summaryrefslogtreecommitdiff
path: root/spec/ruby/core/string/include_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/core/string/include_spec.rb')
-rw-r--r--spec/ruby/core/string/include_spec.rb22
1 files changed, 18 insertions, 4 deletions
diff --git a/spec/ruby/core/string/include_spec.rb b/spec/ruby/core/string/include_spec.rb
index e32eb17c29..d943430335 100644
--- a/spec/ruby/core/string/include_spec.rb
+++ b/spec/ruby/core/string/include_spec.rb
@@ -13,6 +13,20 @@ describe "String#include? with String" do
StringSpecs::MyString.new("hello").include?(StringSpecs::MyString.new("lo")).should == true
end
+ it "returns true if both strings are empty" do
+ "".should.include?("")
+ "".dup.force_encoding("EUC-JP").should.include?("")
+ "".should.include?("".dup.force_encoding("EUC-JP"))
+ "".dup.force_encoding("EUC-JP").should.include?("".dup.force_encoding("EUC-JP"))
+ end
+
+ it "returns true if the RHS is empty" do
+ "a".should.include?("")
+ "a".dup.force_encoding("EUC-JP").should.include?("")
+ "a".should.include?("".dup.force_encoding("EUC-JP"))
+ "a".dup.force_encoding("EUC-JP").should.include?("".dup.force_encoding("EUC-JP"))
+ end
+
it "tries to convert other to string using to_str" do
other = mock('lo')
other.should_receive(:to_str).and_return("lo")
@@ -21,15 +35,15 @@ describe "String#include? with String" do
end
it "raises a TypeError if other can't be converted to string" do
- -> { "hello".include?([]) }.should raise_error(TypeError)
- -> { "hello".include?('h'.ord) }.should raise_error(TypeError)
- -> { "hello".include?(mock('x')) }.should raise_error(TypeError)
+ -> { "hello".include?([]) }.should.raise(TypeError)
+ -> { "hello".include?('h'.ord) }.should.raise(TypeError)
+ -> { "hello".include?(mock('x')) }.should.raise(TypeError)
end
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
pat = "ア".encode Encoding::EUC_JP
-> do
"あれ".include?(pat)
- end.should raise_error(Encoding::CompatibilityError)
+ end.should.raise(Encoding::CompatibilityError)
end
end
/tr> -rw-r--r--.github/workflows/mingw.yml141
-rw-r--r--.github/workflows/mjit.yml93
-rw-r--r--.github/workflows/spec_guards.yml41
-rw-r--r--.github/workflows/ubuntu.yml123
-rw-r--r--.github/workflows/windows.yml75
-rw-r--r--.gitignore7
-rw-r--r--.travis.yml421
-rw-r--r--BSDL6
-rw-r--r--LEGAL688
-rw-r--r--NEWS826
-rw-r--r--NEWS.md820
-rw-r--r--README.ja.md35
-rw-r--r--README.md35
-rw-r--r--aclocal.m447
-rw-r--r--addr2line.c82
-rw-r--r--addr2line.h5
-rw-r--r--appveyor.yml32
-rw-r--r--array.c4277
-rw-r--r--array.rb61
-rw-r--r--ast.c101
-rw-r--r--ast.rb28
-rwxr-xr-xautogen.sh9
-rwxr-xr-xbasictest/test.rb16
-rw-r--r--benchmark/README.md10
-rw-r--r--benchmark/array_max_float.yml30
-rw-r--r--benchmark/array_max_int.yml31
-rw-r--r--benchmark/array_max_str.yml30
-rw-r--r--benchmark/array_min.yml31
-rw-r--r--benchmark/enum_lazy_flat_map.yml16
-rw-r--r--benchmark/enum_lazy_zip.yml22
-rw-r--r--[-rwxr-xr-x]benchmark/fiber_chain.yml0
-rw-r--r--benchmark/fiber_locals.yml8
-rw-r--r--benchmark/hash_defaults.yml6
-rw-r--r--benchmark/kernel_clone.yml6
-rw-r--r--benchmark/kernel_float.yml5
-rw-r--r--benchmark/kernel_tap.yml6
-rw-r--r--benchmark/kernel_then.yml6
-rw-r--r--benchmark/keyword_arguments.yml13
-rw-r--r--benchmark/lib/benchmark_driver/runner/mjit.rb34
-rw-r--r--benchmark/lib/benchmark_driver/runner/mjit_exec.rb6
-rw-r--r--benchmark/mjit_exec_jt2jt.yml4
-rw-r--r--benchmark/mjit_exec_vm2jt.yml4
-rw-r--r--benchmark/mjit_exec_vm2vm.yml4
-rw-r--r--benchmark/mjit_exivar.yml18
-rw-r--r--benchmark/mjit_integer.yml30
-rw-r--r--benchmark/mjit_kernel.yml20
-rw-r--r--benchmark/mjit_leave.yml8
-rw-r--r--benchmark/mjit_opt_cc_insns.yml27
-rw-r--r--benchmark/mjit_struct_aref.yml10
-rw-r--r--benchmark/num_zero_p.yml8
-rw-r--r--benchmark/object_allocate.yml21
-rw-r--r--benchmark/objspace_dump_all.yml13
-rw-r--r--benchmark/pm_array.yml19
-rw-r--r--benchmark/string_casecmp.yml26
-rw-r--r--benchmark/string_casecmp_p.yml26
-rw-r--r--benchmark/string_downcase.yml8
-rw-r--r--benchmark/string_slice.yml11
-rw-r--r--benchmark/string_split.yml25
-rw-r--r--benchmark/string_swapcase.yml8
-rw-r--r--benchmark/string_upcase.yml8
-rw-r--r--benchmark/vm1_attr_ivar.yml14
-rw-r--r--benchmark/vm1_attr_ivar_set.yml14
-rw-r--r--benchmark/vm1_block.yml9
-rw-r--r--benchmark/vm1_blockparam.yml7
-rw-r--r--benchmark/vm1_blockparam_call.yml8
-rw-r--r--benchmark/vm1_blockparam_pass.yml12
-rw-r--r--benchmark/vm1_blockparam_yield.yml8
-rw-r--r--benchmark/vm1_const.yml7
-rw-r--r--benchmark/vm1_ensure.yml14
-rw-r--r--benchmark/vm1_float_simple.yml8
-rw-r--r--benchmark/vm1_gc_short_lived.yml9
-rw-r--r--benchmark/vm1_gc_short_with_complex_long.yml25
-rw-r--r--benchmark/vm1_gc_short_with_long.yml13
-rw-r--r--benchmark/vm1_gc_short_with_symbol.yml13
-rw-r--r--benchmark/vm1_gc_wb_ary.yml12
-rw-r--r--benchmark/vm1_gc_wb_ary_promoted.yml15
-rw-r--r--benchmark/vm1_gc_wb_obj.yml15
-rw-r--r--benchmark/vm1_gc_wb_obj_promoted.yml17
-rw-r--r--benchmark/vm1_ivar.yml6
-rw-r--r--benchmark/vm1_ivar_set.yml5
-rw-r--r--benchmark/vm1_length.yml8
-rw-r--r--benchmark/vm1_lvar_init.yml21
-rw-r--r--benchmark/vm1_lvar_set.yml4
-rw-r--r--benchmark/vm1_neq.yml7
-rw-r--r--benchmark/vm1_not.yml6
-rw-r--r--benchmark/vm1_rescue.yml6
-rw-r--r--benchmark/vm1_simplereturn.yml7
-rw-r--r--benchmark/vm1_swap.yml7
-rw-r--r--benchmark/vm1_yield.yml13
-rw-r--r--benchmark/vm2_array.yml4
-rw-r--r--benchmark/vm2_bigarray.yml105
-rw-r--r--benchmark/vm2_bighash.yml4
-rw-r--r--benchmark/vm2_case.yml13
-rw-r--r--benchmark/vm2_case_lit.yml23
-rw-r--r--benchmark/vm2_defined_method.yml8
-rw-r--r--benchmark/vm2_dstr.yml6
-rw-r--r--benchmark/vm2_eval.yml4
-rw-r--r--benchmark/vm2_fiber_allocate.yml8
-rw-r--r--benchmark/vm2_fiber_count.yml10
-rw-r--r--benchmark/vm2_fiber_reuse.yml14
-rw-r--r--benchmark/vm2_fiber_reuse_gc.yml12
-rw-r--r--benchmark/vm2_fiber_switch.yml9
-rw-r--r--benchmark/vm2_freezestring.yml10
-rw-r--r--benchmark/vm2_method.yml8
-rw-r--r--benchmark/vm2_method_missing.yml11
-rw-r--r--benchmark/vm2_method_with_block.yml8
-rw-r--r--benchmark/vm2_module_ann_const_set.yml4
-rw-r--r--benchmark/vm2_module_const_set.yml8
-rw-r--r--benchmark/vm2_mutex.yml8
-rw-r--r--benchmark/vm2_newlambda.yml4
-rw-r--r--benchmark/vm2_poly_method.yml24
-rw-r--r--benchmark/vm2_poly_method_ov.yml24
-rw-r--r--benchmark/vm2_poly_same_method.yml25
-rw-r--r--benchmark/vm2_poly_singleton.yml18
-rw-r--r--benchmark/vm2_proc.yml12
-rw-r--r--benchmark/vm2_raise1.yml16
-rw-r--r--benchmark/vm2_raise2.yml16
-rw-r--r--benchmark/vm2_regexp.yml8
-rw-r--r--benchmark/vm2_send.yml11
-rw-r--r--benchmark/vm2_string_literal.yml4
-rw-r--r--benchmark/vm2_struct_big_aref_hi.yml7
-rw-r--r--benchmark/vm2_struct_big_aref_lo.yml7
-rw-r--r--benchmark/vm2_struct_big_aset.yml11
-rw-r--r--benchmark/vm2_struct_big_href_hi.yml7
-rw-r--r--benchmark/vm2_struct_big_href_lo.yml7
-rw-r--r--benchmark/vm2_struct_big_hset.yml11
-rw-r--r--benchmark/vm2_struct_small_aref.yml7
-rw-r--r--benchmark/vm2_struct_small_aset.yml11
-rw-r--r--benchmark/vm2_struct_small_href.yml7
-rw-r--r--benchmark/vm2_struct_small_hset.yml7
-rw-r--r--benchmark/vm2_super.yml17
-rw-r--r--benchmark/vm2_unif1.yml7
-rw-r--r--benchmark/vm2_zsuper.yml18
-rw-r--r--benchmark/vm_array.yml4
-rw-r--r--benchmark/vm_attr_ivar.yml14
-rw-r--r--benchmark/vm_attr_ivar_set.yml14
-rw-r--r--benchmark/vm_backtrace.rb (renamed from benchmark/vm3_backtrace.rb)0
-rw-r--r--benchmark/vm_bigarray.yml105
-rw-r--r--benchmark/vm_bighash.yml4
-rw-r--r--benchmark/vm_block.yml9
-rw-r--r--benchmark/vm_block_handler.yml27
-rw-r--r--benchmark/vm_blockparam.yml7
-rw-r--r--benchmark/vm_blockparam_call.yml8
-rw-r--r--benchmark/vm_blockparam_pass.yml12
-rw-r--r--benchmark/vm_blockparam_yield.yml8
-rw-r--r--benchmark/vm_case.yml13
-rw-r--r--benchmark/vm_case_lit.yml23
-rw-r--r--benchmark/vm_clearmethodcache.rb (renamed from benchmark/vm3_clearmethodcache.rb)0
-rw-r--r--benchmark/vm_const.yml7
-rw-r--r--benchmark/vm_defined_method.yml8
-rw-r--r--benchmark/vm_dstr.yml6
-rw-r--r--benchmark/vm_ensure.yml14
-rw-r--r--benchmark/vm_eval.yml4
-rw-r--r--benchmark/vm_fiber_allocate.yml8
-rw-r--r--benchmark/vm_fiber_count.yml10
-rw-r--r--benchmark/vm_fiber_reuse.yml14
-rw-r--r--benchmark/vm_fiber_reuse_gc.yml12
-rw-r--r--benchmark/vm_fiber_switch.yml9
-rw-r--r--benchmark/vm_float_simple.yml8
-rw-r--r--benchmark/vm_freezestring.yml10
-rw-r--r--benchmark/vm_gc.rb (renamed from benchmark/vm3_gc.rb)0
-rw-r--r--benchmark/vm_gc_old_full.rb (renamed from benchmark/vm3_gc_old_full.rb)0
-rw-r--r--benchmark/vm_gc_old_immediate.rb (renamed from benchmark/vm3_gc_old_immediate.rb)0
-rw-r--r--benchmark/vm_gc_old_lazy.rb (renamed from benchmark/vm3_gc_old_lazy.rb)0
-rw-r--r--benchmark/vm_gc_short_lived.yml9
-rw-r--r--benchmark/vm_gc_short_with_complex_long.yml25
-rw-r--r--benchmark/vm_gc_short_with_long.yml13
-rw-r--r--benchmark/vm_gc_short_with_symbol.yml13
-rw-r--r--benchmark/vm_gc_wb_ary.yml12
-rw-r--r--benchmark/vm_gc_wb_ary_promoted.yml15
-rw-r--r--benchmark/vm_gc_wb_obj.yml15
-rw-r--r--benchmark/vm_gc_wb_obj_promoted.yml17
-rw-r--r--benchmark/vm_iclass_super.yml20
-rw-r--r--benchmark/vm_ivar.yml6
-rw-r--r--benchmark/vm_ivar_init.yml14
-rw-r--r--benchmark/vm_ivar_set.yml5
-rw-r--r--benchmark/vm_ivar_set_subclass.yml17
-rw-r--r--benchmark/vm_length.yml8
-rw-r--r--benchmark/vm_lvar_init.yml21
-rw-r--r--benchmark/vm_lvar_set.yml4
-rw-r--r--benchmark/vm_method.yml8
-rw-r--r--benchmark/vm_method_missing.yml11
-rw-r--r--benchmark/vm_method_with_block.yml8
-rw-r--r--benchmark/vm_module_ann_const_set.yml4
-rw-r--r--benchmark/vm_module_const_set.yml8
-rw-r--r--benchmark/vm_mutex.yml8
-rw-r--r--benchmark/vm_neq.yml7
-rw-r--r--benchmark/vm_newlambda.yml4
-rw-r--r--benchmark/vm_not.yml6
-rw-r--r--benchmark/vm_poly_method.yml24
-rw-r--r--benchmark/vm_poly_method_ov.yml24
-rw-r--r--benchmark/vm_poly_same_method.yml25
-rw-r--r--benchmark/vm_poly_singleton.yml18
-rw-r--r--benchmark/vm_proc.yml12
-rw-r--r--benchmark/vm_raise1.yml16
-rw-r--r--benchmark/vm_raise2.yml16
-rw-r--r--benchmark/vm_regexp.yml8
-rw-r--r--benchmark/vm_rescue.yml6
-rw-r--r--benchmark/vm_send.yml14
-rw-r--r--benchmark/vm_send_cfunc.yml3
-rw-r--r--benchmark/vm_simplereturn.yml7
-rw-r--r--benchmark/vm_string_literal.yml4
-rw-r--r--benchmark/vm_struct_big_aref_hi.yml7
-rw-r--r--benchmark/vm_struct_big_aref_lo.yml7
-rw-r--r--benchmark/vm_struct_big_aset.yml11
-rw-r--r--benchmark/vm_struct_big_href_hi.yml7
-rw-r--r--benchmark/vm_struct_big_href_lo.yml7
-rw-r--r--benchmark/vm_struct_big_hset.yml11
-rw-r--r--benchmark/vm_struct_small_aref.yml7
-rw-r--r--benchmark/vm_struct_small_aset.yml11
-rw-r--r--benchmark/vm_struct_small_href.yml7
-rw-r--r--benchmark/vm_struct_small_hset.yml7
-rw-r--r--benchmark/vm_super.yml17
-rw-r--r--benchmark/vm_swap.yml7
-rw-r--r--benchmark/vm_unif1.yml7
-rw-r--r--benchmark/vm_yield.yml13
-rw-r--r--benchmark/vm_zsuper.yml18
-rw-r--r--bignum.c207
-rwxr-xr-xbin/erb193
-rwxr-xr-xbin/racc2y27
-rwxr-xr-xbin/y2racc27
-rw-r--r--bootstraptest/pending.rb23
-rwxr-xr-xbootstraptest/runner.rb30
-rw-r--r--bootstraptest/test_eval.rb8
-rw-r--r--bootstraptest/test_flow.rb8
-rw-r--r--bootstraptest/test_insns.rb15
-rw-r--r--bootstraptest/test_jump.rb23
-rw-r--r--bootstraptest/test_proc.rb17
-rw-r--r--bootstraptest/test_ractor.rb1444
-rw-r--r--bootstraptest/test_syntax.rb6
-rw-r--r--bootstraptest/test_thread.rb14
-rw-r--r--builtin.c28
-rw-r--r--builtin.h11
-rw-r--r--class.c624
-rw-r--r--common.mk13412
-rw-r--r--compar.c12
-rw-r--r--compile.c2116
-rw-r--r--complex.c108
-rw-r--r--configure.ac642
-rw-r--r--constant.h15
-rw-r--r--cont.c843
-rw-r--r--coroutine/Stack.h16
-rw-r--r--coroutine/amd64/Context.h2
-rw-r--r--coroutine/arm32/Context.S4
-rw-r--r--coroutine/arm32/Context.h2
-rw-r--r--coroutine/arm64/Context.h2
-rw-r--r--coroutine/copy/Context.c6
-rw-r--r--coroutine/copy/Context.h4
-rw-r--r--coroutine/ppc64le/Context.h2
-rw-r--r--coroutine/ucontext/Context.c2
-rw-r--r--coroutine/ucontext/Context.h2
-rw-r--r--coroutine/win32/Context.h4
-rw-r--r--coroutine/win64/Context.h4
-rw-r--r--coroutine/x86/Context.h4
-rw-r--r--cygwin/GNUmakefile.in15
-rw-r--r--debug.c292
-rw-r--r--debug_counter.c29
-rw-r--r--debug_counter.h153
-rw-r--r--defs/gmake.mk78
-rw-r--r--dir.c564
-rw-r--r--dir.rb136
-rw-r--r--dln.c5
-rw-r--r--dln.h21
-rw-r--r--dln_find.c34
-rw-r--r--doc/.document1
-rw-r--r--doc/ChangeLog-1.9.32
-rw-r--r--doc/ChangeLog-2.0.06
-rw-r--r--doc/ChangeLog-2.1.04
-rw-r--r--doc/NEWS-2.0.03
-rw-r--r--doc/NEWS-2.2.08
-rw-r--r--doc/NEWS-2.3.070
-rw-r--r--doc/NEWS-2.4.052
-rw-r--r--doc/NEWS-2.6.0218
-rw-r--r--doc/NEWS-2.7.0826
-rw-r--r--doc/contributing.rdoc33
-rw-r--r--doc/contributors.rdoc793
-rw-r--r--doc/csv/arguments/io.rdoc5
-rw-r--r--doc/csv/options/common/col_sep.rdoc63
-rw-r--r--doc/csv/options/common/quote_char.rdoc42
-rw-r--r--doc/csv/options/common/row_sep.rdoc100
-rw-r--r--doc/csv/options/generating/force_quotes.rdoc17
-rw-r--r--doc/csv/options/generating/quote_empty.rdoc12
-rw-r--r--doc/csv/options/generating/write_converters.rdoc33
-rw-r--r--doc/csv/options/generating/write_empty_value.rdoc15
-rw-r--r--doc/csv/options/generating/write_headers.rdoc29
-rw-r--r--doc/csv/options/generating/write_nil_value.rdoc14
-rw-r--r--doc/csv/options/parsing/converters.rdoc46
-rw-r--r--doc/csv/options/parsing/empty_value.rdoc13
-rw-r--r--doc/csv/options/parsing/field_size_limit.rdoc39
-rw-r--r--doc/csv/options/parsing/header_converters.rdoc43
-rw-r--r--doc/csv/options/parsing/headers.rdoc63
-rw-r--r--doc/csv/options/parsing/liberal_parsing.rdoc19
-rw-r--r--doc/csv/options/parsing/nil_value.rdoc12
-rw-r--r--doc/csv/options/parsing/return_headers.rdoc22
-rw-r--r--doc/csv/options/parsing/skip_blanks.rdoc31
-rw-r--r--doc/csv/options/parsing/skip_lines.rdoc37
-rw-r--r--doc/csv/options/parsing/strip.rdoc15
-rw-r--r--doc/csv/options/parsing/unconverted_fields.rdoc27
-rw-r--r--doc/csv/recipes/filtering.rdoc156
-rw-r--r--doc/csv/recipes/generating.rdoc244
-rw-r--r--doc/csv/recipes/parsing.rdoc543
-rw-r--r--doc/csv/recipes/recipes.rdoc6
-rw-r--r--doc/dig_methods.rdoc82
-rw-r--r--doc/dtrace_probes.rdoc78
-rw-r--r--doc/extension.ja.rdoc11
-rw-r--r--doc/extension.rdoc133
-rw-r--r--doc/fiber.md191
-rw-r--r--doc/globals.rdoc3
-rw-r--r--doc/implicit_conversion.rdoc198
-rw-r--r--doc/keywords.rdoc2
-rw-r--r--doc/maintainers.rdoc266
-rw-r--r--doc/make_cheatsheet.md124
-rw-r--r--doc/marshal.rdoc2
-rw-r--r--doc/memory_view.md167
-rw-r--r--doc/method_documentation.rdoc183
-rw-r--r--doc/ractor.md931
-rw-r--r--doc/standard_library.rdoc79
-rw-r--r--doc/syntax.rdoc5
-rw-r--r--doc/syntax/calling_methods.rdoc36
-rw-r--r--doc/syntax/comments.rdoc216
-rw-r--r--doc/syntax/control_expressions.rdoc16
-rw-r--r--doc/syntax/literals.rdoc9
-rw-r--r--doc/syntax/miscellaneous.rdoc30
-rw-r--r--doc/syntax/pattern_matching.rdoc503
-rw-r--r--doc/syntax/refinements.rdoc5
-rw-r--r--enc/Makefile.in3
-rw-r--r--enc/ascii.c2
-rw-r--r--enc/cp949.c2
-rw-r--r--enc/depend5998
-rw-r--r--enc/encdb.c2
-rw-r--r--enc/euc_jp.c4
-rw-r--r--enc/iso_8859_11.c2
-rw-r--r--enc/iso_8859_6.c2
-rw-r--r--enc/iso_8859_8.c2
-rw-r--r--enc/shift_jis.c4
-rw-r--r--enc/trans/escape.trans3
-rw-r--r--enc/trans/ibm720-tbl.rb122
-rw-r--r--enc/trans/newline.trans10
-rw-r--r--enc/trans/single_byte.trans3
-rw-r--r--enc/unicode.c4
-rw-r--r--[-rwxr-xr-x]enc/unicode/case-folding.rb2
-rw-r--r--enc/windows_1250.c2
-rw-r--r--enc/windows_1251.c2
-rw-r--r--enc/windows_1252.c2
-rw-r--r--enc/windows_1253.c2
-rw-r--r--enc/windows_1254.c2
-rw-r--r--enc/windows_1257.c2
-rw-r--r--enc/windows_31j.c2
-rw-r--r--encindex.h5
-rw-r--r--encoding.c658
-rw-r--r--enum.c315
-rw-r--r--enumerator.c517
-rw-r--r--error.c428
-rw-r--r--eval.c147
-rw-r--r--eval_error.c42
-rw-r--r--eval_intern.h21
-rw-r--r--ext/-test-/RUBY_ALIGNOF/c.c15
-rw-r--r--ext/-test-/RUBY_ALIGNOF/cpp.cpp9
-rw-r--r--ext/-test-/RUBY_ALIGNOF/depend163
-rw-r--r--ext/-test-/RUBY_ALIGNOF/extconf.rb6
-rw-r--r--ext/-test-/arith_seq/extract/depend149
-rw-r--r--ext/-test-/array/concat/depend322
-rw-r--r--ext/-test-/array/concat/extconf.rb2
-rw-r--r--ext/-test-/array/concat/to_ary_conact.c34
-rw-r--r--ext/-test-/array/resize/depend149
-rw-r--r--ext/-test-/bignum/big2str.c2
-rw-r--r--ext/-test-/bignum/bigzero.c2
-rw-r--r--ext/-test-/bignum/depend1049
-rw-r--r--ext/-test-/bignum/div.c2
-rw-r--r--ext/-test-/bignum/intpack.c2
-rw-r--r--ext/-test-/bignum/mul.c2
-rw-r--r--ext/-test-/bignum/str2big.c2
-rw-r--r--ext/-test-/bug-14834/depend149
-rw-r--r--ext/-test-/bug-3571/depend149
-rw-r--r--ext/-test-/bug-5832/depend149
-rw-r--r--ext/-test-/bug_reporter/depend149
-rw-r--r--ext/-test-/class/depend298
-rw-r--r--ext/-test-/cxxanyargs/cxxanyargs.cpp346
-rw-r--r--ext/-test-/cxxanyargs/depend2
-rw-r--r--ext/-test-/cxxanyargs/extconf.rb15
-rw-r--r--ext/-test-/debug/depend447
-rw-r--r--ext/-test-/enumerator_kw/depend149
-rw-r--r--ext/-test-/exception/depend596
-rw-r--r--ext/-test-/fatal/depend149
-rw-r--r--ext/-test-/file/depend447
-rw-r--r--ext/-test-/float/depend298
-rw-r--r--ext/-test-/funcall/depend149
-rw-r--r--ext/-test-/gvl/call_without_gvl/depend149
-rw-r--r--ext/-test-/hash/depend298
-rw-r--r--ext/-test-/integer/core_ext.c2
-rw-r--r--ext/-test-/integer/depend455
-rw-r--r--ext/-test-/iseq_load/depend149
-rw-r--r--ext/-test-/iter/depend447
-rw-r--r--ext/-test-/load/protect/depend149
-rw-r--r--ext/-test-/marshal/compat/depend149
-rw-r--r--ext/-test-/marshal/internal_ivar/depend149
-rw-r--r--ext/-test-/marshal/usr/depend149
-rw-r--r--ext/-test-/memory_status/depend149
-rw-r--r--ext/-test-/memory_view/depend164
-rw-r--r--ext/-test-/memory_view/extconf.rb3
-rw-r--r--ext/-test-/memory_view/memory_view.c446
-rw-r--r--ext/-test-/method/depend298
-rw-r--r--ext/-test-/notimplement/depend149
-rw-r--r--ext/-test-/num2int/depend149
-rw-r--r--ext/-test-/path_to_class/depend149
-rw-r--r--ext/-test-/popen_deadlock/depend149
-rw-r--r--ext/-test-/popen_deadlock/extconf.rb1
-rw-r--r--ext/-test-/postponed_job/depend149
-rw-r--r--ext/-test-/postponed_job/postponed_job.c31
-rw-r--r--ext/-test-/printf/depend149
-rw-r--r--ext/-test-/proc/depend447
-rw-r--r--ext/-test-/random/depend328
-rw-r--r--ext/-test-/random/extconf.rb3
-rw-r--r--ext/-test-/random/init.c11
-rw-r--r--ext/-test-/random/loop.c110
-rw-r--r--ext/-test-/rational/depend161
-rw-r--r--ext/-test-/rational/rat.c10
-rw-r--r--ext/-test-/rb_call_super_kw/depend149
-rw-r--r--ext/-test-/recursion/depend149
-rw-r--r--ext/-test-/regexp/depend298
-rw-r--r--ext/-test-/scan_args/depend149
-rw-r--r--ext/-test-/scan_args/scan_args.c10
-rw-r--r--ext/-test-/st/foreach/depend149
-rw-r--r--ext/-test-/st/numhash/depend149
-rw-r--r--ext/-test-/st/numhash/numhash.c2
-rw-r--r--ext/-test-/st/update/depend149
-rw-r--r--ext/-test-/string/capacity.c2
-rw-r--r--ext/-test-/string/coderange.c8
-rw-r--r--ext/-test-/string/cstr.c3
-rw-r--r--ext/-test-/string/depend2411
-rw-r--r--ext/-test-/string/enc_str_buf_cat.c14
-rw-r--r--ext/-test-/string/fstring.c15
-rw-r--r--ext/-test-/string/normalize.c2
-rw-r--r--ext/-test-/string/rb_interned_str.c14
-rw-r--r--ext/-test-/struct/depend596
-rw-r--r--ext/-test-/symbol/depend298
-rw-r--r--ext/-test-/thread_fd_close/depend149
-rw-r--r--ext/-test-/time/depend451
-rw-r--r--ext/-test-/time/leap_second.c3
-rw-r--r--ext/-test-/tracepoint/depend298
-rw-r--r--ext/-test-/tracepoint/gc_hook.c3
-rw-r--r--ext/-test-/typeddata/depend149
-rw-r--r--ext/-test-/typeddata/typeddata.c4
-rw-r--r--ext/-test-/vm/depend149
-rw-r--r--ext/-test-/wait_for_single_fd/depend149
-rw-r--r--ext/-test-/wait_for_single_fd/extconf.rb8
-rw-r--r--ext/.document15
-rw-r--r--ext/Setup1
-rw-r--r--ext/Setup.atheos1
-rw-r--r--ext/Setup.nt1
-rw-r--r--ext/bigdecimal/bigdecimal.c229
-rw-r--r--ext/bigdecimal/bigdecimal.gemspec8
-rw-r--r--ext/bigdecimal/bigdecimal.h4
-rw-r--r--ext/bigdecimal/depend149
-rw-r--r--ext/bigdecimal/extconf.rb5
-rw-r--r--ext/bigdecimal/lib/bigdecimal/util.rb35
-rw-r--r--ext/bigdecimal/util/depend14
-rw-r--r--ext/cgi/escape/depend149
-rw-r--r--ext/cgi/escape/escape.c4
-rw-r--r--ext/continuation/depend149
-rw-r--r--ext/coverage/coverage.c205
-rw-r--r--ext/coverage/depend161
-rw-r--r--ext/date/date.gemspec2
-rw-r--r--ext/date/date_core.c110
-rw-r--r--ext/date/date_parse.c1
-rw-r--r--ext/date/date_strptime.c1
-rw-r--r--ext/date/depend598
-rw-r--r--ext/date/lib/date.rb4
-rw-r--r--ext/date/prereq.mk2
-rw-r--r--ext/date/update-abbr25
-rw-r--r--ext/date/zonetab.list14
-rw-r--r--ext/dbm/dbm.c4
-rw-r--r--ext/dbm/dbm.gemspec3
-rw-r--r--ext/dbm/depend149
-rw-r--r--ext/digest/bubblebabble/depend149
-rw-r--r--ext/digest/depend149
-rw-r--r--ext/digest/digest.c10
-rw-r--r--ext/digest/digest.gemspec47
-rw-r--r--ext/digest/digest.h8
-rw-r--r--ext/digest/digest_conf.rb69
-rw-r--r--ext/digest/md5/depend315
-rw-r--r--ext/digest/md5/md5init.c9
-rw-r--r--ext/digest/md5/md5ossl.h15
-rw-r--r--ext/digest/rmd160/depend315
-rw-r--r--ext/digest/rmd160/extconf.rb2
-rw-r--r--ext/digest/rmd160/rmd160init.c9
-rw-r--r--ext/digest/rmd160/rmd160ossl.h20
-rw-r--r--ext/digest/sha1/depend315
-rw-r--r--ext/digest/sha1/extconf.rb2
-rw-r--r--ext/digest/sha1/sha1init.c9
-rw-r--r--ext/digest/sha1/sha1ossl.h22
-rw-r--r--ext/digest/sha2/depend314
-rw-r--r--ext/digest/sha2/extconf.rb2
-rw-r--r--ext/digest/sha2/sha2init.c8
-rw-r--r--ext/digest/sha2/sha2ossl.h27
-rw-r--r--ext/etc/depend150
-rw-r--r--ext/etc/etc.c72
-rw-r--r--ext/etc/etc.gemspec3
-rw-r--r--ext/etc/extconf.rb2
-rwxr-xr-xext/extmk.rb5
-rw-r--r--ext/fcntl/depend149
-rw-r--r--ext/fcntl/fcntl.c14
-rw-r--r--ext/fcntl/fcntl.gemspec8
-rw-r--r--ext/fiddle/closure.c30
-rw-r--r--ext/fiddle/conversions.c221
-rw-r--r--ext/fiddle/conversions.h17
-rw-r--r--ext/fiddle/depend1226
-rw-r--r--ext/fiddle/extconf.rb126
-rw-r--r--ext/fiddle/extlibs12
-rw-r--r--ext/fiddle/fiddle.c167
-rw-r--r--ext/fiddle/fiddle.gemspec53
-rw-r--r--ext/fiddle/fiddle.h128
-rw-r--r--ext/fiddle/function.c356
-rw-r--r--ext/fiddle/handle.c14
-rw-r--r--ext/fiddle/lib/fiddle.rb16
-rw-r--r--ext/fiddle/lib/fiddle/cparser.rb121
-rw-r--r--ext/fiddle/lib/fiddle/function.rb5
-rw-r--r--ext/fiddle/lib/fiddle/import.rb8
-rw-r--r--ext/fiddle/lib/fiddle/struct.rb310
-rw-r--r--ext/fiddle/lib/fiddle/version.rb3
-rw-r--r--ext/fiddle/memory_view.c254
-rw-r--r--ext/fiddle/pinned.c123
-rw-r--r--ext/fiddle/pointer.c156
-rw-r--r--[-rwxr-xr-x]ext/fiddle/win32/fficonfig.h0
-rwxr-xr-xext/fiddle/win32/libffi-config.rb2
-rw-r--r--[-rwxr-xr-x]ext/fiddle/win32/libffi.mk.tmpl0
-rw-r--r--ext/gdbm/depend149
-rw-r--r--ext/gdbm/gdbm.gemspec2
-rw-r--r--ext/io/console/console.c89
-rw-r--r--ext/io/console/depend149
-rw-r--r--ext/io/console/extconf.rb3
-rw-r--r--ext/io/console/io-console.gemspec6
-rw-r--r--ext/io/nonblock/depend149
-rw-r--r--ext/io/nonblock/io-nonblock.gemspec25
-rw-r--r--ext/io/wait/depend149
-rw-r--r--ext/io/wait/io-wait.gemspec27
-rw-r--r--ext/io/wait/wait.c209
-rw-r--r--ext/json/VERSION1
-rw-r--r--ext/json/extconf.rb1
-rw-r--r--ext/json/generator/depend150
-rw-r--r--ext/json/generator/generator.c143
-rw-r--r--ext/json/generator/generator.h7
-rw-r--r--ext/json/json.gemspec100
-rw-r--r--ext/json/lib/json.rb578
-rw-r--r--ext/json/lib/json/add/complex.rb1
-rw-r--r--ext/json/lib/json/add/rational.rb1
-rw-r--r--ext/json/lib/json/common.rb493
-rw-r--r--ext/json/lib/json/version.rb2
-rw-r--r--ext/json/parser/depend149
-rw-r--r--ext/json/parser/extconf.rb25
-rw-r--r--ext/json/parser/parser.c231
-rw-r--r--ext/json/parser/parser.h1
-rw-r--r--ext/json/parser/parser.rl93
-rw-r--r--ext/json/parser/prereq.mk1
-rw-r--r--ext/monitor/depend149
-rw-r--r--ext/monitor/lib/monitor.rb6
-rw-r--r--ext/monitor/monitor.c14
-rw-r--r--ext/nkf/depend149
-rw-r--r--ext/nkf/nkf.gemspec24
-rw-r--r--ext/objspace/depend478
-rw-r--r--ext/objspace/lib/objspace.rb91
-rw-r--r--ext/objspace/object_tracing.c89
-rw-r--r--ext/objspace/objspace.c277
-rw-r--r--ext/objspace/objspace_dump.c637
-rw-r--r--ext/openssl/History.md90
-rw-r--r--ext/openssl/depend4869
-rw-r--r--ext/openssl/deprecation.rb27
-rw-r--r--ext/openssl/extconf.rb43
-rw-r--r--ext/openssl/lib/openssl.rb34
-rw-r--r--ext/openssl/lib/openssl/bn.rb2
-rw-r--r--ext/openssl/lib/openssl/buffering.rb33
-rw-r--r--ext/openssl/lib/openssl/cipher.rb2
-rw-r--r--ext/openssl/lib/openssl/config.rb25
-rw-r--r--ext/openssl/lib/openssl/digest.rb22
-rw-r--r--ext/openssl/lib/openssl/hmac.rb13
-rw-r--r--ext/openssl/lib/openssl/marshal.rb30
-rw-r--r--ext/openssl/lib/openssl/pkcs5.rb2
-rw-r--r--ext/openssl/lib/openssl/pkey.rb19
-rw-r--r--ext/openssl/lib/openssl/ssl.rb42
-rw-r--r--ext/openssl/lib/openssl/version.rb5
-rw-r--r--ext/openssl/lib/openssl/x509.rb156
-rw-r--r--ext/openssl/openssl.gemspec4
-rw-r--r--ext/openssl/openssl_missing.h37
-rw-r--r--ext/openssl/ossl.c83
-rw-r--r--ext/openssl/ossl.h11
-rw-r--r--ext/openssl/ossl_asn1.c25
-rw-r--r--ext/openssl/ossl_bn.c75
-rw-r--r--ext/openssl/ossl_bn.h3
-rw-r--r--ext/openssl/ossl_cipher.c57
-rw-r--r--ext/openssl/ossl_digest.c67
-rw-r--r--ext/openssl/ossl_engine.c14
-rw-r--r--ext/openssl/ossl_hmac.c16
-rw-r--r--ext/openssl/ossl_kdf.c22
-rw-r--r--ext/openssl/ossl_ns_spki.c2
-rw-r--r--ext/openssl/ossl_ocsp.c17
-rw-r--r--ext/openssl/ossl_ocsp.h6
-rw-r--r--ext/openssl/ossl_pkcs7.c22
-rw-r--r--ext/openssl/ossl_pkcs7.h16
-rw-r--r--ext/openssl/ossl_pkey.c194
-rw-r--r--ext/openssl/ossl_pkey_dsa.c4
-rw-r--r--ext/openssl/ossl_pkey_ec.c29
-rw-r--r--ext/openssl/ossl_pkey_rsa.c26
-rw-r--r--ext/openssl/ossl_rand.c34
-rw-r--r--ext/openssl/ossl_ssl.c136
-rw-r--r--ext/openssl/ossl_ts.c1524
-rw-r--r--ext/openssl/ossl_ts.h16
-rw-r--r--ext/openssl/ossl_version.h15
-rw-r--r--ext/openssl/ossl_x509cert.c4
-rw-r--r--ext/openssl/ossl_x509ext.c14
-rw-r--r--ext/openssl/ossl_x509name.c10
-rw-r--r--ext/pathname/depend149
-rw-r--r--ext/pathname/lib/pathname.rb18
-rw-r--r--ext/pathname/pathname.c29
-rw-r--r--ext/pathname/pathname.gemspec25
-rw-r--r--ext/psych/depend745
-rw-r--r--ext/psych/lib/psych.rb110
-rw-r--r--ext/psych/lib/psych/class_loader.rb10
-rw-r--r--ext/psych/lib/psych/handler.rb2
-rw-r--r--ext/psych/lib/psych/nodes/node.rb4
-rw-r--r--ext/psych/lib/psych/nodes/scalar.rb2
-rw-r--r--ext/psych/lib/psych/scalar_scanner.rb2
-rw-r--r--ext/psych/lib/psych/versions.rb6
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb49
-rw-r--r--ext/psych/lib/psych/visitors/visitor.rb20
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb8
-rw-r--r--ext/psych/psych.c9
-rw-r--r--ext/psych/psych.gemspec15
-rw-r--r--ext/psych/psych_parser.c34
-rw-r--r--ext/psych/psych_yaml_tree.c12
-rw-r--r--ext/psych/yaml/api.c36
-rw-r--r--ext/psych/yaml/config.h82
-rw-r--r--ext/psych/yaml/dumper.c2
-rw-r--r--ext/psych/yaml/emitter.c54
-rw-r--r--ext/psych/yaml/loader.c306
-rw-r--r--ext/psych/yaml/parser.c7
-rw-r--r--ext/psych/yaml/scanner.c68
-rw-r--r--ext/psych/yaml/yaml.h72
-rw-r--r--ext/psych/yaml/yaml_private.h8
-rw-r--r--ext/pty/depend157
-rw-r--r--ext/pty/extconf.rb4
-rw-r--r--ext/pty/pty.c64
-rw-r--r--ext/racc/cparse/cparse.c36
-rw-r--r--ext/racc/cparse/depend149
-rw-r--r--ext/racc/cparse/extconf.rb2
-rw-r--r--ext/rbconfig/sizeof/depend298
-rw-r--r--ext/readline/depend149
-rw-r--r--ext/readline/depend-gem4
-rw-r--r--ext/readline/readline-ext.gemspec2
-rw-r--r--ext/readline/readline.c14
-rw-r--r--ext/ripper/depend180
-rw-r--r--ext/ripper/eventids2.c10
-rw-r--r--ext/ripper/lib/ripper/lexer.rb57
-rw-r--r--ext/ripper/lib/ripper/sexp.rb37
-rw-r--r--ext/ripper/tools/dsl.rb3
-rw-r--r--ext/ripper/tools/preproc.rb12
-rw-r--r--ext/sdbm/_sdbm.c952
-rw-r--r--ext/sdbm/depend27
-rw-r--r--ext/sdbm/extconf.rb5
-rw-r--r--ext/sdbm/init.c1067
-rw-r--r--ext/sdbm/sdbm.gemspec21
-rw-r--r--ext/sdbm/sdbm.h86
-rw-r--r--ext/socket/ancdata.c10
-rw-r--r--ext/socket/depend2400
-rw-r--r--ext/socket/extconf.rb2
-rw-r--r--ext/socket/ifaddr.c3
-rw-r--r--ext/socket/init.c162
-rw-r--r--ext/socket/ipsocket.c19
-rw-r--r--ext/socket/option.c4
-rw-r--r--ext/socket/raddrinfo.c126
-rw-r--r--ext/socket/rubysocket.h71
-rw-r--r--ext/socket/socket.c106
-rw-r--r--ext/socket/sockssocket.c2
-rw-r--r--ext/socket/tcpserver.c2
-rw-r--r--ext/socket/tcpsocket.c28
-rw-r--r--ext/socket/udpsocket.c2
-rw-r--r--ext/socket/unixsocket.c8
-rw-r--r--ext/stringio/depend149
-rw-r--r--ext/stringio/stringio.c99
-rw-r--r--ext/stringio/stringio.gemspec5
-rw-r--r--ext/strscan/depend150
-rw-r--r--ext/strscan/strscan.c52
-rw-r--r--ext/strscan/strscan.gemspec18
-rw-r--r--ext/syslog/depend149
-rw-r--r--ext/syslog/syslog.gemspec23
-rw-r--r--ext/win32/lib/Win32API.rb47
-rw-r--r--ext/win32/lib/win32/importer.rb9
-rw-r--r--ext/win32/lib/win32/registry.rb6
-rw-r--r--ext/win32/lib/win32/resolv.rb13
-rw-r--r--ext/win32/lib/win32/resolv9x.rb253
-rw-r--r--ext/win32/lib/win32/sspi.rb627
-rw-r--r--ext/win32ole/win32ole.c1
-rw-r--r--ext/win32ole/win32ole.gemspec21
-rw-r--r--ext/zlib/depend149
-rw-r--r--ext/zlib/extconf.rb6
-rw-r--r--ext/zlib/extlibs7
-rw-r--r--ext/zlib/zlib.c221
-rw-r--r--ext/zlib/zlib.gemspec4
-rw-r--r--file.c261
-rw-r--r--gc.c3663
-rw-r--r--gc.h11
-rw-r--r--gc.rb94
-rw-r--r--gem_prelude.rb13
-rw-r--r--gems/bundled_gems15
-rw-r--r--goruby.c6
-rw-r--r--hash.c2694
-rw-r--r--id_table.c6
-rw-r--r--id_table.h2
-rw-r--r--include/ruby.h31
-rw-r--r--include/ruby/assert.h254
-rw-r--r--include/ruby/atomic.h236
-rw-r--r--include/ruby/backward.h28
-rw-r--r--include/ruby/backward/2/assume.h43
-rw-r--r--include/ruby/backward/2/attributes.h170
-rw-r--r--include/ruby/backward/2/bool.h37
-rw-r--r--include/ruby/backward/2/gcc_version_since.h38
-rw-r--r--include/ruby/backward/2/inttypes.h132
-rw-r--r--include/ruby/backward/2/limits.h100
-rw-r--r--include/ruby/backward/2/long_long.h65
-rw-r--r--include/ruby/backward/2/r_cast.h33
-rw-r--r--include/ruby/backward/2/rmodule.h37
-rw-r--r--include/ruby/backward/2/stdalign.h30
-rw-r--r--include/ruby/backward/2/stdarg.h47
-rw-r--r--include/ruby/backward/classext.h18
-rw-r--r--include/ruby/backward/cxxanyargs.hpp350
-rw-r--r--include/ruby/backward/rubyio.h6
-rw-r--r--include/ruby/backward/rubysig.h47
-rw-r--r--include/ruby/backward/st.h6
-rw-r--r--include/ruby/backward/util.h6
-rw-r--r--include/ruby/debug.h44
-rw-r--r--include/ruby/defines.h524
-rw-r--r--include/ruby/encoding.h50
-rw-r--r--include/ruby/intern.h1268
-rw-r--r--include/ruby/internal/anyargs.h375
-rw-r--r--include/ruby/internal/arithmetic.h38
-rw-r--r--include/ruby/internal/arithmetic/char.h58
-rw-r--r--include/ruby/internal/arithmetic/double.h39
-rw-r--r--include/ruby/internal/arithmetic/fixnum.h44
-rw-r--r--include/ruby/internal/arithmetic/gid_t.h34
-rw-r--r--include/ruby/internal/arithmetic/int.h163
-rw-r--r--include/ruby/internal/arithmetic/intptr_t.h42
-rw-r--r--include/ruby/internal/arithmetic/long.h244
-rw-r--r--include/ruby/internal/arithmetic/long_long.h53
-rw-r--r--include/ruby/internal/arithmetic/mode_t.h34
-rw-r--r--include/ruby/internal/arithmetic/off_t.h49
-rw-r--r--include/ruby/internal/arithmetic/pid_t.h34
-rw-r--r--include/ruby/internal/arithmetic/short.h54
-rw-r--r--include/ruby/internal/arithmetic/size_t.h56
-rw-r--r--include/ruby/internal/arithmetic/st_data_t.h59
-rw-r--r--include/ruby/internal/arithmetic/uid_t.h34
-rw-r--r--include/ruby/internal/assume.h90
-rw-r--r--include/ruby/internal/attr/alloc_size.h32
-rw-r--r--include/ruby/internal/attr/artificial.h46
-rw-r--r--include/ruby/internal/attr/cold.h37
-rw-r--r--include/ruby/internal/attr/const.h46
-rw-r--r--include/ruby/internal/attr/constexpr.h85
-rw-r--r--include/ruby/internal/attr/deprecated.h63
-rw-r--r--include/ruby/internal/attr/diagnose_if.h42
-rw-r--r--include/ruby/internal/attr/enum_extensibility.h32
-rw-r--r--include/ruby/internal/attr/error.h32
-rw-r--r--include/ruby/internal/attr/flag_enum.h33
-rw-r--r--include/ruby/internal/attr/forceinline.h40
-rw-r--r--include/ruby/internal/attr/format.h38
-rw-r--r--include/ruby/internal/attr/maybe_unused.h38
-rw-r--r--include/ruby/internal/attr/noalias.h58
-rw-r--r--include/ruby/internal/attr/nodiscard.h45
-rw-r--r--include/ruby/internal/attr/noexcept.h91
-rw-r--r--include/ruby/internal/attr/noinline.h35
-rw-r--r--include/ruby/internal/attr/nonnull.h32
-rw-r--r--include/ruby/internal/attr/noreturn.h48
-rw-r--r--include/ruby/internal/attr/pure.h43
-rw-r--r--include/ruby/internal/attr/restrict.h45
-rw-r--r--include/ruby/internal/attr/returns_nonnull.h37
-rw-r--r--include/ruby/internal/attr/warning.h32
-rw-r--r--include/ruby/internal/attr/weakref.h32
-rw-r--r--include/ruby/internal/cast.h53
-rw-r--r--include/ruby/internal/compiler_is.h45
-rw-r--r--include/ruby/internal/compiler_is/apple.h41
-rw-r--r--include/ruby/internal/compiler_is/clang.h38
-rw-r--r--include/ruby/internal/compiler_is/gcc.h46
-rw-r--r--include/ruby/internal/compiler_is/intel.h41
-rw-r--r--include/ruby/internal/compiler_is/msvc.h57
-rw-r--r--include/ruby/internal/compiler_is/sunpro.h55
-rw-r--r--include/ruby/internal/compiler_since.h61
-rw-r--r--include/ruby/internal/config.h144
-rw-r--r--include/ruby/internal/constant_p.h37
-rw-r--r--include/ruby/internal/core.h35
-rw-r--r--include/ruby/internal/core/rarray.h270
-rw-r--r--include/ruby/internal/core/rbasic.h85
-rw-r--r--include/ruby/internal/core/rbignum.h51
-rw-r--r--include/ruby/internal/core/rclass.h47
-rw-r--r--include/ruby/internal/core/rdata.h184
-rw-r--r--include/ruby/internal/core/rfile.h36
-rw-r--r--include/ruby/internal/core/rhash.h62
-rw-r--r--include/ruby/internal/core/rmatch.h73
-rw-r--r--include/ruby/internal/core/robject.h96
-rw-r--r--include/ruby/internal/core/rregexp.h84
-rw-r--r--include/ruby/internal/core/rstring.h215
-rw-r--r--include/ruby/internal/core/rstruct.h73
-rw-r--r--include/ruby/internal/core/rtypeddata.h186
-rw-r--r--include/ruby/internal/ctype.h203
-rw-r--r--include/ruby/internal/dllexport.h92
-rw-r--r--include/ruby/internal/dosish.h63
-rw-r--r--include/ruby/internal/error.h84
-rw-r--r--include/ruby/internal/eval.h50
-rw-r--r--include/ruby/internal/event.h75
-rw-r--r--include/ruby/internal/fl_type.h471
-rw-r--r--include/ruby/internal/gc.h57
-rw-r--r--include/ruby/internal/glob.h35
-rw-r--r--include/ruby/internal/globals.h157
-rw-r--r--include/ruby/internal/has/attribute.h164
-rw-r--r--include/ruby/internal/has/builtin.h105
-rw-r--r--include/ruby/internal/has/c_attribute.h38
-rw-r--r--include/ruby/internal/has/cpp_attribute.h87
-rw-r--r--include/ruby/internal/has/declspec_attribute.h48
-rw-r--r--include/ruby/internal/has/extension.h33
-rw-r--r--include/ruby/internal/has/feature.h31
-rw-r--r--include/ruby/internal/has/warning.h31
-rw-r--r--include/ruby/internal/intern/array.h78
-rw-r--r--include/ruby/internal/intern/bignum.h105
-rw-r--r--include/ruby/internal/intern/class.h57
-rw-r--r--include/ruby/internal/intern/compar.h34
-rw-r--r--include/ruby/internal/intern/complex.h60
-rw-r--r--include/ruby/internal/intern/cont.h41
-rw-r--r--include/ruby/internal/intern/dir.h33
-rw-r--r--include/ruby/internal/intern/enum.h33
-rw-r--r--include/ruby/internal/intern/enumerator.h80
-rw-r--r--include/ruby/internal/intern/error.h82
-rw-r--r--include/ruby/internal/intern/eval.h59
-rw-r--r--include/ruby/internal/intern/file.h42
-rw-r--r--include/ruby/internal/intern/gc.h57
-rw-r--r--include/ruby/internal/intern/hash.h59
-rw-r--r--include/ruby/internal/intern/io.h70
-rw-r--r--include/ruby/internal/intern/load.h44
-rw-r--r--include/ruby/internal/intern/marshal.h35
-rw-r--r--include/ruby/internal/intern/numeric.h42
-rw-r--r--include/ruby/internal/intern/object.h90
-rw-r--r--include/ruby/internal/intern/parse.h64
-rw-r--r--include/ruby/internal/intern/proc.h53
-rw-r--r--include/ruby/internal/intern/process.h46
-rw-r--r--include/ruby/internal/intern/random.h45
-rw-r--r--include/ruby/internal/intern/range.h35
-rw-r--r--include/ruby/internal/intern/rational.h46
-rw-r--r--include/ruby/internal/intern/re.h50
-rw-r--r--include/ruby/internal/intern/ruby.h37
-rw-r--r--include/ruby/internal/intern/select.h52
-rw-r--r--include/ruby/internal/intern/select/largesize.h103
-rw-r--r--include/ruby/internal/intern/select/posix.h82
-rw-r--r--include/ruby/internal/intern/select/win32.h124
-rw-r--r--include/ruby/internal/intern/signal.h39
-rw-r--r--include/ruby/internal/intern/sprintf.h43
-rw-r--r--include/ruby/internal/intern/string.h298
-rw-r--r--include/ruby/internal/intern/struct.h47
-rw-r--r--include/ruby/internal/intern/thread.h76
-rw-r--r--include/ruby/internal/intern/time.h51
-rw-r--r--include/ruby/internal/intern/variable.h83
-rw-r--r--include/ruby/internal/intern/vm.h77
-rw-r--r--include/ruby/internal/interpreter.h93
-rw-r--r--include/ruby/internal/iterator.h65
-rw-r--r--include/ruby/internal/memory.h281
-rw-r--r--include/ruby/internal/method.h39
-rw-r--r--include/ruby/internal/module.h39
-rw-r--r--include/ruby/internal/newobj.h73
-rw-r--r--include/ruby/internal/rgengc.h199
-rw-r--r--include/ruby/internal/scan_args.h401
-rw-r--r--include/ruby/internal/special_consts.h204
-rw-r--r--include/ruby/internal/static_assert.h77
-rw-r--r--include/ruby/internal/stdalign.h133
-rw-r--r--include/ruby/internal/stdbool.h51
-rw-r--r--include/ruby/internal/symbol.h114
-rw-r--r--include/ruby/internal/token_paste.h75
-rw-r--r--include/ruby/internal/value.h66
-rw-r--r--include/ruby/internal/value_type.h354
-rw-r--r--include/ruby/internal/variable.h62
-rw-r--r--include/ruby/internal/warning_push.h91
-rw-r--r--include/ruby/internal/xmalloc.h362
-rw-r--r--include/ruby/io.h71
-rw-r--r--include/ruby/memory_view.h165
-rw-r--r--include/ruby/missing.h134
-rw-r--r--include/ruby/ractor.h68
-rw-r--r--include/ruby/random.h92
-rw-r--r--include/ruby/re.h69
-rw-r--r--include/ruby/regex.h22
-rw-r--r--include/ruby/ruby.h2820
-rw-r--r--include/ruby/st.h2
-rw-r--r--include/ruby/subst.h10
-rw-r--r--include/ruby/thread.h43
-rw-r--r--include/ruby/thread_native.h42
-rw-r--r--include/ruby/util.h68
-rw-r--r--include/ruby/version.h56
-rw-r--r--include/ruby/vm.h42
-rw-r--r--include/ruby/win32.h84
-rw-r--r--inits.c37
-rw-r--r--insns.def101
-rw-r--r--integer.rb150
-rw-r--r--internal.h2729
-rw-r--r--internal/array.h119
-rw-r--r--internal/bignum.h246
-rw-r--r--internal/bits.h566
-rw-r--r--internal/class.h174
-rw-r--r--internal/compar.h50
-rw-r--r--internal/compile.h32
-rw-r--r--internal/compilers.h108
-rw-r--r--internal/complex.h30
-rw-r--r--internal/cont.h26
-rw-r--r--internal/dir.h17
-rw-r--r--internal/enc.h20
-rw-r--r--internal/encoding.h31
-rw-r--r--internal/enum.h19
-rw-r--r--internal/enumerator.h22
-rw-r--r--internal/error.h124
-rw-r--r--internal/eval.h33
-rw-r--r--internal/file.h39
-rw-r--r--internal/fixnum.h185
-rw-r--r--internal/gc.h167
-rw-r--r--internal/hash.h241
-rw-r--r--internal/imemo.h244
-rw-r--r--internal/inits.h51
-rw-r--r--internal/io.h35
-rw-r--r--internal/load.h19
-rw-r--r--internal/loadpath.h17
-rw-r--r--internal/math.h24
-rw-r--r--internal/missing.h19
-rw-r--r--internal/numeric.h255
-rw-r--r--internal/object.h83
-rw-r--r--internal/parse.h23
-rw-r--r--internal/proc.h33
-rw-r--r--internal/process.h136
-rw-r--r--internal/random.h17
-rw-r--r--internal/range.h41
-rw-r--r--internal/rational.h72
-rw-r--r--internal/re.h29
-rw-r--r--internal/sanitizers.h191
-rw-r--r--internal/scheduler.h44
-rw-r--r--internal/serial.h24
-rw-r--r--internal/signal.h22
-rw-r--r--internal/static_assert.h17
-rw-r--r--internal/string.h141
-rw-r--r--internal/struct.h154
-rw-r--r--internal/symbol.h41
-rw-r--r--internal/thread.h54
-rw-r--r--internal/time.h35
-rw-r--r--internal/transcode.h21
-rw-r--r--internal/util.h31
-rw-r--r--internal/variable.h84
-rw-r--r--internal/vm.h131
-rw-r--r--internal/warnings.h17
-rw-r--r--io.c961
-rw-r--r--io.rb4
-rw-r--r--iseq.c286
-rw-r--r--iseq.h19
-rw-r--r--kernel.rb174
-rw-r--r--lib/.document5
-rw-r--r--lib/English.gemspec24
-rw-r--r--lib/abbrev.gemspec22
-rw-r--r--lib/base64.gemspec22
-rw-r--r--lib/benchmark/benchmark.gemspec2
-rw-r--r--lib/benchmark/version.rb2
-rw-r--r--lib/bundler.rb89
-rw-r--r--lib/bundler/build_metadata.rb10
-rw-r--r--lib/bundler/bundler.gemspec11
-rw-r--r--lib/bundler/cli.rb155
-rw-r--r--lib/bundler/cli/add.rb2
-rw-r--r--lib/bundler/cli/binstubs.rb8
-rw-r--r--lib/bundler/cli/cache.rb11
-rw-r--r--lib/bundler/cli/check.rb6
-rw-r--r--lib/bundler/cli/clean.rb2
-rw-r--r--lib/bundler/cli/common.rb31
-rw-r--r--lib/bundler/cli/console.rb2
-rw-r--r--lib/bundler/cli/doctor.rb21
-rw-r--r--lib/bundler/cli/exec.rb15
-rw-r--r--lib/bundler/cli/fund.rb36
-rw-r--r--lib/bundler/cli/gem.rb237
-rw-r--r--lib/bundler/cli/info.rb33
-rw-r--r--lib/bundler/cli/init.rb4
-rw-r--r--lib/bundler/cli/inject.rb2
-rw-r--r--lib/bundler/cli/install.rb56
-rw-r--r--lib/bundler/cli/issue.rb9
-rw-r--r--lib/bundler/cli/list.rb30
-rw-r--r--lib/bundler/cli/lock.rb6
-rw-r--r--lib/bundler/cli/open.rb3
-rw-r--r--lib/bundler/cli/outdated.rb170
-rw-r--r--lib/bundler/cli/package.rb48
-rw-r--r--lib/bundler/cli/plugin.rb10
-rw-r--r--lib/bundler/cli/pristine.rb5
-rw-r--r--lib/bundler/cli/remove.rb3
-rw-r--r--lib/bundler/cli/show.rb2
-rw-r--r--lib/bundler/cli/update.rb21
-rw-r--r--lib/bundler/compact_index_client.rb6
-rw-r--r--lib/bundler/compact_index_client/cache.rb20
-rw-r--r--lib/bundler/compact_index_client/gem_parser.rb28
-rw-r--r--lib/bundler/compact_index_client/updater.rb35
-rw-r--r--lib/bundler/current_ruby.rb9
-rw-r--r--lib/bundler/definition.rb556
-rw-r--r--lib/bundler/dep_proxy.rb25
-rw-r--r--lib/bundler/dependency.rb13
-rw-r--r--lib/bundler/digest.rb71
-rw-r--r--lib/bundler/dsl.rb118
-rw-r--r--lib/bundler/endpoint_specification.rb2
-rw-r--r--lib/bundler/env.rb2
-rw-r--r--lib/bundler/environment_preserver.rb31
-rw-r--r--lib/bundler/errors.rb23
-rw-r--r--lib/bundler/feature_flag.rb8
-rw-r--r--lib/bundler/fetcher.rb12
-rw-r--r--lib/bundler/fetcher/base.rb2
-rw-r--r--lib/bundler/fetcher/compact_index.rb4
-rw-r--r--lib/bundler/fetcher/downloader.rb17
-rw-r--r--lib/bundler/fetcher/index.rb8
-rw-r--r--lib/bundler/friendly_errors.rb68
-rw-r--r--lib/bundler/gem_helper.rb84
-rw-r--r--lib/bundler/gem_helpers.rb61
-rw-r--r--lib/bundler/gem_remote_fetcher.rb43
-rw-r--r--lib/bundler/gem_version_promoter.rb8
-rw-r--r--lib/bundler/graph.rb2
-rw-r--r--lib/bundler/index.rb18
-rw-r--r--lib/bundler/injector.rb28
-rw-r--r--lib/bundler/inline.rb5
-rw-r--r--lib/bundler/installer.rb92
-rw-r--r--lib/bundler/installer/gem_installer.rb25
-rw-r--r--lib/bundler/installer/parallel_installer.rb71
-rw-r--r--lib/bundler/installer/standalone.rb40
-rw-r--r--lib/bundler/lazy_specification.rb88
-rw-r--r--lib/bundler/lockfile_generator.rb2
-rw-r--r--lib/bundler/lockfile_parser.rb42
-rw-r--r--lib/bundler/man/.document1
-rw-r--r--lib/bundler/man/bundle-add.166
-rw-r--r--lib/bundler/man/bundle-add.1.ronn (renamed from man/bundle-add.ronn)0
-rw-r--r--lib/bundler/man/bundle-binstubs.142
-rw-r--r--lib/bundler/man/bundle-binstubs.1.ronn41
-rw-r--r--lib/bundler/man/bundle-cache.155
-rw-r--r--lib/bundler/man/bundle-cache.1.ronn (renamed from man/bundle-cache.ronn)0
-rw-r--r--lib/bundler/man/bundle-check.131
-rw-r--r--lib/bundler/man/bundle-check.1.ronn (renamed from man/bundle-check.ronn)0
-rw-r--r--lib/bundler/man/bundle-clean.124
-rw-r--r--lib/bundler/man/bundle-clean.1.ronn (renamed from man/bundle-clean.ronn)0
-rw-r--r--lib/bundler/man/bundle-config.1496
-rw-r--r--lib/bundler/man/bundle-config.1.ronn396
-rw-r--r--lib/bundler/man/bundle-doctor.144
-rw-r--r--lib/bundler/man/bundle-doctor.1.ronn (renamed from man/bundle-doctor.ronn)0
-rw-r--r--lib/bundler/man/bundle-exec.1165
-rw-r--r--lib/bundler/man/bundle-exec.1.ronn (renamed from man/bundle-exec.ronn)0
-rw-r--r--lib/bundler/man/bundle-gem.1115
-rw-r--r--lib/bundler/man/bundle-gem.1.ronn117
-rw-r--r--lib/bundler/man/bundle-info.120
-rw-r--r--lib/bundler/man/bundle-info.1.ronn (renamed from man/bundle-info.ronn)0
-rw-r--r--lib/bundler/man/bundle-init.125
-rw-r--r--lib/bundler/man/bundle-init.1.ronn (renamed from man/bundle-init.ronn)0
-rw-r--r--lib/bundler/man/bundle-inject.133
-rw-r--r--lib/bundler/man/bundle-inject.1.ronn (renamed from man/bundle-inject.ronn)0
-rw-r--r--lib/bundler/man/bundle-install.1338
-rw-r--r--lib/bundler/man/bundle-install.1.ronn405
-rw-r--r--lib/bundler/man/bundle-list.150
-rw-r--r--lib/bundler/man/bundle-list.1.ronn33
-rw-r--r--lib/bundler/man/bundle-lock.184
-rw-r--r--lib/bundler/man/bundle-lock.1.ronn (renamed from man/bundle-lock.ronn)0
-rw-r--r--lib/bundler/man/bundle-open.132
-rw-r--r--lib/bundler/man/bundle-open.1.ronn (renamed from man/bundle-open.ronn)0
-rw-r--r--lib/bundler/man/bundle-outdated.1155
-rw-r--r--lib/bundler/man/bundle-outdated.1.ronn (renamed from man/bundle-outdated.ronn)0
-rw-r--r--lib/bundler/man/bundle-platform.161
-rw-r--r--lib/bundler/man/bundle-platform.1.ronn (renamed from man/bundle-platform.ronn)0
-rw-r--r--lib/bundler/man/bundle-pristine.134
-rw-r--r--lib/bundler/man/bundle-pristine.1.ronn (renamed from man/bundle-pristine.ronn)0
-rw-r--r--lib/bundler/man/bundle-remove.131
-rw-r--r--lib/bundler/man/bundle-remove.1.ronn (renamed from man/bundle-remove.ronn)0
-rw-r--r--lib/bundler/man/bundle-show.123
-rw-r--r--lib/bundler/man/bundle-show.1.ronn (renamed from man/bundle-show.ronn)0
-rw-r--r--lib/bundler/man/bundle-update.1394
-rw-r--r--lib/bundler/man/bundle-update.1.ronn350
-rw-r--r--lib/bundler/man/bundle-viz.139
-rw-r--r--lib/bundler/man/bundle-viz.1.ronn (renamed from man/bundle-viz.ronn)0
-rw-r--r--lib/bundler/man/bundle.1136
-rw-r--r--lib/bundler/man/bundle.1.ronn (renamed from man/bundle.ronn)0
-rw-r--r--lib/bundler/man/gemfile.5712
-rw-r--r--lib/bundler/man/gemfile.5.ronn525
-rw-r--r--lib/bundler/man/index.txt25
-rw-r--r--lib/bundler/mirror.rb4
-rw-r--r--lib/bundler/plugin.rb67
-rw-r--r--lib/bundler/plugin/api/source.rb24
-rw-r--r--lib/bundler/plugin/dsl.rb2
-rw-r--r--lib/bundler/plugin/index.rb14
-rw-r--r--lib/bundler/plugin/installer.rb22
-rw-r--r--lib/bundler/plugin/installer/rubygems.rb2
-rw-r--r--lib/bundler/plugin/source_list.rb6
-rw-r--r--lib/bundler/psyched_yaml.rb15
-rw-r--r--lib/bundler/remote_specification.rb7
-rw-r--r--lib/bundler/resolver.rb222
-rw-r--r--lib/bundler/resolver/spec_group.rb109
-rw-r--r--lib/bundler/retry.rb4
-rw-r--r--lib/bundler/ruby_version.rb2
-rw-r--r--lib/bundler/rubygems_ext.rb112
-rw-r--r--lib/bundler/rubygems_gem_installer.rb77
-rw-r--r--lib/bundler/rubygems_integration.rb129
-rw-r--r--lib/bundler/runtime.rb47
-rw-r--r--lib/bundler/settings.rb206
-rw-r--r--lib/bundler/setup.rb4
-rw-r--r--lib/bundler/shared_helpers.rb18
-rw-r--r--lib/bundler/similarity_detector.rb2
-rw-r--r--lib/bundler/source.rb23
-rw-r--r--lib/bundler/source/git.rb66
-rw-r--r--lib/bundler/source/git/git_proxy.rb172
-rw-r--r--lib/bundler/source/metadata.rb4
-rw-r--r--lib/bundler/source/path.rb14
-rw-r--r--lib/bundler/source/path/installer.rb20
-rw-r--r--lib/bundler/source/rubygems.rb242
-rw-r--r--lib/bundler/source/rubygems/remote.rb2
-rw-r--r--lib/bundler/source/rubygems_aggregate.rb68
-rw-r--r--lib/bundler/source_list.rb164
-rw-r--r--lib/bundler/source_map.rb58
-rw-r--r--lib/bundler/spec_set.rb67
-rw-r--r--lib/bundler/stub_specification.rb32
-rw-r--r--lib/bundler/templates/Executable.bundler12
-rw-r--r--lib/bundler/templates/Gemfile2
-rw-r--r--lib/bundler/templates/gems.rb2
-rw-r--r--lib/bundler/templates/newgem/CHANGELOG.md.tt5
-rw-r--r--lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt104
-rw-r--r--lib/bundler/templates/newgem/Gemfile.tt13
-rw-r--r--lib/bundler/templates/newgem/README.md.tt11
-rw-r--r--lib/bundler/templates/newgem/Rakefile.tt28
-rw-r--r--lib/bundler/templates/newgem/bin/console.tt1
-rw-r--r--lib/bundler/templates/newgem/circleci/config.yml.tt13
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt2
-rw-r--r--lib/bundler/templates/newgem/github/workflows/main.yml.tt27
-rw-r--r--lib/bundler/templates/newgem/gitlab-ci.yml.tt9
-rw-r--r--lib/bundler/templates/newgem/lib/newgem.rb.tt6
-rw-r--r--lib/bundler/templates/newgem/lib/newgem/version.rb.tt2
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt44
-rw-r--r--lib/bundler/templates/newgem/rubocop.yml.tt13
-rw-r--r--lib/bundler/templates/newgem/sig/newgem.rbs.tt8
-rw-r--r--lib/bundler/templates/newgem/spec/newgem_spec.rb.tt2
-rw-r--r--lib/bundler/templates/newgem/spec/spec_helper.rb.tt3
-rw-r--r--lib/bundler/templates/newgem/standard.yml.tt2
-rw-r--r--lib/bundler/templates/newgem/test/minitest/newgem_test.rb.tt13
-rw-r--r--lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt6
-rw-r--r--lib/bundler/templates/newgem/test/newgem_test.rb.tt11
-rw-r--r--lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt15
-rw-r--r--lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt6
-rw-r--r--lib/bundler/templates/newgem/test/test_helper.rb.tt4
-rw-r--r--lib/bundler/ui/shell.rb10
-rw-r--r--lib/bundler/uri_credentials_filter.rb4
-rw-r--r--lib/bundler/vendor/.document1
-rw-r--r--lib/bundler/vendor/connection_pool/LICENSE20
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool.rb113
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb66
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb40
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb2
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb57
-rw-r--r--lib/bundler/vendor/fileutils/LICENSE.txt22
-rw-r--r--lib/bundler/vendor/fileutils/lib/fileutils/version.rb5
-rw-r--r--lib/bundler/vendor/molinillo/LICENSE9
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo.rb1
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb26
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb7
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb40
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb4
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb16
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/errors.rb6
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb2
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb13
-rw-r--r--lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb96
-rw-r--r--lib/bundler/vendor/net-http-persistent/README.rdoc82
-rw-r--r--lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb271
-rw-r--r--lib/bundler/vendor/thor/LICENSE.md20
-rw-r--r--lib/bundler/vendor/thor/lib/thor.rb18
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/create_link.rb3
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/base.rb9
-rw-r--r--lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb12
-rw-r--r--lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb129
-rw-r--r--lib/bundler/vendor/thor/lib/thor/error.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/arguments.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/options.rb17
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/basic.rb7
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/color.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/version.rb2
-rw-r--r--lib/bundler/vendor/tmpdir/lib/tmpdir.rb154
-rw-r--r--lib/bundler/vendor/tsort/LICENSE.txt22
-rw-r--r--lib/bundler/vendor/tsort/lib/tsort.rb453
-rw-r--r--lib/bundler/vendor/uri/LICENSE.txt22
-rw-r--r--lib/bundler/vendored_persistent.rb7
-rw-r--r--lib/bundler/vendored_tmpdir.rb4
-rw-r--r--lib/bundler/vendored_tsort.rb4
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/bundler/worker.rb25
-rw-r--r--lib/bundler/yaml_serializer.rb2
-rw-r--r--lib/cgi.rb1
-rw-r--r--lib/cgi/cgi.gemspec18
-rw-r--r--lib/cgi/cookie.rb44
-rw-r--r--lib/cgi/core.rb45
-rw-r--r--lib/cgi/version.rb3
-rw-r--r--lib/csv.rb2284
-rw-r--r--lib/csv/csv.gemspec50
-rw-r--r--lib/csv/fields_converter.rb2
-rw-r--r--lib/csv/parser.rb16
-rw-r--r--lib/csv/row.rb414
-rw-r--r--lib/csv/table.rb319
-rw-r--r--lib/csv/version.rb2
-rw-r--r--lib/csv/writer.rb49
-rw-r--r--lib/debug.gemspec22
-rw-r--r--lib/debug.rb36
-rw-r--r--lib/delegate.rb25
-rw-r--r--lib/delegate/delegate.gemspec18
-rw-r--r--lib/delegate/version.rb3
-rw-r--r--lib/did_you_mean.rb4
-rw-r--r--lib/did_you_mean/experimental/initializer_name_correction.rb20
-rw-r--r--lib/did_you_mean/experimental/ivar_name_correction.rb76
-rw-r--r--lib/did_you_mean/spell_checkers/method_name_checker.rb7
-rw-r--r--lib/did_you_mean/spell_checkers/require_path_checker.rb35
-rw-r--r--lib/did_you_mean/tree_spell_checker.rb150
-rw-r--r--lib/did_you_mean/version.rb2
-rw-r--r--lib/drb/drb.gemspec30
-rw-r--r--lib/drb/drb.rb9
-rw-r--r--lib/drb/observer.rb2
-rw-r--r--lib/drb/ssl.rb2
-rw-r--r--lib/drb/version.rb3
-rw-r--r--lib/erb.gemspec24
-rw-r--r--lib/fileutils.gemspec2
-rw-r--r--lib/fileutils.rb32
-rw-r--r--lib/find.gemspec24
-rw-r--r--lib/forwardable.rb9
-rw-r--r--lib/forwardable/forwardable.gemspec21
-rw-r--r--lib/forwardable/version.rb5
-rw-r--r--lib/getoptlong.rb3
-rw-r--r--lib/getoptlong/getoptlong.gemspec17
-rw-r--r--lib/getoptlong/version.rb3
-rw-r--r--lib/ipaddr.gemspec10
-rw-r--r--lib/irb.rb147
-rw-r--r--lib/irb/cmd/fork.rb2
-rw-r--r--lib/irb/cmd/info.rb1
-rw-r--r--lib/irb/cmd/ls.rb83
-rw-r--r--lib/irb/cmd/measure.rb40
-rw-r--r--lib/irb/cmd/nop.rb14
-rw-r--r--lib/irb/cmd/show_source.rb86
-rw-r--r--lib/irb/cmd/whereami.rb20
-rw-r--r--lib/irb/color.rb24
-rw-r--r--lib/irb/color_printer.rb47
-rw-r--r--lib/irb/completion.rb100
-rw-r--r--lib/irb/context.rb35
-rw-r--r--lib/irb/easter-egg.rb3
-rw-r--r--lib/irb/ext/loader.rb65
-rw-r--r--lib/irb/ext/save-history.rb20
-rw-r--r--lib/irb/extend-command.rb43
-rw-r--r--lib/irb/init.rb88
-rw-r--r--lib/irb/input-method.rb31
-rw-r--r--lib/irb/inspector.rb26
-rw-r--r--lib/irb/irb.gemspec44
-rw-r--r--lib/irb/lc/help-message12
-rw-r--r--lib/irb/ruby-lex.rb374
-rw-r--r--lib/irb/version.rb4
-rw-r--r--lib/irb/workspace.rb9
-rw-r--r--lib/logger.rb9
-rw-r--r--lib/logger/formatter.rb2
-rw-r--r--lib/logger/log_device.rb2
-rw-r--r--lib/logger/logger.gemspec4
-rw-r--r--lib/logger/version.rb2
-rw-r--r--lib/matrix.rb301
-rw-r--r--lib/matrix/matrix.gemspec5
-rw-r--r--lib/matrix/version.rb2
-rw-r--r--lib/mkmf.rb31
-rw-r--r--lib/mutex_m.gemspec4
-rw-r--r--lib/mutex_m.rb3
-rw-r--r--lib/net/ftp.rb69
-rw-r--r--lib/net/http.rb59
-rw-r--r--lib/net/http/header.rb52
-rw-r--r--lib/net/http/net-http.gemspec36
-rw-r--r--lib/net/imap.rb14
-rw-r--r--lib/net/net-ftp.gemspec36
-rw-r--r--lib/net/net-imap.gemspec37
-rw-r--r--lib/net/net-pop.gemspec34
-rw-r--r--lib/net/net-protocol.gemspec36
-rw-r--r--lib/net/net-smtp.gemspec35
-rw-r--r--lib/net/pop.rb7
-rw-r--r--lib/net/pop/net-pop.gemspec27
-rw-r--r--lib/net/pop/version.rb6
-rw-r--r--lib/net/protocol.rb2
-rw-r--r--lib/net/smtp.rb116
-rw-r--r--lib/net/smtp/net-smtp.gemspec27
-rw-r--r--lib/net/smtp/version.rb6
-rw-r--r--lib/observer.rb27
-rw-r--r--lib/observer/observer.gemspec17
-rw-r--r--lib/observer/version.rb3
-rw-r--r--lib/open-uri.gemspec26
-rw-r--r--lib/open-uri.rb27
-rw-r--r--lib/open3.gemspec33
-rw-r--r--lib/open3.rb8
-rw-r--r--lib/open3/open3.gemspec29
-rw-r--r--lib/open3/version.rb3
-rw-r--r--lib/optparse.rb63
-rw-r--r--lib/optparse/kwargs.rb3
-rw-r--r--lib/optparse/optparse.gemspec33
-rw-r--r--lib/ostruct.rb212
-rw-r--r--lib/ostruct/ostruct.gemspec19
-rw-r--r--lib/ostruct/version.rb5
-rw-r--r--lib/pp.gemspec27
-rw-r--r--lib/pp.rb35
-rw-r--r--lib/prettyprint.gemspec22
-rw-r--r--lib/prettyprint.rb6
-rw-r--r--lib/prime.gemspec15
-rw-r--r--lib/prime.rb138
-rw-r--r--lib/pstore.rb2
-rw-r--r--lib/pstore/pstore.gemspec17
-rw-r--r--lib/pstore/version.rb3
-rw-r--r--lib/racc/compat.rb9
-rw-r--r--lib/racc/debugflags.rb9
-rw-r--r--lib/racc/exception.rb5
-rw-r--r--lib/racc/grammar.rb39
-rw-r--r--lib/racc/grammarfileparser.rb13
-rw-r--r--lib/racc/info.rb7
-rw-r--r--lib/racc/iset.rb9
-rw-r--r--lib/racc/logfilegenerator.rb9
-rw-r--r--lib/racc/parser-text.rb24
-rw-r--r--lib/racc/parser.rb24
-rw-r--r--lib/racc/parserfilegenerator.rb12
-rw-r--r--lib/racc/racc.gemspec38
-rw-r--r--lib/racc/sourcetext.rb9
-rw-r--r--lib/racc/state.rb5
-rw-r--r--lib/racc/statetransitiontable.rb13
-rw-r--r--lib/rdoc.rb21
-rw-r--r--lib/rdoc/any_method.rb59
-rw-r--r--lib/rdoc/context.rb12
-rw-r--r--lib/rdoc/context/section.rb13
-rw-r--r--lib/rdoc/cross_reference.rb4
-rw-r--r--lib/rdoc/erb_partial.rb2
-rw-r--r--lib/rdoc/erbio.rb4
-rw-r--r--lib/rdoc/generator/darkfish.rb6
-rw-r--r--lib/rdoc/generator/pot.rb6
-rw-r--r--lib/rdoc/generator/template/darkfish/_head.rhtml9
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml4
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml4
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml14
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml4
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml14
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml12
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml10
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml10
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml10
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml8
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml8
-rw-r--r--lib/rdoc/generator/template/darkfish/class.rhtml88
-rw-r--r--lib/rdoc/generator/template/darkfish/css/rdoc.css22
-rw-r--r--lib/rdoc/generator/template/darkfish/index.rhtml7
-rw-r--r--lib/rdoc/generator/template/darkfish/servlet_root.rhtml31
-rw-r--r--lib/rdoc/generator/template/darkfish/table_of_contents.rhtml32
-rw-r--r--lib/rdoc/i18n.rb2
-rw-r--r--lib/rdoc/markdown.rb519
-rw-r--r--lib/rdoc/markdown/literals.rb15
-rw-r--r--lib/rdoc/markup.rb1
-rw-r--r--lib/rdoc/markup/attr_span.rb10
-rw-r--r--lib/rdoc/markup/attribute_manager.rb121
-rw-r--r--lib/rdoc/markup/formatter.rb2
-rw-r--r--lib/rdoc/markup/pre_process.rb2
-rw-r--r--lib/rdoc/markup/table.rb47
-rw-r--r--lib/rdoc/markup/to_html.rb52
-rw-r--r--lib/rdoc/markup/to_html_crossref.rb18
-rw-r--r--lib/rdoc/markup/to_joined_paragraph.rb1
-rw-r--r--lib/rdoc/markup/to_rdoc.rb28
-rw-r--r--lib/rdoc/markup/to_table_of_contents.rb1
-rw-r--r--lib/rdoc/options.rb36
-rw-r--r--lib/rdoc/parser.rb14
-rw-r--r--lib/rdoc/parser/c.rb82
-rw-r--r--lib/rdoc/parser/changelog.rb159
-rw-r--r--lib/rdoc/rd/block_parser.rb2
-rw-r--r--lib/rdoc/rd/inline_parser.rb2
-rw-r--r--lib/rdoc/rdoc.gemspec5
-rw-r--r--lib/rdoc/rdoc.rb55
-rw-r--r--lib/rdoc/ri/driver.rb14
-rw-r--r--lib/rdoc/ri/paths.rb20
-rw-r--r--lib/rdoc/ri/task.rb2
-rw-r--r--lib/rdoc/rubygems_hook.rb4
-rw-r--r--lib/rdoc/servlet.rb7
-rw-r--r--lib/rdoc/store.rb4
-rw-r--r--lib/rdoc/version.rb2
-rw-r--r--lib/readline.gemspec2
-rw-r--r--lib/reline.rb40
-rw-r--r--lib/reline/ansi.rb61
-rw-r--r--lib/reline/config.rb16
-rw-r--r--lib/reline/general_io.rb18
-rw-r--r--lib/reline/key_actor/emacs.rb2
-rw-r--r--lib/reline/key_actor/vi_command.rb4
-rw-r--r--lib/reline/kill_ring.rb12
-rw-r--r--lib/reline/line_editor.rb971
-rw-r--r--lib/reline/reline.gemspec3
-rw-r--r--lib/reline/unicode.rb97
-rw-r--r--lib/reline/unicode/east_asian_width.rb2279
-rw-r--r--lib/reline/version.rb2
-rw-r--r--lib/reline/windows.rb48
-rw-r--r--lib/resolv-replace.gemspec24
-rw-r--r--lib/resolv.gemspec22
-rw-r--r--lib/resolv.rb28
-rw-r--r--lib/rexml/attlistdecl.rb63
-rw-r--r--lib/rexml/attribute.rb205
-rw-r--r--lib/rexml/cdata.rb68
-rw-r--r--lib/rexml/child.rb97
-rw-r--r--lib/rexml/comment.rb80
-rw-r--r--lib/rexml/doctype.rb320
-rw-r--r--lib/rexml/document.rb291
-rw-r--r--lib/rexml/dtd/attlistdecl.rb11
-rw-r--r--lib/rexml/dtd/dtd.rb47
-rw-r--r--lib/rexml/dtd/elementdecl.rb18
-rw-r--r--lib/rexml/dtd/entitydecl.rb57
-rw-r--r--lib/rexml/dtd/notationdecl.rb40
-rw-r--r--lib/rexml/element.rb1269
-rw-r--r--lib/rexml/encoding.rb51
-rw-r--r--lib/rexml/entity.rb171
-rw-r--r--lib/rexml/formatters/default.rb116
-rw-r--r--lib/rexml/formatters/pretty.rb142
-rw-r--r--lib/rexml/formatters/transitive.rb58
-rw-r--r--lib/rexml/functions.rb447
-rw-r--r--lib/rexml/instruction.rb79
-rw-r--r--lib/rexml/light/node.rb196
-rw-r--r--lib/rexml/namespace.rb59
-rw-r--r--lib/rexml/node.rb76
-rw-r--r--lib/rexml/output.rb30
-rw-r--r--lib/rexml/parent.rb166
-rw-r--r--lib/rexml/parseexception.rb52
-rw-r--r--lib/rexml/parsers/baseparser.rb694
-rw-r--r--lib/rexml/parsers/lightparser.rb59
-rw-r--r--lib/rexml/parsers/pullparser.rb197
-rw-r--r--lib/rexml/parsers/sax2parser.rb273
-rw-r--r--lib/rexml/parsers/streamparser.rb61
-rw-r--r--lib/rexml/parsers/treeparser.rb101
-rw-r--r--lib/rexml/parsers/ultralightparser.rb57
-rw-r--r--lib/rexml/parsers/xpathparser.rb675
-rw-r--r--lib/rexml/quickpath.rb266
-rw-r--r--lib/rexml/rexml.gemspec84
-rw-r--r--lib/rexml/rexml.rb32
-rw-r--r--lib/rexml/sax2listener.rb98
-rw-r--r--lib/rexml/security.rb28
-rw-r--r--lib/rexml/source.rb298
-rw-r--r--lib/rexml/streamlistener.rb93
-rw-r--r--lib/rexml/text.rb424
-rw-r--r--lib/rexml/undefinednamespaceexception.rb9
-rw-r--r--lib/rexml/validation/relaxng.rb539
-rw-r--r--lib/rexml/validation/validation.rb144
-rw-r--r--lib/rexml/validation/validationexception.rb10
-rw-r--r--lib/rexml/xmldecl.rb130
-rw-r--r--lib/rexml/xmltokens.rb85
-rw-r--r--lib/rexml/xpath.rb81
-rw-r--r--lib/rexml/xpath_parser.rb968
-rw-r--r--lib/rinda/rinda.gemspec28
-rw-r--r--lib/rss.rb94
-rw-r--r--lib/rss/0.9.rb462
-rw-r--r--lib/rss/1.0.rb485
-rw-r--r--lib/rss/2.0.rb143
-rw-r--r--lib/rss/atom.rb1025
-rw-r--r--lib/rss/content.rb34
-rw-r--r--lib/rss/content/1.0.rb10
-rw-r--r--lib/rss/content/2.0.rb12
-rw-r--r--lib/rss/converter.rb171
-rw-r--r--lib/rss/dublincore.rb164
-rw-r--r--lib/rss/dublincore/1.0.rb13
-rw-r--r--lib/rss/dublincore/2.0.rb13
-rw-r--r--lib/rss/dublincore/atom.rb17
-rw-r--r--lib/rss/image.rb198
-rw-r--r--lib/rss/itunes.rb425
-rw-r--r--lib/rss/maker.rb79
-rw-r--r--lib/rss/maker/0.9.rb509
-rw-r--r--lib/rss/maker/1.0.rb436
-rw-r--r--lib/rss/maker/2.0.rb224
-rw-r--r--lib/rss/maker/atom.rb173
-rw-r--r--lib/rss/maker/base.rb945
-rw-r--r--lib/rss/maker/content.rb22
-rw-r--r--lib/rss/maker/dublincore.rb122
-rw-r--r--lib/rss/maker/entry.rb164
-rw-r--r--lib/rss/maker/feed.rb427
-rw-r--r--lib/rss/maker/image.rb112
-rw-r--r--lib/rss/maker/itunes.rb243
-rw-r--r--lib/rss/maker/slash.rb34
-rw-r--r--lib/rss/maker/syndication.rb19
-rw-r--r--lib/rss/maker/taxonomy.rb119
-rw-r--r--lib/rss/maker/trackback.rb62
-rw-r--r--lib/rss/parser.rb589
-rw-r--r--lib/rss/rexmlparser.rb50
-rw-r--r--lib/rss/rss.gemspec80
-rw-r--r--lib/rss/rss.rb1342
-rw-r--r--lib/rss/slash.rb52
-rw-r--r--lib/rss/syndication.rb69
-rw-r--r--lib/rss/taxonomy.rb148
-rw-r--r--lib/rss/trackback.rb291
-rw-r--r--lib/rss/utils.rb200
-rw-r--r--lib/rss/version.rb4
-rw-r--r--lib/rss/xml-stylesheet.rb106
-rw-r--r--lib/rss/xml.rb72
-rw-r--r--lib/rss/xmlparser.rb95
-rw-r--r--lib/rss/xmlscanner.rb122
-rw-r--r--lib/rubygems.rb331
-rw-r--r--lib/rubygems/available_set.rb10
-rw-r--r--lib/rubygems/basic_specification.rb20
-rw-r--r--lib/rubygems/bundler_version_finder.rb23
-rw-r--r--lib/rubygems/command.rb43
-rw-r--r--lib/rubygems/command_manager.rb19
-rw-r--r--lib/rubygems/commands/build_command.rb66
-rw-r--r--lib/rubygems/commands/cert_command.rb109
-rw-r--r--lib/rubygems/commands/check_command.rb10
-rw-r--r--lib/rubygems/commands/cleanup_command.rb24
-rw-r--r--lib/rubygems/commands/contents_command.rb14
-rw-r--r--lib/rubygems/commands/dependency_command.rb20
-rw-r--r--lib/rubygems/commands/environment_command.rb6
-rw-r--r--lib/rubygems/commands/fetch_command.rb12
-rw-r--r--lib/rubygems/commands/generate_index_command.rb6
-rw-r--r--lib/rubygems/commands/help_command.rb8
-rw-r--r--lib/rubygems/commands/info_command.rb15
-rw-r--r--lib/rubygems/commands/install_command.rb33
-rw-r--r--lib/rubygems/commands/list_command.rb17
-rw-r--r--lib/rubygems/commands/lock_command.rb6
-rw-r--r--lib/rubygems/commands/mirror_command.rb4
-rw-r--r--lib/rubygems/commands/open_command.rb10
-rw-r--r--lib/rubygems/commands/outdated_command.rb10
-rw-r--r--lib/rubygems/commands/owner_command.rb21
-rw-r--r--lib/rubygems/commands/pristine_command.rb34
-rw-r--r--lib/rubygems/commands/push_command.rb65
-rw-r--r--lib/rubygems/commands/query_command.rb360
-rw-r--r--lib/rubygems/commands/rdoc_command.rb8
-rw-r--r--lib/rubygems/commands/search_command.rb16
-rw-r--r--lib/rubygems/commands/server_command.rb14
-rw-r--r--lib/rubygems/commands/setup_command.rb309
-rw-r--r--lib/rubygems/commands/signin_command.rb6
-rw-r--r--lib/rubygems/commands/signout_command.rb4
-rw-r--r--lib/rubygems/commands/sources_command.rb18
-rw-r--r--lib/rubygems/commands/specification_command.rb20
-rw-r--r--lib/rubygems/commands/stale_command.rb6
-rw-r--r--lib/rubygems/commands/uninstall_command.rb12
-rw-r--r--lib/rubygems/commands/unpack_command.rb14
-rw-r--r--lib/rubygems/commands/update_command.rb111
-rw-r--r--lib/rubygems/commands/which_command.rb4
-rw-r--r--lib/rubygems/commands/yank_command.rb21
-rw-r--r--lib/rubygems/config_file.rb28
-rw-r--r--lib/rubygems/core_ext/kernel_require.rb7
-rw-r--r--lib/rubygems/core_ext/kernel_warn.rb25
-rw-r--r--lib/rubygems/core_ext/tcpsocket_init.rb52
-rw-r--r--lib/rubygems/defaults.rb112
-rw-r--r--lib/rubygems/dependency.rb17
-rw-r--r--lib/rubygems/dependency_installer.rb100
-rw-r--r--lib/rubygems/dependency_list.rb22
-rw-r--r--lib/rubygems/deprecate.rb51
-rw-r--r--lib/rubygems/doctor.rb12
-rw-r--r--lib/rubygems/errors.rb20
-rw-r--r--lib/rubygems/exceptions.rb38
-rw-r--r--lib/rubygems/ext.rb12
-rw-r--r--lib/rubygems/ext/build_error.rb2
-rw-r--r--lib/rubygems/ext/builder.rb66
-rw-r--r--lib/rubygems/ext/cmake_builder.rb15
-rw-r--r--lib/rubygems/ext/configure_builder.rb13
-rw-r--r--lib/rubygems/ext/ext_conf_builder.rb47
-rw-r--r--lib/rubygems/ext/rake_builder.rb13
-rw-r--r--lib/rubygems/gem_runner.rb19
-rw-r--r--lib/rubygems/gemcutter_utilities.rb137
-rw-r--r--lib/rubygems/indexer.rb29
-rw-r--r--lib/rubygems/install_default_message.rb4
-rw-r--r--lib/rubygems/install_message.rb4
-rw-r--r--lib/rubygems/install_update_options.rb22
-rw-r--r--lib/rubygems/installer.rb228
-rw-r--r--lib/rubygems/installer_test_case.rb233
-rw-r--r--lib/rubygems/installer_uninstaller_utils.rb29
-rw-r--r--lib/rubygems/local_remote_options.rb10
-rw-r--r--lib/rubygems/mock_gem_ui.rb8
-rw-r--r--lib/rubygems/name_tuple.rb10
-rw-r--r--lib/rubygems/openssl.rb7
-rw-r--r--lib/rubygems/optparse.rb3
-rw-r--r--lib/rubygems/optparse/.document1
-rw-r--r--lib/rubygems/optparse/COPYING56
-rw-r--r--lib/rubygems/optparse/lib/optionparser.rb2
-rw-r--r--lib/rubygems/optparse/lib/optparse.rb2230
-rw-r--r--lib/rubygems/optparse/lib/optparse/ac.rb54
-rw-r--r--lib/rubygems/optparse/lib/optparse/date.rb18
-rw-r--r--lib/rubygems/optparse/lib/optparse/kwargs.rb22
-rw-r--r--lib/rubygems/optparse/lib/optparse/shellwords.rb7
-rw-r--r--lib/rubygems/optparse/lib/optparse/time.rb11
-rw-r--r--lib/rubygems/optparse/lib/optparse/uri.rb7
-rw-r--r--lib/rubygems/optparse/lib/optparse/version.rb71
-rw-r--r--lib/rubygems/package.rb126
-rw-r--r--lib/rubygems/package/digest_io.rb2
-rw-r--r--lib/rubygems/package/file_source.rb2
-rw-r--r--lib/rubygems/package/io_source.rb6
-rw-r--r--lib/rubygems/package/old.rb4
-rw-r--r--lib/rubygems/package/tar_header.rb10
-rw-r--r--lib/rubygems/package/tar_reader.rb5
-rw-r--r--lib/rubygems/package/tar_reader/entry.rb3
-rw-r--r--lib/rubygems/package/tar_test_case.rb141
-rw-r--r--lib/rubygems/package/tar_writer.rb14
-rw-r--r--lib/rubygems/package_task.rb12
-rw-r--r--lib/rubygems/path_support.rb4
-rw-r--r--lib/rubygems/platform.rb40
-rw-r--r--lib/rubygems/psych_tree.rb2
-rw-r--r--lib/rubygems/query_utils.rb353
-rw-r--r--lib/rubygems/rdoc.rb14
-rw-r--r--lib/rubygems/remote_fetcher.rb88
-rw-r--r--lib/rubygems/request.rb27
-rw-r--r--lib/rubygems/request/connection_pools.rb8
-rw-r--r--lib/rubygems/request/http_pool.rb4
-rw-r--r--lib/rubygems/request/https_pool.rb2
-rw-r--r--lib/rubygems/request_set.rb41
-rw-r--r--lib/rubygems/request_set/gem_dependency_api.rb12
-rw-r--r--lib/rubygems/request_set/lockfile.rb22
-rw-r--r--lib/rubygems/request_set/lockfile/parser.rb2
-rw-r--r--lib/rubygems/request_set/lockfile/tokenizer.rb6
-rw-r--r--lib/rubygems/requirement.rb64
-rw-r--r--lib/rubygems/resolver.rb88
-rw-r--r--lib/rubygems/resolver/activation_request.rb12
-rw-r--r--lib/rubygems/resolver/api_set.rb53
-rw-r--r--lib/rubygems/resolver/api_set/gem_parser.rb20
-rw-r--r--lib/rubygems/resolver/api_specification.rb32
-rw-r--r--lib/rubygems/resolver/best_set.rb6
-rw-r--r--lib/rubygems/resolver/composed_set.rb8
-rw-r--r--lib/rubygems/resolver/conflict.rb6
-rw-r--r--lib/rubygems/resolver/current_set.rb2
-rw-r--r--lib/rubygems/resolver/dependency_request.rb4
-rw-r--r--lib/rubygems/resolver/git_set.rb2
-rw-r--r--lib/rubygems/resolver/git_specification.rb4
-rw-r--r--lib/rubygems/resolver/index_set.rb4
-rw-r--r--lib/rubygems/resolver/index_specification.rb34
-rw-r--r--lib/rubygems/resolver/installed_specification.rb2
-rw-r--r--lib/rubygems/resolver/installer_set.rb73
-rw-r--r--lib/rubygems/resolver/local_specification.rb2
-rw-r--r--lib/rubygems/resolver/lock_set.rb6
-rw-r--r--lib/rubygems/resolver/lock_specification.rb2
-rw-r--r--lib/rubygems/resolver/molinillo.rb2
-rw-r--r--lib/rubygems/resolver/molinillo/LICENSE9
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo.rb11
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb7
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb8
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb49
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb1
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb3
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb3
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb3
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb3
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb13
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb3
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb7
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb63
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb84
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb3
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb14
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb4
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb675
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb5
-rw-r--r--lib/rubygems/resolver/molinillo/lib/molinillo/state.rb12
-rw-r--r--lib/rubygems/resolver/requirement_list.rb2
-rw-r--r--lib/rubygems/resolver/set.rb3
-rw-r--r--lib/rubygems/resolver/source_set.rb2
-rw-r--r--lib/rubygems/resolver/spec_specification.rb16
-rw-r--r--lib/rubygems/resolver/specification.rb18
-rw-r--r--lib/rubygems/resolver/stats.rb2
-rw-r--r--lib/rubygems/resolver/vendor_set.rb2
-rw-r--r--lib/rubygems/resolver/vendor_specification.rb2
-rw-r--r--lib/rubygems/s3_uri_signer.rb16
-rw-r--r--lib/rubygems/safe_yaml.rb10
-rw-r--r--lib/rubygems/security.rb131
-rw-r--r--lib/rubygems/security/policy.rb22
-rw-r--r--lib/rubygems/security/signer.rb21
-rw-r--r--lib/rubygems/security/trust_dir.rb5
-rw-r--r--lib/rubygems/security_option.rb10
-rw-r--r--lib/rubygems/server.rb31
-rw-r--r--lib/rubygems/source.rb49
-rw-r--r--lib/rubygems/source/git.rb19
-rw-r--r--lib/rubygems/source/installed.rb2
-rw-r--r--lib/rubygems/source/local.rb6
-rw-r--r--lib/rubygems/source/lock.rb2
-rw-r--r--lib/rubygems/source/specific_file.rb2
-rw-r--r--lib/rubygems/source/vendor.rb2
-rw-r--r--lib/rubygems/source_list.rb11
-rw-r--r--lib/rubygems/source_local.rb7
-rw-r--r--lib/rubygems/source_specific_file.rb6
-rw-r--r--lib/rubygems/spec_fetcher.rb47
-rw-r--r--lib/rubygems/specification.rb367
-rw-r--r--lib/rubygems/specification_policy.rb121
-rw-r--r--lib/rubygems/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem21
-rw-r--r--lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem23
-rw-r--r--lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem25
-rw-r--r--lib/rubygems/stub_specification.rb6
-rw-r--r--lib/rubygems/syck_hack.rb79
-rw-r--r--lib/rubygems/test_case.rb1554
-rw-r--r--lib/rubygems/test_utilities.rb380
-rw-r--r--lib/rubygems/tsort.rb3
-rw-r--r--lib/rubygems/tsort/.document1
-rw-r--r--lib/rubygems/tsort/LICENSE.txt22
-rw-r--r--lib/rubygems/tsort/lib/tsort.rb454
-rw-r--r--lib/rubygems/uninstaller.rb100
-rw-r--r--lib/rubygems/uri.rb111
-rw-r--r--lib/rubygems/uri_formatter.rb5
-rw-r--r--lib/rubygems/uri_parser.rb36
-rw-r--r--lib/rubygems/uri_parsing.rb23
-rw-r--r--lib/rubygems/user_interaction.rb33
-rw-r--r--lib/rubygems/util.rb10
-rw-r--r--lib/rubygems/util/licenses.rb123
-rw-r--r--lib/rubygems/util/list.rb2
-rw-r--r--lib/rubygems/validator.rb8
-rw-r--r--lib/rubygems/version.rb10
-rw-r--r--lib/rubygems/version_option.rb12
-rw-r--r--lib/securerandom.gemspec22
-rw-r--r--lib/securerandom.rb46
-rw-r--r--lib/set.rb429
-rw-r--r--lib/set/set.gemspec25
-rw-r--r--lib/set/sorted_set.rb6
-rw-r--r--lib/shellwords.gemspec22
-rw-r--r--lib/shellwords.rb39
-rw-r--r--lib/singleton.rb4
-rw-r--r--lib/singleton/singleton.gemspec17
-rw-r--r--lib/singleton/version.rb3
-rw-r--r--lib/tempfile.gemspec24
-rw-r--r--lib/tempfile.rb42
-rw-r--r--lib/time.gemspec24
-rw-r--r--lib/time.rb17
-rw-r--r--lib/timeout.rb2
-rw-r--r--lib/timeout/timeout.gemspec17
-rw-r--r--lib/timeout/version.rb3
-rw-r--r--lib/tmpdir.gemspec26
-rw-r--r--lib/tmpdir.rb25
-rw-r--r--lib/tracer.rb1
-rw-r--r--lib/tracer/tracer.gemspec20
-rw-r--r--lib/tracer/version.rb5
-rw-r--r--lib/tsort.gemspec22
-rw-r--r--lib/un.gemspec23
-rw-r--r--lib/un.rb18
-rw-r--r--lib/uri.rb21
-rw-r--r--lib/uri/common.rb97
-rw-r--r--lib/uri/ftp.rb1
-rw-r--r--lib/uri/generic.rb11
-rw-r--r--lib/uri/http.rb1
-rw-r--r--lib/uri/https.rb1
-rw-r--r--lib/uri/ldap.rb1
-rw-r--r--lib/uri/mailto.rb1
-rw-r--r--lib/uri/rfc2396_parser.rb15
-rw-r--r--lib/uri/rfc3986_parser.rb13
-rw-r--r--lib/uri/uri.gemspec2
-rw-r--r--lib/uri/version.rb2
-rw-r--r--lib/uri/ws.rb84
-rw-r--r--lib/uri/wss.rb22
-rw-r--r--lib/weakref.rb1
-rw-r--r--lib/weakref/weakref.gemspec34
-rw-r--r--lib/webrick.rb227
-rw-r--r--lib/webrick/httpauth/authenticator.rb117
-rw-r--r--lib/webrick/httpproxy.rb350
-rw-r--r--lib/webrick/httprequest.rb631
-rw-r--r--lib/webrick/httpservlet/filehandler.rb541
-rw-r--r--lib/webrick/httputils.rb511
-rw-r--r--lib/webrick/server.rb378
-rw-r--r--lib/webrick/ssl.rb215
-rw-r--r--lib/webrick/utils.rb270
-rw-r--r--lib/webrick/version.rb18
-rw-r--r--lib/webrick/webrick.gemspec76
-rw-r--r--lib/yaml.rb2
-rw-r--r--lib/yaml/yaml.gemspec4
-rwxr-xr-xlibexec/bundle3
-rwxr-xr-xlibexec/erb174
-rwxr-xr-xlibexec/racc60
-rwxr-xr-xlibexec/racc2y195
-rwxr-xr-xlibexec/y2racc339
-rw-r--r--load.c126
-rw-r--r--localeinit.c5
-rw-r--r--man/bundle-add.166
-rw-r--r--man/bundle-add.1.txt58
-rw-r--r--man/bundle-binstubs.140
-rw-r--r--man/bundle-binstubs.1.txt48
-rw-r--r--man/bundle-binstubs.ronn43
-rw-r--r--man/bundle-cache.155
-rw-r--r--man/bundle-cache.1.txt78
-rw-r--r--man/bundle-check.131
-rw-r--r--man/bundle-check.1.txt33
-rw-r--r--man/bundle-clean.124
-rw-r--r--man/bundle-clean.1.txt26
-rw-r--r--man/bundle-config.1497
-rw-r--r--man/bundle-config.1.txt528
-rw-r--r--man/bundle-config.ronn399
-rw-r--r--man/bundle-doctor.144
-rw-r--r--man/bundle-doctor.1.txt44
-rw-r--r--man/bundle-exec.1165
-rw-r--r--man/bundle-exec.1.txt178
-rw-r--r--man/bundle-gem.180
-rw-r--r--man/bundle-gem.1.txt91
-rw-r--r--man/bundle-gem.ronn78
-rw-r--r--man/bundle-info.120
-rw-r--r--man/bundle-info.1.txt21
-rw-r--r--man/bundle-init.125
-rw-r--r--man/bundle-init.1.txt34
-rw-r--r--man/bundle-inject.133
-rw-r--r--man/bundle-inject.1.txt32
-rw-r--r--man/bundle-install.1311
-rw-r--r--man/bundle-install.1.txt401
-rw-r--r--man/bundle-install.ronn383
-rw-r--r--man/bundle-list.150
-rw-r--r--man/bundle-list.1.txt43
-rw-r--r--man/bundle-list.ronn33
-rw-r--r--man/bundle-lock.184
-rw-r--r--man/bundle-lock.1.txt93
-rw-r--r--man/bundle-open.132
-rw-r--r--man/bundle-open.1.txt29
-rw-r--r--man/bundle-outdated.1155
-rw-r--r--man/bundle-outdated.1.txt131
-rw-r--r--man/bundle-package.155
-rw-r--r--man/bundle-package.1.txt79
-rw-r--r--man/bundle-package.ronn72
-rw-r--r--man/bundle-platform.161
-rw-r--r--man/bundle-platform.1.txt57
-rw-r--r--man/bundle-pristine.134
-rw-r--r--man/bundle-pristine.1.txt44
-rw-r--r--man/bundle-remove.131
-rw-r--r--man/bundle-remove.1.txt34
-rw-r--r--man/bundle-show.123
-rw-r--r--man/bundle-show.1.txt27
-rw-r--r--man/bundle-update.1394
-rw-r--r--man/bundle-update.1.txt390
-rw-r--r--man/bundle-update.ronn350
-rw-r--r--man/bundle-viz.139
-rw-r--r--man/bundle-viz.1.txt39
-rw-r--r--man/bundle.1136
-rw-r--r--man/bundle.1.txt116
-rw-r--r--man/gemfile.5686
-rw-r--r--man/gemfile.5.ronn517
-rw-r--r--man/gemfile.5.txt649
-rw-r--r--man/ruby.12
-rw-r--r--marshal.c143
-rw-r--r--math.c13
-rw-r--r--memory_view.c869
-rw-r--r--method.h24
-rw-r--r--mini_builtin.c3
-rwxr-xr-xmisc/expand_tabs.rb2
-rwxr-xr-xmisc/lldb_cruby.py261
-rw-r--r--misc/lldb_disasm.py239
-rw-r--r--missing/alloca.c2
-rw-r--r--missing/crypt.h5
-rw-r--r--missing/dtoa.c108
-rw-r--r--missing/dup2.c2
-rw-r--r--missing/explicit_bzero.c4
-rw-r--r--missing/file.h3
-rw-r--r--missing/flock.c2
-rw-r--r--missing/isinf.c2
-rw-r--r--missing/stdbool.h20
-rw-r--r--missing/tgamma.c2
-rw-r--r--mjit.c371
-rw-r--r--mjit.h125
-rw-r--r--mjit_compile.c270
-rw-r--r--mjit_worker.c692
-rw-r--r--node.c101
-rw-r--r--node.h41
-rw-r--r--numeric.c486
-rw-r--r--object.c611
-rw-r--r--pack.c17
-rw-r--r--pack.rb8
-rw-r--r--parse.y1616
-rw-r--r--prelude.rb15
-rw-r--r--probes.d11
-rw-r--r--probes_helper.h2
-rw-r--r--proc.c372
-rw-r--r--process.c563
-rw-r--r--ractor.c3257
-rw-r--r--ractor.rb838
-rw-r--r--ractor_core.h341
-rw-r--r--random.c620
-rw-r--r--range.c224
-rw-r--r--rational.c320
-rw-r--r--re.c155
-rw-r--r--regcomp.c22
-rw-r--r--regparse.c12
-rw-r--r--ruby-runner.c2
-rw-r--r--ruby.c401
-rw-r--r--ruby_assert.h24
-rw-r--r--ruby_atomic.h267
-rw-r--r--safe.c145
-rw-r--r--sample/drb/name.rb3
-rw-r--r--sample/list.rb5
-rw-r--r--sample/openssl/c_rehash.rb2
-rw-r--r--sample/openssl/echo_svr.rb2
-rw-r--r--sample/openssl/gen_csr.rb2
-rw-r--r--sample/trick2013/mame/remarks.markdown4
-rw-r--r--sample/trick2015/kinaba/entry.rb2
-rw-r--r--sample/webrick/demo-app.rb66
-rw-r--r--sample/webrick/demo-multipart.cgi12
-rw-r--r--sample/webrick/demo-servlet.rb6
-rw-r--r--sample/webrick/demo-urlencoded.cgi12
-rw-r--r--sample/webrick/hello.cgi11
-rw-r--r--sample/webrick/hello.rb8
-rw-r--r--sample/webrick/httpd.rb23
-rw-r--r--sample/webrick/httpproxy.rb25
-rw-r--r--sample/webrick/httpsd.rb33
-rw-r--r--scheduler.c212
-rw-r--r--signal.c150
-rw-r--r--spec/README.md2
-rw-r--r--spec/bundler/bundler/bundler_spec.rb49
-rw-r--r--spec/bundler/bundler/cli_spec.rb85
-rw-r--r--spec/bundler/bundler/compact_index_client/updater_spec.rb46
-rw-r--r--spec/bundler/bundler/definition_spec.rb92
-rw-r--r--spec/bundler/bundler/dep_proxy_spec.rb22
-rw-r--r--spec/bundler/bundler/digest_spec.rb17
-rw-r--r--spec/bundler/bundler/dsl_spec.rb134
-rw-r--r--spec/bundler/bundler/env_spec.rb59
-rw-r--r--spec/bundler/bundler/fetcher/compact_index_spec.rb5
-rw-r--r--spec/bundler/bundler/fetcher/downloader_spec.rb18
-rw-r--r--spec/bundler/bundler/fetcher/index_spec.rb119
-rw-r--r--spec/bundler/bundler/fetcher_spec.rb3
-rw-r--r--spec/bundler/bundler/friendly_errors_spec.rb33
-rw-r--r--spec/bundler/bundler/gem_helper_spec.rb143
-rw-r--r--spec/bundler/bundler/gem_version_promoter_spec.rb4
-rw-r--r--spec/bundler/bundler/installer/parallel_installer_spec.rb33
-rw-r--r--spec/bundler/bundler/installer/spec_installation_spec.rb4
-rw-r--r--spec/bundler/bundler/mirror_spec.rb2
-rw-r--r--spec/bundler/bundler/plugin/api/source_spec.rb6
-rw-r--r--spec/bundler/bundler/plugin/dsl_spec.rb2
-rw-r--r--spec/bundler/bundler/plugin/index_spec.rb23
-rw-r--r--spec/bundler/bundler/plugin_spec.rb19
-rw-r--r--spec/bundler/bundler/rubygems_integration_spec.rb16
-rw-r--r--spec/bundler/bundler/settings_spec.rb25
-rw-r--r--spec/bundler/bundler/shared_helpers_spec.rb44
-rw-r--r--spec/bundler/bundler/source/git/git_proxy_spec.rb49
-rw-r--r--spec/bundler/bundler/source/git_spec.rb49
-rw-r--r--spec/bundler/bundler/source/rubygems_spec.rb14
-rw-r--r--spec/bundler/bundler/source_list_spec.rb80
-rw-r--r--spec/bundler/bundler/source_spec.rb2
-rw-r--r--spec/bundler/bundler/stub_specification_spec.rb33
-rw-r--r--spec/bundler/bundler/worker_spec.rb47
-rw-r--r--spec/bundler/cache/gems_spec.rb67
-rw-r--r--spec/bundler/cache/git_spec.rb71
-rw-r--r--spec/bundler/cache/path_spec.rb43
-rw-r--r--spec/bundler/cache/platform_spec.rb4
-rw-r--r--spec/bundler/commands/add_spec.rb70
-rw-r--r--spec/bundler/commands/binstubs_spec.rb146
-rw-r--r--spec/bundler/commands/cache_spec.rb121
-rw-r--r--spec/bundler/commands/check_spec.rb260
-rw-r--r--spec/bundler/commands/clean_spec.rb134
-rw-r--r--spec/bundler/commands/config_spec.rb135
-rw-r--r--spec/bundler/commands/console_spec.rb51
-rw-r--r--spec/bundler/commands/doctor_spec.rb42
-rw-r--r--spec/bundler/commands/exec_spec.rb543
-rw-r--r--spec/bundler/commands/fund_spec.rb82
-rw-r--r--spec/bundler/commands/help_spec.rb29
-rw-r--r--spec/bundler/commands/info_spec.rb95
-rw-r--r--spec/bundler/commands/init_spec.rb34
-rw-r--r--spec/bundler/commands/inject_spec.rb36
-rw-r--r--spec/bundler/commands/install_spec.rb558
-rw-r--r--spec/bundler/commands/licenses_spec.rb10
-rw-r--r--spec/bundler/commands/list_spec.rb39
-rw-r--r--spec/bundler/commands/lock_spec.rb250
-rw-r--r--spec/bundler/commands/newgem_spec.rb1137
-rw-r--r--spec/bundler/commands/open_spec.rb15
-rw-r--r--spec/bundler/commands/outdated_spec.rb880
-rw-r--r--spec/bundler/commands/post_bundle_message_spec.rb137
-rw-r--r--spec/bundler/commands/pristine_spec.rb76
-rw-r--r--spec/bundler/commands/remove_spec.rb223
-rw-r--r--spec/bundler/commands/show_spec.rb35
-rw-r--r--spec/bundler/commands/update_spec.rb796
-rw-r--r--spec/bundler/commands/version_spec.rb12
-rw-r--r--spec/bundler/commands/viz_spec.rb25
-rw-r--r--spec/bundler/install/allow_offline_install_spec.rb22
-rw-r--r--spec/bundler/install/binstubs_spec.rb2
-rw-r--r--spec/bundler/install/bundler_spec.rb145
-rw-r--r--spec/bundler/install/deploy_spec.rb193
-rw-r--r--spec/bundler/install/failure_spec.rb101
-rw-r--r--spec/bundler/install/gemfile/eval_gemfile_spec.rb54
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb180
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb367
-rw-r--r--spec/bundler/install/gemfile/groups_spec.rb176
-rw-r--r--spec/bundler/install/gemfile/install_if.rb44
-rw-r--r--spec/bundler/install/gemfile/install_if_spec.rb44
-rw-r--r--spec/bundler/install/gemfile/lockfile_spec.rb8
-rw-r--r--spec/bundler/install/gemfile/path_spec.rb258
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb254
-rw-r--r--spec/bundler/install/gemfile/ruby_spec.rb11
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb1271
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb333
-rw-r--r--spec/bundler/install/gemfile_spec.rb60
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb305
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb162
-rw-r--r--spec/bundler/install/gems/flex_spec.rb102
-rw-r--r--spec/bundler/install/gems/fund_spec.rb137
-rw-r--r--spec/bundler/install/gems/native_extensions_spec.rb73
-rw-r--r--spec/bundler/install/gems/post_install_spec.rb2
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb169
-rw-r--r--spec/bundler/install/gems/standalone_spec.rb268
-rw-r--r--spec/bundler/install/gems/sudo_spec.rb36
-rw-r--r--spec/bundler/install/gems/win32_spec.rb3
-rw-r--r--spec/bundler/install/gemspecs_spec.rb21
-rw-r--r--spec/bundler/install/git_spec.rb47
-rw-r--r--spec/bundler/install/global_cache_spec.rb113
-rw-r--r--spec/bundler/install/path_spec.rb99
-rw-r--r--spec/bundler/install/prereleases_spec.rb21
-rw-r--r--spec/bundler/install/process_lock_spec.rb2
-rw-r--r--spec/bundler/install/redownload_spec.rb21
-rw-r--r--spec/bundler/install/security_policy_spec.rb16
-rw-r--r--spec/bundler/install/yanked_spec.rb37
-rw-r--r--spec/bundler/lock/git_spec.rb1
-rw-r--r--spec/bundler/lock/lockfile_spec.rb658
-rw-r--r--spec/bundler/other/cli_dispatch_spec.rb6
-rw-r--r--spec/bundler/other/ext_spec.rb4
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb417
-rw-r--r--spec/bundler/other/platform_spec.rb665
-rw-r--r--spec/bundler/plugins/command_spec.rb6
-rw-r--r--spec/bundler/plugins/install_spec.rb76
-rw-r--r--spec/bundler/plugins/source/example_spec.rb86
-rw-r--r--spec/bundler/plugins/source_spec.rb3
-rw-r--r--spec/bundler/plugins/uninstall_spec.rb49
-rw-r--r--spec/bundler/quality_es_spec.rb20
-rw-r--r--spec/bundler/quality_spec.rb170
-rw-r--r--spec/bundler/realworld/dependency_api_spec.rb4
-rw-r--r--spec/bundler/realworld/double_check_spec.rb10
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb468
-rw-r--r--spec/bundler/realworld/ffi_spec.rb57
-rw-r--r--spec/bundler/realworld/fixtures/warbler/.gitignore1
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile7
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile.lock30
-rw-r--r--spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb3
-rw-r--r--spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec10
-rw-r--r--spec/bundler/realworld/gemfile_source_header_spec.rb2
-rw-r--r--spec/bundler/realworld/mirror_probe_spec.rb33
-rw-r--r--spec/bundler/realworld/parallel_spec.rb4
-rw-r--r--spec/bundler/realworld/slow_perf_spec.rb22
-rw-r--r--spec/bundler/resolver/basic_spec.rb2
-rw-r--r--spec/bundler/resolver/platform_spec.rb264
-rw-r--r--spec/bundler/runtime/executable_spec.rb54
-rw-r--r--spec/bundler/runtime/gem_tasks_spec.rb56
-rw-r--r--spec/bundler/runtime/inline_spec.rb139
-rw-r--r--spec/bundler/runtime/load_spec.rb16
-rw-r--r--spec/bundler/runtime/platform_spec.rb174
-rw-r--r--spec/bundler/runtime/require_spec.rb41
-rw-r--r--spec/bundler/runtime/setup_spec.rb471
-rw-r--r--spec/bundler/runtime/with_unbundled_env_spec.rb134
-rw-r--r--spec/bundler/spec_helper.rb80
-rw-r--r--spec/bundler/support/api_request_limit_hax.rb16
-rw-r--r--spec/bundler/support/artifice/compact_index.rb12
-rw-r--r--spec/bundler/support/artifice/compact_index_concurrent_download.rb4
-rw-r--r--spec/bundler/support/artifice/compact_index_creds_diff_host.rb2
-rw-r--r--spec/bundler/support/artifice/compact_index_extra.rb8
-rw-r--r--spec/bundler/support/artifice/compact_index_extra_api.rb10
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update.rb6
-rw-r--r--spec/bundler/support/artifice/compact_index_partial_update_no_etag_not_incremental.rb40
-rw-r--r--spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb2
-rw-r--r--spec/bundler/support/artifice/compact_index_rate_limited.rb2
-rw-r--r--spec/bundler/support/artifice/endpoint.rb73
-rw-r--r--spec/bundler/support/artifice/endpoint_500.rb3
-rw-r--r--spec/bundler/support/artifice/endpoint_creds_diff_host.rb2
-rw-r--r--spec/bundler/support/artifice/endpoint_extra.rb8
-rw-r--r--spec/bundler/support/artifice/endpoint_extra_api.rb8
-rw-r--r--spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb (renamed from spec/bundler/support/artifice/endopint_marshal_fail_basic_authentication.rb)0
-rw-r--r--spec/bundler/support/artifice/endpoint_mirror_source.rb2
-rw-r--r--spec/bundler/support/artifice/fail.rb5
-rw-r--r--spec/bundler/support/artifice/vcr.rb19
-rw-r--r--spec/bundler/support/artifice/windows.rb7
-rw-r--r--spec/bundler/support/build_metadata.rb49
-rw-r--r--spec/bundler/support/builders.rb316
-rw-r--r--spec/bundler/support/bundle.rb8
-rw-r--r--spec/bundler/support/command_execution.rb13
-rw-r--r--spec/bundler/support/filters.rb19
-rw-r--r--spec/bundler/support/hax.rb66
-rw-r--r--spec/bundler/support/helpers.rb413
-rw-r--r--spec/bundler/support/indexes.rb13
-rw-r--r--spec/bundler/support/matchers.rb121
-rw-r--r--spec/bundler/support/parallel.rb5
-rw-r--r--spec/bundler/support/path.rb190
-rw-r--r--spec/bundler/support/platforms.rb16
-rw-r--r--spec/bundler/support/rubygems_ext.rb151
-rw-r--r--spec/bundler/support/rubygems_version_manager.rb51
-rw-r--r--spec/bundler/support/sometimes.rb57
-rw-r--r--spec/bundler/support/switch_rubygems.rb4
-rw-r--r--spec/bundler/update/gemfile_spec.rb16
-rw-r--r--spec/bundler/update/gems/fund_spec.rb50
-rw-r--r--spec/bundler/update/gems/post_install_spec.rb8
-rw-r--r--spec/bundler/update/git_spec.rb123
-rw-r--r--spec/bundler/update/path_spec.rb1
-rw-r--r--spec/bundler/update/redownload_spec.rb8
-rw-r--r--spec/mspec/Gemfile2
-rw-r--r--spec/mspec/Gemfile.lock4
-rw-r--r--spec/mspec/README.md4
-rw-r--r--spec/mspec/lib/mspec/expectations/should.rb10
-rw-r--r--spec/mspec/lib/mspec/guards/bug.rb19
-rw-r--r--spec/mspec/lib/mspec/guards/guard.rb2
-rw-r--r--spec/mspec/lib/mspec/guards/platform.rb13
-rw-r--r--spec/mspec/lib/mspec/guards/version.rb37
-rw-r--r--spec/mspec/lib/mspec/helpers.rb1
-rw-r--r--spec/mspec/lib/mspec/helpers/frozen_error_class.rb17
-rw-r--r--spec/mspec/lib/mspec/helpers/io.rb4
-rw-r--r--spec/mspec/lib/mspec/helpers/numeric.rb8
-rw-r--r--spec/mspec/lib/mspec/helpers/ruby_exe.rb4
-rw-r--r--spec/mspec/lib/mspec/helpers/scratch.rb4
-rw-r--r--spec/mspec/lib/mspec/helpers/tmp.rb13
-rw-r--r--spec/mspec/lib/mspec/matchers/include.rb4
-rw-r--r--spec/mspec/lib/mspec/matchers/raise_error.rb35
-rw-r--r--spec/mspec/lib/mspec/mocks/mock.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb11
-rw-r--r--spec/mspec/lib/mspec/runner/actions/leakchecker.rb26
-rw-r--r--spec/mspec/lib/mspec/runner/actions/timeout.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/context.rb35
-rw-r--r--spec/mspec/lib/mspec/runner/example.rb12
-rw-r--r--spec/mspec/lib/mspec/runner/exception.rb31
-rw-r--r--spec/mspec/lib/mspec/runner/formatters.rb1
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/method.rb14
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/spinner.rb2
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/stats.rb57
-rw-r--r--spec/mspec/lib/mspec/runner/mspec.rb86
-rw-r--r--spec/mspec/lib/mspec/runner/object.rb4
-rw-r--r--spec/mspec/lib/mspec/runner/parallel.rb2
-rw-r--r--spec/mspec/lib/mspec/utils/format.rb6
-rw-r--r--spec/mspec/lib/mspec/utils/options.rb16
-rw-r--r--spec/mspec/lib/mspec/utils/script.rb7
-rw-r--r--spec/mspec/lib/mspec/utils/version.rb2
-rw-r--r--spec/mspec/lib/mspec/utils/warnings.rb28
-rw-r--r--spec/mspec/spec/fixtures/config.mspec2
-rwxr-xr-xspec/mspec/spec/fixtures/my_ruby2
-rw-r--r--spec/mspec/spec/guards/guard_spec.rb4
-rw-r--r--spec/mspec/spec/guards/version_spec.rb58
-rw-r--r--spec/mspec/spec/helpers/io_spec.rb2
-rw-r--r--spec/mspec/spec/helpers/tmp_spec.rb2
-rw-r--r--spec/mspec/spec/integration/run_spec.rb2
-rw-r--r--spec/mspec/spec/integration/tag_spec.rb2
-rw-r--r--spec/mspec/spec/matchers/raise_error_spec.rb53
-rw-r--r--spec/mspec/spec/runner/context_spec.rb29
-rw-r--r--spec/mspec/spec/runner/example_spec.rb10
-rw-r--r--spec/mspec/spec/runner/exception_spec.rb2
-rw-r--r--spec/mspec/spec/runner/mspec_spec.rb19
-rw-r--r--spec/mspec/spec/utils/options_spec.rb21
-rw-r--r--spec/mspec/spec/utils/script_spec.rb2
-rw-r--r--spec/mspec/tool/remove_old_guards.rb9
-rw-r--r--spec/mspec/tool/sync/sync-rubyspec.rb44
-rwxr-xr-xspec/mspec/tool/tag_from_output.rb6
-rwxr-xr-xspec/mspec/tool/wrap_with_guard.rb28
-rw-r--r--spec/ruby/.mspec.constants6
-rw-r--r--spec/ruby/.rubocop.yml17
-rw-r--r--spec/ruby/.rubocop_todo.yml67
-rw-r--r--spec/ruby/CONTRIBUTING.md93
-rw-r--r--spec/ruby/README.md27
-rw-r--r--spec/ruby/command_line/dash_e_spec.rb2
-rw-r--r--spec/ruby/command_line/dash_l_spec.rb31
-rw-r--r--spec/ruby/command_line/dash_r_spec.rb19
-rw-r--r--spec/ruby/command_line/dash_upper_k_spec.rb4
-rw-r--r--spec/ruby/command_line/dash_upper_w_spec.rb32
-rw-r--r--spec/ruby/command_line/error_message_spec.rb4
-rw-r--r--spec/ruby/command_line/feature_spec.rb13
-rw-r--r--spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh2
-rw-r--r--spec/ruby/command_line/fixtures/test_file.rb2
-rw-r--r--spec/ruby/command_line/rubyopt_spec.rb20
-rw-r--r--spec/ruby/core/argf/binmode_spec.rb2
-rw-r--r--spec/ruby/core/argf/bytes_spec.rb6
-rw-r--r--spec/ruby/core/argf/chars_spec.rb6
-rw-r--r--spec/ruby/core/argf/codepoints_spec.rb6
-rw-r--r--spec/ruby/core/argf/lines_spec.rb6
-rw-r--r--spec/ruby/core/argf/shared/fileno.rb2
-rw-r--r--spec/ruby/core/array/any_spec.rb6
-rw-r--r--spec/ruby/core/array/append_spec.rb10
-rw-r--r--spec/ruby/core/array/bsearch_index_spec.rb2
-rw-r--r--spec/ruby/core/array/clear_spec.rb6
-rw-r--r--spec/ruby/core/array/clone_spec.rb4
-rw-r--r--spec/ruby/core/array/compact_spec.rb4
-rw-r--r--spec/ruby/core/array/concat_spec.rb8
-rw-r--r--spec/ruby/core/array/deconstruct_spec.rb11
-rw-r--r--spec/ruby/core/array/delete_at_spec.rb4
-rw-r--r--spec/ruby/core/array/delete_if_spec.rb8
-rw-r--r--spec/ruby/core/array/delete_spec.rb4
-rw-r--r--spec/ruby/core/array/element_set_spec.rb59
-rw-r--r--spec/ruby/core/array/empty_spec.rb6
-rw-r--r--spec/ruby/core/array/fill_spec.rb20
-rw-r--r--spec/ruby/core/array/first_spec.rb2
-rw-r--r--spec/ruby/core/array/fixtures/classes.rb4
-rw-r--r--spec/ruby/core/array/flatten_spec.rb52
-rw-r--r--spec/ruby/core/array/frozen_spec.rb6
-rw-r--r--spec/ruby/core/array/hash_spec.rb2
-rw-r--r--spec/ruby/core/array/initialize_spec.rb6
-rw-r--r--spec/ruby/core/array/insert_spec.rb8
-rw-r--r--spec/ruby/core/array/intersection_spec.rb88
-rw-r--r--spec/ruby/core/array/minmax_spec.rb14
-rw-r--r--spec/ruby/core/array/multiply_spec.rb34
-rw-r--r--spec/ruby/core/array/pop_spec.rb14
-rw-r--r--spec/ruby/core/array/prepend_spec.rb6
-rw-r--r--spec/ruby/core/array/reject_spec.rb8
-rw-r--r--spec/ruby/core/array/reverse_spec.rb4
-rw-r--r--spec/ruby/core/array/rotate_spec.rb8
-rw-r--r--spec/ruby/core/array/sample_spec.rb25
-rw-r--r--spec/ruby/core/array/shared/clone.rb8
-rw-r--r--spec/ruby/core/array/shared/collect.rb16
-rw-r--r--spec/ruby/core/array/shared/intersection.rb84
-rw-r--r--spec/ruby/core/array/shared/join.rb14
-rw-r--r--spec/ruby/core/array/shared/keep_if.rb8
-rw-r--r--spec/ruby/core/array/shared/push.rb6
-rw-r--r--spec/ruby/core/array/shared/replace.rb4
-rw-r--r--spec/ruby/core/array/shared/slice.rb83
-rw-r--r--spec/ruby/core/array/shared/union.rb2
-rw-r--r--spec/ruby/core/array/shared/unshift.rb8
-rw-r--r--spec/ruby/core/array/shift_spec.rb8
-rw-r--r--spec/ruby/core/array/shuffle_spec.rb12
-rw-r--r--spec/ruby/core/array/slice_spec.rb16
-rw-r--r--spec/ruby/core/array/sort_by_spec.rb8
-rw-r--r--spec/ruby/core/array/sort_spec.rb22
-rw-r--r--spec/ruby/core/array/uniq_spec.rb32
-rw-r--r--spec/ruby/core/array/values_at_spec.rb7
-rw-r--r--spec/ruby/core/basicobject/instance_eval_spec.rb8
-rw-r--r--spec/ruby/core/basicobject/instance_exec_spec.rb8
-rw-r--r--spec/ruby/core/binding/eval_spec.rb91
-rw-r--r--spec/ruby/core/binding/fixtures/classes.rb14
-rw-r--r--spec/ruby/core/binding/irb_spec.rb22
-rw-r--r--spec/ruby/core/builtin_constants/builtin_constants_spec.rb12
-rw-r--r--spec/ruby/core/class/allocate_spec.rb2
-rw-r--r--spec/ruby/core/class/initialize_spec.rb2
-rw-r--r--spec/ruby/core/class/new_spec.rb15
-rw-r--r--spec/ruby/core/class/superclass_spec.rb2
-rw-r--r--spec/ruby/core/comparable/lt_spec.rb6
-rw-r--r--spec/ruby/core/complex/coerce_spec.rb2
-rw-r--r--spec/ruby/core/complex/comparision_spec.rb27
-rw-r--r--spec/ruby/core/complex/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/complex/exponent_spec.rb2
-rw-r--r--spec/ruby/core/complex/finite_spec.rb12
-rw-r--r--spec/ruby/core/complex/shared/divide.rb4
-rw-r--r--spec/ruby/core/complex/spaceship_spec.rb27
-rw-r--r--spec/ruby/core/complex/to_c_spec.rb12
-rw-r--r--spec/ruby/core/complex/to_f_spec.rb2
-rw-r--r--spec/ruby/core/complex/to_i_spec.rb2
-rw-r--r--spec/ruby/core/complex/to_r_spec.rb2
-rw-r--r--spec/ruby/core/data/constants_spec.rb19
-rw-r--r--spec/ruby/core/dir/children_spec.rb102
-rw-r--r--spec/ruby/core/dir/each_child_spec.rb70
-rw-r--r--spec/ruby/core/dir/exists_spec.rb15
-rw-r--r--spec/ruby/core/dir/fileno_spec.rb2
-rw-r--r--spec/ruby/core/dir/fixtures/common.rb5
-rw-r--r--spec/ruby/core/dir/glob_spec.rb18
-rw-r--r--spec/ruby/core/dir/home_spec.rb6
-rw-r--r--spec/ruby/core/dir/mkdir_spec.rb34
-rw-r--r--spec/ruby/core/dir/shared/glob.rb107
-rw-r--r--spec/ruby/core/dir/shared/open.rb2
-rw-r--r--spec/ruby/core/encoding/converter/constants_spec.rb52
-rw-r--r--spec/ruby/core/encoding/converter/new_spec.rb4
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb1
-rw-r--r--spec/ruby/core/encoding/list_spec.rb14
-rw-r--r--spec/ruby/core/encoding/locale_charmap_spec.rb21
-rw-r--r--spec/ruby/core/enumerable/all_spec.rb139
-rw-r--r--spec/ruby/core/enumerable/any_spec.rb145
-rw-r--r--spec/ruby/core/enumerable/first_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/fixtures/classes.rb2
-rw-r--r--spec/ruby/core/enumerable/grep_spec.rb24
-rw-r--r--spec/ruby/core/enumerable/grep_v_spec.rb24
-rw-r--r--spec/ruby/core/enumerable/minmax_spec.rb34
-rw-r--r--spec/ruby/core/enumerable/none_spec.rb109
-rw-r--r--spec/ruby/core/enumerable/one_spec.rb125
-rw-r--r--spec/ruby/core/enumerable/shared/collect.rb30
-rw-r--r--spec/ruby/core/enumerable/sort_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/uniq_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/each_spec.rb6
-rw-r--r--spec/ruby/core/enumerator/initialize_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/lazy/eager_spec.rb29
-rw-r--r--spec/ruby/core/enumerator/lazy/initialize_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/new_spec.rb131
-rw-r--r--spec/ruby/core/enumerator/next_spec.rb11
-rw-r--r--spec/ruby/core/enumerator/produce_spec.rb36
-rw-r--r--spec/ruby/core/enumerator/yielder/append_spec.rb23
-rw-r--r--spec/ruby/core/enumerator/yielder/to_proc_spec.rb18
-rw-r--r--spec/ruby/core/enumerator/yielder/yield_spec.rb10
-rw-r--r--spec/ruby/core/env/delete_spec.rb7
-rw-r--r--spec/ruby/core/env/element_reference_spec.rb3
-rw-r--r--spec/ruby/core/env/empty_spec.rb6
-rw-r--r--spec/ruby/core/env/fetch_spec.rb3
-rw-r--r--spec/ruby/core/env/index_spec.rb2
-rw-r--r--spec/ruby/core/env/shared/key.rb14
-rw-r--r--spec/ruby/core/env/shift_spec.rb7
-rw-r--r--spec/ruby/core/env/values_at_spec.rb3
-rw-r--r--spec/ruby/core/exception/backtrace_spec.rb2
-rw-r--r--spec/ruby/core/exception/destination_encoding_name_spec.rb23
-rw-r--r--spec/ruby/core/exception/destination_encoding_spec.rb23
-rw-r--r--spec/ruby/core/exception/errno_spec.rb18
-rw-r--r--spec/ruby/core/exception/error_bytes_spec.rb12
-rw-r--r--spec/ruby/core/exception/error_char_spec.rb12
-rw-r--r--spec/ruby/core/exception/exit_value_spec.rb10
-rw-r--r--spec/ruby/core/exception/frozen_error_spec.rb8
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb134
-rw-r--r--spec/ruby/core/exception/hierarchy_spec.rb8
-rw-r--r--spec/ruby/core/exception/incomplete_input_spec.rb5
-rw-r--r--spec/ruby/core/exception/initialize_spec.rb1
-rw-r--r--spec/ruby/core/exception/io_error_spec.rb6
-rw-r--r--spec/ruby/core/exception/key_error_spec.rb6
-rw-r--r--spec/ruby/core/exception/name_error_spec.rb18
-rw-r--r--spec/ruby/core/exception/name_spec.rb4
-rw-r--r--spec/ruby/core/exception/no_method_error_spec.rb34
-rw-r--r--spec/ruby/core/exception/range_error_spec.rb7
-rw-r--r--spec/ruby/core/exception/readagain_bytes_spec.rb12
-rw-r--r--spec/ruby/core/exception/reason_spec.rb10
-rw-r--r--spec/ruby/core/exception/receiver_spec.rb6
-rw-r--r--spec/ruby/core/exception/result_spec.rb6
-rw-r--r--spec/ruby/core/exception/signm_spec.rb6
-rw-r--r--spec/ruby/core/exception/signo_spec.rb6
-rw-r--r--spec/ruby/core/exception/source_encoding_name_spec.rb23
-rw-r--r--spec/ruby/core/exception/source_encoding_spec.rb23
-rw-r--r--spec/ruby/core/exception/status_spec.rb6
-rw-r--r--spec/ruby/core/exception/success_spec.rb12
-rw-r--r--spec/ruby/core/exception/system_call_error_spec.rb15
-rw-r--r--spec/ruby/core/exception/system_exit_spec.rb17
-rw-r--r--spec/ruby/core/exception/system_stack_error_spec.rb7
-rw-r--r--spec/ruby/core/exception/top_level_spec.rb47
-rw-r--r--spec/ruby/core/exception/uncaught_throw_error_spec.rb6
-rw-r--r--spec/ruby/core/false/to_s_spec.rb2
-rw-r--r--spec/ruby/core/fiber/fixtures/classes.rb12
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb101
-rw-r--r--spec/ruby/core/fiber/resume_spec.rb37
-rw-r--r--spec/ruby/core/file/absolute_path_spec.rb6
-rw-r--r--spec/ruby/core/file/atime_spec.rb2
-rw-r--r--spec/ruby/core/file/ctime_spec.rb2
-rw-r--r--spec/ruby/core/file/exists_spec.rb6
-rw-r--r--spec/ruby/core/file/expand_path_spec.rb6
-rw-r--r--spec/ruby/core/file/extname_spec.rb10
-rw-r--r--spec/ruby/core/file/ftype_spec.rb8
-rw-r--r--spec/ruby/core/file/join_spec.rb9
-rw-r--r--spec/ruby/core/file/lchmod_spec.rb20
-rw-r--r--spec/ruby/core/file/link_spec.rb2
-rw-r--r--spec/ruby/core/file/lstat_spec.rb4
-rw-r--r--spec/ruby/core/file/lutime_spec.rb58
-rw-r--r--spec/ruby/core/file/mtime_spec.rb2
-rw-r--r--spec/ruby/core/file/open_spec.rb18
-rw-r--r--spec/ruby/core/file/realpath_spec.rb6
-rw-r--r--spec/ruby/core/file/shared/path.rb49
-rw-r--r--spec/ruby/core/file/size_spec.rb4
-rw-r--r--spec/ruby/core/file/stat/nlink_spec.rb2
-rw-r--r--spec/ruby/core/file/stat/owned_spec.rb6
-rw-r--r--spec/ruby/core/file/stat/pipe_spec.rb4
-rw-r--r--spec/ruby/core/file/stat_spec.rb18
-rw-r--r--spec/ruby/core/file/truncate_spec.rb6
-rw-r--r--spec/ruby/core/file/umask_spec.rb4
-rw-r--r--spec/ruby/core/file/utime_spec.rb12
-rw-r--r--spec/ruby/core/filetest/exists_spec.rb6
-rw-r--r--spec/ruby/core/float/comparison_spec.rb22
-rw-r--r--spec/ruby/core/float/finite_spec.rb8
-rw-r--r--spec/ruby/core/float/inspect_spec.rb6
-rw-r--r--spec/ruby/core/float/nan_spec.rb6
-rw-r--r--spec/ruby/core/float/negative_spec.rb33
-rw-r--r--spec/ruby/core/float/next_float_spec.rb2
-rw-r--r--spec/ruby/core/float/positive_spec.rb33
-rw-r--r--spec/ruby/core/float/prev_float_spec.rb2
-rw-r--r--spec/ruby/core/float/round_spec.rb13
-rw-r--r--spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb32
-rw-r--r--spec/ruby/core/float/shared/comparison_exception_in_coerce.rb34
-rw-r--r--spec/ruby/core/float/shared/quo.rb4
-rw-r--r--spec/ruby/core/float/shared/to_s.rb308
-rw-r--r--spec/ruby/core/float/to_s_spec.rb308
-rw-r--r--spec/ruby/core/float/uminus_spec.rb2
-rw-r--r--spec/ruby/core/float/zero_spec.rb6
-rw-r--r--spec/ruby/core/gc/profiler/disable_spec.rb2
-rw-r--r--spec/ruby/core/gc/profiler/enable_spec.rb2
-rw-r--r--spec/ruby/core/gc/start_spec.rb4
-rw-r--r--spec/ruby/core/hash/any_spec.rb4
-rw-r--r--spec/ruby/core/hash/clear_spec.rb6
-rw-r--r--spec/ruby/core/hash/compact_spec.rb4
-rw-r--r--spec/ruby/core/hash/compare_by_identity_spec.rb6
-rw-r--r--spec/ruby/core/hash/deconstruct_keys_spec.rb25
-rw-r--r--spec/ruby/core/hash/default_proc_spec.rb6
-rw-r--r--spec/ruby/core/hash/default_spec.rb6
-rw-r--r--spec/ruby/core/hash/delete_if_spec.rb6
-rw-r--r--spec/ruby/core/hash/delete_spec.rb6
-rw-r--r--spec/ruby/core/hash/element_reference_spec.rb14
-rw-r--r--spec/ruby/core/hash/empty_spec.rb10
-rw-r--r--spec/ruby/core/hash/except_spec.rb34
-rw-r--r--spec/ruby/core/hash/fixtures/name.rb30
-rw-r--r--spec/ruby/core/hash/index_spec.rb6
-rw-r--r--spec/ruby/core/hash/initialize_spec.rb10
-rw-r--r--spec/ruby/core/hash/keep_if_spec.rb6
-rw-r--r--spec/ruby/core/hash/rehash_spec.rb6
-rw-r--r--spec/ruby/core/hash/reject_spec.rb10
-rw-r--r--spec/ruby/core/hash/ruby2_keywords_hash_spec.rb47
-rw-r--r--spec/ruby/core/hash/shared/each.rb38
-rw-r--r--spec/ruby/core/hash/shared/replace.rb8
-rw-r--r--spec/ruby/core/hash/shared/select.rb8
-rw-r--r--spec/ruby/core/hash/shared/store.rb25
-rw-r--r--spec/ruby/core/hash/shared/update.rb10
-rw-r--r--spec/ruby/core/hash/shift_spec.rb6
-rw-r--r--spec/ruby/core/hash/slice_spec.rb82
-rw-r--r--spec/ruby/core/hash/to_proc_spec.rb16
-rw-r--r--spec/ruby/core/hash/transform_keys_spec.rb200
-rw-r--r--spec/ruby/core/hash/transform_values_spec.rb8
-rw-r--r--spec/ruby/core/integer/allbits_spec.rb62
-rw-r--r--spec/ruby/core/integer/anybits_spec.rb60
-rw-r--r--spec/ruby/core/integer/chr_spec.rb13
-rw-r--r--spec/ruby/core/integer/coerce_spec.rb20
-rw-r--r--spec/ruby/core/integer/comparison_spec.rb30
-rw-r--r--spec/ruby/core/integer/constants_spec.rb2
-rw-r--r--spec/ruby/core/integer/denominator_spec.rb2
-rw-r--r--spec/ruby/core/integer/div_spec.rb2
-rw-r--r--spec/ruby/core/integer/divide_spec.rb8
-rw-r--r--spec/ruby/core/integer/downto_spec.rb2
-rw-r--r--spec/ruby/core/integer/element_reference_spec.rb89
-rw-r--r--spec/ruby/core/integer/even_spec.rb4
-rw-r--r--spec/ruby/core/integer/gcd_spec.rb8
-rw-r--r--spec/ruby/core/integer/gcdlcm_spec.rb8
-rw-r--r--spec/ruby/core/integer/gt_spec.rb8
-rw-r--r--spec/ruby/core/integer/gte_spec.rb8
-rw-r--r--spec/ruby/core/integer/integer_spec.rb6
-rw-r--r--spec/ruby/core/integer/lcm_spec.rb8
-rw-r--r--spec/ruby/core/integer/left_shift_spec.rb25
-rw-r--r--spec/ruby/core/integer/lt_spec.rb8
-rw-r--r--spec/ruby/core/integer/lte_spec.rb13
-rw-r--r--spec/ruby/core/integer/minus_spec.rb8
-rw-r--r--spec/ruby/core/integer/multiply_spec.rb8
-rw-r--r--spec/ruby/core/integer/nobits_spec.rb60
-rw-r--r--spec/ruby/core/integer/plus_spec.rb8
-rw-r--r--spec/ruby/core/integer/pow_spec.rb82
-rw-r--r--spec/ruby/core/integer/right_shift_spec.rb23
-rw-r--r--spec/ruby/core/integer/round_spec.rb26
-rw-r--r--spec/ruby/core/integer/shared/comparison_coerce.rb22
-rw-r--r--spec/ruby/core/integer/shared/equal.rb4
-rw-r--r--spec/ruby/core/integer/shared/integer_rounding.rb16
-rw-r--r--spec/ruby/core/integer/shared/next.rb12
-rw-r--r--spec/ruby/core/integer/sqrt_spec.rb46
-rw-r--r--spec/ruby/core/integer/to_r_spec.rb4
-rw-r--r--spec/ruby/core/integer/uminus_spec.rb2
-rw-r--r--spec/ruby/core/integer/upto_spec.rb2
-rw-r--r--spec/ruby/core/io/bytes_spec.rb64
-rw-r--r--spec/ruby/core/io/chars_spec.rb12
-rw-r--r--spec/ruby/core/io/close_on_exec_spec.rb12
-rw-r--r--spec/ruby/core/io/close_read_spec.rb2
-rw-r--r--spec/ruby/core/io/close_spec.rb30
-rw-r--r--spec/ruby/core/io/close_write_spec.rb2
-rw-r--r--spec/ruby/core/io/codepoints_spec.rb33
-rw-r--r--spec/ruby/core/io/copy_stream_spec.rb40
-rw-r--r--spec/ruby/core/io/dup_spec.rb12
-rw-r--r--spec/ruby/core/io/each_codepoint_spec.rb2
-rw-r--r--spec/ruby/core/io/eof_spec.rb26
-rw-r--r--spec/ruby/core/io/fixtures/classes.rb4
-rw-r--r--spec/ruby/core/io/fixtures/copy_in_out.rb2
-rw-r--r--spec/ruby/core/io/gets_spec.rb8
-rw-r--r--spec/ruby/core/io/initialize_spec.rb2
-rw-r--r--spec/ruby/core/io/ioctl_spec.rb4
-rw-r--r--spec/ruby/core/io/lines_spec.rb52
-rw-r--r--spec/ruby/core/io/pipe_spec.rb12
-rw-r--r--spec/ruby/core/io/popen_spec.rb4
-rw-r--r--spec/ruby/core/io/pread_spec.rb74
-rw-r--r--spec/ruby/core/io/print_spec.rb6
-rw-r--r--spec/ruby/core/io/puts_spec.rb6
-rw-r--r--spec/ruby/core/io/pwrite_spec.rb62
-rw-r--r--spec/ruby/core/io/read_nonblock_spec.rb2
-rw-r--r--spec/ruby/core/io/read_spec.rb2
-rw-r--r--spec/ruby/core/io/readlines_spec.rb58
-rw-r--r--spec/ruby/core/io/reopen_spec.rb8
-rw-r--r--spec/ruby/core/io/rewind_spec.rb2
-rw-r--r--spec/ruby/core/io/seek_spec.rb6
-rw-r--r--spec/ruby/core/io/set_encoding_by_bom_spec.rb57
-rw-r--r--spec/ruby/core/io/shared/each.rb4
-rw-r--r--spec/ruby/core/io/shared/new.rb54
-rw-r--r--spec/ruby/core/io/shared/pos.rb4
-rw-r--r--spec/ruby/core/io/shared/readlines.rb16
-rw-r--r--spec/ruby/core/io/sysopen_spec.rb4
-rw-r--r--spec/ruby/core/io/ungetbyte_spec.rb8
-rw-r--r--spec/ruby/core/io/ungetc_spec.rb25
-rw-r--r--spec/ruby/core/io/write_nonblock_spec.rb2
-rw-r--r--spec/ruby/core/io/write_spec.rb12
-rw-r--r--spec/ruby/core/kernel/Float_spec.rb10
-rw-r--r--spec/ruby/core/kernel/Integer_spec.rb14
-rw-r--r--spec/ruby/core/kernel/__dir___spec.rb23
-rw-r--r--spec/ruby/core/kernel/at_exit_spec.rb31
-rw-r--r--spec/ruby/core/kernel/autoload_spec.rb4
-rw-r--r--spec/ruby/core/kernel/backtick_spec.rb28
-rw-r--r--spec/ruby/core/kernel/caller_locations_spec.rb50
-rw-r--r--spec/ruby/core/kernel/caller_spec.rb22
-rw-r--r--spec/ruby/core/kernel/class_spec.rb2
-rw-r--r--spec/ruby/core/kernel/clone_spec.rb20
-rw-r--r--spec/ruby/core/kernel/dup_spec.rb2
-rw-r--r--spec/ruby/core/kernel/eval_spec.rb68
-rw-r--r--spec/ruby/core/kernel/extend_spec.rb4
-rw-r--r--spec/ruby/core/kernel/fixtures/__dir__.rb2
-rw-r--r--spec/ruby/core/kernel/fixtures/at_exit.rb3
-rw-r--r--spec/ruby/core/kernel/fixtures/classes.rb4
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_core_method.rb14
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_require.rb1
-rw-r--r--spec/ruby/core/kernel/fixtures/warn_require_caller.rb2
-rw-r--r--spec/ruby/core/kernel/freeze_spec.rb32
-rw-r--r--spec/ruby/core/kernel/frozen_spec.rb40
-rw-r--r--spec/ruby/core/kernel/initialize_copy_spec.rb29
-rw-r--r--spec/ruby/core/kernel/instance_of_spec.rb2
-rw-r--r--spec/ruby/core/kernel/instance_variable_get_spec.rb2
-rw-r--r--spec/ruby/core/kernel/instance_variable_set_spec.rb10
-rw-r--r--spec/ruby/core/kernel/instance_variables_spec.rb4
-rw-r--r--spec/ruby/core/kernel/iterator_spec.rb14
-rw-r--r--spec/ruby/core/kernel/lambda_spec.rb20
-rw-r--r--spec/ruby/core/kernel/match_spec.rb2
-rw-r--r--spec/ruby/core/kernel/p_spec.rb8
-rw-r--r--spec/ruby/core/kernel/pp_spec.rb12
-rw-r--r--spec/ruby/core/kernel/printf_spec.rb17
-rw-r--r--spec/ruby/core/kernel/proc_spec.rb30
-rw-r--r--spec/ruby/core/kernel/raise_spec.rb21
-rw-r--r--spec/ruby/core/kernel/require_relative_spec.rb10
-rw-r--r--spec/ruby/core/kernel/respond_to_spec.rb3
-rw-r--r--spec/ruby/core/kernel/shared/dup_clone.rb34
-rw-r--r--spec/ruby/core/kernel/shared/lambda.rb4
-rw-r--r--spec/ruby/core/kernel/shared/require.rb107
-rw-r--r--spec/ruby/core/kernel/shared/sprintf.rb872
-rw-r--r--spec/ruby/core/kernel/shared/sprintf_encoding.rb18
-rw-r--r--spec/ruby/core/kernel/singleton_class_spec.rb2
-rw-r--r--spec/ruby/core/kernel/sleep_spec.rb2
-rw-r--r--spec/ruby/core/kernel/srand_spec.rb6
-rw-r--r--spec/ruby/core/kernel/system_spec.rb8
-rw-r--r--spec/ruby/core/kernel/taint_spec.rb29
-rw-r--r--spec/ruby/core/kernel/tainted_spec.rb21
-rw-r--r--spec/ruby/core/kernel/trust_spec.rb22
-rw-r--r--spec/ruby/core/kernel/untaint_spec.rb22
-rw-r--r--spec/ruby/core/kernel/untrust_spec.rb21
-rw-r--r--spec/ruby/core/kernel/untrusted_spec.rb26
-rw-r--r--spec/ruby/core/kernel/warn_spec.rb189
-rw-r--r--spec/ruby/core/kernel/yield_self_spec.rb6
-rw-r--r--spec/ruby/core/main/fixtures/classes.rb8
-rw-r--r--spec/ruby/core/main/private_spec.rb31
-rw-r--r--spec/ruby/core/main/public_spec.rb27
-rw-r--r--spec/ruby/core/marshal/dump_spec.rb37
-rw-r--r--spec/ruby/core/marshal/fixtures/marshal_data.rb60
-rw-r--r--spec/ruby/core/marshal/shared/load.rb101
-rw-r--r--spec/ruby/core/matchdata/string_spec.rb4
-rw-r--r--spec/ruby/core/math/tan_spec.rb4
-rw-r--r--spec/ruby/core/method/case_compare_spec.rb6
-rw-r--r--spec/ruby/core/method/compose_spec.rb5
-rw-r--r--spec/ruby/core/method/fixtures/classes.rb6
-rw-r--r--spec/ruby/core/method/shared/to_s.rb49
-rw-r--r--spec/ruby/core/method/source_location_spec.rb22
-rw-r--r--spec/ruby/core/module/alias_method_spec.rb40
-rw-r--r--spec/ruby/core/module/append_features_spec.rb4
-rw-r--r--spec/ruby/core/module/attr_accessor_spec.rb33
-rw-r--r--spec/ruby/core/module/attr_reader_spec.rb23
-rw-r--r--spec/ruby/core/module/attr_spec.rb27
-rw-r--r--spec/ruby/core/module/attr_writer_spec.rb23
-rw-r--r--spec/ruby/core/module/autoload_spec.rb47
-rw-r--r--spec/ruby/core/module/class_variable_defined_spec.rb2
-rw-r--r--spec/ruby/core/module/class_variable_get_spec.rb2
-rw-r--r--spec/ruby/core/module/class_variable_set_spec.rb8
-rw-r--r--spec/ruby/core/module/const_set_spec.rb22
-rw-r--r--spec/ruby/core/module/const_source_location_spec.rb220
-rw-r--r--spec/ruby/core/module/constants_spec.rb14
-rw-r--r--spec/ruby/core/module/define_method_spec.rb15
-rw-r--r--spec/ruby/core/module/deprecate_constant_spec.rb10
-rw-r--r--spec/ruby/core/module/fixtures/autoload_during_require_current_file.rb5
-rw-r--r--spec/ruby/core/module/fixtures/autoload_location.rb3
-rw-r--r--spec/ruby/core/module/fixtures/autoload_required_directly_no_constant.rb2
-rw-r--r--spec/ruby/core/module/fixtures/refine.rb12
-rw-r--r--spec/ruby/core/module/included_spec.rb2
-rw-r--r--spec/ruby/core/module/method_added_spec.rb21
-rw-r--r--spec/ruby/core/module/method_defined_spec.rb2
-rw-r--r--spec/ruby/core/module/name_spec.rb26
-rw-r--r--spec/ruby/core/module/prepend_spec.rb39
-rw-r--r--spec/ruby/core/module/private_method_defined_spec.rb2
-rw-r--r--spec/ruby/core/module/protected_method_defined_spec.rb2
-rw-r--r--spec/ruby/core/module/public_method_defined_spec.rb2
-rw-r--r--spec/ruby/core/module/refine_spec.rb474
-rw-r--r--spec/ruby/core/module/remove_method_spec.rb19
-rw-r--r--spec/ruby/core/module/shared/class_eval.rb44
-rw-r--r--spec/ruby/core/module/shared/set_visibility.rb34
-rw-r--r--spec/ruby/core/module/singleton_class_spec.rb10
-rw-r--r--spec/ruby/core/module/undef_method_spec.rb19
-rw-r--r--spec/ruby/core/module/using_spec.rb90
-rw-r--r--spec/ruby/core/mutex/owned_spec.rb12
-rw-r--r--spec/ruby/core/mutex/sleep_spec.rb18
-rw-r--r--spec/ruby/core/mutex/unlock_spec.rb2
-rw-r--r--spec/ruby/core/nil/case_compare_spec.rb13
-rw-r--r--spec/ruby/core/nil/match_spec.rb4
-rw-r--r--spec/ruby/core/nil/nil_spec.rb2
-rw-r--r--spec/ruby/core/nil/to_i_spec.rb2
-rw-r--r--spec/ruby/core/nil/to_s_spec.rb2
-rw-r--r--spec/ruby/core/numeric/clone_spec.rb25
-rw-r--r--spec/ruby/core/numeric/denominator_spec.rb2
-rw-r--r--spec/ruby/core/numeric/dup_spec.rb16
-rw-r--r--spec/ruby/core/numeric/integer_spec.rb2
-rw-r--r--spec/ruby/core/numeric/negative_spec.rb4
-rw-r--r--spec/ruby/core/numeric/positive_spec.rb4
-rw-r--r--spec/ruby/core/numeric/quo_spec.rb2
-rw-r--r--spec/ruby/core/numeric/real_spec.rb4
-rw-r--r--spec/ruby/core/numeric/shared/imag.rb2
-rw-r--r--spec/ruby/core/numeric/shared/rect.rb2
-rw-r--r--spec/ruby/core/numeric/shared/step.rb86
-rw-r--r--spec/ruby/core/numeric/step_spec.rb90
-rw-r--r--spec/ruby/core/numeric/zero_spec.rb4
-rw-r--r--spec/ruby/core/objectspace/_id2ref_spec.rb2
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb128
-rw-r--r--spec/ruby/core/objectspace/weakmap/each_key_spec.rb11
-rw-r--r--spec/ruby/core/objectspace/weakmap/each_pair_spec.rb11
-rw-r--r--spec/ruby/core/objectspace/weakmap/each_spec.rb11
-rw-r--r--spec/ruby/core/objectspace/weakmap/each_value_spec.rb11
-rw-r--r--spec/ruby/core/objectspace/weakmap/element_reference_spec.rb24
-rw-r--r--spec/ruby/core/objectspace/weakmap/element_set_spec.rb61
-rw-r--r--spec/ruby/core/objectspace/weakmap/include_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/inspect_spec.rb25
-rw-r--r--spec/ruby/core/objectspace/weakmap/key_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/keys_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/length_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/member_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/each.rb10
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/include.rb34
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/members.rb14
-rw-r--r--spec/ruby/core/objectspace/weakmap/shared/size.rb14
-rw-r--r--spec/ruby/core/objectspace/weakmap/size_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap/values_spec.rb6
-rw-r--r--spec/ruby/core/objectspace/weakmap_spec.rb12
-rw-r--r--spec/ruby/core/proc/compose_spec.rb20
-rw-r--r--spec/ruby/core/proc/eql_spec.rb8
-rw-r--r--spec/ruby/core/proc/equal_value_spec.rb8
-rw-r--r--spec/ruby/core/proc/fixtures/source_location.rb2
-rw-r--r--spec/ruby/core/proc/hash_spec.rb2
-rw-r--r--spec/ruby/core/proc/lambda_spec.rb4
-rw-r--r--spec/ruby/core/proc/new_spec.rb22
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb4
-rw-r--r--spec/ruby/core/proc/shared/call_arguments.rb2
-rw-r--r--spec/ruby/core/proc/shared/equal.rb14
-rw-r--r--spec/ruby/core/proc/shared/to_s.rb11
-rw-r--r--spec/ruby/core/proc/source_location_spec.rb10
-rw-r--r--spec/ruby/core/process/euid_spec.rb2
-rw-r--r--spec/ruby/core/process/exec_spec.rb20
-rw-r--r--spec/ruby/core/process/getpriority_spec.rb8
-rw-r--r--spec/ruby/core/process/groups_spec.rb4
-rw-r--r--spec/ruby/core/process/kill_spec.rb2
-rw-r--r--spec/ruby/core/process/last_status_spec.rb26
-rw-r--r--spec/ruby/core/process/maxgroups_spec.rb2
-rw-r--r--spec/ruby/core/process/pid_spec.rb2
-rw-r--r--spec/ruby/core/process/spawn_spec.rb47
-rw-r--r--spec/ruby/core/process/times_spec.rb25
-rw-r--r--spec/ruby/core/process/wait_spec.rb3
-rw-r--r--spec/ruby/core/random/default_spec.rb35
-rw-r--r--spec/ruby/core/random/new_seed_spec.rb4
-rw-r--r--spec/ruby/core/random/new_spec.rb2
-rw-r--r--spec/ruby/core/random/rand_spec.rb20
-rw-r--r--spec/ruby/core/random/raw_seed_spec.rb7
-rw-r--r--spec/ruby/core/random/urandom_spec.rb9
-rw-r--r--spec/ruby/core/range/bsearch_spec.rb200
-rw-r--r--spec/ruby/core/range/case_compare_spec.rb5
-rw-r--r--spec/ruby/core/range/cover_spec.rb1
-rw-r--r--spec/ruby/core/range/dup_spec.rb4
-rw-r--r--spec/ruby/core/range/each_spec.rb22
-rw-r--r--spec/ruby/core/range/equal_value_spec.rb6
-rw-r--r--spec/ruby/core/range/exclude_end_spec.rb20
-rw-r--r--spec/ruby/core/range/hash_spec.rb10
-rw-r--r--spec/ruby/core/range/initialize_spec.rb15
-rw-r--r--spec/ruby/core/range/inspect_spec.rb7
-rw-r--r--spec/ruby/core/range/last_spec.rb6
-rw-r--r--spec/ruby/core/range/max_spec.rb6
-rw-r--r--spec/ruby/core/range/min_spec.rb7
-rw-r--r--spec/ruby/core/range/minmax_spec.rb170
-rw-r--r--spec/ruby/core/range/new_spec.rb12
-rw-r--r--spec/ruby/core/range/shared/cover.rb2
-rw-r--r--spec/ruby/core/range/shared/cover_and_include.rb7
-rw-r--r--spec/ruby/core/range/shared/equal_value.rb8
-rw-r--r--spec/ruby/core/range/size_spec.rb7
-rw-r--r--spec/ruby/core/range/step_spec.rb137
-rw-r--r--spec/ruby/core/range/to_a_spec.rb6
-rw-r--r--spec/ruby/core/range/to_s_spec.rb7
-rw-r--r--spec/ruby/core/rational/comparison_spec.rb2
-rw-r--r--spec/ruby/core/regexp/casefold_spec.rb4
-rw-r--r--spec/ruby/core/regexp/initialize_spec.rb12
-rw-r--r--spec/ruby/core/regexp/last_match_spec.rb2
-rw-r--r--spec/ruby/core/regexp/new_spec.rb2
-rw-r--r--spec/ruby/core/regexp/options_spec.rb6
-rw-r--r--spec/ruby/core/regexp/shared/new.rb6
-rw-r--r--spec/ruby/core/regexp/union_spec.rb10
-rw-r--r--spec/ruby/core/signal/trap_spec.rb2
-rw-r--r--spec/ruby/core/string/bytes_spec.rb6
-rw-r--r--spec/ruby/core/string/capitalize_spec.rb41
-rw-r--r--spec/ruby/core/string/casecmp_spec.rb24
-rw-r--r--spec/ruby/core/string/center_spec.rb35
-rw-r--r--spec/ruby/core/string/chomp_spec.rb41
-rw-r--r--spec/ruby/core/string/chop_spec.rb28
-rw-r--r--spec/ruby/core/string/clear_spec.rb6
-rw-r--r--spec/ruby/core/string/crypt_spec.rb16
-rw-r--r--spec/ruby/core/string/delete_prefix_spec.rb123
-rw-r--r--spec/ruby/core/string/delete_spec.rb24
-rw-r--r--spec/ruby/core/string/delete_suffix_spec.rb123
-rw-r--r--spec/ruby/core/string/downcase_spec.rb36
-rw-r--r--spec/ruby/core/string/dump_spec.rb22
-rw-r--r--spec/ruby/core/string/each_grapheme_cluster_spec.rb10
-rw-r--r--spec/ruby/core/string/element_set_spec.rb22
-rw-r--r--spec/ruby/core/string/empty_spec.rb10
-rw-r--r--spec/ruby/core/string/encode_spec.rb39
-rw-r--r--spec/ruby/core/string/end_with_spec.rb52
-rw-r--r--spec/ruby/core/string/fixtures/classes.rb11
-rw-r--r--spec/ruby/core/string/force_encoding_spec.rb4
-rw-r--r--spec/ruby/core/string/grapheme_clusters_spec.rb14
-rw-r--r--spec/ruby/core/string/gsub_spec.rb94
-rw-r--r--spec/ruby/core/string/index_spec.rb2
-rw-r--r--spec/ruby/core/string/insert_spec.rb10
-rw-r--r--spec/ruby/core/string/inspect_spec.rb12
-rw-r--r--spec/ruby/core/string/ljust_spec.rb35
-rw-r--r--spec/ruby/core/string/lstrip_spec.rb34
-rw-r--r--spec/ruby/core/string/match_spec.rb2
-rw-r--r--spec/ruby/core/string/modulo_spec.rb43
-rw-r--r--spec/ruby/core/string/ord_spec.rb4
-rw-r--r--spec/ruby/core/string/percent_spec.rb13
-rw-r--r--spec/ruby/core/string/prepend_spec.rb6
-rw-r--r--spec/ruby/core/string/reverse_spec.rb14
-rw-r--r--spec/ruby/core/string/rindex_spec.rb2
-rw-r--r--spec/ruby/core/string/rjust_spec.rb35
-rw-r--r--spec/ruby/core/string/rstrip_spec.rb16
-rw-r--r--spec/ruby/core/string/setbyte_spec.rb4
-rw-r--r--spec/ruby/core/string/shared/chars.rb4
-rw-r--r--spec/ruby/core/string/shared/codepoints.rb4
-rw-r--r--spec/ruby/core/string/shared/concat.rb20
-rw-r--r--spec/ruby/core/string/shared/each_line.rb56
-rw-r--r--spec/ruby/core/string/shared/length.rb13
-rw-r--r--spec/ruby/core/string/shared/replace.rb16
-rw-r--r--spec/ruby/core/string/shared/slice.rb160
-rw-r--r--spec/ruby/core/string/shared/succ.rb26
-rw-r--r--spec/ruby/core/string/shared/to_s.rb4
-rw-r--r--spec/ruby/core/string/shared/to_sym.rb2
-rw-r--r--spec/ruby/core/string/slice_spec.rb164
-rw-r--r--spec/ruby/core/string/split_spec.rb210
-rw-r--r--spec/ruby/core/string/squeeze_spec.rb26
-rw-r--r--spec/ruby/core/string/start_with_spec.rb72
-rw-r--r--spec/ruby/core/string/strip_spec.rb38
-rw-r--r--spec/ruby/core/string/sub_spec.rb69
-rw-r--r--spec/ruby/core/string/swapcase_spec.rb41
-rw-r--r--spec/ruby/core/string/to_i_spec.rb18
-rw-r--r--spec/ruby/core/string/tr_s_spec.rb26
-rw-r--r--spec/ruby/core/string/tr_spec.rb26
-rw-r--r--spec/ruby/core/string/uminus_spec.rb33
-rw-r--r--spec/ruby/core/string/undump_spec.rb834
-rw-r--r--spec/ruby/core/string/unicode_normalized_spec.rb8
-rw-r--r--spec/ruby/core/string/unpack/m_spec.rb14
-rw-r--r--spec/ruby/core/string/unpack/w_spec.rb10
-rw-r--r--spec/ruby/core/string/upcase_spec.rb42
-rw-r--r--spec/ruby/core/string/uplus_spec.rb2
-rw-r--r--spec/ruby/core/string/valid_encoding_spec.rb10
-rw-r--r--spec/ruby/core/struct/deconstruct_keys_spec.rb70
-rw-r--r--spec/ruby/core/struct/deconstruct_spec.rb12
-rw-r--r--spec/ruby/core/struct/hash_spec.rb18
-rw-r--r--spec/ruby/core/struct/new_spec.rb114
-rw-r--r--spec/ruby/core/symbol/all_symbols_spec.rb11
-rw-r--r--spec/ruby/core/symbol/casecmp_spec.rb2
-rw-r--r--spec/ruby/core/symbol/comparison_spec.rb2
-rw-r--r--spec/ruby/core/symbol/end_with_spec.rb10
-rw-r--r--spec/ruby/core/symbol/match_spec.rb17
-rw-r--r--spec/ruby/core/symbol/start_with_spec.rb10
-rw-r--r--spec/ruby/core/symbol/to_proc_spec.rb45
-rw-r--r--spec/ruby/core/systemexit/success_spec.rb4
-rw-r--r--spec/ruby/core/thread/alive_spec.rb20
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb64
-rw-r--r--spec/ruby/core/thread/backtrace/location/base_label_spec.rb27
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/absolute_path_main.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/fixtures/path.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/location/lineno_spec.rb10
-rw-r--r--spec/ruby/core/thread/backtrace/location/path_spec.rb35
-rw-r--r--spec/ruby/core/thread/backtrace_locations_spec.rb42
-rw-r--r--spec/ruby/core/thread/backtrace_spec.rb34
-rw-r--r--spec/ruby/core/thread/element_set_spec.rb4
-rw-r--r--spec/ruby/core/thread/exclusive_spec.rb66
-rw-r--r--spec/ruby/core/thread/fetch_spec.rb54
-rw-r--r--spec/ruby/core/thread/join_spec.rb5
-rw-r--r--spec/ruby/core/thread/list_spec.rb4
-rw-r--r--spec/ruby/core/thread/new_spec.rb12
-rw-r--r--spec/ruby/core/thread/raise_spec.rb2
-rw-r--r--spec/ruby/core/thread/report_on_exception_spec.rb24
-rw-r--r--spec/ruby/core/thread/shared/to_s.rb6
-rw-r--r--spec/ruby/core/thread/stop_spec.rb20
-rw-r--r--spec/ruby/core/thread/to_s_spec.rb6
-rw-r--r--spec/ruby/core/time/_dump_spec.rb4
-rw-r--r--spec/ruby/core/time/at_spec.rb90
-rw-r--r--spec/ruby/core/time/ceil_spec.rb7
-rw-r--r--spec/ruby/core/time/dup_spec.rb4
-rw-r--r--spec/ruby/core/time/floor_spec.rb7
-rw-r--r--spec/ruby/core/time/friday_spec.rb4
-rw-r--r--spec/ruby/core/time/gmt_spec.rb4
-rw-r--r--spec/ruby/core/time/hash_spec.rb4
-rw-r--r--spec/ruby/core/time/inspect_spec.rb15
-rw-r--r--spec/ruby/core/time/minus_spec.rb10
-rw-r--r--spec/ruby/core/time/monday_spec.rb4
-rw-r--r--spec/ruby/core/time/new_spec.rb6
-rw-r--r--spec/ruby/core/time/plus_spec.rb10
-rw-r--r--spec/ruby/core/time/saturday_spec.rb4
-rw-r--r--spec/ruby/core/time/shared/local.rb2
-rw-r--r--spec/ruby/core/time/shared/now.rb22
-rw-r--r--spec/ruby/core/time/shared/to_i.rb7
-rw-r--r--spec/ruby/core/time/subsec_spec.rb2
-rw-r--r--spec/ruby/core/time/succ_spec.rb56
-rw-r--r--spec/ruby/core/time/sunday_spec.rb4
-rw-r--r--spec/ruby/core/time/thursday_spec.rb4
-rw-r--r--spec/ruby/core/time/tuesday_spec.rb4
-rw-r--r--spec/ruby/core/time/utc_spec.rb2
-rw-r--r--spec/ruby/core/time/wednesday_spec.rb4
-rw-r--r--spec/ruby/core/tracepoint/binding_spec.rb2
-rw-r--r--spec/ruby/core/tracepoint/callee_id_spec.rb1
-rw-r--r--spec/ruby/core/tracepoint/defined_class_spec.rb1
-rw-r--r--spec/ruby/core/tracepoint/disable_spec.rb9
-rw-r--r--spec/ruby/core/tracepoint/enable_spec.rb149
-rw-r--r--spec/ruby/core/tracepoint/enabled_spec.rb5
-rw-r--r--spec/ruby/core/tracepoint/eval_script_spec.rb1
-rw-r--r--spec/ruby/core/tracepoint/event_spec.rb1
-rw-r--r--spec/ruby/core/tracepoint/fixtures/classes.rb6
-rw-r--r--spec/ruby/core/tracepoint/inspect_spec.rb113
-rw-r--r--spec/ruby/core/tracepoint/lineno_spec.rb14
-rw-r--r--spec/ruby/core/tracepoint/method_id_spec.rb10
-rw-r--r--spec/ruby/core/tracepoint/new_spec.rb21
-rw-r--r--spec/ruby/core/tracepoint/parameters_spec.rb11
-rw-r--r--spec/ruby/core/tracepoint/path_spec.rb16
-rw-r--r--spec/ruby/core/tracepoint/raised_exception_spec.rb6
-rw-r--r--spec/ruby/core/tracepoint/return_value_spec.rb6
-rw-r--r--spec/ruby/core/tracepoint/self_spec.rb10
-rw-r--r--spec/ruby/core/tracepoint/trace_spec.rb3
-rw-r--r--spec/ruby/core/true/case_compare_spec.rb13
-rw-r--r--spec/ruby/core/true/to_s_spec.rb2
-rw-r--r--spec/ruby/core/unboundmethod/shared/to_s.rb9
-rw-r--r--spec/ruby/core/unboundmethod/source_location_spec.rb4
-rw-r--r--spec/ruby/core/warning/element_reference_spec.rb14
-rw-r--r--spec/ruby/core/warning/element_set_spec.rb31
-rw-r--r--spec/ruby/core/warning/warn_spec.rb27
-rw-r--r--spec/ruby/default.mspec1
-rw-r--r--spec/ruby/fixtures/code_loading.rb15
-rw-r--r--spec/ruby/fixtures/constants.rb18
-rw-r--r--spec/ruby/language/BEGIN_spec.rb5
-rw-r--r--spec/ruby/language/END_spec.rb15
-rw-r--r--spec/ruby/language/README2
-rw-r--r--spec/ruby/language/alias_spec.rb7
-rw-r--r--spec/ruby/language/block_spec.rb199
-rw-r--r--spec/ruby/language/break_spec.rb18
-rw-r--r--spec/ruby/language/case_spec.rb9
-rw-r--r--spec/ruby/language/class_spec.rb18
-rw-r--r--spec/ruby/language/comment_spec.rb15
-rw-r--r--spec/ruby/language/constants_spec.rb44
-rw-r--r--spec/ruby/language/def_spec.rb47
-rw-r--r--spec/ruby/language/defined_spec.rb44
-rw-r--r--spec/ruby/language/delegation_spec.rb41
-rw-r--r--spec/ruby/language/ensure_spec.rb104
-rw-r--r--spec/ruby/language/fixtures/delegation.rb11
-rw-r--r--spec/ruby/language/fixtures/rescue_captures.rb107
-rw-r--r--spec/ruby/language/fixtures/squiggly_heredoc.rb24
-rw-r--r--spec/ruby/language/fixtures/super.rb46
-rw-r--r--spec/ruby/language/hash_spec.rb8
-rw-r--r--spec/ruby/language/heredoc_spec.rb23
-rw-r--r--spec/ruby/language/lambda_spec.rb83
-rw-r--r--spec/ruby/language/method_spec.rb611
-rw-r--r--spec/ruby/language/module_spec.rb20
-rw-r--r--spec/ruby/language/numbered_parameters_spec.rb106
-rw-r--r--spec/ruby/language/numbers_spec.rb4
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb1035
-rw-r--r--spec/ruby/language/predefined_spec.rb112
-rw-r--r--spec/ruby/language/range_spec.rb7
-rw-r--r--spec/ruby/language/regexp/character_classes_spec.rb6
-rw-r--r--spec/ruby/language/regexp/encoding_spec.rb12
-rw-r--r--spec/ruby/language/regexp_spec.rb12
-rw-r--r--spec/ruby/language/rescue_spec.rb70
-rw-r--r--spec/ruby/language/return_spec.rb380
-rw-r--r--spec/ruby/language/safe_spec.rb14
-rw-r--r--spec/ruby/language/send_spec.rb36
-rw-r--r--spec/ruby/language/singleton_class_spec.rb21
-rw-r--r--spec/ruby/language/string_spec.rb48
-rw-r--r--spec/ruby/language/super_spec.rb46
-rw-r--r--spec/ruby/language/variables_spec.rb39
-rw-r--r--spec/ruby/library/English/English_spec.rb8
-rw-r--r--spec/ruby/library/English/alias_spec.rb14
-rw-r--r--spec/ruby/library/bigdecimal/BigDecimal_spec.rb117
-rw-r--r--spec/ruby/library/bigdecimal/abs_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/add_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/comparison_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/constants_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/div_spec.rb16
-rw-r--r--spec/ruby/library/bigdecimal/divmod_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/exponent_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/finite_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/fix_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/frac_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/gt_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/gte_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/lt_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/lte_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/minus_spec.rb18
-rw-r--r--spec/ruby/library/bigdecimal/mode_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/nan_spec.rb22
-rw-r--r--spec/ruby/library/bigdecimal/plus_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/precs_spec.rb68
-rw-r--r--spec/ruby/library/bigdecimal/quo_spec.rb4
-rw-r--r--spec/ruby/library/bigdecimal/remainder_spec.rb38
-rw-r--r--spec/ruby/library/bigdecimal/shared/clone.rb17
-rw-r--r--spec/ruby/library/bigdecimal/shared/modulo.rb28
-rw-r--r--spec/ruby/library/bigdecimal/shared/mult.rb20
-rw-r--r--spec/ruby/library/bigdecimal/shared/power.rb4
-rw-r--r--spec/ruby/library/bigdecimal/shared/quo.rb10
-rw-r--r--spec/ruby/library/bigdecimal/shared/to_int.rb2
-rw-r--r--spec/ruby/library/bigdecimal/sub_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/to_f_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/to_s_spec.rb17
-rw-r--r--spec/ruby/library/bigdecimal/truncate_spec.rb6
-rw-r--r--spec/ruby/library/bigdecimal/uminus_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/zero_spec.rb26
-rw-r--r--spec/ruby/library/cgi/cookie/name_spec.rb12
-rw-r--r--spec/ruby/library/cgi/cookie/parse_spec.rb10
-rw-r--r--spec/ruby/library/cgi/cookie/to_s_spec.rb13
-rw-r--r--spec/ruby/library/cgi/escapeHTML_spec.rb4
-rw-r--r--spec/ruby/library/cgi/escape_spec.rb16
-rw-r--r--spec/ruby/library/cgi/unescapeHTML_spec.rb5
-rw-r--r--spec/ruby/library/cgi/unescape_spec.rb4
-rw-r--r--spec/ruby/library/conditionvariable/broadcast_spec.rb29
-rw-r--r--spec/ruby/library/conditionvariable/signal_spec.rb33
-rw-r--r--spec/ruby/library/conditionvariable/wait_spec.rb117
-rw-r--r--spec/ruby/library/coverage/fixtures/eval_code.rb11
-rw-r--r--spec/ruby/library/coverage/result_spec.rb14
-rw-r--r--spec/ruby/library/csv/liberal_parsing_spec.rb6
-rw-r--r--spec/ruby/library/date/constants_spec.rb4
-rw-r--r--spec/ruby/library/date/gregorian_spec.rb2
-rw-r--r--spec/ruby/library/date/infinity_spec.rb14
-rw-r--r--spec/ruby/library/date/julian_spec.rb4
-rw-r--r--spec/ruby/library/date/parse_spec.rb17
-rw-r--r--spec/ruby/library/date/shared/civil.rb8
-rw-r--r--spec/ruby/library/delegate/delegator/eql_spec.rb55
-rw-r--r--spec/ruby/library/digest/bubblebabble_spec.rb2
-rw-r--r--spec/ruby/library/digest/hexencode_spec.rb2
-rw-r--r--spec/ruby/library/digest/instance/append_spec.rb7
-rw-r--r--spec/ruby/library/digest/instance/new_spec.rb19
-rw-r--r--spec/ruby/library/digest/instance/shared/update.rb8
-rw-r--r--spec/ruby/library/digest/instance/update_spec.rb7
-rw-r--r--spec/ruby/library/digest/md5/shared/constants.rb1
-rw-r--r--spec/ruby/library/digest/sha1/shared/constants.rb3
-rw-r--r--spec/ruby/library/digest/sha2/hexdigest_spec.rb32
-rw-r--r--spec/ruby/library/digest/sha256/file_spec.rb4
-rw-r--r--spec/ruby/library/digest/sha256/shared/constants.rb1
-rw-r--r--spec/ruby/library/digest/sha384/shared/constants.rb1
-rw-r--r--spec/ruby/library/digest/sha512/shared/constants.rb1
-rw-r--r--spec/ruby/library/erb/util/shared/url_encode.rb16
-rw-r--r--spec/ruby/library/etc/confstr_spec.rb2
-rw-r--r--spec/ruby/library/etc/getgrgid_spec.rb7
-rw-r--r--spec/ruby/library/etc/getgrnam_spec.rb2
-rw-r--r--spec/ruby/library/etc/group_spec.rb2
-rw-r--r--spec/ruby/library/etc/struct_group_spec.rb2
-rw-r--r--spec/ruby/library/etc/struct_passwd_spec.rb2
-rw-r--r--spec/ruby/library/fiber/current_spec.rb16
-rw-r--r--spec/ruby/library/fiber/resume_spec.rb21
-rw-r--r--spec/ruby/library/fiber/transfer_spec.rb56
-rw-r--r--spec/ruby/library/getoptlong/shared/get.rb10
-rw-r--r--spec/ruby/library/getoptlong/terminated_spec.rb6
-rw-r--r--spec/ruby/library/ipaddr/ipv4_conversion_spec.rb8
-rw-r--r--spec/ruby/library/ipaddr/new_spec.rb8
-rw-r--r--spec/ruby/library/logger/logger/debug_spec.rb4
-rw-r--r--spec/ruby/library/logger/logger/error_spec.rb4
-rw-r--r--spec/ruby/library/logger/logger/fatal_spec.rb4
-rw-r--r--spec/ruby/library/logger/logger/info_spec.rb4
-rw-r--r--spec/ruby/library/logger/logger/warn_spec.rb4
-rw-r--r--spec/ruby/library/mathn/bignum/exponent_spec.rb21
-rw-r--r--spec/ruby/library/mathn/complex/Complex_spec.rb14
-rw-r--r--spec/ruby/library/mathn/fixnum/exponent_spec.rb17
-rw-r--r--spec/ruby/library/mathn/float/exponent_spec.rb17
-rw-r--r--spec/ruby/library/mathn/integer/from_prime_division_spec.rb11
-rw-r--r--spec/ruby/library/mathn/integer/prime_division_spec.rb21
-rw-r--r--spec/ruby/library/mathn/math/fixtures/classes.rb3
-rw-r--r--spec/ruby/library/mathn/math/rsqrt_spec.rb17
-rw-r--r--spec/ruby/library/mathn/math/shared/rsqrt.rb21
-rw-r--r--spec/ruby/library/mathn/math/shared/sqrt.rb25
-rw-r--r--spec/ruby/library/mathn/math/sqrt_spec.rb17
-rw-r--r--spec/ruby/library/mathn/mathn_spec.rb13
-rw-r--r--spec/ruby/library/mathn/rational/Rational_spec.rb14
-rw-r--r--spec/ruby/library/mathn/rational/inspect_spec.rb15
-rw-r--r--spec/ruby/library/matrix/coerce_spec.rb2
-rw-r--r--spec/ruby/library/matrix/divide_spec.rb4
-rw-r--r--spec/ruby/library/matrix/hash_spec.rb4
-rw-r--r--spec/ruby/library/matrix/multiply_spec.rb4
-rw-r--r--spec/ruby/library/matrix/normal_spec.rb6
-rw-r--r--spec/ruby/library/matrix/orthogonal_spec.rb6
-rw-r--r--spec/ruby/library/matrix/unitary_spec.rb15
-rw-r--r--spec/ruby/library/matrix/zero_spec.rb10
-rw-r--r--spec/ruby/library/net/ftp/initialize_spec.rb4
-rw-r--r--spec/ruby/library/net/http/HTTPServerException_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/fixtures/http_server.rb12
-rw-r--r--spec/ruby/library/net/http/http/get2_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/get_spec.rb14
-rw-r--r--spec/ruby/library/net/http/http/head2_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/post2_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/put2_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/request_get_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/request_head_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/request_post_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/request_put_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/send_request_spec.rb2
-rw-r--r--spec/ruby/library/net/http/http/shared/request_get.rb2
-rw-r--r--spec/ruby/library/net/http/http/shared/request_head.rb2
-rw-r--r--spec/ruby/library/net/http/http/shared/request_post.rb2
-rw-r--r--spec/ruby/library/net/http/http/shared/request_put.rb2
-rw-r--r--spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb12
-rw-r--r--spec/ruby/library/objectspace/memsize_of_spec.rb4
-rw-r--r--spec/ruby/library/openssl/config/freeze_spec.rb26
-rw-r--r--spec/ruby/library/openssl/digest_spec.rb63
-rw-r--r--spec/ruby/library/openssl/hmac/digest_spec.rb2
-rw-r--r--spec/ruby/library/openssl/hmac/hexdigest_spec.rb2
-rw-r--r--spec/ruby/library/openstruct/frozen_spec.rb2
-rw-r--r--spec/ruby/library/openstruct/marshal_load_spec.rb2
-rw-r--r--spec/ruby/library/openstruct/method_missing_spec.rb29
-rw-r--r--spec/ruby/library/pathname/absolute_spec.rb8
-rw-r--r--spec/ruby/library/pathname/glob_spec.rb57
-rw-r--r--spec/ruby/library/pathname/new_spec.rb2
-rw-r--r--spec/ruby/library/pathname/pathname_spec.rb30
-rw-r--r--spec/ruby/library/pathname/relative_spec.rb8
-rw-r--r--spec/ruby/library/pathname/root_spec.rb10
-rw-r--r--spec/ruby/library/rbconfig/rbconfig_spec.rb36
-rw-r--r--spec/ruby/library/rbconfig/sizeof/limits_spec.rb58
-rw-r--r--spec/ruby/library/rbconfig/unicode_version_spec.rb6
-rw-r--r--spec/ruby/library/rexml/attribute/clone_spec.rb17
-rw-r--r--spec/ruby/library/rexml/attribute/element_spec.rb33
-rw-r--r--spec/ruby/library/rexml/attribute/equal_value_spec.rb25
-rw-r--r--spec/ruby/library/rexml/attribute/hash_spec.rb21
-rw-r--r--spec/ruby/library/rexml/attribute/initialize_spec.rb45
-rw-r--r--spec/ruby/library/rexml/attribute/inspect_spec.rb29
-rw-r--r--spec/ruby/library/rexml/attribute/namespace_spec.rb39
-rw-r--r--spec/ruby/library/rexml/attribute/node_type_spec.rb15
-rw-r--r--spec/ruby/library/rexml/attribute/prefix_spec.rb25
-rw-r--r--spec/ruby/library/rexml/attribute/remove_spec.rb31
-rw-r--r--spec/ruby/library/rexml/attribute/to_s_spec.rb21
-rw-r--r--spec/ruby/library/rexml/attribute/to_string_spec.rb21
-rw-r--r--spec/ruby/library/rexml/attribute/value_spec.rb21
-rw-r--r--spec/ruby/library/rexml/attribute/write_spec.rb35
-rw-r--r--spec/ruby/library/rexml/attribute/xpath_spec.rb27
-rw-r--r--spec/ruby/library/rexml/attributes/add_spec.rb11
-rw-r--r--spec/ruby/library/rexml/attributes/append_spec.rb11
-rw-r--r--spec/ruby/library/rexml/attributes/delete_all_spec.rb51
-rw-r--r--spec/ruby/library/rexml/attributes/delete_spec.rb43
-rw-r--r--spec/ruby/library/rexml/attributes/each_attribute_spec.rb33
-rw-r--r--spec/ruby/library/rexml/attributes/each_spec.rb37
-rw-r--r--spec/ruby/library/rexml/attributes/element_reference_spec.rb27
-rw-r--r--spec/ruby/library/rexml/attributes/element_set_spec.rb39
-rw-r--r--spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb23
-rw-r--r--spec/ruby/library/rexml/attributes/get_attribute_spec.rb45
-rw-r--r--spec/ruby/library/rexml/attributes/initialize_spec.rb27
-rw-r--r--spec/ruby/library/rexml/attributes/length_spec.rb11
-rw-r--r--spec/ruby/library/rexml/attributes/namespaces_spec.rb9
-rw-r--r--spec/ruby/library/rexml/attributes/prefixes_spec.rb37
-rw-r--r--spec/ruby/library/rexml/attributes/size_spec.rb11
-rw-r--r--spec/ruby/library/rexml/attributes/to_a_spec.rb27
-rw-r--r--spec/ruby/library/rexml/cdata/clone_spec.rb15
-rw-r--r--spec/ruby/library/rexml/cdata/initialize_spec.rb37
-rw-r--r--spec/ruby/library/rexml/cdata/to_s_spec.rb11
-rw-r--r--spec/ruby/library/rexml/cdata/value_spec.rb11
-rw-r--r--spec/ruby/library/rexml/document/add_element_spec.rb51
-rw-r--r--spec/ruby/library/rexml/document/add_spec.rb89
-rw-r--r--spec/ruby/library/rexml/document/clone_spec.rb33
-rw-r--r--spec/ruby/library/rexml/document/doctype_spec.rb23
-rw-r--r--spec/ruby/library/rexml/document/encoding_spec.rb33
-rw-r--r--spec/ruby/library/rexml/document/expanded_name_spec.rb23
-rw-r--r--spec/ruby/library/rexml/document/new_spec.rb55
-rw-r--r--spec/ruby/library/rexml/document/node_type_spec.rb11
-rw-r--r--spec/ruby/library/rexml/document/root_spec.rb17
-rw-r--r--spec/ruby/library/rexml/document/stand_alone_spec.rb31
-rw-r--r--spec/ruby/library/rexml/document/version_spec.rb21
-rw-r--r--spec/ruby/library/rexml/document/write_spec.rb57
-rw-r--r--spec/ruby/library/rexml/document/xml_decl_spec.rb23
-rw-r--r--spec/ruby/library/rexml/element/add_attribute_spec.rb65
-rw-r--r--spec/ruby/library/rexml/element/add_attributes_spec.rb35
-rw-r--r--spec/ruby/library/rexml/element/add_element_spec.rb62
-rw-r--r--spec/ruby/library/rexml/element/add_namespace_spec.rb35
-rw-r--r--spec/ruby/library/rexml/element/add_text_spec.rb37
-rw-r--r--spec/ruby/library/rexml/element/attribute_spec.rb27
-rw-r--r--spec/ruby/library/rexml/element/attributes_spec.rb27
-rw-r--r--spec/ruby/library/rexml/element/cdatas_spec.rb37
-rw-r--r--spec/ruby/library/rexml/element/clone_spec.rb47
-rw-r--r--spec/ruby/library/rexml/element/comments_spec.rb31
-rw-r--r--spec/ruby/library/rexml/element/delete_attribute_spec.rb61
-rw-r--r--spec/ruby/library/rexml/element/delete_element_spec.rb81
-rw-r--r--spec/ruby/library/rexml/element/delete_namespace_spec.rb37
-rw-r--r--spec/ruby/library/rexml/element/document_spec.rb23
-rw-r--r--spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb57
-rw-r--r--spec/ruby/library/rexml/element/each_element_with_text_spec.rb49
-rw-r--r--spec/ruby/library/rexml/element/element_reference_spec.rb29
-rw-r--r--spec/ruby/library/rexml/element/get_text_spec.rb27
-rw-r--r--spec/ruby/library/rexml/element/has_attributes_spec.rb25
-rw-r--r--spec/ruby/library/rexml/element/has_elements_spec.rb27
-rw-r--r--spec/ruby/library/rexml/element/has_text_spec.rb23
-rw-r--r--spec/ruby/library/rexml/element/inspect_spec.rb41
-rw-r--r--spec/ruby/library/rexml/element/instructions_spec.rb33
-rw-r--r--spec/ruby/library/rexml/element/namespace_spec.rb41
-rw-r--r--spec/ruby/library/rexml/element/namespaces_spec.rb51
-rw-r--r--spec/ruby/library/rexml/element/new_spec.rb55
-rw-r--r--spec/ruby/library/rexml/element/next_element_spec.rb31
-rw-r--r--spec/ruby/library/rexml/element/node_type_spec.rb11
-rw-r--r--spec/ruby/library/rexml/element/prefixes_spec.rb35
-rw-r--r--spec/ruby/library/rexml/element/previous_element_spec.rb31
-rw-r--r--spec/ruby/library/rexml/element/raw_spec.rb35
-rw-r--r--spec/ruby/library/rexml/element/root_spec.rb43
-rw-r--r--spec/ruby/library/rexml/element/text_spec.rb87
-rw-r--r--spec/ruby/library/rexml/element/texts_spec.rb23
-rw-r--r--spec/ruby/library/rexml/element/whitespace_spec.rb33
-rw-r--r--spec/ruby/library/rexml/node/each_recursive_spec.rb35
-rw-r--r--spec/ruby/library/rexml/node/find_first_recursive_spec.rb41
-rw-r--r--spec/ruby/library/rexml/node/index_in_parent_spec.rb23
-rw-r--r--spec/ruby/library/rexml/node/next_sibling_node_spec.rb33
-rw-r--r--spec/ruby/library/rexml/node/parent_spec.rb31
-rw-r--r--spec/ruby/library/rexml/node/previous_sibling_node_spec.rb33
-rw-r--r--spec/ruby/library/rexml/text/append_spec.rb15
-rw-r--r--spec/ruby/library/rexml/text/clone_spec.rb15
-rw-r--r--spec/ruby/library/rexml/text/comparison_spec.rb39
-rw-r--r--spec/ruby/library/rexml/text/empty_spec.rb17
-rw-r--r--spec/ruby/library/rexml/text/indent_text_spec.rb35
-rw-r--r--spec/ruby/library/rexml/text/inspect_spec.rb11
-rw-r--r--spec/ruby/library/rexml/text/new_spec.rb91
-rw-r--r--spec/ruby/library/rexml/text/node_type_spec.rb11
-rw-r--r--spec/ruby/library/rexml/text/normalize_spec.rb11
-rw-r--r--spec/ruby/library/rexml/text/read_with_substitution_spec.rb17
-rw-r--r--spec/ruby/library/rexml/text/to_s_spec.rb25
-rw-r--r--spec/ruby/library/rexml/text/unnormalize_spec.rb11
-rw-r--r--spec/ruby/library/rexml/text/value_spec.rb55
-rw-r--r--spec/ruby/library/rexml/text/wrap_spec.rb29
-rw-r--r--spec/ruby/library/rexml/text/write_with_substitution_spec.rb53
-rw-r--r--spec/ruby/library/ripper/lex_spec.rb23
-rw-r--r--spec/ruby/library/ripper/sexp_spec.rb13
-rw-r--r--spec/ruby/library/securerandom/random_number_spec.rb2
-rw-r--r--spec/ruby/library/set/case_compare_spec.rb12
-rw-r--r--spec/ruby/library/set/case_equality_spec.rb6
-rw-r--r--spec/ruby/library/set/compare_by_identity_spec.rb16
-rw-r--r--spec/ruby/library/set/enumerable/to_set_spec.rb10
-rw-r--r--spec/ruby/library/set/sortedset/add_spec.rb59
-rw-r--r--spec/ruby/library/set/sortedset/append_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/case_equality_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/classify_spec.rb41
-rw-r--r--spec/ruby/library/set/sortedset/clear_spec.rb25
-rw-r--r--spec/ruby/library/set/sortedset/collect_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/constructor_spec.rb21
-rw-r--r--spec/ruby/library/set/sortedset/delete_if_spec.rb57
-rw-r--r--spec/ruby/library/set/sortedset/delete_spec.rb55
-rw-r--r--spec/ruby/library/set/sortedset/difference_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/divide_spec.rb53
-rw-r--r--spec/ruby/library/set/sortedset/each_spec.rb39
-rw-r--r--spec/ruby/library/set/sortedset/empty_spec.rb15
-rw-r--r--spec/ruby/library/set/sortedset/eql_spec.rb23
-rw-r--r--spec/ruby/library/set/sortedset/equal_value_spec.rb19
-rw-r--r--spec/ruby/library/set/sortedset/exclusion_spec.rb27
-rw-r--r--spec/ruby/library/set/sortedset/filter_spec.rb13
-rw-r--r--spec/ruby/library/set/sortedset/flatten_merge_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/flatten_spec.rb67
-rw-r--r--spec/ruby/library/set/sortedset/hash_spec.rb19
-rw-r--r--spec/ruby/library/set/sortedset/include_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/initialize_spec.rb49
-rw-r--r--spec/ruby/library/set/sortedset/inspect_spec.rb15
-rw-r--r--spec/ruby/library/set/sortedset/intersection_spec.rb17
-rw-r--r--spec/ruby/library/set/sortedset/keep_if_spec.rb47
-rw-r--r--spec/ruby/library/set/sortedset/length_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/map_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/member_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/merge_spec.rb29
-rw-r--r--spec/ruby/library/set/sortedset/minus_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/plus_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb15
-rw-r--r--spec/ruby/library/set/sortedset/pretty_print_spec.rb23
-rw-r--r--spec/ruby/library/set/sortedset/proper_subset_spec.rb51
-rw-r--r--spec/ruby/library/set/sortedset/proper_superset_spec.rb51
-rw-r--r--spec/ruby/library/set/sortedset/reject_spec.rb63
-rw-r--r--spec/ruby/library/set/sortedset/replace_spec.rb25
-rw-r--r--spec/ruby/library/set/sortedset/select_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/size_spec.rb11
-rw-r--r--spec/ruby/library/set/sortedset/subset_spec.rb51
-rw-r--r--spec/ruby/library/set/sortedset/subtract_spec.rb25
-rw-r--r--spec/ruby/library/set/sortedset/superset_spec.rb51
-rw-r--r--spec/ruby/library/set/sortedset/to_a_spec.rb25
-rw-r--r--spec/ruby/library/set/sortedset/union_spec.rb17
-rw-r--r--spec/ruby/library/set/to_s_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb22
-rw-r--r--spec/ruby/library/socket/addrinfo/initialize_spec.rb50
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb8
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb10
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb12
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb6
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb10
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb10
-rw-r--r--spec/ruby/library/socket/addrinfo/listen_spec.rb2
-rw-r--r--spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb64
-rw-r--r--spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb62
-rw-r--r--spec/ruby/library/socket/constants/constants_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/gethostbyaddr_spec.rb22
-rw-r--r--spec/ruby/library/socket/socket/gethostbyname_spec.rb16
-rw-r--r--spec/ruby/library/socket/socket/listen_spec.rb6
-rw-r--r--spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/tcp_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/udp_server_sockets_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/unix_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb2
-rw-r--r--spec/ruby/library/socket/tcpserver/accept_spec.rb20
-rw-r--r--spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb16
-rw-r--r--spec/ruby/library/socket/udpsocket/inspect_spec.rb14
-rw-r--r--spec/ruby/library/socket/unixsocket/open_spec.rb2
-rw-r--r--spec/ruby/library/socket/unixsocket/shared/new.rb2
-rw-r--r--spec/ruby/library/stringio/append_spec.rb8
-rw-r--r--spec/ruby/library/stringio/binmode_spec.rb14
-rw-r--r--spec/ruby/library/stringio/bytes_spec.rb12
-rw-r--r--spec/ruby/library/stringio/chars_spec.rb12
-rw-r--r--spec/ruby/library/stringio/codepoints_spec.rb9
-rw-r--r--spec/ruby/library/stringio/each_char_spec.rb2
-rw-r--r--spec/ruby/library/stringio/each_codepoint_spec.rb2
-rw-r--r--spec/ruby/library/stringio/getpass_spec.rb11
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb5
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb22
-rw-r--r--spec/ruby/library/stringio/inspect_spec.rb19
-rw-r--r--spec/ruby/library/stringio/lines_spec.rb24
-rw-r--r--spec/ruby/library/stringio/open_spec.rb4
-rw-r--r--spec/ruby/library/stringio/print_spec.rb10
-rw-r--r--spec/ruby/library/stringio/printf_spec.rb2
-rw-r--r--spec/ruby/library/stringio/puts_spec.rb15
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb5
-rw-r--r--spec/ruby/library/stringio/readlines_spec.rb5
-rw-r--r--spec/ruby/library/stringio/reopen_spec.rb46
-rw-r--r--spec/ruby/library/stringio/shared/each.rb5
-rw-r--r--spec/ruby/library/stringio/shared/read.rb4
-rw-r--r--spec/ruby/library/stringio/shared/write.rb8
-rw-r--r--spec/ruby/library/stringscanner/append_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/concat_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/shared/peek.rb2
-rw-r--r--spec/ruby/library/syslog/close_spec.rb2
-rw-r--r--spec/ruby/library/syslog/ident_spec.rb2
-rw-r--r--spec/ruby/library/syslog/log_spec.rb2
-rw-r--r--spec/ruby/library/syslog/mask_spec.rb2
-rw-r--r--spec/ruby/library/syslog/shared/log.rb2
-rw-r--r--spec/ruby/library/timeout/timeout_spec.rb16
-rw-r--r--spec/ruby/library/weakref/weakref_alive_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/input_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/value_spec.rb2
-rw-r--r--spec/ruby/library/yaml/add_builtin_type_spec.rb2
-rw-r--r--spec/ruby/library/yaml/add_domain_type_spec.rb2
-rw-r--r--spec/ruby/library/yaml/add_private_type_spec.rb2
-rw-r--r--spec/ruby/library/yaml/add_ruby_type_spec.rb2
-rw-r--r--spec/ruby/library/yaml/detect_implicit_spec.rb2
-rw-r--r--spec/ruby/library/yaml/dump_spec.rb7
-rw-r--r--spec/ruby/library/yaml/each_node_spec.rb2
-rw-r--r--spec/ruby/library/yaml/emitter_spec.rb2
-rw-r--r--spec/ruby/library/yaml/generic_parser_spec.rb2
-rw-r--r--spec/ruby/library/yaml/load_documents_spec.rb10
-rw-r--r--spec/ruby/library/yaml/object_maker_spec.rb2
-rw-r--r--spec/ruby/library/yaml/parse_documents_spec.rb2
-rw-r--r--spec/ruby/library/yaml/parser_spec.rb2
-rw-r--r--spec/ruby/library/yaml/quick_emit_spec.rb2
-rw-r--r--spec/ruby/library/yaml/read_type_class_spec.rb2
-rw-r--r--spec/ruby/library/yaml/tagurize_spec.rb11
-rw-r--r--spec/ruby/library/yaml/transfer_spec.rb2
-rw-r--r--spec/ruby/library/yaml/try_implicit_spec.rb2
-rw-r--r--spec/ruby/library/zlib/adler32_spec.rb2
-rw-r--r--spec/ruby/library/zlib/crc32_spec.rb2
-rw-r--r--spec/ruby/library/zlib/gzipfile/close_spec.rb2
-rw-r--r--spec/ruby/library/zlib/gzipfile/closed_spec.rb4
-rw-r--r--spec/ruby/library/zlib/zstream/flush_next_out_spec.rb2
-rw-r--r--spec/ruby/optional/capi/README9
-rw-r--r--spec/ruby/optional/capi/array_spec.rb38
-rw-r--r--spec/ruby/optional/capi/basic_object_spec.rb24
-rw-r--r--spec/ruby/optional/capi/class_spec.rb66
-rw-r--r--spec/ruby/optional/capi/constants_spec.rb105
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb175
-rw-r--r--spec/ruby/optional/capi/exception_spec.rb45
-rw-r--r--spec/ruby/optional/capi/ext/array_spec.c16
-rw-r--r--spec/ruby/optional/capi/ext/basic_object_spec.c19
-rw-r--r--spec/ruby/optional/capi/ext/bignum_spec.c4
-rw-r--r--spec/ruby/optional/capi/ext/boolean_spec.c2
-rw-r--r--spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/class_spec.c26
-rw-r--r--spec/ruby/optional/capi/ext/class_under_autoload_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/constants_spec.c383
-rw-r--r--spec/ruby/optional/capi/ext/data_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/encoding_spec.c123
-rw-r--r--spec/ruby/optional/capi/ext/exception_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/float_spec.c9
-rw-r--r--spec/ruby/optional/capi/ext/gc_spec.c17
-rw-r--r--spec/ruby/optional/capi/ext/globals_spec.c13
-rw-r--r--spec/ruby/optional/capi/ext/hash_spec.c17
-rw-r--r--spec/ruby/optional/capi/ext/integer_spec.c9
-rw-r--r--spec/ruby/optional/capi/ext/io_spec.c22
-rw-r--r--spec/ruby/optional/capi/ext/kernel_spec.c31
-rw-r--r--spec/ruby/optional/capi/ext/language_spec.c42
-rw-r--r--spec/ruby/optional/capi/ext/module_under_autoload_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/numeric_spec.c7
-rw-r--r--spec/ruby/optional/capi/ext/object_spec.c45
-rw-r--r--spec/ruby/optional/capi/ext/proc_spec.c5
-rw-r--r--spec/ruby/optional/capi/ext/rbasic_spec.c94
-rw-r--r--spec/ruby/optional/capi/ext/regexp_spec.c14
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h35
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c77
-rw-r--r--spec/ruby/optional/capi/ext/struct_spec.c4
-rw-r--r--spec/ruby/optional/capi/ext/symbol_spec.c15
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c6
-rw-r--r--spec/ruby/optional/capi/ext/tracepoint_spec.c49
-rw-r--r--spec/ruby/optional/capi/ext/typed_data_spec.c66
-rw-r--r--spec/ruby/optional/capi/ext/util_spec.c19
-rw-r--r--spec/ruby/optional/capi/float_spec.rb13
-rw-r--r--spec/ruby/optional/capi/gc_spec.rb26
-rw-r--r--spec/ruby/optional/capi/globals_spec.rb29
-rw-r--r--spec/ruby/optional/capi/hash_spec.rb17
-rw-r--r--spec/ruby/optional/capi/integer_spec.rb15
-rw-r--r--spec/ruby/optional/capi/io_spec.rb10
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb125
-rw-r--r--spec/ruby/optional/capi/language_spec.rb37
-rw-r--r--spec/ruby/optional/capi/module_spec.rb14
-rw-r--r--spec/ruby/optional/capi/numeric_spec.rb51
-rw-r--r--spec/ruby/optional/capi/object_spec.rb106
-rw-r--r--spec/ruby/optional/capi/proc_spec.rb19
-rw-r--r--spec/ruby/optional/capi/rbasic_spec.rb22
-rw-r--r--spec/ruby/optional/capi/regexp_spec.rb14
-rw-r--r--spec/ruby/optional/capi/shared/rbasic.rb83
-rw-r--r--spec/ruby/optional/capi/spec_helper.rb38
-rw-r--r--spec/ruby/optional/capi/string_spec.rb95
-rw-r--r--spec/ruby/optional/capi/struct_spec.rb6
-rw-r--r--spec/ruby/optional/capi/symbol_spec.rb39
-rw-r--r--spec/ruby/optional/capi/time_spec.rb84
-rw-r--r--spec/ruby/optional/capi/tracepoint_spec.rb56
-rw-r--r--spec/ruby/optional/capi/typed_data_spec.rb17
-rw-r--r--spec/ruby/optional/capi/util_spec.rb113
-rw-r--r--spec/ruby/security/cve_2014_8080_spec.rb51
-rw-r--r--spec/ruby/security/cve_2018_8780_spec.rb20
-rw-r--r--spec/ruby/security/cve_2020_10663_spec.rb41
-rw-r--r--spec/ruby/shared/enumerable/minmax.rb24
-rw-r--r--spec/ruby/shared/enumerator/enum_for.rb7
-rw-r--r--spec/ruby/shared/fiber/resume.rb21
-rw-r--r--spec/ruby/shared/file/executable.rb2
-rw-r--r--spec/ruby/shared/file/identical.rb6
-rw-r--r--spec/ruby/shared/file/readable.rb5
-rw-r--r--spec/ruby/shared/file/world_readable.rb12
-rw-r--r--spec/ruby/shared/file/world_writable.rb12
-rw-r--r--spec/ruby/shared/file/writable.rb2
-rw-r--r--spec/ruby/shared/hash/key_error.rb28
-rw-r--r--spec/ruby/shared/io/putc.rb2
-rw-r--r--spec/ruby/shared/kernel/object_id.rb8
-rw-r--r--spec/ruby/shared/kernel/raise.rb68
-rw-r--r--spec/ruby/shared/process/exit.rb20
-rw-r--r--spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb32
-rw-r--r--spec/ruby/shared/rational/coerce.rb5
-rw-r--r--spec/ruby/shared/rational/comparison.rb30
-rw-r--r--spec/ruby/shared/rational/exponent.rb2
-rw-r--r--spec/ruby/shared/string/end_with.rb54
-rw-r--r--spec/ruby/shared/string/start_with.rb72
-rw-r--r--spec/ruby/shared/string/times.rb28
-rw-r--r--sprintf.c26
-rw-r--r--st.c262
-rw-r--r--strftime.c19
-rw-r--r--string.c1694
-rw-r--r--struct.c96
-rw-r--r--symbol.c511
-rw-r--r--symbol.h8
-rw-r--r--template/Doxyfile.tmpl45
-rw-r--r--template/GNUmakefile.in2
-rw-r--r--template/Makefile.in134
-rw-r--r--template/builtin_binary.inc.tmpl30
-rw-r--r--template/call_iseq_optimized.inc.tmpl68
-rw-r--r--template/configure-ext.mk.tmpl5
-rw-r--r--template/encdb.h.tmpl8
-rw-r--r--template/exts.mk.tmpl16
-rw-r--r--template/id.c.tmpl2
-rw-r--r--template/prelude.c.tmpl39
-rwxr-xr-xtemplate/ruby-gdb.in6
-rwxr-xr-xtemplate/ruby-lldb.in6
-rw-r--r--template/transdb.h.tmpl4
-rw-r--r--test/-ext-/array/test_to_ary_concat.rb20
-rw-r--r--test/-ext-/bug_reporter/test_bug_reporter.rb4
-rw-r--r--test/-ext-/debug/test_profile_frames.rb16
-rw-r--r--test/-ext-/funcall/test_passing_block.rb23
-rw-r--r--test/-ext-/postponed_job/test_postponed_job.rb7
-rw-r--r--test/-ext-/rational/test_rat.rb38
-rw-r--r--test/-ext-/string/test_cstr.rb8
-rw-r--r--test/-ext-/string/test_ellipsize.rb2
-rw-r--r--test/-ext-/string/test_enc_str_buf_cat.rb9
-rw-r--r--test/-ext-/string/test_fstring.rb16
-rw-r--r--test/-ext-/string/test_interned_str.rb12
-rw-r--r--test/-ext-/string/test_normalize.rb8
-rw-r--r--test/-ext-/symbol/test_inadvertent_creation.rb8
-rw-r--r--test/-ext-/test_random.rb27
-rw-r--r--test/-ext-/test_scan_args.rb121
-rw-r--r--test/-ext-/tracepoint/test_tracepoint.rb14
-rw-r--r--test/bigdecimal/test_bigdecimal.rb195
-rw-r--r--test/bigdecimal/test_bigdecimal_util.rb32
-rw-r--r--test/bigdecimal/test_ractor.rb23
-rw-r--r--test/cgi/test_cgi_cookie.rb82
-rw-r--r--test/cgi/test_cgi_core.rb4
-rw-r--r--test/cgi/test_cgi_header.rb8
-rw-r--r--test/coverage/test_coverage.rb20
-rw-r--r--test/csv/helper.rb24
-rw-r--r--test/csv/interface/test_read.rb62
-rw-r--r--test/csv/interface/test_read_write.rb67
-rw-r--r--test/csv/parse/test_general.rb6
-rw-r--r--test/csv/parse/test_skip_lines.rb13
-rw-r--r--test/csv/parse/test_strip.rb5
-rw-r--r--test/csv/test_encodings.rb22
-rw-r--r--test/csv/test_row.rb3
-rw-r--r--test/csv/test_table.rb2
-rw-r--r--test/csv/write/test_converters.rb8
-rw-r--r--test/csv/write/test_force_quotes.rb78
-rw-r--r--test/csv/write/test_general.rb16
-rw-r--r--test/date/test_date_ractor.rb27
-rw-r--r--test/did_you_mean/fixtures/book.rb2
-rw-r--r--test/did_you_mean/spell_checking/test_class_name_check.rb4
-rw-r--r--test/did_you_mean/spell_checking/test_method_name_check.rb7
-rw-r--r--test/did_you_mean/spell_checking/test_require_path_check.rb32
-rw-r--r--test/did_you_mean/test_tree_spell_checker.rb203
-rw-r--r--test/did_you_mean/test_verbose_formatter.rb2
-rw-r--r--test/did_you_mean/tree_spell/human_typo.rb34
-rw-r--r--test/digest/test_digest.rb8
-rw-r--r--test/digest/test_ractor.rb101
-rw-r--r--test/drb/drbtest.rb2
-rw-r--r--test/drb/test_drbssl.rb1
-rw-r--r--test/drb/ut_drb.rb2
-rw-r--r--test/erb/test_erb_command.rb8
-rw-r--r--test/etc/test_etc.rb28
-rw-r--r--test/fiber/http.rb53
-rw-r--r--test/fiber/scheduler.rb210
-rw-r--r--test/fiber/test_backtrace.rb22
-rw-r--r--test/fiber/test_enumerator.rb51
-rw-r--r--test/fiber/test_io.rb100
-rw-r--r--test/fiber/test_mutex.rb220
-rw-r--r--test/fiber/test_process.rb51
-rw-r--r--test/fiber/test_ractor.rb23
-rw-r--r--test/fiber/test_scheduler.rb90
-rw-r--r--test/fiber/test_sleep.rb71
-rw-r--r--test/fiber/test_thread.rb108
-rw-r--r--test/fiddle/helper.rb36
-rw-r--r--test/fiddle/test_c_struct_entry.rb130
-rw-r--r--test/fiddle/test_c_union_entity.rb15
-rw-r--r--test/fiddle/test_closure.rb25
-rw-r--r--test/fiddle/test_cparser.rb169
-rw-r--r--test/fiddle/test_func.rb55
-rw-r--r--test/fiddle/test_function.rb32
-rw-r--r--test/fiddle/test_import.rb372
-rw-r--r--test/fiddle/test_memory_view.rb115
-rw-r--r--test/fiddle/test_pinned.rb27
-rw-r--r--test/fiddle/test_pointer.rb95
-rw-r--r--test/fileutils/test_fileutils.rb55
-rw-r--r--test/fixtures/fake_sorted_set_gem/sorted_set.rb9
-rw-r--r--test/gdbm/test_gdbm.rb2
-rw-r--r--test/io/console/test_io_console.rb39
-rw-r--r--test/io/wait/test_io_wait_uncommon.rb34
-rw-r--r--test/io/wait/test_ractor.rb22
-rw-r--r--test/irb/test_cmd.rb320
-rw-r--r--test/irb/test_color.rb29
-rw-r--r--test/irb/test_color_printer.rb68
-rw-r--r--test/irb/test_completion.rb36
-rw-r--r--test/irb/test_context.rb231
-rw-r--r--test/irb/test_history.rb36
-rw-r--r--test/irb/test_init.rb6
-rw-r--r--test/irb/test_raise_no_backtrace_exception.rb9
-rw-r--r--test/irb/test_ruby_lex.rb326
-rw-r--r--test/irb/test_workspace.rb6
-rw-r--r--test/irb/yamatanooroti/test_rendering.rb165
-rw-r--r--test/json/fixtures/fail29.json1
-rw-r--r--test/json/fixtures/fail30.json1
-rw-r--r--test/json/fixtures/fail31.json1
-rw-r--r--test/json/fixtures/fail32.json1
-rw-r--r--test/json/json_addition_test.rb4
-rw-r--r--test/json/json_common_interface_test.rb43
-rw-r--r--test/json/json_fixtures_test.rb10
-rw-r--r--test/json/json_generator_test.rb54
-rw-r--r--test/json/json_parser_test.rb25
-rw-r--r--test/json/ractor_test.rb30
-rw-r--r--test/json/test_helper.rb6
-rw-r--r--test/lib/jit_support.rb23
-rw-r--r--test/logger/test_logdevice.rb2
-rw-r--r--test/logger/test_logger.rb12
-rw-r--r--test/matrix/test_matrix.rb37
-rw-r--r--test/misc/test_ruby_mode.rb183
-rw-r--r--test/mkmf/test_install.rb30
-rw-r--r--test/mkmf/test_mkmf.rb15
-rw-r--r--test/monitor/test_monitor.rb23
-rw-r--r--test/net/ftp/test_ftp.rb76
-rw-r--r--test/net/http/test_http.rb23
-rw-r--r--test/net/http/test_httpresponse.rb2
-rw-r--r--test/net/http/test_https.rb50
-rw-r--r--test/net/http/utils.rb6
-rw-r--r--test/net/imap/test_imap.rb70
-rw-r--r--test/net/smtp/test_smtp.rb104
-rw-r--r--test/net/smtp/test_ssl_socket.rb4
-rw-r--r--test/net/smtp/test_sslcontext.rb129
-rw-r--r--test/net/smtp/test_starttls.rb122
-rw-r--r--test/objspace/test_objspace.rb113
-rw-r--r--test/open-uri/test_open-uri.rb12
-rw-r--r--test/openssl/test_asn1.rb41
-rw-r--r--test/openssl/test_bn.rb11
-rw-r--r--test/openssl/test_buffering.rb11
-rw-r--r--test/openssl/test_cipher.rb75
-rw-r--r--test/openssl/test_config.rb108
-rw-r--r--test/openssl/test_digest.rb64
-rw-r--r--test/openssl/test_engine.rb4
-rw-r--r--test/openssl/test_fips.rb2
-rw-r--r--test/openssl/test_hmac.rb12
-rw-r--r--test/openssl/test_kdf.rb2
-rw-r--r--test/openssl/test_ns_spki.rb6
-rw-r--r--test/openssl/test_ocsp.rb35
-rw-r--r--test/openssl/test_ossl.rb65
-rw-r--r--test/openssl/test_pair.rb28
-rw-r--r--test/openssl/test_pkcs12.rb2
-rw-r--r--test/openssl/test_pkcs7.rb26
-rw-r--r--test/openssl/test_pkey.rb28
-rw-r--r--test/openssl/test_pkey_dh.rb9
-rw-r--r--test/openssl/test_pkey_dsa.rb15
-rw-r--r--test/openssl/test_pkey_ec.rb30
-rw-r--r--test/openssl/test_pkey_rsa.rb157
-rw-r--r--test/openssl/test_random.rb2
-rw-r--r--test/openssl/test_ssl.rb115
-rw-r--r--test/openssl/test_ssl_session.rb2
-rw-r--r--test/openssl/test_ts.rb680
-rw-r--r--test/openssl/test_x509attr.rb12
-rw-r--r--test/openssl/test_x509cert.rb95
-rw-r--r--test/openssl/test_x509crl.rb45
-rw-r--r--test/openssl/test_x509ext.rb15
-rw-r--r--test/openssl/test_x509name.rb21
-rw-r--r--test/openssl/test_x509req.rb33
-rw-r--r--test/openssl/test_x509store.rb14
-rw-r--r--test/openssl/ut_eof.rb10
-rw-r--r--test/openssl/utils.rb92
-rw-r--r--test/optparse/test_acceptable.rb1
-rw-r--r--test/optparse/test_optparse.rb30
-rw-r--r--test/ostruct/test_ostruct.rb124
-rw-r--r--test/pathname/test_pathname.rb52
-rw-r--r--test/pathname/test_ractor.rb22
-rw-r--r--test/psych/helper.rb40
-rw-r--r--test/psych/test_alias_and_anchor.rb12
-rw-r--r--test/psych/test_array.rb6
-rw-r--r--test/psych/test_class.rb4
-rw-r--r--test/psych/test_coder.rb135
-rw-r--r--test/psych/test_date_time.rb4
-rw-r--r--test/psych/test_deprecated.rb4
-rw-r--r--test/psych/test_document.rb2
-rw-r--r--test/psych/test_emitter.rb10
-rw-r--r--test/psych/test_encoding.rb4
-rw-r--r--test/psych/test_exception.rb51
-rw-r--r--test/psych/test_hash.rb18
-rw-r--r--test/psych/test_marshalable.rb12
-rw-r--r--test/psych/test_merge_keys.rb34
-rw-r--r--test/psych/test_object.rb4
-rw-r--r--test/psych/test_object_references.rb12
-rw-r--r--test/psych/test_omap.rb4
-rw-r--r--test/psych/test_parser.rb16
-rw-r--r--test/psych/test_psych.rb103
-rw-r--r--test/psych/test_ractor.rb50
-rw-r--r--test/psych/test_safe_load.rb28
-rw-r--r--test/psych/test_scalar_scanner.rb3
-rw-r--r--test/psych/test_serialize_subclasses.rb4
-rw-r--r--test/psych/test_set.rb6
-rw-r--r--test/psych/test_string.rb14
-rw-r--r--test/psych/test_struct.rb6
-rw-r--r--test/psych/test_yaml.rb15
-rw-r--r--test/psych/test_yaml_special_cases.rb6
-rw-r--r--test/psych/test_yamlstore.rb47
-rw-r--r--test/psych/visitors/test_to_ruby.rb5
-rw-r--r--test/psych/visitors/test_yaml_tree.rb12
-rw-r--r--test/racc/assets/ifelse.y14
-rw-r--r--test/racc/helper.rb6
-rw-r--r--test/racc/regress/cadenza190
-rw-r--r--test/racc/regress/cast927
-rw-r--r--test/racc/regress/csspool396
-rw-r--r--test/racc/regress/edtf446
-rw-r--r--test/racc/regress/huia288
-rw-r--r--test/racc/regress/journey2
-rw-r--r--test/racc/regress/liquor218
-rw-r--r--test/racc/regress/machete48
-rw-r--r--test/racc/regress/mediacloth454
-rw-r--r--test/racc/regress/mof186
-rw-r--r--test/racc/regress/namae70
-rw-r--r--test/racc/regress/nasl620
-rw-r--r--test/racc/regress/nokogiri-css124
-rw-r--r--test/racc/regress/opal3522
-rw-r--r--test/racc/regress/php_serialization36
-rw-r--r--test/racc/regress/riml1166
-rw-r--r--test/racc/regress/ruby182277
-rw-r--r--test/racc/regress/ruby223582
-rw-r--r--test/racc/regress/tp_plus430
-rw-r--r--test/racc/regress/twowaysql42
-rw-r--r--test/racc/test_racc_command.rb17
-rw-r--r--test/rdoc/support/test_case.rb12
-rw-r--r--test/rdoc/test_rdoc_context_section.rb8
-rw-r--r--test/rdoc/test_rdoc_markdown.rb61
-rw-r--r--test/rdoc/test_rdoc_markup_attribute_manager.rb25
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb32
-rw-r--r--test/rdoc/test_rdoc_markup_to_html_crossref.rb21
-rw-r--r--test/rdoc/test_rdoc_markup_to_markdown.rb4
-rw-r--r--test/rdoc/test_rdoc_parser_changelog.rb169
-rw-r--r--test/rdoc/test_rdoc_rdoc.rb41
-rw-r--r--test/rdoc/test_rdoc_ri_driver.rb28
-rw-r--r--test/rdoc/test_rdoc_ri_paths.rb10
-rw-r--r--test/rdoc/test_rdoc_rubygems_hook.rb89
-rw-r--r--test/rdoc/test_rdoc_servlet.rb8
-rw-r--r--test/rdoc/test_rdoc_store.rb15
-rw-r--r--test/rdoc/test_rdoc_top_level.rb3
-rw-r--r--test/readline/test_readline.rb2
-rw-r--r--test/reline/helper.rb23
-rw-r--r--test/reline/test_key_actor_emacs.rb233
-rw-r--r--test/reline/test_key_actor_vi.rb229
-rw-r--r--test/reline/test_kill_ring.rb12
-rw-r--r--test/reline/test_reline.rb4
-rw-r--r--test/reline/test_string_processing.rb54
-rw-r--r--test/reline/test_unicode.rb16
-rw-r--r--test/reline/test_within_pipe.rb14
-rwxr-xr-xtest/reline/yamatanooroti/multiline_repl74
-rw-r--r--test/reline/yamatanooroti/termination_checker.rb30
-rw-r--r--test/reline/yamatanooroti/test_rendering.rb650
-rw-r--r--test/resolv/test_addr.rb22
-rw-r--r--test/resolv/test_dns.rb2
-rw-r--r--test/rexml/data/LostineRiver.kml.gzbin50154 -> 0 bytes-rw-r--r--test/rexml/data/ProductionSupport.xml29
-rw-r--r--test/rexml/data/axis.xml25
-rw-r--r--test/rexml/data/bad.xml5
-rw-r--r--test/rexml/data/basic.xml11
-rw-r--r--test/rexml/data/basicupdate.xml47
-rw-r--r--test/rexml/data/broken.rss20
-rw-r--r--test/rexml/data/contents.xml70
-rw-r--r--test/rexml/data/dash.xml12
-rw-r--r--test/rexml/data/defaultNamespace.xml6
-rw-r--r--test/rexml/data/doctype_test.xml34
-rw-r--r--test/rexml/data/documentation.xml542
-rw-r--r--test/rexml/data/euc.xml296
-rw-r--r--test/rexml/data/evaluate.xml28
-rw-r--r--test/rexml/data/fibo.xml29
-rw-r--r--test/rexml/data/foo.xml10
-rw-r--r--test/rexml/data/google.2.xml156
-rw-r--r--test/rexml/data/id.xml21
-rw-r--r--test/rexml/data/iso8859-1.xml4
-rw-r--r--test/rexml/data/jaxen24.xml2
-rw-r--r--test/rexml/data/jaxen3.xml15
-rw-r--r--test/rexml/data/lang.xml11
-rw-r--r--test/rexml/data/lang0.xml18
-rw-r--r--test/rexml/data/message.xml27
-rw-r--r--test/rexml/data/moreover.xml244
-rw-r--r--test/rexml/data/much_ado.xml6850
-rw-r--r--test/rexml/data/namespaces.xml18
-rw-r--r--test/rexml/data/nitf.xml67
-rw-r--r--test/rexml/data/numbers.xml18
-rw-r--r--test/rexml/data/ofbiz-issues-full-177.xml13971
-rw-r--r--test/rexml/data/pi.xml13
-rw-r--r--test/rexml/data/pi2.xml6
-rw-r--r--test/rexml/data/project.xml1
-rw-r--r--test/rexml/data/simple.xml2
-rw-r--r--test/rexml/data/stream_accents.xml4
-rw-r--r--test/rexml/data/t63-1.xmlbin161690 -> 0 bytes-rw-r--r--test/rexml/data/t63-2.svg2828
-rw-r--r--test/rexml/data/t75.xml31
-rw-r--r--test/rexml/data/test/tests.xml683
-rw-r--r--test/rexml/data/test/tests.xsl369
-rw-r--r--test/rexml/data/testNamespaces.xml22
-rw-r--r--test/rexml/data/testsrc.xml64
-rw-r--r--test/rexml/data/text.xml10
-rw-r--r--test/rexml/data/ticket_61.xml4
-rw-r--r--test/rexml/data/ticket_68.xml590
-rw-r--r--test/rexml/data/tutorial.xml678
-rw-r--r--test/rexml/data/underscore.xml6
-rw-r--r--test/rexml/data/utf16.xmlbin207464 -> 0 bytes-rw-r--r--test/rexml/data/web.xml42
-rw-r--r--test/rexml/data/web2.xml7
-rw-r--r--test/rexml/data/working.rss202
-rw-r--r--test/rexml/data/xmlfile-bug.xml15
-rw-r--r--test/rexml/data/xp.tst27
-rw-r--r--test/rexml/data/yahoo.xml80
-rw-r--r--test/rexml/formatter/test_default.rb19
-rw-r--r--test/rexml/functions/test_base.rb261
-rw-r--r--test/rexml/functions/test_boolean.rb75
-rw-r--r--test/rexml/functions/test_local_name.rb44
-rw-r--r--test/rexml/functions/test_number.rb38
-rw-r--r--test/rexml/listener.rb51
-rw-r--r--test/rexml/parse/test_document_type_declaration.rb229
-rw-r--r--test/rexml/parse/test_element.rb77
-rw-r--r--test/rexml/parse/test_notation_declaration.rb281
-rw-r--r--test/rexml/parse/test_processing_instruction.rb44
-rw-r--r--test/rexml/parser/test_sax2.rb203
-rw-r--r--test/rexml/parser/test_stream.rb32
-rw-r--r--test/rexml/parser/test_tree.rb43
-rw-r--r--test/rexml/parser/test_ultra_light.rb69
-rw-r--r--test/rexml/rexml_test_utils.rb10
-rw-r--r--test/rexml/test_attribute.rb14
-rw-r--r--test/rexml/test_attributes.rb223
-rw-r--r--test/rexml/test_attributes_mixin.rb32
-rw-r--r--test/rexml/test_changing_encoding.rb45
-rw-r--r--test/rexml/test_comment.rb26
-rw-r--r--test/rexml/test_contrib.rb585
-rw-r--r--test/rexml/test_core.rb1517
-rw-r--r--test/rexml/test_doctype.rb147
-rw-r--r--test/rexml/test_document.rb416
-rw-r--r--test/rexml/test_element.rb18
-rw-r--r--test/rexml/test_elements.rb119
-rw-r--r--test/rexml/test_encoding.rb108
-rw-r--r--test/rexml/test_entity.rb206
-rw-r--r--test/rexml/test_instruction.rb14
-rw-r--r--test/rexml/test_jaxen.rb131
-rw-r--r--test/rexml/test_light.rb107
-rw-r--r--test/rexml/test_lightparser.rb16
-rw-r--r--test/rexml/test_listener.rb131
-rw-r--r--test/rexml/test_martin_fowler.rb40
-rw-r--r--test/rexml/test_namespace.rb41
-rw-r--r--test/rexml/test_order.rb110
-rw-r--r--test/rexml/test_preceding_sibling.rb41
-rw-r--r--test/rexml/test_pullparser.rb103
-rw-r--r--test/rexml/test_rexml_issuezilla.rb19
-rw-r--r--test/rexml/test_sax.rb287
-rw-r--r--test/rexml/test_stream.rb130
-rw-r--r--test/rexml/test_text.rb75
-rw-r--r--test/rexml/test_ticket_80.rb59
-rw-r--r--test/rexml/test_validation_rng.rb793
-rw-r--r--test/rexml/test_xml_declaration.rb48
-rw-r--r--test/rexml/xpath/test_attribute.rb38
-rw-r--r--test/rexml/xpath/test_axis_preceding_sibling.rb40
-rw-r--r--test/rexml/xpath/test_base.rb1125
-rw-r--r--test/rexml/xpath/test_compare.rb256
-rw-r--r--test/rexml/xpath/test_node.rb43
-rw-r--r--test/rexml/xpath/test_predicate.rb83
-rw-r--r--test/rexml/xpath/test_text.rb77
-rw-r--r--test/rinda/test_rinda.rb16
-rw-r--r--test/ripper/dummyparser.rb6
-rw-r--r--test/ripper/test_lexer.rb89
-rw-r--r--test/ripper/test_parser_events.rb80
-rw-r--r--test/ripper/test_sexp.rb42
-rw-r--r--test/rss/dot.pngbin111 -> 0 bytes-rw-r--r--test/rss/rss-assertions.rb2120
-rw-r--r--test/rss/rss-testcase.rb479
-rw-r--r--test/rss/test_1.0.rb308
-rw-r--r--test/rss/test_2.0.rb412
-rw-r--r--test/rss/test_accessor.rb104
-rw-r--r--test/rss/test_atom.rb684
-rw-r--r--test/rss/test_content.rb105
-rw-r--r--test/rss/test_dublincore.rb270
-rw-r--r--test/rss/test_image.rb215
-rw-r--r--test/rss/test_inherit.rb41
-rw-r--r--test/rss/test_itunes.rb356
-rw-r--r--test/rss/test_maker_0.9.rb477
-rw-r--r--test/rss/test_maker_1.0.rb519
-rw-r--r--test/rss/test_maker_2.0.rb758
-rw-r--r--test/rss/test_maker_atom_entry.rb394
-rw-r--r--test/rss/test_maker_atom_feed.rb455
-rw-r--r--test/rss/test_maker_content.rb48
-rw-r--r--test/rss/test_maker_dc.rb150
-rw-r--r--test/rss/test_maker_image.rb63
-rw-r--r--test/rss/test_maker_itunes.rb487
-rw-r--r--test/rss/test_maker_slash.rb38
-rw-r--r--test/rss/test_maker_sy.rb45
-rw-r--r--test/rss/test_maker_taxo.rb82
-rw-r--r--test/rss/test_maker_trackback.rb42
-rw-r--r--test/rss/test_maker_xml-stylesheet.rb84
-rw-r--r--test/rss/test_parser.rb121
-rw-r--r--test/rss/test_parser_1.0.rb529
-rw-r--r--test/rss/test_parser_2.0.rb123
-rw-r--r--test/rss/test_parser_atom_entry.rb164
-rw-r--r--test/rss/test_parser_atom_feed.rb277
-rw-r--r--test/rss/test_setup_maker_0.9.rb247
-rw-r--r--test/rss/test_setup_maker_1.0.rb551
-rw-r--r--test/rss/test_setup_maker_2.0.rb309
-rw-r--r--test/rss/test_setup_maker_atom_entry.rb410
-rw-r--r--test/rss/test_setup_maker_atom_feed.rb446
-rw-r--r--test/rss/test_setup_maker_itunes.rb144
-rw-r--r--test/rss/test_setup_maker_slash.rb39
-rw-r--r--test/rss/test_slash.rb65
-rw-r--r--test/rss/test_syndication.rb126
-rw-r--r--test/rss/test_taxonomy.rb173
-rw-r--r--test/rss/test_to_s.rb701
-rw-r--r--test/rss/test_trackback.rb136
-rw-r--r--test/rss/test_xml-stylesheet.rb109
-rw-r--r--test/ruby/enc/test_regex_casefold.rb2
-rw-r--r--test/ruby/test_alias.rb26
-rw-r--r--test/ruby/test_argf.rb52
-rw-r--r--test/ruby/test_arithmetic_sequence.rb15
-rw-r--r--test/ruby/test_array.rb347
-rw-r--r--test/ruby/test_autoload.rb23
-rw-r--r--test/ruby/test_backtrace.rb56
-rw-r--r--test/ruby/test_basicinstructions.rb5
-rw-r--r--test/ruby/test_bignum.rb51
-rw-r--r--test/ruby/test_call.rb9
-rw-r--r--test/ruby/test_class.rb2
-rw-r--r--test/ruby/test_complex.rb5
-rw-r--r--test/ruby/test_const.rb28
-rw-r--r--test/ruby/test_defined.rb66
-rw-r--r--test/ruby/test_dir.rb211
-rw-r--r--test/ruby/test_dir_m17n.rb53
-rw-r--r--test/ruby/test_econv.rb19
-rw-r--r--test/ruby/test_encoding.rb31
-rw-r--r--test/ruby/test_enum.rb105
-rw-r--r--test/ruby/test_enumerator.rb8
-rw-r--r--test/ruby/test_env.rb37
-rw-r--r--test/ruby/test_eval.rb13
-rw-r--r--test/ruby/test_exception.rb373
-rw-r--r--test/ruby/test_fiber.rb164
-rw-r--r--test/ruby/test_file_exhaustive.rb9
-rw-r--r--test/ruby/test_fixnum.rb1
-rw-r--r--test/ruby/test_float.rb7
-rw-r--r--test/ruby/test_frozen_error.rb57
-rw-r--r--test/ruby/test_gc.rb49
-rw-r--r--test/ruby/test_gc_compact.rb90
-rw-r--r--test/ruby/test_hash.rb131
-rw-r--r--test/ruby/test_inlinecache.rb110
-rw-r--r--test/ruby/test_integer.rb1
-rw-r--r--test/ruby/test_io.rb192
-rw-r--r--test/ruby/test_io_m17n.rb12
-rw-r--r--test/ruby/test_iseq.rb58
-rw-r--r--test/ruby/test_iterator.rb3
-rw-r--r--test/ruby/test_jit.rb172
-rw-r--r--test/ruby/test_jit_debug.rb17
-rw-r--r--test/ruby/test_keyword.rb2170
-rw-r--r--test/ruby/test_lambda.rb6
-rw-r--r--test/ruby/test_lazy_enumerator.rb8
-rw-r--r--test/ruby/test_literal.rb4
-rw-r--r--test/ruby/test_m17n.rb11
-rw-r--r--test/ruby/test_m17n_comb.rb10
-rw-r--r--test/ruby/test_marshal.rb96
-rw-r--r--test/ruby/test_memory_view.rb341
-rw-r--r--test/ruby/test_method.rb87
-rw-r--r--test/ruby/test_method_cache.rb65
-rw-r--r--test/ruby/test_module.rb533
-rw-r--r--test/ruby/test_name_error.rb156
-rw-r--r--test/ruby/test_nomethod_error.rb109
-rw-r--r--test/ruby/test_numeric.rb67
-rw-r--r--test/ruby/test_object.rb43
-rw-r--r--test/ruby/test_optimization.rb8
-rw-r--r--test/ruby/test_parse.rb153
-rw-r--r--test/ruby/test_pattern_matching.rb183
-rw-r--r--test/ruby/test_primitive.rb78
-rw-r--r--test/ruby/test_proc.rb298
-rw-r--r--test/ruby/test_process.rb79
-rw-r--r--test/ruby/test_rand.rb353
-rw-r--r--test/ruby/test_range.rb17
-rw-r--r--test/ruby/test_rational.rb27
-rw-r--r--test/ruby/test_refinement.rb181
-rw-r--r--test/ruby/test_regexp.rb122
-rw-r--r--test/ruby/test_require.rb30
-rw-r--r--test/ruby/test_rubyoptions.rb32
-rw-r--r--test/ruby/test_rubyvm.rb4
-rw-r--r--test/ruby/test_settracefunc.rb90
-rw-r--r--test/ruby/test_stack.rb82
-rw-r--r--test/ruby/test_string.rb182
-rw-r--r--test/ruby/test_struct.rb28
-rw-r--r--test/ruby/test_super.rb108
-rw-r--r--test/ruby/test_symbol.rb39
-rw-r--r--test/ruby/test_syntax.rb121
-rw-r--r--test/ruby/test_thread.rb27
-rw-r--r--test/ruby/test_thread_queue.rb3
-rw-r--r--test/ruby/test_time.rb33
-rw-r--r--test/ruby/test_time_tz.rb17
-rw-r--r--test/ruby/test_transcode.rb50
-rw-r--r--test/ruby/test_variable.rb16
-rw-r--r--test/ruby/test_vm_dump.rb2
-rw-r--r--test/rubygems/data/null-required-ruby-version.gemspec.rzbin0 -> 403 bytes-rw-r--r--test/rubygems/data/null-required-rubygems-version.gemspec.rzbin0 -> 421 bytes-rw-r--r--test/rubygems/data/null-type.gemspec.rzbin554 -> 504 bytes-rw-r--r--test/rubygems/encrypted_private_key.pem52
-rw-r--r--test/rubygems/helper.rb1595
-rw-r--r--test/rubygems/installer_test_case.rb247
-rw-r--r--test/rubygems/package/tar_test_case.rb139
-rw-r--r--test/rubygems/packages/ascii_binder-0.1.10.1.gembin0 -> 244736 bytes-rw-r--r--test/rubygems/packages/ill-formatted-platform-1.0.0.10.gembin0 -> 10240 bytes-rw-r--r--test/rubygems/plugin/load/rubygems_plugin.rb2
-rw-r--r--test/rubygems/private_ec_key.pem9
-rw-r--r--test/rubygems/rubygems/commands/crash_command.rb2
-rw-r--r--test/rubygems/rubygems_plugin.rb2
-rw-r--r--test/rubygems/specifications/bar-0.0.2.gemspec2
-rw-r--r--test/rubygems/specifications/rubyforge-0.0.1.gemspec2
-rw-r--r--test/rubygems/test_bundled_ca.rb91
-rw-r--r--test/rubygems/test_config.rb4
-rw-r--r--test/rubygems/test_deprecate.rb95
-rw-r--r--test/rubygems/test_gem.rb720
-rw-r--r--test/rubygems/test_gem_available_set.rb10
-rw-r--r--test/rubygems/test_gem_bundler_version_finder.rb28
-rw-r--r--test/rubygems/test_gem_command.rb47
-rw-r--r--test/rubygems/test_gem_command_manager.rb65
-rw-r--r--test/rubygems/test_gem_commands_build_command.rb262
-rw-r--r--test/rubygems/test_gem_commands_cert_command.rb151
-rw-r--r--test/rubygems/test_gem_commands_check_command.rb14
-rw-r--r--test/rubygems/test_gem_commands_cleanup_command.rb69
-rw-r--r--test/rubygems/test_gem_commands_contents_command.rb75
-rw-r--r--test/rubygems/test_gem_commands_dependency_command.rb8
-rw-r--r--test/rubygems/test_gem_commands_environment_command.rb48
-rw-r--r--test/rubygems/test_gem_commands_fetch_command.rb58
-rw-r--r--test/rubygems/test_gem_commands_generate_index_command.rb10
-rw-r--r--test/rubygems/test_gem_commands_help_command.rb30
-rw-r--r--test/rubygems/test_gem_commands_info_command.rb16
-rw-r--r--test/rubygems/test_gem_commands_install_command.rb332
-rw-r--r--test/rubygems/test_gem_commands_list_command.rb6
-rw-r--r--test/rubygems/test_gem_commands_lock_command.rb6
-rw-r--r--test/rubygems/test_gem_commands_mirror.rb6
-rw-r--r--test/rubygems/test_gem_commands_open_command.rb27
-rw-r--r--test/rubygems/test_gem_commands_outdated_command.rb20
-rw-r--r--test/rubygems/test_gem_commands_owner_command.rb72
-rw-r--r--test/rubygems/test_gem_commands_pristine_command.rb85
-rw-r--r--test/rubygems/test_gem_commands_push_command.rb105
-rw-r--r--test/rubygems/test_gem_commands_query_command.rb40
-rw-r--r--test/rubygems/test_gem_commands_search_command.rb4
-rw-r--r--test/rubygems/test_gem_commands_server_command.rb10
-rw-r--r--test/rubygems/test_gem_commands_setup_command.rb385
-rw-r--r--test/rubygems/test_gem_commands_signin_command.rb61
-rw-r--r--test/rubygems/test_gem_commands_signout_command.rb9
-rw-r--r--test/rubygems/test_gem_commands_sources_command.rb74
-rw-r--r--test/rubygems/test_gem_commands_specification_command.rb80
-rw-r--r--test/rubygems/test_gem_commands_stale_command.rb4
-rw-r--r--test/rubygems/test_gem_commands_uninstall_command.rb14
-rw-r--r--test/rubygems/test_gem_commands_unpack_command.rb8
-rw-r--r--test/rubygems/test_gem_commands_update_command.rb162
-rw-r--r--test/rubygems/test_gem_commands_which_command.rb16
-rw-r--r--test/rubygems/test_gem_commands_yank_command.rb56
-rw-r--r--test/rubygems/test_gem_config_file.rb49
-rw-r--r--test/rubygems/test_gem_dependency.rb20
-rw-r--r--test/rubygems/test_gem_dependency_installer.rb390
-rw-r--r--test/rubygems/test_gem_dependency_list.rb24
-rw-r--r--test/rubygems/test_gem_dependency_resolution_error.rb6
-rw-r--r--test/rubygems/test_gem_doctor.rb88
-rw-r--r--test/rubygems/test_gem_ext_builder.rb142
-rw-r--r--test/rubygems/test_gem_ext_cmake_builder.rb47
-rw-r--r--test/rubygems/test_gem_ext_configure_builder.rb38
-rw-r--r--test/rubygems/test_gem_ext_ext_conf_builder.rb77
-rw-r--r--test/rubygems/test_gem_ext_rake_builder.rb69
-rw-r--r--test/rubygems/test_gem_gem_runner.rb47
-rw-r--r--test/rubygems/test_gem_gemcutter_utilities.rb49
-rw-r--r--test/rubygems/test_gem_impossible_dependencies_error.rb4
-rw-r--r--test/rubygems/test_gem_indexer.rb26
-rw-r--r--test/rubygems/test_gem_install_update_options.rb34
-rw-r--r--test/rubygems/test_gem_installer.rb731
-rw-r--r--test/rubygems/test_gem_local_remote_options.rb6
-rw-r--r--test/rubygems/test_gem_name_tuple.rb4
-rw-r--r--test/rubygems/test_gem_package.rb199
-rw-r--r--test/rubygems/test_gem_package_old.rb22
-rw-r--r--test/rubygems/test_gem_package_tar_header.rb31
-rw-r--r--test/rubygems/test_gem_package_tar_reader.rb4
-rw-r--r--test/rubygems/test_gem_package_tar_reader_entry.rb20
-rw-r--r--test/rubygems/test_gem_package_tar_writer.rb48
-rw-r--r--test/rubygems/test_gem_package_task.rb63
-rw-r--r--test/rubygems/test_gem_path_support.rb6
-rw-r--r--test/rubygems/test_gem_platform.rb80
-rw-r--r--test/rubygems/test_gem_rdoc.rb22
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb480
-rw-r--r--test/rubygems/test_gem_request.rb94
-rw-r--r--test/rubygems/test_gem_request_connection_pools.rb8
-rw-r--r--test/rubygems/test_gem_request_set.rb73
-rw-r--r--test/rubygems/test_gem_request_set_gem_dependency_api.rb42
-rw-r--r--test/rubygems/test_gem_request_set_lockfile.rb18
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_parser.rb28
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_tokenizer.rb248
-rw-r--r--test/rubygems/test_gem_requirement.rb108
-rw-r--r--test/rubygems/test_gem_resolver.rb40
-rw-r--r--test/rubygems/test_gem_resolver_activation_request.rb4
-rw-r--r--test/rubygems/test_gem_resolver_api_set.rb121
-rw-r--r--test/rubygems/test_gem_resolver_api_specification.rb10
-rw-r--r--test/rubygems/test_gem_resolver_best_set.rb37
-rw-r--r--test/rubygems/test_gem_resolver_composed_set.rb4
-rw-r--r--test/rubygems/test_gem_resolver_conflict.rb6
-rw-r--r--test/rubygems/test_gem_resolver_dependency_request.rb4
-rw-r--r--test/rubygems/test_gem_resolver_git_set.rb6
-rw-r--r--test/rubygems/test_gem_resolver_git_specification.rb9
-rw-r--r--test/rubygems/test_gem_resolver_index_set.rb8
-rw-r--r--test/rubygems/test_gem_resolver_index_specification.rb6
-rw-r--r--test/rubygems/test_gem_resolver_installed_specification.rb4
-rw-r--r--test/rubygems/test_gem_resolver_installer_set.rb44
-rw-r--r--test/rubygems/test_gem_resolver_local_specification.rb6
-rw-r--r--test/rubygems/test_gem_resolver_lock_set.rb10
-rw-r--r--test/rubygems/test_gem_resolver_lock_specification.rb4
-rw-r--r--test/rubygems/test_gem_resolver_requirement_list.rb4
-rw-r--r--test/rubygems/test_gem_resolver_specification.rb8
-rw-r--r--test/rubygems/test_gem_resolver_vendor_set.rb10
-rw-r--r--test/rubygems/test_gem_resolver_vendor_specification.rb4
-rw-r--r--test/rubygems/test_gem_security.rb94
-rw-r--r--test/rubygems/test_gem_security_policy.rb75
-rw-r--r--test/rubygems/test_gem_security_signer.rb38
-rw-r--r--test/rubygems/test_gem_security_trust_dir.rb20
-rw-r--r--test/rubygems/test_gem_server.rb38
-rw-r--r--test/rubygems/test_gem_silent_ui.rb22
-rw-r--r--test/rubygems/test_gem_source.rb43
-rw-r--r--test/rubygems/test_gem_source_fetch_problem.rb14
-rw-r--r--test/rubygems/test_gem_source_git.rb54
-rw-r--r--test/rubygems/test_gem_source_installed.rb18
-rw-r--r--test/rubygems/test_gem_source_list.rb5
-rw-r--r--test/rubygems/test_gem_source_local.rb20
-rw-r--r--test/rubygems/test_gem_source_lock.rb24
-rw-r--r--test/rubygems/test_gem_source_specific_file.rb20
-rw-r--r--test/rubygems/test_gem_source_subpath_problem.rb49
-rw-r--r--test/rubygems/test_gem_source_vendor.rb18
-rw-r--r--test/rubygems/test_gem_spec_fetcher.rb19
-rw-r--r--test/rubygems/test_gem_specification.rb1073
-rw-r--r--test/rubygems/test_gem_stream_ui.rb10
-rw-r--r--test/rubygems/test_gem_stub_specification.rb20
-rw-r--r--test/rubygems/test_gem_text.rb6
-rw-r--r--test/rubygems/test_gem_uninstaller.rb189
-rw-r--r--test/rubygems/test_gem_unsatisfiable_dependency_error.rb4
-rw-r--r--test/rubygems/test_gem_uri.rb39
-rw-r--r--test/rubygems/test_gem_uri_formatter.rb4
-rw-r--r--test/rubygems/test_gem_util.rb36
-rw-r--r--test/rubygems/test_gem_validator.rb6
-rw-r--r--test/rubygems/test_gem_version.rb23
-rw-r--r--test/rubygems/test_gem_version_option.rb6
-rw-r--r--test/rubygems/test_kernel.rb36
-rw-r--r--test/rubygems/test_project_sanity.rb11
-rw-r--r--test/rubygems/test_remote_fetch_error.rb6
-rw-r--r--test/rubygems/test_require.rb301
-rw-r--r--test/rubygems/test_rubygems.rb44
-rw-r--r--test/rubygems/utilities.rb371
-rw-r--r--test/sdbm/test_sdbm.rb544
-rw-r--r--test/socket/test_addrinfo.rb7
-rw-r--r--test/socket/test_basicsocket.rb2
-rw-r--r--test/socket/test_socket.rb2
-rw-r--r--test/socket/test_tcp.rb22
-rw-r--r--test/socket/test_unix.rb20
-rw-r--r--test/stringio/test_ractor.rb23
-rw-r--r--test/stringio/test_stringio.rb75
-rw-r--r--test/strscan/test_ractor.rb28
-rw-r--r--test/strscan/test_stringscanner.rb17
-rw-r--r--test/test_delegate.rb53
-rw-r--r--test/test_extlibs.rb2
-rw-r--r--test/test_mutex_m.rb32
-rw-r--r--test/test_open3.rb11
-rw-r--r--test/test_pp.rb16
-rw-r--r--test/test_prime.rb19
-rw-r--r--test/test_securerandom.rb2
-rw-r--r--test/test_set.rb149
-rw-r--r--test/test_sorted_set.rb45
-rw-r--r--test/test_tmpdir.rb41
-rw-r--r--test/test_win32api.rb27
-rw-r--r--test/uri/test_generic.rb49
-rw-r--r--test/uri/test_ws.rb71
-rw-r--r--test/webrick/test_cgi.rb170
-rw-r--r--test/webrick/test_filehandler.rb353
-rw-r--r--test/webrick/test_httpproxy.rb466
-rw-r--r--test/webrick/test_httprequest.rb476
-rw-r--r--test/webrick/test_httpresponse.rb282
-rw-r--r--test/webrick/test_httpserver.rb543
-rw-r--r--test/webrick/test_server.rb163
-rw-r--r--test/zlib/test_zlib.rb132
-rw-r--r--thread.c1308
-rw-r--r--thread_pthread.c289
-rw-r--r--thread_pthread.h52
-rw-r--r--thread_sync.c455
-rw-r--r--thread_win32.c95
-rw-r--r--thread_win32.h31
-rw-r--r--time.c679
-rw-r--r--timev.h1
-rwxr-xr-xtool/actions-commit-info.sh17
-rw-r--r--tool/bundler/rubocop_gems.rb11
-rw-r--r--tool/bundler/rubocop_gems.rb.lock63
-rw-r--r--tool/bundler/standard_gems.rb11
-rw-r--r--tool/bundler/standard_gems.rb.lock69
-rw-r--r--tool/bundler/test_gems.rb12
-rw-r--r--tool/bundler/test_gems.rb.lock44
-rw-r--r--tool/downloader.rb11
-rwxr-xr-xtool/extlibs.rb82
-rw-r--r--tool/fake.rb1
-rwxr-xr-xtool/fetch-bundled_gems.rb24
-rw-r--r--tool/gem-unpack.rb2
-rwxr-xr-xtool/leaked-globals4
-rw-r--r--tool/lib/colorize.rb12
-rw-r--r--tool/lib/envutil.rb44
-rw-r--r--tool/lib/leakchecker.rb111
-rw-r--r--tool/lib/minitest/benchmark.rb2
-rw-r--r--tool/lib/minitest/unit.rb59
-rw-r--r--tool/lib/test/unit.rb82
-rw-r--r--tool/lib/test/unit/assertions.rb268
-rw-r--r--tool/lib/test/unit/core_assertions.rb365
-rw-r--r--tool/lib/test/unit/parallel.rb37
-rw-r--r--tool/lib/test/unit/testcase.rb4
-rw-r--r--tool/lib/vcs.rb149
-rw-r--r--tool/lib/webrick.rb232
-rw-r--r--tool/lib/webrick/.document (renamed from lib/webrick/.document)0
-rw-r--r--tool/lib/webrick/accesslog.rb (renamed from lib/webrick/accesslog.rb)0
-rw-r--r--tool/lib/webrick/cgi.rb (renamed from lib/webrick/cgi.rb)0
-rw-r--r--tool/lib/webrick/compat.rb (renamed from lib/webrick/compat.rb)0
-rw-r--r--tool/lib/webrick/config.rb (renamed from lib/webrick/config.rb)0
-rw-r--r--tool/lib/webrick/cookie.rb (renamed from lib/webrick/cookie.rb)0
-rw-r--r--tool/lib/webrick/htmlutils.rb (renamed from lib/webrick/htmlutils.rb)0
-rw-r--r--tool/lib/webrick/httpauth.rb (renamed from lib/webrick/httpauth.rb)0
-rw-r--r--tool/lib/webrick/httpauth/authenticator.rb117
-rw-r--r--tool/lib/webrick/httpauth/basicauth.rb (renamed from lib/webrick/httpauth/basicauth.rb)0
-rw-r--r--tool/lib/webrick/httpauth/digestauth.rb (renamed from lib/webrick/httpauth/digestauth.rb)0
-rw-r--r--tool/lib/webrick/httpauth/htdigest.rb (renamed from lib/webrick/httpauth/htdigest.rb)0
-rw-r--r--tool/lib/webrick/httpauth/htgroup.rb (renamed from lib/webrick/httpauth/htgroup.rb)0
-rw-r--r--tool/lib/webrick/httpauth/htpasswd.rb (renamed from lib/webrick/httpauth/htpasswd.rb)0
-rw-r--r--tool/lib/webrick/httpauth/userdb.rb (renamed from lib/webrick/httpauth/userdb.rb)0
-rw-r--r--tool/lib/webrick/httpproxy.rb354
-rw-r--r--tool/lib/webrick/httprequest.rb636
-rw-r--r--tool/lib/webrick/httpresponse.rb (renamed from lib/webrick/httpresponse.rb)0
-rw-r--r--tool/lib/webrick/https.rb (renamed from lib/webrick/https.rb)0
-rw-r--r--tool/lib/webrick/httpserver.rb (renamed from lib/webrick/httpserver.rb)0
-rw-r--r--tool/lib/webrick/httpservlet.rb (renamed from lib/webrick/httpservlet.rb)0
-rw-r--r--tool/lib/webrick/httpservlet/abstract.rb (renamed from lib/webrick/httpservlet/abstract.rb)0
-rw-r--r--tool/lib/webrick/httpservlet/cgi_runner.rb (renamed from lib/webrick/httpservlet/cgi_runner.rb)0
-rw-r--r--tool/lib/webrick/httpservlet/cgihandler.rb (renamed from lib/webrick/httpservlet/cgihandler.rb)0
-rw-r--r--tool/lib/webrick/httpservlet/erbhandler.rb (renamed from lib/webrick/httpservlet/erbhandler.rb)0
-rw-r--r--tool/lib/webrick/httpservlet/filehandler.rb552
-rw-r--r--tool/lib/webrick/httpservlet/prochandler.rb (renamed from lib/webrick/httpservlet/prochandler.rb)0
-rw-r--r--tool/lib/webrick/httpstatus.rb (renamed from lib/webrick/httpstatus.rb)0
-rw-r--r--tool/lib/webrick/httputils.rb512
-rw-r--r--tool/lib/webrick/httpversion.rb (renamed from lib/webrick/httpversion.rb)0
-rw-r--r--tool/lib/webrick/log.rb (renamed from lib/webrick/log.rb)0
-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/m4/ruby_setjmp_type.m42
-rw-r--r--tool/m4/ruby_try_cxxflags.m417
-rwxr-xr-xtool/make-snapshot22
-rw-r--r--tool/mjit_tabs.rb65
-rw-r--r--tool/mk_builtin_binary.rb44
-rw-r--r--tool/mk_builtin_loader.rb298
-rw-r--r--tool/mk_call_iseq_optimized.rb74
-rwxr-xr-xtool/mkconfig.rb12
-rwxr-xr-xtool/mkrunnable.rb8
-rwxr-xr-xtool/pure_parser.rb2
-rwxr-xr-xtool/rbinstall.rb213
-rwxr-xr-xtool/rbuninstall.rb18
-rwxr-xr-xtool/redmine-backporter.rb18
-rwxr-xr-xtool/releng/gen-mail.rb50
-rwxr-xr-xtool/releng/gen-release-note.rb36
-rwxr-xr-xtool/releng/update-www-meta.rb213
-rw-r--r--tool/ruby_vm/helpers/c_escape.rb6
-rw-r--r--tool/ruby_vm/helpers/dumper.rb3
-rw-r--r--tool/ruby_vm/helpers/scanner.rb3
-rw-r--r--tool/ruby_vm/loaders/insns_def.rb8
-rwxr-xr-xtool/ruby_vm/models/bare_instructions.rb4
-rw-r--r--tool/ruby_vm/models/typemap.rb1
-rw-r--r--tool/ruby_vm/views/_insn_entry.erb4
-rw-r--r--tool/ruby_vm/views/_leaf_helpers.erb61
-rw-r--r--tool/ruby_vm/views/_mjit_compile_getinlinecache.erb31
-rw-r--r--tool/ruby_vm/views/_mjit_compile_insn.erb6
-rw-r--r--tool/ruby_vm/views/_mjit_compile_insn_body.erb20
-rw-r--r--tool/ruby_vm/views/_mjit_compile_invokebuiltin.erb29
-rw-r--r--tool/ruby_vm/views/_mjit_compile_ivar.erb75
-rw-r--r--tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb8
-rw-r--r--tool/ruby_vm/views/_mjit_compile_send.erb146
-rw-r--r--tool/ruby_vm/views/_sp_inc_helpers.erb8
-rw-r--r--tool/ruby_vm/views/_trace_instruction.erb2
-rw-r--r--tool/ruby_vm/views/mjit_compile.inc.erb61
-rwxr-xr-xtool/runruby.rb5
-rw-r--r--tool/search-cgvars.rb55
-rw-r--r--tool/sync_default_gems.rb401
-rw-r--r--tool/test-bundled-gems.rb35
-rw-r--r--tool/test-coverage.rb2
-rw-r--r--tool/test/minitest/test_minitest_unit.rb3
-rw-r--r--tool/test/testunit/test_hideskip.rb2
-rw-r--r--tool/test/testunit/test_parallel.rb2
-rw-r--r--tool/test/webrick/.htaccess (renamed from test/webrick/.htaccess)0
-rw-r--r--tool/test/webrick/test_cgi.rb170
-rw-r--r--tool/test/webrick/test_config.rb (renamed from test/webrick/test_config.rb)0
-rw-r--r--tool/test/webrick/test_cookie.rb (renamed from test/webrick/test_cookie.rb)0
-rw-r--r--tool/test/webrick/test_do_not_reverse_lookup.rb (renamed from test/webrick/test_do_not_reverse_lookup.rb)0
-rw-r--r--tool/test/webrick/test_filehandler.rb402
-rw-r--r--tool/test/webrick/test_htgroup.rb (renamed from test/webrick/test_htgroup.rb)0
-rw-r--r--tool/test/webrick/test_htmlutils.rb (renamed from test/webrick/test_htmlutils.rb)0
-rw-r--r--tool/test/webrick/test_httpauth.rb (renamed from test/webrick/test_httpauth.rb)0
-rw-r--r--tool/test/webrick/test_httpproxy.rb466
-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.rb (renamed from test/webrick/test_https.rb)0
-rw-r--r--tool/test/webrick/test_httpserver.rb543
-rw-r--r--tool/test/webrick/test_httpstatus.rb (renamed from test/webrick/test_httpstatus.rb)0
-rw-r--r--tool/test/webrick/test_httputils.rb (renamed from test/webrick/test_httputils.rb)0
-rw-r--r--tool/test/webrick/test_httpversion.rb (renamed from test/webrick/test_httpversion.rb)0
-rw-r--r--tool/test/webrick/test_server.rb191
-rw-r--r--tool/test/webrick/test_ssl_server.rb (renamed from test/webrick/test_ssl_server.rb)0
-rw-r--r--tool/test/webrick/test_utils.rb (renamed from test/webrick/test_utils.rb)0
-rw-r--r--tool/test/webrick/utils.rb (renamed from test/webrick/utils.rb)0
-rw-r--r--tool/test/webrick/webrick.cgi (renamed from test/webrick/webrick.cgi)0
-rw-r--r--tool/test/webrick/webrick.rhtml (renamed from test/webrick/webrick.rhtml)0
-rw-r--r--tool/test/webrick/webrick_long_filename.cgi (renamed from test/webrick/webrick_long_filename.cgi)0
-rw-r--r--tool/transcode-tblgen.rb6
-rw-r--r--tool/transform_mjit_header.rb52
-rw-r--r--tool/update-bundled_gems.rb14
-rwxr-xr-xtool/update-deps2
-rw-r--r--trace_point.rb42
-rw-r--r--transcode.c76
-rw-r--r--transcode_data.h5
-rw-r--r--transient_heap.c177
-rw-r--r--transient_heap.h9
-rw-r--r--util.c14
-rw-r--r--util/remove_openssl.rb55
-rw-r--r--variable.c911
-rw-r--r--variable.h15
-rw-r--r--version.h20
-rw-r--r--vm.c675
-rw-r--r--vm_args.c508
-rw-r--r--vm_backtrace.c465
-rw-r--r--vm_callinfo.h455
-rw-r--r--vm_core.h452
-rw-r--r--vm_debug.h88
-rw-r--r--vm_dump.c188
-rw-r--r--vm_eval.c607
-rw-r--r--vm_exec.c41
-rw-r--r--vm_exec.h15
-rw-r--r--vm_insnhelper.c2373
-rw-r--r--vm_insnhelper.h52
-rw-r--r--vm_method.c957
-rw-r--r--vm_opts.h11
-rw-r--r--vm_sync.c299
-rw-r--r--vm_sync.h138
-rw-r--r--vm_trace.c72
-rw-r--r--vsnprintf.c2
-rw-r--r--warning.rb16
-rw-r--r--win32/Makefile.sub42
-rw-r--r--win32/dir.h9
-rw-r--r--win32/file.c5
-rwxr-xr-xwin32/mkexports.rb2
-rw-r--r--win32/setup.mak9
-rw-r--r--win32/win32.c107
4172 files changed, 222795 insertions, 166301 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
index 7c32d1f7ee..8f4b96445c 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -24,6 +24,8 @@
(c-mode . ((c-file-style . "ruby")))
+ (c++-mode . ((c-file-style . "ruby")))
+
(change-log-mode .
((buffer-file-coding-system . us-ascii)
(indent-tabs-mode . t)
diff --git a/.document b/.document
index 8a418e5d4a..8616203552 100644
--- a/.document
+++ b/.document
@@ -10,13 +10,17 @@
# prelude
prelude.rb
rbconfig.rb
-
+array.rb
ast.rb
+dir.rb
gc.rb
+integer.rb
io.rb
+kernel.rb
pack.rb
trace_point.rb
warning.rb
+ractor.rb
# the lib/ directory (which has its own .document file)
lib
@@ -25,7 +29,7 @@ lib
ext
# rdoc files
-NEWS
+NEWS.md
README.md
README.ja.md
diff --git a/.gdbinit b/.gdbinit
index 0d44622691..49380951b8 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -136,7 +136,7 @@ define rp
printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len
if ($flags & RUBY_FL_USER2)
printf "(shared) shared="
- output/x ((struct RArray*)($arg0))->as.heap.aux.shared
+ output/x ((struct RArray*)($arg0))->as.heap.aux.shared_root
printf " "
else
printf "(ownership) capa=%ld ", ((struct RArray*)($arg0))->as.heap.aux.capa
@@ -156,12 +156,12 @@ define rp
else
if ($flags & RUBY_T_MASK) == RUBY_T_HASH
printf "%sT_HASH%s: ", $color_type, $color_end,
- if (((struct RHash *)($arg0))->basic->flags & RHASH_ST_TABLE_FLAG)
+ if (((struct RHash *)($arg0))->basic.flags & RHASH_ST_TABLE_FLAG)
printf "st len=%ld ", ((struct RHash *)($arg0))->as.st->num_entries
else
printf "li len=%ld bound=%ld ", \
- ((((struct RHash *)($arg0))->basic->flags & RHASH_AR_TABLE_SIZE_MASK) >> RHASH_AR_TABLE_SIZE_SHIFT), \
- ((((struct RHash *)($arg0))->basic->flags & RHASH_AR_TABLE_BOUND_MASK) >> RHASH_AR_TABLE_BOUND_SHIFT)
+ ((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_SIZE_MASK) >> RHASH_AR_TABLE_SIZE_SHIFT), \
+ ((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_BOUND_MASK) >> RHASH_AR_TABLE_BOUND_SHIFT)
end
print (struct RHash *)($arg0)
else
@@ -265,6 +265,10 @@ define rp
printf "%sT_ZOMBIE%s: ", $color_type, $color_end
print (struct RData *)($arg0)
else
+ if ($flags & RUBY_T_MASK) == RUBY_T_MOVED
+ printf "%sT_MOVED%s: ", $color_type, $color_end
+ print *(struct RMoved *)$arg0
+ else
printf "%sunknown%s: ", $color_type, $color_end
print (struct RBasic *)($arg0)
end
@@ -300,6 +304,7 @@ define rp
end
end
end
+ end
end
document rp
Print a Ruby's VALUE.
@@ -1274,7 +1279,7 @@ document rb_count_objects
Counts all objects grouped by type.
end
-# Details: https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/MachineInstructionsTraceWithGDB
+# Details: https://bugs.ruby-lang.org/projects/ruby-master/wiki/MachineInstructionsTraceWithGDB
define trace_machine_instructions
set logging on
set height 0
diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml
new file mode 100644
index 0000000000..7196708b21
--- /dev/null
+++ b/.github/codeql/codeql-config.yml
@@ -0,0 +1,4 @@
+name: "CodeQL config for the Ruby language"
+
+paths-ignore:
+ - '/ext/**/*/conftest.c'
diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml
new file mode 100644
index 0000000000..16d1e4a85a
--- /dev/null
+++ b/.github/workflows/baseruby.yml
@@ -0,0 +1,47 @@
+name: BASERUBY Check
+
+on: [push, pull_request]
+
+jobs:
+ baseruby:
+ name: BASERUBY
+ runs-on: ubuntu-20.04
+ if: "!contains(github.event.head_commit.message, '[ci skip]')"
+ strategy:
+ matrix:
+ ruby:
+ - ruby-2.2
+# - ruby-2.3
+# - ruby-2.4
+# - ruby-2.5
+# - ruby-2.6
+ - ruby-2.7
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler: none
+ - run: echo "make=make -sj$((1 + $(nproc --all)))" >> $GITHUB_ENV
+ - run: sudo apt-get install build-essential autoconf bison
+ - run: ./autogen.sh
+ - run: ./configure --disable-install-doc
+ - run: $make update-unicode
+ - run: $make common-srcs
+ - run: $make incs
+ - run: $make all
+ - run: $make test
+ - uses: k0kubun/action-slack@v2.0.0
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / BASERUBY @ ${{ matrix.ruby }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref }}".split('/').reverse()[0]
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: failure() && github.event_name == 'push'
diff --git a/.github/workflows/check_branch.yml b/.github/workflows/check_branch.yml
deleted file mode 100644
index 5bc20a5541..0000000000
--- a/.github/workflows/check_branch.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-# We bidirectionally synchronize github.com/ruby/ruby.git's ruby_2_7 branch and
-# git.ruby-lang.org/ruby.git's ruby_2_7 branch.
-# We can use a pull request's merge button only on the ruby_2_7 branch.
-#
-# Therefore, we require to pass this "check_branch" on all protected branches
-# to prevent us from accidentally pushing commits to GitHub directly.
-#
-# Details: https://bugs.ruby-lang.org/issues/16094
-name: Pull Request
-on: [pull_request]
-jobs:
- check_branch:
- runs-on: ubuntu-20.04
- steps:
- - name: Check if branch is ruby_2_7
- run: |
- if [ "$BASE_REF" != ruby_2_7 ]; then
- echo "Only ruby_2_7 branch accepts a pull request, but it's '$BASE_REF'."
- exit 1
- fi
- env:
- BASE_REF: ${{ github.base_ref }}
diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml
new file mode 100644
index 0000000000..b5c5ea3036
--- /dev/null
+++ b/.github/workflows/check_dependencies.yml
@@ -0,0 +1,45 @@
+name: Check Dependencies
+on: [push, pull_request]
+jobs:
+ update-deps:
+ strategy:
+ matrix:
+ os: [ubuntu-20.04, macos-latest]
+ fail-fast: true
+ runs-on: ${{ matrix.os }}
+ if: "!contains(github.event.head_commit.message, '[ci skip]')"
+ steps:
+ - name: Install libraries
+ run: |
+ set -x
+ sudo apt-get update -q || :
+ sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev bison autoconf ruby
+ if: "contains(matrix.os, 'ubuntu')"
+ - name: Install libraries
+ run: |
+ brew upgrade
+ brew install gdbm gmp libffi openssl@1.1 zlib autoconf automake libtool readline
+ if: "contains(matrix.os, 'macos')"
+ - name: git config
+ run: |
+ git config --global advice.detachedHead 0
+ - uses: actions/checkout@v2
+ - run: ./autogen.sh
+ - name: Run configure
+ run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g'
+ - run: make all golf
+ - run: ruby tool/update-deps --fix
+ - run: git diff --no-ext-diff --ignore-submodules --exit-code
+ - uses: k0kubun/action-slack@v2.0.0
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ matrix.os }} / Dependencies need to update",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref }}".split('/').reverse()[0]
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: failure() && github.event_name == 'push'
diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml
new file mode 100644
index 0000000000..2f4bbc7093
--- /dev/null
+++ b/.github/workflows/check_misc.yml
@@ -0,0 +1,17 @@
+name: Miscellaneous checks
+on: [push, pull_request]
+
+jobs:
+ checks:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Check if C-sources are US-ASCII
+ run: |
+ ! grep -r -n '[^ -~]' *.[chy] include internal win32/*.[ch]
+ - name: Check for header macros
+ run: |
+ ! for header in ruby/*.h; do \
+ git grep -l -F -e $header -e HAVE_`echo $header | tr a-z./ A-Z__` -- . > /dev/null || echo $header
+ done | grep -F .
+ working-directory: include
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000000..9fbabd35c6
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,43 @@
+name: "Code scanning - action"
+
+on:
+ push:
+ pull_request:
+ schedule:
+ - cron: '0 12 * * 4'
+
+jobs:
+ CodeQL-Build:
+
+ # CodeQL runs on ubuntu-latest and windows-latest
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Install libraries
+ run: |
+ set -x
+ sudo apt-get update -q || :
+ sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev bison autoconf ruby
+
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 2
+
+ - run: git checkout HEAD^2
+ if: ${{ github.event_name == 'pull_request' }}
+
+ - name: Remove an obsolete rubygems vendored file
+ run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v1
+ with:
+ languages: cpp
+ config-file: ./.github/codeql/codeql-config.yml
+
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@v1
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v1
diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml
new file mode 100644
index 0000000000..b954c64bd8
--- /dev/null
+++ b/.github/workflows/compilers.yml
@@ -0,0 +1,216 @@
+name: Compilations
+
+on: [push, pull_request]
+
+# Github actions does not support YAML anchors. This creative use of
+# environment variables (plus the "echo ::set-env" hack) is to reroute that
+# restriction.
+env:
+ default_cc: clang-11
+ append_cc: ''
+ crosshost: ''
+
+ # -O1 is faster than -O3 in our tests... Majority of time are consumed trying
+ # to optimize binaries. Also Github Actions runs on a relatively modern CPU
+ # compared to, say, GCC 4 or Clang 3. We don't specify `-march=native`
+ # because compilers tend not understand what the CPU is.
+ optflags: '-O1'
+
+ # -g0 disables backtraces when SEGV. Do not set that.
+ debugflags: '-ggdb3'
+
+ default_configure: >-
+ --enable-debug-env
+ --disable-install-doc
+ --with-ext=-test-/cxxanyargs,+
+ append_configure: >-
+ --without-valgrind
+ --without-jemalloc
+ --without-gmp
+
+ UPDATE_UNICODE: >-
+ UNICODE_FILES=.
+ UNICODE_PROPERTY_FILES=.
+ UNICODE_AUXILIARY_FILES=.
+ UNICODE_EMOJI_FILES=.
+ CONFIGURE_TTY: never
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
+ RUBY_DEBUG: ci rgengc
+ RUBY_TESTOPTS: >-
+ -q
+ --color=always
+ --tty=no
+
+jobs:
+ compile:
+ strategy:
+ fail-fast: false
+ matrix:
+ entry:
+ - { key: default_cc, name: gcc-10, value: gcc-10 }
+# - { key: default_cc, name: gcc-9, value: gcc-9 }
+# - { key: default_cc, name: gcc-8, value: gcc-8 }
+# - { key: default_cc, name: gcc-7, value: gcc-7 }
+# - { key: default_cc, name: gcc-6, value: gcc-6 }
+# - { key: default_cc, name: gcc-5, value: gcc-5 }
+ - { key: default_cc, name: gcc-4.8, value: gcc-4.8 }
+ - { key: default_cc, name: clang-12, value: clang-12 }
+# - { key: default_cc, name: clang-11, value: clang-11 }
+# - { key: default_cc, name: clang-10, value: clang-10 }
+# - { key: default_cc, name: clang-9, value: clang-9 }
+# - { key: default_cc, name: clang-8, value: clang-8 }
+# - { key: default_cc, name: clang-7, value: clang-7 }
+# - { key: default_cc, name: clang-6.0, value: clang-6.0 }
+# - { key: default_cc, name: clang-5.0, value: clang-5.0 }
+# - { key: default_cc, name: clang-4.0, value: clang-4.0 }
+ - { key: default_cc, name: clang-3.9, value: clang-3.9 }
+
+ - { key: crosshost, name: aarch64-linux-gnu, value: aarch64-linux-gnu }
+# - { key: crosshost, name: arm-linux-gnueabi, value: arm-linux-gnueabi }
+# - { key: crosshost, name: arm-linux-gnueabihf, value: arm-linux-gnueabihf }
+# - { key: crosshost, name: i686-w64-mingw32, value: i686-w64-mingw32 }
+# - { key: crosshost, name: powerpc-linux-gnu, value: powerpc-linux-gnu }
+ - { key: crosshost, name: powerpc64le-linux-gnu, value: powerpc64le-linux-gnu }
+ - { key: crosshost, name: s390x-linux-gnu, value: s390x-linux-gnu }
+ - { key: crosshost, name: x86_64-w64-mingw32, value: x86_64-w64-mingw32 }
+
+ - { key: append_cc, name: c99, value: '-std=c99 -Werror=pedantic -pedantic-errors' }
+# - { key: append_cc, name: c11, value: '-std=c11 -Werror=pedantic -pedantic-errors' }
+# - { key: append_cc, name: c17, value: '-std=c17 -Werror=pedantic -pedantic-errors' }
+ - { key: append_cc, name: c2x, value: '-std=c2x -Werror=pedantic -pedantic-errors' }
+ - { key: CXXFLAGS, name: c++98, value: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
+# - { key: CXXFLAGS, name: c++11, value: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
+# - { key: CXXFLAGS, name: c++14, value: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
+# - { key: CXXFLAGS, name: c++17, value: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
+ - { key: CXXFLAGS, name: c++2a, value: '-std=c++2a -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }
+
+ - { key: optflags, name: '-O0', value: '-O0 -march=x86-64 -mtune=generic' }
+# - { key: optflags, name: '-O3', value: '-O3 -march=x86-64 -mtune=generic' }
+
+ - { key: append_configure, name: gmp, value: '--with-gmp' }
+ - { key: append_configure, name: jemalloc, value: '--with-jemalloc' }
+ - { key: append_configure, name: valgrind, value: '--with-valgrind' }
+ - { key: append_configure, name: 'coroutine=ucontext', value: '--with-coroutine=ucontext' }
+ - { key: append_configure, name: 'coroutine=copy', value: '--with-coroutine=copy' }
+ - { key: append_configure, name: disable-jit-support, value: '--disable-jit-support' }
+ - { key: append_configure, name: disable-dln, value: '--disable-dln' }
+ - { key: append_configure, name: disable-rubygems, value: '--disable-rubygems' }
+
+ - { key: cppflags, name: OPT_THREADED_CODE=1, value: '-DOPT_THREADED_CODE=1' }
+ - { key: cppflags, name: OPT_THREADED_CODE=2, value: '-DOPT_THREADED_CODE=2' }
+ - { key: cppflags, name: OPT_THREADED_CODE=3, value: '-DOPT_THREADED_CODE=3' }
+
+ - { key: cppflags, name: NDEBUG, value: '-DNDEBUG' }
+ - { key: cppflags, name: RUBY_DEBUG, value: '-DRUBY_DEBUG' }
+# - { key: cppflags, name: ARRAY_DEBUG, value: '-DARRAY_DEBUG' }
+# - { key: cppflags, name: BIGNUM_DEBUG, value: '-DBIGNUM_DEBUG' }
+# - { key: cppflags, name: CCAN_LIST_DEBUG, value: '-DCCAN_LIST_DEBUG' }
+# - { key: cppflags, name: CPDEBUG=-1, value: '-DCPDEBUG=-1' }
+# - { key: cppflags, name: ENC_DEBUG, value: '-DENC_DEBUG' }
+# - { key: cppflags, name: GC_DEBUG, value: '-DGC_DEBUG' }
+# - { key: cppflags, name: HASH_DEBUG, value: '-DHASH_DEBUG' }
+# - { key: cppflags, name: ID_TABLE_DEBUG, value: '-DID_TABLE_DEBUG' }
+# - { key: cppflags, name: RGENGC_DEBUG=-1, value: '-DRGENGC_DEBUG=-1' }
+# - { key: cppflags, name: SYMBOL_DEBUG, value: '-DSYMBOL_DEBUG' }
+# - { key: cppflags, name: THREAD_DEBUG=-1, value: '-DTHREAD_DEBUG=-1' }
+
+# - { key: cppflags, name: RGENGC_CHECK_MODE, value: '-DRGENGC_CHECK_MODE' }
+# - { key: cppflags, name: TRANSIENT_HEAP_CHECK_MODE, value: '-DTRANSIENT_HEAP_CHECK_MODE' }
+# - { key: cppflags, name: VM_CHECK_MODE, value: '-DVM_CHECK_MODE' }
+
+ - { key: cppflags, name: USE_EMBED_CI=0, value: '-DUSE_EMBED_CI=0' }
+ - { key: cppflags, name: USE_FLONUM=0, value: '-DUSE_FLONUM=0' }
+# - { key: cppflags, name: USE_GC_MALLOC_OBJ_INFO_DETAILS, value: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' }
+ - { key: cppflags, name: USE_LAZY_LOAD, value: '-DUSE_LAZY_LOAD' }
+# - { key: cppflags, name: USE_RINCGC=0, value: '-DUSE_RINCGC=0' }
+# - { key: cppflags, name: USE_SYMBOL_GC=0, value: '-DUSE_SYMBOL_GC=0' }
+# - { key: cppflags, name: USE_THREAD_CACHE=0, value: '-DUSE_THREAD_CACHE=0' }
+# - { key: cppflags, name: USE_TRANSIENT_HEAP=0, value: '-DUSE_TRANSIENT_HEAP=0' }
+# - { key: cppflags, name: USE_RUBY_DEBUG_LOG=1, value: '-DUSE_RUBY_DEBUG_LOG=1' }
+
+ - { key: cppflags, name: DEBUG_FIND_TIME_NUMGUESS, value: '-DDEBUG_FIND_TIME_NUMGUESS' }
+ - { key: cppflags, name: DEBUG_INTEGER_PACK, value: '-DDEBUG_INTEGER_PACK' }
+ - { key: cppflags, name: ENABLE_PATH_CHECK, value: '-DENABLE_PATH_CHECK' }
+
+ - { key: cppflags, name: GC_DEBUG_STRESS_TO_CLASS, value: '-DGC_DEBUG_STRESS_TO_CLASS' }
+# - { key: cppflags, name: GC_ENABLE_LAZY_SWEEP=0, value: '-DGC_ENABLE_LAZY_SWEEP=0' }
+# - { key: cppflags, name: GC_PROFILE_DETAIL_MEMOTY, value: '-DGC_PROFILE_DETAIL_MEMOTY' }
+# - { key: cppflags, name: GC_PROFILE_MORE_DETAIL, value: '-DGC_PROFILE_MORE_DETAIL' }
+
+# - { key: cppflags, name: CALC_EXACT_MALLOC_SIZE, value: '-DCALC_EXACT_MALLOC_SIZE' }
+# - { key: cppflags, name: MALLOC_ALLOCATED_SIZE_CHECK, value: '-DMALLOC_ALLOCATED_SIZE_CHECK' }
+
+# - { key: cppflags, name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, value: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' }
+
+# - { key: cppflags, name: RGENGC_ESTIMATE_OLDMALLOC, value: '-DRGENGC_ESTIMATE_OLDMALLOC' }
+# - { key: cppflags, name: RGENGC_FORCE_MAJOR_GC, value: '-DRGENGC_FORCE_MAJOR_GC' }
+# - { key: cppflags, name: RGENGC_OBJ_INFO, value: '-DRGENGC_OBJ_INFO' }
+# - { key: cppflags, name: RGENGC_OLD_NEWOBJ_CHECK, value: '-DRGENGC_OLD_NEWOBJ_CHECK' }
+# - { key: cppflags, name: RGENGC_PROFILE, value: '-DRGENGC_PROFILE' }
+
+# - { key: cppflags, name: VM_DEBUG_BP_CHECK, value: '-DVM_DEBUG_BP_CHECK' }
+# - { key: cppflags, name: VM_DEBUG_VERIFY_METHOD_CACHE, value: '-DVM_DEBUG_VERIFY_METHOD_CACHE' }
+
+ - { key: cppflags, name: MJIT_FORCE_ENABLE, value: '-DMJIT_FORCE_ENABLE' }
+
+ name: ${{ matrix.entry.name }}
+ runs-on: ubuntu-latest
+ container: ghcr.io/ruby/ruby-ci-image:latest
+ if: "!contains(github.event.head_commit.message, '[ci skip]')"
+ steps:
+ - run: mkdir build
+ working-directory:
+ - name: setenv
+ run: |
+ echo "${{ matrix.entry.key }}=${{ matrix.entry.value }}" >> $GITHUB_ENV
+ echo "make=make -sj$((1 + $(nproc --all)))" >> $GITHUB_ENV
+ - uses: actions/checkout@v2
+ with:
+ path: src
+ - run: ./autogen.sh
+ working-directory: src
+ - name: Run configure
+ run: |
+ if [ -n "${crosshost}" ]; then
+ ../src/configure -C \
+ ${default_configure} \
+ ${append_configure} \
+ --host="${crosshost}"
+ else
+ ../src/configure -C \
+ ${default_configure} \
+ ${append_configure} \
+ --with-gcc="${default_cc} ${append_cc}"
+ fi
+ - run: $make extract-extlibs
+ - run: $make incs
+ - run: $make
+ - run: $make test
+ - run: $make install
+ if: "matrix.entry.name == '-O3'"
+ - run: /usr/local/bin/gem install --no-doc timezone tzinfo
+ if: "matrix.entry.name == '-O3'"
+ - run: $make test-tool
+ if: "matrix.entry.name == '-O3'"
+ - run: $make test-all TESTS='-- ruby -ext-'
+ if: "matrix.entry.name == '-O3'"
+ - run: $make test-spec
+ if: "matrix.entry.name == '-O3'"
+
+ - uses: k0kubun/action-slack@v2.0.0
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / ${{ matrix.entry.name }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref }}".split('/').reverse()[0]
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: failure() && github.event_name == 'push'
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 9213e2a381..f9c0a17302 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -1,82 +1,66 @@
name: macOS
-on:
- push:
- branches:
- - '*'
- pull_request:
- branches:
- - '*'
+on: [push, pull_request]
jobs:
make:
runs-on: macos-latest
strategy:
matrix:
- test_task: [ "check", "test-bundler", "test-bundled-gems" ]
+ test_task: [ "check", "test-bundler-parallel" ] #, "test-bundled-gems" ] matrix tests has unknown issues
fail-fast: false
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
if: "!contains(github.event.head_commit.message, '[ci skip]')"
steps:
+ - run: mkdir build
+ working-directory:
- name: Disable Firewall
run: |
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate
- # Not using official actions/checkout because it's unstable and sometimes doesn't work for a fork.
- - name: Checkout ruby
+ - name: git config
run: |
- git clone --single-branch --shallow-since=yesterday --branch=${GITHUB_REF#refs/heads/} https://github.com/${{ github.repository }} src
- git -C src reset --hard "$GITHUB_SHA"
- if: github.event_name == 'push'
- - name: Checkout a pull request
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${{ github.event.pull_request.head.ref }} https://github.com/${{ github.event.pull_request.head.repo.full_name }} src
- git -C src reset --hard ${{ github.event.pull_request.head.sha }}
- if: github.event_name == 'pull_request'
- - run: ./src/tool/actions-commit-info.sh
- id: commit_info
+ git config --global advice.detachedHead 0
+ - uses: actions/checkout@v2
+ with:
+ path: src
- name: Install libraries
run: |
export WAITS='5 60'
- cd src
tool/travis_retry.sh brew upgrade
tool/travis_retry.sh brew install gdbm gmp libffi openssl@1.1 zlib autoconf automake libtool readline
+ working-directory: src
- name: Set ENV
run: |
echo "JOBS=-j$((1 + $(sysctl -n hw.activecpu)))" >> $GITHUB_ENV
- - name: Autoconf
- run: |
- cd src
- autoreconf -i
- - name: Configure
- run: |
- mkdir build
- cd build
- ../src/configure -C --disable-install-doc --with-openssl-dir=$(brew --prefix openssl@1.1) --with-readline-dir=$(brew --prefix readline)
- - name: Make
- run: make -C build $JOBS
- - name: Remove system gems
- run: rm -rf /usr/local/lib/ruby/gems/2.7.0/
- - name: Extract gems
- run: make -C build update-gems extract-gems
+ - run: ./autogen.sh
+ working-directory: src
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --with-openssl-dir=$(brew --prefix openssl@1.1) --with-readline-dir=$(brew --prefix readline)
+ - run: make $JOBS incs
+ - run: make $JOBS
+ - run: make leaked-globals
+ if: matrix.test_task == 'check'
+ - run: make prepare-gems
if: matrix.test_task == 'check'
- - name: Tests
- run: make -C build $JOBS -s ${{ matrix.test_task }}
+ - run: make $JOBS -s ${{ matrix.test_task }}
+ timeout-minutes: 60
env:
RUBY_TESTOPTS: "-q --tty=no"
- # Remove minitest from TEST_BUNDLED_GEMS_ALLOW_FAILURES if https://github.com/seattlerb/minitest/pull/798 is resolved
- # rss needs to add workaround for the non rexml environment
- TEST_BUNDLED_GEMS_ALLOW_FAILURES: "minitest,xmlrpc,rss,rexml"
- - name: Leaked Globals
- run: make -C build -s leaked-globals
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: "rexml"
- uses: k0kubun/action-slack@v2.0.0
with:
payload: |
{
- "attachments": [{
- "text": "${{ github.workflow }} / ${{ matrix.test_task }} <https://github.com/${{ github.repository }}/commit/${{ github.sha }}/checks|${{ steps.commit_info.outputs.COMMIT_DATE }} #${{ steps.commit_info.outputs.COMMIT_NUMBER_OF_DAY }}> " +
- "(<https://github.com/${{ github.repository }}/commit/${{ github.sha }}|" + "${{ github.sha }}".substring(0, 10) + ">) " +
- "of ${{ github.repository }}@" + "${{ github.ref }}".split('/').reverse()[0] + " by ${{ github.event.head_commit.committer.name }} failed",
- "color": "danger"
- }]
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / ${{ matrix.test_task }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref }}".split('/').reverse()[0]
}
env:
- SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: failure() && github.event_name == 'push'
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml
new file mode 100644
index 0000000000..a5d64c7b2d
--- /dev/null
+++ b/.github/workflows/mingw.yml
@@ -0,0 +1,141 @@
+name: MinGW
+on: [push, pull_request]
+
+# Notes:
+# Actions console encoding causes issues, see test-all & test-spec steps
+#
+jobs:
+ make:
+ runs-on: windows-2022
+ name: ${{ github.workflow }} (${{ matrix.msystem }})
+ env:
+ MSYSTEM: MINGW64
+ MSYSTEM_PREFIX: /mingw64
+ MSYS2_ARCH: x86_64
+ CHOST: "x86_64-w64-mingw32"
+ CFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe -fstack-protector-strong"
+ CXXFLAGS: "-march=x86-64 -mtune=generic -O3 -pipe"
+ CPPFLAGS: "-D_FORTIFY_SOURCE=2 -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048"
+ LDFLAGS: "-pipe -fstack-protector-strong"
+ UPDATE_UNICODE: "UNICODE_FILES=. UNICODE_PROPERTY_FILES=. UNICODE_AUXILIARY_FILES=. UNICODE_EMOJI_FILES=."
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
+ strategy:
+ matrix:
+ test_task: [ "check" ] # to make job names consistent
+ fail-fast: false
+ if: "!contains(github.event.head_commit.message, '[ci skip]')"
+ steps:
+ - run: mkdir build
+ working-directory:
+ - name: git config
+ run: |
+ git config --system core.autocrlf false
+ git config --system core.eol lf
+ git config --system advice.detachedHead 0
+ - uses: actions/checkout@v2
+ with:
+ path: src
+ - name: Set up Ruby & MSYS2
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 2.6
+ mingw: _upgrade_ gdbm gmp libffi libyaml openssl ragel readline
+ msys2: automake1.16 bison
+ - name: where check
+ run: |
+ # show where
+ Write-Host
+ $where = 'gcc.exe', 'ragel.exe', 'make.exe', 'bison.exe', 'libcrypto-1_1-x64.dll', 'libssl-1_1-x64.dll'
+ foreach ($e in $where) {
+ $rslt = where.exe $e 2>&1 | Out-String
+ if ($rslt.contains($e)) { Write-Host $rslt }
+ else { Write-Host "`nCan't find $e" }
+ }
+
+ - name: autogen
+ run: |
+ ./autogen.sh
+ working-directory: src
+ shell: sh
+
+ - name: configure
+ run: |
+ # Actions uses UTF8, causes test failures, similar to normal OS setup
+ $PSDefaultParameterValues['*:Encoding'] = 'utf8'
+ [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("IBM437")
+ [Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("IBM437")
+ $config_args = "--build=$env:CHOST --host=$env:CHOST --target=$env:CHOST"
+ Write-Host $config_args
+ sh -c "../src/configure --disable-install-doc --prefix=/. $config_args"
+ # Write-Host "-------------------------------------- config.log"
+ # Get-Content ./config.log | foreach {Write-Output $_}
+
+ - name: update
+ run: |
+ $jobs = [int](2 * $env:NUMBER_OF_PROCESSORS)
+ make -j $jobs incs
+
+ - name: download gems
+ run: |
+ $jobs = [int](2 * $env:NUMBER_OF_PROCESSORS)
+ make -j $jobs update-gems
+
+ - name: make all
+ timeout-minutes: 40
+ run: |
+ $jobs = [int](2 * $env:NUMBER_OF_PROCESSORS)
+ make -j $jobs
+
+ - name: make install
+ run: |
+ # Actions uses UTF8, causes test failures, similar to normal OS setup
+ $PSDefaultParameterValues['*:Encoding'] = 'utf8'
+ [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("IBM437")
+ [Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("IBM437")
+ make DESTDIR=../install install-nodoc
+
+ - name: test
+ timeout-minutes: 5
+ run: |
+ make test
+
+ - name: test-all
+ timeout-minutes: 60
+ run: |
+ # Actions uses UTF8, causes test failures, similar to normal OS setup
+ $PSDefaultParameterValues['*:Encoding'] = 'utf8'
+ [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("IBM437")
+ [Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("IBM437")
+ $jobs = [int](1.5 * $env:NUMBER_OF_PROCESSORS)
+ if ($env:BUNDLER_VERSION) { Remove-Item env:\BUNDLER_VERSION }
+ make test-all TESTOPTS="-j $jobs --retry --job-status=normal --show-skip --timeout-scale=1.5"
+
+ - name: test-spec
+ timeout-minutes: 10
+ working-directory: src/spec/ruby
+ run: |
+ $env:Path = "$pwd/../../../install/bin;$env:Path"
+ # Actions uses UTF8, causes test failures, similar to normal OS setup
+ $PSDefaultParameterValues['*:Encoding'] = 'utf8'
+ [Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("IBM437")
+ [Console]::InputEncoding = [System.Text.Encoding]::GetEncoding("IBM437")
+ ruby -v
+ ruby ../mspec/bin/mspec -I../../tool/lib -j
+
+ - uses: k0kubun/action-slack@v2.0.0
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} ${{ matrix.msystem }} / ${{ matrix.test_task }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref }}".split('/').reverse()[0]
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: failure() && github.event_name == 'push'
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/mjit.yml b/.github/workflows/mjit.yml
index ecef045c38..9e3a6d6ab7 100644
--- a/.github/workflows/mjit.yml
+++ b/.github/workflows/mjit.yml
@@ -1,11 +1,5 @@
name: MJIT
-on:
- push:
- branches:
- - '*'
- pull_request:
- branches:
- - '*'
+on: [push, pull_request]
jobs:
make:
strategy:
@@ -13,64 +7,71 @@ jobs:
test_task: [ "check" ] # to make job names consistent
jit_opts: [ "--jit", "--jit-wait" ]
fail-fast: false
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]')"
+ env:
+ TESTOPTS: '-q --tty=no'
+ RUN_OPTS: '--disable-gems ${{ matrix.jit_opts }} --jit-debug=-ggdb3'
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
steps:
+ - run: mkdir build
+ working-directory:
- name: Install libraries
run: |
set -x
sudo apt-get update -q || :
sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev bison autoconf ruby
- # Not using official actions/checkout because it's unstable and sometimes doesn't work for a fork.
- - name: Checkout ruby
+ - name: git config
run: |
- git clone --single-branch --shallow-since=yesterday --branch=${GITHUB_REF#refs/heads/} https://github.com/${{ github.repository }} src
- git -C src reset --hard "$GITHUB_SHA"
- if: github.event_name == 'push'
- - name: Checkout a pull request
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${{ github.event.pull_request.head.ref }} https://github.com/${{ github.event.pull_request.head.repo.full_name }} src
- git -C src reset --hard ${{ github.event.pull_request.head.sha }}
- if: github.event_name == 'pull_request'
- - run: ./src/tool/actions-commit-info.sh
- id: commit_info
+ git config --global advice.detachedHead 0
+ - uses: actions/checkout@v2
+ with:
+ path: src
- name: Fixed world writable dirs
run: |
- chmod go-w $HOME
+ chmod -v go-w $HOME $HOME/.config
sudo chmod -R go-w /usr/share
+ sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || :
- name: Set ENV
run: |
echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- - name: Autoconf
- run: cd src && exec autoreconf -i
- - name: configure
+ - run: ./autogen.sh
+ working-directory: src
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc cppflags=-DVM_CHECK_MODE
+ - run: make $JOBS incs
+ - run: make $JOBS
+ - run: sudo make $JOBS -s install
+ - run: sudo apt-get install gdb # used by test / test-all failure
+ - name: Run test
+ run: |
+ ulimit -c unlimited
+ make $JOBS -s test RUN_OPTS="$RUN_OPTS"
+ timeout-minutes: 60
+ - name: Run test-all
+ run: |
+ ulimit -c unlimited
+ make $JOBS -s test-all RUN_OPTS="$RUN_OPTS"
+ timeout-minutes: 60
+ - name: Run test-spec
run: |
- mkdir build
- cd build
- ../src/configure -C --disable-install-doc
- - name: make all
- run: make -C build $JOBS
- - name: make install
- run: sudo make -C build $JOBS install
- - name: make test
- run: "make -C build $JOBS -s test TESTOPTS='-q --tty=no' RUN_OPTS='--disable-gems --jit-warnings ${{ matrix.jit_opts }}'"
- - name: make test-all
- run: "make -C build $JOBS -s test-all TESTOPTS='-q --tty=no' RUN_OPTS='--disable-gems --jit-warnings ${{ matrix.jit_opts }}'"
- - name: make test-spec
- run: "make -C build $JOBS -s test-spec RUN_OPTS='--disable-gems --jit-warnings ${{ matrix.jit_opts }}'"
- - name: Leaked Globals
- run: make -C build -s leaked-globals
+ ulimit -c unlimited
+ make $JOBS -s test-spec RUN_OPTS="$RUN_OPTS"
+ timeout-minutes: 60
- uses: k0kubun/action-slack@v2.0.0
with:
payload: |
{
- "attachments": [{
- "text": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.jit_opts }} <https://github.com/${{ github.repository }}/commit/${{ github.sha }}/checks|${{ steps.commit_info.outputs.COMMIT_DATE }} #${{ steps.commit_info.outputs.COMMIT_NUMBER_OF_DAY }}> " +
- "(<https://github.com/${{ github.repository }}/commit/${{ github.sha }}|" + "${{ github.sha }}".substring(0, 10) + ">) " +
- "of ${{ github.repository }}@" + "${{ github.ref }}".split('/').reverse()[0] + " by ${{ github.event.head_commit.committer.name }} failed",
- "color": "danger"
- }]
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / ${{ matrix.test_task }} ${{ matrix.jit_opts }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref }}".split('/').reverse()[0]
}
env:
- SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: failure() && github.event_name == 'push'
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml
new file mode 100644
index 0000000000..bf053cdd05
--- /dev/null
+++ b/.github/workflows/spec_guards.yml
@@ -0,0 +1,41 @@
+name: Rubyspec Version Guards Check
+
+on: [push, pull_request]
+
+jobs:
+ rubyspec:
+ name: Rubyspec
+ runs-on: ubuntu-20.04
+ if: "!contains(github.event.head_commit.message, '[ci skip]')"
+ strategy:
+ matrix:
+ # Specs from ruby/spec should still run on all supported Ruby versions.
+ # This also ensures the needed ruby_version_is guards are there, see spec/README.md.
+ ruby:
+ - ruby-2.5
+# - ruby-2.6
+ - ruby-2.7
+ - ruby-3.0
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler: none
+ - run: gem install webrick
+ - run: ruby ../mspec/bin/mspec
+ working-directory: spec/ruby
+ - uses: k0kubun/action-slack@v2.0.0
+ with:
+ payload: |
+ {
+ "ci": "GitHub Actions",
+ "env": "${{ github.workflow }} / rubyspec @ ${{ matrix.ruby }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref }}".split('/').reverse()[0]
+ }
+ env:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: failure() && github.event_name == 'push'
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index a206886eef..93187699be 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -1,114 +1,87 @@
name: Ubuntu
-on:
- push:
- branches:
- - '*'
- pull_request:
- branches:
- - '*'
+on: [push, pull_request]
jobs:
make:
strategy:
matrix:
- test_task: [ "check", "test-bundler", "test-bundled-gems" ]
- os: [ubuntu-20.04, ubuntu-18.04]
+ test_task: [ "check", "test-bundler-parallel", "test-bundled-gems", "test-all TESTS=--repeat-count=2" ]
+ os:
+ - ubuntu-20.04
+# - ubuntu-18.04
+# - ubuntu-16.04
+ debug: ["", "-DRUBY_DEBUG"]
exclude:
- - test_task: test-bundler
+ - test_task: test-bundler-parallel
os: ubuntu-16.04
- test_task: test-bundled-gems
os: ubuntu-16.04
+ - test_task: "test-all TESTS=--repeat-count=2"
+ os: ubuntu-16.04
+ - os: ubuntu-16.04
+ debug: -DRUBY_DEBUG
+ - test_task: "test-all TESTS=--repeat-count=2"
+ debug: -DRUBY_DEBUG
fail-fast: false
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
+ RUBY_DEBUG: ci
runs-on: ${{ matrix.os }}
if: "!contains(github.event.head_commit.message, '[ci skip]')"
steps:
- - run: env | sort
- - name: Dump GitHub context
- env:
- GITHUB_CONTEXT: ${{ toJson(github) }}
- run: echo "$GITHUB_CONTEXT"
- - name: Dump job context
- env:
- JOB_CONTEXT: ${{ toJson(job) }}
- run: echo "$JOB_CONTEXT"
- - name: Dump steps context
- env:
- STEPS_CONTEXT: ${{ toJson(steps) }}
- run: echo "$STEPS_CONTEXT"
- - name: Dump runner context
- env:
- RUNNER_CONTEXT: ${{ toJson(runner) }}
- run: echo "$RUNNER_CONTEXT"
- - name: Dump strategy context
- env:
- STRATEGY_CONTEXT: ${{ toJson(strategy) }}
- run: echo "$STRATEGY_CONTEXT"
- - name: Dump matrix context
- env:
- MATRIX_CONTEXT: ${{ toJson(matrix) }}
- run: echo "$MATRIX_CONTEXT"
-
+ - run: mkdir build
+ working-directory:
- name: Install libraries
run: |
set -x
sudo apt-get update -q || :
sudo apt-get install --no-install-recommends -q -y build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm-dev bison autoconf ruby
- # Not using official actions/checkout because it's unstable and sometimes doesn't work for a fork.
- - name: Checkout ruby
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${GITHUB_REF#refs/heads/} https://github.com/${{ github.repository }} src
- git -C src reset --hard "$GITHUB_SHA"
- if: github.event_name == 'push'
- - name: Checkout a pull request
+ - name: git config
run: |
- git clone --single-branch --shallow-since=yesterday --branch=${{ github.event.pull_request.head.ref }} https://github.com/${{ github.event.pull_request.head.repo.full_name }} src
- git -C src reset --hard ${{ github.event.pull_request.head.sha }}
- if: github.event_name == 'pull_request'
- - run: ./src/tool/actions-commit-info.sh
- id: commit_info
+ git config --global advice.detachedHead 0
+ - uses: actions/checkout@v2
+ with:
+ path: src
- name: Fixed world writable dirs
run: |
- chmod go-w $HOME
+ chmod -v go-w $HOME $HOME/.config
sudo chmod -R go-w /usr/share
+ sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || :
- name: Set ENV
run: |
echo "JOBS=-j$((1 + $(nproc --all)))" >> $GITHUB_ENV
- - name: Autoconf
- run: cd src && exec autoreconf -i
- - name: configure
- run: |
- mkdir build
- cd build
- ../src/configure -C --disable-install-doc
- - name: Make
- run: make -C build $JOBS
- - name: Extract gems
- run: make -C build update-gems extract-gems
+ - run: ./autogen.sh
+ working-directory: src
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc cppflags=${{ matrix.debug }}
+ - run: make $JOBS incs
+ - run: make $JOBS
+ - run: make leaked-globals
+ if: matrix.test_task == 'check'
+ - run: make prepare-gems
if: matrix.test_task == 'check'
- name: Create dummy files in build dir
run: |
- cd build
./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}'
if: matrix.test_task == 'check'
- - name: Tests
- run: make -C build $JOBS -s ${{ matrix.test_task }}
+ - run: make $JOBS -s ${{ matrix.test_task }}
+ timeout-minutes: 30
env:
RUBY_TESTOPTS: "-q --tty=no"
- # Remove minitest from TEST_BUNDLED_GEMS_ALLOW_FAILURES if https://github.com/seattlerb/minitest/pull/798 is resolved
- # rss needs to add workaround for the non rexml environment
- TEST_BUNDLED_GEMS_ALLOW_FAILURES: "minitest,xmlrpc,rss"
- - name: Leaked Globals
- run: make -C build -s leaked-globals
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ""
- uses: k0kubun/action-slack@v2.0.0
with:
payload: |
{
- "attachments": [{
- "text": "${{ matrix.os }} / ${{ matrix.test_task }} <https://github.com/${{ github.repository }}/commit/${{ github.sha }}/checks|${{ steps.commit_info.outputs.COMMIT_DATE }} #${{ steps.commit_info.outputs.COMMIT_NUMBER_OF_DAY }}> " +
- "(<https://github.com/${{ github.repository }}/commit/${{ github.sha }}|" + "${{ github.sha }}".substring(0, 10) + ">) " +
- "of ${{ github.repository }}@" + "${{ github.ref }}".split('/').reverse()[0] + " by ${{ github.event.head_commit.committer.name }} failed",
- "color": "danger"
- }]
+ "ci": "GitHub Actions",
+ "env": "${{ matrix.os }} / ${{ matrix.test_task }}${{ matrix.debug }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref }}".split('/').reverse()[0]
}
env:
- SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: failure() && github.event_name == 'push'
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 82cca9353b..98e59ae188 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -1,11 +1,5 @@
name: Windows
-on:
- push:
- branches:
- - '*'
- pull_request:
- branches:
- - '*'
+on: [push, pull_request]
jobs:
make:
strategy:
@@ -15,9 +9,14 @@ jobs:
vs: [2019]
fail-fast: false
runs-on: ${{ matrix.os }}
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{github.ref}}
+ VCVARS: C:\Program Files (x86)\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat
if: "!contains(github.event.head_commit.message, '[ci skip]')"
steps:
- - uses: actions/cache@v1
+ - run: md build
+ working-directory:
+ - uses: actions/cache@v2
with:
path: C:\vcpkg\downloads
key: ${{ runner.os }}-vcpkg-download-${{ matrix.os }}-${{ github.sha }}
@@ -27,7 +26,7 @@ jobs:
- name: Install libraries with vcpkg
run: |
vcpkg --triplet x64-windows install readline zlib
- - uses: actions/cache@v1
+ - uses: actions/cache@v2
with:
path: C:\Users\runneradmin\AppData\Local\Temp\chocolatey
key: ${{ runner.os }}-chocolatey-${{ matrix.os }}-${{ github.sha }}
@@ -36,56 +35,46 @@ jobs:
${{ runner.os }}-chocolatey-
- name: Install libraries with chocolatey
run: |
- choco install --no-progress openssl winflexbison3
- # Not using official actions/checkout because it's unstable and sometimes doesn't work for a fork.
- - name: Checkout ruby
+ choco install --no-progress openssl
+ choco install --no-progress winflexbison3 --version=2.5.18.20190508
+ - name: git config
run: |
- git clone --single-branch --shallow-since=yesterday --branch=${GITHUB_REF#refs/heads/} https://github.com/${{ github.repository }} src
- git -C src reset --hard ${{ github.sha }}
- if: github.event_name == 'push'
- shell: bash
- - name: Checkout a pull request
- run: |
- git clone --single-branch --shallow-since=yesterday --branch=${{ github.event.pull_request.head.ref }} https://github.com/${{ github.event.pull_request.head.repo.full_name }} src
- git -C src reset --hard ${{ github.event.pull_request.head.sha }}
- if: github.event_name == 'pull_request'
- - run: ./src/tool/actions-commit-info.sh
- shell: bash
- id: commit_info
+ git config --system advice.detachedHead 0
+ - uses: actions/checkout@v2
+ with:
+ path: src
- name: Configure
run: |
- md build
- cd build
- call "C:\Program Files (x86)\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
+ call "%VCVARS%"
../src/win32/configure.bat --disable-install-doc --without-ext=+,dbm,gdbm --enable-bundled-libffi --with-opt-dir=C:/vcpkg/installed/x64-windows --with-openssl-dir="C:/Program Files/OpenSSL-Win64"
- shell: cmd
- name: nmake
run: |
- call "C:\Program Files (x86)\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
+ call "%VCVARS%"
set YACC=win_bison
- cd build
echo on
- nmake up
- nmake extract-gems
+ nmake incs
+ nmake extract-extlibs
nmake
- shell: cmd
- name: nmake test
+ timeout-minutes: 30
run: |
- call "C:\Program Files (x86)\Microsoft Visual Studio\${{ matrix.vs }}\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
- cd build
+ call "%VCVARS%"
nmake ${{ matrix.test_task }}
- shell: cmd
- uses: k0kubun/action-slack@v2.0.0
with:
payload: |
{
- "attachments": [{
- "text": "${{ matrix.os }} / ${{ matrix.test_task }} <https://github.com/${{ github.repository }}/commit/${{ github.sha }}/checks|${{ steps.commit_info.outputs.COMMIT_DATE }} #${{ steps.commit_info.outputs.COMMIT_NUMBER_OF_DAY }}> " +
- "(<https://github.com/${{ github.repository }}/commit/${{ github.sha }}|" + "${{ github.sha }}".substring(0, 10) + ">) " +
- "of ${{ github.repository }}@" + "${{ github.ref }}".split('/').reverse()[0] + " by ${{ github.event.head_commit.committer.name }} failed",
- "color": "danger"
- }]
+ "ci": "GitHub Actions",
+ "env": "${{ matrix.os }} / ${{ matrix.test_task }}",
+ "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
+ "commit": "${{ github.sha }}",
+ "branch": "${{ github.ref }}".split('/').reverse()[0]
}
env:
- SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: failure() && github.event_name == 'push'
+
+defaults:
+ run:
+ working-directory: build
+ shell: cmd
diff --git a/.gitignore b/.gitignore
index 487af950f3..8d11d7278a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,7 +27,6 @@
*.swp
*.yarb
*~
-.*-*
.*.list
.*.time
.DS_Store
@@ -38,6 +37,7 @@
.ppack
.svn
.time
+.ruby-version
Makefile
cygruby*.def
extconf.h
@@ -57,6 +57,8 @@ lcov*.info
/*.pc
/*.rc
/*_prelude.c
+/.downloaded-cache
+/.top-enc.mk
/build*/
/COPYING.LIB
/ChangeLog
@@ -117,6 +119,7 @@ lcov*.info
/rename2.h
/repack
/revision.h
+/revision.tmp
/riscos
/rubicon
/ruby
@@ -125,6 +128,7 @@ lcov*.info
/ruby-man.rd.gz
/run.gdb
/sizes.c
+/static-ruby
/test.rb
/test-coverage.dat
/tmp
@@ -190,6 +194,7 @@ lcov*.info
# /ext/ripper/
/ext/ripper/eventids1.c
+/ext/ripper/.eventids2-check
/ext/ripper/eventids2table.c
/ext/ripper/ripper.*
/ext/ripper/ids1
diff --git a/.travis.yml b/.travis.yml
index 71945e349e..d480307dd6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -47,15 +47,13 @@ env:
- RUBY_PREFIX=/tmp/ruby-prefix
- GEMS_FOR_TEST='timezone tzinfo'
- UPDATE_UNICODE="UNICODE_FILES=. UNICODE_PROPERTY_FILES=. UNICODE_AUXILIARY_FILES=. UNICODE_EMOJI_FILES=."
+ - BEFORE_INSTALL=true
# 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"
.org.ruby-lang.ci.matrix-definitions:
- - &cron-only
- if: (type = cron) AND (branch = master) AND (fork = false)
-
- &make-test-only
script:
- $SETARCH make -s test TESTOPTS="${TESTOPTS=$JOBS -q --tty=no}"
@@ -68,26 +66,23 @@ env:
# sources:
# - ubuntu-toolchain-r-test
before_install:
+ - bash -cx "${BEFORE_INSTALL}"
- tool/travis_retry.sh sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
- tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - |-
- ${BEFORE_INSTALL}
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install \
- ccache \
- gcc-8 \
- g++-8 \
- libffi-dev \
- libgdbm-dev \
- libgmp-dev \
- libjemalloc-dev \
- libncurses5-dev \
- libncursesw5-dev \
- libreadline6-dev \
- libssl-dev \
- libyaml-dev \
- openssl \
- valgrind \
- zlib1g-dev
+ - >-
+ tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
+ ccache
+ gcc-8
+ g++-8
+ libffi-dev
+ libgdbm-dev
+ libncurses5-dev
+ libncursesw5-dev
+ libreadline6-dev
+ libssl-dev
+ libyaml-dev
+ openssl
+ zlib1g-dev
- &clang-8
compiler: clang-8
@@ -100,22 +95,19 @@ env:
retries: true
before_install:
- tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - |-
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install \
- clang-8 \
- llvm-8-tools \
- libffi-dev \
- libgdbm-dev \
- libgmp-dev \
- libjemalloc-dev \
- libncurses5-dev \
- libncursesw5-dev \
- libreadline6-dev \
- libssl-dev \
- libyaml-dev \
- openssl \
- valgrind \
- zlib1g-dev
+ - >-
+ tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
+ clang-8
+ llvm-8-tools
+ libffi-dev
+ libgdbm-dev
+ libncurses5-dev
+ libncursesw5-dev
+ libreadline6-dev
+ libssl-dev
+ libyaml-dev
+ openssl
+ zlib1g-dev
# --------
@@ -132,130 +124,6 @@ env:
name: s390x-linux
arch: s390x
<<: *gcc-8
-
- - &jemalloc
- name: --with-jemalloc
- <<: *gcc-8
- <<: *cron-only
- env:
- - CONFIG_FLAG='--with-gmp --with-jemalloc --with-valgrind'
-
- - &assertions
- name: RUBY_DEBUG=1
- <<: *gcc-8
- #<<: *cron-only
- <<: *make-test-only
- env:
- - GEMS_FOR_TEST=
- - cppflags='-DRUBY_DEBUG -DVM_CHECK_MODE=1 -DTRANSIENT_HEAP_CHECK_MODE -DRGENGC_CHECK_MODE -DENC_DEBUG'
-
- - &VM_CHECK_MODE
- name: VM_CHECK_MODE=3
- <<: *gcc-8
- <<: *cron-only
- <<: *make-test-only
- env:
- - GEMS_FOR_TEST=
- - cppflags=-DVM_CHECK_MODE=0x0003
-
- - &SUPPORT_JOKE
- name: SUPPORT_JOKE
- <<: *gcc-8
- <<: *cron-only
- <<: *make-test-only
- env:
- - BEFORE_INSTALL="sed vm_opts.h -e 's/OPT_SUPPORT_JOKE *0/OPT_SUPPORT_JOKE 1/' -i"
-
- - &CPDEBUG
- name: CPDEBUG
- <<: *gcc-8
- <<: *cron-only
- <<: *make-test-only
- env:
- - cppflags=-DCPDEBUG
-
- - &WITH_COROUTINE_UCONTEXT
- name: COROUTINE=ucontext
- <<: *gcc-8
- <<: *cron-only
- env:
- - CONFIG_FLAG='--with-coroutine=ucontext'
-
- - &WITH_COROUTINE_COPY
- name: COROUTINE=copy
- <<: *gcc-8
- <<: *cron-only
- env:
- - CONFIG_FLAG='--with-coroutine=copy'
-
- - &TOKEN_THREADED_CODE
- name: TOKEN_THREADED_CODE
- <<: *gcc-8
- <<: *cron-only
- <<: *make-test-only
- env:
- - GEMS_FOR_TEST=
- - cppflags=-DOPT_THREADED_CODE=1
-
- - &CALL_THREADED_CODE
- name: CALL_THREADED_CODE
- <<: *gcc-8
- <<: *cron-only
- <<: *make-test-only
- env:
- - GEMS_FOR_TEST=
- - cppflags=-DOPT_THREADED_CODE=2
-
- - &NO_THREADED_CODE
- name: NO_THREADED_CODE
- <<: *gcc-8
- <<: *cron-only
- <<: *make-test-only
- env:
- - GEMS_FOR_TEST=
- - cppflags=-DOPT_THREADED_CODE=3
-
- - &ASAN
- name: -fsanitize=address
- <<: *clang-8
- #<<: *cron-only
- <<: *make-test-only
- env:
- - GEMS_FOR_TEST=
- - ASAN_OPTIONS=detect_leaks=0
- - cflags='-U_FORTIFY_SOURCE -march=native -fsanitize=address -fno-omit-frame-pointer -fPIC'
- - debugflags=-ggdb3
- - optflags=-O1
- - LD=clang-8
- - LDFLAGS='-fsanitize=address -fPIC'
- - CONFIG_FLAG='--with-out-ext=openssl --without-gmp --without-jemalloc --without-valgrind'
-
- - &MSAN
- name: -fsanitize=memory
- <<: *clang-8
- #<<: *cron-only
- <<: *make-test-only
- env:
- - GEMS_FOR_TEST=
- - cflags='-U_FORTIFY_SOURCE -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fPIC'
- - optflags=-O1
- - LD=clang-8
- - LDFLAGS='-fsanitize=memory -fPIC'
- - CONFIG_FLAG='--with-out-ext=openssl --without-gmp --without-jemalloc --without-valgrind'
-
- - &UBSAN
- name: -fsanitize=undefined
- <<: *clang-8
- #<<: *cron-only
- <<: *make-test-only
- env:
- - GEMS_FOR_TEST=
- - cflags='-U_FORTIFY_SOURCE -fsanitize=undefined,integer,nullability -fno-sanitize=implicit-integer-sign-change,unsigned-integer-overflow'
- - cppflags=-DUNALIGNED_WORD_ACCESS=0
- - debugflags=-ggdb3
- - optflags='-O1 -march=native'
- - LD=clang-8
- - LDFLAGS='-fsanitize=undefined,integer,nullability -fno-sanitize=implicit-integer-sign-change,unsigned-integer-overflow'
- &i686-linux
name: i686-linux
@@ -273,26 +141,26 @@ env:
before_install:
- tool/travis_retry.sh sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
- tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - |-
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install \
- gcc-8-multilib \
- g++-8 \
- g++-8-multilib \
- libstdc++-8-dev:i386 \
- libffi-dev:i386 \
- libffi6:i386 \
- libgdbm-dev:i386 \
- libgdbm3:i386 \
- libncurses5-dev:i386 \
- libncurses5:i386 \
- libncursesw5-dev:i386 \
- libreadline6-dev:i386 \
- libreadline6:i386 \
- libssl-dev:i386 \
- libssl1.0.0:i386 \
- linux-libc-dev:i386 \
- zlib1g-dev:i386 \
- zlib1g:i386
+ - >-
+ tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
+ gcc-8-multilib
+ g++-8
+ g++-8-multilib
+ libstdc++-8-dev:i386
+ libffi-dev:i386
+ libffi6:i386
+ libgdbm-dev:i386
+ libgdbm3:i386
+ libncurses5-dev:i386
+ libncurses5:i386
+ libncursesw5-dev:i386
+ libreadline6-dev:i386
+ libreadline6:i386
+ libssl-dev:i386
+ libssl1.0.0:i386
+ linux-libc-dev:i386
+ zlib1g-dev:i386
+ zlib1g:i386
- &arm32-linux
name: arm32-linux
@@ -305,156 +173,43 @@ env:
before_install:
- sudo dpkg --add-architecture armhf
- tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - |-
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install \
- ccache \
- crossbuild-essential-armhf \
- libc6:armhf \
- libstdc++-5-dev:armhf \
- libffi-dev:armhf \
- libffi6:armhf \
- libgdbm-dev:armhf \
- libgdbm3:armhf \
- libncurses5-dev:armhf \
- libncurses5:armhf \
- libncursesw5-dev:armhf \
- libreadline6-dev:armhf \
- libreadline6:armhf \
- libssl-dev:armhf \
- libssl1.0.0:armhf \
- linux-libc-dev:armhf \
- zlib1g-dev:armhf \
- zlib1g:armhf
-
- - &pedanticism
- name: -std=c99 -pedantic
- compiler: clang
- <<: *make-test-only
- env:
- - GEMS_FOR_TEST=
- - GCC_FLAGS='-std=c99 -Werror=pedantic -pedantic-errors'
- - CONFIG_FLAG=
- - JOBS=
- >-
- warnflags='
- -Wall
- -Wextra
- -Werror=deprecated-declarations
- -Werror=division-by-zero
- -Werror=extra-tokens
- -Werror=implicit-function-declaration
- -Werror=implicit-int
- -Werror=pointer-arith
- -Werror=shorten-64-to-32
- -Werror=write-strings
- -Wmissing-noreturn
- -Wno-constant-logical-operand
- -Wno-missing-field-initializers
- -Wno-overlength-strings
- -Wno-parentheses-equality
- -Wno-self-assign
- -Wno-tautological-compare
- -Wno-unused-local-typedef
- -Wno-unused-parameter
- -Wunused-variable'
- - LDFLAGS=-Wno-unused-command-line-argument
-
- - &rubyspec
- name: Check ruby/spec version guards on Ruby 2.4
- language: ruby
- rvm: 2.4.6
- before_install:
- install:
- before_script: chmod -R u+w spec/ruby
- # -j randomly hangs.
- script: ruby -C spec/ruby ../mspec/bin/mspec .
- after_failure:
- - echo "ruby/spec failed on Ruby 2.4. This is likely because of a missing ruby_version_is guard, please add it. See spec/README.md."
-
- - &baseruby
- name: "BASERUBY: Ruby 2.2"
- <<: *gcc-8
- <<: *make-test-only
- language: ruby
- rvm: 2.2
-
- - &dependency
- name: Check dependencies in makefiles
- language: ruby
- before_install:
- install:
- before_script:
- - |-
- ruby -e 'new = []
- Dir.glob("ext/**/extconf.rb") {|ex|
- unless File.exist?(dep = File.dirname(ex)+"/depend")
- puts "Adding "+dep
- File.copy_stream("template/depend.tmpl", dep)
- new << dep
- end
- }
- exec("git", "add", *new) unless new.empty?'
- - git diff --cached
- - "> config.status"
- - "> .rbconfig.time"
- - sed -f tool/prereq.status template/Makefile.in common.mk > Makefile
- - make touch-unicode-files
- - make -s $JOBS $UPDATE_UNICODE up
- - make -s $JOBS srcs
- - rm -f config.status Makefile rbconfig.rb .rbconfig.time
- - $SETARCH ./configure -C --disable-install-doc --prefix=$RUBY_PREFIX --disable-rubygems 'optflags=-O0' 'debugflags=-save-temps=obj -g'
- - ruby tool/update-deps --fix
- script:
- - git diff --no-ext-diff --ignore-submodules --exit-code
- after_failure:
- - echo "Dependencies need to update"
- env:
- - CONFIG_FLAG=
+ tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
+ ccache
+ crossbuild-essential-armhf
+ libc6:armhf
+ libstdc++-5-dev:armhf
+ libffi-dev:armhf
+ libffi6:armhf
+ libgdbm-dev:armhf
+ libgdbm3:armhf
+ libncurses5-dev:armhf
+ libncurses5:armhf
+ libncursesw5-dev:armhf
+ libreadline6-dev:armhf
+ libreadline6:armhf
+ libssl-dev:armhf
+ libssl1.0.0:armhf
+ linux-libc-dev:armhf
+ zlib1g-dev:armhf
+ zlib1g:armhf
matrix:
include:
# Build every commit:
- - <<: *x86_64-linux
- - <<: *arm64-linux
- <<: *i686-linux
+ # Build every commit (Allowed Failures):
- <<: *arm32-linux
+ - <<: *arm64-linux
- <<: *s390x-linux
- - <<: *pedanticism
- - <<: *assertions
- - <<: *baseruby
- - <<: *rubyspec
- - <<: *dependency
- # Build every commit (Allowed Failures):
- - <<: *ASAN
- - <<: *MSAN
- - <<: *UBSAN
- # Cron only:
- - <<: *jemalloc
- - <<: *VM_CHECK_MODE
- - <<: *SUPPORT_JOKE
- - <<: *CPDEBUG
- - <<: *WITH_COROUTINE_UCONTEXT
- - <<: *WITH_COROUTINE_COPY
- - <<: *TOKEN_THREADED_CODE
- - <<: *CALL_THREADED_CODE
- - <<: *NO_THREADED_CODE
allow_failures:
+ - name: arm32-linux
+ - name: arm64-linux
- name: s390x-linux
- - name: -fsanitize=address
- - name: -fsanitize=memory
- - name: -fsanitize=undefined
fast_finish: true
before_script:
- - date # Debugging "Permission defined" failure on darwin like https://travis-ci.org/ruby/ruby/jobs/508683759
- - dpkg --print-architecture
- - dpkg --print-foreign-architectures
- - setarch --list
- - echo JOBS=${JOBS} SETARCH=${SETARCH}
- - $SETARCH uname -a
- - $SETARCH uname -r
- rm -fr .ext autom4te.cache
- - echo $TERM
- |-
[ -d ~/.downloaded-cache ] ||
mkdir ~/.downloaded-cache
@@ -462,9 +217,9 @@ before_script:
- "> config.status"
- "> .rbconfig.time"
- sed -f tool/prereq.status template/Makefile.in common.mk > Makefile
- - date; make touch-unicode-files
- - date; make -s $JOBS $UPDATE_UNICODE up
- - date; make -s $JOBS srcs
+ - make touch-unicode-files
+ - make -s $JOBS $UPDATE_UNICODE up
+ - make -s $JOBS srcs
- rm -f config.status Makefile rbconfig.rb .rbconfig.time
- |-
if [ -d ~/config_2nd ]; then
@@ -476,7 +231,6 @@ before_script:
- chmod -R a-w .
- chmod -R u+w build config_1st config_2nd
- cd build
- - ccache --show-stats
- |-
case "$CC" in
gcc*) CC="ccache $CC${GCC_FLAGS:+ }$GCC_FLAGS -fno-diagnostics-color";;
@@ -496,20 +250,7 @@ before_script:
- mv ../config_2nd ~
- chmod u-w ..
- $SETARCH make -s $JOBS
- - |-
- date; : # Debugging "Permission defined" failure on darwin like https://travis-ci.org/ruby/ruby/jobs/508683759
- if ! make install; then
- if [ "$(uname)" = Darwin ]; then
- # Debugging "Permission defined" failure on darwin like https://travis-ci.org/ruby/ruby/jobs/508683759
- set -x
- date
- ./miniruby -e 'ARGV.map{|path|[path,File.stat(path)]}.sort_by{|path,st|st.mtime}.each{|path,st|p mtime:st.mtime.to_f, ctime:st.ctime.to_f, path:path}' .ext/.timestamp/.RUBYCOMMONDIR*time .ext/common/bigdecimal/*.rb ../ext/bigdecimal/lib/bigdecimal/*.rb . .. .ext .ext/common .ext/common/bigdecimal ext/bigdecimal ../ext ../ext/bigdecimal ../ext/bigdecimal/lib ../ext/bigdecimal/lib/bigdecimal
- make COPY='cp -f' install
- else
- exit 1
- fi
- fi
- - ccache --show-stats
+ - make -s install
- |-
[ -z "${GEMS_FOR_TEST}" ] ||
$RUBY_PREFIX/bin/gem install --no-document $GEMS_FOR_TEST
@@ -528,6 +269,7 @@ branches:
- ruby_2_4
- ruby_2_5
- ruby_2_6
+ - ruby_2_7
# We want to be notified when something happens.
notifications:
@@ -539,11 +281,10 @@ notifications:
template:
- "%{message} by @%{author}: See %{build_url}"
- slack:
- rooms:
- - secure: ah7UEHBvncXT7bM5mvYIQAO+tIyV/wl7nXLb7wQD16dO2v8Gragy0mWjB79Q09hrrMGmp6H9bCDpdGS80boIA5EHaHoG4QaP0i9bsSt8U2AMWgZtfyIgQKJ4H2kXkGlrjO+AXTgnIkP7LNjdgAVUUTGQPb26T3QmoN2Splt+fIQ= # ruby:<token>#alerts
- on_pull_requests: false
- on_success: change
+ webhooks:
+ urls:
+ - secure: mRsoS/UbqDkKkW5p3AEqM27d4SZnV6Gsylo3bm8T/deltQzTsGzZwrm7OIBXZv0UFZdE68XmPlyHfZFLSP2V9QZ7apXMf9/vw0GtcSe1gchtnjpAPF6lYBn7nMCbVPPx9cS0dwL927fjdRM1vj7IKZ2bk4F0lAJ25R25S6teqdk= # ruby-lang slack: ruby/simpler-alerts-bot (travis)
+ on_success: never
on_failure: always
email:
diff --git a/BSDL b/BSDL
index a009caefea..66d93598aa 100644
--- a/BSDL
+++ b/BSDL
@@ -4,10 +4,10 @@ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
+ notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
-notice, this list of conditions and the following disclaimer in the
-documentation and/or other materials provided with the distribution.
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
diff --git a/LEGAL b/LEGAL
index 565c4c9cde..2a7964e771 100644
--- a/LEGAL
+++ b/LEGAL
@@ -7,92 +7,118 @@ All the files in this distribution are covered under either the Ruby's
license (see the file COPYING) or public-domain except some files
mentioned below.
-ccan/build_assert/build_assert.h::
-ccan/check_type/check_type.h::
-ccan/container_of/container_of.h::
-ccan/str/str.h::
+[addr2line.c]
- These files are licensed under the CC0.
+ A part of this file is from FreeBSD.
>>>
- https://creativecommons.org/choose/zero/
+ Copyright (c) 1986, 1988, 1991, 1993::
+ The Regents of the University of California. All rights reserved.
-ccan/list/list.h::
+ (c) UNIX System Laboratories, Inc.
- This file is licensed under the MIT License.
+ All or some portions of this file are derived from material licensed
+ to the University of California by American Telephone and Telegraph
+ Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ the permission of UNIX System Laboratories, Inc.
- >>>
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-
-include/ruby/onigmo.h::
-include/ruby/oniguruma.h::
-regcomp.c::
-regenc.c::
-regenc.h::
-regerror.c::
-regexec.c::
-regint.h::
-regparse.c::
-regparse.h::
-enc/ascii.c::
-enc/big5.c::
-enc/cp949.c::
-enc/emacs_mule.c::
-enc/encdb.c::
-enc/euc_jp.c::
-enc/euc_kr.c::
-enc/euc_tw.c::
-enc/gb18030.c::
-enc/gb2312.c::
-enc/gbk.c::
-enc/iso_8859_1.c::
-enc/iso_8859_10.c::
-enc/iso_8859_11.c::
-enc/iso_8859_13.c::
-enc/iso_8859_14.c::
-enc/iso_8859_15.c::
-enc/iso_8859_16.c::
-enc/iso_8859_2.c::
-enc/iso_8859_3.c::
-enc/iso_8859_4.c::
-enc/iso_8859_5.c::
-enc/iso_8859_6.c::
-enc/iso_8859_7.c::
-enc/iso_8859_8.c::
-enc/iso_8859_9.c::
-enc/koi8_r.c::
-enc/koi8_u.c::
-enc/shift_jis.c::
-enc/unicode.c::
-enc/us_ascii.c::
-enc/utf_16be.c::
-enc/utf_16le.c::
-enc/utf_32be.c::
-enc/utf_32le.c::
-enc/utf_8.c::
-enc/windows_1251.c::
+ @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
+
+
+[ccan/build_assert/build_assert.h]
+[ccan/check_type/check_type.h]
+[ccan/container_of/container_of.h]
+[ccan/str/str.h]
+
+ These files are licensed under the {CC0}[https://creativecommons.org/choose/zero/].
+
+[ccan/list/list.h]
+
+ This file is licensed under the {MIT License}[rdoc-label:label-MIT+License].
+
+[coroutine]
+
+ Unless otherwise specified, these files are licensed under the
+ {MIT License}[rdoc-label:label-MIT+License].
+
+[include/ruby/onigmo.h]
+[include/ruby/oniguruma.h]
+[regcomp.c]
+[regenc.c]
+[regenc.h]
+[regerror.c]
+[regexec.c]
+[regint.h]
+[regparse.c]
+[regparse.h]
+[enc/ascii.c]
+[enc/big5.c]
+[enc/cp949.c]
+[enc/emacs_mule.c]
+[enc/encdb.c]
+[enc/euc_jp.c]
+[enc/euc_kr.c]
+[enc/euc_tw.c]
+[enc/gb18030.c]
+[enc/gb2312.c]
+[enc/gbk.c]
+[enc/iso_8859_1.c]
+[enc/iso_8859_10.c]
+[enc/iso_8859_11.c]
+[enc/iso_8859_13.c]
+[enc/iso_8859_14.c]
+[enc/iso_8859_15.c]
+[enc/iso_8859_16.c]
+[enc/iso_8859_2.c]
+[enc/iso_8859_3.c]
+[enc/iso_8859_4.c]
+[enc/iso_8859_5.c]
+[enc/iso_8859_6.c]
+[enc/iso_8859_7.c]
+[enc/iso_8859_8.c]
+[enc/iso_8859_9.c]
+[enc/koi8_r.c]
+[enc/koi8_u.c]
+[enc/shift_jis.c]
+[enc/unicode.c]
+[enc/us_ascii.c]
+[enc/utf_16be.c]
+[enc/utf_16le.c]
+[enc/utf_32be.c]
+[enc/utf_32le.c]
+[enc/utf_8.c]
+[enc/windows_1251.c]
+[enc/windows_31j.c]
Onigmo (Oniguruma-mod) LICENSE
>>>
- Copyright (c) 2002-2009 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- Copyright (c) 2011-2014 K.Takata <kentkt AT csc DOT jp>
+ Copyright (c) 2002-2009:: K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
+ Copyright (c) 2011-2014:: K.Takata <kentkt AT csc DOT jp>
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -119,7 +145,7 @@ enc/windows_1251.c::
Oniguruma LICENSE
>>>
- Copyright (c) 2002-2009 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
+ Copyright (c) 2002-2009:: K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -150,10 +176,69 @@ enc/windows_1251.c::
When this software is partly used or it is distributed with Ruby,
this of Ruby follows the license of Ruby.
-enc/trans/GB/GB12345%UCS.src::
-enc/trans/GB/UCS%GB12345.src::
-enc/trans/GB/GB2312%UCS.src::
-enc/trans/GB/UCS%GB2312.src::
+[enc/windows_1250.c]
+[enc/windows_1252.c]
+
+ >>>
+ Copyright (c) 2006-2007:: Byte <byte AT mail DOT kna DOT ru>
+ K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+[enc/cesu_8.c]
+[enc/windows_1253.c]
+[enc/windows_1254.c]
+[enc/windows_1257.c]
+
+ >>>
+ Copyright (c) 2002-2007:: K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+[enc/trans/GB/GB12345%UCS.src]
+[enc/trans/GB/UCS%GB12345.src]
+[enc/trans/GB/GB2312%UCS.src]
+[enc/trans/GB/UCS%GB2312.src]
These files have this explanatory texts.
@@ -165,12 +250,12 @@ enc/trans/GB/UCS%GB2312.src::
files for any particular purpose, and has ceased to publish the files many
years ago.
-enc/trans/JIS/JISX0201-KANA%UCS.src::
-enc/trans/JIS/JISX0208\@1990%UCS.src::
-enc/trans/JIS/JISX0212%UCS.src::
-enc/trans/JIS/UCS%JISX0201-KANA.src::
-enc/trans/JIS/UCS%JISX0208@1990.src::
-enc/trans/JIS/UCS%JISX0212.src::
+[enc/trans/JIS/JISX0201-KANA%UCS.src]
+[enc/trans/JIS/JISX0208\@1990%UCS.src]
+[enc/trans/JIS/JISX0212%UCS.src]
+[enc/trans/JIS/UCS%JISX0201-KANA.src]
+[enc/trans/JIS/UCS%JISX0208@1990.src]
+[enc/trans/JIS/UCS%JISX0212.src]
These files are copyrighted as the following.
@@ -179,49 +264,75 @@ enc/trans/JIS/UCS%JISX0212.src::
For terms of use, see http://www.unicode.org/terms_of_use.html
-enc/trans/JIS/JISX0213-1%UCS@BMP.src::
-enc/trans/JIS/JISX0213-1%UCS@SIP.src::
-enc/trans/JIS/JISX0213-2%UCS@BMP.src::
-enc/trans/JIS/JISX0213-2%UCS@SIP.src::
+[enc/trans/JIS/JISX0213-1%UCS@BMP.src]
+[enc/trans/JIS/JISX0213-1%UCS@SIP.src]
+[enc/trans/JIS/JISX0213-2%UCS@BMP.src]
+[enc/trans/JIS/JISX0213-2%UCS@SIP.src]
These files are copyrighted as the following.
>>>
- Copyright (C) 2001 earthian@tama.or.jp, All Rights Reserved.
- Copyright (C) 2001 I'O, All Rights Reserved.
- Copyright (C) 2006 Project X0213, All Rights Reserved.
+ Copyright (C) 2001:: earthian@tama.or.jp, All Rights Reserved.
+ Copyright (C) 2001:: I'O, All Rights Reserved.
+ Copyright (C) 2006:: Project X0213, All Rights Reserved.
You can use, modify, distribute this table freely.
-enc/trans/JIS/UCS@BMP%JISX0213-1.src::
-enc/trans/JIS/UCS@BMP%JISX0213-2.src::
-enc/trans/JIS/UCS@SIP%JISX0213-1.src::
-enc/trans/JIS/UCS@SIP%JISX0213-2.src::
+[enc/trans/JIS/UCS@BMP%JISX0213-1.src]
+[enc/trans/JIS/UCS@BMP%JISX0213-2.src]
+[enc/trans/JIS/UCS@SIP%JISX0213-1.src]
+[enc/trans/JIS/UCS@SIP%JISX0213-2.src]
These files are copyrighted as the following.
>>>
- Copyright (C) 2001 earthian@tama.or.jp, All Rights Reserved.
- Copyright (C) 2001 I'O, All Rights Reserved.
+ Copyright (C) 2001:: earthian@tama.or.jp, All Rights Reserved.
+ Copyright (C) 2001:: I'O, All Rights Reserved.
You can use, modify, distribute this table freely.
-configure::
+[enc/trans/ucm/glibc-BIG5-2.3.3.ucm]
+[enc/trans/ucm/glibc-BIG5HKSCS-2.3.3.ucm]
+
+ >>>
+ Copyright (C) 2001-2005:: International Business Machines
+ Corporation and others. All Rights Reserved.
+
+[enc/trans/ucm/windows-950-2000.ucm]
+[enc/trans/ucm/windows-950_hkscs-2001.ucm]
+
+ >>>
+ Copyright (C) 2001-2002:: International Business Machines
+ Corporation and others. All Rights Reserved.
+
+
+[configure]
This file is free software.
>>>
- Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+ Copyright (C) 1992-1996, 1998-2012:: Free Software Foundation, Inc.
This configure script is free software; the Free Software Foundation
gives unlimited permission to copy, distribute and modify it.
-tool/config.guess::
-tool/config.sub::
+[aclocal.m4]
+
+ This file is free software.
+
+ >>>
+ Copyright (C) 1996-2020:: Free Software Foundation, Inc.
+
+ This file is free software; the Free Software Foundation
+ gives unlimited permission to copy and/or distribute it,
+ with or without modifications, as long as this notice is preserved.
+
+[tool/config.guess]
+[tool/config.sub]
As long as you distribute these files with the file configure, they
are covered under the Ruby's license.
>>>
- Copyright 1992-2018 Free Software Foundation, Inc.
+ Copyright 1992-2018:: Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
@@ -243,14 +354,15 @@ tool/config.sub::
program. This Exception is an additional permission under section 7
of the GNU General Public License, version 3 ("GPLv3").
-parse.c::
+[parse.c]
+[parse.h]
- This file is licensed under the GPL, but is incorporated into Ruby and
+ These files are licensed under the GPL, but are incorporated into Ruby and
redistributed under the terms of the Ruby license, as permitted by the
exception to the GPL below.
>>>
- Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989-1990, 2000-2015, 2018:: Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -278,12 +390,12 @@ parse.c::
This special exception was added by the Free Software Foundation in
version 2.2 of Bison.
-missing/dtoa.c::
+[missing/dtoa.c]
This file is under these licenses.
>>>
- Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
+ Copyright (c) 1991, 2000, 2001:: by Lucent Technologies.
Permission to use, copy, modify, and distribute this software for any
purpose without fee is hereby granted, provided that this entire notice
@@ -297,8 +409,8 @@ missing/dtoa.c::
OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
>>>
- Copyright (c) 2004-2008 David Schultz <das@FreeBSD.ORG>
- All rights reserved.
+ Copyright (c) 2004-2008:: David Schultz <das@FreeBSD.ORG>
+ All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -321,23 +433,24 @@ missing/dtoa.c::
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-win32/win32.{c,h}::
+[win32/win32.c]
+[include/ruby/win32.h]
You can apply the Artistic License to these files. (or GPL,
alternatively)
>>>
- Copyright (c) 1993, Intergraph Corporation
+ Copyright (c) 1993:: Intergraph Corporation
You may distribute under the terms of either the GNU General Public
License or the Artistic License, as specified in the perl README file.
-missing/mt19937.c::
+[missing/mt19937.c]
This file is under the new-style BSD license.
>>>
- A C-program for MT19937, with initialization improved 2002/2/10.
+ A C-program for MT19937, with initialization improved 2002/2/10.::
Coded by Takuji Nishimura and Makoto Matsumoto.
This is a faster version by taking Shawn Cokus's optimization,
Matthe Bellew's simplification, Isaku Wada's real version.
@@ -345,8 +458,8 @@ missing/mt19937.c::
Before using, initialize the state by using init_genrand(seed)
or init_by_array(init_key, key_length).
- Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
- All rights reserved.
+ Copyright (C) 1997 - 2002:: Makoto Matsumoto and Takuji Nishimura,
+ All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -382,13 +495,13 @@ missing/mt19937.c::
The Wayback Machine url: http://web.archive.org/web/19990429082237/http://www.math.keio.ac.jp/matumoto/emt.html
-missing/procstat_vm.c::
+[missing/procstat_vm.c]
This file is under the new-style BSD license.
>>>
- Copyright (c) 2007 Robert N. M. Watson
- All rights reserved.
+ Copyright (c) 2007:: Robert N. M. Watson
+ All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -413,151 +526,69 @@ missing/procstat_vm.c::
$FreeBSD: head/usr.bin/procstat/procstat_vm.c 261780 2014-02-11 21:57:37Z jhb $
-vsnprintf.c::
+[vsnprintf.c]
- This file is under the old-style BSD license. Note that the
- paragraph 3 below is now null and void.
+ This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license].
>>>
- Copyright (c) 1990, 1993
+ Copyright (c) 1990, 1993::
The Regents of the University of California. All rights reserved.
This code is derived from software contributed to Berkeley by
Chris Torek.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-
- IMPORTANT NOTE:
- --------------
- From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
- paragraph 3 above is now null and void.
-
-st.c::
-strftime.c::
-include/ruby/st.h::
-missing/acosh.c::
-missing/alloca.c::
-missing/dup2.c::
-missing/erf.c::
-missing/finite.c::
-missing/hypot.c::
-missing/isinf.c::
-missing/isnan.c::
-missing/lgamma_r.c::
-missing/memcmp.c::
-missing/memmove.c::
-missing/strchr.c::
-missing/strerror.c::
-missing/strstr.c::
-missing/tgamma.c::
-ext/date/date_strftime.c::
-ext/digest/sha1/sha1.c::
-ext/digest/sha1/sha1.h::
-ext/sdbm/_sdbm.c::
-ext/sdbm/sdbm.h::
+[st.c]
+[strftime.c]
+[include/ruby/st.h]
+[missing/acosh.c]
+[missing/alloca.c]
+[missing/dup2.c]
+[missing/erf.c]
+[missing/finite.c]
+[missing/hypot.c]
+[missing/isinf.c]
+[missing/isnan.c]
+[missing/lgamma_r.c]
+[missing/memcmp.c]
+[missing/memmove.c]
+[missing/strchr.c]
+[missing/strerror.c]
+[missing/strstr.c]
+[missing/tgamma.c]
+[ext/date/date_strftime.c]
+[ext/digest/sha1/sha1.c]
+[ext/digest/sha1/sha1.h]
These files are all under public domain.
-missing/crypt.c::
+[missing/crypt.c]
- This file is under the old-style BSD license. Note that the
- paragraph 3 below is now null and void.
+ This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license].
>>>
- Copyright (c) 1989, 1993
+ Copyright (c) 1989, 1993::
The Regents of the University of California. All rights reserved.
This code is derived from software contributed to Berkeley by
Tom Truscott.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
+[missing/setproctitle.c]
- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-
-missing/setproctitle.c::
-
- This file is under the old-style BSD license. Note that the
- paragraph 3 below is now null and void.
+ This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license].
>>>
- Copyright 2003 Damien Miller
- Copyright (c) 1983, 1995-1997 Eric P. Allman
- Copyright (c) 1988, 1993
+ Copyright 2003:: Damien Miller
+ Copyright (c) 1983, 1995-1997:: Eric P. Allman
+ Copyright (c) 1988, 1993::
The Regents of the University of California. All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. Neither the name of the University nor the names of its contributors
- may be used to endorse or promote products derived from this software
- without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-
-missing/strlcat.c::
-missing/strlcpy.c::
+[missing/strlcat.c]
+[missing/strlcpy.c]
These files are under an ISC-style license.
>>>
- Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ Copyright (c) 1998, 2015:: Todd C. Miller <Todd.Miller@courtesan.com>
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@@ -571,26 +602,26 @@ missing/strlcpy.c::
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-missing/langinfo.c::
+[missing/langinfo.c]
This file is from http://www.cl.cam.ac.uk/~mgk25/ucs/langinfo.c.
Ruby uses a modified version. The file contains the following
author/copyright notice:
>>>
- Markus.Kuhn@cl.cam.ac.uk -- 2002-03-11
+ Markus.Kuhn@cl.cam.ac.uk -- 2002-03-11::
Permission to use, copy, modify, and distribute this software
for any purpose and without fee is hereby granted. The author
disclaims all warranties with regard to this software.
-ext/digest/md5/md5.c::
-ext/digest/md5/md5.h::
+[ext/digest/md5/md5.c]
+[ext/digest/md5/md5.h]
These files are under the following license. Ruby uses modified
versions of them.
>>>
- Copyright (C) 1999, 2000 Aladdin Enterprises. All rights reserved.
+ Copyright (C) 1999, 2000:: Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -611,8 +642,8 @@ ext/digest/md5/md5.h::
L. Peter Deutsch
ghost@aladdin.com
-ext/digest/rmd160/rmd160.c::
-ext/digest/rmd160/rmd160.h::
+[ext/digest/rmd160/rmd160.c]
+[ext/digest/rmd160/rmd160.h]
These files have the following copyright information, and by the
author we are allowed to use it under the new-style BSD license.
@@ -622,16 +653,16 @@ ext/digest/rmd160/rmd160.h::
(Arranged for libc by Todd C. Miller)
DATE:: 1 March 1996
- Copyright (c) Katholieke Universiteit Leuven
+ Copyright (c):: Katholieke Universiteit Leuven
1996, All Rights Reserved
-ext/digest/sha2/sha2.c::
-ext/digest/sha2/sha2.h::
+[ext/digest/sha2/sha2.c]
+[ext/digest/sha2/sha2.h]
These files are under the new-style BSD license.
>>>
- Copyright 2000 Aaron D. Gifford. All rights reserved.
+ Copyright 2000:: Aaron D. Gifford. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -657,12 +688,12 @@ ext/digest/sha2/sha2.h::
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-ext/json/generator/generator.c::
+[ext/json/generator/generator.c]
The file contains the following copyright notice.
>>>
- Copyright 2001-2004 Unicode, Inc.
+ Copyright 2001-2004:: Unicode, Inc.
Disclaimer::
@@ -682,15 +713,15 @@ ext/json/generator/generator.c::
for internal or external distribution as long as this notice
remains attached.
-ext/nkf/nkf-utf8/config.h::
-ext/nkf/nkf-utf8/nkf.c::
-ext/nkf/nkf-utf8/utf8tbl.c::
+[ext/nkf/nkf-utf8/config.h]
+[ext/nkf/nkf-utf8/nkf.c]
+[ext/nkf/nkf-utf8/utf8tbl.c]
These files are under the following license. So to speak, it is
copyrighted semi-public-domain software.
>>>
- Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
+ Copyright (C) 1987:: Fujitsu LTD. (Itaru ICHIKAWA)
Everyone is permitted to do anything on this program
including copying, modifying, improving,
@@ -700,14 +731,14 @@ ext/nkf/nkf-utf8/utf8tbl.c::
You don't have to ask before copying, redistribution or publishing.
THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
-ext/psych::
-test/psych::
+[ext/psych]
+[test/psych]
The files under these directories are under the following license, except for
ext/psych/yaml.
>>>
- Copyright 2009 Aaron Patterson, et al.
+ Copyright 2009:: Aaron Patterson, et al.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the 'Software'), to deal in
@@ -727,12 +758,12 @@ test/psych::
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-ext/psych/yaml::
+[ext/psych/yaml]
The files under this directory are under the following license.
>>>
- Copyright (c) 2006 Kirill Simonov
+ Copyright (c) 2006:: Kirill Simonov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
@@ -752,14 +783,28 @@ ext/psych/yaml::
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-ext/socket/addrinfo.h::
-ext/socket/getaddrinfo.c::
-ext/socket/getnameinfo.c::
+[ext/pty/pty.c]
+
+ >>>
+ C) Copyright 1998:: by Akinori Ito.
+
+ This software may be redistributed freely for this purpose, in full
+ or in part, provided that this entire copyright notice is included
+ on any copies of this software and applications and derivations thereof.
+
+ This software is provided on an "as is" basis, without warranty of any
+ kind, either expressed or implied, as to any matter including, but not
+ limited to warranty of fitness of purpose, or merchantability, or
+ results obtained from use of this software.
+
+[ext/socket/addrinfo.h]
+[ext/socket/getaddrinfo.c]
+[ext/socket/getnameinfo.c]
These files are under the new-style BSD license.
>>>
- Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ Copyright (C) 1995, 1996, 1997, 1998, and 1999:: WIDE Project.
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -786,16 +831,16 @@ ext/socket/getnameinfo.c::
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-ext/win32ole/win32ole.c::
+[ext/win32ole/win32ole.c]
You can apply the Artistic License to this file. (or GPL,
alternatively)
>>>
- (c) 1995 Microsoft Corporation. All rights reserved.
+ (c) 1995:: Microsoft Corporation. All rights reserved.
Developed by ActiveWare Internet Corp., http://www.ActiveWare.com
- Other modifications Copyright (c) 1997, 1998 by Gurusamy Sarathy
+ Other modifications Copyright (c) 1997, 1998:: by Gurusamy Sarathy
<gsar@umich.edu> and Jan Dubois <jan.dubois@ibm.net>
You may distribute under the terms of either the GNU General Public
@@ -804,20 +849,17 @@ ext/win32ole/win32ole.c::
The Wayback Machine url: http://web.archive.org/web/19970607104352/http://www.activeware.com:80/
-lib/rdoc/generator/template/darkfish/css/fonts.css::
-
- This file is licensed under the SIL Open Font License.
+[lib/rdoc/generator/template/darkfish/css/fonts.css]
- >>>
- http://scripts.sil.org/OFL
+ This file is licensed under the {SIL Open Font License}[http://scripts.sil.org/OFL].
-spec/mspec::
-spec/ruby::
+[spec/mspec]
+[spec/ruby]
The files under these directories are under the following license.
>>>
- Copyright (c) 2008 Engine Yard, Inc. All rights reserved.
+ Copyright (c) 2008:: Engine Yard, Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@@ -840,17 +882,17 @@ spec/ruby::
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
-lib/rubygems.rb::
-lib/rubygems::
-test/rubygems::
+[lib/rubygems.rb]
+[lib/rubygems]
+[test/rubygems]
RubyGems is under the following license.
>>>
RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim
Weirich and others. You can redistribute it and/or modify it under
- either the terms of the MIT license (see the file MIT.txt), or the
- conditions below:
+ either the terms of the {MIT license}[rdoc-label:label-MIT+License], or the conditions
+ below:
1. You may make and give away verbatim copies of the source form of the
software without restriction, provided that you duplicate all of the
@@ -901,20 +943,63 @@ test/rubygems::
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.
-lib/bundler::
-lib/bundler.rb::
-lib/bundler.gemspec::
-spec/bundler::
-man/bundle-*,gemfile.*::
+[lib/bundler]
+[lib/bundler.rb]
+[lib/bundler.gemspec]
+[spec/bundler]
+[man/bundle-*,gemfile.*]
Bundler is under the following license.
>>>
- Portions copyright (c) 2010 Andre Arko
- Portions copyright (c) 2009 Engine Yard
+ Portions copyright (c) 2010:: Andre Arko
+ Portions copyright (c) 2009:: Engine Yard
+
+ {MIT License}[rdoc-label:label-MIT+License]
+
+[lib/did_you_mean]
+[lib/did_you_mean.rb]
+[test/did_you_mean]
- MIT License::
+ did_you_mean is under the following license.
+ >>>
+ Copyright (c) 2014-2016 Yuki Nishijima
+
+ {MIT License}[rdoc-label:label-MIT+License]
+
+[benchmark/so_ackermann.rb]
+[benchmark/so_array.rb]
+[benchmark/so_binary_trees.rb]
+[benchmark/so_concatenate.rb]
+[benchmark/so_count_words.yml]
+[benchmark/so_exception.rb]
+[benchmark/so_fannkuch.rb]
+[benchmark/so_fasta.rb]
+[benchmark/so_k_nucleotide.yml]
+[benchmark/so_lists.rb]
+[benchmark/so_mandelbrot.rb]
+[benchmark/so_matrix.rb]
+[benchmark/so_meteor_contest.rb]
+[benchmark/so_nbody.rb]
+[benchmark/so_nested_loop.rb]
+[benchmark/so_nsieve.rb]
+[benchmark/so_nsieve_bits.rb]
+[benchmark/so_object.rb]
+[benchmark/so_partial_sums.rb]
+[benchmark/so_pidigits.rb]
+[benchmark/so_random.rb]
+[benchmark/so_reverse_complement.yml]
+[benchmark/so_sieve.rb]
+[benchmark/so_spectralnorm.rb]
+
+ These files are very old copy of then-called "The Great Computer Language
+ Shootout". LEGAL SITUATION OF THESE FILES ARE UNCLEAR because the original
+ site has been lost. Upstream diverged to delete several benchmarks listed
+ above.
+
+== MIT License
+>>>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
@@ -933,3 +1018,34 @@ man/bundle-*,gemfile.*::
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+== Old-style BSD license
+>>>
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+ IMPORTANT NOTE::
+
+ From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
+ paragraph 3 above is now null and void.
diff --git a/NEWS b/NEWS
deleted file mode 100644
index e1adb5115d..0000000000
--- a/NEWS
+++ /dev/null
@@ -1,826 +0,0 @@
-# -*- rdoc -*-
-
-= NEWS for Ruby 2.7.0
-
-This document is a list of user visible feature changes made between
-releases except for bug fixes.
-
-Note that each entry is kept so brief that no reason behind or reference
-information is supplied with. For a full list of changes with all
-sufficient information, see the ChangeLog file or Redmine
-(e.g. <tt>https://bugs.ruby-lang.org/issues/$FEATURE_OR_BUG_NUMBER</tt>).
-
-== Changes since the 2.6.0 release
-
-=== Language changes
-
-==== Pattern matching
-
-* Pattern matching is introduced as an experimental feature. [Feature #14912]
-
- case [0, [1, 2, 3]]
- in [a, [b, *c]]
- p a #=> 0
- p b #=> 1
- p c #=> [2, 3]
- end
-
- case {a: 0, b: 1}
- in {a: 0, x: 1}
- :unreachable
- in {a: 0, b: var}
- p var #=> 1
- end
-
- case -1
- in 0 then :unreachable
- in 1 then :unreachable
- end #=> NoMatchingPatternError
-
- json = <<END
- {
- "name": "Alice",
- "age": 30,
- "children": [{ "name": "Bob", "age": 2 }]
- }
- END
-
- JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: name, age: age}]}
-
- p name #=> "Bob"
- p age #=> 2
-
- JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: "Charlie", age: age}]}
- #=> NoMatchingPatternError
-
-* See the following slides for more details:
- * https://speakerdeck.com/k_tsj/pattern-matching-new-feature-in-ruby-2-dot-7
- * Note that the slides are slightly obsolete.
-
-* The warning against pattern matching can be suppressed with
- {-W:no-experimental option}[#label-Warning+option].
-
-==== The spec of keyword arguments is changed towards 3.0
-
-* Automatic conversion of keyword arguments and positional arguments is
- deprecated, and conversion will be removed in Ruby 3. [Feature #14183]
-
- * When a method call passes a Hash at the last argument, and when it
- passes no keywords, and when the called method accepts keywords,
- a warning is emitted. To continue treating the hash as keywords,
- add a double splat operator to avoid the warning and ensure
- correct behavior in Ruby 3.
-
- def foo(key: 42); end; foo({key: 42}) # warned
- def foo(**kw); end; foo({key: 42}) # warned
- def foo(key: 42); end; foo(**{key: 42}) # OK
- def foo(**kw); end; foo(**{key: 42}) # OK
-
- * When a method call passes keywords to a method that accepts keywords,
- but it does not pass enough required positional arguments, the
- keywords are treated as a final required positional argument, and a
- warning is emitted. Pass the argument as a hash instead of keywords
- to avoid the warning and ensure correct behavior in Ruby 3.
-
- def foo(h, **kw); end; foo(key: 42) # warned
- def foo(h, key: 42); end; foo(key: 42) # warned
- def foo(h, **kw); end; foo({key: 42}) # OK
- def foo(h, key: 42); end; foo({key: 42}) # OK
-
- * When a method accepts specific keywords but not a keyword splat, and
- a hash or keywords splat is passed to the method that includes both
- Symbol and non-Symbol keys, the hash will continue to be split, and
- a warning will be emitted. You will need to update the calling code
- to pass separate hashes to ensure correct behavior in Ruby 3.
-
- def foo(h={}, key: 42); end; foo("key" => 43, key: 42) # warned
- def foo(h={}, key: 42); end; foo({"key" => 43, key: 42}) # warned
- def foo(h={}, key: 42); end; foo({"key" => 43}, key: 42) # OK
-
- * If a method does not accept keywords, and is called with keywords,
- the keywords are still treated as a positional hash, with no warning.
- This behavior will continue to work in Ruby 3.
-
- def foo(opt={}); end; foo( key: 42 ) # OK
-
-* Non-symbols are allowed as keyword argument keys if the method accepts
- arbitrary keywords. [Feature #14183]
-
- * Non-Symbol keys in a keyword arguments hash were prohibited in 2.6.0,
- but are now allowed again. [Bug #15658]
-
- def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1}
-
-* <code>**nil</code> is allowed in method definitions to explicitly mark
- that the method accepts no keywords. Calling such a method with keywords
- will result in an ArgumentError. [Feature #14183]
-
- def foo(h, **nil); end; foo(key: 1) # ArgumentError
- def foo(h, **nil); end; foo(**{key: 1}) # ArgumentError
- def foo(h, **nil); end; foo("str" => 1) # ArgumentError
- def foo(h, **nil); end; foo({key: 1}) # OK
- def foo(h, **nil); end; foo({"str" => 1}) # OK
-
-* Passing an empty keyword splat to a method that does not accept keywords
- no longer passes an empty hash, unless the empty hash is necessary for
- a required parameter, in which case a warning will be emitted. Remove
- the double splat to continue passing a positional hash. [Feature #14183]
-
- h = {}; def foo(*a) a end; foo(**h) # []
- h = {}; def foo(a) a end; foo(**h) # {} and warning
- h = {}; def foo(*a) a end; foo(h) # [{}]
- h = {}; def foo(a) a end; foo(h) # {}
-
-* Above warnings can be suppressed also with {-W:no-deprecated option}[#label-Warning+option].
-
-==== Numbered parameters
-
-* Numbered parameters as default block parameters are introduced.
- [Feature #4475]
-
- [1, 2, 10].map { _1.to_s(16) } #=> ["1", "2", "a"]
- [[1, 2], [3, 4]].map { _1 + _2 } #=> [3, 7]
-
- You can still define a local variable named +_1+ and so on,
- and that is honored when present, but renders a warning.
-
- _1 = 0 #=> warning: `_1' is reserved for numbered parameter; consider another name
- [1].each { p _1 } # prints 0 instead of 1
-
-==== proc/lambda without block is deprecated
-
-* Proc.new and Kernel#proc with no block in a method called with a block is
- warned now.
-
- def foo
- proc
- end
- foo { puts "Hello" } #=> warning: Capturing the given block using Kernel#proc is deprecated; use `&block` instead
-
- This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
-
-* Kernel#lambda with no block in a method called with a block raises an exception.
-
- def bar
- lambda
- end
- bar { puts "Hello" } #=> tried to create Proc object without a block (ArgumentError)
-
-==== Other miscellaneous changes
-
-* A beginless range is experimentally introduced. It might be useful
- in +case+, new call-sequence of the <code>Comparable#clamp</code>,
- constants and DSLs. [Feature #14799]
-
- ary[..3] # identical to ary[0..3]
-
- case RUBY_VERSION
- when ..."2.4" then puts "EOL"
- # ...
- end
-
- age.clamp(..100)
-
- where(sales: ..100)
-
-* Setting <code>$;</code> to a non-nil value is warned now. [Feature #14240]
- Use of it in String#split is warned too.
- This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
-
-* Setting <code>$,</code> to a non-nil value is warned now. [Feature #14240]
- Use of it in Array#join is warned too.
- This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
-
-* Quoted here-document identifiers must end within the same line.
-
- <<"EOS
- " # This had been warned since 2.4; Now it raises a SyntaxError
- EOS
-
-* The flip-flop syntax deprecation is reverted. [Feature #5400]
-
-* Comment lines can be placed between fluent dot now.
-
- foo
- # .bar
- .baz # => foo.baz
-
-* Calling a private method with a literal +self+ as the receiver
- is now allowed. [Feature #11297] [Feature #16123]
-
-* Modifier rescue now operates the same for multiple assignment as single
- assignment. [Bug #8279]
-
- a, b = raise rescue [1, 2]
- # Previously parsed as: (a, b = raise) rescue [1, 2]
- # Now parsed as: a, b = (raise rescue [1, 2])
-
-* +yield+ in singleton class syntax is warned and will be deprecated later. [Feature #15575].
-
- def foo
- class << Object.new
- yield #=> warning: `yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575]
- end
- end
- foo { p :ok }
-
- This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
-
-* Argument forwarding by <code>(...)</code> is introduced. [Feature #16253]
-
- def foo(...)
- bar(...)
- end
-
- All arguments to +foo+ are forwarded to +bar+, including keyword and
- block arguments.
- Note that the parentheses are mandatory. <code>bar ...</code> is parsed
- as an endless range.
-
-* Access and setting of <code>$SAFE</code> is now always warned. <code>$SAFE</code>
- will become a normal global variable in Ruby 3.0. [Feature #16131]
-
-* <code>Object#{taint,untaint,trust,untrust}</code> and related functions in the C-API
- no longer have an effect (all objects are always considered untainted), and are now
- warned in verbose mode. This warning will be disabled even in non-verbose mode in
- Ruby 3.0, and the methods and C functions will be removed in Ruby 3.2. [Feature #16131]
-
-* Refinements take place at Object#method and Module#instance_method. [Feature #15373]
-
-=== Command line options
-
-==== Warning option
-
-The +-W+ option has been extended with a following +:+, to manage categorized
-warnings. [Feature #16345] [Feature #16420]
-
-* To suppress deprecation warnings:
-
- $ ruby -e '$; = ""'
- -e:1: warning: `$;' is deprecated
-
- $ ruby -W:no-deprecated -e '$; = //'
-
-* It works with the +RUBYOPT+ environment variable:
-
- $ RUBYOPT=-W:no-deprecated ruby -e '$; = //'
-
-* To suppress experimental feature warnings:
-
- $ ruby -e '0 in a'
- -e:1: warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!
-
- $ ruby -W:no-experimental -e '0 in a'
-
-* To suppress both by using +RUBYOPT+, set space separated values:
-
- $ RUBYOPT='-W:no-deprecated -W:no-experimental' ruby -e '($; = "") in a'
-
-See also Warning in {Core classes updates}[#label-Core+classes+updates+-28outstanding+ones+only-29].
-
-=== Core classes updates (outstanding ones only)
-
-Array::
-
- New methods::
-
- * Added Array#intersection. [Feature #16155]
-
- * Added Array#minmax, with a faster implementation than Enumerable#minmax. [Bug #15929]
-
-Comparable::
-
- Modified method::
-
- * Comparable#clamp now accepts a Range argument. [Feature #14784]
-
- -1.clamp(0..2) #=> 0
- 1.clamp(0..2) #=> 1
- 3.clamp(0..2) #=> 2
- # With beginless and endless ranges:
- -1.clamp(0..) #=> 0
- 3.clamp(..2) #=> 2
-
-
-Complex::
-
- New method::
-
- * Added Complex#<=>.
- So <code>0 <=> 0i</code> will not raise NoMethodError. [Bug #15857]
-
-Dir::
-
- Modified methods::
-
- * Dir.glob and Dir.[] no longer allow NUL-separated glob pattern.
- Use Array instead. [Feature #14643]
-
-Encoding::
-
- New encoding::
-
- * Added new encoding CESU-8. [Feature #15931]
-
-Enumerable::
-
- New methods::
-
- * Added Enumerable#filter_map. [Feature #15323]
-
- [1, 2, 3].filter_map {|x| x.odd? ? x.to_s : nil } #=> ["1", "3"]
-
- * Added Enumerable#tally. [Feature #11076]
-
- ["A", "B", "C", "B", "A"].tally #=> {"A"=>2, "B"=>2, "C"=>1}
-
-Enumerator::
-
- New methods::
-
- * Added Enumerator.produce to generate an Enumerator from any custom
- data transformation. [Feature #14781]
-
- require "date"
- dates = Enumerator.produce(Date.today, &:succ) #=> infinite sequence of dates
- dates.detect(&:tuesday?) #=> next Tuesday
-
- * Added Enumerator::Lazy#eager that generates a non-lazy enumerator
- from a lazy enumerator. [Feature #15901]
-
- a = %w(foo bar baz)
- e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager
- p e.class #=> Enumerator
- p e.map {|x| x + "?" } #=> ["FOO!?", "BAR!?", "BAZ!?"]
-
- * Added Enumerator::Yielder#to_proc so that a Yielder object
- can be directly passed to another method as a block
- argument. [Feature #15618]
-
-Fiber::
-
- New method::
-
- * Added Fiber#raise that behaves like Fiber#resume but raises an
- exception on the resumed fiber. [Feature #10344]
-
-File::
-
- Modified method::
-
- * File.extname now returns a dot string for names ending with a dot on
- non-Windows platforms. [Bug #15267]
-
- File.extname("foo.") #=> "."
-
-FrozenError::
-
- New method::
-
- * Added FrozenError#receiver to return the frozen object on which
- modification was attempted. To set this object when raising
- FrozenError in Ruby code, FrozenError.new accepts a +:receiver+
- option. [Feature #15751]
-
-GC::
-
- New method::
-
- * Added GC.compact method for compacting the heap.
- This function compacts live objects in the heap so that fewer pages may
- be used, and the heap may be more CoW (copy-on-write) friendly. [Feature #15626]
-
- Details on the algorithm and caveats can be found here:
- https://bugs.ruby-lang.org/issues/15626
-
-IO::
-
- New method::
-
- * Added IO#set_encoding_by_bom to check the BOM and set the external
- encoding. [Bug #15210]
-
-Integer::
-
- Modified method::
-
- * Integer#[] now supports range operations. [Feature #8842]
-
- 0b01001101[2, 4] #=> 0b0011
- 0b01001100[2..5] #=> 0b0011
- 0b01001100[2...6] #=> 0b0011
- # ^^^^
-
-Method::
-
- Modified method::
-
- * Method#inspect shows more information. [Feature #14145]
-
-Module::
-
- New methods::
-
- * Added Module#const_source_location to retrieve the location where a
- constant is defined. [Feature #10771]
-
- * Added Module#ruby2_keywords for marking a method as passing keyword
- arguments through a regular argument splat, useful when delegating
- all arguments to another method in a way that can be backwards
- compatible with older Ruby versions. [Bug #16154]
-
- Modified methods::
-
- * Module#autoload? now takes an +inherit+ optional argument, like
- Module#const_defined?. [Feature #15777]
-
- * Module#name now always returns a frozen String. The returned String is
- always the same for a given Module. This change is
- experimental. [Feature #16150]
-
-NilClass / TrueClass / FalseClass::
-
- Modified methods::
-
- * NilClass#to_s, TrueClass#to_s, and FalseClass#to_s now always return a
- frozen String. The returned String is always the same for each of these
- values. This change is experimental. [Feature #16150]
-
-ObjectSpace::WeakMap::
-
- Modified method::
-
- * ObjectSpace::WeakMap#[]= now accepts special objects as either key or
- values. [Feature #16035]
-
-Proc::
-
- New method::
-
- * Added Proc#ruby2_keywords for marking the proc as passing keyword
- arguments through a regular argument splat, useful when delegating
- all arguments to another method or proc in a way that can be backwards
- compatible with older Ruby versions. [Feature #16404]
-
-Range::
-
- New method::
-
- * Added Range#minmax, with a faster implementation than Enumerable#minmax.
- It returns a maximum that now corresponds to Range#max. [Bug #15807]
-
- Modified method::
-
- * Range#=== now uses Range#cover? for String arguments, too (in Ruby 2.6, it was
- changed from Range#include? for all types except strings). [Bug #15449]
-
-
-RubyVM::
-
- Removed method::
-
- * +RubyVM.resolve_feature_path+ moved to
- <code>$LOAD_PATH.resolve_feature_path</code>. [Feature #15903] [Feature #15230]
-
-String::
-
- Unicode::
-
- * Update Unicode version and Emoji version from 11.0.0 to
- 12.0.0. [Feature #15321]
-
- * Update Unicode version to 12.1.0, adding support for
- U+32FF SQUARE ERA NAME REIWA. [Feature #15195]
-
- * Update Unicode Emoji version to 12.1. [Feature #16272]
-
-Symbol::
-
- New methods::
-
- * Added Symbol#start_with? and Symbol#end_with? methods. [Feature #16348]
-
-Time::
-
- New methods::
-
- * Added Time#ceil method. [Feature #15772]
-
- * Added Time#floor method. [Feature #15653]
-
- Modified method::
-
- * Time#inspect is separated from Time#to_s and it shows
- the time's sub second. [Feature #15958]
-
-UnboundMethod::
-
- New method::
-
- * Added UnboundMethod#bind_call method. [Feature #15955]
-
- <code>umethod.bind_call(obj, ...)</code> is semantically equivalent
- to <code>umethod.bind(obj).call(...)</code>. This idiom is used in
- some libraries to call a method that is overridden. The added
- method does the same without allocation of an intermediate Method
- object.
-
- class Foo
- def add_1(x)
- x + 1
- end
- end
- class Bar < Foo
- def add_1(x) # override
- x + 2
- end
- end
-
- obj = Bar.new
- p obj.add_1(1) #=> 3
- p Foo.instance_method(:add_1).bind(obj).call(1) #=> 2
- p Foo.instance_method(:add_1).bind_call(obj, 1) #=> 2
-
-Warning::
-
- New methods::
-
- * Added Warning.[] and Warning.[]= to manage emitting/suppressing
- some categories of warnings. [Feature #16345] [Feature #16420]
-
-$LOAD_PATH::
-
- New method::
-
- * Added <code>$LOAD_PATH.resolve_feature_path</code>. [Feature #15903] [Feature #15230]
-
-=== Stdlib updates (outstanding ones only)
-
-Bundler::
-
- * Upgrade to Bundler 2.1.2.
- See https://github.com/bundler/bundler/releases/tag/v2.1.2
-
-CGI::
-
- * CGI.escapeHTML becomes 2~5x faster when there is at least one escaped character.
- See https://github.com/ruby/ruby/pull/2226
-
-CSV::
-
- * Upgrade to 3.1.2.
- See https://github.com/ruby/csv/blob/master/NEWS.md.
-
-Date::
-
- * Date.jisx0301, Date#jisx0301, and Date.parse support the new Japanese
- era. [Feature #15742]
-
-Delegator::
-
- * Object#DelegateClass accepts a block and module_evals it in the context
- of the returned class, similar to Class.new and Struct.new.
-
-ERB::
-
- * Prohibit marshaling ERB instance.
-
-IRB::
-
- * Introduce syntax highlighting inspired by the Pry gem to Binding#irb
- source lines, REPL input, and inspect output of some core-class objects.
-
- * Introduce multiline editing mode provided by Reline.
-
- * Show documentation when completion.
-
- * Enable auto indent and save/load history by default.
-
-JSON::
-
- * Upgrade to 2.3.0.
-
-Net::FTP::
-
- * Add Net::FTP#features to check available features, and Net::FTP#option to
- enable/disable each of them. [Feature #15964]
-
-Net::HTTP::
-
- * Add +ipaddr+ optional parameter to Net::HTTP#start to replace the address for
- the TCP/IP connection. [Feature #5180]
-
-Net::IMAP::
-
- * Add Server Name Indication (SNI) support. [Feature #15594]
-
-open-uri::
-
- * Warn open-uri's "open" method at Kernel.
- Use URI.open instead. [Misc #15893]
-
- * The default charset of "text/*" media type is UTF-8 instead of
- ISO-8859-1. [Bug #15933]
-
-OptionParser::
-
- * Now show "Did you mean?" for unknown options. [Feature #16256]
-
- test.rb:
-
- require "optparse"
- OptionParser.new do |opts|
- opts.on("-f", "--foo", "foo") {|v| }
- opts.on("-b", "--bar", "bar") {|v| }
- opts.on("-c", "--baz", "baz") {|v| }
- end.parse!
-
- example:
-
- $ ruby test.rb --baa
- Traceback (most recent call last):
- test.rb:7:in `<main>': invalid option: --baa (OptionParser::InvalidOption)
- Did you mean? baz
- bar
-
-Pathname::
-
- * Pathname.glob now delegates 3 arguments to Dir.glob
- to accept +base+ keyword. [Feature #14405]
-
-Racc::
-
- * Merge 1.4.15 from upstream repository and added cli of racc.
-
-Reline::
-
- * New stdlib that is compatible with the readline stdlib but is
- implemented in pure Ruby. It also provides a multiline editing mode.
-
-REXML::
-
- * Upgrade to 3.2.3.
- See https://github.com/ruby/rexml/blob/master/NEWS.md.
-
-RSS::
-
- * Upgrade to RSS 0.2.8.
- See https://github.com/ruby/rss/blob/master/NEWS.md.
-
-RubyGems::
-
- * Upgrade to RubyGems 3.1.2.
- * https://github.com/rubygems/rubygems/releases/tag/v3.1.0
- * https://github.com/rubygems/rubygems/releases/tag/v3.1.1
- * https://github.com/rubygems/rubygems/releases/tag/v3.1.2
-
-StringScanner::
-
- * Upgrade to 1.0.3.
- See https://github.com/ruby/strscan/blob/master/NEWS.md.
-
-=== Compatibility issues (excluding feature bug fixes)
-
-* The following libraries are no longer bundled gems.
- Install corresponding gems to use these features.
- * CMath (cmath gem)
- * Scanf (scanf gem)
- * Shell (shell gem)
- * Synchronizer (sync gem)
- * ThreadsWait (thwait gem)
- * E2MM (e2mmap gem)
-
-Proc::
- * The Proc#to_s format was changed. [Feature #16101]
-
-Range::
- * Range#minmax used to iterate on the range to determine the maximum.
- It now uses the same algorithm as Range#max. In rare cases (e.g.
- ranges of Floats or Strings), this may yield different results. [Bug #15807]
-
-=== Stdlib compatibility issues (excluding feature bug fixes)
-
-* Promote stdlib to default gems
- * The following default gems were published on rubygems.org
- * benchmark
- * cgi
- * delegate
- * getoptlong
- * net-pop
- * net-smtp
- * open3
- * pstore
- * readline
- * readline-ext
- * singleton
- * The following default gems were only promoted at ruby-core,
- but not yet published on rubygems.org.
- * monitor
- * observer
- * timeout
- * tracer
- * uri
- * yaml
-* The <tt>did_you_mean</tt> gem has been promoted up to a default gem from a bundled gem
-
-pathname::
-
- * Kernel#Pathname when called with a Pathname argument now returns
- the argument instead of creating a new Pathname. This is more
- similar to other Kernel methods, but can break code that modifies
- the return value and expects the argument not to be modified.
-
-profile.rb, Profiler__::
-
- * Removed from standard library. It was unmaintained since Ruby 2.0.0.
-
-=== C API updates
-
-* Many <code>*_kw</code> functions have been added for setting whether
- the final argument being passed should be treated as keywords. You
- may need to switch to these functions to avoid keyword argument
- separation warnings, and to ensure correct behavior in Ruby 3.
-
-* The <code>:</code> character in rb_scan_args format string is now
- treated as keyword arguments. Passing a positional hash instead of
- keyword arguments will emit a deprecation warning.
-
-* C API declarations with +ANYARGS+ are changed not to use +ANYARGS+.
- See https://github.com/ruby/ruby/pull/2404
-
-=== Implementation improvements
-
-Fiber::
-
- * Allow selecting different coroutine implementations by using
- +--with-coroutine=+, e.g.
-
- $ ./configure --with-coroutine=ucontext
- $ ./configure --with-coroutine=copy
-
- * Replace previous stack cache with fiber pool cache. The fiber pool
- allocates many stacks in a single memory region. Stack allocation
- becomes O(log N) and fiber creation is amortized O(1). Around 10x
- performance improvement was measured in micro-benchmarks.
- https://github.com/ruby/ruby/pull/2224
-
-File::
- * File.realpath now uses realpath(3) on many platforms, which can
- significantly improve performance. [Feature #15797]
-
-Hash::
- * Change data structure of small Hash objects. [Feature #15602]
-
-Monitor::
- * Monitor class is written in C-extension. [Feature #16255]
-
-Thread::
-
- * VM stack memory allocation is now combined with native thread stack,
- improving thread allocation performance and reducing allocation related
- failures. Around 10x performance improvement was measured in micro-benchmarks.
-
-JIT::
-
- * JIT-ed code is recompiled to less-optimized code when an optimization assumption is invalidated.
-
- * Method inlining is performed when a method is considered as pure.
- This optimization is still experimental and many methods are NOT considered as pure yet.
-
- * The default value of +--jit-max-cache+ is changed from 1,000 to 100.
-
- * The default value of +--jit-min-calls+ is changed from 5 to 10,000.
-
-RubyVM::
-
- * Per-call-site method cache, which has been there since around 1.9, was
- improved: cache hit rate raised from 89% to 94%.
- See https://github.com/ruby/ruby/pull/2583
-
-RubyVM::InstructionSequence::
-
- * RubyVM::InstructionSequence#to_binary method generates compiled binary.
- The binary size is reduced. [Feature #16163]
-
-=== Miscellaneous changes
-
-* Support for IA64 architecture has been removed. Hardware for testing was
- difficult to find, native fiber code is difficult to implement, and it added
- non-trivial complexity to the interpreter. [Feature #15894]
-
-* Require compilers to support C99. [Misc #15347]
-
- * Details of our dialect: https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/C99
-
-* Ruby's upstream repository is changed from Subversion to Git.
-
- * https://git.ruby-lang.org/ruby.git
-
- * RUBY_REVISION class is changed from Integer to String.
-
- * RUBY_DESCRIPTION includes Git revision instead of Subversion's one.
-
-* Support built-in methods in Ruby with the <code>_\_builtin_</code> syntax. [Feature #16254]
-
- Some methods are defined in *.rb (such as trace_point.rb).
- For example, it is easy to define a method which accepts keyword arguments.
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000000..2dcfacb6e2
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,820 @@
+# NEWS for Ruby 3.0.0
+
+This document is a list of user visible feature changes
+since the **2.7.0** release, except for bug fixes.
+
+Note that each entry is kept so brief that no reason behind or reference
+information is supplied with. For a full list of changes with all
+sufficient information, see the ChangeLog file or Redmine
+(e.g. `https://bugs.ruby-lang.org/issues/$FEATURE_OR_BUG_NUMBER`).
+
+## Language changes
+
+* Keyword arguments are now separated from positional arguments.
+ Code that resulted in deprecation warnings in Ruby 2.7 will now
+ result in ArgumentError or different behavior. [[Feature #14183]]
+
+* Procs accepting a single rest argument and keywords are no longer
+ subject to autosplatting. This now matches the behavior of Procs
+ accepting a single rest argument and no keywords.
+ [[Feature #16166]]
+
+ ```ruby
+ pr = proc{|*a, **kw| [a, kw]}
+
+ pr.call([1])
+ # 2.7 => [[1], {}]
+ # 3.0 => [[[1]], {}]
+
+ pr.call([1, {a: 1}])
+ # 2.7 => [[1], {:a=>1}] # and deprecation warning
+ # 3.0 => [[[1, {:a=>1}]], {}]
+ ```
+
+* Arguments forwarding (`...`) now supports leading arguments.
+ [[Feature #16378]]
+
+ ```ruby
+ def method_missing(meth, ...)
+ send(:"do_#{meth}", ...)
+ end
+ ```
+
+* Pattern matching (`case/in`) is no longer experimental. [[Feature #17260]]
+
+* One-line pattern matching is redesigned. [EXPERIMENTAL]
+
+ * `=>` is added. It can be used like a rightward assignment.
+ [[Feature #17260]]
+
+ ```ruby
+ 0 => a
+ p a #=> 0
+
+ {b: 0, c: 1} => {b:}
+ p b #=> 0
+ ```
+
+ * `in` is changed to return `true` or `false`. [[Feature #17371]]
+
+ ```ruby
+ # version 3.0
+ 0 in 1 #=> false
+
+ # version 2.7
+ 0 in 1 #=> raise NoMatchingPatternError
+ ```
+
+* Find-pattern is added. [EXPERIMENTAL]
+ [[Feature #16828]]
+
+ ```ruby
+ case ["a", 1, "b", "c", 2, "d", "e", "f", 3]
+ in [*pre, String => x, String => y, *post]
+ p pre #=> ["a", 1]
+ p x #=> "b"
+ p y #=> "c"
+ p post #=> [2, "d", "e", "f", 3]
+ end
+ ```
+
+* Endless method definition is added. [EXPERIMENTAL]
+ [[Feature #16746]]
+
+ ```ruby
+ def square(x) = x * x
+ ```
+
+* Interpolated String literals are no longer frozen when
+ `# frozen-string-literal: true` is used. [[Feature #17104]]
+
+* Magic comment `shareable_constant_value` added to freeze constants.
+ See {Magic Comments}[rdoc-ref:doc/syntax/comments.rdoc@Magic+Comments] for more details.
+ [[Feature #17273]]
+
+* A {static analysis}[rdoc-label:label-Static+analysis] foundation is
+ introduced.
+ * {RBS}[rdoc-label:label-RBS] is introduced. It is a type definition
+ language for Ruby programs.
+ * {TypeProf}[rdoc-label:label-TypeProf] is experimentally bundled. It is a
+ type analysis tool for Ruby programs.
+
+* Deprecation warnings are no longer shown by default (since Ruby 2.7.2).
+ Turn them on with `-W:deprecated` (or with `-w` to show other warnings too).
+ [[Feature #16345]]
+
+* $SAFE and $KCODE are now normal global variables with no special behavior.
+ C-API methods related to $SAFE have been removed.
+ [[Feature #16131]] [[Feature #17136]]
+
+* yield in singleton class definitions in methods is now a SyntaxError
+ instead of a warning. yield in a class definition outside of a method
+ is now a SyntaxError instead of a LocalJumpError. [[Feature #15575]]
+
+* When a class variable is overtaken by the same definition in an
+ ancestor class/module, a RuntimeError is now raised (previously,
+ it only issued a warning in verbose mode). Additionally, accessing a
+ class variable from the toplevel scope is now a RuntimeError.
+ [[Bug #14541]]
+
+* Assigning to a numbered parameter is now a SyntaxError instead of
+ a warning.
+
+## Command line options
+
+### `--help` option
+
+When the environment variable `RUBY_PAGER` or `PAGER` is present and has
+a non-empty value, and the standard input and output are tty, the `--help`
+option shows the help message via the pager designated by the value.
+[[Feature #16754]]
+
+### `--backtrace-limit` option
+
+The `--backtrace-limit` option limits the maximum length of a backtrace.
+[[Feature #8661]]
+
+## Core classes updates
+
+Outstanding ones only.
+
+* Array
+
+ * The following methods now return Array instances instead of
+ subclass instances when called on subclass instances:
+ [[Bug #6087]]
+
+ * Array#drop
+ * Array#drop_while
+ * Array#flatten
+ * Array#slice!
+ * Array#slice / Array#[]
+ * Array#take
+ * Array#take_while
+ * Array#uniq
+ * Array#*
+
+ * Can be sliced with Enumerator::ArithmeticSequence
+
+ ```ruby
+ dirty_data = ['--', 'data1', '--', 'data2', '--', 'data3']
+ dirty_data[(1..).step(2)] # take each second element
+ # => ["data1", "data2", "data3"]
+ ```
+
+* Binding
+
+ * Binding#eval when called with one argument will use "(eval)"
+ for `__FILE__` and 1 for `__LINE__` in the evaluated code.
+ [[Bug #4352]] [[Bug #17419]]
+
+* ConditionVariable
+
+ * ConditionVariable#wait may now invoke the `block`/`unblock` scheduler
+ hooks in a non-blocking context. [[Feature #16786]]
+
+* Dir
+
+ * Dir.glob and Dir.[] now sort the results by default, and
+ accept the `sort:` keyword option. [[Feature #8709]]
+
+* ENV
+
+ * ENV.except has been added, which returns a hash excluding the
+ given keys and their values. [[Feature #15822]]
+
+ * Windows: Read ENV names and values as UTF-8 encoded Strings
+ [[Feature #12650]]
+
+* Encoding
+
+ * Added new encoding IBM720. [[Feature #16233]]
+
+ * Changed default for Encoding.default_external to UTF-8 on Windows
+ [[Feature #16604]]
+
+* Fiber
+
+ * Fiber.new(blocking: true/false) allows you to create non-blocking
+ execution contexts. [[Feature #16786]]
+
+ * Fiber#blocking? tells whether the fiber is non-blocking. [[Feature #16786]]
+
+ * Fiber#backtrace and Fiber#backtrace_locations provide per-fiber backtrace.
+ [[Feature #16815]]
+
+ * The limitation of Fiber#transfer is relaxed. [[Bug #17221]]
+
+* GC
+
+ * GC.auto_compact= and GC.auto_compact have been added to control
+ when compaction runs. Setting `auto_compact=` to true will cause
+ compaction to occur during major collections. At the moment,
+ compaction adds significant overhead to major collections, so please
+ test first! [[Feature #17176]]
+
+* Hash
+
+ * Hash#transform_keys and Hash#transform_keys! now accept a hash that maps
+ keys to new keys. [[Feature #16274]]
+
+ * Hash#except has been added, which returns a hash excluding the
+ given keys and their values. [[Feature #15822]]
+
+* IO
+
+ * IO#nonblock? now defaults to `true`. [[Feature #16786]]
+
+ * IO#wait_readable, IO#wait_writable, IO#read, IO#write and other
+ related methods (e.g. IO#puts, IO#gets) may invoke the scheduler hook
+ `#io_wait(io, events, timeout)` in a non-blocking execution context.
+ [[Feature #16786]]
+
+* Kernel
+
+ * Kernel#clone when called with the `freeze: false` keyword will call
+ `#initialize_clone` with the `freeze: false` keyword.
+ [[Bug #14266]]
+
+ * Kernel#clone when called with the `freeze: true` keyword will call
+ `#initialize_clone` with the `freeze: true` keyword, and will
+ return a frozen copy even if the receiver is unfrozen.
+ [[Feature #16175]]
+
+ * Kernel#eval when called with two arguments will use "(eval)"
+ for `__FILE__` and 1 for `__LINE__` in the evaluated code.
+ [[Bug #4352]]
+
+ * Kernel#lambda now warns if called without a literal block.
+ [[Feature #15973]]
+
+ * Kernel.sleep invokes the scheduler hook `#kernel_sleep(...)` in a
+ non-blocking execution context. [[Feature #16786]]
+
+* Module
+
+ * Module#include and Module#prepend now affect classes and modules
+ that have already included or prepended the receiver, mirroring the
+ behavior if the arguments were included in the receiver before
+ the other modules and classes included or prepended the receiver.
+ [[Feature #9573]]
+
+ ```ruby
+ class C; end
+ module M1; end
+ module M2; end
+ C.include M1
+ M1.include M2
+ p C.ancestors #=> [C, M1, M2, Object, Kernel, BasicObject]
+ ```
+
+ * Module#public, Module#protected, Module#private, Module#public_class_method,
+ Module#private_class_method, toplevel "private" and "public" methods
+ now accept single array argument with a list of method names. [[Feature #17314]]
+
+ * Module#attr_accessor, Module#attr_reader, Module#attr_writer and Module#attr
+ methods now return an array of defined method names as symbols.
+ [[Feature #17314]]
+
+ * Module#alias_method now returns the defined alias as a symbol.
+ [[Feature #17314]]
+
+* Mutex
+
+ * `Mutex` is now acquired per-`Fiber` instead of per-`Thread`. This change
+ should be compatible for essentially all usages and avoids blocking when
+ using a scheduler. [[Feature #16792]]
+
+* Proc
+
+ * Proc#== and Proc#eql? are now defined and will return true for
+ separate Proc instances if the procs were created from the same block.
+ [[Feature #14267]]
+
+* Queue / SizedQueue
+
+ * Queue#pop, SizedQueue#push and related methods may now invoke the
+ `block`/`unblock` scheduler hooks in a non-blocking context.
+ [[Feature #16786]]
+
+* Ractor
+
+ * New class added to enable parallel execution. See rdoc-ref:ractor.md for
+ more details.
+
+* Random
+
+ * `Random::DEFAULT` now refers to the `Random` class instead of being a `Random` instance,
+ so it can work with `Ractor`.
+ [[Feature #17322]]
+
+ * `Random::DEFAULT` is deprecated since its value is now confusing and it is no longer global,
+ use `Kernel.rand`/`Random.rand` directly, or create a `Random` instance with `Random.new` instead.
+ [[Feature #17351]]
+
+
+* String
+
+ * The following methods now return or yield String instances
+ instead of subclass instances when called on subclass instances:
+ [[Bug #10845]]
+
+ * String#*
+ * String#capitalize
+ * String#center
+ * String#chomp
+ * String#chop
+ * String#delete
+ * String#delete_prefix
+ * String#delete_suffix
+ * String#downcase
+ * String#dump
+ * String#each_char
+ * String#each_grapheme_cluster
+ * String#each_line
+ * String#gsub
+ * String#ljust
+ * String#lstrip
+ * String#partition
+ * String#reverse
+ * String#rjust
+ * String#rpartition
+ * String#rstrip
+ * String#scrub
+ * String#slice!
+ * String#slice / String#[]
+ * String#split
+ * String#squeeze
+ * String#strip
+ * String#sub
+ * String#succ / String#next
+ * String#swapcase
+ * String#tr
+ * String#tr_s
+ * String#upcase
+
+* Symbol
+
+ * Symbol#to_proc now returns a lambda Proc. [[Feature #16260]]
+
+ * Symbol#name has been added, which returns the name of the symbol
+ if it is named. The returned string is frozen. [[Feature #16150]]
+
+* Fiber
+
+ * Introduce Fiber.set_scheduler for intercepting blocking operations and
+ Fiber.scheduler for accessing the current scheduler. See
+ rdoc-ref:fiber.md for more details about what operations are supported and
+ how to implement the scheduler hooks. [[Feature #16786]]
+
+ * Fiber.blocking? tells whether the current execution context is
+ blocking. [[Feature #16786]]
+
+ * Thread#join invokes the scheduler hooks `block`/`unblock` in a
+ non-blocking execution context. [[Feature #16786]]
+
+* Thread
+
+ * Thread.ignore_deadlock accessor has been added for disabling the
+ default deadlock detection, allowing the use of signal handlers to
+ break deadlock. [[Bug #13768]]
+
+* Warning
+
+ * Warning#warn now supports a category keyword argument.
+ [[Feature #17122]]
+
+## Stdlib updates
+
+Outstanding ones only.
+
+* BigDecimal
+
+ * Update to BigDecimal 3.0.0
+
+ * This version is Ractor compatible.
+
+* Bundler
+
+ * Update to Bundler 2.2.3
+
+* CGI
+
+ * Update to 0.2.0
+
+ * This version is Ractor compatible.
+
+* CSV
+
+ * Update to CSV 3.1.9
+
+* Date
+
+ * Update to Date 3.1.1
+
+ * This version is Ractor compatible.
+
+* Digest
+
+ * Update to Digest 3.0.0
+
+ * This version is Ractor compatible.
+
+* Etc
+
+ * Update to Etc 1.2.0
+
+ * This version is Ractor compatible.
+
+* Fiddle
+
+ * Update to Fiddle 1.0.5
+
+* IRB
+
+ * Update to IRB 1.2.6
+
+* JSON
+
+ * Update to JSON 2.5.0
+
+ * This version is Ractor compatible.
+
+* Set
+
+ * Update to set 1.0.0
+
+ * SortedSet has been removed for dependency and performance reasons.
+
+ * Set#join is added as a shorthand for `.to_a.join`.
+
+ * Set#<=> is added.
+
+* Socket
+
+ * Add :connect_timeout to TCPSocket.new [[Feature #17187]]
+
+* Net::HTTP
+
+ * Net::HTTP#verify_hostname= and Net::HTTP#verify_hostname have been
+ added to skip hostname verification. [[Feature #16555]]
+
+ * Net::HTTP.get, Net::HTTP.get_response, and Net::HTTP.get_print
+ can take the request headers as a Hash in the second argument when the
+ first argument is a URI. [[Feature #16686]]
+
+* Net::SMTP
+
+ * Add SNI support.
+
+ * Net::SMTP.start arguments are keyword arguments.
+
+ * TLS should not check the host name by default.
+
+* OpenStruct
+
+ * Initialization is no longer lazy. [[Bug #12136]]
+
+ * Builtin methods can now be overridden safely. [[Bug #15409]]
+
+ * Implementation uses only methods ending with `!`.
+
+ * Ractor compatible.
+
+ * Improved support for YAML. [[Bug #8382]]
+
+ * Use officially discouraged. Read OpenStruct@Caveats section.
+
+* Pathname
+
+ * Ractor compatible.
+
+* Psych
+
+ * Update to Psych 3.3.0
+
+ * This version is Ractor compatible.
+
+* Reline
+
+ * Update to Reline 0.1.5
+
+* RubyGems
+
+ * Update to RubyGems 3.2.3
+
+* StringIO
+
+ * Update to StringIO 3.0.0
+
+ * This version is Ractor compatible.
+
+* StringScanner
+
+ * Update to StringScanner 3.0.0
+
+ * This version is Ractor compatible.
+
+## Compatibility issues
+
+Excluding feature bug fixes.
+
+* Regexp literals and all Range objects are frozen. [[Feature #8948]] [[Feature #16377]] [[Feature #15504]]
+
+ ```ruby
+ /foo/.frozen? #=> true
+ (42...).frozen? # => true
+ ```
+
+* EXPERIMENTAL: Hash#each consistently yields a 2-element array. [[Bug #12706]]
+
+ * Now `{ a: 1 }.each(&->(k, v) { })` raises an ArgumentError
+ due to lambda's arity check.
+
+* When writing to STDOUT redirected to a closed pipe, no broken pipe
+ error message will be shown now. [[Feature #14413]]
+
+* `TRUE`/`FALSE`/`NIL` constants are no longer defined.
+
+* Integer#zero? overrides Numeric#zero? for optimization. [[Misc #16961]]
+
+* Enumerable#grep and Enumerable#grep_v when passed a Regexp and no block no longer modify
+ Regexp.last_match. [[Bug #17030]]
+
+* Requiring 'open-uri' no longer redefines `Kernel#open`.
+ Call `URI.open` directly or `use URI#open` instead. [[Misc #15893]]
+
+* SortedSet has been removed for dependency and performance reasons.
+
+## Stdlib compatibility issues
+
+* Default gems
+
+ * The following libraries are promoted to default gems from stdlib.
+
+ * English
+ * abbrev
+ * base64
+ * drb
+ * debug
+ * erb
+ * find
+ * net-ftp
+ * net-http
+ * net-imap
+ * net-protocol
+ * open-uri
+ * optparse
+ * pp
+ * prettyprint
+ * resolv-replace
+ * resolv
+ * rinda
+ * set
+ * securerandom
+ * shellwords
+ * tempfile
+ * tmpdir
+ * time
+ * tsort
+ * un
+ * weakref
+
+ * The following extensions are promoted to default gems from stdlib.
+
+ * digest
+ * io-nonblock
+ * io-wait
+ * nkf
+ * pathname
+ * syslog
+ * win32ole
+
+* Bundled gems
+
+ * net-telnet and xmlrpc have been removed from the bundled gems.
+ If you are interested in maintaining them, please comment on
+ your plan to https://github.com/ruby/xmlrpc
+ or https://github.com/ruby/net-telnet.
+
+* SDBM has been removed from the Ruby standard library. [[Bug #8446]]
+
+ * The issues of sdbm will be handled at https://github.com/ruby/sdbm
+
+* WEBrick has been removed from the Ruby standard library. [[Feature #17303]]
+
+ * The issues of WEBrick will be handled at https://github.com/ruby/webrick
+
+## C API updates
+
+* C API functions related to $SAFE have been removed.
+ [[Feature #16131]]
+
+* C API header file `ruby/ruby.h` was split. [[GH-2991]]
+
+ This should have no impact on extension libraries,
+ but users might experience slow compilations.
+
+* Memory view interface [EXPERIMENTAL]
+
+ * The memory view interface is a C-API set to exchange a raw memory area,
+ such as a numeric array or a bitmap image, between extension libraries.
+ The extension libraries can share also the metadata of the memory area
+ that consists of the shape, the element format, and so on.
+ Using these kinds of metadata, the extension libraries can share even
+ a multidimensional array appropriately.
+ This feature is designed by referring to Python's buffer protocol.
+ [[Feature #13767]] [[Feature #14722]]
+
+* Ractor related C APIs are introduced (experimental) in "include/ruby/ractor.h".
+
+## Implementation improvements
+
+* New method cache mechanism for Ractor. [[Feature #16614]]
+
+ * Inline method caches pointed from ISeq can be accessed by multiple Ractors
+ in parallel and synchronization is needed even for method caches. However,
+ such synchronization can be overhead so introducing new inline method cache
+ mechanisms, (1) Disposable inline method cache (2) per-Class method cache
+ and (3) new invalidation mechanism. (1) can avoid per-method call
+ synchronization because it only uses atomic operations.
+ See the ticket for more details.
+
+* The number of hashes allocated when using a keyword splat in
+ a method call has been reduced to a maximum of 1, and passing
+ a keyword splat to a method that accepts specific keywords
+ does not allocate a hash.
+
+* `super` is optimized when the same type of method is called in the previous call
+ if it's not refinements or an attr reader or writer.
+
+### JIT
+
+* Performance improvements of JIT-ed code
+
+ * Microarchitectural optimizations
+
+ * Native functions shared by multiple methods are deduplicated on JIT compaction.
+
+ * Decrease code size of hot paths by some optimizations and partitioning cold paths.
+
+ * Instance variables
+
+ * Eliminate some redundant checks.
+
+ * Skip checking a class and a object multiple times in a method when possible.
+
+ * Optimize accesses in some core classes like Hash and their subclasses.
+
+ * Method inlining support for some C methods
+
+ * `Kernel`: `#class`, `#frozen?`
+
+ * `Integer`: `#-@`, `#~`, `#abs`, `#bit_length`, `#even?`, `#integer?`, `#magnitude`,
+ `#odd?`, `#ord`, `#to_i`, `#to_int`, `#zero?`
+
+ * `Struct`: reader methods for 10th or later members
+
+ * Constant references are inlined.
+
+ * Always generate appropriate code for `==`, `nil?`, and `!` calls depending on
+ a receiver class.
+
+ * Reduce the number of PC accesses on branches and method returns.
+
+ * Optimize C method calls a little.
+
+* Compilation process improvements
+
+ * It does not keep temporary files in /tmp anymore.
+
+ * Throttle GC and compaction of JIT-ed code.
+
+ * Avoid GC-ing JIT-ed code when not necessary.
+
+ * GC-ing JIT-ed code is executed in a background thread.
+
+ * Reduce the number of locks between Ruby and JIT threads.
+
+## Static analysis
+
+### RBS
+
+* RBS is a new language for type definition of Ruby programs.
+ It allows writing types of classes and modules with advanced
+ types including union types, overloading, generics, and
+ _interface types_ for duck typing.
+
+* Ruby ships with type definitions for core/stdlib classes.
+
+* `rbs` gem is bundled to load and process RBS files.
+
+### TypeProf
+
+* TypeProf is a type analysis tool for Ruby code based on abstract interpretation.
+
+ * It reads non-annotated Ruby code, tries inferring its type signature, and prints
+ the analysis result in RBS format.
+
+ * Though it supports only a subset of the Ruby language yet, we will continuously
+ improve the coverage of language features, analysis performance, and usability.
+
+```ruby
+# test.rb
+def foo(x)
+ if x > 10
+ x.to_s
+ else
+ nil
+ end
+end
+
+foo(42)
+```
+
+```
+$ typeprof test.rb
+# Classes
+class Object
+ def foo : (Integer) -> String?
+end
+```
+
+## Miscellaneous changes
+
+* Methods using `ruby2_keywords` will no longer keep empty keyword
+ splats, those are now removed just as they are for methods not
+ using `ruby2_keywords`.
+
+* When an exception is caught in the default handler, the error
+ message and backtrace are printed in order from the innermost.
+ [[Feature #8661]]
+
+* Accessing an uninitialized instance variable no longer emits a
+ warning in verbose mode. [[Feature #17055]]
+
+[Bug #4352]: https://bugs.ruby-lang.org/issues/4352
+[Bug #6087]: https://bugs.ruby-lang.org/issues/6087
+[Bug #8382]: https://bugs.ruby-lang.org/issues/8382
+[Bug #8446]: https://bugs.ruby-lang.org/issues/8446
+[Feature #8661]: https://bugs.ruby-lang.org/issues/8661
+[Feature #8709]: https://bugs.ruby-lang.org/issues/8709
+[Feature #8948]: https://bugs.ruby-lang.org/issues/8948
+[Feature #9573]: https://bugs.ruby-lang.org/issues/9573
+[Bug #10845]: https://bugs.ruby-lang.org/issues/10845
+[Bug #12136]: https://bugs.ruby-lang.org/issues/12136
+[Feature #12650]: https://bugs.ruby-lang.org/issues/12650
+[Bug #12706]: https://bugs.ruby-lang.org/issues/12706
+[Feature #13767]: https://bugs.ruby-lang.org/issues/13767
+[Bug #13768]: https://bugs.ruby-lang.org/issues/13768
+[Feature #14183]: https://bugs.ruby-lang.org/issues/14183
+[Bug #14266]: https://bugs.ruby-lang.org/issues/14266
+[Feature #14267]: https://bugs.ruby-lang.org/issues/14267
+[Feature #14413]: https://bugs.ruby-lang.org/issues/14413
+[Bug #14541]: https://bugs.ruby-lang.org/issues/14541
+[Feature #14722]: https://bugs.ruby-lang.org/issues/14722
+[Bug #15409]: https://bugs.ruby-lang.org/issues/15409
+[Feature #15504]: https://bugs.ruby-lang.org/issues/15504
+[Feature #15575]: https://bugs.ruby-lang.org/issues/15575
+[Feature #15822]: https://bugs.ruby-lang.org/issues/15822
+[Misc #15893]: https://bugs.ruby-lang.org/issues/15893
+[Feature #15921]: https://bugs.ruby-lang.org/issues/15921
+[Feature #15973]: https://bugs.ruby-lang.org/issues/15973
+[Feature #16131]: https://bugs.ruby-lang.org/issues/16131
+[Feature #16150]: https://bugs.ruby-lang.org/issues/16150
+[Feature #16166]: https://bugs.ruby-lang.org/issues/16166
+[Feature #16175]: https://bugs.ruby-lang.org/issues/16175
+[Feature #16233]: https://bugs.ruby-lang.org/issues/16233
+[Feature #16260]: https://bugs.ruby-lang.org/issues/16260
+[Feature #16274]: https://bugs.ruby-lang.org/issues/16274
+[Feature #16345]: https://bugs.ruby-lang.org/issues/16345
+[Feature #16377]: https://bugs.ruby-lang.org/issues/16377
+[Feature #16378]: https://bugs.ruby-lang.org/issues/16378
+[Feature #16555]: https://bugs.ruby-lang.org/issues/16555
+[Feature #16604]: https://bugs.ruby-lang.org/issues/16604
+[Feature #16614]: https://bugs.ruby-lang.org/issues/16614
+[Feature #16686]: https://bugs.ruby-lang.org/issues/16686
+[Feature #16746]: https://bugs.ruby-lang.org/issues/16746
+[Feature #16754]: https://bugs.ruby-lang.org/issues/16754
+[Feature #16786]: https://bugs.ruby-lang.org/issues/16786
+[Feature #16792]: https://bugs.ruby-lang.org/issues/16792
+[Feature #16815]: https://bugs.ruby-lang.org/issues/16815
+[Feature #16828]: https://bugs.ruby-lang.org/issues/16828
+[Misc #16961]: https://bugs.ruby-lang.org/issues/16961
+[Bug #17030]: https://bugs.ruby-lang.org/issues/17030
+[Feature #17055]: https://bugs.ruby-lang.org/issues/17055
+[Feature #17104]: https://bugs.ruby-lang.org/issues/17104
+[Feature #17122]: https://bugs.ruby-lang.org/issues/17122
+[Feature #17136]: https://bugs.ruby-lang.org/issues/17136
+[Feature #17176]: https://bugs.ruby-lang.org/issues/17176
+[Feature #17187]: https://bugs.ruby-lang.org/issues/17187
+[Bug #17221]: https://bugs.ruby-lang.org/issues/17221
+[Feature #17260]: https://bugs.ruby-lang.org/issues/17260
+[Feature #17273]: https://bugs.ruby-lang.org/issues/17273
+[Feature #17303]: https://bugs.ruby-lang.org/issues/17303
+[Feature #17314]: https://bugs.ruby-lang.org/issues/17314
+[Feature #17322]: https://bugs.ruby-lang.org/issues/17322
+[Feature #17351]: https://bugs.ruby-lang.org/issues/17351
+[Feature #17371]: https://bugs.ruby-lang.org/issues/17371
+[Bug #17419]: https://bugs.ruby-lang.org/issues/17419
+[GH-2991]: https://github.com/ruby/ruby/pull/2991
diff --git a/README.ja.md b/README.ja.md
index 4e1e6b9d87..6663b94680 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -1,10 +1,10 @@
[![Build Status](https://travis-ci.org/ruby/ruby.svg?branch=master)](https://travis-ci.org/ruby/ruby)
[![Build status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
-![](https://github.com/ruby/ruby/workflows/Cygwin/badge.svg)
-![](https://github.com/ruby/ruby/workflows/macOS/badge.svg)
-![](https://github.com/ruby/ruby/workflows/MJIT/badge.svg)
-![](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)
-![](https://github.com/ruby/ruby/workflows/Windows/badge.svg)
+[![Actions Status](https://github.com/ruby/ruby/workflows/macOS/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"macOS")
+[![Actions Status](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW")
+[![Actions Status](https://github.com/ruby/ruby/workflows/MJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MJIT")
+[![Actions Status](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu")
+[![Actions Status](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
# Rubyとは
@@ -52,11 +52,11 @@ Rubyリポジトリの本来のmasterは https://git.ruby-lang.org/ruby.git に
### Subversion
-古いRubyのバージョンのソースコードは次のコマンドで取得できます.
+古いRubyのバージョンのソースコードは次のコマンドでも取得できます.
$ svn co https://svn.ruby-lang.org/repos/ruby/branches/ruby_2_6/ ruby
-他に開発中のブランチの一覧は次のコマンドで見られます.
+他のブランチの一覧は次のコマンドで見られます.
$ svn ls https://svn.ruby-lang.org/repos/ruby/branches/
@@ -71,38 +71,33 @@ https://www.ruby-lang.org/
## メーリングリスト
-Rubyのメーリングリストがあります.参加希望の方は
-
-mailto:ruby-list-request@ruby-lang.org
-
-まで本文に
+Rubyのメーリングリストがあります.参加希望の方は [ruby-list-request@ruby-lang.org] まで本文に
subscribe
と書いて送って下さい.
-Ruby開発者向けメーリングリストもあります.こちらではrubyのバグ,将来の仕様拡張など実装上の問題について議論されています. 参加希望の方は
-
-mailto:ruby-dev-request@ruby-lang.org
-
-までruby-listと同様の方法でメールしてください.
+Ruby開発者向けメーリングリストもあります.こちらではrubyのバグ,将来の仕様拡張など実装上の問題について議論されています.
+参加希望の方は [ruby-dev-request@ruby-lang.org] までruby-listと同様の方法でメールしてください.
Ruby拡張モジュールについて話し合うruby-extメーリングリストと数学関係の話題について話し合うruby-mathメーリングリストと
英語でrubyについて話し合うruby-talkメーリングリストもあります.参加方法はどれも同じです.
+[ruby-list-request@ruby-lang.org]: mailto:ruby-list-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe
+[ruby-dev-request@ruby-lang.org]: mailto:ruby-dev-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe
+
## コンパイル・インストール
以下の手順で行ってください.
-1. もし `configure` ファイルが見つからない,もしくは `configure.ac` より古いようなら, `autoconf` を実行して
- 新しく `configure` を生成する
+1. (Gitリポジトリから取得したソースをビルドする場合) `./autogen.sh` を実行して新しく `configure` を生成する
2. `configure` を実行して `Makefile` などを生成する
環境によってはデフォルトのCコンパイラ用オプションが付きます. `configure` オプションで `optflags=..`
`warnflags=..` 等で上書きできます.
-3. (必要ならば)`defines.h` を編集する
+3. (必要ならば)`include/ruby/defines.h` を編集する
多分,必要無いと思います.
diff --git a/README.md b/README.md
index 1e935095c6..bd7c7813a7 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
[![Build Status](https://travis-ci.org/ruby/ruby.svg?branch=master)](https://travis-ci.org/ruby/ruby)
[![Build status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
-![](https://github.com/ruby/ruby/workflows/Cygwin/badge.svg)
-![](https://github.com/ruby/ruby/workflows/macOS/badge.svg)
-![](https://github.com/ruby/ruby/workflows/MJIT/badge.svg)
-![](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)
-![](https://github.com/ruby/ruby/workflows/Windows/badge.svg)
+[![Actions Status](https://github.com/ruby/ruby/workflows/macOS/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"macOS")
+[![Actions Status](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW")
+[![Actions Status](https://github.com/ruby/ruby/workflows/MJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MJIT")
+[![Actions Status](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu")
+[![Actions Status](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
# What's Ruby
@@ -24,8 +24,8 @@ It is simple, straightforward, and extensible.
* Garbage Collection
* Dynamic Loading of Object Files (on some architectures)
* Highly Portable (works on many Unix-like/POSIX compatible platforms as
- well as Windows, macOS, Haiku, etc.) cf.
- https://github.com/ruby/ruby/blob/master/doc/contributing.rdoc#platform-maintainers
+ well as Windows, macOS, etc.) cf.
+ https://github.com/ruby/ruby/blob/master/doc/contributing.rdoc#label-Platform+Maintainers
## How to get Ruby
@@ -51,7 +51,8 @@ if you are a committer.
### Subversion
-Stable branches for older Ruby versions can be checked out with the following command:
+Stable branches for older Ruby versions can be checked out with also the
+following command:
$ svn co https://svn.ruby-lang.org/repos/ruby/branches/ruby_2_6/ ruby
@@ -71,16 +72,17 @@ send the following phrase:
subscribe
-in the mail body (not subject) to the address
-[ruby-talk-request@ruby-lang.org](mailto:ruby-talk-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe).
+in the mail body (not subject) to the address [ruby-talk-request@ruby-lang.org].
+
+[ruby-talk-request@ruby-lang.org]: mailto:ruby-talk-request@ruby-lang.org?subject=Join%20Ruby%20Mailing%20List&body=subscribe
## How to compile and install
1. If you want to use Microsoft Visual C++ to compile Ruby, read
[win32/README.win32](win32/README.win32) instead of this document.
-2. If `./configure` does not exist or is older than `configure.ac`, run
- `autoconf` to (re)generate configure.
+2. Run `./autogen.sh` to generate configure, when you build the source checked
+ out from the Git repository.
3. Run `./configure`, which will generate `config.h` and `Makefile`.
@@ -88,7 +90,7 @@ in the mail body (not subject) to the address
environment. Specify `optflags=..` and `warnflags=..` as necessary to
override them.
-4. Edit `defines.h` if you need. Usually this step will not be needed.
+4. Edit `include/ruby/defines.h` if you need. Usually this step will not be needed.
5. Remove comment mark(`#`) before the module names from `ext/Setup` (or add
module names if not present), if you want to link modules statically.
@@ -108,12 +110,7 @@ in the mail body (not subject) to the address
interpreter works well. If you see the message "`check succeeded`", your
Ruby works as it should (hopefully).
-8. Optionally, run `make update-gems` and `make extract-gems`.
-
- If you want to install bundled gems, run `make update-gems` and
- `make extract-gems` before running `make install`.
-
-9. Run '`make install`'.
+8. Run '`make install`'.
This command will create the following directories and install files into
them.
diff --git a/aclocal.m4 b/aclocal.m4
index ed7d14ef63..e69de29bb2 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,47 +0,0 @@
-# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
-
-# Copyright (C) 1996-2018 Free Software Foundation, Inc.
-
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE.
-
-m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
-m4_include([tool/m4/_colorize_result_prepare.m4])
-m4_include([tool/m4/ac_msg_result.m4])
-m4_include([tool/m4/colorize_result.m4])
-m4_include([tool/m4/ruby_append_option.m4])
-m4_include([tool/m4/ruby_append_options.m4])
-m4_include([tool/m4/ruby_check_builtin_func.m4])
-m4_include([tool/m4/ruby_check_builtin_setjmp.m4])
-m4_include([tool/m4/ruby_check_printf_prefix.m4])
-m4_include([tool/m4/ruby_check_setjmp.m4])
-m4_include([tool/m4/ruby_check_signedness.m4])
-m4_include([tool/m4/ruby_check_sizeof.m4])
-m4_include([tool/m4/ruby_check_sysconf.m4])
-m4_include([tool/m4/ruby_cppoutfile.m4])
-m4_include([tool/m4/ruby_decl_attribute.m4])
-m4_include([tool/m4/ruby_default_arch.m4])
-m4_include([tool/m4/ruby_define_if.m4])
-m4_include([tool/m4/ruby_defint.m4])
-m4_include([tool/m4/ruby_dtrace_available.m4])
-m4_include([tool/m4/ruby_dtrace_postprocess.m4])
-m4_include([tool/m4/ruby_func_attribute.m4])
-m4_include([tool/m4/ruby_mingw32.m4])
-m4_include([tool/m4/ruby_prepend_option.m4])
-m4_include([tool/m4/ruby_prog_gnu_ld.m4])
-m4_include([tool/m4/ruby_replace_funcs.m4])
-m4_include([tool/m4/ruby_replace_type.m4])
-m4_include([tool/m4/ruby_rm_recursive.m4])
-m4_include([tool/m4/ruby_setjmp_type.m4])
-m4_include([tool/m4/ruby_stack_grow_direction.m4])
-m4_include([tool/m4/ruby_try_cflags.m4])
-m4_include([tool/m4/ruby_try_ldflags.m4])
-m4_include([tool/m4/ruby_type_attribute.m4])
-m4_include([tool/m4/ruby_universal_arch.m4])
-m4_include([tool/m4/ruby_werror_flag.m4])
diff --git a/addr2line.c b/addr2line.c
index 283382f51d..0029cffbca 100644
--- a/addr2line.c
+++ b/addr2line.c
@@ -13,7 +13,7 @@
#pragma clang diagnostic ignored "-Wgcc-compat"
#endif
-#include "ruby/config.h"
+#include "ruby/internal/config.h"
#include "ruby/defines.h"
#include "ruby/missing.h"
#include "addr2line.h"
@@ -25,11 +25,7 @@
#include <libproc.h>
#endif
-#ifdef HAVE_STDBOOL_H
-#include <stdbool.h>
-#else
-#include "missing/stdbool.h"
-#endif
+#include "ruby/internal/stdbool.h"
#if defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)
@@ -441,7 +437,8 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line,
addr += a;
break;
case DW_LNS_fixed_advance_pc:
- a = *(unsigned char *)p++;
+ a = *(uint16_t *)p;
+ p += sizeof(uint16_t);
addr += a;
break;
case DW_LNS_set_prologue_end:
@@ -530,13 +527,25 @@ append_obj(obj_info_t **objp)
}
#ifdef USE_ELF
+/* Ideally we should check 4 paths to follow gnu_debuglink:
+ *
+ * - /usr/lib/debug/.build-id/ab/cdef1234.debug
+ * - /usr/bin/ruby.debug
+ * - /usr/bin/.debug/ruby.debug
+ * - /usr/lib/debug/usr/bin/ruby.debug.
+ *
+ * but we handle only two cases for now as the two formats are
+ * used by some linux distributions.
+ *
+ * See GDB's info for detail.
+ * https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
+ */
+
+// check the path pattern of "/usr/lib/debug/usr/bin/ruby.debug"
static void
follow_debuglink(const char *debuglink, int num_traces, void **traces,
obj_info_t **objp, line_info_t *lines, int offset)
{
- /* Ideally we should check 4 paths to follow gnu_debuglink,
- but we handle only one case for now as this format is used
- by some linux distributions. See GDB's info for detail. */
static const char global_debug_dir[] = "/usr/lib/debug";
const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
char *p;
@@ -563,6 +572,37 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces,
o2->path = o1->path;
fill_lines(num_traces, traces, 0, objp, lines, offset);
}
+
+// check the path pattern of "/usr/lib/debug/.build-id/ab/cdef1234.debug"
+static void
+follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_traces, void **traces,
+ obj_info_t **objp, line_info_t *lines, int offset)
+{
+ static const char global_debug_dir[] = "/usr/lib/debug/.build-id/";
+ const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
+ char *p;
+ obj_info_t *o1 = *objp, *o2;
+ size_t i;
+
+ if (PATH_MAX < global_debug_dir_len + 1 + build_id_size * 2 + 6) return;
+
+ memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
+ p = binary_filename + global_debug_dir_len;
+ for (i = 0; i < build_id_size; i++) {
+ static const char tbl[] = "0123456789abcdef";
+ unsigned char n = build_id[i];
+ *p++ = tbl[n / 16];
+ *p++ = tbl[n % 16];
+ if (i == 0) *p++ = '/';
+ }
+ strcpy(p, ".debug");
+
+ append_obj(objp);
+ o2 = *objp;
+ o2->base_addr = o1->base_addr;
+ o2->path = o1->path;
+ fill_lines(num_traces, traces, 0, objp, lines, offset);
+}
#endif
enum
@@ -918,6 +958,7 @@ debug_info_reader_init(DebugInfoReader *reader, obj_info_t *obj)
reader->p = obj->debug_info.ptr;
reader->pend = obj->debug_info.ptr + obj->debug_info.size;
reader->debug_line_cu_end = obj->debug_line.ptr;
+ reader->current_low_pc = 0;
}
static void
@@ -1621,6 +1662,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
ElfW(Ehdr) *ehdr;
ElfW(Shdr) *shdr, *shstr_shdr;
ElfW(Shdr) *gnu_debuglink_shdr = NULL;
+ ElfW(Shdr) *note_gnu_build_id = NULL;
int fd;
off_t filesize;
char *file;
@@ -1693,6 +1735,11 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
/* if (!strcmp(section_name, ".dynsym")) */
dynsym_shdr = shdr + i;
break;
+ case SHT_NOTE:
+ if (!strcmp(section_name, ".note.gnu.build-id")) {
+ note_gnu_build_id = shdr + i;
+ }
+ break;
case SHT_PROGBITS:
if (!strcmp(section_name, ".gnu_debuglink")) {
gnu_debuglink_shdr = shdr + i;
@@ -1808,6 +1855,13 @@ use_symtab:
num_traces, traces,
objp, lines, offset);
}
+ if (note_gnu_build_id && check_debuglink) {
+ ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
+ const char *build_id = (char *)(nhdr + 1) + nhdr->n_namesz;
+ follow_debuglink_build_id(build_id, nhdr->n_descsz,
+ num_traces, traces,
+ objp, lines, offset);
+ }
goto finish;
}
@@ -2050,11 +2104,15 @@ fail:
* and returns strlen(binary_filename).
* it is NUL terminated.
*/
-#if defined(__linux__)
+#if defined(__linux__) || defined(__NetBSD__)
static ssize_t
main_exe_path(void)
{
-# define PROC_SELF_EXE "/proc/self/exe"
+# if defined(__linux__)
+# define PROC_SELF_EXE "/proc/self/exe"
+# elif defined(__NetBSD__)
+# define PROC_SELF_EXE "/proc/curproc/exe"
+# endif
ssize_t len = readlink(PROC_SELF_EXE, binary_filename, PATH_MAX);
if (len < 0) return 0;
binary_filename[len] = 0;
diff --git a/addr2line.h b/addr2line.h
index 4f6cf179ef..f09b665800 100644
--- a/addr2line.h
+++ b/addr2line.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_ADDR2LINE_H
+#define RUBY_ADDR2LINE_H
/**********************************************************************
addr2line.h -
@@ -8,9 +10,6 @@
**********************************************************************/
-#ifndef RUBY_ADDR2LINE_H
-#define RUBY_ADDR2LINE_H
-
#if (defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H))
void
diff --git a/appveyor.yml b/appveyor.yml
index d13ec885d1..5ad4972f19 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,11 +1,14 @@
---
version: '{build}'
-shallow_clone: true
+init:
+ - git config --global user.name git
+ - git config --global user.email svn-admin@ruby-lang.org
+clone_depth: 10
platform:
- x64
environment:
ruby_version: "24-%Platform%"
- zlib_version: "1.2.13"
+ zlib_version: "1.2.12"
matrix:
- build: vs
vs: 120
@@ -44,13 +47,15 @@ for:
- echo>> Makefile BUILTIN_ENCOBJS=nul
- type win32\Makefile.sub >> Makefile
- nmake %mflags% touch-unicode-files
- - nmake %mflags% %UPDATE_UNICODE% up incs
+ - nmake %mflags% %UPDATE_UNICODE% incs
+ - nmake %mflags% extract-extlibs
- del Makefile
- mkdir \usr\local\bin
- mkdir \usr\local\include
- mkdir \usr\local\lib
- - curl -fsSL -o zlib%zlib_version:.=%.zip --retry 10 https://zlib.net/zlib%zlib_version:.=%.zip
- - 7z x -o%APPVEYOR_BUILD_FOLDER%\ext\zlib zlib%zlib_version:.=%.zip
+ - SET ZLIB_ZIP=.downloaded-cache\zlib%zlib_version:.=%.zip
+ - if not exist %ZLIB_ZIP% curl -fsSL -o %ZLIB_ZIP% --retry 10 https://zlib.net/zlib%zlib_version:.=%.zip
+ - 7z x -aos -o%APPVEYOR_BUILD_FOLDER%\ext\zlib %ZLIB_ZIP%
- for %%I in (%OPENSSL_DIR%\*.dll) do mklink /h \usr\local\bin\%%~nxI %%I
- attrib +r /s /d
- mkdir %Platform%-mswin_%vs%
@@ -72,23 +77,20 @@ for:
- nmake -l "TESTOPTS=-v --timeout-scale=3.0 --excludes=../test/excludes/_appveyor" test-all TESTS="../test/win32ole ../test/ruby/test_bignum.rb ../test/ruby/test_syntax.rb ../test/open-uri/test_open-uri.rb ../test/rubygems/test_bundled_ca.rb"
- nmake -l test-spec MSPECOPT=-fs # not using `-j` because sometimes `mspec -j` silently dies on Windows
notifications:
- # Using "Webhook" with templated body to skip notification on Pull Request
- provider: Webhook
method: POST
url:
- secure: iMINHMS0nZabaDsxN9omRDsekxzVvAAzEq5ev7lN6vb+gUETT+rbDKLGxBxBpEpxlnPlLdzroIJ+DTKlwfJA8VkGawTn9EXNsucH0OkSf2M= # AppVeyor CI
+ secure: CcFlJNDJ/a6to7u3Z4Fnz6dScEPNx7hTha2GkSRlV+1U6dqmxY/7uBcLXYb9gR3jfQk6w+2o/HrjNAyXMNGU/JOka3s2WRI4VKitzM+lQ08owvJIh0R7LxrGH0J2e81U # ruby-lang slack: ruby/simpler-alerts-bot
body: >-
{{^isPullRequest}}
{
- "attachments": [
- {
- "text": "Build <{{buildUrl}}|#{{buildVersion}}> (<{{commitUrl}}|{{commitId}}>) of {{repositoryName}}@{{branch}} by {{commitAuthor}} {{status}}",
- "color": "{{#passed}}good{{/passed}}{{#failed}}danger{{/failed}}"
- }
- ],
- "channel": "#alerts"
+ "ci": "AppVeyor CI",
+ "env": "Visual Studio 2013 / 2015",
+ "url": "{{buildUrl}}",
+ "commit": "{{commitId}}",
+ "branch": "{{branch}}"
}
{{/isPullRequest}}
on_build_success: false
on_build_failure: true
- on_build_status_changed: true
+ on_build_status_changed: false
diff --git a/array.c b/array.c
index 90fa2e06d6..b48a6431e7 100644
--- a/array.c
+++ b/array.c
@@ -10,16 +10,29 @@
Copyright (C) 2000 Information-technology Promotion Agency, Japan
**********************************************************************/
+
+#include "debug_counter.h"
+#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/compar.h"
+#include "internal/enum.h"
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/proc.h"
+#include "internal/rational.h"
+#include "internal/vm.h"
+#include "probes.h"
#include "ruby/encoding.h"
-#include "ruby/util.h"
#include "ruby/st.h"
-#include "probes.h"
-#include "id.h"
-#include "debug_counter.h"
+#include "ruby/util.h"
#include "transient_heap.h"
-#include "internal.h"
+#include "builtin.h"
#if !ARRAY_DEBUG
+# undef NDEBUG
# define NDEBUG
#endif
#include "ruby_assert.h"
@@ -33,12 +46,14 @@ VALUE rb_cArray;
#define ARY_MAX_SIZE (LONG_MAX / (int)sizeof(VALUE))
#define SMALL_ARRAY_LEN 16
+RBIMPL_ATTR_MAYBE_UNUSED()
static int
should_be_T_ARRAY(VALUE ary)
{
return RB_TYPE_P(ary, T_ARRAY);
}
+RBIMPL_ATTR_MAYBE_UNUSED()
static int
should_not_be_shared_and_embedded(VALUE ary)
{
@@ -204,9 +219,11 @@ ary_verify_(VALUE ary, const char *file, int line)
#endif
}
+#if USE_TRANSIENT_HEAP
if (RARRAY_TRANSIENT_P(ary)) {
assert(rb_transient_heap_managed_ptr_p(RARRAY_CONST_PTR_TRANSIENT(ary)));
}
+#endif
rb_transient_heap_verify();
@@ -545,34 +562,33 @@ rb_ary_modify_check(VALUE ary)
}
void
-rb_ary_modify(VALUE ary)
+rb_ary_cancel_sharing(VALUE ary)
{
- rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
- long shared_len, len = RARRAY_LEN(ary);
+ long shared_len, len = RARRAY_LEN(ary);
VALUE shared_root = ARY_SHARED_ROOT(ary);
ary_verify(shared_root);
if (len <= RARRAY_EMBED_LEN_MAX) {
- const VALUE *ptr = ARY_HEAP_PTR(ary);
+ const VALUE *ptr = ARY_HEAP_PTR(ary);
FL_UNSET_SHARED(ary);
FL_SET_EMBED(ary);
- MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
+ MEMCPY((VALUE *)ARY_EMBED_PTR(ary), ptr, VALUE, len);
rb_ary_decrement_share(shared_root);
ARY_SET_EMBED_LEN(ary, len);
}
else if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && len > ((shared_len = RARRAY_LEN(shared_root))>>1)) {
long shift = RARRAY_CONST_PTR_TRANSIENT(ary) - RARRAY_CONST_PTR_TRANSIENT(shared_root);
- FL_UNSET_SHARED(ary);
+ FL_UNSET_SHARED(ary);
ARY_SET_PTR(ary, RARRAY_CONST_PTR_TRANSIENT(shared_root));
- ARY_SET_CAPA(ary, shared_len);
+ ARY_SET_CAPA(ary, shared_len);
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- MEMMOVE(ptr, ptr+shift, VALUE, len);
- });
+ MEMMOVE(ptr, ptr+shift, VALUE, len);
+ });
FL_SET_EMBED(shared_root);
rb_ary_decrement_share(shared_root);
- }
+ }
else {
VALUE *ptr = ary_heap_alloc(ary, len);
MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
@@ -581,11 +597,18 @@ rb_ary_modify(VALUE ary)
ARY_SET_PTR(ary, ptr);
}
- rb_gc_writebarrier_remember(ary);
+ rb_gc_writebarrier_remember(ary);
}
ary_verify(ary);
}
+void
+rb_ary_modify(VALUE ary)
+{
+ rb_ary_modify_check(ary);
+ rb_ary_cancel_sharing(ary);
+}
+
static VALUE
ary_ensure_room_for_push(VALUE ary, long add_len)
{
@@ -636,12 +659,15 @@ ary_ensure_room_for_push(VALUE ary, long add_len)
/*
* call-seq:
- * ary.freeze -> ary
+ * array.freeze -> self
*
- * Calls Object#freeze on +ary+ to prevent any further
- * modification. A RuntimeError will be raised if a modification
- * attempt is made.
+ * Freezes +self+; returns +self+:
+ * a = []
+ * a.frozen? # => false
+ * a.freeze
+ * a.frozen? # => true
*
+ * An attempt to modify a frozen \Array raises FrozenError.
*/
VALUE
@@ -764,6 +790,58 @@ rb_ary_new_from_values(long n, const VALUE *elts)
return rb_ary_tmp_new_from_values(rb_cArray, n, elts);
}
+static VALUE
+ec_ary_alloc(rb_execution_context_t *ec, VALUE klass)
+{
+ RB_EC_NEWOBJ_OF(ec, ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
+ /* Created array is:
+ * FL_SET_EMBED((VALUE)ary);
+ * ARY_SET_EMBED_LEN((VALUE)ary, 0);
+ */
+ return (VALUE)ary;
+}
+
+static VALUE
+ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa)
+{
+ VALUE ary,*ptr;
+
+ if (capa < 0) {
+ rb_raise(rb_eArgError, "negative array size (or size too big)");
+ }
+ if (capa > ARY_MAX_SIZE) {
+ rb_raise(rb_eArgError, "array size too big");
+ }
+
+ RUBY_DTRACE_CREATE_HOOK(ARRAY, capa);
+
+ ary = ec_ary_alloc(ec, klass);
+
+ if (capa > RARRAY_EMBED_LEN_MAX) {
+ ptr = ary_heap_alloc(ary, capa);
+ FL_UNSET_EMBED(ary);
+ ARY_SET_PTR(ary, ptr);
+ ARY_SET_CAPA(ary, capa);
+ ARY_SET_HEAP_LEN(ary, 0);
+ }
+
+ return ary;
+}
+
+VALUE
+rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VALUE *elts)
+{
+ VALUE ary;
+
+ ary = ec_ary_new(ec, rb_cArray, n);
+ if (n > 0 && elts) {
+ ary_memcpy(ary, 0, n, elts);
+ ARY_SET_LEN(ary, n);
+ }
+
+ return ary;
+}
+
VALUE
rb_ary_tmp_new(long capa)
{
@@ -854,25 +932,26 @@ ary_make_shared(VALUE ary)
long capa = ARY_CAPA(ary), len = RARRAY_LEN(ary);
const VALUE *ptr;
NEWOBJ_OF(shared, struct RArray, 0, T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0));
+ VALUE vshared = (VALUE)shared;
rb_ary_transient_heap_evacuate(ary, TRUE);
ptr = ARY_HEAP_PTR(ary);
- FL_UNSET_EMBED(shared);
- ARY_SET_LEN((VALUE)shared, capa);
- ARY_SET_PTR((VALUE)shared, ptr);
- ary_mem_clear((VALUE)shared, len, capa - len);
- FL_SET_SHARED_ROOT(shared);
- ARY_SET_SHARED_ROOT_REFCNT((VALUE)shared, 1);
+ FL_UNSET_EMBED(vshared);
+ ARY_SET_LEN(vshared, capa);
+ ARY_SET_PTR(vshared, ptr);
+ ary_mem_clear(vshared, len, capa - len);
+ FL_SET_SHARED_ROOT(vshared);
+ ARY_SET_SHARED_ROOT_REFCNT(vshared, 1);
FL_SET_SHARED(ary);
RB_DEBUG_COUNTER_INC(obj_ary_shared_create);
- ARY_SET_SHARED(ary, (VALUE)shared);
- OBJ_FREEZE(shared);
+ ARY_SET_SHARED(ary, vshared);
+ OBJ_FREEZE(vshared);
- ary_verify((VALUE)shared);
+ ary_verify(vshared);
ary_verify(ary);
- return (VALUE)shared;
+ return vshared;
}
}
@@ -919,21 +998,16 @@ rb_check_to_array(VALUE ary)
/*
* call-seq:
- * Array.try_convert(obj) -> array or nil
+ * Array.try_convert(object) -> object, new_array, or nil
*
- * Tries to convert +obj+ into an array, using the +to_ary+ method. Returns
- * the converted array or +nil+ if +obj+ cannot be converted.
- * This method can be used to check if an argument is an array.
+ * If +object+ is an \Array object, returns +object+.
*
- * Array.try_convert([1]) #=> [1]
- * Array.try_convert("1") #=> nil
+ * Otherwise if +object+ responds to <tt>:to_ary</tt>,
+ * calls <tt>object.to_ary</tt> and returns the result.
*
- * if tmp = Array.try_convert(arg)
- * # the argument is an array
- * elsif tmp = String.try_convert(arg)
- * # the argument is a string
- * end
+ * Returns +nil+ if +object+ does not respond to <tt>:to_ary</tt>
*
+ * Raises an exception unless <tt>object.to_ary</tt> returns an \Array object.
*/
static VALUE
@@ -944,58 +1018,46 @@ rb_ary_s_try_convert(VALUE dummy, VALUE ary)
/*
* call-seq:
- * Array.new(size=0, default=nil)
- * Array.new(array)
- * Array.new(size) {|index| block }
- *
- * Returns a new array.
- *
- * In the first form, if no arguments are sent, the new array will be empty.
- * When a +size+ and an optional +default+ are sent, an array is created with
- * +size+ copies of +default+. Take notice that all elements will reference the
- * same object +default+.
- *
- * The second form creates a copy of the array passed as a parameter (the
- * array is generated by calling to_ary on the parameter).
- *
- * first_array = ["Matz", "Guido"]
- *
- * second_array = Array.new(first_array) #=> ["Matz", "Guido"]
- *
- * first_array.equal? second_array #=> false
- *
- * In the last form, an array of the given size is created. Each element in
- * this array is created by passing the element's index to the given block
- * and storing the return value.
- *
- * Array.new(3) {|index| index ** 2}
- * # => [0, 1, 4]
- *
- * == Common gotchas
- *
- * When sending the second parameter, the same object will be used as the
- * value for all the array elements:
- *
- * a = Array.new(2, Hash.new)
- * # => [{}, {}]
- *
- * a[0]['cat'] = 'feline'
- * a # => [{"cat"=>"feline"}, {"cat"=>"feline"}]
- *
- * a[1]['cat'] = 'Felix'
- * a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]
- *
- * Since all the Array elements store the same hash, changes to one of them
- * will affect them all.
- *
- * If multiple copies are what you want, you should use the block
- * version which uses the result of that block each time an element
- * of the array needs to be initialized:
- *
- * a = Array.new(2) {Hash.new}
- * a[0]['cat'] = 'feline'
- * a # => [{"cat"=>"feline"}, {}]
- *
+ * Array.new -> new_empty_array
+ * Array.new(array) -> new_array
+ * Array.new(size) -> new_array
+ * Array.new(size, default_value) -> new_array
+ * Array.new(size) {|index| ... } -> new_array
+ *
+ * Returns a new \Array.
+ *
+ * With no block and no arguments, returns a new empty \Array object.
+ *
+ * With no block and a single \Array argument +array+,
+ * returns a new \Array formed from +array+:
+ * a = Array.new([:foo, 'bar', 2])
+ * a.class # => Array
+ * a # => [:foo, "bar", 2]
+ *
+ * With no block and a single \Integer argument +size+,
+ * returns a new \Array of the given size
+ * whose elements are all +nil+:
+ * a = Array.new(3)
+ * a # => [nil, nil, nil]
+ *
+ * With no block and arguments +size+ and +default_value+,
+ * returns an \Array of the given size;
+ * each element is that same +default_value+:
+ * a = Array.new(3, 'x')
+ * a # => ['x', 'x', 'x']
+ *
+ * With a block and argument +size+,
+ * returns an \Array of the given size;
+ * the block is called with each successive integer +index+;
+ * the element for that +index+ is the return value from the block:
+ * a = Array.new(3) {|index| "Element #{index}" }
+ * a # => ["Element 0", "Element 1", "Element 2"]
+ *
+ * Raises ArgumentError if +size+ is negative.
+ *
+ * With a block and no argument,
+ * or a single argument +0+,
+ * ignores the block and returns a new empty \Array.
*/
static VALUE
@@ -1137,9 +1199,55 @@ ary_make_partial(VALUE ary, VALUE klass, long offset, long len)
}
static VALUE
+ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step)
+{
+ assert(offset >= 0);
+ assert(len >= 0);
+ assert(offset+len <= RARRAY_LEN(ary));
+ assert(step != 0);
+
+ const VALUE *values = RARRAY_CONST_PTR_TRANSIENT(ary);
+ const long orig_len = len;
+
+ if ((step > 0 && step >= len) || (step < 0 && (step < -len))) {
+ VALUE result = ary_new(klass, 1);
+ VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
+ RB_OBJ_WRITE(result, ptr, values[offset]);
+ ARY_SET_EMBED_LEN(result, 1);
+ return result;
+ }
+
+ long ustep = (step < 0) ? -step : step;
+ len = (len + ustep - 1) / ustep;
+
+ long i;
+ long j = offset + ((step > 0) ? 0 : (orig_len - 1));
+ VALUE result = ary_new(klass, len);
+ if (len <= RARRAY_EMBED_LEN_MAX) {
+ VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result);
+ for (i = 0; i < len; ++i) {
+ RB_OBJ_WRITE(result, ptr+i, values[j]);
+ j += step;
+ }
+ ARY_SET_EMBED_LEN(result, len);
+ }
+ else {
+ RARRAY_PTR_USE_TRANSIENT(result, ptr, {
+ for (i = 0; i < len; ++i) {
+ RB_OBJ_WRITE(result, ptr+i, values[j]);
+ j += step;
+ }
+ });
+ ARY_SET_LEN(result, len);
+ }
+
+ return result;
+}
+
+static VALUE
ary_make_shared_copy(VALUE ary)
{
- return ary_make_partial(ary, rb_obj_class(ary), 0, RARRAY_LEN(ary));
+ return ary_make_partial(ary, rb_cArray, 0, RARRAY_LEN(ary));
}
enum ary_take_pos_flags
@@ -1177,18 +1285,16 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos
/*
* call-seq:
- * ary << obj -> ary
- *
- * Append---Pushes the given object on to the end of this array. This
- * expression returns the array itself, so several appends
- * may be chained together.
+ * array << object -> self
*
- * a = [ 1, 2 ]
- * a << "c" << "d" << [ 3, 4 ]
- * #=> [ 1, 2, "c", "d", [ 3, 4 ] ]
- * a
- * #=> [ 1, 2, "c", "d", [ 3, 4 ] ]
+ * Appends +object+ to +self+; returns +self+:
+ * a = [:foo, 'bar', 2]
+ * a << :baz # => [:foo, "bar", 2, :baz]
*
+ * Appends +object+ as one element, even if it is another \Array:
+ * a = [:foo, 'bar', 2]
+ * a1 = a << [3, 4]
+ * a1 # => [:foo, "bar", 2, [3, 4]]
*/
VALUE
@@ -1216,19 +1322,22 @@ rb_ary_cat(VALUE ary, const VALUE *argv, long len)
/*
* call-seq:
- * ary.push(obj, ...) -> ary
- * ary.append(obj, ...) -> ary
- *
- * Append --- Pushes the given object(s) on to the end of this array. This
- * expression returns the array itself, so several appends
- * may be chained together. See also Array#pop for the opposite
- * effect.
- *
- * a = [ "a", "b", "c" ]
- * a.push("d", "e", "f")
- * #=> ["a", "b", "c", "d", "e", "f"]
- * [1, 2, 3].push(4).push(5)
- * #=> [1, 2, 3, 4, 5]
+ * array.push(*objects) -> self
+ *
+ * Appends trailing elements.
+ *
+ * Appends each argument in +objects+ to +self+; returns +self+:
+ * a = [:foo, 'bar', 2]
+ * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
+ *
+ * Appends each argument as one element, even if it is another \Array:
+ * a = [:foo, 'bar', 2]
+ * a1 = a.push([:baz, :bat], [:bam, :bad])
+ * a1 # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
+ *
+ * Array#append is an alias for \Array#push.
+ *
+ * Related: #pop, #shift, #unshift.
*/
static VALUE
@@ -1258,20 +1367,30 @@ rb_ary_pop(VALUE ary)
/*
* call-seq:
- * ary.pop -> obj or nil
- * ary.pop(n) -> new_ary
+ * array.pop -> object or nil
+ * array.pop(n) -> new_array
+ *
+ * Removes and returns trailing elements.
*
- * Removes the last element from +self+ and returns it, or
- * +nil+ if the array is empty.
+ * When no argument is given and +self+ is not empty,
+ * removes and returns the last element:
+ * a = [:foo, 'bar', 2]
+ * a.pop # => 2
+ * a # => [:foo, "bar"]
*
- * If a number +n+ is given, returns an array of the last +n+ elements
- * (or less) just like <code>array.slice!(-n, n)</code> does. See also
- * Array#push for the opposite effect.
+ * Returns +nil+ if the array is empty.
*
- * a = [ "a", "b", "c", "d" ]
- * a.pop #=> "d"
- * a.pop(2) #=> ["b", "c"]
- * a #=> ["a"]
+ * When a non-negative \Integer argument +n+ is given and is in range,
+ * removes and returns the last +n+ elements in a new \Array:
+ * a = [:foo, 'bar', 2]
+ * a.pop(2) # => ["bar", 2]
+ *
+ * If +n+ is positive and out of range,
+ * removes and returns all elements:
+ * a = [:foo, 'bar', 2]
+ * a.pop(50) # => [:foo, "bar", 2]
+ *
+ * Related: #push, #shift, #unshift.
*/
static VALUE
@@ -1326,25 +1445,32 @@ rb_ary_shift(VALUE ary)
/*
* call-seq:
- * ary.shift -> obj or nil
- * ary.shift(n) -> new_ary
+ * array.shift -> object or nil
+ * array.shift(n) -> new_array
+ *
+ * Removes and returns leading elements.
*
- * Removes the first element of +self+ and returns it (shifting all
- * other elements down by one). Returns +nil+ if the array
- * is empty.
+ * When no argument is given, removes and returns the first element:
+ * a = [:foo, 'bar', 2]
+ * a.shift # => :foo
+ * a # => ['bar', 2]
*
- * If a number +n+ is given, returns an array of the first +n+ elements
- * (or less) just like <code>array.slice!(0, n)</code> does. With +ary+
- * containing only the remainder elements, not including what was shifted to
- * +new_ary+. See also Array#unshift for the opposite effect.
+ * Returns +nil+ if +self+ is empty.
*
- * args = [ "-m", "-q", "filename" ]
- * args.shift #=> "-m"
- * args #=> ["-q", "filename"]
+ * When positive \Integer argument +n+ is given, removes the first +n+ elements;
+ * returns those elements in a new \Array:
+ * a = [:foo, 'bar', 2]
+ * a.shift(2) # => [:foo, 'bar']
+ * a # => [2]
*
- * args = [ "-m", "-q", "filename" ]
- * args.shift(2) #=> ["-m", "-q"]
- * args #=> ["filename"]
+ * If +n+ is as large as or larger than <tt>self.length</tt>,
+ * removes all elements; returns those elements in a new \Array:
+ * a = [:foo, 'bar', 2]
+ * a.shift(3) # => [:foo, 'bar', 2]
+ *
+ * If +n+ is zero, returns a new empty \Array; +self+ is unmodified.
+ *
+ * Related: #push, #pop, #unshift.
*/
static VALUE
@@ -1365,59 +1491,75 @@ rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
return result;
}
-MJIT_FUNC_EXPORTED VALUE
-rb_ary_behead(VALUE ary, long n)
+static VALUE
+behead_shared(VALUE ary, long n)
{
- if (n<=0) return ary;
+ assert(ARY_SHARED_P(ary));
+ rb_ary_modify_check(ary);
+ if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
+ ary_mem_clear(ary, 0, n);
+ }
+ ARY_INCREASE_PTR(ary, n);
+ ARY_INCREASE_LEN(ary, -n);
+ ary_verify(ary);
+ return ary;
+}
+static VALUE
+behead_transient(VALUE ary, long n)
+{
rb_ary_modify_check(ary);
- if (ARY_SHARED_P(ary)) {
- if (ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))) {
- setup_occupied_shared:
- ary_mem_clear(ary, 0, n);
- }
- ARY_INCREASE_PTR(ary, n);
+ RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
+ MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n);
+ }); /* WB: no new reference */
+ ARY_INCREASE_LEN(ary, -n);
+ ary_verify(ary);
+ return ary;
+}
+
+MJIT_FUNC_EXPORTED VALUE
+rb_ary_behead(VALUE ary, long n)
+{
+ if (n <= 0) {
+ return ary;
+ }
+ else if (ARY_SHARED_P(ary)) {
+ return behead_shared(ary, n);
+ }
+ else if (RARRAY_LEN(ary) >= ARY_DEFAULT_SIZE) {
+ ary_make_shared(ary);
+ return behead_shared(ary, n);
}
else {
- if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) {
- RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
- MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n);
- }); /* WB: no new reference */
- }
- else {
- ary_make_shared(ary);
- goto setup_occupied_shared;
- }
+ return behead_transient(ary, n);
}
- ARY_INCREASE_LEN(ary, -n);
+}
+
+static VALUE
+make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, long capa, long len)
+{
+ if (head - sharedp < argc) {
+ long room = capa - len - argc;
+
+ room -= room >> 4;
+ MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
+ head = sharedp + argc + room;
+ }
+ ARY_SET_PTR(ary, head - argc);
+ assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
ary_verify(ary);
- return ary;
+ return ARY_SHARED_ROOT(ary);
}
static VALUE
-ary_ensure_room_for_unshift(VALUE ary, int argc)
+ary_modify_for_unshift(VALUE ary, int argc)
{
long len = RARRAY_LEN(ary);
long new_len = len + argc;
long capa;
const VALUE *head, *sharedp;
- if (len > ARY_MAX_SIZE - argc) {
- rb_raise(rb_eIndexError, "index %ld too big", new_len);
- }
-
- if (ARY_SHARED_P(ary)) {
- VALUE shared_root = ARY_SHARED_ROOT(ary);
- capa = RARRAY_LEN(shared_root);
- if (ARY_SHARED_ROOT_OCCUPIED(shared_root) && capa > new_len) {
- rb_ary_modify_check(ary);
- head = RARRAY_CONST_PTR_TRANSIENT(ary);
- sharedp = RARRAY_CONST_PTR_TRANSIENT(shared_root);
- goto makeroom_if_need;
- }
- }
-
rb_ary_modify(ary);
capa = ARY_CAPA(ary);
if (capa - (capa >> 6) <= new_len) {
@@ -1433,21 +1575,7 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
ary_make_shared(ary);
head = sharedp = RARRAY_CONST_PTR_TRANSIENT(ary);
- goto makeroom;
- makeroom_if_need:
- if (head - sharedp < argc) {
- long room;
- makeroom:
- room = capa - new_len;
- room -= room >> 4;
- MEMMOVE((VALUE *)sharedp + argc + room, head, VALUE, len);
- head = sharedp + argc + room;
- }
- ARY_SET_PTR(ary, head - argc);
- assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary)));
-
- ary_verify(ary);
- return ARY_SHARED_ROOT(ary);
+ return make_room_for_unshift(ary, head, (void *)sharedp, argc, capa, len);
}
else {
/* sliding items */
@@ -1460,17 +1588,49 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
}
}
+static VALUE
+ary_ensure_room_for_unshift(VALUE ary, int argc)
+{
+ long len = RARRAY_LEN(ary);
+ long new_len = len + argc;
+
+ if (len > ARY_MAX_SIZE - argc) {
+ rb_raise(rb_eIndexError, "index %ld too big", new_len);
+ }
+ else if (! ARY_SHARED_P(ary)) {
+ return ary_modify_for_unshift(ary, argc);
+ }
+ else {
+ VALUE shared_root = ARY_SHARED_ROOT(ary);
+ long capa = RARRAY_LEN(shared_root);
+
+ if (! ARY_SHARED_ROOT_OCCUPIED(shared_root)) {
+ return ary_modify_for_unshift(ary, argc);
+ }
+ else if (new_len > capa) {
+ return ary_modify_for_unshift(ary, argc);
+ }
+ else {
+ const VALUE * head = RARRAY_CONST_PTR_TRANSIENT(ary);
+ void *sharedp = (void *)RARRAY_CONST_PTR_TRANSIENT(shared_root);
+
+ rb_ary_modify_check(ary);
+ return make_room_for_unshift(ary, head, sharedp, argc, capa, len);
+ }
+ }
+}
+
/*
* call-seq:
- * ary.unshift(obj, ...) -> ary
- * ary.prepend(obj, ...) -> ary
+ * array.unshift(*objects) -> self
+ *
+ * Prepends the given +objects+ to +self+:
+ * a = [:foo, 'bar', 2]
+ * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
*
- * Prepends objects to the front of +self+, moving other elements upwards.
- * See also Array#shift for the opposite effect.
+ * Array#prepend is an alias for Array#unshift.
*
- * a = [ "b", "c", "d" ]
- * a.unshift("a") #=> ["a", "b", "c", "d"]
- * a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"]
+ * Related: #push, #pop, #shift.
*/
static VALUE
@@ -1515,7 +1675,7 @@ rb_ary_entry(VALUE ary, long offset)
}
VALUE
-rb_ary_subseq(VALUE ary, long beg, long len)
+rb_ary_subseq_step(VALUE ary, long beg, long len, long step)
{
VALUE klass;
long alen = RARRAY_LEN(ary);
@@ -1526,48 +1686,116 @@ rb_ary_subseq(VALUE ary, long beg, long len)
if (alen < len || alen < beg + len) {
len = alen - beg;
}
- klass = rb_obj_class(ary);
+ klass = rb_cArray;
if (len == 0) return ary_new(klass, 0);
+ if (step == 0)
+ rb_raise(rb_eArgError, "slice step cannot be zero");
+ if (step == 1)
+ return ary_make_partial(ary, klass, beg, len);
+ else
+ return ary_make_partial_step(ary, klass, beg, len, step);
+}
- return ary_make_partial(ary, klass, beg, len);
+VALUE
+rb_ary_subseq(VALUE ary, long beg, long len)
+{
+ return rb_ary_subseq_step(ary, beg, len, 1);
}
static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
/*
* call-seq:
- * ary[index] -> obj or nil
- * ary[start, length] -> new_ary or nil
- * ary[range] -> new_ary or nil
- * ary.slice(index) -> obj or nil
- * ary.slice(start, length) -> new_ary or nil
- * ary.slice(range) -> new_ary or nil
- *
- * Element Reference --- Returns the element at +index+, or returns a
- * subarray starting at the +start+ index and continuing for +length+
- * elements, or returns a subarray specified by +range+ of indices.
- *
- * Negative indices count backward from the end of the array (-1 is the last
- * element). For +start+ and +range+ cases the starting index is just before
- * an element. Additionally, an empty array is returned when the starting
- * index for an element range is at the end of the array.
- *
- * Returns +nil+ if the index (or starting index) are out of range.
- *
- * a = [ "a", "b", "c", "d", "e" ]
- * a[2] + a[0] + a[1] #=> "cab"
- * a[6] #=> nil
- * a[1, 2] #=> [ "b", "c" ]
- * a[1..3] #=> [ "b", "c", "d" ]
- * a[4..7] #=> [ "e" ]
- * a[6..10] #=> nil
- * a[-3, 3] #=> [ "c", "d", "e" ]
- * # special cases
- * a[5] #=> nil
- * a[6, 1] #=> nil
- * a[5, 1] #=> []
- * a[5..10] #=> []
- *
+ * array[index] -> object or nil
+ * array[start, length] -> object or nil
+ * array[range] -> object or nil
+ * array[aseq] -> object or nil
+ * array.slice(index) -> object or nil
+ * array.slice(start, length) -> object or nil
+ * array.slice(range) -> object or nil
+ * array.slice(aseq) -> object or nil
+ *
+ * Returns elements from +self+; does not modify +self+.
+ *
+ * When a single \Integer argument +index+ is given, returns the element at offset +index+:
+ * a = [:foo, 'bar', 2]
+ * a[0] # => :foo
+ * a[2] # => 2
+ * a # => [:foo, "bar", 2]
+ *
+ * If +index+ is negative, counts relative to the end of +self+:
+ * a = [:foo, 'bar', 2]
+ * a[-1] # => 2
+ * a[-2] # => "bar"
+ *
+ * If +index+ is out of range, returns +nil+.
+ *
+ * When two \Integer arguments +start+ and +length+ are given,
+ * returns a new \Array of size +length+ containing successive elements beginning at offset +start+:
+ * a = [:foo, 'bar', 2]
+ * a[0, 2] # => [:foo, "bar"]
+ * a[1, 2] # => ["bar", 2]
+ *
+ * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
+ * returns all elements from offset +start+ to the end:
+ * a = [:foo, 'bar', 2]
+ * a[0, 4] # => [:foo, "bar", 2]
+ * a[1, 3] # => ["bar", 2]
+ * a[2, 2] # => [2]
+ *
+ * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
+ * returns a new empty \Array.
+ *
+ * If +length+ 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:
+ * 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.
+ *
+ * If <tt>range.end</tt> is negative, calculates the end index from the end:
+ * a = [:foo, 'bar', 2]
+ * a[0..-1] # => [:foo, "bar", 2]
+ * a[0..-2] # => [:foo, "bar"]
+ * a[0..-3] # => [:foo]
+ *
+ * If <tt>range.start</tt> is negative, calculates the start index from the end:
+ * a = [:foo, 'bar', 2]
+ * a[-1..2] # => [2]
+ * a[-2..2] # => ["bar", 2]
+ * a[-3..2] # => [:foo, "bar", 2]
+ *
+ * If <tt>range.start</tt> is larger than the array size, returns +nil+.
+ * a = [:foo, 'bar', 2]
+ * a[4..1] # => nil
+ * a[4..0] # => nil
+ * a[4..-1] # => nil
+ *
+ * When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
+ * returns an Array of elements corresponding to the indexes produced by
+ * the sequence.
+ * a = ['--', 'data1', '--', 'data2', '--', 'data3']
+ * a[(1..).step(2)] # => ["data1", "data2", "data3"]
+ *
+ * Unlike slicing with range, if the start or the end of the arithmetic sequence
+ * is larger than array size, throws RangeError.
+ * a = ['--', 'data1', '--', 'data2', '--', 'data3']
+ * a[(1..11).step(2)]
+ * # RangeError (((1..11).step(2)) out of range)
+ * a[(7..).step(2)]
+ * # RangeError (((7..).step(2)) out of range)
+ *
+ * If given a single argument, and its type is not one of the listed, tries to
+ * convert it to Integer, and raises if it is impossible:
+ * a = [:foo, 'bar', 2]
+ * # Raises TypeError (no implicit conversion of Symbol into Integer):
+ * a[:foo]
+ *
+ * Array#slice is an alias for Array#[].
*/
VALUE
@@ -1580,7 +1808,7 @@ rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
return rb_ary_aref1(ary, argv[0]);
}
-VALUE
+static VALUE
rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
{
long beg = NUM2LONG(b);
@@ -1594,35 +1822,33 @@ rb_ary_aref2(VALUE ary, VALUE b, VALUE e)
MJIT_FUNC_EXPORTED VALUE
rb_ary_aref1(VALUE ary, VALUE arg)
{
- long beg, len;
+ long beg, len, step;
/* special case - speeding up */
if (FIXNUM_P(arg)) {
return rb_ary_entry(ary, FIX2LONG(arg));
}
- /* check if idx is Range */
- switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) {
+ /* check if idx is Range or ArithmeticSequence */
+ switch (rb_arithmetic_sequence_beg_len_step(arg, &beg, &len, &step, RARRAY_LEN(ary), 0)) {
case Qfalse:
- break;
+ break;
case Qnil:
- return Qnil;
+ return Qnil;
default:
- return rb_ary_subseq(ary, beg, len);
+ return rb_ary_subseq_step(ary, beg, len, step);
}
+
return rb_ary_entry(ary, NUM2LONG(arg));
}
/*
* call-seq:
- * ary.at(index) -> obj or nil
- *
- * Returns the element at +index+. A negative index counts from the end of
- * +self+. Returns +nil+ if the index is out of range. See also
- * Array#[].
+ * array.at(index) -> object
*
- * a = [ "a", "b", "c", "d", "e" ]
- * a.at(0) #=> "a"
- * a.at(-1) #=> "e"
+ * Returns the element at \Integer offset +index+; does not modify +self+.
+ * a = [:foo, 'bar', 2]
+ * a.at(0) # => :foo
+ * a.at(2) # => 2
*/
VALUE
@@ -1633,19 +1859,33 @@ rb_ary_at(VALUE ary, VALUE pos)
/*
* call-seq:
- * ary.first -> obj or nil
- * ary.first(n) -> new_ary
+ * array.first -> object or nil
+ * array.first(n) -> new_array
+ *
+ * Returns elements from +self+; does not modify +self+.
+ *
+ * When no argument is given, returns the first element:
+ * a = [:foo, 'bar', 2]
+ * a.first # => :foo
+ * a # => [:foo, "bar", 2]
+ *
+ * If +self+ is empty, returns +nil+.
*
- * Returns the first element, or the first +n+ elements, of the array.
- * If the array is empty, the first form returns +nil+, and the
- * second form returns an empty array. See also Array#last for
- * the opposite effect.
+ * When non-negative \Integer argument +n+ is given,
+ * returns the first +n+ elements in a new \Array:
+ * a = [:foo, 'bar', 2]
+ * a.first(2) # => [:foo, "bar"]
*
- * a = [ "q", "r", "s", "t" ]
- * a.first #=> "q"
- * a.first(2) #=> ["q", "r"]
+ * If <tt>n >= array.size</tt>, returns all elements:
+ * a = [:foo, 'bar', 2]
+ * 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.
*/
-
static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
@@ -1660,17 +1900,32 @@ rb_ary_first(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.last -> obj or nil
- * ary.last(n) -> new_ary
+ * array.last -> object or nil
+ * array.last(n) -> new_array
+ *
+ * Returns elements from +self+; +self+ is not modified.
+ *
+ * When no argument is given, returns the last element:
+ * a = [:foo, 'bar', 2]
+ * a.last # => 2
+ * a # => [:foo, "bar", 2]
*
- * Returns the last element(s) of +self+. If the array is empty,
- * the first form returns +nil+.
+ * If +self+ is empty, returns +nil+.
*
- * See also Array#first for the opposite effect.
+ * When non-negative \Innteger argument +n+ is given,
+ * returns the last +n+ elements in a new \Array:
+ * a = [:foo, 'bar', 2]
+ * a.last(2) # => ["bar", 2]
*
- * a = [ "w", "x", "y", "z" ]
- * a.last #=> "z"
- * a.last(2) #=> ["y", "z"]
+ * If <tt>n >= array.size</tt>, returns all elements:
+ * a = [:foo, 'bar', 2]
+ * a.last(50) # => [:foo, "bar", 2]
+ *
+ * If <tt>n == 0</tt>, returns an new empty \Array:
+ * a = [:foo, 'bar', 2]
+ * a.last(0) # []
+ *
+ * Related: #first.
*/
VALUE
@@ -1688,26 +1943,35 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.fetch(index) -> obj
- * ary.fetch(index, default) -> obj
- * ary.fetch(index) {|index| block} -> obj
- *
- * Tries to return the element at position +index+, but throws an IndexError
- * exception if the referenced +index+ lies outside of the array bounds. This
- * error can be prevented by supplying a second argument, which will act as a
- * +default+ value.
- *
- * Alternatively, if a block is given it will only be executed when an
- * invalid +index+ is referenced.
- *
- * Negative values of +index+ count from the end of the array.
- *
- * a = [ 11, 22, 33, 44 ]
- * a.fetch(1) #=> 22
- * a.fetch(-1) #=> 44
- * a.fetch(4, 'cat') #=> "cat"
- * a.fetch(100) {|i| puts "#{i} is out of bounds"}
- * #=> "100 is out of bounds"
+ * array.fetch(index) -> element
+ * array.fetch(index, default_value) -> element
+ * array.fetch(index) {|index| ... } -> element
+ *
+ * Returns the element at offset +index+.
+ *
+ * With the single \Integer argument +index+,
+ * returns the element at offset +index+:
+ * a = [:foo, 'bar', 2]
+ * a.fetch(1) # => "bar"
+ *
+ * If +index+ is negative, counts from the end of the array:
+ * a = [:foo, 'bar', 2]
+ * a.fetch(-1) # => 2
+ * a.fetch(-2) # => "bar"
+ *
+ * With arguments +index+ and +default_value+,
+ * returns the element at offset +index+ if index is in range,
+ * otherwise returns +default_value+:
+ * a = [:foo, 'bar', 2]
+ * a.fetch(1, nil) # => "bar"
+ *
+ * With argument +index+ and a block,
+ * returns the element at offset +index+ if index is in range
+ * (and the block is not called); otherwise calls the block with index and returns its return value:
+ *
+ * a = [:foo, 'bar', 2]
+ * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
+ * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
*/
static VALUE
@@ -1740,28 +2004,37 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.find_index(obj) -> int or nil
- * ary.find_index {|item| block} -> int or nil
- * ary.find_index -> Enumerator
- * ary.index(obj) -> int or nil
- * ary.index {|item| block} -> int or nil
- * ary.index -> Enumerator
+ * array.index(object) -> integer or nil
+ * array.index {|element| ... } -> integer or nil
+ * array.index -> new_enumerator
+ *
+ * Returns the index of a specified element.
*
- * Returns the _index_ of the first object in +ary+ such that the object is
- * <code>==</code> to +obj+.
+ * When argument +object+ is given but no block,
+ * returns the index of the first element +element+
+ * for which <tt>object == element</tt>:
+ * a = [:foo, 'bar', 2, 'bar']
+ * a.index('bar') # => 1
*
- * If a block is given instead of an argument, returns the _index_ of the
- * first object for which the block returns +true+. Returns +nil+ if no
- * match is found.
+ * Returns +nil+ if no such element found.
*
- * See also Array#rindex.
+ * When both argument +object+ and a block are given,
+ * calls the block with each successive element;
+ * returns the index of the first element for which the block returns a truthy value:
+ * a = [:foo, 'bar', 2, 'bar']
+ * a.index {|element| element == 'bar' } # => 1
*
- * An Enumerator is returned if neither a block nor argument is given.
+ * Returns +nil+ if the block never returns a truthy value.
*
- * a = [ "a", "b", "c" ]
- * a.index("b") #=> 1
- * a.index("z") #=> nil
- * a.index {|x| x == "b"} #=> 1
+ * When neither an argument nor a block is given, returns a new Enumerator:
+ * a = [:foo, 'bar', 2]
+ * e = a.index
+ * e # => #<Enumerator: [:foo, "bar", 2]:index>
+ * e.each {|element| element == 'bar' } # => 1
+ *
+ * Array#find_index is an alias for Array#index.
+ *
+ * Related: #rindex.
*/
static VALUE
@@ -1794,26 +2067,33 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.rindex(obj) -> int or nil
- * ary.rindex {|item| block} -> int or nil
- * ary.rindex -> Enumerator
+ * array.rindex(object) -> integer or nil
+ * array.rindex {|element| ... } -> integer or nil
+ * array.rindex -> new_enumerator
+ *
+ * Returns the index of the last element for which <tt>object == element</tt>.
*
- * Returns the _index_ of the last object in +self+ <code>==</code> to +obj+.
+ * When argument +object+ is given but no block, returns the index of the last such element found:
+ * a = [:foo, 'bar', 2, 'bar']
+ * a.rindex('bar') # => 3
*
- * If a block is given instead of an argument, returns the _index_ of the
- * first object for which the block returns +true+, starting from the last
- * object.
+ * Returns +nil+ if no such object found.
*
- * Returns +nil+ if no match is found.
+ * When a block is given but no argument, calls the block with each successive element;
+ * returns the index of the last element for which the block returns a truthy value:
+ * a = [:foo, 'bar', 2, 'bar']
+ * a.rindex {|element| element == 'bar' } # => 3
*
- * See also Array#index.
+ * Returns +nil+ if the block never returns a truthy value.
*
- * If neither block nor argument is given, an Enumerator is returned instead.
+ * When neither an argument nor a block is given, returns a new \Enumerator:
*
- * a = [ "a", "b", "b", "b", "c" ]
- * a.rindex("b") #=> 3
- * a.rindex("z") #=> nil
- * a.rindex {|x| x == "b"} #=> 3
+ * a = [:foo, 'bar', 2, 'bar']
+ * e = a.rindex
+ * e # => #<Enumerator: [:foo, "bar", 2, "bar"]:rindex>
+ * e.each {|element| element == 'bar' } # => 3
+ *
+ * Related: #index.
*/
static VALUE
@@ -1990,88 +2270,175 @@ rb_ary_resize(VALUE ary, long len)
return ary;
}
+static VALUE
+ary_aset_by_rb_ary_store(VALUE ary, long key, VALUE val)
+{
+ rb_ary_store(ary, key, val);
+ return val;
+}
+
+static VALUE
+ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
+{
+ VALUE rpl = rb_ary_to_ary(val);
+ rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR_TRANSIENT(rpl), RARRAY_LEN(rpl));
+ RB_GC_GUARD(rpl);
+ return val;
+}
+
/*
* call-seq:
- * ary[index] = obj -> obj
- * ary[start, length] = obj or other_ary or nil -> obj or other_ary or nil
- * ary[range] = obj or other_ary or nil -> obj or other_ary or nil
- *
- * Element Assignment --- Sets the element at +index+, or replaces a subarray
- * from the +start+ index for +length+ elements, or replaces a subarray
- * specified by the +range+ of indices.
- *
- * If indices are greater than the current capacity of the array, the array
- * grows automatically. Elements are inserted into the array at +start+ if
- * +length+ is zero.
- *
- * Negative indices will count backward from the end of the array. For
- * +start+ and +range+ cases the starting index is just before an element.
- *
- * An IndexError is raised if a negative index points past the beginning of
- * the array.
- *
- * See also Array#push, and Array#unshift.
- *
- * a = Array.new
- * a[4] = "4"; #=> [nil, nil, nil, nil, "4"]
- * a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
- * a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"]
- * a[0, 2] = "?" #=> ["?", 2, nil, "4"]
- * a[0..2] = "A" #=> ["A", "4"]
- * a[-1] = "Z" #=> ["A", "Z"]
- * a[1..-1] = nil #=> ["A", nil]
- * a[1..-1] = [] #=> ["A"]
- * a[0, 0] = [ 1, 2 ] #=> [1, 2, "A"]
- * a[3, 0] = "B" #=> [1, 2, "A", "B"]
+ * array[index] = object -> object
+ * array[start, length] = object -> object
+ * array[range] = object -> object
+ *
+ * Assigns elements in +self+; returns the given +object+.
+ *
+ * When \Integer argument +index+ is given, assigns +object+ to an element in +self+.
+ *
+ * If +index+ is non-negative, assigns +object+ the element at offset +index+:
+ * a = [:foo, 'bar', 2]
+ * a[0] = 'foo' # => "foo"
+ * a # => ["foo", "bar", 2]
+ *
+ * If +index+ is greater than <tt>self.length</tt>, extends the array:
+ * a = [:foo, 'bar', 2]
+ * a[7] = 'foo' # => "foo"
+ * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
+ *
+ * If +index+ is negative, counts backwards from the end of the array:
+ * a = [:foo, 'bar', 2]
+ * a[-1] = 'two' # => "two"
+ * a # => [:foo, "bar", "two"]
+ *
+ * When \Integer arguments +start+ and +length+ are given and +object+ is not an \Array,
+ * removes <tt>length - 1</tt> elements beginning at offset +start+,
+ * and assigns +object+ at offset +start+:
+ * a = [:foo, 'bar', 2]
+ * a[0, 2] = 'foo' # => "foo"
+ * a # => ["foo", 2]
+ *
+ * If +start+ is negative, counts backwards from the end of the array:
+ * a = [:foo, 'bar', 2]
+ * a[-2, 2] = 'foo' # => "foo"
+ * a # => [:foo, "foo"]
+ *
+ * If +start+ is non-negative and outside the array (<tt> >= self.size</tt>),
+ * extends the array with +nil+, assigns +object+ at offset +start+,
+ * and ignores +length+:
+ * a = [:foo, 'bar', 2]
+ * a[6, 50] = 'foo' # => "foo"
+ * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
+ *
+ * If +length+ is zero, shifts elements at and following offset +start+
+ * and assigns +object+ at offset +start+:
+ * a = [:foo, 'bar', 2]
+ * a[1, 0] = 'foo' # => "foo"
+ * a # => [:foo, "foo", "bar", 2]
+ *
+ * If +length+ is too large for the existing array, does not extend the array:
+ * a = [:foo, 'bar', 2]
+ * a[1, 5] = 'foo' # => "foo"
+ * a # => [:foo, "foo"]
+ *
+ * When \Range argument +range+ is given and +object+ is an \Array,
+ * removes <tt>length - 1</tt> elements beginning at offset +start+,
+ * and assigns +object+ at offset +start+:
+ * a = [:foo, 'bar', 2]
+ * a[0..1] = 'foo' # => "foo"
+ * a # => ["foo", 2]
+ *
+ * if <tt>range.begin</tt> is negative, counts backwards from the end of the array:
+ * a = [:foo, 'bar', 2]
+ * a[-2..2] = 'foo' # => "foo"
+ * a # => [:foo, "foo"]
+ *
+ * If the array length is less than <tt>range.begin</tt>,
+ * assigns +object+ at offset <tt>range.begin</tt>, and ignores +length+:
+ * a = [:foo, 'bar', 2]
+ * a[6..50] = 'foo' # => "foo"
+ * a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
+ *
+ * If <tt>range.end</tt> is zero, shifts elements at and following offset +start+
+ * and assigns +object+ at offset +start+:
+ * a = [:foo, 'bar', 2]
+ * a[1..0] = 'foo' # => "foo"
+ * a # => [:foo, "foo", "bar", 2]
+ *
+ * If <tt>range.end</tt> is negative, assigns +object+ at offset +start+,
+ * retains <tt>range.end.abs -1</tt> elements past that, and removes those beyond:
+ * a = [:foo, 'bar', 2]
+ * a[1..-1] = 'foo' # => "foo"
+ * a # => [:foo, "foo"]
+ * a = [:foo, 'bar', 2]
+ * a[1..-2] = 'foo' # => "foo"
+ * a # => [:foo, "foo", 2]
+ * a = [:foo, 'bar', 2]
+ * a[1..-3] = 'foo' # => "foo"
+ * a # => [:foo, "foo", "bar", 2]
+ * a = [:foo, 'bar', 2]
+ *
+ * If <tt>range.end</tt> is too large for the existing array,
+ * replaces array elements, but does not extend the array with +nil+ values:
+ * a = [:foo, 'bar', 2]
+ * a[1..5] = 'foo' # => "foo"
+ * a # => [:foo, "foo"]
*/
static VALUE
rb_ary_aset(int argc, VALUE *argv, VALUE ary)
{
long offset, beg, len;
- VALUE rpl;
+ rb_check_arity(argc, 2, 3);
+ rb_ary_modify_check(ary);
if (argc == 3) {
- rb_ary_modify_check(ary);
beg = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
- goto range;
+ return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
}
- rb_check_arity(argc, 2, 2);
- rb_ary_modify_check(ary);
if (FIXNUM_P(argv[0])) {
offset = FIX2LONG(argv[0]);
- goto fixnum;
+ return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
}
if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
/* check if idx is Range */
- range:
- rpl = rb_ary_to_ary(argv[argc-1]);
- rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR_TRANSIENT(rpl), RARRAY_LEN(rpl));
- RB_GC_GUARD(rpl);
- return argv[argc-1];
+ return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
}
offset = NUM2LONG(argv[0]);
-fixnum:
- rb_ary_store(ary, offset, argv[1]);
- return argv[1];
+ return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
}
/*
* call-seq:
- * ary.insert(index, obj...) -> ary
- *
- * Inserts the given values before the element with the given +index+.
+ * array.insert(index, *objects) -> self
*
- * Negative indices count backwards from the end of the array, where +-1+ is
- * the last element. If a negative index is used, the given values will be
- * inserted after that element, so using an index of +-1+ will insert the
- * values at the end of the array.
+ * Inserts given +objects+ before or after the element at \Integer index +offset+;
+ * returns +self+.
*
- * a = %w{ a b c d }
- * a.insert(2, 99) #=> ["a", "b", 99, "c", "d"]
- * a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
+ * When +index+ is non-negative, inserts all given +objects+
+ * before the element at offset +index+:
+ * a = [:foo, 'bar', 2]
+ * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2]
+ *
+ * Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
+ * a = [:foo, 'bar', 2]
+ * a.insert(5, :bat, :bam)
+ * a # => [:foo, "bar", 2, nil, nil, :bat, :bam]
+ *
+ * Does nothing if no objects given:
+ * a = [:foo, 'bar', 2]
+ * a.insert(1)
+ * a.insert(50)
+ * a.insert(-50)
+ * a # => [:foo, "bar", 2]
+ *
+ * When +index+ is negative, inserts all given +objects+
+ * _after_ the element at offset <tt>index+self.size</tt>:
+ * a = [:foo, 'bar', 2]
+ * a.insert(-2, :bat, :bam)
+ * a # => [:foo, "bar", :bat, :bam, 2]
*/
static VALUE
@@ -2109,20 +2476,41 @@ ary_enum_length(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * ary.each {|item| block} -> ary
- * ary.each -> Enumerator
+ * array.each {|element| ... } -> self
+ * array.each -> Enumerator
+ *
+ * Iterates over array elements.
+ *
+ * When a block given, passes each successive array element to the block;
+ * returns +self+:
+ * a = [:foo, 'bar', 2]
+ * a.each {|element| puts "#{element.class} #{element}" }
*
- * Calls the given block once for each element in +self+, passing that element
- * as a parameter. Returns the array itself.
+ * Output:
+ * Symbol foo
+ * String bar
+ * Integer 2
*
- * If no block is given, an Enumerator is returned.
+ * Allows the array to be modified during iteration:
+ * a = [:foo, 'bar', 2]
+ * a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
*
- * a = [ "a", "b", "c" ]
- * a.each {|x| print x, " -- " }
+ * Output:
+ * foo
+ * bar
*
- * produces:
+ * When no block given, returns a new \Enumerator:
+ * a = [:foo, 'bar', 2]
+ * e = a.each
+ * e # => #<Enumerator: [:foo, "bar", 2]:each>
+ * a1 = e.each {|element| puts "#{element.class} #{element}" }
*
- * a -- b -- c --
+ * Output:
+ * Symbol foo
+ * String bar
+ * Integer 2
+ *
+ * Related: #each_index, #reverse_each.
*/
VALUE
@@ -2139,20 +2527,41 @@ rb_ary_each(VALUE ary)
/*
* call-seq:
- * ary.each_index {|index| block} -> ary
- * ary.each_index -> Enumerator
+ * array.each_index {|index| ... } -> self
+ * array.each_index -> Enumerator
+ *
+ * Iterates over array indexes.
+ *
+ * When a block given, passes each successive array index to the block;
+ * returns +self+:
+ * a = [:foo, 'bar', 2]
+ * a.each_index {|index| puts "#{index} #{a[index]}" }
*
- * Same as Array#each, but passes the +index+ of the element instead of the
- * element itself.
+ * Output:
+ * 0 foo
+ * 1 bar
+ * 2 2
*
- * An Enumerator is returned if no block is given.
+ * Allows the array to be modified during iteration:
+ * a = [:foo, 'bar', 2]
+ * a.each_index {|index| puts index; a.clear if index > 0 }
*
- * a = [ "a", "b", "c" ]
- * a.each_index {|x| print x, " -- " }
+ * Output:
+ * 0
+ * 1
*
- * produces:
+ * When 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]}"}
*
- * 0 -- 1 -- 2 --
+ * Output:
+ * 0 foo
+ * 1 bar
+ * 2 2
+ *
+ * Related: #each, #reverse_each.
*/
static VALUE
@@ -2169,17 +2578,40 @@ rb_ary_each_index(VALUE ary)
/*
* call-seq:
- * ary.reverse_each {|item| block} -> ary
- * ary.reverse_each -> Enumerator
- *
- * Same as Array#each, but traverses +self+ in reverse order.
- *
- * a = [ "a", "b", "c" ]
- * a.reverse_each {|x| print x, " " }
- *
- * produces:
- *
- * c b a
+ * array.reverse_each {|element| ... } -> self
+ * array.reverse_each -> Enumerator
+ *
+ * Iterates backwards over array elements.
+ *
+ * When a block given, passes, in reverse order, each element to the block;
+ * returns +self+:
+ * a = [:foo, 'bar', 2]
+ * a.reverse_each {|element| puts "#{element.class} #{element}" }
+ *
+ * Output:
+ * Integer 2
+ * String bar
+ * Symbol foo
+ *
+ * Allows the array to be modified during iteration:
+ * a = [:foo, 'bar', 2]
+ * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
+ *
+ * Output:
+ * 2
+ * bar
+ *
+ * When no block given, returns a new \Enumerator:
+ * a = [:foo, 'bar', 2]
+ * e = a.reverse_each
+ * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
+ * a1 = e.each {|element| puts "#{element.class} #{element}" }
+ * Output:
+ * Integer 2
+ * String bar
+ * Symbol foo
+ *
+ * Related: #each, #each_index.
*/
static VALUE
@@ -2202,12 +2634,9 @@ rb_ary_reverse_each(VALUE ary)
/*
* call-seq:
- * ary.length -> int
+ * array.length -> an_integer
*
- * Returns the number of elements in +self+. May be zero.
- *
- * [ 1, 2, 3, 4, 5 ].length #=> 5
- * [].length #=> 0
+ * Returns the count of elements in +self+.
*/
static VALUE
@@ -2219,11 +2648,10 @@ rb_ary_length(VALUE ary)
/*
* call-seq:
- * ary.empty? -> true or false
- *
- * Returns +true+ if +self+ contains no elements.
+ * array.empty? -> true or false
*
- * [].empty? #=> true
+ * Returns +true+ if the count of elements in +self+ is zero,
+ * +false+ otherwise.
*/
static VALUE
@@ -2275,7 +2703,7 @@ recursive_join(VALUE obj, VALUE argp, int recur)
return Qnil;
}
-static void
+static long
ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
{
long i;
@@ -2284,10 +2712,40 @@ ary_join_0(VALUE ary, VALUE sep, long max, VALUE result)
if (max > 0) rb_enc_copy(result, RARRAY_AREF(ary, 0));
for (i=0; i<max; i++) {
val = RARRAY_AREF(ary, i);
+ if (!RB_TYPE_P(val, T_STRING)) break;
if (i > 0 && !NIL_P(sep))
rb_str_buf_append(result, sep);
rb_str_buf_append(result, val);
}
+ return i;
+}
+
+static void
+ary_join_1_str(VALUE dst, VALUE src, int *first)
+{
+ rb_str_buf_append(dst, src);
+ if (*first) {
+ rb_enc_copy(dst, src);
+ *first = FALSE;
+ }
+}
+
+static void
+ary_join_1_ary(VALUE obj, VALUE ary, VALUE sep, VALUE result, VALUE val, int *first)
+{
+ if (val == ary) {
+ rb_raise(rb_eArgError, "recursive array join");
+ }
+ else {
+ VALUE args[4];
+
+ *first = FALSE;
+ args[0] = val;
+ args[1] = sep;
+ args[2] = result;
+ args[3] = (VALUE)first;
+ rb_exec_recursive(recursive_join, obj, (VALUE)args);
+ }
}
static void
@@ -2301,44 +2759,19 @@ ary_join_1(VALUE obj, VALUE ary, VALUE sep, long i, VALUE result, int *first)
val = RARRAY_AREF(ary, i);
if (RB_TYPE_P(val, T_STRING)) {
- str_join:
- rb_str_buf_append(result, val);
- if (*first) {
- rb_enc_copy(result, val);
- *first = FALSE;
- }
+ ary_join_1_str(result, val, first);
}
else if (RB_TYPE_P(val, T_ARRAY)) {
- obj = val;
- ary_join:
- if (val == ary) {
- rb_raise(rb_eArgError, "recursive array join");
- }
- else {
- VALUE args[4];
-
- *first = FALSE;
- args[0] = val;
- args[1] = sep;
- args[2] = result;
- args[3] = (VALUE)first;
- rb_exec_recursive(recursive_join, obj, (VALUE)args);
- }
+ ary_join_1_ary(val, ary, sep, result, val, first);
}
- else {
- tmp = rb_check_string_type(val);
- if (!NIL_P(tmp)) {
- val = tmp;
- goto str_join;
- }
- tmp = rb_check_array_type(val);
- if (!NIL_P(tmp)) {
- obj = val;
- val = tmp;
- goto ary_join;
- }
- val = rb_obj_as_string(val);
- goto str_join;
+ else if (!NIL_P(tmp = rb_check_string_type(val))) {
+ ary_join_1_str(result, tmp, first);
+ }
+ else if (!NIL_P(tmp = rb_check_array_type(val))) {
+ ary_join_1_ary(val, ary, sep, result, tmp, first);
+ }
+ else {
+ ary_join_1_str(result, rb_obj_as_string(val), first);
}
}
}
@@ -2361,9 +2794,11 @@ rb_ary_join(VALUE ary, VALUE sep)
if (NIL_P(tmp) || tmp != val) {
int first;
- result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10);
+ long n = RARRAY_LEN(ary);
+ if (i > n) i = n;
+ result = rb_str_buf_new(len + (n-i)*10);
rb_enc_associate(result, rb_usascii_encoding());
- ary_join_0(ary, sep, i, result);
+ i = ary_join_0(ary, sep, i, result);
first = i == 0;
ary_join_1(ary, ary, sep, i, result, &first);
return result;
@@ -2382,22 +2817,27 @@ rb_ary_join(VALUE ary, VALUE sep)
/*
* call-seq:
- * ary.join(separator=$,) -> str
- *
- * Returns a string created by converting each element of the array to
- * a string, separated by the given +separator+.
- * If the +separator+ is +nil+, it uses current <code>$,</code>.
- * If both the +separator+ and <code>$,</code> are +nil+,
- * it uses an empty string.
- *
- * [ "a", "b", "c" ].join #=> "abc"
- * [ "a", "b", "c" ].join("-") #=> "a-b-c"
- *
- * For nested arrays, join is applied recursively:
- *
- * [ "a", [1, 2, [:x, :y]], "b" ].join("-") #=> "a-1-2-x-y-b"
+ * array.join ->new_string
+ * array.join(separator = $,) -> new_string
+ *
+ * Returns the new \String formed by joining the array elements after conversion.
+ * For each element +element+
+ * - Uses <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>.
+ *
+ * With no argument, joins using the output field separator, <tt>$,</tt>:
+ * a = [:foo, 'bar', 2]
+ * $, # => nil
+ * a.join # => "foobar2"
+ *
+ * With \string argument +separator+, joins using that separator:
+ * a = [:foo, 'bar', 2]
+ * a.join("\n") # => "foo\nbar\n2"
+ *
+ * Joins recursively for nested Arrays:
+ * a = [:foo, [:bar, [:baz, :bat]]]
+ * a.join # => "foobarbazbat"
*/
-
static VALUE
rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
{
@@ -2406,7 +2846,7 @@ rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
sep = rb_output_fs;
if (!NIL_P(sep)) {
- rb_warn("$, is set to non-nil value");
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
}
}
@@ -2433,13 +2873,14 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
/*
* call-seq:
- * ary.inspect -> string
- * ary.to_s -> string
+ * array.inspect -> new_string
*
- * Creates a string representation of +self+, by calling #inspect
- * on each element.
+ * Returns the new \String formed by calling method <tt>#inspect</tt>
+ * on each array element:
+ * a = [:foo, 'bar', 2]
+ * a.inspect # => "[:foo, \"bar\", 2]"
*
- * [ "a", "b", "c" ].to_s #=> "[\"a\", \"b\", \"c\"]"
+ * Array#to_s is an alias for Array#inspect.
*/
static VALUE
@@ -2457,11 +2898,20 @@ rb_ary_to_s(VALUE ary)
/*
* call-seq:
- * ary.to_a -> ary
- *
- * Returns +self+.
- *
- * If called on a subclass of Array, converts the receiver to an Array object.
+ * to_a -> self or new_array
+ *
+ * When +self+ is an instance of \Array, returns +self+:
+ * a = [:foo, 'bar', 2]
+ * a.to_a # => [:foo, "bar", 2]
+ *
+ * Otherwise, returns a new \Array containing the elements of +self+:
+ * class MyArray < Array; end
+ * a = MyArray.new(['foo', 'bar', 'two'])
+ * a.instance_of?(Array) # => false
+ * a.kind_of?(Array) # => true
+ * a1 = a.to_a
+ * a1 # => ["foo", "bar", "two"]
+ * a1.class # => Array # Not MyArray
*/
static VALUE
@@ -2477,20 +2927,24 @@ rb_ary_to_a(VALUE ary)
/*
* call-seq:
- * ary.to_h -> hash
- * ary.to_h {|item| block } -> hash
- *
- * Returns the result of interpreting <i>ary</i> as an array of
- * <tt>[key, value]</tt> pairs.
- *
- * [[:foo, :bar], [1, 2]].to_h
- * # => {:foo => :bar, 1 => 2}
- *
- * If a block is given, the results of the block on each element of
- * the array will be used as pairs.
- *
- * ["foo", "bar"].to_h {|s| [s.ord, s]}
- * # => {102=>"foo", 98=>"bar"}
+ * array.to_h -> new_hash
+ * array.to_h {|item| ... } -> new_hash
+ *
+ * Returns a new \Hash formed from +self+.
+ *
+ * When a block is given, calls the block with each array element;
+ * the block must return a 2-element \Array whose two elements
+ * form a key-value pair in the returned \Hash:
+ * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
+ * h = a.to_h {|item| [item, item] }
+ * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
+ *
+ * When no block is given, +self+ must be an \Array of 2-element sub-arrays,
+ * each sub-array is formed into a key-value pair in the new \Hash:
+ * [].to_h # => {}
+ * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
+ * h = a.to_h
+ * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
*/
static VALUE
@@ -2519,7 +2973,7 @@ rb_ary_to_h(VALUE ary)
/*
* call-seq:
- * ary.to_ary -> ary
+ * array.to_ary -> self
*
* Returns +self+.
*/
@@ -2558,13 +3012,11 @@ rb_ary_reverse(VALUE ary)
/*
* call-seq:
- * ary.reverse! -> ary
+ * array.reverse! -> self
*
- * Reverses +self+ in place.
- *
- * a = [ "a", "b", "c" ]
- * a.reverse! #=> ["c", "b", "a"]
- * a #=> ["c", "b", "a"]
+ * Reverses +self+ in place:
+ * a = ['foo', 'bar', 'two']
+ * a.reverse! # => ["two", "bar", "foo"]
*/
static VALUE
@@ -2575,12 +3027,12 @@ rb_ary_reverse_bang(VALUE ary)
/*
* call-seq:
- * ary.reverse -> new_ary
- *
- * Returns a new array containing +self+'s elements in reverse order.
+ * array.reverse -> new_array
*
- * [ "a", "b", "c" ].reverse #=> ["c", "b", "a"]
- * [ 1 ].reverse #=> [1]
+ * Returns a new \Array with the elements of +self+ in reverse order.
+ * a = ['foo', 'bar', 'two']
+ * a1 = a.reverse
+ * a1 # => ["two", "bar", "foo"]
*/
static VALUE
@@ -2607,10 +3059,20 @@ rotate_count(long cnt, long len)
static void
ary_rotate_ptr(VALUE *ptr, long len, long cnt)
{
- --len;
- if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
- if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
- if (len > 0) ary_reverse(ptr, ptr + len);
+ if (cnt == 1) {
+ VALUE tmp = *ptr;
+ memmove(ptr, ptr + 1, sizeof(VALUE)*(len - 1));
+ *(ptr + len - 1) = tmp;
+ } else if (cnt == len - 1) {
+ VALUE tmp = *(ptr + len - 1);
+ memmove(ptr + 1, ptr, sizeof(VALUE)*(len - 1));
+ *ptr = tmp;
+ } else {
+ --len;
+ if (cnt < len) ary_reverse(ptr + cnt, ptr + len);
+ if (--cnt > 0) ary_reverse(ptr, ptr + cnt);
+ if (len > 0) ary_reverse(ptr, ptr + len);
+ }
}
VALUE
@@ -2620,7 +3082,7 @@ rb_ary_rotate(VALUE ary, long cnt)
if (cnt != 0) {
long len = RARRAY_LEN(ary);
- if (len > 0 && (cnt = rotate_count(cnt, len)) > 0) {
+ if (len > 1 && (cnt = rotate_count(cnt, len)) > 0) {
RARRAY_PTR_USE_TRANSIENT(ary, ptr, ary_rotate_ptr(ptr, len, cnt));
return ary;
}
@@ -2630,19 +3092,41 @@ rb_ary_rotate(VALUE ary, long cnt)
/*
* call-seq:
- * ary.rotate!(count=1) -> ary
- *
- * Rotates +self+ in place so that the element at +count+ comes first, and
- * returns +self+.
- *
- * If +count+ is negative then it rotates in the opposite direction, starting
- * from the end of the array where +-1+ is the last element.
- *
- * a = [ "a", "b", "c", "d" ]
- * a.rotate! #=> ["b", "c", "d", "a"]
- * a #=> ["b", "c", "d", "a"]
- * a.rotate!(2) #=> ["d", "a", "b", "c"]
- * a.rotate!(-3) #=> ["a", "b", "c", "d"]
+ * array.rotate! -> self
+ * array.rotate!(count) -> self
+ *
+ * Rotates +self+ in place by moving elements from one end to the other; returns +self+.
+ *
+ * When no argument given, rotates the first element to the last position:
+ * a = [:foo, 'bar', 2, 'bar']
+ * a.rotate! # => ["bar", 2, "bar", :foo]
+ *
+ * When given a non-negative \Integer +count+,
+ * rotates +count+ elements from the beginning to the end:
+ * a = [:foo, 'bar', 2]
+ * a.rotate!(2)
+ * a # => [2, :foo, "bar"]
+ *
+ * If +count+ is large, uses <tt>count % array.size</tt> as the count:
+ * a = [:foo, 'bar', 2]
+ * a.rotate!(20)
+ * a # => [2, :foo, "bar"]
+ *
+ * If +count+ is zero, returns +self+ unmodified:
+ * a = [:foo, 'bar', 2]
+ * a.rotate!(0)
+ * a # => [:foo, "bar", 2]
+ *
+ * When given a negative Integer +count+, rotates in the opposite direction,
+ * from end to beginning:
+ * a = [:foo, 'bar', 2]
+ * a.rotate!(-2)
+ * a # => ["bar", 2, :foo]
+ *
+ * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
+ * a = [:foo, 'bar', 2]
+ * a.rotate!(-5)
+ * a # => ["bar", 2, :foo]
*/
static VALUE
@@ -2655,19 +3139,44 @@ rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.rotate(count=1) -> new_ary
- *
- * Returns a new array by rotating +self+ so that the element at +count+ is
- * the first element of the new array.
- *
- * If +count+ is negative then it rotates in the opposite direction, starting
- * from the end of +self+ where +-1+ is the last element.
- *
- * a = [ "a", "b", "c", "d" ]
- * a.rotate #=> ["b", "c", "d", "a"]
- * a #=> ["a", "b", "c", "d"]
- * a.rotate(2) #=> ["c", "d", "a", "b"]
- * a.rotate(-3) #=> ["b", "c", "d", "a"]
+ * array.rotate -> new_array
+ * array.rotate(count) -> new_array
+ *
+ * Returns a new \Array formed from +self+ with elements
+ * rotated from one end to the other.
+ *
+ * When no argument given, returns a new \Array that is like +self+,
+ * except that the first element has been rotated to the last position:
+ * a = [:foo, 'bar', 2, 'bar']
+ * a1 = a.rotate
+ * a1 # => ["bar", 2, "bar", :foo]
+ *
+ * When given a non-negative \Integer +count+,
+ * returns a new \Array with +count+ elements rotated from the beginning to the end:
+ * a = [:foo, 'bar', 2]
+ * a1 = a.rotate(2)
+ * a1 # => [2, :foo, "bar"]
+ *
+ * If +count+ is large, uses <tt>count % array.size</tt> as the count:
+ * a = [:foo, 'bar', 2]
+ * a1 = a.rotate(20)
+ * a1 # => [2, :foo, "bar"]
+ *
+ * If +count+ is zero, returns a copy of +self+, unmodified:
+ * a = [:foo, 'bar', 2]
+ * a1 = a.rotate(0)
+ * a1 # => [:foo, "bar", 2]
+ *
+ * When given a negative \Integer +count+, rotates in the opposite direction,
+ * from end to beginning:
+ * a = [:foo, 'bar', 2]
+ * a1 = a.rotate(-2)
+ * a1 # => ["bar", 2, :foo]
+ *
+ * If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
+ * a = [:foo, 'bar', 2]
+ * a1 = a.rotate(-5)
+ * a1 # => ["bar", 2, :foo]
*/
static VALUE
@@ -2730,7 +3239,7 @@ sort_2(const void *ap, const void *bp, void *dummy)
VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
int n;
- if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, Fixnum)) {
+ if (FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data->cmp_opt, Integer)) {
if ((long)a > (long)b) return 1;
if ((long)a < (long)b) return -1;
return 0;
@@ -2751,26 +3260,38 @@ sort_2(const void *ap, const void *bp, void *dummy)
/*
* call-seq:
- * ary.sort! -> ary
- * ary.sort! {|a, b| block} -> ary
- *
- * Sorts +self+ in place.
- *
- * Comparisons for the sort will be done using the <code><=></code> operator
- * or using an optional code block.
- *
- * The block must implement a comparison between +a+ and +b+ and return
- * an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+
- * are equivalent, or an integer greater than 0 when +a+ follows +b+.
- *
- * The result is not guaranteed to be stable. When the comparison of two
- * elements returns +0+, the order of the elements is unpredictable.
- *
- * ary = [ "d", "a", "e", "c", "b" ]
- * ary.sort! #=> ["a", "b", "c", "d", "e"]
- * ary.sort! {|a, b| b <=> a} #=> ["e", "d", "c", "b", "a"]
- *
- * See also Enumerable#sort_by.
+ * array.sort! -> self
+ * array.sort! {|a, b| ... } -> self
+ *
+ * Returns +self+ with its elements sorted in place.
+ *
+ * With no block, compares elements using operator <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"]
*/
VALUE
@@ -2835,31 +3356,40 @@ rb_ary_sort_bang(VALUE ary)
/*
* call-seq:
- * ary.sort -> new_ary
- * ary.sort {|a, b| block} -> new_ary
- *
- * Returns a new array created by sorting +self+.
- *
- * Comparisons for the sort will be done using the <code><=></code> operator
- * or using an optional code block.
- *
- * The block must implement a comparison between +a+ and +b+ and return
- * an integer less than 0 when +b+ follows +a+, +0+ when +a+ and +b+
- * are equivalent, or an integer greater than 0 when +a+ follows +b+.
- *
- * The result is not guaranteed to be stable. When the comparison of two
- * elements returns +0+, the order of the elements is unpredictable.
- *
- * ary = [ "d", "a", "e", "c", "b" ]
- * ary.sort #=> ["a", "b", "c", "d", "e"]
- * ary.sort {|a, b| b <=> a} #=> ["e", "d", "c", "b", "a"]
- *
- * To produce the reverse order, the following can also be used
- * (and may be faster):
- *
- * ary.sort.reverse! #=> ["e", "d", "c", "b", "a"]
- *
- * See also Enumerable#sort_by.
+ * array.sort -> new_array
+ * array.sort {|a, b| ... } -> new_array
+ *
+ * Returns a new \Array whose elements are those from +self+, sorted.
+ *
+ * With no block, compares elements using operator <tt><=></tt>
+ * (see Comparable):
+ * a = 'abcde'.split('').shuffle
+ * a # => ["e", "b", "d", "a", "c"]
+ * a1 = a.sort
+ * a1 # => ["a", "b", "c", "d", "e"]
+ *
+ * With a block, calls the block with each element pair;
+ * for each element pair +a+ and +b+, the block should return an integer:
+ * - Negative when +b+ is to follow +a+.
+ * - Zero when +a+ and +b+ are equivalent.
+ * - Positive when +a+ is to follow +b+.
+ *
+ * Example:
+ * a = 'abcde'.split('').shuffle
+ * a # => ["e", "b", "d", "a", "c"]
+ * a1 = a.sort {|a, b| a <=> b }
+ * a1 # => ["a", "b", "c", "d", "e"]
+ * a2 = a.sort {|a, b| b <=> a }
+ * a2 # => ["e", "d", "c", "b", "a"]
+ *
+ * When the block returns zero, the order for +a+ and +b+ is indeterminate,
+ * and may be unstable:
+ * a = 'abcde'.split('').shuffle
+ * a # => ["e", "b", "d", "a", "c"]
+ * a1 = a.sort {|a, b| 0 }
+ * a1 # => ["c", "e", "b", "d", "a"]
+ *
+ * Related: Enumerable#sort_by.
*/
VALUE
@@ -2874,55 +3404,93 @@ static VALUE rb_ary_bsearch_index(VALUE ary);
/*
* call-seq:
- * ary.bsearch {|x| block } -> elem
+ * array.bsearch {|element| ... } -> object
+ * array.bsearch -> new_enumerator
+ *
+ * Returns an element from +self+ selected by a binary search.
+ * +self+ should be sorted, but this is not checked.
*
* By using binary search, finds a value from this array which meets
- * the given condition in O(log n) where n is the size of the array.
- *
- * You can use this method in two modes: a find-minimum mode and
- * a find-any mode. In either case, the elements of the array must be
- * monotone (or sorted) with respect to the block.
- *
- * In find-minimum mode (this is a good choice for typical use cases),
- * the block must always return true or false, and there must be an index i
- * (0 <= i <= ary.size) so that:
- *
- * - the block returns false for any element whose index is less than
- * i, and
- * - the block returns true for any element whose index is greater
- * than or equal to i.
- *
- * This method returns the i-th element. If i is equal to ary.size,
- * it returns nil.
- *
- * ary = [0, 4, 7, 10, 12]
- * ary.bsearch {|x| x >= 4 } #=> 4
- * ary.bsearch {|x| x >= 6 } #=> 7
- * ary.bsearch {|x| x >= -1 } #=> 0
- * ary.bsearch {|x| x >= 100 } #=> nil
- *
- * In find-any mode (this behaves like libc's bsearch(3)), the block
- * must always return a number, and there must be two indices i and j
- * (0 <= i <= j <= ary.size) so that:
- *
- * - the block returns a positive number for ary[k] if 0 <= k < i,
- * - the block returns zero for ary[k] if i <= k < j, and
- * - the block returns a negative number for ary[k] if
- * j <= k < ary.size.
- *
- * Under this condition, this method returns any element whose index
- * is within i...j. If i is equal to j (i.e., there is no element
- * that satisfies the block), this method returns nil.
- *
- * ary = [0, 4, 7, 10, 12]
- * # try to find v such that 4 <= v < 8
- * ary.bsearch {|x| 1 - x / 4 } #=> 4 or 7
- * # try to find v such that 8 <= v < 10
- * ary.bsearch {|x| 4 - x / 2 } #=> nil
- *
- * You must not mix the two modes at a time; the block must always
- * return either true/false, or always return a number. It is
- * undefined which value is actually picked up at each iteration.
+ * the given condition in <tt>O(log n)</tt> where +n+ is the size of the array.
+ *
+ * There are two search modes:
+ * - <b>Find-minimum mode</b>: the block should return +true+ or +false+.
+ * - <b>Find-any mode</b>: the block should return a numeric value.
+ *
+ * The block should not mix the modes by and sometimes returning +true+ or +false+
+ * and sometimes returning a numeric value, but this is not checked.
+ *
+ * <b>Find-Minimum Mode</b>
+ *
+ * In find-minimum mode, the block always returns +true+ or +false+.
+ * The further requirement (though not checked) is that
+ * there are no indexes +i+ and +j+ such that:
+ * - <tt>0 <= i < j <= self.size</tt>.
+ * - The block returns +true+ for <tt>self[i]</tt> and +false+ for <tt>self[j]</tt>.
+ *
+ * In find-minimum mode, method bsearch returns the first element for which the block returns true.
+ *
+ * Examples:
+ * a = [0, 4, 7, 10, 12]
+ * a.bsearch {|x| x >= 4 } # => 4
+ * a.bsearch {|x| x >= 6 } # => 7
+ * a.bsearch {|x| x >= -1 } # => 0
+ * a.bsearch {|x| x >= 100 } # => nil
+ *
+ * Less formally: the block is such that all +false+-evaluating elements
+ * precede all +true+-evaluating elements.
+ *
+ * These make sense as blocks in find-minimum mode:
+ * a = [0, 4, 7, 10, 12]
+ * a.map {|x| x >= 4 } # => [false, true, true, true, true]
+ * a.map {|x| x >= 6 } # => [false, false, true, true, true]
+ * a.map {|x| x >= -1 } # => [true, true, true, true, true]
+ * a.map {|x| x >= 100 } # => [false, false, false, false, false]
+ *
+ * This would not make sense:
+ * a = [0, 4, 7, 10, 12]
+ * a.map {|x| x == 7 } # => [false, false, true, false, false]
+ *
+ * <b>Find-Any Mode</b>
+ *
+ * In find-any mode, the block always returns a numeric value.
+ * The further requirement (though not checked) is that
+ * there are no indexes +i+ and +j+ such that:
+ * - <tt>0 <= i < j <= self.size</tt>.
+ * - The block returns a negative value for <tt>self[i]</tt>
+ * and a positive value for <tt>self[j]</tt>.
+ * - The block returns a negative value for <tt>self[i]</tt> and zero <tt>self[j]</tt>.
+ * - The block returns zero for <tt>self[i]</tt> and a positive value for <tt>self[j]</tt>.
+ *
+ * In find-any mode, method bsearch returns some element
+ * for which the block returns zero, or +nil+ if no such element is found.
+ *
+ * Examples:
+ * a = [0, 4, 7, 10, 12]
+ * a.bsearch {|element| 7 <=> element } # => 7
+ * a.bsearch {|element| -1 <=> element } # => nil
+ * a.bsearch {|element| 5 <=> element } # => nil
+ * a.bsearch {|element| 15 <=> element } # => nil
+ *
+ * Less formally: the block is such that:
+ * - All positive-evaluating elements precede all zero-evaluating elements.
+ * - All positive-evaluating elements precede all negative-evaluating elements.
+ * - All zero-evaluating elements precede all negative-evaluating elements.
+ *
+ * These make sense as blocks in find-any mode:
+ * a = [0, 4, 7, 10, 12]
+ * a.map {|element| 7 <=> element } # => [1, 1, 0, -1, -1]
+ * a.map {|element| -1 <=> element } # => [-1, -1, -1, -1, -1]
+ * a.map {|element| 5 <=> element } # => [1, 1, -1, -1, -1]
+ * a.map {|element| 15 <=> element } # => [1, 1, 1, 1, 1]
+ *
+ * This would not make sense:
+ * a = [0, 4, 7, 10, 12]
+ * a.map {|element| element <=> 7 } # => [-1, -1, 0, 1, 1]
+ *
+ * Returns an enumerator if no block given:
+ * a = [0, 4, 7, 10, 12]
+ * a.bsearch # => #<Enumerator: [0, 4, 7, 10, 12]:bsearch>
*/
static VALUE
@@ -2938,15 +3506,11 @@ rb_ary_bsearch(VALUE ary)
/*
* call-seq:
- * ary.bsearch_index {|x| block } -> int or nil
+ * array.bsearch_index {|element| ... } -> integer or nil
+ * array.bsearch_index -> new_enumerator
*
- * By using binary search, finds an index of a value from this array which
- * meets the given condition in O(log n) where n is the size of the array.
- *
- * It supports two modes, depending on the nature of the block. They are
- * exactly the same as in the case of the #bsearch method, with the only difference
- * being that this method returns the index of the element instead of the
- * element itself. For more details consult the documentation for #bsearch.
+ * Searches +self+ as described at method #bsearch,
+ * but returns the _index_ of the found element instead of the element itself.
*/
static VALUE
@@ -3005,18 +3569,26 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
/*
* call-seq:
- * ary.sort_by! {|obj| block} -> ary
- * ary.sort_by! -> Enumerator
+ * array.sort_by! {|element| ... } -> self
+ * array.sort_by! -> new_enumerator
+ *
+ * Sorts the elements of +self+ in place,
+ * using an ordering determined by the block; returns self.
+ *
+ * Calls the block with each successive element;
+ * sorts elements based on the values returned from the block.
*
- * Sorts +self+ in place using a set of keys generated by mapping the
- * values in +self+ through the given block.
+ * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
*
- * The result is not guaranteed to be stable. When two keys are equal,
- * the order of the corresponding elements is unpredictable.
+ * This example sorts strings based on their sizes:
+ * a = ['aaaa', 'bbb', 'cc', 'd']
+ * a.sort_by! {|element| element.size }
+ * a # => ["d", "cc", "bbb", "aaaa"]
*
- * If no block is given, an Enumerator is returned instead.
+ * Returns a new \Enumerator if no block given:
*
- * See also Enumerable#sort_by.
+ * a = ['aaaa', 'bbb', 'cc', 'd']
+ * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
*/
static VALUE
@@ -3034,23 +3606,21 @@ rb_ary_sort_by_bang(VALUE ary)
/*
* call-seq:
- * ary.collect {|item| block} -> new_ary
- * ary.map {|item| block} -> new_ary
- * ary.collect -> Enumerator
- * ary.map -> Enumerator
- *
- * Invokes the given block once for each element of +self+.
- *
- * Creates a new array containing the values returned by the block.
+ * array.map {|element| ... } -> new_array
+ * array.map -> new_enumerator
*
- * See also Enumerable#collect.
+ * Calls the block, if given, with each element of +self+;
+ * returns a new \Array whose elements are the return values from the block:
+ * a = [:foo, 'bar', 2]
+ * a1 = a.map {|element| element.class }
+ * a1 # => [Symbol, String, Integer]
*
- * If no block is given, an Enumerator is returned instead.
+ * Returns a new \Enumerator if no block given:
+ * a = [:foo, 'bar', 2]
+ * a1 = a.map
+ * a1 # => #<Enumerator: [:foo, "bar", 2]:map>
*
- * a = [ "a", "b", "c", "d" ]
- * a.collect {|x| x + "!"} #=> ["a!", "b!", "c!", "d!"]
- * a.map.with_index {|x, i| x * i} #=> ["", "b", "cc", "ddd"]
- * a #=> ["a", "b", "c", "d"]
+ * Array#collect is an alias for Array#map.
*/
static VALUE
@@ -3070,23 +3640,20 @@ rb_ary_collect(VALUE ary)
/*
* call-seq:
- * ary.collect! {|item| block } -> ary
- * ary.map! {|item| block } -> ary
- * ary.collect! -> Enumerator
- * ary.map! -> Enumerator
+ * array.map! {|element| ... } -> self
+ * array.map! -> new_enumerator
*
- * Invokes the given block once for each element of +self+, replacing the
- * element with the value returned by the block.
+ * Calls the block, if given, with each element;
+ * replaces the element with the block's return value:
+ * a = [:foo, 'bar', 2]
+ * a.map! { |element| element.class } # => [Symbol, String, Integer]
*
- * See also Enumerable#collect.
+ * Returns a new \Enumerator if no block given:
+ * a = [:foo, 'bar', 2]
+ * a1 = a.map!
+ * a1 # => #<Enumerator: [:foo, "bar", 2]:map!>
*
- * If no block is given, an Enumerator is returned instead.
- *
- * a = [ "a", "b", "c", "d" ]
- * a.map! {|x| x + "!" }
- * a #=> [ "a!", "b!", "c!", "d!" ]
- * a.collect!.with_index {|x, i| x[0...i] }
- * a #=> ["", "b", "c!", "d!"]
+ * Array#collect! is an alias for Array#map!.
*/
static VALUE
@@ -3158,20 +3725,36 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
/*
* call-seq:
- * ary.values_at(selector, ...) -> new_ary
+ * array.values_at(*indexes) -> new_array
+ *
+ * Returns a new \Array whose elements are the elements
+ * of +self+ at the given \Integer +indexes+.
+ *
+ * For each positive +index+, returns the element at offset +index+:
+ * a = [:foo, 'bar', 2]
+ * a.values_at(0, 2) # => [:foo, 2]
*
- * Returns an array containing the elements in +self+ corresponding to the
- * given +selector+(s).
+ * The given +indexes+ may be in any order, and may repeat:
+ * a = [:foo, 'bar', 2]
+ * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2]
*
- * The selectors may be either integer indices or ranges.
+ * Assigns +nil+ for an +index+ that is too large:
+ * a = [:foo, 'bar', 2]
+ * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
*
- * See also Array#select.
+ * Returns a new empty \Array if no arguments given.
*
- * a = %w{ a b c d e f }
- * a.values_at(1, 3, 5) # => ["b", "d", "f"]
- * a.values_at(1, 3, 5, 7) # => ["b", "d", "f", nil]
- * a.values_at(-1, -2, -2, -7) # => ["f", "e", "e", nil]
- * a.values_at(4..6, 3...6) # => ["e", "f", nil, "d", "e", "f"]
+ * For each negative +index+, counts backward from the end of the array:
+ * a = [:foo, 'bar', 2]
+ * a.values_at(-1, -3) # => [2, :foo]
+ *
+ * Assigns +nil+ for an +index+ that is too small:
+ * a = [:foo, 'bar', 2]
+ * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
+ *
+ * The given +indexes+ may have a mixture of signs:
+ * a = [:foo, 'bar', 2]
+ * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
*/
static VALUE
@@ -3189,22 +3772,19 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.select {|item| block} -> new_ary
- * ary.select -> Enumerator
- * ary.filter {|item| block} -> new_ary
- * ary.filter -> Enumerator
- *
- * Returns a new array containing all elements of +ary+
- * for which the given +block+ returns a true value.
+ * array.select {|element| ... } -> new_array
+ * array.select -> new_enumerator
*
- * If no block is given, an Enumerator is returned instead.
+ * Calls the block, if given, with each element of +self+;
+ * returns a new \Array containing those elements of +self+
+ * for which the block returns a truthy value:
+ * a = [:foo, 'bar', 2, :bam]
+ * a1 = a.select {|element| element.to_s.start_with?('b') }
+ * a1 # => ["bar", :bam]
*
- * [1,2,3,4,5].select {|num| num.even? } #=> [2, 4]
- *
- * a = %w[ a b c d e f ]
- * a.select {|v| v =~ /[aeiou]/ } #=> ["a", "e"]
- *
- * See also Enumerable#select.
+ * Returns a new \Enumerator if no block given:
+ * a = [:foo, 'bar', 2, :bam]
+ * a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
*
* Array#filter is an alias for Array#select.
*/
@@ -3258,6 +3838,7 @@ select_bang_ensure(VALUE a)
if (i2 < len && i2 < i1) {
long tail = 0;
+ rb_ary_modify(ary);
if (i1 < len) {
tail = len - i1;
RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
@@ -3271,21 +3852,21 @@ select_bang_ensure(VALUE a)
/*
* call-seq:
- * ary.select! {|item| block } -> ary or nil
- * ary.select! -> Enumerator
- * ary.filter! {|item| block } -> ary or nil
- * ary.filter! -> Enumerator
+ * array.select! {|element| ... } -> self or nil
+ * array.select! -> new_enumerator
*
- * Invokes the given block passing in successive elements from +self+,
- * deleting elements for which the block returns a +false+ value.
+ * Calls the block, if given with each element of +self+;
+ * removes from +self+ those elements for which the block returns +false+ or +nil+.
*
- * The array may not be changed instantly every time the block is called.
+ * Returns +self+ if any elements were removed:
+ * a = [:foo, 'bar', 2, :bam]
+ * a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
*
- * If changes were made, it will return +self+, otherwise it returns +nil+.
+ * Returns +nil+ if no elements were removed.
*
- * If no block is given, an Enumerator is returned instead.
- *
- * See also Array#keep_if.
+ * Returns a new \Enumerator if no block given:
+ * a = [:foo, 'bar', 2, :bam]
+ * a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
*
* Array#filter! is an alias for Array#select!.
*/
@@ -3305,19 +3886,17 @@ rb_ary_select_bang(VALUE ary)
/*
* call-seq:
- * ary.keep_if {|item| block} -> ary
- * ary.keep_if -> Enumerator
- *
- * Deletes every element of +self+ for which the given block evaluates to
- * +false+, and returns +self+.
+ * array.keep_if {|element| ... } -> self
+ * array.keep_if -> new_enumeration
*
- * If no block is given, an Enumerator is returned instead.
+ * Retains those elements for which the block returns a truthy value;
+ * deletes all other elements; returns +self+:
+ * a = [:foo, 'bar', 2, :bam]
+ * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
*
- * a = %w[ a b c d e f ]
- * a.keep_if {|v| v =~ /[aeiou]/ } #=> ["a", "e"]
- * a #=> ["a", "e"]
- *
- * See also Array#select!.
+ * Returns a new \Enumerator if no block given:
+ * a = [:foo, 'bar', 2, :bam]
+ * a.keep_if # => #<Enumerator: [:foo, "bar", 2, :bam]:keep_if>
*/
static VALUE
@@ -3343,22 +3922,34 @@ ary_resize_smaller(VALUE ary, long len)
/*
* call-seq:
- * ary.delete(obj) -> item or nil
- * ary.delete(obj) {block} -> item or result of block
- *
- * Deletes all items from +self+ that are equal to +obj+.
- *
- * Returns the last deleted item, or +nil+ if no matching item is found.
- *
- * If the optional code block is given, the result of the block is returned if
- * the item is not found. (To remove +nil+ elements and get an informative
- * return value, use Array#compact!)
- *
- * a = [ "a", "b", "b", "b", "c" ]
- * a.delete("b") #=> "b"
- * a #=> ["a", "c"]
- * a.delete("z") #=> nil
- * a.delete("z") {"not found"} #=> "not found"
+ * array.delete(obj) -> deleted_object
+ * array.delete(obj) {|nosuch| ... } -> deleted_object or block_return
+ *
+ * Removes zero or more elements from +self+; returns +self+.
+ *
+ * When no block is given,
+ * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>;
+ * returns the last deleted element:
+ * s1 = 'bar'; s2 = 'bar'
+ * a = [:foo, s1, 2, s2]
+ * a.delete('bar') # => "bar"
+ * a # => [:foo, 2]
+ *
+ * Returns +nil+ if no elements removed.
+ *
+ * When a block is given,
+ * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>.
+ *
+ * If any such elements are found, ignores the block
+ * and returns the last deleted element:
+ * s1 = 'bar'; s2 = 'bar'
+ * a = [:foo, s1, 2, s2]
+ * deleted_obj = a.delete('bar') {|obj| fail 'Cannot happen' }
+ * a # => [:foo, 2]
+ *
+ * If no such elements are found, returns the block's return value:
+ * a = [:foo, 'bar', 2]
+ * a.delete(:nosuch) {|obj| "#{obj} not found" } # => "nosuch not found"
*/
VALUE
@@ -3439,17 +4030,23 @@ rb_ary_delete_at(VALUE ary, long pos)
/*
* call-seq:
- * ary.delete_at(index) -> obj or nil
+ * array.delete_at(index) -> deleted_object or nil
*
- * Deletes the element at the specified +index+, returning that element, or
- * +nil+ if the +index+ is out of range.
+ * Deletes an element from +self+, per the given \Integer +index+.
*
- * See also Array#slice!
+ * When +index+ is non-negative, deletes the element at offset +index+:
+ * a = [:foo, 'bar', 2]
+ * a.delete_at(1) # => "bar"
+ * a # => [:foo, 2]
*
- * a = ["ant", "bat", "cat", "dog"]
- * a.delete_at(2) #=> "cat"
- * a #=> ["ant", "bat", "dog"]
- * a.delete_at(99) #=> nil
+ * 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.
*/
static VALUE
@@ -3458,63 +4055,118 @@ rb_ary_delete_at_m(VALUE ary, VALUE pos)
return rb_ary_delete_at(ary, NUM2LONG(pos));
}
+static VALUE
+ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
+{
+ const long orig_len = RARRAY_LEN(ary);
+
+ if (len < 0) {
+ return Qnil;
+ }
+ else if (pos < -orig_len) {
+ return Qnil;
+ }
+ else if (pos < 0) {
+ pos += orig_len;
+ }
+ else if (orig_len < pos) {
+ return Qnil;
+ }
+ if (orig_len < pos + len) {
+ len = orig_len - pos;
+ }
+ if (len == 0) {
+ return rb_ary_new2(0);
+ }
+ else {
+ VALUE arg2 = rb_ary_new4(len, RARRAY_CONST_PTR_TRANSIENT(ary)+pos);
+ rb_ary_splice(ary, pos, len, 0, 0);
+ return arg2;
+ }
+}
+
/*
* call-seq:
- * ary.slice!(index) -> obj or nil
- * ary.slice!(start, length) -> new_ary or nil
- * ary.slice!(range) -> new_ary or nil
- *
- * Deletes the element(s) given by an +index+ (optionally up to +length+
- * elements) or by a +range+.
- *
- * Returns the deleted object (or objects), or +nil+ if the +index+ is out of
- * range.
- *
- * a = [ "a", "b", "c" ]
- * a.slice!(1) #=> "b"
- * a #=> ["a", "c"]
- * a.slice!(-1) #=> "c"
- * a #=> ["a"]
- * a.slice!(100) #=> nil
- * a #=> ["a"]
+ * array.slice!(n) -> object or nil
+ * array.slice!(start, length) -> new_array or nil
+ * array.slice!(range) -> new_array or nil
+ *
+ * Removes and returns elements from +self+.
+ *
+ * When the only argument is an \Integer +n+,
+ * removes and returns the _nth_ element in +self+:
+ * a = [:foo, 'bar', 2]
+ * a.slice!(1) # => "bar"
+ * a # => [:foo, 2]
+ *
+ * If +n+ is negative, counts backwards from the end of +self+:
+ * a = [:foo, 'bar', 2]
+ * a.slice!(-1) # => 2
+ * a # => [:foo, "bar"]
+ *
+ * If +n+ is out of range, returns +nil+.
+ *
+ * When the only arguments are Integers +start+ and +length+,
+ * removes +length+ elements from +self+ beginning at offset +start+;
+ * returns the deleted objects in a new Array:
+ * a = [:foo, 'bar', 2]
+ * a.slice!(0, 2) # => [:foo, "bar"]
+ * a # => [2]
+ *
+ * If <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]
+ *
+ * If <tt>start == a.size</tt> and +length+ is non-negative,
+ * returns a new empty \Array.
+ *
+ * If +length+ is negative, returns +nil+.
+ *
+ * When the only argument is a \Range object +range+,
+ * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
+ * a = [:foo, 'bar', 2]
+ * a.slice!(1..2) # => ["bar", 2]
+ * a # => [:foo]
+ *
+ * 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+.
+ *
+ * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
+ * a = [:foo, 'bar', 2]
+ * a.slice!(0..-2) # => [:foo, "bar"]
+ * a # => [2]
+ *
+ * If <tt>range.start</tt> is negative,
+ * calculates the start index backwards from the end of the array:
+ * a = [:foo, 'bar', 2]
+ * a.slice!(-2..2) # => ["bar", 2]
+ * a # => [:foo]
*/
static VALUE
rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
{
- VALUE arg1, arg2;
- long pos, len, orig_len;
+ VALUE arg1;
+ long pos, len;
rb_ary_modify_check(ary);
+ rb_check_arity(argc, 1, 2);
+ arg1 = argv[0];
+
if (argc == 2) {
pos = NUM2LONG(argv[0]);
len = NUM2LONG(argv[1]);
- delete_pos_len:
- if (len < 0) return Qnil;
- orig_len = RARRAY_LEN(ary);
- if (pos < 0) {
- pos += orig_len;
- if (pos < 0) return Qnil;
- }
- else if (orig_len < pos) return Qnil;
- if (orig_len < pos + len) {
- len = orig_len - pos;
- }
- if (len == 0) return rb_ary_new2(0);
- arg2 = rb_ary_new4(len, RARRAY_CONST_PTR_TRANSIENT(ary)+pos);
- RBASIC_SET_CLASS(arg2, rb_obj_class(ary));
- rb_ary_splice(ary, pos, len, 0, 0);
- return arg2;
+ return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
}
- rb_check_arity(argc, 1, 2);
- arg1 = argv[0];
-
if (!FIXNUM_P(arg1)) {
switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
case Qtrue:
/* valid range */
- goto delete_pos_len;
+ return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
case Qnil:
/* invalid range */
return Qnil;
@@ -3572,17 +4224,20 @@ ary_reject_bang(VALUE ary)
/*
* call-seq:
- * ary.reject! {|item| block} -> ary or nil
- * ary.reject! -> Enumerator
+ * array.reject! {|element| ... } -> self or nil
+ * array.reject! -> new_enumerator
*
- * Deletes every element of +self+ for which the block evaluates to +true+,
- * if no changes were made returns +nil+.
+ * Removes each element for which the block returns a truthy value.
*
- * The array may not be changed instantly every time the block is called.
+ * Returns +self+ if any elements removed:
+ * a = [:foo, 'bar', 2, 'bat']
+ * a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]
*
- * See also Enumerable#reject and Array#delete_if.
+ * Returns +nil+ if no elements removed.
*
- * If no block is given, an Enumerator is returned instead.
+ * Returns a new \Enumerator if no block given:
+ * a = [:foo, 'bar', 2]
+ * a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
*/
static VALUE
@@ -3595,15 +4250,18 @@ rb_ary_reject_bang(VALUE ary)
/*
* call-seq:
- * ary.reject {|item| block } -> new_ary
- * ary.reject -> Enumerator
- *
- * Returns a new array containing the items in +self+ for which the given
- * block is not +true+. The ordering of non-rejected elements is maintained.
- *
- * See also Array#delete_if
- *
- * If no block is given, an Enumerator is returned instead.
+ * array.reject {|element| ... } -> new_array
+ * array.reject -> new_enumerator
+ *
+ * Returns a new \Array whose elements are all those from +self+
+ * for which the block returns +false+ or +nil+:
+ * a = [:foo, 'bar', 2, 'bat']
+ * a1 = a.reject {|element| element.to_s.start_with?('b') }
+ * a1 # => [:foo, 2]
+ *
+ * Returns a new \Enumerator if no block given:
+ * a = [:foo, 'bar', 2]
+ * a.reject # => #<Enumerator: [:foo, "bar", 2]:reject>
*/
static VALUE
@@ -3619,20 +4277,17 @@ rb_ary_reject(VALUE ary)
/*
* call-seq:
- * ary.delete_if {|item| block} -> ary
- * ary.delete_if -> Enumerator
- *
- * Deletes every element of +self+ for which block evaluates to +true+.
+ * array.delete_if {|element| ... } -> self
+ * array.delete_if -> Enumerator
*
- * The array is changed instantly every time the block is called, not after
- * the iteration is over.
+ * Removes each element in +self+ for which the block returns a truthy value;
+ * returns +self+:
+ * a = [:foo, 'bar', 2, 'bat']
+ * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
*
- * See also Array#reject!
- *
- * If no block is given, an Enumerator is returned instead.
- *
- * scores = [ 97, 42, 75 ]
- * scores.delete_if {|score| score < 80 } #=> [97]
+ * Returns a new \Enumerator if no block given:
+ * a = [:foo, 'bar', 2]
+ * a.delete_if # => #<Enumerator: [:foo, "bar", 2]:delete_if>
*/
static VALUE
@@ -3673,26 +4328,51 @@ take_items(VALUE obj, long n)
/*
* call-seq:
- * ary.zip(arg, ...) -> new_ary
- * ary.zip(arg, ...) {|arr| block} -> nil
- *
- * Converts any arguments to arrays, then merges elements of +self+ with
- * corresponding elements from each argument.
- *
- * This generates a sequence of <code>ary.size</code> _n_-element arrays,
- * where _n_ is one more than the count of arguments.
- *
- * If the size of any argument is less than the size of the initial array,
- * +nil+ values are supplied.
- *
- * If a block is given, it is invoked for each output +array+, otherwise an
- * array of arrays is returned.
- *
- * a = [ 4, 5, 6 ]
- * b = [ 7, 8, 9 ]
- * [1, 2, 3].zip(a, b) #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
- * [1, 2].zip(a, b) #=> [[1, 4, 7], [2, 5, 8]]
- * a.zip([1, 2], [8]) #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
+ * array.zip(*other_arrays) -> new_array
+ * array.zip(*other_arrays) {|other_array| ... } -> nil
+ *
+ * When no block given, returns a new \Array +new_array+ of size <tt>self.size</tt>
+ * whose elements are Arrays.
+ *
+ * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
+ * and contains:
+ * - The _nth_ element of +self+.
+ * - The _nth_ element of each of the +other_arrays+.
+ *
+ * If all +other_arrays+ and +self+ are the same size:
+ * a = [:a0, :a1, :a2, :a3]
+ * b = [:b0, :b1, :b2, :b3]
+ * c = [:c0, :c1, :c2, :c3]
+ * d = a.zip(b, c)
+ * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
+ *
+ * If any array in +other_arrays+ is smaller than +self+,
+ * fills to <tt>self.size</tt> with +nil+:
+ * a = [:a0, :a1, :a2, :a3]
+ * b = [:b0, :b1, :b2]
+ * c = [:c0, :c1]
+ * d = a.zip(b, c)
+ * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
+ *
+ * If any array in +other_arrays+ is larger than +self+,
+ * its trailing elements are ignored:
+ * a = [:a0, :a1, :a2, :a3]
+ * b = [:b0, :b1, :b2, :b3, :b4]
+ * c = [:c0, :c1, :c2, :c3, :c4, :c5]
+ * d = a.zip(b, c)
+ * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
+ *
+ * When a block is given, calls the block with each of the sub-arrays (formed as above); returns nil
+ * a = [:a0, :a1, :a2, :a3]
+ * b = [:b0, :b1, :b2, :b3]
+ * c = [:c0, :c1, :c2, :c3]
+ * a.zip(b, c) {|sub_array| p sub_array} # => nil
+ *
+ * Output:
+ * [:a0, :b0, :c0]
+ * [:a1, :b1, :c1]
+ * [:a2, :b2, :c2]
+ * [:a3, :b3, :c3]
*/
static VALUE
@@ -3755,15 +4435,12 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.transpose -> new_ary
- *
- * Assumes that +self+ is an array of arrays and transposes the rows and
- * columns.
+ * array.transpose -> new_array
*
- * a = [[1,2], [3,4], [5,6]]
- * a.transpose #=> [[1, 3, 5], [2, 4, 6]]
- *
- * If the length of the subarrays don't match, an IndexError is raised.
+ * Transposes the rows and columns in an \Array of Arrays;
+ * the nested Arrays must all be the same size:
+ * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
+ * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
*/
static VALUE
@@ -3796,15 +4473,11 @@ rb_ary_transpose(VALUE ary)
/*
* call-seq:
- * ary.replace(other_ary) -> ary
- * ary.initialize_copy(other_ary) -> ary
- *
- * Replaces the contents of +self+ with the contents of +other_ary+,
- * truncating or expanding if necessary.
+ * array.replace(other_array) -> self
*
- * a = [ "a", "b", "c", "d", "e" ]
- * a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"]
- * a #=> ["x", "y", "z"]
+ * Replaces the content of +self+ with the content of +other_array+; returns +self+:
+ * a = [:foo, 'bar', 2]
+ * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3]
*/
VALUE
@@ -3850,12 +4523,11 @@ rb_ary_replace(VALUE copy, VALUE orig)
/*
* call-seq:
- * ary.clear -> ary
- *
- * Removes all elements from +self+.
+ * array.clear -> self
*
- * a = [ "a", "b", "c", "d", "e" ]
- * a.clear #=> [ ]
+ * Removes all elements from +self+:
+ * a = [:foo, 'bar', 2]
+ * a.clear # => []
*/
VALUE
@@ -3881,32 +4553,171 @@ rb_ary_clear(VALUE ary)
/*
* call-seq:
- * ary.fill(obj) -> ary
- * ary.fill(obj, start [, length]) -> ary
- * ary.fill(obj, range) -> ary
- * ary.fill {|index| block} -> ary
- * ary.fill(start [, length]) {|index| block} -> ary
- * ary.fill(range) {|index| block} -> ary
- *
- * The first three forms set the selected elements of +self+ (which
- * may be the entire array) to +obj+.
- *
- * A +start+ of +nil+ is equivalent to zero.
- *
- * A +length+ of +nil+ is equivalent to the length of the array.
- *
- * The last three forms fill the array with the value of the given block,
- * which is passed the absolute index of each element to be filled.
- *
- * Negative values of +start+ count from the end of the array, where +-1+ is
- * the last element.
- *
- * a = [ "a", "b", "c", "d" ]
- * a.fill("x") #=> ["x", "x", "x", "x"]
- * a.fill("z", 2, 2) #=> ["x", "x", "z", "z"]
- * a.fill("y", 0..1) #=> ["y", "y", "z", "z"]
- * a.fill {|i| i*i} #=> [0, 1, 4, 9]
- * a.fill(-2) {|i| i*i*i} #=> [0, 1, 8, 27]
+ * array.fill(obj) -> self
+ * array.fill(obj, start) -> self
+ * array.fill(obj, start, length) -> self
+ * array.fill(obj, range) -> self
+ * array.fill {|index| ... } -> self
+ * array.fill(start) {|index| ... } -> self
+ * array.fill(start, length) {|index| ... } -> self
+ * array.fill(range) {|index| ... } -> self
+ *
+ * Replaces specified elements in +self+ with specified objects; returns +self+.
+ *
+ * With argument +obj+ and no block given, replaces all elements with that one object:
+ * a = ['a', 'b', 'c', 'd']
+ * a # => ["a", "b", "c", "d"]
+ * a.fill(:X) # => [:X, :X, :X, :X]
+ *
+ * With arguments +obj+ and \Integer +start+, and no block given,
+ * replaces elements based on the given start.
+ *
+ * If +start+ is in range (<tt>0 <= start < array.size</tt>),
+ * replaces all elements from offset +start+ through the end:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, 2) # => ["a", "b", :X, :X]
+ *
+ * If +start+ is too large (<tt>start >= array.size</tt>), does nothing:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, 4) # => ["a", "b", "c", "d"]
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, 5) # => ["a", "b", "c", "d"]
+ *
+ * If +start+ is negative, counts from the end (starting index is <tt>start + array.size</tt>):
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, -2) # => ["a", "b", :X, :X]
+ *
+ * If +start+ is too small (less than and far from zero), replaces all elements:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, -6) # => [:X, :X, :X, :X]
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, -50) # => [:X, :X, :X, :X]
+ *
+ * With arguments +obj+, \Integer +start+, and \Integer +length+, and no block given,
+ * replaces elements based on the given +start+ and +length+.
+ *
+ * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"]
+ *
+ * If +start+ is negative, counts from the end:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"]
+ *
+ * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil]
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X]
+ *
+ * If +length+ is zero or negative, replaces no elements:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"]
+ * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"]
+ *
+ * With arguments +obj+ and \Range +range+, and no block given,
+ * replaces elements based on the given range.
+ *
+ * If the range is positive and ascending (<tt>0 < range.begin <= range.end</tt>),
+ * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"]
+ *
+ * If <tt>range.first</tt> is negative, replaces no elements:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"]
+ *
+ * If <tt>range.last</tt> is negative, counts from the end:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"]
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, (1..-2)) # => ["a", :X, :X, "d"]
+ *
+ * If <tt>range.last</tt> and <tt>range.last</tt> are both negative,
+ * both count from the end of the array:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, (-1..-1)) # => ["a", "b", "c", :X]
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(:X, (-2..-2)) # => ["a", "b", :X, "d"]
+ *
+ * With no arguments and a block given, calls the block with each index;
+ * replaces the corresponding element with the block's return value:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
+ *
+ * With argument +start+ and a block given, calls the block with each index
+ * from offset +start+ to the end; replaces the corresponding element
+ * with the block's return value:
+ *
+ * If start is in range (<tt>0 <= start < array.size</tt>),
+ * replaces from offset +start+ to the end:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"]
+ *
+ * If +start+ is too large(<tt>start >= array.size</tt>), does nothing:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
+ *
+ * If +start+ is negative, counts from the end:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"]
+ *
+ * If start is too small (<tt>start <= -array.size</tt>, replaces all elements:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(-50) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
+ *
+ * With arguments +start+ and +length+, and a block given,
+ * calls the block for each index specified by start length;
+ * replaces the corresponding element with the block's return value.
+ *
+ * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
+ *
+ * If start is negative, counts from the end:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
+ *
+ * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(5, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil]
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(5, 2) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil, "new_5", "new_6"]
+ *
+ * If +length+ is zero or less, replaces no elements:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
+ * a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
+ *
+ * With arguments +obj+ and +range+, and a block given,
+ * calls the block with each index in the given range;
+ * replaces the corresponding element with the block's return value.
+ *
+ * If the range is positive and ascending (<tt>range 0 < range.begin <= range.end</tt>,
+ * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
+ *
+ * If +range.first+ is negative, does nothing:
+ * a = ['a', 'b', 'c', 'd']
+ * a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
+ *
+ * If <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"]
*/
static VALUE
@@ -3975,25 +4786,14 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary + other_ary -> new_ary
- *
- * Concatenation --- Returns a new array built by concatenating the
- * two arrays together to produce a third array.
- *
- * [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]
- * a = [ "a", "b", "c" ]
- * c = a + [ "d", "e", "f" ]
- * c #=> [ "a", "b", "c", "d", "e", "f" ]
- * a #=> [ "a", "b", "c" ]
+ * array + other_array -> new_array
*
- * Note that
- * x += y
- * is the same as
- * x = x + y
- * This means that it produces a new array. As a consequence,
- * repeated use of <code>+=</code> on arrays can be quite inefficient.
+ * Returns a new \Array containing all elements of +array+
+ * followed by all elements of +other_array+:
+ * a = [0, 1] + [2, 3]
+ * a # => [0, 1, 2, 3]
*
- * See also Array#concat.
+ * Related: #concat.
*/
VALUE
@@ -4021,27 +4821,17 @@ ary_append(VALUE x, VALUE y)
if (n > 0) {
rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR_TRANSIENT(y), n);
}
+ RB_GC_GUARD(y);
return x;
}
/*
* call-seq:
- * ary.concat(other_ary1, other_ary2, ...) -> ary
- *
- * Appends the elements of <code>other_ary</code>s to +self+.
- *
- * [ "a", "b" ].concat( ["c", "d"]) #=> [ "a", "b", "c", "d" ]
- * [ "a" ].concat( ["b"], ["c", "d"]) #=> [ "a", "b", "c", "d" ]
- * [ "a" ].concat #=> [ "a" ]
- *
- * a = [ 1, 2, 3 ]
- * a.concat( [ 4, 5 ])
- * a #=> [ 1, 2, 3, 4, 5 ]
+ * array.concat(*other_arrays) -> self
*
- * a = [ 1, 2 ]
- * a.concat(a, a) #=> [1, 2, 1, 2, 1, 2]
- *
- * See also Array#+.
+ * Adds to +array+ all elements from each \Array in +other_arrays+; returns +self+:
+ * a = [0, 1]
+ * a.concat([2, 3], [4, 5]) # => [0, 1, 2, 3, 4, 5]
*/
static VALUE
@@ -4073,19 +4863,17 @@ rb_ary_concat(VALUE x, VALUE y)
/*
* call-seq:
- * ary * int -> new_ary
- * ary * str -> new_string
- *
- * Repetition --- With a String argument, equivalent to
- * <code>ary.join(str)</code>.
- *
- * Otherwise, returns a new array built by concatenating the +int+ copies of
- * +self+.
+ * array * n -> new_array
+ * array * string_separator -> new_string
*
+ * When non-negative argument \Integer +n+ is given,
+ * returns a new \Array built by concatenating the +n+ copies of +self+:
+ * a = ['x', 'y']
+ * a * 3 # => ["x", "y", "x", "y", "x", "y"]
*
- * [ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
- * [ 1, 2, 3 ] * "," #=> "1,2,3"
- *
+ * When \String argument +string_separator+ is given,
+ * equivalent to <tt>array.join(string_separator)</tt>:
+ * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
*/
static VALUE
@@ -4102,7 +4890,7 @@ rb_ary_times(VALUE ary, VALUE times)
len = NUM2LONG(times);
if (len == 0) {
- ary2 = ary_new(rb_obj_class(ary), 0);
+ ary2 = ary_new(rb_cArray, 0);
goto out;
}
if (len < 0) {
@@ -4113,7 +4901,7 @@ rb_ary_times(VALUE ary, VALUE times)
}
len *= RARRAY_LEN(ary);
- ary2 = ary_new(rb_obj_class(ary), len);
+ ary2 = ary_new(rb_cArray, len);
ARY_SET_LEN(ary2, len);
ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
@@ -4134,22 +4922,16 @@ rb_ary_times(VALUE ary, VALUE times)
/*
* call-seq:
- * ary.assoc(obj) -> element_ary or nil
- *
- * Searches through an array whose elements are also arrays comparing +obj+
- * with the first element of each contained array using <code>obj.==</code>.
+ * array.assoc(obj) -> found_array or nil
*
- * Returns the first contained array that matches (that is, the first
- * associated array), or +nil+ if no match is found.
+ * Returns the first element in +self+ that is an \Array
+ * whose first element <tt>==</tt> +obj+:
+ * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
+ * a.assoc(4) # => [4, 5, 6]
*
- * See also Array#rassoc
+ * Returns +nil+ if no such element is found.
*
- * s1 = [ "colors", "red", "blue", "green" ]
- * s2 = [ "letters", "a", "b", "c" ]
- * s3 = "foo"
- * a = [ s1, s2, s3 ]
- * a.assoc("letters") #=> [ "letters", "a", "b", "c" ]
- * a.assoc("foo") #=> nil
+ * Related: #rassoc.
*/
VALUE
@@ -4169,20 +4951,16 @@ rb_ary_assoc(VALUE ary, VALUE key)
/*
* call-seq:
- * ary.rassoc(obj) -> element_ary or nil
+ * array.rassoc(obj) -> found_array or nil
*
- * Searches through the array whose elements are also arrays.
+ * Returns the first element in +self+ that is an \Array
+ * whose second element <tt>==</tt> +obj+:
+ * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
+ * a.rassoc(4) # => [2, 4]
*
- * Compares +obj+ with the second element of each contained array using
- * <code>obj.==</code>.
+ * Returns +nil+ if no such element is found.
*
- * Returns the first contained array that matches +obj+.
- *
- * See also Array#assoc.
- *
- * a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
- * a.rassoc("two") #=> [2, "two"]
- * a.rassoc("four") #=> nil
+ * Related: #assoc.
*/
VALUE
@@ -4237,16 +5015,19 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur)
/*
* call-seq:
- * ary == other_ary -> bool
+ * array == other_array -> true or false
*
- * Equality --- Two arrays are equal if they contain the same number of
- * elements and if each element is equal to (according to Object#==) the
- * corresponding element in +other_ary+.
+ * Returns +true+ if both <tt>array.size == other_array.size</tt>
+ * and for each index +i+ in +array+, <tt>array[i] == other_array[i]</tt>:
+ * a0 = [:foo, 'bar', 2]
+ * a1 = [:foo, 'bar', 2.0]
+ * a1 == a0 # => true
+ * [] == [] # => true
*
- * [ "a", "c" ] == [ "a", "c", 7 ] #=> false
- * [ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true
- * [ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false
+ * Otherwise, returns +false+.
*
+ * This method is different from method Array#eql?,
+ * which compares elements using <tt>Object#eql?</tt>.
*/
static VALUE
@@ -4279,10 +5060,18 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
/*
* call-seq:
- * ary.eql?(other) -> true or false
+ * array.eql? other_array -> true or false
+ *
+ * Returns +true+ if +self+ and +other_array+ are the same size,
+ * and if, for each index +i+ in +self+, <tt>self[i].eql? other_array[i]</tt>:
+ * a0 = [:foo, 'bar', 2]
+ * a1 = [:foo, 'bar', 2]
+ * a1.eql?(a0) # => true
*
- * Returns +true+ if +self+ and +other+ are the same object,
- * or are both arrays with the same content (according to Object#eql?).
+ * Otherwise, returns +false+.
+ *
+ * This method is different from method {Array#==}[#method-i-3D-3D],
+ * which compares using method <tt>Object#==</tt>.
*/
static VALUE
@@ -4297,14 +5086,13 @@ rb_ary_eql(VALUE ary1, VALUE ary2)
/*
* call-seq:
- * ary.hash -> integer
- *
- * Compute a hash-code for this array.
+ * array.hash -> integer
*
- * Two arrays with the same content will have the same hash code (and will
- * compare using #eql?).
+ * Returns the integer hash value for +self+.
*
- * See also Object#hash.
+ * Two arrays with the same content will have the same hash code (and will compare using eql?):
+ * [0, 1, 2].hash == [0, 1, 2].hash # => true
+ * [0, 1, 2].hash == [0, 1, 3].hash # => false
*/
static VALUE
@@ -4326,14 +5114,12 @@ rb_ary_hash(VALUE ary)
/*
* call-seq:
- * ary.include?(object) -> true or false
- *
- * Returns +true+ if the given +object+ is present in +self+ (that is, if any
- * element <code>==</code> +object+), otherwise returns +false+.
+ * array.include?(obj) -> true or false
*
- * a = [ "a", "b", "c" ]
- * a.include?("b") #=> true
- * a.include?("z") #=> false
+ * Returns +true+ if for some index +i+ in +self+, <tt>obj == self[i]</tt>;
+ * otherwise +false+:
+ * [0, 1, 2].include?(2) # => true
+ * [0, 1, 2].include?(3) # => false
*/
VALUE
@@ -4388,32 +5174,24 @@ recursive_cmp(VALUE ary1, VALUE ary2, int recur)
/*
* call-seq:
- * ary <=> other_ary -> -1, 0, +1 or nil
+ * array <=> other_array -> -1, 0, or 1
*
- * Comparison --- Returns an integer (+-1+, +0+, or <code>+1</code>) if this
- * array is less than, equal to, or greater than +other_ary+.
+ * 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>.
*
- * Each object in each array is compared (using the <=> operator).
+ * Returns -1 if any result is -1:
+ * [0, 1, 2] <=> [0, 1, 3] # => -1
*
- * Arrays are compared in an "element-wise" manner; the first element of +ary+
- * is compared with the first one of +other_ary+ using the <=> operator, then
- * each of the second elements, etc...
- * As soon as the result of any such comparison is non zero (i.e. the two
- * corresponding elements are not equal), that result is returned for the
- * whole array comparison.
- *
- * If all the elements are equal, then the result is based on a comparison of
- * the array lengths. Thus, two arrays are "equal" according to Array#<=> if,
- * and only if, they have the same length and the value of each element is
- * equal to the value of the corresponding element in the other array.
- *
- * +nil+ is returned if the +other_ary+ is not an array or if the comparison
- * of two elements returned +nil+.
- *
- * [ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1
- * [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1
- * [ 1, 2 ] <=> [ 1, :two ] #=> nil
+ * Returns 1 if any result is 1:
+ * [0, 1, 2] <=> [0, 1, 1] # => 1
*
+ * When all results are zero:
+ * - Returns -1 if +array+ is smaller than +other_array+:
+ * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
+ * - Returns 1 if +array+ is larger than +other_array+:
+ * [0, 1, 2] <=> [0, 1] # => 1
+ * - Returns 0 if +array+ and +other_array+ are the same size:
+ * [0, 1, 2] <=> [0, 1, 2] # => 0
*/
VALUE
@@ -4494,25 +5272,17 @@ ary_recycle_hash(VALUE hash)
/*
* call-seq:
- * ary - other_ary -> new_ary
- *
- * Array Difference
- *
- * Returns a new array that is a copy of the original array, removing all
- * occurrences of any item that also appear in +other_ary+. The order is
- * preserved from the original array.
+ * array - other_array -> new_array
*
- * It compares elements using their #hash and #eql? methods for efficiency.
+ * 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, 2, 3] - [3, 0] # => [1, 2]
+ * [0, 1, 2] - [4] # => [0, 1, 2]
*
- * [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
- *
- * Note that while 1 and 2 were only present once in the array argument, and
- * were present twice in the receiver array, all occurrences of each Integer are
- * removed in the returned array.
- *
- * If you need set-like behavior, see the library class Set.
- *
- * See also Array#difference.
+ * Related: Array#difference.
*/
static VALUE
@@ -4545,31 +5315,18 @@ rb_ary_diff(VALUE ary1, VALUE ary2)
/*
* call-seq:
- * ary.difference(other_ary1, other_ary2, ...) -> new_ary
- *
- * Array Difference
- *
- * Returns a new array that is a copy of the original array, removing all
- * occurrences of any item that also appear in +other_ary+. The order is
- * preserved from the original array.
- *
- * It compares elements using their #hash and #eql? methods for efficiency.
+ * array.difference(*other_arrays) -> new_array
*
- * [ 1, 1, 2, 2, 3, 3, 4, 5 ].difference([ 1, 2, 4 ]) #=> [ 3, 3, 5 ]
+ * Returns a new \Array containing only those elements from +self+
+ * that are not found in any of the Arrays +other_arrays+;
+ * items are compared using <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]
*
- * Note that while 1 and 2 were only present once in the array argument, and
- * were present twice in the receiver array, all occurrences of each Integer are
- * removed in the returned array.
+ * Returns a copy of +self+ if no arguments given.
*
- * Multiple array arguments can be supplied and all occurrences of any element
- * in those supplied arrays that match the receiver will be removed from the
- * returned array.
- *
- * [ 1, 'c', :s, 'yep' ].difference([ 1 ], [ 'a', 'c' ]) #=> [ :s, "yep" ]
- *
- * If you need set-like behavior, see the library class Set.
- *
- * See also Array#-.
+ * Related: Array#-.
*/
static VALUE
@@ -4611,17 +5368,17 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary & other_ary -> new_ary
+ * array & other_array -> new_array
*
- * Set Intersection --- Returns a new array containing unique elements common to the
- * two arrays. The order is preserved from the original array.
+ * Returns a new \Array containing each element found in both +array+ and \Array +other_array+;
+ * duplicates are omitted; items are compared using <tt>eql?</tt>:
+ * [0, 1, 2, 3] & [1, 2] # => [1, 2]
+ * [0, 1, 0, 1] & [0, 1] # => [0, 1]
*
- * It compares elements using their #hash and #eql? methods for efficiency.
+ * Preserves order from +array+:
+ * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
*
- * [ 1, 1, 3, 5 ] & [ 3, 2, 1 ] #=> [ 1, 3 ]
- * [ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ] #=> [ 'a', 'b' ]
- *
- * See also Array#uniq.
+ * Related: Array#intersection.
*/
@@ -4662,19 +5419,20 @@ rb_ary_and(VALUE ary1, VALUE ary2)
/*
* call-seq:
- * ary.intersection(other_ary1, other_ary2, ...) -> new_ary
+ * array.intersection(*other_arrays) -> new_array
*
- * Set Intersection --- Returns a new array containing unique elements common
- * to +self+ and <code>other_ary</code>s. Order is preserved from the original
- * array.
+ * Returns a new \Array containing each element found both in +self+
+ * and in all of the given Arrays +other_arrays+;
+ * duplicates are omitted; items are compared using <tt>eql?</tt>:
+ * [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
+ * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
*
- * It compares elements using their #hash and #eql? methods for efficiency.
+ * Preserves order from +self+:
+ * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
*
- * [ 1, 1, 3, 5 ].intersection([ 3, 2, 1 ]) # => [ 1, 3 ]
- * [ "a", "b", "z" ].intersection([ "a", "b", "c" ], [ "b" ]) # => [ "b" ]
- * [ "a" ].intersection #=> [ "a" ]
+ * Returns a copy of +self+ if no arguments given.
*
- * See also Array#&.
+ * Related: Array#&.
*/
static VALUE
@@ -4723,17 +5481,16 @@ rb_ary_union_hash(VALUE hash, VALUE ary2)
/*
* call-seq:
- * ary | other_ary -> new_ary
- *
- * Set Union --- Returns a new array by joining +ary+ with +other_ary+,
- * excluding any duplicates and preserving the order from the given arrays.
+ * array | other_array -> new_array
*
- * It compares elements using their #hash and #eql? methods for efficiency.
+ * Returns the union of +array+ and \Array +other_array+;
+ * duplicates are removed; order is preserved;
+ * items are compared using <tt>eql?</tt>:
+ * [0, 1] | [2, 3] # => [0, 1, 2, 3]
+ * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
+ * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
*
- * [ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ]
- * [ "c", "d", "a" ] | [ "a", "b", "c" ] #=> [ "c", "d", "a", "b" ]
- *
- * See also Array#union.
+ * Related: Array#union.
*/
static VALUE
@@ -4759,18 +5516,17 @@ rb_ary_or(VALUE ary1, VALUE ary2)
/*
* call-seq:
- * ary.union(other_ary1, other_ary2, ...) -> new_ary
- *
- * Set Union --- Returns a new array by joining <code>other_ary</code>s with +self+,
- * excluding any duplicates and preserving the order from the given arrays.
+ * array.union(*other_arrays) -> new_array
*
- * It compares elements using their #hash and #eql? methods for efficiency.
+ * Returns a new \Array that is the union of +self+ and all given Arrays +other_arrays+;
+ * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
+ * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
+ * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
+ * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
*
- * [ "a", "b", "c" ].union( [ "c", "d", "a" ] ) #=> [ "a", "b", "c", "d" ]
- * [ "a" ].union( ["e", "b"], ["a", "c", "b"] ) #=> [ "a", "e", "b", "c" ]
- * [ "a" ].union #=> [ "a" ]
+ * Returns a copy of +self+ if no arguments given.
*
- * See also Array#|.
+ * Related: Array#|.
*/
static VALUE
@@ -4803,27 +5559,127 @@ rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
return ary_union;
}
+static VALUE
+ary_max_generic(VALUE ary, long i, VALUE vmax)
+{
+ RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
+
+ VALUE v;
+ for (; i < RARRAY_LEN(ary); ++i) {
+ v = RARRAY_AREF(ary, i);
+
+ if (rb_cmpint(rb_funcallv(vmax, id_cmp, 1, &v), vmax, v) < 0) {
+ vmax = v;
+ }
+ }
+
+ return vmax;
+}
+
+static VALUE
+ary_max_opt_fixnum(VALUE ary, long i, VALUE vmax)
+{
+ const long n = RARRAY_LEN(ary);
+ RUBY_ASSERT(i > 0 && i < n);
+ RUBY_ASSERT(FIXNUM_P(vmax));
+
+ VALUE v;
+ for (; i < n; ++i) {
+ v = RARRAY_AREF(ary, i);
+
+ if (FIXNUM_P(v)) {
+ if ((long)vmax < (long)v) {
+ vmax = v;
+ }
+ }
+ else {
+ return ary_max_generic(ary, i, vmax);
+ }
+ }
+
+ return vmax;
+}
+
+static VALUE
+ary_max_opt_float(VALUE ary, long i, VALUE vmax)
+{
+ const long n = RARRAY_LEN(ary);
+ RUBY_ASSERT(i > 0 && i < n);
+ RUBY_ASSERT(RB_FLOAT_TYPE_P(vmax));
+
+ VALUE v;
+ for (; i < n; ++i) {
+ v = RARRAY_AREF(ary, i);
+
+ if (RB_FLOAT_TYPE_P(v)) {
+ if (rb_float_cmp(vmax, v) < 0) {
+ vmax = v;
+ }
+ }
+ else {
+ return ary_max_generic(ary, i, vmax);
+ }
+ }
+
+ return vmax;
+}
+
+static VALUE
+ary_max_opt_string(VALUE ary, long i, VALUE vmax)
+{
+ const long n = RARRAY_LEN(ary);
+ RUBY_ASSERT(i > 0 && i < n);
+ RUBY_ASSERT(STRING_P(vmax));
+
+ VALUE v;
+ for (; i < n; ++i) {
+ v = RARRAY_AREF(ary, i);
+
+ if (STRING_P(v)) {
+ if (rb_str_cmp(vmax, v) < 0) {
+ vmax = v;
+ }
+ }
+ else {
+ return ary_max_generic(ary, i, vmax);
+ }
+ }
+
+ return vmax;
+}
+
/*
* call-seq:
- * ary.max -> obj
- * ary.max {|a, b| block} -> obj
- * ary.max(n) -> array
- * ary.max(n) {|a, b| block} -> array
+ * array.max -> element
+ * array.max {|a, b| ... } -> element
+ * array.max(n) -> new_array
+ * array.max(n) {|a, b| ... } -> new_array
+ *
+ * Returns one of the following:
+ * - The maximum-valued element from +self+.
+ * - A new \Array of maximum-valued elements selected from +self+.
+ *
+ * When no block is given, each element in +self+ must respond to method <tt><=></tt>
+ * with an \Integer.
+ *
+ * With no argument and no block, returns the element in +self+
+ * having the maximum value per method <tt><=></tt>:
+ * [0, 1, 2].max # => 2
*
- * Returns the object in _ary_ with the maximum value. The
- * first form assumes all objects implement Comparable;
- * the second uses the block to return <em>a <=> b</em>.
+ * With an argument \Integer +n+ and no block, returns a new \Array with at most +n+ 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]
*
- * ary = %w(albatross dog horse)
- * ary.max #=> "horse"
- * ary.max {|a, b| a.length <=> b.length} #=> "albatross"
+ * When a block is given, the block must return an \Integer.
*
- * If the +n+ argument is given, maximum +n+ elements are returned
- * as an array.
+ * 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"
*
- * ary = %w[albatross dog horse]
- * ary.max(2) #=> ["horse", "dog"]
- * ary.max(2) {|a, b| a.length <=> b.length } #=> ["albatross", "horse"]
+ * With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
+ * in descending order per the block:
+ * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
*/
static VALUE
rb_ary_max(int argc, VALUE *argv, VALUE ary)
@@ -4836,6 +5692,7 @@ rb_ary_max(int argc, VALUE *argv, VALUE ary)
if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
return rb_nmin_run(ary, num, 0, 1, 1);
+ const long n = RARRAY_LEN(ary);
if (rb_block_given_p()) {
for (i = 0; i < RARRAY_LEN(ary); i++) {
v = RARRAY_AREF(ary, i);
@@ -4844,39 +5701,149 @@ rb_ary_max(int argc, VALUE *argv, VALUE ary)
}
}
}
- else {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- v = RARRAY_AREF(ary, i);
- if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) > 0) {
- result = v;
- }
- }
+ else if (n > 0) {
+ result = RARRAY_AREF(ary, 0);
+ if (n > 1) {
+ if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
+ return ary_max_opt_fixnum(ary, 1, result);
+ }
+ else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
+ return ary_max_opt_string(ary, 1, result);
+ }
+ else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
+ return ary_max_opt_float(ary, 1, result);
+ }
+ else {
+ return ary_max_generic(ary, 1, result);
+ }
+ }
}
if (result == Qundef) return Qnil;
return result;
}
+static VALUE
+ary_min_generic(VALUE ary, long i, VALUE vmin)
+{
+ RUBY_ASSERT(i > 0 && i < RARRAY_LEN(ary));
+
+ VALUE v;
+ for (; i < RARRAY_LEN(ary); ++i) {
+ v = RARRAY_AREF(ary, i);
+
+ if (rb_cmpint(rb_funcallv(vmin, id_cmp, 1, &v), vmin, v) > 0) {
+ vmin = v;
+ }
+ }
+
+ return vmin;
+}
+
+static VALUE
+ary_min_opt_fixnum(VALUE ary, long i, VALUE vmin)
+{
+ const long n = RARRAY_LEN(ary);
+ RUBY_ASSERT(i > 0 && i < n);
+ RUBY_ASSERT(FIXNUM_P(vmin));
+
+ VALUE a;
+ for (; i < n; ++i) {
+ a = RARRAY_AREF(ary, i);
+
+ if (FIXNUM_P(a)) {
+ if ((long)vmin > (long)a) {
+ vmin = a;
+ }
+ }
+ else {
+ return ary_min_generic(ary, i, vmin);
+ }
+ }
+
+ return vmin;
+}
+
+static VALUE
+ary_min_opt_float(VALUE ary, long i, VALUE vmin)
+{
+ const long n = RARRAY_LEN(ary);
+ RUBY_ASSERT(i > 0 && i < n);
+ RUBY_ASSERT(RB_FLOAT_TYPE_P(vmin));
+
+ VALUE a;
+ for (; i < n; ++i) {
+ a = RARRAY_AREF(ary, i);
+
+ if (RB_FLOAT_TYPE_P(a)) {
+ if (rb_float_cmp(vmin, a) > 0) {
+ vmin = a;
+ }
+ }
+ else {
+ return ary_min_generic(ary, i, vmin);
+ }
+ }
+
+ return vmin;
+}
+
+static VALUE
+ary_min_opt_string(VALUE ary, long i, VALUE vmin)
+{
+ const long n = RARRAY_LEN(ary);
+ RUBY_ASSERT(i > 0 && i < n);
+ RUBY_ASSERT(STRING_P(vmin));
+
+ VALUE a;
+ for (; i < n; ++i) {
+ a = RARRAY_AREF(ary, i);
+
+ if (STRING_P(a)) {
+ if (rb_str_cmp(vmin, a) > 0) {
+ vmin = a;
+ }
+ }
+ else {
+ return ary_min_generic(ary, i, vmin);
+ }
+ }
+
+ return vmin;
+}
+
/*
* call-seq:
- * ary.min -> obj
- * ary.min {| a,b | block } -> obj
- * ary.min(n) -> array
- * ary.min(n) {| a,b | block } -> array
+ * array.min -> element
+ * array.min { |a, b| ... } -> element
+ * array.min(n) -> new_array
+ * array.min(n) { |a, b| ... } -> new_array
+ *
+ * Returns one of the following:
+ * - The minimum-valued element from +self+.
+ * - A new \Array of minimum-valued elements selected from +self+.
+ *
+ * When no block is given, each element in +self+ must respond to method <tt><=></tt>
+ * with an \Integer.
*
- * Returns the object in _ary_ with the minimum value. The
- * first form assumes all objects implement Comparable;
- * the second uses the block to return <em>a <=> b</em>.
+ * With no argument and no block, returns the element in +self+
+ * having the minimum value per method <tt><=></tt>:
+ * [0, 1, 2].min # => 0
*
- * ary = %w(albatross dog horse)
- * ary.min #=> "albatross"
- * ary.min {|a, b| a.length <=> b.length} #=> "dog"
+ * With \Integer argument +n+ and no block, returns a new \Array with at most +n+ 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]
*
- * If the +n+ argument is given, minimum +n+ elements are returned
- * as an array.
+ * When a block is given, the block must return an Integer.
*
- * ary = %w[albatross dog horse]
- * ary.min(2) #=> ["albatross", "dog"]
- * ary.min(2) {|a, b| a.length <=> b.length } #=> ["dog", "horse"]
+ * 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"
+ *
+ * With an argument +n+ and a block, returns a new \Array with at most +n+ elements,
+ * in ascending order per the block:
+ * [0, 1, 2, 3].min(3) # => [0, 1, 2]
+ * [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
*/
static VALUE
rb_ary_min(int argc, VALUE *argv, VALUE ary)
@@ -4889,6 +5856,7 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
return rb_nmin_run(ary, num, 0, 0, 1);
+ const long n = RARRAY_LEN(ary);
if (rb_block_given_p()) {
for (i = 0; i < RARRAY_LEN(ary); i++) {
v = RARRAY_AREF(ary, i);
@@ -4897,13 +5865,22 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
}
}
}
- else {
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- v = RARRAY_AREF(ary, i);
- if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) < 0) {
- result = v;
- }
- }
+ else if (n > 0) {
+ result = RARRAY_AREF(ary, 0);
+ if (n > 1) {
+ if (FIXNUM_P(result) && CMP_OPTIMIZABLE(cmp_opt, Integer)) {
+ return ary_min_opt_fixnum(ary, 1, result);
+ }
+ else if (STRING_P(result) && CMP_OPTIMIZABLE(cmp_opt, String)) {
+ return ary_min_opt_string(ary, 1, result);
+ }
+ else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(cmp_opt, Float)) {
+ return ary_min_opt_float(ary, 1, result);
+ }
+ else {
+ return ary_min_generic(ary, 1, result);
+ }
+ }
}
if (result == Qundef) return Qnil;
return result;
@@ -4911,14 +5888,23 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.minmax -> [obj, obj]
- * ary.minmax {| a,b | block } -> [obj, obj]
- *
- * Returns a two element array which contains the minimum and the
- * maximum value in the array.
- *
- * Can be given an optional block to override the default comparison
- * method <code>a <=> b</code>.
+ * array.minmax -> [min_val, max_val]
+ * array.minmax {|a, b| ... } -> [min_val, max_val]
+ *
+ * Returns a new 2-element \Array containing the minimum and maximum values
+ * from +self+, either per method <tt><=></tt> or per a given block:.
+ *
+ * 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>:
+ * [0, 1, 2].minmax # => [0, 2]
+ *
+ * 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:
+ * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
*/
static VALUE
rb_ary_minmax(VALUE ary)
@@ -4938,31 +5924,31 @@ push_value(st_data_t key, st_data_t val, st_data_t ary)
/*
* call-seq:
- * ary.uniq! -> ary or nil
- * ary.uniq! {|item| ...} -> ary or nil
- *
- * Removes duplicate elements from +self+.
+ * array.uniq! -> self or nil
+ * array.uniq! {|element| ... } -> self or nil
*
- * If a block is given, it will use the return value of the block for
- * comparison.
+ * Removes duplicate elements from +self+, the first occurrence always being retained;
+ * returns +self+ if any elements removed, +nil+ otherwise.
*
- * It compares values using their #hash and #eql? methods for efficiency.
+ * With no block given, identifies and removes elements using method <tt>eql?</tt>
+ * to compare.
*
- * +self+ is traversed in order, and the first occurrence is kept.
+ * Returns +self+ if any elements removed:
+ * a = [0, 0, 1, 1, 2, 2]
+ * a.uniq! # => [0, 1, 2]
*
- * Returns +nil+ if no changes are made (that is, no duplicates are found).
+ * Returns +nil+ if no elements removed.
*
- * a = [ "a", "a", "b", "b", "c" ]
- * a.uniq! # => ["a", "b", "c"]
+ * 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.
*
- * b = [ "a", "b", "c" ]
- * b.uniq! # => nil
- *
- * c = [["student","sam"], ["student","george"], ["teacher","matz"]]
- * c.uniq! {|s| s.first} # => [["student", "sam"], ["teacher", "matz"]]
+ * Returns +self+ if any elements removed:
+ * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
+ * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
*
+ * Returns +nil+ if no elements removed.
*/
-
static VALUE
rb_ary_uniq_bang(VALUE ary)
{
@@ -4996,23 +5982,22 @@ rb_ary_uniq_bang(VALUE ary)
/*
* call-seq:
- * ary.uniq -> new_ary
- * ary.uniq {|item| ...} -> new_ary
- *
- * Returns a new array by removing duplicate values in +self+.
- *
- * If a block is given, it will use the return value of the block for comparison.
- *
- * It compares values using their #hash and #eql? methods for efficiency.
- *
- * +self+ is traversed in order, and the first occurrence is kept.
- *
- * a = [ "a", "a", "b", "b", "c" ]
- * a.uniq # => ["a", "b", "c"]
- *
- * b = [["student","sam"], ["student","george"], ["teacher","matz"]]
- * b.uniq {|s| s.first} # => [["student", "sam"], ["teacher", "matz"]]
- *
+ * array.uniq -> new_array
+ * array.uniq {|element| ... } -> new_array
+ *
+ * Returns a new \Array containing those elements from +self+ that are not duplicates,
+ * the first occurrence always being retained.
+ *
+ * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
+ * to compare.
+ * a = [0, 0, 1, 1, 2, 2]
+ * a.uniq # => [0, 1, 2]
+ *
+ * With a block given, calls the block for each element;
+ * identifies (using method <tt>eql?</tt>) and omits duplicate values,
+ * that is, those elements for which the block returns the same value:
+ * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
+ * a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
*/
static VALUE
@@ -5032,7 +6017,6 @@ rb_ary_uniq(VALUE ary)
hash = ary_make_hash(ary);
uniq = rb_hash_values(hash);
}
- RBASIC_SET_CLASS(uniq, rb_obj_class(ary));
if (hash) {
ary_recycle_hash(hash);
}
@@ -5042,14 +6026,11 @@ rb_ary_uniq(VALUE ary)
/*
* call-seq:
- * ary.compact! -> ary or nil
+ * array.compact! -> self or nil
*
- * Removes +nil+ elements from the array.
+ * Removes all +nil+ elements from +self+.
*
- * Returns +nil+ if no changes were made, otherwise returns the array.
- *
- * [ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
- * [ "a", "b", "c" ].compact! #=> nil
+ * Returns +self+ if any elements removed, otherwise +nil+.
*/
static VALUE
@@ -5077,12 +6058,11 @@ rb_ary_compact_bang(VALUE ary)
/*
* call-seq:
- * ary.compact -> new_ary
- *
- * Returns a copy of +self+ with all +nil+ elements removed.
+ * array.compact -> new_array
*
- * [ "a", nil, "b", nil, "c", nil ].compact
- * #=> [ "a", "b", "c" ]
+ * Returns a new \Array containing all non-+nil+ elements from +self+:
+ * a = [nil, 0, nil, 1, nil, 2, nil]
+ * a.compact # => [0, 1, 2]
*/
static VALUE
@@ -5095,23 +6075,26 @@ rb_ary_compact(VALUE ary)
/*
* call-seq:
- * ary.count -> int
- * ary.count(obj) -> int
- * ary.count {|item| block} -> int
+ * array.count -> an_integer
+ * array.count(obj) -> an_integer
+ * array.count {|element| ... } -> an_integer
*
- * Returns the number of elements.
+ * Returns a count of specified elements.
*
- * If an argument is given, counts the number of elements which equal +obj+
- * using <code>==</code>.
+ * With no argument and no block, returns the count of all elements:
+ * [0, 1, 2].count # => 3
+ * [].count # => 0
*
- * If a block is given, counts the number of elements for which the block
- * returns a true value.
+ * With argument +obj+, returns the count of elements <tt>eql?</tt> to +obj+:
+ * [0, 1, 2, 0].count(0) # => 2
+ * [0, 1, 2].count(3) # => 0
*
- * ary = [1, 2, 4, 2]
- * ary.count #=> 4
- * ary.count(2) #=> 2
- * ary.count {|x| x%2 == 0} #=> 3
+ * With no argument and a block given, calls the block with each element;
+ * returns the count of elements for which the block returns a truthy value:
+ * [0, 1, 2, 3].count {|element| element > 1} # => 2
*
+ * With argument +obj+ and a block given, issues a warning, ignores the block,
+ * and returns the count of elements <tt>eql?</tt> to +obj+:
*/
static VALUE
@@ -5148,7 +6131,7 @@ static VALUE
flatten(VALUE ary, int level)
{
long i;
- VALUE stack, result, tmp, elt, vmemo;
+ VALUE stack, result, tmp = 0, elt, vmemo;
st_table *memo = 0;
st_data_t id;
@@ -5232,28 +6215,36 @@ flatten(VALUE ary, int level)
st_clear(memo);
}
- RBASIC_SET_CLASS(result, rb_obj_class(ary));
+ RBASIC_SET_CLASS(result, rb_cArray);
return result;
}
/*
* call-seq:
- * ary.flatten! -> ary or nil
- * ary.flatten!(level) -> ary or nil
- *
- * Flattens +self+ in place.
- *
- * Returns +nil+ if no modifications were made (i.e., the array contains no
- * subarrays.)
- *
- * The optional +level+ argument determines the level of recursion to flatten.
- *
- * a = [ 1, 2, [3, [4, 5] ] ]
- * a.flatten! #=> [1, 2, 3, 4, 5]
- * a.flatten! #=> nil
- * a #=> [1, 2, 3, 4, 5]
- * a = [ 1, 2, [3, [4, 5] ] ]
- * a.flatten!(1) #=> [1, 2, 3, [4, 5]]
+ * array.flatten! -> self or nil
+ * array.flatten!(level) -> self or nil
+ *
+ * Replaces each nested \Array in +self+ with the elements from that \Array;
+ * returns +self+ if any changes, +nil+ otherwise.
+ *
+ * With non-negative \Integer argument +level+, flattens recursively through +level+ levels:
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten!(1) # => [0, 1, [2, 3], 4, 5]
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten!(2) # => [0, 1, 2, 3, 4, 5]
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten!(3) # => [0, 1, 2, 3, 4, 5]
+ * [0, 1, 2].flatten!(1) # => nil
+ *
+ * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten! # => [0, 1, 2, 3, 4, 5]
+ * [0, 1, 2].flatten! # => nil
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten!(-1) # => [0, 1, 2, 3, 4, 5]
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten!(-2) # => [0, 1, 2, 3, 4, 5]
+ * [0, 1, 2].flatten!(-1) # => nil
*/
static VALUE
@@ -5280,24 +6271,32 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.flatten -> new_ary
- * ary.flatten(level) -> new_ary
- *
- * Returns a new array that is a one-dimensional flattening of +self+
- * (recursively).
- *
- * That is, for every element that is an array, extract its elements into
- * the new array.
- *
- * The optional +level+ argument determines the level of recursion to
- * flatten.
- *
- * s = [ 1, 2, 3 ] #=> [1, 2, 3]
- * t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]]
- * a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
- * a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- * a = [ 1, 2, [3, [4, 5] ] ]
- * a.flatten(1) #=> [1, 2, 3, [4, 5]]
+ * array.flatten -> new_array
+ * array.flatten(level) -> new_array
+ *
+ * Returns a new \Array that is a recursive flattening of +self+:
+ * - Each non-Array element is unchanged.
+ * - Each \Array is replaced by its individual elements.
+ *
+ * With non-negative \Integer argument +level+, flattens recursively through +level+ levels:
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten(0) # => [0, [1, [2, 3], 4], 5]
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten(1) # => [0, 1, [2, 3], 4, 5]
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten(2) # => [0, 1, 2, 3, 4, 5]
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten(3) # => [0, 1, 2, 3, 4, 5]
+ *
+ * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten # => [0, 1, 2, 3, 4, 5]
+ * [0, 1, 2].flatten # => [0, 1, 2]
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten(-1) # => [0, 1, 2, 3, 4, 5]
+ * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
+ * a.flatten(-2) # => [0, 1, 2, 3, 4, 5]
+ * [0, 1, 2].flatten(-1) # => [0, 1, 2]
*/
static VALUE
@@ -5319,45 +6318,13 @@ rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
return result;
}
-#define OPTHASH_GIVEN_P(opts) \
- (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
-static ID id_random;
-
#define RAND_UPTO(max) (long)rb_random_ulong_limited((randgen), (max)-1)
-/*
- * call-seq:
- * ary.shuffle! -> ary
- * ary.shuffle!(random: rng) -> ary
- *
- * Shuffles elements in +self+ in place.
- *
- * a = [ 1, 2, 3 ] #=> [1, 2, 3]
- * a.shuffle! #=> [2, 3, 1]
- * a #=> [2, 3, 1]
- *
- * The optional +rng+ argument will be used as the random number generator.
- *
- * a.shuffle!(random: Random.new(1)) #=> [1, 3, 2]
- */
-
static VALUE
-rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
+rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
{
- VALUE opts, randgen = rb_cRandom;
long i, len;
- if (OPTHASH_GIVEN_P(opts)) {
- VALUE rnd;
- ID keyword_ids[1];
-
- keyword_ids[0] = id_random;
- rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
- if (rnd != Qundef) {
- randgen = rnd;
- }
- }
- rb_check_arity(argc, 0, 0);
rb_ary_modify(ary);
i = len = RARRAY_LEN(ary);
RARRAY_PTR_USE(ary, ptr, {
@@ -5375,80 +6342,24 @@ rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
return ary;
}
-
-/*
- * call-seq:
- * ary.shuffle -> new_ary
- * ary.shuffle(random: rng) -> new_ary
- *
- * Returns a new array with elements of +self+ shuffled.
- *
- * a = [ 1, 2, 3 ] #=> [1, 2, 3]
- * a.shuffle #=> [2, 3, 1]
- * a #=> [1, 2, 3]
- *
- * The optional +rng+ argument will be used as the random number generator.
- *
- * a.shuffle(random: Random.new(1)) #=> [1, 3, 2]
- */
-
static VALUE
-rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
+rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
{
ary = rb_ary_dup(ary);
- rb_ary_shuffle_bang(argc, argv, ary);
+ rb_ary_shuffle_bang(ec, ary, randgen);
return ary;
}
-
-/*
- * call-seq:
- * ary.sample -> obj
- * ary.sample(random: rng) -> obj
- * ary.sample(n) -> new_ary
- * ary.sample(n, random: rng) -> new_ary
- *
- * Choose a random element or +n+ random elements from the array.
- *
- * The elements are chosen by using random and unique indices into the array
- * in order to ensure that an element doesn't repeat itself unless the array
- * already contained duplicate elements.
- *
- * If the array is empty the first form returns +nil+ and the second form
- * returns an empty array.
- *
- * a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
- * a.sample #=> 7
- * a.sample(4) #=> [6, 4, 2, 5]
- *
- * The optional +rng+ argument will be used as the random number generator.
- *
- * a.sample(random: Random.new(1)) #=> 6
- * a.sample(4, random: Random.new(1)) #=> [6, 10, 9, 2]
- */
-
-
static VALUE
-rb_ary_sample(int argc, VALUE *argv, VALUE ary)
+rb_ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array)
{
- VALUE nv, result;
- VALUE opts, randgen = rb_cRandom;
+ VALUE result;
long n, len, i, j, k, idx[10];
long rnds[numberof(idx)];
long memo_threshold;
- if (OPTHASH_GIVEN_P(opts)) {
- VALUE rnd;
- ID keyword_ids[1];
-
- keyword_ids[0] = id_random;
- rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
- if (rnd != Qundef) {
- randgen = rnd;
- }
- }
len = RARRAY_LEN(ary);
- if (rb_check_arity(argc, 0, 1) == 0) {
+ if (!to_array) {
if (len < 2)
i = 0;
else
@@ -5456,7 +6367,6 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
return rb_ary_elt(ary, i);
}
- nv = argv[0];
n = NUM2LONG(nv);
if (n < 0) rb_raise(rb_eArgError, "negative sample number");
if (n > len) n = len;
@@ -5478,7 +6388,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
return rb_ary_new_capa(0);
case 1:
i = rnds[0];
- return rb_ary_new_from_values(1, &RARRAY_AREF(ary, i));
+ return rb_ary_new_from_args(1, RARRAY_AREF(ary, i));
case 2:
i = rnds[0];
j = rnds[1];
@@ -5588,24 +6498,33 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
/*
* call-seq:
- * ary.cycle(n=nil) {|obj| block} -> nil
- * ary.cycle(n=nil) -> Enumerator
- *
- * Calls the given block for each element +n+ times or forever if +nil+ is
- * given.
- *
- * Does nothing if a non-positive number is given or the array is empty.
- *
- * Returns +nil+ if the loop has finished without getting interrupted.
- *
- * If no block is given, an Enumerator is returned instead.
- *
- * a = ["a", "b", "c"]
- * a.cycle {|x| puts x} # print, a, b, c, a, b, c,.. forever.
- * a.cycle(2) {|x| puts x} # print, a, b, c, a, b, c.
- *
+ * array.cycle {|element| ... } -> nil
+ * array.cycle(count) {|element| ... } -> nil
+ * array.cycle -> new_enumerator
+ * array.cycle(count) -> new_enumerator
+ *
+ * When called with positive \Integer argument +count+ and a block,
+ * calls the block with each element, then does so again,
+ * until it has done so +count+ times; returns +nil+:
+ * output = []
+ * [0, 1].cycle(2) {|element| output.push(element) } # => nil
+ * output # => [0, 1, 0, 1]
+ *
+ * If +count+ is zero or negative, does not call the block:
+ * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
+ * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
+ *
+ * When a block is given, and argument is omitted or +nil+, cycles forever:
+ * # Prints 0 and 1 forever.
+ * [0, 1].cycle {|element| puts element }
+ * [0, 1].cycle(nil) {|element| puts element }
+ *
+ * When no block is given, returns a new \Enumerator:
+ *
+ * [0, 1].cycle(2) # => #<Enumerator: [0, 1]:cycle(2)>
+ * [0, 1].cycle # => # => #<Enumerator: [0, 1]:cycle>
+ * [0, 1].cycle.first(5) # => [0, 1, 0, 1, 0]
*/
-
static VALUE
rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
{
@@ -5699,7 +6618,7 @@ permute0(const long n, const long r, long *const p, char *const used, const VALU
/*
* Returns the product of from, from-1, ..., from - how_many + 1.
- * http://en.wikipedia.org/wiki/Pochhammer_symbol
+ * https://en.wikipedia.org/wiki/Pochhammer_symbol
*/
static VALUE
descending_factorial(long from, long how_many)
@@ -5751,30 +6670,66 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * ary.permutation {|p| block} -> ary
- * ary.permutation -> Enumerator
- * ary.permutation(n) {|p| block} -> ary
- * ary.permutation(n) -> Enumerator
- *
- * When invoked with a block, yield all permutations of length +n+ of the
- * elements of the array, then return the array itself.
- *
- * If +n+ is not specified, yield all permutations of all elements.
- *
- * The implementation makes no guarantees about the order in which the
- * permutations are yielded.
- *
- * If no block is given, an Enumerator is returned instead.
- *
- * Examples:
- *
- * a = [1, 2, 3]
- * a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
- * a.permutation(1).to_a #=> [[1],[2],[3]]
- * a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
- * a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
- * a.permutation(0).to_a #=> [[]] # one permutation of length 0
- * a.permutation(4).to_a #=> [] # no permutations of length 4
+ * array.permutation {|element| ... } -> self
+ * array.permutation(n) {|element| ... } -> self
+ * array.permutation -> new_enumerator
+ * array.permutation(n) -> new_enumerator
+ *
+ * When invoked with a block, yield all permutations of elements of +self+; returns +self+.
+ * The order of permutations is indeterminate.
+ *
+ * When a block and an in-range positive \Integer argument +n+ (<tt>0 < n <= self.size</tt>)
+ * are given, calls the block with all +n+-tuple permutations of +self+.
+ *
+ * Example:
+ * a = [0, 1, 2]
+ * a.permutation(2) {|permutation| p permutation }
+ * Output:
+ * [0, 1]
+ * [0, 2]
+ * [1, 0]
+ * [1, 2]
+ * [2, 0]
+ * [2, 1]
+ * Another example:
+ * a = [0, 1, 2]
+ * a.permutation(3) {|permutation| p permutation }
+ * Output:
+ * [0, 1, 2]
+ * [0, 2, 1]
+ * [1, 0, 2]
+ * [1, 2, 0]
+ * [2, 0, 1]
+ * [2, 1, 0]
+ *
+ * When +n+ is zero, calls the block once with a new empty \Array:
+ * a = [0, 1, 2]
+ * a.permutation(0) {|permutation| p permutation }
+ * Output:
+ * []
+ *
+ * When +n+ is out of range (negative or larger than <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)>
*/
static VALUE
@@ -5847,27 +6802,44 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * ary.combination(n) {|c| block} -> ary
- * ary.combination(n) -> Enumerator
- *
- * When invoked with a block, yields all combinations of length +n+ of elements
- * from the array and then returns the array itself.
- *
- * The implementation makes no guarantees about the order in which the
- * combinations are yielded.
- *
- * If no block is given, an Enumerator is returned instead.
- *
- * Examples:
- *
- * a = [1, 2, 3, 4]
- * a.combination(1).to_a #=> [[1],[2],[3],[4]]
- * a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
- * a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
- * a.combination(4).to_a #=> [[1,2,3,4]]
- * a.combination(0).to_a #=> [[]] # one combination of length 0
- * a.combination(5).to_a #=> [] # no combinations of length 5
- *
+ * array.combination(n) {|element| ... } -> self
+ * array.combination(n) -> new_enumerator
+ *
+ * Calls the block, if given, with combinations of elements of +self+;
+ * returns +self+. The order of combinations is indeterminate.
+ *
+ * When a block and an in-range positive \Integer argument +n+ (<tt>0 < n <= self.size</tt>)
+ * are given, calls the block with all +n+-tuple combinations of +self+.
+ *
+ * Example:
+ * a = [0, 1, 2]
+ * a.combination(2) {|combination| p combination }
+ * Output:
+ * [0, 1]
+ * [0, 2]
+ * [1, 2]
+ *
+ * Another example:
+ * a = [0, 1, 2]
+ * a.combination(3) {|combination| p combination }
+ * Output:
+ * [0, 1, 2]
+ *
+ * When +n+ is zero, calls the block once with a new empty \Array:
+ * a = [0, 1, 2]
+ * a1 = a.combination(0) {|combination| p combination }
+ * Output:
+ * []
+ *
+ * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
+ * does not call the block:
+ * a = [0, 1, 2]
+ * a.combination(-1) {|combination| fail 'Cannot happen' }
+ * a.combination(4) {|combination| fail 'Cannot happen' }
+ *
+ * Returns a new \Enumerator if no block given:
+ * a = [0, 1, 2]
+ * a.combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
*/
static VALUE
@@ -5954,27 +6926,59 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * ary.repeated_permutation(n) {|p| block} -> ary
- * ary.repeated_permutation(n) -> Enumerator
- *
- * When invoked with a block, yield all repeated permutations of length +n+ of
- * the elements of the array, then return the array itself.
- *
- * The implementation makes no guarantees about the order in which the repeated
- * permutations are yielded.
- *
- * If no block is given, an Enumerator is returned instead.
- *
- * Examples:
- *
- * a = [1, 2]
- * a.repeated_permutation(1).to_a #=> [[1], [2]]
- * a.repeated_permutation(2).to_a #=> [[1,1],[1,2],[2,1],[2,2]]
- * a.repeated_permutation(3).to_a #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2],
- * # [2,1,1],[2,1,2],[2,2,1],[2,2,2]]
- * a.repeated_permutation(0).to_a #=> [[]] # one permutation of length 0
+ * array.repeated_permutation(n) {|permutation| ... } -> self
+ * array.repeated_permutation(n) -> new_enumerator
+ *
+ * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
+ * each permutation is an \Array;
+ * returns +self+. The order of the permutations is indeterminate.
+ *
+ * When a block and a positive \Integer argument +n+ are given, calls the block with each
+ * +n+-tuple repeated permutation of the elements of +self+.
+ * The number of permutations is <tt>self.size**n</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:
+ * [0, 0]
+ * [0, 1]
+ * [0, 2]
+ * [1, 0]
+ * [1, 1]
+ * [1, 2]
+ * [2, 0]
+ * [2, 1]
+ * [2, 2]
+ *
+ * If +n+ is zero, calls the block once with an empty \Array.
+ *
+ * If +n+ is negative, does not call the block:
+ * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
+ *
+ * Returns a new \Enumerator if no block given:
+ * a = [0, 1, 2]
+ * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
+ *
+ * Using Enumerators, it's convenient to show the permutations and counts
+ * for some values of +n+:
+ * e = a.repeated_permutation(0)
+ * e.size # => 1
+ * e.to_a # => [[]]
+ * e = a.repeated_permutation(1)
+ * e.size # => 3
+ * e.to_a # => [[0], [1], [2]]
+ * e = a.repeated_permutation(2)
+ * e.size # => 9
+ * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
*/
-
static VALUE
rb_ary_repeated_permutation(VALUE ary, VALUE num)
{
@@ -6044,29 +7048,55 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * ary.repeated_combination(n) {|c| block} -> ary
- * ary.repeated_combination(n) -> Enumerator
- *
- * When invoked with a block, yields all repeated combinations of length +n+ of
- * elements from the array and then returns the array itself.
- *
- * The implementation makes no guarantees about the order in which the repeated
- * combinations are yielded.
- *
- * If no block is given, an Enumerator is returned instead.
- *
- * Examples:
- *
- * a = [1, 2, 3]
- * a.repeated_combination(1).to_a #=> [[1], [2], [3]]
- * a.repeated_combination(2).to_a #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
- * a.repeated_combination(3).to_a #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],
- * # [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]
- * a.repeated_combination(4).to_a #=> [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3],
- * # [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3],
- * # [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]]
- * a.repeated_combination(0).to_a #=> [[]] # one combination of length 0
- *
+ * array.repeated_combination(n) {|combination| ... } -> self
+ * array.repeated_combination(n) -> new_enumerator
+ *
+ * Calls the block with each repeated combination of length +n+ of the elements of +self+;
+ * each combination is an \Array;
+ * returns +self+. The order of the combinations is indeterminate.
+ *
+ * When a block and a positive \Integer argument +n+ are given, calls the block with each
+ * +n+-tuple repeated combination of the elements of +self+.
+ * The number of combinations is <tt>(n+1)(n+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:
+ * [0, 0]
+ * [0, 1]
+ * [0, 2]
+ * [1, 1]
+ * [1, 2]
+ * [2, 2]
+ *
+ * If +n+ is zero, calls the block once with an empty \Array.
+ *
+ * If +n+ is negative, does not call the block:
+ * a.repeated_combination(-1) {|combination| fail 'Cannot happen' }
+ *
+ * Returns a new \Enumerator if no block given:
+ * a = [0, 1, 2]
+ * a.repeated_combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
+ *
+ * Using Enumerators, it's convenient to show the combinations and counts
+ * for some values of +n+:
+ * e = a.repeated_combination(0)
+ * e.size # => 1
+ * e.to_a # => [[]]
+ * e = a.repeated_combination(1)
+ * e.size # => 3
+ * e.to_a # => [[0], [1], [2]]
+ * e = a.repeated_combination(2)
+ * e.size # => 6
+ * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
*/
static VALUE
@@ -6106,23 +7136,51 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
/*
* call-seq:
- * ary.product(other_ary, ...) -> new_ary
- * ary.product(other_ary, ...) {|p| block} -> ary
- *
- * Returns an array of all combinations of elements from all arrays.
- *
- * The length of the returned array is the product of the length of +self+ and
- * the argument arrays.
- *
- * If given a block, #product will yield all combinations and return +self+
- * instead.
- *
- * [1,2,3].product([4,5]) #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
- * [1,2].product([1,2]) #=> [[1,1],[1,2],[2,1],[2,2]]
- * [1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
- * # [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
- * [1,2].product() #=> [[1],[2]]
- * [1,2].product([]) #=> []
+ * array.product(*other_arrays) -> new_array
+ * array.product(*other_arrays) {|combination| ... } -> self
+ *
+ * Computes and returns or yields all combinations of elements from all the Arrays,
+ * including both +self+ and +other_arrays+.
+ * - The number of combinations is the product of the sizes of all the arrays,
+ * including both +self+ and +other_arrays+.
+ * - The order of the returned combinations is indeterminate.
+ *
+ * When no block is given, returns the combinations as an \Array of Arrays:
+ * a = [0, 1, 2]
+ * a1 = [3, 4]
+ * a2 = [5, 6]
+ * p = a.product(a1)
+ * p.size # => 6 # a.size * a1.size
+ * p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]]
+ * p = a.product(a1, a2)
+ * p.size # => 12 # a.size * a1.size * a2.size
+ * p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
+ *
+ * If any argument is an empty \Array, returns an empty \Array.
+ *
+ * If no argument is given, returns an \Array of 1-element Arrays,
+ * each containing an element of +self+:
+ * a.product # => [[0], [1], [2]]
+ *
+ * When a block is given, yields each combination as an \Array; returns +self+:
+ * a.product(a1) {|combination| p combination }
+ * Output:
+ * [0, 3]
+ * [0, 4]
+ * [1, 3]
+ * [1, 4]
+ * [2, 3]
+ * [2, 4]
+ *
+ * If any argument is an empty \Array, does not call the block:
+ * a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
+ *
+ * If no argument is given, yields each element of +self+ as a 1-element \Array:
+ * a.product {|combination| p combination }
+ * Output:
+ * [0]
+ * [1]
+ * [2]
*/
static VALUE
@@ -6215,17 +7273,18 @@ done:
/*
* call-seq:
- * ary.take(n) -> new_ary
- *
- * Returns first +n+ elements from the array.
- *
- * If a negative number is given, raises an ArgumentError.
- *
- * See also Array#drop
- *
- * a = [1, 2, 3, 4, 5, 0]
- * a.take(3) #=> [1, 2, 3]
- *
+ * array.take(n) -> new_array
+ *
+ * Returns a new \Array containing the first +n+ element of +self+,
+ * where +n+ is a non-negative \Integer;
+ * does not modify +self+.
+ *
+ * Examples:
+ * a = [0, 1, 2, 3, 4, 5]
+ * a.take(1) # => [0]
+ * a.take(2) # => [0, 1]
+ * a.take(50) # => [0, 1, 2, 3, 4, 5]
+ * a # => [0, 1, 2, 3, 4, 5]
*/
static VALUE
@@ -6240,19 +7299,22 @@ rb_ary_take(VALUE obj, VALUE n)
/*
* call-seq:
- * ary.take_while {|obj| block} -> new_ary
- * ary.take_while -> Enumerator
- *
- * Passes elements to the block until the block returns +nil+ or +false+, then
- * stops iterating and returns an array of all prior elements.
- *
- * If no block is given, an Enumerator is returned instead.
- *
- * See also Array#drop_while
- *
- * a = [1, 2, 3, 4, 5, 0]
- * a.take_while {|i| i < 3} #=> [1, 2]
- *
+ * array.take_while {|element| ... } -> new_array
+ * array.take_while -> new_enumerator
+ *
+ * Returns a new \Array containing zero or more leading elements of +self+;
+ * does not modify +self+.
+ *
+ * With a block given, calls the block with each successive element of +self+;
+ * stops if the block returns +false+ or +nil+;
+ * returns a new Array containing those elements for which the block returned a truthy value:
+ * a = [0, 1, 2, 3, 4, 5]
+ * a.take_while {|element| element < 3 } # => [0, 1, 2]
+ * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
+ * a # => [0, 1, 2, 3, 4, 5]
+ *
+ * With no block given, returns a new \Enumerator:
+ * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
*/
static VALUE
@@ -6269,18 +7331,17 @@ rb_ary_take_while(VALUE ary)
/*
* call-seq:
- * ary.drop(n) -> new_ary
- *
- * Drops first +n+ elements from +ary+ and returns the rest of the elements in
- * an array.
- *
- * If a negative number is given, raises an ArgumentError.
+ * array.drop(n) -> new_array
*
- * See also Array#take
- *
- * a = [1, 2, 3, 4, 5, 0]
- * a.drop(3) #=> [4, 5, 0]
+ * Returns a new \Array containing all but the first +n+ element of +self+,
+ * where +n+ is a non-negative \Integer;
+ * does not modify +self+.
*
+ * Examples:
+ * a = [0, 1, 2, 3, 4, 5]
+ * a.drop(0) # => [0, 1, 2, 3, 4, 5]
+ * a.drop(1) # => [1, 2, 3, 4, 5]
+ * a.drop(2) # => [2, 3, 4, 5]
*/
static VALUE
@@ -6299,20 +7360,20 @@ rb_ary_drop(VALUE ary, VALUE n)
/*
* call-seq:
- * ary.drop_while {|obj| block} -> new_ary
- * ary.drop_while -> Enumerator
- *
- * Drops elements up to, but not including, the first element for which the
- * block returns +nil+ or +false+ and returns an array containing the
- * remaining elements.
- *
- * If no block is given, an Enumerator is returned instead.
- *
- * See also Array#take_while
+ * array.drop_while {|element| ... } -> new_array
+ * array.drop_while -> new_enumerator
+
+ * Returns a new \Array containing zero or more trailing elements of +self+;
+ * does not modify +self+.
*
- * a = [1, 2, 3, 4, 5, 0]
- * a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]
+ * With a block given, calls the block with each successive element of +self+;
+ * stops if the block returns +false+ or +nil+;
+ * returns a new Array _omitting_ those elements for which the block returned a truthy value:
+ * a = [0, 1, 2, 3, 4, 5]
+ * a.drop_while {|element| element < 3 } # => [3, 4, 5]
*
+ * With no block given, returns a new \Enumerator:
+ * [0, 1].drop_while # => # => #<Enumerator: [0, 1]:drop_while>
*/
static VALUE
@@ -6329,10 +7390,32 @@ rb_ary_drop_while(VALUE ary)
/*
* call-seq:
- * ary.any? [{|obj| block} ] -> true or false
- * ary.any?(pattern) -> true or false
- *
- * See also Enumerable#any?
+ * array.any? -> true or false
+ * array.any? {|element| ... } -> true or false
+ * array.any?(obj) -> true or false
+ *
+ * Returns +true+ if any element of +self+ meets a given criterion.
+ *
+ * With no block given and no argument, returns +true+ if +self+ has any truthy element,
+ * +false+ otherwise:
+ * [nil, 0, false].any? # => true
+ * [nil, false].any? # => false
+ * [].any? # => false
+ *
+ * With a block given and no argument, calls the block with each element in +self+;
+ * returns +true+ if the block returns any truthy value, +false+ otherwise:
+ * [0, 1, 2].any? {|element| element > 1 } # => true
+ * [0, 1, 2].any? {|element| element > 2 } # => false
+ *
+ * If argument +obj+ is given, returns +true+ if +obj+.<tt>===</tt> any element,
+ * +false+ otherwise:
+ * ['food', 'drink'].any?(/foo/) # => true
+ * ['food', 'drink'].any?(/bar/) # => false
+ * [].any?(/foo/) # => false
+ * [0, 1, 2].any?(1) # => true
+ * [0, 1, 2].any?(3) # => false
+ *
+ * Related: Enumerable#any?
*/
static VALUE
@@ -6365,10 +7448,31 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.all? [{|obj| block} ] -> true or false
- * ary.all?(pattern) -> true or false
- *
- * See also Enumerable#all?
+ * array.all? -> true or false
+ * array.all? {|element| ... } -> true or false
+ * array.all?(obj) -> true or false
+ *
+ * Returns +true+ if all elements of +self+ meet a given criterion.
+ *
+ * With no block given and no argument, returns +true+ if +self+ contains only truthy elements,
+ * +false+ otherwise:
+ * [0, 1, :foo].all? # => true
+ * [0, nil, 2].all? # => false
+ * [].all? # => true
+ *
+ * With a block given and no argument, calls the block with each element in +self+;
+ * returns +true+ if the block returns only truthy values, +false+ otherwise:
+ * [0, 1, 2].all? { |element| element < 3 } # => true
+ * [0, 1, 2].all? { |element| element < 2 } # => false
+ *
+ * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> every element, +false+ otherwise:
+ * ['food', 'fool', 'foot'].all?(/foo/) # => true
+ * ['food', 'drink'].all?(/bar/) # => false
+ * [].all?(/foo/) # => true
+ * [0, 0, 0].all?(0) # => true
+ * [0, 1, 2].all?(1) # => false
+ *
+ * Related: Enumerable#all?
*/
static VALUE
@@ -6401,10 +7505,31 @@ rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.none? [{|obj| block} ] -> true or false
- * ary.none?(pattern) -> true or false
- *
- * See also Enumerable#none?
+ * array.none? -> true or false
+ * array.none? {|element| ... } -> true or false
+ * array.none?(obj) -> true or false
+ *
+ * Returns +true+ if no element of +self+ meet a given criterion.
+ *
+ * With no block given and no argument, returns +true+ if +self+ has no truthy elements,
+ * +false+ otherwise:
+ * [nil, false].none? # => true
+ * [nil, 0, false].none? # => false
+ * [].none? # => true
+ *
+ * With a block given and no argument, calls the block with each element in +self+;
+ * returns +true+ if the block returns no truthy value, +false+ otherwise:
+ * [0, 1, 2].none? {|element| element > 3 } # => true
+ * [0, 1, 2].none? {|element| element > 1 } # => false
+ *
+ * If argument +obj+ is given, returns +true+ if <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?
*/
static VALUE
@@ -6437,10 +7562,35 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.one? [{|obj| block} ] -> true or false
- * ary.one?(pattern) -> true or false
- *
- * See also Enumerable#one?
+ * array.one? -> true or false
+ * array.one? {|element| ... } -> true or false
+ * array.one?(obj) -> true or false
+ *
+ * Returns +true+ if exactly one element of +self+ meets a given criterion.
+ *
+ * With no block given and no argument, returns +true+ if +self+ has exactly one truthy element,
+ * +false+ otherwise:
+ * [nil, 0].one? # => true
+ * [0, 0].one? # => false
+ * [nil, nil].one? # => false
+ * [].one? # => false
+ *
+ * With a block given and no argument, calls the block with each element in +self+;
+ * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
+ * [0, 1, 2].one? {|element| element > 0 } # => false
+ * [0, 1, 2].one? {|element| element > 1 } # => true
+ * [0, 1, 2].one? {|element| element > 2 } # => false
+ *
+ * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> exactly one element,
+ * +false+ otherwise:
+ * [0, 1, 2].one?(0) # => true
+ * [0, 0, 1].one?(0) # => false
+ * [1, 1, 2].one?(0) # => false
+ * ['food', 'drink'].one?(/bar/) # => false
+ * ['food', 'drink'].one?(/foo/) # => true
+ * [].one?(/foo/) # => false
+ *
+ * Related: Enumerable#one?
*/
static VALUE
@@ -6482,19 +7632,20 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
}
/*
- * call-seq:
- * ary.dig(idx, ...) -> object
- *
- * Extracts the nested value specified by the sequence of <i>idx</i>
- * objects by calling +dig+ at each step, returning +nil+ if any
- * intermediate step is +nil+.
- *
- * a = [[1, [2, 3]]]
- *
- * a.dig(0, 1, 1) #=> 3
- * a.dig(1, 2, 3) #=> nil
- * a.dig(0, 0, 0) #=> TypeError: Integer does not have #dig method
- * [42, {foo: :bar}].dig(1, :foo) #=> :bar
+ * call-seq:
+ * array.dig(index, *identifiers) -> object
+ *
+ * Finds and returns the object in nested objects
+ * that is specified by +index+ and +identifiers+.
+ * The nested objects may be instances of various classes.
+ * See {Dig Methods}[rdoc-ref:doc/dig_methods.rdoc].
+ *
+ * Examples:
+ * a = [:foo, [:bar, :baz, [:bat, :bam]]]
+ * a.dig(1) # => [:bar, :baz, [:bat, :bam]]
+ * a.dig(1, 2) # => [:bat, :bam]
+ * a.dig(1, 2, 0) # => :bat
+ * a.dig(1, 2, 3) # => nil
*/
static VALUE
@@ -6513,13 +7664,7 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z)
if (n != 0)
v = rb_fix_plus(LONG2FIX(n), v);
if (r != Qundef) {
- /* r can be an Integer when mathn is loaded */
- if (FIXNUM_P(r))
- v = rb_fix_plus(r, v);
- else if (RB_TYPE_P(r, T_BIGNUM))
- v = rb_big_plus(r, v);
- else
- v = rb_rational_plus(r, v);
+ v = rb_rational_plus(r, v);
}
else if (!n && z) {
v = rb_fix_plus(LONG2FIX(0), v);
@@ -6529,44 +7674,35 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z)
/*
* call-seq:
- * ary.sum(init=0) -> number
- * ary.sum(init=0) {|e| expr } -> number
- *
- * Returns the sum of elements.
- * For example, [e1, e2, e3].sum returns init + e1 + e2 + e3.
- *
- * If a block is given, the block is applied to each element
- * before addition.
- *
- * If <i>ary</i> is empty, it returns <i>init</i>.
- *
- * [].sum #=> 0
- * [].sum(0.0) #=> 0.0
- * [1, 2, 3].sum #=> 6
- * [3, 5.5].sum #=> 8.5
- * [2.5, 3.0].sum(0.0) {|e| e * e } #=> 15.25
- * [Object.new].sum #=> TypeError
- *
- * The (arithmetic) mean value of an array can be obtained as follows.
- *
- * mean = ary.sum(0.0) / ary.length
- *
- * This method can be used for non-numeric objects by
- * explicit <i>init</i> argument.
- *
- * ["a", "b", "c"].sum("") #=> "abc"
- * [[1], [[2]], [3]].sum([]) #=> [1, [2], 3]
- *
- * However, Array#join and Array#flatten is faster than Array#sum for
- * array of strings and array of arrays.
- *
- * ["a", "b", "c"].join #=> "abc"
- * [[1], [[2]], [3]].flatten(1) #=> [1, [2], 3]
- *
- *
- * Array#sum method may not respect method redefinition of "+" methods
- * such as Integer#+.
- *
+ * array.sum(init = 0) -> object
+ * array.sum(init = 0) {|element| ... } -> object
+ *
+ * When no block is given, returns the object equivalent to:
+ * sum = init
+ * array.each {|element| sum += element }
+ * sum
+ * For example, <tt>[e1, e2, e3].sum</tt> returns </tt>init + e1 + e2 + e3</tt>.
+ *
+ * Examples:
+ * a = [0, 1, 2, 3]
+ * a.sum # => 6
+ * a.sum(100) # => 106
+ *
+ * The elements need not be numeric, but must be <tt>+</tt>-compatible
+ * with each other and with +init+:
+ * a = ['abc', 'def', 'ghi']
+ * a.sum('jkl') # => "jklabcdefghi"
+ *
+ * When a block is given, it is called with each element
+ * and the block's return value (instead of the element itself) is used as the addend:
+ * a = ['zero', 1, :two]
+ * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
+ * s # => "Coerced and concatenated: zero1two"
+ *
+ * Notes:
+ * - Array#join and Array#flatten may be faster than Array#sum
+ * for an \Array of Strings or an \Array of Arrays.
+ * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
*/
static VALUE
@@ -6616,7 +7752,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary)
if (RB_FLOAT_TYPE_P(e)) {
/*
* Kahan-Babuska balancing compensated summation algorithm
- * See http://link.springer.com/article/10.1007/s00607-005-0139-x
+ * See https://link.springer.com/article/10.1007/s00607-005-0139-x
*/
double f, c;
double x, t;
@@ -6686,12 +7822,32 @@ rb_ary_deconstruct(VALUE ary)
}
/*
- * Arrays are ordered, integer-indexed collections of any object.
+ * An \Array is an ordered, integer-indexed collection of objects,
+ * called _elements_. Any object may be an \Array element.
+ *
+ * == \Array Indexes
+ *
+ * \Array indexing starts at 0, as in C or Java.
+ *
+ * A positive index is an offset from the first element:
+ * - Index 0 indicates the first element.
+ * - Index 1 indicates the second element.
+ * - ...
+ *
+ * A negative index is an offset, backwards, from the end of the array:
+ * - Index -1 indicates the last element.
+ * - Index -2 indicates the next-to-last element.
+ * - ...
*
- * Array indexing starts at 0, as in C or Java. A negative index is assumed
- * to be relative to the end of the array---that is, an index of -1 indicates
- * the last element of the array, -2 is the next to last element in the
- * array, and so on.
+ * A non-negative index is <i>in range</i> if it is smaller than
+ * the size of the array. For a 3-element array:
+ * - Indexes 0 through 2 are in range.
+ * - Index 3 is out of range.
+ *
+ * A negative index is <i>in range</i> if its absolute value is
+ * not larger than the size of the array. For a 3-element array:
+ * - Indexes -1 through -3 are in range.
+ * - Index -4 is out of range.
*
* == Creating Arrays
*
@@ -6920,15 +8076,11 @@ rb_ary_deconstruct(VALUE ary)
* arr = [1, 2, 3, 4, 5, 6]
* arr.keep_if {|a| a < 4} #=> [1, 2, 3]
* arr #=> [1, 2, 3]
- *
*/
void
Init_Array(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
rb_cArray = rb_define_class("Array", rb_cObject);
rb_include_module(rb_cArray, rb_mEnumerable);
@@ -6970,7 +8122,7 @@ Init_Array(void)
rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
rb_define_method(rb_cArray, "length", rb_ary_length, 0);
- rb_define_alias(rb_cArray, "size", "length");
+ rb_define_method(rb_cArray, "size", rb_ary_length, 0);
rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
rb_define_method(rb_cArray, "index", rb_ary_index, -1);
@@ -7030,9 +8182,6 @@ Init_Array(void)
rb_define_method(rb_cArray, "flatten", rb_ary_flatten, -1);
rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, -1);
rb_define_method(rb_cArray, "count", rb_ary_count, -1);
- rb_define_method(rb_cArray, "shuffle!", rb_ary_shuffle_bang, -1);
- rb_define_method(rb_cArray, "shuffle", rb_ary_shuffle, -1);
- rb_define_method(rb_cArray, "sample", rb_ary_sample, -1);
rb_define_method(rb_cArray, "cycle", rb_ary_cycle, -1);
rb_define_method(rb_cArray, "permutation", rb_ary_permutation, -1);
rb_define_method(rb_cArray, "combination", rb_ary_combination, 1);
@@ -7054,6 +8203,6 @@ Init_Array(void)
rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
-
- id_random = rb_intern("random");
}
+
+#include "array.rbinc"
diff --git a/array.rb b/array.rb
new file mode 100644
index 0000000000..a43a3b27b1
--- /dev/null
+++ b/array.rb
@@ -0,0 +1,61 @@
+class Array
+ # call-seq:
+ # array.shuffle!(random: Random) -> array
+ #
+ # Shuffles the elements of +self+ in place.
+ # a = [1, 2, 3] #=> [1, 2, 3]
+ # a.shuffle! #=> [2, 3, 1]
+ # a #=> [2, 3, 1]
+ #
+ # The optional +random+ argument will be used as the random number generator:
+ # a.shuffle!(random: Random.new(1)) #=> [1, 3, 2]
+ def shuffle!(random: Random)
+ Primitive.rb_ary_shuffle_bang(random)
+ end
+
+ # call-seq:
+ # array.shuffle(random: Random) -> new_ary
+ #
+ # Returns a new array with elements of +self+ shuffled.
+ # a = [1, 2, 3] #=> [1, 2, 3]
+ # a.shuffle #=> [2, 3, 1]
+ # a #=> [1, 2, 3]
+ #
+ # The optional +random+ argument will be used as the random number generator:
+ # a.shuffle(random: Random.new(1)) #=> [1, 3, 2]
+ def shuffle(random: Random)
+ Primitive.rb_ary_shuffle(random)
+ end
+
+ # call-seq:
+ # array.sample(random: Random) -> object
+ # array.sample(n, random: Random) -> new_ary
+ #
+ # Returns random elements from +self+.
+ #
+ # When no arguments are given, returns a random element from +self+:
+ # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ # a.sample # => 3
+ # a.sample # => 8
+ # If +self+ is empty, returns +nil+.
+ #
+ # When argument +n+ is given, returns a new \Array containing +n+ random
+ # elements from +self+:
+ # a.sample(3) # => [8, 9, 2]
+ # a.sample(6) # => [9, 6, 10, 3, 1, 4]
+ # Returns no more than <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]
+ # Returns a new empty \Array if +self+ is empty.
+ #
+ # The optional +random+ argument will be used as the random number generator:
+ # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ # a.sample(random: Random.new(1)) #=> 6
+ # a.sample(4, random: Random.new(1)) #=> [6, 10, 9, 2]
+ def sample(n = (ary = false), random: Random)
+ Primitive.rb_ary_sample(random, n, ary)
+ end
+end
diff --git a/ast.c b/ast.c
index a0c026229c..2af0b3e530 100644
--- a/ast.c
+++ b/ast.c
@@ -1,11 +1,15 @@
/* indent-tabs-mode: nil */
+#include "internal.h"
+#include "internal/parse.h"
+#include "internal/symbol.h"
+#include "internal/warnings.h"
+#include "iseq.h"
+#include "node.h"
#include "ruby.h"
#include "ruby/encoding.h"
#include "ruby/util.h"
-#include "internal.h"
-#include "node.h"
#include "vm_core.h"
-#include "iseq.h"
+
#include "builtin.h"
static VALUE rb_mAST;
@@ -13,7 +17,7 @@ static VALUE rb_cNode;
struct ASTNodeData {
rb_ast_t *ast;
- NODE *node;
+ const NODE *node;
};
static void
@@ -40,7 +44,7 @@ static const rb_data_type_t rb_node_type = {
static VALUE rb_ast_node_alloc(VALUE klass);
static void
-setup_node(VALUE obj, rb_ast_t *ast, NODE *node)
+setup_node(VALUE obj, rb_ast_t *ast, const NODE *node)
{
struct ASTNodeData *data;
@@ -50,7 +54,7 @@ setup_node(VALUE obj, rb_ast_t *ast, NODE *node)
}
static VALUE
-ast_new_internal(rb_ast_t *ast, NODE *node)
+ast_new_internal(rb_ast_t *ast, const NODE *node)
{
VALUE obj;
@@ -141,7 +145,7 @@ rb_ast_parse_array(VALUE array)
return ast_parse_done(ast);
}
-static VALUE node_children(rb_ast_t*, NODE*);
+static VALUE node_children(rb_ast_t*, const NODE*);
static VALUE
node_find(VALUE self, const int node_id)
@@ -264,7 +268,7 @@ rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...)
}
static VALUE
-dump_block(rb_ast_t *ast, NODE *node)
+dump_block(rb_ast_t *ast, const NODE *node)
{
VALUE ary = rb_ary_new();
do {
@@ -280,7 +284,7 @@ dump_block(rb_ast_t *ast, NODE *node)
}
static VALUE
-dump_array(rb_ast_t *ast, NODE *node)
+dump_array(rb_ast_t *ast, const NODE *node)
{
VALUE ary = rb_ary_new();
rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
@@ -303,7 +307,21 @@ var_name(ID id)
}
static VALUE
-node_children(rb_ast_t *ast, NODE *node)
+no_name_rest(void)
+{
+ ID rest;
+ CONST_ID(rest, "NODE_SPECIAL_NO_NAME_REST");
+ return ID2SYM(rest);
+}
+
+static VALUE
+rest_arg(rb_ast_t *ast, const NODE *rest_arg)
+{
+ return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast, rest_arg) : no_name_rest();
+}
+
+static VALUE
+node_children(rb_ast_t *ast, const NODE *node)
{
char name[DECIMAL_SIZE_OF_BITS(sizeof(long) * CHAR_BIT) + 2]; /* including '$' */
@@ -326,9 +344,7 @@ node_children(rb_ast_t *ast, NODE *node)
case NODE_IN:
return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_body, node->nd_next);
case NODE_WHILE:
- goto loop;
case NODE_UNTIL:
- loop:
return rb_ary_push(rb_ary_new_from_node_args(ast, 2, node->nd_cond, node->nd_body),
(node->nd_state ? Qtrue : Qfalse));
case NODE_ITER:
@@ -337,11 +353,8 @@ node_children(rb_ast_t *ast, NODE *node)
case NODE_FOR_MASGN:
return rb_ary_new_from_node_args(ast, 1, node->nd_var);
case NODE_BREAK:
- goto jump;
case NODE_NEXT:
- goto jump;
case NODE_RETURN:
- jump:
return rb_ary_new_from_node_args(ast, 1, node->nd_stts);
case NODE_REDO:
return rb_ary_new_from_node_args(ast, 0);
@@ -356,9 +369,7 @@ node_children(rb_ast_t *ast, NODE *node)
case NODE_ENSURE:
return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_ensr);
case NODE_AND:
- goto andor;
case NODE_OR:
- andor:
{
VALUE ary = rb_ary_new();
@@ -378,24 +389,18 @@ node_children(rb_ast_t *ast, NODE *node)
else {
return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_value),
NEW_CHILD(ast, node->nd_head),
- ID2SYM(rb_intern("NODE_SPECIAL_NO_NAME_REST")));
+ no_name_rest());
}
case NODE_LASGN:
- goto asgn;
case NODE_DASGN:
- goto asgn;
case NODE_DASGN_CURR:
- goto asgn;
case NODE_IASGN:
- goto asgn;
case NODE_CVASGN:
- asgn:
+ case NODE_GASGN:
if (NODE_REQUIRED_KEYWORD_P(node)) {
return rb_ary_new_from_args(2, var_name(node->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
}
return rb_ary_new_from_args(2, var_name(node->nd_vid), NEW_CHILD(ast, node->nd_value));
- case NODE_GASGN:
- goto asgn;
case NODE_CDECL:
if (node->nd_vid) {
return rb_ary_new_from_args(2, ID2SYM(node->nd_vid), NEW_CHILD(ast, node->nd_value));
@@ -438,9 +443,7 @@ node_children(rb_ast_t *ast, NODE *node)
case NODE_ZSUPER:
return rb_ary_new_from_node_args(ast, 0);
case NODE_LIST:
- goto ary;
case NODE_VALUES:
- ary:
return dump_array(ast, node);
case NODE_ZLIST:
return rb_ary_new_from_node_args(ast, 0);
@@ -464,8 +467,6 @@ node_children(rb_ast_t *ast, NODE *node)
name[1] = (char)node->nd_nth;
name[2] = '\0';
return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
- case NODE_MATCH:
- goto lit;
case NODE_MATCH2:
if (node->nd_args) {
return rb_ary_new_from_node_args(ast, 3, node->nd_recv, node->nd_value, node->nd_args);
@@ -473,26 +474,26 @@ node_children(rb_ast_t *ast, NODE *node)
return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_value);
case NODE_MATCH3:
return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_value);
+ case NODE_MATCH:
case NODE_LIT:
- goto lit;
case NODE_STR:
- goto lit;
case NODE_XSTR:
- lit:
return rb_ary_new_from_args(1, node->nd_lit);
case NODE_ONCE:
return rb_ary_new_from_node_args(ast, 1, node->nd_body);
case NODE_DSTR:
- goto dlit;
case NODE_DXSTR:
- goto dlit;
case NODE_DREGX:
- goto dlit;
case NODE_DSYM:
- dlit:
- return rb_ary_new_from_args(3, node->nd_lit,
- NEW_CHILD(ast, node->nd_next->nd_head),
- NEW_CHILD(ast, node->nd_next->nd_next));
+ {
+ NODE *n = node->nd_next;
+ VALUE head = Qnil, next = Qnil;
+ if (n) {
+ head = NEW_CHILD(ast, n->nd_head);
+ next = NEW_CHILD(ast, n->nd_next);
+ }
+ return rb_ary_new_from_args(3, node->nd_lit, head, next);
+ }
case NODE_EVSTR:
return rb_ary_new_from_node_args(ast, 1, node->nd_body);
case NODE_ARGSCAT:
@@ -524,13 +525,9 @@ node_children(rb_ast_t *ast, NODE *node)
case NODE_COLON3:
return rb_ary_new_from_args(1, ID2SYM(node->nd_mid));
case NODE_DOT2:
- goto dot;
case NODE_DOT3:
- goto dot;
case NODE_FLIP2:
- goto dot;
case NODE_FLIP3:
- dot:
return rb_ary_new_from_node_args(ast, 2, node->nd_beg, node->nd_end);
case NODE_SELF:
return rb_ary_new_from_node_args(ast, 0);
@@ -558,7 +555,7 @@ node_children(rb_ast_t *ast, NODE *node)
if (NODE_NAMED_REST_P(node->nd_1st)) {
return rb_ary_new_from_node_args(ast, 2, node->nd_1st, node->nd_2nd);
}
- return rb_ary_new_from_args(2, ID2SYM(rb_intern("NODE_SPECIAL_NO_NAME_REST")),
+ return rb_ary_new_from_args(2, no_name_rest(),
NEW_CHILD(ast, node->nd_2nd));
case NODE_ARGS:
{
@@ -590,14 +587,24 @@ node_children(rb_ast_t *ast, NODE *node)
case NODE_ARYPTN:
{
struct rb_ary_pattern_info *apinfo = node->nd_apinfo;
- VALUE rest = NODE_NAMED_REST_P(apinfo->rest_arg) ? NEW_CHILD(ast, apinfo->rest_arg) :
- ID2SYM(rb_intern("NODE_SPECIAL_NO_NAME_REST"));
+ VALUE rest = rest_arg(ast, apinfo->rest_arg);
return rb_ary_new_from_args(4,
NEW_CHILD(ast, node->nd_pconst),
NEW_CHILD(ast, apinfo->pre_args),
rest,
NEW_CHILD(ast, apinfo->post_args));
}
+ case NODE_FNDPTN:
+ {
+ struct rb_fnd_pattern_info *fpinfo = node->nd_fpinfo;
+ VALUE pre_rest = rest_arg(ast, fpinfo->pre_rest_arg);
+ VALUE post_rest = rest_arg(ast, fpinfo->post_rest_arg);
+ return rb_ary_new_from_args(4,
+ NEW_CHILD(ast, node->nd_pconst),
+ pre_rest,
+ NEW_CHILD(ast, fpinfo->args),
+ post_rest);
+ }
case NODE_HSHPTN:
{
VALUE kwrest = node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) :
@@ -689,6 +696,4 @@ Init_ast(void)
rb_mAST = rb_define_module_under(rb_cRubyVM, "AbstractSyntaxTree");
rb_cNode = rb_define_class_under(rb_mAST, "Node", rb_cObject);
rb_undef_alloc_func(rb_cNode);
-
- load_ast();
}
diff --git a/ast.rb b/ast.rb
index 1fedf76649..34fa645671 100644
--- a/ast.rb
+++ b/ast.rb
@@ -6,10 +6,10 @@ class RubyVM
# abstract syntax trees. The nodes in the tree
# are instances of RubyVM::AbstractSyntaxTree::Node.
#
- # This class is MRI specific as it exposes implementation details
+ # This module is MRI specific as it exposes implementation details
# of the MRI abstract syntax tree.
#
- # This class is experimental and its API is not stable, therefore it might
+ # This module is experimental and its API is not stable, therefore it might
# change without notice. As examples, the order of children nodes is not
# guaranteed, the number of children nodes might change, there is no way to
# access children nodes by name, etc.
@@ -32,7 +32,7 @@ class RubyVM
# RubyVM::AbstractSyntaxTree.parse("x = 1 + 2")
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-1:9>
def self.parse string
- __builtin_ast_s_parse string
+ Primitive.ast_s_parse string
end
# call-seq:
@@ -47,7 +47,7 @@ class RubyVM
# RubyVM::AbstractSyntaxTree.parse_file("my-app/app.rb")
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-31:3>
def self.parse_file pathname
- __builtin_ast_s_parse_file pathname
+ Primitive.ast_s_parse_file pathname
end
# call-seq:
@@ -66,7 +66,7 @@ class RubyVM
# RubyVM::AbstractSyntaxTree.of(method(:hello))
# # => #<RubyVM::AbstractSyntaxTree::Node:SCOPE@1:0-3:3>
def self.of body
- __builtin_ast_s_of body
+ Primitive.ast_s_of body
end
# RubyVM::AbstractSyntaxTree::Node instances are created by parse methods in
@@ -83,10 +83,12 @@ class RubyVM
#
# root = RubyVM::AbstractSyntaxTree.parse("x = 1 + 2")
# root.type # => :SCOPE
- # call = root.children[2]
+ # lasgn = root.children[2]
+ # lasgn.type # => :LASGN
+ # call = lasgn.children[1]
# call.type # => :OPCALL
def type
- __builtin_ast_node_type
+ Primitive.ast_node_type
end
# call-seq:
@@ -94,7 +96,7 @@ class RubyVM
#
# The line number in the source code where this AST's text began.
def first_lineno
- __builtin_ast_node_first_lineno
+ Primitive.ast_node_first_lineno
end
# call-seq:
@@ -102,7 +104,7 @@ class RubyVM
#
# The column number in the source code where this AST's text began.
def first_column
- __builtin_ast_node_first_column
+ Primitive.ast_node_first_column
end
# call-seq:
@@ -110,7 +112,7 @@ class RubyVM
#
# The line number in the source code where this AST's text ended.
def last_lineno
- __builtin_ast_node_last_lineno
+ Primitive.ast_node_last_lineno
end
# call-seq:
@@ -118,7 +120,7 @@ class RubyVM
#
# The column number in the source code where this AST's text ended.
def last_column
- __builtin_ast_node_last_column
+ Primitive.ast_node_last_column
end
# call-seq:
@@ -129,7 +131,7 @@ class RubyVM
#
# The returned array may contain other nodes or <code>nil</code>.
def children
- __builtin_ast_node_children
+ Primitive.ast_node_children
end
# call-seq:
@@ -137,7 +139,7 @@ class RubyVM
#
# Returns debugging information about this node as a string.
def inspect
- __builtin_ast_node_inspect
+ Primitive.ast_node_inspect
end
end
end
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000000..44a1922cb0
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+PWD=
+case "$0" in
+*/*) srcdir=`dirname $0`;;
+*) srcdir="";;
+esac
+
+exec ${AUTORECONF:-autoreconf} --install --symlink "$@" ${srcdir:+"$srcdir"}
diff --git a/basictest/test.rb b/basictest/test.rb
index 25a4298234..52008b78db 100755
--- a/basictest/test.rb
+++ b/basictest/test.rb
@@ -1425,9 +1425,6 @@ marity_test(:test_ok)
marity_test(:marity_test)
marity_test(:p)
-lambda(&method(:test_ok)).call(true)
-lambda(&block_get{|a,n| test_ok(a,n)}).call(true, 2)
-
class ITER_TEST1
def a
block_given?
@@ -2140,7 +2137,7 @@ $_ = foobar
test_ok($_ == foobar)
class Gods
- @@rule = "Uranus" # private to Gods
+ @@rule = "Uranus"
def ruler0
@@rule
end
@@ -2163,7 +2160,7 @@ module Olympians
end
class Titans < Gods
- @@rule = "Cronus" # do not affect @@rule in Gods
+ @@rule = "Cronus" # modifies @@rule in Gods
include Olympians
def ruler4
@@rule
@@ -2178,7 +2175,14 @@ test_ok(Titans.ruler2 == "Cronus")
atlas = Titans.new
test_ok(atlas.ruler0 == "Cronus")
test_ok(atlas.ruler3 == "Zeus")
-test_ok(atlas.ruler4 == "Cronus")
+begin
+ atlas.ruler4
+rescue RuntimeError => e
+ test_ok(e.message.include?("class variable @@rule of Olympians is overtaken by Gods"))
+else
+ test_ok(false)
+end
+test_ok(atlas.ruler3 == "Zeus")
test_check "trace"
$x = 1234
diff --git a/benchmark/README.md b/benchmark/README.md
index 24a2669143..39a5aa139b 100644
--- a/benchmark/README.md
+++ b/benchmark/README.md
@@ -53,20 +53,20 @@ make benchmark
# Or compare with specific ruby binary
make benchmark COMPARE_RUBY="/path/to/ruby --jit"
-# Run vm1 benchmarks
-make benchmark ITEM=vm1
+# Run vm benchmarks
+make benchmark ITEM=vm
# Run some limited benchmarks in ITEM-matched files
-make benchmark ITEM=vm1 OPTS=--filter=block
+make benchmark ITEM=vm OPTS=--filter=block
# You can specify the benchmark by an exact filename instead of using the default argument:
# ARGS = $$(find $(srcdir)/benchmark -maxdepth 1 -name '*$(ITEM)*.yml' -o -name '*$(ITEM)*.rb')
-make benchmark ARGS=../benchmark/erb_render.yml
+make benchmark ARGS=benchmark/erb_render.yml
# You can specify any option via $OPTS
make benchmark OPTS="--help"
# With `make benchmark`, some special runner plugins are available:
# -r peak, -r size, -r total, -r utime, -r stime, -r cutime, -r cstime
-make benchmark ITEM=vm2_bigarray OPTS="-r peak"
+make benchmark ITEM=vm_bigarray OPTS="-r peak"
```
diff --git a/benchmark/array_max_float.yml b/benchmark/array_max_float.yml
new file mode 100644
index 0000000000..ace1ae2e14
--- /dev/null
+++ b/benchmark/array_max_float.yml
@@ -0,0 +1,30 @@
+prelude: |
+ ary2 = 2.times.map(&:to_f).shuffle
+ ary10 = 10.times.map(&:to_f).shuffle
+ ary100 = 100.times.map(&:to_f).shuffle
+ ary500 = 500.times.map(&:to_f).shuffle
+ ary1000 = 1000.times.map(&:to_f).shuffle
+ ary2000 = 2500.times.map(&:to_f).shuffle
+ ary3000 = 2500.times.map(&:to_f).shuffle
+ ary5000 = 5000.times.map(&:to_f).shuffle
+ ary10000 = 10000.times.map(&:to_f).shuffle
+ ary20000 = 20000.times.map(&:to_f).shuffle
+ ary50000 = 50000.times.map(&:to_f).shuffle
+ ary100000 = 100000.times.map(&:to_f).shuffle
+
+benchmark:
+ ary2.max: ary2.max
+ ary10.max: ary10.max
+ ary100.max: ary100.max
+ ary500.max: ary500.max
+ ary1000.max: ary1000.max
+ ary2000.max: ary2000.max
+ ary3000.max: ary3000.max
+ ary5000.max: ary5000.max
+ ary10000.max: ary10000.max
+ ary20000.max: ary20000.max
+ ary50000.max: ary50000.max
+ ary100000.max: ary100000.max
+
+loop_count: 10000
+
diff --git a/benchmark/array_max_int.yml b/benchmark/array_max_int.yml
new file mode 100644
index 0000000000..acd83684d0
--- /dev/null
+++ b/benchmark/array_max_int.yml
@@ -0,0 +1,31 @@
+prelude: |
+ ary2 = 2.times.to_a.shuffle
+ ary10 = 10.times.to_a.shuffle
+ ary100 = 100.times.to_a.shuffle
+ ary500 = 500.times.to_a.shuffle
+ ary1000 = 1000.times.to_a.shuffle
+ ary2000 = 2500.times.to_a.shuffle
+ ary3000 = 2500.times.to_a.shuffle
+ ary5000 = 5000.times.to_a.shuffle
+ ary10000 = 10000.times.to_a.shuffle
+ ary20000 = 20000.times.to_a.shuffle
+ ary50000 = 50000.times.to_a.shuffle
+ ary100000 = 100000.times.to_a.shuffle
+ ary1000000 = 1000000.times.to_a.shuffle
+
+benchmark:
+ ary2.max: ary2.max
+ ary10.max: ary10.max
+ ary100.max: ary100.max
+ ary500.max: ary500.max
+ ary1000.max: ary1000.max
+ ary2000.max: ary2000.max
+ ary3000.max: ary3000.max
+ ary5000.max: ary5000.max
+ ary10000.max: ary10000.max
+ ary20000.max: ary20000.max
+ ary50000.max: ary50000.max
+ ary100000.max: ary100000.max
+ ary1000000.max: ary1000000.max
+
+loop_count: 10000
diff --git a/benchmark/array_max_str.yml b/benchmark/array_max_str.yml
new file mode 100644
index 0000000000..2aeed010f2
--- /dev/null
+++ b/benchmark/array_max_str.yml
@@ -0,0 +1,30 @@
+prelude: |
+ ary2 = 2.times.map(&:to_s).shuffle
+ ary10 = 10.times.map(&:to_s).shuffle
+ ary100 = 100.times.map(&:to_s).shuffle
+ ary500 = 500.times.map(&:to_s).shuffle
+ ary1000 = 1000.times.map(&:to_s).shuffle
+ ary2000 = 2500.times.map(&:to_s).shuffle
+ ary3000 = 2500.times.map(&:to_s).shuffle
+ ary5000 = 5000.times.map(&:to_s).shuffle
+ ary10000 = 10000.times.map(&:to_s).shuffle
+ ary20000 = 20000.times.map(&:to_s).shuffle
+ ary50000 = 50000.times.map(&:to_s).shuffle
+ ary100000 = 100000.times.map(&:to_s).shuffle
+
+benchmark:
+ ary2.max: ary2.max
+ ary10.max: ary10.max
+ ary100.max: ary100.max
+ ary500.max: ary500.max
+ ary1000.max: ary1000.max
+ ary2000.max: ary2000.max
+ ary3000.max: ary3000.max
+ ary5000.max: ary5000.max
+ ary10000.max: ary10000.max
+ ary20000.max: ary20000.max
+ ary50000.max: ary50000.max
+ ary100000.max: ary100000.max
+
+loop_count: 10000
+
diff --git a/benchmark/array_min.yml b/benchmark/array_min.yml
new file mode 100644
index 0000000000..53e5072b14
--- /dev/null
+++ b/benchmark/array_min.yml
@@ -0,0 +1,31 @@
+prelude: |
+ ary2 = 2.times.to_a.shuffle
+ ary10 = 10.times.to_a.shuffle
+ ary100 = 100.times.to_a.shuffle
+ ary500 = 500.times.to_a.shuffle
+ ary1000 = 1000.times.to_a.shuffle
+ ary2000 = 2500.times.to_a.shuffle
+ ary3000 = 2500.times.to_a.shuffle
+ ary5000 = 5000.times.to_a.shuffle
+ ary10000 = 10000.times.to_a.shuffle
+ ary20000 = 20000.times.to_a.shuffle
+ ary50000 = 50000.times.to_a.shuffle
+ ary100000 = 100000.times.to_a.shuffle
+ ary1000000 = 1000000.times.to_a.shuffle
+
+benchmark:
+ ary2.min: ary2.min
+ ary10.min: ary10.min
+ ary100.min: ary100.min
+ ary500.min: ary500.min
+ ary1000.min: ary1000.min
+ ary2000.min: ary2000.min
+ ary3000.min: ary3000.min
+ ary5000.min: ary5000.min
+ ary10000.min: ary10000.min
+ ary20000.min: ary20000.min
+ ary50000.min: ary50000.min
+ ary100000.min: ary100000.min
+ ary1000000.min: ary1000000.min
+
+loop_count: 10000
diff --git a/benchmark/enum_lazy_flat_map.yml b/benchmark/enum_lazy_flat_map.yml
new file mode 100644
index 0000000000..0ee390a441
--- /dev/null
+++ b/benchmark/enum_lazy_flat_map.yml
@@ -0,0 +1,16 @@
+prelude: |
+ num = (1..).lazy.take(100)
+ ary2 = [[1,2]].cycle.lazy.take(10)
+ ary10 = [[*1..10]].cycle.lazy.take(10)
+ ary20 = [[*1..20]].cycle.lazy.take(10)
+ ary50 = [[*1..50]].cycle.lazy.take(10)
+ ary100 = [[*1..100]].cycle.lazy.take(10)
+
+benchmark:
+ num3: num.flat_map {|x| x}.take(3).to_a
+ num10: num.flat_map {|x| x}.take(3).to_a
+ ary2: ary2.flat_map {|x| x}.take(3).to_a
+ ary10: ary10.flat_map {|x| x}.take(3).to_a
+ ary20: ary20.flat_map {|x| x}.take(3).to_a
+ ary50: ary50.flat_map {|x| x}.take(3).to_a
+ ary100: ary100.flat_map {|x| x}.take(3).to_a
diff --git a/benchmark/enum_lazy_zip.yml b/benchmark/enum_lazy_zip.yml
new file mode 100644
index 0000000000..4566ff0261
--- /dev/null
+++ b/benchmark/enum_lazy_zip.yml
@@ -0,0 +1,22 @@
+prelude: |
+ a = (1..3).lazy
+ b = a.map {|x| x}
+
+benchmark:
+ first_ary: a.zip(["a", "b", "c"]).first
+ first_nonary: a.zip("a".."c").first
+ first_noarg: a.zip.first
+
+ take3_ary: a.zip(["a", "b", "c"]).take(3).force
+ take3_nonary: a.zip("a".."c").take(3).force
+ take3_noarg: a.zip.take(3).force
+
+ chain-first_ary: b.zip(["a", "b", "c"]).first
+ chain-first_nonary: b.zip("a".."c").first
+ chain-first_noarg: b.zip.first
+
+ chain-take3_ary: b.zip(["a", "b", "c"]).take(3).force
+ chain-take3_nonary: b.zip("a".."c").take(3).force
+ chain-take3_noarg: b.zip.take(3).force
+
+ block: a.zip("a".."c") {|x, y| [x, y]}
diff --git a/benchmark/fiber_chain.yml b/benchmark/fiber_chain.yml
index a36c759f8e..a36c759f8e 100755..100644
--- a/benchmark/fiber_chain.yml
+++ b/benchmark/fiber_chain.yml
diff --git a/benchmark/fiber_locals.yml b/benchmark/fiber_locals.yml
new file mode 100644
index 0000000000..8588686477
--- /dev/null
+++ b/benchmark/fiber_locals.yml
@@ -0,0 +1,8 @@
+prelude: |
+ th = Thread.current
+ th[:key] = :val
+benchmark:
+ key?: th.key?(:key)
+ []: th[:key]
+ keys: th.keys
+loop_count: 1_000_000
diff --git a/benchmark/hash_defaults.yml b/benchmark/hash_defaults.yml
new file mode 100644
index 0000000000..833f10e1c7
--- /dev/null
+++ b/benchmark/hash_defaults.yml
@@ -0,0 +1,6 @@
+prelude: |
+ h = Hash.new { :foo }
+benchmark:
+ default_aref: h[1]
+ default_method: h.default(1)
+loop_count: 1000000
diff --git a/benchmark/kernel_clone.yml b/benchmark/kernel_clone.yml
new file mode 100644
index 0000000000..069b23abcd
--- /dev/null
+++ b/benchmark/kernel_clone.yml
@@ -0,0 +1,6 @@
+prelude: "object = Object.new"
+benchmark:
+ clone: "object.clone"
+ clone_true: "object.clone(freeze: true)"
+ clone_false: "object.clone(freeze: false)"
+loop_count: 10000
diff --git a/benchmark/kernel_float.yml b/benchmark/kernel_float.yml
new file mode 100644
index 0000000000..215f6750fc
--- /dev/null
+++ b/benchmark/kernel_float.yml
@@ -0,0 +1,5 @@
+benchmark:
+ float: "Float(42)"
+ float_true: "Float(42, exception: true)"
+ float_false: "Float(42, exception: false)"
+loop_count: 10000
diff --git a/benchmark/kernel_tap.yml b/benchmark/kernel_tap.yml
new file mode 100644
index 0000000000..4dcbb31b4d
--- /dev/null
+++ b/benchmark/kernel_tap.yml
@@ -0,0 +1,6 @@
+prelude: |
+ obj = Object.new
+ x = nil
+benchmark:
+ kernel_tap: obj.tap { |o| x = o }
+loop_count: 20000000
diff --git a/benchmark/kernel_then.yml b/benchmark/kernel_then.yml
new file mode 100644
index 0000000000..85f7341e33
--- /dev/null
+++ b/benchmark/kernel_then.yml
@@ -0,0 +1,6 @@
+benchmark:
+ kernel_then: 1.then { |i| i + 1 }
+ kernel_then_enum: 1.then
+ kernel_yield_self: 1.yield_self { |i| i + 1 }
+ kernel_yield_self_enum: 1.yield_self
+loop_count: 20000000
diff --git a/benchmark/keyword_arguments.yml b/benchmark/keyword_arguments.yml
new file mode 100644
index 0000000000..fce6bce0b8
--- /dev/null
+++ b/benchmark/keyword_arguments.yml
@@ -0,0 +1,13 @@
+prelude: |
+ h = {a: 1}
+ def kw(a: 1) a end
+ def kws(**kw) kw end
+benchmark:
+ kw_to_kw: "kw(a: 1)"
+ kw_splat_to_kw: "kw(**h)"
+ kw_to_kw_splat: "kws(a: 1)"
+ kw_splat_to_kw_splat: "kws(**h)"
+ kw_and_splat_to_kw: "kw(a: 1, **h)"
+ kw_splats_to_kw: "kw(**h, **h)"
+ kw_and_splat_to_kw_splat: "kws(a: 1, **h)"
+ kw_splats_to_kw_splat: "kws(**h, **h)"
diff --git a/benchmark/lib/benchmark_driver/runner/mjit.rb b/benchmark/lib/benchmark_driver/runner/mjit.rb
new file mode 100644
index 0000000000..1d4693e8be
--- /dev/null
+++ b/benchmark/lib/benchmark_driver/runner/mjit.rb
@@ -0,0 +1,34 @@
+require 'benchmark_driver/struct'
+require 'benchmark_driver/metric'
+require 'erb'
+
+# A runner to measure after-JIT performance easily
+class BenchmarkDriver::Runner::Mjit < BenchmarkDriver::Runner::Ips
+ # JobParser returns this, `BenchmarkDriver::Runner.runner_for` searches "*::Job"
+ Job = Class.new(BenchmarkDriver::DefaultJob)
+
+ # Dynamically fetched and used by `BenchmarkDriver::JobParser.parse`
+ JobParser = BenchmarkDriver::DefaultJobParser.for(klass: Job, metrics: [METRIC]).extend(Module.new{
+ def parse(**)
+ jobs = super
+ jobs.map do |job|
+ job = job.dup
+ job.prelude = "#{job.prelude}\n#{<<~EOS}"
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
+ __bmdv_ruby_i = 0
+ while __bmdv_ruby_i < 10000 # jit_min_calls
+ #{job.script}
+ __bmdv_ruby_i += 1
+ end
+ RubyVM::MJIT.pause # compile
+ #{job.script}
+ RubyVM::MJIT.resume; RubyVM::MJIT.pause # recompile
+ #{job.script}
+ RubyVM::MJIT.resume; RubyVM::MJIT.pause # recompile 2
+ end
+ EOS
+ job
+ end
+ end
+ })
+end
diff --git a/benchmark/lib/benchmark_driver/runner/mjit_exec.rb b/benchmark/lib/benchmark_driver/runner/mjit_exec.rb
index 9f7c8c8af3..eac3dfba84 100644
--- a/benchmark/lib/benchmark_driver/runner/mjit_exec.rb
+++ b/benchmark/lib/benchmark_driver/runner/mjit_exec.rb
@@ -135,7 +135,7 @@ class BenchmarkDriver::Runner::MjitExec
nil
end
% end
- RubyVM::MJIT.pause if RubyVM::MJIT.enabled?
+ RubyVM::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
def vm
t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
@@ -172,7 +172,7 @@ class BenchmarkDriver::Runner::MjitExec
a<%= i %>
a<%= i %> # --jit-min-calls=2
% end
- RubyVM::MJIT.pause if RubyVM::MJIT.enabled?
+ RubyVM::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
def vm
t = Process.clock_gettime(Process::CLOCK_MONOTONIC)
@@ -228,7 +228,7 @@ class BenchmarkDriver::Runner::MjitExec
jit
jit
- RubyVM::MJIT.pause if RubyVM::MJIT.enabled?
+ RubyVM::MJIT.pause if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
File.write(<%= result.dump %>, jit)
EOS
end
diff --git a/benchmark/mjit_exec_jt2jt.yml b/benchmark/mjit_exec_jt2jt.yml
index 5be408e30c..6c303c7a44 100644
--- a/benchmark/mjit_exec_jt2jt.yml
+++ b/benchmark/mjit_exec_jt2jt.yml
@@ -1,6 +1,4 @@
-# Usage:
-# RUBYOPT=-Ibenchmark/lib benchmark-driver -e 'ruby --jit' benchmark/mjit_exec_vm2jt.yml
-type: mjit_exec # benchmark/lib/benchmark_driver/runner/mjit_exec.rb
+type: lib/benchmark_driver/runner/mjit_exec
num_methods: [1]
#num_methods: (1..100).to_a + [200, 300, 400, 500, 600, 700, 800, 900, 1000]
loop_count: 50000000
diff --git a/benchmark/mjit_exec_vm2jt.yml b/benchmark/mjit_exec_vm2jt.yml
index 9947dbb7dd..764883f070 100644
--- a/benchmark/mjit_exec_vm2jt.yml
+++ b/benchmark/mjit_exec_vm2jt.yml
@@ -1,6 +1,4 @@
-# Usage:
-# RUBYOPT=-Ibenchmark/lib benchmark-driver -e 'ruby --jit' benchmark/mjit_exec_vm2jt.yml
-type: mjit_exec # benchmark/lib/benchmark_driver/runner/mjit_exec.rb
+type: lib/benchmark_driver/runner/mjit_exec
num_methods: [1]
#num_methods: (1..100).to_a + [200, 300, 400, 500, 600, 700, 800, 900, 1000]
loop_count: 50000000
diff --git a/benchmark/mjit_exec_vm2vm.yml b/benchmark/mjit_exec_vm2vm.yml
index 4b84427b10..030aa76c1c 100644
--- a/benchmark/mjit_exec_vm2vm.yml
+++ b/benchmark/mjit_exec_vm2vm.yml
@@ -1,6 +1,4 @@
-# Usage:
-# RUBYOPT=-Ibenchmark/lib benchmark-driver -e 'ruby --jit' benchmark/mjit_exec_vm2vm.yml
-type: mjit_exec # benchmark/lib/benchmark_driver/runner/mjit_exec.rb
+type: lib/benchmark_driver/runner/mjit_exec
num_methods: [1]
#num_methods: (1..100).to_a + [200, 300, 400, 500, 600, 700, 800, 900, 1000]
loop_count: 50000000
diff --git a/benchmark/mjit_exivar.yml b/benchmark/mjit_exivar.yml
new file mode 100644
index 0000000000..2584fa6410
--- /dev/null
+++ b/benchmark/mjit_exivar.yml
@@ -0,0 +1,18 @@
+type: lib/benchmark_driver/runner/mjit
+prelude: |
+ class Bench < Hash
+ def initialize
+ @exivar = nil
+ end
+
+ def exivar
+ @exivar
+ end
+ end
+
+ bench = Bench.new
+
+benchmark:
+ mjit_exivar: bench.exivar
+
+loop_count: 200000000
diff --git a/benchmark/mjit_integer.yml b/benchmark/mjit_integer.yml
new file mode 100644
index 0000000000..edc3556479
--- /dev/null
+++ b/benchmark/mjit_integer.yml
@@ -0,0 +1,30 @@
+type: lib/benchmark_driver/runner/mjit
+prelude: |
+ def mjit_abs(int) int.abs end
+ def mjit_bit_length(int) int.bit_length end
+ def mjit_comp(int) ~int end
+ def mjit_even?(int) int.even? end
+ def mjit_integer?(int) int.integer? end
+ def mjit_magnitude(int) int.magnitude end
+ def mjit_odd?(int) int.odd? end
+ def mjit_ord(int) int.ord end
+ def mjit_to_i(int) int.to_i end
+ def mjit_to_int(int) int.to_int end
+ def mjit_uminus(int) -int end
+ def mjit_zero?(int) int.zero? end
+
+benchmark:
+ - mjit_abs(-1)
+ - mjit_bit_length(100)
+ - mjit_comp(1)
+ - mjit_even?(2)
+ - mjit_integer?(0)
+ - mjit_magnitude(-1)
+ - mjit_odd?(1)
+ - mjit_ord(1)
+ - mjit_to_i(1)
+ - mjit_to_int(1)
+ - mjit_uminus(1)
+ - mjit_zero?(0)
+
+loop_count: 40000000
diff --git a/benchmark/mjit_kernel.yml b/benchmark/mjit_kernel.yml
new file mode 100644
index 0000000000..7720e65c2c
--- /dev/null
+++ b/benchmark/mjit_kernel.yml
@@ -0,0 +1,20 @@
+type: lib/benchmark_driver/runner/mjit
+prelude: |
+ def mjit_class(obj)
+ obj.class
+ end
+
+ def mjit_frozen?(obj)
+ obj.frozen?
+ end
+
+ str = ""
+ fstr = "".freeze
+
+benchmark:
+ - mjit_class(self)
+ - mjit_class(1)
+ - mjit_frozen?(str)
+ - mjit_frozen?(fstr)
+
+loop_count: 40000000
diff --git a/benchmark/mjit_leave.yml b/benchmark/mjit_leave.yml
new file mode 100644
index 0000000000..9ac68b164b
--- /dev/null
+++ b/benchmark/mjit_leave.yml
@@ -0,0 +1,8 @@
+type: lib/benchmark_driver/runner/mjit
+prelude: |
+ def leave
+ nil
+ end
+benchmark:
+ mjit_leave: leave
+loop_count: 200000000
diff --git a/benchmark/mjit_opt_cc_insns.yml b/benchmark/mjit_opt_cc_insns.yml
new file mode 100644
index 0000000000..fed6d34bd5
--- /dev/null
+++ b/benchmark/mjit_opt_cc_insns.yml
@@ -0,0 +1,27 @@
+# opt_* insns using vm_method_cfunc_is with send-compatible operands:
+# * opt_nil_p
+# * opt_not
+# * opt_eq
+type: lib/benchmark_driver/runner/mjit
+prelude: |
+ def mjit_nil?(obj)
+ obj.nil?
+ end
+
+ def mjit_not(obj)
+ !obj
+ end
+
+ def mjit_eq(a, b)
+ a == b
+ end
+
+benchmark:
+ - script: mjit_nil?(1)
+ loop_count: 40000000
+ - script: mjit_not(1)
+ loop_count: 40000000
+ - script: mjit_eq(1, nil)
+ loop_count: 8000000
+ - script: mjit_eq(nil, 1)
+ loop_count: 8000000
diff --git a/benchmark/mjit_struct_aref.yml b/benchmark/mjit_struct_aref.yml
new file mode 100644
index 0000000000..bfba1323f2
--- /dev/null
+++ b/benchmark/mjit_struct_aref.yml
@@ -0,0 +1,10 @@
+type: lib/benchmark_driver/runner/mjit
+prelude: |
+ def mjit_struct_aref(struct)
+ struct.aa
+ end
+ struct = Struct.new(:a0, :a1, :a2, :a3, :a4, :a5, :a6, :a7, :a8, :a9, :aa).new
+
+benchmark: mjit_struct_aref(struct)
+
+loop_count: 40000000
diff --git a/benchmark/num_zero_p.yml b/benchmark/num_zero_p.yml
new file mode 100644
index 0000000000..2195963433
--- /dev/null
+++ b/benchmark/num_zero_p.yml
@@ -0,0 +1,8 @@
+benchmark:
+ - 0.zero?
+ - 1.zero?
+ - 0r.zero?
+ - 1r.zero?
+ - 0i.zero?
+ - 1i.zero?
+loop_count: 50000000
diff --git a/benchmark/object_allocate.yml b/benchmark/object_allocate.yml
new file mode 100644
index 0000000000..93ff463e41
--- /dev/null
+++ b/benchmark/object_allocate.yml
@@ -0,0 +1,21 @@
+prelude: |
+ class Eight
+ 8.times { include(Module.new) }
+ end
+ class ThirtyTwo
+ 32.times { include(Module.new) }
+ end
+ class SixtyFour
+ 64.times { include(Module.new) }
+ end
+ class OneTwentyEight
+ 128.times { include(Module.new) }
+ end
+ # Disable GC to see raw throughput:
+ GC.disable
+benchmark:
+ allocate_8_deep: Eight.new
+ allocate_32_deep: ThirtyTwo.new
+ allocate_64_deep: SixtyFour.new
+ allocate_128_deep: OneTwentyEight.new
+loop_count: 100000
diff --git a/benchmark/objspace_dump_all.yml b/benchmark/objspace_dump_all.yml
new file mode 100644
index 0000000000..ebab562d2e
--- /dev/null
+++ b/benchmark/objspace_dump_all.yml
@@ -0,0 +1,13 @@
+prelude: |
+ require 'objspace'
+ require 'tempfile'
+ $objs = 1_000.times.map { Object.new }
+ $strings = 1_000.times.map { |i| "string #{i}" }
+ $file = Tempfile.new('heap')
+ $dev_null = File.open(File::NULL, 'w+')
+
+benchmark:
+ dump_all_string: "ObjectSpace.dump_all(output: :string)"
+ dump_all_file: "ObjectSpace.dump_all(output: $file)"
+ dump_all_dev_null: "ObjectSpace.dump_all(output: $dev_null)"
+loop_count: 1
diff --git a/benchmark/pm_array.yml b/benchmark/pm_array.yml
new file mode 100644
index 0000000000..babb65a289
--- /dev/null
+++ b/benchmark/pm_array.yml
@@ -0,0 +1,19 @@
+prelude: |
+ def call(*val)
+ case val
+ in [String => body]
+ [200, {}, [body]]
+ in [Integer => status]
+ [status, {}, [""]]
+ in [Integer, String] => response
+ [response[0], {}, [response[1]]]
+ in [Integer, Hash, String] => response
+ [response[0], response[1], [response[2]]]
+ end
+ end
+
+benchmark:
+ first_match: call("ok")
+ second_match: call(401)
+ third_match: call(200, "ok")
+ fourth_match: call(201, {}, "created")
diff --git a/benchmark/string_casecmp.yml b/benchmark/string_casecmp.yml
new file mode 100644
index 0000000000..2354040a04
--- /dev/null
+++ b/benchmark/string_casecmp.yml
@@ -0,0 +1,26 @@
+prelude: |
+ lstr1 = [*"a".."z",*"0".."9"].join("")
+ lstr10 = lstr1 * 10
+ lstr100 = lstr10 * 10
+ lstr1000 = lstr100 * 10
+ lnonascii1 = [*"\u{e0}".."\u{ff}"].join("")
+ lnonascii10 = lnonascii1 * 10
+ lnonascii100 = lnonascii10 * 10
+ lnonascii1000 = lnonascii100 * 10
+ ustr1 = [*"A".."Z",*"0".."9"].join("")
+ ustr10 = ustr1 * 10
+ ustr100 = ustr10 * 10
+ ustr1000 = ustr100 * 10
+ unonascii1 = [*"\u{c0}".."\u{df}"].join("")
+ unonascii10 = unonascii1 * 10
+ unonascii100 = unonascii10 * 10
+ unonascii1000 = unonascii100 * 10
+benchmark:
+ casecmp-1: lstr1.casecmp(ustr1)
+ casecmp-10: lstr10.casecmp(ustr10)
+ casecmp-100: lstr100.casecmp(ustr100)
+ casecmp-1000: lstr1000.casecmp(ustr1000)
+ casecmp-nonascii1: lnonascii1.casecmp(unonascii1)
+ casecmp-nonascii10: lnonascii10.casecmp(unonascii10)
+ casecmp-nonascii100: lnonascii100.casecmp(unonascii100)
+ casecmp-nonascii1000: lnonascii1000.casecmp(unonascii1000)
diff --git a/benchmark/string_casecmp_p.yml b/benchmark/string_casecmp_p.yml
new file mode 100644
index 0000000000..a790ce7d55
--- /dev/null
+++ b/benchmark/string_casecmp_p.yml
@@ -0,0 +1,26 @@
+prelude: |
+ lstr1 = [*"a".."z",*"0".."9"].join("")
+ lstr10 = lstr1 * 10
+ lstr100 = lstr10 * 10
+ lstr1000 = lstr100 * 10
+ lnonascii1 = [*"\u{e0}".."\u{ff}"].join("")
+ lnonascii10 = lnonascii1 * 10
+ lnonascii100 = lnonascii10 * 10
+ lnonascii1000 = lnonascii100 * 10
+ ustr1 = [*"A".."Z",*"0".."9"].join("")
+ ustr10 = ustr1 * 10
+ ustr100 = ustr10 * 10
+ ustr1000 = ustr100 * 10
+ unonascii1 = [*"\u{c0}".."\u{df}"].join("")
+ unonascii10 = unonascii1 * 10
+ unonascii100 = unonascii10 * 10
+ unonascii1000 = unonascii100 * 10
+benchmark:
+ casecmp_p-1: lstr1.casecmp?(ustr1)
+ casecmp_p-10: lstr10.casecmp?(ustr10)
+ casecmp_p-100: lstr100.casecmp?(ustr100)
+ casecmp_p-1000: lstr1000.casecmp?(ustr1000)
+ casecmp_p-nonascii1: lnonascii1.casecmp?(unonascii1)
+ casecmp_p-nonascii10: lnonascii10.casecmp?(unonascii10)
+ casecmp_p-nonascii100: lnonascii100.casecmp?(unonascii100)
+ casecmp_p-nonascii1000: lnonascii1000.casecmp?(unonascii1000)
diff --git a/benchmark/string_downcase.yml b/benchmark/string_downcase.yml
index a31c3ac712..1fea6afbec 100644
--- a/benchmark/string_downcase.yml
+++ b/benchmark/string_downcase.yml
@@ -3,8 +3,16 @@ prelude: |
str10 = str1 * 10
str100 = str10 * 10
str1000 = str100 * 10
+ nonascii1 = [*"\u{c0}".."\u{df}"].join("")
+ nonascii10 = nonascii1 * 10
+ nonascii100 = nonascii10 * 10
+ nonascii1000 = nonascii100 * 10
benchmark:
downcase-1: str1.upcase
downcase-10: str10.upcase
downcase-100: str100.upcase
downcase-1000: str1000.upcase
+ downcase-nonascii1: nonascii1.downcase
+ downcase-nonascii10: nonascii10.downcase
+ downcase-nonascii100: nonascii100.downcase
+ downcase-nonascii1000: nonascii1000.downcase
diff --git a/benchmark/string_slice.yml b/benchmark/string_slice.yml
new file mode 100644
index 0000000000..fc2393c5d1
--- /dev/null
+++ b/benchmark/string_slice.yml
@@ -0,0 +1,11 @@
+prelude: |
+ long_string = "x"*1000+"-hår"
+benchmark:
+ regexp-short: |
+ "x-hår".slice!(/-(.)(.)(.)/, 3)
+ regexp-long: |
+ long_string.dup.slice!(/-(.)(.)(.)/, 3)
+ string-short: |
+ "x-hår".slice!("r")
+ string-long: |
+ long_string.dup.slice!("r")
diff --git a/benchmark/string_split.yml b/benchmark/string_split.yml
index 84ffe8f6a7..cc2c7d7855 100644
--- a/benchmark/string_split.yml
+++ b/benchmark/string_split.yml
@@ -1,7 +1,22 @@
prelude: |
- str0 = [*0..9].join("")
+ str1 = [*0..5].join(" ") + " "
+ str10 = str1 * 10
+ str100 = str10 * 10
+ str1000 = str100 * 10
benchmark:
- to_chars-1: str0.split('')
- to_chars-10: (str0 * 10).split('')
- to_chars-100: (str0 * 100).split('')
- to_chars-1000: (str0 * 1000).split('')
+ to_chars-1: str1.split('')
+ to_chars-10: str10.split('')
+ to_chars-100: str100.split('')
+ to_chars-1000: str1000.split('')
+ to_words-1: str1.split(' ')
+ to_words-10: str10.split(' ')
+ to_words-100: str100.split(' ')
+ to_words-1000: str1000.split(' ')
+ re_chars-1: str1.split(//)
+ re_chars-10: str10.split(//)
+ re_chars-100: str100.split(//)
+ re_chars-1000: str1000.split(//)
+ re_space-1: str1.split(/ /)
+ re_space-10: str10.split(/ /)
+ re_space-100: str100.split(/ /)
+ re_space-1000: str1000.split(/ /)
diff --git a/benchmark/string_swapcase.yml b/benchmark/string_swapcase.yml
index afaae3f696..eeb5928907 100644
--- a/benchmark/string_swapcase.yml
+++ b/benchmark/string_swapcase.yml
@@ -3,8 +3,16 @@ prelude: |
str10 = str1 * 10
str100 = str10 * 10
str1000 = str100 * 10
+ nonascii1 = [*"\u{c0}".."\u{cf}",*"\u{f0}".."\u{ff}"].join("")
+ nonascii10 = nonascii1 * 10
+ nonascii100 = nonascii10 * 10
+ nonascii1000 = nonascii100 * 10
benchmark:
swapcase-1: str1.swapcase
swapcase-10: str10.swapcase
swapcase-100: str100.swapcase
swapcase-1000: str1000.swapcase
+ swapcase-nonascii1: nonascii1.swapcase
+ swapcase-nonascii10: nonascii10.swapcase
+ swapcase-nonascii100: nonascii100.swapcase
+ swapcase-nonascii1000: nonascii1000.swapcase
diff --git a/benchmark/string_upcase.yml b/benchmark/string_upcase.yml
index 456d213c74..dab84bbde2 100644
--- a/benchmark/string_upcase.yml
+++ b/benchmark/string_upcase.yml
@@ -3,8 +3,16 @@ prelude: |
str10 = str1 * 10
str100 = str10 * 10
str1000 = str100 * 10
+ nonascii1 = [*"\u{e0}".."\u{ff}"].join("")
+ nonascii10 = nonascii1 * 10
+ nonascii100 = nonascii10 * 10
+ nonascii1000 = nonascii100 * 10
benchmark:
upcase-1: str1.upcase
upcase-10: str10.upcase
upcase-100: str100.upcase
upcase-1000: str1000.upcase
+ upcase-nonascii1: nonascii1.upcase
+ upcase-nonascii10: nonascii10.upcase
+ upcase-nonascii100: nonascii100.upcase
+ upcase-nonascii1000: nonascii1000.upcase
diff --git a/benchmark/vm1_attr_ivar.yml b/benchmark/vm1_attr_ivar.yml
deleted file mode 100644
index f714dd9bd9..0000000000
--- a/benchmark/vm1_attr_ivar.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-prelude: |
- class C
- attr_reader :a, :b
- def initialize
- @a = nil
- @b = nil
- end
- end
- obj = C.new
-benchmark:
- vm1_attr_ivar: |
- j = obj.a
- k = obj.b
-loop_count: 30000000
diff --git a/benchmark/vm1_attr_ivar_set.yml b/benchmark/vm1_attr_ivar_set.yml
deleted file mode 100644
index f383e59ef4..0000000000
--- a/benchmark/vm1_attr_ivar_set.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-prelude: |
- class C
- attr_accessor :a, :b
- def initialize
- @a = nil
- @b = nil
- end
- end
- obj = C.new
-benchmark:
- vm1_attr_ivar_set: |
- obj.a = 1
- obj.b = 2
-loop_count: 30000000
diff --git a/benchmark/vm1_block.yml b/benchmark/vm1_block.yml
deleted file mode 100644
index ac7c940f93..0000000000
--- a/benchmark/vm1_block.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-prelude: |
- def m
- yield
- end
-benchmark:
- vm1_block: |
- m{
- }
-loop_count: 30000000
diff --git a/benchmark/vm1_blockparam.yml b/benchmark/vm1_blockparam.yml
deleted file mode 100644
index 947b8c53d5..0000000000
--- a/benchmark/vm1_blockparam.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- def m &b
- end
-benchmark:
- vm1_blockparam: |
- m{}
-loop_count: 30000000
diff --git a/benchmark/vm1_blockparam_call.yml b/benchmark/vm1_blockparam_call.yml
deleted file mode 100644
index e2817a3ce2..0000000000
--- a/benchmark/vm1_blockparam_call.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- def m &b
- b.call
- end
-benchmark:
- vm1_blockparam_call: |
- m{}
-loop_count: 30000000
diff --git a/benchmark/vm1_blockparam_pass.yml b/benchmark/vm1_blockparam_pass.yml
deleted file mode 100644
index ca1bef3369..0000000000
--- a/benchmark/vm1_blockparam_pass.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-prelude: |
- def bp_yield
- yield
- end
-
- def bp_pass &b
- bp_yield &b
- end
-benchmark:
- vm1_blockparam_pass: |
- bp_pass{}
-loop_count: 30000000
diff --git a/benchmark/vm1_blockparam_yield.yml b/benchmark/vm1_blockparam_yield.yml
deleted file mode 100644
index 56ae617798..0000000000
--- a/benchmark/vm1_blockparam_yield.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- def bp_yield &b
- yield
- end
-benchmark:
- vm1_blockparam_yield: |
- bp_yield{}
-loop_count: 30000000
diff --git a/benchmark/vm1_const.yml b/benchmark/vm1_const.yml
deleted file mode 100644
index b98db1545c..0000000000
--- a/benchmark/vm1_const.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- Const = 1
-benchmark:
- vm1_const: |
- j = Const
- k = Const
-loop_count: 30000000
diff --git a/benchmark/vm1_ensure.yml b/benchmark/vm1_ensure.yml
deleted file mode 100644
index afbbe38bec..0000000000
--- a/benchmark/vm1_ensure.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-# Not utilizing loop_count since using it for this is too unstable for now
-benchmark:
- vm1_ensure: |
- i = 0
- while i<30_000_000
- i += 1
- begin
- begin
- ensure
- end
- ensure
- end
- end
-loop_count: 1
diff --git a/benchmark/vm1_float_simple.yml b/benchmark/vm1_float_simple.yml
deleted file mode 100644
index 4e9ad1852b..0000000000
--- a/benchmark/vm1_float_simple.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- f = 0.0
-benchmark:
- vm1_float_simple: |
- f += 0.1; f -= 0.1
- f += 0.1; f -= 0.1
- f += 0.1; f -= 0.1
-loop_count: 30000000
diff --git a/benchmark/vm1_gc_short_lived.yml b/benchmark/vm1_gc_short_lived.yml
deleted file mode 100644
index 8fdcb7371d..0000000000
--- a/benchmark/vm1_gc_short_lived.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-benchmark:
- vm1_gc_short_lived: |
- a = '' # short-lived String
- b = ''
- c = ''
- d = ''
- e = ''
- f = ''
-loop_count: 30000000
diff --git a/benchmark/vm1_gc_short_with_complex_long.yml b/benchmark/vm1_gc_short_with_complex_long.yml
deleted file mode 100644
index c22ea74a60..0000000000
--- a/benchmark/vm1_gc_short_with_complex_long.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-prelude: |
- def nested_hash h, n
- if n == 0
- ''
- else
- 10.times{
- h[Object.new] = nested_hash(h, n-1)
- }
- end
- end
-
- long_lived = Hash.new
- nested_hash long_lived, 6
-
- GC.start
- GC.start
-benchmark:
- vm1_gc_short_with_complex_long: |
- a = '' # short-lived String
- b = ''
- c = ''
- d = ''
- e = ''
- f = ''
-loop_count: 30000000
diff --git a/benchmark/vm1_gc_short_with_long.yml b/benchmark/vm1_gc_short_with_long.yml
deleted file mode 100644
index c731aae548..0000000000
--- a/benchmark/vm1_gc_short_with_long.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-prelude: |
- long_lived = Array.new(1_000_000){|i| "#{i}"}
- GC.start
- GC.start
-benchmark:
- vm1_gc_short_with_long: |
- a = '' # short-lived String
- b = ''
- c = ''
- d = ''
- e = ''
- f = ''
-loop_count: 30000000
diff --git a/benchmark/vm1_gc_short_with_symbol.yml b/benchmark/vm1_gc_short_with_symbol.yml
deleted file mode 100644
index 7fc1abedd8..0000000000
--- a/benchmark/vm1_gc_short_with_symbol.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-prelude: |
- 50_000.times{|i| sym = "sym#{i}".to_sym}
- GC.start
- GC.start
-benchmark:
- vm1_gc_short_with_symbol: |
- a = '' # short-lived String
- b = ''
- c = ''
- d = ''
- e = ''
- f = ''
-loop_count: 30000000
diff --git a/benchmark/vm1_gc_wb_ary.yml b/benchmark/vm1_gc_wb_ary.yml
deleted file mode 100644
index 50fb4b6f84..0000000000
--- a/benchmark/vm1_gc_wb_ary.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-prelude: |
- short_lived_ary = []
-
- if RUBY_VERSION >= "2.2.0"
- GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true)
- end
-
- short_lived = ''
-benchmark:
- vm1_gc_wb_ary: |
- short_lived_ary[0] = short_lived # write barrier
-loop_count: 30000000
diff --git a/benchmark/vm1_gc_wb_ary_promoted.yml b/benchmark/vm1_gc_wb_ary_promoted.yml
deleted file mode 100644
index cf9b5de005..0000000000
--- a/benchmark/vm1_gc_wb_ary_promoted.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-prelude: |
- long_lived = []
-
- if RUBY_VERSION > "2.2.0"
- 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) }
- elsif
- GC.start
- end
-
- short_lived = ''
-
-benchmark:
- vm1_gc_wb_ary_promoted: |
- long_lived[0] = short_lived # write barrier
-loop_count: 30000000
diff --git a/benchmark/vm1_gc_wb_obj.yml b/benchmark/vm1_gc_wb_obj.yml
deleted file mode 100644
index 9dc08e7e1a..0000000000
--- a/benchmark/vm1_gc_wb_obj.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-prelude: |
- class C
- attr_accessor :foo
- end
- short_lived_obj = C.new
-
- if RUBY_VERSION >= "2.2.0"
- GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true)
- end
-
- short_lived = ''
-benchmark:
- vm1_gc_wb_obj: |
- short_lived_obj.foo = short_lived # write barrier
-loop_count: 30000000
diff --git a/benchmark/vm1_gc_wb_obj_promoted.yml b/benchmark/vm1_gc_wb_obj_promoted.yml
deleted file mode 100644
index 26859d2a52..0000000000
--- a/benchmark/vm1_gc_wb_obj_promoted.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-prelude: |
- class C
- attr_accessor :foo
- end
- long_lived = C.new
-
- if RUBY_VERSION >= "2.2.0"
- 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) }
- elsif
- GC.start
- end
-
- short_lived = ''
-benchmark:
- vm1_gc_wb_obj_promoted: |
- long_lived.foo = short_lived # write barrier
-loop_count: 30000000
diff --git a/benchmark/vm1_ivar.yml b/benchmark/vm1_ivar.yml
deleted file mode 100644
index 7aa6fac729..0000000000
--- a/benchmark/vm1_ivar.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-prelude: "@a = 1\n"
-benchmark:
- vm1_ivar: |
- j = @a
- k = @a
-loop_count: 30000000
diff --git a/benchmark/vm1_ivar_set.yml b/benchmark/vm1_ivar_set.yml
deleted file mode 100644
index 6f19412d16..0000000000
--- a/benchmark/vm1_ivar_set.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-benchmark:
- vm1_ivar_set: |
- @a = 1
- @b = 2
-loop_count: 30000000
diff --git a/benchmark/vm1_length.yml b/benchmark/vm1_length.yml
deleted file mode 100644
index a18e2ca2e6..0000000000
--- a/benchmark/vm1_length.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- a = 'abc'
- b = [1, 2, 3]
-benchmark:
- vm1_length: |
- a.length
- b.length
-loop_count: 30000000
diff --git a/benchmark/vm1_lvar_init.yml b/benchmark/vm1_lvar_init.yml
deleted file mode 100644
index 10e2becef9..0000000000
--- a/benchmark/vm1_lvar_init.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-# while loop cost is not removed because `i` is used in the script
-benchmark:
- vm1_lvar_init: |
- def m v
- unless v
- # unreachable code
- v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = v10 =
- v11 = v12 = v13 = v14 = v15 = v16 = v17 = v18 = v19 = v20 =
- v21 = v22 = v23 = v24 = v25 = v26 = v27 = v28 = v29 = v30 =
- v31 = v32 = v33 = v34 = v35 = v36 = v37 = v38 = v39 = v40 =
- v41 = v42 = v43 = v44 = v45 = v46 = v47 = v48 = v49 = v50 = 1
- end
- end
-
- i = 0
-
- while i<30_000_000
- i += 1
- m i
- end
-loop_count: 1
diff --git a/benchmark/vm1_lvar_set.yml b/benchmark/vm1_lvar_set.yml
deleted file mode 100644
index df8f6b6ea4..0000000000
--- a/benchmark/vm1_lvar_set.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-benchmark:
- vm1_lvar_set: |
- a = b = c = d = e = f = g = h = j = k = l = m = n = o = p = q = r = 1
-loop_count: 30000000
diff --git a/benchmark/vm1_neq.yml b/benchmark/vm1_neq.yml
deleted file mode 100644
index 65a8128dda..0000000000
--- a/benchmark/vm1_neq.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- obj1 = Object.new
- obj2 = Object.new
-benchmark:
- vm1_neq: |
- obj1 != obj2
-loop_count: 30000000
diff --git a/benchmark/vm1_not.yml b/benchmark/vm1_not.yml
deleted file mode 100644
index 0fb7b282a9..0000000000
--- a/benchmark/vm1_not.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-prelude: |
- obj = Object.new
-benchmark:
- vm1_not: |
- !obj
-loop_count: 30000000
diff --git a/benchmark/vm1_rescue.yml b/benchmark/vm1_rescue.yml
deleted file mode 100644
index a175b823af..0000000000
--- a/benchmark/vm1_rescue.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-benchmark:
- vm1_rescue: |
- begin
- rescue
- end
-loop_count: 30000000
diff --git a/benchmark/vm1_simplereturn.yml b/benchmark/vm1_simplereturn.yml
deleted file mode 100644
index 3564aac7e2..0000000000
--- a/benchmark/vm1_simplereturn.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- def m
- return 1
- end
-benchmark:
- vm1_simplereturn: m
-loop_count: 30000000
diff --git a/benchmark/vm1_swap.yml b/benchmark/vm1_swap.yml
deleted file mode 100644
index fed87ccd62..0000000000
--- a/benchmark/vm1_swap.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- a = 1
- b = 2
-benchmark:
- vm1_swap: |
- a, b = b, a
-loop_count: 30000000
diff --git a/benchmark/vm1_yield.yml b/benchmark/vm1_yield.yml
deleted file mode 100644
index ae1f9316f9..0000000000
--- a/benchmark/vm1_yield.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-# while loop cost is not removed due to benchmark_driver.gem's limitation
-benchmark:
- vm1_yield: |
- def m
- i = 0
- while i<30_000_000
- i += 1
- yield
- end
- end
-
- m{}
-loop_count: 1
diff --git a/benchmark/vm2_array.yml b/benchmark/vm2_array.yml
deleted file mode 100644
index 7373098d5e..0000000000
--- a/benchmark/vm2_array.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-benchmark:
- vm2_array: |
- a = [1,2,3,4,5,6,7,8,9,10]
-loop_count: 6000000
diff --git a/benchmark/vm2_bigarray.yml b/benchmark/vm2_bigarray.yml
deleted file mode 100644
index 2ad6da3905..0000000000
--- a/benchmark/vm2_bigarray.yml
+++ /dev/null
@@ -1,105 +0,0 @@
-benchmark:
- vm2_bigarray: |
- a = [
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- 1,2,3,4,5,6,7,8,9,10,
- ]
-loop_count: 6000000
diff --git a/benchmark/vm2_bighash.yml b/benchmark/vm2_bighash.yml
deleted file mode 100644
index e9154e4ba9..0000000000
--- a/benchmark/vm2_bighash.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-benchmark:
- vm2_bighash: |
- a = {0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, 10=>10, 11=>11, 12=>12, 13=>13, 14=>14, 15=>15, 16=>16, 17=>17, 18=>18, 19=>19, 20=>20, 21=>21, 22=>22, 23=>23, 24=>24, 25=>25, 26=>26, 27=>27, 28=>28, 29=>29, 30=>30, 31=>31, 32=>32, 33=>33, 34=>34, 35=>35, 36=>36, 37=>37, 38=>38, 39=>39, 40=>40, 41=>41, 42=>42, 43=>43, 44=>44, 45=>45, 46=>46, 47=>47, 48=>48, 49=>49, 50=>50, 51=>51, 52=>52, 53=>53, 54=>54, 55=>55, 56=>56, 57=>57, 58=>58, 59=>59, 60=>60, 61=>61, 62=>62, 63=>63, 64=>64, 65=>65, 66=>66, 67=>67, 68=>68, 69=>69, 70=>70, 71=>71, 72=>72, 73=>73, 74=>74, 75=>75, 76=>76, 77=>77, 78=>78, 79=>79, 80=>80, 81=>81, 82=>82, 83=>83, 84=>84, 85=>85, 86=>86, 87=>87, 88=>88, 89=>89, 90=>90, 91=>91, 92=>92, 93=>93, 94=>94, 95=>95, 96=>96, 97=>97, 98=>98, 99=>99, 100=>100, 101=>101, 102=>102, 103=>103, 104=>104, 105=>105, 106=>106, 107=>107, 108=>108, 109=>109, 110=>110, 111=>111, 112=>112, 113=>113, 114=>114, 115=>115, 116=>116, 117=>117, 118=>118, 119=>119, 120=>120, 121=>121, 122=>122, 123=>123, 124=>124, 125=>125, 126=>126, 127=>127, 128=>128, 129=>129, 130=>130, 131=>131, 132=>132, 133=>133, 134=>134, 135=>135, 136=>136, 137=>137, 138=>138, 139=>139, 140=>140, 141=>141, 142=>142, 143=>143, 144=>144, 145=>145, 146=>146, 147=>147, 148=>148, 149=>149, 150=>150, 151=>151, 152=>152, 153=>153, 154=>154, 155=>155, 156=>156, 157=>157, 158=>158, 159=>159, 160=>160, 161=>161, 162=>162, 163=>163, 164=>164, 165=>165, 166=>166, 167=>167, 168=>168, 169=>169, 170=>170, 171=>171, 172=>172, 173=>173, 174=>174, 175=>175, 176=>176, 177=>177, 178=>178, 179=>179, 180=>180, 181=>181, 182=>182, 183=>183, 184=>184, 185=>185, 186=>186, 187=>187, 188=>188, 189=>189, 190=>190, 191=>191, 192=>192, 193=>193, 194=>194, 195=>195, 196=>196, 197=>197, 198=>198, 199=>199, 200=>200, 201=>201, 202=>202, 203=>203, 204=>204, 205=>205, 206=>206, 207=>207, 208=>208, 209=>209, 210=>210, 211=>211, 212=>212, 213=>213, 214=>214, 215=>215, 216=>216, 217=>217, 218=>218, 219=>219, 220=>220, 221=>221, 222=>222, 223=>223, 224=>224, 225=>225, 226=>226, 227=>227, 228=>228, 229=>229, 230=>230, 231=>231, 232=>232, 233=>233, 234=>234, 235=>235, 236=>236, 237=>237, 238=>238, 239=>239, 240=>240, 241=>241, 242=>242, 243=>243, 244=>244, 245=>245, 246=>246, 247=>247, 248=>248, 249=>249, 250=>250, 251=>251, 252=>252, 253=>253, 254=>254, 255=>255, 256=>256, 257=>257, 258=>258, 259=>259, 260=>260, 261=>261, 262=>262, 263=>263, 264=>264, 265=>265, 266=>266, 267=>267, 268=>268, 269=>269, 270=>270, 271=>271, 272=>272, 273=>273, 274=>274, 275=>275, 276=>276, 277=>277, 278=>278, 279=>279, 280=>280, 281=>281, 282=>282, 283=>283, 284=>284, 285=>285, 286=>286, 287=>287, 288=>288, 289=>289, 290=>290, 291=>291, 292=>292, 293=>293, 294=>294, 295=>295, 296=>296, 297=>297, 298=>298, 299=>299, 300=>300, 301=>301, 302=>302, 303=>303, 304=>304, 305=>305, 306=>306, 307=>307, 308=>308, 309=>309, 310=>310, 311=>311, 312=>312, 313=>313, 314=>314, 315=>315, 316=>316, 317=>317, 318=>318, 319=>319, 320=>320, 321=>321, 322=>322, 323=>323, 324=>324, 325=>325, 326=>326, 327=>327, 328=>328, 329=>329, 330=>330, 331=>331, 332=>332, 333=>333, 334=>334, 335=>335, 336=>336, 337=>337, 338=>338, 339=>339, 340=>340, 341=>341, 342=>342, 343=>343, 344=>344, 345=>345, 346=>346, 347=>347, 348=>348, 349=>349, 350=>350, 351=>351, 352=>352, 353=>353, 354=>354, 355=>355, 356=>356, 357=>357, 358=>358, 359=>359, 360=>360, 361=>361, 362=>362, 363=>363, 364=>364, 365=>365, 366=>366, 367=>367, 368=>368, 369=>369, 370=>370, 371=>371, 372=>372, 373=>373, 374=>374, 375=>375, 376=>376, 377=>377, 378=>378, 379=>379, 380=>380, 381=>381, 382=>382, 383=>383, 384=>384, 385=>385, 386=>386, 387=>387, 388=>388, 389=>389, 390=>390, 391=>391, 392=>392, 393=>393, 394=>394, 395=>395, 396=>396, 397=>397, 398=>398, 399=>399, 400=>400, 401=>401, 402=>402, 403=>403, 404=>404, 405=>405, 406=>406, 407=>407, 408=>408, 409=>409, 410=>410, 411=>411, 412=>412, 413=>413, 414=>414, 415=>415, 416=>416, 417=>417, 418=>418, 419=>419, 420=>420, 421=>421, 422=>422, 423=>423, 424=>424, 425=>425, 426=>426, 427=>427, 428=>428, 429=>429, 430=>430, 431=>431, 432=>432, 433=>433, 434=>434, 435=>435, 436=>436, 437=>437, 438=>438, 439=>439, 440=>440, 441=>441, 442=>442, 443=>443, 444=>444, 445=>445, 446=>446, 447=>447, 448=>448, 449=>449, 450=>450, 451=>451, 452=>452, 453=>453, 454=>454, 455=>455, 456=>456, 457=>457, 458=>458, 459=>459, 460=>460, 461=>461, 462=>462, 463=>463, 464=>464, 465=>465, 466=>466, 467=>467, 468=>468, 469=>469, 470=>470, 471=>471, 472=>472, 473=>473, 474=>474, 475=>475, 476=>476, 477=>477, 478=>478, 479=>479, 480=>480, 481=>481, 482=>482, 483=>483, 484=>484, 485=>485, 486=>486, 487=>487, 488=>488, 489=>489, 490=>490, 491=>491, 492=>492, 493=>493, 494=>494, 495=>495, 496=>496, 497=>497, 498=>498, 499=>499, 500=>500,}
-loop_count: 60000
diff --git a/benchmark/vm2_case.yml b/benchmark/vm2_case.yml
deleted file mode 100644
index 7716783c09..0000000000
--- a/benchmark/vm2_case.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-benchmark:
- vm2_case: |
- case :foo
- when :bar
- raise
- when :baz
- raise
- when :boo
- raise
- when :foo
- # noop
- end
-loop_count: 6000000
diff --git a/benchmark/vm2_case_lit.yml b/benchmark/vm2_case_lit.yml
deleted file mode 100644
index c49b8dfe5e..0000000000
--- a/benchmark/vm2_case_lit.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-# loop_count is not utilized since `i` is involved in the script
-benchmark:
- vm2_case_lit: |
- i = 0
- @ret = [ "foo", true, false, :sym, 6, nil, 0.1, 0xffffffffffffffff ]
- def foo(i)
- @ret[i % @ret.size]
- end
-
- while i<6_000_000
- case foo(i)
- when "foo" then :foo
- when true then true
- when false then false
- when :sym then :sym
- when 6 then :fix
- when nil then nil
- when 0.1 then :float
- when 0xffffffffffffffff then :big
- end
- i += 1
- end
-loop_count: 1
diff --git a/benchmark/vm2_defined_method.yml b/benchmark/vm2_defined_method.yml
deleted file mode 100644
index e1b0d55674..0000000000
--- a/benchmark/vm2_defined_method.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- class Object
- define_method(:m){}
- end
-benchmark:
- vm2_defined_method: |
- m; m; m; m; m; m; m; m;
-loop_count: 6000000
diff --git a/benchmark/vm2_dstr.yml b/benchmark/vm2_dstr.yml
deleted file mode 100644
index f8bd6e0133..0000000000
--- a/benchmark/vm2_dstr.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-prelude: |
- x = y = 'z'
-benchmark:
- vm2_dstr: |
- str = "foo#{x}bar#{y}baz"
-loop_count: 6000000
diff --git a/benchmark/vm2_eval.yml b/benchmark/vm2_eval.yml
deleted file mode 100644
index d506a9c079..0000000000
--- a/benchmark/vm2_eval.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-benchmark:
- vm2_eval: |
- eval("1")
-loop_count: 6000000
diff --git a/benchmark/vm2_fiber_allocate.yml b/benchmark/vm2_fiber_allocate.yml
deleted file mode 100644
index f29705f694..0000000000
--- a/benchmark/vm2_fiber_allocate.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- # Disable GC to see raw throughput:
- GC.disable
-benchmark:
- vm2_fiber_allocate: |
- fiber = Fiber.new{Fiber.yield}
- fiber.resume
-loop_count: 100000
diff --git a/benchmark/vm2_fiber_count.yml b/benchmark/vm2_fiber_count.yml
deleted file mode 100644
index 3ecf6bdcb2..0000000000
--- a/benchmark/vm2_fiber_count.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-# On Linux, you will need to increase the maximum number of memory maps:
-# sudo sysctl -w vm.max_map_count=200000
-prelude: |
- fibers = []
-benchmark:
- vm2_fiber_count: |
- fiber = Fiber.new{Fiber.yield}
- fibers << fiber
- fiber.resume
-loop_count: 100000
diff --git a/benchmark/vm2_fiber_reuse.yml b/benchmark/vm2_fiber_reuse.yml
deleted file mode 100644
index 0170650638..0000000000
--- a/benchmark/vm2_fiber_reuse.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-prelude: |
- GC.disable
- fibers = []
-benchmark:
- vm2_fiber_reuse: |
- 1024.times do
- fiber = Fiber.new{Fiber.yield}
- fibers << fiber
- fiber.resume
- end
-
- fibers.clear
- GC.start
-loop_count: 200
diff --git a/benchmark/vm2_fiber_reuse_gc.yml b/benchmark/vm2_fiber_reuse_gc.yml
deleted file mode 100644
index 8fb91a84eb..0000000000
--- a/benchmark/vm2_fiber_reuse_gc.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-# https://bugs.ruby-lang.org/issues/16009
-prelude: |
- fibers = []
-benchmark:
- vm2_fiber_reuse_gc: |
- 2000.times do
- fiber = Fiber.new{Fiber.yield}
- fibers << fiber
- fiber.resume
- end
- fibers.clear
-loop_count: 100
diff --git a/benchmark/vm2_fiber_switch.yml b/benchmark/vm2_fiber_switch.yml
deleted file mode 100644
index fbf7283c29..0000000000
--- a/benchmark/vm2_fiber_switch.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-prelude: |
- # based on benchmark for [ruby-core:65518] [Feature #10341] by Knut Franke
- fib = Fiber.new do
- loop { Fiber.yield }
- end
-benchmark:
- vm2_fiber_switch: |
- fib.resume
-loop_count: 20000000
diff --git a/benchmark/vm2_freezestring.yml b/benchmark/vm2_freezestring.yml
deleted file mode 100644
index b78af91a20..0000000000
--- a/benchmark/vm2_freezestring.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-prelude: |
- class String
- def freeze
- -self
- end
- end
-benchmark:
- vm2_freezestring: |
- "tXnL1BP5T1WPXMjuFNLQtallEtRcay1t2lHtJSrlVsDgvunlbtfpr/DGdH0NGYE9".freeze
-loop_count: 6000000
diff --git a/benchmark/vm2_method.yml b/benchmark/vm2_method.yml
deleted file mode 100644
index cc7b9b28ff..0000000000
--- a/benchmark/vm2_method.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- def m
- nil
- end
-benchmark:
- vm2_method: |
- m; m; m; m; m; m; m; m;
-loop_count: 6000000
diff --git a/benchmark/vm2_method_missing.yml b/benchmark/vm2_method_missing.yml
deleted file mode 100644
index cbfb794b25..0000000000
--- a/benchmark/vm2_method_missing.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-prelude: |
- class C
- def method_missing mid
- end
- end
-
- obj = C.new
-benchmark:
- vm2_method_missing: |
- obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m;
-loop_count: 6000000
diff --git a/benchmark/vm2_method_with_block.yml b/benchmark/vm2_method_with_block.yml
deleted file mode 100644
index 6e522adccc..0000000000
--- a/benchmark/vm2_method_with_block.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- def m
- nil
- end
-benchmark:
- vm2_method_with_block: |
- m{}; m{}; m{}; m{}; m{}; m{}; m{}; m{};
-loop_count: 6000000
diff --git a/benchmark/vm2_module_ann_const_set.yml b/benchmark/vm2_module_ann_const_set.yml
deleted file mode 100644
index b0becd9d3d..0000000000
--- a/benchmark/vm2_module_ann_const_set.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-benchmark:
- vm2_module_ann_const_set: |
- Module.new.const_set(:X, Module.new)
-loop_count: 6000000
diff --git a/benchmark/vm2_module_const_set.yml b/benchmark/vm2_module_const_set.yml
deleted file mode 100644
index 05a640069c..0000000000
--- a/benchmark/vm2_module_const_set.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- module M
- end
- $VERBOSE = nil
-benchmark:
- vm2_module_const_set: |
- M.const_set(:X, Module.new)
-loop_count: 6000000
diff --git a/benchmark/vm2_mutex.yml b/benchmark/vm2_mutex.yml
deleted file mode 100644
index c40a90444a..0000000000
--- a/benchmark/vm2_mutex.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- require 'thread'
-
- m = Thread::Mutex.new
-benchmark:
- vm2_mutex: |
- m.synchronize{}
-loop_count: 6000000
diff --git a/benchmark/vm2_newlambda.yml b/benchmark/vm2_newlambda.yml
deleted file mode 100644
index 93133f9f30..0000000000
--- a/benchmark/vm2_newlambda.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-benchmark:
- vm2_newlambda: |
- lambda {}
-loop_count: 6000000
diff --git a/benchmark/vm2_poly_method.yml b/benchmark/vm2_poly_method.yml
deleted file mode 100644
index 0104bdfb66..0000000000
--- a/benchmark/vm2_poly_method.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-# loop_count is not utilized since `i` is involved in the script
-benchmark:
- vm2_poly_method: |
- class C1
- def m
- 1
- end
- end
- class C2
- def m
- 2
- end
- end
-
- o1 = C1.new
- o2 = C2.new
-
- i = 0
- while i<6_000_000
- o = (i % 2 == 0) ? o1 : o2
- o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m
- i += 1
- end
-loop_count: 1
diff --git a/benchmark/vm2_poly_method_ov.yml b/benchmark/vm2_poly_method_ov.yml
deleted file mode 100644
index 3748073ba2..0000000000
--- a/benchmark/vm2_poly_method_ov.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-# loop_count is not utilized since `i` is involved in the script
-benchmark:
- vm2_poly_method_ov: |
- class C1
- def m
- 1
- end
- end
- class C2
- def m
- 2
- end
- end
-
- o1 = C1.new
- o2 = C2.new
-
- i = 0
- while i<6_000_000
- o = (i % 2 == 0) ? o1 : o2
- # o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m
- i += 1
- end
-loop_count: 1
diff --git a/benchmark/vm2_poly_same_method.yml b/benchmark/vm2_poly_same_method.yml
deleted file mode 100644
index 867c433cf8..0000000000
--- a/benchmark/vm2_poly_same_method.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-prelude: |
- module AR; end
- class AR::Base
- def create_or_update
- nil
- end
- def save
- create_or_update
- end
- end
- class Foo < AR::Base; end
- class Bar < AR::Base; end
- o1 = Foo.new
- o2 = Bar.new
-benchmark:
- vm2_poly_same_method: |
- o1.save; o2.save;
- o1.save; o2.save;
- o1.save; o2.save;
- o1.save; o2.save;
- o1.save; o2.save;
- o1.save; o2.save;
- o1.save; o2.save;
- o1.save; o2.save;
-loop_count: 6000000
diff --git a/benchmark/vm2_poly_singleton.yml b/benchmark/vm2_poly_singleton.yml
deleted file mode 100644
index e58d7bfb37..0000000000
--- a/benchmark/vm2_poly_singleton.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-# loop_count is not utilized since `i` is involved in the script
-benchmark:
- vm2_poly_singleton: |
- class C1
- def m; 1; end
- end
-
- o1 = C1.new
- o2 = C1.new
- o2.singleton_class
-
- i = 0
- while i<6_000_000 # benchmark loop 2
- o = (i % 2 == 0) ? o1 : o2
- o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m
- i += 1
- end
-loop_count: 1
diff --git a/benchmark/vm2_proc.yml b/benchmark/vm2_proc.yml
deleted file mode 100644
index 5c36e936d9..0000000000
--- a/benchmark/vm2_proc.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-prelude: |
- def m &b
- b
- end
-
- pr = m{
- a = 1
- }
-benchmark:
- vm2_proc: |
- pr.call
-loop_count: 6000000
diff --git a/benchmark/vm2_raise1.yml b/benchmark/vm2_raise1.yml
deleted file mode 100644
index f6eb308968..0000000000
--- a/benchmark/vm2_raise1.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-prelude: |
- def rec n
- if n > 0
- rec n-1
- else
- raise
- end
- end
-benchmark:
- vm2_raise1: |
- begin
- rec 1
- rescue
- # ignore
- end
-loop_count: 6000000
diff --git a/benchmark/vm2_raise2.yml b/benchmark/vm2_raise2.yml
deleted file mode 100644
index 7d51b1b314..0000000000
--- a/benchmark/vm2_raise2.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-prelude: |
- def rec n
- if n > 0
- rec n-1
- else
- raise
- end
- end
-benchmark:
- vm2_raise2: |
- begin
- rec 10
- rescue
- # ignore
- end
-loop_count: 6000000
diff --git a/benchmark/vm2_regexp.yml b/benchmark/vm2_regexp.yml
deleted file mode 100644
index e53341f43b..0000000000
--- a/benchmark/vm2_regexp.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-prelude: |
- str = 'xxxhogexxx'
-benchmark:
- vm2_regexp: |
- /hoge/ =~ str
- vm2_regexp_invert: |
- str =~ /hoge/
-loop_count: 6000000
diff --git a/benchmark/vm2_send.yml b/benchmark/vm2_send.yml
deleted file mode 100644
index 44a12a27d9..0000000000
--- a/benchmark/vm2_send.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-prelude: |
- class C
- def m
- end
- end
-
- o = C.new
-benchmark:
- vm2_send: |
- o.__send__ :m
-loop_count: 6000000
diff --git a/benchmark/vm2_string_literal.yml b/benchmark/vm2_string_literal.yml
deleted file mode 100644
index 54b0aec1fe..0000000000
--- a/benchmark/vm2_string_literal.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-benchmark:
- vm2_string_literal: |
- x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-loop_count: 6000000
diff --git a/benchmark/vm2_struct_big_aref_hi.yml b/benchmark/vm2_struct_big_aref_hi.yml
deleted file mode 100644
index eed1846d28..0000000000
--- a/benchmark/vm2_struct_big_aref_hi.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- s = Struct.new(*('a'..'z').map { |x| x.to_sym })
- x = s.new
-benchmark:
- vm2_struct_big_aref_hi: |
- x.z # x[25]
-loop_count: 6000000
diff --git a/benchmark/vm2_struct_big_aref_lo.yml b/benchmark/vm2_struct_big_aref_lo.yml
deleted file mode 100644
index 0915435b76..0000000000
--- a/benchmark/vm2_struct_big_aref_lo.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- s = Struct.new(*('a'..'z').map { |x| x.to_sym })
- x = s.new
-benchmark:
- vm2_struct_big_aref_lo: |
- x.k # x[10]
-loop_count: 6000000
diff --git a/benchmark/vm2_struct_big_aset.yml b/benchmark/vm2_struct_big_aset.yml
deleted file mode 100644
index 6af50103d3..0000000000
--- a/benchmark/vm2_struct_big_aset.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-# loop_count is not utilized since `i` is involved in the script
-benchmark:
- vm2_struct_big_aset: |
- s = Struct.new(*('a'..'z').map { |x| x.to_sym })
- x = s.new
- i = 0
- while i<6_000_000
- i += 1
- x.k = i # x[10] = i
- end
-loop_count: 1
diff --git a/benchmark/vm2_struct_big_href_hi.yml b/benchmark/vm2_struct_big_href_hi.yml
deleted file mode 100644
index 60aa7fddf3..0000000000
--- a/benchmark/vm2_struct_big_href_hi.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- s = Struct.new(*('a'..'z').map { |x| x.to_sym })
- x = s.new
-benchmark:
- vm2_struct_big_href_hi: |
- x[:z]
-loop_count: 6000000
diff --git a/benchmark/vm2_struct_big_href_lo.yml b/benchmark/vm2_struct_big_href_lo.yml
deleted file mode 100644
index c55c0bd16c..0000000000
--- a/benchmark/vm2_struct_big_href_lo.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- s = Struct.new(*('a'..'z').map { |x| x.to_sym })
- x = s.new
-benchmark:
- vm2_struct_big_href_lo: |
- x[:k]
-loop_count: 6000000
diff --git a/benchmark/vm2_struct_big_hset.yml b/benchmark/vm2_struct_big_hset.yml
deleted file mode 100644
index d199c5bd47..0000000000
--- a/benchmark/vm2_struct_big_hset.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-# loop_count is not utilized since `i` is involved in the script
-benchmark:
- vm2_struct_big_hset: |
- s = Struct.new(*('a'..'z').map { |x| x.to_sym })
- x = s.new
- i = 0
- while i<6_000_000
- i += 1
- x[:k] = i
- end
-loop_count: 1
diff --git a/benchmark/vm2_struct_small_aref.yml b/benchmark/vm2_struct_small_aref.yml
deleted file mode 100644
index 83381bed3a..0000000000
--- a/benchmark/vm2_struct_small_aref.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- s = Struct.new(:a, :b, :c)
- x = s.new
-benchmark:
- vm2_struct_small_aref: |
- x.a
-loop_count: 6000000
diff --git a/benchmark/vm2_struct_small_aset.yml b/benchmark/vm2_struct_small_aset.yml
deleted file mode 100644
index 3e84a61dd0..0000000000
--- a/benchmark/vm2_struct_small_aset.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-# loop_count is not utilized since `i` is involved in the script
-benchmark:
- vm2_struct_small_aset: |
- s = Struct.new(:a, :b, :c)
- x = s.new
- i = 0
- while i<6_000_000
- i += 1
- x.a = i
- end
-loop_count: 1
diff --git a/benchmark/vm2_struct_small_href.yml b/benchmark/vm2_struct_small_href.yml
deleted file mode 100644
index b744f070d1..0000000000
--- a/benchmark/vm2_struct_small_href.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- s = Struct.new(:a, :b, :c)
- x = s.new
-benchmark:
- vm2_struct_small_href: |
- x[:a]
-loop_count: 6000000
diff --git a/benchmark/vm2_struct_small_hset.yml b/benchmark/vm2_struct_small_hset.yml
deleted file mode 100644
index d43845d6e0..0000000000
--- a/benchmark/vm2_struct_small_hset.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- s = Struct.new(:a, :b, :c)
- x = s.new
-benchmark:
- vm2_struct_small_hset: |
- x[:a] = 1
-loop_count: 6000000
diff --git a/benchmark/vm2_super.yml b/benchmark/vm2_super.yml
deleted file mode 100644
index 674743762a..0000000000
--- a/benchmark/vm2_super.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-prelude: |
- class C
- def m
- 1
- end
- end
-
- class CC < C
- def m
- super()
- end
- end
-
- obj = CC.new
-benchmark:
- vm2_super: obj.m
-loop_count: 6000000
diff --git a/benchmark/vm2_unif1.yml b/benchmark/vm2_unif1.yml
deleted file mode 100644
index caef13279f..0000000000
--- a/benchmark/vm2_unif1.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-prelude: |
- def m a, b
- end
-benchmark:
- vm2_unif1: |
- m 100, 200
-loop_count: 6000000
diff --git a/benchmark/vm2_zsuper.yml b/benchmark/vm2_zsuper.yml
deleted file mode 100644
index f760cfd48e..0000000000
--- a/benchmark/vm2_zsuper.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-prelude: |
- class C
- def m a
- 1
- end
- end
-
- class CC < C
- def m a
- super
- end
- end
-
- obj = CC.new
-benchmark:
- vm2_zsuper: |
- obj.m 10
-loop_count: 6000000
diff --git a/benchmark/vm_array.yml b/benchmark/vm_array.yml
new file mode 100644
index 0000000000..2a177237ef
--- /dev/null
+++ b/benchmark/vm_array.yml
@@ -0,0 +1,4 @@
+benchmark:
+ vm_array: |
+ a = [1,2,3,4,5,6,7,8,9,10]
+loop_count: 6000000
diff --git a/benchmark/vm_attr_ivar.yml b/benchmark/vm_attr_ivar.yml
new file mode 100644
index 0000000000..75b803478e
--- /dev/null
+++ b/benchmark/vm_attr_ivar.yml
@@ -0,0 +1,14 @@
+prelude: |
+ class C
+ attr_reader :a, :b
+ def initialize
+ @a = nil
+ @b = nil
+ end
+ end
+ obj = C.new
+benchmark:
+ vm_attr_ivar: |
+ j = obj.a
+ k = obj.b
+loop_count: 30000000
diff --git a/benchmark/vm_attr_ivar_set.yml b/benchmark/vm_attr_ivar_set.yml
new file mode 100644
index 0000000000..a0d379b18a
--- /dev/null
+++ b/benchmark/vm_attr_ivar_set.yml
@@ -0,0 +1,14 @@
+prelude: |
+ class C
+ attr_accessor :a, :b
+ def initialize
+ @a = nil
+ @b = nil
+ end
+ end
+ obj = C.new
+benchmark:
+ vm_attr_ivar_set: |
+ obj.a = 1
+ obj.b = 2
+loop_count: 30000000
diff --git a/benchmark/vm3_backtrace.rb b/benchmark/vm_backtrace.rb
index 0fbf73e1ca..0fbf73e1ca 100644
--- a/benchmark/vm3_backtrace.rb
+++ b/benchmark/vm_backtrace.rb
diff --git a/benchmark/vm_bigarray.yml b/benchmark/vm_bigarray.yml
new file mode 100644
index 0000000000..8b2d3f3443
--- /dev/null
+++ b/benchmark/vm_bigarray.yml
@@ -0,0 +1,105 @@
+benchmark:
+ vm_bigarray: |
+ a = [
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ 1,2,3,4,5,6,7,8,9,10,
+ ]
+loop_count: 6000000
diff --git a/benchmark/vm_bighash.yml b/benchmark/vm_bighash.yml
new file mode 100644
index 0000000000..4dacfde793
--- /dev/null
+++ b/benchmark/vm_bighash.yml
@@ -0,0 +1,4 @@
+benchmark:
+ vm_bighash: |
+ a = {0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, 10=>10, 11=>11, 12=>12, 13=>13, 14=>14, 15=>15, 16=>16, 17=>17, 18=>18, 19=>19, 20=>20, 21=>21, 22=>22, 23=>23, 24=>24, 25=>25, 26=>26, 27=>27, 28=>28, 29=>29, 30=>30, 31=>31, 32=>32, 33=>33, 34=>34, 35=>35, 36=>36, 37=>37, 38=>38, 39=>39, 40=>40, 41=>41, 42=>42, 43=>43, 44=>44, 45=>45, 46=>46, 47=>47, 48=>48, 49=>49, 50=>50, 51=>51, 52=>52, 53=>53, 54=>54, 55=>55, 56=>56, 57=>57, 58=>58, 59=>59, 60=>60, 61=>61, 62=>62, 63=>63, 64=>64, 65=>65, 66=>66, 67=>67, 68=>68, 69=>69, 70=>70, 71=>71, 72=>72, 73=>73, 74=>74, 75=>75, 76=>76, 77=>77, 78=>78, 79=>79, 80=>80, 81=>81, 82=>82, 83=>83, 84=>84, 85=>85, 86=>86, 87=>87, 88=>88, 89=>89, 90=>90, 91=>91, 92=>92, 93=>93, 94=>94, 95=>95, 96=>96, 97=>97, 98=>98, 99=>99, 100=>100, 101=>101, 102=>102, 103=>103, 104=>104, 105=>105, 106=>106, 107=>107, 108=>108, 109=>109, 110=>110, 111=>111, 112=>112, 113=>113, 114=>114, 115=>115, 116=>116, 117=>117, 118=>118, 119=>119, 120=>120, 121=>121, 122=>122, 123=>123, 124=>124, 125=>125, 126=>126, 127=>127, 128=>128, 129=>129, 130=>130, 131=>131, 132=>132, 133=>133, 134=>134, 135=>135, 136=>136, 137=>137, 138=>138, 139=>139, 140=>140, 141=>141, 142=>142, 143=>143, 144=>144, 145=>145, 146=>146, 147=>147, 148=>148, 149=>149, 150=>150, 151=>151, 152=>152, 153=>153, 154=>154, 155=>155, 156=>156, 157=>157, 158=>158, 159=>159, 160=>160, 161=>161, 162=>162, 163=>163, 164=>164, 165=>165, 166=>166, 167=>167, 168=>168, 169=>169, 170=>170, 171=>171, 172=>172, 173=>173, 174=>174, 175=>175, 176=>176, 177=>177, 178=>178, 179=>179, 180=>180, 181=>181, 182=>182, 183=>183, 184=>184, 185=>185, 186=>186, 187=>187, 188=>188, 189=>189, 190=>190, 191=>191, 192=>192, 193=>193, 194=>194, 195=>195, 196=>196, 197=>197, 198=>198, 199=>199, 200=>200, 201=>201, 202=>202, 203=>203, 204=>204, 205=>205, 206=>206, 207=>207, 208=>208, 209=>209, 210=>210, 211=>211, 212=>212, 213=>213, 214=>214, 215=>215, 216=>216, 217=>217, 218=>218, 219=>219, 220=>220, 221=>221, 222=>222, 223=>223, 224=>224, 225=>225, 226=>226, 227=>227, 228=>228, 229=>229, 230=>230, 231=>231, 232=>232, 233=>233, 234=>234, 235=>235, 236=>236, 237=>237, 238=>238, 239=>239, 240=>240, 241=>241, 242=>242, 243=>243, 244=>244, 245=>245, 246=>246, 247=>247, 248=>248, 249=>249, 250=>250, 251=>251, 252=>252, 253=>253, 254=>254, 255=>255, 256=>256, 257=>257, 258=>258, 259=>259, 260=>260, 261=>261, 262=>262, 263=>263, 264=>264, 265=>265, 266=>266, 267=>267, 268=>268, 269=>269, 270=>270, 271=>271, 272=>272, 273=>273, 274=>274, 275=>275, 276=>276, 277=>277, 278=>278, 279=>279, 280=>280, 281=>281, 282=>282, 283=>283, 284=>284, 285=>285, 286=>286, 287=>287, 288=>288, 289=>289, 290=>290, 291=>291, 292=>292, 293=>293, 294=>294, 295=>295, 296=>296, 297=>297, 298=>298, 299=>299, 300=>300, 301=>301, 302=>302, 303=>303, 304=>304, 305=>305, 306=>306, 307=>307, 308=>308, 309=>309, 310=>310, 311=>311, 312=>312, 313=>313, 314=>314, 315=>315, 316=>316, 317=>317, 318=>318, 319=>319, 320=>320, 321=>321, 322=>322, 323=>323, 324=>324, 325=>325, 326=>326, 327=>327, 328=>328, 329=>329, 330=>330, 331=>331, 332=>332, 333=>333, 334=>334, 335=>335, 336=>336, 337=>337, 338=>338, 339=>339, 340=>340, 341=>341, 342=>342, 343=>343, 344=>344, 345=>345, 346=>346, 347=>347, 348=>348, 349=>349, 350=>350, 351=>351, 352=>352, 353=>353, 354=>354, 355=>355, 356=>356, 357=>357, 358=>358, 359=>359, 360=>360, 361=>361, 362=>362, 363=>363, 364=>364, 365=>365, 366=>366, 367=>367, 368=>368, 369=>369, 370=>370, 371=>371, 372=>372, 373=>373, 374=>374, 375=>375, 376=>376, 377=>377, 378=>378, 379=>379, 380=>380, 381=>381, 382=>382, 383=>383, 384=>384, 385=>385, 386=>386, 387=>387, 388=>388, 389=>389, 390=>390, 391=>391, 392=>392, 393=>393, 394=>394, 395=>395, 396=>396, 397=>397, 398=>398, 399=>399, 400=>400, 401=>401, 402=>402, 403=>403, 404=>404, 405=>405, 406=>406, 407=>407, 408=>408, 409=>409, 410=>410, 411=>411, 412=>412, 413=>413, 414=>414, 415=>415, 416=>416, 417=>417, 418=>418, 419=>419, 420=>420, 421=>421, 422=>422, 423=>423, 424=>424, 425=>425, 426=>426, 427=>427, 428=>428, 429=>429, 430=>430, 431=>431, 432=>432, 433=>433, 434=>434, 435=>435, 436=>436, 437=>437, 438=>438, 439=>439, 440=>440, 441=>441, 442=>442, 443=>443, 444=>444, 445=>445, 446=>446, 447=>447, 448=>448, 449=>449, 450=>450, 451=>451, 452=>452, 453=>453, 454=>454, 455=>455, 456=>456, 457=>457, 458=>458, 459=>459, 460=>460, 461=>461, 462=>462, 463=>463, 464=>464, 465=>465, 466=>466, 467=>467, 468=>468, 469=>469, 470=>470, 471=>471, 472=>472, 473=>473, 474=>474, 475=>475, 476=>476, 477=>477, 478=>478, 479=>479, 480=>480, 481=>481, 482=>482, 483=>483, 484=>484, 485=>485, 486=>486, 487=>487, 488=>488, 489=>489, 490=>490, 491=>491, 492=>492, 493=>493, 494=>494, 495=>495, 496=>496, 497=>497, 498=>498, 499=>499, 500=>500,}
+loop_count: 60000
diff --git a/benchmark/vm_block.yml b/benchmark/vm_block.yml
new file mode 100644
index 0000000000..68b3e40bf5
--- /dev/null
+++ b/benchmark/vm_block.yml
@@ -0,0 +1,9 @@
+prelude: |
+ def m
+ yield
+ end
+benchmark:
+ vm_block: |
+ m{
+ }
+loop_count: 30000000
diff --git a/benchmark/vm_block_handler.yml b/benchmark/vm_block_handler.yml
new file mode 100644
index 0000000000..461d7953ad
--- /dev/null
+++ b/benchmark/vm_block_handler.yml
@@ -0,0 +1,27 @@
+# :FIXME: is there a way to benchmark block_handler_type_ifunc?
+
+prelude: |
+ p = proc{_1}
+ o = Object.new
+ def o.each
+ i = 0
+ while i < 3_000_000 do
+ yield i
+ i += 1
+ end
+ end
+
+benchmark:
+ - name: block_handler_type_iseq
+ script: |
+ o.each{_1}
+
+ - name: block_handler_type_symbol
+ script: |
+ o.each(&:itself)
+
+ - name: block_handler_type_proc
+ script: |
+ o.each(&p)
+
+loop_count: 1
diff --git a/benchmark/vm_blockparam.yml b/benchmark/vm_blockparam.yml
new file mode 100644
index 0000000000..5e5a0170a2
--- /dev/null
+++ b/benchmark/vm_blockparam.yml
@@ -0,0 +1,7 @@
+prelude: |
+ def m &b
+ end
+benchmark:
+ vm_blockparam: |
+ m{}
+loop_count: 30000000
diff --git a/benchmark/vm_blockparam_call.yml b/benchmark/vm_blockparam_call.yml
new file mode 100644
index 0000000000..a7d8d366ea
--- /dev/null
+++ b/benchmark/vm_blockparam_call.yml
@@ -0,0 +1,8 @@
+prelude: |
+ def m &b
+ b.call
+ end
+benchmark:
+ vm_blockparam_call: |
+ m{}
+loop_count: 30000000
diff --git a/benchmark/vm_blockparam_pass.yml b/benchmark/vm_blockparam_pass.yml
new file mode 100644
index 0000000000..841f5e7a63
--- /dev/null
+++ b/benchmark/vm_blockparam_pass.yml
@@ -0,0 +1,12 @@
+prelude: |
+ def bp_yield
+ yield
+ end
+
+ def bp_pass &b
+ bp_yield &b
+ end
+benchmark:
+ vm_blockparam_pass: |
+ bp_pass{}
+loop_count: 30000000
diff --git a/benchmark/vm_blockparam_yield.yml b/benchmark/vm_blockparam_yield.yml
new file mode 100644
index 0000000000..8ea9b46ed2
--- /dev/null
+++ b/benchmark/vm_blockparam_yield.yml
@@ -0,0 +1,8 @@
+prelude: |
+ def bp_yield &b
+ yield
+ end
+benchmark:
+ vm_blockparam_yield: |
+ bp_yield{}
+loop_count: 30000000
diff --git a/benchmark/vm_case.yml b/benchmark/vm_case.yml
new file mode 100644
index 0000000000..b26a491a15
--- /dev/null
+++ b/benchmark/vm_case.yml
@@ -0,0 +1,13 @@
+benchmark:
+ vm_case: |
+ case :foo
+ when :bar
+ raise
+ when :baz
+ raise
+ when :boo
+ raise
+ when :foo
+ # noop
+ end
+loop_count: 6000000
diff --git a/benchmark/vm_case_lit.yml b/benchmark/vm_case_lit.yml
new file mode 100644
index 0000000000..9f91801544
--- /dev/null
+++ b/benchmark/vm_case_lit.yml
@@ -0,0 +1,23 @@
+# loop_count is not utilized since `i` is involved in the script
+benchmark:
+ vm_case_lit: |
+ i = 0
+ @ret = [ "foo", true, false, :sym, 6, nil, 0.1, 0xffffffffffffffff ]
+ def foo(i)
+ @ret[i % @ret.size]
+ end
+
+ while i<6_000_000
+ case foo(i)
+ when "foo" then :foo
+ when true then true
+ when false then false
+ when :sym then :sym
+ when 6 then :fix
+ when nil then nil
+ when 0.1 then :float
+ when 0xffffffffffffffff then :big
+ end
+ i += 1
+ end
+loop_count: 1
diff --git a/benchmark/vm3_clearmethodcache.rb b/benchmark/vm_clearmethodcache.rb
index 9661323cd2..9661323cd2 100644
--- a/benchmark/vm3_clearmethodcache.rb
+++ b/benchmark/vm_clearmethodcache.rb
diff --git a/benchmark/vm_const.yml b/benchmark/vm_const.yml
new file mode 100644
index 0000000000..6064d4eed0
--- /dev/null
+++ b/benchmark/vm_const.yml
@@ -0,0 +1,7 @@
+prelude: |
+ Const = 1
+benchmark:
+ vm_const: |
+ j = Const
+ k = Const
+loop_count: 30000000
diff --git a/benchmark/vm_defined_method.yml b/benchmark/vm_defined_method.yml
new file mode 100644
index 0000000000..347e0cfd33
--- /dev/null
+++ b/benchmark/vm_defined_method.yml
@@ -0,0 +1,8 @@
+prelude: |
+ class Object
+ define_method(:m){}
+ end
+benchmark:
+ vm_defined_method: |
+ m; m; m; m; m; m; m; m;
+loop_count: 6000000
diff --git a/benchmark/vm_dstr.yml b/benchmark/vm_dstr.yml
new file mode 100644
index 0000000000..30c7a3193c
--- /dev/null
+++ b/benchmark/vm_dstr.yml
@@ -0,0 +1,6 @@
+prelude: |
+ x = y = 'z'
+benchmark:
+ vm_dstr: |
+ str = "foo#{x}bar#{y}baz"
+loop_count: 6000000
diff --git a/benchmark/vm_ensure.yml b/benchmark/vm_ensure.yml
new file mode 100644
index 0000000000..4ea62f30de
--- /dev/null
+++ b/benchmark/vm_ensure.yml
@@ -0,0 +1,14 @@
+# Not utilizing loop_count since using it for this is too unstable for now
+benchmark:
+ vm_ensure: |
+ i = 0
+ while i<30_000_000
+ i += 1
+ begin
+ begin
+ ensure
+ end
+ ensure
+ end
+ end
+loop_count: 1
diff --git a/benchmark/vm_eval.yml b/benchmark/vm_eval.yml
new file mode 100644
index 0000000000..7ba1a8d1de
--- /dev/null
+++ b/benchmark/vm_eval.yml
@@ -0,0 +1,4 @@
+benchmark:
+ vm_eval: |
+ eval("1")
+loop_count: 6000000
diff --git a/benchmark/vm_fiber_allocate.yml b/benchmark/vm_fiber_allocate.yml
new file mode 100644
index 0000000000..b5a54e1ddf
--- /dev/null
+++ b/benchmark/vm_fiber_allocate.yml
@@ -0,0 +1,8 @@
+prelude: |
+ # Disable GC to see raw throughput:
+ GC.disable
+benchmark:
+ vm_fiber_allocate: |
+ fiber = Fiber.new{Fiber.yield}
+ fiber.resume
+loop_count: 100000
diff --git a/benchmark/vm_fiber_count.yml b/benchmark/vm_fiber_count.yml
new file mode 100644
index 0000000000..b83d3152d4
--- /dev/null
+++ b/benchmark/vm_fiber_count.yml
@@ -0,0 +1,10 @@
+# On Linux, you will need to increase the maximum number of memory maps:
+# sudo sysctl -w vm.max_map_count=200000
+prelude: |
+ fibers = []
+benchmark:
+ vm_fiber_count: |
+ fiber = Fiber.new{Fiber.yield}
+ fibers << fiber
+ fiber.resume
+loop_count: 100000
diff --git a/benchmark/vm_fiber_reuse.yml b/benchmark/vm_fiber_reuse.yml
new file mode 100644
index 0000000000..4ca41085b1
--- /dev/null
+++ b/benchmark/vm_fiber_reuse.yml
@@ -0,0 +1,14 @@
+prelude: |
+ GC.disable
+ fibers = []
+benchmark:
+ vm_fiber_reuse: |
+ 1024.times do
+ fiber = Fiber.new{Fiber.yield}
+ fibers << fiber
+ fiber.resume
+ end
+
+ fibers.clear
+ GC.start
+loop_count: 200
diff --git a/benchmark/vm_fiber_reuse_gc.yml b/benchmark/vm_fiber_reuse_gc.yml
new file mode 100644
index 0000000000..892622f121
--- /dev/null
+++ b/benchmark/vm_fiber_reuse_gc.yml
@@ -0,0 +1,12 @@
+# https://bugs.ruby-lang.org/issues/16009
+prelude: |
+ fibers = []
+benchmark:
+ vm_fiber_reuse_gc: |
+ 2000.times do
+ fiber = Fiber.new{Fiber.yield}
+ fibers << fiber
+ fiber.resume
+ end
+ fibers.clear
+loop_count: 100
diff --git a/benchmark/vm_fiber_switch.yml b/benchmark/vm_fiber_switch.yml
new file mode 100644
index 0000000000..3de36b66eb
--- /dev/null
+++ b/benchmark/vm_fiber_switch.yml
@@ -0,0 +1,9 @@
+prelude: |
+ # based on benchmark for [ruby-core:65518] [Feature #10341] by Knut Franke
+ fib = Fiber.new do
+ loop { Fiber.yield }
+ end
+benchmark:
+ vm_fiber_switch: |
+ fib.resume
+loop_count: 20000000
diff --git a/benchmark/vm_float_simple.yml b/benchmark/vm_float_simple.yml
new file mode 100644
index 0000000000..92f5fd52ab
--- /dev/null
+++ b/benchmark/vm_float_simple.yml
@@ -0,0 +1,8 @@
+prelude: |
+ f = 0.0
+benchmark:
+ vm_float_simple: |
+ f += 0.1; f -= 0.1
+ f += 0.1; f -= 0.1
+ f += 0.1; f -= 0.1
+loop_count: 30000000
diff --git a/benchmark/vm_freezestring.yml b/benchmark/vm_freezestring.yml
new file mode 100644
index 0000000000..facc9aa043
--- /dev/null
+++ b/benchmark/vm_freezestring.yml
@@ -0,0 +1,10 @@
+prelude: |
+ class String
+ def freeze
+ -self
+ end
+ end
+benchmark:
+ vm_freezestring: |
+ "tXnL1BP5T1WPXMjuFNLQtallEtRcay1t2lHtJSrlVsDgvunlbtfpr/DGdH0NGYE9".freeze
+loop_count: 6000000
diff --git a/benchmark/vm3_gc.rb b/benchmark/vm_gc.rb
index e668026915..e668026915 100644
--- a/benchmark/vm3_gc.rb
+++ b/benchmark/vm_gc.rb
diff --git a/benchmark/vm3_gc_old_full.rb b/benchmark/vm_gc_old_full.rb
index cfdfc8c5a5..cfdfc8c5a5 100644
--- a/benchmark/vm3_gc_old_full.rb
+++ b/benchmark/vm_gc_old_full.rb
diff --git a/benchmark/vm3_gc_old_immediate.rb b/benchmark/vm_gc_old_immediate.rb
index ad22feb655..ad22feb655 100644
--- a/benchmark/vm3_gc_old_immediate.rb
+++ b/benchmark/vm_gc_old_immediate.rb
diff --git a/benchmark/vm3_gc_old_lazy.rb b/benchmark/vm_gc_old_lazy.rb
index b74d44baf1..b74d44baf1 100644
--- a/benchmark/vm3_gc_old_lazy.rb
+++ b/benchmark/vm_gc_old_lazy.rb
diff --git a/benchmark/vm_gc_short_lived.yml b/benchmark/vm_gc_short_lived.yml
new file mode 100644
index 0000000000..29c803fee3
--- /dev/null
+++ b/benchmark/vm_gc_short_lived.yml
@@ -0,0 +1,9 @@
+benchmark:
+ vm_gc_short_lived: |
+ a = '' # short-lived String
+ b = ''
+ c = ''
+ d = ''
+ e = ''
+ f = ''
+loop_count: 30000000
diff --git a/benchmark/vm_gc_short_with_complex_long.yml b/benchmark/vm_gc_short_with_complex_long.yml
new file mode 100644
index 0000000000..4b6c3ed7b9
--- /dev/null
+++ b/benchmark/vm_gc_short_with_complex_long.yml
@@ -0,0 +1,25 @@
+prelude: |
+ def nested_hash h, n
+ if n == 0
+ ''
+ else
+ 10.times{
+ h[Object.new] = nested_hash(h, n-1)
+ }
+ end
+ end
+
+ long_lived = Hash.new
+ nested_hash long_lived, 6
+
+ GC.start
+ GC.start
+benchmark:
+ vm_gc_short_with_complex_long: |
+ a = '' # short-lived String
+ b = ''
+ c = ''
+ d = ''
+ e = ''
+ f = ''
+loop_count: 30000000
diff --git a/benchmark/vm_gc_short_with_long.yml b/benchmark/vm_gc_short_with_long.yml
new file mode 100644
index 0000000000..03ba0f95a9
--- /dev/null
+++ b/benchmark/vm_gc_short_with_long.yml
@@ -0,0 +1,13 @@
+prelude: |
+ long_lived = Array.new(1_000_000){|i| "#{i}"}
+ GC.start
+ GC.start
+benchmark:
+ vm_gc_short_with_long: |
+ a = '' # short-lived String
+ b = ''
+ c = ''
+ d = ''
+ e = ''
+ f = ''
+loop_count: 30000000
diff --git a/benchmark/vm_gc_short_with_symbol.yml b/benchmark/vm_gc_short_with_symbol.yml
new file mode 100644
index 0000000000..129b8bf4ed
--- /dev/null
+++ b/benchmark/vm_gc_short_with_symbol.yml
@@ -0,0 +1,13 @@
+prelude: |
+ 50_000.times{|i| sym = "sym#{i}".to_sym}
+ GC.start
+ GC.start
+benchmark:
+ vm_gc_short_with_symbol: |
+ a = '' # short-lived String
+ b = ''
+ c = ''
+ d = ''
+ e = ''
+ f = ''
+loop_count: 30000000
diff --git a/benchmark/vm_gc_wb_ary.yml b/benchmark/vm_gc_wb_ary.yml
new file mode 100644
index 0000000000..e3293e72d0
--- /dev/null
+++ b/benchmark/vm_gc_wb_ary.yml
@@ -0,0 +1,12 @@
+prelude: |
+ short_lived_ary = []
+
+ if RUBY_VERSION >= "2.2.0"
+ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true)
+ end
+
+ short_lived = ''
+benchmark:
+ vm_gc_wb_ary: |
+ short_lived_ary[0] = short_lived # write barrier
+loop_count: 30000000
diff --git a/benchmark/vm_gc_wb_ary_promoted.yml b/benchmark/vm_gc_wb_ary_promoted.yml
new file mode 100644
index 0000000000..003995945b
--- /dev/null
+++ b/benchmark/vm_gc_wb_ary_promoted.yml
@@ -0,0 +1,15 @@
+prelude: |
+ long_lived = []
+
+ if RUBY_VERSION > "2.2.0"
+ 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) }
+ elsif
+ GC.start
+ end
+
+ short_lived = ''
+
+benchmark:
+ vm_gc_wb_ary_promoted: |
+ long_lived[0] = short_lived # write barrier
+loop_count: 30000000
diff --git a/benchmark/vm_gc_wb_obj.yml b/benchmark/vm_gc_wb_obj.yml
new file mode 100644
index 0000000000..a2a2ce2d18
--- /dev/null
+++ b/benchmark/vm_gc_wb_obj.yml
@@ -0,0 +1,15 @@
+prelude: |
+ class C
+ attr_accessor :foo
+ end
+ short_lived_obj = C.new
+
+ if RUBY_VERSION >= "2.2.0"
+ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true)
+ end
+
+ short_lived = ''
+benchmark:
+ vm_gc_wb_obj: |
+ short_lived_obj.foo = short_lived # write barrier
+loop_count: 30000000
diff --git a/benchmark/vm_gc_wb_obj_promoted.yml b/benchmark/vm_gc_wb_obj_promoted.yml
new file mode 100644
index 0000000000..00a454ba72
--- /dev/null
+++ b/benchmark/vm_gc_wb_obj_promoted.yml
@@ -0,0 +1,17 @@
+prelude: |
+ class C
+ attr_accessor :foo
+ end
+ long_lived = C.new
+
+ if RUBY_VERSION >= "2.2.0"
+ 3.times{ GC.start(full_mark: false, immediate_mark: true, immediate_sweep: true) }
+ elsif
+ GC.start
+ end
+
+ short_lived = ''
+benchmark:
+ vm_gc_wb_obj_promoted: |
+ long_lived.foo = short_lived # write barrier
+loop_count: 30000000
diff --git a/benchmark/vm_iclass_super.yml b/benchmark/vm_iclass_super.yml
new file mode 100644
index 0000000000..21bb7db247
--- /dev/null
+++ b/benchmark/vm_iclass_super.yml
@@ -0,0 +1,20 @@
+prelude: |
+ class C
+ def m
+ 1
+ end
+
+ ("A".."M").each do |module_name|
+ eval <<-EOM
+ module #{module_name}
+ def m; super; end
+ end
+ prepend #{module_name}
+ EOM
+ end
+ end
+
+ obj = C.new
+benchmark:
+ vm_iclass_super: obj.m
+loop_count: 6000000
diff --git a/benchmark/vm_ivar.yml b/benchmark/vm_ivar.yml
new file mode 100644
index 0000000000..119531d5ef
--- /dev/null
+++ b/benchmark/vm_ivar.yml
@@ -0,0 +1,6 @@
+prelude: "@a = 1\n"
+benchmark:
+ vm_ivar: |
+ j = @a
+ k = @a
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_init.yml b/benchmark/vm_ivar_init.yml
new file mode 100644
index 0000000000..c6f1633907
--- /dev/null
+++ b/benchmark/vm_ivar_init.yml
@@ -0,0 +1,14 @@
+prelude: |
+ class C
+ def initialize
+ @a = nil
+ @b = nil
+ @c = nil
+ @d = nil
+ @e = nil
+ end
+ end
+benchmark:
+ vm_ivar_init: |
+ C.new
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_set.yml b/benchmark/vm_ivar_set.yml
new file mode 100644
index 0000000000..8bbb60043b
--- /dev/null
+++ b/benchmark/vm_ivar_set.yml
@@ -0,0 +1,5 @@
+benchmark:
+ vm_ivar_set: |
+ @a = 1
+ @b = 2
+loop_count: 30000000
diff --git a/benchmark/vm_ivar_set_subclass.yml b/benchmark/vm_ivar_set_subclass.yml
new file mode 100644
index 0000000000..2653d36ded
--- /dev/null
+++ b/benchmark/vm_ivar_set_subclass.yml
@@ -0,0 +1,17 @@
+prelude: |
+ class A
+ def initialize
+ @a = nil
+ @b = nil
+ @c = nil
+ @d = nil
+ @e = nil
+ end
+ end
+ class B < A; end
+ class C < A; end
+benchmark:
+ vm_ivar_init_subclass: |
+ B.new
+ C.new
+loop_count: 3000000
diff --git a/benchmark/vm_length.yml b/benchmark/vm_length.yml
new file mode 100644
index 0000000000..5fd94e7d86
--- /dev/null
+++ b/benchmark/vm_length.yml
@@ -0,0 +1,8 @@
+prelude: |
+ a = 'abc'
+ b = [1, 2, 3]
+benchmark:
+ vm_length: |
+ a.length
+ b.length
+loop_count: 30000000
diff --git a/benchmark/vm_lvar_init.yml b/benchmark/vm_lvar_init.yml
new file mode 100644
index 0000000000..70a9b1c0ca
--- /dev/null
+++ b/benchmark/vm_lvar_init.yml
@@ -0,0 +1,21 @@
+# while loop cost is not removed because `i` is used in the script
+benchmark:
+ vm_lvar_init: |
+ def m v
+ unless v
+ # unreachable code
+ v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = v10 =
+ v11 = v12 = v13 = v14 = v15 = v16 = v17 = v18 = v19 = v20 =
+ v21 = v22 = v23 = v24 = v25 = v26 = v27 = v28 = v29 = v30 =
+ v31 = v32 = v33 = v34 = v35 = v36 = v37 = v38 = v39 = v40 =
+ v41 = v42 = v43 = v44 = v45 = v46 = v47 = v48 = v49 = v50 = 1
+ end
+ end
+
+ i = 0
+
+ while i<30_000_000
+ i += 1
+ m i
+ end
+loop_count: 1
diff --git a/benchmark/vm_lvar_set.yml b/benchmark/vm_lvar_set.yml
new file mode 100644
index 0000000000..f29f763d81
--- /dev/null
+++ b/benchmark/vm_lvar_set.yml
@@ -0,0 +1,4 @@
+benchmark:
+ vm_lvar_set: |
+ a = b = c = d = e = f = g = h = j = k = l = m = n = o = p = q = r = 1
+loop_count: 30000000
diff --git a/benchmark/vm_method.yml b/benchmark/vm_method.yml
new file mode 100644
index 0000000000..d45e4ec572
--- /dev/null
+++ b/benchmark/vm_method.yml
@@ -0,0 +1,8 @@
+prelude: |
+ def m
+ nil
+ end
+benchmark:
+ vm_method: |
+ m; m; m; m; m; m; m; m;
+loop_count: 6000000
diff --git a/benchmark/vm_method_missing.yml b/benchmark/vm_method_missing.yml
new file mode 100644
index 0000000000..3da456c0bb
--- /dev/null
+++ b/benchmark/vm_method_missing.yml
@@ -0,0 +1,11 @@
+prelude: |
+ class C
+ def method_missing mid
+ end
+ end
+
+ obj = C.new
+benchmark:
+ vm_method_missing: |
+ obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m; obj.m;
+loop_count: 6000000
diff --git a/benchmark/vm_method_with_block.yml b/benchmark/vm_method_with_block.yml
new file mode 100644
index 0000000000..281a481394
--- /dev/null
+++ b/benchmark/vm_method_with_block.yml
@@ -0,0 +1,8 @@
+prelude: |
+ def m
+ nil
+ end
+benchmark:
+ vm_method_with_block: |
+ m{}; m{}; m{}; m{}; m{}; m{}; m{}; m{};
+loop_count: 6000000
diff --git a/benchmark/vm_module_ann_const_set.yml b/benchmark/vm_module_ann_const_set.yml
new file mode 100644
index 0000000000..243229ba4a
--- /dev/null
+++ b/benchmark/vm_module_ann_const_set.yml
@@ -0,0 +1,4 @@
+benchmark:
+ vm_module_ann_const_set: |
+ Module.new.const_set(:X, Module.new)
+loop_count: 6000000
diff --git a/benchmark/vm_module_const_set.yml b/benchmark/vm_module_const_set.yml
new file mode 100644
index 0000000000..e5a24181a9
--- /dev/null
+++ b/benchmark/vm_module_const_set.yml
@@ -0,0 +1,8 @@
+prelude: |
+ module M
+ end
+ $VERBOSE = nil
+benchmark:
+ vm_module_const_set: |
+ M.const_set(:X, Module.new)
+loop_count: 6000000
diff --git a/benchmark/vm_mutex.yml b/benchmark/vm_mutex.yml
new file mode 100644
index 0000000000..abcf1e28ce
--- /dev/null
+++ b/benchmark/vm_mutex.yml
@@ -0,0 +1,8 @@
+prelude: |
+ require 'thread'
+
+ m = Thread::Mutex.new
+benchmark:
+ vm_mutex: |
+ m.synchronize{}
+loop_count: 6000000
diff --git a/benchmark/vm_neq.yml b/benchmark/vm_neq.yml
new file mode 100644
index 0000000000..fb04d15ae8
--- /dev/null
+++ b/benchmark/vm_neq.yml
@@ -0,0 +1,7 @@
+prelude: |
+ obj1 = Object.new
+ obj2 = Object.new
+benchmark:
+ vm_neq: |
+ obj1 != obj2
+loop_count: 30000000
diff --git a/benchmark/vm_newlambda.yml b/benchmark/vm_newlambda.yml
new file mode 100644
index 0000000000..0b9787d91a
--- /dev/null
+++ b/benchmark/vm_newlambda.yml
@@ -0,0 +1,4 @@
+benchmark:
+ vm_newlambda: |
+ lambda {}
+loop_count: 6000000
diff --git a/benchmark/vm_not.yml b/benchmark/vm_not.yml
new file mode 100644
index 0000000000..c68dde3c50
--- /dev/null
+++ b/benchmark/vm_not.yml
@@ -0,0 +1,6 @@
+prelude: |
+ obj = Object.new
+benchmark:
+ vm_not: |
+ !obj
+loop_count: 30000000
diff --git a/benchmark/vm_poly_method.yml b/benchmark/vm_poly_method.yml
new file mode 100644
index 0000000000..dd2f4e71de
--- /dev/null
+++ b/benchmark/vm_poly_method.yml
@@ -0,0 +1,24 @@
+# loop_count is not utilized since `i` is involved in the script
+benchmark:
+ vm_poly_method: |
+ class C1
+ def m
+ 1
+ end
+ end
+ class C2
+ def m
+ 2
+ end
+ end
+
+ o1 = C1.new
+ o2 = C2.new
+
+ i = 0
+ while i<6_000_000
+ o = (i % 2 == 0) ? o1 : o2
+ o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m
+ i += 1
+ end
+loop_count: 1
diff --git a/benchmark/vm_poly_method_ov.yml b/benchmark/vm_poly_method_ov.yml
new file mode 100644
index 0000000000..bca1b62729
--- /dev/null
+++ b/benchmark/vm_poly_method_ov.yml
@@ -0,0 +1,24 @@
+# loop_count is not utilized since `i` is involved in the script
+benchmark:
+ vm_poly_method_ov: |
+ class C1
+ def m
+ 1
+ end
+ end
+ class C2
+ def m
+ 2
+ end
+ end
+
+ o1 = C1.new
+ o2 = C2.new
+
+ i = 0
+ while i<6_000_000
+ o = (i % 2 == 0) ? o1 : o2
+ # o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m
+ i += 1
+ end
+loop_count: 1
diff --git a/benchmark/vm_poly_same_method.yml b/benchmark/vm_poly_same_method.yml
new file mode 100644
index 0000000000..6c5404ac84
--- /dev/null
+++ b/benchmark/vm_poly_same_method.yml
@@ -0,0 +1,25 @@
+prelude: |
+ module AR; end
+ class AR::Base
+ def create_or_update
+ nil
+ end
+ def save
+ create_or_update
+ end
+ end
+ class Foo < AR::Base; end
+ class Bar < AR::Base; end
+ o1 = Foo.new
+ o2 = Bar.new
+benchmark:
+ vm_poly_same_method: |
+ o1.save; o2.save;
+ o1.save; o2.save;
+ o1.save; o2.save;
+ o1.save; o2.save;
+ o1.save; o2.save;
+ o1.save; o2.save;
+ o1.save; o2.save;
+ o1.save; o2.save;
+loop_count: 6000000
diff --git a/benchmark/vm_poly_singleton.yml b/benchmark/vm_poly_singleton.yml
new file mode 100644
index 0000000000..c7923160fb
--- /dev/null
+++ b/benchmark/vm_poly_singleton.yml
@@ -0,0 +1,18 @@
+# loop_count is not utilized since `i` is involved in the script
+benchmark:
+ vm_poly_singleton: |
+ class C1
+ def m; 1; end
+ end
+
+ o1 = C1.new
+ o2 = C1.new
+ o2.singleton_class
+
+ i = 0
+ while i<6_000_000 # benchmark loop 2
+ o = (i % 2 == 0) ? o1 : o2
+ o.m; o.m; o.m; o.m; o.m; o.m; o.m; o.m
+ i += 1
+ end
+loop_count: 1
diff --git a/benchmark/vm_proc.yml b/benchmark/vm_proc.yml
new file mode 100644
index 0000000000..2f8de6c272
--- /dev/null
+++ b/benchmark/vm_proc.yml
@@ -0,0 +1,12 @@
+prelude: |
+ def m &b
+ b
+ end
+
+ pr = m{
+ a = 1
+ }
+benchmark:
+ vm_proc: |
+ pr.call
+loop_count: 6000000
diff --git a/benchmark/vm_raise1.yml b/benchmark/vm_raise1.yml
new file mode 100644
index 0000000000..247d9f70ee
--- /dev/null
+++ b/benchmark/vm_raise1.yml
@@ -0,0 +1,16 @@
+prelude: |
+ def rec n
+ if n > 0
+ rec n-1
+ else
+ raise
+ end
+ end
+benchmark:
+ vm_raise1: |
+ begin
+ rec 1
+ rescue
+ # ignore
+ end
+loop_count: 6000000
diff --git a/benchmark/vm_raise2.yml b/benchmark/vm_raise2.yml
new file mode 100644
index 0000000000..f0fa047b3c
--- /dev/null
+++ b/benchmark/vm_raise2.yml
@@ -0,0 +1,16 @@
+prelude: |
+ def rec n
+ if n > 0
+ rec n-1
+ else
+ raise
+ end
+ end
+benchmark:
+ vm_raise2: |
+ begin
+ rec 10
+ rescue
+ # ignore
+ end
+loop_count: 6000000
diff --git a/benchmark/vm_regexp.yml b/benchmark/vm_regexp.yml
new file mode 100644
index 0000000000..2aa3d94dbd
--- /dev/null
+++ b/benchmark/vm_regexp.yml
@@ -0,0 +1,8 @@
+prelude: |
+ str = 'xxxhogexxx'
+benchmark:
+ vm_regexp: |
+ /hoge/ =~ str
+ vm_regexp_invert: |
+ str =~ /hoge/
+loop_count: 6000000
diff --git a/benchmark/vm_rescue.yml b/benchmark/vm_rescue.yml
new file mode 100644
index 0000000000..b4a0af521f
--- /dev/null
+++ b/benchmark/vm_rescue.yml
@@ -0,0 +1,6 @@
+benchmark:
+ vm_rescue: |
+ begin
+ rescue
+ end
+loop_count: 30000000
diff --git a/benchmark/vm_send.yml b/benchmark/vm_send.yml
new file mode 100644
index 0000000000..f31bc7ac89
--- /dev/null
+++ b/benchmark/vm_send.yml
@@ -0,0 +1,14 @@
+prelude: |
+ class C
+ def m
+ end
+ end
+
+ o = C.new
+ m = :m
+benchmark:
+ vm_send: |
+ o.__send__ :m
+ vm_send_var: |
+ o.__send__ m
+loop_count: 6000000
diff --git a/benchmark/vm_send_cfunc.yml b/benchmark/vm_send_cfunc.yml
new file mode 100644
index 0000000000..b114ac317d
--- /dev/null
+++ b/benchmark/vm_send_cfunc.yml
@@ -0,0 +1,3 @@
+benchmark:
+ vm_send_cfunc: self.class
+loop_count: 100000000
diff --git a/benchmark/vm_simplereturn.yml b/benchmark/vm_simplereturn.yml
new file mode 100644
index 0000000000..c9829cff0b
--- /dev/null
+++ b/benchmark/vm_simplereturn.yml
@@ -0,0 +1,7 @@
+prelude: |
+ def m
+ return 1
+ end
+benchmark:
+ vm_simplereturn: m
+loop_count: 30000000
diff --git a/benchmark/vm_string_literal.yml b/benchmark/vm_string_literal.yml
new file mode 100644
index 0000000000..64439c7980
--- /dev/null
+++ b/benchmark/vm_string_literal.yml
@@ -0,0 +1,4 @@
+benchmark:
+ vm_string_literal: |
+ x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+loop_count: 6000000
diff --git a/benchmark/vm_struct_big_aref_hi.yml b/benchmark/vm_struct_big_aref_hi.yml
new file mode 100644
index 0000000000..4cf78970cb
--- /dev/null
+++ b/benchmark/vm_struct_big_aref_hi.yml
@@ -0,0 +1,7 @@
+prelude: |
+ s = Struct.new(*('a'..'z').map { |x| x.to_sym })
+ x = s.new
+benchmark:
+ vm_struct_big_aref_hi: |
+ x.z # x[25]
+loop_count: 6000000
diff --git a/benchmark/vm_struct_big_aref_lo.yml b/benchmark/vm_struct_big_aref_lo.yml
new file mode 100644
index 0000000000..c91af27fa5
--- /dev/null
+++ b/benchmark/vm_struct_big_aref_lo.yml
@@ -0,0 +1,7 @@
+prelude: |
+ s = Struct.new(*('a'..'z').map { |x| x.to_sym })
+ x = s.new
+benchmark:
+ vm_struct_big_aref_lo: |
+ x.k # x[10]
+loop_count: 6000000
diff --git a/benchmark/vm_struct_big_aset.yml b/benchmark/vm_struct_big_aset.yml
new file mode 100644
index 0000000000..69550d14ea
--- /dev/null
+++ b/benchmark/vm_struct_big_aset.yml
@@ -0,0 +1,11 @@
+# loop_count is not utilized since `i` is involved in the script
+benchmark:
+ vm_struct_big_aset: |
+ s = Struct.new(*('a'..'z').map { |x| x.to_sym })
+ x = s.new
+ i = 0
+ while i<6_000_000
+ i += 1
+ x.k = i # x[10] = i
+ end
+loop_count: 1
diff --git a/benchmark/vm_struct_big_href_hi.yml b/benchmark/vm_struct_big_href_hi.yml
new file mode 100644
index 0000000000..09b764dd13
--- /dev/null
+++ b/benchmark/vm_struct_big_href_hi.yml
@@ -0,0 +1,7 @@
+prelude: |
+ s = Struct.new(*('a'..'z').map { |x| x.to_sym })
+ x = s.new
+benchmark:
+ vm_struct_big_href_hi: |
+ x[:z]
+loop_count: 6000000
diff --git a/benchmark/vm_struct_big_href_lo.yml b/benchmark/vm_struct_big_href_lo.yml
new file mode 100644
index 0000000000..d2f00b220f
--- /dev/null
+++ b/benchmark/vm_struct_big_href_lo.yml
@@ -0,0 +1,7 @@
+prelude: |
+ s = Struct.new(*('a'..'z').map { |x| x.to_sym })
+ x = s.new
+benchmark:
+ vm_struct_big_href_lo: |
+ x[:k]
+loop_count: 6000000
diff --git a/benchmark/vm_struct_big_hset.yml b/benchmark/vm_struct_big_hset.yml
new file mode 100644
index 0000000000..fc45cbee9c
--- /dev/null
+++ b/benchmark/vm_struct_big_hset.yml
@@ -0,0 +1,11 @@
+# loop_count is not utilized since `i` is involved in the script
+benchmark:
+ vm_struct_big_hset: |
+ s = Struct.new(*('a'..'z').map { |x| x.to_sym })
+ x = s.new
+ i = 0
+ while i<6_000_000
+ i += 1
+ x[:k] = i
+ end
+loop_count: 1
diff --git a/benchmark/vm_struct_small_aref.yml b/benchmark/vm_struct_small_aref.yml
new file mode 100644
index 0000000000..5a83251d1e
--- /dev/null
+++ b/benchmark/vm_struct_small_aref.yml
@@ -0,0 +1,7 @@
+prelude: |
+ s = Struct.new(:a, :b, :c)
+ x = s.new
+benchmark:
+ vm_struct_small_aref: |
+ x.a
+loop_count: 6000000
diff --git a/benchmark/vm_struct_small_aset.yml b/benchmark/vm_struct_small_aset.yml
new file mode 100644
index 0000000000..74f435f126
--- /dev/null
+++ b/benchmark/vm_struct_small_aset.yml
@@ -0,0 +1,11 @@
+# loop_count is not utilized since `i` is involved in the script
+benchmark:
+ vm_struct_small_aset: |
+ s = Struct.new(:a, :b, :c)
+ x = s.new
+ i = 0
+ while i<6_000_000
+ i += 1
+ x.a = i
+ end
+loop_count: 1
diff --git a/benchmark/vm_struct_small_href.yml b/benchmark/vm_struct_small_href.yml
new file mode 100644
index 0000000000..6b7d7f39e7
--- /dev/null
+++ b/benchmark/vm_struct_small_href.yml
@@ -0,0 +1,7 @@
+prelude: |
+ s = Struct.new(:a, :b, :c)
+ x = s.new
+benchmark:
+ vm_struct_small_href: |
+ x[:a]
+loop_count: 6000000
diff --git a/benchmark/vm_struct_small_hset.yml b/benchmark/vm_struct_small_hset.yml
new file mode 100644
index 0000000000..5d43b150de
--- /dev/null
+++ b/benchmark/vm_struct_small_hset.yml
@@ -0,0 +1,7 @@
+prelude: |
+ s = Struct.new(:a, :b, :c)
+ x = s.new
+benchmark:
+ vm_struct_small_hset: |
+ x[:a] = 1
+loop_count: 6000000
diff --git a/benchmark/vm_super.yml b/benchmark/vm_super.yml
new file mode 100644
index 0000000000..0d1e965c6e
--- /dev/null
+++ b/benchmark/vm_super.yml
@@ -0,0 +1,17 @@
+prelude: |
+ class C
+ def m
+ 1
+ end
+ end
+
+ class CC < C
+ def m
+ super()
+ end
+ end
+
+ obj = CC.new
+benchmark:
+ vm_super: obj.m
+loop_count: 6000000
diff --git a/benchmark/vm_swap.yml b/benchmark/vm_swap.yml
new file mode 100644
index 0000000000..e824a65e0a
--- /dev/null
+++ b/benchmark/vm_swap.yml
@@ -0,0 +1,7 @@
+prelude: |
+ a = 1
+ b = 2
+benchmark:
+ vm_swap: |
+ a, b = b, a
+loop_count: 30000000
diff --git a/benchmark/vm_unif1.yml b/benchmark/vm_unif1.yml
new file mode 100644
index 0000000000..04187bb0e2
--- /dev/null
+++ b/benchmark/vm_unif1.yml
@@ -0,0 +1,7 @@
+prelude: |
+ def m a, b
+ end
+benchmark:
+ vm_unif1: |
+ m 100, 200
+loop_count: 6000000
diff --git a/benchmark/vm_yield.yml b/benchmark/vm_yield.yml
new file mode 100644
index 0000000000..230be3d84f
--- /dev/null
+++ b/benchmark/vm_yield.yml
@@ -0,0 +1,13 @@
+# while loop cost is not removed due to benchmark_driver.gem's limitation
+benchmark:
+ vm_yield: |
+ def m
+ i = 0
+ while i<30_000_000
+ i += 1
+ yield
+ end
+ end
+
+ m{}
+loop_count: 1
diff --git a/benchmark/vm_zsuper.yml b/benchmark/vm_zsuper.yml
new file mode 100644
index 0000000000..bfb5837578
--- /dev/null
+++ b/benchmark/vm_zsuper.yml
@@ -0,0 +1,18 @@
+prelude: |
+ class C
+ def m a
+ 1
+ end
+ end
+
+ class CC < C
+ def m a
+ super
+ end
+ end
+
+ obj = CC.new
+benchmark:
+ vm_zsuper: |
+ obj.m 10
+loop_count: 6000000
diff --git a/bignum.c b/bignum.c
index 4569183e45..7c55366ecb 100644
--- a/bignum.c
+++ b/bignum.c
@@ -9,32 +9,42 @@
**********************************************************************/
-#include "internal.h"
-#include "ruby/thread.h"
-#include "ruby/util.h"
-#include "id.h"
+#include "ruby/internal/config.h"
+
+#include <ctype.h>
+#include <float.h>
+#include <math.h>
#ifdef HAVE_STRINGS_H
-#include <strings.h>
+# include <strings.h>
#endif
-#include <math.h>
-#include <float.h>
-#include <ctype.h>
+
#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
+# include <ieeefp.h>
#endif
-#include "ruby_assert.h"
#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
-#define USE_GMP
-#include <gmp.h>
+# define USE_GMP
+# include <gmp.h>
#endif
+#include "id.h"
+#include "internal.h"
+#include "internal/bignum.h"
+#include "internal/complex.h"
+#include "internal/gc.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/sanitizers.h"
+#include "internal/util.h"
+#include "internal/variable.h"
+#include "internal/warnings.h"
+#include "ruby/thread.h"
+#include "ruby/util.h"
+#include "ruby_assert.h"
+
#define RB_BIGNUM_TYPE_P(x) RB_TYPE_P((x), T_BIGNUM)
-#ifndef RUBY_INTEGER_UNIFICATION
-VALUE rb_cBignum;
-#endif
const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
#ifndef SIZEOF_BDIGIT_DBL
@@ -1996,7 +2006,7 @@ bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGI
}
/*
- * ref. http://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication
+ * ref. https://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication
*
* x(b) = x0 * b^0 + x1 * b^1 + x2 * b^2
* y(b) = y0 * b^0 + y1 * b^1 + y2 * b^2
@@ -2277,10 +2287,23 @@ rb_big_mul_toom3(VALUE x, VALUE y)
}
#ifdef USE_GMP
+static inline void
+bdigits_to_mpz(mpz_t mp, const BDIGIT *digits, size_t len)
+{
+ const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
+ mpz_import(mp, len, -1, sizeof(BDIGIT), 0, nails, digits);
+}
+
+static inline void
+bdigits_from_mpz(mpz_t mp, BDIGIT *digits, size_t *len)
+{
+ const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
+ mpz_export(digits, len, -1, sizeof(BDIGIT), 0, nails, mp);
+}
+
static void
bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
{
- const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
mpz_t x, y, z;
size_t count;
@@ -2289,15 +2312,15 @@ bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT
mpz_init(x);
mpz_init(y);
mpz_init(z);
- mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds);
+ bdigits_to_mpz(x, xds, xn);
if (xds == yds && xn == yn) {
mpz_mul(z, x, x);
}
else {
- mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds);
+ bdigits_to_mpz(y, yds, yn);
mpz_mul(z, x, y);
}
- mpz_export(zds, &count, -1, sizeof(BDIGIT), 0, nails, z);
+ bdigits_from_mpz(z, zds, &count);
BDIGITS_ZERO(zds+count, zn-count);
mpz_clear(x);
mpz_clear(y);
@@ -2336,9 +2359,9 @@ bary_sparse_p(const BDIGIT *ds, size_t n)
{
long c = 0;
- if ( ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++;
- if (c <= 1 && ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++;
- if (c <= 1 && ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++;
+ if ( ds[2 * n / 5]) c++;
+ if (c <= 1 && ds[ n / 2]) c++;
+ if (c <= 1 && ds[3 * n / 5]) c++;
return (c <= 1) ? 1 : 0;
}
@@ -2446,12 +2469,7 @@ bary_mul_karatsuba_branch(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn,
{
/* normal multiplication when x is small */
if (xn < KARATSUBA_MUL_DIGITS) {
- normal:
- if (xds == yds && xn == yn)
- bary_sq_fast(zds, zn, xds, xn);
- else
- bary_short_mul(zds, zn, xds, xn, yds, yn);
- return;
+ goto normal;
}
/* normal multiplication when x or y is a sparse bignum */
@@ -2469,6 +2487,15 @@ bary_mul_karatsuba_branch(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn,
/* multiplication by karatsuba method */
bary_mul_karatsuba(zds, zn, xds, xn, yds, yn, wds, wn);
+ return;
+
+ normal:
+ if (xds == yds && xn == yn) {
+ bary_sq_fast(zds, zn, xds, xn);
+ }
+ else {
+ bary_short_mul(zds, zn, xds, xn, yds, yn);
+ }
}
static void
@@ -2748,7 +2775,6 @@ rb_big_divrem_normal(VALUE x, VALUE y)
static void
bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
{
- const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
mpz_t x, y, q, r;
size_t count;
@@ -2762,8 +2788,8 @@ bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xd
if (qds) mpz_init(q);
if (rds) mpz_init(r);
- mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds);
- mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds);
+ bdigits_to_mpz(x, xds, xn);
+ bdigits_to_mpz(y, yds, yn);
if (!rds) {
mpz_fdiv_q(q, x, y);
@@ -2779,13 +2805,13 @@ bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xd
mpz_clear(y);
if (qds) {
- mpz_export(qds, &count, -1, sizeof(BDIGIT), 0, nails, q);
+ bdigits_from_mpz(q, qds, &count);
BDIGITS_ZERO(qds+count, qn-count);
mpz_clear(q);
}
if (rds) {
- mpz_export(rds, &count, -1, sizeof(BDIGIT), 0, nails, r);
+ bdigits_from_mpz(r, rds, &count);
BDIGITS_ZERO(rds+count, rn-count);
mpz_clear(r);
}
@@ -2884,29 +2910,8 @@ bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, s
}
-#define BIGNUM_DEBUG 0
-#if BIGNUM_DEBUG
-#define ON_DEBUG(x) do { x; } while (0)
-static void
-dump_bignum(VALUE x)
-{
- long i;
- printf("%c0x0", BIGNUM_SIGN(x) ? '+' : '-');
- for (i = BIGNUM_LEN(x); i--; ) {
- printf("_%0*"PRIxBDIGIT, SIZEOF_BDIGIT*2, BDIGITS(x)[i]);
- }
- printf(", len=%"PRIuSIZE, BIGNUM_LEN(x));
- puts("");
-}
-
-static VALUE
-rb_big_dump(VALUE x)
-{
- dump_bignum(x);
- return x;
-}
-#else
-#define ON_DEBUG(x)
+#ifndef BIGNUM_DEBUG
+# define BIGNUM_DEBUG (0+RUBY_DEBUG)
#endif
static int
@@ -2944,7 +2949,7 @@ rb_cmpint(VALUE val, VALUE a, VALUE b)
}
#define BIGNUM_SET_LEN(b,l) \
- ((RBASIC(b)->flags & BIGNUM_EMBED_FLAG) ? \
+ (BIGNUM_EMBED_P(b) ? \
(void)(RBASIC(b)->flags = \
(RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
@@ -2954,19 +2959,19 @@ static void
rb_big_realloc(VALUE big, size_t len)
{
BDIGIT *ds;
- if (RBASIC(big)->flags & BIGNUM_EMBED_FLAG) {
+ if (BIGNUM_EMBED_P(big)) {
if (BIGNUM_EMBED_LEN_MAX < len) {
ds = ALLOC_N(BDIGIT, len);
MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, BIGNUM_EMBED_LEN_MAX);
RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
RBIGNUM(big)->as.heap.digits = ds;
- RBASIC(big)->flags &= ~BIGNUM_EMBED_FLAG;
+ FL_UNSET_RAW(big, BIGNUM_EMBED_FLAG);
}
}
else {
if (len <= BIGNUM_EMBED_LEN_MAX) {
ds = RBIGNUM(big)->as.heap.digits;
- RBASIC(big)->flags |= BIGNUM_EMBED_FLAG;
+ FL_SET_RAW(big, BIGNUM_EMBED_FLAG);
BIGNUM_SET_LEN(big, len);
(void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary));
if (ds) {
@@ -2996,18 +3001,19 @@ static VALUE
bignew_1(VALUE klass, size_t len, int sign)
{
NEWOBJ_OF(big, struct RBignum, klass, T_BIGNUM | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0));
- BIGNUM_SET_SIGN(big, sign);
+ VALUE bigv = (VALUE)big;
+ BIGNUM_SET_SIGN(bigv, sign);
if (len <= BIGNUM_EMBED_LEN_MAX) {
- RBASIC(big)->flags |= BIGNUM_EMBED_FLAG;
- BIGNUM_SET_LEN(big, len);
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary));
+ FL_SET_RAW(bigv, BIGNUM_EMBED_FLAG);
+ BIGNUM_SET_LEN(bigv, len);
+ (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)big->as.ary, sizeof(big->as.ary));
}
else {
- RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
- RBIGNUM(big)->as.heap.len = len;
+ big->as.heap.digits = ALLOC_N(BDIGIT, len);
+ big->as.heap.len = len;
}
- OBJ_FREEZE(big);
- return (VALUE)big;
+ OBJ_FREEZE(bigv);
+ return bigv;
}
VALUE
@@ -3384,7 +3390,7 @@ rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
size_t numbytes;
int nlz_bits_in_msbyte;
size_t numwords;
- size_t nlz_bits;
+ size_t nlz_bits = 0;
if (word_numbits == 0)
return (size_t)-1;
@@ -3586,7 +3592,7 @@ rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t
}
/*
- * Import an integer into a buffer.
+ * Import an integer from a buffer.
*
* [words] buffer to import.
* [numwords] the size of given buffer as number of words.
@@ -3741,12 +3747,12 @@ str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size
return TRUE;
}
- if (badcheck && *str == '_') goto bad;
+ if (badcheck && *str == '_') return FALSE;
while ((c = *str++) != 0) {
if (c == '_') {
if (nondigit) {
- if (badcheck) goto bad;
+ if (badcheck) return FALSE;
break;
}
nondigit = (char) c;
@@ -3761,7 +3767,7 @@ str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size
}
if (len > 0 && !--len) break;
}
- if (badcheck && nondigit) goto bad;
+ if (badcheck && nondigit) return FALSE;
if (badcheck && len) {
str--;
while (*str && ISSPACE(*str)) {
@@ -3769,7 +3775,6 @@ str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size
if (len > 0 && !--len) break;
}
if (len && *str) {
- bad:
return FALSE;
}
}
@@ -3956,7 +3961,6 @@ str2big_gmp(
size_t num_bdigits,
int base)
{
- const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
char *buf, *p;
const char *q;
VALUE tmps;
@@ -3979,7 +3983,7 @@ str2big_gmp(
zn = num_bdigits;
z = bignew(zn, sign);
zds = BDIGITS(z);
- mpz_export(BDIGITS(z), &count, -1, sizeof(BDIGIT), 0, nails, mz);
+ bdigits_from_mpz(mz, BDIGITS(z), &count);
BDIGITS_ZERO(zds+count, zn-count);
mpz_clear(mz);
@@ -4066,10 +4070,7 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
} while (0)
if (!str) {
- bad:
- if (endp) *endp = (char *)str;
- if (ndigits) *ndigits = num_digits;
- return z;
+ goto bad;
}
if (len && (flags & RB_INT_PARSE_SIGN)) {
while (ISSPACE(*str)) ADV(1);
@@ -4233,6 +4234,11 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
}
return bignorm(z);
+
+ bad:
+ if (endp) *endp = (char *)str;
+ if (ndigits) *ndigits = num_digits;
+ return z;
}
static VALUE
@@ -4652,12 +4658,6 @@ static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
static void
power_cache_init(void)
{
- int i, j;
- for (i = 0; i < 35; ++i) {
- for (j = 0; j < MAX_BASE36_POWER_TABLE_ENTRIES; ++j) {
- base36_power_cache[i][j] = Qnil;
- }
- }
}
static inline VALUE
@@ -4680,8 +4680,8 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
rb_bug("too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
- if (NIL_P(base36_power_cache[base - 2][power_level])) {
- VALUE power;
+ VALUE power = base36_power_cache[base - 2][power_level];
+ if (!power) {
size_t numdigits;
if (power_level == 0) {
int numdigits0;
@@ -4701,7 +4701,7 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
}
if (numdigits_ret)
*numdigits_ret = base36_numdigits_cache[base - 2][power_level];
- return base36_power_cache[base - 2][power_level];
+ return power;
}
struct big2str_struct {
@@ -5010,7 +5010,6 @@ rb_big2str_generic(VALUE x, int base)
static VALUE
big2str_gmp(VALUE x, int base)
{
- const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
mpz_t mx;
size_t size;
VALUE str;
@@ -5018,7 +5017,7 @@ big2str_gmp(VALUE x, int base)
size_t xn = BIGNUM_LEN(x);
mpz_init(mx);
- mpz_import(mx, xn, -1, sizeof(BDIGIT), 0, nails, xds);
+ bdigits_to_mpz(mx, xds, xn);
size = mpz_sizeinbase(mx, base);
@@ -5373,11 +5372,9 @@ rb_integer_float_cmp(VALUE x, VALUE y)
#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG /* assume FLT_RADIX == 2 */
COMPILER_WARNING_PUSH
-#ifdef __has_warning
#if __has_warning("-Wimplicit-int-float-conversion")
COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion)
#endif
-#endif
static const double LONG_MAX_as_double = LONG_MAX;
COMPILER_WARNING_POP
#endif
@@ -5515,7 +5512,7 @@ rb_big_le(VALUE x, VALUE y)
*
* Returns <code>true</code> only if <i>obj</i> has the same value
* as <i>big</i>. Contrast this with Integer#eql?, which requires
- * <i>obj</i> to be a Integer.
+ * <i>obj</i> to be an Integer.
*
* 68719476736 == 68719476736.0 #=> true
*/
@@ -6266,7 +6263,7 @@ rb_big_pow(VALUE x, VALUE y)
yy = FIX2LONG(y);
if (yy < 0) {
- x = rb_big_pow(x, INT2NUM(-yy));
+ x = rb_big_pow(x, LONG2NUM(-yy));
if (RB_INTEGER_TYPE_P(x))
return rb_rational_raw(INT2FIX(1), x);
else
@@ -6691,7 +6688,6 @@ rb_big_aref(VALUE x, VALUE y)
return INT2FIX(0);
bigtrunc(y);
if (BIGSIZE(y) > sizeof(size_t)) {
- out_of_range:
return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
}
#if SIZEOF_SIZE_T <= SIZEOF_LONG
@@ -6709,7 +6705,8 @@ rb_big_aref(VALUE x, VALUE y)
s2 = shift%BITSPERDIG;
bit = (BDIGIT)1 << s2;
- if (s1 >= BIGNUM_LEN(x)) goto out_of_range;
+ if (s1 >= BIGNUM_LEN(x))
+ return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
xds = BDIGITS(x);
if (BIGNUM_POSITIVE_P(x))
@@ -6951,18 +6948,17 @@ rb_big_isqrt(VALUE n)
static void
bary_powm_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, const BDIGIT *mds, size_t mn)
{
- const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
mpz_t z, x, y, m;
size_t count;
mpz_init(x);
mpz_init(y);
mpz_init(m);
mpz_init(z);
- mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds);
- mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds);
- mpz_import(m, mn, -1, sizeof(BDIGIT), 0, nails, mds);
+ bdigits_to_mpz(x, xds, xn);
+ bdigits_to_mpz(y, yds, yn);
+ bdigits_to_mpz(m, mds, mn);
mpz_powm(z, x, y, m);
- mpz_export(zds, &count, -1, sizeof(BDIGIT), 0, nails, z);
+ bdigits_from_mpz(z, zds, &count);
BDIGITS_ZERO(zds+count, zn-count);
mpz_clear(x);
mpz_clear(y);
@@ -7140,6 +7136,7 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
long const half_val = (long)HALF_LONG_MSB;
long const mm = FIX2LONG(m);
if (!mm) rb_num_zerodiv();
+ if (mm == 1) return INT2FIX(0);
if (mm <= half_val) {
return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
}
@@ -7149,6 +7146,7 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
}
else {
if (rb_bigzero_p(m)) rb_num_zerodiv();
+ if (bignorm(m) == INT2FIX(1)) return INT2FIX(0);
return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
}
}
@@ -7176,9 +7174,6 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
void
Init_Bignum(void)
{
-#ifndef RUBY_INTEGER_UNIFICATION
- rb_cBignum = rb_cInteger;
-#endif
/* An obsolete class, use Integer */
rb_define_const(rb_cObject, "Bignum", rb_cInteger);
rb_deprecate_constant(rb_cObject, "Bignum");
diff --git a/bin/erb b/bin/erb
index 2435224fe1..89d74fc525 100755
--- a/bin/erb
+++ b/bin/erb
@@ -1,176 +1,27 @@
#!/usr/bin/env ruby
-# Tiny eRuby --- ERB2
-# Copyright (c) 1999-2000,2002 Masatoshi SEKI
-# You can redistribute it and/or modify it under the same terms as Ruby.
-
-require 'erb'
-
-class ERB
- module Main
- def ARGV.switch
- return nil if self.empty?
- arg = self.shift
- return nil if arg == '--'
- case arg
- when /\A-(.)(.*)/
- if $1 == '-'
- arg, @maybe_arg = arg.split(/=/, 2)
- return arg
- end
- raise 'unknown switch "-"' if $2[0] == ?- and $1 != 'T'
- if $2.size > 0
- self.unshift "-#{$2}"
- @maybe_arg = $2
- else
- @maybe_arg = nil
- end
- "-#{$1}"
- when /\A(\w+)=/
- arg
- else
- self.unshift arg
- nil
- end
- end
-
- def ARGV.req_arg
- (@maybe_arg || self.shift || raise('missing argument')).tap {
- @maybe_arg = nil
- }
- end
-
- def trim_mode_opt(trim_mode, disable_percent)
- return trim_mode if disable_percent
- case trim_mode
- when 0
- return '%'
- when 1
- return '%>'
- when 2
- return '%<>'
- when '-'
- return '%-'
- end
- end
- module_function :trim_mode_opt
-
- def run(factory=ERB)
- trim_mode = 0
- disable_percent = false
- variables = {}
- begin
- while switch = ARGV.switch
- case switch
- when '-x' # ruby source
- output = true
- when '-n' # line number
- number = true
- when '-v' # verbose
- $VERBOSE = true
- when '--version' # version
- STDERR.puts factory.version
- exit
- when '-d', '--debug' # debug
- $DEBUG = true
- when '-r' # require
- require ARGV.req_arg
- when '-S' # security level
- warn 'warning: -S option of erb command is deprecated. Please do not use this.'
- arg = ARGV.req_arg
- raise "invalid safe_level #{arg.dump}" unless arg =~ /\A[0-1]\z/
- safe_level = arg.to_i
- when '-T' # trim mode
- arg = ARGV.req_arg
- if arg == '-'
- trim_mode = arg
- next
- end
- raise "invalid trim mode #{arg.dump}" unless arg =~ /\A[0-2]\z/
- trim_mode = arg.to_i
- when '-E', '--encoding'
- arg = ARGV.req_arg
- set_encoding(*arg.split(/:/, 2))
- when '-U'
- set_encoding(Encoding::UTF_8, Encoding::UTF_8)
- when '-P'
- disable_percent = true
- when '--help'
- raise "print this help"
- when /\A-/
- 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]"
- 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
-EOU
- exit 1
- end
-
- $<.set_encoding(Encoding::UTF_8, nil)
- src = $<.read
- filename = $FILENAME
- exit 2 unless src
- trim = trim_mode_opt(trim_mode, disable_percent)
- if safe_level.nil?
- erb = factory.new(src, trim_mode: trim)
- else
- # [deprecated] This will be removed at Ruby 2.7.
- erb = factory.new(src, safe_level, trim_mode: trim)
- end
- erb.filename = filename
- if output
- if number
- erb.src.each_line.with_index do |line, l|
- puts "%3d %s"%[l+1, line]
- end
- else
- puts erb.src
- end
- else
- bind = TOPLEVEL_BINDING
- if variables
- enc = erb.encoding
- for var, val in variables do
- val = val.encode(enc) if val
- bind.local_variable_set(var, val)
- end
- end
- erb.run(bind)
- end
- end
- module_function :run
-
- def set_encoding(extern, intern = nil)
- verbose, $VERBOSE = $VERBOSE, nil
- Encoding.default_external = extern unless extern.nil? || extern == ""
- Encoding.default_internal = intern unless intern.nil? || intern == ""
- [$stdin, $stdout, $stderr].each do |io|
- io.set_encoding(extern, intern)
- end
- ensure
- $VERBOSE = verbose
- end
- module_function :set_encoding
- class << self; private :set_encoding; end
+#
+# This file was generated by RubyGems.
+#
+# The application 'erb' is installed as part of a gem, and
+# this file is here to facilitate running it.
+#
+
+require 'rubygems'
+
+version = ">= 0.a"
+
+str = ARGV.first
+if str
+ str = str.b[/\A_(.*)_\z/, 1]
+ if str and Gem::Version.correct?(str)
+ version = str
+ ARGV.shift
end
end
-if __FILE__ == $0
- ERB::Main.run
+if Gem.respond_to?(:activate_bin_path)
+load Gem.activate_bin_path('erb', 'erb', version)
+else
+gem "erb", version
+load Gem.bin_path("erb", "erb", version)
end
diff --git a/bin/racc2y b/bin/racc2y
deleted file mode 100755
index a1e4352632..0000000000
--- a/bin/racc2y
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env ruby
-#
-# This file was generated by RubyGems.
-#
-# The application 'racc' is installed as part of a gem, and
-# this file is here to facilitate running it.
-#
-
-require 'rubygems'
-
-version = ">= 0.a"
-
-if ARGV.first
- str = ARGV.first
- str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
- if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then
- version = $1
- ARGV.shift
- end
-end
-
-if Gem.respond_to?(:activate_bin_path)
-load Gem.activate_bin_path('racc', 'racc2y', version)
-else
-gem "racc", version
-load Gem.bin_path("racc", "racc2y", version)
-end
diff --git a/bin/y2racc b/bin/y2racc
deleted file mode 100755
index 023615f369..0000000000
--- a/bin/y2racc
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env ruby
-#
-# This file was generated by RubyGems.
-#
-# The application 'racc' is installed as part of a gem, and
-# this file is here to facilitate running it.
-#
-
-require 'rubygems'
-
-version = ">= 0.a"
-
-if ARGV.first
- str = ARGV.first
- str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding
- if str =~ /\A_(.*)_\z/ and Gem::Version.correct?($1) then
- version = $1
- ARGV.shift
- end
-end
-
-if Gem.respond_to?(:activate_bin_path)
-load Gem.activate_bin_path('racc', 'y2racc', version)
-else
-gem "racc", version
-load Gem.bin_path("racc", "y2racc", version)
-end
diff --git a/bootstraptest/pending.rb b/bootstraptest/pending.rb
index 0959bfa2b0..2c4b85a419 100644
--- a/bootstraptest/pending.rb
+++ b/bootstraptest/pending.rb
@@ -1,19 +1,3 @@
-assert_equal 'A', %q{
- class A
- @@a = 'A'
- def a=(x)
- @@a = x
- end
- def a
- @@a
- end
- end
-
- B = A.dup
- B.new.a = 'B'
- A.new.a
-}, '[ruby-core:17019]'
-
assert_equal 'ok', %q{
def m
lambda{
@@ -31,13 +15,6 @@ assert_equal 'ok', %q{
end
}
-assert_normal_exit %q{
- r = Range.allocate
- def r.<=>(o) true end
- r.instance_eval { initialize r, r }
- r.inspect
-}
-
# This randomly fails on mswin.
assert_equal %q{[]}, %q{
Thread.new{sleep}.backtrace
diff --git a/bootstraptest/runner.rb b/bootstraptest/runner.rb
index 56b4b12230..2cd91ffd07 100755
--- a/bootstraptest/runner.rb
+++ b/bootstraptest/runner.rb
@@ -261,6 +261,14 @@ rescue Exception => err
$stderr.print 'E'
$stderr.puts if @verbose
error err.message, message
+ensure
+ begin
+ check_coredump
+ rescue CoreDumpError => err
+ $stderr.print 'E'
+ $stderr.puts if @verbose
+ error err.message, message
+ end
end
def show_limit(testsrc, opt = '', **argh)
@@ -275,7 +283,6 @@ end
def assert_check(testsrc, message = '', opt = '', **argh)
show_progress(message) {
result = get_result_string(testsrc, opt, **argh)
- check_coredump
yield(result)
}
end
@@ -376,8 +383,8 @@ def assert_normal_exit(testsrc, *rest, timeout: nil, **opt)
end
def assert_finish(timeout_seconds, testsrc, message = '')
- if RubyVM.const_defined? :MJIT
- timeout_seconds *= 3 if RubyVM::MJIT.enabled? # for --jit-wait
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
+ timeout_seconds *= 3
end
newtest
show_progress(message) {
@@ -453,7 +460,6 @@ def get_result_string(src, opt = '', **argh)
`#{@ruby} -W0 #{opt} #{filename}`
ensure
raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"]
- raise CoreDumpError, "core dumped" if $? and $?.coredump?
end
else
eval(src).to_s
@@ -513,7 +519,21 @@ def in_temporary_working_directory(dir)
end
def cleanup_coredump
- FileUtils.rm_f 'core'
+ if File.file?('core')
+ require 'time'
+ Dir.glob('/tmp/bootstraptest-core.*').each do |f|
+ if Time.now - File.mtime(f) > 7 * 24 * 60 * 60 # 7 days
+ warn "Deleting an old core file: #{f}"
+ FileUtils.rm(f)
+ end
+ end
+ core_path = "/tmp/bootstraptest-core.#{Time.now.utc.iso8601}"
+ warn "A core file is found. Saving it at: #{core_path.dump}"
+ FileUtils.mv('core', core_path)
+ cmd = ['gdb', @ruby, '-c', core_path, '-ex', 'bt', '-batch']
+ p cmd # debugging why it's not working
+ system(*cmd)
+ end
FileUtils.rm_f Dir.glob('core.*')
FileUtils.rm_f @ruby+'.stackdump' if @ruby
end
diff --git a/bootstraptest/test_eval.rb b/bootstraptest/test_eval.rb
index fa04323b7f..5d2593c306 100644
--- a/bootstraptest/test_eval.rb
+++ b/bootstraptest/test_eval.rb
@@ -250,7 +250,9 @@ assert_equal 'ok', %q{
assert_equal 'ok', %q{
begin
- 12.instance_eval { @@a }
+ class A
+ 12.instance_eval { @@a }
+ end
rescue NameError
:ok
end
@@ -258,7 +260,9 @@ assert_equal 'ok', %q{
assert_equal 'ok', %q{
begin
- 12.instance_exec { @@a }
+ class A
+ 12.instance_exec { @@a }
+ end
rescue NameError
:ok
end
diff --git a/bootstraptest/test_flow.rb b/bootstraptest/test_flow.rb
index 9da6d45cbd..35f19db588 100644
--- a/bootstraptest/test_flow.rb
+++ b/bootstraptest/test_flow.rb
@@ -534,11 +534,11 @@ assert_equal %Q{ENSURE\n}, %q{
['[ruby-core:39125]', %q{
class Bug5234
include Enumerable
- def each
+ def each(&block)
begin
yield :foo
ensure
- proc
+ proc(&block)
end
end
end
@@ -547,11 +547,11 @@ assert_equal %Q{ENSURE\n}, %q{
['[ruby-dev:45656]', %q{
class Bug6460
include Enumerable
- def each
+ def each(&block)
begin
yield :foo
ensure
- 1.times { Proc.new }
+ 1.times { Proc.new(&block) }
end
end
end
diff --git a/bootstraptest/test_insns.rb b/bootstraptest/test_insns.rb
index 1269d7d013..9052cad7bd 100644
--- a/bootstraptest/test_insns.rb
+++ b/bootstraptest/test_insns.rb
@@ -64,8 +64,8 @@ tests = [
[ 'setinstancevariable', %q{ @x = true }, ],
[ 'getinstancevariable', %q{ @x = true; @x }, ],
- [ 'setclassvariable', %q{ @@x = true }, ],
- [ 'getclassvariable', %q{ @@x = true; @@x }, ],
+ [ 'setclassvariable', %q{ class A; @@x = true; end }, ],
+ [ 'getclassvariable', %q{ class A; @@x = true; @@x end }, ],
[ 'setconstant', %q{ X = true }, ],
[ 'setconstant', %q{ Object::X = true }, ],
@@ -86,11 +86,8 @@ tests = [
[ 'putobject', %q{ /(?<x>x)/ =~ "x"; x == "x" }, ],
[ 'putspecialobject', %q{ {//=>true}[//] }, ],
- [ 'putiseq', %q{ -> { true }.() }, ],
[ 'putstring', %q{ "true" }, ],
[ 'tostring / concatstrings', %q{ "#{true}" }, ],
- [ 'freezestring', %q{ "#{true}" }, fsl, ],
- [ 'freezestring', %q{ "#{true}" }, '-d', fsl, ],
[ 'toregexp', %q{ /#{true}/ =~ "true" && $~ }, ],
[ 'intern', %q{ :"#{true}" }, ],
@@ -394,7 +391,6 @@ tests = [
[ 'opt_succ',%Q{ #{ $FIXNUM_MAX }.succ == #{ $FIXNUM_MAX + 1 } }, ]
end,
[ 'opt_succ', %q{ '1'.succ == '2' }, ],
- [ 'opt_succ', %q{ x = Time.at(0); x.succ == Time.at(1) }, ],
[ 'opt_not', %q{ ! false }, ],
[ 'opt_neq', <<-'},', ], # {
@@ -412,8 +408,6 @@ tests = [
class String; def =~ other; true; end; end
'true' =~ /true/
},
-
- [ 'opt_call_c_function', 'Struct.new(:x).new.x = true', ],
]
# normal path
@@ -438,3 +432,8 @@ tests.compact.each {|(insn, expr, *a)|
assert_equal 'true', progn, 'trace_' + insn, *a
end
}
+
+assert_normal_exit("#{<<-"begin;"}\n#{<<-'end;'}")
+begin;
+ RubyVM::InstructionSequence.compile("", debug_level: 5)
+end;
diff --git a/bootstraptest/test_jump.rb b/bootstraptest/test_jump.rb
index 7944915862..18a2737ea3 100644
--- a/bootstraptest/test_jump.rb
+++ b/bootstraptest/test_jump.rb
@@ -296,14 +296,19 @@ assert_equal "true", %q{
s.return_eigenclass == class << s; self; end
}, '[ruby-core:21379]'
-assert_equal "true", %q{
- class Object
- def yield_eigenclass
- class << self
- yield self
+assert_match %r{Invalid yield}, %q{
+STDERR.reopen(STDOUT)
+begin
+ eval %q{
+ class Object
+ def yield_eigenclass
+ class << self
+ yield self
+ end
end
end
- end
- s = "foo"
- s.yield_eigenclass {|c| c == class << s; self; end }
-}, '[ruby-dev:40975]'
+ }
+rescue SyntaxError => e
+ e.message
+end
+}
diff --git a/bootstraptest/test_proc.rb b/bootstraptest/test_proc.rb
index 1e384411dc..637603243d 100644
--- a/bootstraptest/test_proc.rb
+++ b/bootstraptest/test_proc.rb
@@ -225,19 +225,6 @@ assert_equal %q{[[nil, []], [1, []], [1, [2]], [1, [2, 3]]]}, %q{
]
}
assert_equal %q{1}, %q{
- pr = proc{
- $SAFE
- }
- $SAFE = 1
- pr.call
-}
-assert_equal %q{[1, 1]}, %q{
- pr = proc{
- $SAFE += 1
- }
- [pr.call, $SAFE]
-}
-assert_equal %q{1}, %q{
def m(&b)
b
end
@@ -380,8 +367,8 @@ assert_equal 'ok', %q{
assert_equal 'ok', %q{
class Foo
- def call_it
- p = Proc.new
+ def call_it(&block)
+ p = Proc.new(&block)
p.call
end
end
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
new file mode 100644
index 0000000000..7d920c31b5
--- /dev/null
+++ b/bootstraptest/test_ractor.rb
@@ -0,0 +1,1444 @@
+# Ractor.current returns a current ractor
+assert_equal 'Ractor', %q{
+ Ractor.current.class
+}
+
+# Ractor.new returns new Ractor
+assert_equal 'Ractor', %q{
+ Ractor.new{}.class
+}
+
+# Ractor.allocate is not supported
+assert_equal "[:ok, :ok]", %q{
+ rs = []
+ begin
+ Ractor.allocate
+ rescue => e
+ rs << :ok if e.message == 'allocator undefined for Ractor'
+ end
+
+ begin
+ Ractor.new{}.dup
+ rescue
+ rs << :ok if e.message == 'allocator undefined for Ractor'
+ end
+
+ rs
+}
+
+# A Ractor can have a name
+assert_equal 'test-name', %q{
+ r = Ractor.new name: 'test-name' do
+ end
+ r.name
+}
+
+# If Ractor doesn't have a name, Ractor#name returns nil.
+assert_equal 'nil', %q{
+ r = Ractor.new do
+ end
+ r.name.inspect
+}
+
+# Raises exceptions if initialize with an invalid name
+assert_equal 'ok', %q{
+ begin
+ r = Ractor.new(name: [{}]) {}
+ rescue TypeError => e
+ 'ok'
+ end
+}
+
+# Ractor.new must call with a block
+assert_equal "must be called with a block", %q{
+ begin
+ Ractor.new
+ rescue ArgumentError => e
+ e.message
+ end
+}
+
+# Ractor#inspect
+# Return only id and status for main ractor
+assert_equal "#<Ractor:#1 running>", %q{
+ Ractor.current.inspect
+}
+
+# Return id, loc, and status for no-name ractor
+assert_match /^#<Ractor:#([^ ]*?) .+:[0-9]+ terminated>$/, %q{
+ r = Ractor.new { '' }
+ r.take
+ sleep 0.1 until r.inspect =~ /terminated/
+ r.inspect
+}
+
+# Return id, name, loc, and status for named ractor
+assert_match /^#<Ractor:#([^ ]*?) Test Ractor .+:[0-9]+ terminated>$/, %q{
+ r = Ractor.new(name: 'Test Ractor') { '' }
+ r.take
+ sleep 0.1 until r.inspect =~ /terminated/
+ r.inspect
+}
+
+# A return value of a Ractor block will be a message from the Ractor.
+assert_equal 'ok', %q{
+ # join
+ r = Ractor.new do
+ 'ok'
+ end
+ r.take
+}
+
+# Passed arguments to Ractor.new will be a block parameter
+# The values are passed with Ractor-communication pass.
+assert_equal 'ok', %q{
+ # ping-pong with arg
+ r = Ractor.new 'ok' do |msg|
+ msg
+ end
+ r.take
+}
+
+# Pass multiple arguments to Ractor.new
+assert_equal 'ok', %q{
+ # ping-pong with two args
+ r = Ractor.new 'ping', 'pong' do |msg, msg2|
+ [msg, msg2]
+ end
+ 'ok' if r.take == ['ping', 'pong']
+}
+
+# Ractor#send passes an object with copy to a Ractor
+# and Ractor.receive in the Ractor block can receive the passed value.
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ msg = Ractor.receive
+ end
+ r.send 'ok'
+ r.take
+}
+
+# Ractor#receive_if can filter the message
+assert_equal '[2, 3, 1]', %q{
+ r = Ractor.new Ractor.current do |main|
+ main << 1
+ main << 2
+ main << 3
+ end
+ a = []
+ a << Ractor.receive_if{|msg| msg == 2}
+ a << Ractor.receive_if{|msg| msg == 3}
+ a << Ractor.receive
+}
+
+# Ractor#receive_if with break
+assert_equal '[2, [1, :break], 3]', %q{
+ r = Ractor.new Ractor.current do |main|
+ main << 1
+ main << 2
+ main << 3
+ end
+
+ a = []
+ a << Ractor.receive_if{|msg| msg == 2}
+ a << Ractor.receive_if{|msg| break [msg, :break]}
+ a << Ractor.receive
+}
+
+# Ractor#receive_if can't be called recursively
+assert_equal '[[:e1, 1], [:e2, 2]]', %q{
+ r = Ractor.new Ractor.current do |main|
+ main << 1
+ main << 2
+ main << 3
+ end
+
+ a = []
+
+ Ractor.receive_if do |msg|
+ begin
+ Ractor.receive
+ rescue Ractor::Error
+ a << [:e1, msg]
+ end
+ true # delete 1 from queue
+ end
+
+ Ractor.receive_if do |msg|
+ begin
+ Ractor.receive_if{}
+ rescue Ractor::Error
+ a << [:e2, msg]
+ end
+ true # delete 2 from queue
+ end
+
+ a #
+}
+
+# dtoa race condition
+assert_equal '[:ok, :ok, :ok]', %q{
+ n = 3
+ n.times.map{
+ Ractor.new{
+ 10_000.times{ rand.to_s }
+ :ok
+ }
+ }.map(&:take)
+}
+
+# Ractor.make_shareable issue for locals in proc [Bug #18023]
+assert_equal '[:a, :b, :c, :d, :e]', %q{
+ v1, v2, v3, v4, v5 = :a, :b, :c, :d, :e
+ closure = Proc.new { [v1, v2, v3, v4, v5] }
+
+ Ractor.make_shareable(closure).call
+}
+
+# Ractor.make_shareable issue for locals in proc [Bug #18023]
+assert_equal '[:a, :b, :c, :d, :e, :f, :g]', %q{
+ a = :a
+ closure = -> {
+ b, c, d = :b, :c, :d
+ -> {
+ e, f, g = :e, :f, :g
+ -> { [a, b, c, d, e, f, g] }
+ }.call
+ }.call
+
+ Ractor.make_shareable(closure).call
+}
+
+###
+###
+# Ractor still has several memory corruption so skip huge number of tests
+if ENV['GITHUB_WORKFLOW'] &&
+ ENV['GITHUB_WORKFLOW'] == 'Compilations'
+ # ignore the follow
+else
+
+# Ractor.select(*ractors) receives a values from a ractors.
+# It is similar to select(2) and Go's select syntax.
+# The return value is [ch, received_value]
+assert_equal 'ok', %q{
+ # select 1
+ r1 = Ractor.new{'r1'}
+ r, obj = Ractor.select(r1)
+ 'ok' if r == r1 and obj == 'r1'
+}
+
+# Ractor.select from two ractors.
+assert_equal '["r1", "r2"]', %q{
+ # select 2
+ r1 = Ractor.new{'r1'}
+ r2 = Ractor.new{'r2'}
+ rs = [r1, r2]
+ as = []
+ r, obj = Ractor.select(*rs)
+ rs.delete(r)
+ as << obj
+ r, obj = Ractor.select(*rs)
+ as << obj
+ as.sort #=> ["r1", "r2"]
+}
+
+# Ractor.select from multiple ractors.
+assert_equal 30.times.map { 'ok' }.to_s, %q{
+ def test n
+ rs = (1..n).map do |i|
+ Ractor.new(i) do |i|
+ "r#{i}"
+ end
+ end
+ as = []
+ all_rs = rs.dup
+
+ n.times{
+ r, obj = Ractor.select(*rs)
+ as << [r, obj]
+ rs.delete(r)
+ }
+
+ if as.map{|r, o| r.object_id}.sort == all_rs.map{|r| r.object_id}.sort &&
+ as.map{|r, o| o}.sort == (1..n).map{|i| "r#{i}"}.sort
+ 'ok'
+ else
+ 'ng'
+ end
+ end
+
+ 30.times.map{|i|
+ test i
+ }
+} unless ENV['RUN_OPTS'] =~ /--jit-min-calls=5/ # This always fails with --jit-wait --jit-min-calls=5
+
+# Exception for empty select
+assert_match /specify at least one ractor/, %q{
+ begin
+ Ractor.select
+ rescue ArgumentError => e
+ e.message
+ end
+}
+
+# Outgoing port of a ractor will be closed when the Ractor is terminated.
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ 'finish'
+ end
+
+ r.take
+ sleep 0.1 until r.inspect =~ /terminated/
+
+ begin
+ o = r.take
+ rescue Ractor::ClosedError
+ 'ok'
+ else
+ "ng: #{o}"
+ end
+}
+
+# Raise Ractor::ClosedError when try to send into a terminated ractor
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ end
+
+ r.take # closed
+ sleep 0.1 until r.inspect =~ /terminated/
+
+ begin
+ r.send(1)
+ rescue Ractor::ClosedError
+ 'ok'
+ else
+ 'ng'
+ end
+}
+
+# Raise Ractor::ClosedError when try to send into a closed actor
+assert_equal 'ok', %q{
+ r = Ractor.new { Ractor.receive }
+ r.close_incoming
+
+ begin
+ r.send(1)
+ rescue Ractor::ClosedError
+ 'ok'
+ else
+ 'ng'
+ end
+}
+
+# Raise Ractor::ClosedError when try to take from closed actor
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ Ractor.yield 1
+ Ractor.receive
+ end
+
+ r.close_outgoing
+ begin
+ r.take
+ rescue Ractor::ClosedError
+ 'ok'
+ else
+ 'ng'
+ end
+}
+
+# Can mix with Thread#interrupt and Ractor#take [Bug #17366]
+assert_equal 'err', %q{
+ Ractor.new{
+ t = Thread.current
+ begin
+ Thread.new{ t.raise "err" }.join
+ rescue => e
+ e.message
+ end
+ }.take
+}
+
+# Killed Ractor's thread yields nil
+assert_equal 'nil', %q{
+ Ractor.new{
+ t = Thread.current
+ Thread.new{ t.kill }.join
+ }.take.inspect #=> nil
+}
+
+# Ractor.yield raises Ractor::ClosedError when outgoing port is closed.
+assert_equal 'ok', %q{
+ r = Ractor.new Ractor.current do |main|
+ Ractor.receive
+ main << true
+ Ractor.yield 1
+ end
+
+ r.close_outgoing
+ r << true
+ Ractor.receive
+
+ begin
+ r.take
+ rescue Ractor::ClosedError
+ 'ok'
+ else
+ 'ng'
+ end
+}
+
+# Raise Ractor::ClosedError when try to send into a ractor with closed incoming port
+assert_equal 'ok', %q{
+ r = Ractor.new { Ractor.receive }
+ r.close_incoming
+
+ begin
+ r.send(1)
+ rescue Ractor::ClosedError
+ 'ok'
+ else
+ 'ng'
+ end
+}
+
+# A ractor with closed incoming port still can send messages out
+assert_equal '[1, 2]', %q{
+ r = Ractor.new do
+ Ractor.yield 1
+ 2
+ end
+ r.close_incoming
+
+ [r.take, r.take]
+}
+
+# Raise Ractor::ClosedError when try to take from a ractor with closed outgoing port
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ Ractor.yield 1
+ Ractor.receive
+ end
+
+ sleep 0.01 # wait for Ractor.yield in r
+ r.close_outgoing
+ begin
+ r.take
+ rescue Ractor::ClosedError
+ 'ok'
+ else
+ 'ng'
+ end
+}
+
+# A ractor with closed outgoing port still can receive messages from incoming port
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ Ractor.receive
+ end
+
+ r.close_outgoing
+ begin
+ r.send(1)
+ rescue Ractor::ClosedError
+ 'ng'
+ else
+ 'ok'
+ end
+}
+
+# Ractor.main returns main ractor
+assert_equal 'true', %q{
+ Ractor.new{
+ Ractor.main
+ }.take == Ractor.current
+}
+
+# a ractor with closed outgoing port should terminate
+assert_equal 'ok', %q{
+ Ractor.new do
+ close_outgoing
+ end
+
+ true until Ractor.count == 1
+ :ok
+}
+
+# multiple Ractors can receive (wait) from one Ractor
+assert_equal '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]', %q{
+ pipe = Ractor.new do
+ loop do
+ Ractor.yield Ractor.receive
+ end
+ end
+
+ RN = 10
+ rs = RN.times.map{|i|
+ Ractor.new pipe, i do |pipe, i|
+ msg = pipe.take
+ msg # ping-pong
+ end
+ }
+ RN.times{|i|
+ pipe << i
+ }
+ RN.times.map{
+ r, n = Ractor.select(*rs)
+ rs.delete r
+ n
+ }.sort
+}
+
+# Ractor.select also support multiple take, receive and yield
+assert_equal '[true, true, true]', %q{
+ RN = 10
+ CR = Ractor.current
+
+ rs = (1..RN).map{
+ Ractor.new do
+ CR.send 'send' + CR.take #=> 'sendyield'
+ 'take'
+ end
+ }
+ received = []
+ take = []
+ yielded = []
+ until rs.empty?
+ r, v = Ractor.select(CR, *rs, yield_value: 'yield')
+ case r
+ when :receive
+ received << v
+ when :yield
+ yielded << v
+ else
+ take << v
+ rs.delete r
+ end
+ end
+ [received.all?('sendyield'), yielded.all?(nil), take.all?('take')]
+}
+
+# multiple Ractors can send to one Ractor
+assert_equal '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]', %q{
+ pipe = Ractor.new do
+ loop do
+ Ractor.yield Ractor.receive
+ end
+ end
+
+ RN = 10
+ RN.times.map{|i|
+ Ractor.new pipe, i do |pipe, i|
+ pipe << i
+ end
+ }
+ RN.times.map{
+ pipe.take
+ }.sort
+}
+
+# an exception in a Ractor will be re-raised at Ractor#receive
+assert_equal '[RuntimeError, "ok", true]', %q{
+ r = Ractor.new do
+ raise 'ok' # exception will be transferred receiver
+ end
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ [e.cause.class, #=> RuntimeError
+ e.cause.message, #=> 'ok'
+ e.ractor == r] #=> true
+ end
+}
+
+# threads in a ractor will killed
+assert_equal '{:ok=>3}', %q{
+ Ractor.new Ractor.current do |main|
+ q = Queue.new
+ Thread.new do
+ q << true
+ loop{}
+ ensure
+ main << :ok
+ end
+
+ Thread.new do
+ q << true
+ while true
+ end
+ ensure
+ main << :ok
+ end
+
+ Thread.new do
+ q << true
+ sleep 1
+ ensure
+ main << :ok
+ end
+
+ # wait for the start of all threads
+ 3.times{q.pop}
+ end
+
+ 3.times.map{Ractor.receive}.tally
+}
+
+# unshareable object are copied
+assert_equal 'false', %q{
+ obj = 'str'.dup
+ r = Ractor.new obj do |msg|
+ msg.object_id
+ end
+
+ obj.object_id == r.take
+}
+
+# To copy the object, now Marshal#dump is used
+assert_equal "allocator undefined for Thread", %q{
+ obj = Thread.new{}
+ begin
+ r = Ractor.new obj do |msg|
+ msg
+ end
+ rescue TypeError => e
+ e.message #=> no _dump_data is defined for class Thread
+ else
+ 'ng'
+ end
+}
+
+# send shareable and unshareable objects
+assert_equal "ok", %q{
+ echo_ractor = Ractor.new do
+ loop do
+ v = Ractor.receive
+ Ractor.yield v
+ end
+ end
+
+ class C; end
+ module M; end
+ S = Struct.new(:a, :b, :c, :d)
+
+ shareable_objects = [
+ true,
+ false,
+ nil,
+ 1,
+ 1.1, # Float
+ 1+2r, # Rational
+ 3+4i, # Complex
+ 2**128, # Bignum
+ :sym, # Symbol
+ 'xyzzy'.to_sym, # dynamic symbol
+ 'frozen'.freeze, # frozen String
+ /regexp/, # regexp literal
+ /reg{true}exp/.freeze, # frozen dregexp
+ [1, 2].freeze, # frozen Array which only refers to shareable
+ {a: 1}.freeze, # frozen Hash which only refers to shareable
+ [{a: 1}.freeze, 'str'.freeze].freeze, # nested frozen container
+ S.new(1, 2).freeze, # frozen Struct
+ S.new(1, 2, 3, 4).freeze, # frozen Struct
+ (1..2), # Range on Struct
+ (1..), # Range on Struct
+ (..1), # Range on Struct
+ C, # class
+ M, # module
+ Ractor.current, # Ractor
+ ]
+
+ unshareable_objects = [
+ 'mutable str'.dup,
+ [:array],
+ {hash: true},
+ S.new(1, 2),
+ S.new(1, 2, 3, 4),
+ S.new("a", 2).freeze, # frozen, but refers to an unshareable object
+ ]
+
+ results = []
+
+ shareable_objects.map{|o|
+ echo_ractor << o
+ o2 = echo_ractor.take
+ results << "#{o} is copied" unless o.object_id == o2.object_id
+ }
+
+ unshareable_objects.map{|o|
+ echo_ractor << o
+ o2 = echo_ractor.take
+ results << "#{o.inspect} is not copied" if o.object_id == o2.object_id
+ }
+
+ if results.empty?
+ :ok
+ else
+ results.inspect
+ end
+}
+
+# frozen Objects are shareable
+assert_equal [false, true, false].inspect, %q{
+ class C
+ def initialize freeze
+ @a = 1
+ @b = :sym
+ @c = 'frozen_str'
+ @c.freeze if freeze
+ @d = true
+ end
+ end
+
+ def check obj1
+ obj2 = Ractor.new obj1 do |obj|
+ obj
+ end.take
+
+ obj1.object_id == obj2.object_id
+ end
+
+ results = []
+ results << check(C.new(true)) # false
+ results << check(C.new(true).freeze) # true
+ results << check(C.new(false).freeze) # false
+}
+
+# move example2: String
+# touching moved object causes an error
+assert_equal 'hello world', %q{
+ # move
+ r = Ractor.new do
+ obj = Ractor.receive
+ obj << ' world'
+ end
+
+ str = 'hello'
+ r.send str, move: true
+ modified = r.take
+
+ begin
+ str << ' exception' # raise Ractor::MovedError
+ rescue Ractor::MovedError
+ modified #=> 'hello world'
+ else
+ raise 'unreachable'
+ end
+}
+
+# move example2: Array
+assert_equal '[0, 1]', %q{
+ r = Ractor.new do
+ ary = Ractor.receive
+ ary << 1
+ end
+
+ a1 = [0]
+ r.send a1, move: true
+ a2 = r.take
+ begin
+ a1 << 2 # raise Ractor::MovedError
+ rescue Ractor::MovedError
+ a2.inspect
+ end
+}
+
+# move with yield
+assert_equal 'hello', %q{
+ r = Ractor.new do
+ Thread.current.report_on_exception = false
+ obj = 'hello'
+ Ractor.yield obj, move: true
+ obj << 'world'
+ end
+
+ str = r.take
+ begin
+ r.take
+ rescue Ractor::RemoteError
+ str #=> "hello"
+ end
+}
+
+# yield/move should not make moved object when the yield is not succeeded
+assert_equal '"str"', %q{
+ R = Ractor.new{}
+ M = Ractor.current
+ r = Ractor.new do
+ s = 'str'
+ selected_r, v = Ractor.select R, yield_value: s, move: true
+ raise if selected_r != R # taken from R
+ M.send s.inspect # s should not be a moved object
+ end
+
+ Ractor.receive
+}
+
+# yield/move can fail
+assert_equal "allocator undefined for Thread", %q{
+ r = Ractor.new do
+ obj = Thread.new{}
+ Ractor.yield obj
+ rescue => e
+ e.message
+ end
+ r.take
+}
+
+# Access to global-variables are prohibited
+assert_equal 'can not access global variables $gv from non-main Ractors', %q{
+ $gv = 1
+ r = Ractor.new do
+ $gv
+ end
+
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# Access to global-variables are prohibited
+assert_equal 'can not access global variables $gv from non-main Ractors', %q{
+ r = Ractor.new do
+ $gv = 1
+ end
+
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# $stdin,out,err is Ractor local, but shared fds
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ [$stdin, $stdout, $stderr].map{|io|
+ [io.object_id, io.fileno]
+ }
+ end
+
+ [$stdin, $stdout, $stderr].zip(r.take){|io, (oid, fno)|
+ raise "should not be different object" if io.object_id == oid
+ raise "fd should be same" unless io.fileno == fno
+ }
+ 'ok'
+}
+
+# $stdin,out,err belong to Ractor
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ $stdin.itself
+ $stdout.itself
+ $stderr.itself
+ 'ok'
+ end
+
+ r.take
+}
+
+# $DEBUG, $VERBOSE are Ractor local
+assert_equal 'true', %q{
+ $DEBUG = true
+ $VERBOSE = true
+
+ def ractor_local_globals
+ /a(b)(c)d/ =~ 'abcd' # for $~
+ `echo foo` unless /solaris/ =~ RUBY_PLATFORM
+
+ {
+ # ractor-local (derived from created ractor): debug
+ '$DEBUG' => $DEBUG,
+ '$-d' => $-d,
+
+ # ractor-local (derived from created ractor): verbose
+ '$VERBOSE' => $VERBOSE,
+ '$-w' => $-w,
+ '$-W' => $-W,
+ '$-v' => $-v,
+
+ # process-local (readonly): other commandline parameters
+ '$-p' => $-p,
+ '$-l' => $-l,
+ '$-a' => $-a,
+
+ # process-local (readonly): getpid
+ '$$' => $$,
+
+ # thread local: process result
+ '$?' => $?,
+
+ # scope local: match
+ '$~' => $~.inspect,
+ '$&' => $&,
+ '$`' => $`,
+ '$\'' => $',
+ '$+' => $+,
+ '$1' => $1,
+
+ # scope local: last line
+ '$_' => $_,
+
+ # scope local: last backtrace
+ '$@' => $@,
+ '$!' => $!,
+
+ # ractor local: stdin, out, err
+ '$stdin' => $stdin.inspect,
+ '$stdout' => $stdout.inspect,
+ '$stderr' => $stderr.inspect,
+ }
+ end
+
+ h = Ractor.new do
+ ractor_local_globals
+ end.take
+ ractor_local_globals == h #=> true
+}
+
+# selfs are different objects
+assert_equal 'false', %q{
+ r = Ractor.new do
+ self.object_id
+ end
+ r.take == self.object_id #=> false
+}
+
+# self is a Ractor instance
+assert_equal 'true', %q{
+ r = Ractor.new do
+ self.object_id
+ end
+ r.object_id == r.take #=> true
+}
+
+# given block Proc will be isolated, so can not access outer variables.
+assert_equal 'ArgumentError', %q{
+ begin
+ a = true
+ r = Ractor.new do
+ a
+ end
+ rescue => e
+ e.class
+ end
+}
+
+# ivar in shareable-objects are not allowed to access from non-main Ractor
+assert_equal 'can not access instance variables of classes/modules from non-main Ractors', %q{
+ class C
+ @iv = 'str'
+ end
+
+ r = Ractor.new do
+ class C
+ p @iv
+ end
+ end
+
+
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# ivar in shareable-objects are not allowed to access from non-main Ractor
+assert_equal 'can not access instance variables of shareable objects from non-main Ractors', %q{
+ shared = Ractor.new{}
+ shared.instance_variable_set(:@iv, 'str')
+
+ r = Ractor.new shared do |shared|
+ p shared.instance_variable_get(:@iv)
+ end
+
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# ivar in shareable-objects are not allowed to access from non-main Ractor, by @iv (get)
+assert_equal 'can not access instance variables of shareable objects from non-main Ractors', %q{
+ class Ractor
+ def setup
+ @foo = ''
+ end
+
+ def foo
+ @foo
+ end
+ end
+
+ shared = Ractor.new{}
+ shared.setup
+
+ r = Ractor.new shared do |shared|
+ p shared.foo
+ end
+
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# ivar in shareable-objects are not allowed to access from non-main Ractor, by @iv (set)
+assert_equal 'can not access instance variables of shareable objects from non-main Ractors', %q{
+ class Ractor
+ def setup
+ @foo = ''
+ end
+ end
+
+ shared = Ractor.new{}
+
+ r = Ractor.new shared do |shared|
+ p shared.setup
+ end
+
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# But a shareable object is frozen, it is allowed to access ivars from non-main Ractor
+assert_equal '11', %q{
+ [Object.new, [], ].map{|obj|
+ obj.instance_variable_set('@a', 1)
+ Ractor.make_shareable obj = obj.freeze
+
+ Ractor.new obj do |obj|
+ obj.instance_variable_get('@a')
+ end.take.to_s
+ }.join
+}
+
+# cvar in shareable-objects are not allowed to access from non-main Ractor
+assert_equal 'can not access class variables from non-main Ractors', %q{
+ class C
+ @@cv = 'str'
+ end
+
+ r = Ractor.new do
+ class C
+ p @@cv
+ end
+ end
+
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# Getting non-shareable objects via constants by other Ractors is not allowed
+assert_equal 'can not access non-shareable objects in constant C::CONST by non-main Ractor.', %q{
+ class C
+ CONST = 'str'
+ end
+ r = Ractor.new do
+ C::CONST
+ end
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# Constant cache should care about non-sharable constants
+assert_equal "can not access non-shareable objects in constant Object::STR by non-main Ractor.", %q{
+ STR = "hello"
+ def str; STR; end
+ s = str() # fill const cache
+ begin
+ Ractor.new{ str() }.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# Setting non-shareable objects into constants by other Ractors is not allowed
+assert_equal 'can not set constants with non-shareable objects by non-main Ractors', %q{
+ class C
+ end
+ r = Ractor.new do
+ C::CONST = 'str'
+ end
+ begin
+ r.take
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+# define_method is not allowed
+assert_equal "defined in a different Ractor", %q{
+ str = "foo"
+ define_method(:buggy){|i| str << "#{i}"}
+ begin
+ Ractor.new{buggy(10)}.take
+ rescue => e
+ e.cause.message
+ end
+}
+
+# Immutable Array and Hash are shareable, so it can be shared with constants
+assert_equal '[1000, 3]', %q{
+ A = Array.new(1000).freeze # [nil, ...]
+ H = {a: 1, b: 2, c: 3}.freeze
+
+ Ractor.new{ [A.size, H.size] }.take
+}
+
+# Ractor.count
+assert_equal '[1, 4, 3, 2, 1]', %q{
+ counts = []
+ counts << Ractor.count
+ ractors = (1..3).map { Ractor.new { Ractor.receive } }
+ counts << Ractor.count
+
+ ractors[0].send('End 0').take
+ sleep 0.1 until ractors[0].inspect =~ /terminated/
+ counts << Ractor.count
+
+ ractors[1].send('End 1').take
+ sleep 0.1 until ractors[1].inspect =~ /terminated/
+ counts << Ractor.count
+
+ ractors[2].send('End 2').take
+ sleep 0.1 until ractors[2].inspect =~ /terminated/
+ counts << Ractor.count
+
+ counts.inspect
+}
+
+# ObjectSpace.each_object can not handle unshareable objects with Ractors
+assert_equal '0', %q{
+ Ractor.new{
+ n = 0
+ ObjectSpace.each_object{|o| n += 1 unless Ractor.shareable?(o)}
+ n
+ }.take
+}
+
+# ObjectSpace._id2ref can not handle unshareable objects with Ractors
+assert_equal 'ok', %q{
+ s = 'hello'
+
+ Ractor.new s.object_id do |id ;s|
+ begin
+ s = ObjectSpace._id2ref(id)
+ rescue => e
+ :ok
+ end
+ end.take
+}
+
+# Ractor.make_shareable(obj)
+assert_equal 'true', %q{
+ class C
+ def initialize
+ @a = 'foo'
+ @b = 'bar'
+ end
+
+ def freeze
+ @c = [:freeze_called]
+ super
+ end
+
+ attr_reader :a, :b, :c
+ end
+ S = Struct.new(:s1, :s2)
+ str = "hello"
+ str.instance_variable_set("@iv", "hello")
+ /a/ =~ 'a'
+ m = $~
+ class N < Numeric
+ def /(other)
+ 1
+ end
+ end
+ ary = []; ary << ary
+
+ a = [[1, ['2', '3']],
+ {Object.new => "hello"},
+ C.new,
+ S.new("x", "y"),
+ ("a".."b"),
+ str,
+ ary, # cycle
+ /regexp/,
+ /#{'r'.upcase}/,
+ m,
+ Complex(N.new,0),
+ Rational(N.new,0),
+ true,
+ false,
+ nil,
+ 1, 1.2, 1+3r, 1+4i, # Numeric
+ ]
+ Ractor.make_shareable(a)
+
+ # check all frozen
+ a.each{|o|
+ raise o.inspect unless o.frozen?
+
+ case o
+ when C
+ raise o.a.inspect unless o.a.frozen?
+ raise o.b.inspect unless o.b.frozen?
+ raise o.c.inspect unless o.c.frozen? && o.c == [:freeze_called]
+ when Rational
+ raise o.numerator.inspect unless o.numerator.frozen?
+ when Complex
+ raise o.real.inspect unless o.real.frozen?
+ when Array
+ if o[0] == 1
+ raise o[1][1].inspect unless o[1][1].frozen?
+ end
+ when Hash
+ o.each{|k, v|
+ raise k.inspect unless k.frozen?
+ raise v.inspect unless v.frozen?
+ }
+ end
+ }
+
+ Ractor.shareable?(a)
+}
+
+# Ractor.make_shareable(obj) doesn't freeze shareable objects
+assert_equal 'true', %q{
+ r = Ractor.new{}
+ Ractor.make_shareable(a = [r])
+ [a.frozen?, a[0].frozen?] == [true, false]
+}
+
+# Ractor.make_shareable(a_proc) makes a proc shareable.
+assert_equal 'true', %q{
+ a = [1, [2, 3], {a: "4"}]
+ pr = Proc.new do
+ a
+ end
+ Ractor.make_shareable(a) # referred value should be shareable
+ Ractor.make_shareable(pr)
+ Ractor.shareable?(pr)
+}
+
+# Ractor.shareable?(recursive_objects)
+assert_equal '[false, false]', %q{
+ y = []
+ x = [y, {}].freeze
+ y << x
+ y.freeze
+ [Ractor.shareable?(x), Ractor.shareable?(y)]
+}
+
+# Ractor.make_shareable(recursive_objects)
+assert_equal '[:ok, false, false]', %q{
+ o = Object.new
+ def o.freeze; raise; end
+ y = []
+ x = [y, o].freeze
+ y << x
+ y.freeze
+ [(Ractor.make_shareable(x) rescue :ok), Ractor.shareable?(x), Ractor.shareable?(y)]
+}
+
+# Ractor.make_shareable with Class/Module
+assert_equal '[C, M]', %q{
+ class C; end
+ module M; end
+
+ Ractor.make_shareable(ary = [C, M])
+}
+
+# define_method() can invoke different Ractor's proc if the proc is shareable.
+assert_equal '1', %q{
+ class C
+ a = 1
+ define_method "foo", Ractor.make_shareable(Proc.new{ a })
+ a = 2
+ end
+
+ Ractor.new{ C.new.foo }.take
+}
+
+# Ractor.make_shareable(a_proc) makes a proc shareable.
+assert_equal 'can not make a Proc shareable because it accesses outer variables (a).', %q{
+ a = b = nil
+ pr = 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
+
+ begin
+ Ractor.make_shareable(pr)
+ rescue => e
+ e.message
+ end
+}
+
+# Ractor.make_shareable(obj, copy: true) makes copied shareable object.
+assert_equal '[false, false, true, true]', %q{
+ r = []
+ o1 = [1, 2, ["3"]]
+
+ o2 = Ractor.make_shareable(o1, copy: true)
+ r << Ractor.shareable?(o1) # false
+ r << (o1.object_id == o2.object_id) # false
+
+ o3 = Ractor.make_shareable(o1)
+ r << Ractor.shareable?(o1) # true
+ r << (o1.object_id == o3.object_id) # false
+ r
+}
+
+# TracePoint with normal Proc should be Ractor local
+assert_equal '[4, 8]', %q{
+ rs = []
+ TracePoint.new(:line){|tp| rs << tp.lineno if tp.path == __FILE__}.enable do
+ Ractor.new{ # line 4
+ a = 1
+ b = 2
+ }.take
+ c = 3 # line 8
+ end
+ rs
+}
+
+# Ractor deep copies frozen objects (ary)
+assert_equal '[true, false]', %q{
+ Ractor.new([[]].freeze) { |ary|
+ [ary.frozen?, ary.first.frozen? ]
+ }.take
+}
+
+# Ractor deep copies frozen objects (str)
+assert_equal '[true, false]', %q{
+ s = String.new.instance_eval { @x = []; freeze}
+ Ractor.new(s) { |s|
+ [s.frozen?, s.instance_variable_get(:@x).frozen?]
+ }.take
+}
+
+# Can not trap with not isolated Proc on non-main ractor
+assert_equal '[:ok, :ok]', %q{
+ a = []
+ Ractor.new{
+ trap(:INT){p :ok}
+ }.take
+ a << :ok
+
+ begin
+ Ractor.new{
+ s = 'str'
+ trap(:INT){p s}
+ }.take
+ rescue => Ractor::RemoteError
+ a << :ok
+ end
+}
+
+# Ractor-local storage
+assert_equal '[nil, "b", "a"]', %q{
+ ans = []
+ Ractor.current[:key] = 'a'
+ r = Ractor.new{
+ Ractor.yield self[:key]
+ self[:key] = 'b'
+ self[:key]
+ }
+ ans << r.take
+ ans << r.take
+ ans << Ractor.current[:key]
+}
+
+###
+### Synchronization tests
+###
+
+N = 100_000
+
+# fstring pool
+assert_equal "#{N}#{N}", %Q{
+ N = #{N}
+ 2.times.map{
+ Ractor.new{
+ N.times{|i| -(i.to_s)}
+ }
+ }.map{|r| r.take}.join
+}
+
+# enc_table
+assert_equal "#{N/10}", %Q{
+ Ractor.new do
+ loop do
+ Encoding.find("test-enc-#{rand(5_000)}").inspect
+ rescue ArgumentError => e
+ end
+ end
+
+ src = Encoding.find("UTF-8")
+ #{N/10}.times{|i|
+ src.replicate("test-enc-\#{i}")
+ }
+}
+
+# Generic ivtbl
+n = N/2
+assert_equal "#{n}#{n}", %Q{
+ 2.times.map{
+ Ractor.new do
+ #{n}.times do
+ obj = ''
+ obj.instance_variable_set("@a", 1)
+ obj.instance_variable_set("@b", 1)
+ obj.instance_variable_set("@c", 1)
+ obj.instance_variable_defined?("@a")
+ end
+ end
+ }.map{|r| r.take}.join
+}
+
+# NameError
+assert_equal "ok", %q{
+ begin
+ bar
+ rescue => err
+ end
+ begin
+ Ractor.new{} << err
+ rescue TypeError
+ 'ok'
+ end
+}
+
+# Can yield back values while GC is sweeping [Bug #18117]
+assert_equal "ok", %q{
+ workers = (0...8).map do
+ Ractor.new do
+ loop do
+ 10_000.times.map { Object.new }
+ Ractor.yield Time.now
+ end
+ end
+ end
+
+ 1_000.times { idle_worker, tmp_reporter = Ractor.select(*workers) }
+ "ok"
+}
+
+end # if !ENV['GITHUB_WORKFLOW']
diff --git a/bootstraptest/test_syntax.rb b/bootstraptest/test_syntax.rb
index a111990a1f..fa27bf2aeb 100644
--- a/bootstraptest/test_syntax.rb
+++ b/bootstraptest/test_syntax.rb
@@ -268,8 +268,10 @@ assert_equal %q{}, %q{
defined?(@@a)
}
assert_equal %q{class variable}, %q{
- @@a = 1
- defined?(@@a)
+ class A
+ @@a = 1
+ defined?(@@a)
+ end
}
assert_equal %q{}, %q{
defined?($a)
diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb
index e7ddadf4a7..38a55ff229 100644
--- a/bootstraptest/test_thread.rb
+++ b/bootstraptest/test_thread.rb
@@ -484,3 +484,17 @@ assert_equal 'foo', %q{
GC.start
f.call.source
}
+assert_normal_exit %q{
+ class C
+ def inspect
+ sleep 0.5
+ 'C!!'
+ end
+ end
+ Thread.new{
+ loop{
+ p C.new
+ }
+ }
+ sleep 0.1
+}, timeout: 5
diff --git a/builtin.c b/builtin.c
index 6de77228d0..7c3653dab7 100644
--- a/builtin.c
+++ b/builtin.c
@@ -12,27 +12,24 @@
#include "builtin_binary.inc"
+static const unsigned char *
+bin4feature(const struct builtin_binary *bb, const char *feature, size_t *psize)
+{
+ *psize = bb->bin_size;
+ return strcmp(bb->feature, feature) ? NULL : bb->bin;
+}
+
static const unsigned char*
builtin_lookup(const char *feature, size_t *psize)
{
static int index = 0;
- int i = index++;
+ const unsigned char *bin = bin4feature(&builtin_binary[index++], feature, psize);
// usually, `builtin_binary` order is loading order at miniruby.
- if (LIKELY(strcmp(builtin_binary[i].feature, feature) == 0)) {
- found:
- *psize = builtin_binary[i].bin_size;
- return builtin_binary[i].bin;
+ for (const struct builtin_binary *bb = &builtin_binary[0]; bb->feature &&! bin; bb++) {
+ bin = bin4feature(bb++, feature, psize);
}
- else {
- if (0) fprintf(stderr, "builtin_lookup: cached index miss (index:%d)\n", i);
- for (i=0; i<BUILTIN_BINARY_SIZE; i++) {
- if (strcmp(builtin_binary[i].feature, feature) == 0) {
- goto found;
- }
- }
- }
- rb_bug("builtin_lookup: can not find %s\n", feature);
+ return bin;
}
void
@@ -41,6 +38,9 @@ rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin
// search binary
size_t size;
const unsigned char *bin = builtin_lookup(feature_name, &size);
+ if (! bin) {
+ rb_bug("builtin_lookup: can not find %s\n", feature_name);
+ }
// load binary
rb_vm_t *vm = GET_VM();
diff --git a/builtin.h b/builtin.h
index f4d485e08d..3b2f477654 100644
--- a/builtin.h
+++ b/builtin.h
@@ -11,19 +11,24 @@ struct rb_builtin_function {
// for load
const int index;
const char * const name;
+
+ // for jit
+ void (*compiler)(FILE *, long, unsigned, bool);
};
-#define RB_BUILTIN_FUNCTION(_i, _name, _fname, _arity) { \
+#define RB_BUILTIN_FUNCTION(_i, _name, _fname, _arity, _compiler) {\
.name = #_name, \
.func_ptr = (void *)_fname, \
.argc = _arity, \
- .index = _i \
+ .index = _i, \
+ .compiler = _compiler, \
}
void rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table);
-#ifndef VM_CORE_H_EC_DEFINED
+#ifndef rb_execution_context_t
typedef struct rb_execution_context_struct rb_execution_context_t;
+#define rb_execution_context_t rb_execution_context_t
#endif
/* The following code is generated by the following Ruby script:
diff --git a/class.c b/class.c
index f17e7f053a..682a21d488 100644
--- a/class.c
+++ b/class.c
@@ -23,12 +23,21 @@
* \{
*/
+#include "ruby/internal/config.h"
+#include <ctype.h>
+
+#include "gc.h"
+#include "constant.h"
+#include "id_table.h"
#include "internal.h"
+#include "internal/class.h"
+#include "internal/eval.h"
+#include "internal/hash.h"
+#include "internal/object.h"
+#include "internal/string.h"
+#include "internal/variable.h"
#include "ruby/st.h"
-#include "constant.h"
#include "vm_core.h"
-#include "id_table.h"
-#include <ctype.h>
#define id_attached id__attached__
@@ -222,7 +231,7 @@ void
rb_check_inheritable(VALUE super)
{
if (!RB_TYPE_P(super, T_CLASS)) {
- rb_raise(rb_eTypeError, "superclass must be a Class (%"PRIsVALUE" given)",
+ rb_raise(rb_eTypeError, "superclass must be an instance of Class (given an instance of %"PRIsVALUE")",
rb_obj_class(super));
}
if (RBASIC(super)->flags & FL_SINGLETON) {
@@ -311,26 +320,9 @@ class_init_copy_check(VALUE clone, VALUE orig)
}
}
-/* :nodoc: */
-VALUE
-rb_mod_init_copy(VALUE clone, VALUE orig)
+static void
+copy_tables(VALUE clone, VALUE orig)
{
- /* cloned flag is refer at constant inline cache
- * see vm_get_const_key_cref() in vm_insnhelper.c
- */
- FL_SET(clone, RCLASS_CLONED);
- FL_SET(orig , RCLASS_CLONED);
-
- if (RB_TYPE_P(clone, T_CLASS)) {
- class_init_copy_check(clone, orig);
- }
- if (!OBJ_INIT_COPY(clone, orig)) return clone;
- if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
- RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
- rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
- }
- RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
- RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator;
if (RCLASS_IV_TBL(clone)) {
st_free_table(RCLASS_IV_TBL(clone));
RCLASS_IV_TBL(clone) = 0;
@@ -358,6 +350,31 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
arg.klass = clone;
rb_id_table_foreach(RCLASS_CONST_TBL(orig), clone_const_i, &arg);
}
+}
+
+static void ensure_origin(VALUE klass);
+
+/* :nodoc: */
+VALUE
+rb_mod_init_copy(VALUE clone, VALUE orig)
+{
+ if (RB_TYPE_P(clone, T_CLASS)) {
+ class_init_copy_check(clone, orig);
+ }
+ if (!OBJ_INIT_COPY(clone, orig)) return clone;
+
+ /* cloned flag is refer at constant inline cache
+ * see vm_get_const_key_cref() in vm_insnhelper.c
+ */
+ FL_SET(clone, RCLASS_CLONED);
+ FL_SET(orig , RCLASS_CLONED);
+
+ if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
+ RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
+ rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
+ }
+ RCLASS_EXT(clone)->allocator = RCLASS_EXT(orig)->allocator;
+ copy_tables(clone, orig);
if (RCLASS_M_TBL(orig)) {
struct clone_method_arg arg;
arg.old_klass = orig;
@@ -366,6 +383,75 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
rb_id_table_foreach(RCLASS_M_TBL(orig), clone_method_i, &arg);
}
+ if (RCLASS_ORIGIN(orig) == orig) {
+ RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
+ }
+ else {
+ VALUE p = RCLASS_SUPER(orig);
+ VALUE orig_origin = RCLASS_ORIGIN(orig);
+ VALUE prev_clone_p = clone;
+ VALUE origin_stack = rb_ary_tmp_new(2);
+ VALUE origin[2];
+ VALUE clone_p = 0;
+ long origin_len;
+ int add_subclass;
+ VALUE clone_origin;
+
+ ensure_origin(clone);
+ clone_origin = RCLASS_ORIGIN(clone);
+
+ while (p && p != orig_origin) {
+ if (BUILTIN_TYPE(p) != T_ICLASS) {
+ rb_bug("non iclass between module/class and origin");
+ }
+ clone_p = class_alloc(RBASIC(p)->flags, RBASIC(p)->klass);
+ RCLASS_SET_SUPER(prev_clone_p, clone_p);
+ prev_clone_p = clone_p;
+ RCLASS_M_TBL(clone_p) = RCLASS_M_TBL(p);
+ RCLASS_CONST_TBL(clone_p) = RCLASS_CONST_TBL(p);
+ RCLASS_IV_TBL(clone_p) = RCLASS_IV_TBL(p);
+ RCLASS_EXT(clone_p)->allocator = RCLASS_EXT(p)->allocator;
+ if (RB_TYPE_P(clone, T_CLASS)) {
+ RCLASS_SET_INCLUDER(clone_p, clone);
+ }
+ add_subclass = TRUE;
+ if (p != RCLASS_ORIGIN(p)) {
+ origin[0] = clone_p;
+ origin[1] = RCLASS_ORIGIN(p);
+ rb_ary_cat(origin_stack, origin, 2);
+ }
+ else if ((origin_len = RARRAY_LEN(origin_stack)) > 1 &&
+ RARRAY_AREF(origin_stack, origin_len - 1) == p) {
+ RCLASS_SET_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), clone_p);
+ RICLASS_SET_ORIGIN_SHARED_MTBL(clone_p);
+ rb_ary_resize(origin_stack, origin_len);
+ add_subclass = FALSE;
+ }
+ if (add_subclass) {
+ rb_module_add_to_subclasses_list(RBASIC(p)->klass, clone_p);
+ }
+ p = RCLASS_SUPER(p);
+ }
+
+ if (p == orig_origin) {
+ if (clone_p) {
+ RCLASS_SET_SUPER(clone_p, clone_origin);
+ RCLASS_SET_SUPER(clone_origin, RCLASS_SUPER(orig_origin));
+ }
+ copy_tables(clone_origin, orig_origin);
+ if (RCLASS_M_TBL(orig_origin)) {
+ struct clone_method_arg arg;
+ arg.old_klass = orig;
+ arg.new_klass = clone;
+ RCLASS_M_TBL_INIT(clone_origin);
+ rb_id_table_foreach(RCLASS_M_TBL(orig_origin), clone_method_i, &arg);
+ }
+ }
+ else {
+ rb_bug("no origin for class that has origin");
+ }
+ }
+
return clone;
}
@@ -554,7 +640,7 @@ boot_defclass(const char *name, VALUE super)
ID id = rb_intern(name);
rb_const_set((rb_cObject ? rb_cObject : obj), id, obj);
- rb_vm_add_root_module(id, obj);
+ rb_vm_add_root_module(obj);
return obj;
}
@@ -676,14 +762,14 @@ rb_define_class(const char *name, VALUE super)
}
/* Class may have been defined in Ruby and not pin-rooted */
- rb_vm_add_root_module(id, klass);
+ rb_vm_add_root_module(klass);
return klass;
}
if (!super) {
rb_raise(rb_eArgError, "no super class for `%s'", name);
}
klass = rb_define_class_id(id, super);
- rb_vm_add_root_module(id, klass);
+ rb_vm_add_root_module(klass);
rb_const_set(rb_cObject, id, klass);
rb_class_inherited(super, klass);
@@ -749,7 +835,7 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super)
outer, rb_id2str(id), RCLASS_SUPER(klass), super);
}
/* Class may have been defined in Ruby and not pin-rooted */
- rb_vm_add_root_module(id, klass);
+ rb_vm_add_root_module(klass);
return klass;
}
@@ -761,8 +847,7 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super)
rb_set_class_path_string(klass, outer, rb_id2str(id));
rb_const_set(outer, id, klass);
rb_class_inherited(super, klass);
- rb_vm_add_root_module(id, klass);
- rb_gc_register_mark_object(klass);
+ rb_vm_add_root_module(klass);
return klass;
}
@@ -775,6 +860,7 @@ rb_module_new(void)
return (VALUE)mdl;
}
+// Kept for compatibility. Use rb_module_new() instead.
VALUE
rb_define_module_id(ID id)
{
@@ -795,12 +881,11 @@ rb_define_module(const char *name)
name, rb_obj_class(module));
}
/* Module may have been defined in Ruby and not pin-rooted */
- rb_vm_add_root_module(id, module);
+ rb_vm_add_root_module(module);
return module;
}
- module = rb_define_module_id(id);
- rb_vm_add_root_module(id, module);
- rb_gc_register_mark_object(module);
+ module = rb_module_new();
+ rb_vm_add_root_module(module);
rb_const_set(rb_cObject, id, module);
return module;
@@ -826,7 +911,7 @@ rb_define_module_id_under(VALUE outer, ID id)
}
return module;
}
- module = rb_define_module_id(id);
+ module = rb_module_new();
rb_const_set(outer, id, module);
rb_set_class_path_string(module, outer, rb_id2str(id));
rb_gc_register_mark_object(module);
@@ -839,13 +924,13 @@ rb_include_class_new(VALUE module, VALUE super)
{
VALUE klass = class_alloc(T_ICLASS, rb_cClass);
- RCLASS_M_TBL(OBJ_WB_UNPROTECT(klass)) =
- RCLASS_M_TBL(OBJ_WB_UNPROTECT(module)); /* TODO: unprotected? */
+ RCLASS_M_TBL(klass) = RCLASS_M_TBL(module);
- RCLASS_SET_ORIGIN(klass, module == RCLASS_ORIGIN(module) ? klass : RCLASS_ORIGIN(module));
+ RCLASS_SET_ORIGIN(klass, klass);
if (BUILTIN_TYPE(module) == T_ICLASS) {
module = RBASIC(module)->klass;
}
+ RUBY_ASSERT(!RB_TYPE_P(module, T_ICLASS));
if (!RCLASS_IV_TBL(module)) {
RCLASS_IV_TBL(module) = st_init_numtable();
}
@@ -856,12 +941,7 @@ rb_include_class_new(VALUE module, VALUE super)
RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
RCLASS_SET_SUPER(klass, super);
- if (RB_TYPE_P(module, T_ICLASS)) {
- RBASIC_SET_CLASS(klass, RBASIC(module)->klass);
- }
- else {
- RBASIC_SET_CLASS(klass, module);
- }
+ RBASIC_SET_CLASS(klass, module);
return (VALUE)klass;
}
@@ -888,6 +968,31 @@ rb_include_module(VALUE klass, VALUE module)
changed = include_modules_at(klass, RCLASS_ORIGIN(klass), module, TRUE);
if (changed < 0)
rb_raise(rb_eArgError, "cyclic include detected");
+
+ if (RB_TYPE_P(klass, T_MODULE)) {
+ rb_subclass_entry_t *iclass = RCLASS_EXT(klass)->subclasses;
+ int do_include = 1;
+ while (iclass) {
+ VALUE check_class = iclass->klass;
+ /* During lazy sweeping, iclass->klass could be a dead object that
+ * has not yet been swept. */
+ if (!rb_objspace_garbage_object_p(check_class)) {
+ while (check_class) {
+ if (RB_TYPE_P(check_class, T_ICLASS) &&
+ (RBASIC(check_class)->klass == module)) {
+ do_include = 0;
+ }
+ check_class = RCLASS_SUPER(check_class);
+ }
+
+ if (do_include) {
+ include_modules_at(iclass->klass, RCLASS_ORIGIN(iclass->klass), module, TRUE);
+ }
+ }
+
+ iclass = iclass->next;
+ }
+ }
}
static enum rb_id_table_iterator_result
@@ -897,18 +1002,22 @@ add_refined_method_entry_i(ID key, VALUE value, void *data)
return ID_TABLE_CONTINUE;
}
-static void ensure_origin(VALUE klass);
+static enum rb_id_table_iterator_result
+clear_module_cache_i(ID id, VALUE val, void *data)
+{
+ VALUE klass = (VALUE)data;
+ rb_clear_method_cache(klass, id);
+ return ID_TABLE_CONTINUE;
+}
static int
include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super)
{
- VALUE p, iclass;
- int method_changed = 0, constant_changed = 0;
+ VALUE p, iclass, origin_stack = 0;
+ int method_changed = 0, constant_changed = 0, add_subclass;
+ long origin_len;
struct rb_id_table *const klass_m_tbl = RCLASS_M_TBL(RCLASS_ORIGIN(klass));
-
- if (FL_TEST(module, RCLASS_REFINED_BY_ANY)) {
- ensure_origin(module);
- }
+ VALUE original_klass = klass;
while (module) {
int origin_seen = FALSE;
@@ -920,13 +1029,13 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super)
if (klass_m_tbl && klass_m_tbl == RCLASS_M_TBL(module))
return -1;
/* ignore if the module included already in superclasses */
- for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
+ for (p = RCLASS_SUPER(klass); p; p = RCLASS_SUPER(p)) {
int type = BUILTIN_TYPE(p);
if (c == p)
origin_seen = TRUE;
if (type == T_ICLASS) {
if (RCLASS_M_TBL(p) == RCLASS_M_TBL(module)) {
- if (!superclass_seen && origin_seen) {
+ if (!superclass_seen && origin_seen) {
c = p; /* move insertion point */
}
goto skip;
@@ -934,37 +1043,66 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super)
}
else if (type == T_CLASS) {
if (!search_super) break;
- superclass_seen = TRUE;
+ superclass_seen = TRUE;
}
}
- iclass = rb_include_class_new(module, RCLASS_SUPER(c));
+
+ VALUE super_class = RCLASS_SUPER(c);
+
+ // invalidate inline method cache
+ tbl = RCLASS_M_TBL(module);
+ if (tbl && rb_id_table_size(tbl)) {
+ if (search_super) { // include
+ if (super_class && !RB_TYPE_P(super_class, T_MODULE)) {
+ rb_id_table_foreach(tbl, clear_module_cache_i, (void *)super_class);
+ }
+ }
+ else { // prepend
+ if (!RB_TYPE_P(original_klass, T_MODULE)) {
+ rb_id_table_foreach(tbl, clear_module_cache_i, (void *)original_klass);
+ }
+ }
+ method_changed = 1;
+ }
+
+ // setup T_ICLASS for the include/prepend module
+ iclass = rb_include_class_new(module, super_class);
c = RCLASS_SET_SUPER(c, iclass);
RCLASS_SET_INCLUDER(iclass, klass);
+ add_subclass = TRUE;
+ if (module != RCLASS_ORIGIN(module)) {
+ if (!origin_stack) origin_stack = rb_ary_tmp_new(2);
+ VALUE origin[2] = {iclass, RCLASS_ORIGIN(module)};
+ rb_ary_cat(origin_stack, origin, 2);
+ }
+ else if (origin_stack && (origin_len = RARRAY_LEN(origin_stack)) > 1 &&
+ RARRAY_AREF(origin_stack, origin_len - 1) == module) {
+ RCLASS_SET_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), iclass);
+ RICLASS_SET_ORIGIN_SHARED_MTBL(iclass);
+ rb_ary_resize(origin_stack, origin_len);
+ add_subclass = FALSE;
+ }
{
VALUE m = module;
- if (BUILTIN_TYPE(m) == T_ICLASS) m = RBASIC(m)->klass;
- rb_module_add_to_subclasses_list(m, iclass);
+ if (BUILTIN_TYPE(m) == T_ICLASS) m = RBASIC(m)->klass;
+ if (add_subclass) rb_module_add_to_subclasses_list(m, iclass);
}
if (FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
VALUE refined_class =
rb_refinement_module_get_refined_class(klass);
- rb_id_table_foreach(RMODULE_M_TBL(module), add_refined_method_entry_i, (void *)refined_class);
+ rb_id_table_foreach(RCLASS_M_TBL(module), add_refined_method_entry_i, (void *)refined_class);
FL_SET(c, RMODULE_INCLUDED_INTO_REFINEMENT);
}
- tbl = RMODULE_M_TBL(module);
- if (tbl && rb_id_table_size(tbl)) method_changed = 1;
-
- tbl = RMODULE_CONST_TBL(module);
+ tbl = RCLASS_CONST_TBL(module);
if (tbl && rb_id_table_size(tbl)) constant_changed = 1;
skip:
module = RCLASS_SUPER(module);
}
- if (method_changed) rb_clear_method_cache_by_class(klass);
if (constant_changed) rb_clear_constant_cache();
return method_changed;
@@ -973,22 +1111,22 @@ include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super)
static enum rb_id_table_iterator_result
move_refined_method(ID key, VALUE value, void *data)
{
- rb_method_entry_t *me = (rb_method_entry_t *) value;
- VALUE klass = (VALUE)data;
- struct rb_id_table *tbl = RCLASS_M_TBL(klass);
+ rb_method_entry_t *me = (rb_method_entry_t *)value;
if (me->def->type == VM_METHOD_TYPE_REFINED) {
- if (me->def->body.refined.orig_me) {
+ VALUE klass = (VALUE)data;
+ struct rb_id_table *tbl = RCLASS_M_TBL(klass);
+
+ if (me->def->body.refined.orig_me) {
const rb_method_entry_t *orig_me = me->def->body.refined.orig_me, *new_me;
RB_OBJ_WRITE(me, &me->def->body.refined.orig_me, NULL);
new_me = rb_method_entry_clone(me);
- rb_id_table_insert(tbl, key, (VALUE)new_me);
- RB_OBJ_WRITTEN(klass, Qundef, new_me);
+ rb_method_table_insert(klass, tbl, key, new_me);
rb_method_entry_copy(me, orig_me);
return ID_TABLE_CONTINUE;
}
else {
- rb_id_table_insert(tbl, key, (VALUE)me);
+ rb_method_table_insert(klass, tbl, key, me);
return ID_TABLE_DELETE;
}
}
@@ -997,18 +1135,33 @@ move_refined_method(ID key, VALUE value, void *data)
}
}
+static enum rb_id_table_iterator_result
+cache_clear_refined_method(ID key, VALUE value, void *data)
+{
+ rb_method_entry_t *me = (rb_method_entry_t *) value;
+
+ if (me->def->type == VM_METHOD_TYPE_REFINED && me->def->body.refined.orig_me) {
+ VALUE klass = (VALUE)data;
+ rb_clear_method_cache(klass, me->called_id);
+ }
+ // Refined method entries without an orig_me is going to stay in the method
+ // table of klass, like before the move, so no need to clear the cache.
+
+ return ID_TABLE_CONTINUE;
+}
+
static void
ensure_origin(VALUE klass)
{
VALUE origin = RCLASS_ORIGIN(klass);
if (origin == klass) {
origin = class_alloc(T_ICLASS, klass);
- OBJ_WB_UNPROTECT(origin); /* TODO: conservative shading. Need more survey. */
RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
RCLASS_SET_SUPER(klass, origin);
RCLASS_SET_ORIGIN(klass, origin);
RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass);
RCLASS_M_TBL_INIT(klass);
+ rb_id_table_foreach(RCLASS_M_TBL(origin), cache_clear_refined_method, (void *)klass);
rb_id_table_foreach(RCLASS_M_TBL(origin), move_refined_method, (void *)klass);
}
}
@@ -1017,6 +1170,7 @@ void
rb_prepend_module(VALUE klass, VALUE module)
{
int changed = 0;
+ bool klass_had_no_origin = RCLASS_ORIGIN(klass) == klass;
ensure_includable(klass, module);
ensure_origin(klass);
@@ -1026,23 +1180,53 @@ rb_prepend_module(VALUE klass, VALUE module)
if (changed) {
rb_vm_check_redefinition_by_prepend(klass);
}
+ if (RB_TYPE_P(klass, T_MODULE)) {
+ rb_subclass_entry_t *iclass = RCLASS_EXT(klass)->subclasses;
+ VALUE klass_origin = RCLASS_ORIGIN(klass);
+ struct rb_id_table *klass_m_tbl = RCLASS_M_TBL(klass);
+ struct rb_id_table *klass_origin_m_tbl = RCLASS_M_TBL(klass_origin);
+ while (iclass) {
+ /* During lazy sweeping, iclass->klass could be a dead object that
+ * has not yet been swept. */
+ if (!rb_objspace_garbage_object_p(iclass->klass)) {
+ if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(iclass->klass)) {
+ // backfill an origin iclass to handle refinements and future prepends
+ rb_id_table_foreach(RCLASS_M_TBL(iclass->klass), clear_module_cache_i, (void *)iclass->klass);
+ RCLASS_M_TBL(iclass->klass) = klass_m_tbl;
+ VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(iclass->klass));
+ RCLASS_SET_SUPER(iclass->klass, origin);
+ RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(iclass->klass));
+ RCLASS_SET_ORIGIN(iclass->klass, origin);
+ RICLASS_SET_ORIGIN_SHARED_MTBL(origin);
+ }
+ include_modules_at(iclass->klass, iclass->klass, module, FALSE);
+ }
+
+ iclass = iclass->next;
+ }
+ }
}
/*
* call-seq:
* mod.included_modules -> array
*
- * Returns the list of modules included in <i>mod</i>.
+ * Returns the list of modules included or prepended in <i>mod</i>
+ * or one of <i>mod</i>'s ancestors.
+ *
+ * module Sub
+ * end
*
* module Mixin
+ * prepend Sub
* end
*
* module Outer
* include Mixin
* end
*
- * Mixin.included_modules #=> []
- * Outer.included_modules #=> [Mixin]
+ * Mixin.included_modules #=> [Sub]
+ * Outer.included_modules #=> [Sub, Mixin]
*/
VALUE
@@ -1053,7 +1237,7 @@ rb_mod_included_modules(VALUE mod)
VALUE origin = RCLASS_ORIGIN(mod);
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
- if (p != origin && BUILTIN_TYPE(p) == T_ICLASS) {
+ if (p != origin && RCLASS_ORIGIN(p) == p && BUILTIN_TYPE(p) == T_ICLASS) {
VALUE m = RBASIC(p)->klass;
if (RB_TYPE_P(m, T_MODULE))
rb_ary_push(ary, m);
@@ -1066,8 +1250,8 @@ rb_mod_included_modules(VALUE mod)
* call-seq:
* mod.include?(module) -> true or false
*
- * Returns <code>true</code> if <i>module</i> is included in
- * <i>mod</i> or one of <i>mod</i>'s ancestors.
+ * Returns <code>true</code> if <i>module</i> is included
+ * or prepended in <i>mod</i> or one of <i>mod</i>'s ancestors.
*
* module A
* end
@@ -1088,7 +1272,7 @@ rb_mod_include_p(VALUE mod, VALUE mod2)
Check_Type(mod2, T_MODULE);
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
- if (BUILTIN_TYPE(p) == T_ICLASS) {
+ if (BUILTIN_TYPE(p) == T_ICLASS && !FL_TEST(p, RICLASS_IS_ORIGIN)) {
if (RBASIC(p)->klass == mod2) return Qtrue;
}
}
@@ -1620,19 +1804,15 @@ rb_undef_methods_from(VALUE klass, VALUE super)
* \{
*/
-#define SPECIAL_SINGLETON(x,c) do {\
- if (obj == (x)) {\
- return (c);\
- }\
-} while (0)
-
static inline VALUE
special_singleton_class_of(VALUE obj)
{
- SPECIAL_SINGLETON(Qnil, rb_cNilClass);
- SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
- SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
- return Qnil;
+ switch (obj) {
+ case Qnil: return rb_cNilClass;
+ case Qfalse: return rb_cFalseClass;
+ case Qtrue: return rb_cTrueClass;
+ default: return Qnil;
+ }
}
VALUE
@@ -1655,29 +1835,30 @@ singleton_class_of(VALUE obj)
{
VALUE klass;
- if (FIXNUM_P(obj) || FLONUM_P(obj) || STATIC_SYM_P(obj)) {
- no_singleton:
+ switch (TYPE(obj)) {
+ case T_FIXNUM:
+ case T_BIGNUM:
+ case T_FLOAT:
+ case T_SYMBOL:
rb_raise(rb_eTypeError, "can't define singleton");
- }
- if (SPECIAL_CONST_P(obj)) {
+
+ case T_FALSE:
+ case T_TRUE:
+ case T_NIL:
klass = special_singleton_class_of(obj);
if (NIL_P(klass))
rb_bug("unknown immediate %p", (void *)obj);
return klass;
- }
- else {
- switch (BUILTIN_TYPE(obj)) {
- case T_FLOAT: case T_BIGNUM: case T_SYMBOL:
- goto no_singleton;
- case T_STRING:
- if (FL_TEST_RAW(obj, RSTRING_FSTR)) goto no_singleton;
- break;
- }
+
+ case T_STRING:
+ if (FL_TEST_RAW(obj, RSTRING_FSTR)) {
+ rb_raise(rb_eTypeError, "can't define singleton");
+ }
}
klass = RBASIC(obj)->klass;
if (!(FL_TEST(klass, FL_SINGLETON) &&
- rb_ivar_get(klass, id_attached) == obj)) {
+ rb_attr_get(klass, id_attached) == obj)) {
rb_serial_t serial = RCLASS_SERIAL(klass);
klass = rb_make_metaclass(obj, klass);
RCLASS_SERIAL(klass) = serial;
@@ -1718,7 +1899,7 @@ rb_singleton_class_get(VALUE obj)
}
klass = RBASIC(obj)->klass;
if (!FL_TEST(klass, FL_SINGLETON)) return Qnil;
- if (rb_ivar_get(klass, id_attached) != obj) return Qnil;
+ if (rb_attr_get(klass, id_attached) != obj) return Qnil;
return klass;
}
@@ -1726,7 +1907,7 @@ rb_singleton_class_get(VALUE obj)
* Returns the singleton class of \a obj. Creates it if necessary.
*
* \param obj an arbitrary object.
- * \throw TypeError if \a obj is a Integer or a Symbol.
+ * \throw TypeError if \a obj is an Integer or a Symbol.
* \return the singleton class.
*
* \post \a obj has its own singleton class.
@@ -1957,52 +2138,22 @@ rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, V
}
struct rb_scan_args_t {
- int argc;
- const VALUE *argv;
- va_list vargs;
- int f_var;
- int f_hash;
- int f_block;
+ int kw_flag;
int n_lead;
int n_opt;
int n_trail;
- int n_mand;
- int argi;
- int last_idx;
- VALUE hash;
- VALUE last_hash;
- VALUE *tmp_buffer;
+ bool f_var;
+ bool f_hash;
+ bool f_block;
};
static void
-rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, struct rb_scan_args_t *arg)
+rb_scan_args_parse(int kw_flag, const char *fmt, struct rb_scan_args_t *arg)
{
const char *p = fmt;
- VALUE *tmp_buffer = arg->tmp_buffer;
- int keyword_given = 0;
- int empty_keyword_given = 0;
- int last_hash_keyword = 0;
memset(arg, 0, sizeof(*arg));
- arg->last_idx = -1;
- arg->hash = Qnil;
-
- switch (kw_flag) {
- case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS:
- if (!(keyword_given = rb_keyword_given_p())) {
- empty_keyword_given = rb_empty_keyword_given_p();
- }
- break;
- case RB_SCAN_ARGS_KEYWORDS:
- keyword_given = 1;
- break;
- case RB_SCAN_ARGS_EMPTY_KEYWORDS:
- empty_keyword_given = 1;
- break;
- case RB_SCAN_ARGS_LAST_HASH_KEYWORDS:
- last_hash_keyword = 1;
- break;
- }
+ arg->kw_flag = kw_flag;
if (ISDIGIT(*p)) {
arg->n_lead = *p - '0';
@@ -2031,97 +2182,47 @@ rb_scan_args_parse(int kw_flag, int argc, const VALUE *argv, const char *fmt, st
if (*p != '\0') {
rb_fatal("bad scan arg format: %s", fmt);
}
- arg->n_mand = arg->n_lead + arg->n_trail;
+}
- /* capture an option hash - phase 1: pop */
- /* Ignore final positional hash if empty keywords given */
- if (argc > 0 && !(arg->f_hash && empty_keyword_given)) {
+static int
+rb_scan_args_assign(const struct rb_scan_args_t *arg, int argc, const VALUE *const argv, va_list vargs)
+{
+ int i, argi = 0;
+ VALUE *var, hash = Qnil;
+#define rb_scan_args_next_param() va_arg(vargs, VALUE *)
+ const int kw_flag = arg->kw_flag;
+ const int n_lead = arg->n_lead;
+ const int n_opt = arg->n_opt;
+ const int n_trail = arg->n_trail;
+ const int n_mand = n_lead + n_trail;
+ const bool f_var = arg->f_var;
+ const bool f_hash = arg->f_hash;
+ const bool f_block = arg->f_block;
+
+ /* capture an option hash - phase 1: pop from the argv */
+ if (f_hash && argc > 0) {
VALUE last = argv[argc - 1];
-
- if (arg->f_hash && arg->n_mand < argc) {
- if (keyword_given) {
- if (!RB_TYPE_P(last, T_HASH)) {
- rb_warn("Keyword flag set when calling rb_scan_args, but last entry is not a hash");
- }
- else {
- arg->hash = last;
- }
- }
- else if (NIL_P(last)) {
- /* For backwards compatibility, nil is taken as an empty
- option hash only if it is not ambiguous; i.e. '*' is
- not specified and arguments are given more than sufficient.
- This will be removed in Ruby 3. */
- if (!arg->f_var && arg->n_mand + arg->n_opt < argc) {
- rb_warn("The last argument is nil, treating as empty keywords");
- argc--;
- }
- }
- else {
- arg->hash = rb_check_hash_type(last);
- }
-
- /* Ruby 3: Remove if branch, as it will not attempt to split hashes */
- if (!NIL_P(arg->hash)) {
- VALUE opts = rb_extract_keywords(&arg->hash);
-
- if (!(arg->last_hash = arg->hash)) {
- if (!keyword_given && !last_hash_keyword) {
- /* Warn if treating positional as keyword, as in Ruby 3,
- this will be an error */
- rb_warn("Using the last argument as keyword parameters is deprecated");
- }
- argc--;
- }
- else {
- /* Warn if splitting either positional hash to keywords or keywords
- to positional hash, as in Ruby 3, no splitting will be done */
- rb_warn("The last argument is split into positional and keyword parameters");
- arg->last_idx = argc - 1;
- }
- arg->hash = opts ? opts : Qnil;
- }
- }
- else if (arg->f_hash && keyword_given && arg->n_mand == argc) {
- /* Warn if treating keywords as positional, as in Ruby 3, this will be an error */
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
+ if (rb_scan_args_keyword_p(kw_flag, last)) {
+ hash = rb_hash_dup(last);
+ argc--;
}
}
- if (arg->f_hash && arg->n_mand == argc+1 && empty_keyword_given) {
- VALUE *ptr = rb_alloc_tmp_buffer2(tmp_buffer, argc+1, sizeof(VALUE));
- memcpy(ptr, argv, sizeof(VALUE)*argc);
- ptr[argc] = rb_hash_new();
- argc++;
- *(&argv) = ptr;
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- }
-
- arg->argc = argc;
- arg->argv = argv;
-}
-
-static int
-rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs)
-{
- int argi = 0;
- int i;
- VALUE *var;
- if (arg->argc < arg->n_mand) {
- return 1;
+ if (argc < n_mand) {
+ goto argc_error;
}
/* capture leading mandatory arguments */
- for (i = arg->n_lead; i-- > 0; ) {
- var = va_arg(vargs, VALUE *);
- if (var) *var = (argi == arg->last_idx) ? arg->last_hash : arg->argv[argi];
+ for (i = 0; i < n_lead; i++) {
+ var = rb_scan_args_next_param();
+ if (var) *var = argv[argi];
argi++;
}
/* capture optional arguments */
- for (i = arg->n_opt; i-- > 0; ) {
- var = va_arg(vargs, VALUE *);
- if (argi < arg->argc - arg->n_trail) {
- if (var) *var = (argi == arg->last_idx) ? arg->last_hash : arg->argv[argi];
+ for (i = 0; i < n_opt; i++) {
+ var = rb_scan_args_next_param();
+ if (argi < argc - n_trail) {
+ if (var) *var = argv[argi];
argi++;
}
else {
@@ -2129,16 +2230,12 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs)
}
}
/* capture variable length arguments */
- if (arg->f_var) {
- int n_var = arg->argc - argi - arg->n_trail;
+ if (f_var) {
+ int n_var = argc - argi - n_trail;
- var = va_arg(vargs, VALUE *);
+ var = rb_scan_args_next_param();
if (0 < n_var) {
- if (var) {
- int f_last = (arg->last_idx + 1 == arg->argc - arg->n_trail);
- *var = rb_ary_new4(n_var - f_last, &arg->argv[argi]);
- if (f_last) rb_ary_push(*var, arg->last_hash);
- }
+ if (var) *var = rb_ary_new_from_values(n_var, &argv[argi]);
argi += n_var;
}
else {
@@ -2146,19 +2243,19 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs)
}
}
/* capture trailing mandatory arguments */
- for (i = arg->n_trail; i-- > 0; ) {
- var = va_arg(vargs, VALUE *);
- if (var) *var = (argi == arg->last_idx) ? arg->last_hash : arg->argv[argi];
+ for (i = 0; i < n_trail; i++) {
+ var = rb_scan_args_next_param();
+ if (var) *var = argv[argi];
argi++;
}
/* capture an option hash - phase 2: assignment */
- if (arg->f_hash) {
- var = va_arg(vargs, VALUE *);
- if (var) *var = arg->hash;
+ if (f_hash) {
+ var = rb_scan_args_next_param();
+ if (var) *var = hash;
}
/* capture iterator block */
- if (arg->f_block) {
- var = va_arg(vargs, VALUE *);
+ if (f_block) {
+ var = rb_scan_args_next_param();
if (rb_block_given_p()) {
*var = rb_block_proc();
}
@@ -2167,52 +2264,57 @@ rb_scan_args_assign(struct rb_scan_args_t *arg, va_list vargs)
}
}
- if (argi < arg->argc) return 1;
+ if (argi == argc) {
+ return argc;
+ }
+
+ argc_error:
+ return -(argc + 1);
+#undef rb_scan_args_next_param
+}
+
+static int
+rb_scan_args_result(const struct rb_scan_args_t *const arg, int argc)
+{
+ const int n_lead = arg->n_lead;
+ const int n_opt = arg->n_opt;
+ const int n_trail = arg->n_trail;
+ const int n_mand = n_lead + n_trail;
+ const bool f_var = arg->f_var;
+
+ if (argc >= 0) {
+ return argc;
+ }
- return 0;
+ argc = -argc - 1;
+ rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
+ UNREACHABLE_RETURN(-1);
}
#undef rb_scan_args
int
rb_scan_args(int argc, const VALUE *argv, const char *fmt, ...)
{
- int error;
va_list vargs;
- VALUE tmp_buffer = 0;
struct rb_scan_args_t arg;
- arg.tmp_buffer = &tmp_buffer;
- rb_scan_args_parse(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, argc, argv, fmt, &arg);
+ rb_scan_args_parse(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, fmt, &arg);
va_start(vargs,fmt);
- error = rb_scan_args_assign(&arg, vargs);
+ argc = rb_scan_args_assign(&arg, argc, argv, vargs);
va_end(vargs);
- if (tmp_buffer) {
- rb_free_tmp_buffer(&tmp_buffer);
- }
- if (error) {
- rb_error_arity(arg.argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
- }
- return arg.argc;
+ return rb_scan_args_result(&arg, argc);
}
+#undef rb_scan_args_kw
int
rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt, ...)
{
- int error;
va_list vargs;
- VALUE tmp_buffer = 0;
struct rb_scan_args_t arg;
- arg.tmp_buffer = &tmp_buffer;
- rb_scan_args_parse(kw_flag, argc, argv, fmt, &arg);
+ rb_scan_args_parse(kw_flag, fmt, &arg);
va_start(vargs,fmt);
- error = rb_scan_args_assign(&arg, vargs);
+ argc = rb_scan_args_assign(&arg, argc, argv, vargs);
va_end(vargs);
- if (tmp_buffer) {
- rb_free_tmp_buffer(&tmp_buffer);
- }
- if (error) {
- rb_error_arity(arg.argc, arg.n_mand, arg.f_var ? UNLIMITED_ARGUMENTS : arg.n_mand + arg.n_opt);
- }
- return arg.argc;
+ return rb_scan_args_result(&arg, argc);
}
int
diff --git a/common.mk b/common.mk
index fd14ab6688..2c76f24924 100644
--- a/common.mk
+++ b/common.mk
@@ -38,7 +38,7 @@ RUBYLIB = $(PATH_SEPARATOR)
RUBYOPT = -
RUN_OPTS = --disable-gems
-GITPULLOPTIONS = --rebase
+# GITPULLOPTIONS = --no-tags
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) -I$(UNICODE_HDR_DIR)
@@ -47,7 +47,7 @@ GEM_PATH =
GEM_VENDOR =
BENCHMARK_DRIVER_GIT_URL = https://github.com/benchmark-driver/benchmark-driver
-BENCHMARK_DRIVER_GIT_REF = v0.15.6
+BENCHMARK_DRIVER_GIT_REF = v0.15.15
SIMPLECOV_GIT_URL = https://github.com/colszowka/simplecov.git
SIMPLECOV_GIT_REF = v0.17.0
SIMPLECOV_HTML_GIT_URL = https://github.com/colszowka/simplecov-html.git
@@ -107,6 +107,7 @@ COMMONOBJS = array.$(OBJEXT) \
load.$(OBJEXT) \
marshal.$(OBJEXT) \
math.$(OBJEXT) \
+ memory_view.$(OBJEXT) \
mjit.$(OBJEXT) \
mjit_compile.$(OBJEXT) \
node.$(OBJEXT) \
@@ -116,6 +117,7 @@ COMMONOBJS = array.$(OBJEXT) \
parse.$(OBJEXT) \
proc.$(OBJEXT) \
process.$(OBJEXT) \
+ ractor.$(OBJEXT) \
random.$(OBJEXT) \
range.$(OBJEXT) \
rational.$(OBJEXT) \
@@ -127,7 +129,7 @@ COMMONOBJS = array.$(OBJEXT) \
regparse.$(OBJEXT) \
regsyntax.$(OBJEXT) \
ruby.$(OBJEXT) \
- safe.$(OBJEXT) \
+ scheduler.$(OBJEXT) \
signal.$(OBJEXT) \
sprintf.$(OBJEXT) \
st.$(OBJEXT) \
@@ -145,6 +147,7 @@ COMMONOBJS = array.$(OBJEXT) \
vm.$(OBJEXT) \
vm_backtrace.$(OBJEXT) \
vm_dump.$(OBJEXT) \
+ vm_sync.$(OBJEXT) \
vm_trace.$(OBJEXT) \
$(COROUTINE_OBJ) \
$(DTRACE_OBJ) \
@@ -176,7 +179,7 @@ EXTMK_ARGS = $(SCRIPT_ARGS) --extension $(EXTS) --extstatic $(EXTSTATIC) \
--make-flags="V=$(V) MINIRUBY='$(MINIRUBY)'" \
--gnumake=$(gnumake) --extflags="$(EXTLDFLAGS)" \
--
-INSTRUBY = $(SUDO) $(RUNRUBY) -r./$(arch)-fake $(srcdir)/tool/rbinstall.rb
+INSTRUBY = $(SUDO) $(RUNRUBY) -r./$(arch)-fake $(tooldir)/rbinstall.rb
INSTRUBY_ARGS = $(SCRIPT_ARGS) \
--data-mode=$(INSTALL_DATA_MODE) \
--prog-mode=$(INSTALL_PROG_MODE) \
@@ -186,14 +189,15 @@ INSTALL_PROG_MODE = 0755
INSTALL_DATA_MODE = 0644
TESTSDIR = $(srcdir)/test
-TOOL_TESTSDIR = $(srcdir)/tool/test
+TOOL_TESTSDIR = $(tooldir)/test
TEST_EXCLUDES = --excludes-dir=$(TESTSDIR)/excludes --name=!/memory_leak/
TESTWORKDIR = testwork
TESTOPTS = $(RUBY_TESTOPTS)
TESTRUN_SCRIPT = $(srcdir)/test.rb
-COMPILE_PRELUDE = $(srcdir)/tool/generic_erb.rb $(srcdir)/template/prelude.c.tmpl
+COMPILE_PRELUDE = $(tooldir)/generic_erb.rb $(srcdir)/template/prelude.c.tmpl \
+ $(tooldir)/ruby_vm/helpers/c_escape.rb
SHOWFLAGS = showflags
@@ -208,7 +212,7 @@ MAKE_LINK = $(MINIRUBY) -rfileutils -e "include FileUtils::Verbose" \
all: $(SHOWFLAGS) main docs
-main: $(SHOWFLAGS) exts $(ENCSTATIC:static=lib)encs
+main: $(SHOWFLAGS) exts $(ENCSTATIC:static=lib)encs programs
@$(NULLCMD)
mjit-headers: $(MJIT_SUPPORT)-mjit-headers
@@ -225,19 +229,20 @@ mjit_config.h: Makefile
# Other `-Dxxx`s preceding `-DMJIT_HEADER` will be removed in transform_mjit_header.rb.
# So `-DMJIT_HEADER` should be passed first when rb_mjit_header.h is generated.
$(TIMESTAMPDIR)/$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).time: probes.h vm.$(OBJEXT) \
- $(TIMESTAMPDIR)/$(arch)/.time
+ $(TIMESTAMPDIR)/$(arch)/.time $(tooldir)/mjit_tabs.rb $(PREP) $(RBCONFIG)
$(ECHO) building $(@F:.time=.h)
- $(Q) $(CPP) -DMJIT_HEADER $(MJIT_HEADER_FLAGS) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(srcdir)/vm.c $(CPPOUTFLAG)$(@F:.time=.h).new
+ $(MINIRUBY) $(tooldir)/mjit_tabs.rb "$(MJIT_TABS)" \
+ $(CPP) -DMJIT_HEADER $(MJIT_HEADER_FLAGS) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(srcdir)/vm.c $(CPPOUTFLAG)$(@F:.time=.h).new
$(Q) $(IFCHANGE) "--timestamp=$@" $(@F:.time=.h) $(@F:.time=.h).new
$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).h: $(TIMESTAMPDIR)/$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).time
$(MJIT_MIN_HEADER:.h=)$(MJIT_HEADER_SUFFIX).h: \
$(TIMESTAMPDIR)/$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).time \
- $(srcdir)/tool/transform_mjit_header.rb $(PREP) \
+ $(tooldir)/transform_mjit_header.rb $(PREP) \
$(MJIT_HEADER:.h=)$(MJIT_HEADER_SUFFIX).h
$(ECHO) building $@
- $(MINIRUBY) $(srcdir)/tool/transform_mjit_header.rb "$(CC) $(ARCH_FLAG) $(CFLAGS)" $(MJIT_HEADER:.h=)$(MJIT_HEADER_ARCH).h $@
+ $(MINIRUBY) $(tooldir)/transform_mjit_header.rb "$(CC) $(ARCH_FLAG) $(CFLAGS)" $(MJIT_HEADER:.h=)$(MJIT_HEADER_ARCH).h $@
$(Q) $(MAKEDIRS) $(MJIT_HEADER_INSTALL_DIR)
$(Q) $(MAKE_LINK) $@ $(MJIT_HEADER_INSTALL_DIR)/$(@F)
@@ -278,14 +283,14 @@ $(EXTS_MK): ext/configure-ext.mk $(srcdir)/template/exts.mk.tmpl \
gnumake=$(gnumake) MINIRUBY="$(MINIRUBY)" \
EXTLDFLAGS="$(EXTLDFLAGS)" srcdir="$(srcdir)"
$(ECHO) generating makefile $@
- $(Q)$(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ -c \
- $(srcdir)/template/exts.mk.tmpl --gnumake=$(gnumake)
+ $(Q)$(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ -c \
+ $(srcdir)/template/exts.mk.tmpl --gnumake=$(gnumake) --configure-exts=ext/configure-ext.mk
ext/configure-ext.mk: $(PREP) all-incs $(MKFILES) $(RBCONFIG) $(LIBRUBY) \
$(srcdir)/template/configure-ext.mk.tmpl
$(ECHO) generating makefiles $@
$(Q)$(MAKEDIRS) $(@D)
- $(Q)$(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ -c \
+ $(Q)$(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ -c \
$(srcdir)/template/$(@F).tmpl --srcdir="$(srcdir)" \
--miniruby="$(MINIRUBY)" --script-args='$(SCRIPT_ARGS)'
@@ -299,12 +304,12 @@ build-ext: $(EXTS_MK)
exts-note: $(EXTS_MK)
$(Q)$(MAKE) $(EXTS_NOTE)
-ext/extinit.c: $(srcdir)/template/extinit.c.tmpl
- $(Q)$(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ -c \
+ext/extinit.c: $(srcdir)/template/extinit.c.tmpl $(PREP)
+ $(Q)$(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ -c \
$(srcdir)/template/extinit.c.tmpl $(EXTINITS)
prog: program wprogram
-programs: $(PROGRAM) $(WPROGRAM)
+programs: $(PROGRAM) $(WPROGRAM) $(arch)-fake.rb
$(PREP): $(MKFILES)
@@ -331,9 +336,9 @@ $(CAPIOUT)/.timestamp: Doxyfile $(PREP)
-$(Q) $(DOXYGEN) -b
$(Q) $(MINIRUBY) -e 'File.open(ARGV[0], "w"){'"|f|"' f.puts(Time.now)}' "$@"
-Doxyfile: $(srcdir)/template/Doxyfile.tmpl $(PREP) $(srcdir)/tool/generic_erb.rb $(RBCONFIG)
+Doxyfile: $(srcdir)/template/Doxyfile.tmpl $(PREP) $(tooldir)/generic_erb.rb $(RBCONFIG)
$(ECHO) generating $@
- $(Q) $(MINIRUBY) $(srcdir)/tool/generic_erb.rb -o $@ $(srcdir)/template/Doxyfile.tmpl \
+ $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ $(srcdir)/template/Doxyfile.tmpl \
--srcdir="$(srcdir)" --miniruby="$(MINIRUBY)"
program: $(SHOWFLAGS) $(PROGRAM)
@@ -356,7 +361,7 @@ $(STATIC_RUBY)$(EXEEXT): $(MAINOBJ) $(DLDOBJS) $(EXTOBJS) $(LIBRUBY_A)
ruby.imp: $(COMMONOBJS)
$(Q){ \
$(NM) -Pgp $(COMMONOBJS) | \
- awk 'BEGIN{print "#!"}; $$2~/^[BDT]$$/&&$$1!~/^$(SYMBOL_PREFIX)(Init_|InitVM_|ruby_static_id_|.*_threadptr_|rb_ec_)|^\./{print $$1}'; \
+ awk 'BEGIN{print "#!"}; $$2~/^[A-TV-Z]$$/&&$$1!~/^$(SYMBOL_PREFIX)(Init_|InitVM_|ruby_static_id_|.*_threadptr_|rb_ec_)|^\./{print $$1}'; \
($(CHDIR) $(srcdir) && \
exec sed -n '/^MJIT_FUNC_EXPORTED/!d;N;s/.*\n\(rb_[a-zA-Z_0-9]*\).*/$(SYMBOL_PREFIX)\1/p' cont.c gc.c thread*c vm*.c) \
} | \
@@ -368,17 +373,17 @@ pkgconfig-data: $(ruby_pc)
$(ruby_pc): $(srcdir)/template/ruby.pc.in config.status
install-all: docs pre-install-all do-install-all post-install-all
-pre-install-all:: all pre-install-local pre-install-ext pre-install-doc
+pre-install-all:: all pre-install-local pre-install-ext pre-install-gem pre-install-doc
do-install-all: pre-install-all
$(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) $(INSTALL_DOC_OPTS)
-post-install-all:: post-install-local post-install-ext post-install-doc
+post-install-all:: post-install-local post-install-ext post-install-gem post-install-doc
@$(NULLCMD)
install-nodoc: pre-install-nodoc do-install-nodoc post-install-nodoc
-pre-install-nodoc:: pre-install-local pre-install-ext
+pre-install-nodoc:: pre-install-local pre-install-ext pre-install-gem
do-install-nodoc: main pre-install-nodoc
$(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --exclude=doc
-post-install-nodoc:: post-install-local post-install-ext
+post-install-nodoc:: post-install-local post-install-ext post-install-gem
install-local: pre-install-local do-install-local post-install-local
pre-install-local:: pre-install-bin pre-install-lib pre-install-man
@@ -457,7 +462,7 @@ post-no-install-all:: post-no-install-local post-no-install-ext post-no-install-
@$(NULLCMD)
uninstall: $(INSTALLED_LIST) sudo-precheck
- $(Q)$(SUDO) $(MINIRUBY) $(srcdir)/tool/rbuninstall.rb --destdir=$(DESTDIR) $(INSTALLED_LIST)
+ $(Q)$(SUDO) $(MINIRUBY) $(tooldir)/rbuninstall.rb --destdir=$(DESTDIR) $(INSTALLED_LIST)
reinstall: all uninstall install
@@ -544,12 +549,19 @@ post-install-doc::
@$(NULLCMD)
install-gem: pre-install-gem do-install-gem post-install-gem
-pre-install-gem:: pre-install-bin pre-install-lib pre-install-man
+pre-install-gem:: prepare-gems pre-install-bin pre-install-lib pre-install-man
do-install-gem: $(PROGRAM) pre-install-gem
$(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=gem
post-install-gem::
@$(NULLCMD)
+install-dbg: pre-install-dbg do-install-dbg post-install-dbg
+pre-install-dbg::
+do-install-dbg: $(PROGRAM) pre-install-dbg
+ $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=dbg
+post-install-dbg::
+ @$(NULLCMD)
+
rdoc: PHONY main
@echo Generating RDoc documentation
$(Q) $(RDOC) --ri --op "$(RDOCOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) "$(srcdir)"
@@ -594,8 +606,8 @@ clean-local:: clean-runnable
$(Q)$(RM) $(OBJS) $(MINIOBJS) $(MAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
$(Q)$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) dmyenc.$(OBJEXT) $(ARCHFILE) .*.time
$(Q)$(RM) y.tab.c y.output encdb.h transdb.h config.log rbconfig.rb $(ruby_pc) $(COROUTINE_H:/Context.h=/.time)
- $(Q)$(RM) probes.h probes.$(OBJEXT) probes.stamp ruby-glommed.$(OBJEXT) ruby.imp
- $(Q)$(RM) GNUmakefile.old Makefile.old $(arch)-fake.rb bisect.sh $(ENC_TRANS_D)
+ $(Q)$(RM) probes.h probes.$(OBJEXT) probes.stamp ruby-glommed.$(OBJEXT) ruby.imp ChangeLog $(STATIC_RUBY)$(EXEEXT)
+ $(Q)$(RM) GNUmakefile.old Makefile.old $(arch)-fake.rb bisect.sh $(ENC_TRANS_D) builtin_binary.inc
-$(Q) $(RMDIR) enc/jis enc/trans enc $(COROUTINE_H:/Context.h=) coroutine 2> $(NULL) || $(NULLCMD)
bin/clean-runnable:: PHONY
@@ -712,7 +724,7 @@ clean-capi distclean-capi realclean-capi:
@echo $(@:-capi=ing) capi
$(Q)$(RMALL) $(CAPIOUT)
-clean-platform:
+clean-platform distclean-platform realclean-platform:
$(Q) $(RM) $(PLATFORM_D)
-$(Q) $(RMDIR) $(PLATFORM_DIR) 2> $(NULL) || $(NULLCMD)
@@ -720,11 +732,14 @@ RUBYSPEC_CAPIEXT = spec/ruby/optional/capi/ext
clean-spec: PHONY
-$(Q) $(RM) $(RUBYSPEC_CAPIEXT)/*.$(OBJEXT) $(RUBYSPEC_CAPIEXT)/*.$(DLEXT)
-$(Q) $(RMDIRS) $(RUBYSPEC_CAPIEXT) 2> $(NULL) || $(NULLCMD)
+ -$(Q) $(RMALL) rubyspec_temp
check: main test test-tool test-all test-spec
$(ECHO) check succeeded
- -$(Q) if [ x"$(GIT)" != x ] && $(CHDIR) "$(srcdir)" && $(GIT) rev-parse > /dev/null 2>&1; then \
- set -x; $(GIT) --no-pager log --format=oneline -G "^ *# *include" origin/master..HEAD; \
+ -$(Q) if [ x"$(GIT)" != x ] && $(CHDIR) "$(srcdir)" && \
+ b=`$(GIT) symbolic-ref --short HEAD 2>&1` && \
+ u=`$(GIT) branch --list --format='%(upstream:short)' $$b`; then \
+ set -x; $(GIT) --no-pager log --format=oneline -G "^ *# *include" $$u..HEAD --; \
fi
check-ruby: test test-ruby
@@ -734,10 +749,10 @@ no-fake -fake: PHONY
# really doesn't depend on .o, just ensure newer than headers which
# version.o depends on.
-$(arch)-fake.rb: $(srcdir)/template/fake.rb.in $(srcdir)/tool/generic_erb.rb version.$(OBJEXT) miniruby$(EXEEXT)
+$(arch)-fake.rb: $(srcdir)/template/fake.rb.in $(tooldir)/generic_erb.rb version.$(OBJEXT) miniruby$(EXEEXT)
$(ECHO) generating $@
$(Q) $(CPP) -DRUBY_EXPORT $(INCFLAGS) $(CPPFLAGS) "$(srcdir)/version.c" | \
- $(BOOTSTRAPRUBY) "$(srcdir)/tool/generic_erb.rb" -o $@ "$(srcdir)/template/fake.rb.in" \
+ $(BOOTSTRAPRUBY) "$(tooldir)/generic_erb.rb" -o $@ "$(srcdir)/template/fake.rb.in" \
i=- srcdir="$(srcdir)" BASERUBY="$(BASERUBY)"
btest: $(TEST_RUNNABLE)-btest
@@ -750,6 +765,9 @@ no-btest-ruby: PHONY
yes-btest-ruby: prog PHONY
$(Q)$(exec) $(RUNRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(PROGRAM) -I$(srcdir)/lib $(RUN_OPTS)" -q $(OPTS) $(TESTOPTS) $(BTESTS)
+rtest: fake miniruby$(EXEEXT) PHONY
+ $(Q)$(exec) $(BOOTSTRAPRUBY) "$(srcdir)/bootstraptest/runner.rb" --ruby="$(BTESTRUBY) $(RUN_OPTS)" --sets=ractor -v
+
test-basic: $(TEST_RUNNABLE)-test-basic
no-test-basic: PHONY
yes-test-basic: prog PHONY
@@ -797,13 +815,13 @@ extconf: $(PREP)
$(Q) $(MAKEDIRS) "$(EXTCONFDIR)"
$(RUNRUBY) -C "$(EXTCONFDIR)" $(EXTCONF) $(EXTCONFARGS)
-$(RBCONFIG): $(srcdir)/tool/mkconfig.rb config.status $(srcdir)/version.h
+$(RBCONFIG): $(tooldir)/mkconfig.rb config.status $(srcdir)/version.h
$(Q)$(BOOTSTRAPRUBY) -n \
-e 'BEGIN{version=ARGV.shift;mis=ARGV.dup}' \
-e 'END{abort "UNICODE version mismatch: #{mis}" unless mis.empty?}' \
-e '(mis.delete(ARGF.path); ARGF.close) if /ONIG_UNICODE_VERSION_STRING +"#{Regexp.quote(version)}"/o' \
$(UNICODE_VERSION) $(UNICODE_DATA_HEADERS)
- $(Q)$(BOOTSTRAPRUBY) $(srcdir)/tool/mkconfig.rb \
+ $(Q)$(BOOTSTRAPRUBY) $(tooldir)/mkconfig.rb \
-arch=$(arch) -version=$(RUBY_PROGRAM_VERSION) \
-install_name=$(RUBY_INSTALL_NAME) \
-so_name=$(RUBY_SO_NAME) \
@@ -815,17 +833,17 @@ $(RBCONFIG): $(srcdir)/tool/mkconfig.rb config.status $(srcdir)/version.h
test-rubyspec: test-spec
yes-test-rubyspec: yes-test-spec
-test-spec-precheck: $(arch)-fake.rb programs
+test-spec-precheck: main
test-spec: $(TEST_RUNNABLE)-test-spec
yes-test-spec: test-spec-precheck
$(gnumake_recursive)$(Q) \
- $(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec run -B $(srcdir)/spec/default.mspec $(MSPECOPT) $(SPECOPTS)
+ $(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec run -B $(srcdir)/spec/default.mspec -I$(srcdir)/tool/lib $(MSPECOPT) $(SPECOPTS)
no-test-spec:
RUNNABLE = $(LIBRUBY_RELATIVE:no=un)-runnable
-runnable: $(RUNNABLE) prog $(srcdir)/tool/mkrunnable.rb PHONY
- $(Q) $(MINIRUBY) $(srcdir)/tool/mkrunnable.rb -v $(EXTOUT)
+runnable: $(RUNNABLE) prog $(tooldir)/mkrunnable.rb PHONY
+ $(Q) $(MINIRUBY) $(tooldir)/mkrunnable.rb -v $(EXTOUT)
yes-runnable: PHONY
encs: enc trans
@@ -859,16 +877,17 @@ $(ENC_MK): $(srcdir)/enc/make_encmake.rb $(srcdir)/enc/Makefile.in $(srcdir)/enc
PHONY:
-{$(VPATH)}parse.c: {$(VPATH)}parse.y $(srcdir)/tool/ytab.sed {$(VPATH)}id.h
+{$(VPATH)}parse.c: {$(VPATH)}parse.y $(tooldir)/ytab.sed {$(VPATH)}id.h
{$(VPATH)}parse.h: {$(VPATH)}parse.c
{$(srcdir)}.y.c:
$(ECHO) generating $@
- $(Q)$(BASERUBY) $(srcdir)/tool/id2token.rb --path-separator=.$(PATH_SEPARATOR)./ --vpath=$(VPATH) id.h $(SRC_FILE) > parse.tmp.y
- $(Q)$(BASERUBY) $(srcdir)/tool/pure_parser.rb parse.tmp.y $(YACC)
+ $(Q)$(BASERUBY) $(tooldir)/id2token.rb --path-separator=.$(PATH_SEPARATOR)./ --vpath=$(VPATH) id.h $(SRC_FILE) > parse.tmp.y
+ $(Q)$(BASERUBY) $(tooldir)/pure_parser.rb parse.tmp.y $(YACC)
+ $(Q)$(RM) parse.tmp.y.bak
$(Q)$(YACC) -d $(YFLAGS) -o y.tab.c parse.tmp.y
$(Q)$(RM) parse.tmp.y
- $(Q)sed -f $(srcdir)/tool/ytab.sed -e "/^#/s|parse\.tmp\.[iy]|$(SRC_FILE)|" -e "/^#/s!y\.tab\.c!$@!" y.tab.c > $@.new
+ $(Q)sed -f $(tooldir)/ytab.sed -e "/^#/s|parse\.tmp\.[iy]|$(SRC_FILE)|" -e "/^#/s!y\.tab\.c!$@!" y.tab.c > $@.new
$(Q)$(MV) $@.new $@
$(Q)sed -e "/^#line.*y\.tab\.h/d;/^#line.*parse.*\.y/d" y.tab.h > $(@:.c=.h)
$(Q)$(RM) y.tab.c y.tab.h
@@ -960,14 +979,14 @@ win32/win32.$(OBJEXT): {$(VPATH)}win32/win32.c {$(VPATH)}win32/file.h \
win32/file.$(OBJEXT): {$(VPATH)}win32/file.c {$(VPATH)}win32/file.h \
$(RUBY_H_INCLUDES) $(PLATFORM_D)
-$(NEWLINE_C): $(srcdir)/enc/trans/newline.trans $(srcdir)/tool/transcode-tblgen.rb
+$(NEWLINE_C): $(srcdir)/enc/trans/newline.trans $(tooldir)/transcode-tblgen.rb
$(Q) $(MAKEDIRS) $(@D)
- $(Q) $(BASERUBY) "$(srcdir)/tool/transcode-tblgen.rb" -vo $@ $(srcdir)/enc/trans/newline.trans
+ $(Q) $(BASERUBY) "$(tooldir)/transcode-tblgen.rb" -vo $@ $(srcdir)/enc/trans/newline.trans
enc/trans/newline.$(OBJEXT): $(NEWLINE_C)
-verconf.h: $(srcdir)/template/verconf.h.tmpl $(srcdir)/tool/generic_erb.rb
+verconf.h: $(srcdir)/template/verconf.h.tmpl $(tooldir)/generic_erb.rb
$(ECHO) creating $@
- $(Q) $(BOOTSTRAPRUBY) "$(srcdir)/tool/generic_erb.rb" -o $@ $(srcdir)/template/verconf.h.tmpl
+ $(Q) $(BOOTSTRAPRUBY) "$(tooldir)/generic_erb.rb" -o $@ $(srcdir)/template/verconf.h.tmpl
ruby-glommed.$(OBJEXT): $(OBJS)
@@ -977,31 +996,37 @@ INSNS2VMOPT = --srcdir="$(srcdir)"
srcs_vpath = {$(VPATH)}
-inc_common_headers = $(srcdir)/tool/ruby_vm/views/_copyright.erb $(srcdir)/tool/ruby_vm/views/_notice.erb
-$(srcs_vpath)opt_sc.inc: $(srcdir)/tool/ruby_vm/views/opt_sc.inc.erb $(inc_common_headers)
-$(srcs_vpath)optinsn.inc: $(srcdir)/tool/ruby_vm/views/optinsn.inc.erb $(inc_common_headers)
-$(srcs_vpath)optunifs.inc: $(srcdir)/tool/ruby_vm/views/optunifs.inc.erb $(inc_common_headers)
-$(srcs_vpath)insns.inc: $(srcdir)/tool/ruby_vm/views/insns.inc.erb $(inc_common_headers)
-$(srcs_vpath)insns_info.inc: $(srcdir)/tool/ruby_vm/views/insns_info.inc.erb $(inc_common_headers) \
- $(srcdir)/tool/ruby_vm/views/_insn_type_chars.erb $(srcdir)/tool/ruby_vm/views/_insn_name_info.erb \
- $(srcdir)/tool/ruby_vm/views/_insn_len_info.erb $(srcdir)/tool/ruby_vm/views/_insn_operand_info.erb \
- $(srcdir)/tool/ruby_vm/views/_attributes.erb $(srcdir)/tool/ruby_vm/views/_comptime_insn_stack_increase.erb \
- $(srcdir)/tool/ruby_vm/views/_insn_sp_pc_dependency.erb
-$(srcs_vpath)vmtc.inc: $(srcdir)/tool/ruby_vm/views/vmtc.inc.erb $(inc_common_headers)
-$(srcs_vpath)vm.inc: $(srcdir)/tool/ruby_vm/views/vm.inc.erb $(inc_common_headers) \
- $(srcdir)/tool/ruby_vm/views/_insn_entry.erb $(srcdir)/tool/ruby_vm/views/_trace_instruction.erb
-$(srcs_vpath)mjit_compile.inc: $(srcdir)/tool/ruby_vm/views/mjit_compile.inc.erb $(inc_common_headers) \
- $(srcdir)/tool/ruby_vm/views/_mjit_compile_insn.erb $(srcdir)/tool/ruby_vm/views/_mjit_compile_send.erb \
- $(srcdir)/tool/ruby_vm/views/_mjit_compile_ivar.erb \
- $(srcdir)/tool/ruby_vm/views/_mjit_compile_insn_body.erb $(srcdir)/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb
+inc_common_headers = $(tooldir)/ruby_vm/views/_copyright.erb $(tooldir)/ruby_vm/views/_notice.erb
+$(srcs_vpath)opt_sc.inc: $(tooldir)/ruby_vm/views/opt_sc.inc.erb $(inc_common_headers)
+$(srcs_vpath)optinsn.inc: $(tooldir)/ruby_vm/views/optinsn.inc.erb $(inc_common_headers)
+$(srcs_vpath)optunifs.inc: $(tooldir)/ruby_vm/views/optunifs.inc.erb $(inc_common_headers)
+$(srcs_vpath)insns.inc: $(tooldir)/ruby_vm/views/insns.inc.erb $(inc_common_headers)
+$(srcs_vpath)insns_info.inc: $(tooldir)/ruby_vm/views/insns_info.inc.erb $(inc_common_headers) \
+ $(tooldir)/ruby_vm/views/_insn_type_chars.erb $(tooldir)/ruby_vm/views/_insn_name_info.erb \
+ $(tooldir)/ruby_vm/views/_insn_len_info.erb $(tooldir)/ruby_vm/views/_insn_operand_info.erb \
+ $(tooldir)/ruby_vm/views/_attributes.erb $(tooldir)/ruby_vm/views/_comptime_insn_stack_increase.erb \
+ $(tooldir)/ruby_vm/views/_insn_sp_pc_dependency.erb
+$(srcs_vpath)vmtc.inc: $(tooldir)/ruby_vm/views/vmtc.inc.erb $(inc_common_headers)
+$(srcs_vpath)vm.inc: $(tooldir)/ruby_vm/views/vm.inc.erb $(inc_common_headers) \
+ $(tooldir)/ruby_vm/views/_insn_entry.erb $(tooldir)/ruby_vm/views/_trace_instruction.erb
+$(srcs_vpath)mjit_compile.inc: $(tooldir)/ruby_vm/views/mjit_compile.inc.erb $(inc_common_headers) \
+ $(tooldir)/ruby_vm/views/_mjit_compile_insn.erb $(tooldir)/ruby_vm/views/_mjit_compile_send.erb \
+ $(tooldir)/ruby_vm/views/_mjit_compile_ivar.erb \
+ $(tooldir)/ruby_vm/views/_mjit_compile_insn_body.erb $(tooldir)/ruby_vm/views/_mjit_compile_pc_and_sp.erb \
+ $(tooldir)/ruby_vm/views/_mjit_compile_invokebuiltin.erb
BUILTIN_RB_SRCS = \
$(srcdir)/ast.rb \
+ $(srcdir)/dir.rb \
$(srcdir)/gc.rb \
+ $(srcdir)/integer.rb \
$(srcdir)/io.rb \
$(srcdir)/pack.rb \
$(srcdir)/trace_point.rb \
$(srcdir)/warning.rb \
+ $(srcdir)/array.rb \
+ $(srcdir)/kernel.rb \
+ $(srcdir)/ractor.rb \
$(srcdir)/prelude.rb \
$(srcdir)/gem_prelude.rb \
$(empty)
@@ -1051,46 +1076,46 @@ incs: $(INSNS) {$(VPATH)}node_name.inc {$(VPATH)}known_errors.inc \
insns: $(INSNS)
-id.h: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.h.tmpl $(srcdir)/defs/id.def
+id.h: $(tooldir)/generic_erb.rb $(srcdir)/template/id.h.tmpl $(srcdir)/defs/id.def
$(ECHO) generating $@
- $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \
+ $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb --output=$@ \
$(srcdir)/template/id.h.tmpl
-id.c: $(srcdir)/tool/generic_erb.rb $(srcdir)/template/id.c.tmpl $(srcdir)/defs/id.def
+id.c: $(tooldir)/generic_erb.rb $(srcdir)/template/id.c.tmpl $(srcdir)/defs/id.def
$(ECHO) generating $@
- $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb --output=$@ \
+ $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb --output=$@ \
$(srcdir)/template/id.c.tmpl
-node_name.inc: $(srcdir)/tool/node_name.rb $(srcdir)/node.h
+node_name.inc: $(tooldir)/node_name.rb $(srcdir)/node.h
$(ECHO) generating $@
- $(Q) $(BASERUBY) -n $(srcdir)/tool/node_name.rb < $(srcdir)/node.h > $@
+ $(Q) $(BASERUBY) -n $(tooldir)/node_name.rb < $(srcdir)/node.h > $@
-encdb.h: $(PREP) $(srcdir)/tool/generic_erb.rb $(srcdir)/template/encdb.h.tmpl
+encdb.h: $(PREP) $(tooldir)/generic_erb.rb $(srcdir)/template/encdb.h.tmpl
$(ECHO) generating $@
- $(Q) $(MINIRUBY) $(srcdir)/tool/generic_erb.rb -c -o $@ $(srcdir)/template/encdb.h.tmpl $(srcdir)/enc enc
+ $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/encdb.h.tmpl $(srcdir)/enc enc
-transdb.h: $(PREP) srcs-enc $(srcdir)/tool/generic_erb.rb $(srcdir)/template/transdb.h.tmpl
+transdb.h: $(PREP) srcs-enc $(tooldir)/generic_erb.rb $(srcdir)/template/transdb.h.tmpl
$(ECHO) generating $@
- $(Q) $(MINIRUBY) $(srcdir)/tool/generic_erb.rb -c -o $@ $(srcdir)/template/transdb.h.tmpl $(srcdir)/enc/trans enc/trans
+ $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/transdb.h.tmpl $(srcdir)/enc/trans enc/trans
enc/encinit.c: $(ENC_MK) $(srcdir)/enc/encinit.c.erb
known_errors.inc: $(srcdir)/template/known_errors.inc.tmpl $(srcdir)/defs/known_errors.def
$(ECHO) generating $@
- $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb -c -o $@ $(srcdir)/template/known_errors.inc.tmpl $(srcdir)/defs/known_errors.def
+ $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/known_errors.inc.tmpl $(srcdir)/defs/known_errors.def
-vm_call_iseq_optimized.inc: $(srcdir)/tool/mk_call_iseq_optimized.rb
+vm_call_iseq_optimized.inc: $(srcdir)/template/call_iseq_optimized.inc.tmpl
$(ECHO) generating $@
- $(Q) $(BASERUBY) $(srcdir)/tool/mk_call_iseq_optimized.rb > $@
+ $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -c -o $@ $(srcdir)/template/call_iseq_optimized.inc.tmpl
$(MINIPRELUDE_C): $(COMPILE_PRELUDE) $(BUILTIN_RB_SRCS)
$(ECHO) generating $@
- $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb -I$(srcdir) -o $@ \
+ $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -I$(srcdir) -o $@ \
$(srcdir)/template/prelude.c.tmpl $(BUILTIN_RB_SRCS)
$(GOLF_PRELUDE_C): $(COMPILE_PRELUDE) {$(srcdir)}golf_prelude.rb
$(ECHO) generating $@
- $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb -I$(srcdir) -c -o $@ \
+ $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -I$(srcdir) -c -o $@ \
$(srcdir)/template/prelude.c.tmpl golf_prelude.rb
MAINCPPFLAGS = $(ENABLE_DEBUG_ENV:yes=-DRUBY_DEBUG_ENV=1)
@@ -1099,10 +1124,10 @@ $(MAINOBJ): $(srcdir)/$(MAINSRC)
$(ECHO) compiling $(srcdir)/$(MAINSRC)
$(Q) $(CC) $(MAINCPPFLAGS) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$(srcdir)/$(MAINSRC)
-{$(VPATH)}probes.dmyh: {$(srcdir)}probes.d $(srcdir)/tool/gen_dummy_probes.rb
+{$(VPATH)}probes.dmyh: {$(srcdir)}probes.d $(tooldir)/gen_dummy_probes.rb
probes.dmyh:
- $(BASERUBY) $(srcdir)/tool/gen_dummy_probes.rb $(srcdir)/probes.d > $@
+ $(BASERUBY) $(tooldir)/gen_dummy_probes.rb $(srcdir)/probes.d > $@
probes.h: {$(VPATH)}probes.$(DTRACE_EXT)
@@ -1113,10 +1138,11 @@ preludes: {$(srcdir)}golf_prelude.c
{$(srcdir)}.rb.rbinc:
$(ECHO) making $@
- $(Q) $(BASERUBY) $(srcdir)/tool/mk_builtin_loader.rb $<
+ $(Q) $(BASERUBY) $(tooldir)/mk_builtin_loader.rb $<
-builtin_binary.inc: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/tool/mk_builtin_binary.rb
- $(Q) $(MINIRUBY) $(srcdir)/tool/mk_builtin_binary.rb --cross=$(CROSS_COMPILING)
+builtin_binary.inc: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/template/builtin_binary.inc.tmpl
+ $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ \
+ $(srcdir)/template/builtin_binary.inc.tmpl -- --cross=$(CROSS_COMPILING)
$(BUILTIN_RB_INCS): $(top_srcdir)/tool/mk_builtin_loader.rb
@@ -1126,8 +1152,8 @@ $(srcdir)/revision.h:
revision.tmp::
$(Q) $(NULLCMD) > $@
-revision.$(HAVE_BASERUBY:yes=tmp):: $(srcdir)/version.h $(srcdir)/tool/file2lastrev.rb $(REVISION_FORCE)
- $(Q) $(BASERUBY) $(srcdir)/tool/file2lastrev.rb -q --revision.h --srcdir="$(srcdir)" > $@
+revision.$(HAVE_BASERUBY:yes=tmp):: $(srcdir)/version.h $(tooldir)/file2lastrev.rb $(REVISION_FORCE)
+ $(Q) $(BASERUBY) $(tooldir)/file2lastrev.rb -q --revision.h --srcdir="$(srcdir)" > $@
$(REVISION_H): revision.tmp
$(Q)$(IFCHANGE) "--timestamp=$@" "$(srcdir)/revision.h" revision.tmp
@@ -1138,7 +1164,7 @@ $(srcdir)/ext/ripper/ripper.c: $(srcdir)/ext/ripper/tools/preproc.rb $(srcdir)/p
sed -e 's/{\$$([^(){}]*)[^{}]*}//g' -e /AUTOGENERATED/q depend | \
$(exec) $(MAKE) -f - $(mflags) \
Q=$(Q) ECHO=$(ECHO) RM="$(RM)" BISON=$(YACC) top_srcdir=../.. srcdir=. VPATH="$${VPATH}" \
- RUBY="$(BASERUBY)" PATH_SEPARATOR="$(PATH_SEPARATOR)"
+ RUBY="$(BASERUBY)" PATH_SEPARATOR="$(PATH_SEPARATOR)" LANG=C
$(srcdir)/ext/json/parser/parser.c: $(srcdir)/ext/json/parser/parser.rl $(srcdir)/ext/json/parser/prereq.mk
$(ECHO) generating $@
@@ -1151,7 +1177,7 @@ $(srcdir)/ext/date/zonetab.h: $(srcdir)/ext/date/zonetab.list $(srcdir)/ext/date
Q=$(Q) ECHO=$(ECHO) top_srcdir=../.. srcdir=. VPATH=../.. BASERUBY="$(BASERUBY)"
$(srcdir)/ext/rbconfig/sizeof/sizes.c: $(srcdir)/ext/rbconfig/sizeof/depend \
- $(srcdir)/tool/generic_erb.rb $(srcdir)/template/sizes.c.tmpl $(srcdir)/configure.ac
+ $(tooldir)/generic_erb.rb $(srcdir)/template/sizes.c.tmpl $(srcdir)/configure.ac
$(ECHO) generating $@
$(Q) $(CHDIR) $(@D) && \
sed '/AUTOGENERATED/q' depend | \
@@ -1159,7 +1185,7 @@ $(srcdir)/ext/rbconfig/sizeof/sizes.c: $(srcdir)/ext/rbconfig/sizeof/depend \
Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. RUBY="$(BASERUBY)" $(@F)
$(srcdir)/ext/rbconfig/sizeof/limits.c: $(srcdir)/ext/rbconfig/sizeof/depend \
- $(srcdir)/tool/generic_erb.rb $(srcdir)/template/limits.c.tmpl
+ $(tooldir)/generic_erb.rb $(srcdir)/template/limits.c.tmpl
$(ECHO) generating $@
$(Q) $(CHDIR) $(@D) && \
sed '/AUTOGENERATED/q' depend | \
@@ -1181,22 +1207,23 @@ $(srcdir)/ext/etc/constdefs.h: $(srcdir)/ext/etc/depend
##
run: fake miniruby$(EXEEXT) PHONY
- $(BTESTRUBY) $(TESTRUN_SCRIPT) $(RUNOPT)
+ $(BTESTRUBY) $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT)
runruby: $(PROGRAM) PHONY
- $(RUNRUBY) $(TESTRUN_SCRIPT)
+ $(RUNRUBY) $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT)
parse: fake miniruby$(EXEEXT) PHONY
$(BTESTRUBY) --dump=parsetree_with_comment,insns $(TESTRUN_SCRIPT)
bisect: PHONY
- $(srcdir)/tool/bisect.sh miniruby $(srcdir)
+ $(tooldir)/bisect.sh miniruby $(srcdir)
bisect-ruby: PHONY
- $(srcdir)/tool/bisect.sh ruby $(srcdir)
+ $(tooldir)/bisect.sh ruby $(srcdir)
COMPARE_RUBY = $(BASERUBY)
BENCH_RUBY = $(RUNRUBY)
+BENCH_OPTS = --output=markdown --output-compare
ITEM =
ARGS = $$(find $(srcdir)/benchmark -maxdepth 1 -name '$(ITEM)' -o -name '*$(ITEM)*.yml' -o -name '*$(ITEM)*.rb' | sort)
OPTS =
@@ -1206,10 +1233,12 @@ benchmark: miniruby$(EXEEXT) update-benchmark-driver PHONY
$(BASERUBY) -rrubygems -I$(srcdir)/benchmark/lib $(srcdir)/benchmark/benchmark-driver/exe/benchmark-driver \
--executables="compare-ruby::$(COMPARE_RUBY) -I$(EXTOUT)/common --disable-gem" \
--executables="built-ruby::$(BENCH_RUBY) --disable-gem" \
- $(ARGS) $(OPTS)
+ $(BENCH_OPTS) $(ARGS) $(OPTS)
run.gdb:
echo set breakpoint pending on > run.gdb
+ echo b rb_assert_failure >> run.gdb
+ echo b rb_bug >> run.gdb
echo b ruby_debug_breakpoint >> run.gdb
echo '# handle SIGINT nostop' >> run.gdb
echo '# handle SIGPIPE nostop' >> run.gdb
@@ -1224,37 +1253,36 @@ run.gdb:
gdb: miniruby$(EXEEXT) run.gdb PHONY
- gdb -x run.gdb --quiet --args $(MINIRUBY) $(TESTRUN_SCRIPT)
+ gdb -x run.gdb --quiet --args $(MINIRUBY) $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT)
gdb-ruby: $(PROGRAM) run.gdb PHONY
- $(Q) $(RUNRUBY_COMMAND) $(RUNRUBY_DEBUGGER) -- $(TESTRUN_SCRIPT)
+ $(Q) $(RUNRUBY_COMMAND) $(RUNRUBY_DEBUGGER) -- $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT)
LLDB_INIT = command script import -r $(srcdir)/misc/lldb_cruby.py
lldb: miniruby$(EXEEXT) PHONY
- lldb -o '$(LLDB_INIT)' miniruby$(EXEEXT) -- $(TESTRUN_SCRIPT)
+ lldb -o '$(LLDB_INIT)' miniruby$(EXEEXT) -- $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT)
lldb-ruby: $(PROGRAM) PHONY
- lldb $(enable_shared:yes=-o 'target modules add ${LIBRUBY_SO}') -o '$(LLDB_INIT)' $(PROGRAM) -- $(TESTRUN_SCRIPT)
+ lldb $(enable_shared:yes=-o 'target modules add ${LIBRUBY_SO}') -o '$(LLDB_INIT)' $(PROGRAM) -- $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT)
DISTPKGS = gzip,zip,all
+PKGSDIR = tmp
dist:
- $(BASERUBY) $(srcdir)/tool/make-snapshot \
+ $(BASERUBY) $(tooldir)/make-snapshot \
-srcdir=$(srcdir) -packages=$(DISTPKGS) \
-unicode-version=$(UNICODE_VERSION) \
- tmp $(RELNAME)
+ $(DISTOPTS) $(PKGSDIR) $(RELNAME)
up:: update-remote
up::
- -$(Q)$(MAKE) $(mflags) Q=$(Q) REVISION_FORCE=PHONY "$(REVISION_H)"
-
-up::
- -$(Q)$(MAKE) $(mflags) Q=$(Q) after-update
+ -$(Q)$(MAKE) $(mflags) Q=$(Q) REVISION_FORCE=PHONY after-update
yes::
no::
+after-update:: $(REVISION_H)
after-update:: extract-extlibs
after-update:: extract-gems
@@ -1270,13 +1298,15 @@ update-config_files: PHONY
$(Q) $(BASERUBY) -C "$(srcdir)" tool/downloader.rb -d tool --cache-dir=$(CACHE_DIR) -e gnu \
config.guess config.sub
-refresh-gems: update-bundled_gems update-gems extract-gems
+refresh-gems: update-bundled_gems prepare-gems
+prepare-gems: $(HAVE_BASERUBY:yes=update-gems) $(HAVE_BASERUBY:yes=extract-gems)
-update-gems: PHONY
+update-gems$(gnumake:yes=-nongnumake): PHONY
$(ECHO) Downloading bundled gem files...
$(Q) $(BASERUBY) -C "$(srcdir)" \
-I./tool -rdownloader -answ \
-e 'gem, ver = *$$F' \
+ -e 'next if !ver or /^#/=~gem' \
-e 'old = Dir.glob("gems/#{gem}-*.gem")' \
-e 'gem = "#{gem}-#{ver}.gem"' \
-e 'Downloader::RubyGems.download(gem, "gems", nil) and' \
@@ -1285,35 +1315,36 @@ update-gems: PHONY
-e 'FileUtils.rm_rf(old.map{'"|n|"'n.chomp(".gem")})' \
gems/bundled_gems
-extract-gems: PHONY
+extract-gems$(gnumake:yes=-nongnumake): PHONY
$(ECHO) Extracting bundled gem files...
- $(Q) $(RUNRUBY) -C "$(srcdir)/gems" \
- -I../tool -rgem-unpack -answ \
+ $(Q) $(RUNRUBY) -C "$(srcdir)" \
+ -Itool -rgem-unpack -answ \
+ -e 'BEGIN {FileUtils.mkdir_p(d = ".bundle/gems")}' \
-e 'gem, ver = *$$F' \
- -e 'Gem.unpack("#{gem}-#{ver}.gem")' \
- bundled_gems
+ -e 'next if !ver or /^#/=~gem' \
+ -e 'g = "#{gem}-#{ver}"' \
+ -e 'File.directory?("#{d}/#{g}") or Gem.unpack("gems/#{g}.gem", d)' \
+ gems/bundled_gems
update-bundled_gems: PHONY
$(Q) $(RUNRUBY) -rrubygems \
- -pla \
- -e '(gem,src), = Gem::SpecFetcher.fetcher.detect(:latest) {'"|s|" \
- -e 's.platform=="ruby"&&s.name==$$F[0]' \
- -e '}' \
- -e 'gem = src.fetch_spec(gem)' \
- -e 'uri = gem.metadata["source_code_uri"]||gem.homepage' \
- -e 'uri = uri.sub(%r[\Ahttps://github\.com/[^/]+/[^/]+\K/tree/.*], "")' \
- -e '$$_ = [gem.name, gem.version, uri].join(" ")' \
+ $(tooldir)/update-bundled_gems.rb \
"$(srcdir)/gems/bundled_gems" | \
"$(IFCHANGE)" "$(srcdir)/gems/bundled_gems" -
-test-bundled-gems-precheck: $(arch)-fake.rb programs
+test-bundled-gems-precheck: $(TEST_RUNNABLE)-test-bundled-gems-precheck
+yes-test-bundled-gems-precheck: main
+no-test-bundled-gems-precheck:
test-bundled-gems-fetch: $(PREP)
$(Q) $(BASERUBY) -C $(srcdir)/gems ../tool/fetch-bundled_gems.rb src bundled_gems
test-bundled-gems-prepare: test-bundled-gems-precheck test-bundled-gems-fetch
+test-bundled-gems-prepare: $(TEST_RUNNABLE)-test-bundled-gems-prepare
+no-test-bundled-gems-prepare: no-test-bundled-gems-precheck
+yes-test-bundled-gems-prepare: yes-test-bundled-gems-precheck
$(XRUBY) -C "$(srcdir)" bin/gem install --no-document \
- --install-dir .bundle --conservative "bundler" "minitest:~> 5" 'test-unit' 'rake' 'hoe' 'yard' 'pry' 'packnga'
+ --install-dir .bundle --conservative "bundler" "minitest:~> 5" "test-unit" "rake" "hoe" "yard" "pry" "packnga" "rexml" "json-schema" "rbs:~> 1.6.2"
PREPARE_BUNDLED_GEMS = test-bundled-gems-prepare
test-bundled-gems: $(TEST_RUNNABLE)-test-bundled-gems
@@ -1323,14 +1354,18 @@ no-test-bundled-gems:
# Override this to allow failure of specific gems on CI
# TEST_BUNDLED_GEMS_ALLOW_FAILURES =
+BUNDLED_GEMS =
test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS)
- $(Q) $(XRUBY) $(srcdir)/tool/test-bundled-gems.rb
+ $(Q) $(XRUBY) $(tooldir)/test-bundled-gems.rb $(BUNDLED_GEMS)
-test-bundler-precheck: $(arch)-fake.rb programs
+test-bundler-precheck: $(TEST_RUNNABLE)-test-bundler-precheck
+no-test-bundler-precheck:
+yes-test-bundler-precheck: main
-yes-test-bundler-prepare: test-bundler-precheck
+no-test-bundler-prepare: no-test-bundler-precheck
+yes-test-bundler-prepare: yes-test-bundler-precheck
$(XRUBY) -C "$(srcdir)" bin/gem install --no-document \
- --install-dir .bundle --conservative "rspec:~> 3.5" "rake:~> 12.0" "parallel_tests:~> 2.29"
+ --install-dir .bundle --conservative "rspec:~> 3.8" "rake:~> 13.0" "parallel_tests:~> 2.29"
RSPECOPTS =
BUNDLER_SPECS =
@@ -1343,9 +1378,13 @@ no-test-bundler:
PARALLELRSPECOPTS = --runtime-log $(srcdir)/tmp/parallel_runtime_rspec.log
test-bundler-parallel: $(TEST_RUNNABLE)-test-bundler-parallel
yes-test-bundler-parallel: yes-test-bundler-prepare
- $(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/parallel_rspec \
- -o "--require $(srcdir)/spec/bundler/spec_helper --require $(srcdir)/spec/bundler/support/parallel" \
- $(PARALLELRSPECOPTS) spec/bundler/$(BUNDLER_SPECS)
+ $(XRUBY) -I$(srcdir)/spec/bundler \
+ -e "ENV['PARALLEL_TESTS_EXECUTABLE'] = ARGV.shift" \
+ -e "load ARGV.shift" \
+ "$(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/rspec" \
+ $(srcdir)/.bundle/bin/parallel_rspec \
+ -o "--require spec_helper" \
+ $(PARALLELRSPECOPTS) $(srcdir)/spec/bundler/$(BUNDLER_SPECS)
no-test-bundler-parallel:
GEM = up
@@ -1387,21 +1426,21 @@ update-unicode: $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) \
CACHE_DIR = $(srcdir)/.downloaded-cache
UNICODE_DOWNLOAD = \
- $(BASERUBY) $(srcdir)/tool/downloader.rb \
+ $(BASERUBY) $(tooldir)/downloader.rb \
--cache-dir=$(CACHE_DIR) \
--unicode-beta $(UNICODE_BETA) \
-d $(UNICODE_SRC_DATA_DIR) \
-p $(UNICODE_VERSION)/ucd \
-e $(ALWAYS_UPDATE_UNICODE:yes=-a) unicode
UNICODE_AUXILIARY_DOWNLOAD = \
- $(BASERUBY) $(srcdir)/tool/downloader.rb \
+ $(BASERUBY) $(tooldir)/downloader.rb \
--cache-dir=$(CACHE_DIR) \
--unicode-beta $(UNICODE_BETA) \
-d $(UNICODE_SRC_DATA_DIR)/auxiliary \
-p $(UNICODE_VERSION)/ucd/auxiliary \
-e $(ALWAYS_UPDATE_UNICODE:yes=-a) unicode
UNICODE_EMOJI_DOWNLOAD = \
- $(BASERUBY) $(srcdir)/tool/downloader.rb \
+ $(BASERUBY) $(tooldir)/downloader.rb \
--cache-dir=$(CACHE_DIR) \
--unicode-beta $(UNICODE_BETA) \
-d $(UNICODE_SRC_EMOJI_DATA_DIR) \
@@ -1438,11 +1477,11 @@ touch-unicode-files:
touch $(UNICODE_SRC_DATA_DIR)/.unicode-tables.time $(UNICODE_DATA_HEADERS)
UNICODE_TABLES_TIMESTAMP = yes
-$(UNICODE_SRC_DATA_DIR)/.unicode-tables.time: $(srcdir)/tool/generic_erb.rb \
+$(UNICODE_SRC_DATA_DIR)/.unicode-tables.time: $(tooldir)/generic_erb.rb \
$(srcdir)/template/unicode_norm_gen.tmpl \
$(ALWAYS_UPDATE_UNICODE:yes=update-unicode)
$(Q) $(MAKE) $(@D)
- $(Q) $(BASERUBY) $(srcdir)/tool/generic_erb.rb \
+ $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb \
-c $(UNICODE_TABLES_TIMESTAMP:yes=-t$@) \
-o $(srcdir)/lib/unicode_normalize/tables.rb \
-I $(srcdir) \
@@ -1453,14 +1492,14 @@ $(UNICODE_SRC_DATA_DIR):
$(gnumake_recursive)$(Q) $(MAKEDIRS) $@
$(UNICODE_HDR_DIR)/$(ALWAYS_UPDATE_UNICODE:yes=name2ctype.h): \
- $(srcdir)/tool/enc-unicode.rb \
+ $(tooldir)/enc-unicode.rb \
$(UNICODE_SRC_DATA_DIR)/UnicodeData.txt \
$(UNICODE_PROPERTY_FILES) \
$(UNICODE_EMOJI_FILES)
$(UNICODE_HDR_DIR)/name2ctype.h:
$(MAKEDIRS) $(@D)
- $(BOOTSTRAPRUBY) $(srcdir)/tool/enc-unicode.rb --header \
+ $(BOOTSTRAPRUBY) $(tooldir)/enc-unicode.rb --header \
$(UNICODE_SRC_DATA_DIR) $(UNICODE_SRC_EMOJI_DATA_DIR) > $@.new
$(MV) $@.new $@
@@ -1518,11 +1557,18 @@ sudo-precheck: PHONY
@$(SUDO) echo > $(NULL)
update-man-date: PHONY
- -$(Q) $(BASERUBY) -I"$(srcdir)/tool/lib" -rvcs -i -p \
+ -$(Q) $(BASERUBY) -I"$(tooldir)/lib" -rvcs -i -p \
-e 'BEGIN{@vcs=VCS.detect(ARGV.shift)}' \
-e '$$_.sub!(/^(\.Dd ).*/){$$1+@vcs.modified(ARGF.path).strftime("%B %d, %Y")}' \
"$(srcdir)" "$(srcdir)"/man/*.1
+.PHONY: ChangeLog
+ChangeLog:
+ $(ECHO) Generating $@
+ -$(Q) $(BASERUBY) -I"$(tooldir)/lib" -rvcs \
+ -e 'VCS.detect(ARGV[0]).export_changelog("@", nil, nil, ARGV[1])' \
+ "$(srcdir)" $@
+
HELP_EXTRA_TASKS = ""
help: PHONY
@@ -1568,20 +1614,241 @@ help: PHONY
# AUTOGENERATED DEPENDENCIES START
addr2line.$(OBJEXT): {$(VPATH)}addr2line.c
addr2line.$(OBJEXT): {$(VPATH)}addr2line.h
+addr2line.$(OBJEXT): {$(VPATH)}assert.h
+addr2line.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+addr2line.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+addr2line.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+addr2line.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+addr2line.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+addr2line.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+addr2line.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
addr2line.$(OBJEXT): {$(VPATH)}config.h
addr2line.$(OBJEXT): {$(VPATH)}defines.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/assume.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/cast.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/config.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/dosish.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+addr2line.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
addr2line.$(OBJEXT): {$(VPATH)}missing.h
array.$(OBJEXT): $(hdrdir)/ruby.h
array.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+array.$(OBJEXT): $(top_srcdir)/internal/array.h
+array.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+array.$(OBJEXT): $(top_srcdir)/internal/bits.h
+array.$(OBJEXT): $(top_srcdir)/internal/class.h
+array.$(OBJEXT): $(top_srcdir)/internal/compar.h
+array.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+array.$(OBJEXT): $(top_srcdir)/internal/enum.h
+array.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+array.$(OBJEXT): $(top_srcdir)/internal/gc.h
+array.$(OBJEXT): $(top_srcdir)/internal/hash.h
+array.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+array.$(OBJEXT): $(top_srcdir)/internal/object.h
+array.$(OBJEXT): $(top_srcdir)/internal/proc.h
+array.$(OBJEXT): $(top_srcdir)/internal/rational.h
+array.$(OBJEXT): $(top_srcdir)/internal/serial.h
+array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+array.$(OBJEXT): $(top_srcdir)/internal/vm.h
+array.$(OBJEXT): $(top_srcdir)/internal/warnings.h
array.$(OBJEXT): {$(VPATH)}array.c
+array.$(OBJEXT): {$(VPATH)}array.rbinc
array.$(OBJEXT): {$(VPATH)}assert.h
+array.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+array.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+array.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+array.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+array.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+array.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+array.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+array.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+array.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+array.$(OBJEXT): {$(VPATH)}builtin.h
array.$(OBJEXT): {$(VPATH)}config.h
array.$(OBJEXT): {$(VPATH)}debug_counter.h
array.$(OBJEXT): {$(VPATH)}defines.h
array.$(OBJEXT): {$(VPATH)}encoding.h
array.$(OBJEXT): {$(VPATH)}id.h
+array.$(OBJEXT): {$(VPATH)}id_table.h
array.$(OBJEXT): {$(VPATH)}intern.h
array.$(OBJEXT): {$(VPATH)}internal.h
+array.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+array.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+array.$(OBJEXT): {$(VPATH)}internal/assume.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+array.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+array.$(OBJEXT): {$(VPATH)}internal/cast.h
+array.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+array.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+array.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+array.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+array.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+array.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+array.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+array.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+array.$(OBJEXT): {$(VPATH)}internal/config.h
+array.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+array.$(OBJEXT): {$(VPATH)}internal/core.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+array.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+array.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+array.$(OBJEXT): {$(VPATH)}internal/ctype.h
+array.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+array.$(OBJEXT): {$(VPATH)}internal/dosish.h
+array.$(OBJEXT): {$(VPATH)}internal/error.h
+array.$(OBJEXT): {$(VPATH)}internal/eval.h
+array.$(OBJEXT): {$(VPATH)}internal/event.h
+array.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+array.$(OBJEXT): {$(VPATH)}internal/gc.h
+array.$(OBJEXT): {$(VPATH)}internal/glob.h
+array.$(OBJEXT): {$(VPATH)}internal/globals.h
+array.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+array.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+array.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+array.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+array.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+array.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+array.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+array.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+array.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+array.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+array.$(OBJEXT): {$(VPATH)}internal/iterator.h
+array.$(OBJEXT): {$(VPATH)}internal/memory.h
+array.$(OBJEXT): {$(VPATH)}internal/method.h
+array.$(OBJEXT): {$(VPATH)}internal/module.h
+array.$(OBJEXT): {$(VPATH)}internal/newobj.h
+array.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+array.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+array.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+array.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+array.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+array.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+array.$(OBJEXT): {$(VPATH)}internal/symbol.h
+array.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+array.$(OBJEXT): {$(VPATH)}internal/value.h
+array.$(OBJEXT): {$(VPATH)}internal/value_type.h
+array.$(OBJEXT): {$(VPATH)}internal/variable.h
+array.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+array.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
array.$(OBJEXT): {$(VPATH)}missing.h
array.$(OBJEXT): {$(VPATH)}onigmo.h
array.$(OBJEXT): {$(VPATH)}oniguruma.h
@@ -1598,9 +1865,29 @@ ast.$(OBJEXT): $(CCAN_DIR)/list/list.h
ast.$(OBJEXT): $(CCAN_DIR)/str/str.h
ast.$(OBJEXT): $(hdrdir)/ruby.h
ast.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+ast.$(OBJEXT): $(top_srcdir)/internal/array.h
+ast.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ast.$(OBJEXT): $(top_srcdir)/internal/gc.h
+ast.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+ast.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ast.$(OBJEXT): $(top_srcdir)/internal/serial.h
+ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+ast.$(OBJEXT): $(top_srcdir)/internal/vm.h
+ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h
ast.$(OBJEXT): {$(VPATH)}assert.h
ast.$(OBJEXT): {$(VPATH)}ast.c
ast.$(OBJEXT): {$(VPATH)}ast.rbinc
+ast.$(OBJEXT): {$(VPATH)}atomic.h
+ast.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+ast.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+ast.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+ast.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+ast.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+ast.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+ast.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+ast.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+ast.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
ast.$(OBJEXT): {$(VPATH)}builtin.h
ast.$(OBJEXT): {$(VPATH)}config.h
ast.$(OBJEXT): {$(VPATH)}defines.h
@@ -1608,6 +1895,146 @@ ast.$(OBJEXT): {$(VPATH)}encoding.h
ast.$(OBJEXT): {$(VPATH)}id.h
ast.$(OBJEXT): {$(VPATH)}intern.h
ast.$(OBJEXT): {$(VPATH)}internal.h
+ast.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+ast.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+ast.$(OBJEXT): {$(VPATH)}internal/assume.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+ast.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+ast.$(OBJEXT): {$(VPATH)}internal/cast.h
+ast.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+ast.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+ast.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+ast.$(OBJEXT): {$(VPATH)}internal/config.h
+ast.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+ast.$(OBJEXT): {$(VPATH)}internal/core.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+ast.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+ast.$(OBJEXT): {$(VPATH)}internal/ctype.h
+ast.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+ast.$(OBJEXT): {$(VPATH)}internal/dosish.h
+ast.$(OBJEXT): {$(VPATH)}internal/error.h
+ast.$(OBJEXT): {$(VPATH)}internal/eval.h
+ast.$(OBJEXT): {$(VPATH)}internal/event.h
+ast.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+ast.$(OBJEXT): {$(VPATH)}internal/gc.h
+ast.$(OBJEXT): {$(VPATH)}internal/glob.h
+ast.$(OBJEXT): {$(VPATH)}internal/globals.h
+ast.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+ast.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+ast.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+ast.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+ast.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+ast.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+ast.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+ast.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+ast.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+ast.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+ast.$(OBJEXT): {$(VPATH)}internal/iterator.h
+ast.$(OBJEXT): {$(VPATH)}internal/memory.h
+ast.$(OBJEXT): {$(VPATH)}internal/method.h
+ast.$(OBJEXT): {$(VPATH)}internal/module.h
+ast.$(OBJEXT): {$(VPATH)}internal/newobj.h
+ast.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+ast.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+ast.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+ast.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+ast.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+ast.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+ast.$(OBJEXT): {$(VPATH)}internal/symbol.h
+ast.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -1625,13 +2052,180 @@ ast.$(OBJEXT): {$(VPATH)}vm_core.h
ast.$(OBJEXT): {$(VPATH)}vm_opts.h
bignum.$(OBJEXT): $(hdrdir)/ruby.h
bignum.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/bits.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/class.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/complex.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/gc.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/object.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/serial.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/util.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/variable.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/vm.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/warnings.h
bignum.$(OBJEXT): {$(VPATH)}assert.h
+bignum.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+bignum.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+bignum.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+bignum.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+bignum.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+bignum.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+bignum.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+bignum.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+bignum.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
bignum.$(OBJEXT): {$(VPATH)}bignum.c
bignum.$(OBJEXT): {$(VPATH)}config.h
+bignum.$(OBJEXT): {$(VPATH)}constant.h
bignum.$(OBJEXT): {$(VPATH)}defines.h
bignum.$(OBJEXT): {$(VPATH)}id.h
+bignum.$(OBJEXT): {$(VPATH)}id_table.h
bignum.$(OBJEXT): {$(VPATH)}intern.h
bignum.$(OBJEXT): {$(VPATH)}internal.h
+bignum.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+bignum.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+bignum.$(OBJEXT): {$(VPATH)}internal/assume.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+bignum.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+bignum.$(OBJEXT): {$(VPATH)}internal/cast.h
+bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+bignum.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+bignum.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+bignum.$(OBJEXT): {$(VPATH)}internal/config.h
+bignum.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+bignum.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+bignum.$(OBJEXT): {$(VPATH)}internal/ctype.h
+bignum.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+bignum.$(OBJEXT): {$(VPATH)}internal/dosish.h
+bignum.$(OBJEXT): {$(VPATH)}internal/error.h
+bignum.$(OBJEXT): {$(VPATH)}internal/eval.h
+bignum.$(OBJEXT): {$(VPATH)}internal/event.h
+bignum.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+bignum.$(OBJEXT): {$(VPATH)}internal/gc.h
+bignum.$(OBJEXT): {$(VPATH)}internal/glob.h
+bignum.$(OBJEXT): {$(VPATH)}internal/globals.h
+bignum.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+bignum.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+bignum.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+bignum.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+bignum.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+bignum.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+bignum.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+bignum.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+bignum.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+bignum.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+bignum.$(OBJEXT): {$(VPATH)}internal/iterator.h
+bignum.$(OBJEXT): {$(VPATH)}internal/memory.h
+bignum.$(OBJEXT): {$(VPATH)}internal/method.h
+bignum.$(OBJEXT): {$(VPATH)}internal/module.h
+bignum.$(OBJEXT): {$(VPATH)}internal/newobj.h
+bignum.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+bignum.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+bignum.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+bignum.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+bignum.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+bignum.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+bignum.$(OBJEXT): {$(VPATH)}internal/symbol.h
+bignum.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+bignum.$(OBJEXT): {$(VPATH)}internal/value.h
+bignum.$(OBJEXT): {$(VPATH)}internal/value_type.h
+bignum.$(OBJEXT): {$(VPATH)}internal/variable.h
+bignum.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+bignum.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
bignum.$(OBJEXT): {$(VPATH)}missing.h
bignum.$(OBJEXT): {$(VPATH)}ruby_assert.h
bignum.$(OBJEXT): {$(VPATH)}st.h
@@ -1644,7 +2238,25 @@ builtin.$(OBJEXT): $(CCAN_DIR)/list/list.h
builtin.$(OBJEXT): $(CCAN_DIR)/str/str.h
builtin.$(OBJEXT): $(hdrdir)/ruby.h
builtin.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/array.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h
builtin.$(OBJEXT): {$(VPATH)}assert.h
+builtin.$(OBJEXT): {$(VPATH)}atomic.h
+builtin.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+builtin.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+builtin.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+builtin.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+builtin.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+builtin.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+builtin.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+builtin.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+builtin.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
builtin.$(OBJEXT): {$(VPATH)}builtin.c
builtin.$(OBJEXT): {$(VPATH)}builtin.h
builtin.$(OBJEXT): {$(VPATH)}builtin_binary.inc
@@ -1653,6 +2265,146 @@ builtin.$(OBJEXT): {$(VPATH)}defines.h
builtin.$(OBJEXT): {$(VPATH)}id.h
builtin.$(OBJEXT): {$(VPATH)}intern.h
builtin.$(OBJEXT): {$(VPATH)}internal.h
+builtin.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+builtin.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+builtin.$(OBJEXT): {$(VPATH)}internal/assume.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+builtin.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+builtin.$(OBJEXT): {$(VPATH)}internal/cast.h
+builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+builtin.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+builtin.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+builtin.$(OBJEXT): {$(VPATH)}internal/config.h
+builtin.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+builtin.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+builtin.$(OBJEXT): {$(VPATH)}internal/ctype.h
+builtin.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+builtin.$(OBJEXT): {$(VPATH)}internal/dosish.h
+builtin.$(OBJEXT): {$(VPATH)}internal/error.h
+builtin.$(OBJEXT): {$(VPATH)}internal/eval.h
+builtin.$(OBJEXT): {$(VPATH)}internal/event.h
+builtin.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+builtin.$(OBJEXT): {$(VPATH)}internal/gc.h
+builtin.$(OBJEXT): {$(VPATH)}internal/glob.h
+builtin.$(OBJEXT): {$(VPATH)}internal/globals.h
+builtin.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+builtin.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+builtin.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+builtin.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+builtin.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+builtin.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+builtin.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+builtin.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+builtin.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+builtin.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+builtin.$(OBJEXT): {$(VPATH)}internal/iterator.h
+builtin.$(OBJEXT): {$(VPATH)}internal/memory.h
+builtin.$(OBJEXT): {$(VPATH)}internal/method.h
+builtin.$(OBJEXT): {$(VPATH)}internal/module.h
+builtin.$(OBJEXT): {$(VPATH)}internal/newobj.h
+builtin.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+builtin.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+builtin.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+builtin.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+builtin.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+builtin.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+builtin.$(OBJEXT): {$(VPATH)}internal/symbol.h
+builtin.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -1671,18 +2423,187 @@ class.$(OBJEXT): $(CCAN_DIR)/list/list.h
class.$(OBJEXT): $(CCAN_DIR)/str/str.h
class.$(OBJEXT): $(hdrdir)/ruby.h
class.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+class.$(OBJEXT): $(top_srcdir)/internal/array.h
+class.$(OBJEXT): $(top_srcdir)/internal/class.h
+class.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+class.$(OBJEXT): $(top_srcdir)/internal/error.h
+class.$(OBJEXT): $(top_srcdir)/internal/eval.h
+class.$(OBJEXT): $(top_srcdir)/internal/gc.h
+class.$(OBJEXT): $(top_srcdir)/internal/hash.h
+class.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+class.$(OBJEXT): $(top_srcdir)/internal/object.h
+class.$(OBJEXT): $(top_srcdir)/internal/serial.h
+class.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+class.$(OBJEXT): $(top_srcdir)/internal/string.h
+class.$(OBJEXT): $(top_srcdir)/internal/variable.h
+class.$(OBJEXT): $(top_srcdir)/internal/vm.h
+class.$(OBJEXT): $(top_srcdir)/internal/warnings.h
class.$(OBJEXT): {$(VPATH)}assert.h
+class.$(OBJEXT): {$(VPATH)}atomic.h
+class.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+class.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+class.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+class.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+class.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+class.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+class.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+class.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+class.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
class.$(OBJEXT): {$(VPATH)}class.c
class.$(OBJEXT): {$(VPATH)}config.h
class.$(OBJEXT): {$(VPATH)}constant.h
class.$(OBJEXT): {$(VPATH)}defines.h
+class.$(OBJEXT): {$(VPATH)}encoding.h
+class.$(OBJEXT): {$(VPATH)}gc.h
class.$(OBJEXT): {$(VPATH)}id.h
class.$(OBJEXT): {$(VPATH)}id_table.h
class.$(OBJEXT): {$(VPATH)}intern.h
class.$(OBJEXT): {$(VPATH)}internal.h
+class.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+class.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+class.$(OBJEXT): {$(VPATH)}internal/assume.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+class.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+class.$(OBJEXT): {$(VPATH)}internal/cast.h
+class.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+class.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+class.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+class.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+class.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+class.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+class.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+class.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+class.$(OBJEXT): {$(VPATH)}internal/config.h
+class.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+class.$(OBJEXT): {$(VPATH)}internal/core.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+class.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+class.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+class.$(OBJEXT): {$(VPATH)}internal/ctype.h
+class.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+class.$(OBJEXT): {$(VPATH)}internal/dosish.h
+class.$(OBJEXT): {$(VPATH)}internal/error.h
+class.$(OBJEXT): {$(VPATH)}internal/eval.h
+class.$(OBJEXT): {$(VPATH)}internal/event.h
+class.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+class.$(OBJEXT): {$(VPATH)}internal/gc.h
+class.$(OBJEXT): {$(VPATH)}internal/glob.h
+class.$(OBJEXT): {$(VPATH)}internal/globals.h
+class.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+class.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+class.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+class.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+class.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+class.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+class.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+class.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+class.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+class.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+class.$(OBJEXT): {$(VPATH)}internal/iterator.h
+class.$(OBJEXT): {$(VPATH)}internal/memory.h
+class.$(OBJEXT): {$(VPATH)}internal/method.h
+class.$(OBJEXT): {$(VPATH)}internal/module.h
+class.$(OBJEXT): {$(VPATH)}internal/newobj.h
+class.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+class.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+class.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+class.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+class.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+class.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+class.$(OBJEXT): {$(VPATH)}internal/symbol.h
+class.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+class.$(OBJEXT): {$(VPATH)}internal/value.h
+class.$(OBJEXT): {$(VPATH)}internal/value_type.h
+class.$(OBJEXT): {$(VPATH)}internal/variable.h
+class.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+class.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
class.$(OBJEXT): {$(VPATH)}method.h
class.$(OBJEXT): {$(VPATH)}missing.h
class.$(OBJEXT): {$(VPATH)}node.h
+class.$(OBJEXT): {$(VPATH)}onigmo.h
+class.$(OBJEXT): {$(VPATH)}oniguruma.h
class.$(OBJEXT): {$(VPATH)}ruby_assert.h
class.$(OBJEXT): {$(VPATH)}ruby_atomic.h
class.$(OBJEXT): {$(VPATH)}st.h
@@ -1693,14 +2614,173 @@ class.$(OBJEXT): {$(VPATH)}vm_core.h
class.$(OBJEXT): {$(VPATH)}vm_opts.h
compar.$(OBJEXT): $(hdrdir)/ruby.h
compar.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+compar.$(OBJEXT): $(top_srcdir)/internal/compar.h
+compar.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+compar.$(OBJEXT): $(top_srcdir)/internal/error.h
+compar.$(OBJEXT): $(top_srcdir)/internal/serial.h
+compar.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+compar.$(OBJEXT): $(top_srcdir)/internal/string.h
+compar.$(OBJEXT): $(top_srcdir)/internal/vm.h
compar.$(OBJEXT): {$(VPATH)}assert.h
+compar.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+compar.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+compar.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+compar.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+compar.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+compar.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+compar.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+compar.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+compar.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
compar.$(OBJEXT): {$(VPATH)}compar.c
compar.$(OBJEXT): {$(VPATH)}config.h
compar.$(OBJEXT): {$(VPATH)}defines.h
+compar.$(OBJEXT): {$(VPATH)}encoding.h
compar.$(OBJEXT): {$(VPATH)}id.h
compar.$(OBJEXT): {$(VPATH)}intern.h
compar.$(OBJEXT): {$(VPATH)}internal.h
+compar.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+compar.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+compar.$(OBJEXT): {$(VPATH)}internal/assume.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+compar.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+compar.$(OBJEXT): {$(VPATH)}internal/cast.h
+compar.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+compar.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+compar.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+compar.$(OBJEXT): {$(VPATH)}internal/config.h
+compar.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+compar.$(OBJEXT): {$(VPATH)}internal/core.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+compar.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+compar.$(OBJEXT): {$(VPATH)}internal/ctype.h
+compar.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+compar.$(OBJEXT): {$(VPATH)}internal/dosish.h
+compar.$(OBJEXT): {$(VPATH)}internal/error.h
+compar.$(OBJEXT): {$(VPATH)}internal/eval.h
+compar.$(OBJEXT): {$(VPATH)}internal/event.h
+compar.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+compar.$(OBJEXT): {$(VPATH)}internal/gc.h
+compar.$(OBJEXT): {$(VPATH)}internal/glob.h
+compar.$(OBJEXT): {$(VPATH)}internal/globals.h
+compar.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+compar.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+compar.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+compar.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+compar.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+compar.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+compar.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+compar.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+compar.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+compar.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+compar.$(OBJEXT): {$(VPATH)}internal/iterator.h
+compar.$(OBJEXT): {$(VPATH)}internal/memory.h
+compar.$(OBJEXT): {$(VPATH)}internal/method.h
+compar.$(OBJEXT): {$(VPATH)}internal/module.h
+compar.$(OBJEXT): {$(VPATH)}internal/newobj.h
+compar.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+compar.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+compar.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+compar.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+compar.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+compar.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+compar.$(OBJEXT): {$(VPATH)}internal/symbol.h
+compar.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -1709,10 +2789,47 @@ compile.$(OBJEXT): $(CCAN_DIR)/list/list.h
compile.$(OBJEXT): $(CCAN_DIR)/str/str.h
compile.$(OBJEXT): $(hdrdir)/ruby.h
compile.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+compile.$(OBJEXT): $(top_srcdir)/internal/array.h
+compile.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+compile.$(OBJEXT): $(top_srcdir)/internal/bits.h
+compile.$(OBJEXT): $(top_srcdir)/internal/class.h
+compile.$(OBJEXT): $(top_srcdir)/internal/compile.h
+compile.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+compile.$(OBJEXT): $(top_srcdir)/internal/complex.h
+compile.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+compile.$(OBJEXT): $(top_srcdir)/internal/error.h
+compile.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+compile.$(OBJEXT): $(top_srcdir)/internal/gc.h
+compile.$(OBJEXT): $(top_srcdir)/internal/hash.h
+compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+compile.$(OBJEXT): $(top_srcdir)/internal/object.h
+compile.$(OBJEXT): $(top_srcdir)/internal/rational.h
+compile.$(OBJEXT): $(top_srcdir)/internal/re.h
+compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
+compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+compile.$(OBJEXT): $(top_srcdir)/internal/string.h
+compile.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+compile.$(OBJEXT): $(top_srcdir)/internal/thread.h
+compile.$(OBJEXT): $(top_srcdir)/internal/variable.h
+compile.$(OBJEXT): $(top_srcdir)/internal/vm.h
+compile.$(OBJEXT): $(top_srcdir)/internal/warnings.h
compile.$(OBJEXT): {$(VPATH)}assert.h
+compile.$(OBJEXT): {$(VPATH)}atomic.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
compile.$(OBJEXT): {$(VPATH)}builtin.h
compile.$(OBJEXT): {$(VPATH)}compile.c
compile.$(OBJEXT): {$(VPATH)}config.h
+compile.$(OBJEXT): {$(VPATH)}constant.h
+compile.$(OBJEXT): {$(VPATH)}debug_counter.h
compile.$(OBJEXT): {$(VPATH)}defines.h
compile.$(OBJEXT): {$(VPATH)}encindex.h
compile.$(OBJEXT): {$(VPATH)}encoding.h
@@ -1724,6 +2841,147 @@ compile.$(OBJEXT): {$(VPATH)}insns.inc
compile.$(OBJEXT): {$(VPATH)}insns_info.inc
compile.$(OBJEXT): {$(VPATH)}intern.h
compile.$(OBJEXT): {$(VPATH)}internal.h
+compile.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+compile.$(OBJEXT): {$(VPATH)}internal/assume.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+compile.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+compile.$(OBJEXT): {$(VPATH)}internal/cast.h
+compile.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+compile.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+compile.$(OBJEXT): {$(VPATH)}internal/config.h
+compile.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+compile.$(OBJEXT): {$(VPATH)}internal/core.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+compile.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+compile.$(OBJEXT): {$(VPATH)}internal/ctype.h
+compile.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+compile.$(OBJEXT): {$(VPATH)}internal/dosish.h
+compile.$(OBJEXT): {$(VPATH)}internal/error.h
+compile.$(OBJEXT): {$(VPATH)}internal/eval.h
+compile.$(OBJEXT): {$(VPATH)}internal/event.h
+compile.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+compile.$(OBJEXT): {$(VPATH)}internal/gc.h
+compile.$(OBJEXT): {$(VPATH)}internal/glob.h
+compile.$(OBJEXT): {$(VPATH)}internal/globals.h
+compile.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+compile.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+compile.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+compile.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+compile.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+compile.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+compile.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+compile.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+compile.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+compile.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+compile.$(OBJEXT): {$(VPATH)}internal/iterator.h
+compile.$(OBJEXT): {$(VPATH)}internal/memory.h
+compile.$(OBJEXT): {$(VPATH)}internal/method.h
+compile.$(OBJEXT): {$(VPATH)}internal/module.h
+compile.$(OBJEXT): {$(VPATH)}internal/newobj.h
+compile.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+compile.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+compile.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+compile.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+compile.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+compile.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+compile.$(OBJEXT): {$(VPATH)}internal/symbol.h
+compile.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+compile.$(OBJEXT): {$(VPATH)}internal/value.h
+compile.$(OBJEXT): {$(VPATH)}internal/value_type.h
+compile.$(OBJEXT): {$(VPATH)}internal/variable.h
+compile.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+compile.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
compile.$(OBJEXT): {$(VPATH)}iseq.h
compile.$(OBJEXT): {$(VPATH)}method.h
compile.$(OBJEXT): {$(VPATH)}missing.h
@@ -1742,19 +3000,191 @@ compile.$(OBJEXT): {$(VPATH)}subst.h
compile.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
compile.$(OBJEXT): {$(VPATH)}thread_native.h
compile.$(OBJEXT): {$(VPATH)}util.h
+compile.$(OBJEXT): {$(VPATH)}vm_callinfo.h
compile.$(OBJEXT): {$(VPATH)}vm_core.h
compile.$(OBJEXT): {$(VPATH)}vm_debug.h
compile.$(OBJEXT): {$(VPATH)}vm_opts.h
complex.$(OBJEXT): $(hdrdir)/ruby.h
complex.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+complex.$(OBJEXT): $(top_srcdir)/internal/array.h
+complex.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+complex.$(OBJEXT): $(top_srcdir)/internal/bits.h
+complex.$(OBJEXT): $(top_srcdir)/internal/class.h
+complex.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+complex.$(OBJEXT): $(top_srcdir)/internal/complex.h
+complex.$(OBJEXT): $(top_srcdir)/internal/error.h
+complex.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+complex.$(OBJEXT): $(top_srcdir)/internal/gc.h
+complex.$(OBJEXT): $(top_srcdir)/internal/math.h
+complex.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+complex.$(OBJEXT): $(top_srcdir)/internal/object.h
+complex.$(OBJEXT): $(top_srcdir)/internal/rational.h
+complex.$(OBJEXT): $(top_srcdir)/internal/serial.h
+complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+complex.$(OBJEXT): $(top_srcdir)/internal/string.h
+complex.$(OBJEXT): $(top_srcdir)/internal/vm.h
+complex.$(OBJEXT): $(top_srcdir)/internal/warnings.h
complex.$(OBJEXT): {$(VPATH)}assert.h
+complex.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+complex.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+complex.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+complex.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+complex.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+complex.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+complex.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+complex.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+complex.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
complex.$(OBJEXT): {$(VPATH)}complex.c
complex.$(OBJEXT): {$(VPATH)}config.h
complex.$(OBJEXT): {$(VPATH)}defines.h
+complex.$(OBJEXT): {$(VPATH)}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/anyargs.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+complex.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+complex.$(OBJEXT): {$(VPATH)}internal/assume.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+complex.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+complex.$(OBJEXT): {$(VPATH)}internal/cast.h
+complex.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+complex.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+complex.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+complex.$(OBJEXT): {$(VPATH)}internal/config.h
+complex.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+complex.$(OBJEXT): {$(VPATH)}internal/core.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+complex.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+complex.$(OBJEXT): {$(VPATH)}internal/ctype.h
+complex.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+complex.$(OBJEXT): {$(VPATH)}internal/dosish.h
+complex.$(OBJEXT): {$(VPATH)}internal/error.h
+complex.$(OBJEXT): {$(VPATH)}internal/eval.h
+complex.$(OBJEXT): {$(VPATH)}internal/event.h
+complex.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+complex.$(OBJEXT): {$(VPATH)}internal/gc.h
+complex.$(OBJEXT): {$(VPATH)}internal/glob.h
+complex.$(OBJEXT): {$(VPATH)}internal/globals.h
+complex.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+complex.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+complex.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+complex.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+complex.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+complex.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+complex.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+complex.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+complex.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+complex.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+complex.$(OBJEXT): {$(VPATH)}internal/iterator.h
+complex.$(OBJEXT): {$(VPATH)}internal/memory.h
+complex.$(OBJEXT): {$(VPATH)}internal/method.h
+complex.$(OBJEXT): {$(VPATH)}internal/module.h
+complex.$(OBJEXT): {$(VPATH)}internal/newobj.h
+complex.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+complex.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+complex.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+complex.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+complex.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+complex.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+complex.$(OBJEXT): {$(VPATH)}internal/symbol.h
+complex.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+complex.$(OBJEXT): {$(VPATH)}internal/value.h
+complex.$(OBJEXT): {$(VPATH)}internal/value_type.h
+complex.$(OBJEXT): {$(VPATH)}internal/variable.h
+complex.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+complex.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
complex.$(OBJEXT): {$(VPATH)}missing.h
+complex.$(OBJEXT): {$(VPATH)}onigmo.h
+complex.$(OBJEXT): {$(VPATH)}oniguruma.h
complex.$(OBJEXT): {$(VPATH)}ruby_assert.h
complex.$(OBJEXT): {$(VPATH)}st.h
complex.$(OBJEXT): {$(VPATH)}subst.h
@@ -1764,8 +3194,29 @@ cont.$(OBJEXT): $(CCAN_DIR)/list/list.h
cont.$(OBJEXT): $(CCAN_DIR)/str/str.h
cont.$(OBJEXT): $(hdrdir)/ruby.h
cont.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+cont.$(OBJEXT): $(top_srcdir)/internal/array.h
+cont.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+cont.$(OBJEXT): $(top_srcdir)/internal/cont.h
+cont.$(OBJEXT): $(top_srcdir)/internal/gc.h
+cont.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+cont.$(OBJEXT): $(top_srcdir)/internal/proc.h
+cont.$(OBJEXT): $(top_srcdir)/internal/scheduler.h
+cont.$(OBJEXT): $(top_srcdir)/internal/serial.h
+cont.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+cont.$(OBJEXT): $(top_srcdir)/internal/vm.h
+cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h
cont.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
cont.$(OBJEXT): {$(VPATH)}assert.h
+cont.$(OBJEXT): {$(VPATH)}atomic.h
+cont.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+cont.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+cont.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+cont.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+cont.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+cont.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+cont.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+cont.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+cont.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
cont.$(OBJEXT): {$(VPATH)}config.h
cont.$(OBJEXT): {$(VPATH)}cont.c
cont.$(OBJEXT): {$(VPATH)}debug_counter.h
@@ -1773,12 +3224,155 @@ cont.$(OBJEXT): {$(VPATH)}defines.h
cont.$(OBJEXT): {$(VPATH)}eval_intern.h
cont.$(OBJEXT): {$(VPATH)}gc.h
cont.$(OBJEXT): {$(VPATH)}id.h
+cont.$(OBJEXT): {$(VPATH)}id_table.h
cont.$(OBJEXT): {$(VPATH)}intern.h
cont.$(OBJEXT): {$(VPATH)}internal.h
+cont.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+cont.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+cont.$(OBJEXT): {$(VPATH)}internal/assume.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+cont.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+cont.$(OBJEXT): {$(VPATH)}internal/cast.h
+cont.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+cont.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+cont.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+cont.$(OBJEXT): {$(VPATH)}internal/config.h
+cont.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+cont.$(OBJEXT): {$(VPATH)}internal/core.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+cont.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+cont.$(OBJEXT): {$(VPATH)}internal/ctype.h
+cont.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+cont.$(OBJEXT): {$(VPATH)}internal/dosish.h
+cont.$(OBJEXT): {$(VPATH)}internal/error.h
+cont.$(OBJEXT): {$(VPATH)}internal/eval.h
+cont.$(OBJEXT): {$(VPATH)}internal/event.h
+cont.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+cont.$(OBJEXT): {$(VPATH)}internal/gc.h
+cont.$(OBJEXT): {$(VPATH)}internal/glob.h
+cont.$(OBJEXT): {$(VPATH)}internal/globals.h
+cont.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+cont.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+cont.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+cont.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+cont.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+cont.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+cont.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+cont.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+cont.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+cont.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+cont.$(OBJEXT): {$(VPATH)}internal/iterator.h
+cont.$(OBJEXT): {$(VPATH)}internal/memory.h
+cont.$(OBJEXT): {$(VPATH)}internal/method.h
+cont.$(OBJEXT): {$(VPATH)}internal/module.h
+cont.$(OBJEXT): {$(VPATH)}internal/newobj.h
+cont.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+cont.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+cont.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+cont.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+cont.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+cont.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+cont.$(OBJEXT): {$(VPATH)}internal/symbol.h
+cont.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+cont.$(OBJEXT): {$(VPATH)}internal/value.h
+cont.$(OBJEXT): {$(VPATH)}internal/value_type.h
+cont.$(OBJEXT): {$(VPATH)}internal/variable.h
+cont.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+cont.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
cont.$(OBJEXT): {$(VPATH)}method.h
cont.$(OBJEXT): {$(VPATH)}missing.h
cont.$(OBJEXT): {$(VPATH)}mjit.h
cont.$(OBJEXT): {$(VPATH)}node.h
+cont.$(OBJEXT): {$(VPATH)}ractor.h
+cont.$(OBJEXT): {$(VPATH)}ractor_core.h
cont.$(OBJEXT): {$(VPATH)}ruby_assert.h
cont.$(OBJEXT): {$(VPATH)}ruby_atomic.h
cont.$(OBJEXT): {$(VPATH)}st.h
@@ -1786,6 +3380,7 @@ 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
debug.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
debug.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
@@ -1793,22 +3388,186 @@ debug.$(OBJEXT): $(CCAN_DIR)/list/list.h
debug.$(OBJEXT): $(CCAN_DIR)/str/str.h
debug.$(OBJEXT): $(hdrdir)/ruby.h
debug.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+debug.$(OBJEXT): $(top_srcdir)/internal/array.h
+debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+debug.$(OBJEXT): $(top_srcdir)/internal/gc.h
+debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+debug.$(OBJEXT): $(top_srcdir)/internal/serial.h
+debug.$(OBJEXT): $(top_srcdir)/internal/signal.h
+debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+debug.$(OBJEXT): $(top_srcdir)/internal/util.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)}debug.c
+debug.$(OBJEXT): {$(VPATH)}debug_counter.h
debug.$(OBJEXT): {$(VPATH)}defines.h
debug.$(OBJEXT): {$(VPATH)}encoding.h
debug.$(OBJEXT): {$(VPATH)}eval_intern.h
debug.$(OBJEXT): {$(VPATH)}gc.h
debug.$(OBJEXT): {$(VPATH)}id.h
+debug.$(OBJEXT): {$(VPATH)}id_table.h
debug.$(OBJEXT): {$(VPATH)}intern.h
debug.$(OBJEXT): {$(VPATH)}internal.h
+debug.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+debug.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+debug.$(OBJEXT): {$(VPATH)}internal/assume.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+debug.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+debug.$(OBJEXT): {$(VPATH)}internal/cast.h
+debug.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+debug.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+debug.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+debug.$(OBJEXT): {$(VPATH)}internal/config.h
+debug.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+debug.$(OBJEXT): {$(VPATH)}internal/core.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+debug.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+debug.$(OBJEXT): {$(VPATH)}internal/ctype.h
+debug.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+debug.$(OBJEXT): {$(VPATH)}internal/dosish.h
+debug.$(OBJEXT): {$(VPATH)}internal/error.h
+debug.$(OBJEXT): {$(VPATH)}internal/eval.h
+debug.$(OBJEXT): {$(VPATH)}internal/event.h
+debug.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+debug.$(OBJEXT): {$(VPATH)}internal/gc.h
+debug.$(OBJEXT): {$(VPATH)}internal/glob.h
+debug.$(OBJEXT): {$(VPATH)}internal/globals.h
+debug.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+debug.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+debug.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+debug.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+debug.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+debug.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+debug.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+debug.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+debug.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+debug.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+debug.$(OBJEXT): {$(VPATH)}internal/iterator.h
+debug.$(OBJEXT): {$(VPATH)}internal/memory.h
+debug.$(OBJEXT): {$(VPATH)}internal/method.h
+debug.$(OBJEXT): {$(VPATH)}internal/module.h
+debug.$(OBJEXT): {$(VPATH)}internal/newobj.h
+debug.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+debug.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+debug.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+debug.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+debug.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+debug.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+debug.$(OBJEXT): {$(VPATH)}internal/symbol.h
+debug.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+debug.$(OBJEXT): {$(VPATH)}internal/value.h
+debug.$(OBJEXT): {$(VPATH)}internal/value_type.h
+debug.$(OBJEXT): {$(VPATH)}internal/variable.h
+debug.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+debug.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
debug.$(OBJEXT): {$(VPATH)}io.h
debug.$(OBJEXT): {$(VPATH)}method.h
debug.$(OBJEXT): {$(VPATH)}missing.h
debug.$(OBJEXT): {$(VPATH)}node.h
debug.$(OBJEXT): {$(VPATH)}onigmo.h
debug.$(OBJEXT): {$(VPATH)}oniguruma.h
+debug.$(OBJEXT): {$(VPATH)}ractor.h
+debug.$(OBJEXT): {$(VPATH)}ractor_core.h
debug.$(OBJEXT): {$(VPATH)}ruby_assert.h
debug.$(OBJEXT): {$(VPATH)}ruby_atomic.h
debug.$(OBJEXT): {$(VPATH)}st.h
@@ -1817,32 +3576,348 @@ debug.$(OBJEXT): {$(VPATH)}symbol.h
debug.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
debug.$(OBJEXT): {$(VPATH)}thread_native.h
debug.$(OBJEXT): {$(VPATH)}util.h
+debug.$(OBJEXT): {$(VPATH)}vm_callinfo.h
debug.$(OBJEXT): {$(VPATH)}vm_core.h
debug.$(OBJEXT): {$(VPATH)}vm_debug.h
debug.$(OBJEXT): {$(VPATH)}vm_opts.h
debug_counter.$(OBJEXT): $(hdrdir)/ruby.h
debug_counter.$(OBJEXT): $(hdrdir)/ruby/ruby.h
debug_counter.$(OBJEXT): {$(VPATH)}assert.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
debug_counter.$(OBJEXT): {$(VPATH)}config.h
debug_counter.$(OBJEXT): {$(VPATH)}debug_counter.c
debug_counter.$(OBJEXT): {$(VPATH)}debug_counter.h
debug_counter.$(OBJEXT): {$(VPATH)}defines.h
debug_counter.$(OBJEXT): {$(VPATH)}intern.h
debug_counter.$(OBJEXT): {$(VPATH)}internal.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/assume.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/cast.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/config.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/ctype.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/dosish.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/error.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/eval.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/event.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/gc.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/glob.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/globals.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/iterator.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/memory.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/method.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/module.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/newobj.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/symbol.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/token_paste.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): $(hdrdir)/ruby.h
dir.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+dir.$(OBJEXT): $(top_srcdir)/internal/array.h
+dir.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+dir.$(OBJEXT): $(top_srcdir)/internal/dir.h
+dir.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+dir.$(OBJEXT): $(top_srcdir)/internal/error.h
+dir.$(OBJEXT): $(top_srcdir)/internal/file.h
+dir.$(OBJEXT): $(top_srcdir)/internal/gc.h
+dir.$(OBJEXT): $(top_srcdir)/internal/io.h
+dir.$(OBJEXT): $(top_srcdir)/internal/serial.h
+dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+dir.$(OBJEXT): $(top_srcdir)/internal/string.h
+dir.$(OBJEXT): $(top_srcdir)/internal/vm.h
+dir.$(OBJEXT): $(top_srcdir)/internal/warnings.h
dir.$(OBJEXT): {$(VPATH)}assert.h
+dir.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+dir.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+dir.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+dir.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+dir.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+dir.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+dir.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+dir.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+dir.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+dir.$(OBJEXT): {$(VPATH)}builtin.h
dir.$(OBJEXT): {$(VPATH)}config.h
dir.$(OBJEXT): {$(VPATH)}defines.h
dir.$(OBJEXT): {$(VPATH)}dir.c
+dir.$(OBJEXT): {$(VPATH)}dir.rbinc
dir.$(OBJEXT): {$(VPATH)}encindex.h
dir.$(OBJEXT): {$(VPATH)}encoding.h
dir.$(OBJEXT): {$(VPATH)}id.h
dir.$(OBJEXT): {$(VPATH)}intern.h
dir.$(OBJEXT): {$(VPATH)}internal.h
+dir.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+dir.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+dir.$(OBJEXT): {$(VPATH)}internal/assume.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+dir.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+dir.$(OBJEXT): {$(VPATH)}internal/cast.h
+dir.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+dir.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+dir.$(OBJEXT): {$(VPATH)}internal/config.h
+dir.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+dir.$(OBJEXT): {$(VPATH)}internal/core.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+dir.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+dir.$(OBJEXT): {$(VPATH)}internal/ctype.h
+dir.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+dir.$(OBJEXT): {$(VPATH)}internal/dosish.h
+dir.$(OBJEXT): {$(VPATH)}internal/error.h
+dir.$(OBJEXT): {$(VPATH)}internal/eval.h
+dir.$(OBJEXT): {$(VPATH)}internal/event.h
+dir.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+dir.$(OBJEXT): {$(VPATH)}internal/gc.h
+dir.$(OBJEXT): {$(VPATH)}internal/glob.h
+dir.$(OBJEXT): {$(VPATH)}internal/globals.h
+dir.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+dir.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+dir.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+dir.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+dir.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+dir.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+dir.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+dir.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+dir.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+dir.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+dir.$(OBJEXT): {$(VPATH)}internal/iterator.h
+dir.$(OBJEXT): {$(VPATH)}internal/memory.h
+dir.$(OBJEXT): {$(VPATH)}internal/method.h
+dir.$(OBJEXT): {$(VPATH)}internal/module.h
+dir.$(OBJEXT): {$(VPATH)}internal/newobj.h
+dir.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+dir.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+dir.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+dir.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+dir.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+dir.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+dir.$(OBJEXT): {$(VPATH)}internal/symbol.h
+dir.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+dir.$(OBJEXT): {$(VPATH)}internal/value.h
+dir.$(OBJEXT): {$(VPATH)}internal/value_type.h
+dir.$(OBJEXT): {$(VPATH)}internal/variable.h
+dir.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+dir.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+dir.$(OBJEXT): {$(VPATH)}io.h
dir.$(OBJEXT): {$(VPATH)}missing.h
dir.$(OBJEXT): {$(VPATH)}onigmo.h
dir.$(OBJEXT): {$(VPATH)}oniguruma.h
@@ -1852,32 +3927,481 @@ dir.$(OBJEXT): {$(VPATH)}thread.h
dir.$(OBJEXT): {$(VPATH)}util.h
dln.$(OBJEXT): $(hdrdir)/ruby.h
dln.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+dln.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+dln.$(OBJEXT): $(top_srcdir)/internal/warnings.h
dln.$(OBJEXT): {$(VPATH)}assert.h
+dln.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+dln.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+dln.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+dln.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+dln.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+dln.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+dln.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+dln.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+dln.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
dln.$(OBJEXT): {$(VPATH)}config.h
dln.$(OBJEXT): {$(VPATH)}defines.h
dln.$(OBJEXT): {$(VPATH)}dln.c
dln.$(OBJEXT): {$(VPATH)}dln.h
dln.$(OBJEXT): {$(VPATH)}intern.h
dln.$(OBJEXT): {$(VPATH)}internal.h
+dln.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+dln.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+dln.$(OBJEXT): {$(VPATH)}internal/assume.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+dln.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+dln.$(OBJEXT): {$(VPATH)}internal/cast.h
+dln.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+dln.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+dln.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+dln.$(OBJEXT): {$(VPATH)}internal/config.h
+dln.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+dln.$(OBJEXT): {$(VPATH)}internal/core.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+dln.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+dln.$(OBJEXT): {$(VPATH)}internal/ctype.h
+dln.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+dln.$(OBJEXT): {$(VPATH)}internal/dosish.h
+dln.$(OBJEXT): {$(VPATH)}internal/error.h
+dln.$(OBJEXT): {$(VPATH)}internal/eval.h
+dln.$(OBJEXT): {$(VPATH)}internal/event.h
+dln.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+dln.$(OBJEXT): {$(VPATH)}internal/gc.h
+dln.$(OBJEXT): {$(VPATH)}internal/glob.h
+dln.$(OBJEXT): {$(VPATH)}internal/globals.h
+dln.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+dln.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+dln.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+dln.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+dln.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+dln.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+dln.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+dln.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+dln.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+dln.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+dln.$(OBJEXT): {$(VPATH)}internal/iterator.h
+dln.$(OBJEXT): {$(VPATH)}internal/memory.h
+dln.$(OBJEXT): {$(VPATH)}internal/method.h
+dln.$(OBJEXT): {$(VPATH)}internal/module.h
+dln.$(OBJEXT): {$(VPATH)}internal/newobj.h
+dln.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+dln.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+dln.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+dln.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+dln.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+dln.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+dln.$(OBJEXT): {$(VPATH)}internal/symbol.h
+dln.$(OBJEXT): {$(VPATH)}internal/token_paste.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/gcc_version_since.h
+dln_find.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+dln_find.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+dln_find.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+dln_find.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+dln_find.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
dln_find.$(OBJEXT): {$(VPATH)}config.h
dln_find.$(OBJEXT): {$(VPATH)}defines.h
dln_find.$(OBJEXT): {$(VPATH)}dln.h
dln_find.$(OBJEXT): {$(VPATH)}dln_find.c
dln_find.$(OBJEXT): {$(VPATH)}intern.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/assume.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/cast.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/config.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/ctype.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/dosish.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/error.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/eval.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/event.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/gc.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/glob.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/globals.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/iterator.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/memory.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/method.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/module.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/newobj.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/symbol.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/token_paste.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/gcc_version_since.h
+dmydln.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+dmydln.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+dmydln.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+dmydln.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+dmydln.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
dmydln.$(OBJEXT): {$(VPATH)}config.h
dmydln.$(OBJEXT): {$(VPATH)}defines.h
dmydln.$(OBJEXT): {$(VPATH)}dmydln.c
dmydln.$(OBJEXT): {$(VPATH)}intern.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/assume.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/cast.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/config.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/ctype.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/dosish.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/error.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/eval.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/event.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/gc.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/glob.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/globals.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/iterator.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/memory.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/method.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/module.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/newobj.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/symbol.h
+dmydln.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -1925,15 +4449,180 @@ enc/utf_8.$(OBJEXT): {$(VPATH)}missing.h
enc/utf_8.$(OBJEXT): {$(VPATH)}regenc.h
encoding.$(OBJEXT): $(hdrdir)/ruby.h
encoding.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/class.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/enc.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/gc.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/inits.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/load.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/object.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/serial.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/string.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/vm.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/warnings.h
encoding.$(OBJEXT): {$(VPATH)}assert.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
encoding.$(OBJEXT): {$(VPATH)}config.h
+encoding.$(OBJEXT): {$(VPATH)}debug_counter.h
encoding.$(OBJEXT): {$(VPATH)}defines.h
encoding.$(OBJEXT): {$(VPATH)}encindex.h
encoding.$(OBJEXT): {$(VPATH)}encoding.c
encoding.$(OBJEXT): {$(VPATH)}encoding.h
+encoding.$(OBJEXT): {$(VPATH)}id_table.h
encoding.$(OBJEXT): {$(VPATH)}intern.h
encoding.$(OBJEXT): {$(VPATH)}internal.h
+encoding.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+encoding.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+encoding.$(OBJEXT): {$(VPATH)}internal/assume.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+encoding.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+encoding.$(OBJEXT): {$(VPATH)}internal/cast.h
+encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+encoding.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+encoding.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+encoding.$(OBJEXT): {$(VPATH)}internal/config.h
+encoding.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+encoding.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+encoding.$(OBJEXT): {$(VPATH)}internal/ctype.h
+encoding.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+encoding.$(OBJEXT): {$(VPATH)}internal/dosish.h
+encoding.$(OBJEXT): {$(VPATH)}internal/error.h
+encoding.$(OBJEXT): {$(VPATH)}internal/eval.h
+encoding.$(OBJEXT): {$(VPATH)}internal/event.h
+encoding.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+encoding.$(OBJEXT): {$(VPATH)}internal/gc.h
+encoding.$(OBJEXT): {$(VPATH)}internal/glob.h
+encoding.$(OBJEXT): {$(VPATH)}internal/globals.h
+encoding.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+encoding.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+encoding.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+encoding.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+encoding.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+encoding.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+encoding.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+encoding.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+encoding.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+encoding.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+encoding.$(OBJEXT): {$(VPATH)}internal/iterator.h
+encoding.$(OBJEXT): {$(VPATH)}internal/memory.h
+encoding.$(OBJEXT): {$(VPATH)}internal/method.h
+encoding.$(OBJEXT): {$(VPATH)}internal/module.h
+encoding.$(OBJEXT): {$(VPATH)}internal/newobj.h
+encoding.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+encoding.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+encoding.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+encoding.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+encoding.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+encoding.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+encoding.$(OBJEXT): {$(VPATH)}internal/symbol.h
+encoding.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+encoding.$(OBJEXT): {$(VPATH)}internal/value.h
+encoding.$(OBJEXT): {$(VPATH)}internal/value_type.h
+encoding.$(OBJEXT): {$(VPATH)}internal/variable.h
+encoding.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+encoding.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
encoding.$(OBJEXT): {$(VPATH)}missing.h
+encoding.$(OBJEXT): {$(VPATH)}node.h
encoding.$(OBJEXT): {$(VPATH)}onigmo.h
encoding.$(OBJEXT): {$(VPATH)}oniguruma.h
encoding.$(OBJEXT): {$(VPATH)}regenc.h
@@ -1941,33 +4630,378 @@ encoding.$(OBJEXT): {$(VPATH)}ruby_assert.h
encoding.$(OBJEXT): {$(VPATH)}st.h
encoding.$(OBJEXT): {$(VPATH)}subst.h
encoding.$(OBJEXT): {$(VPATH)}util.h
+encoding.$(OBJEXT): {$(VPATH)}vm_debug.h
+encoding.$(OBJEXT): {$(VPATH)}vm_sync.h
enum.$(OBJEXT): $(hdrdir)/ruby.h
enum.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enum.$(OBJEXT): $(top_srcdir)/internal/array.h
+enum.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+enum.$(OBJEXT): $(top_srcdir)/internal/bits.h
+enum.$(OBJEXT): $(top_srcdir)/internal/class.h
+enum.$(OBJEXT): $(top_srcdir)/internal/compar.h
+enum.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+enum.$(OBJEXT): $(top_srcdir)/internal/enum.h
+enum.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+enum.$(OBJEXT): $(top_srcdir)/internal/gc.h
+enum.$(OBJEXT): $(top_srcdir)/internal/hash.h
+enum.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+enum.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+enum.$(OBJEXT): $(top_srcdir)/internal/object.h
+enum.$(OBJEXT): $(top_srcdir)/internal/proc.h
+enum.$(OBJEXT): $(top_srcdir)/internal/rational.h
+enum.$(OBJEXT): $(top_srcdir)/internal/re.h
+enum.$(OBJEXT): $(top_srcdir)/internal/serial.h
+enum.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+enum.$(OBJEXT): $(top_srcdir)/internal/vm.h
+enum.$(OBJEXT): $(top_srcdir)/internal/warnings.h
enum.$(OBJEXT): {$(VPATH)}assert.h
+enum.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+enum.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+enum.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+enum.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+enum.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+enum.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+enum.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+enum.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+enum.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enum.$(OBJEXT): {$(VPATH)}config.h
enum.$(OBJEXT): {$(VPATH)}defines.h
enum.$(OBJEXT): {$(VPATH)}encoding.h
enum.$(OBJEXT): {$(VPATH)}enum.c
enum.$(OBJEXT): {$(VPATH)}id.h
+enum.$(OBJEXT): {$(VPATH)}id_table.h
enum.$(OBJEXT): {$(VPATH)}intern.h
enum.$(OBJEXT): {$(VPATH)}internal.h
+enum.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+enum.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+enum.$(OBJEXT): {$(VPATH)}internal/assume.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+enum.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+enum.$(OBJEXT): {$(VPATH)}internal/cast.h
+enum.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+enum.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+enum.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+enum.$(OBJEXT): {$(VPATH)}internal/config.h
+enum.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+enum.$(OBJEXT): {$(VPATH)}internal/core.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+enum.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+enum.$(OBJEXT): {$(VPATH)}internal/ctype.h
+enum.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+enum.$(OBJEXT): {$(VPATH)}internal/dosish.h
+enum.$(OBJEXT): {$(VPATH)}internal/error.h
+enum.$(OBJEXT): {$(VPATH)}internal/eval.h
+enum.$(OBJEXT): {$(VPATH)}internal/event.h
+enum.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+enum.$(OBJEXT): {$(VPATH)}internal/gc.h
+enum.$(OBJEXT): {$(VPATH)}internal/glob.h
+enum.$(OBJEXT): {$(VPATH)}internal/globals.h
+enum.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+enum.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+enum.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+enum.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+enum.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+enum.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+enum.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+enum.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+enum.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+enum.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+enum.$(OBJEXT): {$(VPATH)}internal/iterator.h
+enum.$(OBJEXT): {$(VPATH)}internal/memory.h
+enum.$(OBJEXT): {$(VPATH)}internal/method.h
+enum.$(OBJEXT): {$(VPATH)}internal/module.h
+enum.$(OBJEXT): {$(VPATH)}internal/newobj.h
+enum.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+enum.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+enum.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+enum.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+enum.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+enum.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+enum.$(OBJEXT): {$(VPATH)}internal/symbol.h
+enum.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+enum.$(OBJEXT): {$(VPATH)}internal/value.h
+enum.$(OBJEXT): {$(VPATH)}internal/value_type.h
+enum.$(OBJEXT): {$(VPATH)}internal/variable.h
+enum.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+enum.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
enum.$(OBJEXT): {$(VPATH)}missing.h
enum.$(OBJEXT): {$(VPATH)}onigmo.h
enum.$(OBJEXT): {$(VPATH)}oniguruma.h
+enum.$(OBJEXT): {$(VPATH)}ruby_assert.h
enum.$(OBJEXT): {$(VPATH)}st.h
enum.$(OBJEXT): {$(VPATH)}subst.h
enum.$(OBJEXT): {$(VPATH)}symbol.h
enum.$(OBJEXT): {$(VPATH)}util.h
enumerator.$(OBJEXT): $(hdrdir)/ruby.h
enumerator.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/array.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/bits.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/enumerator.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/error.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/gc.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/hash.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/range.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/rational.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/serial.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/string.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/struct.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/vm.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/warnings.h
enumerator.$(OBJEXT): {$(VPATH)}assert.h
+enumerator.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+enumerator.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+enumerator.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+enumerator.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+enumerator.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+enumerator.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+enumerator.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+enumerator.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+enumerator.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
enumerator.$(OBJEXT): {$(VPATH)}config.h
enumerator.$(OBJEXT): {$(VPATH)}defines.h
+enumerator.$(OBJEXT): {$(VPATH)}encoding.h
enumerator.$(OBJEXT): {$(VPATH)}enumerator.c
enumerator.$(OBJEXT): {$(VPATH)}id.h
enumerator.$(OBJEXT): {$(VPATH)}intern.h
enumerator.$(OBJEXT): {$(VPATH)}internal.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/assume.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/cast.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/config.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/ctype.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/dosish.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/error.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/eval.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/event.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/gc.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/glob.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/globals.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/iterator.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/memory.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/method.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/module.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/newobj.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/symbol.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/value.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/value_type.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/variable.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
enumerator.$(OBJEXT): {$(VPATH)}missing.h
+enumerator.$(OBJEXT): {$(VPATH)}onigmo.h
+enumerator.$(OBJEXT): {$(VPATH)}oniguruma.h
+enumerator.$(OBJEXT): {$(VPATH)}ruby_assert.h
enumerator.$(OBJEXT): {$(VPATH)}st.h
enumerator.$(OBJEXT): {$(VPATH)}subst.h
error.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
@@ -1976,16 +5010,187 @@ error.$(OBJEXT): $(CCAN_DIR)/list/list.h
error.$(OBJEXT): $(CCAN_DIR)/str/str.h
error.$(OBJEXT): $(hdrdir)/ruby.h
error.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+error.$(OBJEXT): $(top_srcdir)/internal/array.h
+error.$(OBJEXT): $(top_srcdir)/internal/class.h
+error.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+error.$(OBJEXT): $(top_srcdir)/internal/error.h
+error.$(OBJEXT): $(top_srcdir)/internal/eval.h
+error.$(OBJEXT): $(top_srcdir)/internal/gc.h
+error.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+error.$(OBJEXT): $(top_srcdir)/internal/io.h
+error.$(OBJEXT): $(top_srcdir)/internal/load.h
+error.$(OBJEXT): $(top_srcdir)/internal/object.h
+error.$(OBJEXT): $(top_srcdir)/internal/serial.h
+error.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+error.$(OBJEXT): $(top_srcdir)/internal/string.h
+error.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+error.$(OBJEXT): $(top_srcdir)/internal/thread.h
+error.$(OBJEXT): $(top_srcdir)/internal/variable.h
+error.$(OBJEXT): $(top_srcdir)/internal/vm.h
+error.$(OBJEXT): $(top_srcdir)/internal/warnings.h
error.$(OBJEXT): {$(VPATH)}assert.h
+error.$(OBJEXT): {$(VPATH)}atomic.h
+error.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+error.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+error.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+error.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+error.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+error.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+error.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+error.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+error.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
error.$(OBJEXT): {$(VPATH)}builtin.h
error.$(OBJEXT): {$(VPATH)}config.h
+error.$(OBJEXT): {$(VPATH)}constant.h
error.$(OBJEXT): {$(VPATH)}defines.h
error.$(OBJEXT): {$(VPATH)}encoding.h
error.$(OBJEXT): {$(VPATH)}error.c
error.$(OBJEXT): {$(VPATH)}eval_intern.h
error.$(OBJEXT): {$(VPATH)}id.h
+error.$(OBJEXT): {$(VPATH)}id_table.h
error.$(OBJEXT): {$(VPATH)}intern.h
error.$(OBJEXT): {$(VPATH)}internal.h
+error.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+error.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+error.$(OBJEXT): {$(VPATH)}internal/assume.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+error.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+error.$(OBJEXT): {$(VPATH)}internal/cast.h
+error.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+error.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+error.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+error.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+error.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+error.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+error.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+error.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+error.$(OBJEXT): {$(VPATH)}internal/config.h
+error.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+error.$(OBJEXT): {$(VPATH)}internal/core.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+error.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+error.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+error.$(OBJEXT): {$(VPATH)}internal/ctype.h
+error.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+error.$(OBJEXT): {$(VPATH)}internal/dosish.h
+error.$(OBJEXT): {$(VPATH)}internal/error.h
+error.$(OBJEXT): {$(VPATH)}internal/eval.h
+error.$(OBJEXT): {$(VPATH)}internal/event.h
+error.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+error.$(OBJEXT): {$(VPATH)}internal/gc.h
+error.$(OBJEXT): {$(VPATH)}internal/glob.h
+error.$(OBJEXT): {$(VPATH)}internal/globals.h
+error.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+error.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+error.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+error.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+error.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+error.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+error.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+error.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+error.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+error.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+error.$(OBJEXT): {$(VPATH)}internal/iterator.h
+error.$(OBJEXT): {$(VPATH)}internal/memory.h
+error.$(OBJEXT): {$(VPATH)}internal/method.h
+error.$(OBJEXT): {$(VPATH)}internal/module.h
+error.$(OBJEXT): {$(VPATH)}internal/newobj.h
+error.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+error.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+error.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+error.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+error.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+error.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+error.$(OBJEXT): {$(VPATH)}internal/symbol.h
+error.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2007,26 +5212,203 @@ eval.$(OBJEXT): $(CCAN_DIR)/list/list.h
eval.$(OBJEXT): $(CCAN_DIR)/str/str.h
eval.$(OBJEXT): $(hdrdir)/ruby.h
eval.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+eval.$(OBJEXT): $(top_srcdir)/internal/array.h
+eval.$(OBJEXT): $(top_srcdir)/internal/class.h
+eval.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+eval.$(OBJEXT): $(top_srcdir)/internal/error.h
+eval.$(OBJEXT): $(top_srcdir)/internal/eval.h
+eval.$(OBJEXT): $(top_srcdir)/internal/gc.h
+eval.$(OBJEXT): $(top_srcdir)/internal/hash.h
+eval.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+eval.$(OBJEXT): $(top_srcdir)/internal/inits.h
+eval.$(OBJEXT): $(top_srcdir)/internal/io.h
+eval.$(OBJEXT): $(top_srcdir)/internal/object.h
+eval.$(OBJEXT): $(top_srcdir)/internal/scheduler.h
+eval.$(OBJEXT): $(top_srcdir)/internal/serial.h
+eval.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+eval.$(OBJEXT): $(top_srcdir)/internal/string.h
+eval.$(OBJEXT): $(top_srcdir)/internal/thread.h
+eval.$(OBJEXT): $(top_srcdir)/internal/variable.h
+eval.$(OBJEXT): $(top_srcdir)/internal/vm.h
+eval.$(OBJEXT): $(top_srcdir)/internal/warnings.h
eval.$(OBJEXT): {$(VPATH)}assert.h
+eval.$(OBJEXT): {$(VPATH)}atomic.h
+eval.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+eval.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+eval.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+eval.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+eval.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+eval.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+eval.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+eval.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+eval.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
eval.$(OBJEXT): {$(VPATH)}config.h
+eval.$(OBJEXT): {$(VPATH)}constant.h
eval.$(OBJEXT): {$(VPATH)}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)}gc.h
eval.$(OBJEXT): {$(VPATH)}id.h
+eval.$(OBJEXT): {$(VPATH)}id_table.h
eval.$(OBJEXT): {$(VPATH)}intern.h
eval.$(OBJEXT): {$(VPATH)}internal.h
+eval.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+eval.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+eval.$(OBJEXT): {$(VPATH)}internal/assume.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+eval.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+eval.$(OBJEXT): {$(VPATH)}internal/cast.h
+eval.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+eval.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+eval.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+eval.$(OBJEXT): {$(VPATH)}internal/config.h
+eval.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+eval.$(OBJEXT): {$(VPATH)}internal/core.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+eval.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+eval.$(OBJEXT): {$(VPATH)}internal/ctype.h
+eval.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+eval.$(OBJEXT): {$(VPATH)}internal/dosish.h
+eval.$(OBJEXT): {$(VPATH)}internal/error.h
+eval.$(OBJEXT): {$(VPATH)}internal/eval.h
+eval.$(OBJEXT): {$(VPATH)}internal/event.h
+eval.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+eval.$(OBJEXT): {$(VPATH)}internal/gc.h
+eval.$(OBJEXT): {$(VPATH)}internal/glob.h
+eval.$(OBJEXT): {$(VPATH)}internal/globals.h
+eval.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+eval.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+eval.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+eval.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+eval.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+eval.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+eval.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+eval.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+eval.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+eval.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+eval.$(OBJEXT): {$(VPATH)}internal/iterator.h
+eval.$(OBJEXT): {$(VPATH)}internal/memory.h
+eval.$(OBJEXT): {$(VPATH)}internal/method.h
+eval.$(OBJEXT): {$(VPATH)}internal/module.h
+eval.$(OBJEXT): {$(VPATH)}internal/newobj.h
+eval.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+eval.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+eval.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+eval.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+eval.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+eval.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+eval.$(OBJEXT): {$(VPATH)}internal/symbol.h
+eval.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+eval.$(OBJEXT): {$(VPATH)}internal/value.h
+eval.$(OBJEXT): {$(VPATH)}internal/value_type.h
+eval.$(OBJEXT): {$(VPATH)}internal/variable.h
+eval.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+eval.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+eval.$(OBJEXT): {$(VPATH)}io.h
eval.$(OBJEXT): {$(VPATH)}iseq.h
eval.$(OBJEXT): {$(VPATH)}method.h
eval.$(OBJEXT): {$(VPATH)}missing.h
eval.$(OBJEXT): {$(VPATH)}mjit.h
eval.$(OBJEXT): {$(VPATH)}node.h
+eval.$(OBJEXT): {$(VPATH)}onigmo.h
+eval.$(OBJEXT): {$(VPATH)}oniguruma.h
eval.$(OBJEXT): {$(VPATH)}probes.dmyh
eval.$(OBJEXT): {$(VPATH)}probes.h
eval.$(OBJEXT): {$(VPATH)}probes_helper.h
+eval.$(OBJEXT): {$(VPATH)}ractor.h
+eval.$(OBJEXT): {$(VPATH)}ractor_core.h
eval.$(OBJEXT): {$(VPATH)}ruby_assert.h
eval.$(OBJEXT): {$(VPATH)}ruby_atomic.h
eval.$(OBJEXT): {$(VPATH)}st.h
@@ -2035,13 +5417,51 @@ 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
explicit_bzero.$(OBJEXT): {$(VPATH)}config.h
explicit_bzero.$(OBJEXT): {$(VPATH)}explicit_bzero.c
+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)}missing.h
file.$(OBJEXT): $(hdrdir)/ruby.h
file.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+file.$(OBJEXT): $(top_srcdir)/internal/array.h
+file.$(OBJEXT): $(top_srcdir)/internal/class.h
+file.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+file.$(OBJEXT): $(top_srcdir)/internal/dir.h
+file.$(OBJEXT): $(top_srcdir)/internal/error.h
+file.$(OBJEXT): $(top_srcdir)/internal/file.h
+file.$(OBJEXT): $(top_srcdir)/internal/gc.h
+file.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+file.$(OBJEXT): $(top_srcdir)/internal/io.h
+file.$(OBJEXT): $(top_srcdir)/internal/load.h
+file.$(OBJEXT): $(top_srcdir)/internal/object.h
+file.$(OBJEXT): $(top_srcdir)/internal/process.h
+file.$(OBJEXT): $(top_srcdir)/internal/serial.h
+file.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+file.$(OBJEXT): $(top_srcdir)/internal/string.h
+file.$(OBJEXT): $(top_srcdir)/internal/thread.h
+file.$(OBJEXT): $(top_srcdir)/internal/vm.h
+file.$(OBJEXT): $(top_srcdir)/internal/warnings.h
file.$(OBJEXT): {$(VPATH)}assert.h
+file.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+file.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+file.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+file.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+file.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+file.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+file.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+file.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+file.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
file.$(OBJEXT): {$(VPATH)}config.h
file.$(OBJEXT): {$(VPATH)}defines.h
file.$(OBJEXT): {$(VPATH)}dln.h
@@ -2049,8 +5469,149 @@ file.$(OBJEXT): {$(VPATH)}encindex.h
file.$(OBJEXT): {$(VPATH)}encoding.h
file.$(OBJEXT): {$(VPATH)}file.c
file.$(OBJEXT): {$(VPATH)}id.h
+file.$(OBJEXT): {$(VPATH)}id_table.h
file.$(OBJEXT): {$(VPATH)}intern.h
file.$(OBJEXT): {$(VPATH)}internal.h
+file.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+file.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+file.$(OBJEXT): {$(VPATH)}internal/assume.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+file.$(OBJEXT): {$(VPATH)}internal/cast.h
+file.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+file.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+file.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+file.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+file.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+file.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+file.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+file.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+file.$(OBJEXT): {$(VPATH)}internal/config.h
+file.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+file.$(OBJEXT): {$(VPATH)}internal/core.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+file.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+file.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+file.$(OBJEXT): {$(VPATH)}internal/ctype.h
+file.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+file.$(OBJEXT): {$(VPATH)}internal/dosish.h
+file.$(OBJEXT): {$(VPATH)}internal/error.h
+file.$(OBJEXT): {$(VPATH)}internal/eval.h
+file.$(OBJEXT): {$(VPATH)}internal/event.h
+file.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+file.$(OBJEXT): {$(VPATH)}internal/gc.h
+file.$(OBJEXT): {$(VPATH)}internal/glob.h
+file.$(OBJEXT): {$(VPATH)}internal/globals.h
+file.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+file.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+file.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+file.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+file.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+file.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+file.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+file.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+file.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+file.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+file.$(OBJEXT): {$(VPATH)}internal/iterator.h
+file.$(OBJEXT): {$(VPATH)}internal/memory.h
+file.$(OBJEXT): {$(VPATH)}internal/method.h
+file.$(OBJEXT): {$(VPATH)}internal/module.h
+file.$(OBJEXT): {$(VPATH)}internal/newobj.h
+file.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+file.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+file.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+file.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+file.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+file.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+file.$(OBJEXT): {$(VPATH)}internal/symbol.h
+file.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2065,7 +5626,45 @@ gc.$(OBJEXT): $(CCAN_DIR)/list/list.h
gc.$(OBJEXT): $(CCAN_DIR)/str/str.h
gc.$(OBJEXT): $(hdrdir)/ruby.h
gc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+gc.$(OBJEXT): $(top_srcdir)/internal/array.h
+gc.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+gc.$(OBJEXT): $(top_srcdir)/internal/bits.h
+gc.$(OBJEXT): $(top_srcdir)/internal/class.h
+gc.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+gc.$(OBJEXT): $(top_srcdir)/internal/complex.h
+gc.$(OBJEXT): $(top_srcdir)/internal/cont.h
+gc.$(OBJEXT): $(top_srcdir)/internal/error.h
+gc.$(OBJEXT): $(top_srcdir)/internal/eval.h
+gc.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+gc.$(OBJEXT): $(top_srcdir)/internal/gc.h
+gc.$(OBJEXT): $(top_srcdir)/internal/hash.h
+gc.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+gc.$(OBJEXT): $(top_srcdir)/internal/io.h
+gc.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+gc.$(OBJEXT): $(top_srcdir)/internal/object.h
+gc.$(OBJEXT): $(top_srcdir)/internal/proc.h
+gc.$(OBJEXT): $(top_srcdir)/internal/rational.h
+gc.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+gc.$(OBJEXT): $(top_srcdir)/internal/serial.h
+gc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+gc.$(OBJEXT): $(top_srcdir)/internal/string.h
+gc.$(OBJEXT): $(top_srcdir)/internal/struct.h
+gc.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+gc.$(OBJEXT): $(top_srcdir)/internal/thread.h
+gc.$(OBJEXT): $(top_srcdir)/internal/variable.h
+gc.$(OBJEXT): $(top_srcdir)/internal/vm.h
+gc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
gc.$(OBJEXT): {$(VPATH)}assert.h
+gc.$(OBJEXT): {$(VPATH)}atomic.h
+gc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+gc.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+gc.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+gc.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+gc.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+gc.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+gc.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+gc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+gc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
gc.$(OBJEXT): {$(VPATH)}builtin.h
gc.$(OBJEXT): {$(VPATH)}config.h
gc.$(OBJEXT): {$(VPATH)}constant.h
@@ -2081,6 +5680,147 @@ gc.$(OBJEXT): {$(VPATH)}id.h
gc.$(OBJEXT): {$(VPATH)}id_table.h
gc.$(OBJEXT): {$(VPATH)}intern.h
gc.$(OBJEXT): {$(VPATH)}internal.h
+gc.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+gc.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+gc.$(OBJEXT): {$(VPATH)}internal/assume.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+gc.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+gc.$(OBJEXT): {$(VPATH)}internal/cast.h
+gc.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+gc.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+gc.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+gc.$(OBJEXT): {$(VPATH)}internal/config.h
+gc.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+gc.$(OBJEXT): {$(VPATH)}internal/core.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+gc.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+gc.$(OBJEXT): {$(VPATH)}internal/ctype.h
+gc.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+gc.$(OBJEXT): {$(VPATH)}internal/dosish.h
+gc.$(OBJEXT): {$(VPATH)}internal/error.h
+gc.$(OBJEXT): {$(VPATH)}internal/eval.h
+gc.$(OBJEXT): {$(VPATH)}internal/event.h
+gc.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+gc.$(OBJEXT): {$(VPATH)}internal/gc.h
+gc.$(OBJEXT): {$(VPATH)}internal/glob.h
+gc.$(OBJEXT): {$(VPATH)}internal/globals.h
+gc.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+gc.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+gc.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+gc.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+gc.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+gc.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+gc.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+gc.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+gc.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+gc.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+gc.$(OBJEXT): {$(VPATH)}internal/iterator.h
+gc.$(OBJEXT): {$(VPATH)}internal/memory.h
+gc.$(OBJEXT): {$(VPATH)}internal/method.h
+gc.$(OBJEXT): {$(VPATH)}internal/module.h
+gc.$(OBJEXT): {$(VPATH)}internal/newobj.h
+gc.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+gc.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+gc.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+gc.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+gc.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+gc.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+gc.$(OBJEXT): {$(VPATH)}internal/symbol.h
+gc.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+gc.$(OBJEXT): {$(VPATH)}internal/value.h
+gc.$(OBJEXT): {$(VPATH)}internal/value_type.h
+gc.$(OBJEXT): {$(VPATH)}internal/variable.h
+gc.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+gc.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
gc.$(OBJEXT): {$(VPATH)}io.h
gc.$(OBJEXT): {$(VPATH)}method.h
gc.$(OBJEXT): {$(VPATH)}missing.h
@@ -2090,6 +5830,8 @@ gc.$(OBJEXT): {$(VPATH)}onigmo.h
gc.$(OBJEXT): {$(VPATH)}oniguruma.h
gc.$(OBJEXT): {$(VPATH)}probes.dmyh
gc.$(OBJEXT): {$(VPATH)}probes.h
+gc.$(OBJEXT): {$(VPATH)}ractor.h
+gc.$(OBJEXT): {$(VPATH)}ractor_core.h
gc.$(OBJEXT): {$(VPATH)}re.h
gc.$(OBJEXT): {$(VPATH)}regenc.h
gc.$(OBJEXT): {$(VPATH)}regex.h
@@ -2104,15 +5846,36 @@ gc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
gc.$(OBJEXT): {$(VPATH)}thread_native.h
gc.$(OBJEXT): {$(VPATH)}transient_heap.h
gc.$(OBJEXT): {$(VPATH)}util.h
+gc.$(OBJEXT): {$(VPATH)}vm_callinfo.h
gc.$(OBJEXT): {$(VPATH)}vm_core.h
+gc.$(OBJEXT): {$(VPATH)}vm_debug.h
gc.$(OBJEXT): {$(VPATH)}vm_opts.h
+gc.$(OBJEXT): {$(VPATH)}vm_sync.h
golf_prelude.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
golf_prelude.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
golf_prelude.$(OBJEXT): $(CCAN_DIR)/list/list.h
golf_prelude.$(OBJEXT): $(CCAN_DIR)/str/str.h
golf_prelude.$(OBJEXT): $(hdrdir)/ruby.h
golf_prelude.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+golf_prelude.$(OBJEXT): $(top_srcdir)/internal/array.h
+golf_prelude.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+golf_prelude.$(OBJEXT): $(top_srcdir)/internal/gc.h
+golf_prelude.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+golf_prelude.$(OBJEXT): $(top_srcdir)/internal/serial.h
+golf_prelude.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+golf_prelude.$(OBJEXT): $(top_srcdir)/internal/vm.h
+golf_prelude.$(OBJEXT): $(top_srcdir)/internal/warnings.h
golf_prelude.$(OBJEXT): {$(VPATH)}assert.h
+golf_prelude.$(OBJEXT): {$(VPATH)}atomic.h
+golf_prelude.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+golf_prelude.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+golf_prelude.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+golf_prelude.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+golf_prelude.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+golf_prelude.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+golf_prelude.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+golf_prelude.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+golf_prelude.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
golf_prelude.$(OBJEXT): {$(VPATH)}config.h
golf_prelude.$(OBJEXT): {$(VPATH)}defines.h
golf_prelude.$(OBJEXT): {$(VPATH)}golf_prelude.c
@@ -2120,6 +5883,146 @@ golf_prelude.$(OBJEXT): {$(VPATH)}golf_prelude.rb
golf_prelude.$(OBJEXT): {$(VPATH)}id.h
golf_prelude.$(OBJEXT): {$(VPATH)}intern.h
golf_prelude.$(OBJEXT): {$(VPATH)}internal.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/assume.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/cast.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/config.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/ctype.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/dosish.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/error.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/eval.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/event.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/gc.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/glob.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/globals.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/iterator.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/memory.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/method.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/module.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/newobj.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/symbol.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/value.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/value_type.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/variable.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+golf_prelude.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
golf_prelude.$(OBJEXT): {$(VPATH)}iseq.h
golf_prelude.$(OBJEXT): {$(VPATH)}method.h
golf_prelude.$(OBJEXT): {$(VPATH)}missing.h
@@ -2136,10 +6039,159 @@ goruby.$(OBJEXT): $(hdrdir)/ruby.h
goruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h
goruby.$(OBJEXT): {$(VPATH)}assert.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)}defines.h
goruby.$(OBJEXT): {$(VPATH)}goruby.c
goruby.$(OBJEXT): {$(VPATH)}intern.h
+goruby.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+goruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+goruby.$(OBJEXT): {$(VPATH)}internal/assume.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+goruby.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+goruby.$(OBJEXT): {$(VPATH)}internal/cast.h
+goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+goruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+goruby.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+goruby.$(OBJEXT): {$(VPATH)}internal/config.h
+goruby.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+goruby.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+goruby.$(OBJEXT): {$(VPATH)}internal/ctype.h
+goruby.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+goruby.$(OBJEXT): {$(VPATH)}internal/dosish.h
+goruby.$(OBJEXT): {$(VPATH)}internal/error.h
+goruby.$(OBJEXT): {$(VPATH)}internal/eval.h
+goruby.$(OBJEXT): {$(VPATH)}internal/event.h
+goruby.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+goruby.$(OBJEXT): {$(VPATH)}internal/gc.h
+goruby.$(OBJEXT): {$(VPATH)}internal/glob.h
+goruby.$(OBJEXT): {$(VPATH)}internal/globals.h
+goruby.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+goruby.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+goruby.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+goruby.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+goruby.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+goruby.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+goruby.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+goruby.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+goruby.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+goruby.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+goruby.$(OBJEXT): {$(VPATH)}internal/iterator.h
+goruby.$(OBJEXT): {$(VPATH)}internal/memory.h
+goruby.$(OBJEXT): {$(VPATH)}internal/method.h
+goruby.$(OBJEXT): {$(VPATH)}internal/module.h
+goruby.$(OBJEXT): {$(VPATH)}internal/newobj.h
+goruby.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+goruby.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+goruby.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+goruby.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+goruby.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+goruby.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+goruby.$(OBJEXT): {$(VPATH)}internal/symbol.h
+goruby.$(OBJEXT): {$(VPATH)}internal/token_paste.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)}main.c
goruby.$(OBJEXT): {$(VPATH)}missing.h
goruby.$(OBJEXT): {$(VPATH)}node.h
@@ -2148,15 +6200,183 @@ goruby.$(OBJEXT): {$(VPATH)}subst.h
goruby.$(OBJEXT): {$(VPATH)}vm_debug.h
hash.$(OBJEXT): $(hdrdir)/ruby.h
hash.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+hash.$(OBJEXT): $(top_srcdir)/internal/array.h
+hash.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+hash.$(OBJEXT): $(top_srcdir)/internal/bits.h
+hash.$(OBJEXT): $(top_srcdir)/internal/class.h
+hash.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+hash.$(OBJEXT): $(top_srcdir)/internal/cont.h
+hash.$(OBJEXT): $(top_srcdir)/internal/error.h
+hash.$(OBJEXT): $(top_srcdir)/internal/gc.h
+hash.$(OBJEXT): $(top_srcdir)/internal/hash.h
+hash.$(OBJEXT): $(top_srcdir)/internal/object.h
+hash.$(OBJEXT): $(top_srcdir)/internal/proc.h
+hash.$(OBJEXT): $(top_srcdir)/internal/serial.h
+hash.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+hash.$(OBJEXT): $(top_srcdir)/internal/string.h
+hash.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+hash.$(OBJEXT): $(top_srcdir)/internal/time.h
+hash.$(OBJEXT): $(top_srcdir)/internal/vm.h
+hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h
hash.$(OBJEXT): {$(VPATH)}assert.h
+hash.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+hash.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+hash.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+hash.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+hash.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+hash.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+hash.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+hash.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+hash.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
hash.$(OBJEXT): {$(VPATH)}config.h
hash.$(OBJEXT): {$(VPATH)}debug_counter.h
hash.$(OBJEXT): {$(VPATH)}defines.h
hash.$(OBJEXT): {$(VPATH)}encoding.h
hash.$(OBJEXT): {$(VPATH)}hash.c
hash.$(OBJEXT): {$(VPATH)}id.h
+hash.$(OBJEXT): {$(VPATH)}id_table.h
hash.$(OBJEXT): {$(VPATH)}intern.h
hash.$(OBJEXT): {$(VPATH)}internal.h
+hash.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+hash.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+hash.$(OBJEXT): {$(VPATH)}internal/assume.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+hash.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+hash.$(OBJEXT): {$(VPATH)}internal/cast.h
+hash.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+hash.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+hash.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+hash.$(OBJEXT): {$(VPATH)}internal/config.h
+hash.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+hash.$(OBJEXT): {$(VPATH)}internal/core.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+hash.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+hash.$(OBJEXT): {$(VPATH)}internal/ctype.h
+hash.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+hash.$(OBJEXT): {$(VPATH)}internal/dosish.h
+hash.$(OBJEXT): {$(VPATH)}internal/error.h
+hash.$(OBJEXT): {$(VPATH)}internal/eval.h
+hash.$(OBJEXT): {$(VPATH)}internal/event.h
+hash.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+hash.$(OBJEXT): {$(VPATH)}internal/gc.h
+hash.$(OBJEXT): {$(VPATH)}internal/glob.h
+hash.$(OBJEXT): {$(VPATH)}internal/globals.h
+hash.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+hash.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+hash.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+hash.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+hash.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+hash.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+hash.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+hash.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+hash.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+hash.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+hash.$(OBJEXT): {$(VPATH)}internal/iterator.h
+hash.$(OBJEXT): {$(VPATH)}internal/memory.h
+hash.$(OBJEXT): {$(VPATH)}internal/method.h
+hash.$(OBJEXT): {$(VPATH)}internal/module.h
+hash.$(OBJEXT): {$(VPATH)}internal/newobj.h
+hash.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+hash.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+hash.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+hash.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+hash.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+hash.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+hash.$(OBJEXT): {$(VPATH)}internal/symbol.h
+hash.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+hash.$(OBJEXT): {$(VPATH)}internal/value.h
+hash.$(OBJEXT): {$(VPATH)}internal/value_type.h
+hash.$(OBJEXT): {$(VPATH)}internal/variable.h
+hash.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+hash.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
hash.$(OBJEXT): {$(VPATH)}missing.h
hash.$(OBJEXT): {$(VPATH)}onigmo.h
hash.$(OBJEXT): {$(VPATH)}oniguruma.h
@@ -2170,13 +6390,165 @@ hash.$(OBJEXT): {$(VPATH)}transient_heap.h
hash.$(OBJEXT): {$(VPATH)}util.h
inits.$(OBJEXT): $(hdrdir)/ruby.h
inits.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+inits.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+inits.$(OBJEXT): $(top_srcdir)/internal/inits.h
+inits.$(OBJEXT): $(top_srcdir)/internal/warnings.h
inits.$(OBJEXT): {$(VPATH)}assert.h
+inits.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+inits.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+inits.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+inits.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+inits.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+inits.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+inits.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+inits.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+inits.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
inits.$(OBJEXT): {$(VPATH)}builtin.h
inits.$(OBJEXT): {$(VPATH)}config.h
inits.$(OBJEXT): {$(VPATH)}defines.h
inits.$(OBJEXT): {$(VPATH)}inits.c
inits.$(OBJEXT): {$(VPATH)}intern.h
inits.$(OBJEXT): {$(VPATH)}internal.h
+inits.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+inits.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+inits.$(OBJEXT): {$(VPATH)}internal/assume.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+inits.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+inits.$(OBJEXT): {$(VPATH)}internal/cast.h
+inits.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+inits.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+inits.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+inits.$(OBJEXT): {$(VPATH)}internal/config.h
+inits.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+inits.$(OBJEXT): {$(VPATH)}internal/core.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+inits.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+inits.$(OBJEXT): {$(VPATH)}internal/ctype.h
+inits.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+inits.$(OBJEXT): {$(VPATH)}internal/dosish.h
+inits.$(OBJEXT): {$(VPATH)}internal/error.h
+inits.$(OBJEXT): {$(VPATH)}internal/eval.h
+inits.$(OBJEXT): {$(VPATH)}internal/event.h
+inits.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+inits.$(OBJEXT): {$(VPATH)}internal/gc.h
+inits.$(OBJEXT): {$(VPATH)}internal/glob.h
+inits.$(OBJEXT): {$(VPATH)}internal/globals.h
+inits.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+inits.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+inits.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+inits.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+inits.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+inits.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+inits.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+inits.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+inits.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+inits.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+inits.$(OBJEXT): {$(VPATH)}internal/iterator.h
+inits.$(OBJEXT): {$(VPATH)}internal/memory.h
+inits.$(OBJEXT): {$(VPATH)}internal/method.h
+inits.$(OBJEXT): {$(VPATH)}internal/module.h
+inits.$(OBJEXT): {$(VPATH)}internal/newobj.h
+inits.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+inits.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+inits.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+inits.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+inits.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+inits.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+inits.$(OBJEXT): {$(VPATH)}internal/symbol.h
+inits.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2187,16 +6559,192 @@ io.$(OBJEXT): $(CCAN_DIR)/list/list.h
io.$(OBJEXT): $(CCAN_DIR)/str/str.h
io.$(OBJEXT): $(hdrdir)/ruby.h
io.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+io.$(OBJEXT): $(top_srcdir)/internal/array.h
+io.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+io.$(OBJEXT): $(top_srcdir)/internal/bits.h
+io.$(OBJEXT): $(top_srcdir)/internal/class.h
+io.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+io.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+io.$(OBJEXT): $(top_srcdir)/internal/error.h
+io.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+io.$(OBJEXT): $(top_srcdir)/internal/gc.h
+io.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+io.$(OBJEXT): $(top_srcdir)/internal/inits.h
+io.$(OBJEXT): $(top_srcdir)/internal/io.h
+io.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+io.$(OBJEXT): $(top_srcdir)/internal/object.h
+io.$(OBJEXT): $(top_srcdir)/internal/process.h
+io.$(OBJEXT): $(top_srcdir)/internal/scheduler.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)}defines.h
io.$(OBJEXT): {$(VPATH)}dln.h
io.$(OBJEXT): {$(VPATH)}encindex.h
io.$(OBJEXT): {$(VPATH)}encoding.h
io.$(OBJEXT): {$(VPATH)}id.h
+io.$(OBJEXT): {$(VPATH)}id_table.h
io.$(OBJEXT): {$(VPATH)}intern.h
io.$(OBJEXT): {$(VPATH)}internal.h
+io.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+io.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+io.$(OBJEXT): {$(VPATH)}internal/assume.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+io.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+io.$(OBJEXT): {$(VPATH)}internal/cast.h
+io.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+io.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+io.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+io.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+io.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+io.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+io.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+io.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+io.$(OBJEXT): {$(VPATH)}internal/config.h
+io.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+io.$(OBJEXT): {$(VPATH)}internal/core.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+io.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+io.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+io.$(OBJEXT): {$(VPATH)}internal/ctype.h
+io.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+io.$(OBJEXT): {$(VPATH)}internal/dosish.h
+io.$(OBJEXT): {$(VPATH)}internal/error.h
+io.$(OBJEXT): {$(VPATH)}internal/eval.h
+io.$(OBJEXT): {$(VPATH)}internal/event.h
+io.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+io.$(OBJEXT): {$(VPATH)}internal/gc.h
+io.$(OBJEXT): {$(VPATH)}internal/glob.h
+io.$(OBJEXT): {$(VPATH)}internal/globals.h
+io.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+io.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+io.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+io.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+io.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+io.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+io.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+io.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+io.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+io.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+io.$(OBJEXT): {$(VPATH)}internal/iterator.h
+io.$(OBJEXT): {$(VPATH)}internal/memory.h
+io.$(OBJEXT): {$(VPATH)}internal/method.h
+io.$(OBJEXT): {$(VPATH)}internal/module.h
+io.$(OBJEXT): {$(VPATH)}internal/newobj.h
+io.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+io.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+io.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+io.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+io.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+io.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+io.$(OBJEXT): {$(VPATH)}internal/symbol.h
+io.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2205,6 +6753,7 @@ io.$(OBJEXT): {$(VPATH)}missing.h
io.$(OBJEXT): {$(VPATH)}node.h
io.$(OBJEXT): {$(VPATH)}onigmo.h
io.$(OBJEXT): {$(VPATH)}oniguruma.h
+io.$(OBJEXT): {$(VPATH)}ractor.h
io.$(OBJEXT): {$(VPATH)}ruby_assert.h
io.$(OBJEXT): {$(VPATH)}ruby_atomic.h
io.$(OBJEXT): {$(VPATH)}st.h
@@ -2221,11 +6770,43 @@ iseq.$(OBJEXT): $(CCAN_DIR)/list/list.h
iseq.$(OBJEXT): $(CCAN_DIR)/str/str.h
iseq.$(OBJEXT): $(hdrdir)/ruby.h
iseq.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/array.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/bits.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/class.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/compile.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/error.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/file.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/gc.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/hash.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/parse.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/serial.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/string.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/thread.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/variable.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/vm.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/warnings.h
iseq.$(OBJEXT): {$(VPATH)}assert.h
+iseq.$(OBJEXT): {$(VPATH)}atomic.h
+iseq.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+iseq.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+iseq.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+iseq.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+iseq.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+iseq.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+iseq.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+iseq.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+iseq.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
iseq.$(OBJEXT): {$(VPATH)}builtin.h
iseq.$(OBJEXT): {$(VPATH)}config.h
+iseq.$(OBJEXT): {$(VPATH)}constant.h
iseq.$(OBJEXT): {$(VPATH)}debug_counter.h
iseq.$(OBJEXT): {$(VPATH)}defines.h
+iseq.$(OBJEXT): {$(VPATH)}encoding.h
iseq.$(OBJEXT): {$(VPATH)}eval_intern.h
iseq.$(OBJEXT): {$(VPATH)}gc.h
iseq.$(OBJEXT): {$(VPATH)}id.h
@@ -2235,6 +6816,146 @@ iseq.$(OBJEXT): {$(VPATH)}insns.inc
iseq.$(OBJEXT): {$(VPATH)}insns_info.inc
iseq.$(OBJEXT): {$(VPATH)}intern.h
iseq.$(OBJEXT): {$(VPATH)}internal.h
+iseq.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+iseq.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+iseq.$(OBJEXT): {$(VPATH)}internal/assume.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+iseq.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+iseq.$(OBJEXT): {$(VPATH)}internal/cast.h
+iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+iseq.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+iseq.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+iseq.$(OBJEXT): {$(VPATH)}internal/config.h
+iseq.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+iseq.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+iseq.$(OBJEXT): {$(VPATH)}internal/ctype.h
+iseq.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+iseq.$(OBJEXT): {$(VPATH)}internal/dosish.h
+iseq.$(OBJEXT): {$(VPATH)}internal/error.h
+iseq.$(OBJEXT): {$(VPATH)}internal/eval.h
+iseq.$(OBJEXT): {$(VPATH)}internal/event.h
+iseq.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+iseq.$(OBJEXT): {$(VPATH)}internal/gc.h
+iseq.$(OBJEXT): {$(VPATH)}internal/glob.h
+iseq.$(OBJEXT): {$(VPATH)}internal/globals.h
+iseq.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+iseq.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+iseq.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+iseq.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+iseq.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+iseq.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+iseq.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+iseq.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+iseq.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+iseq.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+iseq.$(OBJEXT): {$(VPATH)}internal/iterator.h
+iseq.$(OBJEXT): {$(VPATH)}internal/memory.h
+iseq.$(OBJEXT): {$(VPATH)}internal/method.h
+iseq.$(OBJEXT): {$(VPATH)}internal/module.h
+iseq.$(OBJEXT): {$(VPATH)}internal/newobj.h
+iseq.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+iseq.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+iseq.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+iseq.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+iseq.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+iseq.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+iseq.$(OBJEXT): {$(VPATH)}internal/symbol.h
+iseq.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+iseq.$(OBJEXT): {$(VPATH)}internal/value.h
+iseq.$(OBJEXT): {$(VPATH)}internal/value_type.h
+iseq.$(OBJEXT): {$(VPATH)}internal/variable.h
+iseq.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+iseq.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
iseq.$(OBJEXT): {$(VPATH)}iseq.c
iseq.$(OBJEXT): {$(VPATH)}iseq.h
iseq.$(OBJEXT): {$(VPATH)}method.h
@@ -2242,6 +6963,8 @@ iseq.$(OBJEXT): {$(VPATH)}missing.h
iseq.$(OBJEXT): {$(VPATH)}mjit.h
iseq.$(OBJEXT): {$(VPATH)}node.h
iseq.$(OBJEXT): {$(VPATH)}node_name.inc
+iseq.$(OBJEXT): {$(VPATH)}onigmo.h
+iseq.$(OBJEXT): {$(VPATH)}oniguruma.h
iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h
iseq.$(OBJEXT): {$(VPATH)}ruby_atomic.h
iseq.$(OBJEXT): {$(VPATH)}st.h
@@ -2249,6 +6972,7 @@ iseq.$(OBJEXT): {$(VPATH)}subst.h
iseq.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
iseq.$(OBJEXT): {$(VPATH)}thread_native.h
iseq.$(OBJEXT): {$(VPATH)}util.h
+iseq.$(OBJEXT): {$(VPATH)}vm_callinfo.h
iseq.$(OBJEXT): {$(VPATH)}vm_core.h
iseq.$(OBJEXT): {$(VPATH)}vm_opts.h
load.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
@@ -2257,15 +6981,183 @@ load.$(OBJEXT): $(CCAN_DIR)/list/list.h
load.$(OBJEXT): $(CCAN_DIR)/str/str.h
load.$(OBJEXT): $(hdrdir)/ruby.h
load.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+load.$(OBJEXT): $(top_srcdir)/internal/array.h
+load.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+load.$(OBJEXT): $(top_srcdir)/internal/dir.h
+load.$(OBJEXT): $(top_srcdir)/internal/error.h
+load.$(OBJEXT): $(top_srcdir)/internal/file.h
+load.$(OBJEXT): $(top_srcdir)/internal/gc.h
+load.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+load.$(OBJEXT): $(top_srcdir)/internal/load.h
+load.$(OBJEXT): $(top_srcdir)/internal/parse.h
+load.$(OBJEXT): $(top_srcdir)/internal/serial.h
+load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+load.$(OBJEXT): $(top_srcdir)/internal/string.h
+load.$(OBJEXT): $(top_srcdir)/internal/thread.h
+load.$(OBJEXT): $(top_srcdir)/internal/variable.h
+load.$(OBJEXT): $(top_srcdir)/internal/vm.h
+load.$(OBJEXT): $(top_srcdir)/internal/warnings.h
load.$(OBJEXT): {$(VPATH)}assert.h
+load.$(OBJEXT): {$(VPATH)}atomic.h
+load.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+load.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+load.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+load.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+load.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+load.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+load.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+load.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+load.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
load.$(OBJEXT): {$(VPATH)}config.h
+load.$(OBJEXT): {$(VPATH)}constant.h
load.$(OBJEXT): {$(VPATH)}defines.h
load.$(OBJEXT): {$(VPATH)}dln.h
load.$(OBJEXT): {$(VPATH)}encoding.h
load.$(OBJEXT): {$(VPATH)}eval_intern.h
load.$(OBJEXT): {$(VPATH)}id.h
+load.$(OBJEXT): {$(VPATH)}id_table.h
load.$(OBJEXT): {$(VPATH)}intern.h
load.$(OBJEXT): {$(VPATH)}internal.h
+load.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+load.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+load.$(OBJEXT): {$(VPATH)}internal/assume.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+load.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+load.$(OBJEXT): {$(VPATH)}internal/cast.h
+load.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+load.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+load.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+load.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+load.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+load.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+load.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+load.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+load.$(OBJEXT): {$(VPATH)}internal/config.h
+load.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+load.$(OBJEXT): {$(VPATH)}internal/core.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+load.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+load.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+load.$(OBJEXT): {$(VPATH)}internal/ctype.h
+load.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+load.$(OBJEXT): {$(VPATH)}internal/dosish.h
+load.$(OBJEXT): {$(VPATH)}internal/error.h
+load.$(OBJEXT): {$(VPATH)}internal/eval.h
+load.$(OBJEXT): {$(VPATH)}internal/event.h
+load.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+load.$(OBJEXT): {$(VPATH)}internal/gc.h
+load.$(OBJEXT): {$(VPATH)}internal/glob.h
+load.$(OBJEXT): {$(VPATH)}internal/globals.h
+load.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+load.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+load.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+load.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+load.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+load.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+load.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+load.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+load.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+load.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+load.$(OBJEXT): {$(VPATH)}internal/iterator.h
+load.$(OBJEXT): {$(VPATH)}internal/memory.h
+load.$(OBJEXT): {$(VPATH)}internal/method.h
+load.$(OBJEXT): {$(VPATH)}internal/module.h
+load.$(OBJEXT): {$(VPATH)}internal/newobj.h
+load.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+load.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+load.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+load.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+load.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+load.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+load.$(OBJEXT): {$(VPATH)}internal/symbol.h
+load.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2288,9 +7180,158 @@ 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/gcc_version_since.h
+loadpath.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+loadpath.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+loadpath.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+loadpath.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+loadpath.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
loadpath.$(OBJEXT): {$(VPATH)}config.h
loadpath.$(OBJEXT): {$(VPATH)}defines.h
loadpath.$(OBJEXT): {$(VPATH)}intern.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/assume.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/cast.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/config.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/ctype.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/dosish.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/error.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/eval.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/event.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/gc.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/glob.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/globals.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/iterator.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/memory.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/method.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/module.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/newobj.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/symbol.h
+loadpath.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2299,12 +7340,161 @@ loadpath.$(OBJEXT): {$(VPATH)}verconf.h
localeinit.$(OBJEXT): $(hdrdir)/ruby.h
localeinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
localeinit.$(OBJEXT): {$(VPATH)}assert.h
+localeinit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+localeinit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+localeinit.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+localeinit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+localeinit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+localeinit.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+localeinit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+localeinit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+localeinit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
localeinit.$(OBJEXT): {$(VPATH)}config.h
localeinit.$(OBJEXT): {$(VPATH)}defines.h
localeinit.$(OBJEXT): {$(VPATH)}encindex.h
localeinit.$(OBJEXT): {$(VPATH)}encoding.h
localeinit.$(OBJEXT): {$(VPATH)}intern.h
localeinit.$(OBJEXT): {$(VPATH)}internal.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/assume.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/cast.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/config.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/ctype.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/dosish.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/error.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/eval.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/event.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/gc.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/glob.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/globals.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/iterator.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/memory.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/method.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/module.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/newobj.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/symbol.h
+localeinit.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2315,9 +7505,158 @@ main.$(OBJEXT): $(hdrdir)/ruby.h
main.$(OBJEXT): $(hdrdir)/ruby/ruby.h
main.$(OBJEXT): {$(VPATH)}assert.h
main.$(OBJEXT): {$(VPATH)}backward.h
+main.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+main.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+main.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+main.$(OBJEXT): {$(VPATH)}backward/2/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/anyargs.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+main.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+main.$(OBJEXT): {$(VPATH)}internal/assume.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+main.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+main.$(OBJEXT): {$(VPATH)}internal/cast.h
+main.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+main.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+main.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+main.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+main.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+main.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+main.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+main.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+main.$(OBJEXT): {$(VPATH)}internal/config.h
+main.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+main.$(OBJEXT): {$(VPATH)}internal/core.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+main.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+main.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+main.$(OBJEXT): {$(VPATH)}internal/ctype.h
+main.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+main.$(OBJEXT): {$(VPATH)}internal/dosish.h
+main.$(OBJEXT): {$(VPATH)}internal/error.h
+main.$(OBJEXT): {$(VPATH)}internal/eval.h
+main.$(OBJEXT): {$(VPATH)}internal/event.h
+main.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+main.$(OBJEXT): {$(VPATH)}internal/gc.h
+main.$(OBJEXT): {$(VPATH)}internal/glob.h
+main.$(OBJEXT): {$(VPATH)}internal/globals.h
+main.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+main.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+main.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+main.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+main.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+main.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+main.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+main.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+main.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+main.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+main.$(OBJEXT): {$(VPATH)}internal/iterator.h
+main.$(OBJEXT): {$(VPATH)}internal/memory.h
+main.$(OBJEXT): {$(VPATH)}internal/method.h
+main.$(OBJEXT): {$(VPATH)}internal/module.h
+main.$(OBJEXT): {$(VPATH)}internal/newobj.h
+main.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+main.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+main.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+main.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+main.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+main.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+main.$(OBJEXT): {$(VPATH)}internal/symbol.h
+main.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+main.$(OBJEXT): {$(VPATH)}internal/value.h
+main.$(OBJEXT): {$(VPATH)}internal/value_type.h
+main.$(OBJEXT): {$(VPATH)}internal/variable.h
+main.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+main.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
main.$(OBJEXT): {$(VPATH)}main.c
main.$(OBJEXT): {$(VPATH)}missing.h
main.$(OBJEXT): {$(VPATH)}node.h
@@ -2326,7 +7665,32 @@ main.$(OBJEXT): {$(VPATH)}subst.h
main.$(OBJEXT): {$(VPATH)}vm_debug.h
marshal.$(OBJEXT): $(hdrdir)/ruby.h
marshal.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/array.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/class.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/error.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/gc.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/object.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/string.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/struct.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/util.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/vm.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
marshal.$(OBJEXT): {$(VPATH)}assert.h
+marshal.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+marshal.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+marshal.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+marshal.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+marshal.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+marshal.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+marshal.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+marshal.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+marshal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
marshal.$(OBJEXT): {$(VPATH)}config.h
marshal.$(OBJEXT): {$(VPATH)}defines.h
marshal.$(OBJEXT): {$(VPATH)}encindex.h
@@ -2334,6 +7698,146 @@ marshal.$(OBJEXT): {$(VPATH)}encoding.h
marshal.$(OBJEXT): {$(VPATH)}id_table.h
marshal.$(OBJEXT): {$(VPATH)}intern.h
marshal.$(OBJEXT): {$(VPATH)}internal.h
+marshal.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+marshal.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+marshal.$(OBJEXT): {$(VPATH)}internal/assume.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+marshal.$(OBJEXT): {$(VPATH)}internal/cast.h
+marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+marshal.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+marshal.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+marshal.$(OBJEXT): {$(VPATH)}internal/config.h
+marshal.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+marshal.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+marshal.$(OBJEXT): {$(VPATH)}internal/ctype.h
+marshal.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+marshal.$(OBJEXT): {$(VPATH)}internal/dosish.h
+marshal.$(OBJEXT): {$(VPATH)}internal/error.h
+marshal.$(OBJEXT): {$(VPATH)}internal/eval.h
+marshal.$(OBJEXT): {$(VPATH)}internal/event.h
+marshal.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+marshal.$(OBJEXT): {$(VPATH)}internal/gc.h
+marshal.$(OBJEXT): {$(VPATH)}internal/glob.h
+marshal.$(OBJEXT): {$(VPATH)}internal/globals.h
+marshal.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+marshal.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+marshal.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+marshal.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+marshal.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+marshal.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+marshal.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+marshal.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+marshal.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+marshal.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+marshal.$(OBJEXT): {$(VPATH)}internal/iterator.h
+marshal.$(OBJEXT): {$(VPATH)}internal/memory.h
+marshal.$(OBJEXT): {$(VPATH)}internal/method.h
+marshal.$(OBJEXT): {$(VPATH)}internal/module.h
+marshal.$(OBJEXT): {$(VPATH)}internal/newobj.h
+marshal.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+marshal.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+marshal.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+marshal.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+marshal.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+marshal.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+marshal.$(OBJEXT): {$(VPATH)}internal/symbol.h
+marshal.$(OBJEXT): {$(VPATH)}internal/token_paste.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)}missing.h
@@ -2344,34 +7848,526 @@ marshal.$(OBJEXT): {$(VPATH)}subst.h
marshal.$(OBJEXT): {$(VPATH)}util.h
math.$(OBJEXT): $(hdrdir)/ruby.h
math.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+math.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+math.$(OBJEXT): $(top_srcdir)/internal/class.h
+math.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+math.$(OBJEXT): $(top_srcdir)/internal/complex.h
+math.$(OBJEXT): $(top_srcdir)/internal/gc.h
+math.$(OBJEXT): $(top_srcdir)/internal/math.h
+math.$(OBJEXT): $(top_srcdir)/internal/object.h
+math.$(OBJEXT): $(top_srcdir)/internal/serial.h
+math.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+math.$(OBJEXT): $(top_srcdir)/internal/vm.h
+math.$(OBJEXT): $(top_srcdir)/internal/warnings.h
math.$(OBJEXT): {$(VPATH)}assert.h
+math.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+math.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+math.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+math.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+math.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+math.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+math.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+math.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+math.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
math.$(OBJEXT): {$(VPATH)}config.h
math.$(OBJEXT): {$(VPATH)}defines.h
+math.$(OBJEXT): {$(VPATH)}id_table.h
math.$(OBJEXT): {$(VPATH)}intern.h
math.$(OBJEXT): {$(VPATH)}internal.h
+math.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+math.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+math.$(OBJEXT): {$(VPATH)}internal/assume.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+math.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+math.$(OBJEXT): {$(VPATH)}internal/cast.h
+math.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+math.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+math.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+math.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+math.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+math.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+math.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+math.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+math.$(OBJEXT): {$(VPATH)}internal/config.h
+math.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+math.$(OBJEXT): {$(VPATH)}internal/core.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+math.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+math.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+math.$(OBJEXT): {$(VPATH)}internal/ctype.h
+math.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+math.$(OBJEXT): {$(VPATH)}internal/dosish.h
+math.$(OBJEXT): {$(VPATH)}internal/error.h
+math.$(OBJEXT): {$(VPATH)}internal/eval.h
+math.$(OBJEXT): {$(VPATH)}internal/event.h
+math.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+math.$(OBJEXT): {$(VPATH)}internal/gc.h
+math.$(OBJEXT): {$(VPATH)}internal/glob.h
+math.$(OBJEXT): {$(VPATH)}internal/globals.h
+math.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+math.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+math.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+math.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+math.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+math.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+math.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+math.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+math.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+math.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+math.$(OBJEXT): {$(VPATH)}internal/iterator.h
+math.$(OBJEXT): {$(VPATH)}internal/memory.h
+math.$(OBJEXT): {$(VPATH)}internal/method.h
+math.$(OBJEXT): {$(VPATH)}internal/module.h
+math.$(OBJEXT): {$(VPATH)}internal/newobj.h
+math.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+math.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+math.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+math.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+math.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+math.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+math.$(OBJEXT): {$(VPATH)}internal/symbol.h
+math.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+math.$(OBJEXT): {$(VPATH)}internal/value.h
+math.$(OBJEXT): {$(VPATH)}internal/value_type.h
+math.$(OBJEXT): {$(VPATH)}internal/variable.h
+math.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+math.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
math.$(OBJEXT): {$(VPATH)}math.c
math.$(OBJEXT): {$(VPATH)}missing.h
math.$(OBJEXT): {$(VPATH)}st.h
math.$(OBJEXT): {$(VPATH)}subst.h
+memory_view.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/util.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h
+memory_view.$(OBJEXT): {$(VPATH)}assert.h
+memory_view.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+memory_view.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+memory_view.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+memory_view.$(OBJEXT): {$(VPATH)}backward/2/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)}id_table.h
+memory_view.$(OBJEXT): {$(VPATH)}intern.h
+memory_view.$(OBJEXT): {$(VPATH)}internal.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/assume.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/cast.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/config.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/ctype.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/dosish.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/error.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/eval.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/event.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/gc.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/glob.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/globals.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/iterator.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/memory.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/method.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/module.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/newobj.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/symbol.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/value.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/value_type.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/variable.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+memory_view.$(OBJEXT): {$(VPATH)}memory_view.c
+memory_view.$(OBJEXT): {$(VPATH)}memory_view.h
+memory_view.$(OBJEXT): {$(VPATH)}missing.h
+memory_view.$(OBJEXT): {$(VPATH)}node.h
+memory_view.$(OBJEXT): {$(VPATH)}st.h
+memory_view.$(OBJEXT): {$(VPATH)}subst.h
+memory_view.$(OBJEXT): {$(VPATH)}vm_debug.h
+memory_view.$(OBJEXT): {$(VPATH)}vm_sync.h
miniinit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
miniinit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
miniinit.$(OBJEXT): $(CCAN_DIR)/list/list.h
miniinit.$(OBJEXT): $(CCAN_DIR)/str/str.h
miniinit.$(OBJEXT): $(hdrdir)/ruby.h
miniinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/array.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/gc.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+miniinit.$(OBJEXT): {$(VPATH)}array.rb
miniinit.$(OBJEXT): {$(VPATH)}assert.h
miniinit.$(OBJEXT): {$(VPATH)}ast.rb
+miniinit.$(OBJEXT): {$(VPATH)}atomic.h
+miniinit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+miniinit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+miniinit.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+miniinit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+miniinit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+miniinit.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+miniinit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+miniinit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
miniinit.$(OBJEXT): {$(VPATH)}builtin.h
miniinit.$(OBJEXT): {$(VPATH)}config.h
miniinit.$(OBJEXT): {$(VPATH)}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)}integer.rb
miniinit.$(OBJEXT): {$(VPATH)}intern.h
miniinit.$(OBJEXT): {$(VPATH)}internal.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/assume.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/cast.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/config.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/ctype.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/dosish.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/error.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/eval.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/event.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/gc.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/glob.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/globals.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/iterator.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/memory.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/method.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/module.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/newobj.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/symbol.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/token_paste.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)}method.h
miniinit.$(OBJEXT): {$(VPATH)}mini_builtin.c
miniinit.$(OBJEXT): {$(VPATH)}miniinit.c
@@ -2382,6 +8378,7 @@ miniinit.$(OBJEXT): {$(VPATH)}onigmo.h
miniinit.$(OBJEXT): {$(VPATH)}oniguruma.h
miniinit.$(OBJEXT): {$(VPATH)}pack.rb
miniinit.$(OBJEXT): {$(VPATH)}prelude.rb
+miniinit.$(OBJEXT): {$(VPATH)}ractor.rb
miniinit.$(OBJEXT): {$(VPATH)}ruby_assert.h
miniinit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
miniinit.$(OBJEXT): {$(VPATH)}st.h
@@ -2392,24 +8389,226 @@ miniinit.$(OBJEXT): {$(VPATH)}trace_point.rb
miniinit.$(OBJEXT): {$(VPATH)}vm_core.h
miniinit.$(OBJEXT): {$(VPATH)}vm_opts.h
miniinit.$(OBJEXT): {$(VPATH)}warning.rb
+miniprelude.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+miniprelude.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+miniprelude.$(OBJEXT): $(CCAN_DIR)/list/list.h
+miniprelude.$(OBJEXT): $(CCAN_DIR)/str/str.h
+miniprelude.$(OBJEXT): $(hdrdir)/ruby.h
+miniprelude.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+miniprelude.$(OBJEXT): {$(VPATH)}assert.h
+miniprelude.$(OBJEXT): {$(VPATH)}ast.rb
+miniprelude.$(OBJEXT): {$(VPATH)}atomic.h
+miniprelude.$(OBJEXT): {$(VPATH)}config.h
+miniprelude.$(OBJEXT): {$(VPATH)}defines.h
+miniprelude.$(OBJEXT): {$(VPATH)}gc.rb
+miniprelude.$(OBJEXT): {$(VPATH)}id.h
+miniprelude.$(OBJEXT): {$(VPATH)}intern.h
+miniprelude.$(OBJEXT): {$(VPATH)}internal.h
+miniprelude.$(OBJEXT): {$(VPATH)}io.rb
+miniprelude.$(OBJEXT): {$(VPATH)}iseq.h
+miniprelude.$(OBJEXT): {$(VPATH)}method.h
+miniprelude.$(OBJEXT): {$(VPATH)}miniprelude.c
+miniprelude.$(OBJEXT): {$(VPATH)}missing.h
+miniprelude.$(OBJEXT): {$(VPATH)}node.h
+miniprelude.$(OBJEXT): {$(VPATH)}pack.rb
+miniprelude.$(OBJEXT): {$(VPATH)}prelude.rb
+miniprelude.$(OBJEXT): {$(VPATH)}ruby_assert.h
+miniprelude.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+miniprelude.$(OBJEXT): {$(VPATH)}st.h
+miniprelude.$(OBJEXT): {$(VPATH)}subst.h
+miniprelude.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+miniprelude.$(OBJEXT): {$(VPATH)}thread_native.h
+miniprelude.$(OBJEXT): {$(VPATH)}trace_point.rb
+miniprelude.$(OBJEXT): {$(VPATH)}vm_core.h
+miniprelude.$(OBJEXT): {$(VPATH)}vm_opts.h
mjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
mjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
mjit.$(OBJEXT): $(CCAN_DIR)/list/list.h
mjit.$(OBJEXT): $(CCAN_DIR)/str/str.h
mjit.$(OBJEXT): $(hdrdir)/ruby.h
mjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+mjit.$(OBJEXT): $(hdrdir)/ruby/version.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/array.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/class.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/compile.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/cont.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/file.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/gc.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
+mjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
mjit.$(OBJEXT): {$(VPATH)}assert.h
+mjit.$(OBJEXT): {$(VPATH)}atomic.h
+mjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+mjit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+mjit.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+mjit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+mjit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+mjit.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+mjit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+mjit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+mjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+mjit.$(OBJEXT): {$(VPATH)}builtin.h
mjit.$(OBJEXT): {$(VPATH)}config.h
mjit.$(OBJEXT): {$(VPATH)}constant.h
mjit.$(OBJEXT): {$(VPATH)}debug.h
mjit.$(OBJEXT): {$(VPATH)}debug_counter.h
mjit.$(OBJEXT): {$(VPATH)}defines.h
mjit.$(OBJEXT): {$(VPATH)}dln.h
+mjit.$(OBJEXT): {$(VPATH)}encoding.h
mjit.$(OBJEXT): {$(VPATH)}gc.h
mjit.$(OBJEXT): {$(VPATH)}id.h
mjit.$(OBJEXT): {$(VPATH)}id_table.h
+mjit.$(OBJEXT): {$(VPATH)}insns.def
+mjit.$(OBJEXT): {$(VPATH)}insns.inc
+mjit.$(OBJEXT): {$(VPATH)}insns_info.inc
mjit.$(OBJEXT): {$(VPATH)}intern.h
mjit.$(OBJEXT): {$(VPATH)}internal.h
+mjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+mjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+mjit.$(OBJEXT): {$(VPATH)}internal/assume.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+mjit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+mjit.$(OBJEXT): {$(VPATH)}internal/cast.h
+mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+mjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+mjit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+mjit.$(OBJEXT): {$(VPATH)}internal/config.h
+mjit.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+mjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+mjit.$(OBJEXT): {$(VPATH)}internal/ctype.h
+mjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+mjit.$(OBJEXT): {$(VPATH)}internal/dosish.h
+mjit.$(OBJEXT): {$(VPATH)}internal/error.h
+mjit.$(OBJEXT): {$(VPATH)}internal/eval.h
+mjit.$(OBJEXT): {$(VPATH)}internal/event.h
+mjit.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+mjit.$(OBJEXT): {$(VPATH)}internal/gc.h
+mjit.$(OBJEXT): {$(VPATH)}internal/glob.h
+mjit.$(OBJEXT): {$(VPATH)}internal/globals.h
+mjit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+mjit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+mjit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+mjit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+mjit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+mjit.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+mjit.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+mjit.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+mjit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+mjit.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+mjit.$(OBJEXT): {$(VPATH)}internal/iterator.h
+mjit.$(OBJEXT): {$(VPATH)}internal/memory.h
+mjit.$(OBJEXT): {$(VPATH)}internal/method.h
+mjit.$(OBJEXT): {$(VPATH)}internal/module.h
+mjit.$(OBJEXT): {$(VPATH)}internal/newobj.h
+mjit.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+mjit.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+mjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+mjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+mjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+mjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+mjit.$(OBJEXT): {$(VPATH)}internal/symbol.h
+mjit.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+mjit.$(OBJEXT): {$(VPATH)}internal/value.h
+mjit.$(OBJEXT): {$(VPATH)}internal/value_type.h
+mjit.$(OBJEXT): {$(VPATH)}internal/variable.h
+mjit.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+mjit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+mjit.$(OBJEXT): {$(VPATH)}iseq.h
mjit.$(OBJEXT): {$(VPATH)}method.h
mjit.$(OBJEXT): {$(VPATH)}missing.h
mjit.$(OBJEXT): {$(VPATH)}mjit.c
@@ -2417,6 +8616,8 @@ mjit.$(OBJEXT): {$(VPATH)}mjit.h
mjit.$(OBJEXT): {$(VPATH)}mjit_config.h
mjit.$(OBJEXT): {$(VPATH)}mjit_worker.c
mjit.$(OBJEXT): {$(VPATH)}node.h
+mjit.$(OBJEXT): {$(VPATH)}onigmo.h
+mjit.$(OBJEXT): {$(VPATH)}oniguruma.h
mjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
mjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
mjit.$(OBJEXT): {$(VPATH)}st.h
@@ -2425,25 +8626,203 @@ mjit.$(OBJEXT): {$(VPATH)}thread.h
mjit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
mjit.$(OBJEXT): {$(VPATH)}thread_native.h
mjit.$(OBJEXT): {$(VPATH)}util.h
+mjit.$(OBJEXT): {$(VPATH)}vm_callinfo.h
mjit.$(OBJEXT): {$(VPATH)}vm_core.h
mjit.$(OBJEXT): {$(VPATH)}vm_opts.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}config.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}internal/config.h
+mjit_build_dir.$(OBJEXT): {$(VPATH)}ruby-runner.c
+mjit_build_dir.$(OBJEXT): {$(VPATH)}ruby-runner.h
mjit_compile.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
mjit_compile.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
mjit_compile.$(OBJEXT): $(CCAN_DIR)/list/list.h
mjit_compile.$(OBJEXT): $(CCAN_DIR)/str/str.h
mjit_compile.$(OBJEXT): $(hdrdir)/ruby.h
mjit_compile.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/array.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/class.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/compile.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/gc.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/hash.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/object.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/variable.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/vm.h
+mjit_compile.$(OBJEXT): $(top_srcdir)/internal/warnings.h
mjit_compile.$(OBJEXT): {$(VPATH)}assert.h
+mjit_compile.$(OBJEXT): {$(VPATH)}atomic.h
+mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+mjit_compile.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
mjit_compile.$(OBJEXT): {$(VPATH)}builtin.h
mjit_compile.$(OBJEXT): {$(VPATH)}config.h
+mjit_compile.$(OBJEXT): {$(VPATH)}constant.h
mjit_compile.$(OBJEXT): {$(VPATH)}debug_counter.h
mjit_compile.$(OBJEXT): {$(VPATH)}defines.h
mjit_compile.$(OBJEXT): {$(VPATH)}id.h
+mjit_compile.$(OBJEXT): {$(VPATH)}id_table.h
mjit_compile.$(OBJEXT): {$(VPATH)}insns.def
mjit_compile.$(OBJEXT): {$(VPATH)}insns.inc
mjit_compile.$(OBJEXT): {$(VPATH)}insns_info.inc
mjit_compile.$(OBJEXT): {$(VPATH)}intern.h
mjit_compile.$(OBJEXT): {$(VPATH)}internal.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/assume.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/cast.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/config.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/ctype.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/dosish.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/error.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/eval.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/event.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/gc.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/glob.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/globals.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/iterator.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/memory.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/method.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/module.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/newobj.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/symbol.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/value.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/value_type.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/variable.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+mjit_compile.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
mjit_compile.$(OBJEXT): {$(VPATH)}iseq.h
mjit_compile.$(OBJEXT): {$(VPATH)}method.h
mjit_compile.$(OBJEXT): {$(VPATH)}missing.h
@@ -2457,6 +8836,7 @@ mjit_compile.$(OBJEXT): {$(VPATH)}st.h
mjit_compile.$(OBJEXT): {$(VPATH)}subst.h
mjit_compile.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
mjit_compile.$(OBJEXT): {$(VPATH)}thread_native.h
+mjit_compile.$(OBJEXT): {$(VPATH)}vm_callinfo.h
mjit_compile.$(OBJEXT): {$(VPATH)}vm_core.h
mjit_compile.$(OBJEXT): {$(VPATH)}vm_exec.h
mjit_compile.$(OBJEXT): {$(VPATH)}vm_insnhelper.h
@@ -2467,12 +8847,174 @@ node.$(OBJEXT): $(CCAN_DIR)/list/list.h
node.$(OBJEXT): $(CCAN_DIR)/str/str.h
node.$(OBJEXT): $(hdrdir)/ruby.h
node.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+node.$(OBJEXT): $(top_srcdir)/internal/array.h
+node.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+node.$(OBJEXT): $(top_srcdir)/internal/gc.h
+node.$(OBJEXT): $(top_srcdir)/internal/hash.h
+node.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+node.$(OBJEXT): $(top_srcdir)/internal/serial.h
+node.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+node.$(OBJEXT): $(top_srcdir)/internal/variable.h
+node.$(OBJEXT): $(top_srcdir)/internal/vm.h
+node.$(OBJEXT): $(top_srcdir)/internal/warnings.h
node.$(OBJEXT): {$(VPATH)}assert.h
+node.$(OBJEXT): {$(VPATH)}atomic.h
+node.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+node.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+node.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+node.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+node.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+node.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+node.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+node.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+node.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
node.$(OBJEXT): {$(VPATH)}config.h
+node.$(OBJEXT): {$(VPATH)}constant.h
node.$(OBJEXT): {$(VPATH)}defines.h
node.$(OBJEXT): {$(VPATH)}id.h
+node.$(OBJEXT): {$(VPATH)}id_table.h
node.$(OBJEXT): {$(VPATH)}intern.h
node.$(OBJEXT): {$(VPATH)}internal.h
+node.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+node.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+node.$(OBJEXT): {$(VPATH)}internal/assume.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+node.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+node.$(OBJEXT): {$(VPATH)}internal/cast.h
+node.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+node.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+node.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+node.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+node.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+node.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+node.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+node.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+node.$(OBJEXT): {$(VPATH)}internal/config.h
+node.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+node.$(OBJEXT): {$(VPATH)}internal/core.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+node.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+node.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+node.$(OBJEXT): {$(VPATH)}internal/ctype.h
+node.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+node.$(OBJEXT): {$(VPATH)}internal/dosish.h
+node.$(OBJEXT): {$(VPATH)}internal/error.h
+node.$(OBJEXT): {$(VPATH)}internal/eval.h
+node.$(OBJEXT): {$(VPATH)}internal/event.h
+node.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+node.$(OBJEXT): {$(VPATH)}internal/gc.h
+node.$(OBJEXT): {$(VPATH)}internal/glob.h
+node.$(OBJEXT): {$(VPATH)}internal/globals.h
+node.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+node.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+node.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+node.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+node.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+node.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+node.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+node.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+node.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+node.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+node.$(OBJEXT): {$(VPATH)}internal/iterator.h
+node.$(OBJEXT): {$(VPATH)}internal/memory.h
+node.$(OBJEXT): {$(VPATH)}internal/method.h
+node.$(OBJEXT): {$(VPATH)}internal/module.h
+node.$(OBJEXT): {$(VPATH)}internal/newobj.h
+node.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+node.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+node.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+node.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+node.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+node.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+node.$(OBJEXT): {$(VPATH)}internal/symbol.h
+node.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2487,30 +9029,377 @@ node.$(OBJEXT): {$(VPATH)}vm_core.h
node.$(OBJEXT): {$(VPATH)}vm_opts.h
numeric.$(OBJEXT): $(hdrdir)/ruby.h
numeric.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/array.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/bits.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/class.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/complex.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/enumerator.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/gc.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/hash.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/object.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/util.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/variable.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/vm.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/warnings.h
numeric.$(OBJEXT): {$(VPATH)}assert.h
+numeric.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+numeric.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+numeric.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+numeric.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+numeric.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+numeric.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+numeric.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+numeric.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+numeric.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+numeric.$(OBJEXT): {$(VPATH)}builtin.h
numeric.$(OBJEXT): {$(VPATH)}config.h
+numeric.$(OBJEXT): {$(VPATH)}constant.h
numeric.$(OBJEXT): {$(VPATH)}defines.h
numeric.$(OBJEXT): {$(VPATH)}encoding.h
numeric.$(OBJEXT): {$(VPATH)}id.h
+numeric.$(OBJEXT): {$(VPATH)}id_table.h
+numeric.$(OBJEXT): {$(VPATH)}integer.rb
+numeric.$(OBJEXT): {$(VPATH)}integer.rbinc
numeric.$(OBJEXT): {$(VPATH)}intern.h
numeric.$(OBJEXT): {$(VPATH)}internal.h
+numeric.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+numeric.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+numeric.$(OBJEXT): {$(VPATH)}internal/assume.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+numeric.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+numeric.$(OBJEXT): {$(VPATH)}internal/cast.h
+numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+numeric.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+numeric.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+numeric.$(OBJEXT): {$(VPATH)}internal/config.h
+numeric.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+numeric.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+numeric.$(OBJEXT): {$(VPATH)}internal/ctype.h
+numeric.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+numeric.$(OBJEXT): {$(VPATH)}internal/dosish.h
+numeric.$(OBJEXT): {$(VPATH)}internal/error.h
+numeric.$(OBJEXT): {$(VPATH)}internal/eval.h
+numeric.$(OBJEXT): {$(VPATH)}internal/event.h
+numeric.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+numeric.$(OBJEXT): {$(VPATH)}internal/gc.h
+numeric.$(OBJEXT): {$(VPATH)}internal/glob.h
+numeric.$(OBJEXT): {$(VPATH)}internal/globals.h
+numeric.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+numeric.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+numeric.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+numeric.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+numeric.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+numeric.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+numeric.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+numeric.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+numeric.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+numeric.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+numeric.$(OBJEXT): {$(VPATH)}internal/iterator.h
+numeric.$(OBJEXT): {$(VPATH)}internal/memory.h
+numeric.$(OBJEXT): {$(VPATH)}internal/method.h
+numeric.$(OBJEXT): {$(VPATH)}internal/module.h
+numeric.$(OBJEXT): {$(VPATH)}internal/newobj.h
+numeric.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+numeric.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+numeric.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+numeric.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+numeric.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+numeric.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+numeric.$(OBJEXT): {$(VPATH)}internal/symbol.h
+numeric.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+numeric.$(OBJEXT): {$(VPATH)}internal/value.h
+numeric.$(OBJEXT): {$(VPATH)}internal/value_type.h
+numeric.$(OBJEXT): {$(VPATH)}internal/variable.h
+numeric.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+numeric.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
numeric.$(OBJEXT): {$(VPATH)}missing.h
numeric.$(OBJEXT): {$(VPATH)}numeric.c
numeric.$(OBJEXT): {$(VPATH)}onigmo.h
numeric.$(OBJEXT): {$(VPATH)}oniguruma.h
+numeric.$(OBJEXT): {$(VPATH)}ruby_assert.h
numeric.$(OBJEXT): {$(VPATH)}st.h
numeric.$(OBJEXT): {$(VPATH)}subst.h
numeric.$(OBJEXT): {$(VPATH)}util.h
object.$(OBJEXT): $(hdrdir)/ruby.h
object.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+object.$(OBJEXT): $(top_srcdir)/internal/array.h
+object.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+object.$(OBJEXT): $(top_srcdir)/internal/bits.h
+object.$(OBJEXT): $(top_srcdir)/internal/class.h
+object.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+object.$(OBJEXT): $(top_srcdir)/internal/error.h
+object.$(OBJEXT): $(top_srcdir)/internal/eval.h
+object.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+object.$(OBJEXT): $(top_srcdir)/internal/gc.h
+object.$(OBJEXT): $(top_srcdir)/internal/inits.h
+object.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+object.$(OBJEXT): $(top_srcdir)/internal/object.h
+object.$(OBJEXT): $(top_srcdir)/internal/serial.h
+object.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+object.$(OBJEXT): $(top_srcdir)/internal/string.h
+object.$(OBJEXT): $(top_srcdir)/internal/struct.h
+object.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+object.$(OBJEXT): $(top_srcdir)/internal/variable.h
+object.$(OBJEXT): $(top_srcdir)/internal/vm.h
+object.$(OBJEXT): $(top_srcdir)/internal/warnings.h
object.$(OBJEXT): {$(VPATH)}assert.h
+object.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+object.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+object.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+object.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+object.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+object.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+object.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+object.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+object.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+object.$(OBJEXT): {$(VPATH)}builtin.h
object.$(OBJEXT): {$(VPATH)}config.h
object.$(OBJEXT): {$(VPATH)}constant.h
object.$(OBJEXT): {$(VPATH)}defines.h
object.$(OBJEXT): {$(VPATH)}encoding.h
object.$(OBJEXT): {$(VPATH)}id.h
+object.$(OBJEXT): {$(VPATH)}id_table.h
object.$(OBJEXT): {$(VPATH)}intern.h
object.$(OBJEXT): {$(VPATH)}internal.h
+object.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+object.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+object.$(OBJEXT): {$(VPATH)}internal/assume.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+object.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+object.$(OBJEXT): {$(VPATH)}internal/cast.h
+object.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+object.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+object.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+object.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+object.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+object.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+object.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+object.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+object.$(OBJEXT): {$(VPATH)}internal/config.h
+object.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+object.$(OBJEXT): {$(VPATH)}internal/core.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+object.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+object.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+object.$(OBJEXT): {$(VPATH)}internal/ctype.h
+object.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+object.$(OBJEXT): {$(VPATH)}internal/dosish.h
+object.$(OBJEXT): {$(VPATH)}internal/error.h
+object.$(OBJEXT): {$(VPATH)}internal/eval.h
+object.$(OBJEXT): {$(VPATH)}internal/event.h
+object.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+object.$(OBJEXT): {$(VPATH)}internal/gc.h
+object.$(OBJEXT): {$(VPATH)}internal/glob.h
+object.$(OBJEXT): {$(VPATH)}internal/globals.h
+object.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+object.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+object.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+object.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+object.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+object.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+object.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+object.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+object.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+object.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+object.$(OBJEXT): {$(VPATH)}internal/iterator.h
+object.$(OBJEXT): {$(VPATH)}internal/memory.h
+object.$(OBJEXT): {$(VPATH)}internal/method.h
+object.$(OBJEXT): {$(VPATH)}internal/module.h
+object.$(OBJEXT): {$(VPATH)}internal/newobj.h
+object.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+object.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+object.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+object.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+object.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+object.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+object.$(OBJEXT): {$(VPATH)}internal/symbol.h
+object.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+object.$(OBJEXT): {$(VPATH)}internal/value.h
+object.$(OBJEXT): {$(VPATH)}internal/value_type.h
+object.$(OBJEXT): {$(VPATH)}internal/variable.h
+object.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+object.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+object.$(OBJEXT): {$(VPATH)}kernel.rb
+object.$(OBJEXT): {$(VPATH)}kernel.rbinc
object.$(OBJEXT): {$(VPATH)}missing.h
object.$(OBJEXT): {$(VPATH)}object.c
object.$(OBJEXT): {$(VPATH)}onigmo.h
@@ -2522,13 +9411,173 @@ object.$(OBJEXT): {$(VPATH)}subst.h
object.$(OBJEXT): {$(VPATH)}util.h
pack.$(OBJEXT): $(hdrdir)/ruby.h
pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+pack.$(OBJEXT): $(top_srcdir)/internal/array.h
+pack.$(OBJEXT): $(top_srcdir)/internal/bits.h
+pack.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+pack.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+pack.$(OBJEXT): $(top_srcdir)/internal/string.h
+pack.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+pack.$(OBJEXT): $(top_srcdir)/internal/util.h
+pack.$(OBJEXT): $(top_srcdir)/internal/variable.h
+pack.$(OBJEXT): $(top_srcdir)/internal/warnings.h
pack.$(OBJEXT): {$(VPATH)}assert.h
+pack.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+pack.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+pack.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+pack.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+pack.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+pack.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+pack.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+pack.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+pack.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
pack.$(OBJEXT): {$(VPATH)}builtin.h
pack.$(OBJEXT): {$(VPATH)}config.h
+pack.$(OBJEXT): {$(VPATH)}constant.h
pack.$(OBJEXT): {$(VPATH)}defines.h
pack.$(OBJEXT): {$(VPATH)}encoding.h
+pack.$(OBJEXT): {$(VPATH)}id_table.h
pack.$(OBJEXT): {$(VPATH)}intern.h
pack.$(OBJEXT): {$(VPATH)}internal.h
+pack.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+pack.$(OBJEXT): {$(VPATH)}internal/assume.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+pack.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+pack.$(OBJEXT): {$(VPATH)}internal/cast.h
+pack.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+pack.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+pack.$(OBJEXT): {$(VPATH)}internal/config.h
+pack.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+pack.$(OBJEXT): {$(VPATH)}internal/core.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+pack.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+pack.$(OBJEXT): {$(VPATH)}internal/ctype.h
+pack.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+pack.$(OBJEXT): {$(VPATH)}internal/dosish.h
+pack.$(OBJEXT): {$(VPATH)}internal/error.h
+pack.$(OBJEXT): {$(VPATH)}internal/eval.h
+pack.$(OBJEXT): {$(VPATH)}internal/event.h
+pack.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+pack.$(OBJEXT): {$(VPATH)}internal/gc.h
+pack.$(OBJEXT): {$(VPATH)}internal/glob.h
+pack.$(OBJEXT): {$(VPATH)}internal/globals.h
+pack.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+pack.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+pack.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+pack.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+pack.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+pack.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+pack.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+pack.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+pack.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+pack.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+pack.$(OBJEXT): {$(VPATH)}internal/iterator.h
+pack.$(OBJEXT): {$(VPATH)}internal/memory.h
+pack.$(OBJEXT): {$(VPATH)}internal/method.h
+pack.$(OBJEXT): {$(VPATH)}internal/module.h
+pack.$(OBJEXT): {$(VPATH)}internal/newobj.h
+pack.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+pack.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+pack.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+pack.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+pack.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+pack.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+pack.$(OBJEXT): {$(VPATH)}internal/symbol.h
+pack.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+pack.$(OBJEXT): {$(VPATH)}internal/value.h
+pack.$(OBJEXT): {$(VPATH)}internal/value_type.h
+pack.$(OBJEXT): {$(VPATH)}internal/variable.h
+pack.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+pack.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
pack.$(OBJEXT): {$(VPATH)}missing.h
pack.$(OBJEXT): {$(VPATH)}onigmo.h
pack.$(OBJEXT): {$(VPATH)}oniguruma.h
@@ -2538,14 +9587,191 @@ pack.$(OBJEXT): {$(VPATH)}st.h
pack.$(OBJEXT): {$(VPATH)}subst.h
parse.$(OBJEXT): $(hdrdir)/ruby.h
parse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+parse.$(OBJEXT): $(top_srcdir)/internal/array.h
+parse.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+parse.$(OBJEXT): $(top_srcdir)/internal/bits.h
+parse.$(OBJEXT): $(top_srcdir)/internal/compile.h
+parse.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+parse.$(OBJEXT): $(top_srcdir)/internal/complex.h
+parse.$(OBJEXT): $(top_srcdir)/internal/error.h
+parse.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+parse.$(OBJEXT): $(top_srcdir)/internal/gc.h
+parse.$(OBJEXT): $(top_srcdir)/internal/hash.h
+parse.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+parse.$(OBJEXT): $(top_srcdir)/internal/io.h
+parse.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+parse.$(OBJEXT): $(top_srcdir)/internal/parse.h
+parse.$(OBJEXT): $(top_srcdir)/internal/rational.h
+parse.$(OBJEXT): $(top_srcdir)/internal/re.h
+parse.$(OBJEXT): $(top_srcdir)/internal/serial.h
+parse.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+parse.$(OBJEXT): $(top_srcdir)/internal/string.h
+parse.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+parse.$(OBJEXT): $(top_srcdir)/internal/thread.h
+parse.$(OBJEXT): $(top_srcdir)/internal/util.h
+parse.$(OBJEXT): $(top_srcdir)/internal/variable.h
+parse.$(OBJEXT): $(top_srcdir)/internal/vm.h
+parse.$(OBJEXT): $(top_srcdir)/internal/warnings.h
parse.$(OBJEXT): {$(VPATH)}assert.h
+parse.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+parse.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+parse.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+parse.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+parse.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+parse.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+parse.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+parse.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+parse.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
parse.$(OBJEXT): {$(VPATH)}config.h
+parse.$(OBJEXT): {$(VPATH)}constant.h
parse.$(OBJEXT): {$(VPATH)}defines.h
parse.$(OBJEXT): {$(VPATH)}defs/keywords
parse.$(OBJEXT): {$(VPATH)}encoding.h
parse.$(OBJEXT): {$(VPATH)}id.h
+parse.$(OBJEXT): {$(VPATH)}id_table.h
parse.$(OBJEXT): {$(VPATH)}intern.h
parse.$(OBJEXT): {$(VPATH)}internal.h
+parse.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+parse.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+parse.$(OBJEXT): {$(VPATH)}internal/assume.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+parse.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+parse.$(OBJEXT): {$(VPATH)}internal/cast.h
+parse.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+parse.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+parse.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+parse.$(OBJEXT): {$(VPATH)}internal/config.h
+parse.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+parse.$(OBJEXT): {$(VPATH)}internal/core.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+parse.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+parse.$(OBJEXT): {$(VPATH)}internal/ctype.h
+parse.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+parse.$(OBJEXT): {$(VPATH)}internal/dosish.h
+parse.$(OBJEXT): {$(VPATH)}internal/error.h
+parse.$(OBJEXT): {$(VPATH)}internal/eval.h
+parse.$(OBJEXT): {$(VPATH)}internal/event.h
+parse.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+parse.$(OBJEXT): {$(VPATH)}internal/gc.h
+parse.$(OBJEXT): {$(VPATH)}internal/glob.h
+parse.$(OBJEXT): {$(VPATH)}internal/globals.h
+parse.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+parse.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+parse.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+parse.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+parse.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+parse.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+parse.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+parse.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+parse.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+parse.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+parse.$(OBJEXT): {$(VPATH)}internal/iterator.h
+parse.$(OBJEXT): {$(VPATH)}internal/memory.h
+parse.$(OBJEXT): {$(VPATH)}internal/method.h
+parse.$(OBJEXT): {$(VPATH)}internal/module.h
+parse.$(OBJEXT): {$(VPATH)}internal/newobj.h
+parse.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+parse.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+parse.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+parse.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+parse.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+parse.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+parse.$(OBJEXT): {$(VPATH)}internal/symbol.h
+parse.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+parse.$(OBJEXT): {$(VPATH)}internal/value.h
+parse.$(OBJEXT): {$(VPATH)}internal/value_type.h
+parse.$(OBJEXT): {$(VPATH)}internal/variable.h
+parse.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+parse.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+parse.$(OBJEXT): {$(VPATH)}io.h
parse.$(OBJEXT): {$(VPATH)}lex.c
parse.$(OBJEXT): {$(VPATH)}missing.h
parse.$(OBJEXT): {$(VPATH)}node.h
@@ -2556,30 +9782,228 @@ parse.$(OBJEXT): {$(VPATH)}parse.h
parse.$(OBJEXT): {$(VPATH)}parse.y
parse.$(OBJEXT): {$(VPATH)}probes.dmyh
parse.$(OBJEXT): {$(VPATH)}probes.h
+parse.$(OBJEXT): {$(VPATH)}ractor.h
parse.$(OBJEXT): {$(VPATH)}regenc.h
parse.$(OBJEXT): {$(VPATH)}regex.h
+parse.$(OBJEXT): {$(VPATH)}ruby_assert.h
parse.$(OBJEXT): {$(VPATH)}st.h
parse.$(OBJEXT): {$(VPATH)}subst.h
parse.$(OBJEXT): {$(VPATH)}symbol.h
parse.$(OBJEXT): {$(VPATH)}util.h
+prelude.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+prelude.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+prelude.$(OBJEXT): $(CCAN_DIR)/list/list.h
+prelude.$(OBJEXT): $(CCAN_DIR)/str/str.h
+prelude.$(OBJEXT): $(hdrdir)/ruby.h
+prelude.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+prelude.$(OBJEXT): {$(VPATH)}assert.h
+prelude.$(OBJEXT): {$(VPATH)}atomic.h
+prelude.$(OBJEXT): {$(VPATH)}config.h
+prelude.$(OBJEXT): {$(VPATH)}defines.h
+prelude.$(OBJEXT): {$(VPATH)}gem_prelude.rb
+prelude.$(OBJEXT): {$(VPATH)}id.h
+prelude.$(OBJEXT): {$(VPATH)}intern.h
+prelude.$(OBJEXT): {$(VPATH)}internal.h
+prelude.$(OBJEXT): {$(VPATH)}iseq.h
+prelude.$(OBJEXT): {$(VPATH)}method.h
+prelude.$(OBJEXT): {$(VPATH)}missing.h
+prelude.$(OBJEXT): {$(VPATH)}node.h
+prelude.$(OBJEXT): {$(VPATH)}prelude.c
+prelude.$(OBJEXT): {$(VPATH)}ruby_assert.h
+prelude.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+prelude.$(OBJEXT): {$(VPATH)}st.h
+prelude.$(OBJEXT): {$(VPATH)}subst.h
+prelude.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+prelude.$(OBJEXT): {$(VPATH)}thread_native.h
+prelude.$(OBJEXT): {$(VPATH)}vm_core.h
+prelude.$(OBJEXT): {$(VPATH)}vm_opts.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.h
proc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+proc.$(OBJEXT): $(top_srcdir)/internal/array.h
+proc.$(OBJEXT): $(top_srcdir)/internal/class.h
+proc.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+proc.$(OBJEXT): $(top_srcdir)/internal/error.h
+proc.$(OBJEXT): $(top_srcdir)/internal/eval.h
+proc.$(OBJEXT): $(top_srcdir)/internal/gc.h
+proc.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+proc.$(OBJEXT): $(top_srcdir)/internal/object.h
+proc.$(OBJEXT): $(top_srcdir)/internal/proc.h
+proc.$(OBJEXT): $(top_srcdir)/internal/serial.h
+proc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+proc.$(OBJEXT): $(top_srcdir)/internal/string.h
+proc.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+proc.$(OBJEXT): $(top_srcdir)/internal/vm.h
+proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
proc.$(OBJEXT): {$(VPATH)}assert.h
+proc.$(OBJEXT): {$(VPATH)}atomic.h
+proc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+proc.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+proc.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+proc.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+proc.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+proc.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+proc.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+proc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+proc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
proc.$(OBJEXT): {$(VPATH)}config.h
proc.$(OBJEXT): {$(VPATH)}defines.h
+proc.$(OBJEXT): {$(VPATH)}encoding.h
proc.$(OBJEXT): {$(VPATH)}eval_intern.h
proc.$(OBJEXT): {$(VPATH)}gc.h
proc.$(OBJEXT): {$(VPATH)}id.h
+proc.$(OBJEXT): {$(VPATH)}id_table.h
proc.$(OBJEXT): {$(VPATH)}intern.h
proc.$(OBJEXT): {$(VPATH)}internal.h
+proc.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+proc.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+proc.$(OBJEXT): {$(VPATH)}internal/assume.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+proc.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+proc.$(OBJEXT): {$(VPATH)}internal/cast.h
+proc.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+proc.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+proc.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+proc.$(OBJEXT): {$(VPATH)}internal/config.h
+proc.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+proc.$(OBJEXT): {$(VPATH)}internal/core.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+proc.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+proc.$(OBJEXT): {$(VPATH)}internal/ctype.h
+proc.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+proc.$(OBJEXT): {$(VPATH)}internal/dosish.h
+proc.$(OBJEXT): {$(VPATH)}internal/error.h
+proc.$(OBJEXT): {$(VPATH)}internal/eval.h
+proc.$(OBJEXT): {$(VPATH)}internal/event.h
+proc.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+proc.$(OBJEXT): {$(VPATH)}internal/gc.h
+proc.$(OBJEXT): {$(VPATH)}internal/glob.h
+proc.$(OBJEXT): {$(VPATH)}internal/globals.h
+proc.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+proc.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+proc.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+proc.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+proc.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+proc.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+proc.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+proc.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+proc.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+proc.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+proc.$(OBJEXT): {$(VPATH)}internal/iterator.h
+proc.$(OBJEXT): {$(VPATH)}internal/memory.h
+proc.$(OBJEXT): {$(VPATH)}internal/method.h
+proc.$(OBJEXT): {$(VPATH)}internal/module.h
+proc.$(OBJEXT): {$(VPATH)}internal/newobj.h
+proc.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+proc.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+proc.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+proc.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+proc.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+proc.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+proc.$(OBJEXT): {$(VPATH)}internal/symbol.h
+proc.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+proc.$(OBJEXT): {$(VPATH)}internal/value.h
+proc.$(OBJEXT): {$(VPATH)}internal/value_type.h
+proc.$(OBJEXT): {$(VPATH)}internal/variable.h
+proc.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+proc.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
proc.$(OBJEXT): {$(VPATH)}iseq.h
proc.$(OBJEXT): {$(VPATH)}method.h
proc.$(OBJEXT): {$(VPATH)}missing.h
proc.$(OBJEXT): {$(VPATH)}node.h
+proc.$(OBJEXT): {$(VPATH)}onigmo.h
+proc.$(OBJEXT): {$(VPATH)}oniguruma.h
proc.$(OBJEXT): {$(VPATH)}proc.c
proc.$(OBJEXT): {$(VPATH)}ruby_assert.h
proc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
@@ -2595,22 +10019,198 @@ process.$(OBJEXT): $(CCAN_DIR)/list/list.h
process.$(OBJEXT): $(CCAN_DIR)/str/str.h
process.$(OBJEXT): $(hdrdir)/ruby.h
process.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+process.$(OBJEXT): $(top_srcdir)/internal/array.h
+process.$(OBJEXT): $(top_srcdir)/internal/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/gc.h
+process.$(OBJEXT): $(top_srcdir)/internal/hash.h
+process.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+process.$(OBJEXT): $(top_srcdir)/internal/object.h
+process.$(OBJEXT): $(top_srcdir)/internal/process.h
+process.$(OBJEXT): $(top_srcdir)/internal/scheduler.h
+process.$(OBJEXT): $(top_srcdir)/internal/serial.h
+process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+process.$(OBJEXT): $(top_srcdir)/internal/string.h
+process.$(OBJEXT): $(top_srcdir)/internal/thread.h
+process.$(OBJEXT): $(top_srcdir)/internal/variable.h
+process.$(OBJEXT): $(top_srcdir)/internal/vm.h
+process.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+process.$(OBJEXT): {$(VPATH)}$(COROUTINE_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)}hrtime.h
process.$(OBJEXT): {$(VPATH)}id.h
+process.$(OBJEXT): {$(VPATH)}id_table.h
process.$(OBJEXT): {$(VPATH)}intern.h
process.$(OBJEXT): {$(VPATH)}internal.h
+process.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+process.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+process.$(OBJEXT): {$(VPATH)}internal/assume.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+process.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+process.$(OBJEXT): {$(VPATH)}internal/cast.h
+process.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+process.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+process.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+process.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+process.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+process.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+process.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+process.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+process.$(OBJEXT): {$(VPATH)}internal/config.h
+process.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+process.$(OBJEXT): {$(VPATH)}internal/core.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+process.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+process.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+process.$(OBJEXT): {$(VPATH)}internal/ctype.h
+process.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+process.$(OBJEXT): {$(VPATH)}internal/dosish.h
+process.$(OBJEXT): {$(VPATH)}internal/error.h
+process.$(OBJEXT): {$(VPATH)}internal/eval.h
+process.$(OBJEXT): {$(VPATH)}internal/event.h
+process.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+process.$(OBJEXT): {$(VPATH)}internal/gc.h
+process.$(OBJEXT): {$(VPATH)}internal/glob.h
+process.$(OBJEXT): {$(VPATH)}internal/globals.h
+process.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+process.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+process.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+process.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+process.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+process.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+process.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+process.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+process.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+process.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+process.$(OBJEXT): {$(VPATH)}internal/iterator.h
+process.$(OBJEXT): {$(VPATH)}internal/memory.h
+process.$(OBJEXT): {$(VPATH)}internal/method.h
+process.$(OBJEXT): {$(VPATH)}internal/module.h
+process.$(OBJEXT): {$(VPATH)}internal/newobj.h
+process.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+process.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+process.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+process.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+process.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+process.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+process.$(OBJEXT): {$(VPATH)}internal/symbol.h
+process.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+process.$(OBJEXT): {$(VPATH)}internal/value.h
+process.$(OBJEXT): {$(VPATH)}internal/value_type.h
+process.$(OBJEXT): {$(VPATH)}internal/variable.h
+process.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+process.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
process.$(OBJEXT): {$(VPATH)}io.h
process.$(OBJEXT): {$(VPATH)}method.h
process.$(OBJEXT): {$(VPATH)}missing.h
+process.$(OBJEXT): {$(VPATH)}mjit.h
process.$(OBJEXT): {$(VPATH)}node.h
process.$(OBJEXT): {$(VPATH)}onigmo.h
process.$(OBJEXT): {$(VPATH)}oniguruma.h
process.$(OBJEXT): {$(VPATH)}process.c
+process.$(OBJEXT): {$(VPATH)}ractor.h
process.$(OBJEXT): {$(VPATH)}ruby_assert.h
process.$(OBJEXT): {$(VPATH)}ruby_atomic.h
process.$(OBJEXT): {$(VPATH)}st.h
@@ -2621,16 +10221,398 @@ process.$(OBJEXT): {$(VPATH)}thread_native.h
process.$(OBJEXT): {$(VPATH)}util.h
process.$(OBJEXT): {$(VPATH)}vm_core.h
process.$(OBJEXT): {$(VPATH)}vm_opts.h
+ractor.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+ractor.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+ractor.$(OBJEXT): $(CCAN_DIR)/list/list.h
+ractor.$(OBJEXT): $(CCAN_DIR)/str/str.h
+ractor.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/array.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/bits.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/complex.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/error.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/gc.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/hash.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/rational.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/serial.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/string.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/struct.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/thread.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/vm.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+ractor.$(OBJEXT): {$(VPATH)}assert.h
+ractor.$(OBJEXT): {$(VPATH)}atomic.h
+ractor.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+ractor.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+ractor.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+ractor.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+ractor.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+ractor.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+ractor.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+ractor.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+ractor.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+ractor.$(OBJEXT): {$(VPATH)}builtin.h
+ractor.$(OBJEXT): {$(VPATH)}config.h
+ractor.$(OBJEXT): {$(VPATH)}constant.h
+ractor.$(OBJEXT): {$(VPATH)}debug.h
+ractor.$(OBJEXT): {$(VPATH)}debug_counter.h
+ractor.$(OBJEXT): {$(VPATH)}defines.h
+ractor.$(OBJEXT): {$(VPATH)}encoding.h
+ractor.$(OBJEXT): {$(VPATH)}gc.h
+ractor.$(OBJEXT): {$(VPATH)}id.h
+ractor.$(OBJEXT): {$(VPATH)}id_table.h
+ractor.$(OBJEXT): {$(VPATH)}intern.h
+ractor.$(OBJEXT): {$(VPATH)}internal.h
+ractor.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+ractor.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+ractor.$(OBJEXT): {$(VPATH)}internal/assume.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+ractor.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+ractor.$(OBJEXT): {$(VPATH)}internal/cast.h
+ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+ractor.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+ractor.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+ractor.$(OBJEXT): {$(VPATH)}internal/config.h
+ractor.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+ractor.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+ractor.$(OBJEXT): {$(VPATH)}internal/ctype.h
+ractor.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+ractor.$(OBJEXT): {$(VPATH)}internal/dosish.h
+ractor.$(OBJEXT): {$(VPATH)}internal/error.h
+ractor.$(OBJEXT): {$(VPATH)}internal/eval.h
+ractor.$(OBJEXT): {$(VPATH)}internal/event.h
+ractor.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+ractor.$(OBJEXT): {$(VPATH)}internal/gc.h
+ractor.$(OBJEXT): {$(VPATH)}internal/glob.h
+ractor.$(OBJEXT): {$(VPATH)}internal/globals.h
+ractor.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+ractor.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+ractor.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+ractor.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+ractor.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+ractor.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+ractor.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+ractor.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+ractor.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+ractor.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+ractor.$(OBJEXT): {$(VPATH)}internal/iterator.h
+ractor.$(OBJEXT): {$(VPATH)}internal/memory.h
+ractor.$(OBJEXT): {$(VPATH)}internal/method.h
+ractor.$(OBJEXT): {$(VPATH)}internal/module.h
+ractor.$(OBJEXT): {$(VPATH)}internal/newobj.h
+ractor.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+ractor.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+ractor.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+ractor.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+ractor.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+ractor.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+ractor.$(OBJEXT): {$(VPATH)}internal/symbol.h
+ractor.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+ractor.$(OBJEXT): {$(VPATH)}internal/value.h
+ractor.$(OBJEXT): {$(VPATH)}internal/value_type.h
+ractor.$(OBJEXT): {$(VPATH)}internal/variable.h
+ractor.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+ractor.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+ractor.$(OBJEXT): {$(VPATH)}method.h
+ractor.$(OBJEXT): {$(VPATH)}missing.h
+ractor.$(OBJEXT): {$(VPATH)}node.h
+ractor.$(OBJEXT): {$(VPATH)}onigmo.h
+ractor.$(OBJEXT): {$(VPATH)}oniguruma.h
+ractor.$(OBJEXT): {$(VPATH)}ractor.c
+ractor.$(OBJEXT): {$(VPATH)}ractor.h
+ractor.$(OBJEXT): {$(VPATH)}ractor.rb
+ractor.$(OBJEXT): {$(VPATH)}ractor.rbinc
+ractor.$(OBJEXT): {$(VPATH)}ractor_core.h
+ractor.$(OBJEXT): {$(VPATH)}ruby_assert.h
+ractor.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+ractor.$(OBJEXT): {$(VPATH)}st.h
+ractor.$(OBJEXT): {$(VPATH)}subst.h
+ractor.$(OBJEXT): {$(VPATH)}thread.h
+ractor.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+ractor.$(OBJEXT): {$(VPATH)}thread_native.h
+ractor.$(OBJEXT): {$(VPATH)}transient_heap.h
+ractor.$(OBJEXT): {$(VPATH)}variable.h
+ractor.$(OBJEXT): {$(VPATH)}vm_core.h
+ractor.$(OBJEXT): {$(VPATH)}vm_debug.h
+ractor.$(OBJEXT): {$(VPATH)}vm_opts.h
+ractor.$(OBJEXT): {$(VPATH)}vm_sync.h
random.$(OBJEXT): $(hdrdir)/ruby.h
random.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+random.$(OBJEXT): $(top_srcdir)/internal/array.h
+random.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+random.$(OBJEXT): $(top_srcdir)/internal/bits.h
+random.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+random.$(OBJEXT): $(top_srcdir)/internal/error.h
+random.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+random.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+random.$(OBJEXT): $(top_srcdir)/internal/random.h
+random.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+random.$(OBJEXT): $(top_srcdir)/internal/serial.h
+random.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+random.$(OBJEXT): $(top_srcdir)/internal/string.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_table.h
random.$(OBJEXT): {$(VPATH)}intern.h
random.$(OBJEXT): {$(VPATH)}internal.h
+random.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+random.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+random.$(OBJEXT): {$(VPATH)}internal/assume.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+random.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+random.$(OBJEXT): {$(VPATH)}internal/cast.h
+random.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+random.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+random.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+random.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+random.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+random.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+random.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+random.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+random.$(OBJEXT): {$(VPATH)}internal/config.h
+random.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+random.$(OBJEXT): {$(VPATH)}internal/core.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+random.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+random.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+random.$(OBJEXT): {$(VPATH)}internal/ctype.h
+random.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+random.$(OBJEXT): {$(VPATH)}internal/dosish.h
+random.$(OBJEXT): {$(VPATH)}internal/error.h
+random.$(OBJEXT): {$(VPATH)}internal/eval.h
+random.$(OBJEXT): {$(VPATH)}internal/event.h
+random.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+random.$(OBJEXT): {$(VPATH)}internal/gc.h
+random.$(OBJEXT): {$(VPATH)}internal/glob.h
+random.$(OBJEXT): {$(VPATH)}internal/globals.h
+random.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+random.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+random.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+random.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+random.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+random.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+random.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+random.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+random.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+random.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+random.$(OBJEXT): {$(VPATH)}internal/iterator.h
+random.$(OBJEXT): {$(VPATH)}internal/memory.h
+random.$(OBJEXT): {$(VPATH)}internal/method.h
+random.$(OBJEXT): {$(VPATH)}internal/module.h
+random.$(OBJEXT): {$(VPATH)}internal/newobj.h
+random.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+random.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+random.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+random.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+random.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+random.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+random.$(OBJEXT): {$(VPATH)}internal/symbol.h
+random.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+random.$(OBJEXT): {$(VPATH)}internal/value.h
+random.$(OBJEXT): {$(VPATH)}internal/value_type.h
+random.$(OBJEXT): {$(VPATH)}internal/variable.h
+random.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+random.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
random.$(OBJEXT): {$(VPATH)}missing.h
random.$(OBJEXT): {$(VPATH)}mt19937.c
+random.$(OBJEXT): {$(VPATH)}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_atomic.h
random.$(OBJEXT): {$(VPATH)}siphash.c
random.$(OBJEXT): {$(VPATH)}siphash.h
@@ -2638,38 +10620,541 @@ random.$(OBJEXT): {$(VPATH)}st.h
random.$(OBJEXT): {$(VPATH)}subst.h
range.$(OBJEXT): $(hdrdir)/ruby.h
range.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+range.$(OBJEXT): $(top_srcdir)/internal/array.h
+range.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+range.$(OBJEXT): $(top_srcdir)/internal/bits.h
+range.$(OBJEXT): $(top_srcdir)/internal/compar.h
+range.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+range.$(OBJEXT): $(top_srcdir)/internal/enum.h
+range.$(OBJEXT): $(top_srcdir)/internal/enumerator.h
+range.$(OBJEXT): $(top_srcdir)/internal/error.h
+range.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+range.$(OBJEXT): $(top_srcdir)/internal/gc.h
+range.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+range.$(OBJEXT): $(top_srcdir)/internal/range.h
+range.$(OBJEXT): $(top_srcdir)/internal/serial.h
+range.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+range.$(OBJEXT): $(top_srcdir)/internal/string.h
+range.$(OBJEXT): $(top_srcdir)/internal/struct.h
+range.$(OBJEXT): $(top_srcdir)/internal/vm.h
+range.$(OBJEXT): $(top_srcdir)/internal/warnings.h
range.$(OBJEXT): {$(VPATH)}assert.h
+range.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+range.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+range.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+range.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+range.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+range.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+range.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+range.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+range.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
range.$(OBJEXT): {$(VPATH)}config.h
range.$(OBJEXT): {$(VPATH)}defines.h
+range.$(OBJEXT): {$(VPATH)}encoding.h
range.$(OBJEXT): {$(VPATH)}id.h
range.$(OBJEXT): {$(VPATH)}intern.h
range.$(OBJEXT): {$(VPATH)}internal.h
+range.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+range.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+range.$(OBJEXT): {$(VPATH)}internal/assume.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+range.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+range.$(OBJEXT): {$(VPATH)}internal/cast.h
+range.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+range.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+range.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+range.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+range.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+range.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+range.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+range.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+range.$(OBJEXT): {$(VPATH)}internal/config.h
+range.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+range.$(OBJEXT): {$(VPATH)}internal/core.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+range.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+range.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+range.$(OBJEXT): {$(VPATH)}internal/ctype.h
+range.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+range.$(OBJEXT): {$(VPATH)}internal/dosish.h
+range.$(OBJEXT): {$(VPATH)}internal/error.h
+range.$(OBJEXT): {$(VPATH)}internal/eval.h
+range.$(OBJEXT): {$(VPATH)}internal/event.h
+range.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+range.$(OBJEXT): {$(VPATH)}internal/gc.h
+range.$(OBJEXT): {$(VPATH)}internal/glob.h
+range.$(OBJEXT): {$(VPATH)}internal/globals.h
+range.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+range.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+range.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+range.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+range.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+range.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+range.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+range.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+range.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+range.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+range.$(OBJEXT): {$(VPATH)}internal/iterator.h
+range.$(OBJEXT): {$(VPATH)}internal/memory.h
+range.$(OBJEXT): {$(VPATH)}internal/method.h
+range.$(OBJEXT): {$(VPATH)}internal/module.h
+range.$(OBJEXT): {$(VPATH)}internal/newobj.h
+range.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+range.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+range.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+range.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+range.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+range.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+range.$(OBJEXT): {$(VPATH)}internal/symbol.h
+range.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+range.$(OBJEXT): {$(VPATH)}internal/value.h
+range.$(OBJEXT): {$(VPATH)}internal/value_type.h
+range.$(OBJEXT): {$(VPATH)}internal/variable.h
+range.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+range.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
range.$(OBJEXT): {$(VPATH)}missing.h
+range.$(OBJEXT): {$(VPATH)}onigmo.h
+range.$(OBJEXT): {$(VPATH)}oniguruma.h
range.$(OBJEXT): {$(VPATH)}range.c
range.$(OBJEXT): {$(VPATH)}st.h
range.$(OBJEXT): {$(VPATH)}subst.h
rational.$(OBJEXT): $(hdrdir)/ruby.h
rational.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+rational.$(OBJEXT): $(top_srcdir)/internal/array.h
+rational.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+rational.$(OBJEXT): $(top_srcdir)/internal/bits.h
+rational.$(OBJEXT): $(top_srcdir)/internal/class.h
+rational.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+rational.$(OBJEXT): $(top_srcdir)/internal/complex.h
+rational.$(OBJEXT): $(top_srcdir)/internal/error.h
+rational.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+rational.$(OBJEXT): $(top_srcdir)/internal/gc.h
+rational.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+rational.$(OBJEXT): $(top_srcdir)/internal/object.h
+rational.$(OBJEXT): $(top_srcdir)/internal/rational.h
+rational.$(OBJEXT): $(top_srcdir)/internal/serial.h
+rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+rational.$(OBJEXT): $(top_srcdir)/internal/string.h
+rational.$(OBJEXT): $(top_srcdir)/internal/vm.h
+rational.$(OBJEXT): $(top_srcdir)/internal/warnings.h
rational.$(OBJEXT): {$(VPATH)}assert.h
+rational.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+rational.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+rational.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+rational.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+rational.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+rational.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+rational.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+rational.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+rational.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
rational.$(OBJEXT): {$(VPATH)}config.h
rational.$(OBJEXT): {$(VPATH)}defines.h
+rational.$(OBJEXT): {$(VPATH)}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/anyargs.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+rational.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+rational.$(OBJEXT): {$(VPATH)}internal/assume.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+rational.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+rational.$(OBJEXT): {$(VPATH)}internal/cast.h
+rational.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+rational.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+rational.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+rational.$(OBJEXT): {$(VPATH)}internal/config.h
+rational.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+rational.$(OBJEXT): {$(VPATH)}internal/core.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+rational.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+rational.$(OBJEXT): {$(VPATH)}internal/ctype.h
+rational.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+rational.$(OBJEXT): {$(VPATH)}internal/dosish.h
+rational.$(OBJEXT): {$(VPATH)}internal/error.h
+rational.$(OBJEXT): {$(VPATH)}internal/eval.h
+rational.$(OBJEXT): {$(VPATH)}internal/event.h
+rational.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+rational.$(OBJEXT): {$(VPATH)}internal/gc.h
+rational.$(OBJEXT): {$(VPATH)}internal/glob.h
+rational.$(OBJEXT): {$(VPATH)}internal/globals.h
+rational.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+rational.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+rational.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+rational.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+rational.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+rational.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+rational.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+rational.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+rational.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+rational.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+rational.$(OBJEXT): {$(VPATH)}internal/iterator.h
+rational.$(OBJEXT): {$(VPATH)}internal/memory.h
+rational.$(OBJEXT): {$(VPATH)}internal/method.h
+rational.$(OBJEXT): {$(VPATH)}internal/module.h
+rational.$(OBJEXT): {$(VPATH)}internal/newobj.h
+rational.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+rational.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+rational.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+rational.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+rational.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+rational.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+rational.$(OBJEXT): {$(VPATH)}internal/symbol.h
+rational.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+rational.$(OBJEXT): {$(VPATH)}internal/value.h
+rational.$(OBJEXT): {$(VPATH)}internal/value_type.h
+rational.$(OBJEXT): {$(VPATH)}internal/variable.h
+rational.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+rational.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
rational.$(OBJEXT): {$(VPATH)}missing.h
+rational.$(OBJEXT): {$(VPATH)}onigmo.h
+rational.$(OBJEXT): {$(VPATH)}oniguruma.h
rational.$(OBJEXT): {$(VPATH)}rational.c
rational.$(OBJEXT): {$(VPATH)}ruby_assert.h
rational.$(OBJEXT): {$(VPATH)}st.h
rational.$(OBJEXT): {$(VPATH)}subst.h
re.$(OBJEXT): $(hdrdir)/ruby.h
re.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+re.$(OBJEXT): $(top_srcdir)/internal/array.h
+re.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+re.$(OBJEXT): $(top_srcdir)/internal/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/re.h
+re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+re.$(OBJEXT): $(top_srcdir)/internal/string.h
+re.$(OBJEXT): $(top_srcdir)/internal/variable.h
+re.$(OBJEXT): $(top_srcdir)/internal/warnings.h
re.$(OBJEXT): {$(VPATH)}assert.h
+re.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+re.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+re.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+re.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+re.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+re.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+re.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+re.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+re.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
re.$(OBJEXT): {$(VPATH)}config.h
+re.$(OBJEXT): {$(VPATH)}constant.h
re.$(OBJEXT): {$(VPATH)}defines.h
re.$(OBJEXT): {$(VPATH)}encindex.h
re.$(OBJEXT): {$(VPATH)}encoding.h
+re.$(OBJEXT): {$(VPATH)}id_table.h
re.$(OBJEXT): {$(VPATH)}intern.h
re.$(OBJEXT): {$(VPATH)}internal.h
+re.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+re.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+re.$(OBJEXT): {$(VPATH)}internal/assume.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+re.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+re.$(OBJEXT): {$(VPATH)}internal/cast.h
+re.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+re.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+re.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+re.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+re.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+re.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+re.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+re.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+re.$(OBJEXT): {$(VPATH)}internal/config.h
+re.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+re.$(OBJEXT): {$(VPATH)}internal/core.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h
+re.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+re.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+re.$(OBJEXT): {$(VPATH)}internal/ctype.h
+re.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+re.$(OBJEXT): {$(VPATH)}internal/dosish.h
+re.$(OBJEXT): {$(VPATH)}internal/error.h
+re.$(OBJEXT): {$(VPATH)}internal/eval.h
+re.$(OBJEXT): {$(VPATH)}internal/event.h
+re.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+re.$(OBJEXT): {$(VPATH)}internal/gc.h
+re.$(OBJEXT): {$(VPATH)}internal/glob.h
+re.$(OBJEXT): {$(VPATH)}internal/globals.h
+re.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+re.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+re.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+re.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+re.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+re.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+re.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+re.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+re.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+re.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+re.$(OBJEXT): {$(VPATH)}internal/iterator.h
+re.$(OBJEXT): {$(VPATH)}internal/memory.h
+re.$(OBJEXT): {$(VPATH)}internal/method.h
+re.$(OBJEXT): {$(VPATH)}internal/module.h
+re.$(OBJEXT): {$(VPATH)}internal/newobj.h
+re.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+re.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+re.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+re.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+re.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+re.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+re.$(OBJEXT): {$(VPATH)}internal/symbol.h
+re.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+re.$(OBJEXT): {$(VPATH)}internal/value.h
+re.$(OBJEXT): {$(VPATH)}internal/value_type.h
+re.$(OBJEXT): {$(VPATH)}internal/variable.h
+re.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+re.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
re.$(OBJEXT): {$(VPATH)}missing.h
re.$(OBJEXT): {$(VPATH)}onigmo.h
re.$(OBJEXT): {$(VPATH)}oniguruma.h
@@ -2683,9 +11168,158 @@ re.$(OBJEXT): {$(VPATH)}subst.h
re.$(OBJEXT): {$(VPATH)}util.h
regcomp.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regcomp.$(OBJEXT): {$(VPATH)}assert.h
+regcomp.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+regcomp.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+regcomp.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+regcomp.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+regcomp.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+regcomp.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+regcomp.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+regcomp.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+regcomp.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regcomp.$(OBJEXT): {$(VPATH)}config.h
regcomp.$(OBJEXT): {$(VPATH)}defines.h
regcomp.$(OBJEXT): {$(VPATH)}intern.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/assume.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/cast.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/config.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/ctype.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/dosish.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/error.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/eval.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/event.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/gc.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/glob.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/globals.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/iterator.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/memory.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/method.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/module.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/newobj.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/symbol.h
+regcomp.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2696,9 +11330,158 @@ regcomp.$(OBJEXT): {$(VPATH)}st.h
regcomp.$(OBJEXT): {$(VPATH)}subst.h
regenc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regenc.$(OBJEXT): {$(VPATH)}assert.h
+regenc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+regenc.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+regenc.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+regenc.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+regenc.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+regenc.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+regenc.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+regenc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+regenc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regenc.$(OBJEXT): {$(VPATH)}config.h
regenc.$(OBJEXT): {$(VPATH)}defines.h
regenc.$(OBJEXT): {$(VPATH)}intern.h
+regenc.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+regenc.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+regenc.$(OBJEXT): {$(VPATH)}internal/assume.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+regenc.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+regenc.$(OBJEXT): {$(VPATH)}internal/cast.h
+regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+regenc.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+regenc.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+regenc.$(OBJEXT): {$(VPATH)}internal/config.h
+regenc.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+regenc.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+regenc.$(OBJEXT): {$(VPATH)}internal/ctype.h
+regenc.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+regenc.$(OBJEXT): {$(VPATH)}internal/dosish.h
+regenc.$(OBJEXT): {$(VPATH)}internal/error.h
+regenc.$(OBJEXT): {$(VPATH)}internal/eval.h
+regenc.$(OBJEXT): {$(VPATH)}internal/event.h
+regenc.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+regenc.$(OBJEXT): {$(VPATH)}internal/gc.h
+regenc.$(OBJEXT): {$(VPATH)}internal/glob.h
+regenc.$(OBJEXT): {$(VPATH)}internal/globals.h
+regenc.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+regenc.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+regenc.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+regenc.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+regenc.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+regenc.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+regenc.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+regenc.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+regenc.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+regenc.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+regenc.$(OBJEXT): {$(VPATH)}internal/iterator.h
+regenc.$(OBJEXT): {$(VPATH)}internal/memory.h
+regenc.$(OBJEXT): {$(VPATH)}internal/method.h
+regenc.$(OBJEXT): {$(VPATH)}internal/module.h
+regenc.$(OBJEXT): {$(VPATH)}internal/newobj.h
+regenc.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+regenc.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+regenc.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+regenc.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+regenc.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+regenc.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regenc.$(OBJEXT): {$(VPATH)}internal/symbol.h
+regenc.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2708,9 +11491,158 @@ regenc.$(OBJEXT): {$(VPATH)}st.h
regenc.$(OBJEXT): {$(VPATH)}subst.h
regerror.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regerror.$(OBJEXT): {$(VPATH)}assert.h
+regerror.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+regerror.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+regerror.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+regerror.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+regerror.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+regerror.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+regerror.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+regerror.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+regerror.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regerror.$(OBJEXT): {$(VPATH)}config.h
regerror.$(OBJEXT): {$(VPATH)}defines.h
regerror.$(OBJEXT): {$(VPATH)}intern.h
+regerror.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+regerror.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+regerror.$(OBJEXT): {$(VPATH)}internal/assume.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+regerror.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+regerror.$(OBJEXT): {$(VPATH)}internal/cast.h
+regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+regerror.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+regerror.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+regerror.$(OBJEXT): {$(VPATH)}internal/config.h
+regerror.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+regerror.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+regerror.$(OBJEXT): {$(VPATH)}internal/ctype.h
+regerror.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+regerror.$(OBJEXT): {$(VPATH)}internal/dosish.h
+regerror.$(OBJEXT): {$(VPATH)}internal/error.h
+regerror.$(OBJEXT): {$(VPATH)}internal/eval.h
+regerror.$(OBJEXT): {$(VPATH)}internal/event.h
+regerror.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+regerror.$(OBJEXT): {$(VPATH)}internal/gc.h
+regerror.$(OBJEXT): {$(VPATH)}internal/glob.h
+regerror.$(OBJEXT): {$(VPATH)}internal/globals.h
+regerror.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+regerror.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+regerror.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+regerror.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+regerror.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+regerror.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+regerror.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+regerror.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+regerror.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+regerror.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+regerror.$(OBJEXT): {$(VPATH)}internal/iterator.h
+regerror.$(OBJEXT): {$(VPATH)}internal/memory.h
+regerror.$(OBJEXT): {$(VPATH)}internal/method.h
+regerror.$(OBJEXT): {$(VPATH)}internal/module.h
+regerror.$(OBJEXT): {$(VPATH)}internal/newobj.h
+regerror.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+regerror.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+regerror.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+regerror.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+regerror.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+regerror.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regerror.$(OBJEXT): {$(VPATH)}internal/symbol.h
+regerror.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2720,9 +11652,158 @@ regerror.$(OBJEXT): {$(VPATH)}st.h
regerror.$(OBJEXT): {$(VPATH)}subst.h
regexec.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regexec.$(OBJEXT): {$(VPATH)}assert.h
+regexec.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+regexec.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+regexec.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+regexec.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+regexec.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+regexec.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+regexec.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+regexec.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+regexec.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regexec.$(OBJEXT): {$(VPATH)}config.h
regexec.$(OBJEXT): {$(VPATH)}defines.h
regexec.$(OBJEXT): {$(VPATH)}intern.h
+regexec.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+regexec.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+regexec.$(OBJEXT): {$(VPATH)}internal/assume.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+regexec.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+regexec.$(OBJEXT): {$(VPATH)}internal/cast.h
+regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+regexec.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+regexec.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+regexec.$(OBJEXT): {$(VPATH)}internal/config.h
+regexec.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+regexec.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+regexec.$(OBJEXT): {$(VPATH)}internal/ctype.h
+regexec.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+regexec.$(OBJEXT): {$(VPATH)}internal/dosish.h
+regexec.$(OBJEXT): {$(VPATH)}internal/error.h
+regexec.$(OBJEXT): {$(VPATH)}internal/eval.h
+regexec.$(OBJEXT): {$(VPATH)}internal/event.h
+regexec.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+regexec.$(OBJEXT): {$(VPATH)}internal/gc.h
+regexec.$(OBJEXT): {$(VPATH)}internal/glob.h
+regexec.$(OBJEXT): {$(VPATH)}internal/globals.h
+regexec.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+regexec.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+regexec.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+regexec.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+regexec.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+regexec.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+regexec.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+regexec.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+regexec.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+regexec.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+regexec.$(OBJEXT): {$(VPATH)}internal/iterator.h
+regexec.$(OBJEXT): {$(VPATH)}internal/memory.h
+regexec.$(OBJEXT): {$(VPATH)}internal/method.h
+regexec.$(OBJEXT): {$(VPATH)}internal/module.h
+regexec.$(OBJEXT): {$(VPATH)}internal/newobj.h
+regexec.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+regexec.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+regexec.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+regexec.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+regexec.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+regexec.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regexec.$(OBJEXT): {$(VPATH)}internal/symbol.h
+regexec.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2732,9 +11813,158 @@ regexec.$(OBJEXT): {$(VPATH)}st.h
regexec.$(OBJEXT): {$(VPATH)}subst.h
regparse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regparse.$(OBJEXT): {$(VPATH)}assert.h
+regparse.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+regparse.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+regparse.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+regparse.$(OBJEXT): {$(VPATH)}backward/2/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/anyargs.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+regparse.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+regparse.$(OBJEXT): {$(VPATH)}internal/assume.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+regparse.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+regparse.$(OBJEXT): {$(VPATH)}internal/cast.h
+regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+regparse.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+regparse.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+regparse.$(OBJEXT): {$(VPATH)}internal/config.h
+regparse.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+regparse.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+regparse.$(OBJEXT): {$(VPATH)}internal/ctype.h
+regparse.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+regparse.$(OBJEXT): {$(VPATH)}internal/dosish.h
+regparse.$(OBJEXT): {$(VPATH)}internal/error.h
+regparse.$(OBJEXT): {$(VPATH)}internal/eval.h
+regparse.$(OBJEXT): {$(VPATH)}internal/event.h
+regparse.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+regparse.$(OBJEXT): {$(VPATH)}internal/gc.h
+regparse.$(OBJEXT): {$(VPATH)}internal/glob.h
+regparse.$(OBJEXT): {$(VPATH)}internal/globals.h
+regparse.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+regparse.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+regparse.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+regparse.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+regparse.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+regparse.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+regparse.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+regparse.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+regparse.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+regparse.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+regparse.$(OBJEXT): {$(VPATH)}internal/iterator.h
+regparse.$(OBJEXT): {$(VPATH)}internal/memory.h
+regparse.$(OBJEXT): {$(VPATH)}internal/method.h
+regparse.$(OBJEXT): {$(VPATH)}internal/module.h
+regparse.$(OBJEXT): {$(VPATH)}internal/newobj.h
+regparse.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+regparse.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+regparse.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+regparse.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+regparse.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+regparse.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regparse.$(OBJEXT): {$(VPATH)}internal/symbol.h
+regparse.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2745,9 +11975,158 @@ regparse.$(OBJEXT): {$(VPATH)}st.h
regparse.$(OBJEXT): {$(VPATH)}subst.h
regsyntax.$(OBJEXT): $(hdrdir)/ruby/ruby.h
regsyntax.$(OBJEXT): {$(VPATH)}assert.h
+regsyntax.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+regsyntax.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+regsyntax.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+regsyntax.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+regsyntax.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+regsyntax.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+regsyntax.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+regsyntax.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+regsyntax.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
regsyntax.$(OBJEXT): {$(VPATH)}config.h
regsyntax.$(OBJEXT): {$(VPATH)}defines.h
regsyntax.$(OBJEXT): {$(VPATH)}intern.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/assume.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/cast.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/config.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/ctype.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/dosish.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/error.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/eval.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/event.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/gc.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/glob.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/globals.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/iterator.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/memory.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/method.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/module.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/newobj.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/symbol.h
+regsyntax.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2756,6 +12135,15 @@ regsyntax.$(OBJEXT): {$(VPATH)}regsyntax.c
regsyntax.$(OBJEXT): {$(VPATH)}st.h
regsyntax.$(OBJEXT): {$(VPATH)}subst.h
ruby-runner.$(OBJEXT): {$(VPATH)}config.h
+ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+ruby-runner.$(OBJEXT): {$(VPATH)}internal/config.h
ruby-runner.$(OBJEXT): {$(VPATH)}ruby-runner.c
ruby-runner.$(OBJEXT): {$(VPATH)}ruby-runner.h
ruby.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
@@ -2765,16 +12153,190 @@ ruby.$(OBJEXT): $(CCAN_DIR)/str/str.h
ruby.$(OBJEXT): $(hdrdir)/ruby.h
ruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h
ruby.$(OBJEXT): $(hdrdir)/ruby/version.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/array.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/class.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/error.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/file.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/inits.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/io.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/load.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/loadpath.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/missing.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/object.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/process.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/string.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
ruby.$(OBJEXT): {$(VPATH)}assert.h
+ruby.$(OBJEXT): {$(VPATH)}atomic.h
+ruby.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+ruby.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+ruby.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+ruby.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+ruby.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+ruby.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+ruby.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+ruby.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+ruby.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
ruby.$(OBJEXT): {$(VPATH)}config.h
+ruby.$(OBJEXT): {$(VPATH)}constant.h
ruby.$(OBJEXT): {$(VPATH)}debug_counter.h
ruby.$(OBJEXT): {$(VPATH)}defines.h
ruby.$(OBJEXT): {$(VPATH)}dln.h
ruby.$(OBJEXT): {$(VPATH)}encoding.h
ruby.$(OBJEXT): {$(VPATH)}eval_intern.h
ruby.$(OBJEXT): {$(VPATH)}id.h
+ruby.$(OBJEXT): {$(VPATH)}id_table.h
ruby.$(OBJEXT): {$(VPATH)}intern.h
ruby.$(OBJEXT): {$(VPATH)}internal.h
+ruby.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+ruby.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+ruby.$(OBJEXT): {$(VPATH)}internal/assume.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+ruby.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+ruby.$(OBJEXT): {$(VPATH)}internal/cast.h
+ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+ruby.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+ruby.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+ruby.$(OBJEXT): {$(VPATH)}internal/config.h
+ruby.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+ruby.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+ruby.$(OBJEXT): {$(VPATH)}internal/ctype.h
+ruby.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+ruby.$(OBJEXT): {$(VPATH)}internal/dosish.h
+ruby.$(OBJEXT): {$(VPATH)}internal/error.h
+ruby.$(OBJEXT): {$(VPATH)}internal/eval.h
+ruby.$(OBJEXT): {$(VPATH)}internal/event.h
+ruby.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+ruby.$(OBJEXT): {$(VPATH)}internal/gc.h
+ruby.$(OBJEXT): {$(VPATH)}internal/glob.h
+ruby.$(OBJEXT): {$(VPATH)}internal/globals.h
+ruby.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+ruby.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+ruby.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+ruby.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+ruby.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+ruby.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+ruby.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+ruby.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+ruby.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+ruby.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+ruby.$(OBJEXT): {$(VPATH)}internal/iterator.h
+ruby.$(OBJEXT): {$(VPATH)}internal/memory.h
+ruby.$(OBJEXT): {$(VPATH)}internal/method.h
+ruby.$(OBJEXT): {$(VPATH)}internal/module.h
+ruby.$(OBJEXT): {$(VPATH)}internal/newobj.h
+ruby.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+ruby.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+ruby.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+ruby.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+ruby.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+ruby.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+ruby.$(OBJEXT): {$(VPATH)}internal/symbol.h
+ruby.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+ruby.$(OBJEXT): {$(VPATH)}internal/value.h
+ruby.$(OBJEXT): {$(VPATH)}internal/value_type.h
+ruby.$(OBJEXT): {$(VPATH)}internal/variable.h
+ruby.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+ruby.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+ruby.$(OBJEXT): {$(VPATH)}io.h
ruby.$(OBJEXT): {$(VPATH)}method.h
ruby.$(OBJEXT): {$(VPATH)}missing.h
ruby.$(OBJEXT): {$(VPATH)}mjit.h
@@ -2792,36 +12354,348 @@ ruby.$(OBJEXT): {$(VPATH)}thread_native.h
ruby.$(OBJEXT): {$(VPATH)}util.h
ruby.$(OBJEXT): {$(VPATH)}vm_core.h
ruby.$(OBJEXT): {$(VPATH)}vm_opts.h
-safe.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-safe.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-safe.$(OBJEXT): $(CCAN_DIR)/list/list.h
-safe.$(OBJEXT): $(CCAN_DIR)/str/str.h
-safe.$(OBJEXT): $(hdrdir)/ruby.h
-safe.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-safe.$(OBJEXT): {$(VPATH)}assert.h
-safe.$(OBJEXT): {$(VPATH)}config.h
-safe.$(OBJEXT): {$(VPATH)}defines.h
-safe.$(OBJEXT): {$(VPATH)}id.h
-safe.$(OBJEXT): {$(VPATH)}intern.h
-safe.$(OBJEXT): {$(VPATH)}internal.h
-safe.$(OBJEXT): {$(VPATH)}method.h
-safe.$(OBJEXT): {$(VPATH)}missing.h
-safe.$(OBJEXT): {$(VPATH)}node.h
-safe.$(OBJEXT): {$(VPATH)}ruby_assert.h
-safe.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-safe.$(OBJEXT): {$(VPATH)}safe.c
-safe.$(OBJEXT): {$(VPATH)}st.h
-safe.$(OBJEXT): {$(VPATH)}subst.h
-safe.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-safe.$(OBJEXT): {$(VPATH)}thread_native.h
-safe.$(OBJEXT): {$(VPATH)}vm_core.h
-safe.$(OBJEXT): {$(VPATH)}vm_opts.h
+scheduler.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+scheduler.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+scheduler.$(OBJEXT): $(CCAN_DIR)/list/list.h
+scheduler.$(OBJEXT): $(CCAN_DIR)/str/str.h
+scheduler.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/array.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/gc.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/scheduler.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/serial.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.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)}defines.h
+scheduler.$(OBJEXT): {$(VPATH)}encoding.h
+scheduler.$(OBJEXT): {$(VPATH)}id.h
+scheduler.$(OBJEXT): {$(VPATH)}intern.h
+scheduler.$(OBJEXT): {$(VPATH)}internal.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/assume.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/cast.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/config.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/ctype.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/dosish.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/error.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/eval.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/event.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/gc.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/glob.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/globals.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/iterator.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/memory.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/method.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/module.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/newobj.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/scheduler.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/symbol.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/token_paste.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)}method.h
+scheduler.$(OBJEXT): {$(VPATH)}missing.h
+scheduler.$(OBJEXT): {$(VPATH)}node.h
+scheduler.$(OBJEXT): {$(VPATH)}onigmo.h
+scheduler.$(OBJEXT): {$(VPATH)}oniguruma.h
+scheduler.$(OBJEXT): {$(VPATH)}ruby_assert.h
+scheduler.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+scheduler.$(OBJEXT): {$(VPATH)}scheduler.c
+scheduler.$(OBJEXT): {$(VPATH)}st.h
+scheduler.$(OBJEXT): {$(VPATH)}subst.h
+scheduler.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+scheduler.$(OBJEXT): {$(VPATH)}thread_native.h
+scheduler.$(OBJEXT): {$(VPATH)}vm_core.h
+scheduler.$(OBJEXT): {$(VPATH)}vm_opts.h
setproctitle.$(OBJEXT): $(hdrdir)/ruby.h
setproctitle.$(OBJEXT): $(hdrdir)/ruby/ruby.h
setproctitle.$(OBJEXT): {$(VPATH)}assert.h
+setproctitle.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+setproctitle.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+setproctitle.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+setproctitle.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+setproctitle.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+setproctitle.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+setproctitle.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+setproctitle.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+setproctitle.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
setproctitle.$(OBJEXT): {$(VPATH)}config.h
setproctitle.$(OBJEXT): {$(VPATH)}defines.h
setproctitle.$(OBJEXT): {$(VPATH)}intern.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/assume.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/cast.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/config.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/ctype.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/dosish.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/error.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/eval.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/event.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/gc.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/glob.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/globals.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/iterator.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/memory.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/method.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/module.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/newobj.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/symbol.h
+setproctitle.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2833,17 +12707,186 @@ signal.$(OBJEXT): $(CCAN_DIR)/list/list.h
signal.$(OBJEXT): $(CCAN_DIR)/str/str.h
signal.$(OBJEXT): $(hdrdir)/ruby.h
signal.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+signal.$(OBJEXT): $(top_srcdir)/internal/array.h
+signal.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+signal.$(OBJEXT): $(top_srcdir)/internal/eval.h
+signal.$(OBJEXT): $(top_srcdir)/internal/gc.h
+signal.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+signal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+signal.$(OBJEXT): $(top_srcdir)/internal/serial.h
+signal.$(OBJEXT): $(top_srcdir)/internal/signal.h
+signal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+signal.$(OBJEXT): $(top_srcdir)/internal/string.h
+signal.$(OBJEXT): $(top_srcdir)/internal/thread.h
+signal.$(OBJEXT): $(top_srcdir)/internal/vm.h
+signal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
signal.$(OBJEXT): {$(VPATH)}assert.h
+signal.$(OBJEXT): {$(VPATH)}atomic.h
+signal.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+signal.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+signal.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+signal.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+signal.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+signal.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+signal.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+signal.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+signal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
signal.$(OBJEXT): {$(VPATH)}config.h
signal.$(OBJEXT): {$(VPATH)}debug_counter.h
signal.$(OBJEXT): {$(VPATH)}defines.h
+signal.$(OBJEXT): {$(VPATH)}encoding.h
signal.$(OBJEXT): {$(VPATH)}eval_intern.h
signal.$(OBJEXT): {$(VPATH)}id.h
+signal.$(OBJEXT): {$(VPATH)}id_table.h
signal.$(OBJEXT): {$(VPATH)}intern.h
signal.$(OBJEXT): {$(VPATH)}internal.h
+signal.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+signal.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+signal.$(OBJEXT): {$(VPATH)}internal/assume.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+signal.$(OBJEXT): {$(VPATH)}internal/cast.h
+signal.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+signal.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+signal.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+signal.$(OBJEXT): {$(VPATH)}internal/config.h
+signal.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+signal.$(OBJEXT): {$(VPATH)}internal/core.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+signal.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+signal.$(OBJEXT): {$(VPATH)}internal/ctype.h
+signal.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+signal.$(OBJEXT): {$(VPATH)}internal/dosish.h
+signal.$(OBJEXT): {$(VPATH)}internal/error.h
+signal.$(OBJEXT): {$(VPATH)}internal/eval.h
+signal.$(OBJEXT): {$(VPATH)}internal/event.h
+signal.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+signal.$(OBJEXT): {$(VPATH)}internal/gc.h
+signal.$(OBJEXT): {$(VPATH)}internal/glob.h
+signal.$(OBJEXT): {$(VPATH)}internal/globals.h
+signal.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+signal.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+signal.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+signal.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+signal.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+signal.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+signal.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+signal.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+signal.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+signal.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+signal.$(OBJEXT): {$(VPATH)}internal/iterator.h
+signal.$(OBJEXT): {$(VPATH)}internal/memory.h
+signal.$(OBJEXT): {$(VPATH)}internal/method.h
+signal.$(OBJEXT): {$(VPATH)}internal/module.h
+signal.$(OBJEXT): {$(VPATH)}internal/newobj.h
+signal.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+signal.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+signal.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+signal.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+signal.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+signal.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+signal.$(OBJEXT): {$(VPATH)}internal/symbol.h
+signal.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+signal.$(OBJEXT): {$(VPATH)}internal/value.h
+signal.$(OBJEXT): {$(VPATH)}internal/value_type.h
+signal.$(OBJEXT): {$(VPATH)}internal/variable.h
+signal.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+signal.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
signal.$(OBJEXT): {$(VPATH)}method.h
signal.$(OBJEXT): {$(VPATH)}missing.h
signal.$(OBJEXT): {$(VPATH)}node.h
+signal.$(OBJEXT): {$(VPATH)}onigmo.h
+signal.$(OBJEXT): {$(VPATH)}oniguruma.h
+signal.$(OBJEXT): {$(VPATH)}ractor.h
+signal.$(OBJEXT): {$(VPATH)}ractor_core.h
signal.$(OBJEXT): {$(VPATH)}ruby_assert.h
signal.$(OBJEXT): {$(VPATH)}ruby_atomic.h
signal.$(OBJEXT): {$(VPATH)}signal.c
@@ -2852,16 +12895,186 @@ signal.$(OBJEXT): {$(VPATH)}subst.h
signal.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
signal.$(OBJEXT): {$(VPATH)}thread_native.h
signal.$(OBJEXT): {$(VPATH)}vm_core.h
+signal.$(OBJEXT): {$(VPATH)}vm_debug.h
signal.$(OBJEXT): {$(VPATH)}vm_opts.h
sprintf.$(OBJEXT): $(hdrdir)/ruby.h
sprintf.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/bits.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/class.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/error.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/gc.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/hash.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/object.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/serial.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/string.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/util.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/vm.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/warnings.h
sprintf.$(OBJEXT): {$(VPATH)}assert.h
+sprintf.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+sprintf.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+sprintf.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+sprintf.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+sprintf.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+sprintf.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+sprintf.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+sprintf.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+sprintf.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
sprintf.$(OBJEXT): {$(VPATH)}config.h
sprintf.$(OBJEXT): {$(VPATH)}defines.h
sprintf.$(OBJEXT): {$(VPATH)}encoding.h
sprintf.$(OBJEXT): {$(VPATH)}id.h
+sprintf.$(OBJEXT): {$(VPATH)}id_table.h
sprintf.$(OBJEXT): {$(VPATH)}intern.h
sprintf.$(OBJEXT): {$(VPATH)}internal.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/assume.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/cast.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/config.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/ctype.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/dosish.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/error.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/eval.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/event.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/gc.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/glob.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/globals.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/iterator.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/memory.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/method.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/module.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/newobj.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/symbol.h
+sprintf.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2873,23 +13086,333 @@ sprintf.$(OBJEXT): {$(VPATH)}subst.h
sprintf.$(OBJEXT): {$(VPATH)}vsnprintf.c
st.$(OBJEXT): $(hdrdir)/ruby.h
st.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+st.$(OBJEXT): $(top_srcdir)/internal/bits.h
+st.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+st.$(OBJEXT): $(top_srcdir)/internal/hash.h
+st.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+st.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+st.$(OBJEXT): $(top_srcdir)/internal/warnings.h
st.$(OBJEXT): {$(VPATH)}assert.h
+st.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+st.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+st.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+st.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+st.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+st.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+st.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+st.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+st.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
st.$(OBJEXT): {$(VPATH)}config.h
st.$(OBJEXT): {$(VPATH)}defines.h
st.$(OBJEXT): {$(VPATH)}intern.h
st.$(OBJEXT): {$(VPATH)}internal.h
+st.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+st.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+st.$(OBJEXT): {$(VPATH)}internal/assume.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+st.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+st.$(OBJEXT): {$(VPATH)}internal/cast.h
+st.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+st.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+st.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+st.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+st.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+st.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+st.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+st.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+st.$(OBJEXT): {$(VPATH)}internal/config.h
+st.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+st.$(OBJEXT): {$(VPATH)}internal/core.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+st.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+st.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+st.$(OBJEXT): {$(VPATH)}internal/ctype.h
+st.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+st.$(OBJEXT): {$(VPATH)}internal/dosish.h
+st.$(OBJEXT): {$(VPATH)}internal/error.h
+st.$(OBJEXT): {$(VPATH)}internal/eval.h
+st.$(OBJEXT): {$(VPATH)}internal/event.h
+st.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+st.$(OBJEXT): {$(VPATH)}internal/gc.h
+st.$(OBJEXT): {$(VPATH)}internal/glob.h
+st.$(OBJEXT): {$(VPATH)}internal/globals.h
+st.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+st.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+st.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+st.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+st.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+st.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+st.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+st.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+st.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+st.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+st.$(OBJEXT): {$(VPATH)}internal/iterator.h
+st.$(OBJEXT): {$(VPATH)}internal/memory.h
+st.$(OBJEXT): {$(VPATH)}internal/method.h
+st.$(OBJEXT): {$(VPATH)}internal/module.h
+st.$(OBJEXT): {$(VPATH)}internal/newobj.h
+st.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+st.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+st.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+st.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+st.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+st.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+st.$(OBJEXT): {$(VPATH)}internal/symbol.h
+st.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+st.$(OBJEXT): {$(VPATH)}internal/value.h
+st.$(OBJEXT): {$(VPATH)}internal/value_type.h
+st.$(OBJEXT): {$(VPATH)}internal/variable.h
+st.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
st.$(OBJEXT): {$(VPATH)}missing.h
st.$(OBJEXT): {$(VPATH)}st.c
st.$(OBJEXT): {$(VPATH)}st.h
st.$(OBJEXT): {$(VPATH)}subst.h
strftime.$(OBJEXT): $(hdrdir)/ruby.h
strftime.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/serial.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/string.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/util.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/vm.h
strftime.$(OBJEXT): {$(VPATH)}assert.h
+strftime.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+strftime.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+strftime.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+strftime.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+strftime.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+strftime.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+strftime.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+strftime.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+strftime.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
strftime.$(OBJEXT): {$(VPATH)}config.h
strftime.$(OBJEXT): {$(VPATH)}defines.h
strftime.$(OBJEXT): {$(VPATH)}encoding.h
strftime.$(OBJEXT): {$(VPATH)}intern.h
strftime.$(OBJEXT): {$(VPATH)}internal.h
+strftime.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+strftime.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+strftime.$(OBJEXT): {$(VPATH)}internal/assume.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+strftime.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+strftime.$(OBJEXT): {$(VPATH)}internal/cast.h
+strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+strftime.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+strftime.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+strftime.$(OBJEXT): {$(VPATH)}internal/config.h
+strftime.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+strftime.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+strftime.$(OBJEXT): {$(VPATH)}internal/ctype.h
+strftime.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+strftime.$(OBJEXT): {$(VPATH)}internal/dosish.h
+strftime.$(OBJEXT): {$(VPATH)}internal/error.h
+strftime.$(OBJEXT): {$(VPATH)}internal/eval.h
+strftime.$(OBJEXT): {$(VPATH)}internal/event.h
+strftime.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+strftime.$(OBJEXT): {$(VPATH)}internal/gc.h
+strftime.$(OBJEXT): {$(VPATH)}internal/glob.h
+strftime.$(OBJEXT): {$(VPATH)}internal/globals.h
+strftime.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+strftime.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+strftime.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+strftime.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+strftime.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+strftime.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+strftime.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+strftime.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+strftime.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+strftime.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+strftime.$(OBJEXT): {$(VPATH)}internal/iterator.h
+strftime.$(OBJEXT): {$(VPATH)}internal/memory.h
+strftime.$(OBJEXT): {$(VPATH)}internal/method.h
+strftime.$(OBJEXT): {$(VPATH)}internal/module.h
+strftime.$(OBJEXT): {$(VPATH)}internal/newobj.h
+strftime.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+strftime.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+strftime.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+strftime.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+strftime.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+strftime.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+strftime.$(OBJEXT): {$(VPATH)}internal/symbol.h
+strftime.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -2899,7 +13422,37 @@ strftime.$(OBJEXT): {$(VPATH)}subst.h
strftime.$(OBJEXT): {$(VPATH)}timev.h
string.$(OBJEXT): $(hdrdir)/ruby.h
string.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+string.$(OBJEXT): $(top_srcdir)/internal/array.h
+string.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+string.$(OBJEXT): $(top_srcdir)/internal/bits.h
+string.$(OBJEXT): $(top_srcdir)/internal/class.h
+string.$(OBJEXT): $(top_srcdir)/internal/compar.h
+string.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+string.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+string.$(OBJEXT): $(top_srcdir)/internal/error.h
+string.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+string.$(OBJEXT): $(top_srcdir)/internal/gc.h
+string.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+string.$(OBJEXT): $(top_srcdir)/internal/object.h
+string.$(OBJEXT): $(top_srcdir)/internal/proc.h
+string.$(OBJEXT): $(top_srcdir)/internal/re.h
+string.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+string.$(OBJEXT): $(top_srcdir)/internal/serial.h
+string.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+string.$(OBJEXT): $(top_srcdir)/internal/string.h
+string.$(OBJEXT): $(top_srcdir)/internal/transcode.h
+string.$(OBJEXT): $(top_srcdir)/internal/vm.h
+string.$(OBJEXT): $(top_srcdir)/internal/warnings.h
string.$(OBJEXT): {$(VPATH)}assert.h
+string.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+string.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+string.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+string.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+string.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+string.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+string.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+string.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+string.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
string.$(OBJEXT): {$(VPATH)}config.h
string.$(OBJEXT): {$(VPATH)}crypt.h
string.$(OBJEXT): {$(VPATH)}debug_counter.h
@@ -2908,9 +13461,152 @@ string.$(OBJEXT): {$(VPATH)}encindex.h
string.$(OBJEXT): {$(VPATH)}encoding.h
string.$(OBJEXT): {$(VPATH)}gc.h
string.$(OBJEXT): {$(VPATH)}id.h
+string.$(OBJEXT): {$(VPATH)}id_table.h
string.$(OBJEXT): {$(VPATH)}intern.h
string.$(OBJEXT): {$(VPATH)}internal.h
+string.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+string.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+string.$(OBJEXT): {$(VPATH)}internal/assume.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+string.$(OBJEXT): {$(VPATH)}internal/cast.h
+string.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+string.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+string.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+string.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+string.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+string.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+string.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+string.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+string.$(OBJEXT): {$(VPATH)}internal/config.h
+string.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+string.$(OBJEXT): {$(VPATH)}internal/core.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rmatch.h
+string.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+string.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+string.$(OBJEXT): {$(VPATH)}internal/ctype.h
+string.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+string.$(OBJEXT): {$(VPATH)}internal/dosish.h
+string.$(OBJEXT): {$(VPATH)}internal/error.h
+string.$(OBJEXT): {$(VPATH)}internal/eval.h
+string.$(OBJEXT): {$(VPATH)}internal/event.h
+string.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+string.$(OBJEXT): {$(VPATH)}internal/gc.h
+string.$(OBJEXT): {$(VPATH)}internal/glob.h
+string.$(OBJEXT): {$(VPATH)}internal/globals.h
+string.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+string.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+string.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+string.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+string.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+string.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+string.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+string.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+string.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+string.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+string.$(OBJEXT): {$(VPATH)}internal/iterator.h
+string.$(OBJEXT): {$(VPATH)}internal/memory.h
+string.$(OBJEXT): {$(VPATH)}internal/method.h
+string.$(OBJEXT): {$(VPATH)}internal/module.h
+string.$(OBJEXT): {$(VPATH)}internal/newobj.h
+string.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+string.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+string.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+string.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+string.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+string.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+string.$(OBJEXT): {$(VPATH)}internal/symbol.h
+string.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+string.$(OBJEXT): {$(VPATH)}internal/value.h
+string.$(OBJEXT): {$(VPATH)}internal/value_type.h
+string.$(OBJEXT): {$(VPATH)}internal/variable.h
+string.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+string.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
string.$(OBJEXT): {$(VPATH)}missing.h
+string.$(OBJEXT): {$(VPATH)}node.h
string.$(OBJEXT): {$(VPATH)}onigmo.h
string.$(OBJEXT): {$(VPATH)}oniguruma.h
string.$(OBJEXT): {$(VPATH)}probes.dmyh
@@ -2922,10 +13618,32 @@ string.$(OBJEXT): {$(VPATH)}st.h
string.$(OBJEXT): {$(VPATH)}string.c
string.$(OBJEXT): {$(VPATH)}subst.h
string.$(OBJEXT): {$(VPATH)}util.h
+string.$(OBJEXT): {$(VPATH)}vm_debug.h
+string.$(OBJEXT): {$(VPATH)}vm_sync.h
strlcat.$(OBJEXT): {$(VPATH)}config.h
+strlcat.$(OBJEXT): {$(VPATH)}internal/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)}missing.h
strlcat.$(OBJEXT): {$(VPATH)}strlcat.c
strlcpy.$(OBJEXT): {$(VPATH)}config.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)}missing.h
strlcpy.$(OBJEXT): {$(VPATH)}strlcpy.c
struct.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
@@ -2934,15 +13652,186 @@ struct.$(OBJEXT): $(CCAN_DIR)/list/list.h
struct.$(OBJEXT): $(CCAN_DIR)/str/str.h
struct.$(OBJEXT): $(hdrdir)/ruby.h
struct.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+struct.$(OBJEXT): $(top_srcdir)/internal/array.h
+struct.$(OBJEXT): $(top_srcdir)/internal/class.h
+struct.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+struct.$(OBJEXT): $(top_srcdir)/internal/error.h
+struct.$(OBJEXT): $(top_srcdir)/internal/gc.h
+struct.$(OBJEXT): $(top_srcdir)/internal/hash.h
+struct.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+struct.$(OBJEXT): $(top_srcdir)/internal/object.h
+struct.$(OBJEXT): $(top_srcdir)/internal/proc.h
+struct.$(OBJEXT): $(top_srcdir)/internal/serial.h
+struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+struct.$(OBJEXT): $(top_srcdir)/internal/string.h
+struct.$(OBJEXT): $(top_srcdir)/internal/struct.h
+struct.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+struct.$(OBJEXT): $(top_srcdir)/internal/vm.h
+struct.$(OBJEXT): $(top_srcdir)/internal/warnings.h
struct.$(OBJEXT): {$(VPATH)}assert.h
+struct.$(OBJEXT): {$(VPATH)}atomic.h
+struct.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+struct.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+struct.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+struct.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+struct.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+struct.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+struct.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+struct.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+struct.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+struct.$(OBJEXT): {$(VPATH)}builtin.h
struct.$(OBJEXT): {$(VPATH)}config.h
struct.$(OBJEXT): {$(VPATH)}defines.h
+struct.$(OBJEXT): {$(VPATH)}encoding.h
struct.$(OBJEXT): {$(VPATH)}id.h
+struct.$(OBJEXT): {$(VPATH)}id_table.h
struct.$(OBJEXT): {$(VPATH)}intern.h
struct.$(OBJEXT): {$(VPATH)}internal.h
+struct.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+struct.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+struct.$(OBJEXT): {$(VPATH)}internal/assume.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+struct.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+struct.$(OBJEXT): {$(VPATH)}internal/cast.h
+struct.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+struct.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+struct.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+struct.$(OBJEXT): {$(VPATH)}internal/config.h
+struct.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+struct.$(OBJEXT): {$(VPATH)}internal/core.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+struct.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+struct.$(OBJEXT): {$(VPATH)}internal/ctype.h
+struct.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+struct.$(OBJEXT): {$(VPATH)}internal/dosish.h
+struct.$(OBJEXT): {$(VPATH)}internal/error.h
+struct.$(OBJEXT): {$(VPATH)}internal/eval.h
+struct.$(OBJEXT): {$(VPATH)}internal/event.h
+struct.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+struct.$(OBJEXT): {$(VPATH)}internal/gc.h
+struct.$(OBJEXT): {$(VPATH)}internal/glob.h
+struct.$(OBJEXT): {$(VPATH)}internal/globals.h
+struct.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+struct.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+struct.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+struct.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+struct.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+struct.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+struct.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+struct.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+struct.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+struct.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+struct.$(OBJEXT): {$(VPATH)}internal/iterator.h
+struct.$(OBJEXT): {$(VPATH)}internal/memory.h
+struct.$(OBJEXT): {$(VPATH)}internal/method.h
+struct.$(OBJEXT): {$(VPATH)}internal/module.h
+struct.$(OBJEXT): {$(VPATH)}internal/newobj.h
+struct.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+struct.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+struct.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+struct.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+struct.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+struct.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+struct.$(OBJEXT): {$(VPATH)}internal/symbol.h
+struct.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+struct.$(OBJEXT): {$(VPATH)}internal/value.h
+struct.$(OBJEXT): {$(VPATH)}internal/value_type.h
+struct.$(OBJEXT): {$(VPATH)}internal/variable.h
+struct.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+struct.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
struct.$(OBJEXT): {$(VPATH)}method.h
struct.$(OBJEXT): {$(VPATH)}missing.h
struct.$(OBJEXT): {$(VPATH)}node.h
+struct.$(OBJEXT): {$(VPATH)}onigmo.h
+struct.$(OBJEXT): {$(VPATH)}oniguruma.h
struct.$(OBJEXT): {$(VPATH)}ruby_assert.h
struct.$(OBJEXT): {$(VPATH)}ruby_atomic.h
struct.$(OBJEXT): {$(VPATH)}st.h
@@ -2955,8 +13844,30 @@ struct.$(OBJEXT): {$(VPATH)}vm_core.h
struct.$(OBJEXT): {$(VPATH)}vm_opts.h
symbol.$(OBJEXT): $(hdrdir)/ruby.h
symbol.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/class.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/error.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/gc.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/hash.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/object.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/string.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/vm.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/warnings.h
symbol.$(OBJEXT): {$(VPATH)}assert.h
+symbol.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+symbol.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+symbol.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+symbol.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+symbol.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+symbol.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+symbol.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+symbol.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+symbol.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
symbol.$(OBJEXT): {$(VPATH)}config.h
+symbol.$(OBJEXT): {$(VPATH)}debug_counter.h
symbol.$(OBJEXT): {$(VPATH)}defines.h
symbol.$(OBJEXT): {$(VPATH)}encoding.h
symbol.$(OBJEXT): {$(VPATH)}gc.h
@@ -2966,7 +13877,148 @@ symbol.$(OBJEXT): {$(VPATH)}id_table.c
symbol.$(OBJEXT): {$(VPATH)}id_table.h
symbol.$(OBJEXT): {$(VPATH)}intern.h
symbol.$(OBJEXT): {$(VPATH)}internal.h
+symbol.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+symbol.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+symbol.$(OBJEXT): {$(VPATH)}internal/assume.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+symbol.$(OBJEXT): {$(VPATH)}internal/cast.h
+symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+symbol.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+symbol.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+symbol.$(OBJEXT): {$(VPATH)}internal/config.h
+symbol.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+symbol.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+symbol.$(OBJEXT): {$(VPATH)}internal/ctype.h
+symbol.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+symbol.$(OBJEXT): {$(VPATH)}internal/dosish.h
+symbol.$(OBJEXT): {$(VPATH)}internal/error.h
+symbol.$(OBJEXT): {$(VPATH)}internal/eval.h
+symbol.$(OBJEXT): {$(VPATH)}internal/event.h
+symbol.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+symbol.$(OBJEXT): {$(VPATH)}internal/gc.h
+symbol.$(OBJEXT): {$(VPATH)}internal/glob.h
+symbol.$(OBJEXT): {$(VPATH)}internal/globals.h
+symbol.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+symbol.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+symbol.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+symbol.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+symbol.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+symbol.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+symbol.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+symbol.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+symbol.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+symbol.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+symbol.$(OBJEXT): {$(VPATH)}internal/iterator.h
+symbol.$(OBJEXT): {$(VPATH)}internal/memory.h
+symbol.$(OBJEXT): {$(VPATH)}internal/method.h
+symbol.$(OBJEXT): {$(VPATH)}internal/module.h
+symbol.$(OBJEXT): {$(VPATH)}internal/newobj.h
+symbol.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+symbol.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+symbol.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+symbol.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+symbol.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+symbol.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+symbol.$(OBJEXT): {$(VPATH)}internal/symbol.h
+symbol.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+symbol.$(OBJEXT): {$(VPATH)}internal/value.h
+symbol.$(OBJEXT): {$(VPATH)}internal/value_type.h
+symbol.$(OBJEXT): {$(VPATH)}internal/variable.h
+symbol.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+symbol.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
symbol.$(OBJEXT): {$(VPATH)}missing.h
+symbol.$(OBJEXT): {$(VPATH)}node.h
symbol.$(OBJEXT): {$(VPATH)}onigmo.h
symbol.$(OBJEXT): {$(VPATH)}oniguruma.h
symbol.$(OBJEXT): {$(VPATH)}probes.dmyh
@@ -2976,13 +14028,47 @@ symbol.$(OBJEXT): {$(VPATH)}st.h
symbol.$(OBJEXT): {$(VPATH)}subst.h
symbol.$(OBJEXT): {$(VPATH)}symbol.c
symbol.$(OBJEXT): {$(VPATH)}symbol.h
+symbol.$(OBJEXT): {$(VPATH)}vm_debug.h
+symbol.$(OBJEXT): {$(VPATH)}vm_sync.h
thread.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
thread.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
thread.$(OBJEXT): $(CCAN_DIR)/list/list.h
thread.$(OBJEXT): $(CCAN_DIR)/str/str.h
thread.$(OBJEXT): $(hdrdir)/ruby.h
thread.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+thread.$(OBJEXT): $(top_srcdir)/internal/array.h
+thread.$(OBJEXT): $(top_srcdir)/internal/bits.h
+thread.$(OBJEXT): $(top_srcdir)/internal/class.h
+thread.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+thread.$(OBJEXT): $(top_srcdir)/internal/cont.h
+thread.$(OBJEXT): $(top_srcdir)/internal/error.h
+thread.$(OBJEXT): $(top_srcdir)/internal/gc.h
+thread.$(OBJEXT): $(top_srcdir)/internal/hash.h
+thread.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+thread.$(OBJEXT): $(top_srcdir)/internal/io.h
+thread.$(OBJEXT): $(top_srcdir)/internal/object.h
+thread.$(OBJEXT): $(top_srcdir)/internal/proc.h
+thread.$(OBJEXT): $(top_srcdir)/internal/scheduler.h
+thread.$(OBJEXT): $(top_srcdir)/internal/serial.h
+thread.$(OBJEXT): $(top_srcdir)/internal/signal.h
+thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+thread.$(OBJEXT): $(top_srcdir)/internal/string.h
+thread.$(OBJEXT): $(top_srcdir)/internal/thread.h
+thread.$(OBJEXT): $(top_srcdir)/internal/time.h
+thread.$(OBJEXT): $(top_srcdir)/internal/vm.h
+thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+thread.$(OBJEXT): {$(VPATH)}$(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)}config.h
thread.$(OBJEXT): {$(VPATH)}debug.h
thread.$(OBJEXT): {$(VPATH)}debug_counter.h
@@ -2992,8 +14078,149 @@ thread.$(OBJEXT): {$(VPATH)}eval_intern.h
thread.$(OBJEXT): {$(VPATH)}gc.h
thread.$(OBJEXT): {$(VPATH)}hrtime.h
thread.$(OBJEXT): {$(VPATH)}id.h
+thread.$(OBJEXT): {$(VPATH)}id_table.h
thread.$(OBJEXT): {$(VPATH)}intern.h
thread.$(OBJEXT): {$(VPATH)}internal.h
+thread.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+thread.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+thread.$(OBJEXT): {$(VPATH)}internal/assume.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+thread.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+thread.$(OBJEXT): {$(VPATH)}internal/cast.h
+thread.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+thread.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+thread.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+thread.$(OBJEXT): {$(VPATH)}internal/config.h
+thread.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+thread.$(OBJEXT): {$(VPATH)}internal/core.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+thread.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+thread.$(OBJEXT): {$(VPATH)}internal/ctype.h
+thread.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+thread.$(OBJEXT): {$(VPATH)}internal/dosish.h
+thread.$(OBJEXT): {$(VPATH)}internal/error.h
+thread.$(OBJEXT): {$(VPATH)}internal/eval.h
+thread.$(OBJEXT): {$(VPATH)}internal/event.h
+thread.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+thread.$(OBJEXT): {$(VPATH)}internal/gc.h
+thread.$(OBJEXT): {$(VPATH)}internal/glob.h
+thread.$(OBJEXT): {$(VPATH)}internal/globals.h
+thread.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+thread.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+thread.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+thread.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+thread.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+thread.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+thread.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+thread.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+thread.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+thread.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+thread.$(OBJEXT): {$(VPATH)}internal/iterator.h
+thread.$(OBJEXT): {$(VPATH)}internal/memory.h
+thread.$(OBJEXT): {$(VPATH)}internal/method.h
+thread.$(OBJEXT): {$(VPATH)}internal/module.h
+thread.$(OBJEXT): {$(VPATH)}internal/newobj.h
+thread.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+thread.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+thread.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+thread.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+thread.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+thread.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+thread.$(OBJEXT): {$(VPATH)}internal/symbol.h
+thread.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -3002,6 +14229,8 @@ thread.$(OBJEXT): {$(VPATH)}mjit.h
thread.$(OBJEXT): {$(VPATH)}node.h
thread.$(OBJEXT): {$(VPATH)}onigmo.h
thread.$(OBJEXT): {$(VPATH)}oniguruma.h
+thread.$(OBJEXT): {$(VPATH)}ractor.h
+thread.$(OBJEXT): {$(VPATH)}ractor_core.h
thread.$(OBJEXT): {$(VPATH)}ruby_assert.h
thread.$(OBJEXT): {$(VPATH)}ruby_atomic.h
thread.$(OBJEXT): {$(VPATH)}st.h
@@ -3014,32 +14243,363 @@ thread.$(OBJEXT): {$(VPATH)}thread_native.h
thread.$(OBJEXT): {$(VPATH)}thread_sync.c
thread.$(OBJEXT): {$(VPATH)}timev.h
thread.$(OBJEXT): {$(VPATH)}vm_core.h
+thread.$(OBJEXT): {$(VPATH)}vm_debug.h
thread.$(OBJEXT): {$(VPATH)}vm_opts.h
+thread.$(OBJEXT): {$(VPATH)}vm_sync.h
time.$(OBJEXT): $(hdrdir)/ruby.h
time.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+time.$(OBJEXT): $(top_srcdir)/internal/array.h
+time.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+time.$(OBJEXT): $(top_srcdir)/internal/bits.h
+time.$(OBJEXT): $(top_srcdir)/internal/compar.h
+time.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+time.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+time.$(OBJEXT): $(top_srcdir)/internal/gc.h
+time.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+time.$(OBJEXT): $(top_srcdir)/internal/rational.h
+time.$(OBJEXT): $(top_srcdir)/internal/serial.h
+time.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+time.$(OBJEXT): $(top_srcdir)/internal/string.h
+time.$(OBJEXT): $(top_srcdir)/internal/time.h
+time.$(OBJEXT): $(top_srcdir)/internal/variable.h
+time.$(OBJEXT): $(top_srcdir)/internal/vm.h
+time.$(OBJEXT): $(top_srcdir)/internal/warnings.h
time.$(OBJEXT): {$(VPATH)}assert.h
+time.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+time.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+time.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+time.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+time.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+time.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+time.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+time.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+time.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
time.$(OBJEXT): {$(VPATH)}config.h
+time.$(OBJEXT): {$(VPATH)}constant.h
time.$(OBJEXT): {$(VPATH)}defines.h
time.$(OBJEXT): {$(VPATH)}encoding.h
time.$(OBJEXT): {$(VPATH)}id.h
+time.$(OBJEXT): {$(VPATH)}id_table.h
time.$(OBJEXT): {$(VPATH)}intern.h
time.$(OBJEXT): {$(VPATH)}internal.h
+time.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+time.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+time.$(OBJEXT): {$(VPATH)}internal/assume.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+time.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+time.$(OBJEXT): {$(VPATH)}internal/cast.h
+time.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+time.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+time.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+time.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+time.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+time.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+time.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+time.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+time.$(OBJEXT): {$(VPATH)}internal/config.h
+time.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+time.$(OBJEXT): {$(VPATH)}internal/core.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+time.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+time.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+time.$(OBJEXT): {$(VPATH)}internal/ctype.h
+time.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+time.$(OBJEXT): {$(VPATH)}internal/dosish.h
+time.$(OBJEXT): {$(VPATH)}internal/error.h
+time.$(OBJEXT): {$(VPATH)}internal/eval.h
+time.$(OBJEXT): {$(VPATH)}internal/event.h
+time.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+time.$(OBJEXT): {$(VPATH)}internal/gc.h
+time.$(OBJEXT): {$(VPATH)}internal/glob.h
+time.$(OBJEXT): {$(VPATH)}internal/globals.h
+time.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+time.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+time.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+time.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+time.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+time.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+time.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+time.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+time.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+time.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+time.$(OBJEXT): {$(VPATH)}internal/iterator.h
+time.$(OBJEXT): {$(VPATH)}internal/memory.h
+time.$(OBJEXT): {$(VPATH)}internal/method.h
+time.$(OBJEXT): {$(VPATH)}internal/module.h
+time.$(OBJEXT): {$(VPATH)}internal/newobj.h
+time.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+time.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+time.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+time.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+time.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+time.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+time.$(OBJEXT): {$(VPATH)}internal/symbol.h
+time.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+time.$(OBJEXT): {$(VPATH)}internal/value.h
+time.$(OBJEXT): {$(VPATH)}internal/value_type.h
+time.$(OBJEXT): {$(VPATH)}internal/variable.h
+time.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+time.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
time.$(OBJEXT): {$(VPATH)}missing.h
time.$(OBJEXT): {$(VPATH)}onigmo.h
time.$(OBJEXT): {$(VPATH)}oniguruma.h
+time.$(OBJEXT): {$(VPATH)}ruby_assert.h
time.$(OBJEXT): {$(VPATH)}st.h
time.$(OBJEXT): {$(VPATH)}subst.h
time.$(OBJEXT): {$(VPATH)}time.c
time.$(OBJEXT): {$(VPATH)}timev.h
transcode.$(OBJEXT): $(hdrdir)/ruby.h
transcode.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/array.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/class.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/gc.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/inits.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/object.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/serial.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/string.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/transcode.h
+transcode.$(OBJEXT): $(top_srcdir)/internal/warnings.h
transcode.$(OBJEXT): {$(VPATH)}assert.h
+transcode.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+transcode.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+transcode.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+transcode.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+transcode.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+transcode.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+transcode.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+transcode.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+transcode.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
transcode.$(OBJEXT): {$(VPATH)}config.h
transcode.$(OBJEXT): {$(VPATH)}defines.h
transcode.$(OBJEXT): {$(VPATH)}encoding.h
transcode.$(OBJEXT): {$(VPATH)}id.h
+transcode.$(OBJEXT): {$(VPATH)}id_table.h
transcode.$(OBJEXT): {$(VPATH)}intern.h
transcode.$(OBJEXT): {$(VPATH)}internal.h
+transcode.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+transcode.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+transcode.$(OBJEXT): {$(VPATH)}internal/assume.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+transcode.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+transcode.$(OBJEXT): {$(VPATH)}internal/cast.h
+transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+transcode.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+transcode.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+transcode.$(OBJEXT): {$(VPATH)}internal/config.h
+transcode.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+transcode.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+transcode.$(OBJEXT): {$(VPATH)}internal/ctype.h
+transcode.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+transcode.$(OBJEXT): {$(VPATH)}internal/dosish.h
+transcode.$(OBJEXT): {$(VPATH)}internal/error.h
+transcode.$(OBJEXT): {$(VPATH)}internal/eval.h
+transcode.$(OBJEXT): {$(VPATH)}internal/event.h
+transcode.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+transcode.$(OBJEXT): {$(VPATH)}internal/gc.h
+transcode.$(OBJEXT): {$(VPATH)}internal/glob.h
+transcode.$(OBJEXT): {$(VPATH)}internal/globals.h
+transcode.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+transcode.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+transcode.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+transcode.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+transcode.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+transcode.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+transcode.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+transcode.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+transcode.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+transcode.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+transcode.$(OBJEXT): {$(VPATH)}internal/iterator.h
+transcode.$(OBJEXT): {$(VPATH)}internal/memory.h
+transcode.$(OBJEXT): {$(VPATH)}internal/method.h
+transcode.$(OBJEXT): {$(VPATH)}internal/module.h
+transcode.$(OBJEXT): {$(VPATH)}internal/newobj.h
+transcode.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+transcode.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+transcode.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+transcode.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+transcode.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+transcode.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+transcode.$(OBJEXT): {$(VPATH)}internal/symbol.h
+transcode.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -3047,33 +14607,364 @@ transcode.$(OBJEXT): {$(VPATH)}st.h
transcode.$(OBJEXT): {$(VPATH)}subst.h
transcode.$(OBJEXT): {$(VPATH)}transcode.c
transcode.$(OBJEXT): {$(VPATH)}transcode_data.h
+transient_heap.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+transient_heap.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+transient_heap.$(OBJEXT): $(CCAN_DIR)/list/list.h
+transient_heap.$(OBJEXT): $(CCAN_DIR)/str/str.h
transient_heap.$(OBJEXT): $(hdrdir)/ruby.h
transient_heap.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/array.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/gc.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/hash.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/serial.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/struct.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/variable.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/vm.h
+transient_heap.$(OBJEXT): $(top_srcdir)/internal/warnings.h
transient_heap.$(OBJEXT): {$(VPATH)}assert.h
+transient_heap.$(OBJEXT): {$(VPATH)}atomic.h
+transient_heap.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+transient_heap.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+transient_heap.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+transient_heap.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+transient_heap.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+transient_heap.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+transient_heap.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+transient_heap.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+transient_heap.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
transient_heap.$(OBJEXT): {$(VPATH)}config.h
+transient_heap.$(OBJEXT): {$(VPATH)}constant.h
transient_heap.$(OBJEXT): {$(VPATH)}debug.h
transient_heap.$(OBJEXT): {$(VPATH)}debug_counter.h
transient_heap.$(OBJEXT): {$(VPATH)}defines.h
transient_heap.$(OBJEXT): {$(VPATH)}gc.h
+transient_heap.$(OBJEXT): {$(VPATH)}id.h
+transient_heap.$(OBJEXT): {$(VPATH)}id_table.h
transient_heap.$(OBJEXT): {$(VPATH)}intern.h
transient_heap.$(OBJEXT): {$(VPATH)}internal.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/assume.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/cast.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/config.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/ctype.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/dosish.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/error.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/eval.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/event.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/gc.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/glob.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/globals.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/iterator.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/memory.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/method.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/module.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/newobj.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/symbol.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/value.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/value_type.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/variable.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+transient_heap.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+transient_heap.$(OBJEXT): {$(VPATH)}method.h
transient_heap.$(OBJEXT): {$(VPATH)}missing.h
transient_heap.$(OBJEXT): {$(VPATH)}node.h
transient_heap.$(OBJEXT): {$(VPATH)}ruby_assert.h
+transient_heap.$(OBJEXT): {$(VPATH)}ruby_atomic.h
transient_heap.$(OBJEXT): {$(VPATH)}st.h
transient_heap.$(OBJEXT): {$(VPATH)}subst.h
+transient_heap.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+transient_heap.$(OBJEXT): {$(VPATH)}thread_native.h
transient_heap.$(OBJEXT): {$(VPATH)}transient_heap.c
transient_heap.$(OBJEXT): {$(VPATH)}transient_heap.h
+transient_heap.$(OBJEXT): {$(VPATH)}vm_core.h
transient_heap.$(OBJEXT): {$(VPATH)}vm_debug.h
+transient_heap.$(OBJEXT): {$(VPATH)}vm_opts.h
+transient_heap.$(OBJEXT): {$(VPATH)}vm_sync.h
util.$(OBJEXT): $(hdrdir)/ruby.h
util.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+util.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+util.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+util.$(OBJEXT): $(top_srcdir)/internal/util.h
+util.$(OBJEXT): $(top_srcdir)/internal/warnings.h
util.$(OBJEXT): {$(VPATH)}assert.h
+util.$(OBJEXT): {$(VPATH)}atomic.h
+util.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+util.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+util.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+util.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+util.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+util.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+util.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+util.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+util.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
util.$(OBJEXT): {$(VPATH)}config.h
util.$(OBJEXT): {$(VPATH)}defines.h
util.$(OBJEXT): {$(VPATH)}dtoa.c
util.$(OBJEXT): {$(VPATH)}intern.h
util.$(OBJEXT): {$(VPATH)}internal.h
+util.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+util.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+util.$(OBJEXT): {$(VPATH)}internal/assume.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+util.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+util.$(OBJEXT): {$(VPATH)}internal/cast.h
+util.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+util.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+util.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+util.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+util.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+util.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+util.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+util.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+util.$(OBJEXT): {$(VPATH)}internal/config.h
+util.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+util.$(OBJEXT): {$(VPATH)}internal/core.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+util.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+util.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+util.$(OBJEXT): {$(VPATH)}internal/ctype.h
+util.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+util.$(OBJEXT): {$(VPATH)}internal/dosish.h
+util.$(OBJEXT): {$(VPATH)}internal/error.h
+util.$(OBJEXT): {$(VPATH)}internal/eval.h
+util.$(OBJEXT): {$(VPATH)}internal/event.h
+util.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+util.$(OBJEXT): {$(VPATH)}internal/gc.h
+util.$(OBJEXT): {$(VPATH)}internal/glob.h
+util.$(OBJEXT): {$(VPATH)}internal/globals.h
+util.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+util.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+util.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+util.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+util.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+util.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+util.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+util.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+util.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+util.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+util.$(OBJEXT): {$(VPATH)}internal/iterator.h
+util.$(OBJEXT): {$(VPATH)}internal/memory.h
+util.$(OBJEXT): {$(VPATH)}internal/method.h
+util.$(OBJEXT): {$(VPATH)}internal/module.h
+util.$(OBJEXT): {$(VPATH)}internal/newobj.h
+util.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+util.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+util.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+util.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+util.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+util.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+util.$(OBJEXT): {$(VPATH)}internal/symbol.h
+util.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -3084,7 +14975,35 @@ variable.$(OBJEXT): $(CCAN_DIR)/list/list.h
variable.$(OBJEXT): $(CCAN_DIR)/str/str.h
variable.$(OBJEXT): $(hdrdir)/ruby.h
variable.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+variable.$(OBJEXT): $(top_srcdir)/internal/array.h
+variable.$(OBJEXT): $(top_srcdir)/internal/class.h
+variable.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+variable.$(OBJEXT): $(top_srcdir)/internal/error.h
+variable.$(OBJEXT): $(top_srcdir)/internal/eval.h
+variable.$(OBJEXT): $(top_srcdir)/internal/gc.h
+variable.$(OBJEXT): $(top_srcdir)/internal/hash.h
+variable.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+variable.$(OBJEXT): $(top_srcdir)/internal/object.h
+variable.$(OBJEXT): $(top_srcdir)/internal/re.h
+variable.$(OBJEXT): $(top_srcdir)/internal/serial.h
+variable.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+variable.$(OBJEXT): $(top_srcdir)/internal/string.h
+variable.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+variable.$(OBJEXT): $(top_srcdir)/internal/thread.h
+variable.$(OBJEXT): $(top_srcdir)/internal/variable.h
+variable.$(OBJEXT): $(top_srcdir)/internal/vm.h
+variable.$(OBJEXT): $(top_srcdir)/internal/warnings.h
variable.$(OBJEXT): {$(VPATH)}assert.h
+variable.$(OBJEXT): {$(VPATH)}atomic.h
+variable.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+variable.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+variable.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+variable.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+variable.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+variable.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+variable.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+variable.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+variable.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
variable.$(OBJEXT): {$(VPATH)}config.h
variable.$(OBJEXT): {$(VPATH)}constant.h
variable.$(OBJEXT): {$(VPATH)}debug_counter.h
@@ -3094,11 +15013,153 @@ variable.$(OBJEXT): {$(VPATH)}id.h
variable.$(OBJEXT): {$(VPATH)}id_table.h
variable.$(OBJEXT): {$(VPATH)}intern.h
variable.$(OBJEXT): {$(VPATH)}internal.h
+variable.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+variable.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+variable.$(OBJEXT): {$(VPATH)}internal/assume.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+variable.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+variable.$(OBJEXT): {$(VPATH)}internal/cast.h
+variable.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+variable.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+variable.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+variable.$(OBJEXT): {$(VPATH)}internal/config.h
+variable.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+variable.$(OBJEXT): {$(VPATH)}internal/core.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+variable.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+variable.$(OBJEXT): {$(VPATH)}internal/ctype.h
+variable.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+variable.$(OBJEXT): {$(VPATH)}internal/dosish.h
+variable.$(OBJEXT): {$(VPATH)}internal/error.h
+variable.$(OBJEXT): {$(VPATH)}internal/eval.h
+variable.$(OBJEXT): {$(VPATH)}internal/event.h
+variable.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+variable.$(OBJEXT): {$(VPATH)}internal/gc.h
+variable.$(OBJEXT): {$(VPATH)}internal/glob.h
+variable.$(OBJEXT): {$(VPATH)}internal/globals.h
+variable.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+variable.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+variable.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+variable.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+variable.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+variable.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+variable.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+variable.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+variable.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+variable.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+variable.$(OBJEXT): {$(VPATH)}internal/iterator.h
+variable.$(OBJEXT): {$(VPATH)}internal/memory.h
+variable.$(OBJEXT): {$(VPATH)}internal/method.h
+variable.$(OBJEXT): {$(VPATH)}internal/module.h
+variable.$(OBJEXT): {$(VPATH)}internal/newobj.h
+variable.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+variable.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+variable.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+variable.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+variable.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+variable.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+variable.$(OBJEXT): {$(VPATH)}internal/symbol.h
+variable.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+variable.$(OBJEXT): {$(VPATH)}internal/value.h
+variable.$(OBJEXT): {$(VPATH)}internal/value_type.h
+variable.$(OBJEXT): {$(VPATH)}internal/variable.h
+variable.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+variable.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
variable.$(OBJEXT): {$(VPATH)}method.h
variable.$(OBJEXT): {$(VPATH)}missing.h
variable.$(OBJEXT): {$(VPATH)}node.h
variable.$(OBJEXT): {$(VPATH)}onigmo.h
variable.$(OBJEXT): {$(VPATH)}oniguruma.h
+variable.$(OBJEXT): {$(VPATH)}ractor.h
+variable.$(OBJEXT): {$(VPATH)}ractor_core.h
variable.$(OBJEXT): {$(VPATH)}ruby_assert.h
variable.$(OBJEXT): {$(VPATH)}ruby_atomic.h
variable.$(OBJEXT): {$(VPATH)}st.h
@@ -3110,7 +15171,9 @@ variable.$(OBJEXT): {$(VPATH)}util.h
variable.$(OBJEXT): {$(VPATH)}variable.c
variable.$(OBJEXT): {$(VPATH)}variable.h
variable.$(OBJEXT): {$(VPATH)}vm_core.h
+variable.$(OBJEXT): {$(VPATH)}vm_debug.h
variable.$(OBJEXT): {$(VPATH)}vm_opts.h
+variable.$(OBJEXT): {$(VPATH)}vm_sync.h
version.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
version.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
version.$(OBJEXT): $(CCAN_DIR)/list/list.h
@@ -3118,15 +15181,173 @@ version.$(OBJEXT): $(CCAN_DIR)/str/str.h
version.$(OBJEXT): $(hdrdir)/ruby.h
version.$(OBJEXT): $(hdrdir)/ruby/ruby.h
version.$(OBJEXT): $(hdrdir)/ruby/version.h
+version.$(OBJEXT): $(top_srcdir)/internal/array.h
+version.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+version.$(OBJEXT): $(top_srcdir)/internal/gc.h
+version.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+version.$(OBJEXT): $(top_srcdir)/internal/serial.h
+version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+version.$(OBJEXT): $(top_srcdir)/internal/vm.h
+version.$(OBJEXT): $(top_srcdir)/internal/warnings.h
version.$(OBJEXT): $(top_srcdir)/revision.h
version.$(OBJEXT): $(top_srcdir)/version.h
version.$(OBJEXT): {$(VPATH)}assert.h
+version.$(OBJEXT): {$(VPATH)}atomic.h
+version.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+version.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+version.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+version.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+version.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+version.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+version.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+version.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+version.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
version.$(OBJEXT): {$(VPATH)}config.h
version.$(OBJEXT): {$(VPATH)}debug_counter.h
version.$(OBJEXT): {$(VPATH)}defines.h
version.$(OBJEXT): {$(VPATH)}id.h
version.$(OBJEXT): {$(VPATH)}intern.h
version.$(OBJEXT): {$(VPATH)}internal.h
+version.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+version.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+version.$(OBJEXT): {$(VPATH)}internal/assume.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+version.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+version.$(OBJEXT): {$(VPATH)}internal/cast.h
+version.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+version.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+version.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+version.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+version.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+version.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+version.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+version.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+version.$(OBJEXT): {$(VPATH)}internal/config.h
+version.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+version.$(OBJEXT): {$(VPATH)}internal/core.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+version.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+version.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+version.$(OBJEXT): {$(VPATH)}internal/ctype.h
+version.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+version.$(OBJEXT): {$(VPATH)}internal/dosish.h
+version.$(OBJEXT): {$(VPATH)}internal/error.h
+version.$(OBJEXT): {$(VPATH)}internal/eval.h
+version.$(OBJEXT): {$(VPATH)}internal/event.h
+version.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+version.$(OBJEXT): {$(VPATH)}internal/gc.h
+version.$(OBJEXT): {$(VPATH)}internal/glob.h
+version.$(OBJEXT): {$(VPATH)}internal/globals.h
+version.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+version.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+version.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+version.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+version.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+version.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+version.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+version.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+version.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+version.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+version.$(OBJEXT): {$(VPATH)}internal/iterator.h
+version.$(OBJEXT): {$(VPATH)}internal/memory.h
+version.$(OBJEXT): {$(VPATH)}internal/method.h
+version.$(OBJEXT): {$(VPATH)}internal/module.h
+version.$(OBJEXT): {$(VPATH)}internal/newobj.h
+version.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+version.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+version.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+version.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+version.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+version.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+version.$(OBJEXT): {$(VPATH)}internal/symbol.h
+version.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+version.$(OBJEXT): {$(VPATH)}internal/value.h
+version.$(OBJEXT): {$(VPATH)}internal/value_type.h
+version.$(OBJEXT): {$(VPATH)}internal/variable.h
+version.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+version.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
version.$(OBJEXT): {$(VPATH)}method.h
version.$(OBJEXT): {$(VPATH)}missing.h
version.$(OBJEXT): {$(VPATH)}mjit.h
@@ -3146,13 +15367,53 @@ vm.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm.$(OBJEXT): $(hdrdir)/ruby.h
vm.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+vm.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+vm.$(OBJEXT): $(top_srcdir)/internal/bits.h
+vm.$(OBJEXT): $(top_srcdir)/internal/class.h
+vm.$(OBJEXT): $(top_srcdir)/internal/compar.h
+vm.$(OBJEXT): $(top_srcdir)/internal/compile.h
+vm.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+vm.$(OBJEXT): $(top_srcdir)/internal/cont.h
+vm.$(OBJEXT): $(top_srcdir)/internal/error.h
+vm.$(OBJEXT): $(top_srcdir)/internal/eval.h
+vm.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+vm.$(OBJEXT): $(top_srcdir)/internal/gc.h
+vm.$(OBJEXT): $(top_srcdir)/internal/hash.h
+vm.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm.$(OBJEXT): $(top_srcdir)/internal/inits.h
+vm.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+vm.$(OBJEXT): $(top_srcdir)/internal/object.h
+vm.$(OBJEXT): $(top_srcdir)/internal/parse.h
+vm.$(OBJEXT): $(top_srcdir)/internal/proc.h
+vm.$(OBJEXT): $(top_srcdir)/internal/random.h
+vm.$(OBJEXT): $(top_srcdir)/internal/re.h
+vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+vm.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm.$(OBJEXT): $(top_srcdir)/internal/string.h
+vm.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+vm.$(OBJEXT): $(top_srcdir)/internal/variable.h
+vm.$(OBJEXT): $(top_srcdir)/internal/vm.h
+vm.$(OBJEXT): $(top_srcdir)/internal/warnings.h
vm.$(OBJEXT): {$(VPATH)}assert.h
+vm.$(OBJEXT): {$(VPATH)}atomic.h
+vm.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+vm.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+vm.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+vm.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+vm.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+vm.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+vm.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+vm.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+vm.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm.$(OBJEXT): {$(VPATH)}builtin.h
vm.$(OBJEXT): {$(VPATH)}config.h
vm.$(OBJEXT): {$(VPATH)}constant.h
vm.$(OBJEXT): {$(VPATH)}debug_counter.h
vm.$(OBJEXT): {$(VPATH)}defines.h
vm.$(OBJEXT): {$(VPATH)}defs/opt_operand.def
+vm.$(OBJEXT): {$(VPATH)}encoding.h
vm.$(OBJEXT): {$(VPATH)}eval_intern.h
vm.$(OBJEXT): {$(VPATH)}gc.h
vm.$(OBJEXT): {$(VPATH)}id.h
@@ -3162,14 +15423,158 @@ vm.$(OBJEXT): {$(VPATH)}insns.inc
vm.$(OBJEXT): {$(VPATH)}insns_info.inc
vm.$(OBJEXT): {$(VPATH)}intern.h
vm.$(OBJEXT): {$(VPATH)}internal.h
+vm.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+vm.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+vm.$(OBJEXT): {$(VPATH)}internal/assume.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+vm.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+vm.$(OBJEXT): {$(VPATH)}internal/cast.h
+vm.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+vm.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+vm.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+vm.$(OBJEXT): {$(VPATH)}internal/config.h
+vm.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+vm.$(OBJEXT): {$(VPATH)}internal/core.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+vm.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+vm.$(OBJEXT): {$(VPATH)}internal/ctype.h
+vm.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+vm.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm.$(OBJEXT): {$(VPATH)}internal/error.h
+vm.$(OBJEXT): {$(VPATH)}internal/eval.h
+vm.$(OBJEXT): {$(VPATH)}internal/event.h
+vm.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+vm.$(OBJEXT): {$(VPATH)}internal/gc.h
+vm.$(OBJEXT): {$(VPATH)}internal/glob.h
+vm.$(OBJEXT): {$(VPATH)}internal/globals.h
+vm.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+vm.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+vm.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+vm.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+vm.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+vm.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+vm.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+vm.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+vm.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+vm.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+vm.$(OBJEXT): {$(VPATH)}internal/iterator.h
+vm.$(OBJEXT): {$(VPATH)}internal/memory.h
+vm.$(OBJEXT): {$(VPATH)}internal/method.h
+vm.$(OBJEXT): {$(VPATH)}internal/module.h
+vm.$(OBJEXT): {$(VPATH)}internal/newobj.h
+vm.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+vm.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+vm.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+vm.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+vm.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+vm.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm.$(OBJEXT): {$(VPATH)}internal/symbol.h
+vm.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+vm.$(OBJEXT): {$(VPATH)}internal/value.h
+vm.$(OBJEXT): {$(VPATH)}internal/value_type.h
+vm.$(OBJEXT): {$(VPATH)}internal/variable.h
+vm.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+vm.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
vm.$(OBJEXT): {$(VPATH)}iseq.h
vm.$(OBJEXT): {$(VPATH)}method.h
vm.$(OBJEXT): {$(VPATH)}missing.h
vm.$(OBJEXT): {$(VPATH)}mjit.h
vm.$(OBJEXT): {$(VPATH)}node.h
+vm.$(OBJEXT): {$(VPATH)}onigmo.h
+vm.$(OBJEXT): {$(VPATH)}oniguruma.h
vm.$(OBJEXT): {$(VPATH)}probes.dmyh
vm.$(OBJEXT): {$(VPATH)}probes.h
vm.$(OBJEXT): {$(VPATH)}probes_helper.h
+vm.$(OBJEXT): {$(VPATH)}ractor.h
+vm.$(OBJEXT): {$(VPATH)}ractor_core.h
vm.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm.$(OBJEXT): {$(VPATH)}ruby_atomic.h
vm.$(OBJEXT): {$(VPATH)}st.h
@@ -3182,6 +15587,7 @@ vm.$(OBJEXT): {$(VPATH)}vm.h
vm.$(OBJEXT): {$(VPATH)}vm.inc
vm.$(OBJEXT): {$(VPATH)}vm_args.c
vm.$(OBJEXT): {$(VPATH)}vm_call_iseq_optimized.inc
+vm.$(OBJEXT): {$(VPATH)}vm_callinfo.h
vm.$(OBJEXT): {$(VPATH)}vm_core.h
vm.$(OBJEXT): {$(VPATH)}vm_debug.h
vm.$(OBJEXT): {$(VPATH)}vm_eval.c
@@ -3191,6 +15597,7 @@ 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_backtrace.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
vm_backtrace.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
@@ -3198,7 +15605,25 @@ vm_backtrace.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm_backtrace.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm_backtrace.$(OBJEXT): $(hdrdir)/ruby.h
vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/gc.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
vm_backtrace.$(OBJEXT): {$(VPATH)}assert.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}atomic.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_backtrace.$(OBJEXT): {$(VPATH)}config.h
vm_backtrace.$(OBJEXT): {$(VPATH)}debug.h
vm_backtrace.$(OBJEXT): {$(VPATH)}defines.h
@@ -3207,6 +15632,146 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}eval_intern.h
vm_backtrace.$(OBJEXT): {$(VPATH)}id.h
vm_backtrace.$(OBJEXT): {$(VPATH)}intern.h
vm_backtrace.$(OBJEXT): {$(VPATH)}internal.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/assume.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/cast.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/config.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/ctype.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/error.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/eval.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/event.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/gc.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/glob.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/globals.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/iterator.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/memory.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/method.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/module.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/newobj.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/symbol.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/token_paste.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
@@ -3228,19 +15793,182 @@ vm_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm_dump.$(OBJEXT): $(hdrdir)/ruby.h
vm_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/warnings.h
vm_dump.$(OBJEXT): {$(VPATH)}addr2line.h
vm_dump.$(OBJEXT): {$(VPATH)}assert.h
+vm_dump.$(OBJEXT): {$(VPATH)}atomic.h
+vm_dump.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+vm_dump.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+vm_dump.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+vm_dump.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+vm_dump.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+vm_dump.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+vm_dump.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+vm_dump.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+vm_dump.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_dump.$(OBJEXT): {$(VPATH)}config.h
+vm_dump.$(OBJEXT): {$(VPATH)}constant.h
vm_dump.$(OBJEXT): {$(VPATH)}defines.h
vm_dump.$(OBJEXT): {$(VPATH)}gc.h
vm_dump.$(OBJEXT): {$(VPATH)}id.h
+vm_dump.$(OBJEXT): {$(VPATH)}id_table.h
vm_dump.$(OBJEXT): {$(VPATH)}intern.h
vm_dump.$(OBJEXT): {$(VPATH)}internal.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/assume.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/cast.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/config.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/ctype.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/error.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/eval.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/event.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/gc.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/glob.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/globals.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/iterator.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/memory.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/method.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/module.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/newobj.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/symbol.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/value.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/value_type.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/variable.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
vm_dump.$(OBJEXT): {$(VPATH)}iseq.h
vm_dump.$(OBJEXT): {$(VPATH)}method.h
vm_dump.$(OBJEXT): {$(VPATH)}missing.h
vm_dump.$(OBJEXT): {$(VPATH)}node.h
vm_dump.$(OBJEXT): {$(VPATH)}procstat_vm.c
+vm_dump.$(OBJEXT): {$(VPATH)}ractor.h
+vm_dump.$(OBJEXT): {$(VPATH)}ractor_core.h
vm_dump.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_dump.$(OBJEXT): {$(VPATH)}ruby_atomic.h
vm_dump.$(OBJEXT): {$(VPATH)}st.h
@@ -3248,29 +15976,393 @@ 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.h
+vm_sync.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/vm.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_sync.$(OBJEXT): {$(VPATH)}addr2line.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)}gc.h
+vm_sync.$(OBJEXT): {$(VPATH)}id.h
+vm_sync.$(OBJEXT): {$(VPATH)}id_table.h
+vm_sync.$(OBJEXT): {$(VPATH)}intern.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/array.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/assume.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/cast.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/compilers.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/config.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/ctype.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/error.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/eval.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/event.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/gc.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/glob.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/globals.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/imemo.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/iterator.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/memory.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/method.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/module.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/newobj.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/serial.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/symbol.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/token_paste.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/vm.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/warnings.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+vm_sync.$(OBJEXT): {$(VPATH)}iseq.h
+vm_sync.$(OBJEXT): {$(VPATH)}method.h
+vm_sync.$(OBJEXT): {$(VPATH)}missing.h
+vm_sync.$(OBJEXT): {$(VPATH)}node.h
+vm_sync.$(OBJEXT): {$(VPATH)}procstat_vm.c
+vm_sync.$(OBJEXT): {$(VPATH)}ractor.h
+vm_sync.$(OBJEXT): {$(VPATH)}ractor_core.h
+vm_sync.$(OBJEXT): {$(VPATH)}ruby_assert.h
+vm_sync.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm_sync.$(OBJEXT): {$(VPATH)}st.h
+vm_sync.$(OBJEXT): {$(VPATH)}subst.h
+vm_sync.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+vm_sync.$(OBJEXT): {$(VPATH)}thread_native.h
+vm_sync.$(OBJEXT): {$(VPATH)}vm_core.h
+vm_sync.$(OBJEXT): {$(VPATH)}vm_debug.h
+vm_sync.$(OBJEXT): {$(VPATH)}vm_opts.h
+vm_sync.$(OBJEXT): {$(VPATH)}vm_sync.c
+vm_sync.$(OBJEXT): {$(VPATH)}vm_sync.h
vm_trace.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
vm_trace.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
vm_trace.$(OBJEXT): $(CCAN_DIR)/list/list.h
vm_trace.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm_trace.$(OBJEXT): $(hdrdir)/ruby.h
vm_trace.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
vm_trace.$(OBJEXT): {$(VPATH)}assert.h
+vm_trace.$(OBJEXT): {$(VPATH)}atomic.h
+vm_trace.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+vm_trace.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+vm_trace.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+vm_trace.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+vm_trace.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+vm_trace.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+vm_trace.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+vm_trace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
vm_trace.$(OBJEXT): {$(VPATH)}builtin.h
vm_trace.$(OBJEXT): {$(VPATH)}config.h
vm_trace.$(OBJEXT): {$(VPATH)}debug.h
vm_trace.$(OBJEXT): {$(VPATH)}debug_counter.h
vm_trace.$(OBJEXT): {$(VPATH)}defines.h
+vm_trace.$(OBJEXT): {$(VPATH)}encoding.h
vm_trace.$(OBJEXT): {$(VPATH)}eval_intern.h
vm_trace.$(OBJEXT): {$(VPATH)}id.h
vm_trace.$(OBJEXT): {$(VPATH)}intern.h
vm_trace.$(OBJEXT): {$(VPATH)}internal.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/assume.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/cast.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/config.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/ctype.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/dosish.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/error.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/eval.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/event.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/gc.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/glob.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/globals.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/gc.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/iterator.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/memory.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/method.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/module.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/newobj.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/rgengc.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/symbol.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/token_paste.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/value.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/value_type.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/variable.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
vm_trace.$(OBJEXT): {$(VPATH)}iseq.h
vm_trace.$(OBJEXT): {$(VPATH)}method.h
vm_trace.$(OBJEXT): {$(VPATH)}missing.h
vm_trace.$(OBJEXT): {$(VPATH)}mjit.h
vm_trace.$(OBJEXT): {$(VPATH)}node.h
+vm_trace.$(OBJEXT): {$(VPATH)}onigmo.h
+vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h
+vm_trace.$(OBJEXT): {$(VPATH)}ractor.h
vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h
vm_trace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
vm_trace.$(OBJEXT): {$(VPATH)}st.h
diff --git a/compar.c b/compar.c
index 94072c9fc1..04d4ff8c70 100644
--- a/compar.c
+++ b/compar.c
@@ -9,9 +9,12 @@
**********************************************************************/
-#include "ruby/ruby.h"
#include "id.h"
#include "internal.h"
+#include "internal/compar.h"
+#include "internal/error.h"
+#include "internal/vm.h"
+#include "ruby/ruby.h"
VALUE rb_mComparable;
@@ -230,11 +233,9 @@ cmp_clamp(int argc, VALUE *argv, VALUE x)
}
if (!NIL_P(max)) {
if (excl) rb_raise(rb_eArgError, "cannot clamp with an exclusive range");
- if (!NIL_P(min) && cmpint(min, max) > 0) goto arg_error;
}
}
- else if (cmpint(min, max) > 0) {
- arg_error:
+ if (!NIL_P(min) && !NIL_P(max) && cmpint(min, max) > 0) {
rb_raise(rb_eArgError, "min argument must be smaller than max argument");
}
@@ -293,9 +294,6 @@ cmp_clamp(int argc, VALUE *argv, VALUE x)
void
Init_Comparable(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
rb_mComparable = rb_define_module("Comparable");
rb_define_method(rb_mComparable, "==", cmp_equal, 1);
rb_define_method(rb_mComparable, ">", cmp_gt, 1);
diff --git a/compile.c b/compile.c
index e2c24a119b..9844c145bc 100644
--- a/compile.c
+++ b/compile.c
@@ -9,25 +9,40 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/re.h"
-#include "ruby/util.h"
-#include "internal.h"
-#include "encindex.h"
+#include "ruby/internal/config.h"
#include <math.h>
+#ifdef HAVE_DLADDR
+# include <dlfcn.h>
+#endif
+
+#include "encindex.h"
+#include "gc.h"
+#include "id_table.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/compile.h"
+#include "internal/complex.h"
+#include "internal/encoding.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/rational.h"
+#include "internal/re.h"
+#include "internal/symbol.h"
+#include "internal/thread.h"
+#include "internal/variable.h"
+#include "iseq.h"
+#include "ruby/re.h"
+#include "ruby/util.h"
#include "vm_core.h"
+#include "vm_callinfo.h"
#include "vm_debug.h"
+
#include "builtin.h"
-#include "iseq.h"
#include "insns.inc"
#include "insns_info.inc"
-#include "id_table.h"
-#include "gc.h"
-
-#ifdef HAVE_DLADDR
-# include <dlfcn.h>
-#endif
#undef RUBY_UNTYPED_DATA_WARNING
#define RUBY_UNTYPED_DATA_WARNING 0
@@ -176,6 +191,7 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO};
#endif
#if CPDEBUG > 1 || CPDEBUG < 0
+#undef printf
#define printf ruby_debug_printf
#define debugs if (compile_debug_print_indent(1)) ruby_debug_printf
#define debug_compile(msg, v) ((void)(compile_debug_print_indent(1) && fputs((msg), stderr)), (v))
@@ -267,41 +283,6 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO};
#define ADD_TRACE_WITH_DATA(seq, event, data) \
ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), (data)))
-
-#define DECL_BRANCH_BASE(branches, first_line, first_column, last_line, last_column, type) \
- do { \
- if (ISEQ_COVERAGE(iseq) && \
- ISEQ_BRANCH_COVERAGE(iseq) && \
- (first_line) > 0) { \
- VALUE structure = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 0); \
- branches = rb_ary_tmp_new(5); \
- rb_ary_push(structure, branches); \
- rb_ary_push(branches, ID2SYM(rb_intern(type))); \
- rb_ary_push(branches, INT2FIX(first_line)); \
- rb_ary_push(branches, INT2FIX(first_column)); \
- rb_ary_push(branches, INT2FIX(last_line)); \
- rb_ary_push(branches, INT2FIX(last_column)); \
- } \
- } while (0)
-#define ADD_TRACE_BRANCH_COVERAGE(seq, first_line, first_column, last_line, last_column, type, branches) \
- do { \
- if (ISEQ_COVERAGE(iseq) && \
- ISEQ_BRANCH_COVERAGE(iseq) && \
- (first_line) > 0) { \
- VALUE counters = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 1); \
- long counter_idx = RARRAY_LEN(counters); \
- rb_ary_push(counters, INT2FIX(0)); \
- rb_ary_push(branches, ID2SYM(rb_intern(type))); \
- rb_ary_push(branches, INT2FIX(first_line)); \
- rb_ary_push(branches, INT2FIX(first_column)); \
- rb_ary_push(branches, INT2FIX(last_line)); \
- rb_ary_push(branches, INT2FIX(last_column)); \
- rb_ary_push(branches, INT2FIX(counter_idx)); \
- ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx); \
- ADD_INSN(seq, last_line, nop); \
- } \
- } while (0)
-
static void iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int idx, int level);
static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int idx, int level);
@@ -510,6 +491,7 @@ static int iseq_set_exception_table(rb_iseq_t *iseq);
static int iseq_set_optargs_table(rb_iseq_t *iseq);
static int compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr);
+static int compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int method_call_keywords, int popped);
/*
* To make Array to LinkedList, use link_anchor
@@ -551,6 +533,8 @@ static void
verify_call_cache(rb_iseq_t *iseq)
{
#if CPDEBUG
+ // fprintf(stderr, "ci_size:%d\t", iseq->body->ci_size); rp(iseq);
+
VALUE *original = rb_iseq_original_iseq(iseq);
size_t i = 0;
while (i < iseq->body->iseq_size) {
@@ -559,16 +543,27 @@ verify_call_cache(rb_iseq_t *iseq)
for (int j=0; types[j]; j++) {
if (types[j] == TS_CALLDATA) {
- struct rb_call_cache cc;
struct rb_call_data *cd = (struct rb_call_data *)original[i+j+1];
- MEMZERO(&cc, cc, 1);
- if (memcmp(&cc, &cd->cc, sizeof(cc))) {
- rb_bug("call cache not zero for fresh iseq");
+ const struct rb_callinfo *ci = cd->ci;
+ const struct rb_callcache *cc = cd->cc;
+ if (cc != vm_cc_empty()) {
+ vm_ci_dump(ci);
+ rb_bug("call cache is not initialized by vm_cc_empty()");
}
}
}
i += insn_len(insn);
}
+
+ for (unsigned int i=0; i<iseq->body->ci_size; i++) {
+ struct rb_call_data *cd = &iseq->body->call_data[i];
+ const struct rb_callinfo *ci = cd->ci;
+ const struct rb_callcache *cc = cd->cc;
+ if (cc != NULL && cc != vm_cc_empty()) {
+ vm_ci_dump(ci);
+ rb_bug("call cache is not initialized by vm_cc_empty()");
+ }
+ }
#endif
}
@@ -602,6 +597,96 @@ APPEND_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *before, LI
#define APPEND_ELEM(anchor, before, elem) APPEND_ELEM(iseq, (anchor), (before), (elem))
#endif
+static int
+branch_coverage_valid_p(rb_iseq_t *iseq, int first_line)
+{
+ if (!ISEQ_COVERAGE(iseq)) return 0;
+ if (!ISEQ_BRANCH_COVERAGE(iseq)) return 0;
+ if (first_line <= 0) return 0;
+ return 1;
+}
+
+static VALUE
+decl_branch_base(rb_iseq_t *iseq, const NODE *node, const char *type)
+{
+ const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node);
+ const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node);
+
+ if (!branch_coverage_valid_p(iseq, first_lineno)) return Qundef;
+
+ /*
+ * if !structure[node]
+ * structure[node] = [type, first_lineno, first_column, last_lineno, last_column, branches = {}]
+ * else
+ * branches = structure[node][5]
+ * end
+ */
+
+ VALUE structure = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 0);
+ VALUE key = (VALUE)node | 1; // FIXNUM for hash key
+ VALUE branch_base = rb_hash_aref(structure, key);
+ VALUE branches;
+
+ if (NIL_P(branch_base)) {
+ branch_base = rb_ary_tmp_new(6);
+ rb_hash_aset(structure, key, branch_base);
+ rb_ary_push(branch_base, ID2SYM(rb_intern(type)));
+ rb_ary_push(branch_base, INT2FIX(first_lineno));
+ rb_ary_push(branch_base, INT2FIX(first_column));
+ rb_ary_push(branch_base, INT2FIX(last_lineno));
+ rb_ary_push(branch_base, INT2FIX(last_column));
+ branches = rb_hash_new();
+ rb_obj_hide(branches);
+ rb_ary_push(branch_base, branches);
+ }
+ else {
+ branches = RARRAY_AREF(branch_base, 5);
+ }
+
+ return branches;
+}
+
+static void
+add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *node, int branch_id, const char *type, VALUE branches)
+{
+ const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node);
+ const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node);
+
+ if (!branch_coverage_valid_p(iseq, first_lineno)) return;
+
+ /*
+ * if !branches[branch_id]
+ * branches[branch_id] = [type, first_lineno, first_column, last_lineno, last_column, counter_idx]
+ * else
+ * counter_idx= branches[branch_id][5]
+ * end
+ */
+
+ VALUE key = INT2FIX(branch_id);
+ VALUE branch = rb_hash_aref(branches, key);
+ long counter_idx;
+
+ if (NIL_P(branch)) {
+ branch = rb_ary_tmp_new(6);
+ rb_hash_aset(branches, key, branch);
+ rb_ary_push(branch, ID2SYM(rb_intern(type)));
+ rb_ary_push(branch, INT2FIX(first_lineno));
+ rb_ary_push(branch, INT2FIX(first_column));
+ rb_ary_push(branch, INT2FIX(last_lineno));
+ rb_ary_push(branch, INT2FIX(last_column));
+ VALUE counters = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 1);
+ counter_idx = RARRAY_LEN(counters);
+ rb_ary_push(branch, LONG2FIX(counter_idx));
+ rb_ary_push(counters, INT2FIX(0));
+ }
+ else {
+ counter_idx = FIX2LONG(RARRAY_AREF(branch, 5));
+ }
+
+ ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx);
+ ADD_INSN(seq, last_lineno, nop);
+}
+
#define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line)
static int
@@ -646,7 +731,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
DECL_ANCHOR(ret);
INIT_ANCHOR(ret);
- if (imemo_type_p((VALUE)node, imemo_ifunc)) {
+ if (IMEMO_TYPE_P(node, imemo_ifunc)) {
rb_raise(rb_eArgError, "unexpected imemo_ifunc");
}
@@ -769,7 +854,7 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
encoded[i] = (VALUE)table[insn];
i += len;
}
- FL_SET(iseq, ISEQ_TRANSLATED);
+ FL_SET((VALUE)iseq, ISEQ_TRANSLATED);
#endif
return COMPILE_OK;
}
@@ -813,6 +898,16 @@ rb_iseq_original_iseq(const rb_iseq_t *iseq) /* cold path */
#define STRICT_ALIGNMENT
#endif
+/*
+ * Some OpenBSD platforms (including sparc64) require strict alignment.
+ */
+#if defined(__OpenBSD__)
+ #include <sys/endian.h>
+ #ifdef __STRICT_ALIGNMENT
+ #define STRICT_ALIGNMENT
+ #endif
+#endif
+
#ifdef STRICT_ALIGNMENT
#if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE
#define ALIGNMENT_SIZE SIZEOF_LONG_LONG
@@ -905,6 +1000,15 @@ compile_data_alloc2(rb_iseq_t *iseq, size_t x, size_t y)
return compile_data_alloc(iseq, size);
}
+static inline void *
+compile_data_calloc2(rb_iseq_t *iseq, size_t x, size_t y)
+{
+ size_t size = rb_size_mul_or_raise(x, y, rb_eRuntimeError);
+ void *p = compile_data_alloc(iseq, size);
+ memset(p, 0, size);
+ return p;
+}
+
static INSN *
compile_data_alloc_insn(rb_iseq_t *iseq)
{
@@ -1070,7 +1174,7 @@ APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *const anc1, LINK_ANCHOR *const anc2)
#if CPDEBUG && 0
static void
-debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor)
+debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor, LINK_ELEMENT *cur)
{
LINK_ELEMENT *list = FIRST_ELEMENT(anchor);
printf("----\n");
@@ -1078,19 +1182,19 @@ debug_list(ISEQ_ARG_DECLARE LINK_ANCHOR *const anchor)
anchor->anchor.next, anchor->last);
while (list) {
printf("curr: %p, next: %p, prev: %p, type: %d\n", list, list->next,
- list->prev, FIX2INT(list->type));
+ list->prev, (int)list->type);
list = list->next;
}
printf("----\n");
- dump_disasm_list(anchor->anchor.next);
+ dump_disasm_list_with_cursor(anchor->anchor.next, cur, 0);
verify_list("debug list", anchor);
}
#if CPDEBUG < 0
-#define debug_list(anc) debug_list(iseq, (anc))
+#define debug_list(anc, cur) debug_list(iseq, (anc), (cur))
#endif
#else
-#define debug_list(anc) ((void)0)
+#define debug_list(anc, cur) ((void)0)
#endif
static TRACE *
@@ -1162,7 +1266,7 @@ new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type insn_id, int a
va_list argv;
if (argc > 0) {
int i;
- va_init_list(argv, argc);
+ va_start(argv, argc);
operands = compile_data_alloc2(iseq, sizeof(VALUE), argc);
for (i = 0; i < argc; i++) {
VALUE v = va_arg(argv, VALUE);
@@ -1173,41 +1277,42 @@ new_insn_body(rb_iseq_t *iseq, int line_no, enum ruby_vminsn_type insn_id, int a
return new_insn_core(iseq, line_no, insn_id, argc, operands);
}
-static struct rb_call_info *
-new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_call_info_kw_arg *kw_arg, int has_blockiseq)
+static const struct rb_callinfo *
+new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_callinfo_kwarg *kw_arg, int has_blockiseq)
{
- size_t size = kw_arg != NULL ? sizeof(struct rb_call_info_with_kwarg) : sizeof(struct rb_call_info);
- struct rb_call_info *ci = (struct rb_call_info *)compile_data_alloc(iseq, size);
- struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci;
+ VM_ASSERT(argc >= 0);
- ci->mid = mid;
- ci->flag = flag;
- ci->orig_argc = argc;
+ if (!(flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT)) &&
+ kw_arg == NULL && !has_blockiseq) {
+ flag |= VM_CALL_ARGS_SIMPLE;
+ }
if (kw_arg) {
- ci->flag |= VM_CALL_KWARG;
- ci_kw->kw_arg = kw_arg;
- ci->orig_argc += kw_arg->keyword_len;
- iseq->body->ci_kw_size++;
- }
- else {
- iseq->body->ci_size++;
+ flag |= VM_CALL_KWARG;
+ argc += kw_arg->keyword_len;
}
- if (!(ci->flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT)) &&
- kw_arg == NULL && !has_blockiseq) {
- ci->flag |= VM_CALL_ARGS_SIMPLE;
- }
+ // fprintf(stderr, "[%d] id:%s\t", (int)iseq->body->ci_size, rb_id2name(mid)); rp(iseq);
+ iseq->body->ci_size++;
+ const struct rb_callinfo *ci = vm_ci_new(mid, flag, argc, kw_arg);
+ RB_OBJ_WRITTEN(iseq, Qundef, ci);
return ci;
}
static INSN *
-new_insn_send(rb_iseq_t *iseq, int line_no, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_call_info_kw_arg *keywords)
+new_insn_send(rb_iseq_t *iseq, int line_no, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_callinfo_kwarg *keywords)
{
- VALUE *operands = compile_data_alloc2(iseq, sizeof(VALUE), 2);
- operands[0] = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL);
+ VALUE *operands = compile_data_calloc2(iseq, sizeof(VALUE), 2);
+ VALUE ci = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL);
+ operands[0] = ci;
operands[1] = (VALUE)blockiseq;
- return new_insn_core(iseq, line_no, BIN(send), 2, operands);
+ if (blockiseq) {
+ RB_OBJ_WRITTEN(iseq, Qundef, blockiseq);
+ }
+ INSN *insn = new_insn_core(iseq, line_no, BIN(send), 2, operands);
+ RB_OBJ_WRITTEN(iseq, Qundef, ci);
+ RB_GC_GUARD(ci);
+ return insn;
}
static rb_iseq_t *
@@ -1222,9 +1327,12 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node,
ast.line_count = -1;
debugs("[new_child_iseq]> ---------------------------------------\n");
+ int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
ret_iseq = rb_iseq_new_with_opt(&ast, name,
rb_iseq_path(iseq), rb_iseq_realpath(iseq),
- INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option);
+ INT2FIX(line_no), parent,
+ isolated_depth ? isolated_depth + 1 : 0,
+ type, ISEQ_COMPILE_DATA(iseq)->option);
debugs("[new_child_iseq]< ---------------------------------------\n");
return ret_iseq;
}
@@ -1353,6 +1461,8 @@ iseq_setup_insn(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
debugs("[compile step 3.4 (iseq_insert_nop_between_end_and_cont)]\n");
iseq_insert_nop_between_end_and_cont(iseq);
+ if (compile_debug > 5)
+ dump_disasm_list(FIRST_ELEMENT(anchor));
return COMPILE_OK;
}
@@ -1377,8 +1487,16 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
debugs("[compile step 5 (iseq_translate_threaded_code)] \n");
if (!rb_iseq_translate_threaded_code(iseq)) return COMPILE_NG;
+ debugs("[compile step 6 (update_catch_except_flags)] \n");
update_catch_except_flags(iseq->body);
+#if VM_INSN_INFO_TABLE_IMPL == 2
+ if (iseq->body->insns_info.succ_index_table == NULL) {
+ debugs("[compile step 7 (rb_iseq_insns_info_encode_positions)] \n");
+ rb_iseq_insns_info_encode_positions(iseq);
+ }
+#endif
+
if (compile_debug > 1) {
VALUE str = rb_iseq_disasm(iseq);
printf("%s\n", StringValueCStr(str));
@@ -1494,6 +1612,53 @@ iseq_block_param_id_p(const rb_iseq_t *iseq, ID id, int *pidx, int *plevel)
}
static void
+access_outer_variables(const rb_iseq_t *iseq, int level, ID id, bool write)
+{
+ int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
+
+ if (isolated_depth && level >= isolated_depth) {
+ if (id == rb_intern("yield")) {
+ COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not yield from isolated Proc", rb_id2name(id));
+ }
+ else {
+ COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not access variable `%s' from isolated Proc", rb_id2name(id));
+ }
+ }
+
+ for (int i=0; i<level; i++) {
+ VALUE val;
+ struct rb_id_table *ovs = iseq->body->outer_variables;
+
+ if (!ovs) {
+ ovs = iseq->body->outer_variables = rb_id_table_create(8);
+ }
+
+ if (rb_id_table_lookup(iseq->body->outer_variables, id, &val)) {
+ if (write && !val) {
+ rb_id_table_insert(iseq->body->outer_variables, id, Qtrue);
+ }
+ }
+ else {
+ rb_id_table_insert(iseq->body->outer_variables, id, write ? Qtrue : Qfalse);
+ }
+
+ iseq = iseq->body->parent_iseq;
+ }
+}
+
+static ID
+iseq_lvar_id(const rb_iseq_t *iseq, int idx, int level)
+{
+ for (int i=0; i<level; i++) {
+ iseq = iseq->body->parent_iseq;
+ }
+
+ ID id = iseq->body->local_table[iseq->body->local_table_size - idx];
+ // fprintf(stderr, "idx:%d level:%d ID:%s\n", idx, level, rb_id2name(id));
+ return id;
+}
+
+static void
iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int idx, int level)
{
if (iseq_local_block_param_p(iseq, idx, level)) {
@@ -1502,6 +1667,7 @@ iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int idx, in
else {
ADD_INSN2(seq, line, getlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
}
+ if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level), Qfalse);
}
static void
@@ -1513,6 +1679,7 @@ iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int idx, in
else {
ADD_INSN2(seq, line, setlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
}
+ if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level), Qtrue);
}
@@ -1819,6 +1986,16 @@ cdhash_cmp(VALUE val, VALUE lit)
else if (tlit == T_FLOAT) {
return rb_float_cmp(lit, val);
}
+ else if (tlit == T_RATIONAL) {
+ const struct RRational *rat1 = RRATIONAL(val);
+ const struct RRational *rat2 = RRATIONAL(lit);
+ return cdhash_cmp(rat1->num, rat2->num) || cdhash_cmp(rat1->den, rat2->den);
+ }
+ else if (tlit == T_COMPLEX) {
+ const struct RComplex *comp1 = RCOMPLEX(val);
+ const struct RComplex *comp2 = RCOMPLEX(lit);
+ return cdhash_cmp(comp1->real, comp2->real) || cdhash_cmp(comp1->imag, comp2->imag);
+ }
else {
UNREACHABLE_RETURN(-1);
}
@@ -1837,6 +2014,10 @@ cdhash_hash(VALUE a)
return FIX2LONG(rb_big_hash(a));
case T_FLOAT:
return rb_dbl_long_hash(RFLOAT_VALUE(a));
+ case T_RATIONAL:
+ return rb_rational_hash(a);
+ case T_COMPLEX:
+ return rb_complex_hash(a);
default:
UNREACHABLE_RETURN(0);
}
@@ -1954,7 +2135,11 @@ fix_sp_depth(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
}
if (lobj->sp == -1) {
lobj->sp = sp;
- }
+ } else if (lobj->sp != sp) {
+ debugs("%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n",
+ RSTRING_PTR(rb_iseq_path(iseq)), line,
+ lobj->label_no, lobj->sp, sp);
+ }
}
}
break;
@@ -1966,6 +2151,11 @@ fix_sp_depth(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
lobj->sp = sp;
}
else {
+ if (lobj->sp != sp) {
+ debugs("%s:%d: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n",
+ RSTRING_PTR(rb_iseq_path(iseq)), line,
+ lobj->label_no, lobj->sp, sp);
+ }
sp = lobj->sp;
}
break;
@@ -2034,6 +2224,7 @@ add_adjust_info(struct iseq_insn_info_entry *insns_info, unsigned int *positions
static int
iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
{
+ VALUE iseqv = (VALUE)iseq;
struct iseq_insn_info_entry *insns_info;
struct rb_iseq_constant_body *const body = iseq->body;
unsigned int *positions;
@@ -2082,6 +2273,11 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
{
LABEL *lobj = (LABEL *)list;
lobj->position = code_index;
+ if (lobj->sp != sp) {
+ debugs("%s: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n",
+ RSTRING_PTR(rb_iseq_path(iseq)),
+ lobj->label_no, lobj->sp, sp);
+ }
sp = lobj->sp;
break;
}
@@ -2115,11 +2311,8 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
insns_info = ALLOC_N(struct iseq_insn_info_entry, insn_num);
positions = ALLOC_N(unsigned int, insn_num);
body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, body->is_size);
- body->call_data =
- rb_xcalloc_mul_add_mul(
- sizeof(struct rb_call_data), body->ci_size,
- sizeof(struct rb_kwarg_call_data), body->ci_kw_size);
- ISEQ_COMPILE_DATA(iseq)->ci_index = ISEQ_COMPILE_DATA(iseq)->ci_kw_index = 0;
+ body->call_data = ZALLOC_N(struct rb_call_data, body->ci_size);
+ ISEQ_COMPILE_DATA(iseq)->ci_index = 0;
list = FIRST_ELEMENT(anchor);
insns_info_index = code_index = sp = 0;
@@ -2166,7 +2359,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
freeze_hide_obj(map);
generated_iseq[code_index + 1 + j] = map;
RB_OBJ_WRITTEN(iseq, Qundef, map);
- FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
+ FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
break;
}
case TS_LINDEX:
@@ -2181,15 +2374,12 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
/* to mark ruby object */
if (!SPECIAL_CONST_P(v)) {
RB_OBJ_WRITTEN(iseq, Qundef, v);
- FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
+ FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
}
break;
}
- case TS_ISE: /* inline storage entry */
- /* Treated as an IC, but may contain a markable VALUE */
- FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
- /* fall through */
case TS_IC: /* inline cache */
+ case TS_ISE: /* inline storage entry */
case TS_IVC: /* inline ivar cache */
{
unsigned int ic_index = FIX2UINT(operands[j]);
@@ -2201,39 +2391,22 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
ic_index, body->is_size);
}
generated_iseq[code_index + 1 + j] = (VALUE)ic;
+ FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
break;
}
case TS_CALLDATA:
{
- struct rb_call_info *source_ci = (struct rb_call_info *)operands[j];
- struct rb_call_data *cd;
-
- if (source_ci->flag & VM_CALL_KWARG) {
- struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size];
- struct rb_kwarg_call_data *cd_kw = &kw_calls[ISEQ_COMPILE_DATA(iseq)->ci_kw_index++];
- cd_kw->ci_kw = *((struct rb_call_info_with_kwarg *)source_ci);
- cd = (struct rb_call_data *)cd_kw;
- assert(ISEQ_COMPILE_DATA(iseq)->ci_kw_index <= body->ci_kw_size);
- }
- else {
- cd = &body->call_data[ISEQ_COMPILE_DATA(iseq)->ci_index++];
- cd->ci = *source_ci;
- assert(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size);
- }
-
+ const struct rb_callinfo *source_ci = (const struct rb_callinfo *)operands[j];
+ struct rb_call_data *cd = &body->call_data[ISEQ_COMPILE_DATA(iseq)->ci_index++];
+ assert(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size);
+ cd->ci = source_ci;
+ cd->cc = vm_cc_empty();
generated_iseq[code_index + 1 + j] = (VALUE)cd;
break;
}
case TS_ID: /* ID */
generated_iseq[code_index + 1 + j] = SYM2ID(operands[j]);
break;
- case TS_GENTRY:
- {
- struct rb_global_entry *entry =
- (struct rb_global_entry *)(operands[j] & (~1));
- generated_iseq[code_index + 1 + j] = (VALUE)entry;
- }
- break;
case TS_FUNCPTR:
generated_iseq[code_index + 1 + j] = operands[j];
break;
@@ -2253,6 +2426,11 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
case ISEQ_ELEMENT_LABEL:
{
LABEL *lobj = (LABEL *)list;
+ if (lobj->sp != sp) {
+ debugs("%s: sp inconsistency found but ignored (" LABEL_FORMAT " sp: %d, calculated sp: %d)\n",
+ RSTRING_PTR(rb_iseq_path(iseq)),
+ lobj->label_no, lobj->sp, sp);
+ }
sp = lobj->sp;
break;
}
@@ -2285,7 +2463,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
xfree(generated_iseq);
xfree(insns_info);
xfree(positions);
- debug_list(anchor);
+ debug_list(anchor, list);
COMPILE_ERROR(iseq, adjust->line_no,
"iseq_set_sequence: adjust bug to %d %d < %d",
label_no, orig_sp, sp);
@@ -2337,7 +2515,8 @@ iseq_set_exception_table(rb_iseq_t *iseq)
unsigned int tlen, i;
struct iseq_catch_table_entry *entry;
- if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) goto no_catch_table;
+ iseq->body->catch_table = NULL;
+ if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) return COMPILE_OK;
tlen = (int)RARRAY_LEN(ISEQ_COMPILE_DATA(iseq)->catch_table_ary);
tptr = RARRAY_CONST_PTR_TRANSIENT(ISEQ_COMPILE_DATA(iseq)->catch_table_ary);
@@ -2374,10 +2553,6 @@ iseq_set_exception_table(rb_iseq_t *iseq)
iseq->body->catch_table = table;
RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0); /* free */
}
- else {
- no_catch_table:
- iseq->body->catch_table = NULL;
- }
return COMPILE_OK;
}
@@ -2551,10 +2726,7 @@ remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i)
unref_destination((INSN *)i, pos);
break;
case TS_CALLDATA:
- if (((struct rb_call_info *)OPERAND_AT(i, pos))->flag & VM_CALL_KWARG)
- --(body->ci_kw_size);
- else
- --(body->ci_size);
+ --(body->ci_size);
break;
}
}
@@ -2581,21 +2753,6 @@ iseq_pop_newarray(rb_iseq_t *iseq, INSN *iobj)
}
static int
-same_debug_pos_p(LINK_ELEMENT *iobj1, LINK_ELEMENT *iobj2)
-{
- VALUE debug1 = OPERAND_AT(iobj1, 0);
- VALUE debug2 = OPERAND_AT(iobj2, 0);
- if (debug1 == debug2) return TRUE;
- if (!RB_TYPE_P(debug1, T_ARRAY)) return FALSE;
- if (!RB_TYPE_P(debug2, T_ARRAY)) return FALSE;
- if (RARRAY_LEN(debug1) != 2) return FALSE;
- if (RARRAY_LEN(debug2) != 2) return FALSE;
- if (RARRAY_AREF(debug1, 0) != RARRAY_AREF(debug2, 0)) return FALSE;
- if (RARRAY_AREF(debug1, 1) != RARRAY_AREF(debug2, 1)) return FALSE;
- return TRUE;
-}
-
-static int
is_frozen_putstring(INSN *insn, VALUE *op)
{
if (IS_INSN_ID(insn, putstring)) {
@@ -2661,7 +2818,6 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
if (!ciobj || !IS_INSN_ID(ciobj, checktype)) return FALSE;
niobj = (INSN *)get_next_insn(ciobj);
if (!niobj) {
- no_branch:
/* TODO: putobject true/false */
return FALSE;
}
@@ -2677,7 +2833,7 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
}
break;
default:
- goto no_branch;
+ return FALSE;
}
line = ciobj->insn_info.line_no;
if (!dest) {
@@ -2695,6 +2851,28 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
return TRUE;
}
+static const struct rb_callinfo *
+ci_flag_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, unsigned int add)
+{
+ const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
+ vm_ci_flag(ci) | add,
+ vm_ci_argc(ci),
+ vm_ci_kwarg(ci));
+ RB_OBJ_WRITTEN(iseq, ci, nci);
+ return nci;
+}
+
+static const struct rb_callinfo *
+ci_argc_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, int argc)
+{
+ const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
+ vm_ci_flag(ci),
+ argc,
+ vm_ci_kwarg(ci));
+ RB_OBJ_WRITTEN(iseq, ci, nci);
+ return nci;
+}
+
static int
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
{
@@ -2721,7 +2899,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
else if (iobj != diobj && IS_INSN(&diobj->link) &&
IS_INSN_ID(diobj, jump) &&
- OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0)) {
+ OPERAND_AT(iobj, 0) != OPERAND_AT(diobj, 0) &&
+ diobj->insn_info.events == 0) {
/*
* useless jump elimination:
* jump LABEL1
@@ -2755,7 +2934,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
iobj->insn_info = diobj->insn_info;
goto again;
}
- else if (IS_INSN(iobj->link.prev) &&
+ else if (IS_INSN(iobj->link.prev) &&
(piobj = (INSN *)iobj->link.prev) &&
(IS_INSN_ID(piobj, branchif) ||
IS_INSN_ID(piobj, branchunless))) {
@@ -3091,10 +3270,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* =>
* concatstrings N+M-1
*/
- LINK_ELEMENT *next = iobj->link.next, *freeze = 0;
+ LINK_ELEMENT *next = iobj->link.next;
INSN *jump = 0;
- if (IS_INSN(next) && IS_INSN_ID(next, freezestring))
- next = (freeze = next)->next;
if (IS_INSN(next) && IS_INSN_ID(next, jump))
next = get_destination_insn(jump = (INSN *)next);
if (IS_INSN(next) && IS_INSN_ID(next, concatstrings)) {
@@ -3110,43 +3287,15 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
OPERAND_AT(jump, 0) = (VALUE)label;
}
label->refcnt++;
- if (freeze && IS_NEXT_INSN_ID(next, freezestring)) {
- if (same_debug_pos_p(freeze, next->next)) {
- ELEM_REMOVE(freeze);
- }
- else {
- next = next->next;
- }
- }
ELEM_INSERT_NEXT(next, &label->link);
CHECK(iseq_peephole_optimize(iseq, get_next_insn(jump), do_tailcallopt));
}
else {
- if (freeze) ELEM_REMOVE(freeze);
ELEM_REMOVE(next);
}
}
}
- if (IS_INSN_ID(iobj, freezestring) &&
- NIL_P(OPERAND_AT(iobj, 0)) &&
- IS_NEXT_INSN_ID(&iobj->link, send)) {
- INSN *niobj = (INSN *)iobj->link.next;
- struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(niobj, 0);
- /*
- * freezestring nil # no debug_info
- * send <:+@, 0, ARG_SIMPLE> # :-@, too
- * =>
- * send <:+@, 0, ARG_SIMPLE> # :-@, too
- */
- if ((ci->mid == idUPlus || ci->mid == idUMinus) &&
- (ci->flag & VM_CALL_ARGS_SIMPLE) &&
- ci->orig_argc == 0) {
- ELEM_REMOVE(list);
- return COMPILE_OK;
- }
- }
-
if (do_tailcallopt &&
(IS_INSN_ID(iobj, send) ||
IS_INSN_ID(iobj, opt_aref_with) ||
@@ -3189,14 +3338,19 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
if (piobj) {
- struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(piobj, 0);
- if (IS_INSN_ID(piobj, send) || IS_INSN_ID(piobj, invokesuper)) {
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(piobj, 0);
+ if (IS_INSN_ID(piobj, send) ||
+ IS_INSN_ID(piobj, invokesuper)) {
if (OPERAND_AT(piobj, 1) == 0) { /* no blockiseq */
- ci->flag |= VM_CALL_TAILCALL;
+ ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
+ OPERAND_AT(piobj, 0) = (VALUE)ci;
+ RB_OBJ_WRITTEN(iseq, Qundef, ci);
}
}
else {
- ci->flag |= VM_CALL_TAILCALL;
+ ci = ci_flag_set(iseq, ci, VM_CALL_TAILCALL);
+ OPERAND_AT(piobj, 0) = (VALUE)ci;
+ RB_OBJ_WRITTEN(iseq, Qundef, ci);
}
}
}
@@ -3259,7 +3413,7 @@ insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id)
if (insn_id == BIN(opt_neq)) {
VALUE *old_operands = iobj->operands;
iobj->operand_size = 2;
- iobj->operands = compile_data_alloc2(iseq, iobj->operand_size, sizeof(VALUE));
+ iobj->operands = compile_data_calloc2(iseq, iobj->operand_size, sizeof(VALUE));
iobj->operands[0] = (VALUE)new_callinfo(iseq, idEq, 1, 0, NULL, FALSE);
iobj->operands[1] = old_operands[0];
}
@@ -3277,9 +3431,9 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
*/
INSN *niobj = (INSN *)iobj->link.next;
if (IS_INSN_ID(niobj, send)) {
- struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(niobj, 0);
- if ((ci->flag & VM_CALL_ARGS_SIMPLE) && ci->orig_argc == 0) {
- switch (ci->mid) {
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(niobj, 0);
+ if ((vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) && vm_ci_argc(ci) == 0) {
+ switch (vm_ci_mid(ci)) {
case idMax:
iobj->insn_id = BIN(opt_newarray_max);
ELEM_REMOVE(&niobj->link);
@@ -3294,14 +3448,14 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
}
if (IS_INSN_ID(iobj, send)) {
- struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(iobj, 0);
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0);
const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(iobj, 1);
#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt))
- if (ci->flag & VM_CALL_ARGS_SIMPLE) {
- switch (ci->orig_argc) {
+ if (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) {
+ switch (vm_ci_argc(ci)) {
case 0:
- switch (ci->mid) {
+ switch (vm_ci_mid(ci)) {
case idLength: SP_INSN(length); return COMPILE_OK;
case idSize: SP_INSN(size); return COMPILE_OK;
case idEmptyP: SP_INSN(empty_p);return COMPILE_OK;
@@ -3311,7 +3465,7 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
}
break;
case 1:
- switch (ci->mid) {
+ switch (vm_ci_mid(ci)) {
case idPLUS: SP_INSN(plus); return COMPILE_OK;
case idMINUS: SP_INSN(minus); return COMPILE_OK;
case idMULT: SP_INSN(mult); return COMPILE_OK;
@@ -3331,14 +3485,14 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
}
break;
case 2:
- switch (ci->mid) {
+ switch (vm_ci_mid(ci)) {
case idASET: SP_INSN(aset); return COMPILE_OK;
}
break;
}
}
- if ((ci->flag & VM_CALL_ARGS_BLOCKARG) == 0 && blockiseq == NULL) {
+ if ((vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) == 0 && blockiseq == NULL) {
iobj->insn_id = BIN(opt_send_without_block);
iobj->operand_size = insn_len(iobj->insn_id) - 1;
}
@@ -3426,8 +3580,7 @@ new_unified_insn(rb_iseq_t *iseq,
}
if (argc > 0) {
- ptr = operands =
- compile_data_alloc2(iseq, sizeof(VALUE), argc);
+ ptr = operands = compile_data_alloc2(iseq, sizeof(VALUE), argc);
}
/* copy operands */
@@ -3731,8 +3884,16 @@ static int
compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
{
int cnt;
- CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
- ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt));
+ if (!node->nd_next) {
+ VALUE lit = rb_fstring(node->nd_lit);
+ const int line = (int)nd_line(node);
+ ADD_INSN1(ret, line, putstring, lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
+ }
+ else {
+ CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
+ ADD_INSN1(ret, nd_line(node), concatstrings, INT2FIX(cnt));
+ }
return COMPILE_OK;
}
@@ -3789,7 +3950,10 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *co
LABEL *label = NEW_LABEL(nd_line(cond));
CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, label,
else_label));
- if (!label->refcnt) break;
+ if (!label->refcnt) {
+ ADD_INSN(ret, nd_line(cond), putnil);
+ break;
+ }
ADD_LABEL(ret, label);
cond = cond->nd_2nd;
goto again;
@@ -3799,7 +3963,10 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *co
LABEL *label = NEW_LABEL(nd_line(cond));
CHECK(compile_branch_condition(iseq, ret, cond->nd_1st, then_label,
label));
- if (!label->refcnt) break;
+ if (!label->refcnt) {
+ ADD_INSN(ret, nd_line(cond), putnil);
+ break;
+ }
ADD_LABEL(ret, label);
cond = cond->nd_2nd;
goto again;
@@ -3811,68 +3978,77 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *co
case NODE_LAMBDA:
/* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
ADD_INSNL(ret, nd_line(cond), jump, then_label);
- break;
+ return COMPILE_OK;
case NODE_FALSE:
case NODE_NIL:
/* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
ADD_INSNL(ret, nd_line(cond), jump, else_label);
- break;
+ return COMPILE_OK;
case NODE_LIST:
case NODE_ARGSCAT:
case NODE_DREGX:
case NODE_DSTR:
CHECK(COMPILE_POPPED(ret, "branch condition", cond));
ADD_INSNL(ret, nd_line(cond), jump, then_label);
- break;
+ return COMPILE_OK;
case NODE_FLIP2:
CHECK(compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label));
- break;
+ return COMPILE_OK;
case NODE_FLIP3:
CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label));
- break;
+ return COMPILE_OK;
case NODE_DEFINED:
CHECK(compile_defined_expr(iseq, ret, cond, Qfalse));
- goto branch;
+ break;
default:
CHECK(COMPILE(ret, "branch condition", cond));
- branch:
- ADD_INSNL(ret, nd_line(cond), branchunless, else_label);
- ADD_INSNL(ret, nd_line(cond), jump, then_label);
- break;
+ break;
}
+
+ ADD_INSNL(ret, nd_line(cond), branchunless, else_label);
+ ADD_INSNL(ret, nd_line(cond), jump, then_label);
return COMPILE_OK;
}
+#define HASH_BRACE 1
+
static int
keyword_node_p(const NODE *const node)
{
- return nd_type(node) == NODE_HASH && node->nd_brace == FALSE;
+ return nd_type(node) == NODE_HASH && (node->nd_brace & HASH_BRACE) != HASH_BRACE;
}
static int
compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
const NODE *const root_node,
- struct rb_call_info_kw_arg **const kw_arg_ptr,
+ struct rb_callinfo_kwarg **const kw_arg_ptr,
unsigned int *flag)
{
if (kw_arg_ptr == NULL) return FALSE;
- if (keyword_node_p(root_node) && root_node->nd_head && nd_type(root_node->nd_head) == NODE_LIST) {
+ if (root_node->nd_head && nd_type(root_node->nd_head) == NODE_LIST) {
const NODE *node = root_node->nd_head;
+ int seen_nodes = 0;
while (node) {
const NODE *key_node = node->nd_head;
+ seen_nodes++;
assert(nd_type(node) == NODE_LIST);
- if (!key_node) {
- if (flag) *flag |= VM_CALL_KW_SPLAT;
- return FALSE;
- }
- else if (nd_type(key_node) == NODE_LIT && RB_TYPE_P(key_node->nd_lit, T_SYMBOL)) {
+ if (key_node && nd_type(key_node) == NODE_LIT && RB_TYPE_P(key_node->nd_lit, T_SYMBOL)) {
/* can be keywords */
}
else {
- if (flag) *flag |= VM_CALL_KW_SPLAT;
+ if (flag) {
+ *flag |= VM_CALL_KW_SPLAT;
+ if (seen_nodes > 1 || node->nd_next->nd_next) {
+ /* A new hash will be created for the keyword arguments
+ * in this case, so mark the method as passing mutable
+ * keyword splat.
+ */
+ *flag |= VM_CALL_KW_SPLAT_MUT;
+ }
+ }
return FALSE;
}
node = node->nd_next; /* skip value node */
@@ -3883,8 +4059,8 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
node = root_node->nd_head;
{
int len = (int)node->nd_alen / 2;
- struct rb_call_info_kw_arg *kw_arg =
- rb_xmalloc_mul_add(len - 1, sizeof(VALUE), sizeof(struct rb_call_info_kw_arg));
+ struct rb_callinfo_kwarg *kw_arg =
+ rb_xmalloc_mul_add(len, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg));
VALUE *keywords = kw_arg->keywords;
int i = 0;
kw_arg->keyword_len = len;
@@ -3906,7 +4082,7 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
static int
compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node,
- struct rb_call_info_kw_arg **keywords_ptr, unsigned int *flag)
+ struct rb_callinfo_kwarg **keywords_ptr, unsigned int *flag)
{
int len = 0;
@@ -3915,9 +4091,13 @@ compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node,
EXPECT_NODE("compile_args", node, NODE_LIST, -1);
}
- if (node->nd_next == NULL /* last node */ &&
- compile_keyword_arg(iseq, ret, node->nd_head, keywords_ptr, flag)) {
- len--;
+ if (node->nd_next == NULL && keyword_node_p(node->nd_head)) { /* last node */
+ if (compile_keyword_arg(iseq, ret, node->nd_head, keywords_ptr, flag)) {
+ len--;
+ }
+ else {
+ compile_hash(iseq, ret, node->nd_head, TRUE, FALSE);
+ }
}
else {
NO_CHECK(COMPILE_(ret, "array element", node->nd_head, FALSE));
@@ -4107,7 +4287,7 @@ static_literal_node_pair_p(const NODE *node, const rb_iseq_t *iseq)
}
static int
-compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped)
+compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int method_call_keywords, int popped)
{
int line = (int)nd_line(node);
@@ -4242,32 +4422,48 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popp
int only_kw = last_kw && first_kw; /* foo(1,2,3, **kw) */
if (empty_kw) {
- if (only_kw) {
- /* **{} appears at the last, so it won't be modified.
+ if (only_kw && method_call_keywords) {
+ /* **{} appears at the only keyword argument in method call,
+ * so it won't be modified.
* kw is a special NODE_LIT that contains a special empty hash,
- * so this emits: putobject {}
+ * so this emits: putobject {}.
+ * This is only done for method calls and not for literal hashes,
+ * because literal hashes should always result in a new hash.
*/
NO_CHECK(COMPILE(ret, "keyword splat", kw));
}
else if (first_kw) {
- /* **{} appears at the first, so it may be modified.
+ /* **{} appears as the first keyword argument, so it may be modified.
* We need to create a fresh hash object.
*/
ADD_INSN1(ret, line, newhash, INT2FIX(0));
}
+ /* Any empty keyword splats that are not the first can be ignored.
+ * since merging an empty hash into the existing hash is the same
+ * as not merging it. */
}
else {
- /* This is not empty hash: **{k:1}.
- * We need to clone the hash (if first), or merge the hash to
- * the accumulated hash (if not first).
- */
- ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- if (first_kw) ADD_INSN1(ret, line, newhash, INT2FIX(0));
- else ADD_INSN(ret, line, swap);
+ if (only_kw && method_call_keywords) {
+ /* **kw is only keyword argument in method call.
+ * Use directly. This will be not be flagged as mutable.
+ * This is only done for method calls and not for literal hashes,
+ * because literal hashes should always result in a new hash.
+ */
+ NO_CHECK(COMPILE(ret, "keyword splat", kw));
+ }
+ else {
+ /* There is more than one keyword argument, or this is not a method
+ * call. In that case, we need to add an empty hash (if first keyword),
+ * or merge the hash to the accumulated hash (if not the first keyword).
+ */
+ ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ if (first_kw) ADD_INSN1(ret, line, newhash, INT2FIX(0));
+ else ADD_INSN(ret, line, swap);
- NO_CHECK(COMPILE(ret, "keyword splat", kw));
+ NO_CHECK(COMPILE(ret, "keyword splat", kw));
- ADD_SEND(ret, line, id_core_hash_merge_kwd, INT2FIX(2));
+ ADD_SEND(ret, line, id_core_hash_merge_kwd, INT2FIX(2));
+ }
}
first_chunk = 0;
@@ -4389,21 +4585,26 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const n
switch (nd_type(node)) {
case NODE_ATTRASGN: {
INSN *iobj;
- struct rb_call_info *ci;
VALUE dupidx;
int line = nd_line(node);
CHECK(COMPILE_POPPED(ret, "masgn lhs (NODE_ATTRASGN)", node));
iobj = (INSN *)get_prev_insn((INSN *)LAST_ELEMENT(ret)); /* send insn */
- ci = (struct rb_call_info *)OPERAND_AT(iobj, 0);
- ci->orig_argc += 1;
- dupidx = INT2FIX(ci->orig_argc);
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0);
+ int argc = vm_ci_argc(ci) + 1;
+ ci = ci_argc_set(iseq, ci, argc);
+ OPERAND_AT(iobj, 0) = (VALUE)ci;
+ RB_OBJ_WRITTEN(iseq, Qundef, ci);
+ dupidx = INT2FIX(argc);
INSERT_BEFORE_INSN1(iobj, line, topn, dupidx);
- if (ci->flag & VM_CALL_ARGS_SPLAT) {
- --ci->orig_argc;
- INSERT_BEFORE_INSN1(iobj, line, newarray, INT2FIX(1));
+ if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
+ int argc = vm_ci_argc(ci);
+ ci = ci_argc_set(iseq, ci, argc - 1);
+ OPERAND_AT(iobj, 0) = (VALUE)ci;
+ RB_OBJ_WRITTEN(iseq, Qundef, iobj);
+ INSERT_BEFORE_INSN1(iobj, line, newarray, INT2FIX(1));
INSERT_BEFORE_INSN(iobj, line, concatarray);
}
ADD_INSN(ret, line, pop); /* result */
@@ -4725,7 +4926,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
case NODE_GVAR:
ADD_INSN(ret, line, putnil);
ADD_INSN3(ret, line, defined, INT2FIX(DEFINED_GVAR),
- ID2SYM(node->nd_entry->id), needstr);
+ ID2SYM(node->nd_entry), needstr);
return;
case NODE_CVAR:
@@ -4999,7 +5200,7 @@ check_keyword(const NODE *node)
static VALUE
setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
- int dup_rest, unsigned int *flag, struct rb_call_info_kw_arg **keywords)
+ int dup_rest, unsigned int *flag, struct rb_callinfo_kwarg **keywords)
{
if (argn) {
switch (nd_type(argn)) {
@@ -5059,16 +5260,16 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
static VALUE
setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
- unsigned int *flag, struct rb_call_info_kw_arg **keywords)
+ unsigned int *flag, struct rb_callinfo_kwarg **keywords)
{
VALUE ret;
if (argn && nd_type(argn) == NODE_BLOCK_PASS) {
+ unsigned int dup_rest = 1;
DECL_ANCHOR(arg_block);
INIT_ANCHOR(arg_block);
NO_CHECK(COMPILE(arg_block, "block", argn->nd_body));
*flag |= VM_CALL_ARGS_BLOCKARG;
- ret = setup_args_core(iseq, args, argn->nd_head, 0, flag, keywords);
if (LIST_INSN_SIZE_ONE(arg_block)) {
LINK_ELEMENT *elem = FIRST_ELEMENT(arg_block);
@@ -5077,8 +5278,10 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
if (iobj->insn_id == BIN(getblockparam)) {
iobj->insn_id = BIN(getblockparamproxy);
}
+ dup_rest = 0;
}
}
+ ret = setup_args_core(iseq, args, argn->nd_head, dup_rest, flag, keywords);
ADD_SEQ(args, arg_block);
}
else {
@@ -5110,7 +5313,7 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
LABEL *fail_label = NEW_LABEL(line), *end_label = NEW_LABEL(line);
#if !(defined(NAMED_CAPTURE_BY_SVAR) && NAMED_CAPTURE_BY_SVAR-0)
- ADD_INSN1(ret, line, getglobal, ((VALUE)rb_global_entry(idBACKREF) | 1));
+ ADD_INSN1(ret, line, getglobal, ID2SYM(idBACKREF));
#else
ADD_INSN2(ret, line, getspecial, INT2FIX(1) /* '~' */, INT2FIX(0));
#endif
@@ -5161,9 +5364,17 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
}
static int
-number_literal_p(const NODE *n)
+optimizable_range_item_p(const NODE *n)
{
- return (n && nd_type(n) == NODE_LIT && RB_INTEGER_TYPE_P(n->nd_lit));
+ if (!n) return FALSE;
+ switch (nd_type(n)) {
+ case NODE_LIT:
+ return RB_INTEGER_TYPE_P(n->nd_lit);
+ case NODE_NIL:
+ return TRUE;
+ default:
+ return FALSE;
+ }
}
static int
@@ -5174,16 +5385,12 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
const NODE *const node_else = type == NODE_IF ? node->nd_else : node->nd_body;
const int line = nd_line(node);
- const int lineno = nd_first_lineno(node);
- const int column = nd_first_column(node);
- const int last_lineno = nd_last_lineno(node);
- const int last_column = nd_last_column(node);
DECL_ANCHOR(cond_seq);
DECL_ANCHOR(then_seq);
DECL_ANCHOR(else_seq);
LABEL *then_label, *else_label, *end_label;
VALUE branches = Qfalse;
- int ci_size, ci_kw_size;
+ int ci_size;
VALUE catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
long catch_table_size = NIL_P(catch_table) ? 0 : RARRAY_LEN(catch_table);
@@ -5198,12 +5405,10 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
then_label, else_label);
ci_size = body->ci_size;
- ci_kw_size = body->ci_kw_size;
CHECK(COMPILE_(then_seq, "then", node_body, popped));
catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
if (!then_label->refcnt) {
body->ci_size = ci_size;
- body->ci_kw_size = ci_kw_size;
if (!NIL_P(catch_table)) rb_ary_set_len(catch_table, catch_table_size);
}
else {
@@ -5211,12 +5416,10 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
}
ci_size = body->ci_size;
- ci_kw_size = body->ci_kw_size;
CHECK(COMPILE_(else_seq, "else", node_else, popped));
catch_table = ISEQ_COMPILE_DATA(iseq)->catch_table_ary;
if (!else_label->refcnt) {
body->ci_size = ci_size;
- body->ci_kw_size = ci_kw_size;
if (!NIL_P(catch_table)) rb_ary_set_len(catch_table, catch_table_size);
}
else {
@@ -5226,18 +5429,17 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
ADD_SEQ(ret, cond_seq);
if (then_label->refcnt && else_label->refcnt) {
- DECL_BRANCH_BASE(branches, lineno, column, last_lineno, last_column, type == NODE_IF ? "if" : "unless");
+ branches = decl_branch_base(iseq, node, type == NODE_IF ? "if" : "unless");
}
if (then_label->refcnt) {
ADD_LABEL(ret, then_label);
if (else_label->refcnt) {
- ADD_TRACE_BRANCH_COVERAGE(
+ add_trace_branch_coverage(
+ iseq,
ret,
- node_body ? nd_first_lineno(node_body) : lineno,
- node_body ? nd_first_column(node_body) : column,
- node_body ? nd_last_lineno(node_body) : last_lineno,
- node_body ? nd_last_column(node_body) : last_column,
+ node_body ? node_body : node,
+ 0,
type == NODE_IF ? "then" : "else",
branches);
end_label = NEW_LABEL(line);
@@ -5252,12 +5454,11 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
if (else_label->refcnt) {
ADD_LABEL(ret, else_label);
if (then_label->refcnt) {
- ADD_TRACE_BRANCH_COVERAGE(
+ add_trace_branch_coverage(
+ iseq,
ret,
- node_else ? nd_first_lineno(node_else) : lineno,
- node_else ? nd_first_column(node_else) : column,
- node_else ? nd_last_lineno(node_else) : last_lineno,
- node_else ? nd_last_column(node_else) : last_column,
+ node_else ? node_else : node,
+ 1,
type == NODE_IF ? "else" : "then",
branches);
}
@@ -5282,9 +5483,10 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
DECL_ANCHOR(cond_seq);
int only_special_literals = 1;
VALUE literals = rb_hash_new();
- int line, lineno, column, last_lineno, last_column;
+ int line;
enum node_type type;
VALUE branches = Qfalse;
+ int branch_id = 0;
INIT_ANCHOR(head);
INIT_ANCHOR(body_seq);
@@ -5294,16 +5496,12 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
CHECK(COMPILE(head, "case base", node->nd_head));
- DECL_BRANCH_BASE(branches, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node), "case");
+ branches = decl_branch_base(iseq, node, "case");
node = node->nd_body;
EXPECT_NODE("NODE_CASE", node, NODE_WHEN, COMPILE_NG);
type = nd_type(node);
line = nd_line(node);
- lineno = nd_first_lineno(node);
- column = nd_first_column(node);
- last_lineno = nd_last_lineno(node);
- last_column = nd_last_column(node);
endlabel = NEW_LABEL(line);
elselabel = NEW_LABEL(line);
@@ -5316,12 +5514,11 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
l1 = NEW_LABEL(line);
ADD_LABEL(body_seq, l1);
ADD_INSN(body_seq, line, pop);
- ADD_TRACE_BRANCH_COVERAGE(
+ add_trace_branch_coverage(
+ iseq,
body_seq,
- node->nd_body ? nd_first_lineno(node->nd_body) : lineno,
- node->nd_body ? nd_first_column(node->nd_body) : column,
- node->nd_body ? nd_last_lineno(node->nd_body) : last_lineno,
- node->nd_body ? nd_last_column(node->nd_body) : last_column,
+ node->nd_body ? node->nd_body : node,
+ branch_id++,
"when",
branches);
CHECK(COMPILE_(body_seq, "when body", node->nd_body, popped));
@@ -5354,16 +5551,12 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
}
type = nd_type(node);
line = nd_line(node);
- lineno = nd_first_lineno(node);
- column = nd_first_column(node);
- last_lineno = nd_last_lineno(node);
- last_column = nd_last_column(node);
}
/* else */
if (node) {
ADD_LABEL(cond_seq, elselabel);
ADD_INSN(cond_seq, line, pop);
- ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node), "else", branches);
+ add_trace_branch_coverage(iseq, cond_seq, node, branch_id, "else", branches);
CHECK(COMPILE_(cond_seq, "else", node, popped));
ADD_INSNL(cond_seq, line, jump, endlabel);
}
@@ -5371,7 +5564,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
debugs("== else (implicit)\n");
ADD_LABEL(cond_seq, elselabel);
ADD_INSN(cond_seq, nd_line(orig_node), pop);
- ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_first_lineno(orig_node), nd_first_column(orig_node), nd_last_lineno(orig_node), nd_last_column(orig_node), "else", branches);
+ add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches);
if (!popped) {
ADD_INSN(cond_seq, nd_line(orig_node), putnil);
}
@@ -5400,26 +5593,22 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
LABEL *endlabel;
DECL_ANCHOR(body_seq);
VALUE branches = Qfalse;
+ int branch_id = 0;
- DECL_BRANCH_BASE(branches, nd_first_lineno(orig_node), nd_first_column(orig_node), nd_last_lineno(orig_node), nd_last_column(orig_node), "case");
+ branches = decl_branch_base(iseq, orig_node, "case");
INIT_ANCHOR(body_seq);
endlabel = NEW_LABEL(nd_line(node));
while (node && nd_type(node) == NODE_WHEN) {
const int line = nd_line(node);
- const int lineno = nd_first_lineno(node);
- const int column = nd_first_column(node);
- const int last_lineno = nd_last_lineno(node);
- const int last_column = nd_last_column(node);
LABEL *l1 = NEW_LABEL(line);
ADD_LABEL(body_seq, l1);
- ADD_TRACE_BRANCH_COVERAGE(
+ add_trace_branch_coverage(
+ iseq,
body_seq,
- node->nd_body ? nd_first_lineno(node->nd_body) : lineno,
- node->nd_body ? nd_first_column(node->nd_body) : column,
- node->nd_body ? nd_last_lineno(node->nd_body) : last_lineno,
- node->nd_body ? nd_last_column(node->nd_body) : last_column,
+ node->nd_body ? node->nd_body : node,
+ branch_id++,
"when",
branches);
CHECK(COMPILE_(body_seq, "when", node->nd_body, popped));
@@ -5455,12 +5644,11 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
node = node->nd_next;
}
/* else */
- ADD_TRACE_BRANCH_COVERAGE(
+ add_trace_branch_coverage(
+ iseq,
ret,
- node ? nd_first_lineno(node) : nd_first_lineno(orig_node),
- node ? nd_first_column(node) : nd_first_column(orig_node),
- node ? nd_last_lineno(node) : nd_last_lineno(orig_node),
- node ? nd_last_column(node) : nd_last_column(orig_node),
+ node ? node : orig_node,
+ branch_id,
"else",
branches);
CHECK(COMPILE_(ret, "else", node, popped));
@@ -5471,8 +5659,12 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
return COMPILE_OK;
}
+static int iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *unmatched, int in_alt_pattern, int deconstructed_pos);
+
+static int iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error, int deconstructed_pos);
+
static int
-iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int in_alt_pattern)
+iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *matched, LABEL *unmatched, int in_alt_pattern, int deconstructed_pos)
{
const int line = nd_line(node);
@@ -5524,13 +5716,11 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
* goto match_failed
* end
* end
- * true
- * goto fin
+ * goto matched
* type_error:
* FrozenCore.raise TypeError
* match_failed:
- * false
- * fin:
+ * goto unmatched
*/
struct rb_ary_pattern_info *apinfo = node->nd_apinfo;
const NODE *args = apinfo->pre_args;
@@ -5541,15 +5731,19 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
const int use_rest_num = apinfo->rest_arg && (NODE_NAMED_REST_P(apinfo->rest_arg) ||
(!NODE_NAMED_REST_P(apinfo->rest_arg) && post_args_num > 0));
- LABEL *match_failed, *type_error, *fin;
+ LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
int i;
match_failed = NEW_LABEL(line);
type_error = NEW_LABEL(line);
- fin = NEW_LABEL(line);
+ deconstruct = NEW_LABEL(line);
+ deconstructed = NEW_LABEL(line);
if (use_rest_num) {
ADD_INSN1(ret, line, putobject, INT2FIX(0)); /* allocate stack for rest_num */
ADD_INSN(ret, line, swap);
+ if (deconstructed_pos) {
+ deconstructed_pos++;
+ }
}
if (node->nd_pconst) {
@@ -5559,16 +5753,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSNL(ret, line, branchunless, match_failed);
}
- ADD_INSN(ret, line, dup);
- ADD_INSN1(ret, line, putobject, ID2SYM(rb_intern("deconstruct")));
- ADD_SEND(ret, line, idRespond_to, INT2FIX(1));
- ADD_INSNL(ret, line, branchunless, match_failed);
-
- ADD_SEND(ret, line, rb_intern("deconstruct"), INT2FIX(0));
-
- ADD_INSN(ret, line, dup);
- ADD_INSN1(ret, line, checktype, INT2FIX(T_ARRAY));
- ADD_INSNL(ret, line, branchunless, type_error);
+ CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, deconstructed_pos));
ADD_INSN(ret, line, dup);
ADD_SEND(ret, line, idLength, INT2FIX(0));
@@ -5580,9 +5765,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN(ret, line, dup);
ADD_INSN1(ret, line, putobject, INT2FIX(i));
ADD_SEND(ret, line, idAREF, INT2FIX(1));
- iseq_compile_pattern_each(iseq, ret, args->nd_head, in_alt_pattern);
+ CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern, FALSE));
args = args->nd_next;
- ADD_INSNL(ret, line, branchunless, match_failed);
}
if (apinfo->rest_arg) {
@@ -5596,8 +5780,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN1(ret, line, setn, INT2FIX(4));
ADD_SEND(ret, line, idAREF, INT2FIX(2));
- iseq_compile_pattern_each(iseq, ret, apinfo->rest_arg, in_alt_pattern);
- ADD_INSNL(ret, line, branchunless, match_failed);
+ CHECK(iseq_compile_pattern_match(iseq, ret, apinfo->rest_arg, match_failed, in_alt_pattern, FALSE));
}
else {
if (post_args_num > 0) {
@@ -5620,31 +5803,196 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_SEND(ret, line, idPLUS, INT2FIX(1));
ADD_SEND(ret, line, idAREF, INT2FIX(1));
- iseq_compile_pattern_each(iseq, ret, args->nd_head, in_alt_pattern);
+ CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_alt_pattern, FALSE));
args = args->nd_next;
- ADD_INSNL(ret, line, branchunless, match_failed);
}
ADD_INSN(ret, line, pop);
if (use_rest_num) {
ADD_INSN(ret, line, pop);
}
- ADD_INSN1(ret, line, putobject, Qtrue);
- ADD_INSNL(ret, line, jump, fin);
+ ADD_INSNL(ret, line, jump, matched);
+ ADD_INSN(ret, line, putnil);
+ if (use_rest_num) {
+ ADD_INSN(ret, line, putnil);
+ }
ADD_LABEL(ret, type_error);
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(ret, line, putobject, rb_eTypeError);
ADD_INSN1(ret, line, putobject, rb_fstring_lit("deconstruct must return Array"));
ADD_SEND(ret, line, id_core_raise, INT2FIX(2));
+ ADD_INSN(ret, line, pop);
ADD_LABEL(ret, match_failed);
ADD_INSN(ret, line, pop);
if (use_rest_num) {
ADD_INSN(ret, line, pop);
}
- ADD_INSN1(ret, line, putobject, Qfalse);
- ADD_LABEL(ret, fin);
+ ADD_INSNL(ret, line, jump, unmatched);
+
+ break;
+ }
+ case NODE_FNDPTN: {
+ /*
+ * if pattern.has_constant_node?
+ * unless pattern.constant === obj
+ * goto match_failed
+ * end
+ * end
+ * unless obj.respond_to?(:deconstruct)
+ * goto match_failed
+ * end
+ * d = obj.deconstruct
+ * unless Array === d
+ * goto type_error
+ * end
+ * unless d.length >= pattern.args_num
+ * goto match_failed
+ * end
+ *
+ * begin
+ * len = d.length
+ * limit = d.length - pattern.args_num
+ * i = 0
+ * while i <= limit
+ * if pattern.args_num.times.all? {|j| pattern.args[j].match?(d[i+j]) }
+ * if pattern.has_pre_rest_arg_id
+ * unless pattern.pre_rest_arg.match?(d[0, i])
+ * goto find_failed
+ * end
+ * end
+ * if pattern.has_post_rest_arg_id
+ * unless pattern.post_rest_arg.match?(d[i+pattern.args_num, len])
+ * goto find_failed
+ * end
+ * end
+ * goto find_succeeded
+ * end
+ * i+=1
+ * end
+ * find_failed:
+ * goto match_failed
+ * find_succeeded:
+ * end
+ *
+ * goto matched
+ * type_error:
+ * FrozenCore.raise TypeError
+ * match_failed:
+ * goto unmatched
+ */
+ struct rb_fnd_pattern_info *fpinfo = node->nd_fpinfo;
+ const NODE *args = fpinfo->args;
+ const int args_num = fpinfo->args ? rb_long2int(fpinfo->args->nd_alen) : 0;
+
+ LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
+ match_failed = NEW_LABEL(line);
+ type_error = NEW_LABEL(line);
+ deconstruct = NEW_LABEL(line);
+ deconstructed = NEW_LABEL(line);
+
+ if (node->nd_pconst) {
+ ADD_INSN(ret, line, dup);
+ CHECK(COMPILE(ret, "constant", node->nd_pconst));
+ ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
+ ADD_INSNL(ret, line, branchunless, match_failed);
+ }
+
+ CHECK(iseq_compile_array_deconstruct(iseq, ret, node, deconstruct, deconstructed, match_failed, type_error, deconstructed_pos));
+
+ ADD_INSN(ret, line, dup);
+ ADD_SEND(ret, line, idLength, INT2FIX(0));
+ ADD_INSN1(ret, line, putobject, INT2FIX(args_num));
+ ADD_SEND(ret, line, idGE, INT2FIX(1));
+ ADD_INSNL(ret, line, branchunless, match_failed);
+
+ {
+ LABEL *while_begin = NEW_LABEL(nd_line(node));
+ LABEL *next_loop = NEW_LABEL(nd_line(node));
+ LABEL *find_succeeded = NEW_LABEL(line);
+ LABEL *find_failed = NEW_LABEL(nd_line(node));
+ int j;
+
+ ADD_INSN(ret, line, dup); /* allocate stack for len */
+ ADD_SEND(ret, line, idLength, INT2FIX(0));
+
+ ADD_INSN(ret, line, dup); /* allocate stack for limit */
+ ADD_INSN1(ret, line, putobject, INT2FIX(args_num));
+ ADD_SEND(ret, line, idMINUS, INT2FIX(1));
+
+ ADD_INSN1(ret, line, putobject, INT2FIX(0)); /* allocate stack for i */
+
+ ADD_LABEL(ret, while_begin);
+
+ ADD_INSN(ret, line, dup);
+ ADD_INSN1(ret, line, topn, INT2FIX(2));
+ ADD_SEND(ret, line, idLE, INT2FIX(1));
+ ADD_INSNL(ret, line, branchunless, find_failed);
+
+ for (j = 0; j < args_num; j++) {
+ ADD_INSN1(ret, line, topn, INT2FIX(3));
+ ADD_INSN1(ret, line, topn, INT2FIX(1));
+ if (j != 0) {
+ ADD_INSN1(ret, line, putobject, INT2FIX(j));
+ ADD_SEND(ret, line, idPLUS, INT2FIX(1));
+ }
+ ADD_SEND(ret, line, idAREF, INT2FIX(1));
+
+ CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, next_loop, in_alt_pattern, FALSE));
+ args = args->nd_next;
+ }
+
+ if (NODE_NAMED_REST_P(fpinfo->pre_rest_arg)) {
+ ADD_INSN1(ret, line, topn, INT2FIX(3));
+ ADD_INSN1(ret, line, putobject, INT2FIX(0));
+ ADD_INSN1(ret, line, topn, INT2FIX(2));
+ ADD_SEND(ret, line, idAREF, INT2FIX(2));
+ CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->pre_rest_arg, find_failed, in_alt_pattern, FALSE));
+ }
+ if (NODE_NAMED_REST_P(fpinfo->post_rest_arg)) {
+ ADD_INSN1(ret, line, topn, INT2FIX(3));
+ ADD_INSN1(ret, line, topn, INT2FIX(1));
+ ADD_INSN1(ret, line, putobject, INT2FIX(args_num));
+ ADD_SEND(ret, line, idPLUS, INT2FIX(1));
+ ADD_INSN1(ret, line, topn, INT2FIX(3));
+ ADD_SEND(ret, line, idAREF, INT2FIX(2));
+ CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->post_rest_arg, find_failed, in_alt_pattern, FALSE));
+ }
+ ADD_INSNL(ret, line, jump, find_succeeded);
+
+ ADD_LABEL(ret, next_loop);
+ ADD_INSN1(ret, line, putobject, INT2FIX(1));
+ ADD_SEND(ret, line, idPLUS, INT2FIX(1));
+ ADD_INSNL(ret, line, jump, while_begin);
+
+ ADD_LABEL(ret, find_failed);
+ ADD_INSN(ret, line, pop);
+ ADD_INSN(ret, line, pop);
+ ADD_INSN(ret, line, pop);
+ ADD_INSNL(ret, line, jump, match_failed);
+ ADD_INSN1(ret, line, dupn, INT2FIX(3));
+
+ ADD_LABEL(ret, find_succeeded);
+ ADD_INSN(ret, line, pop);
+ ADD_INSN(ret, line, pop);
+ ADD_INSN(ret, line, pop);
+ }
+
+ ADD_INSN(ret, line, pop);
+ ADD_INSNL(ret, line, jump, matched);
+ ADD_INSN(ret, line, putnil);
+
+ ADD_LABEL(ret, type_error);
+ ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(ret, line, putobject, rb_eTypeError);
+ ADD_INSN1(ret, line, putobject, rb_fstring_lit("deconstruct must return Array"));
+ ADD_SEND(ret, line, id_core_raise, INT2FIX(2));
+ ADD_INSN(ret, line, pop);
+
+ ADD_LABEL(ret, match_failed);
+ ADD_INSN(ret, line, pop);
+ ADD_INSNL(ret, line, jump, unmatched);
break;
}
@@ -5702,20 +6050,17 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
* end
* end
* end
- * true
- * goto fin
+ * goto matched
* type_error:
* FrozenCore.raise TypeError
* match_failed:
- * false
- * fin:
+ * goto unmatched
*/
- LABEL *match_failed, *type_error, *fin;
+ LABEL *match_failed, *type_error;
VALUE keys = Qnil;
match_failed = NEW_LABEL(line);
type_error = NEW_LABEL(line);
- fin = NEW_LABEL(line);
if (node->nd_pkwargs && !node->nd_pkwrestarg) {
const NODE *kw_args = node->nd_pkwargs->nd_head;
@@ -5782,8 +6127,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN(match_values, line, dup);
ADD_INSN1(match_values, line, putobject, key);
ADD_SEND(match_values, line, node->nd_pkwrestarg ? rb_intern("delete") : idAREF, INT2FIX(1));
- iseq_compile_pattern_each(iseq, match_values, value_node, in_alt_pattern);
- ADD_INSNL(match_values, line, branchunless, match_failed);
+ CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_alt_pattern, FALSE));
args = args->nd_next->nd_next;
}
ADD_SEQ(ret, match_values);
@@ -5803,26 +6147,24 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
}
else {
ADD_INSN(ret, line, dup);
- iseq_compile_pattern_each(iseq, ret, node->nd_pkwrestarg, in_alt_pattern);
- ADD_INSNL(ret, line, branchunless, match_failed);
+ CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_pkwrestarg, match_failed, in_alt_pattern, FALSE));
}
}
ADD_INSN(ret, line, pop);
- ADD_INSN1(ret, line, putobject, Qtrue);
- ADD_INSNL(ret, line, jump, fin);
+ ADD_INSNL(ret, line, jump, matched);
+ ADD_INSN(ret, line, putnil);
ADD_LABEL(ret, type_error);
ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(ret, line, putobject, rb_eTypeError);
ADD_INSN1(ret, line, putobject, rb_fstring_lit("deconstruct_keys must return Hash"));
ADD_SEND(ret, line, id_core_raise, INT2FIX(2));
+ ADD_INSN(ret, line, pop);
ADD_LABEL(ret, match_failed);
ADD_INSN(ret, line, pop);
- ADD_INSN1(ret, line, putobject, Qfalse);
-
- ADD_LABEL(ret, fin);
+ ADD_INSNL(ret, line, jump, unmatched);
break;
}
case NODE_LIT:
@@ -5847,6 +6189,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
case NODE_COLON3:
CHECK(COMPILE(ret, "case in literal", node));
ADD_INSN1(ret, line, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
+ ADD_INSNL(ret, line, branchif, matched);
+ ADD_INSNL(ret, line, jump, unmatched);
break;
case NODE_LASGN: {
struct rb_iseq_constant_body *const body = iseq->body;
@@ -5863,7 +6207,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
}
ADD_SETLOCAL(ret, line, idx, get_lvar_level(iseq));
- ADD_INSN1(ret, line, putobject, Qtrue);
+ ADD_INSNL(ret, line, jump, matched);
break;
}
case NODE_DASGN:
@@ -5888,16 +6232,14 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
return COMPILE_NG;
}
ADD_SETLOCAL(ret, line, ls - idx, lv);
- ADD_INSN1(ret, line, putobject, Qtrue);
+ ADD_INSNL(ret, line, jump, matched);
break;
}
case NODE_IF:
case NODE_UNLESS: {
- LABEL *match_failed, *fin;
- match_failed = NEW_LABEL(line);
- fin = NEW_LABEL(line);
- iseq_compile_pattern_each(iseq, ret, node->nd_body, in_alt_pattern);
- ADD_INSNL(ret, line, branchunless, match_failed);
+ LABEL *match_failed;
+ match_failed = unmatched;
+ CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_body, unmatched, in_alt_pattern, deconstructed_pos));
CHECK(COMPILE(ret, "case in if", node->nd_cond));
if (nd_type(node) == NODE_IF) {
ADD_INSNL(ret, line, branchunless, match_failed);
@@ -5905,20 +6247,13 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
else {
ADD_INSNL(ret, line, branchif, match_failed);
}
- ADD_INSN1(ret, line, putobject, Qtrue);
- ADD_INSNL(ret, line, jump, fin);
-
- ADD_LABEL(ret, match_failed);
- ADD_INSN1(ret, line, putobject, Qfalse);
-
- ADD_LABEL(ret, fin);
+ ADD_INSNL(ret, line, jump, matched);
break;
}
case NODE_HASH: {
NODE *n;
- LABEL *match_failed, *fin;
+ LABEL *match_failed;
match_failed = NEW_LABEL(line);
- fin = NEW_LABEL(line);
n = node->nd_head;
if (! (nd_type(n) == NODE_LIST && n->nd_alen == 2)) {
@@ -5927,16 +6262,13 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
}
ADD_INSN(ret, line, dup);
- iseq_compile_pattern_each(iseq, ret, n->nd_head, in_alt_pattern);
- ADD_INSNL(ret, line, branchunless, match_failed);
- iseq_compile_pattern_each(iseq, ret, n->nd_next->nd_head, in_alt_pattern);
- ADD_INSNL(ret, line, jump, fin);
+ CHECK(iseq_compile_pattern_match(iseq, ret, n->nd_head, match_failed, in_alt_pattern, deconstructed_pos ? deconstructed_pos + 1 : FALSE));
+ CHECK(iseq_compile_pattern_each(iseq, ret, n->nd_next->nd_head, matched, match_failed, in_alt_pattern, FALSE));
+ ADD_INSN(ret, line, putnil);
ADD_LABEL(ret, match_failed);
ADD_INSN(ret, line, pop);
- ADD_INSN1(ret, line, putobject, Qfalse);
-
- ADD_LABEL(ret, fin);
+ ADD_INSNL(ret, line, jump, unmatched);
break;
}
case NODE_OR: {
@@ -5945,16 +6277,13 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
fin = NEW_LABEL(line);
ADD_INSN(ret, line, dup);
- iseq_compile_pattern_each(iseq, ret, node->nd_1st, TRUE);
- ADD_INSNL(ret, line, branchif, match_succeeded);
- iseq_compile_pattern_each(iseq, ret, node->nd_2nd, TRUE);
- ADD_INSNL(ret, line, jump, fin);
-
+ CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_1st, match_succeeded, fin, TRUE, deconstructed_pos ? deconstructed_pos + 1 : FALSE));
ADD_LABEL(ret, match_succeeded);
ADD_INSN(ret, line, pop);
- ADD_INSN1(ret, line, putobject, Qtrue);
-
+ ADD_INSNL(ret, line, jump, matched);
+ ADD_INSN(ret, line, putnil);
ADD_LABEL(ret, fin);
+ CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_2nd, matched, unmatched, TRUE, deconstructed_pos));
break;
}
default:
@@ -5964,6 +6293,71 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
}
static int
+iseq_compile_pattern_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *unmatched, int in_alt_pattern, int deconstructed_pos)
+{
+ LABEL *fin = NEW_LABEL(nd_line(node));
+ CHECK(iseq_compile_pattern_each(iseq, ret, node, fin, unmatched, in_alt_pattern, deconstructed_pos));
+ ADD_LABEL(ret, fin);
+ return COMPILE_OK;
+}
+
+static int
+iseq_compile_array_deconstruct(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *deconstruct, LABEL *deconstructed, LABEL *match_failed, LABEL *type_error, int deconstructed_pos)
+{
+ const int line = nd_line(node);
+
+ // NOTE: this optimization allows us to re-use the #deconstruct value
+ // (or its absence).
+ // `deconstructed_pos` contains the distance to the stack relative location
+ // where the value is stored.
+ if (deconstructed_pos) {
+ // If value is nil then we haven't tried to deconstruct
+ ADD_INSN1(ret, line, topn, INT2FIX(deconstructed_pos));
+ ADD_INSNL(ret, line, branchnil, deconstruct);
+
+ // If false then the value is not deconstructable
+ ADD_INSN1(ret, line, topn, INT2FIX(deconstructed_pos));
+ ADD_INSNL(ret, line, branchunless, match_failed);
+
+ // Drop value, add deconstructed to the stack and jump
+ ADD_INSN(ret, line, pop);
+ ADD_INSN1(ret, line, topn, INT2FIX(deconstructed_pos - 1));
+ ADD_INSNL(ret, line, jump, deconstructed);
+ }
+ else {
+ ADD_INSNL(ret, line, jump, deconstruct);
+ }
+
+ ADD_LABEL(ret, deconstruct);
+ ADD_INSN(ret, line, dup);
+ ADD_INSN1(ret, line, putobject, ID2SYM(rb_intern("deconstruct")));
+ ADD_SEND(ret, line, idRespond_to, INT2FIX(1));
+
+ // Cache the result of respond_to? (in case it's false is stays there, if true - it's overwritten after #deconstruct)
+ if (deconstructed_pos) {
+ ADD_INSN1(ret, line, setn, INT2FIX(deconstructed_pos + 1));
+ }
+
+ ADD_INSNL(ret, line, branchunless, match_failed);
+
+ ADD_SEND(ret, line, rb_intern("deconstruct"), INT2FIX(0));
+
+ // Cache the result (if it's cacheable - currently, only top-level array patterns)
+ if (deconstructed_pos) {
+ ADD_INSN1(ret, line, setn, INT2FIX(deconstructed_pos));
+ }
+
+ ADD_INSN(ret, line, dup);
+ ADD_INSN1(ret, line, checktype, INT2FIX(T_ARRAY));
+ ADD_INSNL(ret, line, branchunless, type_error);
+ ADD_INSNL(ret, line, jump, deconstructed);
+
+ ADD_LABEL(ret, deconstructed);
+
+ return COMPILE_OK;
+}
+
+static int
compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_node, int popped)
{
const NODE *pattern;
@@ -5972,44 +6366,46 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
DECL_ANCHOR(head);
DECL_ANCHOR(body_seq);
DECL_ANCHOR(cond_seq);
- int line, lineno, column, last_lineno, last_column;
+ int line;
enum node_type type;
VALUE branches = 0;
+ int branch_id = 0;
INIT_ANCHOR(head);
INIT_ANCHOR(body_seq);
INIT_ANCHOR(cond_seq);
- CHECK(COMPILE(head, "case base", node->nd_head));
-
- DECL_BRANCH_BASE(branches, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node), "case");
+ branches = decl_branch_base(iseq, node, "case");
node = node->nd_body;
EXPECT_NODE("NODE_CASE3", node, NODE_IN, COMPILE_NG);
type = nd_type(node);
line = nd_line(node);
- lineno = nd_first_lineno(node);
- column = nd_first_column(node);
- last_lineno = nd_last_lineno(node);
- last_column = nd_last_column(node);
endlabel = NEW_LABEL(line);
elselabel = NEW_LABEL(line);
+ ADD_INSN(head, line, putnil); /* allocate stack for cached #deconstruct value */
+
+ CHECK(COMPILE(head, "case base", orig_node->nd_head));
+
ADD_SEQ(ret, head); /* case VAL */
while (type == NODE_IN) {
LABEL *l1;
+ if (branch_id) {
+ ADD_INSN(body_seq, line, putnil);
+ }
l1 = NEW_LABEL(line);
ADD_LABEL(body_seq, l1);
ADD_INSN(body_seq, line, pop);
- ADD_TRACE_BRANCH_COVERAGE(
+ ADD_INSN(body_seq, line, pop); /* discard cached #deconstruct value */
+ add_trace_branch_coverage(
+ iseq,
body_seq,
- node->nd_body ? nd_first_lineno(node->nd_body) : lineno,
- node->nd_body ? nd_first_column(node->nd_body) : column,
- node->nd_body ? nd_last_lineno(node->nd_body) : last_lineno,
- node->nd_body ? nd_last_column(node->nd_body) : last_column,
+ node->nd_body ? node->nd_body : node,
+ branch_id++,
"in",
branches);
CHECK(COMPILE_(body_seq, "in body", node->nd_body, popped));
@@ -6017,9 +6413,14 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
pattern = node->nd_head;
if (pattern) {
- ADD_INSN (cond_seq, nd_line(pattern), dup);
- iseq_compile_pattern_each(iseq, cond_seq, pattern, FALSE);
- ADD_INSNL(cond_seq, nd_line(pattern), branchif, l1);
+ int pat_line = nd_line(pattern);
+ LABEL *next_pat = NEW_LABEL(pat_line);
+ ADD_INSN (cond_seq, pat_line, dup);
+ // NOTE: set deconstructed_pos to the current cached value location
+ // (it's "under" the matchee value, so it's position is 2)
+ CHECK(iseq_compile_pattern_each(iseq, cond_seq, pattern, l1, next_pat, FALSE, 2));
+ ADD_LABEL(cond_seq, next_pat);
+ LABEL_UNREMOVABLE(next_pat);
}
else {
COMPILE_ERROR(ERROR_ARGS "unexpected node");
@@ -6032,33 +6433,39 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
}
type = nd_type(node);
line = nd_line(node);
- lineno = nd_first_lineno(node);
- column = nd_first_column(node);
- last_lineno = nd_last_lineno(node);
- last_column = nd_last_column(node);
}
/* else */
if (node) {
ADD_LABEL(cond_seq, elselabel);
ADD_INSN(cond_seq, line, pop);
- ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node), "else", branches);
+ ADD_INSN(cond_seq, line, pop); /* discard cached #deconstruct value */
+ add_trace_branch_coverage(iseq, cond_seq, node, branch_id, "else", branches);
CHECK(COMPILE_(cond_seq, "else", node, popped));
ADD_INSNL(cond_seq, line, jump, endlabel);
+ ADD_INSN(cond_seq, line, putnil);
+ if (popped) {
+ ADD_INSN(cond_seq, line, putnil);
+ }
}
else {
debugs("== else (implicit)\n");
ADD_LABEL(cond_seq, elselabel);
- ADD_TRACE_BRANCH_COVERAGE(cond_seq, nd_first_lineno(orig_node), nd_first_column(orig_node), nd_last_lineno(orig_node), nd_last_column(orig_node), "else", branches);
+ add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches);
ADD_INSN1(cond_seq, nd_line(orig_node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(cond_seq, nd_line(orig_node), putobject, rb_eNoMatchingPatternError);
ADD_INSN1(cond_seq, nd_line(orig_node), topn, INT2FIX(2));
ADD_SEND(cond_seq, nd_line(orig_node), id_core_raise, INT2FIX(2));
ADD_INSN(cond_seq, nd_line(orig_node), pop);
ADD_INSN(cond_seq, nd_line(orig_node), pop);
+ ADD_INSN(cond_seq, nd_line(orig_node), pop); /* discard cached #deconstruct value */
if (!popped) {
ADD_INSN(cond_seq, nd_line(orig_node), putnil);
}
ADD_INSNL(cond_seq, nd_line(orig_node), jump, endlabel);
+ ADD_INSN(cond_seq, line, putnil);
+ if (popped) {
+ ADD_INSN(cond_seq, line, putnil);
+ }
}
ADD_SEQ(ret, cond_seq);
@@ -6071,10 +6478,7 @@ static int
compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
{
const int line = (int)nd_line(node);
- const int lineno = nd_first_lineno(node);
- const int column = nd_first_column(node);
- const int last_lineno = nd_last_lineno(node);
- const int last_column = nd_last_column(node);
+
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;
@@ -6110,13 +6514,12 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
if (tmp_label) ADD_LABEL(ret, tmp_label);
ADD_LABEL(ret, redo_label);
- DECL_BRANCH_BASE(branches, lineno, column, last_lineno, last_column, type == NODE_WHILE ? "while" : "until");
- ADD_TRACE_BRANCH_COVERAGE(
+ branches = decl_branch_base(iseq, node, type == NODE_WHILE ? "while" : "until");
+ add_trace_branch_coverage(
+ iseq,
ret,
- node->nd_body ? nd_first_lineno(node->nd_body) : lineno,
- node->nd_body ? nd_first_column(node->nd_body) : column,
- node->nd_body ? nd_last_lineno(node->nd_body) : last_lineno,
- node->nd_body ? nd_last_column(node->nd_body) : last_column,
+ node->nd_body ? node->nd_body : node,
+ 0,
"body",
branches);
CHECK(COMPILE_POPPED(ret, "while body", node->nd_body));
@@ -6253,22 +6656,8 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
ADD_INSN(ret, line, putnil);
}
}
- else if (iseq->body->type == ISEQ_TYPE_BLOCK) {
- break_by_insn:
- /* escape from block */
- CHECK(COMPILE(ret, "break val (block)", node->nd_stts));
- ADD_INSN1(ret, line, throw, INT2FIX(throw_flag | TAG_BREAK));
- if (popped) {
- ADD_INSN(ret, line, pop);
- }
- }
- else if (iseq->body->type == ISEQ_TYPE_EVAL) {
- break_in_eval:
- COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break");
- return COMPILE_NG;
- }
else {
- const rb_iseq_t *ip = iseq->body->parent_iseq;
+ const rb_iseq_t *ip = iseq;
while (ip) {
if (!ISEQ_COMPILE_DATA(ip)) {
@@ -6278,16 +6667,26 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
throw_flag = VM_THROW_NO_ESCAPE_FLAG;
- goto break_by_insn;
}
else if (ip->body->type == ISEQ_TYPE_BLOCK) {
- goto break_by_insn;
+ throw_flag = 0;
}
else if (ip->body->type == ISEQ_TYPE_EVAL) {
- goto break_in_eval;
+ COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break");
+ return COMPILE_NG;
}
+ else {
+ ip = ip->body->parent_iseq;
+ continue;
+ }
- ip = ip->body->parent_iseq;
+ /* escape from block */
+ CHECK(COMPILE(ret, "break val (block)", node->nd_stts));
+ ADD_INSN1(ret, line, throw, INT2FIX(throw_flag | TAG_BREAK));
+ if (popped) {
+ ADD_INSN(ret, line, pop);
+ }
+ return COMPILE_OK;
}
COMPILE_ERROR(ERROR_ARGS "Invalid break");
return COMPILE_NG;
@@ -6329,11 +6728,6 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
ADD_INSN(ret, line, putnil);
}
}
- else if (iseq->body->type == ISEQ_TYPE_EVAL) {
- next_in_eval:
- COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next");
- return COMPILE_NG;
- }
else {
const rb_iseq_t *ip = iseq;
@@ -6352,7 +6746,8 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
break;
}
else if (ip->body->type == ISEQ_TYPE_EVAL) {
- goto next_in_eval;
+ COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with next");
+ return COMPILE_NG;
}
ip = ip->body->parent_iseq;
@@ -6390,12 +6785,7 @@ compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
ADD_INSN(ret, line, putnil);
}
}
- else if (iseq->body->type == ISEQ_TYPE_EVAL) {
- redo_in_eval:
- COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with redo");
- return COMPILE_NG;
- }
- else if (ISEQ_COMPILE_DATA(iseq)->start_label) {
+ else if (iseq->body->type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label) {
LABEL *splabel = NEW_LABEL(0);
debugs("redo in block");
@@ -6425,7 +6815,8 @@ compile_redo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
break;
}
else if (ip->body->type == ISEQ_TYPE_EVAL) {
- goto redo_in_eval;
+ COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with redo");
+ return COMPILE_NG;
}
ip = ip->body->parent_iseq;
@@ -6685,15 +7076,13 @@ static LABEL *
qcall_branch_start(rb_iseq_t *iseq, LINK_ANCHOR *const recv, VALUE *branches, const NODE *node, int line)
{
LABEL *else_label = NEW_LABEL(line);
- const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node);
- const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node);
VALUE br = 0;
- DECL_BRANCH_BASE(br, first_lineno, first_column, last_lineno, last_column, "&.");
+ br = decl_branch_base(iseq, node, "&.");
*branches = br;
ADD_INSN(recv, line, dup);
ADD_INSNL(recv, line, branchnil, else_label);
- ADD_TRACE_BRANCH_COVERAGE(recv, first_lineno, first_column, last_lineno, last_column, "then", br);
+ add_trace_branch_coverage(iseq, recv, node, 0, "then", br);
return else_label;
}
@@ -6705,8 +7094,7 @@ qcall_branch_end(rb_iseq_t *iseq, LINK_ANCHOR *const ret, LABEL *else_label, VAL
end_label = NEW_LABEL(line);
ADD_INSNL(ret, line, jump, end_label);
ADD_LABEL(ret, else_label);
- ADD_TRACE_BRANCH_COVERAGE(ret, nd_first_lineno(node), nd_first_column(node), nd_last_lineno(node), nd_last_column(node),
- "else", branches);
+ add_trace_branch_coverage(iseq, ret, node, 1, "else", branches);
ADD_LABEL(ret, end_label);
}
@@ -6778,18 +7166,39 @@ iseq_builtin_function_lookup(const rb_iseq_t *iseq, const char *name)
}
static const char *
-iseq_builtin_function_name(ID mid)
+iseq_builtin_function_name(const enum node_type type, const NODE *recv, ID mid)
{
const char *name = rb_id2name(mid);
static const char prefix[] = "__builtin_";
const size_t prefix_len = sizeof(prefix) - 1;
- if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) {
- return &name[prefix_len];
- }
- else {
- return NULL;
+ switch (type) {
+ case NODE_CALL:
+ if (recv) {
+ switch (nd_type(recv)) {
+ case NODE_VCALL:
+ if (recv->nd_mid == rb_intern("__builtin")) {
+ return name;
+ }
+ break;
+ case NODE_CONST:
+ if (recv->nd_vid == rb_intern("Primitive")) {
+ return name;
+ }
+ break;
+ default: break;
+ }
+ }
+ break;
+ case NODE_VCALL:
+ case NODE_FCALL:
+ if (UNLIKELY(strncmp(prefix, name, prefix_len) == 0)) {
+ return &name[prefix_len];
+ }
+ break;
+ default: break;
}
+ return NULL;
}
static int
@@ -6855,7 +7264,93 @@ delegate_call_p(const rb_iseq_t *iseq, unsigned int argc, const LINK_ANCHOR *arg
}
static int
-compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int type, int line, int popped)
+compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int line, int popped,
+ const rb_iseq_t *parent_block, LINK_ANCHOR *args, const char *builtin_func)
+{
+ NODE *args_node = node->nd_args;
+
+ if (parent_block != NULL) {
+ COMPILE_ERROR(iseq, line, "should not call builtins here.");
+ return COMPILE_NG;
+ }
+ else {
+# define BUILTIN_INLINE_PREFIX "_bi"
+ char inline_func[DECIMAL_SIZE_OF_BITS(sizeof(int) * CHAR_BIT) + sizeof(BUILTIN_INLINE_PREFIX)];
+ bool cconst = false;
+ retry:;
+ const struct rb_builtin_function *bf = iseq_builtin_function_lookup(iseq, builtin_func);
+
+ if (bf == NULL) {
+ if (strcmp("cstmt!", builtin_func) == 0 ||
+ strcmp("cexpr!", builtin_func) == 0) {
+ // ok
+ }
+ else if (strcmp("cconst!", builtin_func) == 0) {
+ cconst = true;
+ }
+ else if (strcmp("cinit!", builtin_func) == 0) {
+ // ignore
+ GET_VM()->builtin_inline_index++;
+ return COMPILE_OK;
+ }
+ else if (strcmp("attr!", builtin_func) == 0) {
+ // There's only "inline" attribute for now
+ iseq->body->builtin_inline_p = true;
+ return COMPILE_OK;
+ }
+ else if (1) {
+ rb_bug("can't find builtin function:%s", builtin_func);
+ }
+ else {
+ COMPILE_ERROR(ERROR_ARGS "can't find builtin function:%s", builtin_func);
+ return COMPILE_NG;
+ }
+
+ if (GET_VM()->builtin_inline_index == INT_MAX) {
+ rb_bug("builtin inline function index overflow:%s", builtin_func);
+ }
+ int inline_index = GET_VM()->builtin_inline_index++;
+ snprintf(inline_func, sizeof(inline_func), BUILTIN_INLINE_PREFIX "%d", inline_index);
+ builtin_func = inline_func;
+ args_node = NULL;
+ goto retry;
+ }
+
+ if (cconst) {
+ typedef VALUE(*builtin_func0)(void *, VALUE);
+ VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL, Qnil);
+ ADD_INSN1(ret, line, putobject, const_val);
+ return COMPILE_OK;
+ }
+
+ // fprintf(stderr, "func_name:%s -> %p\n", builtin_func, bf->func_ptr);
+
+ unsigned int flag = 0;
+ struct rb_callinfo_kwarg *keywords = NULL;
+ VALUE argc = setup_args(iseq, args, args_node, &flag, &keywords);
+
+ if (FIX2INT(argc) != bf->argc) {
+ COMPILE_ERROR(ERROR_ARGS "argc is not match for builtin function:%s (expect %d but %d)",
+ builtin_func, bf->argc, FIX2INT(argc));
+ return COMPILE_NG;
+ }
+
+ unsigned int start_index;
+ if (delegate_call_p(iseq, FIX2INT(argc), args, &start_index)) {
+ ADD_INSN2(ret, line, opt_invokebuiltin_delegate, bf, INT2FIX(start_index));
+ }
+ else {
+ ADD_SEQ(ret, args);
+ ADD_INSN1(ret,line, invokebuiltin, bf);
+ }
+
+ if (popped) ADD_INSN(ret, line, pop);
+ return COMPILE_OK;
+ }
+}
+
+static int
+compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const enum node_type type, int line, int popped)
{
/* call: obj.method(...)
* fcall: func(...)
@@ -6866,7 +7361,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
ID mid = node->nd_mid;
VALUE argc;
unsigned int flag = 0;
- struct rb_call_info_kw_arg *keywords = NULL;
+ struct rb_callinfo_kwarg *keywords = NULL;
const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
LABEL *else_label = NULL;
VALUE branches = Qfalse;
@@ -6939,83 +7434,13 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
}
}
#endif
- const char *builtin_func;
- NODE *args_node = node->nd_args;
+ const char *builtin_func;
if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
- (builtin_func = iseq_builtin_function_name(mid)) != NULL) {
-
- if (parent_block != NULL) {
- COMPILE_ERROR(iseq, line, "should not call builtins here.");
- return COMPILE_NG;
- }
- else {
- char inline_func[0x20];
- bool cconst = false;
- retry:;
- const struct rb_builtin_function *bf = iseq_builtin_function_lookup(iseq, builtin_func);
-
- if (bf == NULL) {
- if (strcmp("cstmt!", builtin_func) == 0 ||
- strcmp("cexpr!", builtin_func) == 0) {
- inlinec:;
- int inline_index = GET_VM()->builtin_inline_index++;
- snprintf(inline_func, 0x20, "_bi%d", inline_index);
- builtin_func = inline_func;
- args_node = NULL;
- goto retry;
- }
- else if (strcmp("cconst!", builtin_func) == 0) {
- cconst = true;
- goto inlinec;
- }
- else if (strcmp("cinit!", builtin_func) == 0) {
- // ignore
- GET_VM()->builtin_inline_index++;
- return COMPILE_OK;
- }
-
- if (1) {
- rb_bug("can't find builtin function:%s", builtin_func);
- }
- else {
- COMPILE_ERROR(ERROR_ARGS "can't find builtin function:%s", builtin_func);
- }
- return COMPILE_NG;
- }
-
- if (cconst) {
- typedef VALUE(*builtin_func0)(void *, VALUE);
- VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL, Qnil);
- ADD_INSN1(ret, line, putobject, const_val);
- return COMPILE_OK;
- }
-
- // fprintf(stderr, "func_name:%s -> %p\n", builtin_func, bf->func_ptr);
-
- argc = setup_args(iseq, args, args_node, &flag, &keywords);
-
- if (FIX2INT(argc) != bf->argc) {
- COMPILE_ERROR(ERROR_ARGS "argc is not match for builtin function:%s (expect %d but %d)",
- builtin_func, bf->argc, FIX2INT(argc));
- return COMPILE_NG;
- }
-
- unsigned int start_index;
- if (delegate_call_p(iseq, FIX2INT(argc), args, &start_index)) {
- ADD_INSN2(ret, line, opt_invokebuiltin_delegate, bf, INT2FIX(start_index));
- }
- else {
- ADD_SEQ(ret, args);
- ADD_INSN1(ret,line, invokebuiltin, bf);
- }
-
- if (popped) ADD_INSN(ret, line, pop);
- return COMPILE_OK;
- }
+ (builtin_func = iseq_builtin_function_name(type, node->nd_recv, mid)) != NULL) {
+ return compile_builtin_function_call(iseq, ret, node, line, popped, parent_block, args, builtin_func);
}
-
/* receiver */
if (type == NODE_CALL || type == NODE_OPCALL || type == NODE_QCALL) {
int idx, level;
@@ -7098,20 +7523,13 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *node, int poppe
}
static int
-check_yield_place(const rb_iseq_t *iseq, int line)
+check_yield_place(const rb_iseq_t *iseq)
{
- VALUE file;
switch (iseq->body->local_iseq->body->type) {
case ISEQ_TYPE_TOP:
case ISEQ_TYPE_MAIN:
- return FALSE;
case ISEQ_TYPE_CLASS:
- file = rb_iseq_path(iseq);
- if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) {
- rb_compile_warn(RSTRING_PTR(file), line,
- "`yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575]");
- }
- return TRUE;
+ return FALSE;
default:
return TRUE;
}
@@ -7270,8 +7688,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
if (!popped) {
ADD_INSN(ret, line, dup);
}
- ADD_INSN1(ret, line, setglobal,
- ((VALUE)node->nd_entry | 1));
+ ADD_INSN1(ret, line, setglobal, ID2SYM(node->nd_entry));
break;
}
case NODE_IASGN:{
@@ -7623,7 +8040,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
LABEL *lfin = NEW_LABEL(line);
LABEL *lassign;
- if (nd_type(node) == NODE_OP_ASGN_OR) {
+ if (nd_type(node) == NODE_OP_ASGN_OR && nd_type(node->nd_head) != NODE_IVAR) {
LABEL *lfinish[2];
lfinish[0] = lfin;
lfinish[1] = 0;
@@ -7676,7 +8093,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
DECL_ANCHOR(args);
int argc;
unsigned int flag = 0;
- struct rb_call_info_kw_arg *keywords = NULL;
+ struct rb_callinfo_kwarg *keywords = NULL;
const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block;
INIT_ANCHOR(args);
@@ -7756,10 +8173,10 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
if (local_body->param.flags.has_kwrest) {
int idx = local_body->local_table_size - local_kwd->rest_start;
ADD_GETLOCAL(args, line, idx, lvar_level);
- ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0));
}
else {
ADD_INSN1(args, line, newhash, INT2FIX(0));
+ flag |= VM_CALL_KW_SPLAT_MUT;
}
for (i = 0; i < local_kwd->num; ++i) {
ID id = local_kwd->table[i];
@@ -7779,7 +8196,6 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
int idx = local_body->local_table_size - local_kwd->rest_start;
ADD_GETLOCAL(args, line, idx, lvar_level);
- ADD_SEND (args, line, rb_intern("dup"), INT2FIX(0));
if (local_body->param.flags.has_rest) {
ADD_INSN1(args, line, newarray, INT2FIX(1));
ADD_INSN (args, line, concatarray);
@@ -7825,7 +8241,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
break;
}
case NODE_HASH:
- CHECK(compile_hash(iseq, ret, node, popped) >= 0);
+ CHECK(compile_hash(iseq, ret, node, FALSE, popped) >= 0);
break;
case NODE_RETURN:
CHECK(compile_return(iseq, ret, node, popped));
@@ -7834,11 +8250,11 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
DECL_ANCHOR(args);
VALUE argc;
unsigned int flag = 0;
- struct rb_call_info_kw_arg *keywords = NULL;
+ struct rb_callinfo_kwarg *keywords = NULL;
INIT_ANCHOR(args);
- if (check_yield_place(iseq, line) == FALSE) {
+ if (check_yield_place(iseq) == FALSE) {
COMPILE_ERROR(ERROR_ARGS "Invalid yield");
goto ng;
}
@@ -7857,6 +8273,13 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
if (popped) {
ADD_INSN(ret, line, pop);
}
+
+ int level = 0;
+ const rb_iseq_t *tmp_iseq = iseq;
+ for (; tmp_iseq != iseq->body->local_iseq; level++ ) {
+ tmp_iseq = tmp_iseq->body->parent_iseq;
+ }
+ if (level > 0) access_outer_variables(iseq, level, rb_intern("yield"), true);
break;
}
case NODE_LVAR:{
@@ -7884,8 +8307,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
break;
}
case NODE_GVAR:{
- ADD_INSN1(ret, line, getglobal,
- ((VALUE)node->nd_entry | 1));
+ ADD_INSN1(ret, line, getglobal, ID2SYM(node->nd_entry));
if (popped) {
ADD_INSN(ret, line, pop);
}
@@ -7990,6 +8412,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
debugp_param("lit", node->nd_lit);
if (!popped) {
ADD_INSN1(ret, line, putobject, node->nd_lit);
+ RB_OBJ_WRITTEN(iseq, Qundef, node->nd_lit);
}
break;
}
@@ -8024,18 +8447,6 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
if (popped) {
ADD_INSN(ret, line, pop);
}
- else {
- if (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
- VALUE debug_info = Qnil;
- if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
- debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line));
- }
- ADD_INSN1(ret, line, freezestring, debug_info);
- if (!NIL_P(debug_info)) {
- RB_OBJ_WRITTEN(iseq, Qundef, rb_obj_freeze(debug_info));
- }
- }
- }
break;
}
case NODE_XSTR:{
@@ -8316,10 +8727,13 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in
VALUE flag = INT2FIX(excl);
const NODE *b = node->nd_beg;
const NODE *e = node->nd_end;
- if (number_literal_p(b) && number_literal_p(e)) {
+
+ if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
if (!popped) {
- VALUE val = rb_range_new(b->nd_lit, e->nd_lit, excl);
- ADD_INSN1(ret, line, putobject, val);
+ VALUE bv = nd_type(b) == NODE_LIT ? b->nd_lit : Qnil;
+ VALUE ev = nd_type(e) == NODE_LIT ? e->nd_lit : Qnil;
+ VALUE val = rb_range_new(bv, ev, excl);
+ ADD_INSN1(ret, line, putobject, val);
RB_OBJ_WRITTEN(iseq, Qundef, val);
}
}
@@ -8592,15 +9006,16 @@ calc_sp_depth(int depth, INSN *insn)
static VALUE
opobj_inspect(VALUE obj)
{
- struct RBasic *r = (struct RBasic *) obj;
- if (!SPECIAL_CONST_P(r) && r->klass == 0) {
- switch (BUILTIN_TYPE(r)) {
+ if (!SPECIAL_CONST_P(obj) && !RBASIC_CLASS(obj)) {
+ switch (BUILTIN_TYPE(obj)) {
case T_STRING:
obj = rb_str_new_cstr(RSTRING_PTR(obj));
break;
case T_ARRAY:
obj = rb_ary_dup(obj);
break;
+ default:
+ break;
}
}
return rb_inspect(obj);
@@ -8643,19 +9058,16 @@ insn_data_to_s_detail(INSN *iobj)
case TS_VALUE: /* VALUE */
{
VALUE v = OPERAND_AT(iobj, j);
- rb_str_concat(str, opobj_inspect(v));
+ if (!CLASS_OF(v))
+ rb_str_cat2(str, "<hidden>");
+ else {
+ rb_str_concat(str, opobj_inspect(v));
+ }
break;
}
case TS_ID: /* ID */
rb_str_concat(str, opobj_inspect(OPERAND_AT(iobj, j)));
break;
- case TS_GENTRY:
- {
- struct rb_global_entry *entry = (struct rb_global_entry *)
- (OPERAND_AT(iobj, j) & (~1));
- rb_str_append(str, rb_id2str(entry->id));
- break;
- }
case TS_IC: /* inline cache */
case TS_IVC: /* inline ivar cache */
case TS_ISE: /* inline storage entry */
@@ -8663,10 +9075,10 @@ insn_data_to_s_detail(INSN *iobj)
break;
case TS_CALLDATA: /* we store these as call infos at compile time */
{
- const struct rb_call_info *ci = (struct rb_call_info *)OPERAND_AT(iobj, j);
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, j);
rb_str_cat2(str, "<calldata:");
- if (ci->mid) rb_str_catf(str, "%"PRIsVALUE, rb_id2str(ci->mid));
- rb_str_catf(str, ", %d>", ci->orig_argc);
+ if (vm_ci_mid(ci)) rb_str_catf(str, "%"PRIsVALUE, rb_id2str(vm_ci_mid(ci)));
+ rb_str_catf(str, ", %d>", vm_ci_argc(ci));
break;
}
case TS_CDHASH: /* case/when condition cache */
@@ -8686,7 +9098,7 @@ insn_data_to_s_detail(INSN *iobj)
}
break;
case TS_BUILTIN:
- rb_bug("unsupported: TS_BUILTIN");
+ rb_str_cat2(str, "<TS_BUILTIN>");
break;
default:{
rb_raise(rb_eSyntaxError, "unknown operand type: %c", type);
@@ -8723,7 +9135,7 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr,
{
iobj = (INSN *)link;
str = insn_data_to_s_detail(iobj);
- printf("%04d %-65s(%4u)\n", pos, StringValueCStr(str), iobj->insn_info.line_no);
+ printf(" %04d %-65s(%4u)\n", pos, StringValueCStr(str), iobj->insn_info.line_no);
pos += insn_data_length(iobj);
break;
}
@@ -8737,13 +9149,13 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr,
case ISEQ_ELEMENT_TRACE:
{
TRACE *trace = (TRACE *)link;
- printf("trace: %0x\n", trace->event);
+ printf(" trace: %0x\n", trace->event);
break;
}
case ISEQ_ELEMENT_ADJUST:
{
ADJUST *adjust = (ADJUST *)link;
- printf("adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1);
+ printf(" adjust: [label: %d]\n", adjust->label ? adjust->label->label_no : -1);
break;
}
default:
@@ -8794,18 +9206,16 @@ register_label(rb_iseq_t *iseq, struct st_table *labels_table, VALUE obj)
static VALUE
get_exception_sym2type(VALUE sym)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
static VALUE symRescue, symEnsure, symRetry;
static VALUE symBreak, symRedo, symNext;
if (symRescue == 0) {
- symRescue = ID2SYM(rb_intern("rescue"));
- symEnsure = ID2SYM(rb_intern("ensure"));
- symRetry = ID2SYM(rb_intern("retry"));
- symBreak = ID2SYM(rb_intern("break"));
- symRedo = ID2SYM(rb_intern("redo"));
- symNext = ID2SYM(rb_intern("next"));
+ symRescue = ID2SYM(rb_intern_const("rescue"));
+ symEnsure = ID2SYM(rb_intern_const("ensure"));
+ symRetry = ID2SYM(rb_intern_const("retry"));
+ symBreak = ID2SYM(rb_intern_const("break"));
+ symRedo = ID2SYM(rb_intern_const("redo"));
+ symNext = ID2SYM(rb_intern_const("next"));
}
if (sym == symRescue) return CATCH_TYPE_RESCUE;
@@ -8871,7 +9281,7 @@ insn_make_insn_table(void)
table = st_init_numtable_with_size(VM_INSTRUCTION_SIZE);
for (i=0; i<VM_INSTRUCTION_SIZE; i++) {
- st_insert(table, ID2SYM(rb_intern(insn_name(i))), i);
+ st_insert(table, ID2SYM(rb_intern_const(insn_name(i))), i);
}
return table;
@@ -8903,13 +9313,13 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op)
ID mid = 0;
int orig_argc = 0;
unsigned int flag = 0;
- struct rb_call_info_kw_arg *kw_arg = 0;
+ struct rb_callinfo_kwarg *kw_arg = 0;
if (!NIL_P(op)) {
- VALUE vmid = rb_hash_aref(op, ID2SYM(rb_intern("mid")));
- VALUE vflag = rb_hash_aref(op, ID2SYM(rb_intern("flag")));
- VALUE vorig_argc = rb_hash_aref(op, ID2SYM(rb_intern("orig_argc")));
- VALUE vkw_arg = rb_hash_aref(op, ID2SYM(rb_intern("kw_arg")));
+ VALUE vmid = rb_hash_aref(op, ID2SYM(rb_intern_const("mid")));
+ VALUE vflag = rb_hash_aref(op, ID2SYM(rb_intern_const("flag")));
+ VALUE vorig_argc = rb_hash_aref(op, ID2SYM(rb_intern_const("orig_argc")));
+ VALUE vkw_arg = rb_hash_aref(op, ID2SYM(rb_intern_const("kw_arg")));
if (!NIL_P(vmid)) mid = SYM2ID(vmid);
if (!NIL_P(vflag)) flag = NUM2UINT(vflag);
@@ -8918,7 +9328,7 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op)
if (!NIL_P(vkw_arg)) {
int i;
int len = RARRAY_LENINT(vkw_arg);
- size_t n = rb_call_info_kw_arg_bytes(len);
+ size_t n = rb_callinfo_kwarg_bytes(len);
kw_arg = xmalloc(n);
kw_arg->keyword_len = len;
@@ -8930,13 +9340,15 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op)
}
}
- return (VALUE)new_callinfo(iseq, mid, orig_argc, flag, kw_arg, (flag & VM_CALL_ARGS_SIMPLE) == 0);
+ const struct rb_callinfo *ci = new_callinfo(iseq, mid, orig_argc, flag, kw_arg, (flag & VM_CALL_ARGS_SIMPLE) == 0);
+ RB_OBJ_WRITTEN(iseq, Qundef, ci);
+ return (VALUE)ci;
}
static rb_event_flag_t
event_name_to_flag(VALUE sym)
{
-#define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern(#ev))) return ev;
+#define CHECK_EVENT(ev) if (sym == ID2SYM(rb_intern_const(#ev))) return ev;
CHECK_EVENT(RUBY_EVENT_LINE);
CHECK_EVENT(RUBY_EVENT_CLASS);
CHECK_EVENT(RUBY_EVENT_END);
@@ -9007,7 +9419,13 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
}
if (argc > 0) {
- argv = compile_data_alloc2(iseq, sizeof(VALUE), argc);
+ argv = compile_data_calloc2(iseq, sizeof(VALUE), argc);
+
+ // add element before operand setup to make GC root
+ ADD_ELEM(anchor,
+ (LINK_ELEMENT*)new_insn_core(iseq, line_no,
+ (enum ruby_vminsn_type)insn_id, argc, argv));
+
for (j=0; j<argc; j++) {
VALUE op = rb_ary_entry(obj, j+1);
switch (insn_op_type((VALUE)insn_id, j)) {
@@ -9037,19 +9455,14 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
}
}
break;
- case TS_GENTRY:
- op = rb_to_symbol_type(op);
- argv[j] = (VALUE)rb_global_entry(SYM2ID(op));
- break;
case TS_ISE:
- FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
- /* fall through */
case TS_IC:
case TS_IVC: /* inline ivar cache */
argv[j] = op;
if (NUM2UINT(op) >= iseq->body->is_size) {
iseq->body->is_size = NUM2INT(op) + 1;
}
+ FL_SET((VALUE)iseq, ISEQ_MARKABLE_ISEQ);
break;
case TS_CALLDATA:
argv[j] = iseq_build_callinfo_from_hash(iseq, op);
@@ -9091,9 +9504,11 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
}
}
}
- ADD_ELEM(anchor,
- (LINK_ELEMENT*)new_insn_core(iseq, line_no,
- (enum ruby_vminsn_type)insn_id, argc, argv));
+ else {
+ ADD_ELEM(anchor,
+ (LINK_ELEMENT*)new_insn_core(iseq, line_no,
+ (enum ruby_vminsn_type)insn_id, argc, NULL));
+ }
}
else {
rb_raise(rb_eTypeError, "unexpected object for instruction");
@@ -9137,7 +9552,7 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
iseq->body->param.flags.has_kw = TRUE;
keyword->num = len;
-#define SYM(s) ID2SYM(rb_intern(#s))
+#define SYM(s) ID2SYM(rb_intern_const(#s))
(void)int_param(&keyword->bits_start, params, SYM(kwbits));
i = keyword->bits_start - keyword->num;
ids = (ID *)&iseq->body->local_table[i];
@@ -9227,13 +9642,15 @@ rb_iseq_mark_insn_storage(struct iseq_compile_data_storage *storage)
case TS_CDHASH:
case TS_ISEQ:
case TS_VALUE:
+ case TS_CALLDATA: // ci is stored.
{
VALUE op = OPERAND_AT(iobj, j);
+
if (!SPECIAL_CONST_P(op)) {
rb_gc_mark(op);
}
- break;
}
+ break;
default:
break;
}
@@ -9248,7 +9665,7 @@ void
rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
VALUE exception, VALUE body)
{
-#define SYM(s) ID2SYM(rb_intern(#s))
+#define SYM(s) ID2SYM(rb_intern_const(#s))
int i, len;
unsigned int arg_size, local_size, stack_max;
ID *tbl;
@@ -9256,7 +9673,7 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params,
VALUE labels_wrapper = Data_Wrap_Struct(0, rb_mark_set, st_free_table, labels_table);
VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt));
VALUE keywords = rb_hash_aref(params, SYM(keyword));
- VALUE sym_arg_rest = ID2SYM(rb_intern("#arg_rest"));
+ VALUE sym_arg_rest = ID2SYM(rb_intern_const("#arg_rest"));
DECL_ANCHOR(anchor);
INIT_ANCHOR(anchor);
@@ -9414,19 +9831,19 @@ caller_location(VALUE *path, VALUE *realpath)
typedef struct {
VALUE arg;
- rb_insn_func_t func;
+ VALUE func;
int line;
} accessor_args;
static const rb_iseq_t *
-method_for_self(VALUE name, VALUE arg, rb_insn_func_t func,
+method_for_self(VALUE name, VALUE arg, const struct rb_builtin_function *func,
void (*build)(rb_iseq_t *, LINK_ANCHOR *, const void *))
{
VALUE path, realpath;
accessor_args acc;
acc.arg = arg;
- acc.func = func;
+ acc.func = (VALUE)func;
acc.line = caller_location(&path, &realpath);
struct rb_iseq_new_with_callback_callback_func *ifunc =
rb_iseq_new_with_callback_new_callback(build, &acc);
@@ -9447,7 +9864,7 @@ for_self_aref(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *a)
body->param.size = 0;
ADD_INSN1(ret, line, putobject, args->arg);
- ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func);
+ ADD_INSN1(ret, line, invokebuiltin, args->func);
}
static void
@@ -9464,24 +9881,23 @@ for_self_aset(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *a)
ADD_GETLOCAL(ret, line, numberof(vars)-1, 0);
ADD_INSN1(ret, line, putobject, args->arg);
- ADD_INSN1(ret, line, opt_call_c_function, (VALUE)args->func);
- ADD_INSN(ret, line, pop);
+ ADD_INSN1(ret, line, invokebuiltin, args->func);
}
/*
* func (index) -> (value)
*/
const rb_iseq_t *
-rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func)
+rb_method_for_self_aref(VALUE name, VALUE arg, const struct rb_builtin_function *func)
{
return method_for_self(name, arg, func, for_self_aref);
}
/*
- * func (index, value) -> (index, value)
+ * func (index, value) -> (value)
*/
const rb_iseq_t *
-rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func)
+rb_method_for_self_aset(VALUE name, VALUE arg, const struct rb_builtin_function *func)
{
return method_for_self(name, arg, func, for_self_aset);
}
@@ -9501,7 +9917,7 @@ typedef unsigned int ibf_offset_t;
#define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
#if RUBY_DEVEL
-#define IBF_DEVEL_VERSION 2
+#define IBF_DEVEL_VERSION 3
#define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
#else
#define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
@@ -9522,11 +9938,10 @@ struct ibf_header {
struct ibf_dump_buffer {
VALUE str;
- VALUE obj_list; /* [objs] */
+ st_table *obj_table; /* obj -> obj number */
};
struct ibf_dump {
- VALUE iseq_list; /* [iseqs] */
st_table *iseq_table; /* iseq -> iseq number */
struct ibf_dump_buffer global_buffer;
struct ibf_dump_buffer *current_buffer;
@@ -9553,6 +9968,85 @@ struct ibf_load {
struct ibf_load_buffer *current_buffer;
};
+struct pinned_list {
+ long size;
+ VALUE * buffer;
+};
+
+static void
+pinned_list_mark(void *ptr)
+{
+ long i;
+ struct pinned_list *list = (struct pinned_list *)ptr;
+ for (i = 0; i < list->size; i++) {
+ if (list->buffer[i]) {
+ rb_gc_mark(list->buffer[i]);
+ }
+ }
+}
+
+static void
+pinned_list_free(void *ptr)
+{
+ struct pinned_list *list = (struct pinned_list *)ptr;
+ xfree(list->buffer);
+ xfree(ptr);
+}
+
+static size_t
+pinned_list_memsize(const void *ptr)
+{
+ struct pinned_list *list = (struct pinned_list *)ptr;
+ return sizeof(struct pinned_list) + (list->size * sizeof(VALUE *));
+}
+
+static const rb_data_type_t pinned_list_type = {
+ "pinned_list",
+ {pinned_list_mark, pinned_list_free, pinned_list_memsize,},
+ 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE
+pinned_list_fetch(VALUE list, long offset)
+{
+ struct pinned_list * ptr;
+
+ TypedData_Get_Struct(list, struct pinned_list, &pinned_list_type, ptr);
+
+ if (offset >= ptr->size) {
+ rb_raise(rb_eIndexError, "object index out of range: %ld", offset);
+ }
+
+ return ptr->buffer[offset];
+}
+
+static void
+pinned_list_store(VALUE list, long offset, VALUE object)
+{
+ struct pinned_list * ptr;
+
+ TypedData_Get_Struct(list, struct pinned_list, &pinned_list_type, ptr);
+
+ if (offset >= ptr->size) {
+ rb_raise(rb_eIndexError, "object index out of range: %ld", offset);
+ }
+
+ RB_OBJ_WRITE(list, &ptr->buffer[offset], object);
+}
+
+static VALUE
+pinned_list_new(long size)
+{
+ struct pinned_list * ptr;
+ VALUE obj_list =
+ TypedData_Make_Struct(0, struct pinned_list, &pinned_list_type, ptr);
+
+ ptr->buffer = xcalloc(size, sizeof(VALUE));
+ ptr->size = size;
+
+ return obj_list;
+}
+
static ibf_offset_t
ibf_dump_pos(struct ibf_dump *dump)
{
@@ -9648,7 +10142,7 @@ ibf_table_lookup(struct st_table *table, st_data_t key)
}
static int
-ibf_table_index(struct st_table *table, st_data_t key)
+ibf_table_find_or_insert(struct st_table *table, st_data_t key)
{
int index = ibf_table_lookup(table, key);
@@ -9667,26 +10161,19 @@ static void ibf_dump_object_list(struct ibf_dump *dump, ibf_offset_t *obj_list_o
static VALUE ibf_load_object(const struct ibf_load *load, VALUE object_index);
static rb_iseq_t *ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq);
-static VALUE
-ibf_dump_object_list_new(void)
+static st_table *
+ibf_dump_object_table_new(void)
{
- VALUE obj_list = rb_ary_tmp_new(1);
- rb_ary_push(obj_list, Qnil); /* 0th is nil */
+ st_table *obj_table = st_init_numtable(); /* need free */
+ st_insert(obj_table, (st_data_t)Qnil, (st_data_t)0); /* 0th is nil */
- return obj_list;
+ return obj_table;
}
static VALUE
ibf_dump_object(struct ibf_dump *dump, VALUE obj)
{
- VALUE obj_list = dump->current_buffer->obj_list;
- long index = RARRAY_LEN(obj_list);
- long i;
- for (i=0; i<index; i++) {
- if (RARRAY_AREF(obj_list, i) == obj) return (VALUE)i; /* dedup */
- }
- rb_ary_push(obj_list, obj);
- return (VALUE)index;
+ return ibf_table_find_or_insert(dump->current_buffer->obj_table, (st_data_t)obj);
}
static VALUE
@@ -9710,12 +10197,6 @@ ibf_load_id(const struct ibf_load *load, const ID id_index)
/* dump/load: code */
-static VALUE
-ibf_dump_calldata(struct ibf_dump *dump, const struct rb_call_data *cd)
-{
- return (cd->ci.flag & VM_CALL_KWARG) ? Qtrue : Qfalse;
-}
-
static ibf_offset_t ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq);
static int
@@ -9725,28 +10206,10 @@ ibf_dump_iseq(struct ibf_dump *dump, const rb_iseq_t *iseq)
return -1;
}
else {
- int iseq_index = ibf_table_lookup(dump->iseq_table, (st_data_t)iseq);
- if (iseq_index < 0) {
- iseq_index = ibf_table_index(dump->iseq_table, (st_data_t)iseq);
- rb_ary_push(dump->iseq_list, (VALUE)iseq);
- }
- return iseq_index;
+ return ibf_table_find_or_insert(dump->iseq_table, (st_data_t)iseq);
}
}
-static VALUE
-ibf_dump_gentry(struct ibf_dump *dump, const struct rb_global_entry *entry)
-{
- return (VALUE)ibf_dump_id(dump, entry->id);
-}
-
-static VALUE
-ibf_load_gentry(const struct ibf_load *load, const struct rb_global_entry *entry)
-{
- ID gid = ibf_load_id(load, (ID)(VALUE)entry);
- return (VALUE)rb_global_entry(gid);
-}
-
static unsigned char
ibf_load_byte(const struct ibf_load *load, ibf_offset_t *offset)
{
@@ -9769,6 +10232,7 @@ ibf_dump_write_small_value(struct ibf_dump *dump, VALUE x)
{
if (sizeof(VALUE) > 8 || CHAR_BIT != 8) {
ibf_dump_write(dump, &x, sizeof(VALUE));
+ return;
}
enum { max_byte_length = sizeof(VALUE) + 1 };
@@ -9907,17 +10371,11 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
break;
case TS_CALLDATA:
{
- /* ibf_dump_calldata() always returns either Qtrue or Qfalse */
- char c = ibf_dump_calldata(dump, (const struct rb_call_data *)op) == Qtrue; // 1 or 0
- ibf_dump_write_byte(dump, c);
goto skip_wv;
}
case TS_ID:
wv = ibf_dump_id(dump, (ID)op);
break;
- case TS_GENTRY:
- wv = ibf_dump_gentry(dump, (const struct rb_global_entry *)op);
- break;
case TS_FUNCPTR:
rb_raise(rb_eRuntimeError, "TS_FUNCPTR is not supported");
goto skip_wv;
@@ -9938,15 +10396,15 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq)
}
static VALUE *
-ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, ibf_offset_t bytecode_offset, ibf_offset_t bytecode_size, unsigned int iseq_size)
+ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecode_offset, ibf_offset_t bytecode_size, unsigned int iseq_size)
{
+ VALUE iseqv = (VALUE)iseq;
unsigned int code_index;
ibf_offset_t reading_pos = bytecode_offset;
VALUE *code = ALLOC_N(VALUE, iseq_size);
struct rb_iseq_constant_body *load_body = iseq->body;
struct rb_call_data *cd_entries = load_body->call_data;
- struct rb_kwarg_call_data *cd_kw_entries = (struct rb_kwarg_call_data *)&load_body->call_data[load_body->ci_size];
union iseq_inline_storage_entry *is_entries = load_body->is_entries;
for (code_index=0; code_index<iseq_size;) {
@@ -9965,8 +10423,8 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, ibf_offset_t b
VALUE v = ibf_load_object(load, op);
code[code_index] = v;
if (!SPECIAL_CONST_P(v)) {
- RB_OBJ_WRITTEN(iseq, Qundef, v);
- FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
+ RB_OBJ_WRITTEN(iseqv, Qundef, v);
+ FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
}
break;
}
@@ -9976,25 +10434,23 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, ibf_offset_t b
VALUE v = (VALUE)ibf_load_iseq(load, (const rb_iseq_t *)op);
code[code_index] = v;
if (!SPECIAL_CONST_P(v)) {
- RB_OBJ_WRITTEN(iseq, Qundef, v);
- FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
+ RB_OBJ_WRITTEN(iseqv, Qundef, v);
+ FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
}
break;
}
case TS_ISE:
- FL_SET(iseq, ISEQ_MARKABLE_ISEQ);
- /* fall through */
case TS_IC:
case TS_IVC:
{
VALUE op = ibf_load_small_value(load, &reading_pos);
code[code_index] = (VALUE)&is_entries[op];
}
+ FL_SET(iseqv, ISEQ_MARKABLE_ISEQ);
break;
case TS_CALLDATA:
{
- unsigned char op = ibf_load_byte(load, &reading_pos);
- code[code_index] = op ? (VALUE)cd_kw_entries++ : (VALUE)cd_entries++; /* op is 1 (kw) or 0 (!kw) */
+ code[code_index] = (VALUE)cd_entries++;
}
break;
case TS_ID:
@@ -10003,12 +10459,6 @@ ibf_load_code(const struct ibf_load *load, const rb_iseq_t *iseq, ibf_offset_t b
code[code_index] = ibf_load_id(load, (ID)(VALUE)op);
}
break;
- case TS_GENTRY:
- {
- VALUE op = ibf_load_small_value(load, &reading_pos);
- code[code_index] = ibf_load_gentry(load, (const struct rb_global_entry *)(VALUE)op);
- }
- break;
case TS_FUNCPTR:
rb_raise(rb_eRuntimeError, "TS_FUNCPTR is not supported");
break;
@@ -10266,92 +10716,132 @@ ibf_dump_ci_entries(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
const struct rb_iseq_constant_body *const body = iseq->body;
const unsigned int ci_size = body->ci_size;
- const unsigned int ci_kw_size = body->ci_kw_size;
- const struct rb_call_data *calls = body->call_data;
- const struct rb_kwarg_call_data *kw_calls = (const struct rb_kwarg_call_data *)&body->call_data[ci_size];
+ const struct rb_call_data *cds = body->call_data;
ibf_offset_t offset = ibf_dump_pos(dump);
unsigned int i;
for (i = 0; i < ci_size; i++) {
- VALUE mid = ibf_dump_id(dump, calls[i].ci.mid);
-
- ibf_dump_write_small_value(dump, mid);
- ibf_dump_write_small_value(dump, calls[i].ci.flag);
- ibf_dump_write_small_value(dump, calls[i].ci.orig_argc);
+ const struct rb_callinfo *ci = cds[i].ci;
+ if (ci != NULL) {
+ ibf_dump_write_small_value(dump, ibf_dump_id(dump, vm_ci_mid(ci)));
+ ibf_dump_write_small_value(dump, vm_ci_flag(ci));
+ ibf_dump_write_small_value(dump, vm_ci_argc(ci));
+
+ const struct rb_callinfo_kwarg *kwarg = vm_ci_kwarg(ci);
+ if (kwarg) {
+ int len = kwarg->keyword_len;
+ ibf_dump_write_small_value(dump, len);
+ for (int j=0; j<len; j++) {
+ VALUE keyword = ibf_dump_object(dump, kwarg->keywords[j]);
+ ibf_dump_write_small_value(dump, keyword);
+ }
+ }
+ else {
+ ibf_dump_write_small_value(dump, 0);
+ }
+ }
+ else {
+ // TODO: truncate NULL ci from call_data.
+ ibf_dump_write_small_value(dump, (VALUE)-1);
+ }
}
- for (i = 0; i < ci_kw_size; i++) {
- const struct rb_call_info_kw_arg *kw_arg = kw_calls[i].ci_kw.kw_arg;
+ return offset;
+}
- VALUE mid = ibf_dump_id(dump, kw_calls[i].ci_kw.ci.mid);
+static enum rb_id_table_iterator_result
+dump_outer_variable(ID id, VALUE val, void *dump)
+{
+ ibf_dump_write_small_value(dump, ibf_dump_id(dump, id));
+ ibf_dump_write_small_value(dump, val);
- ibf_dump_write_small_value(dump, mid);
- ibf_dump_write_small_value(dump, kw_calls[i].ci_kw.ci.flag);
- ibf_dump_write_small_value(dump, kw_calls[i].ci_kw.ci.orig_argc);
+ return ID_TABLE_CONTINUE;
+}
- ibf_dump_write_small_value(dump, kw_arg->keyword_len);
+static ibf_offset_t
+ibf_dump_outer_variables(struct ibf_dump *dump, const rb_iseq_t *iseq)
+{
+ struct rb_id_table * ovs = iseq->body->outer_variables;
- int j;
- for (j = 0; j < kw_calls[i].ci_kw.kw_arg->keyword_len; j++) {
- VALUE keyword = ibf_dump_object(dump, kw_arg->keywords[j]); /* kw_arg->keywords[n] is Symbol */
+ ibf_offset_t offset = ibf_dump_pos(dump);
- ibf_dump_write_small_value(dump, keyword);
- }
+ if (ovs) {
+ ibf_dump_write_small_value(dump, (VALUE)rb_id_table_size(ovs));
+ rb_id_table_foreach(ovs, dump_outer_variable, (void *)dump);
+ }
+ else {
+ ibf_dump_write_small_value(dump, (VALUE)0);
}
return offset;
}
/* note that we dump out rb_call_info but load back rb_call_data */
-static struct rb_call_data *
+static void
ibf_load_ci_entries(const struct ibf_load *load,
ibf_offset_t ci_entries_offset,
unsigned int ci_size,
- unsigned int ci_kw_size)
+ struct rb_call_data **cd_ptr)
{
ibf_offset_t reading_pos = ci_entries_offset;
unsigned int i;
- struct rb_call_data *calls =
- rb_xcalloc_mul_add_mul(
- sizeof(struct rb_call_data), ci_size,
- sizeof(struct rb_kwarg_call_data), ci_kw_size);
- struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&calls[ci_size];
+ struct rb_call_data *cds = ZALLOC_N(struct rb_call_data, ci_size);
+ *cd_ptr = cds;
for (i = 0; i < ci_size; i++) {
VALUE mid_index = ibf_load_small_value(load, &reading_pos);
+ if (mid_index != (VALUE)-1) {
+ ID mid = ibf_load_id(load, mid_index);
+ unsigned int flag = (unsigned int)ibf_load_small_value(load, &reading_pos);
+ unsigned int argc = (unsigned int)ibf_load_small_value(load, &reading_pos);
+
+ struct rb_callinfo_kwarg *kwarg = NULL;
+ int kwlen = (int)ibf_load_small_value(load, &reading_pos);
+ if (kwlen > 0) {
+ kwarg = rb_xmalloc_mul_add(kwlen, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg));
+ kwarg->keyword_len = kwlen;
+ for (int j=0; j<kwlen; j++) {
+ VALUE keyword = ibf_load_small_value(load, &reading_pos);
+ kwarg->keywords[j] = ibf_load_object(load, keyword);
+ }
+ }
- calls[i].ci.mid = ibf_load_id(load, mid_index);
- calls[i].ci.flag = (unsigned int)ibf_load_small_value(load, &reading_pos);
- calls[i].ci.orig_argc = (int)ibf_load_small_value(load, &reading_pos);
+ cds[i].ci = vm_ci_new(mid, flag, argc, kwarg);
+ RB_OBJ_WRITTEN(load->iseq, Qundef, cds[i].ci);
+ cds[i].cc = vm_cc_empty();
+ }
+ else {
+ // NULL ci
+ cds[i].ci = NULL;
+ cds[i].cc = NULL;
+ }
}
+}
- for (i = 0; i < ci_kw_size; i++) {
- VALUE mid_index = ibf_load_small_value(load, &reading_pos);
-
- kw_calls[i].ci_kw.ci.mid = ibf_load_id(load, mid_index);
- kw_calls[i].ci_kw.ci.flag = (unsigned int)ibf_load_small_value(load, &reading_pos);
- kw_calls[i].ci_kw.ci.orig_argc = (int)ibf_load_small_value(load, &reading_pos);
-
- int keyword_len = (int)ibf_load_small_value(load, &reading_pos);
+static struct rb_id_table *
+ibf_load_outer_variables(const struct ibf_load * load, ibf_offset_t outer_variables_offset)
+{
+ ibf_offset_t reading_pos = outer_variables_offset;
- kw_calls[i].ci_kw.kw_arg =
- rb_xmalloc_mul_add(keyword_len - 1, sizeof(VALUE), sizeof(struct rb_call_info_kw_arg));
+ struct rb_id_table *tbl = NULL;
- kw_calls[i].ci_kw.kw_arg->keyword_len = keyword_len;
+ size_t table_size = (size_t)ibf_load_small_value(load, &reading_pos);
- int j;
- for (j = 0; j < kw_calls[i].ci_kw.kw_arg->keyword_len; j++) {
- VALUE keyword = ibf_load_small_value(load, &reading_pos);
+ if (table_size > 0) {
+ tbl = rb_id_table_create(table_size);
+ }
- kw_calls[i].ci_kw.kw_arg->keywords[j] = ibf_load_object(load, keyword);
- }
+ for (size_t i = 0; i < table_size; i++) {
+ ID key = ibf_load_id(load, (ID)ibf_load_small_value(load, &reading_pos));
+ VALUE value = ibf_load_small_value(load, &reading_pos);
+ rb_id_table_insert(tbl, key, value);
}
- return calls;
+ return tbl;
}
static ibf_offset_t
@@ -10373,7 +10863,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
struct ibf_dump_buffer *saved_buffer = dump->current_buffer;
struct ibf_dump_buffer buffer;
buffer.str = rb_str_new(0, 0);
- buffer.obj_list = ibf_dump_object_list_new();
+ buffer.obj_table = ibf_dump_object_table_new();
dump->current_buffer = &buffer;
#endif
@@ -10393,6 +10883,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
const int parent_iseq_index = ibf_dump_iseq(dump, iseq->body->parent_iseq);
const int local_iseq_index = ibf_dump_iseq(dump, iseq->body->local_iseq);
const ibf_offset_t ci_entries_offset = ibf_dump_ci_entries(dump, iseq);
+ const ibf_offset_t outer_variables_offset = ibf_dump_outer_variables(dump, iseq);
#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
ibf_offset_t local_obj_list_offset;
@@ -10454,13 +10945,14 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
ibf_dump_write_small_value(dump, parent_iseq_index);
ibf_dump_write_small_value(dump, local_iseq_index);
ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(ci_entries_offset));
+ ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(outer_variables_offset));
ibf_dump_write_small_value(dump, body->variable.flip_count);
ibf_dump_write_small_value(dump, body->local_table_size);
ibf_dump_write_small_value(dump, body->is_size);
ibf_dump_write_small_value(dump, body->ci_size);
- ibf_dump_write_small_value(dump, body->ci_kw_size);
ibf_dump_write_small_value(dump, body->stack_max);
ibf_dump_write_small_value(dump, body->catch_except_p);
+ ibf_dump_write_small_value(dump, body->builtin_inline_p);
#undef IBF_BODY_OFFSET
@@ -10478,6 +10970,8 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
ibf_dump_write_small_value(dump, local_obj_list_offset);
ibf_dump_write_small_value(dump, local_obj_list_size);
+ st_free_table(buffer.obj_table); // TODO: this leaks in case of exception
+
return offset;
#else
return body_offset;
@@ -10505,17 +10999,16 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
struct ibf_load_buffer *saved_buffer = load->current_buffer;
load->current_buffer = &load->global_buffer;
- const ibf_offset_t iseq_start = ibf_load_small_value(load, &reading_pos);
- const ibf_offset_t iseq_length_bytes = ibf_load_small_value(load, &reading_pos);
- const ibf_offset_t body_offset = ibf_load_small_value(load, &reading_pos);
+ const ibf_offset_t iseq_start = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
+ const ibf_offset_t iseq_length_bytes = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
+ const ibf_offset_t body_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
struct ibf_load_buffer buffer;
buffer.buff = load->global_buffer.buff + iseq_start;
buffer.size = iseq_length_bytes;
- buffer.obj_list_offset = ibf_load_small_value(load, &reading_pos);
- buffer.obj_list_size = ibf_load_small_value(load, &reading_pos);
- buffer.obj_list = rb_ary_tmp_new(buffer.obj_list_size);
- rb_ary_resize(buffer.obj_list, buffer.obj_list_size);
+ buffer.obj_list_offset = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
+ buffer.obj_list_size = (ibf_offset_t)ibf_load_small_value(load, &reading_pos);
+ buffer.obj_list = pinned_list_new(buffer.obj_list_size);
load->current_buffer = &buffer;
reading_pos = body_offset;
@@ -10559,13 +11052,14 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
const int parent_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
const int local_iseq_index = (int)ibf_load_small_value(load, &reading_pos);
const ibf_offset_t ci_entries_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
+ const ibf_offset_t outer_variables_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
const rb_snum_t variable_flip_count = (rb_snum_t)ibf_load_small_value(load, &reading_pos);
const unsigned int local_table_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
const unsigned int is_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
const unsigned int ci_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
- const unsigned int ci_kw_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
const unsigned int stack_max = (unsigned int)ibf_load_small_value(load, &reading_pos);
const char catch_except_p = (char)ibf_load_small_value(load, &reading_pos);
+ const bool builtin_inline_p = (bool)ibf_load_small_value(load, &reading_pos);
#undef IBF_BODY_OFFSET
@@ -10591,7 +11085,6 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->local_table_size = local_table_size;
load_body->is_size = is_size;
load_body->ci_size = ci_size;
- load_body->ci_kw_size = ci_kw_size;
load_body->insns_info.size = insns_info_size;
ISEQ_COVERAGE_SET(iseq, Qnil);
@@ -10605,9 +11098,11 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->location.code_location.end_pos.lineno = location_code_location_end_pos_lineno;
load_body->location.code_location.end_pos.column = location_code_location_end_pos_column;
load_body->catch_except_p = catch_except_p;
+ load_body->builtin_inline_p = builtin_inline_p;
load_body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, is_size);
- load_body->call_data = ibf_load_ci_entries(load, ci_entries_offset, ci_size, ci_kw_size);
+ ibf_load_ci_entries(load, ci_entries_offset, ci_size, &load_body->call_data);
+ load_body->outer_variables = ibf_load_outer_variables(load, outer_variables_offset);
load_body->param.opt_table = ibf_load_param_opt_table(load, param_opt_table_offset, param_opt_num);
load_body->param.keyword = ibf_load_param_keyword(load, param_keyword_offset);
load_body->param.flags.has_kw = (param_flags >> 4) & 1;
@@ -10665,22 +11160,41 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
verify_call_cache(iseq);
}
+struct ibf_dump_iseq_list_arg
+{
+ struct ibf_dump *dump;
+ VALUE offset_list;
+};
+
+static int
+ibf_dump_iseq_list_i(st_data_t key, st_data_t val, st_data_t ptr)
+{
+ const rb_iseq_t *iseq = (const rb_iseq_t *)key;
+ struct ibf_dump_iseq_list_arg *args = (struct ibf_dump_iseq_list_arg *)ptr;
+
+ ibf_offset_t offset = ibf_dump_iseq_each(args->dump, iseq);
+ rb_ary_push(args->offset_list, UINT2NUM(offset));
+
+ return ST_CONTINUE;
+}
+
static void
ibf_dump_iseq_list(struct ibf_dump *dump, struct ibf_header *header)
{
- VALUE list = rb_ary_tmp_new(RARRAY_LEN(dump->iseq_list));
- long i;
+ VALUE offset_list = rb_ary_tmp_new(dump->iseq_table->num_entries);
- for (i = 0; i < RARRAY_LEN(dump->iseq_list); i++) {
- ibf_offset_t offset = ibf_dump_iseq_each(dump, (rb_iseq_t *)RARRAY_AREF(dump->iseq_list, i));
- rb_ary_push(list, UINT2NUM(offset));
- }
+ struct ibf_dump_iseq_list_arg args;
+ args.dump = dump;
+ args.offset_list = offset_list;
- long size = RARRAY_LEN(dump->iseq_list);
+ st_foreach(dump->iseq_table, ibf_dump_iseq_list_i, (st_data_t)&args);
+
+ st_index_t i;
+ st_index_t size = dump->iseq_table->num_entries;
ibf_offset_t *offsets = ALLOCA_N(ibf_offset_t, size);
for (i = 0; i < size; i++) {
- offsets[i] = NUM2UINT(RARRAY_AREF(list, i));
+ offsets[i] = NUM2UINT(RARRAY_AREF(offset_list, i));
}
ibf_dump_align(dump, sizeof(ibf_offset_t));
@@ -10770,11 +11284,13 @@ ibf_dump_object_unsupported(struct ibf_dump *dump, VALUE obj)
rb_raise(rb_eNotImpError, "ibf_dump_object_unsupported: %s", buff);
}
+NORETURN(static VALUE ibf_load_object_unsupported(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset));
+
static VALUE
ibf_load_object_unsupported(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
{
rb_raise(rb_eArgError, "unsupported");
- return Qnil;
+ UNREACHABLE_RETURN(Qnil);
}
static void
@@ -11187,7 +11703,7 @@ ibf_load_object_object_header(const struct ibf_load *load, ibf_offset_t *offset)
}
static ibf_offset_t
-ibf_dump_object_object(struct ibf_dump *dump, VALUE obj_list, VALUE obj)
+ibf_dump_object_object(struct ibf_dump *dump, VALUE obj)
{
struct ibf_object_header obj_header;
ibf_offset_t current_offset;
@@ -11197,12 +11713,9 @@ ibf_dump_object_object(struct ibf_dump *dump, VALUE obj_list, VALUE obj)
IBF_W_ALIGN(ibf_offset_t);
current_offset = ibf_dump_pos(dump);
- if (SPECIAL_CONST_P(obj)) {
- if (RB_TYPE_P(obj, T_SYMBOL) ||
- RB_TYPE_P(obj, T_FLOAT)) {
- obj_header.internal = FALSE;
- goto dump_object;
- }
+ if (SPECIAL_CONST_P(obj) &&
+ ! (RB_TYPE_P(obj, T_SYMBOL) ||
+ RB_TYPE_P(obj, T_FLOAT))) {
obj_header.special_const = TRUE;
obj_header.frozen = TRUE;
obj_header.internal = TRUE;
@@ -11210,8 +11723,7 @@ ibf_dump_object_object(struct ibf_dump *dump, VALUE obj_list, VALUE obj)
ibf_dump_write_small_value(dump, obj);
}
else {
- obj_header.internal = (RBASIC_CLASS(obj) == 0) ? TRUE : FALSE;
- dump_object:
+ obj_header.internal = SPECIAL_CONST_P(obj) ? FALSE : (RBASIC_CLASS(obj) == 0) ? TRUE : FALSE;
obj_header.special_const = FALSE;
obj_header.frozen = FL_TEST(obj, FL_FREEZE) ? TRUE : FALSE;
ibf_dump_object_object_header(dump, obj_header);
@@ -11263,12 +11775,9 @@ ibf_load_object(const struct ibf_load *load, VALUE object_index)
if (object_index == 0) {
return Qnil;
}
- else if (object_index >= (VALUE)RARRAY_LEN(load->current_buffer->obj_list)) {
- rb_raise(rb_eIndexError, "object index out of range: %"PRIdVALUE, object_index);
- }
else {
- VALUE obj = rb_ary_entry(load->current_buffer->obj_list, (long)object_index);
- if (obj == Qnil) { /* TODO: avoid multiple Qnil load */
+ VALUE obj = pinned_list_fetch(load->current_buffer->obj_list, (long)object_index);
+ if (!obj) {
ibf_offset_t *offsets = (ibf_offset_t *)(load->current_buffer->obj_list_offset + load->current_buffer->buff);
ibf_offset_t offset = offsets[object_index];
const struct ibf_object_header header = ibf_load_object_object_header(load, &offset);
@@ -11292,7 +11801,7 @@ ibf_load_object(const struct ibf_load *load, VALUE object_index)
obj = (*load_object_functions[header.type])(load, &header, offset);
}
- rb_ary_store(load->current_buffer->obj_list, (long)object_index, obj);
+ pinned_list_store(load->current_buffer->obj_list, (long)object_index, obj);
}
#if IBF_ISEQ_DEBUG
fprintf(stderr, "ibf_load_object: index=%#"PRIxVALUE" obj=%#"PRIxVALUE"\n",
@@ -11302,28 +11811,48 @@ ibf_load_object(const struct ibf_load *load, VALUE object_index)
}
}
+struct ibf_dump_object_list_arg
+{
+ struct ibf_dump *dump;
+ VALUE offset_list;
+};
+
+static int
+ibf_dump_object_list_i(st_data_t key, st_data_t val, st_data_t ptr)
+{
+ VALUE obj = (VALUE)key;
+ struct ibf_dump_object_list_arg *args = (struct ibf_dump_object_list_arg *)ptr;
+
+ ibf_offset_t offset = ibf_dump_object_object(args->dump, obj);
+ rb_ary_push(args->offset_list, UINT2NUM(offset));
+
+ return ST_CONTINUE;
+}
+
static void
ibf_dump_object_list(struct ibf_dump *dump, ibf_offset_t *obj_list_offset, unsigned int *obj_list_size)
{
- VALUE obj_list = dump->current_buffer->obj_list;
- VALUE list = rb_ary_tmp_new(RARRAY_LEN(obj_list));
- int i, size;
+ st_table *obj_table = dump->current_buffer->obj_table;
+ VALUE offset_list = rb_ary_tmp_new(obj_table->num_entries);
+
+ struct ibf_dump_object_list_arg args;
+ args.dump = dump;
+ args.offset_list = offset_list;
+
+ st_foreach(obj_table, ibf_dump_object_list_i, (st_data_t)&args);
- for (i=0; i<RARRAY_LEN(obj_list); i++) {
- VALUE obj = RARRAY_AREF(obj_list, i);
- ibf_offset_t offset = ibf_dump_object_object(dump, obj_list, obj);
- rb_ary_push(list, UINT2NUM(offset));
- }
- size = i;
IBF_W_ALIGN(ibf_offset_t);
*obj_list_offset = ibf_dump_pos(dump);
+ st_index_t size = obj_table->num_entries;
+ st_index_t i;
+
for (i=0; i<size; i++) {
- ibf_offset_t offset = NUM2UINT(RARRAY_AREF(list, i));
+ ibf_offset_t offset = NUM2UINT(RARRAY_AREF(offset_list, i));
IBF_WV(offset);
}
- *obj_list_size = size;
+ *obj_list_size = (unsigned int)size;
}
static void
@@ -11331,14 +11860,19 @@ ibf_dump_mark(void *ptr)
{
struct ibf_dump *dump = (struct ibf_dump *)ptr;
rb_gc_mark(dump->global_buffer.str);
- rb_gc_mark(dump->global_buffer.obj_list);
- rb_gc_mark(dump->iseq_list);
+
+ rb_mark_set(dump->global_buffer.obj_table);
+ rb_mark_set(dump->iseq_table);
}
static void
ibf_dump_free(void *ptr)
{
struct ibf_dump *dump = (struct ibf_dump *)ptr;
+ if (dump->global_buffer.obj_table) {
+ st_free_table(dump->global_buffer.obj_table);
+ dump->global_buffer.obj_table = 0;
+ }
if (dump->iseq_table) {
st_free_table(dump->iseq_table);
dump->iseq_table = 0;
@@ -11352,6 +11886,7 @@ ibf_dump_memsize(const void *ptr)
struct ibf_dump *dump = (struct ibf_dump *)ptr;
size_t size = sizeof(*dump);
if (dump->iseq_table) size += st_memsize(dump->iseq_table);
+ if (dump->global_buffer.obj_table) size += st_memsize(dump->global_buffer.obj_table);
return size;
}
@@ -11364,9 +11899,11 @@ static const rb_data_type_t ibf_dump_type = {
static void
ibf_dump_setup(struct ibf_dump *dump, VALUE dumper_obj)
{
- RB_OBJ_WRITE(dumper_obj, &dump->iseq_list, rb_ary_tmp_new(0));
- RB_OBJ_WRITE(dumper_obj, &dump->global_buffer.obj_list, ibf_dump_object_list_new());
+ dump->global_buffer.obj_table = NULL; // GC may run before a value is assigned
+ dump->iseq_table = NULL;
+
RB_OBJ_WRITE(dumper_obj, &dump->global_buffer.str, rb_str_new(0, 0));
+ dump->global_buffer.obj_table = ibf_dump_object_table_new();
dump->iseq_table = st_init_numtable(); /* need free */
dump->current_buffer = &dump->global_buffer;
@@ -11444,7 +11981,7 @@ rb_ibf_load_iseq_complete(rb_iseq_t *iseq)
#endif
ibf_load_iseq_each(load, iseq, offset);
ISEQ_COMPILE_DATA_CLEAR(iseq);
- FL_UNSET(iseq, ISEQ_NOT_LOADED_YET);
+ FL_UNSET((VALUE)iseq, ISEQ_NOT_LOADED_YET);
rb_iseq_init_trace(iseq);
load->iseq = prev_src_iseq;
}
@@ -11471,12 +12008,12 @@ ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq)
return NULL;
}
else {
- VALUE iseqv = rb_ary_entry(load->iseq_list, iseq_index);
+ VALUE iseqv = pinned_list_fetch(load->iseq_list, iseq_index);
#if IBF_ISEQ_DEBUG
fprintf(stderr, "ibf_load_iseq: iseqv=%p\n", (void *)iseqv);
#endif
- if (iseqv != Qnil) {
+ if (iseqv) {
return (rb_iseq_t *)iseqv;
}
else {
@@ -11484,14 +12021,14 @@ ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq)
#if IBF_ISEQ_DEBUG
fprintf(stderr, "ibf_load_iseq: new iseq=%p\n", (void *)iseq);
#endif
- FL_SET(iseq, ISEQ_NOT_LOADED_YET);
+ FL_SET((VALUE)iseq, ISEQ_NOT_LOADED_YET);
iseq->aux.loader.obj = load->loader_obj;
iseq->aux.loader.index = iseq_index;
#if IBF_ISEQ_DEBUG
fprintf(stderr, "ibf_load_iseq: iseq=%p loader_obj=%p index=%d\n",
(void *)iseq, (void *)load->loader_obj, iseq_index);
#endif
- rb_ary_store(load->iseq_list, iseq_index, (VALUE)iseq);
+ pinned_list_store(load->iseq_list, iseq_index, (VALUE)iseq);
#if !USE_LAZY_LOAD
#if IBF_ISEQ_DEBUG
@@ -11522,9 +12059,8 @@ ibf_load_setup_bytes(struct ibf_load *load, VALUE loader_obj, const char *bytes,
load->global_buffer.size = load->header->size;
load->global_buffer.obj_list_offset = load->header->global_object_list_offset;
load->global_buffer.obj_list_size = load->header->global_object_list_size;
- RB_OBJ_WRITE(loader_obj, &load->iseq_list, rb_ary_tmp_new(0));
- RB_OBJ_WRITE(loader_obj, &load->global_buffer.obj_list, rb_ary_tmp_new(load->global_buffer.obj_list_size));
- rb_ary_resize(load->global_buffer.obj_list, load->global_buffer.obj_list_size);
+ RB_OBJ_WRITE(loader_obj, &load->iseq_list, pinned_list_new(load->header->iseq_list_size));
+ RB_OBJ_WRITE(loader_obj, &load->global_buffer.obj_list, pinned_list_new(load->global_buffer.obj_list_size));
load->iseq = NULL;
load->current_buffer = &load->global_buffer;
diff --git a/complex.c b/complex.c
index cdd5edc50a..27c1f131e3 100644
--- a/complex.c
+++ b/complex.c
@@ -5,16 +5,27 @@
which is written in ruby.
*/
-#include "ruby/config.h"
+#include "ruby/internal/config.h"
+
#if defined _MSC_VER
/* Microsoft Visual C does not define M_PI and others by default */
# define _USE_MATH_DEFINES 1
#endif
+
+#include <ctype.h>
#include <math.h>
-#include "internal.h"
-#include "id.h"
+#undef NDEBUG
#define NDEBUG
+#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/class.h"
+#include "internal/complex.h"
+#include "internal/math.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/rational.h"
#include "ruby_assert.h"
#define ZERO INT2FIX(0)
@@ -392,7 +403,7 @@ nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag)
RCOMPLEX_SET_REAL(obj, real);
RCOMPLEX_SET_IMAG(obj, imag);
- OBJ_FREEZE_RAW(obj);
+ OBJ_FREEZE_RAW((VALUE)obj);
return (VALUE)obj;
}
@@ -418,18 +429,6 @@ f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
return nucomp_s_new_internal(klass, x, y);
}
-#ifdef CANONICALIZATION_FOR_MATHN
-static int canonicalization = 0;
-
-RUBY_FUNC_EXPORTED void
-nucomp_canonicalization(int f)
-{
- canonicalization = f;
-}
-#else
-#define canonicalization 0
-#endif
-
inline static void
nucomp_real_check(VALUE num)
{
@@ -445,10 +444,6 @@ inline static VALUE
nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag)
{
int complex_r, complex_i;
-#ifdef CANONICALIZATION_FOR_MATHN
- if (k_exact_zero_p(imag) && canonicalization)
- return real;
-#endif
complex_r = RB_TYPE_P(real, T_COMPLEX);
complex_i = RB_TYPE_P(imag, T_COMPLEX);
if (!complex_r && !complex_i) {
@@ -625,14 +620,12 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y)
assert(!RB_TYPE_P(x, T_COMPLEX));
assert(!RB_TYPE_P(y, T_COMPLEX));
if (f_zero_p(x) || f_zero_p(y)) {
- if (canonicalization) return x;
return nucomp_s_new_internal(klass, x, RFLOAT_0);
}
if (RB_FLOAT_TYPE_P(y)) {
const double arg = RFLOAT_VALUE(y);
if (arg == M_PI) {
x = f_negate(x);
- if (canonicalization) return x;
y = RFLOAT_0;
}
else if (arg == M_PI_2) {
@@ -647,13 +640,12 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y)
const double abs = RFLOAT_VALUE(x);
const double real = abs * cos(arg), imag = abs * sin(arg);
x = DBL2NUM(real);
- if (canonicalization && imag == 0.0) return x;
y = DBL2NUM(imag);
}
else {
- y = f_mul(x, DBL2NUM(sin(arg)));
- x = f_mul(x, DBL2NUM(cos(arg)));
- if (canonicalization && f_zero_p(y)) return x;
+ const double ax = sin(arg), ay = cos(arg);
+ y = f_mul(x, DBL2NUM(ax));
+ x = f_mul(x, DBL2NUM(ay));
}
return nucomp_s_new_internal(klass, x, y);
}
@@ -662,6 +654,16 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y)
f_mul(x, m_sin(y)));
}
+#ifdef HAVE___COSPI
+# define cospi(x) __cospi(x)
+#else
+# define cospi(x) cos((x) * M_PI)
+#endif
+#ifdef HAVE___SINPI
+# define sinpi(x) __sinpi(x)
+#else
+# define sinpi(x) sin((x) * M_PI)
+#endif
/* returns a Complex or Float of ang*PI-rotated abs */
VALUE
rb_dbl_complex_new_polar_pi(double abs, double ang)
@@ -679,8 +681,8 @@ rb_dbl_complex_new_polar_pi(double abs, double ang)
return DBL2NUM(abs);
}
else {
- ang *= M_PI;
- return rb_complex_new(DBL2NUM(abs * cos(ang)), DBL2NUM(abs * sin(ang)));
+ const double real = abs * cospi(ang), imag = abs * sinpi(ang);
+ return rb_complex_new(DBL2NUM(real), DBL2NUM(imag));
}
}
@@ -703,13 +705,20 @@ nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
switch (rb_scan_args(argc, argv, "11", &abs, &arg)) {
case 1:
nucomp_real_check(abs);
- if (canonicalization) return abs;
return nucomp_s_new_internal(klass, abs, ZERO);
default:
nucomp_real_check(abs);
nucomp_real_check(arg);
break;
}
+ if (RB_TYPE_P(abs, T_COMPLEX)) {
+ get_dat1(abs);
+ abs = dat->real;
+ }
+ if (RB_TYPE_P(arg, T_COMPLEX)) {
+ get_dat1(arg);
+ arg = dat->real;
+ }
return f_complex_polar(klass, abs, arg);
}
@@ -1319,8 +1328,8 @@ nucomp_numerator(VALUE self)
}
/* :nodoc: */
-static VALUE
-nucomp_hash(VALUE self)
+st_index_t
+rb_complex_hash(VALUE self)
{
st_index_t v, h[2];
VALUE n;
@@ -1331,7 +1340,13 @@ nucomp_hash(VALUE self)
n = rb_hash(dat->imag);
h[1] = NUM2LONG(n);
v = rb_memhash(h, sizeof(h));
- return ST2FIX(v);
+ return v;
+}
+
+static VALUE
+nucomp_hash(VALUE self)
+{
+ return ST2FIX(rb_complex_hash(self));
}
/* :nodoc: */
@@ -1700,8 +1715,6 @@ numeric_to_c(VALUE self)
return rb_complex_new1(self);
}
-#include <ctype.h>
-
inline static int
issign(int c)
{
@@ -2309,20 +2322,17 @@ void
Init_Complex(void)
{
VALUE compat;
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
- id_abs = rb_intern("abs");
- id_arg = rb_intern("arg");
- id_denominator = rb_intern("denominator");
- id_numerator = rb_intern("numerator");
- id_real_p = rb_intern("real?");
- id_i_real = rb_intern("@real");
- id_i_imag = rb_intern("@image"); /* @image, not @imag */
- id_finite_p = rb_intern("finite?");
- id_infinite_p = rb_intern("infinite?");
- id_rationalize = rb_intern("rationalize");
- id_PI = rb_intern("PI");
+ id_abs = rb_intern_const("abs");
+ id_arg = rb_intern_const("arg");
+ id_denominator = rb_intern_const("denominator");
+ id_numerator = rb_intern_const("numerator");
+ id_real_p = rb_intern_const("real?");
+ id_i_real = rb_intern_const("@real");
+ id_i_imag = rb_intern_const("@image"); /* @image, not @imag */
+ id_finite_p = rb_intern_const("finite?");
+ id_infinite_p = rb_intern_const("infinite?");
+ id_rationalize = rb_intern_const("rationalize");
+ id_PI = rb_intern_const("PI");
rb_cComplex = rb_define_class("Complex", rb_cNumeric);
@@ -2337,7 +2347,7 @@ Init_Complex(void)
rb_define_global_function("Complex", nucomp_f_complex, -1);
- rb_undef_methods_from(rb_cComplex, rb_mComparable);
+ rb_undef_methods_from(rb_cComplex, RCLASS_ORIGIN(rb_mComparable));
rb_undef_method(rb_cComplex, "%");
rb_undef_method(rb_cComplex, "div");
rb_undef_method(rb_cComplex, "divmod");
diff --git a/configure.ac b/configure.ac
index 4395a2b156..49e0c79a4c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,19 +2,47 @@ dnl Process this file with autoconf to produce a configure script.
AC_INIT
{
AC_CONFIG_AUX_DIR(tool)
-AC_CONFIG_MACRO_DIRS(tool/m4)
AC_PREREQ(2.67)
-dnl override AC_CHECKING
-dnl placed here due to aclocal(1)'s
-dnl ignoring this definition in separate files
-AC_DEFUN([AC_CHECKING],[dnl
-AC_REQUIRE([_COLORIZE_RESULT_PREPARE])dnl
-AS_MESSAGE([checking ${msg_checking}$1${msg_reset}...])])dnl
+tooldir="$srcdir/tool"
AC_DISABLE_OPTION_CHECKING
+m4_include([tool/m4/_colorize_result_prepare.m4])
+m4_include([tool/m4/ac_msg_result.m4])
+m4_include([tool/m4/colorize_result.m4])
+m4_include([tool/m4/ruby_append_option.m4])
+m4_include([tool/m4/ruby_append_options.m4])
+m4_include([tool/m4/ruby_check_builtin_func.m4])
+m4_include([tool/m4/ruby_check_builtin_setjmp.m4])
+m4_include([tool/m4/ruby_check_printf_prefix.m4])
+m4_include([tool/m4/ruby_check_setjmp.m4])
+m4_include([tool/m4/ruby_check_signedness.m4])
+m4_include([tool/m4/ruby_check_sizeof.m4])
+m4_include([tool/m4/ruby_check_sysconf.m4])
+m4_include([tool/m4/ruby_cppoutfile.m4])
+m4_include([tool/m4/ruby_decl_attribute.m4])
+m4_include([tool/m4/ruby_default_arch.m4])
+m4_include([tool/m4/ruby_define_if.m4])
+m4_include([tool/m4/ruby_defint.m4])
+m4_include([tool/m4/ruby_dtrace_available.m4])
+m4_include([tool/m4/ruby_dtrace_postprocess.m4])
+m4_include([tool/m4/ruby_func_attribute.m4])
+m4_include([tool/m4/ruby_mingw32.m4])
+m4_include([tool/m4/ruby_prepend_option.m4])
+m4_include([tool/m4/ruby_prog_gnu_ld.m4])
+m4_include([tool/m4/ruby_replace_funcs.m4])
+m4_include([tool/m4/ruby_replace_type.m4])
+m4_include([tool/m4/ruby_rm_recursive.m4])
+m4_include([tool/m4/ruby_setjmp_type.m4])
+m4_include([tool/m4/ruby_stack_grow_direction.m4])
+m4_include([tool/m4/ruby_try_cflags.m4])
+m4_include([tool/m4/ruby_try_cxxflags.m4])
+m4_include([tool/m4/ruby_try_ldflags.m4])
+m4_include([tool/m4/ruby_universal_arch.m4])
+m4_include([tool/m4/ruby_werror_flag.m4])
+
AC_ARG_VAR([cflags], [additional CFLAGS (ignored when CFLAGS is given)])
AC_ARG_VAR([cppflags], [additional CPPFLAGS (ignored when CPPFLAGS is given)])
AC_ARG_VAR([cxxflags], [additional CXXFLAGS (ignored when CXXFLAGS is given)])
@@ -32,11 +60,9 @@ AC_ARG_WITH(baseruby,
[
AC_PATH_PROG([BASERUBY], [ruby], [false])
])
-AS_IF([test "$HAVE_BASERUBY" = yes -a "`RUBYOPT=- $BASERUBY -e 'print 42' 2>/dev/null`" = 42], [
- AS_IF([test "`RUBYOPT=- $BASERUBY --disable=gems -e 'print 42' 2>/dev/null`" = 42], [
- BASERUBY="$BASERUBY --disable=gems"
- BASERUBY_VERSION=`$BASERUBY -v`
- ])
+AS_IF([test "$HAVE_BASERUBY" != no -a "`RUBYOPT=- $BASERUBY --disable=gems -e 'print 42 if RUBY_VERSION > "2.2"' 2>/dev/null`" = 42], [
+ BASERUBY="$BASERUBY --disable=gems"
+ BASERUBY_VERSION=`$BASERUBY -v`
$BASERUBY -C "$srcdir" tool/downloader.rb -d tool -e gnu config.guess config.sub >&AS_MESSAGE_FD
], [
BASERUBY="echo executable host ruby is required. use --with-baseruby option.; false"
@@ -71,8 +97,23 @@ AC_SUBST(TEENY)
AC_SUBST(RUBY_API_VERSION, '$(MAJOR).$(MINOR)')
AC_SUBST(RUBY_PROGRAM_VERSION, '$(MAJOR).$(MINOR).$(TEENY)')
+AS_IF([test "$program_prefix" = NONE], [
+ program_prefix=
+])
+AS_IF([test "$prefix" -ef .], [
+ AC_MSG_ERROR(--prefix cannot be the current working directory.)
+])
+RUBY_BASE_NAME=`echo ruby | sed "$program_transform_name"`
+RUBYW_BASE_NAME=`echo rubyw | sed "$program_transform_name"`
+AC_SUBST(RUBY_BASE_NAME)
+AC_SUBST(RUBYW_BASE_NAME)
+AC_SUBST(RUBY_VERSION_NAME, '${RUBY_BASE_NAME}-${ruby_version}')
+
dnl checks for alternative programs
AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+AC_ARG_PROGRAM
RUBY_RM_RECURSIVE
AC_ARG_WITH(gcc,
AS_HELP_STRING([--without-gcc], [never use gcc]),
@@ -86,21 +127,105 @@ AS_IF([test ! -z "$ac_cv_prog_CC" -a ! -z "$CC" -a "$CC" != "$ac_cv_prog_CC"], [
AC_MSG_ERROR(cached CC is different -- throw away $cache_file
(it is also a good idea to do 'make clean' before compiling))
])
-test -z "$CC" || ac_cv_prog_CC="$CC"
-
-AS_IF([test "$program_prefix" = NONE], [
- program_prefix=
+AS_CASE(["${build_os}"], [linux*|cygwin*], [
+ AC_CHECK_TOOLS([CC], [gcc clang cc])
+], [
+ # OpenBSD wants to prefer cc over gcc.
+ # See https://github.com/ruby/ruby/pull/2443
+ AC_CHECK_TOOLS([CC], [cl.exe clang cc gcc c99 /usr/ucb/cc])
+])
+
+AC_ARG_VAR([AR], [Archiver command])
+AC_ARG_VAR([AS], [Assembler command])
+AC_ARG_VAR([CC], [C compiler command])
+AC_ARG_VAR([CXX], [C++ compiler command])
+AC_ARG_VAR([LD], [Linker command])
+AC_ARG_VAR([NM], [Symbol list command])
+AC_ARG_VAR([OBJCOPY], [Objcopy command])
+AC_ARG_VAR([OBJDUMP], [Objdump command])
+AC_ARG_VAR([RANLIB], [Ranlib command])
+AC_ARG_VAR([STRIP], [Strip command])
+
+# We don't want to bother things like `ccache gcc`, `clang -shared-libgcc`, ...
+set rb_dummy ${CC}
+rb_CC=$2
+AS_CASE(["/${rb_CC} "],
+[*@<:@\ /@:>@"cc "*], [
+ # Don't try g++/clang++ when CC=cc
+ AC_CHECK_TOOLS([CXX], [cl.exe CC c++])
+],
+[*icc*], [
+ # Intel C++ has interprocedural optimizations. It tends to come with its
+ # own linker etc.
+ AC_CHECK_TOOL([AR], [`echo "${rb_CC}" | sed s/icc/xiar/`])
+ AC_CHECK_TOOL([CXX], [`echo "${rb_CC}" | sed s/icc/icpc/`])
+ AC_CHECK_TOOL([LD], [`echo "${rb_CC}" | sed s/icc/xild/`])
+],
+[*gcc*], [
+ # Dito for GCC.
+ AC_CHECK_TOOL([LD], [`echo "${rb_CC}" | sed s/gcc/ld/`])
+ AC_CHECK_TOOL([AR], [`echo "${rb_CC}" | sed s/gcc/gcc-ar/`])
+ AC_CHECK_TOOL([CXX], [`echo "${rb_CC}" | sed s/gcc/g++/`])
+ AC_CHECK_TOOL([NM], [`echo "${rb_CC}" | sed s/gcc/gcc-nm/`])
+ AC_CHECK_TOOL([RANLIB], [`echo "${rb_CC}" | sed s/gcc/gcc-ranlib/`])
+],
+[*clang*], [
+ # Dito for LLVM. Note however that llvm-as is a LLVM-IR to LLVM bitcode
+ # assembler that does not target your machine native binary.
+ : ${LD:="${CC}"} # ... try -fuse-ld=lld ?
+ AC_CHECK_TOOL([AR], [`echo "${rb_CC}" | sed s/clang/llvm-ar/`])
+# AC_CHECK_TOOL([AS], [`echo "${rb_CC}" | sed s/clang/llvm-as/`])
+ AC_CHECK_TOOL([CXX], [`echo "${rb_CC}" | sed s/clang/clang++/`])
+ AC_CHECK_TOOL([NM], [`echo "${rb_CC}" | sed s/clang/llvm-nm/`])
+ AC_CHECK_TOOL([OBJCOPY], [`echo "${rb_CC}" | sed s/clang/llvm-objcopy/`])
+ AC_CHECK_TOOL([OBJDUMP], [`echo "${rb_CC}" | sed s/clang/llvm-objdump/`])
+ AC_CHECK_TOOL([RANLIB], [`echo "${rb_CC}" | sed s/clang/llvm-ranlib/`])
+ AC_CHECK_TOOL([STRIP], [`echo "${rb_CC}" | sed s/clang/llvm-strip/`])
+])
+AS_UNSET(rb_CC)
+AS_UNSET(rb_dummy)
+
+AS_CASE(["${build_os}"],
+[solaris*], [
+ AC_PATH_TOOL([LD], [ld], [/usr/ccs/bin/ld], [/usr/ccs/bin:$PATH])
+],
+[aix*], [
+ AC_PATH_TOOL([NM], [nm], [/usr/ccs/bin/nm], [/usr/ccs/bin:$PATH])
+])
+AS_CASE(["${target_os}"],
+[cygwin*|mingw*], [
+ ac_cv_prog_ac_ct_OBJCOPY=":"
])
-AS_IF([test "$prefix" -ef .], [
- AC_MSG_ERROR(--prefix cannot be the current working directory.)
+
+rb_test_CFLAGS=${CFLAGS+yes}
+rb_test_CXXFLAGS=${CXXFLAGS+yes}
+
+# BSD's ports and MacPorts prefix GNU binutils with 'g'
+
+dnl Seems necessarily in order to add -std=gnu99 option for gcc 4.9.
+m4_version_prereq([2.70], [], [AC_PROG_CC_C99])
+
+AC_PROG_CXX
+AC_PROG_CPP
+AC_PROG_RANLIB
+AC_CHECK_TOOLS([AR], [gar ar])
+AC_CHECK_TOOLS([AS], [gas as])
+AC_CHECK_TOOLS([LD], [gld ld]) # ... try gold ?
+AC_CHECK_TOOLS([NM], [gnm nm])
+AC_CHECK_TOOLS([OBJCOPY], [gobjcopy objcopy])
+AC_CHECK_TOOLS([OBJDUMP], [gobjdump objdump])
+AC_CHECK_TOOLS([STRIP], [gstrip strip], [:])
+
+AS_IF([test ! $rb_test_CFLAGS], [AS_UNSET(CFLAGS)]); AS_UNSET(rb_test_CFLAGS)
+AS_IF([test ! $rb_test_CXXFLAGS], [AS_UNSET(CXXFLAGS)]); AS_UNSET(rb_save_CXXFLAGS)
+
+AS_IF([test "${CXX}" = "g++" -a -z "${GXX}"], [
+ # AC_PROG_CXX sets $CXX to "g++" when it purposefully finds that there is
+ # _no_ g++. This brain-damaged design must be worked around. Thankfully,
+ # similar thing doesn't happen for AC_PROG_CC.
+ rb_there_is_in_fact_no_gplusplus_but_autoconf_is_cheating_us=true
])
-RUBY_BASE_NAME=`echo ruby | sed "$program_transform_name"`
-RUBYW_BASE_NAME=`echo rubyw | sed "$program_transform_name"`
-AC_SUBST(RUBY_BASE_NAME)
-AC_SUBST(RUBYW_BASE_NAME)
-AC_SUBST(RUBY_VERSION_NAME, '${RUBY_BASE_NAME}-${ruby_version}')
-AC_CANONICAL_TARGET
test x"$target_alias" = x &&
target_os=`echo $target_os | sed 's/linux-gnu$/linux/;s/linux-gnu/linux-/'`
ac_install_sh='' # unusable for extension libraries.
@@ -148,8 +273,6 @@ AC_ARG_ENABLE(load-relative,
AS_HELP_STRING([--enable-load-relative], [resolve load paths at run time]),
[load_relative=$enableval])
-AC_ARG_PROGRAM
-
# checks for UNIX variants that set C preprocessor variables
AC_USE_SYSTEM_EXTENSIONS
@@ -175,7 +298,6 @@ dnl ])
AS_CASE(["$host_os:$build_os"],
[darwin*:darwin*], [
- AC_CHECK_TOOLS(CC, [clang gcc cc])
# Following Apple deployed clang are broken
# clang version 1.0 (http://llvm.org/svn/llvm-project/cfe/tags/Apple/clang-23 exported)
# Apple clang version 2.0 (tags/Apple/clang-137) (based on LLVM 2.9svn)
@@ -187,46 +309,9 @@ AS_CASE(["$host_os:$build_os"],
@%:@endif
])],
[],
- [AC_MSG_ERROR([clang version 3.0 or later is required])
- ])],
-[openbsd*:openbsd*], [
- AC_CHECK_TOOLS(CC, [cc])
-])
-AS_IF([test x"${build}" != x"${host}"], [
- AC_CHECK_TOOL(CC, gcc)
+ [AC_MSG_ERROR([clang version 3.0 or later is required])])
])
-dnl Seems necessarily in order to add -std=gnu99 option for gcc 4.9.
-m4_version_prereq([2.70], [], [AC_PROG_CC_C99])
-
-AS_CASE([$CC],
-[gcc-*], [
- gcc_prefix=gcc- gcc_suffix=`echo "$CC" | sed 's/^gcc//'`
- AC_PROG_CXX(g++${gcc_suffix})],
-[clang-*|clang], [
- gcc_prefix=clang- gcc_suffix=`echo "$CC" | sed 's/^clang//'`
- AC_PROG_CXX(clang++${gcc_suffix})],
-[gcc_prefix= gcc_suffix=])
-
-dnl Select the appropriate C++ compiler in OS X
-AS_CASE(["$build_os:${CXX}"],
- [darwin1*.*:], [
- AC_MSG_CHECKING([CXX for $CC])
- AS_CASE(["/$CC "],
- [*@<:@\ /@:>@"gcc-4.2 "*], [pat='gcc-4\.2' CXX=g++-4.2],
- [*@<:@\ /@:>@"gcc "*], [pat=gcc CXX=g++],
- [*@<:@\ /@:>@"cc "*], [pat=cc CXX=c++],
- [*@<:@\ /@:>@"icc "*], [pat=icc CXX=icpc],
- [*@<:@\ /@:>@"clang "*], [pat=clang CXX=clang++])
- AS_IF([test "${CXX}"], [
- CXX=`echo "/$CC " | sed ["s:\([ /]\)${pat}:\1$CXX:; s:^/::; s: *$::"]`
- ])
- AC_MSG_RESULT([$CXX])],
- [openbsd*:*], [
- AC_CHECK_TOOLS(CXX, [c++])
- ])
-test -z "$CXX" || ac_cv_prog_CXX="$CXX"
-
AS_CASE(["$target_os"],
[darwin*], [
AC_MSG_CHECKING(if minimum required OS X version is supported)
@@ -242,13 +327,8 @@ AS_CASE(["$target_os"],
AC_MSG_RESULT(${macosx_min_required})
])
-AC_PROG_CXX
RUBY_MINGW32
-AC_PROG_GCC_TRADITIONAL
AC_SUBST(GCC)
-AS_CASE(["$target_os"],
-[solaris*], [AC_PATH_TOOL([LD], [ld], [/usr/ccs/bin/ld], [/usr/ccs/bin:$PATH])],
-[AC_CHECK_TOOL([LD], [ld], [ld])])
AC_SUBST(LD)
AS_IF([test "$GCC" = yes], [
linker_flag=-Wl,
@@ -281,6 +361,12 @@ AC_SUBST(CSRCFLAG)
: ${MJIT_CC=$CC}
AS_IF([test "x$cross_compiling" = xno], [
AC_PATH_PROG([MJIT_CC], ${MJIT_CC})
+
+ # if $CC is in /usr/lib/ccache/$CC, search original $CC (disable ccache)
+ AS_IF([echo $RUBY_DEBUG | grep ci > /dev/null &&
+ echo $MJIT_CC | grep ^/usr/lib/ccache > /dev/null], [
+ PATH=`echo $PATH | sed "s/\/usr\/lib\/ccache://"` MJIT_CC=`which $CC`])
+
AS_CASE([$target_os],
[*mingw*], [command -v cygpath > /dev/null && MJIT_CC=`cygpath -ma $MJIT_CC`])
shift 2
@@ -295,7 +381,7 @@ AS_CASE(["$build_os"],
echo 'int main(void) {return 0;}' > conftest.c
AS_IF([$CC -framework Foundation -o conftest conftest.c 2>&1 |
grep '^ld: warning: text-based stub file' >/dev/null], [
- CC_WRAPPER=`cd -P "$srcdir/tool" && pwd`/darwin-cc
+ CC_WRAPPER=`cd -P "${tooldir}" && pwd`/darwin-cc
CC="$CC_WRAPPER $CC"
])
rm -fr conftest*
@@ -325,34 +411,13 @@ host_cpu=$target_cpu
host=$target
host_alias=$target_alias
-AS_CASE(["$target_os"], [darwin*], [
-if libtool 2>&1 | grep no_warning_for_no_symbols > /dev/null; then
- ac_cv_prog_ac_ct_RANLIB=:
- ac_cv_prog_ac_ct_AR='libtool -static'
- rb_cv_arflags='-no_warning_for_no_symbols -o'
-fi
-])
-AC_CHECK_TOOLS(RANLIB, [${gcc_prefix}ranlib${gcc_suffix} ranlib], :)
-AC_CHECK_TOOLS(AR, [${gcc_prefix}ar${gcc_suffix} ar])
-AS_IF([test -z "$AR"], [
- AC_CHECK_PROGS(AR, aal, ar)
-])
AC_CACHE_CHECK([for $AR flags], [rb_cv_arflags], [
AS_IF([$AR rcD conftest.a > /dev/null 2>&1 && rm conftest.a],
[rb_cv_arflags=rcD], [rb_cv_arflags=rcu])
])
AC_SUBST(ARFLAGS, ["$rb_cv_arflags "])
-
-AC_CHECK_TOOL(AS, as)
-ASFLAGS=$ASFLAGS
AC_SUBST(ASFLAGS)
-AS_CASE(["$target_os"],[cygwin*|mingw*], [ac_cv_prog_ac_ct_OBJCOPY=":"])
-
-# BSD's ports and MacPorts prefix GNU binutils with 'g'
-AC_CHECK_TOOLS(OBJDUMP, [objdump gobjdump])
-AC_CHECK_TOOLS(OBJCOPY, [objcopy gobjcopy])
-
AS_CASE(["$target_os"],
[cygwin*|mingw*], [
AC_CHECK_TOOL(WINDRES, windres)
@@ -380,9 +445,7 @@ AS_CASE(["$target_os"],
])
: ${enable_shared=yes}
],
-[aix*], [AC_CHECK_TOOL(NM, nm, /usr/ccs/bin/nm, /usr/ccs/bin:$PATH)],
[hiuxmpp*], [AC_DEFINE(__HIUX_MPP__)]) # by TOYODA Eizi <toyoda@npd.kishou.go.jp>
-AC_CHECK_TOOLS(NM, [${gcc_prefix}nm${gcc_suffix} nm])
AC_PROG_LN_S
AC_PROG_MAKE_SET
@@ -407,8 +470,28 @@ AS_IF([test "$cross_compiling:$ac_cv_prog_DTRACE" = no: -a -n "$ac_tool_prefix"]
AC_CHECK_PROGS(DOT, dot)
AC_CHECK_PROGS(DOXYGEN, doxygen)
-AC_CHECK_PROG(PKG_CONFIG, pkg-config, [pkg-config], [], [],
- [`"$as_dir/$ac_word$ac_exec_ext" --print-errors --version > /dev/null 2>&1 || echo "$as_dir/$ac_word$ac_exec_ext"`])
+for prog in ${ac_tool_prefix:+${ac_tool_prefix}pkg-config} pkg-config; do
+ AC_CHECK_PROG(PKG_CONFIG, $prog, [$prog], [], [],
+ [`"$as_dir/$ac_word$ac_exec_ext" --print-errors --version > /dev/null 2>&1 || echo "$as_dir/$ac_word$ac_exec_ext"`])
+ test -z "${PKG_CONFIG}" || break
+done
+
+AC_MSG_CHECKING([whether it is Android])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ @%:@ifdef __ANDROID__
+ @%:@error android
+ @%:@endif
+]], [[]])],
+[AC_MSG_RESULT(no)],
+[
+ AC_MSG_RESULT(yes)
+ target_os=${target_os}-android
+ AC_MSG_CHECKING([for Android API version])
+ # hacky workaround: https://github.com/termux/termux-packages/issues/6176
+ rb_android_api=`getprop ro.build.version.sdk`
+ AC_MSG_RESULT($rb_android_api)
+ RUBY_APPEND_OPTIONS(CPPFLAGS, -D__ANDROID_API__=$rb_android_api -Wno-macro-redefined)
+])
AC_SUBST(RM, ['rm -f'])
AC_SUBST(CP, ['cp'])
@@ -490,6 +573,12 @@ AS_IF([test x"${RPATHFLAG}" = x], [
rpathflag=`echo "$RPATHFLAG" | sed 's/%.*//'`
])
+RUBY_TRY_CFLAGS(-fdeclspec, [
+ RUBY_APPEND_OPTIONS(CC, -fdeclspec)
+ RUBY_APPEND_OPTIONS(MJIT_CC, -fdeclspec)
+])
+RUBY_TRY_CXXFLAGS(-fdeclspec, [RUBY_APPEND_OPTIONS(CXX, -fdeclspec)])
+
AS_CASE([$RUBY_PATCHLEVEL], [-*],
[RUBY_DEVEL=yes], [RUBY_DEVEL=no])
particular_werror_flags=$RUBY_DEVEL
@@ -566,6 +655,22 @@ AS_CASE(["$GCC:${warnflags+set}:${extra_warnflags:+set}:"],
warnflags=
])
RUBY_TRY_CFLAGS(-Qunused-arguments, [RUBY_APPEND_OPTIONS(rb_cv_wsuppress_flags, -Qunused-arguments)])
+AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([
+@%:@if !(defined(__SUNPRO_C)||defined(__SUNPRO_CC))
+@%:@error not sunpro
+@%:@endif],[])], [
+ for e in \
+ E_STATEMENT_NOT_REACHED \
+ E_INIT_SIGN_EXTEND \
+ E_INIT_DOES_NOT_FIT \
+ E_INITIALIZATION_TYPE_MISMATCH
+ do
+ RUBY_TRY_CFLAGS([-erroff=${e}], [
+ RUBY_APPEND_OPTIONS(rb_cv_warnflags, [-erroff=${e}])
+ ])
+ done
+])
AC_ARG_WITH(compress-debug-sections,
AS_HELP_STRING([--with-compress-debug-sections=type],
@@ -589,14 +694,15 @@ AS_IF([test "$GCC" = yes], [
[disable -D_FORTIFY_SOURCE=2 option, which causes link error on mingw]),
[fortify_source=$enableval])
AS_IF([test "x$fortify_source" != xno], [
- RUBY_TRY_CFLAGS(-D_FORTIFY_SOURCE=2, [RUBY_APPEND_OPTION(XCFLAGS, -D_FORTIFY_SOURCE=2)])
+ RUBY_TRY_CFLAGS([$optflags -D_FORTIFY_SOURCE=2], [RUBY_APPEND_OPTION(XCFLAGS, -D_FORTIFY_SOURCE=2)], [],
+ [@%:@include <stdio.h>])
])
: ${MJIT_HEADER_FLAGS='-P -dD'}
# -fstack-protector
AS_CASE(["$target_os"],
- [mingw*], [
+ [mingw*|haiku*], [
stack_protector=no
])
AS_IF([test -z "${stack_protector+set}"], [
@@ -950,6 +1056,8 @@ main()
AC_MSG_RESULT($define_xopen_source)
AS_IF([test x"$define_xopen_source" != xno], [
RUBY_APPEND_OPTIONS(CPPFLAGS, -D_XOPEN_SOURCE=$define_xopen_source)
+ # _XOPEN_SOURCE should not be defined for C++ on Solaris.
+ RUBY_APPEND_OPTIONS(CXXFLAGS, -U_XOPEN_SOURCE)
])
])
],
@@ -1049,6 +1157,24 @@ main()
[ LIBS="-lm $LIBS"])
: ${ORIG_LIBS=$LIBS}
+AS_IF([test -n "${rb_there_is_in_fact_no_gplusplus_but_autoconf_is_cheating_us}"], [
+ AC_MSG_NOTICE([Test skipped due to lack of a C++ compiler.])
+],
+[test -n "${CXX}"], [
+ RUBY_WERROR_FLAG([
+ AC_MSG_CHECKING([whether CXXFLAGS is valid])
+ AC_LANG_PUSH(C++)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <cstdio>]], [[]])],
+ [AC_MSG_RESULT(yes)],[
+ AC_MSG_RESULT(no)
+ # The message mentions CXXFLAGS, but CPPFLAGS might also affects.
+ AC_MSG_WARN([something wrong with CXXFLAGS="$CXXFLAGS"])
+ CXX=false
+ ])
+ AC_LANG_POP(C++)
+ ])
+])
+
AC_CHECK_LIB(crypt, crypt) # glibc (GNU/Linux, GNU/Hurd, GNU/kFreeBSD)
AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV
AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX
@@ -1105,6 +1231,9 @@ AC_CHECK_HEADERS(syscall.h)
AC_CHECK_HEADERS(time.h)
AC_CHECK_HEADERS(ucontext.h)
AC_CHECK_HEADERS(utime.h)
+AS_CASE("$target_cpu", [x64|x86_64|i[3-6]86*], [
+ AC_CHECK_HEADERS(x86intrin.h)
+])
AC_ARG_WITH([gmp],
[AS_HELP_STRING([--without-gmp],
@@ -1274,82 +1403,13 @@ RUBY_REPLACE_TYPE(clockid_t, [], CLOCKID, [@%:@ifdef HAVE_TIME_H
@%:@ include <sys/time.h>
@%:@endif])
-AC_CACHE_CHECK(for prototypes, rb_cv_have_prototypes,
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int foo(int x) { return 0; }]], [[return foo(10);]])],
- rb_cv_have_prototypes=yes,
- rb_cv_have_prototypes=no)])
-AS_IF([test "$rb_cv_have_prototypes" = yes], [
- AC_DEFINE(HAVE_PROTOTYPES)
-])
-
-AC_CACHE_CHECK(token paste string, rb_cv_tokenpaste,
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@define paste(a,b) a@%:@@%:@b]],
- [[int xy = 1; return paste(x,y);]])],
- rb_cv_tokenpaste=ansi,
- rb_cv_tokenpaste=knr)])
-AS_IF([test "$rb_cv_tokenpaste" = ansi], [
- AC_DEFINE(TOKEN_PASTE(x,y),[x@%:@@%:@y])
-], [
- AC_DEFINE(TOKEN_PASTE(x,y),[x/**/y])
-])
-
-AC_CACHE_CHECK(stringization, rb_cv_stringization, [
- rb_cv_stringization=no
- for string in "#expr" '"expr"'; do
- AC_COMPILE_IFELSE([
- AC_LANG_BOOL_COMPILE_TRY([
-#define STRINGIZE0(expr) $string
-#define STRINGIZE(expr) STRINGIZE0(expr)
-#undef real_test_for_stringization
-#define test_for_stringization -.real_test_for_stringization.-
-const char stringized[[]] = STRINGIZE(test_for_stringization);
-], [sizeof(stringized) == 32])],
- [rb_cv_stringization="$string"; break],
- [rb_cv_stringization=no])
- done]
-)
-AC_DEFINE(STRINGIZE(expr),STRINGIZE0(expr))
-AS_IF([test x"$rb_cv_stringization" != xno -a "$rb_cv_stringization" != "#expr"], [
- AC_DEFINE_UNQUOTED(STRINGIZE0(expr),$rb_cv_stringization)
- AC_DEFINE(OLD_FASHIONED_STRINGIZATION,1)
-])
-
-AC_CACHE_CHECK([string literal concatenation],
- rb_cv_string_literal_concatenation, [
- AC_COMPILE_IFELSE([
- AC_LANG_BOOL_COMPILE_TRY([
-const char concatenated_literal[[]] = "literals" "to"
- "be" "concatenated.";
-], [sizeof(concatenated_literal) == 26])],
- [rb_cv_string_literal_concatenation=yes],
- [rb_cv_string_literal_concatenation=no])]
-)
-AS_IF([test "$rb_cv_string_literal_concatenation" = no], [
- AC_MSG_ERROR([No string literal concatenation])
-])
-
-AC_CACHE_CHECK(for variable length prototypes and stdarg.h, rb_cv_stdarg,
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <stdarg.h>
-int foo(int x, ...) {
- va_list va;
- va_start(va, x);
- va_arg(va, int);
- va_arg(va, char *);
- va_arg(va, double);
- return 0;
-}
-]], [[return foo(10, "", 3.14);]])],
- rb_cv_stdarg=yes,
- rb_cv_stdarg=no)])
-AS_IF([test "$rb_cv_stdarg" = yes], [
- AC_DEFINE(HAVE_STDARG_PROTOTYPES)
-])
-
+# __VA_ARGS__ is also tested in AC_PROG_CC_C99 since autoconf 2.60a (around
+# 2006). The check below is redundant and should always success. Remain not
+# deleted for backward compat.
AC_CACHE_CHECK(for variable length macro, rb_cv_va_args_macro,
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-int foo(int x, ...);
-@%:@define FOO(a, ...) foo(a, @%:@@%:@__VA_ARGS__)
+int foo(const char*);
+@%:@define FOO(...) foo(@%:@__VA_ARGS__)
]], [[FOO(1);FOO(1,2);FOO(1,2,3);]])],
rb_cv_va_args_macro=yes,
rb_cv_va_args_macro=no)])
@@ -1357,49 +1417,44 @@ AS_IF([test "$rb_cv_va_args_macro" = yes], [
AC_DEFINE(HAVE_VA_ARGS_MACRO)
])
-AC_CACHE_CHECK([for alignas() syntax], rb_cv_have_alignas, [
-rb_cv_have_alignas=no
-RUBY_WERROR_FLAG([
-for attr in \
- "_Alignas(x)" \
- "alignas(x)" \
- "@<:@@<:@alignas(x)@:>@@:>@" \
- "__declspec(aligned(x))" \
- "__attribute__((__aligned__(x)))" \
-;
-do
- # C11 _Alignas and GCC __attribute__((__aligned__)) behave
- # slightly differently. What we want is GCC's. Check that
- # here by something C11 does not allow (`struct ALIGNAS ...`)
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
- [@%:@define ALIGNAS(x) $attr
- struct ALIGNAS(128) conftest_tag { int foo; } foo; ]], [[]])],
- [rb_cv_have_alignas="$attr"; break], [])
-done
-])])
-AS_IF([test "$rb_cv_have_alignas" != no], [
- AC_DEFINE_UNQUOTED([RUBY_ALIGNAS(x)], $rb_cv_have_alignas)
+# We want C11's `_Alignof`. GCC (and alike) have `__alignof__`, which behave
+# slightly differently than the C11's. We cannot use `__alignof__` for our
+# purpose. The problem is, however, that old gcc and old clang had both
+# implemented `_Alignof` as a synonym of `__alignof__`. They are not what we
+# want. We have to check sanity.
+#
+# See also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023
+# See also: https://bugs.llvm.org/show_bug.cgi?id=26547
+AC_CACHE_CHECK([if _Alignof() works], rb_cv_have__alignof,[
+ rb_cv_have__alignof=no
+ RUBY_WERROR_FLAG([
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ @%:@ifdef HAVE_STDALIGN_H
+ @%:@include <stdalign.h>
+ @%:@endif
+ @%:@ifdef STDC_HEADERS
+ @%:@include <stddef.h>
+ @%:@endif
+ @%:@ifndef __GNUC__
+ @%:@define __extension__
+ @%:@endif
+ ]], [[
+ typedef struct conftest_tag {
+ char _;
+ double d;
+ } T;
+ static int conftest_ary@<:@
+ offsetof(T, d) == __extension__ _Alignof(double)
+ ? 1 : -1
+ @:>@;
+ return conftest_ary@<:@0@:>@;
+ ]])],[
+ rb_cv_have__alignof=yes
+ ],[])
+ ])
])
-
-AC_CACHE_CHECK([for alignof() syntax], rb_cv_have_alignof,[
-rb_cv_have_alignof=no
-RUBY_WERROR_FLAG([
-for expr in \
- "alignof" \
- "_Alignof" \
- "__alignof" \
- "__alignof__" \
-;
-do
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
- @%:@ifdef HAVE_STDALIGN_H
- @%:@include <stdalign.h>
- @%:@endif]],[[return (int)$expr(int);]])],
- [rb_cv_have_alignof="$expr"; break], [])
-done
-])])
-AS_IF([test "$rb_cv_have_alignof" != no], [
- AC_DEFINE_UNQUOTED(RUBY_ALIGNOF, $rb_cv_have_alignof)
+AS_IF([test "$rb_cv_have__alignof" != no], [
+ AC_DEFINE(HAVE__ALIGNOF)
])
RUBY_FUNC_ATTRIBUTE(__const__, CONSTFUNC)
@@ -1407,7 +1462,6 @@ RUBY_FUNC_ATTRIBUTE(__pure__, PUREFUNC)
RUBY_FUNC_ATTRIBUTE(__noreturn__, NORETURN)
RUBY_FUNC_ATTRIBUTE(__deprecated__, DEPRECATED)
RUBY_FUNC_ATTRIBUTE(__deprecated__("by "@%:@n), DEPRECATED_BY(n,x), rb_cv_func_deprecated_by)
-RUBY_TYPE_ATTRIBUTE(__deprecated__ mesg, DEPRECATED_TYPE(mesg,x), rb_cv_type_deprecated)
RUBY_FUNC_ATTRIBUTE(__noinline__, NOINLINE)
RUBY_FUNC_ATTRIBUTE(__always_inline__, ALWAYS_INLINE)
RUBY_FUNC_ATTRIBUTE(__no_sanitize__(san), NO_SANITIZE(san, x), rb_cv_func_no_sanitize)
@@ -1437,6 +1491,17 @@ AS_IF([test "$rb_cv_CentOS6_CXX_workaround" != no],[
AC_DEFINE([RUBY_CXX_DEPRECATED(msg)],
[__attribute__((__deprecated__(msg)))])])
+AC_CACHE_CHECK([for std::nullptr_t], rb_cv_CXX_nullptr, [
+ AC_LANG_PUSH([C++])
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [@%:@include <cstddef>],
+ [static std::nullptr_t const *const conftest = nullptr;])],
+ [rb_cv_CXX_nullptr=yes],
+ [rb_cv_CXX_nullptr=no])
+ AC_LANG_POP()])
+AS_IF([test "$rb_cv_CXX_nullptr" != no],[AC_DEFINE(HAVE_NULLPTR)])
+
if_i386=${universal_binary+[defined __i386__]}
RUBY_FUNC_ATTRIBUTE(__stdcall__, FUNC_STDCALL, rb_cv_func_stdcall, ${if_i386})
RUBY_FUNC_ATTRIBUTE(__cdecl__, FUNC_CDECL, rb_cv_func_cdecl, ${if_i386})
@@ -1490,6 +1555,7 @@ AS_IF([test "$GCC" = yes], [
AS_IF([test "$rb_cv_gcc_sync_builtins" = yes], [
AC_DEFINE(HAVE_GCC_SYNC_BUILTINS)
])
+])
AC_CACHE_CHECK(for __builtin_unreachable, rb_cv_func___builtin_unreachable,
[RUBY_WERROR_FLAG(
@@ -1502,7 +1568,6 @@ AS_IF([test "$GCC" = yes], [
AS_IF([test "$rb_cv_func___builtin_unreachable" = yes], [
AC_DEFINE_UNQUOTED(UNREACHABLE, [__builtin_unreachable()])
])
-])
AC_CACHE_CHECK(for exported function attribute, rb_cv_func_exported, [
rb_cv_func_exported=no
@@ -1525,10 +1590,8 @@ RUBY_DECL_ATTRIBUTE([__nonnull__(n)], [RUBY_FUNC_NONNULL(n,x)], [rb_cv_func_nonn
RUBY_APPEND_OPTION(XCFLAGS, -DRUBY_EXPORT)
AC_ARG_ENABLE(mathn,
- AS_HELP_STRING([--disable-mathn], [disable canonicalization for mathn]),
- [mathn=$enableval], [mathn=yes])
-test "x$mathn" = xyes || mathn=
-AC_SUBST(MATHN, $mathn)
+ AS_HELP_STRING([--enable-mathn], [enable canonicalization for mathn]),
+ [AC_MSG_ERROR([mathn support has been dropped])])
AC_CACHE_CHECK(for function name string predefined identifier,
rb_cv_function_name_string,
@@ -1707,7 +1770,6 @@ AS_IF([test $rb_cv_stack_end_address != no], [
dnl Checks for library functions.
AC_TYPE_GETGROUPS
-AC_DEFINE(RETSIGTYPE, void)
AS_CASE(["${target_cpu}-${target_os}:${target_archs}"],
[powerpc-darwin*], [
AC_LIBSOURCES(alloca.c)
@@ -1935,6 +1997,8 @@ AC_CHECK_FUNCS(utimensat)
AC_CHECK_FUNCS(utimes)
AC_CHECK_FUNCS(wait4)
AC_CHECK_FUNCS(waitpid)
+AC_CHECK_FUNCS(__cospi)
+AC_CHECK_FUNCS(__sinpi)
AS_IF([test "x$ac_cv_member_struct_statx_stx_btime" = xyes],
[AC_CHECK_FUNCS(statx)])
@@ -2276,6 +2340,45 @@ AS_IF([test "$rb_cv_rshift_sign" = yes], [
AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>(int)(y)) : (x)>>(int)(y)))
])
+AS_IF([test "$ac_cv_func_copy_file_range" = no], [
+ AC_CACHE_CHECK([for copy_file_range],
+ rb_cv_use_copy_file_range,
+ [AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifndef O_TMPFILE
+ #define O_TMPFILE __O_TMPFILE
+#endif
+
+int
+main()
+{
+#ifdef __NR_copy_file_range
+ int ret, fd_in, fd_out;
+ fd_in = open("/tmp", O_TMPFILE|O_RDWR, S_IRUSR);
+ fd_out = open("/tmp", O_TMPFILE|O_WRONLY, S_IWUSR);
+ ret = syscall(__NR_copy_file_range, fd_in, NULL, fd_out, NULL, 0, 0);
+ close(fd_in);
+ close(fd_out);
+ if (ret == -1) { return 1; }
+ return 0;
+#else
+ return 1;
+#endif
+}
+ ]])],
+ [rb_cv_use_copy_file_range=yes],
+ [rb_cv_use_copy_file_range=no],
+ [rb_cv_use_copy_file_range=no])])
+])
+AS_CASE(["$ac_cv_func_copy_file_range:$rb_cv_use_copy_file_range"], [*yes*], [
+ AC_DEFINE(USE_COPY_FILE_RANGE)
+])
+
AS_CASE(["$ac_cv_func_gettimeofday:$ac_cv_func_clock_gettime"],
[*yes*], [],
[
@@ -2322,6 +2425,7 @@ AC_ARG_WITH(coroutine,
[rb_cv_coroutine=$withval])
AS_CASE([$rb_cv_coroutine], [yes|''], [
AC_MSG_CHECKING(native coroutine implementation for ${target_cpu}-${target_os})
+ rb_cv_coroutine=
AS_CASE(["$target_cpu-$target_os"],
[x*64-darwin*], [
rb_cv_coroutine=amd64
@@ -2333,7 +2437,7 @@ AS_CASE([$rb_cv_coroutine], [yes|''], [
AS_CASE(["$ac_cv_sizeof_voidp"],
[8], [ rb_cv_coroutine=amd64 ],
[4], [ rb_cv_coroutine=x86 ],
- [*], [ rb_cv_coroutine= ]
+ dnl unknown pointer size, bail out as no Context.h soon.
)
],
[*86-linux*], [
@@ -2345,8 +2449,8 @@ AS_CASE([$rb_cv_coroutine], [yes|''], [
[*86-mingw32], [
rb_cv_coroutine=win32
],
- [armv7*-linux*], [
- rb_cv_coroutine=ucontext
+ [arm*-linux*], [
+ rb_cv_coroutine=arm32
],
[aarch64-linux*], [
rb_cv_coroutine=arm64
@@ -2363,20 +2467,25 @@ AS_CASE([$rb_cv_coroutine], [yes|''], [
[*-openbsd*], [
rb_cv_coroutine=copy
],
- [*], [
+ [*-haiku*], [
+ rb_cv_coroutine=copy
+ ],
+ [
rb_cv_coroutine=ucontext
]
)
AC_MSG_RESULT(${rb_cv_coroutine})
])
COROUTINE_H=coroutine/$rb_cv_coroutine/Context.h
+AS_IF([test ! -f "$srcdir/$COROUTINE_H"],
+ [AC_MSG_ERROR('$rb_cv_coroutine' is not supported as coroutine)])
AS_CASE([$rb_cv_coroutine],
[copy|ucontext], [
COROUTINE_SRC=coroutine/$rb_cv_coroutine/Context.c
],
- [*], [
+ [
COROUTINE_SRC=coroutine/$rb_cv_coroutine/Context.'$(ASMEXT)'
- ],
+ ]
)
AC_DEFINE_UNQUOTED(COROUTINE_H, ["$COROUTINE_H"])
AC_SUBST(X_COROUTINE_H, [$COROUTINE_H])
@@ -2587,9 +2696,7 @@ AS_IF([test "$rb_cv_binary_elf" = yes], [
AC_CHECK_HEADERS([elf.h elf_abi.h])
AS_IF([test $ac_cv_header_elf_h = yes -o $ac_cv_header_elf_abi_h = yes], [
AC_LIBOBJ([addr2line])
- AS_IF([test "x$compress_debug_sections" = xzlib], [
- AC_CHECK_LIB([z], [uncompress])
- ])
+ AC_CHECK_LIB([z], [uncompress])
])
])
@@ -2607,6 +2714,10 @@ AS_CASE(["$target_os"],
])])
LIBEXT=a
+AC_ARG_WITH(mjit-tabs,
+ AS_HELP_STRING([--without-mjit-tabs], [expand tabs in mjit header]),
+ [AS_IF([test $withval = no], [MJIT_TABS=false])])
+AC_SUBST(MJIT_TABS)dnl
AC_SUBST(DLDFLAGS)dnl
AC_SUBST(ARCH_FLAG)dnl
AC_SUBST(MJIT_HEADER_FLAGS)dnl
@@ -2729,14 +2840,6 @@ AS_IF([test "$with_dln_a_out" != yes], [
: ${LDFLAGS=""}
: ${LIBPATHENV=DYLD_FALLBACK_LIBRARY_PATH}
: ${PRELOADENV=DYLD_INSERT_LIBRARIES}
- AS_IF([test x"$enable_shared" = xyes], [
- # Resolve symbols from libruby.dylib when --enable-shared
- EXTDLDFLAGS='$(LIBRUBYARG_SHARED)'
- ], [test "x$EXTSTATIC" = x], [
- # When building exts as bundles, a mach-o bundle needs to know its loader
- # program to bind symbols from the ruby executable
- EXTDLDFLAGS="-bundle_loader '\$(BUILTRUBY)'"
- ])
rb_cv_dlopen=yes],
[aix*], [ : ${LDSHARED='$(CC)'}
AS_IF([test "$GCC" = yes], [
@@ -2773,26 +2876,15 @@ AS_IF([test "$with_dln_a_out" != yes], [
AS_IF([test "$rb_cv_dlopen" = yes], [
AS_CASE(["$target_os"],
[darwin*], [
- AC_SUBST(ADDITIONAL_DLDFLAGS, "")
for flag in \
- "-multiply_defined suppress" \
"-undefined dynamic_lookup" \
+ "-multiply_defined suppress" \
; do
- test "x${linker_flag}" = x || flag="${linker_flag}`echo ${flag} | tr ' ' ,`"
- RUBY_TRY_LDFLAGS([$flag], [], [$flag=])
- AS_IF([test x"$flag" = x], [continue])
-
- AC_MSG_CHECKING([whether $flag is accepted for bundle])
- : > conftest.c
- AS_IF([${LDSHARED/'$(CC)'/$CC} -o conftest.bundle $flag conftest.c >/dev/null 2>conftest.err &&
- test ! -s conftest.err], [
- AC_MSG_RESULT([yes])
- RUBY_APPEND_OPTIONS(DLDFLAGS, [$flag])
- ], [
- AC_MSG_RESULT([no])
- RUBY_APPEND_OPTIONS(ADDITIONAL_DLDFLAGS, [$flag])
- ])
- rm -fr conftest.*
+ test "x${linker_flag}" = x || flag="${linker_flag}`echo ${flag} | tr ' ' ,`"
+ RUBY_TRY_LDFLAGS([$flag], [], [flag=])
+ AS_IF([test "x$flag" != x], [
+ RUBY_APPEND_OPTIONS(DLDFLAGS, [$flag])
+ ])
done
])
])
@@ -2877,6 +2969,7 @@ AS_IF([test "x$ac_cv_func_backtrace" = xyes], [
#include <signal.h>
#include <execinfo.h>
+]`grep '^@%:@ *define *RUBY_SIGALTSTACK_SIZE' ${srcdir}/signal.c`[
#define TRACE_SIZE 256
void sigsegv(int signum, siginfo_t *info, void *ctx){
@@ -2896,12 +2989,12 @@ main(void)
stack_t ss;
struct sigaction sa;
- ss.ss_sp = malloc(16*1024);
+ ss.ss_sp = malloc(RUBY_SIGALTSTACK_SIZE);
if (ss.ss_sp == NULL) {
fprintf(stderr, "cannot allocate memory for sigaltstack\n");
return EXIT_FAILURE;
}
- ss.ss_size = 16*1024;
+ ss.ss_size = RUBY_SIGALTSTACK_SIZE;
ss.ss_flags = 0;
if (sigaltstack(&ss, NULL) == -1) {
fprintf(stderr, "sigaltstack failed\n");
@@ -2995,14 +3088,21 @@ AC_SUBST(DLEXT)
AS_IF([test "$with_dln_a_out" = yes], [
STRIP=true
], [
- AC_CHECK_TOOL(STRIP, strip, :)dnl
+ AC_MSG_CHECKING([for $STRIP flags])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM], [AS_IF(
+ ["${STRIP}" -A -n conftest$ac_exeext 2>/dev/null], [
+ AC_MSG_RESULT([-A -n])
+ STRIP="${STRIP} -A -n"
+ ],
+ ["${STRIP}" -S -x conftest$ac_exeext 2>/dev/null], [
+ AC_MSG_RESULT([-S -x])
+ STRIP="${STRIP} -S -x"
+ ], [
+ AC_MSG_RESULT([none needed])
+ ])
+ ])
])
-AS_CASE(["$target_os"],
- [linux* | gnu* | k*bsd*-gnu | kopensolaris*-gnu], [
- STRIP="$STRIP -S -x"],
- [darwin*], [
- STRIP="$STRIP -A -n"])
AC_ARG_WITH(ext,
AS_HELP_STRING([--with-ext=EXTS],
@@ -3096,7 +3196,7 @@ AS_IF([test x"$cross_compiling" = xyes], [
MINIRUBY='./miniruby$(EXEEXT) -I$(srcdir)/lib -I.'
MINIRUBY="$MINIRUBY"' -I$(EXTOUT)/common'
PREP='miniruby$(EXEEXT)'
- RUNRUBY_COMMAND='$(MINIRUBY) $(srcdir)/tool/runruby.rb --extout=$(EXTOUT) $(RUNRUBYOPT)'
+ RUNRUBY_COMMAND='$(MINIRUBY) $(tooldir)/runruby.rb --extout=$(EXTOUT) $(RUNRUBYOPT)'
RUNRUBY='$(RUNRUBY_COMMAND) --'
XRUBY='$(RUNRUBY)'
AS_CASE(["$HAVE_BASERUBY:$build_os"], [no:*|*:mingw*], [BOOTSTRAPRUBY='$(MINIRUBY)'])
@@ -3192,6 +3292,11 @@ AS_CASE("$enable_shared", [yes], [
AC_DEFINE_UNQUOTED(LIBDIR_BASENAME, ["${libdir_basename}"])
libdir_basename="${libdir_basename}"${multiarch+'/${arch}'}
+ RUBY_TRY_LDFLAGS([${linker_flag}--no-as-needed], [no_as_needed=yes], [no_as_needed=no])
+ AS_IF([test "$no_as_needed" = yes], [
+ RUBY_APPEND_OPTIONS(LDFLAGS, [${linker_flag}--no-as-needed])
+ ])
+
AS_CASE(["$target_os"],
[freebsd*|dragonfly*], [],
[
@@ -3351,6 +3456,9 @@ AS_CASE(["${enable_dtrace}"],
], [
rb_cv_dtrace_available=no
])
+AS_CASE(["$target_os"],[freebsd*],[
+ rb_cv_dtrace_available=no
+ ])
AS_IF([test "${enable_dtrace}" = yes], [dnl
AS_IF([test -z "$DTRACE"], [dnl
AC_MSG_ERROR([dtrace(1) is missing])
@@ -3955,7 +4063,7 @@ guard=INCLUDE_RUBY_CONFIG_H
} | tr -d '\015' |
(
AS_IF([test "x$CONFIGURE_TTY" = xyes], [color=--color], [color=])
- exec ${srcdir}/tool/ifchange $color "${config_h}" -
+ exec ${tooldir}/ifchange $color "${config_h}" -
) >&AS_MESSAGE_FD || AC_MSG_ERROR([failed to create ${config_h}])
tr -d '\015' < largefile.h > confdefs.h
rm largefile.h
@@ -4008,7 +4116,7 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [
VCS='echo cannot'
])
AS_CASE("$VCS",
- ['$(GIT)'|git], [VCSUP='$(VCS) pull $(GITPULLOPTIONS)'],
+ ['$(GIT)'|git], [VCSUP='$(VCS) pull --rebase $(GITPULLOPTIONS)'],
[VCSUP='$(VCS)'])
sed -n \
-e '[/^@%:@define \(RUBY_RELEASE_[A-Z]*\) \([0-9][0-9]*\)/]{' \
@@ -4038,7 +4146,7 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [
echo 'ruby: $(PROGRAM);' >> $tmpmk
test "$tmpmk" = "$tmpgmk" || rm -f "$tmpgmk"
]) && mv -f $tmpmk Makefile],
-[EXEEXT='$EXEEXT' gnumake='$gnumake' GIT='$GIT'])
+[EXEEXT='$EXEEXT' MAKE='${MAKE-make}' gnumake='$gnumake' GIT='$GIT'])
AC_ARG_WITH([ruby-pc],
AS_HELP_STRING([--with-ruby-pc=FILENAME], [pc file basename]),
diff --git a/constant.h b/constant.h
index 3f1418df17..e0d36909e1 100644
--- a/constant.h
+++ b/constant.h
@@ -1,3 +1,5 @@
+#ifndef CONSTANT_H
+#define CONSTANT_H
/**********************************************************************
constant.h -
@@ -8,8 +10,8 @@
Copyright (C) 2009 Yusuke Endoh
**********************************************************************/
-#ifndef CONSTANT_H
-#define CONSTANT_H
+#include "ruby/ruby.h"
+#include "id_table.h"
typedef enum {
CONST_DEPRECATED = 0x100,
@@ -39,12 +41,15 @@ VALUE rb_mod_private_constant(int argc, const VALUE *argv, VALUE obj);
VALUE rb_mod_public_constant(int argc, const VALUE *argv, VALUE obj);
VALUE rb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj);
void rb_free_const_table(struct rb_id_table *tbl);
+VALUE rb_const_source_location(VALUE, ID);
+
+MJIT_SYMBOL_EXPORT_BEGIN
+int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag);
+rb_const_entry_t *rb_const_lookup(VALUE klass, ID id);
VALUE rb_public_const_get_at(VALUE klass, ID id);
VALUE rb_public_const_get_from(VALUE klass, ID id);
int rb_public_const_defined_from(VALUE klass, ID id);
-rb_const_entry_t *rb_const_lookup(VALUE klass, ID id);
-int rb_autoloading_value(VALUE mod, ID id, VALUE *value, rb_const_flag_t *flag);
-VALUE rb_const_source_location(VALUE, ID);
VALUE rb_const_source_location_at(VALUE, ID);
+MJIT_SYMBOL_EXPORT_END
#endif /* CONSTANT_H */
diff --git a/cont.c b/cont.c
index f1edd82bf0..a7103a087e 100644
--- a/cont.c
+++ b/cont.c
@@ -9,19 +9,27 @@
**********************************************************************/
-#include "internal.h"
-#include "vm_core.h"
-#include "gc.h"
-#include "eval_intern.h"
-#include "mjit.h"
-
-#include COROUTINE_H
+#include "ruby/internal/config.h"
#ifndef _WIN32
#include <unistd.h>
#include <sys/mman.h>
#endif
+#include COROUTINE_H
+
+#include "eval_intern.h"
+#include "gc.h"
+#include "internal.h"
+#include "internal/cont.h"
+#include "internal/proc.h"
+#include "internal/warnings.h"
+#include "internal/scheduler.h"
+#include "mjit.h"
+#include "vm_core.h"
+#include "id_table.h"
+#include "ractor_core.h"
+
static const int DEBUG = 0;
#define RB_PAGE_SIZE (pagesize)
@@ -227,12 +235,12 @@ struct rb_fiber_struct {
rb_context_t cont;
VALUE first_proc;
struct rb_fiber_struct *prev;
+ VALUE resuming_fiber;
+
BITFIELD(enum fiber_status, status, 2);
- /* If a fiber invokes by "transfer",
- * then this fiber can't be invoked by "resume" any more after that.
- * You shouldn't mix "transfer" and "resume".
- */
- unsigned int transferred : 1;
+ /* Whether the fiber is allowed to implicitly yield. */
+ unsigned int yielding : 1;
+ unsigned int blocking : 1;
struct coroutine_context context;
struct fiber_pool_stack stack;
@@ -240,6 +248,8 @@ struct rb_fiber_struct {
static struct fiber_pool shared_fiber_pool = {NULL, NULL, 0, 0, 0, 0};
+static ID fiber_initialize_keywords[2] = {0};
+
/*
* FreeBSD require a first (i.e. addr) argument of mmap(2) is not NULL
* if MAP_STACK is passed.
@@ -796,14 +806,15 @@ static inline void
ec_switch(rb_thread_t *th, rb_fiber_t *fiber)
{
rb_execution_context_t *ec = &fiber->cont.saved_ec;
-
- ruby_current_execution_context_ptr = th->ec = ec;
+ rb_ractor_set_current_ec(th->ractor, th->ec = ec);
+ // ruby_current_execution_context_ptr = th->ec = ec;
/*
* timer-thread may set trap interrupt on previous th->ec at any time;
* ensure we do not delay (or lose) the trap interrupt handling.
*/
- if (th->vm->main_thread == th && rb_signal_buff_size() > 0) {
+ if (th->vm->ractor.main_thread == th &&
+ rb_signal_buff_size() > 0) {
RUBY_VM_SET_TRAP_INTERRUPT(ec);
}
@@ -837,6 +848,12 @@ NOINLINE(static VALUE cont_capture(volatile int *volatile stat));
if (!(th)->ec->tag) rb_raise(rb_eThreadError, "not running thread"); \
} while (0)
+rb_thread_t*
+rb_fiber_threadptr(const rb_fiber_t *fiber)
+{
+ return fiber->cont.saved_ec.thread_ptr;
+}
+
static VALUE
cont_thread_value(const rb_context_t *cont)
{
@@ -899,11 +916,13 @@ cont_mark(void *ptr)
RUBY_MARK_LEAVE("cont");
}
+#if 0
static int
fiber_is_root_p(const rb_fiber_t *fiber)
{
return fiber == fiber->cont.saved_ec.thread_ptr->root_fiber;
}
+#endif
static void
cont_free(void *ptr)
@@ -925,7 +944,8 @@ cont_free(void *ptr)
RUBY_FREE_UNLESS_NULL(cont->saved_vm_stack.ptr);
- if (mjit_enabled && cont->mjit_cont != NULL) {
+ if (mjit_enabled) {
+ VM_ASSERT(cont->mjit_cont != NULL);
mjit_cont_free(cont->mjit_cont);
}
/* free rb_cont_t or rb_fiber_t */
@@ -1011,7 +1031,7 @@ fiber_free(void *ptr)
//if (DEBUG) fprintf(stderr, "fiber_free: %p[%p]\n", fiber, fiber->stack.base);
if (fiber->cont.saved_ec.local_storage) {
- st_free_table(fiber->cont.saved_ec.local_storage);
+ rb_id_table_free(fiber->cont.saved_ec.local_storage);
}
cont_free(&fiber->cont);
@@ -1030,7 +1050,7 @@ fiber_memsize(const void *ptr)
* vm.c::thread_memsize already counts th->ec->local_storage
*/
if (saved_ec->local_storage && fiber != th->root_fiber) {
- size += st_memsize(saved_ec->local_storage);
+ size += rb_id_table_memsize(saved_ec->local_storage);
}
size += cont_memsize(&fiber->cont);
return size;
@@ -1130,11 +1150,20 @@ cont_new(VALUE klass)
return cont;
}
+VALUE rb_fiberptr_self(struct rb_fiber_struct *fiber)
+{
+ return fiber->cont.self;
+}
+
+unsigned int rb_fiberptr_blocking(struct rb_fiber_struct *fiber)
+{
+ return fiber->blocking;
+}
+
+// This is used for root_fiber because other fibers call cont_init_mjit_cont through cont_new.
void
rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber)
{
- // Currently this function is meant for root_fiber. Others go through cont_new.
- // XXX: Is this mjit_cont `mjit_cont_free`d?
cont_init_mjit_cont(&fiber->cont);
}
@@ -1602,6 +1631,8 @@ rollback_ensure_stack(VALUE self,rb_ensure_list_t *current,rb_ensure_entry_t *ta
}
}
+NORETURN(static VALUE rb_cont_call(int argc, VALUE *argv, VALUE contval));
+
/*
* call-seq:
* cont.call(args, ...)
@@ -1640,7 +1671,7 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
cont->value = make_passing_arg(argc, argv);
cont_restore_0(cont, &contval);
- return Qnil; /* unreachable */
+ UNREACHABLE_RETURN(Qnil);
}
/*********/
@@ -1708,6 +1739,28 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
* 1000000
* FiberError: dead fiber called
*
+ * == Non-blocking Fibers
+ *
+ * Since Ruby 3.0, the concept of <em>non-blocking fiber</em> was introduced.
+ * Non-blocking fiber, when reaching any potentially blocking operation (like
+ * sleep, wait for another process, wait for I/O data to be ready), instead
+ * of just freezing itself and all execution in the thread, yields control
+ * to other fibers, and allows the <em>scheduler</em> to handle waiting and waking
+ * (resuming) the fiber when it can proceed.
+ *
+ * For Fiber to behave as non-blocking, it should be created in Fiber.new with
+ * <tt>blocking: false</tt> (which is the default now), and Fiber.scheduler
+ * should be set with Fiber.set_scheduler. If Fiber.scheduler is not set in
+ * the current thread, blocking and non-blocking fiber's behavior is identical.
+ *
+ * Ruby doesn't provide a scheduler class: it is expected to be implemented by
+ * the user and correspond to Fiber::SchedulerInterface.
+ *
+ * There is also Fiber.schedule method, which is expected to immediately perform
+ * passed block in a non-blocking manner (but its actual implementation is up to
+ * the scheduler).
+ *
+ *
*/
static const rb_data_type_t fiber_data_type = {
@@ -1723,7 +1776,7 @@ fiber_alloc(VALUE klass)
}
static rb_fiber_t*
-fiber_t_alloc(VALUE fiber_value)
+fiber_t_alloc(VALUE fiber_value, unsigned int blocking)
{
rb_fiber_t *fiber;
rb_thread_t *th = GET_THREAD();
@@ -1736,6 +1789,7 @@ fiber_t_alloc(VALUE fiber_value)
fiber = ZALLOC(rb_fiber_t);
fiber->cont.self = fiber_value;
fiber->cont.type = FIBER_CONTEXT;
+ fiber->blocking = blocking;
cont_init(&fiber->cont, th);
fiber->cont.saved_ec.fiber_ptr = fiber;
@@ -1753,9 +1807,9 @@ fiber_t_alloc(VALUE fiber_value)
}
static VALUE
-fiber_initialize(VALUE self, VALUE proc, struct fiber_pool * fiber_pool)
+fiber_initialize(VALUE self, VALUE proc, struct fiber_pool * fiber_pool, unsigned int blocking)
{
- rb_fiber_t *fiber = fiber_t_alloc(self);
+ rb_fiber_t *fiber = fiber_t_alloc(self, blocking);
fiber->first_proc = proc;
fiber->stack.base = NULL;
@@ -1783,22 +1837,178 @@ fiber_prepare_stack(rb_fiber_t *fiber)
sec->local_storage_recursive_hash_for_trace = Qnil;
}
+static struct fiber_pool *
+rb_fiber_pool_default(VALUE pool)
+{
+ return &shared_fiber_pool;
+}
+
/* :nodoc: */
static VALUE
+rb_fiber_initialize_kw(int argc, VALUE* argv, VALUE self, int kw_splat)
+{
+ VALUE pool = Qnil;
+ VALUE blocking = Qfalse;
+
+ if (kw_splat != RB_NO_KEYWORDS) {
+ VALUE options = Qnil;
+ VALUE arguments[2] = {Qundef};
+
+ argc = rb_scan_args_kw(kw_splat, argc, argv, ":", &options);
+ rb_get_kwargs(options, fiber_initialize_keywords, 0, 2, arguments);
+
+ if (arguments[0] != Qundef) {
+ blocking = arguments[0];
+ }
+
+ if (arguments[1] != Qundef) {
+ pool = arguments[1];
+ }
+ }
+
+ return fiber_initialize(self, rb_block_proc(), rb_fiber_pool_default(pool), RTEST(blocking));
+}
+
+/*
+ * call-seq:
+ * Fiber.new(blocking: false) { |*args| ... } -> fiber
+ *
+ * Creates new Fiber. Initially, fiber is not running, but can be resumed with
+ * #resume. Arguments to the first #resume call would be passed to the block:
+ *
+ * f = Fiber.new do |initial|
+ * current = initial
+ * loop do
+ * puts "current: #{current.inspect}"
+ * current = Fiber.yield
+ * end
+ * end
+ * f.resume(100) # prints: current: 100
+ * f.resume(1, 2, 3) # prints: current: [1, 2, 3]
+ * f.resume # prints: current: nil
+ * # ... and so on ...
+ *
+ * if <tt>blocking: false</tt> is passed to the <tt>Fiber.new</tt>, _and_ current thread
+ * has Fiber.scheduler defined, the Fiber becomes non-blocking (see "Non-blocking
+ * fibers" section in class docs).
+ */
+static VALUE
rb_fiber_initialize(int argc, VALUE* argv, VALUE self)
{
- return fiber_initialize(self, rb_block_proc(), &shared_fiber_pool);
+ return rb_fiber_initialize_kw(argc, argv, self, rb_keyword_given_p());
}
VALUE
rb_fiber_new(rb_block_call_func_t func, VALUE obj)
{
- return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), &shared_fiber_pool);
+ return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), rb_fiber_pool_default(Qnil), 1);
}
-NORETURN(static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt));
+static VALUE
+rb_f_fiber_kw(int argc, VALUE* argv, int kw_splat)
+{
+ rb_thread_t * th = GET_THREAD();
+ VALUE scheduler = th->scheduler;
+ VALUE fiber = Qnil;
+
+ if (scheduler != Qnil) {
+ fiber = rb_funcall_passing_block_kw(scheduler, rb_intern("fiber"), argc, argv, kw_splat);
+ } else {
+ rb_raise(rb_eRuntimeError, "No scheduler is available!");
+ }
+
+ return fiber;
+}
+
+/*
+ * call-seq:
+ * Fiber.schedule { |*args| ... } -> fiber
+ *
+ * The method is <em>expected</em> to immediately run the provided block of code in a
+ * separate non-blocking fiber.
+ *
+ * puts "Go to sleep!"
+ *
+ * Fiber.set_scheduler(MyScheduler.new)
+ *
+ * Fiber.schedule do
+ * puts "Going to sleep"
+ * sleep(1)
+ * puts "I slept well"
+ * end
+ *
+ * puts "Wakey-wakey, sleepyhead"
+ *
+ * Assuming MyScheduler is properly implemented, this program will produce:
+ *
+ * Go to sleep!
+ * Going to sleep
+ * Wakey-wakey, sleepyhead
+ * ...1 sec pause here...
+ * I slept well
+ *
+ * ...e.g. on the first blocking operation inside the Fiber (<tt>sleep(1)</tt>),
+ * the control is yielded at the outside code (main fiber), and <em>at the end
+ * of the execution</em>, the scheduler takes care of properly resuming all the
+ * blocked fibers.
+ *
+ * Note that the behavior described above is how the method is <em>expected</em>
+ * to behave, actual behavior is up to the current scheduler's implementation of
+ * Fiber::SchedulerInterface#fiber method. Ruby doesn't enforce this method to
+ * behave in any particular way.
+ *
+ * If the scheduler is not set, the method raises
+ * <tt>RuntimeError (No scheduler is available!)</tt>.
+ *
+ */
+static VALUE
+rb_f_fiber(int argc, VALUE *argv, VALUE obj)
+{
+ return rb_f_fiber_kw(argc, argv, rb_keyword_given_p());
+}
-#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? RB_PASS_EMPTY_KEYWORDS : rb_keyword_given_p())
+/*
+ * call-seq:
+ * Fiber.scheduler -> obj or nil
+ *
+ * Fiber scheduler, set in the current thread with Fiber.set_scheduler. If the scheduler
+ * is +nil+ (which is the default), non-blocking fibers behavior is the same as blocking.
+ * (see "Non-blocking fibers" section in class docs for details about the scheduler concept).
+ *
+ */
+static VALUE
+rb_fiber_scheduler(VALUE klass)
+{
+ return rb_scheduler_get();
+}
+
+/*
+ * call-seq:
+ * Fiber.set_scheduler(scheduler) -> scheduler
+ *
+ * Sets Fiber scheduler for the current thread. If the scheduler is set, non-blocking
+ * fibers (created by Fiber.new with <tt>blocking: false</tt>, or by Fiber.schedule)
+ * call that scheduler's hook methods on potentially blocking operations, and the current
+ * thread will call scheduler's +close+ method on finalization (allowing the scheduler to
+ * properly manage all non-finished fibers).
+ *
+ * +scheduler+ can be an object of any class corresponding to Fiber::SchedulerInterface. Its
+ * implementation is up to the user.
+ *
+ * See also the "Non-blocking fibers" section in class docs.
+ *
+ */
+static VALUE
+rb_fiber_set_scheduler(VALUE klass, VALUE scheduler)
+{
+ // if (rb_scheduler_get() != Qnil) {
+ // rb_raise(rb_eFiberError, "Scheduler is already defined!");
+ // }
+
+ return rb_scheduler_set(scheduler);
+}
+
+NORETURN(static void rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt));
void
rb_fiber_start(void)
@@ -1809,15 +2019,18 @@ rb_fiber_start(void)
enum ruby_tag_type state;
int need_interrupt = TRUE;
- VM_ASSERT(th->ec == ruby_current_execution_context_ptr);
+ VM_ASSERT(th->ec == GET_EC());
VM_ASSERT(FIBER_RESUMED_P(fiber));
+ if (fiber->blocking) {
+ th->blocking += 1;
+ }
+
EC_PUSH_TAG(th->ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
rb_context_t *cont = &VAR_FROM_MEMORY(fiber)->cont;
int argc;
const VALUE *argv, args = cont->value;
- int kw_splat = cont->kw_splat;
GetProcPtr(fiber->first_proc, proc);
argv = (argc = cont->argc) > 1 ? RARRAY_CONST_PTR(args) : &args;
cont->value = Qnil;
@@ -1826,8 +2039,7 @@ rb_fiber_start(void)
th->ec->root_svar = Qfalse;
EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_FIBER_SWITCH, th->self, 0, 0, 0, Qnil);
- rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- cont->value = rb_vm_invoke_proc(th->ec, proc, argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE);
+ cont->value = rb_vm_invoke_proc(th->ec, proc, argc, argv, cont->kw_splat, VM_BLOCK_HANDLER_NONE);
}
EC_POP_TAG();
@@ -1886,8 +2098,12 @@ rb_threadptr_root_fiber_setup(rb_thread_t *th)
fiber->cont.type = FIBER_CONTEXT;
fiber->cont.saved_ec.fiber_ptr = fiber;
fiber->cont.saved_ec.thread_ptr = th;
+ fiber->blocking = 1;
fiber_status_set(fiber, FIBER_RESUMED); /* skip CREATED */
th->ec = &fiber->cont.saved_ec;
+ // This skips mjit_cont_new for the initial thread because mjit_enabled is always false
+ // at this point. mjit_init calls rb_fiber_init_mjit_cont again for this root_fiber.
+ rb_fiber_init_mjit_cont(fiber);
}
void
@@ -1897,13 +2113,15 @@ rb_threadptr_root_fiber_release(rb_thread_t *th)
/* ignore. A root fiber object will free th->ec */
}
else {
+ rb_execution_context_t *ec = GET_EC();
+
VM_ASSERT(th->ec->fiber_ptr->cont.type == FIBER_CONTEXT);
VM_ASSERT(th->ec->fiber_ptr->cont.self == 0);
- fiber_free(th->ec->fiber_ptr);
- if (th->ec == ruby_current_execution_context_ptr) {
- ruby_current_execution_context_ptr = NULL;
+ if (th->ec == ec) {
+ rb_ractor_set_current_ec(th->ractor, NULL);
}
+ fiber_free(th->ec->fiber_ptr);
th->ec = NULL;
}
}
@@ -1930,25 +2148,33 @@ fiber_current(void)
}
static inline rb_fiber_t*
-return_fiber(void)
+return_fiber(bool terminate)
{
rb_fiber_t *fiber = fiber_current();
rb_fiber_t *prev = fiber->prev;
- if (!prev) {
+ if (prev) {
+ fiber->prev = NULL;
+ prev->resuming_fiber = Qnil;
+ return prev;
+ }
+ else {
+ if (!terminate) {
+ rb_raise(rb_eFiberError, "attempt to yield on a not resumed fiber");
+ }
+
rb_thread_t *th = GET_THREAD();
rb_fiber_t *root_fiber = th->root_fiber;
VM_ASSERT(root_fiber != NULL);
- if (root_fiber == fiber) {
- rb_raise(rb_eFiberError, "can't yield from root fiber");
+ // search resuming fiber
+ for (fiber = root_fiber;
+ RTEST(fiber->resuming_fiber);
+ fiber = fiber_ptr(fiber->resuming_fiber)) {
}
- return root_fiber;
- }
- else {
- fiber->prev = NULL;
- return prev;
+
+ return fiber;
}
}
@@ -1993,7 +2219,7 @@ fiber_store(rb_fiber_t *next_fiber, rb_thread_t *th)
}
static inline VALUE
-fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume, int kw_splat)
+fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat, VALUE resuming_fiber, bool yielding)
{
VALUE value;
rb_context_t *cont = &fiber->cont;
@@ -2038,11 +2264,25 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume, int
}
}
- if (is_resume) {
+ VM_ASSERT(FIBER_RUNNABLE_P(fiber));
+
+ rb_fiber_t *current_fiber = fiber_current();
+
+ VM_ASSERT(!RTEST(current_fiber->resuming_fiber));
+ if (RTEST(resuming_fiber)) {
+ current_fiber->resuming_fiber = resuming_fiber;
fiber->prev = fiber_current();
+ fiber->yielding = 0;
}
- VM_ASSERT(FIBER_RUNNABLE_P(fiber));
+ VM_ASSERT(!current_fiber->yielding);
+ if (yielding) {
+ current_fiber->yielding = 1;
+ }
+
+ if (current_fiber->blocking) {
+ th->blocking -= 1;
+ }
cont->argc = argc;
cont->kw_splat = kw_splat;
@@ -2050,10 +2290,14 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume, int
value = fiber_store(fiber, th);
- if (is_resume && FIBER_TERMINATED_P(fiber)) {
+ if (RTEST(resuming_fiber) && FIBER_TERMINATED_P(fiber)) {
fiber_stack_release(fiber);
}
+ if (fiber_current()->blocking) {
+ th->blocking += 1;
+ }
+
RUBY_VM_CHECK_INTS(th->ec);
EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_FIBER_SWITCH, th->self, 0, 0, 0, Qnil);
@@ -2064,7 +2308,57 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int is_resume, int
VALUE
rb_fiber_transfer(VALUE fiber_value, int argc, const VALUE *argv)
{
- return fiber_switch(fiber_ptr(fiber_value), argc, argv, 0, RB_NO_KEYWORDS);
+ return fiber_switch(fiber_ptr(fiber_value), argc, argv, RB_NO_KEYWORDS, Qfalse, false);
+}
+
+/*
+ * call-seq:
+ * fiber.blocking? -> true or false
+ *
+ * Returns +true+ if +fiber+ is blocking and +false+ otherwise.
+ * Fiber is non-blocking if it was created via passing <tt>blocking: false</tt>
+ * to Fiber.new, or via Fiber.schedule.
+ *
+ * Note, that even if the method returns +false+, Fiber behaves differently
+ * only if Fiber.scheduler is set in the current thread.
+ *
+ * See the "Non-blocking fibers" section in class docs for details.
+ *
+ */
+VALUE
+rb_fiber_blocking_p(VALUE fiber)
+{
+ return (fiber_ptr(fiber)->blocking == 0) ? Qfalse : Qtrue;
+}
+
+/*
+ * call-seq:
+ * Fiber.blocking? -> false or number
+ *
+ * Returns +false+ if the current fiber is non-blocking.
+ * Fiber is non-blocking if it was created via passing <tt>blocking: false</tt>
+ * to Fiber.new, or via Fiber.schedule.
+ *
+ * If the current Fiber is blocking, the method, unlike usual
+ * predicate methods, returns a *number* of blocking fibers currently
+ * running (TBD: always 1?).
+ *
+ * Note, that even if the method returns +false+, Fiber behaves differently
+ * only if Fiber.scheduler is set in the current thread.
+ *
+ * See the "Non-blocking fibers" section in class docs for details.
+ *
+ */
+static VALUE
+rb_f_fiber_blocking_p(VALUE klass)
+{
+ rb_thread_t *thread = GET_THREAD();
+ unsigned blocking = thread->blocking;
+
+ if (blocking == 0)
+ return Qfalse;
+
+ return INT2NUM(blocking);
}
void
@@ -2087,9 +2381,9 @@ rb_fiber_terminate(rb_fiber_t *fiber, int need_interrupt)
fiber->cont.machine.stack = NULL;
fiber->cont.machine.stack_size = 0;
- next_fiber = return_fiber();
+ next_fiber = return_fiber(true);
if (need_interrupt) RUBY_VM_SET_INTERRUPT(&next_fiber->cont.saved_ec);
- fiber_switch(next_fiber, 1, &value, 0, RB_NO_KEYWORDS);
+ fiber_switch(next_fiber, 1, &value, RB_NO_KEYWORDS, Qfalse, false);
ruby_stop(0);
}
@@ -2097,20 +2391,29 @@ VALUE
rb_fiber_resume_kw(VALUE fiber_value, int argc, const VALUE *argv, int kw_splat)
{
rb_fiber_t *fiber = fiber_ptr(fiber_value);
+ rb_fiber_t *current_fiber = fiber_current();
if (argc == -1 && FIBER_CREATED_P(fiber)) {
rb_raise(rb_eFiberError, "cannot raise exception on unborn fiber");
}
-
- if (fiber->prev != 0 || fiber_is_root_p(fiber)) {
- rb_raise(rb_eFiberError, "double resume");
+ else if (FIBER_TERMINATED_P(fiber)) {
+ rb_raise(rb_eFiberError, "attempt to resume a terminated fiber");
}
-
- if (fiber->transferred != 0) {
- rb_raise(rb_eFiberError, "cannot resume transferred Fiber");
+ else if (fiber == current_fiber) {
+ rb_raise(rb_eFiberError, "attempt to resume the current fiber");
+ }
+ else if (fiber->prev != NULL) {
+ rb_raise(rb_eFiberError, "attempt to resume a resumed fiber (double resume)");
+ }
+ else if (RTEST(fiber->resuming_fiber)) {
+ rb_raise(rb_eFiberError, "attempt to resume a resuming fiber");
+ }
+ else if (fiber->prev == NULL &&
+ (!fiber->yielding && fiber->status != FIBER_CREATED)) {
+ rb_raise(rb_eFiberError, "attempt to resume a transferring fiber");
}
- return fiber_switch(fiber, argc, argv, 1, kw_splat);
+ return fiber_switch(fiber, argc, argv, kw_splat, fiber_value, false);
}
VALUE
@@ -2122,13 +2425,13 @@ rb_fiber_resume(VALUE fiber_value, int argc, const VALUE *argv)
VALUE
rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat)
{
- return fiber_switch(return_fiber(), argc, argv, 0, kw_splat);
+ return fiber_switch(return_fiber(false), argc, argv, kw_splat, Qfalse, true);
}
VALUE
rb_fiber_yield(int argc, const VALUE *argv)
{
- return fiber_switch(return_fiber(), argc, argv, 0, RB_NO_KEYWORDS);
+ return fiber_switch(return_fiber(false), argc, argv, RB_NO_KEYWORDS, Qfalse, true);
}
void
@@ -2172,9 +2475,11 @@ rb_fiber_alive_p(VALUE fiber_value)
static VALUE
rb_fiber_m_resume(int argc, VALUE *argv, VALUE fiber)
{
- return rb_fiber_resume_kw(fiber, argc, argv, PASS_KW_SPLAT);
+ return rb_fiber_resume_kw(fiber, argc, argv, rb_keyword_given_p());
}
+static VALUE rb_fiber_transfer_kw(VALUE fiber_value, int argc, VALUE *argv, int kw_splat);
+
/*
* call-seq:
* fiber.raise -> obj
@@ -2182,8 +2487,10 @@ rb_fiber_m_resume(int argc, VALUE *argv, VALUE fiber)
* fiber.raise(exception [, string [, array]]) -> obj
*
* Raises an exception in the fiber at the point at which the last
- * Fiber.yield was called, or at the start if neither +resume+
- * nor +raise+ were called before.
+ * +Fiber.yield+ was called. If the fiber has not been started or has
+ * already run to completion, raises +FiberError+. If the fiber is
+ * yielding, it is resumed. If it is transferring, it is transferred into.
+ * But if it is resuming, raises +FiberError+.
*
* With no arguments, raises a +RuntimeError+. With a single +String+
* argument, raises a +RuntimeError+ with the string as a message. Otherwise,
@@ -2195,10 +2502,96 @@ rb_fiber_m_resume(int argc, VALUE *argv, VALUE fiber)
* blocks.
*/
static VALUE
-rb_fiber_raise(int argc, VALUE *argv, VALUE fiber)
+rb_fiber_raise(int argc, VALUE *argv, VALUE fiber_value)
{
+ rb_fiber_t *fiber = fiber_ptr(fiber_value);
VALUE exc = rb_make_exception(argc, argv);
- return rb_fiber_resume_kw(fiber, -1, &exc, RB_NO_KEYWORDS);
+ if (RTEST(fiber->resuming_fiber)) {
+ rb_raise(rb_eFiberError, "attempt to raise a resuming fiber");
+ }
+ else if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) {
+ return rb_fiber_transfer_kw(fiber_value, -1, &exc, RB_NO_KEYWORDS);
+ }
+ else {
+ return rb_fiber_resume_kw(fiber_value, -1, &exc, RB_NO_KEYWORDS);
+ }
+}
+
+/*
+ * call-seq:
+ * fiber.backtrace -> array
+ * fiber.backtrace(start) -> array
+ * fiber.backtrace(start, count) -> array
+ * fiber.backtrace(start..end) -> array
+ *
+ * Returns the current execution stack of the fiber. +start+, +count+ and +end+ allow
+ * to select only parts of the backtrace.
+ *
+ * def level3
+ * Fiber.yield
+ * end
+ *
+ * def level2
+ * level3
+ * end
+ *
+ * def level1
+ * level2
+ * end
+ *
+ * f = Fiber.new { level1 }
+ *
+ * # It is empty before the fiber started
+ * f.backtrace
+ * #=> []
+ *
+ * f.resume
+ *
+ * f.backtrace
+ * #=> ["test.rb:2:in `yield'", "test.rb:2:in `level3'", "test.rb:6:in `level2'", "test.rb:10:in `level1'", "test.rb:13:in `block in <main>'"]
+ * p f.backtrace(1) # start from the item 1
+ * #=> ["test.rb:2:in `level3'", "test.rb:6:in `level2'", "test.rb:10:in `level1'", "test.rb:13:in `block in <main>'"]
+ * p f.backtrace(2, 2) # start from item 2, take 2
+ * #=> ["test.rb:6:in `level2'", "test.rb:10:in `level1'"]
+ * p f.backtrace(1..3) # take items from 1 to 3
+ * #=> ["test.rb:2:in `level3'", "test.rb:6:in `level2'", "test.rb:10:in `level1'"]
+ *
+ * f.resume
+ *
+ * # It is nil after the fiber is finished
+ * f.backtrace
+ * #=> nil
+ *
+ */
+static VALUE
+rb_fiber_backtrace(int argc, VALUE *argv, VALUE fiber)
+{
+ return rb_vm_backtrace(argc, argv, &fiber_ptr(fiber)->cont.saved_ec);
+}
+
+/*
+ * call-seq:
+ * fiber.backtrace_locations -> array
+ * fiber.backtrace_locations(start) -> array
+ * fiber.backtrace_locations(start, count) -> array
+ * fiber.backtrace_locations(start..end) -> array
+ *
+ * Like #backtrace, but returns each line of the execution stack as a
+ * Thread::Backtrace::Location. Accepts the same arguments as #backtrace.
+ *
+ * f = Fiber.new { Fiber.yield }
+ * f.resume
+ * loc = f.backtrace_locations.first
+ * loc.label #=> "yield"
+ * loc.path #=> "test.rb"
+ * loc.lineno #=> 1
+ *
+ *
+ */
+static VALUE
+rb_fiber_backtrace_locations(int argc, VALUE *argv, VALUE fiber)
+{
+ return rb_vm_backtrace_locations(argc, argv, &fiber_ptr(fiber)->cont.saved_ec);
}
/*
@@ -2215,50 +2608,94 @@ rb_fiber_raise(int argc, VALUE *argv, VALUE fiber)
* a resume call. Arguments passed to transfer are treated like those
* passed to resume.
*
- * You cannot call +resume+ on a fiber that has been transferred to.
- * If you call +transfer+ on a fiber, and later call +resume+ on the
- * the fiber, a +FiberError+ will be raised. Once you call +transfer+ on
- * a fiber, the only way to resume processing the fiber is to
- * call +transfer+ on it again.
+ * The two style of control passing to and from fiber (one is #resume and
+ * Fiber::yield, another is #transfer to and from fiber) can't be freely
+ * mixed.
+ *
+ * * If the Fiber's lifecycle had started with transfer, it will never
+ * be able to yield or be resumed control passing, only
+ * finish or transfer back. (It still can resume other fibers that
+ * are allowed to be resumed.)
+ * * If the Fiber's lifecycle had started with resume, it can yield
+ * or transfer to another Fiber, but can receive control back only
+ * the way compatible with the way it was given away: if it had
+ * transferred, it only can be transferred back, and if it had
+ * yielded, it only can be resumed back. After that, it again can
+ * transfer or yield.
+ *
+ * If those rules are broken FiberError is raised.
+ *
+ * For an individual Fiber design, yield/resume is more easy to use
+ * style (the Fiber just gives away control, it doesn't need to think
+ * about who the control is given to), while transfer is more flexible
+ * for complex cases, allowing to build arbitrary graphs of Fibers
+ * dependent on each other.
+ *
*
* Example:
*
- * fiber1 = Fiber.new do
- * puts "In Fiber 1"
- * Fiber.yield
- * puts "In Fiber 1 again"
- * end
+ * require 'fiber'
*
- * fiber2 = Fiber.new do
- * puts "In Fiber 2"
- * fiber1.transfer
- * puts "Never see this message"
- * end
+ * manager = nil # For local var to be visible inside worker block
*
- * fiber3 = Fiber.new do
- * puts "In Fiber 3"
- * end
+ * # This fiber would be started with transfer
+ * # It can't yield, and can't be resumed
+ * worker = Fiber.new { |work|
+ * puts "Worker: starts"
+ * puts "Worker: Performed #{work.inspect}, transferring back"
+ * # Fiber.yield # this would raise FiberError: attempt to yield on a not resumed fiber
+ * # manager.resume # this would raise FiberError: attempt to resume a resumed fiber (double resume)
+ * manager.transfer(work.capitalize)
+ * }
*
- * fiber2.resume
- * fiber3.resume
- * fiber1.resume rescue (p $!)
- * fiber1.transfer
+ * # This fiber would be started with resume
+ * # It can yield or transfer, and can be transferred
+ * # back or resumed
+ * manager = Fiber.new {
+ * puts "Manager: starts"
+ * puts "Manager: transferring 'something' to worker"
+ * result = worker.transfer('something')
+ * puts "Manager: worker returned #{result.inspect}"
+ * # worker.resume # this would raise FiberError: attempt to resume a transferring fiber
+ * Fiber.yield # this is OK, the fiber transferred from and to, now it can yield
+ * puts "Manager: finished"
+ * }
+ *
+ * puts "Starting the manager"
+ * manager.resume
+ * puts "Resuming the manager"
+ * # manager.transfer # this would raise FiberError: attempt to transfer to a yielding fiber
+ * manager.resume
*
* <em>produces</em>
*
- * In Fiber 2
- * In Fiber 1
- * In Fiber 3
- * #<FiberError: cannot resume transferred Fiber>
- * In Fiber 1 again
+ * Starting the manager
+ * Manager: starts
+ * Manager: transferring 'something' to worker
+ * Worker: starts
+ * Worker: Performed "something", transferring back
+ * Manager: worker returned "Something"
+ * Resuming the manager
+ * Manager: finished
*
*/
static VALUE
rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value)
{
+ return rb_fiber_transfer_kw(fiber_value, argc, argv, rb_keyword_given_p());
+}
+
+static VALUE
+rb_fiber_transfer_kw(VALUE fiber_value, int argc, VALUE *argv, int kw_splat)
+{
rb_fiber_t *fiber = fiber_ptr(fiber_value);
- fiber->transferred = 1;
- return fiber_switch(fiber, argc, argv, 0, PASS_KW_SPLAT);
+ if (RTEST(fiber->resuming_fiber)) {
+ rb_raise(rb_eFiberError, "attempt to transfer to a resuming fiber");
+ }
+ if (fiber->yielding) {
+ rb_raise(rb_eFiberError, "attempt to transfer to a yielding fiber");
+ }
+ return fiber_switch(fiber, argc, argv, kw_splat, Qfalse, false);
}
/*
@@ -2274,7 +2711,7 @@ rb_fiber_m_transfer(int argc, VALUE *argv, VALUE fiber_value)
static VALUE
rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass)
{
- return rb_fiber_yield_kw(argc, argv, PASS_KW_SPLAT);
+ return rb_fiber_yield_kw(argc, argv, rb_keyword_given_p());
}
/*
@@ -2306,8 +2743,8 @@ fiber_to_s(VALUE fiber_value)
const rb_proc_t *proc;
char status_info[0x20];
- if (fiber->transferred) {
- snprintf(status_info, 0x20, " (%s, transferred)", fiber_status_name(fiber->status));
+ if (RTEST(fiber->resuming_fiber)) {
+ snprintf(status_info, 0x20, " (%s by resuming)", fiber_status_name(fiber->status));
}
else {
snprintf(status_info, 0x20, " (%s)", fiber_status_name(fiber->status));
@@ -2418,6 +2855,191 @@ rb_fiber_pool_initialize(int argc, VALUE* argv, VALUE self)
* fiber.resume #=> FiberError: dead fiber called
*/
+/*
+ * Document-class: Fiber::SchedulerInterface
+ *
+ * This is not an existing class, but documentation of the interface that Scheduler
+ * object should comply in order to be used as Fiber.scheduler and handle non-blocking
+ * fibers. See also the "Non-blocking fibers" section in Fiber class docs for explanations
+ * of some concepts.
+ *
+ * Scheduler's behavior and usage are expected to be as follows:
+ *
+ * * When the execution in the non-blocking Fiber reaches some blocking operation (like
+ * sleep, wait for a process, or a non-ready I/O), it calls some of the scheduler's
+ * hook methods, listed below.
+ * * Scheduler somehow registers what the current fiber is waited for, and yields control
+ * to other fibers with Fiber.yield (so the fiber would be suspended while expecting its
+ * wait to end, and other fibers in the same thread can perform)
+ * * At the end of the current thread execution, the scheduler's method #close is called
+ * * The scheduler runs into a wait loop, checking all the blocked fibers (which it has
+ * registered on hook calls) and resuming them when the awaited resource is ready (I/O
+ * ready, sleep time passed).
+ *
+ * A typical implementation would probably rely for this closing loop on a gem like
+ * EventMachine[https://github.com/eventmachine/eventmachine] or
+ * Async[https://github.com/socketry/async].
+ *
+ * This way concurrent execution will be achieved in a way that is transparent for every
+ * individual Fiber's code.
+ *
+ * Hook methods are:
+ *
+ * * #io_wait
+ * * #process_wait
+ * * #kernel_sleep
+ * * #block and #unblock
+ * * (the list is expanded as Ruby developers make more methods having non-blocking calls)
+ *
+ * When not specified otherwise, the hook implementations are mandatory: if they are not
+ * implemented, the methods trying to call hook will fail. To provide backward compatibility,
+ * in the future hooks will be optional (if they are not implemented, due to the scheduler
+ * being created for the older Ruby version, the code which needs this hook will not fail,
+ * and will just behave in a blocking fashion).
+ *
+ * It is also strongly suggested that the scheduler implement the #fiber method, which is
+ * delegated to by Fiber.schedule.
+ *
+ * Sample _toy_ implementation of the scheduler can be found in Ruby's code, in
+ * <tt>test/fiber/scheduler.rb</tt>
+ *
+ */
+
+#if 0 /* for RDoc */
+/*
+ *
+ * Document-method: Fiber::SchedulerInterface#close
+ *
+ * Called when the current thread exits. The scheduler is expected to implement this
+ * method in order to allow all waiting fibers to finalize their execution.
+ *
+ * The suggested pattern is to implement the main event loop in the #close method.
+ *
+ */
+static VALUE
+rb_fiber_scheduler_interface_close(VALUE self)
+{
+}
+
+/*
+ * Document-method: SchedulerInterface#process_wait
+ * call-seq: process_wait(pid, flags)
+ *
+ * Invoked by Process::Status.wait in order to wait for a specified process.
+ * See that method description for arguments description.
+ *
+ * Suggested minimal implementation:
+ *
+ * Thread.new do
+ * Process::Status.wait(pid, flags)
+ * end.value
+ *
+ * This hook is optional: if it is not present in the current scheduler,
+ * Process::Status.wait will behave as a blocking method.
+ *
+ * Expected to returns a Process::Status instance.
+ */
+static VALUE
+rb_fiber_scheduler_interface_process_wait(VALUE self)
+{
+}
+
+/*
+ * Document-method: SchedulerInterface#io_wait
+ * call-seq: io_wait(io, events, timeout)
+ *
+ * Invoked by IO#wait, IO#wait_readable, IO#wait_writable to ask whether the
+ * specified descriptor is ready for specified events within
+ * the specified +timeout+.
+ *
+ * +events+ is a bit mask of <tt>IO::READABLE</tt>, <tt>IO::WRITABLE</tt>, and
+ * <tt>IO::PRIORITY</tt>.
+ *
+ * Suggested implementation should register which Fiber is waiting for which
+ * resources and immediately calling Fiber.yield to pass control to other
+ * fibers. Then, in the #close method, the scheduler might dispatch all the
+ * I/O resources to fibers waiting for it.
+ *
+ * Expected to return the subset of events that are ready immediately.
+ *
+ */
+static VALUE
+rb_fiber_scheduler_interface_io_wait(VALUE self)
+{
+}
+
+/*
+ * Document-method: SchedulerInterface#kernel_sleep
+ * call-seq: kernel_sleep(duration = nil)
+ *
+ * Invoked by Kernel#sleep and Mutex#sleep and is expected to provide
+ * an implementation of sleeping in a non-blocking way. Implementation might
+ * register the current fiber in some list of "what fiber waits till what
+ * moment", call Fiber.yield to pass control, and then in #close resume
+ * the fibers whose wait period have ended.
+ *
+ */
+static VALUE
+rb_fiber_scheduler_interface_kernel_sleep(VALUE self)
+{
+}
+
+/*
+ * Document-method: SchedulerInterface#block
+ * call-seq: block(blocker, timeout = nil)
+ *
+ * Invoked by methods like Thread.join, and by Mutex, to signify that current
+ * Fiber is blocked till further notice (e.g. #unblock) or till +timeout+ will
+ * pass.
+ *
+ * +blocker+ is what we are waiting on, informational only (for debugging and
+ * logging). There are no guarantees about its value.
+ *
+ * Expected to return boolean, specifying whether the blocking operation was
+ * successful or not.
+ */
+static VALUE
+rb_fiber_scheduler_interface_block(VALUE self)
+{
+}
+
+/*
+ * Document-method: SchedulerInterface#unblock
+ * call-seq: unblock(blocker, fiber)
+ *
+ * Invoked to wake up Fiber previously blocked with #block (for example, Mutex#lock
+ * calls #block and Mutex#unlock calls #unblock). The scheduler should use
+ * the +fiber+ parameter to understand which fiber is unblocked.
+ *
+ * +blocker+ is what was awaited for, but it is informational only (for debugging
+ * and logging), and it is not guaranteed to be the same value as the +blocker+ for
+ * #block.
+ *
+ */
+static VALUE
+rb_fiber_scheduler_interface_unblock(VALUE self)
+{
+}
+
+/*
+ * Document-method: SchedulerInterface#fiber
+ * call-seq: fiber(&block)
+ *
+ * Implementation of the Fiber.schedule. The method is <em>expected</em> to immediately
+ * run passed block of code in a separate non-blocking fiber, and to return that Fiber.
+ *
+ * Minimal suggested implementation is:
+ *
+ * def fiber(&block)
+ * Fiber.new(blocking: false, &block).tap(&:resume)
+ * end
+ */
+static VALUE
+rb_fiber_scheduler_interface_fiber(VALUE self)
+{
+}
+#endif
+
void
Init_Cont(void)
{
@@ -2437,6 +3059,9 @@ Init_Cont(void)
fiber_pool_initialize(&shared_fiber_pool, stack_size, FIBER_POOL_INITIAL_SIZE, vm_stack_size);
+ fiber_initialize_keywords[0] = rb_intern_const("blocking");
+ fiber_initialize_keywords[1] = rb_intern_const("pool");
+
char * fiber_shared_fiber_pool_free_stacks = getenv("RUBY_SHARED_FIBER_POOL_FREE_STACKS");
if (fiber_shared_fiber_pool_free_stacks) {
shared_fiber_pool.free_stacks = atoi(fiber_shared_fiber_pool_free_stacks);
@@ -2447,11 +3072,32 @@ Init_Cont(void)
rb_eFiberError = rb_define_class("FiberError", rb_eStandardError);
rb_define_singleton_method(rb_cFiber, "yield", rb_fiber_s_yield, -1);
rb_define_method(rb_cFiber, "initialize", rb_fiber_initialize, -1);
+ rb_define_method(rb_cFiber, "blocking?", rb_fiber_blocking_p, 0);
rb_define_method(rb_cFiber, "resume", rb_fiber_m_resume, -1);
rb_define_method(rb_cFiber, "raise", rb_fiber_raise, -1);
+ rb_define_method(rb_cFiber, "backtrace", rb_fiber_backtrace, -1);
+ rb_define_method(rb_cFiber, "backtrace_locations", rb_fiber_backtrace_locations, -1);
rb_define_method(rb_cFiber, "to_s", fiber_to_s, 0);
rb_define_alias(rb_cFiber, "inspect", "to_s");
+ rb_define_singleton_method(rb_cFiber, "blocking?", rb_f_fiber_blocking_p, 0);
+ rb_define_singleton_method(rb_cFiber, "scheduler", rb_fiber_scheduler, 0);
+ rb_define_singleton_method(rb_cFiber, "set_scheduler", rb_fiber_set_scheduler, 1);
+
+ rb_define_singleton_method(rb_cFiber, "schedule", rb_f_fiber, -1);
+ //rb_define_global_function("Fiber", rb_f_fiber, -1);
+
+#if 0 /* for RDoc */
+ rb_cFiberScheduler = rb_define_class_under(rb_cFiber, "SchedulerInterface", rb_cObject);
+ rb_define_method(rb_cFiberScheduler, "close", rb_fiber_scheduler_interface_close, 0);
+ rb_define_method(rb_cFiberScheduler, "process_wait", rb_fiber_scheduler_interface_process_wait, 0);
+ rb_define_method(rb_cFiberScheduler, "io_wait", rb_fiber_scheduler_interface_io_wait, 0);
+ rb_define_method(rb_cFiberScheduler, "kernel_sleep", rb_fiber_scheduler_interface_kernel_sleep, 0);
+ rb_define_method(rb_cFiberScheduler, "block", rb_fiber_scheduler_interface_block, 0);
+ rb_define_method(rb_cFiberScheduler, "unblock", rb_fiber_scheduler_interface_unblock, 0);
+ rb_define_method(rb_cFiberScheduler, "fiber", rb_fiber_scheduler_interface_fiber, 0);
+#endif
+
#ifdef RB_EXPERIMENTAL_FIBER_POOL
rb_cFiberPool = rb_define_class("Pool", rb_cFiber);
rb_define_alloc_func(rb_cFiberPool, fiber_pool_alloc);
@@ -2475,6 +3121,9 @@ ruby_Init_Continuation_body(void)
void
ruby_Init_Fiber_as_Coroutine(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
rb_define_method(rb_cFiber, "transfer", rb_fiber_m_transfer, -1);
rb_define_method(rb_cFiber, "alive?", rb_fiber_alive_p, 0);
rb_define_singleton_method(rb_cFiber, "current", rb_fiber_s_current, 0);
diff --git a/coroutine/Stack.h b/coroutine/Stack.h
new file mode 100644
index 0000000000..f0fc703622
--- /dev/null
+++ b/coroutine/Stack.h
@@ -0,0 +1,16 @@
+/*
+ * This file is part of the "Coroutine" project and released under the MIT License.
+ *
+ * Created by Samuel Williams on 10/11/2020.
+ * Copyright, 2020, by Samuel Williams.
+*/
+
+#include COROUTINE_H
+
+#ifdef COROUTINE_PRIVATE_STACK
+#define COROUTINE_STACK_LOCAL(type, name) type *name = ruby_xmalloc(sizeof(type))
+#define COROUTINE_STACK_FREE(name) ruby_xfree(name)
+#else
+#define COROUTINE_STACK_LOCAL(type, name) type name##_local; type * name = &name##_local
+#define COROUTINE_STACK_FREE(name)
+#endif
diff --git a/coroutine/amd64/Context.h b/coroutine/amd64/Context.h
index 352ed5555a..581525b67e 100644
--- a/coroutine/amd64/Context.h
+++ b/coroutine/amd64/Context.h
@@ -8,6 +8,8 @@
#pragma once
#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
#include <string.h>
#define COROUTINE __attribute__((noreturn)) void
diff --git a/coroutine/arm32/Context.S b/coroutine/arm32/Context.S
index c5338f0b67..1850c4c408 100644
--- a/coroutine/arm32/Context.S
+++ b/coroutine/arm32/Context.S
@@ -27,3 +27,7 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
# Restore callee state (8 registers program counter)
pop {r4-r11,pc}
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits
+#endif
diff --git a/coroutine/arm32/Context.h b/coroutine/arm32/Context.h
index 6b6807904f..e69f4b2eeb 100644
--- a/coroutine/arm32/Context.h
+++ b/coroutine/arm32/Context.h
@@ -8,6 +8,8 @@
#pragma once
#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
#include <string.h>
#define COROUTINE __attribute__((noreturn)) void
diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h
index 3bc19b1e4b..34be995a4f 100644
--- a/coroutine/arm64/Context.h
+++ b/coroutine/arm64/Context.h
@@ -8,6 +8,8 @@
#pragma once
#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
#include <string.h>
#define COROUTINE __attribute__((noreturn)) void
diff --git a/coroutine/copy/Context.c b/coroutine/copy/Context.c
index f6cf462282..aa8bb2ff05 100644
--- a/coroutine/copy/Context.c
+++ b/coroutine/copy/Context.c
@@ -17,7 +17,7 @@
#if defined(__sparc)
__attribute__((noinline))
// https://marc.info/?l=linux-sparc&m=131914569320660&w=2
-static void coroutine_flush_register_windows() {
+static void coroutine_flush_register_windows(void) {
__asm__
#ifdef __GNUC__
__volatile__
@@ -34,11 +34,11 @@ static void coroutine_flush_register_windows() {
;
}
#else
-static void coroutine_flush_register_windows() {}
+static void coroutine_flush_register_windows(void) {}
#endif
__attribute__((noinline))
-void *coroutine_stack_pointer() {
+void *coroutine_stack_pointer(void) {
return (void*)(
(char*)__builtin_frame_address(0)
);
diff --git a/coroutine/copy/Context.h b/coroutine/copy/Context.h
index 8514a61dff..6038f00cf6 100644
--- a/coroutine/copy/Context.h
+++ b/coroutine/copy/Context.h
@@ -12,7 +12,11 @@
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>
+
+/* OpenBSD supports alloca, but does not include alloca.h */
+#ifndef __OpenBSD__
#include <alloca.h>
+#endif
#define COROUTINE __attribute__((noreturn)) void
diff --git a/coroutine/ppc64le/Context.h b/coroutine/ppc64le/Context.h
index adf21b4fd9..e36f9c3583 100644
--- a/coroutine/ppc64le/Context.h
+++ b/coroutine/ppc64le/Context.h
@@ -1,6 +1,8 @@
#pragma once
#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
#include <string.h>
#define COROUTINE __attribute__((noreturn)) void
diff --git a/coroutine/ucontext/Context.c b/coroutine/ucontext/Context.c
index 2dc3f478e8..9ba76ee628 100644
--- a/coroutine/ucontext/Context.c
+++ b/coroutine/ucontext/Context.c
@@ -15,7 +15,7 @@
void coroutine_trampoline(void * _start, void * _context)
{
- coroutine_start start = _start;
+ coroutine_start start = (coroutine_start)_start;
struct coroutine_context * context = _context;
start(context->from, context);
diff --git a/coroutine/ucontext/Context.h b/coroutine/ucontext/Context.h
index 6cf16c8604..2b2a593793 100644
--- a/coroutine/ucontext/Context.h
+++ b/coroutine/ucontext/Context.h
@@ -2,7 +2,7 @@
* This file is part of the "Coroutine" project and released under the MIT License.
*
* Created by Samuel Williams on 24/6/2019.
- * Copyright, 2019, by Samuel Williams. All rights reserved.
+ * Copyright, 2019, by Samuel Williams.
*/
#pragma once
diff --git a/coroutine/win32/Context.h b/coroutine/win32/Context.h
index 299515ed92..e20342a98d 100644
--- a/coroutine/win32/Context.h
+++ b/coroutine/win32/Context.h
@@ -2,12 +2,14 @@
* This file is part of the "Coroutine" project and released under the MIT License.
*
* Created by Samuel Williams on 10/5/2018.
- * Copyright, 2018, by Samuel Williams. All rights reserved.
+ * Copyright, 2018, by Samuel Williams.
*/
#pragma once
#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
#include <string.h>
#define COROUTINE __declspec(noreturn) void __fastcall
diff --git a/coroutine/win64/Context.h b/coroutine/win64/Context.h
index 6bf2dc5b35..e28e6a6ff0 100644
--- a/coroutine/win64/Context.h
+++ b/coroutine/win64/Context.h
@@ -2,12 +2,14 @@
* This file is part of the "Coroutine" project and released under the MIT License.
*
* Created by Samuel Williams on 10/5/2018.
- * Copyright, 2018, by Samuel Williams. All rights reserved.
+ * Copyright, 2018, by Samuel Williams.
*/
#pragma once
#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
#include <string.h>
#define COROUTINE __declspec(noreturn) void
diff --git a/coroutine/x86/Context.h b/coroutine/x86/Context.h
index 6d3a56eaa6..dfdde24f5d 100644
--- a/coroutine/x86/Context.h
+++ b/coroutine/x86/Context.h
@@ -2,12 +2,14 @@
* This file is part of the "Coroutine" project and released under the MIT License.
*
* Created by Samuel Williams on 3/11/2018.
- * Copyright, 2018, by Samuel Williams. All rights reserved.
+ * Copyright, 2018, by Samuel Williams.
*/
#pragma once
#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
#include <string.h>
#define COROUTINE __attribute__((noreturn, fastcall)) void
diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in
index 192cf43b37..86098814a1 100644
--- a/cygwin/GNUmakefile.in
+++ b/cygwin/GNUmakefile.in
@@ -1,8 +1,13 @@
+gnumake = yes
+
include Makefile
ENABLE_SHARED=@ENABLE_SHARED@
DLLWRAP = @DLLWRAP@ --target=@target_os@ --driver-name="$(CC)"
-WINDRES = @WINDRES@ --preprocessor="$(CPP) -xc" -DRC_INVOKED
+windres-cpp := $(CPP) -xc
+windres-cpp := --preprocessor=$(firstword $(windres-cpp)) \
+ $(addprefix --preprocessor-arg=,$(wordlist 2,$(words $(windres-cpp)),$(windres-cpp)))
+WINDRES = @WINDRES@ $(windres-cpp) -DRC_INVOKED
STRIP = @STRIP@
ifeq (@target_os@,cygwin)
@@ -94,13 +99,5 @@ $(RUBYDEF): $(LIBRUBY_A) $(PREP) $(RBCONFIG)
clean-local::
@$(RM) $(RUBYDEF)
-
-ifeq (@target_os@,cygwin)
-cygwin-$(RUBY_INSTALL_NAME)$(MAJOR)$(MINOR)0.dll: $(LIBRUBY_A) $(RUBYDEF)
- $(ECHO) generating $@
- $(Q) @DLLWRAP@ -s --def=$(RUBYDEF) -o $@
-endif
-
-clean-local::
@$(RM) $(RUBY_EXP) $(RCFILES:.rc=.res.@OBJEXT@)
@$(RM) $(RCFILES)
diff --git a/debug.c b/debug.c
index a54be27152..75d4cc6569 100644
--- a/debug.c
+++ b/debug.c
@@ -9,15 +9,33 @@
**********************************************************************/
-#include "ruby/ruby.h"
+#include "ruby/internal/config.h"
+
+#include <stdio.h>
+
+#include "eval_intern.h"
+#include "id.h"
+#include "internal/signal.h"
+#include "internal/util.h"
#include "ruby/encoding.h"
#include "ruby/io.h"
+#include "ruby/ruby.h"
#include "ruby/util.h"
-#include "vm_debug.h"
-#include "eval_intern.h"
-#include "vm_core.h"
#include "symbol.h"
-#include "id.h"
+#include "vm_core.h"
+#include "vm_debug.h"
+#include "vm_callinfo.h"
+#include "ruby/thread_native.h"
+#include "ractor_core.h"
+
+/* This is the only place struct RIMemo is actually used */
+struct RIMemo {
+ VALUE flags;
+ VALUE v0;
+ VALUE v1;
+ VALUE v2;
+ VALUE v3;
+};
/* for gdb */
const union {
@@ -28,13 +46,18 @@ const union {
enum ruby_method_ids method_ids;
enum ruby_id_types id_types;
enum ruby_fl_type fl_types;
+ enum ruby_fl_ushift fl_ushift;
enum ruby_encoding_consts encoding_consts;
enum ruby_coderange_type enc_coderange_types;
enum ruby_econv_flag_type econv_flag_types;
+ rb_econv_result_t econv_result;
enum ruby_robject_flags robject_flags;
+ enum ruby_robject_consts robject_consts;
enum ruby_rmodule_flags rmodule_flags;
enum ruby_rstring_flags rstring_flags;
+ enum ruby_rstring_consts rstring_consts;
enum ruby_rarray_flags rarray_flags;
+ enum ruby_rarray_consts rarray_consts;
enum {
RUBY_FMODE_READABLE = FMODE_READABLE,
RUBY_FMODE_WRITABLE = FMODE_WRITABLE,
@@ -222,8 +245,267 @@ set_debug_option(const char *str, int len, void *arg)
}
}
+#ifdef USE_RUBY_DEBUG_LOG
+STATIC_ASSERT(USE_RUBY_DEBUG_LOG, USE_RUBY_DEBUG_LOG ? RUBY_DEVEL : 1);
+#endif
+
+#if RUBY_DEVEL
+static void setup_debug_log(void);
+#else
+#define setup_debug_log()
+#endif
+
void
ruby_set_debug_option(const char *str)
{
ruby_each_words(str, set_debug_option, 0);
+ setup_debug_log();
+}
+
+#if RUBY_DEVEL
+
+// RUBY_DEBUG_LOG features
+// See vm_debug.h comments for details.
+
+#define MAX_DEBUG_LOG 0x1000
+#define MAX_DEBUG_LOG_MESSAGE_LEN 0x0200
+#define MAX_DEBUG_LOG_FILTER 0x0010
+
+enum ruby_debug_log_mode ruby_debug_log_mode;
+
+static struct {
+ char *mem;
+ unsigned int cnt;
+ char filters[MAX_DEBUG_LOG_FILTER][MAX_DEBUG_LOG_FILTER];
+ unsigned int filters_num;
+ rb_nativethread_lock_t lock;
+ FILE *output;
+} debug_log;
+
+static char *
+RUBY_DEBUG_LOG_MEM_ENTRY(unsigned int index)
+{
+ return &debug_log.mem[MAX_DEBUG_LOG_MESSAGE_LEN * index];
+}
+
+static void
+setup_debug_log(void)
+{
+ // check RUBY_DEBUG_LOG
+ const char *log_config = getenv("RUBY_DEBUG_LOG");
+ if (log_config) {
+ fprintf(stderr, "RUBY_DEBUG_LOG=%s\n", log_config);
+
+ if (strcmp(log_config, "mem") == 0) {
+ debug_log.mem = (char *)malloc(MAX_DEBUG_LOG * MAX_DEBUG_LOG_MESSAGE_LEN);
+ if (debug_log.mem == NULL) {
+ fprintf(stderr, "setup_debug_log failed (can't allocate memory)\n");
+ exit(1);
+ }
+ ruby_debug_log_mode |= ruby_debug_log_memory;
+ }
+ else if (strcmp(log_config, "stderr") == 0) {
+ ruby_debug_log_mode |= ruby_debug_log_stderr;
+ }
+ else {
+ ruby_debug_log_mode |= ruby_debug_log_file;
+ if ((debug_log.output = fopen(log_config, "w")) == NULL) {
+ fprintf(stderr, "can not open %s for RUBY_DEBUG_LOG\n", log_config);
+ exit(1);
+ }
+ setvbuf(debug_log.output, NULL, _IONBF, 0);
+ }
+
+ rb_nativethread_lock_initialize(&debug_log.lock);
+ }
+
+ // check RUBY_DEBUG_LOG_FILTER
+ const char *filter_config = getenv("RUBY_DEBUG_LOG_FILTER");
+ if (filter_config && strlen(filter_config) > 0) {
+ unsigned int i;
+ for (i=0; i<MAX_DEBUG_LOG_FILTER; i++) {
+ const char *p;
+ if ((p = strchr(filter_config, ',')) == NULL) {
+ if (strlen(filter_config) >= MAX_DEBUG_LOG_FILTER) {
+ fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER);
+ exit(1);
+ }
+ strncpy(debug_log.filters[i], filter_config, MAX_DEBUG_LOG_FILTER - 1);
+ i++;
+ break;
+ }
+ else {
+ size_t n = p - filter_config;
+ if (n >= MAX_DEBUG_LOG_FILTER) {
+ fprintf(stderr, "too long: %s (max:%d)\n", filter_config, MAX_DEBUG_LOG_FILTER);
+ exit(1);
+ }
+ strncpy(debug_log.filters[i], filter_config, n);
+ filter_config = p+1;
+ }
+ }
+ debug_log.filters_num = i;
+ for (i=0; i<debug_log.filters_num; i++) {
+ fprintf(stderr, "RUBY_DEBUG_LOG_FILTER[%d]=%s\n", i, debug_log.filters[i]);
+ }
+ }
+}
+
+bool
+ruby_debug_log_filter(const char *func_name)
+{
+ if (debug_log.filters_num > 0) {
+ for (unsigned int i = 0; i<debug_log.filters_num; i++) {
+ if (strstr(func_name, debug_log.filters[i]) != NULL) {
+ return true;
+ }
+ }
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+static const char *
+pretty_filename(const char *path)
+{
+ // basename is one idea.
+ const char *s;
+ while ((s = strchr(path, '/')) != NULL) {
+ path = s+1;
+ }
+ return path;
+}
+
+void
+ruby_debug_log(const char *file, int line, const char *func_name, const char *fmt, ...)
+{
+ char buff[MAX_DEBUG_LOG_MESSAGE_LEN] = {0};
+ int len = 0;
+ int r = 0;
+
+ // message title
+ if (func_name && len < MAX_DEBUG_LOG_MESSAGE_LEN) {
+ r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN, "%s\t", func_name);
+ if (r < 0) rb_bug("ruby_debug_log returns %d\n", r);
+ len += r;
+ }
+
+ // message
+ if (fmt && len < MAX_DEBUG_LOG_MESSAGE_LEN) {
+ va_list args;
+ va_start(args, fmt);
+ r = vsnprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN - len, fmt, args);
+ va_end(args);
+ if (r < 0) rb_bug("ruby_debug_log vsnprintf() returns %d", r);
+ len += r;
+ }
+
+ // optional information
+
+ // C location
+ if (file && len < MAX_DEBUG_LOG_MESSAGE_LEN) {
+ r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN, "\t%s:%d", pretty_filename(file), line);
+ if (r < 0) rb_bug("ruby_debug_log returns %d\n", r);
+ len += r;
+ }
+
+ // Ruby location
+ int ruby_line;
+ const char *ruby_file = rb_source_location_cstr(&ruby_line);
+ if (len < MAX_DEBUG_LOG_MESSAGE_LEN) {
+ if (ruby_file) {
+ r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN - len, "\t%s:%d", pretty_filename(ruby_file), ruby_line);
+ }
+ else {
+ r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN - len, "\t");
+ }
+ if (r < 0) rb_bug("ruby_debug_log returns %d\n", r);
+ len += r;
+ }
+
+ // ractor information
+ if (ruby_single_main_ractor == NULL) {
+ rb_ractor_t *cr = GET_RACTOR();
+ if (r && len < MAX_DEBUG_LOG_MESSAGE_LEN) {
+ r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN - len, "\tr:#%u/%u",
+ (unsigned int)rb_ractor_id(cr), GET_VM()->ractor.cnt);
+ if (r < 0) rb_bug("ruby_debug_log returns %d\n", r);
+ len += r;
+ }
+ }
+
+ // thread information
+ if (!rb_thread_alone()) {
+ const rb_thread_t *th = GET_THREAD();
+ if (r && len < MAX_DEBUG_LOG_MESSAGE_LEN) {
+ r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN - len, "\tth:%p", (void *)th);
+ if (r < 0) rb_bug("ruby_debug_log returns %d\n", r);
+ len += r;
+ }
+ }
+
+ rb_nativethread_lock_lock(&debug_log.lock);
+ {
+ unsigned int cnt = debug_log.cnt++;
+
+ if (ruby_debug_log_mode & ruby_debug_log_memory) {
+ unsigned int index = cnt % MAX_DEBUG_LOG;
+ char *dst = RUBY_DEBUG_LOG_MEM_ENTRY(index);
+ strncpy(dst, buff, MAX_DEBUG_LOG_MESSAGE_LEN);
+ }
+ if (ruby_debug_log_mode & ruby_debug_log_stderr) {
+ fprintf(stderr, "%4u: %s\n", cnt, buff);
+ }
+ if (ruby_debug_log_mode & ruby_debug_log_file) {
+ fprintf(debug_log.output, "%u\t%s\n", cnt, buff);
+ }
+ }
+ rb_nativethread_lock_unlock(&debug_log.lock);
+}
+
+// for debugger
+static void
+debug_log_dump(FILE *out, unsigned int n)
+{
+ if (ruby_debug_log_mode & ruby_debug_log_memory) {
+ unsigned int size = debug_log.cnt > MAX_DEBUG_LOG ? MAX_DEBUG_LOG : debug_log.cnt;
+ unsigned int current_index = debug_log.cnt % MAX_DEBUG_LOG;
+ if (n == 0) n = size;
+ if (n > size) n = size;
+
+ for (unsigned int i=0; i<n; i++) {
+ int index = current_index - size + i;
+ if (index < 0) index += MAX_DEBUG_LOG;
+ VM_ASSERT(index <= MAX_DEBUG_LOG);
+ const char *mesg = RUBY_DEBUG_LOG_MEM_ENTRY(index);;
+ fprintf(out, "%4u: %s\n", debug_log.cnt - size + i, mesg);
+ }
+ }
+ else {
+ fprintf(stderr, "RUBY_DEBUG_LOG=mem is not specified.");
+ }
+}
+
+// for debuggers
+
+void
+ruby_debug_log_print(unsigned int n)
+{
+ debug_log_dump(stderr, n);
+}
+
+void
+ruby_debug_log_dump(const char *fname, unsigned int n)
+{
+ FILE *fp = fopen(fname, "w");
+ if (fp == NULL) {
+ fprintf(stderr, "can't open %s. give up.\n", fname);
+ }
+ else {
+ debug_log_dump(fp, n);
+ fclose(fp);
+ }
}
+#endif // #if RUBY_DEVEL
diff --git a/debug_counter.c b/debug_counter.c
index 11ec57a961..e7b0bb0acd 100644
--- a/debug_counter.c
+++ b/debug_counter.c
@@ -8,12 +8,14 @@
**********************************************************************/
-#include "internal.h"
#include "debug_counter.h"
+#include "internal.h"
#include <stdio.h>
#include <locale.h>
+#include "ruby/thread_native.h"
#if USE_DEBUG_COUNTER
+
static const char *const debug_counter_names[] = {
""
#define RB_DEBUG_COUNTER(name) #name,
@@ -23,8 +25,28 @@ static const char *const debug_counter_names[] = {
MJIT_SYMBOL_EXPORT_BEGIN
size_t rb_debug_counter[numberof(debug_counter_names)];
+void rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add);
MJIT_SYMBOL_EXPORT_END
+rb_nativethread_lock_t debug_counter_lock;
+
+__attribute__((constructor))
+static void
+debug_counter_setup(void)
+{
+ rb_nativethread_lock_initialize(&debug_counter_lock);
+}
+
+void
+rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add)
+{
+ rb_nativethread_lock_lock(&debug_counter_lock);
+ {
+ rb_debug_counter[(int)type] += add;
+ }
+ rb_nativethread_lock_unlock(&debug_counter_lock);
+}
+
int debug_counter_disable_show_at_exit = 0;
// note that this operation is not atomic.
@@ -92,7 +114,8 @@ rb_debug_counter_show_results(const char *msg)
VALUE
rb_debug_counter_show(RB_UNUSED_VAR(VALUE klass))
{
- rb_debug_counter_show_results("method call");
+ rb_debug_counter_show_results("show_debug_counters");
+ ruby_debug_counter_show_at_exit(FALSE);
return Qnil;
}
@@ -111,7 +134,9 @@ debug_counter_show_results_at_exit(void)
rb_debug_counter_show_results("normal exit.");
}
}
+
#else
+
void
rb_debug_counter_show_results(const char *msg)
{
diff --git a/debug_counter.h b/debug_counter.h
index 066533d1d1..3c20821db6 100644
--- a/debug_counter.h
+++ b/debug_counter.h
@@ -14,40 +14,61 @@
#ifdef RB_DEBUG_COUNTER
-/*
- * method cache (mc) counts.
- *
- * * mc_inline_hit/miss: inline mc hit/miss counts (VM send insn)
- * * mc_global_hit/miss: global method cache hit/miss counts
- * two types: (1) inline cache miss (VM send insn)
- * (2) called from C (rb_funcall).
- * * mc_global_state_miss: inline mc miss by global_state miss.
- * * mc_class_serial_miss: ... by mc_class_serial_miss
- * * mc_cme_complement: callable_method_entry complement counts.
- * * mc_cme_complement_hit: callable_method_entry cache hit counts.
- * * mc_search_super: search_method() call counts.
- * * mc_miss_by_nome: inline mc miss by no ment.
- * * mc_miss_by_distinct: ... by distinct ment.
- * * mc_miss_by_refine: ... by ment being refined.
- * * mc_miss_by_visi: ... by visibility change.
- * * mc_miss_spurious: spurious inline mc misshit.
- * * mc_miss_reuse_call: count of reuse of cc->call.
- */
-RB_DEBUG_COUNTER(mc_inline_hit)
-RB_DEBUG_COUNTER(mc_inline_miss)
-RB_DEBUG_COUNTER(mc_global_hit)
-RB_DEBUG_COUNTER(mc_global_miss)
-RB_DEBUG_COUNTER(mc_global_state_miss)
-RB_DEBUG_COUNTER(mc_class_serial_miss)
-RB_DEBUG_COUNTER(mc_cme_complement)
-RB_DEBUG_COUNTER(mc_cme_complement_hit)
-RB_DEBUG_COUNTER(mc_search_super)
-RB_DEBUG_COUNTER(mc_miss_by_nome)
-RB_DEBUG_COUNTER(mc_miss_by_distinct)
-RB_DEBUG_COUNTER(mc_miss_by_refine)
-RB_DEBUG_COUNTER(mc_miss_by_visi)
-RB_DEBUG_COUNTER(mc_miss_spurious)
-RB_DEBUG_COUNTER(mc_miss_reuse_call)
+// method cache (IMC: inline method cache)
+RB_DEBUG_COUNTER(mc_inline_hit) // IMC hit
+RB_DEBUG_COUNTER(mc_inline_miss_klass) // IMC miss by different class
+RB_DEBUG_COUNTER(mc_inline_miss_invalidated) // IMC miss by invalidated ME
+RB_DEBUG_COUNTER(mc_inline_miss_empty) // IMC miss because prev is empty slot
+RB_DEBUG_COUNTER(mc_inline_miss_same_cc) // IMC miss, but same CC
+RB_DEBUG_COUNTER(mc_inline_miss_same_cme) // IMC miss, but same CME
+RB_DEBUG_COUNTER(mc_inline_miss_same_def) // IMC miss, but same definition
+RB_DEBUG_COUNTER(mc_inline_miss_diff) // IMC miss, different methods
+
+RB_DEBUG_COUNTER(mc_cme_complement) // number of acquiring complement CME
+RB_DEBUG_COUNTER(mc_cme_complement_hit) // number of cache hit for complemented CME
+
+RB_DEBUG_COUNTER(mc_search) // count for method lookup in class tree
+RB_DEBUG_COUNTER(mc_search_notfound) // method lookup, but not found
+RB_DEBUG_COUNTER(mc_search_super) // total traversed classes
+
+// callinfo
+RB_DEBUG_COUNTER(ci_packed) // number of packed CI
+RB_DEBUG_COUNTER(ci_kw) // non-packed CI w/ keywords
+RB_DEBUG_COUNTER(ci_nokw) // non-packed CI w/o keywords
+RB_DEBUG_COUNTER(ci_runtime) // creating temporary CI
+
+// callcache
+RB_DEBUG_COUNTER(cc_new) // number of CC
+RB_DEBUG_COUNTER(cc_temp) // dummy CC (stack-allocated)
+RB_DEBUG_COUNTER(cc_found_in_ccs) // count for CC lookup success in CCS
+RB_DEBUG_COUNTER(cc_not_found_in_ccs) // count for CC lookup success in CCS
+
+RB_DEBUG_COUNTER(cc_ent_invalidate) // count for invalidating cc (cc->klass = 0)
+RB_DEBUG_COUNTER(cc_cme_invalidate) // count for invalidating CME
+
+RB_DEBUG_COUNTER(cc_invalidate_leaf) // count for invalidating klass if klass has no-sublcasses
+RB_DEBUG_COUNTER(cc_invalidate_leaf_ccs) // corresponding CCS
+RB_DEBUG_COUNTER(cc_invalidate_leaf_callable) // complimented cache (no-subclasses)
+RB_DEBUG_COUNTER(cc_invalidate_tree) // count for invalidating klass if klass has sublcasses
+RB_DEBUG_COUNTER(cc_invalidate_tree_cme) // cme if cme is found in this class or superclasses
+RB_DEBUG_COUNTER(cc_invalidate_tree_callable) // complimented cache (subclasses)
+RB_DEBUG_COUNTER(cc_invalidate_negative) // count for invalidating negative cache
+
+RB_DEBUG_COUNTER(ccs_free) // count for free'ing ccs
+RB_DEBUG_COUNTER(ccs_maxlen) // maximum length of ccs
+RB_DEBUG_COUNTER(ccs_found) // count for finding corresponding ccs on method lookup
+RB_DEBUG_COUNTER(ccs_not_found) // count for not found corresponding ccs on method lookup
+
+// vm_eval.c
+RB_DEBUG_COUNTER(call0_public)
+RB_DEBUG_COUNTER(call0_other)
+RB_DEBUG_COUNTER(gccct_hit)
+RB_DEBUG_COUNTER(gccct_miss)
+RB_DEBUG_COUNTER(gccct_null)
+
+// iseq
+RB_DEBUG_COUNTER(iseq_num) // number of total created iseq
+RB_DEBUG_COUNTER(iseq_cd_num) // number of total created cd (call_data)
/*
* call cache fastpath usage
@@ -61,6 +82,7 @@ RB_DEBUG_COUNTER(ccf_iseq_opt) /* has_opt == TRUE (has optional parameters), but
RB_DEBUG_COUNTER(ccf_iseq_kw1) /* vm_call_iseq_setup_kwparm_kwarg() */
RB_DEBUG_COUNTER(ccf_iseq_kw2) /* vm_call_iseq_setup_kwparm_nokwarg() */
RB_DEBUG_COUNTER(ccf_cfunc)
+RB_DEBUG_COUNTER(ccf_cfunc_with_frame)
RB_DEBUG_COUNTER(ccf_ivar) /* attr_reader */
RB_DEBUG_COUNTER(ccf_attrset) /* attr_writer */
RB_DEBUG_COUNTER(ccf_method_missing)
@@ -117,7 +139,7 @@ RB_DEBUG_COUNTER(ivar_set_ic_hit)
RB_DEBUG_COUNTER(ivar_set_ic_miss)
RB_DEBUG_COUNTER(ivar_set_ic_miss_serial)
RB_DEBUG_COUNTER(ivar_set_ic_miss_unset)
-RB_DEBUG_COUNTER(ivar_set_ic_miss_oorange)
+RB_DEBUG_COUNTER(ivar_set_ic_miss_iv_hit)
RB_DEBUG_COUNTER(ivar_set_ic_miss_noobject)
RB_DEBUG_COUNTER(ivar_get_base)
RB_DEBUG_COUNTER(ivar_set_base)
@@ -155,6 +177,12 @@ RB_DEBUG_COUNTER(gc_major_shady)
RB_DEBUG_COUNTER(gc_major_force)
RB_DEBUG_COUNTER(gc_major_oldmalloc)
+RB_DEBUG_COUNTER(gc_enter_start)
+RB_DEBUG_COUNTER(gc_enter_mark_continue)
+RB_DEBUG_COUNTER(gc_enter_sweep_continue)
+RB_DEBUG_COUNTER(gc_enter_rest)
+RB_DEBUG_COUNTER(gc_enter_finalizer)
+
RB_DEBUG_COUNTER(gc_isptr_trial)
RB_DEBUG_COUNTER(gc_isptr_range)
RB_DEBUG_COUNTER(gc_isptr_align)
@@ -164,7 +192,7 @@ RB_DEBUG_COUNTER(gc_isptr_maybe)
*
* * obj_newobj: newobj counts
* * obj_newobj_slowpath: newobj with slowpath counts
- * * obj_newobj_wb_unprotected: newobj for wb_unprotecte.
+ * * obj_newobj_wb_unprotected: newobj for wb_unprotected.
* * obj_free: obj_free() counts
* * obj_promote: promoted counts (oldgen)
* * obj_wb_unprotect: wb unprotect counts
@@ -282,6 +310,9 @@ RB_DEBUG_COUNTER(obj_imemo_throw_data)
RB_DEBUG_COUNTER(obj_imemo_ifunc)
RB_DEBUG_COUNTER(obj_imemo_memo)
RB_DEBUG_COUNTER(obj_imemo_parser_strterm)
+RB_DEBUG_COUNTER(obj_imemo_callinfo)
+RB_DEBUG_COUNTER(obj_imemo_callcache)
+RB_DEBUG_COUNTER(obj_imemo_constcache)
/* ar_table */
RB_DEBUG_COUNTER(artable_hint_hit)
@@ -301,14 +332,24 @@ RB_DEBUG_COUNTER(theap_alloc)
RB_DEBUG_COUNTER(theap_alloc_fail)
RB_DEBUG_COUNTER(theap_evacuate)
+// VM sync
+RB_DEBUG_COUNTER(vm_sync_lock)
+RB_DEBUG_COUNTER(vm_sync_lock_enter)
+RB_DEBUG_COUNTER(vm_sync_lock_enter_nb)
+RB_DEBUG_COUNTER(vm_sync_lock_enter_cr)
+RB_DEBUG_COUNTER(vm_sync_barrier)
+
/* mjit_exec() counts */
RB_DEBUG_COUNTER(mjit_exec)
RB_DEBUG_COUNTER(mjit_exec_not_added)
-RB_DEBUG_COUNTER(mjit_exec_not_added_add_iseq)
RB_DEBUG_COUNTER(mjit_exec_not_ready)
RB_DEBUG_COUNTER(mjit_exec_not_compiled)
RB_DEBUG_COUNTER(mjit_exec_call_func)
+/* MJIT enqueue / unload */
+RB_DEBUG_COUNTER(mjit_add_iseq_to_process)
+RB_DEBUG_COUNTER(mjit_unload_units)
+
/* MJIT <-> VM frame push counts */
RB_DEBUG_COUNTER(mjit_frame_VM2VM)
RB_DEBUG_COUNTER(mjit_frame_VM2JT)
@@ -318,9 +359,11 @@ RB_DEBUG_COUNTER(mjit_frame_JT2VM)
/* MJIT cancel counters */
RB_DEBUG_COUNTER(mjit_cancel)
RB_DEBUG_COUNTER(mjit_cancel_ivar_inline)
+RB_DEBUG_COUNTER(mjit_cancel_exivar_inline)
RB_DEBUG_COUNTER(mjit_cancel_send_inline)
RB_DEBUG_COUNTER(mjit_cancel_opt_insn) /* CALL_SIMPLE_METHOD */
RB_DEBUG_COUNTER(mjit_cancel_invalidate_all)
+RB_DEBUG_COUNTER(mjit_cancel_leave)
/* rb_mjit_unit_list length */
RB_DEBUG_COUNTER(mjit_length_unit_queue)
@@ -341,6 +384,10 @@ RB_DEBUG_COUNTER(load_path_is_not_realpath)
#ifndef RUBY_DEBUG_COUNTER_H
#define RUBY_DEBUG_COUNTER_H 1
+#include "ruby/internal/config.h"
+#include <stddef.h> /* for size_t */
+#include "ruby/ruby.h" /* for VALUE */
+
#if !defined(__GNUC__) && USE_DEBUG_COUNTER
#error "USE_DEBUG_COUNTER is not supported by other than __GNUC__"
#endif
@@ -354,27 +401,51 @@ enum rb_debug_counter_type {
#if USE_DEBUG_COUNTER
extern size_t rb_debug_counter[];
+RUBY_EXTERN struct rb_ractor_struct *ruby_single_main_ractor;
+RUBY_EXTERN void rb_debug_counter_add_atomic(enum rb_debug_counter_type type, int add);
inline static int
rb_debug_counter_add(enum rb_debug_counter_type type, int add, int cond)
{
if (cond) {
- rb_debug_counter[(int)type] += add;
+ if (ruby_single_main_ractor != NULL) {
+ rb_debug_counter[(int)type] += add;
+ }
+ else {
+ rb_debug_counter_add_atomic(type, add);
+ }
}
return cond;
}
+inline static int
+rb_debug_counter_max(enum rb_debug_counter_type type, unsigned int num)
+{
+ // TODO: sync
+ if (rb_debug_counter[(int)type] < num) {
+ rb_debug_counter[(int)type] = num;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
VALUE rb_debug_counter_reset(VALUE klass);
VALUE rb_debug_counter_show(VALUE klass);
#define RB_DEBUG_COUNTER_INC(type) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, 1)
#define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (!rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, !(cond)))
-#define RB_DEBUG_COUNTER_INC_IF(type, cond) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, (cond))
+#define RB_DEBUG_COUNTER_INC_IF(type, cond) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, 1, !!(cond))
+#define RB_DEBUG_COUNTER_ADD(type, num) rb_debug_counter_add(RB_DEBUG_COUNTER_##type, (num), 1)
+#define RB_DEBUG_COUNTER_SETMAX(type, num) rb_debug_counter_max(RB_DEBUG_COUNTER_##type, (unsigned int)(num))
#else
#define RB_DEBUG_COUNTER_INC(type) ((void)0)
-#define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (cond)
-#define RB_DEBUG_COUNTER_INC_IF(type, cond) (cond)
+#define RB_DEBUG_COUNTER_INC_UNLESS(type, cond) (!!(cond))
+#define RB_DEBUG_COUNTER_INC_IF(type, cond) (!!(cond))
+#define RB_DEBUG_COUNTER_ADD(type, num) ((void)0)
+#define RB_DEBUG_COUNTER_SETMAX(type, num) 0
#endif
void rb_debug_counter_show_results(const char *msg);
diff --git a/defs/gmake.mk b/defs/gmake.mk
index 226e1066a5..f093fd4e26 100644
--- a/defs/gmake.mk
+++ b/defs/gmake.mk
@@ -1,9 +1,10 @@
# -*- mode: makefile-gmake; indent-tabs-mode: t -*-
-gnumake = yes
+reconfig config.status: export MAKE:=$(MAKE)
override gnumake_recursive := $(if $(findstring n,$(firstword $(MFLAGS))),,+)
override mflags := $(filter-out -j%,$(MFLAGS))
MSPECOPT += $(if $(filter -j%,$(MFLAGS)),-j)
+nproc = $(subst -j,,$(filter -j%,$(MFLAGS)))
CHECK_TARGETS := great exam love check test check% test% btest%
# expand test targets, and those dependents
@@ -67,7 +68,7 @@ endif
ORDERED_TEST_TARGETS := $(filter $(TEST_TARGETS), \
btest-ruby test-knownbug test-basic \
test-testframework test-tool test-ruby test-all \
- test-spec test-bundler-prepare test-bundler \
+ test-spec test-bundler-prepare test-bundler test-bundler-parallel \
)
prev_test := $(if $(filter test-spec,$(ORDERED_TEST_TARGETS)),test-spec-precheck)
$(foreach test,$(ORDERED_TEST_TARGETS), \
@@ -90,6 +91,8 @@ sudo-precheck: test yes-test-testframework no-test-testframework
install-prereq: sudo-precheck
yes-test-all no-test-all: install
endif
+yes-test-bundler-parallel: PARALLELRSPECOPTS += $(if $(nproc),-n$(shell expr $(nproc) + $(nproc) / 2))
+
# Cross reference needs to parse all files at once
love install reinstall: RDOCFLAGS = --force-update
@@ -107,6 +110,8 @@ else
$(Q) $(RMALL) make_des_table*
endif
+config.status: $(wildcard config.cache)
+
STUBPROGRAM = rubystub$(EXEEXT)
IGNOREDPATTERNS = %~ .% %.orig %.rej \#%\#
SCRIPTBINDIR := $(if $(EXEEXT),,exec/)
@@ -241,16 +246,43 @@ HELP_EXTRA_TASKS = \
" update-github: merge master branch and push it to Pull Request [PR=1234]" \
""
-ifneq ($(filter refresh-gems,$(MAKECMDGOALS)),)
-extract-gems: update-gems
+extract-gems: $(HAVE_BASERUBY:yes=update-gems)
+
+bundled-gems := $(shell sed '/^[ ]*\#/d;/^[ ]*$$/d;s/[ ][ ]*/-/;s/[ ].*//' $(srcdir)/gems/bundled_gems)
+
+update-gems: | $(patsubst %,gems/%.gem,$(bundled-gems))
+
+test-bundler-precheck: | $(srcdir)/.bundle/cache
+
+$(srcdir)/.bundle/cache:
+ $(MAKEDIRS) $(@D) $(CACHE_DIR)
+ $(LN_S) ../.downloaded-cache $@
+
+gems/%.gem:
+ $(ECHO) Downloading bundled gem $*...
+ $(Q) $(BASERUBY) -C "$(srcdir)" \
+ -I./tool -rdownloader \
+ -e 'gem = "$(@F)"' \
+ -e 'old = Dir.glob("gems/"+gem.sub(/-[^-]*$$/, "-*.gem"))' \
+ -e 'Downloader::RubyGems.download(gem, "gems", nil) and' \
+ -e '(old.delete("gems/#{gem}"); !old.empty?) and' \
+ -e 'File.unlink(*old) and' \
+ -e 'FileUtils.rm_rf(old.map{'"|n|"'n.chomp(".gem")})'
+
+extract-gems: | $(patsubst %,.bundle/gems/%,$(bundled-gems))
+
+.bundle/gems/%: gems/%.gem | .bundle/gems
+ $(ECHO) Extracting bundle gem $*...
+ $(Q) $(BASERUBY) -C "$(srcdir)" \
+ -Itool -rgem-unpack \
+ -e 'Gem.unpack("gems/$(@F).gem", ".bundle/gems")'
+
+$(srcdir)/.bundle/gems:
+ $(MAKEDIRS) $@
+
+ifneq ($(filter update-bundled_gems refresh-gems,$(MAKECMDGOALS)),)
update-gems: update-bundled_gems
endif
-ifneq ($(filter extract-gems,$(MAKECMDGOALS)),)
-extract-gems: $(filter update-gems update-bundled_gems,$(MAKECMDGOALS))
-endif
-ifneq ($(filter update-gems,$(MAKECMDGOALS)),)
-update-gems: $(filter update-bundled_gems,$(MAKECMDGOALS))
-endif
ifeq ($(filter 0 1,$(words $(arch_flags))),)
$(foreach x,$(patsubst -arch=%,%,$(arch_flags)), \
@@ -306,19 +338,22 @@ rdoc\:%: PHONY
$(Q)$(RUNRUBY) $(srcdir)/libexec/ri --no-standard-docs --doc-dir=$(RDOCOUT) $(patsubst rdoc:%,%,$@)
test_%.rb test/%: programs PHONY
- +$(Q)$(exec) $(RUNRUBY) "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TEST_EXCLUDES) $(TESTOPTS) -- $(patsubst test/%,%,$@)
+ $(Q)$(exec) $(RUNRUBY) "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TEST_EXCLUDES) $(TESTOPTS) -- $(patsubst test/%,%,$@)
spec/bundler/%: PHONY
- +$(Q)$(exec) $(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/rspec --require spec_helper $(RSPECOPTS) $@
+ $(Q)$(exec) $(XRUBY) -C $(srcdir) -Ispec/bundler .bundle/bin/rspec --require spec_helper $(RSPECOPTS) $@
+
+spec/bundler: test-bundler-parallel
+ $(Q)$(NULLCMD)
spec/%: programs exts PHONY
- +$(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec-run -B $(srcdir)/spec/default.mspec $(SPECOPTS) $(patsubst %,$(srcdir)/%,$@)
+ $(RUNRUBY) -r./$(arch)-fake $(srcdir)/spec/mspec/bin/mspec-run -B $(srcdir)/spec/default.mspec $(SPECOPTS) $(patsubst %,$(srcdir)/%,$@)
benchmark/%: miniruby$(EXEEXT) update-benchmark-driver PHONY
$(Q)$(BASERUBY) -rrubygems -I$(srcdir)/benchmark/lib $(srcdir)/benchmark/benchmark-driver/exe/benchmark-driver \
--executables="compare-ruby::$(COMPARE_RUBY) -I$(EXTOUT)/common --disable-gem" \
--executables="built-ruby::$(BENCH_RUBY) --disable-gem" \
- $(srcdir)/$@ $(OPTS)
+ $(srcdir)/$@ $(BENCH_OPTS) $(OPTS)
clean-srcs-ext::
$(Q)$(RM) $(patsubst $(srcdir)/%,%,$(EXT_SRCS))
@@ -328,7 +363,7 @@ clean-srcs-extra::
ifneq ($(filter $(VCS),git),)
update-src::
- @$(BASERUBY) $(srcdir)/tool/lib/colorize.rb pass "Latest commit hash = $(shell $(filter-out svn,$(VCS)) -C $(srcdir) rev-parse --short=10 HEAD)"
+ @$(BASERUBY) $(tooldir)/lib/colorize.rb pass "Latest commit hash = $(shell $(filter-out svn,$(VCS)) -C $(srcdir) rev-parse --short=10 HEAD)"
endif
# Update dependencies and commit the updates to the current branch.
@@ -337,7 +372,7 @@ update-deps:
$(eval deps_dir := $(shell mktemp -d)/$(update_deps))
$(eval GIT_DIR := $(shell git -C $(srcdir) rev-parse --absolute-git-dir))
git --git-dir=$(GIT_DIR) worktree add $(deps_dir)
- cp $(srcdir)/tool/config.guess $(srcdir)/tool/config.sub $(deps_dir)/tool
+ cp $(tooldir)/config.guess $(tooldir)/config.sub $(deps_dir)/tool
[ -f config.status ] && cp config.status $(deps_dir)
cd $(deps_dir) && autoconf && \
exec ./configure -q -C --enable-load-relative --disable-install-doc --disable-rubygems 'optflags=-O0' 'debugflags=-save-temps=obj -g'
@@ -348,3 +383,14 @@ update-deps:
$(RMDIR) $(dir $(deps_dir))
git --git-dir=$(GIT_DIR) merge --no-edit --ff-only $(update_deps)
git --git-dir=$(GIT_DIR) branch --delete $(update_deps)
+
+# order-only-prerequisites doesn't work for $(RUBYSPEC_CAPIEXT)
+# because the same named directory exists in the source tree.
+$(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(srcdir)/$(RUBYSPEC_CAPIEXT)/rubyspec.h $(RUBY_H_INCLUDES) $(LIBRUBY_SO)
+ $(ECHO) building $@
+ $(Q) $(MAKEDIRS) $(@D)
+ $(Q) $(DLDSHARED) $(XDLDFLAGS) $(XLDFLAGS) $(ARCH_FLAG) $(ARCH_FLAG) $(CFLAGS) $(INCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ $< $(LIBRUBY_SO)
+ $(Q) $(RMALL) $@.*
+
+rubyspec-capiext: $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildcard $(srcdir)/$(RUBYSPEC_CAPIEXT)/*.c)))
+ @ $(NULLCMD)
diff --git a/dir.c b/dir.c
index 6a926f438c..c19ef637a1 100644
--- a/dir.c
+++ b/dir.c
@@ -11,12 +11,10 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/thread.h"
-#include "internal.h"
-#include "id.h"
-#include "encindex.h"
+#include "ruby/internal/config.h"
+#include <ctype.h>
+#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -36,12 +34,10 @@
# define USE_OPENDIR_AT 0
# endif
#endif
+
#if USE_OPENDIR_AT
# include <fcntl.h>
#endif
-#ifndef AT_FDCWD
-# define AT_FDCWD -1
-#endif
#undef HAVE_DIRENT_NAMLEN
#if defined HAVE_DIRENT_H && !defined _WIN32
@@ -68,8 +64,6 @@
# endif
#endif
-#include <errno.h>
-
#ifndef HAVE_STDLIB_H
char *getenv();
#endif
@@ -78,28 +72,6 @@ char *getenv();
char *strchr(char*,char);
#endif
-#include <ctype.h>
-
-#include "ruby/util.h"
-
-#define vm_initialized rb_cThread
-
-/* define system APIs */
-#ifdef _WIN32
-#undef chdir
-#define chdir(p) rb_w32_uchdir(p)
-#undef mkdir
-#define mkdir(p, m) rb_w32_umkdir((p), (m))
-#undef rmdir
-#define rmdir(p) rb_w32_urmdir(p)
-#undef opendir
-#define opendir(p) rb_w32_uopendir(p)
-#define ruby_getcwd() rb_w32_ugetcwd(NULL, 0)
-#define IS_WIN32 1
-#else
-#define IS_WIN32 0
-#endif
-
#ifdef HAVE_SYS_ATTR_H
#include <sys/attr.h>
#endif
@@ -123,15 +95,53 @@ char *strchr(char*,char);
#ifdef __APPLE__
# define NORMALIZE_UTF8PATH 1
+# include <sys/param.h>
+# include <sys/mount.h>
+# include <sys/vnode.h>
#else
# define NORMALIZE_UTF8PATH 0
#endif
-#if NORMALIZE_UTF8PATH
-#include <sys/param.h>
-#include <sys/mount.h>
-#include <sys/vnode.h>
+#include "encindex.h"
+#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/dir.h"
+#include "internal/encoding.h"
+#include "internal/error.h"
+#include "internal/file.h"
+#include "internal/gc.h"
+#include "internal/io.h"
+#include "internal/vm.h"
+#include "ruby/encoding.h"
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+#include "ruby/util.h"
+#include "builtin.h"
+#ifndef AT_FDCWD
+# define AT_FDCWD -1
+#endif
+
+#define vm_initialized rb_cThread
+
+/* define system APIs */
+#ifdef _WIN32
+# undef chdir
+# define chdir(p) rb_w32_uchdir(p)
+# undef mkdir
+# define mkdir(p, m) rb_w32_umkdir((p), (m))
+# undef rmdir
+# define rmdir(p) rb_w32_urmdir(p)
+# undef opendir
+# define opendir(p) rb_w32_uopendir(p)
+# define ruby_getcwd() rb_w32_ugetcwd(NULL, 0)
+# define IS_WIN32 1
+#else
+# define IS_WIN32 0
+#endif
+
+#if NORMALIZE_UTF8PATH
# if defined HAVE_FGETATTRLIST || !defined HAVE_GETATTRLIST
# define need_normalization(dirp, path) need_normalization(dirp)
# else
@@ -211,6 +221,7 @@ typedef enum {
#else
#define FNM_SHORTNAME 0
#endif
+#define FNM_GLOB_NOSORT 0x40
#define FNM_NOMATCH 1
#define FNM_ERROR 2
@@ -511,40 +522,13 @@ opendir_without_gvl(const char *path)
return opendir(path);
}
-/*
- * call-seq:
- * Dir.new( string ) -> aDir
- * Dir.new( string, encoding: enc ) -> aDir
- *
- * Returns a new directory object for the named directory.
- *
- * The optional <i>encoding</i> keyword argument specifies the encoding of the directory.
- * If not specified, the filesystem encoding is used.
- */
static VALUE
-dir_initialize(int argc, VALUE *argv, VALUE dir)
+dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc)
{
struct dir_data *dp;
- rb_encoding *fsenc;
- VALUE dirname, opt, orig;
- static ID keyword_ids[1];
+ VALUE orig;
const char *path;
-
- if (!keyword_ids[0]) {
- keyword_ids[0] = rb_id_encoding();
- }
-
- fsenc = rb_filesystem_encoding();
-
- rb_scan_args(argc, argv, "1:", &dirname, &opt);
-
- if (!NIL_P(opt)) {
- VALUE enc;
- rb_get_kwargs(opt, keyword_ids, 0, 1, &enc);
- if (enc != Qundef && !NIL_P(enc)) {
- fsenc = rb_to_encoding(enc);
- }
- }
+ rb_encoding *fsenc = NIL_P(enc) ? rb_filesystem_encoding() : rb_to_encoding(enc);
FilePathValue(dirname);
orig = rb_str_dup_frozen(dirname);
@@ -582,35 +566,23 @@ dir_initialize(int argc, VALUE *argv, VALUE dir)
return dir;
}
-/*
- * call-seq:
- * Dir.open( string ) -> aDir
- * Dir.open( string, encoding: enc ) -> aDir
- * Dir.open( string ) {| aDir | block } -> anObject
- * Dir.open( string, encoding: enc ) {| aDir | block } -> anObject
- *
- * The optional <i>encoding</i> keyword argument specifies the encoding of the directory.
- * If not specified, the filesystem encoding is used.
- *
- * With no block, <code>open</code> is a synonym for Dir::new. If a
- * block is present, it is passed <i>aDir</i> as a parameter. The
- * directory is closed at the end of the block, and Dir::open returns
- * the value of the block.
- */
static VALUE
-dir_s_open(int argc, VALUE *argv, VALUE klass)
+dir_s_open(rb_execution_context_t *ec, VALUE klass, VALUE dirname, VALUE enc)
{
struct dir_data *dp;
VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp);
- dir_initialize(argc, argv, dir);
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, dir, dir_close, dir);
- }
+ dir_initialize(ec, dir, dirname, enc);
return dir;
}
+static VALUE
+dir_s_close(rb_execution_context_t *ec, VALUE klass, VALUE dir)
+{
+ return dir_close(dir);
+}
+
NORETURN(static void dir_closed(void));
static void
@@ -1052,7 +1024,8 @@ chdir_restore(VALUE v)
* block. <code>chdir</code> blocks can be nested, but in a
* multi-threaded program an error will be raised if a thread attempts
* to open a <code>chdir</code> block while another thread has one
- * open.
+ * open or a call to <code>chdir</code> without a block occurs inside
+ * a block passed to <code>chdir</code> (even in the same thread).
*
* Dir.chdir("/var/spool/mail")
* puts Dir.pwd
@@ -1091,8 +1064,10 @@ dir_s_chdir(int argc, VALUE *argv, VALUE obj)
}
if (chdir_blocking > 0) {
- if (!rb_block_given_p() || rb_thread_current() != chdir_thread)
- rb_warn("conflicting chdir during another chdir block");
+ if (rb_thread_current() != chdir_thread)
+ rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block");
+ if (!rb_block_given_p())
+ rb_warn("conflicting chdir during another chdir block");
}
if (rb_block_given_p()) {
@@ -1342,21 +1317,34 @@ sys_enc_warning_in(const char *func, const char *mesg, rb_encoding *enc)
#define sys_warning(val, enc) \
((flags & GLOB_VERBOSE) ? sys_enc_warning_in(RUBY_FUNCTION_NAME_STRING, (val), (enc)) :(void)0)
-static inline void *
-glob_alloc_n(size_t x, size_t y)
+static inline size_t
+glob_alloc_size(size_t x, size_t y)
{
size_t z;
if (rb_mul_size_overflow(x, y, SSIZE_MAX, &z)) {
rb_memerror(); /* or...? */
}
else {
- return malloc(z);
+ return z;
}
}
+static inline void *
+glob_alloc_n(size_t x, size_t y)
+{
+ return malloc(glob_alloc_size(x, y));
+}
+
+static inline void *
+glob_realloc_n(void *p, size_t x, size_t y)
+{
+ return realloc(p, glob_alloc_size(x, y));
+}
+
#define GLOB_ALLOC(type) ((type *)malloc(sizeof(type)))
#define GLOB_ALLOC_N(type, n) ((type *)glob_alloc_n(sizeof(type), n))
#define GLOB_REALLOC(ptr, size) realloc((ptr), (size))
+#define GLOB_REALLOC_N(ptr, n) glob_realloc_n(ptr, sizeof(*(ptr)), n)
#define GLOB_FREE(ptr) free(ptr)
#define GLOB_JUMP_TAG(status) (((status) == -1) ? rb_memerror() : rb_jump_tag(status))
@@ -1721,10 +1709,7 @@ glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
tmp = GLOB_ALLOC(struct glob_pattern);
if (!tmp) {
- error:
- *tail = 0;
- glob_free_pattern(list);
- return 0;
+ goto error;
}
tmp->type = dirsep ? MATCH_DIR : MATCH_ALL;
tmp->str = 0;
@@ -1732,6 +1717,11 @@ glob_make_pattern(const char *p, const char *e, int flags, rb_encoding *enc)
tmp->next = 0;
return list;
+
+ error:
+ *tail = 0;
+ glob_free_pattern(list);
+ return 0;
}
static void
@@ -1982,13 +1972,15 @@ rb_glob_warning(const char *path, VALUE a, const void *enc, int error)
}
#endif
+NORETURN(static VALUE glob_func_error(VALUE val));
+
static VALUE
glob_func_error(VALUE val)
{
struct glob_error_args *arg = (struct glob_error_args *)val;
VALUE path = rb_enc_str_new_cstr(arg->path, arg->enc);
rb_syserr_fail_str(arg->error, path);
- return Qnil;
+ UNREACHABLE_RETURN(Qnil);
}
static int
@@ -2008,8 +2000,17 @@ rb_glob_error(const char *path, VALUE a, const void *enc, int error)
return status;
}
+typedef struct rb_dirent {
+ long d_namlen;
+ const char *d_name;
+#ifdef _WIN32
+ const char *d_altname;
+#endif
+ uint8_t d_type;
+} rb_dirent_t;
+
static inline int
-dirent_match(const char *pat, rb_encoding *enc, const char *name, const struct dirent *dp, int flags)
+dirent_match(const char *pat, rb_encoding *enc, const char *name, const rb_dirent_t *dp, int flags)
{
if (fnmatch(pat, enc, name, flags) == 0) return 1;
#ifdef _WIN32
@@ -2034,7 +2035,7 @@ struct push_glob_args {
struct dirent_brace_args {
const char *name;
- const struct dirent *dp;
+ const rb_dirent_t *dp;
int flags;
};
@@ -2097,6 +2098,159 @@ static int push_caller(const char *path, VALUE val, void *enc);
static int ruby_brace_expand(const char *str, int flags, ruby_glob_func *func, VALUE arg,
rb_encoding *enc, VALUE var);
+static const size_t rb_dirent_name_offset =
+ offsetof(rb_dirent_t, d_type) + sizeof(uint8_t);
+
+static rb_dirent_t *
+dirent_copy(const struct dirent *dp, rb_dirent_t *rdp)
+{
+ if (!dp) return NULL;
+ size_t namlen = NAMLEN(dp);
+ const size_t altlen =
+#ifdef _WIN32
+ dp->d_altlen ? dp->d_altlen + 1 :
+#endif
+ 0;
+ rb_dirent_t *newrdp = rdp;
+ if (!rdp && !(newrdp = malloc(rb_dirent_name_offset + namlen + 1 + altlen)))
+ return NULL;
+ newrdp->d_namlen = namlen;
+ if (!rdp) {
+ char *name = (char *)newrdp + rb_dirent_name_offset;
+ memcpy(name, dp->d_name, namlen);
+ name[namlen] = '\0';
+#ifdef _WIN32
+ newrdp->d_altname = NULL;
+ if (altlen) {
+ char *const altname = name + namlen + 1;
+ memcpy(altname, dp->d_altname, altlen - 1);
+ altname[altlen - 1] = '\0';
+ newrdp->d_altname = altname;
+ }
+#endif
+ newrdp->d_name = name;
+ }
+ else {
+ newrdp->d_name = dp->d_name;
+#ifdef _WIN32
+ newrdp->d_altname = dp->d_altname;
+#endif
+ }
+#ifdef DT_UNKNOWN
+ newrdp->d_type = dp->d_type;
+#else
+ newrdp->d_type = 0;
+#endif
+ return newrdp;
+}
+
+typedef union {
+ struct {
+ DIR *dirp;
+ rb_dirent_t ent;
+ } nosort;
+ struct {
+ size_t count, idx;
+ rb_dirent_t **entries;
+ } sort;
+} ruby_glob_entries_t;
+
+static int
+glob_sort_cmp(const void *a, const void *b, void *e)
+{
+ const rb_dirent_t *ent1 = *(void **)a;
+ const rb_dirent_t *ent2 = *(void **)b;
+ return strcmp(ent1->d_name, ent2->d_name);
+}
+
+static void
+glob_dir_finish(ruby_glob_entries_t *ent, int flags)
+{
+ if (flags & FNM_GLOB_NOSORT) {
+ closedir(ent->nosort.dirp);
+ ent->nosort.dirp = NULL;
+ }
+ else if (ent->sort.entries) {
+ for (size_t i = 0, count = ent->sort.count; i < count;) {
+ GLOB_FREE(ent->sort.entries[i++]);
+ }
+ GLOB_FREE(ent->sort.entries);
+ ent->sort.entries = NULL;
+ ent->sort.count = ent->sort.idx = 0;
+ }
+}
+
+static ruby_glob_entries_t *
+glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc)
+{
+ MEMZERO(ent, ruby_glob_entries_t, 1);
+ if (flags & FNM_GLOB_NOSORT) {
+ ent->nosort.dirp = dirp;
+ return ent;
+ }
+ else {
+ void *newp;
+ struct dirent *dp;
+ size_t count = 0, capacity = 0;
+ ent->sort.count = 0;
+ ent->sort.idx = 0;
+ ent->sort.entries = 0;
+#ifdef _WIN32
+ if ((capacity = dirp->nfiles) > 0) {
+ if (!(newp = GLOB_ALLOC_N(rb_dirent_t, capacity))) {
+ closedir(dirp);
+ return NULL;
+ }
+ ent->sort.entries = newp;
+ }
+#endif
+ while ((dp = READDIR(dirp, enc)) != NULL) {
+ rb_dirent_t *rdp = dirent_copy(dp, NULL);
+ if (!rdp) {
+ goto nomem;
+ }
+ if (count >= capacity) {
+ capacity += 256;
+ if (!(newp = GLOB_REALLOC_N(ent->sort.entries, capacity)))
+ goto nomem;
+ ent->sort.entries = newp;
+ }
+ ent->sort.entries[count++] = rdp;
+ ent->sort.count = count;
+ }
+ closedir(dirp);
+ if (count < capacity) {
+ if (!(newp = GLOB_REALLOC_N(ent->sort.entries, count))) {
+ glob_dir_finish(ent, 0);
+ return NULL;
+ }
+ ent->sort.entries = newp;
+ }
+ ruby_qsort(ent->sort.entries, ent->sort.count, sizeof(ent->sort.entries[0]),
+ glob_sort_cmp, NULL);
+ return ent;
+ }
+
+ nomem:
+ glob_dir_finish(ent, 0);
+ closedir(dirp);
+ return NULL;
+}
+
+static rb_dirent_t *
+glob_getent(ruby_glob_entries_t *ent, int flags, rb_encoding *enc)
+{
+ if (flags & FNM_GLOB_NOSORT) {
+ return dirent_copy(READDIR(ent->nosort.dirp, enc), &ent->nosort.ent);
+ }
+ else if (ent->sort.idx < ent->sort.count) {
+ return ent->sort.entries[ent->sort.idx++];
+ }
+ else {
+ return NULL;
+ }
+}
+
static int
glob_helper(
int fd,
@@ -2119,6 +2273,8 @@ glob_helper(
int escape = !(flags & FNM_NOESCAPE);
size_t pathlen = baselen + namelen;
+ rb_check_stack_overflow();
+
for (cur = beg; cur < end; ++cur) {
struct glob_pattern *p = *cur;
if (p->type == RECURSIVE) {
@@ -2209,7 +2365,7 @@ glob_helper(
if (pathtype == path_noent) return 0;
if (magical || recursive) {
- struct dirent *dp;
+ rb_dirent_t *dp;
DIR *dirp;
# if USE_NAME_ON_FS == USE_NAME_ON_FS_BY_FNMATCH
char *plainname = 0;
@@ -2248,7 +2404,18 @@ glob_helper(
if (is_case_sensitive(dirp, path) == 0)
flags |= FNM_CASEFOLD;
# endif
- while ((dp = READDIR(dirp, enc)) != NULL) {
+ ruby_glob_entries_t globent;
+ if (!glob_opendir(&globent, dirp, flags, enc)) {
+ status = 0;
+ if (funcs->error) {
+ status = (*funcs->error)(path, arg, enc, ENOMEM);
+ }
+ else {
+ sys_warning(path, enc);
+ }
+ return status;
+ }
+ while ((dp = glob_getent(&globent, flags, enc)) != NULL) {
char *buf;
rb_pathtype_t new_pathtype = path_unknown;
const char *name;
@@ -2257,7 +2424,7 @@ glob_helper(
IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil);
name = dp->d_name;
- namlen = NAMLEN(dp);
+ namlen = dp->d_namlen;
if (recursive && name[0] == '.') {
++dotfile;
if (namlen == 1) {
@@ -2352,7 +2519,7 @@ glob_helper(
if (status) break;
}
- closedir(dirp);
+ glob_dir_finish(&globent, flags);
}
else if (plain) {
struct glob_pattern **copy_beg, **copy_end, **cur2;
@@ -2522,7 +2689,7 @@ ruby_glob(const char *path, int flags, ruby_glob_func *func, VALUE arg)
{
ruby_glob_funcs_t funcs;
funcs.match = func;
- funcs.error = NULL;
+ funcs.error = 0;
return ruby_glob0(path, AT_FDCWD, 0, flags & ~GLOB_VERBOSE,
&funcs, arg, rb_ascii8bit_encoding());
}
@@ -2651,7 +2818,7 @@ ruby_brace_glob_with_enc(const char *str, int flags, ruby_glob_func *func, VALUE
flags &= ~GLOB_VERBOSE;
args.funcs.match = func;
- args.funcs.error = NULL;
+ args.funcs.error = 0;
args.value = arg;
args.flags = flags;
return ruby_brace_expand(str, flags, glob_brace, (VALUE)&args, enc, Qfalse);
@@ -2728,177 +2895,67 @@ rb_push_glob(VALUE str, VALUE base, int flags) /* '\0' is delimiter */
}
static VALUE
-dir_globs(long argc, const VALUE *argv, VALUE base, int flags)
+dir_globs(VALUE args, VALUE base, int flags)
{
VALUE ary = rb_ary_new();
long i;
- for (i = 0; i < argc; ++i) {
+ for (i = 0; i < RARRAY_LEN(args); ++i) {
int status;
- VALUE str = argv[i];
+ VALUE str = RARRAY_AREF(args, i);
FilePathValue(str);
status = push_glob(ary, str, base, flags);
if (status) GLOB_JUMP_TAG(status);
}
+ RB_GC_GUARD(args);
return ary;
}
-static void
-dir_glob_options(VALUE opt, VALUE *base, int *flags)
+static VALUE
+dir_glob_option_base(VALUE base)
{
- ID kw[2];
- VALUE args[2];
- kw[0] = rb_intern("base");
- if (flags) kw[1] = rb_intern("flags");
- rb_get_kwargs(opt, kw, 0, flags ? 2 : 1, args);
- if (args[0] == Qundef || NIL_P(args[0])) {
- *base = Qnil;
+ if (base == Qundef || NIL_P(base)) {
+ return Qnil;
}
#if USE_OPENDIR_AT
- else if (rb_typeddata_is_kind_of(args[0], &dir_data_type)) {
- *base = args[0];
+ if (rb_typeddata_is_kind_of(base, &dir_data_type)) {
+ return base;
}
#endif
- else {
- FilePathValue(args[0]);
- if (!RSTRING_LEN(args[0])) args[0] = Qnil;
- *base = args[0];
- }
- if (flags && args[1] != Qundef) {
- *flags = NUM2INT(args[1]);
- }
+ FilePathValue(base);
+ if (!RSTRING_LEN(base)) return Qnil;
+ return base;
+}
+
+static int
+dir_glob_option_sort(VALUE sort)
+{
+ return (sort ? 0 : FNM_GLOB_NOSORT);
}
-/*
- * call-seq:
- * Dir[ string [, string ...] [, base: path] ] -> array
- *
- * Equivalent to calling
- * <code>Dir.glob([</code><i>string,...</i><code>], 0)</code>.
- *
- */
static VALUE
-dir_s_aref(int argc, VALUE *argv, VALUE obj)
+dir_s_aref(rb_execution_context_t *ec, VALUE obj, VALUE args, VALUE base, VALUE sort)
{
- VALUE opts, base;
- argc = rb_scan_args(argc, argv, "*:", NULL, &opts);
- dir_glob_options(opts, &base, NULL);
- if (argc == 1) {
- return rb_push_glob(argv[0], base, 0);
+ const int flags = dir_glob_option_sort(sort);
+ base = dir_glob_option_base(base);
+ if (RARRAY_LEN(args) == 1) {
+ return rb_push_glob(RARRAY_AREF(args, 0), base, flags);
}
- return dir_globs(argc, argv, base, 0);
+ return dir_globs(args, base, flags);
}
-/*
- * call-seq:
- * Dir.glob( pattern, [flags], [base: path] ) -> array
- * Dir.glob( pattern, [flags], [base: path] ) { |filename| block } -> nil
- *
- * Expands +pattern+, which is a pattern string or an Array of pattern
- * strings, and returns an array containing the matching filenames.
- * If a block is given, calls the block once for each matching filename,
- * passing the filename as a parameter to the block.
- *
- * The optional +base+ keyword argument specifies the base directory for
- * interpreting relative pathnames instead of the current working directory.
- * As the results are not prefixed with the base directory name in this
- * case, you will need to prepend the base directory name if you want real
- * paths.
- *
- * Note that the pattern is not a regexp, it's closer to a shell glob.
- * See File::fnmatch for the meaning of the +flags+ parameter.
- * Case sensitivity depends on your system (File::FNM_CASEFOLD is ignored),
- * as does the order in which the results are returned.
- *
- * <code>*</code>::
- * Matches any file. Can be restricted by other values in the glob.
- * Equivalent to <code>/ .* /mx</code> in regexp.
- *
- * <code>*</code>:: Matches all files
- * <code>c*</code>:: Matches all files beginning with <code>c</code>
- * <code>*c</code>:: Matches all files ending with <code>c</code>
- * <code>\*c\*</code>:: Match all files that have <code>c</code> in them
- * (including at the beginning or end).
- *
- * Note, this will not match Unix-like hidden files (dotfiles). In order
- * to include those in the match results, you must use the
- * File::FNM_DOTMATCH flag or something like <code>"{*,.*}"</code>.
- *
- * <code>**</code>::
- * Matches directories recursively.
- *
- * <code>?</code>::
- * Matches any one character. Equivalent to <code>/.{1}/</code> in regexp.
- *
- * <code>[set]</code>::
- * Matches any one character in +set+. Behaves exactly like character sets
- * in Regexp, including set negation (<code>[^a-z]</code>).
- *
- * <code>{p,q}</code>::
- * Matches either literal <code>p</code> or literal <code>q</code>.
- * Equivalent to pattern alternation in regexp.
- *
- * Matching literals may be more than one character in length. More than
- * two literals may be specified.
- *
- * <code> \\ </code>::
- * Escapes the next metacharacter.
- *
- * Note that this means you cannot use backslash on windows as part of a
- * glob, i.e. <code>Dir["c:\\foo*"]</code> will not work, use
- * <code>Dir["c:/foo*"]</code> instead.
- *
- * Examples:
- *
- * Dir["config.?"] #=> ["config.h"]
- * Dir.glob("config.?") #=> ["config.h"]
- * Dir.glob("*.[a-z][a-z]") #=> ["main.rb"]
- * Dir.glob("*.[^r]*") #=> ["config.h"]
- * Dir.glob("*.{rb,h}") #=> ["main.rb", "config.h"]
- * Dir.glob("*") #=> ["config.h", "main.rb"]
- * Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "..", "config.h", "main.rb"]
- * Dir.glob(["*.rb", "*.h"]) #=> ["main.rb", "config.h"]
- *
- * rbfiles = File.join("**", "*.rb")
- * Dir.glob(rbfiles) #=> ["main.rb",
- * # "lib/song.rb",
- * # "lib/song/karaoke.rb"]
- *
- * Dir.glob(rbfiles, base: "lib") #=> ["song.rb",
- * # "song/karaoke.rb"]
- *
- * libdirs = File.join("**", "lib")
- * Dir.glob(libdirs) #=> ["lib"]
- *
- * librbfiles = File.join("**", "lib", "**", "*.rb")
- * Dir.glob(librbfiles) #=> ["lib/song.rb",
- * # "lib/song/karaoke.rb"]
- *
- * librbfiles = File.join("**", "lib", "*.rb")
- * Dir.glob(librbfiles) #=> ["lib/song.rb"]
- */
static VALUE
-dir_s_glob(int argc, VALUE *argv, VALUE obj)
+dir_s_glob(rb_execution_context_t *ec, VALUE obj, VALUE str, VALUE rflags, VALUE base, VALUE sort)
{
- VALUE str, rflags, ary, opts, base;
- int flags;
-
- argc = rb_scan_args(argc, argv, "11:", &str, &rflags, &opts);
- if (argc == 2)
- flags = NUM2INT(rflags);
- else
- flags = 0;
- dir_glob_options(opts, &base, &flags);
-
- ary = rb_check_array_type(str);
+ VALUE ary = rb_check_array_type(str);
+ const int flags = NUM2INT(rflags) | dir_glob_option_sort(sort);
+ base = dir_glob_option_base(base);
if (NIL_P(ary)) {
ary = rb_push_glob(str, base, flags);
}
else {
- VALUE v = ary;
- ary = dir_globs(RARRAY_LEN(v), RARRAY_CONST_PTR(v), base, flags);
- RB_GC_GUARD(v);
+ ary = dir_globs(ary, base, flags);
}
if (rb_block_given_p()) {
@@ -3023,7 +3080,7 @@ dir_s_each_child(int argc, VALUE *argv, VALUE io)
/*
* call-seq:
- * dir.each_child {| filename | block } -> nil
+ * dir.each_child {| filename | block } -> dir
* dir.each_child -> an_enumerator
*
* Calls the block once for each entry except for "." and ".." in
@@ -3289,16 +3346,11 @@ rb_file_directory_p(void)
}
#endif
-/*
- * call-seq:
- * Dir.exists?(file_name) -> true or false
- *
- * Deprecated method. Don't use.
- */
+/* :nodoc: */
static VALUE
rb_dir_exists_p(VALUE obj, VALUE fname)
{
- rb_warning("Dir.exists? is a deprecated name, use Dir.exist? instead");
+ rb_warn_deprecated("Dir.exists?", "Dir.exist?");
return rb_file_directory_p(obj, fname);
}
@@ -3399,13 +3451,11 @@ Init_Dir(void)
rb_include_module(rb_cDir, rb_mEnumerable);
rb_define_alloc_func(rb_cDir, dir_s_alloc);
- rb_define_singleton_method(rb_cDir, "open", dir_s_open, -1);
rb_define_singleton_method(rb_cDir, "foreach", dir_foreach, -1);
rb_define_singleton_method(rb_cDir, "entries", dir_entries, -1);
rb_define_singleton_method(rb_cDir, "each_child", dir_s_each_child, -1);
rb_define_singleton_method(rb_cDir, "children", dir_s_children, -1);
- rb_define_method(rb_cDir,"initialize", dir_initialize, -1);
rb_define_method(rb_cDir,"fileno", dir_fileno, 0);
rb_define_method(rb_cDir,"path", dir_path, 0);
rb_define_method(rb_cDir,"to_path", dir_path, 0);
@@ -3431,8 +3481,6 @@ Init_Dir(void)
rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
rb_define_singleton_method(rb_cDir,"home", dir_s_home, -1);
- rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, -1);
- rb_define_singleton_method(rb_cDir,"[]", dir_s_aref, -1);
rb_define_singleton_method(rb_cDir,"exist?", rb_file_directory_p, 1);
rb_define_singleton_method(rb_cDir,"exists?", rb_dir_exists_p, 1);
rb_define_singleton_method(rb_cDir,"empty?", rb_dir_s_empty_p, 1);
@@ -3487,3 +3535,5 @@ Init_Dir(void)
*/
rb_file_const("FNM_SHORTNAME", INT2FIX(FNM_SHORTNAME));
}
+
+#include "dir.rbinc"
diff --git a/dir.rb b/dir.rb
new file mode 100644
index 0000000000..eb46305013
--- /dev/null
+++ b/dir.rb
@@ -0,0 +1,136 @@
+class Dir
+ # Dir.open( string ) -> aDir
+ # Dir.open( string, encoding: enc ) -> aDir
+ # Dir.open( string ) {| aDir | block } -> anObject
+ # Dir.open( string, encoding: enc ) {| aDir | block } -> anObject
+ #
+ # The optional <i>encoding</i> keyword argument specifies the encoding of the directory.
+ # If not specified, the filesystem encoding is used.
+ #
+ # With no block, <code>open</code> is a synonym for Dir::new. If a
+ # block is present, it is passed <i>aDir</i> as a parameter. The
+ # directory is closed at the end of the block, and Dir::open returns
+ # the value of the block.
+ def self.open(name, encoding: nil, &block)
+ dir = Primitive.dir_s_open(name, encoding)
+ if block
+ begin
+ yield dir
+ ensure
+ Primitive.dir_s_close(dir)
+ end
+ else
+ dir
+ end
+ end
+
+ # Dir.new( string ) -> aDir
+ # Dir.new( string, encoding: enc ) -> aDir
+ #
+ # Returns a new directory object for the named directory.
+ #
+ # The optional <i>encoding</i> keyword argument specifies the encoding of the directory.
+ # If not specified, the filesystem encoding is used.
+ def initialize(name, encoding: nil)
+ Primitive.dir_initialize(name, encoding)
+ end
+
+ # Dir[ string [, string ...] [, base: path] [, sort: true] ] -> array
+ #
+ # Equivalent to calling
+ # <code>Dir.glob([</code><i>string,...</i><code>], 0)</code>.
+ def self.[](*args, base: nil, sort: true)
+ Primitive.dir_s_aref(args, base, sort)
+ end
+
+ # Dir.glob( pattern, [flags], [base: path] [, sort: true] ) -> array
+ # Dir.glob( pattern, [flags], [base: path] [, sort: true] ) { |filename| block } -> nil
+ #
+ # Expands +pattern+, which is a pattern string or an Array of pattern
+ # strings, and returns an array containing the matching filenames.
+ # If a block is given, calls the block once for each matching filename,
+ # passing the filename as a parameter to the block.
+ #
+ # The optional +base+ keyword argument specifies the base directory for
+ # interpreting relative pathnames instead of the current working directory.
+ # As the results are not prefixed with the base directory name in this
+ # case, you will need to prepend the base directory name if you want real
+ # paths.
+ #
+ # The results which matched single wildcard or character set are sorted in
+ # binary ascending order, unless false is given as the optional +sort+
+ # keyword argument. The order of an Array of pattern strings and braces
+ # are preserved.
+ #
+ # Note that the pattern is not a regexp, it's closer to a shell glob.
+ # See File::fnmatch for the meaning of the +flags+ parameter.
+ # Case sensitivity depends on your system (File::FNM_CASEFOLD is ignored).
+ #
+ # <code>*</code>::
+ # Matches any file. Can be restricted by other values in the glob.
+ # Equivalent to <code>/ .* /mx</code> in regexp.
+ #
+ # <code>*</code>:: Matches all files
+ # <code>c*</code>:: Matches all files beginning with <code>c</code>
+ # <code>*c</code>:: Matches all files ending with <code>c</code>
+ # <code>\*c\*</code>:: Match all files that have <code>c</code> in them
+ # (including at the beginning or end).
+ #
+ # Note, this will not match Unix-like hidden files (dotfiles). In order
+ # to include those in the match results, you must use the
+ # File::FNM_DOTMATCH flag or something like <code>"{*,.*}"</code>.
+ #
+ # <code>**</code>::
+ # Matches directories recursively if followed by <code>/</code>. If
+ # this path segment contains any other characters, it is the same as the
+ # usual <code>*</code>.
+ #
+ # <code>?</code>::
+ # Matches any one character. Equivalent to <code>/.{1}/</code> in regexp.
+ #
+ # <code>[set]</code>::
+ # Matches any one character in +set+. Behaves exactly like character sets
+ # in Regexp, including set negation (<code>[^a-z]</code>).
+ #
+ # <code>{p,q}</code>::
+ # Matches either literal <code>p</code> or literal <code>q</code>.
+ # Equivalent to pattern alternation in regexp.
+ #
+ # Matching literals may be more than one character in length. More than
+ # two literals may be specified.
+ #
+ # <code> \\ </code>::
+ # Escapes the next metacharacter.
+ #
+ # Note that this means you cannot use backslash on windows as part of a
+ # glob, i.e. <code>Dir["c:\\foo*"]</code> will not work, use
+ # <code>Dir["c:/foo*"]</code> instead.
+ #
+ # Examples:
+ #
+ # Dir["config.?"] #=> ["config.h"]
+ # Dir.glob("config.?") #=> ["config.h"]
+ # Dir.glob("*.[a-z][a-z]") #=> ["main.rb"]
+ # Dir.glob("*.[^r]*") #=> ["config.h"]
+ # Dir.glob("*.{rb,h}") #=> ["main.rb", "config.h"]
+ # Dir.glob("*") #=> ["config.h", "main.rb"]
+ # Dir.glob("*", File::FNM_DOTMATCH) #=> [".", "..", "config.h", "main.rb"]
+ # Dir.glob(["*.rb", "*.h"]) #=> ["main.rb", "config.h"]
+ #
+ # Dir.glob("**/*.rb") #=> ["main.rb",
+ # # "lib/song.rb",
+ # # "lib/song/karaoke.rb"]
+ #
+ # Dir.glob("**/*.rb", base: "lib") #=> ["song.rb",
+ # # "song/karaoke.rb"]
+ #
+ # Dir.glob("**/lib") #=> ["lib"]
+ #
+ # Dir.glob("**/lib/**/*.rb") #=> ["lib/song.rb",
+ # # "lib/song/karaoke.rb"]
+ #
+ # Dir.glob("**/lib/*.rb") #=> ["lib/song.rb"]
+ def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true)
+ Primitive.dir_s_glob(pattern, flags, base, sort)
+ end
+end
diff --git a/dln.c b/dln.c
index c40cbfc6ac..caaa685a6e 100644
--- a/dln.c
+++ b/dln.c
@@ -1244,6 +1244,8 @@ rb_w32_check_imported(HMODULE ext, HMODULE mine)
#endif
#ifdef USE_DLN_DLOPEN
+# include "ruby/internal/stdbool.h"
+# include "internal/warnings.h"
COMPILER_WARNING_PUSH
#if defined(__clang__) || GCC_VERSION_SINCE(4, 2, 0)
COMPILER_WARNING_IGNORED(-Wpedantic)
@@ -1252,7 +1254,8 @@ static bool
dln_incompatible_library_p(void *handle)
{
void *ex = dlsym(handle, EXTERNAL_PREFIX"ruby_xmalloc");
- return ex && ex != ruby_xmalloc;
+ void *const fp = (void *)ruby_xmalloc;
+ return ex && ex != fp;
}
COMPILER_WARNING_POP
#endif
diff --git a/dln.h b/dln.h
index d98b2607e2..99106fd22b 100644
--- a/dln.h
+++ b/dln.h
@@ -1,3 +1,5 @@
+#ifndef DLN_H
+#define DLN_H
/**********************************************************************
dln.h -
@@ -9,24 +11,7 @@
**********************************************************************/
-#ifndef DLN_H
-#define DLN_H
-
-#ifdef __cplusplus
-# ifndef HAVE_PROTOTYPES
-# define HAVE_PROTOTYPES 1
-# endif
-# ifndef HAVE_STDARG_PROTOTYPES
-# define HAVE_STDARG_PROTOTYPES 1
-# endif
-#endif
-
-#undef _
-#ifdef HAVE_PROTOTYPES
-# define _(args) args
-#else
-# define _(args) ()
-#endif
+#include "ruby/defines.h" /* for RUBY_SYMBOL_EXPORT_BEGIN */
RUBY_SYMBOL_EXPORT_BEGIN
diff --git a/dln_find.c b/dln_find.c
index b08612764e..ca62441631 100644
--- a/dln_find.c
+++ b/dln_find.c
@@ -248,26 +248,14 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
/* now append the file name */
i = fnlen;
if (fspace < i) {
- toolong:
- PATHNAME_TOO_LONG();
- goto next;
+ goto toolong;
}
fspace -= i;
memcpy(bp, fname, i + 1);
#if defined(DOSISH)
if (exe_flag && !ext) {
- needs_extension:
- for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
- if (fspace < strlen(extension[j])) {
- PATHNAME_TOO_LONG();
- continue;
- }
- strlcpy(bp + i, extension[j], fspace);
- if (stat(fbuf, &st) == 0)
- return fbuf;
- }
- goto next;
+ goto needs_extension;
}
#endif
@@ -284,7 +272,25 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size,
if (*ep == '\0') {
return NULL;
}
+ continue;
+
+ toolong:
+ PATHNAME_TOO_LONG();
+ goto next;
+#if defined(DOSISH)
+ needs_extension:
+ for (j = 0; j < sizeof(extension) / sizeof(extension[0]); j++) {
+ if (fspace < strlen(extension[j])) {
+ PATHNAME_TOO_LONG();
+ continue;
+ }
+ strlcpy(bp + i, extension[j], fspace);
+ if (stat(fbuf, &st) == 0)
+ return fbuf;
+ }
+ goto next;
+#endif
/* otherwise try the next component in the search path */
}
}
diff --git a/doc/.document b/doc/.document
index d739c9f6bc..ad17aada6d 100644
--- a/doc/.document
+++ b/doc/.document
@@ -1,3 +1,4 @@
+*.md
*.rdoc
NEWS-*
syntax
diff --git a/doc/ChangeLog-1.9.3 b/doc/ChangeLog-1.9.3
index eecfc44325..d6aaea7f19 100644
--- a/doc/ChangeLog-1.9.3
+++ b/doc/ChangeLog-1.9.3
@@ -92076,7 +92076,7 @@ Mon Sep 1 16:59:10 2003 Nobuyoshi Nakada <nobu@ruby-lang.org>
* eval.c (rb_thread_start_0): should not error_print() within
terminated thread, because $stderr used by it might be
- overriden now. [ruby-dev:21280]
+ overridden now. [ruby-dev:21280]
Sun Aug 31 22:46:55 2003 WATANABE Hirofumi <eban@ruby-lang.org>
diff --git a/doc/ChangeLog-2.0.0 b/doc/ChangeLog-2.0.0
index a1a79b8dca..b51d742203 100644
--- a/doc/ChangeLog-2.0.0
+++ b/doc/ChangeLog-2.0.0
@@ -9758,7 +9758,7 @@ Thu Aug 23 16:20:04 2012 Koichi Sasada <ko1@atdot.net>
are b10.
If flonum is activated, then USE_FLONUM macro is 1.
I'll write detailed in this technique on
- https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/Flonum_tech
+ https://bugs.ruby-lang.org/projects/ruby-master/wiki/Flonum_tech
* benchmark/bmx_temp.rb: add an benchmark for simple
Float calculation.
@@ -13008,7 +13008,7 @@ Thu Jun 7 15:53:03 2012 Koichi Sasada <ko1@atdot.net>
* .gdbinit: add function `trace_machine_instructions' to trace
in native machine assemble.
- See https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/MachineInstructionsTraceWithGDB
+ See https://bugs.ruby-lang.org/projects/ruby-master/wiki/MachineInstructionsTraceWithGDB
for more details.
Wed Jun 6 21:31:21 2012 Tanaka Akira <akr@fsij.org>
@@ -14711,7 +14711,7 @@ Fri Apr 27 01:45:05 2012 NARUSE, Yui <naruse@ruby-lang.org>
(22) main thread waits at gvl_yield:112 (native_cond_wait)
As described above, the main thread can't escape from
rb_threadptr_execute_interrupts_common.
- See extended memo: http://bugs.ruby-lang.org/projects/ruby-trunk/wiki/R35480_ExtendedMemo
+ See extended memo: http://bugs.ruby-lang.org/projects/ruby-master/wiki/R35480_ExtendedMemo
Fri Apr 27 07:15:07 2012 Tanaka Akira <akr@fsij.org>
diff --git a/doc/ChangeLog-2.1.0 b/doc/ChangeLog-2.1.0
index 76edfd3ce7..5b670b31c9 100644
--- a/doc/ChangeLog-2.1.0
+++ b/doc/ChangeLog-2.1.0
@@ -3596,7 +3596,7 @@ Tue Oct 22 19:19:05 2013 Koichi Sasada <ko1@atdot.net>
maintains all pages.
For example, pages are allocated from the heap_pages.
- See https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/GC_design
+ See https://bugs.ruby-lang.org/projects/ruby-master/wiki/GC_design
and https://bugs.ruby-lang.org/attachments/4015/data-heap_structure_with_multiple_heaps.png
for more details.
@@ -8612,7 +8612,7 @@ Wed Jul 17 14:31:13 2013 Koichi Sasada <ko1@atdot.net>
(4) heap::sorted is an array of "slots", sorted by an address of
slot::body.
- See https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/GC_design
+ See https://bugs.ruby-lang.org/projects/ruby-master/wiki/GC_design
for more details (figure).
* gc.c: Avoid "heaps" terminology. It is ambiguous.
diff --git a/doc/NEWS-2.0.0 b/doc/NEWS-2.0.0
index 414789dcd1..712d3a693b 100644
--- a/doc/NEWS-2.0.0
+++ b/doc/NEWS-2.0.0
@@ -116,8 +116,7 @@ with all sufficient information, see the ChangeLog file.
corresponding method in the prepending module.
* added Module.prepended and Module.prepend_features, similar
to included and append_features.
- * added Module#refine, which extends a class or module locally.
- [experimental]
+ * added Module#refine, which extends a class or module locally. [experimental]
* extended method:
* Module#define_method accepts a UnboundMethod from a Module.
* Module#const_get accepts a qualified constant string, e.g.
diff --git a/doc/NEWS-2.2.0 b/doc/NEWS-2.2.0
index 5564c606ae..98e252ec77 100644
--- a/doc/NEWS-2.2.0
+++ b/doc/NEWS-2.2.0
@@ -90,7 +90,7 @@ with all sufficient information, see the ChangeLog file.
* Method
* New methods:
- * Method#curry([arity]) returns a curried Proc.
+ * Method#curry([ arity ]) returns a curried Proc.
* Method#super_method returns a Method of superclass, which would be called
when super is used.
@@ -250,8 +250,7 @@ with all sufficient information, see the ChangeLog file.
* Logger::Application is extracted to logger-application gem. It's unmaintain code.
* ObjectSpace (after requiring "objspace")
- * ObjectSpace.memsize_of(obj) returns a size includes sizeof(RVALUE).
- [Bug #8984]
+ * ObjectSpace.memsize_of(obj) returns a size includes sizeof(RVALUE). [Bug #8984]
* Prime
* incompatible changes:
@@ -353,8 +352,7 @@ with all sufficient information, see the ChangeLog file.
* VM
* Use frozen string literals for Hash#[] and Hash#[]=
* Fast keyword arguments passing [Feature #10440]
- * Allow to receive huge splatted array by a rest argument
- [Feature #10440]
+ * Allow to receive huge splatted array by a rest argument [Feature #10440]
* Process
* Process creation methods, such as spawn(), uses vfork() system call.
diff --git a/doc/NEWS-2.3.0 b/doc/NEWS-2.3.0
index 489aba4a89..065515257e 100644
--- a/doc/NEWS-2.3.0
+++ b/doc/NEWS-2.3.0
@@ -16,20 +16,19 @@ with all sufficient information, see the ChangeLog file or Redmine
* frozen-string-literal pragma:
- * new pragma, frozen-string-literal has been experimentally introduced.
- [Feature #8976]
+ * new pragma, frozen-string-literal has been experimentally introduced. [Feature #8976]
* besides, --enable/--disable=frozen-string-literal options also have
been introduced. [Feature #8976]
* command line options --debug or --debug=frozen-string-literal enable
additional debugging mode which shows created location with at frozen
- object error (RuntimeError).
- [Feature #11725]
+ object error (RuntimeError). [Feature #11725]
* safe navigation operator:
* new method call syntax, `object&.foo', method #foo is called on
- `object' if it is not nil.
- this is similar to `try!' in Active Support, except:
+ `object' if it is not nil. [Feature #11537]
+
+ This is similar to `try!' in Active Support, except:
* method name is syntactically required
obj.try! {} # valid
obj&. {} # syntax error
@@ -38,7 +37,6 @@ with all sufficient information, see the ChangeLog file or Redmine
obj&.foo(bar()) # bar() is conditionally evaluated
* attribute assignment is valid
obj&.attr += 1
- [Feature #11537]
* the did_you_mean gem:
@@ -53,15 +51,13 @@ with all sufficient information, see the ChangeLog file or Redmine
* indented here document:
* new string literal, here document starts with `<<~`.
- refer doc/syntax/literals.rdoc for more details.
- [Feature #9098]
+ refer doc/syntax/literals.rdoc for more details. [Feature #9098]
=== Core classes updates (outstanding ones only)
* ARGF
- * ARGF.read_nonblock supports `exception: false' like IO#read_nonblock.
- [Feature #11358]
+ * ARGF.read_nonblock supports `exception: false' like IO#read_nonblock. [Feature #11358]
* Array
@@ -78,8 +74,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* Enumerable
- * Enumerable#grep_v is added as inverse version of Enumerable#grep.
- [Feature #11049]
+ * Enumerable#grep_v is added as inverse version of Enumerable#grep. [Feature #11049]
* Enumerable#chunk_while [Feature #10769]
* Enumerator::Lazy
@@ -105,8 +100,7 @@ with all sufficient information, see the ChangeLog file or Redmine
this affect only files opened as binary. [Feature #11218]
* new option parameter `flags' is added.
- this parameter is bitwise-ORed to oflags generated by normal mode argument.
- [Feature #11253]
+ this parameter is bitwise-ORed to oflags generated by normal mode argument. [Feature #11253]
* IO#advise no longer raises Errno::ENOSYS in cases where it was
detected at build time but not available at runtime. [Feature #11806]
@@ -125,8 +119,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* Numeric
* Numeric#positive? and Numeric#negative? are added, which return
- true when the receiver is positive and negative respectively.
- [Feature #11151]
+ true when the receiver is positive and negative respectively. [Feature #11151]
* Proc
@@ -152,11 +145,9 @@ with all sufficient information, see the ChangeLog file or Redmine
* String
- * String#+@ and String#-@ are added to get mutable/frozen strings.
- [Feature #11782]
+ * String#+@ and String#-@ are added to get mutable/frozen strings. [Feature #11782]
- * String.new now accepts new option parameter `encoding'.
- [Feature #11785]
+ * String.new now accepts new option parameter `encoding'. [Feature #11785]
* Struct
* Struct#dig [Feature #11688]
@@ -233,12 +224,10 @@ with all sufficient information, see the ChangeLog file or Redmine
* OpenSSL
* OpenSSL::SSL::SSLSocket#accept_nonblock and
- OpenSSL::SSL::SSLSocket#connect_nonblock supports `exception: false`.
- [Feature #10532]
+ OpenSSL::SSL::SSLSocket#connect_nonblock supports `exception: false`. [Feature #10532]
* Pathname
- * Pathname#descend and Pathname#ascend supported blockless form.
- [Feature #11052]
+ * Pathname#descend and Pathname#ascend supported blockless form. [Feature #11052]
* Socket
* Socket#connect_nonblock, Socket#accept_nonblock,
@@ -246,8 +235,7 @@ with all sufficient information, see the ChangeLog file or Redmine
BasicSocket#recv_nonblock, BasicSocket#recvmsg_nonblock,
BasicSocket#sendmsg_nonblock all support `exception: false` to return
:wait_readable or :wait_writable symbols instead of raising
- IO::WaitReadable or IO::WaitWritable exceptions
- [Feature #10532] [Feature #11229]
+ IO::WaitReadable or IO::WaitWritable exceptions [Feature #10532] [Feature #11229]
* BasicSocket#recv and BasicSocket#recv_nonblock allow an output
String buffer argument like IO#read and IO#read_nonblock to reduce
GC overhead [Feature #11242]
@@ -255,8 +243,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* StringIO
* In read-only mode, StringIO#set_encoding no longer sets the encoding
of its buffer string. Setting the encoding of the string directly
- without StringIO#set_encoding may cause unpredictable behavior now.
- [Bug #11827]
+ without StringIO#set_encoding may cause unpredictable behavior now. [Bug #11827]
* timeout
* Object#timeout is now warned as deprecated when called.
@@ -297,8 +284,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* default value of Net::HTTP#open_timeout is now 60 (was nil).
* Net::Telnet
- * Net::Telnet is extracted to net-telnet gem. It's unmaintain code.
- [Feature #11083]
+ * Net::Telnet is extracted to net-telnet gem. It's unmaintain code. [Feature #11083]
* Psych
* Updated to Psych 2.0.17
@@ -330,8 +316,7 @@ with all sufficient information, see the ChangeLog file or Redmine
class is already defined but its superclass does not match the given
superclass, as well as definitions in ruby level.
-* rb_timespec_now() is added to fetch current datetime as struct timespec.
- [Feature #11558]
+* rb_timespec_now() is added to fetch current datetime as struct timespec. [Feature #11558]
* rb_time_timespec_new() is added to create a time object with epoch,
nanosecond, and UTC/localtime/time offset arguments. [Feature #11558]
@@ -354,11 +339,9 @@ with all sufficient information, see the ChangeLog file or Redmine
=== Implementation improvements
-* Optimize Proc#call to eliminate method frame construction.
- [Feature #11569]
+* Optimize Proc#call to eliminate method frame construction. [Feature #11569]
-* Reconsidering method entry data structure.
- [Bug #11278]
+* Reconsidering method entry data structure. [Bug #11278]
* Introducing new table data structure for ID keys tables used by
method table and so on. New table structure is simple and fast
@@ -367,13 +350,11 @@ with all sufficient information, see the ChangeLog file or Redmine
* Machine code level tuning for object allocation and method calling
code. r52099, r52254
-* RubyVM::InstructionSequence is extended for future improvement.
- [Feature #11788]
+* RubyVM::InstructionSequence is extended for future improvement. [Feature #11788]
* Case dispatch is now optimized for all special constant literals
including nil, true, and false. Previously, only literal strings,
- symbols, integers and floats compiled to optimized case dispatch.
- [Feature #11769]
+ symbols, integers and floats compiled to optimized case dispatch. [Feature #11769]
* Instance variables on non-pure Ruby classes (T_DATA, T_FILE,
etc..) is less expensive to store than before. [Feature #11170]
@@ -382,8 +363,7 @@ with all sufficient information, see the ChangeLog file or Redmine
constant-time. Previously, Struct elements beyond the first 10
elements used a linear scan. [Feature #10585]
-* The Set class got several speed up.
- [Misc #10754], [r52591]
+* The Set class got several speed up. [Misc #10754], [r52591]
* Socket and I/O-related improvements
@@ -397,8 +377,8 @@ with all sufficient information, see the ChangeLog file or Redmine
addition to reducing expensive exceptions. [Feature #11044]
* (Linux-only) waiting on a single FD anywhere in the stdlib no longer
- uses select(2), making it immune to slowdowns with high-numbered FDs.
- [Feature #11081] [Feature #11377]
+ uses select(2), making it immune to slowdowns with high-numbered
+ FDs. [Feature #11081] [Feature #11377]
* CGI.escapeHTML is optimized with C extension.
https://github.com/ruby/ruby/pull/1164
diff --git a/doc/NEWS-2.4.0 b/doc/NEWS-2.4.0
index 28e855cde1..8a02f03809 100644
--- a/doc/NEWS-2.4.0
+++ b/doc/NEWS-2.4.0
@@ -14,16 +14,13 @@ with all sufficient information, see the ChangeLog file or Redmine
=== Language changes
-* Multiple assignment in conditional expression is now allowed.
- [Feature #10617]
+* Multiple assignment in conditional expression is now allowed. [Feature #10617]
* Refinements is enabled at method by Symbol#to_proc. [Feature #9451]
-* Refinements is enabled with Kernel#send and BasicObject#__send__.
- [Feature #11476]
+* Refinements is enabled with Kernel#send and BasicObject#__send__. [Feature #11476]
-* Rescue modifier now applicable to method arguments.
- [Feature #12686]
+* Rescue modifier now applicable to method arguments. [Feature #12686]
* Toplevel return is now allowed. [Feature #4840]
@@ -32,17 +29,21 @@ with all sufficient information, see the ChangeLog file or Redmine
* Array
* Array#concat [Feature #12333]
+
Now takes multiple arguments.
* Array#max and Array#min. [Feature #12172]
+
This may cause a tiny incompatibility: if you redefine
Enumerable#max and call max to an Array, your redefinition will be
now ignored. You should also redefine Array#max.
* Array#pack [Feature #12754]
+
Now takes optional argument `buffer:' to reuse already allocated buffer.
* Array#sum [Feature #12217]
+
This is different from Enumerable#sum in that Array#sum doesn't depend on
the definition of each method.
@@ -56,8 +57,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* Enumerable
- * Enumerable#chunk called without a block now return an Enumerator
- [Feature #2172]
+ * Enumerable#chunk called without a block now return an Enumerator [Feature #2172]
* Enumerable#sum [Feature #12217]
* Enumerable#uniq [Feature #11090]
@@ -95,6 +95,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* Integer#round now takes an optional keyword argument, half option, and the
default behavior is round-up now. [Bug #12548] [Bug #12958]
+
half option can be one of :even, :up, and :down. [Feature #12953]
* IO
@@ -104,8 +105,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* Kernel
- * Kernel#clone now takes an optional keyword argument, freeze flag.
- [Feature #12300]
+ * Kernel#clone now takes an optional keyword argument, freeze flag. [Feature #12300]
* MatchData
@@ -138,6 +138,7 @@ with all sufficient information, see the ChangeLog file or Redmine
for UTR #51 Unicode Emoji, Version 4.0 emoji zwj sequences.
* Regexp#match? [Feature #8110]
+
This returns bool and doesn't save backref.
* Update to Onigmo 6.0.0.
@@ -153,6 +154,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* String#casecmp? [Feature #12786]
* String#concat, String#prepend [Feature #12333]
+
Now takes multiple arguments.
* String#each_line, String#lines now takes an optional keyword argument,
@@ -189,8 +191,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* Thread
- * Thread#report_on_exception and Thread.report_on_exception
- [Feature #6647]
+ * Thread#report_on_exception and Thread.report_on_exception [Feature #6647]
* TracePoint
@@ -200,8 +201,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* New module named Warning is introduced. By default it has only
one singleton method, named warn. This makes it possible for
- 3rd-party libraries to control the way warnings are handled.
- [Feature #12299]
+ 3rd-party libraries to control the way warnings are handled. [Feature #12299]
=== Stdlib updates (outstanding ones only)
@@ -215,8 +215,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* IPAddr
- * IPAddr#== and IPAddr#<=> no longer raise an exception if coercion fails.
- [Bug #12799]
+ * IPAddr#== and IPAddr#<=> no longer raise an exception if coercion fails. [Bug #12799]
* IRB
@@ -256,8 +255,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* Readline
- * Readline.quoting_detection_proc and Readline.quoting_detection_proc=
- [Feature #12659]
+ * Readline.quoting_detection_proc and Readline.quoting_detection_proc= [Feature #12659]
* REXML
@@ -267,8 +265,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* set
- * New methods: Set#compare_by_identity and Set#compare_by_identity?.
- [Feature #12210]
+ * New methods: Set#compare_by_identity and Set#compare_by_identity?. [Feature #12210]
* WEBrick
@@ -277,6 +274,7 @@ with all sufficient information, see the ChangeLog file or Redmine
=== Compatibility issues (excluding feature bug fixes)
* Array#sum and Enumerable#sum are implemented. [Feature #12217]
+
Ruby itself has no compatibility problem because Ruby didn't have sum method
for arrays before Ruby 2.4.
However many third party gems, activesupport, facets, simple_stats, etc,
@@ -286,6 +284,7 @@ with all sufficient information, see the ChangeLog file or Redmine
be perfectly compatible with all of them.
* Fixnum and Bignum are unified into Integer [Feature #12005]
+
Fixnum class and Bignum class is removed.
Integer class is changed from abstract class to concrete class.
For example, 0 is an instance of Integer: 0.class returns Integer.
@@ -300,6 +299,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* String/Symbol#upcase/downcase/swapcase/capitalize(!) now work for all of
Unicode, not only for ASCII. [Feature #10085]
+
No change is needed if the data is in ASCII anyway or if the limitation
to ASCII was only tolerated while waiting for a more extensive implementation.
A change (using the :ascii option) is needed in cases where Unicode data
@@ -307,6 +307,7 @@ with all sufficient information, see the ChangeLog file or Redmine
A good example of this are internationalized domain names.
* TRUE / FALSE / NIL
+
These constants are now obsoleted. [Feature #12574]
Use true / false / nil resp. instead.
@@ -332,8 +333,7 @@ with all sufficient information, see the ChangeLog file or Redmine
* Shellwords.shellwords (shellsplit) treats the backslash as escape
character only when followed by one of the following characters:
- $ ` " \ <newline>
- [Bug #10055]
+ $ ` " \ <newline> [Bug #10055]
* Time
@@ -348,11 +348,13 @@ with all sufficient information, see the ChangeLog file or Redmine
* Tk
* Tk is removed from stdlib. [Feature #8539]
+
https://github.com/ruby/tk is the new upstream.
* XMLRPC
* XMLRPC is removed from stdlib, and bundled as gem. [Feature #12160][ruby-core:74239]
+
https://github.com/ruby/xmlrpc is the new upstream.
* Zlib
@@ -390,8 +392,8 @@ with all sufficient information, see the ChangeLog file or Redmine
=== Miscellaneous changes
* ChangeLog is removed from the repository.
+
It is generated from commit messages in Subversion by `make dist`.
Also note that now people should follow Git style commit message.
- The template is written at
- [Short (50 chars or less) summary of changes](https://git-scm.com/book/ch5-2.html).
- [Feature #12283]
+ The template is written at {Short (50 chars or less) summary of
+ changes}[https://git-scm.com/book/ch5-2.html]. [Feature #12283]
diff --git a/doc/NEWS-2.6.0 b/doc/NEWS-2.6.0
index 2303a5bd41..6e70696de2 100644
--- a/doc/NEWS-2.6.0
+++ b/doc/NEWS-2.6.0
@@ -50,24 +50,24 @@ sufficient information, see the ChangeLog file or Redmine
=== Core classes updates (outstanding ones only)
-Array::
+[Array]
- New methods::
+ [New methods]
* Added Array#union and Array#difference instance methods. [Feature #14097]
- Modified method::
+ [Modified method]
* Array#to_h now accepts a block that maps elements to new key/value pairs. [Feature #15143]
- Aliased methods::
+ [Aliased methods]
* Array#filter is a new alias for Array#select. [Feature #13784]
* Array#filter! is a new alias for Array#select!. [Feature #13784]
-Binding::
+[Binding]
- New method::
+ [New method]
* Added Binding#source_location. [Feature #14230]
@@ -79,97 +79,97 @@ Binding::
binding's source location [Bug #4352]. So, users should use this
newly-introduced method instead of Kernel#eval.
-Dir::
+[Dir]
- New methods::
+ [New methods]
* Added Dir#each_child and Dir#children instance methods. [Feature #13969]
-Enumerable::
+[Enumerable]
- New method::
+ [New method]
* Enumerable#chain returns an enumerator object that iterates over the
elements of the receiver and then those of each argument
in sequence. [Feature #15144]
- Modified method::
+ [Modified method]
* Enumerable#to_h now accepts a block that maps elements to new key/value pairs. [Feature #15143]
- Aliased method::
+ [Aliased method]
* Enumerable#filter is a new alias for Enumerable#select. [Feature #13784]
-Enumerator::ArithmeticSequence::
+[Enumerator::ArithmeticSequence]
* This is a new class to represent a generator of an arithmetic sequence,
that is a number sequence defined by a common difference. It can be used
for representing what is similar to Python's slice. You can get an
instance of this class from Numeric#step and Range#step.
-Enumerator::Chain::
+[Enumerator::Chain]
* This is a new class to represent a chain of enumerables that works as a
single enumerator, generated by such methods as Enumerable#chain and
Enumerator#+.
-Enumerator::Lazy::
+[Enumerator::Lazy]
- Aliased method::
+ [Aliased method]
* Enumerator::Lazy#filter is a new alias for
Enumerator::Lazy#select. [Feature #13784]
-Enumerator::
+[Enumerator]
- New methods::
+ [New methods]
* Enumerator#+ returns an enumerator object that iterates over the
elements of the receiver and then those of the other operand. [Feature #15144]
-ENV::
+[ENV]
- Modified method::
+ [Modified method]
* ENV.to_h now accepts a block that maps names and values to new keys and values. [Feature #15143]
-Exception::
+[Exception]
- New options::
+ [New options]
* Exception#full_message takes +:highlight+ and +:order+
options. [Bug #14324]
-Hash::
+[Hash]
- Modified methods::
+ [Modified methods]
* Hash#merge, Hash#merge!, and Hash#update now accept multiple
arguments. [Feature #15111]
* Hash#to_h now accepts a block that maps keys and values to new keys and values. [Feature #15143]
- Aliased methods::
+ [Aliased methods]
* Hash#filter is a new alias for Hash#select. [Feature #13784]
* Hash#filter! is a new alias for Hash#select!. [Feature #13784]
-IO::
+[IO]
- New option::
+ [New option]
* Added new mode character <code>'x'</code> to open files for exclusive
access. [Feature #11258]
-Kernel::
+[Kernel]
- Aliased method::
+ [Aliased method]
* Kernel#then is a new alias for Kernel#yield_self. [Feature #14594]
- New options::
+ [New options]
* Kernel#Complex, Kernel#Float, Kernel#Integer, and
Kernel#Rational take an +:exception+ option to specify the way of
@@ -178,98 +178,98 @@ Kernel::
* Kernel#system takes an +:exception+ option to raise an exception
on failure. [Feature #14386]
- Incompatible changes::
+ [Incompatible changes]
* Kernel#system and Kernel#exec do not close non-standard file descriptors
(the default of the +:close_others+ option is changed to +false+,
but we still set the +FD_CLOEXEC+ flag on descriptors we
create). [Misc #14907]
-KeyError::
+[KeyError]
- New options::
+ [New options]
* KeyError.new accepts +:receiver+ and +:key+ options to set receiver and
key in Ruby code. [Feature #14313]
-Method::
+[Method]
- New methods::
+ [New methods]
* Added Method#<< and Method#>> for Proc composition. [Feature #6284]
-Module::
+[Module]
- Modified methods::
+ [Modified methods]
* Module#method_defined?, Module#private_method_defined?, and
Module#protected_method_defined? now accept the second
parameter as optional. If it is +true+ (the default value), it checks
ancestor modules/classes, or checks only the class itself. [Feature #14944]
-NameError::
+[NameError]
- New option::
+ [New option]
* NameError.new accepts a +:receiver+ option to set receiver in Ruby
code. [Feature #14313]
-NilClass::
+[NilClass]
- New method::
+ [New method]
* NilClass#=~ is added for compatibility. [Feature #15231]
-NoMethodError::
+[NoMethodError]
- New option::
+ [New option]
* NoMethodError.new accepts a +:receiver+ option to set receiver in Ruby
code. [Feature #14313]
-Numeric::
+[Numeric]
- Incompatible changes::
+ [Incompatible changes]
* Numeric#step now returns an instance of the Enumerator::ArithmeticSequence
class rather than one of the Enumerator class.
-OpenStruct::
+[OpenStruct]
- Modified method::
+ [Modified method]
* OpenStruct#to_h now accepts a block that maps keys and values to new keys and values. [Feature #15143]
-Proc::
+[Proc]
- New methods::
+ [New methods]
* Added Proc#<< and Proc#>> for Proc composition. [Feature #6284]
- Incompatible changes::
+ [Incompatible changes]
* Proc#call doesn't change <code>$SAFE</code> any more. [Feature #14250]
-Random::
+[Random]
- New method::
+ [New method]
* Added Random.bytes. [Feature #4938]
-Range::
+[Range]
- New method::
+ [New method]
* Added Range#% instance method. [Feature #14697]
- Incompatible changes::
+ [Incompatible changes]
* Range#=== now uses the +#cover?+ instead of the +#include?+ method. [Feature #14575]
* Range#cover? now accepts a Range object. [Feature #14473]
* Range#step now returns an instance of the Enumerator::ArithmeticSequence
class rather than one of the Enumerator class.
-Regexp/String::
+[Regexp/String]
* Update Unicode version from 10.0.0 to 11.0.0. [Feature #14802]
@@ -278,9 +278,9 @@ Regexp/String::
* Update Emoji version from 5.0 to 11.0.0 [Feature #14802]
-RubyVM::AbstractSyntaxTree::
+[RubyVM::AbstractSyntaxTree]
- New methods::
+ [New methods]
* RubyVM::AbstractSyntaxTree.parse parses a given string and returns AST
nodes. [experimental]
@@ -291,46 +291,46 @@ RubyVM::AbstractSyntaxTree::
* RubyVM::AbstractSyntaxTree.of returns AST nodes of the given proc or
method. [experimental]
-RubyVM::
+[RubyVM]
- New method::
+ [New method]
* RubyVM.resolve_feature_path identifies the file that will be loaded by
"require(feature)". [experimental] [Feature #15230]
-String::
+[String]
* String#crypt is now deprecated. [Feature #14915]
- New features::
+ [New features]
* String#split yields each substring to the block if given. [Feature #4780]
-Struct::
+[Struct]
- Modified method::
+ [Modified method]
* Struct#to_h now accepts a block that maps keys and values to new keys and values. [Feature #15143]
- Aliased method::
+ [Aliased method]
* Struct#filter is a new alias for Struct#select. [Feature #13784]
-Time::
+[Time]
- New features::
+ [New features]
* Time.new and Time#getlocal accept a timezone object as well as
a UTC offset string. Time#+, Time#-, and Time#succ also preserve
the timezone. [Feature #14850]
-TracePoint::
+[TracePoint]
- New features::
+ [New features]
* "script_compiled" event is supported. [Feature #15287]
- New methods::
+ [New methods]
* TracePoint#parameters [Feature #14694]
@@ -338,23 +338,23 @@ TracePoint::
* TracePoint#eval_script [Feature #15287]
- Modified method::
+ [Modified method]
* TracePoint#enable accepts new keywords "target:" and
"target_line:". [Feature #15289]
=== Stdlib updates (outstanding ones only)
-BigDecimal::
+[BigDecimal]
Update to version 1.4.0. This version includes several compatibility
issues, see Compatibility issues section below for details.
- Modified method::
+ [Modified method]
* BigDecimal() accepts the new keyword "exception:" similar to Float().
- Note for the differences among recent versions::
+ [Note for the differences among recent versions]
You should want to know the differences among recent versions of bigdecimal.
Please select the suitable version of bigdecimal according to the following
@@ -371,13 +371,13 @@ BigDecimal::
* 2.0.0 will be released soon after releasing Ruby 2.6.0. This version
will not have the BigDecimal.new method.
-Bundler::
+[Bundler]
* Add Bundler to Standard Library. [Feature #12733]
* Use 1.17.2, the latest stable version.
-Coverage::
+[Coverage]
A oneshot_lines mode is added. [Feature #15022]
@@ -386,7 +386,7 @@ Coverage::
A hook for each line is fired at most once, and after it is fired
the hook flag is removed, i.e., it runs with zero overhead.
- New options::
+ [New options]
* Add +:oneshot_lines+ keyword argument to Coverage.start.
@@ -394,20 +394,20 @@ Coverage::
If +clear+ is true, it clears the counters to zero.
If +stop+ is true, it disables coverage measurement.
- New methods::
+ [New methods]
* Coverage.line_stub, which is a simple helper function that
creates the "stub" of line coverage from a given source code.
-CSV::
+[CSV]
* Upgrade to 3.0.2. This includes performance improvements especially
for writing. Writing is about 2 times faster.
See https://github.com/ruby/csv/blob/master/NEWS.md.
-ERB::
+[ERB]
- New options::
+ [New options]
* Add +:trim_mode+ and +:eoutvar+ keyword arguments to ERB.new.
Now non-keyword arguments other than the first one are softly deprecated
@@ -416,15 +416,15 @@ ERB::
* erb command's <tt>-S</tt> option is deprecated, and will be removed
in the next version.
-FileUtils::
+[FileUtils]
- New methods::
+ [New methods]
* FileUtils#cp_lr. [Feature #4189]
-Matrix::
+[Matrix]
- New methods::
+ [New methods]
* Matrix#antisymmetric?, Matrix#skew_symmetric?
@@ -436,30 +436,30 @@ Matrix::
* Vector#[]=
-Net::
+[Net]
- New options::
+ [New options]
* Add +:write_timeout+ keyword argument to Net::HTTP.new. [Feature #13396]
- New methods::
+ [New methods]
* Add Net::HTTP#write_timeout and Net::HTTP#write_timeout=. [Feature #13396]
- New constant::
+ [New constant]
* Add Net::HTTPClientException to deprecate Net::HTTPServerException,
whose name is misleading. [Bug #14688]
-NKF::
+[NKF]
* Upgrade to nkf v2.1.5
-Psych::
+[Psych]
* Upgrade to Psych 3.1.0
-RDoc::
+[RDoc]
* Become about 2 times faster.
@@ -478,12 +478,12 @@ RDoc::
* Fix many parsing bugs.
-REXML::
+[REXML]
* Upgrade to REXML 3.1.9.
See https://github.com/ruby/rexml/blob/master/NEWS.md.
- Improved some XPath implementations::
+ [Improved some XPath implementations]
* <code>concat()</code> function: Stringify all arguments before concatenating.
@@ -493,7 +493,7 @@ REXML::
* Support <code>"*:#{ELEMENT_NAME}"</code> syntax in XPath 2.0.
- Fixed some XPath implementations::
+ [Fixed some XPath implementations]
* <code>"//#{ELEMENT_NAME}[#{POSITION}]"</code> case
@@ -517,14 +517,14 @@ REXML::
* <code>"name(#{NODE_SET})"</code> case
-RSS::
+[RSS]
- New options::
+ [New options]
* RSS::Parser.parse now accepts options as Hash. +:validate+ ,
+:ignore_unknown_element+ , +:parser_class+ options are available.
-RubyGems::
+[RubyGems]
* Upgrade to RubyGems 3.0.1
@@ -532,32 +532,32 @@ RubyGems::
* https://blog.rubygems.org/2018/12/23/3.0.1-released.html
-Set::
+[Set]
- Aliased method::
+ [Aliased method]
* Set#filter! is a new alias for Set#select!. [Feature #13784]
-URI::
+[URI]
- New constant::
+ [New constant]
* Add URI::File to handle the file URI scheme. [Feature #14035]
=== Compatibility issues (excluding feature bug fixes)
-Dir::
+[Dir]
* Dir.glob with <code>'\0'</code>-separated pattern list will be deprecated,
and is now warned. [Feature #14643]
-File::
+[File]
* File.read, File.binread, File.write, File.binwrite, File.foreach, and
File.readlines do not invoke external commands even if the path starts
with the pipe character <code>'|'</code>. [Feature #14245]
-Object::
+[Object]
* Object#=~ is deprecated. [Feature #15231]
@@ -580,7 +580,7 @@ Object::
* thwait
* tracer
-BigDecimal::
+[BigDecimal]
* The following methods are removed.
@@ -595,7 +595,7 @@ BigDecimal::
* BigDecimal.new will be removed in version 2.0.
-Pathname::
+[Pathname]
* Pathname#read, Pathname#binread, Pathname#write, Pathname#binwrite,
Pathname#each_line and Pathname#readlines do not invoke external
@@ -650,12 +650,12 @@ Pathname::
in their names. This eliminates the burden of each teeny upgrade on the
platform that users need to rebuild every extension library.
- Before::
+ [Before]
* libruby.2.6.0.dylib
* libruby.2.6.dylib -> libruby.2.6.0.dylib
* libruby.dylib -> libruby.2.6.0.dylib
- After::
+ [After]
* libruby.2.6.dylib
* libruby.dylib -> libruby.2.6.dylib
diff --git a/doc/NEWS-2.7.0 b/doc/NEWS-2.7.0
new file mode 100644
index 0000000000..3e6b98c1fd
--- /dev/null
+++ b/doc/NEWS-2.7.0
@@ -0,0 +1,826 @@
+# -*- rdoc -*-
+
+= NEWS for Ruby 2.7.0
+
+This document is a list of user visible feature changes made between
+releases except for bug fixes.
+
+Note that each entry is kept so brief that no reason behind or reference
+information is supplied with. For a full list of changes with all
+sufficient information, see the ChangeLog file or Redmine
+(e.g. <tt>https://bugs.ruby-lang.org/issues/$FEATURE_OR_BUG_NUMBER</tt>).
+
+== Changes since the 2.6.0 release
+
+=== Language changes
+
+==== Pattern matching
+
+* Pattern matching is introduced as an experimental feature. [Feature #14912]
+
+ case [0, [1, 2, 3]]
+ in [a, [b, *c]]
+ p a #=> 0
+ p b #=> 1
+ p c #=> [2, 3]
+ end
+
+ case {a: 0, b: 1}
+ in {a: 0, x: 1}
+ :unreachable
+ in {a: 0, b: var}
+ p var #=> 1
+ end
+
+ case -1
+ in 0 then :unreachable
+ in 1 then :unreachable
+ end #=> NoMatchingPatternError
+
+ json = <<END
+ {
+ "name": "Alice",
+ "age": 30,
+ "children": [{ "name": "Bob", "age": 2 }]
+ }
+ END
+
+ JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: name, age: age}]}
+
+ p name #=> "Bob"
+ p age #=> 2
+
+ JSON.parse(json, symbolize_names: true) in {name: "Alice", children: [{name: "Charlie", age: age}]}
+ #=> NoMatchingPatternError
+
+* See the following slides for more details:
+ * https://speakerdeck.com/k_tsj/pattern-matching-new-feature-in-ruby-2-dot-7
+ * Note that the slides are slightly obsolete.
+
+* The warning against pattern matching can be suppressed with
+ {-W:no-experimental option}[#label-Warning+option].
+
+==== The spec of keyword arguments is changed towards 3.0
+
+* Automatic conversion of keyword arguments and positional arguments is
+ deprecated, and conversion will be removed in Ruby 3. [Feature #14183]
+
+ * When a method call passes a Hash at the last argument, and when it
+ passes no keywords, and when the called method accepts keywords,
+ a warning is emitted. To continue treating the hash as keywords,
+ add a double splat operator to avoid the warning and ensure
+ correct behavior in Ruby 3.
+
+ def foo(key: 42); end; foo({key: 42}) # warned
+ def foo(**kw); end; foo({key: 42}) # warned
+ def foo(key: 42); end; foo(**{key: 42}) # OK
+ def foo(**kw); end; foo(**{key: 42}) # OK
+
+ * When a method call passes keywords to a method that accepts keywords,
+ but it does not pass enough required positional arguments, the
+ keywords are treated as a final required positional argument, and a
+ warning is emitted. Pass the argument as a hash instead of keywords
+ to avoid the warning and ensure correct behavior in Ruby 3.
+
+ def foo(h, **kw); end; foo(key: 42) # warned
+ def foo(h, key: 42); end; foo(key: 42) # warned
+ def foo(h, **kw); end; foo({key: 42}) # OK
+ def foo(h, key: 42); end; foo({key: 42}) # OK
+
+ * When a method accepts specific keywords but not a keyword splat, and
+ a hash or keywords splat is passed to the method that includes both
+ Symbol and non-Symbol keys, the hash will continue to be split, and
+ a warning will be emitted. You will need to update the calling code
+ to pass separate hashes to ensure correct behavior in Ruby 3.
+
+ def foo(h={}, key: 42); end; foo("key" => 43, key: 42) # warned
+ def foo(h={}, key: 42); end; foo({"key" => 43, key: 42}) # warned
+ def foo(h={}, key: 42); end; foo({"key" => 43}, key: 42) # OK
+
+ * If a method does not accept keywords, and is called with keywords,
+ the keywords are still treated as a positional hash, with no warning.
+ This behavior will continue to work in Ruby 3.
+
+ def foo(opt={}); end; foo( key: 42 ) # OK
+
+* Non-symbols are allowed as keyword argument keys if the method accepts
+ arbitrary keywords. [Feature #14183]
+
+ * Non-Symbol keys in a keyword arguments hash were prohibited in 2.6.0,
+ but are now allowed again. [Bug #15658]
+
+ def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1}
+
+* <code>**nil</code> is allowed in method definitions to explicitly mark
+ that the method accepts no keywords. Calling such a method with keywords
+ will result in an ArgumentError. [Feature #14183]
+
+ def foo(h, **nil); end; foo(key: 1) # ArgumentError
+ def foo(h, **nil); end; foo(**{key: 1}) # ArgumentError
+ def foo(h, **nil); end; foo("str" => 1) # ArgumentError
+ def foo(h, **nil); end; foo({key: 1}) # OK
+ def foo(h, **nil); end; foo({"str" => 1}) # OK
+
+* Passing an empty keyword splat to a method that does not accept keywords
+ no longer passes an empty hash, unless the empty hash is necessary for
+ a required parameter, in which case a warning will be emitted. Remove
+ the double splat to continue passing a positional hash. [Feature #14183]
+
+ h = {}; def foo(*a) a end; foo(**h) # []
+ h = {}; def foo(a) a end; foo(**h) # {} and warning
+ h = {}; def foo(*a) a end; foo(h) # [{}]
+ h = {}; def foo(a) a end; foo(h) # {}
+
+* Above warnings can be suppressed also with {-W:no-deprecated option}[#label-Warning+option].
+
+==== Numbered parameters
+
+* Numbered parameters as default block parameters are introduced. [Feature #4475]
+
+ [1, 2, 10].map { _1.to_s(16) } #=> ["1", "2", "a"]
+ [[1, 2], [3, 4]].map { _1 + _2 } #=> [3, 7]
+
+ You can still define a local variable named +_1+ and so on,
+ and that is honored when present, but renders a warning.
+
+ _1 = 0 #=> warning: `_1' is reserved for numbered parameter; consider another name
+ [1].each { p _1 } # prints 0 instead of 1
+
+==== proc/lambda without block is deprecated
+
+* Proc.new and Kernel#proc with no block in a method called with a block will
+ now display a warning.
+
+ def foo
+ proc
+ end
+ foo { puts "Hello" } #=> warning: Capturing the given block using Kernel#proc is deprecated; use `&block` instead
+
+ This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
+
+* Kernel#lambda with no block in a method called with a block raises an exception.
+
+ def bar
+ lambda
+ end
+ bar { puts "Hello" } #=> tried to create Proc object without a block (ArgumentError)
+
+==== Other miscellaneous changes
+
+* A beginless range is experimentally introduced. It might be useful
+ in +case+, new call-sequence of the <code>Comparable#clamp</code>,
+ constants and DSLs. [Feature #14799]
+
+ ary[..3] # identical to ary[0..3]
+
+ case RUBY_VERSION
+ when ..."2.4" then puts "EOL"
+ # ...
+ end
+
+ age.clamp(..100)
+
+ where(sales: ..100)
+
+* Setting <code>$;</code> to a non-nil value will now display a warning. [Feature #14240]
+ This includes the usage in String#split.
+ This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
+
+* Setting <code>$,</code> to a non-nil value will now display a warning. [Feature #14240]
+ This includes the usage in Array#join.
+ This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
+
+* Quoted here-document identifiers must end within the same line.
+
+ <<"EOS
+ " # This had been warned since 2.4; Now it raises a SyntaxError
+ EOS
+
+* The flip-flop syntax deprecation is reverted. [Feature #5400]
+
+* Comment lines can be placed between fluent dot now.
+
+ foo
+ # .bar
+ .baz # => foo.baz
+
+* Calling a private method with a literal +self+ as the receiver
+ is now allowed. [Feature #11297] [Feature #16123]
+
+* Modifier rescue now operates the same for multiple assignment as single
+ assignment. [Bug #8279]
+
+ a, b = raise rescue [1, 2]
+ # Previously parsed as: (a, b = raise) rescue [1, 2]
+ # Now parsed as: a, b = (raise rescue [1, 2])
+
+* +yield+ in singleton class syntax will now display a warning. This behavior
+ will soon be deprecated. [Feature #15575].
+
+ def foo
+ class << Object.new
+ yield #=> warning: `yield' in class syntax will not be supported from Ruby 3.0. [Feature #15575]
+ end
+ end
+ foo { p :ok }
+
+ This warning can be suppressed with {-W:no-deprecated option}[#label-Warning+option].
+
+* Argument forwarding by <code>(...)</code> is introduced. [Feature #16253]
+
+ def foo(...)
+ bar(...)
+ end
+
+ All arguments to +foo+ are forwarded to +bar+, including keyword and
+ block arguments.
+ Note that the parentheses are mandatory. <code>bar ...</code> is parsed
+ as an endless range.
+
+* Access and setting of <code>$SAFE</code> will now always display a warning.
+ <code>$SAFE</code> will become a normal global variable in Ruby 3.0. [Feature #16131]
+
+* <code>Object#{taint,untaint,trust,untrust}</code> and related functions in the C-API
+ no longer have an effect (all objects are always considered untainted), and will now
+ display a warning in verbose mode. This warning will be disabled even in non-verbose mode in
+ Ruby 3.0, and the methods and C functions will be removed in Ruby 3.2. [Feature #16131]
+
+* Refinements take place at Object#method and Module#instance_method. [Feature #15373]
+
+=== Command line options
+
+==== Warning option
+
+The +-W+ option has been extended with a following +:+, to manage categorized
+warnings. [Feature #16345] [Feature #16420]
+
+* To suppress deprecation warnings:
+
+ $ ruby -e '$; = ""'
+ -e:1: warning: `$;' is deprecated
+
+ $ ruby -W:no-deprecated -e '$; = //'
+
+* It works with the +RUBYOPT+ environment variable:
+
+ $ RUBYOPT=-W:no-deprecated ruby -e '$; = //'
+
+* To suppress experimental feature warnings:
+
+ $ ruby -e '0 in a'
+ -e:1: warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!
+
+ $ ruby -W:no-experimental -e '0 in a'
+
+* To suppress both by using +RUBYOPT+, set space separated values:
+
+ $ RUBYOPT='-W:no-deprecated -W:no-experimental' ruby -e '($; = "") in a'
+
+See also Warning in {Core classes updates}[#label-Core+classes+updates+-28outstanding+ones+only-29].
+
+=== Core classes updates (outstanding ones only)
+
+[Array]
+
+ [New methods]
+
+ * Added Array#intersection. [Feature #16155]
+
+ * Added Array#minmax, with a faster implementation than Enumerable#minmax. [Bug #15929]
+
+[Comparable]
+
+ [Modified method]
+
+ * Comparable#clamp now accepts a Range argument. [Feature #14784]
+
+ -1.clamp(0..2) #=> 0
+ 1.clamp(0..2) #=> 1
+ 3.clamp(0..2) #=> 2
+ # With beginless and endless ranges:
+ -1.clamp(0..) #=> 0
+ 3.clamp(..2) #=> 2
+
+
+[Complex]
+
+ [New method]
+
+ * Added Complex#<=>.
+ So <code>0 <=> 0i</code> will not raise NoMethodError. [Bug #15857]
+
+[Dir]
+
+ [Modified methods]
+
+ * Dir.glob and Dir.[] no longer allow NUL-separated glob pattern.
+ Use Array instead. [Feature #14643]
+
+[Encoding]
+
+ [New encoding]
+
+ * Added new encoding CESU-8. [Feature #15931]
+
+[Enumerable]
+
+ [New methods]
+
+ * Added Enumerable#filter_map. [Feature #15323]
+
+ [1, 2, 3].filter_map {|x| x.odd? ? x.to_s : nil } #=> ["1", "3"]
+
+ * Added Enumerable#tally. [Feature #11076]
+
+ ["A", "B", "C", "B", "A"].tally #=> {"A"=>2, "B"=>2, "C"=>1}
+
+[Enumerator]
+
+ [New methods]
+
+ * Added Enumerator.produce to generate an Enumerator from any custom
+ data transformation. [Feature #14781]
+
+ require "date"
+ dates = Enumerator.produce(Date.today, &:succ) #=> infinite sequence of dates
+ dates.detect(&:tuesday?) #=> next Tuesday
+
+ * Added Enumerator::Lazy#eager that generates a non-lazy enumerator
+ from a lazy enumerator. [Feature #15901]
+
+ a = %w(foo bar baz)
+ e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager
+ p e.class #=> Enumerator
+ p e.map {|x| x + "?" } #=> ["FOO!?", "BAR!?", "BAZ!?"]
+
+ * Added Enumerator::Yielder#to_proc so that a Yielder object
+ can be directly passed to another method as a block
+ argument. [Feature #15618]
+
+[Fiber]
+
+ [New method]
+
+ * Added Fiber#raise that behaves like Fiber#resume but raises an
+ exception on the resumed fiber. [Feature #10344]
+
+[File]
+
+ [Modified method]
+
+ * File.extname now returns a dot string for names ending with a dot on
+ non-Windows platforms. [Bug #15267]
+
+ File.extname("foo.") #=> "."
+
+[FrozenError]
+
+ [New method]
+
+ * Added FrozenError#receiver to return the frozen object on which
+ modification was attempted. To set this object when raising
+ FrozenError in Ruby code, FrozenError.new accepts a +:receiver+
+ option. [Feature #15751]
+
+[GC]
+
+ [New method]
+
+ * Added GC.compact method for compacting the heap.
+ This function compacts live objects in the heap so that fewer pages may
+ be used, and the heap may be more CoW (copy-on-write) friendly. [Feature #15626]
+
+ Details on the algorithm and caveats can be found here:
+ https://bugs.ruby-lang.org/issues/15626
+
+[IO]
+
+ [New method]
+
+ * Added IO#set_encoding_by_bom to check the BOM and set the external
+ encoding. [Bug #15210]
+
+[Integer]
+
+ [Modified method]
+
+ * Integer#[] now supports range operations. [Feature #8842]
+
+ 0b01001101[2, 4] #=> 0b0011
+ 0b01001100[2..5] #=> 0b0011
+ 0b01001100[2...6] #=> 0b0011
+ # ^^^^
+
+[Method]
+
+ [Modified method]
+
+ * Method#inspect shows more information. [Feature #14145]
+
+[Module]
+
+ [New methods]
+
+ * Added Module#const_source_location to retrieve the location where a
+ constant is defined. [Feature #10771]
+
+ * Added Module#ruby2_keywords for marking a method as passing keyword
+ arguments through a regular argument splat, useful when delegating
+ all arguments to another method in a way that can be backwards
+ compatible with older Ruby versions. [Bug #16154]
+
+ [Modified methods]
+
+ * Module#autoload? now takes an +inherit+ optional argument, like
+ Module#const_defined?. [Feature #15777]
+
+ * Module#name now always returns a frozen String. The returned String is
+ always the same for a given Module. This change is
+ experimental. [Feature #16150]
+
+[NilClass / TrueClass / FalseClass]
+
+ [Modified methods]
+
+ * NilClass#to_s, TrueClass#to_s, and FalseClass#to_s now always return a
+ frozen String. The returned String is always the same for each of these
+ values. This change is experimental. [Feature #16150]
+
+[ObjectSpace::WeakMap]
+
+ [Modified method]
+
+ * ObjectSpace::WeakMap#[]= now accepts special objects as either key or
+ values. [Feature #16035]
+
+[Proc]
+
+ [New method]
+
+ * Added Proc#ruby2_keywords for marking the proc as passing keyword
+ arguments through a regular argument splat, useful when delegating
+ all arguments to another method or proc in a way that can be backwards
+ compatible with older Ruby versions. [Feature #16404]
+
+[Range]
+
+ [New method]
+
+ * Added Range#minmax, with a faster implementation than Enumerable#minmax.
+ It returns a maximum that now corresponds to Range#max. [Bug #15807]
+
+ [Modified method]
+
+ * Range#=== now uses Range#cover? for String arguments, too (in Ruby 2.6, it was
+ changed from Range#include? for all types except strings). [Bug #15449]
+
+
+[RubyVM]
+
+ [Removed method]
+
+ * +RubyVM.resolve_feature_path+ moved to
+ <code>$LOAD_PATH.resolve_feature_path</code>. [Feature #15903] [Feature #15230]
+
+[String]
+
+ [Unicode]
+
+ * Update Unicode version and Emoji version from 11.0.0 to
+ 12.0.0. [Feature #15321]
+
+ * Update Unicode version to 12.1.0, adding support for
+ U+32FF SQUARE ERA NAME REIWA. [Feature #15195]
+
+ * Update Unicode Emoji version to 12.1. [Feature #16272]
+
+[Symbol]
+
+ [New methods]
+
+ * Added Symbol#start_with? and Symbol#end_with? methods. [Feature #16348]
+
+[Time]
+
+ [New methods]
+
+ * Added Time#ceil method. [Feature #15772]
+
+ * Added Time#floor method. [Feature #15653]
+
+ [Modified method]
+
+ * Time#inspect is separated from Time#to_s and it shows
+ the time's sub second. [Feature #15958]
+
+[UnboundMethod]
+
+ [New method]
+
+ * Added UnboundMethod#bind_call method. [Feature #15955]
+
+ <code>umethod.bind_call(obj, ...)</code> is semantically equivalent
+ to <code>umethod.bind(obj).call(...)</code>. This idiom is used in
+ some libraries to call a method that is overridden. The added
+ method does the same without allocation of an intermediate Method
+ object.
+
+ class Foo
+ def add_1(x)
+ x + 1
+ end
+ end
+ class Bar < Foo
+ def add_1(x) # override
+ x + 2
+ end
+ end
+
+ obj = Bar.new
+ p obj.add_1(1) #=> 3
+ p Foo.instance_method(:add_1).bind(obj).call(1) #=> 2
+ p Foo.instance_method(:add_1).bind_call(obj, 1) #=> 2
+
+[Warning]
+
+ [New methods]
+
+ * Added Warning.[] and Warning.[]= to manage emitting/suppressing
+ some categories of warnings. [Feature #16345] [Feature #16420]
+
+[$LOAD_PATH]
+
+ [New method]
+
+ * Added <code>$LOAD_PATH.resolve_feature_path</code>. [Feature #15903] [Feature #15230]
+
+=== Stdlib updates (outstanding ones only)
+
+[Bundler]
+
+ * Upgrade to Bundler 2.1.2.
+ See https://github.com/bundler/bundler/releases/tag/v2.1.2
+
+[CGI]
+
+ * CGI.escapeHTML becomes 2~5x faster when there is at least one escaped character.
+ See https://github.com/ruby/ruby/pull/2226
+
+[CSV]
+
+ * Upgrade to 3.1.2.
+ See https://github.com/ruby/csv/blob/master/NEWS.md.
+
+[Date]
+
+ * Date.jisx0301, Date#jisx0301, and Date.parse support the new Japanese
+ era. [Feature #15742]
+
+[Delegator]
+
+ * Object#DelegateClass accepts a block and module_evals it in the context
+ of the returned class, similar to Class.new and Struct.new.
+
+[ERB]
+
+ * Prohibit marshaling ERB instance.
+
+[IRB]
+
+ * Introduce syntax highlighting inspired by the Pry gem to Binding#irb
+ source lines, REPL input, and inspect output of some core-class objects.
+
+ * Introduce multiline editing mode provided by Reline.
+
+ * Show documentation when completion.
+
+ * Enable auto indent and save/load history by default.
+
+[JSON]
+
+ * Upgrade to 2.3.0.
+
+[Net::FTP]
+
+ * Add Net::FTP#features to check available features, and Net::FTP#option to
+ enable/disable each of them. [Feature #15964]
+
+[Net::HTTP]
+
+ * Add +ipaddr+ optional parameter to Net::HTTP#start to replace the address for
+ the TCP/IP connection. [Feature #5180]
+
+[Net::IMAP]
+
+ * Add Server Name Indication (SNI) support. [Feature #15594]
+
+[open-uri]
+
+ * Warn open-uri's "open" method at Kernel.
+ Use URI.open instead. [Misc #15893]
+
+ * The default charset of "text/*" media type is UTF-8 instead of
+ ISO-8859-1. [Bug #15933]
+
+[OptionParser]
+
+ * Now show "Did you mean?" for unknown options. [Feature #16256]
+
+ test.rb:
+
+ require "optparse"
+ OptionParser.new do |opts|
+ opts.on("-f", "--foo", "foo") {|v| }
+ opts.on("-b", "--bar", "bar") {|v| }
+ opts.on("-c", "--baz", "baz") {|v| }
+ end.parse!
+
+ example:
+
+ $ ruby test.rb --baa
+ Traceback (most recent call last):
+ test.rb:7:in `<main>': invalid option: --baa (OptionParser::InvalidOption)
+ Did you mean? baz
+ bar
+
+[Pathname]
+
+ * Pathname.glob now delegates 3 arguments to Dir.glob
+ to accept +base+ keyword. [Feature #14405]
+
+[Racc]
+
+ * Merge 1.4.15 from upstream repository and added cli of racc.
+
+[Reline]
+
+ * New stdlib that is compatible with the readline stdlib but is
+ implemented in pure Ruby. It also provides a multiline editing mode.
+
+[REXML]
+
+ * Upgrade to 3.2.3.
+ See https://github.com/ruby/rexml/blob/master/NEWS.md.
+
+[RSS]
+
+ * Upgrade to RSS 0.2.8.
+ See https://github.com/ruby/rss/blob/master/NEWS.md.
+
+[RubyGems]
+
+ * Upgrade to RubyGems 3.1.2.
+ * https://github.com/rubygems/rubygems/releases/tag/v3.1.0
+ * https://github.com/rubygems/rubygems/releases/tag/v3.1.1
+ * https://github.com/rubygems/rubygems/releases/tag/v3.1.2
+
+[StringScanner]
+
+ * Upgrade to 1.0.3.
+ See https://github.com/ruby/strscan/blob/master/NEWS.md.
+
+=== Compatibility issues (excluding feature bug fixes)
+
+* The following libraries are no longer bundled gems.
+ Install corresponding gems to use these features.
+ * CMath (cmath gem)
+ * Scanf (scanf gem)
+ * Shell (shell gem)
+ * Synchronizer (sync gem)
+ * ThreadsWait (thwait gem)
+ * E2MM (e2mmap gem)
+
+[Proc]
+ * The Proc#to_s format was changed. [Feature #16101]
+
+[Range]
+ * Range#minmax used to iterate on the range to determine the maximum.
+ It now uses the same algorithm as Range#max. In rare cases (e.g.
+ ranges of Floats or Strings), this may yield different results. [Bug #15807]
+
+=== Stdlib compatibility issues (excluding feature bug fixes)
+
+* Promote stdlib to default gems
+ * The following default gems were published on rubygems.org
+ * benchmark
+ * cgi
+ * delegate
+ * getoptlong
+ * net-pop
+ * net-smtp
+ * open3
+ * pstore
+ * readline
+ * readline-ext
+ * singleton
+ * The following default gems were only promoted at ruby-core,
+ but not yet published on rubygems.org.
+ * monitor
+ * observer
+ * timeout
+ * tracer
+ * uri
+ * yaml
+* The <tt>did_you_mean</tt> gem has been promoted up to a default gem from a bundled gem
+
+[pathname]
+
+ * Kernel#Pathname when called with a Pathname argument now returns
+ the argument instead of creating a new Pathname. This is more
+ similar to other Kernel methods, but can break code that modifies
+ the return value and expects the argument not to be modified.
+
+[profile.rb, Profiler__]
+
+ * Removed from standard library. It was unmaintained since Ruby 2.0.0.
+
+=== C API updates
+
+* Many <code>*_kw</code> functions have been added for setting whether
+ the final argument being passed should be treated as keywords. You
+ may need to switch to these functions to avoid keyword argument
+ separation warnings, and to ensure correct behavior in Ruby 3.
+
+* The <code>:</code> character in rb_scan_args format string is now
+ treated as keyword arguments. Passing a positional hash instead of
+ keyword arguments will emit a deprecation warning.
+
+* C API declarations with +ANYARGS+ are changed not to use +ANYARGS+.
+ See https://github.com/ruby/ruby/pull/2404
+
+=== Implementation improvements
+
+[Fiber]
+
+ * Allow selecting different coroutine implementations by using
+ +--with-coroutine=+, e.g.
+
+ $ ./configure --with-coroutine=ucontext
+ $ ./configure --with-coroutine=copy
+
+ * Replace previous stack cache with fiber pool cache. The fiber pool
+ allocates many stacks in a single memory region. Stack allocation
+ becomes O(log N) and fiber creation is amortized O(1). Around 10x
+ performance improvement was measured in micro-benchmarks.
+ https://github.com/ruby/ruby/pull/2224
+
+[File]
+ * File.realpath now uses realpath(3) on many platforms, which can
+ significantly improve performance. [Feature #15797]
+
+[Hash]
+ * Change data structure of small Hash objects. [Feature #15602]
+
+[Monitor]
+ * Monitor class is written in C-extension. [Feature #16255]
+
+[Thread]
+
+ * VM stack memory allocation is now combined with native thread stack,
+ improving thread allocation performance and reducing allocation related
+ failures. Around 10x performance improvement was measured in micro-benchmarks.
+
+[JIT]
+
+ * JIT-ed code is recompiled to less-optimized code when an optimization assumption is invalidated.
+
+ * Method inlining is performed when a method is considered as pure.
+ This optimization is still experimental and many methods are NOT considered as pure yet.
+
+ * The default value of +--jit-max-cache+ is changed from 1,000 to 100.
+
+ * The default value of +--jit-min-calls+ is changed from 5 to 10,000.
+
+[RubyVM]
+
+ * Per-call-site method cache, which has been there since around 1.9, was
+ improved: cache hit rate raised from 89% to 94%.
+ See https://github.com/ruby/ruby/pull/2583
+
+[RubyVM::InstructionSequence]
+
+ * RubyVM::InstructionSequence#to_binary method generates compiled binary.
+ The binary size is reduced. [Feature #16163]
+
+=== Miscellaneous changes
+
+* Support for IA64 architecture has been removed. Hardware for testing was
+ difficult to find, native fiber code is difficult to implement, and it added
+ non-trivial complexity to the interpreter. [Feature #15894]
+
+* Require compilers to support C99. [Misc #15347]
+
+ * Details of our dialect: https://bugs.ruby-lang.org/projects/ruby-master/wiki/C99
+
+* Ruby's upstream repository is changed from Subversion to Git.
+
+ * https://git.ruby-lang.org/ruby.git
+
+ * RUBY_REVISION class is changed from Integer to String.
+
+ * RUBY_DESCRIPTION includes Git revision instead of Subversion's one.
+
+* Support built-in methods in Ruby with the <code>_\_builtin_</code> syntax. [Feature #16254]
+
+ Some methods are defined in *.rb (such as trace_point.rb).
+ For example, it is easy to define a method which accepts keyword arguments.
diff --git a/doc/contributing.rdoc b/doc/contributing.rdoc
index 68dda66e46..d7395627ca 100644
--- a/doc/contributing.rdoc
+++ b/doc/contributing.rdoc
@@ -27,10 +27,10 @@ on your ticket.
stable release. See
{Downloading Ruby}[https://www.ruby-lang.org/en/downloads/].
* Look to see if anyone already reported your issue, try
- {searching on redmine}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues]
+ {searching on redmine}[https://bugs.ruby-lang.org/projects/ruby-master/issues]
for your problem.
* If you can't find a ticket addressing your issue,
- {create a new one}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues/new].
+ {create a new one}[https://bugs.ruby-lang.org/projects/ruby-master/issues/new].
* Choose the target version, usually current. Bugs will be first fixed in the
current release and then {backported}[rdoc-label:label-Backport+Requests].
* Fill in the Ruby version you're using when experiencing this issue
@@ -82,7 +82,7 @@ The current active platform maintainers are as follows:
Kenta Murata (mrkn)
[OpenBSD]
Jeremy Evans (jeremyevans0)
-[cygwin, bcc32, djgpp, wince, ...]
+[cygwin, ...]
none. (Maintainer WANTED)
== Reporting Security Issues
@@ -116,7 +116,7 @@ these? Quite a bit, actually:
When a bug report goes for a while without any feedback, it goes to the bug
graveyard which is unfortunate. If you check the {issues
-list}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues] you will find lots
+list}[https://bugs.ruby-lang.org/projects/ruby-master/issues] you will find lots
of delinquent bugs that require attention.
You can help by verifying the existing tickets, try to reproduce the reported
@@ -156,7 +156,7 @@ If there's a new feature that you want to see added to Ruby, you will need to
write a convincing proposal and patch to implement the feature.
For new features in CRuby, use the {'Feature'
-tracker}[https://bugs.ruby-lang.org/projects/ruby-trunk/issues?set_filter=1&tracker_id=2]
+tracker}[https://bugs.ruby-lang.org/projects/ruby-master/issues?set_filter=1&tracker_id=2]
on ruby-master. For non-CRuby dependent features, features that would apply to
alternate Ruby implementations such as JRuby and Rubinius, use the {CommonRuby
tracker}[https://bugs.ruby-lang.org/projects/common-ruby].
@@ -195,25 +195,6 @@ A good template for a feature proposal should look something like this:
[See also]
Links to the other related resources
-=== Slideshow
-
-At the Ruby Developer Meeting in Japan, committers discuss Feature Proposals together in Tokyo. We will judge proposals and then accept, reject, or give feedback for them.
-If you have a stalled proposal, making a slide to submit is good way to get feedback.
-
-Slides should be:
-
-* One-page slide
-* Include a corresponding ticket number
-* MUST include a figure and/or short example code
-* SHOULD have less sentence in natural language (try to write less than 140 characters)
-* It is RECOMMENDED to itemize: motivation/use case, proposal, pros/cons, corner case
-* PDF or Image (Web browsers can show it)
-
-Please note:
-
-* Even if the proposal is generally acceptable, it won't be accepted without writing corner cases in the ticket
-* Slide's example: DevelopersMeeting20130727Japan
-
== Backport Requests
When a new version of Ruby is released, it starts at patch level 0 (p0), and
@@ -260,8 +241,8 @@ run tests.
* autoconf - 2.67 or later, preferably 2.69.
* bison - 2.0 or later, preferably 3.4.
* gperf - 3.0.3 or later, preferably 3.1.
-* ruby - Ruby itself is prerequisite in order to build Ruby from source. It
- can be 1.8.
+* ruby - Ruby itself is prerequisite in order to build Ruby from source.
+ You should use [a maintained version of Ruby](https://www.ruby-lang.org/en/downloads/).
You should also have access to development headers for the following
libraries, but these are not required:
diff --git a/doc/contributors.rdoc b/doc/contributors.rdoc
deleted file mode 100644
index 7c3722032b..0000000000
--- a/doc/contributors.rdoc
+++ /dev/null
@@ -1,793 +0,0 @@
-= Contributors to Ruby
-
-The following list might be incomplete. Feel free to add your name if your
-patch was accepted into Ruby.
-
-== A
-
-Ayumu AIZAWA (ayumin)
-* committer
-
-AKIYOSHI, Masamichi (akiyoshi)
-* committer
-* He had maintained the VMS support on 2003-2004.
-
-Muhammad Ali
-* wrote rdoc for Fiber
-
-Minero Aoki (aamine)
-* committer
-* He is the maintainer of:
- * fileutils
- * net/http, net/https
- * net/pop
- * net/smtp
- * racc
- * ripper
- * strscan
-
-Wakou Aoyama (wakou)
-* committer
-* He was the maintainer of some standard libraries.
-
-Koji Arai
-* committer
-
-arton
-* He is the distributor of ActiveScriptRuby and experimental 1.9.0-x installers for win32.
-* Wrote patches for win32ole, gc.c, tmpdir.rb
-
-Sergey Avseyev
-* Added IO#pread and IO#pwrite.
-
-== B
-
-Daniel Berger
-* a patch for irb
-* documentation
-* He wrote forwardable.rb
-
-David Black (dblack)
-* committer
-* He is the maintainer of scanf
-
-Ken Bloom
-* a patch for REXML.
-
-Oliver M. Bolzer
-* a patch for soap
-
-Alexey Borzenkov
-* a patch for mkmf.rb
-
-Evan Brodie
-* a patch for documentation of Float#round
-
-Richard Brown
-* a patch for configure.in
-
-Dirkjan Bussink
-* a patch for date.rb
-
-Daniel Bovensiepen
-* documentation
-* a patch for irb
-
-== C
-
-Brian Candler
-* a patch for configure.in, net/telnet
-
-keith cascio
-* a patch for optparse.rb
-
-Frederick Cheung
-* a patch for test/ruby/test_symbol.rb
-
-Christoph
-* patches for set.rb
-
-Sean Chittenden
-* patches for net/http, cgi
-
-William D. Clinger
-* ruby_strtod is based on his paper.
-
-== D
-
-Ryan Davis (ryan)
-* committer
-* He wrote and is the maintainer of miniunit
-
-Guy Decoux (ts)
-* committer
-
-Zach Dennis
-
-Martin Duerst (duerst)
-* committer
-* M17N
-
-Paul Duncan
-* patches for rdoc
-
-Alexander Dymo
-* a patch for lib/benchmark.rb
-
-== E
-
-Yusuke Endoh (mame)
-* committer
-* He wrote and is the maintainer of base64 library (1.9)
-* did much upon YARV compiler.
-
-erlercw
-* wrote Integer::gcd2
-
-== F
-
-Frank S.Fejes
-* a patch for net/pop
-
-Fundakowski Feldman
-* a patch for process.c
-
-Mauricio Fernandez
-* patches for parse.y
-
-David Flanagan (davidflanagan)
-* committer
-* M17N
-
-Takeyuki Fujioka (xibbar)
-* committer
-* He is the maintainer of cgi/*
-
-FUKUMOTO, Atsushi
-* a patch for tracer.rb
-
-Shota Fukumori (sorah)
-* committer
-* #4415 parallel unit/test
-
-Tadayoshi Funaba (tadf)
-* committer
-* He wrote and is the maintainer of
- * date
- * parsedate (1.8)
-* He ported rational.rb and complex.rb, which 1.8 contains, into rational.c and complex.c of 1.9.
-
-== G
-
-David M. Gay
-* ruby_strtod
-
-Florian Gilcher
-* documentation
-
-GOTOU, Kentaro (gotoken)
-* committer
-* He wrote benchmark.rb
-* He is the maintainer of:
- * benchmark.rb
- * open3
-
-GOTOU, Yuuzou (gotoyuzo)
-* committer
-
-James Edward Gray II (jeg2)
-* committer
-* He wrote the faster implementation of CSV and is the maintainer of csv.
-* Wrote documentation for rdoc
-
-== H
-
-Phil Hagelberg
-* patch for ruby-mode.el's documentation.
-
-Kirk Haines (wyhaines)
-* committer
-* the maintainer of ruby_1_8_6 branch
-
-Shinichiro Hamaji
-* fixed memory leaks (marshal.c, string.c)
-
-Shin-ichiro HARA
-* the developer and the sysop of ruby-{dev,list,core,talk} archive.
-* a patch for numeric.c
-
-Chris Heath (traumdeutung)
-* a patch for proc.c
-
-HIROKAWA Hisashi
-* fixed socket/socket.c
-
-Daniel Hob
-* He wrote:
- * SMTP-TLS support for net/smtp.
- * POP3S support
-
-Eric Hodel (drbrain)
-* committer
-* He is the maintainer of:
- * rdoc
- * ri
- * rubygems
-
-Erik Hollensbe
-* a patch for delegate.rb
-
-Johan Holmberg
-* a patch for dir.c
-* documentation
-
-Erik Huelsmann
-
-Dae San Hwang
-* built a continuous integration environment on OpenSolaris.
-
-== I
-
-Nobuhiro IMAI
-* a patch for logger.rb
-
-"incorporate"
-* a patch for sprintf.c
-
-Keiju Ishitsuka (keiju)
-* committer
-* He wrote and is the maintainer of:
- * cmath.rb (1.9)
- * complex.rb (1.8)
- * e2mmap.rb
- * forwardable.rb
- * irb
- * mathn
- * matrix.rb
- * mutex_m.rb
- * rational.rb (1.8)
- * sync.rb
- * shell/*
- * thwait.rb
- * tracer.rb
-
-== J
-
-Curtis Jackson
-* missing/dup2.c
-
-Alan Johnson
-* a patch for net/ftp
-
-Lyle Johnson
-* patches for nkf, bigdecimal, numeric.c
-
-== K
-
-Yoshihiro Kambayashi
-* a patch for enc/trans/single_byte.trans.
-* He wrote supports for some encodings.
-
-Yutaka Kanemoto
-* patches for common.mk, AIX AF_INET6 support
-
-Motoyuki Kasahara
-* He wrote getoptlong.rb
-
-Masahiro Kawato
-* a patch for shellwords.rb
-
-Wataru Kimura
-* a patch for configure.in
-
-Michael Klishin
-* patch for make help.
-
-Noritada Kobayashi
-* a patch for optparse.rb
-
-Shigeo Kobayashi (shigek)
-* committer
-* He is the maintainer of bigdecimal
-
-KONISHI, Hiromasa (H_Konishi)
-* committer
-* He had maintained the bcc32 support in 2004.
-
-Kornelius "murphy" Kalnbach
-* documentation
-
-K.Kosako (kosako)
-* committer
-* He wrote Oniguruma.
-
-Takehiro Kubo
-* patches for dl 64bit support.
-
-== L
-
-Marc-Andre Lafortune (marcandre)
-* committer
-* patches for hash.c, array.c, thread.c, enumc, string.c, range.c and rdoc documentation.
-
-Hongli Lai
-* improved pstore.rb
-* patch for tool/file2lastrev.rb.
-
-raspberry lemon
-* a patch for webrick/httpproxy.rb.
-
-Christian Loew
-* a patch for fileutils.rb
-
-== M
-
-Shugo Maeda (shugo)
-* committer
-* A system administrator of ruby-lang.org servers.
-* He wrote and is the maintainer of:
- * monitor.rb
- * net/ftp
- * net/imap
-
-Stephan Maka (mathew)
-* documentation
-
-Yukihiro Matsumoto (matz)
-* Matz -- the founder, language designer of Ruby.
-* committer
-* Ruby itself, most of Ruby.
-* He is the maintainer of:
- * singleton
- * timeout
- * gdbm
- * sdbm
-
-Konrad Meyer
-* documentation
-
-Mib Software
-* missing/vsnprintf.c
-
-Todd C. Miller
-* missing/strlcat.c
-* missing/strlcpy.c
-
-MIYASAKA, Masaru
-* a patch for cgi.rb
-
-Stefan Monnier
-* regex.c was fixed with based on his Emacs21 patch.
-
-Marcel Moolenaar
-* patches for eval.c and gc.c.
-
-moonwolf
-* a patch for REXML, xmlrpc
-
-Hiroshi Moriyama
-* a patch for yaml.
-
-Kyosuke Morohashi
-* a patch for gem_prelude.rb
-
-Kenta Murata
-* patches for json, bignum.c
-
-Akinori MUSHA (knu)
-* committer
-* He wrote and is the maintainer of:
- * abbrev.rb
- * generator (1.8)
- * enumerator (1.8)
- * set
- * ipaddr.rb
- * digest/*
- * syslog
-* He is the branch maintainer of ruby_1_8, the release manager of 1.8 series.
-
-== N
-
-Hidetoshi NAGAI (nagai)
-* committer
-* He is the maintainer of tk/*
-
-Nobuyoshi Nakada (nobu)
-* committer
-* a.k.a. the "patch monster"
-* He wrote and is the maintainer of:
- * optparse
- * stringio
- * io/wait
- * iconv
-
-Satoshi Nakagawa
-* patches for util.c
-
-Narihiro Nakamura (nari)
-* committer
-* a.k.a. authorNari
-* working at GC
-
-NAKAMURA, Hiroshi (nahi)
-* committer
-* He is the maintainer of:
- * csv.rb (1.8)
- * logger.rb
- * soap/* (1.8)
- * wsdl/* (1.8)
- * xsd/* (1.8)
-
-NAKAMURA, Usaku (usa)
-* committer
-* a.k.a. unak
-* He is the maintainer of mswin32 and mswin64 support.
-
-NARUSE, Yui (naruse)
-* committer
-* a.k.a. "nurse"
-* Did much upon m17n.
-* He is the maintainer of:
- * json
- * nkf
-
-Christian Neukirchen
-* a patch for webrick/httputils
-
-Michael Neumann (mneumann)
-* committer
-* He is the maintainer of
- * xmlrpc (1.8)
- * gserver (1.8)
-
-NISHIO Hirokazu
-* wrote a patch for CVE-2010-0541
-
-Kazuhiro NISHIYAMA (kazu)
-* committer
-* a.k.a. znz
-
-Go Noguchi
-
-Martin Nordholts
-* misc/rdebug.el
-
-nmu
-* a patch for socket
-
-== O
-
-okkez
-* He is a sysop of the Ruby Reference Manual Renewal Project.
-* fixed ipaddr.rb, ext/etc
-
-Haruhiko Okumura
-* some of missing/* is based on his book:
- * missing/erf.c
- * missing/lgamma_r.c
- * missing/tgamma.c
-
-OMAE, jun
-* a patch for debug.rb
-
-Eugene Ossintsev
-* documentation
-
-== P
-
-Heesob Park
-* a patch for win32/win32.c.
-
-pegacorn
-* a patch for instruby.rb
-
-== Q
-
-== R
-
-Gaston Ramos
-* documentation
-
-The Regents of the University of California
-* missing/crypt.c
-* missing/vsnprintf.c
-
-Sam Roberts
-* patch for socket
-* documentation
-
-Michal Rokos (michal)
-* committer
-* He was the maintainer of DJGPP support.
-
-rubikitch
-* a patch for io.c
-
-Marcus Rueckert
-* a patch for mkconfig.rb.
-
-Run Paint Run Run
-* patch for enc/unicode.c
-* documentation
-
-Sean Russell (ser)
-* committer
-* He wrote and is the maintainer of REXML.
-
-== S
-
-Kazuo Saito (ksaito)
-* committer
-* M17N
-
-Tadashi Saito
-* patches for test/ruby/test_math.rb, thread_*.c, bignum.c
-* working upon BigDecimal.
-* did much upon documentation
-
-Masahiro Sakai
-* a patch for io.c
-
-Laurent Sansonetti
-* a patch for tool/ytab.sed
-
-Jeff Saracco
-* documentation
-
-Koichi Sasada (ko1)
-* committer
-* He wrote YARV.
-
-Hugh Sasse
-* a patch for net/http
-* documentation
-
-Charlie Savage
-* a patch for win32/Makefile.sub
-
-Michael Scholz
-* a patch for ruby-mode.el
-
-Arthur Schreiber
-* patch for net/http and rdoc.
-
-Masatoshi SEKI (seki)
-* committer
-* He wrote and is the maintainer of:
- * drb/*
- * erb
- * rinda
-
-Roman Shterenzon
-* a patch for open-uri.
-
-Kent Sibilev
-
-Gavin Sinclair (gsinclair)
-* committer
-
-John W. Small
-* He wrote gserver.rb
-
-Yuki Sonoda (yugui)
-* committer
-* She is the maintainer of man/* manual pages and is the release manager of 1.9 series.
-* She wrote prime.rb.
-* A developer and a sysop of redmine.ruby-lang.org.
-
-SOUMA, Yutaka
-* a patch for pack.c.
-
-Tatsuki Sugiura
-* WebDAV support for net/http
-
-Masaki Suketa (suke)
-* committer
-* He is the maintainer of win32ole
-
-sheepman
-* patches for ruby.c, thread.c, stringio, enum.c, webrick, net/http
-
-Siena. (siena)
-* committer
-
-Kirill A. Shutemov
-* a patch for parse.y
-
-Darren Smith
-* a patch for golf_prelude.rb
-
-Richard M. Stallman
-* missing/alloca.c
-
-Robin Stocker
-* documentation
-
-Joshua Stowers
-* a patch for array.c
-
-Marcus Stollsteimer (stomar)
-* committer
-* a maintainer of www.ruby-lang.org
-* patches for cgi (HTML5 tag maker), numeric.c, bigdecimal, ostruct.rb, prime.rb, and others
-* documentation
-
-Adam Strzelecki
-* a patch for compile.c
-
-Masashi Sumi
-* improved net/pop.rb
-
-Eric Sunshine
-* NeXT OpenStep, Rhapsody support
-
-Kouhei Sutou (kou)
-* committer
-* He wrote and is the maintainer of rss/*
-
-David Symonds
-* documentation
-
-== T
-
-TAKANO Mitsuhiro (takano32)
-* committer
-* He is the maintainer of IA-64 support.
-* BigDecimal
-
-TAKAO, Kouji (kouji)
-* committer
-* He is the maintainer of readline.
-
-Nathaniel Talbott (ntalbott)
-* committer
-* He was the maintainer of test/unit, runit, rubyunit.
-
-TANAKA, Akira (akr)
-* committer
-* Did much upon m17n.
-* And he is the maintainer of:
- * open-uri
- * pathname
- * pp
- * resolv-replace
- * resolv
- * time
- * tsort
-
-Takaaki Tateishi (ttate)
-* committer
-* He was the maintainer of dl
-
-Technorama Ltd. (technoroma)
-* committer
-* openssl
-
-Andrew Thompson
-* a patch for socket.c IRIX support.
-
-Dave Thomas (dave)
-* committer
-* a.k.a. the Pragmatic Programmer.
-* He wrote rdoc.
-
-Tietew
-* patches for win32 support
-
-Masahiro Tomita
-* a patch for cgi.rb
-
-Jakub Travnik
-* a patch for eval.c
-
-Tom Truscott
-* missing/crypt.c
-
-== U
-
-UEDA, Satoshi
-* a patch for uri
-
-Takaaki Uematsu (uema2)
-* committer
-* He was the maintainer of WinCE support.
-
-UENO, Katsuhiro (katsu)
-* committer
-* He is the maintainer of zlib
-
-Hajimu UMEMOTO
-* He wrote ipaddr.rb
-
-URABE, Shyouhei (shyouhei)
-* committer
-* a.k.a. mput.
-* He is the branch maintainer of ruby_1_8_6 and ruby_1_8_7
-* and is the release manager of 1.8.x-pXXX.
-
-== V
-
-Joel VanderWerf
-* a patch for numeric.c
-
-Peter Vanbroekhoven
-
-Corinna Vinschen
-
-== W
-
-wanabe (wanabe)
-* committer
-* fixed YARV and Oniguruma.
-
-Chun Wang
-* a patch for time.rb
-
-WATANABE, Hirofumi (eban)
-* committer
-* He is the maintainer of
- * ftools (1.8)
- * tmpdir
- * un
- * Win32API
-
-WATANABE, Tetsuya
-* a patch for ruby.c
-
-William Webber (wew)
-* committer
-
-Jim Weirich (jim)
-* committer
-* He wrote Rake.
-
-Nathan Weizenbaum
-* fixed misc/ruby-mode.el.
-
-why the lukky stiff (why)
-* committer
-* He is the maintainer of syck
-
-Caley Woods
-* documentation
-
-Gary Wright
-* documentation
-
-== X
-
-== Y
-
-Akira Yamada (akira)
-* committer
-* He is the maintainer of ruby related packages at Debian project.
-
-Keita Yamaguchi
-* patches for enum.c, parse.y
-* documentation
-
-Hirokazu Yamamoto (ocean)
-* committer
-
-Hirotaka Yoshioka
-* a patch for improving SEGV handling
-
-== Z
-
-Aristarkh A Zagorodnikov
-* a patch for io.c
-
-Alexander Zavorine
-* committer
-* He is the maintainer for Symbian OS.
-
-Chiyuan Zhang
-* a patch for misc/ruby-mode.el.
-
-Dee Zsombor (zunda)
-* a patch for thread_pthread.c
-
-Dan Zwell
-* a patch for net/pop
-
-
diff --git a/doc/csv/arguments/io.rdoc b/doc/csv/arguments/io.rdoc
new file mode 100644
index 0000000000..f5fe1d1975
--- /dev/null
+++ b/doc/csv/arguments/io.rdoc
@@ -0,0 +1,5 @@
+* Argument +io+ should be an IO object that is:
+ * Open for reading; on return, the IO object will be closed.
+ * Positioned at the beginning.
+ To position at the end, for appending, use method CSV.generate.
+ For any other positioning, pass a preset \StringIO object instead.
diff --git a/doc/csv/options/common/col_sep.rdoc b/doc/csv/options/common/col_sep.rdoc
new file mode 100644
index 0000000000..05769b5773
--- /dev/null
+++ b/doc/csv/options/common/col_sep.rdoc
@@ -0,0 +1,63 @@
+====== Option +col_sep+
+
+Specifies the \String field separator to be used
+for both parsing and generating.
+The \String will be transcoded into the data's \Encoding before use.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:col_sep) # => "," (comma)
+
+Using the default (comma):
+ str = CSV.generate do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo,0\nbar,1\nbaz,2\n"
+ ary = CSV.parse(str)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Using +:+ (colon):
+ col_sep = ':'
+ str = CSV.generate(col_sep: col_sep) do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo:0\nbar:1\nbaz:2\n"
+ ary = CSV.parse(str, col_sep: col_sep)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Using +::+ (two colons):
+ col_sep = '::'
+ str = CSV.generate(col_sep: col_sep) do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo::0\nbar::1\nbaz::2\n"
+ ary = CSV.parse(str, col_sep: col_sep)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Using <tt>''</tt> (empty string):
+ col_sep = ''
+ str = CSV.generate(col_sep: col_sep) do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo0\nbar1\nbaz2\n"
+
+---
+
+Raises an exception if parsing with the empty \String:
+ col_sep = ''
+ # Raises ArgumentError (:col_sep must be 1 or more characters: "")
+ CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep)
+
+Raises an exception if the given value is not String-convertible:
+ col_sep = BasicObject.new
+ # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
+ CSV.generate(line, col_sep: col_sep)
+ # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
+ CSV.parse(str, col_sep: col_sep)
diff --git a/doc/csv/options/common/quote_char.rdoc b/doc/csv/options/common/quote_char.rdoc
new file mode 100644
index 0000000000..67fd3af68b
--- /dev/null
+++ b/doc/csv/options/common/quote_char.rdoc
@@ -0,0 +1,42 @@
+====== Option +quote_char+
+
+Specifies the character (\String of length 1) used used to quote fields
+in both parsing and generating.
+This String will be transcoded into the data's \Encoding before use.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:quote_char) # => "\"" (double quote)
+
+This is useful for an application that incorrectly uses <tt>'</tt> (single-quote)
+to quote fields, instead of the correct <tt>"</tt> (double-quote).
+
+Using the default (double quote):
+ str = CSV.generate do |csv|
+ csv << ['foo', 0]
+ csv << ["'bar'", 1]
+ csv << ['"baz"', 2]
+ end
+ str # => "foo,0\n'bar',1\n\"\"\"baz\"\"\",2\n"
+ ary = CSV.parse(str)
+ ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
+
+Using <tt>'</tt> (single-quote):
+ quote_char = "'"
+ str = CSV.generate(quote_char: quote_char) do |csv|
+ csv << ['foo', 0]
+ csv << ["'bar'", 1]
+ csv << ['"baz"', 2]
+ end
+ str # => "foo,0\n'''bar''',1\n\"baz\",2\n"
+ ary = CSV.parse(str, quote_char: quote_char)
+ ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
+
+---
+
+Raises an exception if the \String length is greater than 1:
+ # Raises ArgumentError (:quote_char has to be nil or a single character String)
+ CSV.new('', quote_char: 'xx')
+
+Raises an exception if the value is not a \String:
+ # Raises ArgumentError (:quote_char has to be nil or a single character String)
+ CSV.new('', quote_char: :foo)
diff --git a/doc/csv/options/common/row_sep.rdoc b/doc/csv/options/common/row_sep.rdoc
new file mode 100644
index 0000000000..872d9d1f3f
--- /dev/null
+++ b/doc/csv/options/common/row_sep.rdoc
@@ -0,0 +1,100 @@
+====== Option +row_sep+
+
+Specifies the row separator, a \String or the \Symbol <tt>:auto</tt> (see below),
+to be used for both parsing and generating.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:row_sep) # => :auto
+
+---
+
+When +row_sep+ is a \String, that \String becomes the row separator.
+The String will be transcoded into the data's Encoding before use.
+
+Using <tt>"\n"</tt>:
+ row_sep = "\n"
+ str = CSV.generate(row_sep: row_sep) do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo,0\nbar,1\nbaz,2\n"
+ ary = CSV.parse(str)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Using <tt>|</tt> (pipe):
+ row_sep = '|'
+ str = CSV.generate(row_sep: row_sep) do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo,0|bar,1|baz,2|"
+ ary = CSV.parse(str, row_sep: row_sep)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Using <tt>--</tt> (two hyphens):
+ row_sep = '--'
+ str = CSV.generate(row_sep: row_sep) do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo,0--bar,1--baz,2--"
+ ary = CSV.parse(str, row_sep: row_sep)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Using <tt>''</tt> (empty string):
+ row_sep = ''
+ str = CSV.generate(row_sep: row_sep) do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo,0bar,1baz,2"
+ ary = CSV.parse(str, row_sep: row_sep)
+ ary # => [["foo", "0bar", "1baz", "2"]]
+
+---
+
+When +row_sep+ is the \Symbol +:auto+ (the default),
+generating uses <tt>"\n"</tt> as the row separator:
+ str = CSV.generate do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo,0\nbar,1\nbaz,2\n"
+
+Parsing, on the other hand, invokes auto-discovery of the row separator.
+
+Auto-discovery reads ahead in the data looking for the next <tt>\r\n</tt>, +\n+, or +\r+ sequence.
+The sequence will be selected even if it occurs in a quoted field,
+assuming that you would have the same line endings there.
+
+Example:
+ str = CSV.generate do |csv|
+ csv << [:foo, 0]
+ csv << [:bar, 1]
+ csv << [:baz, 2]
+ end
+ str # => "foo,0\nbar,1\nbaz,2\n"
+ ary = CSV.parse(str)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+The default <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) is used
+if any of the following is true:
+* None of those sequences is found.
+* Data is +ARGF+, +STDIN+, +STDOUT+, or +STDERR+.
+* The stream is only available for output.
+
+Obviously, discovery takes a little time. Set manually if speed is important. Also note that IO objects should be opened in binary mode on Windows if this feature will be used as the line-ending translation can cause problems with resetting the document position to where it was before the read ahead.
+
+---
+
+Raises an exception if the given value is not String-convertible:
+ row_sep = BasicObject.new
+ # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
+ CSV.generate(ary, row_sep: row_sep)
+ # Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
+ CSV.parse(str, row_sep: row_sep)
diff --git a/doc/csv/options/generating/force_quotes.rdoc b/doc/csv/options/generating/force_quotes.rdoc
new file mode 100644
index 0000000000..11afd1a16c
--- /dev/null
+++ b/doc/csv/options/generating/force_quotes.rdoc
@@ -0,0 +1,17 @@
+====== Option +force_quotes+
+
+Specifies the boolean that determines whether each output field is to be double-quoted.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:force_quotes) # => false
+
+For examples in this section:
+ ary = ['foo', 0, nil]
+
+Using the default, +false+:
+ str = CSV.generate_line(ary)
+ str # => "foo,0,\n"
+
+Using +true+:
+ str = CSV.generate_line(ary, force_quotes: true)
+ str # => "\"foo\",\"0\",\"\"\n"
diff --git a/doc/csv/options/generating/quote_empty.rdoc b/doc/csv/options/generating/quote_empty.rdoc
new file mode 100644
index 0000000000..4c5645c662
--- /dev/null
+++ b/doc/csv/options/generating/quote_empty.rdoc
@@ -0,0 +1,12 @@
+====== Option +quote_empty+
+
+Specifies the boolean that determines whether an empty value is to be double-quoted.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:quote_empty) # => true
+
+With the default +true+:
+ CSV.generate_line(['"', ""]) # => "\"\"\"\",\"\"\n"
+
+With +false+:
+ CSV.generate_line(['"', ""], quote_empty: false) # => "\"\"\"\",\n"
diff --git a/doc/csv/options/generating/write_converters.rdoc b/doc/csv/options/generating/write_converters.rdoc
new file mode 100644
index 0000000000..6e5fae5fda
--- /dev/null
+++ b/doc/csv/options/generating/write_converters.rdoc
@@ -0,0 +1,33 @@
+====== Option +write_converters+
+
+Specifies converters to be used in generating fields.
+See {Write Converters}[#class-CSV-label-Write+Converters]
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:write_converters) # => nil
+
+With no write converter:
+ str = CSV.generate_line(["\na\n", "\tb\t", " c "])
+ str # => "\"\na\n\",\tb\t, c \n"
+
+With a write converter:
+ strip_converter = proc {|field| field.strip }
+ str = CSV.generate_line(["\na\n", "\tb\t", " c "], write_converters: strip_converter)
+ str # => "a,b,c\n"
+
+With two write converters (called in order):
+ upcase_converter = proc {|field| field.upcase }
+ downcase_converter = proc {|field| field.downcase }
+ write_converters = [upcase_converter, downcase_converter]
+ str = CSV.generate_line(['a', 'b', 'c'], write_converters: write_converters)
+ str # => "a,b,c\n"
+
+See also {Write Converters}[#class-CSV-label-Write+Converters]
+
+---
+
+Raises an exception if the converter returns a value that is neither +nil+
+nor \String-convertible:
+ bad_converter = proc {|field| BasicObject.new }
+ # Raises NoMethodError (undefined method `is_a?' for #<BasicObject:>)
+ CSV.generate_line(['a', 'b', 'c'], write_converters: bad_converter) \ No newline at end of file
diff --git a/doc/csv/options/generating/write_empty_value.rdoc b/doc/csv/options/generating/write_empty_value.rdoc
new file mode 100644
index 0000000000..67be5662cb
--- /dev/null
+++ b/doc/csv/options/generating/write_empty_value.rdoc
@@ -0,0 +1,15 @@
+====== Option +write_empty_value+
+
+Specifies the object that is to be substituted for each field
+that has an empty \String.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:write_empty_value) # => ""
+
+Without the option:
+ str = CSV.generate_line(['a', '', 'c', ''])
+ str # => "a,\"\",c,\"\"\n"
+
+With the option:
+ str = CSV.generate_line(['a', '', 'c', ''], write_empty_value: "x")
+ str # => "a,x,c,x\n"
diff --git a/doc/csv/options/generating/write_headers.rdoc b/doc/csv/options/generating/write_headers.rdoc
new file mode 100644
index 0000000000..f9faa9d438
--- /dev/null
+++ b/doc/csv/options/generating/write_headers.rdoc
@@ -0,0 +1,29 @@
+====== Option +write_headers+
+
+Specifies the boolean that determines whether a header row is included in the output;
+ignored if there are no headers.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:write_headers) # => nil
+
+Without +write_headers+:
+ file_path = 't.csv'
+ CSV.open(file_path,'w',
+ :headers => ['Name','Value']
+ ) do |csv|
+ csv << ['foo', '0']
+ end
+ CSV.open(file_path) do |csv|
+ csv.shift
+ end # => ["foo", "0"]
+
+With +write_headers+":
+ CSV.open(file_path,'w',
+ :write_headers=> true,
+ :headers => ['Name','Value']
+ ) do |csv|
+ csv << ['foo', '0']
+ end
+ CSV.open(file_path) do |csv|
+ csv.shift
+ end # => ["Name", "Value"]
diff --git a/doc/csv/options/generating/write_nil_value.rdoc b/doc/csv/options/generating/write_nil_value.rdoc
new file mode 100644
index 0000000000..65d33ff54e
--- /dev/null
+++ b/doc/csv/options/generating/write_nil_value.rdoc
@@ -0,0 +1,14 @@
+====== Option +write_nil_value+
+
+Specifies the object that is to be substituted for each +nil+-valued field.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:write_nil_value) # => nil
+
+Without the option:
+ str = CSV.generate_line(['a', nil, 'c', nil])
+ str # => "a,,c,\n"
+
+With the option:
+ str = CSV.generate_line(['a', nil, 'c', nil], write_nil_value: "x")
+ str # => "a,x,c,x\n"
diff --git a/doc/csv/options/parsing/converters.rdoc b/doc/csv/options/parsing/converters.rdoc
new file mode 100644
index 0000000000..211fa48de6
--- /dev/null
+++ b/doc/csv/options/parsing/converters.rdoc
@@ -0,0 +1,46 @@
+====== Option +converters+
+
+Specifies converters to be used in parsing fields.
+See {Field Converters}[#class-CSV-label-Field+Converters]
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:converters) # => nil
+
+The value may be a field converter name
+(see {Stored Converters}[#class-CSV-label-Stored+Converters]):
+ str = '1,2,3'
+ # Without a converter
+ array = CSV.parse_line(str)
+ array # => ["1", "2", "3"]
+ # With built-in converter :integer
+ array = CSV.parse_line(str, converters: :integer)
+ array # => [1, 2, 3]
+
+The value may be a converter list
+(see {Converter Lists}[#class-CSV-label-Converter+Lists]):
+ str = '1,3.14159'
+ # Without converters
+ array = CSV.parse_line(str)
+ array # => ["1", "3.14159"]
+ # With built-in converters
+ array = CSV.parse_line(str, converters: [:integer, :float])
+ array # => [1, 3.14159]
+
+The value may be a \Proc custom converter:
+(see {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters]):
+ str = ' foo , bar , baz '
+ # Without a converter
+ array = CSV.parse_line(str)
+ array # => [" foo ", " bar ", " baz "]
+ # With a custom converter
+ array = CSV.parse_line(str, converters: proc {|field| field.strip })
+ array # => ["foo", "bar", "baz"]
+
+See also {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters]
+
+---
+
+Raises an exception if the converter is not a converter name or a \Proc:
+ str = 'foo,0'
+ # Raises NoMethodError (undefined method `arity' for nil:NilClass)
+ CSV.parse(str, converters: :foo)
diff --git a/doc/csv/options/parsing/empty_value.rdoc b/doc/csv/options/parsing/empty_value.rdoc
new file mode 100644
index 0000000000..7d3bcc078c
--- /dev/null
+++ b/doc/csv/options/parsing/empty_value.rdoc
@@ -0,0 +1,13 @@
+====== Option +empty_value+
+
+Specifies the object that is to be substituted
+for each field that has an empty \String.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:empty_value) # => "" (empty string)
+
+With the default, <tt>""</tt>:
+ CSV.parse_line('a,"",b,"",c') # => ["a", "", "b", "", "c"]
+
+With a different object:
+ CSV.parse_line('a,"",b,"",c', empty_value: 'x') # => ["a", "x", "b", "x", "c"]
diff --git a/doc/csv/options/parsing/field_size_limit.rdoc b/doc/csv/options/parsing/field_size_limit.rdoc
new file mode 100644
index 0000000000..797c5776fc
--- /dev/null
+++ b/doc/csv/options/parsing/field_size_limit.rdoc
@@ -0,0 +1,39 @@
+====== Option +field_size_limit+
+
+Specifies the \Integer field size limit.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:field_size_limit) # => nil
+
+This is a maximum size CSV will read ahead looking for the closing quote for a field.
+(In truth, it reads to the first line ending beyond this size.)
+If a quote cannot be found within the limit CSV will raise a MalformedCSVError,
+assuming the data is faulty.
+You can use this limit to prevent what are effectively DoS attacks on the parser.
+However, this limit can cause a legitimate parse to fail;
+therefore the default value is +nil+ (no limit).
+
+For the examples in this section:
+ str = <<~EOT
+ "a","b"
+ "
+ 2345
+ ",""
+ EOT
+ str # => "\"a\",\"b\"\n\"\n2345\n\",\"\"\n"
+
+Using the default +nil+:
+ ary = CSV.parse(str)
+ ary # => [["a", "b"], ["\n2345\n", ""]]
+
+Using <tt>50</tt>:
+ field_size_limit = 50
+ ary = CSV.parse(str, field_size_limit: field_size_limit)
+ ary # => [["a", "b"], ["\n2345\n", ""]]
+
+---
+
+Raises an exception if a field is too long:
+ big_str = "123456789\n" * 1024
+ # Raises CSV::MalformedCSVError (Field size exceeded in line 1.)
+ CSV.parse('valid,fields,"' + big_str + '"', field_size_limit: 2048)
diff --git a/doc/csv/options/parsing/header_converters.rdoc b/doc/csv/options/parsing/header_converters.rdoc
new file mode 100644
index 0000000000..309180805f
--- /dev/null
+++ b/doc/csv/options/parsing/header_converters.rdoc
@@ -0,0 +1,43 @@
+====== Option +header_converters+
+
+Specifies converters to be used in parsing headers.
+See {Header Converters}[#class-CSV-label-Header+Converters]
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:header_converters) # => nil
+
+Identical in functionality to option {converters}[#class-CSV-label-Option+converters]
+except that:
+- The converters apply only to the header row.
+- The built-in header converters are +:downcase+ and +:symbol+.
+
+This section assumes prior execution of:
+ str = <<-EOT
+ Name,Value
+ foo,0
+ bar,1
+ baz,2
+ EOT
+ # With no header converter
+ table = CSV.parse(str, headers: true)
+ table.headers # => ["Name", "Value"]
+
+The value may be a header converter name
+(see {Stored Converters}[#class-CSV-label-Stored+Converters]):
+ table = CSV.parse(str, headers: true, header_converters: :downcase)
+ table.headers # => ["name", "value"]
+
+The value may be a converter list
+(see {Converter Lists}[#class-CSV-label-Converter+Lists]):
+ header_converters = [:downcase, :symbol]
+ table = CSV.parse(str, headers: true, header_converters: header_converters)
+ table.headers # => [:name, :value]
+
+The value may be a \Proc custom converter
+(see {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters]):
+ upcase_converter = proc {|field| field.upcase }
+ table = CSV.parse(str, headers: true, header_converters: upcase_converter)
+ table.headers # => ["NAME", "VALUE"]
+
+See also {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters]
+
diff --git a/doc/csv/options/parsing/headers.rdoc b/doc/csv/options/parsing/headers.rdoc
new file mode 100644
index 0000000000..0ea151f24b
--- /dev/null
+++ b/doc/csv/options/parsing/headers.rdoc
@@ -0,0 +1,63 @@
+====== Option +headers+
+
+Specifies a boolean, \Symbol, \Array, or \String to be used
+to define column headers.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:headers) # => false
+
+---
+
+Without +headers+:
+ str = <<-EOT
+ Name,Count
+ foo,0
+ bar,1
+ bax,2
+ EOT
+ csv = CSV.new(str)
+ csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
+ csv.headers # => nil
+ csv.shift # => ["Name", "Count"]
+
+---
+
+If set to +true+ or the \Symbol +:first_row+,
+the first row of the data is treated as a row of headers:
+ str = <<-EOT
+ Name,Count
+ foo,0
+ bar,1
+ bax,2
+ EOT
+ csv = CSV.new(str, headers: true)
+ csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:2 col_sep:"," row_sep:"\n" quote_char:"\"" headers:["Name", "Count"]>
+ csv.headers # => ["Name", "Count"]
+ csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
+
+---
+
+If set to an \Array, the \Array elements are treated as headers:
+ str = <<-EOT
+ foo,0
+ bar,1
+ bax,2
+ EOT
+ csv = CSV.new(str, headers: ['Name', 'Count'])
+ csv
+ csv.headers # => ["Name", "Count"]
+ csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
+
+---
+
+If set to a \String +str+, method <tt>CSV::parse_line(str, options)</tt> is called
+with the current +options+, and the returned \Array is treated as headers:
+ str = <<-EOT
+ foo,0
+ bar,1
+ bax,2
+ EOT
+ csv = CSV.new(str, headers: 'Name,Count')
+ csv
+ csv.headers # => ["Name", "Count"]
+ csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
diff --git a/doc/csv/options/parsing/liberal_parsing.rdoc b/doc/csv/options/parsing/liberal_parsing.rdoc
new file mode 100644
index 0000000000..b8b9b00c98
--- /dev/null
+++ b/doc/csv/options/parsing/liberal_parsing.rdoc
@@ -0,0 +1,19 @@
+====== Option +liberal_parsing+
+
+Specifies the boolean value that determines whether
+CSV will attempt to parse input not conformant with RFC 4180,
+such as double quotes in unquoted fields.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:liberal_parsing) # => false
+
+For examples in this section:
+ str = 'is,this "three, or four",fields'
+
+Without +liberal_parsing+:
+ # Raises CSV::MalformedCSVError (Illegal quoting in str 1.)
+ CSV.parse_line(str)
+
+With +liberal_parsing+:
+ ary = CSV.parse_line(str, liberal_parsing: true)
+ ary # => ["is", "this \"three", " or four\"", "fields"]
diff --git a/doc/csv/options/parsing/nil_value.rdoc b/doc/csv/options/parsing/nil_value.rdoc
new file mode 100644
index 0000000000..412e8795e8
--- /dev/null
+++ b/doc/csv/options/parsing/nil_value.rdoc
@@ -0,0 +1,12 @@
+====== Option +nil_value+
+
+Specifies the object that is to be substituted for each null (no-text) field.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:nil_value) # => nil
+
+With the default, +nil+:
+ CSV.parse_line('a,,b,,c') # => ["a", nil, "b", nil, "c"]
+
+With a different object:
+ CSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"]
diff --git a/doc/csv/options/parsing/return_headers.rdoc b/doc/csv/options/parsing/return_headers.rdoc
new file mode 100644
index 0000000000..45d2e3f3de
--- /dev/null
+++ b/doc/csv/options/parsing/return_headers.rdoc
@@ -0,0 +1,22 @@
+====== Option +return_headers+
+
+Specifies the boolean that determines whether method #shift
+returns or ignores the header row.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:return_headers) # => false
+
+Examples:
+ str = <<-EOT
+ Name,Count
+ foo,0
+ bar,1
+ bax,2
+ EOT
+ # Without return_headers first row is str.
+ csv = CSV.new(str, headers: true)
+ csv.shift # => #<CSV::Row "Name":"foo" "Count":"0">
+ # With return_headers first row is headers.
+ csv = CSV.new(str, headers: true, return_headers: true)
+ csv.shift # => #<CSV::Row "Name":"Name" "Count":"Count">
+
diff --git a/doc/csv/options/parsing/skip_blanks.rdoc b/doc/csv/options/parsing/skip_blanks.rdoc
new file mode 100644
index 0000000000..2c8f7b7bb8
--- /dev/null
+++ b/doc/csv/options/parsing/skip_blanks.rdoc
@@ -0,0 +1,31 @@
+====== Option +skip_blanks+
+
+Specifies a boolean that determines whether blank lines in the input will be ignored;
+a line that contains a column separator is not considered to be blank.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:skip_blanks) # => false
+
+See also option {skiplines}[#class-CSV-label-Option+skip_lines].
+
+For examples in this section:
+ str = <<-EOT
+ foo,0
+
+ bar,1
+ baz,2
+
+ ,
+ EOT
+
+Using the default, +false+:
+ ary = CSV.parse(str)
+ ary # => [["foo", "0"], [], ["bar", "1"], ["baz", "2"], [], [nil, nil]]
+
+Using +true+:
+ ary = CSV.parse(str, skip_blanks: true)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]]
+
+Using a truthy value:
+ ary = CSV.parse(str, skip_blanks: :foo)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]]
diff --git a/doc/csv/options/parsing/skip_lines.rdoc b/doc/csv/options/parsing/skip_lines.rdoc
new file mode 100644
index 0000000000..1481c40a5f
--- /dev/null
+++ b/doc/csv/options/parsing/skip_lines.rdoc
@@ -0,0 +1,37 @@
+====== Option +skip_lines+
+
+Specifies an object to use in identifying comment lines in the input that are to be ignored:
+* If a \Regexp, ignores lines that match it.
+* If a \String, converts it to a \Regexp, ignores lines that match it.
+* If +nil+, no lines are considered to be comments.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:skip_lines) # => nil
+
+For examples in this section:
+ str = <<-EOT
+ # Comment
+ foo,0
+ bar,1
+ baz,2
+ # Another comment
+ EOT
+ str # => "# Comment\nfoo,0\nbar,1\nbaz,2\n# Another comment\n"
+
+Using the default, +nil+:
+ ary = CSV.parse(str)
+ ary # => [["# Comment"], ["foo", "0"], ["bar", "1"], ["baz", "2"], ["# Another comment"]]
+
+Using a \Regexp:
+ ary = CSV.parse(str, skip_lines: /^#/)
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Using a \String:
+ ary = CSV.parse(str, skip_lines: '#')
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+---
+
+Raises an exception if given an object that is not a \Regexp, a \String, or +nil+:
+ # Raises ArgumentError (:skip_lines has to respond to #match: 0)
+ CSV.parse(str, skip_lines: 0)
diff --git a/doc/csv/options/parsing/strip.rdoc b/doc/csv/options/parsing/strip.rdoc
new file mode 100644
index 0000000000..56ae4310c3
--- /dev/null
+++ b/doc/csv/options/parsing/strip.rdoc
@@ -0,0 +1,15 @@
+====== Option +strip+
+
+Specifies the boolean value that determines whether
+whitespace is stripped from each input field.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:strip) # => false
+
+With default value +false+:
+ ary = CSV.parse_line(' a , b ')
+ ary # => [" a ", " b "]
+
+With value +true+:
+ ary = CSV.parse_line(' a , b ', strip: true)
+ ary # => ["a", "b"]
diff --git a/doc/csv/options/parsing/unconverted_fields.rdoc b/doc/csv/options/parsing/unconverted_fields.rdoc
new file mode 100644
index 0000000000..3e7f839d49
--- /dev/null
+++ b/doc/csv/options/parsing/unconverted_fields.rdoc
@@ -0,0 +1,27 @@
+====== Option +unconverted_fields+
+
+Specifies the boolean that determines whether unconverted field values are to be available.
+
+Default value:
+ CSV::DEFAULT_OPTIONS.fetch(:unconverted_fields) # => nil
+
+The unconverted field values are those found in the source data,
+prior to any conversions performed via option +converters+.
+
+When option +unconverted_fields+ is +true+,
+each returned row (\Array or \CSV::Row) has an added method,
++unconverted_fields+, that returns the unconverted field values:
+ str = <<-EOT
+ foo,0
+ bar,1
+ baz,2
+ EOT
+ # Without unconverted_fields
+ csv = CSV.parse(str, converters: :integer)
+ csv # => [["foo", 0], ["bar", 1], ["baz", 2]]
+ csv.first.respond_to?(:unconverted_fields) # => false
+ # With unconverted_fields
+ csv = CSV.parse(str, converters: :integer, unconverted_fields: true)
+ csv # => [["foo", 0], ["bar", 1], ["baz", 2]]
+ csv.first.respond_to?(:unconverted_fields) # => true
+ csv.first.unconverted_fields # => ["foo", "0"]
diff --git a/doc/csv/recipes/filtering.rdoc b/doc/csv/recipes/filtering.rdoc
new file mode 100644
index 0000000000..470649d09a
--- /dev/null
+++ b/doc/csv/recipes/filtering.rdoc
@@ -0,0 +1,156 @@
+== Recipes for Filtering \CSV
+
+For other recipes, see {Recipes for CSV}[./recipes_rdoc.html].
+
+All code snippets on this page assume that the following has been executed:
+ require 'csv'
+
+=== Contents
+
+- {Source and Output Formats}[#label-Source+and+Output+Formats]
+ - {Filtering String to String}[#label-Filtering+String+to+String]
+ - {Recipe: Filter String to String with Headers}[#label-Recipe-3A+Filter+String+to+String+with+Headers]
+ - {Recipe: Filter String to String Without Headers}[#label-Recipe-3A+Filter+String+to+String+Without+Headers]
+ - {Filtering String to IO Stream}[#label-Filtering+String+to+IO+Stream]
+ - {Recipe: Filter String to IO Stream with Headers}[#label-Recipe-3A+Filter+String+to+IO+Stream+with+Headers]
+ - {Recipe: Filter String to IO Stream Without Headers}[#label-Recipe-3A+Filter+String+to+IO+Stream+Without+Headers]
+ - {Filtering IO Stream to String}[#label-Filtering+IO+Stream+to+String]
+ - {Recipe: Filter IO Stream to String with Headers}[#label-Recipe-3A+Filter+IO+Stream+to+String+with+Headers]
+ - {Recipe: Filter IO Stream to String Without Headers}[#label-Recipe-3A+Filter+IO+Stream+to+String+Without+Headers]
+ - {Filtering IO Stream to IO Stream}[#label-Filtering+IO+Stream+to+IO+Stream]
+ - {Recipe: Filter IO Stream to IO Stream with Headers}[#label-Recipe-3A+Filter+IO+Stream+to+IO+Stream+with+Headers]
+ - {Recipe: Filter IO Stream to IO Stream Without Headers}[#label-Recipe-3A+Filter+IO+Stream+to+IO+Stream+Without+Headers]
+
+=== Source and Output Formats
+
+You can use a Unix-style "filter" for \CSV data.
+The filter reads source \CSV data and writes output \CSV data as modified by the filter.
+The input and output \CSV data may be any mixture of \Strings and \IO streams.
+
+==== Filtering \String to \String
+
+You can filter one \String to another, with or without headers.
+
+===== Recipe: Filter \String to \String with Headers
+
+Use class method CSV.filter with option +headers+ to filter a \String to another \String:
+ in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ out_string = ''
+ CSV.filter(in_string, out_string, headers: true) do |row|
+ row[0] = row[0].upcase
+ row[1] *= 4
+ end
+ out_string # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n"
+
+===== Recipe: Filter \String to \String Without Headers
+
+Use class method CSV.filter without option +headers+ to filter a \String to another \String:
+ in_string = "foo,0\nbar,1\nbaz,2\n"
+ out_string = ''
+ CSV.filter(in_string, out_string) do |row|
+ row[0] = row[0].upcase
+ row[1] *= 4
+ end
+ out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
+
+==== Filtering \String to \IO Stream
+
+You can filter a \String to an \IO stream, with or without headers.
+
+===== Recipe: Filter \String to \IO Stream with Headers
+
+Use class method CSV.filter with option +headers+ to filter a \String to an \IO stream:
+ in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ path = 't.csv'
+ File.open(path, 'w') do |out_io|
+ CSV.filter(in_string, out_io, headers: true) do |row|
+ row[0] = row[0].upcase
+ row[1] *= 4
+ end
+ end
+ p File.read(path) # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n"
+
+===== Recipe: Filter \String to \IO Stream Without Headers
+
+Use class method CSV.filter without option +headers+ to filter a \String to an \IO stream:
+ in_string = "foo,0\nbar,1\nbaz,2\n"
+ path = 't.csv'
+ File.open(path, 'w') do |out_io|
+ CSV.filter(in_string, out_io) do |row|
+ row[0] = row[0].upcase
+ row[1] *= 4
+ end
+ end
+ p File.read(path) # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
+
+==== Filtering \IO Stream to \String
+
+You can filter an \IO stream to a \String, with or without headers.
+
+===== Recipe: Filter \IO Stream to \String with Headers
+
+Use class method CSV.filter with option +headers+ to filter an \IO stream to a \String:
+ in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ path = 't.csv'
+ File.write(path, in_string)
+ out_string = ''
+ File.open(path, headers: true) do |in_io|
+ CSV.filter(in_io, out_string, headers: true) do |row|
+ row[0] = row[0].upcase
+ row[1] *= 4
+ end
+ end
+ out_string # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n"
+
+===== Recipe: Filter \IO Stream to \String Without Headers
+
+Use class method CSV.filter without option +headers+ to filter an \IO stream to a \String:
+ in_string = "foo,0\nbar,1\nbaz,2\n"
+ path = 't.csv'
+ File.write(path, in_string)
+ out_string = ''
+ File.open(path) do |in_io|
+ CSV.filter(in_io, out_string) do |row|
+ row[0] = row[0].upcase
+ row[1] *= 4
+ end
+ end
+ out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
+
+==== Filtering \IO Stream to \IO Stream
+
+You can filter an \IO stream to another \IO stream, with or without headers.
+
+===== Recipe: Filter \IO Stream to \IO Stream with Headers
+
+Use class method CSV.filter with option +headers+ to filter an \IO stream to another \IO stream:
+ in_path = 't.csv'
+ in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ File.write(in_path, in_string)
+ out_path = 'u.csv'
+ File.open(in_path) do |in_io|
+ File.open(out_path, 'w') do |out_io|
+ CSV.filter(in_io, out_io, headers: true) do |row|
+ row[0] = row[0].upcase
+ row[1] *= 4
+ end
+ end
+ end
+ p File.read(out_path) # => "Name,Value\nFOO,0000\nBAR,1111\nBAZ,2222\n"
+
+===== Recipe: Filter \IO Stream to \IO Stream Without Headers
+
+Use class method CSV.filter without option +headers+ to filter an \IO stream to another \IO stream:
+ in_path = 't.csv'
+ in_string = "foo,0\nbar,1\nbaz,2\n"
+ File.write(in_path, in_string)
+ out_path = 'u.csv'
+ File.open(in_path) do |in_io|
+ File.open(out_path, 'w') do |out_io|
+ CSV.filter(in_io, out_io) do |row|
+ row[0] = row[0].upcase
+ row[1] *= 4
+ end
+ end
+ end
+ p File.read(out_path) # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
diff --git a/doc/csv/recipes/generating.rdoc b/doc/csv/recipes/generating.rdoc
new file mode 100644
index 0000000000..3ef6df99b4
--- /dev/null
+++ b/doc/csv/recipes/generating.rdoc
@@ -0,0 +1,244 @@
+== Recipes for Generating \CSV
+
+For other recipes, see {Recipes for CSV}[./recipes_rdoc.html].
+
+All code snippets on this page assume that the following has been executed:
+ require 'csv'
+
+=== Contents
+
+- {Output Formats}[#label-Output+Formats]
+ - {Generating to a String}[#label-Generating+to+a+String]
+ - {Recipe: Generate to String with Headers}[#label-Recipe-3A+Generate+to+String+with+Headers]
+ - {Recipe: Generate to String Without Headers}[#label-Recipe-3A+Generate+to+String+Without+Headers]
+ - {Generating to a File}[#label-Generating+to+a+File]
+ - {Recipe: Generate to File with Headers}[#label-Recipe-3A+Generate+to+File+with+Headers]
+ - {Recipe: Generate to File Without Headers}[#label-Recipe-3A+Generate+to+File+Without+Headers]
+ - {Generating to IO an Stream}[#label-Generating+to+an+IO+Stream]
+ - {Recipe: Generate to IO Stream with Headers}[#label-Recipe-3A+Generate+to+IO+Stream+with+Headers]
+ - {Recipe: Generate to IO Stream Without Headers}[#label-Recipe-3A+Generate+to+IO+Stream+Without+Headers]
+- {Converting Fields}[#label-Converting+Fields]
+ - {Recipe: Filter Generated Field Strings}[#label-Recipe-3A+Filter+Generated+Field+Strings]
+ - {Recipe: Specify Multiple Write Converters}[#label-Recipe-3A+Specify+Multiple+Write+Converters]
+- {RFC 4180 Compliance}[#label-RFC+4180+Compliance]
+ - {Row Separator}[#label-Row+Separator]
+ - {Recipe: Generate Compliant Row Separator}[#label-Recipe-3A+Generate+Compliant+Row+Separator]
+ - {Recipe: Generate Non-Compliant Row Separator}[#label-Recipe-3A+Generate+Non-Compliant+Row+Separator]
+ - {Column Separator}[#label-Column+Separator]
+ - {Recipe: Generate Compliant Column Separator}[#label-Recipe-3A+Generate+Compliant+Column+Separator]
+ - {Recipe: Generate Non-Compliant Column Separator}[#label-Recipe-3A+Generate+Non-Compliant+Column+Separator]
+ - {Quote Character}[#label-Quote+Character]
+ - {Recipe: Generate Compliant Quote Character}[#label-Recipe-3A+Generate+Compliant+Quote+Character]
+ - {Recipe: Generate Non-Compliant Quote Character}[#label-Recipe-3A+Generate+Non-Compliant+Quote+Character]
+
+=== Output Formats
+
+You can generate \CSV output to a \String, to a \File (via its path), or to an \IO stream.
+
+==== Generating to a \String
+
+You can generate \CSV output to a \String, with or without headers.
+
+===== Recipe: Generate to \String with Headers
+
+Use class method CSV.generate with option +headers+ to generate to a \String.
+
+This example uses method CSV#<< to append the rows
+that are to be generated:
+ output_string = CSV.generate('', headers: ['Name', 'Value'], write_headers: true) do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ output_string # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n"
+
+===== Recipe: Generate to \String Without Headers
+
+Use class method CSV.generate without option +headers+ to generate to a \String.
+
+This example uses method CSV#<< to append the rows
+that are to be generated:
+ output_string = CSV.generate do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ output_string # => "Foo,0\nBar,1\nBaz,2\n"
+
+==== Generating to a \File
+
+You can generate /CSV data to a \File, with or without headers.
+
+===== Recipe: Generate to \File with Headers
+
+Use class method CSV.open with option +headers+ generate to a \File.
+
+This example uses method CSV#<< to append the rows
+that are to be generated:
+ path = 't.csv'
+ CSV.open(path, 'w', headers: ['Name', 'Value'], write_headers: true) do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n"
+
+===== Recipe: Generate to \File Without Headers
+
+Use class method CSV.open without option +headers+ to generate to a \File.
+
+This example uses method CSV#<< to append the rows
+that are to be generated:
+ path = 't.csv'
+ CSV.open(path, 'w') do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ p File.read(path) # => "Foo,0\nBar,1\nBaz,2\n"
+
+==== Generating to an \IO Stream
+
+You can generate \CSV data to an \IO stream, with or without headers.
+
+==== Recipe: Generate to \IO Stream with Headers
+
+Use class method CSV.new with option +headers+ to generate \CSV data to an \IO stream:
+ path = 't.csv'
+ File.open(path, 'w') do |file|
+ csv = CSV.new(file, headers: ['Name', 'Value'], write_headers: true)
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n"
+
+===== Recipe: Generate to \IO Stream Without Headers
+
+Use class method CSV.new without option +headers+ to generate \CSV data to an \IO stream:
+ path = 't.csv'
+ File.open(path, 'w') do |file|
+ csv = CSV.new(file)
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ p File.read(path) # => "Foo,0\nBar,1\nBaz,2\n"
+
+=== Converting Fields
+
+You can use _write_ _converters_ to convert fields when generating \CSV.
+
+==== Recipe: Filter Generated Field Strings
+
+Use option <tt>:write_converters</tt> and a custom converter to convert field values when generating \CSV.
+
+This example defines and uses a custom write converter to strip whitespace from generated fields:
+ strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field }
+ output_string = CSV.generate(write_converters: strip_converter) do |csv|
+ csv << [' foo ', 0]
+ csv << [' bar ', 1]
+ csv << [' baz ', 2]
+ end
+ output_string # => "foo,0\nbar,1\nbaz,2\n"
+
+==== Recipe: Specify Multiple Write Converters
+
+Use option <tt>:write_converters</tt> and multiple custom coverters
+to convert field values when generating \CSV.
+
+This example defines and uses two custom write converters to strip and upcase generated fields:
+ strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field }
+ upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field }
+ converters = [strip_converter, upcase_converter]
+ output_string = CSV.generate(write_converters: converters) do |csv|
+ csv << [' foo ', 0]
+ csv << [' bar ', 1]
+ csv << [' baz ', 2]
+ end
+ output_string # => "FOO,0\nBAR,1\nBAZ,2\n"
+
+=== RFC 4180 Compliance
+
+By default, \CSV generates data that is compliant with
+{RFC 4180}[https://tools.ietf.org/html/rfc4180]
+with respect to:
+- Column separator.
+- Quote character.
+
+==== Row Separator
+
+RFC 4180 specifies the row separator CRLF (Ruby <tt>"\r\n"</tt>).
+
+===== Recipe: Generate Compliant Row Separator
+
+For strict compliance, use option +:row_sep+ to specify row separator <tt>"\r\n"</tt>:
+ output_string = CSV.generate('', row_sep: "\r\n") do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ output_string # => "Foo,0\r\nBar,1\r\nBaz,2\r\n"
+
+===== Recipe: Generate Non-Compliant Row Separator
+
+For data with non-compliant row separators, use option +:row_sep+ with a different value:
+This example source uses semicolon (<tt>";'</tt>) as its row separator:
+ output_string = CSV.generate('', row_sep: ";") do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ output_string # => "Foo,0;Bar,1;Baz,2;"
+
+==== Column Separator
+
+RFC 4180 specifies column separator COMMA (Ruby <tt>","</tt>).
+
+===== Recipe: Generate Compliant Column Separator
+
+Because the \CSV default comma separator is <tt>","</tt>,
+you need not specify option +:col_sep+ for compliant data:
+ output_string = CSV.generate('') do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ output_string # => "Foo,0\nBar,1\nBaz,2\n"
+
+===== Recipe: Generate Non-Compliant Column Separator
+
+For data with non-compliant column separators, use option +:col_sep+.
+This example source uses TAB (<tt>"\t"</tt>) as its column separator:
+ output_string = CSV.generate('', col_sep: "\t") do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ output_string # => "Foo\t0\nBar\t1\nBaz\t2\n"
+
+==== Quote Character
+
+RFC 4180 specifies quote character DQUOTE (Ruby <tt>"\""</tt>).
+
+===== Recipe: Generate Compliant Quote Character
+
+Because the \CSV default quote character is <tt>"\""</tt>,
+you need not specify option +:quote_char+ for compliant data:
+ output_string = CSV.generate('', force_quotes: true) do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ output_string # => "\"Foo\",\"0\"\n\"Bar\",\"1\"\n\"Baz\",\"2\"\n"
+
+===== Recipe: Generate Non-Compliant Quote Character
+
+For data with non-compliant quote characters, use option +:quote_char+.
+This example source uses SQUOTE (<tt>"'"</tt>) as its quote character:
+ output_string = CSV.generate('', quote_char: "'", force_quotes: true) do |csv|
+ csv << ['Foo', 0]
+ csv << ['Bar', 1]
+ csv << ['Baz', 2]
+ end
+ output_string # => "'Foo','0'\n'Bar','1'\n'Baz','2'\n"
diff --git a/doc/csv/recipes/parsing.rdoc b/doc/csv/recipes/parsing.rdoc
new file mode 100644
index 0000000000..6312cea5c4
--- /dev/null
+++ b/doc/csv/recipes/parsing.rdoc
@@ -0,0 +1,543 @@
+== Recipes for Parsing \CSV
+
+For other recipes, see {Recipes for CSV}[./recipes_rdoc.html].
+
+All code snippets on this page assume that the following has been executed:
+ require 'csv'
+
+=== Contents
+
+- {Source Formats}[#label-Source+Formats]
+ - {Parsing from a String}[#label-Parsing+from+a+String]
+ - {Recipe: Parse from String with Headers}[#label-Recipe-3A+Parse+from+String+with+Headers]
+ - {Recipe: Parse from String Without Headers}[#label-Recipe-3A+Parse+from+String+Without+Headers]
+ - {Parsing from a File}[#label-Parsing+from+a+File]
+ - {Recipe: Parse from File with Headers}[#label-Recipe-3A+Parse+from+File+with+Headers]
+ - {Recipe: Parse from File Without Headers}[#label-Recipe-3A+Parse+from+File+Without+Headers]
+ - {Parsing from an IO Stream}[#label-Parsing+from+an+IO+Stream]
+ - {Recipe: Parse from IO Stream with Headers}[#label-Recipe-3A+Parse+from+IO+Stream+with+Headers]
+ - {Recipe: Parse from IO Stream Without Headers}[#label-Recipe-3A+Parse+from+IO+Stream+Without+Headers]
+- {RFC 4180 Compliance}[#label-RFC+4180+Compliance]
+ - {Row Separator}[#label-Row+Separator]
+ - {Recipe: Handle Compliant Row Separator}[#label-Recipe-3A+Handle+Compliant+Row+Separator]
+ - {Recipe: Handle Non-Compliant Row Separator}[#label-Recipe-3A+Handle+Non-Compliant+Row+Separator]
+ - {Column Separator}[#label-Column+Separator]
+ - {Recipe: Handle Compliant Column Separator}[#label-Recipe-3A+Handle+Compliant+Column+Separator]
+ - {Recipe: Handle Non-Compliant Column Separator}[#label-Recipe-3A+Handle+Non-Compliant+Column+Separator]
+ - {Quote Character}[#label-Quote+Character]
+ - {Recipe: Handle Compliant Quote Character}[#label-Recipe-3A+Handle+Compliant+Quote+Character]
+ - {Recipe: Handle Non-Compliant Quote Character}[#label-Recipe-3A+Handle+Non-Compliant+Quote+Character]
+ - {Recipe: Allow Liberal Parsing}[#label-Recipe-3A+Allow+Liberal+Parsing]
+- {Special Handling}[#label-Special+Handling]
+ - {Special Line Handling}[#label-Special+Line+Handling]
+ - {Recipe: Ignore Blank Lines}[#label-Recipe-3A+Ignore+Blank+Lines]
+ - {Recipe: Ignore Selected Lines}[#label-Recipe-3A+Ignore+Selected+Lines]
+ - {Special Field Handling}[#label-Special+Field+Handling]
+ - {Recipe: Strip Fields}[#label-Recipe-3A+Strip+Fields]
+ - {Recipe: Handle Null Fields}[#label-Recipe-3A+Handle+Null+Fields]
+ - {Recipe: Handle Empty Fields}[#label-Recipe-3A+Handle+Empty+Fields]
+- {Converting Fields}[#label-Converting+Fields]
+ - {Converting Fields to Objects}[#label-Converting+Fields+to+Objects]
+ - {Recipe: Convert Fields to Integers}[#label-Recipe-3A+Convert+Fields+to+Integers]
+ - {Recipe: Convert Fields to Floats}[#label-Recipe-3A+Convert+Fields+to+Floats]
+ - {Recipe: Convert Fields to Numerics}[#label-Recipe-3A+Convert+Fields+to+Numerics]
+ - {Recipe: Convert Fields to Dates}[#label-Recipe-3A+Convert+Fields+to+Dates]
+ - {Recipe: Convert Fields to DateTimes}[#label-Recipe-3A+Convert+Fields+to+DateTimes]
+ - {Recipe: Convert Assorted Fields to Objects}[#label-Recipe-3A+Convert+Assorted+Fields+to+Objects]
+ - {Recipe: Convert Fields to Other Objects}[#label-Recipe-3A+Convert+Fields+to+Other+Objects]
+ - {Recipe: Filter Field Strings}[#label-Recipe-3A+Filter+Field+Strings]
+ - {Recipe: Register Field Converters}[#label-Recipe-3A+Register+Field+Converters]
+ - {Using Multiple Field Converters}[#label-Using+Multiple+Field+Converters]
+ - {Recipe: Specify Multiple Field Converters in Option :converters}[#label-Recipe-3A+Specify+Multiple+Field+Converters+in+Option+-3Aconverters]
+ - {Recipe: Specify Multiple Field Converters in a Custom Converter List}[#label-Recipe-3A+Specify+Multiple+Field+Converters+in+a+Custom+Converter+List]
+- {Converting Headers}[#label-Converting+Headers]
+ - {Recipe: Convert Headers to Lowercase}[#label-Recipe-3A+Convert+Headers+to+Lowercase]
+ - {Recipe: Convert Headers to Symbols}[#label-Recipe-3A+Convert+Headers+to+Symbols]
+ - {Recipe: Filter Header Strings}[#label-Recipe-3A+Filter+Header+Strings]
+ - {Recipe: Register Header Converters}[#label-Recipe-3A+Register+Header+Converters]
+ - {Using Multiple Header Converters}[#label-Using+Multiple+Header+Converters]
+ - {Recipe: Specify Multiple Header Converters in Option :header_converters}[#label-Recipe-3A+Specify+Multiple+Header+Converters+in+Option+-3Aheader_converters]
+ - {Recipe: Specify Multiple Header Converters in a Custom Header Converter List}[#label-Recipe-3A+Specify+Multiple+Header+Converters+in+a+Custom+Header+Converter+List]
+- {Diagnostics}[#label-Diagnostics]
+ - {Recipe: Capture Unconverted Fields}[#label-Recipe-3A+Capture+Unconverted+Fields]
+ - {Recipe: Capture Field Info}[#label-Recipe-3A+Capture+Field+Info]
+
+=== Source Formats
+
+You can parse \CSV data from a \String, from a \File (via its path), or from an \IO stream.
+
+==== Parsing from a \String
+
+You can parse \CSV data from a \String, with or without headers.
+
+===== Recipe: Parse from \String with Headers
+
+Use class method CSV.parse with option +headers+ to read a source \String all at once
+(may have memory resource implications):
+ string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ CSV.parse(string, headers: true) # => #<CSV::Table mode:col_or_row row_count:4>
+
+Use instance method CSV#each with option +headers+ to read a source \String one row at a time:
+ CSV.new(string, headers: true).each do |row|
+ p row
+ end
+Output:
+ #<CSV::Row "Name":"foo" "Value":"0">
+ #<CSV::Row "Name":"bar" "Value":"1">
+ #<CSV::Row "Name":"baz" "Value":"2">
+
+===== Recipe: Parse from \String Without Headers
+
+Use class method CSV.parse without option +headers+ to read a source \String all at once
+(may have memory resource implications):
+ string = "foo,0\nbar,1\nbaz,2\n"
+ CSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Use instance method CSV#each without option +headers+ to read a source \String one row at a time:
+ CSV.new(string).each do |row|
+ p row
+ end
+Output:
+ ["foo", "0"]
+ ["bar", "1"]
+ ["baz", "2"]
+
+==== Parsing from a \File
+
+You can parse \CSV data from a \File, with or without headers.
+
+===== Recipe: Parse from \File with Headers
+
+Use instance method CSV#read with option +headers+ to read a file all at once:
+ string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ path = 't.csv'
+ File.write(path, string)
+ CSV.read(path, headers: true) # => #<CSV::Table mode:col_or_row row_count:4>
+
+Use class method CSV.foreach with option +headers+ to read one row at a time:
+ CSV.foreach(path, headers: true) do |row|
+ p row
+ end
+Output:
+ #<CSV::Row "Name":"foo" "Value":"0">
+ #<CSV::Row "Name":"bar" "Value":"1">
+ #<CSV::Row "Name":"baz" "Value":"2">
+
+===== Recipe: Parse from \File Without Headers
+
+Use class method CSV.read without option +headers+ to read a file all at once:
+ string = "foo,0\nbar,1\nbaz,2\n"
+ path = 't.csv'
+ File.write(path, string)
+ CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Use class method CSV.foreach without option +headers+ to read one row at a time:
+ CSV.foreach(path) do |row|
+ p row
+ end
+Output:
+ ["foo", "0"]
+ ["bar", "1"]
+ ["baz", "2"]
+
+==== Parsing from an \IO Stream
+
+You can parse \CSV data from an \IO stream, with or without headers.
+
+===== Recipe: Parse from \IO Stream with Headers
+
+Use class method CSV.parse with option +headers+ to read an \IO stream all at once:
+ string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ path = 't.csv'
+ File.write(path, string)
+ File.open(path) do |file|
+ CSV.parse(file, headers: true)
+ end # => #<CSV::Table mode:col_or_row row_count:4>
+
+Use class method CSV.foreach with option +headers+ to read one row at a time:
+ File.open(path) do |file|
+ CSV.foreach(file, headers: true) do |row|
+ p row
+ end
+ end
+Output:
+ #<CSV::Row "Name":"foo" "Value":"0">
+ #<CSV::Row "Name":"bar" "Value":"1">
+ #<CSV::Row "Name":"baz" "Value":"2">
+
+===== Recipe: Parse from \IO Stream Without Headers
+
+Use class method CSV.parse without option +headers+ to read an \IO stream all at once:
+ string = "foo,0\nbar,1\nbaz,2\n"
+ path = 't.csv'
+ File.write(path, string)
+ File.open(path) do |file|
+ CSV.parse(file)
+ end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+Use class method CSV.foreach without option +headers+ to read one row at a time:
+ File.open(path) do |file|
+ CSV.foreach(file) do |row|
+ p row
+ end
+ end
+Output:
+ ["foo", "0"]
+ ["bar", "1"]
+ ["baz", "2"]
+
+=== RFC 4180 Compliance
+
+By default, \CSV parses data that is compliant with
+{RFC 4180}[https://tools.ietf.org/html/rfc4180]
+with respect to:
+- Row separator.
+- Column separator.
+- Quote character.
+
+==== Row Separator
+
+RFC 4180 specifies the row separator CRLF (Ruby <tt>"\r\n"</tt>).
+
+Although the \CSV default row separator is <tt>"\n"</tt>,
+the parser also by default handles row separator <tt>"\r"</tt> and the RFC-compliant <tt>"\r\n"</tt>.
+
+===== Recipe: Handle Compliant Row Separator
+
+For strict compliance, use option +:row_sep+ to specify row separator <tt>"\r\n"</tt>,
+which allows the compliant row separator:
+ source = "foo,1\r\nbar,1\r\nbaz,2\r\n"
+ CSV.parse(source, row_sep: "\r\n") # => [["foo", "1"], ["bar", "1"], ["baz", "2"]]
+But rejects other row separators:
+ source = "foo,1\nbar,1\nbaz,2\n"
+ CSV.parse(source, row_sep: "\r\n") # Raised MalformedCSVError
+ source = "foo,1\rbar,1\rbaz,2\r"
+ CSV.parse(source, row_sep: "\r\n") # Raised MalformedCSVError
+ source = "foo,1\n\rbar,1\n\rbaz,2\n\r"
+ CSV.parse(source, row_sep: "\r\n") # Raised MalformedCSVError
+
+===== Recipe: Handle Non-Compliant Row Separator
+
+For data with non-compliant row separators, use option +:row_sep+.
+This example source uses semicolon (<tt>";"</tt>) as its row separator:
+ source = "foo,1;bar,1;baz,2;"
+ CSV.parse(source, row_sep: ';') # => [["foo", "1"], ["bar", "1"], ["baz", "2"]]
+
+==== Column Separator
+
+RFC 4180 specifies column separator COMMA (Ruby <tt>","</tt>).
+
+===== Recipe: Handle Compliant Column Separator
+
+Because the \CSV default comma separator is ',',
+you need not specify option +:col_sep+ for compliant data:
+ source = "foo,1\nbar,1\nbaz,2\n"
+ CSV.parse(source) # => [["foo", "1"], ["bar", "1"], ["baz", "2"]]
+
+===== Recipe: Handle Non-Compliant Column Separator
+
+For data with non-compliant column separators, use option +:col_sep+.
+This example source uses TAB (<tt>"\t"</tt>) as its column separator:
+ source = "foo,1\tbar,1\tbaz,2"
+ CSV.parse(source, col_sep: "\t") # => [["foo", "1"], ["bar", "1"], ["baz", "2"]]
+
+==== Quote Character
+
+RFC 4180 specifies quote character DQUOTE (Ruby <tt>"\""</tt>).
+
+===== Recipe: Handle Compliant Quote Character
+
+Because the \CSV default quote character is <tt>"\""</tt>,
+you need not specify option +:quote_char+ for compliant data:
+ source = "\"foo\",\"1\"\n\"bar\",\"1\"\n\"baz\",\"2\"\n"
+ CSV.parse(source) # => [["foo", "1"], ["bar", "1"], ["baz", "2"]]
+
+===== Recipe: Handle Non-Compliant Quote Character
+
+For data with non-compliant quote characters, use option +:quote_char+.
+This example source uses SQUOTE (<tt>"'"</tt>) as its quote character:
+ source = "'foo','1'\n'bar','1'\n'baz','2'\n"
+ CSV.parse(source, quote_char: "'") # => [["foo", "1"], ["bar", "1"], ["baz", "2"]]
+
+==== Recipe: Allow Liberal Parsing
+
+Use option +:liberal_parsing+ to specify that \CSV should
+attempt to parse input not conformant with RFC 4180, such as double quotes in unquoted fields:
+ source = 'is,this "three, or four",fields'
+ CSV.parse(source) # Raises MalformedCSVError
+ CSV.parse(source, liberal_parsing: true) # => [["is", "this \"three", " or four\"", "fields"]]
+
+=== Special Handling
+
+You can use parsing options to specify special handling for certain lines and fields.
+
+==== Special Line Handling
+
+Use parsing options to specify special handling for blank lines, or for other selected lines.
+
+===== Recipe: Ignore Blank Lines
+
+Use option +:skip_blanks+ to ignore blank lines:
+ source = <<-EOT
+ foo,0
+
+ bar,1
+ baz,2
+
+ ,
+ EOT
+ parsed = CSV.parse(source, skip_blanks: true)
+ parsed # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]]
+
+===== Recipe: Ignore Selected Lines
+
+Use option +:skip_lines+ to ignore selected lines.
+ source = <<-EOT
+ # Comment
+ foo,0
+ bar,1
+ baz,2
+ # Another comment
+ EOT
+ parsed = CSV.parse(source, skip_lines: /^#/)
+ parsed # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+
+==== Special Field Handling
+
+Use parsing options to specify special handling for certain field values.
+
+===== Recipe: Strip Fields
+
+Use option +:strip+ to strip parsed field values:
+ CSV.parse_line(' a , b ', strip: true) # => ["a", "b"]
+
+===== Recipe: Handle Null Fields
+
+Use option +:nil_value+ to specify a value that will replace each field
+that is null (no text):
+ CSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"]
+
+===== Recipe: Handle Empty Fields
+
+Use option +:empty_value+ to specify a value that will replace each field
+that is empty (\String of length 0);
+ CSV.parse_line('a,"",b,"",c', empty_value: 'x') # => ["a", "x", "b", "x", "c"]
+
+=== Converting Fields
+
+You can use field converters to change parsed \String fields into other objects,
+or to otherwise modify the \String fields.
+
+==== Converting Fields to Objects
+
+Use field converters to change parsed \String objects into other, more specific, objects.
+
+There are built-in field converters for converting to objects of certain classes:
+- \Float
+- \Integer
+- \Date
+- \DateTime
+
+Other built-in field converters include:
+- +:numeric+: converts to \Integer and \Float.
+- +:all+: converts to \DateTime, \Integer, \Float.
+
+You can also define field converters to convert to objects of other classes.
+
+===== Recipe: Convert Fields to Integers
+
+Convert fields to \Integer objects using built-in converter +:integer+:
+ source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ parsed = CSV.parse(source, headers: true, converters: :integer)
+ parsed.map {|row| row['Value'].class} # => [Integer, Integer, Integer]
+
+===== Recipe: Convert Fields to Floats
+
+Convert fields to \Float objects using built-in converter +:float+:
+ source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ parsed = CSV.parse(source, headers: true, converters: :float)
+ parsed.map {|row| row['Value'].class} # => [Float, Float, Float]
+
+===== Recipe: Convert Fields to Numerics
+
+Convert fields to \Integer and \Float objects using built-in converter +:numeric+:
+ source = "Name,Value\nfoo,0\nbar,1.1\nbaz,2.2\n"
+ parsed = CSV.parse(source, headers: true, converters: :numeric)
+ parsed.map {|row| row['Value'].class} # => [Integer, Float, Float]
+
+===== Recipe: Convert Fields to Dates
+
+Convert fields to \Date objects using built-in converter +:date+:
+ source = "Name,Date\nfoo,2001-02-03\nbar,2001-02-04\nbaz,2001-02-03\n"
+ parsed = CSV.parse(source, headers: true, converters: :date)
+ parsed.map {|row| row['Date'].class} # => [Date, Date, Date]
+
+===== Recipe: Convert Fields to DateTimes
+
+Convert fields to \DateTime objects using built-in converter +:date_time+:
+ source = "Name,DateTime\nfoo,2001-02-03\nbar,2001-02-04\nbaz,2020-05-07T14:59:00-05:00\n"
+ parsed = CSV.parse(source, headers: true, converters: :date_time)
+ parsed.map {|row| row['DateTime'].class} # => [DateTime, DateTime, DateTime]
+
+===== Recipe: Convert Assorted Fields to Objects
+
+Convert assorted fields to objects using built-in converter +:all+:
+ source = "Type,Value\nInteger,0\nFloat,1.0\nDateTime,2001-02-04\n"
+ parsed = CSV.parse(source, headers: true, converters: :all)
+ parsed.map {|row| row['Value'].class} # => [Integer, Float, DateTime]
+
+===== Recipe: Convert Fields to Other Objects
+
+Define a custom field converter to convert \String fields into other objects.
+This example defines and uses a custom field converter
+that converts each column-1 value to a \Rational object:
+ rational_converter = proc do |field, field_context|
+ field_context.index == 1 ? field.to_r : field
+ end
+ source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ parsed = CSV.parse(source, headers: true, converters: rational_converter)
+ parsed.map {|row| row['Value'].class} # => [Rational, Rational, Rational]
+
+==== Recipe: Filter Field Strings
+
+Define a custom field converter to modify \String fields.
+This example defines and uses a custom field converter
+that strips whitespace from each field value:
+ strip_converter = proc {|field| field.strip }
+ source = "Name,Value\n foo , 0 \n bar , 1 \n baz , 2 \n"
+ parsed = CSV.parse(source, headers: true, converters: strip_converter)
+ parsed['Name'] # => ["foo", "bar", "baz"]
+ parsed['Value'] # => ["0", "1", "2"]
+
+==== Recipe: Register Field Converters
+
+Register a custom field converter, assigning it a name;
+then refer to the converter by its name:
+ rational_converter = proc do |field, field_context|
+ field_context.index == 1 ? field.to_r : field
+ end
+ CSV::Converters[:rational] = rational_converter
+ source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ parsed = CSV.parse(source, headers: true, converters: :rational)
+ parsed['Value'] # => [(0/1), (1/1), (2/1)]
+
+==== Using Multiple Field Converters
+
+You can use multiple field converters in either of these ways:
+- Specify converters in option +:converters+.
+- Specify converters in a custom converter list.
+
+===== Recipe: Specify Multiple Field Converters in Option +:converters+
+
+Apply multiple field converters by specifying them in option +:conveters+:
+ source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n"
+ parsed = CSV.parse(source, headers: true, converters: [:integer, :float])
+ parsed['Value'] # => [0, 1.0, 2.0]
+
+===== Recipe: Specify Multiple Field Converters in a Custom Converter List
+
+Apply multiple field converters by defining and registering a custom converter list:
+ strip_converter = proc {|field| field.strip }
+ CSV::Converters[:strip] = strip_converter
+ CSV::Converters[:my_converters] = [:integer, :float, :strip]
+ source = "Name,Value\n foo , 0 \n bar , 1.0 \n baz , 2.0 \n"
+ parsed = CSV.parse(source, headers: true, converters: :my_converters)
+ parsed['Name'] # => ["foo", "bar", "baz"]
+ parsed['Value'] # => [0, 1.0, 2.0]
+
+=== Converting Headers
+
+You can use header converters to modify parsed \String headers.
+
+Built-in header converters include:
+- +:symbol+: converts \String header to \Symbol.
+- +:downcase+: converts \String header to lowercase.
+
+You can also define header converters to otherwise modify header \Strings.
+
+==== Recipe: Convert Headers to Lowercase
+
+Convert headers to lowercase using built-in converter +:downcase+:
+ source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ parsed = CSV.parse(source, headers: true, header_converters: :downcase)
+ parsed.headers # => ["name", "value"]
+
+==== Recipe: Convert Headers to Symbols
+
+Convert headers to downcased Symbols using built-in converter +:symbol+:
+ source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ parsed = CSV.parse(source, headers: true, header_converters: :symbol)
+ parsed.headers # => [:name, :value]
+ parsed.headers.map {|header| header.class} # => [Symbol, Symbol]
+
+==== Recipe: Filter Header Strings
+
+Define a custom header converter to modify \String fields.
+This example defines and uses a custom header converter
+that capitalizes each header \String:
+ capitalize_converter = proc {|header| header.capitalize }
+ source = "NAME,VALUE\nfoo,0\nbar,1\nbaz,2\n"
+ parsed = CSV.parse(source, headers: true, header_converters: capitalize_converter)
+ parsed.headers # => ["Name", "Value"]
+
+==== Recipe: Register Header Converters
+
+Register a custom header converter, assigning it a name;
+then refer to the converter by its name:
+ capitalize_converter = proc {|header| header.capitalize }
+ CSV::HeaderConverters[:capitalize] = capitalize_converter
+ source = "NAME,VALUE\nfoo,0\nbar,1\nbaz,2\n"
+ parsed = CSV.parse(source, headers: true, header_converters: :capitalize)
+ parsed.headers # => ["Name", "Value"]
+
+==== Using Multiple Header Converters
+
+You can use multiple header converters in either of these ways:
+- Specify header converters in option +:header_converters+.
+- Specify header converters in a custom header converter list.
+
+===== Recipe: Specify Multiple Header Converters in Option :header_converters
+
+Apply multiple header converters by specifying them in option +:header_conveters+:
+ source = "Name,Value\nfoo,0\nbar,1.0\nbaz,2.0\n"
+ parsed = CSV.parse(source, headers: true, header_converters: [:downcase, :symbol])
+ parsed.headers # => [:name, :value]
+
+===== Recipe: Specify Multiple Header Converters in a Custom Header Converter List
+
+Apply multiple header converters by defining and registering a custom header converter list:
+ CSV::HeaderConverters[:my_header_converters] = [:symbol, :downcase]
+ source = "NAME,VALUE\nfoo,0\nbar,1.0\nbaz,2.0\n"
+ parsed = CSV.parse(source, headers: true, header_converters: :my_header_converters)
+ parsed.headers # => [:name, :value]
+
+=== Diagnostics
+
+==== Recipe: Capture Unconverted Fields
+
+To capture unconverted field values, use option +:unconverted_fields+:
+ source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ parsed = CSV.parse(source, converters: :integer, unconverted_fields: true)
+ parsed # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+ parsed.each {|row| p row.unconverted_fields }
+Output:
+ ["Name", "Value"]
+ ["foo", "0"]
+ ["bar", "1"]
+ ["baz", "2"]
+
+==== Recipe: Capture Field Info
+
+To capture field info in a custom converter, accept two block arguments.
+The first is the field value; the second is a +CSV::FieldInfo+ object:
+ strip_converter = proc {|field, field_info| p field_info; field.strip }
+ source = " foo , 0 \n bar , 1 \n baz , 2 \n"
+ parsed = CSV.parse(source, converters: strip_converter)
+ parsed # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+Output:
+ #<struct CSV::FieldInfo index=0, line=1, header=nil>
+ #<struct CSV::FieldInfo index=1, line=1, header=nil>
+ #<struct CSV::FieldInfo index=0, line=2, header=nil>
+ #<struct CSV::FieldInfo index=1, line=2, header=nil>
+ #<struct CSV::FieldInfo index=0, line=3, header=nil>
+ #<struct CSV::FieldInfo index=1, line=3, header=nil>
diff --git a/doc/csv/recipes/recipes.rdoc b/doc/csv/recipes/recipes.rdoc
new file mode 100644
index 0000000000..9e4eaa1da4
--- /dev/null
+++ b/doc/csv/recipes/recipes.rdoc
@@ -0,0 +1,6 @@
+== Recipes for \CSV
+
+See:
+- {Recipes for Parsing CSV}[./parsing_rdoc.html]
+- {Recipes for Generating CSV}[./generating_rdoc.html]
+- {Recipes for Filtering CSV}[./filtering_rdoc.html]
diff --git a/doc/dig_methods.rdoc b/doc/dig_methods.rdoc
new file mode 100644
index 0000000000..366275d451
--- /dev/null
+++ b/doc/dig_methods.rdoc
@@ -0,0 +1,82 @@
+= Dig Methods
+
+Ruby's +dig+ methods are useful for accessing nested data structures.
+
+Consider this data:
+ item = {
+ id: "0001",
+ type: "donut",
+ name: "Cake",
+ ppu: 0.55,
+ batters: {
+ batter: [
+ {id: "1001", type: "Regular"},
+ {id: "1002", type: "Chocolate"},
+ {id: "1003", type: "Blueberry"},
+ {id: "1004", type: "Devil's Food"}
+ ]
+ },
+ topping: [
+ {id: "5001", type: "None"},
+ {id: "5002", type: "Glazed"},
+ {id: "5005", type: "Sugar"},
+ {id: "5007", type: "Powdered Sugar"},
+ {id: "5006", type: "Chocolate with Sprinkles"},
+ {id: "5003", type: "Chocolate"},
+ {id: "5004", type: "Maple"}
+ ]
+ }
+
+Without a +dig+ method, you can write:
+ item[:batters][:batter][1][:type] # => "Chocolate"
+
+With a +dig+ method, you can write:
+ item.dig(:batters, :batter, 1, :type) # => "Chocolate"
+
+Without a +dig+ method, you can write, erroneously
+(raises <tt>NoMethodError (undefined method `[]' for nil:NilClass)</tt>):
+ item[:batters][:BATTER][1][:type]
+
+With a +dig+ method, you can write (still erroneously, but avoiding the exception):
+ item.dig(:batters, :BATTER, 1, :type) # => nil
+
+== Why Is +dig+ Better?
+
+- It has fewer syntactical elements (to get wrong).
+- It reads better.
+- It does not raise an exception if an item is not found.
+
+== How Does +dig+ Work?
+
+The call sequence is:
+ obj.dig(*identifiers)
+
+The +identifiers+ define a "path" into the nested data structures:
+- For each identifier in +identifiers+, calls method \#dig on a receiver
+ with that identifier.
+- The first receiver is +self+.
+- Each successive receiver is the value returned by the previous call to +dig+.
+- The value finally returned is the value returned by the last call to +dig+.
+
+A +dig+ method raises an exception if any receiver does not respond to \#dig:
+ h = { foo: 1 }
+ # Raises TypeError (Integer does not have #dig method):
+ h.dig(:foo, :bar)
+
+== What Else?
+
+The structure above has \Hash objects and \Array objects,
+both of which have instance method +dig+.
+
+Altogether there are six built-in Ruby classes that have method +dig+,
+three in the core classes and three in the standard library.
+
+In the core:
+- Array#dig: the first argument is an \Integer index.
+- Hash#dig: the first argument is a key.
+- Struct#dig: the first argument is a key.
+
+In the standard library:
+- OpenStruct#dig: the first argument is a \String name.
+- CSV::Table#dig: the first argument is an \Integer index or a \String header.
+- CSV::Row#dig: the first argument is an \Integer index or a \String header.
diff --git a/doc/dtrace_probes.rdoc b/doc/dtrace_probes.rdoc
index d2cdd56902..1b20597ab4 100644
--- a/doc/dtrace_probes.rdoc
+++ b/doc/dtrace_probes.rdoc
@@ -52,15 +52,21 @@ with when they are fired and the arguments they take:
[ruby:::method-entry(classname, methodname, filename, lineno);]
This probe is fired just before a method is entered.
- classname name of the class (a string)
- methodname name of the method about to be executed (a string)
- filename the file name where the method is _being called_ (a string)
- lineno the line number where the method is _being called_ (an int)
+ classname:: name of the class (a string)
+ methodname:: name of the method about to be executed (a string)
+ filename:: the file name where the method is _being called_ (a string)
+ lineno:: the line number where the method is _being called_ (an int)
+
+ *NOTE*: will only be fired if tracing is enabled, e.g. with: <code>TracePoint.new{}.enable</code>.
+ See Feature#14104[https://bugs.ruby-lang.org/issues/14104] for more details.
[ruby:::method-return(classname, methodname, filename, lineno);]
This probe is fired just after a method has returned. The arguments are the
same as "ruby:::method-entry".
+ *NOTE*: will only be fired if tracing is enabled, e.g. with: <code>TracePoint.new{}.enable</code>.
+ See Feature#14104[https://bugs.ruby-lang.org/issues/14104] for more details.
+
[ruby:::cmethod-entry(classname, methodname, filename, lineno);]
This probe is fired just before a C method is entered. The arguments are the
same as "ruby:::method-entry".
@@ -72,9 +78,9 @@ with when they are fired and the arguments they take:
[ruby:::require-entry(requiredfile, filename, lineno);]
This probe is fired on calls to rb_require_safe (when a file is required).
- requiredfile is the name of the file to be required (string).
- filename is the file that called "require" (string).
- lineno is the line number where the call to require was made (int).
+ requiredfile:: the name of the file to be required (string).
+ filename:: the file that called "+require+" (string).
+ lineno:: the line number where the call to require was made (int).
[ruby:::require-return(requiredfile, filename, lineno);]
This probe is fired just before rb_require_safe (when a file is required)
@@ -84,11 +90,11 @@ with when they are fired and the arguments they take:
[ruby:::find-require-entry(requiredfile, filename, lineno);]
This probe is fired right before search_required is called. search_required
determines whether the file has already been required by searching loaded
- features ($"), and if not, figures out which file must be loaded.
+ features (<code>$"</code>), and if not, figures out which file must be loaded.
- requiredfile is the file to be required (string).
- filename is the file that called "require" (string).
- lineno is the line number where the call to require was made (int).
+ requiredfile:: the file to be required (string).
+ filename:: the file that called "require" (string).
+ lineno:: the line number where the call to require was made (int).
[ruby:::find-require-return(requiredfile, filename, lineno);]
This probe is fired right after search_required returns. See the
@@ -106,56 +112,56 @@ with when they are fired and the arguments they take:
[ruby:::raise(classname, filename, lineno);]
This probe is fired when an exception is raised.
- classname is the class name of the raised exception (string)
- filename the name of the file where the exception was raised (string)
- lineno the line number in the file where the exception was raised (int)
+ classname:: the class name of the raised exception (string)
+ filename:: the name of the file where the exception was raised (string)
+ lineno:: the line number in the file where the exception was raised (int)
[ruby:::object-create(classname, filename, lineno);]
This probe is fired when an object is about to be allocated.
- classname the class of the allocated object (string)
- filename the name of the file where the object is allocated (string)
- lineno the line number in the file where the object is allocated (int)
+ classname:: the class of the allocated object (string)
+ filename:: the name of the file where the object is allocated (string)
+ lineno:: the line number in the file where the object is allocated (int)
[ruby:::array-create(length, filename, lineno);]
This probe is fired when an Array is about to be allocated.
- length the size of the array (long)
- filename the name of the file where the array is allocated (string)
- lineno the line number in the file where the array is allocated (int)
+ length:: the size of the array (long)
+ filename:: the name of the file where the array is allocated (string)
+ lineno:: the line number in the file where the array is allocated (int)
[ruby:::hash-create(length, filename, lineno);]
This probe is fired when a Hash is about to be allocated.
- length the size of the hash (long)
- filename the name of the file where the hash is allocated (string)
- lineno the line number in the file where the hash is allocated (int)
+ length:: the size of the hash (long)
+ filename:: the name of the file where the hash is allocated (string)
+ lineno:: the line number in the file where the hash is allocated (int)
[ruby:::string-create(length, filename, lineno);]
This probe is fired when a String is about to be allocated.
- length the size of the string (long)
- filename the name of the file where the string is allocated (string)
- lineno the line number in the file where the string is allocated (int)
+ length:: the size of the string (long)
+ filename:: the name of the file where the string is allocated (string)
+ lineno:: the line number in the file where the string is allocated (int)
[ruby:::symbol-create(str, filename, lineno);]
This probe is fired when a Symbol is about to be allocated.
- str the contents of the symbol (string)
- filename the name of the file where the string is allocated (string)
- lineno the line number in the file where the string is allocated (int)
+ str:: the contents of the symbol (string)
+ filename:: the name of the file where the string is allocated (string)
+ lineno:: the line number in the file where the string is allocated (int)
[ruby:::parse-begin(sourcefile, lineno);]
Fired just before parsing and compiling a source file.
- sourcefile the file being parsed (string)
- lineno the line number where the source starts (int)
+ sourcefile:: the file being parsed (string)
+ lineno:: the line number where the source starts (int)
[ruby:::parse-end(sourcefile, lineno);]
Fired just after parsing and compiling a source file.
- sourcefile the file being parsed (string)
- lineno the line number where the source ended (int)
+ sourcefile:: the file being parsed (string)
+ lineno:: the line number where the source ended (int)
[ruby:::gc-mark-begin();]
Fired at the beginning of a mark phase.
@@ -172,7 +178,7 @@ with when they are fired and the arguments they take:
[ruby:::method-cache-clear(class, sourcefile, lineno);]
Fired when the method cache is cleared.
- class is the classname being cleared, or "global" (string)
- sourcefile the file being parsed (string)
- lineno the line number where the source ended (int)
+ class:: the classname being cleared, or "global" (string)
+ sourcefile:: the file being parsed (string)
+ lineno:: the line number where the source ended (int)
diff --git a/doc/extension.ja.rdoc b/doc/extension.ja.rdoc
index 47303ec408..fe483e50d3 100644
--- a/doc/extension.ja.rdoc
+++ b/doc/extension.ja.rdoc
@@ -1829,6 +1829,17 @@ rb_ary_store() などの,適切な API 関数を利用するようにして下
そのほか,対応についての詳細は extension.rdoc の「Appendix D. Generational
GC」を参照して下さい.
+== Appendix E. Ractor サポート
+
+Ruby 3.0 から、Ruby プログラムを並列に実行するための仕組みである Ractor
+が導入されました。適切に並列に実行するためには、Ractor サポートが必要に
+なります。サポートしていないライブラリは、メイン Ractor 以外で実行すると
+エラーになります(Ractor::UnsafeError)。
+
+Ractor をサポートするための詳細は、extension.rdoc の「Appendix F. Ractor
+support」を参照してください。
+
+
:enddoc: Local variables:
:enddoc: fill-column: 60
:enddoc: end:
diff --git a/doc/extension.rdoc b/doc/extension.rdoc
index 79eb96d518..71a03cbf52 100644
--- a/doc/extension.rdoc
+++ b/doc/extension.rdoc
@@ -457,8 +457,6 @@ To specify whether keyword arguments are passed when calling super:
RB_NO_KEYWORDS :: Do not pass keywords
RB_PASS_KEYWORDS :: Pass keywords, final argument should be a hash of keywords
-RB_PASS_EMPTY_KEYWORDS :: Pass empty keywords (not included in arguments)
- (this will be removed in Ruby 3.0)
RB_PASS_CALLED_KEYWORDS :: Pass keywords if current method was called with
keywords, useful for argument delegation
@@ -678,7 +676,8 @@ member of the struct.
void (*dmark)(void*);
void (*dfree)(void*);
size_t (*dsize)(const void *);
- void *reserved[2];
+ void (*dcompact)(void*);
+ void *reserved[1];
} function;
const rb_data_type_t *parent;
void *data;
@@ -710,7 +709,15 @@ Its parameter is a pointer to your struct.
You can pass 0 as dsize if it is hard to implement such a function.
But it is still recommended to avoid 0.
-You have to fill reserved and parent with 0.
+dcompact is invoked when memory compaction took place.
+Referred Ruby objects that were marked by rb_gc_mark_movable()
+can here be updated per rb_gc_location().
+
+You have to fill reserved with 0.
+
+parent can point to another C type definition that the Ruby object
+is inherited from. Then TypedData_Get_Struct() does also accept
+derived objects.
You can fill "data" with an arbitrary value for your use.
Ruby does nothing with the member.
@@ -742,6 +749,14 @@ RUBY_TYPED_WB_PROTECTED ::
More about write barriers can be found in "Generational GC" in
Appendix D.
+RUBY_TYPED_FROZEN_SHAREABLE ::
+
+ This flag indicates that the object is shareable object
+ if the object is frozen. See Appendix F more details.
+
+ If this flag is not set, the object can not become a shareable
+ object by Ractor.make_shareable() method.
+
You can allocate and wrap the structure in one step.
TypedData_Make_Struct(klass, type, data_type, sval)
@@ -1423,28 +1438,6 @@ rb_scan_args(int argc, VALUE *argv, const char *fmt, ...) ::
; argument captured as a hash.
; If keyword arguments are not
; provided, returns nil.
- ;
- ; Currently, will also consider
- ; final argument as keywords if
- ; it is a hash or can be
- ; converted to a hash with
- ; #to_hash. When the last
- ; argument is nil, it is
- ; captured if it is not
- ; ambiguous to take it as
- ; empty option hash; i.e. '*'
- ; is not specified and
- ; arguments are given more
- ; than sufficient.
- ;
- ; However, handling final
- ; argument as keywords if
- ; method was not called with
- ; keywords (whether final
- ; argument is hash or nil) is
- ; deprecated. In that case, a
- ; warning will be emitted, and
- ; in Ruby 3.0 it will be an error.
sym-for-block-arg := "&" ; Indicates that an iterator
; block should be captured if
; given
@@ -1469,8 +1462,6 @@ rb_scan_args_kw(int kw_splat, int argc, VALUE *argv, const char *fmt, ...) ::
RB_SCAN_ARGS_PASS_CALLED_KEYWORDS :: Same behavior as +rb_scan_args+.
RB_SCAN_ARGS_KEYWORDS :: The final argument should be a hash treated as
keywords.
- RB_SCAN_ARGS_EMPTY_KEYWORDS :: Don't treat a final hash as keywords.
- (this will be removed in Ruby 3.0)
RB_SCAN_ARGS_LAST_HASH_KEYWORDS :: Treat a final argument as keywords if it
is a hash, and not as keywords otherwise.
@@ -1946,6 +1937,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)
#endif
== Appendix C. Functions available for use in extconf.rb
@@ -2049,7 +2041,7 @@ Before inserting write barriers, you need to know about RGenGC algorithm
available in include/ruby/ruby.h. An example is available in iseq.c.
For a complete guide for RGenGC and write barriers, please refer to
-<https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/RGenGC>.
+<https://bugs.ruby-lang.org/projects/ruby-master/wiki/RGenGC>.
== Appendix E. RB_GC_GUARD to protect from premature GC
@@ -2100,6 +2092,89 @@ keyword in C. RB_GC_GUARD has the following advantages:
compilers and architectures. RB_GC_GUARD is customizable for broken
systems/compilers without negatively affecting other systems.
+== Appendix F. Ractor support
+
+Ractor is parallel execution mechanism introduced from Ruby 3.0. All
+ractrors can run in parallel by different OS thread (underlying system
+provided thread), so the C extension should be thread-safe. Now we call
+the property that C extension can run in multiple ractors "Ractor-safe".
+
+By default, all C extensions are recognized as Ractor-unsafe. If C
+extension becomes Ractor-safe, the extension should call
+rb_ext_ractor_safe(true) at the Init_ function and all defined method
+marked as Ractor-safe. Ractor-unsafe C-methods only been called from
+main-ractor. If non-main ractor calls it, then Ractor::UnsafeError is
+raised.
+
+BTW non-"Ractor-safe" extensions raises an error on non-main ractors, so
+that it is "safe" because unsafe operations are not allowed.
+"Ractor-safe" property means "multi-Ractor-ready" or "safe on
+multi-ractors execution". "Ractor-safe" term comes from "Thread-safe".
+
+To make "Ractor-safe" C extension, we need to check the following points:
+
+(1) Do not share unshareable objects between ractors
+
+For example, C's global variable can lead sharing an unshareable objects
+betwee ractors.
+
+ VALUE g_var;
+ VALUE set(VALUE self, VALUE v){ return g_var = v; }
+ VALUE get(VALUE self){ return g_var; }
+
+set() and get() pair can share an unshareable objects using g_var, and
+it is Ractor-unsafe.
+
+Not only using global variables directly, some indirect data structure
+such as global st_table can share the objects, so please take care.
+
+Note that class and module objects are shareable objects, so you can
+keep the code "cFoo = rb_define_class(...)" with C's global variables.
+
+(2) Check the thread-safety of the extension
+
+An extension should be thread-safe. For example, the following code is
+not thread-safe:
+
+ bool g_called = false;
+ VALUE call(VALUE self) {
+ if (g_called) rb_raise("recursive call is not allowed.");
+ g_called = true;
+ VALUE ret = do_something();
+ g_called = false;
+ return ret;
+ }
+
+because g_called global variable should be synchronized by other
+ractor's threads. To avoid such data-race, some synchronization should
+be used. Check include/ruby/thread_native.h and include/ruby/atomic.h.
+
+On the Ractor mechanism, most of objects given by the method parameters
+or the receiver are isolated by Ractor's boundary, it is easy to make
+thread-safe code than usual thread-programming in general. For example,
+we don't need to lock an array object to access the element of it.
+
+(3) Check the thread-safety of using library
+
+If an extension relies on the external library libfoo and the function
+foo(), the function foo() should be thread safe.
+
+(4) Make an object shareable
+
+This is not required to make an extension Ractor-safe.
+
+If an extension provides special objects defined by rb_data_type_t,
+consider these objects can become shareable or not.
+
+RUBY_TYPED_FROZEN_SHAREABLE flag indicates that these objects can be
+shareable objects if the object is frozen. This means that if the object
+is frozen, the mutation of wrapped data is not allowed.
+
+(5) Others
+
+Maybe there are more points which should be considered to make
+Ractor-safe extension, so this document will be extended.
+
:enddoc: Local variables:
:enddoc: fill-column: 70
:enddoc: end:
diff --git a/doc/fiber.md b/doc/fiber.md
new file mode 100644
index 0000000000..5abd848677
--- /dev/null
+++ b/doc/fiber.md
@@ -0,0 +1,191 @@
+# 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)
+```
+
+### 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 file descriptor 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
+
+ # Sleep the current task for the specified duration, or forever if not
+ # specified.
+ # @param duration [Numeric] The amount of time to sleep in seconds.
+ def kernel_sleep(duration = nil)
+ 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/globals.rdoc b/doc/globals.rdoc
index 89b94e9a8f..1d7cda69f9 100644
--- a/doc/globals.rdoc
+++ b/doc/globals.rdoc
@@ -50,9 +50,6 @@ $-p:: True if option <tt>-p</tt> is set. Read-only variable.
== Pre-defined global constants
-TRUE:: The typical true value. Deprecated.
-FALSE:: The +false+ itself. Deprecated.
-NIL:: The +nil+ itself. Deprecated.
STDIN:: The standard input. The default value for $stdin.
STDOUT:: The standard output. The default value for $stdout.
STDERR:: The standard error output. The default value for $stderr.
diff --git a/doc/implicit_conversion.rdoc b/doc/implicit_conversion.rdoc
new file mode 100644
index 0000000000..0c2a1d4971
--- /dev/null
+++ b/doc/implicit_conversion.rdoc
@@ -0,0 +1,198 @@
+== Implicit Conversions
+
+Some Ruby methods accept one or more objects
+that can be either:
+* <i>Of a given class</i>, and so accepted as is.
+* <i>Implicitly convertible to that class</i>, in which case
+ the called method converts the object.
+
+For each of the relevant classes, the conversion is done by calling
+a specific conversion method:
+
+* Array: +to_ary+
+* Hash: +to_hash+
+* Integer: +to_int+
+* String: +to_str+
+
+=== Array-Convertible Objects
+
+An <i>Array-convertible object</i> is an object that:
+* Has instance method +to_ary+.
+* The method accepts no arguments.
+* The method returns an object +obj+ for which <tt>obj.kind_of?(Array)</tt> returns +true+.
+
+The examples in this section use method <tt>Array#replace</tt>,
+which accepts an Array-convertible argument.
+
+This class is Array-convertible:
+
+ class ArrayConvertible
+ def to_ary
+ [:foo, 'bar', 2]
+ end
+ end
+ a = []
+ a.replace(ArrayConvertible.new) # => [:foo, "bar", 2]
+
+This class is not Array-convertible (no +to_ary+ method):
+
+ class NotArrayConvertible; end
+ a = []
+ # Raises TypeError (no implicit conversion of NotArrayConvertible into Array)
+ a.replace(NotArrayConvertible.new)
+
+This class is not Array-convertible (method +to_ary+ takes arguments):
+
+ class NotArrayConvertible
+ def to_ary(x)
+ [:foo, 'bar', 2]
+ end
+ end
+ a = []
+ # Raises ArgumentError (wrong number of arguments (given 0, expected 1))
+ a.replace(NotArrayConvertible.new)
+
+This class is not Array-convertible (method +to_ary+ returns non-Array):
+
+ class NotArrayConvertible
+ def to_ary
+ :foo
+ end
+ end
+ a = []
+ # Raises TypeError (can't convert NotArrayConvertible to Array (NotArrayConvertible#to_ary gives Symbol))
+ a.replace(NotArrayConvertible.new)
+
+=== Hash-Convertible Objects
+
+A <i>Hash-convertible object</i> is an object that:
+* Has instance method +to_hash+.
+* The method accepts no arguments.
+* The method returns an object +obj+ for which <tt>obj.kind_of?(Hash)</tt> returns +true+.
+
+The examples in this section use method <tt>Hash#merge</tt>,
+which accepts a Hash-convertible argument.
+
+This class is Hash-convertible:
+
+ class HashConvertible
+ def to_hash
+ {foo: 0, bar: 1, baz: 2}
+ end
+ end
+ h = {}
+ h.merge(HashConvertible.new) # => {:foo=>0, :bar=>1, :baz=>2}
+
+This class is not Hash-convertible (no +to_hash+ method):
+
+ class NotHashConvertible; end
+ h = {}
+ # Raises TypeError (no implicit conversion of NotHashConvertible into Hash)
+ h.merge(NotHashConvertible.new)
+
+This class is not Hash-convertible (method +to_hash+ takes arguments):
+
+ class NotHashConvertible
+ def to_hash(x)
+ {foo: 0, bar: 1, baz: 2}
+ end
+ end
+ h = {}
+ # Raises ArgumentError (wrong number of arguments (given 0, expected 1))
+ h.merge(NotHashConvertible.new)
+
+This class is not Hash-convertible (method +to_hash+ returns non-Hash):
+
+ class NotHashConvertible
+ def to_hash
+ :foo
+ end
+ end
+ h = {}
+ # Raises TypeError (can't convert NotHashConvertible to Hash (ToHashReturnsNonHash#to_hash gives Symbol))
+ h.merge(NotHashConvertible.new)
+
+=== Integer-Convertible Objects
+
+An <i>Integer-convertible object</i> is an object that:
+* Has instance method +to_int+.
+* The method accepts no arguments.
+* The method returns an object +obj+ for which <tt>obj.kind_of?(Integer)</tt> returns +true+.
+
+The examples in this section use method <tt>Array.new</tt>,
+which accepts an Integer-convertible argument.
+
+This user-defined class is Integer-convertible:
+
+ class IntegerConvertible
+ def to_int
+ 3
+ end
+ end
+ a = Array.new(IntegerConvertible.new).size
+ a # => 3
+
+This class is not Integer-convertible (method +to_int+ takes arguments):
+
+ class NotIntegerConvertible
+ def to_int(x)
+ 3
+ end
+ end
+ # Raises ArgumentError (wrong number of arguments (given 0, expected 1))
+ Array.new(NotIntegerConvertible.new)
+
+This class is not Integer-convertible (method +to_int+ returns non-Integer):
+
+ class NotIntegerConvertible
+ def to_int
+ :foo
+ end
+ end
+ # Raises TypeError (can't convert NotIntegerConvertible to Integer (NotIntegerConvertible#to_int gives Symbol))
+ Array.new(NotIntegerConvertible.new)
+
+=== String-Convertible Objects
+
+A <i>String-convertible object</i> is an object that:
+* Has instance method +to_str+.
+* The method accepts no arguments.
+* The method returns an object +obj+ for which <tt>obj.kind_of?(String)</tt> returns +true+.
+
+The examples in this section use method <tt>String::new</tt>,
+which accepts a String-convertible argument.
+
+This class is String-convertible:
+
+ class StringConvertible
+ def to_str
+ 'foo'
+ end
+ end
+ String.new(StringConvertible.new) # => "foo"
+
+This class is not String-convertible (no +to_str+ method):
+
+ class NotStringConvertible; end
+ # Raises TypeError (no implicit conversion of NotStringConvertible into String)
+ String.new(NotStringConvertible.new)
+
+This class is not String-convertible (method +to_str+ takes arguments):
+
+ class NotStringConvertible
+ def to_str(x)
+ 'foo'
+ end
+ end
+ # Raises ArgumentError (wrong number of arguments (given 0, expected 1))
+ String.new(NotStringConvertible.new)
+
+This class is not String-convertible (method +to_str+ returns non-String):
+
+ class NotStringConvertible
+ def to_str
+ :foo
+ end
+ end
+ # Raises TypeError (can't convert NotStringConvertible to String (NotStringConvertible#to_str gives Symbol))
+ String.new(NotStringConvertible.new)
diff --git a/doc/keywords.rdoc b/doc/keywords.rdoc
index a74126823d..cb1cff33f0 100644
--- a/doc/keywords.rdoc
+++ b/doc/keywords.rdoc
@@ -82,6 +82,8 @@ if::
in::
Used to separate the iterable object and iterator variable in a +for+ loop.
See {control expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+ It also serves as a pattern in a +case+ expression.
+ See {pattern matching}[rdoc-ref:syntax/pattern_matching.rdoc]
module::
Creates or opens a module. See {modules and classes
diff --git a/doc/maintainers.rdoc b/doc/maintainers.rdoc
index 98de9f2549..64510b2559 100644
--- a/doc/maintainers.rdoc
+++ b/doc/maintainers.rdoc
@@ -13,7 +13,7 @@ A module maintainer is responsible for a certain part of Ruby.
* They have "developer" role on the Redmine to modify issues.
* They have authority to decide the feature of their part. But they should always respect discussions on ruby-core/ruby-dev.
-A submaintainer of a module is like a maintainer. But The submaintainer does
+A submaintainer of a module is like a maintainer. But the submaintainer does
not have authority to change/add a feature on his/her part. They need consensus
on ruby-core/ruby-dev before changing/adding. Some of submaintainers have
commit right, others don't.
@@ -30,77 +30,17 @@ Koichi Sasada (ko1)
Yukihiro Matsumoto (matz)
-=== Documentation
-
-Zachary Scott (zzak)
-
== Standard Library Maintainers
=== Libraries
-[lib/English.rb]
- _unmaintained_
-[lib/abbrev.rb]
- Akinori MUSHA (knu)
-[lib/base64.rb]
- Yusuke Endoh (mame)
-[lib/drb.rb, lib/drb/*]
- Masatoshi SEKI (seki)
-[lib/debug.rb]
- _unmaintained_
-[lib/erb.rb]
- Masatoshi SEKI (seki), Takashi Kokubun (k0kubun)
-[lib/find.rb]
- Kazuki Tsujimoto (ktsj)
[lib/mkmf.rb]
_unmaintained_
-[lib/monitor.rb]
- Shugo Maeda (shugo)
-[lib/net/ftp.rb]
- Shugo Maeda (shugo)
-[lib/net/imap.rb]
- Shugo Maeda (shugo)
-[lib/net/http.rb, lib/net/https.rb]
- NARUSE, Yui (naruse)
-[lib/net/protocol.rb]
- _unmaintained_
-[lib/open-uri.rb]
- Tanaka Akira (akr)
-[lib/optparse.rb, lib/optparse/*]
- Nobuyuki Nakada (nobu)
-[lib/pp.rb]
- Tanaka Akira (akr)
-[lib/prettyprint.rb]
- Tanaka Akira (akr)
-[lib/resolv-replace.rb]
- Tanaka Akira (akr)
-[lib/resolv.rb]
- Tanaka Akira (akr)
-[lib/rinda/*]
- Masatoshi SEKI (seki)
[lib/rubygems.rb, lib/rubygems/*]
Eric Hodel (drbrain), Hiroshi SHIBATA (hsbt)
https://github.com/rubygems/rubygems
-[lib/set.rb]
- Akinori MUSHA (knu)
-[lib/securerandom.rb]
- Tanaka Akira (akr)
-[lib/shellwords.rb]
- Akinori MUSHA (knu)
-[lib/tempfile.rb]
- _unmaintained_
-[lib/tmpdir.rb]
- _unmaintained_
-[lib/time.rb]
- Tanaka Akira (akr)
-[lib/tsort.rb]
- Tanaka Akira (akr)
-[lib/un.rb]
- WATANABE Hirofumi (eban)
[lib/unicode_normalize.rb, lib/unicode_normalize/*]
Martin J. Dürst
-[lib/weakref.rb]
- _unmaintained_
=== Extensions
@@ -108,47 +48,41 @@ Zachary Scott (zzak)
Koichi Sasada (ko1)
[ext/coverage]
Yusuke Endoh (mame)
-[ext/digest, ext/digest/*]
- Akinori MUSHA (knu)
[ext/fiber]
Koichi Sasada (ko1)
-[ext/io/nonblock]
- Nobuyuki Nakada (nobu)
-[ext/io/wait]
- Nobuyuki Nakada (nobu)
-[ext/nkf]
- NARUSE, Yui (naruse)
+[ext/monitor]
+ Koichi Sasada (ko1)
[ext/objspace]
_unmaintained_
-[ext/pathname]
- Tanaka Akira (akr)
[ext/pty]
_unmaintained_
-[ext/readline]
- TAKAO Kouji (kouji)
[ext/ripper]
_unmaintained_
[ext/socket]
* Tanaka Akira (akr)
* API change needs matz's approval
-[ext/syslog]
- Akinori MUSHA (knu)
[ext/win32]
NAKAMURA Usaku (usa)
-[ext/win32ole]
- Masaki Suketa (suke)
== Default gems Maintainers
=== Libraries
+[lib/abbrev.rb]
+ Akinori MUSHA (knu)
+ https://github.com/ruby/abbrev
+ https://rubygems.org/gems/abbrev
+[lib/base64.rb]
+ Yusuke Endoh (mame)
+ https://github.com/ruby/base64
+ https://rubygems.org/gems/base64
[lib/benchmark.rb]
_unmaintained_
- https://github.com/bundler/benchmark
+ https://github.com/ruby/benchmark
https://rubygems.org/gems/benchmark
[lib/bundler.rb, lib/bundler/*]
Hiroshi SHIBATA (hsbt)
- https://github.com/bundler/bundler
+ https://github.com/rubygems/rubygems
https://rubygems.org/gems/bundler
[lib/cgi.rb, lib/cgi/*]
Takeyuki Fujioka (xibbar)
@@ -158,6 +92,13 @@ Zachary Scott (zzak)
Kenta Murata (mrkn), Kouhei Sutou (kou)
https://github.com/ruby/csv
https://rubygems.org/gems/csv
+[lib/English.rb]
+ _unmaintained_
+ https://github.com/ruby/English
+ https://rubygems.org/gems/English
+[lib/debug.rb]
+ _unmaintained_
+ https://github.com/ruby/debug
[lib/delegate.rb]
_unmaintained_
https://github.com/ruby/delegate
@@ -165,10 +106,27 @@ Zachary Scott (zzak)
[lib/did_you_mean.rb]
Yuki Nishijima (yuki24)
https://github.com/ruby/did_you_mean
+ https://rubygems.org/gems/did_you_mean
+[ext/digest, ext/digest/*]
+ Akinori MUSHA (knu)
+ https://github.com/ruby/digest
+ https://rubygems.org/gems/digest
+[lib/drb.rb, lib/drb/*]
+ Masatoshi SEKI (seki)
+ https://github.com/ruby/drb
+ https://rubygems.org/gems/drb
+[lib/erb.rb]
+ Masatoshi SEKI (seki), Takashi Kokubun (k0kubun)
+ https://github.com/ruby/erb
+ https://rubygems.org/gems/erb
[lib/fileutils.rb]
_unmaintained_
https://github.com/ruby/fileutils
https://rubygems.org/gems/fileutils
+[lib/find.rb]
+ Kazuki Tsujimoto (ktsj)
+ https://github.com/ruby/find
+ https://rubygems.org/gems/find
[lib/forwardable.rb]
Keiju ISHITSUKA (keiju)
https://github.com/ruby/forwardable
@@ -182,21 +140,36 @@ Zachary Scott (zzak)
https://github.com/ruby/ipaddr
https://rubygems.org/gems/ipaddr
[lib/irb.rb, lib/irb/*]
- Keiju ISHITSUKA (keiju)
+ aycabta
https://github.com/ruby/irb
https://rubygems.org/gems/irb
+[lib/optparse.rb, lib/optparse/*]
+ Nobuyuki Nakada (nobu)
+ https://github.com/ruby/optparse
[lib/logger.rb]
Naotoshi Seo (sonots)
https://github.com/ruby/logger
https://rubygems.org/gems/logger
[lib/matrix.rb]
- Marc-Andre Lafortune (marcandre)
+ Marc-André Lafortune (marcandre)
https://github.com/ruby/matrix
https://rubygems.org/gems/matrix
[lib/mutex_m.rb]
Keiju ISHITSUKA (keiju)
https://github.com/ruby/mutex_m
https://rubygems.org/gems/mutex_m
+[lib/net/ftp.rb]
+ Shugo Maeda (shugo)
+ https://github.com/ruby/net-ftp
+ https://rubygems.org/gems/net-ftp
+[lib/net/http.rb, lib/net/https.rb]
+ NARUSE, Yui (naruse)
+ https://github.com/ruby/net-http
+ https://rubygems.org/gems/net-http
+[lib/net/imap.rb]
+ Shugo Maeda (shugo)
+ https://github.com/ruby/net-imap
+ https://rubygems.org/gems/net-imap
[lib/net/pop.rb]
_unmaintained_
https://github.com/ruby/net-pop
@@ -205,20 +178,37 @@ Zachary Scott (zzak)
_unmaintained_
https://github.com/ruby/net-smtp
https://rubygems.org/gems/net-smtp
+[lib/net/protocol.rb]
+ _unmaintained_
+ https://github.com/ruby/net-protocol
+ https://rubygems.org/gems/net-protocol
[lib/observer.rb]
_unmaintained_
https://github.com/ruby/observer
+ https://rubygems.org/gems/observer
[lib/open3.rb]
_unmaintained_
https://github.com/ruby/open3
https://rubygems.org/gems/open3
+[lib/open-uri.rb]
+ Tanaka Akira (akr)
+ https://github.com/ruby/open-uri
[lib/ostruct.rb]
- Marc-Andre Lafortune (marcandre)
+ Marc-André Lafortune (marcandre)
https://github.com/ruby/ostruct
https://rubygems.org/gems/ostruct
+[lib/pp.rb]
+ Tanaka Akira (akr)
+ https://github.com/ruby/pp
+ https://rubygems.org/gems/pp
+[lib/prettyprint.rb]
+ Tanaka Akira (akr)
+ https://github.com/ruby/prettyprint
+ https://rubygems.org/gems/prettyprint
[lib/prime.rb]
- Yuki Sonoda (yugui)
+ Marc-André Lafortune (marcandre)
https://github.com/ruby/prime
+ https://rubygems.org/gems/prime
[lib/pstore.rb]
_unmaintained_
https://github.com/ruby/pstore
@@ -231,6 +221,14 @@ Zachary Scott (zzak)
aycabta
https://github.com/ruby/readline
https://rubygems.org/gems/readline
+[lib/resolv.rb]
+ Tanaka Akira (akr)
+ https://github.com/ruby/resolv
+ https://rubygems.org/gems/resolv
+[lib/resolv-replace.rb]
+ Tanaka Akira (akr)
+ https://github.com/ruby/resolv-replace
+ https://rubygems.org/gems/resolv-replace
[lib/rdoc.rb, lib/rdoc/*]
Eric Hodel (drbrain), Hiroshi SHIBATA (hsbt)
https://github.com/ruby/rdoc
@@ -239,38 +237,70 @@ Zachary Scott (zzak)
aycabta
https://github.com/ruby/reline
https://rubygems.org/gems/reline
-[lib/rexml/*]
- Kouhei Sutou (kou)
- https://github.com/ruby/rexml
- https://rubygems.org/gems/rexml
-[lib/rss.rb, lib/rss/*]
- Kouhei Sutou (kou)
- https://github.com/ruby/rss
- https://rubygems.org/gems/rss
+[lib/rinda/*]
+ Masatoshi SEKI (seki)
+ https://github.com/ruby/rinda
+ https://rubygems.org/gems/rinda
+[lib/securerandom.rb]
+ Tanaka Akira (akr)
+ https://github.com/ruby/securerandom
+ https://rubygems.org/gems/securerandom
+[lib/set.rb]
+ Akinori MUSHA (knu)
+ https://github.com/ruby/set
+ https://rubygems.org/gems/set
+[lib/shellwords.rb]
+ Akinori MUSHA (knu)
+ https://github.com/ruby/shellwords
+ https://rubygems.org/gems/shellwords
[lib/singleton.rb]
Yukihiro Matsumoto (matz)
https://github.com/ruby/singleton
https://rubygems.org/gems/singleton
+[lib/tempfile.rb]
+ _unmaintained_
+ https://github.com/ruby/tempfile
+ https://rubygems.org/gems/tempfile
+[lib/time.rb]
+ Tanaka Akira (akr)
+ https://github.com/ruby/time
+ https://rubygems.org/gems/time
[lib/timeout.rb]
Yukihiro Matsumoto (matz)
https://github.com/ruby/timeout
+ https://rubygems.org/gems/timeout
[lib/thwait.rb]
Keiju ISHITSUKA (keiju)
https://github.com/ruby/thwait
https://rubygems.org/gems/thwait
+[lib/tmpdir.rb]
+ _unmaintained_
+ https://github.com/ruby/tmpdir
+ https://rubygems.org/gems/tmpdir
[lib/tracer.rb]
Keiju ISHITSUKA (keiju)
https://github.com/ruby/tracer
+ https://rubygems.org/gems/tracer
+[lib/tsort.rb]
+ Tanaka Akira (akr)
+ https://github.com/ruby/tsort
+ https://rubygems.org/gems/tsort
+[lib/un.rb]
+ WATANABE Hirofumi (eban)
+ https://github.com/ruby/un
+ https://rubygems.org/gems/un
[lib/uri.rb, lib/uri/*]
YAMADA, Akira (akira)
https://github.com/ruby/uri
-[lib/webrick.rb, lib/webrick/*]
- Eric Wong (normalperson)
- https://bugs.ruby-lang.org/
- https://rubygems.org/gems/webrick
+ https://rubygems.org/gems/uri
[lib/yaml.rb, lib/yaml/*]
Aaron Patterson (tenderlove), Hiroshi SHIBATA (hsbt)
https://github.com/ruby/yaml
+ https://rubygems.org/gems/yaml
+[lib/weakref.rb]
+ _unmaintained_
+ https://github.com/ruby/weakref
+ https://rubygems.org/gems/weakref
=== Extensions
@@ -310,14 +340,30 @@ Zachary Scott (zzak)
Nobuyuki Nakada (nobu)
https://github.com/ruby/io-console
https://rubygems.org/gems/io-console
+[ext/io/nonblock]
+ Nobuyuki Nakada (nobu)
+ https://github.com/ruby/io-nonblock
+ https://rubygems.org/gems/io-nonblock
+[ext/io/wait]
+ Nobuyuki Nakada (nobu)
+ https://github.com/ruby/io-wait
+ https://rubygems.org/gems/io-wait
[ext/json]
NARUSE, Yui (naruse), Hiroshi SHIBATA (hsbt)
https://github.com/flori/json
https://rubygems.org/gems/json
+[ext/nkf]
+ NARUSE, Yui (naruse)
+ https://github.com/ruby/nkf
+ https://rubygems.org/gems/nkf
[ext/openssl]
Kazuki Yamaguchi (rhe)
https://github.com/ruby/openssl
https://rubygems.org/gems/openssl
+[ext/pathname]
+ Tanaka Akira (akr)
+ https://github.com/ruby/pathname
+ https://rubygems.org/gems/pathname
[ext/psych]
Aaron Patterson (tenderlove), Hiroshi SHIBATA (hsbt)
https://github.com/ruby/psych
@@ -326,10 +372,10 @@ Zachary Scott (zzak)
Aaron Patterson (tenderlove), Hiroshi SHIBATA (hsbt)
https://github.com/ruby/racc
https://rubygems.org/gems/racc
-[ext/sdbm]
- Yukihiro Matsumoto (matz)
- https://github.com/ruby/sdbm
- https://rubygems.org/gems/sdbm
+[ext/readline]
+ TAKAO Kouji (kouji)
+ https://github.com/ruby/readline-ext
+ https://rubygems.org/gems/readline-ext
[ext/stringio]
Nobuyuki Nakada (nobu)
https://github.com/ruby/stringio
@@ -338,6 +384,14 @@ Zachary Scott (zzak)
Kouhei Sutou (kou)
https://github.com/ruby/strscan
https://rubygems.org/gems/strscan
+[ext/syslog]
+ Akinori MUSHA (knu)
+ https://github.com/ruby/syslog
+ https://rubygems.org/gems/syslog
+[ext/win32ole]
+ Masaki Suketa (suke)
+ https://github.com/ruby/win32ole
+ https://rubygems.org/gems/win32ole
[ext/zlib]
NARUSE, Yui (naruse)
https://github.com/ruby/zlib
@@ -347,13 +401,17 @@ Zachary Scott (zzak)
[minitest]
https://github.com/seattlerb/minitest
-[net-telnet]
- https://github.com/ruby/net-telnet
[power_assert]
- https://github.com/k-tsj/power_assert
+ https://github.com/ruby/power_assert
[rake]
https://github.com/ruby/rake
[test-unit]
https://github.com/test-unit/test-unit
-[xmlrpc]
- https://github.com/ruby/xmlrpc
+[rexml]
+ https://github.com/ruby/rexml
+[rss]
+ https://github.com/ruby/rss
+[rbs]
+ https://github.com/ruby/rbs
+[typeprof]
+ https://github.com/ruby/typeprof
diff --git a/doc/make_cheatsheet.md b/doc/make_cheatsheet.md
new file mode 100644
index 0000000000..bf245bea03
--- /dev/null
+++ b/doc/make_cheatsheet.md
@@ -0,0 +1,124 @@
+# How to use "configure" and "make" commands for Ruby
+
+This is for developers of Ruby.
+If you are a user of Ruby, please see README.md.
+
+## In-place build
+
+```
+$ autoconf
+$ ./configure --prefix=$PWD/local
+$ make
+$ make install
+$ ./local/bin/ruby -e 'puts "Hello"'
+Hello
+```
+
+## Out-of-place build
+
+```
+$ autoconf
+$ mkdir ../ruby-build
+$ cd ../ruby-build
+$ ../ruby-src/configure --prefix=$PWD/local
+$ make
+$ make install
+$ ./local/bin/ruby -e 'puts "Hello"'
+Hello
+```
+
+## How to run the whole test suite
+
+```
+$ make check
+```
+
+It runs (about) three test suites:
+
+* `make test` (a test suite for the interpreter core)
+* `make test-all` (for all builtin classes and libraries)
+* `make test-spec` (a conformance test suite for Ruby implementations)
+* `make test-bundler` (a test suite for the bundler examples)
+
+## How to run the test suite with log
+
+```
+$ make test OPTS=-v
+
+$ make test-all TESTS=-v
+
+$ make test-spec MSPECOPT=-Vfs
+```
+
+## How to run a part of the test suite
+
+### Runs a directory
+```
+$ make test-all TESTS=test/rubygems
+$ make test-all TESTS=rubygems
+```
+
+### Runs a file
+```
+$ make test-all TESTS=test/ruby/test_foo.rb
+$ make test-all TESTS=ruby/foo
+```
+
+### Runs a test whose name includes test_bar
+```
+$ make test-all TESTS="test/ruby/test_foo.rb -n /test_bar/"
+```
+
+### Runs a file or directory with GNU make
+```
+$ make test/ruby/test_foo.rb
+$ make test/ruby/test_foo.rb TESTOPTS="-n /test_bar/"
+```
+
+### Runs a ruby-spec directory
+```
+$ make test-spec MSPECOPT=spec/ruby/core/foo
+```
+
+### Runs a ruby-spec file
+```
+$ make test-spec MSPECOPT=spec/ruby/core/foo/bar_spec.rb
+```
+
+### Runs a ruby-spec file or directory with GNU make
+```
+$ make spec/ruby/core/foo/bar_spec.rb
+```
+
+### Runs a bundler spec file
+```
+$ make test-bundler BUNDLER_SPECS=commands/exec_spec.rb:58
+```
+
+## How to measure coverage of C and Ruby code
+
+You need to be able to use gcc (gcov) and lcov visualizer.
+
+```
+$ autoconf
+$ ./configure --enable-gcov
+$ make
+$ make update-coverage
+$ rm -f test-coverage.dat
+$ make test-all COVERAGE=true
+$ make lcov
+$ open lcov-out/index.html
+```
+
+If you need only C code coverage, you can remove `COVERAGE=true` from the above process.
+You can also use `gcov` command directly to get per-file coverage.
+
+If you need only Ruby code coverage, you can remove `--enable-gcov`.
+Note that `test-coverage.dat` accumulates all runs of `make test-all`.
+Make sure that you remove the file if you want to measure one test run.
+
+You can see the coverage result of CI: https://rubyci.org/coverage
+
+## How to benchmark
+
+see https://github.com/ruby/ruby/tree/master/benchmark#make-benchmark
diff --git a/doc/marshal.rdoc b/doc/marshal.rdoc
index a51f1bf873..78a3d29d4a 100644
--- a/doc/marshal.rdoc
+++ b/doc/marshal.rdoc
@@ -73,7 +73,7 @@ The first byte has the following special values:
a positive little-endian integer.
"\xfd"::
- The total size of the integer is two bytes. The following three bytes are a
+ The total size of the integer is four bytes. The following three bytes are a
negative little-endian integer.
"\x04"::
diff --git a/doc/memory_view.md b/doc/memory_view.md
new file mode 100644
index 0000000000..646a35423a
--- /dev/null
+++ b/doc/memory_view.md
@@ -0,0 +1,167 @@
+# MemoryView
+
+MemoryView provides the features to share multidimensional homogeneous arrays of
+fixed-size element on memory among extension libraries.
+
+## Disclaimer
+
+* This feature is still experimental. The specification described here can be changed in the future.
+
+* This document is under construction. Please refer the master branch of ruby for the latest version of this document.
+
+## Overview
+
+We sometimes deal with certain kinds of objects that have arrays of the same typed fixed-size elements on a contiguous memory area as its internal representation.
+Numo::NArray in numo-narray and Magick::Image in rmagick are typical examples of such objects.
+MemoryView plays the role of the hub to share the internal data of such objects without copy among such libraries.
+
+Copy-less sharing of data is very important in some field such as data analysis, machine learning, and image processing. In these field, people need to handle large amount of on-memory data with several libraries. If we are forced to copy to exchange large data among libraries, a large amount of the data processing time must be occupied by copying data. You can avoid such wasting time by using MemoryView.
+
+MemoryView has two categories of APIs:
+
+1. Producer API
+
+ Classes can register own MemoryView entry which allows objects of that classes to expose their MemoryView
+
+2. Consumer API
+
+ Consumer API allows us to obtain and manage the MemoryView of an object
+
+## MemoryView structure
+
+A MemoryView structure, `rb_memory_view_t`, is used for exporting objects' MemoryView.
+This structure contains the reference of the object, which is the owner of the MemoryView, the pointer to the head of exported memory, and the metadata that describes the structure of the memory. The metadata can describe multidimensional arrays with strides.
+
+### The member of MemoryView structure
+
+The MemoryView structure consists of the following members.
+
+- `VALUE obj`
+
+ The reference to the original object that has the memory exported via the MemoryView.
+
+ RubyVM manages the reference count of the MemoryView-exported objects to guard them from the garbage collection. The consumers do not have to struggle to guard this object from GC.
+
+- `void *data`
+
+ The pointer to the head of the exported memory.
+
+- `ssize_t byte_size`
+
+ The numbero f bytes in the memory pointed by `data`.
+
+- `bool readonly`
+
+ `true` for readonly memory, `false` for writable memory.
+
+- `const char *format`
+
+ A string to describeth e format of an element, or NULL for unsigned byte.
+
+- `ssize_t item_size`
+
+ The number of bytes in each element.
+
+- `const rb_memory_view_item_component_t *item_desc.components`
+
+ The array of the metadata of the component in an element.
+
+- `size_t item_desc.length`
+
+ The number of items in `item_desc.components`.
+
+- `ssize_t ndim`
+
+ The number of dimensions.
+
+- `const ssize_t *shape`
+
+ A `ndim` size array indicating the number of elements in each dimension.
+ This can be `NULL` when `ndim` is 1.
+
+- `const ssize_t *strides`
+
+ A `ndim` size array indicating the number of bytes to skip to go to the next element in each dimension.
+ This can be `NULL` when `ndim` is 1.
+
+- `const ssize_t *sub_offsets`
+
+ A `ndim` size array consisting of the offsets in each dimension when the MemoryView exposes a nested array.
+ This can be `NULL` when the MemoryView exposes a flat array.
+
+- `void *const private`
+
+ The private data that MemoryView provider uses internally.
+ This can be `NULL` when any private data is unnecessary.
+
+## MemoryView APIs
+
+### For consumers
+
+- `bool rb_memory_view_available_p(VALUE obj)`
+
+ Return `true` if `obj` supports to export a MemoryView. Return `false` otherwise.
+
+ If this function returns `true`, it doesn't mean the function `rb_memory_view_get` will succeed.
+
+- `bool rb_memory_view_get(VALUE obj, rb_memory_view_t *view, int flags)`
+
+ If the given `obj` supports to export a MemoryView that conforms the given `flags`, this function fills `view` by the information of the MemoryView and returns `true`. In this case, the reference count of `obj` is increased.
+
+ If the given combination of `obj` and `flags` cannot export a MemoryView, this function returns `false`. The content of `view` is not touched in this case.
+
+ The exported MemoryView must be released by `rb_memory_view_release` when the MemoryView is no longer needed.
+
+- `bool rb_memory_view_release(rb_memory_view_t *view)`
+
+ Release the given MemoryView `view` and decrement the reference count of `view->obj`.
+
+ Consumers must call this function when the MemoryView is no longer needed. Missing to call this function leads memory leak.
+
+- `ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err)`
+
+ Calculate the number of bytes occupied by an element.
+
+ When the calculation fails, the failed location in `format` is stored into `err`, and returns `-1`.
+
+- `void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices)`
+
+ Calculate the location of the item indicated by the given `indices`.
+ The length of `indices` must equal to `view->ndim`.
+ This function initializes `view->item_desc` if needed.
+
+- `VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices)`
+
+ Return the Ruby object representation of the item indicated by the given `indices`.
+ The length of `indices` must equal to `view->ndim`.
+ This function uses `rb_memory_view_get_item_pointer`.
+
+- `rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly)`
+
+ Fill the members of `view` as an 1-dimensional byte array.
+
+- `void rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides)`
+
+ Fill the `strides` array with byte-Strides of a contiguous array of the given shape with the given element size.
+
+- `void rb_memory_view_prepare_item_desc(rb_memory_view_t *view)`
+
+ Fill the `item_desc` member of `view`.
+
+- `bool rb_memory_view_is_contiguous(const rb_memory_view_t *view)`
+
+ Return `true` if the data in the MemoryView `view` is row-major or column-major contiguous.
+
+ Return `false` otherwise.
+
+- `bool rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view)`
+
+ Return `true` if the data in the MemoryView `view` is row-major contiguous.
+
+ Return `false` otherwise.
+
+- `bool rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view)`
+
+ Return `true` if the data in the MemoryView `view` is column-major contiguous.
+
+ Return `false` otherwise.
diff --git a/doc/method_documentation.rdoc b/doc/method_documentation.rdoc
new file mode 100644
index 0000000000..0432216868
--- /dev/null
+++ b/doc/method_documentation.rdoc
@@ -0,0 +1,183 @@
+= Method Documentation Guide
+
+This guide discusses recommendations for documenting methods for Ruby core
+classes and classes in the standard library.
+
+== Goal
+
+The goal when documenting a method is to impart the most important
+information about the method in the least amount of time. A reader
+of the method documentation should be able to quickly understand
+the purpose of the method and how to use it. Providing too little
+information about the method is not good, but providing unimportant
+information or unnecessary examples is not good either. Use your
+judgment about what the user of the method needs to know to use the
+method correctly.
+
+== General Structure
+
+The general structure of the method documentation should be:
+
+* call-seq (for methods written in C)
+* Synopsis (Short Description)
+* Details and Examples
+* Argument Description (if necessary)
+* Corner Cases and Exceptions
+* Aliases
+* Related Methods (optional)
+
+== call-seq (for methods written in C)
+
+For methods written in C, RDoc cannot determine what arguments
+the method accepts, so those need to be documented using a
+<tt>call-seq</tt>. Here's an example <tt>call-seq</tt>:
+
+ * call-seq:
+ * array.count -> integer
+ * array.count(obj) -> integer
+ * array.count {|element| ... } -> integer
+
+When creating the <tt>call-seq</tt>, use the form
+
+ receiver_type.method_name(arguments) {|block_arguments|} -> return_type
+
+Omit the parentheses for cases where the method does not accept arguments,
+and omit the block for cases where a block is not accepted.
+
+In the cases where method can return multiple different types, separate the
+types with "or". If the method can return any type, use "object". If the
+method returns the receiver, use "self".
+
+In cases where the method accepts optional arguments, use a <tt>call-seq</tt>
+with an optional argument if the method has the same behavior when an argument
+is omitted as when the argument is passed with the default value. For example,
+use:
+
+ * obj.respond_to?(symbol, include_all=false) -> true or false
+
+Instead of:
+
+ * obj.respond_to?(symbol) -> true or false
+ * obj.respond_to?(symbol, include_all) -> true or false
+
+However, as shown above for <tt>Array#count</tt>, use separate lines if the
+behavior is different if the argument is omitted.
+
+Omit aliases from the call-seq.
+
+== Synopsis
+
+The synopsis comes next, and is a short description of what the
+method does and why you would want to use it. Ideally, this
+is a single sentence, but for more complex methods it may require
+an entire paragraph.
+
+For <tt>Array#count</tt>, the synopsis is:
+
+ Returns a count of specified elements.
+
+This is great as it is short and descriptive. Avoid documenting
+too much in the synopsis, stick to the most important information
+for the benefit of the reader.
+
+== Details and Examples
+
+Most non-trivial methods benefit from examples, as well as details
+beyond what is given in the synopsis. In the details and examples
+section, you can document how the method handles different types
+of arguments, and provides examples on proper usage. In this
+section, focus on how to use the method properly, not on how the
+method handles improper arguments or corner cases.
+
+Not every behavior of a method requires an example. If the method
+is documented to return +self+, you don't need to provide an example
+showing the return value is the same as the receiver. If the method
+is documented to return +nil+, you don't need to provide an example
+showing that it returns +nil+. If the details mention that for a
+certain argument type, an empty array is returned, you don't need
+to provide an example for that.
+
+Only add an example if it provides the user additional information,
+do not add an example if it provides the same information given
+in the synopsis or details. The purpose of examples is not to prove
+what the details are stating.
+
+== Argument Description (if necessary)
+
+For methods that require arguments, if not obvious and not explicitly
+mentioned in the details or implicitly shown in the examples, you can
+provide details about the types of arguments supported. When discussing
+the types of arguments, use simple language even if less-precise, such
+as "level must be an integer", not "level must be an Integer-convertible
+object". The vast majority of use will be with the expected type, not an
+argument that is explicitly convertible to the expected type, and
+documenting the difference is not important.
+
+For methods that take blocks, it can be useful to document the type of
+argument passed if it is not obvious, not explicitly mentioned in the
+details, and not implicitly shown in the examples.
+
+If there is more than one argument or block argument, use an RDoc
+definition list:
+
+argument_name1 :: type and description
+argument_name2 :: type and description
+
+== Corner Cases and Exceptions
+
+For corner cases of methods, such as atypical usage, briefly mention
+the behavior, but do not provide any examples.
+
+Only document exceptions raised if they are not obvious. For example,
+if you have stated earlier than an argument type must be an integer,
+you do not need to document that a TypeError is raised if a non-integer
+is passed. Do not provide examples of exceptions being raised unless
+that is a common case, such as Hash#fetch raising KeyError.
+
+== Aliases
+
+Mention aliases in the form "Array#find_index is an alias for Array#index."
+
+== Related Methods (optional)
+
+In some cases, it is useful to document which methods are related to
+the current method. For example, documentation for Hash#[] might
+mention Hash#fetch as a related method, and Hash#merge might mention
+#merge! as a related method. Consider which methods may be related
+to the current method, and if you think the reader would benefit it,
+at the end of the method documentation, add a line starting with
+"Related: " (e.g. "Related: #fetch"). Don't list more than three
+related methods. If you think more than three methods are related,
+pick the three you think are most important and list those three.
+
+== Methods Accepting Multiple Argument Types
+
+For methods that accept multiple argument types, in some cases it can
+be useful to document the different argument types separately. It's
+best to use a separate paragraph for each case you are discussing.
+
+== Use of English
+
+Readers of this documentation may not be native speakers of English.
+Documentation should be written with this in mind.
+
+Use short sentences and group them into paragraphs that cover a single
+topic. Avoid complex verb tenses, excessive comma-separated phrases,
+and idioms.
+
+When writing documentation, define unusual or critical concepts in
+simple language. Provide links to authoritative sources, or add a
+general description to the top-level documentation for the class or
+module.
+
+== Formatting
+
+Extraneous formatting such as headings and horizontal lines should be
+avoided in general. It is best to keep the formatting as simple as
+possible. Only use headings and other formatting for the most complex
+cases where the method documentation is very long due to the complexity
+of the method.
+
+Methods are documented using RDoc syntax. See the
+{RDoc Markup Reference}[https://docs.ruby-lang.org/en/master/RDoc/Markup.html#class-RDoc::Markup-label-RDoc+Markup+Reference]
+for more information on formatting with RDoc syntax.
diff --git a/doc/ractor.md b/doc/ractor.md
new file mode 100644
index 0000000000..0ca36326ab
--- /dev/null
+++ b/doc/ractor.md
@@ -0,0 +1,931 @@
+# 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 problem which is 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 message from any ractors).
+ * Receiver has infinite queue and sender enqueues the message. Sender doesn't block to put message into this queue.
+ * This type message exchangin is employed by many other Actor-based language.
+ * `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 of state-mutations to debug thread-safety issues.
+With Ractor, you can concentrate to 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 execute given `expr` in a given block.
+Given block will be isolated from outer scope by `Proc#isolate`. To prevent sharing unshareable objects between ractors, block outer-variables, `self` and other information are isolated.
+
+Given block will be isolated by `Proc#isolate` method (not exposed yet for Ruby users). `Proc#isolate` is called at Ractor creation timing (`Ractor.new` is called). If given Proc object is not enable 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 `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 is two way to communicate 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 APIs: push type and pull type.
+
+* (1-1) send/receive (push type)
+ * `Ractor#send(obj)` (`Ractor#<<(obj)` is an aliases) 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 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 way 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 is not support deep copy. Some `T_DATA` objects are not supported.
+ * (3) Move an object: Sending an unshareable object reference with a membership. Sender Ractor can not access moved objects anymore (raise an exception) after moving it. Current implementation makes new object as a moved object for receiver Ractor and copy references of sending object to moved object.
+ * You can choose "Copy" and "Move" by the `move:` keyword, `Ractor#send(obj, move: true/false)` and `Ractor.yield(obj, move: true/false)` (default is `false` (COPY)).
+
+### Sending/Receiving ports
+
+Each Ractor has _incoming-port_ and _outgoing-port_. Incoming-port is connected to the infinite sized incoming queue.
+
+```
+ Ractor r
+ +-------------------------------------------+
+ | incoming outgoing |
+ | port port |
+ r.send(obj) ->*->[incoming queue] Ractor.yield(obj) ->*-> r.take
+ | | |
+ | v |
+ | Ractor.receive |
+ +-------------------------------------------+
+
+
+Connection example: r2.send obj on r1、Ractor.receive on r2
+ +----+ +----+
+ * r1 |---->* r2 *
+ +----+ +----+
+
+
+Connection example: Ractor.yield(obj) on r1, r1.take on r2
+ +----+ +----+
+ * r1 *---->- r2 *
+ +----+ +----+
+
+Connection example: Ractor.yield(obj) on r1 and r2,
+ and waiting for both simultaneously by Ractor.select(r1, r2)
+
+ +----+
+ * r1 *------+
+ +----+ |
+ +----> Ractor.select(r1, r2)
+ +----+ |
+ * r2 *------|
+ +----+
+```
+
+```ruby
+ r = Ractor.new do
+ msg = Ractor.receive # Receive from r's incoming queue
+ msg # send back msg as block return value
+ end
+ r.send 'ok' # Send 'ok' to r's incoming port -> incoming queue
+ r.take # Receive from r's outgoing port
+```
+
+The last example shows the following ractor network.
+
+```
+
+ +------+ +---+
+ * main |------> * r *---+
+ +-----+ +---+ |
+ ^ |
+ +-------------------+
+```
+
+And this code can be rewrite more simple way by using an argument for `Ractor.new`.
+
+```ruby
+ # Actual argument 'ok' for `Ractor.new()` will be send 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` raise 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 waiting for `Ractor.yield()`, `Ractor#close_outgoing` will cancel all blocking by raise 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 raise.
+
+```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 sharble 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 sharable objects, `Ractor.make_shareable(obj)` method is provided. In this case, try to make sharaeble by freezing `obj` and recursively travasible objects. This method accepts `copy:` keyword (default value is false).`Ractor.make_sharable(obj, copy: true)` tries to make a deep copy of `obj` and make the copied object sharable.
+
+## 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
+
+Only the main Ractor can access instance variables of shareable objects.
+
+```ruby
+ class C
+ @iv = 'str'
+ end
+
+ r = Ractor.new do
+ class C
+ p @iv
+ end
+ end
+
+
+ begin
+ r.take
+ rescue => e
+ e.class #=> Ractor::IsolationError
+ end
+```
+
+```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 sharable objects.
+
+```ruby
+TABLE = {a: 'ko1', b: 'ko2', c: 'ko3'}
+```
+
+In this case, `TABLE` reference an unsharable Hash object. So that other ractors can not refer `TABLE` constant. To make it shareable, we can use `Ractor.make_sharable()` like that.
+
+```ruby
+TABLE = Ractor.make_sharable( {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_sharable( {a: 'ko1', b: 'ko2', c: 'ko3'} )
+```
+
+`shareable_constant_value` directive accepts the following modes (descriptions use the example: `CONST = expr`):
+
+* none: Do nothing. Same as: `CONST = expr`
+* literal:
+ * if `expr` is consites of literals, replaced to `CONST = Ractor.make_sharable(expr)`.
+ * otherwise: replaced to `CONST = expr.tap{|o| raise unless Ractor.shareable?}`.
+* experimental_everything: replaced to `CONST = Ractor.make_sharable(expr)`.
+* experimental_copy: replaced to `CONST = Ractor.make_sharable(expr, copy: true)`.
+
+Except the `none` mode (default), it is guaranteed that the assigned constants refer to only sharable objects.
+
+See [doc/syntax/comment.rdoc](syntax/comment.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/standard_library.rdoc b/doc/standard_library.rdoc
index f71cedebf7..e4418aea81 100644
--- a/doc/standard_library.rdoc
+++ b/doc/standard_library.rdoc
@@ -8,86 +8,76 @@ description.
== Libraries
-Abbrev:: Calculates a set of unique abbreviations for a given set of strings
-Base64:: Support for encoding and decoding binary data using a Base64 representation
-DEBUGGER__:: Debugging functionality for Ruby
-DRb:: Distributed object system for Ruby
-English.rb:: Require 'English.rb' to reference global variables with less cryptic names
-ERB:: An easy to use but powerful templating system for Ruby
-Find:: This module supports top-down traversal of a set of file paths
MakeMakefile:: Module used to generate a Makefile for C extensions
-Monitor:: Provides an object or module to use safely by more than one thread
-Net::FTP:: Support for the File Transfer Protocol
-Net::HTTP:: HTTP client api for Ruby
-Net::IMAP:: Ruby client api for Internet Message Access Protocol
-OpenURI:: An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP
-OptionParser:: Ruby-oriented class for command-line option analysis
-PP:: Provides a PrettyPrinter for Ruby objects
-PrettyPrinter:: Implements a pretty printing algorithm for readable structure
RbConfig:: Information of your configure and build of Ruby
-resolv-replace.rb:: Replace Socket DNS with Resolv
-Resolv:: Thread-aware DNS resolver library in Ruby
-Rinda:: The Linda distributed computing paradigm in Ruby
Gem:: Package management framework for Ruby
-SecureRandom:: Interface for secure random number generator
-Set:: Provides a class to deal with collections of unordered, unique values
-Shellwords:: Manipulates strings with word parsing rules of UNIX Bourne shell
-Tempfile:: A utility class for managing temporary files
-Time:: Extends the Time class with methods for parsing and conversion
-tmpdir.rb:: Extends the Dir class to manage the OS temporary file path
-TSort:: Topological sorting using Tarjan's algorithm
-un.rb:: Utilities to replace common UNIX commands
-WeakRef:: Allows a referenced object to be garbage-collected
== Extensions
Coverage:: Provides coverage measurement for Ruby
-Digest:: Provides a framework for message digest libraries
-IO:: Extensions for Ruby IO class, including #wait and ::console
-NKF:: Ruby extension for Network Kanji Filter
+Monitor:: Provides an object or module to use safely by more than one thread
objspace:: Extends ObjectSpace module to add methods for internal statistics
-Pathname:: Representation of the name of a file or directory on the filesystem
PTY:: Creates and manages pseudo terminals
Ripper:: Provides an interface for parsing Ruby programs into S-expressions
Socket:: Access underlying OS socket implementations
-Syslog:: Ruby interface for the POSIX system logging facility
-WIN32OLE:: Provides an interface for OLE Automation in Ruby
= Default gems
== Libraries
+Abbrev:: Calculates a set of unique abbreviations for a given set of strings
+Base64:: Support for encoding and decoding binary data using a Base64 representation
Benchmark:: Provides methods to measure and report the time used to execute code
Bundler:: Manage your Ruby application's gem dependencies
CGI:: Support for the Common Gateway Interface protocol
CSV:: Provides an interface to read and write CSV files and data
+DEBUGGER__:: Debugging functionality for Ruby
Delegator:: Provides three abilities to delegate method calls to an object
DidYouMean:: "Did you mean?" experience in Ruby
+DRb:: Distributed object system for Ruby
+English:: Provides references to special global variables with less cryptic names
+ERB:: An easy to use but powerful templating system for Ruby
FileUtils:: Several file utility methods for copying, moving, removing, etc
+Find:: This module supports top-down traversal of a set of file paths
Forwardable:: Provides delegation of specified methods to a designated object
GetoptLong:: Parse command line options similar to the GNU C getopt_long()
IPAddr:: Provides methods to manipulate IPv4 and IPv6 IP addresses
IRB:: Interactive Ruby command-line tool for REPL (Read Eval Print Loop)
+OptionParser:: Ruby-oriented class for command-line option analysis
Logger:: Provides a simple logging utility for outputting messages
Matrix:: Represents a mathematical matrix.
Mutex_m:: Mixin to extend objects to be handled like a Mutex
+Net::FTP:: Support for the File Transfer Protocol
+Net::HTTP:: HTTP client api for Ruby
+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
Observable:: Provides a mechanism for publish/subscribe pattern in Ruby
Open3:: Provides access to stdin, stdout and stderr when running other programs
OpenStruct:: Class to build custom data structures, similar to a Hash
+OpenURI:: An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP
+PP:: Provides a PrettyPrinter for Ruby objects
+PrettyPrinter:: Implements a pretty printing algorithm for readable structure
Prime:: Prime numbers and factorization library
PStore:: Implements a file based persistence mechanism based on a Hash
-Racc:: A LALR(1) parser generator written in Ruby.
+Resolv:: Thread-aware DNS resolver library in Ruby
+resolv-replace.rb:: Replace Socket DNS with Resolv
RDoc:: Produces HTML and command-line documentation for Ruby
-REXML:: An XML toolkit for Ruby
-RSS:: Family of libraries that support various formats of XML "feeds"
+Rinda:: The Linda distributed computing paradigm in Ruby
+SecureRandom:: Interface for secure random number generator
+Set:: Provides a class to deal with collections of unordered, unique values
+Shellwords:: Manipulates strings with word parsing rules of UNIX Bourne shell
Singleton:: Implementation of the Singleton pattern for Ruby
+Tempfile:: A utility class for managing temporary files
+Time:: Extends the Time class with methods for parsing and conversion
Timeout:: Auto-terminate potentially long-running operations in Ruby
+tmpdir.rb:: Extends the Dir class to manage the OS temporary file path
Tracer:: Outputs a source level execution trace of a Ruby program
+TSort:: Topological sorting using Tarjan's algorithm
+un.rb:: Utilities to replace common UNIX commands
URI:: A Ruby module providing support for Uniform Resource Identifiers
-WEBrick:: An HTTP server toolkit for Ruby
YAML:: Ruby client library for the Psych YAML implementation
+WeakRef:: Allows a referenced object to be garbage-collected
== Extensions
@@ -95,18 +85,23 @@ BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic
Date:: A subclass of Object includes Comparable module for handling dates
DateTime:: Subclass of Date to handling dates, hours, minutes, seconds, offsets
DBM:: Provides a wrapper for the UNIX-style Database Manager Library
+Digest:: Provides a framework for message digest libraries
Etc:: Provides access to information typically stored in UNIX /etc directory
Fcntl:: Loads constants defined in the OS fcntl.h C header file
Fiddle:: A libffi wrapper for Ruby
GDBM:: Ruby extension for the GNU dbm (gdbm) library
-IO::console:: Console interface
+IO:: Extensions for Ruby IO class, including #wait, #nonblock and ::console
JSON:: Implements Javascript Object Notation for Ruby
+NKF:: Ruby extension for Network Kanji Filter
OpenSSL:: Provides SSL, TLS and general purpose cryptography for Ruby
+Pathname:: Representation of the name of a file or directory on the filesystem
Psych:: A YAML parser and emitter for Ruby
+Racc:: A LALR(1) parser generator written in Ruby.
Readline:: Provides an interface for GNU Readline and Edit Line (libedit)
-SDBM:: Provides a simple file-based key-value store with String keys and values
StringIO:: Pseudo I/O on String objects
StringScanner:: Provides lexical scanning operations on a String
+Syslog:: Ruby interface for the POSIX system logging facility
+WIN32OLE:: Provides an interface for OLE Automation in Ruby
Zlib:: Ruby interface for the zlib compression/decompression library
= Bundled gems
@@ -114,8 +109,10 @@ Zlib:: Ruby interface for the zlib compression/decompression library
== Libraries
MiniTest:: A test suite with TDD, BDD, mocking and benchmarking
-Net::Telnet:: Telnet client library for Ruby
PowerAssert:: Power Assert for Ruby.
Rake:: Ruby build program with capabilities similar to make
Test::Unit:: A compatibility layer for MiniTest
-XMLRPC:: Remote Procedure Call over HTTP support for Ruby
+REXML:: An XML toolkit for Ruby
+RSS:: Family of libraries that support various formats of XML "feeds"
+RBS:: RBS is a language to describe the structure of Ruby programs
+TypeProf:: A type analysis tool for Ruby code based on abstract interpretation
diff --git a/doc/syntax.rdoc b/doc/syntax.rdoc
index 2463c12a63..5895673f36 100644
--- a/doc/syntax.rdoc
+++ b/doc/syntax.rdoc
@@ -11,6 +11,9 @@ Assignment[rdoc-ref:syntax/assignment.rdoc] ::
{Control Expressions}[rdoc-ref:syntax/control_expressions.rdoc] ::
+if+, +unless+, +while+, +until+, +for+, +break+, +next+, +redo+
+{Pattern matching}[rdoc-ref:syntax/pattern_matching.rdoc] ::
+ Experimental structural pattern matching and variable binding syntax
+
Methods[rdoc-ref:syntax/methods.rdoc] ::
Method and method argument syntax
@@ -27,7 +30,7 @@ Precedence[rdoc-ref:syntax/precedence.rdoc] ::
Precedence of ruby operators
Refinements[rdoc-ref:syntax/refinements.rdoc] ::
- Use and behavior of the experimental refinements feature
+ Use and behavior of the refinements feature
Miscellaneous[rdoc-ref:syntax/miscellaneous.rdoc] ::
+alias+, +undef+, +BEGIN+, +END+
diff --git a/doc/syntax/calling_methods.rdoc b/doc/syntax/calling_methods.rdoc
index 5abecc69da..fc806d5c31 100644
--- a/doc/syntax/calling_methods.rdoc
+++ b/doc/syntax/calling_methods.rdoc
@@ -30,7 +30,41 @@ 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.
-=== Safe navigation operator
+=== Chaining \Method Calls
+
+You can "chain" method calls by immediately following one method call with another.
+
+This example chains methods Array#append and Array#compact:
+
+ a = [:foo, 'bar', 2]
+ a1 = [:baz, nil, :bam, nil]
+ a2 = a.append(*a1).compact
+ a2 # => [:foo, "bar", 2, :baz, :bam]
+
+Details:
+
+- First method <tt>merge</tt> creates a copy of <tt>a</tt>,
+ appends (separately) each element of <tt>a1</tt> to the copy, and returns
+ [:foo, "bar", 2, :baz, nil, :bam, nil]
+- Chained method <tt>compact</tt> creates a copy of that return value,
+ removes its <tt>nil</tt>-valued entries, and returns
+ [:foo, "bar", 2, :baz, :bam]
+
+You can chain methods that are in different classes.
+This example chains methods Hash#to_a and Array#reverse:
+
+ h = {foo: 0, bar: 1, baz: 2}
+ h.to_a.reverse # => [[:baz, 2], [:bar, 1], [:foo, 0]]
+
+Details:
+
+- First method Hash#to_a converts <tt>a</tt> to an \Array, and returns
+ [[:foo, 0], [:bar, 1], [:baz, 2]]
+- Chained method Array#reverse creates copy of that return value,
+ reverses it, and returns
+ [[:baz, 2], [:bar, 1], [:foo, 0]]
+
+=== Safe Navigation Operator
<code>&.</code>, called "safe navigation operator", allows to skip method call
when receiver is +nil+. It returns +nil+ and doesn't evaluate method's arguments
diff --git a/doc/syntax/comments.rdoc b/doc/syntax/comments.rdoc
index a07dd41494..650d13c2dc 100644
--- a/doc/syntax/comments.rdoc
+++ b/doc/syntax/comments.rdoc
@@ -35,3 +35,219 @@ syntax error:
Will not work
=end
end
+
+== Magic Comments
+
+While comments are typically ignored by Ruby, special "magic comments" contain
+directives that affect how the code is interpreted.
+
+Top-level magic comments must start on the first line, or on the second line if
+the first line looks like <tt>#! shebang line</tt>.
+
+NOTE: Magic comments affect only the file in which they appear;
+other files are unaffected.
+
+ # frozen_string_literal: true
+
+ var = 'hello'
+ var.frozen? # => true
+
+=== Alternative syntax
+
+Magic comments may consist of a single directive (as in the example above).
+Alternatively, multiple directives may appear on the same line if separated by ";"
+and wrapped between "-*-" (see Emacs' {file variables}[https://www.gnu.org/software/emacs/manual/html_node/emacs/Specifying-File-Variables.html]).
+
+ # emacs-compatible; -*- coding: big5; mode: ruby -*-
+
+ p 'hello'.frozen? # => true
+ p 'hello'.encoding # => #<Encoding:Big5>
+
+=== +encoding+ Directive
+
+Indicates which string encoding should be used for string literals,
+regexp literals and <code>__ENCODING__</code>:
+
+ # encoding: big5
+
+ ''.encoding # => #<Encoding:Big5>
+
+Default encoding is UTF-8.
+
+It must appear in the first comment section of a file.
+
+The word "coding" may be used instead of "encoding".
+
+=== +frozen_string_literal+ Directive
+
+Indicates that string literals should be allocated once at parse time and frozen.
+
+ # frozen_string_literal: true
+
+ 3.times do
+ p 'hello'.object_id # => prints same number
+ end
+ p 'world'.frozen? # => true
+
+The default is false; this can be changed with <code>--enable=frozen-string-literal</code>.
+Without the directive, or with <code># frozen_string_literal: false</code>,
+the example above would print 3 different numbers and "false".
+
+Starting in Ruby 3.0, string literals that are dynamic are not frozen nor reused:
+
+ # frozen_string_literal: true
+
+ p "Addition: #{2 + 2}".frozen? # => false
+
+It must appear in the first comment section of a file.
+
+=== +warn_indent+ Directive
+
+This directive can turn on detection of bad indentation for statements that follow it:
+
+ def foo
+ end # => no warning
+
+ # warn_indent: true
+ def bar
+ end # => warning: mismatched indentations at 'end' with 'def' at 6
+
+Another way to get these warnings to show is by running Ruby with warnings (<code>ruby -w</code>). Using a directive to set this false will prevent these warnings to show.
+
+=== +shareable_constant_value+ Directive
+
+Note: This directive is experimental in Ruby 3.0 and may change in future releases.
+
+This special directive helps to create constants that hold only immutable objects, or {Ractor-shareable}[rdoc-ref:Ractor@Shareable+and+unshareable+objects] constants.
+
+The directive can specify special treatment for values assigned to constants:
+
+* +none+: (default)
+* +literal+: literals are implicitly frozen, others must be Ractor-shareable
+* +experimental_everything+: all made shareable
+* +experimental_copy+: copy deeply and make it shareable
+
+==== Mode +none+ (default)
+
+No special treatment in this mode (as in Ruby 2.x): no automatic freezing and no checks.
+
+It has always been a good idea to deep-freeze constants; Ractor makes this
+an even better idea as only the main ractor can access non-shareable constants:
+
+ # shareable_constant_value: none
+ A = {foo: []}
+ A.frozen? # => false
+ Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor.
+
+==== Mode +literal+
+
+In "literal" mode, constants assigned to literals will be deeply-frozen:
+
+ # shareable_constant_value: literal
+ X = [{foo: []}] # => same as [{foo: [].freeze}.freeze].freeze
+
+Other values must be shareable:
+
+ # shareable_constant_value: literal
+ X = Object.new # => cannot assign unshareable object to X
+
+Note that only literals directly assigned to constants, or recursively held in such literals will be frozen:
+
+ # shareable_constant_value: literal
+ var = [{foo: []}]
+ var.frozen? # => false (assignment was made to local variable)
+ X = var # => cannot assign unshareable object to X
+
+ X = Set[1, 2, {foo: []}].freeze # => cannot assign unshareable object to X
+ # (`Set[...]` is not a literal and
+ # `{foo: []}` is an argument to `Set.[]`)
+
+The method Module#const_set is not affected.
+
+==== Mode +experimental_everything+
+
+In this mode, all values assigned to constants are made shareable.
+
+ # shareable_constant_value: experimental_everything
+ FOO = Set[1, 2, {foo: []}]
+ # same as FOO = Ractor.make_sharable(...)
+ # OR same as `FOO = Set[1, 2, {foo: [].freeze}.freeze].freeze`
+
+ var = [{foo: []}]
+ var.frozen? # => false (assignment was made to local variable)
+ X = var # => calls `Ractor.make_shareable(var)`
+ var.frozen? # => true
+
+This mode is "experimental", because it might be error prone, for
+example by deep-freezing the constants of an external resource which
+could cause errors:
+
+ # shareable_constant_value: experimental_everything
+ FOO = SomeGem::Something::FOO
+ # => deep freezes the gem's constant!
+
+This will be revisited before Ruby 3.1 to either allow `everything`
+or to instead remove this mode.
+
+The method Module#const_set is not affected.
+
+==== Mode +experimental_copy+
+
+In this mode, all values assigned to constants are deeply copied and
+made shareable. It is safer mode than +experimental_everything+.
+
+ # shareable_constant_value: experimental_everything
+ var = [{foo: []}]
+ var.frozen? # => false (assignment was made to local variable)
+ X = var # => calls `Ractor.make_shareable(var, copy: true)`
+ var.frozen? # => false
+ Ractor.shareable?(X) #=> true
+ var.object_id == X.object_id #=> false
+
+This mode is "experimental" and has not been discussed thoroughly.
+This will be revisited before Ruby 3.1 to either allow `copy`
+or to instead remove this mode.
+
+The method Module#const_set is not affected.
+
+==== Scope
+
+This directive can be used multiple times in the same file:
+
+ # shareable_constant_value: none
+ A = {foo: []}
+ A.frozen? # => false
+ Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor.
+
+ # shareable_constant_value: literal
+ B = {foo: []}
+ B.frozen? # => true
+ B[:foo].frozen? # => true
+
+ C = [Object.new] # => cannot assign unshareable object to C (Ractor::IsolationError)
+
+ D = [Object.new.freeze]
+ D.frozen? # => true
+
+ # shareable_constant_value: experimental_everything
+ E = Set[1, 2, Object.new]
+ E.frozen? # => true
+ E.all(&:frozen?) # => true
+
+The directive affects only subsequent constants and only for the current scope:
+
+ module Mod
+ # shareable_constant_value: literal
+ A = [1, 2, 3]
+ module Sub
+ B = [4, 5]
+ end
+ end
+
+ C = [4, 5]
+
+ module Mod
+ D = [6]
+ end
+ p Mod::A.frozen?, Mod::Sub::B.frozen? # => true, true
+ p C.frozen?, Mod::D.frozen? # => false, false
diff --git a/doc/syntax/control_expressions.rdoc b/doc/syntax/control_expressions.rdoc
index f7e6d54924..e91b03e72d 100644
--- a/doc/syntax/control_expressions.rdoc
+++ b/doc/syntax/control_expressions.rdoc
@@ -232,7 +232,7 @@ You may use +then+ after the +when+ condition. This is most frequently used
to place the body of the +when+ on a single line.
case a
- when 1, 2 then puts "a is one or two
+ when 1, 2 then puts "a is one or two"
when 3 then puts "a is three"
else puts "I don't know what a is"
end
@@ -255,6 +255,20 @@ Again, the +then+ and +else+ are optional.
The result value of a +case+ expression is the last value executed in the
expression.
+Since Ruby 2.7, +case+ expressions also provide a more powerful experimental
+pattern matching feature via the +in+ keyword:
+
+ case {a: 1, b: 2, c: 3}
+ in a: Integer => m
+ "matched: #{m}"
+ else
+ "not matched"
+ end
+ # => "matched: 1"
+
+The pattern matching syntax is described on
+{its own page}[rdoc-ref:syntax/pattern_matching.rdoc].
+
== +while+ Loop
The +while+ loop executes while a condition is true:
diff --git a/doc/syntax/literals.rdoc b/doc/syntax/literals.rdoc
index 38bfa38676..d6d677806e 100644
--- a/doc/syntax/literals.rdoc
+++ b/doc/syntax/literals.rdoc
@@ -20,9 +20,6 @@ Literals create objects you can use in your program. Literals include:
+true+ is a true value. All objects except +nil+ and +false+ evaluate to a
true value in conditional expressions.
-(There are also the constants +TRUE+, +FALSE+ and +NIL+, but the lowercase
-literal forms are preferred.)
-
== Numbers
You can write integers of any size as follows:
@@ -146,6 +143,10 @@ Double-quote strings allow interpolation of other values using
Any expression may be placed inside the interpolated section, but it's best to
keep the expression small for readability.
+You can also use <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>.
+
Interpolation may be disabled by escaping the "#" character or using
single-quote strings:
@@ -362,7 +363,7 @@ See Regexp for a description of the syntax of regular expressions.
== Procs
-A proc can be created with <tt>-></tt>:
+A lambda proc can be created with <tt>-></tt>:
-> { 1 + 1 }
diff --git a/doc/syntax/miscellaneous.rdoc b/doc/syntax/miscellaneous.rdoc
index 87ec059ae7..d5cfd3e474 100644
--- a/doc/syntax/miscellaneous.rdoc
+++ b/doc/syntax/miscellaneous.rdoc
@@ -83,6 +83,36 @@ Using the specific reflection methods such as instance_variable_defined? for
instance variables or const_defined? for constants is less error prone than
using +defined?+.
++defined?+ handles some regexp global variables specially based on whether
+there is an active regexp match and how many capture groups there are:
+
+ /b/ =~ 'a'
+ defined?($~) # => "global-variable"
+ defined?($&) # => nil
+ defined?($`) # => nil
+ defined?($') # => nil
+ defined?($+) # => nil
+ defined?($1) # => nil
+ defined?($2) # => nil
+
+ /./ =~ 'a'
+ defined?($~) # => "global-variable"
+ defined?($&) # => "global-variable"
+ defined?($`) # => "global-variable"
+ defined?($') # => "global-variable"
+ defined?($+) # => nil
+ defined?($1) # => nil
+ defined?($2) # => nil
+
+ /(.)/ =~ 'a'
+ defined?($~) # => "global-variable"
+ defined?($&) # => "global-variable"
+ defined?($`) # => "global-variable"
+ defined?($') # => "global-variable"
+ defined?($+) # => "global-variable"
+ defined?($1) # => "global-variable"
+ defined?($2) # => nil
+
== +BEGIN+ and +END+
+BEGIN+ defines a block that is run before any other code in the current file.
diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc
new file mode 100644
index 0000000000..9f6954f1cb
--- /dev/null
+++ b/doc/syntax/pattern_matching.rdoc
@@ -0,0 +1,503 @@
+= Pattern matching
+
+Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables.
+
+Pattern matching in Ruby is implemented with the +case+/+in+ expression:
+
+ case <expression>
+ in <pattern1>
+ ...
+ in <pattern2>
+ ...
+ in <pattern3>
+ ...
+ else
+ ...
+ end
+
+(Note that +in+ and +when+ branches can NOT be mixed in one +case+ expression.)
+
+Or with the <code>=></code> operator and the +in+ operator, which can be used in a standalone expression:
+
+ <expression> => <pattern>
+
+ <expression> in <pattern>
+
+The +case+/+in+ expression is _exhaustive_: if the value of the expression does not match any branch of the +case+ expression (and the +else+ branch is absent), +NoMatchingPatternError+ is raised.
+
+Therefore, the +case+ expression might be used for conditional matching and unpacking:
+
+ config = {db: {user: 'admin', password: 'abc123'}}
+
+ case config
+ in db: {user:} # matches subhash and puts matched value in variable user
+ puts "Connect with user '#{user}'"
+ in connection: {username: }
+ puts "Connect with user '#{username}'"
+ else
+ puts "Unrecognized structure of config"
+ end
+ # Prints: "Connect with user 'admin'"
+
+whilst the <code>=></code> operator is most useful when the expected data structure is known beforehand, to just unpack parts of it:
+
+ config = {db: {user: 'admin', password: 'abc123'}}
+
+ config => {db: {user:}} # will raise if the config's structure is unexpected
+
+ puts "Connect with user '#{user}'"
+ # Prints: "Connect with user 'admin'"
+
+<code><expression> in <pattern></code> is the same as <code>case <expression>; in <pattern>; true; else false; end</code>.
+You can use it when you only want to know if a pattern has been matched or not:
+
+ users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}]
+ users.any? {|user| user in {name: /B/, age: 20..} } #=> true
+
+See below for more examples and explanations of the syntax.
+
+== Patterns
+
+Patterns can be:
+
+* any Ruby object (matched by the <code>===</code> operator, like in +when+); (<em>Value pattern</em>)
+* array pattern: <code>[<subpattern>, <subpattern>, <subpattern>, ...]</code>; (<em>Array pattern</em>)
+* find pattern: <code>[*variable, <subpattern>, <subpattern>, <subpattern>, ..., *variable]</code>; (<em>Find pattern</em>)
+* hash pattern: <code>{key: <subpattern>, key: <subpattern>, ...}</code>; (<em>Hash pattern</em>)
+* combination of patterns with <code>|</code>; (<em>Alternative pattern</em>)
+* variable capture: <code><pattern> => variable</code> or <code>variable</code>; (<em>As pattern</em>, <em>Variable pattern</em>)
+
+Any pattern can be nested inside array/find/hash patterns where <code><subpattern></code> is specified.
+
+Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter).
+Hash patterns match hashes, or objects that respond to +deconstruct_keys+ (see below about the latter). Note that only symbol keys are supported for hash patterns.
+
+An important difference between array and hash pattern behavior is that arrays match only a _whole_ array:
+
+ case [1, 2, 3]
+ in [Integer, Integer]
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
+while the hash matches even if there are other keys besides the specified part:
+
+ case {a: 1, b: 2, c: 3}
+ in {a: Integer}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+<code>{}</code> is the only exclusion from this rule. It matches only if an empty hash is given:
+
+ case {a: 1, b: 2, c: 3}
+ in {}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
+ case {}
+ in {}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+There is also a way to specify there should be no other keys in the matched hash except those explicitly specified by the pattern, with <code>**nil</code>:
+
+ case {a: 1, b: 2}
+ in {a: Integer, **nil} # this will not match the pattern having keys other than a:
+ "matched a part"
+ in {a: Integer, b: Integer, **nil}
+ "matched a whole"
+ else
+ "not matched"
+ end
+ #=> "matched a whole"
+
+Both array and hash patterns support "rest" specification:
+
+ case [1, 2, 3]
+ in [Integer, *]
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+ case {a: 1, b: 2, c: 3}
+ in {a: Integer, **}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+In +case+ (but not in <code>=></code> and +in+) expressions, parentheses around both kinds of patterns could be omitted:
+
+ case [1, 2]
+ in Integer, Integer
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+ case {a: 1, b: 2, c: 3}
+ in a: Integer
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+Find pattern is similar to array pattern but it can be used to check if the given object has any elements that match the pattern:
+
+ case ["a", 1, "b", "c", 2]
+ in [*, String, String, *]
+ "matched"
+ else
+ "not matched"
+ end
+
+== Variable binding
+
+Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying <code>=> variable_name</code> after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a <code>rescue ExceptionClass => var</code> clause):
+
+ case [1, 2]
+ in Integer => a, Integer
+ "matched: #{a}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+ case {a: 1, b: 2, c: 3}
+ in a: Integer => m
+ "matched: #{m}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+If no additional check is required, for only binding some part of the data to a variable, a simpler form could be used:
+
+ case [1, 2]
+ in a, Integer
+ "matched: #{a}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+ case {a: 1, b: 2, c: 3}
+ in a: m
+ "matched: #{m}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+For hash patterns, even a simpler form exists: key-only specification (without any sub-pattern) binds the local variable with the key's name, too:
+
+ case {a: 1, b: 2, c: 3}
+ in a:
+ "matched: #{a}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+Binding works for nested patterns as well:
+
+ case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]}
+ in name:, friends: [{name: first_friend}, *]
+ "matched: #{first_friend}"
+ else
+ "not matched"
+ end
+ #=> "matched: Jane"
+
+The "rest" part of a pattern also can be bound to a variable:
+
+ case [1, 2, 3]
+ in a, *rest
+ "matched: #{a}, #{rest}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1, [2, 3]"
+
+ case {a: 1, b: 2, c: 3}
+ in a:, **rest
+ "matched: #{a}, #{rest}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1, {:b=>2, :c=>3}"
+
+Binding to variables currently does NOT work for alternative patterns joined with <code>|</code>:
+
+ case {a: 1, b: 2}
+ in {a: } | Array
+ "matched: #{a}"
+ else
+ "not matched"
+ end
+ # SyntaxError (illegal variable in alternative pattern (a))
+
+Variables that start with <code>_</code> are the only exclusions from this rule:
+
+ case {a: 1, b: 2}
+ in {a: _, b: _foo} | Array
+ "matched: #{_}, #{_foo}"
+ else
+ "not matched"
+ end
+ # => "matched: 1, 2"
+
+It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value.
+
+== Variable pinning
+
+Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern:
+
+ expectation = 18
+
+ case [1, 2]
+ in expectation, *rest
+ "matched. expectation was: #{expectation}"
+ else
+ "not matched. expectation was: #{expectation}"
+ end
+ # expected: "not matched. expectation was: 18"
+ # real: "matched. expectation was: 1" -- local variable just rewritten
+
+For this case, the pin operator <code>^</code> can be used, to tell Ruby "just use this value as part of the pattern":
+
+ expectation = 18
+ case [1, 2]
+ in ^expectation, *rest
+ "matched. expectation was: #{expectation}"
+ else
+ "not matched. expectation was: #{expectation}"
+ end
+ #=> "not matched. expectation was: 18"
+
+One important usage of variable pinning is specifying that the same value should occur in the pattern several times:
+
+ jane = {school: 'high', schools: [{id: 1, level: 'middle'}, {id: 2, level: 'high'}]}
+ john = {school: 'high', schools: [{id: 1, level: 'middle'}]}
+
+ case jane
+ in school:, schools: [*, {id:, level: ^school}] # select the last school, level should match
+ "matched. school: #{id}"
+ else
+ "not matched"
+ end
+ #=> "matched. school: 2"
+
+ case john # the specified school level is "high", but last school does not match
+ in school:, schools: [*, {id:, level: ^school}]
+ "matched. school: #{id}"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
+== Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+
+
+As already mentioned above, array, find, and hash patterns besides literal arrays and hashes will try to match any object implementing +deconstruct+ (for array/find patterns) or +deconstruct_keys+ (for hash patterns).
+
+ class Point
+ def initialize(x, y)
+ @x, @y = x, y
+ end
+
+ def deconstruct
+ puts "deconstruct called"
+ [@x, @y]
+ end
+
+ def deconstruct_keys(keys)
+ puts "deconstruct_keys called with #{keys.inspect}"
+ {x: @x, y: @y}
+ end
+ end
+
+ case Point.new(1, -2)
+ in px, Integer # sub-patterns and variable binding works
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ # prints "deconstruct called"
+ "matched: 1"
+
+ case Point.new(1, -2)
+ in x: 0.. => px
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ # prints: deconstruct_keys called with [:x]
+ #=> "matched: 1"
+
++keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the <code>**rest</code> pattern is used, +nil+ is passed as a +keys+ value:
+
+ case Point.new(1, -2)
+ in x: 0.. => px, **rest
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ # prints: deconstruct_keys called with nil
+ #=> "matched: 1"
+
+Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with <code>===</code>
+
+ class SuperPoint < Point
+ end
+
+ case Point.new(1, -2)
+ in SuperPoint(x: 0.. => px)
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
+ case SuperPoint.new(1, -2)
+ in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+== Guard clauses
+
++if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables:
+
+ case [1, 2]
+ in a, b if b == a*2
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+ case [1, 1]
+ in a, b if b == a*2
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
++unless+ works, too:
+
+ case [1, 1]
+ in a, b unless b == a*2
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+== Current feature status
+
+As of Ruby 3.0, one-line pattern matching and find patterns are considered _experimental_: its syntax can change in the future. Every time you use these features in code, a warning will be printed:
+
+ [0] => [*, 0, *]
+ # warning: Find pattern is experimental, and the behavior may change in future versions of Ruby!
+ # warning: One-line pattern matching is experimental, and the behavior may change in future versions of Ruby!
+
+To suppress this warning, one may use the Warning::[]= method:
+
+ Warning[:experimental] = false
+ eval('[0] => [*, 0, *]')
+ # ...no warning printed...
+
+Note that pattern-matching warnings are raised at compile time, so this will not suppress the warning:
+
+ Warning[:experimental] = false # At the time this line is evaluated, the parsing happened and warning emitted
+ [0] => [*, 0, *]
+
+So, only subsequently loaded files or `eval`-ed code is affected by switching the flag.
+
+Alternatively, the command line option <code>-W:no-experimental</code> can be used to turn off "experimental" feature warnings.
+
+== Appendix A. Pattern syntax
+
+Approximate syntax is:
+
+ pattern: value_pattern
+ | variable_pattern
+ | alternative_pattern
+ | as_pattern
+ | array_pattern
+ | find_pattern
+ | hash_pattern
+
+ value_pattern: literal
+ | Constant
+ | ^variable
+
+ variable_pattern: variable
+
+ alternative_pattern: pattern | pattern | ...
+
+ as_pattern: pattern => variable
+
+ array_pattern: [pattern, ..., *variable]
+ | Constant(pattern, ..., *variable)
+ | Constant[pattern, ..., *variable]
+
+ find_pattern: [*variable, pattern, ..., *variable]
+ | Constant(*variable, pattern, ..., *variable)
+ | Constant[*variable, pattern, ..., *variable]
+
+ hash_pattern: {key: pattern, key:, ..., **variable}
+ | Constant(key: pattern, key:, ..., **variable)
+ | Constant[key: pattern, key:, ..., **variable]
+
+== Appendix B. Some undefined behavior examples
+
+To leave room for optimization in the future, the specification contains some undefined behavior.
+
+Use of a variable in an unmatched pattern:
+
+ case [0, 1]
+ in [a, 2]
+ "not matched"
+ in b
+ "matched"
+ in c
+ "not matched"
+ end
+ a #=> undefined
+ c #=> undefined
+
+Number of +deconstruct+, +deconstruct_keys+ method calls:
+
+ $i = 0
+ ary = [0]
+ def ary.deconstruct
+ $i += 1
+ self
+ end
+ case ary
+ in [0, 1]
+ "not matched"
+ in [0]
+ "matched"
+ end
+ $i #=> undefined
diff --git a/doc/syntax/refinements.rdoc b/doc/syntax/refinements.rdoc
index fc554bb476..c900ab1bdc 100644
--- a/doc/syntax/refinements.rdoc
+++ b/doc/syntax/refinements.rdoc
@@ -245,7 +245,8 @@ When +super+ is invoked method lookup checks:
Note that +super+ in a method of a refinement invokes the method in the
refined class even if there is another refinement which has been activated in
-the same context.
+the same context. This is only true for +super+ in a method of a refinement, it
+does not apply to +super+ in a method in a module that is included in a refinement.
== Methods Introspection
@@ -278,6 +279,6 @@ Refinements in descendants have higher precedence than those of ancestors.
== Further Reading
-See https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/RefinementsSpec for the
+See https://bugs.ruby-lang.org/projects/ruby-master/wiki/RefinementsSpec for the
current specification for implementing refinements. The specification also
contains more details.
diff --git a/enc/Makefile.in b/enc/Makefile.in
index c389c24825..9203874386 100644
--- a/enc/Makefile.in
+++ b/enc/Makefile.in
@@ -11,6 +11,7 @@ exec_prefix = @exec_prefix@
libdir = @libdir@
top_srcdir = $(encsrcdir:/enc=)
srcdir = $(top_srcdir)
+tooldir = $(top_srcdir)/tool
arch = @arch@
EXTOUT = @EXTOUT@
hdrdir = $(srcdir)/include
@@ -20,7 +21,6 @@ TRANSSODIR = $(ENCSODIR)/trans
DLEXT = @DLEXT@
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
@@ -34,7 +34,6 @@ RUBY_SO_NAME = @RUBY_SO_NAME@
LIBRUBY = @LIBRUBY@
LIBRUBYARG_SHARED = @LIBRUBYARG_SHARED@
LIBRUBYARG_STATIC = $(LIBRUBYARG_SHARED)
-BUILTRUBY = $(topdir)/miniruby$(EXEEXT)
empty =
AR = @AR@
diff --git a/enc/ascii.c b/enc/ascii.c
index 8b32c414fe..a2fef2f879 100644
--- a/enc/ascii.c
+++ b/enc/ascii.c
@@ -61,6 +61,8 @@ OnigEncodingDefine(ascii, ASCII) = {
ENC_ALIAS("BINARY", "ASCII-8BIT")
ENC_REPLICATE("IBM437", "ASCII-8BIT")
ENC_ALIAS("CP437", "IBM437")
+ENC_REPLICATE("IBM720", "ASCII-8BIT")
+ENC_ALIAS("CP720", "IBM720")
ENC_REPLICATE("IBM737", "ASCII-8BIT")
ENC_ALIAS("CP737", "IBM737")
ENC_REPLICATE("IBM775", "ASCII-8BIT")
diff --git a/enc/cp949.c b/enc/cp949.c
index bd2c8d21a4..1600d0cd5b 100644
--- a/enc/cp949.c
+++ b/enc/cp949.c
@@ -218,5 +218,5 @@ OnigEncodingDefine(cp949, CP949) = {
/*
* Name: CP949
* Link: http://www.microsoft.com/globaldev/reference/dbcs/949.mspx
- * Link: http://en.wikipedia.org/wiki/EUC-KR#EUC-KR
+ * Link: https://en.wikipedia.org/wiki/EUC-KR#EUC-KR
*/
diff --git a/enc/depend b/enc/depend
index 0fffcc273f..26f8e70c15 100644
--- a/enc/depend
+++ b/enc/depend
@@ -97,7 +97,7 @@ $(ENCSOS) $(TRANSSOS): $(ENC_TRANS_SO_D)
<%=transvpath_prefix%>.trans<%=transvpath_prefix%>.c:
$(ECHO) generating table from $@
- $(Q)$(MINIRUBY) "$(srcdir)/tool/transcode-tblgen.rb" -vo "$@" "$<"
+ $(Q)$(MINIRUBY) "$(tooldir)/transcode-tblgen.rb" -vo "$@" "$<"
% unless ENCS.empty? or TRANS.empty?
@@ -113,7 +113,7 @@ enc/<%=e%>.$(OBJEXT): <%=deps.map {|n| rule_subst % n}.join(' ')%>
% if src.empty?
% src = trans.scan(/^\s*transcode_tblgen_\w+\s+[\'\"]([^\'\"]*)/).flatten.map{|c|c.downcase+"-tbl.rb"}
% end
-<%=transvpath % "#{e}.c"%>: <%= src.map {|s| transvpath % "#{s}"}.join(" ")%> $(srcdir)/tool/transcode-tblgen.rb
+<%=transvpath % "#{e}.c"%>: <%= src.map {|s| transvpath % "#{s}"}.join(" ")%> $(tooldir)/transcode-tblgen.rb
% end
% end
@@ -178,33 +178,499 @@ clean-srcs:
<%# vim: set ft=eruby noexpandtab ts=8 sw=2 : -%>
# AUTOGENERATED DEPENDENCIES START
+enc/ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/ascii.$(OBJEXT): $(top_srcdir)/encindex.h
enc/ascii.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/ascii.$(OBJEXT): internal/anyargs.h
+enc/ascii.$(OBJEXT): internal/arithmetic.h
+enc/ascii.$(OBJEXT): internal/arithmetic/char.h
+enc/ascii.$(OBJEXT): internal/arithmetic/double.h
+enc/ascii.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/ascii.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/ascii.$(OBJEXT): internal/arithmetic/int.h
+enc/ascii.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/ascii.$(OBJEXT): internal/arithmetic/long.h
+enc/ascii.$(OBJEXT): internal/arithmetic/long_long.h
+enc/ascii.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/ascii.$(OBJEXT): internal/arithmetic/off_t.h
+enc/ascii.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/ascii.$(OBJEXT): internal/arithmetic/short.h
+enc/ascii.$(OBJEXT): internal/arithmetic/size_t.h
+enc/ascii.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/ascii.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/ascii.$(OBJEXT): internal/assume.h
+enc/ascii.$(OBJEXT): internal/attr/alloc_size.h
+enc/ascii.$(OBJEXT): internal/attr/artificial.h
+enc/ascii.$(OBJEXT): internal/attr/cold.h
+enc/ascii.$(OBJEXT): internal/attr/const.h
+enc/ascii.$(OBJEXT): internal/attr/constexpr.h
+enc/ascii.$(OBJEXT): internal/attr/deprecated.h
+enc/ascii.$(OBJEXT): internal/attr/diagnose_if.h
+enc/ascii.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/ascii.$(OBJEXT): internal/attr/error.h
+enc/ascii.$(OBJEXT): internal/attr/flag_enum.h
+enc/ascii.$(OBJEXT): internal/attr/forceinline.h
+enc/ascii.$(OBJEXT): internal/attr/format.h
+enc/ascii.$(OBJEXT): internal/attr/maybe_unused.h
+enc/ascii.$(OBJEXT): internal/attr/noalias.h
+enc/ascii.$(OBJEXT): internal/attr/nodiscard.h
+enc/ascii.$(OBJEXT): internal/attr/noexcept.h
+enc/ascii.$(OBJEXT): internal/attr/noinline.h
+enc/ascii.$(OBJEXT): internal/attr/nonnull.h
+enc/ascii.$(OBJEXT): internal/attr/noreturn.h
+enc/ascii.$(OBJEXT): internal/attr/pure.h
+enc/ascii.$(OBJEXT): internal/attr/restrict.h
+enc/ascii.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/ascii.$(OBJEXT): internal/attr/warning.h
+enc/ascii.$(OBJEXT): internal/attr/weakref.h
+enc/ascii.$(OBJEXT): internal/cast.h
+enc/ascii.$(OBJEXT): internal/compiler_is.h
+enc/ascii.$(OBJEXT): internal/compiler_is/apple.h
+enc/ascii.$(OBJEXT): internal/compiler_is/clang.h
+enc/ascii.$(OBJEXT): internal/compiler_is/gcc.h
+enc/ascii.$(OBJEXT): internal/compiler_is/intel.h
+enc/ascii.$(OBJEXT): internal/compiler_is/msvc.h
+enc/ascii.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/ascii.$(OBJEXT): internal/compiler_since.h
+enc/ascii.$(OBJEXT): internal/config.h
+enc/ascii.$(OBJEXT): internal/constant_p.h
+enc/ascii.$(OBJEXT): internal/core.h
+enc/ascii.$(OBJEXT): internal/core/rarray.h
+enc/ascii.$(OBJEXT): internal/core/rbasic.h
+enc/ascii.$(OBJEXT): internal/core/rbignum.h
+enc/ascii.$(OBJEXT): internal/core/rclass.h
+enc/ascii.$(OBJEXT): internal/core/rdata.h
+enc/ascii.$(OBJEXT): internal/core/rfile.h
+enc/ascii.$(OBJEXT): internal/core/rhash.h
+enc/ascii.$(OBJEXT): internal/core/robject.h
+enc/ascii.$(OBJEXT): internal/core/rregexp.h
+enc/ascii.$(OBJEXT): internal/core/rstring.h
+enc/ascii.$(OBJEXT): internal/core/rstruct.h
+enc/ascii.$(OBJEXT): internal/core/rtypeddata.h
+enc/ascii.$(OBJEXT): internal/ctype.h
+enc/ascii.$(OBJEXT): internal/dllexport.h
+enc/ascii.$(OBJEXT): internal/dosish.h
+enc/ascii.$(OBJEXT): internal/error.h
+enc/ascii.$(OBJEXT): internal/eval.h
+enc/ascii.$(OBJEXT): internal/event.h
+enc/ascii.$(OBJEXT): internal/fl_type.h
+enc/ascii.$(OBJEXT): internal/gc.h
+enc/ascii.$(OBJEXT): internal/glob.h
+enc/ascii.$(OBJEXT): internal/globals.h
+enc/ascii.$(OBJEXT): internal/has/attribute.h
+enc/ascii.$(OBJEXT): internal/has/builtin.h
+enc/ascii.$(OBJEXT): internal/has/c_attribute.h
+enc/ascii.$(OBJEXT): internal/has/cpp_attribute.h
+enc/ascii.$(OBJEXT): internal/has/declspec_attribute.h
+enc/ascii.$(OBJEXT): internal/has/extension.h
+enc/ascii.$(OBJEXT): internal/has/feature.h
+enc/ascii.$(OBJEXT): internal/has/warning.h
+enc/ascii.$(OBJEXT): internal/intern/array.h
+enc/ascii.$(OBJEXT): internal/intern/bignum.h
+enc/ascii.$(OBJEXT): internal/intern/class.h
+enc/ascii.$(OBJEXT): internal/intern/compar.h
+enc/ascii.$(OBJEXT): internal/intern/complex.h
+enc/ascii.$(OBJEXT): internal/intern/cont.h
+enc/ascii.$(OBJEXT): internal/intern/dir.h
+enc/ascii.$(OBJEXT): internal/intern/enum.h
+enc/ascii.$(OBJEXT): internal/intern/enumerator.h
+enc/ascii.$(OBJEXT): internal/intern/error.h
+enc/ascii.$(OBJEXT): internal/intern/eval.h
+enc/ascii.$(OBJEXT): internal/intern/file.h
+enc/ascii.$(OBJEXT): internal/intern/gc.h
+enc/ascii.$(OBJEXT): internal/intern/hash.h
+enc/ascii.$(OBJEXT): internal/intern/io.h
+enc/ascii.$(OBJEXT): internal/intern/load.h
+enc/ascii.$(OBJEXT): internal/intern/marshal.h
+enc/ascii.$(OBJEXT): internal/intern/numeric.h
+enc/ascii.$(OBJEXT): internal/intern/object.h
+enc/ascii.$(OBJEXT): internal/intern/parse.h
+enc/ascii.$(OBJEXT): internal/intern/proc.h
+enc/ascii.$(OBJEXT): internal/intern/process.h
+enc/ascii.$(OBJEXT): internal/intern/random.h
+enc/ascii.$(OBJEXT): internal/intern/range.h
+enc/ascii.$(OBJEXT): internal/intern/rational.h
+enc/ascii.$(OBJEXT): internal/intern/re.h
+enc/ascii.$(OBJEXT): internal/intern/ruby.h
+enc/ascii.$(OBJEXT): internal/intern/select.h
+enc/ascii.$(OBJEXT): internal/intern/select/largesize.h
+enc/ascii.$(OBJEXT): internal/intern/signal.h
+enc/ascii.$(OBJEXT): internal/intern/sprintf.h
+enc/ascii.$(OBJEXT): internal/intern/string.h
+enc/ascii.$(OBJEXT): internal/intern/struct.h
+enc/ascii.$(OBJEXT): internal/intern/thread.h
+enc/ascii.$(OBJEXT): internal/intern/time.h
+enc/ascii.$(OBJEXT): internal/intern/variable.h
+enc/ascii.$(OBJEXT): internal/intern/vm.h
+enc/ascii.$(OBJEXT): internal/interpreter.h
+enc/ascii.$(OBJEXT): internal/iterator.h
+enc/ascii.$(OBJEXT): internal/memory.h
+enc/ascii.$(OBJEXT): internal/method.h
+enc/ascii.$(OBJEXT): internal/module.h
+enc/ascii.$(OBJEXT): internal/newobj.h
+enc/ascii.$(OBJEXT): internal/rgengc.h
+enc/ascii.$(OBJEXT): internal/scan_args.h
+enc/ascii.$(OBJEXT): internal/special_consts.h
+enc/ascii.$(OBJEXT): internal/static_assert.h
+enc/ascii.$(OBJEXT): internal/stdalign.h
+enc/ascii.$(OBJEXT): internal/stdbool.h
+enc/ascii.$(OBJEXT): internal/symbol.h
+enc/ascii.$(OBJEXT): internal/token_paste.h
+enc/ascii.$(OBJEXT): internal/value.h
+enc/ascii.$(OBJEXT): internal/value_type.h
+enc/ascii.$(OBJEXT): internal/variable.h
+enc/ascii.$(OBJEXT): internal/warning_push.h
+enc/ascii.$(OBJEXT): internal/xmalloc.h
+enc/ascii.$(OBJEXT): assert.h
+enc/ascii.$(OBJEXT): backward/2/assume.h
+enc/ascii.$(OBJEXT): backward/2/attributes.h
+enc/ascii.$(OBJEXT): backward/2/bool.h
+enc/ascii.$(OBJEXT): backward/2/gcc_version_since.h
+enc/ascii.$(OBJEXT): backward/2/inttypes.h
+enc/ascii.$(OBJEXT): backward/2/limits.h
+enc/ascii.$(OBJEXT): backward/2/long_long.h
+enc/ascii.$(OBJEXT): backward/2/stdalign.h
+enc/ascii.$(OBJEXT): backward/2/stdarg.h
enc/ascii.$(OBJEXT): config.h
enc/ascii.$(OBJEXT): defines.h
enc/ascii.$(OBJEXT): enc/ascii.c
+enc/ascii.$(OBJEXT): encoding.h
+enc/ascii.$(OBJEXT): intern.h
enc/ascii.$(OBJEXT): missing.h
enc/ascii.$(OBJEXT): onigmo.h
+enc/ascii.$(OBJEXT): oniguruma.h
+enc/ascii.$(OBJEXT): st.h
+enc/ascii.$(OBJEXT): subst.h
enc/big5.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/big5.$(OBJEXT): internal/assume.h
+enc/big5.$(OBJEXT): internal/attr/alloc_size.h
+enc/big5.$(OBJEXT): internal/attr/cold.h
+enc/big5.$(OBJEXT): internal/attr/const.h
+enc/big5.$(OBJEXT): internal/attr/deprecated.h
+enc/big5.$(OBJEXT): internal/attr/error.h
+enc/big5.$(OBJEXT): internal/attr/forceinline.h
+enc/big5.$(OBJEXT): internal/attr/format.h
+enc/big5.$(OBJEXT): internal/attr/maybe_unused.h
+enc/big5.$(OBJEXT): internal/attr/nodiscard.h
+enc/big5.$(OBJEXT): internal/attr/noexcept.h
+enc/big5.$(OBJEXT): internal/attr/noinline.h
+enc/big5.$(OBJEXT): internal/attr/nonnull.h
+enc/big5.$(OBJEXT): internal/attr/noreturn.h
+enc/big5.$(OBJEXT): internal/attr/pure.h
+enc/big5.$(OBJEXT): internal/attr/restrict.h
+enc/big5.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/big5.$(OBJEXT): internal/attr/warning.h
+enc/big5.$(OBJEXT): internal/cast.h
+enc/big5.$(OBJEXT): internal/compiler_is.h
+enc/big5.$(OBJEXT): internal/compiler_is/apple.h
+enc/big5.$(OBJEXT): internal/compiler_is/clang.h
+enc/big5.$(OBJEXT): internal/compiler_is/gcc.h
+enc/big5.$(OBJEXT): internal/compiler_is/intel.h
+enc/big5.$(OBJEXT): internal/compiler_is/msvc.h
+enc/big5.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/big5.$(OBJEXT): internal/compiler_since.h
+enc/big5.$(OBJEXT): internal/config.h
+enc/big5.$(OBJEXT): internal/dllexport.h
+enc/big5.$(OBJEXT): internal/dosish.h
+enc/big5.$(OBJEXT): internal/has/attribute.h
+enc/big5.$(OBJEXT): internal/has/builtin.h
+enc/big5.$(OBJEXT): internal/has/c_attribute.h
+enc/big5.$(OBJEXT): internal/has/cpp_attribute.h
+enc/big5.$(OBJEXT): internal/has/declspec_attribute.h
+enc/big5.$(OBJEXT): internal/has/extension.h
+enc/big5.$(OBJEXT): internal/has/feature.h
+enc/big5.$(OBJEXT): internal/has/warning.h
+enc/big5.$(OBJEXT): internal/stdalign.h
+enc/big5.$(OBJEXT): internal/stdbool.h
+enc/big5.$(OBJEXT): internal/token_paste.h
+enc/big5.$(OBJEXT): internal/warning_push.h
+enc/big5.$(OBJEXT): internal/xmalloc.h
+enc/big5.$(OBJEXT): assert.h
+enc/big5.$(OBJEXT): backward/2/assume.h
+enc/big5.$(OBJEXT): backward/2/attributes.h
+enc/big5.$(OBJEXT): backward/2/bool.h
+enc/big5.$(OBJEXT): backward/2/gcc_version_since.h
+enc/big5.$(OBJEXT): backward/2/long_long.h
+enc/big5.$(OBJEXT): backward/2/stdalign.h
+enc/big5.$(OBJEXT): backward/2/stdarg.h
enc/big5.$(OBJEXT): config.h
enc/big5.$(OBJEXT): defines.h
enc/big5.$(OBJEXT): enc/big5.c
enc/big5.$(OBJEXT): missing.h
enc/big5.$(OBJEXT): onigmo.h
+enc/cesu_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/cesu_8.$(OBJEXT): $(top_srcdir)/encindex.h
enc/cesu_8.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/cesu_8.$(OBJEXT): internal/anyargs.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/char.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/double.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/int.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/long.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/long_long.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/off_t.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/short.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/size_t.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/cesu_8.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/cesu_8.$(OBJEXT): internal/assume.h
+enc/cesu_8.$(OBJEXT): internal/attr/alloc_size.h
+enc/cesu_8.$(OBJEXT): internal/attr/artificial.h
+enc/cesu_8.$(OBJEXT): internal/attr/cold.h
+enc/cesu_8.$(OBJEXT): internal/attr/const.h
+enc/cesu_8.$(OBJEXT): internal/attr/constexpr.h
+enc/cesu_8.$(OBJEXT): internal/attr/deprecated.h
+enc/cesu_8.$(OBJEXT): internal/attr/diagnose_if.h
+enc/cesu_8.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/cesu_8.$(OBJEXT): internal/attr/error.h
+enc/cesu_8.$(OBJEXT): internal/attr/flag_enum.h
+enc/cesu_8.$(OBJEXT): internal/attr/forceinline.h
+enc/cesu_8.$(OBJEXT): internal/attr/format.h
+enc/cesu_8.$(OBJEXT): internal/attr/maybe_unused.h
+enc/cesu_8.$(OBJEXT): internal/attr/noalias.h
+enc/cesu_8.$(OBJEXT): internal/attr/nodiscard.h
+enc/cesu_8.$(OBJEXT): internal/attr/noexcept.h
+enc/cesu_8.$(OBJEXT): internal/attr/noinline.h
+enc/cesu_8.$(OBJEXT): internal/attr/nonnull.h
+enc/cesu_8.$(OBJEXT): internal/attr/noreturn.h
+enc/cesu_8.$(OBJEXT): internal/attr/pure.h
+enc/cesu_8.$(OBJEXT): internal/attr/restrict.h
+enc/cesu_8.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/cesu_8.$(OBJEXT): internal/attr/warning.h
+enc/cesu_8.$(OBJEXT): internal/attr/weakref.h
+enc/cesu_8.$(OBJEXT): internal/cast.h
+enc/cesu_8.$(OBJEXT): internal/compiler_is.h
+enc/cesu_8.$(OBJEXT): internal/compiler_is/apple.h
+enc/cesu_8.$(OBJEXT): internal/compiler_is/clang.h
+enc/cesu_8.$(OBJEXT): internal/compiler_is/gcc.h
+enc/cesu_8.$(OBJEXT): internal/compiler_is/intel.h
+enc/cesu_8.$(OBJEXT): internal/compiler_is/msvc.h
+enc/cesu_8.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/cesu_8.$(OBJEXT): internal/compiler_since.h
+enc/cesu_8.$(OBJEXT): internal/config.h
+enc/cesu_8.$(OBJEXT): internal/constant_p.h
+enc/cesu_8.$(OBJEXT): internal/core.h
+enc/cesu_8.$(OBJEXT): internal/core/rarray.h
+enc/cesu_8.$(OBJEXT): internal/core/rbasic.h
+enc/cesu_8.$(OBJEXT): internal/core/rbignum.h
+enc/cesu_8.$(OBJEXT): internal/core/rclass.h
+enc/cesu_8.$(OBJEXT): internal/core/rdata.h
+enc/cesu_8.$(OBJEXT): internal/core/rfile.h
+enc/cesu_8.$(OBJEXT): internal/core/rhash.h
+enc/cesu_8.$(OBJEXT): internal/core/robject.h
+enc/cesu_8.$(OBJEXT): internal/core/rregexp.h
+enc/cesu_8.$(OBJEXT): internal/core/rstring.h
+enc/cesu_8.$(OBJEXT): internal/core/rstruct.h
+enc/cesu_8.$(OBJEXT): internal/core/rtypeddata.h
+enc/cesu_8.$(OBJEXT): internal/ctype.h
+enc/cesu_8.$(OBJEXT): internal/dllexport.h
+enc/cesu_8.$(OBJEXT): internal/dosish.h
+enc/cesu_8.$(OBJEXT): internal/error.h
+enc/cesu_8.$(OBJEXT): internal/eval.h
+enc/cesu_8.$(OBJEXT): internal/event.h
+enc/cesu_8.$(OBJEXT): internal/fl_type.h
+enc/cesu_8.$(OBJEXT): internal/gc.h
+enc/cesu_8.$(OBJEXT): internal/glob.h
+enc/cesu_8.$(OBJEXT): internal/globals.h
+enc/cesu_8.$(OBJEXT): internal/has/attribute.h
+enc/cesu_8.$(OBJEXT): internal/has/builtin.h
+enc/cesu_8.$(OBJEXT): internal/has/c_attribute.h
+enc/cesu_8.$(OBJEXT): internal/has/cpp_attribute.h
+enc/cesu_8.$(OBJEXT): internal/has/declspec_attribute.h
+enc/cesu_8.$(OBJEXT): internal/has/extension.h
+enc/cesu_8.$(OBJEXT): internal/has/feature.h
+enc/cesu_8.$(OBJEXT): internal/has/warning.h
+enc/cesu_8.$(OBJEXT): internal/intern/array.h
+enc/cesu_8.$(OBJEXT): internal/intern/bignum.h
+enc/cesu_8.$(OBJEXT): internal/intern/class.h
+enc/cesu_8.$(OBJEXT): internal/intern/compar.h
+enc/cesu_8.$(OBJEXT): internal/intern/complex.h
+enc/cesu_8.$(OBJEXT): internal/intern/cont.h
+enc/cesu_8.$(OBJEXT): internal/intern/dir.h
+enc/cesu_8.$(OBJEXT): internal/intern/enum.h
+enc/cesu_8.$(OBJEXT): internal/intern/enumerator.h
+enc/cesu_8.$(OBJEXT): internal/intern/error.h
+enc/cesu_8.$(OBJEXT): internal/intern/eval.h
+enc/cesu_8.$(OBJEXT): internal/intern/file.h
+enc/cesu_8.$(OBJEXT): internal/intern/gc.h
+enc/cesu_8.$(OBJEXT): internal/intern/hash.h
+enc/cesu_8.$(OBJEXT): internal/intern/io.h
+enc/cesu_8.$(OBJEXT): internal/intern/load.h
+enc/cesu_8.$(OBJEXT): internal/intern/marshal.h
+enc/cesu_8.$(OBJEXT): internal/intern/numeric.h
+enc/cesu_8.$(OBJEXT): internal/intern/object.h
+enc/cesu_8.$(OBJEXT): internal/intern/parse.h
+enc/cesu_8.$(OBJEXT): internal/intern/proc.h
+enc/cesu_8.$(OBJEXT): internal/intern/process.h
+enc/cesu_8.$(OBJEXT): internal/intern/random.h
+enc/cesu_8.$(OBJEXT): internal/intern/range.h
+enc/cesu_8.$(OBJEXT): internal/intern/rational.h
+enc/cesu_8.$(OBJEXT): internal/intern/re.h
+enc/cesu_8.$(OBJEXT): internal/intern/ruby.h
+enc/cesu_8.$(OBJEXT): internal/intern/select.h
+enc/cesu_8.$(OBJEXT): internal/intern/select/largesize.h
+enc/cesu_8.$(OBJEXT): internal/intern/signal.h
+enc/cesu_8.$(OBJEXT): internal/intern/sprintf.h
+enc/cesu_8.$(OBJEXT): internal/intern/string.h
+enc/cesu_8.$(OBJEXT): internal/intern/struct.h
+enc/cesu_8.$(OBJEXT): internal/intern/thread.h
+enc/cesu_8.$(OBJEXT): internal/intern/time.h
+enc/cesu_8.$(OBJEXT): internal/intern/variable.h
+enc/cesu_8.$(OBJEXT): internal/intern/vm.h
+enc/cesu_8.$(OBJEXT): internal/interpreter.h
+enc/cesu_8.$(OBJEXT): internal/iterator.h
+enc/cesu_8.$(OBJEXT): internal/memory.h
+enc/cesu_8.$(OBJEXT): internal/method.h
+enc/cesu_8.$(OBJEXT): internal/module.h
+enc/cesu_8.$(OBJEXT): internal/newobj.h
+enc/cesu_8.$(OBJEXT): internal/rgengc.h
+enc/cesu_8.$(OBJEXT): internal/scan_args.h
+enc/cesu_8.$(OBJEXT): internal/special_consts.h
+enc/cesu_8.$(OBJEXT): internal/static_assert.h
+enc/cesu_8.$(OBJEXT): internal/stdalign.h
+enc/cesu_8.$(OBJEXT): internal/stdbool.h
+enc/cesu_8.$(OBJEXT): internal/symbol.h
+enc/cesu_8.$(OBJEXT): internal/token_paste.h
+enc/cesu_8.$(OBJEXT): internal/value.h
+enc/cesu_8.$(OBJEXT): internal/value_type.h
+enc/cesu_8.$(OBJEXT): internal/variable.h
+enc/cesu_8.$(OBJEXT): internal/warning_push.h
+enc/cesu_8.$(OBJEXT): internal/xmalloc.h
+enc/cesu_8.$(OBJEXT): assert.h
+enc/cesu_8.$(OBJEXT): backward.h
+enc/cesu_8.$(OBJEXT): backward/2/assume.h
+enc/cesu_8.$(OBJEXT): backward/2/attributes.h
+enc/cesu_8.$(OBJEXT): backward/2/bool.h
+enc/cesu_8.$(OBJEXT): backward/2/gcc_version_since.h
+enc/cesu_8.$(OBJEXT): backward/2/inttypes.h
+enc/cesu_8.$(OBJEXT): backward/2/limits.h
+enc/cesu_8.$(OBJEXT): backward/2/long_long.h
+enc/cesu_8.$(OBJEXT): backward/2/stdalign.h
+enc/cesu_8.$(OBJEXT): backward/2/stdarg.h
enc/cesu_8.$(OBJEXT): config.h
enc/cesu_8.$(OBJEXT): defines.h
enc/cesu_8.$(OBJEXT): enc/cesu_8.c
+enc/cesu_8.$(OBJEXT): encoding.h
+enc/cesu_8.$(OBJEXT): intern.h
enc/cesu_8.$(OBJEXT): missing.h
enc/cesu_8.$(OBJEXT): onigmo.h
+enc/cesu_8.$(OBJEXT): oniguruma.h
+enc/cesu_8.$(OBJEXT): st.h
+enc/cesu_8.$(OBJEXT): subst.h
enc/cp949.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/cp949.$(OBJEXT): internal/assume.h
+enc/cp949.$(OBJEXT): internal/attr/alloc_size.h
+enc/cp949.$(OBJEXT): internal/attr/cold.h
+enc/cp949.$(OBJEXT): internal/attr/const.h
+enc/cp949.$(OBJEXT): internal/attr/deprecated.h
+enc/cp949.$(OBJEXT): internal/attr/error.h
+enc/cp949.$(OBJEXT): internal/attr/forceinline.h
+enc/cp949.$(OBJEXT): internal/attr/format.h
+enc/cp949.$(OBJEXT): internal/attr/maybe_unused.h
+enc/cp949.$(OBJEXT): internal/attr/nodiscard.h
+enc/cp949.$(OBJEXT): internal/attr/noexcept.h
+enc/cp949.$(OBJEXT): internal/attr/noinline.h
+enc/cp949.$(OBJEXT): internal/attr/nonnull.h
+enc/cp949.$(OBJEXT): internal/attr/noreturn.h
+enc/cp949.$(OBJEXT): internal/attr/pure.h
+enc/cp949.$(OBJEXT): internal/attr/restrict.h
+enc/cp949.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/cp949.$(OBJEXT): internal/attr/warning.h
+enc/cp949.$(OBJEXT): internal/cast.h
+enc/cp949.$(OBJEXT): internal/compiler_is.h
+enc/cp949.$(OBJEXT): internal/compiler_is/apple.h
+enc/cp949.$(OBJEXT): internal/compiler_is/clang.h
+enc/cp949.$(OBJEXT): internal/compiler_is/gcc.h
+enc/cp949.$(OBJEXT): internal/compiler_is/intel.h
+enc/cp949.$(OBJEXT): internal/compiler_is/msvc.h
+enc/cp949.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/cp949.$(OBJEXT): internal/compiler_since.h
+enc/cp949.$(OBJEXT): internal/config.h
+enc/cp949.$(OBJEXT): internal/dllexport.h
+enc/cp949.$(OBJEXT): internal/dosish.h
+enc/cp949.$(OBJEXT): internal/has/attribute.h
+enc/cp949.$(OBJEXT): internal/has/builtin.h
+enc/cp949.$(OBJEXT): internal/has/c_attribute.h
+enc/cp949.$(OBJEXT): internal/has/cpp_attribute.h
+enc/cp949.$(OBJEXT): internal/has/declspec_attribute.h
+enc/cp949.$(OBJEXT): internal/has/extension.h
+enc/cp949.$(OBJEXT): internal/has/feature.h
+enc/cp949.$(OBJEXT): internal/has/warning.h
+enc/cp949.$(OBJEXT): internal/stdalign.h
+enc/cp949.$(OBJEXT): internal/stdbool.h
+enc/cp949.$(OBJEXT): internal/token_paste.h
+enc/cp949.$(OBJEXT): internal/warning_push.h
+enc/cp949.$(OBJEXT): internal/xmalloc.h
+enc/cp949.$(OBJEXT): assert.h
+enc/cp949.$(OBJEXT): backward/2/assume.h
+enc/cp949.$(OBJEXT): backward/2/attributes.h
+enc/cp949.$(OBJEXT): backward/2/bool.h
+enc/cp949.$(OBJEXT): backward/2/gcc_version_since.h
+enc/cp949.$(OBJEXT): backward/2/long_long.h
+enc/cp949.$(OBJEXT): backward/2/stdalign.h
+enc/cp949.$(OBJEXT): backward/2/stdarg.h
enc/cp949.$(OBJEXT): config.h
enc/cp949.$(OBJEXT): defines.h
enc/cp949.$(OBJEXT): enc/cp949.c
enc/cp949.$(OBJEXT): missing.h
enc/cp949.$(OBJEXT): onigmo.h
enc/emacs_mule.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/emacs_mule.$(OBJEXT): internal/assume.h
+enc/emacs_mule.$(OBJEXT): internal/attr/alloc_size.h
+enc/emacs_mule.$(OBJEXT): internal/attr/cold.h
+enc/emacs_mule.$(OBJEXT): internal/attr/const.h
+enc/emacs_mule.$(OBJEXT): internal/attr/deprecated.h
+enc/emacs_mule.$(OBJEXT): internal/attr/error.h
+enc/emacs_mule.$(OBJEXT): internal/attr/forceinline.h
+enc/emacs_mule.$(OBJEXT): internal/attr/format.h
+enc/emacs_mule.$(OBJEXT): internal/attr/maybe_unused.h
+enc/emacs_mule.$(OBJEXT): internal/attr/nodiscard.h
+enc/emacs_mule.$(OBJEXT): internal/attr/noexcept.h
+enc/emacs_mule.$(OBJEXT): internal/attr/noinline.h
+enc/emacs_mule.$(OBJEXT): internal/attr/nonnull.h
+enc/emacs_mule.$(OBJEXT): internal/attr/noreturn.h
+enc/emacs_mule.$(OBJEXT): internal/attr/pure.h
+enc/emacs_mule.$(OBJEXT): internal/attr/restrict.h
+enc/emacs_mule.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/emacs_mule.$(OBJEXT): internal/attr/warning.h
+enc/emacs_mule.$(OBJEXT): internal/cast.h
+enc/emacs_mule.$(OBJEXT): internal/compiler_is.h
+enc/emacs_mule.$(OBJEXT): internal/compiler_is/apple.h
+enc/emacs_mule.$(OBJEXT): internal/compiler_is/clang.h
+enc/emacs_mule.$(OBJEXT): internal/compiler_is/gcc.h
+enc/emacs_mule.$(OBJEXT): internal/compiler_is/intel.h
+enc/emacs_mule.$(OBJEXT): internal/compiler_is/msvc.h
+enc/emacs_mule.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/emacs_mule.$(OBJEXT): internal/compiler_since.h
+enc/emacs_mule.$(OBJEXT): internal/config.h
+enc/emacs_mule.$(OBJEXT): internal/dllexport.h
+enc/emacs_mule.$(OBJEXT): internal/dosish.h
+enc/emacs_mule.$(OBJEXT): internal/has/attribute.h
+enc/emacs_mule.$(OBJEXT): internal/has/builtin.h
+enc/emacs_mule.$(OBJEXT): internal/has/c_attribute.h
+enc/emacs_mule.$(OBJEXT): internal/has/cpp_attribute.h
+enc/emacs_mule.$(OBJEXT): internal/has/declspec_attribute.h
+enc/emacs_mule.$(OBJEXT): internal/has/extension.h
+enc/emacs_mule.$(OBJEXT): internal/has/feature.h
+enc/emacs_mule.$(OBJEXT): internal/has/warning.h
+enc/emacs_mule.$(OBJEXT): internal/stdalign.h
+enc/emacs_mule.$(OBJEXT): internal/stdbool.h
+enc/emacs_mule.$(OBJEXT): internal/token_paste.h
+enc/emacs_mule.$(OBJEXT): internal/warning_push.h
+enc/emacs_mule.$(OBJEXT): internal/xmalloc.h
+enc/emacs_mule.$(OBJEXT): assert.h
+enc/emacs_mule.$(OBJEXT): backward/2/assume.h
+enc/emacs_mule.$(OBJEXT): backward/2/attributes.h
+enc/emacs_mule.$(OBJEXT): backward/2/bool.h
+enc/emacs_mule.$(OBJEXT): backward/2/gcc_version_since.h
+enc/emacs_mule.$(OBJEXT): backward/2/long_long.h
+enc/emacs_mule.$(OBJEXT): backward/2/stdalign.h
+enc/emacs_mule.$(OBJEXT): backward/2/stdarg.h
enc/emacs_mule.$(OBJEXT): config.h
enc/emacs_mule.$(OBJEXT): defines.h
enc/emacs_mule.$(OBJEXT): enc/emacs_mule.c
@@ -213,17 +679,221 @@ enc/emacs_mule.$(OBJEXT): onigmo.h
enc/encdb.$(OBJEXT): $(hdrdir)/ruby.h
enc/encdb.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/encdb.$(OBJEXT): $(top_srcdir)/internal.h
+enc/encdb.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+enc/encdb.$(OBJEXT): internal/anyargs.h
+enc/encdb.$(OBJEXT): internal/arithmetic.h
+enc/encdb.$(OBJEXT): internal/arithmetic/char.h
+enc/encdb.$(OBJEXT): internal/arithmetic/double.h
+enc/encdb.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/encdb.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/encdb.$(OBJEXT): internal/arithmetic/int.h
+enc/encdb.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/encdb.$(OBJEXT): internal/arithmetic/long.h
+enc/encdb.$(OBJEXT): internal/arithmetic/long_long.h
+enc/encdb.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/encdb.$(OBJEXT): internal/arithmetic/off_t.h
+enc/encdb.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/encdb.$(OBJEXT): internal/arithmetic/short.h
+enc/encdb.$(OBJEXT): internal/arithmetic/size_t.h
+enc/encdb.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/encdb.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/encdb.$(OBJEXT): internal/assume.h
+enc/encdb.$(OBJEXT): internal/attr/alloc_size.h
+enc/encdb.$(OBJEXT): internal/attr/artificial.h
+enc/encdb.$(OBJEXT): internal/attr/cold.h
+enc/encdb.$(OBJEXT): internal/attr/const.h
+enc/encdb.$(OBJEXT): internal/attr/constexpr.h
+enc/encdb.$(OBJEXT): internal/attr/deprecated.h
+enc/encdb.$(OBJEXT): internal/attr/diagnose_if.h
+enc/encdb.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/encdb.$(OBJEXT): internal/attr/error.h
+enc/encdb.$(OBJEXT): internal/attr/flag_enum.h
+enc/encdb.$(OBJEXT): internal/attr/forceinline.h
+enc/encdb.$(OBJEXT): internal/attr/format.h
+enc/encdb.$(OBJEXT): internal/attr/maybe_unused.h
+enc/encdb.$(OBJEXT): internal/attr/noalias.h
+enc/encdb.$(OBJEXT): internal/attr/nodiscard.h
+enc/encdb.$(OBJEXT): internal/attr/noexcept.h
+enc/encdb.$(OBJEXT): internal/attr/noinline.h
+enc/encdb.$(OBJEXT): internal/attr/nonnull.h
+enc/encdb.$(OBJEXT): internal/attr/noreturn.h
+enc/encdb.$(OBJEXT): internal/attr/pure.h
+enc/encdb.$(OBJEXT): internal/attr/restrict.h
+enc/encdb.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/encdb.$(OBJEXT): internal/attr/warning.h
+enc/encdb.$(OBJEXT): internal/attr/weakref.h
+enc/encdb.$(OBJEXT): internal/cast.h
+enc/encdb.$(OBJEXT): internal/compiler_is.h
+enc/encdb.$(OBJEXT): internal/compiler_is/apple.h
+enc/encdb.$(OBJEXT): internal/compiler_is/clang.h
+enc/encdb.$(OBJEXT): internal/compiler_is/gcc.h
+enc/encdb.$(OBJEXT): internal/compiler_is/intel.h
+enc/encdb.$(OBJEXT): internal/compiler_is/msvc.h
+enc/encdb.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/encdb.$(OBJEXT): internal/compiler_since.h
+enc/encdb.$(OBJEXT): internal/config.h
+enc/encdb.$(OBJEXT): internal/constant_p.h
+enc/encdb.$(OBJEXT): internal/core.h
+enc/encdb.$(OBJEXT): internal/core/rarray.h
+enc/encdb.$(OBJEXT): internal/core/rbasic.h
+enc/encdb.$(OBJEXT): internal/core/rbignum.h
+enc/encdb.$(OBJEXT): internal/core/rclass.h
+enc/encdb.$(OBJEXT): internal/core/rdata.h
+enc/encdb.$(OBJEXT): internal/core/rfile.h
+enc/encdb.$(OBJEXT): internal/core/rhash.h
+enc/encdb.$(OBJEXT): internal/core/robject.h
+enc/encdb.$(OBJEXT): internal/core/rregexp.h
+enc/encdb.$(OBJEXT): internal/core/rstring.h
+enc/encdb.$(OBJEXT): internal/core/rstruct.h
+enc/encdb.$(OBJEXT): internal/core/rtypeddata.h
+enc/encdb.$(OBJEXT): internal/ctype.h
+enc/encdb.$(OBJEXT): internal/dllexport.h
+enc/encdb.$(OBJEXT): internal/dosish.h
+enc/encdb.$(OBJEXT): internal/error.h
+enc/encdb.$(OBJEXT): internal/eval.h
+enc/encdb.$(OBJEXT): internal/event.h
+enc/encdb.$(OBJEXT): internal/fl_type.h
+enc/encdb.$(OBJEXT): internal/gc.h
+enc/encdb.$(OBJEXT): internal/glob.h
+enc/encdb.$(OBJEXT): internal/globals.h
+enc/encdb.$(OBJEXT): internal/has/attribute.h
+enc/encdb.$(OBJEXT): internal/has/builtin.h
+enc/encdb.$(OBJEXT): internal/has/c_attribute.h
+enc/encdb.$(OBJEXT): internal/has/cpp_attribute.h
+enc/encdb.$(OBJEXT): internal/has/declspec_attribute.h
+enc/encdb.$(OBJEXT): internal/has/extension.h
+enc/encdb.$(OBJEXT): internal/has/feature.h
+enc/encdb.$(OBJEXT): internal/has/warning.h
+enc/encdb.$(OBJEXT): internal/intern/array.h
+enc/encdb.$(OBJEXT): internal/intern/bignum.h
+enc/encdb.$(OBJEXT): internal/intern/class.h
+enc/encdb.$(OBJEXT): internal/intern/compar.h
+enc/encdb.$(OBJEXT): internal/intern/complex.h
+enc/encdb.$(OBJEXT): internal/intern/cont.h
+enc/encdb.$(OBJEXT): internal/intern/dir.h
+enc/encdb.$(OBJEXT): internal/intern/enum.h
+enc/encdb.$(OBJEXT): internal/intern/enumerator.h
+enc/encdb.$(OBJEXT): internal/intern/error.h
+enc/encdb.$(OBJEXT): internal/intern/eval.h
+enc/encdb.$(OBJEXT): internal/intern/file.h
+enc/encdb.$(OBJEXT): internal/intern/gc.h
+enc/encdb.$(OBJEXT): internal/intern/hash.h
+enc/encdb.$(OBJEXT): internal/intern/io.h
+enc/encdb.$(OBJEXT): internal/intern/load.h
+enc/encdb.$(OBJEXT): internal/intern/marshal.h
+enc/encdb.$(OBJEXT): internal/intern/numeric.h
+enc/encdb.$(OBJEXT): internal/intern/object.h
+enc/encdb.$(OBJEXT): internal/intern/parse.h
+enc/encdb.$(OBJEXT): internal/intern/proc.h
+enc/encdb.$(OBJEXT): internal/intern/process.h
+enc/encdb.$(OBJEXT): internal/intern/random.h
+enc/encdb.$(OBJEXT): internal/intern/range.h
+enc/encdb.$(OBJEXT): internal/intern/rational.h
+enc/encdb.$(OBJEXT): internal/intern/re.h
+enc/encdb.$(OBJEXT): internal/intern/ruby.h
+enc/encdb.$(OBJEXT): internal/intern/select.h
+enc/encdb.$(OBJEXT): internal/intern/select/largesize.h
+enc/encdb.$(OBJEXT): internal/intern/signal.h
+enc/encdb.$(OBJEXT): internal/intern/sprintf.h
+enc/encdb.$(OBJEXT): internal/intern/string.h
+enc/encdb.$(OBJEXT): internal/intern/struct.h
+enc/encdb.$(OBJEXT): internal/intern/thread.h
+enc/encdb.$(OBJEXT): internal/intern/time.h
+enc/encdb.$(OBJEXT): internal/intern/variable.h
+enc/encdb.$(OBJEXT): internal/intern/vm.h
+enc/encdb.$(OBJEXT): internal/interpreter.h
+enc/encdb.$(OBJEXT): internal/iterator.h
+enc/encdb.$(OBJEXT): internal/memory.h
+enc/encdb.$(OBJEXT): internal/method.h
+enc/encdb.$(OBJEXT): internal/module.h
+enc/encdb.$(OBJEXT): internal/newobj.h
+enc/encdb.$(OBJEXT): internal/rgengc.h
+enc/encdb.$(OBJEXT): internal/scan_args.h
+enc/encdb.$(OBJEXT): internal/special_consts.h
+enc/encdb.$(OBJEXT): internal/static_assert.h
+enc/encdb.$(OBJEXT): internal/stdalign.h
+enc/encdb.$(OBJEXT): internal/stdbool.h
+enc/encdb.$(OBJEXT): internal/symbol.h
+enc/encdb.$(OBJEXT): internal/token_paste.h
+enc/encdb.$(OBJEXT): internal/value.h
+enc/encdb.$(OBJEXT): internal/value_type.h
+enc/encdb.$(OBJEXT): internal/variable.h
+enc/encdb.$(OBJEXT): internal/warning_push.h
+enc/encdb.$(OBJEXT): internal/xmalloc.h
enc/encdb.$(OBJEXT): assert.h
enc/encdb.$(OBJEXT): backward.h
+enc/encdb.$(OBJEXT): backward/2/assume.h
+enc/encdb.$(OBJEXT): backward/2/attributes.h
+enc/encdb.$(OBJEXT): backward/2/bool.h
+enc/encdb.$(OBJEXT): backward/2/gcc_version_since.h
+enc/encdb.$(OBJEXT): backward/2/inttypes.h
+enc/encdb.$(OBJEXT): backward/2/limits.h
+enc/encdb.$(OBJEXT): backward/2/long_long.h
+enc/encdb.$(OBJEXT): backward/2/stdalign.h
+enc/encdb.$(OBJEXT): backward/2/stdarg.h
enc/encdb.$(OBJEXT): config.h
enc/encdb.$(OBJEXT): defines.h
enc/encdb.$(OBJEXT): enc/encdb.c
enc/encdb.$(OBJEXT): encdb.h
+enc/encdb.$(OBJEXT): encoding.h
enc/encdb.$(OBJEXT): intern.h
enc/encdb.$(OBJEXT): missing.h
+enc/encdb.$(OBJEXT): onigmo.h
+enc/encdb.$(OBJEXT): oniguruma.h
enc/encdb.$(OBJEXT): st.h
enc/encdb.$(OBJEXT): subst.h
enc/euc_jp.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/euc_jp.$(OBJEXT): internal/assume.h
+enc/euc_jp.$(OBJEXT): internal/attr/alloc_size.h
+enc/euc_jp.$(OBJEXT): internal/attr/cold.h
+enc/euc_jp.$(OBJEXT): internal/attr/const.h
+enc/euc_jp.$(OBJEXT): internal/attr/deprecated.h
+enc/euc_jp.$(OBJEXT): internal/attr/error.h
+enc/euc_jp.$(OBJEXT): internal/attr/forceinline.h
+enc/euc_jp.$(OBJEXT): internal/attr/format.h
+enc/euc_jp.$(OBJEXT): internal/attr/maybe_unused.h
+enc/euc_jp.$(OBJEXT): internal/attr/nodiscard.h
+enc/euc_jp.$(OBJEXT): internal/attr/noexcept.h
+enc/euc_jp.$(OBJEXT): internal/attr/noinline.h
+enc/euc_jp.$(OBJEXT): internal/attr/nonnull.h
+enc/euc_jp.$(OBJEXT): internal/attr/noreturn.h
+enc/euc_jp.$(OBJEXT): internal/attr/pure.h
+enc/euc_jp.$(OBJEXT): internal/attr/restrict.h
+enc/euc_jp.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/euc_jp.$(OBJEXT): internal/attr/warning.h
+enc/euc_jp.$(OBJEXT): internal/cast.h
+enc/euc_jp.$(OBJEXT): internal/compiler_is.h
+enc/euc_jp.$(OBJEXT): internal/compiler_is/apple.h
+enc/euc_jp.$(OBJEXT): internal/compiler_is/clang.h
+enc/euc_jp.$(OBJEXT): internal/compiler_is/gcc.h
+enc/euc_jp.$(OBJEXT): internal/compiler_is/intel.h
+enc/euc_jp.$(OBJEXT): internal/compiler_is/msvc.h
+enc/euc_jp.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/euc_jp.$(OBJEXT): internal/compiler_since.h
+enc/euc_jp.$(OBJEXT): internal/config.h
+enc/euc_jp.$(OBJEXT): internal/dllexport.h
+enc/euc_jp.$(OBJEXT): internal/dosish.h
+enc/euc_jp.$(OBJEXT): internal/has/attribute.h
+enc/euc_jp.$(OBJEXT): internal/has/builtin.h
+enc/euc_jp.$(OBJEXT): internal/has/c_attribute.h
+enc/euc_jp.$(OBJEXT): internal/has/cpp_attribute.h
+enc/euc_jp.$(OBJEXT): internal/has/declspec_attribute.h
+enc/euc_jp.$(OBJEXT): internal/has/extension.h
+enc/euc_jp.$(OBJEXT): internal/has/feature.h
+enc/euc_jp.$(OBJEXT): internal/has/warning.h
+enc/euc_jp.$(OBJEXT): internal/stdalign.h
+enc/euc_jp.$(OBJEXT): internal/stdbool.h
+enc/euc_jp.$(OBJEXT): internal/token_paste.h
+enc/euc_jp.$(OBJEXT): internal/warning_push.h
+enc/euc_jp.$(OBJEXT): internal/xmalloc.h
+enc/euc_jp.$(OBJEXT): assert.h
+enc/euc_jp.$(OBJEXT): backward/2/assume.h
+enc/euc_jp.$(OBJEXT): backward/2/attributes.h
+enc/euc_jp.$(OBJEXT): backward/2/bool.h
+enc/euc_jp.$(OBJEXT): backward/2/gcc_version_since.h
+enc/euc_jp.$(OBJEXT): backward/2/long_long.h
+enc/euc_jp.$(OBJEXT): backward/2/stdalign.h
+enc/euc_jp.$(OBJEXT): backward/2/stdarg.h
enc/euc_jp.$(OBJEXT): config.h
enc/euc_jp.$(OBJEXT): defines.h
enc/euc_jp.$(OBJEXT): enc/euc_jp.c
@@ -232,36 +902,342 @@ enc/euc_jp.$(OBJEXT): enc/jis/props.kwd
enc/euc_jp.$(OBJEXT): missing.h
enc/euc_jp.$(OBJEXT): onigmo.h
enc/euc_kr.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/euc_kr.$(OBJEXT): internal/assume.h
+enc/euc_kr.$(OBJEXT): internal/attr/alloc_size.h
+enc/euc_kr.$(OBJEXT): internal/attr/cold.h
+enc/euc_kr.$(OBJEXT): internal/attr/const.h
+enc/euc_kr.$(OBJEXT): internal/attr/deprecated.h
+enc/euc_kr.$(OBJEXT): internal/attr/error.h
+enc/euc_kr.$(OBJEXT): internal/attr/forceinline.h
+enc/euc_kr.$(OBJEXT): internal/attr/format.h
+enc/euc_kr.$(OBJEXT): internal/attr/maybe_unused.h
+enc/euc_kr.$(OBJEXT): internal/attr/nodiscard.h
+enc/euc_kr.$(OBJEXT): internal/attr/noexcept.h
+enc/euc_kr.$(OBJEXT): internal/attr/noinline.h
+enc/euc_kr.$(OBJEXT): internal/attr/nonnull.h
+enc/euc_kr.$(OBJEXT): internal/attr/noreturn.h
+enc/euc_kr.$(OBJEXT): internal/attr/pure.h
+enc/euc_kr.$(OBJEXT): internal/attr/restrict.h
+enc/euc_kr.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/euc_kr.$(OBJEXT): internal/attr/warning.h
+enc/euc_kr.$(OBJEXT): internal/cast.h
+enc/euc_kr.$(OBJEXT): internal/compiler_is.h
+enc/euc_kr.$(OBJEXT): internal/compiler_is/apple.h
+enc/euc_kr.$(OBJEXT): internal/compiler_is/clang.h
+enc/euc_kr.$(OBJEXT): internal/compiler_is/gcc.h
+enc/euc_kr.$(OBJEXT): internal/compiler_is/intel.h
+enc/euc_kr.$(OBJEXT): internal/compiler_is/msvc.h
+enc/euc_kr.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/euc_kr.$(OBJEXT): internal/compiler_since.h
+enc/euc_kr.$(OBJEXT): internal/config.h
+enc/euc_kr.$(OBJEXT): internal/dllexport.h
+enc/euc_kr.$(OBJEXT): internal/dosish.h
+enc/euc_kr.$(OBJEXT): internal/has/attribute.h
+enc/euc_kr.$(OBJEXT): internal/has/builtin.h
+enc/euc_kr.$(OBJEXT): internal/has/c_attribute.h
+enc/euc_kr.$(OBJEXT): internal/has/cpp_attribute.h
+enc/euc_kr.$(OBJEXT): internal/has/declspec_attribute.h
+enc/euc_kr.$(OBJEXT): internal/has/extension.h
+enc/euc_kr.$(OBJEXT): internal/has/feature.h
+enc/euc_kr.$(OBJEXT): internal/has/warning.h
+enc/euc_kr.$(OBJEXT): internal/stdalign.h
+enc/euc_kr.$(OBJEXT): internal/stdbool.h
+enc/euc_kr.$(OBJEXT): internal/token_paste.h
+enc/euc_kr.$(OBJEXT): internal/warning_push.h
+enc/euc_kr.$(OBJEXT): internal/xmalloc.h
+enc/euc_kr.$(OBJEXT): assert.h
+enc/euc_kr.$(OBJEXT): backward/2/assume.h
+enc/euc_kr.$(OBJEXT): backward/2/attributes.h
+enc/euc_kr.$(OBJEXT): backward/2/bool.h
+enc/euc_kr.$(OBJEXT): backward/2/gcc_version_since.h
+enc/euc_kr.$(OBJEXT): backward/2/long_long.h
+enc/euc_kr.$(OBJEXT): backward/2/stdalign.h
+enc/euc_kr.$(OBJEXT): backward/2/stdarg.h
enc/euc_kr.$(OBJEXT): config.h
enc/euc_kr.$(OBJEXT): defines.h
enc/euc_kr.$(OBJEXT): enc/euc_kr.c
enc/euc_kr.$(OBJEXT): missing.h
enc/euc_kr.$(OBJEXT): onigmo.h
enc/euc_tw.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/euc_tw.$(OBJEXT): internal/assume.h
+enc/euc_tw.$(OBJEXT): internal/attr/alloc_size.h
+enc/euc_tw.$(OBJEXT): internal/attr/cold.h
+enc/euc_tw.$(OBJEXT): internal/attr/const.h
+enc/euc_tw.$(OBJEXT): internal/attr/deprecated.h
+enc/euc_tw.$(OBJEXT): internal/attr/error.h
+enc/euc_tw.$(OBJEXT): internal/attr/forceinline.h
+enc/euc_tw.$(OBJEXT): internal/attr/format.h
+enc/euc_tw.$(OBJEXT): internal/attr/maybe_unused.h
+enc/euc_tw.$(OBJEXT): internal/attr/nodiscard.h
+enc/euc_tw.$(OBJEXT): internal/attr/noexcept.h
+enc/euc_tw.$(OBJEXT): internal/attr/noinline.h
+enc/euc_tw.$(OBJEXT): internal/attr/nonnull.h
+enc/euc_tw.$(OBJEXT): internal/attr/noreturn.h
+enc/euc_tw.$(OBJEXT): internal/attr/pure.h
+enc/euc_tw.$(OBJEXT): internal/attr/restrict.h
+enc/euc_tw.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/euc_tw.$(OBJEXT): internal/attr/warning.h
+enc/euc_tw.$(OBJEXT): internal/cast.h
+enc/euc_tw.$(OBJEXT): internal/compiler_is.h
+enc/euc_tw.$(OBJEXT): internal/compiler_is/apple.h
+enc/euc_tw.$(OBJEXT): internal/compiler_is/clang.h
+enc/euc_tw.$(OBJEXT): internal/compiler_is/gcc.h
+enc/euc_tw.$(OBJEXT): internal/compiler_is/intel.h
+enc/euc_tw.$(OBJEXT): internal/compiler_is/msvc.h
+enc/euc_tw.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/euc_tw.$(OBJEXT): internal/compiler_since.h
+enc/euc_tw.$(OBJEXT): internal/config.h
+enc/euc_tw.$(OBJEXT): internal/dllexport.h
+enc/euc_tw.$(OBJEXT): internal/dosish.h
+enc/euc_tw.$(OBJEXT): internal/has/attribute.h
+enc/euc_tw.$(OBJEXT): internal/has/builtin.h
+enc/euc_tw.$(OBJEXT): internal/has/c_attribute.h
+enc/euc_tw.$(OBJEXT): internal/has/cpp_attribute.h
+enc/euc_tw.$(OBJEXT): internal/has/declspec_attribute.h
+enc/euc_tw.$(OBJEXT): internal/has/extension.h
+enc/euc_tw.$(OBJEXT): internal/has/feature.h
+enc/euc_tw.$(OBJEXT): internal/has/warning.h
+enc/euc_tw.$(OBJEXT): internal/stdalign.h
+enc/euc_tw.$(OBJEXT): internal/stdbool.h
+enc/euc_tw.$(OBJEXT): internal/token_paste.h
+enc/euc_tw.$(OBJEXT): internal/warning_push.h
+enc/euc_tw.$(OBJEXT): internal/xmalloc.h
+enc/euc_tw.$(OBJEXT): assert.h
+enc/euc_tw.$(OBJEXT): backward/2/assume.h
+enc/euc_tw.$(OBJEXT): backward/2/attributes.h
+enc/euc_tw.$(OBJEXT): backward/2/bool.h
+enc/euc_tw.$(OBJEXT): backward/2/gcc_version_since.h
+enc/euc_tw.$(OBJEXT): backward/2/long_long.h
+enc/euc_tw.$(OBJEXT): backward/2/stdalign.h
+enc/euc_tw.$(OBJEXT): backward/2/stdarg.h
enc/euc_tw.$(OBJEXT): config.h
enc/euc_tw.$(OBJEXT): defines.h
enc/euc_tw.$(OBJEXT): enc/euc_tw.c
enc/euc_tw.$(OBJEXT): missing.h
enc/euc_tw.$(OBJEXT): onigmo.h
enc/gb18030.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/gb18030.$(OBJEXT): internal/assume.h
+enc/gb18030.$(OBJEXT): internal/attr/alloc_size.h
+enc/gb18030.$(OBJEXT): internal/attr/cold.h
+enc/gb18030.$(OBJEXT): internal/attr/const.h
+enc/gb18030.$(OBJEXT): internal/attr/deprecated.h
+enc/gb18030.$(OBJEXT): internal/attr/error.h
+enc/gb18030.$(OBJEXT): internal/attr/forceinline.h
+enc/gb18030.$(OBJEXT): internal/attr/format.h
+enc/gb18030.$(OBJEXT): internal/attr/maybe_unused.h
+enc/gb18030.$(OBJEXT): internal/attr/nodiscard.h
+enc/gb18030.$(OBJEXT): internal/attr/noexcept.h
+enc/gb18030.$(OBJEXT): internal/attr/noinline.h
+enc/gb18030.$(OBJEXT): internal/attr/nonnull.h
+enc/gb18030.$(OBJEXT): internal/attr/noreturn.h
+enc/gb18030.$(OBJEXT): internal/attr/pure.h
+enc/gb18030.$(OBJEXT): internal/attr/restrict.h
+enc/gb18030.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/gb18030.$(OBJEXT): internal/attr/warning.h
+enc/gb18030.$(OBJEXT): internal/cast.h
+enc/gb18030.$(OBJEXT): internal/compiler_is.h
+enc/gb18030.$(OBJEXT): internal/compiler_is/apple.h
+enc/gb18030.$(OBJEXT): internal/compiler_is/clang.h
+enc/gb18030.$(OBJEXT): internal/compiler_is/gcc.h
+enc/gb18030.$(OBJEXT): internal/compiler_is/intel.h
+enc/gb18030.$(OBJEXT): internal/compiler_is/msvc.h
+enc/gb18030.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/gb18030.$(OBJEXT): internal/compiler_since.h
+enc/gb18030.$(OBJEXT): internal/config.h
+enc/gb18030.$(OBJEXT): internal/dllexport.h
+enc/gb18030.$(OBJEXT): internal/dosish.h
+enc/gb18030.$(OBJEXT): internal/has/attribute.h
+enc/gb18030.$(OBJEXT): internal/has/builtin.h
+enc/gb18030.$(OBJEXT): internal/has/c_attribute.h
+enc/gb18030.$(OBJEXT): internal/has/cpp_attribute.h
+enc/gb18030.$(OBJEXT): internal/has/declspec_attribute.h
+enc/gb18030.$(OBJEXT): internal/has/extension.h
+enc/gb18030.$(OBJEXT): internal/has/feature.h
+enc/gb18030.$(OBJEXT): internal/has/warning.h
+enc/gb18030.$(OBJEXT): internal/stdalign.h
+enc/gb18030.$(OBJEXT): internal/stdbool.h
+enc/gb18030.$(OBJEXT): internal/token_paste.h
+enc/gb18030.$(OBJEXT): internal/warning_push.h
+enc/gb18030.$(OBJEXT): internal/xmalloc.h
+enc/gb18030.$(OBJEXT): assert.h
+enc/gb18030.$(OBJEXT): backward/2/assume.h
+enc/gb18030.$(OBJEXT): backward/2/attributes.h
+enc/gb18030.$(OBJEXT): backward/2/bool.h
+enc/gb18030.$(OBJEXT): backward/2/gcc_version_since.h
+enc/gb18030.$(OBJEXT): backward/2/long_long.h
+enc/gb18030.$(OBJEXT): backward/2/stdalign.h
+enc/gb18030.$(OBJEXT): backward/2/stdarg.h
enc/gb18030.$(OBJEXT): config.h
enc/gb18030.$(OBJEXT): defines.h
enc/gb18030.$(OBJEXT): enc/gb18030.c
enc/gb18030.$(OBJEXT): missing.h
enc/gb18030.$(OBJEXT): onigmo.h
enc/gb2312.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/gb2312.$(OBJEXT): internal/assume.h
+enc/gb2312.$(OBJEXT): internal/attr/alloc_size.h
+enc/gb2312.$(OBJEXT): internal/attr/cold.h
+enc/gb2312.$(OBJEXT): internal/attr/const.h
+enc/gb2312.$(OBJEXT): internal/attr/deprecated.h
+enc/gb2312.$(OBJEXT): internal/attr/error.h
+enc/gb2312.$(OBJEXT): internal/attr/forceinline.h
+enc/gb2312.$(OBJEXT): internal/attr/format.h
+enc/gb2312.$(OBJEXT): internal/attr/maybe_unused.h
+enc/gb2312.$(OBJEXT): internal/attr/nodiscard.h
+enc/gb2312.$(OBJEXT): internal/attr/noexcept.h
+enc/gb2312.$(OBJEXT): internal/attr/noinline.h
+enc/gb2312.$(OBJEXT): internal/attr/nonnull.h
+enc/gb2312.$(OBJEXT): internal/attr/noreturn.h
+enc/gb2312.$(OBJEXT): internal/attr/pure.h
+enc/gb2312.$(OBJEXT): internal/attr/restrict.h
+enc/gb2312.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/gb2312.$(OBJEXT): internal/attr/warning.h
+enc/gb2312.$(OBJEXT): internal/cast.h
+enc/gb2312.$(OBJEXT): internal/compiler_is.h
+enc/gb2312.$(OBJEXT): internal/compiler_is/apple.h
+enc/gb2312.$(OBJEXT): internal/compiler_is/clang.h
+enc/gb2312.$(OBJEXT): internal/compiler_is/gcc.h
+enc/gb2312.$(OBJEXT): internal/compiler_is/intel.h
+enc/gb2312.$(OBJEXT): internal/compiler_is/msvc.h
+enc/gb2312.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/gb2312.$(OBJEXT): internal/compiler_since.h
+enc/gb2312.$(OBJEXT): internal/config.h
+enc/gb2312.$(OBJEXT): internal/dllexport.h
+enc/gb2312.$(OBJEXT): internal/dosish.h
+enc/gb2312.$(OBJEXT): internal/has/attribute.h
+enc/gb2312.$(OBJEXT): internal/has/builtin.h
+enc/gb2312.$(OBJEXT): internal/has/c_attribute.h
+enc/gb2312.$(OBJEXT): internal/has/cpp_attribute.h
+enc/gb2312.$(OBJEXT): internal/has/declspec_attribute.h
+enc/gb2312.$(OBJEXT): internal/has/extension.h
+enc/gb2312.$(OBJEXT): internal/has/feature.h
+enc/gb2312.$(OBJEXT): internal/has/warning.h
+enc/gb2312.$(OBJEXT): internal/stdalign.h
+enc/gb2312.$(OBJEXT): internal/stdbool.h
+enc/gb2312.$(OBJEXT): internal/token_paste.h
+enc/gb2312.$(OBJEXT): internal/warning_push.h
+enc/gb2312.$(OBJEXT): internal/xmalloc.h
+enc/gb2312.$(OBJEXT): assert.h
+enc/gb2312.$(OBJEXT): backward/2/assume.h
+enc/gb2312.$(OBJEXT): backward/2/attributes.h
+enc/gb2312.$(OBJEXT): backward/2/bool.h
+enc/gb2312.$(OBJEXT): backward/2/gcc_version_since.h
+enc/gb2312.$(OBJEXT): backward/2/long_long.h
+enc/gb2312.$(OBJEXT): backward/2/stdalign.h
+enc/gb2312.$(OBJEXT): backward/2/stdarg.h
enc/gb2312.$(OBJEXT): config.h
enc/gb2312.$(OBJEXT): defines.h
enc/gb2312.$(OBJEXT): enc/gb2312.c
enc/gb2312.$(OBJEXT): missing.h
enc/gb2312.$(OBJEXT): onigmo.h
enc/gbk.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/gbk.$(OBJEXT): internal/assume.h
+enc/gbk.$(OBJEXT): internal/attr/alloc_size.h
+enc/gbk.$(OBJEXT): internal/attr/cold.h
+enc/gbk.$(OBJEXT): internal/attr/const.h
+enc/gbk.$(OBJEXT): internal/attr/deprecated.h
+enc/gbk.$(OBJEXT): internal/attr/error.h
+enc/gbk.$(OBJEXT): internal/attr/forceinline.h
+enc/gbk.$(OBJEXT): internal/attr/format.h
+enc/gbk.$(OBJEXT): internal/attr/maybe_unused.h
+enc/gbk.$(OBJEXT): internal/attr/nodiscard.h
+enc/gbk.$(OBJEXT): internal/attr/noexcept.h
+enc/gbk.$(OBJEXT): internal/attr/noinline.h
+enc/gbk.$(OBJEXT): internal/attr/nonnull.h
+enc/gbk.$(OBJEXT): internal/attr/noreturn.h
+enc/gbk.$(OBJEXT): internal/attr/pure.h
+enc/gbk.$(OBJEXT): internal/attr/restrict.h
+enc/gbk.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/gbk.$(OBJEXT): internal/attr/warning.h
+enc/gbk.$(OBJEXT): internal/cast.h
+enc/gbk.$(OBJEXT): internal/compiler_is.h
+enc/gbk.$(OBJEXT): internal/compiler_is/apple.h
+enc/gbk.$(OBJEXT): internal/compiler_is/clang.h
+enc/gbk.$(OBJEXT): internal/compiler_is/gcc.h
+enc/gbk.$(OBJEXT): internal/compiler_is/intel.h
+enc/gbk.$(OBJEXT): internal/compiler_is/msvc.h
+enc/gbk.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/gbk.$(OBJEXT): internal/compiler_since.h
+enc/gbk.$(OBJEXT): internal/config.h
+enc/gbk.$(OBJEXT): internal/dllexport.h
+enc/gbk.$(OBJEXT): internal/dosish.h
+enc/gbk.$(OBJEXT): internal/has/attribute.h
+enc/gbk.$(OBJEXT): internal/has/builtin.h
+enc/gbk.$(OBJEXT): internal/has/c_attribute.h
+enc/gbk.$(OBJEXT): internal/has/cpp_attribute.h
+enc/gbk.$(OBJEXT): internal/has/declspec_attribute.h
+enc/gbk.$(OBJEXT): internal/has/extension.h
+enc/gbk.$(OBJEXT): internal/has/feature.h
+enc/gbk.$(OBJEXT): internal/has/warning.h
+enc/gbk.$(OBJEXT): internal/stdalign.h
+enc/gbk.$(OBJEXT): internal/stdbool.h
+enc/gbk.$(OBJEXT): internal/token_paste.h
+enc/gbk.$(OBJEXT): internal/warning_push.h
+enc/gbk.$(OBJEXT): internal/xmalloc.h
+enc/gbk.$(OBJEXT): assert.h
+enc/gbk.$(OBJEXT): backward/2/assume.h
+enc/gbk.$(OBJEXT): backward/2/attributes.h
+enc/gbk.$(OBJEXT): backward/2/bool.h
+enc/gbk.$(OBJEXT): backward/2/gcc_version_since.h
+enc/gbk.$(OBJEXT): backward/2/long_long.h
+enc/gbk.$(OBJEXT): backward/2/stdalign.h
+enc/gbk.$(OBJEXT): backward/2/stdarg.h
enc/gbk.$(OBJEXT): config.h
enc/gbk.$(OBJEXT): defines.h
enc/gbk.$(OBJEXT): enc/gbk.c
enc/gbk.$(OBJEXT): missing.h
enc/gbk.$(OBJEXT): onigmo.h
enc/iso_8859_1.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_1.$(OBJEXT): internal/assume.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_1.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_1.$(OBJEXT): internal/cast.h
+enc/iso_8859_1.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_1.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_1.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_1.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_1.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_1.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_1.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_1.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_1.$(OBJEXT): internal/config.h
+enc/iso_8859_1.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_1.$(OBJEXT): internal/dosish.h
+enc/iso_8859_1.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_1.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_1.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_1.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_1.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_1.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_1.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_1.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_1.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_1.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_1.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_1.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_1.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_1.$(OBJEXT): assert.h
+enc/iso_8859_1.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_1.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_1.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_1.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_1.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_1.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_1.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_1.$(OBJEXT): config.h
enc/iso_8859_1.$(OBJEXT): defines.h
enc/iso_8859_1.$(OBJEXT): enc/iso_8859.h
@@ -269,6 +1245,57 @@ enc/iso_8859_1.$(OBJEXT): enc/iso_8859_1.c
enc/iso_8859_1.$(OBJEXT): missing.h
enc/iso_8859_1.$(OBJEXT): onigmo.h
enc/iso_8859_10.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_10.$(OBJEXT): internal/assume.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_10.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_10.$(OBJEXT): internal/cast.h
+enc/iso_8859_10.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_10.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_10.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_10.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_10.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_10.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_10.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_10.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_10.$(OBJEXT): internal/config.h
+enc/iso_8859_10.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_10.$(OBJEXT): internal/dosish.h
+enc/iso_8859_10.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_10.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_10.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_10.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_10.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_10.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_10.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_10.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_10.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_10.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_10.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_10.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_10.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_10.$(OBJEXT): assert.h
+enc/iso_8859_10.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_10.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_10.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_10.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_10.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_10.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_10.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_10.$(OBJEXT): config.h
enc/iso_8859_10.$(OBJEXT): defines.h
enc/iso_8859_10.$(OBJEXT): enc/iso_8859.h
@@ -276,12 +1303,114 @@ enc/iso_8859_10.$(OBJEXT): enc/iso_8859_10.c
enc/iso_8859_10.$(OBJEXT): missing.h
enc/iso_8859_10.$(OBJEXT): onigmo.h
enc/iso_8859_11.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_11.$(OBJEXT): internal/assume.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_11.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_11.$(OBJEXT): internal/cast.h
+enc/iso_8859_11.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_11.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_11.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_11.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_11.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_11.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_11.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_11.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_11.$(OBJEXT): internal/config.h
+enc/iso_8859_11.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_11.$(OBJEXT): internal/dosish.h
+enc/iso_8859_11.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_11.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_11.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_11.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_11.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_11.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_11.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_11.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_11.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_11.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_11.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_11.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_11.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_11.$(OBJEXT): assert.h
+enc/iso_8859_11.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_11.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_11.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_11.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_11.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_11.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_11.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_11.$(OBJEXT): config.h
enc/iso_8859_11.$(OBJEXT): defines.h
enc/iso_8859_11.$(OBJEXT): enc/iso_8859_11.c
enc/iso_8859_11.$(OBJEXT): missing.h
enc/iso_8859_11.$(OBJEXT): onigmo.h
enc/iso_8859_13.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_13.$(OBJEXT): internal/assume.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_13.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_13.$(OBJEXT): internal/cast.h
+enc/iso_8859_13.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_13.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_13.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_13.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_13.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_13.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_13.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_13.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_13.$(OBJEXT): internal/config.h
+enc/iso_8859_13.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_13.$(OBJEXT): internal/dosish.h
+enc/iso_8859_13.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_13.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_13.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_13.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_13.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_13.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_13.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_13.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_13.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_13.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_13.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_13.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_13.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_13.$(OBJEXT): assert.h
+enc/iso_8859_13.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_13.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_13.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_13.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_13.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_13.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_13.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_13.$(OBJEXT): config.h
enc/iso_8859_13.$(OBJEXT): defines.h
enc/iso_8859_13.$(OBJEXT): enc/iso_8859.h
@@ -289,6 +1418,57 @@ enc/iso_8859_13.$(OBJEXT): enc/iso_8859_13.c
enc/iso_8859_13.$(OBJEXT): missing.h
enc/iso_8859_13.$(OBJEXT): onigmo.h
enc/iso_8859_14.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_14.$(OBJEXT): internal/assume.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_14.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_14.$(OBJEXT): internal/cast.h
+enc/iso_8859_14.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_14.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_14.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_14.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_14.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_14.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_14.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_14.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_14.$(OBJEXT): internal/config.h
+enc/iso_8859_14.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_14.$(OBJEXT): internal/dosish.h
+enc/iso_8859_14.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_14.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_14.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_14.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_14.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_14.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_14.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_14.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_14.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_14.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_14.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_14.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_14.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_14.$(OBJEXT): assert.h
+enc/iso_8859_14.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_14.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_14.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_14.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_14.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_14.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_14.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_14.$(OBJEXT): config.h
enc/iso_8859_14.$(OBJEXT): defines.h
enc/iso_8859_14.$(OBJEXT): enc/iso_8859.h
@@ -296,6 +1476,57 @@ enc/iso_8859_14.$(OBJEXT): enc/iso_8859_14.c
enc/iso_8859_14.$(OBJEXT): missing.h
enc/iso_8859_14.$(OBJEXT): onigmo.h
enc/iso_8859_15.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_15.$(OBJEXT): internal/assume.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_15.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_15.$(OBJEXT): internal/cast.h
+enc/iso_8859_15.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_15.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_15.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_15.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_15.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_15.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_15.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_15.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_15.$(OBJEXT): internal/config.h
+enc/iso_8859_15.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_15.$(OBJEXT): internal/dosish.h
+enc/iso_8859_15.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_15.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_15.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_15.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_15.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_15.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_15.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_15.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_15.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_15.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_15.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_15.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_15.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_15.$(OBJEXT): assert.h
+enc/iso_8859_15.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_15.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_15.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_15.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_15.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_15.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_15.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_15.$(OBJEXT): config.h
enc/iso_8859_15.$(OBJEXT): defines.h
enc/iso_8859_15.$(OBJEXT): enc/iso_8859.h
@@ -303,6 +1534,57 @@ enc/iso_8859_15.$(OBJEXT): enc/iso_8859_15.c
enc/iso_8859_15.$(OBJEXT): missing.h
enc/iso_8859_15.$(OBJEXT): onigmo.h
enc/iso_8859_16.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_16.$(OBJEXT): internal/assume.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_16.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_16.$(OBJEXT): internal/cast.h
+enc/iso_8859_16.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_16.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_16.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_16.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_16.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_16.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_16.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_16.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_16.$(OBJEXT): internal/config.h
+enc/iso_8859_16.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_16.$(OBJEXT): internal/dosish.h
+enc/iso_8859_16.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_16.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_16.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_16.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_16.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_16.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_16.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_16.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_16.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_16.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_16.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_16.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_16.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_16.$(OBJEXT): assert.h
+enc/iso_8859_16.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_16.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_16.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_16.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_16.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_16.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_16.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_16.$(OBJEXT): config.h
enc/iso_8859_16.$(OBJEXT): defines.h
enc/iso_8859_16.$(OBJEXT): enc/iso_8859.h
@@ -310,6 +1592,57 @@ enc/iso_8859_16.$(OBJEXT): enc/iso_8859_16.c
enc/iso_8859_16.$(OBJEXT): missing.h
enc/iso_8859_16.$(OBJEXT): onigmo.h
enc/iso_8859_2.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_2.$(OBJEXT): internal/assume.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_2.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_2.$(OBJEXT): internal/cast.h
+enc/iso_8859_2.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_2.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_2.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_2.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_2.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_2.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_2.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_2.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_2.$(OBJEXT): internal/config.h
+enc/iso_8859_2.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_2.$(OBJEXT): internal/dosish.h
+enc/iso_8859_2.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_2.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_2.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_2.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_2.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_2.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_2.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_2.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_2.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_2.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_2.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_2.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_2.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_2.$(OBJEXT): assert.h
+enc/iso_8859_2.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_2.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_2.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_2.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_2.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_2.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_2.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_2.$(OBJEXT): config.h
enc/iso_8859_2.$(OBJEXT): defines.h
enc/iso_8859_2.$(OBJEXT): enc/iso_8859.h
@@ -317,6 +1650,57 @@ enc/iso_8859_2.$(OBJEXT): enc/iso_8859_2.c
enc/iso_8859_2.$(OBJEXT): missing.h
enc/iso_8859_2.$(OBJEXT): onigmo.h
enc/iso_8859_3.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_3.$(OBJEXT): internal/assume.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_3.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_3.$(OBJEXT): internal/cast.h
+enc/iso_8859_3.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_3.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_3.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_3.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_3.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_3.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_3.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_3.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_3.$(OBJEXT): internal/config.h
+enc/iso_8859_3.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_3.$(OBJEXT): internal/dosish.h
+enc/iso_8859_3.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_3.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_3.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_3.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_3.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_3.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_3.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_3.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_3.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_3.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_3.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_3.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_3.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_3.$(OBJEXT): assert.h
+enc/iso_8859_3.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_3.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_3.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_3.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_3.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_3.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_3.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_3.$(OBJEXT): config.h
enc/iso_8859_3.$(OBJEXT): defines.h
enc/iso_8859_3.$(OBJEXT): enc/iso_8859.h
@@ -324,6 +1708,57 @@ enc/iso_8859_3.$(OBJEXT): enc/iso_8859_3.c
enc/iso_8859_3.$(OBJEXT): missing.h
enc/iso_8859_3.$(OBJEXT): onigmo.h
enc/iso_8859_4.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_4.$(OBJEXT): internal/assume.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_4.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_4.$(OBJEXT): internal/cast.h
+enc/iso_8859_4.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_4.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_4.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_4.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_4.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_4.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_4.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_4.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_4.$(OBJEXT): internal/config.h
+enc/iso_8859_4.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_4.$(OBJEXT): internal/dosish.h
+enc/iso_8859_4.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_4.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_4.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_4.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_4.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_4.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_4.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_4.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_4.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_4.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_4.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_4.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_4.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_4.$(OBJEXT): assert.h
+enc/iso_8859_4.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_4.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_4.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_4.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_4.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_4.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_4.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_4.$(OBJEXT): config.h
enc/iso_8859_4.$(OBJEXT): defines.h
enc/iso_8859_4.$(OBJEXT): enc/iso_8859.h
@@ -331,30 +1766,285 @@ enc/iso_8859_4.$(OBJEXT): enc/iso_8859_4.c
enc/iso_8859_4.$(OBJEXT): missing.h
enc/iso_8859_4.$(OBJEXT): onigmo.h
enc/iso_8859_5.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_5.$(OBJEXT): internal/assume.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_5.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_5.$(OBJEXT): internal/cast.h
+enc/iso_8859_5.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_5.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_5.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_5.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_5.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_5.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_5.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_5.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_5.$(OBJEXT): internal/config.h
+enc/iso_8859_5.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_5.$(OBJEXT): internal/dosish.h
+enc/iso_8859_5.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_5.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_5.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_5.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_5.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_5.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_5.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_5.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_5.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_5.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_5.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_5.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_5.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_5.$(OBJEXT): assert.h
+enc/iso_8859_5.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_5.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_5.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_5.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_5.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_5.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_5.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_5.$(OBJEXT): config.h
enc/iso_8859_5.$(OBJEXT): defines.h
enc/iso_8859_5.$(OBJEXT): enc/iso_8859_5.c
enc/iso_8859_5.$(OBJEXT): missing.h
enc/iso_8859_5.$(OBJEXT): onigmo.h
enc/iso_8859_6.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_6.$(OBJEXT): internal/assume.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_6.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_6.$(OBJEXT): internal/cast.h
+enc/iso_8859_6.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_6.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_6.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_6.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_6.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_6.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_6.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_6.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_6.$(OBJEXT): internal/config.h
+enc/iso_8859_6.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_6.$(OBJEXT): internal/dosish.h
+enc/iso_8859_6.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_6.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_6.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_6.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_6.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_6.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_6.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_6.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_6.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_6.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_6.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_6.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_6.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_6.$(OBJEXT): assert.h
+enc/iso_8859_6.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_6.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_6.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_6.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_6.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_6.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_6.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_6.$(OBJEXT): config.h
enc/iso_8859_6.$(OBJEXT): defines.h
enc/iso_8859_6.$(OBJEXT): enc/iso_8859_6.c
enc/iso_8859_6.$(OBJEXT): missing.h
enc/iso_8859_6.$(OBJEXT): onigmo.h
enc/iso_8859_7.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_7.$(OBJEXT): internal/assume.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_7.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_7.$(OBJEXT): internal/cast.h
+enc/iso_8859_7.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_7.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_7.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_7.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_7.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_7.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_7.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_7.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_7.$(OBJEXT): internal/config.h
+enc/iso_8859_7.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_7.$(OBJEXT): internal/dosish.h
+enc/iso_8859_7.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_7.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_7.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_7.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_7.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_7.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_7.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_7.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_7.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_7.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_7.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_7.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_7.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_7.$(OBJEXT): assert.h
+enc/iso_8859_7.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_7.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_7.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_7.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_7.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_7.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_7.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_7.$(OBJEXT): config.h
enc/iso_8859_7.$(OBJEXT): defines.h
enc/iso_8859_7.$(OBJEXT): enc/iso_8859_7.c
enc/iso_8859_7.$(OBJEXT): missing.h
enc/iso_8859_7.$(OBJEXT): onigmo.h
enc/iso_8859_8.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_8.$(OBJEXT): internal/assume.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_8.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_8.$(OBJEXT): internal/cast.h
+enc/iso_8859_8.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_8.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_8.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_8.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_8.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_8.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_8.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_8.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_8.$(OBJEXT): internal/config.h
+enc/iso_8859_8.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_8.$(OBJEXT): internal/dosish.h
+enc/iso_8859_8.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_8.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_8.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_8.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_8.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_8.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_8.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_8.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_8.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_8.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_8.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_8.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_8.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_8.$(OBJEXT): assert.h
+enc/iso_8859_8.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_8.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_8.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_8.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_8.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_8.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_8.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_8.$(OBJEXT): config.h
enc/iso_8859_8.$(OBJEXT): defines.h
enc/iso_8859_8.$(OBJEXT): enc/iso_8859_8.c
enc/iso_8859_8.$(OBJEXT): missing.h
enc/iso_8859_8.$(OBJEXT): onigmo.h
enc/iso_8859_9.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/iso_8859_9.$(OBJEXT): internal/assume.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/alloc_size.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/cold.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/const.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/deprecated.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/error.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/forceinline.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/format.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/maybe_unused.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/nodiscard.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/noexcept.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/noinline.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/nonnull.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/noreturn.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/pure.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/restrict.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/iso_8859_9.$(OBJEXT): internal/attr/warning.h
+enc/iso_8859_9.$(OBJEXT): internal/cast.h
+enc/iso_8859_9.$(OBJEXT): internal/compiler_is.h
+enc/iso_8859_9.$(OBJEXT): internal/compiler_is/apple.h
+enc/iso_8859_9.$(OBJEXT): internal/compiler_is/clang.h
+enc/iso_8859_9.$(OBJEXT): internal/compiler_is/gcc.h
+enc/iso_8859_9.$(OBJEXT): internal/compiler_is/intel.h
+enc/iso_8859_9.$(OBJEXT): internal/compiler_is/msvc.h
+enc/iso_8859_9.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/iso_8859_9.$(OBJEXT): internal/compiler_since.h
+enc/iso_8859_9.$(OBJEXT): internal/config.h
+enc/iso_8859_9.$(OBJEXT): internal/dllexport.h
+enc/iso_8859_9.$(OBJEXT): internal/dosish.h
+enc/iso_8859_9.$(OBJEXT): internal/has/attribute.h
+enc/iso_8859_9.$(OBJEXT): internal/has/builtin.h
+enc/iso_8859_9.$(OBJEXT): internal/has/c_attribute.h
+enc/iso_8859_9.$(OBJEXT): internal/has/cpp_attribute.h
+enc/iso_8859_9.$(OBJEXT): internal/has/declspec_attribute.h
+enc/iso_8859_9.$(OBJEXT): internal/has/extension.h
+enc/iso_8859_9.$(OBJEXT): internal/has/feature.h
+enc/iso_8859_9.$(OBJEXT): internal/has/warning.h
+enc/iso_8859_9.$(OBJEXT): internal/stdalign.h
+enc/iso_8859_9.$(OBJEXT): internal/stdbool.h
+enc/iso_8859_9.$(OBJEXT): internal/token_paste.h
+enc/iso_8859_9.$(OBJEXT): internal/warning_push.h
+enc/iso_8859_9.$(OBJEXT): internal/xmalloc.h
+enc/iso_8859_9.$(OBJEXT): assert.h
+enc/iso_8859_9.$(OBJEXT): backward/2/assume.h
+enc/iso_8859_9.$(OBJEXT): backward/2/attributes.h
+enc/iso_8859_9.$(OBJEXT): backward/2/bool.h
+enc/iso_8859_9.$(OBJEXT): backward/2/gcc_version_since.h
+enc/iso_8859_9.$(OBJEXT): backward/2/long_long.h
+enc/iso_8859_9.$(OBJEXT): backward/2/stdalign.h
+enc/iso_8859_9.$(OBJEXT): backward/2/stdarg.h
enc/iso_8859_9.$(OBJEXT): config.h
enc/iso_8859_9.$(OBJEXT): defines.h
enc/iso_8859_9.$(OBJEXT): enc/iso_8859.h
@@ -362,18 +2052,171 @@ enc/iso_8859_9.$(OBJEXT): enc/iso_8859_9.c
enc/iso_8859_9.$(OBJEXT): missing.h
enc/iso_8859_9.$(OBJEXT): onigmo.h
enc/koi8_r.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/koi8_r.$(OBJEXT): internal/assume.h
+enc/koi8_r.$(OBJEXT): internal/attr/alloc_size.h
+enc/koi8_r.$(OBJEXT): internal/attr/cold.h
+enc/koi8_r.$(OBJEXT): internal/attr/const.h
+enc/koi8_r.$(OBJEXT): internal/attr/deprecated.h
+enc/koi8_r.$(OBJEXT): internal/attr/error.h
+enc/koi8_r.$(OBJEXT): internal/attr/forceinline.h
+enc/koi8_r.$(OBJEXT): internal/attr/format.h
+enc/koi8_r.$(OBJEXT): internal/attr/maybe_unused.h
+enc/koi8_r.$(OBJEXT): internal/attr/nodiscard.h
+enc/koi8_r.$(OBJEXT): internal/attr/noexcept.h
+enc/koi8_r.$(OBJEXT): internal/attr/noinline.h
+enc/koi8_r.$(OBJEXT): internal/attr/nonnull.h
+enc/koi8_r.$(OBJEXT): internal/attr/noreturn.h
+enc/koi8_r.$(OBJEXT): internal/attr/pure.h
+enc/koi8_r.$(OBJEXT): internal/attr/restrict.h
+enc/koi8_r.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/koi8_r.$(OBJEXT): internal/attr/warning.h
+enc/koi8_r.$(OBJEXT): internal/cast.h
+enc/koi8_r.$(OBJEXT): internal/compiler_is.h
+enc/koi8_r.$(OBJEXT): internal/compiler_is/apple.h
+enc/koi8_r.$(OBJEXT): internal/compiler_is/clang.h
+enc/koi8_r.$(OBJEXT): internal/compiler_is/gcc.h
+enc/koi8_r.$(OBJEXT): internal/compiler_is/intel.h
+enc/koi8_r.$(OBJEXT): internal/compiler_is/msvc.h
+enc/koi8_r.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/koi8_r.$(OBJEXT): internal/compiler_since.h
+enc/koi8_r.$(OBJEXT): internal/config.h
+enc/koi8_r.$(OBJEXT): internal/dllexport.h
+enc/koi8_r.$(OBJEXT): internal/dosish.h
+enc/koi8_r.$(OBJEXT): internal/has/attribute.h
+enc/koi8_r.$(OBJEXT): internal/has/builtin.h
+enc/koi8_r.$(OBJEXT): internal/has/c_attribute.h
+enc/koi8_r.$(OBJEXT): internal/has/cpp_attribute.h
+enc/koi8_r.$(OBJEXT): internal/has/declspec_attribute.h
+enc/koi8_r.$(OBJEXT): internal/has/extension.h
+enc/koi8_r.$(OBJEXT): internal/has/feature.h
+enc/koi8_r.$(OBJEXT): internal/has/warning.h
+enc/koi8_r.$(OBJEXT): internal/stdalign.h
+enc/koi8_r.$(OBJEXT): internal/stdbool.h
+enc/koi8_r.$(OBJEXT): internal/token_paste.h
+enc/koi8_r.$(OBJEXT): internal/warning_push.h
+enc/koi8_r.$(OBJEXT): internal/xmalloc.h
+enc/koi8_r.$(OBJEXT): assert.h
+enc/koi8_r.$(OBJEXT): backward/2/assume.h
+enc/koi8_r.$(OBJEXT): backward/2/attributes.h
+enc/koi8_r.$(OBJEXT): backward/2/bool.h
+enc/koi8_r.$(OBJEXT): backward/2/gcc_version_since.h
+enc/koi8_r.$(OBJEXT): backward/2/long_long.h
+enc/koi8_r.$(OBJEXT): backward/2/stdalign.h
+enc/koi8_r.$(OBJEXT): backward/2/stdarg.h
enc/koi8_r.$(OBJEXT): config.h
enc/koi8_r.$(OBJEXT): defines.h
enc/koi8_r.$(OBJEXT): enc/koi8_r.c
enc/koi8_r.$(OBJEXT): missing.h
enc/koi8_r.$(OBJEXT): onigmo.h
enc/koi8_u.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/koi8_u.$(OBJEXT): internal/assume.h
+enc/koi8_u.$(OBJEXT): internal/attr/alloc_size.h
+enc/koi8_u.$(OBJEXT): internal/attr/cold.h
+enc/koi8_u.$(OBJEXT): internal/attr/const.h
+enc/koi8_u.$(OBJEXT): internal/attr/deprecated.h
+enc/koi8_u.$(OBJEXT): internal/attr/error.h
+enc/koi8_u.$(OBJEXT): internal/attr/forceinline.h
+enc/koi8_u.$(OBJEXT): internal/attr/format.h
+enc/koi8_u.$(OBJEXT): internal/attr/maybe_unused.h
+enc/koi8_u.$(OBJEXT): internal/attr/nodiscard.h
+enc/koi8_u.$(OBJEXT): internal/attr/noexcept.h
+enc/koi8_u.$(OBJEXT): internal/attr/noinline.h
+enc/koi8_u.$(OBJEXT): internal/attr/nonnull.h
+enc/koi8_u.$(OBJEXT): internal/attr/noreturn.h
+enc/koi8_u.$(OBJEXT): internal/attr/pure.h
+enc/koi8_u.$(OBJEXT): internal/attr/restrict.h
+enc/koi8_u.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/koi8_u.$(OBJEXT): internal/attr/warning.h
+enc/koi8_u.$(OBJEXT): internal/cast.h
+enc/koi8_u.$(OBJEXT): internal/compiler_is.h
+enc/koi8_u.$(OBJEXT): internal/compiler_is/apple.h
+enc/koi8_u.$(OBJEXT): internal/compiler_is/clang.h
+enc/koi8_u.$(OBJEXT): internal/compiler_is/gcc.h
+enc/koi8_u.$(OBJEXT): internal/compiler_is/intel.h
+enc/koi8_u.$(OBJEXT): internal/compiler_is/msvc.h
+enc/koi8_u.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/koi8_u.$(OBJEXT): internal/compiler_since.h
+enc/koi8_u.$(OBJEXT): internal/config.h
+enc/koi8_u.$(OBJEXT): internal/dllexport.h
+enc/koi8_u.$(OBJEXT): internal/dosish.h
+enc/koi8_u.$(OBJEXT): internal/has/attribute.h
+enc/koi8_u.$(OBJEXT): internal/has/builtin.h
+enc/koi8_u.$(OBJEXT): internal/has/c_attribute.h
+enc/koi8_u.$(OBJEXT): internal/has/cpp_attribute.h
+enc/koi8_u.$(OBJEXT): internal/has/declspec_attribute.h
+enc/koi8_u.$(OBJEXT): internal/has/extension.h
+enc/koi8_u.$(OBJEXT): internal/has/feature.h
+enc/koi8_u.$(OBJEXT): internal/has/warning.h
+enc/koi8_u.$(OBJEXT): internal/stdalign.h
+enc/koi8_u.$(OBJEXT): internal/stdbool.h
+enc/koi8_u.$(OBJEXT): internal/token_paste.h
+enc/koi8_u.$(OBJEXT): internal/warning_push.h
+enc/koi8_u.$(OBJEXT): internal/xmalloc.h
+enc/koi8_u.$(OBJEXT): assert.h
+enc/koi8_u.$(OBJEXT): backward/2/assume.h
+enc/koi8_u.$(OBJEXT): backward/2/attributes.h
+enc/koi8_u.$(OBJEXT): backward/2/bool.h
+enc/koi8_u.$(OBJEXT): backward/2/gcc_version_since.h
+enc/koi8_u.$(OBJEXT): backward/2/long_long.h
+enc/koi8_u.$(OBJEXT): backward/2/stdalign.h
+enc/koi8_u.$(OBJEXT): backward/2/stdarg.h
enc/koi8_u.$(OBJEXT): config.h
enc/koi8_u.$(OBJEXT): defines.h
enc/koi8_u.$(OBJEXT): enc/koi8_u.c
enc/koi8_u.$(OBJEXT): missing.h
enc/koi8_u.$(OBJEXT): onigmo.h
enc/shift_jis.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/shift_jis.$(OBJEXT): internal/assume.h
+enc/shift_jis.$(OBJEXT): internal/attr/alloc_size.h
+enc/shift_jis.$(OBJEXT): internal/attr/cold.h
+enc/shift_jis.$(OBJEXT): internal/attr/const.h
+enc/shift_jis.$(OBJEXT): internal/attr/deprecated.h
+enc/shift_jis.$(OBJEXT): internal/attr/error.h
+enc/shift_jis.$(OBJEXT): internal/attr/forceinline.h
+enc/shift_jis.$(OBJEXT): internal/attr/format.h
+enc/shift_jis.$(OBJEXT): internal/attr/maybe_unused.h
+enc/shift_jis.$(OBJEXT): internal/attr/nodiscard.h
+enc/shift_jis.$(OBJEXT): internal/attr/noexcept.h
+enc/shift_jis.$(OBJEXT): internal/attr/noinline.h
+enc/shift_jis.$(OBJEXT): internal/attr/nonnull.h
+enc/shift_jis.$(OBJEXT): internal/attr/noreturn.h
+enc/shift_jis.$(OBJEXT): internal/attr/pure.h
+enc/shift_jis.$(OBJEXT): internal/attr/restrict.h
+enc/shift_jis.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/shift_jis.$(OBJEXT): internal/attr/warning.h
+enc/shift_jis.$(OBJEXT): internal/cast.h
+enc/shift_jis.$(OBJEXT): internal/compiler_is.h
+enc/shift_jis.$(OBJEXT): internal/compiler_is/apple.h
+enc/shift_jis.$(OBJEXT): internal/compiler_is/clang.h
+enc/shift_jis.$(OBJEXT): internal/compiler_is/gcc.h
+enc/shift_jis.$(OBJEXT): internal/compiler_is/intel.h
+enc/shift_jis.$(OBJEXT): internal/compiler_is/msvc.h
+enc/shift_jis.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/shift_jis.$(OBJEXT): internal/compiler_since.h
+enc/shift_jis.$(OBJEXT): internal/config.h
+enc/shift_jis.$(OBJEXT): internal/dllexport.h
+enc/shift_jis.$(OBJEXT): internal/dosish.h
+enc/shift_jis.$(OBJEXT): internal/has/attribute.h
+enc/shift_jis.$(OBJEXT): internal/has/builtin.h
+enc/shift_jis.$(OBJEXT): internal/has/c_attribute.h
+enc/shift_jis.$(OBJEXT): internal/has/cpp_attribute.h
+enc/shift_jis.$(OBJEXT): internal/has/declspec_attribute.h
+enc/shift_jis.$(OBJEXT): internal/has/extension.h
+enc/shift_jis.$(OBJEXT): internal/has/feature.h
+enc/shift_jis.$(OBJEXT): internal/has/warning.h
+enc/shift_jis.$(OBJEXT): internal/stdalign.h
+enc/shift_jis.$(OBJEXT): internal/stdbool.h
+enc/shift_jis.$(OBJEXT): internal/token_paste.h
+enc/shift_jis.$(OBJEXT): internal/warning_push.h
+enc/shift_jis.$(OBJEXT): internal/xmalloc.h
+enc/shift_jis.$(OBJEXT): assert.h
+enc/shift_jis.$(OBJEXT): backward/2/assume.h
+enc/shift_jis.$(OBJEXT): backward/2/attributes.h
+enc/shift_jis.$(OBJEXT): backward/2/bool.h
+enc/shift_jis.$(OBJEXT): backward/2/gcc_version_since.h
+enc/shift_jis.$(OBJEXT): backward/2/long_long.h
+enc/shift_jis.$(OBJEXT): backward/2/stdalign.h
+enc/shift_jis.$(OBJEXT): backward/2/stdarg.h
enc/shift_jis.$(OBJEXT): config.h
enc/shift_jis.$(OBJEXT): defines.h
enc/shift_jis.$(OBJEXT): enc/jis/props.h
@@ -384,8 +2227,157 @@ enc/shift_jis.$(OBJEXT): missing.h
enc/shift_jis.$(OBJEXT): onigmo.h
enc/trans/big5.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/big5.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/big5.$(OBJEXT): internal/anyargs.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/big5.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/big5.$(OBJEXT): internal/assume.h
+enc/trans/big5.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/big5.$(OBJEXT): internal/attr/artificial.h
+enc/trans/big5.$(OBJEXT): internal/attr/cold.h
+enc/trans/big5.$(OBJEXT): internal/attr/const.h
+enc/trans/big5.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/big5.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/big5.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/big5.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/big5.$(OBJEXT): internal/attr/error.h
+enc/trans/big5.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/big5.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/big5.$(OBJEXT): internal/attr/format.h
+enc/trans/big5.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/big5.$(OBJEXT): internal/attr/noalias.h
+enc/trans/big5.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/big5.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/big5.$(OBJEXT): internal/attr/noinline.h
+enc/trans/big5.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/big5.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/big5.$(OBJEXT): internal/attr/pure.h
+enc/trans/big5.$(OBJEXT): internal/attr/restrict.h
+enc/trans/big5.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/big5.$(OBJEXT): internal/attr/warning.h
+enc/trans/big5.$(OBJEXT): internal/attr/weakref.h
+enc/trans/big5.$(OBJEXT): internal/cast.h
+enc/trans/big5.$(OBJEXT): internal/compiler_is.h
+enc/trans/big5.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/big5.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/big5.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/big5.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/big5.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/big5.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/big5.$(OBJEXT): internal/compiler_since.h
+enc/trans/big5.$(OBJEXT): internal/config.h
+enc/trans/big5.$(OBJEXT): internal/constant_p.h
+enc/trans/big5.$(OBJEXT): internal/core.h
+enc/trans/big5.$(OBJEXT): internal/core/rarray.h
+enc/trans/big5.$(OBJEXT): internal/core/rbasic.h
+enc/trans/big5.$(OBJEXT): internal/core/rbignum.h
+enc/trans/big5.$(OBJEXT): internal/core/rclass.h
+enc/trans/big5.$(OBJEXT): internal/core/rdata.h
+enc/trans/big5.$(OBJEXT): internal/core/rfile.h
+enc/trans/big5.$(OBJEXT): internal/core/rhash.h
+enc/trans/big5.$(OBJEXT): internal/core/robject.h
+enc/trans/big5.$(OBJEXT): internal/core/rregexp.h
+enc/trans/big5.$(OBJEXT): internal/core/rstring.h
+enc/trans/big5.$(OBJEXT): internal/core/rstruct.h
+enc/trans/big5.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/big5.$(OBJEXT): internal/ctype.h
+enc/trans/big5.$(OBJEXT): internal/dllexport.h
+enc/trans/big5.$(OBJEXT): internal/dosish.h
+enc/trans/big5.$(OBJEXT): internal/error.h
+enc/trans/big5.$(OBJEXT): internal/eval.h
+enc/trans/big5.$(OBJEXT): internal/event.h
+enc/trans/big5.$(OBJEXT): internal/fl_type.h
+enc/trans/big5.$(OBJEXT): internal/gc.h
+enc/trans/big5.$(OBJEXT): internal/glob.h
+enc/trans/big5.$(OBJEXT): internal/globals.h
+enc/trans/big5.$(OBJEXT): internal/has/attribute.h
+enc/trans/big5.$(OBJEXT): internal/has/builtin.h
+enc/trans/big5.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/big5.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/big5.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/big5.$(OBJEXT): internal/has/extension.h
+enc/trans/big5.$(OBJEXT): internal/has/feature.h
+enc/trans/big5.$(OBJEXT): internal/has/warning.h
+enc/trans/big5.$(OBJEXT): internal/intern/array.h
+enc/trans/big5.$(OBJEXT): internal/intern/bignum.h
+enc/trans/big5.$(OBJEXT): internal/intern/class.h
+enc/trans/big5.$(OBJEXT): internal/intern/compar.h
+enc/trans/big5.$(OBJEXT): internal/intern/complex.h
+enc/trans/big5.$(OBJEXT): internal/intern/cont.h
+enc/trans/big5.$(OBJEXT): internal/intern/dir.h
+enc/trans/big5.$(OBJEXT): internal/intern/enum.h
+enc/trans/big5.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/big5.$(OBJEXT): internal/intern/error.h
+enc/trans/big5.$(OBJEXT): internal/intern/eval.h
+enc/trans/big5.$(OBJEXT): internal/intern/file.h
+enc/trans/big5.$(OBJEXT): internal/intern/gc.h
+enc/trans/big5.$(OBJEXT): internal/intern/hash.h
+enc/trans/big5.$(OBJEXT): internal/intern/io.h
+enc/trans/big5.$(OBJEXT): internal/intern/load.h
+enc/trans/big5.$(OBJEXT): internal/intern/marshal.h
+enc/trans/big5.$(OBJEXT): internal/intern/numeric.h
+enc/trans/big5.$(OBJEXT): internal/intern/object.h
+enc/trans/big5.$(OBJEXT): internal/intern/parse.h
+enc/trans/big5.$(OBJEXT): internal/intern/proc.h
+enc/trans/big5.$(OBJEXT): internal/intern/process.h
+enc/trans/big5.$(OBJEXT): internal/intern/random.h
+enc/trans/big5.$(OBJEXT): internal/intern/range.h
+enc/trans/big5.$(OBJEXT): internal/intern/rational.h
+enc/trans/big5.$(OBJEXT): internal/intern/re.h
+enc/trans/big5.$(OBJEXT): internal/intern/ruby.h
+enc/trans/big5.$(OBJEXT): internal/intern/select.h
+enc/trans/big5.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/big5.$(OBJEXT): internal/intern/signal.h
+enc/trans/big5.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/big5.$(OBJEXT): internal/intern/string.h
+enc/trans/big5.$(OBJEXT): internal/intern/struct.h
+enc/trans/big5.$(OBJEXT): internal/intern/thread.h
+enc/trans/big5.$(OBJEXT): internal/intern/time.h
+enc/trans/big5.$(OBJEXT): internal/intern/variable.h
+enc/trans/big5.$(OBJEXT): internal/intern/vm.h
+enc/trans/big5.$(OBJEXT): internal/interpreter.h
+enc/trans/big5.$(OBJEXT): internal/iterator.h
+enc/trans/big5.$(OBJEXT): internal/memory.h
+enc/trans/big5.$(OBJEXT): internal/method.h
+enc/trans/big5.$(OBJEXT): internal/module.h
+enc/trans/big5.$(OBJEXT): internal/newobj.h
+enc/trans/big5.$(OBJEXT): internal/rgengc.h
+enc/trans/big5.$(OBJEXT): internal/scan_args.h
+enc/trans/big5.$(OBJEXT): internal/special_consts.h
+enc/trans/big5.$(OBJEXT): internal/static_assert.h
+enc/trans/big5.$(OBJEXT): internal/stdalign.h
+enc/trans/big5.$(OBJEXT): internal/stdbool.h
+enc/trans/big5.$(OBJEXT): internal/symbol.h
+enc/trans/big5.$(OBJEXT): internal/token_paste.h
+enc/trans/big5.$(OBJEXT): internal/value.h
+enc/trans/big5.$(OBJEXT): internal/value_type.h
+enc/trans/big5.$(OBJEXT): internal/variable.h
+enc/trans/big5.$(OBJEXT): internal/warning_push.h
+enc/trans/big5.$(OBJEXT): internal/xmalloc.h
enc/trans/big5.$(OBJEXT): assert.h
enc/trans/big5.$(OBJEXT): backward.h
+enc/trans/big5.$(OBJEXT): backward/2/assume.h
+enc/trans/big5.$(OBJEXT): backward/2/attributes.h
+enc/trans/big5.$(OBJEXT): backward/2/bool.h
+enc/trans/big5.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/big5.$(OBJEXT): backward/2/inttypes.h
+enc/trans/big5.$(OBJEXT): backward/2/limits.h
+enc/trans/big5.$(OBJEXT): backward/2/long_long.h
+enc/trans/big5.$(OBJEXT): backward/2/stdalign.h
+enc/trans/big5.$(OBJEXT): backward/2/stdarg.h
enc/trans/big5.$(OBJEXT): config.h
enc/trans/big5.$(OBJEXT): defines.h
enc/trans/big5.$(OBJEXT): enc/trans/big5.c
@@ -395,8 +2387,157 @@ enc/trans/big5.$(OBJEXT): st.h
enc/trans/big5.$(OBJEXT): subst.h
enc/trans/cesu_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/cesu_8.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/cesu_8.$(OBJEXT): internal/anyargs.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/cesu_8.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/cesu_8.$(OBJEXT): internal/assume.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/artificial.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/cold.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/const.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/error.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/format.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/noalias.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/noinline.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/pure.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/restrict.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/warning.h
+enc/trans/cesu_8.$(OBJEXT): internal/attr/weakref.h
+enc/trans/cesu_8.$(OBJEXT): internal/cast.h
+enc/trans/cesu_8.$(OBJEXT): internal/compiler_is.h
+enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/cesu_8.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/cesu_8.$(OBJEXT): internal/compiler_since.h
+enc/trans/cesu_8.$(OBJEXT): internal/config.h
+enc/trans/cesu_8.$(OBJEXT): internal/constant_p.h
+enc/trans/cesu_8.$(OBJEXT): internal/core.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rarray.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rbasic.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rbignum.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rclass.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rdata.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rfile.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rhash.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/robject.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rregexp.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rstring.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rstruct.h
+enc/trans/cesu_8.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/cesu_8.$(OBJEXT): internal/ctype.h
+enc/trans/cesu_8.$(OBJEXT): internal/dllexport.h
+enc/trans/cesu_8.$(OBJEXT): internal/dosish.h
+enc/trans/cesu_8.$(OBJEXT): internal/error.h
+enc/trans/cesu_8.$(OBJEXT): internal/eval.h
+enc/trans/cesu_8.$(OBJEXT): internal/event.h
+enc/trans/cesu_8.$(OBJEXT): internal/fl_type.h
+enc/trans/cesu_8.$(OBJEXT): internal/gc.h
+enc/trans/cesu_8.$(OBJEXT): internal/glob.h
+enc/trans/cesu_8.$(OBJEXT): internal/globals.h
+enc/trans/cesu_8.$(OBJEXT): internal/has/attribute.h
+enc/trans/cesu_8.$(OBJEXT): internal/has/builtin.h
+enc/trans/cesu_8.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/cesu_8.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/cesu_8.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/cesu_8.$(OBJEXT): internal/has/extension.h
+enc/trans/cesu_8.$(OBJEXT): internal/has/feature.h
+enc/trans/cesu_8.$(OBJEXT): internal/has/warning.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/array.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/bignum.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/class.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/compar.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/complex.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/cont.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/dir.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/enum.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/error.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/eval.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/file.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/gc.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/hash.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/io.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/load.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/marshal.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/numeric.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/object.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/parse.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/proc.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/process.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/random.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/range.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/rational.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/re.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/ruby.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/select.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/signal.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/string.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/struct.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/thread.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/time.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/variable.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/vm.h
+enc/trans/cesu_8.$(OBJEXT): internal/interpreter.h
+enc/trans/cesu_8.$(OBJEXT): internal/iterator.h
+enc/trans/cesu_8.$(OBJEXT): internal/memory.h
+enc/trans/cesu_8.$(OBJEXT): internal/method.h
+enc/trans/cesu_8.$(OBJEXT): internal/module.h
+enc/trans/cesu_8.$(OBJEXT): internal/newobj.h
+enc/trans/cesu_8.$(OBJEXT): internal/rgengc.h
+enc/trans/cesu_8.$(OBJEXT): internal/scan_args.h
+enc/trans/cesu_8.$(OBJEXT): internal/special_consts.h
+enc/trans/cesu_8.$(OBJEXT): internal/static_assert.h
+enc/trans/cesu_8.$(OBJEXT): internal/stdalign.h
+enc/trans/cesu_8.$(OBJEXT): internal/stdbool.h
+enc/trans/cesu_8.$(OBJEXT): internal/symbol.h
+enc/trans/cesu_8.$(OBJEXT): internal/token_paste.h
+enc/trans/cesu_8.$(OBJEXT): internal/value.h
+enc/trans/cesu_8.$(OBJEXT): internal/value_type.h
+enc/trans/cesu_8.$(OBJEXT): internal/variable.h
+enc/trans/cesu_8.$(OBJEXT): internal/warning_push.h
+enc/trans/cesu_8.$(OBJEXT): internal/xmalloc.h
enc/trans/cesu_8.$(OBJEXT): assert.h
enc/trans/cesu_8.$(OBJEXT): backward.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/assume.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/attributes.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/bool.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/inttypes.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/limits.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/long_long.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/stdalign.h
+enc/trans/cesu_8.$(OBJEXT): backward/2/stdarg.h
enc/trans/cesu_8.$(OBJEXT): config.h
enc/trans/cesu_8.$(OBJEXT): defines.h
enc/trans/cesu_8.$(OBJEXT): enc/trans/cesu_8.c
@@ -406,8 +2547,157 @@ enc/trans/cesu_8.$(OBJEXT): st.h
enc/trans/cesu_8.$(OBJEXT): subst.h
enc/trans/chinese.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/chinese.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/chinese.$(OBJEXT): internal/anyargs.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/chinese.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/chinese.$(OBJEXT): internal/assume.h
+enc/trans/chinese.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/chinese.$(OBJEXT): internal/attr/artificial.h
+enc/trans/chinese.$(OBJEXT): internal/attr/cold.h
+enc/trans/chinese.$(OBJEXT): internal/attr/const.h
+enc/trans/chinese.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/chinese.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/chinese.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/chinese.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/chinese.$(OBJEXT): internal/attr/error.h
+enc/trans/chinese.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/chinese.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/chinese.$(OBJEXT): internal/attr/format.h
+enc/trans/chinese.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/chinese.$(OBJEXT): internal/attr/noalias.h
+enc/trans/chinese.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/chinese.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/chinese.$(OBJEXT): internal/attr/noinline.h
+enc/trans/chinese.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/chinese.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/chinese.$(OBJEXT): internal/attr/pure.h
+enc/trans/chinese.$(OBJEXT): internal/attr/restrict.h
+enc/trans/chinese.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/chinese.$(OBJEXT): internal/attr/warning.h
+enc/trans/chinese.$(OBJEXT): internal/attr/weakref.h
+enc/trans/chinese.$(OBJEXT): internal/cast.h
+enc/trans/chinese.$(OBJEXT): internal/compiler_is.h
+enc/trans/chinese.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/chinese.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/chinese.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/chinese.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/chinese.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/chinese.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/chinese.$(OBJEXT): internal/compiler_since.h
+enc/trans/chinese.$(OBJEXT): internal/config.h
+enc/trans/chinese.$(OBJEXT): internal/constant_p.h
+enc/trans/chinese.$(OBJEXT): internal/core.h
+enc/trans/chinese.$(OBJEXT): internal/core/rarray.h
+enc/trans/chinese.$(OBJEXT): internal/core/rbasic.h
+enc/trans/chinese.$(OBJEXT): internal/core/rbignum.h
+enc/trans/chinese.$(OBJEXT): internal/core/rclass.h
+enc/trans/chinese.$(OBJEXT): internal/core/rdata.h
+enc/trans/chinese.$(OBJEXT): internal/core/rfile.h
+enc/trans/chinese.$(OBJEXT): internal/core/rhash.h
+enc/trans/chinese.$(OBJEXT): internal/core/robject.h
+enc/trans/chinese.$(OBJEXT): internal/core/rregexp.h
+enc/trans/chinese.$(OBJEXT): internal/core/rstring.h
+enc/trans/chinese.$(OBJEXT): internal/core/rstruct.h
+enc/trans/chinese.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/chinese.$(OBJEXT): internal/ctype.h
+enc/trans/chinese.$(OBJEXT): internal/dllexport.h
+enc/trans/chinese.$(OBJEXT): internal/dosish.h
+enc/trans/chinese.$(OBJEXT): internal/error.h
+enc/trans/chinese.$(OBJEXT): internal/eval.h
+enc/trans/chinese.$(OBJEXT): internal/event.h
+enc/trans/chinese.$(OBJEXT): internal/fl_type.h
+enc/trans/chinese.$(OBJEXT): internal/gc.h
+enc/trans/chinese.$(OBJEXT): internal/glob.h
+enc/trans/chinese.$(OBJEXT): internal/globals.h
+enc/trans/chinese.$(OBJEXT): internal/has/attribute.h
+enc/trans/chinese.$(OBJEXT): internal/has/builtin.h
+enc/trans/chinese.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/chinese.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/chinese.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/chinese.$(OBJEXT): internal/has/extension.h
+enc/trans/chinese.$(OBJEXT): internal/has/feature.h
+enc/trans/chinese.$(OBJEXT): internal/has/warning.h
+enc/trans/chinese.$(OBJEXT): internal/intern/array.h
+enc/trans/chinese.$(OBJEXT): internal/intern/bignum.h
+enc/trans/chinese.$(OBJEXT): internal/intern/class.h
+enc/trans/chinese.$(OBJEXT): internal/intern/compar.h
+enc/trans/chinese.$(OBJEXT): internal/intern/complex.h
+enc/trans/chinese.$(OBJEXT): internal/intern/cont.h
+enc/trans/chinese.$(OBJEXT): internal/intern/dir.h
+enc/trans/chinese.$(OBJEXT): internal/intern/enum.h
+enc/trans/chinese.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/chinese.$(OBJEXT): internal/intern/error.h
+enc/trans/chinese.$(OBJEXT): internal/intern/eval.h
+enc/trans/chinese.$(OBJEXT): internal/intern/file.h
+enc/trans/chinese.$(OBJEXT): internal/intern/gc.h
+enc/trans/chinese.$(OBJEXT): internal/intern/hash.h
+enc/trans/chinese.$(OBJEXT): internal/intern/io.h
+enc/trans/chinese.$(OBJEXT): internal/intern/load.h
+enc/trans/chinese.$(OBJEXT): internal/intern/marshal.h
+enc/trans/chinese.$(OBJEXT): internal/intern/numeric.h
+enc/trans/chinese.$(OBJEXT): internal/intern/object.h
+enc/trans/chinese.$(OBJEXT): internal/intern/parse.h
+enc/trans/chinese.$(OBJEXT): internal/intern/proc.h
+enc/trans/chinese.$(OBJEXT): internal/intern/process.h
+enc/trans/chinese.$(OBJEXT): internal/intern/random.h
+enc/trans/chinese.$(OBJEXT): internal/intern/range.h
+enc/trans/chinese.$(OBJEXT): internal/intern/rational.h
+enc/trans/chinese.$(OBJEXT): internal/intern/re.h
+enc/trans/chinese.$(OBJEXT): internal/intern/ruby.h
+enc/trans/chinese.$(OBJEXT): internal/intern/select.h
+enc/trans/chinese.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/chinese.$(OBJEXT): internal/intern/signal.h
+enc/trans/chinese.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/chinese.$(OBJEXT): internal/intern/string.h
+enc/trans/chinese.$(OBJEXT): internal/intern/struct.h
+enc/trans/chinese.$(OBJEXT): internal/intern/thread.h
+enc/trans/chinese.$(OBJEXT): internal/intern/time.h
+enc/trans/chinese.$(OBJEXT): internal/intern/variable.h
+enc/trans/chinese.$(OBJEXT): internal/intern/vm.h
+enc/trans/chinese.$(OBJEXT): internal/interpreter.h
+enc/trans/chinese.$(OBJEXT): internal/iterator.h
+enc/trans/chinese.$(OBJEXT): internal/memory.h
+enc/trans/chinese.$(OBJEXT): internal/method.h
+enc/trans/chinese.$(OBJEXT): internal/module.h
+enc/trans/chinese.$(OBJEXT): internal/newobj.h
+enc/trans/chinese.$(OBJEXT): internal/rgengc.h
+enc/trans/chinese.$(OBJEXT): internal/scan_args.h
+enc/trans/chinese.$(OBJEXT): internal/special_consts.h
+enc/trans/chinese.$(OBJEXT): internal/static_assert.h
+enc/trans/chinese.$(OBJEXT): internal/stdalign.h
+enc/trans/chinese.$(OBJEXT): internal/stdbool.h
+enc/trans/chinese.$(OBJEXT): internal/symbol.h
+enc/trans/chinese.$(OBJEXT): internal/token_paste.h
+enc/trans/chinese.$(OBJEXT): internal/value.h
+enc/trans/chinese.$(OBJEXT): internal/value_type.h
+enc/trans/chinese.$(OBJEXT): internal/variable.h
+enc/trans/chinese.$(OBJEXT): internal/warning_push.h
+enc/trans/chinese.$(OBJEXT): internal/xmalloc.h
enc/trans/chinese.$(OBJEXT): assert.h
enc/trans/chinese.$(OBJEXT): backward.h
+enc/trans/chinese.$(OBJEXT): backward/2/assume.h
+enc/trans/chinese.$(OBJEXT): backward/2/attributes.h
+enc/trans/chinese.$(OBJEXT): backward/2/bool.h
+enc/trans/chinese.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/chinese.$(OBJEXT): backward/2/inttypes.h
+enc/trans/chinese.$(OBJEXT): backward/2/limits.h
+enc/trans/chinese.$(OBJEXT): backward/2/long_long.h
+enc/trans/chinese.$(OBJEXT): backward/2/stdalign.h
+enc/trans/chinese.$(OBJEXT): backward/2/stdarg.h
enc/trans/chinese.$(OBJEXT): config.h
enc/trans/chinese.$(OBJEXT): defines.h
enc/trans/chinese.$(OBJEXT): enc/trans/chinese.c
@@ -417,8 +2707,157 @@ enc/trans/chinese.$(OBJEXT): st.h
enc/trans/chinese.$(OBJEXT): subst.h
enc/trans/ebcdic.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/ebcdic.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/ebcdic.$(OBJEXT): internal/anyargs.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/ebcdic.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/ebcdic.$(OBJEXT): internal/assume.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/artificial.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/cold.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/const.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/error.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/format.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/noalias.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/noinline.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/pure.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/restrict.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/warning.h
+enc/trans/ebcdic.$(OBJEXT): internal/attr/weakref.h
+enc/trans/ebcdic.$(OBJEXT): internal/cast.h
+enc/trans/ebcdic.$(OBJEXT): internal/compiler_is.h
+enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/ebcdic.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/ebcdic.$(OBJEXT): internal/compiler_since.h
+enc/trans/ebcdic.$(OBJEXT): internal/config.h
+enc/trans/ebcdic.$(OBJEXT): internal/constant_p.h
+enc/trans/ebcdic.$(OBJEXT): internal/core.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rarray.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rbasic.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rbignum.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rclass.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rdata.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rfile.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rhash.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/robject.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rregexp.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rstring.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rstruct.h
+enc/trans/ebcdic.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/ebcdic.$(OBJEXT): internal/ctype.h
+enc/trans/ebcdic.$(OBJEXT): internal/dllexport.h
+enc/trans/ebcdic.$(OBJEXT): internal/dosish.h
+enc/trans/ebcdic.$(OBJEXT): internal/error.h
+enc/trans/ebcdic.$(OBJEXT): internal/eval.h
+enc/trans/ebcdic.$(OBJEXT): internal/event.h
+enc/trans/ebcdic.$(OBJEXT): internal/fl_type.h
+enc/trans/ebcdic.$(OBJEXT): internal/gc.h
+enc/trans/ebcdic.$(OBJEXT): internal/glob.h
+enc/trans/ebcdic.$(OBJEXT): internal/globals.h
+enc/trans/ebcdic.$(OBJEXT): internal/has/attribute.h
+enc/trans/ebcdic.$(OBJEXT): internal/has/builtin.h
+enc/trans/ebcdic.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/ebcdic.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/ebcdic.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/ebcdic.$(OBJEXT): internal/has/extension.h
+enc/trans/ebcdic.$(OBJEXT): internal/has/feature.h
+enc/trans/ebcdic.$(OBJEXT): internal/has/warning.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/array.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/bignum.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/class.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/compar.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/complex.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/cont.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/dir.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/enum.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/error.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/eval.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/file.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/gc.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/hash.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/io.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/load.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/marshal.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/numeric.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/object.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/parse.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/proc.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/process.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/random.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/range.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/rational.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/re.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/ruby.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/select.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/signal.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/string.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/struct.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/thread.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/time.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/variable.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/vm.h
+enc/trans/ebcdic.$(OBJEXT): internal/interpreter.h
+enc/trans/ebcdic.$(OBJEXT): internal/iterator.h
+enc/trans/ebcdic.$(OBJEXT): internal/memory.h
+enc/trans/ebcdic.$(OBJEXT): internal/method.h
+enc/trans/ebcdic.$(OBJEXT): internal/module.h
+enc/trans/ebcdic.$(OBJEXT): internal/newobj.h
+enc/trans/ebcdic.$(OBJEXT): internal/rgengc.h
+enc/trans/ebcdic.$(OBJEXT): internal/scan_args.h
+enc/trans/ebcdic.$(OBJEXT): internal/special_consts.h
+enc/trans/ebcdic.$(OBJEXT): internal/static_assert.h
+enc/trans/ebcdic.$(OBJEXT): internal/stdalign.h
+enc/trans/ebcdic.$(OBJEXT): internal/stdbool.h
+enc/trans/ebcdic.$(OBJEXT): internal/symbol.h
+enc/trans/ebcdic.$(OBJEXT): internal/token_paste.h
+enc/trans/ebcdic.$(OBJEXT): internal/value.h
+enc/trans/ebcdic.$(OBJEXT): internal/value_type.h
+enc/trans/ebcdic.$(OBJEXT): internal/variable.h
+enc/trans/ebcdic.$(OBJEXT): internal/warning_push.h
+enc/trans/ebcdic.$(OBJEXT): internal/xmalloc.h
enc/trans/ebcdic.$(OBJEXT): assert.h
enc/trans/ebcdic.$(OBJEXT): backward.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/assume.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/attributes.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/bool.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/inttypes.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/limits.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/long_long.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/stdalign.h
+enc/trans/ebcdic.$(OBJEXT): backward/2/stdarg.h
enc/trans/ebcdic.$(OBJEXT): config.h
enc/trans/ebcdic.$(OBJEXT): defines.h
enc/trans/ebcdic.$(OBJEXT): enc/trans/ebcdic.c
@@ -428,8 +2867,157 @@ enc/trans/ebcdic.$(OBJEXT): st.h
enc/trans/ebcdic.$(OBJEXT): subst.h
enc/trans/emoji.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/emoji.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/emoji.$(OBJEXT): internal/anyargs.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/emoji.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/emoji.$(OBJEXT): internal/assume.h
+enc/trans/emoji.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/emoji.$(OBJEXT): internal/attr/artificial.h
+enc/trans/emoji.$(OBJEXT): internal/attr/cold.h
+enc/trans/emoji.$(OBJEXT): internal/attr/const.h
+enc/trans/emoji.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/emoji.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/emoji.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/emoji.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/emoji.$(OBJEXT): internal/attr/error.h
+enc/trans/emoji.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/emoji.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/emoji.$(OBJEXT): internal/attr/format.h
+enc/trans/emoji.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/emoji.$(OBJEXT): internal/attr/noalias.h
+enc/trans/emoji.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/emoji.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/emoji.$(OBJEXT): internal/attr/noinline.h
+enc/trans/emoji.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/emoji.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/emoji.$(OBJEXT): internal/attr/pure.h
+enc/trans/emoji.$(OBJEXT): internal/attr/restrict.h
+enc/trans/emoji.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/emoji.$(OBJEXT): internal/attr/warning.h
+enc/trans/emoji.$(OBJEXT): internal/attr/weakref.h
+enc/trans/emoji.$(OBJEXT): internal/cast.h
+enc/trans/emoji.$(OBJEXT): internal/compiler_is.h
+enc/trans/emoji.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/emoji.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/emoji.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/emoji.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/emoji.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/emoji.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/emoji.$(OBJEXT): internal/compiler_since.h
+enc/trans/emoji.$(OBJEXT): internal/config.h
+enc/trans/emoji.$(OBJEXT): internal/constant_p.h
+enc/trans/emoji.$(OBJEXT): internal/core.h
+enc/trans/emoji.$(OBJEXT): internal/core/rarray.h
+enc/trans/emoji.$(OBJEXT): internal/core/rbasic.h
+enc/trans/emoji.$(OBJEXT): internal/core/rbignum.h
+enc/trans/emoji.$(OBJEXT): internal/core/rclass.h
+enc/trans/emoji.$(OBJEXT): internal/core/rdata.h
+enc/trans/emoji.$(OBJEXT): internal/core/rfile.h
+enc/trans/emoji.$(OBJEXT): internal/core/rhash.h
+enc/trans/emoji.$(OBJEXT): internal/core/robject.h
+enc/trans/emoji.$(OBJEXT): internal/core/rregexp.h
+enc/trans/emoji.$(OBJEXT): internal/core/rstring.h
+enc/trans/emoji.$(OBJEXT): internal/core/rstruct.h
+enc/trans/emoji.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/emoji.$(OBJEXT): internal/ctype.h
+enc/trans/emoji.$(OBJEXT): internal/dllexport.h
+enc/trans/emoji.$(OBJEXT): internal/dosish.h
+enc/trans/emoji.$(OBJEXT): internal/error.h
+enc/trans/emoji.$(OBJEXT): internal/eval.h
+enc/trans/emoji.$(OBJEXT): internal/event.h
+enc/trans/emoji.$(OBJEXT): internal/fl_type.h
+enc/trans/emoji.$(OBJEXT): internal/gc.h
+enc/trans/emoji.$(OBJEXT): internal/glob.h
+enc/trans/emoji.$(OBJEXT): internal/globals.h
+enc/trans/emoji.$(OBJEXT): internal/has/attribute.h
+enc/trans/emoji.$(OBJEXT): internal/has/builtin.h
+enc/trans/emoji.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/emoji.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/emoji.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/emoji.$(OBJEXT): internal/has/extension.h
+enc/trans/emoji.$(OBJEXT): internal/has/feature.h
+enc/trans/emoji.$(OBJEXT): internal/has/warning.h
+enc/trans/emoji.$(OBJEXT): internal/intern/array.h
+enc/trans/emoji.$(OBJEXT): internal/intern/bignum.h
+enc/trans/emoji.$(OBJEXT): internal/intern/class.h
+enc/trans/emoji.$(OBJEXT): internal/intern/compar.h
+enc/trans/emoji.$(OBJEXT): internal/intern/complex.h
+enc/trans/emoji.$(OBJEXT): internal/intern/cont.h
+enc/trans/emoji.$(OBJEXT): internal/intern/dir.h
+enc/trans/emoji.$(OBJEXT): internal/intern/enum.h
+enc/trans/emoji.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/emoji.$(OBJEXT): internal/intern/error.h
+enc/trans/emoji.$(OBJEXT): internal/intern/eval.h
+enc/trans/emoji.$(OBJEXT): internal/intern/file.h
+enc/trans/emoji.$(OBJEXT): internal/intern/gc.h
+enc/trans/emoji.$(OBJEXT): internal/intern/hash.h
+enc/trans/emoji.$(OBJEXT): internal/intern/io.h
+enc/trans/emoji.$(OBJEXT): internal/intern/load.h
+enc/trans/emoji.$(OBJEXT): internal/intern/marshal.h
+enc/trans/emoji.$(OBJEXT): internal/intern/numeric.h
+enc/trans/emoji.$(OBJEXT): internal/intern/object.h
+enc/trans/emoji.$(OBJEXT): internal/intern/parse.h
+enc/trans/emoji.$(OBJEXT): internal/intern/proc.h
+enc/trans/emoji.$(OBJEXT): internal/intern/process.h
+enc/trans/emoji.$(OBJEXT): internal/intern/random.h
+enc/trans/emoji.$(OBJEXT): internal/intern/range.h
+enc/trans/emoji.$(OBJEXT): internal/intern/rational.h
+enc/trans/emoji.$(OBJEXT): internal/intern/re.h
+enc/trans/emoji.$(OBJEXT): internal/intern/ruby.h
+enc/trans/emoji.$(OBJEXT): internal/intern/select.h
+enc/trans/emoji.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji.$(OBJEXT): internal/intern/signal.h
+enc/trans/emoji.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/emoji.$(OBJEXT): internal/intern/string.h
+enc/trans/emoji.$(OBJEXT): internal/intern/struct.h
+enc/trans/emoji.$(OBJEXT): internal/intern/thread.h
+enc/trans/emoji.$(OBJEXT): internal/intern/time.h
+enc/trans/emoji.$(OBJEXT): internal/intern/variable.h
+enc/trans/emoji.$(OBJEXT): internal/intern/vm.h
+enc/trans/emoji.$(OBJEXT): internal/interpreter.h
+enc/trans/emoji.$(OBJEXT): internal/iterator.h
+enc/trans/emoji.$(OBJEXT): internal/memory.h
+enc/trans/emoji.$(OBJEXT): internal/method.h
+enc/trans/emoji.$(OBJEXT): internal/module.h
+enc/trans/emoji.$(OBJEXT): internal/newobj.h
+enc/trans/emoji.$(OBJEXT): internal/rgengc.h
+enc/trans/emoji.$(OBJEXT): internal/scan_args.h
+enc/trans/emoji.$(OBJEXT): internal/special_consts.h
+enc/trans/emoji.$(OBJEXT): internal/static_assert.h
+enc/trans/emoji.$(OBJEXT): internal/stdalign.h
+enc/trans/emoji.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji.$(OBJEXT): internal/symbol.h
+enc/trans/emoji.$(OBJEXT): internal/token_paste.h
+enc/trans/emoji.$(OBJEXT): internal/value.h
+enc/trans/emoji.$(OBJEXT): internal/value_type.h
+enc/trans/emoji.$(OBJEXT): internal/variable.h
+enc/trans/emoji.$(OBJEXT): internal/warning_push.h
+enc/trans/emoji.$(OBJEXT): internal/xmalloc.h
enc/trans/emoji.$(OBJEXT): assert.h
enc/trans/emoji.$(OBJEXT): backward.h
+enc/trans/emoji.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/emoji.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji.$(OBJEXT): backward/2/stdarg.h
enc/trans/emoji.$(OBJEXT): config.h
enc/trans/emoji.$(OBJEXT): defines.h
enc/trans/emoji.$(OBJEXT): enc/trans/emoji.c
@@ -439,8 +3027,157 @@ enc/trans/emoji.$(OBJEXT): st.h
enc/trans/emoji.$(OBJEXT): subst.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/anyargs.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/assume.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/artificial.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/cold.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/const.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/error.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/format.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/noalias.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/noinline.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/pure.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/restrict.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/warning.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/attr/weakref.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/cast.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/compiler_since.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/config.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/constant_p.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rarray.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rbasic.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rbignum.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rclass.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rdata.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rfile.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rhash.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/robject.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rregexp.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rstring.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rstruct.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/ctype.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/dllexport.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/dosish.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/error.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/eval.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/event.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/fl_type.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/gc.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/glob.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/globals.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/attribute.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/builtin.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/extension.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/feature.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/has/warning.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/array.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/bignum.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/class.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/compar.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/complex.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/cont.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/dir.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/enum.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/error.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/eval.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/file.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/gc.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/hash.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/io.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/load.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/marshal.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/numeric.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/object.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/parse.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/proc.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/process.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/random.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/range.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/rational.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/re.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/ruby.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/select.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/signal.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/string.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/struct.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/thread.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/time.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/variable.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/vm.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/interpreter.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/iterator.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/memory.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/method.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/module.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/newobj.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/rgengc.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/scan_args.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/special_consts.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/static_assert.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/stdalign.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/symbol.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/token_paste.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/value.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/value_type.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/variable.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/warning_push.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/xmalloc.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): assert.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): backward/2/stdarg.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): config.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): defines.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): enc/trans/emoji_iso2022_kddi.c
@@ -450,8 +3187,157 @@ enc/trans/emoji_iso2022_kddi.$(OBJEXT): st.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): subst.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/anyargs.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/assume.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/artificial.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/cold.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/const.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/error.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/format.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/noalias.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/noinline.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/pure.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/restrict.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/warning.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/attr/weakref.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/cast.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/compiler_since.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/config.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/constant_p.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rarray.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rbasic.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rbignum.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rclass.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rdata.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rfile.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rhash.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/robject.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rregexp.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rstring.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rstruct.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/ctype.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/dllexport.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/dosish.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/error.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/eval.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/event.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/fl_type.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/gc.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/glob.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/globals.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/attribute.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/builtin.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/extension.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/feature.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/has/warning.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/array.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/bignum.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/class.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/compar.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/complex.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/cont.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/dir.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/enum.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/error.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/eval.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/file.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/gc.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/hash.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/io.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/load.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/marshal.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/numeric.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/object.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/parse.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/proc.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/process.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/random.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/range.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/rational.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/re.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/ruby.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/select.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/signal.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/string.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/struct.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/thread.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/time.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/variable.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/vm.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/interpreter.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/iterator.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/memory.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/method.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/module.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/newobj.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/rgengc.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/scan_args.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/special_consts.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/static_assert.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/stdalign.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/symbol.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/token_paste.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/value.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/value_type.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/variable.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/warning_push.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/xmalloc.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): assert.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): backward.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): backward/2/stdarg.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): config.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): defines.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): enc/trans/emoji_sjis_docomo.c
@@ -461,8 +3347,157 @@ enc/trans/emoji_sjis_docomo.$(OBJEXT): st.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): subst.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/anyargs.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/assume.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/artificial.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/cold.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/const.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/error.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/format.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/noalias.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/noinline.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/pure.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/restrict.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/warning.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/attr/weakref.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/cast.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/compiler_since.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/config.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/constant_p.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rarray.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rbasic.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rbignum.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rclass.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rdata.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rfile.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rhash.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/robject.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rregexp.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rstring.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rstruct.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/ctype.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/dllexport.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/dosish.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/error.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/eval.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/event.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/fl_type.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/gc.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/glob.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/globals.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/attribute.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/builtin.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/extension.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/feature.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/has/warning.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/array.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/bignum.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/class.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/compar.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/complex.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/cont.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/dir.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/enum.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/error.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/eval.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/file.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/gc.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/hash.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/io.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/load.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/marshal.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/numeric.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/object.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/parse.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/proc.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/process.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/random.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/range.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/rational.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/re.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/ruby.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/select.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/signal.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/string.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/struct.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/thread.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/time.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/variable.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/vm.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/interpreter.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/iterator.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/memory.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/method.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/module.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/newobj.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/rgengc.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/scan_args.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/special_consts.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/static_assert.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/stdalign.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/symbol.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/token_paste.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/value.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/value_type.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/variable.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/warning_push.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/xmalloc.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): assert.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): backward.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): backward/2/stdarg.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): config.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): defines.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): enc/trans/emoji_sjis_kddi.c
@@ -472,8 +3507,157 @@ enc/trans/emoji_sjis_kddi.$(OBJEXT): st.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): subst.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/anyargs.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/assume.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/artificial.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/cold.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/const.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/error.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/format.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/noalias.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/noinline.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/pure.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/restrict.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/warning.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/attr/weakref.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/cast.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/compiler_since.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/config.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/constant_p.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rarray.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rbasic.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rbignum.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rclass.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rdata.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rfile.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rhash.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/robject.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rregexp.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rstring.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rstruct.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/ctype.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/dllexport.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/dosish.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/error.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/eval.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/event.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/fl_type.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/gc.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/glob.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/globals.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/attribute.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/builtin.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/extension.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/feature.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/has/warning.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/array.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/bignum.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/class.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/compar.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/complex.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/cont.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/dir.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/enum.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/error.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/eval.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/file.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/gc.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/hash.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/io.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/load.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/marshal.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/numeric.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/object.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/parse.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/proc.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/process.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/random.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/range.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/rational.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/re.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/ruby.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/select.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/signal.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/string.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/struct.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/thread.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/time.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/variable.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/vm.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/interpreter.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/iterator.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/memory.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/method.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/module.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/newobj.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/rgengc.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/scan_args.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/special_consts.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/static_assert.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/stdalign.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/stdbool.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/symbol.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/token_paste.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/value.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/value_type.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/variable.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/warning_push.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/xmalloc.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): assert.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): backward.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/assume.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/attributes.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/bool.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/inttypes.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/limits.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/long_long.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/stdalign.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): backward/2/stdarg.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): config.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): defines.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): enc/trans/emoji_sjis_softbank.c
@@ -483,8 +3667,157 @@ enc/trans/emoji_sjis_softbank.$(OBJEXT): st.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): subst.h
enc/trans/escape.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/escape.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/escape.$(OBJEXT): internal/anyargs.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/escape.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/escape.$(OBJEXT): internal/assume.h
+enc/trans/escape.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/escape.$(OBJEXT): internal/attr/artificial.h
+enc/trans/escape.$(OBJEXT): internal/attr/cold.h
+enc/trans/escape.$(OBJEXT): internal/attr/const.h
+enc/trans/escape.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/escape.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/escape.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/escape.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/escape.$(OBJEXT): internal/attr/error.h
+enc/trans/escape.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/escape.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/escape.$(OBJEXT): internal/attr/format.h
+enc/trans/escape.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/escape.$(OBJEXT): internal/attr/noalias.h
+enc/trans/escape.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/escape.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/escape.$(OBJEXT): internal/attr/noinline.h
+enc/trans/escape.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/escape.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/escape.$(OBJEXT): internal/attr/pure.h
+enc/trans/escape.$(OBJEXT): internal/attr/restrict.h
+enc/trans/escape.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/escape.$(OBJEXT): internal/attr/warning.h
+enc/trans/escape.$(OBJEXT): internal/attr/weakref.h
+enc/trans/escape.$(OBJEXT): internal/cast.h
+enc/trans/escape.$(OBJEXT): internal/compiler_is.h
+enc/trans/escape.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/escape.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/escape.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/escape.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/escape.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/escape.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/escape.$(OBJEXT): internal/compiler_since.h
+enc/trans/escape.$(OBJEXT): internal/config.h
+enc/trans/escape.$(OBJEXT): internal/constant_p.h
+enc/trans/escape.$(OBJEXT): internal/core.h
+enc/trans/escape.$(OBJEXT): internal/core/rarray.h
+enc/trans/escape.$(OBJEXT): internal/core/rbasic.h
+enc/trans/escape.$(OBJEXT): internal/core/rbignum.h
+enc/trans/escape.$(OBJEXT): internal/core/rclass.h
+enc/trans/escape.$(OBJEXT): internal/core/rdata.h
+enc/trans/escape.$(OBJEXT): internal/core/rfile.h
+enc/trans/escape.$(OBJEXT): internal/core/rhash.h
+enc/trans/escape.$(OBJEXT): internal/core/robject.h
+enc/trans/escape.$(OBJEXT): internal/core/rregexp.h
+enc/trans/escape.$(OBJEXT): internal/core/rstring.h
+enc/trans/escape.$(OBJEXT): internal/core/rstruct.h
+enc/trans/escape.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/escape.$(OBJEXT): internal/ctype.h
+enc/trans/escape.$(OBJEXT): internal/dllexport.h
+enc/trans/escape.$(OBJEXT): internal/dosish.h
+enc/trans/escape.$(OBJEXT): internal/error.h
+enc/trans/escape.$(OBJEXT): internal/eval.h
+enc/trans/escape.$(OBJEXT): internal/event.h
+enc/trans/escape.$(OBJEXT): internal/fl_type.h
+enc/trans/escape.$(OBJEXT): internal/gc.h
+enc/trans/escape.$(OBJEXT): internal/glob.h
+enc/trans/escape.$(OBJEXT): internal/globals.h
+enc/trans/escape.$(OBJEXT): internal/has/attribute.h
+enc/trans/escape.$(OBJEXT): internal/has/builtin.h
+enc/trans/escape.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/escape.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/escape.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/escape.$(OBJEXT): internal/has/extension.h
+enc/trans/escape.$(OBJEXT): internal/has/feature.h
+enc/trans/escape.$(OBJEXT): internal/has/warning.h
+enc/trans/escape.$(OBJEXT): internal/intern/array.h
+enc/trans/escape.$(OBJEXT): internal/intern/bignum.h
+enc/trans/escape.$(OBJEXT): internal/intern/class.h
+enc/trans/escape.$(OBJEXT): internal/intern/compar.h
+enc/trans/escape.$(OBJEXT): internal/intern/complex.h
+enc/trans/escape.$(OBJEXT): internal/intern/cont.h
+enc/trans/escape.$(OBJEXT): internal/intern/dir.h
+enc/trans/escape.$(OBJEXT): internal/intern/enum.h
+enc/trans/escape.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/escape.$(OBJEXT): internal/intern/error.h
+enc/trans/escape.$(OBJEXT): internal/intern/eval.h
+enc/trans/escape.$(OBJEXT): internal/intern/file.h
+enc/trans/escape.$(OBJEXT): internal/intern/gc.h
+enc/trans/escape.$(OBJEXT): internal/intern/hash.h
+enc/trans/escape.$(OBJEXT): internal/intern/io.h
+enc/trans/escape.$(OBJEXT): internal/intern/load.h
+enc/trans/escape.$(OBJEXT): internal/intern/marshal.h
+enc/trans/escape.$(OBJEXT): internal/intern/numeric.h
+enc/trans/escape.$(OBJEXT): internal/intern/object.h
+enc/trans/escape.$(OBJEXT): internal/intern/parse.h
+enc/trans/escape.$(OBJEXT): internal/intern/proc.h
+enc/trans/escape.$(OBJEXT): internal/intern/process.h
+enc/trans/escape.$(OBJEXT): internal/intern/random.h
+enc/trans/escape.$(OBJEXT): internal/intern/range.h
+enc/trans/escape.$(OBJEXT): internal/intern/rational.h
+enc/trans/escape.$(OBJEXT): internal/intern/re.h
+enc/trans/escape.$(OBJEXT): internal/intern/ruby.h
+enc/trans/escape.$(OBJEXT): internal/intern/select.h
+enc/trans/escape.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/escape.$(OBJEXT): internal/intern/signal.h
+enc/trans/escape.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/escape.$(OBJEXT): internal/intern/string.h
+enc/trans/escape.$(OBJEXT): internal/intern/struct.h
+enc/trans/escape.$(OBJEXT): internal/intern/thread.h
+enc/trans/escape.$(OBJEXT): internal/intern/time.h
+enc/trans/escape.$(OBJEXT): internal/intern/variable.h
+enc/trans/escape.$(OBJEXT): internal/intern/vm.h
+enc/trans/escape.$(OBJEXT): internal/interpreter.h
+enc/trans/escape.$(OBJEXT): internal/iterator.h
+enc/trans/escape.$(OBJEXT): internal/memory.h
+enc/trans/escape.$(OBJEXT): internal/method.h
+enc/trans/escape.$(OBJEXT): internal/module.h
+enc/trans/escape.$(OBJEXT): internal/newobj.h
+enc/trans/escape.$(OBJEXT): internal/rgengc.h
+enc/trans/escape.$(OBJEXT): internal/scan_args.h
+enc/trans/escape.$(OBJEXT): internal/special_consts.h
+enc/trans/escape.$(OBJEXT): internal/static_assert.h
+enc/trans/escape.$(OBJEXT): internal/stdalign.h
+enc/trans/escape.$(OBJEXT): internal/stdbool.h
+enc/trans/escape.$(OBJEXT): internal/symbol.h
+enc/trans/escape.$(OBJEXT): internal/token_paste.h
+enc/trans/escape.$(OBJEXT): internal/value.h
+enc/trans/escape.$(OBJEXT): internal/value_type.h
+enc/trans/escape.$(OBJEXT): internal/variable.h
+enc/trans/escape.$(OBJEXT): internal/warning_push.h
+enc/trans/escape.$(OBJEXT): internal/xmalloc.h
enc/trans/escape.$(OBJEXT): assert.h
enc/trans/escape.$(OBJEXT): backward.h
+enc/trans/escape.$(OBJEXT): backward/2/assume.h
+enc/trans/escape.$(OBJEXT): backward/2/attributes.h
+enc/trans/escape.$(OBJEXT): backward/2/bool.h
+enc/trans/escape.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/escape.$(OBJEXT): backward/2/inttypes.h
+enc/trans/escape.$(OBJEXT): backward/2/limits.h
+enc/trans/escape.$(OBJEXT): backward/2/long_long.h
+enc/trans/escape.$(OBJEXT): backward/2/stdalign.h
+enc/trans/escape.$(OBJEXT): backward/2/stdarg.h
enc/trans/escape.$(OBJEXT): config.h
enc/trans/escape.$(OBJEXT): defines.h
enc/trans/escape.$(OBJEXT): enc/trans/escape.c
@@ -494,8 +3827,157 @@ enc/trans/escape.$(OBJEXT): st.h
enc/trans/escape.$(OBJEXT): subst.h
enc/trans/gb18030.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/gb18030.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/gb18030.$(OBJEXT): internal/anyargs.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/gb18030.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/gb18030.$(OBJEXT): internal/assume.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/artificial.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/cold.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/const.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/error.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/format.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/noalias.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/noinline.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/pure.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/restrict.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/warning.h
+enc/trans/gb18030.$(OBJEXT): internal/attr/weakref.h
+enc/trans/gb18030.$(OBJEXT): internal/cast.h
+enc/trans/gb18030.$(OBJEXT): internal/compiler_is.h
+enc/trans/gb18030.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/gb18030.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/gb18030.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/gb18030.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/gb18030.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/gb18030.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/gb18030.$(OBJEXT): internal/compiler_since.h
+enc/trans/gb18030.$(OBJEXT): internal/config.h
+enc/trans/gb18030.$(OBJEXT): internal/constant_p.h
+enc/trans/gb18030.$(OBJEXT): internal/core.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rarray.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rbasic.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rbignum.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rclass.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rdata.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rfile.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rhash.h
+enc/trans/gb18030.$(OBJEXT): internal/core/robject.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rregexp.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rstring.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rstruct.h
+enc/trans/gb18030.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/gb18030.$(OBJEXT): internal/ctype.h
+enc/trans/gb18030.$(OBJEXT): internal/dllexport.h
+enc/trans/gb18030.$(OBJEXT): internal/dosish.h
+enc/trans/gb18030.$(OBJEXT): internal/error.h
+enc/trans/gb18030.$(OBJEXT): internal/eval.h
+enc/trans/gb18030.$(OBJEXT): internal/event.h
+enc/trans/gb18030.$(OBJEXT): internal/fl_type.h
+enc/trans/gb18030.$(OBJEXT): internal/gc.h
+enc/trans/gb18030.$(OBJEXT): internal/glob.h
+enc/trans/gb18030.$(OBJEXT): internal/globals.h
+enc/trans/gb18030.$(OBJEXT): internal/has/attribute.h
+enc/trans/gb18030.$(OBJEXT): internal/has/builtin.h
+enc/trans/gb18030.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/gb18030.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/gb18030.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/gb18030.$(OBJEXT): internal/has/extension.h
+enc/trans/gb18030.$(OBJEXT): internal/has/feature.h
+enc/trans/gb18030.$(OBJEXT): internal/has/warning.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/array.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/bignum.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/class.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/compar.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/complex.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/cont.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/dir.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/enum.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/error.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/eval.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/file.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/gc.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/hash.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/io.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/load.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/marshal.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/numeric.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/object.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/parse.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/proc.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/process.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/random.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/range.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/rational.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/re.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/ruby.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/select.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/signal.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/string.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/struct.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/thread.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/time.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/variable.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/vm.h
+enc/trans/gb18030.$(OBJEXT): internal/interpreter.h
+enc/trans/gb18030.$(OBJEXT): internal/iterator.h
+enc/trans/gb18030.$(OBJEXT): internal/memory.h
+enc/trans/gb18030.$(OBJEXT): internal/method.h
+enc/trans/gb18030.$(OBJEXT): internal/module.h
+enc/trans/gb18030.$(OBJEXT): internal/newobj.h
+enc/trans/gb18030.$(OBJEXT): internal/rgengc.h
+enc/trans/gb18030.$(OBJEXT): internal/scan_args.h
+enc/trans/gb18030.$(OBJEXT): internal/special_consts.h
+enc/trans/gb18030.$(OBJEXT): internal/static_assert.h
+enc/trans/gb18030.$(OBJEXT): internal/stdalign.h
+enc/trans/gb18030.$(OBJEXT): internal/stdbool.h
+enc/trans/gb18030.$(OBJEXT): internal/symbol.h
+enc/trans/gb18030.$(OBJEXT): internal/token_paste.h
+enc/trans/gb18030.$(OBJEXT): internal/value.h
+enc/trans/gb18030.$(OBJEXT): internal/value_type.h
+enc/trans/gb18030.$(OBJEXT): internal/variable.h
+enc/trans/gb18030.$(OBJEXT): internal/warning_push.h
+enc/trans/gb18030.$(OBJEXT): internal/xmalloc.h
enc/trans/gb18030.$(OBJEXT): assert.h
enc/trans/gb18030.$(OBJEXT): backward.h
+enc/trans/gb18030.$(OBJEXT): backward/2/assume.h
+enc/trans/gb18030.$(OBJEXT): backward/2/attributes.h
+enc/trans/gb18030.$(OBJEXT): backward/2/bool.h
+enc/trans/gb18030.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/gb18030.$(OBJEXT): backward/2/inttypes.h
+enc/trans/gb18030.$(OBJEXT): backward/2/limits.h
+enc/trans/gb18030.$(OBJEXT): backward/2/long_long.h
+enc/trans/gb18030.$(OBJEXT): backward/2/stdalign.h
+enc/trans/gb18030.$(OBJEXT): backward/2/stdarg.h
enc/trans/gb18030.$(OBJEXT): config.h
enc/trans/gb18030.$(OBJEXT): defines.h
enc/trans/gb18030.$(OBJEXT): enc/trans/gb18030.c
@@ -505,8 +3987,157 @@ enc/trans/gb18030.$(OBJEXT): st.h
enc/trans/gb18030.$(OBJEXT): subst.h
enc/trans/gbk.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/gbk.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/gbk.$(OBJEXT): internal/anyargs.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/gbk.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/gbk.$(OBJEXT): internal/assume.h
+enc/trans/gbk.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/gbk.$(OBJEXT): internal/attr/artificial.h
+enc/trans/gbk.$(OBJEXT): internal/attr/cold.h
+enc/trans/gbk.$(OBJEXT): internal/attr/const.h
+enc/trans/gbk.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/gbk.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/gbk.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/gbk.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/gbk.$(OBJEXT): internal/attr/error.h
+enc/trans/gbk.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/gbk.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/gbk.$(OBJEXT): internal/attr/format.h
+enc/trans/gbk.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/gbk.$(OBJEXT): internal/attr/noalias.h
+enc/trans/gbk.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/gbk.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/gbk.$(OBJEXT): internal/attr/noinline.h
+enc/trans/gbk.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/gbk.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/gbk.$(OBJEXT): internal/attr/pure.h
+enc/trans/gbk.$(OBJEXT): internal/attr/restrict.h
+enc/trans/gbk.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/gbk.$(OBJEXT): internal/attr/warning.h
+enc/trans/gbk.$(OBJEXT): internal/attr/weakref.h
+enc/trans/gbk.$(OBJEXT): internal/cast.h
+enc/trans/gbk.$(OBJEXT): internal/compiler_is.h
+enc/trans/gbk.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/gbk.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/gbk.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/gbk.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/gbk.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/gbk.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/gbk.$(OBJEXT): internal/compiler_since.h
+enc/trans/gbk.$(OBJEXT): internal/config.h
+enc/trans/gbk.$(OBJEXT): internal/constant_p.h
+enc/trans/gbk.$(OBJEXT): internal/core.h
+enc/trans/gbk.$(OBJEXT): internal/core/rarray.h
+enc/trans/gbk.$(OBJEXT): internal/core/rbasic.h
+enc/trans/gbk.$(OBJEXT): internal/core/rbignum.h
+enc/trans/gbk.$(OBJEXT): internal/core/rclass.h
+enc/trans/gbk.$(OBJEXT): internal/core/rdata.h
+enc/trans/gbk.$(OBJEXT): internal/core/rfile.h
+enc/trans/gbk.$(OBJEXT): internal/core/rhash.h
+enc/trans/gbk.$(OBJEXT): internal/core/robject.h
+enc/trans/gbk.$(OBJEXT): internal/core/rregexp.h
+enc/trans/gbk.$(OBJEXT): internal/core/rstring.h
+enc/trans/gbk.$(OBJEXT): internal/core/rstruct.h
+enc/trans/gbk.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/gbk.$(OBJEXT): internal/ctype.h
+enc/trans/gbk.$(OBJEXT): internal/dllexport.h
+enc/trans/gbk.$(OBJEXT): internal/dosish.h
+enc/trans/gbk.$(OBJEXT): internal/error.h
+enc/trans/gbk.$(OBJEXT): internal/eval.h
+enc/trans/gbk.$(OBJEXT): internal/event.h
+enc/trans/gbk.$(OBJEXT): internal/fl_type.h
+enc/trans/gbk.$(OBJEXT): internal/gc.h
+enc/trans/gbk.$(OBJEXT): internal/glob.h
+enc/trans/gbk.$(OBJEXT): internal/globals.h
+enc/trans/gbk.$(OBJEXT): internal/has/attribute.h
+enc/trans/gbk.$(OBJEXT): internal/has/builtin.h
+enc/trans/gbk.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/gbk.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/gbk.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/gbk.$(OBJEXT): internal/has/extension.h
+enc/trans/gbk.$(OBJEXT): internal/has/feature.h
+enc/trans/gbk.$(OBJEXT): internal/has/warning.h
+enc/trans/gbk.$(OBJEXT): internal/intern/array.h
+enc/trans/gbk.$(OBJEXT): internal/intern/bignum.h
+enc/trans/gbk.$(OBJEXT): internal/intern/class.h
+enc/trans/gbk.$(OBJEXT): internal/intern/compar.h
+enc/trans/gbk.$(OBJEXT): internal/intern/complex.h
+enc/trans/gbk.$(OBJEXT): internal/intern/cont.h
+enc/trans/gbk.$(OBJEXT): internal/intern/dir.h
+enc/trans/gbk.$(OBJEXT): internal/intern/enum.h
+enc/trans/gbk.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/gbk.$(OBJEXT): internal/intern/error.h
+enc/trans/gbk.$(OBJEXT): internal/intern/eval.h
+enc/trans/gbk.$(OBJEXT): internal/intern/file.h
+enc/trans/gbk.$(OBJEXT): internal/intern/gc.h
+enc/trans/gbk.$(OBJEXT): internal/intern/hash.h
+enc/trans/gbk.$(OBJEXT): internal/intern/io.h
+enc/trans/gbk.$(OBJEXT): internal/intern/load.h
+enc/trans/gbk.$(OBJEXT): internal/intern/marshal.h
+enc/trans/gbk.$(OBJEXT): internal/intern/numeric.h
+enc/trans/gbk.$(OBJEXT): internal/intern/object.h
+enc/trans/gbk.$(OBJEXT): internal/intern/parse.h
+enc/trans/gbk.$(OBJEXT): internal/intern/proc.h
+enc/trans/gbk.$(OBJEXT): internal/intern/process.h
+enc/trans/gbk.$(OBJEXT): internal/intern/random.h
+enc/trans/gbk.$(OBJEXT): internal/intern/range.h
+enc/trans/gbk.$(OBJEXT): internal/intern/rational.h
+enc/trans/gbk.$(OBJEXT): internal/intern/re.h
+enc/trans/gbk.$(OBJEXT): internal/intern/ruby.h
+enc/trans/gbk.$(OBJEXT): internal/intern/select.h
+enc/trans/gbk.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/gbk.$(OBJEXT): internal/intern/signal.h
+enc/trans/gbk.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/gbk.$(OBJEXT): internal/intern/string.h
+enc/trans/gbk.$(OBJEXT): internal/intern/struct.h
+enc/trans/gbk.$(OBJEXT): internal/intern/thread.h
+enc/trans/gbk.$(OBJEXT): internal/intern/time.h
+enc/trans/gbk.$(OBJEXT): internal/intern/variable.h
+enc/trans/gbk.$(OBJEXT): internal/intern/vm.h
+enc/trans/gbk.$(OBJEXT): internal/interpreter.h
+enc/trans/gbk.$(OBJEXT): internal/iterator.h
+enc/trans/gbk.$(OBJEXT): internal/memory.h
+enc/trans/gbk.$(OBJEXT): internal/method.h
+enc/trans/gbk.$(OBJEXT): internal/module.h
+enc/trans/gbk.$(OBJEXT): internal/newobj.h
+enc/trans/gbk.$(OBJEXT): internal/rgengc.h
+enc/trans/gbk.$(OBJEXT): internal/scan_args.h
+enc/trans/gbk.$(OBJEXT): internal/special_consts.h
+enc/trans/gbk.$(OBJEXT): internal/static_assert.h
+enc/trans/gbk.$(OBJEXT): internal/stdalign.h
+enc/trans/gbk.$(OBJEXT): internal/stdbool.h
+enc/trans/gbk.$(OBJEXT): internal/symbol.h
+enc/trans/gbk.$(OBJEXT): internal/token_paste.h
+enc/trans/gbk.$(OBJEXT): internal/value.h
+enc/trans/gbk.$(OBJEXT): internal/value_type.h
+enc/trans/gbk.$(OBJEXT): internal/variable.h
+enc/trans/gbk.$(OBJEXT): internal/warning_push.h
+enc/trans/gbk.$(OBJEXT): internal/xmalloc.h
enc/trans/gbk.$(OBJEXT): assert.h
enc/trans/gbk.$(OBJEXT): backward.h
+enc/trans/gbk.$(OBJEXT): backward/2/assume.h
+enc/trans/gbk.$(OBJEXT): backward/2/attributes.h
+enc/trans/gbk.$(OBJEXT): backward/2/bool.h
+enc/trans/gbk.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/gbk.$(OBJEXT): backward/2/inttypes.h
+enc/trans/gbk.$(OBJEXT): backward/2/limits.h
+enc/trans/gbk.$(OBJEXT): backward/2/long_long.h
+enc/trans/gbk.$(OBJEXT): backward/2/stdalign.h
+enc/trans/gbk.$(OBJEXT): backward/2/stdarg.h
enc/trans/gbk.$(OBJEXT): config.h
enc/trans/gbk.$(OBJEXT): defines.h
enc/trans/gbk.$(OBJEXT): enc/trans/gbk.c
@@ -516,8 +4147,157 @@ enc/trans/gbk.$(OBJEXT): st.h
enc/trans/gbk.$(OBJEXT): subst.h
enc/trans/iso2022.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/iso2022.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/iso2022.$(OBJEXT): internal/anyargs.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/iso2022.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/iso2022.$(OBJEXT): internal/assume.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/artificial.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/cold.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/const.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/error.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/format.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/noalias.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/noinline.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/pure.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/restrict.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/warning.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/weakref.h
+enc/trans/iso2022.$(OBJEXT): internal/cast.h
+enc/trans/iso2022.$(OBJEXT): internal/compiler_is.h
+enc/trans/iso2022.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/iso2022.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/iso2022.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/iso2022.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/iso2022.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/iso2022.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/iso2022.$(OBJEXT): internal/compiler_since.h
+enc/trans/iso2022.$(OBJEXT): internal/config.h
+enc/trans/iso2022.$(OBJEXT): internal/constant_p.h
+enc/trans/iso2022.$(OBJEXT): internal/core.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rarray.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rbasic.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rbignum.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rclass.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rdata.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rfile.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rhash.h
+enc/trans/iso2022.$(OBJEXT): internal/core/robject.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rregexp.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rstring.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rstruct.h
+enc/trans/iso2022.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/iso2022.$(OBJEXT): internal/ctype.h
+enc/trans/iso2022.$(OBJEXT): internal/dllexport.h
+enc/trans/iso2022.$(OBJEXT): internal/dosish.h
+enc/trans/iso2022.$(OBJEXT): internal/error.h
+enc/trans/iso2022.$(OBJEXT): internal/eval.h
+enc/trans/iso2022.$(OBJEXT): internal/event.h
+enc/trans/iso2022.$(OBJEXT): internal/fl_type.h
+enc/trans/iso2022.$(OBJEXT): internal/gc.h
+enc/trans/iso2022.$(OBJEXT): internal/glob.h
+enc/trans/iso2022.$(OBJEXT): internal/globals.h
+enc/trans/iso2022.$(OBJEXT): internal/has/attribute.h
+enc/trans/iso2022.$(OBJEXT): internal/has/builtin.h
+enc/trans/iso2022.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/iso2022.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/iso2022.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/iso2022.$(OBJEXT): internal/has/extension.h
+enc/trans/iso2022.$(OBJEXT): internal/has/feature.h
+enc/trans/iso2022.$(OBJEXT): internal/has/warning.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/array.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/bignum.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/class.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/compar.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/complex.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/cont.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/dir.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/enum.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/error.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/eval.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/file.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/gc.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/hash.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/io.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/load.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/marshal.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/numeric.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/object.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/parse.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/proc.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/process.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/random.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/range.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/rational.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/re.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/ruby.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/select.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/signal.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/string.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/struct.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/thread.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/time.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/variable.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/vm.h
+enc/trans/iso2022.$(OBJEXT): internal/interpreter.h
+enc/trans/iso2022.$(OBJEXT): internal/iterator.h
+enc/trans/iso2022.$(OBJEXT): internal/memory.h
+enc/trans/iso2022.$(OBJEXT): internal/method.h
+enc/trans/iso2022.$(OBJEXT): internal/module.h
+enc/trans/iso2022.$(OBJEXT): internal/newobj.h
+enc/trans/iso2022.$(OBJEXT): internal/rgengc.h
+enc/trans/iso2022.$(OBJEXT): internal/scan_args.h
+enc/trans/iso2022.$(OBJEXT): internal/special_consts.h
+enc/trans/iso2022.$(OBJEXT): internal/static_assert.h
+enc/trans/iso2022.$(OBJEXT): internal/stdalign.h
+enc/trans/iso2022.$(OBJEXT): internal/stdbool.h
+enc/trans/iso2022.$(OBJEXT): internal/symbol.h
+enc/trans/iso2022.$(OBJEXT): internal/token_paste.h
+enc/trans/iso2022.$(OBJEXT): internal/value.h
+enc/trans/iso2022.$(OBJEXT): internal/value_type.h
+enc/trans/iso2022.$(OBJEXT): internal/variable.h
+enc/trans/iso2022.$(OBJEXT): internal/warning_push.h
+enc/trans/iso2022.$(OBJEXT): internal/xmalloc.h
enc/trans/iso2022.$(OBJEXT): assert.h
enc/trans/iso2022.$(OBJEXT): backward.h
+enc/trans/iso2022.$(OBJEXT): backward/2/assume.h
+enc/trans/iso2022.$(OBJEXT): backward/2/attributes.h
+enc/trans/iso2022.$(OBJEXT): backward/2/bool.h
+enc/trans/iso2022.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/iso2022.$(OBJEXT): backward/2/inttypes.h
+enc/trans/iso2022.$(OBJEXT): backward/2/limits.h
+enc/trans/iso2022.$(OBJEXT): backward/2/long_long.h
+enc/trans/iso2022.$(OBJEXT): backward/2/stdalign.h
+enc/trans/iso2022.$(OBJEXT): backward/2/stdarg.h
enc/trans/iso2022.$(OBJEXT): config.h
enc/trans/iso2022.$(OBJEXT): defines.h
enc/trans/iso2022.$(OBJEXT): enc/trans/iso2022.c
@@ -527,8 +4307,157 @@ enc/trans/iso2022.$(OBJEXT): st.h
enc/trans/iso2022.$(OBJEXT): subst.h
enc/trans/japanese.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/japanese.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/japanese.$(OBJEXT): internal/anyargs.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/japanese.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/japanese.$(OBJEXT): internal/assume.h
+enc/trans/japanese.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/japanese.$(OBJEXT): internal/attr/artificial.h
+enc/trans/japanese.$(OBJEXT): internal/attr/cold.h
+enc/trans/japanese.$(OBJEXT): internal/attr/const.h
+enc/trans/japanese.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/japanese.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/japanese.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/japanese.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/japanese.$(OBJEXT): internal/attr/error.h
+enc/trans/japanese.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/japanese.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/japanese.$(OBJEXT): internal/attr/format.h
+enc/trans/japanese.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/japanese.$(OBJEXT): internal/attr/noalias.h
+enc/trans/japanese.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/japanese.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/japanese.$(OBJEXT): internal/attr/noinline.h
+enc/trans/japanese.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/japanese.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/japanese.$(OBJEXT): internal/attr/pure.h
+enc/trans/japanese.$(OBJEXT): internal/attr/restrict.h
+enc/trans/japanese.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/japanese.$(OBJEXT): internal/attr/warning.h
+enc/trans/japanese.$(OBJEXT): internal/attr/weakref.h
+enc/trans/japanese.$(OBJEXT): internal/cast.h
+enc/trans/japanese.$(OBJEXT): internal/compiler_is.h
+enc/trans/japanese.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/japanese.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/japanese.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/japanese.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/japanese.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/japanese.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/japanese.$(OBJEXT): internal/compiler_since.h
+enc/trans/japanese.$(OBJEXT): internal/config.h
+enc/trans/japanese.$(OBJEXT): internal/constant_p.h
+enc/trans/japanese.$(OBJEXT): internal/core.h
+enc/trans/japanese.$(OBJEXT): internal/core/rarray.h
+enc/trans/japanese.$(OBJEXT): internal/core/rbasic.h
+enc/trans/japanese.$(OBJEXT): internal/core/rbignum.h
+enc/trans/japanese.$(OBJEXT): internal/core/rclass.h
+enc/trans/japanese.$(OBJEXT): internal/core/rdata.h
+enc/trans/japanese.$(OBJEXT): internal/core/rfile.h
+enc/trans/japanese.$(OBJEXT): internal/core/rhash.h
+enc/trans/japanese.$(OBJEXT): internal/core/robject.h
+enc/trans/japanese.$(OBJEXT): internal/core/rregexp.h
+enc/trans/japanese.$(OBJEXT): internal/core/rstring.h
+enc/trans/japanese.$(OBJEXT): internal/core/rstruct.h
+enc/trans/japanese.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/japanese.$(OBJEXT): internal/ctype.h
+enc/trans/japanese.$(OBJEXT): internal/dllexport.h
+enc/trans/japanese.$(OBJEXT): internal/dosish.h
+enc/trans/japanese.$(OBJEXT): internal/error.h
+enc/trans/japanese.$(OBJEXT): internal/eval.h
+enc/trans/japanese.$(OBJEXT): internal/event.h
+enc/trans/japanese.$(OBJEXT): internal/fl_type.h
+enc/trans/japanese.$(OBJEXT): internal/gc.h
+enc/trans/japanese.$(OBJEXT): internal/glob.h
+enc/trans/japanese.$(OBJEXT): internal/globals.h
+enc/trans/japanese.$(OBJEXT): internal/has/attribute.h
+enc/trans/japanese.$(OBJEXT): internal/has/builtin.h
+enc/trans/japanese.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/japanese.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/japanese.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/japanese.$(OBJEXT): internal/has/extension.h
+enc/trans/japanese.$(OBJEXT): internal/has/feature.h
+enc/trans/japanese.$(OBJEXT): internal/has/warning.h
+enc/trans/japanese.$(OBJEXT): internal/intern/array.h
+enc/trans/japanese.$(OBJEXT): internal/intern/bignum.h
+enc/trans/japanese.$(OBJEXT): internal/intern/class.h
+enc/trans/japanese.$(OBJEXT): internal/intern/compar.h
+enc/trans/japanese.$(OBJEXT): internal/intern/complex.h
+enc/trans/japanese.$(OBJEXT): internal/intern/cont.h
+enc/trans/japanese.$(OBJEXT): internal/intern/dir.h
+enc/trans/japanese.$(OBJEXT): internal/intern/enum.h
+enc/trans/japanese.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/japanese.$(OBJEXT): internal/intern/error.h
+enc/trans/japanese.$(OBJEXT): internal/intern/eval.h
+enc/trans/japanese.$(OBJEXT): internal/intern/file.h
+enc/trans/japanese.$(OBJEXT): internal/intern/gc.h
+enc/trans/japanese.$(OBJEXT): internal/intern/hash.h
+enc/trans/japanese.$(OBJEXT): internal/intern/io.h
+enc/trans/japanese.$(OBJEXT): internal/intern/load.h
+enc/trans/japanese.$(OBJEXT): internal/intern/marshal.h
+enc/trans/japanese.$(OBJEXT): internal/intern/numeric.h
+enc/trans/japanese.$(OBJEXT): internal/intern/object.h
+enc/trans/japanese.$(OBJEXT): internal/intern/parse.h
+enc/trans/japanese.$(OBJEXT): internal/intern/proc.h
+enc/trans/japanese.$(OBJEXT): internal/intern/process.h
+enc/trans/japanese.$(OBJEXT): internal/intern/random.h
+enc/trans/japanese.$(OBJEXT): internal/intern/range.h
+enc/trans/japanese.$(OBJEXT): internal/intern/rational.h
+enc/trans/japanese.$(OBJEXT): internal/intern/re.h
+enc/trans/japanese.$(OBJEXT): internal/intern/ruby.h
+enc/trans/japanese.$(OBJEXT): internal/intern/select.h
+enc/trans/japanese.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/japanese.$(OBJEXT): internal/intern/signal.h
+enc/trans/japanese.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/japanese.$(OBJEXT): internal/intern/string.h
+enc/trans/japanese.$(OBJEXT): internal/intern/struct.h
+enc/trans/japanese.$(OBJEXT): internal/intern/thread.h
+enc/trans/japanese.$(OBJEXT): internal/intern/time.h
+enc/trans/japanese.$(OBJEXT): internal/intern/variable.h
+enc/trans/japanese.$(OBJEXT): internal/intern/vm.h
+enc/trans/japanese.$(OBJEXT): internal/interpreter.h
+enc/trans/japanese.$(OBJEXT): internal/iterator.h
+enc/trans/japanese.$(OBJEXT): internal/memory.h
+enc/trans/japanese.$(OBJEXT): internal/method.h
+enc/trans/japanese.$(OBJEXT): internal/module.h
+enc/trans/japanese.$(OBJEXT): internal/newobj.h
+enc/trans/japanese.$(OBJEXT): internal/rgengc.h
+enc/trans/japanese.$(OBJEXT): internal/scan_args.h
+enc/trans/japanese.$(OBJEXT): internal/special_consts.h
+enc/trans/japanese.$(OBJEXT): internal/static_assert.h
+enc/trans/japanese.$(OBJEXT): internal/stdalign.h
+enc/trans/japanese.$(OBJEXT): internal/stdbool.h
+enc/trans/japanese.$(OBJEXT): internal/symbol.h
+enc/trans/japanese.$(OBJEXT): internal/token_paste.h
+enc/trans/japanese.$(OBJEXT): internal/value.h
+enc/trans/japanese.$(OBJEXT): internal/value_type.h
+enc/trans/japanese.$(OBJEXT): internal/variable.h
+enc/trans/japanese.$(OBJEXT): internal/warning_push.h
+enc/trans/japanese.$(OBJEXT): internal/xmalloc.h
enc/trans/japanese.$(OBJEXT): assert.h
enc/trans/japanese.$(OBJEXT): backward.h
+enc/trans/japanese.$(OBJEXT): backward/2/assume.h
+enc/trans/japanese.$(OBJEXT): backward/2/attributes.h
+enc/trans/japanese.$(OBJEXT): backward/2/bool.h
+enc/trans/japanese.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/japanese.$(OBJEXT): backward/2/inttypes.h
+enc/trans/japanese.$(OBJEXT): backward/2/limits.h
+enc/trans/japanese.$(OBJEXT): backward/2/long_long.h
+enc/trans/japanese.$(OBJEXT): backward/2/stdalign.h
+enc/trans/japanese.$(OBJEXT): backward/2/stdarg.h
enc/trans/japanese.$(OBJEXT): config.h
enc/trans/japanese.$(OBJEXT): defines.h
enc/trans/japanese.$(OBJEXT): enc/trans/japanese.c
@@ -538,8 +4467,157 @@ enc/trans/japanese.$(OBJEXT): st.h
enc/trans/japanese.$(OBJEXT): subst.h
enc/trans/japanese_euc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/japanese_euc.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/japanese_euc.$(OBJEXT): internal/anyargs.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/japanese_euc.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/japanese_euc.$(OBJEXT): internal/assume.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/artificial.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/cold.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/const.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/error.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/format.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/noalias.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/noinline.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/pure.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/restrict.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/warning.h
+enc/trans/japanese_euc.$(OBJEXT): internal/attr/weakref.h
+enc/trans/japanese_euc.$(OBJEXT): internal/cast.h
+enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is.h
+enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/japanese_euc.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/japanese_euc.$(OBJEXT): internal/compiler_since.h
+enc/trans/japanese_euc.$(OBJEXT): internal/config.h
+enc/trans/japanese_euc.$(OBJEXT): internal/constant_p.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rarray.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rbasic.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rbignum.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rclass.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rdata.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rfile.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rhash.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/robject.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rregexp.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rstring.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rstruct.h
+enc/trans/japanese_euc.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/japanese_euc.$(OBJEXT): internal/ctype.h
+enc/trans/japanese_euc.$(OBJEXT): internal/dllexport.h
+enc/trans/japanese_euc.$(OBJEXT): internal/dosish.h
+enc/trans/japanese_euc.$(OBJEXT): internal/error.h
+enc/trans/japanese_euc.$(OBJEXT): internal/eval.h
+enc/trans/japanese_euc.$(OBJEXT): internal/event.h
+enc/trans/japanese_euc.$(OBJEXT): internal/fl_type.h
+enc/trans/japanese_euc.$(OBJEXT): internal/gc.h
+enc/trans/japanese_euc.$(OBJEXT): internal/glob.h
+enc/trans/japanese_euc.$(OBJEXT): internal/globals.h
+enc/trans/japanese_euc.$(OBJEXT): internal/has/attribute.h
+enc/trans/japanese_euc.$(OBJEXT): internal/has/builtin.h
+enc/trans/japanese_euc.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/japanese_euc.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/japanese_euc.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/japanese_euc.$(OBJEXT): internal/has/extension.h
+enc/trans/japanese_euc.$(OBJEXT): internal/has/feature.h
+enc/trans/japanese_euc.$(OBJEXT): internal/has/warning.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/array.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/bignum.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/class.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/compar.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/complex.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/cont.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/dir.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/enum.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/error.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/eval.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/file.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/gc.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/hash.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/io.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/load.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/marshal.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/numeric.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/object.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/parse.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/proc.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/process.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/random.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/range.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/rational.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/re.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/ruby.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/select.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/signal.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/string.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/struct.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/thread.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/time.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/variable.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/vm.h
+enc/trans/japanese_euc.$(OBJEXT): internal/interpreter.h
+enc/trans/japanese_euc.$(OBJEXT): internal/iterator.h
+enc/trans/japanese_euc.$(OBJEXT): internal/memory.h
+enc/trans/japanese_euc.$(OBJEXT): internal/method.h
+enc/trans/japanese_euc.$(OBJEXT): internal/module.h
+enc/trans/japanese_euc.$(OBJEXT): internal/newobj.h
+enc/trans/japanese_euc.$(OBJEXT): internal/rgengc.h
+enc/trans/japanese_euc.$(OBJEXT): internal/scan_args.h
+enc/trans/japanese_euc.$(OBJEXT): internal/special_consts.h
+enc/trans/japanese_euc.$(OBJEXT): internal/static_assert.h
+enc/trans/japanese_euc.$(OBJEXT): internal/stdalign.h
+enc/trans/japanese_euc.$(OBJEXT): internal/stdbool.h
+enc/trans/japanese_euc.$(OBJEXT): internal/symbol.h
+enc/trans/japanese_euc.$(OBJEXT): internal/token_paste.h
+enc/trans/japanese_euc.$(OBJEXT): internal/value.h
+enc/trans/japanese_euc.$(OBJEXT): internal/value_type.h
+enc/trans/japanese_euc.$(OBJEXT): internal/variable.h
+enc/trans/japanese_euc.$(OBJEXT): internal/warning_push.h
+enc/trans/japanese_euc.$(OBJEXT): internal/xmalloc.h
enc/trans/japanese_euc.$(OBJEXT): assert.h
enc/trans/japanese_euc.$(OBJEXT): backward.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/assume.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/attributes.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/bool.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/inttypes.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/limits.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/long_long.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/stdalign.h
+enc/trans/japanese_euc.$(OBJEXT): backward/2/stdarg.h
enc/trans/japanese_euc.$(OBJEXT): config.h
enc/trans/japanese_euc.$(OBJEXT): defines.h
enc/trans/japanese_euc.$(OBJEXT): enc/trans/japanese_euc.c
@@ -549,8 +4627,157 @@ enc/trans/japanese_euc.$(OBJEXT): st.h
enc/trans/japanese_euc.$(OBJEXT): subst.h
enc/trans/japanese_sjis.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/japanese_sjis.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/anyargs.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/assume.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/artificial.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/cold.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/const.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/error.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/format.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/noalias.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/noinline.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/pure.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/restrict.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/warning.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/attr/weakref.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/cast.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/compiler_since.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/config.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/constant_p.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rarray.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rbasic.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rbignum.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rclass.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rdata.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rfile.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rhash.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/robject.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rregexp.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rstring.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rstruct.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/ctype.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/dllexport.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/dosish.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/error.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/eval.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/event.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/fl_type.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/gc.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/glob.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/globals.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/has/attribute.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/has/builtin.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/has/extension.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/has/feature.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/has/warning.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/array.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/bignum.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/class.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/compar.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/complex.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/cont.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/dir.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/enum.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/error.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/eval.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/file.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/gc.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/hash.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/io.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/load.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/marshal.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/numeric.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/object.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/parse.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/proc.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/process.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/random.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/range.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/rational.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/re.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/ruby.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/select.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/signal.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/string.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/struct.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/thread.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/time.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/variable.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/vm.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/interpreter.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/iterator.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/memory.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/method.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/module.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/newobj.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/rgengc.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/scan_args.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/special_consts.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/static_assert.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/stdalign.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/stdbool.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/symbol.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/token_paste.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/value.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/value_type.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/variable.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/warning_push.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/xmalloc.h
enc/trans/japanese_sjis.$(OBJEXT): assert.h
enc/trans/japanese_sjis.$(OBJEXT): backward.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/assume.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/attributes.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/bool.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/inttypes.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/limits.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/long_long.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/stdalign.h
+enc/trans/japanese_sjis.$(OBJEXT): backward/2/stdarg.h
enc/trans/japanese_sjis.$(OBJEXT): config.h
enc/trans/japanese_sjis.$(OBJEXT): defines.h
enc/trans/japanese_sjis.$(OBJEXT): enc/trans/japanese_sjis.c
@@ -560,8 +4787,157 @@ enc/trans/japanese_sjis.$(OBJEXT): st.h
enc/trans/japanese_sjis.$(OBJEXT): subst.h
enc/trans/korean.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/korean.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/korean.$(OBJEXT): internal/anyargs.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/korean.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/korean.$(OBJEXT): internal/assume.h
+enc/trans/korean.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/korean.$(OBJEXT): internal/attr/artificial.h
+enc/trans/korean.$(OBJEXT): internal/attr/cold.h
+enc/trans/korean.$(OBJEXT): internal/attr/const.h
+enc/trans/korean.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/korean.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/korean.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/korean.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/korean.$(OBJEXT): internal/attr/error.h
+enc/trans/korean.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/korean.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/korean.$(OBJEXT): internal/attr/format.h
+enc/trans/korean.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/korean.$(OBJEXT): internal/attr/noalias.h
+enc/trans/korean.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/korean.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/korean.$(OBJEXT): internal/attr/noinline.h
+enc/trans/korean.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/korean.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/korean.$(OBJEXT): internal/attr/pure.h
+enc/trans/korean.$(OBJEXT): internal/attr/restrict.h
+enc/trans/korean.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/korean.$(OBJEXT): internal/attr/warning.h
+enc/trans/korean.$(OBJEXT): internal/attr/weakref.h
+enc/trans/korean.$(OBJEXT): internal/cast.h
+enc/trans/korean.$(OBJEXT): internal/compiler_is.h
+enc/trans/korean.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/korean.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/korean.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/korean.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/korean.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/korean.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/korean.$(OBJEXT): internal/compiler_since.h
+enc/trans/korean.$(OBJEXT): internal/config.h
+enc/trans/korean.$(OBJEXT): internal/constant_p.h
+enc/trans/korean.$(OBJEXT): internal/core.h
+enc/trans/korean.$(OBJEXT): internal/core/rarray.h
+enc/trans/korean.$(OBJEXT): internal/core/rbasic.h
+enc/trans/korean.$(OBJEXT): internal/core/rbignum.h
+enc/trans/korean.$(OBJEXT): internal/core/rclass.h
+enc/trans/korean.$(OBJEXT): internal/core/rdata.h
+enc/trans/korean.$(OBJEXT): internal/core/rfile.h
+enc/trans/korean.$(OBJEXT): internal/core/rhash.h
+enc/trans/korean.$(OBJEXT): internal/core/robject.h
+enc/trans/korean.$(OBJEXT): internal/core/rregexp.h
+enc/trans/korean.$(OBJEXT): internal/core/rstring.h
+enc/trans/korean.$(OBJEXT): internal/core/rstruct.h
+enc/trans/korean.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/korean.$(OBJEXT): internal/ctype.h
+enc/trans/korean.$(OBJEXT): internal/dllexport.h
+enc/trans/korean.$(OBJEXT): internal/dosish.h
+enc/trans/korean.$(OBJEXT): internal/error.h
+enc/trans/korean.$(OBJEXT): internal/eval.h
+enc/trans/korean.$(OBJEXT): internal/event.h
+enc/trans/korean.$(OBJEXT): internal/fl_type.h
+enc/trans/korean.$(OBJEXT): internal/gc.h
+enc/trans/korean.$(OBJEXT): internal/glob.h
+enc/trans/korean.$(OBJEXT): internal/globals.h
+enc/trans/korean.$(OBJEXT): internal/has/attribute.h
+enc/trans/korean.$(OBJEXT): internal/has/builtin.h
+enc/trans/korean.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/korean.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/korean.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/korean.$(OBJEXT): internal/has/extension.h
+enc/trans/korean.$(OBJEXT): internal/has/feature.h
+enc/trans/korean.$(OBJEXT): internal/has/warning.h
+enc/trans/korean.$(OBJEXT): internal/intern/array.h
+enc/trans/korean.$(OBJEXT): internal/intern/bignum.h
+enc/trans/korean.$(OBJEXT): internal/intern/class.h
+enc/trans/korean.$(OBJEXT): internal/intern/compar.h
+enc/trans/korean.$(OBJEXT): internal/intern/complex.h
+enc/trans/korean.$(OBJEXT): internal/intern/cont.h
+enc/trans/korean.$(OBJEXT): internal/intern/dir.h
+enc/trans/korean.$(OBJEXT): internal/intern/enum.h
+enc/trans/korean.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/korean.$(OBJEXT): internal/intern/error.h
+enc/trans/korean.$(OBJEXT): internal/intern/eval.h
+enc/trans/korean.$(OBJEXT): internal/intern/file.h
+enc/trans/korean.$(OBJEXT): internal/intern/gc.h
+enc/trans/korean.$(OBJEXT): internal/intern/hash.h
+enc/trans/korean.$(OBJEXT): internal/intern/io.h
+enc/trans/korean.$(OBJEXT): internal/intern/load.h
+enc/trans/korean.$(OBJEXT): internal/intern/marshal.h
+enc/trans/korean.$(OBJEXT): internal/intern/numeric.h
+enc/trans/korean.$(OBJEXT): internal/intern/object.h
+enc/trans/korean.$(OBJEXT): internal/intern/parse.h
+enc/trans/korean.$(OBJEXT): internal/intern/proc.h
+enc/trans/korean.$(OBJEXT): internal/intern/process.h
+enc/trans/korean.$(OBJEXT): internal/intern/random.h
+enc/trans/korean.$(OBJEXT): internal/intern/range.h
+enc/trans/korean.$(OBJEXT): internal/intern/rational.h
+enc/trans/korean.$(OBJEXT): internal/intern/re.h
+enc/trans/korean.$(OBJEXT): internal/intern/ruby.h
+enc/trans/korean.$(OBJEXT): internal/intern/select.h
+enc/trans/korean.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/korean.$(OBJEXT): internal/intern/signal.h
+enc/trans/korean.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/korean.$(OBJEXT): internal/intern/string.h
+enc/trans/korean.$(OBJEXT): internal/intern/struct.h
+enc/trans/korean.$(OBJEXT): internal/intern/thread.h
+enc/trans/korean.$(OBJEXT): internal/intern/time.h
+enc/trans/korean.$(OBJEXT): internal/intern/variable.h
+enc/trans/korean.$(OBJEXT): internal/intern/vm.h
+enc/trans/korean.$(OBJEXT): internal/interpreter.h
+enc/trans/korean.$(OBJEXT): internal/iterator.h
+enc/trans/korean.$(OBJEXT): internal/memory.h
+enc/trans/korean.$(OBJEXT): internal/method.h
+enc/trans/korean.$(OBJEXT): internal/module.h
+enc/trans/korean.$(OBJEXT): internal/newobj.h
+enc/trans/korean.$(OBJEXT): internal/rgengc.h
+enc/trans/korean.$(OBJEXT): internal/scan_args.h
+enc/trans/korean.$(OBJEXT): internal/special_consts.h
+enc/trans/korean.$(OBJEXT): internal/static_assert.h
+enc/trans/korean.$(OBJEXT): internal/stdalign.h
+enc/trans/korean.$(OBJEXT): internal/stdbool.h
+enc/trans/korean.$(OBJEXT): internal/symbol.h
+enc/trans/korean.$(OBJEXT): internal/token_paste.h
+enc/trans/korean.$(OBJEXT): internal/value.h
+enc/trans/korean.$(OBJEXT): internal/value_type.h
+enc/trans/korean.$(OBJEXT): internal/variable.h
+enc/trans/korean.$(OBJEXT): internal/warning_push.h
+enc/trans/korean.$(OBJEXT): internal/xmalloc.h
enc/trans/korean.$(OBJEXT): assert.h
enc/trans/korean.$(OBJEXT): backward.h
+enc/trans/korean.$(OBJEXT): backward/2/assume.h
+enc/trans/korean.$(OBJEXT): backward/2/attributes.h
+enc/trans/korean.$(OBJEXT): backward/2/bool.h
+enc/trans/korean.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/korean.$(OBJEXT): backward/2/inttypes.h
+enc/trans/korean.$(OBJEXT): backward/2/limits.h
+enc/trans/korean.$(OBJEXT): backward/2/long_long.h
+enc/trans/korean.$(OBJEXT): backward/2/stdalign.h
+enc/trans/korean.$(OBJEXT): backward/2/stdarg.h
enc/trans/korean.$(OBJEXT): config.h
enc/trans/korean.$(OBJEXT): defines.h
enc/trans/korean.$(OBJEXT): enc/trans/korean.c
@@ -571,7 +4947,156 @@ enc/trans/korean.$(OBJEXT): st.h
enc/trans/korean.$(OBJEXT): subst.h
enc/trans/newline.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/newline.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/newline.$(OBJEXT): internal/anyargs.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/newline.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/newline.$(OBJEXT): internal/assume.h
+enc/trans/newline.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/newline.$(OBJEXT): internal/attr/artificial.h
+enc/trans/newline.$(OBJEXT): internal/attr/cold.h
+enc/trans/newline.$(OBJEXT): internal/attr/const.h
+enc/trans/newline.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/newline.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/newline.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/newline.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/newline.$(OBJEXT): internal/attr/error.h
+enc/trans/newline.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/newline.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/newline.$(OBJEXT): internal/attr/format.h
+enc/trans/newline.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/newline.$(OBJEXT): internal/attr/noalias.h
+enc/trans/newline.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/newline.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/newline.$(OBJEXT): internal/attr/noinline.h
+enc/trans/newline.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/newline.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/newline.$(OBJEXT): internal/attr/pure.h
+enc/trans/newline.$(OBJEXT): internal/attr/restrict.h
+enc/trans/newline.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/newline.$(OBJEXT): internal/attr/warning.h
+enc/trans/newline.$(OBJEXT): internal/attr/weakref.h
+enc/trans/newline.$(OBJEXT): internal/cast.h
+enc/trans/newline.$(OBJEXT): internal/compiler_is.h
+enc/trans/newline.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/newline.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/newline.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/newline.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/newline.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/newline.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/newline.$(OBJEXT): internal/compiler_since.h
+enc/trans/newline.$(OBJEXT): internal/config.h
+enc/trans/newline.$(OBJEXT): internal/constant_p.h
+enc/trans/newline.$(OBJEXT): internal/core.h
+enc/trans/newline.$(OBJEXT): internal/core/rarray.h
+enc/trans/newline.$(OBJEXT): internal/core/rbasic.h
+enc/trans/newline.$(OBJEXT): internal/core/rbignum.h
+enc/trans/newline.$(OBJEXT): internal/core/rclass.h
+enc/trans/newline.$(OBJEXT): internal/core/rdata.h
+enc/trans/newline.$(OBJEXT): internal/core/rfile.h
+enc/trans/newline.$(OBJEXT): internal/core/rhash.h
+enc/trans/newline.$(OBJEXT): internal/core/robject.h
+enc/trans/newline.$(OBJEXT): internal/core/rregexp.h
+enc/trans/newline.$(OBJEXT): internal/core/rstring.h
+enc/trans/newline.$(OBJEXT): internal/core/rstruct.h
+enc/trans/newline.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/newline.$(OBJEXT): internal/ctype.h
+enc/trans/newline.$(OBJEXT): internal/dllexport.h
+enc/trans/newline.$(OBJEXT): internal/dosish.h
+enc/trans/newline.$(OBJEXT): internal/error.h
+enc/trans/newline.$(OBJEXT): internal/eval.h
+enc/trans/newline.$(OBJEXT): internal/event.h
+enc/trans/newline.$(OBJEXT): internal/fl_type.h
+enc/trans/newline.$(OBJEXT): internal/gc.h
+enc/trans/newline.$(OBJEXT): internal/glob.h
+enc/trans/newline.$(OBJEXT): internal/globals.h
+enc/trans/newline.$(OBJEXT): internal/has/attribute.h
+enc/trans/newline.$(OBJEXT): internal/has/builtin.h
+enc/trans/newline.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/newline.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/newline.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/newline.$(OBJEXT): internal/has/extension.h
+enc/trans/newline.$(OBJEXT): internal/has/feature.h
+enc/trans/newline.$(OBJEXT): internal/has/warning.h
+enc/trans/newline.$(OBJEXT): internal/intern/array.h
+enc/trans/newline.$(OBJEXT): internal/intern/bignum.h
+enc/trans/newline.$(OBJEXT): internal/intern/class.h
+enc/trans/newline.$(OBJEXT): internal/intern/compar.h
+enc/trans/newline.$(OBJEXT): internal/intern/complex.h
+enc/trans/newline.$(OBJEXT): internal/intern/cont.h
+enc/trans/newline.$(OBJEXT): internal/intern/dir.h
+enc/trans/newline.$(OBJEXT): internal/intern/enum.h
+enc/trans/newline.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/newline.$(OBJEXT): internal/intern/error.h
+enc/trans/newline.$(OBJEXT): internal/intern/eval.h
+enc/trans/newline.$(OBJEXT): internal/intern/file.h
+enc/trans/newline.$(OBJEXT): internal/intern/gc.h
+enc/trans/newline.$(OBJEXT): internal/intern/hash.h
+enc/trans/newline.$(OBJEXT): internal/intern/io.h
+enc/trans/newline.$(OBJEXT): internal/intern/load.h
+enc/trans/newline.$(OBJEXT): internal/intern/marshal.h
+enc/trans/newline.$(OBJEXT): internal/intern/numeric.h
+enc/trans/newline.$(OBJEXT): internal/intern/object.h
+enc/trans/newline.$(OBJEXT): internal/intern/parse.h
+enc/trans/newline.$(OBJEXT): internal/intern/proc.h
+enc/trans/newline.$(OBJEXT): internal/intern/process.h
+enc/trans/newline.$(OBJEXT): internal/intern/random.h
+enc/trans/newline.$(OBJEXT): internal/intern/range.h
+enc/trans/newline.$(OBJEXT): internal/intern/rational.h
+enc/trans/newline.$(OBJEXT): internal/intern/re.h
+enc/trans/newline.$(OBJEXT): internal/intern/ruby.h
+enc/trans/newline.$(OBJEXT): internal/intern/select.h
+enc/trans/newline.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/newline.$(OBJEXT): internal/intern/signal.h
+enc/trans/newline.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/newline.$(OBJEXT): internal/intern/string.h
+enc/trans/newline.$(OBJEXT): internal/intern/struct.h
+enc/trans/newline.$(OBJEXT): internal/intern/thread.h
+enc/trans/newline.$(OBJEXT): internal/intern/time.h
+enc/trans/newline.$(OBJEXT): internal/intern/variable.h
+enc/trans/newline.$(OBJEXT): internal/intern/vm.h
+enc/trans/newline.$(OBJEXT): internal/interpreter.h
+enc/trans/newline.$(OBJEXT): internal/iterator.h
+enc/trans/newline.$(OBJEXT): internal/memory.h
+enc/trans/newline.$(OBJEXT): internal/method.h
+enc/trans/newline.$(OBJEXT): internal/module.h
+enc/trans/newline.$(OBJEXT): internal/newobj.h
+enc/trans/newline.$(OBJEXT): internal/rgengc.h
+enc/trans/newline.$(OBJEXT): internal/scan_args.h
+enc/trans/newline.$(OBJEXT): internal/special_consts.h
+enc/trans/newline.$(OBJEXT): internal/static_assert.h
+enc/trans/newline.$(OBJEXT): internal/stdalign.h
+enc/trans/newline.$(OBJEXT): internal/stdbool.h
+enc/trans/newline.$(OBJEXT): internal/symbol.h
+enc/trans/newline.$(OBJEXT): internal/token_paste.h
+enc/trans/newline.$(OBJEXT): internal/value.h
+enc/trans/newline.$(OBJEXT): internal/value_type.h
+enc/trans/newline.$(OBJEXT): internal/variable.h
+enc/trans/newline.$(OBJEXT): internal/warning_push.h
+enc/trans/newline.$(OBJEXT): internal/xmalloc.h
enc/trans/newline.$(OBJEXT): assert.h
+enc/trans/newline.$(OBJEXT): backward/2/assume.h
+enc/trans/newline.$(OBJEXT): backward/2/attributes.h
+enc/trans/newline.$(OBJEXT): backward/2/bool.h
+enc/trans/newline.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/newline.$(OBJEXT): backward/2/inttypes.h
+enc/trans/newline.$(OBJEXT): backward/2/limits.h
+enc/trans/newline.$(OBJEXT): backward/2/long_long.h
+enc/trans/newline.$(OBJEXT): backward/2/stdalign.h
+enc/trans/newline.$(OBJEXT): backward/2/stdarg.h
enc/trans/newline.$(OBJEXT): config.h
enc/trans/newline.$(OBJEXT): defines.h
enc/trans/newline.$(OBJEXT): enc/trans/newline.c
@@ -581,8 +5106,157 @@ enc/trans/newline.$(OBJEXT): st.h
enc/trans/newline.$(OBJEXT): subst.h
enc/trans/single_byte.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/single_byte.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/single_byte.$(OBJEXT): internal/anyargs.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/single_byte.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/single_byte.$(OBJEXT): internal/assume.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/artificial.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/cold.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/const.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/error.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/format.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/noalias.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/noinline.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/pure.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/restrict.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/warning.h
+enc/trans/single_byte.$(OBJEXT): internal/attr/weakref.h
+enc/trans/single_byte.$(OBJEXT): internal/cast.h
+enc/trans/single_byte.$(OBJEXT): internal/compiler_is.h
+enc/trans/single_byte.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/single_byte.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/single_byte.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/single_byte.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/single_byte.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/single_byte.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/single_byte.$(OBJEXT): internal/compiler_since.h
+enc/trans/single_byte.$(OBJEXT): internal/config.h
+enc/trans/single_byte.$(OBJEXT): internal/constant_p.h
+enc/trans/single_byte.$(OBJEXT): internal/core.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rarray.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rbasic.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rbignum.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rclass.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rdata.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rfile.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rhash.h
+enc/trans/single_byte.$(OBJEXT): internal/core/robject.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rregexp.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rstring.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rstruct.h
+enc/trans/single_byte.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/single_byte.$(OBJEXT): internal/ctype.h
+enc/trans/single_byte.$(OBJEXT): internal/dllexport.h
+enc/trans/single_byte.$(OBJEXT): internal/dosish.h
+enc/trans/single_byte.$(OBJEXT): internal/error.h
+enc/trans/single_byte.$(OBJEXT): internal/eval.h
+enc/trans/single_byte.$(OBJEXT): internal/event.h
+enc/trans/single_byte.$(OBJEXT): internal/fl_type.h
+enc/trans/single_byte.$(OBJEXT): internal/gc.h
+enc/trans/single_byte.$(OBJEXT): internal/glob.h
+enc/trans/single_byte.$(OBJEXT): internal/globals.h
+enc/trans/single_byte.$(OBJEXT): internal/has/attribute.h
+enc/trans/single_byte.$(OBJEXT): internal/has/builtin.h
+enc/trans/single_byte.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/single_byte.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/single_byte.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/single_byte.$(OBJEXT): internal/has/extension.h
+enc/trans/single_byte.$(OBJEXT): internal/has/feature.h
+enc/trans/single_byte.$(OBJEXT): internal/has/warning.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/array.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/bignum.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/class.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/compar.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/complex.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/cont.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/dir.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/enum.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/error.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/eval.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/file.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/gc.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/hash.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/io.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/load.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/marshal.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/numeric.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/object.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/parse.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/proc.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/process.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/random.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/range.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/rational.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/re.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/ruby.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/select.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/signal.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/string.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/struct.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/thread.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/time.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/variable.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/vm.h
+enc/trans/single_byte.$(OBJEXT): internal/interpreter.h
+enc/trans/single_byte.$(OBJEXT): internal/iterator.h
+enc/trans/single_byte.$(OBJEXT): internal/memory.h
+enc/trans/single_byte.$(OBJEXT): internal/method.h
+enc/trans/single_byte.$(OBJEXT): internal/module.h
+enc/trans/single_byte.$(OBJEXT): internal/newobj.h
+enc/trans/single_byte.$(OBJEXT): internal/rgengc.h
+enc/trans/single_byte.$(OBJEXT): internal/scan_args.h
+enc/trans/single_byte.$(OBJEXT): internal/special_consts.h
+enc/trans/single_byte.$(OBJEXT): internal/static_assert.h
+enc/trans/single_byte.$(OBJEXT): internal/stdalign.h
+enc/trans/single_byte.$(OBJEXT): internal/stdbool.h
+enc/trans/single_byte.$(OBJEXT): internal/symbol.h
+enc/trans/single_byte.$(OBJEXT): internal/token_paste.h
+enc/trans/single_byte.$(OBJEXT): internal/value.h
+enc/trans/single_byte.$(OBJEXT): internal/value_type.h
+enc/trans/single_byte.$(OBJEXT): internal/variable.h
+enc/trans/single_byte.$(OBJEXT): internal/warning_push.h
+enc/trans/single_byte.$(OBJEXT): internal/xmalloc.h
enc/trans/single_byte.$(OBJEXT): assert.h
enc/trans/single_byte.$(OBJEXT): backward.h
+enc/trans/single_byte.$(OBJEXT): backward/2/assume.h
+enc/trans/single_byte.$(OBJEXT): backward/2/attributes.h
+enc/trans/single_byte.$(OBJEXT): backward/2/bool.h
+enc/trans/single_byte.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/single_byte.$(OBJEXT): backward/2/inttypes.h
+enc/trans/single_byte.$(OBJEXT): backward/2/limits.h
+enc/trans/single_byte.$(OBJEXT): backward/2/long_long.h
+enc/trans/single_byte.$(OBJEXT): backward/2/stdalign.h
+enc/trans/single_byte.$(OBJEXT): backward/2/stdarg.h
enc/trans/single_byte.$(OBJEXT): config.h
enc/trans/single_byte.$(OBJEXT): defines.h
enc/trans/single_byte.$(OBJEXT): enc/trans/single_byte.c
@@ -594,8 +5268,157 @@ enc/trans/transdb.$(OBJEXT): enc/trans/transdb.c
enc/trans/transdb.$(OBJEXT): transdb.h
enc/trans/utf8_mac.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/utf8_mac.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/utf8_mac.$(OBJEXT): internal/anyargs.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/utf8_mac.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/utf8_mac.$(OBJEXT): internal/assume.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/artificial.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/cold.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/const.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/error.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/format.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/noalias.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/noinline.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/pure.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/restrict.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/warning.h
+enc/trans/utf8_mac.$(OBJEXT): internal/attr/weakref.h
+enc/trans/utf8_mac.$(OBJEXT): internal/cast.h
+enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is.h
+enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/utf8_mac.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/utf8_mac.$(OBJEXT): internal/compiler_since.h
+enc/trans/utf8_mac.$(OBJEXT): internal/config.h
+enc/trans/utf8_mac.$(OBJEXT): internal/constant_p.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rarray.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rbasic.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rbignum.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rclass.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rdata.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rfile.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rhash.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/robject.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rregexp.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rstring.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rstruct.h
+enc/trans/utf8_mac.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/utf8_mac.$(OBJEXT): internal/ctype.h
+enc/trans/utf8_mac.$(OBJEXT): internal/dllexport.h
+enc/trans/utf8_mac.$(OBJEXT): internal/dosish.h
+enc/trans/utf8_mac.$(OBJEXT): internal/error.h
+enc/trans/utf8_mac.$(OBJEXT): internal/eval.h
+enc/trans/utf8_mac.$(OBJEXT): internal/event.h
+enc/trans/utf8_mac.$(OBJEXT): internal/fl_type.h
+enc/trans/utf8_mac.$(OBJEXT): internal/gc.h
+enc/trans/utf8_mac.$(OBJEXT): internal/glob.h
+enc/trans/utf8_mac.$(OBJEXT): internal/globals.h
+enc/trans/utf8_mac.$(OBJEXT): internal/has/attribute.h
+enc/trans/utf8_mac.$(OBJEXT): internal/has/builtin.h
+enc/trans/utf8_mac.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/utf8_mac.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/utf8_mac.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/utf8_mac.$(OBJEXT): internal/has/extension.h
+enc/trans/utf8_mac.$(OBJEXT): internal/has/feature.h
+enc/trans/utf8_mac.$(OBJEXT): internal/has/warning.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/array.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/bignum.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/class.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/compar.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/complex.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/cont.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/dir.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/enum.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/error.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/eval.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/file.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/gc.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/hash.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/io.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/load.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/marshal.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/numeric.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/object.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/parse.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/proc.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/process.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/random.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/range.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/rational.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/re.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/ruby.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/select.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/signal.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/string.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/struct.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/thread.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/time.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/variable.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/vm.h
+enc/trans/utf8_mac.$(OBJEXT): internal/interpreter.h
+enc/trans/utf8_mac.$(OBJEXT): internal/iterator.h
+enc/trans/utf8_mac.$(OBJEXT): internal/memory.h
+enc/trans/utf8_mac.$(OBJEXT): internal/method.h
+enc/trans/utf8_mac.$(OBJEXT): internal/module.h
+enc/trans/utf8_mac.$(OBJEXT): internal/newobj.h
+enc/trans/utf8_mac.$(OBJEXT): internal/rgengc.h
+enc/trans/utf8_mac.$(OBJEXT): internal/scan_args.h
+enc/trans/utf8_mac.$(OBJEXT): internal/special_consts.h
+enc/trans/utf8_mac.$(OBJEXT): internal/static_assert.h
+enc/trans/utf8_mac.$(OBJEXT): internal/stdalign.h
+enc/trans/utf8_mac.$(OBJEXT): internal/stdbool.h
+enc/trans/utf8_mac.$(OBJEXT): internal/symbol.h
+enc/trans/utf8_mac.$(OBJEXT): internal/token_paste.h
+enc/trans/utf8_mac.$(OBJEXT): internal/value.h
+enc/trans/utf8_mac.$(OBJEXT): internal/value_type.h
+enc/trans/utf8_mac.$(OBJEXT): internal/variable.h
+enc/trans/utf8_mac.$(OBJEXT): internal/warning_push.h
+enc/trans/utf8_mac.$(OBJEXT): internal/xmalloc.h
enc/trans/utf8_mac.$(OBJEXT): assert.h
enc/trans/utf8_mac.$(OBJEXT): backward.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/assume.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/attributes.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/bool.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/inttypes.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/limits.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/long_long.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/stdalign.h
+enc/trans/utf8_mac.$(OBJEXT): backward/2/stdarg.h
enc/trans/utf8_mac.$(OBJEXT): config.h
enc/trans/utf8_mac.$(OBJEXT): defines.h
enc/trans/utf8_mac.$(OBJEXT): enc/trans/utf8_mac.c
@@ -605,8 +5428,157 @@ enc/trans/utf8_mac.$(OBJEXT): st.h
enc/trans/utf8_mac.$(OBJEXT): subst.h
enc/trans/utf_16_32.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/trans/utf_16_32.$(OBJEXT): $(top_srcdir)/transcode_data.h
+enc/trans/utf_16_32.$(OBJEXT): internal/anyargs.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/char.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/double.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/int.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/long.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/long_long.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/off_t.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/short.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/size_t.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/trans/utf_16_32.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/trans/utf_16_32.$(OBJEXT): internal/assume.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/alloc_size.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/artificial.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/cold.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/const.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/constexpr.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/deprecated.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/diagnose_if.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/error.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/flag_enum.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/forceinline.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/format.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/maybe_unused.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/noalias.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/nodiscard.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/noexcept.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/noinline.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/noreturn.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/pure.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/restrict.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/warning.h
+enc/trans/utf_16_32.$(OBJEXT): internal/attr/weakref.h
+enc/trans/utf_16_32.$(OBJEXT): internal/cast.h
+enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is.h
+enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/apple.h
+enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/clang.h
+enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/gcc.h
+enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/intel.h
+enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/msvc.h
+enc/trans/utf_16_32.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/trans/utf_16_32.$(OBJEXT): internal/compiler_since.h
+enc/trans/utf_16_32.$(OBJEXT): internal/config.h
+enc/trans/utf_16_32.$(OBJEXT): internal/constant_p.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rarray.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rbasic.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rbignum.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rclass.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rdata.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rfile.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rhash.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/robject.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rregexp.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rstring.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rstruct.h
+enc/trans/utf_16_32.$(OBJEXT): internal/core/rtypeddata.h
+enc/trans/utf_16_32.$(OBJEXT): internal/ctype.h
+enc/trans/utf_16_32.$(OBJEXT): internal/dllexport.h
+enc/trans/utf_16_32.$(OBJEXT): internal/dosish.h
+enc/trans/utf_16_32.$(OBJEXT): internal/error.h
+enc/trans/utf_16_32.$(OBJEXT): internal/eval.h
+enc/trans/utf_16_32.$(OBJEXT): internal/event.h
+enc/trans/utf_16_32.$(OBJEXT): internal/fl_type.h
+enc/trans/utf_16_32.$(OBJEXT): internal/gc.h
+enc/trans/utf_16_32.$(OBJEXT): internal/glob.h
+enc/trans/utf_16_32.$(OBJEXT): internal/globals.h
+enc/trans/utf_16_32.$(OBJEXT): internal/has/attribute.h
+enc/trans/utf_16_32.$(OBJEXT): internal/has/builtin.h
+enc/trans/utf_16_32.$(OBJEXT): internal/has/c_attribute.h
+enc/trans/utf_16_32.$(OBJEXT): internal/has/cpp_attribute.h
+enc/trans/utf_16_32.$(OBJEXT): internal/has/declspec_attribute.h
+enc/trans/utf_16_32.$(OBJEXT): internal/has/extension.h
+enc/trans/utf_16_32.$(OBJEXT): internal/has/feature.h
+enc/trans/utf_16_32.$(OBJEXT): internal/has/warning.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/array.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/bignum.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/class.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/compar.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/complex.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/cont.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/dir.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/enum.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/enumerator.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/error.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/eval.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/file.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/gc.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/hash.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/io.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/load.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/marshal.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/numeric.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/object.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/parse.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/proc.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/process.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/random.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/range.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/rational.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/re.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/ruby.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/select.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/signal.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/sprintf.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/string.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/struct.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/thread.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/time.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/variable.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/vm.h
+enc/trans/utf_16_32.$(OBJEXT): internal/interpreter.h
+enc/trans/utf_16_32.$(OBJEXT): internal/iterator.h
+enc/trans/utf_16_32.$(OBJEXT): internal/memory.h
+enc/trans/utf_16_32.$(OBJEXT): internal/method.h
+enc/trans/utf_16_32.$(OBJEXT): internal/module.h
+enc/trans/utf_16_32.$(OBJEXT): internal/newobj.h
+enc/trans/utf_16_32.$(OBJEXT): internal/rgengc.h
+enc/trans/utf_16_32.$(OBJEXT): internal/scan_args.h
+enc/trans/utf_16_32.$(OBJEXT): internal/special_consts.h
+enc/trans/utf_16_32.$(OBJEXT): internal/static_assert.h
+enc/trans/utf_16_32.$(OBJEXT): internal/stdalign.h
+enc/trans/utf_16_32.$(OBJEXT): internal/stdbool.h
+enc/trans/utf_16_32.$(OBJEXT): internal/symbol.h
+enc/trans/utf_16_32.$(OBJEXT): internal/token_paste.h
+enc/trans/utf_16_32.$(OBJEXT): internal/value.h
+enc/trans/utf_16_32.$(OBJEXT): internal/value_type.h
+enc/trans/utf_16_32.$(OBJEXT): internal/variable.h
+enc/trans/utf_16_32.$(OBJEXT): internal/warning_push.h
+enc/trans/utf_16_32.$(OBJEXT): internal/xmalloc.h
enc/trans/utf_16_32.$(OBJEXT): assert.h
enc/trans/utf_16_32.$(OBJEXT): backward.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/assume.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/attributes.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/bool.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/gcc_version_since.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/inttypes.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/limits.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/long_long.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/stdalign.h
+enc/trans/utf_16_32.$(OBJEXT): backward/2/stdarg.h
enc/trans/utf_16_32.$(OBJEXT): config.h
enc/trans/utf_16_32.$(OBJEXT): defines.h
enc/trans/utf_16_32.$(OBJEXT): enc/trans/utf_16_32.c
@@ -619,7 +5591,156 @@ enc/unicode.$(OBJEXT): $(UNICODE_HDR_DIR)/name2ctype.h
enc/unicode.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/unicode.$(OBJEXT): $(top_srcdir)/regenc.h
enc/unicode.$(OBJEXT): $(top_srcdir)/regint.h
+enc/unicode.$(OBJEXT): internal/anyargs.h
+enc/unicode.$(OBJEXT): internal/arithmetic.h
+enc/unicode.$(OBJEXT): internal/arithmetic/char.h
+enc/unicode.$(OBJEXT): internal/arithmetic/double.h
+enc/unicode.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/unicode.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/unicode.$(OBJEXT): internal/arithmetic/int.h
+enc/unicode.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/unicode.$(OBJEXT): internal/arithmetic/long.h
+enc/unicode.$(OBJEXT): internal/arithmetic/long_long.h
+enc/unicode.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/unicode.$(OBJEXT): internal/arithmetic/off_t.h
+enc/unicode.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/unicode.$(OBJEXT): internal/arithmetic/short.h
+enc/unicode.$(OBJEXT): internal/arithmetic/size_t.h
+enc/unicode.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/unicode.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/unicode.$(OBJEXT): internal/assume.h
+enc/unicode.$(OBJEXT): internal/attr/alloc_size.h
+enc/unicode.$(OBJEXT): internal/attr/artificial.h
+enc/unicode.$(OBJEXT): internal/attr/cold.h
+enc/unicode.$(OBJEXT): internal/attr/const.h
+enc/unicode.$(OBJEXT): internal/attr/constexpr.h
+enc/unicode.$(OBJEXT): internal/attr/deprecated.h
+enc/unicode.$(OBJEXT): internal/attr/diagnose_if.h
+enc/unicode.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/unicode.$(OBJEXT): internal/attr/error.h
+enc/unicode.$(OBJEXT): internal/attr/flag_enum.h
+enc/unicode.$(OBJEXT): internal/attr/forceinline.h
+enc/unicode.$(OBJEXT): internal/attr/format.h
+enc/unicode.$(OBJEXT): internal/attr/maybe_unused.h
+enc/unicode.$(OBJEXT): internal/attr/noalias.h
+enc/unicode.$(OBJEXT): internal/attr/nodiscard.h
+enc/unicode.$(OBJEXT): internal/attr/noexcept.h
+enc/unicode.$(OBJEXT): internal/attr/noinline.h
+enc/unicode.$(OBJEXT): internal/attr/nonnull.h
+enc/unicode.$(OBJEXT): internal/attr/noreturn.h
+enc/unicode.$(OBJEXT): internal/attr/pure.h
+enc/unicode.$(OBJEXT): internal/attr/restrict.h
+enc/unicode.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/unicode.$(OBJEXT): internal/attr/warning.h
+enc/unicode.$(OBJEXT): internal/attr/weakref.h
+enc/unicode.$(OBJEXT): internal/cast.h
+enc/unicode.$(OBJEXT): internal/compiler_is.h
+enc/unicode.$(OBJEXT): internal/compiler_is/apple.h
+enc/unicode.$(OBJEXT): internal/compiler_is/clang.h
+enc/unicode.$(OBJEXT): internal/compiler_is/gcc.h
+enc/unicode.$(OBJEXT): internal/compiler_is/intel.h
+enc/unicode.$(OBJEXT): internal/compiler_is/msvc.h
+enc/unicode.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/unicode.$(OBJEXT): internal/compiler_since.h
+enc/unicode.$(OBJEXT): internal/config.h
+enc/unicode.$(OBJEXT): internal/constant_p.h
+enc/unicode.$(OBJEXT): internal/core.h
+enc/unicode.$(OBJEXT): internal/core/rarray.h
+enc/unicode.$(OBJEXT): internal/core/rbasic.h
+enc/unicode.$(OBJEXT): internal/core/rbignum.h
+enc/unicode.$(OBJEXT): internal/core/rclass.h
+enc/unicode.$(OBJEXT): internal/core/rdata.h
+enc/unicode.$(OBJEXT): internal/core/rfile.h
+enc/unicode.$(OBJEXT): internal/core/rhash.h
+enc/unicode.$(OBJEXT): internal/core/robject.h
+enc/unicode.$(OBJEXT): internal/core/rregexp.h
+enc/unicode.$(OBJEXT): internal/core/rstring.h
+enc/unicode.$(OBJEXT): internal/core/rstruct.h
+enc/unicode.$(OBJEXT): internal/core/rtypeddata.h
+enc/unicode.$(OBJEXT): internal/ctype.h
+enc/unicode.$(OBJEXT): internal/dllexport.h
+enc/unicode.$(OBJEXT): internal/dosish.h
+enc/unicode.$(OBJEXT): internal/error.h
+enc/unicode.$(OBJEXT): internal/eval.h
+enc/unicode.$(OBJEXT): internal/event.h
+enc/unicode.$(OBJEXT): internal/fl_type.h
+enc/unicode.$(OBJEXT): internal/gc.h
+enc/unicode.$(OBJEXT): internal/glob.h
+enc/unicode.$(OBJEXT): internal/globals.h
+enc/unicode.$(OBJEXT): internal/has/attribute.h
+enc/unicode.$(OBJEXT): internal/has/builtin.h
+enc/unicode.$(OBJEXT): internal/has/c_attribute.h
+enc/unicode.$(OBJEXT): internal/has/cpp_attribute.h
+enc/unicode.$(OBJEXT): internal/has/declspec_attribute.h
+enc/unicode.$(OBJEXT): internal/has/extension.h
+enc/unicode.$(OBJEXT): internal/has/feature.h
+enc/unicode.$(OBJEXT): internal/has/warning.h
+enc/unicode.$(OBJEXT): internal/intern/array.h
+enc/unicode.$(OBJEXT): internal/intern/bignum.h
+enc/unicode.$(OBJEXT): internal/intern/class.h
+enc/unicode.$(OBJEXT): internal/intern/compar.h
+enc/unicode.$(OBJEXT): internal/intern/complex.h
+enc/unicode.$(OBJEXT): internal/intern/cont.h
+enc/unicode.$(OBJEXT): internal/intern/dir.h
+enc/unicode.$(OBJEXT): internal/intern/enum.h
+enc/unicode.$(OBJEXT): internal/intern/enumerator.h
+enc/unicode.$(OBJEXT): internal/intern/error.h
+enc/unicode.$(OBJEXT): internal/intern/eval.h
+enc/unicode.$(OBJEXT): internal/intern/file.h
+enc/unicode.$(OBJEXT): internal/intern/gc.h
+enc/unicode.$(OBJEXT): internal/intern/hash.h
+enc/unicode.$(OBJEXT): internal/intern/io.h
+enc/unicode.$(OBJEXT): internal/intern/load.h
+enc/unicode.$(OBJEXT): internal/intern/marshal.h
+enc/unicode.$(OBJEXT): internal/intern/numeric.h
+enc/unicode.$(OBJEXT): internal/intern/object.h
+enc/unicode.$(OBJEXT): internal/intern/parse.h
+enc/unicode.$(OBJEXT): internal/intern/proc.h
+enc/unicode.$(OBJEXT): internal/intern/process.h
+enc/unicode.$(OBJEXT): internal/intern/random.h
+enc/unicode.$(OBJEXT): internal/intern/range.h
+enc/unicode.$(OBJEXT): internal/intern/rational.h
+enc/unicode.$(OBJEXT): internal/intern/re.h
+enc/unicode.$(OBJEXT): internal/intern/ruby.h
+enc/unicode.$(OBJEXT): internal/intern/select.h
+enc/unicode.$(OBJEXT): internal/intern/select/largesize.h
+enc/unicode.$(OBJEXT): internal/intern/signal.h
+enc/unicode.$(OBJEXT): internal/intern/sprintf.h
+enc/unicode.$(OBJEXT): internal/intern/string.h
+enc/unicode.$(OBJEXT): internal/intern/struct.h
+enc/unicode.$(OBJEXT): internal/intern/thread.h
+enc/unicode.$(OBJEXT): internal/intern/time.h
+enc/unicode.$(OBJEXT): internal/intern/variable.h
+enc/unicode.$(OBJEXT): internal/intern/vm.h
+enc/unicode.$(OBJEXT): internal/interpreter.h
+enc/unicode.$(OBJEXT): internal/iterator.h
+enc/unicode.$(OBJEXT): internal/memory.h
+enc/unicode.$(OBJEXT): internal/method.h
+enc/unicode.$(OBJEXT): internal/module.h
+enc/unicode.$(OBJEXT): internal/newobj.h
+enc/unicode.$(OBJEXT): internal/rgengc.h
+enc/unicode.$(OBJEXT): internal/scan_args.h
+enc/unicode.$(OBJEXT): internal/special_consts.h
+enc/unicode.$(OBJEXT): internal/static_assert.h
+enc/unicode.$(OBJEXT): internal/stdalign.h
+enc/unicode.$(OBJEXT): internal/stdbool.h
+enc/unicode.$(OBJEXT): internal/symbol.h
+enc/unicode.$(OBJEXT): internal/token_paste.h
+enc/unicode.$(OBJEXT): internal/value.h
+enc/unicode.$(OBJEXT): internal/value_type.h
+enc/unicode.$(OBJEXT): internal/variable.h
+enc/unicode.$(OBJEXT): internal/warning_push.h
+enc/unicode.$(OBJEXT): internal/xmalloc.h
enc/unicode.$(OBJEXT): assert.h
+enc/unicode.$(OBJEXT): backward/2/assume.h
+enc/unicode.$(OBJEXT): backward/2/attributes.h
+enc/unicode.$(OBJEXT): backward/2/bool.h
+enc/unicode.$(OBJEXT): backward/2/gcc_version_since.h
+enc/unicode.$(OBJEXT): backward/2/inttypes.h
+enc/unicode.$(OBJEXT): backward/2/limits.h
+enc/unicode.$(OBJEXT): backward/2/long_long.h
+enc/unicode.$(OBJEXT): backward/2/stdalign.h
+enc/unicode.$(OBJEXT): backward/2/stdarg.h
enc/unicode.$(OBJEXT): config.h
enc/unicode.$(OBJEXT): defines.h
enc/unicode.$(OBJEXT): enc/unicode.c
@@ -628,14 +5749,221 @@ enc/unicode.$(OBJEXT): missing.h
enc/unicode.$(OBJEXT): onigmo.h
enc/unicode.$(OBJEXT): st.h
enc/unicode.$(OBJEXT): subst.h
+enc/us_ascii.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/us_ascii.$(OBJEXT): $(top_srcdir)/encindex.h
enc/us_ascii.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/us_ascii.$(OBJEXT): internal/anyargs.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/char.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/double.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/int.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/long.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/long_long.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/off_t.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/short.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/size_t.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/us_ascii.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/us_ascii.$(OBJEXT): internal/assume.h
+enc/us_ascii.$(OBJEXT): internal/attr/alloc_size.h
+enc/us_ascii.$(OBJEXT): internal/attr/artificial.h
+enc/us_ascii.$(OBJEXT): internal/attr/cold.h
+enc/us_ascii.$(OBJEXT): internal/attr/const.h
+enc/us_ascii.$(OBJEXT): internal/attr/constexpr.h
+enc/us_ascii.$(OBJEXT): internal/attr/deprecated.h
+enc/us_ascii.$(OBJEXT): internal/attr/diagnose_if.h
+enc/us_ascii.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/us_ascii.$(OBJEXT): internal/attr/error.h
+enc/us_ascii.$(OBJEXT): internal/attr/flag_enum.h
+enc/us_ascii.$(OBJEXT): internal/attr/forceinline.h
+enc/us_ascii.$(OBJEXT): internal/attr/format.h
+enc/us_ascii.$(OBJEXT): internal/attr/maybe_unused.h
+enc/us_ascii.$(OBJEXT): internal/attr/noalias.h
+enc/us_ascii.$(OBJEXT): internal/attr/nodiscard.h
+enc/us_ascii.$(OBJEXT): internal/attr/noexcept.h
+enc/us_ascii.$(OBJEXT): internal/attr/noinline.h
+enc/us_ascii.$(OBJEXT): internal/attr/nonnull.h
+enc/us_ascii.$(OBJEXT): internal/attr/noreturn.h
+enc/us_ascii.$(OBJEXT): internal/attr/pure.h
+enc/us_ascii.$(OBJEXT): internal/attr/restrict.h
+enc/us_ascii.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/us_ascii.$(OBJEXT): internal/attr/warning.h
+enc/us_ascii.$(OBJEXT): internal/attr/weakref.h
+enc/us_ascii.$(OBJEXT): internal/cast.h
+enc/us_ascii.$(OBJEXT): internal/compiler_is.h
+enc/us_ascii.$(OBJEXT): internal/compiler_is/apple.h
+enc/us_ascii.$(OBJEXT): internal/compiler_is/clang.h
+enc/us_ascii.$(OBJEXT): internal/compiler_is/gcc.h
+enc/us_ascii.$(OBJEXT): internal/compiler_is/intel.h
+enc/us_ascii.$(OBJEXT): internal/compiler_is/msvc.h
+enc/us_ascii.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/us_ascii.$(OBJEXT): internal/compiler_since.h
+enc/us_ascii.$(OBJEXT): internal/config.h
+enc/us_ascii.$(OBJEXT): internal/constant_p.h
+enc/us_ascii.$(OBJEXT): internal/core.h
+enc/us_ascii.$(OBJEXT): internal/core/rarray.h
+enc/us_ascii.$(OBJEXT): internal/core/rbasic.h
+enc/us_ascii.$(OBJEXT): internal/core/rbignum.h
+enc/us_ascii.$(OBJEXT): internal/core/rclass.h
+enc/us_ascii.$(OBJEXT): internal/core/rdata.h
+enc/us_ascii.$(OBJEXT): internal/core/rfile.h
+enc/us_ascii.$(OBJEXT): internal/core/rhash.h
+enc/us_ascii.$(OBJEXT): internal/core/robject.h
+enc/us_ascii.$(OBJEXT): internal/core/rregexp.h
+enc/us_ascii.$(OBJEXT): internal/core/rstring.h
+enc/us_ascii.$(OBJEXT): internal/core/rstruct.h
+enc/us_ascii.$(OBJEXT): internal/core/rtypeddata.h
+enc/us_ascii.$(OBJEXT): internal/ctype.h
+enc/us_ascii.$(OBJEXT): internal/dllexport.h
+enc/us_ascii.$(OBJEXT): internal/dosish.h
+enc/us_ascii.$(OBJEXT): internal/error.h
+enc/us_ascii.$(OBJEXT): internal/eval.h
+enc/us_ascii.$(OBJEXT): internal/event.h
+enc/us_ascii.$(OBJEXT): internal/fl_type.h
+enc/us_ascii.$(OBJEXT): internal/gc.h
+enc/us_ascii.$(OBJEXT): internal/glob.h
+enc/us_ascii.$(OBJEXT): internal/globals.h
+enc/us_ascii.$(OBJEXT): internal/has/attribute.h
+enc/us_ascii.$(OBJEXT): internal/has/builtin.h
+enc/us_ascii.$(OBJEXT): internal/has/c_attribute.h
+enc/us_ascii.$(OBJEXT): internal/has/cpp_attribute.h
+enc/us_ascii.$(OBJEXT): internal/has/declspec_attribute.h
+enc/us_ascii.$(OBJEXT): internal/has/extension.h
+enc/us_ascii.$(OBJEXT): internal/has/feature.h
+enc/us_ascii.$(OBJEXT): internal/has/warning.h
+enc/us_ascii.$(OBJEXT): internal/intern/array.h
+enc/us_ascii.$(OBJEXT): internal/intern/bignum.h
+enc/us_ascii.$(OBJEXT): internal/intern/class.h
+enc/us_ascii.$(OBJEXT): internal/intern/compar.h
+enc/us_ascii.$(OBJEXT): internal/intern/complex.h
+enc/us_ascii.$(OBJEXT): internal/intern/cont.h
+enc/us_ascii.$(OBJEXT): internal/intern/dir.h
+enc/us_ascii.$(OBJEXT): internal/intern/enum.h
+enc/us_ascii.$(OBJEXT): internal/intern/enumerator.h
+enc/us_ascii.$(OBJEXT): internal/intern/error.h
+enc/us_ascii.$(OBJEXT): internal/intern/eval.h
+enc/us_ascii.$(OBJEXT): internal/intern/file.h
+enc/us_ascii.$(OBJEXT): internal/intern/gc.h
+enc/us_ascii.$(OBJEXT): internal/intern/hash.h
+enc/us_ascii.$(OBJEXT): internal/intern/io.h
+enc/us_ascii.$(OBJEXT): internal/intern/load.h
+enc/us_ascii.$(OBJEXT): internal/intern/marshal.h
+enc/us_ascii.$(OBJEXT): internal/intern/numeric.h
+enc/us_ascii.$(OBJEXT): internal/intern/object.h
+enc/us_ascii.$(OBJEXT): internal/intern/parse.h
+enc/us_ascii.$(OBJEXT): internal/intern/proc.h
+enc/us_ascii.$(OBJEXT): internal/intern/process.h
+enc/us_ascii.$(OBJEXT): internal/intern/random.h
+enc/us_ascii.$(OBJEXT): internal/intern/range.h
+enc/us_ascii.$(OBJEXT): internal/intern/rational.h
+enc/us_ascii.$(OBJEXT): internal/intern/re.h
+enc/us_ascii.$(OBJEXT): internal/intern/ruby.h
+enc/us_ascii.$(OBJEXT): internal/intern/select.h
+enc/us_ascii.$(OBJEXT): internal/intern/select/largesize.h
+enc/us_ascii.$(OBJEXT): internal/intern/signal.h
+enc/us_ascii.$(OBJEXT): internal/intern/sprintf.h
+enc/us_ascii.$(OBJEXT): internal/intern/string.h
+enc/us_ascii.$(OBJEXT): internal/intern/struct.h
+enc/us_ascii.$(OBJEXT): internal/intern/thread.h
+enc/us_ascii.$(OBJEXT): internal/intern/time.h
+enc/us_ascii.$(OBJEXT): internal/intern/variable.h
+enc/us_ascii.$(OBJEXT): internal/intern/vm.h
+enc/us_ascii.$(OBJEXT): internal/interpreter.h
+enc/us_ascii.$(OBJEXT): internal/iterator.h
+enc/us_ascii.$(OBJEXT): internal/memory.h
+enc/us_ascii.$(OBJEXT): internal/method.h
+enc/us_ascii.$(OBJEXT): internal/module.h
+enc/us_ascii.$(OBJEXT): internal/newobj.h
+enc/us_ascii.$(OBJEXT): internal/rgengc.h
+enc/us_ascii.$(OBJEXT): internal/scan_args.h
+enc/us_ascii.$(OBJEXT): internal/special_consts.h
+enc/us_ascii.$(OBJEXT): internal/static_assert.h
+enc/us_ascii.$(OBJEXT): internal/stdalign.h
+enc/us_ascii.$(OBJEXT): internal/stdbool.h
+enc/us_ascii.$(OBJEXT): internal/symbol.h
+enc/us_ascii.$(OBJEXT): internal/token_paste.h
+enc/us_ascii.$(OBJEXT): internal/value.h
+enc/us_ascii.$(OBJEXT): internal/value_type.h
+enc/us_ascii.$(OBJEXT): internal/variable.h
+enc/us_ascii.$(OBJEXT): internal/warning_push.h
+enc/us_ascii.$(OBJEXT): internal/xmalloc.h
+enc/us_ascii.$(OBJEXT): assert.h
+enc/us_ascii.$(OBJEXT): backward/2/assume.h
+enc/us_ascii.$(OBJEXT): backward/2/attributes.h
+enc/us_ascii.$(OBJEXT): backward/2/bool.h
+enc/us_ascii.$(OBJEXT): backward/2/gcc_version_since.h
+enc/us_ascii.$(OBJEXT): backward/2/inttypes.h
+enc/us_ascii.$(OBJEXT): backward/2/limits.h
+enc/us_ascii.$(OBJEXT): backward/2/long_long.h
+enc/us_ascii.$(OBJEXT): backward/2/stdalign.h
+enc/us_ascii.$(OBJEXT): backward/2/stdarg.h
enc/us_ascii.$(OBJEXT): config.h
enc/us_ascii.$(OBJEXT): defines.h
enc/us_ascii.$(OBJEXT): enc/us_ascii.c
+enc/us_ascii.$(OBJEXT): encoding.h
+enc/us_ascii.$(OBJEXT): intern.h
enc/us_ascii.$(OBJEXT): missing.h
enc/us_ascii.$(OBJEXT): onigmo.h
+enc/us_ascii.$(OBJEXT): oniguruma.h
+enc/us_ascii.$(OBJEXT): st.h
+enc/us_ascii.$(OBJEXT): subst.h
enc/utf_16be.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_16be.$(OBJEXT): internal/assume.h
+enc/utf_16be.$(OBJEXT): internal/attr/alloc_size.h
+enc/utf_16be.$(OBJEXT): internal/attr/cold.h
+enc/utf_16be.$(OBJEXT): internal/attr/const.h
+enc/utf_16be.$(OBJEXT): internal/attr/deprecated.h
+enc/utf_16be.$(OBJEXT): internal/attr/error.h
+enc/utf_16be.$(OBJEXT): internal/attr/forceinline.h
+enc/utf_16be.$(OBJEXT): internal/attr/format.h
+enc/utf_16be.$(OBJEXT): internal/attr/maybe_unused.h
+enc/utf_16be.$(OBJEXT): internal/attr/nodiscard.h
+enc/utf_16be.$(OBJEXT): internal/attr/noexcept.h
+enc/utf_16be.$(OBJEXT): internal/attr/noinline.h
+enc/utf_16be.$(OBJEXT): internal/attr/nonnull.h
+enc/utf_16be.$(OBJEXT): internal/attr/noreturn.h
+enc/utf_16be.$(OBJEXT): internal/attr/pure.h
+enc/utf_16be.$(OBJEXT): internal/attr/restrict.h
+enc/utf_16be.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/utf_16be.$(OBJEXT): internal/attr/warning.h
+enc/utf_16be.$(OBJEXT): internal/cast.h
+enc/utf_16be.$(OBJEXT): internal/compiler_is.h
+enc/utf_16be.$(OBJEXT): internal/compiler_is/apple.h
+enc/utf_16be.$(OBJEXT): internal/compiler_is/clang.h
+enc/utf_16be.$(OBJEXT): internal/compiler_is/gcc.h
+enc/utf_16be.$(OBJEXT): internal/compiler_is/intel.h
+enc/utf_16be.$(OBJEXT): internal/compiler_is/msvc.h
+enc/utf_16be.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/utf_16be.$(OBJEXT): internal/compiler_since.h
+enc/utf_16be.$(OBJEXT): internal/config.h
+enc/utf_16be.$(OBJEXT): internal/dllexport.h
+enc/utf_16be.$(OBJEXT): internal/dosish.h
+enc/utf_16be.$(OBJEXT): internal/has/attribute.h
+enc/utf_16be.$(OBJEXT): internal/has/builtin.h
+enc/utf_16be.$(OBJEXT): internal/has/c_attribute.h
+enc/utf_16be.$(OBJEXT): internal/has/cpp_attribute.h
+enc/utf_16be.$(OBJEXT): internal/has/declspec_attribute.h
+enc/utf_16be.$(OBJEXT): internal/has/extension.h
+enc/utf_16be.$(OBJEXT): internal/has/feature.h
+enc/utf_16be.$(OBJEXT): internal/has/warning.h
+enc/utf_16be.$(OBJEXT): internal/stdalign.h
+enc/utf_16be.$(OBJEXT): internal/stdbool.h
+enc/utf_16be.$(OBJEXT): internal/token_paste.h
+enc/utf_16be.$(OBJEXT): internal/warning_push.h
+enc/utf_16be.$(OBJEXT): internal/xmalloc.h
+enc/utf_16be.$(OBJEXT): assert.h
+enc/utf_16be.$(OBJEXT): backward/2/assume.h
+enc/utf_16be.$(OBJEXT): backward/2/attributes.h
+enc/utf_16be.$(OBJEXT): backward/2/bool.h
+enc/utf_16be.$(OBJEXT): backward/2/gcc_version_since.h
+enc/utf_16be.$(OBJEXT): backward/2/long_long.h
+enc/utf_16be.$(OBJEXT): backward/2/stdalign.h
+enc/utf_16be.$(OBJEXT): backward/2/stdarg.h
enc/utf_16be.$(OBJEXT): config.h
enc/utf_16be.$(OBJEXT): defines.h
enc/utf_16be.$(OBJEXT): enc/iso_8859.h
@@ -643,6 +5971,57 @@ enc/utf_16be.$(OBJEXT): enc/utf_16be.c
enc/utf_16be.$(OBJEXT): missing.h
enc/utf_16be.$(OBJEXT): onigmo.h
enc/utf_16le.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_16le.$(OBJEXT): internal/assume.h
+enc/utf_16le.$(OBJEXT): internal/attr/alloc_size.h
+enc/utf_16le.$(OBJEXT): internal/attr/cold.h
+enc/utf_16le.$(OBJEXT): internal/attr/const.h
+enc/utf_16le.$(OBJEXT): internal/attr/deprecated.h
+enc/utf_16le.$(OBJEXT): internal/attr/error.h
+enc/utf_16le.$(OBJEXT): internal/attr/forceinline.h
+enc/utf_16le.$(OBJEXT): internal/attr/format.h
+enc/utf_16le.$(OBJEXT): internal/attr/maybe_unused.h
+enc/utf_16le.$(OBJEXT): internal/attr/nodiscard.h
+enc/utf_16le.$(OBJEXT): internal/attr/noexcept.h
+enc/utf_16le.$(OBJEXT): internal/attr/noinline.h
+enc/utf_16le.$(OBJEXT): internal/attr/nonnull.h
+enc/utf_16le.$(OBJEXT): internal/attr/noreturn.h
+enc/utf_16le.$(OBJEXT): internal/attr/pure.h
+enc/utf_16le.$(OBJEXT): internal/attr/restrict.h
+enc/utf_16le.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/utf_16le.$(OBJEXT): internal/attr/warning.h
+enc/utf_16le.$(OBJEXT): internal/cast.h
+enc/utf_16le.$(OBJEXT): internal/compiler_is.h
+enc/utf_16le.$(OBJEXT): internal/compiler_is/apple.h
+enc/utf_16le.$(OBJEXT): internal/compiler_is/clang.h
+enc/utf_16le.$(OBJEXT): internal/compiler_is/gcc.h
+enc/utf_16le.$(OBJEXT): internal/compiler_is/intel.h
+enc/utf_16le.$(OBJEXT): internal/compiler_is/msvc.h
+enc/utf_16le.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/utf_16le.$(OBJEXT): internal/compiler_since.h
+enc/utf_16le.$(OBJEXT): internal/config.h
+enc/utf_16le.$(OBJEXT): internal/dllexport.h
+enc/utf_16le.$(OBJEXT): internal/dosish.h
+enc/utf_16le.$(OBJEXT): internal/has/attribute.h
+enc/utf_16le.$(OBJEXT): internal/has/builtin.h
+enc/utf_16le.$(OBJEXT): internal/has/c_attribute.h
+enc/utf_16le.$(OBJEXT): internal/has/cpp_attribute.h
+enc/utf_16le.$(OBJEXT): internal/has/declspec_attribute.h
+enc/utf_16le.$(OBJEXT): internal/has/extension.h
+enc/utf_16le.$(OBJEXT): internal/has/feature.h
+enc/utf_16le.$(OBJEXT): internal/has/warning.h
+enc/utf_16le.$(OBJEXT): internal/stdalign.h
+enc/utf_16le.$(OBJEXT): internal/stdbool.h
+enc/utf_16le.$(OBJEXT): internal/token_paste.h
+enc/utf_16le.$(OBJEXT): internal/warning_push.h
+enc/utf_16le.$(OBJEXT): internal/xmalloc.h
+enc/utf_16le.$(OBJEXT): assert.h
+enc/utf_16le.$(OBJEXT): backward/2/assume.h
+enc/utf_16le.$(OBJEXT): backward/2/attributes.h
+enc/utf_16le.$(OBJEXT): backward/2/bool.h
+enc/utf_16le.$(OBJEXT): backward/2/gcc_version_since.h
+enc/utf_16le.$(OBJEXT): backward/2/long_long.h
+enc/utf_16le.$(OBJEXT): backward/2/stdalign.h
+enc/utf_16le.$(OBJEXT): backward/2/stdarg.h
enc/utf_16le.$(OBJEXT): config.h
enc/utf_16le.$(OBJEXT): defines.h
enc/utf_16le.$(OBJEXT): enc/iso_8859.h
@@ -650,6 +6029,57 @@ enc/utf_16le.$(OBJEXT): enc/utf_16le.c
enc/utf_16le.$(OBJEXT): missing.h
enc/utf_16le.$(OBJEXT): onigmo.h
enc/utf_32be.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_32be.$(OBJEXT): internal/assume.h
+enc/utf_32be.$(OBJEXT): internal/attr/alloc_size.h
+enc/utf_32be.$(OBJEXT): internal/attr/cold.h
+enc/utf_32be.$(OBJEXT): internal/attr/const.h
+enc/utf_32be.$(OBJEXT): internal/attr/deprecated.h
+enc/utf_32be.$(OBJEXT): internal/attr/error.h
+enc/utf_32be.$(OBJEXT): internal/attr/forceinline.h
+enc/utf_32be.$(OBJEXT): internal/attr/format.h
+enc/utf_32be.$(OBJEXT): internal/attr/maybe_unused.h
+enc/utf_32be.$(OBJEXT): internal/attr/nodiscard.h
+enc/utf_32be.$(OBJEXT): internal/attr/noexcept.h
+enc/utf_32be.$(OBJEXT): internal/attr/noinline.h
+enc/utf_32be.$(OBJEXT): internal/attr/nonnull.h
+enc/utf_32be.$(OBJEXT): internal/attr/noreturn.h
+enc/utf_32be.$(OBJEXT): internal/attr/pure.h
+enc/utf_32be.$(OBJEXT): internal/attr/restrict.h
+enc/utf_32be.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/utf_32be.$(OBJEXT): internal/attr/warning.h
+enc/utf_32be.$(OBJEXT): internal/cast.h
+enc/utf_32be.$(OBJEXT): internal/compiler_is.h
+enc/utf_32be.$(OBJEXT): internal/compiler_is/apple.h
+enc/utf_32be.$(OBJEXT): internal/compiler_is/clang.h
+enc/utf_32be.$(OBJEXT): internal/compiler_is/gcc.h
+enc/utf_32be.$(OBJEXT): internal/compiler_is/intel.h
+enc/utf_32be.$(OBJEXT): internal/compiler_is/msvc.h
+enc/utf_32be.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/utf_32be.$(OBJEXT): internal/compiler_since.h
+enc/utf_32be.$(OBJEXT): internal/config.h
+enc/utf_32be.$(OBJEXT): internal/dllexport.h
+enc/utf_32be.$(OBJEXT): internal/dosish.h
+enc/utf_32be.$(OBJEXT): internal/has/attribute.h
+enc/utf_32be.$(OBJEXT): internal/has/builtin.h
+enc/utf_32be.$(OBJEXT): internal/has/c_attribute.h
+enc/utf_32be.$(OBJEXT): internal/has/cpp_attribute.h
+enc/utf_32be.$(OBJEXT): internal/has/declspec_attribute.h
+enc/utf_32be.$(OBJEXT): internal/has/extension.h
+enc/utf_32be.$(OBJEXT): internal/has/feature.h
+enc/utf_32be.$(OBJEXT): internal/has/warning.h
+enc/utf_32be.$(OBJEXT): internal/stdalign.h
+enc/utf_32be.$(OBJEXT): internal/stdbool.h
+enc/utf_32be.$(OBJEXT): internal/token_paste.h
+enc/utf_32be.$(OBJEXT): internal/warning_push.h
+enc/utf_32be.$(OBJEXT): internal/xmalloc.h
+enc/utf_32be.$(OBJEXT): assert.h
+enc/utf_32be.$(OBJEXT): backward/2/assume.h
+enc/utf_32be.$(OBJEXT): backward/2/attributes.h
+enc/utf_32be.$(OBJEXT): backward/2/bool.h
+enc/utf_32be.$(OBJEXT): backward/2/gcc_version_since.h
+enc/utf_32be.$(OBJEXT): backward/2/long_long.h
+enc/utf_32be.$(OBJEXT): backward/2/stdalign.h
+enc/utf_32be.$(OBJEXT): backward/2/stdarg.h
enc/utf_32be.$(OBJEXT): config.h
enc/utf_32be.$(OBJEXT): defines.h
enc/utf_32be.$(OBJEXT): enc/iso_8859.h
@@ -657,20 +6087,278 @@ enc/utf_32be.$(OBJEXT): enc/utf_32be.c
enc/utf_32be.$(OBJEXT): missing.h
enc/utf_32be.$(OBJEXT): onigmo.h
enc/utf_32le.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_32le.$(OBJEXT): internal/assume.h
+enc/utf_32le.$(OBJEXT): internal/attr/alloc_size.h
+enc/utf_32le.$(OBJEXT): internal/attr/cold.h
+enc/utf_32le.$(OBJEXT): internal/attr/const.h
+enc/utf_32le.$(OBJEXT): internal/attr/deprecated.h
+enc/utf_32le.$(OBJEXT): internal/attr/error.h
+enc/utf_32le.$(OBJEXT): internal/attr/forceinline.h
+enc/utf_32le.$(OBJEXT): internal/attr/format.h
+enc/utf_32le.$(OBJEXT): internal/attr/maybe_unused.h
+enc/utf_32le.$(OBJEXT): internal/attr/nodiscard.h
+enc/utf_32le.$(OBJEXT): internal/attr/noexcept.h
+enc/utf_32le.$(OBJEXT): internal/attr/noinline.h
+enc/utf_32le.$(OBJEXT): internal/attr/nonnull.h
+enc/utf_32le.$(OBJEXT): internal/attr/noreturn.h
+enc/utf_32le.$(OBJEXT): internal/attr/pure.h
+enc/utf_32le.$(OBJEXT): internal/attr/restrict.h
+enc/utf_32le.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/utf_32le.$(OBJEXT): internal/attr/warning.h
+enc/utf_32le.$(OBJEXT): internal/cast.h
+enc/utf_32le.$(OBJEXT): internal/compiler_is.h
+enc/utf_32le.$(OBJEXT): internal/compiler_is/apple.h
+enc/utf_32le.$(OBJEXT): internal/compiler_is/clang.h
+enc/utf_32le.$(OBJEXT): internal/compiler_is/gcc.h
+enc/utf_32le.$(OBJEXT): internal/compiler_is/intel.h
+enc/utf_32le.$(OBJEXT): internal/compiler_is/msvc.h
+enc/utf_32le.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/utf_32le.$(OBJEXT): internal/compiler_since.h
+enc/utf_32le.$(OBJEXT): internal/config.h
+enc/utf_32le.$(OBJEXT): internal/dllexport.h
+enc/utf_32le.$(OBJEXT): internal/dosish.h
+enc/utf_32le.$(OBJEXT): internal/has/attribute.h
+enc/utf_32le.$(OBJEXT): internal/has/builtin.h
+enc/utf_32le.$(OBJEXT): internal/has/c_attribute.h
+enc/utf_32le.$(OBJEXT): internal/has/cpp_attribute.h
+enc/utf_32le.$(OBJEXT): internal/has/declspec_attribute.h
+enc/utf_32le.$(OBJEXT): internal/has/extension.h
+enc/utf_32le.$(OBJEXT): internal/has/feature.h
+enc/utf_32le.$(OBJEXT): internal/has/warning.h
+enc/utf_32le.$(OBJEXT): internal/stdalign.h
+enc/utf_32le.$(OBJEXT): internal/stdbool.h
+enc/utf_32le.$(OBJEXT): internal/token_paste.h
+enc/utf_32le.$(OBJEXT): internal/warning_push.h
+enc/utf_32le.$(OBJEXT): internal/xmalloc.h
+enc/utf_32le.$(OBJEXT): assert.h
+enc/utf_32le.$(OBJEXT): backward/2/assume.h
+enc/utf_32le.$(OBJEXT): backward/2/attributes.h
+enc/utf_32le.$(OBJEXT): backward/2/bool.h
+enc/utf_32le.$(OBJEXT): backward/2/gcc_version_since.h
+enc/utf_32le.$(OBJEXT): backward/2/long_long.h
+enc/utf_32le.$(OBJEXT): backward/2/stdalign.h
+enc/utf_32le.$(OBJEXT): backward/2/stdarg.h
enc/utf_32le.$(OBJEXT): config.h
enc/utf_32le.$(OBJEXT): defines.h
enc/utf_32le.$(OBJEXT): enc/iso_8859.h
enc/utf_32le.$(OBJEXT): enc/utf_32le.c
enc/utf_32le.$(OBJEXT): missing.h
enc/utf_32le.$(OBJEXT): onigmo.h
+enc/utf_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h
enc/utf_8.$(OBJEXT): $(top_srcdir)/encindex.h
enc/utf_8.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/utf_8.$(OBJEXT): internal/anyargs.h
+enc/utf_8.$(OBJEXT): internal/arithmetic.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/char.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/double.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/fixnum.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/gid_t.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/int.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/intptr_t.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/long.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/long_long.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/mode_t.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/off_t.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/pid_t.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/short.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/size_t.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/st_data_t.h
+enc/utf_8.$(OBJEXT): internal/arithmetic/uid_t.h
+enc/utf_8.$(OBJEXT): internal/assume.h
+enc/utf_8.$(OBJEXT): internal/attr/alloc_size.h
+enc/utf_8.$(OBJEXT): internal/attr/artificial.h
+enc/utf_8.$(OBJEXT): internal/attr/cold.h
+enc/utf_8.$(OBJEXT): internal/attr/const.h
+enc/utf_8.$(OBJEXT): internal/attr/constexpr.h
+enc/utf_8.$(OBJEXT): internal/attr/deprecated.h
+enc/utf_8.$(OBJEXT): internal/attr/diagnose_if.h
+enc/utf_8.$(OBJEXT): internal/attr/enum_extensibility.h
+enc/utf_8.$(OBJEXT): internal/attr/error.h
+enc/utf_8.$(OBJEXT): internal/attr/flag_enum.h
+enc/utf_8.$(OBJEXT): internal/attr/forceinline.h
+enc/utf_8.$(OBJEXT): internal/attr/format.h
+enc/utf_8.$(OBJEXT): internal/attr/maybe_unused.h
+enc/utf_8.$(OBJEXT): internal/attr/noalias.h
+enc/utf_8.$(OBJEXT): internal/attr/nodiscard.h
+enc/utf_8.$(OBJEXT): internal/attr/noexcept.h
+enc/utf_8.$(OBJEXT): internal/attr/noinline.h
+enc/utf_8.$(OBJEXT): internal/attr/nonnull.h
+enc/utf_8.$(OBJEXT): internal/attr/noreturn.h
+enc/utf_8.$(OBJEXT): internal/attr/pure.h
+enc/utf_8.$(OBJEXT): internal/attr/restrict.h
+enc/utf_8.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/utf_8.$(OBJEXT): internal/attr/warning.h
+enc/utf_8.$(OBJEXT): internal/attr/weakref.h
+enc/utf_8.$(OBJEXT): internal/cast.h
+enc/utf_8.$(OBJEXT): internal/compiler_is.h
+enc/utf_8.$(OBJEXT): internal/compiler_is/apple.h
+enc/utf_8.$(OBJEXT): internal/compiler_is/clang.h
+enc/utf_8.$(OBJEXT): internal/compiler_is/gcc.h
+enc/utf_8.$(OBJEXT): internal/compiler_is/intel.h
+enc/utf_8.$(OBJEXT): internal/compiler_is/msvc.h
+enc/utf_8.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/utf_8.$(OBJEXT): internal/compiler_since.h
+enc/utf_8.$(OBJEXT): internal/config.h
+enc/utf_8.$(OBJEXT): internal/constant_p.h
+enc/utf_8.$(OBJEXT): internal/core.h
+enc/utf_8.$(OBJEXT): internal/core/rarray.h
+enc/utf_8.$(OBJEXT): internal/core/rbasic.h
+enc/utf_8.$(OBJEXT): internal/core/rbignum.h
+enc/utf_8.$(OBJEXT): internal/core/rclass.h
+enc/utf_8.$(OBJEXT): internal/core/rdata.h
+enc/utf_8.$(OBJEXT): internal/core/rfile.h
+enc/utf_8.$(OBJEXT): internal/core/rhash.h
+enc/utf_8.$(OBJEXT): internal/core/robject.h
+enc/utf_8.$(OBJEXT): internal/core/rregexp.h
+enc/utf_8.$(OBJEXT): internal/core/rstring.h
+enc/utf_8.$(OBJEXT): internal/core/rstruct.h
+enc/utf_8.$(OBJEXT): internal/core/rtypeddata.h
+enc/utf_8.$(OBJEXT): internal/ctype.h
+enc/utf_8.$(OBJEXT): internal/dllexport.h
+enc/utf_8.$(OBJEXT): internal/dosish.h
+enc/utf_8.$(OBJEXT): internal/error.h
+enc/utf_8.$(OBJEXT): internal/eval.h
+enc/utf_8.$(OBJEXT): internal/event.h
+enc/utf_8.$(OBJEXT): internal/fl_type.h
+enc/utf_8.$(OBJEXT): internal/gc.h
+enc/utf_8.$(OBJEXT): internal/glob.h
+enc/utf_8.$(OBJEXT): internal/globals.h
+enc/utf_8.$(OBJEXT): internal/has/attribute.h
+enc/utf_8.$(OBJEXT): internal/has/builtin.h
+enc/utf_8.$(OBJEXT): internal/has/c_attribute.h
+enc/utf_8.$(OBJEXT): internal/has/cpp_attribute.h
+enc/utf_8.$(OBJEXT): internal/has/declspec_attribute.h
+enc/utf_8.$(OBJEXT): internal/has/extension.h
+enc/utf_8.$(OBJEXT): internal/has/feature.h
+enc/utf_8.$(OBJEXT): internal/has/warning.h
+enc/utf_8.$(OBJEXT): internal/intern/array.h
+enc/utf_8.$(OBJEXT): internal/intern/bignum.h
+enc/utf_8.$(OBJEXT): internal/intern/class.h
+enc/utf_8.$(OBJEXT): internal/intern/compar.h
+enc/utf_8.$(OBJEXT): internal/intern/complex.h
+enc/utf_8.$(OBJEXT): internal/intern/cont.h
+enc/utf_8.$(OBJEXT): internal/intern/dir.h
+enc/utf_8.$(OBJEXT): internal/intern/enum.h
+enc/utf_8.$(OBJEXT): internal/intern/enumerator.h
+enc/utf_8.$(OBJEXT): internal/intern/error.h
+enc/utf_8.$(OBJEXT): internal/intern/eval.h
+enc/utf_8.$(OBJEXT): internal/intern/file.h
+enc/utf_8.$(OBJEXT): internal/intern/gc.h
+enc/utf_8.$(OBJEXT): internal/intern/hash.h
+enc/utf_8.$(OBJEXT): internal/intern/io.h
+enc/utf_8.$(OBJEXT): internal/intern/load.h
+enc/utf_8.$(OBJEXT): internal/intern/marshal.h
+enc/utf_8.$(OBJEXT): internal/intern/numeric.h
+enc/utf_8.$(OBJEXT): internal/intern/object.h
+enc/utf_8.$(OBJEXT): internal/intern/parse.h
+enc/utf_8.$(OBJEXT): internal/intern/proc.h
+enc/utf_8.$(OBJEXT): internal/intern/process.h
+enc/utf_8.$(OBJEXT): internal/intern/random.h
+enc/utf_8.$(OBJEXT): internal/intern/range.h
+enc/utf_8.$(OBJEXT): internal/intern/rational.h
+enc/utf_8.$(OBJEXT): internal/intern/re.h
+enc/utf_8.$(OBJEXT): internal/intern/ruby.h
+enc/utf_8.$(OBJEXT): internal/intern/select.h
+enc/utf_8.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_8.$(OBJEXT): internal/intern/signal.h
+enc/utf_8.$(OBJEXT): internal/intern/sprintf.h
+enc/utf_8.$(OBJEXT): internal/intern/string.h
+enc/utf_8.$(OBJEXT): internal/intern/struct.h
+enc/utf_8.$(OBJEXT): internal/intern/thread.h
+enc/utf_8.$(OBJEXT): internal/intern/time.h
+enc/utf_8.$(OBJEXT): internal/intern/variable.h
+enc/utf_8.$(OBJEXT): internal/intern/vm.h
+enc/utf_8.$(OBJEXT): internal/interpreter.h
+enc/utf_8.$(OBJEXT): internal/iterator.h
+enc/utf_8.$(OBJEXT): internal/memory.h
+enc/utf_8.$(OBJEXT): internal/method.h
+enc/utf_8.$(OBJEXT): internal/module.h
+enc/utf_8.$(OBJEXT): internal/newobj.h
+enc/utf_8.$(OBJEXT): internal/rgengc.h
+enc/utf_8.$(OBJEXT): internal/scan_args.h
+enc/utf_8.$(OBJEXT): internal/special_consts.h
+enc/utf_8.$(OBJEXT): internal/static_assert.h
+enc/utf_8.$(OBJEXT): internal/stdalign.h
+enc/utf_8.$(OBJEXT): internal/stdbool.h
+enc/utf_8.$(OBJEXT): internal/symbol.h
+enc/utf_8.$(OBJEXT): internal/token_paste.h
+enc/utf_8.$(OBJEXT): internal/value.h
+enc/utf_8.$(OBJEXT): internal/value_type.h
+enc/utf_8.$(OBJEXT): internal/variable.h
+enc/utf_8.$(OBJEXT): internal/warning_push.h
+enc/utf_8.$(OBJEXT): internal/xmalloc.h
+enc/utf_8.$(OBJEXT): assert.h
+enc/utf_8.$(OBJEXT): backward/2/assume.h
+enc/utf_8.$(OBJEXT): backward/2/attributes.h
+enc/utf_8.$(OBJEXT): backward/2/bool.h
+enc/utf_8.$(OBJEXT): backward/2/gcc_version_since.h
+enc/utf_8.$(OBJEXT): backward/2/inttypes.h
+enc/utf_8.$(OBJEXT): backward/2/limits.h
+enc/utf_8.$(OBJEXT): backward/2/long_long.h
+enc/utf_8.$(OBJEXT): backward/2/stdalign.h
+enc/utf_8.$(OBJEXT): backward/2/stdarg.h
enc/utf_8.$(OBJEXT): config.h
enc/utf_8.$(OBJEXT): defines.h
enc/utf_8.$(OBJEXT): enc/utf_8.c
+enc/utf_8.$(OBJEXT): encoding.h
+enc/utf_8.$(OBJEXT): intern.h
enc/utf_8.$(OBJEXT): missing.h
enc/utf_8.$(OBJEXT): onigmo.h
+enc/utf_8.$(OBJEXT): oniguruma.h
+enc/utf_8.$(OBJEXT): st.h
+enc/utf_8.$(OBJEXT): subst.h
enc/windows_1250.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1250.$(OBJEXT): internal/assume.h
+enc/windows_1250.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1250.$(OBJEXT): internal/attr/cold.h
+enc/windows_1250.$(OBJEXT): internal/attr/const.h
+enc/windows_1250.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1250.$(OBJEXT): internal/attr/error.h
+enc/windows_1250.$(OBJEXT): internal/attr/forceinline.h
+enc/windows_1250.$(OBJEXT): internal/attr/format.h
+enc/windows_1250.$(OBJEXT): internal/attr/maybe_unused.h
+enc/windows_1250.$(OBJEXT): internal/attr/nodiscard.h
+enc/windows_1250.$(OBJEXT): internal/attr/noexcept.h
+enc/windows_1250.$(OBJEXT): internal/attr/noinline.h
+enc/windows_1250.$(OBJEXT): internal/attr/nonnull.h
+enc/windows_1250.$(OBJEXT): internal/attr/noreturn.h
+enc/windows_1250.$(OBJEXT): internal/attr/pure.h
+enc/windows_1250.$(OBJEXT): internal/attr/restrict.h
+enc/windows_1250.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/windows_1250.$(OBJEXT): internal/attr/warning.h
+enc/windows_1250.$(OBJEXT): internal/cast.h
+enc/windows_1250.$(OBJEXT): internal/compiler_is.h
+enc/windows_1250.$(OBJEXT): internal/compiler_is/apple.h
+enc/windows_1250.$(OBJEXT): internal/compiler_is/clang.h
+enc/windows_1250.$(OBJEXT): internal/compiler_is/gcc.h
+enc/windows_1250.$(OBJEXT): internal/compiler_is/intel.h
+enc/windows_1250.$(OBJEXT): internal/compiler_is/msvc.h
+enc/windows_1250.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/windows_1250.$(OBJEXT): internal/compiler_since.h
+enc/windows_1250.$(OBJEXT): internal/config.h
+enc/windows_1250.$(OBJEXT): internal/dllexport.h
+enc/windows_1250.$(OBJEXT): internal/dosish.h
+enc/windows_1250.$(OBJEXT): internal/has/attribute.h
+enc/windows_1250.$(OBJEXT): internal/has/builtin.h
+enc/windows_1250.$(OBJEXT): internal/has/c_attribute.h
+enc/windows_1250.$(OBJEXT): internal/has/cpp_attribute.h
+enc/windows_1250.$(OBJEXT): internal/has/declspec_attribute.h
+enc/windows_1250.$(OBJEXT): internal/has/extension.h
+enc/windows_1250.$(OBJEXT): internal/has/feature.h
+enc/windows_1250.$(OBJEXT): internal/has/warning.h
+enc/windows_1250.$(OBJEXT): internal/stdalign.h
+enc/windows_1250.$(OBJEXT): internal/stdbool.h
+enc/windows_1250.$(OBJEXT): internal/token_paste.h
+enc/windows_1250.$(OBJEXT): internal/warning_push.h
+enc/windows_1250.$(OBJEXT): internal/xmalloc.h
+enc/windows_1250.$(OBJEXT): assert.h
+enc/windows_1250.$(OBJEXT): backward/2/assume.h
+enc/windows_1250.$(OBJEXT): backward/2/attributes.h
+enc/windows_1250.$(OBJEXT): backward/2/bool.h
+enc/windows_1250.$(OBJEXT): backward/2/gcc_version_since.h
+enc/windows_1250.$(OBJEXT): backward/2/long_long.h
+enc/windows_1250.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1250.$(OBJEXT): backward/2/stdarg.h
enc/windows_1250.$(OBJEXT): config.h
enc/windows_1250.$(OBJEXT): defines.h
enc/windows_1250.$(OBJEXT): enc/iso_8859.h
@@ -678,12 +6366,114 @@ enc/windows_1250.$(OBJEXT): enc/windows_1250.c
enc/windows_1250.$(OBJEXT): missing.h
enc/windows_1250.$(OBJEXT): onigmo.h
enc/windows_1251.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1251.$(OBJEXT): internal/assume.h
+enc/windows_1251.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1251.$(OBJEXT): internal/attr/cold.h
+enc/windows_1251.$(OBJEXT): internal/attr/const.h
+enc/windows_1251.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1251.$(OBJEXT): internal/attr/error.h
+enc/windows_1251.$(OBJEXT): internal/attr/forceinline.h
+enc/windows_1251.$(OBJEXT): internal/attr/format.h
+enc/windows_1251.$(OBJEXT): internal/attr/maybe_unused.h
+enc/windows_1251.$(OBJEXT): internal/attr/nodiscard.h
+enc/windows_1251.$(OBJEXT): internal/attr/noexcept.h
+enc/windows_1251.$(OBJEXT): internal/attr/noinline.h
+enc/windows_1251.$(OBJEXT): internal/attr/nonnull.h
+enc/windows_1251.$(OBJEXT): internal/attr/noreturn.h
+enc/windows_1251.$(OBJEXT): internal/attr/pure.h
+enc/windows_1251.$(OBJEXT): internal/attr/restrict.h
+enc/windows_1251.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/windows_1251.$(OBJEXT): internal/attr/warning.h
+enc/windows_1251.$(OBJEXT): internal/cast.h
+enc/windows_1251.$(OBJEXT): internal/compiler_is.h
+enc/windows_1251.$(OBJEXT): internal/compiler_is/apple.h
+enc/windows_1251.$(OBJEXT): internal/compiler_is/clang.h
+enc/windows_1251.$(OBJEXT): internal/compiler_is/gcc.h
+enc/windows_1251.$(OBJEXT): internal/compiler_is/intel.h
+enc/windows_1251.$(OBJEXT): internal/compiler_is/msvc.h
+enc/windows_1251.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/windows_1251.$(OBJEXT): internal/compiler_since.h
+enc/windows_1251.$(OBJEXT): internal/config.h
+enc/windows_1251.$(OBJEXT): internal/dllexport.h
+enc/windows_1251.$(OBJEXT): internal/dosish.h
+enc/windows_1251.$(OBJEXT): internal/has/attribute.h
+enc/windows_1251.$(OBJEXT): internal/has/builtin.h
+enc/windows_1251.$(OBJEXT): internal/has/c_attribute.h
+enc/windows_1251.$(OBJEXT): internal/has/cpp_attribute.h
+enc/windows_1251.$(OBJEXT): internal/has/declspec_attribute.h
+enc/windows_1251.$(OBJEXT): internal/has/extension.h
+enc/windows_1251.$(OBJEXT): internal/has/feature.h
+enc/windows_1251.$(OBJEXT): internal/has/warning.h
+enc/windows_1251.$(OBJEXT): internal/stdalign.h
+enc/windows_1251.$(OBJEXT): internal/stdbool.h
+enc/windows_1251.$(OBJEXT): internal/token_paste.h
+enc/windows_1251.$(OBJEXT): internal/warning_push.h
+enc/windows_1251.$(OBJEXT): internal/xmalloc.h
+enc/windows_1251.$(OBJEXT): assert.h
+enc/windows_1251.$(OBJEXT): backward/2/assume.h
+enc/windows_1251.$(OBJEXT): backward/2/attributes.h
+enc/windows_1251.$(OBJEXT): backward/2/bool.h
+enc/windows_1251.$(OBJEXT): backward/2/gcc_version_since.h
+enc/windows_1251.$(OBJEXT): backward/2/long_long.h
+enc/windows_1251.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1251.$(OBJEXT): backward/2/stdarg.h
enc/windows_1251.$(OBJEXT): config.h
enc/windows_1251.$(OBJEXT): defines.h
enc/windows_1251.$(OBJEXT): enc/windows_1251.c
enc/windows_1251.$(OBJEXT): missing.h
enc/windows_1251.$(OBJEXT): onigmo.h
enc/windows_1252.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1252.$(OBJEXT): internal/assume.h
+enc/windows_1252.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1252.$(OBJEXT): internal/attr/cold.h
+enc/windows_1252.$(OBJEXT): internal/attr/const.h
+enc/windows_1252.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1252.$(OBJEXT): internal/attr/error.h
+enc/windows_1252.$(OBJEXT): internal/attr/forceinline.h
+enc/windows_1252.$(OBJEXT): internal/attr/format.h
+enc/windows_1252.$(OBJEXT): internal/attr/maybe_unused.h
+enc/windows_1252.$(OBJEXT): internal/attr/nodiscard.h
+enc/windows_1252.$(OBJEXT): internal/attr/noexcept.h
+enc/windows_1252.$(OBJEXT): internal/attr/noinline.h
+enc/windows_1252.$(OBJEXT): internal/attr/nonnull.h
+enc/windows_1252.$(OBJEXT): internal/attr/noreturn.h
+enc/windows_1252.$(OBJEXT): internal/attr/pure.h
+enc/windows_1252.$(OBJEXT): internal/attr/restrict.h
+enc/windows_1252.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/windows_1252.$(OBJEXT): internal/attr/warning.h
+enc/windows_1252.$(OBJEXT): internal/cast.h
+enc/windows_1252.$(OBJEXT): internal/compiler_is.h
+enc/windows_1252.$(OBJEXT): internal/compiler_is/apple.h
+enc/windows_1252.$(OBJEXT): internal/compiler_is/clang.h
+enc/windows_1252.$(OBJEXT): internal/compiler_is/gcc.h
+enc/windows_1252.$(OBJEXT): internal/compiler_is/intel.h
+enc/windows_1252.$(OBJEXT): internal/compiler_is/msvc.h
+enc/windows_1252.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/windows_1252.$(OBJEXT): internal/compiler_since.h
+enc/windows_1252.$(OBJEXT): internal/config.h
+enc/windows_1252.$(OBJEXT): internal/dllexport.h
+enc/windows_1252.$(OBJEXT): internal/dosish.h
+enc/windows_1252.$(OBJEXT): internal/has/attribute.h
+enc/windows_1252.$(OBJEXT): internal/has/builtin.h
+enc/windows_1252.$(OBJEXT): internal/has/c_attribute.h
+enc/windows_1252.$(OBJEXT): internal/has/cpp_attribute.h
+enc/windows_1252.$(OBJEXT): internal/has/declspec_attribute.h
+enc/windows_1252.$(OBJEXT): internal/has/extension.h
+enc/windows_1252.$(OBJEXT): internal/has/feature.h
+enc/windows_1252.$(OBJEXT): internal/has/warning.h
+enc/windows_1252.$(OBJEXT): internal/stdalign.h
+enc/windows_1252.$(OBJEXT): internal/stdbool.h
+enc/windows_1252.$(OBJEXT): internal/token_paste.h
+enc/windows_1252.$(OBJEXT): internal/warning_push.h
+enc/windows_1252.$(OBJEXT): internal/xmalloc.h
+enc/windows_1252.$(OBJEXT): assert.h
+enc/windows_1252.$(OBJEXT): backward/2/assume.h
+enc/windows_1252.$(OBJEXT): backward/2/attributes.h
+enc/windows_1252.$(OBJEXT): backward/2/bool.h
+enc/windows_1252.$(OBJEXT): backward/2/gcc_version_since.h
+enc/windows_1252.$(OBJEXT): backward/2/long_long.h
+enc/windows_1252.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1252.$(OBJEXT): backward/2/stdarg.h
enc/windows_1252.$(OBJEXT): config.h
enc/windows_1252.$(OBJEXT): defines.h
enc/windows_1252.$(OBJEXT): enc/iso_8859.h
@@ -691,12 +6481,114 @@ enc/windows_1252.$(OBJEXT): enc/windows_1252.c
enc/windows_1252.$(OBJEXT): missing.h
enc/windows_1252.$(OBJEXT): onigmo.h
enc/windows_1253.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1253.$(OBJEXT): internal/assume.h
+enc/windows_1253.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1253.$(OBJEXT): internal/attr/cold.h
+enc/windows_1253.$(OBJEXT): internal/attr/const.h
+enc/windows_1253.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1253.$(OBJEXT): internal/attr/error.h
+enc/windows_1253.$(OBJEXT): internal/attr/forceinline.h
+enc/windows_1253.$(OBJEXT): internal/attr/format.h
+enc/windows_1253.$(OBJEXT): internal/attr/maybe_unused.h
+enc/windows_1253.$(OBJEXT): internal/attr/nodiscard.h
+enc/windows_1253.$(OBJEXT): internal/attr/noexcept.h
+enc/windows_1253.$(OBJEXT): internal/attr/noinline.h
+enc/windows_1253.$(OBJEXT): internal/attr/nonnull.h
+enc/windows_1253.$(OBJEXT): internal/attr/noreturn.h
+enc/windows_1253.$(OBJEXT): internal/attr/pure.h
+enc/windows_1253.$(OBJEXT): internal/attr/restrict.h
+enc/windows_1253.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/windows_1253.$(OBJEXT): internal/attr/warning.h
+enc/windows_1253.$(OBJEXT): internal/cast.h
+enc/windows_1253.$(OBJEXT): internal/compiler_is.h
+enc/windows_1253.$(OBJEXT): internal/compiler_is/apple.h
+enc/windows_1253.$(OBJEXT): internal/compiler_is/clang.h
+enc/windows_1253.$(OBJEXT): internal/compiler_is/gcc.h
+enc/windows_1253.$(OBJEXT): internal/compiler_is/intel.h
+enc/windows_1253.$(OBJEXT): internal/compiler_is/msvc.h
+enc/windows_1253.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/windows_1253.$(OBJEXT): internal/compiler_since.h
+enc/windows_1253.$(OBJEXT): internal/config.h
+enc/windows_1253.$(OBJEXT): internal/dllexport.h
+enc/windows_1253.$(OBJEXT): internal/dosish.h
+enc/windows_1253.$(OBJEXT): internal/has/attribute.h
+enc/windows_1253.$(OBJEXT): internal/has/builtin.h
+enc/windows_1253.$(OBJEXT): internal/has/c_attribute.h
+enc/windows_1253.$(OBJEXT): internal/has/cpp_attribute.h
+enc/windows_1253.$(OBJEXT): internal/has/declspec_attribute.h
+enc/windows_1253.$(OBJEXT): internal/has/extension.h
+enc/windows_1253.$(OBJEXT): internal/has/feature.h
+enc/windows_1253.$(OBJEXT): internal/has/warning.h
+enc/windows_1253.$(OBJEXT): internal/stdalign.h
+enc/windows_1253.$(OBJEXT): internal/stdbool.h
+enc/windows_1253.$(OBJEXT): internal/token_paste.h
+enc/windows_1253.$(OBJEXT): internal/warning_push.h
+enc/windows_1253.$(OBJEXT): internal/xmalloc.h
+enc/windows_1253.$(OBJEXT): assert.h
+enc/windows_1253.$(OBJEXT): backward/2/assume.h
+enc/windows_1253.$(OBJEXT): backward/2/attributes.h
+enc/windows_1253.$(OBJEXT): backward/2/bool.h
+enc/windows_1253.$(OBJEXT): backward/2/gcc_version_since.h
+enc/windows_1253.$(OBJEXT): backward/2/long_long.h
+enc/windows_1253.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1253.$(OBJEXT): backward/2/stdarg.h
enc/windows_1253.$(OBJEXT): config.h
enc/windows_1253.$(OBJEXT): defines.h
enc/windows_1253.$(OBJEXT): enc/windows_1253.c
enc/windows_1253.$(OBJEXT): missing.h
enc/windows_1253.$(OBJEXT): onigmo.h
enc/windows_1254.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1254.$(OBJEXT): internal/assume.h
+enc/windows_1254.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1254.$(OBJEXT): internal/attr/cold.h
+enc/windows_1254.$(OBJEXT): internal/attr/const.h
+enc/windows_1254.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1254.$(OBJEXT): internal/attr/error.h
+enc/windows_1254.$(OBJEXT): internal/attr/forceinline.h
+enc/windows_1254.$(OBJEXT): internal/attr/format.h
+enc/windows_1254.$(OBJEXT): internal/attr/maybe_unused.h
+enc/windows_1254.$(OBJEXT): internal/attr/nodiscard.h
+enc/windows_1254.$(OBJEXT): internal/attr/noexcept.h
+enc/windows_1254.$(OBJEXT): internal/attr/noinline.h
+enc/windows_1254.$(OBJEXT): internal/attr/nonnull.h
+enc/windows_1254.$(OBJEXT): internal/attr/noreturn.h
+enc/windows_1254.$(OBJEXT): internal/attr/pure.h
+enc/windows_1254.$(OBJEXT): internal/attr/restrict.h
+enc/windows_1254.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/windows_1254.$(OBJEXT): internal/attr/warning.h
+enc/windows_1254.$(OBJEXT): internal/cast.h
+enc/windows_1254.$(OBJEXT): internal/compiler_is.h
+enc/windows_1254.$(OBJEXT): internal/compiler_is/apple.h
+enc/windows_1254.$(OBJEXT): internal/compiler_is/clang.h
+enc/windows_1254.$(OBJEXT): internal/compiler_is/gcc.h
+enc/windows_1254.$(OBJEXT): internal/compiler_is/intel.h
+enc/windows_1254.$(OBJEXT): internal/compiler_is/msvc.h
+enc/windows_1254.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/windows_1254.$(OBJEXT): internal/compiler_since.h
+enc/windows_1254.$(OBJEXT): internal/config.h
+enc/windows_1254.$(OBJEXT): internal/dllexport.h
+enc/windows_1254.$(OBJEXT): internal/dosish.h
+enc/windows_1254.$(OBJEXT): internal/has/attribute.h
+enc/windows_1254.$(OBJEXT): internal/has/builtin.h
+enc/windows_1254.$(OBJEXT): internal/has/c_attribute.h
+enc/windows_1254.$(OBJEXT): internal/has/cpp_attribute.h
+enc/windows_1254.$(OBJEXT): internal/has/declspec_attribute.h
+enc/windows_1254.$(OBJEXT): internal/has/extension.h
+enc/windows_1254.$(OBJEXT): internal/has/feature.h
+enc/windows_1254.$(OBJEXT): internal/has/warning.h
+enc/windows_1254.$(OBJEXT): internal/stdalign.h
+enc/windows_1254.$(OBJEXT): internal/stdbool.h
+enc/windows_1254.$(OBJEXT): internal/token_paste.h
+enc/windows_1254.$(OBJEXT): internal/warning_push.h
+enc/windows_1254.$(OBJEXT): internal/xmalloc.h
+enc/windows_1254.$(OBJEXT): assert.h
+enc/windows_1254.$(OBJEXT): backward/2/assume.h
+enc/windows_1254.$(OBJEXT): backward/2/attributes.h
+enc/windows_1254.$(OBJEXT): backward/2/bool.h
+enc/windows_1254.$(OBJEXT): backward/2/gcc_version_since.h
+enc/windows_1254.$(OBJEXT): backward/2/long_long.h
+enc/windows_1254.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1254.$(OBJEXT): backward/2/stdarg.h
enc/windows_1254.$(OBJEXT): config.h
enc/windows_1254.$(OBJEXT): defines.h
enc/windows_1254.$(OBJEXT): enc/iso_8859.h
@@ -704,6 +6596,57 @@ enc/windows_1254.$(OBJEXT): enc/windows_1254.c
enc/windows_1254.$(OBJEXT): missing.h
enc/windows_1254.$(OBJEXT): onigmo.h
enc/windows_1257.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_1257.$(OBJEXT): internal/assume.h
+enc/windows_1257.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_1257.$(OBJEXT): internal/attr/cold.h
+enc/windows_1257.$(OBJEXT): internal/attr/const.h
+enc/windows_1257.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_1257.$(OBJEXT): internal/attr/error.h
+enc/windows_1257.$(OBJEXT): internal/attr/forceinline.h
+enc/windows_1257.$(OBJEXT): internal/attr/format.h
+enc/windows_1257.$(OBJEXT): internal/attr/maybe_unused.h
+enc/windows_1257.$(OBJEXT): internal/attr/nodiscard.h
+enc/windows_1257.$(OBJEXT): internal/attr/noexcept.h
+enc/windows_1257.$(OBJEXT): internal/attr/noinline.h
+enc/windows_1257.$(OBJEXT): internal/attr/nonnull.h
+enc/windows_1257.$(OBJEXT): internal/attr/noreturn.h
+enc/windows_1257.$(OBJEXT): internal/attr/pure.h
+enc/windows_1257.$(OBJEXT): internal/attr/restrict.h
+enc/windows_1257.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/windows_1257.$(OBJEXT): internal/attr/warning.h
+enc/windows_1257.$(OBJEXT): internal/cast.h
+enc/windows_1257.$(OBJEXT): internal/compiler_is.h
+enc/windows_1257.$(OBJEXT): internal/compiler_is/apple.h
+enc/windows_1257.$(OBJEXT): internal/compiler_is/clang.h
+enc/windows_1257.$(OBJEXT): internal/compiler_is/gcc.h
+enc/windows_1257.$(OBJEXT): internal/compiler_is/intel.h
+enc/windows_1257.$(OBJEXT): internal/compiler_is/msvc.h
+enc/windows_1257.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/windows_1257.$(OBJEXT): internal/compiler_since.h
+enc/windows_1257.$(OBJEXT): internal/config.h
+enc/windows_1257.$(OBJEXT): internal/dllexport.h
+enc/windows_1257.$(OBJEXT): internal/dosish.h
+enc/windows_1257.$(OBJEXT): internal/has/attribute.h
+enc/windows_1257.$(OBJEXT): internal/has/builtin.h
+enc/windows_1257.$(OBJEXT): internal/has/c_attribute.h
+enc/windows_1257.$(OBJEXT): internal/has/cpp_attribute.h
+enc/windows_1257.$(OBJEXT): internal/has/declspec_attribute.h
+enc/windows_1257.$(OBJEXT): internal/has/extension.h
+enc/windows_1257.$(OBJEXT): internal/has/feature.h
+enc/windows_1257.$(OBJEXT): internal/has/warning.h
+enc/windows_1257.$(OBJEXT): internal/stdalign.h
+enc/windows_1257.$(OBJEXT): internal/stdbool.h
+enc/windows_1257.$(OBJEXT): internal/token_paste.h
+enc/windows_1257.$(OBJEXT): internal/warning_push.h
+enc/windows_1257.$(OBJEXT): internal/xmalloc.h
+enc/windows_1257.$(OBJEXT): assert.h
+enc/windows_1257.$(OBJEXT): backward/2/assume.h
+enc/windows_1257.$(OBJEXT): backward/2/attributes.h
+enc/windows_1257.$(OBJEXT): backward/2/bool.h
+enc/windows_1257.$(OBJEXT): backward/2/gcc_version_since.h
+enc/windows_1257.$(OBJEXT): backward/2/long_long.h
+enc/windows_1257.$(OBJEXT): backward/2/stdalign.h
+enc/windows_1257.$(OBJEXT): backward/2/stdarg.h
enc/windows_1257.$(OBJEXT): config.h
enc/windows_1257.$(OBJEXT): defines.h
enc/windows_1257.$(OBJEXT): enc/iso_8859.h
@@ -711,6 +6654,57 @@ enc/windows_1257.$(OBJEXT): enc/windows_1257.c
enc/windows_1257.$(OBJEXT): missing.h
enc/windows_1257.$(OBJEXT): onigmo.h
enc/windows_31j.$(OBJEXT): $(top_srcdir)/regenc.h
+enc/windows_31j.$(OBJEXT): internal/assume.h
+enc/windows_31j.$(OBJEXT): internal/attr/alloc_size.h
+enc/windows_31j.$(OBJEXT): internal/attr/cold.h
+enc/windows_31j.$(OBJEXT): internal/attr/const.h
+enc/windows_31j.$(OBJEXT): internal/attr/deprecated.h
+enc/windows_31j.$(OBJEXT): internal/attr/error.h
+enc/windows_31j.$(OBJEXT): internal/attr/forceinline.h
+enc/windows_31j.$(OBJEXT): internal/attr/format.h
+enc/windows_31j.$(OBJEXT): internal/attr/maybe_unused.h
+enc/windows_31j.$(OBJEXT): internal/attr/nodiscard.h
+enc/windows_31j.$(OBJEXT): internal/attr/noexcept.h
+enc/windows_31j.$(OBJEXT): internal/attr/noinline.h
+enc/windows_31j.$(OBJEXT): internal/attr/nonnull.h
+enc/windows_31j.$(OBJEXT): internal/attr/noreturn.h
+enc/windows_31j.$(OBJEXT): internal/attr/pure.h
+enc/windows_31j.$(OBJEXT): internal/attr/restrict.h
+enc/windows_31j.$(OBJEXT): internal/attr/returns_nonnull.h
+enc/windows_31j.$(OBJEXT): internal/attr/warning.h
+enc/windows_31j.$(OBJEXT): internal/cast.h
+enc/windows_31j.$(OBJEXT): internal/compiler_is.h
+enc/windows_31j.$(OBJEXT): internal/compiler_is/apple.h
+enc/windows_31j.$(OBJEXT): internal/compiler_is/clang.h
+enc/windows_31j.$(OBJEXT): internal/compiler_is/gcc.h
+enc/windows_31j.$(OBJEXT): internal/compiler_is/intel.h
+enc/windows_31j.$(OBJEXT): internal/compiler_is/msvc.h
+enc/windows_31j.$(OBJEXT): internal/compiler_is/sunpro.h
+enc/windows_31j.$(OBJEXT): internal/compiler_since.h
+enc/windows_31j.$(OBJEXT): internal/config.h
+enc/windows_31j.$(OBJEXT): internal/dllexport.h
+enc/windows_31j.$(OBJEXT): internal/dosish.h
+enc/windows_31j.$(OBJEXT): internal/has/attribute.h
+enc/windows_31j.$(OBJEXT): internal/has/builtin.h
+enc/windows_31j.$(OBJEXT): internal/has/c_attribute.h
+enc/windows_31j.$(OBJEXT): internal/has/cpp_attribute.h
+enc/windows_31j.$(OBJEXT): internal/has/declspec_attribute.h
+enc/windows_31j.$(OBJEXT): internal/has/extension.h
+enc/windows_31j.$(OBJEXT): internal/has/feature.h
+enc/windows_31j.$(OBJEXT): internal/has/warning.h
+enc/windows_31j.$(OBJEXT): internal/stdalign.h
+enc/windows_31j.$(OBJEXT): internal/stdbool.h
+enc/windows_31j.$(OBJEXT): internal/token_paste.h
+enc/windows_31j.$(OBJEXT): internal/warning_push.h
+enc/windows_31j.$(OBJEXT): internal/xmalloc.h
+enc/windows_31j.$(OBJEXT): assert.h
+enc/windows_31j.$(OBJEXT): backward/2/assume.h
+enc/windows_31j.$(OBJEXT): backward/2/attributes.h
+enc/windows_31j.$(OBJEXT): backward/2/bool.h
+enc/windows_31j.$(OBJEXT): backward/2/gcc_version_since.h
+enc/windows_31j.$(OBJEXT): backward/2/long_long.h
+enc/windows_31j.$(OBJEXT): backward/2/stdalign.h
+enc/windows_31j.$(OBJEXT): backward/2/stdarg.h
enc/windows_31j.$(OBJEXT): config.h
enc/windows_31j.$(OBJEXT): defines.h
enc/windows_31j.$(OBJEXT): enc/jis/props.h
diff --git a/enc/encdb.c b/enc/encdb.c
index a41e4edc6d..a1936df804 100644
--- a/enc/encdb.c
+++ b/enc/encdb.c
@@ -9,7 +9,7 @@
**********************************************************************/
-#include "internal.h"
+#include "internal/encoding.h"
#define ENC_REPLICATE(name, orig) rb_encdb_replicate((name), (orig))
#define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
diff --git a/enc/euc_jp.c b/enc/euc_jp.c
index ded051af69..d283bf4ebb 100644
--- a/enc/euc_jp.c
+++ b/enc/euc_jp.c
@@ -593,7 +593,7 @@ ENC_ALIAS("eucJP", "EUC-JP") /* UI-OSF Application Platform Profile for Japanese
* Name: eucJP-ms
* Link: http://home.m05.itscom.net/numa/cde/ucs-conv/ucs-conv.html
* Link: http://www2d.biglobe.ne.jp/~msyk/charcode/cp932/eucJP-ms.html
- * Link: http://ja.wikipedia.org/wiki/EUC-JP
+ * Link: https://ja.wikipedia.org/wiki/EUC-JP
*/
ENC_REPLICATE("eucJP-ms", "EUC-JP") /* TOG/JVC CDE/Motif Technical WG */
ENC_ALIAS("euc-jp-ms", "eucJP-ms")
@@ -610,7 +610,7 @@ ENC_REPLICATE("CP51932", "EUC-JP")
/*
* Name: EUC-JIS-2004
- * Link: http://ja.wikipedia.org/wiki/EUC-JIS-2004
+ * Link: https://ja.wikipedia.org/wiki/EUC-JIS-2004
*/
ENC_REPLICATE("EUC-JIS-2004", "EUC-JP") /* defined at JIS X 0213:2004 */
ENC_ALIAS("EUC-JISX0213", "EUC-JIS-2004") /* defined at JIS X 0213:2000, and obsolete at JIS X 0213:2004 */
diff --git a/enc/iso_8859_11.c b/enc/iso_8859_11.c
index 85e8f2cdb4..b9c6119fd9 100644
--- a/enc/iso_8859_11.c
+++ b/enc/iso_8859_11.c
@@ -102,7 +102,7 @@ ENC_ALIAS("ISO8859-11", "ISO-8859-11")
/*
* Name: TIS-620
* MIBenum: 2259
- * Link: http://en.wikipedia.org/wiki/Thai_Industrial_Standard_620-2533
+ * Link: https://en.wikipedia.org/wiki/Thai_Industrial_Standard_620-2533
*/
ENC_REPLICATE("TIS-620", "ISO-8859-11")
diff --git a/enc/iso_8859_6.c b/enc/iso_8859_6.c
index 6d852ac8c0..cdb74054d1 100644
--- a/enc/iso_8859_6.c
+++ b/enc/iso_8859_6.c
@@ -104,7 +104,7 @@ ENC_ALIAS("ISO8859-6", "ISO-8859-6")
* MIBenum: 2256
* Link: http://www.iana.org/assignments/character-sets
* Link: http://www.microsoft.com/globaldev/reference/sbcs/1256.mspx
- * Link: http://en.wikipedia.org/wiki/Windows-1256
+ * Link: https://en.wikipedia.org/wiki/Windows-1256
*/
ENC_REPLICATE("Windows-1256", "ISO-8859-6")
ENC_ALIAS("CP1256", "Windows-1256")
diff --git a/enc/iso_8859_8.c b/enc/iso_8859_8.c
index 0a7a29e82e..e256855f21 100644
--- a/enc/iso_8859_8.c
+++ b/enc/iso_8859_8.c
@@ -104,7 +104,7 @@ ENC_ALIAS("ISO8859-8", "ISO-8859-8")
* MIBenum: 2255
* Link: http://www.iana.org/assignments/character-sets
* Link: http://www.microsoft.com/globaldev/reference/sbcs/1255.mspx
- * Link: http://en.wikipedia.org/wiki/Windows-1255
+ * Link: https://en.wikipedia.org/wiki/Windows-1255
*/
ENC_REPLICATE("Windows-1255", "ISO-8859-8")
ENC_ALIAS("CP1255", "Windows-1255")
diff --git a/enc/shift_jis.c b/enc/shift_jis.c
index 65fd5102de..f1355d2d95 100644
--- a/enc/shift_jis.c
+++ b/enc/shift_jis.c
@@ -55,13 +55,13 @@ OnigEncodingDefine(shift_jis, Shift_JIS) = {
* Name: Shift_JIS
* MIBenum: 17
* Link: http://www.iana.org/assignments/character-sets
- * Link: http://ja.wikipedia.org/wiki/Shift_JIS
+ * Link: https://ja.wikipedia.org/wiki/Shift_JIS
*/
/*
* Name: MacJapanese
* Link: http://unicode.org/Public/MAPPINGS/VENDORS/APPLE/JAPANESE.TXT
- * Link: http://ja.wikipedia.org/wiki/MacJapanese
+ * Link: https://ja.wikipedia.org/wiki/MacJapanese
*/
ENC_REPLICATE("MacJapanese", "Shift_JIS")
ENC_ALIAS("MacJapan", "MacJapanese")
diff --git a/enc/trans/escape.trans b/enc/trans/escape.trans
index c76ffa0e06..36d9dd0f13 100644
--- a/enc/trans/escape.trans
+++ b/enc/trans/escape.trans
@@ -18,9 +18,10 @@
], nil)
transcode_tblgen("", "xml_attr_content_escape", [
- ["{00-21,23-25,27-3B,3D,3F-FF}", :nomap],
+ ["{00-21,23-25,28-3B,3D,3F-FF}", :nomap],
["22", hexstr("&quot;")],
["26", hexstr("&amp;")],
+ ["27", hexstr("&apos;")],
["3C", hexstr("&lt;")],
["3E", hexstr("&gt;")]
], nil)
diff --git a/enc/trans/ibm720-tbl.rb b/enc/trans/ibm720-tbl.rb
new file mode 100644
index 0000000000..558684d649
--- /dev/null
+++ b/enc/trans/ibm720-tbl.rb
@@ -0,0 +1,122 @@
+IBM720_TO_UCS_TBL = [
+ ["FF",0xA0],
+ ["9C",0xA3],
+ ["94",0xA4],
+ ["AE",0xAB],
+ ["F8",0xB0],
+ ["FD",0xB2],
+ ["E6",0xB5],
+ ["FA",0xB7],
+ ["AF",0xBB],
+ ["85",0xE0],
+ ["83",0xE2],
+ ["87",0xE7],
+ ["8A",0xE8],
+ ["82",0xE9],
+ ["88",0xEA],
+ ["89",0xEB],
+ ["8C",0xEE],
+ ["8B",0xEF],
+ ["93",0xF4],
+ ["97",0xF9],
+ ["96",0xFB],
+ ["98",0x621],
+ ["99",0x622],
+ ["9A",0x623],
+ ["9B",0x624],
+ ["9D",0x625],
+ ["9E",0x626],
+ ["9F",0x627],
+ ["A0",0x628],
+ ["A1",0x629],
+ ["A2",0x62A],
+ ["A3",0x62B],
+ ["A4",0x62C],
+ ["A5",0x62D],
+ ["A6",0x62E],
+ ["A7",0x62F],
+ ["A8",0x630],
+ ["A9",0x631],
+ ["AA",0x632],
+ ["AB",0x633],
+ ["AC",0x634],
+ ["AD",0x635],
+ ["E0",0x636],
+ ["E1",0x637],
+ ["E2",0x638],
+ ["E3",0x639],
+ ["E4",0x63A],
+ ["95",0x640],
+ ["E5",0x641],
+ ["E7",0x642],
+ ["E8",0x643],
+ ["E9",0x644],
+ ["EA",0x645],
+ ["EB",0x646],
+ ["EC",0x647],
+ ["ED",0x648],
+ ["EE",0x649],
+ ["EF",0x64A],
+ ["F1",0x64B],
+ ["F2",0x64C],
+ ["F3",0x64D],
+ ["F4",0x64E],
+ ["F5",0x64F],
+ ["F6",0x650],
+ ["91",0x651],
+ ["92",0x652],
+ ["FC",0x207F],
+ ["F9",0x2219],
+ ["FB",0x221A],
+ ["F7",0x2248],
+ ["F0",0x2261],
+ ["C4",0x2500],
+ ["B3",0x2502],
+ ["DA",0x250C],
+ ["BF",0x2510],
+ ["C0",0x2514],
+ ["D9",0x2518],
+ ["C3",0x251C],
+ ["B4",0x2524],
+ ["C2",0x252C],
+ ["C1",0x2534],
+ ["C5",0x253C],
+ ["CD",0x2550],
+ ["BA",0x2551],
+ ["D5",0x2552],
+ ["D6",0x2553],
+ ["C9",0x2554],
+ ["B8",0x2555],
+ ["B7",0x2556],
+ ["BB",0x2557],
+ ["D4",0x2558],
+ ["D3",0x2559],
+ ["C8",0x255A],
+ ["BE",0x255B],
+ ["BD",0x255C],
+ ["BC",0x255D],
+ ["C6",0x255E],
+ ["C7",0x255F],
+ ["CC",0x2560],
+ ["B5",0x2561],
+ ["B6",0x2562],
+ ["B9",0x2563],
+ ["D1",0x2564],
+ ["D2",0x2565],
+ ["CB",0x2566],
+ ["CF",0x2567],
+ ["D0",0x2568],
+ ["CA",0x2569],
+ ["D8",0x256A],
+ ["D7",0x256B],
+ ["CE",0x256C],
+ ["DF",0x2580],
+ ["DC",0x2584],
+ ["DB",0x2588],
+ ["DD",0x258C],
+ ["DE",0x2590],
+ ["B0",0x2591],
+ ["B1",0x2592],
+ ["B2",0x2593],
+ ["FE",0x25A0],
+]
diff --git a/enc/trans/newline.trans b/enc/trans/newline.trans
index a200ec00a7..9e763407f9 100644
--- a/enc/trans/newline.trans
+++ b/enc/trans/newline.trans
@@ -98,7 +98,7 @@ rb_universal_newline = {
2, /* max_output */
asciicompat_converter, /* asciicompat_type */
2, universal_newline_init, universal_newline_init, /* state_size, state_init, state_fini */
- NULL, NULL, NULL, fun_so_universal_newline,
+ 0, 0, 0, fun_so_universal_newline,
universal_newline_finish
};
@@ -110,8 +110,8 @@ rb_crlf_newline = {
1, /* max_input */
2, /* max_output */
asciicompat_converter, /* asciicompat_type */
- 0, NULL, NULL, /* state_size, state_init, state_fini */
- NULL, NULL, NULL, NULL
+ 0, 0, 0, /* state_size, state_init, state_fini */
+ 0, 0, 0, 0
};
static const rb_transcoder
@@ -122,8 +122,8 @@ rb_cr_newline = {
1, /* max_input */
1, /* max_output */
asciicompat_converter, /* asciicompat_type */
- 0, NULL, NULL, /* state_size, state_init, state_fini */
- NULL, NULL, NULL, NULL
+ 0, 0, 0, /* state_size, state_init, state_fini */
+ 0, 0, 0, 0
};
void
diff --git a/enc/trans/single_byte.trans b/enc/trans/single_byte.trans
index cf521bed38..0d5407b918 100644
--- a/enc/trans/single_byte.trans
+++ b/enc/trans/single_byte.trans
@@ -51,8 +51,9 @@
transcode_tblgen_singlebyte "WINDOWS-1256"
transcode_tblgen_singlebyte "WINDOWS-1257"
transcode_tblgen_singlebyte "IBM437"
- transcode_tblgen_singlebyte "IBM775"
+ transcode_tblgen_singlebyte "IBM720"
transcode_tblgen_singlebyte "IBM737"
+ transcode_tblgen_singlebyte "IBM775"
transcode_tblgen_singlebyte "IBM852"
transcode_tblgen_singlebyte "IBM855"
transcode_tblgen_singlebyte "IBM857"
diff --git a/enc/unicode.c b/enc/unicode.c
index 6e8c3d8816..18fba02476 100644
--- a/enc/unicode.c
+++ b/enc/unicode.c
@@ -493,6 +493,10 @@ onigenc_unicode_get_case_fold_codes_by_str(OnigEncoding enc,
#endif
if ((to = onigenc_unicode_fold_lookup(code)) != 0) {
+ if (OnigCodePointCount(to->n) == 0) {
+ /* any codepoint should not be empty */
+ UNREACHABLE_RETURN(0);
+ }
if (OnigCodePointCount(to->n) == 1) {
OnigCodePoint orig_code = code;
diff --git a/enc/unicode/case-folding.rb b/enc/unicode/case-folding.rb
index 362d6ebfd9..4a29fdebf7 100755..100644
--- a/enc/unicode/case-folding.rb
+++ b/enc/unicode/case-folding.rb
@@ -232,7 +232,7 @@ class CaseMapping
@version = nil
IO.foreach(File.join(mapping_directory, 'UnicodeData.txt'), mode: "rb") do |line|
next if line =~ /^</
- code, _1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11, upper, lower, title = line.chomp.split ';'
+ code, _, _, _, _, _, _, _, _, _, _, _, upper, lower, title = line.chomp.split ';'
unless upper and lower and title and (upper+lower+title)==''
@mappings[code] = MapItem.new(code, upper, lower, title)
end
diff --git a/enc/windows_1250.c b/enc/windows_1250.c
index d2cf7b16bc..daf23e9d1e 100644
--- a/enc/windows_1250.c
+++ b/enc/windows_1250.c
@@ -266,6 +266,6 @@ OnigEncodingDefine(windows_1250, Windows_1250) = {
* MIBenum: 2251
* Link: http://www.iana.org/assignments/character-sets
* Link: http://www.microsoft.com/globaldev/reference/sbcs/1250.mspx
- * Link: http://en.wikipedia.org/wiki/Windows-1250
+ * Link: https://en.wikipedia.org/wiki/Windows-1250
*/
ENC_ALIAS("CP1250", "Windows-1250")
diff --git a/enc/windows_1251.c b/enc/windows_1251.c
index fcd0f1015d..6c892c1b8c 100644
--- a/enc/windows_1251.c
+++ b/enc/windows_1251.c
@@ -248,6 +248,6 @@ OnigEncodingDefine(windows_1251, Windows_1251) = {
* MIBenum: 2251
* Link: http://www.iana.org/assignments/character-sets
* Link: http://www.microsoft.com/globaldev/reference/sbcs/1251.mspx
- * Link: http://en.wikipedia.org/wiki/Windows-1251
+ * Link: https://en.wikipedia.org/wiki/Windows-1251
*/
ENC_ALIAS("CP1251", "Windows-1251")
diff --git a/enc/windows_1252.c b/enc/windows_1252.c
index 5f90c15601..b685878d3f 100644
--- a/enc/windows_1252.c
+++ b/enc/windows_1252.c
@@ -255,6 +255,6 @@ OnigEncodingDefine(windows_1252, Windows_1252) = {
* MIBenum: 2251
* Link: http://www.iana.org/assignments/character-sets
* Link: http://www.microsoft.com/globaldev/reference/sbcs/1252.mspx
- * Link: http://en.wikipedia.org/wiki/Windows-1252
+ * Link: https://en.wikipedia.org/wiki/Windows-1252
*/
ENC_ALIAS("CP1252", "Windows-1252")
diff --git a/enc/windows_1253.c b/enc/windows_1253.c
index 9e9c63a581..b2a43581c3 100644
--- a/enc/windows_1253.c
+++ b/enc/windows_1253.c
@@ -32,7 +32,7 @@
* MIBenum: 2253
* Link: http://www.iana.org/assignments/character-sets
* Link: http://www.microsoft.com/globaldev/reference/sbcs/1253.mspx
- * Link: http://en.wikipedia.org/wiki/Windows-1253
+ * Link: https://en.wikipedia.org/wiki/Windows-1253
*/
#include "regenc.h"
diff --git a/enc/windows_1254.c b/enc/windows_1254.c
index 9ae66978a2..5e6d92d3d2 100644
--- a/enc/windows_1254.c
+++ b/enc/windows_1254.c
@@ -32,7 +32,7 @@
* MIBenum: 2254
* Link: http://www.iana.org/assignments/character-sets
* Link: http://www.microsoft.com/globaldev/reference/sbcs/1254.mspx
- * Link: http://en.wikipedia.org/wiki/Windows-1254
+ * Link: https://en.wikipedia.org/wiki/Windows-1254
*/
#include "regenc.h"
diff --git a/enc/windows_1257.c b/enc/windows_1257.c
index 936a94ac76..ada03b72bf 100644
--- a/enc/windows_1257.c
+++ b/enc/windows_1257.c
@@ -35,7 +35,7 @@
* MIBenum: 2257
* Link: http://www.iana.org/assignments/character-sets
* Link: http://www.microsoft.com/globaldev/reference/sbcs/1257.mspx
- * Link: http://en.wikipedia.org/wiki/Windows-1257
+ * Link: https://en.wikipedia.org/wiki/Windows-1257
*/
#define ENC_CP1252_TO_LOWER_CASE(c) EncCP1252_ToLowerCaseTable[c]
diff --git a/enc/windows_31j.c b/enc/windows_31j.c
index e3a468f414..1eb859596a 100644
--- a/enc/windows_31j.c
+++ b/enc/windows_31j.c
@@ -57,7 +57,7 @@ OnigEncodingDefine(windows_31j, Windows_31J) = {
* MIBenum: 2024
* Link: http://www.iana.org/assignments/character-sets
* Link: http://www.microsoft.com/globaldev/reference/dbcs/932.mspx
- * Link: http://ja.wikipedia.org/wiki/Windows-31J
+ * Link: https://ja.wikipedia.org/wiki/Windows-31J
* Link: http://source.icu-project.org/repos/icu/data/trunk/charset/data/ucm/windows-932-2000.ucm
*
* Windows Standard Character Set and its mapping to Unicode by Microsoft.
diff --git a/encindex.h b/encindex.h
index 658b60a9fd..8457a7b39f 100644
--- a/encindex.h
+++ b/encindex.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_ENCINDEX_H
+#define RUBY_ENCINDEX_H 1
/**********************************************************************
encindex.h -
@@ -9,8 +11,7 @@
**********************************************************************/
-#ifndef RUBY_ENCINDEX_H
-#define RUBY_ENCINDEX_H 1
+#include "ruby/encoding.h" /* rb_ascii8bit_encindex etc. */
#if defined(__cplusplus)
extern "C" {
#if 0
diff --git a/encoding.c b/encoding.c
index 69015cc8fd..32d5a349eb 100644
--- a/encoding.c
+++ b/encoding.c
@@ -9,14 +9,25 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "internal.h"
+#include "ruby/internal/config.h"
+
+#include <ctype.h>
+
#include "encindex.h"
+#include "internal.h"
+#include "internal/enc.h"
+#include "internal/encoding.h"
+#include "internal/inits.h"
+#include "internal/load.h"
+#include "internal/object.h"
+#include "internal/string.h"
+#include "internal/vm.h"
#include "regenc.h"
-#include <ctype.h>
+#include "ruby/encoding.h"
#include "ruby/util.h"
-
#include "ruby_assert.h"
+#include "vm_sync.h"
+
#ifndef ENC_DEBUG
#define ENC_DEBUG 0
#endif
@@ -44,7 +55,10 @@ void rb_encdb_set_unicode(int index);
static ID id_encoding;
VALUE rb_cEncoding;
-static VALUE rb_encoding_list;
+
+#define DEFAULT_ENCODING_LIST_CAPA 128
+static VALUE rb_default_encoding_list;
+static VALUE rb_additional_encoding_list;
struct rb_encoding_entry {
const char *name;
@@ -52,12 +66,27 @@ struct rb_encoding_entry {
rb_encoding *base;
};
-static struct {
+static struct enc_table {
struct rb_encoding_entry *list;
int count;
int size;
st_table *names;
-} enc_table;
+} global_enc_table;
+
+static rb_encoding *global_enc_ascii,
+ *global_enc_utf_8,
+ *global_enc_us_ascii;
+
+#define GLOBAL_ENC_TABLE_ENTER(enc_table) struct enc_table *enc_table = &global_enc_table; RB_VM_LOCK_ENTER()
+#define GLOBAL_ENC_TABLE_LEAVE() RB_VM_LOCK_LEAVE()
+#define GLOBAL_ENC_TABLE_EVAL(enc_table, expr) do { \
+ GLOBAL_ENC_TABLE_ENTER(enc_table); \
+ { \
+ expr; \
+ } \
+ GLOBAL_ENC_TABLE_LEAVE(); \
+} while (0)
+
#define ENC_DUMMY_FLAG (1<<24)
#define ENC_INDEX_MASK (~(~0U<<24))
@@ -72,10 +101,6 @@ static struct {
#define ENCODING_NAMELEN_MAX 63
#define valid_encoding_name_p(name) ((name) && strlen(name) <= ENCODING_NAMELEN_MAX)
-#define enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
-
-static int load_encoding(const char *name);
-
static const rb_data_type_t encoding_data_type = {
"encoding",
{0, 0, 0,},
@@ -94,22 +119,69 @@ rb_data_is_encoding(VALUE obj)
static VALUE
enc_new(rb_encoding *encoding)
{
- return TypedData_Wrap_Struct(rb_cEncoding, &encoding_data_type, (void *)encoding);
+ VALUE enc = TypedData_Wrap_Struct(rb_cEncoding, &encoding_data_type, (void *)encoding);
+ rb_obj_freeze(enc);
+ FL_SET_RAW(enc, RUBY_FL_SHAREABLE);
+ return enc;
+}
+
+static void
+enc_list_update(int index, rb_raw_encoding *encoding)
+{
+ if (index < DEFAULT_ENCODING_LIST_CAPA) {
+ VALUE list = rb_default_encoding_list;
+ if (list && NIL_P(rb_ary_entry(list, index))) {
+ /* initialize encoding data */
+ rb_ary_store(list, index, enc_new(encoding));
+ }
+ }
+ else {
+ RB_VM_LOCK_ENTER();
+ {
+ VALUE list = rb_additional_encoding_list;
+ if (list && NIL_P(rb_ary_entry(list, index))) {
+ /* initialize encoding data */
+ rb_ary_store(list, index - DEFAULT_ENCODING_LIST_CAPA, enc_new(encoding));
+ }
+ }
+ RB_VM_LOCK_LEAVE();
+ }
}
static VALUE
-rb_enc_from_encoding_index(int idx)
+enc_list_lookup(int idx)
{
VALUE list, enc;
- if (!(list = rb_encoding_list)) {
- rb_bug("rb_enc_from_encoding_index(%d): no rb_encoding_list", idx);
+ if (idx < DEFAULT_ENCODING_LIST_CAPA) {
+ if (!(list = rb_default_encoding_list)) {
+ rb_bug("rb_enc_from_encoding_index(%d): no rb_default_encoding_list", idx);
+ }
+ enc = rb_ary_entry(list, idx);
}
- enc = rb_ary_entry(list, idx);
+ else {
+ RB_VM_LOCK_ENTER();
+ {
+ if (!(list = rb_additional_encoding_list)) {
+ rb_bug("rb_enc_from_encoding_index(%d): no rb_additional_encoding_list", idx);
+ }
+ enc = rb_ary_entry(list, idx - DEFAULT_ENCODING_LIST_CAPA);
+ }
+ RB_VM_LOCK_LEAVE();
+ }
+
if (NIL_P(enc)) {
- rb_bug("rb_enc_from_encoding_index(%d): not created yet", idx);
+ rb_bug("rb_enc_from_encoding_index(%d): not created yet", idx);
+ }
+ else {
+ return enc;
}
- return enc;
+}
+
+static VALUE
+rb_enc_from_encoding_index(int idx)
+{
+ return enc_list_lookup(idx);
}
VALUE
@@ -133,16 +205,14 @@ rb_enc_dummy_p(rb_encoding *enc)
return ENC_DUMMY_P(enc) != 0;
}
-static int enc_autoload(rb_encoding *);
-
static int
check_encoding(rb_encoding *enc)
{
int index = rb_enc_to_index(enc);
if (rb_enc_from_index(index) != enc)
return -1;
- if (enc_autoload_p(enc)) {
- index = enc_autoload(enc);
+ if (rb_enc_autoload_p(enc)) {
+ index = rb_enc_autoload(enc);
}
return index;
}
@@ -186,7 +256,7 @@ must_encindex(int index)
rb_raise(rb_eEncodingError, "wrong encoding index %d for %s (expected %d)",
index, rb_enc_name(enc), ENC_TO_ENCINDEX(enc));
}
- if (enc_autoload_p(enc) && enc_autoload(enc) == -1) {
+ if (rb_enc_autoload_p(enc) && rb_enc_autoload(enc) == -1) {
rb_loaderror("failed to load encoding (%s)",
rb_enc_name(enc));
}
@@ -197,6 +267,7 @@ int
rb_to_encoding_index(VALUE enc)
{
int idx;
+ const char *name;
idx = enc_check_encoding(enc);
if (idx >= 0) {
@@ -208,20 +279,33 @@ rb_to_encoding_index(VALUE enc)
if (!rb_enc_asciicompat(rb_enc_get(enc))) {
return -1;
}
- return rb_enc_find_index(StringValueCStr(enc));
+ if (!(name = rb_str_to_cstr(enc))) {
+ return -1;
+ }
+ return rb_enc_find_index(name);
+}
+
+static const char *
+name_for_encoding(volatile VALUE *enc)
+{
+ VALUE name = StringValue(*enc);
+ const char *n;
+
+ if (!rb_enc_asciicompat(rb_enc_get(name))) {
+ rb_raise(rb_eArgError, "invalid encoding name (non ASCII)");
+ }
+ if (!(n = rb_str_to_cstr(name))) {
+ rb_raise(rb_eArgError, "invalid encoding name (NUL byte)");
+ }
+ return n;
}
/* Returns encoding index or UNSPECIFIED_ENCODING */
static int
str_find_encindex(VALUE enc)
{
- int idx;
-
- StringValue(enc);
- if (!rb_enc_asciicompat(rb_enc_get(enc))) {
- rb_raise(rb_eArgError, "invalid name encoding (non ASCII)");
- }
- idx = rb_enc_find_index(StringValueCStr(enc));
+ int idx = rb_enc_find_index(name_for_encoding(&enc));
+ RB_GC_GUARD(enc);
return idx;
}
@@ -259,26 +343,25 @@ rb_find_encoding(VALUE enc)
}
static int
-enc_table_expand(int newsize)
+enc_table_expand(struct enc_table *enc_table, int newsize)
{
struct rb_encoding_entry *ent;
int count = newsize;
- if (enc_table.size >= newsize) return newsize;
+ if (enc_table->size >= newsize) return newsize;
newsize = (newsize + 7) / 8 * 8;
- ent = REALLOC_N(enc_table.list, struct rb_encoding_entry, newsize);
- memset(ent + enc_table.size, 0, sizeof(*ent)*(newsize - enc_table.size));
- enc_table.list = ent;
- enc_table.size = newsize;
+ ent = REALLOC_N(enc_table->list, struct rb_encoding_entry, newsize);
+ memset(ent + enc_table->size, 0, sizeof(*ent)*(newsize - enc_table->size));
+ enc_table->list = ent;
+ enc_table->size = newsize;
return count;
}
static int
-enc_register_at(int index, const char *name, rb_encoding *base_encoding)
+enc_register_at(struct enc_table *enc_table, int index, const char *name, rb_encoding *base_encoding)
{
- struct rb_encoding_entry *ent = &enc_table.list[index];
+ struct rb_encoding_entry *ent = &enc_table->list[index];
rb_raw_encoding *encoding;
- VALUE list;
if (!valid_encoding_name_p(name)) return -1;
if (!ent->name) {
@@ -300,76 +383,120 @@ enc_register_at(int index, const char *name, rb_encoding *base_encoding)
encoding->name = name;
encoding->ruby_encoding_index = index;
ent->enc = encoding;
- st_insert(enc_table.names, (st_data_t)name, (st_data_t)index);
- list = rb_encoding_list;
- if (list && NIL_P(rb_ary_entry(list, index))) {
- /* initialize encoding data */
- rb_ary_store(list, index, enc_new(encoding));
- }
+ st_insert(enc_table->names, (st_data_t)name, (st_data_t)index);
+
+ enc_list_update(index, encoding);
return index;
}
static int
-enc_register(const char *name, rb_encoding *encoding)
+enc_register(struct enc_table *enc_table, const char *name, rb_encoding *encoding)
{
- int index = enc_table.count;
+ int index = enc_table->count;
- if ((index = enc_table_expand(index + 1)) < 0) return -1;
- enc_table.count = index;
- return enc_register_at(index - 1, name, encoding);
+ enc_table->count = enc_table_expand(enc_table, index + 1);
+ return enc_register_at(enc_table, index, name, encoding);
}
static void set_encoding_const(const char *, rb_encoding *);
-int rb_enc_registered(const char *name);
+static int enc_registered(struct enc_table *enc_table, const char *name);
+
+static rb_encoding *
+enc_from_index(struct enc_table *enc_table, int index)
+{
+ if (UNLIKELY(index < 0 || enc_table->count <= (index &= ENC_INDEX_MASK))) {
+ return 0;
+ }
+ return enc_table->list[index].enc;
+}
+
+rb_encoding *
+rb_enc_from_index(int index)
+{
+ rb_encoding *enc;
+
+ switch (index) {
+ case ENCINDEX_ASCII: return global_enc_ascii;
+ case ENCINDEX_UTF_8: return global_enc_utf_8;
+ case ENCINDEX_US_ASCII: return global_enc_us_ascii;
+ default:
+ GLOBAL_ENC_TABLE_EVAL(enc_table,
+ enc = enc_from_index(enc_table, index));
+ return enc;
+ }
+}
int
rb_enc_register(const char *name, rb_encoding *encoding)
{
- int index = rb_enc_registered(name);
+ int index;
+
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ index = enc_registered(enc_table, name);
+
+ if (index >= 0) {
+ rb_encoding *oldenc = enc_from_index(enc_table, index);
+ if (STRCASECMP(name, rb_enc_name(oldenc))) {
+ index = enc_register(enc_table, name, encoding);
+ }
+ else if (rb_enc_autoload_p(oldenc) || !ENC_DUMMY_P(oldenc)) {
+ enc_register_at(enc_table, index, name, encoding);
+ }
+ else {
+ rb_raise(rb_eArgError, "encoding %s is already registered", name);
+ }
+ }
+ else {
+ index = enc_register(enc_table, name, encoding);
+ set_encoding_const(name, rb_enc_from_index(index));
+ }
+ }
+ GLOBAL_ENC_TABLE_LEAVE();
+ return index;
+}
- if (index >= 0) {
- rb_encoding *oldenc = rb_enc_from_index(index);
- if (STRCASECMP(name, rb_enc_name(oldenc))) {
- index = enc_register(name, encoding);
- }
- else if (enc_autoload_p(oldenc) || !ENC_DUMMY_P(oldenc)) {
- enc_register_at(index, name, encoding);
- }
- else {
- rb_raise(rb_eArgError, "encoding %s is already registered", name);
- }
- }
- else {
- index = enc_register(name, encoding);
- set_encoding_const(name, rb_enc_from_index(index));
+int
+enc_registered(struct enc_table *enc_table, const char *name)
+{
+ st_data_t idx = 0;
+
+ if (!name) return -1;
+ if (!enc_table->list) return -1;
+ if (st_lookup(enc_table->names, (st_data_t)name, &idx)) {
+ return (int)idx;
}
- return index;
+ return -1;
}
void
rb_encdb_declare(const char *name)
{
- int idx = rb_enc_registered(name);
- if (idx < 0) {
- idx = enc_register(name, 0);
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ int idx = enc_registered(enc_table, name);
+ if (idx < 0) {
+ idx = enc_register(enc_table, name, 0);
+ }
+ set_encoding_const(name, rb_enc_from_index(idx));
}
- set_encoding_const(name, rb_enc_from_index(idx));
+ GLOBAL_ENC_TABLE_LEAVE();
}
static void
-enc_check_duplication(const char *name)
+enc_check_duplication(struct enc_table *enc_table, const char *name)
{
- if (rb_enc_registered(name) >= 0) {
+ if (enc_registered(enc_table, name) >= 0) {
rb_raise(rb_eArgError, "encoding %s is already registered", name);
}
}
static rb_encoding*
-set_base_encoding(int index, rb_encoding *base)
+set_base_encoding(struct enc_table *enc_table, int index, rb_encoding *base)
{
- rb_encoding *enc = enc_table.list[index].enc;
+ rb_encoding *enc = enc_table->list[index].enc;
- enc_table.list[index].base = base;
+ enc_table->list[index].base = base;
if (ENC_DUMMY_P(base)) ENC_SET_DUMMY((rb_raw_encoding *)enc);
return enc;
}
@@ -381,9 +508,13 @@ set_base_encoding(int index, rb_encoding *base)
void
rb_enc_set_base(const char *name, const char *orig)
{
- int idx = rb_enc_registered(name);
- int origidx = rb_enc_registered(orig);
- set_base_encoding(idx, rb_enc_from_index(origidx));
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ int idx = enc_registered(enc_table, name);
+ int origidx = enc_registered(enc_table, orig);
+ set_base_encoding(enc_table, idx, rb_enc_from_index(origidx));
+ }
+ GLOBAL_ENC_TABLE_LEAVE();
}
/* for encdb.h
@@ -392,24 +523,39 @@ rb_enc_set_base(const char *name, const char *orig)
int
rb_enc_set_dummy(int index)
{
- rb_encoding *enc = enc_table.list[index].enc;
+ rb_encoding *enc;
+
+ GLOBAL_ENC_TABLE_EVAL(enc_table,
+ enc = enc_table->list[index].enc);
ENC_SET_DUMMY((rb_raw_encoding *)enc);
return index;
}
-int
-rb_enc_replicate(const char *name, rb_encoding *encoding)
+static int
+enc_replicate(struct enc_table *enc_table, const char *name, rb_encoding *encoding)
{
int idx;
- enc_check_duplication(name);
- idx = enc_register(name, encoding);
- set_base_encoding(idx, encoding);
+ enc_check_duplication(enc_table, name);
+ idx = enc_register(enc_table, name, encoding);
+ if (idx < 0) rb_raise(rb_eArgError, "invalid encoding name: %s", name);
+ set_base_encoding(enc_table, idx, encoding);
set_encoding_const(name, rb_enc_from_index(idx));
return idx;
}
+int
+rb_enc_replicate(const char *name, rb_encoding *encoding)
+{
+ int r;
+
+ GLOBAL_ENC_TABLE_EVAL(enc_table,
+ r = enc_replicate(enc_table, name, encoding));
+
+ return r;
+}
+
/*
* call-seq:
* enc.replicate(name) -> encoding
@@ -420,24 +566,24 @@ rb_enc_replicate(const char *name, rb_encoding *encoding)
*
*/
static VALUE
-enc_replicate(VALUE encoding, VALUE name)
+enc_replicate_m(VALUE encoding, VALUE name)
{
- return rb_enc_from_encoding_index(
- rb_enc_replicate(StringValueCStr(name),
- rb_to_encoding(encoding)));
+ int idx = rb_enc_replicate(name_for_encoding(&name), rb_to_encoding(encoding));
+ RB_GC_GUARD(name);
+ return rb_enc_from_encoding_index(idx);
}
static int
-enc_replicate_with_index(const char *name, rb_encoding *origenc, int idx)
+enc_replicate_with_index(struct enc_table *enc_table, const char *name, rb_encoding *origenc, int idx)
{
if (idx < 0) {
- idx = enc_register(name, origenc);
+ idx = enc_register(enc_table, name, origenc);
}
else {
- idx = enc_register_at(idx, name, origenc);
+ idx = enc_register_at(enc_table, idx, name, origenc);
}
if (idx >= 0) {
- set_base_encoding(idx, origenc);
+ set_base_encoding(enc_table, idx, origenc);
set_encoding_const(name, rb_enc_from_index(idx));
}
else {
@@ -449,33 +595,54 @@ enc_replicate_with_index(const char *name, rb_encoding *origenc, int idx)
int
rb_encdb_replicate(const char *name, const char *orig)
{
- int origidx = rb_enc_registered(orig);
- int idx = rb_enc_registered(name);
+ int r;
+
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ int origidx = enc_registered(enc_table, orig);
+ int idx = enc_registered(enc_table, name);
- if (origidx < 0) {
- origidx = enc_register(orig, 0);
+ if (origidx < 0) {
+ origidx = enc_register(enc_table, orig, 0);
+ }
+ r = enc_replicate_with_index(enc_table, name, rb_enc_from_index(origidx), idx);
}
- return enc_replicate_with_index(name, rb_enc_from_index(origidx), idx);
+ GLOBAL_ENC_TABLE_LEAVE();
+
+ return r;
}
int
rb_define_dummy_encoding(const char *name)
{
- int index = rb_enc_replicate(name, rb_ascii8bit_encoding());
- rb_encoding *enc = enc_table.list[index].enc;
+ int index;
+
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ index = enc_replicate(enc_table, name, rb_ascii8bit_encoding());
+ rb_encoding *enc = enc_table->list[index].enc;
+ ENC_SET_DUMMY((rb_raw_encoding *)enc);
+ }
+ GLOBAL_ENC_TABLE_LEAVE();
- ENC_SET_DUMMY((rb_raw_encoding *)enc);
return index;
}
int
rb_encdb_dummy(const char *name)
{
- int index = enc_replicate_with_index(name, rb_ascii8bit_encoding(),
- rb_enc_registered(name));
- rb_encoding *enc = enc_table.list[index].enc;
+ int index;
+
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ index = enc_replicate_with_index(enc_table, name,
+ rb_ascii8bit_encoding(),
+ enc_registered(enc_table, name));
+ rb_encoding *enc = enc_table->list[index].enc;
+ ENC_SET_DUMMY((rb_raw_encoding *)enc);
+ }
+ GLOBAL_ENC_TABLE_LEAVE();
- ENC_SET_DUMMY((rb_raw_encoding *)enc);
return index;
}
@@ -534,42 +701,58 @@ enc_dup_name(st_data_t name)
* else returns NULL.
*/
static int
-enc_alias_internal(const char *alias, int idx)
+enc_alias_internal(struct enc_table *enc_table, const char *alias, int idx)
{
- return st_insert2(enc_table.names, (st_data_t)alias, (st_data_t)idx,
+ return st_insert2(enc_table->names, (st_data_t)alias, (st_data_t)idx,
enc_dup_name);
}
static int
-enc_alias(const char *alias, int idx)
+enc_alias(struct enc_table *enc_table, const char *alias, int idx)
{
if (!valid_encoding_name_p(alias)) return -1;
- if (!enc_alias_internal(alias, idx))
- set_encoding_const(alias, rb_enc_from_index(idx));
+ if (!enc_alias_internal(enc_table, alias, idx))
+ set_encoding_const(alias, enc_from_index(enc_table, idx));
return idx;
}
int
rb_enc_alias(const char *alias, const char *orig)
{
- int idx;
+ int idx, r;
- enc_check_duplication(alias);
- if ((idx = rb_enc_find_index(orig)) < 0) {
- return -1;
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ enc_check_duplication(enc_table, alias);
+ if ((idx = rb_enc_find_index(orig)) < 0) {
+ r = -1;
+ }
+ else {
+ r = enc_alias(enc_table, alias, idx);
+ }
}
- return enc_alias(alias, idx);
+ GLOBAL_ENC_TABLE_LEAVE();
+
+ return r;
}
int
rb_encdb_alias(const char *alias, const char *orig)
{
- int idx = rb_enc_registered(orig);
+ int r;
- if (idx < 0) {
- idx = enc_register(orig, 0);
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ int idx = enc_registered(enc_table, orig);
+
+ if (idx < 0) {
+ idx = enc_register(enc_table, orig, 0);
+ }
+ r = enc_alias(enc_table, alias, idx);
}
- return enc_alias(alias, idx);
+ GLOBAL_ENC_TABLE_LEAVE();
+
+ return r;
}
void
@@ -578,19 +761,22 @@ rb_encdb_set_unicode(int index)
((rb_raw_encoding *)rb_enc_from_index(index))->flags |= ONIGENC_FLAG_UNICODE;
}
-void
-rb_enc_init(void)
+static void
+rb_enc_init(struct enc_table *enc_table)
{
- enc_table_expand(ENCODING_COUNT + 1);
- if (!enc_table.names) {
- enc_table.names = st_init_strcasetable();
+ enc_table_expand(enc_table, ENCODING_COUNT + 1);
+ if (!enc_table->names) {
+ enc_table->names = st_init_strcasetable();
}
-#define ENC_REGISTER(enc) enc_register_at(ENCINDEX_##enc, rb_enc_name(&OnigEncoding##enc), &OnigEncoding##enc)
+#define ENC_REGISTER(enc) enc_register_at(enc_table, ENCINDEX_##enc, rb_enc_name(&OnigEncoding##enc), &OnigEncoding##enc)
ENC_REGISTER(ASCII);
ENC_REGISTER(UTF_8);
ENC_REGISTER(US_ASCII);
+ global_enc_ascii = enc_table->list[ENCINDEX_ASCII].enc;
+ global_enc_utf_8 = enc_table->list[ENCINDEX_UTF_8].enc;
+ global_enc_us_ascii = enc_table->list[ENCINDEX_US_ASCII].enc;
#undef ENC_REGISTER
-#define ENCDB_REGISTER(name, enc) enc_register_at(ENCINDEX_##enc, name, NULL)
+#define ENCDB_REGISTER(name, enc) enc_register_at(enc_table, ENCINDEX_##enc, name, NULL)
ENCDB_REGISTER("UTF-16BE", UTF_16BE);
ENCDB_REGISTER("UTF-16LE", UTF_16LE);
ENCDB_REGISTER("UTF-32BE", UTF_32BE);
@@ -602,16 +788,7 @@ rb_enc_init(void)
ENCDB_REGISTER("EUC-JP", EUC_JP);
ENCDB_REGISTER("Windows-31J", Windows_31J);
#undef ENCDB_REGISTER
- enc_table.count = ENCINDEX_BUILTIN_MAX;
-}
-
-rb_encoding *
-rb_enc_from_index(int index)
-{
- if (UNLIKELY(index < 0 || enc_table.count <= (index &= ENC_INDEX_MASK))) {
- return 0;
- }
- return enc_table.list[index].enc;
+ enc_table->count = ENCINDEX_BUILTIN_MAX;
}
rb_encoding *
@@ -620,19 +797,6 @@ rb_enc_get_from_index(int index)
return must_encindex(index);
}
-int
-rb_enc_registered(const char *name)
-{
- st_data_t idx = 0;
-
- if (!name) return -1;
- if (!enc_table.list) return -1;
- if (st_lookup(enc_table.names, (st_data_t)name, &idx)) {
- return (int)idx;
- }
- return -1;
-}
-
static int
load_encoding(const char *name)
{
@@ -657,33 +821,55 @@ load_encoding(const char *name)
ruby_verbose = verbose;
ruby_debug = debug;
rb_set_errinfo(errinfo);
- if (loaded < 0 || 1 < loaded) return -1;
- if ((idx = rb_enc_registered(name)) < 0) return -1;
- if (enc_autoload_p(enc_table.list[idx].enc)) return -1;
+
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ if (loaded < 0 || 1 < loaded) {
+ idx = -1;
+ }
+ else if ((idx = enc_registered(enc_table, name)) < 0) {
+ idx = -1;
+ }
+ else if (rb_enc_autoload_p(enc_table->list[idx].enc)) {
+ idx = -1;
+ }
+ }
+ GLOBAL_ENC_TABLE_LEAVE();
+
return idx;
}
static int
-enc_autoload(rb_encoding *enc)
+enc_autoload_body(struct enc_table *enc_table, rb_encoding *enc)
{
- int i;
- rb_encoding *base = enc_table.list[ENC_TO_ENCINDEX(enc)].base;
+ rb_encoding *base = enc_table->list[ENC_TO_ENCINDEX(enc)].base;
if (base) {
- i = 0;
+ int i = 0;
do {
- if (i >= enc_table.count) return -1;
- } while (enc_table.list[i].enc != base && (++i, 1));
- if (enc_autoload_p(base)) {
- if (enc_autoload(base) < 0) return -1;
+ if (i >= enc_table->count) return -1;
+ } while (enc_table->list[i].enc != base && (++i, 1));
+ if (rb_enc_autoload_p(base)) {
+ if (rb_enc_autoload(base) < 0) return -1;
}
i = enc->ruby_encoding_index;
- enc_register_at(i & ENC_INDEX_MASK, rb_enc_name(enc), base);
- ((rb_raw_encoding *)enc)->ruby_encoding_index = i;
+ enc_register_at(enc_table, i & ENC_INDEX_MASK, rb_enc_name(enc), base);
+ ((rb_raw_encoding *)enc)->ruby_encoding_index = i;
i &= ENC_INDEX_MASK;
+ return i;
}
else {
- i = load_encoding(rb_enc_name(enc));
+ return -2;
+ }
+}
+
+int
+rb_enc_autoload(rb_encoding *enc)
+{
+ int i;
+ GLOBAL_ENC_TABLE_EVAL(enc_table, i = enc_autoload_body(enc_table, enc));
+ if (i == -2) {
+ i = load_encoding(rb_enc_name(enc));
}
return i;
}
@@ -692,9 +878,11 @@ enc_autoload(rb_encoding *enc)
int
rb_enc_find_index(const char *name)
{
- int i = rb_enc_registered(name);
+ int i;
rb_encoding *enc;
+ GLOBAL_ENC_TABLE_EVAL(enc_table, i = enc_registered(enc_table, name));
+
if (i < 0) {
i = load_encoding(name);
}
@@ -703,8 +891,8 @@ rb_enc_find_index(const char *name)
rb_raise(rb_eArgError, "encoding %s is not registered", name);
}
}
- else if (enc_autoload_p(enc)) {
- if (enc_autoload(enc) < 0) {
+ else if (rb_enc_autoload_p(enc)) {
+ if (rb_enc_autoload(enc) < 0) {
rb_warn("failed to load encoding (%s); use ASCII-8BIT instead",
name);
return 0;
@@ -769,8 +957,18 @@ enc_get_index_str(VALUE str)
if (i == ENCODING_INLINE_MAX) {
VALUE iv;
+#if 0
iv = rb_ivar_get(str, rb_id_encoding());
i = NUM2INT(iv);
+#else
+ /*
+ * Tentatively, assume ASCII-8BIT, if encoding index instance
+ * variable is not found. This can happen when freeing after
+ * all instance variables are removed in `obj_free`.
+ */
+ iv = rb_attr_get(str, rb_id_encoding());
+ i = NIL_P(iv) ? ENCINDEX_ASCII : NUM2INT(iv);
+#endif
}
return i;
}
@@ -909,7 +1107,7 @@ enc_compatible_latter(VALUE str1, VALUE str2, int idx1, int idx2)
if (isstr2 && RSTRING_LEN(str2) == 0)
return enc1;
isstr1 = RB_TYPE_P(str1, T_STRING);
- if (isstr1 && RSTRING_LEN(str1) == 0)
+ if (isstr1 && isstr2 && RSTRING_LEN(str1) == 0)
return (rb_enc_asciicompat(enc1) && rb_enc_str_asciionly_p(str2)) ? enc1 : enc2;
if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) {
return 0;
@@ -1138,7 +1336,7 @@ enc_inspect(VALUE self)
"#<%"PRIsVALUE":%s%s%s>", rb_obj_class(self),
rb_enc_name(enc),
(ENC_DUMMY_P(enc) ? " (dummy)" : ""),
- enc_autoload_p(enc) ? " (autoload)" : "");
+ rb_enc_autoload_p(enc) ? " (autoload)" : "");
}
/*
@@ -1183,7 +1381,10 @@ enc_names(VALUE self)
args[0] = (VALUE)rb_to_encoding_index(self);
args[1] = rb_ary_new2(0);
- st_foreach(enc_table.names, enc_names_i, (st_data_t)args);
+
+ GLOBAL_ENC_TABLE_EVAL(enc_table,
+ st_foreach(enc_table->names, enc_names_i, (st_data_t)args));
+
return args[1];
}
@@ -1209,7 +1410,14 @@ static VALUE
enc_list(VALUE klass)
{
VALUE ary = rb_ary_new2(0);
- rb_ary_replace(ary, rb_encoding_list);
+
+ RB_VM_LOCK_ENTER();
+ {
+ rb_ary_replace(ary, rb_default_encoding_list);
+ rb_ary_concat(ary, rb_additional_encoding_list);
+ }
+ RB_VM_LOCK_LEAVE();
+
return ary;
}
@@ -1282,12 +1490,13 @@ enc_compatible_p(VALUE klass, VALUE str1, VALUE str2)
return rb_enc_from_encoding(enc);
}
+NORETURN(static VALUE enc_s_alloc(VALUE klass));
/* :nodoc: */
static VALUE
enc_s_alloc(VALUE klass)
{
rb_undefined_alloc(klass);
- return Qnil;
+ UNREACHABLE_RETURN(Qnil);
}
/* :nodoc: */
@@ -1315,7 +1524,7 @@ enc_m_loader(VALUE klass, VALUE str)
rb_encoding *
rb_ascii8bit_encoding(void)
{
- return enc_table.list[ENCINDEX_ASCII].enc;
+ return global_enc_ascii;
}
int
@@ -1327,7 +1536,7 @@ rb_ascii8bit_encindex(void)
rb_encoding *
rb_utf8_encoding(void)
{
- return enc_table.list[ENCINDEX_UTF_8].enc;
+ return global_enc_utf_8;
}
int
@@ -1339,7 +1548,7 @@ rb_utf8_encindex(void)
rb_encoding *
rb_usascii_encoding(void)
{
- return enc_table.list[ENCINDEX_US_ASCII].enc;
+ return global_enc_us_ascii;
}
int
@@ -1355,15 +1564,17 @@ rb_locale_encindex(void)
{
int idx = rb_locale_charmap_index();
- if (idx < 0) idx = ENCINDEX_ASCII;
+ if (idx < 0) idx = ENCINDEX_UTF_8;
- if (rb_enc_registered("locale") < 0) {
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ if (enc_registered(enc_table, "locale") < 0) {
# if defined _WIN32
void Init_w32_codepage(void);
Init_w32_codepage();
# endif
- enc_alias_internal("locale", idx);
+ enc_alias_internal(enc_table, "locale", idx);
}
+ GLOBAL_ENC_TABLE_LEAVE();
return idx;
}
@@ -1377,7 +1588,11 @@ rb_locale_encoding(void)
int
rb_filesystem_encindex(void)
{
- int idx = rb_enc_registered("filesystem");
+ int idx;
+
+ GLOBAL_ENC_TABLE_EVAL(enc_table,
+ idx = enc_registered(enc_table, "filesystem"));
+
if (idx < 0)
idx = ENCINDEX_ASCII;
return idx;
@@ -1405,20 +1620,25 @@ enc_set_default_encoding(struct default_encoding *def, VALUE encoding, const cha
/* Already set */
overridden = TRUE;
- if (NIL_P(encoding)) {
- def->index = -1;
- def->enc = 0;
- st_insert(enc_table.names, (st_data_t)strdup(name),
- (st_data_t)UNSPECIFIED_ENCODING);
- }
- else {
- def->index = rb_enc_to_index(rb_to_encoding(encoding));
- def->enc = 0;
- enc_alias_internal(name, def->index);
- }
-
- if (def == &default_external)
- enc_alias_internal("filesystem", Init_enc_set_filesystem_encoding());
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ if (NIL_P(encoding)) {
+ def->index = -1;
+ def->enc = 0;
+ st_insert(enc_table->names, (st_data_t)strdup(name),
+ (st_data_t)UNSPECIFIED_ENCODING);
+ }
+ else {
+ def->index = rb_enc_to_index(rb_to_encoding(encoding));
+ def->enc = 0;
+ enc_alias_internal(enc_table, name, def->index);
+ }
+
+ if (def == &default_external) {
+ enc_alias_internal(enc_table, "filesystem", Init_enc_set_filesystem_encoding());
+ }
+ }
+ GLOBAL_ENC_TABLE_LEAVE();
return overridden;
}
@@ -1465,9 +1685,11 @@ rb_enc_default_external(void)
* encoding may not be valid. Be sure to check String#valid_encoding?.
*
* File data written to disk will be transcoded to the default external
- * encoding when written.
+ * encoding when written, if default_internal is not nil.
*
- * The default external encoding is initialized by the locale or -E option.
+ * The default external encoding is initialized by the -E option.
+ * If -E isn't set, it is initialized to UTF-8 on Windows and the locale on
+ * other operating systems.
*/
static VALUE
get_default_external(VALUE klass)
@@ -1550,8 +1772,7 @@ rb_enc_default_internal(void)
* The script encoding (__ENCODING__), not default_internal, is used as the
* encoding of created strings.
*
- * Encoding::default_internal is initialized by the source file's
- * internal_encoding or -E option.
+ * Encoding::default_internal is initialized with -E option or nil otherwise.
*/
static VALUE
get_default_internal(VALUE klass)
@@ -1664,8 +1885,15 @@ rb_enc_name_list_i(st_data_t name, st_data_t idx, st_data_t arg)
static VALUE
rb_enc_name_list(VALUE klass)
{
- VALUE ary = rb_ary_new2(enc_table.names->num_entries);
- st_foreach(enc_table.names, rb_enc_name_list_i, (st_data_t)ary);
+ VALUE ary;
+
+ GLOBAL_ENC_TABLE_ENTER(enc_table);
+ {
+ ary = rb_ary_new2(enc_table->names->num_entries);
+ st_foreach(enc_table->names, rb_enc_name_list_i, (st_data_t)ary);
+ }
+ GLOBAL_ENC_TABLE_LEAVE();
+
return ary;
}
@@ -1710,7 +1938,10 @@ rb_enc_aliases(VALUE klass)
VALUE aliases[2];
aliases[0] = rb_hash_new();
aliases[1] = rb_ary_new();
- st_foreach(enc_table.names, rb_enc_aliases_enc_i, (st_data_t)aliases);
+
+ GLOBAL_ENC_TABLE_EVAL(enc_table,
+ st_foreach(enc_table->names, rb_enc_aliases_enc_i, (st_data_t)aliases));
+
return aliases[0];
}
@@ -1918,8 +2149,6 @@ rb_enc_aliases(VALUE klass)
void
Init_Encoding(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
VALUE list;
int i;
@@ -1932,7 +2161,7 @@ Init_Encoding(void)
rb_define_method(rb_cEncoding, "names", enc_names, 0);
rb_define_method(rb_cEncoding, "dummy?", enc_dummy_p, 0);
rb_define_method(rb_cEncoding, "ascii_compatible?", enc_ascii_compatible_p, 0);
- rb_define_method(rb_cEncoding, "replicate", enc_replicate, 1);
+ rb_define_method(rb_cEncoding, "replicate", enc_replicate_m, 1);
rb_define_singleton_method(rb_cEncoding, "list", enc_list, 0);
rb_define_singleton_method(rb_cEncoding, "name_list", rb_enc_name_list, 0);
rb_define_singleton_method(rb_cEncoding, "aliases", rb_enc_aliases, 0);
@@ -1948,22 +2177,29 @@ Init_Encoding(void)
rb_define_singleton_method(rb_cEncoding, "default_internal=", set_default_internal, 1);
rb_define_singleton_method(rb_cEncoding, "locale_charmap", rb_locale_charmap, 0); /* in localeinit.c */
- list = rb_ary_new2(enc_table.count);
+ struct enc_table *enc_table = &global_enc_table;
+
+ if (DEFAULT_ENCODING_LIST_CAPA < enc_table->count) rb_bug("DEFAULT_ENCODING_LIST_CAPA is too small");
+
+ list = rb_additional_encoding_list = rb_ary_new();
+ RBASIC_CLEAR_CLASS(list);
+ rb_gc_register_mark_object(list);
+
+ list = rb_default_encoding_list = rb_ary_new2(DEFAULT_ENCODING_LIST_CAPA);
RBASIC_CLEAR_CLASS(list);
- rb_encoding_list = list;
rb_gc_register_mark_object(list);
- for (i = 0; i < enc_table.count; ++i) {
- rb_ary_push(list, enc_new(enc_table.list[i].enc));
+ for (i = 0; i < enc_table->count; ++i) {
+ rb_ary_push(list, enc_new(enc_table->list[i].enc));
}
- rb_marshal_define_compat(rb_cEncoding, Qnil, NULL, enc_m_loader);
+ rb_marshal_define_compat(rb_cEncoding, Qnil, 0, enc_m_loader);
}
void
Init_encodings(void)
{
- rb_enc_init();
+ rb_enc_init(&global_enc_table);
}
/* locale insensitive ctype functions */
@@ -1971,5 +2207,5 @@ Init_encodings(void)
void
rb_enc_foreach_name(int (*func)(st_data_t name, st_data_t idx, st_data_t arg), st_data_t arg)
{
- st_foreach(enc_table.names, func, arg);
+ GLOBAL_ENC_TABLE_EVAL(enc_table, st_foreach(enc_table->names, func, arg));
}
diff --git a/enum.c b/enum.c
index de4d22d92e..b1a617d585 100644
--- a/enum.c
+++ b/enum.c
@@ -9,14 +9,21 @@
**********************************************************************/
-#include "ruby/encoding.h"
+#include "id.h"
#include "internal.h"
+#include "internal/compar.h"
+#include "internal/enum.h"
+#include "internal/hash.h"
+#include "internal/imemo.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/proc.h"
+#include "internal/rational.h"
+#include "internal/re.h"
#include "ruby/util.h"
-#include "id.h"
+#include "ruby_assert.h"
#include "symbol.h"
-#include <assert.h>
-
VALUE rb_mEnumerable;
static ID id_next;
@@ -76,6 +83,22 @@ grep_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
}
static VALUE
+grep_regexp_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
+{
+ struct MEMO *memo = MEMO_CAST(args);
+ VALUE converted_element, match;
+ ENUM_WANT_SVALUE();
+
+ /* In case element can't be converted to a Symbol or String: not a match (don't raise) */
+ converted_element = SYMBOL_P(i) ? i : rb_check_string_type(i);
+ match = NIL_P(converted_element) ? Qfalse : rb_reg_match_p(memo->v1, i, 0);
+ if (match == memo->u3.value) {
+ rb_ary_push(memo->v2, i);
+ }
+ return Qnil;
+}
+
+static VALUE
grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
{
struct MEMO *memo = MEMO_CAST(args);
@@ -87,6 +110,27 @@ grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
return Qnil;
}
+static VALUE
+enum_grep0(VALUE obj, VALUE pat, VALUE test)
+{
+ VALUE ary = rb_ary_new();
+ struct MEMO *memo = MEMO_NEW(pat, ary, test);
+ rb_block_call_func_t fn;
+ if (rb_block_given_p()) {
+ fn = grep_iter_i;
+ }
+ else if (RB_TYPE_P(pat, T_REGEXP) &&
+ LIKELY(rb_method_basic_definition_p(CLASS_OF(pat), idEqq))) {
+ fn = grep_regexp_i;
+ }
+ else {
+ fn = grep_i;
+ }
+ rb_block_call(obj, id_each, 0, 0, fn, (VALUE)memo);
+
+ return ary;
+}
+
/*
* call-seq:
* enum.grep(pattern) -> array
@@ -108,12 +152,7 @@ grep_iter_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
static VALUE
enum_grep(VALUE obj, VALUE pat)
{
- VALUE ary = rb_ary_new();
- struct MEMO *memo = MEMO_NEW(pat, ary, Qtrue);
-
- rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo);
-
- return ary;
+ return enum_grep0(obj, pat, Qtrue);
}
/*
@@ -134,12 +173,7 @@ enum_grep(VALUE obj, VALUE pat)
static VALUE
enum_grep_v(VALUE obj, VALUE pat)
{
- VALUE ary = rb_ary_new();
- struct MEMO *memo = MEMO_NEW(pat, ary, Qfalse);
-
- rb_block_call(obj, id_each, 0, 0, rb_block_given_p() ? grep_iter_i : grep_i, (VALUE)memo);
-
- return ary;
+ return enum_grep0(obj, pat, Qfalse);
}
#define COUNT_BIGNUM IMEMO_FL_USER0
@@ -728,7 +762,7 @@ inject_op_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, p))
}
else if (SYMBOL_P(name = memo->u3.value)) {
const ID mid = SYM2ID(name);
- MEMO_V1_SET(memo, rb_funcallv(memo->v1, mid, 1, &i));
+ MEMO_V1_SET(memo, rb_funcallv_public(memo->v1, mid, 1, &i));
}
else {
VALUE args[2];
@@ -1015,6 +1049,7 @@ enum_tally(VALUE obj)
return enum_hashify(obj, 0, 0, tally_i);
}
+NORETURN(static VALUE first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params)));
static VALUE
first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, params))
{
@@ -1756,7 +1791,7 @@ min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
* enum.min(n) { |a, b| block } -> array
*
* Returns the object in _enum_ with the minimum value. The
- * first form assumes all objects implement Comparable;
+ * first form assumes all objects implement <code><=></code>;
* the second uses the block to return <em>a <=> b</em>.
*
* a = %w(albatross dog horse)
@@ -1848,7 +1883,7 @@ max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
* enum.max(n) { |a, b| block } -> array
*
* Returns the object in _enum_ with the maximum value. The
- * first form assumes all objects implement Comparable;
+ * first form assumes all objects implement <code><=></code>;
* the second uses the block to return <em>a <=> b</em>.
*
* a = %w(albatross dog horse)
@@ -2007,7 +2042,7 @@ minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
*
* Returns a two element array which contains the minimum and the
* maximum value in the enumerable. The first form assumes all
- * objects implement Comparable; the second uses the
+ * objects implement <code><=></code>; the second uses the
* block to return <em>a <=> b</em>.
*
* a = %w(albatross dog horse)
@@ -3196,7 +3231,7 @@ chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
* The following example counts words for each initial letter.
*
* open("/usr/share/dict/words", "r:iso-8859-1") { |f|
- * f.chunk { |line| line.ord }.each { |ch, lines| p [ch.chr, lines.length] }
+ * f.chunk { |line| line.upcase.ord }.each { |ch, lines| p [ch.chr, lines.length] }
* }
* #=> ["\n", 1]
* # ["A", 1327]
@@ -3694,7 +3729,7 @@ slicewhen_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
* Creates an enumerator for each chunked elements.
* The beginnings of chunks are defined by the block.
*
- * This method split each chunk using adjacent elements,
+ * This method splits each chunk using adjacent elements,
* _elt_before_ and _elt_after_,
* in the receiver enumerator.
* This method split chunks between _elt_before_ and _elt_after_ where
@@ -3773,7 +3808,7 @@ enum_slice_when(VALUE enumerable)
* Creates an enumerator for each chunked elements.
* The beginnings of chunks are defined by the block.
*
- * This method split each chunk using adjacent elements,
+ * This method splits each chunk using adjacent elements,
* _elt_before_ and _elt_after_,
* in the receiver enumerator.
* This method split chunks between _elt_before_ and _elt_after_ where
@@ -3841,122 +3876,141 @@ struct enum_sum_memo {
};
static void
-sum_iter(VALUE i, struct enum_sum_memo *memo)
+sum_iter_normalize_memo(struct enum_sum_memo *memo)
{
- const int unused = (assert(memo != NULL), 0);
+ assert(FIXABLE(memo->n));
+ memo->v = rb_fix_plus(LONG2FIX(memo->n), memo->v);
+ memo->n = 0;
- long n = memo->n;
- VALUE v = memo->v;
- VALUE r = memo->r;
- double f = memo->f;
- double c = memo->c;
+ switch (TYPE(memo->r)) {
+ case T_RATIONAL: memo->v = rb_rational_plus(memo->r, memo->v); break;
+ case T_UNDEF: break;
+ default: UNREACHABLE; /* or ...? */
+ }
+ memo->r = Qundef;
+}
- if (memo->block_given)
- i = rb_yield(i);
+static void
+sum_iter_fixnum(VALUE i, struct enum_sum_memo *memo)
+{
+ memo->n += FIX2LONG(i); /* should not overflow long type */
+ if (! FIXABLE(memo->n)) {
+ memo->v = rb_big_plus(LONG2NUM(memo->n), memo->v);
+ memo->n = 0;
+ }
+}
- if (memo->float_value)
- goto float_value;
+static void
+sum_iter_bignum(VALUE i, struct enum_sum_memo *memo)
+{
+ memo->v = rb_big_plus(i, memo->v);
+}
- if (FIXNUM_P(v) || RB_TYPE_P(v, T_BIGNUM) || RB_TYPE_P(v, T_RATIONAL)) {
- if (FIXNUM_P(i)) {
- n += FIX2LONG(i); /* should not overflow long type */
- if (!FIXABLE(n)) {
- v = rb_big_plus(LONG2NUM(n), v);
- n = 0;
- }
- }
- else if (RB_TYPE_P(i, T_BIGNUM))
- v = rb_big_plus(i, v);
- else if (RB_TYPE_P(i, T_RATIONAL)) {
- if (r == Qundef)
- r = i;
- else
- r = rb_rational_plus(r, i);
- }
- else {
- if (n != 0) {
- v = rb_fix_plus(LONG2FIX(n), v);
- n = 0;
- }
- if (r != Qundef) {
- /* r can be an Integer when mathn is loaded */
- if (FIXNUM_P(r))
- v = rb_fix_plus(r, v);
- else if (RB_TYPE_P(r, T_BIGNUM))
- v = rb_big_plus(r, v);
- else
- v = rb_rational_plus(r, v);
- r = Qundef;
- }
- if (RB_FLOAT_TYPE_P(i)) {
- f = NUM2DBL(v);
- c = 0.0;
- memo->float_value = 1;
- goto float_value;
- }
- else
- goto some_value;
- }
+static void
+sum_iter_rational(VALUE i, struct enum_sum_memo *memo)
+{
+ if (memo->r == Qundef) {
+ memo->r = i;
}
- else if (RB_FLOAT_TYPE_P(v)) {
- /*
- * Kahan-Babuska balancing compensated summation algorithm
- * See http://link.springer.com/article/10.1007/s00607-005-0139-x
- */
- double x, t;
-
- float_value:
- if (RB_FLOAT_TYPE_P(i))
- x = RFLOAT_VALUE(i);
- else if (FIXNUM_P(i))
- x = FIX2LONG(i);
- else if (RB_TYPE_P(i, T_BIGNUM))
- x = rb_big2dbl(i);
- else if (RB_TYPE_P(i, T_RATIONAL))
- x = rb_num2dbl(i);
- else {
- v = DBL2NUM(f);
- memo->float_value = 0;
- goto some_value;
- }
+ else {
+ memo->r = rb_rational_plus(memo->r, i);
+ }
+}
- if (isnan(f)) return;
- if (isnan(x)) {
- memo->v = i;
- memo->f = x;
- return;
- }
- if (isinf(x)) {
- if (isinf(f) && signbit(x) != signbit(f)) {
- memo->f = NAN;
- memo->v = DBL2NUM(f);
- }
- else {
- memo->f = x;
- memo->v = i;
- }
- return;
+static void
+sum_iter_some_value(VALUE i, struct enum_sum_memo *memo)
+{
+ memo->v = rb_funcallv(memo->v, idPLUS, 1, &i);
+}
+
+static void
+sum_iter_Kahan_Babuska(VALUE i, struct enum_sum_memo *memo)
+{
+ /*
+ * Kahan-Babuska balancing compensated summation algorithm
+ * See https://link.springer.com/article/10.1007/s00607-005-0139-x
+ */
+ double x;
+
+ switch (TYPE(i)) {
+ case T_FLOAT: x = RFLOAT_VALUE(i); break;
+ case T_FIXNUM: x = FIX2LONG(i); break;
+ case T_BIGNUM: x = rb_big2dbl(i); break;
+ case T_RATIONAL: x = rb_num2dbl(i); break;
+ default:
+ memo->v = DBL2NUM(memo->f);
+ memo->float_value = 0;
+ sum_iter_some_value(i, memo);
+ return;
+ }
+
+ double f = memo->f;
+
+ if (isnan(f)) {
+ return;
+ }
+ else if (! isfinite(x)) {
+ if (isinf(x) && isinf(f) && signbit(x) != signbit(f)) {
+ i = DBL2NUM(f);
+ x = nan("");
}
- if (isinf(f)) return;
+ memo->v = i;
+ memo->f = x;
+ return;
+ }
+ else if (isinf(f)) {
+ return;
+ }
- t = f + x;
- if (fabs(f) >= fabs(x))
- c += ((f - t) + x);
- else
- c += ((x - t) + f);
- f = t;
+ double c = memo->c;
+ double t = f + x;
+
+ if (fabs(f) >= fabs(x)) {
+ c += ((f - t) + x);
}
else {
- some_value:
- v = rb_funcallv(v, idPLUS, 1, &i);
+ c += ((x - t) + f);
}
+ f = t;
- memo->v = v;
- memo->n = n;
- memo->r = r;
memo->f = f;
memo->c = c;
- (void)unused;
+}
+
+static void
+sum_iter(VALUE i, struct enum_sum_memo *memo)
+{
+ assert(memo != NULL);
+ if (memo->block_given) {
+ i = rb_yield(i);
+ }
+
+ if (memo->float_value) {
+ sum_iter_Kahan_Babuska(i, memo);
+ }
+ else switch (TYPE(memo->v)) {
+ default: sum_iter_some_value(i, memo); return;
+ case T_FLOAT: sum_iter_Kahan_Babuska(i, memo); return;
+ case T_FIXNUM:
+ case T_BIGNUM:
+ case T_RATIONAL:
+ switch (TYPE(i)) {
+ case T_FIXNUM: sum_iter_fixnum(i, memo); return;
+ case T_BIGNUM: sum_iter_bignum(i, memo); return;
+ case T_RATIONAL: sum_iter_rational(i, memo); return;
+ case T_FLOAT:
+ sum_iter_normalize_memo(memo);
+ memo->f = NUM2DBL(memo->v);
+ memo->c = 0.0;
+ memo->float_value = 1;
+ sum_iter_Kahan_Babuska(i, memo);
+ return;
+ default:
+ sum_iter_normalize_memo(memo);
+ sum_iter_some_value(i, memo);
+ return;
+ }
+ }
}
static VALUE
@@ -4078,13 +4132,7 @@ enum_sum(int argc, VALUE* argv, VALUE obj)
if (memo.n != 0)
memo.v = rb_fix_plus(LONG2FIX(memo.n), memo.v);
if (memo.r != Qundef) {
- /* r can be an Integer when mathn is loaded */
- if (FIXNUM_P(memo.r))
- memo.v = rb_fix_plus(memo.r, memo.v);
- else if (RB_TYPE_P(memo.r, T_BIGNUM))
- memo.v = rb_big_plus(memo.r, memo.v);
- else
- memo.v = rb_rational_plus(memo.r, memo.v);
+ memo.v = rb_rational_plus(memo.r, memo.v);
}
return memo.v;
}
@@ -4143,9 +4191,6 @@ enum_uniq(VALUE obj)
void
Init_Enumerable(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
rb_mEnumerable = rb_define_module("Enumerable");
rb_define_method(rb_mEnumerable, "to_a", enum_to_a, -1);
@@ -4207,5 +4252,5 @@ Init_Enumerable(void)
rb_define_method(rb_mEnumerable, "sum", enum_sum, -1);
rb_define_method(rb_mEnumerable, "uniq", enum_uniq, 0);
- id_next = rb_intern("next");
+ id_next = rb_intern_const("next");
}
diff --git a/enumerator.c b/enumerator.c
index 2dc1789974..90d2ec433c 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -12,14 +12,23 @@
************************************************/
-#include "ruby/ruby.h"
-#include "internal.h"
-#include "id.h"
+#include "ruby/internal/config.h"
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
+#include "id.h"
+#include "internal.h"
+#include "internal/enumerator.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/imemo.h"
+#include "internal/numeric.h"
+#include "internal/range.h"
+#include "internal/rational.h"
+#include "ruby/ruby.h"
+
/*
* Document-class: Enumerator
*
@@ -73,6 +82,14 @@
* puts e.next # => 3
* puts e.next # raises StopIteration
*
+ * Note that enumeration sequence by +next+, +next_values+, +peek+ and
+ * +peek_values+ do not affect other non-external
+ * enumeration methods, unless the underlying iteration method itself has
+ * side-effect, e.g. IO#each_line.
+ *
+ * Moreover, implementation typically uses fibers so performance could be
+ * slower and exception stacktraces different than expected.
+ *
* You can use this to implement an internal iterator as follows:
*
* def ext_each(e)
@@ -376,8 +393,6 @@ enumerator_allocate(VALUE klass)
return enum_obj;
}
-#define PASS_KW_SPLAT (rb_empty_keyword_given_p() ? RB_PASS_EMPTY_KEYWORDS : rb_keyword_given_p())
-
static VALUE
enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *argv, rb_enumerator_size_func *size_fn, VALUE size, int kw_splat)
{
@@ -405,15 +420,31 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar
return enum_obj;
}
+static VALUE
+convert_to_feasible_size_value(VALUE obj)
+{
+ if (NIL_P(obj)) {
+ return obj;
+ }
+ else if (rb_respond_to(obj, id_call)) {
+ return obj;
+ }
+ else if (RB_FLOAT_TYPE_P(obj) && RFLOAT_VALUE(obj) == HUGE_VAL) {
+ return obj;
+ }
+ else {
+ return rb_to_int(obj);
+ }
+}
+
/*
* call-seq:
* Enumerator.new(size = nil) { |yielder| ... }
- * Enumerator.new(obj, method = :each, *args)
*
* Creates a new Enumerator object, which can be used as an
* Enumerable.
*
- * In the first form, iteration is defined by the given block, in
+ * Iteration is defined by the given block, in
* which a "yielder" object, given as block parameter, can be used to
* yield a value by calling the +yield+ method (aliased as <code><<</code>):
*
@@ -430,52 +461,16 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar
* The optional parameter can be used to specify how to calculate the size
* in a lazy fashion (see Enumerator#size). It can either be a value or
* a callable object.
- *
- * In the deprecated second form, a generated Enumerator iterates over the
- * given object using the given method with the given arguments passed.
- *
- * Use of this form is discouraged. Use Object#enum_for or Object#to_enum
- * instead.
- *
- * e = Enumerator.new(ObjectSpace, :each_object)
- * #-> ObjectSpace.enum_for(:each_object)
- *
- * e.select { |obj| obj.is_a?(Class) } # => array of all classes
- *
*/
static VALUE
enumerator_initialize(int argc, VALUE *argv, VALUE obj)
{
- VALUE recv, meth = sym_each;
- VALUE size = Qnil;
- int kw_splat = 0;
+ VALUE iter = rb_block_proc();
+ VALUE recv = generator_init(generator_allocate(rb_cGenerator), iter);
+ VALUE arg0 = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
+ VALUE size = convert_to_feasible_size_value(arg0);
- if (rb_block_given_p()) {
- rb_check_arity(argc, 0, 1);
- recv = generator_init(generator_allocate(rb_cGenerator), rb_block_proc());
- if (argc) {
- if (NIL_P(argv[0]) || rb_respond_to(argv[0], id_call) ||
- (RB_TYPE_P(argv[0], T_FLOAT) && RFLOAT_VALUE(argv[0]) == HUGE_VAL)) {
- size = argv[0];
- }
- else {
- size = rb_to_int(argv[0]);
- }
- argc = 0;
- }
- }
- else {
- rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
- rb_warn_deprecated("Enumerator.new without a block", "Object#to_enum");
- recv = *argv++;
- if (--argc) {
- meth = *argv++;
- --argc;
- }
- kw_splat = PASS_KW_SPLAT;
- }
-
- return enumerator_init(obj, recv, meth, argc, argv, 0, size, kw_splat);
+ return enumerator_init(obj, recv, sym_each, 0, 0, 0, size, false);
}
/* :nodoc: */
@@ -527,10 +522,10 @@ rb_enumeratorize_with_size(VALUE obj, VALUE meth, int argc, const VALUE *argv, r
/* Similar effect as calling obj.to_enum, i.e. dispatching to either
Kernel#to_enum vs Lazy#to_enum */
if (RTEST(rb_obj_is_kind_of(obj, rb_cLazy)))
- return lazy_to_enum_i(obj, meth, argc, argv, size_fn, PASS_KW_SPLAT);
+ return lazy_to_enum_i(obj, meth, argc, argv, size_fn, rb_keyword_given_p());
else
return enumerator_init(enumerator_allocate(rb_cEnumerator),
- obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT);
+ obj, meth, argc, argv, size_fn, Qnil, rb_keyword_given_p());
}
VALUE
@@ -716,9 +711,9 @@ enumerator_with_object_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, memo))
* puts "#{string}: #{x}"
* end
*
- * # => foo:0
- * # => foo:1
- * # => foo:2
+ * # => foo: 0
+ * # => foo: 1
+ * # => foo: 2
*/
static VALUE
enumerator_with_object(VALUE obj, VALUE memo)
@@ -798,6 +793,8 @@ get_next_values(VALUE obj, struct enumerator *e)
* internal position forward. When the position reached at the end,
* StopIteration is raised.
*
+ * See class-level notes about external iterators.
+ *
* This method can be used to distinguish <code>yield</code> and <code>yield
* nil</code>.
*
@@ -831,10 +828,6 @@ get_next_values(VALUE obj, struct enumerator *e)
* # yield nil [nil] nil
* # yield [1, 2] [[1, 2]] [1, 2]
*
- * Note that +next_values+ does not affect other non-external enumeration
- * methods unless underlying iteration method itself has side-effect, e.g.
- * IO#each_line.
- *
*/
static VALUE
@@ -888,9 +881,7 @@ ary2sv(VALUE args, int dup)
* p e.next #=> 3
* p e.next #raises StopIteration
*
- * Note that enumeration sequence by +next+ does not affect other non-external
- * enumeration methods, unless the underlying iteration methods itself has
- * side-effect, e.g. IO#each_line.
+ * See class-level notes about external iterators.
*
*/
@@ -920,6 +911,8 @@ enumerator_peek_values(VALUE obj)
* doesn't move the internal position forward. If the position is already at
* the end, StopIteration is raised.
*
+ * See class-level notes about external iterators.
+ *
* === Example
*
* o = Object.new
@@ -954,6 +947,8 @@ enumerator_peek_values_m(VALUE obj)
* position forward. If the position is already at the end, StopIteration
* is raised.
*
+ * See class-level notes about external iterators.
+ *
* === Example
*
* a = [1,2,3]
@@ -1351,7 +1346,7 @@ yielder_yield_push(VALUE obj, VALUE arg)
}
/*
- * Returns a Proc object that takes an argument and yields it.
+ * Returns a Proc object that takes arguments and yields them.
*
* This method is implemented so that a Yielder object can be directly
* passed to another method as a block argument.
@@ -1539,17 +1534,7 @@ lazyenum_size(VALUE self, VALUE args, VALUE eobj)
return enum_size(self);
}
-static VALUE
-lazy_size(VALUE self)
-{
- return enum_size(rb_ivar_get(self, id_receiver));
-}
-
-static VALUE
-lazy_receiver_size(VALUE generator, VALUE args, VALUE lazy)
-{
- return lazy_size(lazy);
-}
+#define lazy_receiver_size lazy_map_size
static VALUE
lazy_init_iterator(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
@@ -1591,24 +1576,47 @@ lazy_init_block_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
#define LAZY_MEMO_BREAK_P(memo) ((memo)->memo_flags & LAZY_MEMO_BREAK)
#define LAZY_MEMO_PACKED_P(memo) ((memo)->memo_flags & LAZY_MEMO_PACKED)
#define LAZY_MEMO_SET_BREAK(memo) ((memo)->memo_flags |= LAZY_MEMO_BREAK)
+#define LAZY_MEMO_RESET_BREAK(memo) ((memo)->memo_flags &= ~LAZY_MEMO_BREAK)
#define LAZY_MEMO_SET_VALUE(memo, value) MEMO_V2_SET(memo, value)
#define LAZY_MEMO_SET_PACKED(memo) ((memo)->memo_flags |= LAZY_MEMO_PACKED)
#define LAZY_MEMO_RESET_PACKED(memo) ((memo)->memo_flags &= ~LAZY_MEMO_PACKED)
+static VALUE lazy_yielder_result(struct MEMO *result, VALUE yielder, VALUE procs_array, VALUE memos, long i);
+
static VALUE
lazy_init_yielder(RB_BLOCK_CALL_FUNC_ARGLIST(_, m))
{
VALUE yielder = RARRAY_AREF(m, 0);
VALUE procs_array = RARRAY_AREF(m, 1);
VALUE memos = rb_attr_get(yielder, id_memo);
- long i = 0;
struct MEMO *result;
- int cont = 1;
- result = MEMO_NEW(Qnil, rb_enum_values_pack(argc, argv),
+ result = MEMO_NEW(m, rb_enum_values_pack(argc, argv),
argc > 1 ? LAZY_MEMO_PACKED : 0);
+ return lazy_yielder_result(result, yielder, procs_array, memos, 0);
+}
- for (i = 0; i < RARRAY_LEN(procs_array); i++) {
+static VALUE
+lazy_yielder_yield(struct MEMO *result, long memo_index, int argc, const VALUE *argv)
+{
+ VALUE m = result->v1;
+ VALUE yielder = RARRAY_AREF(m, 0);
+ VALUE procs_array = RARRAY_AREF(m, 1);
+ VALUE memos = rb_attr_get(yielder, id_memo);
+ LAZY_MEMO_SET_VALUE(result, rb_enum_values_pack(argc, argv));
+ if (argc > 1)
+ LAZY_MEMO_SET_PACKED(result);
+ else
+ LAZY_MEMO_RESET_PACKED(result);
+ return lazy_yielder_result(result, yielder, procs_array, memos, memo_index);
+}
+
+static VALUE
+lazy_yielder_result(struct MEMO *result, VALUE yielder, VALUE procs_array, VALUE memos, long i)
+{
+ int cont = 1;
+
+ for (; i < RARRAY_LEN(procs_array); i++) {
VALUE proc = RARRAY_AREF(procs_array, i);
struct proc_entry *entry = proc_entry_ptr(proc);
if (!(*entry->fn->proc)(proc, result, memos, i)) {
@@ -1803,6 +1811,7 @@ lazy_set_args(VALUE lazy, VALUE args)
}
}
+#if 0
static VALUE
lazy_set_method(VALUE lazy, VALUE args, rb_enumerator_size_func *size_fn)
{
@@ -1811,6 +1820,7 @@ lazy_set_method(VALUE lazy, VALUE args, rb_enumerator_size_func *size_fn)
e->size_fn = size_fn;
return lazy;
}
+#endif
static VALUE
lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
@@ -1884,7 +1894,7 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo,
static VALUE
enumerable_lazy(VALUE obj)
{
- VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, lazyenum_size, PASS_KW_SPLAT);
+ VALUE result = lazy_to_enum_i(obj, sym_each, 0, 0, lazyenum_size, rb_keyword_given_p());
/* Qfalse indicates that the Enumerator::Lazy has no method name */
rb_ivar_set(result, id_method, Qfalse);
return result;
@@ -1932,7 +1942,7 @@ lazy_to_enum(int argc, VALUE *argv, VALUE self)
if (RTEST((super_meth = rb_hash_aref(lazy_use_super_method, meth)))) {
meth = super_meth;
}
- lazy = lazy_to_enum_i(self, meth, argc, argv, 0, PASS_KW_SPLAT);
+ lazy = lazy_to_enum_i(self, meth, argc, argv, 0, rb_keyword_given_p());
if (rb_block_given_p()) {
enumerator_ptr(lazy)->size = rb_block_proc();
}
@@ -2022,58 +2032,58 @@ lazy_map(VALUE obj)
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_map_funcs);
}
+struct flat_map_i_arg {
+ struct MEMO *result;
+ long index;
+};
+
static VALUE
-lazy_flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, yielder))
+lazy_flat_map_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, y))
{
- VALUE arg = rb_enum_values_pack(argc, argv);
+ struct flat_map_i_arg *arg = (struct flat_map_i_arg *)y;
- return rb_funcallv(yielder, idLTLT, 1, &arg);
+ return lazy_yielder_yield(arg->result, arg->index, argc, argv);
}
-static VALUE
-lazy_flat_map_each(VALUE obj, VALUE yielder)
+static struct MEMO *
+lazy_flat_map_proc(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
{
- rb_block_call(obj, id_each, 0, 0, lazy_flat_map_i, yielder);
- return Qnil;
-}
+ VALUE value = lazyenum_yield_values(proc_entry, result);
+ VALUE ary = 0;
+ const long proc_index = memo_index + 1;
+ int break_p = LAZY_MEMO_BREAK_P(result);
-static VALUE
-lazy_flat_map_to_ary(VALUE obj, VALUE yielder)
-{
- VALUE ary = rb_check_array_type(obj);
- if (NIL_P(ary)) {
- rb_funcall(yielder, idLTLT, 1, obj);
+ if (RB_TYPE_P(value, T_ARRAY)) {
+ ary = value;
}
- else {
- long i;
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- rb_funcall(yielder, idLTLT, 1, RARRAY_AREF(ary, i));
- }
+ else if (rb_respond_to(value, id_force) && rb_respond_to(value, id_each)) {
+ struct flat_map_i_arg arg = {.result = result, .index = proc_index};
+ LAZY_MEMO_RESET_BREAK(result);
+ rb_block_call(value, id_each, 0, 0, lazy_flat_map_i, (VALUE)&arg);
+ if (break_p) LAZY_MEMO_SET_BREAK(result);
+ return 0;
}
- return Qnil;
-}
-static VALUE
-lazy_flat_map_proc(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
-{
- VALUE result = rb_yield_values2(argc - 1, &argv[1]);
- if (RB_TYPE_P(result, T_ARRAY)) {
- long i;
- for (i = 0; i < RARRAY_LEN(result); i++) {
- rb_funcall(argv[0], idLTLT, 1, RARRAY_AREF(result, i));
- }
- }
- else {
- if (rb_respond_to(result, id_force) && rb_respond_to(result, id_each)) {
- lazy_flat_map_each(result, argv[0]);
- }
- else {
- lazy_flat_map_to_ary(result, argv[0]);
- }
+ if (ary || !NIL_P(ary = rb_check_array_type(value))) {
+ long i;
+ LAZY_MEMO_RESET_BREAK(result);
+ for (i = 0; i + 1 < RARRAY_LEN(ary); i++) {
+ const VALUE argv = RARRAY_AREF(ary, i);
+ lazy_yielder_yield(result, proc_index, 1, &argv);
+ }
+ if (break_p) LAZY_MEMO_SET_BREAK(result);
+ if (i >= RARRAY_LEN(ary)) return 0;
+ value = RARRAY_AREF(ary, i);
}
- return Qnil;
+ LAZY_MEMO_SET_VALUE(result, value);
+ LAZY_MEMO_RESET_PACKED(result);
+ return result;
}
+static const lazyenum_funcs lazy_flat_map_funcs = {
+ lazy_flat_map_proc, 0,
+};
+
/*
* call-seq:
* lazy.collect_concat { |obj| block } -> a_lazy_enumerator
@@ -2104,9 +2114,7 @@ lazy_flat_map(VALUE obj)
rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
}
- return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
- lazy_flat_map_proc, 0),
- Qnil, 0);
+ return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_flat_map_funcs);
}
static struct MEMO *
@@ -2308,58 +2316,59 @@ next_stopped(VALUE obj, VALUE _)
return Qnil;
}
-static VALUE
-lazy_zip_arrays_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, arrays))
+static struct MEMO *
+lazy_zip_arrays_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
{
- VALUE yielder, ary, memo;
- long i, count;
-
- yielder = argv[0];
- memo = rb_attr_get(yielder, id_memo);
- count = NIL_P(memo) ? 0 : NUM2LONG(memo);
+ struct proc_entry *entry = proc_entry_ptr(proc_entry);
+ VALUE ary, arrays = entry->memo;
+ VALUE memo = rb_ary_entry(memos, memo_index);
+ long i, count = NIL_P(memo) ? 0 : NUM2LONG(memo);
ary = rb_ary_new2(RARRAY_LEN(arrays) + 1);
- rb_ary_push(ary, argv[1]);
+ rb_ary_push(ary, result->memo_value);
for (i = 0; i < RARRAY_LEN(arrays); i++) {
rb_ary_push(ary, rb_ary_entry(RARRAY_AREF(arrays, i), count));
}
- rb_funcall(yielder, idLTLT, 1, ary);
- rb_ivar_set(yielder, id_memo, LONG2NUM(++count));
- return Qnil;
+ LAZY_MEMO_SET_VALUE(result, ary);
+ LAZY_MEMO_SET_PACKED(result);
+ rb_ary_store(memos, memo_index, LONG2NUM(++count));
+ return result;
}
-static VALUE
-lazy_zip_func(RB_BLOCK_CALL_FUNC_ARGLIST(val, zip_args))
+static struct MEMO *
+lazy_zip_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_index)
{
- VALUE yielder, ary, arg, v;
+ struct proc_entry *entry = proc_entry_ptr(proc_entry);
+ VALUE arg = rb_ary_entry(memos, memo_index);
+ VALUE zip_args = entry->memo;
+ VALUE ary, v;
long i;
- yielder = argv[0];
- arg = rb_attr_get(yielder, id_memo);
if (NIL_P(arg)) {
arg = rb_ary_new2(RARRAY_LEN(zip_args));
for (i = 0; i < RARRAY_LEN(zip_args); i++) {
rb_ary_push(arg, rb_funcall(RARRAY_AREF(zip_args, i), id_to_enum, 0));
}
- rb_ivar_set(yielder, id_memo, arg);
+ rb_ary_store(memos, memo_index, arg);
}
ary = rb_ary_new2(RARRAY_LEN(arg) + 1);
- v = Qnil;
- if (--argc > 0) {
- ++argv;
- v = argc > 1 ? rb_ary_new_from_values(argc, argv) : *argv;
- }
- rb_ary_push(ary, v);
+ rb_ary_push(ary, result->memo_value);
for (i = 0; i < RARRAY_LEN(arg); i++) {
v = rb_rescue2(call_next, RARRAY_AREF(arg, i), next_stopped, 0,
rb_eStopIteration, (VALUE)0);
rb_ary_push(ary, v);
}
- rb_funcall(yielder, idLTLT, 1, ary);
- return Qnil;
+ LAZY_MEMO_SET_VALUE(result, ary);
+ LAZY_MEMO_SET_PACKED(result);
+ return result;
}
+static const lazyenum_funcs lazy_zip_funcs[] = {
+ {lazy_zip_func, lazy_receiver_size,},
+ {lazy_zip_arrays_func, lazy_receiver_size,},
+};
+
/*
* call-seq:
* lazy.zip(arg, ...) -> lazy_enumerator
@@ -2373,7 +2382,7 @@ lazy_zip(int argc, VALUE *argv, VALUE obj)
{
VALUE ary, v;
long i;
- rb_block_call_func *func = lazy_zip_arrays_func;
+ const lazyenum_funcs *funcs = &lazy_zip_funcs[1];
if (rb_block_given_p()) {
return rb_call_super(argc, argv);
@@ -2390,15 +2399,13 @@ lazy_zip(int argc, VALUE *argv, VALUE obj)
}
}
ary = rb_ary_new4(argc, argv);
- func = lazy_zip_func;
+ funcs = &lazy_zip_funcs[0];
break;
}
rb_ary_push(ary, v);
}
- return lazy_set_method(rb_block_call(rb_cLazy, id_new, 1, &obj,
- func, ary),
- ary, lazy_receiver_size);
+ return lazy_add_method(obj, 0, 0, ary, ary, funcs);
}
static struct MEMO *
@@ -2662,7 +2669,8 @@ lazy_with_index_proc(VALUE proc_entry, struct MEMO* result, VALUE memos, long me
if (entry->proc) {
rb_proc_call_with_block(entry->proc, 2, argv, Qnil);
LAZY_MEMO_RESET_PACKED(result);
- } else {
+ }
+ else {
LAZY_MEMO_SET_VALUE(result, rb_ary_new_from_values(2, argv));
LAZY_MEMO_SET_PACKED(result);
}
@@ -2670,8 +2678,13 @@ lazy_with_index_proc(VALUE proc_entry, struct MEMO* result, VALUE memos, long me
return result;
}
+static VALUE
+lazy_with_index_size(VALUE proc, VALUE receiver) {
+ return receiver;
+}
+
static const lazyenum_funcs lazy_with_index_funcs = {
- lazy_with_index_proc, 0,
+ lazy_with_index_proc, lazy_with_index_size,
};
/*
@@ -2917,6 +2930,8 @@ producer_each_stop(VALUE dummy, VALUE exc)
return rb_attr_get(exc, id_result);
}
+NORETURN(static VALUE producer_each_i(VALUE obj));
+
static VALUE
producer_each_i(VALUE obj)
{
@@ -2929,7 +2944,8 @@ producer_each_i(VALUE obj)
if (init == Qundef) {
curr = Qnil;
- } else {
+ }
+ else {
rb_yield(init);
curr = init;
}
@@ -2939,7 +2955,7 @@ producer_each_i(VALUE obj)
rb_yield(curr);
}
- return Qnil;
+ UNREACHABLE_RETURN(Qnil);
}
/* :nodoc: */
@@ -2978,7 +2994,7 @@ producer_size(VALUE obj, VALUE args, VALUE eobj)
* enclosing_section = ancestors.find { |n| n.type == :section }
*
* Using ::produce together with Enumerable methods like Enumerable#detect,
- * Enumerable#slice, Enumerable#take_while can provide Enumerator-based alternatives
+ * Enumerable#slice_after, Enumerable#take_while can provide Enumerator-based alternatives
* for +while+ and +until+ cycles:
*
* # Find next Tuesday
@@ -3302,6 +3318,9 @@ enumerator_plus(VALUE obj, VALUE eobj)
* that is a representation of sequences of numbers with common difference.
* Instances of this class can be generated by the Range#step and Numeric#step
* methods.
+ *
+ * The class can be used for slicing Array (see Array#slice) or custom
+ * collections.
*/
VALUE
@@ -3310,7 +3329,7 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
VALUE beg, VALUE end, VALUE step, int excl)
{
VALUE aseq = enumerator_init(enumerator_allocate(rb_cArithSeq),
- obj, meth, argc, argv, size_fn, Qnil, PASS_KW_SPLAT);
+ obj, meth, argc, argv, size_fn, Qnil, rb_keyword_given_p());
rb_ivar_set(aseq, id_begin, beg);
rb_ivar_set(aseq, id_end, end);
rb_ivar_set(aseq, id_step, step);
@@ -3380,17 +3399,53 @@ rb_arithmetic_sequence_extract(VALUE obj, rb_arithmetic_sequence_components_t *c
component->exclude_end = arith_seq_exclude_end_p(obj);
return 1;
}
- else if (rb_obj_is_kind_of(obj, rb_cRange)) {
- component->begin = RANGE_BEG(obj);
- component->end = RANGE_END(obj);
+ else if (rb_range_values(obj, &component->begin, &component->end, &component->exclude_end)) {
component->step = INT2FIX(1);
- component->exclude_end = RTEST(RANGE_EXCL(obj));
return 1;
}
return 0;
}
+VALUE
+rb_arithmetic_sequence_beg_len_step(VALUE obj, long *begp, long *lenp, long *stepp, long len, int err)
+{
+ RUBY_ASSERT(begp != NULL);
+ RUBY_ASSERT(lenp != NULL);
+ RUBY_ASSERT(stepp != NULL);
+
+ rb_arithmetic_sequence_components_t aseq;
+ if (!rb_arithmetic_sequence_extract(obj, &aseq)) {
+ return Qfalse;
+ }
+
+ long step = NIL_P(aseq.step) ? 1 : NUM2LONG(aseq.step);
+ *stepp = step;
+
+ if (step < 0) {
+ VALUE tmp = aseq.begin;
+ aseq.begin = aseq.end;
+ aseq.end = tmp;
+ }
+
+ if (err == 0 && (step < -1 || step > 1)) {
+ if (rb_range_component_beg_len(aseq.begin, aseq.end, aseq.exclude_end, begp, lenp, len, 1) == Qtrue) {
+ if (*begp > len)
+ goto out_of_range;
+ if (*lenp > len)
+ goto out_of_range;
+ return Qtrue;
+ }
+ }
+ else {
+ return rb_range_component_beg_len(aseq.begin, aseq.end, aseq.exclude_end, begp, lenp, len, err);
+ }
+
+ out_of_range:
+ rb_raise(rb_eRangeError, "%+"PRIsVALUE" out of range", obj);
+ return Qnil;
+}
+
/*
* call-seq:
* aseq.first -> num or nil
@@ -3882,35 +3937,6 @@ arith_seq_each(VALUE self)
return self;
}
-static double
-arith_seq_float_step_size(double beg, double end, double step, int excl)
-{
- double const epsilon = DBL_EPSILON;
- double n, err;
-
- if (step == 0) {
- return HUGE_VAL;
- }
- n = (end - beg) / step;
- err = (fabs(beg) + fabs(end) + fabs(end - beg)) / fabs(step) * epsilon;
- if (isinf(step)) {
- return step > 0 ? beg <= end : beg >= end;
- }
- if (err > 0.5) err = 0.5;
- if (excl) {
- if (n <= 0) return 0;
- if (n < 1)
- n = 0;
- else
- n = floor(n - err);
- }
- else {
- if (n < 0) return 0;
- n = floor(n + err);
- }
- return n + 1;
-}
-
/*
* call-seq:
* aseq.size -> num or nil
@@ -3944,9 +3970,9 @@ arith_seq_size(VALUE self)
ee = NUM2DBL(e);
}
- n = arith_seq_float_step_size(NUM2DBL(b), ee, NUM2DBL(s), x);
+ n = ruby_float_step_size(NUM2DBL(b), ee, NUM2DBL(s), x);
if (isinf(n)) return DBL2NUM(n);
- if (POSFIXABLE(n)) return LONG2FIX(n);
+ if (POSFIXABLE(n)) return LONG2FIX((long)n);
return rb_dbl2big(n);
}
@@ -3978,10 +4004,11 @@ arith_seq_size(VALUE self)
return len;
}
+#define sym(name) ID2SYM(rb_intern_const(name))
void
InitVM_Enumerator(void)
{
- ID id_private = rb_intern("private");
+ ID id_private = rb_intern_const("private");
rb_define_method(rb_mKernel, "to_enum", obj_to_enum, -1);
rb_define_method(rb_mKernel, "enum_for", obj_to_enum, -1);
@@ -4031,23 +4058,23 @@ InitVM_Enumerator(void)
rb_define_alias(rb_cLazy, "_enumerable_uniq", "uniq");
rb_define_private_method(rb_cLazy, "_enumerable_with_index", enumerator_with_index, -1);
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_map")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_collect")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_flat_map")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_collect_concat")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_select")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_find_all")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_filter")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_filter_map")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_reject")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_grep")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_grep_v")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_zip")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_take")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_take_while")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_drop")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_drop_while")));
- rb_funcall(rb_cLazy, id_private, 1, ID2SYM(rb_intern("_enumerable_uniq")));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_map"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_collect"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_flat_map"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_collect_concat"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_select"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_find_all"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_filter"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_filter_map"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_reject"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_grep"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_grep_v"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_zip"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_take"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_take_while"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_drop"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_drop_while"));
+ rb_funcall(rb_cLazy, id_private, 1, sym("_enumerable_uniq"));
rb_define_method(rb_cLazy, "initialize", lazy_initialize, -1);
rb_define_method(rb_cLazy, "to_enum", lazy_to_enum, -1);
@@ -4079,24 +4106,24 @@ InitVM_Enumerator(void)
rb_define_method(rb_cLazy, "with_index", lazy_with_index, -1);
lazy_use_super_method = rb_hash_new_with_size(18);
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("map")), ID2SYM(rb_intern("_enumerable_map")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("collect")), ID2SYM(rb_intern("_enumerable_collect")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("flat_map")), ID2SYM(rb_intern("_enumerable_flat_map")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("collect_concat")), ID2SYM(rb_intern("_enumerable_collect_concat")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("select")), ID2SYM(rb_intern("_enumerable_select")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("find_all")), ID2SYM(rb_intern("_enumerable_find_all")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("filter")), ID2SYM(rb_intern("_enumerable_filter")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("filter_map")), ID2SYM(rb_intern("_enumerable_filter_map")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("reject")), ID2SYM(rb_intern("_enumerable_reject")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("grep")), ID2SYM(rb_intern("_enumerable_grep")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("grep_v")), ID2SYM(rb_intern("_enumerable_grep_v")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("zip")), ID2SYM(rb_intern("_enumerable_zip")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("take")), ID2SYM(rb_intern("_enumerable_take")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("take_while")), ID2SYM(rb_intern("_enumerable_take_while")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("drop")), ID2SYM(rb_intern("_enumerable_drop")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("drop_while")), ID2SYM(rb_intern("_enumerable_drop_while")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("uniq")), ID2SYM(rb_intern("_enumerable_uniq")));
- rb_hash_aset(lazy_use_super_method, ID2SYM(rb_intern("with_index")), ID2SYM(rb_intern("_enumerable_with_index")));
+ rb_hash_aset(lazy_use_super_method, sym("map"), sym("_enumerable_map"));
+ rb_hash_aset(lazy_use_super_method, sym("collect"), sym("_enumerable_collect"));
+ rb_hash_aset(lazy_use_super_method, sym("flat_map"), sym("_enumerable_flat_map"));
+ rb_hash_aset(lazy_use_super_method, sym("collect_concat"), sym("_enumerable_collect_concat"));
+ rb_hash_aset(lazy_use_super_method, sym("select"), sym("_enumerable_select"));
+ rb_hash_aset(lazy_use_super_method, sym("find_all"), sym("_enumerable_find_all"));
+ rb_hash_aset(lazy_use_super_method, sym("filter"), sym("_enumerable_filter"));
+ rb_hash_aset(lazy_use_super_method, sym("filter_map"), sym("_enumerable_filter_map"));
+ rb_hash_aset(lazy_use_super_method, sym("reject"), sym("_enumerable_reject"));
+ rb_hash_aset(lazy_use_super_method, sym("grep"), sym("_enumerable_grep"));
+ rb_hash_aset(lazy_use_super_method, sym("grep_v"), sym("_enumerable_grep_v"));
+ rb_hash_aset(lazy_use_super_method, sym("zip"), sym("_enumerable_zip"));
+ rb_hash_aset(lazy_use_super_method, sym("take"), sym("_enumerable_take"));
+ rb_hash_aset(lazy_use_super_method, sym("take_while"), sym("_enumerable_take_while"));
+ rb_hash_aset(lazy_use_super_method, sym("drop"), sym("_enumerable_drop"));
+ rb_hash_aset(lazy_use_super_method, sym("drop_while"), sym("_enumerable_drop_while"));
+ rb_hash_aset(lazy_use_super_method, sym("uniq"), sym("_enumerable_uniq"));
+ rb_hash_aset(lazy_use_super_method, sym("with_index"), sym("_enumerable_with_index"));
rb_obj_freeze(lazy_use_super_method);
rb_gc_register_mark_object(lazy_use_super_method);
@@ -4165,28 +4192,28 @@ InitVM_Enumerator(void)
rb_provide("enumerator.so"); /* for backward compatibility */
}
+#undef sym
-#undef rb_intern
void
Init_Enumerator(void)
{
- id_rewind = rb_intern("rewind");
- id_new = rb_intern("new");
- id_next = rb_intern("next");
- id_result = rb_intern("result");
- id_receiver = rb_intern("receiver");
- id_arguments = rb_intern("arguments");
- id_memo = rb_intern("memo");
- id_method = rb_intern("method");
- id_force = rb_intern("force");
- id_to_enum = rb_intern("to_enum");
- id_begin = rb_intern("begin");
- id_end = rb_intern("end");
- id_step = rb_intern("step");
- id_exclude_end = rb_intern("exclude_end");
+ id_rewind = rb_intern_const("rewind");
+ id_new = rb_intern_const("new");
+ id_next = rb_intern_const("next");
+ id_result = rb_intern_const("result");
+ id_receiver = rb_intern_const("receiver");
+ id_arguments = rb_intern_const("arguments");
+ id_memo = rb_intern_const("memo");
+ id_method = rb_intern_const("method");
+ id_force = rb_intern_const("force");
+ id_to_enum = rb_intern_const("to_enum");
+ id_begin = rb_intern_const("begin");
+ id_end = rb_intern_const("end");
+ id_step = rb_intern_const("step");
+ id_exclude_end = rb_intern_const("exclude_end");
sym_each = ID2SYM(id_each);
- sym_cycle = ID2SYM(rb_intern("cycle"));
- sym_yield = ID2SYM(rb_intern("yield"));
+ sym_cycle = ID2SYM(rb_intern_const("cycle"));
+ sym_yield = ID2SYM(rb_intern_const("yield"));
InitVM(Enumerator);
}
diff --git a/error.c b/error.c
index c29e90244a..d614a9c0a2 100644
--- a/error.c
+++ b/error.c
@@ -9,27 +9,40 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/st.h"
-#include "internal.h"
-#include "ruby_assert.h"
-#include "vm_core.h"
-#include "builtin.h"
+#include "ruby/internal/config.h"
-#include <stdio.h>
+#include <errno.h>
#include <stdarg.h>
+#include <stdio.h>
+
#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
+# include <stdlib.h>
#endif
-#include <errno.h>
+
#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+# include <unistd.h>
#endif
#if defined __APPLE__
# include <AvailabilityMacros.h>
#endif
+#include "internal.h"
+#include "internal/error.h"
+#include "internal/eval.h"
+#include "internal/io.h"
+#include "internal/load.h"
+#include "internal/object.h"
+#include "internal/symbol.h"
+#include "internal/thread.h"
+#include "internal/variable.h"
+#include "ruby/encoding.h"
+#include "ruby/st.h"
+#include "ruby_assert.h"
+#include "vm_core.h"
+
+#include "builtin.h"
+
/*!
* \defgroup exception Exception handlings
* \{
@@ -50,7 +63,9 @@
VALUE rb_iseqw_local_variables(VALUE iseqval);
VALUE rb_iseqw_new(const rb_iseq_t *);
int rb_str_end_with_asciichar(VALUE str, int c);
+VALUE rb_ident_hash_new(void);
+long rb_backtrace_length_limit = -1;
VALUE rb_eEAGAIN;
VALUE rb_eEWOULDBLOCK;
VALUE rb_eEINPROGRESS;
@@ -58,6 +73,12 @@ static VALUE rb_mWarning;
static VALUE rb_cWarningBuffer;
static ID id_warn;
+static ID id_category;
+static ID id_deprecated;
+static ID id_experimental;
+static VALUE sym_category;
+static VALUE warning_categories;
+static VALUE warning_category_t_map;
extern const char ruby_description[];
@@ -141,18 +162,13 @@ rb_warning_category_mask(VALUE category)
rb_warning_category_t
rb_warning_category_from_name(VALUE category)
{
- rb_warning_category_t cat = RB_WARN_CATEGORY_NONE;
+ VALUE cat_value;
Check_Type(category, T_SYMBOL);
- if (category == ID2SYM(rb_intern("deprecated"))) {
- cat = RB_WARN_CATEGORY_DEPRECATED;
- }
- else if (category == ID2SYM(rb_intern("experimental"))) {
- cat = RB_WARN_CATEGORY_EXPERIMENTAL;
- }
- else {
+ cat_value = rb_hash_aref(warning_categories, category);
+ if (cat_value == Qnil) {
rb_raise(rb_eArgError, "unknown category: %"PRIsVALUE, category);
}
- return cat;
+ return NUM2INT(cat_value);
}
void
@@ -169,7 +185,7 @@ rb_warning_category_enabled_p(rb_warning_category_t category)
}
/*
- * call-seq
+ * call-seq:
* Warning[category] -> true or false
*
* Returns the flag to show the warning messages for +category+.
@@ -195,7 +211,7 @@ rb_warning_s_aref(VALUE mod, VALUE category)
}
/*
- * call-seq
+ * call-seq:
* Warning[category] = flag -> flag
*
* Sets the warning flags for +category+.
@@ -217,17 +233,31 @@ rb_warning_s_aset(VALUE mod, VALUE category, VALUE flag)
/*
* call-seq:
- * warn(msg) -> nil
+ * warn(msg, category: nil) -> nil
*
* Writes warning message +msg+ to $stderr. This method is called by
- * Ruby for all emitted warnings.
+ * Ruby for all emitted warnings. A +category+ may be included with
+ * the warning.
+ *
+ * See the documentation of the Warning module for how to customize this.
*/
static VALUE
-rb_warning_s_warn(VALUE mod, VALUE str)
+rb_warning_s_warn(int argc, VALUE *argv, VALUE mod)
{
+ VALUE str;
+ VALUE opt;
+ VALUE category = Qnil;
+
+ rb_scan_args(argc, argv, "1:", &str, &opt);
+ if (!NIL_P(opt)) rb_get_kwargs(opt, &id_category, 0, 1, &category);
+
Check_Type(str, T_STRING);
rb_must_asciicompat(str);
+ if (!NIL_P(category)) {
+ rb_warning_category_t cat = rb_warning_category_from_name(category);
+ if (!rb_warning_category_enabled_p(cat)) return Qnil;
+ }
rb_write_error_str(str);
return Qnil;
}
@@ -240,11 +270,30 @@ rb_warning_s_warn(VALUE mod, VALUE str)
* Warning.warn is called for all warnings issued by Ruby.
* By default, warnings are printed to $stderr.
*
- * By overriding Warning.warn, you can change how warnings are
- * handled by Ruby, either filtering some warnings, and/or outputting
- * warnings somewhere other than $stderr. When Warning.warn is
- * overridden, super can be called to get the default behavior of
- * printing the warning to $stderr.
+ * Changing the behavior of Warning.warn is useful to customize how warnings are
+ * handled by Ruby, for instance by filtering some warnings, and/or outputting
+ * warnings somewhere other than $stderr.
+ *
+ * If you want to change the behavior of Warning.warn you should use
+ * +Warning.extend(MyNewModuleWithWarnMethod)+ and you can use `super`
+ * to get the default behavior of printing the warning to $stderr.
+ *
+ * Example:
+ * module MyWarningFilter
+ * def warn(message, category: nil, **kwargs)
+ * if /some warning I want to ignore/.matches?(message)
+ * # ignore
+ * else
+ * super
+ * end
+ * end
+ * end
+ * Warning.extend MyWarningFilter
+ *
+ * You should never redefine Warning#warn (the instance method), as that will
+ * then no longer provide a way to use the default behavior.
+ *
+ * The +warning+ gem provides convenient ways to customize Warning.warn.
*/
static VALUE
@@ -253,6 +302,36 @@ rb_warning_warn(VALUE mod, VALUE str)
return rb_funcallv(mod, id_warn, 1, &str);
}
+
+static int
+rb_warning_warn_arity(void)
+{
+ const rb_method_entry_t *me = rb_method_entry(rb_singleton_class(rb_mWarning), id_warn);
+ return me ? rb_method_entry_arity(me) : 1;
+}
+
+static VALUE
+rb_warn_category(VALUE str, VALUE category)
+{
+ if (category != Qnil) {
+ category = rb_to_symbol_type(category);
+ if (!RTEST(rb_hash_aref(warning_categories, category))) {
+ rb_raise(rb_eArgError, "invalid warning category used: %s", rb_id2name(SYM2ID(category)));
+ }
+ }
+
+ if (rb_warning_warn_arity() == 1) {
+ return rb_warning_warn(rb_mWarning, str);
+ }
+ else {
+ VALUE args[2];
+ args[0] = str;
+ args[1] = rb_hash_new();
+ rb_hash_aset(args[1], sym_category, category);
+ return rb_funcallv_kw(rb_mWarning, id_warn, 2, args, RB_PASS_KEYWORDS);
+ }
+}
+
static void
rb_write_warning_str(VALUE str)
{
@@ -297,6 +376,20 @@ rb_compile_warning(const char *file, int line, const char *fmt, ...)
rb_write_warning_str(str);
}
+void
+rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt, ...)
+{
+ VALUE str;
+ va_list args;
+
+ if (NIL_P(ruby_verbose)) return;
+
+ va_start(args, fmt);
+ str = warn_vsprintf(NULL, file, line, fmt, args);
+ va_end(args);
+ rb_warn_category(str, rb_hash_fetch(warning_category_t_map, INT2NUM(category)));
+}
+
static VALUE
warning_string(rb_encoding *enc, const char *fmt, va_list args)
{
@@ -322,6 +415,16 @@ rb_warn(const char *fmt, ...)
}
void
+rb_category_warn(rb_warning_category_t category, const char *fmt, ...)
+{
+ if (!NIL_P(ruby_verbose)) {
+ with_warning_string(mesg, 0, fmt) {
+ rb_warn_category(mesg, rb_hash_fetch(warning_category_t_map, INT2NUM(category)));
+ }
+ }
+}
+
+void
rb_enc_warn(rb_encoding *enc, const char *fmt, ...)
{
if (!NIL_P(ruby_verbose)) {
@@ -342,6 +445,17 @@ rb_warning(const char *fmt, ...)
}
}
+/* rb_category_warning() reports only in verbose mode */
+void
+rb_category_warning(rb_warning_category_t category, const char *fmt, ...)
+{
+ if (RTEST(ruby_verbose)) {
+ with_warning_string(mesg, 0, fmt) {
+ rb_warn_category(mesg, rb_hash_fetch(warning_category_t_map, INT2NUM(category)));
+ }
+ }
+}
+
VALUE
rb_warning_string(const char *fmt, ...)
{
@@ -375,7 +489,21 @@ rb_warn_deprecated(const char *fmt, const char *suggest, ...)
rb_str_cat_cstr(mesg, " is deprecated");
if (suggest) rb_str_catf(mesg, "; use %s instead", suggest);
rb_str_cat_cstr(mesg, "\n");
- rb_write_warning_str(mesg);
+ rb_warn_category(mesg, ID2SYM(id_deprecated));
+}
+
+void
+rb_warn_deprecated_to_remove(const char *fmt, const char *removal, ...)
+{
+ if (NIL_P(ruby_verbose)) return;
+ if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return;
+ va_list args;
+ va_start(args, removal);
+ VALUE mesg = warning_string(0, fmt, args);
+ va_end(args);
+ rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1);
+ rb_str_catf(mesg, " is deprecated and will be removed in Ruby %s\n", removal);
+ rb_warn_category(mesg, ID2SYM(id_deprecated));
}
static inline int
@@ -395,9 +523,10 @@ warning_write(int argc, VALUE *argv, VALUE buf)
return buf;
}
-VALUE rb_ec_backtrace_location_ary(rb_execution_context_t *ec, long lev, long n);
+VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal);
+
static VALUE
-rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel)
+rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel, VALUE category)
{
VALUE location = Qnil;
int argc = RARRAY_LENINT(msgs);
@@ -410,7 +539,7 @@ rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel)
if (lev < 0) {
rb_raise(rb_eArgError, "negative level (%ld)", lev);
}
- location = rb_ec_backtrace_location_ary(ec, lev + 1, 1);
+ location = rb_ec_backtrace_location_ary(ec, lev + 1, 1, TRUE);
if (!NIL_P(location)) {
location = rb_ary_entry(location, 0);
}
@@ -433,12 +562,13 @@ rb_warn_m(rb_execution_context_t *ec, VALUE exc, VALUE msgs, VALUE uplevel)
rb_io_puts(argc, argv, str);
RBASIC_SET_CLASS(str, rb_cString);
}
+
if (exc == rb_mWarning) {
rb_must_asciicompat(str);
rb_write_error_str(str);
}
else {
- rb_write_warning_str(str);
+ rb_warn_category(str, category);
}
}
return Qnil;
@@ -569,17 +699,6 @@ bug_report_begin_valist(FILE *out, const char *fmt, va_list args)
snprintf(buf, sizeof(buf), "\n%s\n\n", ruby_description);
fputs(buf, out);
preface_dump(out);
-
-#if RUBY_DEVEL
- const char *cmd = getenv("RUBY_ON_BUG");
- if (cmd) {
- snprintf(buf, sizeof(buf), "%s %"PRI_PIDT_PREFIX"d", cmd, getpid());
- int r = system(buf);
- if (r == -1) {
- snprintf(buf, sizeof(buf), "Launching RUBY_ON_BUG command failed.");
- }
- }
-#endif
}
#define bug_report_begin(out, fmt) do { \
@@ -633,17 +752,25 @@ die(void)
}
void
-rb_bug(const char *fmt, ...)
+rb_bug_without_die(const char *fmt, va_list args)
{
const char *file = NULL;
int line = 0;
if (GET_EC()) {
- file = rb_source_location_cstr(&line);
+ file = rb_source_location_cstr(&line);
}
- report_bug(file, line, fmt, NULL);
+ report_bug_valist(file, line, fmt, NULL, args);
+}
+void
+rb_bug(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ rb_bug_without_die(fmt, args);
+ va_end(args);
die();
}
@@ -738,7 +865,7 @@ static const char builtin_types[][10] = {
"Array",
"Hash",
"Struct",
- "Bignum",
+ "Integer",
"File",
"Data", /* internal use: wrapped C pointers */
"MatchData", /* data of $~ */
@@ -749,7 +876,7 @@ static const char builtin_types[][10] = {
"true",
"false",
"Symbol", /* :symbol */
- "Fixnum",
+ "Integer",
"undef", /* internal use: #undef; should not happen */
"", /* 0x17 */
"", /* 0x18 */
@@ -769,6 +896,17 @@ rb_builtin_type_name(int t)
return 0;
}
+static VALUE
+displaying_class_of(VALUE x)
+{
+ switch (x) {
+ case Qfalse: return rb_fstring_cstr("false");
+ case Qnil: return rb_fstring_cstr("nil");
+ case Qtrue: return rb_fstring_cstr("true");
+ default: return rb_obj_class(x);
+ }
+}
+
static const char *
builtin_class_name(VALUE x)
{
@@ -816,13 +954,8 @@ unexpected_type(VALUE x, int xt, int t)
VALUE mesg, exc = rb_eFatal;
if (tname) {
- const char *cname = builtin_class_name(x);
- if (cname)
- mesg = rb_sprintf("wrong argument type %s (expected %s)",
- cname, tname);
- else
- mesg = rb_sprintf("wrong argument type %"PRIsVALUE" (expected %s)",
- rb_obj_class(x), tname);
+ mesg = rb_sprintf("wrong argument type %"PRIsVALUE" (expected %s)",
+ displaying_class_of(x), tname);
exc = rb_eTypeError;
}
else if (xt > T_MASK && xt <= 0x3f) {
@@ -890,26 +1023,26 @@ rb_typeddata_is_instance_of(VALUE obj, const rb_data_type_t *data_type)
void *
rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
{
- const char *etype;
+ VALUE actual;
if (!RB_TYPE_P(obj, T_DATA)) {
- wrong_type:
- etype = builtin_class_name(obj);
- if (!etype)
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)",
- rb_obj_class(obj), data_type->wrap_struct_name);
- wrong_datatype:
- rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
- etype, data_type->wrap_struct_name);
- }
- if (!RTYPEDDATA_P(obj)) {
- goto wrong_type;
+ actual = displaying_class_of(obj);
+ }
+ else if (!RTYPEDDATA_P(obj)) {
+ actual = displaying_class_of(obj);
}
else if (!rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
- etype = RTYPEDDATA_TYPE(obj)->wrap_struct_name;
- goto wrong_datatype;
+ const char *name = RTYPEDDATA_TYPE(obj)->wrap_struct_name;
+ actual = rb_str_new_cstr(name); /* or rb_fstring_cstr? not sure... */
+ }
+ else {
+ return DATA_PTR(obj);
}
- return DATA_PTR(obj);
+
+ const char *expected = data_type->wrap_struct_name;
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)",
+ actual, expected);
+ UNREACHABLE_RETURN(NULL);
}
/* exception classes */
@@ -988,7 +1121,8 @@ exc_init(VALUE exc, VALUE mesg)
/*
* call-seq:
- * Exception.new(msg = nil) -> exception
+ * Exception.new(msg = nil) -> exception
+ * Exception.exception(msg = nil) -> exception
*
* Construct a new Exception object, optionally passing in
* a message.
@@ -1007,7 +1141,7 @@ exc_initialize(int argc, VALUE *argv, VALUE exc)
* Document-method: exception
*
* call-seq:
- * exc.exception(string) -> an_exception or exc
+ * exc.exception([string]) -> an_exception or exc
*
* With no argument, or if the argument is the same as the receiver,
* return the receiver. Otherwise, create a new
@@ -1714,9 +1848,9 @@ static const rb_data_type_t name_err_mesg_data_type = {
/* :nodoc: */
static VALUE
-rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method)
+rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE method)
{
- VALUE result = TypedData_Wrap_Struct(rb_cNameErrorMesg, &name_err_mesg_data_type, 0);
+ VALUE result = TypedData_Wrap_Struct(klass, &name_err_mesg_data_type, 0);
VALUE *ptr = ALLOC_N(VALUE, NAME_ERR_MESG_COUNT);
ptr[NAME_ERR_MESG__MESG] = mesg;
@@ -1728,6 +1862,35 @@ rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method)
/* :nodoc: */
static VALUE
+rb_name_err_mesg_new(VALUE mesg, VALUE recv, VALUE method)
+{
+ return rb_name_err_mesg_init(rb_cNameErrorMesg, mesg, recv, method);
+}
+
+/* :nodoc: */
+static VALUE
+name_err_mesg_alloc(VALUE klass)
+{
+ return rb_name_err_mesg_init(klass, Qnil, Qnil, Qnil);
+}
+
+/* :nodoc: */
+static VALUE
+name_err_mesg_init_copy(VALUE obj1, VALUE obj2)
+{
+ VALUE *ptr1, *ptr2;
+
+ if (obj1 == obj2) return obj1;
+ rb_obj_init_copy(obj1, obj2);
+
+ TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1);
+ TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2);
+ MEMCPY(ptr1, ptr2, VALUE, NAME_ERR_MESG_COUNT);
+ return obj1;
+}
+
+/* :nodoc: */
+static VALUE
name_err_mesg_equal(VALUE obj1, VALUE obj2)
{
VALUE *ptr1, *ptr2;
@@ -1748,6 +1911,17 @@ name_err_mesg_equal(VALUE obj1, VALUE obj2)
/* :nodoc: */
static VALUE
+name_err_mesg_receiver_name(VALUE obj)
+{
+ if (RB_SPECIAL_CONST_P(obj)) return Qundef;
+ if (RB_BUILTIN_TYPE(obj) == T_MODULE || RB_BUILTIN_TYPE(obj) == T_CLASS) {
+ return rb_check_funcall(obj, rb_intern("name"), 0, 0);
+ }
+ return Qundef;
+}
+
+/* :nodoc: */
+static VALUE
name_err_mesg_to_str(VALUE obj)
{
VALUE *ptr, mesg;
@@ -1774,10 +1948,14 @@ name_err_mesg_to_str(VALUE obj)
d = FAKE_CSTR(&d_str, "false");
break;
default:
- d = rb_protect(rb_inspect, obj, &state);
- if (state)
+ d = rb_protect(name_err_mesg_receiver_name, obj, &state);
+ if (state || d == Qundef || d == Qnil)
+ d = rb_protect(rb_inspect, obj, &state);
+ if (state) {
rb_set_errinfo(Qnil);
- if (NIL_P(d) || RSTRING_LEN(d) > 65) {
+ }
+ d = rb_check_string_type(d);
+ if (NIL_P(d)) {
d = rb_any_to_s(obj);
}
singleton = (RSTRING_LEN(d) > 0 && RSTRING_PTR(d)[0] == '#');
@@ -2446,6 +2624,8 @@ syserr_eqq(VALUE self, VALUE exc)
*/
/*
+ * Document-class: Exception
+ *
* \Class Exception and its subclasses are used to communicate between
* Kernel#raise and +rescue+ statements in <code>begin ... end</code> blocks.
*
@@ -2540,10 +2720,56 @@ syserr_eqq(VALUE self, VALUE exc)
* * fatal
*/
+static VALUE
+exception_alloc(VALUE klass)
+{
+ return rb_class_allocate_instance(klass);
+}
+
+static VALUE
+exception_dumper(VALUE exc)
+{
+ // TODO: Currently, the instance variables "bt" and "bt_locations"
+ // refers to the same object (Array of String). But "bt_locations"
+ // should have an Array of Thread::Backtrace::Locations.
+
+ return exc;
+}
+
+static int
+ivar_copy_i(st_data_t key, st_data_t val, st_data_t exc)
+{
+ rb_ivar_set((VALUE) exc, (ID) key, (VALUE) val);
+ return ST_CONTINUE;
+}
+
+static VALUE
+exception_loader(VALUE exc, VALUE obj)
+{
+ // The loader function of rb_marshal_define_compat seems to be called for two events:
+ // one is for fixup (r_fixup_compat), the other is for TYPE_USERDEF.
+ // In the former case, the first argument is an instance of Exception (because
+ // we pass rb_eException to rb_marshal_define_compat). In the latter case, the first
+ // argument is a class object (see TYPE_USERDEF case in r_object0).
+ // We want to copy all instance variables (but "bt_locations") from obj to exc.
+ // But we do not want to do so in the second case, so the following branch is for that.
+ if (RB_TYPE_P(exc, T_CLASS)) return obj; // maybe called from Marshal's TYPE_USERDEF
+
+ rb_ivar_foreach(obj, ivar_copy_i, exc);
+
+ if (rb_attr_get(exc, id_bt) == rb_attr_get(exc, id_bt_locations)) {
+ rb_ivar_set(exc, id_bt_locations, Qnil);
+ }
+
+ return exc;
+}
+
void
Init_Exception(void)
{
rb_eException = rb_define_class("Exception", rb_cObject);
+ rb_define_alloc_func(rb_eException, exception_alloc);
+ rb_marshal_define_compat(rb_eException, rb_eException, exception_dumper, exception_loader);
rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1);
rb_define_singleton_method(rb_eException, "to_tty?", exc_s_to_tty_p, 0);
rb_define_method(rb_eException, "exception", exc_exception, -1);
@@ -2592,7 +2818,9 @@ Init_Exception(void)
rb_define_method(rb_eNameError, "name", name_err_name, 0);
rb_define_method(rb_eNameError, "receiver", name_err_receiver, 0);
rb_define_method(rb_eNameError, "local_variables", name_err_local_variables, 0);
- rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cData);
+ rb_cNameErrorMesg = rb_define_class_under(rb_eNameError, "message", rb_cObject);
+ rb_define_alloc_func(rb_cNameErrorMesg, name_err_mesg_alloc);
+ rb_define_method(rb_cNameErrorMesg, "initialize_copy", name_err_mesg_init_copy, 1);
rb_define_method(rb_cNameErrorMesg, "==", name_err_mesg_equal, 1);
rb_define_method(rb_cNameErrorMesg, "to_str", name_err_mesg_to_str, 0);
rb_define_method(rb_cNameErrorMesg, "_dump", name_err_mesg_dump, 1);
@@ -2610,7 +2838,7 @@ Init_Exception(void)
rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
rb_eEncodingError = rb_define_class("EncodingError", rb_eStandardError);
rb_eEncCompatError = rb_define_class_under(rb_cEncoding, "CompatibilityError", rb_eEncodingError);
- rb_eNoMatchingPatternError = rb_define_class("NoMatchingPatternError", rb_eRuntimeError);
+ rb_eNoMatchingPatternError = rb_define_class("NoMatchingPatternError", rb_eStandardError);
syserr_tbl = st_init_numtable();
rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
@@ -2623,7 +2851,7 @@ Init_Exception(void)
rb_mWarning = rb_define_module("Warning");
rb_define_singleton_method(rb_mWarning, "[]", rb_warning_s_aref, 1);
rb_define_singleton_method(rb_mWarning, "[]=", rb_warning_s_aset, 2);
- rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, 1);
+ rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, -1);
rb_extend_object(rb_mWarning, rb_mWarning);
/* :nodoc: */
@@ -2642,10 +2870,28 @@ Init_Exception(void)
id_errno = rb_intern_const("errno");
id_i_path = rb_intern_const("@path");
id_warn = rb_intern_const("warn");
+ id_category = rb_intern_const("category");
+ id_deprecated = rb_intern_const("deprecated");
+ id_experimental = rb_intern_const("experimental");
id_top = rb_intern_const("top");
id_bottom = rb_intern_const("bottom");
id_iseq = rb_make_internal_id();
id_recv = rb_make_internal_id();
+
+ sym_category = ID2SYM(id_category);
+
+ warning_categories = rb_ident_hash_new();
+ rb_gc_register_mark_object(warning_categories);
+ rb_hash_aset(warning_categories, ID2SYM(id_deprecated), INT2NUM(RB_WARN_CATEGORY_DEPRECATED));
+ rb_hash_aset(warning_categories, ID2SYM(id_experimental), INT2NUM(RB_WARN_CATEGORY_EXPERIMENTAL));
+ rb_obj_freeze(warning_categories);
+
+ warning_category_t_map = rb_ident_hash_new();
+ rb_gc_register_mark_object(warning_category_t_map);
+ rb_hash_aset(warning_category_t_map, INT2NUM(RB_WARN_CATEGORY_NONE), Qnil);
+ rb_hash_aset(warning_category_t_map, INT2NUM(RB_WARN_CATEGORY_DEPRECATED), ID2SYM(id_deprecated));
+ rb_hash_aset(warning_category_t_map, INT2NUM(RB_WARN_CATEGORY_EXPERIMENTAL), ID2SYM(id_experimental));
+ rb_obj_freeze(warning_category_t_map);
}
void
@@ -2816,6 +3062,12 @@ rb_sys_fail_path_in(const char *func_name, VALUE path)
void
rb_syserr_fail_path_in(const char *func_name, int n, VALUE path)
{
+ rb_exc_raise(rb_syserr_new_path_in(func_name, n, path));
+}
+
+VALUE
+rb_syserr_new_path_in(const char *func_name, int n, VALUE path)
+{
VALUE args[2];
if (!path) path = Qnil;
@@ -2827,7 +3079,7 @@ rb_syserr_fail_path_in(const char *func_name, int n, VALUE path)
}
args[0] = path;
args[1] = rb_str_new_cstr(func_name);
- rb_exc_raise(rb_class_new_instance(2, args, get_syserr(n)));
+ return rb_class_new_instance(2, args, get_syserr(n));
}
#endif
@@ -3035,14 +3287,14 @@ rb_check_frozen(VALUE obj)
void
rb_error_untrusted(VALUE obj)
{
- rb_warning("rb_error_untrusted is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("rb_error_untrusted", "3.2");
}
#undef rb_check_trusted
void
rb_check_trusted(VALUE obj)
{
- rb_warning("rb_check_trusted is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("rb_check_trusted", "3.2");
}
void
@@ -3066,12 +3318,6 @@ Init_syserr(void)
#include "warning.rbinc"
-void
-Init_warning(void)
-{
- load_warning();
-}
-
/*!
* \}
*/
diff --git a/eval.c b/eval.c
index 08f7ba97de..839518185a 100644
--- a/eval.c
+++ b/eval.c
@@ -11,18 +11,32 @@
**********************************************************************/
-#include "internal.h"
+#include "ruby/internal/config.h"
+
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
+#endif
+
#include "eval_intern.h"
-#include "iseq.h"
#include "gc.h"
-#include "ruby/vm.h"
-#include "vm_core.h"
+#include "internal.h"
+#include "internal/class.h"
+#include "internal/error.h"
+#include "internal/eval.h"
+#include "internal/hash.h"
+#include "internal/inits.h"
+#include "internal/io.h"
+#include "internal/object.h"
+#include "internal/thread.h"
+#include "internal/variable.h"
+#include "internal/scheduler.h"
+#include "iseq.h"
#include "mjit.h"
#include "probes.h"
#include "probes_helper.h"
-#ifdef HAVE_SYS_PRCTL_H
-#include <sys/prctl.h>
-#endif
+#include "ruby/vm.h"
+#include "vm_core.h"
+#include "ractor_core.h"
NORETURN(void rb_raise_jump(VALUE, VALUE));
void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec);
@@ -133,8 +147,26 @@ ruby_options(int argc, char **argv)
}
static void
+rb_ec_scheduler_finalize(rb_execution_context_t *ec)
+{
+ enum ruby_tag_type state;
+
+ EC_PUSH_TAG(ec);
+ if ((state = EC_EXEC_TAG()) == TAG_NONE) {
+ rb_scheduler_set(Qnil);
+ }
+ else {
+ state = error_handle(ec, state);
+ }
+ EC_POP_TAG();
+}
+
+static void
rb_ec_teardown(rb_execution_context_t *ec)
{
+ // If the user code defined a scheduler for the top level thread, run it:
+ rb_ec_scheduler_finalize(ec);
+
EC_PUSH_TAG(ec);
if (EC_EXEC_TAG() == TAG_NONE) {
rb_vm_trap_exit(rb_ec_vm_ptr(ec));
@@ -196,6 +228,7 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex)
rb_threadptr_interrupt(th);
rb_threadptr_check_signal(th);
+
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
th = th0;
@@ -215,7 +248,7 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex)
th->status = THREAD_KILLED;
errs[0] = ec->errinfo;
- SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all());
+ SAVE_ROOT_JMPBUF(th, rb_ractor_terminate_all());
}
else {
switch (step) {
@@ -231,6 +264,7 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex)
state = 0;
for (nerr = 0; nerr < numberof(errs); ++nerr) {
VALUE err = ATOMIC_VALUE_EXCHANGE(errs[nerr], Qnil);
+ VALUE sig;
if (!RTEST(err)) continue;
@@ -246,6 +280,11 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex)
state = NUM2INT(sig);
break;
}
+ else if (rb_obj_is_kind_of(err, rb_eSystemCallError) &&
+ FIXNUM_P(sig = rb_attr_get(err, id_signo))) {
+ state = NUM2INT(sig);
+ break;
+ }
else if (sysex == EXIT_SUCCESS) {
sysex = EXIT_FAILURE;
}
@@ -438,7 +477,6 @@ void
rb_class_modify_check(VALUE klass)
{
if (SPECIAL_CONST_P(klass)) {
- noclass:
Check_Type(klass, T_CLASS);
}
if (OBJ_FROZEN(klass)) {
@@ -456,6 +494,8 @@ rb_class_modify_check(VALUE klass)
case T_CLASS:
desc = "Class";
break;
+ default:
+ break;
}
}
}
@@ -469,7 +509,8 @@ rb_class_modify_check(VALUE klass)
desc = "class";
break;
default:
- goto noclass;
+ Check_Type(klass, T_CLASS);
+ UNREACHABLE;
}
}
rb_frozen_error_raise(klass, "can't modify frozen %s: %"PRIsVALUE, desc, klass);
@@ -622,16 +663,19 @@ setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE
}
if (rb_ec_set_raised(ec)) {
- fatal:
- ec->errinfo = exception_error;
- rb_ec_reset_raised(ec);
- EC_JUMP_TAG(ec, TAG_FATAL);
+ goto fatal;
}
if (tag != TAG_FATAL) {
RUBY_DTRACE_HOOK(RAISE, rb_obj_classname(ec->errinfo));
EXEC_EVENT_HOOK(ec, RUBY_EVENT_RAISE, ec->cfp->self, 0, 0, 0, mesg);
}
+ return;
+
+ fatal:
+ ec->errinfo = exception_error;
+ rb_ec_reset_raised(ec);
+ EC_JUMP_TAG(ec, TAG_FATAL);
}
/*! \private */
@@ -784,44 +828,37 @@ static VALUE
make_exception(int argc, const VALUE *argv, int isstr)
{
VALUE mesg, exc;
- int n;
mesg = Qnil;
switch (argc) {
case 0:
- break;
+ return Qnil;
case 1:
exc = argv[0];
- if (NIL_P(exc))
- break;
- if (isstr) {
+ if (isstr &&! NIL_P(exc)) {
mesg = rb_check_string_type(exc);
if (!NIL_P(mesg)) {
- mesg = rb_exc_new3(rb_eRuntimeError, mesg);
- break;
+ return rb_exc_new3(rb_eRuntimeError, mesg);
}
}
- n = 0;
- goto exception_call;
case 2:
case 3:
- exc = argv[0];
- n = 1;
- exception_call:
- mesg = rb_check_funcall(exc, idException, n, argv+1);
- if (mesg == Qundef) {
- rb_raise(rb_eTypeError, "exception class/object expected");
- }
break;
default:
rb_error_arity(argc, 0, 3);
}
- if (argc > 0) {
- if (!rb_obj_is_kind_of(mesg, rb_eException))
- rb_raise(rb_eTypeError, "exception object expected");
- if (argc > 2)
- set_backtrace(mesg, argv[2]);
+ if (NIL_P(mesg)) {
+ mesg = rb_check_funcall(argv[0], idException, argc != 1, &argv[1]);
+ }
+ if (mesg == Qundef) {
+ rb_raise(rb_eTypeError, "exception class/object expected");
+ }
+ if (!rb_obj_is_kind_of(mesg, rb_eException)) {
+ rb_raise(rb_eTypeError, "exception object expected");
+ }
+ if (argc == 3) {
+ set_backtrace(mesg, argv[2]);
}
return mesg;
@@ -913,14 +950,6 @@ rb_keyword_given_p(void)
return rb_vm_cframe_keyword_p(GET_EC()->cfp);
}
-/* -- Remove In 3.0 -- */
-int rb_vm_cframe_empty_keyword_p(const rb_control_frame_t *cfp);
-int
-rb_empty_keyword_given_p(void)
-{
- return rb_vm_cframe_empty_keyword_p(GET_EC()->cfp);
-}
-
VALUE rb_eThreadError;
/*! Declares that the current method needs a block.
@@ -971,7 +1000,7 @@ rb_rescue2(VALUE (* b_proc) (VALUE), VALUE data1,
/*!
* \copydoc rb_rescue2
- * \param[in] args exception classes, terminated by 0.
+ * \param[in] args exception classes, terminated by (VALUE)0.
*/
VALUE
rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
@@ -992,7 +1021,7 @@ rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
else if (result) {
/* escape from r_proc */
if (state == TAG_RETRY) {
- state = 0;
+ state = TAG_NONE;
ec->errinfo = Qnil;
result = Qfalse;
goto retry_entry;
@@ -1004,17 +1033,21 @@ rb_vrescue2(VALUE (* b_proc) (VALUE), VALUE data1,
if (state == TAG_RAISE) {
int handle = FALSE;
VALUE eclass;
+ va_list ap;
- while ((eclass = va_arg(args, VALUE)) != 0) {
+ result = Qnil;
+ /* reuses args when raised again after retrying in r_proc */
+ va_copy(ap, args);
+ while ((eclass = va_arg(ap, VALUE)) != 0) {
if (rb_obj_is_kind_of(ec->errinfo, eclass)) {
handle = TRUE;
break;
}
}
+ va_end(ap);
if (handle) {
- result = Qnil;
- state = 0;
+ state = TAG_NONE;
if (r_proc) {
result = (*r_proc) (data2, ec->errinfo);
}
@@ -1370,7 +1403,7 @@ refinement_superclass(VALUE superclass)
{
if (RB_TYPE_P(superclass, T_MODULE)) {
/* FIXME: Should ancestors of superclass be used here? */
- return rb_include_class_new(superclass, rb_cBasicObject);
+ return rb_include_class_new(RCLASS_ORIGIN(superclass), rb_cBasicObject);
}
else {
return superclass;
@@ -1412,8 +1445,7 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
c = iclass = rb_include_class_new(module, superclass);
RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
- RCLASS_M_TBL(OBJ_WB_UNPROTECT(c)) =
- RCLASS_M_TBL(OBJ_WB_UNPROTECT(module)); /* TODO: check unprotecting */
+ RCLASS_M_TBL(c) = RCLASS_M_TBL(module);
module = RCLASS_SUPER(module);
while (module && module != klass) {
@@ -1473,7 +1505,7 @@ rb_using_module(const rb_cref_t *cref, VALUE module)
{
Check_Type(module, T_MODULE);
using_module_recursive(cref, module);
- rb_clear_method_cache_by_class(rb_cObject);
+ rb_clear_method_cache_all();
}
/*! \private */
@@ -1543,9 +1575,6 @@ rb_mod_refine(VALUE module, VALUE klass)
}
ensure_class_or_module(klass);
- if (RB_TYPE_P(klass, T_MODULE)) {
- FL_SET(klass, RCLASS_REFINED_BY_ANY);
- }
CONST_ID(id_refinements, "__refinements__");
refinements = rb_attr_get(module, id_refinements);
if (NIL_P(refinements)) {
@@ -1993,7 +2022,10 @@ f_current_dirname(VALUE _)
* call-seq:
* global_variables -> array
*
- * Returns an array of the names of global variables.
+ * Returns an array of the names of global variables. This includes
+ * special regexp global variables such as <tt>$~</tt> and <tt>$+</tt>,
+ * but does not include the numbered regexp global variables (<tt>$1</tt>,
+ * <tt>$2</tt>, etc.).
*
* global_variables.grep /std/ #=> [:$stdin, :$stdout, :$stderr]
*/
@@ -2055,6 +2087,9 @@ Init_eval(void)
rb_define_virtual_variable("$@", errat_getter, errat_setter);
rb_define_virtual_variable("$!", errinfo_getter, 0);
+ rb_gvar_ractor_local("$@");
+ rb_gvar_ractor_local("$!");
+
rb_define_global_function("raise", f_raise, -1);
rb_define_global_function("fail", f_raise, -1);
diff --git a/eval_error.c b/eval_error.c
index 9d2de6dbc5..841275eed0 100644
--- a/eval_error.c
+++ b/eval_error.c
@@ -233,29 +233,43 @@ print_backtrace(const VALUE eclass, const VALUE errat, const VALUE str, int reve
if (!NIL_P(errat)) {
long i;
long len = RARRAY_LEN(errat);
- int skip = eclass == rb_eSysStackError;
const int threshold = 1000000000;
int width = (len <= 1) ? INT_MIN : ((int)log10((double)(len > threshold ?
((len - 1) / threshold) :
len - 1)) +
(len < threshold ? 0 : 9) + 1);
-#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
-#define TRACE_HEAD 8
-#define TRACE_TAIL 5
+ long skip_start = -1, skip_len = 0;
+
+ // skip for stackoverflow
+ if (eclass == rb_eSysStackError) {
+ long trace_head = 9;
+ long trace_tail = 4;
+ long trace_max = trace_head + trace_tail + 5;
+ if (len > trace_max) {
+ skip_start = trace_head;
+ skip_len = len - trace_max + 5;
+ }
+ }
+
+ // skip for explicit limit
+ if (rb_backtrace_length_limit >= 0 && len > rb_backtrace_length_limit + 2) {
+ skip_start = rb_backtrace_length_limit + 1;
+ skip_len = len - skip_start;
+ }
for (i = 1; i < len; i++) {
+ if (i == skip_start) {
+ write_warn_str(str, rb_sprintf("\t ... %ld levels...\n", skip_len));
+ i += skip_len;
+ if (i >= len) break;
+ }
VALUE line = RARRAY_AREF(errat, reverse ? len - i : i);
if (RB_TYPE_P(line, T_STRING)) {
VALUE bt = rb_str_new_cstr("\t");
if (reverse) rb_str_catf(bt, "%*ld: ", width, len - i);
write_warn_str(str, rb_str_catf(bt, "from %"PRIsVALUE"\n", line));
}
- if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
- write_warn_str(str, rb_sprintf("\t ... %ld levels...\n",
- len - TRACE_HEAD - TRACE_TAIL));
- i = len - TRACE_TAIL;
- }
}
}
}
@@ -309,9 +323,9 @@ rb_error_write(VALUE errinfo, VALUE emesg, VALUE errat, VALUE str, VALUE highlig
errat = Qnil;
}
eclass = CLASS_OF(errinfo);
- if (NIL_P(reverse) || NIL_P(highlight)) {
+ if (NIL_P(reverse)) reverse = Qfalse;
+ if (NIL_P(highlight)) {
VALUE tty = (VALUE)rb_stderr_tty_p();
- if (NIL_P(reverse)) reverse = tty;
if (NIL_P(highlight)) highlight = tty;
}
if (reverse) {
@@ -365,7 +379,7 @@ rb_ec_error_print(rb_execution_context_t * volatile ec, volatile VALUE errinfo)
if (!written) {
written = true;
- rb_error_write(errinfo, emesg, errat, Qnil, Qnil, Qnil);
+ rb_error_write(errinfo, emesg, errat, Qnil, Qnil, Qfalse);
}
EC_POP_TAG();
@@ -478,6 +492,10 @@ error_handle(rb_execution_context_t *ec, int ex)
rb_ivar_get(errinfo, id_signo) != INT2FIX(SIGSEGV)) {
/* no message when exiting by signal */
}
+ else if (rb_obj_is_kind_of(errinfo, rb_eSystemCallError) &&
+ FIXNUM_P(rb_attr_get(errinfo, id_signo))) {
+ /* no message when exiting by error to be mapped to signal */
+ }
else {
rb_ec_error_print(ec, errinfo);
}
diff --git a/eval_intern.h b/eval_intern.h
index a8eb828597..9fa9031189 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -132,7 +132,8 @@ LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *);
struct rb_vm_tag _tag; \
_tag.state = TAG_NONE; \
_tag.tag = Qundef; \
- _tag.prev = _ec->tag;
+ _tag.prev = _ec->tag; \
+ _tag.lock_rec = rb_ec_vm_lock_rec(_ec); \
#define EC_POP_TAG() \
_ec->tag = _tag.prev; \
@@ -157,12 +158,23 @@ LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *);
# define VAR_NOCLOBBERED(var) var
#endif
+static inline void
+rb_ec_vm_lock_rec_check(const rb_execution_context_t *ec, unsigned int recorded_lock_rec)
+{
+ unsigned int current_lock_rec = rb_ec_vm_lock_rec(ec);
+ if (current_lock_rec != recorded_lock_rec) {
+ rb_ec_vm_lock_rec_release(ec, recorded_lock_rec, current_lock_rec);
+ }
+}
+
/* clear ec->tag->state, and return the value */
static inline int
rb_ec_tag_state(const rb_execution_context_t *ec)
{
- enum ruby_tag_type state = ec->tag->state;
- ec->tag->state = TAG_NONE;
+ struct rb_vm_tag *tag = ec->tag;
+ enum ruby_tag_type state = tag->state;
+ tag->state = TAG_NONE;
+ rb_ec_vm_lock_rec_check(ec, tag->lock_rec);
return state;
}
@@ -281,13 +293,12 @@ rb_cref_t *rb_vm_cref(void);
rb_cref_t *rb_vm_cref_replace_with_duplicated_cref(void);
VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename);
void rb_vm_set_progname(VALUE filename);
-void rb_thread_terminate_all(void);
VALUE rb_vm_cbase(void);
/* vm_backtrace.c */
VALUE rb_ec_backtrace_object(const rb_execution_context_t *ec);
VALUE rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n);
-VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n);
+VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal);
#ifndef CharNext /* defined as CharNext[AW] on Windows. */
# ifdef HAVE_MBLEN
diff --git a/ext/-test-/RUBY_ALIGNOF/c.c b/ext/-test-/RUBY_ALIGNOF/c.c
new file mode 100644
index 0000000000..7a9f7cb498
--- /dev/null
+++ b/ext/-test-/RUBY_ALIGNOF/c.c
@@ -0,0 +1,15 @@
+#include "ruby.h"
+#include <stddef.h>
+
+struct T {
+ char _;
+ double t;
+};
+
+RBIMPL_STATIC_ASSERT(RUBY_ALIGNOF, RUBY_ALIGNOF(double) == offsetof(struct T, t));
+
+void
+Init_RUBY_ALIGNOF(void)
+{
+ // Windows linker mandates this symbol to exist.
+}
diff --git a/ext/-test-/RUBY_ALIGNOF/cpp.cpp b/ext/-test-/RUBY_ALIGNOF/cpp.cpp
new file mode 100644
index 0000000000..ed76d49b9f
--- /dev/null
+++ b/ext/-test-/RUBY_ALIGNOF/cpp.cpp
@@ -0,0 +1,9 @@
+#include "ruby.h"
+#include <cstddef>
+
+struct T {
+ char _;
+ double t;
+};
+
+RBIMPL_STATIC_ASSERT(RUBY_ALIGNOF, RUBY_ALIGNOF(double) == offsetof(T, t));
diff --git a/ext/-test-/RUBY_ALIGNOF/depend b/ext/-test-/RUBY_ALIGNOF/depend
new file mode 100644
index 0000000000..1662feda25
--- /dev/null
+++ b/ext/-test-/RUBY_ALIGNOF/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+c.o: $(RUBY_EXTCONF_H)
+c.o: $(arch_hdrdir)/ruby/config.h
+c.o: $(hdrdir)/ruby.h
+c.o: $(hdrdir)/ruby/assert.h
+c.o: $(hdrdir)/ruby/backward.h
+c.o: $(hdrdir)/ruby/backward/2/assume.h
+c.o: $(hdrdir)/ruby/backward/2/attributes.h
+c.o: $(hdrdir)/ruby/backward/2/bool.h
+c.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+c.o: $(hdrdir)/ruby/backward/2/inttypes.h
+c.o: $(hdrdir)/ruby/backward/2/limits.h
+c.o: $(hdrdir)/ruby/backward/2/long_long.h
+c.o: $(hdrdir)/ruby/backward/2/stdalign.h
+c.o: $(hdrdir)/ruby/backward/2/stdarg.h
+c.o: $(hdrdir)/ruby/defines.h
+c.o: $(hdrdir)/ruby/intern.h
+c.o: $(hdrdir)/ruby/internal/anyargs.h
+c.o: $(hdrdir)/ruby/internal/arithmetic.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+c.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+c.o: $(hdrdir)/ruby/internal/assume.h
+c.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+c.o: $(hdrdir)/ruby/internal/attr/artificial.h
+c.o: $(hdrdir)/ruby/internal/attr/cold.h
+c.o: $(hdrdir)/ruby/internal/attr/const.h
+c.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+c.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+c.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+c.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+c.o: $(hdrdir)/ruby/internal/attr/error.h
+c.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+c.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+c.o: $(hdrdir)/ruby/internal/attr/format.h
+c.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+c.o: $(hdrdir)/ruby/internal/attr/noalias.h
+c.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+c.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+c.o: $(hdrdir)/ruby/internal/attr/noinline.h
+c.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+c.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+c.o: $(hdrdir)/ruby/internal/attr/pure.h
+c.o: $(hdrdir)/ruby/internal/attr/restrict.h
+c.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+c.o: $(hdrdir)/ruby/internal/attr/warning.h
+c.o: $(hdrdir)/ruby/internal/attr/weakref.h
+c.o: $(hdrdir)/ruby/internal/cast.h
+c.o: $(hdrdir)/ruby/internal/compiler_is.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+c.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+c.o: $(hdrdir)/ruby/internal/compiler_since.h
+c.o: $(hdrdir)/ruby/internal/config.h
+c.o: $(hdrdir)/ruby/internal/constant_p.h
+c.o: $(hdrdir)/ruby/internal/core.h
+c.o: $(hdrdir)/ruby/internal/core/rarray.h
+c.o: $(hdrdir)/ruby/internal/core/rbasic.h
+c.o: $(hdrdir)/ruby/internal/core/rbignum.h
+c.o: $(hdrdir)/ruby/internal/core/rclass.h
+c.o: $(hdrdir)/ruby/internal/core/rdata.h
+c.o: $(hdrdir)/ruby/internal/core/rfile.h
+c.o: $(hdrdir)/ruby/internal/core/rhash.h
+c.o: $(hdrdir)/ruby/internal/core/robject.h
+c.o: $(hdrdir)/ruby/internal/core/rregexp.h
+c.o: $(hdrdir)/ruby/internal/core/rstring.h
+c.o: $(hdrdir)/ruby/internal/core/rstruct.h
+c.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+c.o: $(hdrdir)/ruby/internal/ctype.h
+c.o: $(hdrdir)/ruby/internal/dllexport.h
+c.o: $(hdrdir)/ruby/internal/dosish.h
+c.o: $(hdrdir)/ruby/internal/error.h
+c.o: $(hdrdir)/ruby/internal/eval.h
+c.o: $(hdrdir)/ruby/internal/event.h
+c.o: $(hdrdir)/ruby/internal/fl_type.h
+c.o: $(hdrdir)/ruby/internal/gc.h
+c.o: $(hdrdir)/ruby/internal/glob.h
+c.o: $(hdrdir)/ruby/internal/globals.h
+c.o: $(hdrdir)/ruby/internal/has/attribute.h
+c.o: $(hdrdir)/ruby/internal/has/builtin.h
+c.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+c.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+c.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+c.o: $(hdrdir)/ruby/internal/has/extension.h
+c.o: $(hdrdir)/ruby/internal/has/feature.h
+c.o: $(hdrdir)/ruby/internal/has/warning.h
+c.o: $(hdrdir)/ruby/internal/intern/array.h
+c.o: $(hdrdir)/ruby/internal/intern/bignum.h
+c.o: $(hdrdir)/ruby/internal/intern/class.h
+c.o: $(hdrdir)/ruby/internal/intern/compar.h
+c.o: $(hdrdir)/ruby/internal/intern/complex.h
+c.o: $(hdrdir)/ruby/internal/intern/cont.h
+c.o: $(hdrdir)/ruby/internal/intern/dir.h
+c.o: $(hdrdir)/ruby/internal/intern/enum.h
+c.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+c.o: $(hdrdir)/ruby/internal/intern/error.h
+c.o: $(hdrdir)/ruby/internal/intern/eval.h
+c.o: $(hdrdir)/ruby/internal/intern/file.h
+c.o: $(hdrdir)/ruby/internal/intern/gc.h
+c.o: $(hdrdir)/ruby/internal/intern/hash.h
+c.o: $(hdrdir)/ruby/internal/intern/io.h
+c.o: $(hdrdir)/ruby/internal/intern/load.h
+c.o: $(hdrdir)/ruby/internal/intern/marshal.h
+c.o: $(hdrdir)/ruby/internal/intern/numeric.h
+c.o: $(hdrdir)/ruby/internal/intern/object.h
+c.o: $(hdrdir)/ruby/internal/intern/parse.h
+c.o: $(hdrdir)/ruby/internal/intern/proc.h
+c.o: $(hdrdir)/ruby/internal/intern/process.h
+c.o: $(hdrdir)/ruby/internal/intern/random.h
+c.o: $(hdrdir)/ruby/internal/intern/range.h
+c.o: $(hdrdir)/ruby/internal/intern/rational.h
+c.o: $(hdrdir)/ruby/internal/intern/re.h
+c.o: $(hdrdir)/ruby/internal/intern/ruby.h
+c.o: $(hdrdir)/ruby/internal/intern/select.h
+c.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+c.o: $(hdrdir)/ruby/internal/intern/signal.h
+c.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+c.o: $(hdrdir)/ruby/internal/intern/string.h
+c.o: $(hdrdir)/ruby/internal/intern/struct.h
+c.o: $(hdrdir)/ruby/internal/intern/thread.h
+c.o: $(hdrdir)/ruby/internal/intern/time.h
+c.o: $(hdrdir)/ruby/internal/intern/variable.h
+c.o: $(hdrdir)/ruby/internal/intern/vm.h
+c.o: $(hdrdir)/ruby/internal/interpreter.h
+c.o: $(hdrdir)/ruby/internal/iterator.h
+c.o: $(hdrdir)/ruby/internal/memory.h
+c.o: $(hdrdir)/ruby/internal/method.h
+c.o: $(hdrdir)/ruby/internal/module.h
+c.o: $(hdrdir)/ruby/internal/newobj.h
+c.o: $(hdrdir)/ruby/internal/rgengc.h
+c.o: $(hdrdir)/ruby/internal/scan_args.h
+c.o: $(hdrdir)/ruby/internal/special_consts.h
+c.o: $(hdrdir)/ruby/internal/static_assert.h
+c.o: $(hdrdir)/ruby/internal/stdalign.h
+c.o: $(hdrdir)/ruby/internal/stdbool.h
+c.o: $(hdrdir)/ruby/internal/symbol.h
+c.o: $(hdrdir)/ruby/internal/token_paste.h
+c.o: $(hdrdir)/ruby/internal/value.h
+c.o: $(hdrdir)/ruby/internal/value_type.h
+c.o: $(hdrdir)/ruby/internal/variable.h
+c.o: $(hdrdir)/ruby/internal/warning_push.h
+c.o: $(hdrdir)/ruby/internal/xmalloc.h
+c.o: $(hdrdir)/ruby/missing.h
+c.o: $(hdrdir)/ruby/ruby.h
+c.o: $(hdrdir)/ruby/st.h
+c.o: $(hdrdir)/ruby/subst.h
+c.o: c.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/RUBY_ALIGNOF/extconf.rb b/ext/-test-/RUBY_ALIGNOF/extconf.rb
new file mode 100644
index 0000000000..98a370e987
--- /dev/null
+++ b/ext/-test-/RUBY_ALIGNOF/extconf.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: false
+$objs = %W"c.#$OBJEXT"
+
+$objs << "cpp.#$OBJEXT" if MakeMakefile['C++'].have_devel?
+
+create_makefile("-test-/RUBY_ALIGNOF")
diff --git a/ext/-test-/arith_seq/extract/depend b/ext/-test-/arith_seq/extract/depend
index bb0719941f..46117d1000 100644
--- a/ext/-test-/arith_seq/extract/depend
+++ b/ext/-test-/arith_seq/extract/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
extract.o: $(RUBY_EXTCONF_H)
extract.o: $(arch_hdrdir)/ruby/config.h
+extract.o: $(hdrdir)/ruby/internal/anyargs.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+extract.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+extract.o: $(hdrdir)/ruby/internal/assume.h
+extract.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+extract.o: $(hdrdir)/ruby/internal/attr/artificial.h
+extract.o: $(hdrdir)/ruby/internal/attr/cold.h
+extract.o: $(hdrdir)/ruby/internal/attr/const.h
+extract.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+extract.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+extract.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+extract.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+extract.o: $(hdrdir)/ruby/internal/attr/error.h
+extract.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+extract.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+extract.o: $(hdrdir)/ruby/internal/attr/format.h
+extract.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+extract.o: $(hdrdir)/ruby/internal/attr/noalias.h
+extract.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+extract.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+extract.o: $(hdrdir)/ruby/internal/attr/noinline.h
+extract.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+extract.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+extract.o: $(hdrdir)/ruby/internal/attr/pure.h
+extract.o: $(hdrdir)/ruby/internal/attr/restrict.h
+extract.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+extract.o: $(hdrdir)/ruby/internal/attr/warning.h
+extract.o: $(hdrdir)/ruby/internal/attr/weakref.h
+extract.o: $(hdrdir)/ruby/internal/cast.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+extract.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+extract.o: $(hdrdir)/ruby/internal/compiler_since.h
+extract.o: $(hdrdir)/ruby/internal/config.h
+extract.o: $(hdrdir)/ruby/internal/constant_p.h
+extract.o: $(hdrdir)/ruby/internal/core.h
+extract.o: $(hdrdir)/ruby/internal/core/rarray.h
+extract.o: $(hdrdir)/ruby/internal/core/rbasic.h
+extract.o: $(hdrdir)/ruby/internal/core/rbignum.h
+extract.o: $(hdrdir)/ruby/internal/core/rclass.h
+extract.o: $(hdrdir)/ruby/internal/core/rdata.h
+extract.o: $(hdrdir)/ruby/internal/core/rfile.h
+extract.o: $(hdrdir)/ruby/internal/core/rhash.h
+extract.o: $(hdrdir)/ruby/internal/core/robject.h
+extract.o: $(hdrdir)/ruby/internal/core/rregexp.h
+extract.o: $(hdrdir)/ruby/internal/core/rstring.h
+extract.o: $(hdrdir)/ruby/internal/core/rstruct.h
+extract.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+extract.o: $(hdrdir)/ruby/internal/ctype.h
+extract.o: $(hdrdir)/ruby/internal/dllexport.h
+extract.o: $(hdrdir)/ruby/internal/dosish.h
+extract.o: $(hdrdir)/ruby/internal/error.h
+extract.o: $(hdrdir)/ruby/internal/eval.h
+extract.o: $(hdrdir)/ruby/internal/event.h
+extract.o: $(hdrdir)/ruby/internal/fl_type.h
+extract.o: $(hdrdir)/ruby/internal/gc.h
+extract.o: $(hdrdir)/ruby/internal/glob.h
+extract.o: $(hdrdir)/ruby/internal/globals.h
+extract.o: $(hdrdir)/ruby/internal/has/attribute.h
+extract.o: $(hdrdir)/ruby/internal/has/builtin.h
+extract.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+extract.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+extract.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+extract.o: $(hdrdir)/ruby/internal/has/extension.h
+extract.o: $(hdrdir)/ruby/internal/has/feature.h
+extract.o: $(hdrdir)/ruby/internal/has/warning.h
+extract.o: $(hdrdir)/ruby/internal/intern/array.h
+extract.o: $(hdrdir)/ruby/internal/intern/bignum.h
+extract.o: $(hdrdir)/ruby/internal/intern/class.h
+extract.o: $(hdrdir)/ruby/internal/intern/compar.h
+extract.o: $(hdrdir)/ruby/internal/intern/complex.h
+extract.o: $(hdrdir)/ruby/internal/intern/cont.h
+extract.o: $(hdrdir)/ruby/internal/intern/dir.h
+extract.o: $(hdrdir)/ruby/internal/intern/enum.h
+extract.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+extract.o: $(hdrdir)/ruby/internal/intern/error.h
+extract.o: $(hdrdir)/ruby/internal/intern/eval.h
+extract.o: $(hdrdir)/ruby/internal/intern/file.h
+extract.o: $(hdrdir)/ruby/internal/intern/gc.h
+extract.o: $(hdrdir)/ruby/internal/intern/hash.h
+extract.o: $(hdrdir)/ruby/internal/intern/io.h
+extract.o: $(hdrdir)/ruby/internal/intern/load.h
+extract.o: $(hdrdir)/ruby/internal/intern/marshal.h
+extract.o: $(hdrdir)/ruby/internal/intern/numeric.h
+extract.o: $(hdrdir)/ruby/internal/intern/object.h
+extract.o: $(hdrdir)/ruby/internal/intern/parse.h
+extract.o: $(hdrdir)/ruby/internal/intern/proc.h
+extract.o: $(hdrdir)/ruby/internal/intern/process.h
+extract.o: $(hdrdir)/ruby/internal/intern/random.h
+extract.o: $(hdrdir)/ruby/internal/intern/range.h
+extract.o: $(hdrdir)/ruby/internal/intern/rational.h
+extract.o: $(hdrdir)/ruby/internal/intern/re.h
+extract.o: $(hdrdir)/ruby/internal/intern/ruby.h
+extract.o: $(hdrdir)/ruby/internal/intern/select.h
+extract.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+extract.o: $(hdrdir)/ruby/internal/intern/signal.h
+extract.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+extract.o: $(hdrdir)/ruby/internal/intern/string.h
+extract.o: $(hdrdir)/ruby/internal/intern/struct.h
+extract.o: $(hdrdir)/ruby/internal/intern/thread.h
+extract.o: $(hdrdir)/ruby/internal/intern/time.h
+extract.o: $(hdrdir)/ruby/internal/intern/variable.h
+extract.o: $(hdrdir)/ruby/internal/intern/vm.h
+extract.o: $(hdrdir)/ruby/internal/interpreter.h
+extract.o: $(hdrdir)/ruby/internal/iterator.h
+extract.o: $(hdrdir)/ruby/internal/memory.h
+extract.o: $(hdrdir)/ruby/internal/method.h
+extract.o: $(hdrdir)/ruby/internal/module.h
+extract.o: $(hdrdir)/ruby/internal/newobj.h
+extract.o: $(hdrdir)/ruby/internal/rgengc.h
+extract.o: $(hdrdir)/ruby/internal/scan_args.h
+extract.o: $(hdrdir)/ruby/internal/special_consts.h
+extract.o: $(hdrdir)/ruby/internal/static_assert.h
+extract.o: $(hdrdir)/ruby/internal/stdalign.h
+extract.o: $(hdrdir)/ruby/internal/stdbool.h
+extract.o: $(hdrdir)/ruby/internal/symbol.h
+extract.o: $(hdrdir)/ruby/internal/token_paste.h
+extract.o: $(hdrdir)/ruby/internal/value.h
+extract.o: $(hdrdir)/ruby/internal/value_type.h
+extract.o: $(hdrdir)/ruby/internal/variable.h
+extract.o: $(hdrdir)/ruby/internal/warning_push.h
+extract.o: $(hdrdir)/ruby/internal/xmalloc.h
extract.o: $(hdrdir)/ruby/assert.h
extract.o: $(hdrdir)/ruby/backward.h
+extract.o: $(hdrdir)/ruby/backward/2/assume.h
+extract.o: $(hdrdir)/ruby/backward/2/attributes.h
+extract.o: $(hdrdir)/ruby/backward/2/bool.h
+extract.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+extract.o: $(hdrdir)/ruby/backward/2/inttypes.h
+extract.o: $(hdrdir)/ruby/backward/2/limits.h
+extract.o: $(hdrdir)/ruby/backward/2/long_long.h
+extract.o: $(hdrdir)/ruby/backward/2/stdalign.h
+extract.o: $(hdrdir)/ruby/backward/2/stdarg.h
extract.o: $(hdrdir)/ruby/defines.h
extract.o: $(hdrdir)/ruby/intern.h
extract.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/array/concat/depend b/ext/-test-/array/concat/depend
new file mode 100644
index 0000000000..4f2ba01f71
--- /dev/null
+++ b/ext/-test-/array/concat/depend
@@ -0,0 +1,322 @@
+# AUTOGENERATED DEPENDENCIES START
+resize.o: $(RUBY_EXTCONF_H)
+resize.o: $(arch_hdrdir)/ruby/config.h
+resize.o: $(hdrdir)/ruby/assert.h
+resize.o: $(hdrdir)/ruby/backward.h
+resize.o: $(hdrdir)/ruby/backward/2/assume.h
+resize.o: $(hdrdir)/ruby/backward/2/attributes.h
+resize.o: $(hdrdir)/ruby/backward/2/bool.h
+resize.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+resize.o: $(hdrdir)/ruby/backward/2/inttypes.h
+resize.o: $(hdrdir)/ruby/backward/2/limits.h
+resize.o: $(hdrdir)/ruby/backward/2/long_long.h
+resize.o: $(hdrdir)/ruby/backward/2/stdalign.h
+resize.o: $(hdrdir)/ruby/backward/2/stdarg.h
+resize.o: $(hdrdir)/ruby/defines.h
+resize.o: $(hdrdir)/ruby/intern.h
+resize.o: $(hdrdir)/ruby/internal/anyargs.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+resize.o: $(hdrdir)/ruby/internal/assume.h
+resize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+resize.o: $(hdrdir)/ruby/internal/attr/artificial.h
+resize.o: $(hdrdir)/ruby/internal/attr/cold.h
+resize.o: $(hdrdir)/ruby/internal/attr/const.h
+resize.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+resize.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+resize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+resize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+resize.o: $(hdrdir)/ruby/internal/attr/error.h
+resize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+resize.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+resize.o: $(hdrdir)/ruby/internal/attr/format.h
+resize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+resize.o: $(hdrdir)/ruby/internal/attr/noalias.h
+resize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+resize.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+resize.o: $(hdrdir)/ruby/internal/attr/noinline.h
+resize.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+resize.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+resize.o: $(hdrdir)/ruby/internal/attr/pure.h
+resize.o: $(hdrdir)/ruby/internal/attr/restrict.h
+resize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+resize.o: $(hdrdir)/ruby/internal/attr/warning.h
+resize.o: $(hdrdir)/ruby/internal/attr/weakref.h
+resize.o: $(hdrdir)/ruby/internal/cast.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+resize.o: $(hdrdir)/ruby/internal/compiler_since.h
+resize.o: $(hdrdir)/ruby/internal/config.h
+resize.o: $(hdrdir)/ruby/internal/constant_p.h
+resize.o: $(hdrdir)/ruby/internal/core.h
+resize.o: $(hdrdir)/ruby/internal/core/rarray.h
+resize.o: $(hdrdir)/ruby/internal/core/rbasic.h
+resize.o: $(hdrdir)/ruby/internal/core/rbignum.h
+resize.o: $(hdrdir)/ruby/internal/core/rclass.h
+resize.o: $(hdrdir)/ruby/internal/core/rdata.h
+resize.o: $(hdrdir)/ruby/internal/core/rfile.h
+resize.o: $(hdrdir)/ruby/internal/core/rhash.h
+resize.o: $(hdrdir)/ruby/internal/core/robject.h
+resize.o: $(hdrdir)/ruby/internal/core/rregexp.h
+resize.o: $(hdrdir)/ruby/internal/core/rstring.h
+resize.o: $(hdrdir)/ruby/internal/core/rstruct.h
+resize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+resize.o: $(hdrdir)/ruby/internal/ctype.h
+resize.o: $(hdrdir)/ruby/internal/dllexport.h
+resize.o: $(hdrdir)/ruby/internal/dosish.h
+resize.o: $(hdrdir)/ruby/internal/error.h
+resize.o: $(hdrdir)/ruby/internal/eval.h
+resize.o: $(hdrdir)/ruby/internal/event.h
+resize.o: $(hdrdir)/ruby/internal/fl_type.h
+resize.o: $(hdrdir)/ruby/internal/gc.h
+resize.o: $(hdrdir)/ruby/internal/glob.h
+resize.o: $(hdrdir)/ruby/internal/globals.h
+resize.o: $(hdrdir)/ruby/internal/has/attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/builtin.h
+resize.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/extension.h
+resize.o: $(hdrdir)/ruby/internal/has/feature.h
+resize.o: $(hdrdir)/ruby/internal/has/warning.h
+resize.o: $(hdrdir)/ruby/internal/intern/array.h
+resize.o: $(hdrdir)/ruby/internal/intern/bignum.h
+resize.o: $(hdrdir)/ruby/internal/intern/class.h
+resize.o: $(hdrdir)/ruby/internal/intern/compar.h
+resize.o: $(hdrdir)/ruby/internal/intern/complex.h
+resize.o: $(hdrdir)/ruby/internal/intern/cont.h
+resize.o: $(hdrdir)/ruby/internal/intern/dir.h
+resize.o: $(hdrdir)/ruby/internal/intern/enum.h
+resize.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+resize.o: $(hdrdir)/ruby/internal/intern/error.h
+resize.o: $(hdrdir)/ruby/internal/intern/eval.h
+resize.o: $(hdrdir)/ruby/internal/intern/file.h
+resize.o: $(hdrdir)/ruby/internal/intern/gc.h
+resize.o: $(hdrdir)/ruby/internal/intern/hash.h
+resize.o: $(hdrdir)/ruby/internal/intern/io.h
+resize.o: $(hdrdir)/ruby/internal/intern/load.h
+resize.o: $(hdrdir)/ruby/internal/intern/marshal.h
+resize.o: $(hdrdir)/ruby/internal/intern/numeric.h
+resize.o: $(hdrdir)/ruby/internal/intern/object.h
+resize.o: $(hdrdir)/ruby/internal/intern/parse.h
+resize.o: $(hdrdir)/ruby/internal/intern/proc.h
+resize.o: $(hdrdir)/ruby/internal/intern/process.h
+resize.o: $(hdrdir)/ruby/internal/intern/random.h
+resize.o: $(hdrdir)/ruby/internal/intern/range.h
+resize.o: $(hdrdir)/ruby/internal/intern/rational.h
+resize.o: $(hdrdir)/ruby/internal/intern/re.h
+resize.o: $(hdrdir)/ruby/internal/intern/ruby.h
+resize.o: $(hdrdir)/ruby/internal/intern/select.h
+resize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+resize.o: $(hdrdir)/ruby/internal/intern/signal.h
+resize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+resize.o: $(hdrdir)/ruby/internal/intern/string.h
+resize.o: $(hdrdir)/ruby/internal/intern/struct.h
+resize.o: $(hdrdir)/ruby/internal/intern/thread.h
+resize.o: $(hdrdir)/ruby/internal/intern/time.h
+resize.o: $(hdrdir)/ruby/internal/intern/variable.h
+resize.o: $(hdrdir)/ruby/internal/intern/vm.h
+resize.o: $(hdrdir)/ruby/internal/interpreter.h
+resize.o: $(hdrdir)/ruby/internal/iterator.h
+resize.o: $(hdrdir)/ruby/internal/memory.h
+resize.o: $(hdrdir)/ruby/internal/method.h
+resize.o: $(hdrdir)/ruby/internal/module.h
+resize.o: $(hdrdir)/ruby/internal/newobj.h
+resize.o: $(hdrdir)/ruby/internal/rgengc.h
+resize.o: $(hdrdir)/ruby/internal/scan_args.h
+resize.o: $(hdrdir)/ruby/internal/special_consts.h
+resize.o: $(hdrdir)/ruby/internal/static_assert.h
+resize.o: $(hdrdir)/ruby/internal/stdalign.h
+resize.o: $(hdrdir)/ruby/internal/stdbool.h
+resize.o: $(hdrdir)/ruby/internal/symbol.h
+resize.o: $(hdrdir)/ruby/internal/value.h
+resize.o: $(hdrdir)/ruby/internal/value_type.h
+resize.o: $(hdrdir)/ruby/internal/variable.h
+resize.o: $(hdrdir)/ruby/internal/warning_push.h
+resize.o: $(hdrdir)/ruby/internal/xmalloc.h
+resize.o: $(hdrdir)/ruby/missing.h
+resize.o: $(hdrdir)/ruby/ruby.h
+resize.o: $(hdrdir)/ruby/st.h
+resize.o: $(hdrdir)/ruby/subst.h
+resize.o: resize.c
+to_ary_conact.o: $(RUBY_EXTCONF_H)
+to_ary_conact.o: $(arch_hdrdir)/ruby/config.h
+to_ary_conact.o: $(hdrdir)/ruby.h
+to_ary_conact.o: $(hdrdir)/ruby/assert.h
+to_ary_conact.o: $(hdrdir)/ruby/backward.h
+to_ary_conact.o: $(hdrdir)/ruby/backward/2/assume.h
+to_ary_conact.o: $(hdrdir)/ruby/backward/2/attributes.h
+to_ary_conact.o: $(hdrdir)/ruby/backward/2/bool.h
+to_ary_conact.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+to_ary_conact.o: $(hdrdir)/ruby/backward/2/inttypes.h
+to_ary_conact.o: $(hdrdir)/ruby/backward/2/limits.h
+to_ary_conact.o: $(hdrdir)/ruby/backward/2/long_long.h
+to_ary_conact.o: $(hdrdir)/ruby/backward/2/stdalign.h
+to_ary_conact.o: $(hdrdir)/ruby/backward/2/stdarg.h
+to_ary_conact.o: $(hdrdir)/ruby/defines.h
+to_ary_conact.o: $(hdrdir)/ruby/intern.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/anyargs.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/assume.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/artificial.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/cold.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/const.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/error.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/format.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/noalias.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/noinline.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/pure.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/restrict.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/warning.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/attr/weakref.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/cast.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/compiler_is.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/compiler_since.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/config.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/constant_p.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rarray.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rbasic.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rbignum.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rclass.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rdata.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rfile.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rhash.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/robject.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rregexp.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rstring.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rstruct.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/ctype.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/dllexport.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/dosish.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/error.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/eval.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/event.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/fl_type.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/gc.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/glob.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/globals.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/has/attribute.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/has/builtin.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/has/extension.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/has/feature.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/has/warning.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/array.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/bignum.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/class.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/compar.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/complex.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/cont.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/dir.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/enum.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/error.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/eval.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/file.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/gc.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/hash.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/io.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/load.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/marshal.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/numeric.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/object.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/parse.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/proc.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/process.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/random.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/range.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/rational.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/re.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/ruby.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/select.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/signal.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/string.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/struct.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/thread.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/time.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/variable.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/intern/vm.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/interpreter.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/iterator.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/memory.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/method.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/module.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/newobj.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/rgengc.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/scan_args.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/special_consts.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/static_assert.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/stdalign.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/stdbool.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/symbol.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/token_paste.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/value.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/value_type.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/variable.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/warning_push.h
+to_ary_conact.o: $(hdrdir)/ruby/internal/xmalloc.h
+to_ary_conact.o: $(hdrdir)/ruby/missing.h
+to_ary_conact.o: $(hdrdir)/ruby/ruby.h
+to_ary_conact.o: $(hdrdir)/ruby/st.h
+to_ary_conact.o: $(hdrdir)/ruby/subst.h
+to_ary_conact.o: to_ary_conact.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/array/concat/extconf.rb b/ext/-test-/array/concat/extconf.rb
new file mode 100644
index 0000000000..cdd79126c9
--- /dev/null
+++ b/ext/-test-/array/concat/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/array/to_ary_concat")
diff --git a/ext/-test-/array/concat/to_ary_conact.c b/ext/-test-/array/concat/to_ary_conact.c
new file mode 100644
index 0000000000..ec1fd321ce
--- /dev/null
+++ b/ext/-test-/array/concat/to_ary_conact.c
@@ -0,0 +1,34 @@
+#include "ruby.h"
+
+// Bar
+
+typedef struct {
+ int dummy;
+} Bar;
+
+static rb_data_type_t Bar_type = {
+ "Bar",
+ {NULL, RUBY_TYPED_DEFAULT_FREE, NULL },
+};
+
+static VALUE
+Bar_alloc(VALUE klass)
+{
+ return TypedData_Wrap_Struct(klass, &Bar_type, NULL);
+}
+
+VALUE Bar_to_ary(VALUE _self) {
+ VALUE ary = rb_ary_new2(2);
+ VALUE foo = rb_ary_new2(0);
+ rb_ary_push(ary, foo);
+ rb_ary_push(ary, foo);
+ rb_ary_push(ary, foo);
+ return ary;
+}
+
+void Init_to_ary_concat() {
+ VALUE mBug = rb_define_module("Bug");
+ VALUE bar = rb_define_class_under(mBug, "Bar", rb_cObject);
+ rb_define_alloc_func(bar, Bar_alloc);
+ rb_define_method(bar, "to_ary", Bar_to_ary, 0);
+}
diff --git a/ext/-test-/array/resize/depend b/ext/-test-/array/resize/depend
index a03cc47d51..7c52b21e59 100644
--- a/ext/-test-/array/resize/depend
+++ b/ext/-test-/array/resize/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
resize.o: $(RUBY_EXTCONF_H)
resize.o: $(arch_hdrdir)/ruby/config.h
+resize.o: $(hdrdir)/ruby/internal/anyargs.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+resize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+resize.o: $(hdrdir)/ruby/internal/assume.h
+resize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+resize.o: $(hdrdir)/ruby/internal/attr/artificial.h
+resize.o: $(hdrdir)/ruby/internal/attr/cold.h
+resize.o: $(hdrdir)/ruby/internal/attr/const.h
+resize.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+resize.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+resize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+resize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+resize.o: $(hdrdir)/ruby/internal/attr/error.h
+resize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+resize.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+resize.o: $(hdrdir)/ruby/internal/attr/format.h
+resize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+resize.o: $(hdrdir)/ruby/internal/attr/noalias.h
+resize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+resize.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+resize.o: $(hdrdir)/ruby/internal/attr/noinline.h
+resize.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+resize.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+resize.o: $(hdrdir)/ruby/internal/attr/pure.h
+resize.o: $(hdrdir)/ruby/internal/attr/restrict.h
+resize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+resize.o: $(hdrdir)/ruby/internal/attr/warning.h
+resize.o: $(hdrdir)/ruby/internal/attr/weakref.h
+resize.o: $(hdrdir)/ruby/internal/cast.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+resize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+resize.o: $(hdrdir)/ruby/internal/compiler_since.h
+resize.o: $(hdrdir)/ruby/internal/config.h
+resize.o: $(hdrdir)/ruby/internal/constant_p.h
+resize.o: $(hdrdir)/ruby/internal/core.h
+resize.o: $(hdrdir)/ruby/internal/core/rarray.h
+resize.o: $(hdrdir)/ruby/internal/core/rbasic.h
+resize.o: $(hdrdir)/ruby/internal/core/rbignum.h
+resize.o: $(hdrdir)/ruby/internal/core/rclass.h
+resize.o: $(hdrdir)/ruby/internal/core/rdata.h
+resize.o: $(hdrdir)/ruby/internal/core/rfile.h
+resize.o: $(hdrdir)/ruby/internal/core/rhash.h
+resize.o: $(hdrdir)/ruby/internal/core/robject.h
+resize.o: $(hdrdir)/ruby/internal/core/rregexp.h
+resize.o: $(hdrdir)/ruby/internal/core/rstring.h
+resize.o: $(hdrdir)/ruby/internal/core/rstruct.h
+resize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+resize.o: $(hdrdir)/ruby/internal/ctype.h
+resize.o: $(hdrdir)/ruby/internal/dllexport.h
+resize.o: $(hdrdir)/ruby/internal/dosish.h
+resize.o: $(hdrdir)/ruby/internal/error.h
+resize.o: $(hdrdir)/ruby/internal/eval.h
+resize.o: $(hdrdir)/ruby/internal/event.h
+resize.o: $(hdrdir)/ruby/internal/fl_type.h
+resize.o: $(hdrdir)/ruby/internal/gc.h
+resize.o: $(hdrdir)/ruby/internal/glob.h
+resize.o: $(hdrdir)/ruby/internal/globals.h
+resize.o: $(hdrdir)/ruby/internal/has/attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/builtin.h
+resize.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+resize.o: $(hdrdir)/ruby/internal/has/extension.h
+resize.o: $(hdrdir)/ruby/internal/has/feature.h
+resize.o: $(hdrdir)/ruby/internal/has/warning.h
+resize.o: $(hdrdir)/ruby/internal/intern/array.h
+resize.o: $(hdrdir)/ruby/internal/intern/bignum.h
+resize.o: $(hdrdir)/ruby/internal/intern/class.h
+resize.o: $(hdrdir)/ruby/internal/intern/compar.h
+resize.o: $(hdrdir)/ruby/internal/intern/complex.h
+resize.o: $(hdrdir)/ruby/internal/intern/cont.h
+resize.o: $(hdrdir)/ruby/internal/intern/dir.h
+resize.o: $(hdrdir)/ruby/internal/intern/enum.h
+resize.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+resize.o: $(hdrdir)/ruby/internal/intern/error.h
+resize.o: $(hdrdir)/ruby/internal/intern/eval.h
+resize.o: $(hdrdir)/ruby/internal/intern/file.h
+resize.o: $(hdrdir)/ruby/internal/intern/gc.h
+resize.o: $(hdrdir)/ruby/internal/intern/hash.h
+resize.o: $(hdrdir)/ruby/internal/intern/io.h
+resize.o: $(hdrdir)/ruby/internal/intern/load.h
+resize.o: $(hdrdir)/ruby/internal/intern/marshal.h
+resize.o: $(hdrdir)/ruby/internal/intern/numeric.h
+resize.o: $(hdrdir)/ruby/internal/intern/object.h
+resize.o: $(hdrdir)/ruby/internal/intern/parse.h
+resize.o: $(hdrdir)/ruby/internal/intern/proc.h
+resize.o: $(hdrdir)/ruby/internal/intern/process.h
+resize.o: $(hdrdir)/ruby/internal/intern/random.h
+resize.o: $(hdrdir)/ruby/internal/intern/range.h
+resize.o: $(hdrdir)/ruby/internal/intern/rational.h
+resize.o: $(hdrdir)/ruby/internal/intern/re.h
+resize.o: $(hdrdir)/ruby/internal/intern/ruby.h
+resize.o: $(hdrdir)/ruby/internal/intern/select.h
+resize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+resize.o: $(hdrdir)/ruby/internal/intern/signal.h
+resize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+resize.o: $(hdrdir)/ruby/internal/intern/string.h
+resize.o: $(hdrdir)/ruby/internal/intern/struct.h
+resize.o: $(hdrdir)/ruby/internal/intern/thread.h
+resize.o: $(hdrdir)/ruby/internal/intern/time.h
+resize.o: $(hdrdir)/ruby/internal/intern/variable.h
+resize.o: $(hdrdir)/ruby/internal/intern/vm.h
+resize.o: $(hdrdir)/ruby/internal/interpreter.h
+resize.o: $(hdrdir)/ruby/internal/iterator.h
+resize.o: $(hdrdir)/ruby/internal/memory.h
+resize.o: $(hdrdir)/ruby/internal/method.h
+resize.o: $(hdrdir)/ruby/internal/module.h
+resize.o: $(hdrdir)/ruby/internal/newobj.h
+resize.o: $(hdrdir)/ruby/internal/rgengc.h
+resize.o: $(hdrdir)/ruby/internal/scan_args.h
+resize.o: $(hdrdir)/ruby/internal/special_consts.h
+resize.o: $(hdrdir)/ruby/internal/static_assert.h
+resize.o: $(hdrdir)/ruby/internal/stdalign.h
+resize.o: $(hdrdir)/ruby/internal/stdbool.h
+resize.o: $(hdrdir)/ruby/internal/symbol.h
+resize.o: $(hdrdir)/ruby/internal/token_paste.h
+resize.o: $(hdrdir)/ruby/internal/value.h
+resize.o: $(hdrdir)/ruby/internal/value_type.h
+resize.o: $(hdrdir)/ruby/internal/variable.h
+resize.o: $(hdrdir)/ruby/internal/warning_push.h
+resize.o: $(hdrdir)/ruby/internal/xmalloc.h
resize.o: $(hdrdir)/ruby/assert.h
resize.o: $(hdrdir)/ruby/backward.h
+resize.o: $(hdrdir)/ruby/backward/2/assume.h
+resize.o: $(hdrdir)/ruby/backward/2/attributes.h
+resize.o: $(hdrdir)/ruby/backward/2/bool.h
+resize.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+resize.o: $(hdrdir)/ruby/backward/2/inttypes.h
+resize.o: $(hdrdir)/ruby/backward/2/limits.h
+resize.o: $(hdrdir)/ruby/backward/2/long_long.h
+resize.o: $(hdrdir)/ruby/backward/2/stdalign.h
+resize.o: $(hdrdir)/ruby/backward/2/stdarg.h
resize.o: $(hdrdir)/ruby/defines.h
resize.o: $(hdrdir)/ruby/intern.h
resize.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/bignum/big2str.c b/ext/-test-/bignum/big2str.c
index ec4bde2915..bc5a933f82 100644
--- a/ext/-test-/bignum/big2str.c
+++ b/ext/-test-/bignum/big2str.c
@@ -1,4 +1,4 @@
-#include "internal.h"
+#include "internal/bignum.h"
static VALUE
big(VALUE x)
diff --git a/ext/-test-/bignum/bigzero.c b/ext/-test-/bignum/bigzero.c
index 35117db7ae..e2bfebcd3e 100644
--- a/ext/-test-/bignum/bigzero.c
+++ b/ext/-test-/bignum/bigzero.c
@@ -1,4 +1,4 @@
-#include "internal.h"
+#include "internal/bignum.h"
static VALUE
bug_big_zero(VALUE self, VALUE length)
diff --git a/ext/-test-/bignum/depend b/ext/-test-/bignum/depend
index 38c9f6114e..7ddf1da1dc 100644
--- a/ext/-test-/bignum/depend
+++ b/ext/-test-/bignum/depend
@@ -2,8 +2,157 @@
big2str.o: $(RUBY_EXTCONF_H)
big2str.o: $(arch_hdrdir)/ruby/config.h
big2str.o: $(hdrdir)/ruby.h
+big2str.o: $(hdrdir)/ruby/internal/anyargs.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+big2str.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+big2str.o: $(hdrdir)/ruby/internal/assume.h
+big2str.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+big2str.o: $(hdrdir)/ruby/internal/attr/artificial.h
+big2str.o: $(hdrdir)/ruby/internal/attr/cold.h
+big2str.o: $(hdrdir)/ruby/internal/attr/const.h
+big2str.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+big2str.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+big2str.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+big2str.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+big2str.o: $(hdrdir)/ruby/internal/attr/error.h
+big2str.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+big2str.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+big2str.o: $(hdrdir)/ruby/internal/attr/format.h
+big2str.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+big2str.o: $(hdrdir)/ruby/internal/attr/noalias.h
+big2str.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+big2str.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+big2str.o: $(hdrdir)/ruby/internal/attr/noinline.h
+big2str.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+big2str.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+big2str.o: $(hdrdir)/ruby/internal/attr/pure.h
+big2str.o: $(hdrdir)/ruby/internal/attr/restrict.h
+big2str.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+big2str.o: $(hdrdir)/ruby/internal/attr/warning.h
+big2str.o: $(hdrdir)/ruby/internal/attr/weakref.h
+big2str.o: $(hdrdir)/ruby/internal/cast.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+big2str.o: $(hdrdir)/ruby/internal/compiler_since.h
+big2str.o: $(hdrdir)/ruby/internal/config.h
+big2str.o: $(hdrdir)/ruby/internal/constant_p.h
+big2str.o: $(hdrdir)/ruby/internal/core.h
+big2str.o: $(hdrdir)/ruby/internal/core/rarray.h
+big2str.o: $(hdrdir)/ruby/internal/core/rbasic.h
+big2str.o: $(hdrdir)/ruby/internal/core/rbignum.h
+big2str.o: $(hdrdir)/ruby/internal/core/rclass.h
+big2str.o: $(hdrdir)/ruby/internal/core/rdata.h
+big2str.o: $(hdrdir)/ruby/internal/core/rfile.h
+big2str.o: $(hdrdir)/ruby/internal/core/rhash.h
+big2str.o: $(hdrdir)/ruby/internal/core/robject.h
+big2str.o: $(hdrdir)/ruby/internal/core/rregexp.h
+big2str.o: $(hdrdir)/ruby/internal/core/rstring.h
+big2str.o: $(hdrdir)/ruby/internal/core/rstruct.h
+big2str.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+big2str.o: $(hdrdir)/ruby/internal/ctype.h
+big2str.o: $(hdrdir)/ruby/internal/dllexport.h
+big2str.o: $(hdrdir)/ruby/internal/dosish.h
+big2str.o: $(hdrdir)/ruby/internal/error.h
+big2str.o: $(hdrdir)/ruby/internal/eval.h
+big2str.o: $(hdrdir)/ruby/internal/event.h
+big2str.o: $(hdrdir)/ruby/internal/fl_type.h
+big2str.o: $(hdrdir)/ruby/internal/gc.h
+big2str.o: $(hdrdir)/ruby/internal/glob.h
+big2str.o: $(hdrdir)/ruby/internal/globals.h
+big2str.o: $(hdrdir)/ruby/internal/has/attribute.h
+big2str.o: $(hdrdir)/ruby/internal/has/builtin.h
+big2str.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+big2str.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+big2str.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+big2str.o: $(hdrdir)/ruby/internal/has/extension.h
+big2str.o: $(hdrdir)/ruby/internal/has/feature.h
+big2str.o: $(hdrdir)/ruby/internal/has/warning.h
+big2str.o: $(hdrdir)/ruby/internal/intern/array.h
+big2str.o: $(hdrdir)/ruby/internal/intern/bignum.h
+big2str.o: $(hdrdir)/ruby/internal/intern/class.h
+big2str.o: $(hdrdir)/ruby/internal/intern/compar.h
+big2str.o: $(hdrdir)/ruby/internal/intern/complex.h
+big2str.o: $(hdrdir)/ruby/internal/intern/cont.h
+big2str.o: $(hdrdir)/ruby/internal/intern/dir.h
+big2str.o: $(hdrdir)/ruby/internal/intern/enum.h
+big2str.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+big2str.o: $(hdrdir)/ruby/internal/intern/error.h
+big2str.o: $(hdrdir)/ruby/internal/intern/eval.h
+big2str.o: $(hdrdir)/ruby/internal/intern/file.h
+big2str.o: $(hdrdir)/ruby/internal/intern/gc.h
+big2str.o: $(hdrdir)/ruby/internal/intern/hash.h
+big2str.o: $(hdrdir)/ruby/internal/intern/io.h
+big2str.o: $(hdrdir)/ruby/internal/intern/load.h
+big2str.o: $(hdrdir)/ruby/internal/intern/marshal.h
+big2str.o: $(hdrdir)/ruby/internal/intern/numeric.h
+big2str.o: $(hdrdir)/ruby/internal/intern/object.h
+big2str.o: $(hdrdir)/ruby/internal/intern/parse.h
+big2str.o: $(hdrdir)/ruby/internal/intern/proc.h
+big2str.o: $(hdrdir)/ruby/internal/intern/process.h
+big2str.o: $(hdrdir)/ruby/internal/intern/random.h
+big2str.o: $(hdrdir)/ruby/internal/intern/range.h
+big2str.o: $(hdrdir)/ruby/internal/intern/rational.h
+big2str.o: $(hdrdir)/ruby/internal/intern/re.h
+big2str.o: $(hdrdir)/ruby/internal/intern/ruby.h
+big2str.o: $(hdrdir)/ruby/internal/intern/select.h
+big2str.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+big2str.o: $(hdrdir)/ruby/internal/intern/signal.h
+big2str.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+big2str.o: $(hdrdir)/ruby/internal/intern/string.h
+big2str.o: $(hdrdir)/ruby/internal/intern/struct.h
+big2str.o: $(hdrdir)/ruby/internal/intern/thread.h
+big2str.o: $(hdrdir)/ruby/internal/intern/time.h
+big2str.o: $(hdrdir)/ruby/internal/intern/variable.h
+big2str.o: $(hdrdir)/ruby/internal/intern/vm.h
+big2str.o: $(hdrdir)/ruby/internal/interpreter.h
+big2str.o: $(hdrdir)/ruby/internal/iterator.h
+big2str.o: $(hdrdir)/ruby/internal/memory.h
+big2str.o: $(hdrdir)/ruby/internal/method.h
+big2str.o: $(hdrdir)/ruby/internal/module.h
+big2str.o: $(hdrdir)/ruby/internal/newobj.h
+big2str.o: $(hdrdir)/ruby/internal/rgengc.h
+big2str.o: $(hdrdir)/ruby/internal/scan_args.h
+big2str.o: $(hdrdir)/ruby/internal/special_consts.h
+big2str.o: $(hdrdir)/ruby/internal/static_assert.h
+big2str.o: $(hdrdir)/ruby/internal/stdalign.h
+big2str.o: $(hdrdir)/ruby/internal/stdbool.h
+big2str.o: $(hdrdir)/ruby/internal/symbol.h
+big2str.o: $(hdrdir)/ruby/internal/token_paste.h
+big2str.o: $(hdrdir)/ruby/internal/value.h
+big2str.o: $(hdrdir)/ruby/internal/value_type.h
+big2str.o: $(hdrdir)/ruby/internal/variable.h
+big2str.o: $(hdrdir)/ruby/internal/warning_push.h
+big2str.o: $(hdrdir)/ruby/internal/xmalloc.h
big2str.o: $(hdrdir)/ruby/assert.h
big2str.o: $(hdrdir)/ruby/backward.h
+big2str.o: $(hdrdir)/ruby/backward/2/assume.h
+big2str.o: $(hdrdir)/ruby/backward/2/attributes.h
+big2str.o: $(hdrdir)/ruby/backward/2/bool.h
+big2str.o: $(hdrdir)/ruby/backward/2/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
+big2str.o: $(hdrdir)/ruby/backward/2/stdalign.h
+big2str.o: $(hdrdir)/ruby/backward/2/stdarg.h
big2str.o: $(hdrdir)/ruby/defines.h
big2str.o: $(hdrdir)/ruby/intern.h
big2str.o: $(hdrdir)/ruby/missing.h
@@ -11,12 +160,162 @@ big2str.o: $(hdrdir)/ruby/ruby.h
big2str.o: $(hdrdir)/ruby/st.h
big2str.o: $(hdrdir)/ruby/subst.h
big2str.o: $(top_srcdir)/internal.h
+big2str.o: $(top_srcdir)/internal/bignum.h
big2str.o: big2str.c
bigzero.o: $(RUBY_EXTCONF_H)
bigzero.o: $(arch_hdrdir)/ruby/config.h
bigzero.o: $(hdrdir)/ruby.h
+bigzero.o: $(hdrdir)/ruby/internal/anyargs.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bigzero.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bigzero.o: $(hdrdir)/ruby/internal/assume.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/cold.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/const.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/error.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/format.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/pure.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/warning.h
+bigzero.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bigzero.o: $(hdrdir)/ruby/internal/cast.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bigzero.o: $(hdrdir)/ruby/internal/compiler_since.h
+bigzero.o: $(hdrdir)/ruby/internal/config.h
+bigzero.o: $(hdrdir)/ruby/internal/constant_p.h
+bigzero.o: $(hdrdir)/ruby/internal/core.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rarray.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rclass.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rdata.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rfile.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rhash.h
+bigzero.o: $(hdrdir)/ruby/internal/core/robject.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rstring.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bigzero.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bigzero.o: $(hdrdir)/ruby/internal/ctype.h
+bigzero.o: $(hdrdir)/ruby/internal/dllexport.h
+bigzero.o: $(hdrdir)/ruby/internal/dosish.h
+bigzero.o: $(hdrdir)/ruby/internal/error.h
+bigzero.o: $(hdrdir)/ruby/internal/eval.h
+bigzero.o: $(hdrdir)/ruby/internal/event.h
+bigzero.o: $(hdrdir)/ruby/internal/fl_type.h
+bigzero.o: $(hdrdir)/ruby/internal/gc.h
+bigzero.o: $(hdrdir)/ruby/internal/glob.h
+bigzero.o: $(hdrdir)/ruby/internal/globals.h
+bigzero.o: $(hdrdir)/ruby/internal/has/attribute.h
+bigzero.o: $(hdrdir)/ruby/internal/has/builtin.h
+bigzero.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bigzero.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bigzero.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bigzero.o: $(hdrdir)/ruby/internal/has/extension.h
+bigzero.o: $(hdrdir)/ruby/internal/has/feature.h
+bigzero.o: $(hdrdir)/ruby/internal/has/warning.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/array.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/class.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/compar.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/complex.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/cont.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/dir.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/enum.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/error.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/eval.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/file.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/gc.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/hash.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/io.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/load.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/object.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/parse.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/proc.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/process.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/random.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/range.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/rational.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/re.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/select.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/signal.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/string.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/struct.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/thread.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/time.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/variable.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/vm.h
+bigzero.o: $(hdrdir)/ruby/internal/interpreter.h
+bigzero.o: $(hdrdir)/ruby/internal/iterator.h
+bigzero.o: $(hdrdir)/ruby/internal/memory.h
+bigzero.o: $(hdrdir)/ruby/internal/method.h
+bigzero.o: $(hdrdir)/ruby/internal/module.h
+bigzero.o: $(hdrdir)/ruby/internal/newobj.h
+bigzero.o: $(hdrdir)/ruby/internal/rgengc.h
+bigzero.o: $(hdrdir)/ruby/internal/scan_args.h
+bigzero.o: $(hdrdir)/ruby/internal/special_consts.h
+bigzero.o: $(hdrdir)/ruby/internal/static_assert.h
+bigzero.o: $(hdrdir)/ruby/internal/stdalign.h
+bigzero.o: $(hdrdir)/ruby/internal/stdbool.h
+bigzero.o: $(hdrdir)/ruby/internal/symbol.h
+bigzero.o: $(hdrdir)/ruby/internal/token_paste.h
+bigzero.o: $(hdrdir)/ruby/internal/value.h
+bigzero.o: $(hdrdir)/ruby/internal/value_type.h
+bigzero.o: $(hdrdir)/ruby/internal/variable.h
+bigzero.o: $(hdrdir)/ruby/internal/warning_push.h
+bigzero.o: $(hdrdir)/ruby/internal/xmalloc.h
bigzero.o: $(hdrdir)/ruby/assert.h
bigzero.o: $(hdrdir)/ruby/backward.h
+bigzero.o: $(hdrdir)/ruby/backward/2/assume.h
+bigzero.o: $(hdrdir)/ruby/backward/2/attributes.h
+bigzero.o: $(hdrdir)/ruby/backward/2/bool.h
+bigzero.o: $(hdrdir)/ruby/backward/2/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
+bigzero.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bigzero.o: $(hdrdir)/ruby/backward/2/stdarg.h
bigzero.o: $(hdrdir)/ruby/defines.h
bigzero.o: $(hdrdir)/ruby/intern.h
bigzero.o: $(hdrdir)/ruby/missing.h
@@ -24,12 +323,162 @@ bigzero.o: $(hdrdir)/ruby/ruby.h
bigzero.o: $(hdrdir)/ruby/st.h
bigzero.o: $(hdrdir)/ruby/subst.h
bigzero.o: $(top_srcdir)/internal.h
+bigzero.o: $(top_srcdir)/internal/bignum.h
bigzero.o: bigzero.c
div.o: $(RUBY_EXTCONF_H)
div.o: $(arch_hdrdir)/ruby/config.h
div.o: $(hdrdir)/ruby.h
+div.o: $(hdrdir)/ruby/internal/anyargs.h
+div.o: $(hdrdir)/ruby/internal/arithmetic.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+div.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+div.o: $(hdrdir)/ruby/internal/assume.h
+div.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+div.o: $(hdrdir)/ruby/internal/attr/artificial.h
+div.o: $(hdrdir)/ruby/internal/attr/cold.h
+div.o: $(hdrdir)/ruby/internal/attr/const.h
+div.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+div.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+div.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+div.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+div.o: $(hdrdir)/ruby/internal/attr/error.h
+div.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+div.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+div.o: $(hdrdir)/ruby/internal/attr/format.h
+div.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+div.o: $(hdrdir)/ruby/internal/attr/noalias.h
+div.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+div.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+div.o: $(hdrdir)/ruby/internal/attr/noinline.h
+div.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+div.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+div.o: $(hdrdir)/ruby/internal/attr/pure.h
+div.o: $(hdrdir)/ruby/internal/attr/restrict.h
+div.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+div.o: $(hdrdir)/ruby/internal/attr/warning.h
+div.o: $(hdrdir)/ruby/internal/attr/weakref.h
+div.o: $(hdrdir)/ruby/internal/cast.h
+div.o: $(hdrdir)/ruby/internal/compiler_is.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+div.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+div.o: $(hdrdir)/ruby/internal/compiler_since.h
+div.o: $(hdrdir)/ruby/internal/config.h
+div.o: $(hdrdir)/ruby/internal/constant_p.h
+div.o: $(hdrdir)/ruby/internal/core.h
+div.o: $(hdrdir)/ruby/internal/core/rarray.h
+div.o: $(hdrdir)/ruby/internal/core/rbasic.h
+div.o: $(hdrdir)/ruby/internal/core/rbignum.h
+div.o: $(hdrdir)/ruby/internal/core/rclass.h
+div.o: $(hdrdir)/ruby/internal/core/rdata.h
+div.o: $(hdrdir)/ruby/internal/core/rfile.h
+div.o: $(hdrdir)/ruby/internal/core/rhash.h
+div.o: $(hdrdir)/ruby/internal/core/robject.h
+div.o: $(hdrdir)/ruby/internal/core/rregexp.h
+div.o: $(hdrdir)/ruby/internal/core/rstring.h
+div.o: $(hdrdir)/ruby/internal/core/rstruct.h
+div.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+div.o: $(hdrdir)/ruby/internal/ctype.h
+div.o: $(hdrdir)/ruby/internal/dllexport.h
+div.o: $(hdrdir)/ruby/internal/dosish.h
+div.o: $(hdrdir)/ruby/internal/error.h
+div.o: $(hdrdir)/ruby/internal/eval.h
+div.o: $(hdrdir)/ruby/internal/event.h
+div.o: $(hdrdir)/ruby/internal/fl_type.h
+div.o: $(hdrdir)/ruby/internal/gc.h
+div.o: $(hdrdir)/ruby/internal/glob.h
+div.o: $(hdrdir)/ruby/internal/globals.h
+div.o: $(hdrdir)/ruby/internal/has/attribute.h
+div.o: $(hdrdir)/ruby/internal/has/builtin.h
+div.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+div.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+div.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+div.o: $(hdrdir)/ruby/internal/has/extension.h
+div.o: $(hdrdir)/ruby/internal/has/feature.h
+div.o: $(hdrdir)/ruby/internal/has/warning.h
+div.o: $(hdrdir)/ruby/internal/intern/array.h
+div.o: $(hdrdir)/ruby/internal/intern/bignum.h
+div.o: $(hdrdir)/ruby/internal/intern/class.h
+div.o: $(hdrdir)/ruby/internal/intern/compar.h
+div.o: $(hdrdir)/ruby/internal/intern/complex.h
+div.o: $(hdrdir)/ruby/internal/intern/cont.h
+div.o: $(hdrdir)/ruby/internal/intern/dir.h
+div.o: $(hdrdir)/ruby/internal/intern/enum.h
+div.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+div.o: $(hdrdir)/ruby/internal/intern/error.h
+div.o: $(hdrdir)/ruby/internal/intern/eval.h
+div.o: $(hdrdir)/ruby/internal/intern/file.h
+div.o: $(hdrdir)/ruby/internal/intern/gc.h
+div.o: $(hdrdir)/ruby/internal/intern/hash.h
+div.o: $(hdrdir)/ruby/internal/intern/io.h
+div.o: $(hdrdir)/ruby/internal/intern/load.h
+div.o: $(hdrdir)/ruby/internal/intern/marshal.h
+div.o: $(hdrdir)/ruby/internal/intern/numeric.h
+div.o: $(hdrdir)/ruby/internal/intern/object.h
+div.o: $(hdrdir)/ruby/internal/intern/parse.h
+div.o: $(hdrdir)/ruby/internal/intern/proc.h
+div.o: $(hdrdir)/ruby/internal/intern/process.h
+div.o: $(hdrdir)/ruby/internal/intern/random.h
+div.o: $(hdrdir)/ruby/internal/intern/range.h
+div.o: $(hdrdir)/ruby/internal/intern/rational.h
+div.o: $(hdrdir)/ruby/internal/intern/re.h
+div.o: $(hdrdir)/ruby/internal/intern/ruby.h
+div.o: $(hdrdir)/ruby/internal/intern/select.h
+div.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+div.o: $(hdrdir)/ruby/internal/intern/signal.h
+div.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+div.o: $(hdrdir)/ruby/internal/intern/string.h
+div.o: $(hdrdir)/ruby/internal/intern/struct.h
+div.o: $(hdrdir)/ruby/internal/intern/thread.h
+div.o: $(hdrdir)/ruby/internal/intern/time.h
+div.o: $(hdrdir)/ruby/internal/intern/variable.h
+div.o: $(hdrdir)/ruby/internal/intern/vm.h
+div.o: $(hdrdir)/ruby/internal/interpreter.h
+div.o: $(hdrdir)/ruby/internal/iterator.h
+div.o: $(hdrdir)/ruby/internal/memory.h
+div.o: $(hdrdir)/ruby/internal/method.h
+div.o: $(hdrdir)/ruby/internal/module.h
+div.o: $(hdrdir)/ruby/internal/newobj.h
+div.o: $(hdrdir)/ruby/internal/rgengc.h
+div.o: $(hdrdir)/ruby/internal/scan_args.h
+div.o: $(hdrdir)/ruby/internal/special_consts.h
+div.o: $(hdrdir)/ruby/internal/static_assert.h
+div.o: $(hdrdir)/ruby/internal/stdalign.h
+div.o: $(hdrdir)/ruby/internal/stdbool.h
+div.o: $(hdrdir)/ruby/internal/symbol.h
+div.o: $(hdrdir)/ruby/internal/token_paste.h
+div.o: $(hdrdir)/ruby/internal/value.h
+div.o: $(hdrdir)/ruby/internal/value_type.h
+div.o: $(hdrdir)/ruby/internal/variable.h
+div.o: $(hdrdir)/ruby/internal/warning_push.h
+div.o: $(hdrdir)/ruby/internal/xmalloc.h
div.o: $(hdrdir)/ruby/assert.h
div.o: $(hdrdir)/ruby/backward.h
+div.o: $(hdrdir)/ruby/backward/2/assume.h
+div.o: $(hdrdir)/ruby/backward/2/attributes.h
+div.o: $(hdrdir)/ruby/backward/2/bool.h
+div.o: $(hdrdir)/ruby/backward/2/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
+div.o: $(hdrdir)/ruby/backward/2/stdalign.h
+div.o: $(hdrdir)/ruby/backward/2/stdarg.h
div.o: $(hdrdir)/ruby/defines.h
div.o: $(hdrdir)/ruby/intern.h
div.o: $(hdrdir)/ruby/missing.h
@@ -37,12 +486,162 @@ div.o: $(hdrdir)/ruby/ruby.h
div.o: $(hdrdir)/ruby/st.h
div.o: $(hdrdir)/ruby/subst.h
div.o: $(top_srcdir)/internal.h
+div.o: $(top_srcdir)/internal/bignum.h
div.o: div.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -53,8 +652,157 @@ init.o: init.c
intpack.o: $(RUBY_EXTCONF_H)
intpack.o: $(arch_hdrdir)/ruby/config.h
intpack.o: $(hdrdir)/ruby.h
+intpack.o: $(hdrdir)/ruby/internal/anyargs.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+intpack.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+intpack.o: $(hdrdir)/ruby/internal/assume.h
+intpack.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+intpack.o: $(hdrdir)/ruby/internal/attr/artificial.h
+intpack.o: $(hdrdir)/ruby/internal/attr/cold.h
+intpack.o: $(hdrdir)/ruby/internal/attr/const.h
+intpack.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+intpack.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+intpack.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+intpack.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+intpack.o: $(hdrdir)/ruby/internal/attr/error.h
+intpack.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+intpack.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+intpack.o: $(hdrdir)/ruby/internal/attr/format.h
+intpack.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+intpack.o: $(hdrdir)/ruby/internal/attr/noalias.h
+intpack.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+intpack.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+intpack.o: $(hdrdir)/ruby/internal/attr/noinline.h
+intpack.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+intpack.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+intpack.o: $(hdrdir)/ruby/internal/attr/pure.h
+intpack.o: $(hdrdir)/ruby/internal/attr/restrict.h
+intpack.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+intpack.o: $(hdrdir)/ruby/internal/attr/warning.h
+intpack.o: $(hdrdir)/ruby/internal/attr/weakref.h
+intpack.o: $(hdrdir)/ruby/internal/cast.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+intpack.o: $(hdrdir)/ruby/internal/compiler_since.h
+intpack.o: $(hdrdir)/ruby/internal/config.h
+intpack.o: $(hdrdir)/ruby/internal/constant_p.h
+intpack.o: $(hdrdir)/ruby/internal/core.h
+intpack.o: $(hdrdir)/ruby/internal/core/rarray.h
+intpack.o: $(hdrdir)/ruby/internal/core/rbasic.h
+intpack.o: $(hdrdir)/ruby/internal/core/rbignum.h
+intpack.o: $(hdrdir)/ruby/internal/core/rclass.h
+intpack.o: $(hdrdir)/ruby/internal/core/rdata.h
+intpack.o: $(hdrdir)/ruby/internal/core/rfile.h
+intpack.o: $(hdrdir)/ruby/internal/core/rhash.h
+intpack.o: $(hdrdir)/ruby/internal/core/robject.h
+intpack.o: $(hdrdir)/ruby/internal/core/rregexp.h
+intpack.o: $(hdrdir)/ruby/internal/core/rstring.h
+intpack.o: $(hdrdir)/ruby/internal/core/rstruct.h
+intpack.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+intpack.o: $(hdrdir)/ruby/internal/ctype.h
+intpack.o: $(hdrdir)/ruby/internal/dllexport.h
+intpack.o: $(hdrdir)/ruby/internal/dosish.h
+intpack.o: $(hdrdir)/ruby/internal/error.h
+intpack.o: $(hdrdir)/ruby/internal/eval.h
+intpack.o: $(hdrdir)/ruby/internal/event.h
+intpack.o: $(hdrdir)/ruby/internal/fl_type.h
+intpack.o: $(hdrdir)/ruby/internal/gc.h
+intpack.o: $(hdrdir)/ruby/internal/glob.h
+intpack.o: $(hdrdir)/ruby/internal/globals.h
+intpack.o: $(hdrdir)/ruby/internal/has/attribute.h
+intpack.o: $(hdrdir)/ruby/internal/has/builtin.h
+intpack.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+intpack.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+intpack.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+intpack.o: $(hdrdir)/ruby/internal/has/extension.h
+intpack.o: $(hdrdir)/ruby/internal/has/feature.h
+intpack.o: $(hdrdir)/ruby/internal/has/warning.h
+intpack.o: $(hdrdir)/ruby/internal/intern/array.h
+intpack.o: $(hdrdir)/ruby/internal/intern/bignum.h
+intpack.o: $(hdrdir)/ruby/internal/intern/class.h
+intpack.o: $(hdrdir)/ruby/internal/intern/compar.h
+intpack.o: $(hdrdir)/ruby/internal/intern/complex.h
+intpack.o: $(hdrdir)/ruby/internal/intern/cont.h
+intpack.o: $(hdrdir)/ruby/internal/intern/dir.h
+intpack.o: $(hdrdir)/ruby/internal/intern/enum.h
+intpack.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+intpack.o: $(hdrdir)/ruby/internal/intern/error.h
+intpack.o: $(hdrdir)/ruby/internal/intern/eval.h
+intpack.o: $(hdrdir)/ruby/internal/intern/file.h
+intpack.o: $(hdrdir)/ruby/internal/intern/gc.h
+intpack.o: $(hdrdir)/ruby/internal/intern/hash.h
+intpack.o: $(hdrdir)/ruby/internal/intern/io.h
+intpack.o: $(hdrdir)/ruby/internal/intern/load.h
+intpack.o: $(hdrdir)/ruby/internal/intern/marshal.h
+intpack.o: $(hdrdir)/ruby/internal/intern/numeric.h
+intpack.o: $(hdrdir)/ruby/internal/intern/object.h
+intpack.o: $(hdrdir)/ruby/internal/intern/parse.h
+intpack.o: $(hdrdir)/ruby/internal/intern/proc.h
+intpack.o: $(hdrdir)/ruby/internal/intern/process.h
+intpack.o: $(hdrdir)/ruby/internal/intern/random.h
+intpack.o: $(hdrdir)/ruby/internal/intern/range.h
+intpack.o: $(hdrdir)/ruby/internal/intern/rational.h
+intpack.o: $(hdrdir)/ruby/internal/intern/re.h
+intpack.o: $(hdrdir)/ruby/internal/intern/ruby.h
+intpack.o: $(hdrdir)/ruby/internal/intern/select.h
+intpack.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+intpack.o: $(hdrdir)/ruby/internal/intern/signal.h
+intpack.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+intpack.o: $(hdrdir)/ruby/internal/intern/string.h
+intpack.o: $(hdrdir)/ruby/internal/intern/struct.h
+intpack.o: $(hdrdir)/ruby/internal/intern/thread.h
+intpack.o: $(hdrdir)/ruby/internal/intern/time.h
+intpack.o: $(hdrdir)/ruby/internal/intern/variable.h
+intpack.o: $(hdrdir)/ruby/internal/intern/vm.h
+intpack.o: $(hdrdir)/ruby/internal/interpreter.h
+intpack.o: $(hdrdir)/ruby/internal/iterator.h
+intpack.o: $(hdrdir)/ruby/internal/memory.h
+intpack.o: $(hdrdir)/ruby/internal/method.h
+intpack.o: $(hdrdir)/ruby/internal/module.h
+intpack.o: $(hdrdir)/ruby/internal/newobj.h
+intpack.o: $(hdrdir)/ruby/internal/rgengc.h
+intpack.o: $(hdrdir)/ruby/internal/scan_args.h
+intpack.o: $(hdrdir)/ruby/internal/special_consts.h
+intpack.o: $(hdrdir)/ruby/internal/static_assert.h
+intpack.o: $(hdrdir)/ruby/internal/stdalign.h
+intpack.o: $(hdrdir)/ruby/internal/stdbool.h
+intpack.o: $(hdrdir)/ruby/internal/symbol.h
+intpack.o: $(hdrdir)/ruby/internal/token_paste.h
+intpack.o: $(hdrdir)/ruby/internal/value.h
+intpack.o: $(hdrdir)/ruby/internal/value_type.h
+intpack.o: $(hdrdir)/ruby/internal/variable.h
+intpack.o: $(hdrdir)/ruby/internal/warning_push.h
+intpack.o: $(hdrdir)/ruby/internal/xmalloc.h
intpack.o: $(hdrdir)/ruby/assert.h
intpack.o: $(hdrdir)/ruby/backward.h
+intpack.o: $(hdrdir)/ruby/backward/2/assume.h
+intpack.o: $(hdrdir)/ruby/backward/2/attributes.h
+intpack.o: $(hdrdir)/ruby/backward/2/bool.h
+intpack.o: $(hdrdir)/ruby/backward/2/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
+intpack.o: $(hdrdir)/ruby/backward/2/stdalign.h
+intpack.o: $(hdrdir)/ruby/backward/2/stdarg.h
intpack.o: $(hdrdir)/ruby/defines.h
intpack.o: $(hdrdir)/ruby/intern.h
intpack.o: $(hdrdir)/ruby/missing.h
@@ -62,12 +810,162 @@ intpack.o: $(hdrdir)/ruby/ruby.h
intpack.o: $(hdrdir)/ruby/st.h
intpack.o: $(hdrdir)/ruby/subst.h
intpack.o: $(top_srcdir)/internal.h
+intpack.o: $(top_srcdir)/internal/bignum.h
intpack.o: intpack.c
mul.o: $(RUBY_EXTCONF_H)
mul.o: $(arch_hdrdir)/ruby/config.h
mul.o: $(hdrdir)/ruby.h
+mul.o: $(hdrdir)/ruby/internal/anyargs.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+mul.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+mul.o: $(hdrdir)/ruby/internal/assume.h
+mul.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+mul.o: $(hdrdir)/ruby/internal/attr/artificial.h
+mul.o: $(hdrdir)/ruby/internal/attr/cold.h
+mul.o: $(hdrdir)/ruby/internal/attr/const.h
+mul.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+mul.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+mul.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+mul.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+mul.o: $(hdrdir)/ruby/internal/attr/error.h
+mul.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+mul.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+mul.o: $(hdrdir)/ruby/internal/attr/format.h
+mul.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+mul.o: $(hdrdir)/ruby/internal/attr/noalias.h
+mul.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+mul.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+mul.o: $(hdrdir)/ruby/internal/attr/noinline.h
+mul.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+mul.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+mul.o: $(hdrdir)/ruby/internal/attr/pure.h
+mul.o: $(hdrdir)/ruby/internal/attr/restrict.h
+mul.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+mul.o: $(hdrdir)/ruby/internal/attr/warning.h
+mul.o: $(hdrdir)/ruby/internal/attr/weakref.h
+mul.o: $(hdrdir)/ruby/internal/cast.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+mul.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+mul.o: $(hdrdir)/ruby/internal/compiler_since.h
+mul.o: $(hdrdir)/ruby/internal/config.h
+mul.o: $(hdrdir)/ruby/internal/constant_p.h
+mul.o: $(hdrdir)/ruby/internal/core.h
+mul.o: $(hdrdir)/ruby/internal/core/rarray.h
+mul.o: $(hdrdir)/ruby/internal/core/rbasic.h
+mul.o: $(hdrdir)/ruby/internal/core/rbignum.h
+mul.o: $(hdrdir)/ruby/internal/core/rclass.h
+mul.o: $(hdrdir)/ruby/internal/core/rdata.h
+mul.o: $(hdrdir)/ruby/internal/core/rfile.h
+mul.o: $(hdrdir)/ruby/internal/core/rhash.h
+mul.o: $(hdrdir)/ruby/internal/core/robject.h
+mul.o: $(hdrdir)/ruby/internal/core/rregexp.h
+mul.o: $(hdrdir)/ruby/internal/core/rstring.h
+mul.o: $(hdrdir)/ruby/internal/core/rstruct.h
+mul.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+mul.o: $(hdrdir)/ruby/internal/ctype.h
+mul.o: $(hdrdir)/ruby/internal/dllexport.h
+mul.o: $(hdrdir)/ruby/internal/dosish.h
+mul.o: $(hdrdir)/ruby/internal/error.h
+mul.o: $(hdrdir)/ruby/internal/eval.h
+mul.o: $(hdrdir)/ruby/internal/event.h
+mul.o: $(hdrdir)/ruby/internal/fl_type.h
+mul.o: $(hdrdir)/ruby/internal/gc.h
+mul.o: $(hdrdir)/ruby/internal/glob.h
+mul.o: $(hdrdir)/ruby/internal/globals.h
+mul.o: $(hdrdir)/ruby/internal/has/attribute.h
+mul.o: $(hdrdir)/ruby/internal/has/builtin.h
+mul.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+mul.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+mul.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+mul.o: $(hdrdir)/ruby/internal/has/extension.h
+mul.o: $(hdrdir)/ruby/internal/has/feature.h
+mul.o: $(hdrdir)/ruby/internal/has/warning.h
+mul.o: $(hdrdir)/ruby/internal/intern/array.h
+mul.o: $(hdrdir)/ruby/internal/intern/bignum.h
+mul.o: $(hdrdir)/ruby/internal/intern/class.h
+mul.o: $(hdrdir)/ruby/internal/intern/compar.h
+mul.o: $(hdrdir)/ruby/internal/intern/complex.h
+mul.o: $(hdrdir)/ruby/internal/intern/cont.h
+mul.o: $(hdrdir)/ruby/internal/intern/dir.h
+mul.o: $(hdrdir)/ruby/internal/intern/enum.h
+mul.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+mul.o: $(hdrdir)/ruby/internal/intern/error.h
+mul.o: $(hdrdir)/ruby/internal/intern/eval.h
+mul.o: $(hdrdir)/ruby/internal/intern/file.h
+mul.o: $(hdrdir)/ruby/internal/intern/gc.h
+mul.o: $(hdrdir)/ruby/internal/intern/hash.h
+mul.o: $(hdrdir)/ruby/internal/intern/io.h
+mul.o: $(hdrdir)/ruby/internal/intern/load.h
+mul.o: $(hdrdir)/ruby/internal/intern/marshal.h
+mul.o: $(hdrdir)/ruby/internal/intern/numeric.h
+mul.o: $(hdrdir)/ruby/internal/intern/object.h
+mul.o: $(hdrdir)/ruby/internal/intern/parse.h
+mul.o: $(hdrdir)/ruby/internal/intern/proc.h
+mul.o: $(hdrdir)/ruby/internal/intern/process.h
+mul.o: $(hdrdir)/ruby/internal/intern/random.h
+mul.o: $(hdrdir)/ruby/internal/intern/range.h
+mul.o: $(hdrdir)/ruby/internal/intern/rational.h
+mul.o: $(hdrdir)/ruby/internal/intern/re.h
+mul.o: $(hdrdir)/ruby/internal/intern/ruby.h
+mul.o: $(hdrdir)/ruby/internal/intern/select.h
+mul.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+mul.o: $(hdrdir)/ruby/internal/intern/signal.h
+mul.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+mul.o: $(hdrdir)/ruby/internal/intern/string.h
+mul.o: $(hdrdir)/ruby/internal/intern/struct.h
+mul.o: $(hdrdir)/ruby/internal/intern/thread.h
+mul.o: $(hdrdir)/ruby/internal/intern/time.h
+mul.o: $(hdrdir)/ruby/internal/intern/variable.h
+mul.o: $(hdrdir)/ruby/internal/intern/vm.h
+mul.o: $(hdrdir)/ruby/internal/interpreter.h
+mul.o: $(hdrdir)/ruby/internal/iterator.h
+mul.o: $(hdrdir)/ruby/internal/memory.h
+mul.o: $(hdrdir)/ruby/internal/method.h
+mul.o: $(hdrdir)/ruby/internal/module.h
+mul.o: $(hdrdir)/ruby/internal/newobj.h
+mul.o: $(hdrdir)/ruby/internal/rgengc.h
+mul.o: $(hdrdir)/ruby/internal/scan_args.h
+mul.o: $(hdrdir)/ruby/internal/special_consts.h
+mul.o: $(hdrdir)/ruby/internal/static_assert.h
+mul.o: $(hdrdir)/ruby/internal/stdalign.h
+mul.o: $(hdrdir)/ruby/internal/stdbool.h
+mul.o: $(hdrdir)/ruby/internal/symbol.h
+mul.o: $(hdrdir)/ruby/internal/token_paste.h
+mul.o: $(hdrdir)/ruby/internal/value.h
+mul.o: $(hdrdir)/ruby/internal/value_type.h
+mul.o: $(hdrdir)/ruby/internal/variable.h
+mul.o: $(hdrdir)/ruby/internal/warning_push.h
+mul.o: $(hdrdir)/ruby/internal/xmalloc.h
mul.o: $(hdrdir)/ruby/assert.h
mul.o: $(hdrdir)/ruby/backward.h
+mul.o: $(hdrdir)/ruby/backward/2/assume.h
+mul.o: $(hdrdir)/ruby/backward/2/attributes.h
+mul.o: $(hdrdir)/ruby/backward/2/bool.h
+mul.o: $(hdrdir)/ruby/backward/2/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
+mul.o: $(hdrdir)/ruby/backward/2/stdalign.h
+mul.o: $(hdrdir)/ruby/backward/2/stdarg.h
mul.o: $(hdrdir)/ruby/defines.h
mul.o: $(hdrdir)/ruby/intern.h
mul.o: $(hdrdir)/ruby/missing.h
@@ -75,12 +973,162 @@ mul.o: $(hdrdir)/ruby/ruby.h
mul.o: $(hdrdir)/ruby/st.h
mul.o: $(hdrdir)/ruby/subst.h
mul.o: $(top_srcdir)/internal.h
+mul.o: $(top_srcdir)/internal/bignum.h
mul.o: mul.c
str2big.o: $(RUBY_EXTCONF_H)
str2big.o: $(arch_hdrdir)/ruby/config.h
str2big.o: $(hdrdir)/ruby.h
+str2big.o: $(hdrdir)/ruby/internal/anyargs.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+str2big.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+str2big.o: $(hdrdir)/ruby/internal/assume.h
+str2big.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+str2big.o: $(hdrdir)/ruby/internal/attr/artificial.h
+str2big.o: $(hdrdir)/ruby/internal/attr/cold.h
+str2big.o: $(hdrdir)/ruby/internal/attr/const.h
+str2big.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+str2big.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+str2big.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+str2big.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+str2big.o: $(hdrdir)/ruby/internal/attr/error.h
+str2big.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+str2big.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+str2big.o: $(hdrdir)/ruby/internal/attr/format.h
+str2big.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+str2big.o: $(hdrdir)/ruby/internal/attr/noalias.h
+str2big.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+str2big.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+str2big.o: $(hdrdir)/ruby/internal/attr/noinline.h
+str2big.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+str2big.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+str2big.o: $(hdrdir)/ruby/internal/attr/pure.h
+str2big.o: $(hdrdir)/ruby/internal/attr/restrict.h
+str2big.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+str2big.o: $(hdrdir)/ruby/internal/attr/warning.h
+str2big.o: $(hdrdir)/ruby/internal/attr/weakref.h
+str2big.o: $(hdrdir)/ruby/internal/cast.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+str2big.o: $(hdrdir)/ruby/internal/compiler_since.h
+str2big.o: $(hdrdir)/ruby/internal/config.h
+str2big.o: $(hdrdir)/ruby/internal/constant_p.h
+str2big.o: $(hdrdir)/ruby/internal/core.h
+str2big.o: $(hdrdir)/ruby/internal/core/rarray.h
+str2big.o: $(hdrdir)/ruby/internal/core/rbasic.h
+str2big.o: $(hdrdir)/ruby/internal/core/rbignum.h
+str2big.o: $(hdrdir)/ruby/internal/core/rclass.h
+str2big.o: $(hdrdir)/ruby/internal/core/rdata.h
+str2big.o: $(hdrdir)/ruby/internal/core/rfile.h
+str2big.o: $(hdrdir)/ruby/internal/core/rhash.h
+str2big.o: $(hdrdir)/ruby/internal/core/robject.h
+str2big.o: $(hdrdir)/ruby/internal/core/rregexp.h
+str2big.o: $(hdrdir)/ruby/internal/core/rstring.h
+str2big.o: $(hdrdir)/ruby/internal/core/rstruct.h
+str2big.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+str2big.o: $(hdrdir)/ruby/internal/ctype.h
+str2big.o: $(hdrdir)/ruby/internal/dllexport.h
+str2big.o: $(hdrdir)/ruby/internal/dosish.h
+str2big.o: $(hdrdir)/ruby/internal/error.h
+str2big.o: $(hdrdir)/ruby/internal/eval.h
+str2big.o: $(hdrdir)/ruby/internal/event.h
+str2big.o: $(hdrdir)/ruby/internal/fl_type.h
+str2big.o: $(hdrdir)/ruby/internal/gc.h
+str2big.o: $(hdrdir)/ruby/internal/glob.h
+str2big.o: $(hdrdir)/ruby/internal/globals.h
+str2big.o: $(hdrdir)/ruby/internal/has/attribute.h
+str2big.o: $(hdrdir)/ruby/internal/has/builtin.h
+str2big.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+str2big.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+str2big.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+str2big.o: $(hdrdir)/ruby/internal/has/extension.h
+str2big.o: $(hdrdir)/ruby/internal/has/feature.h
+str2big.o: $(hdrdir)/ruby/internal/has/warning.h
+str2big.o: $(hdrdir)/ruby/internal/intern/array.h
+str2big.o: $(hdrdir)/ruby/internal/intern/bignum.h
+str2big.o: $(hdrdir)/ruby/internal/intern/class.h
+str2big.o: $(hdrdir)/ruby/internal/intern/compar.h
+str2big.o: $(hdrdir)/ruby/internal/intern/complex.h
+str2big.o: $(hdrdir)/ruby/internal/intern/cont.h
+str2big.o: $(hdrdir)/ruby/internal/intern/dir.h
+str2big.o: $(hdrdir)/ruby/internal/intern/enum.h
+str2big.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+str2big.o: $(hdrdir)/ruby/internal/intern/error.h
+str2big.o: $(hdrdir)/ruby/internal/intern/eval.h
+str2big.o: $(hdrdir)/ruby/internal/intern/file.h
+str2big.o: $(hdrdir)/ruby/internal/intern/gc.h
+str2big.o: $(hdrdir)/ruby/internal/intern/hash.h
+str2big.o: $(hdrdir)/ruby/internal/intern/io.h
+str2big.o: $(hdrdir)/ruby/internal/intern/load.h
+str2big.o: $(hdrdir)/ruby/internal/intern/marshal.h
+str2big.o: $(hdrdir)/ruby/internal/intern/numeric.h
+str2big.o: $(hdrdir)/ruby/internal/intern/object.h
+str2big.o: $(hdrdir)/ruby/internal/intern/parse.h
+str2big.o: $(hdrdir)/ruby/internal/intern/proc.h
+str2big.o: $(hdrdir)/ruby/internal/intern/process.h
+str2big.o: $(hdrdir)/ruby/internal/intern/random.h
+str2big.o: $(hdrdir)/ruby/internal/intern/range.h
+str2big.o: $(hdrdir)/ruby/internal/intern/rational.h
+str2big.o: $(hdrdir)/ruby/internal/intern/re.h
+str2big.o: $(hdrdir)/ruby/internal/intern/ruby.h
+str2big.o: $(hdrdir)/ruby/internal/intern/select.h
+str2big.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+str2big.o: $(hdrdir)/ruby/internal/intern/signal.h
+str2big.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+str2big.o: $(hdrdir)/ruby/internal/intern/string.h
+str2big.o: $(hdrdir)/ruby/internal/intern/struct.h
+str2big.o: $(hdrdir)/ruby/internal/intern/thread.h
+str2big.o: $(hdrdir)/ruby/internal/intern/time.h
+str2big.o: $(hdrdir)/ruby/internal/intern/variable.h
+str2big.o: $(hdrdir)/ruby/internal/intern/vm.h
+str2big.o: $(hdrdir)/ruby/internal/interpreter.h
+str2big.o: $(hdrdir)/ruby/internal/iterator.h
+str2big.o: $(hdrdir)/ruby/internal/memory.h
+str2big.o: $(hdrdir)/ruby/internal/method.h
+str2big.o: $(hdrdir)/ruby/internal/module.h
+str2big.o: $(hdrdir)/ruby/internal/newobj.h
+str2big.o: $(hdrdir)/ruby/internal/rgengc.h
+str2big.o: $(hdrdir)/ruby/internal/scan_args.h
+str2big.o: $(hdrdir)/ruby/internal/special_consts.h
+str2big.o: $(hdrdir)/ruby/internal/static_assert.h
+str2big.o: $(hdrdir)/ruby/internal/stdalign.h
+str2big.o: $(hdrdir)/ruby/internal/stdbool.h
+str2big.o: $(hdrdir)/ruby/internal/symbol.h
+str2big.o: $(hdrdir)/ruby/internal/token_paste.h
+str2big.o: $(hdrdir)/ruby/internal/value.h
+str2big.o: $(hdrdir)/ruby/internal/value_type.h
+str2big.o: $(hdrdir)/ruby/internal/variable.h
+str2big.o: $(hdrdir)/ruby/internal/warning_push.h
+str2big.o: $(hdrdir)/ruby/internal/xmalloc.h
str2big.o: $(hdrdir)/ruby/assert.h
str2big.o: $(hdrdir)/ruby/backward.h
+str2big.o: $(hdrdir)/ruby/backward/2/assume.h
+str2big.o: $(hdrdir)/ruby/backward/2/attributes.h
+str2big.o: $(hdrdir)/ruby/backward/2/bool.h
+str2big.o: $(hdrdir)/ruby/backward/2/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
+str2big.o: $(hdrdir)/ruby/backward/2/stdalign.h
+str2big.o: $(hdrdir)/ruby/backward/2/stdarg.h
str2big.o: $(hdrdir)/ruby/defines.h
str2big.o: $(hdrdir)/ruby/intern.h
str2big.o: $(hdrdir)/ruby/missing.h
@@ -88,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.h
+str2big.o: $(top_srcdir)/internal/bignum.h
str2big.o: str2big.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/bignum/div.c b/ext/-test-/bignum/div.c
index a1db21dc30..2be0d2d62a 100644
--- a/ext/-test-/bignum/div.c
+++ b/ext/-test-/bignum/div.c
@@ -1,4 +1,4 @@
-#include "internal.h"
+#include "internal/bignum.h"
static VALUE
big(VALUE x)
diff --git a/ext/-test-/bignum/intpack.c b/ext/-test-/bignum/intpack.c
index 2d19442cf2..698362f96f 100644
--- a/ext/-test-/bignum/intpack.c
+++ b/ext/-test-/bignum/intpack.c
@@ -1,4 +1,4 @@
-#include "internal.h"
+#include "internal/bignum.h"
static VALUE
rb_integer_pack_raw_m(VALUE val, VALUE buf, VALUE numwords_arg, VALUE wordsize_arg, VALUE nails, VALUE flags)
diff --git a/ext/-test-/bignum/mul.c b/ext/-test-/bignum/mul.c
index b922f34437..1b6eb911bd 100644
--- a/ext/-test-/bignum/mul.c
+++ b/ext/-test-/bignum/mul.c
@@ -1,4 +1,4 @@
-#include "internal.h"
+#include "internal/bignum.h"
static VALUE
big(VALUE x)
diff --git a/ext/-test-/bignum/str2big.c b/ext/-test-/bignum/str2big.c
index bc79ef0329..7dd2da9a07 100644
--- a/ext/-test-/bignum/str2big.c
+++ b/ext/-test-/bignum/str2big.c
@@ -1,4 +1,4 @@
-#include "internal.h"
+#include "internal/bignum.h"
static VALUE
str2big_poweroftwo(VALUE str, VALUE vbase, VALUE badcheck)
diff --git a/ext/-test-/bug-14834/depend b/ext/-test-/bug-14834/depend
index 5206f995be..dce5a8e5c5 100644
--- a/ext/-test-/bug-14834/depend
+++ b/ext/-test-/bug-14834/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
bug-14384.o: $(RUBY_EXTCONF_H)
bug-14384.o: $(arch_hdrdir)/ruby/config.h
+bug-14384.o: $(hdrdir)/ruby/internal/anyargs.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug-14384.o: $(hdrdir)/ruby/internal/assume.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/const.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/error.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/format.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug-14384.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug-14384.o: $(hdrdir)/ruby/internal/cast.h
+bug-14384.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug-14384.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug-14384.o: $(hdrdir)/ruby/internal/config.h
+bug-14384.o: $(hdrdir)/ruby/internal/constant_p.h
+bug-14384.o: $(hdrdir)/ruby/internal/core.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/robject.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug-14384.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug-14384.o: $(hdrdir)/ruby/internal/ctype.h
+bug-14384.o: $(hdrdir)/ruby/internal/dllexport.h
+bug-14384.o: $(hdrdir)/ruby/internal/dosish.h
+bug-14384.o: $(hdrdir)/ruby/internal/error.h
+bug-14384.o: $(hdrdir)/ruby/internal/eval.h
+bug-14384.o: $(hdrdir)/ruby/internal/event.h
+bug-14384.o: $(hdrdir)/ruby/internal/fl_type.h
+bug-14384.o: $(hdrdir)/ruby/internal/gc.h
+bug-14384.o: $(hdrdir)/ruby/internal/glob.h
+bug-14384.o: $(hdrdir)/ruby/internal/globals.h
+bug-14384.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug-14384.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug-14384.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug-14384.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug-14384.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug-14384.o: $(hdrdir)/ruby/internal/has/extension.h
+bug-14384.o: $(hdrdir)/ruby/internal/has/feature.h
+bug-14384.o: $(hdrdir)/ruby/internal/has/warning.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/array.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/class.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/error.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/file.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/gc.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/io.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/load.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/object.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/process.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/random.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/range.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/re.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/select.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/string.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/time.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug-14384.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug-14384.o: $(hdrdir)/ruby/internal/interpreter.h
+bug-14384.o: $(hdrdir)/ruby/internal/iterator.h
+bug-14384.o: $(hdrdir)/ruby/internal/memory.h
+bug-14384.o: $(hdrdir)/ruby/internal/method.h
+bug-14384.o: $(hdrdir)/ruby/internal/module.h
+bug-14384.o: $(hdrdir)/ruby/internal/newobj.h
+bug-14384.o: $(hdrdir)/ruby/internal/rgengc.h
+bug-14384.o: $(hdrdir)/ruby/internal/scan_args.h
+bug-14384.o: $(hdrdir)/ruby/internal/special_consts.h
+bug-14384.o: $(hdrdir)/ruby/internal/static_assert.h
+bug-14384.o: $(hdrdir)/ruby/internal/stdalign.h
+bug-14384.o: $(hdrdir)/ruby/internal/stdbool.h
+bug-14384.o: $(hdrdir)/ruby/internal/symbol.h
+bug-14384.o: $(hdrdir)/ruby/internal/token_paste.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/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/gcc_version_since.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
diff --git a/ext/-test-/bug-3571/depend b/ext/-test-/bug-3571/depend
index 74911f0af4..a21935558d 100644
--- a/ext/-test-/bug-3571/depend
+++ b/ext/-test-/bug-3571/depend
@@ -2,8 +2,157 @@
bug.o: $(RUBY_EXTCONF_H)
bug.o: $(arch_hdrdir)/ruby/config.h
bug.o: $(hdrdir)/ruby.h
+bug.o: $(hdrdir)/ruby/internal/anyargs.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug.o: $(hdrdir)/ruby/internal/assume.h
+bug.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug.o: $(hdrdir)/ruby/internal/attr/const.h
+bug.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug.o: $(hdrdir)/ruby/internal/attr/error.h
+bug.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/format.h
+bug.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug.o: $(hdrdir)/ruby/internal/cast.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug.o: $(hdrdir)/ruby/internal/config.h
+bug.o: $(hdrdir)/ruby/internal/constant_p.h
+bug.o: $(hdrdir)/ruby/internal/core.h
+bug.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug.o: $(hdrdir)/ruby/internal/core/robject.h
+bug.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug.o: $(hdrdir)/ruby/internal/ctype.h
+bug.o: $(hdrdir)/ruby/internal/dllexport.h
+bug.o: $(hdrdir)/ruby/internal/dosish.h
+bug.o: $(hdrdir)/ruby/internal/error.h
+bug.o: $(hdrdir)/ruby/internal/eval.h
+bug.o: $(hdrdir)/ruby/internal/event.h
+bug.o: $(hdrdir)/ruby/internal/fl_type.h
+bug.o: $(hdrdir)/ruby/internal/gc.h
+bug.o: $(hdrdir)/ruby/internal/glob.h
+bug.o: $(hdrdir)/ruby/internal/globals.h
+bug.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/extension.h
+bug.o: $(hdrdir)/ruby/internal/has/feature.h
+bug.o: $(hdrdir)/ruby/internal/has/warning.h
+bug.o: $(hdrdir)/ruby/internal/intern/array.h
+bug.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug.o: $(hdrdir)/ruby/internal/intern/class.h
+bug.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug.o: $(hdrdir)/ruby/internal/intern/error.h
+bug.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug.o: $(hdrdir)/ruby/internal/intern/file.h
+bug.o: $(hdrdir)/ruby/internal/intern/gc.h
+bug.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug.o: $(hdrdir)/ruby/internal/intern/io.h
+bug.o: $(hdrdir)/ruby/internal/intern/load.h
+bug.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug.o: $(hdrdir)/ruby/internal/intern/object.h
+bug.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug.o: $(hdrdir)/ruby/internal/intern/process.h
+bug.o: $(hdrdir)/ruby/internal/intern/random.h
+bug.o: $(hdrdir)/ruby/internal/intern/range.h
+bug.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug.o: $(hdrdir)/ruby/internal/intern/re.h
+bug.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug.o: $(hdrdir)/ruby/internal/intern/select.h
+bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug.o: $(hdrdir)/ruby/internal/intern/string.h
+bug.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug.o: $(hdrdir)/ruby/internal/intern/time.h
+bug.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug.o: $(hdrdir)/ruby/internal/interpreter.h
+bug.o: $(hdrdir)/ruby/internal/iterator.h
+bug.o: $(hdrdir)/ruby/internal/memory.h
+bug.o: $(hdrdir)/ruby/internal/method.h
+bug.o: $(hdrdir)/ruby/internal/module.h
+bug.o: $(hdrdir)/ruby/internal/newobj.h
+bug.o: $(hdrdir)/ruby/internal/rgengc.h
+bug.o: $(hdrdir)/ruby/internal/scan_args.h
+bug.o: $(hdrdir)/ruby/internal/special_consts.h
+bug.o: $(hdrdir)/ruby/internal/static_assert.h
+bug.o: $(hdrdir)/ruby/internal/stdalign.h
+bug.o: $(hdrdir)/ruby/internal/stdbool.h
+bug.o: $(hdrdir)/ruby/internal/symbol.h
+bug.o: $(hdrdir)/ruby/internal/token_paste.h
+bug.o: $(hdrdir)/ruby/internal/value.h
+bug.o: $(hdrdir)/ruby/internal/value_type.h
+bug.o: $(hdrdir)/ruby/internal/variable.h
+bug.o: $(hdrdir)/ruby/internal/warning_push.h
+bug.o: $(hdrdir)/ruby/internal/xmalloc.h
bug.o: $(hdrdir)/ruby/assert.h
bug.o: $(hdrdir)/ruby/backward.h
+bug.o: $(hdrdir)/ruby/backward/2/assume.h
+bug.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug.o: $(hdrdir)/ruby/backward/2/bool.h
+bug.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+bug.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug.o: $(hdrdir)/ruby/backward/2/limits.h
+bug.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug.o: $(hdrdir)/ruby/backward/2/stdarg.h
bug.o: $(hdrdir)/ruby/defines.h
bug.o: $(hdrdir)/ruby/intern.h
bug.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/bug-5832/depend b/ext/-test-/bug-5832/depend
index 74911f0af4..a21935558d 100644
--- a/ext/-test-/bug-5832/depend
+++ b/ext/-test-/bug-5832/depend
@@ -2,8 +2,157 @@
bug.o: $(RUBY_EXTCONF_H)
bug.o: $(arch_hdrdir)/ruby/config.h
bug.o: $(hdrdir)/ruby.h
+bug.o: $(hdrdir)/ruby/internal/anyargs.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug.o: $(hdrdir)/ruby/internal/assume.h
+bug.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug.o: $(hdrdir)/ruby/internal/attr/const.h
+bug.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug.o: $(hdrdir)/ruby/internal/attr/error.h
+bug.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/format.h
+bug.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug.o: $(hdrdir)/ruby/internal/cast.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug.o: $(hdrdir)/ruby/internal/config.h
+bug.o: $(hdrdir)/ruby/internal/constant_p.h
+bug.o: $(hdrdir)/ruby/internal/core.h
+bug.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug.o: $(hdrdir)/ruby/internal/core/robject.h
+bug.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug.o: $(hdrdir)/ruby/internal/ctype.h
+bug.o: $(hdrdir)/ruby/internal/dllexport.h
+bug.o: $(hdrdir)/ruby/internal/dosish.h
+bug.o: $(hdrdir)/ruby/internal/error.h
+bug.o: $(hdrdir)/ruby/internal/eval.h
+bug.o: $(hdrdir)/ruby/internal/event.h
+bug.o: $(hdrdir)/ruby/internal/fl_type.h
+bug.o: $(hdrdir)/ruby/internal/gc.h
+bug.o: $(hdrdir)/ruby/internal/glob.h
+bug.o: $(hdrdir)/ruby/internal/globals.h
+bug.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/extension.h
+bug.o: $(hdrdir)/ruby/internal/has/feature.h
+bug.o: $(hdrdir)/ruby/internal/has/warning.h
+bug.o: $(hdrdir)/ruby/internal/intern/array.h
+bug.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug.o: $(hdrdir)/ruby/internal/intern/class.h
+bug.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug.o: $(hdrdir)/ruby/internal/intern/error.h
+bug.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug.o: $(hdrdir)/ruby/internal/intern/file.h
+bug.o: $(hdrdir)/ruby/internal/intern/gc.h
+bug.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug.o: $(hdrdir)/ruby/internal/intern/io.h
+bug.o: $(hdrdir)/ruby/internal/intern/load.h
+bug.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug.o: $(hdrdir)/ruby/internal/intern/object.h
+bug.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug.o: $(hdrdir)/ruby/internal/intern/process.h
+bug.o: $(hdrdir)/ruby/internal/intern/random.h
+bug.o: $(hdrdir)/ruby/internal/intern/range.h
+bug.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug.o: $(hdrdir)/ruby/internal/intern/re.h
+bug.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug.o: $(hdrdir)/ruby/internal/intern/select.h
+bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug.o: $(hdrdir)/ruby/internal/intern/string.h
+bug.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug.o: $(hdrdir)/ruby/internal/intern/time.h
+bug.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug.o: $(hdrdir)/ruby/internal/interpreter.h
+bug.o: $(hdrdir)/ruby/internal/iterator.h
+bug.o: $(hdrdir)/ruby/internal/memory.h
+bug.o: $(hdrdir)/ruby/internal/method.h
+bug.o: $(hdrdir)/ruby/internal/module.h
+bug.o: $(hdrdir)/ruby/internal/newobj.h
+bug.o: $(hdrdir)/ruby/internal/rgengc.h
+bug.o: $(hdrdir)/ruby/internal/scan_args.h
+bug.o: $(hdrdir)/ruby/internal/special_consts.h
+bug.o: $(hdrdir)/ruby/internal/static_assert.h
+bug.o: $(hdrdir)/ruby/internal/stdalign.h
+bug.o: $(hdrdir)/ruby/internal/stdbool.h
+bug.o: $(hdrdir)/ruby/internal/symbol.h
+bug.o: $(hdrdir)/ruby/internal/token_paste.h
+bug.o: $(hdrdir)/ruby/internal/value.h
+bug.o: $(hdrdir)/ruby/internal/value_type.h
+bug.o: $(hdrdir)/ruby/internal/variable.h
+bug.o: $(hdrdir)/ruby/internal/warning_push.h
+bug.o: $(hdrdir)/ruby/internal/xmalloc.h
bug.o: $(hdrdir)/ruby/assert.h
bug.o: $(hdrdir)/ruby/backward.h
+bug.o: $(hdrdir)/ruby/backward/2/assume.h
+bug.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug.o: $(hdrdir)/ruby/backward/2/bool.h
+bug.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+bug.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug.o: $(hdrdir)/ruby/backward/2/limits.h
+bug.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug.o: $(hdrdir)/ruby/backward/2/stdarg.h
bug.o: $(hdrdir)/ruby/defines.h
bug.o: $(hdrdir)/ruby/intern.h
bug.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/bug_reporter/depend b/ext/-test-/bug_reporter/depend
index 62bac03566..f49b6147e6 100644
--- a/ext/-test-/bug_reporter/depend
+++ b/ext/-test-/bug_reporter/depend
@@ -2,8 +2,157 @@
bug_reporter.o: $(RUBY_EXTCONF_H)
bug_reporter.o: $(arch_hdrdir)/ruby/config.h
bug_reporter.o: $(hdrdir)/ruby.h
+bug_reporter.o: $(hdrdir)/ruby/internal/anyargs.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug_reporter.o: $(hdrdir)/ruby/internal/assume.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/const.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/error.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/format.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug_reporter.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug_reporter.o: $(hdrdir)/ruby/internal/cast.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug_reporter.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug_reporter.o: $(hdrdir)/ruby/internal/config.h
+bug_reporter.o: $(hdrdir)/ruby/internal/constant_p.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/robject.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug_reporter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug_reporter.o: $(hdrdir)/ruby/internal/ctype.h
+bug_reporter.o: $(hdrdir)/ruby/internal/dllexport.h
+bug_reporter.o: $(hdrdir)/ruby/internal/dosish.h
+bug_reporter.o: $(hdrdir)/ruby/internal/error.h
+bug_reporter.o: $(hdrdir)/ruby/internal/eval.h
+bug_reporter.o: $(hdrdir)/ruby/internal/event.h
+bug_reporter.o: $(hdrdir)/ruby/internal/fl_type.h
+bug_reporter.o: $(hdrdir)/ruby/internal/gc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/glob.h
+bug_reporter.o: $(hdrdir)/ruby/internal/globals.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/extension.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/feature.h
+bug_reporter.o: $(hdrdir)/ruby/internal/has/warning.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/array.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/class.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/error.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/file.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/gc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/io.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/load.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/object.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/process.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/random.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/range.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/re.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/select.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/string.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/time.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug_reporter.o: $(hdrdir)/ruby/internal/interpreter.h
+bug_reporter.o: $(hdrdir)/ruby/internal/iterator.h
+bug_reporter.o: $(hdrdir)/ruby/internal/memory.h
+bug_reporter.o: $(hdrdir)/ruby/internal/method.h
+bug_reporter.o: $(hdrdir)/ruby/internal/module.h
+bug_reporter.o: $(hdrdir)/ruby/internal/newobj.h
+bug_reporter.o: $(hdrdir)/ruby/internal/rgengc.h
+bug_reporter.o: $(hdrdir)/ruby/internal/scan_args.h
+bug_reporter.o: $(hdrdir)/ruby/internal/special_consts.h
+bug_reporter.o: $(hdrdir)/ruby/internal/static_assert.h
+bug_reporter.o: $(hdrdir)/ruby/internal/stdalign.h
+bug_reporter.o: $(hdrdir)/ruby/internal/stdbool.h
+bug_reporter.o: $(hdrdir)/ruby/internal/symbol.h
+bug_reporter.o: $(hdrdir)/ruby/internal/token_paste.h
+bug_reporter.o: $(hdrdir)/ruby/internal/value.h
+bug_reporter.o: $(hdrdir)/ruby/internal/value_type.h
+bug_reporter.o: $(hdrdir)/ruby/internal/variable.h
+bug_reporter.o: $(hdrdir)/ruby/internal/warning_push.h
+bug_reporter.o: $(hdrdir)/ruby/internal/xmalloc.h
bug_reporter.o: $(hdrdir)/ruby/assert.h
bug_reporter.o: $(hdrdir)/ruby/backward.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/assume.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/bool.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/limits.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug_reporter.o: $(hdrdir)/ruby/backward/2/stdarg.h
bug_reporter.o: $(hdrdir)/ruby/defines.h
bug_reporter.o: $(hdrdir)/ruby/intern.h
bug_reporter.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/class/depend b/ext/-test-/class/depend
index 451256cc75..95199c5cf4 100644
--- a/ext/-test-/class/depend
+++ b/ext/-test-/class/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
class2name.o: $(RUBY_EXTCONF_H)
class2name.o: $(arch_hdrdir)/ruby/config.h
+class2name.o: $(hdrdir)/ruby/internal/anyargs.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+class2name.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+class2name.o: $(hdrdir)/ruby/internal/assume.h
+class2name.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+class2name.o: $(hdrdir)/ruby/internal/attr/artificial.h
+class2name.o: $(hdrdir)/ruby/internal/attr/cold.h
+class2name.o: $(hdrdir)/ruby/internal/attr/const.h
+class2name.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+class2name.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+class2name.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+class2name.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+class2name.o: $(hdrdir)/ruby/internal/attr/error.h
+class2name.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+class2name.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+class2name.o: $(hdrdir)/ruby/internal/attr/format.h
+class2name.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+class2name.o: $(hdrdir)/ruby/internal/attr/noalias.h
+class2name.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+class2name.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+class2name.o: $(hdrdir)/ruby/internal/attr/noinline.h
+class2name.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+class2name.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+class2name.o: $(hdrdir)/ruby/internal/attr/pure.h
+class2name.o: $(hdrdir)/ruby/internal/attr/restrict.h
+class2name.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+class2name.o: $(hdrdir)/ruby/internal/attr/warning.h
+class2name.o: $(hdrdir)/ruby/internal/attr/weakref.h
+class2name.o: $(hdrdir)/ruby/internal/cast.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+class2name.o: $(hdrdir)/ruby/internal/compiler_since.h
+class2name.o: $(hdrdir)/ruby/internal/config.h
+class2name.o: $(hdrdir)/ruby/internal/constant_p.h
+class2name.o: $(hdrdir)/ruby/internal/core.h
+class2name.o: $(hdrdir)/ruby/internal/core/rarray.h
+class2name.o: $(hdrdir)/ruby/internal/core/rbasic.h
+class2name.o: $(hdrdir)/ruby/internal/core/rbignum.h
+class2name.o: $(hdrdir)/ruby/internal/core/rclass.h
+class2name.o: $(hdrdir)/ruby/internal/core/rdata.h
+class2name.o: $(hdrdir)/ruby/internal/core/rfile.h
+class2name.o: $(hdrdir)/ruby/internal/core/rhash.h
+class2name.o: $(hdrdir)/ruby/internal/core/robject.h
+class2name.o: $(hdrdir)/ruby/internal/core/rregexp.h
+class2name.o: $(hdrdir)/ruby/internal/core/rstring.h
+class2name.o: $(hdrdir)/ruby/internal/core/rstruct.h
+class2name.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+class2name.o: $(hdrdir)/ruby/internal/ctype.h
+class2name.o: $(hdrdir)/ruby/internal/dllexport.h
+class2name.o: $(hdrdir)/ruby/internal/dosish.h
+class2name.o: $(hdrdir)/ruby/internal/error.h
+class2name.o: $(hdrdir)/ruby/internal/eval.h
+class2name.o: $(hdrdir)/ruby/internal/event.h
+class2name.o: $(hdrdir)/ruby/internal/fl_type.h
+class2name.o: $(hdrdir)/ruby/internal/gc.h
+class2name.o: $(hdrdir)/ruby/internal/glob.h
+class2name.o: $(hdrdir)/ruby/internal/globals.h
+class2name.o: $(hdrdir)/ruby/internal/has/attribute.h
+class2name.o: $(hdrdir)/ruby/internal/has/builtin.h
+class2name.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+class2name.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+class2name.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+class2name.o: $(hdrdir)/ruby/internal/has/extension.h
+class2name.o: $(hdrdir)/ruby/internal/has/feature.h
+class2name.o: $(hdrdir)/ruby/internal/has/warning.h
+class2name.o: $(hdrdir)/ruby/internal/intern/array.h
+class2name.o: $(hdrdir)/ruby/internal/intern/bignum.h
+class2name.o: $(hdrdir)/ruby/internal/intern/class.h
+class2name.o: $(hdrdir)/ruby/internal/intern/compar.h
+class2name.o: $(hdrdir)/ruby/internal/intern/complex.h
+class2name.o: $(hdrdir)/ruby/internal/intern/cont.h
+class2name.o: $(hdrdir)/ruby/internal/intern/dir.h
+class2name.o: $(hdrdir)/ruby/internal/intern/enum.h
+class2name.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+class2name.o: $(hdrdir)/ruby/internal/intern/error.h
+class2name.o: $(hdrdir)/ruby/internal/intern/eval.h
+class2name.o: $(hdrdir)/ruby/internal/intern/file.h
+class2name.o: $(hdrdir)/ruby/internal/intern/gc.h
+class2name.o: $(hdrdir)/ruby/internal/intern/hash.h
+class2name.o: $(hdrdir)/ruby/internal/intern/io.h
+class2name.o: $(hdrdir)/ruby/internal/intern/load.h
+class2name.o: $(hdrdir)/ruby/internal/intern/marshal.h
+class2name.o: $(hdrdir)/ruby/internal/intern/numeric.h
+class2name.o: $(hdrdir)/ruby/internal/intern/object.h
+class2name.o: $(hdrdir)/ruby/internal/intern/parse.h
+class2name.o: $(hdrdir)/ruby/internal/intern/proc.h
+class2name.o: $(hdrdir)/ruby/internal/intern/process.h
+class2name.o: $(hdrdir)/ruby/internal/intern/random.h
+class2name.o: $(hdrdir)/ruby/internal/intern/range.h
+class2name.o: $(hdrdir)/ruby/internal/intern/rational.h
+class2name.o: $(hdrdir)/ruby/internal/intern/re.h
+class2name.o: $(hdrdir)/ruby/internal/intern/ruby.h
+class2name.o: $(hdrdir)/ruby/internal/intern/select.h
+class2name.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+class2name.o: $(hdrdir)/ruby/internal/intern/signal.h
+class2name.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+class2name.o: $(hdrdir)/ruby/internal/intern/string.h
+class2name.o: $(hdrdir)/ruby/internal/intern/struct.h
+class2name.o: $(hdrdir)/ruby/internal/intern/thread.h
+class2name.o: $(hdrdir)/ruby/internal/intern/time.h
+class2name.o: $(hdrdir)/ruby/internal/intern/variable.h
+class2name.o: $(hdrdir)/ruby/internal/intern/vm.h
+class2name.o: $(hdrdir)/ruby/internal/interpreter.h
+class2name.o: $(hdrdir)/ruby/internal/iterator.h
+class2name.o: $(hdrdir)/ruby/internal/memory.h
+class2name.o: $(hdrdir)/ruby/internal/method.h
+class2name.o: $(hdrdir)/ruby/internal/module.h
+class2name.o: $(hdrdir)/ruby/internal/newobj.h
+class2name.o: $(hdrdir)/ruby/internal/rgengc.h
+class2name.o: $(hdrdir)/ruby/internal/scan_args.h
+class2name.o: $(hdrdir)/ruby/internal/special_consts.h
+class2name.o: $(hdrdir)/ruby/internal/static_assert.h
+class2name.o: $(hdrdir)/ruby/internal/stdalign.h
+class2name.o: $(hdrdir)/ruby/internal/stdbool.h
+class2name.o: $(hdrdir)/ruby/internal/symbol.h
+class2name.o: $(hdrdir)/ruby/internal/token_paste.h
+class2name.o: $(hdrdir)/ruby/internal/value.h
+class2name.o: $(hdrdir)/ruby/internal/value_type.h
+class2name.o: $(hdrdir)/ruby/internal/variable.h
+class2name.o: $(hdrdir)/ruby/internal/warning_push.h
+class2name.o: $(hdrdir)/ruby/internal/xmalloc.h
class2name.o: $(hdrdir)/ruby/assert.h
class2name.o: $(hdrdir)/ruby/backward.h
+class2name.o: $(hdrdir)/ruby/backward/2/assume.h
+class2name.o: $(hdrdir)/ruby/backward/2/attributes.h
+class2name.o: $(hdrdir)/ruby/backward/2/bool.h
+class2name.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+class2name.o: $(hdrdir)/ruby/backward/2/inttypes.h
+class2name.o: $(hdrdir)/ruby/backward/2/limits.h
+class2name.o: $(hdrdir)/ruby/backward/2/long_long.h
+class2name.o: $(hdrdir)/ruby/backward/2/stdalign.h
+class2name.o: $(hdrdir)/ruby/backward/2/stdarg.h
class2name.o: $(hdrdir)/ruby/defines.h
class2name.o: $(hdrdir)/ruby/intern.h
class2name.o: $(hdrdir)/ruby/missing.h
@@ -13,8 +162,157 @@ class2name.o: class2name.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/cxxanyargs/cxxanyargs.cpp b/ext/-test-/cxxanyargs/cxxanyargs.cpp
index efe35fa359..eded13e2ee 100644
--- a/ext/-test-/cxxanyargs/cxxanyargs.cpp
+++ b/ext/-test-/cxxanyargs/cxxanyargs.cpp
@@ -5,12 +5,18 @@
#elif defined(_MSC_VER)
#pragma warning(disable : 4996)
+#elif defined(__INTEL_COMPILER)
+#pragma warning(disable : 1786)
+
#elif defined(__clang__)
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#elif defined(__SUNPRO_CC)
+#pragma error_messages (off,symdeprecated)
+
#else
// :FIXME: improve here for your compiler.
@@ -36,6 +42,18 @@ namespace test_rb_define_virtual_variable {
RUBY_METHOD_FUNC(getter),
reinterpret_cast<void(*)(ANYARGS)>(setter)); // old
rb_define_virtual_variable("test", getter, setter); // new
+
+#ifdef HAVE_NULLPTR
+ rb_define_virtual_variable("test", nullptr, reinterpret_cast<void(*)(ANYARGS)>(setter));
+ rb_define_virtual_variable("test", nullptr, setter);
+
+ rb_define_virtual_variable("test", RUBY_METHOD_FUNC(getter), nullptr);
+ rb_define_virtual_variable("test", getter, nullptr);
+
+ // It doesn't make any sense for both function pointers be nullptr at
+ // the same time.
+#endif
+
return self;
}
}
@@ -62,6 +80,18 @@ struct test_rb_define_hooked_variable {
RUBY_METHOD_FUNC(getter),
reinterpret_cast<void(*)(ANYARGS)>(setter)); // old
rb_define_hooked_variable("test", &v, getter, setter); // new
+
+#ifdef HAVE_NULLPTR
+ rb_define_hooked_variable("test", &v, nullptr, reinterpret_cast<void(*)(ANYARGS)>(setter));
+ rb_define_hooked_variable("test", &v, nullptr, setter);
+
+ rb_define_hooked_variable("test", &v, RUBY_METHOD_FUNC(getter), nullptr);
+ rb_define_hooked_variable("test", &v, getter, nullptr);
+
+ // It doesn't make any sense for both function pointers be nullptr at
+ // the same time.
+#endif
+
return self;
}
};
@@ -83,6 +113,10 @@ namespace test_rb_iterate {
VALUE
test(VALUE self)
{
+#ifdef HAVE_NULLPTR
+ rb_iterate(iter, self, nullptr, self);
+#endif
+
rb_iterate(iter, self, RUBY_METHOD_FUNC(block), self); // old
return rb_iterate(iter, self, block, self); // new
}
@@ -100,6 +134,11 @@ namespace test_rb_block_call {
{
const ID mid = rb_intern("each");
const VALUE argv[] = { Qundef };
+
+#ifdef HAVE_NULLPTR
+ rb_block_call(self, mid, 0, argv, nullptr, self);
+#endif
+
rb_block_call(self, mid, 0, argv, RUBY_METHOD_FUNC(block), self); // old
return rb_block_call(self, mid, 0, argv, block, self); // new
}
@@ -121,6 +160,11 @@ namespace test_rb_rescue {
VALUE
test(VALUE self)
{
+#ifdef HAVE_NULLPTR
+ rb_rescue(RUBY_METHOD_FUNC(begin), self, nullptr, self);
+ rb_rescue(begin, self, nullptr, self);
+#endif
+
rb_rescue(RUBY_METHOD_FUNC(begin), self, RUBY_METHOD_FUNC(rescue), self); // old
return rb_rescue(begin, self, rescue, self); // new
}
@@ -142,9 +186,14 @@ namespace test_rb_rescue2 {
VALUE
test(VALUE self)
{
+#ifdef HAVE_NULLPTR
+ rb_rescue2(RUBY_METHOD_FUNC(begin), self, nullptr, self, rb_eStandardError, rb_eFatal, (VALUE)0);
+ rb_rescue2(begin, self, nullptr, self, rb_eStandardError, rb_eFatal, (VALUE)0);
+#endif
+
rb_rescue2(RUBY_METHOD_FUNC(begin), self, RUBY_METHOD_FUNC(rescue), self,
- rb_eStandardError, rb_eFatal, 0); // old
- return rb_rescue2(begin, self, rescue, self, rb_eStandardError, rb_eFatal, 0); // new
+ rb_eStandardError, rb_eFatal, (VALUE)0); // old
+ return rb_rescue2(begin, self, rescue, self, rb_eStandardError, rb_eFatal, (VALUE)0); // new
}
}
@@ -164,6 +213,11 @@ namespace test_rb_ensure {
VALUE
test(VALUE self)
{
+#ifdef HAVE_NULLPTR
+ rb_ensure(RUBY_METHOD_FUNC(begin), self, nullptr, self);
+ rb_ensure(begin, self, nullptr, self);
+#endif
+
rb_ensure(RUBY_METHOD_FUNC(begin), self, RUBY_METHOD_FUNC(ensure), self); // old
return rb_ensure(begin, self, ensure, self); // new
}
@@ -180,6 +234,11 @@ namespace test_rb_catch {
test(VALUE self)
{
static const char *zero = 0;
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a catcher.
+#endif
+
rb_catch(zero, RUBY_METHOD_FUNC(catcher), self); // old
return rb_catch(zero, catcher, self); // new
}
@@ -195,6 +254,10 @@ namespace test_rb_catch_obj {
VALUE
test(VALUE self)
{
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a catcher.
+#endif
+
rb_catch_obj(self, RUBY_METHOD_FUNC(catcher), self); // old
return rb_catch_obj(self, catcher, self); // new
}
@@ -210,6 +273,10 @@ namespace test_rb_fiber_new {
VALUE
test(VALUE self)
{
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a fiber.
+#endif
+
rb_fiber_new(RUBY_METHOD_FUNC(fiber), self); // old
return rb_fiber_new(fiber, self); // new
}
@@ -225,6 +292,10 @@ namespace test_rb_proc_new {
VALUE
test(VALUE self)
{
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a proc.
+#endif
+
rb_fiber_new(RUBY_METHOD_FUNC(proc), self); // old
return rb_fiber_new(proc, self); // new
}
@@ -244,6 +315,11 @@ struct test_rb_thread_create {
test(VALUE self)
{
v = self;
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a thread.
+#endif
+
rb_thread_create(RUBY_METHOD_FUNC(thread), &v); // old
return rb_thread_create(thread, &v); // new
}
@@ -262,6 +338,11 @@ namespace test_st_foreach {
{
st_data_t data = 0;
st_table *st = st_init_numtable();
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
st_foreach(st, reinterpret_cast<int(*)(ANYARGS)>(iter), data); // old
st_foreach(st, iter, data); // new
return self;
@@ -280,6 +361,11 @@ namespace test_st_foreach_check {
{
st_data_t data = 0;
st_table *st = st_init_numtable();
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
st_foreach_check(st, reinterpret_cast<int(*)(ANYARGS)>(iter), data, data); // old
st_foreach_check(st, iter, data, data); // new
return self;
@@ -298,6 +384,11 @@ namespace test_st_foreach_safe {
{
st_data_t data = 0;
st_table *st = st_init_numtable();
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
st_foreach_safe(st, reinterpret_cast<int(*)(ANYARGS)>(iter), data); // old
st_foreach_safe(st, iter, data); // new
return self;
@@ -315,6 +406,11 @@ namespace test_rb_hash_foreach {
test(VALUE self)
{
VALUE h = rb_hash_new();
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
rb_hash_foreach(h, reinterpret_cast<int(*)(ANYARGS)>(iter), self); // old
rb_hash_foreach(h, iter, self); // new
return self;
@@ -331,6 +427,10 @@ namespace test_rb_ivar_foreach {
VALUE
test(VALUE self)
{
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as an iterator.
+#endif
+
rb_ivar_foreach(self, reinterpret_cast<int(*)(ANYARGS)>(iter), self); // old
rb_ivar_foreach(self, iter, self); // new
return self;
@@ -362,6 +462,12 @@ namespace test_rb_define_method {
return Qnil;
}
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
VALUE
test(VALUE self)
{
@@ -370,18 +476,102 @@ namespace test_rb_define_method {
rb_define_method(self, "m2", m2, 2);
rb_define_method(self, "ma", ma, -2);
rb_define_method(self, "mv", mv, -1);
+ rb_define_method(self, "mc", mc, -1);
// Cast by RUBY_METHOD_FUNC
rb_define_method(self, "m1", RUBY_METHOD_FUNC(m1), 1);
rb_define_method(self, "m2", RUBY_METHOD_FUNC(m2), 2);
rb_define_method(self, "ma", RUBY_METHOD_FUNC(ma), -2);
rb_define_method(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_method(self, "mc", RUBY_METHOD_FUNC(mc), -1);
// Explicit cast instead of RUBY_METHOD_FUNC
rb_define_method(self, "m1", (VALUE (*)(...))(m1), 1);
rb_define_method(self, "m2", (VALUE (*)(...))(m2), 2);
rb_define_method(self, "ma", (VALUE (*)(...))(ma), -2);
rb_define_method(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_method(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_method(self, "m1", rb_f_notimplement, 1);
+ rb_define_method(self, "m2", rb_f_notimplement, 2);
+ rb_define_method(self, "ma", rb_f_notimplement, -2);
+ rb_define_method(self, "mv", rb_f_notimplement, -1);
+ rb_define_method(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
+
+ return self;
+ }
+}
+
+namespace test_rb_define_method_id {
+ static VALUE
+ m1(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ m2(VALUE, VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ ma(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mv(int, VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ // No cast
+ rb_define_method_id(self, rb_intern("m1"), m1, 1);
+ rb_define_method_id(self, rb_intern("m2"), m2, 2);
+ rb_define_method_id(self, rb_intern("ma"), ma, -2);
+ rb_define_method_id(self, rb_intern("mv"), mv, -1);
+ rb_define_method_id(self, rb_intern("mc"), mc, -1);
+
+ // Cast by RUBY_METHOD_FUNC
+ rb_define_method_id(self, rb_intern("m1"), RUBY_METHOD_FUNC(m1), 1);
+ rb_define_method_id(self, rb_intern("m2"), RUBY_METHOD_FUNC(m2), 2);
+ rb_define_method_id(self, rb_intern("ma"), RUBY_METHOD_FUNC(ma), -2);
+ rb_define_method_id(self, rb_intern("mv"), RUBY_METHOD_FUNC(mv), -1);
+ rb_define_method_id(self, rb_intern("mc"), RUBY_METHOD_FUNC(mc), -1);
+
+ // Explicit cast instead of RUBY_METHOD_FUNC
+ rb_define_method_id(self, rb_intern("m1"), (VALUE (*)(...))(m1), 1);
+ rb_define_method_id(self, rb_intern("m2"), (VALUE (*)(...))(m2), 2);
+ rb_define_method_id(self, rb_intern("ma"), (VALUE (*)(...))(ma), -2);
+ rb_define_method_id(self, rb_intern("mv"), (VALUE (*)(...))(mv), -1);
+ rb_define_method_id(self, rb_intern("mc"), (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_method_id(self, rb_intern("m1"), rb_f_notimplement, 1);
+ rb_define_method_id(self, rb_intern("m2"), rb_f_notimplement, 2);
+ rb_define_method_id(self, rb_intern("ma"), rb_f_notimplement, -2);
+ rb_define_method_id(self, rb_intern("mv"), rb_f_notimplement, -1);
+ rb_define_method_id(self, rb_intern("mc"), rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
return self;
}
@@ -412,6 +602,12 @@ namespace test_rb_define_module_function {
return Qnil;
}
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
VALUE
test(VALUE self)
{
@@ -420,18 +616,32 @@ namespace test_rb_define_module_function {
rb_define_module_function(self, "m2", m2, 2);
rb_define_module_function(self, "ma", ma, -2);
rb_define_module_function(self, "mv", mv, -1);
+ rb_define_module_function(self, "mc", mc, -1);
// Cast by RUBY_METHOD_FUNC
rb_define_module_function(self, "m1", RUBY_METHOD_FUNC(m1), 1);
rb_define_module_function(self, "m2", RUBY_METHOD_FUNC(m2), 2);
rb_define_module_function(self, "ma", RUBY_METHOD_FUNC(ma), -2);
rb_define_module_function(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_module_function(self, "mc", RUBY_METHOD_FUNC(mc), -1);
// Explicit cast instead of RUBY_METHOD_FUNC
rb_define_module_function(self, "m1", (VALUE (*)(...))(m1), 1);
rb_define_module_function(self, "m2", (VALUE (*)(...))(m2), 2);
rb_define_module_function(self, "ma", (VALUE (*)(...))(ma), -2);
rb_define_module_function(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_module_function(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_module_function(self, "m1", rb_f_notimplement, 1);
+ rb_define_module_function(self, "m2", rb_f_notimplement, 2);
+ rb_define_module_function(self, "ma", rb_f_notimplement, -2);
+ rb_define_module_function(self, "mv", rb_f_notimplement, -1);
+ rb_define_module_function(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
return self;
}
@@ -462,6 +672,12 @@ namespace test_rb_define_singleton_method {
return Qnil;
}
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
VALUE
test(VALUE self)
{
@@ -470,18 +686,32 @@ namespace test_rb_define_singleton_method {
rb_define_singleton_method(self, "m2", m2, 2);
rb_define_singleton_method(self, "ma", ma, -2);
rb_define_singleton_method(self, "mv", mv, -1);
+ rb_define_singleton_method(self, "mc", mc, -1);
// Cast by RUBY_METHOD_FUNC
rb_define_singleton_method(self, "m1", RUBY_METHOD_FUNC(m1), 1);
rb_define_singleton_method(self, "m2", RUBY_METHOD_FUNC(m2), 2);
rb_define_singleton_method(self, "ma", RUBY_METHOD_FUNC(ma), -2);
rb_define_singleton_method(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_singleton_method(self, "mc", RUBY_METHOD_FUNC(mc), -1);
// Explicit cast instead of RUBY_METHOD_FUNC
rb_define_singleton_method(self, "m1", (VALUE (*)(...))(m1), 1);
rb_define_singleton_method(self, "m2", (VALUE (*)(...))(m2), 2);
rb_define_singleton_method(self, "ma", (VALUE (*)(...))(ma), -2);
rb_define_singleton_method(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_singleton_method(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_singleton_method(self, "m1", rb_f_notimplement, 1);
+ rb_define_singleton_method(self, "m2", rb_f_notimplement, 2);
+ rb_define_singleton_method(self, "ma", rb_f_notimplement, -2);
+ rb_define_singleton_method(self, "mv", rb_f_notimplement, -1);
+ rb_define_singleton_method(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
return self;
}
@@ -512,6 +742,12 @@ namespace test_rb_define_protected_method {
return Qnil;
}
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
VALUE
test(VALUE self)
{
@@ -520,18 +756,32 @@ namespace test_rb_define_protected_method {
rb_define_protected_method(self, "m2", m2, 2);
rb_define_protected_method(self, "ma", ma, -2);
rb_define_protected_method(self, "mv", mv, -1);
+ rb_define_protected_method(self, "mc", mc, -1);
// Cast by RUBY_METHOD_FUNC
rb_define_protected_method(self, "m1", RUBY_METHOD_FUNC(m1), 1);
rb_define_protected_method(self, "m2", RUBY_METHOD_FUNC(m2), 2);
rb_define_protected_method(self, "ma", RUBY_METHOD_FUNC(ma), -2);
rb_define_protected_method(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_protected_method(self, "mc", RUBY_METHOD_FUNC(mc), -1);
// Explicit cast instead of RUBY_METHOD_FUNC
rb_define_protected_method(self, "m1", (VALUE (*)(...))(m1), 1);
rb_define_protected_method(self, "m2", (VALUE (*)(...))(m2), 2);
rb_define_protected_method(self, "ma", (VALUE (*)(...))(ma), -2);
rb_define_protected_method(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_protected_method(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_protected_method(self, "m1", rb_f_notimplement, 1);
+ rb_define_protected_method(self, "m2", rb_f_notimplement, 2);
+ rb_define_protected_method(self, "ma", rb_f_notimplement, -2);
+ rb_define_protected_method(self, "mv", rb_f_notimplement, -1);
+ rb_define_protected_method(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
return self;
}
@@ -562,6 +812,12 @@ namespace test_rb_define_private_method {
return Qnil;
}
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
VALUE
test(VALUE self)
{
@@ -570,18 +826,102 @@ namespace test_rb_define_private_method {
rb_define_private_method(self, "m2", m2, 2);
rb_define_private_method(self, "ma", ma, -2);
rb_define_private_method(self, "mv", mv, -1);
+ rb_define_private_method(self, "mc", mc, -1);
// Cast by RUBY_METHOD_FUNC
rb_define_private_method(self, "m1", RUBY_METHOD_FUNC(m1), 1);
rb_define_private_method(self, "m2", RUBY_METHOD_FUNC(m2), 2);
rb_define_private_method(self, "ma", RUBY_METHOD_FUNC(ma), -2);
rb_define_private_method(self, "mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_private_method(self, "mc", RUBY_METHOD_FUNC(mc), -1);
// Explicit cast instead of RUBY_METHOD_FUNC
rb_define_private_method(self, "m1", (VALUE (*)(...))(m1), 1);
rb_define_private_method(self, "m2", (VALUE (*)(...))(m2), 2);
rb_define_private_method(self, "ma", (VALUE (*)(...))(ma), -2);
rb_define_private_method(self, "mv", (VALUE (*)(...))(mv), -1);
+ rb_define_private_method(self, "mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_private_method(self, "m1", rb_f_notimplement, 1);
+ rb_define_private_method(self, "m2", rb_f_notimplement, 2);
+ rb_define_private_method(self, "ma", rb_f_notimplement, -2);
+ rb_define_private_method(self, "mv", rb_f_notimplement, -1);
+ rb_define_private_method(self, "mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
+
+ return self;
+ }
+}
+
+namespace test_rb_define_global_function {
+ static VALUE
+ m1(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ m2(VALUE, VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ ma(VALUE, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mv(int, VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ static VALUE
+ mc(int, const VALUE*, VALUE)
+ {
+ return Qnil;
+ }
+
+ VALUE
+ test(VALUE self)
+ {
+ // No cast
+ rb_define_global_function("m1", m1, 1);
+ rb_define_global_function("m2", m2, 2);
+ rb_define_global_function("ma", ma, -2);
+ rb_define_global_function("mv", mv, -1);
+ rb_define_global_function("mc", mc, -1);
+
+ // Cast by RUBY_METHOD_FUNC
+ rb_define_global_function("m1", RUBY_METHOD_FUNC(m1), 1);
+ rb_define_global_function("m2", RUBY_METHOD_FUNC(m2), 2);
+ rb_define_global_function("ma", RUBY_METHOD_FUNC(ma), -2);
+ rb_define_global_function("mv", RUBY_METHOD_FUNC(mv), -1);
+ rb_define_global_function("mc", RUBY_METHOD_FUNC(mc), -1);
+
+ // Explicit cast instead of RUBY_METHOD_FUNC
+ rb_define_global_function("m1", (VALUE (*)(...))(m1), 1);
+ rb_define_global_function("m2", (VALUE (*)(...))(m2), 2);
+ rb_define_global_function("ma", (VALUE (*)(...))(ma), -2);
+ rb_define_global_function("mv", (VALUE (*)(...))(mv), -1);
+ rb_define_global_function("mc", (VALUE (*)(...))(mc), -1);
+
+ // rb_f_notimplement
+ rb_define_global_function("m1", rb_f_notimplement, 1);
+ rb_define_global_function("m2", rb_f_notimplement, 2);
+ rb_define_global_function("ma", rb_f_notimplement, -2);
+ rb_define_global_function("mv", rb_f_notimplement, -1);
+ rb_define_global_function("mc", rb_f_notimplement, -1);
+
+#ifdef HAVE_NULLPTR
+ // It doesn't make any sense at all to pass nullptr as a method.
+#endif
return self;
}
@@ -612,8 +952,10 @@ Init_cxxanyargs(void)
test(rb_hash_foreach);
test(rb_ivar_foreach);
test(rb_define_method);
+ test(rb_define_method_id);
test(rb_define_module_function);
test(rb_define_singleton_method);
test(rb_define_protected_method);
test(rb_define_private_method);
+ test(rb_define_global_function);
}
diff --git a/ext/-test-/cxxanyargs/depend b/ext/-test-/cxxanyargs/depend
index 02113b6c26..ca821409a2 100644
--- a/ext/-test-/cxxanyargs/depend
+++ b/ext/-test-/cxxanyargs/depend
@@ -6,7 +6,7 @@ $(TARGET_SO) $(STATIC_LIB): $(FAILURES:.cpp=.failed)
$(Q)$(RUBY) -rfileutils \
-e "t = ARGV.shift" \
-e "err = IO.popen(ARGV, err:[:child, :out], &:read)" \
- -e "abort err unless /rb_define_method/ =~ err" \
+ -e "abort err unless /rb_define_method/ =~ err.b" \
-e "File.write(t, err)" $@ $(MAKE) $(*F).o
# AUTOGENERATED DEPENDENCIES START
diff --git a/ext/-test-/cxxanyargs/extconf.rb b/ext/-test-/cxxanyargs/extconf.rb
index 08d8c83010..d1d2469209 100644
--- a/ext/-test-/cxxanyargs/extconf.rb
+++ b/ext/-test-/cxxanyargs/extconf.rb
@@ -2,12 +2,19 @@
cxx = MakeMakefile["C++"]
-ok = cxx.try_compile(<<~'begin', "") do |x|
+# #### have_devel hack ####
+# cxx.try_compile tries to detect compilers, but the try_compile below is
+# trying to detect a compiler in a different way. We need to prevent the
+# default detection routine.
+
+cxx.instance_variable_set(:'@have_devel', true)
+
+ok = cxx.try_link(<<~'begin', "") do |x|
#include "ruby/config.h"
namespace {
- typedef int conftest[SIZEOF_LONG == sizeof(long) ? 1 : -1];
- typedef int conftest[SIZEOF_VOIDP == sizeof(void*) ? 1 : -1];
+ typedef int conftest1[SIZEOF_LONG == sizeof(long) ? 1 : -1];
+ typedef int conftest2[SIZEOF_VOIDP == sizeof(void*) ? 1 : -1];
}
int
@@ -21,6 +28,8 @@ begin
x.sub! %<#include "ruby.h">, ''
end
+cxx.instance_variable_set(:'@have_devel', ok)
+
if ok
$srcs = %w[cxxanyargs.cpp]
failures = Dir.glob($srcdir + "/failure*.cpp").map {|n| File.basename(n)}
diff --git a/ext/-test-/debug/depend b/ext/-test-/debug/depend
index 662ed87510..dad22d46de 100644
--- a/ext/-test-/debug/depend
+++ b/ext/-test-/debug/depend
@@ -2,8 +2,157 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -13,8 +162,157 @@ init.o: $(hdrdir)/ruby/subst.h
init.o: init.c
inspector.o: $(RUBY_EXTCONF_H)
inspector.o: $(arch_hdrdir)/ruby/config.h
+inspector.o: $(hdrdir)/ruby/internal/anyargs.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+inspector.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+inspector.o: $(hdrdir)/ruby/internal/assume.h
+inspector.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+inspector.o: $(hdrdir)/ruby/internal/attr/artificial.h
+inspector.o: $(hdrdir)/ruby/internal/attr/cold.h
+inspector.o: $(hdrdir)/ruby/internal/attr/const.h
+inspector.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+inspector.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+inspector.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+inspector.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+inspector.o: $(hdrdir)/ruby/internal/attr/error.h
+inspector.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+inspector.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+inspector.o: $(hdrdir)/ruby/internal/attr/format.h
+inspector.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+inspector.o: $(hdrdir)/ruby/internal/attr/noalias.h
+inspector.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+inspector.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+inspector.o: $(hdrdir)/ruby/internal/attr/noinline.h
+inspector.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+inspector.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+inspector.o: $(hdrdir)/ruby/internal/attr/pure.h
+inspector.o: $(hdrdir)/ruby/internal/attr/restrict.h
+inspector.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+inspector.o: $(hdrdir)/ruby/internal/attr/warning.h
+inspector.o: $(hdrdir)/ruby/internal/attr/weakref.h
+inspector.o: $(hdrdir)/ruby/internal/cast.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+inspector.o: $(hdrdir)/ruby/internal/compiler_since.h
+inspector.o: $(hdrdir)/ruby/internal/config.h
+inspector.o: $(hdrdir)/ruby/internal/constant_p.h
+inspector.o: $(hdrdir)/ruby/internal/core.h
+inspector.o: $(hdrdir)/ruby/internal/core/rarray.h
+inspector.o: $(hdrdir)/ruby/internal/core/rbasic.h
+inspector.o: $(hdrdir)/ruby/internal/core/rbignum.h
+inspector.o: $(hdrdir)/ruby/internal/core/rclass.h
+inspector.o: $(hdrdir)/ruby/internal/core/rdata.h
+inspector.o: $(hdrdir)/ruby/internal/core/rfile.h
+inspector.o: $(hdrdir)/ruby/internal/core/rhash.h
+inspector.o: $(hdrdir)/ruby/internal/core/robject.h
+inspector.o: $(hdrdir)/ruby/internal/core/rregexp.h
+inspector.o: $(hdrdir)/ruby/internal/core/rstring.h
+inspector.o: $(hdrdir)/ruby/internal/core/rstruct.h
+inspector.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+inspector.o: $(hdrdir)/ruby/internal/ctype.h
+inspector.o: $(hdrdir)/ruby/internal/dllexport.h
+inspector.o: $(hdrdir)/ruby/internal/dosish.h
+inspector.o: $(hdrdir)/ruby/internal/error.h
+inspector.o: $(hdrdir)/ruby/internal/eval.h
+inspector.o: $(hdrdir)/ruby/internal/event.h
+inspector.o: $(hdrdir)/ruby/internal/fl_type.h
+inspector.o: $(hdrdir)/ruby/internal/gc.h
+inspector.o: $(hdrdir)/ruby/internal/glob.h
+inspector.o: $(hdrdir)/ruby/internal/globals.h
+inspector.o: $(hdrdir)/ruby/internal/has/attribute.h
+inspector.o: $(hdrdir)/ruby/internal/has/builtin.h
+inspector.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+inspector.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+inspector.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+inspector.o: $(hdrdir)/ruby/internal/has/extension.h
+inspector.o: $(hdrdir)/ruby/internal/has/feature.h
+inspector.o: $(hdrdir)/ruby/internal/has/warning.h
+inspector.o: $(hdrdir)/ruby/internal/intern/array.h
+inspector.o: $(hdrdir)/ruby/internal/intern/bignum.h
+inspector.o: $(hdrdir)/ruby/internal/intern/class.h
+inspector.o: $(hdrdir)/ruby/internal/intern/compar.h
+inspector.o: $(hdrdir)/ruby/internal/intern/complex.h
+inspector.o: $(hdrdir)/ruby/internal/intern/cont.h
+inspector.o: $(hdrdir)/ruby/internal/intern/dir.h
+inspector.o: $(hdrdir)/ruby/internal/intern/enum.h
+inspector.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+inspector.o: $(hdrdir)/ruby/internal/intern/error.h
+inspector.o: $(hdrdir)/ruby/internal/intern/eval.h
+inspector.o: $(hdrdir)/ruby/internal/intern/file.h
+inspector.o: $(hdrdir)/ruby/internal/intern/gc.h
+inspector.o: $(hdrdir)/ruby/internal/intern/hash.h
+inspector.o: $(hdrdir)/ruby/internal/intern/io.h
+inspector.o: $(hdrdir)/ruby/internal/intern/load.h
+inspector.o: $(hdrdir)/ruby/internal/intern/marshal.h
+inspector.o: $(hdrdir)/ruby/internal/intern/numeric.h
+inspector.o: $(hdrdir)/ruby/internal/intern/object.h
+inspector.o: $(hdrdir)/ruby/internal/intern/parse.h
+inspector.o: $(hdrdir)/ruby/internal/intern/proc.h
+inspector.o: $(hdrdir)/ruby/internal/intern/process.h
+inspector.o: $(hdrdir)/ruby/internal/intern/random.h
+inspector.o: $(hdrdir)/ruby/internal/intern/range.h
+inspector.o: $(hdrdir)/ruby/internal/intern/rational.h
+inspector.o: $(hdrdir)/ruby/internal/intern/re.h
+inspector.o: $(hdrdir)/ruby/internal/intern/ruby.h
+inspector.o: $(hdrdir)/ruby/internal/intern/select.h
+inspector.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+inspector.o: $(hdrdir)/ruby/internal/intern/signal.h
+inspector.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+inspector.o: $(hdrdir)/ruby/internal/intern/string.h
+inspector.o: $(hdrdir)/ruby/internal/intern/struct.h
+inspector.o: $(hdrdir)/ruby/internal/intern/thread.h
+inspector.o: $(hdrdir)/ruby/internal/intern/time.h
+inspector.o: $(hdrdir)/ruby/internal/intern/variable.h
+inspector.o: $(hdrdir)/ruby/internal/intern/vm.h
+inspector.o: $(hdrdir)/ruby/internal/interpreter.h
+inspector.o: $(hdrdir)/ruby/internal/iterator.h
+inspector.o: $(hdrdir)/ruby/internal/memory.h
+inspector.o: $(hdrdir)/ruby/internal/method.h
+inspector.o: $(hdrdir)/ruby/internal/module.h
+inspector.o: $(hdrdir)/ruby/internal/newobj.h
+inspector.o: $(hdrdir)/ruby/internal/rgengc.h
+inspector.o: $(hdrdir)/ruby/internal/scan_args.h
+inspector.o: $(hdrdir)/ruby/internal/special_consts.h
+inspector.o: $(hdrdir)/ruby/internal/static_assert.h
+inspector.o: $(hdrdir)/ruby/internal/stdalign.h
+inspector.o: $(hdrdir)/ruby/internal/stdbool.h
+inspector.o: $(hdrdir)/ruby/internal/symbol.h
+inspector.o: $(hdrdir)/ruby/internal/token_paste.h
+inspector.o: $(hdrdir)/ruby/internal/value.h
+inspector.o: $(hdrdir)/ruby/internal/value_type.h
+inspector.o: $(hdrdir)/ruby/internal/variable.h
+inspector.o: $(hdrdir)/ruby/internal/warning_push.h
+inspector.o: $(hdrdir)/ruby/internal/xmalloc.h
inspector.o: $(hdrdir)/ruby/assert.h
inspector.o: $(hdrdir)/ruby/backward.h
+inspector.o: $(hdrdir)/ruby/backward/2/assume.h
+inspector.o: $(hdrdir)/ruby/backward/2/attributes.h
+inspector.o: $(hdrdir)/ruby/backward/2/bool.h
+inspector.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+inspector.o: $(hdrdir)/ruby/backward/2/inttypes.h
+inspector.o: $(hdrdir)/ruby/backward/2/limits.h
+inspector.o: $(hdrdir)/ruby/backward/2/long_long.h
+inspector.o: $(hdrdir)/ruby/backward/2/stdalign.h
+inspector.o: $(hdrdir)/ruby/backward/2/stdarg.h
inspector.o: $(hdrdir)/ruby/debug.h
inspector.o: $(hdrdir)/ruby/defines.h
inspector.o: $(hdrdir)/ruby/intern.h
@@ -25,8 +323,157 @@ inspector.o: $(hdrdir)/ruby/subst.h
inspector.o: inspector.c
profile_frames.o: $(RUBY_EXTCONF_H)
profile_frames.o: $(arch_hdrdir)/ruby/config.h
+profile_frames.o: $(hdrdir)/ruby/internal/anyargs.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+profile_frames.o: $(hdrdir)/ruby/internal/assume.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/artificial.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/cold.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/const.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/error.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/format.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/noalias.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/noinline.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/pure.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/restrict.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/warning.h
+profile_frames.o: $(hdrdir)/ruby/internal/attr/weakref.h
+profile_frames.o: $(hdrdir)/ruby/internal/cast.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+profile_frames.o: $(hdrdir)/ruby/internal/compiler_since.h
+profile_frames.o: $(hdrdir)/ruby/internal/config.h
+profile_frames.o: $(hdrdir)/ruby/internal/constant_p.h
+profile_frames.o: $(hdrdir)/ruby/internal/core.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rarray.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rbasic.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rbignum.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rclass.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rdata.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rfile.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rhash.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/robject.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rregexp.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rstring.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rstruct.h
+profile_frames.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+profile_frames.o: $(hdrdir)/ruby/internal/ctype.h
+profile_frames.o: $(hdrdir)/ruby/internal/dllexport.h
+profile_frames.o: $(hdrdir)/ruby/internal/dosish.h
+profile_frames.o: $(hdrdir)/ruby/internal/error.h
+profile_frames.o: $(hdrdir)/ruby/internal/eval.h
+profile_frames.o: $(hdrdir)/ruby/internal/event.h
+profile_frames.o: $(hdrdir)/ruby/internal/fl_type.h
+profile_frames.o: $(hdrdir)/ruby/internal/gc.h
+profile_frames.o: $(hdrdir)/ruby/internal/glob.h
+profile_frames.o: $(hdrdir)/ruby/internal/globals.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/attribute.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/builtin.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/extension.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/feature.h
+profile_frames.o: $(hdrdir)/ruby/internal/has/warning.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/array.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/bignum.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/class.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/compar.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/complex.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/cont.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/dir.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/enum.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/error.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/eval.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/file.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/gc.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/hash.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/io.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/load.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/marshal.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/numeric.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/object.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/parse.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/proc.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/process.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/random.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/range.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/rational.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/re.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/ruby.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/select.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/signal.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/string.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/struct.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/thread.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/time.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/variable.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/vm.h
+profile_frames.o: $(hdrdir)/ruby/internal/interpreter.h
+profile_frames.o: $(hdrdir)/ruby/internal/iterator.h
+profile_frames.o: $(hdrdir)/ruby/internal/memory.h
+profile_frames.o: $(hdrdir)/ruby/internal/method.h
+profile_frames.o: $(hdrdir)/ruby/internal/module.h
+profile_frames.o: $(hdrdir)/ruby/internal/newobj.h
+profile_frames.o: $(hdrdir)/ruby/internal/rgengc.h
+profile_frames.o: $(hdrdir)/ruby/internal/scan_args.h
+profile_frames.o: $(hdrdir)/ruby/internal/special_consts.h
+profile_frames.o: $(hdrdir)/ruby/internal/static_assert.h
+profile_frames.o: $(hdrdir)/ruby/internal/stdalign.h
+profile_frames.o: $(hdrdir)/ruby/internal/stdbool.h
+profile_frames.o: $(hdrdir)/ruby/internal/symbol.h
+profile_frames.o: $(hdrdir)/ruby/internal/token_paste.h
+profile_frames.o: $(hdrdir)/ruby/internal/value.h
+profile_frames.o: $(hdrdir)/ruby/internal/value_type.h
+profile_frames.o: $(hdrdir)/ruby/internal/variable.h
+profile_frames.o: $(hdrdir)/ruby/internal/warning_push.h
+profile_frames.o: $(hdrdir)/ruby/internal/xmalloc.h
profile_frames.o: $(hdrdir)/ruby/assert.h
profile_frames.o: $(hdrdir)/ruby/backward.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/assume.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/attributes.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/bool.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/inttypes.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/limits.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/long_long.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/stdalign.h
+profile_frames.o: $(hdrdir)/ruby/backward/2/stdarg.h
profile_frames.o: $(hdrdir)/ruby/debug.h
profile_frames.o: $(hdrdir)/ruby/defines.h
profile_frames.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/-test-/enumerator_kw/depend b/ext/-test-/enumerator_kw/depend
index b7489eaf73..4597e34027 100644
--- a/ext/-test-/enumerator_kw/depend
+++ b/ext/-test-/enumerator_kw/depend
@@ -2,8 +2,157 @@
enumerator_kw.o: $(RUBY_EXTCONF_H)
enumerator_kw.o: $(arch_hdrdir)/ruby/config.h
enumerator_kw.o: $(hdrdir)/ruby.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/anyargs.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/assume.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/artificial.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/cold.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/const.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/error.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/format.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noalias.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noinline.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/pure.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/restrict.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/warning.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/attr/weakref.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/cast.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/compiler_since.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/config.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/constant_p.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rarray.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rbasic.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rbignum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rclass.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rdata.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rfile.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rhash.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/robject.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rregexp.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rstring.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rstruct.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/ctype.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/dllexport.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/dosish.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/error.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/eval.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/event.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/fl_type.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/gc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/glob.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/globals.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/attribute.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/builtin.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/extension.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/feature.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/has/warning.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/array.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/bignum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/class.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/compar.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/complex.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/cont.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/dir.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/enum.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/error.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/eval.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/file.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/gc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/hash.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/io.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/load.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/marshal.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/numeric.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/object.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/parse.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/proc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/process.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/random.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/range.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/rational.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/re.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/ruby.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/select.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/signal.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/string.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/struct.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/thread.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/time.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/variable.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/vm.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/interpreter.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/iterator.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/memory.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/method.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/module.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/newobj.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/rgengc.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/scan_args.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/special_consts.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/static_assert.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/stdalign.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/stdbool.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/symbol.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/token_paste.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/value.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/value_type.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/variable.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/warning_push.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/xmalloc.h
enumerator_kw.o: $(hdrdir)/ruby/assert.h
enumerator_kw.o: $(hdrdir)/ruby/backward.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/assume.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/attributes.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/bool.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/limits.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/long_long.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enumerator_kw.o: $(hdrdir)/ruby/backward/2/stdarg.h
enumerator_kw.o: $(hdrdir)/ruby/defines.h
enumerator_kw.o: $(hdrdir)/ruby/intern.h
enumerator_kw.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/exception/depend b/ext/-test-/exception/depend
index d0958de9b8..47f1ac6a6a 100644
--- a/ext/-test-/exception/depend
+++ b/ext/-test-/exception/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
dataerror.o: $(RUBY_EXTCONF_H)
dataerror.o: $(arch_hdrdir)/ruby/config.h
+dataerror.o: $(hdrdir)/ruby/internal/anyargs.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+dataerror.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+dataerror.o: $(hdrdir)/ruby/internal/assume.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/artificial.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/cold.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/const.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/error.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/format.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/noalias.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/noinline.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/pure.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/restrict.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/warning.h
+dataerror.o: $(hdrdir)/ruby/internal/attr/weakref.h
+dataerror.o: $(hdrdir)/ruby/internal/cast.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+dataerror.o: $(hdrdir)/ruby/internal/compiler_since.h
+dataerror.o: $(hdrdir)/ruby/internal/config.h
+dataerror.o: $(hdrdir)/ruby/internal/constant_p.h
+dataerror.o: $(hdrdir)/ruby/internal/core.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rarray.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rbasic.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rbignum.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rclass.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rdata.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rfile.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rhash.h
+dataerror.o: $(hdrdir)/ruby/internal/core/robject.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rregexp.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rstring.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rstruct.h
+dataerror.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+dataerror.o: $(hdrdir)/ruby/internal/ctype.h
+dataerror.o: $(hdrdir)/ruby/internal/dllexport.h
+dataerror.o: $(hdrdir)/ruby/internal/dosish.h
+dataerror.o: $(hdrdir)/ruby/internal/error.h
+dataerror.o: $(hdrdir)/ruby/internal/eval.h
+dataerror.o: $(hdrdir)/ruby/internal/event.h
+dataerror.o: $(hdrdir)/ruby/internal/fl_type.h
+dataerror.o: $(hdrdir)/ruby/internal/gc.h
+dataerror.o: $(hdrdir)/ruby/internal/glob.h
+dataerror.o: $(hdrdir)/ruby/internal/globals.h
+dataerror.o: $(hdrdir)/ruby/internal/has/attribute.h
+dataerror.o: $(hdrdir)/ruby/internal/has/builtin.h
+dataerror.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+dataerror.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+dataerror.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+dataerror.o: $(hdrdir)/ruby/internal/has/extension.h
+dataerror.o: $(hdrdir)/ruby/internal/has/feature.h
+dataerror.o: $(hdrdir)/ruby/internal/has/warning.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/array.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/bignum.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/class.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/compar.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/complex.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/cont.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/dir.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/enum.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/error.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/eval.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/file.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/gc.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/hash.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/io.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/load.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/marshal.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/numeric.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/object.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/parse.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/proc.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/process.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/random.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/range.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/rational.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/re.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/ruby.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/select.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/signal.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/string.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/struct.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/thread.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/time.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/variable.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/vm.h
+dataerror.o: $(hdrdir)/ruby/internal/interpreter.h
+dataerror.o: $(hdrdir)/ruby/internal/iterator.h
+dataerror.o: $(hdrdir)/ruby/internal/memory.h
+dataerror.o: $(hdrdir)/ruby/internal/method.h
+dataerror.o: $(hdrdir)/ruby/internal/module.h
+dataerror.o: $(hdrdir)/ruby/internal/newobj.h
+dataerror.o: $(hdrdir)/ruby/internal/rgengc.h
+dataerror.o: $(hdrdir)/ruby/internal/scan_args.h
+dataerror.o: $(hdrdir)/ruby/internal/special_consts.h
+dataerror.o: $(hdrdir)/ruby/internal/static_assert.h
+dataerror.o: $(hdrdir)/ruby/internal/stdalign.h
+dataerror.o: $(hdrdir)/ruby/internal/stdbool.h
+dataerror.o: $(hdrdir)/ruby/internal/symbol.h
+dataerror.o: $(hdrdir)/ruby/internal/token_paste.h
+dataerror.o: $(hdrdir)/ruby/internal/value.h
+dataerror.o: $(hdrdir)/ruby/internal/value_type.h
+dataerror.o: $(hdrdir)/ruby/internal/variable.h
+dataerror.o: $(hdrdir)/ruby/internal/warning_push.h
+dataerror.o: $(hdrdir)/ruby/internal/xmalloc.h
dataerror.o: $(hdrdir)/ruby/assert.h
dataerror.o: $(hdrdir)/ruby/backward.h
+dataerror.o: $(hdrdir)/ruby/backward/2/assume.h
+dataerror.o: $(hdrdir)/ruby/backward/2/attributes.h
+dataerror.o: $(hdrdir)/ruby/backward/2/bool.h
+dataerror.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+dataerror.o: $(hdrdir)/ruby/backward/2/inttypes.h
+dataerror.o: $(hdrdir)/ruby/backward/2/limits.h
+dataerror.o: $(hdrdir)/ruby/backward/2/long_long.h
+dataerror.o: $(hdrdir)/ruby/backward/2/stdalign.h
+dataerror.o: $(hdrdir)/ruby/backward/2/stdarg.h
dataerror.o: $(hdrdir)/ruby/defines.h
dataerror.o: $(hdrdir)/ruby/intern.h
dataerror.o: $(hdrdir)/ruby/missing.h
@@ -13,8 +162,157 @@ dataerror.o: dataerror.c
enc_raise.o: $(RUBY_EXTCONF_H)
enc_raise.o: $(arch_hdrdir)/ruby/config.h
enc_raise.o: $(hdrdir)/ruby.h
+enc_raise.o: $(hdrdir)/ruby/internal/anyargs.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+enc_raise.o: $(hdrdir)/ruby/internal/assume.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/artificial.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/cold.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/const.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/error.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/format.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/noalias.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/noinline.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/pure.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/restrict.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/warning.h
+enc_raise.o: $(hdrdir)/ruby/internal/attr/weakref.h
+enc_raise.o: $(hdrdir)/ruby/internal/cast.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+enc_raise.o: $(hdrdir)/ruby/internal/compiler_since.h
+enc_raise.o: $(hdrdir)/ruby/internal/config.h
+enc_raise.o: $(hdrdir)/ruby/internal/constant_p.h
+enc_raise.o: $(hdrdir)/ruby/internal/core.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rarray.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rbasic.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rbignum.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rclass.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rdata.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rfile.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rhash.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/robject.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rregexp.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rstring.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rstruct.h
+enc_raise.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+enc_raise.o: $(hdrdir)/ruby/internal/ctype.h
+enc_raise.o: $(hdrdir)/ruby/internal/dllexport.h
+enc_raise.o: $(hdrdir)/ruby/internal/dosish.h
+enc_raise.o: $(hdrdir)/ruby/internal/error.h
+enc_raise.o: $(hdrdir)/ruby/internal/eval.h
+enc_raise.o: $(hdrdir)/ruby/internal/event.h
+enc_raise.o: $(hdrdir)/ruby/internal/fl_type.h
+enc_raise.o: $(hdrdir)/ruby/internal/gc.h
+enc_raise.o: $(hdrdir)/ruby/internal/glob.h
+enc_raise.o: $(hdrdir)/ruby/internal/globals.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/attribute.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/builtin.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/extension.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/feature.h
+enc_raise.o: $(hdrdir)/ruby/internal/has/warning.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/array.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/bignum.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/class.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/compar.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/complex.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/cont.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/dir.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/enum.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/error.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/eval.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/file.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/gc.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/hash.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/io.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/load.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/marshal.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/numeric.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/object.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/parse.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/proc.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/process.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/random.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/range.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/rational.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/re.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/ruby.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/select.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/signal.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/string.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/struct.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/thread.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/time.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/variable.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/vm.h
+enc_raise.o: $(hdrdir)/ruby/internal/interpreter.h
+enc_raise.o: $(hdrdir)/ruby/internal/iterator.h
+enc_raise.o: $(hdrdir)/ruby/internal/memory.h
+enc_raise.o: $(hdrdir)/ruby/internal/method.h
+enc_raise.o: $(hdrdir)/ruby/internal/module.h
+enc_raise.o: $(hdrdir)/ruby/internal/newobj.h
+enc_raise.o: $(hdrdir)/ruby/internal/rgengc.h
+enc_raise.o: $(hdrdir)/ruby/internal/scan_args.h
+enc_raise.o: $(hdrdir)/ruby/internal/special_consts.h
+enc_raise.o: $(hdrdir)/ruby/internal/static_assert.h
+enc_raise.o: $(hdrdir)/ruby/internal/stdalign.h
+enc_raise.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_raise.o: $(hdrdir)/ruby/internal/symbol.h
+enc_raise.o: $(hdrdir)/ruby/internal/token_paste.h
+enc_raise.o: $(hdrdir)/ruby/internal/value.h
+enc_raise.o: $(hdrdir)/ruby/internal/value_type.h
+enc_raise.o: $(hdrdir)/ruby/internal/variable.h
+enc_raise.o: $(hdrdir)/ruby/internal/warning_push.h
+enc_raise.o: $(hdrdir)/ruby/internal/xmalloc.h
enc_raise.o: $(hdrdir)/ruby/assert.h
enc_raise.o: $(hdrdir)/ruby/backward.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/assume.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/attributes.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/bool.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/limits.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/long_long.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enc_raise.o: $(hdrdir)/ruby/backward/2/stdarg.h
enc_raise.o: $(hdrdir)/ruby/defines.h
enc_raise.o: $(hdrdir)/ruby/encoding.h
enc_raise.o: $(hdrdir)/ruby/intern.h
@@ -28,8 +326,157 @@ enc_raise.o: enc_raise.c
ensured.o: $(RUBY_EXTCONF_H)
ensured.o: $(arch_hdrdir)/ruby/config.h
ensured.o: $(hdrdir)/ruby.h
+ensured.o: $(hdrdir)/ruby/internal/anyargs.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ensured.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ensured.o: $(hdrdir)/ruby/internal/assume.h
+ensured.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ensured.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ensured.o: $(hdrdir)/ruby/internal/attr/cold.h
+ensured.o: $(hdrdir)/ruby/internal/attr/const.h
+ensured.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ensured.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ensured.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ensured.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ensured.o: $(hdrdir)/ruby/internal/attr/error.h
+ensured.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ensured.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ensured.o: $(hdrdir)/ruby/internal/attr/format.h
+ensured.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ensured.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ensured.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ensured.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ensured.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ensured.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ensured.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ensured.o: $(hdrdir)/ruby/internal/attr/pure.h
+ensured.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ensured.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ensured.o: $(hdrdir)/ruby/internal/attr/warning.h
+ensured.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ensured.o: $(hdrdir)/ruby/internal/cast.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ensured.o: $(hdrdir)/ruby/internal/compiler_since.h
+ensured.o: $(hdrdir)/ruby/internal/config.h
+ensured.o: $(hdrdir)/ruby/internal/constant_p.h
+ensured.o: $(hdrdir)/ruby/internal/core.h
+ensured.o: $(hdrdir)/ruby/internal/core/rarray.h
+ensured.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ensured.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ensured.o: $(hdrdir)/ruby/internal/core/rclass.h
+ensured.o: $(hdrdir)/ruby/internal/core/rdata.h
+ensured.o: $(hdrdir)/ruby/internal/core/rfile.h
+ensured.o: $(hdrdir)/ruby/internal/core/rhash.h
+ensured.o: $(hdrdir)/ruby/internal/core/robject.h
+ensured.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ensured.o: $(hdrdir)/ruby/internal/core/rstring.h
+ensured.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ensured.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ensured.o: $(hdrdir)/ruby/internal/ctype.h
+ensured.o: $(hdrdir)/ruby/internal/dllexport.h
+ensured.o: $(hdrdir)/ruby/internal/dosish.h
+ensured.o: $(hdrdir)/ruby/internal/error.h
+ensured.o: $(hdrdir)/ruby/internal/eval.h
+ensured.o: $(hdrdir)/ruby/internal/event.h
+ensured.o: $(hdrdir)/ruby/internal/fl_type.h
+ensured.o: $(hdrdir)/ruby/internal/gc.h
+ensured.o: $(hdrdir)/ruby/internal/glob.h
+ensured.o: $(hdrdir)/ruby/internal/globals.h
+ensured.o: $(hdrdir)/ruby/internal/has/attribute.h
+ensured.o: $(hdrdir)/ruby/internal/has/builtin.h
+ensured.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ensured.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ensured.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ensured.o: $(hdrdir)/ruby/internal/has/extension.h
+ensured.o: $(hdrdir)/ruby/internal/has/feature.h
+ensured.o: $(hdrdir)/ruby/internal/has/warning.h
+ensured.o: $(hdrdir)/ruby/internal/intern/array.h
+ensured.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ensured.o: $(hdrdir)/ruby/internal/intern/class.h
+ensured.o: $(hdrdir)/ruby/internal/intern/compar.h
+ensured.o: $(hdrdir)/ruby/internal/intern/complex.h
+ensured.o: $(hdrdir)/ruby/internal/intern/cont.h
+ensured.o: $(hdrdir)/ruby/internal/intern/dir.h
+ensured.o: $(hdrdir)/ruby/internal/intern/enum.h
+ensured.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ensured.o: $(hdrdir)/ruby/internal/intern/error.h
+ensured.o: $(hdrdir)/ruby/internal/intern/eval.h
+ensured.o: $(hdrdir)/ruby/internal/intern/file.h
+ensured.o: $(hdrdir)/ruby/internal/intern/gc.h
+ensured.o: $(hdrdir)/ruby/internal/intern/hash.h
+ensured.o: $(hdrdir)/ruby/internal/intern/io.h
+ensured.o: $(hdrdir)/ruby/internal/intern/load.h
+ensured.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ensured.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ensured.o: $(hdrdir)/ruby/internal/intern/object.h
+ensured.o: $(hdrdir)/ruby/internal/intern/parse.h
+ensured.o: $(hdrdir)/ruby/internal/intern/proc.h
+ensured.o: $(hdrdir)/ruby/internal/intern/process.h
+ensured.o: $(hdrdir)/ruby/internal/intern/random.h
+ensured.o: $(hdrdir)/ruby/internal/intern/range.h
+ensured.o: $(hdrdir)/ruby/internal/intern/rational.h
+ensured.o: $(hdrdir)/ruby/internal/intern/re.h
+ensured.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ensured.o: $(hdrdir)/ruby/internal/intern/select.h
+ensured.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ensured.o: $(hdrdir)/ruby/internal/intern/signal.h
+ensured.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ensured.o: $(hdrdir)/ruby/internal/intern/string.h
+ensured.o: $(hdrdir)/ruby/internal/intern/struct.h
+ensured.o: $(hdrdir)/ruby/internal/intern/thread.h
+ensured.o: $(hdrdir)/ruby/internal/intern/time.h
+ensured.o: $(hdrdir)/ruby/internal/intern/variable.h
+ensured.o: $(hdrdir)/ruby/internal/intern/vm.h
+ensured.o: $(hdrdir)/ruby/internal/interpreter.h
+ensured.o: $(hdrdir)/ruby/internal/iterator.h
+ensured.o: $(hdrdir)/ruby/internal/memory.h
+ensured.o: $(hdrdir)/ruby/internal/method.h
+ensured.o: $(hdrdir)/ruby/internal/module.h
+ensured.o: $(hdrdir)/ruby/internal/newobj.h
+ensured.o: $(hdrdir)/ruby/internal/rgengc.h
+ensured.o: $(hdrdir)/ruby/internal/scan_args.h
+ensured.o: $(hdrdir)/ruby/internal/special_consts.h
+ensured.o: $(hdrdir)/ruby/internal/static_assert.h
+ensured.o: $(hdrdir)/ruby/internal/stdalign.h
+ensured.o: $(hdrdir)/ruby/internal/stdbool.h
+ensured.o: $(hdrdir)/ruby/internal/symbol.h
+ensured.o: $(hdrdir)/ruby/internal/token_paste.h
+ensured.o: $(hdrdir)/ruby/internal/value.h
+ensured.o: $(hdrdir)/ruby/internal/value_type.h
+ensured.o: $(hdrdir)/ruby/internal/variable.h
+ensured.o: $(hdrdir)/ruby/internal/warning_push.h
+ensured.o: $(hdrdir)/ruby/internal/xmalloc.h
ensured.o: $(hdrdir)/ruby/assert.h
ensured.o: $(hdrdir)/ruby/backward.h
+ensured.o: $(hdrdir)/ruby/backward/2/assume.h
+ensured.o: $(hdrdir)/ruby/backward/2/attributes.h
+ensured.o: $(hdrdir)/ruby/backward/2/bool.h
+ensured.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ensured.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ensured.o: $(hdrdir)/ruby/backward/2/limits.h
+ensured.o: $(hdrdir)/ruby/backward/2/long_long.h
+ensured.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ensured.o: $(hdrdir)/ruby/backward/2/stdarg.h
ensured.o: $(hdrdir)/ruby/defines.h
ensured.o: $(hdrdir)/ruby/intern.h
ensured.o: $(hdrdir)/ruby/missing.h
@@ -40,8 +487,157 @@ ensured.o: ensured.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/fatal/depend b/ext/-test-/fatal/depend
index c74360fdf9..bb2e61a51f 100644
--- a/ext/-test-/fatal/depend
+++ b/ext/-test-/fatal/depend
@@ -2,8 +2,157 @@
rb_fatal.o: $(RUBY_EXTCONF_H)
rb_fatal.o: $(arch_hdrdir)/ruby/config.h
rb_fatal.o: $(hdrdir)/ruby.h
+rb_fatal.o: $(hdrdir)/ruby/internal/anyargs.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rb_fatal.o: $(hdrdir)/ruby/internal/assume.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/cold.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/const.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/error.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/format.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/pure.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/warning.h
+rb_fatal.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rb_fatal.o: $(hdrdir)/ruby/internal/cast.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rb_fatal.o: $(hdrdir)/ruby/internal/compiler_since.h
+rb_fatal.o: $(hdrdir)/ruby/internal/config.h
+rb_fatal.o: $(hdrdir)/ruby/internal/constant_p.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rarray.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rclass.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rdata.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rfile.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rhash.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/robject.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rstring.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rb_fatal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rb_fatal.o: $(hdrdir)/ruby/internal/ctype.h
+rb_fatal.o: $(hdrdir)/ruby/internal/dllexport.h
+rb_fatal.o: $(hdrdir)/ruby/internal/dosish.h
+rb_fatal.o: $(hdrdir)/ruby/internal/error.h
+rb_fatal.o: $(hdrdir)/ruby/internal/eval.h
+rb_fatal.o: $(hdrdir)/ruby/internal/event.h
+rb_fatal.o: $(hdrdir)/ruby/internal/fl_type.h
+rb_fatal.o: $(hdrdir)/ruby/internal/gc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/glob.h
+rb_fatal.o: $(hdrdir)/ruby/internal/globals.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/attribute.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/builtin.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/extension.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/feature.h
+rb_fatal.o: $(hdrdir)/ruby/internal/has/warning.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/array.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/class.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/compar.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/complex.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/cont.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/dir.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/enum.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/error.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/eval.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/file.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/gc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/hash.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/io.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/load.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/object.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/parse.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/proc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/process.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/random.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/range.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/rational.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/re.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/select.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/signal.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/string.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/struct.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/thread.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/time.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/variable.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/vm.h
+rb_fatal.o: $(hdrdir)/ruby/internal/interpreter.h
+rb_fatal.o: $(hdrdir)/ruby/internal/iterator.h
+rb_fatal.o: $(hdrdir)/ruby/internal/memory.h
+rb_fatal.o: $(hdrdir)/ruby/internal/method.h
+rb_fatal.o: $(hdrdir)/ruby/internal/module.h
+rb_fatal.o: $(hdrdir)/ruby/internal/newobj.h
+rb_fatal.o: $(hdrdir)/ruby/internal/rgengc.h
+rb_fatal.o: $(hdrdir)/ruby/internal/scan_args.h
+rb_fatal.o: $(hdrdir)/ruby/internal/special_consts.h
+rb_fatal.o: $(hdrdir)/ruby/internal/static_assert.h
+rb_fatal.o: $(hdrdir)/ruby/internal/stdalign.h
+rb_fatal.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_fatal.o: $(hdrdir)/ruby/internal/symbol.h
+rb_fatal.o: $(hdrdir)/ruby/internal/token_paste.h
+rb_fatal.o: $(hdrdir)/ruby/internal/value.h
+rb_fatal.o: $(hdrdir)/ruby/internal/value_type.h
+rb_fatal.o: $(hdrdir)/ruby/internal/variable.h
+rb_fatal.o: $(hdrdir)/ruby/internal/warning_push.h
+rb_fatal.o: $(hdrdir)/ruby/internal/xmalloc.h
rb_fatal.o: $(hdrdir)/ruby/assert.h
rb_fatal.o: $(hdrdir)/ruby/backward.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_fatal.o: $(hdrdir)/ruby/backward/2/stdarg.h
rb_fatal.o: $(hdrdir)/ruby/defines.h
rb_fatal.o: $(hdrdir)/ruby/intern.h
rb_fatal.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/file/depend b/ext/-test-/file/depend
index afdf116a9d..12b0bbd825 100644
--- a/ext/-test-/file/depend
+++ b/ext/-test-/file/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
fs.o: $(RUBY_EXTCONF_H)
fs.o: $(arch_hdrdir)/ruby/config.h
+fs.o: $(hdrdir)/ruby/internal/anyargs.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+fs.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+fs.o: $(hdrdir)/ruby/internal/assume.h
+fs.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+fs.o: $(hdrdir)/ruby/internal/attr/artificial.h
+fs.o: $(hdrdir)/ruby/internal/attr/cold.h
+fs.o: $(hdrdir)/ruby/internal/attr/const.h
+fs.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+fs.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+fs.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+fs.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+fs.o: $(hdrdir)/ruby/internal/attr/error.h
+fs.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+fs.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+fs.o: $(hdrdir)/ruby/internal/attr/format.h
+fs.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+fs.o: $(hdrdir)/ruby/internal/attr/noalias.h
+fs.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+fs.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+fs.o: $(hdrdir)/ruby/internal/attr/noinline.h
+fs.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+fs.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+fs.o: $(hdrdir)/ruby/internal/attr/pure.h
+fs.o: $(hdrdir)/ruby/internal/attr/restrict.h
+fs.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+fs.o: $(hdrdir)/ruby/internal/attr/warning.h
+fs.o: $(hdrdir)/ruby/internal/attr/weakref.h
+fs.o: $(hdrdir)/ruby/internal/cast.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+fs.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+fs.o: $(hdrdir)/ruby/internal/compiler_since.h
+fs.o: $(hdrdir)/ruby/internal/config.h
+fs.o: $(hdrdir)/ruby/internal/constant_p.h
+fs.o: $(hdrdir)/ruby/internal/core.h
+fs.o: $(hdrdir)/ruby/internal/core/rarray.h
+fs.o: $(hdrdir)/ruby/internal/core/rbasic.h
+fs.o: $(hdrdir)/ruby/internal/core/rbignum.h
+fs.o: $(hdrdir)/ruby/internal/core/rclass.h
+fs.o: $(hdrdir)/ruby/internal/core/rdata.h
+fs.o: $(hdrdir)/ruby/internal/core/rfile.h
+fs.o: $(hdrdir)/ruby/internal/core/rhash.h
+fs.o: $(hdrdir)/ruby/internal/core/robject.h
+fs.o: $(hdrdir)/ruby/internal/core/rregexp.h
+fs.o: $(hdrdir)/ruby/internal/core/rstring.h
+fs.o: $(hdrdir)/ruby/internal/core/rstruct.h
+fs.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+fs.o: $(hdrdir)/ruby/internal/ctype.h
+fs.o: $(hdrdir)/ruby/internal/dllexport.h
+fs.o: $(hdrdir)/ruby/internal/dosish.h
+fs.o: $(hdrdir)/ruby/internal/error.h
+fs.o: $(hdrdir)/ruby/internal/eval.h
+fs.o: $(hdrdir)/ruby/internal/event.h
+fs.o: $(hdrdir)/ruby/internal/fl_type.h
+fs.o: $(hdrdir)/ruby/internal/gc.h
+fs.o: $(hdrdir)/ruby/internal/glob.h
+fs.o: $(hdrdir)/ruby/internal/globals.h
+fs.o: $(hdrdir)/ruby/internal/has/attribute.h
+fs.o: $(hdrdir)/ruby/internal/has/builtin.h
+fs.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+fs.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+fs.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+fs.o: $(hdrdir)/ruby/internal/has/extension.h
+fs.o: $(hdrdir)/ruby/internal/has/feature.h
+fs.o: $(hdrdir)/ruby/internal/has/warning.h
+fs.o: $(hdrdir)/ruby/internal/intern/array.h
+fs.o: $(hdrdir)/ruby/internal/intern/bignum.h
+fs.o: $(hdrdir)/ruby/internal/intern/class.h
+fs.o: $(hdrdir)/ruby/internal/intern/compar.h
+fs.o: $(hdrdir)/ruby/internal/intern/complex.h
+fs.o: $(hdrdir)/ruby/internal/intern/cont.h
+fs.o: $(hdrdir)/ruby/internal/intern/dir.h
+fs.o: $(hdrdir)/ruby/internal/intern/enum.h
+fs.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+fs.o: $(hdrdir)/ruby/internal/intern/error.h
+fs.o: $(hdrdir)/ruby/internal/intern/eval.h
+fs.o: $(hdrdir)/ruby/internal/intern/file.h
+fs.o: $(hdrdir)/ruby/internal/intern/gc.h
+fs.o: $(hdrdir)/ruby/internal/intern/hash.h
+fs.o: $(hdrdir)/ruby/internal/intern/io.h
+fs.o: $(hdrdir)/ruby/internal/intern/load.h
+fs.o: $(hdrdir)/ruby/internal/intern/marshal.h
+fs.o: $(hdrdir)/ruby/internal/intern/numeric.h
+fs.o: $(hdrdir)/ruby/internal/intern/object.h
+fs.o: $(hdrdir)/ruby/internal/intern/parse.h
+fs.o: $(hdrdir)/ruby/internal/intern/proc.h
+fs.o: $(hdrdir)/ruby/internal/intern/process.h
+fs.o: $(hdrdir)/ruby/internal/intern/random.h
+fs.o: $(hdrdir)/ruby/internal/intern/range.h
+fs.o: $(hdrdir)/ruby/internal/intern/rational.h
+fs.o: $(hdrdir)/ruby/internal/intern/re.h
+fs.o: $(hdrdir)/ruby/internal/intern/ruby.h
+fs.o: $(hdrdir)/ruby/internal/intern/select.h
+fs.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fs.o: $(hdrdir)/ruby/internal/intern/signal.h
+fs.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+fs.o: $(hdrdir)/ruby/internal/intern/string.h
+fs.o: $(hdrdir)/ruby/internal/intern/struct.h
+fs.o: $(hdrdir)/ruby/internal/intern/thread.h
+fs.o: $(hdrdir)/ruby/internal/intern/time.h
+fs.o: $(hdrdir)/ruby/internal/intern/variable.h
+fs.o: $(hdrdir)/ruby/internal/intern/vm.h
+fs.o: $(hdrdir)/ruby/internal/interpreter.h
+fs.o: $(hdrdir)/ruby/internal/iterator.h
+fs.o: $(hdrdir)/ruby/internal/memory.h
+fs.o: $(hdrdir)/ruby/internal/method.h
+fs.o: $(hdrdir)/ruby/internal/module.h
+fs.o: $(hdrdir)/ruby/internal/newobj.h
+fs.o: $(hdrdir)/ruby/internal/rgengc.h
+fs.o: $(hdrdir)/ruby/internal/scan_args.h
+fs.o: $(hdrdir)/ruby/internal/special_consts.h
+fs.o: $(hdrdir)/ruby/internal/static_assert.h
+fs.o: $(hdrdir)/ruby/internal/stdalign.h
+fs.o: $(hdrdir)/ruby/internal/stdbool.h
+fs.o: $(hdrdir)/ruby/internal/symbol.h
+fs.o: $(hdrdir)/ruby/internal/token_paste.h
+fs.o: $(hdrdir)/ruby/internal/value.h
+fs.o: $(hdrdir)/ruby/internal/value_type.h
+fs.o: $(hdrdir)/ruby/internal/variable.h
+fs.o: $(hdrdir)/ruby/internal/warning_push.h
+fs.o: $(hdrdir)/ruby/internal/xmalloc.h
fs.o: $(hdrdir)/ruby/assert.h
fs.o: $(hdrdir)/ruby/backward.h
+fs.o: $(hdrdir)/ruby/backward/2/assume.h
+fs.o: $(hdrdir)/ruby/backward/2/attributes.h
+fs.o: $(hdrdir)/ruby/backward/2/bool.h
+fs.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+fs.o: $(hdrdir)/ruby/backward/2/inttypes.h
+fs.o: $(hdrdir)/ruby/backward/2/limits.h
+fs.o: $(hdrdir)/ruby/backward/2/long_long.h
+fs.o: $(hdrdir)/ruby/backward/2/stdalign.h
+fs.o: $(hdrdir)/ruby/backward/2/stdarg.h
fs.o: $(hdrdir)/ruby/defines.h
fs.o: $(hdrdir)/ruby/encoding.h
fs.o: $(hdrdir)/ruby/intern.h
@@ -17,8 +166,157 @@ fs.o: fs.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -28,8 +326,157 @@ init.o: $(hdrdir)/ruby/subst.h
init.o: init.c
stat.o: $(RUBY_EXTCONF_H)
stat.o: $(arch_hdrdir)/ruby/config.h
+stat.o: $(hdrdir)/ruby/internal/anyargs.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stat.o: $(hdrdir)/ruby/internal/assume.h
+stat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stat.o: $(hdrdir)/ruby/internal/attr/cold.h
+stat.o: $(hdrdir)/ruby/internal/attr/const.h
+stat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stat.o: $(hdrdir)/ruby/internal/attr/error.h
+stat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stat.o: $(hdrdir)/ruby/internal/attr/format.h
+stat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stat.o: $(hdrdir)/ruby/internal/attr/pure.h
+stat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stat.o: $(hdrdir)/ruby/internal/attr/warning.h
+stat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stat.o: $(hdrdir)/ruby/internal/cast.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stat.o: $(hdrdir)/ruby/internal/compiler_since.h
+stat.o: $(hdrdir)/ruby/internal/config.h
+stat.o: $(hdrdir)/ruby/internal/constant_p.h
+stat.o: $(hdrdir)/ruby/internal/core.h
+stat.o: $(hdrdir)/ruby/internal/core/rarray.h
+stat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stat.o: $(hdrdir)/ruby/internal/core/rclass.h
+stat.o: $(hdrdir)/ruby/internal/core/rdata.h
+stat.o: $(hdrdir)/ruby/internal/core/rfile.h
+stat.o: $(hdrdir)/ruby/internal/core/rhash.h
+stat.o: $(hdrdir)/ruby/internal/core/robject.h
+stat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stat.o: $(hdrdir)/ruby/internal/core/rstring.h
+stat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stat.o: $(hdrdir)/ruby/internal/ctype.h
+stat.o: $(hdrdir)/ruby/internal/dllexport.h
+stat.o: $(hdrdir)/ruby/internal/dosish.h
+stat.o: $(hdrdir)/ruby/internal/error.h
+stat.o: $(hdrdir)/ruby/internal/eval.h
+stat.o: $(hdrdir)/ruby/internal/event.h
+stat.o: $(hdrdir)/ruby/internal/fl_type.h
+stat.o: $(hdrdir)/ruby/internal/gc.h
+stat.o: $(hdrdir)/ruby/internal/glob.h
+stat.o: $(hdrdir)/ruby/internal/globals.h
+stat.o: $(hdrdir)/ruby/internal/has/attribute.h
+stat.o: $(hdrdir)/ruby/internal/has/builtin.h
+stat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stat.o: $(hdrdir)/ruby/internal/has/extension.h
+stat.o: $(hdrdir)/ruby/internal/has/feature.h
+stat.o: $(hdrdir)/ruby/internal/has/warning.h
+stat.o: $(hdrdir)/ruby/internal/intern/array.h
+stat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stat.o: $(hdrdir)/ruby/internal/intern/class.h
+stat.o: $(hdrdir)/ruby/internal/intern/compar.h
+stat.o: $(hdrdir)/ruby/internal/intern/complex.h
+stat.o: $(hdrdir)/ruby/internal/intern/cont.h
+stat.o: $(hdrdir)/ruby/internal/intern/dir.h
+stat.o: $(hdrdir)/ruby/internal/intern/enum.h
+stat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stat.o: $(hdrdir)/ruby/internal/intern/error.h
+stat.o: $(hdrdir)/ruby/internal/intern/eval.h
+stat.o: $(hdrdir)/ruby/internal/intern/file.h
+stat.o: $(hdrdir)/ruby/internal/intern/gc.h
+stat.o: $(hdrdir)/ruby/internal/intern/hash.h
+stat.o: $(hdrdir)/ruby/internal/intern/io.h
+stat.o: $(hdrdir)/ruby/internal/intern/load.h
+stat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stat.o: $(hdrdir)/ruby/internal/intern/object.h
+stat.o: $(hdrdir)/ruby/internal/intern/parse.h
+stat.o: $(hdrdir)/ruby/internal/intern/proc.h
+stat.o: $(hdrdir)/ruby/internal/intern/process.h
+stat.o: $(hdrdir)/ruby/internal/intern/random.h
+stat.o: $(hdrdir)/ruby/internal/intern/range.h
+stat.o: $(hdrdir)/ruby/internal/intern/rational.h
+stat.o: $(hdrdir)/ruby/internal/intern/re.h
+stat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stat.o: $(hdrdir)/ruby/internal/intern/select.h
+stat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stat.o: $(hdrdir)/ruby/internal/intern/signal.h
+stat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stat.o: $(hdrdir)/ruby/internal/intern/string.h
+stat.o: $(hdrdir)/ruby/internal/intern/struct.h
+stat.o: $(hdrdir)/ruby/internal/intern/thread.h
+stat.o: $(hdrdir)/ruby/internal/intern/time.h
+stat.o: $(hdrdir)/ruby/internal/intern/variable.h
+stat.o: $(hdrdir)/ruby/internal/intern/vm.h
+stat.o: $(hdrdir)/ruby/internal/interpreter.h
+stat.o: $(hdrdir)/ruby/internal/iterator.h
+stat.o: $(hdrdir)/ruby/internal/memory.h
+stat.o: $(hdrdir)/ruby/internal/method.h
+stat.o: $(hdrdir)/ruby/internal/module.h
+stat.o: $(hdrdir)/ruby/internal/newobj.h
+stat.o: $(hdrdir)/ruby/internal/rgengc.h
+stat.o: $(hdrdir)/ruby/internal/scan_args.h
+stat.o: $(hdrdir)/ruby/internal/special_consts.h
+stat.o: $(hdrdir)/ruby/internal/static_assert.h
+stat.o: $(hdrdir)/ruby/internal/stdalign.h
+stat.o: $(hdrdir)/ruby/internal/stdbool.h
+stat.o: $(hdrdir)/ruby/internal/symbol.h
+stat.o: $(hdrdir)/ruby/internal/token_paste.h
+stat.o: $(hdrdir)/ruby/internal/value.h
+stat.o: $(hdrdir)/ruby/internal/value_type.h
+stat.o: $(hdrdir)/ruby/internal/variable.h
+stat.o: $(hdrdir)/ruby/internal/warning_push.h
+stat.o: $(hdrdir)/ruby/internal/xmalloc.h
stat.o: $(hdrdir)/ruby/assert.h
stat.o: $(hdrdir)/ruby/backward.h
+stat.o: $(hdrdir)/ruby/backward/2/assume.h
+stat.o: $(hdrdir)/ruby/backward/2/attributes.h
+stat.o: $(hdrdir)/ruby/backward/2/bool.h
+stat.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+stat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stat.o: $(hdrdir)/ruby/backward/2/limits.h
+stat.o: $(hdrdir)/ruby/backward/2/long_long.h
+stat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stat.o: $(hdrdir)/ruby/backward/2/stdarg.h
stat.o: $(hdrdir)/ruby/defines.h
stat.o: $(hdrdir)/ruby/encoding.h
stat.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/-test-/float/depend b/ext/-test-/float/depend
index 6007bd3c0b..066f008783 100644
--- a/ext/-test-/float/depend
+++ b/ext/-test-/float/depend
@@ -5,8 +5,157 @@ nextafter.o: nextafter.c $(top_srcdir)/missing/nextafter.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -17,8 +166,157 @@ init.o: init.c
nextafter.o: $(RUBY_EXTCONF_H)
nextafter.o: $(arch_hdrdir)/ruby/config.h
nextafter.o: $(hdrdir)/ruby.h
+nextafter.o: $(hdrdir)/ruby/internal/anyargs.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+nextafter.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+nextafter.o: $(hdrdir)/ruby/internal/assume.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/artificial.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/cold.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/const.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/error.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/format.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/noalias.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/noinline.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/pure.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/restrict.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/warning.h
+nextafter.o: $(hdrdir)/ruby/internal/attr/weakref.h
+nextafter.o: $(hdrdir)/ruby/internal/cast.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+nextafter.o: $(hdrdir)/ruby/internal/compiler_since.h
+nextafter.o: $(hdrdir)/ruby/internal/config.h
+nextafter.o: $(hdrdir)/ruby/internal/constant_p.h
+nextafter.o: $(hdrdir)/ruby/internal/core.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rarray.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rbasic.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rbignum.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rclass.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rdata.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rfile.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rhash.h
+nextafter.o: $(hdrdir)/ruby/internal/core/robject.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rregexp.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rstring.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rstruct.h
+nextafter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+nextafter.o: $(hdrdir)/ruby/internal/ctype.h
+nextafter.o: $(hdrdir)/ruby/internal/dllexport.h
+nextafter.o: $(hdrdir)/ruby/internal/dosish.h
+nextafter.o: $(hdrdir)/ruby/internal/error.h
+nextafter.o: $(hdrdir)/ruby/internal/eval.h
+nextafter.o: $(hdrdir)/ruby/internal/event.h
+nextafter.o: $(hdrdir)/ruby/internal/fl_type.h
+nextafter.o: $(hdrdir)/ruby/internal/gc.h
+nextafter.o: $(hdrdir)/ruby/internal/glob.h
+nextafter.o: $(hdrdir)/ruby/internal/globals.h
+nextafter.o: $(hdrdir)/ruby/internal/has/attribute.h
+nextafter.o: $(hdrdir)/ruby/internal/has/builtin.h
+nextafter.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+nextafter.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+nextafter.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+nextafter.o: $(hdrdir)/ruby/internal/has/extension.h
+nextafter.o: $(hdrdir)/ruby/internal/has/feature.h
+nextafter.o: $(hdrdir)/ruby/internal/has/warning.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/array.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/bignum.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/class.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/compar.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/complex.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/cont.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/dir.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/enum.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/error.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/eval.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/file.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/gc.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/hash.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/io.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/load.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/marshal.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/numeric.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/object.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/parse.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/proc.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/process.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/random.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/range.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/rational.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/re.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/ruby.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/select.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/signal.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/string.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/struct.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/thread.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/time.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/variable.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/vm.h
+nextafter.o: $(hdrdir)/ruby/internal/interpreter.h
+nextafter.o: $(hdrdir)/ruby/internal/iterator.h
+nextafter.o: $(hdrdir)/ruby/internal/memory.h
+nextafter.o: $(hdrdir)/ruby/internal/method.h
+nextafter.o: $(hdrdir)/ruby/internal/module.h
+nextafter.o: $(hdrdir)/ruby/internal/newobj.h
+nextafter.o: $(hdrdir)/ruby/internal/rgengc.h
+nextafter.o: $(hdrdir)/ruby/internal/scan_args.h
+nextafter.o: $(hdrdir)/ruby/internal/special_consts.h
+nextafter.o: $(hdrdir)/ruby/internal/static_assert.h
+nextafter.o: $(hdrdir)/ruby/internal/stdalign.h
+nextafter.o: $(hdrdir)/ruby/internal/stdbool.h
+nextafter.o: $(hdrdir)/ruby/internal/symbol.h
+nextafter.o: $(hdrdir)/ruby/internal/token_paste.h
+nextafter.o: $(hdrdir)/ruby/internal/value.h
+nextafter.o: $(hdrdir)/ruby/internal/value_type.h
+nextafter.o: $(hdrdir)/ruby/internal/variable.h
+nextafter.o: $(hdrdir)/ruby/internal/warning_push.h
+nextafter.o: $(hdrdir)/ruby/internal/xmalloc.h
nextafter.o: $(hdrdir)/ruby/assert.h
nextafter.o: $(hdrdir)/ruby/backward.h
+nextafter.o: $(hdrdir)/ruby/backward/2/assume.h
+nextafter.o: $(hdrdir)/ruby/backward/2/attributes.h
+nextafter.o: $(hdrdir)/ruby/backward/2/bool.h
+nextafter.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+nextafter.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nextafter.o: $(hdrdir)/ruby/backward/2/limits.h
+nextafter.o: $(hdrdir)/ruby/backward/2/long_long.h
+nextafter.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nextafter.o: $(hdrdir)/ruby/backward/2/stdarg.h
nextafter.o: $(hdrdir)/ruby/defines.h
nextafter.o: $(hdrdir)/ruby/intern.h
nextafter.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/funcall/depend b/ext/-test-/funcall/depend
index a5f43a8046..1fdf867fac 100644
--- a/ext/-test-/funcall/depend
+++ b/ext/-test-/funcall/depend
@@ -2,8 +2,157 @@
funcall.o: $(RUBY_EXTCONF_H)
funcall.o: $(arch_hdrdir)/ruby/config.h
funcall.o: $(hdrdir)/ruby.h
+funcall.o: $(hdrdir)/ruby/internal/anyargs.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+funcall.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+funcall.o: $(hdrdir)/ruby/internal/assume.h
+funcall.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+funcall.o: $(hdrdir)/ruby/internal/attr/artificial.h
+funcall.o: $(hdrdir)/ruby/internal/attr/cold.h
+funcall.o: $(hdrdir)/ruby/internal/attr/const.h
+funcall.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+funcall.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+funcall.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+funcall.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+funcall.o: $(hdrdir)/ruby/internal/attr/error.h
+funcall.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+funcall.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+funcall.o: $(hdrdir)/ruby/internal/attr/format.h
+funcall.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+funcall.o: $(hdrdir)/ruby/internal/attr/noalias.h
+funcall.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+funcall.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+funcall.o: $(hdrdir)/ruby/internal/attr/noinline.h
+funcall.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+funcall.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+funcall.o: $(hdrdir)/ruby/internal/attr/pure.h
+funcall.o: $(hdrdir)/ruby/internal/attr/restrict.h
+funcall.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+funcall.o: $(hdrdir)/ruby/internal/attr/warning.h
+funcall.o: $(hdrdir)/ruby/internal/attr/weakref.h
+funcall.o: $(hdrdir)/ruby/internal/cast.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+funcall.o: $(hdrdir)/ruby/internal/compiler_since.h
+funcall.o: $(hdrdir)/ruby/internal/config.h
+funcall.o: $(hdrdir)/ruby/internal/constant_p.h
+funcall.o: $(hdrdir)/ruby/internal/core.h
+funcall.o: $(hdrdir)/ruby/internal/core/rarray.h
+funcall.o: $(hdrdir)/ruby/internal/core/rbasic.h
+funcall.o: $(hdrdir)/ruby/internal/core/rbignum.h
+funcall.o: $(hdrdir)/ruby/internal/core/rclass.h
+funcall.o: $(hdrdir)/ruby/internal/core/rdata.h
+funcall.o: $(hdrdir)/ruby/internal/core/rfile.h
+funcall.o: $(hdrdir)/ruby/internal/core/rhash.h
+funcall.o: $(hdrdir)/ruby/internal/core/robject.h
+funcall.o: $(hdrdir)/ruby/internal/core/rregexp.h
+funcall.o: $(hdrdir)/ruby/internal/core/rstring.h
+funcall.o: $(hdrdir)/ruby/internal/core/rstruct.h
+funcall.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+funcall.o: $(hdrdir)/ruby/internal/ctype.h
+funcall.o: $(hdrdir)/ruby/internal/dllexport.h
+funcall.o: $(hdrdir)/ruby/internal/dosish.h
+funcall.o: $(hdrdir)/ruby/internal/error.h
+funcall.o: $(hdrdir)/ruby/internal/eval.h
+funcall.o: $(hdrdir)/ruby/internal/event.h
+funcall.o: $(hdrdir)/ruby/internal/fl_type.h
+funcall.o: $(hdrdir)/ruby/internal/gc.h
+funcall.o: $(hdrdir)/ruby/internal/glob.h
+funcall.o: $(hdrdir)/ruby/internal/globals.h
+funcall.o: $(hdrdir)/ruby/internal/has/attribute.h
+funcall.o: $(hdrdir)/ruby/internal/has/builtin.h
+funcall.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+funcall.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+funcall.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+funcall.o: $(hdrdir)/ruby/internal/has/extension.h
+funcall.o: $(hdrdir)/ruby/internal/has/feature.h
+funcall.o: $(hdrdir)/ruby/internal/has/warning.h
+funcall.o: $(hdrdir)/ruby/internal/intern/array.h
+funcall.o: $(hdrdir)/ruby/internal/intern/bignum.h
+funcall.o: $(hdrdir)/ruby/internal/intern/class.h
+funcall.o: $(hdrdir)/ruby/internal/intern/compar.h
+funcall.o: $(hdrdir)/ruby/internal/intern/complex.h
+funcall.o: $(hdrdir)/ruby/internal/intern/cont.h
+funcall.o: $(hdrdir)/ruby/internal/intern/dir.h
+funcall.o: $(hdrdir)/ruby/internal/intern/enum.h
+funcall.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+funcall.o: $(hdrdir)/ruby/internal/intern/error.h
+funcall.o: $(hdrdir)/ruby/internal/intern/eval.h
+funcall.o: $(hdrdir)/ruby/internal/intern/file.h
+funcall.o: $(hdrdir)/ruby/internal/intern/gc.h
+funcall.o: $(hdrdir)/ruby/internal/intern/hash.h
+funcall.o: $(hdrdir)/ruby/internal/intern/io.h
+funcall.o: $(hdrdir)/ruby/internal/intern/load.h
+funcall.o: $(hdrdir)/ruby/internal/intern/marshal.h
+funcall.o: $(hdrdir)/ruby/internal/intern/numeric.h
+funcall.o: $(hdrdir)/ruby/internal/intern/object.h
+funcall.o: $(hdrdir)/ruby/internal/intern/parse.h
+funcall.o: $(hdrdir)/ruby/internal/intern/proc.h
+funcall.o: $(hdrdir)/ruby/internal/intern/process.h
+funcall.o: $(hdrdir)/ruby/internal/intern/random.h
+funcall.o: $(hdrdir)/ruby/internal/intern/range.h
+funcall.o: $(hdrdir)/ruby/internal/intern/rational.h
+funcall.o: $(hdrdir)/ruby/internal/intern/re.h
+funcall.o: $(hdrdir)/ruby/internal/intern/ruby.h
+funcall.o: $(hdrdir)/ruby/internal/intern/select.h
+funcall.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+funcall.o: $(hdrdir)/ruby/internal/intern/signal.h
+funcall.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+funcall.o: $(hdrdir)/ruby/internal/intern/string.h
+funcall.o: $(hdrdir)/ruby/internal/intern/struct.h
+funcall.o: $(hdrdir)/ruby/internal/intern/thread.h
+funcall.o: $(hdrdir)/ruby/internal/intern/time.h
+funcall.o: $(hdrdir)/ruby/internal/intern/variable.h
+funcall.o: $(hdrdir)/ruby/internal/intern/vm.h
+funcall.o: $(hdrdir)/ruby/internal/interpreter.h
+funcall.o: $(hdrdir)/ruby/internal/iterator.h
+funcall.o: $(hdrdir)/ruby/internal/memory.h
+funcall.o: $(hdrdir)/ruby/internal/method.h
+funcall.o: $(hdrdir)/ruby/internal/module.h
+funcall.o: $(hdrdir)/ruby/internal/newobj.h
+funcall.o: $(hdrdir)/ruby/internal/rgengc.h
+funcall.o: $(hdrdir)/ruby/internal/scan_args.h
+funcall.o: $(hdrdir)/ruby/internal/special_consts.h
+funcall.o: $(hdrdir)/ruby/internal/static_assert.h
+funcall.o: $(hdrdir)/ruby/internal/stdalign.h
+funcall.o: $(hdrdir)/ruby/internal/stdbool.h
+funcall.o: $(hdrdir)/ruby/internal/symbol.h
+funcall.o: $(hdrdir)/ruby/internal/token_paste.h
+funcall.o: $(hdrdir)/ruby/internal/value.h
+funcall.o: $(hdrdir)/ruby/internal/value_type.h
+funcall.o: $(hdrdir)/ruby/internal/variable.h
+funcall.o: $(hdrdir)/ruby/internal/warning_push.h
+funcall.o: $(hdrdir)/ruby/internal/xmalloc.h
funcall.o: $(hdrdir)/ruby/assert.h
funcall.o: $(hdrdir)/ruby/backward.h
+funcall.o: $(hdrdir)/ruby/backward/2/assume.h
+funcall.o: $(hdrdir)/ruby/backward/2/attributes.h
+funcall.o: $(hdrdir)/ruby/backward/2/bool.h
+funcall.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+funcall.o: $(hdrdir)/ruby/backward/2/inttypes.h
+funcall.o: $(hdrdir)/ruby/backward/2/limits.h
+funcall.o: $(hdrdir)/ruby/backward/2/long_long.h
+funcall.o: $(hdrdir)/ruby/backward/2/stdalign.h
+funcall.o: $(hdrdir)/ruby/backward/2/stdarg.h
funcall.o: $(hdrdir)/ruby/defines.h
funcall.o: $(hdrdir)/ruby/intern.h
funcall.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/gvl/call_without_gvl/depend b/ext/-test-/gvl/call_without_gvl/depend
index 3d4253b977..8b606d2eb4 100644
--- a/ext/-test-/gvl/call_without_gvl/depend
+++ b/ext/-test-/gvl/call_without_gvl/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
call_without_gvl.o: $(RUBY_EXTCONF_H)
call_without_gvl.o: $(arch_hdrdir)/ruby/config.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/anyargs.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/assume.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/cold.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/const.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/error.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/format.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/pure.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/warning.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/cast.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/compiler_since.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/config.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/constant_p.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rarray.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rclass.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rdata.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rfile.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rhash.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/robject.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rstring.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/ctype.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/dllexport.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/dosish.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/error.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/eval.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/event.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/fl_type.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/gc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/glob.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/globals.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/attribute.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/builtin.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/extension.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/feature.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/has/warning.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/array.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/class.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/compar.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/complex.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/cont.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/dir.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/enum.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/error.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/eval.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/file.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/gc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/hash.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/io.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/load.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/object.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/parse.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/proc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/process.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/random.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/range.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/rational.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/re.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/signal.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/string.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/struct.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/thread.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/time.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/variable.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/vm.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/interpreter.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/iterator.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/memory.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/method.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/module.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/newobj.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/rgengc.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/scan_args.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/special_consts.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/static_assert.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/stdalign.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/stdbool.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/symbol.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/token_paste.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/value.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/value_type.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/variable.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/warning_push.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/xmalloc.h
call_without_gvl.o: $(hdrdir)/ruby/assert.h
call_without_gvl.o: $(hdrdir)/ruby/backward.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/assume.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/attributes.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/bool.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/limits.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/long_long.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+call_without_gvl.o: $(hdrdir)/ruby/backward/2/stdarg.h
call_without_gvl.o: $(hdrdir)/ruby/defines.h
call_without_gvl.o: $(hdrdir)/ruby/intern.h
call_without_gvl.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/hash/depend b/ext/-test-/hash/depend
index 5e2b8056c8..f4ea9ae5c3 100644
--- a/ext/-test-/hash/depend
+++ b/ext/-test-/hash/depend
@@ -2,8 +2,157 @@
delete.o: $(RUBY_EXTCONF_H)
delete.o: $(arch_hdrdir)/ruby/config.h
delete.o: $(hdrdir)/ruby.h
+delete.o: $(hdrdir)/ruby/internal/anyargs.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+delete.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+delete.o: $(hdrdir)/ruby/internal/assume.h
+delete.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+delete.o: $(hdrdir)/ruby/internal/attr/artificial.h
+delete.o: $(hdrdir)/ruby/internal/attr/cold.h
+delete.o: $(hdrdir)/ruby/internal/attr/const.h
+delete.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+delete.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+delete.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+delete.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+delete.o: $(hdrdir)/ruby/internal/attr/error.h
+delete.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+delete.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+delete.o: $(hdrdir)/ruby/internal/attr/format.h
+delete.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+delete.o: $(hdrdir)/ruby/internal/attr/noalias.h
+delete.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+delete.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+delete.o: $(hdrdir)/ruby/internal/attr/noinline.h
+delete.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+delete.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+delete.o: $(hdrdir)/ruby/internal/attr/pure.h
+delete.o: $(hdrdir)/ruby/internal/attr/restrict.h
+delete.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+delete.o: $(hdrdir)/ruby/internal/attr/warning.h
+delete.o: $(hdrdir)/ruby/internal/attr/weakref.h
+delete.o: $(hdrdir)/ruby/internal/cast.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+delete.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+delete.o: $(hdrdir)/ruby/internal/compiler_since.h
+delete.o: $(hdrdir)/ruby/internal/config.h
+delete.o: $(hdrdir)/ruby/internal/constant_p.h
+delete.o: $(hdrdir)/ruby/internal/core.h
+delete.o: $(hdrdir)/ruby/internal/core/rarray.h
+delete.o: $(hdrdir)/ruby/internal/core/rbasic.h
+delete.o: $(hdrdir)/ruby/internal/core/rbignum.h
+delete.o: $(hdrdir)/ruby/internal/core/rclass.h
+delete.o: $(hdrdir)/ruby/internal/core/rdata.h
+delete.o: $(hdrdir)/ruby/internal/core/rfile.h
+delete.o: $(hdrdir)/ruby/internal/core/rhash.h
+delete.o: $(hdrdir)/ruby/internal/core/robject.h
+delete.o: $(hdrdir)/ruby/internal/core/rregexp.h
+delete.o: $(hdrdir)/ruby/internal/core/rstring.h
+delete.o: $(hdrdir)/ruby/internal/core/rstruct.h
+delete.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+delete.o: $(hdrdir)/ruby/internal/ctype.h
+delete.o: $(hdrdir)/ruby/internal/dllexport.h
+delete.o: $(hdrdir)/ruby/internal/dosish.h
+delete.o: $(hdrdir)/ruby/internal/error.h
+delete.o: $(hdrdir)/ruby/internal/eval.h
+delete.o: $(hdrdir)/ruby/internal/event.h
+delete.o: $(hdrdir)/ruby/internal/fl_type.h
+delete.o: $(hdrdir)/ruby/internal/gc.h
+delete.o: $(hdrdir)/ruby/internal/glob.h
+delete.o: $(hdrdir)/ruby/internal/globals.h
+delete.o: $(hdrdir)/ruby/internal/has/attribute.h
+delete.o: $(hdrdir)/ruby/internal/has/builtin.h
+delete.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+delete.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+delete.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+delete.o: $(hdrdir)/ruby/internal/has/extension.h
+delete.o: $(hdrdir)/ruby/internal/has/feature.h
+delete.o: $(hdrdir)/ruby/internal/has/warning.h
+delete.o: $(hdrdir)/ruby/internal/intern/array.h
+delete.o: $(hdrdir)/ruby/internal/intern/bignum.h
+delete.o: $(hdrdir)/ruby/internal/intern/class.h
+delete.o: $(hdrdir)/ruby/internal/intern/compar.h
+delete.o: $(hdrdir)/ruby/internal/intern/complex.h
+delete.o: $(hdrdir)/ruby/internal/intern/cont.h
+delete.o: $(hdrdir)/ruby/internal/intern/dir.h
+delete.o: $(hdrdir)/ruby/internal/intern/enum.h
+delete.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+delete.o: $(hdrdir)/ruby/internal/intern/error.h
+delete.o: $(hdrdir)/ruby/internal/intern/eval.h
+delete.o: $(hdrdir)/ruby/internal/intern/file.h
+delete.o: $(hdrdir)/ruby/internal/intern/gc.h
+delete.o: $(hdrdir)/ruby/internal/intern/hash.h
+delete.o: $(hdrdir)/ruby/internal/intern/io.h
+delete.o: $(hdrdir)/ruby/internal/intern/load.h
+delete.o: $(hdrdir)/ruby/internal/intern/marshal.h
+delete.o: $(hdrdir)/ruby/internal/intern/numeric.h
+delete.o: $(hdrdir)/ruby/internal/intern/object.h
+delete.o: $(hdrdir)/ruby/internal/intern/parse.h
+delete.o: $(hdrdir)/ruby/internal/intern/proc.h
+delete.o: $(hdrdir)/ruby/internal/intern/process.h
+delete.o: $(hdrdir)/ruby/internal/intern/random.h
+delete.o: $(hdrdir)/ruby/internal/intern/range.h
+delete.o: $(hdrdir)/ruby/internal/intern/rational.h
+delete.o: $(hdrdir)/ruby/internal/intern/re.h
+delete.o: $(hdrdir)/ruby/internal/intern/ruby.h
+delete.o: $(hdrdir)/ruby/internal/intern/select.h
+delete.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+delete.o: $(hdrdir)/ruby/internal/intern/signal.h
+delete.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+delete.o: $(hdrdir)/ruby/internal/intern/string.h
+delete.o: $(hdrdir)/ruby/internal/intern/struct.h
+delete.o: $(hdrdir)/ruby/internal/intern/thread.h
+delete.o: $(hdrdir)/ruby/internal/intern/time.h
+delete.o: $(hdrdir)/ruby/internal/intern/variable.h
+delete.o: $(hdrdir)/ruby/internal/intern/vm.h
+delete.o: $(hdrdir)/ruby/internal/interpreter.h
+delete.o: $(hdrdir)/ruby/internal/iterator.h
+delete.o: $(hdrdir)/ruby/internal/memory.h
+delete.o: $(hdrdir)/ruby/internal/method.h
+delete.o: $(hdrdir)/ruby/internal/module.h
+delete.o: $(hdrdir)/ruby/internal/newobj.h
+delete.o: $(hdrdir)/ruby/internal/rgengc.h
+delete.o: $(hdrdir)/ruby/internal/scan_args.h
+delete.o: $(hdrdir)/ruby/internal/special_consts.h
+delete.o: $(hdrdir)/ruby/internal/static_assert.h
+delete.o: $(hdrdir)/ruby/internal/stdalign.h
+delete.o: $(hdrdir)/ruby/internal/stdbool.h
+delete.o: $(hdrdir)/ruby/internal/symbol.h
+delete.o: $(hdrdir)/ruby/internal/token_paste.h
+delete.o: $(hdrdir)/ruby/internal/value.h
+delete.o: $(hdrdir)/ruby/internal/value_type.h
+delete.o: $(hdrdir)/ruby/internal/variable.h
+delete.o: $(hdrdir)/ruby/internal/warning_push.h
+delete.o: $(hdrdir)/ruby/internal/xmalloc.h
delete.o: $(hdrdir)/ruby/assert.h
delete.o: $(hdrdir)/ruby/backward.h
+delete.o: $(hdrdir)/ruby/backward/2/assume.h
+delete.o: $(hdrdir)/ruby/backward/2/attributes.h
+delete.o: $(hdrdir)/ruby/backward/2/bool.h
+delete.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+delete.o: $(hdrdir)/ruby/backward/2/inttypes.h
+delete.o: $(hdrdir)/ruby/backward/2/limits.h
+delete.o: $(hdrdir)/ruby/backward/2/long_long.h
+delete.o: $(hdrdir)/ruby/backward/2/stdalign.h
+delete.o: $(hdrdir)/ruby/backward/2/stdarg.h
delete.o: $(hdrdir)/ruby/defines.h
delete.o: $(hdrdir)/ruby/intern.h
delete.o: $(hdrdir)/ruby/missing.h
@@ -14,8 +163,157 @@ delete.o: delete.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/integer/core_ext.c b/ext/-test-/integer/core_ext.c
index 510ba4a1e6..2062fa3afa 100644
--- a/ext/-test-/integer/core_ext.c
+++ b/ext/-test-/integer/core_ext.c
@@ -1,4 +1,4 @@
-#include "internal.h"
+#include "internal/numeric.h"
static VALUE
int_bignum_p(VALUE self)
diff --git a/ext/-test-/integer/depend b/ext/-test-/integer/depend
index 5c9d581389..c68651d07c 100644
--- a/ext/-test-/integer/depend
+++ b/ext/-test-/integer/depend
@@ -2,8 +2,157 @@
core_ext.o: $(RUBY_EXTCONF_H)
core_ext.o: $(arch_hdrdir)/ruby/config.h
core_ext.o: $(hdrdir)/ruby.h
+core_ext.o: $(hdrdir)/ruby/internal/anyargs.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+core_ext.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+core_ext.o: $(hdrdir)/ruby/internal/assume.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/artificial.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/cold.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/const.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/error.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/format.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/noalias.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/noinline.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/pure.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/restrict.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/warning.h
+core_ext.o: $(hdrdir)/ruby/internal/attr/weakref.h
+core_ext.o: $(hdrdir)/ruby/internal/cast.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+core_ext.o: $(hdrdir)/ruby/internal/compiler_since.h
+core_ext.o: $(hdrdir)/ruby/internal/config.h
+core_ext.o: $(hdrdir)/ruby/internal/constant_p.h
+core_ext.o: $(hdrdir)/ruby/internal/core.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rarray.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rbasic.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rbignum.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rclass.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rdata.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rfile.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rhash.h
+core_ext.o: $(hdrdir)/ruby/internal/core/robject.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rregexp.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rstring.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rstruct.h
+core_ext.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+core_ext.o: $(hdrdir)/ruby/internal/ctype.h
+core_ext.o: $(hdrdir)/ruby/internal/dllexport.h
+core_ext.o: $(hdrdir)/ruby/internal/dosish.h
+core_ext.o: $(hdrdir)/ruby/internal/error.h
+core_ext.o: $(hdrdir)/ruby/internal/eval.h
+core_ext.o: $(hdrdir)/ruby/internal/event.h
+core_ext.o: $(hdrdir)/ruby/internal/fl_type.h
+core_ext.o: $(hdrdir)/ruby/internal/gc.h
+core_ext.o: $(hdrdir)/ruby/internal/glob.h
+core_ext.o: $(hdrdir)/ruby/internal/globals.h
+core_ext.o: $(hdrdir)/ruby/internal/has/attribute.h
+core_ext.o: $(hdrdir)/ruby/internal/has/builtin.h
+core_ext.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+core_ext.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+core_ext.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+core_ext.o: $(hdrdir)/ruby/internal/has/extension.h
+core_ext.o: $(hdrdir)/ruby/internal/has/feature.h
+core_ext.o: $(hdrdir)/ruby/internal/has/warning.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/array.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/bignum.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/class.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/compar.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/complex.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/cont.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/dir.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/enum.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/error.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/eval.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/file.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/gc.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/hash.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/io.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/load.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/marshal.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/numeric.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/object.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/parse.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/proc.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/process.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/random.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/range.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/rational.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/re.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/ruby.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/select.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/signal.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/string.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/struct.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/thread.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/time.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/variable.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/vm.h
+core_ext.o: $(hdrdir)/ruby/internal/interpreter.h
+core_ext.o: $(hdrdir)/ruby/internal/iterator.h
+core_ext.o: $(hdrdir)/ruby/internal/memory.h
+core_ext.o: $(hdrdir)/ruby/internal/method.h
+core_ext.o: $(hdrdir)/ruby/internal/module.h
+core_ext.o: $(hdrdir)/ruby/internal/newobj.h
+core_ext.o: $(hdrdir)/ruby/internal/rgengc.h
+core_ext.o: $(hdrdir)/ruby/internal/scan_args.h
+core_ext.o: $(hdrdir)/ruby/internal/special_consts.h
+core_ext.o: $(hdrdir)/ruby/internal/static_assert.h
+core_ext.o: $(hdrdir)/ruby/internal/stdalign.h
+core_ext.o: $(hdrdir)/ruby/internal/stdbool.h
+core_ext.o: $(hdrdir)/ruby/internal/symbol.h
+core_ext.o: $(hdrdir)/ruby/internal/token_paste.h
+core_ext.o: $(hdrdir)/ruby/internal/value.h
+core_ext.o: $(hdrdir)/ruby/internal/value_type.h
+core_ext.o: $(hdrdir)/ruby/internal/variable.h
+core_ext.o: $(hdrdir)/ruby/internal/warning_push.h
+core_ext.o: $(hdrdir)/ruby/internal/xmalloc.h
core_ext.o: $(hdrdir)/ruby/assert.h
core_ext.o: $(hdrdir)/ruby/backward.h
+core_ext.o: $(hdrdir)/ruby/backward/2/assume.h
+core_ext.o: $(hdrdir)/ruby/backward/2/attributes.h
+core_ext.o: $(hdrdir)/ruby/backward/2/bool.h
+core_ext.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+core_ext.o: $(hdrdir)/ruby/backward/2/inttypes.h
+core_ext.o: $(hdrdir)/ruby/backward/2/limits.h
+core_ext.o: $(hdrdir)/ruby/backward/2/long_long.h
+core_ext.o: $(hdrdir)/ruby/backward/2/stdalign.h
+core_ext.o: $(hdrdir)/ruby/backward/2/stdarg.h
core_ext.o: $(hdrdir)/ruby/defines.h
core_ext.o: $(hdrdir)/ruby/intern.h
core_ext.o: $(hdrdir)/ruby/missing.h
@@ -11,12 +160,169 @@ core_ext.o: $(hdrdir)/ruby/ruby.h
core_ext.o: $(hdrdir)/ruby/st.h
core_ext.o: $(hdrdir)/ruby/subst.h
core_ext.o: $(top_srcdir)/internal.h
+core_ext.o: $(top_srcdir)/internal/bignum.h
+core_ext.o: $(top_srcdir)/internal/bits.h
+core_ext.o: $(top_srcdir)/internal/compilers.h
+core_ext.o: $(top_srcdir)/internal/fixnum.h
+core_ext.o: $(top_srcdir)/internal/numeric.h
+core_ext.o: $(top_srcdir)/internal/serial.h
+core_ext.o: $(top_srcdir)/internal/static_assert.h
+core_ext.o: $(top_srcdir)/internal/vm.h
core_ext.o: core_ext.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -27,8 +333,157 @@ init.o: init.c
my_integer.o: $(RUBY_EXTCONF_H)
my_integer.o: $(arch_hdrdir)/ruby/config.h
my_integer.o: $(hdrdir)/ruby.h
+my_integer.o: $(hdrdir)/ruby/internal/anyargs.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+my_integer.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+my_integer.o: $(hdrdir)/ruby/internal/assume.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/artificial.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/cold.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/const.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/error.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/format.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/noalias.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/noinline.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/pure.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/restrict.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/warning.h
+my_integer.o: $(hdrdir)/ruby/internal/attr/weakref.h
+my_integer.o: $(hdrdir)/ruby/internal/cast.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+my_integer.o: $(hdrdir)/ruby/internal/compiler_since.h
+my_integer.o: $(hdrdir)/ruby/internal/config.h
+my_integer.o: $(hdrdir)/ruby/internal/constant_p.h
+my_integer.o: $(hdrdir)/ruby/internal/core.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rarray.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rbasic.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rbignum.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rclass.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rdata.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rfile.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rhash.h
+my_integer.o: $(hdrdir)/ruby/internal/core/robject.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rregexp.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rstring.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rstruct.h
+my_integer.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+my_integer.o: $(hdrdir)/ruby/internal/ctype.h
+my_integer.o: $(hdrdir)/ruby/internal/dllexport.h
+my_integer.o: $(hdrdir)/ruby/internal/dosish.h
+my_integer.o: $(hdrdir)/ruby/internal/error.h
+my_integer.o: $(hdrdir)/ruby/internal/eval.h
+my_integer.o: $(hdrdir)/ruby/internal/event.h
+my_integer.o: $(hdrdir)/ruby/internal/fl_type.h
+my_integer.o: $(hdrdir)/ruby/internal/gc.h
+my_integer.o: $(hdrdir)/ruby/internal/glob.h
+my_integer.o: $(hdrdir)/ruby/internal/globals.h
+my_integer.o: $(hdrdir)/ruby/internal/has/attribute.h
+my_integer.o: $(hdrdir)/ruby/internal/has/builtin.h
+my_integer.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+my_integer.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+my_integer.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+my_integer.o: $(hdrdir)/ruby/internal/has/extension.h
+my_integer.o: $(hdrdir)/ruby/internal/has/feature.h
+my_integer.o: $(hdrdir)/ruby/internal/has/warning.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/array.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/bignum.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/class.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/compar.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/complex.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/cont.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/dir.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/enum.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/error.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/eval.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/file.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/gc.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/hash.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/io.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/load.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/marshal.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/numeric.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/object.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/parse.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/proc.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/process.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/random.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/range.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/rational.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/re.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/ruby.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/select.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/signal.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/string.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/struct.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/thread.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/time.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/variable.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/vm.h
+my_integer.o: $(hdrdir)/ruby/internal/interpreter.h
+my_integer.o: $(hdrdir)/ruby/internal/iterator.h
+my_integer.o: $(hdrdir)/ruby/internal/memory.h
+my_integer.o: $(hdrdir)/ruby/internal/method.h
+my_integer.o: $(hdrdir)/ruby/internal/module.h
+my_integer.o: $(hdrdir)/ruby/internal/newobj.h
+my_integer.o: $(hdrdir)/ruby/internal/rgengc.h
+my_integer.o: $(hdrdir)/ruby/internal/scan_args.h
+my_integer.o: $(hdrdir)/ruby/internal/special_consts.h
+my_integer.o: $(hdrdir)/ruby/internal/static_assert.h
+my_integer.o: $(hdrdir)/ruby/internal/stdalign.h
+my_integer.o: $(hdrdir)/ruby/internal/stdbool.h
+my_integer.o: $(hdrdir)/ruby/internal/symbol.h
+my_integer.o: $(hdrdir)/ruby/internal/token_paste.h
+my_integer.o: $(hdrdir)/ruby/internal/value.h
+my_integer.o: $(hdrdir)/ruby/internal/value_type.h
+my_integer.o: $(hdrdir)/ruby/internal/variable.h
+my_integer.o: $(hdrdir)/ruby/internal/warning_push.h
+my_integer.o: $(hdrdir)/ruby/internal/xmalloc.h
my_integer.o: $(hdrdir)/ruby/assert.h
my_integer.o: $(hdrdir)/ruby/backward.h
+my_integer.o: $(hdrdir)/ruby/backward/2/assume.h
+my_integer.o: $(hdrdir)/ruby/backward/2/attributes.h
+my_integer.o: $(hdrdir)/ruby/backward/2/bool.h
+my_integer.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+my_integer.o: $(hdrdir)/ruby/backward/2/inttypes.h
+my_integer.o: $(hdrdir)/ruby/backward/2/limits.h
+my_integer.o: $(hdrdir)/ruby/backward/2/long_long.h
+my_integer.o: $(hdrdir)/ruby/backward/2/stdalign.h
+my_integer.o: $(hdrdir)/ruby/backward/2/stdarg.h
my_integer.o: $(hdrdir)/ruby/defines.h
my_integer.o: $(hdrdir)/ruby/intern.h
my_integer.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/iseq_load/depend b/ext/-test-/iseq_load/depend
index ac549546ec..007790a02e 100644
--- a/ext/-test-/iseq_load/depend
+++ b/ext/-test-/iseq_load/depend
@@ -2,8 +2,157 @@
iseq_load.o: $(RUBY_EXTCONF_H)
iseq_load.o: $(arch_hdrdir)/ruby/config.h
iseq_load.o: $(hdrdir)/ruby.h
+iseq_load.o: $(hdrdir)/ruby/internal/anyargs.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+iseq_load.o: $(hdrdir)/ruby/internal/assume.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/artificial.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/cold.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/const.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/error.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/format.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/noalias.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/noinline.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/pure.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/restrict.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/warning.h
+iseq_load.o: $(hdrdir)/ruby/internal/attr/weakref.h
+iseq_load.o: $(hdrdir)/ruby/internal/cast.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+iseq_load.o: $(hdrdir)/ruby/internal/compiler_since.h
+iseq_load.o: $(hdrdir)/ruby/internal/config.h
+iseq_load.o: $(hdrdir)/ruby/internal/constant_p.h
+iseq_load.o: $(hdrdir)/ruby/internal/core.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rarray.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rbasic.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rbignum.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rclass.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rdata.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rfile.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rhash.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/robject.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rregexp.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rstring.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rstruct.h
+iseq_load.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+iseq_load.o: $(hdrdir)/ruby/internal/ctype.h
+iseq_load.o: $(hdrdir)/ruby/internal/dllexport.h
+iseq_load.o: $(hdrdir)/ruby/internal/dosish.h
+iseq_load.o: $(hdrdir)/ruby/internal/error.h
+iseq_load.o: $(hdrdir)/ruby/internal/eval.h
+iseq_load.o: $(hdrdir)/ruby/internal/event.h
+iseq_load.o: $(hdrdir)/ruby/internal/fl_type.h
+iseq_load.o: $(hdrdir)/ruby/internal/gc.h
+iseq_load.o: $(hdrdir)/ruby/internal/glob.h
+iseq_load.o: $(hdrdir)/ruby/internal/globals.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/attribute.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/builtin.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/extension.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/feature.h
+iseq_load.o: $(hdrdir)/ruby/internal/has/warning.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/array.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/bignum.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/class.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/compar.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/complex.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/cont.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/dir.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/enum.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/error.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/eval.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/file.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/gc.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/hash.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/io.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/load.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/marshal.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/numeric.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/object.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/parse.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/proc.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/process.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/random.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/range.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/rational.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/re.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/ruby.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/select.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/signal.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/string.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/struct.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/thread.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/time.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/variable.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/vm.h
+iseq_load.o: $(hdrdir)/ruby/internal/interpreter.h
+iseq_load.o: $(hdrdir)/ruby/internal/iterator.h
+iseq_load.o: $(hdrdir)/ruby/internal/memory.h
+iseq_load.o: $(hdrdir)/ruby/internal/method.h
+iseq_load.o: $(hdrdir)/ruby/internal/module.h
+iseq_load.o: $(hdrdir)/ruby/internal/newobj.h
+iseq_load.o: $(hdrdir)/ruby/internal/rgengc.h
+iseq_load.o: $(hdrdir)/ruby/internal/scan_args.h
+iseq_load.o: $(hdrdir)/ruby/internal/special_consts.h
+iseq_load.o: $(hdrdir)/ruby/internal/static_assert.h
+iseq_load.o: $(hdrdir)/ruby/internal/stdalign.h
+iseq_load.o: $(hdrdir)/ruby/internal/stdbool.h
+iseq_load.o: $(hdrdir)/ruby/internal/symbol.h
+iseq_load.o: $(hdrdir)/ruby/internal/token_paste.h
+iseq_load.o: $(hdrdir)/ruby/internal/value.h
+iseq_load.o: $(hdrdir)/ruby/internal/value_type.h
+iseq_load.o: $(hdrdir)/ruby/internal/variable.h
+iseq_load.o: $(hdrdir)/ruby/internal/warning_push.h
+iseq_load.o: $(hdrdir)/ruby/internal/xmalloc.h
iseq_load.o: $(hdrdir)/ruby/assert.h
iseq_load.o: $(hdrdir)/ruby/backward.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/assume.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/attributes.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/bool.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/inttypes.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/limits.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/long_long.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/stdalign.h
+iseq_load.o: $(hdrdir)/ruby/backward/2/stdarg.h
iseq_load.o: $(hdrdir)/ruby/defines.h
iseq_load.o: $(hdrdir)/ruby/intern.h
iseq_load.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/iter/depend b/ext/-test-/iter/depend
index 5e754950c1..d00638e78f 100644
--- a/ext/-test-/iter/depend
+++ b/ext/-test-/iter/depend
@@ -2,8 +2,157 @@
break.o: $(RUBY_EXTCONF_H)
break.o: $(arch_hdrdir)/ruby/config.h
break.o: $(hdrdir)/ruby.h
+break.o: $(hdrdir)/ruby/internal/anyargs.h
+break.o: $(hdrdir)/ruby/internal/arithmetic.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+break.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+break.o: $(hdrdir)/ruby/internal/assume.h
+break.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+break.o: $(hdrdir)/ruby/internal/attr/artificial.h
+break.o: $(hdrdir)/ruby/internal/attr/cold.h
+break.o: $(hdrdir)/ruby/internal/attr/const.h
+break.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+break.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+break.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+break.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+break.o: $(hdrdir)/ruby/internal/attr/error.h
+break.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+break.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+break.o: $(hdrdir)/ruby/internal/attr/format.h
+break.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+break.o: $(hdrdir)/ruby/internal/attr/noalias.h
+break.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+break.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+break.o: $(hdrdir)/ruby/internal/attr/noinline.h
+break.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+break.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+break.o: $(hdrdir)/ruby/internal/attr/pure.h
+break.o: $(hdrdir)/ruby/internal/attr/restrict.h
+break.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+break.o: $(hdrdir)/ruby/internal/attr/warning.h
+break.o: $(hdrdir)/ruby/internal/attr/weakref.h
+break.o: $(hdrdir)/ruby/internal/cast.h
+break.o: $(hdrdir)/ruby/internal/compiler_is.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+break.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+break.o: $(hdrdir)/ruby/internal/compiler_since.h
+break.o: $(hdrdir)/ruby/internal/config.h
+break.o: $(hdrdir)/ruby/internal/constant_p.h
+break.o: $(hdrdir)/ruby/internal/core.h
+break.o: $(hdrdir)/ruby/internal/core/rarray.h
+break.o: $(hdrdir)/ruby/internal/core/rbasic.h
+break.o: $(hdrdir)/ruby/internal/core/rbignum.h
+break.o: $(hdrdir)/ruby/internal/core/rclass.h
+break.o: $(hdrdir)/ruby/internal/core/rdata.h
+break.o: $(hdrdir)/ruby/internal/core/rfile.h
+break.o: $(hdrdir)/ruby/internal/core/rhash.h
+break.o: $(hdrdir)/ruby/internal/core/robject.h
+break.o: $(hdrdir)/ruby/internal/core/rregexp.h
+break.o: $(hdrdir)/ruby/internal/core/rstring.h
+break.o: $(hdrdir)/ruby/internal/core/rstruct.h
+break.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+break.o: $(hdrdir)/ruby/internal/ctype.h
+break.o: $(hdrdir)/ruby/internal/dllexport.h
+break.o: $(hdrdir)/ruby/internal/dosish.h
+break.o: $(hdrdir)/ruby/internal/error.h
+break.o: $(hdrdir)/ruby/internal/eval.h
+break.o: $(hdrdir)/ruby/internal/event.h
+break.o: $(hdrdir)/ruby/internal/fl_type.h
+break.o: $(hdrdir)/ruby/internal/gc.h
+break.o: $(hdrdir)/ruby/internal/glob.h
+break.o: $(hdrdir)/ruby/internal/globals.h
+break.o: $(hdrdir)/ruby/internal/has/attribute.h
+break.o: $(hdrdir)/ruby/internal/has/builtin.h
+break.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+break.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+break.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+break.o: $(hdrdir)/ruby/internal/has/extension.h
+break.o: $(hdrdir)/ruby/internal/has/feature.h
+break.o: $(hdrdir)/ruby/internal/has/warning.h
+break.o: $(hdrdir)/ruby/internal/intern/array.h
+break.o: $(hdrdir)/ruby/internal/intern/bignum.h
+break.o: $(hdrdir)/ruby/internal/intern/class.h
+break.o: $(hdrdir)/ruby/internal/intern/compar.h
+break.o: $(hdrdir)/ruby/internal/intern/complex.h
+break.o: $(hdrdir)/ruby/internal/intern/cont.h
+break.o: $(hdrdir)/ruby/internal/intern/dir.h
+break.o: $(hdrdir)/ruby/internal/intern/enum.h
+break.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+break.o: $(hdrdir)/ruby/internal/intern/error.h
+break.o: $(hdrdir)/ruby/internal/intern/eval.h
+break.o: $(hdrdir)/ruby/internal/intern/file.h
+break.o: $(hdrdir)/ruby/internal/intern/gc.h
+break.o: $(hdrdir)/ruby/internal/intern/hash.h
+break.o: $(hdrdir)/ruby/internal/intern/io.h
+break.o: $(hdrdir)/ruby/internal/intern/load.h
+break.o: $(hdrdir)/ruby/internal/intern/marshal.h
+break.o: $(hdrdir)/ruby/internal/intern/numeric.h
+break.o: $(hdrdir)/ruby/internal/intern/object.h
+break.o: $(hdrdir)/ruby/internal/intern/parse.h
+break.o: $(hdrdir)/ruby/internal/intern/proc.h
+break.o: $(hdrdir)/ruby/internal/intern/process.h
+break.o: $(hdrdir)/ruby/internal/intern/random.h
+break.o: $(hdrdir)/ruby/internal/intern/range.h
+break.o: $(hdrdir)/ruby/internal/intern/rational.h
+break.o: $(hdrdir)/ruby/internal/intern/re.h
+break.o: $(hdrdir)/ruby/internal/intern/ruby.h
+break.o: $(hdrdir)/ruby/internal/intern/select.h
+break.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+break.o: $(hdrdir)/ruby/internal/intern/signal.h
+break.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+break.o: $(hdrdir)/ruby/internal/intern/string.h
+break.o: $(hdrdir)/ruby/internal/intern/struct.h
+break.o: $(hdrdir)/ruby/internal/intern/thread.h
+break.o: $(hdrdir)/ruby/internal/intern/time.h
+break.o: $(hdrdir)/ruby/internal/intern/variable.h
+break.o: $(hdrdir)/ruby/internal/intern/vm.h
+break.o: $(hdrdir)/ruby/internal/interpreter.h
+break.o: $(hdrdir)/ruby/internal/iterator.h
+break.o: $(hdrdir)/ruby/internal/memory.h
+break.o: $(hdrdir)/ruby/internal/method.h
+break.o: $(hdrdir)/ruby/internal/module.h
+break.o: $(hdrdir)/ruby/internal/newobj.h
+break.o: $(hdrdir)/ruby/internal/rgengc.h
+break.o: $(hdrdir)/ruby/internal/scan_args.h
+break.o: $(hdrdir)/ruby/internal/special_consts.h
+break.o: $(hdrdir)/ruby/internal/static_assert.h
+break.o: $(hdrdir)/ruby/internal/stdalign.h
+break.o: $(hdrdir)/ruby/internal/stdbool.h
+break.o: $(hdrdir)/ruby/internal/symbol.h
+break.o: $(hdrdir)/ruby/internal/token_paste.h
+break.o: $(hdrdir)/ruby/internal/value.h
+break.o: $(hdrdir)/ruby/internal/value_type.h
+break.o: $(hdrdir)/ruby/internal/variable.h
+break.o: $(hdrdir)/ruby/internal/warning_push.h
+break.o: $(hdrdir)/ruby/internal/xmalloc.h
break.o: $(hdrdir)/ruby/assert.h
break.o: $(hdrdir)/ruby/backward.h
+break.o: $(hdrdir)/ruby/backward/2/assume.h
+break.o: $(hdrdir)/ruby/backward/2/attributes.h
+break.o: $(hdrdir)/ruby/backward/2/bool.h
+break.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+break.o: $(hdrdir)/ruby/backward/2/inttypes.h
+break.o: $(hdrdir)/ruby/backward/2/limits.h
+break.o: $(hdrdir)/ruby/backward/2/long_long.h
+break.o: $(hdrdir)/ruby/backward/2/stdalign.h
+break.o: $(hdrdir)/ruby/backward/2/stdarg.h
break.o: $(hdrdir)/ruby/defines.h
break.o: $(hdrdir)/ruby/intern.h
break.o: $(hdrdir)/ruby/missing.h
@@ -14,8 +163,157 @@ break.o: break.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -26,8 +324,157 @@ init.o: init.c
yield.o: $(RUBY_EXTCONF_H)
yield.o: $(arch_hdrdir)/ruby/config.h
yield.o: $(hdrdir)/ruby.h
+yield.o: $(hdrdir)/ruby/internal/anyargs.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+yield.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+yield.o: $(hdrdir)/ruby/internal/assume.h
+yield.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+yield.o: $(hdrdir)/ruby/internal/attr/artificial.h
+yield.o: $(hdrdir)/ruby/internal/attr/cold.h
+yield.o: $(hdrdir)/ruby/internal/attr/const.h
+yield.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+yield.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+yield.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+yield.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+yield.o: $(hdrdir)/ruby/internal/attr/error.h
+yield.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+yield.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+yield.o: $(hdrdir)/ruby/internal/attr/format.h
+yield.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+yield.o: $(hdrdir)/ruby/internal/attr/noalias.h
+yield.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+yield.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+yield.o: $(hdrdir)/ruby/internal/attr/noinline.h
+yield.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+yield.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+yield.o: $(hdrdir)/ruby/internal/attr/pure.h
+yield.o: $(hdrdir)/ruby/internal/attr/restrict.h
+yield.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+yield.o: $(hdrdir)/ruby/internal/attr/warning.h
+yield.o: $(hdrdir)/ruby/internal/attr/weakref.h
+yield.o: $(hdrdir)/ruby/internal/cast.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+yield.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+yield.o: $(hdrdir)/ruby/internal/compiler_since.h
+yield.o: $(hdrdir)/ruby/internal/config.h
+yield.o: $(hdrdir)/ruby/internal/constant_p.h
+yield.o: $(hdrdir)/ruby/internal/core.h
+yield.o: $(hdrdir)/ruby/internal/core/rarray.h
+yield.o: $(hdrdir)/ruby/internal/core/rbasic.h
+yield.o: $(hdrdir)/ruby/internal/core/rbignum.h
+yield.o: $(hdrdir)/ruby/internal/core/rclass.h
+yield.o: $(hdrdir)/ruby/internal/core/rdata.h
+yield.o: $(hdrdir)/ruby/internal/core/rfile.h
+yield.o: $(hdrdir)/ruby/internal/core/rhash.h
+yield.o: $(hdrdir)/ruby/internal/core/robject.h
+yield.o: $(hdrdir)/ruby/internal/core/rregexp.h
+yield.o: $(hdrdir)/ruby/internal/core/rstring.h
+yield.o: $(hdrdir)/ruby/internal/core/rstruct.h
+yield.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+yield.o: $(hdrdir)/ruby/internal/ctype.h
+yield.o: $(hdrdir)/ruby/internal/dllexport.h
+yield.o: $(hdrdir)/ruby/internal/dosish.h
+yield.o: $(hdrdir)/ruby/internal/error.h
+yield.o: $(hdrdir)/ruby/internal/eval.h
+yield.o: $(hdrdir)/ruby/internal/event.h
+yield.o: $(hdrdir)/ruby/internal/fl_type.h
+yield.o: $(hdrdir)/ruby/internal/gc.h
+yield.o: $(hdrdir)/ruby/internal/glob.h
+yield.o: $(hdrdir)/ruby/internal/globals.h
+yield.o: $(hdrdir)/ruby/internal/has/attribute.h
+yield.o: $(hdrdir)/ruby/internal/has/builtin.h
+yield.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+yield.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+yield.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+yield.o: $(hdrdir)/ruby/internal/has/extension.h
+yield.o: $(hdrdir)/ruby/internal/has/feature.h
+yield.o: $(hdrdir)/ruby/internal/has/warning.h
+yield.o: $(hdrdir)/ruby/internal/intern/array.h
+yield.o: $(hdrdir)/ruby/internal/intern/bignum.h
+yield.o: $(hdrdir)/ruby/internal/intern/class.h
+yield.o: $(hdrdir)/ruby/internal/intern/compar.h
+yield.o: $(hdrdir)/ruby/internal/intern/complex.h
+yield.o: $(hdrdir)/ruby/internal/intern/cont.h
+yield.o: $(hdrdir)/ruby/internal/intern/dir.h
+yield.o: $(hdrdir)/ruby/internal/intern/enum.h
+yield.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+yield.o: $(hdrdir)/ruby/internal/intern/error.h
+yield.o: $(hdrdir)/ruby/internal/intern/eval.h
+yield.o: $(hdrdir)/ruby/internal/intern/file.h
+yield.o: $(hdrdir)/ruby/internal/intern/gc.h
+yield.o: $(hdrdir)/ruby/internal/intern/hash.h
+yield.o: $(hdrdir)/ruby/internal/intern/io.h
+yield.o: $(hdrdir)/ruby/internal/intern/load.h
+yield.o: $(hdrdir)/ruby/internal/intern/marshal.h
+yield.o: $(hdrdir)/ruby/internal/intern/numeric.h
+yield.o: $(hdrdir)/ruby/internal/intern/object.h
+yield.o: $(hdrdir)/ruby/internal/intern/parse.h
+yield.o: $(hdrdir)/ruby/internal/intern/proc.h
+yield.o: $(hdrdir)/ruby/internal/intern/process.h
+yield.o: $(hdrdir)/ruby/internal/intern/random.h
+yield.o: $(hdrdir)/ruby/internal/intern/range.h
+yield.o: $(hdrdir)/ruby/internal/intern/rational.h
+yield.o: $(hdrdir)/ruby/internal/intern/re.h
+yield.o: $(hdrdir)/ruby/internal/intern/ruby.h
+yield.o: $(hdrdir)/ruby/internal/intern/select.h
+yield.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+yield.o: $(hdrdir)/ruby/internal/intern/signal.h
+yield.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+yield.o: $(hdrdir)/ruby/internal/intern/string.h
+yield.o: $(hdrdir)/ruby/internal/intern/struct.h
+yield.o: $(hdrdir)/ruby/internal/intern/thread.h
+yield.o: $(hdrdir)/ruby/internal/intern/time.h
+yield.o: $(hdrdir)/ruby/internal/intern/variable.h
+yield.o: $(hdrdir)/ruby/internal/intern/vm.h
+yield.o: $(hdrdir)/ruby/internal/interpreter.h
+yield.o: $(hdrdir)/ruby/internal/iterator.h
+yield.o: $(hdrdir)/ruby/internal/memory.h
+yield.o: $(hdrdir)/ruby/internal/method.h
+yield.o: $(hdrdir)/ruby/internal/module.h
+yield.o: $(hdrdir)/ruby/internal/newobj.h
+yield.o: $(hdrdir)/ruby/internal/rgengc.h
+yield.o: $(hdrdir)/ruby/internal/scan_args.h
+yield.o: $(hdrdir)/ruby/internal/special_consts.h
+yield.o: $(hdrdir)/ruby/internal/static_assert.h
+yield.o: $(hdrdir)/ruby/internal/stdalign.h
+yield.o: $(hdrdir)/ruby/internal/stdbool.h
+yield.o: $(hdrdir)/ruby/internal/symbol.h
+yield.o: $(hdrdir)/ruby/internal/token_paste.h
+yield.o: $(hdrdir)/ruby/internal/value.h
+yield.o: $(hdrdir)/ruby/internal/value_type.h
+yield.o: $(hdrdir)/ruby/internal/variable.h
+yield.o: $(hdrdir)/ruby/internal/warning_push.h
+yield.o: $(hdrdir)/ruby/internal/xmalloc.h
yield.o: $(hdrdir)/ruby/assert.h
yield.o: $(hdrdir)/ruby/backward.h
+yield.o: $(hdrdir)/ruby/backward/2/assume.h
+yield.o: $(hdrdir)/ruby/backward/2/attributes.h
+yield.o: $(hdrdir)/ruby/backward/2/bool.h
+yield.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+yield.o: $(hdrdir)/ruby/backward/2/inttypes.h
+yield.o: $(hdrdir)/ruby/backward/2/limits.h
+yield.o: $(hdrdir)/ruby/backward/2/long_long.h
+yield.o: $(hdrdir)/ruby/backward/2/stdalign.h
+yield.o: $(hdrdir)/ruby/backward/2/stdarg.h
yield.o: $(hdrdir)/ruby/defines.h
yield.o: $(hdrdir)/ruby/intern.h
yield.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/load/protect/depend b/ext/-test-/load/protect/depend
index b62393f1cb..99c02e1f25 100644
--- a/ext/-test-/load/protect/depend
+++ b/ext/-test-/load/protect/depend
@@ -2,8 +2,157 @@
protect.o: $(RUBY_EXTCONF_H)
protect.o: $(arch_hdrdir)/ruby/config.h
protect.o: $(hdrdir)/ruby.h
+protect.o: $(hdrdir)/ruby/internal/anyargs.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+protect.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+protect.o: $(hdrdir)/ruby/internal/assume.h
+protect.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+protect.o: $(hdrdir)/ruby/internal/attr/artificial.h
+protect.o: $(hdrdir)/ruby/internal/attr/cold.h
+protect.o: $(hdrdir)/ruby/internal/attr/const.h
+protect.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+protect.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+protect.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+protect.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+protect.o: $(hdrdir)/ruby/internal/attr/error.h
+protect.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+protect.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+protect.o: $(hdrdir)/ruby/internal/attr/format.h
+protect.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+protect.o: $(hdrdir)/ruby/internal/attr/noalias.h
+protect.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+protect.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+protect.o: $(hdrdir)/ruby/internal/attr/noinline.h
+protect.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+protect.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+protect.o: $(hdrdir)/ruby/internal/attr/pure.h
+protect.o: $(hdrdir)/ruby/internal/attr/restrict.h
+protect.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+protect.o: $(hdrdir)/ruby/internal/attr/warning.h
+protect.o: $(hdrdir)/ruby/internal/attr/weakref.h
+protect.o: $(hdrdir)/ruby/internal/cast.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+protect.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+protect.o: $(hdrdir)/ruby/internal/compiler_since.h
+protect.o: $(hdrdir)/ruby/internal/config.h
+protect.o: $(hdrdir)/ruby/internal/constant_p.h
+protect.o: $(hdrdir)/ruby/internal/core.h
+protect.o: $(hdrdir)/ruby/internal/core/rarray.h
+protect.o: $(hdrdir)/ruby/internal/core/rbasic.h
+protect.o: $(hdrdir)/ruby/internal/core/rbignum.h
+protect.o: $(hdrdir)/ruby/internal/core/rclass.h
+protect.o: $(hdrdir)/ruby/internal/core/rdata.h
+protect.o: $(hdrdir)/ruby/internal/core/rfile.h
+protect.o: $(hdrdir)/ruby/internal/core/rhash.h
+protect.o: $(hdrdir)/ruby/internal/core/robject.h
+protect.o: $(hdrdir)/ruby/internal/core/rregexp.h
+protect.o: $(hdrdir)/ruby/internal/core/rstring.h
+protect.o: $(hdrdir)/ruby/internal/core/rstruct.h
+protect.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+protect.o: $(hdrdir)/ruby/internal/ctype.h
+protect.o: $(hdrdir)/ruby/internal/dllexport.h
+protect.o: $(hdrdir)/ruby/internal/dosish.h
+protect.o: $(hdrdir)/ruby/internal/error.h
+protect.o: $(hdrdir)/ruby/internal/eval.h
+protect.o: $(hdrdir)/ruby/internal/event.h
+protect.o: $(hdrdir)/ruby/internal/fl_type.h
+protect.o: $(hdrdir)/ruby/internal/gc.h
+protect.o: $(hdrdir)/ruby/internal/glob.h
+protect.o: $(hdrdir)/ruby/internal/globals.h
+protect.o: $(hdrdir)/ruby/internal/has/attribute.h
+protect.o: $(hdrdir)/ruby/internal/has/builtin.h
+protect.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+protect.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+protect.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+protect.o: $(hdrdir)/ruby/internal/has/extension.h
+protect.o: $(hdrdir)/ruby/internal/has/feature.h
+protect.o: $(hdrdir)/ruby/internal/has/warning.h
+protect.o: $(hdrdir)/ruby/internal/intern/array.h
+protect.o: $(hdrdir)/ruby/internal/intern/bignum.h
+protect.o: $(hdrdir)/ruby/internal/intern/class.h
+protect.o: $(hdrdir)/ruby/internal/intern/compar.h
+protect.o: $(hdrdir)/ruby/internal/intern/complex.h
+protect.o: $(hdrdir)/ruby/internal/intern/cont.h
+protect.o: $(hdrdir)/ruby/internal/intern/dir.h
+protect.o: $(hdrdir)/ruby/internal/intern/enum.h
+protect.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+protect.o: $(hdrdir)/ruby/internal/intern/error.h
+protect.o: $(hdrdir)/ruby/internal/intern/eval.h
+protect.o: $(hdrdir)/ruby/internal/intern/file.h
+protect.o: $(hdrdir)/ruby/internal/intern/gc.h
+protect.o: $(hdrdir)/ruby/internal/intern/hash.h
+protect.o: $(hdrdir)/ruby/internal/intern/io.h
+protect.o: $(hdrdir)/ruby/internal/intern/load.h
+protect.o: $(hdrdir)/ruby/internal/intern/marshal.h
+protect.o: $(hdrdir)/ruby/internal/intern/numeric.h
+protect.o: $(hdrdir)/ruby/internal/intern/object.h
+protect.o: $(hdrdir)/ruby/internal/intern/parse.h
+protect.o: $(hdrdir)/ruby/internal/intern/proc.h
+protect.o: $(hdrdir)/ruby/internal/intern/process.h
+protect.o: $(hdrdir)/ruby/internal/intern/random.h
+protect.o: $(hdrdir)/ruby/internal/intern/range.h
+protect.o: $(hdrdir)/ruby/internal/intern/rational.h
+protect.o: $(hdrdir)/ruby/internal/intern/re.h
+protect.o: $(hdrdir)/ruby/internal/intern/ruby.h
+protect.o: $(hdrdir)/ruby/internal/intern/select.h
+protect.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+protect.o: $(hdrdir)/ruby/internal/intern/signal.h
+protect.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+protect.o: $(hdrdir)/ruby/internal/intern/string.h
+protect.o: $(hdrdir)/ruby/internal/intern/struct.h
+protect.o: $(hdrdir)/ruby/internal/intern/thread.h
+protect.o: $(hdrdir)/ruby/internal/intern/time.h
+protect.o: $(hdrdir)/ruby/internal/intern/variable.h
+protect.o: $(hdrdir)/ruby/internal/intern/vm.h
+protect.o: $(hdrdir)/ruby/internal/interpreter.h
+protect.o: $(hdrdir)/ruby/internal/iterator.h
+protect.o: $(hdrdir)/ruby/internal/memory.h
+protect.o: $(hdrdir)/ruby/internal/method.h
+protect.o: $(hdrdir)/ruby/internal/module.h
+protect.o: $(hdrdir)/ruby/internal/newobj.h
+protect.o: $(hdrdir)/ruby/internal/rgengc.h
+protect.o: $(hdrdir)/ruby/internal/scan_args.h
+protect.o: $(hdrdir)/ruby/internal/special_consts.h
+protect.o: $(hdrdir)/ruby/internal/static_assert.h
+protect.o: $(hdrdir)/ruby/internal/stdalign.h
+protect.o: $(hdrdir)/ruby/internal/stdbool.h
+protect.o: $(hdrdir)/ruby/internal/symbol.h
+protect.o: $(hdrdir)/ruby/internal/token_paste.h
+protect.o: $(hdrdir)/ruby/internal/value.h
+protect.o: $(hdrdir)/ruby/internal/value_type.h
+protect.o: $(hdrdir)/ruby/internal/variable.h
+protect.o: $(hdrdir)/ruby/internal/warning_push.h
+protect.o: $(hdrdir)/ruby/internal/xmalloc.h
protect.o: $(hdrdir)/ruby/assert.h
protect.o: $(hdrdir)/ruby/backward.h
+protect.o: $(hdrdir)/ruby/backward/2/assume.h
+protect.o: $(hdrdir)/ruby/backward/2/attributes.h
+protect.o: $(hdrdir)/ruby/backward/2/bool.h
+protect.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+protect.o: $(hdrdir)/ruby/backward/2/inttypes.h
+protect.o: $(hdrdir)/ruby/backward/2/limits.h
+protect.o: $(hdrdir)/ruby/backward/2/long_long.h
+protect.o: $(hdrdir)/ruby/backward/2/stdalign.h
+protect.o: $(hdrdir)/ruby/backward/2/stdarg.h
protect.o: $(hdrdir)/ruby/defines.h
protect.o: $(hdrdir)/ruby/intern.h
protect.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/marshal/compat/depend b/ext/-test-/marshal/compat/depend
index f159506960..017a555852 100644
--- a/ext/-test-/marshal/compat/depend
+++ b/ext/-test-/marshal/compat/depend
@@ -2,8 +2,157 @@
usrcompat.o: $(RUBY_EXTCONF_H)
usrcompat.o: $(arch_hdrdir)/ruby/config.h
usrcompat.o: $(hdrdir)/ruby.h
+usrcompat.o: $(hdrdir)/ruby/internal/anyargs.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+usrcompat.o: $(hdrdir)/ruby/internal/assume.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/cold.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/const.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/error.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/format.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/pure.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/warning.h
+usrcompat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+usrcompat.o: $(hdrdir)/ruby/internal/cast.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+usrcompat.o: $(hdrdir)/ruby/internal/compiler_since.h
+usrcompat.o: $(hdrdir)/ruby/internal/config.h
+usrcompat.o: $(hdrdir)/ruby/internal/constant_p.h
+usrcompat.o: $(hdrdir)/ruby/internal/core.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rarray.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rclass.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rdata.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rfile.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rhash.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/robject.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rstring.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+usrcompat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+usrcompat.o: $(hdrdir)/ruby/internal/ctype.h
+usrcompat.o: $(hdrdir)/ruby/internal/dllexport.h
+usrcompat.o: $(hdrdir)/ruby/internal/dosish.h
+usrcompat.o: $(hdrdir)/ruby/internal/error.h
+usrcompat.o: $(hdrdir)/ruby/internal/eval.h
+usrcompat.o: $(hdrdir)/ruby/internal/event.h
+usrcompat.o: $(hdrdir)/ruby/internal/fl_type.h
+usrcompat.o: $(hdrdir)/ruby/internal/gc.h
+usrcompat.o: $(hdrdir)/ruby/internal/glob.h
+usrcompat.o: $(hdrdir)/ruby/internal/globals.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/attribute.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/builtin.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/extension.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/feature.h
+usrcompat.o: $(hdrdir)/ruby/internal/has/warning.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/array.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/class.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/compar.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/complex.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/cont.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/dir.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/enum.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/error.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/eval.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/file.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/gc.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/hash.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/io.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/load.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/object.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/parse.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/proc.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/process.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/random.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/range.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/rational.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/re.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/select.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/signal.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/string.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/struct.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/thread.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/time.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/variable.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/vm.h
+usrcompat.o: $(hdrdir)/ruby/internal/interpreter.h
+usrcompat.o: $(hdrdir)/ruby/internal/iterator.h
+usrcompat.o: $(hdrdir)/ruby/internal/memory.h
+usrcompat.o: $(hdrdir)/ruby/internal/method.h
+usrcompat.o: $(hdrdir)/ruby/internal/module.h
+usrcompat.o: $(hdrdir)/ruby/internal/newobj.h
+usrcompat.o: $(hdrdir)/ruby/internal/rgengc.h
+usrcompat.o: $(hdrdir)/ruby/internal/scan_args.h
+usrcompat.o: $(hdrdir)/ruby/internal/special_consts.h
+usrcompat.o: $(hdrdir)/ruby/internal/static_assert.h
+usrcompat.o: $(hdrdir)/ruby/internal/stdalign.h
+usrcompat.o: $(hdrdir)/ruby/internal/stdbool.h
+usrcompat.o: $(hdrdir)/ruby/internal/symbol.h
+usrcompat.o: $(hdrdir)/ruby/internal/token_paste.h
+usrcompat.o: $(hdrdir)/ruby/internal/value.h
+usrcompat.o: $(hdrdir)/ruby/internal/value_type.h
+usrcompat.o: $(hdrdir)/ruby/internal/variable.h
+usrcompat.o: $(hdrdir)/ruby/internal/warning_push.h
+usrcompat.o: $(hdrdir)/ruby/internal/xmalloc.h
usrcompat.o: $(hdrdir)/ruby/assert.h
usrcompat.o: $(hdrdir)/ruby/backward.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/assume.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/attributes.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/bool.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/limits.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/long_long.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+usrcompat.o: $(hdrdir)/ruby/backward/2/stdarg.h
usrcompat.o: $(hdrdir)/ruby/defines.h
usrcompat.o: $(hdrdir)/ruby/intern.h
usrcompat.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/marshal/internal_ivar/depend b/ext/-test-/marshal/internal_ivar/depend
index f280347c01..73b76c9080 100644
--- a/ext/-test-/marshal/internal_ivar/depend
+++ b/ext/-test-/marshal/internal_ivar/depend
@@ -2,8 +2,157 @@
internal_ivar.o: $(RUBY_EXTCONF_H)
internal_ivar.o: $(arch_hdrdir)/ruby/config.h
internal_ivar.o: $(hdrdir)/ruby.h
+internal_ivar.o: $(hdrdir)/ruby/internal/anyargs.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+internal_ivar.o: $(hdrdir)/ruby/internal/assume.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/artificial.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/cold.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/const.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/error.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/format.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/noalias.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/noinline.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/pure.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/restrict.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/warning.h
+internal_ivar.o: $(hdrdir)/ruby/internal/attr/weakref.h
+internal_ivar.o: $(hdrdir)/ruby/internal/cast.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+internal_ivar.o: $(hdrdir)/ruby/internal/compiler_since.h
+internal_ivar.o: $(hdrdir)/ruby/internal/config.h
+internal_ivar.o: $(hdrdir)/ruby/internal/constant_p.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rarray.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rbasic.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rbignum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rclass.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rdata.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rfile.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rhash.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/robject.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rregexp.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rstring.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rstruct.h
+internal_ivar.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+internal_ivar.o: $(hdrdir)/ruby/internal/ctype.h
+internal_ivar.o: $(hdrdir)/ruby/internal/dllexport.h
+internal_ivar.o: $(hdrdir)/ruby/internal/dosish.h
+internal_ivar.o: $(hdrdir)/ruby/internal/error.h
+internal_ivar.o: $(hdrdir)/ruby/internal/eval.h
+internal_ivar.o: $(hdrdir)/ruby/internal/event.h
+internal_ivar.o: $(hdrdir)/ruby/internal/fl_type.h
+internal_ivar.o: $(hdrdir)/ruby/internal/gc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/glob.h
+internal_ivar.o: $(hdrdir)/ruby/internal/globals.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/attribute.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/builtin.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/extension.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/feature.h
+internal_ivar.o: $(hdrdir)/ruby/internal/has/warning.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/array.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/bignum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/class.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/compar.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/complex.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/cont.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/dir.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/enum.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/error.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/eval.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/file.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/gc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/hash.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/io.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/load.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/marshal.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/numeric.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/object.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/parse.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/proc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/process.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/random.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/range.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/rational.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/re.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/ruby.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/select.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/signal.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/string.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/struct.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/thread.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/time.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/variable.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/vm.h
+internal_ivar.o: $(hdrdir)/ruby/internal/interpreter.h
+internal_ivar.o: $(hdrdir)/ruby/internal/iterator.h
+internal_ivar.o: $(hdrdir)/ruby/internal/memory.h
+internal_ivar.o: $(hdrdir)/ruby/internal/method.h
+internal_ivar.o: $(hdrdir)/ruby/internal/module.h
+internal_ivar.o: $(hdrdir)/ruby/internal/newobj.h
+internal_ivar.o: $(hdrdir)/ruby/internal/rgengc.h
+internal_ivar.o: $(hdrdir)/ruby/internal/scan_args.h
+internal_ivar.o: $(hdrdir)/ruby/internal/special_consts.h
+internal_ivar.o: $(hdrdir)/ruby/internal/static_assert.h
+internal_ivar.o: $(hdrdir)/ruby/internal/stdalign.h
+internal_ivar.o: $(hdrdir)/ruby/internal/stdbool.h
+internal_ivar.o: $(hdrdir)/ruby/internal/symbol.h
+internal_ivar.o: $(hdrdir)/ruby/internal/token_paste.h
+internal_ivar.o: $(hdrdir)/ruby/internal/value.h
+internal_ivar.o: $(hdrdir)/ruby/internal/value_type.h
+internal_ivar.o: $(hdrdir)/ruby/internal/variable.h
+internal_ivar.o: $(hdrdir)/ruby/internal/warning_push.h
+internal_ivar.o: $(hdrdir)/ruby/internal/xmalloc.h
internal_ivar.o: $(hdrdir)/ruby/assert.h
internal_ivar.o: $(hdrdir)/ruby/backward.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/assume.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/attributes.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/bool.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/inttypes.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/limits.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/long_long.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/stdalign.h
+internal_ivar.o: $(hdrdir)/ruby/backward/2/stdarg.h
internal_ivar.o: $(hdrdir)/ruby/defines.h
internal_ivar.o: $(hdrdir)/ruby/intern.h
internal_ivar.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/marshal/usr/depend b/ext/-test-/marshal/usr/depend
index 21c0c2d744..bf96e44d02 100644
--- a/ext/-test-/marshal/usr/depend
+++ b/ext/-test-/marshal/usr/depend
@@ -2,8 +2,157 @@
usrmarshal.o: $(RUBY_EXTCONF_H)
usrmarshal.o: $(arch_hdrdir)/ruby/config.h
usrmarshal.o: $(hdrdir)/ruby.h
+usrmarshal.o: $(hdrdir)/ruby/internal/anyargs.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+usrmarshal.o: $(hdrdir)/ruby/internal/assume.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/artificial.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/cold.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/const.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/error.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/format.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/noalias.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/noinline.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/pure.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/restrict.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/warning.h
+usrmarshal.o: $(hdrdir)/ruby/internal/attr/weakref.h
+usrmarshal.o: $(hdrdir)/ruby/internal/cast.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+usrmarshal.o: $(hdrdir)/ruby/internal/compiler_since.h
+usrmarshal.o: $(hdrdir)/ruby/internal/config.h
+usrmarshal.o: $(hdrdir)/ruby/internal/constant_p.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rarray.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rbasic.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rbignum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rclass.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rdata.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rfile.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rhash.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/robject.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rregexp.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rstring.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rstruct.h
+usrmarshal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+usrmarshal.o: $(hdrdir)/ruby/internal/ctype.h
+usrmarshal.o: $(hdrdir)/ruby/internal/dllexport.h
+usrmarshal.o: $(hdrdir)/ruby/internal/dosish.h
+usrmarshal.o: $(hdrdir)/ruby/internal/error.h
+usrmarshal.o: $(hdrdir)/ruby/internal/eval.h
+usrmarshal.o: $(hdrdir)/ruby/internal/event.h
+usrmarshal.o: $(hdrdir)/ruby/internal/fl_type.h
+usrmarshal.o: $(hdrdir)/ruby/internal/gc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/glob.h
+usrmarshal.o: $(hdrdir)/ruby/internal/globals.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/attribute.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/builtin.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/extension.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/feature.h
+usrmarshal.o: $(hdrdir)/ruby/internal/has/warning.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/array.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/bignum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/class.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/compar.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/complex.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/cont.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/dir.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/enum.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/error.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/eval.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/file.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/gc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/hash.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/io.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/load.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/marshal.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/numeric.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/object.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/parse.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/proc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/process.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/random.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/range.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/rational.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/re.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/ruby.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/select.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/signal.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/string.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/struct.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/thread.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/time.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/variable.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/vm.h
+usrmarshal.o: $(hdrdir)/ruby/internal/interpreter.h
+usrmarshal.o: $(hdrdir)/ruby/internal/iterator.h
+usrmarshal.o: $(hdrdir)/ruby/internal/memory.h
+usrmarshal.o: $(hdrdir)/ruby/internal/method.h
+usrmarshal.o: $(hdrdir)/ruby/internal/module.h
+usrmarshal.o: $(hdrdir)/ruby/internal/newobj.h
+usrmarshal.o: $(hdrdir)/ruby/internal/rgengc.h
+usrmarshal.o: $(hdrdir)/ruby/internal/scan_args.h
+usrmarshal.o: $(hdrdir)/ruby/internal/special_consts.h
+usrmarshal.o: $(hdrdir)/ruby/internal/static_assert.h
+usrmarshal.o: $(hdrdir)/ruby/internal/stdalign.h
+usrmarshal.o: $(hdrdir)/ruby/internal/stdbool.h
+usrmarshal.o: $(hdrdir)/ruby/internal/symbol.h
+usrmarshal.o: $(hdrdir)/ruby/internal/token_paste.h
+usrmarshal.o: $(hdrdir)/ruby/internal/value.h
+usrmarshal.o: $(hdrdir)/ruby/internal/value_type.h
+usrmarshal.o: $(hdrdir)/ruby/internal/variable.h
+usrmarshal.o: $(hdrdir)/ruby/internal/warning_push.h
+usrmarshal.o: $(hdrdir)/ruby/internal/xmalloc.h
usrmarshal.o: $(hdrdir)/ruby/assert.h
usrmarshal.o: $(hdrdir)/ruby/backward.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/assume.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/attributes.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/bool.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/inttypes.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/limits.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/long_long.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/stdalign.h
+usrmarshal.o: $(hdrdir)/ruby/backward/2/stdarg.h
usrmarshal.o: $(hdrdir)/ruby/defines.h
usrmarshal.o: $(hdrdir)/ruby/intern.h
usrmarshal.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/memory_status/depend b/ext/-test-/memory_status/depend
index 657ef59c35..96a7821451 100644
--- a/ext/-test-/memory_status/depend
+++ b/ext/-test-/memory_status/depend
@@ -4,8 +4,157 @@ memory_status.o: $(arch_hdrdir)/ruby/config.h
memory_status.o: $(hdrdir)/ruby.h
memory_status.o: $(hdrdir)/ruby/assert.h
memory_status.o: $(hdrdir)/ruby/backward.h
+memory_status.o: $(hdrdir)/ruby/backward/2/assume.h
+memory_status.o: $(hdrdir)/ruby/backward/2/attributes.h
+memory_status.o: $(hdrdir)/ruby/backward/2/bool.h
+memory_status.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+memory_status.o: $(hdrdir)/ruby/backward/2/inttypes.h
+memory_status.o: $(hdrdir)/ruby/backward/2/limits.h
+memory_status.o: $(hdrdir)/ruby/backward/2/long_long.h
+memory_status.o: $(hdrdir)/ruby/backward/2/stdalign.h
+memory_status.o: $(hdrdir)/ruby/backward/2/stdarg.h
memory_status.o: $(hdrdir)/ruby/defines.h
memory_status.o: $(hdrdir)/ruby/intern.h
+memory_status.o: $(hdrdir)/ruby/internal/anyargs.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+memory_status.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+memory_status.o: $(hdrdir)/ruby/internal/assume.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/artificial.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/cold.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/const.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/error.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/format.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/noalias.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/noinline.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/pure.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/restrict.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/warning.h
+memory_status.o: $(hdrdir)/ruby/internal/attr/weakref.h
+memory_status.o: $(hdrdir)/ruby/internal/cast.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+memory_status.o: $(hdrdir)/ruby/internal/compiler_since.h
+memory_status.o: $(hdrdir)/ruby/internal/config.h
+memory_status.o: $(hdrdir)/ruby/internal/constant_p.h
+memory_status.o: $(hdrdir)/ruby/internal/core.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rarray.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rbasic.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rbignum.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rclass.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rdata.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rfile.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rhash.h
+memory_status.o: $(hdrdir)/ruby/internal/core/robject.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rregexp.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rstring.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rstruct.h
+memory_status.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+memory_status.o: $(hdrdir)/ruby/internal/ctype.h
+memory_status.o: $(hdrdir)/ruby/internal/dllexport.h
+memory_status.o: $(hdrdir)/ruby/internal/dosish.h
+memory_status.o: $(hdrdir)/ruby/internal/error.h
+memory_status.o: $(hdrdir)/ruby/internal/eval.h
+memory_status.o: $(hdrdir)/ruby/internal/event.h
+memory_status.o: $(hdrdir)/ruby/internal/fl_type.h
+memory_status.o: $(hdrdir)/ruby/internal/gc.h
+memory_status.o: $(hdrdir)/ruby/internal/glob.h
+memory_status.o: $(hdrdir)/ruby/internal/globals.h
+memory_status.o: $(hdrdir)/ruby/internal/has/attribute.h
+memory_status.o: $(hdrdir)/ruby/internal/has/builtin.h
+memory_status.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+memory_status.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+memory_status.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+memory_status.o: $(hdrdir)/ruby/internal/has/extension.h
+memory_status.o: $(hdrdir)/ruby/internal/has/feature.h
+memory_status.o: $(hdrdir)/ruby/internal/has/warning.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/array.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/bignum.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/class.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/compar.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/complex.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/cont.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/dir.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/enum.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/error.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/eval.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/file.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/gc.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/hash.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/io.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/load.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/marshal.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/numeric.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/object.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/parse.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/proc.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/process.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/random.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/range.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/rational.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/re.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/ruby.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/select.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/signal.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/string.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/struct.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/thread.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/time.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/variable.h
+memory_status.o: $(hdrdir)/ruby/internal/intern/vm.h
+memory_status.o: $(hdrdir)/ruby/internal/interpreter.h
+memory_status.o: $(hdrdir)/ruby/internal/iterator.h
+memory_status.o: $(hdrdir)/ruby/internal/memory.h
+memory_status.o: $(hdrdir)/ruby/internal/method.h
+memory_status.o: $(hdrdir)/ruby/internal/module.h
+memory_status.o: $(hdrdir)/ruby/internal/newobj.h
+memory_status.o: $(hdrdir)/ruby/internal/rgengc.h
+memory_status.o: $(hdrdir)/ruby/internal/scan_args.h
+memory_status.o: $(hdrdir)/ruby/internal/special_consts.h
+memory_status.o: $(hdrdir)/ruby/internal/static_assert.h
+memory_status.o: $(hdrdir)/ruby/internal/stdalign.h
+memory_status.o: $(hdrdir)/ruby/internal/stdbool.h
+memory_status.o: $(hdrdir)/ruby/internal/symbol.h
+memory_status.o: $(hdrdir)/ruby/internal/token_paste.h
+memory_status.o: $(hdrdir)/ruby/internal/value.h
+memory_status.o: $(hdrdir)/ruby/internal/value_type.h
+memory_status.o: $(hdrdir)/ruby/internal/variable.h
+memory_status.o: $(hdrdir)/ruby/internal/warning_push.h
+memory_status.o: $(hdrdir)/ruby/internal/xmalloc.h
memory_status.o: $(hdrdir)/ruby/missing.h
memory_status.o: $(hdrdir)/ruby/ruby.h
memory_status.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/memory_view/depend b/ext/-test-/memory_view/depend
new file mode 100644
index 0000000000..bcbd98d41f
--- /dev/null
+++ b/ext/-test-/memory_view/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+memory_view.o: $(RUBY_EXTCONF_H)
+memory_view.o: $(arch_hdrdir)/ruby/config.h
+memory_view.o: $(hdrdir)/ruby.h
+memory_view.o: $(hdrdir)/ruby/assert.h
+memory_view.o: $(hdrdir)/ruby/backward.h
+memory_view.o: $(hdrdir)/ruby/backward/2/assume.h
+memory_view.o: $(hdrdir)/ruby/backward/2/attributes.h
+memory_view.o: $(hdrdir)/ruby/backward/2/bool.h
+memory_view.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+memory_view.o: $(hdrdir)/ruby/backward/2/inttypes.h
+memory_view.o: $(hdrdir)/ruby/backward/2/limits.h
+memory_view.o: $(hdrdir)/ruby/backward/2/long_long.h
+memory_view.o: $(hdrdir)/ruby/backward/2/stdalign.h
+memory_view.o: $(hdrdir)/ruby/backward/2/stdarg.h
+memory_view.o: $(hdrdir)/ruby/defines.h
+memory_view.o: $(hdrdir)/ruby/intern.h
+memory_view.o: $(hdrdir)/ruby/internal/anyargs.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+memory_view.o: $(hdrdir)/ruby/internal/assume.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/artificial.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/cold.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/const.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/error.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/format.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noalias.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noinline.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/pure.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/restrict.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/warning.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/weakref.h
+memory_view.o: $(hdrdir)/ruby/internal/cast.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_since.h
+memory_view.o: $(hdrdir)/ruby/internal/config.h
+memory_view.o: $(hdrdir)/ruby/internal/constant_p.h
+memory_view.o: $(hdrdir)/ruby/internal/core.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rarray.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rbasic.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rbignum.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rclass.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rdata.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rfile.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rhash.h
+memory_view.o: $(hdrdir)/ruby/internal/core/robject.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rregexp.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rstring.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rstruct.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+memory_view.o: $(hdrdir)/ruby/internal/ctype.h
+memory_view.o: $(hdrdir)/ruby/internal/dllexport.h
+memory_view.o: $(hdrdir)/ruby/internal/dosish.h
+memory_view.o: $(hdrdir)/ruby/internal/error.h
+memory_view.o: $(hdrdir)/ruby/internal/eval.h
+memory_view.o: $(hdrdir)/ruby/internal/event.h
+memory_view.o: $(hdrdir)/ruby/internal/fl_type.h
+memory_view.o: $(hdrdir)/ruby/internal/gc.h
+memory_view.o: $(hdrdir)/ruby/internal/glob.h
+memory_view.o: $(hdrdir)/ruby/internal/globals.h
+memory_view.o: $(hdrdir)/ruby/internal/has/attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/builtin.h
+memory_view.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/extension.h
+memory_view.o: $(hdrdir)/ruby/internal/has/feature.h
+memory_view.o: $(hdrdir)/ruby/internal/has/warning.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/array.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/bignum.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/class.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/compar.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/complex.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/cont.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/dir.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/enum.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/error.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/eval.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/file.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/gc.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/hash.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/io.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/load.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/marshal.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/numeric.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/object.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/parse.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/proc.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/process.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/random.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/range.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/rational.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/re.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/ruby.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/select.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/signal.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/string.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/struct.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/thread.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/time.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/variable.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/vm.h
+memory_view.o: $(hdrdir)/ruby/internal/interpreter.h
+memory_view.o: $(hdrdir)/ruby/internal/iterator.h
+memory_view.o: $(hdrdir)/ruby/internal/memory.h
+memory_view.o: $(hdrdir)/ruby/internal/method.h
+memory_view.o: $(hdrdir)/ruby/internal/module.h
+memory_view.o: $(hdrdir)/ruby/internal/newobj.h
+memory_view.o: $(hdrdir)/ruby/internal/rgengc.h
+memory_view.o: $(hdrdir)/ruby/internal/scan_args.h
+memory_view.o: $(hdrdir)/ruby/internal/special_consts.h
+memory_view.o: $(hdrdir)/ruby/internal/static_assert.h
+memory_view.o: $(hdrdir)/ruby/internal/stdalign.h
+memory_view.o: $(hdrdir)/ruby/internal/stdbool.h
+memory_view.o: $(hdrdir)/ruby/internal/symbol.h
+memory_view.o: $(hdrdir)/ruby/internal/token_paste.h
+memory_view.o: $(hdrdir)/ruby/internal/value.h
+memory_view.o: $(hdrdir)/ruby/internal/value_type.h
+memory_view.o: $(hdrdir)/ruby/internal/variable.h
+memory_view.o: $(hdrdir)/ruby/internal/warning_push.h
+memory_view.o: $(hdrdir)/ruby/internal/xmalloc.h
+memory_view.o: $(hdrdir)/ruby/memory_view.h
+memory_view.o: $(hdrdir)/ruby/missing.h
+memory_view.o: $(hdrdir)/ruby/ruby.h
+memory_view.o: $(hdrdir)/ruby/st.h
+memory_view.o: $(hdrdir)/ruby/subst.h
+memory_view.o: memory_view.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/memory_view/extconf.rb b/ext/-test-/memory_view/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/memory_view/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/memory_view/memory_view.c b/ext/-test-/memory_view/memory_view.c
new file mode 100644
index 0000000000..3156dd3101
--- /dev/null
+++ b/ext/-test-/memory_view/memory_view.c
@@ -0,0 +1,446 @@
+#include "ruby.h"
+#include "ruby/memory_view.h"
+
+#define STRUCT_ALIGNOF(T, result) do { \
+ (result) = RUBY_ALIGNOF(T); \
+} while(0)
+
+static ID id_str;
+static VALUE sym_format;
+static VALUE sym_native_size_p;
+static VALUE sym_offset;
+static VALUE sym_size;
+static VALUE sym_repeat;
+static VALUE sym_obj;
+static VALUE sym_byte_size;
+static VALUE sym_readonly;
+static VALUE sym_format;
+static VALUE sym_item_size;
+static VALUE sym_ndim;
+static VALUE sym_shape;
+static VALUE sym_strides;
+static VALUE sym_sub_offsets;
+static VALUE sym_endianness;
+static VALUE sym_little_endian;
+static VALUE sym_big_endian;
+
+static bool
+exportable_string_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
+{
+ VALUE str = rb_ivar_get(obj, id_str);
+ rb_memory_view_init_as_byte_array(view, obj, RSTRING_PTR(str), RSTRING_LEN(str), true);
+ return true;
+}
+
+static bool
+exportable_string_memory_view_available_p(VALUE obj)
+{
+ VALUE str = rb_ivar_get(obj, id_str);
+ return !NIL_P(str);
+}
+
+static const rb_memory_view_entry_t exportable_string_memory_view_entry = {
+ exportable_string_get_memory_view,
+ NULL,
+ exportable_string_memory_view_available_p
+};
+
+static VALUE
+memory_view_available_p(VALUE mod, VALUE obj)
+{
+ return rb_memory_view_available_p(obj) ? Qtrue : Qfalse;
+}
+
+static VALUE
+memory_view_register(VALUE mod, VALUE obj)
+{
+ return rb_memory_view_register(obj, &exportable_string_memory_view_entry) ? Qtrue : Qfalse;
+}
+
+static VALUE
+memory_view_item_size_from_format(VALUE mod, VALUE format)
+{
+ const char *c_str = NULL;
+ if (!NIL_P(format))
+ c_str = StringValueCStr(format);
+ const char *err = NULL;
+ ssize_t item_size = rb_memory_view_item_size_from_format(c_str, &err);
+ if (!err)
+ return rb_assoc_new(SSIZET2NUM(item_size), Qnil);
+ else
+ return rb_assoc_new(SSIZET2NUM(item_size), rb_str_new_cstr(err));
+}
+
+static VALUE
+memory_view_parse_item_format(VALUE mod, VALUE format)
+{
+ const char *c_str = NULL;
+ if (!NIL_P(format))
+ c_str = StringValueCStr(format);
+ const char *err = NULL;
+
+ rb_memory_view_item_component_t *members;
+ size_t n_members;
+ ssize_t item_size = rb_memory_view_parse_item_format(c_str, &members, &n_members, &err);
+
+ VALUE result = rb_ary_new_capa(3);
+ rb_ary_push(result, SSIZET2NUM(item_size));
+
+ if (!err) {
+ VALUE ary = rb_ary_new_capa((long)n_members);
+ size_t i;
+ for (i = 0; i < n_members; ++i) {
+ VALUE member = rb_hash_new();
+ rb_hash_aset(member, sym_format, rb_str_new(&members[i].format, 1));
+ rb_hash_aset(member, sym_native_size_p, members[i].native_size_p ? Qtrue : Qfalse);
+ rb_hash_aset(member, sym_endianness, members[i].little_endian_p ? sym_little_endian : sym_big_endian);
+ rb_hash_aset(member, sym_offset, SSIZET2NUM(members[i].offset));
+ rb_hash_aset(member, sym_size, SSIZET2NUM(members[i].size));
+ rb_hash_aset(member, sym_repeat, SSIZET2NUM(members[i].repeat));
+ rb_ary_push(ary, member);
+ }
+ xfree(members);
+ rb_ary_push(result, ary);
+ rb_ary_push(result, Qnil);
+ }
+ else {
+ rb_ary_push(result, Qnil); // members
+ rb_ary_push(result, rb_str_new_cstr(err));
+ }
+
+ return result;
+}
+
+static VALUE
+memory_view_get_memory_view_info(VALUE mod, VALUE obj)
+{
+ rb_memory_view_t view;
+
+ if (!rb_memory_view_get(obj, &view, 0)) {
+ return Qnil;
+ }
+
+ VALUE hash = rb_hash_new();
+ rb_hash_aset(hash, sym_obj, view.obj);
+ rb_hash_aset(hash, sym_byte_size, SSIZET2NUM(view.byte_size));
+ rb_hash_aset(hash, sym_readonly, view.readonly ? Qtrue : Qfalse);
+ rb_hash_aset(hash, sym_format, view.format ? rb_str_new_cstr(view.format) : Qnil);
+ rb_hash_aset(hash, sym_item_size, SSIZET2NUM(view.item_size));
+ rb_hash_aset(hash, sym_ndim, SSIZET2NUM(view.ndim));
+
+ if (view.shape) {
+ VALUE shape = rb_ary_new_capa(view.ndim);
+ rb_hash_aset(hash, sym_shape, shape);
+ }
+ else {
+ rb_hash_aset(hash, sym_shape, Qnil);
+ }
+
+ if (view.strides) {
+ VALUE strides = rb_ary_new_capa(view.ndim);
+ rb_hash_aset(hash, sym_strides, strides);
+ }
+ else {
+ rb_hash_aset(hash, sym_strides, Qnil);
+ }
+
+ if (view.sub_offsets) {
+ VALUE sub_offsets = rb_ary_new_capa(view.ndim);
+ rb_hash_aset(hash, sym_sub_offsets, sub_offsets);
+ }
+ else {
+ rb_hash_aset(hash, sym_sub_offsets, Qnil);
+ }
+
+ rb_memory_view_release(&view);
+
+ return hash;
+}
+
+static VALUE
+memory_view_fill_contiguous_strides(VALUE mod, VALUE ndim_v, VALUE item_size_v, VALUE shape_v, VALUE row_major_p)
+{
+ ssize_t i, ndim = NUM2SSIZET(ndim_v);
+
+ Check_Type(shape_v, T_ARRAY);
+ ssize_t *shape = ALLOC_N(ssize_t, ndim);
+ for (i = 0; i < ndim; ++i) {
+ shape[i] = NUM2SSIZET(RARRAY_AREF(shape_v, i));
+ }
+
+ ssize_t *strides = ALLOC_N(ssize_t, ndim);
+ rb_memory_view_fill_contiguous_strides(ndim, NUM2SSIZET(item_size_v), shape, RTEST(row_major_p), strides);
+
+ VALUE result = rb_ary_new_capa(ndim);
+ for (i = 0; i < ndim; ++i) {
+ rb_ary_push(result, SSIZET2NUM(strides[i]));
+ }
+
+ xfree(strides);
+ xfree(shape);
+
+ return result;
+}
+
+static VALUE
+memory_view_get_ref_count(VALUE obj)
+{
+ extern VALUE rb_memory_view_exported_object_registry;
+ extern const rb_data_type_t rb_memory_view_exported_object_registry_data_type;
+
+ if (rb_memory_view_exported_object_registry == Qundef) {
+ return Qnil;
+ }
+
+ st_table *table;
+ TypedData_Get_Struct(rb_memory_view_exported_object_registry, st_table,
+ &rb_memory_view_exported_object_registry_data_type,
+ table);
+
+ st_data_t count;
+ if (st_lookup(table, (st_data_t)obj, &count)) {
+ return ULL2NUM(count);
+ }
+
+ return Qnil;
+}
+
+static VALUE
+memory_view_ref_count_while_exporting_i(VALUE obj, long n)
+{
+ if (n == 0) {
+ return memory_view_get_ref_count(obj);
+ }
+
+ rb_memory_view_t view;
+ if (!rb_memory_view_get(obj, &view, 0)) {
+ return Qnil;
+ }
+
+ VALUE ref_count = memory_view_ref_count_while_exporting_i(obj, n-1);
+ rb_memory_view_release(&view);
+
+ return ref_count;
+}
+
+static VALUE
+memory_view_ref_count_while_exporting(VALUE mod, VALUE obj, VALUE n)
+{
+ Check_Type(n, T_FIXNUM);
+ return memory_view_ref_count_while_exporting_i(obj, FIX2LONG(n));
+}
+
+static VALUE
+memory_view_extract_item_members(VALUE mod, VALUE str, VALUE format)
+{
+ StringValue(str);
+ StringValue(format);
+
+ rb_memory_view_item_component_t *members;
+ size_t n_members;
+ const char *err = NULL;
+ (void)rb_memory_view_parse_item_format(RSTRING_PTR(format), &members, &n_members, &err);
+ if (err != NULL) {
+ rb_raise(rb_eArgError, "Unable to parse item format");
+ }
+
+ VALUE item = rb_memory_view_extract_item_members(RSTRING_PTR(str), members, n_members);
+ xfree(members);
+
+ return item;
+}
+
+static VALUE
+expstr_initialize(VALUE obj, VALUE s)
+{
+ if (!NIL_P(s)) {
+ Check_Type(s, T_STRING);
+ }
+ rb_ivar_set(obj, id_str, s);
+ return Qnil;
+}
+
+static bool
+mdview_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
+{
+ VALUE buf_v = rb_ivar_get(obj, id_str);
+ VALUE format_v = rb_ivar_get(obj, SYM2ID(sym_format));
+ VALUE shape_v = rb_ivar_get(obj, SYM2ID(sym_shape));
+ VALUE strides_v = rb_ivar_get(obj, SYM2ID(sym_strides));
+
+ const char *err;
+ const ssize_t item_size = rb_memory_view_item_size_from_format(RSTRING_PTR(format_v), &err);
+ if (item_size < 0) {
+ return false;
+ }
+
+ ssize_t ndim = RARRAY_LEN(shape_v);
+ if (!NIL_P(strides_v) && RARRAY_LEN(strides_v) != ndim) {
+ rb_raise(rb_eArgError, "strides has an invalid dimension");
+ }
+
+ ssize_t *shape = ALLOC_N(ssize_t, ndim);
+ ssize_t *strides = ALLOC_N(ssize_t, ndim);
+ ssize_t i;
+ if (!NIL_P(strides_v)) {
+ for (i = 0; i < ndim; ++i) {
+ shape[i] = NUM2SSIZET(RARRAY_AREF(shape_v, i));
+ strides[i] = NUM2SSIZET(RARRAY_AREF(strides_v, i));
+ }
+ }
+ else {
+ for (i = 0; i < ndim; ++i) {
+ shape[i] = NUM2SSIZET(RARRAY_AREF(shape_v, i));
+ }
+
+ i = ndim - 1;
+ strides[i] = item_size;
+ for (; i > 0; --i) {
+ strides[i-1] = strides[i] * shape[i];
+ }
+ }
+
+ rb_memory_view_init_as_byte_array(view, obj, RSTRING_PTR(buf_v), RSTRING_LEN(buf_v), true);
+ view->format = RSTRING_PTR(format_v);
+ view->item_size = item_size;
+ view->ndim = ndim;
+ view->shape = shape;
+ view->strides = strides;
+ view->sub_offsets = NULL;
+
+ return true;
+}
+
+static bool
+mdview_release_memory_view(VALUE obj, rb_memory_view_t *view)
+{
+ if (view->shape) xfree((void *)view->shape);
+ if (view->strides) xfree((void *)view->strides);
+
+ return true;
+}
+
+static bool
+mdview_memory_view_available_p(VALUE obj)
+{
+ return true;
+}
+
+static const rb_memory_view_entry_t mdview_memory_view_entry = {
+ mdview_get_memory_view,
+ mdview_release_memory_view,
+ mdview_memory_view_available_p
+};
+
+static VALUE
+mdview_initialize(VALUE obj, VALUE buf, VALUE format, VALUE shape, VALUE strides)
+{
+ Check_Type(buf, T_STRING);
+ StringValue(format);
+ Check_Type(shape, T_ARRAY);
+ if (!NIL_P(strides)) Check_Type(strides, T_ARRAY);
+
+ rb_ivar_set(obj, id_str, buf);
+ rb_ivar_set(obj, SYM2ID(sym_format), format);
+ rb_ivar_set(obj, SYM2ID(sym_shape), shape);
+ rb_ivar_set(obj, SYM2ID(sym_strides), strides);
+ return Qnil;
+}
+
+static VALUE
+mdview_aref(VALUE obj, VALUE indices_v)
+{
+ Check_Type(indices_v, T_ARRAY);
+
+ rb_memory_view_t view;
+ if (!rb_memory_view_get(obj, &view, 0)) {
+ rb_raise(rb_eRuntimeError, "rb_memory_view_get: failed");
+ }
+
+ if (RARRAY_LEN(indices_v) != view.ndim) {
+ rb_raise(rb_eKeyError, "Indices has an invalid dimension");
+ }
+
+ VALUE buf_indices;
+ ssize_t *indices = ALLOCV_N(ssize_t, buf_indices, view.ndim);
+
+ ssize_t i;
+ for (i = 0; i < view.ndim; ++i) {
+ indices[i] = NUM2SSIZET(RARRAY_AREF(indices_v, i));
+ }
+
+ VALUE result = rb_memory_view_get_item(&view, indices);
+ ALLOCV_END(buf_indices);
+ rb_memory_view_release(&view);
+
+ return result;
+}
+
+void
+Init_memory_view(void)
+{
+ rb_ext_ractor_safe(true);
+ VALUE mMemoryViewTestUtils = rb_define_module("MemoryViewTestUtils");
+
+ rb_define_module_function(mMemoryViewTestUtils, "available?", memory_view_available_p, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "register", memory_view_register, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "item_size_from_format", memory_view_item_size_from_format, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "parse_item_format", memory_view_parse_item_format, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "get_memory_view_info", memory_view_get_memory_view_info, 1);
+ rb_define_module_function(mMemoryViewTestUtils, "fill_contiguous_strides", memory_view_fill_contiguous_strides, 4);
+ rb_define_module_function(mMemoryViewTestUtils, "ref_count_while_exporting", memory_view_ref_count_while_exporting, 2);
+ rb_define_module_function(mMemoryViewTestUtils, "extract_item_members", memory_view_extract_item_members, 2);
+
+ VALUE cExportableString = rb_define_class_under(mMemoryViewTestUtils, "ExportableString", rb_cObject);
+ rb_define_method(cExportableString, "initialize", expstr_initialize, 1);
+ rb_memory_view_register(cExportableString, &exportable_string_memory_view_entry);
+
+ VALUE cMDView = rb_define_class_under(mMemoryViewTestUtils, "MultiDimensionalView", rb_cObject);
+ rb_define_method(cMDView, "initialize", mdview_initialize, 4);
+ rb_define_method(cMDView, "[]", mdview_aref, 1);
+ rb_memory_view_register(cMDView, &mdview_memory_view_entry);
+
+ id_str = rb_intern_const("__str__");
+ sym_format = ID2SYM(rb_intern_const("format"));
+ sym_native_size_p = ID2SYM(rb_intern_const("native_size_p"));
+ sym_offset = ID2SYM(rb_intern_const("offset"));
+ sym_size = ID2SYM(rb_intern_const("size"));
+ sym_repeat = ID2SYM(rb_intern_const("repeat"));
+ sym_obj = ID2SYM(rb_intern_const("obj"));
+ sym_byte_size = ID2SYM(rb_intern_const("byte_size"));
+ sym_readonly = ID2SYM(rb_intern_const("readonly"));
+ sym_format = ID2SYM(rb_intern_const("format"));
+ sym_item_size = ID2SYM(rb_intern_const("item_size"));
+ sym_ndim = ID2SYM(rb_intern_const("ndim"));
+ sym_shape = ID2SYM(rb_intern_const("shape"));
+ sym_strides = ID2SYM(rb_intern_const("strides"));
+ sym_sub_offsets = ID2SYM(rb_intern_const("sub_offsets"));
+ sym_endianness = ID2SYM(rb_intern_const("endianness"));
+ sym_little_endian = ID2SYM(rb_intern_const("little_endian"));
+ sym_big_endian = ID2SYM(rb_intern_const("big_endian"));
+
+#ifdef WORDS_BIGENDIAN
+ rb_const_set(mMemoryViewTestUtils, rb_intern_const("NATIVE_ENDIAN"), sym_big_endian);
+#else
+ rb_const_set(mMemoryViewTestUtils, rb_intern_const("NATIVE_ENDIAN"), sym_little_endian);
+#endif
+
+#define DEF_ALIGNMENT_CONST(type, TYPE) do { \
+ int alignment; \
+ STRUCT_ALIGNOF(type, alignment); \
+ rb_const_set(mMemoryViewTestUtils, rb_intern_const(#TYPE "_ALIGNMENT"), INT2FIX(alignment)); \
+} while(0)
+
+ DEF_ALIGNMENT_CONST(short, SHORT);
+ DEF_ALIGNMENT_CONST(int, INT);
+ DEF_ALIGNMENT_CONST(long, LONG);
+ DEF_ALIGNMENT_CONST(LONG_LONG, LONG_LONG);
+ DEF_ALIGNMENT_CONST(int16_t, INT16);
+ DEF_ALIGNMENT_CONST(int32_t, INT32);
+ DEF_ALIGNMENT_CONST(int64_t, INT64);
+ DEF_ALIGNMENT_CONST(intptr_t, INTPTR);
+ DEF_ALIGNMENT_CONST(float, FLOAT);
+ DEF_ALIGNMENT_CONST(double, DOUBLE);
+
+#undef DEF_ALIGNMENT_CONST
+}
diff --git a/ext/-test-/method/depend b/ext/-test-/method/depend
index 028d97e1a9..7fdf2bc929 100644
--- a/ext/-test-/method/depend
+++ b/ext/-test-/method/depend
@@ -2,8 +2,157 @@
arity.o: $(RUBY_EXTCONF_H)
arity.o: $(arch_hdrdir)/ruby/config.h
arity.o: $(hdrdir)/ruby.h
+arity.o: $(hdrdir)/ruby/internal/anyargs.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+arity.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+arity.o: $(hdrdir)/ruby/internal/assume.h
+arity.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+arity.o: $(hdrdir)/ruby/internal/attr/artificial.h
+arity.o: $(hdrdir)/ruby/internal/attr/cold.h
+arity.o: $(hdrdir)/ruby/internal/attr/const.h
+arity.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+arity.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+arity.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+arity.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+arity.o: $(hdrdir)/ruby/internal/attr/error.h
+arity.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+arity.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+arity.o: $(hdrdir)/ruby/internal/attr/format.h
+arity.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+arity.o: $(hdrdir)/ruby/internal/attr/noalias.h
+arity.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+arity.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+arity.o: $(hdrdir)/ruby/internal/attr/noinline.h
+arity.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+arity.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+arity.o: $(hdrdir)/ruby/internal/attr/pure.h
+arity.o: $(hdrdir)/ruby/internal/attr/restrict.h
+arity.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+arity.o: $(hdrdir)/ruby/internal/attr/warning.h
+arity.o: $(hdrdir)/ruby/internal/attr/weakref.h
+arity.o: $(hdrdir)/ruby/internal/cast.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+arity.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+arity.o: $(hdrdir)/ruby/internal/compiler_since.h
+arity.o: $(hdrdir)/ruby/internal/config.h
+arity.o: $(hdrdir)/ruby/internal/constant_p.h
+arity.o: $(hdrdir)/ruby/internal/core.h
+arity.o: $(hdrdir)/ruby/internal/core/rarray.h
+arity.o: $(hdrdir)/ruby/internal/core/rbasic.h
+arity.o: $(hdrdir)/ruby/internal/core/rbignum.h
+arity.o: $(hdrdir)/ruby/internal/core/rclass.h
+arity.o: $(hdrdir)/ruby/internal/core/rdata.h
+arity.o: $(hdrdir)/ruby/internal/core/rfile.h
+arity.o: $(hdrdir)/ruby/internal/core/rhash.h
+arity.o: $(hdrdir)/ruby/internal/core/robject.h
+arity.o: $(hdrdir)/ruby/internal/core/rregexp.h
+arity.o: $(hdrdir)/ruby/internal/core/rstring.h
+arity.o: $(hdrdir)/ruby/internal/core/rstruct.h
+arity.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+arity.o: $(hdrdir)/ruby/internal/ctype.h
+arity.o: $(hdrdir)/ruby/internal/dllexport.h
+arity.o: $(hdrdir)/ruby/internal/dosish.h
+arity.o: $(hdrdir)/ruby/internal/error.h
+arity.o: $(hdrdir)/ruby/internal/eval.h
+arity.o: $(hdrdir)/ruby/internal/event.h
+arity.o: $(hdrdir)/ruby/internal/fl_type.h
+arity.o: $(hdrdir)/ruby/internal/gc.h
+arity.o: $(hdrdir)/ruby/internal/glob.h
+arity.o: $(hdrdir)/ruby/internal/globals.h
+arity.o: $(hdrdir)/ruby/internal/has/attribute.h
+arity.o: $(hdrdir)/ruby/internal/has/builtin.h
+arity.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+arity.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+arity.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+arity.o: $(hdrdir)/ruby/internal/has/extension.h
+arity.o: $(hdrdir)/ruby/internal/has/feature.h
+arity.o: $(hdrdir)/ruby/internal/has/warning.h
+arity.o: $(hdrdir)/ruby/internal/intern/array.h
+arity.o: $(hdrdir)/ruby/internal/intern/bignum.h
+arity.o: $(hdrdir)/ruby/internal/intern/class.h
+arity.o: $(hdrdir)/ruby/internal/intern/compar.h
+arity.o: $(hdrdir)/ruby/internal/intern/complex.h
+arity.o: $(hdrdir)/ruby/internal/intern/cont.h
+arity.o: $(hdrdir)/ruby/internal/intern/dir.h
+arity.o: $(hdrdir)/ruby/internal/intern/enum.h
+arity.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+arity.o: $(hdrdir)/ruby/internal/intern/error.h
+arity.o: $(hdrdir)/ruby/internal/intern/eval.h
+arity.o: $(hdrdir)/ruby/internal/intern/file.h
+arity.o: $(hdrdir)/ruby/internal/intern/gc.h
+arity.o: $(hdrdir)/ruby/internal/intern/hash.h
+arity.o: $(hdrdir)/ruby/internal/intern/io.h
+arity.o: $(hdrdir)/ruby/internal/intern/load.h
+arity.o: $(hdrdir)/ruby/internal/intern/marshal.h
+arity.o: $(hdrdir)/ruby/internal/intern/numeric.h
+arity.o: $(hdrdir)/ruby/internal/intern/object.h
+arity.o: $(hdrdir)/ruby/internal/intern/parse.h
+arity.o: $(hdrdir)/ruby/internal/intern/proc.h
+arity.o: $(hdrdir)/ruby/internal/intern/process.h
+arity.o: $(hdrdir)/ruby/internal/intern/random.h
+arity.o: $(hdrdir)/ruby/internal/intern/range.h
+arity.o: $(hdrdir)/ruby/internal/intern/rational.h
+arity.o: $(hdrdir)/ruby/internal/intern/re.h
+arity.o: $(hdrdir)/ruby/internal/intern/ruby.h
+arity.o: $(hdrdir)/ruby/internal/intern/select.h
+arity.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+arity.o: $(hdrdir)/ruby/internal/intern/signal.h
+arity.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+arity.o: $(hdrdir)/ruby/internal/intern/string.h
+arity.o: $(hdrdir)/ruby/internal/intern/struct.h
+arity.o: $(hdrdir)/ruby/internal/intern/thread.h
+arity.o: $(hdrdir)/ruby/internal/intern/time.h
+arity.o: $(hdrdir)/ruby/internal/intern/variable.h
+arity.o: $(hdrdir)/ruby/internal/intern/vm.h
+arity.o: $(hdrdir)/ruby/internal/interpreter.h
+arity.o: $(hdrdir)/ruby/internal/iterator.h
+arity.o: $(hdrdir)/ruby/internal/memory.h
+arity.o: $(hdrdir)/ruby/internal/method.h
+arity.o: $(hdrdir)/ruby/internal/module.h
+arity.o: $(hdrdir)/ruby/internal/newobj.h
+arity.o: $(hdrdir)/ruby/internal/rgengc.h
+arity.o: $(hdrdir)/ruby/internal/scan_args.h
+arity.o: $(hdrdir)/ruby/internal/special_consts.h
+arity.o: $(hdrdir)/ruby/internal/static_assert.h
+arity.o: $(hdrdir)/ruby/internal/stdalign.h
+arity.o: $(hdrdir)/ruby/internal/stdbool.h
+arity.o: $(hdrdir)/ruby/internal/symbol.h
+arity.o: $(hdrdir)/ruby/internal/token_paste.h
+arity.o: $(hdrdir)/ruby/internal/value.h
+arity.o: $(hdrdir)/ruby/internal/value_type.h
+arity.o: $(hdrdir)/ruby/internal/variable.h
+arity.o: $(hdrdir)/ruby/internal/warning_push.h
+arity.o: $(hdrdir)/ruby/internal/xmalloc.h
arity.o: $(hdrdir)/ruby/assert.h
arity.o: $(hdrdir)/ruby/backward.h
+arity.o: $(hdrdir)/ruby/backward/2/assume.h
+arity.o: $(hdrdir)/ruby/backward/2/attributes.h
+arity.o: $(hdrdir)/ruby/backward/2/bool.h
+arity.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+arity.o: $(hdrdir)/ruby/backward/2/inttypes.h
+arity.o: $(hdrdir)/ruby/backward/2/limits.h
+arity.o: $(hdrdir)/ruby/backward/2/long_long.h
+arity.o: $(hdrdir)/ruby/backward/2/stdalign.h
+arity.o: $(hdrdir)/ruby/backward/2/stdarg.h
arity.o: $(hdrdir)/ruby/defines.h
arity.o: $(hdrdir)/ruby/intern.h
arity.o: $(hdrdir)/ruby/missing.h
@@ -14,8 +163,157 @@ arity.o: arity.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/notimplement/depend b/ext/-test-/notimplement/depend
index 74911f0af4..a21935558d 100644
--- a/ext/-test-/notimplement/depend
+++ b/ext/-test-/notimplement/depend
@@ -2,8 +2,157 @@
bug.o: $(RUBY_EXTCONF_H)
bug.o: $(arch_hdrdir)/ruby/config.h
bug.o: $(hdrdir)/ruby.h
+bug.o: $(hdrdir)/ruby/internal/anyargs.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug.o: $(hdrdir)/ruby/internal/assume.h
+bug.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug.o: $(hdrdir)/ruby/internal/attr/const.h
+bug.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug.o: $(hdrdir)/ruby/internal/attr/error.h
+bug.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/format.h
+bug.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug.o: $(hdrdir)/ruby/internal/cast.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug.o: $(hdrdir)/ruby/internal/config.h
+bug.o: $(hdrdir)/ruby/internal/constant_p.h
+bug.o: $(hdrdir)/ruby/internal/core.h
+bug.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug.o: $(hdrdir)/ruby/internal/core/robject.h
+bug.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug.o: $(hdrdir)/ruby/internal/ctype.h
+bug.o: $(hdrdir)/ruby/internal/dllexport.h
+bug.o: $(hdrdir)/ruby/internal/dosish.h
+bug.o: $(hdrdir)/ruby/internal/error.h
+bug.o: $(hdrdir)/ruby/internal/eval.h
+bug.o: $(hdrdir)/ruby/internal/event.h
+bug.o: $(hdrdir)/ruby/internal/fl_type.h
+bug.o: $(hdrdir)/ruby/internal/gc.h
+bug.o: $(hdrdir)/ruby/internal/glob.h
+bug.o: $(hdrdir)/ruby/internal/globals.h
+bug.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug.o: $(hdrdir)/ruby/internal/has/extension.h
+bug.o: $(hdrdir)/ruby/internal/has/feature.h
+bug.o: $(hdrdir)/ruby/internal/has/warning.h
+bug.o: $(hdrdir)/ruby/internal/intern/array.h
+bug.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug.o: $(hdrdir)/ruby/internal/intern/class.h
+bug.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug.o: $(hdrdir)/ruby/internal/intern/error.h
+bug.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug.o: $(hdrdir)/ruby/internal/intern/file.h
+bug.o: $(hdrdir)/ruby/internal/intern/gc.h
+bug.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug.o: $(hdrdir)/ruby/internal/intern/io.h
+bug.o: $(hdrdir)/ruby/internal/intern/load.h
+bug.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug.o: $(hdrdir)/ruby/internal/intern/object.h
+bug.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug.o: $(hdrdir)/ruby/internal/intern/process.h
+bug.o: $(hdrdir)/ruby/internal/intern/random.h
+bug.o: $(hdrdir)/ruby/internal/intern/range.h
+bug.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug.o: $(hdrdir)/ruby/internal/intern/re.h
+bug.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug.o: $(hdrdir)/ruby/internal/intern/select.h
+bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug.o: $(hdrdir)/ruby/internal/intern/string.h
+bug.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug.o: $(hdrdir)/ruby/internal/intern/time.h
+bug.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug.o: $(hdrdir)/ruby/internal/interpreter.h
+bug.o: $(hdrdir)/ruby/internal/iterator.h
+bug.o: $(hdrdir)/ruby/internal/memory.h
+bug.o: $(hdrdir)/ruby/internal/method.h
+bug.o: $(hdrdir)/ruby/internal/module.h
+bug.o: $(hdrdir)/ruby/internal/newobj.h
+bug.o: $(hdrdir)/ruby/internal/rgengc.h
+bug.o: $(hdrdir)/ruby/internal/scan_args.h
+bug.o: $(hdrdir)/ruby/internal/special_consts.h
+bug.o: $(hdrdir)/ruby/internal/static_assert.h
+bug.o: $(hdrdir)/ruby/internal/stdalign.h
+bug.o: $(hdrdir)/ruby/internal/stdbool.h
+bug.o: $(hdrdir)/ruby/internal/symbol.h
+bug.o: $(hdrdir)/ruby/internal/token_paste.h
+bug.o: $(hdrdir)/ruby/internal/value.h
+bug.o: $(hdrdir)/ruby/internal/value_type.h
+bug.o: $(hdrdir)/ruby/internal/variable.h
+bug.o: $(hdrdir)/ruby/internal/warning_push.h
+bug.o: $(hdrdir)/ruby/internal/xmalloc.h
bug.o: $(hdrdir)/ruby/assert.h
bug.o: $(hdrdir)/ruby/backward.h
+bug.o: $(hdrdir)/ruby/backward/2/assume.h
+bug.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug.o: $(hdrdir)/ruby/backward/2/bool.h
+bug.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+bug.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug.o: $(hdrdir)/ruby/backward/2/limits.h
+bug.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug.o: $(hdrdir)/ruby/backward/2/stdarg.h
bug.o: $(hdrdir)/ruby/defines.h
bug.o: $(hdrdir)/ruby/intern.h
bug.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/num2int/depend b/ext/-test-/num2int/depend
index 76b69de851..4b455d12f6 100644
--- a/ext/-test-/num2int/depend
+++ b/ext/-test-/num2int/depend
@@ -2,8 +2,157 @@
num2int.o: $(RUBY_EXTCONF_H)
num2int.o: $(arch_hdrdir)/ruby/config.h
num2int.o: $(hdrdir)/ruby.h
+num2int.o: $(hdrdir)/ruby/internal/anyargs.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+num2int.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+num2int.o: $(hdrdir)/ruby/internal/assume.h
+num2int.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+num2int.o: $(hdrdir)/ruby/internal/attr/artificial.h
+num2int.o: $(hdrdir)/ruby/internal/attr/cold.h
+num2int.o: $(hdrdir)/ruby/internal/attr/const.h
+num2int.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+num2int.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+num2int.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+num2int.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+num2int.o: $(hdrdir)/ruby/internal/attr/error.h
+num2int.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+num2int.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+num2int.o: $(hdrdir)/ruby/internal/attr/format.h
+num2int.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+num2int.o: $(hdrdir)/ruby/internal/attr/noalias.h
+num2int.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+num2int.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+num2int.o: $(hdrdir)/ruby/internal/attr/noinline.h
+num2int.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+num2int.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+num2int.o: $(hdrdir)/ruby/internal/attr/pure.h
+num2int.o: $(hdrdir)/ruby/internal/attr/restrict.h
+num2int.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+num2int.o: $(hdrdir)/ruby/internal/attr/warning.h
+num2int.o: $(hdrdir)/ruby/internal/attr/weakref.h
+num2int.o: $(hdrdir)/ruby/internal/cast.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+num2int.o: $(hdrdir)/ruby/internal/compiler_since.h
+num2int.o: $(hdrdir)/ruby/internal/config.h
+num2int.o: $(hdrdir)/ruby/internal/constant_p.h
+num2int.o: $(hdrdir)/ruby/internal/core.h
+num2int.o: $(hdrdir)/ruby/internal/core/rarray.h
+num2int.o: $(hdrdir)/ruby/internal/core/rbasic.h
+num2int.o: $(hdrdir)/ruby/internal/core/rbignum.h
+num2int.o: $(hdrdir)/ruby/internal/core/rclass.h
+num2int.o: $(hdrdir)/ruby/internal/core/rdata.h
+num2int.o: $(hdrdir)/ruby/internal/core/rfile.h
+num2int.o: $(hdrdir)/ruby/internal/core/rhash.h
+num2int.o: $(hdrdir)/ruby/internal/core/robject.h
+num2int.o: $(hdrdir)/ruby/internal/core/rregexp.h
+num2int.o: $(hdrdir)/ruby/internal/core/rstring.h
+num2int.o: $(hdrdir)/ruby/internal/core/rstruct.h
+num2int.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+num2int.o: $(hdrdir)/ruby/internal/ctype.h
+num2int.o: $(hdrdir)/ruby/internal/dllexport.h
+num2int.o: $(hdrdir)/ruby/internal/dosish.h
+num2int.o: $(hdrdir)/ruby/internal/error.h
+num2int.o: $(hdrdir)/ruby/internal/eval.h
+num2int.o: $(hdrdir)/ruby/internal/event.h
+num2int.o: $(hdrdir)/ruby/internal/fl_type.h
+num2int.o: $(hdrdir)/ruby/internal/gc.h
+num2int.o: $(hdrdir)/ruby/internal/glob.h
+num2int.o: $(hdrdir)/ruby/internal/globals.h
+num2int.o: $(hdrdir)/ruby/internal/has/attribute.h
+num2int.o: $(hdrdir)/ruby/internal/has/builtin.h
+num2int.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+num2int.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+num2int.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+num2int.o: $(hdrdir)/ruby/internal/has/extension.h
+num2int.o: $(hdrdir)/ruby/internal/has/feature.h
+num2int.o: $(hdrdir)/ruby/internal/has/warning.h
+num2int.o: $(hdrdir)/ruby/internal/intern/array.h
+num2int.o: $(hdrdir)/ruby/internal/intern/bignum.h
+num2int.o: $(hdrdir)/ruby/internal/intern/class.h
+num2int.o: $(hdrdir)/ruby/internal/intern/compar.h
+num2int.o: $(hdrdir)/ruby/internal/intern/complex.h
+num2int.o: $(hdrdir)/ruby/internal/intern/cont.h
+num2int.o: $(hdrdir)/ruby/internal/intern/dir.h
+num2int.o: $(hdrdir)/ruby/internal/intern/enum.h
+num2int.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+num2int.o: $(hdrdir)/ruby/internal/intern/error.h
+num2int.o: $(hdrdir)/ruby/internal/intern/eval.h
+num2int.o: $(hdrdir)/ruby/internal/intern/file.h
+num2int.o: $(hdrdir)/ruby/internal/intern/gc.h
+num2int.o: $(hdrdir)/ruby/internal/intern/hash.h
+num2int.o: $(hdrdir)/ruby/internal/intern/io.h
+num2int.o: $(hdrdir)/ruby/internal/intern/load.h
+num2int.o: $(hdrdir)/ruby/internal/intern/marshal.h
+num2int.o: $(hdrdir)/ruby/internal/intern/numeric.h
+num2int.o: $(hdrdir)/ruby/internal/intern/object.h
+num2int.o: $(hdrdir)/ruby/internal/intern/parse.h
+num2int.o: $(hdrdir)/ruby/internal/intern/proc.h
+num2int.o: $(hdrdir)/ruby/internal/intern/process.h
+num2int.o: $(hdrdir)/ruby/internal/intern/random.h
+num2int.o: $(hdrdir)/ruby/internal/intern/range.h
+num2int.o: $(hdrdir)/ruby/internal/intern/rational.h
+num2int.o: $(hdrdir)/ruby/internal/intern/re.h
+num2int.o: $(hdrdir)/ruby/internal/intern/ruby.h
+num2int.o: $(hdrdir)/ruby/internal/intern/select.h
+num2int.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+num2int.o: $(hdrdir)/ruby/internal/intern/signal.h
+num2int.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+num2int.o: $(hdrdir)/ruby/internal/intern/string.h
+num2int.o: $(hdrdir)/ruby/internal/intern/struct.h
+num2int.o: $(hdrdir)/ruby/internal/intern/thread.h
+num2int.o: $(hdrdir)/ruby/internal/intern/time.h
+num2int.o: $(hdrdir)/ruby/internal/intern/variable.h
+num2int.o: $(hdrdir)/ruby/internal/intern/vm.h
+num2int.o: $(hdrdir)/ruby/internal/interpreter.h
+num2int.o: $(hdrdir)/ruby/internal/iterator.h
+num2int.o: $(hdrdir)/ruby/internal/memory.h
+num2int.o: $(hdrdir)/ruby/internal/method.h
+num2int.o: $(hdrdir)/ruby/internal/module.h
+num2int.o: $(hdrdir)/ruby/internal/newobj.h
+num2int.o: $(hdrdir)/ruby/internal/rgengc.h
+num2int.o: $(hdrdir)/ruby/internal/scan_args.h
+num2int.o: $(hdrdir)/ruby/internal/special_consts.h
+num2int.o: $(hdrdir)/ruby/internal/static_assert.h
+num2int.o: $(hdrdir)/ruby/internal/stdalign.h
+num2int.o: $(hdrdir)/ruby/internal/stdbool.h
+num2int.o: $(hdrdir)/ruby/internal/symbol.h
+num2int.o: $(hdrdir)/ruby/internal/token_paste.h
+num2int.o: $(hdrdir)/ruby/internal/value.h
+num2int.o: $(hdrdir)/ruby/internal/value_type.h
+num2int.o: $(hdrdir)/ruby/internal/variable.h
+num2int.o: $(hdrdir)/ruby/internal/warning_push.h
+num2int.o: $(hdrdir)/ruby/internal/xmalloc.h
num2int.o: $(hdrdir)/ruby/assert.h
num2int.o: $(hdrdir)/ruby/backward.h
+num2int.o: $(hdrdir)/ruby/backward/2/assume.h
+num2int.o: $(hdrdir)/ruby/backward/2/attributes.h
+num2int.o: $(hdrdir)/ruby/backward/2/bool.h
+num2int.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+num2int.o: $(hdrdir)/ruby/backward/2/inttypes.h
+num2int.o: $(hdrdir)/ruby/backward/2/limits.h
+num2int.o: $(hdrdir)/ruby/backward/2/long_long.h
+num2int.o: $(hdrdir)/ruby/backward/2/stdalign.h
+num2int.o: $(hdrdir)/ruby/backward/2/stdarg.h
num2int.o: $(hdrdir)/ruby/defines.h
num2int.o: $(hdrdir)/ruby/intern.h
num2int.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/path_to_class/depend b/ext/-test-/path_to_class/depend
index 9a7f7d0176..b51619b905 100644
--- a/ext/-test-/path_to_class/depend
+++ b/ext/-test-/path_to_class/depend
@@ -2,8 +2,157 @@
path_to_class.o: $(RUBY_EXTCONF_H)
path_to_class.o: $(arch_hdrdir)/ruby/config.h
path_to_class.o: $(hdrdir)/ruby.h
+path_to_class.o: $(hdrdir)/ruby/internal/anyargs.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+path_to_class.o: $(hdrdir)/ruby/internal/assume.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/artificial.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/cold.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/const.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/error.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/format.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/noalias.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/noinline.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/pure.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/restrict.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/warning.h
+path_to_class.o: $(hdrdir)/ruby/internal/attr/weakref.h
+path_to_class.o: $(hdrdir)/ruby/internal/cast.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+path_to_class.o: $(hdrdir)/ruby/internal/compiler_since.h
+path_to_class.o: $(hdrdir)/ruby/internal/config.h
+path_to_class.o: $(hdrdir)/ruby/internal/constant_p.h
+path_to_class.o: $(hdrdir)/ruby/internal/core.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rarray.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rbasic.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rbignum.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rclass.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rdata.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rfile.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rhash.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/robject.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rregexp.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rstring.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rstruct.h
+path_to_class.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+path_to_class.o: $(hdrdir)/ruby/internal/ctype.h
+path_to_class.o: $(hdrdir)/ruby/internal/dllexport.h
+path_to_class.o: $(hdrdir)/ruby/internal/dosish.h
+path_to_class.o: $(hdrdir)/ruby/internal/error.h
+path_to_class.o: $(hdrdir)/ruby/internal/eval.h
+path_to_class.o: $(hdrdir)/ruby/internal/event.h
+path_to_class.o: $(hdrdir)/ruby/internal/fl_type.h
+path_to_class.o: $(hdrdir)/ruby/internal/gc.h
+path_to_class.o: $(hdrdir)/ruby/internal/glob.h
+path_to_class.o: $(hdrdir)/ruby/internal/globals.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/attribute.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/builtin.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/extension.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/feature.h
+path_to_class.o: $(hdrdir)/ruby/internal/has/warning.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/array.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/bignum.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/class.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/compar.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/complex.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/cont.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/dir.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/enum.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/error.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/eval.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/file.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/gc.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/hash.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/io.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/load.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/marshal.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/numeric.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/object.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/parse.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/proc.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/process.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/random.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/range.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/rational.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/re.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/ruby.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/select.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/signal.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/string.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/struct.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/thread.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/time.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/variable.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/vm.h
+path_to_class.o: $(hdrdir)/ruby/internal/interpreter.h
+path_to_class.o: $(hdrdir)/ruby/internal/iterator.h
+path_to_class.o: $(hdrdir)/ruby/internal/memory.h
+path_to_class.o: $(hdrdir)/ruby/internal/method.h
+path_to_class.o: $(hdrdir)/ruby/internal/module.h
+path_to_class.o: $(hdrdir)/ruby/internal/newobj.h
+path_to_class.o: $(hdrdir)/ruby/internal/rgengc.h
+path_to_class.o: $(hdrdir)/ruby/internal/scan_args.h
+path_to_class.o: $(hdrdir)/ruby/internal/special_consts.h
+path_to_class.o: $(hdrdir)/ruby/internal/static_assert.h
+path_to_class.o: $(hdrdir)/ruby/internal/stdalign.h
+path_to_class.o: $(hdrdir)/ruby/internal/stdbool.h
+path_to_class.o: $(hdrdir)/ruby/internal/symbol.h
+path_to_class.o: $(hdrdir)/ruby/internal/token_paste.h
+path_to_class.o: $(hdrdir)/ruby/internal/value.h
+path_to_class.o: $(hdrdir)/ruby/internal/value_type.h
+path_to_class.o: $(hdrdir)/ruby/internal/variable.h
+path_to_class.o: $(hdrdir)/ruby/internal/warning_push.h
+path_to_class.o: $(hdrdir)/ruby/internal/xmalloc.h
path_to_class.o: $(hdrdir)/ruby/assert.h
path_to_class.o: $(hdrdir)/ruby/backward.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/assume.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/attributes.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/bool.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/inttypes.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/limits.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/long_long.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/stdalign.h
+path_to_class.o: $(hdrdir)/ruby/backward/2/stdarg.h
path_to_class.o: $(hdrdir)/ruby/defines.h
path_to_class.o: $(hdrdir)/ruby/intern.h
path_to_class.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/popen_deadlock/depend b/ext/-test-/popen_deadlock/depend
index 4c3f3853fd..316e2c6e04 100644
--- a/ext/-test-/popen_deadlock/depend
+++ b/ext/-test-/popen_deadlock/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
infinite_loop_dlsym.o: $(RUBY_EXTCONF_H)
infinite_loop_dlsym.o: $(arch_hdrdir)/ruby/config.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/anyargs.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/assume.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/artificial.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/cold.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/const.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/error.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/format.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noalias.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noinline.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/pure.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/restrict.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/warning.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/attr/weakref.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/cast.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/compiler_since.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/config.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/constant_p.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rarray.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rbasic.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rbignum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rclass.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rdata.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rfile.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rhash.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/robject.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rregexp.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rstring.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rstruct.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/ctype.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/dllexport.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/dosish.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/error.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/eval.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/event.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/fl_type.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/gc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/glob.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/globals.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/attribute.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/builtin.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/extension.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/feature.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/has/warning.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/array.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/bignum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/class.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/compar.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/complex.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/cont.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/dir.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/enum.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/error.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/eval.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/file.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/gc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/hash.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/io.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/load.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/marshal.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/numeric.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/object.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/parse.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/proc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/process.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/random.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/range.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/rational.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/re.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/ruby.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/select.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/signal.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/string.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/struct.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/thread.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/time.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/variable.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/vm.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/interpreter.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/iterator.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/memory.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/method.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/module.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/newobj.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/rgengc.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/scan_args.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/special_consts.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/static_assert.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdalign.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdbool.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/symbol.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/token_paste.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value_type.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/variable.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/warning_push.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/xmalloc.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/assert.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/backward.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/assume.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/attributes.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/bool.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/inttypes.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/limits.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/long_long.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/stdalign.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/backward/2/stdarg.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/defines.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/intern.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/popen_deadlock/extconf.rb b/ext/-test-/popen_deadlock/extconf.rb
index 24a7d79931..6b6ee7a6b8 100644
--- a/ext/-test-/popen_deadlock/extconf.rb
+++ b/ext/-test-/popen_deadlock/extconf.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: false
case RUBY_PLATFORM
when /solaris/i, /linux/i
+ $LDFLAGS << " -ldl"
create_makefile("-test-/popen_deadlock/infinite_loop_dlsym")
end
diff --git a/ext/-test-/postponed_job/depend b/ext/-test-/postponed_job/depend
index 998e2dcc9e..c76cf39089 100644
--- a/ext/-test-/postponed_job/depend
+++ b/ext/-test-/postponed_job/depend
@@ -2,8 +2,157 @@
postponed_job.o: $(RUBY_EXTCONF_H)
postponed_job.o: $(arch_hdrdir)/ruby/config.h
postponed_job.o: $(hdrdir)/ruby.h
+postponed_job.o: $(hdrdir)/ruby/internal/anyargs.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+postponed_job.o: $(hdrdir)/ruby/internal/assume.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/artificial.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/cold.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/const.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/error.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/format.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/noalias.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/noinline.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/pure.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/restrict.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/warning.h
+postponed_job.o: $(hdrdir)/ruby/internal/attr/weakref.h
+postponed_job.o: $(hdrdir)/ruby/internal/cast.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+postponed_job.o: $(hdrdir)/ruby/internal/compiler_since.h
+postponed_job.o: $(hdrdir)/ruby/internal/config.h
+postponed_job.o: $(hdrdir)/ruby/internal/constant_p.h
+postponed_job.o: $(hdrdir)/ruby/internal/core.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rarray.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rbasic.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rbignum.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rclass.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rdata.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rfile.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rhash.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/robject.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rregexp.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rstring.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rstruct.h
+postponed_job.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+postponed_job.o: $(hdrdir)/ruby/internal/ctype.h
+postponed_job.o: $(hdrdir)/ruby/internal/dllexport.h
+postponed_job.o: $(hdrdir)/ruby/internal/dosish.h
+postponed_job.o: $(hdrdir)/ruby/internal/error.h
+postponed_job.o: $(hdrdir)/ruby/internal/eval.h
+postponed_job.o: $(hdrdir)/ruby/internal/event.h
+postponed_job.o: $(hdrdir)/ruby/internal/fl_type.h
+postponed_job.o: $(hdrdir)/ruby/internal/gc.h
+postponed_job.o: $(hdrdir)/ruby/internal/glob.h
+postponed_job.o: $(hdrdir)/ruby/internal/globals.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/attribute.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/builtin.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/extension.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/feature.h
+postponed_job.o: $(hdrdir)/ruby/internal/has/warning.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/array.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/bignum.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/class.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/compar.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/complex.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/cont.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/dir.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/enum.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/error.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/eval.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/file.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/gc.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/hash.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/io.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/load.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/marshal.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/numeric.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/object.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/parse.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/proc.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/process.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/random.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/range.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/rational.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/re.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/ruby.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/select.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/signal.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/string.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/struct.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/thread.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/time.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/variable.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/vm.h
+postponed_job.o: $(hdrdir)/ruby/internal/interpreter.h
+postponed_job.o: $(hdrdir)/ruby/internal/iterator.h
+postponed_job.o: $(hdrdir)/ruby/internal/memory.h
+postponed_job.o: $(hdrdir)/ruby/internal/method.h
+postponed_job.o: $(hdrdir)/ruby/internal/module.h
+postponed_job.o: $(hdrdir)/ruby/internal/newobj.h
+postponed_job.o: $(hdrdir)/ruby/internal/rgengc.h
+postponed_job.o: $(hdrdir)/ruby/internal/scan_args.h
+postponed_job.o: $(hdrdir)/ruby/internal/special_consts.h
+postponed_job.o: $(hdrdir)/ruby/internal/static_assert.h
+postponed_job.o: $(hdrdir)/ruby/internal/stdalign.h
+postponed_job.o: $(hdrdir)/ruby/internal/stdbool.h
+postponed_job.o: $(hdrdir)/ruby/internal/symbol.h
+postponed_job.o: $(hdrdir)/ruby/internal/token_paste.h
+postponed_job.o: $(hdrdir)/ruby/internal/value.h
+postponed_job.o: $(hdrdir)/ruby/internal/value_type.h
+postponed_job.o: $(hdrdir)/ruby/internal/variable.h
+postponed_job.o: $(hdrdir)/ruby/internal/warning_push.h
+postponed_job.o: $(hdrdir)/ruby/internal/xmalloc.h
postponed_job.o: $(hdrdir)/ruby/assert.h
postponed_job.o: $(hdrdir)/ruby/backward.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/assume.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/attributes.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/bool.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/inttypes.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/limits.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/long_long.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/stdalign.h
+postponed_job.o: $(hdrdir)/ruby/backward/2/stdarg.h
postponed_job.o: $(hdrdir)/ruby/debug.h
postponed_job.o: $(hdrdir)/ruby/defines.h
postponed_job.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/-test-/postponed_job/postponed_job.c b/ext/-test-/postponed_job/postponed_job.c
index d8684d475a..fa57bef6f5 100644
--- a/ext/-test-/postponed_job/postponed_job.c
+++ b/ext/-test-/postponed_job/postponed_job.c
@@ -58,6 +58,34 @@ pjob_call_direct(VALUE self, VALUE obj)
return self;
}
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+
+static void *
+pjob_register_in_c_thread_i(void *obj)
+{
+ rb_postponed_job_register_one(0, pjob_one_callback, (void *)obj);
+ rb_postponed_job_register_one(0, pjob_one_callback, (void *)obj);
+ rb_postponed_job_register_one(0, pjob_one_callback, (void *)obj);
+ return NULL;
+}
+
+static VALUE
+pjob_register_in_c_thread(VALUE self, VALUE obj)
+{
+ pthread_t thread;
+ if (pthread_create(&thread, NULL, pjob_register_in_c_thread_i, (void *)obj)) {
+ return Qfalse;
+ }
+
+ if (pthread_join(thread, NULL)) {
+ return Qfalse;
+ }
+
+ return Qtrue;
+}
+#endif
+
void
Init_postponed_job(VALUE self)
{
@@ -65,5 +93,8 @@ Init_postponed_job(VALUE self)
rb_define_module_function(mBug, "postponed_job_register", pjob_register, 1);
rb_define_module_function(mBug, "postponed_job_register_one", pjob_register_one, 1);
rb_define_module_function(mBug, "postponed_job_call_direct", pjob_call_direct, 1);
+#ifdef HAVE_PTHREAD_H
+ rb_define_module_function(mBug, "postponed_job_register_in_c_thread", pjob_register_in_c_thread, 1);
+#endif
}
diff --git a/ext/-test-/printf/depend b/ext/-test-/printf/depend
index 7860797f50..5f42702eaf 100644
--- a/ext/-test-/printf/depend
+++ b/ext/-test-/printf/depend
@@ -2,8 +2,157 @@
printf.o: $(RUBY_EXTCONF_H)
printf.o: $(arch_hdrdir)/ruby/config.h
printf.o: $(hdrdir)/ruby.h
+printf.o: $(hdrdir)/ruby/internal/anyargs.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+printf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+printf.o: $(hdrdir)/ruby/internal/assume.h
+printf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+printf.o: $(hdrdir)/ruby/internal/attr/artificial.h
+printf.o: $(hdrdir)/ruby/internal/attr/cold.h
+printf.o: $(hdrdir)/ruby/internal/attr/const.h
+printf.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+printf.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+printf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+printf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+printf.o: $(hdrdir)/ruby/internal/attr/error.h
+printf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+printf.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+printf.o: $(hdrdir)/ruby/internal/attr/format.h
+printf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+printf.o: $(hdrdir)/ruby/internal/attr/noalias.h
+printf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+printf.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+printf.o: $(hdrdir)/ruby/internal/attr/noinline.h
+printf.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+printf.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+printf.o: $(hdrdir)/ruby/internal/attr/pure.h
+printf.o: $(hdrdir)/ruby/internal/attr/restrict.h
+printf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+printf.o: $(hdrdir)/ruby/internal/attr/warning.h
+printf.o: $(hdrdir)/ruby/internal/attr/weakref.h
+printf.o: $(hdrdir)/ruby/internal/cast.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+printf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+printf.o: $(hdrdir)/ruby/internal/compiler_since.h
+printf.o: $(hdrdir)/ruby/internal/config.h
+printf.o: $(hdrdir)/ruby/internal/constant_p.h
+printf.o: $(hdrdir)/ruby/internal/core.h
+printf.o: $(hdrdir)/ruby/internal/core/rarray.h
+printf.o: $(hdrdir)/ruby/internal/core/rbasic.h
+printf.o: $(hdrdir)/ruby/internal/core/rbignum.h
+printf.o: $(hdrdir)/ruby/internal/core/rclass.h
+printf.o: $(hdrdir)/ruby/internal/core/rdata.h
+printf.o: $(hdrdir)/ruby/internal/core/rfile.h
+printf.o: $(hdrdir)/ruby/internal/core/rhash.h
+printf.o: $(hdrdir)/ruby/internal/core/robject.h
+printf.o: $(hdrdir)/ruby/internal/core/rregexp.h
+printf.o: $(hdrdir)/ruby/internal/core/rstring.h
+printf.o: $(hdrdir)/ruby/internal/core/rstruct.h
+printf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+printf.o: $(hdrdir)/ruby/internal/ctype.h
+printf.o: $(hdrdir)/ruby/internal/dllexport.h
+printf.o: $(hdrdir)/ruby/internal/dosish.h
+printf.o: $(hdrdir)/ruby/internal/error.h
+printf.o: $(hdrdir)/ruby/internal/eval.h
+printf.o: $(hdrdir)/ruby/internal/event.h
+printf.o: $(hdrdir)/ruby/internal/fl_type.h
+printf.o: $(hdrdir)/ruby/internal/gc.h
+printf.o: $(hdrdir)/ruby/internal/glob.h
+printf.o: $(hdrdir)/ruby/internal/globals.h
+printf.o: $(hdrdir)/ruby/internal/has/attribute.h
+printf.o: $(hdrdir)/ruby/internal/has/builtin.h
+printf.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+printf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+printf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+printf.o: $(hdrdir)/ruby/internal/has/extension.h
+printf.o: $(hdrdir)/ruby/internal/has/feature.h
+printf.o: $(hdrdir)/ruby/internal/has/warning.h
+printf.o: $(hdrdir)/ruby/internal/intern/array.h
+printf.o: $(hdrdir)/ruby/internal/intern/bignum.h
+printf.o: $(hdrdir)/ruby/internal/intern/class.h
+printf.o: $(hdrdir)/ruby/internal/intern/compar.h
+printf.o: $(hdrdir)/ruby/internal/intern/complex.h
+printf.o: $(hdrdir)/ruby/internal/intern/cont.h
+printf.o: $(hdrdir)/ruby/internal/intern/dir.h
+printf.o: $(hdrdir)/ruby/internal/intern/enum.h
+printf.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+printf.o: $(hdrdir)/ruby/internal/intern/error.h
+printf.o: $(hdrdir)/ruby/internal/intern/eval.h
+printf.o: $(hdrdir)/ruby/internal/intern/file.h
+printf.o: $(hdrdir)/ruby/internal/intern/gc.h
+printf.o: $(hdrdir)/ruby/internal/intern/hash.h
+printf.o: $(hdrdir)/ruby/internal/intern/io.h
+printf.o: $(hdrdir)/ruby/internal/intern/load.h
+printf.o: $(hdrdir)/ruby/internal/intern/marshal.h
+printf.o: $(hdrdir)/ruby/internal/intern/numeric.h
+printf.o: $(hdrdir)/ruby/internal/intern/object.h
+printf.o: $(hdrdir)/ruby/internal/intern/parse.h
+printf.o: $(hdrdir)/ruby/internal/intern/proc.h
+printf.o: $(hdrdir)/ruby/internal/intern/process.h
+printf.o: $(hdrdir)/ruby/internal/intern/random.h
+printf.o: $(hdrdir)/ruby/internal/intern/range.h
+printf.o: $(hdrdir)/ruby/internal/intern/rational.h
+printf.o: $(hdrdir)/ruby/internal/intern/re.h
+printf.o: $(hdrdir)/ruby/internal/intern/ruby.h
+printf.o: $(hdrdir)/ruby/internal/intern/select.h
+printf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+printf.o: $(hdrdir)/ruby/internal/intern/signal.h
+printf.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+printf.o: $(hdrdir)/ruby/internal/intern/string.h
+printf.o: $(hdrdir)/ruby/internal/intern/struct.h
+printf.o: $(hdrdir)/ruby/internal/intern/thread.h
+printf.o: $(hdrdir)/ruby/internal/intern/time.h
+printf.o: $(hdrdir)/ruby/internal/intern/variable.h
+printf.o: $(hdrdir)/ruby/internal/intern/vm.h
+printf.o: $(hdrdir)/ruby/internal/interpreter.h
+printf.o: $(hdrdir)/ruby/internal/iterator.h
+printf.o: $(hdrdir)/ruby/internal/memory.h
+printf.o: $(hdrdir)/ruby/internal/method.h
+printf.o: $(hdrdir)/ruby/internal/module.h
+printf.o: $(hdrdir)/ruby/internal/newobj.h
+printf.o: $(hdrdir)/ruby/internal/rgengc.h
+printf.o: $(hdrdir)/ruby/internal/scan_args.h
+printf.o: $(hdrdir)/ruby/internal/special_consts.h
+printf.o: $(hdrdir)/ruby/internal/static_assert.h
+printf.o: $(hdrdir)/ruby/internal/stdalign.h
+printf.o: $(hdrdir)/ruby/internal/stdbool.h
+printf.o: $(hdrdir)/ruby/internal/symbol.h
+printf.o: $(hdrdir)/ruby/internal/token_paste.h
+printf.o: $(hdrdir)/ruby/internal/value.h
+printf.o: $(hdrdir)/ruby/internal/value_type.h
+printf.o: $(hdrdir)/ruby/internal/variable.h
+printf.o: $(hdrdir)/ruby/internal/warning_push.h
+printf.o: $(hdrdir)/ruby/internal/xmalloc.h
printf.o: $(hdrdir)/ruby/assert.h
printf.o: $(hdrdir)/ruby/backward.h
+printf.o: $(hdrdir)/ruby/backward/2/assume.h
+printf.o: $(hdrdir)/ruby/backward/2/attributes.h
+printf.o: $(hdrdir)/ruby/backward/2/bool.h
+printf.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+printf.o: $(hdrdir)/ruby/backward/2/inttypes.h
+printf.o: $(hdrdir)/ruby/backward/2/limits.h
+printf.o: $(hdrdir)/ruby/backward/2/long_long.h
+printf.o: $(hdrdir)/ruby/backward/2/stdalign.h
+printf.o: $(hdrdir)/ruby/backward/2/stdarg.h
printf.o: $(hdrdir)/ruby/defines.h
printf.o: $(hdrdir)/ruby/encoding.h
printf.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/-test-/proc/depend b/ext/-test-/proc/depend
index 5946e4ca0d..b72257f5e2 100644
--- a/ext/-test-/proc/depend
+++ b/ext/-test-/proc/depend
@@ -2,8 +2,157 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -14,8 +163,157 @@ init.o: init.c
receiver.o: $(RUBY_EXTCONF_H)
receiver.o: $(arch_hdrdir)/ruby/config.h
receiver.o: $(hdrdir)/ruby.h
+receiver.o: $(hdrdir)/ruby/internal/anyargs.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+receiver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+receiver.o: $(hdrdir)/ruby/internal/assume.h
+receiver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+receiver.o: $(hdrdir)/ruby/internal/attr/artificial.h
+receiver.o: $(hdrdir)/ruby/internal/attr/cold.h
+receiver.o: $(hdrdir)/ruby/internal/attr/const.h
+receiver.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+receiver.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+receiver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+receiver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+receiver.o: $(hdrdir)/ruby/internal/attr/error.h
+receiver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+receiver.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+receiver.o: $(hdrdir)/ruby/internal/attr/format.h
+receiver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+receiver.o: $(hdrdir)/ruby/internal/attr/noalias.h
+receiver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+receiver.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+receiver.o: $(hdrdir)/ruby/internal/attr/noinline.h
+receiver.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+receiver.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+receiver.o: $(hdrdir)/ruby/internal/attr/pure.h
+receiver.o: $(hdrdir)/ruby/internal/attr/restrict.h
+receiver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+receiver.o: $(hdrdir)/ruby/internal/attr/warning.h
+receiver.o: $(hdrdir)/ruby/internal/attr/weakref.h
+receiver.o: $(hdrdir)/ruby/internal/cast.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+receiver.o: $(hdrdir)/ruby/internal/compiler_since.h
+receiver.o: $(hdrdir)/ruby/internal/config.h
+receiver.o: $(hdrdir)/ruby/internal/constant_p.h
+receiver.o: $(hdrdir)/ruby/internal/core.h
+receiver.o: $(hdrdir)/ruby/internal/core/rarray.h
+receiver.o: $(hdrdir)/ruby/internal/core/rbasic.h
+receiver.o: $(hdrdir)/ruby/internal/core/rbignum.h
+receiver.o: $(hdrdir)/ruby/internal/core/rclass.h
+receiver.o: $(hdrdir)/ruby/internal/core/rdata.h
+receiver.o: $(hdrdir)/ruby/internal/core/rfile.h
+receiver.o: $(hdrdir)/ruby/internal/core/rhash.h
+receiver.o: $(hdrdir)/ruby/internal/core/robject.h
+receiver.o: $(hdrdir)/ruby/internal/core/rregexp.h
+receiver.o: $(hdrdir)/ruby/internal/core/rstring.h
+receiver.o: $(hdrdir)/ruby/internal/core/rstruct.h
+receiver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+receiver.o: $(hdrdir)/ruby/internal/ctype.h
+receiver.o: $(hdrdir)/ruby/internal/dllexport.h
+receiver.o: $(hdrdir)/ruby/internal/dosish.h
+receiver.o: $(hdrdir)/ruby/internal/error.h
+receiver.o: $(hdrdir)/ruby/internal/eval.h
+receiver.o: $(hdrdir)/ruby/internal/event.h
+receiver.o: $(hdrdir)/ruby/internal/fl_type.h
+receiver.o: $(hdrdir)/ruby/internal/gc.h
+receiver.o: $(hdrdir)/ruby/internal/glob.h
+receiver.o: $(hdrdir)/ruby/internal/globals.h
+receiver.o: $(hdrdir)/ruby/internal/has/attribute.h
+receiver.o: $(hdrdir)/ruby/internal/has/builtin.h
+receiver.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+receiver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+receiver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+receiver.o: $(hdrdir)/ruby/internal/has/extension.h
+receiver.o: $(hdrdir)/ruby/internal/has/feature.h
+receiver.o: $(hdrdir)/ruby/internal/has/warning.h
+receiver.o: $(hdrdir)/ruby/internal/intern/array.h
+receiver.o: $(hdrdir)/ruby/internal/intern/bignum.h
+receiver.o: $(hdrdir)/ruby/internal/intern/class.h
+receiver.o: $(hdrdir)/ruby/internal/intern/compar.h
+receiver.o: $(hdrdir)/ruby/internal/intern/complex.h
+receiver.o: $(hdrdir)/ruby/internal/intern/cont.h
+receiver.o: $(hdrdir)/ruby/internal/intern/dir.h
+receiver.o: $(hdrdir)/ruby/internal/intern/enum.h
+receiver.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+receiver.o: $(hdrdir)/ruby/internal/intern/error.h
+receiver.o: $(hdrdir)/ruby/internal/intern/eval.h
+receiver.o: $(hdrdir)/ruby/internal/intern/file.h
+receiver.o: $(hdrdir)/ruby/internal/intern/gc.h
+receiver.o: $(hdrdir)/ruby/internal/intern/hash.h
+receiver.o: $(hdrdir)/ruby/internal/intern/io.h
+receiver.o: $(hdrdir)/ruby/internal/intern/load.h
+receiver.o: $(hdrdir)/ruby/internal/intern/marshal.h
+receiver.o: $(hdrdir)/ruby/internal/intern/numeric.h
+receiver.o: $(hdrdir)/ruby/internal/intern/object.h
+receiver.o: $(hdrdir)/ruby/internal/intern/parse.h
+receiver.o: $(hdrdir)/ruby/internal/intern/proc.h
+receiver.o: $(hdrdir)/ruby/internal/intern/process.h
+receiver.o: $(hdrdir)/ruby/internal/intern/random.h
+receiver.o: $(hdrdir)/ruby/internal/intern/range.h
+receiver.o: $(hdrdir)/ruby/internal/intern/rational.h
+receiver.o: $(hdrdir)/ruby/internal/intern/re.h
+receiver.o: $(hdrdir)/ruby/internal/intern/ruby.h
+receiver.o: $(hdrdir)/ruby/internal/intern/select.h
+receiver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+receiver.o: $(hdrdir)/ruby/internal/intern/signal.h
+receiver.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+receiver.o: $(hdrdir)/ruby/internal/intern/string.h
+receiver.o: $(hdrdir)/ruby/internal/intern/struct.h
+receiver.o: $(hdrdir)/ruby/internal/intern/thread.h
+receiver.o: $(hdrdir)/ruby/internal/intern/time.h
+receiver.o: $(hdrdir)/ruby/internal/intern/variable.h
+receiver.o: $(hdrdir)/ruby/internal/intern/vm.h
+receiver.o: $(hdrdir)/ruby/internal/interpreter.h
+receiver.o: $(hdrdir)/ruby/internal/iterator.h
+receiver.o: $(hdrdir)/ruby/internal/memory.h
+receiver.o: $(hdrdir)/ruby/internal/method.h
+receiver.o: $(hdrdir)/ruby/internal/module.h
+receiver.o: $(hdrdir)/ruby/internal/newobj.h
+receiver.o: $(hdrdir)/ruby/internal/rgengc.h
+receiver.o: $(hdrdir)/ruby/internal/scan_args.h
+receiver.o: $(hdrdir)/ruby/internal/special_consts.h
+receiver.o: $(hdrdir)/ruby/internal/static_assert.h
+receiver.o: $(hdrdir)/ruby/internal/stdalign.h
+receiver.o: $(hdrdir)/ruby/internal/stdbool.h
+receiver.o: $(hdrdir)/ruby/internal/symbol.h
+receiver.o: $(hdrdir)/ruby/internal/token_paste.h
+receiver.o: $(hdrdir)/ruby/internal/value.h
+receiver.o: $(hdrdir)/ruby/internal/value_type.h
+receiver.o: $(hdrdir)/ruby/internal/variable.h
+receiver.o: $(hdrdir)/ruby/internal/warning_push.h
+receiver.o: $(hdrdir)/ruby/internal/xmalloc.h
receiver.o: $(hdrdir)/ruby/assert.h
receiver.o: $(hdrdir)/ruby/backward.h
+receiver.o: $(hdrdir)/ruby/backward/2/assume.h
+receiver.o: $(hdrdir)/ruby/backward/2/attributes.h
+receiver.o: $(hdrdir)/ruby/backward/2/bool.h
+receiver.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+receiver.o: $(hdrdir)/ruby/backward/2/inttypes.h
+receiver.o: $(hdrdir)/ruby/backward/2/limits.h
+receiver.o: $(hdrdir)/ruby/backward/2/long_long.h
+receiver.o: $(hdrdir)/ruby/backward/2/stdalign.h
+receiver.o: $(hdrdir)/ruby/backward/2/stdarg.h
receiver.o: $(hdrdir)/ruby/defines.h
receiver.o: $(hdrdir)/ruby/intern.h
receiver.o: $(hdrdir)/ruby/missing.h
@@ -26,8 +324,157 @@ receiver.o: receiver.c
super.o: $(RUBY_EXTCONF_H)
super.o: $(arch_hdrdir)/ruby/config.h
super.o: $(hdrdir)/ruby.h
+super.o: $(hdrdir)/ruby/internal/anyargs.h
+super.o: $(hdrdir)/ruby/internal/arithmetic.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+super.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+super.o: $(hdrdir)/ruby/internal/assume.h
+super.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+super.o: $(hdrdir)/ruby/internal/attr/artificial.h
+super.o: $(hdrdir)/ruby/internal/attr/cold.h
+super.o: $(hdrdir)/ruby/internal/attr/const.h
+super.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+super.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+super.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+super.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+super.o: $(hdrdir)/ruby/internal/attr/error.h
+super.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+super.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+super.o: $(hdrdir)/ruby/internal/attr/format.h
+super.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+super.o: $(hdrdir)/ruby/internal/attr/noalias.h
+super.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+super.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+super.o: $(hdrdir)/ruby/internal/attr/noinline.h
+super.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+super.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+super.o: $(hdrdir)/ruby/internal/attr/pure.h
+super.o: $(hdrdir)/ruby/internal/attr/restrict.h
+super.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+super.o: $(hdrdir)/ruby/internal/attr/warning.h
+super.o: $(hdrdir)/ruby/internal/attr/weakref.h
+super.o: $(hdrdir)/ruby/internal/cast.h
+super.o: $(hdrdir)/ruby/internal/compiler_is.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+super.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+super.o: $(hdrdir)/ruby/internal/compiler_since.h
+super.o: $(hdrdir)/ruby/internal/config.h
+super.o: $(hdrdir)/ruby/internal/constant_p.h
+super.o: $(hdrdir)/ruby/internal/core.h
+super.o: $(hdrdir)/ruby/internal/core/rarray.h
+super.o: $(hdrdir)/ruby/internal/core/rbasic.h
+super.o: $(hdrdir)/ruby/internal/core/rbignum.h
+super.o: $(hdrdir)/ruby/internal/core/rclass.h
+super.o: $(hdrdir)/ruby/internal/core/rdata.h
+super.o: $(hdrdir)/ruby/internal/core/rfile.h
+super.o: $(hdrdir)/ruby/internal/core/rhash.h
+super.o: $(hdrdir)/ruby/internal/core/robject.h
+super.o: $(hdrdir)/ruby/internal/core/rregexp.h
+super.o: $(hdrdir)/ruby/internal/core/rstring.h
+super.o: $(hdrdir)/ruby/internal/core/rstruct.h
+super.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+super.o: $(hdrdir)/ruby/internal/ctype.h
+super.o: $(hdrdir)/ruby/internal/dllexport.h
+super.o: $(hdrdir)/ruby/internal/dosish.h
+super.o: $(hdrdir)/ruby/internal/error.h
+super.o: $(hdrdir)/ruby/internal/eval.h
+super.o: $(hdrdir)/ruby/internal/event.h
+super.o: $(hdrdir)/ruby/internal/fl_type.h
+super.o: $(hdrdir)/ruby/internal/gc.h
+super.o: $(hdrdir)/ruby/internal/glob.h
+super.o: $(hdrdir)/ruby/internal/globals.h
+super.o: $(hdrdir)/ruby/internal/has/attribute.h
+super.o: $(hdrdir)/ruby/internal/has/builtin.h
+super.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+super.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+super.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+super.o: $(hdrdir)/ruby/internal/has/extension.h
+super.o: $(hdrdir)/ruby/internal/has/feature.h
+super.o: $(hdrdir)/ruby/internal/has/warning.h
+super.o: $(hdrdir)/ruby/internal/intern/array.h
+super.o: $(hdrdir)/ruby/internal/intern/bignum.h
+super.o: $(hdrdir)/ruby/internal/intern/class.h
+super.o: $(hdrdir)/ruby/internal/intern/compar.h
+super.o: $(hdrdir)/ruby/internal/intern/complex.h
+super.o: $(hdrdir)/ruby/internal/intern/cont.h
+super.o: $(hdrdir)/ruby/internal/intern/dir.h
+super.o: $(hdrdir)/ruby/internal/intern/enum.h
+super.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+super.o: $(hdrdir)/ruby/internal/intern/error.h
+super.o: $(hdrdir)/ruby/internal/intern/eval.h
+super.o: $(hdrdir)/ruby/internal/intern/file.h
+super.o: $(hdrdir)/ruby/internal/intern/gc.h
+super.o: $(hdrdir)/ruby/internal/intern/hash.h
+super.o: $(hdrdir)/ruby/internal/intern/io.h
+super.o: $(hdrdir)/ruby/internal/intern/load.h
+super.o: $(hdrdir)/ruby/internal/intern/marshal.h
+super.o: $(hdrdir)/ruby/internal/intern/numeric.h
+super.o: $(hdrdir)/ruby/internal/intern/object.h
+super.o: $(hdrdir)/ruby/internal/intern/parse.h
+super.o: $(hdrdir)/ruby/internal/intern/proc.h
+super.o: $(hdrdir)/ruby/internal/intern/process.h
+super.o: $(hdrdir)/ruby/internal/intern/random.h
+super.o: $(hdrdir)/ruby/internal/intern/range.h
+super.o: $(hdrdir)/ruby/internal/intern/rational.h
+super.o: $(hdrdir)/ruby/internal/intern/re.h
+super.o: $(hdrdir)/ruby/internal/intern/ruby.h
+super.o: $(hdrdir)/ruby/internal/intern/select.h
+super.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+super.o: $(hdrdir)/ruby/internal/intern/signal.h
+super.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+super.o: $(hdrdir)/ruby/internal/intern/string.h
+super.o: $(hdrdir)/ruby/internal/intern/struct.h
+super.o: $(hdrdir)/ruby/internal/intern/thread.h
+super.o: $(hdrdir)/ruby/internal/intern/time.h
+super.o: $(hdrdir)/ruby/internal/intern/variable.h
+super.o: $(hdrdir)/ruby/internal/intern/vm.h
+super.o: $(hdrdir)/ruby/internal/interpreter.h
+super.o: $(hdrdir)/ruby/internal/iterator.h
+super.o: $(hdrdir)/ruby/internal/memory.h
+super.o: $(hdrdir)/ruby/internal/method.h
+super.o: $(hdrdir)/ruby/internal/module.h
+super.o: $(hdrdir)/ruby/internal/newobj.h
+super.o: $(hdrdir)/ruby/internal/rgengc.h
+super.o: $(hdrdir)/ruby/internal/scan_args.h
+super.o: $(hdrdir)/ruby/internal/special_consts.h
+super.o: $(hdrdir)/ruby/internal/static_assert.h
+super.o: $(hdrdir)/ruby/internal/stdalign.h
+super.o: $(hdrdir)/ruby/internal/stdbool.h
+super.o: $(hdrdir)/ruby/internal/symbol.h
+super.o: $(hdrdir)/ruby/internal/token_paste.h
+super.o: $(hdrdir)/ruby/internal/value.h
+super.o: $(hdrdir)/ruby/internal/value_type.h
+super.o: $(hdrdir)/ruby/internal/variable.h
+super.o: $(hdrdir)/ruby/internal/warning_push.h
+super.o: $(hdrdir)/ruby/internal/xmalloc.h
super.o: $(hdrdir)/ruby/assert.h
super.o: $(hdrdir)/ruby/backward.h
+super.o: $(hdrdir)/ruby/backward/2/assume.h
+super.o: $(hdrdir)/ruby/backward/2/attributes.h
+super.o: $(hdrdir)/ruby/backward/2/bool.h
+super.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+super.o: $(hdrdir)/ruby/backward/2/inttypes.h
+super.o: $(hdrdir)/ruby/backward/2/limits.h
+super.o: $(hdrdir)/ruby/backward/2/long_long.h
+super.o: $(hdrdir)/ruby/backward/2/stdalign.h
+super.o: $(hdrdir)/ruby/backward/2/stdarg.h
super.o: $(hdrdir)/ruby/defines.h
super.o: $(hdrdir)/ruby/intern.h
super.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/random/depend b/ext/-test-/random/depend
new file mode 100644
index 0000000000..4b4997d340
--- /dev/null
+++ b/ext/-test-/random/depend
@@ -0,0 +1,328 @@
+# AUTOGENERATED DEPENDENCIES START
+init.o: $(RUBY_EXTCONF_H)
+init.o: $(arch_hdrdir)/ruby/config.h
+init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/assert.h
+init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/r_cast.h
+init.o: $(hdrdir)/ruby/backward/2/rmodule.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
+init.o: $(hdrdir)/ruby/defines.h
+init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+loop.o: $(RUBY_EXTCONF_H)
+loop.o: $(arch_hdrdir)/ruby/config.h
+loop.o: $(hdrdir)/ruby/assert.h
+loop.o: $(hdrdir)/ruby/backward.h
+loop.o: $(hdrdir)/ruby/backward/2/assume.h
+loop.o: $(hdrdir)/ruby/backward/2/attributes.h
+loop.o: $(hdrdir)/ruby/backward/2/bool.h
+loop.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+loop.o: $(hdrdir)/ruby/backward/2/inttypes.h
+loop.o: $(hdrdir)/ruby/backward/2/limits.h
+loop.o: $(hdrdir)/ruby/backward/2/long_long.h
+loop.o: $(hdrdir)/ruby/backward/2/r_cast.h
+loop.o: $(hdrdir)/ruby/backward/2/rmodule.h
+loop.o: $(hdrdir)/ruby/backward/2/stdalign.h
+loop.o: $(hdrdir)/ruby/backward/2/stdarg.h
+loop.o: $(hdrdir)/ruby/defines.h
+loop.o: $(hdrdir)/ruby/intern.h
+loop.o: $(hdrdir)/ruby/internal/anyargs.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+loop.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+loop.o: $(hdrdir)/ruby/internal/assume.h
+loop.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+loop.o: $(hdrdir)/ruby/internal/attr/artificial.h
+loop.o: $(hdrdir)/ruby/internal/attr/cold.h
+loop.o: $(hdrdir)/ruby/internal/attr/const.h
+loop.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+loop.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+loop.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+loop.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+loop.o: $(hdrdir)/ruby/internal/attr/error.h
+loop.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+loop.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+loop.o: $(hdrdir)/ruby/internal/attr/format.h
+loop.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+loop.o: $(hdrdir)/ruby/internal/attr/noalias.h
+loop.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+loop.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+loop.o: $(hdrdir)/ruby/internal/attr/noinline.h
+loop.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+loop.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+loop.o: $(hdrdir)/ruby/internal/attr/pure.h
+loop.o: $(hdrdir)/ruby/internal/attr/restrict.h
+loop.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+loop.o: $(hdrdir)/ruby/internal/attr/warning.h
+loop.o: $(hdrdir)/ruby/internal/attr/weakref.h
+loop.o: $(hdrdir)/ruby/internal/cast.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+loop.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+loop.o: $(hdrdir)/ruby/internal/compiler_since.h
+loop.o: $(hdrdir)/ruby/internal/config.h
+loop.o: $(hdrdir)/ruby/internal/constant_p.h
+loop.o: $(hdrdir)/ruby/internal/core.h
+loop.o: $(hdrdir)/ruby/internal/core/rarray.h
+loop.o: $(hdrdir)/ruby/internal/core/rbasic.h
+loop.o: $(hdrdir)/ruby/internal/core/rbignum.h
+loop.o: $(hdrdir)/ruby/internal/core/rclass.h
+loop.o: $(hdrdir)/ruby/internal/core/rdata.h
+loop.o: $(hdrdir)/ruby/internal/core/rfile.h
+loop.o: $(hdrdir)/ruby/internal/core/rhash.h
+loop.o: $(hdrdir)/ruby/internal/core/robject.h
+loop.o: $(hdrdir)/ruby/internal/core/rregexp.h
+loop.o: $(hdrdir)/ruby/internal/core/rstring.h
+loop.o: $(hdrdir)/ruby/internal/core/rstruct.h
+loop.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+loop.o: $(hdrdir)/ruby/internal/ctype.h
+loop.o: $(hdrdir)/ruby/internal/dllexport.h
+loop.o: $(hdrdir)/ruby/internal/dosish.h
+loop.o: $(hdrdir)/ruby/internal/error.h
+loop.o: $(hdrdir)/ruby/internal/eval.h
+loop.o: $(hdrdir)/ruby/internal/event.h
+loop.o: $(hdrdir)/ruby/internal/fl_type.h
+loop.o: $(hdrdir)/ruby/internal/gc.h
+loop.o: $(hdrdir)/ruby/internal/glob.h
+loop.o: $(hdrdir)/ruby/internal/globals.h
+loop.o: $(hdrdir)/ruby/internal/has/attribute.h
+loop.o: $(hdrdir)/ruby/internal/has/builtin.h
+loop.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+loop.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+loop.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+loop.o: $(hdrdir)/ruby/internal/has/extension.h
+loop.o: $(hdrdir)/ruby/internal/has/feature.h
+loop.o: $(hdrdir)/ruby/internal/has/warning.h
+loop.o: $(hdrdir)/ruby/internal/intern/array.h
+loop.o: $(hdrdir)/ruby/internal/intern/bignum.h
+loop.o: $(hdrdir)/ruby/internal/intern/class.h
+loop.o: $(hdrdir)/ruby/internal/intern/compar.h
+loop.o: $(hdrdir)/ruby/internal/intern/complex.h
+loop.o: $(hdrdir)/ruby/internal/intern/cont.h
+loop.o: $(hdrdir)/ruby/internal/intern/dir.h
+loop.o: $(hdrdir)/ruby/internal/intern/enum.h
+loop.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+loop.o: $(hdrdir)/ruby/internal/intern/error.h
+loop.o: $(hdrdir)/ruby/internal/intern/eval.h
+loop.o: $(hdrdir)/ruby/internal/intern/file.h
+loop.o: $(hdrdir)/ruby/internal/intern/gc.h
+loop.o: $(hdrdir)/ruby/internal/intern/hash.h
+loop.o: $(hdrdir)/ruby/internal/intern/io.h
+loop.o: $(hdrdir)/ruby/internal/intern/load.h
+loop.o: $(hdrdir)/ruby/internal/intern/marshal.h
+loop.o: $(hdrdir)/ruby/internal/intern/numeric.h
+loop.o: $(hdrdir)/ruby/internal/intern/object.h
+loop.o: $(hdrdir)/ruby/internal/intern/parse.h
+loop.o: $(hdrdir)/ruby/internal/intern/proc.h
+loop.o: $(hdrdir)/ruby/internal/intern/process.h
+loop.o: $(hdrdir)/ruby/internal/intern/random.h
+loop.o: $(hdrdir)/ruby/internal/intern/range.h
+loop.o: $(hdrdir)/ruby/internal/intern/rational.h
+loop.o: $(hdrdir)/ruby/internal/intern/re.h
+loop.o: $(hdrdir)/ruby/internal/intern/ruby.h
+loop.o: $(hdrdir)/ruby/internal/intern/select.h
+loop.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+loop.o: $(hdrdir)/ruby/internal/intern/signal.h
+loop.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+loop.o: $(hdrdir)/ruby/internal/intern/string.h
+loop.o: $(hdrdir)/ruby/internal/intern/struct.h
+loop.o: $(hdrdir)/ruby/internal/intern/thread.h
+loop.o: $(hdrdir)/ruby/internal/intern/time.h
+loop.o: $(hdrdir)/ruby/internal/intern/variable.h
+loop.o: $(hdrdir)/ruby/internal/intern/vm.h
+loop.o: $(hdrdir)/ruby/internal/interpreter.h
+loop.o: $(hdrdir)/ruby/internal/iterator.h
+loop.o: $(hdrdir)/ruby/internal/memory.h
+loop.o: $(hdrdir)/ruby/internal/method.h
+loop.o: $(hdrdir)/ruby/internal/module.h
+loop.o: $(hdrdir)/ruby/internal/newobj.h
+loop.o: $(hdrdir)/ruby/internal/rgengc.h
+loop.o: $(hdrdir)/ruby/internal/scan_args.h
+loop.o: $(hdrdir)/ruby/internal/special_consts.h
+loop.o: $(hdrdir)/ruby/internal/static_assert.h
+loop.o: $(hdrdir)/ruby/internal/stdalign.h
+loop.o: $(hdrdir)/ruby/internal/stdbool.h
+loop.o: $(hdrdir)/ruby/internal/symbol.h
+loop.o: $(hdrdir)/ruby/internal/token_paste.h
+loop.o: $(hdrdir)/ruby/internal/value.h
+loop.o: $(hdrdir)/ruby/internal/value_type.h
+loop.o: $(hdrdir)/ruby/internal/variable.h
+loop.o: $(hdrdir)/ruby/internal/warning_push.h
+loop.o: $(hdrdir)/ruby/internal/xmalloc.h
+loop.o: $(hdrdir)/ruby/missing.h
+loop.o: $(hdrdir)/ruby/random.h
+loop.o: $(hdrdir)/ruby/ruby.h
+loop.o: $(hdrdir)/ruby/st.h
+loop.o: $(hdrdir)/ruby/subst.h
+loop.o: loop.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/random/extconf.rb b/ext/-test-/random/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/random/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/random/init.c b/ext/-test-/random/init.c
new file mode 100644
index 0000000000..320cba0ad6
--- /dev/null
+++ b/ext/-test-/random/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_random_##n(VALUE mod, VALUE base); Init_random_##n(mod, base);}
+
+void
+Init_random(void)
+{
+ VALUE base = rb_const_get(rb_cRandom, rb_intern_const("Base"));
+ VALUE mod = rb_define_module_under(rb_define_module("Bug"), "Random");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/ext/-test-/random/loop.c b/ext/-test-/random/loop.c
new file mode 100644
index 0000000000..0572096403
--- /dev/null
+++ b/ext/-test-/random/loop.c
@@ -0,0 +1,110 @@
+#include "ruby/random.h"
+
+static const uint32_t max_seeds = 1024;
+
+typedef struct {
+ rb_random_t base;
+ uint32_t num, idx, *buf;
+} rand_loop_t;
+
+RB_RANDOM_INTERFACE_DECLARE_WITH_REAL(loop);
+static const rb_random_interface_t random_loop_if = {
+ 32,
+ RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(loop)
+};
+
+static size_t
+random_loop_memsize(const void *ptr)
+{
+ const rand_loop_t *r = ptr;
+ return sizeof(*r) + r->num * sizeof(r->buf[0]);
+}
+
+static rb_random_data_type_t random_loop_type = {
+ "random/loop",
+ {
+ rb_random_mark,
+ RUBY_TYPED_DEFAULT_FREE,
+ random_loop_memsize,
+ },
+ RB_RANDOM_PARENT,
+ (void *)&random_loop_if,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+
+static VALUE
+loop_alloc(VALUE klass)
+{
+ rand_loop_t *rnd;
+ VALUE obj = TypedData_Make_Struct(klass, rand_loop_t, &random_loop_type, rnd);
+ rb_random_base_init(&rnd->base);
+ return obj;
+}
+
+static void
+loop_init(rb_random_t *rnd, const uint32_t *buf, size_t len)
+{
+ rand_loop_t *r = (rand_loop_t *)rnd;
+
+ if (len > max_seeds) len = max_seeds;
+
+ REALLOC_N(r->buf, uint32_t, len);
+ MEMCPY(r->buf, buf, uint32_t, (r->num = (uint32_t)len));
+}
+
+static void
+loop_get_bytes(rb_random_t *rnd, void *p, size_t n)
+{
+ uint8_t *buf = p;
+ while (n > 0) {
+ uint32_t x = loop_get_int32(rnd);
+ switch (n % 4) {
+ case 0:
+ *buf++ = (uint8_t)x;
+ n--;
+ /* FALLTHROUGH */
+ case 3:
+ *buf++ = (uint8_t)x;
+ n--;
+ /* FALLTHROUGH */
+ case 2:
+ *buf++ = (uint8_t)x;
+ n--;
+ /* FALLTHROUGH */
+ case 1:
+ *buf++ = (uint8_t)x;
+ n--;
+ }
+ }
+}
+
+static uint32_t
+loop_get_int32(rb_random_t *rnd)
+{
+ rand_loop_t *r = (rand_loop_t *)rnd;
+ if (r->idx < r->num) {
+ uint32_t x = r->buf[r->idx++];
+ if (r->idx >= r->num) r->idx = 0;
+ return x;
+ }
+ else if (r->num) {
+ return r->buf[r->idx = 0];
+ }
+ return 0;
+}
+
+static double
+loop_get_real(rb_random_t *rnd, int excl)
+{
+ uint32_t a = loop_get_int32(rnd);
+ return ldexp(a, -16);
+}
+
+void
+Init_random_loop(VALUE mod, VALUE base)
+{
+ VALUE c = rb_define_class_under(mod, "Loop", base);
+ rb_define_alloc_func(c, loop_alloc);
+ RB_RANDOM_DATA_INIT_PARENT(random_loop_type);
+}
diff --git a/ext/-test-/rational/depend b/ext/-test-/rational/depend
index 39e65933f3..c2ebddd093 100644
--- a/ext/-test-/rational/depend
+++ b/ext/-test-/rational/depend
@@ -6,8 +6,157 @@ rat.o: rat.c $(top_srcdir)/internal.h
rat.o: $(RUBY_EXTCONF_H)
rat.o: $(arch_hdrdir)/ruby/config.h
rat.o: $(hdrdir)/ruby.h
+rat.o: $(hdrdir)/ruby/internal/anyargs.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rat.o: $(hdrdir)/ruby/internal/assume.h
+rat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rat.o: $(hdrdir)/ruby/internal/attr/cold.h
+rat.o: $(hdrdir)/ruby/internal/attr/const.h
+rat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rat.o: $(hdrdir)/ruby/internal/attr/error.h
+rat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rat.o: $(hdrdir)/ruby/internal/attr/format.h
+rat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rat.o: $(hdrdir)/ruby/internal/attr/pure.h
+rat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rat.o: $(hdrdir)/ruby/internal/attr/warning.h
+rat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rat.o: $(hdrdir)/ruby/internal/cast.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rat.o: $(hdrdir)/ruby/internal/compiler_since.h
+rat.o: $(hdrdir)/ruby/internal/config.h
+rat.o: $(hdrdir)/ruby/internal/constant_p.h
+rat.o: $(hdrdir)/ruby/internal/core.h
+rat.o: $(hdrdir)/ruby/internal/core/rarray.h
+rat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rat.o: $(hdrdir)/ruby/internal/core/rclass.h
+rat.o: $(hdrdir)/ruby/internal/core/rdata.h
+rat.o: $(hdrdir)/ruby/internal/core/rfile.h
+rat.o: $(hdrdir)/ruby/internal/core/rhash.h
+rat.o: $(hdrdir)/ruby/internal/core/robject.h
+rat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rat.o: $(hdrdir)/ruby/internal/core/rstring.h
+rat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rat.o: $(hdrdir)/ruby/internal/ctype.h
+rat.o: $(hdrdir)/ruby/internal/dllexport.h
+rat.o: $(hdrdir)/ruby/internal/dosish.h
+rat.o: $(hdrdir)/ruby/internal/error.h
+rat.o: $(hdrdir)/ruby/internal/eval.h
+rat.o: $(hdrdir)/ruby/internal/event.h
+rat.o: $(hdrdir)/ruby/internal/fl_type.h
+rat.o: $(hdrdir)/ruby/internal/gc.h
+rat.o: $(hdrdir)/ruby/internal/glob.h
+rat.o: $(hdrdir)/ruby/internal/globals.h
+rat.o: $(hdrdir)/ruby/internal/has/attribute.h
+rat.o: $(hdrdir)/ruby/internal/has/builtin.h
+rat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rat.o: $(hdrdir)/ruby/internal/has/extension.h
+rat.o: $(hdrdir)/ruby/internal/has/feature.h
+rat.o: $(hdrdir)/ruby/internal/has/warning.h
+rat.o: $(hdrdir)/ruby/internal/intern/array.h
+rat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rat.o: $(hdrdir)/ruby/internal/intern/class.h
+rat.o: $(hdrdir)/ruby/internal/intern/compar.h
+rat.o: $(hdrdir)/ruby/internal/intern/complex.h
+rat.o: $(hdrdir)/ruby/internal/intern/cont.h
+rat.o: $(hdrdir)/ruby/internal/intern/dir.h
+rat.o: $(hdrdir)/ruby/internal/intern/enum.h
+rat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rat.o: $(hdrdir)/ruby/internal/intern/error.h
+rat.o: $(hdrdir)/ruby/internal/intern/eval.h
+rat.o: $(hdrdir)/ruby/internal/intern/file.h
+rat.o: $(hdrdir)/ruby/internal/intern/gc.h
+rat.o: $(hdrdir)/ruby/internal/intern/hash.h
+rat.o: $(hdrdir)/ruby/internal/intern/io.h
+rat.o: $(hdrdir)/ruby/internal/intern/load.h
+rat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rat.o: $(hdrdir)/ruby/internal/intern/object.h
+rat.o: $(hdrdir)/ruby/internal/intern/parse.h
+rat.o: $(hdrdir)/ruby/internal/intern/proc.h
+rat.o: $(hdrdir)/ruby/internal/intern/process.h
+rat.o: $(hdrdir)/ruby/internal/intern/random.h
+rat.o: $(hdrdir)/ruby/internal/intern/range.h
+rat.o: $(hdrdir)/ruby/internal/intern/rational.h
+rat.o: $(hdrdir)/ruby/internal/intern/re.h
+rat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rat.o: $(hdrdir)/ruby/internal/intern/select.h
+rat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rat.o: $(hdrdir)/ruby/internal/intern/signal.h
+rat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rat.o: $(hdrdir)/ruby/internal/intern/string.h
+rat.o: $(hdrdir)/ruby/internal/intern/struct.h
+rat.o: $(hdrdir)/ruby/internal/intern/thread.h
+rat.o: $(hdrdir)/ruby/internal/intern/time.h
+rat.o: $(hdrdir)/ruby/internal/intern/variable.h
+rat.o: $(hdrdir)/ruby/internal/intern/vm.h
+rat.o: $(hdrdir)/ruby/internal/interpreter.h
+rat.o: $(hdrdir)/ruby/internal/iterator.h
+rat.o: $(hdrdir)/ruby/internal/memory.h
+rat.o: $(hdrdir)/ruby/internal/method.h
+rat.o: $(hdrdir)/ruby/internal/module.h
+rat.o: $(hdrdir)/ruby/internal/newobj.h
+rat.o: $(hdrdir)/ruby/internal/rgengc.h
+rat.o: $(hdrdir)/ruby/internal/scan_args.h
+rat.o: $(hdrdir)/ruby/internal/special_consts.h
+rat.o: $(hdrdir)/ruby/internal/static_assert.h
+rat.o: $(hdrdir)/ruby/internal/stdalign.h
+rat.o: $(hdrdir)/ruby/internal/stdbool.h
+rat.o: $(hdrdir)/ruby/internal/symbol.h
+rat.o: $(hdrdir)/ruby/internal/token_paste.h
+rat.o: $(hdrdir)/ruby/internal/value.h
+rat.o: $(hdrdir)/ruby/internal/value_type.h
+rat.o: $(hdrdir)/ruby/internal/variable.h
+rat.o: $(hdrdir)/ruby/internal/warning_push.h
+rat.o: $(hdrdir)/ruby/internal/xmalloc.h
rat.o: $(hdrdir)/ruby/assert.h
rat.o: $(hdrdir)/ruby/backward.h
+rat.o: $(hdrdir)/ruby/backward/2/assume.h
+rat.o: $(hdrdir)/ruby/backward/2/attributes.h
+rat.o: $(hdrdir)/ruby/backward/2/bool.h
+rat.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+rat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rat.o: $(hdrdir)/ruby/backward/2/limits.h
+rat.o: $(hdrdir)/ruby/backward/2/long_long.h
+rat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rat.o: $(hdrdir)/ruby/backward/2/stdarg.h
rat.o: $(hdrdir)/ruby/defines.h
rat.o: $(hdrdir)/ruby/intern.h
rat.o: $(hdrdir)/ruby/missing.h
@@ -15,5 +164,17 @@ rat.o: $(hdrdir)/ruby/ruby.h
rat.o: $(hdrdir)/ruby/st.h
rat.o: $(hdrdir)/ruby/subst.h
rat.o: $(top_srcdir)/internal.h
+rat.o: $(top_srcdir)/internal/bignum.h
+rat.o: $(top_srcdir)/internal/bits.h
+rat.o: $(top_srcdir)/internal/compilers.h
+rat.o: $(top_srcdir)/internal/fixnum.h
+rat.o: $(top_srcdir)/internal/gc.h
+rat.o: $(top_srcdir)/internal/numeric.h
+rat.o: $(top_srcdir)/internal/rational.h
+rat.o: $(top_srcdir)/internal/serial.h
+rat.o: $(top_srcdir)/internal/static_assert.h
+rat.o: $(top_srcdir)/internal/vm.h
+rat.o: $(top_srcdir)/internal/warnings.h
+rat.o: $(top_srcdir)/ruby_assert.h
rat.o: rat.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/rational/rat.c b/ext/-test-/rational/rat.c
index 772546fca8..b1ffbda144 100644
--- a/ext/-test-/rational/rat.c
+++ b/ext/-test-/rational/rat.c
@@ -1,4 +1,4 @@
-#include "internal.h"
+#include "internal/rational.h"
#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
static VALUE
@@ -29,9 +29,17 @@ gcd_gmp(VALUE x, VALUE y)
#define gcd_gmp rb_f_notimplement
#endif
+static VALUE
+s_rational_raw(VALUE klass, VALUE x, VALUE y)
+{
+ return rb_rational_raw(x, y);
+}
+
void
Init_rational(VALUE klass)
{
rb_define_method(rb_cInteger, "gcd_normal", gcd_normal, 1);
rb_define_method(rb_cInteger, "gcd_gmp", gcd_gmp, 1);
+
+ rb_define_singleton_method(rb_cRational, "raw", s_rational_raw, 2);
}
diff --git a/ext/-test-/rb_call_super_kw/depend b/ext/-test-/rb_call_super_kw/depend
index f65dcf9694..314e69fd0e 100644
--- a/ext/-test-/rb_call_super_kw/depend
+++ b/ext/-test-/rb_call_super_kw/depend
@@ -2,8 +2,157 @@
rb_call_super_kw.o: $(RUBY_EXTCONF_H)
rb_call_super_kw.o: $(arch_hdrdir)/ruby/config.h
rb_call_super_kw.o: $(hdrdir)/ruby.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/anyargs.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/assume.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/cold.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/const.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/error.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/format.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/pure.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/warning.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/cast.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/compiler_since.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/config.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/constant_p.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rarray.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rclass.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rdata.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rfile.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rhash.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/robject.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rstring.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/ctype.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/dllexport.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/dosish.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/error.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/eval.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/event.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/fl_type.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/gc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/glob.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/globals.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/attribute.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/builtin.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/extension.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/feature.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/has/warning.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/array.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/class.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/compar.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/complex.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/cont.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/dir.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/enum.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/error.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/eval.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/file.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/gc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/hash.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/io.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/load.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/object.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/parse.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/proc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/process.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/random.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/range.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/rational.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/re.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/select.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/signal.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/string.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/struct.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/thread.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/time.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/variable.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/vm.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/interpreter.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/iterator.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/memory.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/method.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/module.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/newobj.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/rgengc.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/scan_args.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/special_consts.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/static_assert.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdalign.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/symbol.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/token_paste.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/value.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/value_type.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/variable.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/warning_push.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/xmalloc.h
rb_call_super_kw.o: $(hdrdir)/ruby/assert.h
rb_call_super_kw.o: $(hdrdir)/ruby/backward.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_call_super_kw.o: $(hdrdir)/ruby/backward/2/stdarg.h
rb_call_super_kw.o: $(hdrdir)/ruby/defines.h
rb_call_super_kw.o: $(hdrdir)/ruby/intern.h
rb_call_super_kw.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/recursion/depend b/ext/-test-/recursion/depend
index bf8005724a..c760e99c41 100644
--- a/ext/-test-/recursion/depend
+++ b/ext/-test-/recursion/depend
@@ -2,8 +2,157 @@
recursion.o: $(RUBY_EXTCONF_H)
recursion.o: $(arch_hdrdir)/ruby/config.h
recursion.o: $(hdrdir)/ruby.h
+recursion.o: $(hdrdir)/ruby/internal/anyargs.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+recursion.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+recursion.o: $(hdrdir)/ruby/internal/assume.h
+recursion.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+recursion.o: $(hdrdir)/ruby/internal/attr/artificial.h
+recursion.o: $(hdrdir)/ruby/internal/attr/cold.h
+recursion.o: $(hdrdir)/ruby/internal/attr/const.h
+recursion.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+recursion.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+recursion.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+recursion.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+recursion.o: $(hdrdir)/ruby/internal/attr/error.h
+recursion.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+recursion.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+recursion.o: $(hdrdir)/ruby/internal/attr/format.h
+recursion.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+recursion.o: $(hdrdir)/ruby/internal/attr/noalias.h
+recursion.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+recursion.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+recursion.o: $(hdrdir)/ruby/internal/attr/noinline.h
+recursion.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+recursion.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+recursion.o: $(hdrdir)/ruby/internal/attr/pure.h
+recursion.o: $(hdrdir)/ruby/internal/attr/restrict.h
+recursion.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+recursion.o: $(hdrdir)/ruby/internal/attr/warning.h
+recursion.o: $(hdrdir)/ruby/internal/attr/weakref.h
+recursion.o: $(hdrdir)/ruby/internal/cast.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+recursion.o: $(hdrdir)/ruby/internal/compiler_since.h
+recursion.o: $(hdrdir)/ruby/internal/config.h
+recursion.o: $(hdrdir)/ruby/internal/constant_p.h
+recursion.o: $(hdrdir)/ruby/internal/core.h
+recursion.o: $(hdrdir)/ruby/internal/core/rarray.h
+recursion.o: $(hdrdir)/ruby/internal/core/rbasic.h
+recursion.o: $(hdrdir)/ruby/internal/core/rbignum.h
+recursion.o: $(hdrdir)/ruby/internal/core/rclass.h
+recursion.o: $(hdrdir)/ruby/internal/core/rdata.h
+recursion.o: $(hdrdir)/ruby/internal/core/rfile.h
+recursion.o: $(hdrdir)/ruby/internal/core/rhash.h
+recursion.o: $(hdrdir)/ruby/internal/core/robject.h
+recursion.o: $(hdrdir)/ruby/internal/core/rregexp.h
+recursion.o: $(hdrdir)/ruby/internal/core/rstring.h
+recursion.o: $(hdrdir)/ruby/internal/core/rstruct.h
+recursion.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+recursion.o: $(hdrdir)/ruby/internal/ctype.h
+recursion.o: $(hdrdir)/ruby/internal/dllexport.h
+recursion.o: $(hdrdir)/ruby/internal/dosish.h
+recursion.o: $(hdrdir)/ruby/internal/error.h
+recursion.o: $(hdrdir)/ruby/internal/eval.h
+recursion.o: $(hdrdir)/ruby/internal/event.h
+recursion.o: $(hdrdir)/ruby/internal/fl_type.h
+recursion.o: $(hdrdir)/ruby/internal/gc.h
+recursion.o: $(hdrdir)/ruby/internal/glob.h
+recursion.o: $(hdrdir)/ruby/internal/globals.h
+recursion.o: $(hdrdir)/ruby/internal/has/attribute.h
+recursion.o: $(hdrdir)/ruby/internal/has/builtin.h
+recursion.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+recursion.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+recursion.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+recursion.o: $(hdrdir)/ruby/internal/has/extension.h
+recursion.o: $(hdrdir)/ruby/internal/has/feature.h
+recursion.o: $(hdrdir)/ruby/internal/has/warning.h
+recursion.o: $(hdrdir)/ruby/internal/intern/array.h
+recursion.o: $(hdrdir)/ruby/internal/intern/bignum.h
+recursion.o: $(hdrdir)/ruby/internal/intern/class.h
+recursion.o: $(hdrdir)/ruby/internal/intern/compar.h
+recursion.o: $(hdrdir)/ruby/internal/intern/complex.h
+recursion.o: $(hdrdir)/ruby/internal/intern/cont.h
+recursion.o: $(hdrdir)/ruby/internal/intern/dir.h
+recursion.o: $(hdrdir)/ruby/internal/intern/enum.h
+recursion.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+recursion.o: $(hdrdir)/ruby/internal/intern/error.h
+recursion.o: $(hdrdir)/ruby/internal/intern/eval.h
+recursion.o: $(hdrdir)/ruby/internal/intern/file.h
+recursion.o: $(hdrdir)/ruby/internal/intern/gc.h
+recursion.o: $(hdrdir)/ruby/internal/intern/hash.h
+recursion.o: $(hdrdir)/ruby/internal/intern/io.h
+recursion.o: $(hdrdir)/ruby/internal/intern/load.h
+recursion.o: $(hdrdir)/ruby/internal/intern/marshal.h
+recursion.o: $(hdrdir)/ruby/internal/intern/numeric.h
+recursion.o: $(hdrdir)/ruby/internal/intern/object.h
+recursion.o: $(hdrdir)/ruby/internal/intern/parse.h
+recursion.o: $(hdrdir)/ruby/internal/intern/proc.h
+recursion.o: $(hdrdir)/ruby/internal/intern/process.h
+recursion.o: $(hdrdir)/ruby/internal/intern/random.h
+recursion.o: $(hdrdir)/ruby/internal/intern/range.h
+recursion.o: $(hdrdir)/ruby/internal/intern/rational.h
+recursion.o: $(hdrdir)/ruby/internal/intern/re.h
+recursion.o: $(hdrdir)/ruby/internal/intern/ruby.h
+recursion.o: $(hdrdir)/ruby/internal/intern/select.h
+recursion.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+recursion.o: $(hdrdir)/ruby/internal/intern/signal.h
+recursion.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+recursion.o: $(hdrdir)/ruby/internal/intern/string.h
+recursion.o: $(hdrdir)/ruby/internal/intern/struct.h
+recursion.o: $(hdrdir)/ruby/internal/intern/thread.h
+recursion.o: $(hdrdir)/ruby/internal/intern/time.h
+recursion.o: $(hdrdir)/ruby/internal/intern/variable.h
+recursion.o: $(hdrdir)/ruby/internal/intern/vm.h
+recursion.o: $(hdrdir)/ruby/internal/interpreter.h
+recursion.o: $(hdrdir)/ruby/internal/iterator.h
+recursion.o: $(hdrdir)/ruby/internal/memory.h
+recursion.o: $(hdrdir)/ruby/internal/method.h
+recursion.o: $(hdrdir)/ruby/internal/module.h
+recursion.o: $(hdrdir)/ruby/internal/newobj.h
+recursion.o: $(hdrdir)/ruby/internal/rgengc.h
+recursion.o: $(hdrdir)/ruby/internal/scan_args.h
+recursion.o: $(hdrdir)/ruby/internal/special_consts.h
+recursion.o: $(hdrdir)/ruby/internal/static_assert.h
+recursion.o: $(hdrdir)/ruby/internal/stdalign.h
+recursion.o: $(hdrdir)/ruby/internal/stdbool.h
+recursion.o: $(hdrdir)/ruby/internal/symbol.h
+recursion.o: $(hdrdir)/ruby/internal/token_paste.h
+recursion.o: $(hdrdir)/ruby/internal/value.h
+recursion.o: $(hdrdir)/ruby/internal/value_type.h
+recursion.o: $(hdrdir)/ruby/internal/variable.h
+recursion.o: $(hdrdir)/ruby/internal/warning_push.h
+recursion.o: $(hdrdir)/ruby/internal/xmalloc.h
recursion.o: $(hdrdir)/ruby/assert.h
recursion.o: $(hdrdir)/ruby/backward.h
+recursion.o: $(hdrdir)/ruby/backward/2/assume.h
+recursion.o: $(hdrdir)/ruby/backward/2/attributes.h
+recursion.o: $(hdrdir)/ruby/backward/2/bool.h
+recursion.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+recursion.o: $(hdrdir)/ruby/backward/2/inttypes.h
+recursion.o: $(hdrdir)/ruby/backward/2/limits.h
+recursion.o: $(hdrdir)/ruby/backward/2/long_long.h
+recursion.o: $(hdrdir)/ruby/backward/2/stdalign.h
+recursion.o: $(hdrdir)/ruby/backward/2/stdarg.h
recursion.o: $(hdrdir)/ruby/defines.h
recursion.o: $(hdrdir)/ruby/intern.h
recursion.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/regexp/depend b/ext/-test-/regexp/depend
index 7c88e1235c..1b00ccd568 100644
--- a/ext/-test-/regexp/depend
+++ b/ext/-test-/regexp/depend
@@ -2,8 +2,157 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -14,8 +163,157 @@ init.o: init.c
parse_depth_limit.o: $(RUBY_EXTCONF_H)
parse_depth_limit.o: $(arch_hdrdir)/ruby/config.h
parse_depth_limit.o: $(hdrdir)/ruby.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/anyargs.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/assume.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/artificial.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/cold.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/const.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/error.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/format.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noalias.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noinline.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/pure.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/restrict.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/warning.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/attr/weakref.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/cast.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/compiler_since.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/config.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/constant_p.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rarray.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rbasic.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rbignum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rclass.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rdata.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rfile.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rhash.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/robject.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rregexp.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rstring.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rstruct.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/ctype.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/dllexport.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/dosish.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/error.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/eval.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/event.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/fl_type.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/gc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/glob.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/globals.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/attribute.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/builtin.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/extension.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/feature.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/has/warning.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/array.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/bignum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/class.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/compar.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/complex.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/cont.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/dir.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/enum.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/error.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/eval.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/file.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/gc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/hash.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/io.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/load.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/marshal.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/numeric.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/object.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/parse.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/proc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/process.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/random.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/range.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/rational.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/re.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/ruby.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/select.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/signal.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/string.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/struct.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/thread.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/time.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/variable.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/vm.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/interpreter.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/iterator.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/memory.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/method.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/module.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/newobj.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/rgengc.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/scan_args.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/special_consts.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/static_assert.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/stdalign.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/stdbool.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/symbol.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/token_paste.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/value.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/value_type.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/variable.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/warning_push.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/xmalloc.h
parse_depth_limit.o: $(hdrdir)/ruby/assert.h
parse_depth_limit.o: $(hdrdir)/ruby/backward.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/assume.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/attributes.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/bool.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/inttypes.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/limits.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/long_long.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/stdalign.h
+parse_depth_limit.o: $(hdrdir)/ruby/backward/2/stdarg.h
parse_depth_limit.o: $(hdrdir)/ruby/defines.h
parse_depth_limit.o: $(hdrdir)/ruby/intern.h
parse_depth_limit.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/scan_args/depend b/ext/-test-/scan_args/depend
index c230961ae3..91bd8419d0 100644
--- a/ext/-test-/scan_args/depend
+++ b/ext/-test-/scan_args/depend
@@ -2,8 +2,157 @@
scan_args.o: $(RUBY_EXTCONF_H)
scan_args.o: $(arch_hdrdir)/ruby/config.h
scan_args.o: $(hdrdir)/ruby.h
+scan_args.o: $(hdrdir)/ruby/internal/anyargs.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+scan_args.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+scan_args.o: $(hdrdir)/ruby/internal/assume.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/artificial.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/cold.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/const.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/error.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/format.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/noalias.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/noinline.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/pure.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/restrict.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/warning.h
+scan_args.o: $(hdrdir)/ruby/internal/attr/weakref.h
+scan_args.o: $(hdrdir)/ruby/internal/cast.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+scan_args.o: $(hdrdir)/ruby/internal/compiler_since.h
+scan_args.o: $(hdrdir)/ruby/internal/config.h
+scan_args.o: $(hdrdir)/ruby/internal/constant_p.h
+scan_args.o: $(hdrdir)/ruby/internal/core.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rarray.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rbasic.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rbignum.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rclass.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rdata.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rfile.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rhash.h
+scan_args.o: $(hdrdir)/ruby/internal/core/robject.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rregexp.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rstring.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rstruct.h
+scan_args.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+scan_args.o: $(hdrdir)/ruby/internal/ctype.h
+scan_args.o: $(hdrdir)/ruby/internal/dllexport.h
+scan_args.o: $(hdrdir)/ruby/internal/dosish.h
+scan_args.o: $(hdrdir)/ruby/internal/error.h
+scan_args.o: $(hdrdir)/ruby/internal/eval.h
+scan_args.o: $(hdrdir)/ruby/internal/event.h
+scan_args.o: $(hdrdir)/ruby/internal/fl_type.h
+scan_args.o: $(hdrdir)/ruby/internal/gc.h
+scan_args.o: $(hdrdir)/ruby/internal/glob.h
+scan_args.o: $(hdrdir)/ruby/internal/globals.h
+scan_args.o: $(hdrdir)/ruby/internal/has/attribute.h
+scan_args.o: $(hdrdir)/ruby/internal/has/builtin.h
+scan_args.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+scan_args.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+scan_args.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+scan_args.o: $(hdrdir)/ruby/internal/has/extension.h
+scan_args.o: $(hdrdir)/ruby/internal/has/feature.h
+scan_args.o: $(hdrdir)/ruby/internal/has/warning.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/array.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/bignum.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/class.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/compar.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/complex.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/cont.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/dir.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/enum.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/error.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/eval.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/file.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/gc.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/hash.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/io.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/load.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/marshal.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/numeric.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/object.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/parse.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/proc.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/process.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/random.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/range.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/rational.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/re.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/ruby.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/select.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/signal.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/string.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/struct.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/thread.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/time.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/variable.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/vm.h
+scan_args.o: $(hdrdir)/ruby/internal/interpreter.h
+scan_args.o: $(hdrdir)/ruby/internal/iterator.h
+scan_args.o: $(hdrdir)/ruby/internal/memory.h
+scan_args.o: $(hdrdir)/ruby/internal/method.h
+scan_args.o: $(hdrdir)/ruby/internal/module.h
+scan_args.o: $(hdrdir)/ruby/internal/newobj.h
+scan_args.o: $(hdrdir)/ruby/internal/rgengc.h
+scan_args.o: $(hdrdir)/ruby/internal/scan_args.h
+scan_args.o: $(hdrdir)/ruby/internal/special_consts.h
+scan_args.o: $(hdrdir)/ruby/internal/static_assert.h
+scan_args.o: $(hdrdir)/ruby/internal/stdalign.h
+scan_args.o: $(hdrdir)/ruby/internal/stdbool.h
+scan_args.o: $(hdrdir)/ruby/internal/symbol.h
+scan_args.o: $(hdrdir)/ruby/internal/token_paste.h
+scan_args.o: $(hdrdir)/ruby/internal/value.h
+scan_args.o: $(hdrdir)/ruby/internal/value_type.h
+scan_args.o: $(hdrdir)/ruby/internal/variable.h
+scan_args.o: $(hdrdir)/ruby/internal/warning_push.h
+scan_args.o: $(hdrdir)/ruby/internal/xmalloc.h
scan_args.o: $(hdrdir)/ruby/assert.h
scan_args.o: $(hdrdir)/ruby/backward.h
+scan_args.o: $(hdrdir)/ruby/backward/2/assume.h
+scan_args.o: $(hdrdir)/ruby/backward/2/attributes.h
+scan_args.o: $(hdrdir)/ruby/backward/2/bool.h
+scan_args.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+scan_args.o: $(hdrdir)/ruby/backward/2/inttypes.h
+scan_args.o: $(hdrdir)/ruby/backward/2/limits.h
+scan_args.o: $(hdrdir)/ruby/backward/2/long_long.h
+scan_args.o: $(hdrdir)/ruby/backward/2/stdalign.h
+scan_args.o: $(hdrdir)/ruby/backward/2/stdarg.h
scan_args.o: $(hdrdir)/ruby/defines.h
scan_args.o: $(hdrdir)/ruby/intern.h
scan_args.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/scan_args/scan_args.c b/ext/-test-/scan_args/scan_args.c
index 9c374da66f..8696aad3c7 100644
--- a/ext/-test-/scan_args/scan_args.c
+++ b/ext/-test-/scan_args/scan_args.c
@@ -260,15 +260,6 @@ scan_args_k_lead_opt_hash(int argc, VALUE *argv, VALUE self)
}
static VALUE
-scan_args_e_lead_opt_hash(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[4];
- int n = rb_scan_args_kw(RB_SCAN_ARGS_EMPTY_KEYWORDS, argc, argv, "11:", args+1, args+2, args+3);
- args[0] = INT2NUM(n);
- return rb_ary_new_from_values(numberof(args), args);
-}
-
-static VALUE
scan_args_n_lead_opt_hash(int argc, VALUE *argv, VALUE self)
{
VALUE args[4];
@@ -310,6 +301,5 @@ Init_scan_args(void)
rb_define_singleton_method(module, "opt_var_trail_hash", scan_args_opt_var_trail_hash, -1);
rb_define_singleton_method(module, "lead_opt_var_trail_hash", scan_args_lead_opt_var_trail_hash, -1);
rb_define_singleton_method(module, "k_lead_opt_hash", scan_args_k_lead_opt_hash, -1);
- rb_define_singleton_method(module, "e_lead_opt_hash", scan_args_e_lead_opt_hash, -1);
rb_define_singleton_method(module, "n_lead_opt_hash", scan_args_n_lead_opt_hash, -1);
}
diff --git a/ext/-test-/st/foreach/depend b/ext/-test-/st/foreach/depend
index 42d3909f49..25381871f0 100644
--- a/ext/-test-/st/foreach/depend
+++ b/ext/-test-/st/foreach/depend
@@ -2,8 +2,157 @@
foreach.o: $(RUBY_EXTCONF_H)
foreach.o: $(arch_hdrdir)/ruby/config.h
foreach.o: $(hdrdir)/ruby.h
+foreach.o: $(hdrdir)/ruby/internal/anyargs.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+foreach.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+foreach.o: $(hdrdir)/ruby/internal/assume.h
+foreach.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+foreach.o: $(hdrdir)/ruby/internal/attr/artificial.h
+foreach.o: $(hdrdir)/ruby/internal/attr/cold.h
+foreach.o: $(hdrdir)/ruby/internal/attr/const.h
+foreach.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+foreach.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+foreach.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+foreach.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+foreach.o: $(hdrdir)/ruby/internal/attr/error.h
+foreach.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+foreach.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+foreach.o: $(hdrdir)/ruby/internal/attr/format.h
+foreach.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+foreach.o: $(hdrdir)/ruby/internal/attr/noalias.h
+foreach.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+foreach.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+foreach.o: $(hdrdir)/ruby/internal/attr/noinline.h
+foreach.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+foreach.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+foreach.o: $(hdrdir)/ruby/internal/attr/pure.h
+foreach.o: $(hdrdir)/ruby/internal/attr/restrict.h
+foreach.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+foreach.o: $(hdrdir)/ruby/internal/attr/warning.h
+foreach.o: $(hdrdir)/ruby/internal/attr/weakref.h
+foreach.o: $(hdrdir)/ruby/internal/cast.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+foreach.o: $(hdrdir)/ruby/internal/compiler_since.h
+foreach.o: $(hdrdir)/ruby/internal/config.h
+foreach.o: $(hdrdir)/ruby/internal/constant_p.h
+foreach.o: $(hdrdir)/ruby/internal/core.h
+foreach.o: $(hdrdir)/ruby/internal/core/rarray.h
+foreach.o: $(hdrdir)/ruby/internal/core/rbasic.h
+foreach.o: $(hdrdir)/ruby/internal/core/rbignum.h
+foreach.o: $(hdrdir)/ruby/internal/core/rclass.h
+foreach.o: $(hdrdir)/ruby/internal/core/rdata.h
+foreach.o: $(hdrdir)/ruby/internal/core/rfile.h
+foreach.o: $(hdrdir)/ruby/internal/core/rhash.h
+foreach.o: $(hdrdir)/ruby/internal/core/robject.h
+foreach.o: $(hdrdir)/ruby/internal/core/rregexp.h
+foreach.o: $(hdrdir)/ruby/internal/core/rstring.h
+foreach.o: $(hdrdir)/ruby/internal/core/rstruct.h
+foreach.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+foreach.o: $(hdrdir)/ruby/internal/ctype.h
+foreach.o: $(hdrdir)/ruby/internal/dllexport.h
+foreach.o: $(hdrdir)/ruby/internal/dosish.h
+foreach.o: $(hdrdir)/ruby/internal/error.h
+foreach.o: $(hdrdir)/ruby/internal/eval.h
+foreach.o: $(hdrdir)/ruby/internal/event.h
+foreach.o: $(hdrdir)/ruby/internal/fl_type.h
+foreach.o: $(hdrdir)/ruby/internal/gc.h
+foreach.o: $(hdrdir)/ruby/internal/glob.h
+foreach.o: $(hdrdir)/ruby/internal/globals.h
+foreach.o: $(hdrdir)/ruby/internal/has/attribute.h
+foreach.o: $(hdrdir)/ruby/internal/has/builtin.h
+foreach.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+foreach.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+foreach.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+foreach.o: $(hdrdir)/ruby/internal/has/extension.h
+foreach.o: $(hdrdir)/ruby/internal/has/feature.h
+foreach.o: $(hdrdir)/ruby/internal/has/warning.h
+foreach.o: $(hdrdir)/ruby/internal/intern/array.h
+foreach.o: $(hdrdir)/ruby/internal/intern/bignum.h
+foreach.o: $(hdrdir)/ruby/internal/intern/class.h
+foreach.o: $(hdrdir)/ruby/internal/intern/compar.h
+foreach.o: $(hdrdir)/ruby/internal/intern/complex.h
+foreach.o: $(hdrdir)/ruby/internal/intern/cont.h
+foreach.o: $(hdrdir)/ruby/internal/intern/dir.h
+foreach.o: $(hdrdir)/ruby/internal/intern/enum.h
+foreach.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+foreach.o: $(hdrdir)/ruby/internal/intern/error.h
+foreach.o: $(hdrdir)/ruby/internal/intern/eval.h
+foreach.o: $(hdrdir)/ruby/internal/intern/file.h
+foreach.o: $(hdrdir)/ruby/internal/intern/gc.h
+foreach.o: $(hdrdir)/ruby/internal/intern/hash.h
+foreach.o: $(hdrdir)/ruby/internal/intern/io.h
+foreach.o: $(hdrdir)/ruby/internal/intern/load.h
+foreach.o: $(hdrdir)/ruby/internal/intern/marshal.h
+foreach.o: $(hdrdir)/ruby/internal/intern/numeric.h
+foreach.o: $(hdrdir)/ruby/internal/intern/object.h
+foreach.o: $(hdrdir)/ruby/internal/intern/parse.h
+foreach.o: $(hdrdir)/ruby/internal/intern/proc.h
+foreach.o: $(hdrdir)/ruby/internal/intern/process.h
+foreach.o: $(hdrdir)/ruby/internal/intern/random.h
+foreach.o: $(hdrdir)/ruby/internal/intern/range.h
+foreach.o: $(hdrdir)/ruby/internal/intern/rational.h
+foreach.o: $(hdrdir)/ruby/internal/intern/re.h
+foreach.o: $(hdrdir)/ruby/internal/intern/ruby.h
+foreach.o: $(hdrdir)/ruby/internal/intern/select.h
+foreach.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+foreach.o: $(hdrdir)/ruby/internal/intern/signal.h
+foreach.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+foreach.o: $(hdrdir)/ruby/internal/intern/string.h
+foreach.o: $(hdrdir)/ruby/internal/intern/struct.h
+foreach.o: $(hdrdir)/ruby/internal/intern/thread.h
+foreach.o: $(hdrdir)/ruby/internal/intern/time.h
+foreach.o: $(hdrdir)/ruby/internal/intern/variable.h
+foreach.o: $(hdrdir)/ruby/internal/intern/vm.h
+foreach.o: $(hdrdir)/ruby/internal/interpreter.h
+foreach.o: $(hdrdir)/ruby/internal/iterator.h
+foreach.o: $(hdrdir)/ruby/internal/memory.h
+foreach.o: $(hdrdir)/ruby/internal/method.h
+foreach.o: $(hdrdir)/ruby/internal/module.h
+foreach.o: $(hdrdir)/ruby/internal/newobj.h
+foreach.o: $(hdrdir)/ruby/internal/rgengc.h
+foreach.o: $(hdrdir)/ruby/internal/scan_args.h
+foreach.o: $(hdrdir)/ruby/internal/special_consts.h
+foreach.o: $(hdrdir)/ruby/internal/static_assert.h
+foreach.o: $(hdrdir)/ruby/internal/stdalign.h
+foreach.o: $(hdrdir)/ruby/internal/stdbool.h
+foreach.o: $(hdrdir)/ruby/internal/symbol.h
+foreach.o: $(hdrdir)/ruby/internal/token_paste.h
+foreach.o: $(hdrdir)/ruby/internal/value.h
+foreach.o: $(hdrdir)/ruby/internal/value_type.h
+foreach.o: $(hdrdir)/ruby/internal/variable.h
+foreach.o: $(hdrdir)/ruby/internal/warning_push.h
+foreach.o: $(hdrdir)/ruby/internal/xmalloc.h
foreach.o: $(hdrdir)/ruby/assert.h
foreach.o: $(hdrdir)/ruby/backward.h
+foreach.o: $(hdrdir)/ruby/backward/2/assume.h
+foreach.o: $(hdrdir)/ruby/backward/2/attributes.h
+foreach.o: $(hdrdir)/ruby/backward/2/bool.h
+foreach.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+foreach.o: $(hdrdir)/ruby/backward/2/inttypes.h
+foreach.o: $(hdrdir)/ruby/backward/2/limits.h
+foreach.o: $(hdrdir)/ruby/backward/2/long_long.h
+foreach.o: $(hdrdir)/ruby/backward/2/stdalign.h
+foreach.o: $(hdrdir)/ruby/backward/2/stdarg.h
foreach.o: $(hdrdir)/ruby/defines.h
foreach.o: $(hdrdir)/ruby/intern.h
foreach.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/st/numhash/depend b/ext/-test-/st/numhash/depend
index 98dcef881b..8e0560e018 100644
--- a/ext/-test-/st/numhash/depend
+++ b/ext/-test-/st/numhash/depend
@@ -2,8 +2,157 @@
numhash.o: $(RUBY_EXTCONF_H)
numhash.o: $(arch_hdrdir)/ruby/config.h
numhash.o: $(hdrdir)/ruby.h
+numhash.o: $(hdrdir)/ruby/internal/anyargs.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+numhash.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+numhash.o: $(hdrdir)/ruby/internal/assume.h
+numhash.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+numhash.o: $(hdrdir)/ruby/internal/attr/artificial.h
+numhash.o: $(hdrdir)/ruby/internal/attr/cold.h
+numhash.o: $(hdrdir)/ruby/internal/attr/const.h
+numhash.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+numhash.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+numhash.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+numhash.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+numhash.o: $(hdrdir)/ruby/internal/attr/error.h
+numhash.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+numhash.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+numhash.o: $(hdrdir)/ruby/internal/attr/format.h
+numhash.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+numhash.o: $(hdrdir)/ruby/internal/attr/noalias.h
+numhash.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+numhash.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+numhash.o: $(hdrdir)/ruby/internal/attr/noinline.h
+numhash.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+numhash.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+numhash.o: $(hdrdir)/ruby/internal/attr/pure.h
+numhash.o: $(hdrdir)/ruby/internal/attr/restrict.h
+numhash.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+numhash.o: $(hdrdir)/ruby/internal/attr/warning.h
+numhash.o: $(hdrdir)/ruby/internal/attr/weakref.h
+numhash.o: $(hdrdir)/ruby/internal/cast.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+numhash.o: $(hdrdir)/ruby/internal/compiler_since.h
+numhash.o: $(hdrdir)/ruby/internal/config.h
+numhash.o: $(hdrdir)/ruby/internal/constant_p.h
+numhash.o: $(hdrdir)/ruby/internal/core.h
+numhash.o: $(hdrdir)/ruby/internal/core/rarray.h
+numhash.o: $(hdrdir)/ruby/internal/core/rbasic.h
+numhash.o: $(hdrdir)/ruby/internal/core/rbignum.h
+numhash.o: $(hdrdir)/ruby/internal/core/rclass.h
+numhash.o: $(hdrdir)/ruby/internal/core/rdata.h
+numhash.o: $(hdrdir)/ruby/internal/core/rfile.h
+numhash.o: $(hdrdir)/ruby/internal/core/rhash.h
+numhash.o: $(hdrdir)/ruby/internal/core/robject.h
+numhash.o: $(hdrdir)/ruby/internal/core/rregexp.h
+numhash.o: $(hdrdir)/ruby/internal/core/rstring.h
+numhash.o: $(hdrdir)/ruby/internal/core/rstruct.h
+numhash.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+numhash.o: $(hdrdir)/ruby/internal/ctype.h
+numhash.o: $(hdrdir)/ruby/internal/dllexport.h
+numhash.o: $(hdrdir)/ruby/internal/dosish.h
+numhash.o: $(hdrdir)/ruby/internal/error.h
+numhash.o: $(hdrdir)/ruby/internal/eval.h
+numhash.o: $(hdrdir)/ruby/internal/event.h
+numhash.o: $(hdrdir)/ruby/internal/fl_type.h
+numhash.o: $(hdrdir)/ruby/internal/gc.h
+numhash.o: $(hdrdir)/ruby/internal/glob.h
+numhash.o: $(hdrdir)/ruby/internal/globals.h
+numhash.o: $(hdrdir)/ruby/internal/has/attribute.h
+numhash.o: $(hdrdir)/ruby/internal/has/builtin.h
+numhash.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+numhash.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+numhash.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+numhash.o: $(hdrdir)/ruby/internal/has/extension.h
+numhash.o: $(hdrdir)/ruby/internal/has/feature.h
+numhash.o: $(hdrdir)/ruby/internal/has/warning.h
+numhash.o: $(hdrdir)/ruby/internal/intern/array.h
+numhash.o: $(hdrdir)/ruby/internal/intern/bignum.h
+numhash.o: $(hdrdir)/ruby/internal/intern/class.h
+numhash.o: $(hdrdir)/ruby/internal/intern/compar.h
+numhash.o: $(hdrdir)/ruby/internal/intern/complex.h
+numhash.o: $(hdrdir)/ruby/internal/intern/cont.h
+numhash.o: $(hdrdir)/ruby/internal/intern/dir.h
+numhash.o: $(hdrdir)/ruby/internal/intern/enum.h
+numhash.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+numhash.o: $(hdrdir)/ruby/internal/intern/error.h
+numhash.o: $(hdrdir)/ruby/internal/intern/eval.h
+numhash.o: $(hdrdir)/ruby/internal/intern/file.h
+numhash.o: $(hdrdir)/ruby/internal/intern/gc.h
+numhash.o: $(hdrdir)/ruby/internal/intern/hash.h
+numhash.o: $(hdrdir)/ruby/internal/intern/io.h
+numhash.o: $(hdrdir)/ruby/internal/intern/load.h
+numhash.o: $(hdrdir)/ruby/internal/intern/marshal.h
+numhash.o: $(hdrdir)/ruby/internal/intern/numeric.h
+numhash.o: $(hdrdir)/ruby/internal/intern/object.h
+numhash.o: $(hdrdir)/ruby/internal/intern/parse.h
+numhash.o: $(hdrdir)/ruby/internal/intern/proc.h
+numhash.o: $(hdrdir)/ruby/internal/intern/process.h
+numhash.o: $(hdrdir)/ruby/internal/intern/random.h
+numhash.o: $(hdrdir)/ruby/internal/intern/range.h
+numhash.o: $(hdrdir)/ruby/internal/intern/rational.h
+numhash.o: $(hdrdir)/ruby/internal/intern/re.h
+numhash.o: $(hdrdir)/ruby/internal/intern/ruby.h
+numhash.o: $(hdrdir)/ruby/internal/intern/select.h
+numhash.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+numhash.o: $(hdrdir)/ruby/internal/intern/signal.h
+numhash.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+numhash.o: $(hdrdir)/ruby/internal/intern/string.h
+numhash.o: $(hdrdir)/ruby/internal/intern/struct.h
+numhash.o: $(hdrdir)/ruby/internal/intern/thread.h
+numhash.o: $(hdrdir)/ruby/internal/intern/time.h
+numhash.o: $(hdrdir)/ruby/internal/intern/variable.h
+numhash.o: $(hdrdir)/ruby/internal/intern/vm.h
+numhash.o: $(hdrdir)/ruby/internal/interpreter.h
+numhash.o: $(hdrdir)/ruby/internal/iterator.h
+numhash.o: $(hdrdir)/ruby/internal/memory.h
+numhash.o: $(hdrdir)/ruby/internal/method.h
+numhash.o: $(hdrdir)/ruby/internal/module.h
+numhash.o: $(hdrdir)/ruby/internal/newobj.h
+numhash.o: $(hdrdir)/ruby/internal/rgengc.h
+numhash.o: $(hdrdir)/ruby/internal/scan_args.h
+numhash.o: $(hdrdir)/ruby/internal/special_consts.h
+numhash.o: $(hdrdir)/ruby/internal/static_assert.h
+numhash.o: $(hdrdir)/ruby/internal/stdalign.h
+numhash.o: $(hdrdir)/ruby/internal/stdbool.h
+numhash.o: $(hdrdir)/ruby/internal/symbol.h
+numhash.o: $(hdrdir)/ruby/internal/token_paste.h
+numhash.o: $(hdrdir)/ruby/internal/value.h
+numhash.o: $(hdrdir)/ruby/internal/value_type.h
+numhash.o: $(hdrdir)/ruby/internal/variable.h
+numhash.o: $(hdrdir)/ruby/internal/warning_push.h
+numhash.o: $(hdrdir)/ruby/internal/xmalloc.h
numhash.o: $(hdrdir)/ruby/assert.h
numhash.o: $(hdrdir)/ruby/backward.h
+numhash.o: $(hdrdir)/ruby/backward/2/assume.h
+numhash.o: $(hdrdir)/ruby/backward/2/attributes.h
+numhash.o: $(hdrdir)/ruby/backward/2/bool.h
+numhash.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+numhash.o: $(hdrdir)/ruby/backward/2/inttypes.h
+numhash.o: $(hdrdir)/ruby/backward/2/limits.h
+numhash.o: $(hdrdir)/ruby/backward/2/long_long.h
+numhash.o: $(hdrdir)/ruby/backward/2/stdalign.h
+numhash.o: $(hdrdir)/ruby/backward/2/stdarg.h
numhash.o: $(hdrdir)/ruby/defines.h
numhash.o: $(hdrdir)/ruby/intern.h
numhash.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/st/numhash/numhash.c b/ext/-test-/st/numhash/numhash.c
index 71eeed4910..aa8015e86c 100644
--- a/ext/-test-/st/numhash/numhash.c
+++ b/ext/-test-/st/numhash/numhash.c
@@ -125,7 +125,7 @@ numhash_delete_safe(VALUE self, VALUE key)
void
Init_numhash(void)
{
- VALUE st = rb_define_class_under(rb_define_module("Bug"), "StNumHash", rb_cData);
+ VALUE st = rb_define_class_under(rb_define_module("Bug"), "StNumHash", rb_cObject);
rb_define_alloc_func(st, numhash_alloc);
rb_define_method(st, "initialize", numhash_init, 0);
rb_define_method(st, "[]", numhash_aref, 1);
diff --git a/ext/-test-/st/update/depend b/ext/-test-/st/update/depend
index 241e6f9e6d..c11a5b14a7 100644
--- a/ext/-test-/st/update/depend
+++ b/ext/-test-/st/update/depend
@@ -2,8 +2,157 @@
update.o: $(RUBY_EXTCONF_H)
update.o: $(arch_hdrdir)/ruby/config.h
update.o: $(hdrdir)/ruby.h
+update.o: $(hdrdir)/ruby/internal/anyargs.h
+update.o: $(hdrdir)/ruby/internal/arithmetic.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+update.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+update.o: $(hdrdir)/ruby/internal/assume.h
+update.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+update.o: $(hdrdir)/ruby/internal/attr/artificial.h
+update.o: $(hdrdir)/ruby/internal/attr/cold.h
+update.o: $(hdrdir)/ruby/internal/attr/const.h
+update.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+update.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+update.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+update.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+update.o: $(hdrdir)/ruby/internal/attr/error.h
+update.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+update.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+update.o: $(hdrdir)/ruby/internal/attr/format.h
+update.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+update.o: $(hdrdir)/ruby/internal/attr/noalias.h
+update.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+update.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+update.o: $(hdrdir)/ruby/internal/attr/noinline.h
+update.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+update.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+update.o: $(hdrdir)/ruby/internal/attr/pure.h
+update.o: $(hdrdir)/ruby/internal/attr/restrict.h
+update.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+update.o: $(hdrdir)/ruby/internal/attr/warning.h
+update.o: $(hdrdir)/ruby/internal/attr/weakref.h
+update.o: $(hdrdir)/ruby/internal/cast.h
+update.o: $(hdrdir)/ruby/internal/compiler_is.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+update.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+update.o: $(hdrdir)/ruby/internal/compiler_since.h
+update.o: $(hdrdir)/ruby/internal/config.h
+update.o: $(hdrdir)/ruby/internal/constant_p.h
+update.o: $(hdrdir)/ruby/internal/core.h
+update.o: $(hdrdir)/ruby/internal/core/rarray.h
+update.o: $(hdrdir)/ruby/internal/core/rbasic.h
+update.o: $(hdrdir)/ruby/internal/core/rbignum.h
+update.o: $(hdrdir)/ruby/internal/core/rclass.h
+update.o: $(hdrdir)/ruby/internal/core/rdata.h
+update.o: $(hdrdir)/ruby/internal/core/rfile.h
+update.o: $(hdrdir)/ruby/internal/core/rhash.h
+update.o: $(hdrdir)/ruby/internal/core/robject.h
+update.o: $(hdrdir)/ruby/internal/core/rregexp.h
+update.o: $(hdrdir)/ruby/internal/core/rstring.h
+update.o: $(hdrdir)/ruby/internal/core/rstruct.h
+update.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+update.o: $(hdrdir)/ruby/internal/ctype.h
+update.o: $(hdrdir)/ruby/internal/dllexport.h
+update.o: $(hdrdir)/ruby/internal/dosish.h
+update.o: $(hdrdir)/ruby/internal/error.h
+update.o: $(hdrdir)/ruby/internal/eval.h
+update.o: $(hdrdir)/ruby/internal/event.h
+update.o: $(hdrdir)/ruby/internal/fl_type.h
+update.o: $(hdrdir)/ruby/internal/gc.h
+update.o: $(hdrdir)/ruby/internal/glob.h
+update.o: $(hdrdir)/ruby/internal/globals.h
+update.o: $(hdrdir)/ruby/internal/has/attribute.h
+update.o: $(hdrdir)/ruby/internal/has/builtin.h
+update.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+update.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+update.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+update.o: $(hdrdir)/ruby/internal/has/extension.h
+update.o: $(hdrdir)/ruby/internal/has/feature.h
+update.o: $(hdrdir)/ruby/internal/has/warning.h
+update.o: $(hdrdir)/ruby/internal/intern/array.h
+update.o: $(hdrdir)/ruby/internal/intern/bignum.h
+update.o: $(hdrdir)/ruby/internal/intern/class.h
+update.o: $(hdrdir)/ruby/internal/intern/compar.h
+update.o: $(hdrdir)/ruby/internal/intern/complex.h
+update.o: $(hdrdir)/ruby/internal/intern/cont.h
+update.o: $(hdrdir)/ruby/internal/intern/dir.h
+update.o: $(hdrdir)/ruby/internal/intern/enum.h
+update.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+update.o: $(hdrdir)/ruby/internal/intern/error.h
+update.o: $(hdrdir)/ruby/internal/intern/eval.h
+update.o: $(hdrdir)/ruby/internal/intern/file.h
+update.o: $(hdrdir)/ruby/internal/intern/gc.h
+update.o: $(hdrdir)/ruby/internal/intern/hash.h
+update.o: $(hdrdir)/ruby/internal/intern/io.h
+update.o: $(hdrdir)/ruby/internal/intern/load.h
+update.o: $(hdrdir)/ruby/internal/intern/marshal.h
+update.o: $(hdrdir)/ruby/internal/intern/numeric.h
+update.o: $(hdrdir)/ruby/internal/intern/object.h
+update.o: $(hdrdir)/ruby/internal/intern/parse.h
+update.o: $(hdrdir)/ruby/internal/intern/proc.h
+update.o: $(hdrdir)/ruby/internal/intern/process.h
+update.o: $(hdrdir)/ruby/internal/intern/random.h
+update.o: $(hdrdir)/ruby/internal/intern/range.h
+update.o: $(hdrdir)/ruby/internal/intern/rational.h
+update.o: $(hdrdir)/ruby/internal/intern/re.h
+update.o: $(hdrdir)/ruby/internal/intern/ruby.h
+update.o: $(hdrdir)/ruby/internal/intern/select.h
+update.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+update.o: $(hdrdir)/ruby/internal/intern/signal.h
+update.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+update.o: $(hdrdir)/ruby/internal/intern/string.h
+update.o: $(hdrdir)/ruby/internal/intern/struct.h
+update.o: $(hdrdir)/ruby/internal/intern/thread.h
+update.o: $(hdrdir)/ruby/internal/intern/time.h
+update.o: $(hdrdir)/ruby/internal/intern/variable.h
+update.o: $(hdrdir)/ruby/internal/intern/vm.h
+update.o: $(hdrdir)/ruby/internal/interpreter.h
+update.o: $(hdrdir)/ruby/internal/iterator.h
+update.o: $(hdrdir)/ruby/internal/memory.h
+update.o: $(hdrdir)/ruby/internal/method.h
+update.o: $(hdrdir)/ruby/internal/module.h
+update.o: $(hdrdir)/ruby/internal/newobj.h
+update.o: $(hdrdir)/ruby/internal/rgengc.h
+update.o: $(hdrdir)/ruby/internal/scan_args.h
+update.o: $(hdrdir)/ruby/internal/special_consts.h
+update.o: $(hdrdir)/ruby/internal/static_assert.h
+update.o: $(hdrdir)/ruby/internal/stdalign.h
+update.o: $(hdrdir)/ruby/internal/stdbool.h
+update.o: $(hdrdir)/ruby/internal/symbol.h
+update.o: $(hdrdir)/ruby/internal/token_paste.h
+update.o: $(hdrdir)/ruby/internal/value.h
+update.o: $(hdrdir)/ruby/internal/value_type.h
+update.o: $(hdrdir)/ruby/internal/variable.h
+update.o: $(hdrdir)/ruby/internal/warning_push.h
+update.o: $(hdrdir)/ruby/internal/xmalloc.h
update.o: $(hdrdir)/ruby/assert.h
update.o: $(hdrdir)/ruby/backward.h
+update.o: $(hdrdir)/ruby/backward/2/assume.h
+update.o: $(hdrdir)/ruby/backward/2/attributes.h
+update.o: $(hdrdir)/ruby/backward/2/bool.h
+update.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+update.o: $(hdrdir)/ruby/backward/2/inttypes.h
+update.o: $(hdrdir)/ruby/backward/2/limits.h
+update.o: $(hdrdir)/ruby/backward/2/long_long.h
+update.o: $(hdrdir)/ruby/backward/2/stdalign.h
+update.o: $(hdrdir)/ruby/backward/2/stdarg.h
update.o: $(hdrdir)/ruby/defines.h
update.o: $(hdrdir)/ruby/intern.h
update.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/string/capacity.c b/ext/-test-/string/capacity.c
index f5277bf4e6..cb8d2c2b3a 100644
--- a/ext/-test-/string/capacity.c
+++ b/ext/-test-/string/capacity.c
@@ -1,5 +1,5 @@
#include "ruby.h"
-#include "internal.h"
+#include "internal/string.h"
static VALUE
bug_str_capacity(VALUE klass, VALUE str)
diff --git a/ext/-test-/string/coderange.c b/ext/-test-/string/coderange.c
index 1342ce20da..bc998ca372 100644
--- a/ext/-test-/string/coderange.c
+++ b/ext/-test-/string/coderange.c
@@ -38,10 +38,10 @@ str_coderange_scan(VALUE str)
void
Init_string_coderange(VALUE klass)
{
- sym_7bit = ID2SYM(rb_intern("7bit"));
- sym_valid = ID2SYM(rb_intern("valid"));
- sym_unknown = ID2SYM(rb_intern("unknown"));
- sym_broken = ID2SYM(rb_intern("broken"));
+ sym_7bit = ID2SYM(rb_intern_const("7bit"));
+ sym_valid = ID2SYM(rb_intern_const("valid"));
+ sym_unknown = ID2SYM(rb_intern_const("unknown"));
+ sym_broken = ID2SYM(rb_intern_const("broken"));
rb_define_method(klass, "coderange", str_coderange, 0);
rb_define_method(klass, "coderange_scan", str_coderange_scan, 0);
}
diff --git a/ext/-test-/string/cstr.c b/ext/-test-/string/cstr.c
index 71eafdb703..4f837998d7 100644
--- a/ext/-test-/string/cstr.c
+++ b/ext/-test-/string/cstr.c
@@ -1,5 +1,6 @@
-#include "ruby/encoding.h"
#include "internal.h"
+#include "internal/string.h"
+#include "ruby/encoding.h"
static VALUE
bug_str_cstr_term(VALUE str)
diff --git a/ext/-test-/string/depend b/ext/-test-/string/depend
index f6888b5da7..7db4465bf9 100644
--- a/ext/-test-/string/depend
+++ b/ext/-test-/string/depend
@@ -4,21 +4,324 @@ capacity.o: $(arch_hdrdir)/ruby/config.h
capacity.o: $(hdrdir)/ruby.h
capacity.o: $(hdrdir)/ruby/assert.h
capacity.o: $(hdrdir)/ruby/backward.h
+capacity.o: $(hdrdir)/ruby/backward/2/assume.h
+capacity.o: $(hdrdir)/ruby/backward/2/attributes.h
+capacity.o: $(hdrdir)/ruby/backward/2/bool.h
+capacity.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+capacity.o: $(hdrdir)/ruby/backward/2/inttypes.h
+capacity.o: $(hdrdir)/ruby/backward/2/limits.h
+capacity.o: $(hdrdir)/ruby/backward/2/long_long.h
+capacity.o: $(hdrdir)/ruby/backward/2/stdalign.h
+capacity.o: $(hdrdir)/ruby/backward/2/stdarg.h
capacity.o: $(hdrdir)/ruby/defines.h
+capacity.o: $(hdrdir)/ruby/encoding.h
capacity.o: $(hdrdir)/ruby/intern.h
+capacity.o: $(hdrdir)/ruby/internal/anyargs.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+capacity.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+capacity.o: $(hdrdir)/ruby/internal/assume.h
+capacity.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+capacity.o: $(hdrdir)/ruby/internal/attr/artificial.h
+capacity.o: $(hdrdir)/ruby/internal/attr/cold.h
+capacity.o: $(hdrdir)/ruby/internal/attr/const.h
+capacity.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+capacity.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+capacity.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+capacity.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+capacity.o: $(hdrdir)/ruby/internal/attr/error.h
+capacity.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+capacity.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+capacity.o: $(hdrdir)/ruby/internal/attr/format.h
+capacity.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+capacity.o: $(hdrdir)/ruby/internal/attr/noalias.h
+capacity.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+capacity.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+capacity.o: $(hdrdir)/ruby/internal/attr/noinline.h
+capacity.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+capacity.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+capacity.o: $(hdrdir)/ruby/internal/attr/pure.h
+capacity.o: $(hdrdir)/ruby/internal/attr/restrict.h
+capacity.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+capacity.o: $(hdrdir)/ruby/internal/attr/warning.h
+capacity.o: $(hdrdir)/ruby/internal/attr/weakref.h
+capacity.o: $(hdrdir)/ruby/internal/cast.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+capacity.o: $(hdrdir)/ruby/internal/compiler_since.h
+capacity.o: $(hdrdir)/ruby/internal/config.h
+capacity.o: $(hdrdir)/ruby/internal/constant_p.h
+capacity.o: $(hdrdir)/ruby/internal/core.h
+capacity.o: $(hdrdir)/ruby/internal/core/rarray.h
+capacity.o: $(hdrdir)/ruby/internal/core/rbasic.h
+capacity.o: $(hdrdir)/ruby/internal/core/rbignum.h
+capacity.o: $(hdrdir)/ruby/internal/core/rclass.h
+capacity.o: $(hdrdir)/ruby/internal/core/rdata.h
+capacity.o: $(hdrdir)/ruby/internal/core/rfile.h
+capacity.o: $(hdrdir)/ruby/internal/core/rhash.h
+capacity.o: $(hdrdir)/ruby/internal/core/robject.h
+capacity.o: $(hdrdir)/ruby/internal/core/rregexp.h
+capacity.o: $(hdrdir)/ruby/internal/core/rstring.h
+capacity.o: $(hdrdir)/ruby/internal/core/rstruct.h
+capacity.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+capacity.o: $(hdrdir)/ruby/internal/ctype.h
+capacity.o: $(hdrdir)/ruby/internal/dllexport.h
+capacity.o: $(hdrdir)/ruby/internal/dosish.h
+capacity.o: $(hdrdir)/ruby/internal/error.h
+capacity.o: $(hdrdir)/ruby/internal/eval.h
+capacity.o: $(hdrdir)/ruby/internal/event.h
+capacity.o: $(hdrdir)/ruby/internal/fl_type.h
+capacity.o: $(hdrdir)/ruby/internal/gc.h
+capacity.o: $(hdrdir)/ruby/internal/glob.h
+capacity.o: $(hdrdir)/ruby/internal/globals.h
+capacity.o: $(hdrdir)/ruby/internal/has/attribute.h
+capacity.o: $(hdrdir)/ruby/internal/has/builtin.h
+capacity.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+capacity.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+capacity.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+capacity.o: $(hdrdir)/ruby/internal/has/extension.h
+capacity.o: $(hdrdir)/ruby/internal/has/feature.h
+capacity.o: $(hdrdir)/ruby/internal/has/warning.h
+capacity.o: $(hdrdir)/ruby/internal/intern/array.h
+capacity.o: $(hdrdir)/ruby/internal/intern/bignum.h
+capacity.o: $(hdrdir)/ruby/internal/intern/class.h
+capacity.o: $(hdrdir)/ruby/internal/intern/compar.h
+capacity.o: $(hdrdir)/ruby/internal/intern/complex.h
+capacity.o: $(hdrdir)/ruby/internal/intern/cont.h
+capacity.o: $(hdrdir)/ruby/internal/intern/dir.h
+capacity.o: $(hdrdir)/ruby/internal/intern/enum.h
+capacity.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+capacity.o: $(hdrdir)/ruby/internal/intern/error.h
+capacity.o: $(hdrdir)/ruby/internal/intern/eval.h
+capacity.o: $(hdrdir)/ruby/internal/intern/file.h
+capacity.o: $(hdrdir)/ruby/internal/intern/gc.h
+capacity.o: $(hdrdir)/ruby/internal/intern/hash.h
+capacity.o: $(hdrdir)/ruby/internal/intern/io.h
+capacity.o: $(hdrdir)/ruby/internal/intern/load.h
+capacity.o: $(hdrdir)/ruby/internal/intern/marshal.h
+capacity.o: $(hdrdir)/ruby/internal/intern/numeric.h
+capacity.o: $(hdrdir)/ruby/internal/intern/object.h
+capacity.o: $(hdrdir)/ruby/internal/intern/parse.h
+capacity.o: $(hdrdir)/ruby/internal/intern/proc.h
+capacity.o: $(hdrdir)/ruby/internal/intern/process.h
+capacity.o: $(hdrdir)/ruby/internal/intern/random.h
+capacity.o: $(hdrdir)/ruby/internal/intern/range.h
+capacity.o: $(hdrdir)/ruby/internal/intern/rational.h
+capacity.o: $(hdrdir)/ruby/internal/intern/re.h
+capacity.o: $(hdrdir)/ruby/internal/intern/ruby.h
+capacity.o: $(hdrdir)/ruby/internal/intern/select.h
+capacity.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+capacity.o: $(hdrdir)/ruby/internal/intern/signal.h
+capacity.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+capacity.o: $(hdrdir)/ruby/internal/intern/string.h
+capacity.o: $(hdrdir)/ruby/internal/intern/struct.h
+capacity.o: $(hdrdir)/ruby/internal/intern/thread.h
+capacity.o: $(hdrdir)/ruby/internal/intern/time.h
+capacity.o: $(hdrdir)/ruby/internal/intern/variable.h
+capacity.o: $(hdrdir)/ruby/internal/intern/vm.h
+capacity.o: $(hdrdir)/ruby/internal/interpreter.h
+capacity.o: $(hdrdir)/ruby/internal/iterator.h
+capacity.o: $(hdrdir)/ruby/internal/memory.h
+capacity.o: $(hdrdir)/ruby/internal/method.h
+capacity.o: $(hdrdir)/ruby/internal/module.h
+capacity.o: $(hdrdir)/ruby/internal/newobj.h
+capacity.o: $(hdrdir)/ruby/internal/rgengc.h
+capacity.o: $(hdrdir)/ruby/internal/scan_args.h
+capacity.o: $(hdrdir)/ruby/internal/special_consts.h
+capacity.o: $(hdrdir)/ruby/internal/static_assert.h
+capacity.o: $(hdrdir)/ruby/internal/stdalign.h
+capacity.o: $(hdrdir)/ruby/internal/stdbool.h
+capacity.o: $(hdrdir)/ruby/internal/symbol.h
+capacity.o: $(hdrdir)/ruby/internal/token_paste.h
+capacity.o: $(hdrdir)/ruby/internal/value.h
+capacity.o: $(hdrdir)/ruby/internal/value_type.h
+capacity.o: $(hdrdir)/ruby/internal/variable.h
+capacity.o: $(hdrdir)/ruby/internal/warning_push.h
+capacity.o: $(hdrdir)/ruby/internal/xmalloc.h
capacity.o: $(hdrdir)/ruby/missing.h
+capacity.o: $(hdrdir)/ruby/onigmo.h
+capacity.o: $(hdrdir)/ruby/oniguruma.h
capacity.o: $(hdrdir)/ruby/ruby.h
capacity.o: $(hdrdir)/ruby/st.h
capacity.o: $(hdrdir)/ruby/subst.h
capacity.o: $(top_srcdir)/internal.h
+capacity.o: $(top_srcdir)/internal/compilers.h
+capacity.o: $(top_srcdir)/internal/string.h
capacity.o: capacity.c
coderange.o: $(RUBY_EXTCONF_H)
coderange.o: $(arch_hdrdir)/ruby/config.h
coderange.o: $(hdrdir)/ruby/assert.h
coderange.o: $(hdrdir)/ruby/backward.h
+coderange.o: $(hdrdir)/ruby/backward/2/assume.h
+coderange.o: $(hdrdir)/ruby/backward/2/attributes.h
+coderange.o: $(hdrdir)/ruby/backward/2/bool.h
+coderange.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+coderange.o: $(hdrdir)/ruby/backward/2/inttypes.h
+coderange.o: $(hdrdir)/ruby/backward/2/limits.h
+coderange.o: $(hdrdir)/ruby/backward/2/long_long.h
+coderange.o: $(hdrdir)/ruby/backward/2/stdalign.h
+coderange.o: $(hdrdir)/ruby/backward/2/stdarg.h
coderange.o: $(hdrdir)/ruby/defines.h
coderange.o: $(hdrdir)/ruby/encoding.h
coderange.o: $(hdrdir)/ruby/intern.h
+coderange.o: $(hdrdir)/ruby/internal/anyargs.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+coderange.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+coderange.o: $(hdrdir)/ruby/internal/assume.h
+coderange.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+coderange.o: $(hdrdir)/ruby/internal/attr/artificial.h
+coderange.o: $(hdrdir)/ruby/internal/attr/cold.h
+coderange.o: $(hdrdir)/ruby/internal/attr/const.h
+coderange.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+coderange.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+coderange.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+coderange.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+coderange.o: $(hdrdir)/ruby/internal/attr/error.h
+coderange.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+coderange.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+coderange.o: $(hdrdir)/ruby/internal/attr/format.h
+coderange.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+coderange.o: $(hdrdir)/ruby/internal/attr/noalias.h
+coderange.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+coderange.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+coderange.o: $(hdrdir)/ruby/internal/attr/noinline.h
+coderange.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+coderange.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+coderange.o: $(hdrdir)/ruby/internal/attr/pure.h
+coderange.o: $(hdrdir)/ruby/internal/attr/restrict.h
+coderange.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+coderange.o: $(hdrdir)/ruby/internal/attr/warning.h
+coderange.o: $(hdrdir)/ruby/internal/attr/weakref.h
+coderange.o: $(hdrdir)/ruby/internal/cast.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+coderange.o: $(hdrdir)/ruby/internal/compiler_since.h
+coderange.o: $(hdrdir)/ruby/internal/config.h
+coderange.o: $(hdrdir)/ruby/internal/constant_p.h
+coderange.o: $(hdrdir)/ruby/internal/core.h
+coderange.o: $(hdrdir)/ruby/internal/core/rarray.h
+coderange.o: $(hdrdir)/ruby/internal/core/rbasic.h
+coderange.o: $(hdrdir)/ruby/internal/core/rbignum.h
+coderange.o: $(hdrdir)/ruby/internal/core/rclass.h
+coderange.o: $(hdrdir)/ruby/internal/core/rdata.h
+coderange.o: $(hdrdir)/ruby/internal/core/rfile.h
+coderange.o: $(hdrdir)/ruby/internal/core/rhash.h
+coderange.o: $(hdrdir)/ruby/internal/core/robject.h
+coderange.o: $(hdrdir)/ruby/internal/core/rregexp.h
+coderange.o: $(hdrdir)/ruby/internal/core/rstring.h
+coderange.o: $(hdrdir)/ruby/internal/core/rstruct.h
+coderange.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+coderange.o: $(hdrdir)/ruby/internal/ctype.h
+coderange.o: $(hdrdir)/ruby/internal/dllexport.h
+coderange.o: $(hdrdir)/ruby/internal/dosish.h
+coderange.o: $(hdrdir)/ruby/internal/error.h
+coderange.o: $(hdrdir)/ruby/internal/eval.h
+coderange.o: $(hdrdir)/ruby/internal/event.h
+coderange.o: $(hdrdir)/ruby/internal/fl_type.h
+coderange.o: $(hdrdir)/ruby/internal/gc.h
+coderange.o: $(hdrdir)/ruby/internal/glob.h
+coderange.o: $(hdrdir)/ruby/internal/globals.h
+coderange.o: $(hdrdir)/ruby/internal/has/attribute.h
+coderange.o: $(hdrdir)/ruby/internal/has/builtin.h
+coderange.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+coderange.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+coderange.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+coderange.o: $(hdrdir)/ruby/internal/has/extension.h
+coderange.o: $(hdrdir)/ruby/internal/has/feature.h
+coderange.o: $(hdrdir)/ruby/internal/has/warning.h
+coderange.o: $(hdrdir)/ruby/internal/intern/array.h
+coderange.o: $(hdrdir)/ruby/internal/intern/bignum.h
+coderange.o: $(hdrdir)/ruby/internal/intern/class.h
+coderange.o: $(hdrdir)/ruby/internal/intern/compar.h
+coderange.o: $(hdrdir)/ruby/internal/intern/complex.h
+coderange.o: $(hdrdir)/ruby/internal/intern/cont.h
+coderange.o: $(hdrdir)/ruby/internal/intern/dir.h
+coderange.o: $(hdrdir)/ruby/internal/intern/enum.h
+coderange.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+coderange.o: $(hdrdir)/ruby/internal/intern/error.h
+coderange.o: $(hdrdir)/ruby/internal/intern/eval.h
+coderange.o: $(hdrdir)/ruby/internal/intern/file.h
+coderange.o: $(hdrdir)/ruby/internal/intern/gc.h
+coderange.o: $(hdrdir)/ruby/internal/intern/hash.h
+coderange.o: $(hdrdir)/ruby/internal/intern/io.h
+coderange.o: $(hdrdir)/ruby/internal/intern/load.h
+coderange.o: $(hdrdir)/ruby/internal/intern/marshal.h
+coderange.o: $(hdrdir)/ruby/internal/intern/numeric.h
+coderange.o: $(hdrdir)/ruby/internal/intern/object.h
+coderange.o: $(hdrdir)/ruby/internal/intern/parse.h
+coderange.o: $(hdrdir)/ruby/internal/intern/proc.h
+coderange.o: $(hdrdir)/ruby/internal/intern/process.h
+coderange.o: $(hdrdir)/ruby/internal/intern/random.h
+coderange.o: $(hdrdir)/ruby/internal/intern/range.h
+coderange.o: $(hdrdir)/ruby/internal/intern/rational.h
+coderange.o: $(hdrdir)/ruby/internal/intern/re.h
+coderange.o: $(hdrdir)/ruby/internal/intern/ruby.h
+coderange.o: $(hdrdir)/ruby/internal/intern/select.h
+coderange.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+coderange.o: $(hdrdir)/ruby/internal/intern/signal.h
+coderange.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+coderange.o: $(hdrdir)/ruby/internal/intern/string.h
+coderange.o: $(hdrdir)/ruby/internal/intern/struct.h
+coderange.o: $(hdrdir)/ruby/internal/intern/thread.h
+coderange.o: $(hdrdir)/ruby/internal/intern/time.h
+coderange.o: $(hdrdir)/ruby/internal/intern/variable.h
+coderange.o: $(hdrdir)/ruby/internal/intern/vm.h
+coderange.o: $(hdrdir)/ruby/internal/interpreter.h
+coderange.o: $(hdrdir)/ruby/internal/iterator.h
+coderange.o: $(hdrdir)/ruby/internal/memory.h
+coderange.o: $(hdrdir)/ruby/internal/method.h
+coderange.o: $(hdrdir)/ruby/internal/module.h
+coderange.o: $(hdrdir)/ruby/internal/newobj.h
+coderange.o: $(hdrdir)/ruby/internal/rgengc.h
+coderange.o: $(hdrdir)/ruby/internal/scan_args.h
+coderange.o: $(hdrdir)/ruby/internal/special_consts.h
+coderange.o: $(hdrdir)/ruby/internal/static_assert.h
+coderange.o: $(hdrdir)/ruby/internal/stdalign.h
+coderange.o: $(hdrdir)/ruby/internal/stdbool.h
+coderange.o: $(hdrdir)/ruby/internal/symbol.h
+coderange.o: $(hdrdir)/ruby/internal/token_paste.h
+coderange.o: $(hdrdir)/ruby/internal/value.h
+coderange.o: $(hdrdir)/ruby/internal/value_type.h
+coderange.o: $(hdrdir)/ruby/internal/variable.h
+coderange.o: $(hdrdir)/ruby/internal/warning_push.h
+coderange.o: $(hdrdir)/ruby/internal/xmalloc.h
coderange.o: $(hdrdir)/ruby/missing.h
coderange.o: $(hdrdir)/ruby/onigmo.h
coderange.o: $(hdrdir)/ruby/oniguruma.h
@@ -31,9 +334,158 @@ cstr.o: $(arch_hdrdir)/ruby/config.h
cstr.o: $(hdrdir)/ruby.h
cstr.o: $(hdrdir)/ruby/assert.h
cstr.o: $(hdrdir)/ruby/backward.h
+cstr.o: $(hdrdir)/ruby/backward/2/assume.h
+cstr.o: $(hdrdir)/ruby/backward/2/attributes.h
+cstr.o: $(hdrdir)/ruby/backward/2/bool.h
+cstr.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+cstr.o: $(hdrdir)/ruby/backward/2/inttypes.h
+cstr.o: $(hdrdir)/ruby/backward/2/limits.h
+cstr.o: $(hdrdir)/ruby/backward/2/long_long.h
+cstr.o: $(hdrdir)/ruby/backward/2/stdalign.h
+cstr.o: $(hdrdir)/ruby/backward/2/stdarg.h
cstr.o: $(hdrdir)/ruby/defines.h
cstr.o: $(hdrdir)/ruby/encoding.h
cstr.o: $(hdrdir)/ruby/intern.h
+cstr.o: $(hdrdir)/ruby/internal/anyargs.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+cstr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+cstr.o: $(hdrdir)/ruby/internal/assume.h
+cstr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+cstr.o: $(hdrdir)/ruby/internal/attr/artificial.h
+cstr.o: $(hdrdir)/ruby/internal/attr/cold.h
+cstr.o: $(hdrdir)/ruby/internal/attr/const.h
+cstr.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+cstr.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+cstr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+cstr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+cstr.o: $(hdrdir)/ruby/internal/attr/error.h
+cstr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+cstr.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+cstr.o: $(hdrdir)/ruby/internal/attr/format.h
+cstr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+cstr.o: $(hdrdir)/ruby/internal/attr/noalias.h
+cstr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+cstr.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+cstr.o: $(hdrdir)/ruby/internal/attr/noinline.h
+cstr.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+cstr.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+cstr.o: $(hdrdir)/ruby/internal/attr/pure.h
+cstr.o: $(hdrdir)/ruby/internal/attr/restrict.h
+cstr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+cstr.o: $(hdrdir)/ruby/internal/attr/warning.h
+cstr.o: $(hdrdir)/ruby/internal/attr/weakref.h
+cstr.o: $(hdrdir)/ruby/internal/cast.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+cstr.o: $(hdrdir)/ruby/internal/compiler_since.h
+cstr.o: $(hdrdir)/ruby/internal/config.h
+cstr.o: $(hdrdir)/ruby/internal/constant_p.h
+cstr.o: $(hdrdir)/ruby/internal/core.h
+cstr.o: $(hdrdir)/ruby/internal/core/rarray.h
+cstr.o: $(hdrdir)/ruby/internal/core/rbasic.h
+cstr.o: $(hdrdir)/ruby/internal/core/rbignum.h
+cstr.o: $(hdrdir)/ruby/internal/core/rclass.h
+cstr.o: $(hdrdir)/ruby/internal/core/rdata.h
+cstr.o: $(hdrdir)/ruby/internal/core/rfile.h
+cstr.o: $(hdrdir)/ruby/internal/core/rhash.h
+cstr.o: $(hdrdir)/ruby/internal/core/robject.h
+cstr.o: $(hdrdir)/ruby/internal/core/rregexp.h
+cstr.o: $(hdrdir)/ruby/internal/core/rstring.h
+cstr.o: $(hdrdir)/ruby/internal/core/rstruct.h
+cstr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+cstr.o: $(hdrdir)/ruby/internal/ctype.h
+cstr.o: $(hdrdir)/ruby/internal/dllexport.h
+cstr.o: $(hdrdir)/ruby/internal/dosish.h
+cstr.o: $(hdrdir)/ruby/internal/error.h
+cstr.o: $(hdrdir)/ruby/internal/eval.h
+cstr.o: $(hdrdir)/ruby/internal/event.h
+cstr.o: $(hdrdir)/ruby/internal/fl_type.h
+cstr.o: $(hdrdir)/ruby/internal/gc.h
+cstr.o: $(hdrdir)/ruby/internal/glob.h
+cstr.o: $(hdrdir)/ruby/internal/globals.h
+cstr.o: $(hdrdir)/ruby/internal/has/attribute.h
+cstr.o: $(hdrdir)/ruby/internal/has/builtin.h
+cstr.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+cstr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+cstr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+cstr.o: $(hdrdir)/ruby/internal/has/extension.h
+cstr.o: $(hdrdir)/ruby/internal/has/feature.h
+cstr.o: $(hdrdir)/ruby/internal/has/warning.h
+cstr.o: $(hdrdir)/ruby/internal/intern/array.h
+cstr.o: $(hdrdir)/ruby/internal/intern/bignum.h
+cstr.o: $(hdrdir)/ruby/internal/intern/class.h
+cstr.o: $(hdrdir)/ruby/internal/intern/compar.h
+cstr.o: $(hdrdir)/ruby/internal/intern/complex.h
+cstr.o: $(hdrdir)/ruby/internal/intern/cont.h
+cstr.o: $(hdrdir)/ruby/internal/intern/dir.h
+cstr.o: $(hdrdir)/ruby/internal/intern/enum.h
+cstr.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+cstr.o: $(hdrdir)/ruby/internal/intern/error.h
+cstr.o: $(hdrdir)/ruby/internal/intern/eval.h
+cstr.o: $(hdrdir)/ruby/internal/intern/file.h
+cstr.o: $(hdrdir)/ruby/internal/intern/gc.h
+cstr.o: $(hdrdir)/ruby/internal/intern/hash.h
+cstr.o: $(hdrdir)/ruby/internal/intern/io.h
+cstr.o: $(hdrdir)/ruby/internal/intern/load.h
+cstr.o: $(hdrdir)/ruby/internal/intern/marshal.h
+cstr.o: $(hdrdir)/ruby/internal/intern/numeric.h
+cstr.o: $(hdrdir)/ruby/internal/intern/object.h
+cstr.o: $(hdrdir)/ruby/internal/intern/parse.h
+cstr.o: $(hdrdir)/ruby/internal/intern/proc.h
+cstr.o: $(hdrdir)/ruby/internal/intern/process.h
+cstr.o: $(hdrdir)/ruby/internal/intern/random.h
+cstr.o: $(hdrdir)/ruby/internal/intern/range.h
+cstr.o: $(hdrdir)/ruby/internal/intern/rational.h
+cstr.o: $(hdrdir)/ruby/internal/intern/re.h
+cstr.o: $(hdrdir)/ruby/internal/intern/ruby.h
+cstr.o: $(hdrdir)/ruby/internal/intern/select.h
+cstr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+cstr.o: $(hdrdir)/ruby/internal/intern/signal.h
+cstr.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+cstr.o: $(hdrdir)/ruby/internal/intern/string.h
+cstr.o: $(hdrdir)/ruby/internal/intern/struct.h
+cstr.o: $(hdrdir)/ruby/internal/intern/thread.h
+cstr.o: $(hdrdir)/ruby/internal/intern/time.h
+cstr.o: $(hdrdir)/ruby/internal/intern/variable.h
+cstr.o: $(hdrdir)/ruby/internal/intern/vm.h
+cstr.o: $(hdrdir)/ruby/internal/interpreter.h
+cstr.o: $(hdrdir)/ruby/internal/iterator.h
+cstr.o: $(hdrdir)/ruby/internal/memory.h
+cstr.o: $(hdrdir)/ruby/internal/method.h
+cstr.o: $(hdrdir)/ruby/internal/module.h
+cstr.o: $(hdrdir)/ruby/internal/newobj.h
+cstr.o: $(hdrdir)/ruby/internal/rgengc.h
+cstr.o: $(hdrdir)/ruby/internal/scan_args.h
+cstr.o: $(hdrdir)/ruby/internal/special_consts.h
+cstr.o: $(hdrdir)/ruby/internal/static_assert.h
+cstr.o: $(hdrdir)/ruby/internal/stdalign.h
+cstr.o: $(hdrdir)/ruby/internal/stdbool.h
+cstr.o: $(hdrdir)/ruby/internal/symbol.h
+cstr.o: $(hdrdir)/ruby/internal/token_paste.h
+cstr.o: $(hdrdir)/ruby/internal/value.h
+cstr.o: $(hdrdir)/ruby/internal/value_type.h
+cstr.o: $(hdrdir)/ruby/internal/variable.h
+cstr.o: $(hdrdir)/ruby/internal/warning_push.h
+cstr.o: $(hdrdir)/ruby/internal/xmalloc.h
cstr.o: $(hdrdir)/ruby/missing.h
cstr.o: $(hdrdir)/ruby/onigmo.h
cstr.o: $(hdrdir)/ruby/oniguruma.h
@@ -41,14 +493,166 @@ cstr.o: $(hdrdir)/ruby/ruby.h
cstr.o: $(hdrdir)/ruby/st.h
cstr.o: $(hdrdir)/ruby/subst.h
cstr.o: $(top_srcdir)/internal.h
+cstr.o: $(top_srcdir)/internal/compilers.h
+cstr.o: $(top_srcdir)/internal/error.h
+cstr.o: $(top_srcdir)/internal/string.h
cstr.o: cstr.c
ellipsize.o: $(RUBY_EXTCONF_H)
ellipsize.o: $(arch_hdrdir)/ruby/config.h
ellipsize.o: $(hdrdir)/ruby.h
ellipsize.o: $(hdrdir)/ruby/assert.h
ellipsize.o: $(hdrdir)/ruby/backward.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/assume.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/attributes.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/bool.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/limits.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/long_long.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ellipsize.o: $(hdrdir)/ruby/backward/2/stdarg.h
ellipsize.o: $(hdrdir)/ruby/defines.h
ellipsize.o: $(hdrdir)/ruby/intern.h
+ellipsize.o: $(hdrdir)/ruby/internal/anyargs.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ellipsize.o: $(hdrdir)/ruby/internal/assume.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/cold.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/const.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/error.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/format.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/pure.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/warning.h
+ellipsize.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ellipsize.o: $(hdrdir)/ruby/internal/cast.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ellipsize.o: $(hdrdir)/ruby/internal/compiler_since.h
+ellipsize.o: $(hdrdir)/ruby/internal/config.h
+ellipsize.o: $(hdrdir)/ruby/internal/constant_p.h
+ellipsize.o: $(hdrdir)/ruby/internal/core.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rarray.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rclass.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rdata.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rfile.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rhash.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/robject.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rstring.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ellipsize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ellipsize.o: $(hdrdir)/ruby/internal/ctype.h
+ellipsize.o: $(hdrdir)/ruby/internal/dllexport.h
+ellipsize.o: $(hdrdir)/ruby/internal/dosish.h
+ellipsize.o: $(hdrdir)/ruby/internal/error.h
+ellipsize.o: $(hdrdir)/ruby/internal/eval.h
+ellipsize.o: $(hdrdir)/ruby/internal/event.h
+ellipsize.o: $(hdrdir)/ruby/internal/fl_type.h
+ellipsize.o: $(hdrdir)/ruby/internal/gc.h
+ellipsize.o: $(hdrdir)/ruby/internal/glob.h
+ellipsize.o: $(hdrdir)/ruby/internal/globals.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/attribute.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/builtin.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/extension.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/feature.h
+ellipsize.o: $(hdrdir)/ruby/internal/has/warning.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/array.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/class.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/compar.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/complex.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/cont.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/dir.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/enum.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/error.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/eval.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/file.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/gc.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/hash.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/io.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/load.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/object.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/parse.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/proc.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/process.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/random.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/range.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/rational.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/re.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/select.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/signal.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/string.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/struct.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/thread.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/time.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/variable.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/vm.h
+ellipsize.o: $(hdrdir)/ruby/internal/interpreter.h
+ellipsize.o: $(hdrdir)/ruby/internal/iterator.h
+ellipsize.o: $(hdrdir)/ruby/internal/memory.h
+ellipsize.o: $(hdrdir)/ruby/internal/method.h
+ellipsize.o: $(hdrdir)/ruby/internal/module.h
+ellipsize.o: $(hdrdir)/ruby/internal/newobj.h
+ellipsize.o: $(hdrdir)/ruby/internal/rgengc.h
+ellipsize.o: $(hdrdir)/ruby/internal/scan_args.h
+ellipsize.o: $(hdrdir)/ruby/internal/special_consts.h
+ellipsize.o: $(hdrdir)/ruby/internal/static_assert.h
+ellipsize.o: $(hdrdir)/ruby/internal/stdalign.h
+ellipsize.o: $(hdrdir)/ruby/internal/stdbool.h
+ellipsize.o: $(hdrdir)/ruby/internal/symbol.h
+ellipsize.o: $(hdrdir)/ruby/internal/token_paste.h
+ellipsize.o: $(hdrdir)/ruby/internal/value.h
+ellipsize.o: $(hdrdir)/ruby/internal/value_type.h
+ellipsize.o: $(hdrdir)/ruby/internal/variable.h
+ellipsize.o: $(hdrdir)/ruby/internal/warning_push.h
+ellipsize.o: $(hdrdir)/ruby/internal/xmalloc.h
ellipsize.o: $(hdrdir)/ruby/missing.h
ellipsize.o: $(hdrdir)/ruby/ruby.h
ellipsize.o: $(hdrdir)/ruby/st.h
@@ -59,9 +663,158 @@ enc_associate.o: $(arch_hdrdir)/ruby/config.h
enc_associate.o: $(hdrdir)/ruby.h
enc_associate.o: $(hdrdir)/ruby/assert.h
enc_associate.o: $(hdrdir)/ruby/backward.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/assume.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/attributes.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/bool.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/limits.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/long_long.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enc_associate.o: $(hdrdir)/ruby/backward/2/stdarg.h
enc_associate.o: $(hdrdir)/ruby/defines.h
enc_associate.o: $(hdrdir)/ruby/encoding.h
enc_associate.o: $(hdrdir)/ruby/intern.h
+enc_associate.o: $(hdrdir)/ruby/internal/anyargs.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+enc_associate.o: $(hdrdir)/ruby/internal/assume.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/artificial.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/cold.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/const.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/error.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/format.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/noalias.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/noinline.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/pure.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/restrict.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/warning.h
+enc_associate.o: $(hdrdir)/ruby/internal/attr/weakref.h
+enc_associate.o: $(hdrdir)/ruby/internal/cast.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+enc_associate.o: $(hdrdir)/ruby/internal/compiler_since.h
+enc_associate.o: $(hdrdir)/ruby/internal/config.h
+enc_associate.o: $(hdrdir)/ruby/internal/constant_p.h
+enc_associate.o: $(hdrdir)/ruby/internal/core.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rarray.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rbasic.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rbignum.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rclass.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rdata.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rfile.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rhash.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/robject.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rregexp.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rstring.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rstruct.h
+enc_associate.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+enc_associate.o: $(hdrdir)/ruby/internal/ctype.h
+enc_associate.o: $(hdrdir)/ruby/internal/dllexport.h
+enc_associate.o: $(hdrdir)/ruby/internal/dosish.h
+enc_associate.o: $(hdrdir)/ruby/internal/error.h
+enc_associate.o: $(hdrdir)/ruby/internal/eval.h
+enc_associate.o: $(hdrdir)/ruby/internal/event.h
+enc_associate.o: $(hdrdir)/ruby/internal/fl_type.h
+enc_associate.o: $(hdrdir)/ruby/internal/gc.h
+enc_associate.o: $(hdrdir)/ruby/internal/glob.h
+enc_associate.o: $(hdrdir)/ruby/internal/globals.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/attribute.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/builtin.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/extension.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/feature.h
+enc_associate.o: $(hdrdir)/ruby/internal/has/warning.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/array.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/bignum.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/class.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/compar.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/complex.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/cont.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/dir.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/enum.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/error.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/eval.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/file.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/gc.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/hash.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/io.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/load.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/marshal.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/numeric.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/object.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/parse.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/proc.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/process.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/random.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/range.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/rational.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/re.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/ruby.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/select.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/signal.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/string.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/struct.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/thread.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/time.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/variable.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/vm.h
+enc_associate.o: $(hdrdir)/ruby/internal/interpreter.h
+enc_associate.o: $(hdrdir)/ruby/internal/iterator.h
+enc_associate.o: $(hdrdir)/ruby/internal/memory.h
+enc_associate.o: $(hdrdir)/ruby/internal/method.h
+enc_associate.o: $(hdrdir)/ruby/internal/module.h
+enc_associate.o: $(hdrdir)/ruby/internal/newobj.h
+enc_associate.o: $(hdrdir)/ruby/internal/rgengc.h
+enc_associate.o: $(hdrdir)/ruby/internal/scan_args.h
+enc_associate.o: $(hdrdir)/ruby/internal/special_consts.h
+enc_associate.o: $(hdrdir)/ruby/internal/static_assert.h
+enc_associate.o: $(hdrdir)/ruby/internal/stdalign.h
+enc_associate.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_associate.o: $(hdrdir)/ruby/internal/symbol.h
+enc_associate.o: $(hdrdir)/ruby/internal/token_paste.h
+enc_associate.o: $(hdrdir)/ruby/internal/value.h
+enc_associate.o: $(hdrdir)/ruby/internal/value_type.h
+enc_associate.o: $(hdrdir)/ruby/internal/variable.h
+enc_associate.o: $(hdrdir)/ruby/internal/warning_push.h
+enc_associate.o: $(hdrdir)/ruby/internal/xmalloc.h
enc_associate.o: $(hdrdir)/ruby/missing.h
enc_associate.o: $(hdrdir)/ruby/onigmo.h
enc_associate.o: $(hdrdir)/ruby/oniguruma.h
@@ -73,9 +826,158 @@ enc_str_buf_cat.o: $(RUBY_EXTCONF_H)
enc_str_buf_cat.o: $(arch_hdrdir)/ruby/config.h
enc_str_buf_cat.o: $(hdrdir)/ruby/assert.h
enc_str_buf_cat.o: $(hdrdir)/ruby/backward.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/assume.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/attributes.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/bool.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/inttypes.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/limits.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/long_long.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/stdalign.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/backward/2/stdarg.h
enc_str_buf_cat.o: $(hdrdir)/ruby/defines.h
enc_str_buf_cat.o: $(hdrdir)/ruby/encoding.h
enc_str_buf_cat.o: $(hdrdir)/ruby/intern.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/anyargs.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/assume.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/artificial.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/cold.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/const.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/error.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/format.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noalias.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noinline.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/pure.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/restrict.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/warning.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/attr/weakref.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/cast.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/compiler_since.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/config.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/constant_p.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rarray.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rbasic.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rbignum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rclass.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rdata.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rfile.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rhash.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/robject.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rregexp.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rstring.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rstruct.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/ctype.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/dllexport.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/dosish.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/error.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/eval.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/event.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/fl_type.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/gc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/glob.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/globals.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/attribute.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/builtin.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/extension.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/feature.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/has/warning.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/array.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/bignum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/class.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/compar.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/complex.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/cont.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/dir.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/enum.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/error.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/eval.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/file.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/gc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/hash.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/io.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/load.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/marshal.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/numeric.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/object.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/parse.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/proc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/process.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/random.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/range.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/rational.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/re.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/ruby.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/select.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/signal.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/string.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/struct.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/thread.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/time.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/variable.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/vm.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/interpreter.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/iterator.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/memory.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/method.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/module.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/newobj.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/rgengc.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/scan_args.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/special_consts.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/static_assert.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdalign.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdbool.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/symbol.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/token_paste.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value_type.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/variable.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/warning_push.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/xmalloc.h
enc_str_buf_cat.o: $(hdrdir)/ruby/missing.h
enc_str_buf_cat.o: $(hdrdir)/ruby/onigmo.h
enc_str_buf_cat.o: $(hdrdir)/ruby/oniguruma.h
@@ -88,9 +990,161 @@ fstring.o: $(arch_hdrdir)/ruby/config.h
fstring.o: $(hdrdir)/ruby.h
fstring.o: $(hdrdir)/ruby/assert.h
fstring.o: $(hdrdir)/ruby/backward.h
+fstring.o: $(hdrdir)/ruby/backward/2/assume.h
+fstring.o: $(hdrdir)/ruby/backward/2/attributes.h
+fstring.o: $(hdrdir)/ruby/backward/2/bool.h
+fstring.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+fstring.o: $(hdrdir)/ruby/backward/2/inttypes.h
+fstring.o: $(hdrdir)/ruby/backward/2/limits.h
+fstring.o: $(hdrdir)/ruby/backward/2/long_long.h
+fstring.o: $(hdrdir)/ruby/backward/2/stdalign.h
+fstring.o: $(hdrdir)/ruby/backward/2/stdarg.h
fstring.o: $(hdrdir)/ruby/defines.h
+fstring.o: $(hdrdir)/ruby/encoding.h
fstring.o: $(hdrdir)/ruby/intern.h
+fstring.o: $(hdrdir)/ruby/internal/anyargs.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+fstring.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+fstring.o: $(hdrdir)/ruby/internal/assume.h
+fstring.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+fstring.o: $(hdrdir)/ruby/internal/attr/artificial.h
+fstring.o: $(hdrdir)/ruby/internal/attr/cold.h
+fstring.o: $(hdrdir)/ruby/internal/attr/const.h
+fstring.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+fstring.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+fstring.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+fstring.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+fstring.o: $(hdrdir)/ruby/internal/attr/error.h
+fstring.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+fstring.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+fstring.o: $(hdrdir)/ruby/internal/attr/format.h
+fstring.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+fstring.o: $(hdrdir)/ruby/internal/attr/noalias.h
+fstring.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+fstring.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+fstring.o: $(hdrdir)/ruby/internal/attr/noinline.h
+fstring.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+fstring.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+fstring.o: $(hdrdir)/ruby/internal/attr/pure.h
+fstring.o: $(hdrdir)/ruby/internal/attr/restrict.h
+fstring.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+fstring.o: $(hdrdir)/ruby/internal/attr/warning.h
+fstring.o: $(hdrdir)/ruby/internal/attr/weakref.h
+fstring.o: $(hdrdir)/ruby/internal/cast.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+fstring.o: $(hdrdir)/ruby/internal/compiler_since.h
+fstring.o: $(hdrdir)/ruby/internal/config.h
+fstring.o: $(hdrdir)/ruby/internal/constant_p.h
+fstring.o: $(hdrdir)/ruby/internal/core.h
+fstring.o: $(hdrdir)/ruby/internal/core/rarray.h
+fstring.o: $(hdrdir)/ruby/internal/core/rbasic.h
+fstring.o: $(hdrdir)/ruby/internal/core/rbignum.h
+fstring.o: $(hdrdir)/ruby/internal/core/rclass.h
+fstring.o: $(hdrdir)/ruby/internal/core/rdata.h
+fstring.o: $(hdrdir)/ruby/internal/core/rfile.h
+fstring.o: $(hdrdir)/ruby/internal/core/rhash.h
+fstring.o: $(hdrdir)/ruby/internal/core/robject.h
+fstring.o: $(hdrdir)/ruby/internal/core/rregexp.h
+fstring.o: $(hdrdir)/ruby/internal/core/rstring.h
+fstring.o: $(hdrdir)/ruby/internal/core/rstruct.h
+fstring.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+fstring.o: $(hdrdir)/ruby/internal/ctype.h
+fstring.o: $(hdrdir)/ruby/internal/dllexport.h
+fstring.o: $(hdrdir)/ruby/internal/dosish.h
+fstring.o: $(hdrdir)/ruby/internal/error.h
+fstring.o: $(hdrdir)/ruby/internal/eval.h
+fstring.o: $(hdrdir)/ruby/internal/event.h
+fstring.o: $(hdrdir)/ruby/internal/fl_type.h
+fstring.o: $(hdrdir)/ruby/internal/gc.h
+fstring.o: $(hdrdir)/ruby/internal/glob.h
+fstring.o: $(hdrdir)/ruby/internal/globals.h
+fstring.o: $(hdrdir)/ruby/internal/has/attribute.h
+fstring.o: $(hdrdir)/ruby/internal/has/builtin.h
+fstring.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+fstring.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+fstring.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+fstring.o: $(hdrdir)/ruby/internal/has/extension.h
+fstring.o: $(hdrdir)/ruby/internal/has/feature.h
+fstring.o: $(hdrdir)/ruby/internal/has/warning.h
+fstring.o: $(hdrdir)/ruby/internal/intern/array.h
+fstring.o: $(hdrdir)/ruby/internal/intern/bignum.h
+fstring.o: $(hdrdir)/ruby/internal/intern/class.h
+fstring.o: $(hdrdir)/ruby/internal/intern/compar.h
+fstring.o: $(hdrdir)/ruby/internal/intern/complex.h
+fstring.o: $(hdrdir)/ruby/internal/intern/cont.h
+fstring.o: $(hdrdir)/ruby/internal/intern/dir.h
+fstring.o: $(hdrdir)/ruby/internal/intern/enum.h
+fstring.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+fstring.o: $(hdrdir)/ruby/internal/intern/error.h
+fstring.o: $(hdrdir)/ruby/internal/intern/eval.h
+fstring.o: $(hdrdir)/ruby/internal/intern/file.h
+fstring.o: $(hdrdir)/ruby/internal/intern/gc.h
+fstring.o: $(hdrdir)/ruby/internal/intern/hash.h
+fstring.o: $(hdrdir)/ruby/internal/intern/io.h
+fstring.o: $(hdrdir)/ruby/internal/intern/load.h
+fstring.o: $(hdrdir)/ruby/internal/intern/marshal.h
+fstring.o: $(hdrdir)/ruby/internal/intern/numeric.h
+fstring.o: $(hdrdir)/ruby/internal/intern/object.h
+fstring.o: $(hdrdir)/ruby/internal/intern/parse.h
+fstring.o: $(hdrdir)/ruby/internal/intern/proc.h
+fstring.o: $(hdrdir)/ruby/internal/intern/process.h
+fstring.o: $(hdrdir)/ruby/internal/intern/random.h
+fstring.o: $(hdrdir)/ruby/internal/intern/range.h
+fstring.o: $(hdrdir)/ruby/internal/intern/rational.h
+fstring.o: $(hdrdir)/ruby/internal/intern/re.h
+fstring.o: $(hdrdir)/ruby/internal/intern/ruby.h
+fstring.o: $(hdrdir)/ruby/internal/intern/select.h
+fstring.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fstring.o: $(hdrdir)/ruby/internal/intern/signal.h
+fstring.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+fstring.o: $(hdrdir)/ruby/internal/intern/string.h
+fstring.o: $(hdrdir)/ruby/internal/intern/struct.h
+fstring.o: $(hdrdir)/ruby/internal/intern/thread.h
+fstring.o: $(hdrdir)/ruby/internal/intern/time.h
+fstring.o: $(hdrdir)/ruby/internal/intern/variable.h
+fstring.o: $(hdrdir)/ruby/internal/intern/vm.h
+fstring.o: $(hdrdir)/ruby/internal/interpreter.h
+fstring.o: $(hdrdir)/ruby/internal/iterator.h
+fstring.o: $(hdrdir)/ruby/internal/memory.h
+fstring.o: $(hdrdir)/ruby/internal/method.h
+fstring.o: $(hdrdir)/ruby/internal/module.h
+fstring.o: $(hdrdir)/ruby/internal/newobj.h
+fstring.o: $(hdrdir)/ruby/internal/rgengc.h
+fstring.o: $(hdrdir)/ruby/internal/scan_args.h
+fstring.o: $(hdrdir)/ruby/internal/special_consts.h
+fstring.o: $(hdrdir)/ruby/internal/static_assert.h
+fstring.o: $(hdrdir)/ruby/internal/stdalign.h
+fstring.o: $(hdrdir)/ruby/internal/stdbool.h
+fstring.o: $(hdrdir)/ruby/internal/symbol.h
+fstring.o: $(hdrdir)/ruby/internal/token_paste.h
+fstring.o: $(hdrdir)/ruby/internal/value.h
+fstring.o: $(hdrdir)/ruby/internal/value_type.h
+fstring.o: $(hdrdir)/ruby/internal/variable.h
+fstring.o: $(hdrdir)/ruby/internal/warning_push.h
+fstring.o: $(hdrdir)/ruby/internal/xmalloc.h
fstring.o: $(hdrdir)/ruby/missing.h
+fstring.o: $(hdrdir)/ruby/onigmo.h
+fstring.o: $(hdrdir)/ruby/oniguruma.h
fstring.o: $(hdrdir)/ruby/ruby.h
fstring.o: $(hdrdir)/ruby/st.h
fstring.o: $(hdrdir)/ruby/subst.h
@@ -100,8 +1154,157 @@ init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
init.o: $(hdrdir)/ruby/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
init.o: $(hdrdir)/ruby/missing.h
init.o: $(hdrdir)/ruby/ruby.h
init.o: $(hdrdir)/ruby/st.h
@@ -112,8 +1315,157 @@ modify.o: $(arch_hdrdir)/ruby/config.h
modify.o: $(hdrdir)/ruby.h
modify.o: $(hdrdir)/ruby/assert.h
modify.o: $(hdrdir)/ruby/backward.h
+modify.o: $(hdrdir)/ruby/backward/2/assume.h
+modify.o: $(hdrdir)/ruby/backward/2/attributes.h
+modify.o: $(hdrdir)/ruby/backward/2/bool.h
+modify.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+modify.o: $(hdrdir)/ruby/backward/2/inttypes.h
+modify.o: $(hdrdir)/ruby/backward/2/limits.h
+modify.o: $(hdrdir)/ruby/backward/2/long_long.h
+modify.o: $(hdrdir)/ruby/backward/2/stdalign.h
+modify.o: $(hdrdir)/ruby/backward/2/stdarg.h
modify.o: $(hdrdir)/ruby/defines.h
modify.o: $(hdrdir)/ruby/intern.h
+modify.o: $(hdrdir)/ruby/internal/anyargs.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+modify.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+modify.o: $(hdrdir)/ruby/internal/assume.h
+modify.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+modify.o: $(hdrdir)/ruby/internal/attr/artificial.h
+modify.o: $(hdrdir)/ruby/internal/attr/cold.h
+modify.o: $(hdrdir)/ruby/internal/attr/const.h
+modify.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+modify.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+modify.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+modify.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+modify.o: $(hdrdir)/ruby/internal/attr/error.h
+modify.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+modify.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+modify.o: $(hdrdir)/ruby/internal/attr/format.h
+modify.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+modify.o: $(hdrdir)/ruby/internal/attr/noalias.h
+modify.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+modify.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+modify.o: $(hdrdir)/ruby/internal/attr/noinline.h
+modify.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+modify.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+modify.o: $(hdrdir)/ruby/internal/attr/pure.h
+modify.o: $(hdrdir)/ruby/internal/attr/restrict.h
+modify.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+modify.o: $(hdrdir)/ruby/internal/attr/warning.h
+modify.o: $(hdrdir)/ruby/internal/attr/weakref.h
+modify.o: $(hdrdir)/ruby/internal/cast.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+modify.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+modify.o: $(hdrdir)/ruby/internal/compiler_since.h
+modify.o: $(hdrdir)/ruby/internal/config.h
+modify.o: $(hdrdir)/ruby/internal/constant_p.h
+modify.o: $(hdrdir)/ruby/internal/core.h
+modify.o: $(hdrdir)/ruby/internal/core/rarray.h
+modify.o: $(hdrdir)/ruby/internal/core/rbasic.h
+modify.o: $(hdrdir)/ruby/internal/core/rbignum.h
+modify.o: $(hdrdir)/ruby/internal/core/rclass.h
+modify.o: $(hdrdir)/ruby/internal/core/rdata.h
+modify.o: $(hdrdir)/ruby/internal/core/rfile.h
+modify.o: $(hdrdir)/ruby/internal/core/rhash.h
+modify.o: $(hdrdir)/ruby/internal/core/robject.h
+modify.o: $(hdrdir)/ruby/internal/core/rregexp.h
+modify.o: $(hdrdir)/ruby/internal/core/rstring.h
+modify.o: $(hdrdir)/ruby/internal/core/rstruct.h
+modify.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+modify.o: $(hdrdir)/ruby/internal/ctype.h
+modify.o: $(hdrdir)/ruby/internal/dllexport.h
+modify.o: $(hdrdir)/ruby/internal/dosish.h
+modify.o: $(hdrdir)/ruby/internal/error.h
+modify.o: $(hdrdir)/ruby/internal/eval.h
+modify.o: $(hdrdir)/ruby/internal/event.h
+modify.o: $(hdrdir)/ruby/internal/fl_type.h
+modify.o: $(hdrdir)/ruby/internal/gc.h
+modify.o: $(hdrdir)/ruby/internal/glob.h
+modify.o: $(hdrdir)/ruby/internal/globals.h
+modify.o: $(hdrdir)/ruby/internal/has/attribute.h
+modify.o: $(hdrdir)/ruby/internal/has/builtin.h
+modify.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+modify.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+modify.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+modify.o: $(hdrdir)/ruby/internal/has/extension.h
+modify.o: $(hdrdir)/ruby/internal/has/feature.h
+modify.o: $(hdrdir)/ruby/internal/has/warning.h
+modify.o: $(hdrdir)/ruby/internal/intern/array.h
+modify.o: $(hdrdir)/ruby/internal/intern/bignum.h
+modify.o: $(hdrdir)/ruby/internal/intern/class.h
+modify.o: $(hdrdir)/ruby/internal/intern/compar.h
+modify.o: $(hdrdir)/ruby/internal/intern/complex.h
+modify.o: $(hdrdir)/ruby/internal/intern/cont.h
+modify.o: $(hdrdir)/ruby/internal/intern/dir.h
+modify.o: $(hdrdir)/ruby/internal/intern/enum.h
+modify.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+modify.o: $(hdrdir)/ruby/internal/intern/error.h
+modify.o: $(hdrdir)/ruby/internal/intern/eval.h
+modify.o: $(hdrdir)/ruby/internal/intern/file.h
+modify.o: $(hdrdir)/ruby/internal/intern/gc.h
+modify.o: $(hdrdir)/ruby/internal/intern/hash.h
+modify.o: $(hdrdir)/ruby/internal/intern/io.h
+modify.o: $(hdrdir)/ruby/internal/intern/load.h
+modify.o: $(hdrdir)/ruby/internal/intern/marshal.h
+modify.o: $(hdrdir)/ruby/internal/intern/numeric.h
+modify.o: $(hdrdir)/ruby/internal/intern/object.h
+modify.o: $(hdrdir)/ruby/internal/intern/parse.h
+modify.o: $(hdrdir)/ruby/internal/intern/proc.h
+modify.o: $(hdrdir)/ruby/internal/intern/process.h
+modify.o: $(hdrdir)/ruby/internal/intern/random.h
+modify.o: $(hdrdir)/ruby/internal/intern/range.h
+modify.o: $(hdrdir)/ruby/internal/intern/rational.h
+modify.o: $(hdrdir)/ruby/internal/intern/re.h
+modify.o: $(hdrdir)/ruby/internal/intern/ruby.h
+modify.o: $(hdrdir)/ruby/internal/intern/select.h
+modify.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+modify.o: $(hdrdir)/ruby/internal/intern/signal.h
+modify.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+modify.o: $(hdrdir)/ruby/internal/intern/string.h
+modify.o: $(hdrdir)/ruby/internal/intern/struct.h
+modify.o: $(hdrdir)/ruby/internal/intern/thread.h
+modify.o: $(hdrdir)/ruby/internal/intern/time.h
+modify.o: $(hdrdir)/ruby/internal/intern/variable.h
+modify.o: $(hdrdir)/ruby/internal/intern/vm.h
+modify.o: $(hdrdir)/ruby/internal/interpreter.h
+modify.o: $(hdrdir)/ruby/internal/iterator.h
+modify.o: $(hdrdir)/ruby/internal/memory.h
+modify.o: $(hdrdir)/ruby/internal/method.h
+modify.o: $(hdrdir)/ruby/internal/module.h
+modify.o: $(hdrdir)/ruby/internal/newobj.h
+modify.o: $(hdrdir)/ruby/internal/rgengc.h
+modify.o: $(hdrdir)/ruby/internal/scan_args.h
+modify.o: $(hdrdir)/ruby/internal/special_consts.h
+modify.o: $(hdrdir)/ruby/internal/static_assert.h
+modify.o: $(hdrdir)/ruby/internal/stdalign.h
+modify.o: $(hdrdir)/ruby/internal/stdbool.h
+modify.o: $(hdrdir)/ruby/internal/symbol.h
+modify.o: $(hdrdir)/ruby/internal/token_paste.h
+modify.o: $(hdrdir)/ruby/internal/value.h
+modify.o: $(hdrdir)/ruby/internal/value_type.h
+modify.o: $(hdrdir)/ruby/internal/variable.h
+modify.o: $(hdrdir)/ruby/internal/warning_push.h
+modify.o: $(hdrdir)/ruby/internal/xmalloc.h
modify.o: $(hdrdir)/ruby/missing.h
modify.o: $(hdrdir)/ruby/ruby.h
modify.o: $(hdrdir)/ruby/st.h
@@ -124,9 +1476,158 @@ new.o: $(arch_hdrdir)/ruby/config.h
new.o: $(hdrdir)/ruby.h
new.o: $(hdrdir)/ruby/assert.h
new.o: $(hdrdir)/ruby/backward.h
+new.o: $(hdrdir)/ruby/backward/2/assume.h
+new.o: $(hdrdir)/ruby/backward/2/attributes.h
+new.o: $(hdrdir)/ruby/backward/2/bool.h
+new.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+new.o: $(hdrdir)/ruby/backward/2/inttypes.h
+new.o: $(hdrdir)/ruby/backward/2/limits.h
+new.o: $(hdrdir)/ruby/backward/2/long_long.h
+new.o: $(hdrdir)/ruby/backward/2/stdalign.h
+new.o: $(hdrdir)/ruby/backward/2/stdarg.h
new.o: $(hdrdir)/ruby/defines.h
new.o: $(hdrdir)/ruby/encoding.h
new.o: $(hdrdir)/ruby/intern.h
+new.o: $(hdrdir)/ruby/internal/anyargs.h
+new.o: $(hdrdir)/ruby/internal/arithmetic.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+new.o: $(hdrdir)/ruby/internal/assume.h
+new.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+new.o: $(hdrdir)/ruby/internal/attr/artificial.h
+new.o: $(hdrdir)/ruby/internal/attr/cold.h
+new.o: $(hdrdir)/ruby/internal/attr/const.h
+new.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+new.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+new.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+new.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+new.o: $(hdrdir)/ruby/internal/attr/error.h
+new.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+new.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+new.o: $(hdrdir)/ruby/internal/attr/format.h
+new.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+new.o: $(hdrdir)/ruby/internal/attr/noalias.h
+new.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+new.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+new.o: $(hdrdir)/ruby/internal/attr/noinline.h
+new.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+new.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+new.o: $(hdrdir)/ruby/internal/attr/pure.h
+new.o: $(hdrdir)/ruby/internal/attr/restrict.h
+new.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+new.o: $(hdrdir)/ruby/internal/attr/warning.h
+new.o: $(hdrdir)/ruby/internal/attr/weakref.h
+new.o: $(hdrdir)/ruby/internal/cast.h
+new.o: $(hdrdir)/ruby/internal/compiler_is.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+new.o: $(hdrdir)/ruby/internal/compiler_since.h
+new.o: $(hdrdir)/ruby/internal/config.h
+new.o: $(hdrdir)/ruby/internal/constant_p.h
+new.o: $(hdrdir)/ruby/internal/core.h
+new.o: $(hdrdir)/ruby/internal/core/rarray.h
+new.o: $(hdrdir)/ruby/internal/core/rbasic.h
+new.o: $(hdrdir)/ruby/internal/core/rbignum.h
+new.o: $(hdrdir)/ruby/internal/core/rclass.h
+new.o: $(hdrdir)/ruby/internal/core/rdata.h
+new.o: $(hdrdir)/ruby/internal/core/rfile.h
+new.o: $(hdrdir)/ruby/internal/core/rhash.h
+new.o: $(hdrdir)/ruby/internal/core/robject.h
+new.o: $(hdrdir)/ruby/internal/core/rregexp.h
+new.o: $(hdrdir)/ruby/internal/core/rstring.h
+new.o: $(hdrdir)/ruby/internal/core/rstruct.h
+new.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+new.o: $(hdrdir)/ruby/internal/ctype.h
+new.o: $(hdrdir)/ruby/internal/dllexport.h
+new.o: $(hdrdir)/ruby/internal/dosish.h
+new.o: $(hdrdir)/ruby/internal/error.h
+new.o: $(hdrdir)/ruby/internal/eval.h
+new.o: $(hdrdir)/ruby/internal/event.h
+new.o: $(hdrdir)/ruby/internal/fl_type.h
+new.o: $(hdrdir)/ruby/internal/gc.h
+new.o: $(hdrdir)/ruby/internal/glob.h
+new.o: $(hdrdir)/ruby/internal/globals.h
+new.o: $(hdrdir)/ruby/internal/has/attribute.h
+new.o: $(hdrdir)/ruby/internal/has/builtin.h
+new.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/extension.h
+new.o: $(hdrdir)/ruby/internal/has/feature.h
+new.o: $(hdrdir)/ruby/internal/has/warning.h
+new.o: $(hdrdir)/ruby/internal/intern/array.h
+new.o: $(hdrdir)/ruby/internal/intern/bignum.h
+new.o: $(hdrdir)/ruby/internal/intern/class.h
+new.o: $(hdrdir)/ruby/internal/intern/compar.h
+new.o: $(hdrdir)/ruby/internal/intern/complex.h
+new.o: $(hdrdir)/ruby/internal/intern/cont.h
+new.o: $(hdrdir)/ruby/internal/intern/dir.h
+new.o: $(hdrdir)/ruby/internal/intern/enum.h
+new.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+new.o: $(hdrdir)/ruby/internal/intern/error.h
+new.o: $(hdrdir)/ruby/internal/intern/eval.h
+new.o: $(hdrdir)/ruby/internal/intern/file.h
+new.o: $(hdrdir)/ruby/internal/intern/gc.h
+new.o: $(hdrdir)/ruby/internal/intern/hash.h
+new.o: $(hdrdir)/ruby/internal/intern/io.h
+new.o: $(hdrdir)/ruby/internal/intern/load.h
+new.o: $(hdrdir)/ruby/internal/intern/marshal.h
+new.o: $(hdrdir)/ruby/internal/intern/numeric.h
+new.o: $(hdrdir)/ruby/internal/intern/object.h
+new.o: $(hdrdir)/ruby/internal/intern/parse.h
+new.o: $(hdrdir)/ruby/internal/intern/proc.h
+new.o: $(hdrdir)/ruby/internal/intern/process.h
+new.o: $(hdrdir)/ruby/internal/intern/random.h
+new.o: $(hdrdir)/ruby/internal/intern/range.h
+new.o: $(hdrdir)/ruby/internal/intern/rational.h
+new.o: $(hdrdir)/ruby/internal/intern/re.h
+new.o: $(hdrdir)/ruby/internal/intern/ruby.h
+new.o: $(hdrdir)/ruby/internal/intern/select.h
+new.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+new.o: $(hdrdir)/ruby/internal/intern/signal.h
+new.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+new.o: $(hdrdir)/ruby/internal/intern/string.h
+new.o: $(hdrdir)/ruby/internal/intern/struct.h
+new.o: $(hdrdir)/ruby/internal/intern/thread.h
+new.o: $(hdrdir)/ruby/internal/intern/time.h
+new.o: $(hdrdir)/ruby/internal/intern/variable.h
+new.o: $(hdrdir)/ruby/internal/intern/vm.h
+new.o: $(hdrdir)/ruby/internal/interpreter.h
+new.o: $(hdrdir)/ruby/internal/iterator.h
+new.o: $(hdrdir)/ruby/internal/memory.h
+new.o: $(hdrdir)/ruby/internal/method.h
+new.o: $(hdrdir)/ruby/internal/module.h
+new.o: $(hdrdir)/ruby/internal/newobj.h
+new.o: $(hdrdir)/ruby/internal/rgengc.h
+new.o: $(hdrdir)/ruby/internal/scan_args.h
+new.o: $(hdrdir)/ruby/internal/special_consts.h
+new.o: $(hdrdir)/ruby/internal/static_assert.h
+new.o: $(hdrdir)/ruby/internal/stdalign.h
+new.o: $(hdrdir)/ruby/internal/stdbool.h
+new.o: $(hdrdir)/ruby/internal/symbol.h
+new.o: $(hdrdir)/ruby/internal/token_paste.h
+new.o: $(hdrdir)/ruby/internal/value.h
+new.o: $(hdrdir)/ruby/internal/value_type.h
+new.o: $(hdrdir)/ruby/internal/variable.h
+new.o: $(hdrdir)/ruby/internal/warning_push.h
+new.o: $(hdrdir)/ruby/internal/xmalloc.h
new.o: $(hdrdir)/ruby/missing.h
new.o: $(hdrdir)/ruby/onigmo.h
new.o: $(hdrdir)/ruby/oniguruma.h
@@ -139,8 +1640,157 @@ nofree.o: $(arch_hdrdir)/ruby/config.h
nofree.o: $(hdrdir)/ruby.h
nofree.o: $(hdrdir)/ruby/assert.h
nofree.o: $(hdrdir)/ruby/backward.h
+nofree.o: $(hdrdir)/ruby/backward/2/assume.h
+nofree.o: $(hdrdir)/ruby/backward/2/attributes.h
+nofree.o: $(hdrdir)/ruby/backward/2/bool.h
+nofree.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+nofree.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nofree.o: $(hdrdir)/ruby/backward/2/limits.h
+nofree.o: $(hdrdir)/ruby/backward/2/long_long.h
+nofree.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nofree.o: $(hdrdir)/ruby/backward/2/stdarg.h
nofree.o: $(hdrdir)/ruby/defines.h
nofree.o: $(hdrdir)/ruby/intern.h
+nofree.o: $(hdrdir)/ruby/internal/anyargs.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+nofree.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+nofree.o: $(hdrdir)/ruby/internal/assume.h
+nofree.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+nofree.o: $(hdrdir)/ruby/internal/attr/artificial.h
+nofree.o: $(hdrdir)/ruby/internal/attr/cold.h
+nofree.o: $(hdrdir)/ruby/internal/attr/const.h
+nofree.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+nofree.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+nofree.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+nofree.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+nofree.o: $(hdrdir)/ruby/internal/attr/error.h
+nofree.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+nofree.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+nofree.o: $(hdrdir)/ruby/internal/attr/format.h
+nofree.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+nofree.o: $(hdrdir)/ruby/internal/attr/noalias.h
+nofree.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+nofree.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+nofree.o: $(hdrdir)/ruby/internal/attr/noinline.h
+nofree.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+nofree.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+nofree.o: $(hdrdir)/ruby/internal/attr/pure.h
+nofree.o: $(hdrdir)/ruby/internal/attr/restrict.h
+nofree.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+nofree.o: $(hdrdir)/ruby/internal/attr/warning.h
+nofree.o: $(hdrdir)/ruby/internal/attr/weakref.h
+nofree.o: $(hdrdir)/ruby/internal/cast.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+nofree.o: $(hdrdir)/ruby/internal/compiler_since.h
+nofree.o: $(hdrdir)/ruby/internal/config.h
+nofree.o: $(hdrdir)/ruby/internal/constant_p.h
+nofree.o: $(hdrdir)/ruby/internal/core.h
+nofree.o: $(hdrdir)/ruby/internal/core/rarray.h
+nofree.o: $(hdrdir)/ruby/internal/core/rbasic.h
+nofree.o: $(hdrdir)/ruby/internal/core/rbignum.h
+nofree.o: $(hdrdir)/ruby/internal/core/rclass.h
+nofree.o: $(hdrdir)/ruby/internal/core/rdata.h
+nofree.o: $(hdrdir)/ruby/internal/core/rfile.h
+nofree.o: $(hdrdir)/ruby/internal/core/rhash.h
+nofree.o: $(hdrdir)/ruby/internal/core/robject.h
+nofree.o: $(hdrdir)/ruby/internal/core/rregexp.h
+nofree.o: $(hdrdir)/ruby/internal/core/rstring.h
+nofree.o: $(hdrdir)/ruby/internal/core/rstruct.h
+nofree.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+nofree.o: $(hdrdir)/ruby/internal/ctype.h
+nofree.o: $(hdrdir)/ruby/internal/dllexport.h
+nofree.o: $(hdrdir)/ruby/internal/dosish.h
+nofree.o: $(hdrdir)/ruby/internal/error.h
+nofree.o: $(hdrdir)/ruby/internal/eval.h
+nofree.o: $(hdrdir)/ruby/internal/event.h
+nofree.o: $(hdrdir)/ruby/internal/fl_type.h
+nofree.o: $(hdrdir)/ruby/internal/gc.h
+nofree.o: $(hdrdir)/ruby/internal/glob.h
+nofree.o: $(hdrdir)/ruby/internal/globals.h
+nofree.o: $(hdrdir)/ruby/internal/has/attribute.h
+nofree.o: $(hdrdir)/ruby/internal/has/builtin.h
+nofree.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+nofree.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+nofree.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+nofree.o: $(hdrdir)/ruby/internal/has/extension.h
+nofree.o: $(hdrdir)/ruby/internal/has/feature.h
+nofree.o: $(hdrdir)/ruby/internal/has/warning.h
+nofree.o: $(hdrdir)/ruby/internal/intern/array.h
+nofree.o: $(hdrdir)/ruby/internal/intern/bignum.h
+nofree.o: $(hdrdir)/ruby/internal/intern/class.h
+nofree.o: $(hdrdir)/ruby/internal/intern/compar.h
+nofree.o: $(hdrdir)/ruby/internal/intern/complex.h
+nofree.o: $(hdrdir)/ruby/internal/intern/cont.h
+nofree.o: $(hdrdir)/ruby/internal/intern/dir.h
+nofree.o: $(hdrdir)/ruby/internal/intern/enum.h
+nofree.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+nofree.o: $(hdrdir)/ruby/internal/intern/error.h
+nofree.o: $(hdrdir)/ruby/internal/intern/eval.h
+nofree.o: $(hdrdir)/ruby/internal/intern/file.h
+nofree.o: $(hdrdir)/ruby/internal/intern/gc.h
+nofree.o: $(hdrdir)/ruby/internal/intern/hash.h
+nofree.o: $(hdrdir)/ruby/internal/intern/io.h
+nofree.o: $(hdrdir)/ruby/internal/intern/load.h
+nofree.o: $(hdrdir)/ruby/internal/intern/marshal.h
+nofree.o: $(hdrdir)/ruby/internal/intern/numeric.h
+nofree.o: $(hdrdir)/ruby/internal/intern/object.h
+nofree.o: $(hdrdir)/ruby/internal/intern/parse.h
+nofree.o: $(hdrdir)/ruby/internal/intern/proc.h
+nofree.o: $(hdrdir)/ruby/internal/intern/process.h
+nofree.o: $(hdrdir)/ruby/internal/intern/random.h
+nofree.o: $(hdrdir)/ruby/internal/intern/range.h
+nofree.o: $(hdrdir)/ruby/internal/intern/rational.h
+nofree.o: $(hdrdir)/ruby/internal/intern/re.h
+nofree.o: $(hdrdir)/ruby/internal/intern/ruby.h
+nofree.o: $(hdrdir)/ruby/internal/intern/select.h
+nofree.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nofree.o: $(hdrdir)/ruby/internal/intern/signal.h
+nofree.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+nofree.o: $(hdrdir)/ruby/internal/intern/string.h
+nofree.o: $(hdrdir)/ruby/internal/intern/struct.h
+nofree.o: $(hdrdir)/ruby/internal/intern/thread.h
+nofree.o: $(hdrdir)/ruby/internal/intern/time.h
+nofree.o: $(hdrdir)/ruby/internal/intern/variable.h
+nofree.o: $(hdrdir)/ruby/internal/intern/vm.h
+nofree.o: $(hdrdir)/ruby/internal/interpreter.h
+nofree.o: $(hdrdir)/ruby/internal/iterator.h
+nofree.o: $(hdrdir)/ruby/internal/memory.h
+nofree.o: $(hdrdir)/ruby/internal/method.h
+nofree.o: $(hdrdir)/ruby/internal/module.h
+nofree.o: $(hdrdir)/ruby/internal/newobj.h
+nofree.o: $(hdrdir)/ruby/internal/rgengc.h
+nofree.o: $(hdrdir)/ruby/internal/scan_args.h
+nofree.o: $(hdrdir)/ruby/internal/special_consts.h
+nofree.o: $(hdrdir)/ruby/internal/static_assert.h
+nofree.o: $(hdrdir)/ruby/internal/stdalign.h
+nofree.o: $(hdrdir)/ruby/internal/stdbool.h
+nofree.o: $(hdrdir)/ruby/internal/symbol.h
+nofree.o: $(hdrdir)/ruby/internal/token_paste.h
+nofree.o: $(hdrdir)/ruby/internal/value.h
+nofree.o: $(hdrdir)/ruby/internal/value_type.h
+nofree.o: $(hdrdir)/ruby/internal/variable.h
+nofree.o: $(hdrdir)/ruby/internal/warning_push.h
+nofree.o: $(hdrdir)/ruby/internal/xmalloc.h
nofree.o: $(hdrdir)/ruby/missing.h
nofree.o: $(hdrdir)/ruby/ruby.h
nofree.o: $(hdrdir)/ruby/st.h
@@ -151,22 +1801,324 @@ normalize.o: $(arch_hdrdir)/ruby/config.h
normalize.o: $(hdrdir)/ruby.h
normalize.o: $(hdrdir)/ruby/assert.h
normalize.o: $(hdrdir)/ruby/backward.h
+normalize.o: $(hdrdir)/ruby/backward/2/assume.h
+normalize.o: $(hdrdir)/ruby/backward/2/attributes.h
+normalize.o: $(hdrdir)/ruby/backward/2/bool.h
+normalize.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+normalize.o: $(hdrdir)/ruby/backward/2/inttypes.h
+normalize.o: $(hdrdir)/ruby/backward/2/limits.h
+normalize.o: $(hdrdir)/ruby/backward/2/long_long.h
+normalize.o: $(hdrdir)/ruby/backward/2/stdalign.h
+normalize.o: $(hdrdir)/ruby/backward/2/stdarg.h
normalize.o: $(hdrdir)/ruby/defines.h
+normalize.o: $(hdrdir)/ruby/encoding.h
normalize.o: $(hdrdir)/ruby/intern.h
+normalize.o: $(hdrdir)/ruby/internal/anyargs.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+normalize.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+normalize.o: $(hdrdir)/ruby/internal/assume.h
+normalize.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+normalize.o: $(hdrdir)/ruby/internal/attr/artificial.h
+normalize.o: $(hdrdir)/ruby/internal/attr/cold.h
+normalize.o: $(hdrdir)/ruby/internal/attr/const.h
+normalize.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+normalize.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+normalize.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+normalize.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+normalize.o: $(hdrdir)/ruby/internal/attr/error.h
+normalize.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+normalize.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+normalize.o: $(hdrdir)/ruby/internal/attr/format.h
+normalize.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+normalize.o: $(hdrdir)/ruby/internal/attr/noalias.h
+normalize.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+normalize.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+normalize.o: $(hdrdir)/ruby/internal/attr/noinline.h
+normalize.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+normalize.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+normalize.o: $(hdrdir)/ruby/internal/attr/pure.h
+normalize.o: $(hdrdir)/ruby/internal/attr/restrict.h
+normalize.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+normalize.o: $(hdrdir)/ruby/internal/attr/warning.h
+normalize.o: $(hdrdir)/ruby/internal/attr/weakref.h
+normalize.o: $(hdrdir)/ruby/internal/cast.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+normalize.o: $(hdrdir)/ruby/internal/compiler_since.h
+normalize.o: $(hdrdir)/ruby/internal/config.h
+normalize.o: $(hdrdir)/ruby/internal/constant_p.h
+normalize.o: $(hdrdir)/ruby/internal/core.h
+normalize.o: $(hdrdir)/ruby/internal/core/rarray.h
+normalize.o: $(hdrdir)/ruby/internal/core/rbasic.h
+normalize.o: $(hdrdir)/ruby/internal/core/rbignum.h
+normalize.o: $(hdrdir)/ruby/internal/core/rclass.h
+normalize.o: $(hdrdir)/ruby/internal/core/rdata.h
+normalize.o: $(hdrdir)/ruby/internal/core/rfile.h
+normalize.o: $(hdrdir)/ruby/internal/core/rhash.h
+normalize.o: $(hdrdir)/ruby/internal/core/robject.h
+normalize.o: $(hdrdir)/ruby/internal/core/rregexp.h
+normalize.o: $(hdrdir)/ruby/internal/core/rstring.h
+normalize.o: $(hdrdir)/ruby/internal/core/rstruct.h
+normalize.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+normalize.o: $(hdrdir)/ruby/internal/ctype.h
+normalize.o: $(hdrdir)/ruby/internal/dllexport.h
+normalize.o: $(hdrdir)/ruby/internal/dosish.h
+normalize.o: $(hdrdir)/ruby/internal/error.h
+normalize.o: $(hdrdir)/ruby/internal/eval.h
+normalize.o: $(hdrdir)/ruby/internal/event.h
+normalize.o: $(hdrdir)/ruby/internal/fl_type.h
+normalize.o: $(hdrdir)/ruby/internal/gc.h
+normalize.o: $(hdrdir)/ruby/internal/glob.h
+normalize.o: $(hdrdir)/ruby/internal/globals.h
+normalize.o: $(hdrdir)/ruby/internal/has/attribute.h
+normalize.o: $(hdrdir)/ruby/internal/has/builtin.h
+normalize.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+normalize.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+normalize.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+normalize.o: $(hdrdir)/ruby/internal/has/extension.h
+normalize.o: $(hdrdir)/ruby/internal/has/feature.h
+normalize.o: $(hdrdir)/ruby/internal/has/warning.h
+normalize.o: $(hdrdir)/ruby/internal/intern/array.h
+normalize.o: $(hdrdir)/ruby/internal/intern/bignum.h
+normalize.o: $(hdrdir)/ruby/internal/intern/class.h
+normalize.o: $(hdrdir)/ruby/internal/intern/compar.h
+normalize.o: $(hdrdir)/ruby/internal/intern/complex.h
+normalize.o: $(hdrdir)/ruby/internal/intern/cont.h
+normalize.o: $(hdrdir)/ruby/internal/intern/dir.h
+normalize.o: $(hdrdir)/ruby/internal/intern/enum.h
+normalize.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+normalize.o: $(hdrdir)/ruby/internal/intern/error.h
+normalize.o: $(hdrdir)/ruby/internal/intern/eval.h
+normalize.o: $(hdrdir)/ruby/internal/intern/file.h
+normalize.o: $(hdrdir)/ruby/internal/intern/gc.h
+normalize.o: $(hdrdir)/ruby/internal/intern/hash.h
+normalize.o: $(hdrdir)/ruby/internal/intern/io.h
+normalize.o: $(hdrdir)/ruby/internal/intern/load.h
+normalize.o: $(hdrdir)/ruby/internal/intern/marshal.h
+normalize.o: $(hdrdir)/ruby/internal/intern/numeric.h
+normalize.o: $(hdrdir)/ruby/internal/intern/object.h
+normalize.o: $(hdrdir)/ruby/internal/intern/parse.h
+normalize.o: $(hdrdir)/ruby/internal/intern/proc.h
+normalize.o: $(hdrdir)/ruby/internal/intern/process.h
+normalize.o: $(hdrdir)/ruby/internal/intern/random.h
+normalize.o: $(hdrdir)/ruby/internal/intern/range.h
+normalize.o: $(hdrdir)/ruby/internal/intern/rational.h
+normalize.o: $(hdrdir)/ruby/internal/intern/re.h
+normalize.o: $(hdrdir)/ruby/internal/intern/ruby.h
+normalize.o: $(hdrdir)/ruby/internal/intern/select.h
+normalize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+normalize.o: $(hdrdir)/ruby/internal/intern/signal.h
+normalize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+normalize.o: $(hdrdir)/ruby/internal/intern/string.h
+normalize.o: $(hdrdir)/ruby/internal/intern/struct.h
+normalize.o: $(hdrdir)/ruby/internal/intern/thread.h
+normalize.o: $(hdrdir)/ruby/internal/intern/time.h
+normalize.o: $(hdrdir)/ruby/internal/intern/variable.h
+normalize.o: $(hdrdir)/ruby/internal/intern/vm.h
+normalize.o: $(hdrdir)/ruby/internal/interpreter.h
+normalize.o: $(hdrdir)/ruby/internal/iterator.h
+normalize.o: $(hdrdir)/ruby/internal/memory.h
+normalize.o: $(hdrdir)/ruby/internal/method.h
+normalize.o: $(hdrdir)/ruby/internal/module.h
+normalize.o: $(hdrdir)/ruby/internal/newobj.h
+normalize.o: $(hdrdir)/ruby/internal/rgengc.h
+normalize.o: $(hdrdir)/ruby/internal/scan_args.h
+normalize.o: $(hdrdir)/ruby/internal/special_consts.h
+normalize.o: $(hdrdir)/ruby/internal/static_assert.h
+normalize.o: $(hdrdir)/ruby/internal/stdalign.h
+normalize.o: $(hdrdir)/ruby/internal/stdbool.h
+normalize.o: $(hdrdir)/ruby/internal/symbol.h
+normalize.o: $(hdrdir)/ruby/internal/token_paste.h
+normalize.o: $(hdrdir)/ruby/internal/value.h
+normalize.o: $(hdrdir)/ruby/internal/value_type.h
+normalize.o: $(hdrdir)/ruby/internal/variable.h
+normalize.o: $(hdrdir)/ruby/internal/warning_push.h
+normalize.o: $(hdrdir)/ruby/internal/xmalloc.h
normalize.o: $(hdrdir)/ruby/missing.h
+normalize.o: $(hdrdir)/ruby/onigmo.h
+normalize.o: $(hdrdir)/ruby/oniguruma.h
normalize.o: $(hdrdir)/ruby/ruby.h
normalize.o: $(hdrdir)/ruby/st.h
normalize.o: $(hdrdir)/ruby/subst.h
normalize.o: $(top_srcdir)/internal.h
+normalize.o: $(top_srcdir)/internal/file.h
normalize.o: normalize.c
qsort.o: $(RUBY_EXTCONF_H)
qsort.o: $(arch_hdrdir)/ruby/config.h
qsort.o: $(hdrdir)/ruby.h
qsort.o: $(hdrdir)/ruby/assert.h
qsort.o: $(hdrdir)/ruby/backward.h
+qsort.o: $(hdrdir)/ruby/backward/2/assume.h
+qsort.o: $(hdrdir)/ruby/backward/2/attributes.h
+qsort.o: $(hdrdir)/ruby/backward/2/bool.h
+qsort.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+qsort.o: $(hdrdir)/ruby/backward/2/inttypes.h
+qsort.o: $(hdrdir)/ruby/backward/2/limits.h
+qsort.o: $(hdrdir)/ruby/backward/2/long_long.h
+qsort.o: $(hdrdir)/ruby/backward/2/stdalign.h
+qsort.o: $(hdrdir)/ruby/backward/2/stdarg.h
qsort.o: $(hdrdir)/ruby/defines.h
qsort.o: $(hdrdir)/ruby/encoding.h
qsort.o: $(hdrdir)/ruby/intern.h
+qsort.o: $(hdrdir)/ruby/internal/anyargs.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+qsort.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+qsort.o: $(hdrdir)/ruby/internal/assume.h
+qsort.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+qsort.o: $(hdrdir)/ruby/internal/attr/artificial.h
+qsort.o: $(hdrdir)/ruby/internal/attr/cold.h
+qsort.o: $(hdrdir)/ruby/internal/attr/const.h
+qsort.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+qsort.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+qsort.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+qsort.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+qsort.o: $(hdrdir)/ruby/internal/attr/error.h
+qsort.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+qsort.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+qsort.o: $(hdrdir)/ruby/internal/attr/format.h
+qsort.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+qsort.o: $(hdrdir)/ruby/internal/attr/noalias.h
+qsort.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+qsort.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+qsort.o: $(hdrdir)/ruby/internal/attr/noinline.h
+qsort.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+qsort.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+qsort.o: $(hdrdir)/ruby/internal/attr/pure.h
+qsort.o: $(hdrdir)/ruby/internal/attr/restrict.h
+qsort.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+qsort.o: $(hdrdir)/ruby/internal/attr/warning.h
+qsort.o: $(hdrdir)/ruby/internal/attr/weakref.h
+qsort.o: $(hdrdir)/ruby/internal/cast.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+qsort.o: $(hdrdir)/ruby/internal/compiler_since.h
+qsort.o: $(hdrdir)/ruby/internal/config.h
+qsort.o: $(hdrdir)/ruby/internal/constant_p.h
+qsort.o: $(hdrdir)/ruby/internal/core.h
+qsort.o: $(hdrdir)/ruby/internal/core/rarray.h
+qsort.o: $(hdrdir)/ruby/internal/core/rbasic.h
+qsort.o: $(hdrdir)/ruby/internal/core/rbignum.h
+qsort.o: $(hdrdir)/ruby/internal/core/rclass.h
+qsort.o: $(hdrdir)/ruby/internal/core/rdata.h
+qsort.o: $(hdrdir)/ruby/internal/core/rfile.h
+qsort.o: $(hdrdir)/ruby/internal/core/rhash.h
+qsort.o: $(hdrdir)/ruby/internal/core/robject.h
+qsort.o: $(hdrdir)/ruby/internal/core/rregexp.h
+qsort.o: $(hdrdir)/ruby/internal/core/rstring.h
+qsort.o: $(hdrdir)/ruby/internal/core/rstruct.h
+qsort.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+qsort.o: $(hdrdir)/ruby/internal/ctype.h
+qsort.o: $(hdrdir)/ruby/internal/dllexport.h
+qsort.o: $(hdrdir)/ruby/internal/dosish.h
+qsort.o: $(hdrdir)/ruby/internal/error.h
+qsort.o: $(hdrdir)/ruby/internal/eval.h
+qsort.o: $(hdrdir)/ruby/internal/event.h
+qsort.o: $(hdrdir)/ruby/internal/fl_type.h
+qsort.o: $(hdrdir)/ruby/internal/gc.h
+qsort.o: $(hdrdir)/ruby/internal/glob.h
+qsort.o: $(hdrdir)/ruby/internal/globals.h
+qsort.o: $(hdrdir)/ruby/internal/has/attribute.h
+qsort.o: $(hdrdir)/ruby/internal/has/builtin.h
+qsort.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+qsort.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+qsort.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+qsort.o: $(hdrdir)/ruby/internal/has/extension.h
+qsort.o: $(hdrdir)/ruby/internal/has/feature.h
+qsort.o: $(hdrdir)/ruby/internal/has/warning.h
+qsort.o: $(hdrdir)/ruby/internal/intern/array.h
+qsort.o: $(hdrdir)/ruby/internal/intern/bignum.h
+qsort.o: $(hdrdir)/ruby/internal/intern/class.h
+qsort.o: $(hdrdir)/ruby/internal/intern/compar.h
+qsort.o: $(hdrdir)/ruby/internal/intern/complex.h
+qsort.o: $(hdrdir)/ruby/internal/intern/cont.h
+qsort.o: $(hdrdir)/ruby/internal/intern/dir.h
+qsort.o: $(hdrdir)/ruby/internal/intern/enum.h
+qsort.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+qsort.o: $(hdrdir)/ruby/internal/intern/error.h
+qsort.o: $(hdrdir)/ruby/internal/intern/eval.h
+qsort.o: $(hdrdir)/ruby/internal/intern/file.h
+qsort.o: $(hdrdir)/ruby/internal/intern/gc.h
+qsort.o: $(hdrdir)/ruby/internal/intern/hash.h
+qsort.o: $(hdrdir)/ruby/internal/intern/io.h
+qsort.o: $(hdrdir)/ruby/internal/intern/load.h
+qsort.o: $(hdrdir)/ruby/internal/intern/marshal.h
+qsort.o: $(hdrdir)/ruby/internal/intern/numeric.h
+qsort.o: $(hdrdir)/ruby/internal/intern/object.h
+qsort.o: $(hdrdir)/ruby/internal/intern/parse.h
+qsort.o: $(hdrdir)/ruby/internal/intern/proc.h
+qsort.o: $(hdrdir)/ruby/internal/intern/process.h
+qsort.o: $(hdrdir)/ruby/internal/intern/random.h
+qsort.o: $(hdrdir)/ruby/internal/intern/range.h
+qsort.o: $(hdrdir)/ruby/internal/intern/rational.h
+qsort.o: $(hdrdir)/ruby/internal/intern/re.h
+qsort.o: $(hdrdir)/ruby/internal/intern/ruby.h
+qsort.o: $(hdrdir)/ruby/internal/intern/select.h
+qsort.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+qsort.o: $(hdrdir)/ruby/internal/intern/signal.h
+qsort.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+qsort.o: $(hdrdir)/ruby/internal/intern/string.h
+qsort.o: $(hdrdir)/ruby/internal/intern/struct.h
+qsort.o: $(hdrdir)/ruby/internal/intern/thread.h
+qsort.o: $(hdrdir)/ruby/internal/intern/time.h
+qsort.o: $(hdrdir)/ruby/internal/intern/variable.h
+qsort.o: $(hdrdir)/ruby/internal/intern/vm.h
+qsort.o: $(hdrdir)/ruby/internal/interpreter.h
+qsort.o: $(hdrdir)/ruby/internal/iterator.h
+qsort.o: $(hdrdir)/ruby/internal/memory.h
+qsort.o: $(hdrdir)/ruby/internal/method.h
+qsort.o: $(hdrdir)/ruby/internal/module.h
+qsort.o: $(hdrdir)/ruby/internal/newobj.h
+qsort.o: $(hdrdir)/ruby/internal/rgengc.h
+qsort.o: $(hdrdir)/ruby/internal/scan_args.h
+qsort.o: $(hdrdir)/ruby/internal/special_consts.h
+qsort.o: $(hdrdir)/ruby/internal/static_assert.h
+qsort.o: $(hdrdir)/ruby/internal/stdalign.h
+qsort.o: $(hdrdir)/ruby/internal/stdbool.h
+qsort.o: $(hdrdir)/ruby/internal/symbol.h
+qsort.o: $(hdrdir)/ruby/internal/token_paste.h
+qsort.o: $(hdrdir)/ruby/internal/value.h
+qsort.o: $(hdrdir)/ruby/internal/value_type.h
+qsort.o: $(hdrdir)/ruby/internal/variable.h
+qsort.o: $(hdrdir)/ruby/internal/warning_push.h
+qsort.o: $(hdrdir)/ruby/internal/xmalloc.h
qsort.o: $(hdrdir)/ruby/missing.h
qsort.o: $(hdrdir)/ruby/onigmo.h
qsort.o: $(hdrdir)/ruby/oniguruma.h
@@ -175,13 +2127,323 @@ qsort.o: $(hdrdir)/ruby/st.h
qsort.o: $(hdrdir)/ruby/subst.h
qsort.o: $(hdrdir)/ruby/util.h
qsort.o: qsort.c
+rb_interned_str.o: $(RUBY_EXTCONF_H)
+rb_interned_str.o: $(arch_hdrdir)/ruby/config.h
+rb_interned_str.o: $(hdrdir)/ruby.h
+rb_interned_str.o: $(hdrdir)/ruby/assert.h
+rb_interned_str.o: $(hdrdir)/ruby/backward.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_interned_str.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rb_interned_str.o: $(hdrdir)/ruby/defines.h
+rb_interned_str.o: $(hdrdir)/ruby/intern.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/anyargs.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/assume.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/cold.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/const.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/error.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/format.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/pure.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/warning.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/cast.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/compiler_since.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/config.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/constant_p.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rarray.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rclass.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rdata.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rfile.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rhash.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/robject.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rstring.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/ctype.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/dllexport.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/dosish.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/error.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/eval.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/event.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/fl_type.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/gc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/glob.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/globals.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/attribute.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/builtin.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/extension.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/feature.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/has/warning.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/array.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/class.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/compar.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/complex.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/cont.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/dir.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/enum.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/error.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/eval.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/file.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/gc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/hash.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/io.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/load.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/object.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/parse.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/proc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/process.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/random.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/range.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/rational.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/re.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/select.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/signal.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/string.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/struct.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/thread.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/time.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/variable.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/vm.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/interpreter.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/iterator.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/memory.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/method.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/module.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/newobj.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/rgengc.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/scan_args.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/special_consts.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/static_assert.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/stdalign.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/symbol.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/token_paste.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/value.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/value_type.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/variable.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/warning_push.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/xmalloc.h
+rb_interned_str.o: $(hdrdir)/ruby/missing.h
+rb_interned_str.o: $(hdrdir)/ruby/ruby.h
+rb_interned_str.o: $(hdrdir)/ruby/st.h
+rb_interned_str.o: $(hdrdir)/ruby/subst.h
+rb_interned_str.o: rb_interned_str.c
rb_str_dup.o: $(RUBY_EXTCONF_H)
rb_str_dup.o: $(arch_hdrdir)/ruby/config.h
rb_str_dup.o: $(hdrdir)/ruby.h
rb_str_dup.o: $(hdrdir)/ruby/assert.h
rb_str_dup.o: $(hdrdir)/ruby/backward.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/assume.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/attributes.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/bool.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/limits.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/long_long.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rb_str_dup.o: $(hdrdir)/ruby/backward/2/stdarg.h
rb_str_dup.o: $(hdrdir)/ruby/defines.h
rb_str_dup.o: $(hdrdir)/ruby/intern.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/anyargs.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/assume.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/cold.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/const.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/error.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/format.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/pure.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/warning.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/cast.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/compiler_since.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/config.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/constant_p.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rarray.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rclass.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rdata.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rfile.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rhash.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/robject.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rstring.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/ctype.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/dllexport.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/dosish.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/error.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/eval.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/event.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/fl_type.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/gc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/glob.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/globals.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/attribute.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/builtin.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/extension.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/feature.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/has/warning.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/array.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/class.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/compar.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/complex.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/cont.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/dir.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/enum.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/error.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/eval.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/file.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/gc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/hash.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/io.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/load.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/object.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/parse.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/proc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/process.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/random.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/range.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/rational.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/re.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/select.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/signal.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/string.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/struct.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/thread.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/time.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/variable.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/vm.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/interpreter.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/iterator.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/memory.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/method.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/module.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/newobj.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/rgengc.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/scan_args.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/special_consts.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/static_assert.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/stdalign.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/stdbool.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/symbol.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/token_paste.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/value.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/value_type.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/variable.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/warning_push.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/xmalloc.h
rb_str_dup.o: $(hdrdir)/ruby/missing.h
rb_str_dup.o: $(hdrdir)/ruby/ruby.h
rb_str_dup.o: $(hdrdir)/ruby/st.h
@@ -192,8 +2454,157 @@ set_len.o: $(arch_hdrdir)/ruby/config.h
set_len.o: $(hdrdir)/ruby.h
set_len.o: $(hdrdir)/ruby/assert.h
set_len.o: $(hdrdir)/ruby/backward.h
+set_len.o: $(hdrdir)/ruby/backward/2/assume.h
+set_len.o: $(hdrdir)/ruby/backward/2/attributes.h
+set_len.o: $(hdrdir)/ruby/backward/2/bool.h
+set_len.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+set_len.o: $(hdrdir)/ruby/backward/2/inttypes.h
+set_len.o: $(hdrdir)/ruby/backward/2/limits.h
+set_len.o: $(hdrdir)/ruby/backward/2/long_long.h
+set_len.o: $(hdrdir)/ruby/backward/2/stdalign.h
+set_len.o: $(hdrdir)/ruby/backward/2/stdarg.h
set_len.o: $(hdrdir)/ruby/defines.h
set_len.o: $(hdrdir)/ruby/intern.h
+set_len.o: $(hdrdir)/ruby/internal/anyargs.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+set_len.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+set_len.o: $(hdrdir)/ruby/internal/assume.h
+set_len.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+set_len.o: $(hdrdir)/ruby/internal/attr/artificial.h
+set_len.o: $(hdrdir)/ruby/internal/attr/cold.h
+set_len.o: $(hdrdir)/ruby/internal/attr/const.h
+set_len.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+set_len.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+set_len.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+set_len.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+set_len.o: $(hdrdir)/ruby/internal/attr/error.h
+set_len.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+set_len.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+set_len.o: $(hdrdir)/ruby/internal/attr/format.h
+set_len.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+set_len.o: $(hdrdir)/ruby/internal/attr/noalias.h
+set_len.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+set_len.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+set_len.o: $(hdrdir)/ruby/internal/attr/noinline.h
+set_len.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+set_len.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+set_len.o: $(hdrdir)/ruby/internal/attr/pure.h
+set_len.o: $(hdrdir)/ruby/internal/attr/restrict.h
+set_len.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+set_len.o: $(hdrdir)/ruby/internal/attr/warning.h
+set_len.o: $(hdrdir)/ruby/internal/attr/weakref.h
+set_len.o: $(hdrdir)/ruby/internal/cast.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+set_len.o: $(hdrdir)/ruby/internal/compiler_since.h
+set_len.o: $(hdrdir)/ruby/internal/config.h
+set_len.o: $(hdrdir)/ruby/internal/constant_p.h
+set_len.o: $(hdrdir)/ruby/internal/core.h
+set_len.o: $(hdrdir)/ruby/internal/core/rarray.h
+set_len.o: $(hdrdir)/ruby/internal/core/rbasic.h
+set_len.o: $(hdrdir)/ruby/internal/core/rbignum.h
+set_len.o: $(hdrdir)/ruby/internal/core/rclass.h
+set_len.o: $(hdrdir)/ruby/internal/core/rdata.h
+set_len.o: $(hdrdir)/ruby/internal/core/rfile.h
+set_len.o: $(hdrdir)/ruby/internal/core/rhash.h
+set_len.o: $(hdrdir)/ruby/internal/core/robject.h
+set_len.o: $(hdrdir)/ruby/internal/core/rregexp.h
+set_len.o: $(hdrdir)/ruby/internal/core/rstring.h
+set_len.o: $(hdrdir)/ruby/internal/core/rstruct.h
+set_len.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+set_len.o: $(hdrdir)/ruby/internal/ctype.h
+set_len.o: $(hdrdir)/ruby/internal/dllexport.h
+set_len.o: $(hdrdir)/ruby/internal/dosish.h
+set_len.o: $(hdrdir)/ruby/internal/error.h
+set_len.o: $(hdrdir)/ruby/internal/eval.h
+set_len.o: $(hdrdir)/ruby/internal/event.h
+set_len.o: $(hdrdir)/ruby/internal/fl_type.h
+set_len.o: $(hdrdir)/ruby/internal/gc.h
+set_len.o: $(hdrdir)/ruby/internal/glob.h
+set_len.o: $(hdrdir)/ruby/internal/globals.h
+set_len.o: $(hdrdir)/ruby/internal/has/attribute.h
+set_len.o: $(hdrdir)/ruby/internal/has/builtin.h
+set_len.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+set_len.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+set_len.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+set_len.o: $(hdrdir)/ruby/internal/has/extension.h
+set_len.o: $(hdrdir)/ruby/internal/has/feature.h
+set_len.o: $(hdrdir)/ruby/internal/has/warning.h
+set_len.o: $(hdrdir)/ruby/internal/intern/array.h
+set_len.o: $(hdrdir)/ruby/internal/intern/bignum.h
+set_len.o: $(hdrdir)/ruby/internal/intern/class.h
+set_len.o: $(hdrdir)/ruby/internal/intern/compar.h
+set_len.o: $(hdrdir)/ruby/internal/intern/complex.h
+set_len.o: $(hdrdir)/ruby/internal/intern/cont.h
+set_len.o: $(hdrdir)/ruby/internal/intern/dir.h
+set_len.o: $(hdrdir)/ruby/internal/intern/enum.h
+set_len.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+set_len.o: $(hdrdir)/ruby/internal/intern/error.h
+set_len.o: $(hdrdir)/ruby/internal/intern/eval.h
+set_len.o: $(hdrdir)/ruby/internal/intern/file.h
+set_len.o: $(hdrdir)/ruby/internal/intern/gc.h
+set_len.o: $(hdrdir)/ruby/internal/intern/hash.h
+set_len.o: $(hdrdir)/ruby/internal/intern/io.h
+set_len.o: $(hdrdir)/ruby/internal/intern/load.h
+set_len.o: $(hdrdir)/ruby/internal/intern/marshal.h
+set_len.o: $(hdrdir)/ruby/internal/intern/numeric.h
+set_len.o: $(hdrdir)/ruby/internal/intern/object.h
+set_len.o: $(hdrdir)/ruby/internal/intern/parse.h
+set_len.o: $(hdrdir)/ruby/internal/intern/proc.h
+set_len.o: $(hdrdir)/ruby/internal/intern/process.h
+set_len.o: $(hdrdir)/ruby/internal/intern/random.h
+set_len.o: $(hdrdir)/ruby/internal/intern/range.h
+set_len.o: $(hdrdir)/ruby/internal/intern/rational.h
+set_len.o: $(hdrdir)/ruby/internal/intern/re.h
+set_len.o: $(hdrdir)/ruby/internal/intern/ruby.h
+set_len.o: $(hdrdir)/ruby/internal/intern/select.h
+set_len.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+set_len.o: $(hdrdir)/ruby/internal/intern/signal.h
+set_len.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+set_len.o: $(hdrdir)/ruby/internal/intern/string.h
+set_len.o: $(hdrdir)/ruby/internal/intern/struct.h
+set_len.o: $(hdrdir)/ruby/internal/intern/thread.h
+set_len.o: $(hdrdir)/ruby/internal/intern/time.h
+set_len.o: $(hdrdir)/ruby/internal/intern/variable.h
+set_len.o: $(hdrdir)/ruby/internal/intern/vm.h
+set_len.o: $(hdrdir)/ruby/internal/interpreter.h
+set_len.o: $(hdrdir)/ruby/internal/iterator.h
+set_len.o: $(hdrdir)/ruby/internal/memory.h
+set_len.o: $(hdrdir)/ruby/internal/method.h
+set_len.o: $(hdrdir)/ruby/internal/module.h
+set_len.o: $(hdrdir)/ruby/internal/newobj.h
+set_len.o: $(hdrdir)/ruby/internal/rgengc.h
+set_len.o: $(hdrdir)/ruby/internal/scan_args.h
+set_len.o: $(hdrdir)/ruby/internal/special_consts.h
+set_len.o: $(hdrdir)/ruby/internal/static_assert.h
+set_len.o: $(hdrdir)/ruby/internal/stdalign.h
+set_len.o: $(hdrdir)/ruby/internal/stdbool.h
+set_len.o: $(hdrdir)/ruby/internal/symbol.h
+set_len.o: $(hdrdir)/ruby/internal/token_paste.h
+set_len.o: $(hdrdir)/ruby/internal/value.h
+set_len.o: $(hdrdir)/ruby/internal/value_type.h
+set_len.o: $(hdrdir)/ruby/internal/variable.h
+set_len.o: $(hdrdir)/ruby/internal/warning_push.h
+set_len.o: $(hdrdir)/ruby/internal/xmalloc.h
set_len.o: $(hdrdir)/ruby/missing.h
set_len.o: $(hdrdir)/ruby/ruby.h
set_len.o: $(hdrdir)/ruby/st.h
diff --git a/ext/-test-/string/enc_str_buf_cat.c b/ext/-test-/string/enc_str_buf_cat.c
index 9ac4a298be..4c1b262e1e 100644
--- a/ext/-test-/string/enc_str_buf_cat.c
+++ b/ext/-test-/string/enc_str_buf_cat.c
@@ -7,8 +7,22 @@ enc_str_buf_cat(VALUE str, VALUE str2)
return rb_enc_str_buf_cat(str, RSTRING_PTR(str2), RSTRING_LEN(str2), rb_enc_get(str2));
}
+static VALUE
+str_conv_enc_opts(VALUE str, VALUE from, VALUE to, VALUE ecflags, VALUE ecopts)
+{
+ rb_encoding *from_enc = NIL_P(from) ? NULL : rb_to_encoding(from);
+ rb_encoding *to_enc = NIL_P(to) ? NULL : rb_to_encoding(to);
+ int flags = NUM2INT(ecflags);
+ if (!NIL_P(ecopts)) {
+ Check_Type(ecopts, T_HASH);
+ OBJ_FREEZE(ecopts);
+ }
+ return rb_str_conv_enc_opts(str, from_enc, to_enc, flags, ecopts);
+}
+
void
Init_string_enc_str_buf_cat(VALUE klass)
{
rb_define_method(klass, "enc_str_buf_cat", enc_str_buf_cat, 1);
+ rb_define_method(klass, "str_conv_enc_opts", str_conv_enc_opts, 4);
}
diff --git a/ext/-test-/string/fstring.c b/ext/-test-/string/fstring.c
index 30120b42f6..2374319fe3 100644
--- a/ext/-test-/string/fstring.c
+++ b/ext/-test-/string/fstring.c
@@ -1,4 +1,5 @@
#include "ruby.h"
+#include "ruby/encoding.h"
VALUE rb_fstring(VALUE str);
@@ -8,8 +9,22 @@ bug_s_fstring(VALUE self, VALUE str)
return rb_fstring(str);
}
+VALUE
+bug_s_rb_enc_interned_str(VALUE self, VALUE encoding)
+{
+ return rb_enc_interned_str("foo", 3, RDATA(encoding)->data);
+}
+
+VALUE
+bug_s_rb_enc_str_new(VALUE self, VALUE encoding)
+{
+ return rb_enc_str_new("foo", 3, RDATA(encoding)->data);
+}
+
void
Init_string_fstring(VALUE klass)
{
rb_define_singleton_method(klass, "fstring", bug_s_fstring, 1);
+ rb_define_singleton_method(klass, "rb_enc_interned_str", bug_s_rb_enc_interned_str, 1);
+ rb_define_singleton_method(klass, "rb_enc_str_new", bug_s_rb_enc_str_new, 1);
}
diff --git a/ext/-test-/string/normalize.c b/ext/-test-/string/normalize.c
index 0ba1797631..a069288ee8 100644
--- a/ext/-test-/string/normalize.c
+++ b/ext/-test-/string/normalize.c
@@ -1,4 +1,4 @@
-#include "internal.h"
+#include "internal/file.h"
#ifdef __APPLE__
static VALUE
diff --git a/ext/-test-/string/rb_interned_str.c b/ext/-test-/string/rb_interned_str.c
new file mode 100644
index 0000000000..47643ec249
--- /dev/null
+++ b/ext/-test-/string/rb_interned_str.c
@@ -0,0 +1,14 @@
+#include "ruby.h"
+
+static VALUE
+bug_rb_interned_str_dup(VALUE self, VALUE str)
+{
+ Check_Type(str, T_STRING);
+ return rb_interned_str(RSTRING_PTR(str), RSTRING_LEN(str));
+}
+
+void
+Init_string_rb_interned_str(VALUE klass)
+{
+ rb_define_singleton_method(klass, "rb_interned_str_dup", bug_rb_interned_str_dup, 1);
+}
diff --git a/ext/-test-/struct/depend b/ext/-test-/struct/depend
index 552daf0ac5..166fff21d9 100644
--- a/ext/-test-/struct/depend
+++ b/ext/-test-/struct/depend
@@ -2,8 +2,157 @@
duplicate.o: $(RUBY_EXTCONF_H)
duplicate.o: $(arch_hdrdir)/ruby/config.h
duplicate.o: $(hdrdir)/ruby.h
+duplicate.o: $(hdrdir)/ruby/internal/anyargs.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+duplicate.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+duplicate.o: $(hdrdir)/ruby/internal/assume.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/artificial.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/cold.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/const.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/error.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/format.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/noalias.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/noinline.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/pure.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/restrict.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/warning.h
+duplicate.o: $(hdrdir)/ruby/internal/attr/weakref.h
+duplicate.o: $(hdrdir)/ruby/internal/cast.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+duplicate.o: $(hdrdir)/ruby/internal/compiler_since.h
+duplicate.o: $(hdrdir)/ruby/internal/config.h
+duplicate.o: $(hdrdir)/ruby/internal/constant_p.h
+duplicate.o: $(hdrdir)/ruby/internal/core.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rarray.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rbasic.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rbignum.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rclass.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rdata.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rfile.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rhash.h
+duplicate.o: $(hdrdir)/ruby/internal/core/robject.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rregexp.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rstring.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rstruct.h
+duplicate.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+duplicate.o: $(hdrdir)/ruby/internal/ctype.h
+duplicate.o: $(hdrdir)/ruby/internal/dllexport.h
+duplicate.o: $(hdrdir)/ruby/internal/dosish.h
+duplicate.o: $(hdrdir)/ruby/internal/error.h
+duplicate.o: $(hdrdir)/ruby/internal/eval.h
+duplicate.o: $(hdrdir)/ruby/internal/event.h
+duplicate.o: $(hdrdir)/ruby/internal/fl_type.h
+duplicate.o: $(hdrdir)/ruby/internal/gc.h
+duplicate.o: $(hdrdir)/ruby/internal/glob.h
+duplicate.o: $(hdrdir)/ruby/internal/globals.h
+duplicate.o: $(hdrdir)/ruby/internal/has/attribute.h
+duplicate.o: $(hdrdir)/ruby/internal/has/builtin.h
+duplicate.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+duplicate.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+duplicate.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+duplicate.o: $(hdrdir)/ruby/internal/has/extension.h
+duplicate.o: $(hdrdir)/ruby/internal/has/feature.h
+duplicate.o: $(hdrdir)/ruby/internal/has/warning.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/array.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/bignum.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/class.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/compar.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/complex.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/cont.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/dir.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/enum.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/error.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/eval.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/file.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/gc.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/hash.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/io.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/load.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/marshal.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/numeric.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/object.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/parse.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/proc.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/process.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/random.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/range.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/rational.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/re.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/ruby.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/select.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/signal.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/string.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/struct.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/thread.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/time.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/variable.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/vm.h
+duplicate.o: $(hdrdir)/ruby/internal/interpreter.h
+duplicate.o: $(hdrdir)/ruby/internal/iterator.h
+duplicate.o: $(hdrdir)/ruby/internal/memory.h
+duplicate.o: $(hdrdir)/ruby/internal/method.h
+duplicate.o: $(hdrdir)/ruby/internal/module.h
+duplicate.o: $(hdrdir)/ruby/internal/newobj.h
+duplicate.o: $(hdrdir)/ruby/internal/rgengc.h
+duplicate.o: $(hdrdir)/ruby/internal/scan_args.h
+duplicate.o: $(hdrdir)/ruby/internal/special_consts.h
+duplicate.o: $(hdrdir)/ruby/internal/static_assert.h
+duplicate.o: $(hdrdir)/ruby/internal/stdalign.h
+duplicate.o: $(hdrdir)/ruby/internal/stdbool.h
+duplicate.o: $(hdrdir)/ruby/internal/symbol.h
+duplicate.o: $(hdrdir)/ruby/internal/token_paste.h
+duplicate.o: $(hdrdir)/ruby/internal/value.h
+duplicate.o: $(hdrdir)/ruby/internal/value_type.h
+duplicate.o: $(hdrdir)/ruby/internal/variable.h
+duplicate.o: $(hdrdir)/ruby/internal/warning_push.h
+duplicate.o: $(hdrdir)/ruby/internal/xmalloc.h
duplicate.o: $(hdrdir)/ruby/assert.h
duplicate.o: $(hdrdir)/ruby/backward.h
+duplicate.o: $(hdrdir)/ruby/backward/2/assume.h
+duplicate.o: $(hdrdir)/ruby/backward/2/attributes.h
+duplicate.o: $(hdrdir)/ruby/backward/2/bool.h
+duplicate.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+duplicate.o: $(hdrdir)/ruby/backward/2/inttypes.h
+duplicate.o: $(hdrdir)/ruby/backward/2/limits.h
+duplicate.o: $(hdrdir)/ruby/backward/2/long_long.h
+duplicate.o: $(hdrdir)/ruby/backward/2/stdalign.h
+duplicate.o: $(hdrdir)/ruby/backward/2/stdarg.h
duplicate.o: $(hdrdir)/ruby/defines.h
duplicate.o: $(hdrdir)/ruby/intern.h
duplicate.o: $(hdrdir)/ruby/missing.h
@@ -14,8 +163,157 @@ duplicate.o: duplicate.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -26,8 +324,157 @@ init.o: init.c
len.o: $(RUBY_EXTCONF_H)
len.o: $(arch_hdrdir)/ruby/config.h
len.o: $(hdrdir)/ruby.h
+len.o: $(hdrdir)/ruby/internal/anyargs.h
+len.o: $(hdrdir)/ruby/internal/arithmetic.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+len.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+len.o: $(hdrdir)/ruby/internal/assume.h
+len.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+len.o: $(hdrdir)/ruby/internal/attr/artificial.h
+len.o: $(hdrdir)/ruby/internal/attr/cold.h
+len.o: $(hdrdir)/ruby/internal/attr/const.h
+len.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+len.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+len.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+len.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+len.o: $(hdrdir)/ruby/internal/attr/error.h
+len.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+len.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+len.o: $(hdrdir)/ruby/internal/attr/format.h
+len.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+len.o: $(hdrdir)/ruby/internal/attr/noalias.h
+len.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+len.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+len.o: $(hdrdir)/ruby/internal/attr/noinline.h
+len.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+len.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+len.o: $(hdrdir)/ruby/internal/attr/pure.h
+len.o: $(hdrdir)/ruby/internal/attr/restrict.h
+len.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+len.o: $(hdrdir)/ruby/internal/attr/warning.h
+len.o: $(hdrdir)/ruby/internal/attr/weakref.h
+len.o: $(hdrdir)/ruby/internal/cast.h
+len.o: $(hdrdir)/ruby/internal/compiler_is.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+len.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+len.o: $(hdrdir)/ruby/internal/compiler_since.h
+len.o: $(hdrdir)/ruby/internal/config.h
+len.o: $(hdrdir)/ruby/internal/constant_p.h
+len.o: $(hdrdir)/ruby/internal/core.h
+len.o: $(hdrdir)/ruby/internal/core/rarray.h
+len.o: $(hdrdir)/ruby/internal/core/rbasic.h
+len.o: $(hdrdir)/ruby/internal/core/rbignum.h
+len.o: $(hdrdir)/ruby/internal/core/rclass.h
+len.o: $(hdrdir)/ruby/internal/core/rdata.h
+len.o: $(hdrdir)/ruby/internal/core/rfile.h
+len.o: $(hdrdir)/ruby/internal/core/rhash.h
+len.o: $(hdrdir)/ruby/internal/core/robject.h
+len.o: $(hdrdir)/ruby/internal/core/rregexp.h
+len.o: $(hdrdir)/ruby/internal/core/rstring.h
+len.o: $(hdrdir)/ruby/internal/core/rstruct.h
+len.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+len.o: $(hdrdir)/ruby/internal/ctype.h
+len.o: $(hdrdir)/ruby/internal/dllexport.h
+len.o: $(hdrdir)/ruby/internal/dosish.h
+len.o: $(hdrdir)/ruby/internal/error.h
+len.o: $(hdrdir)/ruby/internal/eval.h
+len.o: $(hdrdir)/ruby/internal/event.h
+len.o: $(hdrdir)/ruby/internal/fl_type.h
+len.o: $(hdrdir)/ruby/internal/gc.h
+len.o: $(hdrdir)/ruby/internal/glob.h
+len.o: $(hdrdir)/ruby/internal/globals.h
+len.o: $(hdrdir)/ruby/internal/has/attribute.h
+len.o: $(hdrdir)/ruby/internal/has/builtin.h
+len.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+len.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+len.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+len.o: $(hdrdir)/ruby/internal/has/extension.h
+len.o: $(hdrdir)/ruby/internal/has/feature.h
+len.o: $(hdrdir)/ruby/internal/has/warning.h
+len.o: $(hdrdir)/ruby/internal/intern/array.h
+len.o: $(hdrdir)/ruby/internal/intern/bignum.h
+len.o: $(hdrdir)/ruby/internal/intern/class.h
+len.o: $(hdrdir)/ruby/internal/intern/compar.h
+len.o: $(hdrdir)/ruby/internal/intern/complex.h
+len.o: $(hdrdir)/ruby/internal/intern/cont.h
+len.o: $(hdrdir)/ruby/internal/intern/dir.h
+len.o: $(hdrdir)/ruby/internal/intern/enum.h
+len.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+len.o: $(hdrdir)/ruby/internal/intern/error.h
+len.o: $(hdrdir)/ruby/internal/intern/eval.h
+len.o: $(hdrdir)/ruby/internal/intern/file.h
+len.o: $(hdrdir)/ruby/internal/intern/gc.h
+len.o: $(hdrdir)/ruby/internal/intern/hash.h
+len.o: $(hdrdir)/ruby/internal/intern/io.h
+len.o: $(hdrdir)/ruby/internal/intern/load.h
+len.o: $(hdrdir)/ruby/internal/intern/marshal.h
+len.o: $(hdrdir)/ruby/internal/intern/numeric.h
+len.o: $(hdrdir)/ruby/internal/intern/object.h
+len.o: $(hdrdir)/ruby/internal/intern/parse.h
+len.o: $(hdrdir)/ruby/internal/intern/proc.h
+len.o: $(hdrdir)/ruby/internal/intern/process.h
+len.o: $(hdrdir)/ruby/internal/intern/random.h
+len.o: $(hdrdir)/ruby/internal/intern/range.h
+len.o: $(hdrdir)/ruby/internal/intern/rational.h
+len.o: $(hdrdir)/ruby/internal/intern/re.h
+len.o: $(hdrdir)/ruby/internal/intern/ruby.h
+len.o: $(hdrdir)/ruby/internal/intern/select.h
+len.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+len.o: $(hdrdir)/ruby/internal/intern/signal.h
+len.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+len.o: $(hdrdir)/ruby/internal/intern/string.h
+len.o: $(hdrdir)/ruby/internal/intern/struct.h
+len.o: $(hdrdir)/ruby/internal/intern/thread.h
+len.o: $(hdrdir)/ruby/internal/intern/time.h
+len.o: $(hdrdir)/ruby/internal/intern/variable.h
+len.o: $(hdrdir)/ruby/internal/intern/vm.h
+len.o: $(hdrdir)/ruby/internal/interpreter.h
+len.o: $(hdrdir)/ruby/internal/iterator.h
+len.o: $(hdrdir)/ruby/internal/memory.h
+len.o: $(hdrdir)/ruby/internal/method.h
+len.o: $(hdrdir)/ruby/internal/module.h
+len.o: $(hdrdir)/ruby/internal/newobj.h
+len.o: $(hdrdir)/ruby/internal/rgengc.h
+len.o: $(hdrdir)/ruby/internal/scan_args.h
+len.o: $(hdrdir)/ruby/internal/special_consts.h
+len.o: $(hdrdir)/ruby/internal/static_assert.h
+len.o: $(hdrdir)/ruby/internal/stdalign.h
+len.o: $(hdrdir)/ruby/internal/stdbool.h
+len.o: $(hdrdir)/ruby/internal/symbol.h
+len.o: $(hdrdir)/ruby/internal/token_paste.h
+len.o: $(hdrdir)/ruby/internal/value.h
+len.o: $(hdrdir)/ruby/internal/value_type.h
+len.o: $(hdrdir)/ruby/internal/variable.h
+len.o: $(hdrdir)/ruby/internal/warning_push.h
+len.o: $(hdrdir)/ruby/internal/xmalloc.h
len.o: $(hdrdir)/ruby/assert.h
len.o: $(hdrdir)/ruby/backward.h
+len.o: $(hdrdir)/ruby/backward/2/assume.h
+len.o: $(hdrdir)/ruby/backward/2/attributes.h
+len.o: $(hdrdir)/ruby/backward/2/bool.h
+len.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+len.o: $(hdrdir)/ruby/backward/2/inttypes.h
+len.o: $(hdrdir)/ruby/backward/2/limits.h
+len.o: $(hdrdir)/ruby/backward/2/long_long.h
+len.o: $(hdrdir)/ruby/backward/2/stdalign.h
+len.o: $(hdrdir)/ruby/backward/2/stdarg.h
len.o: $(hdrdir)/ruby/defines.h
len.o: $(hdrdir)/ruby/intern.h
len.o: $(hdrdir)/ruby/missing.h
@@ -38,8 +485,157 @@ len.o: len.c
member.o: $(RUBY_EXTCONF_H)
member.o: $(arch_hdrdir)/ruby/config.h
member.o: $(hdrdir)/ruby.h
+member.o: $(hdrdir)/ruby/internal/anyargs.h
+member.o: $(hdrdir)/ruby/internal/arithmetic.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+member.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+member.o: $(hdrdir)/ruby/internal/assume.h
+member.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+member.o: $(hdrdir)/ruby/internal/attr/artificial.h
+member.o: $(hdrdir)/ruby/internal/attr/cold.h
+member.o: $(hdrdir)/ruby/internal/attr/const.h
+member.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+member.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+member.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+member.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+member.o: $(hdrdir)/ruby/internal/attr/error.h
+member.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+member.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+member.o: $(hdrdir)/ruby/internal/attr/format.h
+member.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+member.o: $(hdrdir)/ruby/internal/attr/noalias.h
+member.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+member.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+member.o: $(hdrdir)/ruby/internal/attr/noinline.h
+member.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+member.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+member.o: $(hdrdir)/ruby/internal/attr/pure.h
+member.o: $(hdrdir)/ruby/internal/attr/restrict.h
+member.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+member.o: $(hdrdir)/ruby/internal/attr/warning.h
+member.o: $(hdrdir)/ruby/internal/attr/weakref.h
+member.o: $(hdrdir)/ruby/internal/cast.h
+member.o: $(hdrdir)/ruby/internal/compiler_is.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+member.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+member.o: $(hdrdir)/ruby/internal/compiler_since.h
+member.o: $(hdrdir)/ruby/internal/config.h
+member.o: $(hdrdir)/ruby/internal/constant_p.h
+member.o: $(hdrdir)/ruby/internal/core.h
+member.o: $(hdrdir)/ruby/internal/core/rarray.h
+member.o: $(hdrdir)/ruby/internal/core/rbasic.h
+member.o: $(hdrdir)/ruby/internal/core/rbignum.h
+member.o: $(hdrdir)/ruby/internal/core/rclass.h
+member.o: $(hdrdir)/ruby/internal/core/rdata.h
+member.o: $(hdrdir)/ruby/internal/core/rfile.h
+member.o: $(hdrdir)/ruby/internal/core/rhash.h
+member.o: $(hdrdir)/ruby/internal/core/robject.h
+member.o: $(hdrdir)/ruby/internal/core/rregexp.h
+member.o: $(hdrdir)/ruby/internal/core/rstring.h
+member.o: $(hdrdir)/ruby/internal/core/rstruct.h
+member.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+member.o: $(hdrdir)/ruby/internal/ctype.h
+member.o: $(hdrdir)/ruby/internal/dllexport.h
+member.o: $(hdrdir)/ruby/internal/dosish.h
+member.o: $(hdrdir)/ruby/internal/error.h
+member.o: $(hdrdir)/ruby/internal/eval.h
+member.o: $(hdrdir)/ruby/internal/event.h
+member.o: $(hdrdir)/ruby/internal/fl_type.h
+member.o: $(hdrdir)/ruby/internal/gc.h
+member.o: $(hdrdir)/ruby/internal/glob.h
+member.o: $(hdrdir)/ruby/internal/globals.h
+member.o: $(hdrdir)/ruby/internal/has/attribute.h
+member.o: $(hdrdir)/ruby/internal/has/builtin.h
+member.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+member.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+member.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+member.o: $(hdrdir)/ruby/internal/has/extension.h
+member.o: $(hdrdir)/ruby/internal/has/feature.h
+member.o: $(hdrdir)/ruby/internal/has/warning.h
+member.o: $(hdrdir)/ruby/internal/intern/array.h
+member.o: $(hdrdir)/ruby/internal/intern/bignum.h
+member.o: $(hdrdir)/ruby/internal/intern/class.h
+member.o: $(hdrdir)/ruby/internal/intern/compar.h
+member.o: $(hdrdir)/ruby/internal/intern/complex.h
+member.o: $(hdrdir)/ruby/internal/intern/cont.h
+member.o: $(hdrdir)/ruby/internal/intern/dir.h
+member.o: $(hdrdir)/ruby/internal/intern/enum.h
+member.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+member.o: $(hdrdir)/ruby/internal/intern/error.h
+member.o: $(hdrdir)/ruby/internal/intern/eval.h
+member.o: $(hdrdir)/ruby/internal/intern/file.h
+member.o: $(hdrdir)/ruby/internal/intern/gc.h
+member.o: $(hdrdir)/ruby/internal/intern/hash.h
+member.o: $(hdrdir)/ruby/internal/intern/io.h
+member.o: $(hdrdir)/ruby/internal/intern/load.h
+member.o: $(hdrdir)/ruby/internal/intern/marshal.h
+member.o: $(hdrdir)/ruby/internal/intern/numeric.h
+member.o: $(hdrdir)/ruby/internal/intern/object.h
+member.o: $(hdrdir)/ruby/internal/intern/parse.h
+member.o: $(hdrdir)/ruby/internal/intern/proc.h
+member.o: $(hdrdir)/ruby/internal/intern/process.h
+member.o: $(hdrdir)/ruby/internal/intern/random.h
+member.o: $(hdrdir)/ruby/internal/intern/range.h
+member.o: $(hdrdir)/ruby/internal/intern/rational.h
+member.o: $(hdrdir)/ruby/internal/intern/re.h
+member.o: $(hdrdir)/ruby/internal/intern/ruby.h
+member.o: $(hdrdir)/ruby/internal/intern/select.h
+member.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+member.o: $(hdrdir)/ruby/internal/intern/signal.h
+member.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+member.o: $(hdrdir)/ruby/internal/intern/string.h
+member.o: $(hdrdir)/ruby/internal/intern/struct.h
+member.o: $(hdrdir)/ruby/internal/intern/thread.h
+member.o: $(hdrdir)/ruby/internal/intern/time.h
+member.o: $(hdrdir)/ruby/internal/intern/variable.h
+member.o: $(hdrdir)/ruby/internal/intern/vm.h
+member.o: $(hdrdir)/ruby/internal/interpreter.h
+member.o: $(hdrdir)/ruby/internal/iterator.h
+member.o: $(hdrdir)/ruby/internal/memory.h
+member.o: $(hdrdir)/ruby/internal/method.h
+member.o: $(hdrdir)/ruby/internal/module.h
+member.o: $(hdrdir)/ruby/internal/newobj.h
+member.o: $(hdrdir)/ruby/internal/rgengc.h
+member.o: $(hdrdir)/ruby/internal/scan_args.h
+member.o: $(hdrdir)/ruby/internal/special_consts.h
+member.o: $(hdrdir)/ruby/internal/static_assert.h
+member.o: $(hdrdir)/ruby/internal/stdalign.h
+member.o: $(hdrdir)/ruby/internal/stdbool.h
+member.o: $(hdrdir)/ruby/internal/symbol.h
+member.o: $(hdrdir)/ruby/internal/token_paste.h
+member.o: $(hdrdir)/ruby/internal/value.h
+member.o: $(hdrdir)/ruby/internal/value_type.h
+member.o: $(hdrdir)/ruby/internal/variable.h
+member.o: $(hdrdir)/ruby/internal/warning_push.h
+member.o: $(hdrdir)/ruby/internal/xmalloc.h
member.o: $(hdrdir)/ruby/assert.h
member.o: $(hdrdir)/ruby/backward.h
+member.o: $(hdrdir)/ruby/backward/2/assume.h
+member.o: $(hdrdir)/ruby/backward/2/attributes.h
+member.o: $(hdrdir)/ruby/backward/2/bool.h
+member.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+member.o: $(hdrdir)/ruby/backward/2/inttypes.h
+member.o: $(hdrdir)/ruby/backward/2/limits.h
+member.o: $(hdrdir)/ruby/backward/2/long_long.h
+member.o: $(hdrdir)/ruby/backward/2/stdalign.h
+member.o: $(hdrdir)/ruby/backward/2/stdarg.h
member.o: $(hdrdir)/ruby/defines.h
member.o: $(hdrdir)/ruby/intern.h
member.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/symbol/depend b/ext/-test-/symbol/depend
index bccb4afc15..22d8ca5d23 100644
--- a/ext/-test-/symbol/depend
+++ b/ext/-test-/symbol/depend
@@ -2,8 +2,157 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -14,8 +163,157 @@ init.o: init.c
type.o: $(RUBY_EXTCONF_H)
type.o: $(arch_hdrdir)/ruby/config.h
type.o: $(hdrdir)/ruby.h
+type.o: $(hdrdir)/ruby/internal/anyargs.h
+type.o: $(hdrdir)/ruby/internal/arithmetic.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+type.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+type.o: $(hdrdir)/ruby/internal/assume.h
+type.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+type.o: $(hdrdir)/ruby/internal/attr/artificial.h
+type.o: $(hdrdir)/ruby/internal/attr/cold.h
+type.o: $(hdrdir)/ruby/internal/attr/const.h
+type.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+type.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+type.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+type.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+type.o: $(hdrdir)/ruby/internal/attr/error.h
+type.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+type.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+type.o: $(hdrdir)/ruby/internal/attr/format.h
+type.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+type.o: $(hdrdir)/ruby/internal/attr/noalias.h
+type.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+type.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+type.o: $(hdrdir)/ruby/internal/attr/noinline.h
+type.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+type.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+type.o: $(hdrdir)/ruby/internal/attr/pure.h
+type.o: $(hdrdir)/ruby/internal/attr/restrict.h
+type.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+type.o: $(hdrdir)/ruby/internal/attr/warning.h
+type.o: $(hdrdir)/ruby/internal/attr/weakref.h
+type.o: $(hdrdir)/ruby/internal/cast.h
+type.o: $(hdrdir)/ruby/internal/compiler_is.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+type.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+type.o: $(hdrdir)/ruby/internal/compiler_since.h
+type.o: $(hdrdir)/ruby/internal/config.h
+type.o: $(hdrdir)/ruby/internal/constant_p.h
+type.o: $(hdrdir)/ruby/internal/core.h
+type.o: $(hdrdir)/ruby/internal/core/rarray.h
+type.o: $(hdrdir)/ruby/internal/core/rbasic.h
+type.o: $(hdrdir)/ruby/internal/core/rbignum.h
+type.o: $(hdrdir)/ruby/internal/core/rclass.h
+type.o: $(hdrdir)/ruby/internal/core/rdata.h
+type.o: $(hdrdir)/ruby/internal/core/rfile.h
+type.o: $(hdrdir)/ruby/internal/core/rhash.h
+type.o: $(hdrdir)/ruby/internal/core/robject.h
+type.o: $(hdrdir)/ruby/internal/core/rregexp.h
+type.o: $(hdrdir)/ruby/internal/core/rstring.h
+type.o: $(hdrdir)/ruby/internal/core/rstruct.h
+type.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+type.o: $(hdrdir)/ruby/internal/ctype.h
+type.o: $(hdrdir)/ruby/internal/dllexport.h
+type.o: $(hdrdir)/ruby/internal/dosish.h
+type.o: $(hdrdir)/ruby/internal/error.h
+type.o: $(hdrdir)/ruby/internal/eval.h
+type.o: $(hdrdir)/ruby/internal/event.h
+type.o: $(hdrdir)/ruby/internal/fl_type.h
+type.o: $(hdrdir)/ruby/internal/gc.h
+type.o: $(hdrdir)/ruby/internal/glob.h
+type.o: $(hdrdir)/ruby/internal/globals.h
+type.o: $(hdrdir)/ruby/internal/has/attribute.h
+type.o: $(hdrdir)/ruby/internal/has/builtin.h
+type.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+type.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+type.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+type.o: $(hdrdir)/ruby/internal/has/extension.h
+type.o: $(hdrdir)/ruby/internal/has/feature.h
+type.o: $(hdrdir)/ruby/internal/has/warning.h
+type.o: $(hdrdir)/ruby/internal/intern/array.h
+type.o: $(hdrdir)/ruby/internal/intern/bignum.h
+type.o: $(hdrdir)/ruby/internal/intern/class.h
+type.o: $(hdrdir)/ruby/internal/intern/compar.h
+type.o: $(hdrdir)/ruby/internal/intern/complex.h
+type.o: $(hdrdir)/ruby/internal/intern/cont.h
+type.o: $(hdrdir)/ruby/internal/intern/dir.h
+type.o: $(hdrdir)/ruby/internal/intern/enum.h
+type.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+type.o: $(hdrdir)/ruby/internal/intern/error.h
+type.o: $(hdrdir)/ruby/internal/intern/eval.h
+type.o: $(hdrdir)/ruby/internal/intern/file.h
+type.o: $(hdrdir)/ruby/internal/intern/gc.h
+type.o: $(hdrdir)/ruby/internal/intern/hash.h
+type.o: $(hdrdir)/ruby/internal/intern/io.h
+type.o: $(hdrdir)/ruby/internal/intern/load.h
+type.o: $(hdrdir)/ruby/internal/intern/marshal.h
+type.o: $(hdrdir)/ruby/internal/intern/numeric.h
+type.o: $(hdrdir)/ruby/internal/intern/object.h
+type.o: $(hdrdir)/ruby/internal/intern/parse.h
+type.o: $(hdrdir)/ruby/internal/intern/proc.h
+type.o: $(hdrdir)/ruby/internal/intern/process.h
+type.o: $(hdrdir)/ruby/internal/intern/random.h
+type.o: $(hdrdir)/ruby/internal/intern/range.h
+type.o: $(hdrdir)/ruby/internal/intern/rational.h
+type.o: $(hdrdir)/ruby/internal/intern/re.h
+type.o: $(hdrdir)/ruby/internal/intern/ruby.h
+type.o: $(hdrdir)/ruby/internal/intern/select.h
+type.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+type.o: $(hdrdir)/ruby/internal/intern/signal.h
+type.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+type.o: $(hdrdir)/ruby/internal/intern/string.h
+type.o: $(hdrdir)/ruby/internal/intern/struct.h
+type.o: $(hdrdir)/ruby/internal/intern/thread.h
+type.o: $(hdrdir)/ruby/internal/intern/time.h
+type.o: $(hdrdir)/ruby/internal/intern/variable.h
+type.o: $(hdrdir)/ruby/internal/intern/vm.h
+type.o: $(hdrdir)/ruby/internal/interpreter.h
+type.o: $(hdrdir)/ruby/internal/iterator.h
+type.o: $(hdrdir)/ruby/internal/memory.h
+type.o: $(hdrdir)/ruby/internal/method.h
+type.o: $(hdrdir)/ruby/internal/module.h
+type.o: $(hdrdir)/ruby/internal/newobj.h
+type.o: $(hdrdir)/ruby/internal/rgengc.h
+type.o: $(hdrdir)/ruby/internal/scan_args.h
+type.o: $(hdrdir)/ruby/internal/special_consts.h
+type.o: $(hdrdir)/ruby/internal/static_assert.h
+type.o: $(hdrdir)/ruby/internal/stdalign.h
+type.o: $(hdrdir)/ruby/internal/stdbool.h
+type.o: $(hdrdir)/ruby/internal/symbol.h
+type.o: $(hdrdir)/ruby/internal/token_paste.h
+type.o: $(hdrdir)/ruby/internal/value.h
+type.o: $(hdrdir)/ruby/internal/value_type.h
+type.o: $(hdrdir)/ruby/internal/variable.h
+type.o: $(hdrdir)/ruby/internal/warning_push.h
+type.o: $(hdrdir)/ruby/internal/xmalloc.h
type.o: $(hdrdir)/ruby/assert.h
type.o: $(hdrdir)/ruby/backward.h
+type.o: $(hdrdir)/ruby/backward/2/assume.h
+type.o: $(hdrdir)/ruby/backward/2/attributes.h
+type.o: $(hdrdir)/ruby/backward/2/bool.h
+type.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+type.o: $(hdrdir)/ruby/backward/2/inttypes.h
+type.o: $(hdrdir)/ruby/backward/2/limits.h
+type.o: $(hdrdir)/ruby/backward/2/long_long.h
+type.o: $(hdrdir)/ruby/backward/2/stdalign.h
+type.o: $(hdrdir)/ruby/backward/2/stdarg.h
type.o: $(hdrdir)/ruby/defines.h
type.o: $(hdrdir)/ruby/intern.h
type.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/thread_fd_close/depend b/ext/-test-/thread_fd_close/depend
index 8c49c2d4fe..b04bfe7deb 100644
--- a/ext/-test-/thread_fd_close/depend
+++ b/ext/-test-/thread_fd_close/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
thread_fd_close.o: $(RUBY_EXTCONF_H)
thread_fd_close.o: $(arch_hdrdir)/ruby/config.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/anyargs.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/assume.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/artificial.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/cold.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/const.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/error.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/format.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/noalias.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/noinline.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/pure.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/restrict.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/warning.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/attr/weakref.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/cast.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/compiler_is.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/compiler_since.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/config.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/constant_p.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rarray.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rbasic.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rbignum.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rclass.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rdata.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rfile.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rhash.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/robject.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rregexp.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rstring.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rstruct.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/ctype.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/dllexport.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/dosish.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/error.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/eval.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/event.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/fl_type.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/gc.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/glob.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/globals.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/has/attribute.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/has/builtin.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/has/extension.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/has/feature.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/has/warning.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/array.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/bignum.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/class.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/compar.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/complex.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/cont.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/dir.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/enum.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/error.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/eval.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/file.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/gc.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/hash.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/io.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/load.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/marshal.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/numeric.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/object.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/parse.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/proc.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/process.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/random.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/range.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/rational.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/re.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/ruby.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/select.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/signal.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/string.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/struct.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/thread.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/time.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/variable.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/intern/vm.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/interpreter.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/iterator.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/memory.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/method.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/module.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/newobj.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/rgengc.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/scan_args.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/special_consts.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/static_assert.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/stdalign.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/stdbool.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/symbol.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/token_paste.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/value.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/value_type.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/variable.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/warning_push.h
+thread_fd_close.o: $(hdrdir)/ruby/internal/xmalloc.h
thread_fd_close.o: $(hdrdir)/ruby/assert.h
thread_fd_close.o: $(hdrdir)/ruby/backward.h
+thread_fd_close.o: $(hdrdir)/ruby/backward/2/assume.h
+thread_fd_close.o: $(hdrdir)/ruby/backward/2/attributes.h
+thread_fd_close.o: $(hdrdir)/ruby/backward/2/bool.h
+thread_fd_close.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+thread_fd_close.o: $(hdrdir)/ruby/backward/2/inttypes.h
+thread_fd_close.o: $(hdrdir)/ruby/backward/2/limits.h
+thread_fd_close.o: $(hdrdir)/ruby/backward/2/long_long.h
+thread_fd_close.o: $(hdrdir)/ruby/backward/2/stdalign.h
+thread_fd_close.o: $(hdrdir)/ruby/backward/2/stdarg.h
thread_fd_close.o: $(hdrdir)/ruby/defines.h
thread_fd_close.o: $(hdrdir)/ruby/intern.h
thread_fd_close.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/time/depend b/ext/-test-/time/depend
index 2f4b8d1f13..a3f1ea235b 100644
--- a/ext/-test-/time/depend
+++ b/ext/-test-/time/depend
@@ -2,8 +2,157 @@
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/intern.h
init.o: $(hdrdir)/ruby/missing.h
@@ -14,20 +163,322 @@ init.o: init.c
leap_second.o: $(RUBY_EXTCONF_H)
leap_second.o: $(arch_hdrdir)/ruby/config.h
leap_second.o: $(hdrdir)/ruby.h
+leap_second.o: $(hdrdir)/ruby/internal/anyargs.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+leap_second.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+leap_second.o: $(hdrdir)/ruby/internal/assume.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/artificial.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/cold.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/const.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/error.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/format.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/noalias.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/noinline.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/pure.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/restrict.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/warning.h
+leap_second.o: $(hdrdir)/ruby/internal/attr/weakref.h
+leap_second.o: $(hdrdir)/ruby/internal/cast.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+leap_second.o: $(hdrdir)/ruby/internal/compiler_since.h
+leap_second.o: $(hdrdir)/ruby/internal/config.h
+leap_second.o: $(hdrdir)/ruby/internal/constant_p.h
+leap_second.o: $(hdrdir)/ruby/internal/core.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rarray.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rbasic.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rbignum.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rclass.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rdata.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rfile.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rhash.h
+leap_second.o: $(hdrdir)/ruby/internal/core/robject.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rregexp.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rstring.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rstruct.h
+leap_second.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+leap_second.o: $(hdrdir)/ruby/internal/ctype.h
+leap_second.o: $(hdrdir)/ruby/internal/dllexport.h
+leap_second.o: $(hdrdir)/ruby/internal/dosish.h
+leap_second.o: $(hdrdir)/ruby/internal/error.h
+leap_second.o: $(hdrdir)/ruby/internal/eval.h
+leap_second.o: $(hdrdir)/ruby/internal/event.h
+leap_second.o: $(hdrdir)/ruby/internal/fl_type.h
+leap_second.o: $(hdrdir)/ruby/internal/gc.h
+leap_second.o: $(hdrdir)/ruby/internal/glob.h
+leap_second.o: $(hdrdir)/ruby/internal/globals.h
+leap_second.o: $(hdrdir)/ruby/internal/has/attribute.h
+leap_second.o: $(hdrdir)/ruby/internal/has/builtin.h
+leap_second.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+leap_second.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+leap_second.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+leap_second.o: $(hdrdir)/ruby/internal/has/extension.h
+leap_second.o: $(hdrdir)/ruby/internal/has/feature.h
+leap_second.o: $(hdrdir)/ruby/internal/has/warning.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/array.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/bignum.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/class.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/compar.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/complex.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/cont.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/dir.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/enum.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/error.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/eval.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/file.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/gc.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/hash.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/io.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/load.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/marshal.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/numeric.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/object.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/parse.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/proc.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/process.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/random.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/range.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/rational.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/re.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/ruby.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/select.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/signal.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/string.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/struct.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/thread.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/time.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/variable.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/vm.h
+leap_second.o: $(hdrdir)/ruby/internal/interpreter.h
+leap_second.o: $(hdrdir)/ruby/internal/iterator.h
+leap_second.o: $(hdrdir)/ruby/internal/memory.h
+leap_second.o: $(hdrdir)/ruby/internal/method.h
+leap_second.o: $(hdrdir)/ruby/internal/module.h
+leap_second.o: $(hdrdir)/ruby/internal/newobj.h
+leap_second.o: $(hdrdir)/ruby/internal/rgengc.h
+leap_second.o: $(hdrdir)/ruby/internal/scan_args.h
+leap_second.o: $(hdrdir)/ruby/internal/special_consts.h
+leap_second.o: $(hdrdir)/ruby/internal/static_assert.h
+leap_second.o: $(hdrdir)/ruby/internal/stdalign.h
+leap_second.o: $(hdrdir)/ruby/internal/stdbool.h
+leap_second.o: $(hdrdir)/ruby/internal/symbol.h
+leap_second.o: $(hdrdir)/ruby/internal/token_paste.h
+leap_second.o: $(hdrdir)/ruby/internal/value.h
+leap_second.o: $(hdrdir)/ruby/internal/value_type.h
+leap_second.o: $(hdrdir)/ruby/internal/variable.h
+leap_second.o: $(hdrdir)/ruby/internal/warning_push.h
+leap_second.o: $(hdrdir)/ruby/internal/xmalloc.h
leap_second.o: $(hdrdir)/ruby/assert.h
leap_second.o: $(hdrdir)/ruby/backward.h
+leap_second.o: $(hdrdir)/ruby/backward/2/assume.h
+leap_second.o: $(hdrdir)/ruby/backward/2/attributes.h
+leap_second.o: $(hdrdir)/ruby/backward/2/bool.h
+leap_second.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+leap_second.o: $(hdrdir)/ruby/backward/2/inttypes.h
+leap_second.o: $(hdrdir)/ruby/backward/2/limits.h
+leap_second.o: $(hdrdir)/ruby/backward/2/long_long.h
+leap_second.o: $(hdrdir)/ruby/backward/2/stdalign.h
+leap_second.o: $(hdrdir)/ruby/backward/2/stdarg.h
leap_second.o: $(hdrdir)/ruby/defines.h
leap_second.o: $(hdrdir)/ruby/intern.h
leap_second.o: $(hdrdir)/ruby/missing.h
leap_second.o: $(hdrdir)/ruby/ruby.h
leap_second.o: $(hdrdir)/ruby/st.h
leap_second.o: $(hdrdir)/ruby/subst.h
+leap_second.o: $(top_srcdir)/internal/bits.h
+leap_second.o: $(top_srcdir)/internal/compilers.h
+leap_second.o: $(top_srcdir)/internal/static_assert.h
+leap_second.o: $(top_srcdir)/internal/time.h
leap_second.o: leap_second.c
new.o: $(RUBY_EXTCONF_H)
new.o: $(arch_hdrdir)/ruby/config.h
new.o: $(hdrdir)/ruby.h
+new.o: $(hdrdir)/ruby/internal/anyargs.h
+new.o: $(hdrdir)/ruby/internal/arithmetic.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+new.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+new.o: $(hdrdir)/ruby/internal/assume.h
+new.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+new.o: $(hdrdir)/ruby/internal/attr/artificial.h
+new.o: $(hdrdir)/ruby/internal/attr/cold.h
+new.o: $(hdrdir)/ruby/internal/attr/const.h
+new.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+new.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+new.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+new.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+new.o: $(hdrdir)/ruby/internal/attr/error.h
+new.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+new.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+new.o: $(hdrdir)/ruby/internal/attr/format.h
+new.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+new.o: $(hdrdir)/ruby/internal/attr/noalias.h
+new.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+new.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+new.o: $(hdrdir)/ruby/internal/attr/noinline.h
+new.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+new.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+new.o: $(hdrdir)/ruby/internal/attr/pure.h
+new.o: $(hdrdir)/ruby/internal/attr/restrict.h
+new.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+new.o: $(hdrdir)/ruby/internal/attr/warning.h
+new.o: $(hdrdir)/ruby/internal/attr/weakref.h
+new.o: $(hdrdir)/ruby/internal/cast.h
+new.o: $(hdrdir)/ruby/internal/compiler_is.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+new.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+new.o: $(hdrdir)/ruby/internal/compiler_since.h
+new.o: $(hdrdir)/ruby/internal/config.h
+new.o: $(hdrdir)/ruby/internal/constant_p.h
+new.o: $(hdrdir)/ruby/internal/core.h
+new.o: $(hdrdir)/ruby/internal/core/rarray.h
+new.o: $(hdrdir)/ruby/internal/core/rbasic.h
+new.o: $(hdrdir)/ruby/internal/core/rbignum.h
+new.o: $(hdrdir)/ruby/internal/core/rclass.h
+new.o: $(hdrdir)/ruby/internal/core/rdata.h
+new.o: $(hdrdir)/ruby/internal/core/rfile.h
+new.o: $(hdrdir)/ruby/internal/core/rhash.h
+new.o: $(hdrdir)/ruby/internal/core/robject.h
+new.o: $(hdrdir)/ruby/internal/core/rregexp.h
+new.o: $(hdrdir)/ruby/internal/core/rstring.h
+new.o: $(hdrdir)/ruby/internal/core/rstruct.h
+new.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+new.o: $(hdrdir)/ruby/internal/ctype.h
+new.o: $(hdrdir)/ruby/internal/dllexport.h
+new.o: $(hdrdir)/ruby/internal/dosish.h
+new.o: $(hdrdir)/ruby/internal/error.h
+new.o: $(hdrdir)/ruby/internal/eval.h
+new.o: $(hdrdir)/ruby/internal/event.h
+new.o: $(hdrdir)/ruby/internal/fl_type.h
+new.o: $(hdrdir)/ruby/internal/gc.h
+new.o: $(hdrdir)/ruby/internal/glob.h
+new.o: $(hdrdir)/ruby/internal/globals.h
+new.o: $(hdrdir)/ruby/internal/has/attribute.h
+new.o: $(hdrdir)/ruby/internal/has/builtin.h
+new.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+new.o: $(hdrdir)/ruby/internal/has/extension.h
+new.o: $(hdrdir)/ruby/internal/has/feature.h
+new.o: $(hdrdir)/ruby/internal/has/warning.h
+new.o: $(hdrdir)/ruby/internal/intern/array.h
+new.o: $(hdrdir)/ruby/internal/intern/bignum.h
+new.o: $(hdrdir)/ruby/internal/intern/class.h
+new.o: $(hdrdir)/ruby/internal/intern/compar.h
+new.o: $(hdrdir)/ruby/internal/intern/complex.h
+new.o: $(hdrdir)/ruby/internal/intern/cont.h
+new.o: $(hdrdir)/ruby/internal/intern/dir.h
+new.o: $(hdrdir)/ruby/internal/intern/enum.h
+new.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+new.o: $(hdrdir)/ruby/internal/intern/error.h
+new.o: $(hdrdir)/ruby/internal/intern/eval.h
+new.o: $(hdrdir)/ruby/internal/intern/file.h
+new.o: $(hdrdir)/ruby/internal/intern/gc.h
+new.o: $(hdrdir)/ruby/internal/intern/hash.h
+new.o: $(hdrdir)/ruby/internal/intern/io.h
+new.o: $(hdrdir)/ruby/internal/intern/load.h
+new.o: $(hdrdir)/ruby/internal/intern/marshal.h
+new.o: $(hdrdir)/ruby/internal/intern/numeric.h
+new.o: $(hdrdir)/ruby/internal/intern/object.h
+new.o: $(hdrdir)/ruby/internal/intern/parse.h
+new.o: $(hdrdir)/ruby/internal/intern/proc.h
+new.o: $(hdrdir)/ruby/internal/intern/process.h
+new.o: $(hdrdir)/ruby/internal/intern/random.h
+new.o: $(hdrdir)/ruby/internal/intern/range.h
+new.o: $(hdrdir)/ruby/internal/intern/rational.h
+new.o: $(hdrdir)/ruby/internal/intern/re.h
+new.o: $(hdrdir)/ruby/internal/intern/ruby.h
+new.o: $(hdrdir)/ruby/internal/intern/select.h
+new.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+new.o: $(hdrdir)/ruby/internal/intern/signal.h
+new.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+new.o: $(hdrdir)/ruby/internal/intern/string.h
+new.o: $(hdrdir)/ruby/internal/intern/struct.h
+new.o: $(hdrdir)/ruby/internal/intern/thread.h
+new.o: $(hdrdir)/ruby/internal/intern/time.h
+new.o: $(hdrdir)/ruby/internal/intern/variable.h
+new.o: $(hdrdir)/ruby/internal/intern/vm.h
+new.o: $(hdrdir)/ruby/internal/interpreter.h
+new.o: $(hdrdir)/ruby/internal/iterator.h
+new.o: $(hdrdir)/ruby/internal/memory.h
+new.o: $(hdrdir)/ruby/internal/method.h
+new.o: $(hdrdir)/ruby/internal/module.h
+new.o: $(hdrdir)/ruby/internal/newobj.h
+new.o: $(hdrdir)/ruby/internal/rgengc.h
+new.o: $(hdrdir)/ruby/internal/scan_args.h
+new.o: $(hdrdir)/ruby/internal/special_consts.h
+new.o: $(hdrdir)/ruby/internal/static_assert.h
+new.o: $(hdrdir)/ruby/internal/stdalign.h
+new.o: $(hdrdir)/ruby/internal/stdbool.h
+new.o: $(hdrdir)/ruby/internal/symbol.h
+new.o: $(hdrdir)/ruby/internal/token_paste.h
+new.o: $(hdrdir)/ruby/internal/value.h
+new.o: $(hdrdir)/ruby/internal/value_type.h
+new.o: $(hdrdir)/ruby/internal/variable.h
+new.o: $(hdrdir)/ruby/internal/warning_push.h
+new.o: $(hdrdir)/ruby/internal/xmalloc.h
new.o: $(hdrdir)/ruby/assert.h
new.o: $(hdrdir)/ruby/backward.h
+new.o: $(hdrdir)/ruby/backward/2/assume.h
+new.o: $(hdrdir)/ruby/backward/2/attributes.h
+new.o: $(hdrdir)/ruby/backward/2/bool.h
+new.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+new.o: $(hdrdir)/ruby/backward/2/inttypes.h
+new.o: $(hdrdir)/ruby/backward/2/limits.h
+new.o: $(hdrdir)/ruby/backward/2/long_long.h
+new.o: $(hdrdir)/ruby/backward/2/stdalign.h
+new.o: $(hdrdir)/ruby/backward/2/stdarg.h
new.o: $(hdrdir)/ruby/defines.h
new.o: $(hdrdir)/ruby/intern.h
new.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/time/leap_second.c b/ext/-test-/time/leap_second.c
index 7eed421b73..ccf38194f0 100644
--- a/ext/-test-/time/leap_second.c
+++ b/ext/-test-/time/leap_second.c
@@ -1,6 +1,5 @@
-#include "ruby.h"
+#include "internal/time.h"
-void ruby_reset_leap_second_info(void);
static VALUE
bug_time_s_reset_leap_second_info(VALUE klass)
{
diff --git a/ext/-test-/tracepoint/depend b/ext/-test-/tracepoint/depend
index b811df4472..ba409e88fe 100644
--- a/ext/-test-/tracepoint/depend
+++ b/ext/-test-/tracepoint/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
gc_hook.o: $(RUBY_EXTCONF_H)
gc_hook.o: $(arch_hdrdir)/ruby/config.h
+gc_hook.o: $(hdrdir)/ruby/internal/anyargs.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+gc_hook.o: $(hdrdir)/ruby/internal/assume.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/artificial.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/cold.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/const.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/error.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/format.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/noalias.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/noinline.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/pure.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/restrict.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/warning.h
+gc_hook.o: $(hdrdir)/ruby/internal/attr/weakref.h
+gc_hook.o: $(hdrdir)/ruby/internal/cast.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+gc_hook.o: $(hdrdir)/ruby/internal/compiler_since.h
+gc_hook.o: $(hdrdir)/ruby/internal/config.h
+gc_hook.o: $(hdrdir)/ruby/internal/constant_p.h
+gc_hook.o: $(hdrdir)/ruby/internal/core.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rarray.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rbasic.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rbignum.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rclass.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rdata.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rfile.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rhash.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/robject.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rregexp.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rstring.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rstruct.h
+gc_hook.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+gc_hook.o: $(hdrdir)/ruby/internal/ctype.h
+gc_hook.o: $(hdrdir)/ruby/internal/dllexport.h
+gc_hook.o: $(hdrdir)/ruby/internal/dosish.h
+gc_hook.o: $(hdrdir)/ruby/internal/error.h
+gc_hook.o: $(hdrdir)/ruby/internal/eval.h
+gc_hook.o: $(hdrdir)/ruby/internal/event.h
+gc_hook.o: $(hdrdir)/ruby/internal/fl_type.h
+gc_hook.o: $(hdrdir)/ruby/internal/gc.h
+gc_hook.o: $(hdrdir)/ruby/internal/glob.h
+gc_hook.o: $(hdrdir)/ruby/internal/globals.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/attribute.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/builtin.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/extension.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/feature.h
+gc_hook.o: $(hdrdir)/ruby/internal/has/warning.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/array.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/bignum.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/class.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/compar.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/complex.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/cont.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/dir.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/enum.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/error.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/eval.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/file.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/gc.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/hash.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/io.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/load.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/marshal.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/numeric.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/object.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/parse.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/proc.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/process.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/random.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/range.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/rational.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/re.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/ruby.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/select.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/signal.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/string.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/struct.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/thread.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/time.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/variable.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/vm.h
+gc_hook.o: $(hdrdir)/ruby/internal/interpreter.h
+gc_hook.o: $(hdrdir)/ruby/internal/iterator.h
+gc_hook.o: $(hdrdir)/ruby/internal/memory.h
+gc_hook.o: $(hdrdir)/ruby/internal/method.h
+gc_hook.o: $(hdrdir)/ruby/internal/module.h
+gc_hook.o: $(hdrdir)/ruby/internal/newobj.h
+gc_hook.o: $(hdrdir)/ruby/internal/rgengc.h
+gc_hook.o: $(hdrdir)/ruby/internal/scan_args.h
+gc_hook.o: $(hdrdir)/ruby/internal/special_consts.h
+gc_hook.o: $(hdrdir)/ruby/internal/static_assert.h
+gc_hook.o: $(hdrdir)/ruby/internal/stdalign.h
+gc_hook.o: $(hdrdir)/ruby/internal/stdbool.h
+gc_hook.o: $(hdrdir)/ruby/internal/symbol.h
+gc_hook.o: $(hdrdir)/ruby/internal/token_paste.h
+gc_hook.o: $(hdrdir)/ruby/internal/value.h
+gc_hook.o: $(hdrdir)/ruby/internal/value_type.h
+gc_hook.o: $(hdrdir)/ruby/internal/variable.h
+gc_hook.o: $(hdrdir)/ruby/internal/warning_push.h
+gc_hook.o: $(hdrdir)/ruby/internal/xmalloc.h
gc_hook.o: $(hdrdir)/ruby/assert.h
gc_hook.o: $(hdrdir)/ruby/backward.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/assume.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/attributes.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/bool.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/inttypes.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/limits.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/long_long.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/stdalign.h
+gc_hook.o: $(hdrdir)/ruby/backward/2/stdarg.h
gc_hook.o: $(hdrdir)/ruby/debug.h
gc_hook.o: $(hdrdir)/ruby/defines.h
gc_hook.o: $(hdrdir)/ruby/intern.h
@@ -13,8 +162,157 @@ gc_hook.o: $(hdrdir)/ruby/subst.h
gc_hook.o: gc_hook.c
tracepoint.o: $(RUBY_EXTCONF_H)
tracepoint.o: $(arch_hdrdir)/ruby/config.h
+tracepoint.o: $(hdrdir)/ruby/internal/anyargs.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+tracepoint.o: $(hdrdir)/ruby/internal/assume.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/artificial.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/cold.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/const.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/error.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/format.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/noalias.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/noinline.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/pure.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/restrict.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/warning.h
+tracepoint.o: $(hdrdir)/ruby/internal/attr/weakref.h
+tracepoint.o: $(hdrdir)/ruby/internal/cast.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+tracepoint.o: $(hdrdir)/ruby/internal/compiler_since.h
+tracepoint.o: $(hdrdir)/ruby/internal/config.h
+tracepoint.o: $(hdrdir)/ruby/internal/constant_p.h
+tracepoint.o: $(hdrdir)/ruby/internal/core.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rarray.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rbasic.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rbignum.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rclass.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rdata.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rfile.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rhash.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/robject.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rregexp.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rstring.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rstruct.h
+tracepoint.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+tracepoint.o: $(hdrdir)/ruby/internal/ctype.h
+tracepoint.o: $(hdrdir)/ruby/internal/dllexport.h
+tracepoint.o: $(hdrdir)/ruby/internal/dosish.h
+tracepoint.o: $(hdrdir)/ruby/internal/error.h
+tracepoint.o: $(hdrdir)/ruby/internal/eval.h
+tracepoint.o: $(hdrdir)/ruby/internal/event.h
+tracepoint.o: $(hdrdir)/ruby/internal/fl_type.h
+tracepoint.o: $(hdrdir)/ruby/internal/gc.h
+tracepoint.o: $(hdrdir)/ruby/internal/glob.h
+tracepoint.o: $(hdrdir)/ruby/internal/globals.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/attribute.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/builtin.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/extension.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/feature.h
+tracepoint.o: $(hdrdir)/ruby/internal/has/warning.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/array.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/bignum.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/class.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/compar.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/complex.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/cont.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/dir.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/enum.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/error.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/eval.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/file.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/gc.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/hash.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/io.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/load.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/marshal.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/numeric.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/object.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/parse.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/proc.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/process.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/random.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/range.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/rational.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/re.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/ruby.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/select.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/signal.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/string.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/struct.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/thread.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/time.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/variable.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/vm.h
+tracepoint.o: $(hdrdir)/ruby/internal/interpreter.h
+tracepoint.o: $(hdrdir)/ruby/internal/iterator.h
+tracepoint.o: $(hdrdir)/ruby/internal/memory.h
+tracepoint.o: $(hdrdir)/ruby/internal/method.h
+tracepoint.o: $(hdrdir)/ruby/internal/module.h
+tracepoint.o: $(hdrdir)/ruby/internal/newobj.h
+tracepoint.o: $(hdrdir)/ruby/internal/rgengc.h
+tracepoint.o: $(hdrdir)/ruby/internal/scan_args.h
+tracepoint.o: $(hdrdir)/ruby/internal/special_consts.h
+tracepoint.o: $(hdrdir)/ruby/internal/static_assert.h
+tracepoint.o: $(hdrdir)/ruby/internal/stdalign.h
+tracepoint.o: $(hdrdir)/ruby/internal/stdbool.h
+tracepoint.o: $(hdrdir)/ruby/internal/symbol.h
+tracepoint.o: $(hdrdir)/ruby/internal/token_paste.h
+tracepoint.o: $(hdrdir)/ruby/internal/value.h
+tracepoint.o: $(hdrdir)/ruby/internal/value_type.h
+tracepoint.o: $(hdrdir)/ruby/internal/variable.h
+tracepoint.o: $(hdrdir)/ruby/internal/warning_push.h
+tracepoint.o: $(hdrdir)/ruby/internal/xmalloc.h
tracepoint.o: $(hdrdir)/ruby/assert.h
tracepoint.o: $(hdrdir)/ruby/backward.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/assume.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/attributes.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/bool.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/inttypes.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/limits.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/long_long.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/stdalign.h
+tracepoint.o: $(hdrdir)/ruby/backward/2/stdarg.h
tracepoint.o: $(hdrdir)/ruby/debug.h
tracepoint.o: $(hdrdir)/ruby/defines.h
tracepoint.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/-test-/tracepoint/gc_hook.c b/ext/-test-/tracepoint/gc_hook.c
index 54b469dcad..5fd46fa518 100644
--- a/ext/-test-/tracepoint/gc_hook.c
+++ b/ext/-test-/tracepoint/gc_hook.c
@@ -42,14 +42,12 @@ set_gc_hook(VALUE module, VALUE proc, rb_event_flag_t event, const char *tp_str,
{
VALUE tpval;
ID tp_key = rb_intern(tp_str);
- ID proc_key = rb_intern(proc_str);
/* disable previous keys */
if (rb_ivar_defined(module, tp_key) != 0 &&
RTEST(tpval = rb_ivar_get(module, tp_key))) {
rb_tracepoint_disable(tpval);
rb_ivar_set(module, tp_key, Qnil);
- rb_ivar_set(module, proc_key, Qnil);
}
if (RTEST(proc)) {
@@ -59,7 +57,6 @@ set_gc_hook(VALUE module, VALUE proc, rb_event_flag_t event, const char *tp_str,
tpval = rb_tracepoint_new(0, event, gc_start_end_i, (void *)proc);
rb_ivar_set(module, tp_key, tpval);
- rb_ivar_set(module, proc_key, proc); /* GC guard */
rb_tracepoint_enable(tpval);
}
diff --git a/ext/-test-/typeddata/depend b/ext/-test-/typeddata/depend
index e0dd0653a8..8fe35a8192 100644
--- a/ext/-test-/typeddata/depend
+++ b/ext/-test-/typeddata/depend
@@ -2,8 +2,157 @@
typeddata.o: $(RUBY_EXTCONF_H)
typeddata.o: $(arch_hdrdir)/ruby/config.h
typeddata.o: $(hdrdir)/ruby.h
+typeddata.o: $(hdrdir)/ruby/internal/anyargs.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+typeddata.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+typeddata.o: $(hdrdir)/ruby/internal/assume.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/artificial.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/cold.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/const.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/error.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/format.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/noalias.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/noinline.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/pure.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/restrict.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/warning.h
+typeddata.o: $(hdrdir)/ruby/internal/attr/weakref.h
+typeddata.o: $(hdrdir)/ruby/internal/cast.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+typeddata.o: $(hdrdir)/ruby/internal/compiler_since.h
+typeddata.o: $(hdrdir)/ruby/internal/config.h
+typeddata.o: $(hdrdir)/ruby/internal/constant_p.h
+typeddata.o: $(hdrdir)/ruby/internal/core.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rarray.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rbasic.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rbignum.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rclass.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rdata.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rfile.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rhash.h
+typeddata.o: $(hdrdir)/ruby/internal/core/robject.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rregexp.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rstring.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rstruct.h
+typeddata.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+typeddata.o: $(hdrdir)/ruby/internal/ctype.h
+typeddata.o: $(hdrdir)/ruby/internal/dllexport.h
+typeddata.o: $(hdrdir)/ruby/internal/dosish.h
+typeddata.o: $(hdrdir)/ruby/internal/error.h
+typeddata.o: $(hdrdir)/ruby/internal/eval.h
+typeddata.o: $(hdrdir)/ruby/internal/event.h
+typeddata.o: $(hdrdir)/ruby/internal/fl_type.h
+typeddata.o: $(hdrdir)/ruby/internal/gc.h
+typeddata.o: $(hdrdir)/ruby/internal/glob.h
+typeddata.o: $(hdrdir)/ruby/internal/globals.h
+typeddata.o: $(hdrdir)/ruby/internal/has/attribute.h
+typeddata.o: $(hdrdir)/ruby/internal/has/builtin.h
+typeddata.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+typeddata.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+typeddata.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+typeddata.o: $(hdrdir)/ruby/internal/has/extension.h
+typeddata.o: $(hdrdir)/ruby/internal/has/feature.h
+typeddata.o: $(hdrdir)/ruby/internal/has/warning.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/array.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/bignum.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/class.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/compar.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/complex.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/cont.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/dir.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/enum.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/error.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/eval.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/file.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/gc.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/hash.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/io.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/load.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/marshal.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/numeric.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/object.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/parse.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/proc.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/process.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/random.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/range.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/rational.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/re.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/ruby.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/select.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/signal.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/string.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/struct.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/thread.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/time.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/variable.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/vm.h
+typeddata.o: $(hdrdir)/ruby/internal/interpreter.h
+typeddata.o: $(hdrdir)/ruby/internal/iterator.h
+typeddata.o: $(hdrdir)/ruby/internal/memory.h
+typeddata.o: $(hdrdir)/ruby/internal/method.h
+typeddata.o: $(hdrdir)/ruby/internal/module.h
+typeddata.o: $(hdrdir)/ruby/internal/newobj.h
+typeddata.o: $(hdrdir)/ruby/internal/rgengc.h
+typeddata.o: $(hdrdir)/ruby/internal/scan_args.h
+typeddata.o: $(hdrdir)/ruby/internal/special_consts.h
+typeddata.o: $(hdrdir)/ruby/internal/static_assert.h
+typeddata.o: $(hdrdir)/ruby/internal/stdalign.h
+typeddata.o: $(hdrdir)/ruby/internal/stdbool.h
+typeddata.o: $(hdrdir)/ruby/internal/symbol.h
+typeddata.o: $(hdrdir)/ruby/internal/token_paste.h
+typeddata.o: $(hdrdir)/ruby/internal/value.h
+typeddata.o: $(hdrdir)/ruby/internal/value_type.h
+typeddata.o: $(hdrdir)/ruby/internal/variable.h
+typeddata.o: $(hdrdir)/ruby/internal/warning_push.h
+typeddata.o: $(hdrdir)/ruby/internal/xmalloc.h
typeddata.o: $(hdrdir)/ruby/assert.h
typeddata.o: $(hdrdir)/ruby/backward.h
+typeddata.o: $(hdrdir)/ruby/backward/2/assume.h
+typeddata.o: $(hdrdir)/ruby/backward/2/attributes.h
+typeddata.o: $(hdrdir)/ruby/backward/2/bool.h
+typeddata.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+typeddata.o: $(hdrdir)/ruby/backward/2/inttypes.h
+typeddata.o: $(hdrdir)/ruby/backward/2/limits.h
+typeddata.o: $(hdrdir)/ruby/backward/2/long_long.h
+typeddata.o: $(hdrdir)/ruby/backward/2/stdalign.h
+typeddata.o: $(hdrdir)/ruby/backward/2/stdarg.h
typeddata.o: $(hdrdir)/ruby/defines.h
typeddata.o: $(hdrdir)/ruby/intern.h
typeddata.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/typeddata/typeddata.c b/ext/-test-/typeddata/typeddata.c
index ae060960cd..2adfd56ae8 100644
--- a/ext/-test-/typeddata/typeddata.c
+++ b/ext/-test-/typeddata/typeddata.c
@@ -2,7 +2,7 @@
static const rb_data_type_t test_data = {
"typed_data",
- {NULL, ruby_xfree, NULL},
+ {0, ruby_xfree, 0},
NULL, NULL,
0/* deferred free */,
};
@@ -37,7 +37,7 @@ void
Init_typeddata(void)
{
VALUE mBug = rb_define_module("Bug");
- VALUE klass = rb_define_class_under(mBug, "TypedData", rb_cData);
+ VALUE klass = rb_define_class_under(mBug, "TypedData", rb_cObject);
rb_define_alloc_func(klass, test_alloc);
rb_define_singleton_method(klass, "check", test_check, 1);
rb_define_singleton_method(klass, "make", test_make, 1);
diff --git a/ext/-test-/vm/depend b/ext/-test-/vm/depend
index 0f85d69bb0..5800c3b464 100644
--- a/ext/-test-/vm/depend
+++ b/ext/-test-/vm/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
at_exit.o: $(RUBY_EXTCONF_H)
at_exit.o: $(arch_hdrdir)/ruby/config.h
+at_exit.o: $(hdrdir)/ruby/internal/anyargs.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+at_exit.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+at_exit.o: $(hdrdir)/ruby/internal/assume.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/artificial.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/cold.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/const.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/error.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/format.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/noalias.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/noinline.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/pure.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/restrict.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/warning.h
+at_exit.o: $(hdrdir)/ruby/internal/attr/weakref.h
+at_exit.o: $(hdrdir)/ruby/internal/cast.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+at_exit.o: $(hdrdir)/ruby/internal/compiler_since.h
+at_exit.o: $(hdrdir)/ruby/internal/config.h
+at_exit.o: $(hdrdir)/ruby/internal/constant_p.h
+at_exit.o: $(hdrdir)/ruby/internal/core.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rarray.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rbasic.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rbignum.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rclass.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rdata.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rfile.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rhash.h
+at_exit.o: $(hdrdir)/ruby/internal/core/robject.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rregexp.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rstring.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rstruct.h
+at_exit.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+at_exit.o: $(hdrdir)/ruby/internal/ctype.h
+at_exit.o: $(hdrdir)/ruby/internal/dllexport.h
+at_exit.o: $(hdrdir)/ruby/internal/dosish.h
+at_exit.o: $(hdrdir)/ruby/internal/error.h
+at_exit.o: $(hdrdir)/ruby/internal/eval.h
+at_exit.o: $(hdrdir)/ruby/internal/event.h
+at_exit.o: $(hdrdir)/ruby/internal/fl_type.h
+at_exit.o: $(hdrdir)/ruby/internal/gc.h
+at_exit.o: $(hdrdir)/ruby/internal/glob.h
+at_exit.o: $(hdrdir)/ruby/internal/globals.h
+at_exit.o: $(hdrdir)/ruby/internal/has/attribute.h
+at_exit.o: $(hdrdir)/ruby/internal/has/builtin.h
+at_exit.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+at_exit.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+at_exit.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+at_exit.o: $(hdrdir)/ruby/internal/has/extension.h
+at_exit.o: $(hdrdir)/ruby/internal/has/feature.h
+at_exit.o: $(hdrdir)/ruby/internal/has/warning.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/array.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/bignum.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/class.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/compar.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/complex.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/cont.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/dir.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/enum.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/error.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/eval.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/file.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/gc.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/hash.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/io.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/load.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/marshal.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/numeric.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/object.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/parse.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/proc.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/process.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/random.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/range.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/rational.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/re.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/ruby.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/select.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/signal.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/string.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/struct.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/thread.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/time.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/variable.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/vm.h
+at_exit.o: $(hdrdir)/ruby/internal/interpreter.h
+at_exit.o: $(hdrdir)/ruby/internal/iterator.h
+at_exit.o: $(hdrdir)/ruby/internal/memory.h
+at_exit.o: $(hdrdir)/ruby/internal/method.h
+at_exit.o: $(hdrdir)/ruby/internal/module.h
+at_exit.o: $(hdrdir)/ruby/internal/newobj.h
+at_exit.o: $(hdrdir)/ruby/internal/rgengc.h
+at_exit.o: $(hdrdir)/ruby/internal/scan_args.h
+at_exit.o: $(hdrdir)/ruby/internal/special_consts.h
+at_exit.o: $(hdrdir)/ruby/internal/static_assert.h
+at_exit.o: $(hdrdir)/ruby/internal/stdalign.h
+at_exit.o: $(hdrdir)/ruby/internal/stdbool.h
+at_exit.o: $(hdrdir)/ruby/internal/symbol.h
+at_exit.o: $(hdrdir)/ruby/internal/token_paste.h
+at_exit.o: $(hdrdir)/ruby/internal/value.h
+at_exit.o: $(hdrdir)/ruby/internal/value_type.h
+at_exit.o: $(hdrdir)/ruby/internal/variable.h
+at_exit.o: $(hdrdir)/ruby/internal/warning_push.h
+at_exit.o: $(hdrdir)/ruby/internal/xmalloc.h
at_exit.o: $(hdrdir)/ruby/assert.h
at_exit.o: $(hdrdir)/ruby/backward.h
+at_exit.o: $(hdrdir)/ruby/backward/2/assume.h
+at_exit.o: $(hdrdir)/ruby/backward/2/attributes.h
+at_exit.o: $(hdrdir)/ruby/backward/2/bool.h
+at_exit.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+at_exit.o: $(hdrdir)/ruby/backward/2/inttypes.h
+at_exit.o: $(hdrdir)/ruby/backward/2/limits.h
+at_exit.o: $(hdrdir)/ruby/backward/2/long_long.h
+at_exit.o: $(hdrdir)/ruby/backward/2/stdalign.h
+at_exit.o: $(hdrdir)/ruby/backward/2/stdarg.h
at_exit.o: $(hdrdir)/ruby/defines.h
at_exit.o: $(hdrdir)/ruby/intern.h
at_exit.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/-test-/wait_for_single_fd/depend b/ext/-test-/wait_for_single_fd/depend
index 8549fca781..641e144017 100644
--- a/ext/-test-/wait_for_single_fd/depend
+++ b/ext/-test-/wait_for_single_fd/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
wait_for_single_fd.o: $(RUBY_EXTCONF_H)
wait_for_single_fd.o: $(arch_hdrdir)/ruby/config.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/anyargs.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/assume.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/artificial.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/cold.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/const.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/error.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/format.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/noalias.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/noinline.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/pure.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/restrict.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/warning.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/attr/weakref.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/cast.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/compiler_is.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/compiler_since.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/config.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/constant_p.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rarray.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rbasic.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rbignum.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rclass.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rdata.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rfile.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rhash.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/robject.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rregexp.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rstring.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rstruct.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/ctype.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/dllexport.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/dosish.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/error.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/eval.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/event.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/fl_type.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/gc.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/glob.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/globals.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/has/attribute.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/has/builtin.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/has/extension.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/has/feature.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/has/warning.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/array.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/bignum.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/class.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/compar.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/complex.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/cont.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/dir.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/enum.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/error.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/eval.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/file.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/gc.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/hash.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/io.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/load.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/marshal.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/numeric.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/object.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/parse.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/proc.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/process.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/random.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/range.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/rational.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/re.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/ruby.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/select.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/signal.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/string.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/struct.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/thread.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/time.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/variable.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/intern/vm.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/interpreter.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/iterator.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/memory.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/method.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/module.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/newobj.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/rgengc.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/scan_args.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/special_consts.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/static_assert.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/stdalign.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/stdbool.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/symbol.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/token_paste.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/value.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/value_type.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/variable.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/warning_push.h
+wait_for_single_fd.o: $(hdrdir)/ruby/internal/xmalloc.h
wait_for_single_fd.o: $(hdrdir)/ruby/assert.h
wait_for_single_fd.o: $(hdrdir)/ruby/backward.h
+wait_for_single_fd.o: $(hdrdir)/ruby/backward/2/assume.h
+wait_for_single_fd.o: $(hdrdir)/ruby/backward/2/attributes.h
+wait_for_single_fd.o: $(hdrdir)/ruby/backward/2/bool.h
+wait_for_single_fd.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+wait_for_single_fd.o: $(hdrdir)/ruby/backward/2/inttypes.h
+wait_for_single_fd.o: $(hdrdir)/ruby/backward/2/limits.h
+wait_for_single_fd.o: $(hdrdir)/ruby/backward/2/long_long.h
+wait_for_single_fd.o: $(hdrdir)/ruby/backward/2/stdalign.h
+wait_for_single_fd.o: $(hdrdir)/ruby/backward/2/stdarg.h
wait_for_single_fd.o: $(hdrdir)/ruby/defines.h
wait_for_single_fd.o: $(hdrdir)/ruby/encoding.h
wait_for_single_fd.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/-test-/wait_for_single_fd/extconf.rb b/ext/-test-/wait_for_single_fd/extconf.rb
index 2a976c8f4b..c27100fb42 100644
--- a/ext/-test-/wait_for_single_fd/extconf.rb
+++ b/ext/-test-/wait_for_single_fd/extconf.rb
@@ -1,4 +1,8 @@
# frozen_string_literal: false
-headers = %w(sys/types.h sys/time.h sys/event.h).select { |h| have_header(h) }
-have_func('kqueue', headers)
+case RUBY_PLATFORM when /mingw/ then
+ # skip
+else
+ headers = %w(sys/types.h sys/time.h sys/event.h).select { |h| have_header(h) }
+ have_func('kqueue', headers)
+end
create_makefile("-test-/wait_for_single_fd")
diff --git a/ext/.document b/ext/.document
index 354601569b..aeb40c60fb 100644
--- a/ext/.document
+++ b/ext/.document
@@ -2,9 +2,15 @@
bigdecimal/bigdecimal.c
bigdecimal/lib
+cgi/escape/escape.c
continuation/continuation.c
coverage/coverage.c
+coverage/lib
date/date_core.c
+date/date_parse.c
+date/date_strftime.c
+date/date_strptime.c
+date/lib
dbm/dbm.c
digest/bubblebabble/bubblebabble.c
digest/digest.c
@@ -13,6 +19,7 @@ digest/md5/md5init.c
digest/rmd160/rmd160init.c
digest/sha1/sha1init.c
digest/sha2/sha2init.c
+digest/sha2/lib
etc/etc.c
fcntl/fcntl.c
fiber/fiber.c
@@ -20,11 +27,13 @@ fiddle/closure.c
fiddle/conversions.c
fiddle/fiddle.c
fiddle/function.c
+fiddle/pinned.c
fiddle/pointer.c
fiddle/handle.c
fiddle/lib
gdbm/gdbm.c
io/console/console.c
+io/console/lib
io/nonblock/nonblock.c
io/wait/wait.c
json/generator/generator.c
@@ -37,6 +46,7 @@ nkf/nkf.c
objspace/objspace.c
objspace/objspace_dump.c
objspace/object_tracing.c
+objspace/lib
openssl/lib
openssl/ossl.c
openssl/ossl_asn1.c
@@ -60,6 +70,7 @@ openssl/ossl_pkey_rsa.c
openssl/ossl_rand.c
openssl/ossl_ssl.c
openssl/ossl_ssl_session.c
+openssl/ossl_ts.c
openssl/ossl_x509.c
openssl/ossl_x509attr.c
openssl/ossl_x509cert.c
@@ -80,14 +91,16 @@ psych/psych_yaml_tree.c
pty/lib
pty/pty.c
racc/cparse/cparse.c
+rbconfig/sizeof/*.c
readline/readline.c
ripper/lib
-sdbm/init.c
socket
stringio/stringio.c
strscan/strscan.c
syslog/syslog.c
syslog/lib
+win32/lib
+win32/resolv/*.c
win32ole/lib
win32ole/*.c
zlib/zlib.c
diff --git a/ext/Setup b/ext/Setup
index ac79c86f84..0376e2fc6c 100644
--- a/ext/Setup
+++ b/ext/Setup
@@ -33,7 +33,6 @@
#rbconfig/sizeof
#readline
#ripper
-#sdbm
#socket
#stringio
#strscan
diff --git a/ext/Setup.atheos b/ext/Setup.atheos
index 90a7d01348..3f6263b1e2 100644
--- a/ext/Setup.atheos
+++ b/ext/Setup.atheos
@@ -20,7 +20,6 @@ pty
racc/parse
readline
ripper
-sdbm
socket
stringio
strscan
diff --git a/ext/Setup.nt b/ext/Setup.nt
index fb5989b87f..dc36aa8688 100644
--- a/ext/Setup.nt
+++ b/ext/Setup.nt
@@ -21,7 +21,6 @@ nkf
racc/cparse
#readline
#ripper
-sdbm
socket
stringio
strscan
diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c
index 7ac883730d..7fdf40126e 100644
--- a/ext/bigdecimal/bigdecimal.c
+++ b/ext/bigdecimal/bigdecimal.c
@@ -14,6 +14,7 @@
#include "ruby/util.h"
#ifndef BIGDECIMAL_DEBUG
+# undef NDEBUG
# define NDEBUG
#endif
#include <assert.h>
@@ -24,7 +25,6 @@
#include <string.h>
#include <errno.h>
#include <math.h>
-#include "math.h"
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
@@ -77,7 +77,7 @@ static ID id_half;
#define BASE1 (BASE/10)
#ifndef DBLE_FIG
-#define DBLE_FIG (DBL_DIG+1) /* figure of double */
+#define DBLE_FIG rmpd_double_figures() /* figure of double */
#endif
#ifndef RRATIONAL_ZERO_P
@@ -127,6 +127,30 @@ rb_rational_den(VALUE rat)
}
#endif
+#ifndef HAVE_RB_COMPLEX_REAL
+static inline VALUE
+rb_complex_real(VALUE cmp)
+{
+#ifdef HAVE_TYPE_STRUCT_RCOMPLEX
+ return RCOMPLEX(cmp)->real;
+#else
+ return rb_funcall(cmp, rb_intern("real"), 0);
+#endif
+}
+#endif
+
+#ifndef HAVE_RB_COMPLEX_IMAG
+static inline VALUE
+rb_complex_imag(VALUE cmp)
+{
+#ifdef HAVE_TYPE_STRUCT_RCOMPLEX
+ return RCOMPLEX(cmp)->imag;
+#else
+ return rb_funcall(cmp, rb_intern("imag"), 0);
+#endif
+}
+#endif
+
#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
@@ -165,11 +189,16 @@ BigDecimal_memsize(const void *ptr)
return (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT));
}
+#ifndef HAVE_RB_EXT_RACTOR_SAFE
+# undef RUBY_TYPED_FROZEN_SHAREABLE
+# define RUBY_TYPED_FROZEN_SHAREABLE 0
+#endif
+
static const rb_data_type_t BigDecimal_data_type = {
"BigDecimal",
{ 0, BigDecimal_delete, BigDecimal_memsize, },
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE
#endif
};
@@ -228,7 +257,7 @@ again:
switch(TYPE(v)) {
case T_FLOAT:
if (prec < 0) goto unable_to_coerce_without_prec;
- if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
+ if (prec > (long)DBLE_FIG) goto SomeOneMayDoIt;
d = RFLOAT_VALUE(v);
if (!isfinite(d)) {
pv = VpCreateRbObject(1, NULL);
@@ -326,11 +355,13 @@ BigDecimal_double_fig(VALUE self)
/* call-seq:
* big_decimal.precs -> array
*
- * Returns an Array of two Integer values.
+ * Returns an Array of two Integer values that represent platform-dependent
+ * internal storage properties.
*
- * The first value is the current number of significant digits in the
- * BigDecimal. The second value is the maximum number of significant digits
- * for the BigDecimal.
+ * This method is deprecated and will be removed in the future.
+ * Instead, use BigDecimal#n_significant_digits for obtaining the number of
+ * significant digits in scientific notation, and BigDecimal#precision for
+ * obtaining the number of digits in decimal notation.
*
* BigDecimal('5').precs #=> [9, 18]
*/
@@ -342,13 +373,110 @@ BigDecimal_prec(VALUE self)
Real *p;
VALUE obj;
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
+ "BigDecimal#precs is deprecated and will be removed in the future; "
+ "use BigDecimal#precision instead.");
+
GUARD_OBJ(p, GetVpValue(self, 1));
- obj = rb_assoc_new(INT2NUM(p->Prec*VpBaseFig()),
- INT2NUM(p->MaxPrec*VpBaseFig()));
+ obj = rb_assoc_new(SIZET2NUM(p->Prec*VpBaseFig()),
+ SIZET2NUM(p->MaxPrec*VpBaseFig()));
return obj;
}
/*
+ * call-seq:
+ * big_decimal.precision -> intreger
+ *
+ * Returns the number of decimal digits in this number.
+ *
+ * Example:
+ *
+ * BigDecimal("0").precision # => 0
+ * BigDecimal("1").precision # => 1
+ * BigDecimal("-1e20").precision # => 21
+ * BigDecimal("1e-20").precision # => 20
+ * BigDecimal("Infinity").precision # => 0
+ * BigDecimal("-Infinity").precision # => 0
+ * BigDecimal("NaN").precision # => 0
+ */
+static VALUE
+BigDecimal_precision(VALUE self)
+{
+ ENTER(1);
+
+ Real *p;
+ GUARD_OBJ(p, GetVpValue(self, 1));
+
+ /*
+ * The most significant digit is frac[0], and the least significant digit is frac[Prec-1].
+ * When the exponent is zero, the decimal point is located just before frac[0].
+ * When the exponent is negative, the decimal point moves to leftward.
+ * Conversely, when the exponent is positive, the decimal point moves to rightward.
+ *
+ * | frac[0] frac[1] frac[2] . frac[3] frac[4] ... frac[Prec-1]
+ * |------------------------> exponent == 3
+ */
+
+ ssize_t ex = p->exponent;
+ ssize_t precision = 0;
+ if (ex < 0) {
+ precision = (-ex + 1) * BASE_FIG; /* 1 is for p->frac[0] */
+ ex = 0;
+ }
+ else if (p->Prec > 0) {
+ BDIGIT x = p->frac[0];
+ for (precision = 0; x > 0; x /= 10) {
+ ++precision;
+ }
+ }
+
+ if (ex > (ssize_t)p->Prec) {
+ precision += (ex - 1) * BASE_FIG;
+ }
+ else if (p->Prec > 0) {
+ ssize_t n = (ssize_t)p->Prec - 1;
+ while (n > 0 && p->frac[n] == 0) --n;
+
+ precision += n * BASE_FIG;
+
+ if (ex < (ssize_t)p->Prec) {
+ BDIGIT x = p->frac[n];
+ for (; x > 0 && x % 10 == 0; x /= 10) {
+ --precision;
+ }
+ }
+ }
+
+ return SSIZET2NUM(precision);
+}
+
+static VALUE
+BigDecimal_n_significant_digits(VALUE self)
+{
+ ENTER(1);
+
+ Real *p;
+ GUARD_OBJ(p, GetVpValue(self, 1));
+
+ ssize_t n = p->Prec;
+ while (n > 0 && p->frac[n-1] == 0) --n;
+ if (n <= 0) {
+ return INT2FIX(0);
+ }
+
+ int nlz, ntz;
+
+ BDIGIT x = p->frac[0];
+ for (nlz = BASE_FIG; x > 0; x /= 10) --nlz;
+
+ x = p->frac[n-1];
+ for (ntz = 0; x > 0 && x % 10 == 0; x /= 10) ++ntz;
+
+ ssize_t n_digits = BASE_FIG * n - nlz - ntz;
+ return SSIZET2NUM(n_digits);
+}
+
+/*
* call-seq: hash
*
* Creates a hash for this BigDecimal.
@@ -875,7 +1003,7 @@ BigDecimal_coerce(VALUE self, VALUE other)
Real *b;
if (RB_TYPE_P(other, T_FLOAT)) {
- GUARD_OBJ(b, GetVpValueWithPrec(other, DBL_DIG+1, 1));
+ GUARD_OBJ(b, GetVpValueWithPrec(other, DBLE_FIG, 1));
obj = rb_assoc_new(ToValue(b), self);
}
else {
@@ -933,7 +1061,7 @@ BigDecimal_add(VALUE self, VALUE r)
GUARD_OBJ(a, GetVpValue(self, 1));
if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
}
else if (RB_TYPE_P(r, T_RATIONAL)) {
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -991,7 +1119,7 @@ BigDecimal_sub(VALUE self, VALUE r)
GUARD_OBJ(a, GetVpValue(self,1));
if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
}
else if (RB_TYPE_P(r, T_RATIONAL)) {
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1041,7 +1169,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
break;
case T_FLOAT:
- GUARD_OBJ(b, GetVpValueWithPrec(r, DBL_DIG+1, 0));
+ GUARD_OBJ(b, GetVpValueWithPrec(r, DBLE_FIG, 0));
break;
case T_RATIONAL:
@@ -1254,7 +1382,7 @@ BigDecimal_mult(VALUE self, VALUE r)
GUARD_OBJ(a, GetVpValue(self, 1));
if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
}
else if (RB_TYPE_P(r, T_RATIONAL)) {
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1282,7 +1410,7 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
GUARD_OBJ(a, GetVpValue(self, 1));
if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
}
else if (RB_TYPE_P(r, T_RATIONAL)) {
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1348,7 +1476,7 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
GUARD_OBJ(a, GetVpValue(self, 1));
if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
}
else if (RB_TYPE_P(r, T_RATIONAL)) {
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1449,7 +1577,7 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
GUARD_OBJ(a, GetVpValue(self, 1));
if (RB_TYPE_P(r, T_FLOAT)) {
- b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
+ b = GetVpValueWithPrec(r, DBLE_FIG, 1);
}
else if (RB_TYPE_P(r, T_RATIONAL)) {
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1767,10 +1895,10 @@ BigDecimal_fix(VALUE self)
* more than that many digits.
*
* If n is specified and negative, at least that many digits to the left of the
- * decimal point will be 0 in the result.
+ * decimal point will be 0 in the result, and return value will be an Integer.
*
* BigDecimal('3.14159').round(3) #=> 3.142
- * BigDecimal('13345.234').round(-2) #=> 13300.0
+ * BigDecimal('13345.234').round(-2) #=> 13300
*
* The value of the optional mode argument can be used to determine how
* rounding is performed; see BigDecimal.mode.
@@ -1783,6 +1911,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
int iLoc = 0;
VALUE vLoc;
VALUE vRound;
+ int round_to_int = 0;
size_t mx, pl;
unsigned short sw = VpGetRoundMode();
@@ -1790,6 +1919,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
switch (rb_scan_args(argc, argv, "02", &vLoc, &vRound)) {
case 0:
iLoc = 0;
+ round_to_int = 1;
break;
case 1:
if (RB_TYPE_P(vLoc, T_HASH)) {
@@ -1797,6 +1927,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
}
else {
iLoc = NUM2INT(vLoc);
+ if (iLoc < 1) round_to_int = 1;
}
break;
case 2:
@@ -1818,7 +1949,7 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
VpSetPrecLimit(pl);
VpActiveRound(c, a, sw, iLoc);
- if (argc == 0) {
+ if (round_to_int) {
return BigDecimal_to_i(ToValue(c));
}
return ToValue(c);
@@ -2067,7 +2198,7 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
nc += (nc + mc - 1) / mc + 1;
}
- str = rb_str_new(0, nc);
+ str = rb_usascii_str_new(0, nc);
psz = RSTRING_PTR(str);
if (fmt) {
@@ -2132,7 +2263,7 @@ BigDecimal_split(VALUE self)
rb_ary_push(obj, str);
rb_str_resize(str, strlen(psz1));
rb_ary_push(obj, INT2FIX(10));
- rb_ary_push(obj, INT2NUM(e));
+ rb_ary_push(obj, SSIZET2NUM(e));
return obj;
}
@@ -2145,7 +2276,7 @@ static VALUE
BigDecimal_exponent(VALUE self)
{
ssize_t e = VpExponent10(GetVpValue(self, 1));
- return INT2NUM(e);
+ return SSIZET2NUM(e);
}
/* Returns a string representation of self.
@@ -2338,7 +2469,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
}
goto retry;
}
- exp = GetVpValueWithPrec(vexp, DBL_DIG+1, 1);
+ if (NIL_P(prec)) {
+ n += DBLE_FIG;
+ }
+ exp = GetVpValueWithPrec(vexp, DBLE_FIG, 1);
break;
case T_RATIONAL:
@@ -2353,6 +2487,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
goto retry;
}
exp = GetVpValueWithPrec(vexp, n, 1);
+ if (NIL_P(prec)) {
+ n += n;
+ }
break;
case T_DATA:
@@ -2363,6 +2500,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
vexp = BigDecimal_to_i(vexp);
goto retry;
}
+ if (NIL_P(prec)) {
+ GUARD_OBJ(y, GetVpValue(vexp, 1));
+ n += y->Prec*VpBaseFig();
+ }
exp = DATA_PTR(vexp);
break;
}
@@ -2628,6 +2769,7 @@ VpNewVarArg(int argc, VALUE *argv)
}
}
+ retry:
switch (TYPE(iniValue)) {
case T_DATA:
if (is_kind_of_BigDecimal(iniValue)) {
@@ -2647,7 +2789,7 @@ VpNewVarArg(int argc, VALUE *argv)
VpDtoV(pv, d);
return pv;
}
- if (mf > DBL_DIG+1) {
+ if (mf > DBLE_FIG) {
if (!exc) {
return NULL;
}
@@ -2665,6 +2807,18 @@ VpNewVarArg(int argc, VALUE *argv)
}
return GetVpValueWithPrec(iniValue, mf, 1);
+ case T_COMPLEX:
+ {
+ VALUE im;
+ im = rb_complex_imag(iniValue);
+ if (!is_zero(im)) {
+ rb_raise(rb_eArgError,
+ "Unable to make a BigDecimal from non-zero imaginary number");
+ }
+ iniValue = rb_complex_real(iniValue);
+ goto retry;
+ }
+
case T_STRING:
/* fall through */
default:
@@ -2765,7 +2919,7 @@ static VALUE
BigDecimal_limit(int argc, VALUE *argv, VALUE self)
{
VALUE nFig;
- VALUE nCur = INT2NUM(VpGetPrecLimit());
+ VALUE nCur = SIZET2NUM(VpGetPrecLimit());
if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
int nf;
@@ -2930,7 +3084,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
infinite = isinf(flo);
nan = isnan(flo);
if (!infinite && !nan) {
- vx = GetVpValueWithPrec(x, DBL_DIG+1, 0);
+ vx = GetVpValueWithPrec(x, DBLE_FIG, 0);
}
break;
@@ -3083,7 +3237,7 @@ get_vp_value:
infinite = isinf(flo);
nan = isnan(flo);
if (!zero && !negative && !infinite && !nan) {
- vx = GetVpValueWithPrec(x, DBL_DIG+1, 1);
+ vx = GetVpValueWithPrec(x, DBLE_FIG, 1);
}
break;
@@ -3301,6 +3455,9 @@ get_vp_value:
void
Init_bigdecimal(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
VALUE arg;
id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode");
@@ -3317,7 +3474,7 @@ Init_bigdecimal(void)
rb_define_global_function("BigDecimal", f_BigDecimal, -1);
/* Class methods */
- rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate");
+ rb_undef_alloc_func(rb_cBigDecimal);
rb_undef_method(CLASS_OF(rb_cBigDecimal), "new");
rb_define_singleton_method(rb_cBigDecimal, "interpret_loosely", BigDecimal_s_interpret_loosely, 1);
rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
@@ -3450,8 +3607,9 @@ Init_bigdecimal(void)
/* instance methods */
- rb_define_method(rb_cBigDecimal, "initialize_copy", BigDecimal_initialize_copy, 1);
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
+ rb_define_method(rb_cBigDecimal, "precision", BigDecimal_precision, 0);
+ rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0);
rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
@@ -3568,6 +3726,9 @@ static void VpFormatSt(char *psz, size_t fFmt);
static int VpRdup(Real *m, size_t ind_m);
#ifdef BIGDECIMAL_DEBUG
+# ifdef HAVE_RB_EXT_RACTOR_SAFE
+# error Need to make rewiting gnAlloc atomic
+# endif
static int gnAlloc = 0; /* Memory allocation counter */
#endif /* BIGDECIMAL_DEBUG */
@@ -3974,7 +4135,7 @@ VpNumOfChars(Real *vp,const char *pszFmt)
* by one BDIGIT word in the computer used.
*
* [Returns]
- * 1+DBL_DIG ... OK
+ * DBLE_FIG ... OK
*/
VP_EXPORT size_t
VpInit(BDIGIT BaseVal)
@@ -4144,7 +4305,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
/* at least mx digits. */
/* szVal==NULL ==> allocate zero value. */
vp = VpAllocReal(mx);
- /* xmalloc() alway returns(or throw interruption) */
+ /* xmalloc() always returns(or throw interruption) */
vp->MaxPrec = mx; /* set max precision */
VpSetZero(vp, 1); /* initialize vp to zero. */
return vp;
@@ -4320,7 +4481,7 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
nalloc = Max(nalloc, mx);
mx = nalloc;
vp = VpAllocReal(mx);
- /* xmalloc() alway returns(or throw interruption) */
+ /* xmalloc() always returns(or throw interruption) */
vp->MaxPrec = mx; /* set max precision */
VpSetZero(vp, sign);
VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
diff --git a/ext/bigdecimal/bigdecimal.gemspec b/ext/bigdecimal/bigdecimal.gemspec
index 7d767f598b..7e5388d8e0 100644
--- a/ext/bigdecimal/bigdecimal.gemspec
+++ b/ext/bigdecimal/bigdecimal.gemspec
@@ -1,6 +1,6 @@
# coding: utf-8
-bigdecimal_version = '2.0.0'
+bigdecimal_version = '3.0.0'
Gem::Specification.new do |s|
s.name = "bigdecimal"
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
s.summary = "Arbitrary-precision decimal floating-point number library."
s.description = "This library provides arbitrary-precision decimal floating-point number class."
s.homepage = "https://github.com/ruby/bigdecimal"
- s.license = "ruby"
+ s.license = "Ruby"
s.require_paths = %w[lib]
s.extensions = %w[ext/bigdecimal/extconf.rb]
@@ -30,9 +30,9 @@ Gem::Specification.new do |s|
sample/pi.rb
]
- s.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ s.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
- s.add_development_dependency "rake", "~> 10.0"
+ s.add_development_dependency "rake", ">= 12.3.3"
s.add_development_dependency "rake-compiler", ">= 0.9"
s.add_development_dependency "minitest", "< 5.0.0"
s.add_development_dependency "pry"
diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h
index e3eae06e67..28f3363b3c 100644
--- a/ext/bigdecimal/bigdecimal.h
+++ b/ext/bigdecimal/bigdecimal.h
@@ -159,6 +159,10 @@ rb_sym2str(VALUE sym)
# define vabs llabs
#endif
+#if !defined(HAVE_RB_CATEGORY_WARN) || !defined(HAVE_CONST_RB_WARN_CATEGORY_DEPRECATED)
+# define rb_category_warn(category, ...) rb_warn(__VA_ARGS__)
+#endif
+
extern VALUE rb_cBigDecimal;
#if 0 || SIZEOF_BDIGITS >= 16
diff --git a/ext/bigdecimal/depend b/ext/bigdecimal/depend
index ffd61b8960..d607a71dfe 100644
--- a/ext/bigdecimal/depend
+++ b/ext/bigdecimal/depend
@@ -4,7 +4,156 @@ Makefile: $(BIGDECIMAL_RB)
# AUTOGENERATED DEPENDENCIES START
bigdecimal.o: $(RUBY_EXTCONF_H)
bigdecimal.o: $(arch_hdrdir)/ruby/config.h
+bigdecimal.o: $(hdrdir)/ruby/internal/anyargs.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bigdecimal.o: $(hdrdir)/ruby/internal/assume.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/cold.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/const.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/error.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/format.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/pure.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/warning.h
+bigdecimal.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bigdecimal.o: $(hdrdir)/ruby/internal/cast.h
+bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is.h
+bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bigdecimal.o: $(hdrdir)/ruby/internal/compiler_since.h
+bigdecimal.o: $(hdrdir)/ruby/internal/config.h
+bigdecimal.o: $(hdrdir)/ruby/internal/constant_p.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rarray.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rclass.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rdata.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rfile.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rhash.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/robject.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rstring.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bigdecimal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bigdecimal.o: $(hdrdir)/ruby/internal/ctype.h
+bigdecimal.o: $(hdrdir)/ruby/internal/dllexport.h
+bigdecimal.o: $(hdrdir)/ruby/internal/dosish.h
+bigdecimal.o: $(hdrdir)/ruby/internal/error.h
+bigdecimal.o: $(hdrdir)/ruby/internal/eval.h
+bigdecimal.o: $(hdrdir)/ruby/internal/event.h
+bigdecimal.o: $(hdrdir)/ruby/internal/fl_type.h
+bigdecimal.o: $(hdrdir)/ruby/internal/gc.h
+bigdecimal.o: $(hdrdir)/ruby/internal/glob.h
+bigdecimal.o: $(hdrdir)/ruby/internal/globals.h
+bigdecimal.o: $(hdrdir)/ruby/internal/has/attribute.h
+bigdecimal.o: $(hdrdir)/ruby/internal/has/builtin.h
+bigdecimal.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bigdecimal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bigdecimal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bigdecimal.o: $(hdrdir)/ruby/internal/has/extension.h
+bigdecimal.o: $(hdrdir)/ruby/internal/has/feature.h
+bigdecimal.o: $(hdrdir)/ruby/internal/has/warning.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/array.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/class.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/compar.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/complex.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/cont.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/dir.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/enum.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/error.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/eval.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/file.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/gc.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/hash.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/io.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/load.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/object.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/parse.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/proc.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/process.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/random.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/range.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/rational.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/re.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/select.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/signal.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/string.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/struct.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/thread.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/time.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/variable.h
+bigdecimal.o: $(hdrdir)/ruby/internal/intern/vm.h
+bigdecimal.o: $(hdrdir)/ruby/internal/interpreter.h
+bigdecimal.o: $(hdrdir)/ruby/internal/iterator.h
+bigdecimal.o: $(hdrdir)/ruby/internal/memory.h
+bigdecimal.o: $(hdrdir)/ruby/internal/method.h
+bigdecimal.o: $(hdrdir)/ruby/internal/module.h
+bigdecimal.o: $(hdrdir)/ruby/internal/newobj.h
+bigdecimal.o: $(hdrdir)/ruby/internal/rgengc.h
+bigdecimal.o: $(hdrdir)/ruby/internal/scan_args.h
+bigdecimal.o: $(hdrdir)/ruby/internal/special_consts.h
+bigdecimal.o: $(hdrdir)/ruby/internal/static_assert.h
+bigdecimal.o: $(hdrdir)/ruby/internal/stdalign.h
+bigdecimal.o: $(hdrdir)/ruby/internal/stdbool.h
+bigdecimal.o: $(hdrdir)/ruby/internal/symbol.h
+bigdecimal.o: $(hdrdir)/ruby/internal/token_paste.h
+bigdecimal.o: $(hdrdir)/ruby/internal/value.h
+bigdecimal.o: $(hdrdir)/ruby/internal/value_type.h
+bigdecimal.o: $(hdrdir)/ruby/internal/variable.h
+bigdecimal.o: $(hdrdir)/ruby/internal/warning_push.h
+bigdecimal.o: $(hdrdir)/ruby/internal/xmalloc.h
bigdecimal.o: $(hdrdir)/ruby/assert.h
+bigdecimal.o: $(hdrdir)/ruby/backward/2/assume.h
+bigdecimal.o: $(hdrdir)/ruby/backward/2/attributes.h
+bigdecimal.o: $(hdrdir)/ruby/backward/2/bool.h
+bigdecimal.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+bigdecimal.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bigdecimal.o: $(hdrdir)/ruby/backward/2/limits.h
+bigdecimal.o: $(hdrdir)/ruby/backward/2/long_long.h
+bigdecimal.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bigdecimal.o: $(hdrdir)/ruby/backward/2/stdarg.h
bigdecimal.o: $(hdrdir)/ruby/defines.h
bigdecimal.o: $(hdrdir)/ruby/intern.h
bigdecimal.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb
index b4098fdacf..63123e2892 100644
--- a/ext/bigdecimal/extconf.rb
+++ b/ext/bigdecimal/extconf.rb
@@ -36,9 +36,14 @@ have_func("isfinite", "math.h")
have_type("struct RRational", "ruby.h")
have_func("rb_rational_num", "ruby.h")
have_func("rb_rational_den", "ruby.h")
+have_type("struct RComplex", "ruby.h")
+have_func("rb_complex_real", "ruby.h")
+have_func("rb_complex_imag", "ruby.h")
have_func("rb_array_const_ptr", "ruby.h")
have_func("rb_sym2str", "ruby.h")
have_func("rb_opts_exception_p", "ruby.h")
+have_func("rb_category_warn", "ruby.h")
+have_const("RB_WARN_CATEGORY_DEPRECATED", "ruby.h")
if File.file?(File.expand_path('../lib/bigdecimal.rb', __FILE__))
bigdecimal_rb = "$(srcdir)/lib/bigdecimal.rb"
diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb
index 4ece8347bd..00a3e967bd 100644
--- a/ext/bigdecimal/lib/bigdecimal/util.rb
+++ b/ext/bigdecimal/lib/bigdecimal/util.rb
@@ -43,7 +43,7 @@ class Float < Numeric
#
# See also BigDecimal::new.
#
- def to_d(precision=Float::DIG)
+ def to_d(precision=Float::DIG+1)
BigDecimal(self, precision)
end
end
@@ -131,6 +131,39 @@ class Rational < Numeric
end
+class Complex < Numeric
+ # call-seq:
+ # cmp.to_d -> bigdecimal
+ # cmp.to_d(precision) -> bigdecimal
+ #
+ # Returns the value as a BigDecimal.
+ #
+ # The +precision+ parameter is required for a rational complex number.
+ # This parameter is used to determine the number of significant digits
+ # for the result.
+ #
+ # require 'bigdecimal'
+ # require 'bigdecimal/util'
+ #
+ # Complex(0.1234567, 0).to_d(4) # => 0.1235e0
+ # Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1
+ #
+ # See also BigDecimal::new.
+ #
+ def to_d(*args)
+ BigDecimal(self) unless self.imag.zero? # to raise eerror
+
+ if args.length == 0
+ case self.real
+ when Rational
+ BigDecimal(self.real) # to raise error
+ end
+ end
+ self.real.to_d(*args)
+ end
+end
+
+
class NilClass
# call-seq:
# nil.to_d -> bigdecimal
diff --git a/ext/bigdecimal/util/depend b/ext/bigdecimal/util/depend
deleted file mode 100644
index 96b6a7fea0..0000000000
--- a/ext/bigdecimal/util/depend
+++ /dev/null
@@ -1,14 +0,0 @@
-# AUTOGENERATED DEPENDENCIES START
-util.o: $(RUBY_EXTCONF_H)
-util.o: $(arch_hdrdir)/ruby/config.h
-util.o: $(hdrdir)/ruby.h
-util.o: $(hdrdir)/ruby/assert.h
-util.o: $(hdrdir)/ruby/backward.h
-util.o: $(hdrdir)/ruby/defines.h
-util.o: $(hdrdir)/ruby/intern.h
-util.o: $(hdrdir)/ruby/missing.h
-util.o: $(hdrdir)/ruby/ruby.h
-util.o: $(hdrdir)/ruby/st.h
-util.o: $(hdrdir)/ruby/subst.h
-util.o: util.c
-# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/cgi/escape/depend b/ext/cgi/escape/depend
index 8d4736616f..fc3875d151 100644
--- a/ext/cgi/escape/depend
+++ b/ext/cgi/escape/depend
@@ -2,8 +2,157 @@
escape.o: $(RUBY_EXTCONF_H)
escape.o: $(arch_hdrdir)/ruby/config.h
escape.o: $(hdrdir)/ruby.h
+escape.o: $(hdrdir)/ruby/internal/anyargs.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+escape.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+escape.o: $(hdrdir)/ruby/internal/assume.h
+escape.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+escape.o: $(hdrdir)/ruby/internal/attr/artificial.h
+escape.o: $(hdrdir)/ruby/internal/attr/cold.h
+escape.o: $(hdrdir)/ruby/internal/attr/const.h
+escape.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+escape.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+escape.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+escape.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+escape.o: $(hdrdir)/ruby/internal/attr/error.h
+escape.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+escape.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+escape.o: $(hdrdir)/ruby/internal/attr/format.h
+escape.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+escape.o: $(hdrdir)/ruby/internal/attr/noalias.h
+escape.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+escape.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+escape.o: $(hdrdir)/ruby/internal/attr/noinline.h
+escape.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+escape.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+escape.o: $(hdrdir)/ruby/internal/attr/pure.h
+escape.o: $(hdrdir)/ruby/internal/attr/restrict.h
+escape.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+escape.o: $(hdrdir)/ruby/internal/attr/warning.h
+escape.o: $(hdrdir)/ruby/internal/attr/weakref.h
+escape.o: $(hdrdir)/ruby/internal/cast.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+escape.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+escape.o: $(hdrdir)/ruby/internal/compiler_since.h
+escape.o: $(hdrdir)/ruby/internal/config.h
+escape.o: $(hdrdir)/ruby/internal/constant_p.h
+escape.o: $(hdrdir)/ruby/internal/core.h
+escape.o: $(hdrdir)/ruby/internal/core/rarray.h
+escape.o: $(hdrdir)/ruby/internal/core/rbasic.h
+escape.o: $(hdrdir)/ruby/internal/core/rbignum.h
+escape.o: $(hdrdir)/ruby/internal/core/rclass.h
+escape.o: $(hdrdir)/ruby/internal/core/rdata.h
+escape.o: $(hdrdir)/ruby/internal/core/rfile.h
+escape.o: $(hdrdir)/ruby/internal/core/rhash.h
+escape.o: $(hdrdir)/ruby/internal/core/robject.h
+escape.o: $(hdrdir)/ruby/internal/core/rregexp.h
+escape.o: $(hdrdir)/ruby/internal/core/rstring.h
+escape.o: $(hdrdir)/ruby/internal/core/rstruct.h
+escape.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+escape.o: $(hdrdir)/ruby/internal/ctype.h
+escape.o: $(hdrdir)/ruby/internal/dllexport.h
+escape.o: $(hdrdir)/ruby/internal/dosish.h
+escape.o: $(hdrdir)/ruby/internal/error.h
+escape.o: $(hdrdir)/ruby/internal/eval.h
+escape.o: $(hdrdir)/ruby/internal/event.h
+escape.o: $(hdrdir)/ruby/internal/fl_type.h
+escape.o: $(hdrdir)/ruby/internal/gc.h
+escape.o: $(hdrdir)/ruby/internal/glob.h
+escape.o: $(hdrdir)/ruby/internal/globals.h
+escape.o: $(hdrdir)/ruby/internal/has/attribute.h
+escape.o: $(hdrdir)/ruby/internal/has/builtin.h
+escape.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+escape.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+escape.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+escape.o: $(hdrdir)/ruby/internal/has/extension.h
+escape.o: $(hdrdir)/ruby/internal/has/feature.h
+escape.o: $(hdrdir)/ruby/internal/has/warning.h
+escape.o: $(hdrdir)/ruby/internal/intern/array.h
+escape.o: $(hdrdir)/ruby/internal/intern/bignum.h
+escape.o: $(hdrdir)/ruby/internal/intern/class.h
+escape.o: $(hdrdir)/ruby/internal/intern/compar.h
+escape.o: $(hdrdir)/ruby/internal/intern/complex.h
+escape.o: $(hdrdir)/ruby/internal/intern/cont.h
+escape.o: $(hdrdir)/ruby/internal/intern/dir.h
+escape.o: $(hdrdir)/ruby/internal/intern/enum.h
+escape.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+escape.o: $(hdrdir)/ruby/internal/intern/error.h
+escape.o: $(hdrdir)/ruby/internal/intern/eval.h
+escape.o: $(hdrdir)/ruby/internal/intern/file.h
+escape.o: $(hdrdir)/ruby/internal/intern/gc.h
+escape.o: $(hdrdir)/ruby/internal/intern/hash.h
+escape.o: $(hdrdir)/ruby/internal/intern/io.h
+escape.o: $(hdrdir)/ruby/internal/intern/load.h
+escape.o: $(hdrdir)/ruby/internal/intern/marshal.h
+escape.o: $(hdrdir)/ruby/internal/intern/numeric.h
+escape.o: $(hdrdir)/ruby/internal/intern/object.h
+escape.o: $(hdrdir)/ruby/internal/intern/parse.h
+escape.o: $(hdrdir)/ruby/internal/intern/proc.h
+escape.o: $(hdrdir)/ruby/internal/intern/process.h
+escape.o: $(hdrdir)/ruby/internal/intern/random.h
+escape.o: $(hdrdir)/ruby/internal/intern/range.h
+escape.o: $(hdrdir)/ruby/internal/intern/rational.h
+escape.o: $(hdrdir)/ruby/internal/intern/re.h
+escape.o: $(hdrdir)/ruby/internal/intern/ruby.h
+escape.o: $(hdrdir)/ruby/internal/intern/select.h
+escape.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+escape.o: $(hdrdir)/ruby/internal/intern/signal.h
+escape.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+escape.o: $(hdrdir)/ruby/internal/intern/string.h
+escape.o: $(hdrdir)/ruby/internal/intern/struct.h
+escape.o: $(hdrdir)/ruby/internal/intern/thread.h
+escape.o: $(hdrdir)/ruby/internal/intern/time.h
+escape.o: $(hdrdir)/ruby/internal/intern/variable.h
+escape.o: $(hdrdir)/ruby/internal/intern/vm.h
+escape.o: $(hdrdir)/ruby/internal/interpreter.h
+escape.o: $(hdrdir)/ruby/internal/iterator.h
+escape.o: $(hdrdir)/ruby/internal/memory.h
+escape.o: $(hdrdir)/ruby/internal/method.h
+escape.o: $(hdrdir)/ruby/internal/module.h
+escape.o: $(hdrdir)/ruby/internal/newobj.h
+escape.o: $(hdrdir)/ruby/internal/rgengc.h
+escape.o: $(hdrdir)/ruby/internal/scan_args.h
+escape.o: $(hdrdir)/ruby/internal/special_consts.h
+escape.o: $(hdrdir)/ruby/internal/static_assert.h
+escape.o: $(hdrdir)/ruby/internal/stdalign.h
+escape.o: $(hdrdir)/ruby/internal/stdbool.h
+escape.o: $(hdrdir)/ruby/internal/symbol.h
+escape.o: $(hdrdir)/ruby/internal/token_paste.h
+escape.o: $(hdrdir)/ruby/internal/value.h
+escape.o: $(hdrdir)/ruby/internal/value_type.h
+escape.o: $(hdrdir)/ruby/internal/variable.h
+escape.o: $(hdrdir)/ruby/internal/warning_push.h
+escape.o: $(hdrdir)/ruby/internal/xmalloc.h
escape.o: $(hdrdir)/ruby/assert.h
escape.o: $(hdrdir)/ruby/backward.h
+escape.o: $(hdrdir)/ruby/backward/2/assume.h
+escape.o: $(hdrdir)/ruby/backward/2/attributes.h
+escape.o: $(hdrdir)/ruby/backward/2/bool.h
+escape.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+escape.o: $(hdrdir)/ruby/backward/2/inttypes.h
+escape.o: $(hdrdir)/ruby/backward/2/limits.h
+escape.o: $(hdrdir)/ruby/backward/2/long_long.h
+escape.o: $(hdrdir)/ruby/backward/2/stdalign.h
+escape.o: $(hdrdir)/ruby/backward/2/stdarg.h
escape.o: $(hdrdir)/ruby/defines.h
escape.o: $(hdrdir)/ruby/encoding.h
escape.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/cgi/escape/escape.c b/ext/cgi/escape/escape.c
index feedea34c8..809f95ef4c 100644
--- a/ext/cgi/escape/escape.c
+++ b/ext/cgi/escape/escape.c
@@ -389,6 +389,10 @@ cgiesc_unescape(int argc, VALUE *argv, VALUE self)
void
Init_escape(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
id_accept_charset = rb_intern_const("@@accept_charset");
InitVM(escape);
}
diff --git a/ext/continuation/depend b/ext/continuation/depend
index 08844aa6bb..6e9e4f0122 100644
--- a/ext/continuation/depend
+++ b/ext/continuation/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
continuation.o: $(RUBY_EXTCONF_H)
continuation.o: $(arch_hdrdir)/ruby/config.h
+continuation.o: $(hdrdir)/ruby/internal/anyargs.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+continuation.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+continuation.o: $(hdrdir)/ruby/internal/assume.h
+continuation.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+continuation.o: $(hdrdir)/ruby/internal/attr/artificial.h
+continuation.o: $(hdrdir)/ruby/internal/attr/cold.h
+continuation.o: $(hdrdir)/ruby/internal/attr/const.h
+continuation.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+continuation.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+continuation.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+continuation.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+continuation.o: $(hdrdir)/ruby/internal/attr/error.h
+continuation.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+continuation.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+continuation.o: $(hdrdir)/ruby/internal/attr/format.h
+continuation.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+continuation.o: $(hdrdir)/ruby/internal/attr/noalias.h
+continuation.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+continuation.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+continuation.o: $(hdrdir)/ruby/internal/attr/noinline.h
+continuation.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+continuation.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+continuation.o: $(hdrdir)/ruby/internal/attr/pure.h
+continuation.o: $(hdrdir)/ruby/internal/attr/restrict.h
+continuation.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+continuation.o: $(hdrdir)/ruby/internal/attr/warning.h
+continuation.o: $(hdrdir)/ruby/internal/attr/weakref.h
+continuation.o: $(hdrdir)/ruby/internal/cast.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+continuation.o: $(hdrdir)/ruby/internal/compiler_since.h
+continuation.o: $(hdrdir)/ruby/internal/config.h
+continuation.o: $(hdrdir)/ruby/internal/constant_p.h
+continuation.o: $(hdrdir)/ruby/internal/core.h
+continuation.o: $(hdrdir)/ruby/internal/core/rarray.h
+continuation.o: $(hdrdir)/ruby/internal/core/rbasic.h
+continuation.o: $(hdrdir)/ruby/internal/core/rbignum.h
+continuation.o: $(hdrdir)/ruby/internal/core/rclass.h
+continuation.o: $(hdrdir)/ruby/internal/core/rdata.h
+continuation.o: $(hdrdir)/ruby/internal/core/rfile.h
+continuation.o: $(hdrdir)/ruby/internal/core/rhash.h
+continuation.o: $(hdrdir)/ruby/internal/core/robject.h
+continuation.o: $(hdrdir)/ruby/internal/core/rregexp.h
+continuation.o: $(hdrdir)/ruby/internal/core/rstring.h
+continuation.o: $(hdrdir)/ruby/internal/core/rstruct.h
+continuation.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+continuation.o: $(hdrdir)/ruby/internal/ctype.h
+continuation.o: $(hdrdir)/ruby/internal/dllexport.h
+continuation.o: $(hdrdir)/ruby/internal/dosish.h
+continuation.o: $(hdrdir)/ruby/internal/error.h
+continuation.o: $(hdrdir)/ruby/internal/eval.h
+continuation.o: $(hdrdir)/ruby/internal/event.h
+continuation.o: $(hdrdir)/ruby/internal/fl_type.h
+continuation.o: $(hdrdir)/ruby/internal/gc.h
+continuation.o: $(hdrdir)/ruby/internal/glob.h
+continuation.o: $(hdrdir)/ruby/internal/globals.h
+continuation.o: $(hdrdir)/ruby/internal/has/attribute.h
+continuation.o: $(hdrdir)/ruby/internal/has/builtin.h
+continuation.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+continuation.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+continuation.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+continuation.o: $(hdrdir)/ruby/internal/has/extension.h
+continuation.o: $(hdrdir)/ruby/internal/has/feature.h
+continuation.o: $(hdrdir)/ruby/internal/has/warning.h
+continuation.o: $(hdrdir)/ruby/internal/intern/array.h
+continuation.o: $(hdrdir)/ruby/internal/intern/bignum.h
+continuation.o: $(hdrdir)/ruby/internal/intern/class.h
+continuation.o: $(hdrdir)/ruby/internal/intern/compar.h
+continuation.o: $(hdrdir)/ruby/internal/intern/complex.h
+continuation.o: $(hdrdir)/ruby/internal/intern/cont.h
+continuation.o: $(hdrdir)/ruby/internal/intern/dir.h
+continuation.o: $(hdrdir)/ruby/internal/intern/enum.h
+continuation.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+continuation.o: $(hdrdir)/ruby/internal/intern/error.h
+continuation.o: $(hdrdir)/ruby/internal/intern/eval.h
+continuation.o: $(hdrdir)/ruby/internal/intern/file.h
+continuation.o: $(hdrdir)/ruby/internal/intern/gc.h
+continuation.o: $(hdrdir)/ruby/internal/intern/hash.h
+continuation.o: $(hdrdir)/ruby/internal/intern/io.h
+continuation.o: $(hdrdir)/ruby/internal/intern/load.h
+continuation.o: $(hdrdir)/ruby/internal/intern/marshal.h
+continuation.o: $(hdrdir)/ruby/internal/intern/numeric.h
+continuation.o: $(hdrdir)/ruby/internal/intern/object.h
+continuation.o: $(hdrdir)/ruby/internal/intern/parse.h
+continuation.o: $(hdrdir)/ruby/internal/intern/proc.h
+continuation.o: $(hdrdir)/ruby/internal/intern/process.h
+continuation.o: $(hdrdir)/ruby/internal/intern/random.h
+continuation.o: $(hdrdir)/ruby/internal/intern/range.h
+continuation.o: $(hdrdir)/ruby/internal/intern/rational.h
+continuation.o: $(hdrdir)/ruby/internal/intern/re.h
+continuation.o: $(hdrdir)/ruby/internal/intern/ruby.h
+continuation.o: $(hdrdir)/ruby/internal/intern/select.h
+continuation.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+continuation.o: $(hdrdir)/ruby/internal/intern/signal.h
+continuation.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+continuation.o: $(hdrdir)/ruby/internal/intern/string.h
+continuation.o: $(hdrdir)/ruby/internal/intern/struct.h
+continuation.o: $(hdrdir)/ruby/internal/intern/thread.h
+continuation.o: $(hdrdir)/ruby/internal/intern/time.h
+continuation.o: $(hdrdir)/ruby/internal/intern/variable.h
+continuation.o: $(hdrdir)/ruby/internal/intern/vm.h
+continuation.o: $(hdrdir)/ruby/internal/interpreter.h
+continuation.o: $(hdrdir)/ruby/internal/iterator.h
+continuation.o: $(hdrdir)/ruby/internal/memory.h
+continuation.o: $(hdrdir)/ruby/internal/method.h
+continuation.o: $(hdrdir)/ruby/internal/module.h
+continuation.o: $(hdrdir)/ruby/internal/newobj.h
+continuation.o: $(hdrdir)/ruby/internal/rgengc.h
+continuation.o: $(hdrdir)/ruby/internal/scan_args.h
+continuation.o: $(hdrdir)/ruby/internal/special_consts.h
+continuation.o: $(hdrdir)/ruby/internal/static_assert.h
+continuation.o: $(hdrdir)/ruby/internal/stdalign.h
+continuation.o: $(hdrdir)/ruby/internal/stdbool.h
+continuation.o: $(hdrdir)/ruby/internal/symbol.h
+continuation.o: $(hdrdir)/ruby/internal/token_paste.h
+continuation.o: $(hdrdir)/ruby/internal/value.h
+continuation.o: $(hdrdir)/ruby/internal/value_type.h
+continuation.o: $(hdrdir)/ruby/internal/variable.h
+continuation.o: $(hdrdir)/ruby/internal/warning_push.h
+continuation.o: $(hdrdir)/ruby/internal/xmalloc.h
continuation.o: $(hdrdir)/ruby/assert.h
continuation.o: $(hdrdir)/ruby/backward.h
+continuation.o: $(hdrdir)/ruby/backward/2/assume.h
+continuation.o: $(hdrdir)/ruby/backward/2/attributes.h
+continuation.o: $(hdrdir)/ruby/backward/2/bool.h
+continuation.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+continuation.o: $(hdrdir)/ruby/backward/2/inttypes.h
+continuation.o: $(hdrdir)/ruby/backward/2/limits.h
+continuation.o: $(hdrdir)/ruby/backward/2/long_long.h
+continuation.o: $(hdrdir)/ruby/backward/2/stdalign.h
+continuation.o: $(hdrdir)/ruby/backward/2/stdarg.h
continuation.o: $(hdrdir)/ruby/defines.h
continuation.o: $(hdrdir)/ruby/intern.h
continuation.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c
index 8503c9d6c6..0af5579ffc 100644
--- a/ext/coverage/coverage.c
+++ b/ext/coverage/coverage.c
@@ -8,9 +8,12 @@
************************************************/
+#include "gc.h"
+#include "internal/hash.h"
+#include "internal/thread.h"
+#include "internal/sanitizers.h"
#include "ruby.h"
#include "vm_core.h"
-#include "gc.h"
static int current_mode;
static VALUE me2counter = Qnil;
@@ -74,36 +77,62 @@ rb_coverage_start(int argc, VALUE *argv, VALUE klass)
return Qnil;
}
+struct branch_coverage_result_builder
+{
+ int id;
+ VALUE result;
+ VALUE children;
+ VALUE counters;
+};
+
+static int
+branch_coverage_ii(VALUE _key, VALUE branch, VALUE v)
+{
+ struct branch_coverage_result_builder *b = (struct branch_coverage_result_builder *) v;
+
+ VALUE target_label = RARRAY_AREF(branch, 0);
+ VALUE target_first_lineno = RARRAY_AREF(branch, 1);
+ VALUE target_first_column = RARRAY_AREF(branch, 2);
+ VALUE target_last_lineno = RARRAY_AREF(branch, 3);
+ VALUE target_last_column = RARRAY_AREF(branch, 4);
+ long counter_idx = FIX2LONG(RARRAY_AREF(branch, 5));
+ rb_hash_aset(b->children, rb_ary_new_from_args(6, target_label, LONG2FIX(b->id++), target_first_lineno, target_first_column, target_last_lineno, target_last_column), RARRAY_AREF(b->counters, counter_idx));
+
+ return ST_CONTINUE;
+}
+
+static int
+branch_coverage_i(VALUE _key, VALUE branch_base, VALUE v)
+{
+ struct branch_coverage_result_builder *b = (struct branch_coverage_result_builder *) v;
+
+ VALUE base_type = RARRAY_AREF(branch_base, 0);
+ VALUE base_first_lineno = RARRAY_AREF(branch_base, 1);
+ VALUE base_first_column = RARRAY_AREF(branch_base, 2);
+ VALUE base_last_lineno = RARRAY_AREF(branch_base, 3);
+ VALUE base_last_column = RARRAY_AREF(branch_base, 4);
+ VALUE branches = RARRAY_AREF(branch_base, 5);
+ VALUE children = rb_hash_new();
+ rb_hash_aset(b->result, rb_ary_new_from_args(6, base_type, LONG2FIX(b->id++), base_first_lineno, base_first_column, base_last_lineno, base_last_column), children);
+ b->children = children;
+ rb_hash_foreach(branches, branch_coverage_ii, v);
+
+ return ST_CONTINUE;
+}
+
static VALUE
branch_coverage(VALUE branches)
{
- VALUE ret = rb_hash_new();
- VALUE structure = rb_ary_dup(RARRAY_AREF(branches, 0));
- VALUE counters = rb_ary_dup(RARRAY_AREF(branches, 1));
- int i, j;
- long id = 0;
-
- for (i = 0; i < RARRAY_LEN(structure); i++) {
- VALUE branches = RARRAY_AREF(structure, i);
- VALUE base_type = RARRAY_AREF(branches, 0);
- VALUE base_first_lineno = RARRAY_AREF(branches, 1);
- VALUE base_first_column = RARRAY_AREF(branches, 2);
- VALUE base_last_lineno = RARRAY_AREF(branches, 3);
- VALUE base_last_column = RARRAY_AREF(branches, 4);
- VALUE children = rb_hash_new();
- rb_hash_aset(ret, rb_ary_new_from_args(6, base_type, LONG2FIX(id++), base_first_lineno, base_first_column, base_last_lineno, base_last_column), children);
- for (j = 5; j < RARRAY_LEN(branches); j += 6) {
- VALUE target_label = RARRAY_AREF(branches, j);
- VALUE target_first_lineno = RARRAY_AREF(branches, j + 1);
- VALUE target_first_column = RARRAY_AREF(branches, j + 2);
- VALUE target_last_lineno = RARRAY_AREF(branches, j + 3);
- VALUE target_last_column = RARRAY_AREF(branches, j + 4);
- int idx = FIX2INT(RARRAY_AREF(branches, j + 5));
- rb_hash_aset(children, rb_ary_new_from_args(6, target_label, LONG2FIX(id++), target_first_lineno, target_first_column, target_last_lineno, target_last_column), RARRAY_AREF(counters, idx));
- }
- }
+ VALUE structure = RARRAY_AREF(branches, 0);
+
+ struct branch_coverage_result_builder b;
+ b.id = 0;
+ b.result = rb_hash_new();
+ b.counters = RARRAY_AREF(branches, 1);
- return ret;
+ rb_hash_foreach(structure, branch_coverage_i, (VALUE)&b);
+
+ return b.result;
}
static int
@@ -122,6 +151,9 @@ method_coverage_i(void *vstart, void *vend, size_t stride, void *data)
VALUE ncoverages = *(VALUE*)data, v;
for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
+ void *poisoned = asan_poisoned_object_p(v);
+ asan_unpoison_object(v, false);
+
if (RB_TYPE_P(v, T_IMEMO) && imemo_type(v) == imemo_ment) {
const rb_method_entry_t *me = (rb_method_entry_t *) v;
VALUE path, first_lineno, first_column, last_lineno, last_column;
@@ -161,6 +193,10 @@ method_coverage_i(void *vstart, void *vend, size_t stride, void *data)
rb_hash_aset(methods, key, rcount);
}
}
+
+ if (poisoned) {
+ asan_poison_object(v);
+ }
}
return 0;
}
@@ -224,7 +260,8 @@ rb_coverage_peek_result(VALUE klass)
if (!RTEST(coverages)) {
rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
}
- st_foreach(RHASH_TBL(coverages), coverage_peek_result_i, ncoverages);
+ OBJ_WB_UNPROTECT(coverages);
+ st_foreach(RHASH_TBL_RAW(coverages), coverage_peek_result_i, ncoverages);
if (current_mode & COVERAGE_TARGET_METHODS) {
rb_objspace_each_objects(method_coverage_i, &ncoverages);
@@ -309,7 +346,7 @@ rb_coverage_running(VALUE klass)
* number of line execution by the interpreter. A +nil+ value means
* coverage is disabled for this line (lines like +else+ and +end+).
*
- * = Example
+ * = Examples
*
* [foo.rb]
* s = 0
@@ -328,6 +365,116 @@ rb_coverage_running(VALUE klass)
* Coverage.start
* require "foo.rb"
* p Coverage.result #=> {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}
+ *
+ * == Lines Coverage
+ *
+ * If a coverage mode is not explicitly specified when starting coverage, lines
+ * coverage is what will run. It reports the number of line executions for each
+ * line.
+ *
+ * require "coverage"
+ * Coverage.start(lines: true)
+ * require "foo.rb"
+ * p Coverage.result #=> {"foo.rb"=>{:lines=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}}
+ *
+ * The value of the lines coverage result is an array containing how many times
+ * each line was executed. Order in this array is important. For example, the
+ * first item in this array, at index 0, reports how many times line 1 of this
+ * file was executed while coverage was run (which, in this example, is one
+ * time).
+ *
+ * A +nil+ value means coverage is disabled for this line (lines like +else+
+ * and +end+).
+ *
+ * == Oneshot Lines Coverage
+ *
+ * Oneshot lines coverage tracks and reports on the executed lines while
+ * coverage is running. It will not report how many times a line was executed,
+ * only that it was executed.
+ *
+ * require "coverage"
+ * Coverage.start(oneshot_lines: true)
+ * require "foo.rb"
+ * p Coverage.result #=> {"foo.rb"=>{:oneshot_lines=>[1, 2, 3, 6, 7]}}
+ *
+ * The value of the oneshot lines coverage result is an array containing the
+ * line numbers that were executed.
+ *
+ * == Branches Coverage
+ *
+ * Branches coverage reports how many times each branch within each conditional
+ * was executed.
+ *
+ * require "coverage"
+ * Coverage.start(branches: true)
+ * require "foo.rb"
+ * p Coverage.result #=> {"foo.rb"=>{:branches=>{[:if, 0, 6, 0, 10, 3]=>{[:then, 1, 7, 2, 7, 7]=>1, [:else, 2, 9, 2, 9, 7]=>0}}}}
+ *
+ * Each entry within the branches hash is a conditional, the value of which is
+ * another hash where each entry is a branch in that conditional. The values
+ * are the number of times the method was executed, and the keys are identifying
+ * information about the branch.
+ *
+ * The information that makes up each key identifying branches or conditionals
+ * is the following, from left to right:
+ *
+ * 1. A label for the type of branch or conditional.
+ * 2. A unique identifier.
+ * 3. The starting line number it appears on in the file.
+ * 4. The starting column number it appears on in the file.
+ * 5. The ending line number it appears on in the file.
+ * 6. The ending column number it appears on in the file.
+ *
+ * == Methods Coverage
+ *
+ * Methods coverage reports how many times each method was executed.
+ *
+ * [foo_method.rb]
+ * class Greeter
+ * def greet
+ * "welcome!"
+ * end
+ * end
+ *
+ * def hello
+ * "Hi"
+ * end
+ *
+ * hello()
+ * Greeter.new.greet()
+ * [EOF]
+ *
+ * require "coverage"
+ * Coverage.start(methods: true)
+ * require "foo_method.rb"
+ * p Coverage.result #=> {"foo_method.rb"=>{:methods=>{[Object, :hello, 7, 0, 9, 3]=>1, [Greeter, :greet, 2, 2, 4, 5]=>1}}}
+ *
+ * Each entry within the methods hash represents a method. The values in this
+ * hash are the number of times the method was executed, and the keys are
+ * identifying information about the method.
+ *
+ * The information that makes up each key identifying a method is the following,
+ * from left to right:
+ *
+ * 1. The class.
+ * 2. The method name.
+ * 3. The starting line number the method appears on in the file.
+ * 4. The starting column number the method appears on in the file.
+ * 5. The ending line number the method appears on in the file.
+ * 6. The ending column number the method appears on in the file.
+ *
+ * == All Coverage Modes
+ *
+ * You can also run all modes of coverage simultaneously with this shortcut.
+ * Note that running all coverage modes does not run both lines and oneshot
+ * lines. Those modes cannot be run simultaneously. Lines coverage is run in
+ * this case, because you can still use it to determine whether or not a line
+ * was executed.
+ *
+ * require "coverage"
+ * Coverage.start(:all)
+ * require "foo.rb"
+ * p Coverage.result #=> {"foo.rb"=>{:lines=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil], :branches=>{[:if, 0, 6, 0, 10, 3]=>{[:then, 1, 7, 2, 7, 7]=>1, [:else, 2, 9, 2, 9, 7]=>0}}, :methods=>{}}}
*/
void
Init_coverage(void)
diff --git a/ext/coverage/depend b/ext/coverage/depend
index 20b76be04c..650b480b9b 100644
--- a/ext/coverage/depend
+++ b/ext/coverage/depend
@@ -3,9 +3,159 @@ coverage.o: $(RUBY_EXTCONF_H)
coverage.o: $(arch_hdrdir)/ruby/config.h
coverage.o: $(hdrdir)/ruby.h
coverage.o: $(hdrdir)/ruby/assert.h
+coverage.o: $(hdrdir)/ruby/atomic.h
coverage.o: $(hdrdir)/ruby/backward.h
+coverage.o: $(hdrdir)/ruby/backward/2/assume.h
+coverage.o: $(hdrdir)/ruby/backward/2/attributes.h
+coverage.o: $(hdrdir)/ruby/backward/2/bool.h
+coverage.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+coverage.o: $(hdrdir)/ruby/backward/2/inttypes.h
+coverage.o: $(hdrdir)/ruby/backward/2/limits.h
+coverage.o: $(hdrdir)/ruby/backward/2/long_long.h
+coverage.o: $(hdrdir)/ruby/backward/2/stdalign.h
+coverage.o: $(hdrdir)/ruby/backward/2/stdarg.h
coverage.o: $(hdrdir)/ruby/defines.h
coverage.o: $(hdrdir)/ruby/intern.h
+coverage.o: $(hdrdir)/ruby/internal/anyargs.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+coverage.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+coverage.o: $(hdrdir)/ruby/internal/assume.h
+coverage.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+coverage.o: $(hdrdir)/ruby/internal/attr/artificial.h
+coverage.o: $(hdrdir)/ruby/internal/attr/cold.h
+coverage.o: $(hdrdir)/ruby/internal/attr/const.h
+coverage.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+coverage.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+coverage.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+coverage.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+coverage.o: $(hdrdir)/ruby/internal/attr/error.h
+coverage.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+coverage.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+coverage.o: $(hdrdir)/ruby/internal/attr/format.h
+coverage.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+coverage.o: $(hdrdir)/ruby/internal/attr/noalias.h
+coverage.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+coverage.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+coverage.o: $(hdrdir)/ruby/internal/attr/noinline.h
+coverage.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+coverage.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+coverage.o: $(hdrdir)/ruby/internal/attr/pure.h
+coverage.o: $(hdrdir)/ruby/internal/attr/restrict.h
+coverage.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+coverage.o: $(hdrdir)/ruby/internal/attr/warning.h
+coverage.o: $(hdrdir)/ruby/internal/attr/weakref.h
+coverage.o: $(hdrdir)/ruby/internal/cast.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+coverage.o: $(hdrdir)/ruby/internal/compiler_since.h
+coverage.o: $(hdrdir)/ruby/internal/config.h
+coverage.o: $(hdrdir)/ruby/internal/constant_p.h
+coverage.o: $(hdrdir)/ruby/internal/core.h
+coverage.o: $(hdrdir)/ruby/internal/core/rarray.h
+coverage.o: $(hdrdir)/ruby/internal/core/rbasic.h
+coverage.o: $(hdrdir)/ruby/internal/core/rbignum.h
+coverage.o: $(hdrdir)/ruby/internal/core/rclass.h
+coverage.o: $(hdrdir)/ruby/internal/core/rdata.h
+coverage.o: $(hdrdir)/ruby/internal/core/rfile.h
+coverage.o: $(hdrdir)/ruby/internal/core/rhash.h
+coverage.o: $(hdrdir)/ruby/internal/core/robject.h
+coverage.o: $(hdrdir)/ruby/internal/core/rregexp.h
+coverage.o: $(hdrdir)/ruby/internal/core/rstring.h
+coverage.o: $(hdrdir)/ruby/internal/core/rstruct.h
+coverage.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+coverage.o: $(hdrdir)/ruby/internal/ctype.h
+coverage.o: $(hdrdir)/ruby/internal/dllexport.h
+coverage.o: $(hdrdir)/ruby/internal/dosish.h
+coverage.o: $(hdrdir)/ruby/internal/error.h
+coverage.o: $(hdrdir)/ruby/internal/eval.h
+coverage.o: $(hdrdir)/ruby/internal/event.h
+coverage.o: $(hdrdir)/ruby/internal/fl_type.h
+coverage.o: $(hdrdir)/ruby/internal/gc.h
+coverage.o: $(hdrdir)/ruby/internal/glob.h
+coverage.o: $(hdrdir)/ruby/internal/globals.h
+coverage.o: $(hdrdir)/ruby/internal/has/attribute.h
+coverage.o: $(hdrdir)/ruby/internal/has/builtin.h
+coverage.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+coverage.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+coverage.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+coverage.o: $(hdrdir)/ruby/internal/has/extension.h
+coverage.o: $(hdrdir)/ruby/internal/has/feature.h
+coverage.o: $(hdrdir)/ruby/internal/has/warning.h
+coverage.o: $(hdrdir)/ruby/internal/intern/array.h
+coverage.o: $(hdrdir)/ruby/internal/intern/bignum.h
+coverage.o: $(hdrdir)/ruby/internal/intern/class.h
+coverage.o: $(hdrdir)/ruby/internal/intern/compar.h
+coverage.o: $(hdrdir)/ruby/internal/intern/complex.h
+coverage.o: $(hdrdir)/ruby/internal/intern/cont.h
+coverage.o: $(hdrdir)/ruby/internal/intern/dir.h
+coverage.o: $(hdrdir)/ruby/internal/intern/enum.h
+coverage.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+coverage.o: $(hdrdir)/ruby/internal/intern/error.h
+coverage.o: $(hdrdir)/ruby/internal/intern/eval.h
+coverage.o: $(hdrdir)/ruby/internal/intern/file.h
+coverage.o: $(hdrdir)/ruby/internal/intern/gc.h
+coverage.o: $(hdrdir)/ruby/internal/intern/hash.h
+coverage.o: $(hdrdir)/ruby/internal/intern/io.h
+coverage.o: $(hdrdir)/ruby/internal/intern/load.h
+coverage.o: $(hdrdir)/ruby/internal/intern/marshal.h
+coverage.o: $(hdrdir)/ruby/internal/intern/numeric.h
+coverage.o: $(hdrdir)/ruby/internal/intern/object.h
+coverage.o: $(hdrdir)/ruby/internal/intern/parse.h
+coverage.o: $(hdrdir)/ruby/internal/intern/proc.h
+coverage.o: $(hdrdir)/ruby/internal/intern/process.h
+coverage.o: $(hdrdir)/ruby/internal/intern/random.h
+coverage.o: $(hdrdir)/ruby/internal/intern/range.h
+coverage.o: $(hdrdir)/ruby/internal/intern/rational.h
+coverage.o: $(hdrdir)/ruby/internal/intern/re.h
+coverage.o: $(hdrdir)/ruby/internal/intern/ruby.h
+coverage.o: $(hdrdir)/ruby/internal/intern/select.h
+coverage.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+coverage.o: $(hdrdir)/ruby/internal/intern/signal.h
+coverage.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+coverage.o: $(hdrdir)/ruby/internal/intern/string.h
+coverage.o: $(hdrdir)/ruby/internal/intern/struct.h
+coverage.o: $(hdrdir)/ruby/internal/intern/thread.h
+coverage.o: $(hdrdir)/ruby/internal/intern/time.h
+coverage.o: $(hdrdir)/ruby/internal/intern/variable.h
+coverage.o: $(hdrdir)/ruby/internal/intern/vm.h
+coverage.o: $(hdrdir)/ruby/internal/interpreter.h
+coverage.o: $(hdrdir)/ruby/internal/iterator.h
+coverage.o: $(hdrdir)/ruby/internal/memory.h
+coverage.o: $(hdrdir)/ruby/internal/method.h
+coverage.o: $(hdrdir)/ruby/internal/module.h
+coverage.o: $(hdrdir)/ruby/internal/newobj.h
+coverage.o: $(hdrdir)/ruby/internal/rgengc.h
+coverage.o: $(hdrdir)/ruby/internal/scan_args.h
+coverage.o: $(hdrdir)/ruby/internal/special_consts.h
+coverage.o: $(hdrdir)/ruby/internal/static_assert.h
+coverage.o: $(hdrdir)/ruby/internal/stdalign.h
+coverage.o: $(hdrdir)/ruby/internal/stdbool.h
+coverage.o: $(hdrdir)/ruby/internal/symbol.h
+coverage.o: $(hdrdir)/ruby/internal/token_paste.h
+coverage.o: $(hdrdir)/ruby/internal/value.h
+coverage.o: $(hdrdir)/ruby/internal/value_type.h
+coverage.o: $(hdrdir)/ruby/internal/variable.h
+coverage.o: $(hdrdir)/ruby/internal/warning_push.h
+coverage.o: $(hdrdir)/ruby/internal/xmalloc.h
coverage.o: $(hdrdir)/ruby/missing.h
coverage.o: $(hdrdir)/ruby/ruby.h
coverage.o: $(hdrdir)/ruby/st.h
@@ -17,6 +167,17 @@ coverage.o: $(top_srcdir)/ccan/list/list.h
coverage.o: $(top_srcdir)/ccan/str/str.h
coverage.o: $(top_srcdir)/gc.h
coverage.o: $(top_srcdir)/internal.h
+coverage.o: $(top_srcdir)/internal/array.h
+coverage.o: $(top_srcdir)/internal/compilers.h
+coverage.o: $(top_srcdir)/internal/gc.h
+coverage.o: $(top_srcdir)/internal/hash.h
+coverage.o: $(top_srcdir)/internal/imemo.h
+coverage.o: $(top_srcdir)/internal/sanitizers.h
+coverage.o: $(top_srcdir)/internal/serial.h
+coverage.o: $(top_srcdir)/internal/static_assert.h
+coverage.o: $(top_srcdir)/internal/thread.h
+coverage.o: $(top_srcdir)/internal/vm.h
+coverage.o: $(top_srcdir)/internal/warnings.h
coverage.o: $(top_srcdir)/method.h
coverage.o: $(top_srcdir)/node.h
coverage.o: $(top_srcdir)/ruby_assert.h
diff --git a/ext/date/date.gemspec b/ext/date/date.gemspec
index 847cd0b295..cf07696976 100644
--- a/ext/date/date.gemspec
+++ b/ext/date/date.gemspec
@@ -22,5 +22,5 @@ Gem::Specification.new do |s|
s.authors = ["Tadayoshi Funaba"]
s.email = [nil]
s.homepage = "https://github.com/ruby/date"
- s.license = "BSD-2-Clause"
+ s.licenses = ["Ruby", "BSD-2-Clause"]
end
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index 3917f3e38b..66ec0aa92a 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -53,6 +53,8 @@ static double positive_inf, negative_inf;
#define f_add3(x,y,z) f_add(f_add(x, y), z)
#define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
+#define f_frozen_ary(...) rb_obj_freeze(rb_ary_new3(__VA_ARGS__))
+
static VALUE date_initialize(int argc, VALUE *argv, VALUE self);
static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self);
@@ -2971,11 +2973,15 @@ d_lite_memsize(const void *ptr)
return complex_dat_p(dat) ? sizeof(struct ComplexDateData) : sizeof(struct SimpleDateData);
}
+#ifndef HAVE_RB_EXT_RACTOR_SAFE
+# define RUBY_TYPED_FROZEN_SHAREABLE 0
+#endif
+
static const rb_data_type_t d_lite_type = {
"Date",
{d_lite_gc_mark, RUBY_TYPED_DEFAULT_FREE, d_lite_memsize,},
0, 0,
- RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED,
+ RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED|RUBY_TYPED_FROZEN_SHAREABLE,
};
inline static VALUE
@@ -3767,89 +3773,89 @@ rt_complete_frags(VALUE klass, VALUE hash)
VALUE k, a, d;
if (NIL_P(tab)) {
- tab = rb_ary_new3(11,
- rb_ary_new3(2,
+ tab = f_frozen_ary(11,
+ f_frozen_ary(2,
sym("time"),
- rb_ary_new3(3,
+ f_frozen_ary(3,
sym("hour"),
sym("min"),
sym("sec"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
Qnil,
- rb_ary_new3(1,
+ f_frozen_ary(1,
sym("jd"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
sym("ordinal"),
- rb_ary_new3(5,
+ f_frozen_ary(5,
sym("year"),
sym("yday"),
sym("hour"),
sym("min"),
sym("sec"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
sym("civil"),
- rb_ary_new3(6,
+ f_frozen_ary(6,
sym("year"),
sym("mon"),
sym("mday"),
sym("hour"),
sym("min"),
sym("sec"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
sym("commercial"),
- rb_ary_new3(6,
+ f_frozen_ary(6,
sym("cwyear"),
sym("cweek"),
sym("cwday"),
sym("hour"),
sym("min"),
sym("sec"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
sym("wday"),
- rb_ary_new3(4,
+ f_frozen_ary(4,
sym("wday"),
sym("hour"),
sym("min"),
sym("sec"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
sym("wnum0"),
- rb_ary_new3(6,
+ f_frozen_ary(6,
sym("year"),
sym("wnum0"),
sym("wday"),
sym("hour"),
sym("min"),
sym("sec"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
sym("wnum1"),
- rb_ary_new3(6,
+ f_frozen_ary(6,
sym("year"),
sym("wnum1"),
sym("wday"),
sym("hour"),
sym("min"),
sym("sec"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
Qnil,
- rb_ary_new3(6,
+ f_frozen_ary(6,
sym("cwyear"),
sym("cweek"),
sym("wday"),
sym("hour"),
sym("min"),
sym("sec"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
Qnil,
- rb_ary_new3(6,
+ f_frozen_ary(6,
sym("year"),
sym("wnum0"),
sym("cwday"),
sym("hour"),
sym("min"),
sym("sec"))),
- rb_ary_new3(2,
+ f_frozen_ary(2,
Qnil,
- rb_ary_new3(6,
+ f_frozen_ary(6,
sym("year"),
sym("wnum1"),
sym("cwday"),
@@ -4373,8 +4379,12 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
* Date._parse(string[, comp=true], limit: 128) -> hash
*
* Parses the given representation of date and time, and returns a
- * hash of parsed elements. This method does not function as a
- * validator.
+ * hash of parsed elements.
+ *
+ * This method **does not** function as a validator. If the input
+ * string does not match valid formats strictly, you may get a cryptic
+ * result. Should consider to use `Date._strptime` or
+ * `DateTime._strptime` instead of this method as possible.
*
* If the optional second argument is true and the detected year is in
* the range "00" to "99", considers the year a 2-digit form and makes
@@ -4397,7 +4407,12 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
* Date.parse(string='-4712-01-01'[, comp=true[, start=Date::ITALY]], limit: 128) -> date
*
* Parses the given representation of date and time, and creates a
- * date object. This method does not function as a validator.
+ * date object.
+ *
+ * This method **does not** function as a validator. If the input
+ * string does not match valid formats strictly, you may get a cryptic
+ * result. Should consider to use `Date.strptime` instead of this
+ * method as possible.
*
* If the optional second argument is true and the detected year is in
* the range "00" to "99", considers the year a 2-digit form and makes
@@ -8145,7 +8160,12 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
* DateTime.parse(string='-4712-01-01T00:00:00+00:00'[, comp=true[, start=Date::ITALY]], limit: 128) -> datetime
*
* Parses the given representation of date and time, and creates a
- * DateTime object. This method does not function as a validator.
+ * DateTime object.
+ *
+ * This method **does not** function as a validator. If the input
+ * string does not match valid formats strictly, you may get a cryptic
+ * result. Should consider to use `DateTime.strptime` instead of this
+ * method as possible.
*
* If the optional second argument is true and the detected year is in
* the range "00" to "99", makes it full.
@@ -9313,13 +9333,13 @@ d_lite_zero(VALUE x)
void
Init_date_core(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
- id_cmp = rb_intern("<=>");
- id_le_p = rb_intern("<=");
- id_ge_p = rb_intern(">=");
- id_eqeq_p = rb_intern("==");
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+ #endif
+ id_cmp = rb_intern_const("<=>");
+ id_le_p = rb_intern_const("<=");
+ id_ge_p = rb_intern_const(">=");
+ id_eqeq_p = rb_intern_const("==");
half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2));
@@ -9726,6 +9746,8 @@ Init_date_core(void)
* A subclass of Date that easily handles date, hour, minute, second,
* and offset.
*
+ * DateTime class is considered deprecated. Use Time class.
+ *
* DateTime does not consider any leap seconds, does not track
* any summer time rules.
*
@@ -9786,18 +9808,18 @@ Init_date_core(void)
* === When should you use DateTime and when should you use Time?
*
* It's a common misconception that
- * {William Shakespeare}[http://en.wikipedia.org/wiki/William_Shakespeare]
+ * {William Shakespeare}[https://en.wikipedia.org/wiki/William_Shakespeare]
* and
- * {Miguel de Cervantes}[http://en.wikipedia.org/wiki/Miguel_de_Cervantes]
+ * {Miguel de Cervantes}[https://en.wikipedia.org/wiki/Miguel_de_Cervantes]
* died on the same day in history -
* so much so that UNESCO named April 23 as
- * {World Book Day because of this fact}[http://en.wikipedia.org/wiki/World_Book_Day].
+ * {World Book Day because of this fact}[https://en.wikipedia.org/wiki/World_Book_Day].
* However, because England hadn't yet adopted the
- * {Gregorian Calendar Reform}[http://en.wikipedia.org/wiki/Gregorian_calendar#Gregorian_reform]
- * (and wouldn't until {1752}[http://en.wikipedia.org/wiki/Calendar_(New_Style)_Act_1750])
+ * {Gregorian Calendar Reform}[https://en.wikipedia.org/wiki/Gregorian_calendar#Gregorian_reform]
+ * (and wouldn't until {1752}[https://en.wikipedia.org/wiki/Calendar_(New_Style)_Act_1750])
* their deaths are actually 10 days apart.
* Since Ruby's Time class implements a
- * {proleptic Gregorian calendar}[http://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar]
+ * {proleptic Gregorian calendar}[https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar]
* and has no concept of calendar reform there's no way
* to express this with Time objects. This is where DateTime steps in:
*
@@ -9841,7 +9863,7 @@ Init_date_core(void)
* #=> Fri, 04 May 1753 00:00:00 +0000
*
* As you can see, if we're accurately tracking the number of
- * {solar years}[http://en.wikipedia.org/wiki/Tropical_year]
+ * {solar years}[https://en.wikipedia.org/wiki/Tropical_year]
* since Shakespeare's birthday then the correct anniversary date
* would be the 4th May and not the 23rd April.
*
@@ -9853,10 +9875,10 @@ Init_date_core(void)
* making the same mistakes as UNESCO. If you also have to deal
* with timezones then best of luck - just bear in mind that
* you'll probably be dealing with
- * {local solar times}[http://en.wikipedia.org/wiki/Solar_time],
+ * {local solar times}[https://en.wikipedia.org/wiki/Solar_time],
* since it wasn't until the 19th century that the introduction
* of the railways necessitated the need for
- * {Standard Time}[http://en.wikipedia.org/wiki/Standard_time#Great_Britain]
+ * {Standard Time}[https://en.wikipedia.org/wiki/Standard_time#Great_Britain]
* and eventually timezones.
*/
diff --git a/ext/date/date_parse.c b/ext/date/date_parse.c
index 0378e50cf7..5fa036ed72 100644
--- a/ext/date/date_parse.c
+++ b/ext/date/date_parse.c
@@ -276,6 +276,7 @@ regcomp(const char *source, long len, int opt)
VALUE pat;
pat = rb_reg_new(source, len, opt);
+ rb_obj_freeze(pat);
rb_gc_register_mark_object(pat);
return pat;
}
diff --git a/ext/date/date_strptime.c b/ext/date/date_strptime.c
index 26d9fd11bf..7b06a31471 100644
--- a/ext/date/date_strptime.c
+++ b/ext/date/date_strptime.c
@@ -581,6 +581,7 @@ date__strptime_internal(const char *str, size_t slen,
if (NIL_P(pat)) {
pat = rb_reg_new(pat_source, sizeof pat_source - 1,
ONIG_OPTION_IGNORECASE);
+ rb_obj_freeze(pat);
rb_gc_register_mark_object(pat);
}
diff --git a/ext/date/depend b/ext/date/depend
index 28847bef13..c686530c70 100644
--- a/ext/date/depend
+++ b/ext/date/depend
@@ -2,8 +2,157 @@
date_core.o: $(RUBY_EXTCONF_H)
date_core.o: $(arch_hdrdir)/ruby/config.h
date_core.o: $(hdrdir)/ruby.h
+date_core.o: $(hdrdir)/ruby/internal/anyargs.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+date_core.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+date_core.o: $(hdrdir)/ruby/internal/assume.h
+date_core.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+date_core.o: $(hdrdir)/ruby/internal/attr/artificial.h
+date_core.o: $(hdrdir)/ruby/internal/attr/cold.h
+date_core.o: $(hdrdir)/ruby/internal/attr/const.h
+date_core.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+date_core.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+date_core.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+date_core.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+date_core.o: $(hdrdir)/ruby/internal/attr/error.h
+date_core.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+date_core.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+date_core.o: $(hdrdir)/ruby/internal/attr/format.h
+date_core.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+date_core.o: $(hdrdir)/ruby/internal/attr/noalias.h
+date_core.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+date_core.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+date_core.o: $(hdrdir)/ruby/internal/attr/noinline.h
+date_core.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+date_core.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+date_core.o: $(hdrdir)/ruby/internal/attr/pure.h
+date_core.o: $(hdrdir)/ruby/internal/attr/restrict.h
+date_core.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+date_core.o: $(hdrdir)/ruby/internal/attr/warning.h
+date_core.o: $(hdrdir)/ruby/internal/attr/weakref.h
+date_core.o: $(hdrdir)/ruby/internal/cast.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+date_core.o: $(hdrdir)/ruby/internal/compiler_since.h
+date_core.o: $(hdrdir)/ruby/internal/config.h
+date_core.o: $(hdrdir)/ruby/internal/constant_p.h
+date_core.o: $(hdrdir)/ruby/internal/core.h
+date_core.o: $(hdrdir)/ruby/internal/core/rarray.h
+date_core.o: $(hdrdir)/ruby/internal/core/rbasic.h
+date_core.o: $(hdrdir)/ruby/internal/core/rbignum.h
+date_core.o: $(hdrdir)/ruby/internal/core/rclass.h
+date_core.o: $(hdrdir)/ruby/internal/core/rdata.h
+date_core.o: $(hdrdir)/ruby/internal/core/rfile.h
+date_core.o: $(hdrdir)/ruby/internal/core/rhash.h
+date_core.o: $(hdrdir)/ruby/internal/core/robject.h
+date_core.o: $(hdrdir)/ruby/internal/core/rregexp.h
+date_core.o: $(hdrdir)/ruby/internal/core/rstring.h
+date_core.o: $(hdrdir)/ruby/internal/core/rstruct.h
+date_core.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+date_core.o: $(hdrdir)/ruby/internal/ctype.h
+date_core.o: $(hdrdir)/ruby/internal/dllexport.h
+date_core.o: $(hdrdir)/ruby/internal/dosish.h
+date_core.o: $(hdrdir)/ruby/internal/error.h
+date_core.o: $(hdrdir)/ruby/internal/eval.h
+date_core.o: $(hdrdir)/ruby/internal/event.h
+date_core.o: $(hdrdir)/ruby/internal/fl_type.h
+date_core.o: $(hdrdir)/ruby/internal/gc.h
+date_core.o: $(hdrdir)/ruby/internal/glob.h
+date_core.o: $(hdrdir)/ruby/internal/globals.h
+date_core.o: $(hdrdir)/ruby/internal/has/attribute.h
+date_core.o: $(hdrdir)/ruby/internal/has/builtin.h
+date_core.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+date_core.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+date_core.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+date_core.o: $(hdrdir)/ruby/internal/has/extension.h
+date_core.o: $(hdrdir)/ruby/internal/has/feature.h
+date_core.o: $(hdrdir)/ruby/internal/has/warning.h
+date_core.o: $(hdrdir)/ruby/internal/intern/array.h
+date_core.o: $(hdrdir)/ruby/internal/intern/bignum.h
+date_core.o: $(hdrdir)/ruby/internal/intern/class.h
+date_core.o: $(hdrdir)/ruby/internal/intern/compar.h
+date_core.o: $(hdrdir)/ruby/internal/intern/complex.h
+date_core.o: $(hdrdir)/ruby/internal/intern/cont.h
+date_core.o: $(hdrdir)/ruby/internal/intern/dir.h
+date_core.o: $(hdrdir)/ruby/internal/intern/enum.h
+date_core.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+date_core.o: $(hdrdir)/ruby/internal/intern/error.h
+date_core.o: $(hdrdir)/ruby/internal/intern/eval.h
+date_core.o: $(hdrdir)/ruby/internal/intern/file.h
+date_core.o: $(hdrdir)/ruby/internal/intern/gc.h
+date_core.o: $(hdrdir)/ruby/internal/intern/hash.h
+date_core.o: $(hdrdir)/ruby/internal/intern/io.h
+date_core.o: $(hdrdir)/ruby/internal/intern/load.h
+date_core.o: $(hdrdir)/ruby/internal/intern/marshal.h
+date_core.o: $(hdrdir)/ruby/internal/intern/numeric.h
+date_core.o: $(hdrdir)/ruby/internal/intern/object.h
+date_core.o: $(hdrdir)/ruby/internal/intern/parse.h
+date_core.o: $(hdrdir)/ruby/internal/intern/proc.h
+date_core.o: $(hdrdir)/ruby/internal/intern/process.h
+date_core.o: $(hdrdir)/ruby/internal/intern/random.h
+date_core.o: $(hdrdir)/ruby/internal/intern/range.h
+date_core.o: $(hdrdir)/ruby/internal/intern/rational.h
+date_core.o: $(hdrdir)/ruby/internal/intern/re.h
+date_core.o: $(hdrdir)/ruby/internal/intern/ruby.h
+date_core.o: $(hdrdir)/ruby/internal/intern/select.h
+date_core.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_core.o: $(hdrdir)/ruby/internal/intern/signal.h
+date_core.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+date_core.o: $(hdrdir)/ruby/internal/intern/string.h
+date_core.o: $(hdrdir)/ruby/internal/intern/struct.h
+date_core.o: $(hdrdir)/ruby/internal/intern/thread.h
+date_core.o: $(hdrdir)/ruby/internal/intern/time.h
+date_core.o: $(hdrdir)/ruby/internal/intern/variable.h
+date_core.o: $(hdrdir)/ruby/internal/intern/vm.h
+date_core.o: $(hdrdir)/ruby/internal/interpreter.h
+date_core.o: $(hdrdir)/ruby/internal/iterator.h
+date_core.o: $(hdrdir)/ruby/internal/memory.h
+date_core.o: $(hdrdir)/ruby/internal/method.h
+date_core.o: $(hdrdir)/ruby/internal/module.h
+date_core.o: $(hdrdir)/ruby/internal/newobj.h
+date_core.o: $(hdrdir)/ruby/internal/rgengc.h
+date_core.o: $(hdrdir)/ruby/internal/scan_args.h
+date_core.o: $(hdrdir)/ruby/internal/special_consts.h
+date_core.o: $(hdrdir)/ruby/internal/static_assert.h
+date_core.o: $(hdrdir)/ruby/internal/stdalign.h
+date_core.o: $(hdrdir)/ruby/internal/stdbool.h
+date_core.o: $(hdrdir)/ruby/internal/symbol.h
+date_core.o: $(hdrdir)/ruby/internal/token_paste.h
+date_core.o: $(hdrdir)/ruby/internal/value.h
+date_core.o: $(hdrdir)/ruby/internal/value_type.h
+date_core.o: $(hdrdir)/ruby/internal/variable.h
+date_core.o: $(hdrdir)/ruby/internal/warning_push.h
+date_core.o: $(hdrdir)/ruby/internal/xmalloc.h
date_core.o: $(hdrdir)/ruby/assert.h
date_core.o: $(hdrdir)/ruby/backward.h
+date_core.o: $(hdrdir)/ruby/backward/2/assume.h
+date_core.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_core.o: $(hdrdir)/ruby/backward/2/bool.h
+date_core.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+date_core.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_core.o: $(hdrdir)/ruby/backward/2/limits.h
+date_core.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_core.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_core.o: $(hdrdir)/ruby/backward/2/stdarg.h
date_core.o: $(hdrdir)/ruby/defines.h
date_core.o: $(hdrdir)/ruby/encoding.h
date_core.o: $(hdrdir)/ruby/intern.h
@@ -19,8 +168,158 @@ date_core.o: date_tmx.h
date_parse.o: $(RUBY_EXTCONF_H)
date_parse.o: $(arch_hdrdir)/ruby/config.h
date_parse.o: $(hdrdir)/ruby.h
+date_parse.o: $(hdrdir)/ruby/internal/anyargs.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+date_parse.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+date_parse.o: $(hdrdir)/ruby/internal/assume.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/artificial.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/cold.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/const.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/error.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/format.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/noalias.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/noinline.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/pure.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/restrict.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/warning.h
+date_parse.o: $(hdrdir)/ruby/internal/attr/weakref.h
+date_parse.o: $(hdrdir)/ruby/internal/cast.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+date_parse.o: $(hdrdir)/ruby/internal/compiler_since.h
+date_parse.o: $(hdrdir)/ruby/internal/config.h
+date_parse.o: $(hdrdir)/ruby/internal/constant_p.h
+date_parse.o: $(hdrdir)/ruby/internal/core.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rarray.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rbasic.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rbignum.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rclass.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rdata.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rfile.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rhash.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rmatch.h
+date_parse.o: $(hdrdir)/ruby/internal/core/robject.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rregexp.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rstring.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rstruct.h
+date_parse.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+date_parse.o: $(hdrdir)/ruby/internal/ctype.h
+date_parse.o: $(hdrdir)/ruby/internal/dllexport.h
+date_parse.o: $(hdrdir)/ruby/internal/dosish.h
+date_parse.o: $(hdrdir)/ruby/internal/error.h
+date_parse.o: $(hdrdir)/ruby/internal/eval.h
+date_parse.o: $(hdrdir)/ruby/internal/event.h
+date_parse.o: $(hdrdir)/ruby/internal/fl_type.h
+date_parse.o: $(hdrdir)/ruby/internal/gc.h
+date_parse.o: $(hdrdir)/ruby/internal/glob.h
+date_parse.o: $(hdrdir)/ruby/internal/globals.h
+date_parse.o: $(hdrdir)/ruby/internal/has/attribute.h
+date_parse.o: $(hdrdir)/ruby/internal/has/builtin.h
+date_parse.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+date_parse.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+date_parse.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+date_parse.o: $(hdrdir)/ruby/internal/has/extension.h
+date_parse.o: $(hdrdir)/ruby/internal/has/feature.h
+date_parse.o: $(hdrdir)/ruby/internal/has/warning.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/array.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/bignum.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/class.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/compar.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/complex.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/cont.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/dir.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/enum.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/error.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/eval.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/file.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/gc.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/hash.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/io.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/load.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/marshal.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/numeric.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/object.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/parse.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/proc.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/process.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/random.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/range.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/rational.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/re.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/ruby.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/select.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/signal.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/string.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/struct.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/thread.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/time.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/variable.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/vm.h
+date_parse.o: $(hdrdir)/ruby/internal/interpreter.h
+date_parse.o: $(hdrdir)/ruby/internal/iterator.h
+date_parse.o: $(hdrdir)/ruby/internal/memory.h
+date_parse.o: $(hdrdir)/ruby/internal/method.h
+date_parse.o: $(hdrdir)/ruby/internal/module.h
+date_parse.o: $(hdrdir)/ruby/internal/newobj.h
+date_parse.o: $(hdrdir)/ruby/internal/rgengc.h
+date_parse.o: $(hdrdir)/ruby/internal/scan_args.h
+date_parse.o: $(hdrdir)/ruby/internal/special_consts.h
+date_parse.o: $(hdrdir)/ruby/internal/static_assert.h
+date_parse.o: $(hdrdir)/ruby/internal/stdalign.h
+date_parse.o: $(hdrdir)/ruby/internal/stdbool.h
+date_parse.o: $(hdrdir)/ruby/internal/symbol.h
+date_parse.o: $(hdrdir)/ruby/internal/token_paste.h
+date_parse.o: $(hdrdir)/ruby/internal/value.h
+date_parse.o: $(hdrdir)/ruby/internal/value_type.h
+date_parse.o: $(hdrdir)/ruby/internal/variable.h
+date_parse.o: $(hdrdir)/ruby/internal/warning_push.h
+date_parse.o: $(hdrdir)/ruby/internal/xmalloc.h
date_parse.o: $(hdrdir)/ruby/assert.h
date_parse.o: $(hdrdir)/ruby/backward.h
+date_parse.o: $(hdrdir)/ruby/backward/2/assume.h
+date_parse.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_parse.o: $(hdrdir)/ruby/backward/2/bool.h
+date_parse.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+date_parse.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_parse.o: $(hdrdir)/ruby/backward/2/limits.h
+date_parse.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_parse.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_parse.o: $(hdrdir)/ruby/backward/2/stdarg.h
date_parse.o: $(hdrdir)/ruby/defines.h
date_parse.o: $(hdrdir)/ruby/encoding.h
date_parse.o: $(hdrdir)/ruby/intern.h
@@ -37,8 +336,157 @@ date_parse.o: zonetab.h
date_parse.o: zonetab.list
date_strftime.o: $(RUBY_EXTCONF_H)
date_strftime.o: $(arch_hdrdir)/ruby/config.h
+date_strftime.o: $(hdrdir)/ruby/internal/anyargs.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+date_strftime.o: $(hdrdir)/ruby/internal/assume.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/artificial.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/cold.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/const.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/error.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/format.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/noalias.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/noinline.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/pure.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/restrict.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/warning.h
+date_strftime.o: $(hdrdir)/ruby/internal/attr/weakref.h
+date_strftime.o: $(hdrdir)/ruby/internal/cast.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+date_strftime.o: $(hdrdir)/ruby/internal/compiler_since.h
+date_strftime.o: $(hdrdir)/ruby/internal/config.h
+date_strftime.o: $(hdrdir)/ruby/internal/constant_p.h
+date_strftime.o: $(hdrdir)/ruby/internal/core.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rarray.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rbasic.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rbignum.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rclass.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rdata.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rfile.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rhash.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/robject.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rregexp.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rstring.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rstruct.h
+date_strftime.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+date_strftime.o: $(hdrdir)/ruby/internal/ctype.h
+date_strftime.o: $(hdrdir)/ruby/internal/dllexport.h
+date_strftime.o: $(hdrdir)/ruby/internal/dosish.h
+date_strftime.o: $(hdrdir)/ruby/internal/error.h
+date_strftime.o: $(hdrdir)/ruby/internal/eval.h
+date_strftime.o: $(hdrdir)/ruby/internal/event.h
+date_strftime.o: $(hdrdir)/ruby/internal/fl_type.h
+date_strftime.o: $(hdrdir)/ruby/internal/gc.h
+date_strftime.o: $(hdrdir)/ruby/internal/glob.h
+date_strftime.o: $(hdrdir)/ruby/internal/globals.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/attribute.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/builtin.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/extension.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/feature.h
+date_strftime.o: $(hdrdir)/ruby/internal/has/warning.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/array.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/bignum.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/class.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/compar.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/complex.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/cont.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/dir.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/enum.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/error.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/eval.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/file.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/gc.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/hash.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/io.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/load.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/marshal.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/numeric.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/object.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/parse.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/proc.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/process.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/random.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/range.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/rational.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/re.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/ruby.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/select.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/signal.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/string.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/struct.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/thread.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/time.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/variable.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/vm.h
+date_strftime.o: $(hdrdir)/ruby/internal/interpreter.h
+date_strftime.o: $(hdrdir)/ruby/internal/iterator.h
+date_strftime.o: $(hdrdir)/ruby/internal/memory.h
+date_strftime.o: $(hdrdir)/ruby/internal/method.h
+date_strftime.o: $(hdrdir)/ruby/internal/module.h
+date_strftime.o: $(hdrdir)/ruby/internal/newobj.h
+date_strftime.o: $(hdrdir)/ruby/internal/rgengc.h
+date_strftime.o: $(hdrdir)/ruby/internal/scan_args.h
+date_strftime.o: $(hdrdir)/ruby/internal/special_consts.h
+date_strftime.o: $(hdrdir)/ruby/internal/static_assert.h
+date_strftime.o: $(hdrdir)/ruby/internal/stdalign.h
+date_strftime.o: $(hdrdir)/ruby/internal/stdbool.h
+date_strftime.o: $(hdrdir)/ruby/internal/symbol.h
+date_strftime.o: $(hdrdir)/ruby/internal/token_paste.h
+date_strftime.o: $(hdrdir)/ruby/internal/value.h
+date_strftime.o: $(hdrdir)/ruby/internal/value_type.h
+date_strftime.o: $(hdrdir)/ruby/internal/variable.h
+date_strftime.o: $(hdrdir)/ruby/internal/warning_push.h
+date_strftime.o: $(hdrdir)/ruby/internal/xmalloc.h
date_strftime.o: $(hdrdir)/ruby/assert.h
date_strftime.o: $(hdrdir)/ruby/backward.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/assume.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/bool.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/limits.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_strftime.o: $(hdrdir)/ruby/backward/2/stdarg.h
date_strftime.o: $(hdrdir)/ruby/defines.h
date_strftime.o: $(hdrdir)/ruby/intern.h
date_strftime.o: $(hdrdir)/ruby/missing.h
@@ -50,8 +498,158 @@ date_strftime.o: date_tmx.h
date_strptime.o: $(RUBY_EXTCONF_H)
date_strptime.o: $(arch_hdrdir)/ruby/config.h
date_strptime.o: $(hdrdir)/ruby.h
+date_strptime.o: $(hdrdir)/ruby/internal/anyargs.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+date_strptime.o: $(hdrdir)/ruby/internal/assume.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/artificial.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/cold.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/const.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/error.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/format.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/noalias.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/noinline.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/pure.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/restrict.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/warning.h
+date_strptime.o: $(hdrdir)/ruby/internal/attr/weakref.h
+date_strptime.o: $(hdrdir)/ruby/internal/cast.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+date_strptime.o: $(hdrdir)/ruby/internal/compiler_since.h
+date_strptime.o: $(hdrdir)/ruby/internal/config.h
+date_strptime.o: $(hdrdir)/ruby/internal/constant_p.h
+date_strptime.o: $(hdrdir)/ruby/internal/core.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rarray.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rbasic.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rbignum.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rclass.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rdata.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rfile.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rhash.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rmatch.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/robject.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rregexp.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rstring.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rstruct.h
+date_strptime.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+date_strptime.o: $(hdrdir)/ruby/internal/ctype.h
+date_strptime.o: $(hdrdir)/ruby/internal/dllexport.h
+date_strptime.o: $(hdrdir)/ruby/internal/dosish.h
+date_strptime.o: $(hdrdir)/ruby/internal/error.h
+date_strptime.o: $(hdrdir)/ruby/internal/eval.h
+date_strptime.o: $(hdrdir)/ruby/internal/event.h
+date_strptime.o: $(hdrdir)/ruby/internal/fl_type.h
+date_strptime.o: $(hdrdir)/ruby/internal/gc.h
+date_strptime.o: $(hdrdir)/ruby/internal/glob.h
+date_strptime.o: $(hdrdir)/ruby/internal/globals.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/attribute.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/builtin.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/extension.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/feature.h
+date_strptime.o: $(hdrdir)/ruby/internal/has/warning.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/array.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/bignum.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/class.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/compar.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/complex.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/cont.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/dir.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/enum.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/error.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/eval.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/file.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/gc.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/hash.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/io.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/load.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/marshal.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/numeric.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/object.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/parse.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/proc.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/process.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/random.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/range.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/rational.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/re.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/ruby.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/select.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/signal.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/string.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/struct.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/thread.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/time.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/variable.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/vm.h
+date_strptime.o: $(hdrdir)/ruby/internal/interpreter.h
+date_strptime.o: $(hdrdir)/ruby/internal/iterator.h
+date_strptime.o: $(hdrdir)/ruby/internal/memory.h
+date_strptime.o: $(hdrdir)/ruby/internal/method.h
+date_strptime.o: $(hdrdir)/ruby/internal/module.h
+date_strptime.o: $(hdrdir)/ruby/internal/newobj.h
+date_strptime.o: $(hdrdir)/ruby/internal/rgengc.h
+date_strptime.o: $(hdrdir)/ruby/internal/scan_args.h
+date_strptime.o: $(hdrdir)/ruby/internal/special_consts.h
+date_strptime.o: $(hdrdir)/ruby/internal/static_assert.h
+date_strptime.o: $(hdrdir)/ruby/internal/stdalign.h
+date_strptime.o: $(hdrdir)/ruby/internal/stdbool.h
+date_strptime.o: $(hdrdir)/ruby/internal/symbol.h
+date_strptime.o: $(hdrdir)/ruby/internal/token_paste.h
+date_strptime.o: $(hdrdir)/ruby/internal/value.h
+date_strptime.o: $(hdrdir)/ruby/internal/value_type.h
+date_strptime.o: $(hdrdir)/ruby/internal/variable.h
+date_strptime.o: $(hdrdir)/ruby/internal/warning_push.h
+date_strptime.o: $(hdrdir)/ruby/internal/xmalloc.h
date_strptime.o: $(hdrdir)/ruby/assert.h
date_strptime.o: $(hdrdir)/ruby/backward.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/assume.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/attributes.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/bool.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/inttypes.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/limits.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/long_long.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/stdalign.h
+date_strptime.o: $(hdrdir)/ruby/backward/2/stdarg.h
date_strptime.o: $(hdrdir)/ruby/defines.h
date_strptime.o: $(hdrdir)/ruby/encoding.h
date_strptime.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/date/lib/date.rb b/ext/date/lib/date.rb
index 94abd6451a..0a49076ab6 100644
--- a/ext/date/lib/date.rb
+++ b/ext/date/lib/date.rb
@@ -4,7 +4,7 @@
require 'date_core'
class Date
- VERSION = '3.0.3' # :nodoc:
+ VERSION = '3.1.3' # :nodoc:
def infinite?
false
@@ -12,8 +12,6 @@ class Date
class Infinity < Numeric # :nodoc:
- include Comparable
-
def initialize(d=1) @d = d <=> 0 end
def d() @d end
diff --git a/ext/date/prereq.mk b/ext/date/prereq.mk
index fa371e0d47..eb71e55e71 100644
--- a/ext/date/prereq.mk
+++ b/ext/date/prereq.mk
@@ -9,4 +9,4 @@ zonetab.h: zonetab.list
.PHONY: update-zonetab
update-zonetab:
- $(RUBY) -C $(srcdir) update-abbr.rb
+ $(RUBY) -C $(srcdir) update-abbr
diff --git a/ext/date/update-abbr b/ext/date/update-abbr
index e5f6a78c82..7fe9734e6d 100644
--- a/ext/date/update-abbr
+++ b/ext/date/update-abbr
@@ -2,7 +2,7 @@
require 'nokogiri'
require 'open-uri'
-doc = Nokogiri::HTML(URI.open('https://www.timeanddate.com/time/zones/'))
+doc = Nokogiri::HTML(URI.open(ARGV[0] || 'https://www.timeanddate.com/time/zones/'))
h = {}
@@ -26,9 +26,26 @@ end
h.delete_if{|_,v| !v}
lines = File.readlines('zonetab.list')
-lines.select{|l| l.include?(',')}.
- map{|l| l.split(',', 2)[0]}.
- each{|a| h.delete(a)}
+lines.map! do |l|
+ if (sep = /^%%/ =~ l)...(sep = /^%%/ =~ l) and !sep
+ z, o = l.split(/,\s*/, 2)
+ o.strip!
+ if ho = h.delete(z) and ho != eval(o)
+ warn "offset of #{z}: #{o} -> #{ho}"
+ l = l.sub(/,\s*\K.*/) {
+ if o.include?("*")
+ o1, o2 = ho.abs.divmod(3600)
+ o1 = "#{o1}*3600"
+ o1 = "(#{o1}+#{o2})" if o2 != 0
+ ho < 0 ? "-#{o1}" : o1
+ else
+ ho.to_s
+ end
+ }
+ end
+ end
+ l
+end
lines.insert(-2, h.sort.map{|k,v| "#{k},#{v}\n"})
lines.flatten!
diff --git a/ext/date/zonetab.list b/ext/date/zonetab.list
index 0618546eb0..d2f902d2d5 100644
--- a/ext/date/zonetab.list
+++ b/ext/date/zonetab.list
@@ -47,12 +47,12 @@ utc, 0*3600
wet, 0*3600
at, -2*3600
brst,-2*3600
-ndt, -(2*3600+1800)
+ndt, -(1*3600+1800)
art, -3*3600
adt, -3*3600
brt, -3*3600
clst,-3*3600
-nst, -(3*3600+1800)
+nst, -(2*3600+1800)
ast, -4*3600
clt, -4*3600
akdt,-8*3600
@@ -62,7 +62,7 @@ hadt,-9*3600
hdt, -9*3600
yst, -9*3600
ahst,-10*3600
-cat,-10*3600
+cat,2*3600
hast,-10*3600
hst,-10*3600
nt, -11*3600
@@ -82,7 +82,7 @@ fst, 2*3600
mest, 2*3600
mesz, 2*3600
sast, 2*3600
-sst, 2*3600
+sst, -11*3600
bt, 3*3600
eat, 3*3600
eest, 3*3600
@@ -92,13 +92,13 @@ zp4, 4*3600
zp5, 5*3600
ist, (5*3600+1800)
zp6, 6*3600
-wast, 7*3600
-cct, 8*3600
+wast, 2*3600
+cct, (6*3600+1800)
sgt, 8*3600
wadt, 8*3600
jst, 9*3600
kst, 9*3600
-east,10*3600
+east,-6*3600
gst, 10*3600
eadt,11*3600
idle,12*3600
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index bc1d527735..de7536651c 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -980,7 +980,7 @@ fdbm_reject(VALUE obj)
* == Introduction
*
* The DBM class provides a wrapper to a Unix-style
- * {dbm}[http://en.wikipedia.org/wiki/Dbm] or Database Manager library.
+ * {dbm}[https://en.wikipedia.org/wiki/Dbm] or Database Manager library.
*
* Dbm databases do not have tables or columns; they are simple key-value
* data stores, like a Ruby Hash except not resident in RAM. Keys and values
@@ -992,7 +992,7 @@ fdbm_reject(VALUE obj)
* - The original ndbm library is released in 4.3BSD.
* It is based on dbm library in Unix Version 7 but has different API to
* support multiple databases in a process.
- * - {Berkeley DB}[http://en.wikipedia.org/wiki/Berkeley_DB] versions
+ * - {Berkeley DB}[https://en.wikipedia.org/wiki/Berkeley_DB] versions
* 1 thru 6, also known as BDB and Sleepycat DB, now owned by Oracle
* Corporation.
* - Berkeley DB 1.x, still found in 4.4BSD derivatives (FreeBSD, OpenBSD, etc).
diff --git a/ext/dbm/dbm.gemspec b/ext/dbm/dbm.gemspec
index 9de425b521..0ff036f712 100644
--- a/ext/dbm/dbm.gemspec
+++ b/ext/dbm/dbm.gemspec
@@ -13,8 +13,9 @@ Gem::Specification.new do |s|
s.authors = ["Yukihiro Matsumoto"]
s.email = ["matz@ruby-lang.org"]
s.homepage = "https://github.com/ruby/dbm"
- s.license = "BSD-2-Clause"
+ s.licenses = ["Ruby", "BSD-2-Clause"]
s.add_development_dependency "rake-compiler"
s.add_development_dependency "test-unit"
+ s.metadata["msys2_mingw_dependencies"] = "gdbm"
end
diff --git a/ext/dbm/depend b/ext/dbm/depend
index 192527a8eb..414bb58a0e 100644
--- a/ext/dbm/depend
+++ b/ext/dbm/depend
@@ -2,8 +2,157 @@
dbm.o: $(RUBY_EXTCONF_H)
dbm.o: $(arch_hdrdir)/ruby/config.h
dbm.o: $(hdrdir)/ruby.h
+dbm.o: $(hdrdir)/ruby/internal/anyargs.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+dbm.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+dbm.o: $(hdrdir)/ruby/internal/assume.h
+dbm.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+dbm.o: $(hdrdir)/ruby/internal/attr/artificial.h
+dbm.o: $(hdrdir)/ruby/internal/attr/cold.h
+dbm.o: $(hdrdir)/ruby/internal/attr/const.h
+dbm.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+dbm.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+dbm.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+dbm.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+dbm.o: $(hdrdir)/ruby/internal/attr/error.h
+dbm.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+dbm.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+dbm.o: $(hdrdir)/ruby/internal/attr/format.h
+dbm.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+dbm.o: $(hdrdir)/ruby/internal/attr/noalias.h
+dbm.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+dbm.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+dbm.o: $(hdrdir)/ruby/internal/attr/noinline.h
+dbm.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+dbm.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+dbm.o: $(hdrdir)/ruby/internal/attr/pure.h
+dbm.o: $(hdrdir)/ruby/internal/attr/restrict.h
+dbm.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+dbm.o: $(hdrdir)/ruby/internal/attr/warning.h
+dbm.o: $(hdrdir)/ruby/internal/attr/weakref.h
+dbm.o: $(hdrdir)/ruby/internal/cast.h
+dbm.o: $(hdrdir)/ruby/internal/compiler_is.h
+dbm.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+dbm.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+dbm.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+dbm.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+dbm.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+dbm.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+dbm.o: $(hdrdir)/ruby/internal/compiler_since.h
+dbm.o: $(hdrdir)/ruby/internal/config.h
+dbm.o: $(hdrdir)/ruby/internal/constant_p.h
+dbm.o: $(hdrdir)/ruby/internal/core.h
+dbm.o: $(hdrdir)/ruby/internal/core/rarray.h
+dbm.o: $(hdrdir)/ruby/internal/core/rbasic.h
+dbm.o: $(hdrdir)/ruby/internal/core/rbignum.h
+dbm.o: $(hdrdir)/ruby/internal/core/rclass.h
+dbm.o: $(hdrdir)/ruby/internal/core/rdata.h
+dbm.o: $(hdrdir)/ruby/internal/core/rfile.h
+dbm.o: $(hdrdir)/ruby/internal/core/rhash.h
+dbm.o: $(hdrdir)/ruby/internal/core/robject.h
+dbm.o: $(hdrdir)/ruby/internal/core/rregexp.h
+dbm.o: $(hdrdir)/ruby/internal/core/rstring.h
+dbm.o: $(hdrdir)/ruby/internal/core/rstruct.h
+dbm.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+dbm.o: $(hdrdir)/ruby/internal/ctype.h
+dbm.o: $(hdrdir)/ruby/internal/dllexport.h
+dbm.o: $(hdrdir)/ruby/internal/dosish.h
+dbm.o: $(hdrdir)/ruby/internal/error.h
+dbm.o: $(hdrdir)/ruby/internal/eval.h
+dbm.o: $(hdrdir)/ruby/internal/event.h
+dbm.o: $(hdrdir)/ruby/internal/fl_type.h
+dbm.o: $(hdrdir)/ruby/internal/gc.h
+dbm.o: $(hdrdir)/ruby/internal/glob.h
+dbm.o: $(hdrdir)/ruby/internal/globals.h
+dbm.o: $(hdrdir)/ruby/internal/has/attribute.h
+dbm.o: $(hdrdir)/ruby/internal/has/builtin.h
+dbm.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+dbm.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+dbm.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+dbm.o: $(hdrdir)/ruby/internal/has/extension.h
+dbm.o: $(hdrdir)/ruby/internal/has/feature.h
+dbm.o: $(hdrdir)/ruby/internal/has/warning.h
+dbm.o: $(hdrdir)/ruby/internal/intern/array.h
+dbm.o: $(hdrdir)/ruby/internal/intern/bignum.h
+dbm.o: $(hdrdir)/ruby/internal/intern/class.h
+dbm.o: $(hdrdir)/ruby/internal/intern/compar.h
+dbm.o: $(hdrdir)/ruby/internal/intern/complex.h
+dbm.o: $(hdrdir)/ruby/internal/intern/cont.h
+dbm.o: $(hdrdir)/ruby/internal/intern/dir.h
+dbm.o: $(hdrdir)/ruby/internal/intern/enum.h
+dbm.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+dbm.o: $(hdrdir)/ruby/internal/intern/error.h
+dbm.o: $(hdrdir)/ruby/internal/intern/eval.h
+dbm.o: $(hdrdir)/ruby/internal/intern/file.h
+dbm.o: $(hdrdir)/ruby/internal/intern/gc.h
+dbm.o: $(hdrdir)/ruby/internal/intern/hash.h
+dbm.o: $(hdrdir)/ruby/internal/intern/io.h
+dbm.o: $(hdrdir)/ruby/internal/intern/load.h
+dbm.o: $(hdrdir)/ruby/internal/intern/marshal.h
+dbm.o: $(hdrdir)/ruby/internal/intern/numeric.h
+dbm.o: $(hdrdir)/ruby/internal/intern/object.h
+dbm.o: $(hdrdir)/ruby/internal/intern/parse.h
+dbm.o: $(hdrdir)/ruby/internal/intern/proc.h
+dbm.o: $(hdrdir)/ruby/internal/intern/process.h
+dbm.o: $(hdrdir)/ruby/internal/intern/random.h
+dbm.o: $(hdrdir)/ruby/internal/intern/range.h
+dbm.o: $(hdrdir)/ruby/internal/intern/rational.h
+dbm.o: $(hdrdir)/ruby/internal/intern/re.h
+dbm.o: $(hdrdir)/ruby/internal/intern/ruby.h
+dbm.o: $(hdrdir)/ruby/internal/intern/select.h
+dbm.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+dbm.o: $(hdrdir)/ruby/internal/intern/signal.h
+dbm.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+dbm.o: $(hdrdir)/ruby/internal/intern/string.h
+dbm.o: $(hdrdir)/ruby/internal/intern/struct.h
+dbm.o: $(hdrdir)/ruby/internal/intern/thread.h
+dbm.o: $(hdrdir)/ruby/internal/intern/time.h
+dbm.o: $(hdrdir)/ruby/internal/intern/variable.h
+dbm.o: $(hdrdir)/ruby/internal/intern/vm.h
+dbm.o: $(hdrdir)/ruby/internal/interpreter.h
+dbm.o: $(hdrdir)/ruby/internal/iterator.h
+dbm.o: $(hdrdir)/ruby/internal/memory.h
+dbm.o: $(hdrdir)/ruby/internal/method.h
+dbm.o: $(hdrdir)/ruby/internal/module.h
+dbm.o: $(hdrdir)/ruby/internal/newobj.h
+dbm.o: $(hdrdir)/ruby/internal/rgengc.h
+dbm.o: $(hdrdir)/ruby/internal/scan_args.h
+dbm.o: $(hdrdir)/ruby/internal/special_consts.h
+dbm.o: $(hdrdir)/ruby/internal/static_assert.h
+dbm.o: $(hdrdir)/ruby/internal/stdalign.h
+dbm.o: $(hdrdir)/ruby/internal/stdbool.h
+dbm.o: $(hdrdir)/ruby/internal/symbol.h
+dbm.o: $(hdrdir)/ruby/internal/token_paste.h
+dbm.o: $(hdrdir)/ruby/internal/value.h
+dbm.o: $(hdrdir)/ruby/internal/value_type.h
+dbm.o: $(hdrdir)/ruby/internal/variable.h
+dbm.o: $(hdrdir)/ruby/internal/warning_push.h
+dbm.o: $(hdrdir)/ruby/internal/xmalloc.h
dbm.o: $(hdrdir)/ruby/assert.h
dbm.o: $(hdrdir)/ruby/backward.h
+dbm.o: $(hdrdir)/ruby/backward/2/assume.h
+dbm.o: $(hdrdir)/ruby/backward/2/attributes.h
+dbm.o: $(hdrdir)/ruby/backward/2/bool.h
+dbm.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+dbm.o: $(hdrdir)/ruby/backward/2/inttypes.h
+dbm.o: $(hdrdir)/ruby/backward/2/limits.h
+dbm.o: $(hdrdir)/ruby/backward/2/long_long.h
+dbm.o: $(hdrdir)/ruby/backward/2/stdalign.h
+dbm.o: $(hdrdir)/ruby/backward/2/stdarg.h
dbm.o: $(hdrdir)/ruby/defines.h
dbm.o: $(hdrdir)/ruby/intern.h
dbm.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/digest/bubblebabble/depend b/ext/digest/bubblebabble/depend
index e7e2a8889d..6dcd5fe55c 100644
--- a/ext/digest/bubblebabble/depend
+++ b/ext/digest/bubblebabble/depend
@@ -2,8 +2,157 @@
bubblebabble.o: $(RUBY_EXTCONF_H)
bubblebabble.o: $(arch_hdrdir)/ruby/config.h
bubblebabble.o: $(hdrdir)/ruby.h
+bubblebabble.o: $(hdrdir)/ruby/internal/anyargs.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bubblebabble.o: $(hdrdir)/ruby/internal/assume.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/cold.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/const.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/error.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/format.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/pure.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/warning.h
+bubblebabble.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bubblebabble.o: $(hdrdir)/ruby/internal/cast.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bubblebabble.o: $(hdrdir)/ruby/internal/compiler_since.h
+bubblebabble.o: $(hdrdir)/ruby/internal/config.h
+bubblebabble.o: $(hdrdir)/ruby/internal/constant_p.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rarray.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rclass.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rdata.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rfile.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rhash.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/robject.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rstring.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bubblebabble.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bubblebabble.o: $(hdrdir)/ruby/internal/ctype.h
+bubblebabble.o: $(hdrdir)/ruby/internal/dllexport.h
+bubblebabble.o: $(hdrdir)/ruby/internal/dosish.h
+bubblebabble.o: $(hdrdir)/ruby/internal/error.h
+bubblebabble.o: $(hdrdir)/ruby/internal/eval.h
+bubblebabble.o: $(hdrdir)/ruby/internal/event.h
+bubblebabble.o: $(hdrdir)/ruby/internal/fl_type.h
+bubblebabble.o: $(hdrdir)/ruby/internal/gc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/glob.h
+bubblebabble.o: $(hdrdir)/ruby/internal/globals.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/attribute.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/builtin.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/extension.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/feature.h
+bubblebabble.o: $(hdrdir)/ruby/internal/has/warning.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/array.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/class.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/compar.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/complex.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/cont.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/dir.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/enum.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/error.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/eval.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/file.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/gc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/hash.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/io.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/load.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/object.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/parse.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/proc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/process.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/random.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/range.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/rational.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/re.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/select.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/signal.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/string.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/struct.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/thread.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/time.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/variable.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/vm.h
+bubblebabble.o: $(hdrdir)/ruby/internal/interpreter.h
+bubblebabble.o: $(hdrdir)/ruby/internal/iterator.h
+bubblebabble.o: $(hdrdir)/ruby/internal/memory.h
+bubblebabble.o: $(hdrdir)/ruby/internal/method.h
+bubblebabble.o: $(hdrdir)/ruby/internal/module.h
+bubblebabble.o: $(hdrdir)/ruby/internal/newobj.h
+bubblebabble.o: $(hdrdir)/ruby/internal/rgengc.h
+bubblebabble.o: $(hdrdir)/ruby/internal/scan_args.h
+bubblebabble.o: $(hdrdir)/ruby/internal/special_consts.h
+bubblebabble.o: $(hdrdir)/ruby/internal/static_assert.h
+bubblebabble.o: $(hdrdir)/ruby/internal/stdalign.h
+bubblebabble.o: $(hdrdir)/ruby/internal/stdbool.h
+bubblebabble.o: $(hdrdir)/ruby/internal/symbol.h
+bubblebabble.o: $(hdrdir)/ruby/internal/token_paste.h
+bubblebabble.o: $(hdrdir)/ruby/internal/value.h
+bubblebabble.o: $(hdrdir)/ruby/internal/value_type.h
+bubblebabble.o: $(hdrdir)/ruby/internal/variable.h
+bubblebabble.o: $(hdrdir)/ruby/internal/warning_push.h
+bubblebabble.o: $(hdrdir)/ruby/internal/xmalloc.h
bubblebabble.o: $(hdrdir)/ruby/assert.h
bubblebabble.o: $(hdrdir)/ruby/backward.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/assume.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/attributes.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/bool.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/limits.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/long_long.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bubblebabble.o: $(hdrdir)/ruby/backward/2/stdarg.h
bubblebabble.o: $(hdrdir)/ruby/defines.h
bubblebabble.o: $(hdrdir)/ruby/intern.h
bubblebabble.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/digest/depend b/ext/digest/depend
index 87c39c8b8d..ac01d970dc 100644
--- a/ext/digest/depend
+++ b/ext/digest/depend
@@ -2,8 +2,157 @@
digest.o: $(RUBY_EXTCONF_H)
digest.o: $(arch_hdrdir)/ruby/config.h
digest.o: $(hdrdir)/ruby.h
+digest.o: $(hdrdir)/ruby/internal/anyargs.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+digest.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+digest.o: $(hdrdir)/ruby/internal/assume.h
+digest.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+digest.o: $(hdrdir)/ruby/internal/attr/artificial.h
+digest.o: $(hdrdir)/ruby/internal/attr/cold.h
+digest.o: $(hdrdir)/ruby/internal/attr/const.h
+digest.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+digest.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+digest.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+digest.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+digest.o: $(hdrdir)/ruby/internal/attr/error.h
+digest.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+digest.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+digest.o: $(hdrdir)/ruby/internal/attr/format.h
+digest.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+digest.o: $(hdrdir)/ruby/internal/attr/noalias.h
+digest.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+digest.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+digest.o: $(hdrdir)/ruby/internal/attr/noinline.h
+digest.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+digest.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+digest.o: $(hdrdir)/ruby/internal/attr/pure.h
+digest.o: $(hdrdir)/ruby/internal/attr/restrict.h
+digest.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+digest.o: $(hdrdir)/ruby/internal/attr/warning.h
+digest.o: $(hdrdir)/ruby/internal/attr/weakref.h
+digest.o: $(hdrdir)/ruby/internal/cast.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+digest.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+digest.o: $(hdrdir)/ruby/internal/compiler_since.h
+digest.o: $(hdrdir)/ruby/internal/config.h
+digest.o: $(hdrdir)/ruby/internal/constant_p.h
+digest.o: $(hdrdir)/ruby/internal/core.h
+digest.o: $(hdrdir)/ruby/internal/core/rarray.h
+digest.o: $(hdrdir)/ruby/internal/core/rbasic.h
+digest.o: $(hdrdir)/ruby/internal/core/rbignum.h
+digest.o: $(hdrdir)/ruby/internal/core/rclass.h
+digest.o: $(hdrdir)/ruby/internal/core/rdata.h
+digest.o: $(hdrdir)/ruby/internal/core/rfile.h
+digest.o: $(hdrdir)/ruby/internal/core/rhash.h
+digest.o: $(hdrdir)/ruby/internal/core/robject.h
+digest.o: $(hdrdir)/ruby/internal/core/rregexp.h
+digest.o: $(hdrdir)/ruby/internal/core/rstring.h
+digest.o: $(hdrdir)/ruby/internal/core/rstruct.h
+digest.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+digest.o: $(hdrdir)/ruby/internal/ctype.h
+digest.o: $(hdrdir)/ruby/internal/dllexport.h
+digest.o: $(hdrdir)/ruby/internal/dosish.h
+digest.o: $(hdrdir)/ruby/internal/error.h
+digest.o: $(hdrdir)/ruby/internal/eval.h
+digest.o: $(hdrdir)/ruby/internal/event.h
+digest.o: $(hdrdir)/ruby/internal/fl_type.h
+digest.o: $(hdrdir)/ruby/internal/gc.h
+digest.o: $(hdrdir)/ruby/internal/glob.h
+digest.o: $(hdrdir)/ruby/internal/globals.h
+digest.o: $(hdrdir)/ruby/internal/has/attribute.h
+digest.o: $(hdrdir)/ruby/internal/has/builtin.h
+digest.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+digest.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+digest.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+digest.o: $(hdrdir)/ruby/internal/has/extension.h
+digest.o: $(hdrdir)/ruby/internal/has/feature.h
+digest.o: $(hdrdir)/ruby/internal/has/warning.h
+digest.o: $(hdrdir)/ruby/internal/intern/array.h
+digest.o: $(hdrdir)/ruby/internal/intern/bignum.h
+digest.o: $(hdrdir)/ruby/internal/intern/class.h
+digest.o: $(hdrdir)/ruby/internal/intern/compar.h
+digest.o: $(hdrdir)/ruby/internal/intern/complex.h
+digest.o: $(hdrdir)/ruby/internal/intern/cont.h
+digest.o: $(hdrdir)/ruby/internal/intern/dir.h
+digest.o: $(hdrdir)/ruby/internal/intern/enum.h
+digest.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+digest.o: $(hdrdir)/ruby/internal/intern/error.h
+digest.o: $(hdrdir)/ruby/internal/intern/eval.h
+digest.o: $(hdrdir)/ruby/internal/intern/file.h
+digest.o: $(hdrdir)/ruby/internal/intern/gc.h
+digest.o: $(hdrdir)/ruby/internal/intern/hash.h
+digest.o: $(hdrdir)/ruby/internal/intern/io.h
+digest.o: $(hdrdir)/ruby/internal/intern/load.h
+digest.o: $(hdrdir)/ruby/internal/intern/marshal.h
+digest.o: $(hdrdir)/ruby/internal/intern/numeric.h
+digest.o: $(hdrdir)/ruby/internal/intern/object.h
+digest.o: $(hdrdir)/ruby/internal/intern/parse.h
+digest.o: $(hdrdir)/ruby/internal/intern/proc.h
+digest.o: $(hdrdir)/ruby/internal/intern/process.h
+digest.o: $(hdrdir)/ruby/internal/intern/random.h
+digest.o: $(hdrdir)/ruby/internal/intern/range.h
+digest.o: $(hdrdir)/ruby/internal/intern/rational.h
+digest.o: $(hdrdir)/ruby/internal/intern/re.h
+digest.o: $(hdrdir)/ruby/internal/intern/ruby.h
+digest.o: $(hdrdir)/ruby/internal/intern/select.h
+digest.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+digest.o: $(hdrdir)/ruby/internal/intern/signal.h
+digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+digest.o: $(hdrdir)/ruby/internal/intern/string.h
+digest.o: $(hdrdir)/ruby/internal/intern/struct.h
+digest.o: $(hdrdir)/ruby/internal/intern/thread.h
+digest.o: $(hdrdir)/ruby/internal/intern/time.h
+digest.o: $(hdrdir)/ruby/internal/intern/variable.h
+digest.o: $(hdrdir)/ruby/internal/intern/vm.h
+digest.o: $(hdrdir)/ruby/internal/interpreter.h
+digest.o: $(hdrdir)/ruby/internal/iterator.h
+digest.o: $(hdrdir)/ruby/internal/memory.h
+digest.o: $(hdrdir)/ruby/internal/method.h
+digest.o: $(hdrdir)/ruby/internal/module.h
+digest.o: $(hdrdir)/ruby/internal/newobj.h
+digest.o: $(hdrdir)/ruby/internal/rgengc.h
+digest.o: $(hdrdir)/ruby/internal/scan_args.h
+digest.o: $(hdrdir)/ruby/internal/special_consts.h
+digest.o: $(hdrdir)/ruby/internal/static_assert.h
+digest.o: $(hdrdir)/ruby/internal/stdalign.h
+digest.o: $(hdrdir)/ruby/internal/stdbool.h
+digest.o: $(hdrdir)/ruby/internal/symbol.h
+digest.o: $(hdrdir)/ruby/internal/token_paste.h
+digest.o: $(hdrdir)/ruby/internal/value.h
+digest.o: $(hdrdir)/ruby/internal/value_type.h
+digest.o: $(hdrdir)/ruby/internal/variable.h
+digest.o: $(hdrdir)/ruby/internal/warning_push.h
+digest.o: $(hdrdir)/ruby/internal/xmalloc.h
digest.o: $(hdrdir)/ruby/assert.h
digest.o: $(hdrdir)/ruby/backward.h
+digest.o: $(hdrdir)/ruby/backward/2/assume.h
+digest.o: $(hdrdir)/ruby/backward/2/attributes.h
+digest.o: $(hdrdir)/ruby/backward/2/bool.h
+digest.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+digest.o: $(hdrdir)/ruby/backward/2/inttypes.h
+digest.o: $(hdrdir)/ruby/backward/2/limits.h
+digest.o: $(hdrdir)/ruby/backward/2/long_long.h
+digest.o: $(hdrdir)/ruby/backward/2/stdalign.h
+digest.o: $(hdrdir)/ruby/backward/2/stdarg.h
digest.o: $(hdrdir)/ruby/defines.h
digest.o: $(hdrdir)/ruby/intern.h
digest.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/digest/digest.c b/ext/digest/digest.c
index a59f880ac7..83f4ee42fc 100644
--- a/ext/digest/digest.c
+++ b/ext/digest/digest.c
@@ -406,7 +406,7 @@ rb_digest_instance_digest_length(VALUE self)
/* never blindly assume that #digest() returns a string */
StringValue(digest);
- return INT2NUM(RSTRING_LEN(digest));
+ return LONG2NUM(RSTRING_LEN(digest));
}
/*
@@ -725,7 +725,7 @@ rb_digest_base_digest_length(VALUE self)
algo = get_digest_obj_metadata(self);
- return INT2NUM(algo->digest_len);
+ return SIZET2NUM(algo->digest_len);
}
/*
@@ -740,7 +740,7 @@ rb_digest_base_block_length(VALUE self)
algo = get_digest_obj_metadata(self);
- return INT2NUM(algo->block_len);
+ return SIZET2NUM(algo->block_len);
}
void
@@ -765,6 +765,10 @@ InitVM_digest(void)
*/
rb_mDigest = rb_define_module("Digest");
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
/* module functions */
rb_define_module_function(rb_mDigest, "hexencode", rb_digest_s_hexencode, 1);
diff --git a/ext/digest/digest.gemspec b/ext/digest/digest.gemspec
new file mode 100644
index 0000000000..6f3bf8b05f
--- /dev/null
+++ b/ext/digest/digest.gemspec
@@ -0,0 +1,47 @@
+# coding: utf-8
+# frozen_string_literal: true
+
+Gem::Specification.new do |spec|
+ spec.name = "digest"
+ spec.version = "3.0.0"
+ spec.authors = ["Akinori MUSHA"]
+ spec.email = ["knu@idaemons.org"]
+
+ spec.summary = %q{Provides a framework for message digest libraries.}
+ spec.description = %q{Provides a framework for message digest libraries.}
+ spec.homepage = "https://github.com/ruby/digest"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.files = [
+ "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "digest.gemspec",
+ "ext/digest/bubblebabble/bubblebabble.c", "ext/digest/bubblebabble/extconf.rb", "ext/digest/defs.h",
+ "ext/digest/digest.c", "ext/digest/digest.h", "ext/digest/digest_conf.rb", "ext/digest/extconf.rb",
+ "ext/digest/md5/extconf.rb", "ext/digest/md5/md5.c", "ext/digest/md5/md5.h", "ext/digest/md5/md5cc.h",
+ "ext/digest/md5/md5init.c", "ext/digest/rmd160/extconf.rb", "ext/digest/rmd160/rmd160.c",
+ "ext/digest/rmd160/rmd160.h", "ext/digest/rmd160/rmd160init.c", "ext/digest/sha1/extconf.rb",
+ "ext/digest/sha1/sha1.c", "ext/digest/sha1/sha1.h", "ext/digest/sha1/sha1cc.h",
+ "ext/digest/sha1/sha1init.c", "ext/digest/sha2/extconf.rb", "ext/digest/sha2/lib/sha2.rb",
+ "ext/digest/sha2/sha2.c", "ext/digest/sha2/sha2.h", "ext/digest/sha2/sha2cc.h",
+ "ext/digest/sha2/sha2init.c", "ext/digest/test.sh", "ext/openssl/deprecation.rb",
+ "lib/digest.rb"
+ ]
+
+ spec.required_ruby_version = ">= 2.3.0"
+
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+ spec.extensions = %w[
+ ext/digest/extconf.rb
+ ext/digest/bubblebabble/extconf.rb
+ ext/digest/md5/extconf.rb
+ ext/digest/rmd160/extconf.rb
+ ext/digest/sha1/extconf.rb
+ ext/digest/sha2/extconf.rb
+ ]
+ spec.metadata["msys2_mingw_dependencies"] = "openssl"
+
+ spec.add_development_dependency "bundler"
+ spec.add_development_dependency "rake"
+ spec.add_development_dependency "rake-compiler"
+end
diff --git a/ext/digest/digest.h b/ext/digest/digest.h
index 4b6954089f..0d4f0e7cc2 100644
--- a/ext/digest/digest.h
+++ b/ext/digest/digest.h
@@ -62,3 +62,11 @@ rb_id_metadata(void)
{
return rb_intern_const("metadata");
}
+
+static inline VALUE
+rb_digest_make_metadata(const rb_digest_metadata_t *meta)
+{
+#undef RUBY_UNTYPED_DATA_WARNING
+#define RUBY_UNTYPED_DATA_WARNING 0
+ return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta));
+}
diff --git a/ext/digest/digest_conf.rb b/ext/digest/digest_conf.rb
index 915b61877f..1b929d8732 100644
--- a/ext/digest/digest_conf.rb
+++ b/ext/digest/digest_conf.rb
@@ -1,57 +1,6 @@
# frozen_string_literal: false
-# Copy from ext/openssl/extconf.rb
-def find_openssl_library
- if $mswin || $mingw
- # required for static OpenSSL libraries
- have_library("gdi32") # OpenSSL <= 1.0.2 (for RAND_screen())
- have_library("crypt32")
- end
-
- return false unless have_header("openssl/ssl.h")
-
- ret = have_library("crypto", "CRYPTO_malloc") &&
- have_library("ssl", "SSL_new")
- return ret if ret
-
- if $mswin
- # OpenSSL >= 1.1.0: libcrypto.lib and libssl.lib.
- if have_library("libcrypto", "CRYPTO_malloc") &&
- have_library("libssl", "SSL_new")
- return true
- end
-
- # OpenSSL <= 1.0.2: libeay32.lib and ssleay32.lib.
- if have_library("libeay32", "CRYPTO_malloc") &&
- have_library("ssleay32", "SSL_new")
- return true
- end
-
- # LibreSSL: libcrypto-##.lib and libssl-##.lib, where ## is the ABI version
- # number. We have to find the version number out by scanning libpath.
- libpath = $LIBPATH.dup
- libpath |= ENV["LIB"].split(File::PATH_SEPARATOR)
- libpath.map! { |d| d.tr(File::ALT_SEPARATOR, File::SEPARATOR) }
-
- ret = [
- ["crypto", "CRYPTO_malloc"],
- ["ssl", "SSL_new"]
- ].all? do |base, func|
- result = false
- libs = ["lib#{base}-[0-9][0-9]", "lib#{base}-[0-9][0-9][0-9]"]
- libs = Dir.glob(libs.map{|l| libpath.map{|d| File.join(d, l + ".*")}}.flatten).map{|path| File.basename(path, ".*")}.uniq
- libs.each do |lib|
- result = have_library(lib, func)
- break if result
- end
- result
- end
- return ret if ret
- end
- return false
-end
-
-def digest_conf(name, hdr = name, funcs = nil, types = nil)
+def digest_conf(name)
unless with_config("bundled-#{name}")
cc = with_config("common-digest")
if cc == true or /\b#{name}\b/ =~ cc
@@ -62,22 +11,6 @@ def digest_conf(name, hdr = name, funcs = nil, types = nil)
return :commondigest
end
end
-
- dir_config("openssl")
- pkg_config("openssl")
- require File.expand_path('../../openssl/deprecation', __FILE__)
- if find_openssl_library
- funcs ||= name.upcase
- funcs = Array(funcs)
- types ||= funcs
- hdr = "openssl/#{hdr}.h"
- if funcs.all? {|func| OpenSSL.check_func("#{func}_Transform", hdr)} &&
- types.all? {|type| have_type("#{type}_CTX", hdr)}
- $defs << "-D#{name.upcase}_USE_OPENSSL"
- $headers << "#{name}ossl.h"
- return :ossl
- end
- end
end
$objs << "#{name}.#{$OBJEXT}"
return
diff --git a/ext/digest/md5/depend b/ext/digest/md5/depend
index abfd8de6a5..987ebcc12d 100644
--- a/ext/digest/md5/depend
+++ b/ext/digest/md5/depend
@@ -2,18 +2,331 @@ md5.o: md5.c md5.h $(srcdir)/../defs.h
md5init.o: $(LOCAL_HDRS)
# AUTOGENERATED DEPENDENCIES START
+md5.o: $(RUBY_EXTCONF_H)
+md5.o: $(arch_hdrdir)/ruby/config.h
+md5.o: $(hdrdir)/ruby.h
+md5.o: $(hdrdir)/ruby/assert.h
+md5.o: $(hdrdir)/ruby/backward.h
+md5.o: $(hdrdir)/ruby/backward/2/assume.h
+md5.o: $(hdrdir)/ruby/backward/2/attributes.h
+md5.o: $(hdrdir)/ruby/backward/2/bool.h
+md5.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+md5.o: $(hdrdir)/ruby/backward/2/inttypes.h
+md5.o: $(hdrdir)/ruby/backward/2/limits.h
+md5.o: $(hdrdir)/ruby/backward/2/long_long.h
+md5.o: $(hdrdir)/ruby/backward/2/stdalign.h
+md5.o: $(hdrdir)/ruby/backward/2/stdarg.h
+md5.o: $(hdrdir)/ruby/defines.h
+md5.o: $(hdrdir)/ruby/intern.h
+md5.o: $(hdrdir)/ruby/internal/anyargs.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+md5.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+md5.o: $(hdrdir)/ruby/internal/assume.h
+md5.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+md5.o: $(hdrdir)/ruby/internal/attr/artificial.h
+md5.o: $(hdrdir)/ruby/internal/attr/cold.h
+md5.o: $(hdrdir)/ruby/internal/attr/const.h
+md5.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+md5.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+md5.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+md5.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+md5.o: $(hdrdir)/ruby/internal/attr/error.h
+md5.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+md5.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+md5.o: $(hdrdir)/ruby/internal/attr/format.h
+md5.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+md5.o: $(hdrdir)/ruby/internal/attr/noalias.h
+md5.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+md5.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+md5.o: $(hdrdir)/ruby/internal/attr/noinline.h
+md5.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+md5.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+md5.o: $(hdrdir)/ruby/internal/attr/pure.h
+md5.o: $(hdrdir)/ruby/internal/attr/restrict.h
+md5.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+md5.o: $(hdrdir)/ruby/internal/attr/warning.h
+md5.o: $(hdrdir)/ruby/internal/attr/weakref.h
+md5.o: $(hdrdir)/ruby/internal/cast.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+md5.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+md5.o: $(hdrdir)/ruby/internal/compiler_since.h
+md5.o: $(hdrdir)/ruby/internal/config.h
+md5.o: $(hdrdir)/ruby/internal/constant_p.h
+md5.o: $(hdrdir)/ruby/internal/core.h
+md5.o: $(hdrdir)/ruby/internal/core/rarray.h
+md5.o: $(hdrdir)/ruby/internal/core/rbasic.h
+md5.o: $(hdrdir)/ruby/internal/core/rbignum.h
+md5.o: $(hdrdir)/ruby/internal/core/rclass.h
+md5.o: $(hdrdir)/ruby/internal/core/rdata.h
+md5.o: $(hdrdir)/ruby/internal/core/rfile.h
+md5.o: $(hdrdir)/ruby/internal/core/rhash.h
+md5.o: $(hdrdir)/ruby/internal/core/robject.h
+md5.o: $(hdrdir)/ruby/internal/core/rregexp.h
+md5.o: $(hdrdir)/ruby/internal/core/rstring.h
+md5.o: $(hdrdir)/ruby/internal/core/rstruct.h
+md5.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+md5.o: $(hdrdir)/ruby/internal/ctype.h
+md5.o: $(hdrdir)/ruby/internal/dllexport.h
+md5.o: $(hdrdir)/ruby/internal/dosish.h
+md5.o: $(hdrdir)/ruby/internal/error.h
+md5.o: $(hdrdir)/ruby/internal/eval.h
+md5.o: $(hdrdir)/ruby/internal/event.h
+md5.o: $(hdrdir)/ruby/internal/fl_type.h
+md5.o: $(hdrdir)/ruby/internal/gc.h
+md5.o: $(hdrdir)/ruby/internal/glob.h
+md5.o: $(hdrdir)/ruby/internal/globals.h
+md5.o: $(hdrdir)/ruby/internal/has/attribute.h
+md5.o: $(hdrdir)/ruby/internal/has/builtin.h
+md5.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+md5.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+md5.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+md5.o: $(hdrdir)/ruby/internal/has/extension.h
+md5.o: $(hdrdir)/ruby/internal/has/feature.h
+md5.o: $(hdrdir)/ruby/internal/has/warning.h
+md5.o: $(hdrdir)/ruby/internal/intern/array.h
+md5.o: $(hdrdir)/ruby/internal/intern/bignum.h
+md5.o: $(hdrdir)/ruby/internal/intern/class.h
+md5.o: $(hdrdir)/ruby/internal/intern/compar.h
+md5.o: $(hdrdir)/ruby/internal/intern/complex.h
+md5.o: $(hdrdir)/ruby/internal/intern/cont.h
+md5.o: $(hdrdir)/ruby/internal/intern/dir.h
+md5.o: $(hdrdir)/ruby/internal/intern/enum.h
+md5.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+md5.o: $(hdrdir)/ruby/internal/intern/error.h
+md5.o: $(hdrdir)/ruby/internal/intern/eval.h
+md5.o: $(hdrdir)/ruby/internal/intern/file.h
+md5.o: $(hdrdir)/ruby/internal/intern/gc.h
+md5.o: $(hdrdir)/ruby/internal/intern/hash.h
+md5.o: $(hdrdir)/ruby/internal/intern/io.h
+md5.o: $(hdrdir)/ruby/internal/intern/load.h
+md5.o: $(hdrdir)/ruby/internal/intern/marshal.h
+md5.o: $(hdrdir)/ruby/internal/intern/numeric.h
+md5.o: $(hdrdir)/ruby/internal/intern/object.h
+md5.o: $(hdrdir)/ruby/internal/intern/parse.h
+md5.o: $(hdrdir)/ruby/internal/intern/proc.h
+md5.o: $(hdrdir)/ruby/internal/intern/process.h
+md5.o: $(hdrdir)/ruby/internal/intern/random.h
+md5.o: $(hdrdir)/ruby/internal/intern/range.h
+md5.o: $(hdrdir)/ruby/internal/intern/rational.h
+md5.o: $(hdrdir)/ruby/internal/intern/re.h
+md5.o: $(hdrdir)/ruby/internal/intern/ruby.h
+md5.o: $(hdrdir)/ruby/internal/intern/select.h
+md5.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+md5.o: $(hdrdir)/ruby/internal/intern/signal.h
+md5.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+md5.o: $(hdrdir)/ruby/internal/intern/string.h
+md5.o: $(hdrdir)/ruby/internal/intern/struct.h
+md5.o: $(hdrdir)/ruby/internal/intern/thread.h
+md5.o: $(hdrdir)/ruby/internal/intern/time.h
+md5.o: $(hdrdir)/ruby/internal/intern/variable.h
+md5.o: $(hdrdir)/ruby/internal/intern/vm.h
+md5.o: $(hdrdir)/ruby/internal/interpreter.h
+md5.o: $(hdrdir)/ruby/internal/iterator.h
+md5.o: $(hdrdir)/ruby/internal/memory.h
+md5.o: $(hdrdir)/ruby/internal/method.h
+md5.o: $(hdrdir)/ruby/internal/module.h
+md5.o: $(hdrdir)/ruby/internal/newobj.h
+md5.o: $(hdrdir)/ruby/internal/rgengc.h
+md5.o: $(hdrdir)/ruby/internal/scan_args.h
+md5.o: $(hdrdir)/ruby/internal/special_consts.h
+md5.o: $(hdrdir)/ruby/internal/static_assert.h
+md5.o: $(hdrdir)/ruby/internal/stdalign.h
+md5.o: $(hdrdir)/ruby/internal/stdbool.h
+md5.o: $(hdrdir)/ruby/internal/symbol.h
+md5.o: $(hdrdir)/ruby/internal/token_paste.h
+md5.o: $(hdrdir)/ruby/internal/value.h
+md5.o: $(hdrdir)/ruby/internal/value_type.h
+md5.o: $(hdrdir)/ruby/internal/variable.h
+md5.o: $(hdrdir)/ruby/internal/warning_push.h
+md5.o: $(hdrdir)/ruby/internal/xmalloc.h
+md5.o: $(hdrdir)/ruby/missing.h
+md5.o: $(hdrdir)/ruby/ruby.h
+md5.o: $(hdrdir)/ruby/st.h
+md5.o: $(hdrdir)/ruby/subst.h
+md5.o: $(srcdir)/../defs.h
+md5.o: md5.c
+md5.o: md5.h
md5init.o: $(RUBY_EXTCONF_H)
md5init.o: $(arch_hdrdir)/ruby/config.h
md5init.o: $(hdrdir)/ruby.h
md5init.o: $(hdrdir)/ruby/assert.h
md5init.o: $(hdrdir)/ruby/backward.h
+md5init.o: $(hdrdir)/ruby/backward/2/assume.h
+md5init.o: $(hdrdir)/ruby/backward/2/attributes.h
+md5init.o: $(hdrdir)/ruby/backward/2/bool.h
+md5init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+md5init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+md5init.o: $(hdrdir)/ruby/backward/2/limits.h
+md5init.o: $(hdrdir)/ruby/backward/2/long_long.h
+md5init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+md5init.o: $(hdrdir)/ruby/backward/2/stdarg.h
md5init.o: $(hdrdir)/ruby/defines.h
md5init.o: $(hdrdir)/ruby/intern.h
+md5init.o: $(hdrdir)/ruby/internal/anyargs.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+md5init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+md5init.o: $(hdrdir)/ruby/internal/assume.h
+md5init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+md5init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+md5init.o: $(hdrdir)/ruby/internal/attr/cold.h
+md5init.o: $(hdrdir)/ruby/internal/attr/const.h
+md5init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+md5init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+md5init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+md5init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+md5init.o: $(hdrdir)/ruby/internal/attr/error.h
+md5init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+md5init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+md5init.o: $(hdrdir)/ruby/internal/attr/format.h
+md5init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+md5init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+md5init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+md5init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+md5init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+md5init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+md5init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+md5init.o: $(hdrdir)/ruby/internal/attr/pure.h
+md5init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+md5init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+md5init.o: $(hdrdir)/ruby/internal/attr/warning.h
+md5init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+md5init.o: $(hdrdir)/ruby/internal/cast.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+md5init.o: $(hdrdir)/ruby/internal/compiler_since.h
+md5init.o: $(hdrdir)/ruby/internal/config.h
+md5init.o: $(hdrdir)/ruby/internal/constant_p.h
+md5init.o: $(hdrdir)/ruby/internal/core.h
+md5init.o: $(hdrdir)/ruby/internal/core/rarray.h
+md5init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+md5init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+md5init.o: $(hdrdir)/ruby/internal/core/rclass.h
+md5init.o: $(hdrdir)/ruby/internal/core/rdata.h
+md5init.o: $(hdrdir)/ruby/internal/core/rfile.h
+md5init.o: $(hdrdir)/ruby/internal/core/rhash.h
+md5init.o: $(hdrdir)/ruby/internal/core/robject.h
+md5init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+md5init.o: $(hdrdir)/ruby/internal/core/rstring.h
+md5init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+md5init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+md5init.o: $(hdrdir)/ruby/internal/ctype.h
+md5init.o: $(hdrdir)/ruby/internal/dllexport.h
+md5init.o: $(hdrdir)/ruby/internal/dosish.h
+md5init.o: $(hdrdir)/ruby/internal/error.h
+md5init.o: $(hdrdir)/ruby/internal/eval.h
+md5init.o: $(hdrdir)/ruby/internal/event.h
+md5init.o: $(hdrdir)/ruby/internal/fl_type.h
+md5init.o: $(hdrdir)/ruby/internal/gc.h
+md5init.o: $(hdrdir)/ruby/internal/glob.h
+md5init.o: $(hdrdir)/ruby/internal/globals.h
+md5init.o: $(hdrdir)/ruby/internal/has/attribute.h
+md5init.o: $(hdrdir)/ruby/internal/has/builtin.h
+md5init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+md5init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+md5init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+md5init.o: $(hdrdir)/ruby/internal/has/extension.h
+md5init.o: $(hdrdir)/ruby/internal/has/feature.h
+md5init.o: $(hdrdir)/ruby/internal/has/warning.h
+md5init.o: $(hdrdir)/ruby/internal/intern/array.h
+md5init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+md5init.o: $(hdrdir)/ruby/internal/intern/class.h
+md5init.o: $(hdrdir)/ruby/internal/intern/compar.h
+md5init.o: $(hdrdir)/ruby/internal/intern/complex.h
+md5init.o: $(hdrdir)/ruby/internal/intern/cont.h
+md5init.o: $(hdrdir)/ruby/internal/intern/dir.h
+md5init.o: $(hdrdir)/ruby/internal/intern/enum.h
+md5init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+md5init.o: $(hdrdir)/ruby/internal/intern/error.h
+md5init.o: $(hdrdir)/ruby/internal/intern/eval.h
+md5init.o: $(hdrdir)/ruby/internal/intern/file.h
+md5init.o: $(hdrdir)/ruby/internal/intern/gc.h
+md5init.o: $(hdrdir)/ruby/internal/intern/hash.h
+md5init.o: $(hdrdir)/ruby/internal/intern/io.h
+md5init.o: $(hdrdir)/ruby/internal/intern/load.h
+md5init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+md5init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+md5init.o: $(hdrdir)/ruby/internal/intern/object.h
+md5init.o: $(hdrdir)/ruby/internal/intern/parse.h
+md5init.o: $(hdrdir)/ruby/internal/intern/proc.h
+md5init.o: $(hdrdir)/ruby/internal/intern/process.h
+md5init.o: $(hdrdir)/ruby/internal/intern/random.h
+md5init.o: $(hdrdir)/ruby/internal/intern/range.h
+md5init.o: $(hdrdir)/ruby/internal/intern/rational.h
+md5init.o: $(hdrdir)/ruby/internal/intern/re.h
+md5init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+md5init.o: $(hdrdir)/ruby/internal/intern/select.h
+md5init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+md5init.o: $(hdrdir)/ruby/internal/intern/signal.h
+md5init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+md5init.o: $(hdrdir)/ruby/internal/intern/string.h
+md5init.o: $(hdrdir)/ruby/internal/intern/struct.h
+md5init.o: $(hdrdir)/ruby/internal/intern/thread.h
+md5init.o: $(hdrdir)/ruby/internal/intern/time.h
+md5init.o: $(hdrdir)/ruby/internal/intern/variable.h
+md5init.o: $(hdrdir)/ruby/internal/intern/vm.h
+md5init.o: $(hdrdir)/ruby/internal/interpreter.h
+md5init.o: $(hdrdir)/ruby/internal/iterator.h
+md5init.o: $(hdrdir)/ruby/internal/memory.h
+md5init.o: $(hdrdir)/ruby/internal/method.h
+md5init.o: $(hdrdir)/ruby/internal/module.h
+md5init.o: $(hdrdir)/ruby/internal/newobj.h
+md5init.o: $(hdrdir)/ruby/internal/rgengc.h
+md5init.o: $(hdrdir)/ruby/internal/scan_args.h
+md5init.o: $(hdrdir)/ruby/internal/special_consts.h
+md5init.o: $(hdrdir)/ruby/internal/static_assert.h
+md5init.o: $(hdrdir)/ruby/internal/stdalign.h
+md5init.o: $(hdrdir)/ruby/internal/stdbool.h
+md5init.o: $(hdrdir)/ruby/internal/symbol.h
+md5init.o: $(hdrdir)/ruby/internal/token_paste.h
+md5init.o: $(hdrdir)/ruby/internal/value.h
+md5init.o: $(hdrdir)/ruby/internal/value_type.h
+md5init.o: $(hdrdir)/ruby/internal/variable.h
+md5init.o: $(hdrdir)/ruby/internal/warning_push.h
+md5init.o: $(hdrdir)/ruby/internal/xmalloc.h
md5init.o: $(hdrdir)/ruby/missing.h
md5init.o: $(hdrdir)/ruby/ruby.h
md5init.o: $(hdrdir)/ruby/st.h
md5init.o: $(hdrdir)/ruby/subst.h
+md5init.o: $(srcdir)/../defs.h
md5init.o: $(srcdir)/../digest.h
+md5init.o: md5.h
md5init.o: md5init.c
-md5init.o: md5ossl.h
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c
index dafd38a29c..52cba78bf1 100644
--- a/ext/digest/md5/md5init.c
+++ b/ext/digest/md5/md5init.c
@@ -3,9 +3,7 @@
#include <ruby/ruby.h>
#include "../digest.h"
-#if defined(MD5_USE_OPENSSL)
-#include "md5ossl.h"
-#elif defined(MD5_USE_COMMONDIGEST)
+#if defined(MD5_USE_COMMONDIGEST)
#include "md5cc.h"
#else
#include "md5.h"
@@ -59,8 +57,5 @@ Init_md5(void)
cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base);
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
- rb_iv_set(cDigest_MD5, "metadata",
- Data_Wrap_Struct(0, 0, 0, (void *)&md5));
+ rb_iv_set(cDigest_MD5, "metadata", rb_digest_make_metadata(&md5));
}
diff --git a/ext/digest/md5/md5ossl.h b/ext/digest/md5/md5ossl.h
deleted file mode 100644
index 94aa7ae77b..0000000000
--- a/ext/digest/md5/md5ossl.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* $Id$ */
-
-#ifndef MD5OSSL_H_INCLUDED
-#define MD5OSSL_H_INCLUDED
-
-#include <stddef.h>
-#include <openssl/md5.h>
-
-#define MD5_BLOCK_LENGTH MD5_CBLOCK
-
-static DEFINE_FINISH_FUNC_FROM_FINAL(MD5)
-#undef MD5_Finish
-#define MD5_Finish rb_digest_MD5_finish
-
-#endif
diff --git a/ext/digest/rmd160/depend b/ext/digest/rmd160/depend
index 07c406a7d2..ce5dcdb871 100644
--- a/ext/digest/rmd160/depend
+++ b/ext/digest/rmd160/depend
@@ -2,18 +2,331 @@ rmd160.o: rmd160.c rmd160.h $(srcdir)/../defs.h
rmd160init.o: $(LOCAL_HDRS)
# AUTOGENERATED DEPENDENCIES START
+rmd160.o: $(RUBY_EXTCONF_H)
+rmd160.o: $(arch_hdrdir)/ruby/config.h
+rmd160.o: $(hdrdir)/ruby.h
+rmd160.o: $(hdrdir)/ruby/assert.h
+rmd160.o: $(hdrdir)/ruby/backward.h
+rmd160.o: $(hdrdir)/ruby/backward/2/assume.h
+rmd160.o: $(hdrdir)/ruby/backward/2/attributes.h
+rmd160.o: $(hdrdir)/ruby/backward/2/bool.h
+rmd160.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+rmd160.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rmd160.o: $(hdrdir)/ruby/backward/2/limits.h
+rmd160.o: $(hdrdir)/ruby/backward/2/long_long.h
+rmd160.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rmd160.o: $(hdrdir)/ruby/backward/2/stdarg.h
+rmd160.o: $(hdrdir)/ruby/defines.h
+rmd160.o: $(hdrdir)/ruby/intern.h
+rmd160.o: $(hdrdir)/ruby/internal/anyargs.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rmd160.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rmd160.o: $(hdrdir)/ruby/internal/assume.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/cold.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/const.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/error.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/format.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/pure.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/warning.h
+rmd160.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rmd160.o: $(hdrdir)/ruby/internal/cast.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rmd160.o: $(hdrdir)/ruby/internal/compiler_since.h
+rmd160.o: $(hdrdir)/ruby/internal/config.h
+rmd160.o: $(hdrdir)/ruby/internal/constant_p.h
+rmd160.o: $(hdrdir)/ruby/internal/core.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rarray.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rclass.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rdata.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rfile.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rhash.h
+rmd160.o: $(hdrdir)/ruby/internal/core/robject.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rstring.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rmd160.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rmd160.o: $(hdrdir)/ruby/internal/ctype.h
+rmd160.o: $(hdrdir)/ruby/internal/dllexport.h
+rmd160.o: $(hdrdir)/ruby/internal/dosish.h
+rmd160.o: $(hdrdir)/ruby/internal/error.h
+rmd160.o: $(hdrdir)/ruby/internal/eval.h
+rmd160.o: $(hdrdir)/ruby/internal/event.h
+rmd160.o: $(hdrdir)/ruby/internal/fl_type.h
+rmd160.o: $(hdrdir)/ruby/internal/gc.h
+rmd160.o: $(hdrdir)/ruby/internal/glob.h
+rmd160.o: $(hdrdir)/ruby/internal/globals.h
+rmd160.o: $(hdrdir)/ruby/internal/has/attribute.h
+rmd160.o: $(hdrdir)/ruby/internal/has/builtin.h
+rmd160.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rmd160.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rmd160.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rmd160.o: $(hdrdir)/ruby/internal/has/extension.h
+rmd160.o: $(hdrdir)/ruby/internal/has/feature.h
+rmd160.o: $(hdrdir)/ruby/internal/has/warning.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/array.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/class.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/compar.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/complex.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/cont.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/dir.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/enum.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/error.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/eval.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/file.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/gc.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/hash.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/io.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/load.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/object.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/parse.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/proc.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/process.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/random.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/range.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/rational.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/re.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/select.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/signal.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/string.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/struct.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/thread.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/time.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/variable.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/vm.h
+rmd160.o: $(hdrdir)/ruby/internal/interpreter.h
+rmd160.o: $(hdrdir)/ruby/internal/iterator.h
+rmd160.o: $(hdrdir)/ruby/internal/memory.h
+rmd160.o: $(hdrdir)/ruby/internal/method.h
+rmd160.o: $(hdrdir)/ruby/internal/module.h
+rmd160.o: $(hdrdir)/ruby/internal/newobj.h
+rmd160.o: $(hdrdir)/ruby/internal/rgengc.h
+rmd160.o: $(hdrdir)/ruby/internal/scan_args.h
+rmd160.o: $(hdrdir)/ruby/internal/special_consts.h
+rmd160.o: $(hdrdir)/ruby/internal/static_assert.h
+rmd160.o: $(hdrdir)/ruby/internal/stdalign.h
+rmd160.o: $(hdrdir)/ruby/internal/stdbool.h
+rmd160.o: $(hdrdir)/ruby/internal/symbol.h
+rmd160.o: $(hdrdir)/ruby/internal/token_paste.h
+rmd160.o: $(hdrdir)/ruby/internal/value.h
+rmd160.o: $(hdrdir)/ruby/internal/value_type.h
+rmd160.o: $(hdrdir)/ruby/internal/variable.h
+rmd160.o: $(hdrdir)/ruby/internal/warning_push.h
+rmd160.o: $(hdrdir)/ruby/internal/xmalloc.h
+rmd160.o: $(hdrdir)/ruby/missing.h
+rmd160.o: $(hdrdir)/ruby/ruby.h
+rmd160.o: $(hdrdir)/ruby/st.h
+rmd160.o: $(hdrdir)/ruby/subst.h
+rmd160.o: $(srcdir)/../defs.h
+rmd160.o: rmd160.c
+rmd160.o: rmd160.h
rmd160init.o: $(RUBY_EXTCONF_H)
rmd160init.o: $(arch_hdrdir)/ruby/config.h
rmd160init.o: $(hdrdir)/ruby.h
rmd160init.o: $(hdrdir)/ruby/assert.h
rmd160init.o: $(hdrdir)/ruby/backward.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/assume.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/attributes.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/bool.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/limits.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/long_long.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+rmd160init.o: $(hdrdir)/ruby/backward/2/stdarg.h
rmd160init.o: $(hdrdir)/ruby/defines.h
rmd160init.o: $(hdrdir)/ruby/intern.h
+rmd160init.o: $(hdrdir)/ruby/internal/anyargs.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+rmd160init.o: $(hdrdir)/ruby/internal/assume.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/cold.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/const.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/error.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/format.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/pure.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/warning.h
+rmd160init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+rmd160init.o: $(hdrdir)/ruby/internal/cast.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+rmd160init.o: $(hdrdir)/ruby/internal/compiler_since.h
+rmd160init.o: $(hdrdir)/ruby/internal/config.h
+rmd160init.o: $(hdrdir)/ruby/internal/constant_p.h
+rmd160init.o: $(hdrdir)/ruby/internal/core.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rarray.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rclass.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rdata.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rfile.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rhash.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/robject.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rstring.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+rmd160init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+rmd160init.o: $(hdrdir)/ruby/internal/ctype.h
+rmd160init.o: $(hdrdir)/ruby/internal/dllexport.h
+rmd160init.o: $(hdrdir)/ruby/internal/dosish.h
+rmd160init.o: $(hdrdir)/ruby/internal/error.h
+rmd160init.o: $(hdrdir)/ruby/internal/eval.h
+rmd160init.o: $(hdrdir)/ruby/internal/event.h
+rmd160init.o: $(hdrdir)/ruby/internal/fl_type.h
+rmd160init.o: $(hdrdir)/ruby/internal/gc.h
+rmd160init.o: $(hdrdir)/ruby/internal/glob.h
+rmd160init.o: $(hdrdir)/ruby/internal/globals.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/attribute.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/builtin.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/extension.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/feature.h
+rmd160init.o: $(hdrdir)/ruby/internal/has/warning.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/array.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/class.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/compar.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/complex.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/cont.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/dir.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/enum.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/error.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/eval.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/file.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/gc.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/hash.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/io.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/load.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/object.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/parse.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/proc.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/process.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/random.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/range.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/rational.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/re.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/select.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/signal.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/string.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/struct.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/thread.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/time.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/variable.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/vm.h
+rmd160init.o: $(hdrdir)/ruby/internal/interpreter.h
+rmd160init.o: $(hdrdir)/ruby/internal/iterator.h
+rmd160init.o: $(hdrdir)/ruby/internal/memory.h
+rmd160init.o: $(hdrdir)/ruby/internal/method.h
+rmd160init.o: $(hdrdir)/ruby/internal/module.h
+rmd160init.o: $(hdrdir)/ruby/internal/newobj.h
+rmd160init.o: $(hdrdir)/ruby/internal/rgengc.h
+rmd160init.o: $(hdrdir)/ruby/internal/scan_args.h
+rmd160init.o: $(hdrdir)/ruby/internal/special_consts.h
+rmd160init.o: $(hdrdir)/ruby/internal/static_assert.h
+rmd160init.o: $(hdrdir)/ruby/internal/stdalign.h
+rmd160init.o: $(hdrdir)/ruby/internal/stdbool.h
+rmd160init.o: $(hdrdir)/ruby/internal/symbol.h
+rmd160init.o: $(hdrdir)/ruby/internal/token_paste.h
+rmd160init.o: $(hdrdir)/ruby/internal/value.h
+rmd160init.o: $(hdrdir)/ruby/internal/value_type.h
+rmd160init.o: $(hdrdir)/ruby/internal/variable.h
+rmd160init.o: $(hdrdir)/ruby/internal/warning_push.h
+rmd160init.o: $(hdrdir)/ruby/internal/xmalloc.h
rmd160init.o: $(hdrdir)/ruby/missing.h
rmd160init.o: $(hdrdir)/ruby/ruby.h
rmd160init.o: $(hdrdir)/ruby/st.h
rmd160init.o: $(hdrdir)/ruby/subst.h
+rmd160init.o: $(srcdir)/../defs.h
rmd160init.o: $(srcdir)/../digest.h
+rmd160init.o: rmd160.h
rmd160init.o: rmd160init.c
-rmd160init.o: rmd160ossl.h
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/rmd160/extconf.rb b/ext/digest/rmd160/extconf.rb
index a02ba56169..ffa70ee803 100644
--- a/ext/digest/rmd160/extconf.rb
+++ b/ext/digest/rmd160/extconf.rb
@@ -10,7 +10,7 @@ $defs << "-DNDEBUG" << "-DHAVE_CONFIG_H"
$objs = [ "rmd160init.#{$OBJEXT}" ]
-digest_conf("rmd160", "ripemd", "RIPEMD160")
+digest_conf("rmd160")
have_header("sys/cdefs.h")
diff --git a/ext/digest/rmd160/rmd160init.c b/ext/digest/rmd160/rmd160init.c
index a2c0a023c0..2ae81ec4d6 100644
--- a/ext/digest/rmd160/rmd160init.c
+++ b/ext/digest/rmd160/rmd160init.c
@@ -3,11 +3,7 @@
#include <ruby/ruby.h>
#include "../digest.h"
-#if defined(RMD160_USE_OPENSSL)
-#include "rmd160ossl.h"
-#else
#include "rmd160.h"
-#endif
static const rb_digest_metadata_t rmd160 = {
RUBY_DIGEST_API_VERSION,
@@ -57,8 +53,5 @@ Init_rmd160(void)
cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base);
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
- rb_iv_set(cDigest_RMD160, "metadata",
- Data_Wrap_Struct(0, 0, 0, (void *)&rmd160));
+ rb_iv_set(cDigest_RMD160, "metadata", rb_digest_make_metadata(&rmd160));
}
diff --git a/ext/digest/rmd160/rmd160ossl.h b/ext/digest/rmd160/rmd160ossl.h
deleted file mode 100644
index e6bf5ea8d0..0000000000
--- a/ext/digest/rmd160/rmd160ossl.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* $Id$ */
-
-#ifndef RMD160OSSL_H_INCLUDED
-#define RMD160OSSL_H_INCLUDED
-
-#include <stddef.h>
-#include <openssl/ripemd.h>
-
-#define RMD160_CTX RIPEMD160_CTX
-
-#define RMD160_Init RIPEMD160_Init
-#define RMD160_Update RIPEMD160_Update
-
-#define RMD160_BLOCK_LENGTH RIPEMD160_CBLOCK
-#define RMD160_DIGEST_LENGTH RIPEMD160_DIGEST_LENGTH
-
-static DEFINE_FINISH_FUNC_FROM_FINAL(RIPEMD160)
-#define RMD160_Finish rb_digest_RIPEMD160_finish
-
-#endif
diff --git a/ext/digest/sha1/depend b/ext/digest/sha1/depend
index bc9e216eed..3daf84a137 100644
--- a/ext/digest/sha1/depend
+++ b/ext/digest/sha1/depend
@@ -2,18 +2,331 @@ sha1.o: sha1.c sha1.h $(srcdir)/../defs.h
sha1init.o: $(LOCAL_HDRS)
# AUTOGENERATED DEPENDENCIES START
+sha1.o: $(RUBY_EXTCONF_H)
+sha1.o: $(arch_hdrdir)/ruby/config.h
+sha1.o: $(hdrdir)/ruby.h
+sha1.o: $(hdrdir)/ruby/assert.h
+sha1.o: $(hdrdir)/ruby/backward.h
+sha1.o: $(hdrdir)/ruby/backward/2/assume.h
+sha1.o: $(hdrdir)/ruby/backward/2/attributes.h
+sha1.o: $(hdrdir)/ruby/backward/2/bool.h
+sha1.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+sha1.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sha1.o: $(hdrdir)/ruby/backward/2/limits.h
+sha1.o: $(hdrdir)/ruby/backward/2/long_long.h
+sha1.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sha1.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sha1.o: $(hdrdir)/ruby/defines.h
+sha1.o: $(hdrdir)/ruby/intern.h
+sha1.o: $(hdrdir)/ruby/internal/anyargs.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sha1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sha1.o: $(hdrdir)/ruby/internal/assume.h
+sha1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sha1.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sha1.o: $(hdrdir)/ruby/internal/attr/cold.h
+sha1.o: $(hdrdir)/ruby/internal/attr/const.h
+sha1.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sha1.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sha1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sha1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sha1.o: $(hdrdir)/ruby/internal/attr/error.h
+sha1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sha1.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sha1.o: $(hdrdir)/ruby/internal/attr/format.h
+sha1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sha1.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sha1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sha1.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sha1.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sha1.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sha1.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sha1.o: $(hdrdir)/ruby/internal/attr/pure.h
+sha1.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sha1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sha1.o: $(hdrdir)/ruby/internal/attr/warning.h
+sha1.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sha1.o: $(hdrdir)/ruby/internal/cast.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sha1.o: $(hdrdir)/ruby/internal/compiler_since.h
+sha1.o: $(hdrdir)/ruby/internal/config.h
+sha1.o: $(hdrdir)/ruby/internal/constant_p.h
+sha1.o: $(hdrdir)/ruby/internal/core.h
+sha1.o: $(hdrdir)/ruby/internal/core/rarray.h
+sha1.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sha1.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sha1.o: $(hdrdir)/ruby/internal/core/rclass.h
+sha1.o: $(hdrdir)/ruby/internal/core/rdata.h
+sha1.o: $(hdrdir)/ruby/internal/core/rfile.h
+sha1.o: $(hdrdir)/ruby/internal/core/rhash.h
+sha1.o: $(hdrdir)/ruby/internal/core/robject.h
+sha1.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sha1.o: $(hdrdir)/ruby/internal/core/rstring.h
+sha1.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sha1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sha1.o: $(hdrdir)/ruby/internal/ctype.h
+sha1.o: $(hdrdir)/ruby/internal/dllexport.h
+sha1.o: $(hdrdir)/ruby/internal/dosish.h
+sha1.o: $(hdrdir)/ruby/internal/error.h
+sha1.o: $(hdrdir)/ruby/internal/eval.h
+sha1.o: $(hdrdir)/ruby/internal/event.h
+sha1.o: $(hdrdir)/ruby/internal/fl_type.h
+sha1.o: $(hdrdir)/ruby/internal/gc.h
+sha1.o: $(hdrdir)/ruby/internal/glob.h
+sha1.o: $(hdrdir)/ruby/internal/globals.h
+sha1.o: $(hdrdir)/ruby/internal/has/attribute.h
+sha1.o: $(hdrdir)/ruby/internal/has/builtin.h
+sha1.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sha1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sha1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sha1.o: $(hdrdir)/ruby/internal/has/extension.h
+sha1.o: $(hdrdir)/ruby/internal/has/feature.h
+sha1.o: $(hdrdir)/ruby/internal/has/warning.h
+sha1.o: $(hdrdir)/ruby/internal/intern/array.h
+sha1.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sha1.o: $(hdrdir)/ruby/internal/intern/class.h
+sha1.o: $(hdrdir)/ruby/internal/intern/compar.h
+sha1.o: $(hdrdir)/ruby/internal/intern/complex.h
+sha1.o: $(hdrdir)/ruby/internal/intern/cont.h
+sha1.o: $(hdrdir)/ruby/internal/intern/dir.h
+sha1.o: $(hdrdir)/ruby/internal/intern/enum.h
+sha1.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sha1.o: $(hdrdir)/ruby/internal/intern/error.h
+sha1.o: $(hdrdir)/ruby/internal/intern/eval.h
+sha1.o: $(hdrdir)/ruby/internal/intern/file.h
+sha1.o: $(hdrdir)/ruby/internal/intern/gc.h
+sha1.o: $(hdrdir)/ruby/internal/intern/hash.h
+sha1.o: $(hdrdir)/ruby/internal/intern/io.h
+sha1.o: $(hdrdir)/ruby/internal/intern/load.h
+sha1.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sha1.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sha1.o: $(hdrdir)/ruby/internal/intern/object.h
+sha1.o: $(hdrdir)/ruby/internal/intern/parse.h
+sha1.o: $(hdrdir)/ruby/internal/intern/proc.h
+sha1.o: $(hdrdir)/ruby/internal/intern/process.h
+sha1.o: $(hdrdir)/ruby/internal/intern/random.h
+sha1.o: $(hdrdir)/ruby/internal/intern/range.h
+sha1.o: $(hdrdir)/ruby/internal/intern/rational.h
+sha1.o: $(hdrdir)/ruby/internal/intern/re.h
+sha1.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sha1.o: $(hdrdir)/ruby/internal/intern/select.h
+sha1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha1.o: $(hdrdir)/ruby/internal/intern/signal.h
+sha1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sha1.o: $(hdrdir)/ruby/internal/intern/string.h
+sha1.o: $(hdrdir)/ruby/internal/intern/struct.h
+sha1.o: $(hdrdir)/ruby/internal/intern/thread.h
+sha1.o: $(hdrdir)/ruby/internal/intern/time.h
+sha1.o: $(hdrdir)/ruby/internal/intern/variable.h
+sha1.o: $(hdrdir)/ruby/internal/intern/vm.h
+sha1.o: $(hdrdir)/ruby/internal/interpreter.h
+sha1.o: $(hdrdir)/ruby/internal/iterator.h
+sha1.o: $(hdrdir)/ruby/internal/memory.h
+sha1.o: $(hdrdir)/ruby/internal/method.h
+sha1.o: $(hdrdir)/ruby/internal/module.h
+sha1.o: $(hdrdir)/ruby/internal/newobj.h
+sha1.o: $(hdrdir)/ruby/internal/rgengc.h
+sha1.o: $(hdrdir)/ruby/internal/scan_args.h
+sha1.o: $(hdrdir)/ruby/internal/special_consts.h
+sha1.o: $(hdrdir)/ruby/internal/static_assert.h
+sha1.o: $(hdrdir)/ruby/internal/stdalign.h
+sha1.o: $(hdrdir)/ruby/internal/stdbool.h
+sha1.o: $(hdrdir)/ruby/internal/symbol.h
+sha1.o: $(hdrdir)/ruby/internal/token_paste.h
+sha1.o: $(hdrdir)/ruby/internal/value.h
+sha1.o: $(hdrdir)/ruby/internal/value_type.h
+sha1.o: $(hdrdir)/ruby/internal/variable.h
+sha1.o: $(hdrdir)/ruby/internal/warning_push.h
+sha1.o: $(hdrdir)/ruby/internal/xmalloc.h
+sha1.o: $(hdrdir)/ruby/missing.h
+sha1.o: $(hdrdir)/ruby/ruby.h
+sha1.o: $(hdrdir)/ruby/st.h
+sha1.o: $(hdrdir)/ruby/subst.h
+sha1.o: $(srcdir)/../defs.h
+sha1.o: sha1.c
+sha1.o: sha1.h
sha1init.o: $(RUBY_EXTCONF_H)
sha1init.o: $(arch_hdrdir)/ruby/config.h
sha1init.o: $(hdrdir)/ruby.h
sha1init.o: $(hdrdir)/ruby/assert.h
sha1init.o: $(hdrdir)/ruby/backward.h
+sha1init.o: $(hdrdir)/ruby/backward/2/assume.h
+sha1init.o: $(hdrdir)/ruby/backward/2/attributes.h
+sha1init.o: $(hdrdir)/ruby/backward/2/bool.h
+sha1init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+sha1init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sha1init.o: $(hdrdir)/ruby/backward/2/limits.h
+sha1init.o: $(hdrdir)/ruby/backward/2/long_long.h
+sha1init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sha1init.o: $(hdrdir)/ruby/backward/2/stdarg.h
sha1init.o: $(hdrdir)/ruby/defines.h
sha1init.o: $(hdrdir)/ruby/intern.h
+sha1init.o: $(hdrdir)/ruby/internal/anyargs.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sha1init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sha1init.o: $(hdrdir)/ruby/internal/assume.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/cold.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/const.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/error.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/format.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/pure.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/warning.h
+sha1init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sha1init.o: $(hdrdir)/ruby/internal/cast.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sha1init.o: $(hdrdir)/ruby/internal/compiler_since.h
+sha1init.o: $(hdrdir)/ruby/internal/config.h
+sha1init.o: $(hdrdir)/ruby/internal/constant_p.h
+sha1init.o: $(hdrdir)/ruby/internal/core.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rarray.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rclass.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rdata.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rfile.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rhash.h
+sha1init.o: $(hdrdir)/ruby/internal/core/robject.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rstring.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sha1init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sha1init.o: $(hdrdir)/ruby/internal/ctype.h
+sha1init.o: $(hdrdir)/ruby/internal/dllexport.h
+sha1init.o: $(hdrdir)/ruby/internal/dosish.h
+sha1init.o: $(hdrdir)/ruby/internal/error.h
+sha1init.o: $(hdrdir)/ruby/internal/eval.h
+sha1init.o: $(hdrdir)/ruby/internal/event.h
+sha1init.o: $(hdrdir)/ruby/internal/fl_type.h
+sha1init.o: $(hdrdir)/ruby/internal/gc.h
+sha1init.o: $(hdrdir)/ruby/internal/glob.h
+sha1init.o: $(hdrdir)/ruby/internal/globals.h
+sha1init.o: $(hdrdir)/ruby/internal/has/attribute.h
+sha1init.o: $(hdrdir)/ruby/internal/has/builtin.h
+sha1init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sha1init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sha1init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sha1init.o: $(hdrdir)/ruby/internal/has/extension.h
+sha1init.o: $(hdrdir)/ruby/internal/has/feature.h
+sha1init.o: $(hdrdir)/ruby/internal/has/warning.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/array.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/class.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/compar.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/complex.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/cont.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/dir.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/enum.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/error.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/eval.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/file.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/gc.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/hash.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/io.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/load.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/object.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/parse.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/proc.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/process.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/random.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/range.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/rational.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/re.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/select.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/signal.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/string.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/struct.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/thread.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/time.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/variable.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/vm.h
+sha1init.o: $(hdrdir)/ruby/internal/interpreter.h
+sha1init.o: $(hdrdir)/ruby/internal/iterator.h
+sha1init.o: $(hdrdir)/ruby/internal/memory.h
+sha1init.o: $(hdrdir)/ruby/internal/method.h
+sha1init.o: $(hdrdir)/ruby/internal/module.h
+sha1init.o: $(hdrdir)/ruby/internal/newobj.h
+sha1init.o: $(hdrdir)/ruby/internal/rgengc.h
+sha1init.o: $(hdrdir)/ruby/internal/scan_args.h
+sha1init.o: $(hdrdir)/ruby/internal/special_consts.h
+sha1init.o: $(hdrdir)/ruby/internal/static_assert.h
+sha1init.o: $(hdrdir)/ruby/internal/stdalign.h
+sha1init.o: $(hdrdir)/ruby/internal/stdbool.h
+sha1init.o: $(hdrdir)/ruby/internal/symbol.h
+sha1init.o: $(hdrdir)/ruby/internal/token_paste.h
+sha1init.o: $(hdrdir)/ruby/internal/value.h
+sha1init.o: $(hdrdir)/ruby/internal/value_type.h
+sha1init.o: $(hdrdir)/ruby/internal/variable.h
+sha1init.o: $(hdrdir)/ruby/internal/warning_push.h
+sha1init.o: $(hdrdir)/ruby/internal/xmalloc.h
sha1init.o: $(hdrdir)/ruby/missing.h
sha1init.o: $(hdrdir)/ruby/ruby.h
sha1init.o: $(hdrdir)/ruby/st.h
sha1init.o: $(hdrdir)/ruby/subst.h
+sha1init.o: $(srcdir)/../defs.h
sha1init.o: $(srcdir)/../digest.h
+sha1init.o: sha1.h
sha1init.o: sha1init.c
-sha1init.o: sha1ossl.h
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/sha1/extconf.rb b/ext/digest/sha1/extconf.rb
index 0ff4158bef..1e94ba3ef9 100644
--- a/ext/digest/sha1/extconf.rb
+++ b/ext/digest/sha1/extconf.rb
@@ -10,7 +10,7 @@ $defs << "-DHAVE_CONFIG_H"
$objs = [ "sha1init.#{$OBJEXT}" ]
-digest_conf("sha1", "sha", nil, %w[SHA])
+digest_conf("sha1")
have_header("sys/cdefs.h")
diff --git a/ext/digest/sha1/sha1init.c b/ext/digest/sha1/sha1init.c
index 3adf424b1d..f7047bc6d3 100644
--- a/ext/digest/sha1/sha1init.c
+++ b/ext/digest/sha1/sha1init.c
@@ -3,9 +3,7 @@
#include <ruby/ruby.h>
#include "../digest.h"
-#if defined(SHA1_USE_OPENSSL)
-#include "sha1ossl.h"
-#elif defined(SHA1_USE_COMMONDIGEST)
+#if defined(SHA1_USE_COMMONDIGEST)
#include "sha1cc.h"
#else
#include "sha1.h"
@@ -61,8 +59,5 @@ Init_sha1(void)
cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base);
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
- rb_iv_set(cDigest_SHA1, "metadata",
- Data_Wrap_Struct(0, 0, 0, (void *)&sha1));
+ rb_iv_set(cDigest_SHA1, "metadata", rb_digest_make_metadata(&sha1));
}
diff --git a/ext/digest/sha1/sha1ossl.h b/ext/digest/sha1/sha1ossl.h
deleted file mode 100644
index 599efe9a2f..0000000000
--- a/ext/digest/sha1/sha1ossl.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/* $Id$ */
-
-#ifndef SHA1OSSL_H_INCLUDED
-#define SHA1OSSL_H_INCLUDED
-
-#include <stddef.h>
-#include <openssl/sha.h>
-
-#define SHA1_CTX SHA_CTX
-
-#ifdef SHA_BLOCK_LENGTH
-#define SHA1_BLOCK_LENGTH SHA_BLOCK_LENGTH
-#else
-#define SHA1_BLOCK_LENGTH SHA_CBLOCK
-#endif
-#define SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
-
-static DEFINE_FINISH_FUNC_FROM_FINAL(SHA1)
-#undef SHA1_Finish
-#define SHA1_Finish rb_digest_SHA1_finish
-
-#endif
diff --git a/ext/digest/sha2/depend b/ext/digest/sha2/depend
index 8946d44f31..d8d265c1ef 100644
--- a/ext/digest/sha2/depend
+++ b/ext/digest/sha2/depend
@@ -2,18 +2,330 @@ sha2.o: sha2.c sha2.h $(srcdir)/../defs.h
sha2init.o: $(LOCAL_HDRS)
# AUTOGENERATED DEPENDENCIES START
+sha2.o: $(RUBY_EXTCONF_H)
+sha2.o: $(arch_hdrdir)/ruby/config.h
+sha2.o: $(hdrdir)/ruby.h
+sha2.o: $(hdrdir)/ruby/assert.h
+sha2.o: $(hdrdir)/ruby/backward.h
+sha2.o: $(hdrdir)/ruby/backward/2/assume.h
+sha2.o: $(hdrdir)/ruby/backward/2/attributes.h
+sha2.o: $(hdrdir)/ruby/backward/2/bool.h
+sha2.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+sha2.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sha2.o: $(hdrdir)/ruby/backward/2/limits.h
+sha2.o: $(hdrdir)/ruby/backward/2/long_long.h
+sha2.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sha2.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sha2.o: $(hdrdir)/ruby/defines.h
+sha2.o: $(hdrdir)/ruby/intern.h
+sha2.o: $(hdrdir)/ruby/internal/anyargs.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sha2.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sha2.o: $(hdrdir)/ruby/internal/assume.h
+sha2.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sha2.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sha2.o: $(hdrdir)/ruby/internal/attr/cold.h
+sha2.o: $(hdrdir)/ruby/internal/attr/const.h
+sha2.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sha2.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sha2.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sha2.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sha2.o: $(hdrdir)/ruby/internal/attr/error.h
+sha2.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sha2.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sha2.o: $(hdrdir)/ruby/internal/attr/format.h
+sha2.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sha2.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sha2.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sha2.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sha2.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sha2.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sha2.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sha2.o: $(hdrdir)/ruby/internal/attr/pure.h
+sha2.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sha2.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sha2.o: $(hdrdir)/ruby/internal/attr/warning.h
+sha2.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sha2.o: $(hdrdir)/ruby/internal/cast.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sha2.o: $(hdrdir)/ruby/internal/compiler_since.h
+sha2.o: $(hdrdir)/ruby/internal/config.h
+sha2.o: $(hdrdir)/ruby/internal/constant_p.h
+sha2.o: $(hdrdir)/ruby/internal/core.h
+sha2.o: $(hdrdir)/ruby/internal/core/rarray.h
+sha2.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sha2.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sha2.o: $(hdrdir)/ruby/internal/core/rclass.h
+sha2.o: $(hdrdir)/ruby/internal/core/rdata.h
+sha2.o: $(hdrdir)/ruby/internal/core/rfile.h
+sha2.o: $(hdrdir)/ruby/internal/core/rhash.h
+sha2.o: $(hdrdir)/ruby/internal/core/robject.h
+sha2.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sha2.o: $(hdrdir)/ruby/internal/core/rstring.h
+sha2.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sha2.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sha2.o: $(hdrdir)/ruby/internal/ctype.h
+sha2.o: $(hdrdir)/ruby/internal/dllexport.h
+sha2.o: $(hdrdir)/ruby/internal/dosish.h
+sha2.o: $(hdrdir)/ruby/internal/error.h
+sha2.o: $(hdrdir)/ruby/internal/eval.h
+sha2.o: $(hdrdir)/ruby/internal/event.h
+sha2.o: $(hdrdir)/ruby/internal/fl_type.h
+sha2.o: $(hdrdir)/ruby/internal/gc.h
+sha2.o: $(hdrdir)/ruby/internal/glob.h
+sha2.o: $(hdrdir)/ruby/internal/globals.h
+sha2.o: $(hdrdir)/ruby/internal/has/attribute.h
+sha2.o: $(hdrdir)/ruby/internal/has/builtin.h
+sha2.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sha2.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sha2.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sha2.o: $(hdrdir)/ruby/internal/has/extension.h
+sha2.o: $(hdrdir)/ruby/internal/has/feature.h
+sha2.o: $(hdrdir)/ruby/internal/has/warning.h
+sha2.o: $(hdrdir)/ruby/internal/intern/array.h
+sha2.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sha2.o: $(hdrdir)/ruby/internal/intern/class.h
+sha2.o: $(hdrdir)/ruby/internal/intern/compar.h
+sha2.o: $(hdrdir)/ruby/internal/intern/complex.h
+sha2.o: $(hdrdir)/ruby/internal/intern/cont.h
+sha2.o: $(hdrdir)/ruby/internal/intern/dir.h
+sha2.o: $(hdrdir)/ruby/internal/intern/enum.h
+sha2.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sha2.o: $(hdrdir)/ruby/internal/intern/error.h
+sha2.o: $(hdrdir)/ruby/internal/intern/eval.h
+sha2.o: $(hdrdir)/ruby/internal/intern/file.h
+sha2.o: $(hdrdir)/ruby/internal/intern/gc.h
+sha2.o: $(hdrdir)/ruby/internal/intern/hash.h
+sha2.o: $(hdrdir)/ruby/internal/intern/io.h
+sha2.o: $(hdrdir)/ruby/internal/intern/load.h
+sha2.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sha2.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sha2.o: $(hdrdir)/ruby/internal/intern/object.h
+sha2.o: $(hdrdir)/ruby/internal/intern/parse.h
+sha2.o: $(hdrdir)/ruby/internal/intern/proc.h
+sha2.o: $(hdrdir)/ruby/internal/intern/process.h
+sha2.o: $(hdrdir)/ruby/internal/intern/random.h
+sha2.o: $(hdrdir)/ruby/internal/intern/range.h
+sha2.o: $(hdrdir)/ruby/internal/intern/rational.h
+sha2.o: $(hdrdir)/ruby/internal/intern/re.h
+sha2.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sha2.o: $(hdrdir)/ruby/internal/intern/select.h
+sha2.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha2.o: $(hdrdir)/ruby/internal/intern/signal.h
+sha2.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sha2.o: $(hdrdir)/ruby/internal/intern/string.h
+sha2.o: $(hdrdir)/ruby/internal/intern/struct.h
+sha2.o: $(hdrdir)/ruby/internal/intern/thread.h
+sha2.o: $(hdrdir)/ruby/internal/intern/time.h
+sha2.o: $(hdrdir)/ruby/internal/intern/variable.h
+sha2.o: $(hdrdir)/ruby/internal/intern/vm.h
+sha2.o: $(hdrdir)/ruby/internal/interpreter.h
+sha2.o: $(hdrdir)/ruby/internal/iterator.h
+sha2.o: $(hdrdir)/ruby/internal/memory.h
+sha2.o: $(hdrdir)/ruby/internal/method.h
+sha2.o: $(hdrdir)/ruby/internal/module.h
+sha2.o: $(hdrdir)/ruby/internal/newobj.h
+sha2.o: $(hdrdir)/ruby/internal/rgengc.h
+sha2.o: $(hdrdir)/ruby/internal/scan_args.h
+sha2.o: $(hdrdir)/ruby/internal/special_consts.h
+sha2.o: $(hdrdir)/ruby/internal/static_assert.h
+sha2.o: $(hdrdir)/ruby/internal/stdalign.h
+sha2.o: $(hdrdir)/ruby/internal/stdbool.h
+sha2.o: $(hdrdir)/ruby/internal/symbol.h
+sha2.o: $(hdrdir)/ruby/internal/token_paste.h
+sha2.o: $(hdrdir)/ruby/internal/value.h
+sha2.o: $(hdrdir)/ruby/internal/value_type.h
+sha2.o: $(hdrdir)/ruby/internal/variable.h
+sha2.o: $(hdrdir)/ruby/internal/warning_push.h
+sha2.o: $(hdrdir)/ruby/internal/xmalloc.h
+sha2.o: $(hdrdir)/ruby/missing.h
+sha2.o: $(hdrdir)/ruby/ruby.h
+sha2.o: $(hdrdir)/ruby/st.h
+sha2.o: $(hdrdir)/ruby/subst.h
+sha2.o: $(srcdir)/../defs.h
+sha2.o: sha2.c
+sha2.o: sha2.h
sha2init.o: $(RUBY_EXTCONF_H)
sha2init.o: $(arch_hdrdir)/ruby/config.h
sha2init.o: $(hdrdir)/ruby.h
sha2init.o: $(hdrdir)/ruby/assert.h
sha2init.o: $(hdrdir)/ruby/backward.h
+sha2init.o: $(hdrdir)/ruby/backward/2/assume.h
+sha2init.o: $(hdrdir)/ruby/backward/2/attributes.h
+sha2init.o: $(hdrdir)/ruby/backward/2/bool.h
+sha2init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+sha2init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sha2init.o: $(hdrdir)/ruby/backward/2/limits.h
+sha2init.o: $(hdrdir)/ruby/backward/2/long_long.h
+sha2init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sha2init.o: $(hdrdir)/ruby/backward/2/stdarg.h
sha2init.o: $(hdrdir)/ruby/defines.h
sha2init.o: $(hdrdir)/ruby/intern.h
+sha2init.o: $(hdrdir)/ruby/internal/anyargs.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sha2init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sha2init.o: $(hdrdir)/ruby/internal/assume.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/cold.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/const.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/error.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/format.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/pure.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/warning.h
+sha2init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sha2init.o: $(hdrdir)/ruby/internal/cast.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sha2init.o: $(hdrdir)/ruby/internal/compiler_since.h
+sha2init.o: $(hdrdir)/ruby/internal/config.h
+sha2init.o: $(hdrdir)/ruby/internal/constant_p.h
+sha2init.o: $(hdrdir)/ruby/internal/core.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rarray.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rclass.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rdata.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rfile.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rhash.h
+sha2init.o: $(hdrdir)/ruby/internal/core/robject.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rstring.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sha2init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sha2init.o: $(hdrdir)/ruby/internal/ctype.h
+sha2init.o: $(hdrdir)/ruby/internal/dllexport.h
+sha2init.o: $(hdrdir)/ruby/internal/dosish.h
+sha2init.o: $(hdrdir)/ruby/internal/error.h
+sha2init.o: $(hdrdir)/ruby/internal/eval.h
+sha2init.o: $(hdrdir)/ruby/internal/event.h
+sha2init.o: $(hdrdir)/ruby/internal/fl_type.h
+sha2init.o: $(hdrdir)/ruby/internal/gc.h
+sha2init.o: $(hdrdir)/ruby/internal/glob.h
+sha2init.o: $(hdrdir)/ruby/internal/globals.h
+sha2init.o: $(hdrdir)/ruby/internal/has/attribute.h
+sha2init.o: $(hdrdir)/ruby/internal/has/builtin.h
+sha2init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sha2init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sha2init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sha2init.o: $(hdrdir)/ruby/internal/has/extension.h
+sha2init.o: $(hdrdir)/ruby/internal/has/feature.h
+sha2init.o: $(hdrdir)/ruby/internal/has/warning.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/array.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/class.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/compar.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/complex.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/cont.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/dir.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/enum.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/error.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/eval.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/file.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/gc.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/hash.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/io.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/load.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/object.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/parse.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/proc.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/process.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/random.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/range.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/rational.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/re.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/select.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/signal.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/string.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/struct.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/thread.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/time.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/variable.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/vm.h
+sha2init.o: $(hdrdir)/ruby/internal/interpreter.h
+sha2init.o: $(hdrdir)/ruby/internal/iterator.h
+sha2init.o: $(hdrdir)/ruby/internal/memory.h
+sha2init.o: $(hdrdir)/ruby/internal/method.h
+sha2init.o: $(hdrdir)/ruby/internal/module.h
+sha2init.o: $(hdrdir)/ruby/internal/newobj.h
+sha2init.o: $(hdrdir)/ruby/internal/rgengc.h
+sha2init.o: $(hdrdir)/ruby/internal/scan_args.h
+sha2init.o: $(hdrdir)/ruby/internal/special_consts.h
+sha2init.o: $(hdrdir)/ruby/internal/static_assert.h
+sha2init.o: $(hdrdir)/ruby/internal/stdalign.h
+sha2init.o: $(hdrdir)/ruby/internal/stdbool.h
+sha2init.o: $(hdrdir)/ruby/internal/symbol.h
+sha2init.o: $(hdrdir)/ruby/internal/token_paste.h
+sha2init.o: $(hdrdir)/ruby/internal/value.h
+sha2init.o: $(hdrdir)/ruby/internal/value_type.h
+sha2init.o: $(hdrdir)/ruby/internal/variable.h
+sha2init.o: $(hdrdir)/ruby/internal/warning_push.h
+sha2init.o: $(hdrdir)/ruby/internal/xmalloc.h
sha2init.o: $(hdrdir)/ruby/missing.h
sha2init.o: $(hdrdir)/ruby/ruby.h
sha2init.o: $(hdrdir)/ruby/st.h
sha2init.o: $(hdrdir)/ruby/subst.h
sha2init.o: $(srcdir)/../digest.h
+sha2init.o: sha2.h
sha2init.o: sha2init.c
-sha2init.o: sha2ossl.h
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/digest/sha2/extconf.rb b/ext/digest/sha2/extconf.rb
index 5c7f76c7f3..8bf28111b6 100644
--- a/ext/digest/sha2/extconf.rb
+++ b/ext/digest/sha2/extconf.rb
@@ -10,7 +10,7 @@ $defs << "-DHAVE_CONFIG_H"
$objs = [ "sha2init.#{$OBJEXT}" ]
-unless digest_conf("sha2", "sha", %w[SHA256 SHA512])
+unless digest_conf("sha2")
have_type("u_int8_t")
end
diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c
index 7d211784a3..6ed275eb71 100644
--- a/ext/digest/sha2/sha2init.c
+++ b/ext/digest/sha2/sha2init.c
@@ -3,9 +3,7 @@
#include <ruby/ruby.h>
#include "../digest.h"
-#if defined(SHA2_USE_OPENSSL)
-#include "sha2ossl.h"
-#elif defined(SHA2_USE_COMMONDIGEST)
+#if defined(SHA2_USE_COMMONDIGEST)
#include "sha2cc.h"
#else
#include "sha2.h"
@@ -49,9 +47,7 @@ Init_sha2(void)
cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \
\
rb_ivar_set(cDigest_SHA##bitlen, id_metadata, \
- Data_Wrap_Struct(0, 0, 0, (void *)&sha##bitlen));
+ rb_digest_make_metadata(&sha##bitlen));
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
FOREACH_BITLEN(DEFINE_ALGO_CLASS)
}
diff --git a/ext/digest/sha2/sha2ossl.h b/ext/digest/sha2/sha2ossl.h
deleted file mode 100644
index 8dd0530107..0000000000
--- a/ext/digest/sha2/sha2ossl.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef SHA2OSSL_H_INCLUDED
-#define SHA2OSSL_H_INCLUDED
-
-#include <stddef.h>
-#include <openssl/sha.h>
-
-#define SHA256_BLOCK_LENGTH SHA256_CBLOCK
-#define SHA384_BLOCK_LENGTH SHA512_CBLOCK
-#define SHA512_BLOCK_LENGTH SHA512_CBLOCK
-
-#ifndef __DragonFly__
-#define SHA384_Final SHA512_Final
-#endif
-
-typedef SHA512_CTX SHA384_CTX;
-
-#undef SHA256_Finish
-#undef SHA384_Finish
-#undef SHA512_Finish
-#define SHA256_Finish rb_digest_SHA256_finish
-#define SHA384_Finish rb_digest_SHA384_finish
-#define SHA512_Finish rb_digest_SHA512_finish
-static DEFINE_FINISH_FUNC_FROM_FINAL(SHA256)
-static DEFINE_FINISH_FUNC_FROM_FINAL(SHA384)
-static DEFINE_FINISH_FUNC_FROM_FINAL(SHA512)
-
-#endif
diff --git a/ext/etc/depend b/ext/etc/depend
index 99e812c7e4..67d9be582f 100644
--- a/ext/etc/depend
+++ b/ext/etc/depend
@@ -7,10 +7,160 @@ etc.o: $(RUBY_EXTCONF_H)
etc.o: $(arch_hdrdir)/ruby/config.h
etc.o: $(hdrdir)/ruby.h
etc.o: $(hdrdir)/ruby/assert.h
+etc.o: $(hdrdir)/ruby/atomic.h
etc.o: $(hdrdir)/ruby/backward.h
+etc.o: $(hdrdir)/ruby/backward/2/assume.h
+etc.o: $(hdrdir)/ruby/backward/2/attributes.h
+etc.o: $(hdrdir)/ruby/backward/2/bool.h
+etc.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+etc.o: $(hdrdir)/ruby/backward/2/inttypes.h
+etc.o: $(hdrdir)/ruby/backward/2/limits.h
+etc.o: $(hdrdir)/ruby/backward/2/long_long.h
+etc.o: $(hdrdir)/ruby/backward/2/stdalign.h
+etc.o: $(hdrdir)/ruby/backward/2/stdarg.h
etc.o: $(hdrdir)/ruby/defines.h
etc.o: $(hdrdir)/ruby/encoding.h
etc.o: $(hdrdir)/ruby/intern.h
+etc.o: $(hdrdir)/ruby/internal/anyargs.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+etc.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+etc.o: $(hdrdir)/ruby/internal/assume.h
+etc.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+etc.o: $(hdrdir)/ruby/internal/attr/artificial.h
+etc.o: $(hdrdir)/ruby/internal/attr/cold.h
+etc.o: $(hdrdir)/ruby/internal/attr/const.h
+etc.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+etc.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+etc.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+etc.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+etc.o: $(hdrdir)/ruby/internal/attr/error.h
+etc.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+etc.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+etc.o: $(hdrdir)/ruby/internal/attr/format.h
+etc.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+etc.o: $(hdrdir)/ruby/internal/attr/noalias.h
+etc.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+etc.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+etc.o: $(hdrdir)/ruby/internal/attr/noinline.h
+etc.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+etc.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+etc.o: $(hdrdir)/ruby/internal/attr/pure.h
+etc.o: $(hdrdir)/ruby/internal/attr/restrict.h
+etc.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+etc.o: $(hdrdir)/ruby/internal/attr/warning.h
+etc.o: $(hdrdir)/ruby/internal/attr/weakref.h
+etc.o: $(hdrdir)/ruby/internal/cast.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+etc.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+etc.o: $(hdrdir)/ruby/internal/compiler_since.h
+etc.o: $(hdrdir)/ruby/internal/config.h
+etc.o: $(hdrdir)/ruby/internal/constant_p.h
+etc.o: $(hdrdir)/ruby/internal/core.h
+etc.o: $(hdrdir)/ruby/internal/core/rarray.h
+etc.o: $(hdrdir)/ruby/internal/core/rbasic.h
+etc.o: $(hdrdir)/ruby/internal/core/rbignum.h
+etc.o: $(hdrdir)/ruby/internal/core/rclass.h
+etc.o: $(hdrdir)/ruby/internal/core/rdata.h
+etc.o: $(hdrdir)/ruby/internal/core/rfile.h
+etc.o: $(hdrdir)/ruby/internal/core/rhash.h
+etc.o: $(hdrdir)/ruby/internal/core/robject.h
+etc.o: $(hdrdir)/ruby/internal/core/rregexp.h
+etc.o: $(hdrdir)/ruby/internal/core/rstring.h
+etc.o: $(hdrdir)/ruby/internal/core/rstruct.h
+etc.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+etc.o: $(hdrdir)/ruby/internal/ctype.h
+etc.o: $(hdrdir)/ruby/internal/dllexport.h
+etc.o: $(hdrdir)/ruby/internal/dosish.h
+etc.o: $(hdrdir)/ruby/internal/error.h
+etc.o: $(hdrdir)/ruby/internal/eval.h
+etc.o: $(hdrdir)/ruby/internal/event.h
+etc.o: $(hdrdir)/ruby/internal/fl_type.h
+etc.o: $(hdrdir)/ruby/internal/gc.h
+etc.o: $(hdrdir)/ruby/internal/glob.h
+etc.o: $(hdrdir)/ruby/internal/globals.h
+etc.o: $(hdrdir)/ruby/internal/has/attribute.h
+etc.o: $(hdrdir)/ruby/internal/has/builtin.h
+etc.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+etc.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+etc.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+etc.o: $(hdrdir)/ruby/internal/has/extension.h
+etc.o: $(hdrdir)/ruby/internal/has/feature.h
+etc.o: $(hdrdir)/ruby/internal/has/warning.h
+etc.o: $(hdrdir)/ruby/internal/intern/array.h
+etc.o: $(hdrdir)/ruby/internal/intern/bignum.h
+etc.o: $(hdrdir)/ruby/internal/intern/class.h
+etc.o: $(hdrdir)/ruby/internal/intern/compar.h
+etc.o: $(hdrdir)/ruby/internal/intern/complex.h
+etc.o: $(hdrdir)/ruby/internal/intern/cont.h
+etc.o: $(hdrdir)/ruby/internal/intern/dir.h
+etc.o: $(hdrdir)/ruby/internal/intern/enum.h
+etc.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+etc.o: $(hdrdir)/ruby/internal/intern/error.h
+etc.o: $(hdrdir)/ruby/internal/intern/eval.h
+etc.o: $(hdrdir)/ruby/internal/intern/file.h
+etc.o: $(hdrdir)/ruby/internal/intern/gc.h
+etc.o: $(hdrdir)/ruby/internal/intern/hash.h
+etc.o: $(hdrdir)/ruby/internal/intern/io.h
+etc.o: $(hdrdir)/ruby/internal/intern/load.h
+etc.o: $(hdrdir)/ruby/internal/intern/marshal.h
+etc.o: $(hdrdir)/ruby/internal/intern/numeric.h
+etc.o: $(hdrdir)/ruby/internal/intern/object.h
+etc.o: $(hdrdir)/ruby/internal/intern/parse.h
+etc.o: $(hdrdir)/ruby/internal/intern/proc.h
+etc.o: $(hdrdir)/ruby/internal/intern/process.h
+etc.o: $(hdrdir)/ruby/internal/intern/random.h
+etc.o: $(hdrdir)/ruby/internal/intern/range.h
+etc.o: $(hdrdir)/ruby/internal/intern/rational.h
+etc.o: $(hdrdir)/ruby/internal/intern/re.h
+etc.o: $(hdrdir)/ruby/internal/intern/ruby.h
+etc.o: $(hdrdir)/ruby/internal/intern/select.h
+etc.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+etc.o: $(hdrdir)/ruby/internal/intern/signal.h
+etc.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+etc.o: $(hdrdir)/ruby/internal/intern/string.h
+etc.o: $(hdrdir)/ruby/internal/intern/struct.h
+etc.o: $(hdrdir)/ruby/internal/intern/thread.h
+etc.o: $(hdrdir)/ruby/internal/intern/time.h
+etc.o: $(hdrdir)/ruby/internal/intern/variable.h
+etc.o: $(hdrdir)/ruby/internal/intern/vm.h
+etc.o: $(hdrdir)/ruby/internal/interpreter.h
+etc.o: $(hdrdir)/ruby/internal/iterator.h
+etc.o: $(hdrdir)/ruby/internal/memory.h
+etc.o: $(hdrdir)/ruby/internal/method.h
+etc.o: $(hdrdir)/ruby/internal/module.h
+etc.o: $(hdrdir)/ruby/internal/newobj.h
+etc.o: $(hdrdir)/ruby/internal/rgengc.h
+etc.o: $(hdrdir)/ruby/internal/scan_args.h
+etc.o: $(hdrdir)/ruby/internal/special_consts.h
+etc.o: $(hdrdir)/ruby/internal/static_assert.h
+etc.o: $(hdrdir)/ruby/internal/stdalign.h
+etc.o: $(hdrdir)/ruby/internal/stdbool.h
+etc.o: $(hdrdir)/ruby/internal/symbol.h
+etc.o: $(hdrdir)/ruby/internal/token_paste.h
+etc.o: $(hdrdir)/ruby/internal/value.h
+etc.o: $(hdrdir)/ruby/internal/value_type.h
+etc.o: $(hdrdir)/ruby/internal/variable.h
+etc.o: $(hdrdir)/ruby/internal/warning_push.h
+etc.o: $(hdrdir)/ruby/internal/xmalloc.h
etc.o: $(hdrdir)/ruby/io.h
etc.o: $(hdrdir)/ruby/missing.h
etc.o: $(hdrdir)/ruby/onigmo.h
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index 2f3fbb737b..737d295abc 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -52,10 +52,33 @@ char *getenv();
#endif
char *getlogin();
-#define RUBY_ETC_VERSION "1.1.0"
+#define RUBY_ETC_VERSION "1.3.0"
+
+#ifdef HAVE_RB_DEPRECATE_CONSTANT
+void rb_deprecate_constant(VALUE mod, const char *name);
+#else
+# define rb_deprecate_constant(mod,name) ((void)(mod),(void)(name))
+#endif
#include "constdefs.h"
+#ifdef HAVE_RUBY_ATOMIC_H
+# include "ruby/atomic.h"
+#else
+typedef int rb_atomic_t;
+# define RUBY_ATOMIC_CAS(var, oldval, newval) \
+ ((var) == (oldval) ? ((var) = (newval), (oldval)) : (var))
+# define RUBY_ATOMIC_EXCHANGE(var, newval) \
+ atomic_exchange(&var, newval)
+static inline rb_atomic_t
+atomic_exchange(volatile rb_atomic_t *var, rb_atomic_t newval)
+{
+ rb_atomic_t oldval = *var;
+ *var = newval;
+ return oldval;
+}
+#endif
+
/* call-seq:
* getlogin -> String
*
@@ -119,6 +142,12 @@ safe_setup_filesystem_str(const char *str)
#endif
#ifdef HAVE_GETPWENT
+# ifdef __APPLE__
+# define PW_TIME2VAL(t) INT2NUM((int)(t))
+# else
+# define PW_TIME2VAL(t) TIMET2NUM(t)
+# endif
+
static VALUE
setup_passwd(struct passwd *pwd)
{
@@ -136,7 +165,7 @@ setup_passwd(struct passwd *pwd)
safe_setup_filesystem_str(pwd->pw_dir),
safe_setup_filesystem_str(pwd->pw_shell),
#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
- INT2NUM(pwd->pw_change),
+ PW_TIME2VAL(pwd->pw_change),
#endif
#ifdef HAVE_STRUCT_PASSWD_PW_QUOTA
INT2NUM(pwd->pw_quota),
@@ -151,7 +180,7 @@ setup_passwd(struct passwd *pwd)
safe_setup_locale_str(pwd->pw_comment),
#endif
#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
- INT2NUM(pwd->pw_expire),
+ PW_TIME2VAL(pwd->pw_expire),
#endif
0 /*dummy*/
);
@@ -228,12 +257,14 @@ etc_getpwnam(VALUE obj, VALUE nam)
}
#ifdef HAVE_GETPWENT
-static int passwd_blocking = 0;
+static rb_atomic_t passwd_blocking;
static VALUE
passwd_ensure(VALUE _)
{
endpwent();
- passwd_blocking = (int)Qfalse;
+ if (RUBY_ATOMIC_EXCHANGE(passwd_blocking, 0) != 1) {
+ rb_raise(rb_eRuntimeError, "unexpected passwd_blocking");
+ }
return Qnil;
}
@@ -252,10 +283,9 @@ passwd_iterate(VALUE _)
static void
each_passwd(void)
{
- if (passwd_blocking) {
+ if (RUBY_ATOMIC_CAS(passwd_blocking, 0, 1)) {
rb_raise(rb_eRuntimeError, "parallel passwd iteration");
}
- passwd_blocking = (int)Qtrue;
rb_ensure(passwd_iterate, 0, passwd_ensure, 0);
}
#endif
@@ -471,12 +501,14 @@ etc_getgrnam(VALUE obj, VALUE nam)
}
#ifdef HAVE_GETGRENT
-static int group_blocking = 0;
+static rb_atomic_t group_blocking;
static VALUE
group_ensure(VALUE _)
{
endgrent();
- group_blocking = (int)Qfalse;
+ if (RUBY_ATOMIC_EXCHANGE(group_blocking, 0) != 1) {
+ rb_raise(rb_eRuntimeError, "unexpected group_blocking");
+ }
return Qnil;
}
@@ -496,10 +528,9 @@ group_iterate(VALUE _)
static void
each_group(void)
{
- if (group_blocking) {
+ if (RUBY_ATOMIC_CAS(group_blocking, 0, 1)) {
rb_raise(rb_eRuntimeError, "parallel group iteration");
}
- group_blocking = (int)Qtrue;
rb_ensure(group_iterate, 0, group_ensure, 0);
}
#endif
@@ -926,11 +957,13 @@ io_pathconf(VALUE io, VALUE arg)
static int
etc_nprocessors_affin(void)
{
- cpu_set_t *cpuset;
+ cpu_set_t *cpuset, cpuset_buff[1024 / sizeof(cpu_set_t)];
size_t size;
int ret;
int n;
+ CPU_ZERO_S(sizeof(cpuset_buff), cpuset_buff);
+
/*
* XXX:
* man page says CPU_ALLOC takes number of cpus. But it is not accurate
@@ -949,13 +982,12 @@ etc_nprocessors_affin(void)
*/
for (n=64; n <= 16384; n *= 2) {
size = CPU_ALLOC_SIZE(n);
- if (size >= 1024) {
+ if (size >= sizeof(cpuset_buff)) {
cpuset = xcalloc(1, size);
if (!cpuset)
return -1;
} else {
- cpuset = alloca(size);
- CPU_ZERO_S(size, cpuset);
+ cpuset = cpuset_buff;
}
ret = sched_getaffinity(0, size, cpuset);
@@ -964,10 +996,10 @@ etc_nprocessors_affin(void)
ret = CPU_COUNT_S(size, cpuset);
}
- if (size >= 1024) {
+ if (size >= sizeof(cpuset_buff)) {
xfree(cpuset);
}
- if (ret > 0) {
+ if (ret > 0 || errno != EINVAL) {
return ret;
}
}
@@ -1064,6 +1096,9 @@ Init_etc(void)
{
VALUE mEtc;
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+ #endif
mEtc = rb_define_module("Etc");
rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION));
init_constants(mEtc);
@@ -1165,9 +1200,9 @@ Init_etc(void)
rb_define_const(mEtc, "Passwd", sPasswd);
#endif
rb_define_const(rb_cStruct, "Passwd", sPasswd); /* deprecated name */
+ rb_deprecate_constant(rb_cStruct, "Passwd");
rb_extend_object(sPasswd, rb_mEnumerable);
rb_define_singleton_method(sPasswd, "each", etc_each_passwd, 0);
-
#ifdef HAVE_GETGRENT
sGroup = rb_struct_define_under(mEtc, "Group", "name",
#ifdef HAVE_STRUCT_GROUP_GR_PASSWD
@@ -1200,6 +1235,7 @@ Init_etc(void)
rb_define_const(mEtc, "Group", sGroup);
#endif
rb_define_const(rb_cStruct, "Group", sGroup); /* deprecated name */
+ rb_deprecate_constant(rb_cStruct, "Group");
rb_extend_object(sGroup, rb_mEnumerable);
rb_define_singleton_method(sGroup, "each", etc_each_group, 0);
#endif
diff --git a/ext/etc/etc.gemspec b/ext/etc/etc.gemspec
index f28016925f..7d687e3b99 100644
--- a/ext/etc/etc.gemspec
+++ b/ext/etc/etc.gemspec
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
spec.summary = %q{Provides access to information typically stored in UNIX /etc directory.}
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/etc"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.files = %w[
LICENSE.txt
@@ -29,7 +29,6 @@ Gem::Specification.new do |spec|
ext/etc/etc.c
ext/etc/extconf.rb
ext/etc/mkconstants.rb
- stub/etc.rb
test/etc/test_etc.rb
]
spec.bindir = "exe"
diff --git a/ext/etc/extconf.rb b/ext/etc/extconf.rb
index 435fbe7f3d..6e7810a5e8 100644
--- a/ext/etc/extconf.rb
+++ b/ext/etc/extconf.rb
@@ -47,6 +47,8 @@ if !File.exist?("#{srcdir}/depend")
%x[#{RbConfig.ruby} #{srcdir}/mkconstants.rb -o #{srcdir}/constdefs.h]
end
+have_func('rb_deprecate_constant(Qnil, "None")')
+
$distcleanfiles << "constdefs.h"
create_makefile("etc")
diff --git a/ext/extmk.rb b/ext/extmk.rb
index 97f1ad9c39..80a0a1208d 100755
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -408,10 +408,8 @@ if CROSS_COMPILING
$ruby = $mflags.defined?("MINIRUBY") || CONFIG['MINIRUBY']
elsif sep = config_string('BUILD_FILE_SEPARATOR')
$ruby = "$(topdir:/=#{sep})#{sep}miniruby" + EXEEXT
-elsif CONFIG['EXTSTATIC']
- $ruby = '$(topdir)/miniruby' + EXEEXT
else
- $ruby = '$(topdir)/ruby' + EXEEXT
+ $ruby = '$(topdir)/miniruby' + EXEEXT
end
$ruby = [$ruby]
$ruby << "-I'$(topdir)'"
@@ -423,7 +421,6 @@ end
topruby = $ruby
$ruby = topruby.join(' ')
$mflags << "ruby=#$ruby"
-$builtruby = '$(topdir)/miniruby' + EXEEXT # Must be an executable path
MTIMES = [__FILE__, 'rbconfig.rb', srcdir+'/lib/mkmf.rb'].collect {|f| File.mtime(f)}
diff --git a/ext/fcntl/depend b/ext/fcntl/depend
index 60d6be6b89..cdaa3aa582 100644
--- a/ext/fcntl/depend
+++ b/ext/fcntl/depend
@@ -2,8 +2,157 @@
fcntl.o: $(RUBY_EXTCONF_H)
fcntl.o: $(arch_hdrdir)/ruby/config.h
fcntl.o: $(hdrdir)/ruby.h
+fcntl.o: $(hdrdir)/ruby/internal/anyargs.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+fcntl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+fcntl.o: $(hdrdir)/ruby/internal/assume.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/cold.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/const.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/error.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/format.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/pure.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/warning.h
+fcntl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+fcntl.o: $(hdrdir)/ruby/internal/cast.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+fcntl.o: $(hdrdir)/ruby/internal/compiler_since.h
+fcntl.o: $(hdrdir)/ruby/internal/config.h
+fcntl.o: $(hdrdir)/ruby/internal/constant_p.h
+fcntl.o: $(hdrdir)/ruby/internal/core.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rarray.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rclass.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rdata.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rfile.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rhash.h
+fcntl.o: $(hdrdir)/ruby/internal/core/robject.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rstring.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+fcntl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+fcntl.o: $(hdrdir)/ruby/internal/ctype.h
+fcntl.o: $(hdrdir)/ruby/internal/dllexport.h
+fcntl.o: $(hdrdir)/ruby/internal/dosish.h
+fcntl.o: $(hdrdir)/ruby/internal/error.h
+fcntl.o: $(hdrdir)/ruby/internal/eval.h
+fcntl.o: $(hdrdir)/ruby/internal/event.h
+fcntl.o: $(hdrdir)/ruby/internal/fl_type.h
+fcntl.o: $(hdrdir)/ruby/internal/gc.h
+fcntl.o: $(hdrdir)/ruby/internal/glob.h
+fcntl.o: $(hdrdir)/ruby/internal/globals.h
+fcntl.o: $(hdrdir)/ruby/internal/has/attribute.h
+fcntl.o: $(hdrdir)/ruby/internal/has/builtin.h
+fcntl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+fcntl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+fcntl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+fcntl.o: $(hdrdir)/ruby/internal/has/extension.h
+fcntl.o: $(hdrdir)/ruby/internal/has/feature.h
+fcntl.o: $(hdrdir)/ruby/internal/has/warning.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/array.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/class.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/compar.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/complex.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/cont.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/dir.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/enum.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/error.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/eval.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/file.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/gc.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/hash.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/io.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/load.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/object.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/parse.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/proc.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/process.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/random.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/range.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/rational.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/re.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/select.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/signal.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/string.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/struct.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/thread.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/time.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/variable.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/vm.h
+fcntl.o: $(hdrdir)/ruby/internal/interpreter.h
+fcntl.o: $(hdrdir)/ruby/internal/iterator.h
+fcntl.o: $(hdrdir)/ruby/internal/memory.h
+fcntl.o: $(hdrdir)/ruby/internal/method.h
+fcntl.o: $(hdrdir)/ruby/internal/module.h
+fcntl.o: $(hdrdir)/ruby/internal/newobj.h
+fcntl.o: $(hdrdir)/ruby/internal/rgengc.h
+fcntl.o: $(hdrdir)/ruby/internal/scan_args.h
+fcntl.o: $(hdrdir)/ruby/internal/special_consts.h
+fcntl.o: $(hdrdir)/ruby/internal/static_assert.h
+fcntl.o: $(hdrdir)/ruby/internal/stdalign.h
+fcntl.o: $(hdrdir)/ruby/internal/stdbool.h
+fcntl.o: $(hdrdir)/ruby/internal/symbol.h
+fcntl.o: $(hdrdir)/ruby/internal/token_paste.h
+fcntl.o: $(hdrdir)/ruby/internal/value.h
+fcntl.o: $(hdrdir)/ruby/internal/value_type.h
+fcntl.o: $(hdrdir)/ruby/internal/variable.h
+fcntl.o: $(hdrdir)/ruby/internal/warning_push.h
+fcntl.o: $(hdrdir)/ruby/internal/xmalloc.h
fcntl.o: $(hdrdir)/ruby/assert.h
fcntl.o: $(hdrdir)/ruby/backward.h
+fcntl.o: $(hdrdir)/ruby/backward/2/assume.h
+fcntl.o: $(hdrdir)/ruby/backward/2/attributes.h
+fcntl.o: $(hdrdir)/ruby/backward/2/bool.h
+fcntl.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+fcntl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+fcntl.o: $(hdrdir)/ruby/backward/2/limits.h
+fcntl.o: $(hdrdir)/ruby/backward/2/long_long.h
+fcntl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+fcntl.o: $(hdrdir)/ruby/backward/2/stdarg.h
fcntl.o: $(hdrdir)/ruby/defines.h
fcntl.o: $(hdrdir)/ruby/intern.h
fcntl.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index c93694c431..ee42d2abe5 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -159,6 +159,20 @@ Init_fcntl(void)
*/
rb_define_const(mFcntl, "F_WRLCK", INT2NUM(F_WRLCK));
#endif
+#ifdef F_SETPIPE_SZ
+ /* Document-const: F_SETPIPE_SZ
+ *
+ * Change the capacity of the pipe referred to by fd to be at least arg bytes.
+ */
+ rb_define_const(mFcntl, "F_SETPIPE_SZ", INT2NUM(F_SETPIPE_SZ));
+#endif
+#ifdef F_GETPIPE_SZ
+ /* Document-const: F_GETPIPE_SZ
+ *
+ * Return (as the function result) the capacity of the pipe referred to by fd.
+ */
+ rb_define_const(mFcntl, "F_GETPIPE_SZ", INT2NUM(F_GETPIPE_SZ));
+#endif
#ifdef O_CREAT
/* Document-const: O_CREAT
*
diff --git a/ext/fcntl/fcntl.gemspec b/ext/fcntl/fcntl.gemspec
index 0e3194fbdc..048e101aa5 100644
--- a/ext/fcntl/fcntl.gemspec
+++ b/ext/fcntl/fcntl.gemspec
@@ -3,14 +3,14 @@
Gem::Specification.new do |spec|
spec.name = "fcntl"
- spec.version = "1.0.0"
+ spec.version = "1.0.1"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
spec.summary = "Loads constants defined in the OS fcntl.h C header file"
spec.description = "Loads constants defined in the OS fcntl.h C header file"
spec.homepage = "https://github.com/ruby/fcntl"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.files = ["ext/fcntl/extconf.rb", "ext/fcntl/fcntl.c"]
spec.bindir = "exe"
@@ -18,8 +18,4 @@ Gem::Specification.new do |spec|
spec.require_paths = ["lib"]
spec.extensions = "ext/fcntl/extconf.rb"
spec.required_ruby_version = ">= 2.3.0"
-
- spec.add_development_dependency "bundler", "~> 1.14"
- spec.add_development_dependency "rake", "~> 12"
- spec.add_development_dependency "rake-compiler"
end
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c
index 2044c836ea..3679e5c9ad 100644
--- a/ext/fiddle/closure.c
+++ b/ext/fiddle/closure.c
@@ -13,6 +13,10 @@ typedef struct {
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
@@ -126,6 +130,10 @@ with_gvl_callback(void *ptr)
rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)x->args[i]));
break;
#endif
+ case TYPE_CONST_STRING:
+ rb_ary_push(params,
+ rb_str_new_cstr(*((const char **)(x->args[i]))));
+ break;
default:
rb_raise(rb_eRuntimeError, "closure args: %d", type);
}
@@ -171,6 +179,10 @@ with_gvl_callback(void *ptr)
*(unsigned LONG_LONG *)x->resp = NUM2ULL(ret);
break;
#endif
+ case TYPE_CONST_STRING:
+ /* Dangerous. Callback must keep reference of the String. */
+ *((const char **)(x->resp)) = StringValueCStr(ret);
+ break;
default:
rb_raise(rb_eRuntimeError, "closure retval: %d", type);
}
@@ -217,6 +229,7 @@ initialize(int rbargc, VALUE argv[], VALUE self)
{
VALUE ret;
VALUE args;
+ VALUE normalized_args;
VALUE abi;
fiddle_closure * cl;
ffi_cif * cif;
@@ -235,21 +248,26 @@ initialize(int rbargc, VALUE argv[], VALUE self)
cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
+ normalized_args = rb_ary_new_capa(argc);
for (i = 0; i < argc; i++) {
- int type = NUM2INT(RARRAY_AREF(args, i));
- cl->argv[i] = INT2FFI_TYPE(type);
+ VALUE arg = rb_fiddle_type_ensure(RARRAY_AREF(args, i));
+ rb_ary_push(normalized_args, arg);
+ cl->argv[i] = rb_fiddle_int_to_ffi_type(NUM2INT(arg));
}
cl->argv[argc] = NULL;
+ ret = rb_fiddle_type_ensure(ret);
rb_iv_set(self, "@ctype", ret);
- rb_iv_set(self, "@args", args);
+ rb_iv_set(self, "@args", normalized_args);
cif = &cl->cif;
pcl = cl->pcl;
- result = ffi_prep_cif(cif, NUM2INT(abi), argc,
- INT2FFI_TYPE(NUM2INT(ret)),
- cl->argv);
+ result = ffi_prep_cif(cif,
+ NUM2INT(abi),
+ argc,
+ rb_fiddle_int_to_ffi_type(NUM2INT(ret)),
+ cl->argv);
if (FFI_OK != result)
rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c
index d40ddc1f38..6e0ce36378 100644
--- a/ext/fiddle/conversions.c
+++ b/ext/fiddle/conversions.c
@@ -1,7 +1,159 @@
#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;
+ RUBY_CONST_ID(void_id, "void");
+ RUBY_CONST_ID(voidp_id, "voidp");
+ RUBY_CONST_ID(char_id, "char");
+ RUBY_CONST_ID(short_id, "short");
+ RUBY_CONST_ID(int_id, "int");
+ RUBY_CONST_ID(long_id, "long");
+#ifdef TYPE_LONG_LONG
+ RUBY_CONST_ID(long_long_id, "long_long");
+#endif
+#ifdef TYPE_INT8_T
+ RUBY_CONST_ID(int8_t_id, "int8_t");
+#endif
+#ifdef TYPE_INT16_T
+ RUBY_CONST_ID(int16_t_id, "int16_t");
+#endif
+#ifdef TYPE_INT32_T
+ RUBY_CONST_ID(int32_t_id, "int32_t");
+#endif
+#ifdef TYPE_INT64_T
+ RUBY_CONST_ID(int64_t_id, "int64_t");
+#endif
+ RUBY_CONST_ID(float_id, "float");
+ RUBY_CONST_ID(double_id, "double");
+ RUBY_CONST_ID(variadic_id, "variadic");
+ RUBY_CONST_ID(const_string_id, "const_string");
+ RUBY_CONST_ID(size_t_id, "size_t");
+ RUBY_CONST_ID(ssize_t_id, "ssize_t");
+ RUBY_CONST_ID(ptrdiff_t_id, "ptrdiff_t");
+ RUBY_CONST_ID(intptr_t_id, "intptr_t");
+ RUBY_CONST_ID(uintptr_t_id, "uintptr_t");
+ if (type_id == void_id) {
+ return INT2NUM(TYPE_VOID);
+ }
+ else if (type_id == voidp_id) {
+ return INT2NUM(TYPE_VOIDP);
+ }
+ else if (type_id == char_id) {
+ return INT2NUM(TYPE_CHAR);
+ }
+ else if (type_id == short_id) {
+ return INT2NUM(TYPE_SHORT);
+ }
+ else if (type_id == int_id) {
+ return INT2NUM(TYPE_INT);
+ }
+ else if (type_id == long_id) {
+ return INT2NUM(TYPE_LONG);
+ }
+#ifdef TYPE_LONG_LONG
+ else if (type_id == long_long_id) {
+ return INT2NUM(TYPE_LONG_LONG);
+ }
+#endif
+#ifdef TYPE_INT8_T
+ else if (type_id == int8_t_id) {
+ return INT2NUM(TYPE_INT8_T);
+ }
+#endif
+#ifdef TYPE_INT16_T
+ else if (type_id == int16_t_id) {
+ return INT2NUM(TYPE_INT16_T);
+ }
+#endif
+#ifdef TYPE_INT32_T
+ else if (type_id == int32_t_id) {
+ return INT2NUM(TYPE_INT32_T);
+ }
+#endif
+#ifdef TYPE_INT64_T
+ else if (type_id == int64_t_id) {
+ return INT2NUM(TYPE_INT64_T);
+ }
+#endif
+ else if (type_id == float_id) {
+ return INT2NUM(TYPE_FLOAT);
+ }
+ else if (type_id == double_id) {
+ return INT2NUM(TYPE_DOUBLE);
+ }
+ else if (type_id == variadic_id) {
+ return INT2NUM(TYPE_VARIADIC);
+ }
+ else if (type_id == const_string_id) {
+ return INT2NUM(TYPE_CONST_STRING);
+ }
+ else if (type_id == size_t_id) {
+ return INT2NUM(TYPE_SIZE_T);
+ }
+ else if (type_id == ssize_t_id) {
+ return INT2NUM(TYPE_SSIZE_T);
+ }
+ else if (type_id == ptrdiff_t_id) {
+ return INT2NUM(TYPE_PTRDIFF_T);
+ }
+ else if (type_id == intptr_t_id) {
+ return INT2NUM(TYPE_INTPTR_T);
+ }
+ else if (type_id == uintptr_t_id) {
+ return INT2NUM(TYPE_UINTPTR_T);
+ }
+ else {
+ type = original_type;
+ }
+ }
+
+ return rb_to_int(type);
+}
+
ffi_type *
-int_to_ffi_type(int type)
+rb_fiddle_int_to_ffi_type(int type)
{
int signed_p = 1;
@@ -33,66 +185,90 @@ int_to_ffi_type(int type)
return &ffi_type_float;
case TYPE_DOUBLE:
return &ffi_type_double;
+ case TYPE_CONST_STRING:
+ return &ffi_type_pointer;
default:
rb_raise(rb_eRuntimeError, "unknown type %d", type);
}
return &ffi_type_pointer;
}
+ffi_type *
+int_to_ffi_type(int type)
+{
+ return rb_fiddle_int_to_ffi_type(type);
+}
+
void
-value_to_generic(int type, VALUE src, fiddle_generic * dst)
+rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst)
{
switch (type) {
case TYPE_VOID:
break;
case TYPE_VOIDP:
- dst->pointer = NUM2PTR(rb_Integer(src));
+ dst->pointer = NUM2PTR(rb_Integer(*src));
break;
case TYPE_CHAR:
- dst->schar = (signed char)NUM2INT(src);
+ dst->schar = (signed char)NUM2INT(*src);
break;
case -TYPE_CHAR:
- dst->uchar = (unsigned char)NUM2UINT(src);
+ dst->uchar = (unsigned char)NUM2UINT(*src);
break;
case TYPE_SHORT:
- dst->sshort = (unsigned short)NUM2INT(src);
+ dst->sshort = (unsigned short)NUM2INT(*src);
break;
case -TYPE_SHORT:
- dst->sshort = (signed short)NUM2UINT(src);
+ dst->sshort = (signed short)NUM2UINT(*src);
break;
case TYPE_INT:
- dst->sint = NUM2INT(src);
+ dst->sint = NUM2INT(*src);
break;
case -TYPE_INT:
- dst->uint = NUM2UINT(src);
+ dst->uint = NUM2UINT(*src);
break;
case TYPE_LONG:
- dst->slong = NUM2LONG(src);
+ dst->slong = NUM2LONG(*src);
break;
case -TYPE_LONG:
- dst->ulong = NUM2ULONG(src);
+ dst->ulong = NUM2ULONG(*src);
break;
#if HAVE_LONG_LONG
case TYPE_LONG_LONG:
- dst->slong_long = NUM2LL(src);
+ dst->slong_long = NUM2LL(*src);
break;
case -TYPE_LONG_LONG:
- dst->ulong_long = NUM2ULL(src);
+ dst->ulong_long = NUM2ULL(*src);
break;
#endif
case TYPE_FLOAT:
- dst->ffloat = (float)NUM2DBL(src);
+ dst->ffloat = (float)NUM2DBL(*src);
break;
case TYPE_DOUBLE:
- dst->ddouble = NUM2DBL(src);
+ dst->ddouble = NUM2DBL(*src);
+ break;
+ case TYPE_CONST_STRING:
+ if (NIL_P(*src)) {
+ dst->pointer = NULL;
+ }
+ else {
+ dst->pointer = rb_string_value_cstr(src);
+ }
break;
default:
rb_raise(rb_eRuntimeError, "unknown type %d", type);
}
}
+void
+value_to_generic(int type, VALUE src, fiddle_generic *dst)
+{
+ /* src isn't safe from GC when type is TYPE_CONST_STRING and src
+ * isn't String. */
+ rb_fiddle_value_to_generic(type, &src, dst);
+}
+
VALUE
-generic_to_value(VALUE rettype, fiddle_generic retval)
+rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval)
{
int type = NUM2INT(rettype);
VALUE cPointer;
@@ -131,6 +307,13 @@ generic_to_value(VALUE rettype, fiddle_generic retval)
return rb_float_new(retval.ffloat);
case TYPE_DOUBLE:
return rb_float_new(retval.ddouble);
+ case TYPE_CONST_STRING:
+ if (retval.pointer) {
+ return rb_str_new_cstr(retval.pointer);
+ }
+ else {
+ return Qnil;
+ }
default:
rb_raise(rb_eRuntimeError, "unknown type %d", type);
}
@@ -138,4 +321,10 @@ generic_to_value(VALUE rettype, fiddle_generic retval)
UNREACHABLE;
}
+VALUE
+generic_to_value(VALUE rettype, fiddle_generic retval)
+{
+ return rb_fiddle_generic_to_value(rettype, retval);
+}
+
/* vim: set noet sw=4 sts=4 */
diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h
index cbc610bad2..c7c12a9234 100644
--- a/ext/fiddle/conversions.h
+++ b/ext/fiddle/conversions.h
@@ -24,13 +24,22 @@ typedef union
void * pointer; /* ffi_type_pointer */
} fiddle_generic;
+VALUE rb_fiddle_type_ensure(VALUE type);
+ffi_type * rb_fiddle_int_to_ffi_type(int type);
+void rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst);
+VALUE rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval);
+
+/* Deprecated. Use rb_fiddle_*() version. */
ffi_type * int_to_ffi_type(int type);
-void value_to_generic(int type, VALUE src, fiddle_generic * dst);
+void value_to_generic(int type, VALUE src, fiddle_generic *dst);
VALUE generic_to_value(VALUE rettype, fiddle_generic retval);
-#define VALUE2GENERIC(_type, _src, _dst) value_to_generic((_type), (_src), (_dst))
-#define INT2FFI_TYPE(_type) int_to_ffi_type(_type)
-#define GENERIC2VALUE(_type, _retval) generic_to_value((_type), (_retval))
+#define VALUE2GENERIC(_type, _src, _dst) \
+ rb_fiddle_value_to_generic((_type), &(_src), (_dst))
+#define INT2FFI_TYPE(_type) \
+ rb_fiddle_int_to_ffi_type(_type)
+#define GENERIC2VALUE(_type, _retval) \
+ rb_fiddle_generic_to_value((_type), (_retval))
#if SIZEOF_VOIDP == SIZEOF_LONG
# define PTR2NUM(x) (LONG2NUM((long)(x)))
diff --git a/ext/fiddle/depend b/ext/fiddle/depend
index 5ed745fa0f..6afc09dd67 100644
--- a/ext/fiddle/depend
+++ b/ext/fiddle/depend
@@ -57,8 +57,157 @@ 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/gcc_version_since.h
+closure.o: $(hdrdir)/ruby/backward/2/inttypes.h
+closure.o: $(hdrdir)/ruby/backward/2/limits.h
+closure.o: $(hdrdir)/ruby/backward/2/long_long.h
+closure.o: $(hdrdir)/ruby/backward/2/stdalign.h
+closure.o: $(hdrdir)/ruby/backward/2/stdarg.h
closure.o: $(hdrdir)/ruby/defines.h
closure.o: $(hdrdir)/ruby/intern.h
+closure.o: $(hdrdir)/ruby/internal/anyargs.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+closure.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+closure.o: $(hdrdir)/ruby/internal/assume.h
+closure.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+closure.o: $(hdrdir)/ruby/internal/attr/artificial.h
+closure.o: $(hdrdir)/ruby/internal/attr/cold.h
+closure.o: $(hdrdir)/ruby/internal/attr/const.h
+closure.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+closure.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+closure.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+closure.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+closure.o: $(hdrdir)/ruby/internal/attr/error.h
+closure.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+closure.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+closure.o: $(hdrdir)/ruby/internal/attr/format.h
+closure.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+closure.o: $(hdrdir)/ruby/internal/attr/noalias.h
+closure.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+closure.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+closure.o: $(hdrdir)/ruby/internal/attr/noinline.h
+closure.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+closure.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+closure.o: $(hdrdir)/ruby/internal/attr/pure.h
+closure.o: $(hdrdir)/ruby/internal/attr/restrict.h
+closure.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+closure.o: $(hdrdir)/ruby/internal/attr/warning.h
+closure.o: $(hdrdir)/ruby/internal/attr/weakref.h
+closure.o: $(hdrdir)/ruby/internal/cast.h
+closure.o: $(hdrdir)/ruby/internal/compiler_is.h
+closure.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+closure.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+closure.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+closure.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+closure.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+closure.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+closure.o: $(hdrdir)/ruby/internal/compiler_since.h
+closure.o: $(hdrdir)/ruby/internal/config.h
+closure.o: $(hdrdir)/ruby/internal/constant_p.h
+closure.o: $(hdrdir)/ruby/internal/core.h
+closure.o: $(hdrdir)/ruby/internal/core/rarray.h
+closure.o: $(hdrdir)/ruby/internal/core/rbasic.h
+closure.o: $(hdrdir)/ruby/internal/core/rbignum.h
+closure.o: $(hdrdir)/ruby/internal/core/rclass.h
+closure.o: $(hdrdir)/ruby/internal/core/rdata.h
+closure.o: $(hdrdir)/ruby/internal/core/rfile.h
+closure.o: $(hdrdir)/ruby/internal/core/rhash.h
+closure.o: $(hdrdir)/ruby/internal/core/robject.h
+closure.o: $(hdrdir)/ruby/internal/core/rregexp.h
+closure.o: $(hdrdir)/ruby/internal/core/rstring.h
+closure.o: $(hdrdir)/ruby/internal/core/rstruct.h
+closure.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+closure.o: $(hdrdir)/ruby/internal/ctype.h
+closure.o: $(hdrdir)/ruby/internal/dllexport.h
+closure.o: $(hdrdir)/ruby/internal/dosish.h
+closure.o: $(hdrdir)/ruby/internal/error.h
+closure.o: $(hdrdir)/ruby/internal/eval.h
+closure.o: $(hdrdir)/ruby/internal/event.h
+closure.o: $(hdrdir)/ruby/internal/fl_type.h
+closure.o: $(hdrdir)/ruby/internal/gc.h
+closure.o: $(hdrdir)/ruby/internal/glob.h
+closure.o: $(hdrdir)/ruby/internal/globals.h
+closure.o: $(hdrdir)/ruby/internal/has/attribute.h
+closure.o: $(hdrdir)/ruby/internal/has/builtin.h
+closure.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+closure.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+closure.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+closure.o: $(hdrdir)/ruby/internal/has/extension.h
+closure.o: $(hdrdir)/ruby/internal/has/feature.h
+closure.o: $(hdrdir)/ruby/internal/has/warning.h
+closure.o: $(hdrdir)/ruby/internal/intern/array.h
+closure.o: $(hdrdir)/ruby/internal/intern/bignum.h
+closure.o: $(hdrdir)/ruby/internal/intern/class.h
+closure.o: $(hdrdir)/ruby/internal/intern/compar.h
+closure.o: $(hdrdir)/ruby/internal/intern/complex.h
+closure.o: $(hdrdir)/ruby/internal/intern/cont.h
+closure.o: $(hdrdir)/ruby/internal/intern/dir.h
+closure.o: $(hdrdir)/ruby/internal/intern/enum.h
+closure.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+closure.o: $(hdrdir)/ruby/internal/intern/error.h
+closure.o: $(hdrdir)/ruby/internal/intern/eval.h
+closure.o: $(hdrdir)/ruby/internal/intern/file.h
+closure.o: $(hdrdir)/ruby/internal/intern/gc.h
+closure.o: $(hdrdir)/ruby/internal/intern/hash.h
+closure.o: $(hdrdir)/ruby/internal/intern/io.h
+closure.o: $(hdrdir)/ruby/internal/intern/load.h
+closure.o: $(hdrdir)/ruby/internal/intern/marshal.h
+closure.o: $(hdrdir)/ruby/internal/intern/numeric.h
+closure.o: $(hdrdir)/ruby/internal/intern/object.h
+closure.o: $(hdrdir)/ruby/internal/intern/parse.h
+closure.o: $(hdrdir)/ruby/internal/intern/proc.h
+closure.o: $(hdrdir)/ruby/internal/intern/process.h
+closure.o: $(hdrdir)/ruby/internal/intern/random.h
+closure.o: $(hdrdir)/ruby/internal/intern/range.h
+closure.o: $(hdrdir)/ruby/internal/intern/rational.h
+closure.o: $(hdrdir)/ruby/internal/intern/re.h
+closure.o: $(hdrdir)/ruby/internal/intern/ruby.h
+closure.o: $(hdrdir)/ruby/internal/intern/select.h
+closure.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+closure.o: $(hdrdir)/ruby/internal/intern/signal.h
+closure.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+closure.o: $(hdrdir)/ruby/internal/intern/string.h
+closure.o: $(hdrdir)/ruby/internal/intern/struct.h
+closure.o: $(hdrdir)/ruby/internal/intern/thread.h
+closure.o: $(hdrdir)/ruby/internal/intern/time.h
+closure.o: $(hdrdir)/ruby/internal/intern/variable.h
+closure.o: $(hdrdir)/ruby/internal/intern/vm.h
+closure.o: $(hdrdir)/ruby/internal/interpreter.h
+closure.o: $(hdrdir)/ruby/internal/iterator.h
+closure.o: $(hdrdir)/ruby/internal/memory.h
+closure.o: $(hdrdir)/ruby/internal/method.h
+closure.o: $(hdrdir)/ruby/internal/module.h
+closure.o: $(hdrdir)/ruby/internal/newobj.h
+closure.o: $(hdrdir)/ruby/internal/rgengc.h
+closure.o: $(hdrdir)/ruby/internal/scan_args.h
+closure.o: $(hdrdir)/ruby/internal/special_consts.h
+closure.o: $(hdrdir)/ruby/internal/static_assert.h
+closure.o: $(hdrdir)/ruby/internal/stdalign.h
+closure.o: $(hdrdir)/ruby/internal/stdbool.h
+closure.o: $(hdrdir)/ruby/internal/symbol.h
+closure.o: $(hdrdir)/ruby/internal/token_paste.h
+closure.o: $(hdrdir)/ruby/internal/value.h
+closure.o: $(hdrdir)/ruby/internal/value_type.h
+closure.o: $(hdrdir)/ruby/internal/variable.h
+closure.o: $(hdrdir)/ruby/internal/warning_push.h
+closure.o: $(hdrdir)/ruby/internal/xmalloc.h
closure.o: $(hdrdir)/ruby/missing.h
closure.o: $(hdrdir)/ruby/ruby.h
closure.o: $(hdrdir)/ruby/st.h
@@ -74,8 +223,157 @@ 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/gcc_version_since.h
+conversions.o: $(hdrdir)/ruby/backward/2/inttypes.h
+conversions.o: $(hdrdir)/ruby/backward/2/limits.h
+conversions.o: $(hdrdir)/ruby/backward/2/long_long.h
+conversions.o: $(hdrdir)/ruby/backward/2/stdalign.h
+conversions.o: $(hdrdir)/ruby/backward/2/stdarg.h
conversions.o: $(hdrdir)/ruby/defines.h
conversions.o: $(hdrdir)/ruby/intern.h
+conversions.o: $(hdrdir)/ruby/internal/anyargs.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+conversions.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+conversions.o: $(hdrdir)/ruby/internal/assume.h
+conversions.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+conversions.o: $(hdrdir)/ruby/internal/attr/artificial.h
+conversions.o: $(hdrdir)/ruby/internal/attr/cold.h
+conversions.o: $(hdrdir)/ruby/internal/attr/const.h
+conversions.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+conversions.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+conversions.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+conversions.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+conversions.o: $(hdrdir)/ruby/internal/attr/error.h
+conversions.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+conversions.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+conversions.o: $(hdrdir)/ruby/internal/attr/format.h
+conversions.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+conversions.o: $(hdrdir)/ruby/internal/attr/noalias.h
+conversions.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+conversions.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+conversions.o: $(hdrdir)/ruby/internal/attr/noinline.h
+conversions.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+conversions.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+conversions.o: $(hdrdir)/ruby/internal/attr/pure.h
+conversions.o: $(hdrdir)/ruby/internal/attr/restrict.h
+conversions.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+conversions.o: $(hdrdir)/ruby/internal/attr/warning.h
+conversions.o: $(hdrdir)/ruby/internal/attr/weakref.h
+conversions.o: $(hdrdir)/ruby/internal/cast.h
+conversions.o: $(hdrdir)/ruby/internal/compiler_is.h
+conversions.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+conversions.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+conversions.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+conversions.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+conversions.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+conversions.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+conversions.o: $(hdrdir)/ruby/internal/compiler_since.h
+conversions.o: $(hdrdir)/ruby/internal/config.h
+conversions.o: $(hdrdir)/ruby/internal/constant_p.h
+conversions.o: $(hdrdir)/ruby/internal/core.h
+conversions.o: $(hdrdir)/ruby/internal/core/rarray.h
+conversions.o: $(hdrdir)/ruby/internal/core/rbasic.h
+conversions.o: $(hdrdir)/ruby/internal/core/rbignum.h
+conversions.o: $(hdrdir)/ruby/internal/core/rclass.h
+conversions.o: $(hdrdir)/ruby/internal/core/rdata.h
+conversions.o: $(hdrdir)/ruby/internal/core/rfile.h
+conversions.o: $(hdrdir)/ruby/internal/core/rhash.h
+conversions.o: $(hdrdir)/ruby/internal/core/robject.h
+conversions.o: $(hdrdir)/ruby/internal/core/rregexp.h
+conversions.o: $(hdrdir)/ruby/internal/core/rstring.h
+conversions.o: $(hdrdir)/ruby/internal/core/rstruct.h
+conversions.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+conversions.o: $(hdrdir)/ruby/internal/ctype.h
+conversions.o: $(hdrdir)/ruby/internal/dllexport.h
+conversions.o: $(hdrdir)/ruby/internal/dosish.h
+conversions.o: $(hdrdir)/ruby/internal/error.h
+conversions.o: $(hdrdir)/ruby/internal/eval.h
+conversions.o: $(hdrdir)/ruby/internal/event.h
+conversions.o: $(hdrdir)/ruby/internal/fl_type.h
+conversions.o: $(hdrdir)/ruby/internal/gc.h
+conversions.o: $(hdrdir)/ruby/internal/glob.h
+conversions.o: $(hdrdir)/ruby/internal/globals.h
+conversions.o: $(hdrdir)/ruby/internal/has/attribute.h
+conversions.o: $(hdrdir)/ruby/internal/has/builtin.h
+conversions.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+conversions.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+conversions.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+conversions.o: $(hdrdir)/ruby/internal/has/extension.h
+conversions.o: $(hdrdir)/ruby/internal/has/feature.h
+conversions.o: $(hdrdir)/ruby/internal/has/warning.h
+conversions.o: $(hdrdir)/ruby/internal/intern/array.h
+conversions.o: $(hdrdir)/ruby/internal/intern/bignum.h
+conversions.o: $(hdrdir)/ruby/internal/intern/class.h
+conversions.o: $(hdrdir)/ruby/internal/intern/compar.h
+conversions.o: $(hdrdir)/ruby/internal/intern/complex.h
+conversions.o: $(hdrdir)/ruby/internal/intern/cont.h
+conversions.o: $(hdrdir)/ruby/internal/intern/dir.h
+conversions.o: $(hdrdir)/ruby/internal/intern/enum.h
+conversions.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+conversions.o: $(hdrdir)/ruby/internal/intern/error.h
+conversions.o: $(hdrdir)/ruby/internal/intern/eval.h
+conversions.o: $(hdrdir)/ruby/internal/intern/file.h
+conversions.o: $(hdrdir)/ruby/internal/intern/gc.h
+conversions.o: $(hdrdir)/ruby/internal/intern/hash.h
+conversions.o: $(hdrdir)/ruby/internal/intern/io.h
+conversions.o: $(hdrdir)/ruby/internal/intern/load.h
+conversions.o: $(hdrdir)/ruby/internal/intern/marshal.h
+conversions.o: $(hdrdir)/ruby/internal/intern/numeric.h
+conversions.o: $(hdrdir)/ruby/internal/intern/object.h
+conversions.o: $(hdrdir)/ruby/internal/intern/parse.h
+conversions.o: $(hdrdir)/ruby/internal/intern/proc.h
+conversions.o: $(hdrdir)/ruby/internal/intern/process.h
+conversions.o: $(hdrdir)/ruby/internal/intern/random.h
+conversions.o: $(hdrdir)/ruby/internal/intern/range.h
+conversions.o: $(hdrdir)/ruby/internal/intern/rational.h
+conversions.o: $(hdrdir)/ruby/internal/intern/re.h
+conversions.o: $(hdrdir)/ruby/internal/intern/ruby.h
+conversions.o: $(hdrdir)/ruby/internal/intern/select.h
+conversions.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+conversions.o: $(hdrdir)/ruby/internal/intern/signal.h
+conversions.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+conversions.o: $(hdrdir)/ruby/internal/intern/string.h
+conversions.o: $(hdrdir)/ruby/internal/intern/struct.h
+conversions.o: $(hdrdir)/ruby/internal/intern/thread.h
+conversions.o: $(hdrdir)/ruby/internal/intern/time.h
+conversions.o: $(hdrdir)/ruby/internal/intern/variable.h
+conversions.o: $(hdrdir)/ruby/internal/intern/vm.h
+conversions.o: $(hdrdir)/ruby/internal/interpreter.h
+conversions.o: $(hdrdir)/ruby/internal/iterator.h
+conversions.o: $(hdrdir)/ruby/internal/memory.h
+conversions.o: $(hdrdir)/ruby/internal/method.h
+conversions.o: $(hdrdir)/ruby/internal/module.h
+conversions.o: $(hdrdir)/ruby/internal/newobj.h
+conversions.o: $(hdrdir)/ruby/internal/rgengc.h
+conversions.o: $(hdrdir)/ruby/internal/scan_args.h
+conversions.o: $(hdrdir)/ruby/internal/special_consts.h
+conversions.o: $(hdrdir)/ruby/internal/static_assert.h
+conversions.o: $(hdrdir)/ruby/internal/stdalign.h
+conversions.o: $(hdrdir)/ruby/internal/stdbool.h
+conversions.o: $(hdrdir)/ruby/internal/symbol.h
+conversions.o: $(hdrdir)/ruby/internal/token_paste.h
+conversions.o: $(hdrdir)/ruby/internal/value.h
+conversions.o: $(hdrdir)/ruby/internal/value_type.h
+conversions.o: $(hdrdir)/ruby/internal/variable.h
+conversions.o: $(hdrdir)/ruby/internal/warning_push.h
+conversions.o: $(hdrdir)/ruby/internal/xmalloc.h
conversions.o: $(hdrdir)/ruby/missing.h
conversions.o: $(hdrdir)/ruby/ruby.h
conversions.o: $(hdrdir)/ruby/st.h
@@ -90,8 +388,157 @@ 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/gcc_version_since.h
+fiddle.o: $(hdrdir)/ruby/backward/2/inttypes.h
+fiddle.o: $(hdrdir)/ruby/backward/2/limits.h
+fiddle.o: $(hdrdir)/ruby/backward/2/long_long.h
+fiddle.o: $(hdrdir)/ruby/backward/2/stdalign.h
+fiddle.o: $(hdrdir)/ruby/backward/2/stdarg.h
fiddle.o: $(hdrdir)/ruby/defines.h
fiddle.o: $(hdrdir)/ruby/intern.h
+fiddle.o: $(hdrdir)/ruby/internal/anyargs.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+fiddle.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+fiddle.o: $(hdrdir)/ruby/internal/assume.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/artificial.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/cold.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/const.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/error.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/format.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/noalias.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/noinline.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/pure.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/restrict.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/warning.h
+fiddle.o: $(hdrdir)/ruby/internal/attr/weakref.h
+fiddle.o: $(hdrdir)/ruby/internal/cast.h
+fiddle.o: $(hdrdir)/ruby/internal/compiler_is.h
+fiddle.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+fiddle.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+fiddle.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+fiddle.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+fiddle.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+fiddle.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+fiddle.o: $(hdrdir)/ruby/internal/compiler_since.h
+fiddle.o: $(hdrdir)/ruby/internal/config.h
+fiddle.o: $(hdrdir)/ruby/internal/constant_p.h
+fiddle.o: $(hdrdir)/ruby/internal/core.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rarray.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rbasic.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rbignum.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rclass.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rdata.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rfile.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rhash.h
+fiddle.o: $(hdrdir)/ruby/internal/core/robject.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rregexp.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rstring.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rstruct.h
+fiddle.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+fiddle.o: $(hdrdir)/ruby/internal/ctype.h
+fiddle.o: $(hdrdir)/ruby/internal/dllexport.h
+fiddle.o: $(hdrdir)/ruby/internal/dosish.h
+fiddle.o: $(hdrdir)/ruby/internal/error.h
+fiddle.o: $(hdrdir)/ruby/internal/eval.h
+fiddle.o: $(hdrdir)/ruby/internal/event.h
+fiddle.o: $(hdrdir)/ruby/internal/fl_type.h
+fiddle.o: $(hdrdir)/ruby/internal/gc.h
+fiddle.o: $(hdrdir)/ruby/internal/glob.h
+fiddle.o: $(hdrdir)/ruby/internal/globals.h
+fiddle.o: $(hdrdir)/ruby/internal/has/attribute.h
+fiddle.o: $(hdrdir)/ruby/internal/has/builtin.h
+fiddle.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+fiddle.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+fiddle.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+fiddle.o: $(hdrdir)/ruby/internal/has/extension.h
+fiddle.o: $(hdrdir)/ruby/internal/has/feature.h
+fiddle.o: $(hdrdir)/ruby/internal/has/warning.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/array.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/bignum.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/class.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/compar.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/complex.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/cont.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/dir.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/enum.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/error.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/eval.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/file.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/gc.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/hash.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/io.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/load.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/marshal.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/numeric.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/object.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/parse.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/proc.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/process.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/random.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/range.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/rational.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/re.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/ruby.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/select.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/signal.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/string.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/struct.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/thread.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/time.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/variable.h
+fiddle.o: $(hdrdir)/ruby/internal/intern/vm.h
+fiddle.o: $(hdrdir)/ruby/internal/interpreter.h
+fiddle.o: $(hdrdir)/ruby/internal/iterator.h
+fiddle.o: $(hdrdir)/ruby/internal/memory.h
+fiddle.o: $(hdrdir)/ruby/internal/method.h
+fiddle.o: $(hdrdir)/ruby/internal/module.h
+fiddle.o: $(hdrdir)/ruby/internal/newobj.h
+fiddle.o: $(hdrdir)/ruby/internal/rgengc.h
+fiddle.o: $(hdrdir)/ruby/internal/scan_args.h
+fiddle.o: $(hdrdir)/ruby/internal/special_consts.h
+fiddle.o: $(hdrdir)/ruby/internal/static_assert.h
+fiddle.o: $(hdrdir)/ruby/internal/stdalign.h
+fiddle.o: $(hdrdir)/ruby/internal/stdbool.h
+fiddle.o: $(hdrdir)/ruby/internal/symbol.h
+fiddle.o: $(hdrdir)/ruby/internal/token_paste.h
+fiddle.o: $(hdrdir)/ruby/internal/value.h
+fiddle.o: $(hdrdir)/ruby/internal/value_type.h
+fiddle.o: $(hdrdir)/ruby/internal/variable.h
+fiddle.o: $(hdrdir)/ruby/internal/warning_push.h
+fiddle.o: $(hdrdir)/ruby/internal/xmalloc.h
fiddle.o: $(hdrdir)/ruby/missing.h
fiddle.o: $(hdrdir)/ruby/ruby.h
fiddle.o: $(hdrdir)/ruby/st.h
@@ -106,8 +553,157 @@ 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/gcc_version_since.h
+function.o: $(hdrdir)/ruby/backward/2/inttypes.h
+function.o: $(hdrdir)/ruby/backward/2/limits.h
+function.o: $(hdrdir)/ruby/backward/2/long_long.h
+function.o: $(hdrdir)/ruby/backward/2/stdalign.h
+function.o: $(hdrdir)/ruby/backward/2/stdarg.h
function.o: $(hdrdir)/ruby/defines.h
function.o: $(hdrdir)/ruby/intern.h
+function.o: $(hdrdir)/ruby/internal/anyargs.h
+function.o: $(hdrdir)/ruby/internal/arithmetic.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+function.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+function.o: $(hdrdir)/ruby/internal/assume.h
+function.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+function.o: $(hdrdir)/ruby/internal/attr/artificial.h
+function.o: $(hdrdir)/ruby/internal/attr/cold.h
+function.o: $(hdrdir)/ruby/internal/attr/const.h
+function.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+function.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+function.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+function.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+function.o: $(hdrdir)/ruby/internal/attr/error.h
+function.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+function.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+function.o: $(hdrdir)/ruby/internal/attr/format.h
+function.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+function.o: $(hdrdir)/ruby/internal/attr/noalias.h
+function.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+function.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+function.o: $(hdrdir)/ruby/internal/attr/noinline.h
+function.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+function.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+function.o: $(hdrdir)/ruby/internal/attr/pure.h
+function.o: $(hdrdir)/ruby/internal/attr/restrict.h
+function.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+function.o: $(hdrdir)/ruby/internal/attr/warning.h
+function.o: $(hdrdir)/ruby/internal/attr/weakref.h
+function.o: $(hdrdir)/ruby/internal/cast.h
+function.o: $(hdrdir)/ruby/internal/compiler_is.h
+function.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+function.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+function.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+function.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+function.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+function.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+function.o: $(hdrdir)/ruby/internal/compiler_since.h
+function.o: $(hdrdir)/ruby/internal/config.h
+function.o: $(hdrdir)/ruby/internal/constant_p.h
+function.o: $(hdrdir)/ruby/internal/core.h
+function.o: $(hdrdir)/ruby/internal/core/rarray.h
+function.o: $(hdrdir)/ruby/internal/core/rbasic.h
+function.o: $(hdrdir)/ruby/internal/core/rbignum.h
+function.o: $(hdrdir)/ruby/internal/core/rclass.h
+function.o: $(hdrdir)/ruby/internal/core/rdata.h
+function.o: $(hdrdir)/ruby/internal/core/rfile.h
+function.o: $(hdrdir)/ruby/internal/core/rhash.h
+function.o: $(hdrdir)/ruby/internal/core/robject.h
+function.o: $(hdrdir)/ruby/internal/core/rregexp.h
+function.o: $(hdrdir)/ruby/internal/core/rstring.h
+function.o: $(hdrdir)/ruby/internal/core/rstruct.h
+function.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+function.o: $(hdrdir)/ruby/internal/ctype.h
+function.o: $(hdrdir)/ruby/internal/dllexport.h
+function.o: $(hdrdir)/ruby/internal/dosish.h
+function.o: $(hdrdir)/ruby/internal/error.h
+function.o: $(hdrdir)/ruby/internal/eval.h
+function.o: $(hdrdir)/ruby/internal/event.h
+function.o: $(hdrdir)/ruby/internal/fl_type.h
+function.o: $(hdrdir)/ruby/internal/gc.h
+function.o: $(hdrdir)/ruby/internal/glob.h
+function.o: $(hdrdir)/ruby/internal/globals.h
+function.o: $(hdrdir)/ruby/internal/has/attribute.h
+function.o: $(hdrdir)/ruby/internal/has/builtin.h
+function.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+function.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+function.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+function.o: $(hdrdir)/ruby/internal/has/extension.h
+function.o: $(hdrdir)/ruby/internal/has/feature.h
+function.o: $(hdrdir)/ruby/internal/has/warning.h
+function.o: $(hdrdir)/ruby/internal/intern/array.h
+function.o: $(hdrdir)/ruby/internal/intern/bignum.h
+function.o: $(hdrdir)/ruby/internal/intern/class.h
+function.o: $(hdrdir)/ruby/internal/intern/compar.h
+function.o: $(hdrdir)/ruby/internal/intern/complex.h
+function.o: $(hdrdir)/ruby/internal/intern/cont.h
+function.o: $(hdrdir)/ruby/internal/intern/dir.h
+function.o: $(hdrdir)/ruby/internal/intern/enum.h
+function.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+function.o: $(hdrdir)/ruby/internal/intern/error.h
+function.o: $(hdrdir)/ruby/internal/intern/eval.h
+function.o: $(hdrdir)/ruby/internal/intern/file.h
+function.o: $(hdrdir)/ruby/internal/intern/gc.h
+function.o: $(hdrdir)/ruby/internal/intern/hash.h
+function.o: $(hdrdir)/ruby/internal/intern/io.h
+function.o: $(hdrdir)/ruby/internal/intern/load.h
+function.o: $(hdrdir)/ruby/internal/intern/marshal.h
+function.o: $(hdrdir)/ruby/internal/intern/numeric.h
+function.o: $(hdrdir)/ruby/internal/intern/object.h
+function.o: $(hdrdir)/ruby/internal/intern/parse.h
+function.o: $(hdrdir)/ruby/internal/intern/proc.h
+function.o: $(hdrdir)/ruby/internal/intern/process.h
+function.o: $(hdrdir)/ruby/internal/intern/random.h
+function.o: $(hdrdir)/ruby/internal/intern/range.h
+function.o: $(hdrdir)/ruby/internal/intern/rational.h
+function.o: $(hdrdir)/ruby/internal/intern/re.h
+function.o: $(hdrdir)/ruby/internal/intern/ruby.h
+function.o: $(hdrdir)/ruby/internal/intern/select.h
+function.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+function.o: $(hdrdir)/ruby/internal/intern/signal.h
+function.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+function.o: $(hdrdir)/ruby/internal/intern/string.h
+function.o: $(hdrdir)/ruby/internal/intern/struct.h
+function.o: $(hdrdir)/ruby/internal/intern/thread.h
+function.o: $(hdrdir)/ruby/internal/intern/time.h
+function.o: $(hdrdir)/ruby/internal/intern/variable.h
+function.o: $(hdrdir)/ruby/internal/intern/vm.h
+function.o: $(hdrdir)/ruby/internal/interpreter.h
+function.o: $(hdrdir)/ruby/internal/iterator.h
+function.o: $(hdrdir)/ruby/internal/memory.h
+function.o: $(hdrdir)/ruby/internal/method.h
+function.o: $(hdrdir)/ruby/internal/module.h
+function.o: $(hdrdir)/ruby/internal/newobj.h
+function.o: $(hdrdir)/ruby/internal/rgengc.h
+function.o: $(hdrdir)/ruby/internal/scan_args.h
+function.o: $(hdrdir)/ruby/internal/special_consts.h
+function.o: $(hdrdir)/ruby/internal/static_assert.h
+function.o: $(hdrdir)/ruby/internal/stdalign.h
+function.o: $(hdrdir)/ruby/internal/stdbool.h
+function.o: $(hdrdir)/ruby/internal/symbol.h
+function.o: $(hdrdir)/ruby/internal/token_paste.h
+function.o: $(hdrdir)/ruby/internal/value.h
+function.o: $(hdrdir)/ruby/internal/value_type.h
+function.o: $(hdrdir)/ruby/internal/variable.h
+function.o: $(hdrdir)/ruby/internal/warning_push.h
+function.o: $(hdrdir)/ruby/internal/xmalloc.h
function.o: $(hdrdir)/ruby/missing.h
function.o: $(hdrdir)/ruby/ruby.h
function.o: $(hdrdir)/ruby/st.h
@@ -123,8 +719,157 @@ 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/gcc_version_since.h
+handle.o: $(hdrdir)/ruby/backward/2/inttypes.h
+handle.o: $(hdrdir)/ruby/backward/2/limits.h
+handle.o: $(hdrdir)/ruby/backward/2/long_long.h
+handle.o: $(hdrdir)/ruby/backward/2/stdalign.h
+handle.o: $(hdrdir)/ruby/backward/2/stdarg.h
handle.o: $(hdrdir)/ruby/defines.h
handle.o: $(hdrdir)/ruby/intern.h
+handle.o: $(hdrdir)/ruby/internal/anyargs.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+handle.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+handle.o: $(hdrdir)/ruby/internal/assume.h
+handle.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+handle.o: $(hdrdir)/ruby/internal/attr/artificial.h
+handle.o: $(hdrdir)/ruby/internal/attr/cold.h
+handle.o: $(hdrdir)/ruby/internal/attr/const.h
+handle.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+handle.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+handle.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+handle.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+handle.o: $(hdrdir)/ruby/internal/attr/error.h
+handle.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+handle.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+handle.o: $(hdrdir)/ruby/internal/attr/format.h
+handle.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+handle.o: $(hdrdir)/ruby/internal/attr/noalias.h
+handle.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+handle.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+handle.o: $(hdrdir)/ruby/internal/attr/noinline.h
+handle.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+handle.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+handle.o: $(hdrdir)/ruby/internal/attr/pure.h
+handle.o: $(hdrdir)/ruby/internal/attr/restrict.h
+handle.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+handle.o: $(hdrdir)/ruby/internal/attr/warning.h
+handle.o: $(hdrdir)/ruby/internal/attr/weakref.h
+handle.o: $(hdrdir)/ruby/internal/cast.h
+handle.o: $(hdrdir)/ruby/internal/compiler_is.h
+handle.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+handle.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+handle.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+handle.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+handle.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+handle.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+handle.o: $(hdrdir)/ruby/internal/compiler_since.h
+handle.o: $(hdrdir)/ruby/internal/config.h
+handle.o: $(hdrdir)/ruby/internal/constant_p.h
+handle.o: $(hdrdir)/ruby/internal/core.h
+handle.o: $(hdrdir)/ruby/internal/core/rarray.h
+handle.o: $(hdrdir)/ruby/internal/core/rbasic.h
+handle.o: $(hdrdir)/ruby/internal/core/rbignum.h
+handle.o: $(hdrdir)/ruby/internal/core/rclass.h
+handle.o: $(hdrdir)/ruby/internal/core/rdata.h
+handle.o: $(hdrdir)/ruby/internal/core/rfile.h
+handle.o: $(hdrdir)/ruby/internal/core/rhash.h
+handle.o: $(hdrdir)/ruby/internal/core/robject.h
+handle.o: $(hdrdir)/ruby/internal/core/rregexp.h
+handle.o: $(hdrdir)/ruby/internal/core/rstring.h
+handle.o: $(hdrdir)/ruby/internal/core/rstruct.h
+handle.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+handle.o: $(hdrdir)/ruby/internal/ctype.h
+handle.o: $(hdrdir)/ruby/internal/dllexport.h
+handle.o: $(hdrdir)/ruby/internal/dosish.h
+handle.o: $(hdrdir)/ruby/internal/error.h
+handle.o: $(hdrdir)/ruby/internal/eval.h
+handle.o: $(hdrdir)/ruby/internal/event.h
+handle.o: $(hdrdir)/ruby/internal/fl_type.h
+handle.o: $(hdrdir)/ruby/internal/gc.h
+handle.o: $(hdrdir)/ruby/internal/glob.h
+handle.o: $(hdrdir)/ruby/internal/globals.h
+handle.o: $(hdrdir)/ruby/internal/has/attribute.h
+handle.o: $(hdrdir)/ruby/internal/has/builtin.h
+handle.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+handle.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+handle.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+handle.o: $(hdrdir)/ruby/internal/has/extension.h
+handle.o: $(hdrdir)/ruby/internal/has/feature.h
+handle.o: $(hdrdir)/ruby/internal/has/warning.h
+handle.o: $(hdrdir)/ruby/internal/intern/array.h
+handle.o: $(hdrdir)/ruby/internal/intern/bignum.h
+handle.o: $(hdrdir)/ruby/internal/intern/class.h
+handle.o: $(hdrdir)/ruby/internal/intern/compar.h
+handle.o: $(hdrdir)/ruby/internal/intern/complex.h
+handle.o: $(hdrdir)/ruby/internal/intern/cont.h
+handle.o: $(hdrdir)/ruby/internal/intern/dir.h
+handle.o: $(hdrdir)/ruby/internal/intern/enum.h
+handle.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+handle.o: $(hdrdir)/ruby/internal/intern/error.h
+handle.o: $(hdrdir)/ruby/internal/intern/eval.h
+handle.o: $(hdrdir)/ruby/internal/intern/file.h
+handle.o: $(hdrdir)/ruby/internal/intern/gc.h
+handle.o: $(hdrdir)/ruby/internal/intern/hash.h
+handle.o: $(hdrdir)/ruby/internal/intern/io.h
+handle.o: $(hdrdir)/ruby/internal/intern/load.h
+handle.o: $(hdrdir)/ruby/internal/intern/marshal.h
+handle.o: $(hdrdir)/ruby/internal/intern/numeric.h
+handle.o: $(hdrdir)/ruby/internal/intern/object.h
+handle.o: $(hdrdir)/ruby/internal/intern/parse.h
+handle.o: $(hdrdir)/ruby/internal/intern/proc.h
+handle.o: $(hdrdir)/ruby/internal/intern/process.h
+handle.o: $(hdrdir)/ruby/internal/intern/random.h
+handle.o: $(hdrdir)/ruby/internal/intern/range.h
+handle.o: $(hdrdir)/ruby/internal/intern/rational.h
+handle.o: $(hdrdir)/ruby/internal/intern/re.h
+handle.o: $(hdrdir)/ruby/internal/intern/ruby.h
+handle.o: $(hdrdir)/ruby/internal/intern/select.h
+handle.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+handle.o: $(hdrdir)/ruby/internal/intern/signal.h
+handle.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+handle.o: $(hdrdir)/ruby/internal/intern/string.h
+handle.o: $(hdrdir)/ruby/internal/intern/struct.h
+handle.o: $(hdrdir)/ruby/internal/intern/thread.h
+handle.o: $(hdrdir)/ruby/internal/intern/time.h
+handle.o: $(hdrdir)/ruby/internal/intern/variable.h
+handle.o: $(hdrdir)/ruby/internal/intern/vm.h
+handle.o: $(hdrdir)/ruby/internal/interpreter.h
+handle.o: $(hdrdir)/ruby/internal/iterator.h
+handle.o: $(hdrdir)/ruby/internal/memory.h
+handle.o: $(hdrdir)/ruby/internal/method.h
+handle.o: $(hdrdir)/ruby/internal/module.h
+handle.o: $(hdrdir)/ruby/internal/newobj.h
+handle.o: $(hdrdir)/ruby/internal/rgengc.h
+handle.o: $(hdrdir)/ruby/internal/scan_args.h
+handle.o: $(hdrdir)/ruby/internal/special_consts.h
+handle.o: $(hdrdir)/ruby/internal/static_assert.h
+handle.o: $(hdrdir)/ruby/internal/stdalign.h
+handle.o: $(hdrdir)/ruby/internal/stdbool.h
+handle.o: $(hdrdir)/ruby/internal/symbol.h
+handle.o: $(hdrdir)/ruby/internal/token_paste.h
+handle.o: $(hdrdir)/ruby/internal/value.h
+handle.o: $(hdrdir)/ruby/internal/value_type.h
+handle.o: $(hdrdir)/ruby/internal/variable.h
+handle.o: $(hdrdir)/ruby/internal/warning_push.h
+handle.o: $(hdrdir)/ruby/internal/xmalloc.h
handle.o: $(hdrdir)/ruby/missing.h
handle.o: $(hdrdir)/ruby/ruby.h
handle.o: $(hdrdir)/ruby/st.h
@@ -134,15 +879,496 @@ 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/gcc_version_since.h
+memory_view.o: $(hdrdir)/ruby/backward/2/inttypes.h
+memory_view.o: $(hdrdir)/ruby/backward/2/limits.h
+memory_view.o: $(hdrdir)/ruby/backward/2/long_long.h
+memory_view.o: $(hdrdir)/ruby/backward/2/stdalign.h
+memory_view.o: $(hdrdir)/ruby/backward/2/stdarg.h
+memory_view.o: $(hdrdir)/ruby/defines.h
+memory_view.o: $(hdrdir)/ruby/intern.h
+memory_view.o: $(hdrdir)/ruby/internal/anyargs.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+memory_view.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+memory_view.o: $(hdrdir)/ruby/internal/assume.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/artificial.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/cold.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/const.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/error.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/format.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noalias.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noinline.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/pure.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/restrict.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/warning.h
+memory_view.o: $(hdrdir)/ruby/internal/attr/weakref.h
+memory_view.o: $(hdrdir)/ruby/internal/cast.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+memory_view.o: $(hdrdir)/ruby/internal/compiler_since.h
+memory_view.o: $(hdrdir)/ruby/internal/config.h
+memory_view.o: $(hdrdir)/ruby/internal/constant_p.h
+memory_view.o: $(hdrdir)/ruby/internal/core.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rarray.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rbasic.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rbignum.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rclass.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rdata.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rfile.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rhash.h
+memory_view.o: $(hdrdir)/ruby/internal/core/robject.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rregexp.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rstring.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rstruct.h
+memory_view.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+memory_view.o: $(hdrdir)/ruby/internal/ctype.h
+memory_view.o: $(hdrdir)/ruby/internal/dllexport.h
+memory_view.o: $(hdrdir)/ruby/internal/dosish.h
+memory_view.o: $(hdrdir)/ruby/internal/error.h
+memory_view.o: $(hdrdir)/ruby/internal/eval.h
+memory_view.o: $(hdrdir)/ruby/internal/event.h
+memory_view.o: $(hdrdir)/ruby/internal/fl_type.h
+memory_view.o: $(hdrdir)/ruby/internal/gc.h
+memory_view.o: $(hdrdir)/ruby/internal/glob.h
+memory_view.o: $(hdrdir)/ruby/internal/globals.h
+memory_view.o: $(hdrdir)/ruby/internal/has/attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/builtin.h
+memory_view.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+memory_view.o: $(hdrdir)/ruby/internal/has/extension.h
+memory_view.o: $(hdrdir)/ruby/internal/has/feature.h
+memory_view.o: $(hdrdir)/ruby/internal/has/warning.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/array.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/bignum.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/class.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/compar.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/complex.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/cont.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/dir.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/enum.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/error.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/eval.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/file.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/gc.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/hash.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/io.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/load.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/marshal.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/numeric.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/object.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/parse.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/proc.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/process.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/random.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/range.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/rational.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/re.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/ruby.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/select.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/signal.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/string.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/struct.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/thread.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/time.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/variable.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/vm.h
+memory_view.o: $(hdrdir)/ruby/internal/interpreter.h
+memory_view.o: $(hdrdir)/ruby/internal/iterator.h
+memory_view.o: $(hdrdir)/ruby/internal/memory.h
+memory_view.o: $(hdrdir)/ruby/internal/method.h
+memory_view.o: $(hdrdir)/ruby/internal/module.h
+memory_view.o: $(hdrdir)/ruby/internal/newobj.h
+memory_view.o: $(hdrdir)/ruby/internal/rgengc.h
+memory_view.o: $(hdrdir)/ruby/internal/scan_args.h
+memory_view.o: $(hdrdir)/ruby/internal/special_consts.h
+memory_view.o: $(hdrdir)/ruby/internal/static_assert.h
+memory_view.o: $(hdrdir)/ruby/internal/stdalign.h
+memory_view.o: $(hdrdir)/ruby/internal/stdbool.h
+memory_view.o: $(hdrdir)/ruby/internal/symbol.h
+memory_view.o: $(hdrdir)/ruby/internal/token_paste.h
+memory_view.o: $(hdrdir)/ruby/internal/value.h
+memory_view.o: $(hdrdir)/ruby/internal/value_type.h
+memory_view.o: $(hdrdir)/ruby/internal/variable.h
+memory_view.o: $(hdrdir)/ruby/internal/warning_push.h
+memory_view.o: $(hdrdir)/ruby/internal/xmalloc.h
+memory_view.o: $(hdrdir)/ruby/memory_view.h
+memory_view.o: $(hdrdir)/ruby/missing.h
+memory_view.o: $(hdrdir)/ruby/ruby.h
+memory_view.o: $(hdrdir)/ruby/st.h
+memory_view.o: $(hdrdir)/ruby/subst.h
+memory_view.o: 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/gcc_version_since.h
+pinned.o: $(hdrdir)/ruby/backward/2/inttypes.h
+pinned.o: $(hdrdir)/ruby/backward/2/limits.h
+pinned.o: $(hdrdir)/ruby/backward/2/long_long.h
+pinned.o: $(hdrdir)/ruby/backward/2/stdalign.h
+pinned.o: $(hdrdir)/ruby/backward/2/stdarg.h
+pinned.o: $(hdrdir)/ruby/defines.h
+pinned.o: $(hdrdir)/ruby/intern.h
+pinned.o: $(hdrdir)/ruby/internal/anyargs.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+pinned.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+pinned.o: $(hdrdir)/ruby/internal/assume.h
+pinned.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+pinned.o: $(hdrdir)/ruby/internal/attr/artificial.h
+pinned.o: $(hdrdir)/ruby/internal/attr/cold.h
+pinned.o: $(hdrdir)/ruby/internal/attr/const.h
+pinned.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+pinned.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+pinned.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+pinned.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+pinned.o: $(hdrdir)/ruby/internal/attr/error.h
+pinned.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+pinned.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+pinned.o: $(hdrdir)/ruby/internal/attr/format.h
+pinned.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+pinned.o: $(hdrdir)/ruby/internal/attr/noalias.h
+pinned.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+pinned.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+pinned.o: $(hdrdir)/ruby/internal/attr/noinline.h
+pinned.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+pinned.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+pinned.o: $(hdrdir)/ruby/internal/attr/pure.h
+pinned.o: $(hdrdir)/ruby/internal/attr/restrict.h
+pinned.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+pinned.o: $(hdrdir)/ruby/internal/attr/warning.h
+pinned.o: $(hdrdir)/ruby/internal/attr/weakref.h
+pinned.o: $(hdrdir)/ruby/internal/cast.h
+pinned.o: $(hdrdir)/ruby/internal/compiler_is.h
+pinned.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+pinned.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+pinned.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+pinned.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+pinned.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+pinned.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+pinned.o: $(hdrdir)/ruby/internal/compiler_since.h
+pinned.o: $(hdrdir)/ruby/internal/config.h
+pinned.o: $(hdrdir)/ruby/internal/constant_p.h
+pinned.o: $(hdrdir)/ruby/internal/core.h
+pinned.o: $(hdrdir)/ruby/internal/core/rarray.h
+pinned.o: $(hdrdir)/ruby/internal/core/rbasic.h
+pinned.o: $(hdrdir)/ruby/internal/core/rbignum.h
+pinned.o: $(hdrdir)/ruby/internal/core/rclass.h
+pinned.o: $(hdrdir)/ruby/internal/core/rdata.h
+pinned.o: $(hdrdir)/ruby/internal/core/rfile.h
+pinned.o: $(hdrdir)/ruby/internal/core/rhash.h
+pinned.o: $(hdrdir)/ruby/internal/core/robject.h
+pinned.o: $(hdrdir)/ruby/internal/core/rregexp.h
+pinned.o: $(hdrdir)/ruby/internal/core/rstring.h
+pinned.o: $(hdrdir)/ruby/internal/core/rstruct.h
+pinned.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+pinned.o: $(hdrdir)/ruby/internal/ctype.h
+pinned.o: $(hdrdir)/ruby/internal/dllexport.h
+pinned.o: $(hdrdir)/ruby/internal/dosish.h
+pinned.o: $(hdrdir)/ruby/internal/error.h
+pinned.o: $(hdrdir)/ruby/internal/eval.h
+pinned.o: $(hdrdir)/ruby/internal/event.h
+pinned.o: $(hdrdir)/ruby/internal/fl_type.h
+pinned.o: $(hdrdir)/ruby/internal/gc.h
+pinned.o: $(hdrdir)/ruby/internal/glob.h
+pinned.o: $(hdrdir)/ruby/internal/globals.h
+pinned.o: $(hdrdir)/ruby/internal/has/attribute.h
+pinned.o: $(hdrdir)/ruby/internal/has/builtin.h
+pinned.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+pinned.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+pinned.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+pinned.o: $(hdrdir)/ruby/internal/has/extension.h
+pinned.o: $(hdrdir)/ruby/internal/has/feature.h
+pinned.o: $(hdrdir)/ruby/internal/has/warning.h
+pinned.o: $(hdrdir)/ruby/internal/intern/array.h
+pinned.o: $(hdrdir)/ruby/internal/intern/bignum.h
+pinned.o: $(hdrdir)/ruby/internal/intern/class.h
+pinned.o: $(hdrdir)/ruby/internal/intern/compar.h
+pinned.o: $(hdrdir)/ruby/internal/intern/complex.h
+pinned.o: $(hdrdir)/ruby/internal/intern/cont.h
+pinned.o: $(hdrdir)/ruby/internal/intern/dir.h
+pinned.o: $(hdrdir)/ruby/internal/intern/enum.h
+pinned.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+pinned.o: $(hdrdir)/ruby/internal/intern/error.h
+pinned.o: $(hdrdir)/ruby/internal/intern/eval.h
+pinned.o: $(hdrdir)/ruby/internal/intern/file.h
+pinned.o: $(hdrdir)/ruby/internal/intern/gc.h
+pinned.o: $(hdrdir)/ruby/internal/intern/hash.h
+pinned.o: $(hdrdir)/ruby/internal/intern/io.h
+pinned.o: $(hdrdir)/ruby/internal/intern/load.h
+pinned.o: $(hdrdir)/ruby/internal/intern/marshal.h
+pinned.o: $(hdrdir)/ruby/internal/intern/numeric.h
+pinned.o: $(hdrdir)/ruby/internal/intern/object.h
+pinned.o: $(hdrdir)/ruby/internal/intern/parse.h
+pinned.o: $(hdrdir)/ruby/internal/intern/proc.h
+pinned.o: $(hdrdir)/ruby/internal/intern/process.h
+pinned.o: $(hdrdir)/ruby/internal/intern/random.h
+pinned.o: $(hdrdir)/ruby/internal/intern/range.h
+pinned.o: $(hdrdir)/ruby/internal/intern/rational.h
+pinned.o: $(hdrdir)/ruby/internal/intern/re.h
+pinned.o: $(hdrdir)/ruby/internal/intern/ruby.h
+pinned.o: $(hdrdir)/ruby/internal/intern/select.h
+pinned.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+pinned.o: $(hdrdir)/ruby/internal/intern/signal.h
+pinned.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+pinned.o: $(hdrdir)/ruby/internal/intern/string.h
+pinned.o: $(hdrdir)/ruby/internal/intern/struct.h
+pinned.o: $(hdrdir)/ruby/internal/intern/thread.h
+pinned.o: $(hdrdir)/ruby/internal/intern/time.h
+pinned.o: $(hdrdir)/ruby/internal/intern/variable.h
+pinned.o: $(hdrdir)/ruby/internal/intern/vm.h
+pinned.o: $(hdrdir)/ruby/internal/interpreter.h
+pinned.o: $(hdrdir)/ruby/internal/iterator.h
+pinned.o: $(hdrdir)/ruby/internal/memory.h
+pinned.o: $(hdrdir)/ruby/internal/method.h
+pinned.o: $(hdrdir)/ruby/internal/module.h
+pinned.o: $(hdrdir)/ruby/internal/newobj.h
+pinned.o: $(hdrdir)/ruby/internal/rgengc.h
+pinned.o: $(hdrdir)/ruby/internal/scan_args.h
+pinned.o: $(hdrdir)/ruby/internal/special_consts.h
+pinned.o: $(hdrdir)/ruby/internal/static_assert.h
+pinned.o: $(hdrdir)/ruby/internal/stdalign.h
+pinned.o: $(hdrdir)/ruby/internal/stdbool.h
+pinned.o: $(hdrdir)/ruby/internal/symbol.h
+pinned.o: $(hdrdir)/ruby/internal/token_paste.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/gcc_version_since.h
+pointer.o: $(hdrdir)/ruby/backward/2/inttypes.h
+pointer.o: $(hdrdir)/ruby/backward/2/limits.h
+pointer.o: $(hdrdir)/ruby/backward/2/long_long.h
+pointer.o: $(hdrdir)/ruby/backward/2/stdalign.h
+pointer.o: $(hdrdir)/ruby/backward/2/stdarg.h
pointer.o: $(hdrdir)/ruby/defines.h
pointer.o: $(hdrdir)/ruby/encoding.h
pointer.o: $(hdrdir)/ruby/intern.h
+pointer.o: $(hdrdir)/ruby/internal/anyargs.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+pointer.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+pointer.o: $(hdrdir)/ruby/internal/assume.h
+pointer.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+pointer.o: $(hdrdir)/ruby/internal/attr/artificial.h
+pointer.o: $(hdrdir)/ruby/internal/attr/cold.h
+pointer.o: $(hdrdir)/ruby/internal/attr/const.h
+pointer.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+pointer.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+pointer.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+pointer.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+pointer.o: $(hdrdir)/ruby/internal/attr/error.h
+pointer.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+pointer.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+pointer.o: $(hdrdir)/ruby/internal/attr/format.h
+pointer.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+pointer.o: $(hdrdir)/ruby/internal/attr/noalias.h
+pointer.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+pointer.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+pointer.o: $(hdrdir)/ruby/internal/attr/noinline.h
+pointer.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+pointer.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+pointer.o: $(hdrdir)/ruby/internal/attr/pure.h
+pointer.o: $(hdrdir)/ruby/internal/attr/restrict.h
+pointer.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+pointer.o: $(hdrdir)/ruby/internal/attr/warning.h
+pointer.o: $(hdrdir)/ruby/internal/attr/weakref.h
+pointer.o: $(hdrdir)/ruby/internal/cast.h
+pointer.o: $(hdrdir)/ruby/internal/compiler_is.h
+pointer.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+pointer.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+pointer.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+pointer.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+pointer.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+pointer.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+pointer.o: $(hdrdir)/ruby/internal/compiler_since.h
+pointer.o: $(hdrdir)/ruby/internal/config.h
+pointer.o: $(hdrdir)/ruby/internal/constant_p.h
+pointer.o: $(hdrdir)/ruby/internal/core.h
+pointer.o: $(hdrdir)/ruby/internal/core/rarray.h
+pointer.o: $(hdrdir)/ruby/internal/core/rbasic.h
+pointer.o: $(hdrdir)/ruby/internal/core/rbignum.h
+pointer.o: $(hdrdir)/ruby/internal/core/rclass.h
+pointer.o: $(hdrdir)/ruby/internal/core/rdata.h
+pointer.o: $(hdrdir)/ruby/internal/core/rfile.h
+pointer.o: $(hdrdir)/ruby/internal/core/rhash.h
+pointer.o: $(hdrdir)/ruby/internal/core/robject.h
+pointer.o: $(hdrdir)/ruby/internal/core/rregexp.h
+pointer.o: $(hdrdir)/ruby/internal/core/rstring.h
+pointer.o: $(hdrdir)/ruby/internal/core/rstruct.h
+pointer.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+pointer.o: $(hdrdir)/ruby/internal/ctype.h
+pointer.o: $(hdrdir)/ruby/internal/dllexport.h
+pointer.o: $(hdrdir)/ruby/internal/dosish.h
+pointer.o: $(hdrdir)/ruby/internal/error.h
+pointer.o: $(hdrdir)/ruby/internal/eval.h
+pointer.o: $(hdrdir)/ruby/internal/event.h
+pointer.o: $(hdrdir)/ruby/internal/fl_type.h
+pointer.o: $(hdrdir)/ruby/internal/gc.h
+pointer.o: $(hdrdir)/ruby/internal/glob.h
+pointer.o: $(hdrdir)/ruby/internal/globals.h
+pointer.o: $(hdrdir)/ruby/internal/has/attribute.h
+pointer.o: $(hdrdir)/ruby/internal/has/builtin.h
+pointer.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+pointer.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+pointer.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+pointer.o: $(hdrdir)/ruby/internal/has/extension.h
+pointer.o: $(hdrdir)/ruby/internal/has/feature.h
+pointer.o: $(hdrdir)/ruby/internal/has/warning.h
+pointer.o: $(hdrdir)/ruby/internal/intern/array.h
+pointer.o: $(hdrdir)/ruby/internal/intern/bignum.h
+pointer.o: $(hdrdir)/ruby/internal/intern/class.h
+pointer.o: $(hdrdir)/ruby/internal/intern/compar.h
+pointer.o: $(hdrdir)/ruby/internal/intern/complex.h
+pointer.o: $(hdrdir)/ruby/internal/intern/cont.h
+pointer.o: $(hdrdir)/ruby/internal/intern/dir.h
+pointer.o: $(hdrdir)/ruby/internal/intern/enum.h
+pointer.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+pointer.o: $(hdrdir)/ruby/internal/intern/error.h
+pointer.o: $(hdrdir)/ruby/internal/intern/eval.h
+pointer.o: $(hdrdir)/ruby/internal/intern/file.h
+pointer.o: $(hdrdir)/ruby/internal/intern/gc.h
+pointer.o: $(hdrdir)/ruby/internal/intern/hash.h
+pointer.o: $(hdrdir)/ruby/internal/intern/io.h
+pointer.o: $(hdrdir)/ruby/internal/intern/load.h
+pointer.o: $(hdrdir)/ruby/internal/intern/marshal.h
+pointer.o: $(hdrdir)/ruby/internal/intern/numeric.h
+pointer.o: $(hdrdir)/ruby/internal/intern/object.h
+pointer.o: $(hdrdir)/ruby/internal/intern/parse.h
+pointer.o: $(hdrdir)/ruby/internal/intern/proc.h
+pointer.o: $(hdrdir)/ruby/internal/intern/process.h
+pointer.o: $(hdrdir)/ruby/internal/intern/random.h
+pointer.o: $(hdrdir)/ruby/internal/intern/range.h
+pointer.o: $(hdrdir)/ruby/internal/intern/rational.h
+pointer.o: $(hdrdir)/ruby/internal/intern/re.h
+pointer.o: $(hdrdir)/ruby/internal/intern/ruby.h
+pointer.o: $(hdrdir)/ruby/internal/intern/select.h
+pointer.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+pointer.o: $(hdrdir)/ruby/internal/intern/signal.h
+pointer.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+pointer.o: $(hdrdir)/ruby/internal/intern/string.h
+pointer.o: $(hdrdir)/ruby/internal/intern/struct.h
+pointer.o: $(hdrdir)/ruby/internal/intern/thread.h
+pointer.o: $(hdrdir)/ruby/internal/intern/time.h
+pointer.o: $(hdrdir)/ruby/internal/intern/variable.h
+pointer.o: $(hdrdir)/ruby/internal/intern/vm.h
+pointer.o: $(hdrdir)/ruby/internal/interpreter.h
+pointer.o: $(hdrdir)/ruby/internal/iterator.h
+pointer.o: $(hdrdir)/ruby/internal/memory.h
+pointer.o: $(hdrdir)/ruby/internal/method.h
+pointer.o: $(hdrdir)/ruby/internal/module.h
+pointer.o: $(hdrdir)/ruby/internal/newobj.h
+pointer.o: $(hdrdir)/ruby/internal/rgengc.h
+pointer.o: $(hdrdir)/ruby/internal/scan_args.h
+pointer.o: $(hdrdir)/ruby/internal/special_consts.h
+pointer.o: $(hdrdir)/ruby/internal/static_assert.h
+pointer.o: $(hdrdir)/ruby/internal/stdalign.h
+pointer.o: $(hdrdir)/ruby/internal/stdbool.h
+pointer.o: $(hdrdir)/ruby/internal/symbol.h
+pointer.o: $(hdrdir)/ruby/internal/token_paste.h
+pointer.o: $(hdrdir)/ruby/internal/value.h
+pointer.o: $(hdrdir)/ruby/internal/value_type.h
+pointer.o: $(hdrdir)/ruby/internal/variable.h
+pointer.o: $(hdrdir)/ruby/internal/warning_push.h
+pointer.o: $(hdrdir)/ruby/internal/xmalloc.h
pointer.o: $(hdrdir)/ruby/io.h
+pointer.o: $(hdrdir)/ruby/memory_view.h
pointer.o: $(hdrdir)/ruby/missing.h
pointer.o: $(hdrdir)/ruby/onigmo.h
pointer.o: $(hdrdir)/ruby/oniguruma.h
diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb
index f8a94d41e7..6ca685317e 100644
--- a/ext/fiddle/extconf.rb
+++ b/ext/fiddle/extconf.rb
@@ -3,23 +3,73 @@ 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 = enable_config('bundled-libffi')
-if ! bundle
+unless bundle
dir_config 'libffi'
- pkg_config("libffi") and
- ver = pkg_config("libffi", "modversion")
+ if pkg_config("libffi")
+ libffi_version = pkg_config("libffi", "modversion")
+ end
+ have_ffi_header = false
if have_header(ffi_header = 'ffi.h')
- true
+ have_ffi_header = true
elsif have_header(ffi_header = 'ffi/ffi.h')
$defs.push('-DUSE_HEADER_HACKS')
- true
- end and (have_library('ffi') || have_library('libffi'))
-end or
-begin
+ have_ffi_header = true
+ end
+ if have_ffi_header && (have_library('ffi') || have_library('libffi'))
+ have_libffi = true
+ end
+end
+
+unless have_libffi
# for https://github.com/ruby/fiddle
- if bundle && File.exist?("../../bin/extlibs.rb")
+ extlibs_rb = File.expand_path("../../bin/extlibs.rb", $srcdir)
+ if bundle && File.exist?(extlibs_rb)
require "fileutils"
require_relative "../../bin/extlibs"
extlibs = ExtLibs.new
@@ -28,31 +78,32 @@ begin
Dir.glob("#{$srcdir}/libffi-*/").each{|dir| FileUtils.rm_rf(dir)}
extlibs.run(["--cache=#{cache_dir}", ext_dir])
end
- ver = bundle != false &&
- Dir.glob("#{$srcdir}/libffi-*/")
- .map {|n| File.basename(n)}
- .max_by {|n| n.scan(/\d+/).map(&:to_i)}
- unless ver
+ if bundle != false
+ libffi_package_name = Dir.glob("#{$srcdir}/libffi-*/")
+ .map {|n| File.basename(n)}
+ .max_by {|n| n.scan(/\d+/).map(&:to_i)}
+ end
+ unless libffi_package_name
raise "missing libffi. Please install libffi."
end
- srcdir = "#{$srcdir}/#{ver}"
+ libffi_srcdir = "#{$srcdir}/#{libffi_package_name}"
ffi_header = 'ffi.h'
libffi = Struct.new(*%I[dir srcdir builddir include lib a cflags ldflags opt arch]).new
- libffi.dir = ver
+ libffi.dir = libffi_package_name
if $srcdir == "."
- libffi.builddir = "#{ver}/#{RUBY_PLATFORM}"
+ libffi.builddir = libffi_package_name
libffi.srcdir = "."
else
libffi.builddir = libffi.dir
- libffi.srcdir = relative_from(srcdir, "..")
+ libffi.srcdir = relative_from(libffi_srcdir, "..")
end
libffi.include = "#{libffi.builddir}/include"
libffi.lib = "#{libffi.builddir}/.libs"
libffi.a = "#{libffi.lib}/libffi_convenience.#{$LIBEXT}"
nowarn = CONFIG.merge("warnflags"=>"")
libffi.cflags = RbConfig.expand("$(CFLAGS)".dup, nowarn)
- ver = ver[/libffi-(.*)/, 1]
+ libffi_version = libffi_package_name[/libffi-(.*)/, 1]
FileUtils.mkdir_p(libffi.dir)
libffi.opt = CONFIG['configure_args'][/'(-C)'/, 1]
@@ -81,7 +132,6 @@ begin
args.concat %W[
--srcdir=#{libffi.srcdir}
--host=#{libffi.arch}
- --enable-builddir=#{RUBY_PLATFORM}
]
args << ($enable_shared || !$static ? '--enable-shared' : '--enable-static')
args << libffi.opt if libffi.opt
@@ -98,7 +148,7 @@ begin
begin
IO.copy_stream(libffi.dir + "/config.log", Logging.instance_variable_get(:@logfile))
rescue SystemCallError => e
- Logfile.message("%s\n", e.message)
+ Logging.message("%s\n", e.message)
end
raise "failed to configure libffi. Please install libffi."
end
@@ -107,26 +157,35 @@ begin
FileUtils.rm_f("#{libffi.include}/ffitarget.h")
end
unless File.file?("#{libffi.include}/ffitarget.h")
- FileUtils.cp("#{srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true)
+ FileUtils.cp("#{libffi_srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true)
end
$INCFLAGS << " -I" << libffi.include
end
-if ver
- ver = ver.gsub(/-rc\d+/, '') # If ver contains rc version, just ignored.
- ver = (ver.split('.').map(&:to_i) + [0,0])[0,3]
- $defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % ver }})
- warn "libffi_version: #{ver.join('.')}"
+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, (ver && (ver <=> [3, 2]) >= 0)
+when $mswin, $mingw, (libffi_version && (libffi_version <=> [3, 2]) >= 0)
$defs << "-DUSE_FFI_CLOSURE_ALLOC=1"
-when (ver && (ver <=> [3, 2]) < 0)
+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'
if have_header "dlfcn.h"
@@ -141,6 +200,8 @@ elsif have_header "windows.h"
%w{ LoadLibrary FreeLibrary GetProcAddress }.each do |func|
abort "missing function #{func}" unless have_func(func)
end
+
+ have_library "ws2_32"
end
have_const('FFI_STDCALL', ffi_header)
@@ -156,14 +217,19 @@ types.each do |type, signed|
if signed
check_signedness(type.downcase, "stddef.h")
end
+ else
+ check_signedness(type.downcase, "stddef.h")
end
end
+if have_header("ruby/memory_view.h")
+ have_type("rb_memory_view_t", ["ruby/memory_view.h"])
+end
+
if libffi
$LOCAL_LIBS.prepend("./#{libffi.a} ").strip! # to exts.mk
$INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)')
end
-$INCFLAGS << " -I$(top_srcdir)"
create_makefile 'fiddle' do |conf|
if !libffi
next conf << "LIBFFI_CLEAN = none\n"
diff --git a/ext/fiddle/extlibs b/ext/fiddle/extlibs
index 1f0c9348e6..68dac46a95 100644
--- a/ext/fiddle/extlibs
+++ b/ext/fiddle/extlibs
@@ -1,5 +1,13 @@
-https://ftp.osuosl.org/pub/blfs/conglomeration/libffi/libffi-3.2.1.tar.gz \
+ver = 3.2.1
+pkg = libffi-$(ver)
+
+https://ftp.osuosl.org/pub/blfs/conglomeration/libffi/$(pkg).tar.gz \
md5:83b89587607e3eb65c70d361f13bab43 \
sha512:980ca30a8d76f963fca722432b1fe5af77d7a4e4d2eac5144fbc5374d4c596609a293440573f4294207e1bdd9fda80ad1e1cafb2ffb543df5a275bc3bd546483 \
#
- win32/libffi-3.2.1-mswin.patch -p0
+ win32/$(pkg)-mswin.patch -p0
+
+$(pkg)/config.guess -> /tool/config.guess
+$(pkg)/config.sub -> /tool/config.sub
+
+! chdir: $(pkg)| autoconf || exit 0
diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c
index 9f3d1537d6..dd819a298c 100644
--- a/ext/fiddle/fiddle.c
+++ b/ext/fiddle/fiddle.c
@@ -1,41 +1,15 @@
#include <fiddle.h>
VALUE mFiddle;
+VALUE rb_eFiddleDLError;
VALUE rb_eFiddleError;
-#ifndef TYPE_SSIZE_T
-# if SIZEOF_SIZE_T == SIZEOF_INT
-# define TYPE_SSIZE_T TYPE_INT
-# elif SIZEOF_SIZE_T == SIZEOF_LONG
-# define TYPE_SSIZE_T TYPE_LONG
-# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
-# define TYPE_SSIZE_T TYPE_LONG_LONG
-# endif
-#endif
-#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T)
-
-#ifndef TYPE_PTRDIFF_T
-# if SIZEOF_PTRDIFF_T == SIZEOF_INT
-# define TYPE_PTRDIFF_T TYPE_INT
-# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
-# define TYPE_PTRDIFF_T TYPE_LONG
-# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
-# define TYPE_PTRDIFF_T TYPE_LONG_LONG
-# endif
-#endif
+void Init_fiddle_pointer(void);
+void Init_fiddle_pinned(void);
-#ifndef TYPE_INTPTR_T
-# if SIZEOF_INTPTR_T == SIZEOF_INT
-# define TYPE_INTPTR_T TYPE_INT
-# elif SIZEOF_INTPTR_T == SIZEOF_LONG
-# define TYPE_INTPTR_T TYPE_LONG
-# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
-# define TYPE_INTPTR_T TYPE_LONG_LONG
-# endif
+#ifdef FIDDLE_MEMORY_VIEW
+void Init_fiddle_memory_view(void);
#endif
-#define TYPE_UINTPTR_T (-TYPE_INTPTR_T)
-
-void Init_fiddle_pointer(void);
/*
* call-seq: Fiddle.malloc(size)
@@ -47,8 +21,7 @@ static VALUE
rb_fiddle_malloc(VALUE self, VALUE size)
{
void *ptr;
-
- ptr = (void*)ruby_xmalloc(NUM2SIZET(size));
+ ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size));
return PTR2NUM(ptr);
}
@@ -164,11 +137,32 @@ Init_fiddle(void)
mFiddle = rb_define_module("Fiddle");
/*
+ * Document-class: Fiddle::Error
+ *
+ * Generic error class for Fiddle
+ */
+ rb_eFiddleError = rb_define_class_under(mFiddle, "Error", rb_eStandardError);
+
+ /*
+ * Ruby installed by RubyInstaller for Windows always require
+ * bundled Fiddle because ruby_installer/runtime/dll_directory.rb
+ * requires Fiddle. It's used by
+ * rubygems/defaults/operating_system.rb. It means that the
+ * bundled Fiddle is always required on initialization.
+ *
+ * We just remove existing Fiddle::DLError here to override
+ * the bundled Fiddle.
+ */
+ if (rb_const_defined(mFiddle, rb_intern("DLError"))) {
+ rb_const_remove(mFiddle, rb_intern("DLError"));
+ }
+
+ /*
* Document-class: Fiddle::DLError
*
* standard dynamic load exception
*/
- rb_eFiddleError = rb_define_class_under(mFiddle, "DLError", rb_eStandardError);
+ rb_eFiddleDLError = rb_define_class_under(mFiddle, "DLError", rb_eFiddleError);
/* Document-const: TYPE_VOID
*
@@ -214,6 +208,38 @@ Init_fiddle(void)
rb_define_const(mFiddle, "TYPE_LONG_LONG", INT2NUM(TYPE_LONG_LONG));
#endif
+#ifdef TYPE_INT8_T
+ /* Document-const: TYPE_INT8_T
+ *
+ * C type - int8_t
+ */
+ rb_define_const(mFiddle, "TYPE_INT8_T", INT2NUM(TYPE_INT8_T));
+#endif
+
+#ifdef TYPE_INT16_T
+ /* Document-const: TYPE_INT16_T
+ *
+ * C type - int16_t
+ */
+ rb_define_const(mFiddle, "TYPE_INT16_T", INT2NUM(TYPE_INT16_T));
+#endif
+
+#ifdef TYPE_INT32_T
+ /* Document-const: TYPE_INT32_T
+ *
+ * C type - int32_t
+ */
+ rb_define_const(mFiddle, "TYPE_INT32_T", INT2NUM(TYPE_INT32_T));
+#endif
+
+#ifdef TYPE_INT64_T
+ /* Document-const: TYPE_INT64_T
+ *
+ * C type - int64_t
+ */
+ rb_define_const(mFiddle, "TYPE_INT64_T", INT2NUM(TYPE_INT64_T));
+#endif
+
/* Document-const: TYPE_FLOAT
*
* C type - float
@@ -226,6 +252,20 @@ Init_fiddle(void)
*/
rb_define_const(mFiddle, "TYPE_DOUBLE", INT2NUM(TYPE_DOUBLE));
+#ifdef HAVE_FFI_PREP_CIF_VAR
+ /* Document-const: TYPE_VARIADIC
+ *
+ * C type - ...
+ */
+ rb_define_const(mFiddle, "TYPE_VARIADIC", INT2NUM(TYPE_VARIADIC));
+#endif
+
+ /* Document-const: TYPE_CONST_STRING
+ *
+ * C type - const char* ('\0' terminated const char*)
+ */
+ rb_define_const(mFiddle, "TYPE_CONST_STRING", INT2NUM(TYPE_CONST_STRING));
+
/* Document-const: TYPE_SIZE_T
*
* C type - size_t
@@ -294,6 +334,30 @@ Init_fiddle(void)
rb_define_const(mFiddle, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG));
#endif
+ /* Document-const: ALIGN_INT8_T
+ *
+ * The alignment size of a int8_t
+ */
+ rb_define_const(mFiddle, "ALIGN_INT8_T", INT2NUM(ALIGN_INT8_T));
+
+ /* Document-const: ALIGN_INT16_T
+ *
+ * The alignment size of a int16_t
+ */
+ rb_define_const(mFiddle, "ALIGN_INT16_T", INT2NUM(ALIGN_INT16_T));
+
+ /* Document-const: ALIGN_INT32_T
+ *
+ * The alignment size of a int32_t
+ */
+ rb_define_const(mFiddle, "ALIGN_INT32_T", INT2NUM(ALIGN_INT32_T));
+
+ /* Document-const: ALIGN_INT64_T
+ *
+ * The alignment size of a int64_t
+ */
+ rb_define_const(mFiddle, "ALIGN_INT64_T", INT2NUM(ALIGN_INT64_T));
+
/* Document-const: ALIGN_FLOAT
*
* The alignment size of a float
@@ -384,6 +448,30 @@ Init_fiddle(void)
rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG)));
#endif
+ /* Document-const: SIZEOF_INT8_T
+ *
+ * size of a int8_t
+ */
+ rb_define_const(mFiddle, "SIZEOF_INT8_T", INT2NUM(sizeof(int8_t)));
+
+ /* Document-const: SIZEOF_INT16_T
+ *
+ * size of a int16_t
+ */
+ rb_define_const(mFiddle, "SIZEOF_INT16_T", INT2NUM(sizeof(int16_t)));
+
+ /* Document-const: SIZEOF_INT32_T
+ *
+ * size of a int32_t
+ */
+ rb_define_const(mFiddle, "SIZEOF_INT32_T", INT2NUM(sizeof(int32_t)));
+
+ /* Document-const: SIZEOF_INT64_T
+ *
+ * size of a int64_t
+ */
+ rb_define_const(mFiddle, "SIZEOF_INT64_T", INT2NUM(sizeof(int64_t)));
+
/* Document-const: SIZEOF_FLOAT
*
* size of a float
@@ -426,6 +514,12 @@ Init_fiddle(void)
*/
rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t)));
+ /* Document-const: SIZEOF_CONST_STRING
+ *
+ * size of a const char*
+ */
+ rb_define_const(mFiddle, "SIZEOF_CONST_STRING", INT2NUM(sizeof(const char*)));
+
/* Document-const: RUBY_FREE
*
* Address of the ruby_xfree() function
@@ -450,5 +544,10 @@ Init_fiddle(void)
Init_fiddle_closure();
Init_fiddle_handle();
Init_fiddle_pointer();
+ Init_fiddle_pinned();
+
+#ifdef FIDDLE_MEMORY_VIEW
+ Init_fiddle_memory_view();
+#endif
}
/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/fiddle.gemspec b/ext/fiddle/fiddle.gemspec
index b29f4ec788..a47f795f59 100644
--- a/ext/fiddle/fiddle.gemspec
+++ b/ext/fiddle/fiddle.gemspec
@@ -1,23 +1,66 @@
# frozen_string_literal: true
+
+version_module = Module.new do
+ version_rb = File.join(__dir__, "lib/fiddle/version.rb")
+ module_eval(File.read(version_rb), version_rb, __LINE__)
+end
+
Gem::Specification.new do |spec|
spec.name = "fiddle"
- spec.version = '1.0.0'
+ spec.version = version_module::Fiddle::VERSION
spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"]
spec.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org"]
spec.summary = %q{A libffi wrapper for Ruby.}
spec.description = %q{A libffi wrapper for Ruby.}
spec.homepage = "https://github.com/ruby/fiddle"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "ext/fiddle/closure.c", "ext/fiddle/closure.h", "ext/fiddle/conversions.c", "ext/fiddle/conversions.h", "ext/fiddle/extconf.rb", "ext/fiddle/extlibs", "ext/fiddle/fiddle.c", "ext/fiddle/fiddle.h", "ext/fiddle/function.c", "ext/fiddle/function.h", "ext/fiddle/handle.c", "ext/fiddle/pointer.c", "ext/fiddle/win32/fficonfig.h", "ext/fiddle/win32/libffi-3.2.1-mswin.patch", "ext/fiddle/win32/libffi-config.rb", "ext/fiddle/win32/libffi.mk.tmpl", "fiddle.gemspec", "lib/fiddle.rb", "lib/fiddle/closure.rb", "lib/fiddle/cparser.rb", "lib/fiddle/function.rb", "lib/fiddle/import.rb", "lib/fiddle/pack.rb", "lib/fiddle/struct.rb", "lib/fiddle/types.rb", "lib/fiddle/value.rb"]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.files = [
+ "LICENSE.txt",
+ "README.md",
+ "Rakefile",
+ "bin/downloader.rb",
+ "bin/extlibs.rb",
+ "ext/fiddle/closure.c",
+ "ext/fiddle/closure.h",
+ "ext/fiddle/conversions.c",
+ "ext/fiddle/conversions.h",
+ "ext/fiddle/depend",
+ "ext/fiddle/extconf.rb",
+ "ext/fiddle/extlibs",
+ "ext/fiddle/fiddle.c",
+ "ext/fiddle/fiddle.h",
+ "ext/fiddle/function.c",
+ "ext/fiddle/function.h",
+ "ext/fiddle/handle.c",
+ "ext/fiddle/memory_view.c",
+ "ext/fiddle/pinned.c",
+ "ext/fiddle/pointer.c",
+ "ext/fiddle/win32/fficonfig.h",
+ "ext/fiddle/win32/libffi-3.2.1-mswin.patch",
+ "ext/fiddle/win32/libffi-config.rb",
+ "ext/fiddle/win32/libffi.mk.tmpl",
+ "fiddle.gemspec",
+ "lib/fiddle.rb",
+ "lib/fiddle/closure.rb",
+ "lib/fiddle/cparser.rb",
+ "lib/fiddle/function.rb",
+ "lib/fiddle/import.rb",
+ "lib/fiddle/pack.rb",
+ "lib/fiddle/struct.rb",
+ "lib/fiddle/types.rb",
+ "lib/fiddle/value.rb",
+ "lib/fiddle/version.rb",
+ ]
spec.require_paths = ["lib"]
+ spec.extensions = ["ext/fiddle/extconf.rb"]
spec.required_ruby_version = ">= 2.3.0"
spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
spec.add_development_dependency "rake-compiler"
+
+ spec.metadata["msys2_mingw_dependencies"] = "libffi"
end
diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h
index d2583c1cbf..dbad910d07 100644
--- a/ext/fiddle/fiddle.h
+++ b/ext/fiddle/fiddle.h
@@ -58,38 +58,38 @@
# error "CHAR_BIT not supported"
#endif
-# if SIZEOF_SHORT == 2
-# define ffi_type_ushort ffi_type_uint16
-# define ffi_type_sshort ffi_type_sint16
-# elif SIZEOF_SHORT == 4
-# define ffi_type_ushort ffi_type_uint32
-# define ffi_type_sshort ffi_type_sint32
-# else
-# error "short size not supported"
-# endif
+#if SIZEOF_SHORT == 2
+# define ffi_type_ushort ffi_type_uint16
+# define ffi_type_sshort ffi_type_sint16
+#elif SIZEOF_SHORT == 4
+# define ffi_type_ushort ffi_type_uint32
+# define ffi_type_sshort ffi_type_sint32
+#else
+# error "short size not supported"
+#endif
-# if SIZEOF_INT == 2
-# define ffi_type_uint ffi_type_uint16
-# define ffi_type_sint ffi_type_sint16
-# elif SIZEOF_INT == 4
-# define ffi_type_uint ffi_type_uint32
-# define ffi_type_sint ffi_type_sint32
-# elif SIZEOF_INT == 8
-# define ffi_type_uint ffi_type_uint64
-# define ffi_type_sint ffi_type_sint64
-# else
-# error "int size not supported"
-# endif
+#if SIZEOF_INT == 2
+# define ffi_type_uint ffi_type_uint16
+# define ffi_type_sint ffi_type_sint16
+#elif SIZEOF_INT == 4
+# define ffi_type_uint ffi_type_uint32
+# define ffi_type_sint ffi_type_sint32
+#elif SIZEOF_INT == 8
+# define ffi_type_uint ffi_type_uint64
+# define ffi_type_sint ffi_type_sint64
+#else
+# error "int size not supported"
+#endif
-# if SIZEOF_LONG == 4
-# define ffi_type_ulong ffi_type_uint32
-# define ffi_type_slong ffi_type_sint32
-# elif SIZEOF_LONG == 8
-# define ffi_type_ulong ffi_type_uint64
-# define ffi_type_slong ffi_type_sint64
-# else
-# error "long size not supported"
-# endif
+#if SIZEOF_LONG == 4
+# define ffi_type_ulong ffi_type_uint32
+# define ffi_type_slong ffi_type_sint32
+#elif SIZEOF_LONG == 8
+# define ffi_type_ulong ffi_type_uint64
+# define ffi_type_slong ffi_type_sint64
+#else
+# error "long size not supported"
+#endif
#if HAVE_LONG_LONG
# if SIZEOF_LONG_LONG == 8
@@ -115,12 +115,67 @@
#endif
#define TYPE_FLOAT 7
#define TYPE_DOUBLE 8
+#define TYPE_VARIADIC 9
+#define TYPE_CONST_STRING 10
+
+#define TYPE_INT8_T TYPE_CHAR
+#if SIZEOF_SHORT == 2
+# define TYPE_INT16_T TYPE_SHORT
+#elif SIZEOF_INT == 2
+# define TYPE_INT16_T TYPE_INT
+#endif
+#if SIZEOF_SHORT == 4
+# define TYPE_INT32_T TYPE_SHORT
+#elif SIZEOF_INT == 4
+# define TYPE_INT32_T TYPE_INT
+#elif SIZEOF_LONG == 4
+# define TYPE_INT32_T TYPE_LONG
+#endif
+#if SIZEOF_INT == 8
+# define TYPE_INT64_T TYPE_INT
+#elif SIZEOF_LONG == 8
+# define TYPE_INT64_T TYPE_LONG
+#elif defined(TYPE_LONG_LONG)
+# define TYPE_INT64_T TYPE_LONG_LONG
+#endif
+
+#ifndef TYPE_SSIZE_T
+# if SIZEOF_SIZE_T == SIZEOF_INT
+# define TYPE_SSIZE_T TYPE_INT
+# elif SIZEOF_SIZE_T == SIZEOF_LONG
+# define TYPE_SSIZE_T TYPE_LONG
+# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+# define TYPE_SSIZE_T TYPE_LONG_LONG
+# endif
+#endif
+#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T)
+
+#ifndef TYPE_PTRDIFF_T
+# if SIZEOF_PTRDIFF_T == SIZEOF_INT
+# define TYPE_PTRDIFF_T TYPE_INT
+# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
+# define TYPE_PTRDIFF_T TYPE_LONG
+# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
+# define TYPE_PTRDIFF_T TYPE_LONG_LONG
+# endif
+#endif
+
+#ifndef TYPE_INTPTR_T
+# if SIZEOF_INTPTR_T == SIZEOF_INT
+# define TYPE_INTPTR_T TYPE_INT
+# elif SIZEOF_INTPTR_T == SIZEOF_LONG
+# define TYPE_INTPTR_T TYPE_LONG
+# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
+# define TYPE_INTPTR_T TYPE_LONG_LONG
+# endif
+#endif
+#define TYPE_UINTPTR_T (-TYPE_INTPTR_T)
#define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x)
#define ALIGN_VOIDP ALIGN_OF(void*)
-#define ALIGN_SHORT ALIGN_OF(short)
#define ALIGN_CHAR ALIGN_OF(char)
+#define ALIGN_SHORT ALIGN_OF(short)
#define ALIGN_INT ALIGN_OF(int)
#define ALIGN_LONG ALIGN_OF(long)
#if HAVE_LONG_LONG
@@ -129,8 +184,17 @@
#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)
+
+#ifdef HAVE_TYPE_RB_MEMORY_VIEW_T
+# define FIDDLE_MEMORY_VIEW
+#endif
+
extern VALUE mFiddle;
-extern VALUE rb_eFiddleError;
+extern VALUE rb_eFiddleDLError;
VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type);
diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c
index 994402e26b..d15a54bfa6 100644
--- a/ext/fiddle/function.c
+++ b/ext/fiddle/function.c
@@ -1,6 +1,8 @@
#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)
@@ -19,21 +21,21 @@ VALUE cFiddleFunction;
#define Check_Max_Args_Long(name, len) \
Check_Max_Args_(name, len, "l")
#define Check_Max_Args_(name, len, fmt) \
- if ((size_t)(len) < MAX_ARGS) { \
- /* OK */ \
- } \
- else { \
- rb_raise(rb_eTypeError, \
- name" is so large that it can cause integer overflow (%"fmt"d)", \
- (len)); \
- }
+ do { \
+ if ((size_t)(len) >= MAX_ARGS) { \
+ rb_raise(rb_eTypeError, \
+ "%s is so large " \
+ "that it can cause integer overflow (%"fmt"d)", \
+ (name), (len)); \
+ } \
+ } while (0)
static void
deallocate(void *p)
{
- ffi_cif *ptr = p;
- if (ptr->arg_types) xfree(ptr->arg_types);
- xfree(ptr);
+ ffi_cif *cif = p;
+ if (cif->arg_types) xfree(cif->arg_types);
+ xfree(cif);
}
static size_t
@@ -75,74 +77,114 @@ rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type)
return rb_class_new_instance(3, argv, cFiddleFunction);
}
-static int
-parse_keyword_arg_i(VALUE key, VALUE value, VALUE self)
+static VALUE
+normalize_argument_types(const char *name,
+ VALUE arg_types,
+ bool *is_variadic)
{
- if (key == ID2SYM(rb_intern("name"))) {
- rb_iv_set(self, "@name", value);
- } else {
- rb_raise(rb_eArgError, "unknown keyword: %"PRIsVALUE,
- RB_OBJ_STRING(key));
+ VALUE normalized_arg_types;
+ int i;
+ int n_arg_types;
+ *is_variadic = false;
+
+ Check_Type(arg_types, T_ARRAY);
+ n_arg_types = RARRAY_LENINT(arg_types);
+ Check_Max_Args(name, n_arg_types);
+
+ normalized_arg_types = rb_ary_new_capa(n_arg_types);
+ for (i = 0; i < n_arg_types; i++) {
+ VALUE arg_type = RARRAY_AREF(arg_types, i);
+ int c_arg_type;
+ arg_type = rb_fiddle_type_ensure(arg_type);
+ c_arg_type = NUM2INT(arg_type);
+ if (c_arg_type == TYPE_VARIADIC) {
+ if (i != n_arg_types - 1) {
+ rb_raise(rb_eArgError,
+ "Fiddle::TYPE_VARIADIC must be the last argument type: "
+ "%"PRIsVALUE,
+ arg_types);
+ }
+ *is_variadic = true;
+ break;
+ }
+ else {
+ (void)INT2FFI_TYPE(c_arg_type); /* raise */
+ }
+ rb_ary_push(normalized_arg_types, INT2FIX(c_arg_type));
}
- return ST_CONTINUE;
+
+ /* freeze to prevent inconsistency at calling #to_int later */
+ OBJ_FREEZE(normalized_arg_types);
+ return normalized_arg_types;
}
static VALUE
initialize(int argc, VALUE argv[], VALUE self)
{
ffi_cif * cif;
- ffi_type **arg_types, *rtype;
- ffi_status result;
- VALUE ptr, args, ret_type, abi, kwds, ary;
- int i, len;
- int nabi;
+ VALUE ptr, arg_types, ret_type, abi, kwargs;
+ VALUE name = Qnil;
+ VALUE need_gvl = Qfalse;
+ int c_ret_type;
+ bool is_variadic = false;
+ ffi_abi c_ffi_abi;
void *cfunc;
- rb_scan_args(argc, argv, "31:", &ptr, &args, &ret_type, &abi, &kwds);
+ rb_scan_args(argc, argv, "31:", &ptr, &arg_types, &ret_type, &abi, &kwargs);
rb_iv_set(self, "@closure", ptr);
+ if (!NIL_P(kwargs)) {
+ enum {
+ kw_name,
+ kw_need_gvl,
+ kw_max_,
+ };
+ static ID kw[kw_max_];
+ VALUE args[kw_max_];
+ if (!kw[0]) {
+ kw[kw_name] = rb_intern_const("name");
+ kw[kw_need_gvl] = rb_intern_const("need_gvl");
+ }
+ rb_get_kwargs(kwargs, kw, 0, kw_max_, args);
+ if (args[kw_name] != Qundef) {
+ name = args[kw_name];
+ }
+ if (args[kw_need_gvl] != Qundef) {
+ need_gvl = args[kw_need_gvl];
+ }
+ }
+ rb_iv_set(self, "@name", name);
+ rb_iv_set(self, "@need_gvl", need_gvl);
+
ptr = rb_Integer(ptr);
cfunc = NUM2PTR(ptr);
PTR2NUM(cfunc);
- nabi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi);
- abi = INT2FIX(nabi);
- i = NUM2INT(ret_type);
- rtype = INT2FFI_TYPE(i);
- ret_type = INT2FIX(i);
-
- Check_Type(args, T_ARRAY);
- len = RARRAY_LENINT(args);
- Check_Max_Args("args", len);
- ary = rb_ary_subseq(args, 0, len);
- for (i = 0; i < RARRAY_LEN(args); i++) {
- VALUE a = RARRAY_AREF(args, i);
- int type = NUM2INT(a);
- (void)INT2FFI_TYPE(type); /* raise */
- if (INT2FIX(type) != a) rb_ary_store(ary, i, INT2FIX(type));
+ c_ffi_abi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi);
+ abi = INT2FIX(c_ffi_abi);
+ ret_type = rb_fiddle_type_ensure(ret_type);
+ c_ret_type = NUM2INT(ret_type);
+ (void)INT2FFI_TYPE(c_ret_type); /* raise */
+ ret_type = INT2FIX(c_ret_type);
+
+ arg_types = normalize_argument_types("argument types",
+ arg_types,
+ &is_variadic);
+#ifndef HAVE_FFI_PREP_CIF_VAR
+ if (is_variadic) {
+ rb_raise(rb_eNotImpError,
+ "ffi_prep_cif_var() is required in libffi "
+ "for variadic arguments");
}
- OBJ_FREEZE(ary);
+#endif
rb_iv_set(self, "@ptr", ptr);
- rb_iv_set(self, "@args", args);
+ rb_iv_set(self, "@argument_types", arg_types);
rb_iv_set(self, "@return_type", ret_type);
rb_iv_set(self, "@abi", abi);
-
- if (!NIL_P(kwds)) rb_hash_foreach(kwds, parse_keyword_arg_i, self);
+ rb_iv_set(self, "@is_variadic", is_variadic ? Qtrue : Qfalse);
TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
-
- arg_types = xcalloc(len + 1, sizeof(ffi_type *));
-
- for (i = 0; i < RARRAY_LEN(args); i++) {
- int type = NUM2INT(RARRAY_AREF(args, i));
- arg_types[i] = INT2FFI_TYPE(type);
- }
- arg_types[len] = NULL;
-
- result = ffi_prep_cif(cif, nabi, len, rtype, arg_types);
-
- if (result)
- rb_raise(rb_eRuntimeError, "error creating CIF %d", result);
+ cif->arg_types = NULL;
return self;
}
@@ -169,52 +211,181 @@ function_call(int argc, VALUE argv[], VALUE self)
{
struct nogvl_ffi_call_args args = { 0 };
fiddle_generic *generic_args;
- VALUE cfunc, types, cPointer;
+ VALUE cfunc;
+ VALUE abi;
+ VALUE arg_types;
+ VALUE cPointer;
+ VALUE is_variadic;
+ VALUE need_gvl;
+ int n_arg_types;
+ int n_fixed_args = 0;
+ int n_call_args = 0;
int i;
+ int i_call;
+ VALUE converted_args = Qnil;
VALUE alloc_buffer = 0;
cfunc = rb_iv_get(self, "@ptr");
- types = rb_iv_get(self, "@args");
+ abi = rb_iv_get(self, "@abi");
+ arg_types = rb_iv_get(self, "@argument_types");
cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
-
- Check_Max_Args("number of arguments", argc);
- if (argc != (i = RARRAY_LENINT(types))) {
- rb_error_arity(argc, i, i);
+ is_variadic = rb_iv_get(self, "@is_variadic");
+ need_gvl = rb_iv_get(self, "@need_gvl");
+
+ n_arg_types = RARRAY_LENINT(arg_types);
+ n_fixed_args = n_arg_types;
+ if (RTEST(is_variadic)) {
+ if (argc < n_arg_types) {
+ rb_error_arity(argc, n_arg_types, UNLIMITED_ARGUMENTS);
+ }
+ if (((argc - n_arg_types) % 2) != 0) {
+ rb_raise(rb_eArgError,
+ "variadic arguments must be type and value pairs: "
+ "%"PRIsVALUE,
+ rb_ary_new_from_values(argc, argv));
+ }
+ n_call_args = n_arg_types + ((argc - n_arg_types) / 2);
}
+ else {
+ if (argc != n_arg_types) {
+ rb_error_arity(argc, n_arg_types, n_arg_types);
+ }
+ n_call_args = n_arg_types;
+ }
+ Check_Max_Args("the number of arguments", n_call_args);
TypedData_Get_Struct(self, ffi_cif, &function_data_type, args.cif);
+ if (is_variadic && args.cif->arg_types) {
+ xfree(args.cif->arg_types);
+ args.cif->arg_types = NULL;
+ }
+
+ if (!args.cif->arg_types) {
+ VALUE fixed_arg_types = arg_types;
+ VALUE return_type;
+ int c_return_type;
+ ffi_type *ffi_return_type;
+ ffi_type **ffi_arg_types;
+ ffi_status result;
+
+ arg_types = rb_ary_dup(fixed_arg_types);
+ for (i = n_fixed_args; i < argc; i += 2) {
+ VALUE arg_type = argv[i];
+ int c_arg_type;
+ arg_type = rb_fiddle_type_ensure(arg_type);
+ c_arg_type = NUM2INT(arg_type);
+ (void)INT2FFI_TYPE(c_arg_type); /* raise */
+ rb_ary_push(arg_types, INT2FIX(c_arg_type));
+ }
+
+ return_type = rb_iv_get(self, "@return_type");
+ c_return_type = FIX2INT(return_type);
+ ffi_return_type = INT2FFI_TYPE(c_return_type);
+
+ ffi_arg_types = xcalloc(n_call_args + 1, sizeof(ffi_type *));
+ for (i_call = 0; i_call < n_call_args; i_call++) {
+ VALUE arg_type;
+ int c_arg_type;
+ arg_type = RARRAY_AREF(arg_types, i_call);
+ c_arg_type = FIX2INT(arg_type);
+ ffi_arg_types[i_call] = INT2FFI_TYPE(c_arg_type);
+ }
+ ffi_arg_types[i_call] = NULL;
+
+ if (is_variadic) {
+#ifdef HAVE_FFI_PREP_CIF_VAR
+ result = ffi_prep_cif_var(args.cif,
+ FIX2INT(abi),
+ n_fixed_args,
+ n_call_args,
+ ffi_return_type,
+ ffi_arg_types);
+#else
+ /* This code is never used because ffi_prep_cif_var()
+ * availability check is done in #initialize. */
+ result = FFI_BAD_TYPEDEF;
+#endif
+ }
+ else {
+ result = ffi_prep_cif(args.cif,
+ FIX2INT(abi),
+ n_call_args,
+ ffi_return_type,
+ ffi_arg_types);
+ }
+ if (result != FFI_OK) {
+ xfree(ffi_arg_types);
+ args.cif->arg_types = NULL;
+ rb_raise(rb_eRuntimeError, "error creating CIF %d", result);
+ }
+ }
+
generic_args = ALLOCV(alloc_buffer,
- (size_t)(argc + 1) * sizeof(void *) + (size_t)argc * sizeof(fiddle_generic));
+ sizeof(fiddle_generic) * n_call_args +
+ sizeof(void *) * (n_call_args + 1));
args.values = (void **)((char *)generic_args +
- (size_t)argc * sizeof(fiddle_generic));
-
- for (i = 0; i < argc; i++) {
- VALUE type = RARRAY_AREF(types, i);
- VALUE src = argv[i];
- int argtype = FIX2INT(type);
-
- if (argtype == TYPE_VOIDP) {
- if(NIL_P(src)) {
- src = INT2FIX(0);
- } else if(cPointer != CLASS_OF(src)) {
- src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
- }
- src = rb_Integer(src);
- }
-
- VALUE2GENERIC(argtype, src, &generic_args[i]);
- args.values[i] = (void *)&generic_args[i];
+ sizeof(fiddle_generic) * n_call_args);
+
+ for (i = 0, i_call = 0;
+ i < argc && i_call < n_call_args;
+ i++, i_call++) {
+ VALUE arg_type;
+ int c_arg_type;
+ VALUE original_src;
+ VALUE src;
+ arg_type = RARRAY_AREF(arg_types, i_call);
+ c_arg_type = FIX2INT(arg_type);
+ if (i >= n_fixed_args) {
+ i++;
+ }
+ src = argv[i];
+
+ if (c_arg_type == TYPE_VOIDP) {
+ if (NIL_P(src)) {
+ src = INT2FIX(0);
+ }
+ else if (cPointer != CLASS_OF(src)) {
+ src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
+ if (NIL_P(converted_args)) {
+ converted_args = rb_ary_new();
+ }
+ rb_ary_push(converted_args, src);
+ }
+ src = rb_Integer(src);
+ }
+
+ original_src = src;
+ VALUE2GENERIC(c_arg_type, src, &generic_args[i_call]);
+ if (src != original_src) {
+ if (NIL_P(converted_args)) {
+ converted_args = rb_ary_new();
+ }
+ rb_ary_push(converted_args, src);
+ }
+ args.values[i_call] = (void *)&generic_args[i_call];
}
- args.values[argc] = NULL;
+ args.values[i_call] = NULL;
args.fn = (void(*)(void))NUM2PTR(cfunc);
- (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);
+ if (RTEST(need_gvl)) {
+ ffi_call(args.cif, args.fn, &(args.retval), args.values);
+ }
+ else {
+ (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);
+ }
- rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno));
+ {
+ int errno_keep = errno;
#if defined(_WIN32)
- rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, INT2NUM(errno));
+ int socket_error = WSAGetLastError();
+ rb_funcall(mFiddle, rb_intern("win32_last_error="), 1,
+ INT2NUM(errno_keep));
+ rb_funcall(mFiddle, rb_intern("win32_last_socket_error="), 1,
+ INT2NUM(socket_error));
#endif
+ rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno_keep));
+ }
ALLOCV_END(alloc_buffer);
@@ -287,6 +458,10 @@ Init_fiddle_function(void)
* Caller must ensure the underlying function is called in a
* thread-safe manner if running in a multi-threaded process.
*
+ * Note that it is not thread-safe to use this method to
+ * directly or indirectly call many Ruby C-extension APIs unless
+ * you don't pass +need_gvl: true+ to Fiddle::Function#new.
+ *
* For an example see Fiddle::Function
*
*/
@@ -294,13 +469,20 @@ Init_fiddle_function(void)
/*
* Document-method: new
- * call-seq: new(ptr, args, ret_type, abi = DEFAULT)
+ * call-seq: new(ptr,
+ * args,
+ * ret_type,
+ * abi = DEFAULT,
+ * name: nil,
+ * need_gvl: false)
*
* Constructs a Function object.
* * +ptr+ is a referenced function, of a Fiddle::Handle
* * +args+ is an Array of arguments, passed to the +ptr+ function
* * +ret_type+ is the return type of the function
* * +abi+ is the ABI of the function
+ * * +name+ is the name of the function
+ * * +need_gvl+ is whether GVL is needed to call the function
*
*/
rb_define_method(cFiddleFunction, "initialize", initialize, -1);
diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c
index 700924afb5..c1b2db557a 100644
--- a/ext/fiddle/handle.c
+++ b/ext/fiddle/handle.c
@@ -74,14 +74,14 @@ rb_fiddle_handle_close(VALUE self)
/* Check dlclose for successful return value */
if(ret) {
#if defined(HAVE_DLERROR)
- rb_raise(rb_eFiddleError, "%s", dlerror());
+ rb_raise(rb_eFiddleDLError, "%s", dlerror());
#else
- rb_raise(rb_eFiddleError, "could not close handle");
+ rb_raise(rb_eFiddleDLError, "could not close handle");
#endif
}
return INT2NUM(ret);
}
- rb_raise(rb_eFiddleError, "dlclose() called too many times");
+ rb_raise(rb_eFiddleDLError, "dlclose() called too many times");
UNREACHABLE;
}
@@ -177,12 +177,12 @@ rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self)
ptr = dlopen(clib, cflag);
#if defined(HAVE_DLERROR)
if( !ptr && (err = dlerror()) ){
- rb_raise(rb_eFiddleError, "%s", err);
+ rb_raise(rb_eFiddleDLError, "%s", err);
}
#else
if( !ptr ){
err = dlerror();
- rb_raise(rb_eFiddleError, "%s", err);
+ rb_raise(rb_eFiddleDLError, "%s", err);
}
#endif
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
@@ -278,7 +278,7 @@ rb_fiddle_handle_sym(VALUE self, VALUE sym)
TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
if( ! fiddle_handle->open ){
- rb_raise(rb_eFiddleError, "closed handle");
+ rb_raise(rb_eFiddleDLError, "closed handle");
}
return fiddle_handle_sym(fiddle_handle->ptr, sym);
@@ -366,7 +366,7 @@ fiddle_handle_sym(void *handle, VALUE symbol)
}
#endif
if( !func ){
- rb_raise(rb_eFiddleError, "unknown symbol \"%"PRIsVALUE"\"", symbol);
+ rb_raise(rb_eFiddleDLError, "unknown symbol \"%"PRIsVALUE"\"", symbol);
}
return PTR2NUM(func);
diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb
index e9aa7e50ae..4512989310 100644
--- a/ext/fiddle/lib/fiddle.rb
+++ b/ext/fiddle/lib/fiddle.rb
@@ -1,7 +1,9 @@
# frozen_string_literal: true
+
require 'fiddle.so'
-require 'fiddle/function'
require 'fiddle/closure'
+require 'fiddle/function'
+require 'fiddle/version'
module Fiddle
if WINDOWS
@@ -15,6 +17,18 @@ module Fiddle
def self.win32_last_error= error
Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
end
+
+ # Returns the last win32 socket +Error+ of the current executing
+ # +Thread+ or nil if none
+ def self.win32_last_socket_error
+ Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
+ end
+
+ # Sets the last win32 socket +Error+ of the current executing
+ # +Thread+ to +error+
+ def self.win32_last_socket_error= error
+ Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
+ end
end
# Returns the last +Error+ of the current executing +Thread+ or nil if none
diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb
index cd0a64fef5..93a05513c9 100644
--- a/ext/fiddle/lib/fiddle/cparser.rb
+++ b/ext/fiddle/lib/fiddle/cparser.rb
@@ -35,12 +35,37 @@ module Fiddle
def parse_struct_signature(signature, tymap=nil)
if signature.is_a?(String)
signature = split_arguments(signature, /[,;]/)
+ elsif signature.is_a?(Hash)
+ signature = [signature]
end
mems = []
tys = []
signature.each{|msig|
- msig = compact(msig)
+ msig = compact(msig) if msig.is_a?(String)
case msig
+ when Hash
+ msig.each do |struct_name, struct_signature|
+ struct_name = struct_name.to_s if struct_name.is_a?(Symbol)
+ struct_name = compact(struct_name)
+ struct_count = nil
+ if struct_name =~ /^([\w\*\s]+)\[(\d+)\]$/
+ struct_count = $2.to_i
+ struct_name = $1
+ end
+ if struct_signature.respond_to?(:entity_class)
+ struct_type = struct_signature
+ else
+ parsed_struct = parse_struct_signature(struct_signature, tymap)
+ struct_type = CStructBuilder.create(CStruct, *parsed_struct)
+ end
+ if struct_count
+ ty = [struct_type, struct_count]
+ else
+ ty = struct_type
+ end
+ mems.push([struct_name, struct_type.members])
+ tys.push(ty)
+ end
when /^[\w\*\s]+[\*\s](\w+)$/
mems.push($1)
tys.push(parse_ctype(msig, tymap))
@@ -123,55 +148,97 @@ module Fiddle
#
def parse_ctype(ty, tymap=nil)
tymap ||= {}
- case ty
- when Array
+ if ty.is_a?(Array)
return [parse_ctype(ty[0], tymap), ty[1]]
+ end
+ ty = ty.gsub(/\Aconst\s+/, "")
+ case ty
when 'void'
return TYPE_VOID
- when /^(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?$/
- if( defined?(TYPE_LONG_LONG) )
- return TYPE_LONG_LONG
- else
+ when /\A(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_LONG_LONG)
raise(RuntimeError, "unsupported type: #{ty}")
end
- when /^(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?$/
- if( defined?(TYPE_LONG_LONG) )
- return -TYPE_LONG_LONG
- else
+ return TYPE_LONG_LONG
+ when /\A(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_LONG_LONG)
raise(RuntimeError, "unsupported type: #{ty}")
end
- when /^(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?$/
+ return -TYPE_LONG_LONG
+ when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/
return TYPE_LONG
- when /^unsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?$/
+ when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/
return -TYPE_LONG
- when /^(?:signed\s+)?int(?:\s+\w+)?$/
+ when /\A(?:signed\s+)?int(?:\s+\w+)?\z/
return TYPE_INT
- when /^(?:unsigned\s+int|uint)(?:\s+\w+)?$/
+ when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/
return -TYPE_INT
- when /^(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?$/
+ when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/
return TYPE_SHORT
- when /^unsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?$/
+ when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/
return -TYPE_SHORT
- when /^(?:signed\s+)?char(?:\s+\w+)?$/
+ when /\A(?:signed\s+)?char(?:\s+\w+)?\z/
return TYPE_CHAR
- when /^unsigned\s+char(?:\s+\w+)?$/
+ when /\Aunsigned\s+char(?:\s+\w+)?\z/
return -TYPE_CHAR
- when /^float(?:\s+\w+)?$/
+ when /\Aint8_t(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_INT8_T)
+ raise(RuntimeError, "unsupported type: #{ty}")
+ end
+ return TYPE_INT8_T
+ when /\Auint8_t(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_INT8_T)
+ raise(RuntimeError, "unsupported type: #{ty}")
+ end
+ return -TYPE_INT8_T
+ when /\Aint16_t(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_INT16_T)
+ raise(RuntimeError, "unsupported type: #{ty}")
+ end
+ return TYPE_INT16_T
+ when /\Auint16_t(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_INT16_T)
+ raise(RuntimeError, "unsupported type: #{ty}")
+ end
+ return -TYPE_INT16_T
+ when /\Aint32_t(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_INT32_T)
+ raise(RuntimeError, "unsupported type: #{ty}")
+ end
+ return TYPE_INT32_T
+ when /\Auint32_t(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_INT32_T)
+ raise(RuntimeError, "unsupported type: #{ty}")
+ end
+ return -TYPE_INT32_T
+ when /\Aint64_t(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_INT64_T)
+ raise(RuntimeError, "unsupported type: #{ty}")
+ end
+ return TYPE_INT64_T
+ when /\Auint64_t(?:\s+\w+)?\z/
+ unless Fiddle.const_defined?(:TYPE_INT64_T)
+ raise(RuntimeError, "unsupported type: #{ty}")
+ end
+ return -TYPE_INT64_T
+ when /\Afloat(?:\s+\w+)?\z/
return TYPE_FLOAT
- when /^double(?:\s+\w+)?$/
+ when /\Adouble(?:\s+\w+)?\z/
return TYPE_DOUBLE
- when /^size_t(?:\s+\w+)?$/
+ when /\Asize_t(?:\s+\w+)?\z/
return TYPE_SIZE_T
- when /^ssize_t(?:\s+\w+)?$/
+ when /\Assize_t(?:\s+\w+)?\z/
return TYPE_SSIZE_T
- when /^ptrdiff_t(?:\s+\w+)?$/
+ when /\Aptrdiff_t(?:\s+\w+)?\z/
return TYPE_PTRDIFF_T
- when /^intptr_t(?:\s+\w+)?$/
+ when /\Aintptr_t(?:\s+\w+)?\z/
return TYPE_INTPTR_T
- when /^uintptr_t(?:\s+\w+)?$/
+ when /\Auintptr_t(?:\s+\w+)?\z/
return TYPE_UINTPTR_T
when /\*/, /\[[\s\d]*\]/
return TYPE_VOIDP
+ when "..."
+ return TYPE_VARIADIC
else
ty = ty.split(' ', 2)[0]
if( tymap[ty] )
@@ -186,7 +253,7 @@ module Fiddle
def split_arguments(arguments, sep=',')
return [] if arguments.strip == 'void'
- arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+)(?:#{sep}\s*|$)/).collect {|m| m[0]}
+ arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+|\.\.\.)(?:#{sep}\s*|\z)/).collect {|m| m[0]}
end
def compact(signature)
diff --git a/ext/fiddle/lib/fiddle/function.rb b/ext/fiddle/lib/fiddle/function.rb
index dd5e04e417..0f9913adeb 100644
--- a/ext/fiddle/lib/fiddle/function.rb
+++ b/ext/fiddle/lib/fiddle/function.rb
@@ -10,6 +10,11 @@ module Fiddle
# 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
diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb
index 178ebb8c76..09ffcef544 100644
--- a/ext/fiddle/lib/fiddle/import.rb
+++ b/ext/fiddle/lib/fiddle/import.rb
@@ -83,11 +83,7 @@ module Fiddle
when Importer
lib.handlers
else
- begin
- Fiddle.dlopen(lib)
- rescue DLError
- raise(DLError, "can't load #{lib}")
- end
+ Fiddle.dlopen(lib)
end
}.flatten()
@handler = CompositeHandler.new(handles)
@@ -121,6 +117,8 @@ module Fiddle
return SIZEOF_DOUBLE
when TYPE_VOIDP
return SIZEOF_VOIDP
+ when TYPE_CONST_STRING
+ return SIZEOF_CONST_STRING
else
if defined?(TYPE_LONG_LONG) and
ty == TYPE_LONG_LONG
diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb
index 7c0dedb39f..a766eba83b 100644
--- a/ext/fiddle/lib/fiddle/struct.rb
+++ b/ext/fiddle/lib/fiddle/struct.rb
@@ -4,15 +4,72 @@ require 'fiddle/value'
require 'fiddle/pack'
module Fiddle
- # C struct shell
+ # A base class for objects representing a C structure
class CStruct
+ include Enumerable
+
# accessor to Fiddle::CStructEntity
def CStruct.entity_class
CStructEntity
end
+
+ def each
+ return enum_for(__function__) unless block_given?
+
+ self.class.members.each do |name,|
+ yield(self[name])
+ end
+ end
+
+ def each_pair
+ return enum_for(__function__) unless block_given?
+
+ self.class.members.each do |name,|
+ yield(name, self[name])
+ end
+ end
+
+ def to_h
+ hash = {}
+ each_pair do |name, value|
+ hash[name] = unstruct(value)
+ end
+ hash
+ end
+
+ def replace(another)
+ if another.nil?
+ self.class.members.each do |name,|
+ self[name] = nil
+ end
+ elsif another.respond_to?(:each_pair)
+ another.each_pair do |name, value|
+ self[name] = value
+ end
+ else
+ another.each do |name, value|
+ self[name] = value
+ end
+ end
+ self
+ end
+
+ private
+ def unstruct(value)
+ case value
+ when CStruct
+ value.to_h
+ when Array
+ value.collect do |v|
+ unstruct(v)
+ end
+ else
+ value
+ end
+ end
end
- # C union shell
+ # A base class for objects representing a C union
class CUnion
# accessor to Fiddle::CUnionEntity
def CUnion.entity_class
@@ -20,6 +77,41 @@ module Fiddle
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
@@ -35,7 +127,7 @@ module Fiddle
# Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
# easy-to-use manner.
#
- # Example:
+ # Examples:
#
# require 'fiddle/struct'
# require 'fiddle/cparser'
@@ -46,47 +138,98 @@ module Fiddle
#
# MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members)
#
- # obj = MyStruct.allocate
+ # MyStruct.malloc(Fiddle::RUBY_FREE) do |obj|
+ # ...
+ # end
+ #
+ # obj = MyStruct.malloc(Fiddle::RUBY_FREE)
+ # begin
+ # ...
+ # ensure
+ # obj.call_free
+ # end
+ #
+ # obj = MyStruct.malloc
+ # begin
+ # ...
+ # ensure
+ # Fiddle.free obj.to_ptr
+ # end
#
def create(klass, types, members)
new_class = Class.new(klass){
- define_method(:initialize){|addr|
- @entity = klass.entity_class.new(addr, types)
+ define_method(:initialize){|addr, func = nil|
+ if addr.is_a?(self.class.entity_class)
+ @entity = addr
+ else
+ @entity = self.class.entity_class.new(addr, types, func)
+ end
@entity.assign_names(members)
}
+ define_method(:[]) { |*args| @entity.send(:[], *args) }
+ define_method(:[]=) { |*args| @entity.send(:[]=, *args) }
define_method(:to_ptr){ @entity }
define_method(:to_i){ @entity.to_i }
+ define_singleton_method(:types) { types }
+ define_singleton_method(:members) { members }
members.each{|name|
+ name = name[0] if name.is_a?(Array) # name is a nested struct
+ next if method_defined?(name)
define_method(name){ @entity[name] }
define_method(name + "="){|val| @entity[name] = val }
}
- }
- size = klass.entity_class.size(types)
- new_class.module_eval(<<-EOS, __FILE__, __LINE__+1)
- def new_class.size()
- #{size}
+ 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
- def new_class.malloc()
- addr = Fiddle.malloc(#{size})
- new(addr)
- end
- EOS
+ }
return new_class
end
module_function :create
end
- # A C struct wrapper
+ # A pointer to a C structure
class CStructEntity < Fiddle::Pointer
include PackInfo
include ValueUtil
+ def CStructEntity.alignment(types)
+ max = 1
+ types.each do |type, count = 1|
+ if type.respond_to?(:entity_class)
+ n = type.alignment
+ else
+ n = ALIGN_MAP[type]
+ end
+ max = n if n > max
+ end
+ max
+ end
+
# Allocates a C struct with the +types+ provided.
#
- # When the instance is garbage collected, the C function +func+ is called.
- def CStructEntity.malloc(types, func = nil)
- addr = Fiddle.malloc(CStructEntity.size(types))
- CStructEntity.new(addr, types, func)
+ # See Fiddle::Pointer.malloc for memory management issues.
+ def CStructEntity.malloc(types, func = nil, size = size(types), &block)
+ if block_given?
+ super(size, func) do |struct|
+ struct.set_ctypes types
+ yield struct
+ end
+ else
+ struct = super(size, func)
+ struct.set_ctypes types
+ struct
+ end
end
# Returns the offset for the packed sizes for the given +types+.
@@ -102,9 +245,15 @@ module Fiddle
max_align = types.map { |type, count = 1|
last_offset = offset
- align = PackInfo::ALIGN_MAP[type]
+ if type.respond_to?(:entity_class)
+ align = type.alignment
+ type_size = type.size
+ else
+ align = PackInfo::ALIGN_MAP[type]
+ type_size = PackInfo::SIZE_MAP[type]
+ end
offset = PackInfo.align(last_offset, align) +
- (PackInfo::SIZE_MAP[type] * count)
+ (type_size * count)
align
}.max
@@ -118,13 +267,37 @@ module Fiddle
#
# See also Fiddle::Pointer.new
def initialize(addr, types, func = nil)
+ if func && addr.is_a?(Pointer) && addr.free
+ raise ArgumentError, 'free function specified on both underlying struct Pointer and when creating a CStructEntity - who do you want to free this?'
+ end
set_ctypes(types)
super(addr, @size, func)
end
# Set the names of the +members+ in this C struct
def assign_names(members)
- @members = members
+ @members = []
+ @nested_structs = {}
+ members.each_with_index do |member, index|
+ if member.is_a?(Array) # nested struct
+ member_name = member[0]
+ struct_type, struct_count = @ctypes[index]
+ if struct_count.nil?
+ struct = struct_type.new(to_i + @offset[index])
+ else
+ structs = struct_count.times.map do |i|
+ struct_type.new(to_i + @offset[index] + i * struct_type.size)
+ end
+ struct = StructArray.new(to_i + @offset[index],
+ struct_type,
+ structs)
+ end
+ @nested_structs[member_name] = struct
+ else
+ member_name = member
+ end
+ @members << member_name
+ end
end
# Calculates the offsets and sizes for the given +types+ in the struct.
@@ -135,12 +308,18 @@ module Fiddle
max_align = types.map { |type, count = 1|
orig_offset = offset
- align = ALIGN_MAP[type]
+ if type.respond_to?(:entity_class)
+ align = type.alignment
+ type_size = type.size
+ else
+ align = ALIGN_MAP[type]
+ type_size = SIZE_MAP[type]
+ end
offset = PackInfo.align(orig_offset, align)
@offset << offset
- offset += (SIZE_MAP[type] * count)
+ offset += (type_size * count)
align
}.max
@@ -148,15 +327,34 @@ module Fiddle
@size = PackInfo.align(offset, max_align)
end
- # Fetch struct member +name+
- def [](name)
+ # Fetch struct member +name+ if only one argument is specified. If two
+ # arguments are specified, the first is an offset and the second is a
+ # length and this method returns the string of +length+ bytes beginning at
+ # +offset+.
+ #
+ # Examples:
+ #
+ # my_struct = struct(['int id']).malloc
+ # my_struct.id = 1
+ # my_struct['id'] # => 1
+ # my_struct[0, 4] # => "\x01\x00\x00\x00".b
+ #
+ def [](*args)
+ return super(*args) if args.size > 1
+ name = args[0]
idx = @members.index(name)
if( idx.nil? )
raise(ArgumentError, "no such member: #{name}")
end
ty = @ctypes[idx]
if( ty.is_a?(Array) )
- r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1])
+ if ty.first.respond_to?(:entity_class)
+ return @nested_structs[name]
+ else
+ r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1])
+ end
+ elsif ty.respond_to?(:entity_class)
+ return @nested_structs[name]
else
r = super(@offset[idx], SIZE_MAP[ty.abs])
end
@@ -176,14 +374,44 @@ module Fiddle
if( ty.is_a?(Integer) && (ty < 0) )
return unsigned_value(val, ty)
elsif( ty.is_a?(Array) && (ty[0] < 0) )
- return val.collect{|v| unsigned_value(v,ty[0])}
+ return StructArray.new(self + @offset[idx], ty[0], val)
else
return val
end
end
- # Set struct member +name+, to value +val+
- def []=(name, val)
+ # Set struct member +name+, to value +val+. If more arguments are
+ # specified, writes the string of bytes to the memory at the given
+ # +offset+ and +length+.
+ #
+ # Examples:
+ #
+ # my_struct = struct(['int id']).malloc
+ # my_struct['id'] = 1
+ # my_struct[0, 4] = "\x01\x00\x00\x00".b
+ # my_struct.id # => 1
+ #
+ def []=(*args)
+ return super(*args) if args.size > 2
+ name, val = *args
+ name = name.to_s if name.is_a?(Symbol)
+ nested_struct = @nested_structs[name]
+ if nested_struct
+ if nested_struct.is_a?(StructArray)
+ if val.nil?
+ nested_struct.each do |s|
+ s.replace(nil)
+ end
+ else
+ val.each_with_index do |v, i|
+ nested_struct[i] = v
+ end
+ end
+ else
+ nested_struct.replace(val)
+ end
+ return val
+ end
idx = @members.index(name)
if( idx.nil? )
raise(ArgumentError, "no such member: #{name}")
@@ -202,23 +430,16 @@ module Fiddle
end
end
+ undef_method :size=
def to_s() # :nodoc:
super(@size)
end
end
- # A C union wrapper
+ # A pointer to a C union
class CUnionEntity < CStructEntity
include PackInfo
- # Allocates a C union the +types+ provided.
- #
- # When the instance is garbage collected, the C function +func+ is called.
- def CUnionEntity.malloc(types, func=nil)
- addr = Fiddle.malloc(CUnionEntity.size(types))
- CUnionEntity.new(addr, types, func)
- end
-
# Returns the size needed for the union with the given +types+.
#
# Fiddle::CUnionEntity.size(
@@ -228,7 +449,11 @@ module Fiddle
# Fiddle::TYPE_VOIDP ]) #=> 8
def CUnionEntity.size(types)
types.map { |type, count = 1|
- PackInfo::SIZE_MAP[type] * count
+ if type.respond_to?(:entity_class)
+ type.size * count
+ else
+ PackInfo::SIZE_MAP[type] * count
+ end
}.max
end
@@ -241,4 +466,3 @@ module Fiddle
end
end
end
-
diff --git a/ext/fiddle/lib/fiddle/version.rb b/ext/fiddle/lib/fiddle/version.rb
new file mode 100644
index 0000000000..a699371ee4
--- /dev/null
+++ b/ext/fiddle/lib/fiddle/version.rb
@@ -0,0 +1,3 @@
+module Fiddle
+ VERSION = "1.0.8"
+end
diff --git a/ext/fiddle/memory_view.c b/ext/fiddle/memory_view.c
new file mode 100644
index 0000000000..172b1f18fc
--- /dev/null
+++ b/ext/fiddle/memory_view.c
@@ -0,0 +1,254 @@
+#include <stdbool.h>
+#include <ruby/ruby.h>
+
+#ifdef HAVE_RUBY_MEMORY_VIEW_H
+# include <ruby/memory_view.h>
+#endif
+
+#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
+
+#include <fiddle.h>
+
+#ifdef FIDDLE_MEMORY_VIEW
+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_free(void *ptr)
+{
+ struct memview_data *data = ptr;
+ rb_memory_view_release(&data->view);
+ if (data->members)
+ xfree(data->members);
+ 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->members = NULL;
+ data->n_members = 0;
+ return obj;
+}
+
+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)) {
+ 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);
+}
+
+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_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
+ 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);
+}
+
+#endif /* FIDDLE_MEMORY_VIEW */
diff --git a/ext/fiddle/pinned.c b/ext/fiddle/pinned.c
new file mode 100644
index 0000000000..019a3020e2
--- /dev/null
+++ b/ext/fiddle/pinned.c
@@ -0,0 +1,123 @@
+#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
index 117cc9b826..c5fb442aec 100644
--- a/ext/fiddle/pointer.c
+++ b/ext/fiddle/pointer.c
@@ -2,8 +2,14 @@
* $Id$
*/
+#include <stdbool.h>
#include <ruby/ruby.h>
#include <ruby/io.h>
+
+#ifdef HAVE_RUBY_MEMORY_VIEW_H
+# include <ruby/memory_view.h>
+#endif
+
#include <ctype.h>
#include <fiddle.h>
@@ -24,6 +30,7 @@ struct ptr_data {
void *ptr;
long size;
freefunc_t free;
+ bool freed;
VALUE wrap[2];
};
@@ -57,14 +64,19 @@ fiddle_ptr_mark(void *ptr)
}
static void
-fiddle_ptr_free(void *ptr)
+fiddle_ptr_free_ptr(void *ptr)
{
struct ptr_data *data = ptr;
- if (data->ptr) {
- if (data->free) {
- (*(data->free))(data->ptr);
- }
+ if (data->ptr && data->free && !data->freed) {
+ data->freed = true;
+ (*(data->free))(data->ptr);
}
+}
+
+static void
+fiddle_ptr_free(void *ptr)
+{
+ fiddle_ptr_free_ptr(ptr);
xfree(ptr);
}
@@ -80,6 +92,38 @@ static const rb_data_type_t fiddle_ptr_data_type = {
{fiddle_ptr_mark, fiddle_ptr_free, fiddle_ptr_memsize,},
};
+#ifdef FIDDLE_MEMORY_VIEW
+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)
{
@@ -89,6 +133,7 @@ rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func)
val = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data);
data->ptr = ptr;
data->free = func;
+ data->freed = false;
data->size = size;
return val;
@@ -101,13 +146,13 @@ rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func)
}
static VALUE
-rb_fiddle_ptr_malloc(long size, freefunc_t func)
+rb_fiddle_ptr_malloc(VALUE klass, long size, freefunc_t func)
{
void *ptr;
ptr = ruby_xmalloc((size_t)size);
memset(ptr,0,(size_t)size);
- return rb_fiddle_ptr_new(ptr, size, func);
+ return rb_fiddle_ptr_new2(klass, ptr, size, func);
}
static void *
@@ -140,6 +185,7 @@ rb_fiddle_ptr_s_allocate(VALUE klass)
data->ptr = 0;
data->size = 0;
data->free = 0;
+ data->freed = false;
return obj;
}
@@ -191,16 +237,53 @@ rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self)
return Qnil;
}
+static VALUE
+rb_fiddle_ptr_call_free(VALUE self);
+
/*
* call-seq:
- *
* Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance
+ * Fiddle::Pointer.malloc(size, freefunc) { |pointer| ... } => ...
+ *
+ * == Examples
+ *
+ * # Automatically freeing the pointer when the block is exited - recommended
+ * Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) do |pointer|
+ * ...
+ * end
+ *
+ * # Manually freeing but relying on the garbage collector otherwise
+ * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
+ * ...
+ * pointer.call_free
+ *
+ * # Relying on the garbage collector - may lead to unlimited memory allocated before freeing any, but safe
+ * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
+ * ...
+ *
+ * # Only manually freeing
+ * pointer = Fiddle::Pointer.malloc(size)
+ * begin
+ * ...
+ * ensure
+ * Fiddle.free pointer
+ * end
+ *
+ * # No free function and no call to free - the native memory will leak if the pointer is garbage collected
+ * pointer = Fiddle::Pointer.malloc(size)
+ * ...
*
* Allocate +size+ bytes of memory and associate it with an optional
- * +freefunc+ that will be called when the pointer is garbage collected.
+ * +freefunc+.
+ *
+ * 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.
*
- * +freefunc+ must be an address pointing to a function or an instance of
- * Fiddle::Function
+ * If a +freefunc+ is supplied it will be called once, when the pointer is
+ * garbage collected or when the block is left if a block is supplied or
+ * when the user calls +call_free+, whichever happens first. +freefunc+ must be
+ * an address pointing to a function or an instance of +Fiddle::Function+.
*/
static VALUE
rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
@@ -222,10 +305,17 @@ rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
rb_bug("rb_fiddle_ptr_s_malloc");
}
- obj = rb_fiddle_ptr_malloc(s,f);
+ obj = rb_fiddle_ptr_malloc(klass, s,f);
if (wrap) RPTR_DATA(obj)->wrap[1] = wrap;
- return obj;
+ if (rb_block_given_p()) {
+ if (!f) {
+ rb_raise(rb_eArgError, "a free function must be supplied to Fiddle::Pointer.malloc when it is called with a block");
+ }
+ return rb_ensure(rb_yield, obj, rb_fiddle_ptr_call_free, obj);
+ } else {
+ return obj;
+ }
}
/*
@@ -351,6 +441,34 @@ rb_fiddle_ptr_free_get(VALUE self)
}
/*
+ * 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
@@ -541,7 +659,7 @@ rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
struct ptr_data *data;
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
+ if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
case 1:
offset = NUM2ULONG(arg0);
@@ -579,7 +697,7 @@ rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self)
struct ptr_data *data;
TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleError, "NULL pointer dereference");
+ if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
case 2:
offset = NUM2ULONG(arg0);
@@ -660,7 +778,7 @@ rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
wrap = 0;
}
else{
- rb_raise(rb_eFiddleError, "to_ptr should return a Fiddle::Pointer object");
+ rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object");
}
}
else{
@@ -691,6 +809,8 @@ Init_fiddle_pointer(void)
rb_define_method(rb_cPointer, "initialize", rb_fiddle_ptr_initialize, -1);
rb_define_method(rb_cPointer, "free=", rb_fiddle_ptr_free_set, 1);
rb_define_method(rb_cPointer, "free", rb_fiddle_ptr_free_get, 0);
+ rb_define_method(rb_cPointer, "call_free", rb_fiddle_ptr_call_free, 0);
+ rb_define_method(rb_cPointer, "freed?", rb_fiddle_ptr_freed_p, 0);
rb_define_method(rb_cPointer, "to_i", rb_fiddle_ptr_to_i, 0);
rb_define_method(rb_cPointer, "to_int", rb_fiddle_ptr_to_i, 0);
rb_define_method(rb_cPointer, "to_value", rb_fiddle_ptr_to_value, 0);
@@ -712,6 +832,10 @@ Init_fiddle_pointer(void)
rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0);
rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1);
+#ifdef FIDDLE_MEMORY_VIEW
+ rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry);
+#endif
+
/* Document-const: NULL
*
* A NULL pointer
diff --git a/ext/fiddle/win32/fficonfig.h b/ext/fiddle/win32/fficonfig.h
index 776808159c..776808159c 100755..100644
--- a/ext/fiddle/win32/fficonfig.h
+++ b/ext/fiddle/win32/fficonfig.h
diff --git a/ext/fiddle/win32/libffi-config.rb b/ext/fiddle/win32/libffi-config.rb
index 6abc9b2c02..985fc29d36 100755
--- a/ext/fiddle/win32/libffi-config.rb
+++ b/ext/fiddle/win32/libffi-config.rb
@@ -32,7 +32,7 @@ IO.foreach("#{srcdir}/configure.ac") do |line|
end
end
-builddir = srcdir == "." ? enable['builddir'] : "."
+builddir = srcdir == "." ? (enable['builddir'] || ".") : "."
conf['TARGET'] = /^x64/ =~ host ? "X86_WIN64" : "X86_WIN32"
FileUtils.mkdir_p([builddir, "#{builddir}/include", "#{builddir}/src/x86"])
diff --git a/ext/fiddle/win32/libffi.mk.tmpl b/ext/fiddle/win32/libffi.mk.tmpl
index 2a16e8efec..2a16e8efec 100755..100644
--- a/ext/fiddle/win32/libffi.mk.tmpl
+++ b/ext/fiddle/win32/libffi.mk.tmpl
diff --git a/ext/gdbm/depend b/ext/gdbm/depend
index 33635bc099..c3730c0953 100644
--- a/ext/gdbm/depend
+++ b/ext/gdbm/depend
@@ -2,8 +2,157 @@
gdbm.o: $(RUBY_EXTCONF_H)
gdbm.o: $(arch_hdrdir)/ruby/config.h
gdbm.o: $(hdrdir)/ruby.h
+gdbm.o: $(hdrdir)/ruby/internal/anyargs.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+gdbm.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+gdbm.o: $(hdrdir)/ruby/internal/assume.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/artificial.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/cold.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/const.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/error.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/format.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/noalias.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/noinline.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/pure.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/restrict.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/warning.h
+gdbm.o: $(hdrdir)/ruby/internal/attr/weakref.h
+gdbm.o: $(hdrdir)/ruby/internal/cast.h
+gdbm.o: $(hdrdir)/ruby/internal/compiler_is.h
+gdbm.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+gdbm.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+gdbm.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+gdbm.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+gdbm.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+gdbm.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+gdbm.o: $(hdrdir)/ruby/internal/compiler_since.h
+gdbm.o: $(hdrdir)/ruby/internal/config.h
+gdbm.o: $(hdrdir)/ruby/internal/constant_p.h
+gdbm.o: $(hdrdir)/ruby/internal/core.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rarray.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rbasic.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rbignum.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rclass.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rdata.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rfile.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rhash.h
+gdbm.o: $(hdrdir)/ruby/internal/core/robject.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rregexp.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rstring.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rstruct.h
+gdbm.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+gdbm.o: $(hdrdir)/ruby/internal/ctype.h
+gdbm.o: $(hdrdir)/ruby/internal/dllexport.h
+gdbm.o: $(hdrdir)/ruby/internal/dosish.h
+gdbm.o: $(hdrdir)/ruby/internal/error.h
+gdbm.o: $(hdrdir)/ruby/internal/eval.h
+gdbm.o: $(hdrdir)/ruby/internal/event.h
+gdbm.o: $(hdrdir)/ruby/internal/fl_type.h
+gdbm.o: $(hdrdir)/ruby/internal/gc.h
+gdbm.o: $(hdrdir)/ruby/internal/glob.h
+gdbm.o: $(hdrdir)/ruby/internal/globals.h
+gdbm.o: $(hdrdir)/ruby/internal/has/attribute.h
+gdbm.o: $(hdrdir)/ruby/internal/has/builtin.h
+gdbm.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+gdbm.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+gdbm.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+gdbm.o: $(hdrdir)/ruby/internal/has/extension.h
+gdbm.o: $(hdrdir)/ruby/internal/has/feature.h
+gdbm.o: $(hdrdir)/ruby/internal/has/warning.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/array.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/bignum.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/class.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/compar.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/complex.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/cont.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/dir.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/enum.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/error.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/eval.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/file.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/gc.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/hash.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/io.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/load.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/marshal.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/numeric.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/object.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/parse.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/proc.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/process.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/random.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/range.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/rational.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/re.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/ruby.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/select.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/signal.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/string.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/struct.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/thread.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/time.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/variable.h
+gdbm.o: $(hdrdir)/ruby/internal/intern/vm.h
+gdbm.o: $(hdrdir)/ruby/internal/interpreter.h
+gdbm.o: $(hdrdir)/ruby/internal/iterator.h
+gdbm.o: $(hdrdir)/ruby/internal/memory.h
+gdbm.o: $(hdrdir)/ruby/internal/method.h
+gdbm.o: $(hdrdir)/ruby/internal/module.h
+gdbm.o: $(hdrdir)/ruby/internal/newobj.h
+gdbm.o: $(hdrdir)/ruby/internal/rgengc.h
+gdbm.o: $(hdrdir)/ruby/internal/scan_args.h
+gdbm.o: $(hdrdir)/ruby/internal/special_consts.h
+gdbm.o: $(hdrdir)/ruby/internal/static_assert.h
+gdbm.o: $(hdrdir)/ruby/internal/stdalign.h
+gdbm.o: $(hdrdir)/ruby/internal/stdbool.h
+gdbm.o: $(hdrdir)/ruby/internal/symbol.h
+gdbm.o: $(hdrdir)/ruby/internal/token_paste.h
+gdbm.o: $(hdrdir)/ruby/internal/value.h
+gdbm.o: $(hdrdir)/ruby/internal/value_type.h
+gdbm.o: $(hdrdir)/ruby/internal/variable.h
+gdbm.o: $(hdrdir)/ruby/internal/warning_push.h
+gdbm.o: $(hdrdir)/ruby/internal/xmalloc.h
gdbm.o: $(hdrdir)/ruby/assert.h
gdbm.o: $(hdrdir)/ruby/backward.h
+gdbm.o: $(hdrdir)/ruby/backward/2/assume.h
+gdbm.o: $(hdrdir)/ruby/backward/2/attributes.h
+gdbm.o: $(hdrdir)/ruby/backward/2/bool.h
+gdbm.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+gdbm.o: $(hdrdir)/ruby/backward/2/inttypes.h
+gdbm.o: $(hdrdir)/ruby/backward/2/limits.h
+gdbm.o: $(hdrdir)/ruby/backward/2/long_long.h
+gdbm.o: $(hdrdir)/ruby/backward/2/stdalign.h
+gdbm.o: $(hdrdir)/ruby/backward/2/stdarg.h
gdbm.o: $(hdrdir)/ruby/defines.h
gdbm.o: $(hdrdir)/ruby/intern.h
gdbm.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/gdbm/gdbm.gemspec b/ext/gdbm/gdbm.gemspec
index da074b0180..3ecb3121fe 100644
--- a/ext/gdbm/gdbm.gemspec
+++ b/ext/gdbm/gdbm.gemspec
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
spec.summary = "Ruby extension for GNU dbm."
spec.description = "Ruby extension for GNU dbm."
spec.homepage = "https://github.com/ruby/gdbm"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.files = ["ext/gdbm/extconf.rb", "ext/gdbm/gdbm.c"]
spec.bindir = "exe"
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
index 9baad2bf17..2e2467036d 100644
--- a/ext/io/console/console.c
+++ b/ext/io/console/console.c
@@ -1,4 +1,4 @@
-/* -*- c-file-style: "ruby" -*- */
+/* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */
/*
* console IO module
*/
@@ -77,9 +77,15 @@ getattr(int fd, conmode *t)
static ID id_getc, id_console, id_close, id_min, id_time, id_intr;
#if ENABLE_IO_GETPASS
-static ID id_gets;
+static ID id_gets, id_chomp_bang;
#endif
+#ifdef HAVE_RB_SCHEDULER_TIMEOUT
+extern VALUE rb_scheduler_timeout(struct timeval *timeout);
+#endif
+
+#define sys_fail_fptr(fptr) rb_sys_fail_str((fptr)->pathv)
+
#ifndef HAVE_RB_F_SEND
static ID id___send__;
@@ -410,9 +416,9 @@ console_set_raw(int argc, VALUE *argv, VALUE io)
GetOpenFile(io, fptr);
fd = GetReadFD(fptr);
- if (!getattr(fd, &t)) rb_sys_fail(0);
+ if (!getattr(fd, &t)) sys_fail_fptr(fptr);
set_rawmode(&t, optp);
- if (!setattr(fd, &t)) rb_sys_fail(0);
+ if (!setattr(fd, &t)) sys_fail_fptr(fptr);
return io;
}
@@ -453,9 +459,9 @@ console_set_cooked(VALUE io)
GetOpenFile(io, fptr);
fd = GetReadFD(fptr);
- if (!getattr(fd, &t)) rb_sys_fail(0);
+ if (!getattr(fd, &t)) sys_fail_fptr(fptr);
set_cookedmode(&t, NULL);
- if (!setattr(fd, &t)) rb_sys_fail(0);
+ if (!setattr(fd, &t)) sys_fail_fptr(fptr);
return io;
}
@@ -508,28 +514,50 @@ console_getch(int argc, VALUE *argv, VALUE io)
rb_io_t *fptr;
VALUE str;
wint_t c;
- int w, len;
+ int len;
char buf[8];
wint_t wbuf[2];
+# ifndef HAVE_RB_IO_WAIT
struct timeval *to = NULL, tv;
+# else
+ VALUE timeout = Qnil;
+# endif
GetOpenFile(io, fptr);
if (optp) {
if (optp->vtime) {
+# ifndef HAVE_RB_IO_WAIT
to = &tv;
+# else
+ struct timeval tv;
+# endif
tv.tv_sec = optp->vtime / 10;
tv.tv_usec = (optp->vtime % 10) * 100000;
+# ifdef HAVE_RB_IO_WAIT
+ timeout = rb_scheduler_timeout(&tv);
+# endif
}
- if (optp->vmin != 1) {
- rb_warning("min option ignored");
+ switch (optp->vmin) {
+ case 1: /* default */
+ break;
+ case 0: /* return nil when timed out */
+ if (optp->vtime) break;
+ /* fallthru */
+ default:
+ rb_warning("min option larger than 1 ignored");
}
if (optp->intr) {
- w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
+# ifndef HAVE_RB_IO_WAIT
+ int w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to);
if (w < 0) rb_eof_error();
if (!(w & RB_WAITFD_IN)) return Qnil;
+# else
+ VALUE result = rb_io_wait(io, RUBY_IO_READABLE, timeout);
+ if (result == Qfalse) return Qnil;
+# endif
}
- else {
- rb_warning("vtime option ignored if intr flag is unset");
+ else if (optp->vtime) {
+ rb_warning("Non-zero vtime option ignored if intr flag is unset");
}
}
len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0);
@@ -590,12 +618,12 @@ console_set_echo(VALUE io, VALUE f)
GetOpenFile(io, fptr);
fd = GetReadFD(fptr);
- if (!getattr(fd, &t)) rb_sys_fail(0);
+ if (!getattr(fd, &t)) sys_fail_fptr(fptr);
if (RTEST(f))
set_echo(&t, NULL);
else
set_noecho(&t, NULL);
- if (!setattr(fd, &t)) rb_sys_fail(0);
+ if (!setattr(fd, &t)) sys_fail_fptr(fptr);
return io;
}
@@ -616,7 +644,7 @@ console_echo_p(VALUE io)
GetOpenFile(io, fptr);
fd = GetReadFD(fptr);
- if (!getattr(fd, &t)) rb_sys_fail(0);
+ if (!getattr(fd, &t)) sys_fail_fptr(fptr);
return echo_p(&t) ? Qtrue : Qfalse;
}
@@ -700,7 +728,7 @@ console_conmode_get(VALUE io)
GetOpenFile(io, fptr);
fd = GetReadFD(fptr);
- if (!getattr(fd, &t)) rb_sys_fail(0);
+ if (!getattr(fd, &t)) sys_fail_fptr(fptr);
return conmode_new(cConmode, &t);
}
@@ -724,7 +752,7 @@ console_conmode_set(VALUE io, VALUE mode)
r = *t;
GetOpenFile(io, fptr);
fd = GetReadFD(fptr);
- if (!setattr(fd, &r)) rb_sys_fail(0);
+ if (!setattr(fd, &r)) sys_fail_fptr(fptr);
return mode;
}
@@ -766,7 +794,7 @@ console_winsize(VALUE io)
GetOpenFile(io, fptr);
fd = GetWriteFD(fptr);
- if (!getwinsize(fd, &ws)) rb_sys_fail(0);
+ if (!getwinsize(fd, &ws)) sys_fail_fptr(fptr);
return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));
}
@@ -813,7 +841,7 @@ console_set_winsize(VALUE io, VALUE size)
SET(xpixel);
SET(ypixel);
#undef SET
- if (!setwinsize(fd, &ws)) rb_sys_fail(0);
+ if (!setwinsize(fd, &ws)) sys_fail_fptr(fptr);
#elif defined _WIN32
wh = (HANDLE)rb_w32_get_osfhandle(fd);
#define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
@@ -888,7 +916,7 @@ console_iflush(VALUE io)
GetOpenFile(io, fptr);
fd = GetReadFD(fptr);
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
- if (tcflush(fd, TCIFLUSH)) rb_sys_fail(0);
+ if (tcflush(fd, TCIFLUSH)) sys_fail_fptr(fptr);
#endif
(void)fd;
return io;
@@ -911,7 +939,7 @@ console_oflush(VALUE io)
GetOpenFile(io, fptr);
fd = GetWriteFD(fptr);
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
- if (tcflush(fd, TCOFLUSH)) rb_sys_fail(0);
+ if (tcflush(fd, TCOFLUSH)) sys_fail_fptr(fptr);
#endif
(void)fd;
return io;
@@ -938,11 +966,11 @@ console_ioflush(VALUE io)
fd1 = GetReadFD(fptr);
fd2 = GetWriteFD(fptr);
if (fd2 != -1 && fd1 != fd2) {
- if (tcflush(fd1, TCIFLUSH)) rb_sys_fail(0);
- if (tcflush(fd2, TCOFLUSH)) rb_sys_fail(0);
+ if (tcflush(fd1, TCIFLUSH)) sys_fail_fptr(fptr);
+ if (tcflush(fd2, TCOFLUSH)) sys_fail_fptr(fptr);
}
else {
- if (tcflush(fd1, TCIOFLUSH)) rb_sys_fail(0);
+ if (tcflush(fd1, TCIOFLUSH)) sys_fail_fptr(fptr);
}
#endif
return io;
@@ -961,7 +989,7 @@ console_beep(VALUE io)
MessageBeep(0);
#else
if (write(fd, "\a", 1) < 0)
- rb_sys_fail(0);
+ sys_fail_fptr(fptr);
#endif
return io;
}
@@ -1195,8 +1223,8 @@ console_key_pressed_p(VALUE io, VALUE k)
}
#else
struct query_args {
- const char *qstr;
- int opt;
+ char qstr[6];
+ unsigned char opt;
};
static int
@@ -1534,7 +1562,7 @@ static VALUE
str_chomp(VALUE str)
{
if (!NIL_P(str)) {
- str = rb_funcallv(str, rb_intern("chomp!"), 0, 0);
+ rb_funcallv(str, id_chomp_bang, 0, 0);
}
return str;
}
@@ -1546,6 +1574,10 @@ str_chomp(VALUE str)
* Reads and returns a line without echo back.
* Prints +prompt+ unless it is +nil+.
*
+ * The newline character that terminates the
+ * read line is removed from the returned string,
+ * see String#chomp!.
+ *
* You must require 'io/console' to use this method.
*/
static VALUE
@@ -1590,6 +1622,7 @@ Init_console(void)
id_getc = rb_intern("getc");
#if ENABLE_IO_GETPASS
id_gets = rb_intern("gets");
+ id_chomp_bang = rb_intern("chomp!");
#endif
id_console = rb_intern("console");
id_close = rb_intern("close");
diff --git a/ext/io/console/depend b/ext/io/console/depend
index 9c8f9cd22e..43c280d8ff 100644
--- a/ext/io/console/depend
+++ b/ext/io/console/depend
@@ -2,8 +2,157 @@
console.o: $(RUBY_EXTCONF_H)
console.o: $(arch_hdrdir)/ruby/config.h
console.o: $(hdrdir)/ruby.h
+console.o: $(hdrdir)/ruby/internal/anyargs.h
+console.o: $(hdrdir)/ruby/internal/arithmetic.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+console.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+console.o: $(hdrdir)/ruby/internal/assume.h
+console.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+console.o: $(hdrdir)/ruby/internal/attr/artificial.h
+console.o: $(hdrdir)/ruby/internal/attr/cold.h
+console.o: $(hdrdir)/ruby/internal/attr/const.h
+console.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+console.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+console.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+console.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+console.o: $(hdrdir)/ruby/internal/attr/error.h
+console.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+console.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+console.o: $(hdrdir)/ruby/internal/attr/format.h
+console.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+console.o: $(hdrdir)/ruby/internal/attr/noalias.h
+console.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+console.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+console.o: $(hdrdir)/ruby/internal/attr/noinline.h
+console.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+console.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+console.o: $(hdrdir)/ruby/internal/attr/pure.h
+console.o: $(hdrdir)/ruby/internal/attr/restrict.h
+console.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+console.o: $(hdrdir)/ruby/internal/attr/warning.h
+console.o: $(hdrdir)/ruby/internal/attr/weakref.h
+console.o: $(hdrdir)/ruby/internal/cast.h
+console.o: $(hdrdir)/ruby/internal/compiler_is.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+console.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+console.o: $(hdrdir)/ruby/internal/compiler_since.h
+console.o: $(hdrdir)/ruby/internal/config.h
+console.o: $(hdrdir)/ruby/internal/constant_p.h
+console.o: $(hdrdir)/ruby/internal/core.h
+console.o: $(hdrdir)/ruby/internal/core/rarray.h
+console.o: $(hdrdir)/ruby/internal/core/rbasic.h
+console.o: $(hdrdir)/ruby/internal/core/rbignum.h
+console.o: $(hdrdir)/ruby/internal/core/rclass.h
+console.o: $(hdrdir)/ruby/internal/core/rdata.h
+console.o: $(hdrdir)/ruby/internal/core/rfile.h
+console.o: $(hdrdir)/ruby/internal/core/rhash.h
+console.o: $(hdrdir)/ruby/internal/core/robject.h
+console.o: $(hdrdir)/ruby/internal/core/rregexp.h
+console.o: $(hdrdir)/ruby/internal/core/rstring.h
+console.o: $(hdrdir)/ruby/internal/core/rstruct.h
+console.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+console.o: $(hdrdir)/ruby/internal/ctype.h
+console.o: $(hdrdir)/ruby/internal/dllexport.h
+console.o: $(hdrdir)/ruby/internal/dosish.h
+console.o: $(hdrdir)/ruby/internal/error.h
+console.o: $(hdrdir)/ruby/internal/eval.h
+console.o: $(hdrdir)/ruby/internal/event.h
+console.o: $(hdrdir)/ruby/internal/fl_type.h
+console.o: $(hdrdir)/ruby/internal/gc.h
+console.o: $(hdrdir)/ruby/internal/glob.h
+console.o: $(hdrdir)/ruby/internal/globals.h
+console.o: $(hdrdir)/ruby/internal/has/attribute.h
+console.o: $(hdrdir)/ruby/internal/has/builtin.h
+console.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+console.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+console.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+console.o: $(hdrdir)/ruby/internal/has/extension.h
+console.o: $(hdrdir)/ruby/internal/has/feature.h
+console.o: $(hdrdir)/ruby/internal/has/warning.h
+console.o: $(hdrdir)/ruby/internal/intern/array.h
+console.o: $(hdrdir)/ruby/internal/intern/bignum.h
+console.o: $(hdrdir)/ruby/internal/intern/class.h
+console.o: $(hdrdir)/ruby/internal/intern/compar.h
+console.o: $(hdrdir)/ruby/internal/intern/complex.h
+console.o: $(hdrdir)/ruby/internal/intern/cont.h
+console.o: $(hdrdir)/ruby/internal/intern/dir.h
+console.o: $(hdrdir)/ruby/internal/intern/enum.h
+console.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+console.o: $(hdrdir)/ruby/internal/intern/error.h
+console.o: $(hdrdir)/ruby/internal/intern/eval.h
+console.o: $(hdrdir)/ruby/internal/intern/file.h
+console.o: $(hdrdir)/ruby/internal/intern/gc.h
+console.o: $(hdrdir)/ruby/internal/intern/hash.h
+console.o: $(hdrdir)/ruby/internal/intern/io.h
+console.o: $(hdrdir)/ruby/internal/intern/load.h
+console.o: $(hdrdir)/ruby/internal/intern/marshal.h
+console.o: $(hdrdir)/ruby/internal/intern/numeric.h
+console.o: $(hdrdir)/ruby/internal/intern/object.h
+console.o: $(hdrdir)/ruby/internal/intern/parse.h
+console.o: $(hdrdir)/ruby/internal/intern/proc.h
+console.o: $(hdrdir)/ruby/internal/intern/process.h
+console.o: $(hdrdir)/ruby/internal/intern/random.h
+console.o: $(hdrdir)/ruby/internal/intern/range.h
+console.o: $(hdrdir)/ruby/internal/intern/rational.h
+console.o: $(hdrdir)/ruby/internal/intern/re.h
+console.o: $(hdrdir)/ruby/internal/intern/ruby.h
+console.o: $(hdrdir)/ruby/internal/intern/select.h
+console.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+console.o: $(hdrdir)/ruby/internal/intern/signal.h
+console.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+console.o: $(hdrdir)/ruby/internal/intern/string.h
+console.o: $(hdrdir)/ruby/internal/intern/struct.h
+console.o: $(hdrdir)/ruby/internal/intern/thread.h
+console.o: $(hdrdir)/ruby/internal/intern/time.h
+console.o: $(hdrdir)/ruby/internal/intern/variable.h
+console.o: $(hdrdir)/ruby/internal/intern/vm.h
+console.o: $(hdrdir)/ruby/internal/interpreter.h
+console.o: $(hdrdir)/ruby/internal/iterator.h
+console.o: $(hdrdir)/ruby/internal/memory.h
+console.o: $(hdrdir)/ruby/internal/method.h
+console.o: $(hdrdir)/ruby/internal/module.h
+console.o: $(hdrdir)/ruby/internal/newobj.h
+console.o: $(hdrdir)/ruby/internal/rgengc.h
+console.o: $(hdrdir)/ruby/internal/scan_args.h
+console.o: $(hdrdir)/ruby/internal/special_consts.h
+console.o: $(hdrdir)/ruby/internal/static_assert.h
+console.o: $(hdrdir)/ruby/internal/stdalign.h
+console.o: $(hdrdir)/ruby/internal/stdbool.h
+console.o: $(hdrdir)/ruby/internal/symbol.h
+console.o: $(hdrdir)/ruby/internal/token_paste.h
+console.o: $(hdrdir)/ruby/internal/value.h
+console.o: $(hdrdir)/ruby/internal/value_type.h
+console.o: $(hdrdir)/ruby/internal/variable.h
+console.o: $(hdrdir)/ruby/internal/warning_push.h
+console.o: $(hdrdir)/ruby/internal/xmalloc.h
console.o: $(hdrdir)/ruby/assert.h
console.o: $(hdrdir)/ruby/backward.h
+console.o: $(hdrdir)/ruby/backward/2/assume.h
+console.o: $(hdrdir)/ruby/backward/2/attributes.h
+console.o: $(hdrdir)/ruby/backward/2/bool.h
+console.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+console.o: $(hdrdir)/ruby/backward/2/inttypes.h
+console.o: $(hdrdir)/ruby/backward/2/limits.h
+console.o: $(hdrdir)/ruby/backward/2/long_long.h
+console.o: $(hdrdir)/ruby/backward/2/stdalign.h
+console.o: $(hdrdir)/ruby/backward/2/stdarg.h
console.o: $(hdrdir)/ruby/defines.h
console.o: $(hdrdir)/ruby/encoding.h
console.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/io/console/extconf.rb b/ext/io/console/extconf.rb
index 3d7e75e2af..3efdd6e092 100644
--- a/ext/io/console/extconf.rb
+++ b/ext/io/console/extconf.rb
@@ -24,6 +24,9 @@ when true
# rb_funcallv: 2.1.0
# RARRAY_CONST_PTR: 2.1.0
# rb_sym2str: 2.2.0
+ if have_func("rb_scheduler_timeout")
+ have_func("rb_io_wait")
+ end
$defs << "-D""ENABLE_IO_GETPASS=1"
create_makefile("io/console") {|conf|
conf << "\n""VK_HEADER = #{vk_header}\n"
diff --git a/ext/io/console/io-console.gemspec b/ext/io/console/io-console.gemspec
index 814bd4ef7d..8a0df83b2c 100644
--- a/ext/io/console/io-console.gemspec
+++ b/ext/io/console/io-console.gemspec
@@ -1,11 +1,9 @@
# -*- ruby -*-
-_VERSION = "0.5.6"
-date = %w$Date:: $[1]
+_VERSION = "0.5.7"
Gem::Specification.new do |s|
s.name = "io-console"
s.version = _VERSION
- s.date = date
s.summary = "Console interface"
s.email = "nobu@ruby-lang.org"
s.description = "add console capabilities to IO instances."
@@ -23,5 +21,5 @@ Gem::Specification.new do |s|
lib/io/console/size.rb
]
s.extensions = %w[ext/io/console/extconf.rb]
- s.license = "BSD-2-Clause"
+ s.licenses = ["Ruby", "BSD-2-Clause"]
end
diff --git a/ext/io/nonblock/depend b/ext/io/nonblock/depend
index bea4a15e23..673f4161a7 100644
--- a/ext/io/nonblock/depend
+++ b/ext/io/nonblock/depend
@@ -2,8 +2,157 @@
nonblock.o: $(RUBY_EXTCONF_H)
nonblock.o: $(arch_hdrdir)/ruby/config.h
nonblock.o: $(hdrdir)/ruby.h
+nonblock.o: $(hdrdir)/ruby/internal/anyargs.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+nonblock.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+nonblock.o: $(hdrdir)/ruby/internal/assume.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/artificial.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/cold.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/const.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/error.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/format.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/noalias.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/noinline.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/pure.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/restrict.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/warning.h
+nonblock.o: $(hdrdir)/ruby/internal/attr/weakref.h
+nonblock.o: $(hdrdir)/ruby/internal/cast.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+nonblock.o: $(hdrdir)/ruby/internal/compiler_since.h
+nonblock.o: $(hdrdir)/ruby/internal/config.h
+nonblock.o: $(hdrdir)/ruby/internal/constant_p.h
+nonblock.o: $(hdrdir)/ruby/internal/core.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rarray.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rbasic.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rbignum.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rclass.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rdata.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rfile.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rhash.h
+nonblock.o: $(hdrdir)/ruby/internal/core/robject.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rregexp.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rstring.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rstruct.h
+nonblock.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+nonblock.o: $(hdrdir)/ruby/internal/ctype.h
+nonblock.o: $(hdrdir)/ruby/internal/dllexport.h
+nonblock.o: $(hdrdir)/ruby/internal/dosish.h
+nonblock.o: $(hdrdir)/ruby/internal/error.h
+nonblock.o: $(hdrdir)/ruby/internal/eval.h
+nonblock.o: $(hdrdir)/ruby/internal/event.h
+nonblock.o: $(hdrdir)/ruby/internal/fl_type.h
+nonblock.o: $(hdrdir)/ruby/internal/gc.h
+nonblock.o: $(hdrdir)/ruby/internal/glob.h
+nonblock.o: $(hdrdir)/ruby/internal/globals.h
+nonblock.o: $(hdrdir)/ruby/internal/has/attribute.h
+nonblock.o: $(hdrdir)/ruby/internal/has/builtin.h
+nonblock.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+nonblock.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+nonblock.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+nonblock.o: $(hdrdir)/ruby/internal/has/extension.h
+nonblock.o: $(hdrdir)/ruby/internal/has/feature.h
+nonblock.o: $(hdrdir)/ruby/internal/has/warning.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/array.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/bignum.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/class.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/compar.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/complex.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/cont.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/dir.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/enum.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/error.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/eval.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/file.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/gc.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/hash.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/io.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/load.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/marshal.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/numeric.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/object.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/parse.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/proc.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/process.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/random.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/range.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/rational.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/re.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/ruby.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/select.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/signal.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/string.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/struct.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/thread.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/time.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/variable.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/vm.h
+nonblock.o: $(hdrdir)/ruby/internal/interpreter.h
+nonblock.o: $(hdrdir)/ruby/internal/iterator.h
+nonblock.o: $(hdrdir)/ruby/internal/memory.h
+nonblock.o: $(hdrdir)/ruby/internal/method.h
+nonblock.o: $(hdrdir)/ruby/internal/module.h
+nonblock.o: $(hdrdir)/ruby/internal/newobj.h
+nonblock.o: $(hdrdir)/ruby/internal/rgengc.h
+nonblock.o: $(hdrdir)/ruby/internal/scan_args.h
+nonblock.o: $(hdrdir)/ruby/internal/special_consts.h
+nonblock.o: $(hdrdir)/ruby/internal/static_assert.h
+nonblock.o: $(hdrdir)/ruby/internal/stdalign.h
+nonblock.o: $(hdrdir)/ruby/internal/stdbool.h
+nonblock.o: $(hdrdir)/ruby/internal/symbol.h
+nonblock.o: $(hdrdir)/ruby/internal/token_paste.h
+nonblock.o: $(hdrdir)/ruby/internal/value.h
+nonblock.o: $(hdrdir)/ruby/internal/value_type.h
+nonblock.o: $(hdrdir)/ruby/internal/variable.h
+nonblock.o: $(hdrdir)/ruby/internal/warning_push.h
+nonblock.o: $(hdrdir)/ruby/internal/xmalloc.h
nonblock.o: $(hdrdir)/ruby/assert.h
nonblock.o: $(hdrdir)/ruby/backward.h
+nonblock.o: $(hdrdir)/ruby/backward/2/assume.h
+nonblock.o: $(hdrdir)/ruby/backward/2/attributes.h
+nonblock.o: $(hdrdir)/ruby/backward/2/bool.h
+nonblock.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+nonblock.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nonblock.o: $(hdrdir)/ruby/backward/2/limits.h
+nonblock.o: $(hdrdir)/ruby/backward/2/long_long.h
+nonblock.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nonblock.o: $(hdrdir)/ruby/backward/2/stdarg.h
nonblock.o: $(hdrdir)/ruby/defines.h
nonblock.o: $(hdrdir)/ruby/encoding.h
nonblock.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/io/nonblock/io-nonblock.gemspec b/ext/io/nonblock/io-nonblock.gemspec
new file mode 100644
index 0000000000..34d736650b
--- /dev/null
+++ b/ext/io/nonblock/io-nonblock.gemspec
@@ -0,0 +1,25 @@
+Gem::Specification.new do |spec|
+ spec.name = "io-nonblock"
+ spec.version = "0.1.0"
+ spec.authors = ["Nobu Nakada"]
+ spec.email = ["nobu@ruby-lang.org"]
+
+ spec.summary = %q{Enables non-blocking mode with IO class}
+ spec.description = %q{Enables non-blocking mode with IO class}
+ spec.homepage = "https://github.com/ruby/io-nonblock"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ %x[git ls-files -z].split("\x0").reject do |f|
+ f.match(%r{\A(?:test|spec|features)/|\A\.(?:git|travis)})
+ end
+ end
+ spec.extensions = %w[ext/io/nonblock/extconf.rb]
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/ext/io/wait/depend b/ext/io/wait/depend
index bbf1266aba..af227a8f19 100644
--- a/ext/io/wait/depend
+++ b/ext/io/wait/depend
@@ -2,8 +2,157 @@
wait.o: $(RUBY_EXTCONF_H)
wait.o: $(arch_hdrdir)/ruby/config.h
wait.o: $(hdrdir)/ruby.h
+wait.o: $(hdrdir)/ruby/internal/anyargs.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+wait.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+wait.o: $(hdrdir)/ruby/internal/assume.h
+wait.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+wait.o: $(hdrdir)/ruby/internal/attr/artificial.h
+wait.o: $(hdrdir)/ruby/internal/attr/cold.h
+wait.o: $(hdrdir)/ruby/internal/attr/const.h
+wait.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+wait.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+wait.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+wait.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+wait.o: $(hdrdir)/ruby/internal/attr/error.h
+wait.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+wait.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+wait.o: $(hdrdir)/ruby/internal/attr/format.h
+wait.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+wait.o: $(hdrdir)/ruby/internal/attr/noalias.h
+wait.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+wait.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+wait.o: $(hdrdir)/ruby/internal/attr/noinline.h
+wait.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+wait.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+wait.o: $(hdrdir)/ruby/internal/attr/pure.h
+wait.o: $(hdrdir)/ruby/internal/attr/restrict.h
+wait.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+wait.o: $(hdrdir)/ruby/internal/attr/warning.h
+wait.o: $(hdrdir)/ruby/internal/attr/weakref.h
+wait.o: $(hdrdir)/ruby/internal/cast.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+wait.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+wait.o: $(hdrdir)/ruby/internal/compiler_since.h
+wait.o: $(hdrdir)/ruby/internal/config.h
+wait.o: $(hdrdir)/ruby/internal/constant_p.h
+wait.o: $(hdrdir)/ruby/internal/core.h
+wait.o: $(hdrdir)/ruby/internal/core/rarray.h
+wait.o: $(hdrdir)/ruby/internal/core/rbasic.h
+wait.o: $(hdrdir)/ruby/internal/core/rbignum.h
+wait.o: $(hdrdir)/ruby/internal/core/rclass.h
+wait.o: $(hdrdir)/ruby/internal/core/rdata.h
+wait.o: $(hdrdir)/ruby/internal/core/rfile.h
+wait.o: $(hdrdir)/ruby/internal/core/rhash.h
+wait.o: $(hdrdir)/ruby/internal/core/robject.h
+wait.o: $(hdrdir)/ruby/internal/core/rregexp.h
+wait.o: $(hdrdir)/ruby/internal/core/rstring.h
+wait.o: $(hdrdir)/ruby/internal/core/rstruct.h
+wait.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+wait.o: $(hdrdir)/ruby/internal/ctype.h
+wait.o: $(hdrdir)/ruby/internal/dllexport.h
+wait.o: $(hdrdir)/ruby/internal/dosish.h
+wait.o: $(hdrdir)/ruby/internal/error.h
+wait.o: $(hdrdir)/ruby/internal/eval.h
+wait.o: $(hdrdir)/ruby/internal/event.h
+wait.o: $(hdrdir)/ruby/internal/fl_type.h
+wait.o: $(hdrdir)/ruby/internal/gc.h
+wait.o: $(hdrdir)/ruby/internal/glob.h
+wait.o: $(hdrdir)/ruby/internal/globals.h
+wait.o: $(hdrdir)/ruby/internal/has/attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/builtin.h
+wait.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+wait.o: $(hdrdir)/ruby/internal/has/extension.h
+wait.o: $(hdrdir)/ruby/internal/has/feature.h
+wait.o: $(hdrdir)/ruby/internal/has/warning.h
+wait.o: $(hdrdir)/ruby/internal/intern/array.h
+wait.o: $(hdrdir)/ruby/internal/intern/bignum.h
+wait.o: $(hdrdir)/ruby/internal/intern/class.h
+wait.o: $(hdrdir)/ruby/internal/intern/compar.h
+wait.o: $(hdrdir)/ruby/internal/intern/complex.h
+wait.o: $(hdrdir)/ruby/internal/intern/cont.h
+wait.o: $(hdrdir)/ruby/internal/intern/dir.h
+wait.o: $(hdrdir)/ruby/internal/intern/enum.h
+wait.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+wait.o: $(hdrdir)/ruby/internal/intern/error.h
+wait.o: $(hdrdir)/ruby/internal/intern/eval.h
+wait.o: $(hdrdir)/ruby/internal/intern/file.h
+wait.o: $(hdrdir)/ruby/internal/intern/gc.h
+wait.o: $(hdrdir)/ruby/internal/intern/hash.h
+wait.o: $(hdrdir)/ruby/internal/intern/io.h
+wait.o: $(hdrdir)/ruby/internal/intern/load.h
+wait.o: $(hdrdir)/ruby/internal/intern/marshal.h
+wait.o: $(hdrdir)/ruby/internal/intern/numeric.h
+wait.o: $(hdrdir)/ruby/internal/intern/object.h
+wait.o: $(hdrdir)/ruby/internal/intern/parse.h
+wait.o: $(hdrdir)/ruby/internal/intern/proc.h
+wait.o: $(hdrdir)/ruby/internal/intern/process.h
+wait.o: $(hdrdir)/ruby/internal/intern/random.h
+wait.o: $(hdrdir)/ruby/internal/intern/range.h
+wait.o: $(hdrdir)/ruby/internal/intern/rational.h
+wait.o: $(hdrdir)/ruby/internal/intern/re.h
+wait.o: $(hdrdir)/ruby/internal/intern/ruby.h
+wait.o: $(hdrdir)/ruby/internal/intern/select.h
+wait.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+wait.o: $(hdrdir)/ruby/internal/intern/signal.h
+wait.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+wait.o: $(hdrdir)/ruby/internal/intern/string.h
+wait.o: $(hdrdir)/ruby/internal/intern/struct.h
+wait.o: $(hdrdir)/ruby/internal/intern/thread.h
+wait.o: $(hdrdir)/ruby/internal/intern/time.h
+wait.o: $(hdrdir)/ruby/internal/intern/variable.h
+wait.o: $(hdrdir)/ruby/internal/intern/vm.h
+wait.o: $(hdrdir)/ruby/internal/interpreter.h
+wait.o: $(hdrdir)/ruby/internal/iterator.h
+wait.o: $(hdrdir)/ruby/internal/memory.h
+wait.o: $(hdrdir)/ruby/internal/method.h
+wait.o: $(hdrdir)/ruby/internal/module.h
+wait.o: $(hdrdir)/ruby/internal/newobj.h
+wait.o: $(hdrdir)/ruby/internal/rgengc.h
+wait.o: $(hdrdir)/ruby/internal/scan_args.h
+wait.o: $(hdrdir)/ruby/internal/special_consts.h
+wait.o: $(hdrdir)/ruby/internal/static_assert.h
+wait.o: $(hdrdir)/ruby/internal/stdalign.h
+wait.o: $(hdrdir)/ruby/internal/stdbool.h
+wait.o: $(hdrdir)/ruby/internal/symbol.h
+wait.o: $(hdrdir)/ruby/internal/token_paste.h
+wait.o: $(hdrdir)/ruby/internal/value.h
+wait.o: $(hdrdir)/ruby/internal/value_type.h
+wait.o: $(hdrdir)/ruby/internal/variable.h
+wait.o: $(hdrdir)/ruby/internal/warning_push.h
+wait.o: $(hdrdir)/ruby/internal/xmalloc.h
wait.o: $(hdrdir)/ruby/assert.h
wait.o: $(hdrdir)/ruby/backward.h
+wait.o: $(hdrdir)/ruby/backward/2/assume.h
+wait.o: $(hdrdir)/ruby/backward/2/attributes.h
+wait.o: $(hdrdir)/ruby/backward/2/bool.h
+wait.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+wait.o: $(hdrdir)/ruby/backward/2/inttypes.h
+wait.o: $(hdrdir)/ruby/backward/2/limits.h
+wait.o: $(hdrdir)/ruby/backward/2/long_long.h
+wait.o: $(hdrdir)/ruby/backward/2/stdalign.h
+wait.o: $(hdrdir)/ruby/backward/2/stdarg.h
wait.o: $(hdrdir)/ruby/defines.h
wait.o: $(hdrdir)/ruby/encoding.h
wait.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/io/wait/io-wait.gemspec b/ext/io/wait/io-wait.gemspec
new file mode 100644
index 0000000000..ec23699def
--- /dev/null
+++ b/ext/io/wait/io-wait.gemspec
@@ -0,0 +1,27 @@
+_VERSION = "0.2.0"
+
+Gem::Specification.new do |spec|
+ spec.name = "io-wait"
+ spec.version = _VERSION
+ spec.authors = ["Nobu Nakada"]
+ spec.email = ["nobu@ruby-lang.org"]
+
+ spec.summary = %q{Waits until IO is readable or writable without blocking.}
+ spec.description = %q{Waits until IO is readable or writable without blocking.}
+ spec.homepage = "https://github.com/ruby/io-wait"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject do |f|
+ f.match(%r{\A(?:test|spec|features)/|\A\.(?:git|travis)})
+ end
+ end
+ spec.extensions = %w[ext/io/wait/extconf.rb]
+ spec.bindir = "exe"
+ spec.executables = []
+ spec.require_paths = ["lib"]
+end
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index d846bba49e..512e4f6a80 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -1,3 +1,4 @@
+/* -*- c-file-style: "ruby"; indent-tabs-mode: t -*- */
/**********************************************************************
io/wait.c -
@@ -39,35 +40,6 @@
#define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
#endif
-static VALUE io_ready_p _((VALUE io));
-static VALUE io_wait_readable _((int argc, VALUE *argv, VALUE io));
-static VALUE io_wait_writable _((int argc, VALUE *argv, VALUE io));
-void Init_wait _((void));
-
-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);
-}
-
/*
* call-seq:
* io.nread -> int
@@ -79,13 +51,12 @@ wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv)
static VALUE
io_nread(VALUE io)
{
- rb_io_t *fptr;
- int len;
+ rb_io_t *fptr = NULL;
ioctl_arg n;
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
- len = rb_io_read_pending(fptr);
+ int len = rb_io_read_pending(fptr);
if (len > 0) return INT2FIX(len);
if (!FIONREAD_POSSIBLE_P(fptr->fd)) return INT2FIX(0);
if (ioctl(fptr->fd, FIONREAD, &n)) return INT2FIX(0);
@@ -93,76 +64,114 @@ io_nread(VALUE io)
return INT2FIX(0);
}
+static VALUE
+io_wait_event(VALUE io, int event, VALUE timeout)
+{
+ VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout);
+
+ if (!RB_TEST(result)) {
+ return Qnil;
+ }
+
+ int mask = RB_NUM2INT(result);
+
+ if (mask & event) {
+ return io;
+ }
+ else {
+ return Qfalse;
+ }
+}
+
/*
* call-seq:
* io.ready? -> true or false
*
- * Returns true if input available without blocking, or false.
+ * Returns +true+ if input available without blocking, or +false+.
*/
static VALUE
io_ready_p(VALUE io)
{
rb_io_t *fptr;
- struct timeval tv = {0, 0};
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
if (rb_io_read_pending(fptr)) return Qtrue;
- if (wait_for_single_fd(fptr, RB_WAITFD_IN, &tv))
- return Qtrue;
- return Qfalse;
+
+ return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0));
}
/*
* call-seq:
- * io.wait_readable -> IO, true or nil
- * io.wait_readable(timeout) -> IO, true or nil
+ * io.wait_readable -> true or false
+ * io.wait_readable(timeout) -> true or false
*
- * Waits until IO is readable without blocking and returns +self+, or
- * +nil+ when times out.
+ * Waits until IO is readable and returns +true+, or
+ * +false+ when times out.
* Returns +true+ immediately when buffered data is available.
*/
static VALUE
io_wait_readable(int argc, VALUE *argv, VALUE io)
{
- rb_io_t *fptr;
- struct timeval timerec;
- struct timeval *tv;
+ rb_io_t *fptr = NULL;
- GetOpenFile(io, fptr);
+ RB_IO_POINTER(io, fptr);
rb_io_check_readable(fptr);
- tv = get_timeout(argc, argv, &timerec);
+
if (rb_io_read_pending(fptr)) return Qtrue;
- if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) {
- return io;
- }
- return Qnil;
+
+ rb_check_arity(argc, 0, 1);
+ VALUE timeout = (argc == 1 ? argv[0] : Qnil);
+
+ return io_wait_event(io, RUBY_IO_READABLE, timeout);
}
/*
* call-seq:
- * io.wait_writable -> IO
- * io.wait_writable(timeout) -> IO or nil
+ * io.wait_writable -> true or false
+ * io.wait_writable(timeout) -> true or false
*
- * Waits until IO is writable without blocking and returns +self+ or
- * +nil+ when times out.
+ * Waits until IO is writable and returns +true+ or
+ * +false+ when times out.
*/
static VALUE
io_wait_writable(int argc, VALUE *argv, VALUE io)
{
- rb_io_t *fptr;
- struct timeval timerec;
- struct timeval *tv;
+ rb_io_t *fptr = NULL;
- GetOpenFile(io, fptr);
+ RB_IO_POINTER(io, fptr);
rb_io_check_writable(fptr);
- tv = get_timeout(argc, argv, &timerec);
- if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) {
- return io;
- }
- return Qnil;
+
+ rb_check_arity(argc, 0, 1);
+ VALUE timeout = (argc == 1 ? argv[0] : Qnil);
+
+ return io_wait_event(io, RUBY_IO_WRITABLE, timeout);
+}
+
+/*
+ * call-seq:
+ * io.wait_priority -> true or false
+ * io.wait_priority(timeout) -> true or false
+ *
+ * Waits until IO is priority and returns +true+ or
+ * +false+ when times out.
+ */
+static VALUE
+io_wait_priority(int argc, VALUE *argv, VALUE io)
+{
+ rb_io_t *fptr = NULL;
+
+ RB_IO_POINTER(io, fptr);
+ rb_io_check_readable(fptr);
+
+ if (rb_io_read_pending(fptr)) return Qtrue;
+
+ rb_check_arity(argc, 0, 1);
+ VALUE timeout = argc == 1 ? argv[0] : Qnil;
+
+ return io_wait_event(io, RUBY_IO_PRIORITY, timeout);
}
static int
@@ -201,41 +210,60 @@ wait_mode_sym(VALUE mode)
/*
* call-seq:
- * io.wait(timeout = nil, mode = :read) -> IO, true or nil
+ * io.wait(events, timeout) -> event mask or false.
+ * io.wait(timeout = nil, mode = :read) -> event mask or false.
+ *
+ * Waits until the IO becomes ready for the specified events and returns the
+ * subset of events that become ready, or +false+ when times out.
+ *
+ * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
+ * +IO::PRIORITY+.
*
- * Waits until IO is readable or writable without blocking and returns
- * +self+, or +nil+ when times out.
* Returns +true+ immediately when buffered data is available.
+ *
* Optional parameter +mode+ is one of +:read+, +:write+, or
* +:read_write+.
*/
static VALUE
-io_wait_readwrite(int argc, VALUE *argv, VALUE io)
+io_wait(int argc, VALUE *argv, VALUE io)
{
- rb_io_t *fptr;
- struct timeval timerec;
- struct timeval *tv = NULL;
- int event = 0;
- int i;
+ VALUE timeout = Qundef;
+ rb_io_event_t events = 0;
- GetOpenFile(io, fptr);
- for (i = 0; i < argc; ++i) {
- if (SYMBOL_P(argv[i])) {
- event |= wait_mode_sym(argv[i]);
+ if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
+ for (int i = 0; i < argc; i += 1) {
+ if (RB_SYMBOL_P(argv[i])) {
+ events |= wait_mode_sym(argv[i]);
+ }
+ else if (timeout == Qundef) {
+ rb_time_interval(timeout = argv[i]);
+ }
+ else {
+ rb_raise(rb_eArgError, "timeout given more than once");
+ }
}
- else {
- *(tv = &timerec) = rb_time_interval(argv[i]);
+ if (timeout == Qundef) timeout = Qnil;
+ }
+ else /* argc == 2 */ {
+ events = RB_NUM2UINT(argv[0]);
+ timeout = argv[1];
+ }
+
+ if (events == 0) {
+ events = RUBY_IO_READABLE;
+ }
+
+ if (events & RUBY_IO_READABLE) {
+ rb_io_t *fptr = NULL;
+ RB_IO_POINTER(io, fptr);
+
+ if (rb_io_read_pending(fptr)) {
+ return Qtrue;
}
}
- /* 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;
+
+ return io_wait_event(io, events, timeout);
}
/*
@@ -245,9 +273,16 @@ io_wait_readwrite(int argc, VALUE *argv, VALUE io)
void
Init_wait(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+#endif
+
rb_define_method(rb_cIO, "nread", io_nread, 0);
rb_define_method(rb_cIO, "ready?", io_ready_p, 0);
- rb_define_method(rb_cIO, "wait", io_wait_readwrite, -1);
+
+ rb_define_method(rb_cIO, "wait", io_wait, -1);
+
rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1);
+ rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1);
}
diff --git a/ext/json/VERSION b/ext/json/VERSION
new file mode 100644
index 0000000000..73462a5a13
--- /dev/null
+++ b/ext/json/VERSION
@@ -0,0 +1 @@
+2.5.1
diff --git a/ext/json/extconf.rb b/ext/json/extconf.rb
index 7595d58a98..8a99b6a5c8 100644
--- a/ext/json/extconf.rb
+++ b/ext/json/extconf.rb
@@ -1,2 +1,3 @@
require 'mkmf'
+
create_makefile('json')
diff --git a/ext/json/generator/depend b/ext/json/generator/depend
index 3f04c0d625..89e43dbfab 100644
--- a/ext/json/generator/depend
+++ b/ext/json/generator/depend
@@ -5,8 +5,158 @@ generator.o: generator.c generator.h $(srcdir)/../fbuffer/fbuffer.h
generator.o: $(RUBY_EXTCONF_H)
generator.o: $(arch_hdrdir)/ruby/config.h
generator.o: $(hdrdir)/ruby.h
+generator.o: $(hdrdir)/ruby/internal/anyargs.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+generator.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+generator.o: $(hdrdir)/ruby/internal/assume.h
+generator.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+generator.o: $(hdrdir)/ruby/internal/attr/artificial.h
+generator.o: $(hdrdir)/ruby/internal/attr/cold.h
+generator.o: $(hdrdir)/ruby/internal/attr/const.h
+generator.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+generator.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+generator.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+generator.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+generator.o: $(hdrdir)/ruby/internal/attr/error.h
+generator.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+generator.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+generator.o: $(hdrdir)/ruby/internal/attr/format.h
+generator.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+generator.o: $(hdrdir)/ruby/internal/attr/noalias.h
+generator.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+generator.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+generator.o: $(hdrdir)/ruby/internal/attr/noinline.h
+generator.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+generator.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+generator.o: $(hdrdir)/ruby/internal/attr/pure.h
+generator.o: $(hdrdir)/ruby/internal/attr/restrict.h
+generator.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+generator.o: $(hdrdir)/ruby/internal/attr/warning.h
+generator.o: $(hdrdir)/ruby/internal/attr/weakref.h
+generator.o: $(hdrdir)/ruby/internal/cast.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+generator.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+generator.o: $(hdrdir)/ruby/internal/compiler_since.h
+generator.o: $(hdrdir)/ruby/internal/config.h
+generator.o: $(hdrdir)/ruby/internal/constant_p.h
+generator.o: $(hdrdir)/ruby/internal/core.h
+generator.o: $(hdrdir)/ruby/internal/core/rarray.h
+generator.o: $(hdrdir)/ruby/internal/core/rbasic.h
+generator.o: $(hdrdir)/ruby/internal/core/rbignum.h
+generator.o: $(hdrdir)/ruby/internal/core/rclass.h
+generator.o: $(hdrdir)/ruby/internal/core/rdata.h
+generator.o: $(hdrdir)/ruby/internal/core/rfile.h
+generator.o: $(hdrdir)/ruby/internal/core/rhash.h
+generator.o: $(hdrdir)/ruby/internal/core/rmatch.h
+generator.o: $(hdrdir)/ruby/internal/core/robject.h
+generator.o: $(hdrdir)/ruby/internal/core/rregexp.h
+generator.o: $(hdrdir)/ruby/internal/core/rstring.h
+generator.o: $(hdrdir)/ruby/internal/core/rstruct.h
+generator.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+generator.o: $(hdrdir)/ruby/internal/ctype.h
+generator.o: $(hdrdir)/ruby/internal/dllexport.h
+generator.o: $(hdrdir)/ruby/internal/dosish.h
+generator.o: $(hdrdir)/ruby/internal/error.h
+generator.o: $(hdrdir)/ruby/internal/eval.h
+generator.o: $(hdrdir)/ruby/internal/event.h
+generator.o: $(hdrdir)/ruby/internal/fl_type.h
+generator.o: $(hdrdir)/ruby/internal/gc.h
+generator.o: $(hdrdir)/ruby/internal/glob.h
+generator.o: $(hdrdir)/ruby/internal/globals.h
+generator.o: $(hdrdir)/ruby/internal/has/attribute.h
+generator.o: $(hdrdir)/ruby/internal/has/builtin.h
+generator.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+generator.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+generator.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+generator.o: $(hdrdir)/ruby/internal/has/extension.h
+generator.o: $(hdrdir)/ruby/internal/has/feature.h
+generator.o: $(hdrdir)/ruby/internal/has/warning.h
+generator.o: $(hdrdir)/ruby/internal/intern/array.h
+generator.o: $(hdrdir)/ruby/internal/intern/bignum.h
+generator.o: $(hdrdir)/ruby/internal/intern/class.h
+generator.o: $(hdrdir)/ruby/internal/intern/compar.h
+generator.o: $(hdrdir)/ruby/internal/intern/complex.h
+generator.o: $(hdrdir)/ruby/internal/intern/cont.h
+generator.o: $(hdrdir)/ruby/internal/intern/dir.h
+generator.o: $(hdrdir)/ruby/internal/intern/enum.h
+generator.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+generator.o: $(hdrdir)/ruby/internal/intern/error.h
+generator.o: $(hdrdir)/ruby/internal/intern/eval.h
+generator.o: $(hdrdir)/ruby/internal/intern/file.h
+generator.o: $(hdrdir)/ruby/internal/intern/gc.h
+generator.o: $(hdrdir)/ruby/internal/intern/hash.h
+generator.o: $(hdrdir)/ruby/internal/intern/io.h
+generator.o: $(hdrdir)/ruby/internal/intern/load.h
+generator.o: $(hdrdir)/ruby/internal/intern/marshal.h
+generator.o: $(hdrdir)/ruby/internal/intern/numeric.h
+generator.o: $(hdrdir)/ruby/internal/intern/object.h
+generator.o: $(hdrdir)/ruby/internal/intern/parse.h
+generator.o: $(hdrdir)/ruby/internal/intern/proc.h
+generator.o: $(hdrdir)/ruby/internal/intern/process.h
+generator.o: $(hdrdir)/ruby/internal/intern/random.h
+generator.o: $(hdrdir)/ruby/internal/intern/range.h
+generator.o: $(hdrdir)/ruby/internal/intern/rational.h
+generator.o: $(hdrdir)/ruby/internal/intern/re.h
+generator.o: $(hdrdir)/ruby/internal/intern/ruby.h
+generator.o: $(hdrdir)/ruby/internal/intern/select.h
+generator.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+generator.o: $(hdrdir)/ruby/internal/intern/signal.h
+generator.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+generator.o: $(hdrdir)/ruby/internal/intern/string.h
+generator.o: $(hdrdir)/ruby/internal/intern/struct.h
+generator.o: $(hdrdir)/ruby/internal/intern/thread.h
+generator.o: $(hdrdir)/ruby/internal/intern/time.h
+generator.o: $(hdrdir)/ruby/internal/intern/variable.h
+generator.o: $(hdrdir)/ruby/internal/intern/vm.h
+generator.o: $(hdrdir)/ruby/internal/interpreter.h
+generator.o: $(hdrdir)/ruby/internal/iterator.h
+generator.o: $(hdrdir)/ruby/internal/memory.h
+generator.o: $(hdrdir)/ruby/internal/method.h
+generator.o: $(hdrdir)/ruby/internal/module.h
+generator.o: $(hdrdir)/ruby/internal/newobj.h
+generator.o: $(hdrdir)/ruby/internal/rgengc.h
+generator.o: $(hdrdir)/ruby/internal/scan_args.h
+generator.o: $(hdrdir)/ruby/internal/special_consts.h
+generator.o: $(hdrdir)/ruby/internal/static_assert.h
+generator.o: $(hdrdir)/ruby/internal/stdalign.h
+generator.o: $(hdrdir)/ruby/internal/stdbool.h
+generator.o: $(hdrdir)/ruby/internal/symbol.h
+generator.o: $(hdrdir)/ruby/internal/token_paste.h
+generator.o: $(hdrdir)/ruby/internal/value.h
+generator.o: $(hdrdir)/ruby/internal/value_type.h
+generator.o: $(hdrdir)/ruby/internal/variable.h
+generator.o: $(hdrdir)/ruby/internal/warning_push.h
+generator.o: $(hdrdir)/ruby/internal/xmalloc.h
generator.o: $(hdrdir)/ruby/assert.h
generator.o: $(hdrdir)/ruby/backward.h
+generator.o: $(hdrdir)/ruby/backward/2/assume.h
+generator.o: $(hdrdir)/ruby/backward/2/attributes.h
+generator.o: $(hdrdir)/ruby/backward/2/bool.h
+generator.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+generator.o: $(hdrdir)/ruby/backward/2/inttypes.h
+generator.o: $(hdrdir)/ruby/backward/2/limits.h
+generator.o: $(hdrdir)/ruby/backward/2/long_long.h
+generator.o: $(hdrdir)/ruby/backward/2/stdalign.h
+generator.o: $(hdrdir)/ruby/backward/2/stdarg.h
generator.o: $(hdrdir)/ruby/defines.h
generator.o: $(hdrdir)/ruby/encoding.h
generator.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index 881435e3dc..407c1af4a6 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -15,14 +15,13 @@ static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
#endif
mFloat, mString, mString_Extend,
mTrueClass, mFalseClass, mNilClass, eGeneratorError,
- eNestingError,
- i_SAFE_STATE_PROTOTYPE;
+ eNestingError;
static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before,
i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only,
i_pack, i_unpack, i_create_id, i_extend, i_key_p,
i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth,
- i_buffer_initial_length, i_dup;
+ i_buffer_initial_length, i_dup, i_escape_slash;
/*
* Copyright 2001-2004 Unicode, Inc.
@@ -130,7 +129,7 @@ static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
* and control characters are JSON escaped. */
-static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
+static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash)
{
const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
const UTF8 *sourceEnd = source + RSTRING_LEN(string);
@@ -180,6 +179,11 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
case '"':
fbuffer_append(buffer, "\\\"", 2);
break;
+ case '/':
+ if(escape_slash) {
+ fbuffer_append(buffer, "\\/", 2);
+ break;
+ }
default:
fbuffer_append_char(buffer, (char)ch);
break;
@@ -229,7 +233,7 @@ static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string)
* characters required by the JSON standard are JSON escaped. The remaining
* characters (should be UTF8) are just passed through and appended to the
* result. */
-static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
+static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash)
{
const char *ptr = RSTRING_PTR(string), *p;
unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
@@ -280,6 +284,12 @@ static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string)
escape = "\\\"";
escape_len = 2;
break;
+ case '/':
+ if(escape_slash) {
+ escape = "\\/";
+ escape_len = 2;
+ break;
+ }
default:
{
unsigned short clen = 1;
@@ -328,6 +338,76 @@ static char *fstrndup(const char *ptr, unsigned long len) {
*
*/
+/* Explanation of the following: that's the only way to not pollute
+ * standard library's docs with GeneratorMethods::<ClassName> which
+ * are uninformative and take a large place in a list of classes
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Array
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Bignum
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::FalseClass
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Fixnum
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Float
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Hash
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Integer
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::NilClass
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::Object
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::String
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::String::Extend
+ * :nodoc:
+ */
+
+/*
+ * Document-module: JSON::Ext::Generator::GeneratorMethods::TrueClass
+ * :nodoc:
+ */
+
/*
* call-seq: to_json(state = nil)
*
@@ -539,13 +619,18 @@ static size_t State_memsize(const void *ptr)
return size;
}
+#ifndef HAVE_RB_EXT_RACTOR_SAFE
+# undef RUBY_TYPED_FROZEN_SHAREABLE
+# define RUBY_TYPED_FROZEN_SHAREABLE 0
+#endif
+
#ifdef NEW_TYPEDDATA_WRAPPER
static const rb_data_type_t JSON_Generator_State_type = {
"JSON/Generator/State",
{NULL, State_free, State_memsize,},
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
0, 0,
- RUBY_TYPED_FREE_IMMEDIATELY,
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
#endif
};
#endif
@@ -646,6 +731,8 @@ static VALUE cState_configure(VALUE self, VALUE opts)
state->allow_nan = RTEST(tmp);
tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
state->ascii_only = RTEST(tmp);
+ tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
+ state->escape_slash = RTEST(tmp);
return self;
}
@@ -680,6 +767,7 @@ static VALUE cState_to_h(VALUE self)
rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
+ rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse);
rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth));
rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length));
return result;
@@ -864,9 +952,9 @@ static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_S
}
#endif
if (state->ascii_only) {
- convert_UTF8_to_JSON_ASCII(buffer, obj);
+ convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash);
} else {
- convert_UTF8_to_JSON(buffer, obj);
+ convert_UTF8_to_JSON(buffer, obj, state->escape_slash);
}
fbuffer_append_char(buffer, '"');
}
@@ -1026,7 +1114,7 @@ static VALUE cState_generate(VALUE self, VALUE obj)
* generated, otherwise an exception is thrown, if these values are
* encountered. This options defaults to false.
* * *ascii_only*: true if only ASCII characters should be generated. This
- * ontions defaults to false.
+ * option defaults to false.
* * *buffer_initial_length*: sets the initial length of the generator's
* internal buffer.
*/
@@ -1082,8 +1170,7 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
} else if (rb_obj_is_kind_of(opts, rb_cHash)) {
return rb_funcall(self, i_new, 1, opts);
} else {
- VALUE prototype = rb_const_get(mJSON, i_SAFE_STATE_PROTOTYPE);
- return rb_funcall(prototype, i_dup, 0);
+ return rb_class_new_instance(0, NULL, cState);
}
}
@@ -1308,6 +1395,31 @@ static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
}
/*
+ * call-seq: escape_slash
+ *
+ * If this boolean is true, the forward slashes will be escaped in
+ * the json output.
+ */
+static VALUE cState_escape_slash(VALUE self)
+{
+ GET_STATE(self);
+ return state->escape_slash ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq: escape_slash=(depth)
+ *
+ * This sets whether or not the forward slashes will be escaped in
+ * the json output.
+ */
+static VALUE cState_escape_slash_set(VALUE self, VALUE enable)
+{
+ GET_STATE(self);
+ state->escape_slash = RTEST(enable);
+ return Qnil;
+}
+
+/*
* call-seq: allow_nan?
*
* Returns true, if NaN, Infinity, and -Infinity should be generated, otherwise
@@ -1390,6 +1502,10 @@ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_l
*/
void Init_generator(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
#undef rb_intern
rb_require("json/common");
@@ -1419,6 +1535,9 @@ void Init_generator(void)
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
+ rb_define_method(cState, "escape_slash", cState_escape_slash, 0);
+ rb_define_method(cState, "escape_slash?", cState_escape_slash, 0);
+ rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1);
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
@@ -1475,6 +1594,7 @@ void Init_generator(void)
i_object_nl = rb_intern("object_nl");
i_array_nl = rb_intern("array_nl");
i_max_nesting = rb_intern("max_nesting");
+ i_escape_slash = rb_intern("escape_slash");
i_allow_nan = rb_intern("allow_nan");
i_ascii_only = rb_intern("ascii_only");
i_depth = rb_intern("depth");
@@ -1495,5 +1615,4 @@ void Init_generator(void)
i_encoding = rb_intern("encoding");
i_encode = rb_intern("encode");
#endif
- i_SAFE_STATE_PROTOTYPE = rb_intern("SAFE_STATE_PROTOTYPE");
}
diff --git a/ext/json/generator/generator.h b/ext/json/generator/generator.h
index c367a6209a..3ebd622554 100644
--- a/ext/json/generator/generator.h
+++ b/ext/json/generator/generator.h
@@ -49,8 +49,8 @@ static const UTF32 halfMask = 0x3FFUL;
static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
static void unicode_escape(char *buf, UTF16 character);
static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
-static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string);
-static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string);
+static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash);
+static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash);
static char *fstrndup(const char *ptr, unsigned long len);
/* ruby api and some helpers */
@@ -72,6 +72,7 @@ typedef struct JSON_Generator_StateStruct {
long max_nesting;
char allow_nan;
char ascii_only;
+ char escape_slash;
long depth;
long buffer_initial_length;
} JSON_Generator_State;
@@ -150,6 +151,8 @@ static VALUE cState_allow_nan_p(VALUE self);
static VALUE cState_ascii_only_p(VALUE self);
static VALUE cState_depth(VALUE self);
static VALUE cState_depth_set(VALUE self, VALUE depth);
+static VALUE cState_escape_slash(VALUE self);
+static VALUE cState_escape_slash_set(VALUE self, VALUE depth);
static FBuffer *cState_prepare_buffer(VALUE self);
#ifndef ZALLOC
#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
diff --git a/ext/json/json.gemspec b/ext/json/json.gemspec
index d8be2e52c6..d5f0a4de1d 100644
--- a/ext/json/json.gemspec
+++ b/ext/json/json.gemspec
@@ -2,26 +2,23 @@
Gem::Specification.new do |s|
s.name = "json"
- s.version = "2.3.0"
+ s.version = File.read(File.expand_path('../VERSION', __FILE__)).chomp
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
- s.require_paths = ["lib"]
- s.authors = ["Florian Frank"]
- s.date = "2019-12-11"
+ s.summary = "JSON Implementation for Ruby"
s.description = "This is a JSON implementation as a Ruby extension in C."
+ s.licenses = ["Ruby"]
+ s.authors = ["Florian Frank"]
s.email = "flori@ping.de"
+
s.extensions = ["ext/json/ext/generator/extconf.rb", "ext/json/ext/parser/extconf.rb", "ext/json/extconf.rb"]
s.extra_rdoc_files = ["README.md"]
+ s.rdoc_options = ["--title", "JSON implementation for Ruby", "--main", "README.md"]
s.files = [
- ".gitignore",
- ".travis.yml",
"CHANGES.md",
"Gemfile",
- "README-json-jruby.md",
+ "LICENSE",
"README.md",
- "Rakefile",
"VERSION",
- "diagrams/.keep",
"ext/json/ext/fbuffer/fbuffer.h",
"ext/json/ext/generator/depend",
"ext/json/ext/generator/extconf.rb",
@@ -33,23 +30,7 @@ Gem::Specification.new do |s|
"ext/json/ext/parser/parser.h",
"ext/json/ext/parser/parser.rl",
"ext/json/extconf.rb",
- "install.rb",
- "java/src/json/ext/ByteListTranscoder.java",
- "java/src/json/ext/Generator.java",
- "java/src/json/ext/GeneratorMethods.java",
- "java/src/json/ext/GeneratorService.java",
- "java/src/json/ext/GeneratorState.java",
- "java/src/json/ext/OptionsReader.java",
- "java/src/json/ext/Parser.java",
- "java/src/json/ext/Parser.rl",
- "java/src/json/ext/ParserService.java",
- "java/src/json/ext/RuntimeInfo.java",
- "java/src/json/ext/StringDecoder.java",
- "java/src/json/ext/StringEncoder.java",
- "java/src/json/ext/Utils.java",
- "json-java.gemspec",
"json.gemspec",
- "json_pure.gemspec",
"lib/json.rb",
"lib/json/add/bigdecimal.rb",
"lib/json/add/complex.rb",
@@ -73,61 +54,20 @@ Gem::Specification.new do |s|
"lib/json/pure/generator.rb",
"lib/json/pure/parser.rb",
"lib/json/version.rb",
- "references/rfc7159.txt",
- "tests/fixtures/fail10.json",
- "tests/fixtures/fail11.json",
- "tests/fixtures/fail12.json",
- "tests/fixtures/fail13.json",
- "tests/fixtures/fail14.json",
- "tests/fixtures/fail18.json",
- "tests/fixtures/fail19.json",
- "tests/fixtures/fail2.json",
- "tests/fixtures/fail20.json",
- "tests/fixtures/fail21.json",
- "tests/fixtures/fail22.json",
- "tests/fixtures/fail23.json",
- "tests/fixtures/fail24.json",
- "tests/fixtures/fail25.json",
- "tests/fixtures/fail27.json",
- "tests/fixtures/fail28.json",
- "tests/fixtures/fail3.json",
- "tests/fixtures/fail4.json",
- "tests/fixtures/fail5.json",
- "tests/fixtures/fail6.json",
- "tests/fixtures/fail7.json",
- "tests/fixtures/fail8.json",
- "tests/fixtures/fail9.json",
- "tests/fixtures/obsolete_fail1.json",
- "tests/fixtures/pass1.json",
- "tests/fixtures/pass15.json",
- "tests/fixtures/pass16.json",
- "tests/fixtures/pass17.json",
- "tests/fixtures/pass2.json",
- "tests/fixtures/pass26.json",
- "tests/fixtures/pass3.json",
- "tests/json_addition_test.rb",
- "tests/json_common_interface_test.rb",
- "tests/json_encoding_test.rb",
- "tests/json_ext_parser_test.rb",
- "tests/json_fixtures_test.rb",
- "tests/json_generator_test.rb",
- "tests/json_generic_object_test.rb",
- "tests/json_parser_test.rb",
- "tests/json_string_matching_test.rb",
- "tests/test_helper.rb",
- "tests/test_helper.rb",
- "tools/diff.sh",
- "tools/fuzz.rb",
- "tools/server.rb",
- ]
+ ] + Dir["tests/**/*"]
s.homepage = "http://flori.github.com/json"
- s.licenses = ["Ruby"]
- s.rdoc_options = ["--title", "JSON implemention for Ruby", "--main", "README.md"]
- s.required_ruby_version = Gem::Requirement.new(">= 1.9")
- s.rubygems_version = "3.0.3"
- s.summary = "JSON Implementation for Ruby"
+ s.metadata = {
+ 'bug_tracker_uri' => 'https://github.com/flori/json/issues',
+ 'changelog_uri' => 'https://github.com/flori/json/blob/master/CHANGES.md',
+ 'documentation_uri' => 'http://flori.github.io/json/doc/index.html',
+ 'homepage_uri' => 'http://flori.github.io/json/',
+ 'source_code_uri' => 'https://github.com/flori/json',
+ 'wiki_uri' => 'https://github.com/flori/json/wiki'
+ }
+
+ s.required_ruby_version = Gem::Requirement.new(">= 2.0")
s.test_files = ["tests/test_helper.rb"]
- s.add_development_dependency("rake", [">= 0"])
- s.add_development_dependency("test-unit", ["~> 2.0"])
+ s.add_development_dependency "rake"
+ s.add_development_dependency "test-unit"
end
diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb
index b5a6912415..aeb9774ee9 100644
--- a/ext/json/lib/json.rb
+++ b/ext/json/lib/json.rb
@@ -2,55 +2,575 @@
require 'json/common'
##
-# = JavaScript Object Notation (JSON)
+# = JavaScript \Object Notation (\JSON)
#
-# JSON is a lightweight data-interchange format. It is easy for us
-# humans to read and write. Plus, equally simple for machines to generate or parse.
-# JSON is completely language agnostic, making it the ideal interchange format.
+# \JSON is a lightweight data-interchange format.
#
-# Built on two universally available structures:
-# 1. A collection of name/value pairs. Often referred to as an _object_, hash table, record, struct, keyed list, or associative array.
-# 2. An ordered list of values. More commonly called an _array_, vector, sequence or list.
+# A \JSON value is one of the following:
+# - Double-quoted text: <tt>"foo"</tt>.
+# - Number: +1+, +1.0+, +2.0e2+.
+# - Boolean: +true+, +false+.
+# - Null: +null+.
+# - \Array: an ordered list of values, enclosed by square brackets:
+# ["foo", 1, 1.0, 2.0e2, true, false, null]
#
-# To read more about JSON visit: http://json.org
+# - \Object: a collection of name/value pairs, enclosed by curly braces;
+# each name is double-quoted text;
+# the values may be any \JSON values:
+# {"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}
#
-# == Parsing JSON
+# A \JSON array or object may contain nested arrays, objects, and scalars
+# to any depth:
+# {"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}
+# [{"foo": 0, "bar": 1}, ["baz", 2]]
#
-# To parse a JSON string received by another application or generated within
-# your existing application:
+# == Using \Module \JSON
#
+# To make module \JSON available in your code, begin with:
# require 'json'
#
-# my_hash = JSON.parse('{"hello": "goodbye"}')
-# puts my_hash["hello"] => "goodbye"
+# All examples here assume that this has been done.
#
-# Notice the extra quotes <tt>''</tt> around the hash notation. Ruby expects
-# the argument to be a string and can't convert objects like a hash or array.
+# === Parsing \JSON
#
-# Ruby converts your string into a hash
+# You can parse a \String containing \JSON data using
+# either of two methods:
+# - <tt>JSON.parse(source, opts)</tt>
+# - <tt>JSON.parse!(source, opts)</tt>
#
-# == Generating JSON
+# where
+# - +source+ is a Ruby object.
+# - +opts+ is a \Hash object containing options
+# that control both input allowed and output formatting.
#
-# Creating a JSON string for communication or serialization is
-# just as simple.
+# The difference between the two methods
+# is that JSON.parse! omits some checks
+# and may not be safe for some +source+ data;
+# use it only for data from trusted sources.
+# Use the safer method JSON.parse for less trusted sources.
#
-# require 'json'
+# ==== Parsing \JSON Arrays
#
-# my_hash = {:hello => "goodbye"}
-# puts JSON.generate(my_hash) => "{\"hello\":\"goodbye\"}"
+# When +source+ is a \JSON array, JSON.parse by default returns a Ruby \Array:
+# json = '["foo", 1, 1.0, 2.0e2, true, false, null]'
+# ruby = JSON.parse(json)
+# ruby # => ["foo", 1, 1.0, 200.0, true, false, nil]
+# ruby.class # => Array
#
-# Or an alternative way:
+# The \JSON array may contain nested arrays, objects, and scalars
+# to any depth:
+# json = '[{"foo": 0, "bar": 1}, ["baz", 2]]'
+# JSON.parse(json) # => [{"foo"=>0, "bar"=>1}, ["baz", 2]]
#
-# require 'json'
-# puts {:hello => "goodbye"}.to_json => "{\"hello\":\"goodbye\"}"
+# ==== Parsing \JSON \Objects
+#
+# When the source is a \JSON object, JSON.parse by default returns a Ruby \Hash:
+# json = '{"a": "foo", "b": 1, "c": 1.0, "d": 2.0e2, "e": true, "f": false, "g": null}'
+# ruby = JSON.parse(json)
+# ruby # => {"a"=>"foo", "b"=>1, "c"=>1.0, "d"=>200.0, "e"=>true, "f"=>false, "g"=>nil}
+# ruby.class # => Hash
+#
+# The \JSON object may contain nested arrays, objects, and scalars
+# to any depth:
+# json = '{"foo": {"bar": 1, "baz": 2}, "bat": [0, 1, 2]}'
+# JSON.parse(json) # => {"foo"=>{"bar"=>1, "baz"=>2}, "bat"=>[0, 1, 2]}
+#
+# ==== Parsing \JSON Scalars
+#
+# When the source is a \JSON scalar (not an array or object),
+# JSON.parse returns a Ruby scalar.
+#
+# \String:
+# ruby = JSON.parse('"foo"')
+# ruby # => 'foo'
+# ruby.class # => String
+# \Integer:
+# ruby = JSON.parse('1')
+# ruby # => 1
+# ruby.class # => Integer
+# \Float:
+# ruby = JSON.parse('1.0')
+# ruby # => 1.0
+# ruby.class # => Float
+# ruby = JSON.parse('2.0e2')
+# ruby # => 200
+# ruby.class # => Float
+# Boolean:
+# ruby = JSON.parse('true')
+# ruby # => true
+# ruby.class # => TrueClass
+# ruby = JSON.parse('false')
+# ruby # => false
+# ruby.class # => FalseClass
+# Null:
+# ruby = JSON.parse('null')
+# ruby # => nil
+# ruby.class # => NilClass
+#
+# ==== Parsing Options
+#
+# ====== Input Options
+#
+# Option +max_nesting+ (\Integer) specifies the maximum nesting depth allowed;
+# defaults to +100+; specify +false+ to disable depth checking.
+#
+# With the default, +false+:
+# source = '[0, [1, [2, [3]]]]'
+# ruby = JSON.parse(source)
+# ruby # => [0, [1, [2, [3]]]]
+# Too deep:
+# # Raises JSON::NestingError (nesting of 2 is too deep):
+# JSON.parse(source, {max_nesting: 1})
+# Bad value:
+# # Raises TypeError (wrong argument type Symbol (expected Fixnum)):
+# JSON.parse(source, {max_nesting: :foo})
+#
+# ---
+#
+# Option +allow_nan+ (boolean) specifies whether to allow
+# NaN, Infinity, and MinusInfinity in +source+;
+# defaults to +false+.
+#
+# With the default, +false+:
+# # Raises JSON::ParserError (225: unexpected token at '[NaN]'):
+# JSON.parse('[NaN]')
+# # Raises JSON::ParserError (232: unexpected token at '[Infinity]'):
+# JSON.parse('[Infinity]')
+# # Raises JSON::ParserError (248: unexpected token at '[-Infinity]'):
+# JSON.parse('[-Infinity]')
+# Allow:
+# source = '[NaN, Infinity, -Infinity]'
+# ruby = JSON.parse(source, {allow_nan: true})
+# ruby # => [NaN, Infinity, -Infinity]
+#
+# ====== Output Options
+#
+# Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
+# should be Symbols;
+# defaults to +false+ (use Strings).
+#
+# With the default, +false+:
+# source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
+# ruby = JSON.parse(source)
+# ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
+# Use Symbols:
+# ruby = JSON.parse(source, {symbolize_names: true})
+# ruby # => {:a=>"foo", :b=>1.0, :c=>true, :d=>false, :e=>nil}
+#
+# ---
+#
+# Option +object_class+ (\Class) specifies the Ruby class to be used
+# for each \JSON object;
+# defaults to \Hash.
+#
+# With the default, \Hash:
+# source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
+# ruby = JSON.parse(source)
+# ruby.class # => Hash
+# Use class \OpenStruct:
+# ruby = JSON.parse(source, {object_class: OpenStruct})
+# ruby # => #<OpenStruct a="foo", b=1.0, c=true, d=false, e=nil>
+#
+# ---
+#
+# Option +array_class+ (\Class) specifies the Ruby class to be used
+# for each \JSON array;
+# defaults to \Array.
+#
+# With the default, \Array:
+# source = '["foo", 1.0, true, false, null]'
+# ruby = JSON.parse(source)
+# ruby.class # => Array
+# Use class \Set:
+# ruby = JSON.parse(source, {array_class: Set})
+# ruby # => #<Set: {"foo", 1.0, true, false, nil}>
+#
+# ---
+#
+# Option +create_additions+ (boolean) specifies whether to use \JSON additions in parsing.
+# See {\JSON Additions}[#module-JSON-label-JSON+Additions].
+#
+# === Generating \JSON
+#
+# To generate a Ruby \String containing \JSON data,
+# use method <tt>JSON.generate(source, opts)</tt>, where
+# - +source+ is a Ruby object.
+# - +opts+ is a \Hash object containing options
+# that control both input allowed and output formatting.
+#
+# ==== Generating \JSON from Arrays
+#
+# When the source is a Ruby \Array, JSON.generate returns
+# a \String containing a \JSON array:
+# ruby = [0, 's', :foo]
+# json = JSON.generate(ruby)
+# json # => '[0,"s","foo"]'
+#
+# The Ruby \Array array may contain nested arrays, hashes, and scalars
+# to any depth:
+# ruby = [0, [1, 2], {foo: 3, bar: 4}]
+# json = JSON.generate(ruby)
+# json # => '[0,[1,2],{"foo":3,"bar":4}]'
+#
+# ==== Generating \JSON from Hashes
+#
+# When the source is a Ruby \Hash, JSON.generate returns
+# a \String containing a \JSON object:
+# ruby = {foo: 0, bar: 's', baz: :bat}
+# json = JSON.generate(ruby)
+# json # => '{"foo":0,"bar":"s","baz":"bat"}'
+#
+# The Ruby \Hash array may contain nested arrays, hashes, and scalars
+# to any depth:
+# ruby = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad}
+# json = JSON.generate(ruby)
+# json # => '{"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}'
+#
+# ==== Generating \JSON from Other Objects
+#
+# When the source is neither an \Array nor a \Hash,
+# the generated \JSON data depends on the class of the source.
+#
+# When the source is a Ruby \Integer or \Float, JSON.generate returns
+# a \String containing a \JSON number:
+# JSON.generate(42) # => '42'
+# JSON.generate(0.42) # => '0.42'
+#
+# When the source is a Ruby \String, JSON.generate returns
+# a \String containing a \JSON string (with double-quotes):
+# JSON.generate('A string') # => '"A string"'
+#
+# When the source is +true+, +false+ or +nil+, JSON.generate returns
+# a \String containing the corresponding \JSON token:
+# JSON.generate(true) # => 'true'
+# JSON.generate(false) # => 'false'
+# JSON.generate(nil) # => 'null'
+#
+# When the source is none of the above, JSON.generate returns
+# a \String containing a \JSON string representation of the source:
+# JSON.generate(:foo) # => '"foo"'
+# JSON.generate(Complex(0, 0)) # => '"0+0i"'
+# JSON.generate(Dir.new('.')) # => '"#<Dir>"'
+#
+# ==== Generating Options
+#
+# ====== Input Options
#
-# <tt>JSON.generate</tt> only allows objects or arrays to be converted
-# to JSON syntax. <tt>to_json</tt>, however, accepts many Ruby classes
-# even though it acts only as a method for serialization:
+# Option +allow_nan+ (boolean) specifies whether
+# +NaN+, +Infinity+, and <tt>-Infinity</tt> may be generated;
+# defaults to +false+.
#
+# With the default, +false+:
+# # Raises JSON::GeneratorError (920: NaN not allowed in JSON):
+# JSON.generate(JSON::NaN)
+# # Raises JSON::GeneratorError (917: Infinity not allowed in JSON):
+# JSON.generate(JSON::Infinity)
+# # Raises JSON::GeneratorError (917: -Infinity not allowed in JSON):
+# JSON.generate(JSON::MinusInfinity)
+#
+# Allow:
+# ruby = [Float::NaN, Float::Infinity, Float::MinusInfinity]
+# JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]'
+#
+# ---
+#
+# Option +max_nesting+ (\Integer) specifies the maximum nesting depth
+# in +obj+; defaults to +100+.
+#
+# With the default, +100+:
+# obj = [[[[[[0]]]]]]
+# JSON.generate(obj) # => '[[[[[[0]]]]]]'
+#
+# Too deep:
+# # Raises JSON::NestingError (nesting of 2 is too deep):
+# JSON.generate(obj, max_nesting: 2)
+#
+# ====== Output Options
+#
+# The default formatting options generate the most compact
+# \JSON data, all on one line and with no whitespace.
+#
+# You can use these formatting options to generate
+# \JSON data in a more open format, using whitespace.
+# See also JSON.pretty_generate.
+#
+# - Option +array_nl+ (\String) specifies a string (usually a newline)
+# to be inserted after each \JSON array; defaults to the empty \String, <tt>''</tt>.
+# - Option +object_nl+ (\String) specifies a string (usually a newline)
+# to be inserted after each \JSON object; defaults to the empty \String, <tt>''</tt>.
+# - Option +indent+ (\String) specifies the string (usually spaces) to be
+# used for indentation; defaults to the empty \String, <tt>''</tt>;
+# defaults to the empty \String, <tt>''</tt>;
+# has no effect unless options +array_nl+ or +object_nl+ specify newlines.
+# - Option +space+ (\String) specifies a string (usually a space) to be
+# inserted after the colon in each \JSON object's pair;
+# defaults to the empty \String, <tt>''</tt>.
+# - Option +space_before+ (\String) specifies a string (usually a space) to be
+# inserted before the colon in each \JSON object's pair;
+# defaults to the empty \String, <tt>''</tt>.
+#
+# In this example, +obj+ is used first to generate the shortest
+# \JSON data (no whitespace), then again with all formatting options
+# specified:
+#
+# obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
+# json = JSON.generate(obj)
+# puts 'Compact:', json
+# opts = {
+# array_nl: "\n",
+# object_nl: "\n",
+# indent: ' ',
+# space_before: ' ',
+# space: ' '
+# }
+# puts 'Open:', JSON.generate(obj, opts)
+#
+# Output:
+# Compact:
+# {"foo":["bar","baz"],"bat":{"bam":0,"bad":1}}
+# Open:
+# {
+# "foo" : [
+# "bar",
+# "baz"
+# ],
+# "bat" : {
+# "bam" : 0,
+# "bad" : 1
+# }
+# }
+#
+# == \JSON Additions
+#
+# When you "round trip" a non-\String object from Ruby to \JSON and back,
+# you have a new \String, instead of the object you began with:
+# ruby0 = Range.new(0, 2)
+# json = JSON.generate(ruby0)
+# json # => '0..2"'
+# ruby1 = JSON.parse(json)
+# ruby1 # => '0..2'
+# ruby1.class # => String
+#
+# You can use \JSON _additions_ to preserve the original object.
+# The addition is an extension of a ruby class, so that:
+# - \JSON.generate stores more information in the \JSON string.
+# - \JSON.parse, called with option +create_additions+,
+# uses that information to create a proper Ruby object.
+#
+# This example shows a \Range being generated into \JSON
+# and parsed back into Ruby, both without and with
+# the addition for \Range:
+# ruby = Range.new(0, 2)
+# # This passage does not use the addition for Range.
+# json0 = JSON.generate(ruby)
+# ruby0 = JSON.parse(json0)
+# # This passage uses the addition for Range.
+# require 'json/add/range'
+# json1 = JSON.generate(ruby)
+# ruby1 = JSON.parse(json1, create_additions: true)
+# # Make a nice display.
+# display = <<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
+#
+# This output shows the different results:
+# Generated JSON:
+# Without addition: "0..2" (String)
+# With addition: {"json_class":"Range","a":[0,2,false]} (String)
+# Parsed JSON:
+# Without addition: "0..2" (String)
+# With addition: 0..2 (Range)
+#
+# The \JSON module includes additions for certain classes.
+# You can also craft custom additions.
+# See {Custom \JSON Additions}[#module-JSON-label-Custom+JSON+Additions].
+#
+# === Built-in Additions
+#
+# The \JSON module includes additions for certain classes.
+# To use an addition, +require+ its source:
+# - BigDecimal: <tt>require 'json/add/bigdecimal'</tt>
+# - Complex: <tt>require 'json/add/complex'</tt>
+# - Date: <tt>require 'json/add/date'</tt>
+# - DateTime: <tt>require 'json/add/date_time'</tt>
+# - Exception: <tt>require 'json/add/exception'</tt>
+# - OpenStruct: <tt>require 'json/add/ostruct'</tt>
+# - Range: <tt>require 'json/add/range'</tt>
+# - Rational: <tt>require 'json/add/rational'</tt>
+# - Regexp: <tt>require 'json/add/regexp'</tt>
+# - Set: <tt>require 'json/add/set'</tt>
+# - Struct: <tt>require 'json/add/struct'</tt>
+# - Symbol: <tt>require 'json/add/symbol'</tt>
+# - Time: <tt>require 'json/add/time'</tt>
+#
+# To reduce punctuation clutter, the examples below
+# show the generated \JSON via +puts+, rather than the usual +inspect+,
+#
+# \BigDecimal:
+# require 'json/add/bigdecimal'
+# ruby0 = BigDecimal(0) # 0.0
+# json = JSON.generate(ruby0) # {"json_class":"BigDecimal","b":"27:0.0"}
+# ruby1 = JSON.parse(json, create_additions: true) # 0.0
+# ruby1.class # => BigDecimal
+#
+# \Complex:
+# require 'json/add/complex'
+# ruby0 = Complex(1+0i) # 1+0i
+# json = JSON.generate(ruby0) # {"json_class":"Complex","r":1,"i":0}
+# ruby1 = JSON.parse(json, create_additions: true) # 1+0i
+# ruby1.class # Complex
+#
+# \Date:
+# require 'json/add/date'
+# ruby0 = Date.today # 2020-05-02
+# json = JSON.generate(ruby0) # {"json_class":"Date","y":2020,"m":5,"d":2,"sg":2299161.0}
+# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02
+# ruby1.class # Date
+#
+# \DateTime:
+# require 'json/add/date_time'
+# ruby0 = DateTime.now # 2020-05-02T10:38:13-05:00
+# json = JSON.generate(ruby0) # {"json_class":"DateTime","y":2020,"m":5,"d":2,"H":10,"M":38,"S":13,"of":"-5/24","sg":2299161.0}
+# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02T10:38:13-05:00
+# ruby1.class # DateTime
+#
+# \Exception (and its subclasses including \RuntimeError):
+# require 'json/add/exception'
+# ruby0 = Exception.new('A message') # A message
+# json = JSON.generate(ruby0) # {"json_class":"Exception","m":"A message","b":null}
+# ruby1 = JSON.parse(json, create_additions: true) # A message
+# ruby1.class # Exception
+# ruby0 = RuntimeError.new('Another message') # Another message
+# json = JSON.generate(ruby0) # {"json_class":"RuntimeError","m":"Another message","b":null}
+# ruby1 = JSON.parse(json, create_additions: true) # Another message
+# ruby1.class # RuntimeError
+#
+# \OpenStruct:
+# require 'json/add/ostruct'
+# ruby0 = OpenStruct.new(name: 'Matz', language: 'Ruby') # #<OpenStruct name="Matz", language="Ruby">
+# json = JSON.generate(ruby0) # {"json_class":"OpenStruct","t":{"name":"Matz","language":"Ruby"}}
+# ruby1 = JSON.parse(json, create_additions: true) # #<OpenStruct name="Matz", language="Ruby">
+# ruby1.class # OpenStruct
+#
+# \Range:
+# require 'json/add/range'
+# ruby0 = Range.new(0, 2) # 0..2
+# json = JSON.generate(ruby0) # {"json_class":"Range","a":[0,2,false]}
+# ruby1 = JSON.parse(json, create_additions: true) # 0..2
+# ruby1.class # Range
+#
+# \Rational:
+# require 'json/add/rational'
+# ruby0 = Rational(1, 3) # 1/3
+# json = JSON.generate(ruby0) # {"json_class":"Rational","n":1,"d":3}
+# ruby1 = JSON.parse(json, create_additions: true) # 1/3
+# ruby1.class # Rational
+#
+# \Regexp:
+# require 'json/add/regexp'
+# ruby0 = Regexp.new('foo') # (?-mix:foo)
+# json = JSON.generate(ruby0) # {"json_class":"Regexp","o":0,"s":"foo"}
+# ruby1 = JSON.parse(json, create_additions: true) # (?-mix:foo)
+# ruby1.class # Regexp
+#
+# \Set:
+# require 'json/add/set'
+# ruby0 = Set.new([0, 1, 2]) # #<Set: {0, 1, 2}>
+# json = JSON.generate(ruby0) # {"json_class":"Set","a":[0,1,2]}
+# ruby1 = JSON.parse(json, create_additions: true) # #<Set: {0, 1, 2}>
+# ruby1.class # Set
+#
+# \Struct:
+# require 'json/add/struct'
+# Customer = Struct.new(:name, :address) # Customer
+# ruby0 = Customer.new("Dave", "123 Main") # #<struct Customer name="Dave", address="123 Main">
+# json = JSON.generate(ruby0) # {"json_class":"Customer","v":["Dave","123 Main"]}
+# ruby1 = JSON.parse(json, create_additions: true) # #<struct Customer name="Dave", address="123 Main">
+# ruby1.class # Customer
+ #
+# \Symbol:
+# require 'json/add/symbol'
+# ruby0 = :foo # foo
+# json = JSON.generate(ruby0) # {"json_class":"Symbol","s":"foo"}
+# ruby1 = JSON.parse(json, create_additions: true) # foo
+# ruby1.class # Symbol
+#
+# \Time:
+# require 'json/add/time'
+# ruby0 = Time.now # 2020-05-02 11:28:26 -0500
+# json = JSON.generate(ruby0) # {"json_class":"Time","s":1588436906,"n":840560000}
+# ruby1 = JSON.parse(json, create_additions: true) # 2020-05-02 11:28:26 -0500
+# ruby1.class # Time
+#
+#
+# === Custom \JSON Additions
+#
+# In addition to the \JSON additions provided,
+# you can craft \JSON additions of your own,
+# either for Ruby built-in classes or for user-defined classes.
+#
+# Here's a user-defined class +Foo+:
+# class Foo
+# attr_accessor :bar, :baz
+# def initialize(bar, baz)
+# self.bar = bar
+# self.baz = baz
+# end
+# end
+#
+# Here's the \JSON addition for it:
+# # Extend class Foo with JSON addition.
+# class Foo
+# # Serialize Foo object with its class name and arguments
+# def to_json(*args)
+# {
+# JSON.create_id => self.class.name,
+# 'a' => [ bar, baz ]
+# }.to_json(*args)
+# end
+# # Deserialize JSON string by constructing new Foo object with arguments.
+# def self.json_create(object)
+# new(*object['a'])
+# end
+# end
+#
+# Demonstration:
# require 'json'
+# # This Foo object has no custom addition.
+# foo0 = Foo.new(0, 1)
+# json0 = JSON.generate(foo0)
+# obj0 = JSON.parse(json0)
+# # Lood the custom addition.
+# require_relative 'foo_addition'
+# # This foo has the custom addition.
+# foo1 = Foo.new(0, 1)
+# json1 = JSON.generate(foo1)
+# obj1 = JSON.parse(json1, create_additions: true)
+# # Make a nice display.
+# display = <<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
+#
+# Output:
#
-# 1.to_json => "1"
+# Generated JSON:
+# Without custom addition: "#<Foo:0x0000000006534e80>" (String)
+# With custom addition: {"json_class":"Foo","a":[0,1]} (String)
+# Parsed JSON:
+# Without custom addition: "#<Foo:0x0000000006534e80>" (String)
+# With custom addition: #<Foo:0x0000000006473bb8 @bar=0, @baz=1> (Foo)
#
module JSON
require 'json/version'
diff --git a/ext/json/lib/json/add/complex.rb b/ext/json/lib/json/add/complex.rb
index 4d977e7589..e63e29fd22 100644
--- a/ext/json/lib/json/add/complex.rb
+++ b/ext/json/lib/json/add/complex.rb
@@ -2,7 +2,6 @@
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
-defined?(::Complex) or require 'complex'
class Complex
diff --git a/ext/json/lib/json/add/rational.rb b/ext/json/lib/json/add/rational.rb
index 6be4034581..f776226046 100644
--- a/ext/json/lib/json/add/rational.rb
+++ b/ext/json/lib/json/add/rational.rb
@@ -2,7 +2,6 @@
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
-defined?(::Rational) or require 'rational'
class Rational
# Deserializes JSON string by converting numerator value <tt>n</tt>,
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 3be9fd8dc5..ea46896fcc 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -4,12 +4,17 @@ require 'json/generic_object'
module JSON
class << self
- # If _object_ is string-like, parse the string and return the parsed
- # result as a Ruby data structure. Otherwise generate a JSON text from the
- # Ruby data structure object and return it.
+ # :call-seq:
+ # JSON[object] -> new_array or new_string
#
- # The _opts_ argument is passed through to generate/parse respectively.
- # See generate and parse for their documentation.
+ # If +object+ is a \String,
+ # calls JSON.parse with +object+ and +opts+ (see method #parse):
+ # json = '[0, 1, null]'
+ # JSON[json]# => [0, 1, nil]
+ #
+ # Otherwise, calls JSON.generate with +object+ and +opts+ (see method #generate):
+ # ruby = [0, 1, nil]
+ # JSON[ruby] # => '[0,1,null]'
def [](object, opts = {})
if object.respond_to? :to_str
JSON.parse(object.to_str, opts)
@@ -19,7 +24,8 @@ module JSON
end
# Returns the JSON parser class that is used by JSON. This is either
- # JSON::Ext::Parser or JSON::Pure::Parser.
+ # JSON::Ext::Parser or JSON::Pure::Parser:
+ # JSON.parser # => JSON::Ext::Parser
attr_reader :parser
# Set the JSON parser class _parser_ to be used by JSON.
@@ -65,37 +71,61 @@ module JSON
end
self.state = generator::State
const_set :State, self.state
- const_set :SAFE_STATE_PROTOTYPE, State.new
- const_set :FAST_STATE_PROTOTYPE, State.new(
+ const_set :SAFE_STATE_PROTOTYPE, State.new # for JRuby
+ const_set :FAST_STATE_PROTOTYPE, create_fast_state
+ const_set :PRETTY_STATE_PROTOTYPE, create_pretty_state
+ ensure
+ $VERBOSE = old
+ end
+
+ def create_fast_state
+ State.new(
:indent => '',
:space => '',
:object_nl => "",
:array_nl => "",
:max_nesting => false
)
- const_set :PRETTY_STATE_PROTOTYPE, State.new(
+ end
+
+ def create_pretty_state
+ State.new(
:indent => ' ',
:space => ' ',
:object_nl => "\n",
:array_nl => "\n"
)
- ensure
- $VERBOSE = old
end
# Returns the JSON generator module that is used by JSON. This is
- # either JSON::Ext::Generator or JSON::Pure::Generator.
+ # either JSON::Ext::Generator or JSON::Pure::Generator:
+ # JSON.generator # => JSON::Ext::Generator
attr_reader :generator
- # Returns the JSON generator state class that is used by JSON. This is
- # either JSON::Ext::Generator::State or JSON::Pure::Generator::State.
+ # Sets or Returns the JSON generator state class that is used by JSON. This is
+ # either JSON::Ext::Generator::State or JSON::Pure::Generator::State:
+ # JSON.state # => JSON::Ext::Generator::State
attr_accessor :state
+ end
+
+ DEFAULT_CREATE_ID = 'json_class'.freeze
+ private_constant :DEFAULT_CREATE_ID
+
+ CREATE_ID_TLS_KEY = "JSON.create_id".freeze
+ private_constant :CREATE_ID_TLS_KEY
+
+ # Sets create identifier, which is used to decide if the _json_create_
+ # hook of a class should be called; initial value is +json_class+:
+ # JSON.create_id # => 'json_class'
+ def self.create_id=(new_value)
+ Thread.current[CREATE_ID_TLS_KEY] = new_value.dup.freeze
+ end
- # This is create identifier, which is used to decide if the _json_create_
- # hook of a class should be called. It defaults to 'json_class'.
- attr_accessor :create_id
+ # Returns the current create identifier.
+ # See also JSON.create_id=.
+ def self.create_id
+ Thread.current[CREATE_ID_TLS_KEY] || DEFAULT_CREATE_ID
end
- self.create_id = 'json_class'
NaN = 0.0/0
@@ -126,7 +156,7 @@ module JSON
# This exception is raised if a generator or unparser error occurs.
class GeneratorError < JSONError; end
# For backwards compatibility
- UnparserError = GeneratorError
+ UnparserError = GeneratorError # :nodoc:
# This exception is raised if the required unicode support is missing on the
# system. Usually this means that the iconv library is not installed.
@@ -134,43 +164,69 @@ module JSON
module_function
- # Parse the JSON document _source_ into a Ruby data structure and return it.
- #
- # _opts_ can have the following
- # keys:
- # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
- # structures. Disable depth checking with :max_nesting => false. It
- # defaults to 100.
- # * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
- # defiance of RFC 7159 to be parsed by the Parser. This option defaults
- # to false.
- # * *symbolize_names*: If set to true, returns symbols for the names
- # (keys) in a JSON object. Otherwise strings are returned. Strings are
- # the default.
- # * *create_additions*: If set to false, the Parser doesn't create
- # additions even if a matching class and create_id was found. This option
- # defaults to false.
- # * *object_class*: Defaults to Hash
- # * *array_class*: Defaults to Array
+ # :call-seq:
+ # JSON.parse(source, opts) -> object
+ #
+ # Returns the Ruby objects created by parsing the given +source+.
+ #
+ # Argument +source+ contains the \String to be parsed.
+ #
+ # Argument +opts+, if given, contains a \Hash of options for the parsing.
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
+ #
+ # ---
+ #
+ # When +source+ is a \JSON array, returns a Ruby \Array:
+ # source = '["foo", 1.0, true, false, null]'
+ # ruby = JSON.parse(source)
+ # ruby # => ["foo", 1.0, true, false, nil]
+ # ruby.class # => Array
+ #
+ # When +source+ is a \JSON object, returns a Ruby \Hash:
+ # source = '{"a": "foo", "b": 1.0, "c": true, "d": false, "e": null}'
+ # ruby = JSON.parse(source)
+ # ruby # => {"a"=>"foo", "b"=>1.0, "c"=>true, "d"=>false, "e"=>nil}
+ # ruby.class # => Hash
+ #
+ # For examples of parsing for all \JSON data types, see
+ # {Parsing \JSON}[#module-JSON-label-Parsing+JSON].
+ #
+ # Parses nested JSON objects:
+ # source = <<-EOT
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # EOT
+ # ruby = JSON.parse(source)
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # ---
+ #
+ # Raises an exception if +source+ is not valid JSON:
+ # # Raises JSON::ParserError (783: unexpected token at ''):
+ # JSON.parse('')
+ #
def parse(source, opts = {})
Parser.new(source, **(opts||{})).parse
end
- # Parse the JSON document _source_ into a Ruby data structure and return it.
- # The bang version of the parse method defaults to the more dangerous values
- # for the _opts_ hash, so be sure only to parse trusted _source_ documents.
- #
- # _opts_ can have the following keys:
- # * *max_nesting*: The maximum depth of nesting allowed in the parsed data
- # structures. Enable depth checking with :max_nesting => anInteger. The
- # parse! methods defaults to not doing max depth checking: This can be
- # dangerous if someone wants to fill up your stack.
- # * *allow_nan*: If set to true, allow NaN, Infinity, and -Infinity in
- # defiance of RFC 7159 to be parsed by the Parser. This option defaults
- # to true.
- # * *create_additions*: If set to false, the Parser doesn't create
- # additions even if a matching class and create_id was found. This option
- # defaults to false.
+ # :call-seq:
+ # JSON.parse!(source, opts) -> object
+ #
+ # Calls
+ # parse(source, opts)
+ # with +source+ and possibly modified +opts+.
+ #
+ # Differences from JSON.parse:
+ # - Option +max_nesting+, if not provided, defaults to +false+,
+ # which disables checking for nesting depth.
+ # - Option +allow_nan+, if not provided, defaults to +true+.
def parse!(source, opts = {})
opts = {
:max_nesting => false,
@@ -179,37 +235,69 @@ module JSON
Parser.new(source, **(opts||{})).parse
end
- # Generate a JSON document from the Ruby data structure _obj_ and return
- # it. _state_ is * a JSON::State object,
- # * or a Hash like object (responding to to_hash),
- # * an object convertible into a hash by a to_h method,
- # that is used as or to configure a State object.
- #
- # It defaults to a state object, that creates the shortest possible JSON text
- # in one line, checks for circular data structures and doesn't allow NaN,
- # Infinity, and -Infinity.
- #
- # A _state_ hash can have the following keys:
- # * *indent*: a string used to indent levels (default: ''),
- # * *space*: a string that is put after, a : or , delimiter (default: ''),
- # * *space_before*: a string that is put before a : pair delimiter (default: ''),
- # * *object_nl*: a string that is put at the end of a JSON object (default: ''),
- # * *array_nl*: a string that is put at the end of a JSON array (default: ''),
- # * *allow_nan*: true if NaN, Infinity, and -Infinity should be
- # generated, otherwise an exception is thrown if these values are
- # encountered. This options defaults to false.
- # * *max_nesting*: The maximum depth of nesting allowed in the data
- # structures from which JSON is to be generated. Disable depth checking
- # with :max_nesting => false, it defaults to 100.
- #
- # See also the fast_generate for the fastest creation method with the least
- # amount of sanity checks, and the pretty_generate method for some
- # defaults for pretty output.
+ # :call-seq:
+ # JSON.load_file(path, opts={}) -> object
+ #
+ # Calls:
+ # parse(File.read(path), opts)
+ #
+ # See method #parse.
+ def load_file(filespec, opts = {})
+ parse(File.read(filespec), opts)
+ end
+
+ # :call-seq:
+ # JSON.load_file!(path, opts = {})
+ #
+ # Calls:
+ # JSON.parse!(File.read(path, opts))
+ #
+ # See method #parse!
+ def load_file!(filespec, opts = {})
+ parse!(File.read(filespec), opts)
+ end
+
+ # :call-seq:
+ # JSON.generate(obj, opts = nil) -> new_string
+ #
+ # Returns a \String containing the generated \JSON data.
+ #
+ # See also JSON.fast_generate, JSON.pretty_generate.
+ #
+ # Argument +obj+ is the Ruby object to be converted to \JSON.
+ #
+ # Argument +opts+, if given, contains a \Hash of options for the generation.
+ # See {Generating Options}[#module-JSON-label-Generating+Options].
+ #
+ # ---
+ #
+ # When +obj+ is an \Array, returns a \String containing a \JSON array:
+ # obj = ["foo", 1.0, true, false, nil]
+ # json = JSON.generate(obj)
+ # json # => '["foo",1.0,true,false,null]'
+ #
+ # When +obj+ is a \Hash, returns a \String containing a \JSON object:
+ # obj = {foo: 0, bar: 's', baz: :bat}
+ # json = JSON.generate(obj)
+ # json # => '{"foo":0,"bar":"s","baz":"bat"}'
+ #
+ # For examples of generating from other Ruby objects, see
+ # {Generating \JSON from Other Objects}[#module-JSON-label-Generating+JSON+from+Other+Objects].
+ #
+ # ---
+ #
+ # Raises an exception if any formatting option is not a \String.
+ #
+ # Raises an exception if +obj+ contains circular references:
+ # a = []; b = []; a.push(b); b.push(a)
+ # # Raises JSON::NestingError (nesting of 100 is too deep):
+ # JSON.generate(a)
+ #
def generate(obj, opts = nil)
if State === opts
state, opts = opts, nil
else
- state = SAFE_STATE_PROTOTYPE.dup
+ state = State.new
end
if opts
if opts.respond_to? :to_hash
@@ -231,16 +319,24 @@ module JSON
module_function :unparse
# :startdoc:
- # Generate a JSON document from the Ruby data structure _obj_ and return it.
- # This method disables the checks for circles in Ruby objects.
+ # :call-seq:
+ # JSON.fast_generate(obj, opts) -> new_string
+ #
+ # Arguments +obj+ and +opts+ here are the same as
+ # arguments +obj+ and +opts+ in JSON.generate.
+ #
+ # By default, generates \JSON data without checking
+ # for circular references in +obj+ (option +max_nesting+ set to +false+, disabled).
#
- # *WARNING*: Be careful not to pass any Ruby data structures with circles as
- # _obj_ argument because this will cause JSON to go into an infinite loop.
+ # Raises an exception if +obj+ contains circular references:
+ # a = []; b = []; a.push(b); b.push(a)
+ # # Raises SystemStackError (stack level too deep):
+ # JSON.fast_generate(a)
def fast_generate(obj, opts = nil)
if State === opts
state, opts = opts, nil
else
- state = FAST_STATE_PROTOTYPE.dup
+ state = JSON.create_fast_state
end
if opts
if opts.respond_to? :to_hash
@@ -261,17 +357,41 @@ module JSON
module_function :fast_unparse
# :startdoc:
- # Generate a JSON document from the Ruby data structure _obj_ and return it.
- # The returned document is a prettier form of the document returned by
- # #unparse.
+ # :call-seq:
+ # JSON.pretty_generate(obj, opts = nil) -> new_string
+ #
+ # Arguments +obj+ and +opts+ here are the same as
+ # arguments +obj+ and +opts+ in JSON.generate.
+ #
+ # Default options are:
+ # {
+ # indent: ' ', # Two spaces
+ # space: ' ', # One space
+ # array_nl: "\n", # Newline
+ # object_nl: "\n" # Newline
+ # }
+ #
+ # Example:
+ # obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
+ # json = JSON.pretty_generate(obj)
+ # puts json
+ # Output:
+ # {
+ # "foo": [
+ # "bar",
+ # "baz"
+ # ],
+ # "bat": {
+ # "bam": 0,
+ # "bad": 1
+ # }
+ # }
#
- # The _opts_ argument can be used to configure the generator. See the
- # generate method for a more detailed explanation.
def pretty_generate(obj, opts = nil)
if State === opts
state, opts = opts, nil
else
- state = PRETTY_STATE_PROTOTYPE.dup
+ state = JSON.create_pretty_state
end
if opts
if opts.respond_to? :to_hash
@@ -293,10 +413,10 @@ module JSON
# :startdoc:
class << self
- # The global default options for the JSON.load method:
- # :max_nesting: false
- # :allow_nan: true
- # :allow_blank: true
+ # Sets or returns default options for the JSON.load method.
+ # Initially:
+ # opts = JSON.load_default_options
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
attr_accessor :load_default_options
end
self.load_default_options = {
@@ -306,20 +426,134 @@ module JSON
:create_additions => true,
}
- # Load a ruby data structure from a JSON _source_ and return it. A source can
- # either be a string-like object, an IO-like object, or an object responding
- # to the read method. If _proc_ was given, it will be called with any nested
- # Ruby object as an argument recursively in depth first order. To modify the
- # default options pass in the optional _options_ argument as well.
+ # :call-seq:
+ # JSON.load(source, proc = nil, options = {}) -> object
+ #
+ # Returns the Ruby objects created by parsing the given +source+.
+ #
+ # - Argument +source+ must be, or be convertible to, a \String:
+ # - If +source+ responds to instance method +to_str+,
+ # <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.
+ # BEWARE: This method is meant to serialise data from trusted user input,
+ # like from your own database server or clients under your control, it could
+ # be dangerous to allow untrusted users to pass JSON sources into it.
+ # - Argument +opts+, if given, contains a \Hash of options for the parsing.
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
+ # The default options can be changed via method JSON.load_default_options=.
+ #
+ # ---
+ #
+ # When no +proc+ is given, modifies +source+ as above and returns the result of
+ # <tt>parse(source, opts)</tt>; see #parse.
+ #
+ # Source for following examples:
+ # source = <<-EOT
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # EOT
#
- # BEWARE: This method is meant to serialise data from trusted user input,
- # like from your own database server or clients under your control, it could
- # be dangerous to allow untrusted users to pass JSON sources into it. The
- # default options for the parser can be changed via the load_default_options
- # method.
+ # Load a \String:
+ # ruby = JSON.load(source)
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load an \IO object:
+ # require 'stringio'
+ # object = JSON.load(StringIO.new(source))
+ # object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load a \File object:
+ # path = 't.json'
+ # File.write(path, source)
+ # File.open(path) do |file|
+ # JSON.load(file)
+ # end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # ---
+ #
+ # When +proc+ is given:
+ # - Modifies +source+ as above.
+ # - Gets the +result+ from calling <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
+ # {
+ # "users": [
+ # {"type": "User", "username": "jane", "email": "jane@example.com"},
+ # {"type": "User", "username": "john", "email": "john@example.com"}
+ # ],
+ # "accounts": [
+ # {"account": {"type": "Account", "paid": true, "account_id": "1234"}},
+ # {"account": {"type": "Account", "paid": false, "account_id": "1235"}}
+ # ],
+ # "admins": {"type": "Admin", "password": "0wn3d"}
+ # }
+ # EOF
+ # # Deserializer method.
+ # def deserialize_obj(obj, safe_types = %w(User Account Admin))
+ # type = obj.is_a?(Hash) && obj["type"]
+ # safe_types.include?(type) ? Object.const_get(type).new(obj) : obj
+ # end
+ # # Call to JSON.load
+ # ruby = JSON.load(json, proc {|obj|
+ # case obj
+ # when Hash
+ # obj.each {|k, v| obj[k] = deserialize_obj v }
+ # when Array
+ # obj.map! {|v| deserialize_obj v }
+ # end
+ # })
+ # pp ruby
+ # Output:
+ # {"users"=>
+ # [#<User: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"}>}
#
- # This method is part of the implementation of the load/dump interface of
- # Marshal and YAML.
def load(source, proc = nil, options = {})
opts = load_default_options.merge options
if source.respond_to? :to_str
@@ -338,7 +572,7 @@ module JSON
end
# Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
- def recurse_proc(result, &proc)
+ def recurse_proc(result, &proc) # :nodoc:
case result
when Array
result.each { |x| recurse_proc x, &proc }
@@ -355,32 +589,45 @@ module JSON
module_function :restore
class << self
- # The global default options for the JSON.dump method:
- # :max_nesting: false
- # :allow_nan: true
- # :allow_blank: true
+ # Sets or returns the default options for the JSON.dump method.
+ # Initially:
+ # opts = JSON.dump_default_options
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false}
attr_accessor :dump_default_options
end
self.dump_default_options = {
:max_nesting => false,
:allow_nan => true,
+ :escape_slash => false,
}
- # Dumps _obj_ as a JSON string, i.e. calls generate on the object and returns
- # the result.
+ # :call-seq:
+ # JSON.dump(obj, io = nil, limit = nil)
+ #
+ # Dumps +obj+ as a \JSON string, i.e. calls generate on the object and returns the result.
+ #
+ # The default options can be changed via method JSON.dump_default_options.
#
- # If anIO (an IO-like object or an object that responds to the write method)
- # was given, the resulting JSON is written to it.
+ # - Argument +io+, if given, should respond to method +write+;
+ # the \JSON \String is written to +io+, and +io+ is returned.
+ # If +io+ is not given, the \JSON \String is returned.
+ # - Argument +limit+, if given, is passed to JSON.generate as option +max_nesting+.
#
- # If the number of nested arrays or objects exceeds _limit_, an ArgumentError
- # exception is raised. This argument is similar (but not exactly the
- # same!) to the _limit_ argument in Marshal.dump.
+ # ---
#
- # The default options for the generator can be changed via the
- # dump_default_options method.
+ # When argument +io+ is not given, returns the \JSON \String generated from +obj+:
+ # obj = {foo: [0, 1], bar: {baz: 2, bat: 3}, bam: :bad}
+ # json = JSON.dump(obj)
+ # json # => "{\"foo\":[0,1],\"bar\":{\"baz\":2,\"bat\":3},\"bam\":\"bad\"}"
#
- # This method is part of the implementation of the load/dump interface of
- # Marshal and YAML.
+ # When argument +io+ is given, writes the \JSON \String to +io+ and returns +io+:
+ # path = 't.json'
+ # File.open(path, 'w') do |file|
+ # JSON.dump(obj, file)
+ # end # => #<File:t.json (closed)>
+ # puts File.read(path)
+ # Output:
+ # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
def dump(obj, anIO = nil, limit = nil)
if anIO and limit.nil?
anIO = anIO.to_io if anIO.respond_to?(:to_io)
@@ -402,7 +649,7 @@ module JSON
raise ArgumentError, "exceed depth limit"
end
- # Encodes string using Ruby's _String.encode_
+ # Encodes string using String.encode.
def self.iconv(to, from, string)
string.encode(to, from)
end
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index 9d781df875..7a72272bd0 100644
--- a/ext/json/lib/json/version.rb
+++ b/ext/json/lib/json/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module JSON
# JSON version
- VERSION = '2.3.0'
+ VERSION = '2.5.1'
VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
diff --git a/ext/json/parser/depend b/ext/json/parser/depend
index d0c9c2d2a6..23d704ac85 100644
--- a/ext/json/parser/depend
+++ b/ext/json/parser/depend
@@ -5,8 +5,157 @@ parser.o: parser.c parser.h $(srcdir)/../fbuffer/fbuffer.h
parser.o: $(RUBY_EXTCONF_H)
parser.o: $(arch_hdrdir)/ruby/config.h
parser.o: $(hdrdir)/ruby.h
+parser.o: $(hdrdir)/ruby/internal/anyargs.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+parser.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+parser.o: $(hdrdir)/ruby/internal/assume.h
+parser.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+parser.o: $(hdrdir)/ruby/internal/attr/artificial.h
+parser.o: $(hdrdir)/ruby/internal/attr/cold.h
+parser.o: $(hdrdir)/ruby/internal/attr/const.h
+parser.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+parser.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+parser.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+parser.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+parser.o: $(hdrdir)/ruby/internal/attr/error.h
+parser.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+parser.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+parser.o: $(hdrdir)/ruby/internal/attr/format.h
+parser.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+parser.o: $(hdrdir)/ruby/internal/attr/noalias.h
+parser.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+parser.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+parser.o: $(hdrdir)/ruby/internal/attr/noinline.h
+parser.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+parser.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+parser.o: $(hdrdir)/ruby/internal/attr/pure.h
+parser.o: $(hdrdir)/ruby/internal/attr/restrict.h
+parser.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+parser.o: $(hdrdir)/ruby/internal/attr/warning.h
+parser.o: $(hdrdir)/ruby/internal/attr/weakref.h
+parser.o: $(hdrdir)/ruby/internal/cast.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+parser.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+parser.o: $(hdrdir)/ruby/internal/compiler_since.h
+parser.o: $(hdrdir)/ruby/internal/config.h
+parser.o: $(hdrdir)/ruby/internal/constant_p.h
+parser.o: $(hdrdir)/ruby/internal/core.h
+parser.o: $(hdrdir)/ruby/internal/core/rarray.h
+parser.o: $(hdrdir)/ruby/internal/core/rbasic.h
+parser.o: $(hdrdir)/ruby/internal/core/rbignum.h
+parser.o: $(hdrdir)/ruby/internal/core/rclass.h
+parser.o: $(hdrdir)/ruby/internal/core/rdata.h
+parser.o: $(hdrdir)/ruby/internal/core/rfile.h
+parser.o: $(hdrdir)/ruby/internal/core/rhash.h
+parser.o: $(hdrdir)/ruby/internal/core/robject.h
+parser.o: $(hdrdir)/ruby/internal/core/rregexp.h
+parser.o: $(hdrdir)/ruby/internal/core/rstring.h
+parser.o: $(hdrdir)/ruby/internal/core/rstruct.h
+parser.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+parser.o: $(hdrdir)/ruby/internal/ctype.h
+parser.o: $(hdrdir)/ruby/internal/dllexport.h
+parser.o: $(hdrdir)/ruby/internal/dosish.h
+parser.o: $(hdrdir)/ruby/internal/error.h
+parser.o: $(hdrdir)/ruby/internal/eval.h
+parser.o: $(hdrdir)/ruby/internal/event.h
+parser.o: $(hdrdir)/ruby/internal/fl_type.h
+parser.o: $(hdrdir)/ruby/internal/gc.h
+parser.o: $(hdrdir)/ruby/internal/glob.h
+parser.o: $(hdrdir)/ruby/internal/globals.h
+parser.o: $(hdrdir)/ruby/internal/has/attribute.h
+parser.o: $(hdrdir)/ruby/internal/has/builtin.h
+parser.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+parser.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+parser.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+parser.o: $(hdrdir)/ruby/internal/has/extension.h
+parser.o: $(hdrdir)/ruby/internal/has/feature.h
+parser.o: $(hdrdir)/ruby/internal/has/warning.h
+parser.o: $(hdrdir)/ruby/internal/intern/array.h
+parser.o: $(hdrdir)/ruby/internal/intern/bignum.h
+parser.o: $(hdrdir)/ruby/internal/intern/class.h
+parser.o: $(hdrdir)/ruby/internal/intern/compar.h
+parser.o: $(hdrdir)/ruby/internal/intern/complex.h
+parser.o: $(hdrdir)/ruby/internal/intern/cont.h
+parser.o: $(hdrdir)/ruby/internal/intern/dir.h
+parser.o: $(hdrdir)/ruby/internal/intern/enum.h
+parser.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+parser.o: $(hdrdir)/ruby/internal/intern/error.h
+parser.o: $(hdrdir)/ruby/internal/intern/eval.h
+parser.o: $(hdrdir)/ruby/internal/intern/file.h
+parser.o: $(hdrdir)/ruby/internal/intern/gc.h
+parser.o: $(hdrdir)/ruby/internal/intern/hash.h
+parser.o: $(hdrdir)/ruby/internal/intern/io.h
+parser.o: $(hdrdir)/ruby/internal/intern/load.h
+parser.o: $(hdrdir)/ruby/internal/intern/marshal.h
+parser.o: $(hdrdir)/ruby/internal/intern/numeric.h
+parser.o: $(hdrdir)/ruby/internal/intern/object.h
+parser.o: $(hdrdir)/ruby/internal/intern/parse.h
+parser.o: $(hdrdir)/ruby/internal/intern/proc.h
+parser.o: $(hdrdir)/ruby/internal/intern/process.h
+parser.o: $(hdrdir)/ruby/internal/intern/random.h
+parser.o: $(hdrdir)/ruby/internal/intern/range.h
+parser.o: $(hdrdir)/ruby/internal/intern/rational.h
+parser.o: $(hdrdir)/ruby/internal/intern/re.h
+parser.o: $(hdrdir)/ruby/internal/intern/ruby.h
+parser.o: $(hdrdir)/ruby/internal/intern/select.h
+parser.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+parser.o: $(hdrdir)/ruby/internal/intern/signal.h
+parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+parser.o: $(hdrdir)/ruby/internal/intern/string.h
+parser.o: $(hdrdir)/ruby/internal/intern/struct.h
+parser.o: $(hdrdir)/ruby/internal/intern/thread.h
+parser.o: $(hdrdir)/ruby/internal/intern/time.h
+parser.o: $(hdrdir)/ruby/internal/intern/variable.h
+parser.o: $(hdrdir)/ruby/internal/intern/vm.h
+parser.o: $(hdrdir)/ruby/internal/interpreter.h
+parser.o: $(hdrdir)/ruby/internal/iterator.h
+parser.o: $(hdrdir)/ruby/internal/memory.h
+parser.o: $(hdrdir)/ruby/internal/method.h
+parser.o: $(hdrdir)/ruby/internal/module.h
+parser.o: $(hdrdir)/ruby/internal/newobj.h
+parser.o: $(hdrdir)/ruby/internal/rgengc.h
+parser.o: $(hdrdir)/ruby/internal/scan_args.h
+parser.o: $(hdrdir)/ruby/internal/special_consts.h
+parser.o: $(hdrdir)/ruby/internal/static_assert.h
+parser.o: $(hdrdir)/ruby/internal/stdalign.h
+parser.o: $(hdrdir)/ruby/internal/stdbool.h
+parser.o: $(hdrdir)/ruby/internal/symbol.h
+parser.o: $(hdrdir)/ruby/internal/token_paste.h
+parser.o: $(hdrdir)/ruby/internal/value.h
+parser.o: $(hdrdir)/ruby/internal/value_type.h
+parser.o: $(hdrdir)/ruby/internal/variable.h
+parser.o: $(hdrdir)/ruby/internal/warning_push.h
+parser.o: $(hdrdir)/ruby/internal/xmalloc.h
parser.o: $(hdrdir)/ruby/assert.h
parser.o: $(hdrdir)/ruby/backward.h
+parser.o: $(hdrdir)/ruby/backward/2/assume.h
+parser.o: $(hdrdir)/ruby/backward/2/attributes.h
+parser.o: $(hdrdir)/ruby/backward/2/bool.h
+parser.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+parser.o: $(hdrdir)/ruby/backward/2/inttypes.h
+parser.o: $(hdrdir)/ruby/backward/2/limits.h
+parser.o: $(hdrdir)/ruby/backward/2/long_long.h
+parser.o: $(hdrdir)/ruby/backward/2/stdalign.h
+parser.o: $(hdrdir)/ruby/backward/2/stdarg.h
parser.o: $(hdrdir)/ruby/defines.h
parser.o: $(hdrdir)/ruby/encoding.h
parser.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/json/parser/extconf.rb b/ext/json/parser/extconf.rb
index f7360d46b2..f832b56a61 100644
--- a/ext/json/parser/extconf.rb
+++ b/ext/json/parser/extconf.rb
@@ -3,4 +3,29 @@ require 'mkmf'
have_func("rb_enc_raise", "ruby.h")
+# checking if String#-@ (str_uminus) dedupes... '
+begin
+ a = -(%w(t e s t).join)
+ b = -(%w(t e s t).join)
+ if a.equal?(b)
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 '
+ else
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
+ end
+rescue NoMethodError
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
+end
+
+# checking if String#-@ (str_uminus) directly interns frozen strings... '
+begin
+ s = rand.to_s.freeze
+ if (-s).equal?(s) && (-s.dup).equal?(s)
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=1 '
+ else
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
+ end
+rescue NoMethodError
+ $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
+end
+
create_makefile 'json/ext/parser'
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c
index 0f98cf9827..29b5674d96 100644
--- a/ext/json/parser/parser.c
+++ b/ext/json/parser/parser.c
@@ -91,13 +91,12 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
static VALUE CNaN, CInfinity, CMinusInfinity;
-static VALUE cBigDecimal = Qundef;
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
i_object_class, i_array_class, i_decimal_class, i_key_p,
i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
- i_leftshift, i_new, i_BigDecimal;
+ i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
#line 126 "parser.rl"
@@ -112,7 +111,7 @@ enum {JSON_object_error = 0};
enum {JSON_object_en_main = 1};
-#line 167 "parser.rl"
+#line 168 "parser.rl"
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -133,7 +132,7 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
cs = JSON_object_start;
}
-#line 182 "parser.rl"
+#line 183 "parser.rl"
#line 139 "parser.c"
{
@@ -163,7 +162,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 149 "parser.rl"
+#line 150 "parser.rl"
{
char *np;
json->parsing_name = 1;
@@ -251,6 +250,7 @@ tr11:
p--; {p++; cs = 9; goto _out;}
} else {
if (NIL_P(json->object_class)) {
+ OBJ_FREEZE(last_name);
rb_hash_aset(*result, last_name, v);
} else {
rb_funcall(*result, i_aset, 2, last_name, v);
@@ -263,7 +263,7 @@ st9:
if ( ++p == pe )
goto _test_eof9;
case 9:
-#line 267 "parser.c"
+#line 268 "parser.c"
switch( (*p) ) {
case 13: goto st9;
case 32: goto st9;
@@ -352,14 +352,14 @@ case 18:
goto st9;
goto st18;
tr4:
-#line 157 "parser.rl"
+#line 158 "parser.rl"
{ p--; {p++; cs = 27; goto _out;} }
goto st27;
st27:
if ( ++p == pe )
goto _test_eof27;
case 27:
-#line 363 "parser.c"
+#line 364 "parser.c"
goto st0;
st19:
if ( ++p == pe )
@@ -457,7 +457,7 @@ case 26:
_out: {}
}
-#line 183 "parser.rl"
+#line 184 "parser.rl"
if (cs >= JSON_object_first_final) {
if (json->create_additions) {
@@ -482,7 +482,7 @@ case 26:
-#line 486 "parser.c"
+#line 487 "parser.c"
enum {JSON_value_start = 1};
enum {JSON_value_first_final = 29};
enum {JSON_value_error = 0};
@@ -490,7 +490,7 @@ enum {JSON_value_error = 0};
enum {JSON_value_en_main = 1};
-#line 283 "parser.rl"
+#line 284 "parser.rl"
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -498,14 +498,14 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 502 "parser.c"
+#line 503 "parser.c"
{
cs = JSON_value_start;
}
-#line 290 "parser.rl"
+#line 291 "parser.rl"
-#line 509 "parser.c"
+#line 510 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -539,14 +539,14 @@ st0:
cs = 0;
goto _out;
tr2:
-#line 235 "parser.rl"
+#line 236 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, result);
if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
}
goto st29;
tr3:
-#line 240 "parser.rl"
+#line 241 "parser.rl"
{
char *np;
if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) {
@@ -566,7 +566,7 @@ tr3:
}
goto st29;
tr7:
-#line 258 "parser.rl"
+#line 259 "parser.rl"
{
char *np;
np = JSON_parse_array(json, p, pe, result, current_nesting + 1);
@@ -574,7 +574,7 @@ tr7:
}
goto st29;
tr11:
-#line 264 "parser.rl"
+#line 265 "parser.rl"
{
char *np;
np = JSON_parse_object(json, p, pe, result, current_nesting + 1);
@@ -582,7 +582,7 @@ tr11:
}
goto st29;
tr25:
-#line 228 "parser.rl"
+#line 229 "parser.rl"
{
if (json->allow_nan) {
*result = CInfinity;
@@ -592,7 +592,7 @@ tr25:
}
goto st29;
tr27:
-#line 221 "parser.rl"
+#line 222 "parser.rl"
{
if (json->allow_nan) {
*result = CNaN;
@@ -602,19 +602,19 @@ tr27:
}
goto st29;
tr31:
-#line 215 "parser.rl"
+#line 216 "parser.rl"
{
*result = Qfalse;
}
goto st29;
tr34:
-#line 212 "parser.rl"
+#line 213 "parser.rl"
{
*result = Qnil;
}
goto st29;
tr37:
-#line 218 "parser.rl"
+#line 219 "parser.rl"
{
*result = Qtrue;
}
@@ -623,9 +623,9 @@ st29:
if ( ++p == pe )
goto _test_eof29;
case 29:
-#line 270 "parser.rl"
+#line 271 "parser.rl"
{ p--; {p++; cs = 29; goto _out;} }
-#line 629 "parser.c"
+#line 630 "parser.c"
switch( (*p) ) {
case 13: goto st29;
case 32: goto st29;
@@ -866,7 +866,11 @@ case 28:
_out: {}
}
-#line 291 "parser.rl"
+#line 292 "parser.rl"
+
+ if (json->freeze) {
+ OBJ_FREEZE(*result);
+ }
if (cs >= JSON_value_first_final) {
return p;
@@ -876,7 +880,7 @@ case 28:
}
-#line 880 "parser.c"
+#line 885 "parser.c"
enum {JSON_integer_start = 1};
enum {JSON_integer_first_final = 3};
enum {JSON_integer_error = 0};
@@ -884,7 +888,7 @@ enum {JSON_integer_error = 0};
enum {JSON_integer_en_main = 1};
-#line 307 "parser.rl"
+#line 312 "parser.rl"
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -892,15 +896,15 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
int cs = EVIL;
-#line 896 "parser.c"
+#line 901 "parser.c"
{
cs = JSON_integer_start;
}
-#line 314 "parser.rl"
+#line 319 "parser.rl"
json->memo = p;
-#line 904 "parser.c"
+#line 909 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -934,14 +938,14 @@ case 3:
goto st0;
goto tr4;
tr4:
-#line 304 "parser.rl"
+#line 309 "parser.rl"
{ p--; {p++; cs = 4; goto _out;} }
goto st4;
st4:
if ( ++p == pe )
goto _test_eof4;
case 4:
-#line 945 "parser.c"
+#line 950 "parser.c"
goto st0;
st5:
if ( ++p == pe )
@@ -960,7 +964,7 @@ case 5:
_out: {}
}
-#line 316 "parser.rl"
+#line 321 "parser.rl"
if (cs >= JSON_integer_first_final) {
long len = p - json->memo;
@@ -975,7 +979,7 @@ case 5:
}
-#line 979 "parser.c"
+#line 984 "parser.c"
enum {JSON_float_start = 1};
enum {JSON_float_first_final = 8};
enum {JSON_float_error = 0};
@@ -983,36 +987,23 @@ enum {JSON_float_error = 0};
enum {JSON_float_en_main = 1};
-#line 341 "parser.rl"
+#line 346 "parser.rl"
-static int is_bigdecimal_class(VALUE obj)
-{
- if (cBigDecimal == Qundef) {
- if (rb_const_defined(rb_cObject, i_BigDecimal)) {
- cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
- }
- else {
- return 0;
- }
- }
- return obj == cBigDecimal;
-}
-
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
{
int cs = EVIL;
-#line 1008 "parser.c"
+#line 1013 "parser.c"
{
cs = JSON_float_start;
}
-#line 361 "parser.rl"
+#line 366 "parser.rl"
json->memo = p;
-#line 1016 "parser.c"
+#line 1021 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1070,14 +1061,14 @@ case 8:
goto st0;
goto tr9;
tr9:
-#line 335 "parser.rl"
+#line 340 "parser.rl"
{ p--; {p++; cs = 9; goto _out;} }
goto st9;
st9:
if ( ++p == pe )
goto _test_eof9;
case 9:
-#line 1081 "parser.c"
+#line 1086 "parser.c"
goto st0;
st5:
if ( ++p == pe )
@@ -1138,24 +1129,49 @@ case 7:
_out: {}
}
-#line 363 "parser.rl"
+#line 368 "parser.rl"
if (cs >= JSON_float_first_final) {
+ VALUE mod = Qnil;
+ ID method_id = 0;
+ if (rb_respond_to(json->decimal_class, i_try_convert)) {
+ mod = json->decimal_class;
+ method_id = i_try_convert;
+ } else if (rb_respond_to(json->decimal_class, i_new)) {
+ mod = json->decimal_class;
+ method_id = i_new;
+ } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
+ VALUE name = rb_class_name(json->decimal_class);
+ const char *name_cstr = RSTRING_PTR(name);
+ const char *last_colon = strrchr(name_cstr, ':');
+ if (last_colon) {
+ const char *mod_path_end = last_colon - 1;
+ VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
+ mod = rb_path_to_class(mod_path);
+
+ const char *method_name_beg = last_colon + 1;
+ long before_len = method_name_beg - name_cstr;
+ long len = RSTRING_LEN(name) - before_len;
+ VALUE method_name = rb_str_substr(name, before_len, len);
+ method_id = SYM2ID(rb_str_intern(method_name));
+ } else {
+ mod = rb_mKernel;
+ method_id = SYM2ID(rb_str_intern(name));
+ }
+ }
+
long len = p - json->memo;
fbuffer_clear(json->fbuffer);
fbuffer_append(json->fbuffer, json->memo, len);
fbuffer_append_char(json->fbuffer, '\0');
- if (NIL_P(json->decimal_class)) {
- *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
+
+ if (method_id) {
+ VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
+ *result = rb_funcallv(mod, method_id, 1, &text);
} else {
- VALUE text;
- text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
- if (is_bigdecimal_class(json->decimal_class)) {
- *result = rb_funcall(Qnil, i_BigDecimal, 1, text);
- } else {
- *result = rb_funcall(json->decimal_class, i_new, 1, text);
- }
+ *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
}
+
return p + 1;
} else {
return NULL;
@@ -1164,7 +1180,7 @@ case 7:
-#line 1168 "parser.c"
+#line 1173 "parser.c"
enum {JSON_array_start = 1};
enum {JSON_array_first_final = 17};
enum {JSON_array_error = 0};
@@ -1172,7 +1188,7 @@ enum {JSON_array_error = 0};
enum {JSON_array_en_main = 1};
-#line 416 "parser.rl"
+#line 421 "parser.rl"
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
@@ -1186,14 +1202,14 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
*result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
-#line 1190 "parser.c"
+#line 1195 "parser.c"
{
cs = JSON_array_start;
}
-#line 429 "parser.rl"
+#line 434 "parser.rl"
-#line 1197 "parser.c"
+#line 1202 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1232,7 +1248,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 393 "parser.rl"
+#line 398 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
@@ -1252,7 +1268,7 @@ st3:
if ( ++p == pe )
goto _test_eof3;
case 3:
-#line 1256 "parser.c"
+#line 1261 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -1352,14 +1368,14 @@ case 12:
goto st3;
goto st12;
tr4:
-#line 408 "parser.rl"
+#line 413 "parser.rl"
{ p--; {p++; cs = 17; goto _out;} }
goto st17;
st17:
if ( ++p == pe )
goto _test_eof17;
case 17:
-#line 1363 "parser.c"
+#line 1368 "parser.c"
goto st0;
st13:
if ( ++p == pe )
@@ -1415,7 +1431,7 @@ case 16:
_out: {}
}
-#line 430 "parser.rl"
+#line 435 "parser.rl"
if(cs >= JSON_array_first_final) {
return p + 1;
@@ -1504,7 +1520,7 @@ static VALUE json_string_unescape(VALUE result, char *string, char *stringEnd)
}
-#line 1508 "parser.c"
+#line 1513 "parser.c"
enum {JSON_string_start = 1};
enum {JSON_string_first_final = 8};
enum {JSON_string_error = 0};
@@ -1512,7 +1528,7 @@ enum {JSON_string_error = 0};
enum {JSON_string_en_main = 1};
-#line 537 "parser.rl"
+#line 542 "parser.rl"
static int
@@ -1534,15 +1550,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_str_buf_new(0);
-#line 1538 "parser.c"
+#line 1543 "parser.c"
{
cs = JSON_string_start;
}
-#line 558 "parser.rl"
+#line 563 "parser.rl"
json->memo = p;
-#line 1546 "parser.c"
+#line 1551 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1563,11 +1579,11 @@ case 2:
case 34: goto tr2;
case 92: goto st3;
}
- if ( 0 <= (*p) && (*p) <= 31 )
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
goto st0;
goto st2;
tr2:
-#line 523 "parser.rl"
+#line 528 "parser.rl"
{
*result = json_string_unescape(*result, json->memo + 1, p);
if (NIL_P(*result)) {
@@ -1578,14 +1594,14 @@ tr2:
{p = (( p + 1))-1;}
}
}
-#line 534 "parser.rl"
+#line 539 "parser.rl"
{ p--; {p++; cs = 8; goto _out;} }
goto st8;
st8:
if ( ++p == pe )
goto _test_eof8;
case 8:
-#line 1589 "parser.c"
+#line 1594 "parser.c"
goto st0;
st3:
if ( ++p == pe )
@@ -1593,7 +1609,7 @@ st3:
case 3:
if ( (*p) == 117 )
goto st4;
- if ( 0 <= (*p) && (*p) <= 31 )
+ if ( 0 <= (signed char)(*p) && (*p) <= 31 )
goto st0;
goto st2;
st4:
@@ -1661,7 +1677,7 @@ case 7:
_out: {}
}
-#line 560 "parser.rl"
+#line 565 "parser.rl"
if (json->create_additions && RTEST(match_string = json->match_string)) {
VALUE klass;
@@ -1677,7 +1693,22 @@ case 7:
if (json->symbolize_names && json->parsing_name) {
*result = rb_str_intern(*result);
} else if (RB_TYPE_P(*result, T_STRING)) {
+# if STR_UMINUS_DEDUPE_FROZEN
+ if (json->freeze) {
+ // 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
+ if (json->freeze) {
+ // MRI 2.5 and older do not deduplicate strings that are already
+ // frozen.
+ *result = rb_funcall(*result, i_uminus, 0);
+ }
+# else
rb_str_resize(*result, RSTRING_LEN(*result));
+# endif
}
if (cs >= JSON_string_first_final) {
return p + 1;
@@ -1785,6 +1816,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
} else {
json->symbolize_names = 0;
}
+ tmp = ID2SYM(i_freeze);
+ if (option_given_p(opts, tmp)) {
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
+ } else {
+ json->freeze = 0;
+ }
tmp = ID2SYM(i_create_additions);
if (option_given_p(opts, tmp)) {
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -1848,7 +1885,7 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
}
-#line 1852 "parser.c"
+#line 1878 "parser.c"
enum {JSON_start = 1};
enum {JSON_first_final = 10};
enum {JSON_error = 0};
@@ -1856,7 +1893,7 @@ enum {JSON_error = 0};
enum {JSON_en_main = 1};
-#line 760 "parser.rl"
+#line 786 "parser.rl"
/*
@@ -1873,16 +1910,16 @@ static VALUE cParser_parse(VALUE self)
GET_PARSER;
-#line 1877 "parser.c"
+#line 1903 "parser.c"
{
cs = JSON_start;
}
-#line 776 "parser.rl"
+#line 802 "parser.rl"
p = json->source;
pe = p + json->len;
-#line 1886 "parser.c"
+#line 1912 "parser.c"
{
if ( p == pe )
goto _test_eof;
@@ -1916,7 +1953,7 @@ st0:
cs = 0;
goto _out;
tr2:
-#line 752 "parser.rl"
+#line 778 "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;}
@@ -1926,7 +1963,7 @@ st10:
if ( ++p == pe )
goto _test_eof10;
case 10:
-#line 1930 "parser.c"
+#line 1956 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
@@ -2015,7 +2052,7 @@ case 9:
_out: {}
}
-#line 779 "parser.rl"
+#line 805 "parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
@@ -2082,6 +2119,10 @@ static VALUE cParser_source(VALUE self)
void Init_parser(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
#undef rb_intern
rb_require("json/common");
mJSON = rb_define_module("JSON");
@@ -2124,7 +2165,9 @@ void Init_parser(void)
i_aref = rb_intern("[]");
i_leftshift = rb_intern("<<");
i_new = rb_intern("new");
- i_BigDecimal = rb_intern("BigDecimal");
+ i_try_convert = rb_intern("try_convert");
+ i_freeze = rb_intern("freeze");
+ i_uminus = rb_intern("-@");
}
/*
diff --git a/ext/json/parser/parser.h b/ext/json/parser/parser.h
index e6cf779024..e3eb920cc6 100644
--- a/ext/json/parser/parser.h
+++ b/ext/json/parser/parser.h
@@ -37,6 +37,7 @@ typedef struct JSON_ParserStruct {
int allow_nan;
int parsing_name;
int symbolize_names;
+ int freeze;
VALUE object_class;
VALUE array_class;
VALUE decimal_class;
diff --git a/ext/json/parser/parser.rl b/ext/json/parser/parser.rl
index 6b38bb283a..1da70c544c 100644
--- a/ext/json/parser/parser.rl
+++ b/ext/json/parser/parser.rl
@@ -89,13 +89,12 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
static VALUE CNaN, CInfinity, CMinusInfinity;
-static VALUE cBigDecimal = Qundef;
static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
i_object_class, i_array_class, i_decimal_class, i_key_p,
i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
- i_leftshift, i_new, i_BigDecimal;
+ i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
%%{
machine JSON_common;
@@ -138,6 +137,7 @@ static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
fhold; fbreak;
} else {
if (NIL_P(json->object_class)) {
+ OBJ_FREEZE(last_name);
rb_hash_aset(*result, last_name, v);
} else {
rb_funcall(*result, i_aset, 2, last_name, v);
@@ -289,6 +289,10 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
%% write init;
%% write exec;
+ if (json->freeze) {
+ OBJ_FREEZE(*result);
+ }
+
if (cs >= JSON_value_first_final) {
return p;
} else {
@@ -340,19 +344,6 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
) (^[0-9Ee.\-]? @exit );
}%%
-static int is_bigdecimal_class(VALUE obj)
-{
- if (cBigDecimal == Qundef) {
- if (rb_const_defined(rb_cObject, i_BigDecimal)) {
- cBigDecimal = rb_const_get_at(rb_cObject, i_BigDecimal);
- }
- else {
- return 0;
- }
- }
- return obj == cBigDecimal;
-}
-
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
{
int cs = EVIL;
@@ -362,21 +353,46 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
%% write exec;
if (cs >= JSON_float_first_final) {
+ VALUE mod = Qnil;
+ ID method_id = 0;
+ if (rb_respond_to(json->decimal_class, i_try_convert)) {
+ mod = json->decimal_class;
+ method_id = i_try_convert;
+ } else if (rb_respond_to(json->decimal_class, i_new)) {
+ mod = json->decimal_class;
+ method_id = i_new;
+ } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
+ VALUE name = rb_class_name(json->decimal_class);
+ const char *name_cstr = RSTRING_PTR(name);
+ const char *last_colon = strrchr(name_cstr, ':');
+ if (last_colon) {
+ const char *mod_path_end = last_colon - 1;
+ VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
+ mod = rb_path_to_class(mod_path);
+
+ const char *method_name_beg = last_colon + 1;
+ long before_len = method_name_beg - name_cstr;
+ long len = RSTRING_LEN(name) - before_len;
+ VALUE method_name = rb_str_substr(name, before_len, len);
+ method_id = SYM2ID(rb_str_intern(method_name));
+ } else {
+ mod = rb_mKernel;
+ method_id = SYM2ID(rb_str_intern(name));
+ }
+ }
+
long len = p - json->memo;
fbuffer_clear(json->fbuffer);
fbuffer_append(json->fbuffer, json->memo, len);
fbuffer_append_char(json->fbuffer, '\0');
- if (NIL_P(json->decimal_class)) {
- *result = rb_float_new(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
+
+ if (method_id) {
+ VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
+ *result = rb_funcallv(mod, method_id, 1, &text);
} else {
- VALUE text;
- text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
- if (is_bigdecimal_class(json->decimal_class)) {
- *result = rb_funcall(Qnil, i_BigDecimal, 1, text);
- } else {
- *result = rb_funcall(json->decimal_class, i_new, 1, text);
- }
+ *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
}
+
return p + 1;
} else {
return NULL;
@@ -572,7 +588,22 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
if (json->symbolize_names && json->parsing_name) {
*result = rb_str_intern(*result);
} else if (RB_TYPE_P(*result, T_STRING)) {
+# if STR_UMINUS_DEDUPE_FROZEN
+ if (json->freeze) {
+ // 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
+ if (json->freeze) {
+ // MRI 2.5 and older do not deduplicate strings that are already
+ // frozen.
+ *result = rb_funcall(*result, i_uminus, 0);
+ }
+# else
rb_str_resize(*result, RSTRING_LEN(*result));
+# endif
}
if (cs >= JSON_string_first_final) {
return p + 1;
@@ -680,6 +711,12 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
} else {
json->symbolize_names = 0;
}
+ tmp = ID2SYM(i_freeze);
+ if (option_given_p(opts, tmp)) {
+ json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
+ } else {
+ json->freeze = 0;
+ }
tmp = ID2SYM(i_create_additions);
if (option_given_p(opts, tmp)) {
json->create_additions = RTEST(rb_hash_aref(opts, tmp));
@@ -842,6 +879,10 @@ static VALUE cParser_source(VALUE self)
void Init_parser(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
#undef rb_intern
rb_require("json/common");
mJSON = rb_define_module("JSON");
@@ -884,7 +925,9 @@ void Init_parser(void)
i_aref = rb_intern("[]");
i_leftshift = rb_intern("<<");
i_new = rb_intern("new");
- i_BigDecimal = rb_intern("BigDecimal");
+ i_try_convert = rb_intern("try_convert");
+ i_freeze = rb_intern("freeze");
+ i_uminus = rb_intern("-@");
}
/*
diff --git a/ext/json/parser/prereq.mk b/ext/json/parser/prereq.mk
index 37bacc3380..9111431ab8 100644
--- a/ext/json/parser/prereq.mk
+++ b/ext/json/parser/prereq.mk
@@ -6,6 +6,7 @@ RAGEL = ragel
$(RAGEL) -G2 $<
$(BASERUBY) -pli -e '$$_.sub!(/[ \t]+$$/, "")' \
-e '$$_.sub!(/^static const int (JSON_.*=.*);$$/, "enum {\\1};")' \
+ -e '$$_.sub!(/0 <= \(\*p\) && \(\*p\) <= 31/, "0 <= (signed char)(*p) && (*p) <= 31")' \
-e '$$_ = "/* This file is automatically generated from parser.rl by using ragel */" + $$_ if $$. == 1' $@
parser.c:
diff --git a/ext/monitor/depend b/ext/monitor/depend
index 89efe1766b..fe9ec68806 100644
--- a/ext/monitor/depend
+++ b/ext/monitor/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
monitor.o: $(RUBY_EXTCONF_H)
monitor.o: $(arch_hdrdir)/ruby/config.h
+monitor.o: $(hdrdir)/ruby/internal/anyargs.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+monitor.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+monitor.o: $(hdrdir)/ruby/internal/assume.h
+monitor.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+monitor.o: $(hdrdir)/ruby/internal/attr/artificial.h
+monitor.o: $(hdrdir)/ruby/internal/attr/cold.h
+monitor.o: $(hdrdir)/ruby/internal/attr/const.h
+monitor.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+monitor.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+monitor.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+monitor.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+monitor.o: $(hdrdir)/ruby/internal/attr/error.h
+monitor.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+monitor.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+monitor.o: $(hdrdir)/ruby/internal/attr/format.h
+monitor.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+monitor.o: $(hdrdir)/ruby/internal/attr/noalias.h
+monitor.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+monitor.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+monitor.o: $(hdrdir)/ruby/internal/attr/noinline.h
+monitor.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+monitor.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+monitor.o: $(hdrdir)/ruby/internal/attr/pure.h
+monitor.o: $(hdrdir)/ruby/internal/attr/restrict.h
+monitor.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+monitor.o: $(hdrdir)/ruby/internal/attr/warning.h
+monitor.o: $(hdrdir)/ruby/internal/attr/weakref.h
+monitor.o: $(hdrdir)/ruby/internal/cast.h
+monitor.o: $(hdrdir)/ruby/internal/compiler_is.h
+monitor.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+monitor.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+monitor.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+monitor.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+monitor.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+monitor.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+monitor.o: $(hdrdir)/ruby/internal/compiler_since.h
+monitor.o: $(hdrdir)/ruby/internal/config.h
+monitor.o: $(hdrdir)/ruby/internal/constant_p.h
+monitor.o: $(hdrdir)/ruby/internal/core.h
+monitor.o: $(hdrdir)/ruby/internal/core/rarray.h
+monitor.o: $(hdrdir)/ruby/internal/core/rbasic.h
+monitor.o: $(hdrdir)/ruby/internal/core/rbignum.h
+monitor.o: $(hdrdir)/ruby/internal/core/rclass.h
+monitor.o: $(hdrdir)/ruby/internal/core/rdata.h
+monitor.o: $(hdrdir)/ruby/internal/core/rfile.h
+monitor.o: $(hdrdir)/ruby/internal/core/rhash.h
+monitor.o: $(hdrdir)/ruby/internal/core/robject.h
+monitor.o: $(hdrdir)/ruby/internal/core/rregexp.h
+monitor.o: $(hdrdir)/ruby/internal/core/rstring.h
+monitor.o: $(hdrdir)/ruby/internal/core/rstruct.h
+monitor.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+monitor.o: $(hdrdir)/ruby/internal/ctype.h
+monitor.o: $(hdrdir)/ruby/internal/dllexport.h
+monitor.o: $(hdrdir)/ruby/internal/dosish.h
+monitor.o: $(hdrdir)/ruby/internal/error.h
+monitor.o: $(hdrdir)/ruby/internal/eval.h
+monitor.o: $(hdrdir)/ruby/internal/event.h
+monitor.o: $(hdrdir)/ruby/internal/fl_type.h
+monitor.o: $(hdrdir)/ruby/internal/gc.h
+monitor.o: $(hdrdir)/ruby/internal/glob.h
+monitor.o: $(hdrdir)/ruby/internal/globals.h
+monitor.o: $(hdrdir)/ruby/internal/has/attribute.h
+monitor.o: $(hdrdir)/ruby/internal/has/builtin.h
+monitor.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+monitor.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+monitor.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+monitor.o: $(hdrdir)/ruby/internal/has/extension.h
+monitor.o: $(hdrdir)/ruby/internal/has/feature.h
+monitor.o: $(hdrdir)/ruby/internal/has/warning.h
+monitor.o: $(hdrdir)/ruby/internal/intern/array.h
+monitor.o: $(hdrdir)/ruby/internal/intern/bignum.h
+monitor.o: $(hdrdir)/ruby/internal/intern/class.h
+monitor.o: $(hdrdir)/ruby/internal/intern/compar.h
+monitor.o: $(hdrdir)/ruby/internal/intern/complex.h
+monitor.o: $(hdrdir)/ruby/internal/intern/cont.h
+monitor.o: $(hdrdir)/ruby/internal/intern/dir.h
+monitor.o: $(hdrdir)/ruby/internal/intern/enum.h
+monitor.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+monitor.o: $(hdrdir)/ruby/internal/intern/error.h
+monitor.o: $(hdrdir)/ruby/internal/intern/eval.h
+monitor.o: $(hdrdir)/ruby/internal/intern/file.h
+monitor.o: $(hdrdir)/ruby/internal/intern/gc.h
+monitor.o: $(hdrdir)/ruby/internal/intern/hash.h
+monitor.o: $(hdrdir)/ruby/internal/intern/io.h
+monitor.o: $(hdrdir)/ruby/internal/intern/load.h
+monitor.o: $(hdrdir)/ruby/internal/intern/marshal.h
+monitor.o: $(hdrdir)/ruby/internal/intern/numeric.h
+monitor.o: $(hdrdir)/ruby/internal/intern/object.h
+monitor.o: $(hdrdir)/ruby/internal/intern/parse.h
+monitor.o: $(hdrdir)/ruby/internal/intern/proc.h
+monitor.o: $(hdrdir)/ruby/internal/intern/process.h
+monitor.o: $(hdrdir)/ruby/internal/intern/random.h
+monitor.o: $(hdrdir)/ruby/internal/intern/range.h
+monitor.o: $(hdrdir)/ruby/internal/intern/rational.h
+monitor.o: $(hdrdir)/ruby/internal/intern/re.h
+monitor.o: $(hdrdir)/ruby/internal/intern/ruby.h
+monitor.o: $(hdrdir)/ruby/internal/intern/select.h
+monitor.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+monitor.o: $(hdrdir)/ruby/internal/intern/signal.h
+monitor.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+monitor.o: $(hdrdir)/ruby/internal/intern/string.h
+monitor.o: $(hdrdir)/ruby/internal/intern/struct.h
+monitor.o: $(hdrdir)/ruby/internal/intern/thread.h
+monitor.o: $(hdrdir)/ruby/internal/intern/time.h
+monitor.o: $(hdrdir)/ruby/internal/intern/variable.h
+monitor.o: $(hdrdir)/ruby/internal/intern/vm.h
+monitor.o: $(hdrdir)/ruby/internal/interpreter.h
+monitor.o: $(hdrdir)/ruby/internal/iterator.h
+monitor.o: $(hdrdir)/ruby/internal/memory.h
+monitor.o: $(hdrdir)/ruby/internal/method.h
+monitor.o: $(hdrdir)/ruby/internal/module.h
+monitor.o: $(hdrdir)/ruby/internal/newobj.h
+monitor.o: $(hdrdir)/ruby/internal/rgengc.h
+monitor.o: $(hdrdir)/ruby/internal/scan_args.h
+monitor.o: $(hdrdir)/ruby/internal/special_consts.h
+monitor.o: $(hdrdir)/ruby/internal/static_assert.h
+monitor.o: $(hdrdir)/ruby/internal/stdalign.h
+monitor.o: $(hdrdir)/ruby/internal/stdbool.h
+monitor.o: $(hdrdir)/ruby/internal/symbol.h
+monitor.o: $(hdrdir)/ruby/internal/token_paste.h
+monitor.o: $(hdrdir)/ruby/internal/value.h
+monitor.o: $(hdrdir)/ruby/internal/value_type.h
+monitor.o: $(hdrdir)/ruby/internal/variable.h
+monitor.o: $(hdrdir)/ruby/internal/warning_push.h
+monitor.o: $(hdrdir)/ruby/internal/xmalloc.h
monitor.o: $(hdrdir)/ruby/assert.h
monitor.o: $(hdrdir)/ruby/backward.h
+monitor.o: $(hdrdir)/ruby/backward/2/assume.h
+monitor.o: $(hdrdir)/ruby/backward/2/attributes.h
+monitor.o: $(hdrdir)/ruby/backward/2/bool.h
+monitor.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+monitor.o: $(hdrdir)/ruby/backward/2/inttypes.h
+monitor.o: $(hdrdir)/ruby/backward/2/limits.h
+monitor.o: $(hdrdir)/ruby/backward/2/long_long.h
+monitor.o: $(hdrdir)/ruby/backward/2/stdalign.h
+monitor.o: $(hdrdir)/ruby/backward/2/stdarg.h
monitor.o: $(hdrdir)/ruby/defines.h
monitor.o: $(hdrdir)/ruby/intern.h
monitor.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/monitor/lib/monitor.rb b/ext/monitor/lib/monitor.rb
index 1883cb72f6..11c5ac17d9 100644
--- a/ext/monitor/lib/monitor.rb
+++ b/ext/monitor/lib/monitor.rb
@@ -17,7 +17,7 @@
# structure.
#
# You can read more about the general principles on the Wikipedia page for
-# Monitors[http://en.wikipedia.org/wiki/Monitor_%28synchronization%29]
+# Monitors[https://en.wikipedia.org/wiki/Monitor_%28synchronization%29]
#
# == Examples
#
@@ -220,7 +220,7 @@ module MonitorMixin
# Use <tt>extend MonitorMixin</tt> or <tt>include MonitorMixin</tt> instead
# of this constructor. Have look at the examples above to understand how to
# use this module.
- def initialize(*args)
+ def initialize(...)
super
mon_initialize
end
@@ -230,7 +230,7 @@ module MonitorMixin
def mon_initialize
if defined?(@mon_data)
if defined?(@mon_initialized_by_new_cond)
- return # already initalized.
+ return # already initialized.
elsif @mon_data_owner_object_id == self.object_id
raise ThreadError, "already initialized"
end
diff --git a/ext/monitor/monitor.c b/ext/monitor/monitor.c
index 256fc4d7db..a3efe96bb3 100644
--- a/ext/monitor/monitor.c
+++ b/ext/monitor/monitor.c
@@ -53,7 +53,7 @@ monitor_ptr(VALUE monitor)
static int
mc_owner_p(struct rb_monitor *mc)
{
- return mc->owner == rb_thread_current();
+ return mc->owner == rb_fiber_current();
}
static VALUE
@@ -65,7 +65,7 @@ monitor_try_enter(VALUE monitor)
if (!rb_mutex_trylock(mc->mutex)) {
return Qfalse;
}
- RB_OBJ_WRITE(monitor, &mc->owner, rb_thread_current());
+ RB_OBJ_WRITE(monitor, &mc->owner, rb_fiber_current());
mc->count = 0;
}
mc->count += 1;
@@ -78,7 +78,7 @@ monitor_enter(VALUE monitor)
struct rb_monitor *mc = monitor_ptr(monitor);
if (!mc_owner_p(mc)) {
rb_mutex_lock(mc->mutex);
- RB_OBJ_WRITE(monitor, &mc->owner, rb_thread_current());
+ RB_OBJ_WRITE(monitor, &mc->owner, rb_fiber_current());
mc->count = 0;
}
mc->count++;
@@ -90,7 +90,7 @@ monitor_check_owner(VALUE monitor)
{
struct rb_monitor *mc = monitor_ptr(monitor);
if (!mc_owner_p(mc)) {
- rb_raise(rb_eThreadError, "current thread not owner");
+ rb_raise(rb_eThreadError, "current fiber not owner");
}
return Qnil;
}
@@ -161,7 +161,7 @@ monitor_enter_for_cond(VALUE v)
struct wait_for_cond_data *data = (struct wait_for_cond_data *)v;
struct rb_monitor *mc = monitor_ptr(data->monitor);
- RB_OBJ_WRITE(data->monitor, &mc->owner, rb_thread_current());
+ RB_OBJ_WRITE(data->monitor, &mc->owner, rb_fiber_current());
mc->count = NUM2LONG(data->count);
return Qnil;
}
@@ -203,6 +203,10 @@ monitor_synchronize(VALUE monitor)
void
Init_monitor(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
VALUE rb_cMonitor = rb_define_class("Monitor", rb_cObject);
rb_define_alloc_func(rb_cMonitor, monitor_alloc);
diff --git a/ext/nkf/depend b/ext/nkf/depend
index 82580ff7fe..caaee22ea4 100644
--- a/ext/nkf/depend
+++ b/ext/nkf/depend
@@ -5,8 +5,157 @@ nkf.o: nkf.c
# AUTOGENERATED DEPENDENCIES START
nkf.o: $(RUBY_EXTCONF_H)
nkf.o: $(arch_hdrdir)/ruby/config.h
+nkf.o: $(hdrdir)/ruby/internal/anyargs.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+nkf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+nkf.o: $(hdrdir)/ruby/internal/assume.h
+nkf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+nkf.o: $(hdrdir)/ruby/internal/attr/artificial.h
+nkf.o: $(hdrdir)/ruby/internal/attr/cold.h
+nkf.o: $(hdrdir)/ruby/internal/attr/const.h
+nkf.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+nkf.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+nkf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+nkf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+nkf.o: $(hdrdir)/ruby/internal/attr/error.h
+nkf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+nkf.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+nkf.o: $(hdrdir)/ruby/internal/attr/format.h
+nkf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+nkf.o: $(hdrdir)/ruby/internal/attr/noalias.h
+nkf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+nkf.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+nkf.o: $(hdrdir)/ruby/internal/attr/noinline.h
+nkf.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+nkf.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+nkf.o: $(hdrdir)/ruby/internal/attr/pure.h
+nkf.o: $(hdrdir)/ruby/internal/attr/restrict.h
+nkf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+nkf.o: $(hdrdir)/ruby/internal/attr/warning.h
+nkf.o: $(hdrdir)/ruby/internal/attr/weakref.h
+nkf.o: $(hdrdir)/ruby/internal/cast.h
+nkf.o: $(hdrdir)/ruby/internal/compiler_is.h
+nkf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+nkf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+nkf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+nkf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+nkf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+nkf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+nkf.o: $(hdrdir)/ruby/internal/compiler_since.h
+nkf.o: $(hdrdir)/ruby/internal/config.h
+nkf.o: $(hdrdir)/ruby/internal/constant_p.h
+nkf.o: $(hdrdir)/ruby/internal/core.h
+nkf.o: $(hdrdir)/ruby/internal/core/rarray.h
+nkf.o: $(hdrdir)/ruby/internal/core/rbasic.h
+nkf.o: $(hdrdir)/ruby/internal/core/rbignum.h
+nkf.o: $(hdrdir)/ruby/internal/core/rclass.h
+nkf.o: $(hdrdir)/ruby/internal/core/rdata.h
+nkf.o: $(hdrdir)/ruby/internal/core/rfile.h
+nkf.o: $(hdrdir)/ruby/internal/core/rhash.h
+nkf.o: $(hdrdir)/ruby/internal/core/robject.h
+nkf.o: $(hdrdir)/ruby/internal/core/rregexp.h
+nkf.o: $(hdrdir)/ruby/internal/core/rstring.h
+nkf.o: $(hdrdir)/ruby/internal/core/rstruct.h
+nkf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+nkf.o: $(hdrdir)/ruby/internal/ctype.h
+nkf.o: $(hdrdir)/ruby/internal/dllexport.h
+nkf.o: $(hdrdir)/ruby/internal/dosish.h
+nkf.o: $(hdrdir)/ruby/internal/error.h
+nkf.o: $(hdrdir)/ruby/internal/eval.h
+nkf.o: $(hdrdir)/ruby/internal/event.h
+nkf.o: $(hdrdir)/ruby/internal/fl_type.h
+nkf.o: $(hdrdir)/ruby/internal/gc.h
+nkf.o: $(hdrdir)/ruby/internal/glob.h
+nkf.o: $(hdrdir)/ruby/internal/globals.h
+nkf.o: $(hdrdir)/ruby/internal/has/attribute.h
+nkf.o: $(hdrdir)/ruby/internal/has/builtin.h
+nkf.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+nkf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+nkf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+nkf.o: $(hdrdir)/ruby/internal/has/extension.h
+nkf.o: $(hdrdir)/ruby/internal/has/feature.h
+nkf.o: $(hdrdir)/ruby/internal/has/warning.h
+nkf.o: $(hdrdir)/ruby/internal/intern/array.h
+nkf.o: $(hdrdir)/ruby/internal/intern/bignum.h
+nkf.o: $(hdrdir)/ruby/internal/intern/class.h
+nkf.o: $(hdrdir)/ruby/internal/intern/compar.h
+nkf.o: $(hdrdir)/ruby/internal/intern/complex.h
+nkf.o: $(hdrdir)/ruby/internal/intern/cont.h
+nkf.o: $(hdrdir)/ruby/internal/intern/dir.h
+nkf.o: $(hdrdir)/ruby/internal/intern/enum.h
+nkf.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+nkf.o: $(hdrdir)/ruby/internal/intern/error.h
+nkf.o: $(hdrdir)/ruby/internal/intern/eval.h
+nkf.o: $(hdrdir)/ruby/internal/intern/file.h
+nkf.o: $(hdrdir)/ruby/internal/intern/gc.h
+nkf.o: $(hdrdir)/ruby/internal/intern/hash.h
+nkf.o: $(hdrdir)/ruby/internal/intern/io.h
+nkf.o: $(hdrdir)/ruby/internal/intern/load.h
+nkf.o: $(hdrdir)/ruby/internal/intern/marshal.h
+nkf.o: $(hdrdir)/ruby/internal/intern/numeric.h
+nkf.o: $(hdrdir)/ruby/internal/intern/object.h
+nkf.o: $(hdrdir)/ruby/internal/intern/parse.h
+nkf.o: $(hdrdir)/ruby/internal/intern/proc.h
+nkf.o: $(hdrdir)/ruby/internal/intern/process.h
+nkf.o: $(hdrdir)/ruby/internal/intern/random.h
+nkf.o: $(hdrdir)/ruby/internal/intern/range.h
+nkf.o: $(hdrdir)/ruby/internal/intern/rational.h
+nkf.o: $(hdrdir)/ruby/internal/intern/re.h
+nkf.o: $(hdrdir)/ruby/internal/intern/ruby.h
+nkf.o: $(hdrdir)/ruby/internal/intern/select.h
+nkf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nkf.o: $(hdrdir)/ruby/internal/intern/signal.h
+nkf.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+nkf.o: $(hdrdir)/ruby/internal/intern/string.h
+nkf.o: $(hdrdir)/ruby/internal/intern/struct.h
+nkf.o: $(hdrdir)/ruby/internal/intern/thread.h
+nkf.o: $(hdrdir)/ruby/internal/intern/time.h
+nkf.o: $(hdrdir)/ruby/internal/intern/variable.h
+nkf.o: $(hdrdir)/ruby/internal/intern/vm.h
+nkf.o: $(hdrdir)/ruby/internal/interpreter.h
+nkf.o: $(hdrdir)/ruby/internal/iterator.h
+nkf.o: $(hdrdir)/ruby/internal/memory.h
+nkf.o: $(hdrdir)/ruby/internal/method.h
+nkf.o: $(hdrdir)/ruby/internal/module.h
+nkf.o: $(hdrdir)/ruby/internal/newobj.h
+nkf.o: $(hdrdir)/ruby/internal/rgengc.h
+nkf.o: $(hdrdir)/ruby/internal/scan_args.h
+nkf.o: $(hdrdir)/ruby/internal/special_consts.h
+nkf.o: $(hdrdir)/ruby/internal/static_assert.h
+nkf.o: $(hdrdir)/ruby/internal/stdalign.h
+nkf.o: $(hdrdir)/ruby/internal/stdbool.h
+nkf.o: $(hdrdir)/ruby/internal/symbol.h
+nkf.o: $(hdrdir)/ruby/internal/token_paste.h
+nkf.o: $(hdrdir)/ruby/internal/value.h
+nkf.o: $(hdrdir)/ruby/internal/value_type.h
+nkf.o: $(hdrdir)/ruby/internal/variable.h
+nkf.o: $(hdrdir)/ruby/internal/warning_push.h
+nkf.o: $(hdrdir)/ruby/internal/xmalloc.h
nkf.o: $(hdrdir)/ruby/assert.h
nkf.o: $(hdrdir)/ruby/backward.h
+nkf.o: $(hdrdir)/ruby/backward/2/assume.h
+nkf.o: $(hdrdir)/ruby/backward/2/attributes.h
+nkf.o: $(hdrdir)/ruby/backward/2/bool.h
+nkf.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+nkf.o: $(hdrdir)/ruby/backward/2/inttypes.h
+nkf.o: $(hdrdir)/ruby/backward/2/limits.h
+nkf.o: $(hdrdir)/ruby/backward/2/long_long.h
+nkf.o: $(hdrdir)/ruby/backward/2/stdalign.h
+nkf.o: $(hdrdir)/ruby/backward/2/stdarg.h
nkf.o: $(hdrdir)/ruby/defines.h
nkf.o: $(hdrdir)/ruby/encoding.h
nkf.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/nkf/nkf.gemspec b/ext/nkf/nkf.gemspec
new file mode 100644
index 0000000000..23f1dcdbaf
--- /dev/null
+++ b/ext/nkf/nkf.gemspec
@@ -0,0 +1,24 @@
+Gem::Specification.new do |spec|
+ spec.name = "nkf"
+ spec.version = "0.1.0"
+ spec.authors = ["NARUSE Yui"]
+ spec.email = ["naruse@airemix.jp"]
+
+ spec.summary = %q{Ruby extension for Network Kanji Filter}
+ spec.description = %q{Ruby extension for Network Kanji Filter}
+ spec.homepage = "https://github.com/ruby/nkf"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/ext/objspace/depend b/ext/objspace/depend
index 18be4fe8a8..d3a702007e 100644
--- a/ext/objspace/depend
+++ b/ext/objspace/depend
@@ -4,9 +4,160 @@ object_tracing.o: $(arch_hdrdir)/ruby/config.h
object_tracing.o: $(hdrdir)/ruby.h
object_tracing.o: $(hdrdir)/ruby/assert.h
object_tracing.o: $(hdrdir)/ruby/backward.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/assume.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/attributes.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/bool.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/inttypes.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/limits.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/long_long.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/r_cast.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/rmodule.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/stdalign.h
+object_tracing.o: $(hdrdir)/ruby/backward/2/stdarg.h
object_tracing.o: $(hdrdir)/ruby/debug.h
object_tracing.o: $(hdrdir)/ruby/defines.h
object_tracing.o: $(hdrdir)/ruby/intern.h
+object_tracing.o: $(hdrdir)/ruby/internal/anyargs.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+object_tracing.o: $(hdrdir)/ruby/internal/assume.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/artificial.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/cold.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/const.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/error.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/format.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/noalias.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/noinline.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/pure.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/restrict.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/warning.h
+object_tracing.o: $(hdrdir)/ruby/internal/attr/weakref.h
+object_tracing.o: $(hdrdir)/ruby/internal/cast.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+object_tracing.o: $(hdrdir)/ruby/internal/compiler_since.h
+object_tracing.o: $(hdrdir)/ruby/internal/config.h
+object_tracing.o: $(hdrdir)/ruby/internal/constant_p.h
+object_tracing.o: $(hdrdir)/ruby/internal/core.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rarray.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rbasic.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rbignum.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rclass.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rdata.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rfile.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rhash.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/robject.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rregexp.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rstring.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rstruct.h
+object_tracing.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+object_tracing.o: $(hdrdir)/ruby/internal/ctype.h
+object_tracing.o: $(hdrdir)/ruby/internal/dllexport.h
+object_tracing.o: $(hdrdir)/ruby/internal/dosish.h
+object_tracing.o: $(hdrdir)/ruby/internal/error.h
+object_tracing.o: $(hdrdir)/ruby/internal/eval.h
+object_tracing.o: $(hdrdir)/ruby/internal/event.h
+object_tracing.o: $(hdrdir)/ruby/internal/fl_type.h
+object_tracing.o: $(hdrdir)/ruby/internal/gc.h
+object_tracing.o: $(hdrdir)/ruby/internal/glob.h
+object_tracing.o: $(hdrdir)/ruby/internal/globals.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/attribute.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/builtin.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/extension.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/feature.h
+object_tracing.o: $(hdrdir)/ruby/internal/has/warning.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/array.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/bignum.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/class.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/compar.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/complex.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/cont.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/dir.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/enum.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/error.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/eval.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/file.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/gc.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/hash.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/io.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/load.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/marshal.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/numeric.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/object.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/parse.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/proc.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/process.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/random.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/range.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/rational.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/re.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/ruby.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/select.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/signal.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/string.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/struct.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/thread.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/time.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/variable.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/vm.h
+object_tracing.o: $(hdrdir)/ruby/internal/interpreter.h
+object_tracing.o: $(hdrdir)/ruby/internal/iterator.h
+object_tracing.o: $(hdrdir)/ruby/internal/memory.h
+object_tracing.o: $(hdrdir)/ruby/internal/method.h
+object_tracing.o: $(hdrdir)/ruby/internal/module.h
+object_tracing.o: $(hdrdir)/ruby/internal/newobj.h
+object_tracing.o: $(hdrdir)/ruby/internal/rgengc.h
+object_tracing.o: $(hdrdir)/ruby/internal/scan_args.h
+object_tracing.o: $(hdrdir)/ruby/internal/special_consts.h
+object_tracing.o: $(hdrdir)/ruby/internal/static_assert.h
+object_tracing.o: $(hdrdir)/ruby/internal/stdalign.h
+object_tracing.o: $(hdrdir)/ruby/internal/stdbool.h
+object_tracing.o: $(hdrdir)/ruby/internal/symbol.h
+object_tracing.o: $(hdrdir)/ruby/internal/token_paste.h
+object_tracing.o: $(hdrdir)/ruby/internal/value.h
+object_tracing.o: $(hdrdir)/ruby/internal/value_type.h
+object_tracing.o: $(hdrdir)/ruby/internal/variable.h
+object_tracing.o: $(hdrdir)/ruby/internal/warning_push.h
+object_tracing.o: $(hdrdir)/ruby/internal/xmalloc.h
object_tracing.o: $(hdrdir)/ruby/missing.h
object_tracing.o: $(hdrdir)/ruby/ruby.h
object_tracing.o: $(hdrdir)/ruby/st.h
@@ -19,9 +170,161 @@ objspace.o: $(arch_hdrdir)/ruby/config.h
objspace.o: $(hdrdir)/ruby.h
objspace.o: $(hdrdir)/ruby/assert.h
objspace.o: $(hdrdir)/ruby/backward.h
+objspace.o: $(hdrdir)/ruby/backward/2/assume.h
+objspace.o: $(hdrdir)/ruby/backward/2/attributes.h
+objspace.o: $(hdrdir)/ruby/backward/2/bool.h
+objspace.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+objspace.o: $(hdrdir)/ruby/backward/2/inttypes.h
+objspace.o: $(hdrdir)/ruby/backward/2/limits.h
+objspace.o: $(hdrdir)/ruby/backward/2/long_long.h
+objspace.o: $(hdrdir)/ruby/backward/2/r_cast.h
+objspace.o: $(hdrdir)/ruby/backward/2/rmodule.h
+objspace.o: $(hdrdir)/ruby/backward/2/stdalign.h
+objspace.o: $(hdrdir)/ruby/backward/2/stdarg.h
objspace.o: $(hdrdir)/ruby/defines.h
objspace.o: $(hdrdir)/ruby/encoding.h
objspace.o: $(hdrdir)/ruby/intern.h
+objspace.o: $(hdrdir)/ruby/internal/anyargs.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+objspace.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+objspace.o: $(hdrdir)/ruby/internal/assume.h
+objspace.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+objspace.o: $(hdrdir)/ruby/internal/attr/artificial.h
+objspace.o: $(hdrdir)/ruby/internal/attr/cold.h
+objspace.o: $(hdrdir)/ruby/internal/attr/const.h
+objspace.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+objspace.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+objspace.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+objspace.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+objspace.o: $(hdrdir)/ruby/internal/attr/error.h
+objspace.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+objspace.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+objspace.o: $(hdrdir)/ruby/internal/attr/format.h
+objspace.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+objspace.o: $(hdrdir)/ruby/internal/attr/noalias.h
+objspace.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+objspace.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+objspace.o: $(hdrdir)/ruby/internal/attr/noinline.h
+objspace.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+objspace.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+objspace.o: $(hdrdir)/ruby/internal/attr/pure.h
+objspace.o: $(hdrdir)/ruby/internal/attr/restrict.h
+objspace.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+objspace.o: $(hdrdir)/ruby/internal/attr/warning.h
+objspace.o: $(hdrdir)/ruby/internal/attr/weakref.h
+objspace.o: $(hdrdir)/ruby/internal/cast.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+objspace.o: $(hdrdir)/ruby/internal/compiler_since.h
+objspace.o: $(hdrdir)/ruby/internal/config.h
+objspace.o: $(hdrdir)/ruby/internal/constant_p.h
+objspace.o: $(hdrdir)/ruby/internal/core.h
+objspace.o: $(hdrdir)/ruby/internal/core/rarray.h
+objspace.o: $(hdrdir)/ruby/internal/core/rbasic.h
+objspace.o: $(hdrdir)/ruby/internal/core/rbignum.h
+objspace.o: $(hdrdir)/ruby/internal/core/rclass.h
+objspace.o: $(hdrdir)/ruby/internal/core/rdata.h
+objspace.o: $(hdrdir)/ruby/internal/core/rfile.h
+objspace.o: $(hdrdir)/ruby/internal/core/rhash.h
+objspace.o: $(hdrdir)/ruby/internal/core/rmatch.h
+objspace.o: $(hdrdir)/ruby/internal/core/robject.h
+objspace.o: $(hdrdir)/ruby/internal/core/rregexp.h
+objspace.o: $(hdrdir)/ruby/internal/core/rstring.h
+objspace.o: $(hdrdir)/ruby/internal/core/rstruct.h
+objspace.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+objspace.o: $(hdrdir)/ruby/internal/ctype.h
+objspace.o: $(hdrdir)/ruby/internal/dllexport.h
+objspace.o: $(hdrdir)/ruby/internal/dosish.h
+objspace.o: $(hdrdir)/ruby/internal/error.h
+objspace.o: $(hdrdir)/ruby/internal/eval.h
+objspace.o: $(hdrdir)/ruby/internal/event.h
+objspace.o: $(hdrdir)/ruby/internal/fl_type.h
+objspace.o: $(hdrdir)/ruby/internal/gc.h
+objspace.o: $(hdrdir)/ruby/internal/glob.h
+objspace.o: $(hdrdir)/ruby/internal/globals.h
+objspace.o: $(hdrdir)/ruby/internal/has/attribute.h
+objspace.o: $(hdrdir)/ruby/internal/has/builtin.h
+objspace.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+objspace.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+objspace.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+objspace.o: $(hdrdir)/ruby/internal/has/extension.h
+objspace.o: $(hdrdir)/ruby/internal/has/feature.h
+objspace.o: $(hdrdir)/ruby/internal/has/warning.h
+objspace.o: $(hdrdir)/ruby/internal/intern/array.h
+objspace.o: $(hdrdir)/ruby/internal/intern/bignum.h
+objspace.o: $(hdrdir)/ruby/internal/intern/class.h
+objspace.o: $(hdrdir)/ruby/internal/intern/compar.h
+objspace.o: $(hdrdir)/ruby/internal/intern/complex.h
+objspace.o: $(hdrdir)/ruby/internal/intern/cont.h
+objspace.o: $(hdrdir)/ruby/internal/intern/dir.h
+objspace.o: $(hdrdir)/ruby/internal/intern/enum.h
+objspace.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+objspace.o: $(hdrdir)/ruby/internal/intern/error.h
+objspace.o: $(hdrdir)/ruby/internal/intern/eval.h
+objspace.o: $(hdrdir)/ruby/internal/intern/file.h
+objspace.o: $(hdrdir)/ruby/internal/intern/gc.h
+objspace.o: $(hdrdir)/ruby/internal/intern/hash.h
+objspace.o: $(hdrdir)/ruby/internal/intern/io.h
+objspace.o: $(hdrdir)/ruby/internal/intern/load.h
+objspace.o: $(hdrdir)/ruby/internal/intern/marshal.h
+objspace.o: $(hdrdir)/ruby/internal/intern/numeric.h
+objspace.o: $(hdrdir)/ruby/internal/intern/object.h
+objspace.o: $(hdrdir)/ruby/internal/intern/parse.h
+objspace.o: $(hdrdir)/ruby/internal/intern/proc.h
+objspace.o: $(hdrdir)/ruby/internal/intern/process.h
+objspace.o: $(hdrdir)/ruby/internal/intern/random.h
+objspace.o: $(hdrdir)/ruby/internal/intern/range.h
+objspace.o: $(hdrdir)/ruby/internal/intern/rational.h
+objspace.o: $(hdrdir)/ruby/internal/intern/re.h
+objspace.o: $(hdrdir)/ruby/internal/intern/ruby.h
+objspace.o: $(hdrdir)/ruby/internal/intern/select.h
+objspace.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+objspace.o: $(hdrdir)/ruby/internal/intern/signal.h
+objspace.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+objspace.o: $(hdrdir)/ruby/internal/intern/string.h
+objspace.o: $(hdrdir)/ruby/internal/intern/struct.h
+objspace.o: $(hdrdir)/ruby/internal/intern/thread.h
+objspace.o: $(hdrdir)/ruby/internal/intern/time.h
+objspace.o: $(hdrdir)/ruby/internal/intern/variable.h
+objspace.o: $(hdrdir)/ruby/internal/intern/vm.h
+objspace.o: $(hdrdir)/ruby/internal/interpreter.h
+objspace.o: $(hdrdir)/ruby/internal/iterator.h
+objspace.o: $(hdrdir)/ruby/internal/memory.h
+objspace.o: $(hdrdir)/ruby/internal/method.h
+objspace.o: $(hdrdir)/ruby/internal/module.h
+objspace.o: $(hdrdir)/ruby/internal/newobj.h
+objspace.o: $(hdrdir)/ruby/internal/rgengc.h
+objspace.o: $(hdrdir)/ruby/internal/scan_args.h
+objspace.o: $(hdrdir)/ruby/internal/special_consts.h
+objspace.o: $(hdrdir)/ruby/internal/static_assert.h
+objspace.o: $(hdrdir)/ruby/internal/stdalign.h
+objspace.o: $(hdrdir)/ruby/internal/stdbool.h
+objspace.o: $(hdrdir)/ruby/internal/symbol.h
+objspace.o: $(hdrdir)/ruby/internal/token_paste.h
+objspace.o: $(hdrdir)/ruby/internal/value.h
+objspace.o: $(hdrdir)/ruby/internal/value_type.h
+objspace.o: $(hdrdir)/ruby/internal/variable.h
+objspace.o: $(hdrdir)/ruby/internal/warning_push.h
+objspace.o: $(hdrdir)/ruby/internal/xmalloc.h
objspace.o: $(hdrdir)/ruby/io.h
objspace.o: $(hdrdir)/ruby/missing.h
objspace.o: $(hdrdir)/ruby/onigmo.h
@@ -32,7 +335,18 @@ objspace.o: $(hdrdir)/ruby/ruby.h
objspace.o: $(hdrdir)/ruby/st.h
objspace.o: $(hdrdir)/ruby/subst.h
objspace.o: $(top_srcdir)/gc.h
+objspace.o: $(top_srcdir)/id_table.h
objspace.o: $(top_srcdir)/internal.h
+objspace.o: $(top_srcdir)/internal/array.h
+objspace.o: $(top_srcdir)/internal/class.h
+objspace.o: $(top_srcdir)/internal/compilers.h
+objspace.o: $(top_srcdir)/internal/gc.h
+objspace.o: $(top_srcdir)/internal/hash.h
+objspace.o: $(top_srcdir)/internal/imemo.h
+objspace.o: $(top_srcdir)/internal/sanitizers.h
+objspace.o: $(top_srcdir)/internal/serial.h
+objspace.o: $(top_srcdir)/internal/static_assert.h
+objspace.o: $(top_srcdir)/internal/warnings.h
objspace.o: $(top_srcdir)/node.h
objspace.o: $(top_srcdir)/symbol.h
objspace.o: objspace.c
@@ -41,11 +355,163 @@ objspace_dump.o: $(RUBY_EXTCONF_H)
objspace_dump.o: $(arch_hdrdir)/ruby/config.h
objspace_dump.o: $(hdrdir)/ruby.h
objspace_dump.o: $(hdrdir)/ruby/assert.h
+objspace_dump.o: $(hdrdir)/ruby/atomic.h
objspace_dump.o: $(hdrdir)/ruby/backward.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/assume.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/attributes.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/bool.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/inttypes.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/limits.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/long_long.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/r_cast.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/rmodule.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/stdalign.h
+objspace_dump.o: $(hdrdir)/ruby/backward/2/stdarg.h
objspace_dump.o: $(hdrdir)/ruby/debug.h
objspace_dump.o: $(hdrdir)/ruby/defines.h
objspace_dump.o: $(hdrdir)/ruby/encoding.h
objspace_dump.o: $(hdrdir)/ruby/intern.h
+objspace_dump.o: $(hdrdir)/ruby/internal/anyargs.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+objspace_dump.o: $(hdrdir)/ruby/internal/assume.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/artificial.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/cold.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/const.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/error.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/format.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/noalias.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/noinline.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/pure.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/restrict.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/warning.h
+objspace_dump.o: $(hdrdir)/ruby/internal/attr/weakref.h
+objspace_dump.o: $(hdrdir)/ruby/internal/cast.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+objspace_dump.o: $(hdrdir)/ruby/internal/compiler_since.h
+objspace_dump.o: $(hdrdir)/ruby/internal/config.h
+objspace_dump.o: $(hdrdir)/ruby/internal/constant_p.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rarray.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rbasic.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rbignum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rclass.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rdata.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rfile.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rhash.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/robject.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rregexp.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rstring.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rstruct.h
+objspace_dump.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+objspace_dump.o: $(hdrdir)/ruby/internal/ctype.h
+objspace_dump.o: $(hdrdir)/ruby/internal/dllexport.h
+objspace_dump.o: $(hdrdir)/ruby/internal/dosish.h
+objspace_dump.o: $(hdrdir)/ruby/internal/error.h
+objspace_dump.o: $(hdrdir)/ruby/internal/eval.h
+objspace_dump.o: $(hdrdir)/ruby/internal/event.h
+objspace_dump.o: $(hdrdir)/ruby/internal/fl_type.h
+objspace_dump.o: $(hdrdir)/ruby/internal/gc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/glob.h
+objspace_dump.o: $(hdrdir)/ruby/internal/globals.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/attribute.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/builtin.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/extension.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/feature.h
+objspace_dump.o: $(hdrdir)/ruby/internal/has/warning.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/array.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/bignum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/class.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/compar.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/complex.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/cont.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/dir.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/enum.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/error.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/eval.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/file.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/gc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/hash.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/io.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/load.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/marshal.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/numeric.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/object.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/parse.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/proc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/process.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/random.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/range.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/rational.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/re.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/ruby.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/select.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/signal.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/string.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/struct.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/thread.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/time.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/variable.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/vm.h
+objspace_dump.o: $(hdrdir)/ruby/internal/interpreter.h
+objspace_dump.o: $(hdrdir)/ruby/internal/iterator.h
+objspace_dump.o: $(hdrdir)/ruby/internal/memory.h
+objspace_dump.o: $(hdrdir)/ruby/internal/method.h
+objspace_dump.o: $(hdrdir)/ruby/internal/module.h
+objspace_dump.o: $(hdrdir)/ruby/internal/newobj.h
+objspace_dump.o: $(hdrdir)/ruby/internal/rgengc.h
+objspace_dump.o: $(hdrdir)/ruby/internal/scan_args.h
+objspace_dump.o: $(hdrdir)/ruby/internal/special_consts.h
+objspace_dump.o: $(hdrdir)/ruby/internal/static_assert.h
+objspace_dump.o: $(hdrdir)/ruby/internal/stdalign.h
+objspace_dump.o: $(hdrdir)/ruby/internal/stdbool.h
+objspace_dump.o: $(hdrdir)/ruby/internal/symbol.h
+objspace_dump.o: $(hdrdir)/ruby/internal/token_paste.h
+objspace_dump.o: $(hdrdir)/ruby/internal/value.h
+objspace_dump.o: $(hdrdir)/ruby/internal/value_type.h
+objspace_dump.o: $(hdrdir)/ruby/internal/variable.h
+objspace_dump.o: $(hdrdir)/ruby/internal/warning_push.h
+objspace_dump.o: $(hdrdir)/ruby/internal/xmalloc.h
objspace_dump.o: $(hdrdir)/ruby/io.h
objspace_dump.o: $(hdrdir)/ruby/missing.h
objspace_dump.o: $(hdrdir)/ruby/onigmo.h
@@ -54,12 +520,24 @@ objspace_dump.o: $(hdrdir)/ruby/ruby.h
objspace_dump.o: $(hdrdir)/ruby/st.h
objspace_dump.o: $(hdrdir)/ruby/subst.h
objspace_dump.o: $(hdrdir)/ruby/thread_native.h
+objspace_dump.o: $(hdrdir)/ruby/util.h
objspace_dump.o: $(top_srcdir)/ccan/check_type/check_type.h
objspace_dump.o: $(top_srcdir)/ccan/container_of/container_of.h
objspace_dump.o: $(top_srcdir)/ccan/list/list.h
objspace_dump.o: $(top_srcdir)/ccan/str/str.h
objspace_dump.o: $(top_srcdir)/gc.h
objspace_dump.o: $(top_srcdir)/internal.h
+objspace_dump.o: $(top_srcdir)/internal/array.h
+objspace_dump.o: $(top_srcdir)/internal/compilers.h
+objspace_dump.o: $(top_srcdir)/internal/gc.h
+objspace_dump.o: $(top_srcdir)/internal/hash.h
+objspace_dump.o: $(top_srcdir)/internal/imemo.h
+objspace_dump.o: $(top_srcdir)/internal/sanitizers.h
+objspace_dump.o: $(top_srcdir)/internal/serial.h
+objspace_dump.o: $(top_srcdir)/internal/static_assert.h
+objspace_dump.o: $(top_srcdir)/internal/string.h
+objspace_dump.o: $(top_srcdir)/internal/vm.h
+objspace_dump.o: $(top_srcdir)/internal/warnings.h
objspace_dump.o: $(top_srcdir)/method.h
objspace_dump.o: $(top_srcdir)/node.h
objspace_dump.o: $(top_srcdir)/ruby_assert.h
diff --git a/ext/objspace/lib/objspace.rb b/ext/objspace/lib/objspace.rb
new file mode 100644
index 0000000000..0298b0646c
--- /dev/null
+++ b/ext/objspace/lib/objspace.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'objspace.so'
+
+module ObjectSpace
+ class << self
+ private :_dump
+ private :_dump_all
+ end
+
+ module_function
+
+ # call-seq:
+ # ObjectSpace.dump(obj[, output: :string]) # => "{ ... }"
+ # ObjectSpace.dump(obj, output: :file) # => #<File:/tmp/rubyobj20131125-88733-1xkfmpv.json>
+ # ObjectSpace.dump(obj, output: :stdout) # => nil
+ #
+ # Dump the contents of a ruby object as JSON.
+ #
+ # This method is only expected to work with C Ruby.
+ # This is an experimental method and is subject to change.
+ # In particular, the function signature and output format are
+ # not guaranteed to be compatible in future versions of ruby.
+ def dump(obj, output: :string)
+ out = case output
+ when :file, nil
+ require 'tempfile'
+ Tempfile.create(%w(rubyobj .json))
+ when :stdout
+ STDOUT
+ when :string
+ +''
+ when IO
+ output
+ else
+ raise ArgumentError, "wrong output option: #{output.inspect}"
+ end
+
+ ret = _dump(obj, out)
+ return nil if output == :stdout
+ ret
+ end
+
+
+ # call-seq:
+ # ObjectSpace.dump_all([output: :file]) # => #<File:/tmp/rubyheap20131125-88469-laoj3v.json>
+ # ObjectSpace.dump_all(output: :stdout) # => nil
+ # ObjectSpace.dump_all(output: :string) # => "{...}\n{...}\n..."
+ # ObjectSpace.dump_all(output:
+ # File.open('heap.json','w')) # => #<File:heap.json>
+ # ObjectSpace.dump_all(output: :string,
+ # since: 42) # => "{...}\n{...}\n..."
+ #
+ # Dump the contents of the ruby heap as JSON.
+ #
+ # _since_ must be a non-negative integer or +nil+.
+ #
+ # If _since_ is a positive integer, only objects of that generation and
+ # newer generations are dumped. The current generation can be accessed using
+ # GC::count.
+ #
+ # Objects that were allocated without object allocation tracing enabled
+ # are ignored. See ::trace_object_allocations for more information and
+ # examples.
+ #
+ # If _since_ is omitted or is +nil+, all objects are dumped.
+ #
+ # This method is only expected to work with C Ruby.
+ # This is an experimental method and is subject to change.
+ # In particular, the function signature and output format are
+ # not guaranteed to be compatible in future versions of ruby.
+ def dump_all(output: :file, full: false, since: nil)
+ out = case output
+ when :file, nil
+ require 'tempfile'
+ Tempfile.create(%w(rubyheap .json))
+ when :stdout
+ STDOUT
+ when :string
+ +''
+ when IO
+ output
+ else
+ raise ArgumentError, "wrong output option: #{output.inspect}"
+ end
+
+ ret = _dump_all(out, full, since)
+ return nil if output == :stdout
+ ret
+ end
+end
diff --git a/ext/objspace/object_tracing.c b/ext/objspace/object_tracing.c
index a057ac2a96..66d6baa491 100644
--- a/ext/objspace/object_tracing.c
+++ b/ext/objspace/object_tracing.c
@@ -151,6 +151,81 @@ free_values_i(st_data_t key, st_data_t value, st_data_t data)
return ST_CONTINUE;
}
+static void
+allocation_info_tracer_mark(void *ptr)
+{
+ struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
+ rb_gc_mark(trace_arg->newobj_trace);
+ rb_gc_mark(trace_arg->freeobj_trace);
+}
+
+static void
+allocation_info_tracer_free(void *ptr)
+{
+ struct traceobj_arg *arg = (struct traceobj_arg *)ptr;
+ /* clear tables */
+ st_foreach(arg->object_table, free_values_i, 0);
+ st_free_table(arg->object_table);
+ st_foreach(arg->str_table, free_keys_i, 0);
+ st_free_table(arg->str_table);
+ xfree(arg);
+}
+
+static size_t
+allocation_info_tracer_memsize(const void *ptr)
+{
+ size_t size;
+ struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
+ size = sizeof(*trace_arg);
+ size += st_memsize(trace_arg->object_table);
+ size += st_memsize(trace_arg->str_table);
+ return size;
+}
+
+static int
+hash_foreach_should_replace_key(st_data_t key, st_data_t value, st_data_t argp, int error)
+{
+ VALUE allocated_object;
+
+ allocated_object = (VALUE)value;
+ if (allocated_object != rb_gc_location(allocated_object)) {
+ return ST_REPLACE;
+ }
+
+ return ST_CONTINUE;
+}
+
+static int
+hash_replace_key(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
+{
+ *key = rb_gc_location((VALUE)*key);
+
+ return ST_CONTINUE;
+}
+
+static void
+allocation_info_tracer_compact(void *ptr)
+{
+ struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
+
+ if (trace_arg->object_table &&
+ st_foreach_with_replace(trace_arg->object_table, hash_foreach_should_replace_key, hash_replace_key, 0)) {
+ rb_raise(rb_eRuntimeError, "hash modified during iteration");
+ }
+}
+
+static const rb_data_type_t allocation_info_tracer_type = {
+ "ObjectTracing/allocation_info_tracer",
+ {
+ allocation_info_tracer_mark,
+ allocation_info_tracer_free, /* Never called because global */
+ allocation_info_tracer_memsize,
+ allocation_info_tracer_compact,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE traceobj_arg;
static struct traceobj_arg *tmp_trace_arg; /* TODO: Do not use global variables */
static int tmp_keep_remains; /* TODO: Do not use global variables */
@@ -158,7 +233,9 @@ static struct traceobj_arg *
get_traceobj_arg(void)
{
if (tmp_trace_arg == 0) {
- tmp_trace_arg = ALLOC_N(struct traceobj_arg, 1);
+ VALUE obj = TypedData_Make_Struct(rb_cObject, struct traceobj_arg, &allocation_info_tracer_type, tmp_trace_arg);
+ traceobj_arg = obj;
+ rb_gc_register_mark_object(traceobj_arg);
tmp_trace_arg->running = 0;
tmp_trace_arg->keep_remains = tmp_keep_remains;
tmp_trace_arg->newobj_trace = 0;
@@ -186,9 +263,7 @@ trace_object_allocations_start(VALUE self)
else {
if (arg->newobj_trace == 0) {
arg->newobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ, newobj_i, arg);
- rb_gc_register_mark_object(arg->newobj_trace);
arg->freeobj_trace = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_FREEOBJ, freeobj_i, arg);
- rb_gc_register_mark_object(arg->freeobj_trace);
}
rb_tracepoint_enable(arg->newobj_trace);
rb_tracepoint_enable(arg->freeobj_trace);
@@ -216,8 +291,12 @@ trace_object_allocations_stop(VALUE self)
}
if (arg->running == 0) {
- rb_tracepoint_disable(arg->newobj_trace);
- rb_tracepoint_disable(arg->freeobj_trace);
+ if (arg->newobj_trace != 0) {
+ rb_tracepoint_disable(arg->newobj_trace);
+ }
+ if (arg->freeobj_trace != 0) {
+ rb_tracepoint_disable(arg->freeobj_trace);
+ }
}
return Qnil;
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index 311e687206..3fa4fd279b 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -12,19 +12,28 @@
**********************************************************************/
-#include <ruby/io.h>
+#include "gc.h"
#include "internal.h"
-#include <ruby/st.h>
-#include <ruby/re.h>
+#include "internal/class.h"
+#include "internal/compilers.h"
+#include "internal/hash.h"
+#include "internal/imemo.h"
+#include "internal/sanitizers.h"
#include "node.h"
-#include "gc.h"
+#include "ruby/io.h"
+#include "ruby/re.h"
+#include "ruby/st.h"
#include "symbol.h"
+#undef rb_funcall
+
+#include "ruby/ruby.h"
+
/*
* call-seq:
* ObjectSpace.memsize_of(obj) -> Integer
*
- * Return consuming memory size of obj.
+ * Return consuming memory size of obj in bytes.
*
* Note that the return size is incomplete. You need to deal with this
* information as only a *HINT*. Especially, the size of +T_DATA+ may not be
@@ -47,37 +56,68 @@ struct total_data {
VALUE klass;
};
+static void
+total_i(VALUE v, void *ptr)
+{
+ struct total_data *data = (struct total_data *)ptr;
+
+ switch (BUILTIN_TYPE(v)) {
+ case T_NONE:
+ case T_IMEMO:
+ case T_ICLASS:
+ case T_NODE:
+ case T_ZOMBIE:
+ return;
+ default:
+ if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
+ data->total += rb_obj_memsize_of(v);
+ }
+ }
+}
+
+typedef void (*each_obj_with_flags)(VALUE, void*);
+
+struct obj_itr {
+ each_obj_with_flags cb;
+ void *data;
+};
+
static int
-total_i(void *vstart, void *vend, size_t stride, void *ptr)
+heap_iter(void *vstart, void *vend, size_t stride, void *ptr)
{
+ struct obj_itr * ctx = (struct obj_itr *)ptr;
VALUE v;
- struct total_data *data = (struct total_data *)ptr;
for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
- if (RBASIC(v)->flags) {
- switch (BUILTIN_TYPE(v)) {
- case T_NONE:
- case T_IMEMO:
- case T_ICLASS:
- case T_NODE:
- case T_ZOMBIE:
- continue;
- default:
- if (data->klass == 0 || rb_obj_is_kind_of(v, data->klass)) {
- data->total += rb_obj_memsize_of(v);
- }
- }
- }
+ void *poisoned = asan_poisoned_object_p(v);
+ asan_unpoison_object(v, false);
+
+ if (RBASIC(v)->flags) {
+ (*ctx->cb)(v, ctx->data);
+ }
+
+ if (poisoned) {
+ asan_poison_object(v);
+ }
}
return 0;
}
+static void
+each_object_with_flags(each_obj_with_flags cb, void *ctx)
+{
+ struct obj_itr data;
+ data.cb = cb;
+ data.data = ctx;
+ rb_objspace_each_objects(heap_iter, &data);
+}
+
/*
* call-seq:
* ObjectSpace.memsize_of_all([klass]) -> Integer
*
- * Return consuming memory size of all living objects.
+ * Return consuming memory size of all living objects in bytes.
*
* If +klass+ (should be Class object) is given, return the total memory size
* of instances of the given class.
@@ -110,7 +150,7 @@ memsize_of_all_m(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &data.klass);
}
- rb_objspace_each_objects(total_i, &data);
+ each_object_with_flags(total_i, &data);
return SIZET2NUM(data.total);
}
@@ -137,24 +177,18 @@ setup_hash(int argc, VALUE *argv)
hash = rb_hash_new();
}
else if (!RHASH_EMPTY_P(hash)) {
- st_foreach(RHASH_TBL(hash), set_zero_i, hash);
+ /* WB: no new reference */
+ st_foreach(RHASH_TBL_RAW(hash), set_zero_i, hash);
}
return hash;
}
-static int
-cos_i(void *vstart, void *vend, size_t stride, void *data)
+static void
+cos_i(VALUE v, void *data)
{
size_t *counts = (size_t *)data;
- VALUE v = (VALUE)vstart;
-
- for (;v != (VALUE)vend; v += stride) {
- if (RBASIC(v)->flags) {
- counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v);
- }
- }
- return 0;
+ counts[BUILTIN_TYPE(v)] += rb_obj_memsize_of(v);
}
static VALUE
@@ -231,7 +265,7 @@ count_objects_size(int argc, VALUE *argv, VALUE os)
counts[i] = 0;
}
- rb_objspace_each_objects(cos_i, &counts[0]);
+ each_object_with_flags(cos_i, &counts[0]);
for (i = 0; i <= T_MASK; i++) {
if (counts[i]) {
@@ -249,25 +283,20 @@ struct dynamic_symbol_counts {
size_t immortal;
};
-static int
-cs_i(void *vstart, void *vend, size_t stride, void *n)
+static void
+cs_i(VALUE v, void *n)
{
struct dynamic_symbol_counts *counts = (struct dynamic_symbol_counts *)n;
- VALUE v = (VALUE)vstart;
- for (; v != (VALUE)vend; v += stride) {
- if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_SYMBOL) {
- ID id = RSYMBOL(v)->id;
- if ((id & ~ID_SCOPE_MASK) == 0) {
- counts->mortal++;
- }
- else {
- counts->immortal++;
- }
- }
+ if (BUILTIN_TYPE(v) == T_SYMBOL) {
+ ID id = RSYMBOL(v)->id;
+ if ((id & ~ID_SCOPE_MASK) == 0) {
+ counts->mortal++;
+ }
+ else {
+ counts->immortal++;
+ }
}
-
- return 0;
}
size_t rb_sym_immortal_count(void);
@@ -305,7 +334,7 @@ count_symbols(int argc, VALUE *argv, VALUE os)
VALUE hash = setup_hash(argc, argv);
size_t immortal_symbols = rb_sym_immortal_count();
- rb_objspace_each_objects(cs_i, &dynamic_counts);
+ each_object_with_flags(cs_i, &dynamic_counts);
rb_hash_aset(hash, ID2SYM(rb_intern("mortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.mortal));
rb_hash_aset(hash, ID2SYM(rb_intern("immortal_dynamic_symbol")), SIZET2NUM(dynamic_counts.immortal));
@@ -315,20 +344,15 @@ count_symbols(int argc, VALUE *argv, VALUE os)
return hash;
}
-static int
-cn_i(void *vstart, void *vend, size_t stride, void *n)
+static void
+cn_i(VALUE v, void *n)
{
size_t *nodes = (size_t *)n;
- VALUE v = (VALUE)vstart;
- for (; v != (VALUE)vend; v += stride) {
- if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_NODE) {
- size_t s = nd_type((NODE *)v);
- nodes[s]++;
- }
+ if (BUILTIN_TYPE(v) == T_NODE) {
+ size_t s = nd_type((NODE *)v);
+ nodes[s]++;
}
-
- return 0;
}
/*
@@ -365,7 +389,7 @@ count_nodes(int argc, VALUE *argv, VALUE os)
nodes[i] = 0;
}
- rb_objspace_each_objects(cn_i, &nodes[0]);
+ each_object_with_flags(cn_i, &nodes[0]);
for (i=0; i<NODE_LAST; i++) {
if (nodes[i] != 0) {
@@ -378,9 +402,9 @@ count_nodes(int argc, VALUE *argv, VALUE os)
COUNT_NODE(NODE_UNLESS);
COUNT_NODE(NODE_CASE);
COUNT_NODE(NODE_CASE2);
- COUNT_NODE(NODE_CASE3);
+ COUNT_NODE(NODE_CASE3);
COUNT_NODE(NODE_WHEN);
- COUNT_NODE(NODE_IN);
+ COUNT_NODE(NODE_IN);
COUNT_NODE(NODE_WHILE);
COUNT_NODE(NODE_UNTIL);
COUNT_NODE(NODE_ITER);
@@ -474,8 +498,9 @@ count_nodes(int argc, VALUE *argv, VALUE os)
COUNT_NODE(NODE_DSYM);
COUNT_NODE(NODE_ATTRASGN);
COUNT_NODE(NODE_LAMBDA);
- COUNT_NODE(NODE_ARYPTN);
- COUNT_NODE(NODE_HSHPTN);
+ COUNT_NODE(NODE_ARYPTN);
+ COUNT_NODE(NODE_FNDPTN);
+ COUNT_NODE(NODE_HSHPTN);
#undef COUNT_NODE
case NODE_LAST: break;
}
@@ -487,36 +512,31 @@ count_nodes(int argc, VALUE *argv, VALUE os)
return hash;
}
-static int
-cto_i(void *vstart, void *vend, size_t stride, void *data)
+static void
+cto_i(VALUE v, void *data)
{
VALUE hash = (VALUE)data;
- VALUE v = (VALUE)vstart;
-
- for (; v != (VALUE)vend; v += stride) {
- if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_DATA) {
- VALUE counter;
- VALUE key = RBASIC(v)->klass;
-
- if (key == 0) {
- const char *name = rb_objspace_data_type_name(v);
- if (name == 0) name = "unknown";
- key = ID2SYM(rb_intern(name));
- }
- counter = rb_hash_aref(hash, key);
- if (NIL_P(counter)) {
- counter = INT2FIX(1);
- }
- else {
- counter = INT2FIX(FIX2INT(counter) + 1);
- }
-
- rb_hash_aset(hash, key, counter);
- }
+ if (BUILTIN_TYPE(v) == T_DATA) {
+ VALUE counter;
+ VALUE key = RBASIC(v)->klass;
+
+ if (key == 0) {
+ const char *name = rb_objspace_data_type_name(v);
+ if (name == 0) name = "unknown";
+ key = ID2SYM(rb_intern(name));
+ }
+
+ counter = rb_hash_aref(hash, key);
+ if (NIL_P(counter)) {
+ counter = INT2FIX(1);
+ }
+ else {
+ counter = INT2FIX(FIX2INT(counter) + 1);
+ }
+
+ rb_hash_aset(hash, key, counter);
}
-
- return 0;
}
/*
@@ -555,37 +575,32 @@ static VALUE
count_tdata_objects(int argc, VALUE *argv, VALUE self)
{
VALUE hash = setup_hash(argc, argv);
- rb_objspace_each_objects(cto_i, (void *)hash);
+ each_object_with_flags(cto_i, (void *)hash);
return hash;
}
static ID imemo_type_ids[IMEMO_MASK+1];
-static int
-count_imemo_objects_i(void *vstart, void *vend, size_t stride, void *data)
+static void
+count_imemo_objects_i(VALUE v, void *data)
{
VALUE hash = (VALUE)data;
- VALUE v = (VALUE)vstart;
- for (; v != (VALUE)vend; v += stride) {
- if (RBASIC(v)->flags && BUILTIN_TYPE(v) == T_IMEMO) {
- VALUE counter;
- VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]);
+ if (BUILTIN_TYPE(v) == T_IMEMO) {
+ VALUE counter;
+ VALUE key = ID2SYM(imemo_type_ids[imemo_type(v)]);
- counter = rb_hash_aref(hash, key);
+ counter = rb_hash_aref(hash, key);
- if (NIL_P(counter)) {
- counter = INT2FIX(1);
- }
- else {
- counter = INT2FIX(FIX2INT(counter) + 1);
- }
+ if (NIL_P(counter)) {
+ counter = INT2FIX(1);
+ }
+ else {
+ counter = INT2FIX(FIX2INT(counter) + 1);
+ }
- rb_hash_aset(hash, key, counter);
- }
+ rb_hash_aset(hash, key, counter);
}
-
- return 0;
}
/*
@@ -633,9 +648,12 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self)
imemo_type_ids[8] = rb_intern("imemo_tmpbuf");
imemo_type_ids[9] = rb_intern("imemo_ast");
imemo_type_ids[10] = rb_intern("imemo_parser_strterm");
+ imemo_type_ids[11] = rb_intern("imemo_callinfo");
+ imemo_type_ids[12] = rb_intern("imemo_callcache");
+ imemo_type_ids[13] = rb_intern("imemo_constcache");
}
- rb_objspace_each_objects(count_imemo_objects_i, (void *)hash);
+ each_object_with_flags(count_imemo_objects_i, (void *)hash);
return hash;
}
@@ -659,12 +677,12 @@ static const rb_data_type_t iow_data_type = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
-static VALUE rb_mInternalObjectWrapper;
+static VALUE rb_cInternalObjectWrapper;
static VALUE
iow_newobj(VALUE obj)
{
- return TypedData_Wrap_Struct(rb_mInternalObjectWrapper, &iow_data_type, (void *)obj);
+ return TypedData_Wrap_Struct(rb_cInternalObjectWrapper, &iow_data_type, (void *)obj);
}
/* Returns the type of the internal object. */
@@ -694,7 +712,7 @@ iow_internal_object_id(VALUE self)
}
struct rof_data {
- st_table *refs;
+ VALUE refs;
VALUE internals;
};
@@ -710,7 +728,7 @@ reachable_object_from_i(VALUE obj, void *data_ptr)
val = iow_newobj(obj);
rb_ary_push(data->internals, val);
}
- st_insert(data->refs, key, val);
+ rb_hash_aset(data->refs, key, val);
}
}
@@ -768,20 +786,18 @@ static VALUE
reachable_objects_from(VALUE self, VALUE obj)
{
if (rb_objspace_markable_object_p(obj)) {
- VALUE ret = rb_ary_new();
struct rof_data data;
if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
obj = (VALUE)DATA_PTR(obj);
}
- data.refs = st_init_numtable();
+ data.refs = rb_ident_hash_new();
data.internals = rb_ary_new();
rb_objspace_reachable_objects_from(obj, reachable_object_from_i, &data);
- st_foreach(data.refs, collect_values, (st_data_t)ret);
- return ret;
+ return rb_funcall(data.refs, rb_intern("values"), 0);
}
else {
return Qnil;
@@ -860,7 +876,8 @@ wrap_klass_iow(VALUE klass)
if (!RTEST(klass)) {
return Qnil;
}
- else if (RB_TYPE_P(klass, T_ICLASS)) {
+ else if (RB_TYPE_P(klass, T_ICLASS) ||
+ CLASS_OF(klass) == Qfalse /* hidden object */) {
return iow_newobj(klass);
}
else {
@@ -886,8 +903,13 @@ objspace_internal_class_of(VALUE self, VALUE obj)
obj = (VALUE)DATA_PTR(obj);
}
- klass = CLASS_OF(obj);
- return wrap_klass_iow(klass);
+ if (RB_TYPE_P(obj, T_IMEMO)) {
+ return Qnil;
+ }
+ else {
+ klass = CLASS_OF(obj);
+ return wrap_klass_iow(klass);
+ }
}
/*
@@ -973,10 +995,11 @@ Init_objspace(void)
*
* You can use the #type method to check the type of the internal object.
*/
- rb_mInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject);
- rb_define_method(rb_mInternalObjectWrapper, "type", iow_type, 0);
- rb_define_method(rb_mInternalObjectWrapper, "inspect", iow_inspect, 0);
- rb_define_method(rb_mInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0);
+ rb_cInternalObjectWrapper = rb_define_class_under(rb_mObjSpace, "InternalObjectWrapper", rb_cObject);
+ rb_undef_alloc_func(rb_cInternalObjectWrapper);
+ rb_define_method(rb_cInternalObjectWrapper, "type", iow_type, 0);
+ rb_define_method(rb_cInternalObjectWrapper, "inspect", iow_inspect, 0);
+ rb_define_method(rb_cInternalObjectWrapper, "internal_object_id", iow_internal_object_id, 0);
Init_object_tracing(rb_mObjSpace);
Init_objspace_dump(rb_mObjSpace);
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c
index 5fa9d98e38..544d11e254 100644
--- a/ext/objspace/objspace_dump.c
+++ b/ext/objspace/objspace_dump.c
@@ -12,20 +12,25 @@
**********************************************************************/
-#include "ruby/io.h"
-#include "internal.h"
-#include "ruby/debug.h"
#include "gc.h"
+#include "internal.h"
+#include "internal/hash.h"
+#include "internal/string.h"
+#include "internal/sanitizers.h"
#include "node.h"
-#include "vm_core.h"
#include "objspace.h"
+#include "ruby/debug.h"
+#include "ruby/util.h"
+#include "ruby/io.h"
+#include "vm_core.h"
+
+RUBY_EXTERN const char ruby_hexdigits[];
-static VALUE sym_output, sym_stdout, sym_string, sym_file;
-static VALUE sym_full;
+#define BUFFER_CAPACITY 4096
struct dump_config {
VALUE type;
- FILE *stream;
+ VALUE stream;
VALUE string;
const char *root_category;
VALUE cur_obj;
@@ -33,22 +38,143 @@ struct dump_config {
size_t cur_obj_references;
unsigned int roots: 1;
unsigned int full_heap: 1;
+ unsigned int partial_dump;
+ size_t since;
+ unsigned long buffer_len;
+ char buffer[BUFFER_CAPACITY];
};
-PRINTF_ARGS(static void dump_append(struct dump_config *, const char *, ...), 2, 3);
static void
-dump_append(struct dump_config *dc, const char *format, ...)
+dump_flush(struct dump_config *dc)
+{
+ if (dc->buffer_len) {
+ if (dc->stream) {
+ size_t written = rb_io_bufwrite(dc->stream, dc->buffer, dc->buffer_len);
+ if (written < dc->buffer_len) {
+ MEMMOVE(dc->buffer, dc->buffer + written, char, dc->buffer_len - written);
+ dc->buffer_len -= written;
+ return;
+ }
+ }
+ else if (dc->string) {
+ rb_str_cat(dc->string, dc->buffer, dc->buffer_len);
+ }
+ dc->buffer_len = 0;
+ }
+}
+
+static inline void
+buffer_ensure_capa(struct dump_config *dc, unsigned long requested)
+{
+ RUBY_ASSERT(requested <= BUFFER_CAPACITY);
+ if (requested + dc->buffer_len >= BUFFER_CAPACITY) {
+ dump_flush(dc);
+ if (requested + dc->buffer_len >= BUFFER_CAPACITY) {
+ rb_raise(rb_eIOError, "full buffer");
+ }
+ }
+}
+
+static void buffer_append(struct dump_config *dc, const char *cstr, unsigned long len)
+{
+ if (LIKELY(len > 0)) {
+ buffer_ensure_capa(dc, len);
+ MEMCPY(dc->buffer + dc->buffer_len, cstr, char, len);
+ dc->buffer_len += len;
+ }
+}
+
+# define dump_append(dc, str) buffer_append(dc, (str), (long)strlen(str))
+
+static void
+dump_append_ld(struct dump_config *dc, const long number)
+{
+ const int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT - 1) + 2;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%ld", number);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+}
+
+static void
+dump_append_lu(struct dump_config *dc, const unsigned long number)
+{
+ const int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT) + 1;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%lu", number);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+}
+
+static void
+dump_append_g(struct dump_config *dc, const double number)
+{
+ unsigned long capa_left = BUFFER_CAPACITY - dc->buffer_len;
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, capa_left, "%#g", number);
+
+ if (required >= capa_left) {
+ buffer_ensure_capa(dc, required);
+ capa_left = BUFFER_CAPACITY - dc->buffer_len;
+ snprintf(dc->buffer + dc->buffer_len, capa_left, "%#g", number);
+ }
+ dc->buffer_len += required;
+}
+
+static void
+dump_append_d(struct dump_config *dc, const int number)
+{
+ const int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT - 1) + 2;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%d", number);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+}
+
+static void
+dump_append_sizet(struct dump_config *dc, const size_t number)
{
- va_list vl;
- va_start(vl, format);
+ const int width = DECIMAL_SIZE_OF_BITS(sizeof(number) * CHAR_BIT) + 1;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "%"PRIuSIZE, number);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+}
- if (dc->stream) {
- vfprintf(dc->stream, format, vl);
+static void
+dump_append_c(struct dump_config *dc, char c)
+{
+ if (c <= 0x1f) {
+ const int width = (sizeof(c) * CHAR_BIT / 4) + 5;
+ buffer_ensure_capa(dc, width);
+ unsigned long required = snprintf(dc->buffer + dc->buffer_len, width, "\\u00%02x", c);
+ RUBY_ASSERT(required <= width);
+ dc->buffer_len += required;
+ }
+ else {
+ buffer_ensure_capa(dc, 1);
+ dc->buffer[dc->buffer_len] = c;
+ dc->buffer_len++;
}
- else if (dc->string)
- rb_str_vcatf(dc->string, format, vl);
+}
+
+static void
+dump_append_ref(struct dump_config *dc, VALUE ref)
+{
+ RUBY_ASSERT(ref > 0);
+
+ char buffer[((sizeof(VALUE) * CHAR_BIT + 3) / 4) + 4];
+ char *buffer_start, *buffer_end;
- va_end(vl);
+ buffer_start = buffer_end = &buffer[sizeof(buffer)];
+ *--buffer_start = '"';
+ while (ref) {
+ *--buffer_start = ruby_hexdigits[ref & 0xF];
+ ref >>= 4;
+ }
+ *--buffer_start = 'x';
+ *--buffer_start = '0';
+ *--buffer_start = '"';
+ buffer_append(dc, buffer_start, buffer_end - buffer_start);
}
static void
@@ -60,35 +186,37 @@ dump_append_string_value(struct dump_config *dc, VALUE obj)
dump_append(dc, "\"");
for (i = 0, value = RSTRING_PTR(obj); i < RSTRING_LEN(obj); i++) {
- switch ((c = value[i])) {
- case '\\':
- case '"':
- dump_append(dc, "\\%c", c);
- break;
- case '\0':
- dump_append(dc, "\\u0000");
- break;
- case '\b':
- dump_append(dc, "\\b");
- break;
- case '\t':
- dump_append(dc, "\\t");
- break;
- case '\f':
- dump_append(dc, "\\f");
- break;
- case '\n':
- dump_append(dc, "\\n");
- break;
- case '\r':
- dump_append(dc, "\\r");
- break;
- default:
- if (c <= 0x1f)
- dump_append(dc, "\\u%04d", c);
- else
- dump_append(dc, "%c", c);
- }
+ switch ((c = value[i])) {
+ case '\\':
+ dump_append(dc, "\\\\");
+ break;
+ case '"':
+ dump_append(dc, "\\\"");
+ break;
+ case '\0':
+ dump_append(dc, "\\u0000");
+ break;
+ case '\b':
+ dump_append(dc, "\\b");
+ break;
+ case '\t':
+ dump_append(dc, "\\t");
+ break;
+ case '\f':
+ dump_append(dc, "\\f");
+ break;
+ case '\n':
+ dump_append(dc, "\\n");
+ break;
+ case '\r':
+ dump_append(dc, "\\r");
+ break;
+ case '\177':
+ dump_append(dc, "\\u007f");
+ break;
+ default:
+ dump_append_c(dc, c);
+ }
}
dump_append(dc, "\"");
}
@@ -133,6 +261,7 @@ obj_type(VALUE obj)
CASE_TYPE(NODE);
CASE_TYPE(ZOMBIE);
#undef CASE_TYPE
+ default: break;
}
return "UNKNOWN";
}
@@ -141,25 +270,25 @@ static void
dump_append_special_const(struct dump_config *dc, VALUE value)
{
if (value == Qtrue) {
- dump_append(dc, "true");
+ dump_append(dc, "true");
}
else if (value == Qfalse) {
- dump_append(dc, "false");
+ dump_append(dc, "false");
}
else if (value == Qnil) {
- dump_append(dc, "null");
+ dump_append(dc, "null");
}
else if (FIXNUM_P(value)) {
- dump_append(dc, "%ld", FIX2LONG(value));
+ dump_append_ld(dc, FIX2LONG(value));
}
else if (FLONUM_P(value)) {
- dump_append(dc, "%#g", RFLOAT_VALUE(value));
+ dump_append_g(dc, RFLOAT_VALUE(value));
}
else if (SYMBOL_P(value)) {
- dump_append_symbol_value(dc, value);
+ dump_append_symbol_value(dc, value);
}
else {
- dump_append(dc, "{}");
+ dump_append(dc, "{}");
}
}
@@ -169,12 +298,16 @@ reachable_object_i(VALUE ref, void *data)
struct dump_config *dc = (struct dump_config *)data;
if (dc->cur_obj_klass == ref)
- return;
+ return;
- if (dc->cur_obj_references == 0)
- dump_append(dc, ", \"references\":[\"%#"PRIxVALUE"\"", ref);
- else
- dump_append(dc, ", \"%#"PRIxVALUE"\"", ref);
+ if (dc->cur_obj_references == 0) {
+ dump_append(dc, ", \"references\":[");
+ dump_append_ref(dc, ref);
+ }
+ else {
+ dump_append(dc, ", ");
+ dump_append_ref(dc, ref);
+ }
dc->cur_obj_references++;
}
@@ -182,35 +315,16 @@ reachable_object_i(VALUE ref, void *data)
static void
dump_append_string_content(struct dump_config *dc, VALUE obj)
{
- dump_append(dc, ", \"bytesize\":%ld", RSTRING_LEN(obj));
- if (!STR_EMBED_P(obj) && !STR_SHARED_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj))
- dump_append(dc, ", \"capacity\":%"PRIuSIZE, rb_str_capacity(obj));
-
- if (is_ascii_string(obj)) {
- dump_append(dc, ", \"value\":");
- dump_append_string_value(dc, obj);
+ dump_append(dc, ", \"bytesize\":");
+ dump_append_ld(dc, RSTRING_LEN(obj));
+ if (!STR_EMBED_P(obj) && !STR_SHARED_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj)) {
+ dump_append(dc, ", \"capacity\":");
+ dump_append_sizet(dc, rb_str_capacity(obj));
}
-}
-static const char *
-imemo_name(int imemo)
-{
- switch(imemo) {
-#define TYPE_STR(t) case(imemo_##t): return #t
- TYPE_STR(env);
- TYPE_STR(cref);
- TYPE_STR(svar);
- TYPE_STR(throw_data);
- TYPE_STR(ifunc);
- TYPE_STR(memo);
- TYPE_STR(ment);
- TYPE_STR(iseq);
- TYPE_STR(tmpbuf);
- TYPE_STR(ast);
- TYPE_STR(parser_strterm);
- default:
- return "unknown";
-#undef TYPE_STR
+ if (is_ascii_string(obj)) {
+ dump_append(dc, ", \"value\":");
+ dump_append_string_value(dc, obj);
}
}
@@ -218,126 +332,177 @@ static void
dump_object(VALUE obj, struct dump_config *dc)
{
size_t memsize;
- struct allocation_info *ainfo;
+ struct allocation_info *ainfo = objspace_lookup_allocation_info(obj);
rb_io_t *fptr;
ID flags[RB_OBJ_GC_FLAGS_MAX];
size_t n, i;
if (SPECIAL_CONST_P(obj)) {
- dump_append_special_const(dc, obj);
- return;
+ dump_append_special_const(dc, obj);
+ return;
}
dc->cur_obj = obj;
dc->cur_obj_references = 0;
dc->cur_obj_klass = BUILTIN_TYPE(obj) == T_NODE ? 0 : RBASIC_CLASS(obj);
+ if (dc->partial_dump && (!ainfo || ainfo->generation < dc->since)) {
+ return;
+ }
+
if (dc->cur_obj == dc->string)
- return;
+ return;
- dump_append(dc, "{\"address\":\"%#"PRIxVALUE"\", \"type\":\"%s\"", obj, obj_type(obj));
+ dump_append(dc, "{\"address\":");
+ dump_append_ref(dc, obj);
- if (dc->cur_obj_klass)
- dump_append(dc, ", \"class\":\"%#"PRIxVALUE"\"", dc->cur_obj_klass);
+ dump_append(dc, ", \"type\":\"");
+ dump_append(dc, obj_type(obj));
+ dump_append(dc, "\"");
+
+ if (dc->cur_obj_klass) {
+ dump_append(dc, ", \"class\":");
+ dump_append_ref(dc, dc->cur_obj_klass);
+ }
if (rb_obj_frozen_p(obj))
- dump_append(dc, ", \"frozen\":true");
+ dump_append(dc, ", \"frozen\":true");
switch (BUILTIN_TYPE(obj)) {
case T_NONE:
- dump_append(dc, "}\n");
- return;
+ dump_append(dc, "}\n");
+ return;
case T_IMEMO:
- dump_append(dc, ", \"imemo_type\":\"%s\"", imemo_name(imemo_type(obj)));
- break;
+ dump_append(dc, ", \"imemo_type\":\"");
+ dump_append(dc, rb_imemo_name(imemo_type(obj)));
+ dump_append(dc, "\"");
+ break;
case T_SYMBOL:
- dump_append_string_content(dc, rb_sym2str(obj));
- break;
+ dump_append_string_content(dc, rb_sym2str(obj));
+ break;
case T_STRING:
- if (STR_EMBED_P(obj))
- dump_append(dc, ", \"embedded\":true");
- if (is_broken_string(obj))
- dump_append(dc, ", \"broken\":true");
- if (FL_TEST(obj, RSTRING_FSTR))
- dump_append(dc, ", \"fstring\":true");
- if (STR_SHARED_P(obj))
- dump_append(dc, ", \"shared\":true");
- else
- dump_append_string_content(dc, obj);
-
- if (!ENCODING_IS_ASCII8BIT(obj))
- dump_append(dc, ", \"encoding\":\"%s\"", rb_enc_name(rb_enc_from_index(ENCODING_GET(obj))));
- break;
+ if (STR_EMBED_P(obj))
+ dump_append(dc, ", \"embedded\":true");
+ if (is_broken_string(obj))
+ dump_append(dc, ", \"broken\":true");
+ if (FL_TEST(obj, RSTRING_FSTR))
+ dump_append(dc, ", \"fstring\":true");
+ if (STR_SHARED_P(obj))
+ dump_append(dc, ", \"shared\":true");
+ else
+ dump_append_string_content(dc, obj);
+
+ if (!ENCODING_IS_ASCII8BIT(obj)) {
+ dump_append(dc, ", \"encoding\":\"");
+ dump_append(dc, rb_enc_name(rb_enc_from_index(ENCODING_GET(obj))));
+ dump_append(dc, "\"");
+ }
+ break;
case T_HASH:
- dump_append(dc, ", \"size\":%"PRIuSIZE, (size_t)RHASH_SIZE(obj));
- if (FL_TEST(obj, RHASH_PROC_DEFAULT))
- dump_append(dc, ", \"default\":\"%#"PRIxVALUE"\"", RHASH_IFNONE(obj));
- break;
+ dump_append(dc, ", \"size\":");
+ dump_append_sizet(dc, (size_t)RHASH_SIZE(obj));
+ if (FL_TEST(obj, RHASH_PROC_DEFAULT)) {
+ dump_append(dc, ", \"default\":");
+ dump_append_ref(dc, RHASH_IFNONE(obj));
+ }
+ break;
case T_ARRAY:
- dump_append(dc, ", \"length\":%ld", RARRAY_LEN(obj));
- if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, ELTS_SHARED))
- dump_append(dc, ", \"shared\":true");
- if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_EMBED_FLAG))
- dump_append(dc, ", \"embedded\":true");
- break;
+ dump_append(dc, ", \"length\":");
+ dump_append_ld(dc, RARRAY_LEN(obj));
+ if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, ELTS_SHARED))
+ dump_append(dc, ", \"shared\":true");
+ if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_EMBED_FLAG))
+ dump_append(dc, ", \"embedded\":true");
+ break;
case T_CLASS:
case T_MODULE:
- if (dc->cur_obj_klass)
- dump_append(dc, ", \"name\":\"%s\"", rb_class2name(obj));
- break;
+ 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, "\"");
+ }
+ }
+ break;
case T_DATA:
- if (RTYPEDDATA_P(obj))
- dump_append(dc, ", \"struct\":\"%s\"", RTYPEDDATA_TYPE(obj)->wrap_struct_name);
- break;
+ if (RTYPEDDATA_P(obj)) {
+ dump_append(dc, ", \"struct\":\"");
+ dump_append(dc, RTYPEDDATA_TYPE(obj)->wrap_struct_name);
+ dump_append(dc, "\"");
+ }
+ break;
case T_FLOAT:
- dump_append(dc, ", \"value\":\"%g\"", RFLOAT_VALUE(obj));
- break;
+ dump_append(dc, ", \"value\":\"");
+ dump_append_g(dc, RFLOAT_VALUE(obj));
+ dump_append(dc, "\"");
+ break;
case T_OBJECT:
- dump_append(dc, ", \"ivars\":%u", ROBJECT_NUMIV(obj));
- break;
+ dump_append(dc, ", \"ivars\":");
+ dump_append_lu(dc, ROBJECT_NUMIV(obj));
+ break;
case T_FILE:
- fptr = RFILE(obj)->fptr;
- if (fptr)
- dump_append(dc, ", \"fd\":%d", fptr->fd);
- break;
+ fptr = RFILE(obj)->fptr;
+ if (fptr) {
+ dump_append(dc, ", \"fd\":");
+ dump_append_d(dc, fptr->fd);
+ }
+ break;
case T_ZOMBIE:
- dump_append(dc, "}\n");
- return;
+ dump_append(dc, "}\n");
+ return;
+
+ default:
+ break;
}
rb_objspace_reachable_objects_from(obj, reachable_object_i, dc);
if (dc->cur_obj_references > 0)
- dump_append(dc, "]");
-
- if ((ainfo = objspace_lookup_allocation_info(obj))) {
- dump_append(dc, ", \"file\":\"%s\", \"line\":%lu", ainfo->path, ainfo->line);
- if (RTEST(ainfo->mid)) {
- VALUE m = rb_sym2str(ainfo->mid);
- dump_append(dc, ", \"method\":\"%s\"", RSTRING_PTR(m));
- }
- dump_append(dc, ", \"generation\":%"PRIuSIZE, ainfo->generation);
+ dump_append(dc, "]");
+
+ if (ainfo) {
+ if (ainfo->path) {
+ dump_append(dc, ", \"file\":\"");
+ dump_append(dc, ainfo->path);
+ dump_append(dc, "\"");
+ }
+ if (ainfo->line) {
+ dump_append(dc, ", \"line\":");
+ dump_append_lu(dc, ainfo->line);
+ }
+ if (RTEST(ainfo->mid)) {
+ VALUE m = rb_sym2str(ainfo->mid);
+ dump_append(dc, ", \"method\":");
+ dump_append_string_value(dc, m);
+ }
+ dump_append(dc, ", \"generation\":");
+ dump_append_sizet(dc, ainfo->generation);
}
- if ((memsize = rb_obj_memsize_of(obj)) > 0)
- dump_append(dc, ", \"memsize\":%"PRIuSIZE, memsize);
+ if ((memsize = rb_obj_memsize_of(obj)) > 0) {
+ dump_append(dc, ", \"memsize\":");
+ dump_append_sizet(dc, memsize);
+ }
if ((n = rb_obj_gc_flags(obj, flags, sizeof(flags))) > 0) {
- dump_append(dc, ", \"flags\":{");
- for (i=0; i<n; i++) {
- dump_append(dc, "\"%s\":true", rb_id2name(flags[i]));
- if (i != n-1) dump_append(dc, ", ");
- }
- dump_append(dc, "}");
+ 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, ", ");
+ }
+ dump_append(dc, "}");
}
dump_append(dc, "}\n");
@@ -349,8 +514,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);
+
if (dc->full_heap || RBASIC(v)->flags)
dump_object(v, dc);
+
+ if (ptr) {
+ asan_poison_object(v);
+ }
}
return 0;
}
@@ -361,138 +533,89 @@ root_obj_i(const char *category, VALUE obj, void *data)
struct dump_config *dc = (struct dump_config *)data;
if (dc->root_category != NULL && category != dc->root_category)
- dump_append(dc, "]}\n");
- if (dc->root_category == NULL || category != dc->root_category)
- dump_append(dc, "{\"type\":\"ROOT\", \"root\":\"%s\", \"references\":[\"%#"PRIxVALUE"\"", category, obj);
- else
- dump_append(dc, ", \"%#"PRIxVALUE"\"", obj);
+ dump_append(dc, "]}\n");
+ if (dc->root_category == NULL || category != dc->root_category) {
+ dump_append(dc, "{\"type\":\"ROOT\", \"root\":\"");
+ dump_append(dc, category);
+ dump_append(dc, "\", \"references\":[");
+ dump_append_ref(dc, obj);
+ }
+ else {
+ dump_append(dc, ", ");
+ dump_append_ref(dc, obj);
+ }
dc->root_category = category;
dc->roots = 1;
}
-static VALUE
-dump_output(struct dump_config *dc, VALUE opts, VALUE output, const char *filename)
+static void
+dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since)
{
- VALUE tmp;
dc->full_heap = 0;
-
- if (RTEST(opts)) {
- output = rb_hash_aref(opts, sym_output);
-
- if (Qtrue == rb_hash_lookup2(opts, sym_full, Qfalse))
- dc->full_heap = 1;
+ dc->buffer_len = 0;
+
+ if (TYPE(output) == T_STRING) {
+ dc->stream = Qfalse;
+ dc->string = output;
+ } else {
+ dc->stream = output;
+ dc->string = Qfalse;
}
- if (output == sym_stdout) {
- dc->stream = stdout;
- dc->string = Qnil;
- }
- else if (output == sym_file) {
- rb_io_t *fptr;
- rb_require("tempfile");
- tmp = rb_assoc_new(rb_str_new_cstr(filename), rb_str_new_cstr(".json"));
- tmp = rb_funcallv(rb_path2class("Tempfile"), rb_intern("create"), 1, &tmp);
- io:
- dc->string = rb_io_get_write_io(tmp);
- rb_io_flush(dc->string);
- GetOpenFile(dc->string, fptr);
- dc->stream = rb_io_stdio_file(fptr);
- }
- else if (output == sym_string) {
- dc->string = rb_str_new_cstr("");
+ if (full == Qtrue) {
+ dc->full_heap = 1;
}
- else if (!NIL_P(tmp = rb_io_check_io(output))) {
- output = sym_file;
- goto io;
- }
- else {
- rb_raise(rb_eArgError, "wrong output option: %"PRIsVALUE, output);
+
+ if (RTEST(since)) {
+ dc->partial_dump = 1;
+ dc->since = NUM2SIZET(since);
+ } else {
+ dc->partial_dump = 0;
}
- return output;
}
static VALUE
-dump_result(struct dump_config *dc, VALUE output)
+dump_result(struct dump_config *dc)
{
- if (output == sym_string) {
- return rb_str_resurrect(dc->string);
- }
- else if (output == sym_file) {
- rb_io_flush(dc->string);
- return dc->string;
- }
- else {
- return Qnil;
+ dump_flush(dc);
+
+ if (dc->string) {
+ return dc->string;
+ } else {
+ rb_io_flush(dc->stream);
+ return dc->stream;
}
}
-/*
- * call-seq:
- * ObjectSpace.dump(obj[, output: :string]) # => "{ ... }"
- * ObjectSpace.dump(obj, output: :file) # => #<File:/tmp/rubyobj20131125-88733-1xkfmpv.json>
- * ObjectSpace.dump(obj, output: :stdout) # => nil
- *
- * Dump the contents of a ruby object as JSON.
- *
- * This method is only expected to work with C Ruby.
- * This is an experimental method and is subject to change.
- * In particular, the function signature and output format are
- * not guaranteed to be compatible in future versions of ruby.
- */
-
static VALUE
-objspace_dump(int argc, VALUE *argv, VALUE os)
+objspace_dump(VALUE os, VALUE obj, VALUE output)
{
- static const char filename[] = "rubyobj";
- VALUE obj = Qnil, opts = Qnil, output;
struct dump_config dc = {0,};
-
- rb_scan_args(argc, argv, "1:", &obj, &opts);
-
- output = dump_output(&dc, opts, sym_string, filename);
+ dump_output(&dc, output, Qnil, Qnil);
dump_object(obj, &dc);
- return dump_result(&dc, output);
+ return dump_result(&dc);
}
-/*
- * call-seq:
- * ObjectSpace.dump_all([output: :file]) # => #<File:/tmp/rubyheap20131125-88469-laoj3v.json>
- * ObjectSpace.dump_all(output: :stdout) # => nil
- * ObjectSpace.dump_all(output: :string) # => "{...}\n{...}\n..."
- * ObjectSpace.dump_all(output:
- * File.open('heap.json','w')) # => #<File:heap.json>
- *
- * Dump the contents of the ruby heap as JSON.
- *
- * This method is only expected to work with C Ruby.
- * This is an experimental method and is subject to change.
- * In particular, the function signature and output format are
- * not guaranteed to be compatible in future versions of ruby.
- */
-
static VALUE
-objspace_dump_all(int argc, VALUE *argv, VALUE os)
+objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since)
{
- static const char filename[] = "rubyheap";
- VALUE opts = Qnil, output;
struct dump_config dc = {0,};
+ dump_output(&dc, output, full, since);
- rb_scan_args(argc, argv, "0:", &opts);
-
- output = dump_output(&dc, opts, sym_file, filename);
-
- /* dump roots */
- rb_objspace_reachable_objects_from_root(root_obj_i, &dc);
- if (dc.roots) dump_append(&dc, "]}\n");
+ if (!dc.partial_dump || dc.since == 0) {
+ /* dump roots */
+ rb_objspace_reachable_objects_from_root(root_obj_i, &dc);
+ if (dc.roots) dump_append(&dc, "]}\n");
+ }
/* dump all objects */
rb_objspace_each_objects(heap_i, &dc);
- return dump_result(&dc, output);
+ return dump_result(&dc);
}
void
@@ -503,14 +626,8 @@ Init_objspace_dump(VALUE rb_mObjSpace)
rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
#endif
- rb_define_module_function(rb_mObjSpace, "dump", objspace_dump, -1);
- rb_define_module_function(rb_mObjSpace, "dump_all", objspace_dump_all, -1);
-
- sym_output = ID2SYM(rb_intern("output"));
- sym_stdout = ID2SYM(rb_intern("stdout"));
- sym_string = ID2SYM(rb_intern("string"));
- sym_file = ID2SYM(rb_intern("file"));
- sym_full = ID2SYM(rb_intern("full"));
+ rb_define_module_function(rb_mObjSpace, "_dump", objspace_dump, 2);
+ rb_define_module_function(rb_mObjSpace, "_dump_all", objspace_dump_all, 3);
/* force create static IDs */
rb_obj_gc_flags(rb_mObjSpace, 0, 0);
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
index 99b268182a..46435f9be6 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -1,11 +1,95 @@
-Version 2.1.4
+Version 2.2.1
=============
+Merged changes in 2.1.3. Additionally, the following issues are fixed by this
+release.
+
Bug fixes
---------
-* Do not use pkg-config if --with-openssl-dir option is specified.
- [[GitHub #486]](https://github.com/ruby/openssl/pull/486)
+* Fix crash in `OpenSSL::Timestamp::{Request,Response,TokenInfo}.new` when
+ invalid arguments are given.
+ [[GitHub #407]](https://github.com/ruby/openssl/pull/407)
+* Fix `OpenSSL::Timestamp::Factory#create_timestamp` with LibreSSL on platforms
+ where `time_t` has a different size from `long`.
+ [[GitHub #454]](https://github.com/ruby/openssl/pull/454)
+
+
+Version 2.2.0
+=============
+
+Compatibility notes
+-------------------
+
+* Remove unsupported MDC2, DSS, DSS1, and SHA algorithms.
+* Remove `OpenSSL::PKCS7::SignerInfo#name` alias for `#issuer`.
+ [[GitHub #266]](https://github.com/ruby/openssl/pull/266)
+* Deprecate `OpenSSL::Config#add_value` and `#[]=` for future removal.
+ [[GitHub #322]](https://github.com/ruby/openssl/pull/322)
+
+
+Notable changes
+---------------
+
+* Change default `OpenSSL::SSL::SSLServer#listen` backlog argument from
+ 5 to `Socket::SOMAXCONN`.
+ [[GitHub #286]](https://github.com/ruby/openssl/issues/286)
+* Make `OpenSSL::HMAC#==` use a timing safe string comparison.
+ [[GitHub #284]](https://github.com/ruby/openssl/pull/284)
+* Add support for SHA3 and BLAKE digests.
+ [[GitHub #282]](https://github.com/ruby/openssl/pull/282)
+* Add `OpenSSL::SSL::SSLSocket.open` for opening a `TCPSocket` and
+ returning an `OpenSSL::SSL::SSLSocket` for it.
+ [[GitHub #225]](https://github.com/ruby/openssl/issues/225)
+* Support marshalling of `OpenSSL::X509` and `OpenSSL::PKey` objects.
+ [[GitHub #281]](https://github.com/ruby/openssl/pull/281)
+ [[GitHub #363]](https://github.com/ruby/openssl/pull/363)
+* Add `OpenSSL.secure_compare` for timing safe string comparison for
+ strings of possibly unequal length.
+ [[GitHub #280]](https://github.com/ruby/openssl/pull/280)
+* Add `OpenSSL.fixed_length_secure_compare` for timing safe string
+ comparison for strings of equal length.
+ [[GitHub #269]](https://github.com/ruby/openssl/pull/269)
+* Add `OpenSSL::SSL::SSLSocket#{finished_message,peer_finished_message}`
+ for last finished message sent and received.
+ [[GitHub #250]](https://github.com/ruby/openssl/pull/250)
+* Add `OpenSSL::Timestamp` module for handing timestamp requests and
+ responses.
+ [[GitHub #204]](https://github.com/ruby/openssl/pull/204)
+* Add helper methods for `OpenSSL::X509::Certificate`:
+ `find_extension`, `subject_key_identifier`,
+ `authority_key_identifier`, `crl_uris`, `ca_issuer_uris` and
+ `ocsp_uris`, and for `OpenSSL::X509::CRL`:
+ `find_extension` and `subject_key_identifier`.
+ [[GitHub #260]](https://github.com/ruby/openssl/pull/260)
+ [[GitHub #275]](https://github.com/ruby/openssl/pull/275)
+ [[GitHub #293]](https://github.com/ruby/openssl/pull/293)
+* Add `OpenSSL::ECPoint#add` for performing elliptic curve point addition.
+ [[GitHub #261]](https://github.com/ruby/openssl/pull/261)
+* Make `OpenSSL::PKey::RSA#{export,to_der}` check `key`, `factors`, and
+ `crt_params` to do proper private key serialization.
+ [[GitHub #258]](https://github.com/ruby/openssl/pull/258)
+* Add `OpenSSL::SSL::{SSLSocket,SSLServer}#fileno`, returning the
+ underlying socket file descriptor number.
+ [[GitHub #247]](https://github.com/ruby/openssl/pull/247)
+* Support client certificates with TLS 1.3, and support post-handshake
+ authentication with OpenSSL 1.1.1+.
+ [[GitHub #239]](https://github.com/ruby/openssl/pull/239)
+* Add `OpenSSL::ASN1::ObjectId#==` for equality testing.
+* Add `OpenSSL::X509::Extension#value_der` for the raw value of
+ the extension.
+ [[GitHub #234]](https://github.com/ruby/openssl/pull/234)
+* Significantly reduce allocated memory in `OpenSSL::Buffering#do_write`.
+ [[GitHub #212]](https://github.com/ruby/openssl/pull/212)
+* Ensure all valid IPv6 addresses are considered valid as elements
+ of subjectAlternativeName in certificates.
+ [[GitHub #185]](https://github.com/ruby/openssl/pull/185)
+* Allow recipient's certificate to be omitted in PCKS7#decrypt.
+ [[GitHub #183]](https://github.com/ruby/openssl/pull/183)
+* Add support for reading keys in PKCS #8 format and export via instance methods
+ added to `OpenSSL::PKey` classes: `private_to_der`, `private_to_pem`,
+ `public_to_der` and `public_to_pem`.
+ [[GitHub #297]](https://github.com/ruby/openssl/pull/297)
Version 2.1.3
diff --git a/ext/openssl/depend b/ext/openssl/depend
index 68cf357294..92825ba0e9 100644
--- a/ext/openssl/depend
+++ b/ext/openssl/depend
@@ -8,9 +8,158 @@ ossl.o: $(arch_hdrdir)/ruby/config.h
ossl.o: $(hdrdir)/ruby.h
ossl.o: $(hdrdir)/ruby/assert.h
ossl.o: $(hdrdir)/ruby/backward.h
+ossl.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl.o: $(hdrdir)/ruby/defines.h
ossl.o: $(hdrdir)/ruby/encoding.h
ossl.o: $(hdrdir)/ruby/intern.h
+ossl.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl.o: $(hdrdir)/ruby/internal/assume.h
+ossl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl.o: $(hdrdir)/ruby/internal/cast.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl.o: $(hdrdir)/ruby/internal/config.h
+ossl.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl.o: $(hdrdir)/ruby/internal/core.h
+ossl.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl.o: $(hdrdir)/ruby/internal/ctype.h
+ossl.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl.o: $(hdrdir)/ruby/internal/dosish.h
+ossl.o: $(hdrdir)/ruby/internal/error.h
+ossl.o: $(hdrdir)/ruby/internal/eval.h
+ossl.o: $(hdrdir)/ruby/internal/event.h
+ossl.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl.o: $(hdrdir)/ruby/internal/gc.h
+ossl.o: $(hdrdir)/ruby/internal/glob.h
+ossl.o: $(hdrdir)/ruby/internal/globals.h
+ossl.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl.o: $(hdrdir)/ruby/internal/iterator.h
+ossl.o: $(hdrdir)/ruby/internal/memory.h
+ossl.o: $(hdrdir)/ruby/internal/method.h
+ossl.o: $(hdrdir)/ruby/internal/module.h
+ossl.o: $(hdrdir)/ruby/internal/newobj.h
+ossl.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl.o: $(hdrdir)/ruby/internal/symbol.h
+ossl.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl.o: $(hdrdir)/ruby/internal/value.h
+ossl.o: $(hdrdir)/ruby/internal/value_type.h
+ossl.o: $(hdrdir)/ruby/internal/variable.h
+ossl.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl.o: $(hdrdir)/ruby/io.h
ossl.o: $(hdrdir)/ruby/missing.h
ossl.o: $(hdrdir)/ruby/onigmo.h
@@ -39,7 +188,7 @@ ossl.o: ossl_pkcs7.h
ossl.o: ossl_pkey.h
ossl.o: ossl_rand.h
ossl.o: ossl_ssl.h
-ossl.o: ossl_version.h
+ossl.o: ossl_ts.h
ossl.o: ossl_x509.h
ossl.o: ruby_missing.h
ossl_asn1.o: $(RUBY_EXTCONF_H)
@@ -47,9 +196,158 @@ ossl_asn1.o: $(arch_hdrdir)/ruby/config.h
ossl_asn1.o: $(hdrdir)/ruby.h
ossl_asn1.o: $(hdrdir)/ruby/assert.h
ossl_asn1.o: $(hdrdir)/ruby/backward.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_asn1.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_asn1.o: $(hdrdir)/ruby/defines.h
ossl_asn1.o: $(hdrdir)/ruby/encoding.h
ossl_asn1.o: $(hdrdir)/ruby/intern.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/assume.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/cast.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/config.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/error.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/eval.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/event.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/gc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/glob.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/globals.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/memory.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/method.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/module.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/value.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/variable.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_asn1.o: $(hdrdir)/ruby/io.h
ossl_asn1.o: $(hdrdir)/ruby/missing.h
ossl_asn1.o: $(hdrdir)/ruby/onigmo.h
@@ -77,7 +375,7 @@ ossl_asn1.o: ossl_pkcs7.h
ossl_asn1.o: ossl_pkey.h
ossl_asn1.o: ossl_rand.h
ossl_asn1.o: ossl_ssl.h
-ossl_asn1.o: ossl_version.h
+ossl_asn1.o: ossl_ts.h
ossl_asn1.o: ossl_x509.h
ossl_asn1.o: ruby_missing.h
ossl_bio.o: $(RUBY_EXTCONF_H)
@@ -85,9 +383,158 @@ ossl_bio.o: $(arch_hdrdir)/ruby/config.h
ossl_bio.o: $(hdrdir)/ruby.h
ossl_bio.o: $(hdrdir)/ruby/assert.h
ossl_bio.o: $(hdrdir)/ruby/backward.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_bio.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_bio.o: $(hdrdir)/ruby/defines.h
ossl_bio.o: $(hdrdir)/ruby/encoding.h
ossl_bio.o: $(hdrdir)/ruby/intern.h
+ossl_bio.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_bio.o: $(hdrdir)/ruby/internal/assume.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_bio.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_bio.o: $(hdrdir)/ruby/internal/cast.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_bio.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_bio.o: $(hdrdir)/ruby/internal/config.h
+ossl_bio.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_bio.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_bio.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_bio.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_bio.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_bio.o: $(hdrdir)/ruby/internal/error.h
+ossl_bio.o: $(hdrdir)/ruby/internal/eval.h
+ossl_bio.o: $(hdrdir)/ruby/internal/event.h
+ossl_bio.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_bio.o: $(hdrdir)/ruby/internal/gc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/glob.h
+ossl_bio.o: $(hdrdir)/ruby/internal/globals.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_bio.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_bio.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_bio.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_bio.o: $(hdrdir)/ruby/internal/memory.h
+ossl_bio.o: $(hdrdir)/ruby/internal/method.h
+ossl_bio.o: $(hdrdir)/ruby/internal/module.h
+ossl_bio.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_bio.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_bio.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_bio.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_bio.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_bio.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_bio.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_bio.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_bio.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_bio.o: $(hdrdir)/ruby/internal/value.h
+ossl_bio.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_bio.o: $(hdrdir)/ruby/internal/variable.h
+ossl_bio.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_bio.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_bio.o: $(hdrdir)/ruby/io.h
ossl_bio.o: $(hdrdir)/ruby/missing.h
ossl_bio.o: $(hdrdir)/ruby/onigmo.h
@@ -115,7 +562,7 @@ ossl_bio.o: ossl_pkcs7.h
ossl_bio.o: ossl_pkey.h
ossl_bio.o: ossl_rand.h
ossl_bio.o: ossl_ssl.h
-ossl_bio.o: ossl_version.h
+ossl_bio.o: ossl_ts.h
ossl_bio.o: ossl_x509.h
ossl_bio.o: ruby_missing.h
ossl_bn.o: $(RUBY_EXTCONF_H)
@@ -123,13 +570,163 @@ ossl_bn.o: $(arch_hdrdir)/ruby/config.h
ossl_bn.o: $(hdrdir)/ruby.h
ossl_bn.o: $(hdrdir)/ruby/assert.h
ossl_bn.o: $(hdrdir)/ruby/backward.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_bn.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_bn.o: $(hdrdir)/ruby/defines.h
ossl_bn.o: $(hdrdir)/ruby/encoding.h
ossl_bn.o: $(hdrdir)/ruby/intern.h
+ossl_bn.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_bn.o: $(hdrdir)/ruby/internal/assume.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_bn.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_bn.o: $(hdrdir)/ruby/internal/cast.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_bn.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_bn.o: $(hdrdir)/ruby/internal/config.h
+ossl_bn.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_bn.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_bn.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_bn.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_bn.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_bn.o: $(hdrdir)/ruby/internal/error.h
+ossl_bn.o: $(hdrdir)/ruby/internal/eval.h
+ossl_bn.o: $(hdrdir)/ruby/internal/event.h
+ossl_bn.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_bn.o: $(hdrdir)/ruby/internal/gc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/glob.h
+ossl_bn.o: $(hdrdir)/ruby/internal/globals.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_bn.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_bn.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_bn.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_bn.o: $(hdrdir)/ruby/internal/memory.h
+ossl_bn.o: $(hdrdir)/ruby/internal/method.h
+ossl_bn.o: $(hdrdir)/ruby/internal/module.h
+ossl_bn.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_bn.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_bn.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_bn.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_bn.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_bn.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_bn.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_bn.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_bn.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_bn.o: $(hdrdir)/ruby/internal/value.h
+ossl_bn.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_bn.o: $(hdrdir)/ruby/internal/variable.h
+ossl_bn.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_bn.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_bn.o: $(hdrdir)/ruby/io.h
ossl_bn.o: $(hdrdir)/ruby/missing.h
ossl_bn.o: $(hdrdir)/ruby/onigmo.h
ossl_bn.o: $(hdrdir)/ruby/oniguruma.h
+ossl_bn.o: $(hdrdir)/ruby/ractor.h
ossl_bn.o: $(hdrdir)/ruby/ruby.h
ossl_bn.o: $(hdrdir)/ruby/st.h
ossl_bn.o: $(hdrdir)/ruby/subst.h
@@ -153,7 +750,7 @@ ossl_bn.o: ossl_pkcs7.h
ossl_bn.o: ossl_pkey.h
ossl_bn.o: ossl_rand.h
ossl_bn.o: ossl_ssl.h
-ossl_bn.o: ossl_version.h
+ossl_bn.o: ossl_ts.h
ossl_bn.o: ossl_x509.h
ossl_bn.o: ruby_missing.h
ossl_cipher.o: $(RUBY_EXTCONF_H)
@@ -161,9 +758,158 @@ ossl_cipher.o: $(arch_hdrdir)/ruby/config.h
ossl_cipher.o: $(hdrdir)/ruby.h
ossl_cipher.o: $(hdrdir)/ruby/assert.h
ossl_cipher.o: $(hdrdir)/ruby/backward.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_cipher.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_cipher.o: $(hdrdir)/ruby/defines.h
ossl_cipher.o: $(hdrdir)/ruby/encoding.h
ossl_cipher.o: $(hdrdir)/ruby/intern.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/assume.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/cast.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/config.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/error.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/eval.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/event.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/gc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/glob.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/globals.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/memory.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/method.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/module.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/value.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/variable.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_cipher.o: $(hdrdir)/ruby/io.h
ossl_cipher.o: $(hdrdir)/ruby/missing.h
ossl_cipher.o: $(hdrdir)/ruby/onigmo.h
@@ -191,7 +937,7 @@ ossl_cipher.o: ossl_pkcs7.h
ossl_cipher.o: ossl_pkey.h
ossl_cipher.o: ossl_rand.h
ossl_cipher.o: ossl_ssl.h
-ossl_cipher.o: ossl_version.h
+ossl_cipher.o: ossl_ts.h
ossl_cipher.o: ossl_x509.h
ossl_cipher.o: ruby_missing.h
ossl_config.o: $(RUBY_EXTCONF_H)
@@ -199,9 +945,158 @@ ossl_config.o: $(arch_hdrdir)/ruby/config.h
ossl_config.o: $(hdrdir)/ruby.h
ossl_config.o: $(hdrdir)/ruby/assert.h
ossl_config.o: $(hdrdir)/ruby/backward.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_config.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_config.o: $(hdrdir)/ruby/defines.h
ossl_config.o: $(hdrdir)/ruby/encoding.h
ossl_config.o: $(hdrdir)/ruby/intern.h
+ossl_config.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_config.o: $(hdrdir)/ruby/internal/assume.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_config.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_config.o: $(hdrdir)/ruby/internal/cast.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_config.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_config.o: $(hdrdir)/ruby/internal/config.h
+ossl_config.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_config.o: $(hdrdir)/ruby/internal/core.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_config.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_config.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_config.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_config.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_config.o: $(hdrdir)/ruby/internal/error.h
+ossl_config.o: $(hdrdir)/ruby/internal/eval.h
+ossl_config.o: $(hdrdir)/ruby/internal/event.h
+ossl_config.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_config.o: $(hdrdir)/ruby/internal/gc.h
+ossl_config.o: $(hdrdir)/ruby/internal/glob.h
+ossl_config.o: $(hdrdir)/ruby/internal/globals.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_config.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_config.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_config.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_config.o: $(hdrdir)/ruby/internal/memory.h
+ossl_config.o: $(hdrdir)/ruby/internal/method.h
+ossl_config.o: $(hdrdir)/ruby/internal/module.h
+ossl_config.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_config.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_config.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_config.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_config.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_config.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_config.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_config.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_config.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_config.o: $(hdrdir)/ruby/internal/value.h
+ossl_config.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_config.o: $(hdrdir)/ruby/internal/variable.h
+ossl_config.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_config.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_config.o: $(hdrdir)/ruby/io.h
ossl_config.o: $(hdrdir)/ruby/missing.h
ossl_config.o: $(hdrdir)/ruby/onigmo.h
@@ -229,7 +1124,7 @@ ossl_config.o: ossl_pkcs7.h
ossl_config.o: ossl_pkey.h
ossl_config.o: ossl_rand.h
ossl_config.o: ossl_ssl.h
-ossl_config.o: ossl_version.h
+ossl_config.o: ossl_ts.h
ossl_config.o: ossl_x509.h
ossl_config.o: ruby_missing.h
ossl_digest.o: $(RUBY_EXTCONF_H)
@@ -237,9 +1132,158 @@ ossl_digest.o: $(arch_hdrdir)/ruby/config.h
ossl_digest.o: $(hdrdir)/ruby.h
ossl_digest.o: $(hdrdir)/ruby/assert.h
ossl_digest.o: $(hdrdir)/ruby/backward.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_digest.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_digest.o: $(hdrdir)/ruby/defines.h
ossl_digest.o: $(hdrdir)/ruby/encoding.h
ossl_digest.o: $(hdrdir)/ruby/intern.h
+ossl_digest.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_digest.o: $(hdrdir)/ruby/internal/assume.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_digest.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_digest.o: $(hdrdir)/ruby/internal/cast.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_digest.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_digest.o: $(hdrdir)/ruby/internal/config.h
+ossl_digest.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_digest.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_digest.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_digest.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_digest.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_digest.o: $(hdrdir)/ruby/internal/error.h
+ossl_digest.o: $(hdrdir)/ruby/internal/eval.h
+ossl_digest.o: $(hdrdir)/ruby/internal/event.h
+ossl_digest.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_digest.o: $(hdrdir)/ruby/internal/gc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/glob.h
+ossl_digest.o: $(hdrdir)/ruby/internal/globals.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_digest.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_digest.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_digest.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_digest.o: $(hdrdir)/ruby/internal/memory.h
+ossl_digest.o: $(hdrdir)/ruby/internal/method.h
+ossl_digest.o: $(hdrdir)/ruby/internal/module.h
+ossl_digest.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_digest.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_digest.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_digest.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_digest.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_digest.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_digest.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_digest.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_digest.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_digest.o: $(hdrdir)/ruby/internal/value.h
+ossl_digest.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_digest.o: $(hdrdir)/ruby/internal/variable.h
+ossl_digest.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_digest.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_digest.o: $(hdrdir)/ruby/io.h
ossl_digest.o: $(hdrdir)/ruby/missing.h
ossl_digest.o: $(hdrdir)/ruby/onigmo.h
@@ -267,7 +1311,7 @@ ossl_digest.o: ossl_pkcs7.h
ossl_digest.o: ossl_pkey.h
ossl_digest.o: ossl_rand.h
ossl_digest.o: ossl_ssl.h
-ossl_digest.o: ossl_version.h
+ossl_digest.o: ossl_ts.h
ossl_digest.o: ossl_x509.h
ossl_digest.o: ruby_missing.h
ossl_engine.o: $(RUBY_EXTCONF_H)
@@ -275,9 +1319,158 @@ ossl_engine.o: $(arch_hdrdir)/ruby/config.h
ossl_engine.o: $(hdrdir)/ruby.h
ossl_engine.o: $(hdrdir)/ruby/assert.h
ossl_engine.o: $(hdrdir)/ruby/backward.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_engine.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_engine.o: $(hdrdir)/ruby/defines.h
ossl_engine.o: $(hdrdir)/ruby/encoding.h
ossl_engine.o: $(hdrdir)/ruby/intern.h
+ossl_engine.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_engine.o: $(hdrdir)/ruby/internal/assume.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_engine.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_engine.o: $(hdrdir)/ruby/internal/cast.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_engine.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_engine.o: $(hdrdir)/ruby/internal/config.h
+ossl_engine.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_engine.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_engine.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_engine.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_engine.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_engine.o: $(hdrdir)/ruby/internal/error.h
+ossl_engine.o: $(hdrdir)/ruby/internal/eval.h
+ossl_engine.o: $(hdrdir)/ruby/internal/event.h
+ossl_engine.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_engine.o: $(hdrdir)/ruby/internal/gc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/glob.h
+ossl_engine.o: $(hdrdir)/ruby/internal/globals.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_engine.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_engine.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_engine.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_engine.o: $(hdrdir)/ruby/internal/memory.h
+ossl_engine.o: $(hdrdir)/ruby/internal/method.h
+ossl_engine.o: $(hdrdir)/ruby/internal/module.h
+ossl_engine.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_engine.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_engine.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_engine.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_engine.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_engine.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_engine.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_engine.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_engine.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_engine.o: $(hdrdir)/ruby/internal/value.h
+ossl_engine.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_engine.o: $(hdrdir)/ruby/internal/variable.h
+ossl_engine.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_engine.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_engine.o: $(hdrdir)/ruby/io.h
ossl_engine.o: $(hdrdir)/ruby/missing.h
ossl_engine.o: $(hdrdir)/ruby/onigmo.h
@@ -305,7 +1498,7 @@ ossl_engine.o: ossl_pkcs7.h
ossl_engine.o: ossl_pkey.h
ossl_engine.o: ossl_rand.h
ossl_engine.o: ossl_ssl.h
-ossl_engine.o: ossl_version.h
+ossl_engine.o: ossl_ts.h
ossl_engine.o: ossl_x509.h
ossl_engine.o: ruby_missing.h
ossl_hmac.o: $(RUBY_EXTCONF_H)
@@ -313,9 +1506,158 @@ ossl_hmac.o: $(arch_hdrdir)/ruby/config.h
ossl_hmac.o: $(hdrdir)/ruby.h
ossl_hmac.o: $(hdrdir)/ruby/assert.h
ossl_hmac.o: $(hdrdir)/ruby/backward.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_hmac.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_hmac.o: $(hdrdir)/ruby/defines.h
ossl_hmac.o: $(hdrdir)/ruby/encoding.h
ossl_hmac.o: $(hdrdir)/ruby/intern.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/assume.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/cast.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/config.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/error.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/eval.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/event.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/gc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/glob.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/globals.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/memory.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/method.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/module.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/value.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/variable.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_hmac.o: $(hdrdir)/ruby/io.h
ossl_hmac.o: $(hdrdir)/ruby/missing.h
ossl_hmac.o: $(hdrdir)/ruby/onigmo.h
@@ -343,7 +1685,7 @@ ossl_hmac.o: ossl_pkcs7.h
ossl_hmac.o: ossl_pkey.h
ossl_hmac.o: ossl_rand.h
ossl_hmac.o: ossl_ssl.h
-ossl_hmac.o: ossl_version.h
+ossl_hmac.o: ossl_ts.h
ossl_hmac.o: ossl_x509.h
ossl_hmac.o: ruby_missing.h
ossl_kdf.o: $(RUBY_EXTCONF_H)
@@ -351,9 +1693,158 @@ ossl_kdf.o: $(arch_hdrdir)/ruby/config.h
ossl_kdf.o: $(hdrdir)/ruby.h
ossl_kdf.o: $(hdrdir)/ruby/assert.h
ossl_kdf.o: $(hdrdir)/ruby/backward.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_kdf.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_kdf.o: $(hdrdir)/ruby/defines.h
ossl_kdf.o: $(hdrdir)/ruby/encoding.h
ossl_kdf.o: $(hdrdir)/ruby/intern.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/assume.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/cast.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/config.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/error.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/eval.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/event.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/gc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/glob.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/globals.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/memory.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/method.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/module.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/value.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/variable.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_kdf.o: $(hdrdir)/ruby/io.h
ossl_kdf.o: $(hdrdir)/ruby/missing.h
ossl_kdf.o: $(hdrdir)/ruby/onigmo.h
@@ -381,7 +1872,7 @@ ossl_kdf.o: ossl_pkcs7.h
ossl_kdf.o: ossl_pkey.h
ossl_kdf.o: ossl_rand.h
ossl_kdf.o: ossl_ssl.h
-ossl_kdf.o: ossl_version.h
+ossl_kdf.o: ossl_ts.h
ossl_kdf.o: ossl_x509.h
ossl_kdf.o: ruby_missing.h
ossl_ns_spki.o: $(RUBY_EXTCONF_H)
@@ -389,9 +1880,158 @@ ossl_ns_spki.o: $(arch_hdrdir)/ruby/config.h
ossl_ns_spki.o: $(hdrdir)/ruby.h
ossl_ns_spki.o: $(hdrdir)/ruby/assert.h
ossl_ns_spki.o: $(hdrdir)/ruby/backward.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ns_spki.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_ns_spki.o: $(hdrdir)/ruby/defines.h
ossl_ns_spki.o: $(hdrdir)/ruby/encoding.h
ossl_ns_spki.o: $(hdrdir)/ruby/intern.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/config.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/error.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/event.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/method.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/module.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/value.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_ns_spki.o: $(hdrdir)/ruby/io.h
ossl_ns_spki.o: $(hdrdir)/ruby/missing.h
ossl_ns_spki.o: $(hdrdir)/ruby/onigmo.h
@@ -419,7 +2059,7 @@ ossl_ns_spki.o: ossl_pkcs7.h
ossl_ns_spki.o: ossl_pkey.h
ossl_ns_spki.o: ossl_rand.h
ossl_ns_spki.o: ossl_ssl.h
-ossl_ns_spki.o: ossl_version.h
+ossl_ns_spki.o: ossl_ts.h
ossl_ns_spki.o: ossl_x509.h
ossl_ns_spki.o: ruby_missing.h
ossl_ocsp.o: $(RUBY_EXTCONF_H)
@@ -427,9 +2067,158 @@ ossl_ocsp.o: $(arch_hdrdir)/ruby/config.h
ossl_ocsp.o: $(hdrdir)/ruby.h
ossl_ocsp.o: $(hdrdir)/ruby/assert.h
ossl_ocsp.o: $(hdrdir)/ruby/backward.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ocsp.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_ocsp.o: $(hdrdir)/ruby/defines.h
ossl_ocsp.o: $(hdrdir)/ruby/encoding.h
ossl_ocsp.o: $(hdrdir)/ruby/intern.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/config.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/error.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/event.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/method.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/module.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/value.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_ocsp.o: $(hdrdir)/ruby/io.h
ossl_ocsp.o: $(hdrdir)/ruby/missing.h
ossl_ocsp.o: $(hdrdir)/ruby/onigmo.h
@@ -457,7 +2246,7 @@ ossl_ocsp.o: ossl_pkcs7.h
ossl_ocsp.o: ossl_pkey.h
ossl_ocsp.o: ossl_rand.h
ossl_ocsp.o: ossl_ssl.h
-ossl_ocsp.o: ossl_version.h
+ossl_ocsp.o: ossl_ts.h
ossl_ocsp.o: ossl_x509.h
ossl_ocsp.o: ruby_missing.h
ossl_pkcs12.o: $(RUBY_EXTCONF_H)
@@ -465,9 +2254,158 @@ ossl_pkcs12.o: $(arch_hdrdir)/ruby/config.h
ossl_pkcs12.o: $(hdrdir)/ruby.h
ossl_pkcs12.o: $(hdrdir)/ruby/assert.h
ossl_pkcs12.o: $(hdrdir)/ruby/backward.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkcs12.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_pkcs12.o: $(hdrdir)/ruby/defines.h
ossl_pkcs12.o: $(hdrdir)/ruby/encoding.h
ossl_pkcs12.o: $(hdrdir)/ruby/intern.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_pkcs12.o: $(hdrdir)/ruby/io.h
ossl_pkcs12.o: $(hdrdir)/ruby/missing.h
ossl_pkcs12.o: $(hdrdir)/ruby/onigmo.h
@@ -495,7 +2433,7 @@ ossl_pkcs12.o: ossl_pkcs7.h
ossl_pkcs12.o: ossl_pkey.h
ossl_pkcs12.o: ossl_rand.h
ossl_pkcs12.o: ossl_ssl.h
-ossl_pkcs12.o: ossl_version.h
+ossl_pkcs12.o: ossl_ts.h
ossl_pkcs12.o: ossl_x509.h
ossl_pkcs12.o: ruby_missing.h
ossl_pkcs7.o: $(RUBY_EXTCONF_H)
@@ -503,9 +2441,158 @@ ossl_pkcs7.o: $(arch_hdrdir)/ruby/config.h
ossl_pkcs7.o: $(hdrdir)/ruby.h
ossl_pkcs7.o: $(hdrdir)/ruby/assert.h
ossl_pkcs7.o: $(hdrdir)/ruby/backward.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkcs7.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_pkcs7.o: $(hdrdir)/ruby/defines.h
ossl_pkcs7.o: $(hdrdir)/ruby/encoding.h
ossl_pkcs7.o: $(hdrdir)/ruby/intern.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_pkcs7.o: $(hdrdir)/ruby/io.h
ossl_pkcs7.o: $(hdrdir)/ruby/missing.h
ossl_pkcs7.o: $(hdrdir)/ruby/onigmo.h
@@ -533,7 +2620,7 @@ ossl_pkcs7.o: ossl_pkcs7.h
ossl_pkcs7.o: ossl_pkey.h
ossl_pkcs7.o: ossl_rand.h
ossl_pkcs7.o: ossl_ssl.h
-ossl_pkcs7.o: ossl_version.h
+ossl_pkcs7.o: ossl_ts.h
ossl_pkcs7.o: ossl_x509.h
ossl_pkcs7.o: ruby_missing.h
ossl_pkey.o: $(RUBY_EXTCONF_H)
@@ -541,9 +2628,158 @@ ossl_pkey.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey.o: $(hdrdir)/ruby.h
ossl_pkey.o: $(hdrdir)/ruby/assert.h
ossl_pkey.o: $(hdrdir)/ruby/backward.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_pkey.o: $(hdrdir)/ruby/defines.h
ossl_pkey.o: $(hdrdir)/ruby/encoding.h
ossl_pkey.o: $(hdrdir)/ruby/intern.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_pkey.o: $(hdrdir)/ruby/io.h
ossl_pkey.o: $(hdrdir)/ruby/missing.h
ossl_pkey.o: $(hdrdir)/ruby/onigmo.h
@@ -571,7 +2807,7 @@ ossl_pkey.o: ossl_pkey.c
ossl_pkey.o: ossl_pkey.h
ossl_pkey.o: ossl_rand.h
ossl_pkey.o: ossl_ssl.h
-ossl_pkey.o: ossl_version.h
+ossl_pkey.o: ossl_ts.h
ossl_pkey.o: ossl_x509.h
ossl_pkey.o: ruby_missing.h
ossl_pkey_dh.o: $(RUBY_EXTCONF_H)
@@ -579,9 +2815,158 @@ ossl_pkey_dh.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey_dh.o: $(hdrdir)/ruby.h
ossl_pkey_dh.o: $(hdrdir)/ruby/assert.h
ossl_pkey_dh.o: $(hdrdir)/ruby/backward.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_pkey_dh.o: $(hdrdir)/ruby/defines.h
ossl_pkey_dh.o: $(hdrdir)/ruby/encoding.h
ossl_pkey_dh.o: $(hdrdir)/ruby/intern.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_pkey_dh.o: $(hdrdir)/ruby/io.h
ossl_pkey_dh.o: $(hdrdir)/ruby/missing.h
ossl_pkey_dh.o: $(hdrdir)/ruby/onigmo.h
@@ -609,7 +2994,7 @@ ossl_pkey_dh.o: ossl_pkey.h
ossl_pkey_dh.o: ossl_pkey_dh.c
ossl_pkey_dh.o: ossl_rand.h
ossl_pkey_dh.o: ossl_ssl.h
-ossl_pkey_dh.o: ossl_version.h
+ossl_pkey_dh.o: ossl_ts.h
ossl_pkey_dh.o: ossl_x509.h
ossl_pkey_dh.o: ruby_missing.h
ossl_pkey_dsa.o: $(RUBY_EXTCONF_H)
@@ -617,9 +3002,158 @@ ossl_pkey_dsa.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey_dsa.o: $(hdrdir)/ruby.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/assert.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/backward.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/defines.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/encoding.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/intern.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/io.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/missing.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/onigmo.h
@@ -647,7 +3181,7 @@ ossl_pkey_dsa.o: ossl_pkey.h
ossl_pkey_dsa.o: ossl_pkey_dsa.c
ossl_pkey_dsa.o: ossl_rand.h
ossl_pkey_dsa.o: ossl_ssl.h
-ossl_pkey_dsa.o: ossl_version.h
+ossl_pkey_dsa.o: ossl_ts.h
ossl_pkey_dsa.o: ossl_x509.h
ossl_pkey_dsa.o: ruby_missing.h
ossl_pkey_ec.o: $(RUBY_EXTCONF_H)
@@ -655,9 +3189,158 @@ ossl_pkey_ec.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey_ec.o: $(hdrdir)/ruby.h
ossl_pkey_ec.o: $(hdrdir)/ruby/assert.h
ossl_pkey_ec.o: $(hdrdir)/ruby/backward.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_pkey_ec.o: $(hdrdir)/ruby/defines.h
ossl_pkey_ec.o: $(hdrdir)/ruby/encoding.h
ossl_pkey_ec.o: $(hdrdir)/ruby/intern.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_pkey_ec.o: $(hdrdir)/ruby/io.h
ossl_pkey_ec.o: $(hdrdir)/ruby/missing.h
ossl_pkey_ec.o: $(hdrdir)/ruby/onigmo.h
@@ -685,7 +3368,7 @@ ossl_pkey_ec.o: ossl_pkey.h
ossl_pkey_ec.o: ossl_pkey_ec.c
ossl_pkey_ec.o: ossl_rand.h
ossl_pkey_ec.o: ossl_ssl.h
-ossl_pkey_ec.o: ossl_version.h
+ossl_pkey_ec.o: ossl_ts.h
ossl_pkey_ec.o: ossl_x509.h
ossl_pkey_ec.o: ruby_missing.h
ossl_pkey_rsa.o: $(RUBY_EXTCONF_H)
@@ -693,9 +3376,158 @@ ossl_pkey_rsa.o: $(arch_hdrdir)/ruby/config.h
ossl_pkey_rsa.o: $(hdrdir)/ruby.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/assert.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/backward.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/defines.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/encoding.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/intern.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/assume.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/cast.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/config.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/error.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/eval.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/event.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/gc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/glob.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/globals.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/memory.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/method.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/module.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/variable.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/io.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/missing.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/onigmo.h
@@ -723,7 +3555,7 @@ ossl_pkey_rsa.o: ossl_pkey.h
ossl_pkey_rsa.o: ossl_pkey_rsa.c
ossl_pkey_rsa.o: ossl_rand.h
ossl_pkey_rsa.o: ossl_ssl.h
-ossl_pkey_rsa.o: ossl_version.h
+ossl_pkey_rsa.o: ossl_ts.h
ossl_pkey_rsa.o: ossl_x509.h
ossl_pkey_rsa.o: ruby_missing.h
ossl_rand.o: $(RUBY_EXTCONF_H)
@@ -731,9 +3563,158 @@ ossl_rand.o: $(arch_hdrdir)/ruby/config.h
ossl_rand.o: $(hdrdir)/ruby.h
ossl_rand.o: $(hdrdir)/ruby/assert.h
ossl_rand.o: $(hdrdir)/ruby/backward.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_rand.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_rand.o: $(hdrdir)/ruby/defines.h
ossl_rand.o: $(hdrdir)/ruby/encoding.h
ossl_rand.o: $(hdrdir)/ruby/intern.h
+ossl_rand.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_rand.o: $(hdrdir)/ruby/internal/assume.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_rand.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_rand.o: $(hdrdir)/ruby/internal/cast.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_rand.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_rand.o: $(hdrdir)/ruby/internal/config.h
+ossl_rand.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_rand.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_rand.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_rand.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_rand.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_rand.o: $(hdrdir)/ruby/internal/error.h
+ossl_rand.o: $(hdrdir)/ruby/internal/eval.h
+ossl_rand.o: $(hdrdir)/ruby/internal/event.h
+ossl_rand.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_rand.o: $(hdrdir)/ruby/internal/gc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/glob.h
+ossl_rand.o: $(hdrdir)/ruby/internal/globals.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_rand.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_rand.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_rand.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_rand.o: $(hdrdir)/ruby/internal/memory.h
+ossl_rand.o: $(hdrdir)/ruby/internal/method.h
+ossl_rand.o: $(hdrdir)/ruby/internal/module.h
+ossl_rand.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_rand.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_rand.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_rand.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_rand.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_rand.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_rand.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_rand.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_rand.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_rand.o: $(hdrdir)/ruby/internal/value.h
+ossl_rand.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_rand.o: $(hdrdir)/ruby/internal/variable.h
+ossl_rand.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_rand.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_rand.o: $(hdrdir)/ruby/io.h
ossl_rand.o: $(hdrdir)/ruby/missing.h
ossl_rand.o: $(hdrdir)/ruby/onigmo.h
@@ -761,7 +3742,7 @@ ossl_rand.o: ossl_pkey.h
ossl_rand.o: ossl_rand.c
ossl_rand.o: ossl_rand.h
ossl_rand.o: ossl_ssl.h
-ossl_rand.o: ossl_version.h
+ossl_rand.o: ossl_ts.h
ossl_rand.o: ossl_x509.h
ossl_rand.o: ruby_missing.h
ossl_ssl.o: $(RUBY_EXTCONF_H)
@@ -769,9 +3750,158 @@ ossl_ssl.o: $(arch_hdrdir)/ruby/config.h
ossl_ssl.o: $(hdrdir)/ruby.h
ossl_ssl.o: $(hdrdir)/ruby/assert.h
ossl_ssl.o: $(hdrdir)/ruby/backward.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ssl.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_ssl.o: $(hdrdir)/ruby/defines.h
ossl_ssl.o: $(hdrdir)/ruby/encoding.h
ossl_ssl.o: $(hdrdir)/ruby/intern.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/config.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/error.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/event.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/method.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/module.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/value.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_ssl.o: $(hdrdir)/ruby/io.h
ossl_ssl.o: $(hdrdir)/ruby/missing.h
ossl_ssl.o: $(hdrdir)/ruby/onigmo.h
@@ -799,7 +3929,7 @@ ossl_ssl.o: ossl_pkey.h
ossl_ssl.o: ossl_rand.h
ossl_ssl.o: ossl_ssl.c
ossl_ssl.o: ossl_ssl.h
-ossl_ssl.o: ossl_version.h
+ossl_ssl.o: ossl_ts.h
ossl_ssl.o: ossl_x509.h
ossl_ssl.o: ruby_missing.h
ossl_ssl_session.o: $(RUBY_EXTCONF_H)
@@ -807,9 +3937,158 @@ ossl_ssl_session.o: $(arch_hdrdir)/ruby/config.h
ossl_ssl_session.o: $(hdrdir)/ruby.h
ossl_ssl_session.o: $(hdrdir)/ruby/assert.h
ossl_ssl_session.o: $(hdrdir)/ruby/backward.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ssl_session.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_ssl_session.o: $(hdrdir)/ruby/defines.h
ossl_ssl_session.o: $(hdrdir)/ruby/encoding.h
ossl_ssl_session.o: $(hdrdir)/ruby/intern.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/config.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/error.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/event.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/method.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/module.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/value.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_ssl_session.o: $(hdrdir)/ruby/io.h
ossl_ssl_session.o: $(hdrdir)/ruby/missing.h
ossl_ssl_session.o: $(hdrdir)/ruby/onigmo.h
@@ -837,17 +4116,353 @@ ossl_ssl_session.o: ossl_pkey.h
ossl_ssl_session.o: ossl_rand.h
ossl_ssl_session.o: ossl_ssl.h
ossl_ssl_session.o: ossl_ssl_session.c
-ossl_ssl_session.o: ossl_version.h
+ossl_ssl_session.o: ossl_ts.h
ossl_ssl_session.o: ossl_x509.h
ossl_ssl_session.o: ruby_missing.h
+ossl_ts.o: $(RUBY_EXTCONF_H)
+ossl_ts.o: $(arch_hdrdir)/ruby/config.h
+ossl_ts.o: $(hdrdir)/ruby.h
+ossl_ts.o: $(hdrdir)/ruby/assert.h
+ossl_ts.o: $(hdrdir)/ruby/backward.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_ts.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ossl_ts.o: $(hdrdir)/ruby/defines.h
+ossl_ts.o: $(hdrdir)/ruby/encoding.h
+ossl_ts.o: $(hdrdir)/ruby/intern.h
+ossl_ts.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_ts.o: $(hdrdir)/ruby/internal/assume.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_ts.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_ts.o: $(hdrdir)/ruby/internal/cast.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_ts.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_ts.o: $(hdrdir)/ruby/internal/config.h
+ossl_ts.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_ts.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_ts.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_ts.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_ts.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_ts.o: $(hdrdir)/ruby/internal/error.h
+ossl_ts.o: $(hdrdir)/ruby/internal/eval.h
+ossl_ts.o: $(hdrdir)/ruby/internal/event.h
+ossl_ts.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_ts.o: $(hdrdir)/ruby/internal/gc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/glob.h
+ossl_ts.o: $(hdrdir)/ruby/internal/globals.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_ts.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_ts.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_ts.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_ts.o: $(hdrdir)/ruby/internal/memory.h
+ossl_ts.o: $(hdrdir)/ruby/internal/method.h
+ossl_ts.o: $(hdrdir)/ruby/internal/module.h
+ossl_ts.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_ts.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_ts.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_ts.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_ts.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_ts.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_ts.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_ts.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_ts.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_ts.o: $(hdrdir)/ruby/internal/value.h
+ossl_ts.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_ts.o: $(hdrdir)/ruby/internal/variable.h
+ossl_ts.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_ts.o: $(hdrdir)/ruby/internal/xmalloc.h
+ossl_ts.o: $(hdrdir)/ruby/io.h
+ossl_ts.o: $(hdrdir)/ruby/missing.h
+ossl_ts.o: $(hdrdir)/ruby/onigmo.h
+ossl_ts.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ts.o: $(hdrdir)/ruby/ruby.h
+ossl_ts.o: $(hdrdir)/ruby/st.h
+ossl_ts.o: $(hdrdir)/ruby/subst.h
+ossl_ts.o: $(hdrdir)/ruby/thread.h
+ossl_ts.o: openssl_missing.h
+ossl_ts.o: ossl.h
+ossl_ts.o: ossl_asn1.h
+ossl_ts.o: ossl_bio.h
+ossl_ts.o: ossl_bn.h
+ossl_ts.o: ossl_cipher.h
+ossl_ts.o: ossl_config.h
+ossl_ts.o: ossl_digest.h
+ossl_ts.o: ossl_engine.h
+ossl_ts.o: ossl_hmac.h
+ossl_ts.o: ossl_kdf.h
+ossl_ts.o: ossl_ns_spki.h
+ossl_ts.o: ossl_ocsp.h
+ossl_ts.o: ossl_pkcs12.h
+ossl_ts.o: ossl_pkcs7.h
+ossl_ts.o: ossl_pkey.h
+ossl_ts.o: ossl_rand.h
+ossl_ts.o: ossl_ssl.h
+ossl_ts.o: ossl_ts.c
+ossl_ts.o: ossl_ts.h
+ossl_ts.o: ossl_x509.h
+ossl_ts.o: ruby_missing.h
ossl_x509.o: $(RUBY_EXTCONF_H)
ossl_x509.o: $(arch_hdrdir)/ruby/config.h
ossl_x509.o: $(hdrdir)/ruby.h
ossl_x509.o: $(hdrdir)/ruby/assert.h
ossl_x509.o: $(hdrdir)/ruby/backward.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_x509.o: $(hdrdir)/ruby/defines.h
ossl_x509.o: $(hdrdir)/ruby/encoding.h
ossl_x509.o: $(hdrdir)/ruby/intern.h
+ossl_x509.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_x509.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_x509.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_x509.o: $(hdrdir)/ruby/io.h
ossl_x509.o: $(hdrdir)/ruby/missing.h
ossl_x509.o: $(hdrdir)/ruby/onigmo.h
@@ -874,7 +4489,7 @@ ossl_x509.o: ossl_pkcs7.h
ossl_x509.o: ossl_pkey.h
ossl_x509.o: ossl_rand.h
ossl_x509.o: ossl_ssl.h
-ossl_x509.o: ossl_version.h
+ossl_x509.o: ossl_ts.h
ossl_x509.o: ossl_x509.c
ossl_x509.o: ossl_x509.h
ossl_x509.o: ruby_missing.h
@@ -883,9 +4498,158 @@ ossl_x509attr.o: $(arch_hdrdir)/ruby/config.h
ossl_x509attr.o: $(hdrdir)/ruby.h
ossl_x509attr.o: $(hdrdir)/ruby/assert.h
ossl_x509attr.o: $(hdrdir)/ruby/backward.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509attr.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_x509attr.o: $(hdrdir)/ruby/defines.h
ossl_x509attr.o: $(hdrdir)/ruby/encoding.h
ossl_x509attr.o: $(hdrdir)/ruby/intern.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_x509attr.o: $(hdrdir)/ruby/io.h
ossl_x509attr.o: $(hdrdir)/ruby/missing.h
ossl_x509attr.o: $(hdrdir)/ruby/onigmo.h
@@ -912,7 +4676,7 @@ ossl_x509attr.o: ossl_pkcs7.h
ossl_x509attr.o: ossl_pkey.h
ossl_x509attr.o: ossl_rand.h
ossl_x509attr.o: ossl_ssl.h
-ossl_x509attr.o: ossl_version.h
+ossl_x509attr.o: ossl_ts.h
ossl_x509attr.o: ossl_x509.h
ossl_x509attr.o: ossl_x509attr.c
ossl_x509attr.o: ruby_missing.h
@@ -921,9 +4685,158 @@ ossl_x509cert.o: $(arch_hdrdir)/ruby/config.h
ossl_x509cert.o: $(hdrdir)/ruby.h
ossl_x509cert.o: $(hdrdir)/ruby/assert.h
ossl_x509cert.o: $(hdrdir)/ruby/backward.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509cert.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_x509cert.o: $(hdrdir)/ruby/defines.h
ossl_x509cert.o: $(hdrdir)/ruby/encoding.h
ossl_x509cert.o: $(hdrdir)/ruby/intern.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_x509cert.o: $(hdrdir)/ruby/io.h
ossl_x509cert.o: $(hdrdir)/ruby/missing.h
ossl_x509cert.o: $(hdrdir)/ruby/onigmo.h
@@ -950,7 +4863,7 @@ ossl_x509cert.o: ossl_pkcs7.h
ossl_x509cert.o: ossl_pkey.h
ossl_x509cert.o: ossl_rand.h
ossl_x509cert.o: ossl_ssl.h
-ossl_x509cert.o: ossl_version.h
+ossl_x509cert.o: ossl_ts.h
ossl_x509cert.o: ossl_x509.h
ossl_x509cert.o: ossl_x509cert.c
ossl_x509cert.o: ruby_missing.h
@@ -959,9 +4872,158 @@ ossl_x509crl.o: $(arch_hdrdir)/ruby/config.h
ossl_x509crl.o: $(hdrdir)/ruby.h
ossl_x509crl.o: $(hdrdir)/ruby/assert.h
ossl_x509crl.o: $(hdrdir)/ruby/backward.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509crl.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_x509crl.o: $(hdrdir)/ruby/defines.h
ossl_x509crl.o: $(hdrdir)/ruby/encoding.h
ossl_x509crl.o: $(hdrdir)/ruby/intern.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_x509crl.o: $(hdrdir)/ruby/io.h
ossl_x509crl.o: $(hdrdir)/ruby/missing.h
ossl_x509crl.o: $(hdrdir)/ruby/onigmo.h
@@ -988,7 +5050,7 @@ ossl_x509crl.o: ossl_pkcs7.h
ossl_x509crl.o: ossl_pkey.h
ossl_x509crl.o: ossl_rand.h
ossl_x509crl.o: ossl_ssl.h
-ossl_x509crl.o: ossl_version.h
+ossl_x509crl.o: ossl_ts.h
ossl_x509crl.o: ossl_x509.h
ossl_x509crl.o: ossl_x509crl.c
ossl_x509crl.o: ruby_missing.h
@@ -997,9 +5059,158 @@ ossl_x509ext.o: $(arch_hdrdir)/ruby/config.h
ossl_x509ext.o: $(hdrdir)/ruby.h
ossl_x509ext.o: $(hdrdir)/ruby/assert.h
ossl_x509ext.o: $(hdrdir)/ruby/backward.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509ext.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_x509ext.o: $(hdrdir)/ruby/defines.h
ossl_x509ext.o: $(hdrdir)/ruby/encoding.h
ossl_x509ext.o: $(hdrdir)/ruby/intern.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_x509ext.o: $(hdrdir)/ruby/io.h
ossl_x509ext.o: $(hdrdir)/ruby/missing.h
ossl_x509ext.o: $(hdrdir)/ruby/onigmo.h
@@ -1026,7 +5237,7 @@ ossl_x509ext.o: ossl_pkcs7.h
ossl_x509ext.o: ossl_pkey.h
ossl_x509ext.o: ossl_rand.h
ossl_x509ext.o: ossl_ssl.h
-ossl_x509ext.o: ossl_version.h
+ossl_x509ext.o: ossl_ts.h
ossl_x509ext.o: ossl_x509.h
ossl_x509ext.o: ossl_x509ext.c
ossl_x509ext.o: ruby_missing.h
@@ -1035,9 +5246,158 @@ ossl_x509name.o: $(arch_hdrdir)/ruby/config.h
ossl_x509name.o: $(hdrdir)/ruby.h
ossl_x509name.o: $(hdrdir)/ruby/assert.h
ossl_x509name.o: $(hdrdir)/ruby/backward.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509name.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_x509name.o: $(hdrdir)/ruby/defines.h
ossl_x509name.o: $(hdrdir)/ruby/encoding.h
ossl_x509name.o: $(hdrdir)/ruby/intern.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_x509name.o: $(hdrdir)/ruby/io.h
ossl_x509name.o: $(hdrdir)/ruby/missing.h
ossl_x509name.o: $(hdrdir)/ruby/onigmo.h
@@ -1064,7 +5424,7 @@ ossl_x509name.o: ossl_pkcs7.h
ossl_x509name.o: ossl_pkey.h
ossl_x509name.o: ossl_rand.h
ossl_x509name.o: ossl_ssl.h
-ossl_x509name.o: ossl_version.h
+ossl_x509name.o: ossl_ts.h
ossl_x509name.o: ossl_x509.h
ossl_x509name.o: ossl_x509name.c
ossl_x509name.o: ruby_missing.h
@@ -1073,9 +5433,158 @@ ossl_x509req.o: $(arch_hdrdir)/ruby/config.h
ossl_x509req.o: $(hdrdir)/ruby.h
ossl_x509req.o: $(hdrdir)/ruby/assert.h
ossl_x509req.o: $(hdrdir)/ruby/backward.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509req.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_x509req.o: $(hdrdir)/ruby/defines.h
ossl_x509req.o: $(hdrdir)/ruby/encoding.h
ossl_x509req.o: $(hdrdir)/ruby/intern.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_x509req.o: $(hdrdir)/ruby/io.h
ossl_x509req.o: $(hdrdir)/ruby/missing.h
ossl_x509req.o: $(hdrdir)/ruby/onigmo.h
@@ -1102,7 +5611,7 @@ ossl_x509req.o: ossl_pkcs7.h
ossl_x509req.o: ossl_pkey.h
ossl_x509req.o: ossl_rand.h
ossl_x509req.o: ossl_ssl.h
-ossl_x509req.o: ossl_version.h
+ossl_x509req.o: ossl_ts.h
ossl_x509req.o: ossl_x509.h
ossl_x509req.o: ossl_x509req.c
ossl_x509req.o: ruby_missing.h
@@ -1111,9 +5620,158 @@ ossl_x509revoked.o: $(arch_hdrdir)/ruby/config.h
ossl_x509revoked.o: $(hdrdir)/ruby.h
ossl_x509revoked.o: $(hdrdir)/ruby/assert.h
ossl_x509revoked.o: $(hdrdir)/ruby/backward.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509revoked.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_x509revoked.o: $(hdrdir)/ruby/defines.h
ossl_x509revoked.o: $(hdrdir)/ruby/encoding.h
ossl_x509revoked.o: $(hdrdir)/ruby/intern.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_x509revoked.o: $(hdrdir)/ruby/io.h
ossl_x509revoked.o: $(hdrdir)/ruby/missing.h
ossl_x509revoked.o: $(hdrdir)/ruby/onigmo.h
@@ -1140,7 +5798,7 @@ ossl_x509revoked.o: ossl_pkcs7.h
ossl_x509revoked.o: ossl_pkey.h
ossl_x509revoked.o: ossl_rand.h
ossl_x509revoked.o: ossl_ssl.h
-ossl_x509revoked.o: ossl_version.h
+ossl_x509revoked.o: ossl_ts.h
ossl_x509revoked.o: ossl_x509.h
ossl_x509revoked.o: ossl_x509revoked.c
ossl_x509revoked.o: ruby_missing.h
@@ -1149,9 +5807,158 @@ ossl_x509store.o: $(arch_hdrdir)/ruby/config.h
ossl_x509store.o: $(hdrdir)/ruby.h
ossl_x509store.o: $(hdrdir)/ruby/assert.h
ossl_x509store.o: $(hdrdir)/ruby/backward.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/assume.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/attributes.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/bool.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/limits.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/long_long.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ossl_x509store.o: $(hdrdir)/ruby/backward/2/stdarg.h
ossl_x509store.o: $(hdrdir)/ruby/defines.h
ossl_x509store.o: $(hdrdir)/ruby/encoding.h
ossl_x509store.o: $(hdrdir)/ruby/intern.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/anyargs.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/assume.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/cold.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/const.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/error.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/format.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/pure.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/warning.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/cast.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/compiler_since.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/config.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/constant_p.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rarray.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rclass.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rdata.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rfile.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rhash.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/robject.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rstring.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/ctype.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/dllexport.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/dosish.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/error.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/eval.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/event.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/fl_type.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/gc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/glob.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/globals.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/attribute.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/builtin.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/extension.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/feature.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/has/warning.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/array.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/class.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/compar.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/complex.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/cont.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/dir.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/enum.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/error.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/eval.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/file.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/gc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/hash.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/io.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/load.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/object.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/parse.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/proc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/process.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/random.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/range.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/rational.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/re.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/signal.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/string.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/struct.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/thread.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/time.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/variable.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/vm.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/interpreter.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/iterator.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/memory.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/method.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/module.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/newobj.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/rgengc.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/scan_args.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/special_consts.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/static_assert.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/stdalign.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/stdbool.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/symbol.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/token_paste.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/value.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/value_type.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/variable.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/warning_push.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/xmalloc.h
ossl_x509store.o: $(hdrdir)/ruby/io.h
ossl_x509store.o: $(hdrdir)/ruby/missing.h
ossl_x509store.o: $(hdrdir)/ruby/onigmo.h
@@ -1178,7 +5985,7 @@ ossl_x509store.o: ossl_pkcs7.h
ossl_x509store.o: ossl_pkey.h
ossl_x509store.o: ossl_rand.h
ossl_x509store.o: ossl_ssl.h
-ossl_x509store.o: ossl_version.h
+ossl_x509store.o: ossl_ts.h
ossl_x509store.o: ossl_x509.h
ossl_x509store.o: ossl_x509store.c
ossl_x509store.o: ruby_missing.h
diff --git a/ext/openssl/deprecation.rb b/ext/openssl/deprecation.rb
deleted file mode 100644
index afe989ead1..0000000000
--- a/ext/openssl/deprecation.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: false
-module OpenSSL
- def self.deprecated_warning_flag
- unless flag = (@deprecated_warning_flag ||= nil)
- if try_compile("", flag = "-Werror=deprecated-declarations")
- $warnflags = "#{@warnflags = $warnflags}" #{flag}"
- else
- flag = ""
- end
- @deprecated_warning_flag = flag
- end
- flag
- end
-
- def self.restore_warning_flag
- $warnflags = @warnflags
- end
-
- def self.check_func(func, header)
- have_func(func, header, deprecated_warning_flag)
- end
-
- def self.check_func_or_macro(func, header)
- check_func(func, header) or
- have_macro(func, header) && $defs.push("-DHAVE_#{func.upcase}")
- end
-end
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index f4212bd450..e13595c7c7 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -1,5 +1,5 @@
# -*- coding: us-ascii -*-
-# frozen_string_literal: false
+# frozen_string_literal: true
=begin
= Info
'OpenSSL for Ruby 2' project
@@ -12,16 +12,12 @@
=end
require "mkmf"
-require File.expand_path('../deprecation', __FILE__)
-dir_config_given = dir_config("openssl").any?
+dir_config("openssl")
dir_config("kerberos")
Logging::message "=== OpenSSL for Ruby configurator ===\n"
-# Check with -Werror=deprecated-declarations if available
-OpenSSL.deprecated_warning_flag
-
##
# Adds -DOSSL_DEBUG for compilation and some more targets when GCC is used
# To turn it on, use: --with-debug or --enable-debug
@@ -37,6 +33,12 @@ if $mswin || $mingw
have_library("ws2_32")
end
+if $mingw
+ append_cflags '-D_FORTIFY_SOURCE=2'
+ append_ldflags '-fstack-protector'
+ have_library 'ssp'
+end
+
def find_openssl_library
if $mswin || $mingw
# required for static OpenSSL libraries
@@ -88,7 +90,7 @@ def find_openssl_library
end
Logging::message "=== Checking for required stuff... ===\n"
-pkg_config_found = !dir_config_given && pkg_config("openssl") && have_header("openssl/ssl.h")
+pkg_config_found = pkg_config("openssl") && have_header("openssl/ssl.h")
if !pkg_config_found && !find_openssl_library
Logging::message "=== Checking for required stuff failed. ===\n"
@@ -119,10 +121,10 @@ end
Logging::message "=== Checking for OpenSSL features... ===\n"
# compile options
have_func("RAND_egd")
-engines = %w{builtin_engines openbsd_dev_crypto dynamic 4758cca aep atalla chil
- cswift nuron sureware ubsec padlock capi gmp gost cryptodev aesni}
+engines = %w{dynamic 4758cca aep atalla chil
+ cswift nuron sureware ubsec padlock capi gmp gost cryptodev}
engines.each { |name|
- OpenSSL.check_func_or_macro("ENGINE_load_#{name}", "openssl/engine.h")
+ have_func("ENGINE_load_#{name}()", "openssl/engine.h")
}
# added in 1.0.2
@@ -130,9 +132,9 @@ have_func("EC_curve_nist2nid")
have_func("X509_REVOKED_dup")
have_func("X509_STORE_CTX_get0_store")
have_func("SSL_CTX_set_alpn_select_cb")
-OpenSSL.check_func_or_macro("SSL_CTX_set1_curves_list", "openssl/ssl.h")
-OpenSSL.check_func_or_macro("SSL_CTX_set_ecdh_auto", "openssl/ssl.h")
-OpenSSL.check_func_or_macro("SSL_get_server_tmp_key", "openssl/ssl.h")
+have_func("SSL_CTX_set1_curves_list(NULL, NULL)", "openssl/ssl.h")
+have_func("SSL_CTX_set_ecdh_auto(NULL, 0)", "openssl/ssl.h")
+have_func("SSL_get_server_tmp_key(NULL, NULL)", "openssl/ssl.h")
have_func("SSL_is_server")
# added in 1.1.0
@@ -148,9 +150,9 @@ have_func("EVP_MD_CTX_new")
have_func("EVP_MD_CTX_free")
have_func("HMAC_CTX_new")
have_func("HMAC_CTX_free")
-OpenSSL.check_func("RAND_pseudo_bytes", "openssl/rand.h") # deprecated
have_func("X509_STORE_get_ex_data")
have_func("X509_STORE_set_ex_data")
+have_func("X509_STORE_get_ex_new_index")
have_func("X509_CRL_get0_signature")
have_func("X509_REQ_get0_signature")
have_func("X509_REVOKED_get0_serialNumber")
@@ -166,16 +168,23 @@ have_func("X509_CRL_up_ref")
have_func("X509_STORE_up_ref")
have_func("SSL_SESSION_up_ref")
have_func("EVP_PKEY_up_ref")
-OpenSSL.check_func_or_macro("SSL_CTX_set_tmp_ecdh_callback", "openssl/ssl.h") # removed
-OpenSSL.check_func_or_macro("SSL_CTX_set_min_proto_version", "openssl/ssl.h")
+have_func("SSL_CTX_set_tmp_ecdh_callback(NULL, NULL)", "openssl/ssl.h") # removed
+have_func("SSL_CTX_set_min_proto_version(NULL, 0)", "openssl/ssl.h")
have_func("SSL_CTX_get_security_level")
have_func("X509_get0_notBefore")
have_func("SSL_SESSION_get_protocol_version")
+have_func("TS_STATUS_INFO_get0_status")
+have_func("TS_STATUS_INFO_get0_text")
+have_func("TS_STATUS_INFO_get0_failure_info")
+have_func("TS_VERIFY_CTS_set_certs")
+have_func("TS_VERIFY_CTX_set_store")
+have_func("TS_VERIFY_CTX_add_flags")
+have_func("TS_RESP_CTX_set_time_cb")
have_func("EVP_PBE_scrypt")
+have_func("SSL_CTX_set_post_handshake_auth")
Logging::message "=== Checking done. ===\n"
create_header
-OpenSSL.restore_warning_flag
create_makefile("openssl")
Logging::message "Done.\n"
diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb
index 0914282920..b047485785 100644
--- a/ext/openssl/lib/openssl.rb
+++ b/ext/openssl/lib/openssl.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
=begin
= Info
'OpenSSL for Ruby 2' project
@@ -12,11 +12,27 @@
require 'openssl.so'
-require 'openssl/bn'
-require 'openssl/pkey'
-require 'openssl/cipher'
-require 'openssl/config'
-require 'openssl/digest'
-require 'openssl/x509'
-require 'openssl/ssl'
-require 'openssl/pkcs5'
+require_relative 'openssl/bn'
+require_relative 'openssl/pkey'
+require_relative 'openssl/cipher'
+require_relative 'openssl/config'
+require_relative 'openssl/digest'
+require_relative 'openssl/hmac'
+require_relative 'openssl/x509'
+require_relative 'openssl/ssl'
+require_relative 'openssl/pkcs5'
+require_relative 'openssl/version'
+
+module OpenSSL
+ # call-seq:
+ # OpenSSL.secure_compare(string, string) -> boolean
+ #
+ # Constant time memory comparison. Inputs are hashed using SHA-256 to mask
+ # the length of the secret. Returns +true+ if the strings are identical,
+ # +false+ otherwise.
+ def self.secure_compare(a, b)
+ hashed_a = OpenSSL::Digest.digest('SHA256', a)
+ hashed_b = OpenSSL::Digest.digest('SHA256', b)
+ OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b
+ end
+end
diff --git a/ext/openssl/lib/openssl/bn.rb b/ext/openssl/lib/openssl/bn.rb
index 8d1ebefb6e..0a5e11b4c2 100644
--- a/ext/openssl/lib/openssl/bn.rb
+++ b/ext/openssl/lib/openssl/bn.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#--
#
# = Ruby-space definitions that completes C-space funcs for BN
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 5d1586e594..32e04b4896 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -1,5 +1,5 @@
# coding: binary
-# frozen_string_literal: false
+# frozen_string_literal: true
#--
#= Info
# 'OpenSSL for Ruby 2' project
@@ -22,6 +22,29 @@
module OpenSSL::Buffering
include Enumerable
+ # A buffer which will retain binary encoding.
+ class Buffer < String
+ BINARY = Encoding::BINARY
+
+ def initialize
+ super
+
+ force_encoding(BINARY)
+ end
+
+ def << string
+ if string.encoding == BINARY
+ super(string)
+ else
+ super(string.b)
+ end
+
+ return self
+ end
+
+ alias concat <<
+ end
+
##
# The "sync mode" of the SSLSocket.
#
@@ -40,7 +63,7 @@ module OpenSSL::Buffering
def initialize(*)
super
@eof = false
- @rbuffer = ""
+ @rbuffer = Buffer.new
@sync = @io.sync
end
@@ -312,7 +335,7 @@ module OpenSSL::Buffering
# buffer is flushed to the underlying socket.
def do_write(s)
- @wbuffer = "" unless defined? @wbuffer
+ @wbuffer = Buffer.new unless defined? @wbuffer
@wbuffer << s
@wbuffer.force_encoding(Encoding::BINARY)
@sync ||= false
@@ -398,7 +421,7 @@ module OpenSSL::Buffering
# See IO#puts for full details.
def puts(*args)
- s = ""
+ s = Buffer.new
if args.empty?
s << "\n"
end
@@ -416,7 +439,7 @@ module OpenSSL::Buffering
# See IO#print for full details.
def print(*args)
- s = ""
+ s = Buffer.new
args.each{ |arg| s << arg.to_s }
do_write(s)
nil
diff --git a/ext/openssl/lib/openssl/cipher.rb b/ext/openssl/lib/openssl/cipher.rb
index af721b3a80..8ad8c35dd3 100644
--- a/ext/openssl/lib/openssl/cipher.rb
+++ b/ext/openssl/lib/openssl/cipher.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#--
# = Ruby-space predefined Cipher subclasses
#
diff --git a/ext/openssl/lib/openssl/config.rb b/ext/openssl/lib/openssl/config.rb
index 78a2da9eb9..9a0b787420 100644
--- a/ext/openssl/lib/openssl/config.rb
+++ b/ext/openssl/lib/openssl/config.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
=begin
= Ruby-space definitions that completes C-space funcs for Config
@@ -37,7 +37,7 @@ module OpenSSL
def parse(string)
c = new()
parse_config(StringIO.new(string)).each do |section, hash|
- c[section] = hash
+ c.set_section(section, hash)
end
c
end
@@ -53,9 +53,8 @@ module OpenSSL
def parse_config(io)
begin
parse_config_lines(io)
- rescue ConfigError => e
- e.message.replace("error in line #{io.lineno}: " + e.message)
- raise
+ rescue => error
+ raise ConfigError, "error in line #{io.lineno}: " + error.message
end
end
@@ -267,7 +266,7 @@ module OpenSSL
if filename
File.open(filename.to_s) do |file|
Config.parse_config(file).each do |section, hash|
- self[section] = hash
+ set_section(section, hash)
end
end
end
@@ -316,6 +315,8 @@ module OpenSSL
end
##
+ # *Deprecated in v2.2.0*. This method will be removed in a future release.
+ #
# Set the target _key_ with a given _value_ under a specific _section_.
#
# Given the following configurating file being loaded:
@@ -370,6 +371,8 @@ module OpenSSL
end
##
+ # *Deprecated in v2.2.0*. This method will be removed in a future release.
+ #
# Sets a specific _section_ name with a Hash _pairs_.
#
# Given the following configuration being created:
@@ -395,9 +398,13 @@ module OpenSSL
#
def []=(section, pairs)
check_modify
- @data[section] ||= {}
+ set_section(section, pairs)
+ end
+
+ def set_section(section, pairs) # :nodoc:
+ hash = @data[section] ||= {}
pairs.each do |key, value|
- self.add_value(section, key, value)
+ hash[key] = value
end
end
@@ -482,6 +489,8 @@ module OpenSSL
end
def check_modify
+ warn "#{caller(2, 1)[0]}: warning: do not modify OpenSSL::Config; this " \
+ "method is deprecated and will be removed in a future release."
raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen?
end
diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb
index b6744de6bd..2ff8398e44 100644
--- a/ext/openssl/lib/openssl/digest.rb
+++ b/ext/openssl/lib/openssl/digest.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#--
# = Ruby-space predefined Digest subclasses
#
@@ -15,11 +15,6 @@
module OpenSSL
class Digest
- alg = %w(MD2 MD4 MD5 MDC2 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512)
- if OPENSSL_VERSION_NUMBER < 0x10100000
- alg += %w(DSS DSS1 SHA)
- end
-
# Return the hash value computed with _name_ Digest. _name_ is either the
# long name or short name of a supported digest algorithm.
#
@@ -29,23 +24,26 @@ module OpenSSL
#
# which is equivalent to:
#
- # OpenSSL::Digest::SHA256.digest("abc")
+ # OpenSSL::Digest.digest('SHA256', "abc")
def self.digest(name, data)
super(data, name)
end
- alg.each{|name|
+ %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512).each do |name|
klass = Class.new(self) {
define_method(:initialize, ->(data = nil) {super(name, data)})
}
+
singleton = (class << klass; self; end)
+
singleton.class_eval{
- define_method(:digest){|data| new.digest(data) }
- define_method(:hexdigest){|data| new.hexdigest(data) }
+ define_method(:digest) {|data| new.digest(data)}
+ define_method(:hexdigest) {|data| new.hexdigest(data)}
}
- const_set(name, klass)
- }
+
+ const_set(name.tr('-', '_'), klass)
+ end
# Deprecated.
#
diff --git a/ext/openssl/lib/openssl/hmac.rb b/ext/openssl/lib/openssl/hmac.rb
new file mode 100644
index 0000000000..3d4427611d
--- /dev/null
+++ b/ext/openssl/lib/openssl/hmac.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module OpenSSL
+ class HMAC
+ # Securely compare with another HMAC instance in constant time.
+ def ==(other)
+ return false unless HMAC === other
+ return false unless self.digest.bytesize == other.digest.bytesize
+
+ OpenSSL.fixed_length_secure_compare(self.digest, other.digest)
+ end
+ end
+end
diff --git a/ext/openssl/lib/openssl/marshal.rb b/ext/openssl/lib/openssl/marshal.rb
new file mode 100644
index 0000000000..af5647192a
--- /dev/null
+++ b/ext/openssl/lib/openssl/marshal.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+#--
+# = Ruby-space definitions to add DER (de)serialization to classes
+#
+# = Info
+# 'OpenSSL for Ruby 2' project
+# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
+# All rights reserved.
+#
+# = Licence
+# This program is licensed under the same licence as Ruby.
+# (See the file 'LICENCE'.)
+#++
+module OpenSSL
+ module Marshal
+ def self.included(base)
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def _load(string)
+ new(string)
+ end
+ end
+
+ def _dump(_level)
+ to_der
+ end
+ end
+end
diff --git a/ext/openssl/lib/openssl/pkcs5.rb b/ext/openssl/lib/openssl/pkcs5.rb
index 959447df5e..8dedc4beef 100644
--- a/ext/openssl/lib/openssl/pkcs5.rb
+++ b/ext/openssl/lib/openssl/pkcs5.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#--
# Ruby/OpenSSL Project
# Copyright (C) 2017 Ruby/OpenSSL Project Authors
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
index 8a547c340d..9cc3276356 100644
--- a/ext/openssl/lib/openssl/pkey.rb
+++ b/ext/openssl/lib/openssl/pkey.rb
@@ -1,11 +1,24 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#--
# Ruby/OpenSSL Project
# Copyright (C) 2017 Ruby/OpenSSL Project Authors
#++
+require_relative 'marshal'
+
module OpenSSL::PKey
+ class DH
+ include OpenSSL::Marshal
+ end
+
+ class DSA
+ include OpenSSL::Marshal
+ end
+
if defined?(EC)
+ class EC
+ include OpenSSL::Marshal
+ end
class EC::Point
# :call-seq:
# point.to_bn([conversion_form]) -> OpenSSL::BN
@@ -22,4 +35,8 @@ module OpenSSL::PKey
end
end
end
+
+ class RSA
+ include OpenSSL::Marshal
+ end
end
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index 355eb2ebbb..8e12007383 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
=begin
= Info
'OpenSSL for Ruby 2' project
@@ -13,6 +13,7 @@
require "openssl/buffering"
require "io/nonblock"
require "ipaddr"
+require "socket"
module OpenSSL
module SSL
@@ -231,6 +232,11 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
end
module SocketForwarder
+ # The file descriptor for the socket.
+ def fileno
+ to_io.fileno
+ end
+
def addr
to_io.addr
end
@@ -435,6 +441,38 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
def session_get_cb
@context.session_get_cb
end
+
+ class << self
+
+ # call-seq:
+ # open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil)
+ #
+ # Creates a new instance of SSLSocket.
+ # _remote\_host_ and _remote\_port_ are used to open TCPSocket.
+ # If _local\_host_ and _local\_port_ are specified,
+ # then those parameters are used on the local end to establish the connection.
+ # If _context_ is provided,
+ # the SSL Sockets initial params will be taken from the context.
+ #
+ # === Examples
+ #
+ # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443)
+ # sock.connect # Initiates a connection to localhost:443
+ #
+ # with SSLContext:
+ #
+ # ctx = OpenSSL::SSL::SSLContext.new
+ # sock = OpenSSL::SSL::SSLSocket.open('localhost', 443, context: ctx)
+ # sock.connect # Initiates a connection to localhost:443 with SSLContext
+ def open(remote_host, remote_port, local_host=nil, local_port=nil, context: nil)
+ sock = ::TCPSocket.open(remote_host, remote_port, local_host, local_port)
+ if context.nil?
+ return OpenSSL::SSL::SSLSocket.new(sock)
+ else
+ return OpenSSL::SSL::SSLSocket.new(sock, context)
+ end
+ end
+ end
end
##
@@ -465,7 +503,7 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
end
# See TCPServer#listen for details.
- def listen(backlog=5)
+ def listen(backlog=Socket::SOMAXCONN)
@svr.listen(backlog)
end
diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb
new file mode 100644
index 0000000000..d541cbf162
--- /dev/null
+++ b/ext/openssl/lib/openssl/version.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+module OpenSSL
+ VERSION = "2.2.1"
+end
diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb
index 98358f90da..6771b90c1a 100644
--- a/ext/openssl/lib/openssl/x509.rb
+++ b/ext/openssl/lib/openssl/x509.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
#--
# = Ruby-space definitions that completes C-space funcs for X509 and subclasses
#
@@ -12,6 +12,8 @@
# (See the file 'LICENCE'.)
#++
+require_relative 'marshal'
+
module OpenSSL
module X509
class ExtensionFactory
@@ -41,6 +43,8 @@ module OpenSSL
end
class Extension
+ include OpenSSL::Marshal
+
def ==(other)
return false unless Extension === other
to_der == other.to_der
@@ -60,9 +64,146 @@ module OpenSSL
def to_a
[ self.oid, self.value, self.critical? ]
end
+
+ module Helpers
+ def find_extension(oid)
+ extensions.find { |e| e.oid == oid }
+ end
+ end
+
+ module SubjectKeyIdentifier
+ include Helpers
+
+ # Get the subject's key identifier from the subjectKeyIdentifier
+ # exteension, as described in RFC5280 Section 4.2.1.2.
+ #
+ # Returns the binary String key identifier or nil or raises
+ # ASN1::ASN1Error.
+ def subject_key_identifier
+ ext = find_extension("subjectKeyIdentifier")
+ return nil if ext.nil?
+
+ ski_asn1 = ASN1.decode(ext.value_der)
+ if ext.critical? || ski_asn1.tag_class != :UNIVERSAL || ski_asn1.tag != ASN1::OCTET_STRING
+ raise ASN1::ASN1Error, "invalid extension"
+ end
+
+ ski_asn1.value
+ end
+ end
+
+ module AuthorityKeyIdentifier
+ include Helpers
+
+ # Get the issuing certificate's key identifier from the
+ # authorityKeyIdentifier extension, as described in RFC5280
+ # Section 4.2.1.1
+ #
+ # Returns the binary String keyIdentifier or nil or raises
+ # ASN1::ASN1Error.
+ def authority_key_identifier
+ ext = find_extension("authorityKeyIdentifier")
+ return nil if ext.nil?
+
+ aki_asn1 = ASN1.decode(ext.value_der)
+ if ext.critical? || aki_asn1.tag_class != :UNIVERSAL || aki_asn1.tag != ASN1::SEQUENCE
+ raise ASN1::ASN1Error, "invalid extension"
+ end
+
+ key_id = aki_asn1.value.find do |v|
+ v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
+ end
+
+ key_id.nil? ? nil : key_id.value
+ end
+ end
+
+ module CRLDistributionPoints
+ include Helpers
+
+ # Get the distributionPoint fullName URI from the certificate's CRL
+ # distribution points extension, as described in RFC5280 Section
+ # 4.2.1.13
+ #
+ # Returns an array of strings or nil or raises ASN1::ASN1Error.
+ def crl_uris
+ ext = find_extension("crlDistributionPoints")
+ return nil if ext.nil?
+
+ cdp_asn1 = ASN1.decode(ext.value_der)
+ if cdp_asn1.tag_class != :UNIVERSAL || cdp_asn1.tag != ASN1::SEQUENCE
+ raise ASN1::ASN1Error, "invalid extension"
+ end
+
+ crl_uris = cdp_asn1.map do |crl_distribution_point|
+ distribution_point = crl_distribution_point.value.find do |v|
+ v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
+ end
+ full_name = distribution_point&.value&.find do |v|
+ v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
+ end
+ full_name&.value&.find do |v|
+ v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier
+ end
+ end
+
+ crl_uris&.map(&:value)
+ end
+ end
+
+ module AuthorityInfoAccess
+ include Helpers
+
+ # Get the information and services for the issuer from the certificate's
+ # authority information access extension exteension, as described in RFC5280
+ # Section 4.2.2.1.
+ #
+ # Returns an array of strings or nil or raises ASN1::ASN1Error.
+ def ca_issuer_uris
+ aia_asn1 = parse_aia_asn1
+ return nil if aia_asn1.nil?
+
+ ca_issuer = aia_asn1.value.select do |authority_info_access|
+ authority_info_access.value.first.value == "caIssuers"
+ end
+
+ ca_issuer&.map(&:value)&.map(&:last)&.map(&:value)
+ end
+
+ # Get the URIs for OCSP from the certificate's authority information access
+ # extension exteension, as described in RFC5280 Section 4.2.2.1.
+ #
+ # Returns an array of strings or nil or raises ASN1::ASN1Error.
+ def ocsp_uris
+ aia_asn1 = parse_aia_asn1
+ return nil if aia_asn1.nil?
+
+ ocsp = aia_asn1.value.select do |authority_info_access|
+ authority_info_access.value.first.value == "OCSP"
+ end
+
+ ocsp&.map(&:value)&.map(&:last)&.map(&:value)
+ end
+
+ private
+
+ def parse_aia_asn1
+ ext = find_extension("authorityInfoAccess")
+ return nil if ext.nil?
+
+ aia_asn1 = ASN1.decode(ext.value_der)
+ if ext.critical? || aia_asn1.tag_class != :UNIVERSAL || aia_asn1.tag != ASN1::SEQUENCE
+ raise ASN1::ASN1Error, "invalid extension"
+ end
+
+ aia_asn1
+ end
+ end
end
class Name
+ include OpenSSL::Marshal
+
module RFC2253DN
Special = ',=+<>#;'
HexChar = /[0-9a-fA-F]/
@@ -166,6 +307,8 @@ module OpenSSL
end
class Attribute
+ include OpenSSL::Marshal
+
def ==(other)
return false unless Attribute === other
to_der == other.to_der
@@ -179,6 +322,12 @@ module OpenSSL
end
class Certificate
+ include OpenSSL::Marshal
+ include Extension::SubjectKeyIdentifier
+ include Extension::AuthorityKeyIdentifier
+ include Extension::CRLDistributionPoints
+ include Extension::AuthorityInfoAccess
+
def pretty_print(q)
q.object_group(self) {
q.breakable
@@ -192,6 +341,9 @@ module OpenSSL
end
class CRL
+ include OpenSSL::Marshal
+ include Extension::AuthorityKeyIdentifier
+
def ==(other)
return false unless CRL === other
to_der == other.to_der
@@ -206,6 +358,8 @@ module OpenSSL
end
class Request
+ include OpenSSL::Marshal
+
def ==(other)
return false unless Request === other
to_der == other.to_der
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index 82a91f4173..ebbd0923dd 100644
--- a/ext/openssl/openssl.gemspec
+++ b/ext/openssl/openssl.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "openssl"
- spec.version = "2.1.4"
+ spec.version = "2.2.1"
spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"]
spec.email = ["ruby-core@ruby-lang.org"]
spec.summary = %q{OpenSSL provides SSL, TLS and general purpose cryptography.}
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 2.3.0"
spec.add_runtime_dependency "ipaddr"
- spec.add_development_dependency "rake", ">= 11.2.0"
+ spec.add_development_dependency "rake"
spec.add_development_dependency "rake-compiler"
spec.add_development_dependency "test-unit", "~> 3.0"
spec.add_development_dependency "rdoc"
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index 09998214e1..7d218f86f5 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -72,6 +72,9 @@ void ossl_HMAC_CTX_free(HMAC_CTX *);
#if !defined(HAVE_X509_STORE_SET_EX_DATA)
# define X509_STORE_set_ex_data(x, idx, data) \
CRYPTO_set_ex_data(&(x)->ex_data, (idx), (data))
+#endif
+
+#if !defined(HAVE_X509_STORE_GET_EX_NEW_INDEX) && !defined(X509_STORE_get_ex_new_index)
# define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, (l), (p), \
(newf), (dupf), (freef))
@@ -144,7 +147,8 @@ void ossl_X509_REQ_get0_signature(const X509_REQ *, const ASN1_BIT_STRING **, co
CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_EVP_PKEY);
#endif
-#if !defined(HAVE_OPAQUE_OPENSSL)
+#if !defined(HAVE_OPAQUE_OPENSSL) && \
+ (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x2070000fL)
#define IMPL_PKEY_GETTER(_type, _name) \
static inline _type *EVP_PKEY_get0_##_type(EVP_PKEY *pkey) { \
return pkey->pkey._name; }
@@ -219,4 +223,35 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
# define SSL_SESSION_get_protocol_version(s) ((s)->ssl_version)
#endif
+#if !defined(HAVE_TS_STATUS_INFO_GET0_STATUS)
+# define TS_STATUS_INFO_get0_status(a) ((a)->status)
+#endif
+
+#if !defined(HAVE_TS_STATUS_INFO_GET0_TEXT)
+# define TS_STATUS_INFO_get0_text(a) ((a)->text)
+#endif
+
+#if !defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO)
+# define TS_STATUS_INFO_get0_failure_info(a) ((a)->failure_info)
+#endif
+
+#if !defined(HAVE_TS_VERIFY_CTS_SET_CERTS)
+# define TS_VERIFY_CTS_set_certs(ctx, crts) ((ctx)->certs=(crts))
+#endif
+
+#if !defined(HAVE_TS_VERIFY_CTX_SET_STORE)
+# define TS_VERIFY_CTX_set_store(ctx, str) ((ctx)->store=(str))
+#endif
+
+#if !defined(HAVE_TS_VERIFY_CTX_ADD_FLAGS)
+# define TS_VERIFY_CTX_add_flags(ctx, f) ((ctx)->flags |= (f))
+#endif
+
+#if !defined(HAVE_TS_RESP_CTX_SET_TIME_CB)
+# define TS_RESP_CTX_set_time_cb(ctx, callback, dta) do { \
+ (ctx)->time_cb = (callback); \
+ (ctx)->time_cb_data = (dta); \
+ } while (0)
+#endif
+
#endif /* _OSSL_OPENSSL_MISSING_H_ */
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index e4196f0754..ce02efd983 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -497,8 +497,11 @@ print_mem_leaks(VALUE self)
int ret;
#endif
- BN_CTX_free(ossl_bn_ctx);
- ossl_bn_ctx = NULL;
+#ifndef HAVE_RB_EXT_RACTOR_SAFE
+ // for Ruby 2.x
+ void ossl_bn_ctx_free(void); // ossl_bn.c
+ ossl_bn_ctx_free();
+#endif
#if OPENSSL_VERSION_NUMBER >= 0x10100000
ret = CRYPTO_mem_leaks_fp(stderr);
@@ -605,6 +608,35 @@ static void Init_ossl_locks(void)
#endif /* !HAVE_OPENSSL_110_THREADING_API */
/*
+ * call-seq:
+ * OpenSSL.fixed_length_secure_compare(string, string) -> boolean
+ *
+ * Constant time memory comparison for fixed length strings, such as results
+ * of HMAC calculations.
+ *
+ * Returns +true+ if the strings are identical, +false+ if they are of the same
+ * length but not identical. If the length is different, +ArgumentError+ is
+ * raised.
+ */
+static VALUE
+ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
+{
+ const unsigned char *p1 = (const unsigned char *)StringValuePtr(str1);
+ const unsigned char *p2 = (const unsigned char *)StringValuePtr(str2);
+ long len1 = RSTRING_LEN(str1);
+ long len2 = RSTRING_LEN(str2);
+
+ if (len1 != len2) {
+ ossl_raise(rb_eArgError, "inputs must be of equal length");
+ }
+
+ switch (CRYPTO_memcmp(p1, p2, len1)) {
+ case 0: return Qtrue;
+ default: return Qfalse;
+ }
+}
+
+/*
* OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
* OpenSSL[https://www.openssl.org/] library.
*
@@ -635,7 +667,7 @@ static void Init_ossl_locks(void)
* ahold of the key may use it unless it is encrypted. In order to securely
* export a key you may export it with a pass phrase.
*
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
* pass_phrase = 'my secure pass phrase goes here'
*
* key_secure = key.export cipher, pass_phrase
@@ -710,16 +742,14 @@ static void Init_ossl_locks(void)
* To sign a document, a cryptographically secure hash of the document is
* computed first, which is then signed using the private key.
*
- * digest = OpenSSL::Digest::SHA256.new
- * signature = key.sign digest, document
+ * signature = key.sign 'SHA256', document
*
* To validate the signature, again a hash of the document is computed and
* the signature is decrypted using the public key. The result is then
* compared to the hash just computed, if they are equal the signature was
* valid.
*
- * digest = OpenSSL::Digest::SHA256.new
- * if key.verify digest, signature, document
+ * if key.verify 'SHA256', signature, document
* puts 'Valid'
* else
* puts 'Invalid'
@@ -745,7 +775,7 @@ static void Init_ossl_locks(void)
* using PBKDF2. PKCS #5 v2.0 recommends at least 8 bytes for the salt,
* the number of iterations largely depends on the hardware being used.
*
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
* cipher.encrypt
* iv = cipher.random_iv
*
@@ -753,7 +783,7 @@ static void Init_ossl_locks(void)
* salt = OpenSSL::Random.random_bytes 16
* iter = 20000
* key_len = cipher.key_len
- * digest = OpenSSL::Digest::SHA256.new
+ * digest = OpenSSL::Digest.new('SHA256')
*
* key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
* cipher.key = key
@@ -768,7 +798,7 @@ static void Init_ossl_locks(void)
* Use the same steps as before to derive the symmetric AES key, this time
* setting the Cipher up for decryption.
*
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
* cipher.decrypt
* cipher.iv = iv # the one generated with #random_iv
*
@@ -776,7 +806,7 @@ static void Init_ossl_locks(void)
* salt = ... # the one generated above
* iter = 20000
* key_len = cipher.key_len
- * digest = OpenSSL::Digest::SHA256.new
+ * digest = OpenSSL::Digest.new('SHA256')
*
* key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
* cipher.key = key
@@ -803,7 +833,7 @@ static void Init_ossl_locks(void)
*
* First set up the cipher for encryption
*
- * encryptor = OpenSSL::Cipher.new 'AES-128-CBC'
+ * encryptor = OpenSSL::Cipher.new 'AES-256-CBC'
* encryptor.encrypt
* encryptor.pkcs5_keyivgen pass_phrase, salt
*
@@ -816,7 +846,7 @@ static void Init_ossl_locks(void)
*
* Use a new Cipher instance set up for decryption
*
- * decryptor = OpenSSL::Cipher.new 'AES-128-CBC'
+ * decryptor = OpenSSL::Cipher.new 'AES-256-CBC'
* decryptor.decrypt
* decryptor.pkcs5_keyivgen pass_phrase, salt
*
@@ -833,7 +863,7 @@ static void Init_ossl_locks(void)
* signature.
*
* key = OpenSSL::PKey::RSA.new 2048
- * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
+ * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example'
*
* cert = OpenSSL::X509::Certificate.new
* cert.version = 2
@@ -872,7 +902,7 @@ static void Init_ossl_locks(void)
* certificate.
*
* cert.issuer = name
- * cert.sign key, OpenSSL::Digest::SHA1.new
+ * cert.sign key, OpenSSL::Digest.new('SHA1')
*
* open 'certificate.pem', 'w' do |io| io.write cert.to_pem end
*
@@ -904,7 +934,7 @@ static void Init_ossl_locks(void)
* ca_key = OpenSSL::PKey::RSA.new 2048
* pass_phrase = 'my secure pass phrase goes here'
*
- * cipher = OpenSSL::Cipher.new 'AES-128-CBC'
+ * cipher = OpenSSL::Cipher.new 'AES-256-CBC'
*
* open 'ca_key.pem', 'w', 0400 do |io|
* io.write ca_key.export(cipher, pass_phrase)
@@ -915,7 +945,7 @@ static void Init_ossl_locks(void)
* A CA certificate is created the same way we created a certificate above, but
* with different extensions.
*
- * ca_name = OpenSSL::X509::Name.parse 'CN=ca/DC=example'
+ * ca_name = OpenSSL::X509::Name.parse '/CN=ca/DC=example'
*
* ca_cert = OpenSSL::X509::Certificate.new
* ca_cert.serial = 0
@@ -948,7 +978,7 @@ static void Init_ossl_locks(void)
*
* Root CA certificates are self-signed.
*
- * ca_cert.sign ca_key, OpenSSL::Digest::SHA1.new
+ * ca_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
*
* The CA certificate is saved to disk so it may be distributed to all the
* users of the keys this CA will sign.
@@ -966,7 +996,7 @@ static void Init_ossl_locks(void)
* csr.version = 0
* csr.subject = name
* csr.public_key = key.public_key
- * csr.sign key, OpenSSL::Digest::SHA1.new
+ * csr.sign key, OpenSSL::Digest.new('SHA1')
*
* A CSR is saved to disk and sent to the CA for signing.
*
@@ -1010,7 +1040,7 @@ static void Init_ossl_locks(void)
* csr_cert.add_extension \
* extension_factory.create_extension('subjectKeyIdentifier', 'hash')
*
- * csr_cert.sign ca_key, OpenSSL::Digest::SHA1.new
+ * csr_cert.sign ca_key, OpenSSL::Digest.new('SHA1')
*
* open 'csr_cert.pem', 'w' do |io|
* io.write csr_cert.to_pem
@@ -1099,6 +1129,10 @@ static void Init_ossl_locks(void)
void
Init_openssl(void)
{
+#if HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
#undef rb_intern
/*
* Init timezone info
@@ -1125,11 +1159,7 @@ Init_openssl(void)
*/
mOSSL = rb_define_module("OpenSSL");
rb_global_variable(&mOSSL);
-
- /*
- * OpenSSL ruby extension version
- */
- rb_define_const(mOSSL, "VERSION", rb_str_new2(OSSL_VERSION));
+ rb_define_singleton_method(mOSSL, "fixed_length_secure_compare", ossl_crypto_fixed_length_secure_compare, 2);
/*
* Version of OpenSSL the ruby OpenSSL extension was built with
@@ -1205,6 +1235,9 @@ Init_openssl(void)
Init_ossl_pkey();
Init_ossl_rand();
Init_ossl_ssl();
+#ifndef OPENSSL_NO_TS
+ Init_ossl_ts();
+#endif
Init_ossl_x509();
Init_ossl_ocsp();
Init_ossl_engine();
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 39699bd5e6..c20f506bda 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -27,7 +27,9 @@
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/conf.h>
-#include <openssl/conf_api.h>
+#ifndef OPENSSL_NO_TS
+ #include <openssl/ts.h>
+#endif
#include <openssl/crypto.h>
#if !defined(OPENSSL_NO_ENGINE)
# include <openssl/engine.h>
@@ -86,9 +88,8 @@ VALUE ossl_buf2str(char *buf, int len);
VALUE ossl_str_new(const char *, long, int *);
#define ossl_str_adjust(str, p) \
do{\
- long len = RSTRING_LEN(str);\
long newlen = (long)((p) - (unsigned char*)RSTRING_PTR(str));\
- assert(newlen <= len);\
+ assert(newlen <= RSTRING_LEN(str));\
rb_str_set_len((str), newlen);\
}while(0)
/*
@@ -168,7 +169,9 @@ void ossl_debug(const char *, ...);
#include "ossl_pkey.h"
#include "ossl_rand.h"
#include "ossl_ssl.h"
-#include "ossl_version.h"
+#ifndef OPENSSL_NO_TS
+ #include "ossl_ts.h"
+#endif
#include "ossl_x509.h"
#include "ossl_engine.h"
#include "ossl_kdf.h"
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 0085d4beab..9eb1826f02 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -1285,6 +1285,30 @@ ossl_asn1obj_get_ln(VALUE self)
return ret;
}
+/*
+ * call-seq:
+ * oid == other_oid => true or false
+ *
+ * Returns +true+ if _other_oid_ is the same as _oid_
+ */
+static VALUE
+ossl_asn1obj_eq(VALUE self, VALUE other)
+{
+ VALUE valSelf, valOther;
+ int nidSelf, nidOther;
+
+ valSelf = ossl_asn1_get_value(self);
+ valOther = ossl_asn1_get_value(other);
+
+ if ((nidSelf = OBJ_txt2nid(StringValueCStr(valSelf))) == NID_undef)
+ ossl_raise(eASN1Error, "OBJ_txt2nid");
+
+ if ((nidOther = OBJ_txt2nid(StringValueCStr(valOther))) == NID_undef)
+ ossl_raise(eASN1Error, "OBJ_txt2nid");
+
+ return nidSelf == nidOther ? Qtrue : Qfalse;
+}
+
static VALUE
asn1obj_get_oid_i(VALUE vobj)
{
@@ -1818,6 +1842,7 @@ do{\
rb_define_method(cASN1ObjectId, "oid", ossl_asn1obj_get_oid, 0);
rb_define_alias(cASN1ObjectId, "short_name", "sn");
rb_define_alias(cASN1ObjectId, "long_name", "ln");
+ rb_define_method(cASN1ObjectId, "==", ossl_asn1obj_eq, 1);
rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0);
rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0);
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index e3846d2df9..bec37299f7 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -10,6 +10,10 @@
/* modified by Michal Rokos <m.rokos@sh.cvut.cz> */
#include "ossl.h"
+#if HAVE_RB_EXT_RACTOR_SAFE
+#include <ruby/ractor.h>
+#endif
+
#define NewBN(klass) \
TypedData_Wrap_Struct((klass), &ossl_bn_type, 0)
#define SetBN(obj, bn) do { \
@@ -150,12 +154,58 @@ ossl_bn_value_ptr(volatile VALUE *ptr)
/*
* Private
*/
-/*
- * BN_CTX - is used in more difficult math. ops
- * (Why just 1? Because Ruby itself isn't thread safe,
- * we don't need to care about threads)
- */
-BN_CTX *ossl_bn_ctx;
+
+#if HAVE_RB_EXT_RACTOR_SAFE
+void
+ossl_bn_ctx_free(void *ptr)
+{
+ BN_CTX *ctx = (BN_CTX *)ptr;
+ BN_CTX_free(ctx);
+}
+
+struct rb_ractor_local_storage_type ossl_bn_ctx_key_type = {
+ NULL, // mark
+ ossl_bn_ctx_free,
+};
+
+rb_ractor_local_key_t ossl_bn_ctx_key;
+
+BN_CTX *
+ossl_bn_ctx_get(void)
+{
+ // stored in ractor local storage
+
+ BN_CTX *ctx = rb_ractor_local_storage_ptr(ossl_bn_ctx_key);
+ if (!ctx) {
+ if (!(ctx = BN_CTX_new())) {
+ ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
+ }
+ rb_ractor_local_storage_ptr_set(ossl_bn_ctx_key, ctx);
+ }
+ return ctx;
+}
+#else
+// for ruby 2.x
+static BN_CTX *gv_ossl_bn_ctx;
+
+BN_CTX *
+ossl_bn_ctx_get(void)
+{
+ if (gv_ossl_bn_ctx == NULL) {
+ if (!(gv_ossl_bn_ctx = BN_CTX_new())) {
+ ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
+ }
+ }
+ return gv_ossl_bn_ctx;
+}
+
+void
+ossl_bn_ctx_free(void)
+{
+ BN_CTX_free(gv_ossl_bn_ctx);
+ gv_ossl_bn_ctx = NULL;
+}
+#endif
static VALUE
ossl_bn_alloc(VALUE klass)
@@ -173,7 +223,6 @@ ossl_bn_alloc(VALUE klass)
/*
* call-seq:
- * OpenSSL::BN.new => aBN
* OpenSSL::BN.new(bn) => aBN
* OpenSSL::BN.new(integer) => aBN
* OpenSSL::BN.new(string) => aBN
@@ -193,6 +242,10 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
base = NUM2INT(bs);
}
+ if (NIL_P(str)) {
+ ossl_raise(rb_eArgError, "invalid argument");
+ }
+
if (RB_INTEGER_TYPE_P(str)) {
GetBN(self, bn);
integer_to_bnptr(str, bn);
@@ -1099,9 +1152,11 @@ Init_ossl_bn(void)
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
- if (!(ossl_bn_ctx = BN_CTX_new())) {
- ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
- }
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ ossl_bn_ctx_key = rb_ractor_local_storage_ptr_newkey(&ossl_bn_ctx_key_type);
+#else
+ ossl_bn_ctx_get();
+#endif
eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError);
diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h
index a19ba19487..1cc041fc22 100644
--- a/ext/openssl/ossl_bn.h
+++ b/ext/openssl/ossl_bn.h
@@ -13,7 +13,8 @@
extern VALUE cBN;
extern VALUE eBNError;
-extern BN_CTX *ossl_bn_ctx;
+BN_CTX *ossl_bn_ctx_get(void);
+#define ossl_bn_ctx ossl_bn_ctx_get()
#define GetBNPtr(obj) ossl_bn_value_ptr(&(obj))
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 0840c84a71..5b92fc39f0 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -104,7 +104,7 @@ ossl_cipher_alloc(VALUE klass)
* call-seq:
* Cipher.new(string) -> cipher
*
- * The string must be a valid cipher name like "AES-128-CBC" or "3DES".
+ * The string must contain a valid cipher name like "AES-256-CBC".
*
* A list of cipher names is available by calling OpenSSL::Cipher.ciphers.
*/
@@ -237,8 +237,7 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
ossl_raise(eCipherError, NULL);
}
- if (p_key)
- rb_ivar_set(self, id_key_set, Qtrue);
+ rb_ivar_set(self, id_key_set, p_key ? Qtrue : Qfalse);
return self;
}
@@ -815,6 +814,31 @@ ossl_cipher_block_size(VALUE self)
}
/*
+ * call-seq:
+ * cipher.ccm_data_len = integer -> integer
+ *
+ * Sets the length of the plaintext / ciphertext message that will be
+ * processed in CCM mode. Make sure to call this method after #key= and
+ * #iv= have been set, and before #auth_data=.
+ *
+ * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
+ */
+static VALUE
+ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len)
+{
+ int in_len, out_len;
+ EVP_CIPHER_CTX *ctx;
+
+ in_len = NUM2INT(data_len);
+
+ GetCipher(self, ctx);
+ if (EVP_CipherUpdate(ctx, NULL, &out_len, NULL, in_len) != 1)
+ ossl_raise(eCipherError, NULL);
+
+ return data_len;
+}
+
+/*
* INIT
*/
void
@@ -852,22 +876,6 @@ Init_ossl_cipher(void)
*
* cipher = OpenSSL::Cipher.new('AES-128-CBC')
*
- * For each algorithm supported, there is a class defined under the
- * Cipher class that goes by the name of the cipher, e.g. to obtain an
- * instance of AES, you could also use
- *
- * # these are equivalent
- * cipher = OpenSSL::Cipher::AES.new(128, :CBC)
- * cipher = OpenSSL::Cipher::AES.new(128, 'CBC')
- * cipher = OpenSSL::Cipher::AES.new('128-CBC')
- *
- * Finally, due to its wide-spread use, there are also extra classes
- * defined for the different key sizes of AES
- *
- * cipher = OpenSSL::Cipher::AES128.new(:CBC)
- * cipher = OpenSSL::Cipher::AES192.new(:CBC)
- * cipher = OpenSSL::Cipher::AES256.new(:CBC)
- *
* === Choosing either encryption or decryption mode
*
* Encryption and decryption are often very similar operations for
@@ -896,7 +904,7 @@ Init_ossl_cipher(void)
* without processing the password further. A simple and secure way to
* create a key for a particular Cipher is
*
- * cipher = OpenSSL::AES256.new(:CFB)
+ * cipher = OpenSSL::Cipher.new('AES-256-CFB')
* cipher.encrypt
* key = cipher.random_key # also sets the generated key on the Cipher
*
@@ -964,14 +972,14 @@ Init_ossl_cipher(void)
*
* data = "Very, very confidential data"
*
- * cipher = OpenSSL::Cipher::AES.new(128, :CBC)
+ * cipher = OpenSSL::Cipher.new('AES-128-CBC')
* cipher.encrypt
* key = cipher.random_key
* iv = cipher.random_iv
*
* encrypted = cipher.update(data) + cipher.final
* ...
- * decipher = OpenSSL::Cipher::AES.new(128, :CBC)
+ * decipher = OpenSSL::Cipher.new('AES-128-CBC')
* decipher.decrypt
* decipher.key = key
* decipher.iv = iv
@@ -1007,7 +1015,7 @@ Init_ossl_cipher(void)
* not to reuse the _key_ and _nonce_ pair. Reusing an nonce ruins the
* security guarantees of GCM mode.
*
- * cipher = OpenSSL::Cipher::AES.new(128, :GCM).encrypt
+ * cipher = OpenSSL::Cipher.new('AES-128-GCM').encrypt
* cipher.key = key
* cipher.iv = nonce
* cipher.auth_data = auth_data
@@ -1023,7 +1031,7 @@ Init_ossl_cipher(void)
* ciphertext with a probability of 1/256.
*
* raise "tag is truncated!" unless tag.bytesize == 16
- * decipher = OpenSSL::Cipher::AES.new(128, :GCM).decrypt
+ * decipher = OpenSSL::Cipher.new('AES-128-GCM').decrypt
* decipher.key = key
* decipher.iv = nonce
* decipher.auth_tag = tag
@@ -1060,6 +1068,7 @@ Init_ossl_cipher(void)
rb_define_method(cCipher, "iv_len", ossl_cipher_iv_length, 0);
rb_define_method(cCipher, "block_size", ossl_cipher_block_size, 0);
rb_define_method(cCipher, "padding=", ossl_cipher_set_padding, 1);
+ rb_define_method(cCipher, "ccm_data_len=", ossl_cipher_set_ccm_data_len, 1);
id_auth_tag_len = rb_intern_const("auth_tag_len");
id_key_set = rb_intern_const("key_set");
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index 8674a3947c..6294fa2acf 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -192,7 +192,7 @@ ossl_digest_reset(VALUE self)
* be passed individually to the Digest instance.
*
* === Example
- * digest = OpenSSL::Digest::SHA256.new
+ * digest = OpenSSL::Digest.new('SHA256')
* digest.update('First input')
* digest << 'Second input' # equivalent to digest.update('Second input')
* result = digest.digest
@@ -248,7 +248,7 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self)
* Returns the sn of this Digest algorithm.
*
* === Example
- * digest = OpenSSL::Digest::SHA512.new
+ * digest = OpenSSL::Digest.new('SHA512')
* puts digest.name # => SHA512
*
*/
@@ -270,7 +270,7 @@ ossl_digest_name(VALUE self)
* final message digest result.
*
* === Example
- * digest = OpenSSL::Digest::SHA1.new
+ * digest = OpenSSL::Digest.new('SHA1')
* puts digest.digest_length # => 20
*
*/
@@ -294,7 +294,7 @@ ossl_digest_size(VALUE self)
* consecutively.
*
* === Example
- * digest = OpenSSL::Digest::SHA1.new
+ * digest = OpenSSL::Digest.new('SHA1')
* puts digest.block_length # => 64
*/
static VALUE
@@ -346,54 +346,19 @@ Init_ossl_digest(void)
* the integrity of a signed document, it suffices to re-compute the hash
* and verify that it is equal to that in the signature.
*
- * Among the supported message digest algorithms are:
- * * SHA, SHA1, SHA224, SHA256, SHA384 and SHA512
- * * MD2, MD4, MDC2 and MD5
- * * RIPEMD160
- * * DSS, DSS1 (Pseudo algorithms to be used for DSA signatures. DSS is
- * equal to SHA and DSS1 is equal to SHA1)
+ * You can get a list of all digest algorithms supported on your system by
+ * running this command in your terminal:
*
- * For each of these algorithms, there is a sub-class of Digest that
- * can be instantiated as simply as e.g.
+ * openssl list -digest-algorithms
*
- * digest = OpenSSL::Digest::SHA1.new
+ * Among the OpenSSL 1.1.1 supported message digest algorithms are:
+ * * SHA224, SHA256, SHA384, SHA512, SHA512-224 and SHA512-256
+ * * SHA3-224, SHA3-256, SHA3-384 and SHA3-512
+ * * BLAKE2s256 and BLAKE2b512
*
- * === Mapping between Digest class and sn/ln
+ * Each of these algorithms can be instantiated using the name:
*
- * The sn (short names) and ln (long names) are defined in
- * <openssl/object.h> and <openssl/obj_mac.h>. They are textual
- * representations of ASN.1 OBJECT IDENTIFIERs. Each supported digest
- * algorithm has an OBJECT IDENTIFIER associated to it and those again
- * have short/long names assigned to them.
- * E.g. the OBJECT IDENTIFIER for SHA-1 is 1.3.14.3.2.26 and its
- * sn is "SHA1" and its ln is "sha1".
- * ==== MD2
- * * sn: MD2
- * * ln: md2
- * ==== MD4
- * * sn: MD4
- * * ln: md4
- * ==== MD5
- * * sn: MD5
- * * ln: md5
- * ==== SHA
- * * sn: SHA
- * * ln: SHA
- * ==== SHA-1
- * * sn: SHA1
- * * ln: sha1
- * ==== SHA-224
- * * sn: SHA224
- * * ln: sha224
- * ==== SHA-256
- * * sn: SHA256
- * * ln: sha256
- * ==== SHA-384
- * * sn: SHA384
- * * ln: sha384
- * ==== SHA-512
- * * sn: SHA512
- * * ln: sha512
+ * digest = OpenSSL::Digest.new('SHA256')
*
* "Breaking" a message digest algorithm means defying its one-way
* function characteristics, i.e. producing a collision or finding a way
@@ -406,7 +371,7 @@ Init_ossl_digest(void)
* === Hashing a file
*
* data = File.read('document')
- * sha256 = OpenSSL::Digest::SHA256.new
+ * sha256 = OpenSSL::Digest.new('SHA256')
* digest = sha256.digest(data)
*
* === Hashing several pieces of data at once
@@ -414,7 +379,7 @@ Init_ossl_digest(void)
* data1 = File.read('file1')
* data2 = File.read('file2')
* data3 = File.read('file3')
- * sha256 = OpenSSL::Digest::SHA256.new
+ * sha256 = OpenSSL::Digest.new('SHA256')
* sha256 << data1
* sha256 << data2
* sha256 << data3
@@ -423,7 +388,7 @@ Init_ossl_digest(void)
* === Reuse a Digest instance
*
* data1 = File.read('file1')
- * sha256 = OpenSSL::Digest::SHA256.new
+ * sha256 = OpenSSL::Digest.new('SHA256')
* digest1 = sha256.digest(data1)
*
* data2 = File.read('file2')
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 5ca0d4ca3f..90546934d1 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -93,9 +93,6 @@ static const rb_data_type_t ossl_engine_type = {
static VALUE
ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
{
-#if !defined(HAVE_ENGINE_LOAD_BUILTIN_ENGINES)
- return Qnil;
-#else
VALUE name;
rb_scan_args(argc, argv, "01", &name);
@@ -104,10 +101,10 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
return Qtrue;
}
StringValueCStr(name);
-#ifndef OPENSSL_NO_STATIC_ENGINE
#if HAVE_ENGINE_LOAD_DYNAMIC
OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC);
#endif
+#ifndef OPENSSL_NO_STATIC_ENGINE
#if HAVE_ENGINE_LOAD_4758CCA
OSSL_ENGINE_LOAD_IF_MATCH(4758cca, 4758CCA);
#endif
@@ -144,20 +141,13 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
#if HAVE_ENGINE_LOAD_GOST
OSSL_ENGINE_LOAD_IF_MATCH(gost, GOST);
#endif
+#endif
#if HAVE_ENGINE_LOAD_CRYPTODEV
OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV);
#endif
-#if HAVE_ENGINE_LOAD_AESNI
- OSSL_ENGINE_LOAD_IF_MATCH(aesni, AESNI);
-#endif
-#endif
-#ifdef HAVE_ENGINE_LOAD_OPENBSD_DEV_CRYPTO
- OSSL_ENGINE_LOAD_IF_MATCH(openbsd_dev_crypto, OPENBSD_DEV_CRYPTO);
-#endif
OSSL_ENGINE_LOAD_IF_MATCH(openssl, OPENSSL);
rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
return Qnil;
-#endif /* HAVE_ENGINE_LOAD_BUILTIN_ENGINES */
}
/*
diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
index 564dcab522..e831cff519 100644
--- a/ext/openssl/ossl_hmac.c
+++ b/ext/openssl/ossl_hmac.c
@@ -84,18 +84,12 @@ ossl_hmac_alloc(VALUE klass)
*
* === A note about comparisons
*
- * Two instances won't be equal when they're compared, even if they have the
- * same value. Use #to_s or #hexdigest to return the authentication code that
- * the instance represents. For example:
+ * Two instances can be securely compared with #== in constant time:
*
* other_instance = OpenSSL::HMAC.new('key', OpenSSL::Digest.new('sha1'))
- * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
- * instance
- * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
- * instance == other_instance
- * #=> false
- * instance.to_s == other_instance.to_s
- * #=> true
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
+ * instance == other_instance
+ * #=> true
*
*/
static VALUE
@@ -359,7 +353,7 @@ Init_ossl_hmac(void)
* data1 = File.read("file1")
* data2 = File.read("file2")
* key = "key"
- * digest = OpenSSL::Digest::SHA256.new
+ * digest = OpenSSL::Digest.new('SHA256')
* hmac = OpenSSL::HMAC.new(key, digest)
* hmac << data1
* hmac << data2
diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c
index ee124718b5..486e789458 100644
--- a/ext/openssl/ossl_kdf.c
+++ b/ext/openssl/ossl_kdf.c
@@ -272,7 +272,7 @@ Init_ossl_kdf(void)
* # store this with the generated value
* salt = OpenSSL::Random.random_bytes(16)
* iter = 20_000
- * hash = OpenSSL::Digest::SHA256.new
+ * hash = OpenSSL::Digest.new('SHA256')
* len = hash.digest_length
* # the final value to be stored
* value = OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter,
@@ -284,24 +284,8 @@ Init_ossl_kdf(void)
* Typically, "==" short-circuits on evaluation, and is therefore
* vulnerable to timing attacks. The proper way is to use a method that
* always takes the same amount of time when comparing two values, thus
- * not leaking any information to potential attackers. To compare two
- * values, the following could be used:
- *
- * def eql_time_cmp(a, b)
- * unless a.length == b.length
- * return false
- * end
- * cmp = b.bytes
- * result = 0
- * a.bytes.each_with_index {|c,i|
- * result |= c ^ cmp[i]
- * }
- * result == 0
- * end
- *
- * Please note that the premature return in case of differing lengths
- * typically does not leak valuable information - when using PBKDF2, the
- * length of the values to be compared is of fixed size.
+ * not leaking any information to potential attackers. To do this, use
+ * +OpenSSL.fixed_length_secure_compare+.
*/
mKDF = rb_define_module_under(mOSSL, "KDF");
/*
diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c
index 6f61e61bf5..9b1147367a 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -350,7 +350,7 @@ ossl_spki_verify(VALUE self, VALUE key)
* spki = OpenSSL::Netscape::SPKI.new
* spki.challenge = "RandomChallenge"
* spki.public_key = key.public_key
- * spki.sign(key, OpenSSL::Digest::SHA256.new)
+ * spki.sign(key, OpenSSL::Digest.new('SHA256'))
* #send a request containing this to a server generating a certificate
* === Verifying an SPKI request
* request = #...
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index c0237791da..7a92e5df68 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -1489,13 +1489,15 @@ ossl_ocspcid_initialize_copy(VALUE self, VALUE other)
* call-seq:
* OpenSSL::OCSP::CertificateId.new(subject, issuer, digest = nil) -> certificate_id
* OpenSSL::OCSP::CertificateId.new(der_string) -> certificate_id
+ * OpenSSL::OCSP::CertificateId.new(obj) -> certificate_id
*
* Creates a new OpenSSL::OCSP::CertificateId for the given _subject_ and
* _issuer_ X509 certificates. The _digest_ is a digest algorithm that is used
* to compute the hash values. This defaults to SHA-1.
*
* If only one argument is given, decodes it as DER representation of a
- * certificate ID.
+ * certificate ID or generates certificate ID from the object that responds to
+ * the to_der method.
*/
static VALUE
ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self)
@@ -1717,7 +1719,7 @@ Init_ossl_ocsp(void)
* subject certificate so the CA knows which certificate we are asking
* about:
*
- * digest = OpenSSL::Digest::SHA1.new
+ * digest = OpenSSL::Digest.new('SHA1')
* certificate_id =
* OpenSSL::OCSP::CertificateId.new subject, issuer, digest
*
@@ -1734,18 +1736,11 @@ Init_ossl_ocsp(void)
* To submit the request to the CA for verification we need to extract the
* OCSP URI from the subject certificate:
*
- * authority_info_access = subject.extensions.find do |extension|
- * extension.oid == 'authorityInfoAccess'
- * end
- *
- * descriptions = authority_info_access.value.split "\n"
- * ocsp = descriptions.find do |description|
- * description.start_with? 'OCSP'
- * end
+ * ocsp_uris = subject.ocsp_uris
*
* require 'uri'
*
- * ocsp_uri = URI ocsp[/URI:(.*)/, 1]
+ * ocsp_uri = URI ocsp_uris[0]
*
* To submit the request we'll POST the request to the OCSP URI (per RFC
* 2560). Note that we only handle HTTP requests and don't handle any
diff --git a/ext/openssl/ossl_ocsp.h b/ext/openssl/ossl_ocsp.h
index 21e2c99a2e..6d2aac8657 100644
--- a/ext/openssl/ossl_ocsp.h
+++ b/ext/openssl/ossl_ocsp.h
@@ -13,9 +13,9 @@
#if !defined(OPENSSL_NO_OCSP)
extern VALUE mOCSP;
-extern VALUE cOPCSReq;
-extern VALUE cOPCSRes;
-extern VALUE cOPCSBasicRes;
+extern VALUE cOCSPReq;
+extern VALUE cOCSPRes;
+extern VALUE cOCSPBasicRes;
#endif
void Init_ossl_ocsp(void);
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 79ba0bdf48..ea8e92d1bc 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -9,21 +9,6 @@
*/
#include "ossl.h"
-#define NewPKCS7(klass) \
- TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, 0)
-#define SetPKCS7(obj, pkcs7) do { \
- if (!(pkcs7)) { \
- ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
- } \
- RTYPEDDATA_DATA(obj) = (pkcs7); \
-} while (0)
-#define GetPKCS7(obj, pkcs7) do { \
- TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \
- if (!(pkcs7)) { \
- ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
- } \
-} while (0)
-
#define NewPKCS7si(klass) \
TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, 0)
#define SetPKCS7si(obj, p7si) do { \
@@ -75,7 +60,7 @@ ossl_pkcs7_free(void *ptr)
PKCS7_free(ptr);
}
-static const rb_data_type_t ossl_pkcs7_type = {
+const rb_data_type_t ossl_pkcs7_type = {
"OpenSSL/PKCS7",
{
0, ossl_pkcs7_free,
@@ -803,9 +788,9 @@ ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self)
BIO *out;
VALUE str;
- rb_scan_args(argc, argv, "21", &pkey, &cert, &flags);
+ rb_scan_args(argc, argv, "12", &pkey, &cert, &flags);
key = GetPrivPKeyPtr(pkey); /* NO NEED TO DUP */
- x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
+ x509 = NIL_P(cert) ? NULL : GetX509CertPtr(cert); /* NO NEED TO DUP */
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
GetPKCS7(self, p7);
if(!(out = BIO_new(BIO_s_mem())))
@@ -1088,7 +1073,6 @@ Init_ossl_pkcs7(void)
rb_define_alloc_func(cPKCS7Signer, ossl_pkcs7si_alloc);
rb_define_method(cPKCS7Signer, "initialize", ossl_pkcs7si_initialize,3);
rb_define_method(cPKCS7Signer, "issuer", ossl_pkcs7si_get_issuer, 0);
- rb_define_alias(cPKCS7Signer, "name", "issuer");
rb_define_method(cPKCS7Signer, "serial", ossl_pkcs7si_get_serial,0);
rb_define_method(cPKCS7Signer,"signed_time",ossl_pkcs7si_get_signed_time,0);
diff --git a/ext/openssl/ossl_pkcs7.h b/ext/openssl/ossl_pkcs7.h
index 139e00d640..3e1b094670 100644
--- a/ext/openssl/ossl_pkcs7.h
+++ b/ext/openssl/ossl_pkcs7.h
@@ -10,6 +10,22 @@
#if !defined(_OSSL_PKCS7_H_)
#define _OSSL_PKCS7_H_
+#define NewPKCS7(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, 0)
+#define SetPKCS7(obj, pkcs7) do { \
+ if (!(pkcs7)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+ } \
+ RTYPEDDATA_DATA(obj) = (pkcs7); \
+} while (0)
+#define GetPKCS7(obj, pkcs7) do { \
+ TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \
+ if (!(pkcs7)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+ } \
+} while (0)
+
+extern const rb_data_type_t ossl_pkcs7_type;
extern VALUE cPKCS7;
extern VALUE cPKCS7Signer;
extern VALUE cPKCS7Recipient;
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index e1fffb2446..23204087ac 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -167,21 +167,27 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
pass = ossl_pem_passwd_value(pass);
bio = ossl_obj2bio(&data);
- if (!(pkey = d2i_PrivateKey_bio(bio, NULL))) {
- OSSL_BIO_reset(bio);
- if (!(pkey = PEM_read_bio_PrivateKey(bio, NULL, ossl_pem_passwd_cb, (void *)pass))) {
- OSSL_BIO_reset(bio);
- if (!(pkey = d2i_PUBKEY_bio(bio, NULL))) {
- OSSL_BIO_reset(bio);
- pkey = PEM_read_bio_PUBKEY(bio, NULL, ossl_pem_passwd_cb, (void *)pass);
- }
- }
- }
+ if ((pkey = d2i_PrivateKey_bio(bio, NULL)))
+ goto ok;
+ OSSL_BIO_reset(bio);
+ if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, (void *)pass)))
+ goto ok;
+ OSSL_BIO_reset(bio);
+ if ((pkey = d2i_PUBKEY_bio(bio, NULL)))
+ goto ok;
+ 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, (void *)pass)))
+ goto ok;
+ OSSL_BIO_reset(bio);
+ if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)))
+ goto ok;
BIO_free(bio);
- if (!pkey)
- ossl_raise(ePKeyError, "Could not parse PKey");
+ ossl_raise(ePKeyError, "Could not parse PKey");
+ok:
+ BIO_free(bio);
return ossl_pkey_new(pkey);
}
@@ -294,6 +300,160 @@ ossl_pkey_initialize(VALUE self)
}
/*
+ * call-seq:
+ * pkey.oid -> string
+ *
+ * Returns the short name of the OID associated with _pkey_.
+ */
+static VALUE
+ossl_pkey_oid(VALUE self)
+{
+ EVP_PKEY *pkey;
+ int nid;
+
+ GetPKey(self, pkey);
+ nid = EVP_PKEY_id(pkey);
+ return rb_str_new_cstr(OBJ_nid2sn(nid));
+}
+
+/*
+ * call-seq:
+ * pkey.inspect -> string
+ *
+ * Returns a string describing the PKey object.
+ */
+static VALUE
+ossl_pkey_inspect(VALUE self)
+{
+ EVP_PKEY *pkey;
+ int nid;
+
+ GetPKey(self, pkey);
+ nid = EVP_PKEY_id(pkey);
+ return rb_sprintf("#<%"PRIsVALUE":%p oid=%s>",
+ rb_class_name(CLASS_OF(self)), (void *)self,
+ OBJ_nid2sn(nid));
+}
+
+static VALUE
+do_pkcs8_export(int argc, VALUE *argv, VALUE self, int to_der)
+{
+ EVP_PKEY *pkey;
+ VALUE cipher, pass;
+ const EVP_CIPHER *enc = NULL;
+ BIO *bio;
+
+ GetPKey(self, pkey);
+ rb_scan_args(argc, argv, "02", &cipher, &pass);
+ if (argc > 0) {
+ /*
+ * TODO: EncryptedPrivateKeyInfo actually has more options.
+ * Should they be exposed?
+ */
+ enc = ossl_evp_get_cipherbyname(cipher);
+ pass = ossl_pem_passwd_value(pass);
+ }
+
+ bio = BIO_new(BIO_s_mem());
+ if (!bio)
+ ossl_raise(ePKeyError, "BIO_new");
+ if (to_der) {
+ if (!i2d_PKCS8PrivateKey_bio(bio, pkey, enc, NULL, 0,
+ ossl_pem_passwd_cb, (void *)pass)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "i2d_PKCS8PrivateKey_bio");
+ }
+ }
+ else {
+ if (!PEM_write_bio_PKCS8PrivateKey(bio, pkey, enc, NULL, 0,
+ ossl_pem_passwd_cb, (void *)pass)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "PEM_write_bio_PKCS8PrivateKey");
+ }
+ }
+ return ossl_membio2str(bio);
+}
+
+/*
+ * call-seq:
+ * pkey.private_to_der -> string
+ * pkey.private_to_der(cipher, password) -> string
+ *
+ * Serializes the private key to DER-encoded PKCS #8 format. If called without
+ * arguments, unencrypted PKCS #8 PrivateKeyInfo format is used. If called with
+ * a cipher name and a password, PKCS #8 EncryptedPrivateKeyInfo format with
+ * PBES2 encryption scheme is used.
+ */
+static VALUE
+ossl_pkey_private_to_der(int argc, VALUE *argv, VALUE self)
+{
+ return do_pkcs8_export(argc, argv, self, 1);
+}
+
+/*
+ * call-seq:
+ * pkey.private_to_pem -> string
+ * pkey.private_to_pem(cipher, password) -> string
+ *
+ * Serializes the private key to PEM-encoded PKCS #8 format. See #private_to_der
+ * for more details.
+ */
+static VALUE
+ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
+{
+ return do_pkcs8_export(argc, argv, self, 0);
+}
+
+static VALUE
+do_spki_export(VALUE self, int to_der)
+{
+ EVP_PKEY *pkey;
+ BIO *bio;
+
+ GetPKey(self, pkey);
+ bio = BIO_new(BIO_s_mem());
+ if (!bio)
+ ossl_raise(ePKeyError, "BIO_new");
+ if (to_der) {
+ if (!i2d_PUBKEY_bio(bio, pkey)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "i2d_PUBKEY_bio");
+ }
+ }
+ else {
+ if (!PEM_write_bio_PUBKEY(bio, pkey)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "PEM_write_bio_PUBKEY");
+ }
+ }
+ return ossl_membio2str(bio);
+}
+
+/*
+ * call-seq:
+ * pkey.public_to_der -> string
+ *
+ * Serializes the public key to DER-encoded X.509 SubjectPublicKeyInfo format.
+ */
+static VALUE
+ossl_pkey_public_to_der(VALUE self)
+{
+ return do_spki_export(self, 1);
+}
+
+/*
+ * call-seq:
+ * pkey.public_to_pem -> string
+ *
+ * Serializes the public key to PEM-encoded X.509 SubjectPublicKeyInfo format.
+ */
+static VALUE
+ossl_pkey_public_to_pem(VALUE self)
+{
+ return do_spki_export(self, 0);
+}
+
+/*
* call-seq:
* pkey.sign(digest, data) -> String
*
@@ -306,7 +466,7 @@ ossl_pkey_initialize(VALUE self)
*
* == Example
* data = 'Sign me!'
- * digest = OpenSSL::Digest::SHA256.new
+ * digest = OpenSSL::Digest.new('SHA256')
* pkey = OpenSSL::PKey::RSA.new(2048)
* signature = pkey.sign(digest, data)
*/
@@ -360,7 +520,7 @@ ossl_pkey_sign(VALUE self, VALUE digest, VALUE data)
*
* == Example
* data = 'Sign me!'
- * digest = OpenSSL::Digest::SHA256.new
+ * digest = OpenSSL::Digest.new('SHA256')
* pkey = OpenSSL::PKey::RSA.new(2048)
* signature = pkey.sign(digest, data)
* pub_key = pkey.public_key
@@ -491,6 +651,12 @@ Init_ossl_pkey(void)
rb_define_alloc_func(cPKey, ossl_pkey_alloc);
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
+ rb_define_method(cPKey, "oid", ossl_pkey_oid, 0);
+ rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0);
+ rb_define_method(cPKey, "private_to_der", ossl_pkey_private_to_der, -1);
+ rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
+ rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
+ rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0);
rb_define_method(cPKey, "sign", ossl_pkey_sign, 2);
rb_define_method(cPKey, "verify", ossl_pkey_verify, 3);
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 56cc9dd4f1..431c20e05c 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -513,7 +513,7 @@ ossl_dsa_to_public_key(VALUE self)
* === Example
* dsa = OpenSSL::PKey::DSA.new(2048)
* doc = "Sign me"
- * digest = OpenSSL::Digest::SHA1.digest(doc)
+ * digest = OpenSSL::Digest.digest('SHA1', doc)
* sig = dsa.syssign(digest)
*
*
@@ -558,7 +558,7 @@ ossl_dsa_sign(VALUE self, VALUE data)
* === Example
* dsa = OpenSSL::PKey::DSA.new(2048)
* doc = "Sign me"
- * digest = OpenSSL::Digest::SHA1.digest(doc)
+ * digest = OpenSSL::Digest.digest('SHA1', doc)
* sig = dsa.syssign(digest)
* puts dsa.sysverify(digest, sig) # => true
*
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index b47678dc1d..1d105abd35 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -1564,6 +1564,34 @@ ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form)
/*
* call-seq:
+ * point.add(point) => point
+ *
+ * Performs elliptic curve point addition.
+ */
+static VALUE ossl_ec_point_add(VALUE self, VALUE other)
+{
+ EC_POINT *point_self, *point_other, *point_result;
+ const EC_GROUP *group;
+ VALUE group_v = rb_attr_get(self, id_i_group);
+ VALUE result;
+
+ GetECPoint(self, point_self);
+ GetECPoint(other, point_other);
+ GetECGroup(group_v, group);
+
+ result = rb_obj_alloc(cEC_POINT);
+ ossl_ec_point_initialize(1, &group_v, result);
+ GetECPoint(result, point_result);
+
+ if (EC_POINT_add(group, point_result, point_self, point_other, ossl_bn_ctx) != 1) {
+ ossl_raise(eEC_POINT, "EC_POINT_add");
+ }
+
+ return result;
+}
+
+/*
+ * call-seq:
* point.mul(bn1 [, bn2]) => point
* point.mul(bns, points [, bn2]) => point
*
@@ -1786,6 +1814,7 @@ void Init_ossl_ec(void)
/* all the other methods */
rb_define_method(cEC_POINT, "to_octet_string", ossl_ec_point_to_octet_string, 1);
+ rb_define_method(cEC_POINT, "add", ossl_ec_point_add, 1);
rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
id_i_group = rb_intern("@group");
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 4800fb2710..761866c66a 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -26,10 +26,10 @@
static inline int
RSA_HAS_PRIVATE(RSA *rsa)
{
- const BIGNUM *p, *q;
+ const BIGNUM *e, *d;
- RSA_get0_factors(rsa, &p, &q);
- return p && q; /* d? why? */
+ RSA_get0_key(rsa, NULL, &e, &d);
+ return e && d;
}
static inline int
@@ -341,6 +341,7 @@ static VALUE
ossl_rsa_export(int argc, VALUE *argv, VALUE self)
{
RSA *rsa;
+ const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
BIO *out;
const EVP_CIPHER *ciph = NULL;
VALUE cipher, pass, str;
@@ -356,7 +357,10 @@ ossl_rsa_export(int argc, VALUE *argv, VALUE self)
if (!(out = BIO_new(BIO_s_mem()))) {
ossl_raise(eRSAError, NULL);
}
- if (RSA_HAS_PRIVATE(rsa)) {
+ RSA_get0_key(rsa, &n, &e, &d);
+ RSA_get0_factors(rsa, &p, &q);
+ RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
+ if (n && e && d && p && q && dmp1 && dmq1 && iqmp) {
if (!PEM_write_bio_RSAPrivateKey(out, rsa, ciph, NULL, 0,
ossl_pem_passwd_cb, (void *)pass)) {
BIO_free(out);
@@ -383,23 +387,27 @@ static VALUE
ossl_rsa_to_der(VALUE self)
{
RSA *rsa;
+ const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
int (*i2d_func)(const RSA *, unsigned char **);
- unsigned char *p;
+ unsigned char *ptr;
long len;
VALUE str;
GetRSA(self, rsa);
- if (RSA_HAS_PRIVATE(rsa))
+ RSA_get0_key(rsa, &n, &e, &d);
+ RSA_get0_factors(rsa, &p, &q);
+ RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
+ if (n && e && d && p && q && dmp1 && dmq1 && iqmp)
i2d_func = i2d_RSAPrivateKey;
else
i2d_func = (int (*)(const RSA *, unsigned char **))i2d_RSA_PUBKEY;
if((len = i2d_func(rsa, NULL)) <= 0)
ossl_raise(eRSAError, NULL);
str = rb_str_new(0, len);
- p = (unsigned char *)RSTRING_PTR(str);
- if(i2d_func(rsa, &p) < 0)
+ ptr = (unsigned char *)RSTRING_PTR(str);
+ if(i2d_func(rsa, &ptr) < 0)
ossl_raise(eRSAError, NULL);
- ossl_str_adjust(str, p);
+ ossl_str_adjust(str, ptr);
return str;
}
diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c
index 4a4f9dd5bf..659dc818b6 100644
--- a/ext/openssl/ossl_rand.c
+++ b/ext/openssl/ossl_rand.c
@@ -120,36 +120,6 @@ ossl_rand_bytes(VALUE self, VALUE len)
return str;
}
-#if defined(HAVE_RAND_PSEUDO_BYTES)
-/*
- * call-seq:
- * pseudo_bytes(length) -> string
- *
- * Generates a String with _length_ number of pseudo-random bytes.
- *
- * Pseudo-random byte sequences generated by ::pseudo_bytes will be unique if
- * they are of sufficient length, but are not necessarily unpredictable.
- *
- * === Example
- *
- * OpenSSL::Random.pseudo_bytes(12)
- * #=> "..."
- */
-static VALUE
-ossl_rand_pseudo_bytes(VALUE self, VALUE len)
-{
- VALUE str;
- int n = NUM2INT(len);
-
- str = rb_str_new(0, n);
- if (RAND_pseudo_bytes((unsigned char *)RSTRING_PTR(str), n) < 1) {
- ossl_raise(eRandomError, NULL);
- }
-
- return str;
-}
-#endif
-
#ifdef HAVE_RAND_EGD
/*
* call-seq:
@@ -219,8 +189,8 @@ Init_ossl_rand(void)
rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
-#if defined(HAVE_RAND_PSEUDO_BYTES)
- rb_define_module_function(mRandom, "pseudo_bytes", ossl_rand_pseudo_bytes, 1);
+#if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER)
+ rb_define_alias(rb_singleton_class(mRandom), "pseudo_bytes", "random_bytes");
#endif
#ifdef HAVE_RAND_EGD
rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index bfd80126c2..7654be12ee 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -830,6 +830,10 @@ ossl_sslctx_setup(VALUE self)
}
#endif /* OPENSSL_NO_EC */
+#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+ SSL_CTX_set_post_handshake_auth(ctx, 1);
+#endif
+
val = rb_attr_get(self, id_i_cert_store);
if (!NIL_P(val)) {
X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */
@@ -2352,7 +2356,57 @@ ossl_ssl_get_verify_result(VALUE self)
GetSSL(self, ssl);
- return INT2NUM(SSL_get_verify_result(ssl));
+ return LONG2NUM(SSL_get_verify_result(ssl));
+}
+
+/*
+ * call-seq:
+ * ssl.finished_message => "finished message"
+ *
+ * Returns the last *Finished* message sent
+ *
+ */
+static VALUE
+ossl_ssl_get_finished(VALUE self)
+{
+ SSL *ssl;
+ char sizer[1], *buf;
+ size_t len;
+
+ GetSSL(self, ssl);
+
+ len = SSL_get_finished(ssl, sizer, 0);
+ if (len == 0)
+ return Qnil;
+
+ buf = ALLOCA_N(char, len);
+ SSL_get_finished(ssl, buf, len);
+ return rb_str_new(buf, len);
+}
+
+/*
+ * call-seq:
+ * ssl.peer_finished_message => "peer finished message"
+ *
+ * Returns the last *Finished* message received
+ *
+ */
+static VALUE
+ossl_ssl_get_peer_finished(VALUE self)
+{
+ SSL *ssl;
+ char sizer[1], *buf;
+ size_t len;
+
+ GetSSL(self, ssl);
+
+ len = SSL_get_peer_finished(ssl, sizer, 0);
+ if (len == 0)
+ return Qnil;
+
+ buf = ALLOCA_N(char, len);
+ SSL_get_peer_finished(ssl, buf, len);
+ return rb_str_new(buf, len);
}
/*
@@ -2449,8 +2503,6 @@ ossl_ssl_tmp_key(VALUE self)
# endif /* defined(HAVE_SSL_GET_SERVER_TMP_KEY) */
#endif /* !defined(OPENSSL_NO_SOCK) */
-#undef rb_intern
-#define rb_intern(s) rb_intern_const(s)
void
Init_ossl_ssl(void)
{
@@ -2461,8 +2513,8 @@ Init_ossl_ssl(void)
rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
#endif
- id_call = rb_intern("call");
- ID_callback_state = rb_intern("callback_state");
+ id_call = rb_intern_const("call");
+ ID_callback_state = rb_intern_const("callback_state");
ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_vcb_idx", 0, 0, 0);
if (ossl_ssl_ex_vcb_idx < 0)
@@ -2529,7 +2581,7 @@ Init_ossl_ssl(void)
* The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
* It is recommended to use #add_certificate instead.
*/
- rb_attr(cSSLContext, rb_intern("cert"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("cert"), 1, 1, Qfalse);
/*
* Context private key
@@ -2537,29 +2589,29 @@ Init_ossl_ssl(void)
* The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
* It is recommended to use #add_certificate instead.
*/
- rb_attr(cSSLContext, rb_intern("key"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("key"), 1, 1, Qfalse);
/*
* A certificate or Array of certificates that will be sent to the client.
*/
- rb_attr(cSSLContext, rb_intern("client_ca"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("client_ca"), 1, 1, Qfalse);
/*
* The path to a file containing a PEM-format CA certificate
*/
- rb_attr(cSSLContext, rb_intern("ca_file"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("ca_file"), 1, 1, Qfalse);
/*
* The path to a directory containing CA certificates in PEM format.
*
* Files are looked up by subject's X509 name's hash value.
*/
- rb_attr(cSSLContext, rb_intern("ca_path"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("ca_path"), 1, 1, Qfalse);
/*
* Maximum session lifetime in seconds.
*/
- rb_attr(cSSLContext, rb_intern("timeout"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("timeout"), 1, 1, Qfalse);
/*
* Session verification mode.
@@ -2572,12 +2624,12 @@ Init_ossl_ssl(void)
*
* See SSL_CTX_set_verify(3) for details.
*/
- rb_attr(cSSLContext, rb_intern("verify_mode"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("verify_mode"), 1, 1, Qfalse);
/*
* Number of CA certificates to walk when verifying a certificate chain.
*/
- rb_attr(cSSLContext, rb_intern("verify_depth"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("verify_depth"), 1, 1, Qfalse);
/*
* A callback for additional certificate verification. The callback is
@@ -2591,7 +2643,7 @@ Init_ossl_ssl(void)
* If the callback returns +false+, the chain verification is immediately
* stopped and a bad_certificate alert is then sent.
*/
- rb_attr(cSSLContext, rb_intern("verify_callback"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("verify_callback"), 1, 1, Qfalse);
/*
* Whether to check the server certificate is valid for the hostname.
@@ -2599,12 +2651,12 @@ Init_ossl_ssl(void)
* In order to make this work, verify_mode must be set to VERIFY_PEER and
* the server hostname must be given by OpenSSL::SSL::SSLSocket#hostname=.
*/
- rb_attr(cSSLContext, rb_intern("verify_hostname"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("verify_hostname"), 1, 1, Qfalse);
/*
* An OpenSSL::X509::Store used for certificate verification.
*/
- rb_attr(cSSLContext, rb_intern("cert_store"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("cert_store"), 1, 1, Qfalse);
/*
* An Array of extra X509 certificates to be added to the certificate
@@ -2613,7 +2665,7 @@ Init_ossl_ssl(void)
* The _cert_, _key_, and _extra_chain_cert_ attributes are deprecated.
* It is recommended to use #add_certificate instead.
*/
- rb_attr(cSSLContext, rb_intern("extra_chain_cert"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("extra_chain_cert"), 1, 1, Qfalse);
/*
* A callback invoked when a client certificate is requested by a server
@@ -2623,7 +2675,7 @@ Init_ossl_ssl(void)
* containing an OpenSSL::X509::Certificate and an OpenSSL::PKey. If any
* other value is returned the handshake is suspended.
*/
- rb_attr(cSSLContext, rb_intern("client_cert_cb"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("client_cert_cb"), 1, 1, Qfalse);
#if !defined(OPENSSL_NO_EC) && defined(HAVE_SSL_CTX_SET_TMP_ECDH_CALLBACK)
/*
@@ -2636,7 +2688,7 @@ Init_ossl_ssl(void)
* The callback is deprecated. This does not work with recent versions of
* OpenSSL. Use OpenSSL::SSL::SSLContext#ecdh_curves= instead.
*/
- rb_attr(cSSLContext, rb_intern("tmp_ecdh_callback"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("tmp_ecdh_callback"), 1, 1, Qfalse);
#endif
/*
@@ -2644,7 +2696,7 @@ Init_ossl_ssl(void)
* sessions for multiple applications to be distinguished, for example, by
* name.
*/
- rb_attr(cSSLContext, rb_intern("session_id_context"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("session_id_context"), 1, 1, Qfalse);
/*
* A callback invoked on a server when a session is proposed by the client
@@ -2653,7 +2705,7 @@ Init_ossl_ssl(void)
* The callback is invoked with the SSLSocket and session id. The
* callback may return a Session from an external cache.
*/
- rb_attr(cSSLContext, rb_intern("session_get_cb"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("session_get_cb"), 1, 1, Qfalse);
/*
* A callback invoked when a new session was negotiated.
@@ -2661,7 +2713,7 @@ Init_ossl_ssl(void)
* The callback is invoked with an SSLSocket. If +false+ is returned the
* session will be removed from the internal cache.
*/
- rb_attr(cSSLContext, rb_intern("session_new_cb"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("session_new_cb"), 1, 1, Qfalse);
/*
* A callback invoked when a session is removed from the internal cache.
@@ -2672,18 +2724,18 @@ Init_ossl_ssl(void)
* multi-threaded application. The callback is called inside a global lock
* and it can randomly cause deadlock on Ruby thread switching.
*/
- rb_attr(cSSLContext, rb_intern("session_remove_cb"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("session_remove_cb"), 1, 1, Qfalse);
rb_define_const(mSSLExtConfig, "HAVE_TLSEXT_HOST_NAME", Qtrue);
/*
- * A callback invoked whenever a new handshake is initiated. May be used
- * to disable renegotiation entirely.
+ * A callback invoked whenever a new handshake is initiated on an
+ * established connection. May be used to disable renegotiation entirely.
*
* The callback is invoked with the active SSLSocket. The callback's
- * return value is irrelevant, normal return indicates "approval" of the
+ * return value is ignored. A normal return indicates "approval" of the
* renegotiation and will continue the process. To forbid renegotiation
- * and to cancel the process, an Error may be raised within the callback.
+ * and to cancel the process, raise an exception within the callback.
*
* === Disable client renegotiation
*
@@ -2691,13 +2743,11 @@ Init_ossl_ssl(void)
* renegotiation entirely. You may use a callback as follows to implement
* this feature:
*
- * num_handshakes = 0
* ctx.renegotiation_cb = lambda do |ssl|
- * num_handshakes += 1
- * raise RuntimeError.new("Client renegotiation disabled") if num_handshakes > 1
+ * raise RuntimeError, "Client renegotiation disabled"
* end
*/
- rb_attr(cSSLContext, rb_intern("renegotiation_cb"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("renegotiation_cb"), 1, 1, Qfalse);
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* An Enumerable of Strings. Each String represents a protocol to be
@@ -2710,7 +2760,7 @@ Init_ossl_ssl(void)
*
* ctx.npn_protocols = ["http/1.1", "spdy/2"]
*/
- rb_attr(cSSLContext, rb_intern("npn_protocols"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("npn_protocols"), 1, 1, Qfalse);
/*
* A callback invoked on the client side when the client needs to select
* a protocol from the list sent by the server. Supported in OpenSSL 1.0.1
@@ -2727,7 +2777,7 @@ Init_ossl_ssl(void)
* protocols.first
* end
*/
- rb_attr(cSSLContext, rb_intern("npn_select_cb"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("npn_select_cb"), 1, 1, Qfalse);
#endif
#ifdef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
@@ -2742,7 +2792,7 @@ Init_ossl_ssl(void)
*
* ctx.alpn_protocols = ["http/1.1", "spdy/2", "h2"]
*/
- rb_attr(cSSLContext, rb_intern("alpn_protocols"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("alpn_protocols"), 1, 1, Qfalse);
/*
* A callback invoked on the server side when the server needs to select
* a protocol from the list sent by the client. Supported in OpenSSL 1.0.2
@@ -2759,7 +2809,7 @@ Init_ossl_ssl(void)
* protocols.first
* end
*/
- rb_attr(cSSLContext, rb_intern("alpn_select_cb"), 1, 1, Qfalse);
+ rb_attr(cSSLContext, rb_intern_const("alpn_select_cb"), 1, 1, Qfalse);
#endif
rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
@@ -2872,6 +2922,8 @@ Init_ossl_ssl(void)
rb_define_method(cSSLSocket, "client_ca", ossl_ssl_get_client_ca_list, 0);
/* #hostname is defined in lib/openssl/ssl.rb */
rb_define_method(cSSLSocket, "hostname=", ossl_ssl_set_hostname, 1);
+ rb_define_method(cSSLSocket, "finished_message", ossl_ssl_get_finished, 0);
+ rb_define_method(cSSLSocket, "peer_finished_message", ossl_ssl_get_peer_finished, 0);
# ifdef HAVE_SSL_GET_SERVER_TMP_KEY
rb_define_method(cSSLSocket, "tmp_key", ossl_ssl_tmp_key, 0);
# endif
@@ -2985,17 +3037,17 @@ Init_ossl_ssl(void)
#endif
- sym_exception = ID2SYM(rb_intern("exception"));
- sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
- sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
+ sym_exception = ID2SYM(rb_intern_const("exception"));
+ sym_wait_readable = ID2SYM(rb_intern_const("wait_readable"));
+ sym_wait_writable = ID2SYM(rb_intern_const("wait_writable"));
- id_tmp_dh_callback = rb_intern("tmp_dh_callback");
- id_tmp_ecdh_callback = rb_intern("tmp_ecdh_callback");
- id_npn_protocols_encoded = rb_intern("npn_protocols_encoded");
+ id_tmp_dh_callback = rb_intern_const("tmp_dh_callback");
+ id_tmp_ecdh_callback = rb_intern_const("tmp_ecdh_callback");
+ id_npn_protocols_encoded = rb_intern_const("npn_protocols_encoded");
id_each = rb_intern_const("each");
#define DefIVarID(name) do \
- id_i_##name = rb_intern("@"#name); while (0)
+ id_i_##name = rb_intern_const("@"#name); while (0)
DefIVarID(cert_store);
DefIVarID(ca_file);
diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c
new file mode 100644
index 0000000000..cff9b7bfff
--- /dev/null
+++ b/ext/openssl/ossl_ts.c
@@ -0,0 +1,1524 @@
+/*
+ *
+ * Copyright (C) 2010 Martin Bosslet <Martin.Bosslet@googlemail.com>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+#include "ossl.h"
+
+#ifndef OPENSSL_NO_TS
+
+#define NewTSRequest(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ts_req_type, 0)
+#define SetTSRequest(obj, req) do { \
+ if (!(req)) { \
+ ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \
+ } \
+ RTYPEDDATA_DATA(obj) = (req); \
+} while (0)
+#define GetTSRequest(obj, req) do { \
+ TypedData_Get_Struct((obj), TS_REQ, &ossl_ts_req_type, (req)); \
+ if (!(req)) { \
+ ossl_raise(rb_eRuntimeError, "TS_REQ wasn't initialized."); \
+ } \
+} while (0)
+
+#define NewTSResponse(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ts_resp_type, 0)
+#define SetTSResponse(obj, resp) do { \
+ if (!(resp)) { \
+ ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \
+ } \
+ RTYPEDDATA_DATA(obj) = (resp); \
+} while (0)
+#define GetTSResponse(obj, resp) do { \
+ TypedData_Get_Struct((obj), TS_RESP, &ossl_ts_resp_type, (resp)); \
+ if (!(resp)) { \
+ ossl_raise(rb_eRuntimeError, "TS_RESP wasn't initialized."); \
+ } \
+} while (0)
+
+#define NewTSTokenInfo(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_ts_token_info_type, 0)
+#define SetTSTokenInfo(obj, info) do { \
+ if (!(info)) { \
+ ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \
+ } \
+ RTYPEDDATA_DATA(obj) = (info); \
+} while (0)
+#define GetTSTokenInfo(obj, info) do { \
+ TypedData_Get_Struct((obj), TS_TST_INFO, &ossl_ts_token_info_type, (info)); \
+ if (!(info)) { \
+ ossl_raise(rb_eRuntimeError, "TS_TST_INFO wasn't initialized."); \
+ } \
+} while (0)
+
+#define ossl_tsfac_get_default_policy_id(o) rb_attr_get((o),rb_intern("@default_policy_id"))
+#define ossl_tsfac_get_serial_number(o) rb_attr_get((o),rb_intern("@serial_number"))
+#define ossl_tsfac_get_gen_time(o) rb_attr_get((o),rb_intern("@gen_time"))
+#define ossl_tsfac_get_additional_certs(o) rb_attr_get((o),rb_intern("@additional_certs"))
+#define ossl_tsfac_get_allowed_digests(o) rb_attr_get((o),rb_intern("@allowed_digests"))
+
+static VALUE mTimestamp;
+static VALUE eTimestampError;
+static VALUE cTimestampRequest;
+static VALUE cTimestampResponse;
+static VALUE cTimestampTokenInfo;
+static VALUE cTimestampFactory;
+static VALUE sBAD_ALG, sBAD_REQUEST, sBAD_DATA_FORMAT, sTIME_NOT_AVAILABLE;
+static VALUE sUNACCEPTED_POLICY, sUNACCEPTED_EXTENSION, sADD_INFO_NOT_AVAILABLE;
+static VALUE sSYSTEM_FAILURE;
+
+static void
+ossl_ts_req_free(void *ptr)
+{
+ TS_REQ_free(ptr);
+}
+
+static const rb_data_type_t ossl_ts_req_type = {
+ "OpenSSL/Timestamp/Request",
+ {
+ 0, ossl_ts_req_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static void
+ossl_ts_resp_free(void *ptr)
+{
+ TS_RESP_free(ptr);
+}
+
+static const rb_data_type_t ossl_ts_resp_type = {
+ "OpenSSL/Timestamp/Response",
+ {
+ 0, ossl_ts_resp_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static void
+ossl_ts_token_info_free(void *ptr)
+{
+ TS_TST_INFO_free(ptr);
+}
+
+static const rb_data_type_t ossl_ts_token_info_type = {
+ "OpenSSL/Timestamp/TokenInfo",
+ {
+ 0, ossl_ts_token_info_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static VALUE
+asn1_to_der(void *template, int (*i2d)(void *template, unsigned char **pp))
+{
+ VALUE str;
+ int len;
+ unsigned char *p;
+
+ if((len = i2d(template, NULL)) <= 0)
+ ossl_raise(eTimestampError, "Error when encoding to DER");
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ if(i2d(template, &p) <= 0)
+ ossl_raise(eTimestampError, "Error when encoding to DER");
+ rb_str_set_len(str, p - (unsigned char*)RSTRING_PTR(str));
+
+ return str;
+}
+
+static ASN1_OBJECT*
+obj_to_asn1obj(VALUE obj)
+{
+ ASN1_OBJECT *a1obj;
+
+ StringValue(obj);
+ a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 0);
+ if(!a1obj) a1obj = OBJ_txt2obj(RSTRING_PTR(obj), 1);
+ if(!a1obj) ossl_raise(eASN1Error, "invalid OBJECT ID");
+
+ return a1obj;
+}
+
+static VALUE
+get_asn1obj(ASN1_OBJECT *obj)
+{
+ BIO *out;
+ VALUE ret;
+ int nid;
+ if ((nid = OBJ_obj2nid(obj)) != NID_undef)
+ ret = rb_str_new2(OBJ_nid2sn(nid));
+ else{
+ if (!(out = BIO_new(BIO_s_mem())))
+ ossl_raise(eX509AttrError, NULL);
+ i2a_ASN1_OBJECT(out, obj);
+ ret = ossl_membio2str(out);
+ }
+
+ return ret;
+}
+
+static VALUE
+ossl_ts_req_alloc(VALUE klass)
+{
+ TS_REQ *req;
+ VALUE obj;
+
+ obj = NewTSRequest(klass);
+ if (!(req = TS_REQ_new()))
+ ossl_raise(eTimestampError, NULL);
+ SetTSRequest(obj, req);
+
+ /* Defaults */
+ TS_REQ_set_version(req, 1);
+ TS_REQ_set_cert_req(req, 1);
+
+ return obj;
+}
+
+/*
+ * When creating a Request with the +File+ or +string+ parameter, the
+ * corresponding +File+ or +string+ must be DER-encoded.
+ *
+ * call-seq:
+ * OpenSSL::Timestamp::Request.new(file) -> request
+ * OpenSSL::Timestamp::Request.new(string) -> request
+ * OpenSSL::Timestamp::Request.new -> empty request
+ */
+static VALUE
+ossl_ts_req_initialize(int argc, VALUE *argv, VALUE self)
+{
+ TS_REQ *ts_req = DATA_PTR(self);
+ BIO *in;
+ VALUE arg;
+
+ if(rb_scan_args(argc, argv, "01", &arg) == 0) {
+ return self;
+ }
+
+ arg = ossl_to_der_if_possible(arg);
+ in = ossl_obj2bio(&arg);
+ ts_req = d2i_TS_REQ_bio(in, &ts_req);
+ BIO_free(in);
+ if (!ts_req) {
+ DATA_PTR(self) = NULL;
+ ossl_raise(eTimestampError, "Error when decoding the timestamp request");
+ }
+ DATA_PTR(self) = ts_req;
+
+ return self;
+}
+
+/*
+ * Returns the 'short name' of the object identifier that represents the
+ * algorithm that was used to create the message imprint digest.
+ *
+ * call-seq:
+ * request.algorithm -> string
+ */
+static VALUE
+ossl_ts_req_get_algorithm(VALUE self)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ X509_ALGOR *algor;
+
+ GetTSRequest(self, req);
+ mi = TS_REQ_get_msg_imprint(req);
+ algor = TS_MSG_IMPRINT_get_algo(mi);
+ return get_asn1obj(algor->algorithm);
+}
+
+/*
+ * Allows to set the object identifier or the 'short name' of the
+ * algorithm that was used to create the message imprint digest.
+ *
+ * ===Example:
+ * request.algorithm = "SHA1"
+ *
+ * call-seq:
+ * request.algorithm = "string" -> string
+ */
+static VALUE
+ossl_ts_req_set_algorithm(VALUE self, VALUE algo)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ ASN1_OBJECT *obj;
+ X509_ALGOR *algor;
+
+ GetTSRequest(self, req);
+ obj = obj_to_asn1obj(algo);
+ mi = TS_REQ_get_msg_imprint(req);
+ algor = TS_MSG_IMPRINT_get_algo(mi);
+ if (!X509_ALGOR_set0(algor, obj, V_ASN1_NULL, NULL)) {
+ ASN1_OBJECT_free(obj);
+ ossl_raise(eTimestampError, "X509_ALGOR_set0");
+ }
+
+ return algo;
+}
+
+/*
+ * Returns the message imprint (digest) of the data to be timestamped.
+ *
+ * call-seq:
+ * request.message_imprint -> string or nil
+ */
+static VALUE
+ossl_ts_req_get_msg_imprint(VALUE self)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ ASN1_OCTET_STRING *hashed_msg;
+ VALUE ret;
+
+ GetTSRequest(self, req);
+ mi = TS_REQ_get_msg_imprint(req);
+ hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
+
+ ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length);
+
+ return ret;
+}
+
+/*
+ * Set the message imprint digest.
+ *
+ * call-seq:
+ * request.message_imprint = "string" -> string
+ */
+static VALUE
+ossl_ts_req_set_msg_imprint(VALUE self, VALUE hash)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ StringValue(hash);
+
+ GetTSRequest(self, req);
+ mi = TS_REQ_get_msg_imprint(req);
+ if (!TS_MSG_IMPRINT_set_msg(mi, (unsigned char *)RSTRING_PTR(hash), RSTRING_LENINT(hash)))
+ ossl_raise(eTimestampError, "TS_MSG_IMPRINT_set_msg");
+
+ return hash;
+}
+
+/*
+ * Returns the version of this request. +1+ is the default value.
+ *
+ * call-seq:
+ * request.version -> Integer
+ */
+static VALUE
+ossl_ts_req_get_version(VALUE self)
+{
+ TS_REQ *req;
+
+ GetTSRequest(self, req);
+ return LONG2NUM(TS_REQ_get_version(req));
+}
+
+/*
+ * Sets the version number for this Request. This should be +1+ for compliant
+ * servers.
+ *
+ * call-seq:
+ * request.version = number -> Integer
+ */
+static VALUE
+ossl_ts_req_set_version(VALUE self, VALUE version)
+{
+ TS_REQ *req;
+ long ver;
+
+ if ((ver = NUM2LONG(version)) < 0)
+ ossl_raise(eTimestampError, "version must be >= 0!");
+ GetTSRequest(self, req);
+ if (!TS_REQ_set_version(req, ver))
+ ossl_raise(eTimestampError, "TS_REQ_set_version");
+
+ return version;
+}
+
+/*
+ * Returns the 'short name' of the object identifier that represents the
+ * timestamp policy under which the server shall create the timestamp.
+ *
+ * call-seq:
+ * request.policy_id -> string or nil
+ */
+static VALUE
+ossl_ts_req_get_policy_id(VALUE self)
+{
+ TS_REQ *req;
+
+ GetTSRequest(self, req);
+ if (!TS_REQ_get_policy_id(req))
+ return Qnil;
+ return get_asn1obj(TS_REQ_get_policy_id(req));
+}
+
+/*
+ * Allows to set the object identifier that represents the
+ * timestamp policy under which the server shall create the timestamp. This
+ * may be left +nil+, implying that the timestamp server will issue the
+ * timestamp using some default policy.
+ *
+ * ===Example:
+ * request.policy_id = "1.2.3.4.5"
+ *
+ * call-seq:
+ * request.policy_id = "string" -> string
+ */
+static VALUE
+ossl_ts_req_set_policy_id(VALUE self, VALUE oid)
+{
+ TS_REQ *req;
+ ASN1_OBJECT *obj;
+ int ok;
+
+ GetTSRequest(self, req);
+ obj = obj_to_asn1obj(oid);
+ ok = TS_REQ_set_policy_id(req, obj);
+ ASN1_OBJECT_free(obj);
+ if (!ok)
+ ossl_raise(eTimestampError, "TS_REQ_set_policy_id");
+
+ return oid;
+}
+
+/*
+ * Returns the nonce (number used once) that the server shall include in its
+ * response.
+ *
+ * call-seq:
+ * request.nonce -> BN or nil
+ */
+static VALUE
+ossl_ts_req_get_nonce(VALUE self)
+{
+ TS_REQ *req;
+ const ASN1_INTEGER * nonce;
+
+ GetTSRequest(self, req);
+ if (!(nonce = TS_REQ_get_nonce(req)))
+ return Qnil;
+ return asn1integer_to_num(nonce);
+}
+
+/*
+ * Sets the nonce (number used once) that the server shall include in its
+ * response. If the nonce is set, the server must return the same nonce value in
+ * a valid Response.
+ *
+ * call-seq:
+ * request.nonce = number -> BN
+ */
+static VALUE
+ossl_ts_req_set_nonce(VALUE self, VALUE num)
+{
+ TS_REQ *req;
+ ASN1_INTEGER *nonce;
+ int ok;
+
+ GetTSRequest(self, req);
+ nonce = num_to_asn1integer(num, NULL);
+ ok = TS_REQ_set_nonce(req, nonce);
+ ASN1_INTEGER_free(nonce);
+ if (!ok)
+ ossl_raise(eTimestampError, NULL);
+ return num;
+}
+
+/*
+ * Indicates whether the response shall contain the timestamp authority's
+ * certificate or not.
+ *
+ * call-seq:
+ * request.cert_requested? -> true or false
+ */
+static VALUE
+ossl_ts_req_get_cert_requested(VALUE self)
+{
+ TS_REQ *req;
+
+ GetTSRequest(self, req);
+ return TS_REQ_get_cert_req(req) ? Qtrue: Qfalse;
+}
+
+/*
+ * Specify whether the response shall contain the timestamp authority's
+ * certificate or not. The default value is +true+.
+ *
+ * call-seq:
+ * request.cert_requested = boolean -> true or false
+ */
+static VALUE
+ossl_ts_req_set_cert_requested(VALUE self, VALUE requested)
+{
+ TS_REQ *req;
+
+ GetTSRequest(self, req);
+ TS_REQ_set_cert_req(req, RTEST(requested));
+
+ return requested;
+}
+
+/*
+ * DER-encodes this Request.
+ *
+ * call-seq:
+ * request.to_der -> DER-encoded string
+ */
+static VALUE
+ossl_ts_req_to_der(VALUE self)
+{
+ TS_REQ *req;
+ TS_MSG_IMPRINT *mi;
+ X509_ALGOR *algo;
+ ASN1_OCTET_STRING *hashed_msg;
+
+ GetTSRequest(self, req);
+ mi = TS_REQ_get_msg_imprint(req);
+
+ algo = TS_MSG_IMPRINT_get_algo(mi);
+ if (OBJ_obj2nid(algo->algorithm) == NID_undef)
+ ossl_raise(eTimestampError, "Message imprint missing algorithm");
+
+ hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
+ if (!hashed_msg->length)
+ ossl_raise(eTimestampError, "Message imprint missing hashed message");
+
+ return asn1_to_der((void *)req, (int (*)(void *, unsigned char **))i2d_TS_REQ);
+}
+
+static VALUE
+ossl_ts_resp_alloc(VALUE klass)
+{
+ TS_RESP *resp;
+ VALUE obj;
+
+ obj = NewTSResponse(klass);
+ if (!(resp = TS_RESP_new()))
+ ossl_raise(eTimestampError, NULL);
+ SetTSResponse(obj, resp);
+
+ return obj;
+}
+
+/*
+ * Creates a Response from a +File+ or +string+ parameter, the
+ * corresponding +File+ or +string+ must be DER-encoded. Please note
+ * that Response is an immutable read-only class. If you'd like to create
+ * timestamps please refer to Factory instead.
+ *
+ * call-seq:
+ * OpenSSL::Timestamp::Response.new(file) -> response
+ * OpenSSL::Timestamp::Response.new(string) -> response
+ */
+static VALUE
+ossl_ts_resp_initialize(VALUE self, VALUE der)
+{
+ TS_RESP *ts_resp = DATA_PTR(self);
+ BIO *in;
+
+ der = ossl_to_der_if_possible(der);
+ in = ossl_obj2bio(&der);
+ ts_resp = d2i_TS_RESP_bio(in, &ts_resp);
+ BIO_free(in);
+ if (!ts_resp) {
+ DATA_PTR(self) = NULL;
+ ossl_raise(eTimestampError, "Error when decoding the timestamp response");
+ }
+ DATA_PTR(self) = ts_resp;
+
+ return self;
+}
+
+/*
+ * Returns one of GRANTED, GRANTED_WITH_MODS, REJECTION, WAITING,
+ * REVOCATION_WARNING or REVOCATION_NOTIFICATION. A timestamp token has
+ * been created only in case +status+ is equal to GRANTED or GRANTED_WITH_MODS.
+ *
+ * call-seq:
+ * response.status -> BN (never nil)
+ */
+static VALUE
+ossl_ts_resp_get_status(VALUE self)
+{
+ TS_RESP *resp;
+ TS_STATUS_INFO *si;
+ const ASN1_INTEGER *st;
+
+ GetTSResponse(self, resp);
+ si = TS_RESP_get_status_info(resp);
+ st = TS_STATUS_INFO_get0_status(si);
+
+ return asn1integer_to_num(st);
+}
+
+/*
+ * In cases no timestamp token has been created, this field contains further
+ * info about the reason why response creation failed. The method returns either
+ * nil (the request was successful and a timestamp token was created) or one of
+ * the following:
+ * * :BAD_ALG - Indicates that the timestamp server rejects the message
+ * imprint algorithm used in the Request
+ * * :BAD_REQUEST - Indicates that the timestamp server was not able to process
+ * the Request properly
+ * * :BAD_DATA_FORMAT - Indicates that the timestamp server was not able to
+ * parse certain data in the Request
+ * * :TIME_NOT_AVAILABLE - Indicates that the server could not access its time
+ * source
+ * * :UNACCEPTED_POLICY - Indicates that the requested policy identifier is not
+ * recognized or supported by the timestamp server
+ * * :UNACCEPTED_EXTENSIION - Indicates that an extension in the Request is
+ * not supported by the timestamp server
+ * * :ADD_INFO_NOT_AVAILABLE -Indicates that additional information requested
+ * is either not understood or currently not available
+ * * :SYSTEM_FAILURE - Timestamp creation failed due to an internal error that
+ * occurred on the timestamp server
+ *
+ * call-seq:
+ * response.failure_info -> nil or symbol
+ */
+static VALUE
+ossl_ts_resp_get_failure_info(VALUE self)
+{
+ TS_RESP *resp;
+ TS_STATUS_INFO *si;
+
+ /* The ASN1_BIT_STRING_get_bit changed from 1.0.0. to 1.1.0, making this
+ * const. */
+ #if defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO)
+ const ASN1_BIT_STRING *fi;
+ #else
+ ASN1_BIT_STRING *fi;
+ #endif
+
+ GetTSResponse(self, resp);
+ si = TS_RESP_get_status_info(resp);
+ fi = TS_STATUS_INFO_get0_failure_info(si);
+ if (!fi)
+ return Qnil;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_ALG))
+ return sBAD_ALG;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_REQUEST))
+ return sBAD_REQUEST;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_DATA_FORMAT))
+ return sBAD_DATA_FORMAT;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_TIME_NOT_AVAILABLE))
+ return sTIME_NOT_AVAILABLE;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_POLICY))
+ return sUNACCEPTED_POLICY;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_EXTENSION))
+ return sUNACCEPTED_EXTENSION;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_ADD_INFO_NOT_AVAILABLE))
+ return sADD_INFO_NOT_AVAILABLE;
+ if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_SYSTEM_FAILURE))
+ return sSYSTEM_FAILURE;
+
+ ossl_raise(eTimestampError, "Unrecognized failure info.");
+}
+
+/*
+ * In cases of failure this field may contain an array of strings further
+ * describing the origin of the failure.
+ *
+ * call-seq:
+ * response.status_text -> Array of strings or nil
+ */
+static VALUE
+ossl_ts_resp_get_status_text(VALUE self)
+{
+ TS_RESP *resp;
+ TS_STATUS_INFO *si;
+ const STACK_OF(ASN1_UTF8STRING) *text;
+ ASN1_UTF8STRING *current;
+ int i;
+ VALUE ret = rb_ary_new();
+
+ GetTSResponse(self, resp);
+ si = TS_RESP_get_status_info(resp);
+ if ((text = TS_STATUS_INFO_get0_text(si))) {
+ for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) {
+ current = sk_ASN1_UTF8STRING_value(text, i);
+ rb_ary_push(ret, asn1str_to_str(current));
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * If a timestamp token is present, this returns it in the form of a
+ * OpenSSL::PKCS7.
+ *
+ * call-seq:
+ * response.token -> nil or OpenSSL::PKCS7
+ */
+static VALUE
+ossl_ts_resp_get_token(VALUE self)
+{
+ TS_RESP *resp;
+ PKCS7 *p7, *copy;
+ VALUE obj;
+
+ GetTSResponse(self, resp);
+ if (!(p7 = TS_RESP_get_token(resp)))
+ return Qnil;
+
+ obj = NewPKCS7(cPKCS7);
+
+ if (!(copy = PKCS7_dup(p7)))
+ ossl_raise(eTimestampError, NULL);
+
+ SetPKCS7(obj, copy);
+
+ return obj;
+}
+
+/*
+ * Get the response's token info if present.
+ *
+ * call-seq:
+ * response.token_info -> nil or OpenSSL::Timestamp::TokenInfo
+ */
+static VALUE
+ossl_ts_resp_get_token_info(VALUE self)
+{
+ TS_RESP *resp;
+ TS_TST_INFO *info, *copy;
+ VALUE obj;
+
+ GetTSResponse(self, resp);
+ if (!(info = TS_RESP_get_tst_info(resp)))
+ return Qnil;
+
+ obj = NewTSTokenInfo(cTimestampTokenInfo);
+
+ if (!(copy = TS_TST_INFO_dup(info)))
+ ossl_raise(eTimestampError, NULL);
+
+ SetTSTokenInfo(obj, copy);
+
+ return obj;
+}
+
+/*
+ * If the Request specified to request the TSA certificate
+ * (Request#cert_requested = true), then this field contains the
+ * certificate of the timestamp authority.
+ *
+ * call-seq:
+ * response.tsa_certificate -> OpenSSL::X509::Certificate or nil
+ */
+static VALUE
+ossl_ts_resp_get_tsa_certificate(VALUE self)
+{
+ TS_RESP *resp;
+ PKCS7 *p7;
+ PKCS7_SIGNER_INFO *ts_info;
+ X509 *cert;
+
+ GetTSResponse(self, resp);
+ if (!(p7 = TS_RESP_get_token(resp)))
+ return Qnil;
+ ts_info = sk_PKCS7_SIGNER_INFO_value(p7->d.sign->signer_info, 0);
+ cert = PKCS7_cert_from_signer_info(p7, ts_info);
+ if (!cert)
+ return Qnil;
+ return ossl_x509_new(cert);
+}
+
+/*
+ * Returns the Response in DER-encoded form.
+ *
+ * call-seq:
+ * response.to_der -> string
+ */
+static VALUE
+ossl_ts_resp_to_der(VALUE self)
+{
+ TS_RESP *resp;
+
+ GetTSResponse(self, resp);
+ return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP);
+}
+
+/*
+ * Verifies a timestamp token by checking the signature, validating the
+ * certificate chain implied by tsa_certificate and by checking conformance to
+ * a given Request. Mandatory parameters are the Request associated to this
+ * Response, and an OpenSSL::X509::Store of trusted roots.
+ *
+ * Intermediate certificates can optionally be supplied for creating the
+ * certificate chain. These intermediate certificates must all be
+ * instances of OpenSSL::X509::Certificate.
+ *
+ * If validation fails, several kinds of exceptions can be raised:
+ * * TypeError if types don't fit
+ * * TimestampError if something is wrong with the timestamp token itself, if
+ * it is not conformant to the Request, or if validation of the timestamp
+ * certificate chain fails.
+ *
+ * call-seq:
+ * response.verify(Request, root_store) -> Response
+ * response.verify(Request, root_store, [intermediate_cert]) -> Response
+ */
+static VALUE
+ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self)
+{
+ VALUE ts_req, store, intermediates;
+ TS_RESP *resp;
+ TS_REQ *req;
+ X509_STORE *x509st;
+ TS_VERIFY_CTX *ctx;
+ STACK_OF(X509) *x509inter = NULL;
+ PKCS7* p7;
+ X509 *cert;
+ int status, i, ok;
+
+ rb_scan_args(argc, argv, "21", &ts_req, &store, &intermediates);
+
+ GetTSResponse(self, resp);
+ GetTSRequest(ts_req, req);
+ x509st = GetX509StorePtr(store);
+
+ if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(req, NULL))) {
+ ossl_raise(eTimestampError, "Error when creating the verification context.");
+ }
+
+ if (!NIL_P(intermediates)) {
+ x509inter = ossl_protect_x509_ary2sk(intermediates, &status);
+ if (status) {
+ TS_VERIFY_CTX_free(ctx);
+ rb_jump_tag(status);
+ }
+ } else if (!(x509inter = sk_X509_new_null())) {
+ TS_VERIFY_CTX_free(ctx);
+ ossl_raise(eTimestampError, "sk_X509_new_null");
+ }
+
+ if (!(p7 = TS_RESP_get_token(resp))) {
+ TS_VERIFY_CTX_free(ctx);
+ sk_X509_pop_free(x509inter, X509_free);
+ ossl_raise(eTimestampError, "TS_RESP_get_token");
+ }
+ for (i=0; i < sk_X509_num(p7->d.sign->cert); i++) {
+ cert = sk_X509_value(p7->d.sign->cert, i);
+ if (!sk_X509_push(x509inter, cert)) {
+ sk_X509_pop_free(x509inter, X509_free);
+ TS_VERIFY_CTX_free(ctx);
+ ossl_raise(eTimestampError, "sk_X509_push");
+ }
+ X509_up_ref(cert);
+ }
+
+ TS_VERIFY_CTS_set_certs(ctx, x509inter);
+ TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
+ TS_VERIFY_CTX_set_store(ctx, x509st);
+
+ ok = TS_RESP_verify_response(ctx, resp);
+
+ /* WORKAROUND:
+ * X509_STORE can count references, but X509_STORE_free() doesn't check
+ * this. To prevent our X509_STORE from being freed with our
+ * TS_VERIFY_CTX we set the store to NULL first.
+ * Fixed in OpenSSL 1.0.2; bff9ce4db38b (master), 5b4b9ce976fc (1.0.2)
+ */
+ TS_VERIFY_CTX_set_store(ctx, NULL);
+ TS_VERIFY_CTX_free(ctx);
+
+ if (!ok)
+ ossl_raise(eTimestampError, "TS_RESP_verify_response");
+
+ return self;
+}
+
+static VALUE
+ossl_ts_token_info_alloc(VALUE klass)
+{
+ TS_TST_INFO *info;
+ VALUE obj;
+
+ obj = NewTSTokenInfo(klass);
+ if (!(info = TS_TST_INFO_new()))
+ ossl_raise(eTimestampError, NULL);
+ SetTSTokenInfo(obj, info);
+
+ return obj;
+}
+
+/*
+ * Creates a TokenInfo from a +File+ or +string+ parameter, the
+ * corresponding +File+ or +string+ must be DER-encoded. Please note
+ * that TokenInfo is an immutable read-only class. If you'd like to create
+ * timestamps please refer to Factory instead.
+ *
+ * call-seq:
+ * OpenSSL::Timestamp::TokenInfo.new(file) -> token-info
+ * OpenSSL::Timestamp::TokenInfo.new(string) -> token-info
+ */
+static VALUE
+ossl_ts_token_info_initialize(VALUE self, VALUE der)
+{
+ TS_TST_INFO *info = DATA_PTR(self);
+ BIO *in;
+
+ der = ossl_to_der_if_possible(der);
+ in = ossl_obj2bio(&der);
+ info = d2i_TS_TST_INFO_bio(in, &info);
+ BIO_free(in);
+ if (!info) {
+ DATA_PTR(self) = NULL;
+ ossl_raise(eTimestampError, "Error when decoding the timestamp token info");
+ }
+ DATA_PTR(self) = info;
+
+ return self;
+}
+
+/*
+ * Returns the version number of the token info. With compliant servers,
+ * this value should be +1+ if present. If status is GRANTED or
+ * GRANTED_WITH_MODS.
+ *
+ * call-seq:
+ * token_info.version -> Integer or nil
+ */
+static VALUE
+ossl_ts_token_info_get_version(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return LONG2NUM(TS_TST_INFO_get_version(info));
+}
+
+/*
+ * Returns the timestamp policy object identifier of the policy this timestamp
+ * was created under. If status is GRANTED or GRANTED_WITH_MODS, this is never
+ * +nil+.
+ *
+ * ===Example:
+ * id = token_info.policy_id
+ * puts id -> "1.2.3.4.5"
+ *
+ * call-seq:
+ * token_info.policy_id -> string or nil
+ */
+static VALUE
+ossl_ts_token_info_get_policy_id(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return get_asn1obj(TS_TST_INFO_get_policy_id(info));
+}
+
+/*
+ * Returns the 'short name' of the object identifier representing the algorithm
+ * that was used to derive the message imprint digest. For valid timestamps,
+ * this is the same value that was already given in the Request. If status is
+ * GRANTED or GRANTED_WITH_MODS, this is never +nil+.
+ *
+ * ===Example:
+ * algo = token_info.algorithm
+ * puts algo -> "SHA1"
+ *
+ * call-seq:
+ * token_info.algorithm -> string or nil
+ */
+static VALUE
+ossl_ts_token_info_get_algorithm(VALUE self)
+{
+ TS_TST_INFO *info;
+ TS_MSG_IMPRINT *mi;
+ X509_ALGOR *algo;
+
+ GetTSTokenInfo(self, info);
+ mi = TS_TST_INFO_get_msg_imprint(info);
+ algo = TS_MSG_IMPRINT_get_algo(mi);
+ return get_asn1obj(algo->algorithm);
+}
+
+/*
+ * Returns the message imprint digest. For valid timestamps,
+ * this is the same value that was already given in the Request.
+ * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+.
+ *
+ * ===Example:
+ * mi = token_info.msg_imprint
+ * puts mi -> "DEADBEEF"
+ *
+ * call-seq:
+ * token_info.msg_imprint -> string.
+ */
+static VALUE
+ossl_ts_token_info_get_msg_imprint(VALUE self)
+{
+ TS_TST_INFO *info;
+ TS_MSG_IMPRINT *mi;
+ ASN1_OCTET_STRING *hashed_msg;
+ VALUE ret;
+
+ GetTSTokenInfo(self, info);
+ mi = TS_TST_INFO_get_msg_imprint(info);
+ hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
+ ret = rb_str_new((const char *)hashed_msg->data, hashed_msg->length);
+
+ return ret;
+}
+
+/*
+ * Returns serial number of the timestamp token. This value shall never be the
+ * same for two timestamp tokens issued by a dedicated timestamp authority.
+ * If status is GRANTED or GRANTED_WITH_MODS, this is never +nil+.
+ *
+ * call-seq:
+ * token_info.serial_number -> BN or nil
+ */
+static VALUE
+ossl_ts_token_info_get_serial_number(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return asn1integer_to_num(TS_TST_INFO_get_serial(info));
+}
+
+/*
+ * Returns time when this timestamp token was created. If status is GRANTED or
+ * GRANTED_WITH_MODS, this is never +nil+.
+ *
+ * call-seq:
+ * token_info.gen_time -> Time
+ */
+static VALUE
+ossl_ts_token_info_get_gen_time(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return asn1time_to_time(TS_TST_INFO_get_time(info));
+}
+
+/*
+ * If the ordering field is missing, or if the ordering field is present
+ * and set to false, then the genTime field only indicates the time at
+ * which the time-stamp token has been created by the TSA. In such a
+ * case, the ordering of time-stamp tokens issued by the same TSA or
+ * different TSAs is only possible when the difference between the
+ * genTime of the first time-stamp token and the genTime of the second
+ * time-stamp token is greater than the sum of the accuracies of the
+ * genTime for each time-stamp token.
+ *
+ * If the ordering field is present and set to true, every time-stamp
+ * token from the same TSA can always be ordered based on the genTime
+ * field, regardless of the genTime accuracy.
+ *
+ * call-seq:
+ * token_info.ordering -> true, falses or nil
+ */
+static VALUE
+ossl_ts_token_info_get_ordering(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return TS_TST_INFO_get_ordering(info) ? Qtrue : Qfalse;
+}
+
+/*
+ * If the timestamp token is valid then this field contains the same nonce that
+ * was passed to the timestamp server in the initial Request.
+ *
+ * call-seq:
+ * token_info.nonce -> BN or nil
+ */
+static VALUE
+ossl_ts_token_info_get_nonce(VALUE self)
+{
+ TS_TST_INFO *info;
+ const ASN1_INTEGER *nonce;
+
+ GetTSTokenInfo(self, info);
+ if (!(nonce = TS_TST_INFO_get_nonce(info)))
+ return Qnil;
+
+ return asn1integer_to_num(nonce);
+}
+
+/*
+ * Returns the TokenInfo in DER-encoded form.
+ *
+ * call-seq:
+ * token_info.to_der -> string
+ */
+static VALUE
+ossl_ts_token_info_to_der(VALUE self)
+{
+ TS_TST_INFO *info;
+
+ GetTSTokenInfo(self, info);
+ return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO);
+}
+
+static ASN1_INTEGER *
+ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data)
+{
+ ASN1_INTEGER **snptr = (ASN1_INTEGER **)data;
+ ASN1_INTEGER *sn = *snptr;
+ *snptr = NULL;
+ return sn;
+}
+
+static int
+#if !defined(LIBRESSL_VERSION_NUMBER)
+ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, long *sec, long *usec)
+#else
+ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
+#endif
+{
+ *sec = *((long *)data);
+ *usec = 0;
+ return 1;
+}
+
+/*
+ * Creates a Response with the help of an OpenSSL::PKey, an
+ * OpenSSL::X509::Certificate and a Request.
+ *
+ * Mandatory parameters for timestamp creation that need to be set in the
+ * Request:
+ *
+ * * Request#algorithm
+ * * Request#message_imprint
+ *
+ * Mandatory parameters that need to be set in the Factory:
+ * * Factory#serial_number
+ * * Factory#gen_time
+ * * Factory#allowed_digests
+ *
+ * In addition one of either Request#policy_id or Factory#default_policy_id
+ * must be set.
+ *
+ * Raises a TimestampError if creation fails, though successfully created error
+ * responses may be returned.
+ *
+ * call-seq:
+ * factory.create_timestamp(key, certificate, request) -> Response
+ */
+static VALUE
+ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
+{
+ VALUE serial_number, def_policy_id, gen_time, additional_certs, allowed_digests;
+ VALUE str;
+ STACK_OF(X509) *inter_certs;
+ VALUE tsresp, ret = Qnil;
+ EVP_PKEY *sign_key;
+ X509 *tsa_cert;
+ TS_REQ *req;
+ TS_RESP *response = NULL;
+ TS_RESP_CTX *ctx = NULL;
+ BIO *req_bio;
+ ASN1_INTEGER *asn1_serial = NULL;
+ ASN1_OBJECT *def_policy_id_obj = NULL;
+ long lgen_time;
+ const char * err_msg = NULL;
+ int status = 0;
+
+ tsresp = NewTSResponse(cTimestampResponse);
+ tsa_cert = GetX509CertPtr(certificate);
+ sign_key = GetPrivPKeyPtr(key);
+ GetTSRequest(request, req);
+
+ gen_time = ossl_tsfac_get_gen_time(self);
+ if (!rb_obj_is_instance_of(gen_time, rb_cTime)) {
+ err_msg = "@gen_time must be a Time.";
+ goto end;
+ }
+ lgen_time = NUM2LONG(rb_funcall(gen_time, rb_intern("to_i"), 0));
+
+ serial_number = ossl_tsfac_get_serial_number(self);
+ if (NIL_P(serial_number)) {
+ err_msg = "@serial_number must be set.";
+ goto end;
+ }
+ asn1_serial = num_to_asn1integer(serial_number, NULL);
+
+ def_policy_id = ossl_tsfac_get_default_policy_id(self);
+ if (NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
+ err_msg = "No policy id in the request and no default policy set";
+ goto end;
+ }
+ if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
+ def_policy_id_obj = (ASN1_OBJECT*)rb_protect((VALUE (*)(VALUE))obj_to_asn1obj, (VALUE)def_policy_id, &status);
+ if (status)
+ goto end;
+ }
+
+ if (!(ctx = TS_RESP_CTX_new())) {
+ err_msg = "Memory allocation failed.";
+ goto end;
+ }
+
+ TS_RESP_CTX_set_serial_cb(ctx, ossl_tsfac_serial_cb, &asn1_serial);
+ if (!TS_RESP_CTX_set_signer_cert(ctx, tsa_cert)) {
+ err_msg = "Certificate does not contain the timestamping extension";
+ goto end;
+ }
+
+ additional_certs = ossl_tsfac_get_additional_certs(self);
+ if (rb_obj_is_kind_of(additional_certs, rb_cArray)) {
+ inter_certs = ossl_protect_x509_ary2sk(additional_certs, &status);
+ if (status)
+ goto end;
+
+ /* this dups the sk_X509 and ups each cert's ref count */
+ TS_RESP_CTX_set_certs(ctx, inter_certs);
+ sk_X509_pop_free(inter_certs, X509_free);
+ }
+
+ TS_RESP_CTX_set_signer_key(ctx, sign_key);
+ if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req))
+ TS_RESP_CTX_set_def_policy(ctx, def_policy_id_obj);
+ if (TS_REQ_get_policy_id(req))
+ TS_RESP_CTX_set_def_policy(ctx, TS_REQ_get_policy_id(req));
+ TS_RESP_CTX_set_time_cb(ctx, ossl_tsfac_time_cb, &lgen_time);
+
+ allowed_digests = ossl_tsfac_get_allowed_digests(self);
+ if (rb_obj_is_kind_of(allowed_digests, rb_cArray)) {
+ int i;
+ VALUE rbmd;
+ const EVP_MD *md;
+
+ for (i = 0; i < RARRAY_LEN(allowed_digests); i++) {
+ rbmd = rb_ary_entry(allowed_digests, i);
+ md = (const EVP_MD *)rb_protect((VALUE (*)(VALUE))ossl_evp_get_digestbyname, rbmd, &status);
+ if (status)
+ goto end;
+ TS_RESP_CTX_add_md(ctx, md);
+ }
+ }
+
+ str = rb_protect(ossl_to_der, request, &status);
+ if (status)
+ goto end;
+
+ req_bio = (BIO*)rb_protect((VALUE (*)(VALUE))ossl_obj2bio, (VALUE)&str, &status);
+ if (status)
+ goto end;
+
+ response = TS_RESP_create_response(ctx, req_bio);
+ BIO_free(req_bio);
+
+ if (!response) {
+ err_msg = "Error during response generation";
+ goto end;
+ }
+
+ /* bad responses aren't exceptional, but openssl still sets error
+ * information. */
+ ossl_clear_error();
+
+ SetTSResponse(tsresp, response);
+ ret = tsresp;
+
+end:
+ ASN1_INTEGER_free(asn1_serial);
+ ASN1_OBJECT_free(def_policy_id_obj);
+ TS_RESP_CTX_free(ctx);
+ if (err_msg)
+ ossl_raise(eTimestampError, err_msg);
+ if (status)
+ rb_jump_tag(status);
+ return ret;
+}
+
+/*
+ * INIT
+ */
+void
+Init_ossl_ts(void)
+{
+ #if 0
+ mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
+ #endif
+
+ /*
+ * Possible return value for +Response#failure_info+. Indicates that the
+ * timestamp server rejects the message imprint algorithm used in the
+ * +Request+
+ */
+ sBAD_ALG = ID2SYM(rb_intern_const("BAD_ALG"));
+
+ /*
+ * Possible return value for +Response#failure_info+. Indicates that the
+ * timestamp server was not able to process the +Request+ properly.
+ */
+ sBAD_REQUEST = ID2SYM(rb_intern_const("BAD_REQUEST"));
+ /*
+ * Possible return value for +Response#failure_info+. Indicates that the
+ * timestamp server was not able to parse certain data in the +Request+.
+ */
+ sBAD_DATA_FORMAT = ID2SYM(rb_intern_const("BAD_DATA_FORMAT"));
+
+ sTIME_NOT_AVAILABLE = ID2SYM(rb_intern_const("TIME_NOT_AVAILABLE"));
+ sUNACCEPTED_POLICY = ID2SYM(rb_intern_const("UNACCEPTED_POLICY"));
+ sUNACCEPTED_EXTENSION = ID2SYM(rb_intern_const("UNACCEPTED_EXTENSION"));
+ sADD_INFO_NOT_AVAILABLE = ID2SYM(rb_intern_const("ADD_INFO_NOT_AVAILABLE"));
+ sSYSTEM_FAILURE = ID2SYM(rb_intern_const("SYSTEM_FAILURE"));
+
+ /* Document-class: OpenSSL::Timestamp
+ * Provides classes and methods to request, create and validate
+ * {RFC3161-compliant}[http://www.ietf.org/rfc/rfc3161.txt] timestamps.
+ * Request may be used to either create requests from scratch or to parse
+ * existing requests that again can be used to request timestamps from a
+ * timestamp server, e.g. via the net/http. The resulting timestamp
+ * response may be parsed using Response.
+ *
+ * Please note that Response is read-only and immutable. To create a
+ * Response, an instance of Factory as well as a valid Request are needed.
+ *
+ * ===Create a Response:
+ * #Assumes ts.p12 is a PKCS#12-compatible file with a private key
+ * #and a certificate that has an extended key usage of 'timeStamping'
+ * p12 = OpenSSL::PKCS12.new(File.open('ts.p12', 'rb'), 'pwd')
+ * md = OpenSSL::Digest.new('SHA1')
+ * hash = md.digest(data) #some binary data to be timestamped
+ * req = OpenSSL::Timestamp::Request.new
+ * req.algorithm = 'SHA1'
+ * req.message_imprint = hash
+ * req.policy_id = "1.2.3.4.5"
+ * req.nonce = 42
+ * fac = OpenSSL::Timestamp::Factory.new
+ * fac.gen_time = Time.now
+ * fac.serial_number = 1
+ * timestamp = fac.create_timestamp(p12.key, p12.certificate, req)
+ *
+ * ===Verify a timestamp response:
+ * #Assume we have a timestamp token in a file called ts.der
+ * ts = OpenSSL::Timestamp::Response.new(File.open('ts.der', 'rb')
+ * #Assume we have the Request for this token in a file called req.der
+ * req = OpenSSL::Timestamp::Request.new(File.open('req.der', 'rb')
+ * # Assume the associated root CA certificate is contained in a
+ * # DER-encoded file named root.cer
+ * root = OpenSSL::X509::Certificate.new(File.open('root.cer', 'rb')
+ * # get the necessary intermediate certificates, available in
+ * # DER-encoded form in inter1.cer and inter2.cer
+ * inter1 = OpenSSL::X509::Certificate.new(File.open('inter1.cer', 'rb')
+ * inter2 = OpenSSL::X509::Certificate.new(File.open('inter2.cer', 'rb')
+ * ts.verify(req, root, inter1, inter2) -> ts or raises an exception if validation fails
+ *
+ */
+ mTimestamp = rb_define_module_under(mOSSL, "Timestamp");
+
+ /* Document-class: OpenSSL::Timestamp::TimestampError
+ * Generic exception class of the Timestamp module.
+ */
+ eTimestampError = rb_define_class_under(mTimestamp, "TimestampError", eOSSLError);
+
+ /* Document-class: OpenSSL::Timestamp::Response
+ * Immutable and read-only representation of a timestamp response returned
+ * from a timestamp server after receiving an associated Request. Allows
+ * access to specific information about the response but also allows to
+ * verify the Response.
+ */
+ cTimestampResponse = rb_define_class_under(mTimestamp, "Response", rb_cObject);
+ rb_define_alloc_func(cTimestampResponse, ossl_ts_resp_alloc);
+ rb_define_method(cTimestampResponse, "initialize", ossl_ts_resp_initialize, 1);
+ rb_define_method(cTimestampResponse, "status", ossl_ts_resp_get_status, 0);
+ rb_define_method(cTimestampResponse, "failure_info", ossl_ts_resp_get_failure_info, 0);
+ rb_define_method(cTimestampResponse, "status_text", ossl_ts_resp_get_status_text, 0);
+ rb_define_method(cTimestampResponse, "token", ossl_ts_resp_get_token, 0);
+ rb_define_method(cTimestampResponse, "token_info", ossl_ts_resp_get_token_info, 0);
+ rb_define_method(cTimestampResponse, "tsa_certificate", ossl_ts_resp_get_tsa_certificate, 0);
+ rb_define_method(cTimestampResponse, "to_der", ossl_ts_resp_to_der, 0);
+ rb_define_method(cTimestampResponse, "verify", ossl_ts_resp_verify, -1);
+
+ /* Document-class: OpenSSL::Timestamp::TokenInfo
+ * Immutable and read-only representation of a timestamp token info from a
+ * Response.
+ */
+ cTimestampTokenInfo = rb_define_class_under(mTimestamp, "TokenInfo", rb_cObject);
+ rb_define_alloc_func(cTimestampTokenInfo, ossl_ts_token_info_alloc);
+ rb_define_method(cTimestampTokenInfo, "initialize", ossl_ts_token_info_initialize, 1);
+ rb_define_method(cTimestampTokenInfo, "version", ossl_ts_token_info_get_version, 0);
+ rb_define_method(cTimestampTokenInfo, "policy_id", ossl_ts_token_info_get_policy_id, 0);
+ rb_define_method(cTimestampTokenInfo, "algorithm", ossl_ts_token_info_get_algorithm, 0);
+ rb_define_method(cTimestampTokenInfo, "message_imprint", ossl_ts_token_info_get_msg_imprint, 0);
+ rb_define_method(cTimestampTokenInfo, "serial_number", ossl_ts_token_info_get_serial_number, 0);
+ rb_define_method(cTimestampTokenInfo, "gen_time", ossl_ts_token_info_get_gen_time, 0);
+ rb_define_method(cTimestampTokenInfo, "ordering", ossl_ts_token_info_get_ordering, 0);
+ rb_define_method(cTimestampTokenInfo, "nonce", ossl_ts_token_info_get_nonce, 0);
+ rb_define_method(cTimestampTokenInfo, "to_der", ossl_ts_token_info_to_der, 0);
+
+ /* Document-class: OpenSSL::Timestamp::Request
+ * Allows to create timestamp requests or parse existing ones. A Request is
+ * also needed for creating timestamps from scratch with Factory. When
+ * created from scratch, some default values are set:
+ * * version is set to +1+
+ * * cert_requested is set to +true+
+ * * algorithm, message_imprint, policy_id, and nonce are set to +false+
+ */
+ cTimestampRequest = rb_define_class_under(mTimestamp, "Request", rb_cObject);
+ rb_define_alloc_func(cTimestampRequest, ossl_ts_req_alloc);
+ rb_define_method(cTimestampRequest, "initialize", ossl_ts_req_initialize, -1);
+ rb_define_method(cTimestampRequest, "version=", ossl_ts_req_set_version, 1);
+ rb_define_method(cTimestampRequest, "version", ossl_ts_req_get_version, 0);
+ rb_define_method(cTimestampRequest, "algorithm=", ossl_ts_req_set_algorithm, 1);
+ rb_define_method(cTimestampRequest, "algorithm", ossl_ts_req_get_algorithm, 0);
+ rb_define_method(cTimestampRequest, "message_imprint=", ossl_ts_req_set_msg_imprint, 1);
+ rb_define_method(cTimestampRequest, "message_imprint", ossl_ts_req_get_msg_imprint, 0);
+ rb_define_method(cTimestampRequest, "policy_id=", ossl_ts_req_set_policy_id, 1);
+ rb_define_method(cTimestampRequest, "policy_id", ossl_ts_req_get_policy_id, 0);
+ rb_define_method(cTimestampRequest, "nonce=", ossl_ts_req_set_nonce, 1);
+ rb_define_method(cTimestampRequest, "nonce", ossl_ts_req_get_nonce, 0);
+ rb_define_method(cTimestampRequest, "cert_requested=", ossl_ts_req_set_cert_requested, 1);
+ rb_define_method(cTimestampRequest, "cert_requested?", ossl_ts_req_get_cert_requested, 0);
+ rb_define_method(cTimestampRequest, "to_der", ossl_ts_req_to_der, 0);
+
+ /*
+ * Indicates a successful response. Equal to +0+.
+ */
+ rb_define_const(cTimestampResponse, "GRANTED", INT2NUM(TS_STATUS_GRANTED));
+ /*
+ * Indicates a successful response that probably contains modifications
+ * from the initial request. Equal to +1+.
+ */
+ rb_define_const(cTimestampResponse, "GRANTED_WITH_MODS", INT2NUM(TS_STATUS_GRANTED_WITH_MODS));
+ /*
+ * Indicates a failure. No timestamp token was created. Equal to +2+.
+ */
+ rb_define_const(cTimestampResponse, "REJECTION", INT2NUM(TS_STATUS_REJECTION));
+ /*
+ * Indicates a failure. No timestamp token was created. Equal to +3+.
+ */
+ rb_define_const(cTimestampResponse, "WAITING", INT2NUM(TS_STATUS_WAITING));
+ /*
+ * Indicates a failure. No timestamp token was created. Revocation of a
+ * certificate is imminent. Equal to +4+.
+ */
+ rb_define_const(cTimestampResponse, "REVOCATION_WARNING", INT2NUM(TS_STATUS_REVOCATION_WARNING));
+ /*
+ * Indicates a failure. No timestamp token was created. A certificate
+ * has been revoked. Equal to +5+.
+ */
+ rb_define_const(cTimestampResponse, "REVOCATION_NOTIFICATION", INT2NUM(TS_STATUS_REVOCATION_NOTIFICATION));
+
+ /* Document-class: OpenSSL::Timestamp::Factory
+ *
+ * Used to generate a Response from scratch.
+ *
+ * Please bear in mind that the implementation will always apply and prefer
+ * the policy object identifier given in the request over the default policy
+ * id specified in the Factory. As a consequence, +default_policy_id+ will
+ * only be applied if no Request#policy_id was given. But this also means
+ * that one needs to check the policy identifier in the request manually
+ * before creating the Response, e.g. to check whether it complies to a
+ * specific set of acceptable policies.
+ *
+ * There exists also the possibility to add certificates (instances of
+ * OpenSSL::X509::Certificate) besides the timestamping certificate
+ * that will be included in the resulting timestamp token if
+ * Request#cert_requested? is +true+. Ideally, one would also include any
+ * intermediate certificates (the root certificate can be left out - in
+ * order to trust it any verifying party will have to be in its possession
+ * anyway). This simplifies validation of the timestamp since these
+ * intermediate certificates are "already there" and need not be passed as
+ * external parameters to Response#verify anymore, thus minimizing external
+ * resources needed for verification.
+ *
+ * ===Example: Inclusion of (untrusted) intermediate certificates
+ *
+ * Assume we received a timestamp request that has set Request#policy_id to
+ * +nil+ and Request#cert_requested? to true. The raw request bytes are
+ * stored in a variable called +req_raw+. We'd still like to integrate
+ * the necessary intermediate certificates (in +inter1.cer+ and
+ * +inter2.cer+) to simplify validation of the resulting Response. +ts.p12+
+ * is a PKCS#12-compatible file including the private key and the
+ * timestamping certificate.
+ *
+ * req = OpenSSL::Timestamp::Request.new(raw_bytes)
+ * p12 = OpenSSL::PKCS12.new(File.open('ts.p12', 'rb'), 'pwd')
+ * inter1 = OpenSSL::X509::Certificate.new(File.open('inter1.cer', 'rb')
+ * inter2 = OpenSSL::X509::Certificate.new(File.open('inter2.cer', 'rb')
+ * fac = OpenSSL::Timestamp::Factory.new
+ * fac.gen_time = Time.now
+ * fac.serial_number = 1
+ * fac.allowed_digests = ["sha256", "sha384", "sha512"]
+ * #needed because the Request contained no policy identifier
+ * fac.default_policy_id = '1.2.3.4.5'
+ * fac.additional_certificates = [ inter1, inter2 ]
+ * timestamp = fac.create_timestamp(p12.key, p12.certificate, req)
+ *
+ * ==Attributes
+ *
+ * ===default_policy_id
+ *
+ * Request#policy_id will always be preferred over this if present in the
+ * Request, only if Request#policy_id is nil default_policy will be used.
+ * If none of both is present, a TimestampError will be raised when trying
+ * to create a Response.
+ *
+ * call-seq:
+ * factory.default_policy_id = "string" -> string
+ * factory.default_policy_id -> string or nil
+ *
+ * ===serial_number
+ *
+ * Sets or retrieves the serial number to be used for timestamp creation.
+ * Must be present for timestamp creation.
+ *
+ * call-seq:
+ * factory.serial_number = number -> number
+ * factory.serial_number -> number or nil
+ *
+ * ===gen_time
+ *
+ * Sets or retrieves the Time value to be used in the Response. Must be
+ * present for timestamp creation.
+ *
+ * call-seq:
+ * factory.gen_time = Time -> Time
+ * factory.gen_time -> Time or nil
+ *
+ * ===additional_certs
+ *
+ * Sets or retrieves additional certificates apart from the timestamp
+ * certificate (e.g. intermediate certificates) to be added to the Response.
+ * Must be an Array of OpenSSL::X509::Certificate.
+ *
+ * call-seq:
+ * factory.additional_certs = [cert1, cert2] -> [ cert1, cert2 ]
+ * factory.additional_certs -> array or nil
+ *
+ * ===allowed_digests
+ *
+ * Sets or retrieves the digest algorithms that the factory is allowed
+ * create timestamps for. Known vulnerable or weak algorithms should not be
+ * allowed where possible.
+ * Must be an Array of String or OpenSSL::Digest subclass instances.
+ *
+ * call-seq:
+ * factory.allowed_digests = ["sha1", OpenSSL::Digest.new('SHA256').new] -> [ "sha1", OpenSSL::Digest) ]
+ * factory.allowed_digests -> array or nil
+ *
+ */
+ cTimestampFactory = rb_define_class_under(mTimestamp, "Factory", rb_cObject);
+ rb_attr(cTimestampFactory, rb_intern_const("allowed_digests"), 1, 1, 0);
+ rb_attr(cTimestampFactory, rb_intern_const("default_policy_id"), 1, 1, 0);
+ rb_attr(cTimestampFactory, rb_intern_const("serial_number"), 1, 1, 0);
+ rb_attr(cTimestampFactory, rb_intern_const("gen_time"), 1, 1, 0);
+ rb_attr(cTimestampFactory, rb_intern_const("additional_certs"), 1, 1, 0);
+ rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3);
+}
+
+#endif
diff --git a/ext/openssl/ossl_ts.h b/ext/openssl/ossl_ts.h
new file mode 100644
index 0000000000..25fb0e1d64
--- /dev/null
+++ b/ext/openssl/ossl_ts.h
@@ -0,0 +1,16 @@
+/*
+ *
+ * Copyright (C) 2010 Martin Bosslet <Martin.Bosslet@googlemail.com>
+ * All rights reserved.
+ */
+/*
+ * This program is licenced under the same licence as Ruby.
+ * (See the file 'LICENCE'.)
+ */
+
+#if !defined(_OSSL_TS_H_)
+#define _OSSL_TS_H_
+
+void Init_ossl_ts(void);
+
+#endif
diff --git a/ext/openssl/ossl_version.h b/ext/openssl/ossl_version.h
deleted file mode 100644
index 70182a71e7..0000000000
--- a/ext/openssl/ossl_version.h
+++ /dev/null
@@ -1,15 +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'.)
- */
-#if !defined(_OSSL_VERSION_H_)
-#define _OSSL_VERSION_H_
-
-#define OSSL_VERSION "2.1.4"
-
-#endif /* _OSSL_VERSION_H_ */
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index 40542c4a78..e3766b1b16 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -788,7 +788,7 @@ Init_ossl_x509cert(void)
* root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
* root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
* root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
- * root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)
+ * root_ca.sign(root_key, OpenSSL::Digest.new('SHA256'))
*
* The next step is to create the end-entity certificate using the root CA
* certificate.
@@ -807,7 +807,7 @@ Init_ossl_x509cert(void)
* ef.issuer_certificate = root_ca
* cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
* cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
- * cert.sign(root_key, OpenSSL::Digest::SHA256.new)
+ * cert.sign(root_key, OpenSSL::Digest.new('SHA256'))
*
*/
cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c
index 30ec09d7a3..5eb9bd759f 100644
--- a/ext/openssl/ossl_x509ext.c
+++ b/ext/openssl/ossl_x509ext.c
@@ -403,6 +403,19 @@ ossl_x509ext_get_value(VALUE obj)
}
static VALUE
+ossl_x509ext_get_value_der(VALUE obj)
+{
+ X509_EXTENSION *ext;
+ ASN1_OCTET_STRING *value;
+
+ GetX509Ext(obj, ext);
+ if ((value = X509_EXTENSION_get_data(ext)) == NULL)
+ ossl_raise(eX509ExtError, NULL);
+
+ return rb_str_new((const char *)value->data, value->length);
+}
+
+static VALUE
ossl_x509ext_get_critical(VALUE obj)
{
X509_EXTENSION *ext;
@@ -472,6 +485,7 @@ Init_ossl_x509ext(void)
rb_define_method(cX509Ext, "critical=", ossl_x509ext_set_critical, 1);
rb_define_method(cX509Ext, "oid", ossl_x509ext_get_oid, 0);
rb_define_method(cX509Ext, "value", ossl_x509ext_get_value, 0);
+ rb_define_method(cX509Ext, "value_der", ossl_x509ext_get_value_der, 0);
rb_define_method(cX509Ext, "critical?", ossl_x509ext_get_critical, 0);
rb_define_method(cX509Ext, "to_der", ossl_x509ext_to_der, 0);
}
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index 1ea8400dbb..1522c3d897 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -387,17 +387,21 @@ ossl_x509name_cmp0(VALUE self, VALUE other)
/*
* call-seq:
- * name.cmp(other) -> -1 | 0 | 1
- * name <=> other -> -1 | 0 | 1
+ * name.cmp(other) -> -1 | 0 | 1 | nil
+ * name <=> other -> -1 | 0 | 1 | nil
*
* Compares this Name with _other_ and returns +0+ if they are the same and +-1+
* or ++1+ if they are greater or less than each other respectively.
+ * Returns +nil+ if they are not comparable (i.e. different types).
*/
static VALUE
ossl_x509name_cmp(VALUE self, VALUE other)
{
int result;
+ if (!rb_obj_is_kind_of(other, cX509Name))
+ return Qnil;
+
result = ossl_x509name_cmp0(self, other);
if (result < 0) return INT2FIX(-1);
if (result > 0) return INT2FIX(1);
@@ -494,7 +498,7 @@ ossl_x509name_to_der(VALUE self)
* You can create a Name by parsing a distinguished name String or by
* supplying the distinguished name as an Array.
*
- * name = OpenSSL::X509::Name.parse 'CN=nobody/DC=example'
+ * name = OpenSSL::X509::Name.parse '/CN=nobody/DC=example'
*
* name = OpenSSL::X509::Name.new [['CN', 'nobody'], ['DC', 'example']]
*/
diff --git a/ext/pathname/depend b/ext/pathname/depend
index 1e13dd5f37..9df2ba8e18 100644
--- a/ext/pathname/depend
+++ b/ext/pathname/depend
@@ -2,8 +2,157 @@
pathname.o: $(RUBY_EXTCONF_H)
pathname.o: $(arch_hdrdir)/ruby/config.h
pathname.o: $(hdrdir)/ruby.h
+pathname.o: $(hdrdir)/ruby/internal/anyargs.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+pathname.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+pathname.o: $(hdrdir)/ruby/internal/assume.h
+pathname.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+pathname.o: $(hdrdir)/ruby/internal/attr/artificial.h
+pathname.o: $(hdrdir)/ruby/internal/attr/cold.h
+pathname.o: $(hdrdir)/ruby/internal/attr/const.h
+pathname.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+pathname.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+pathname.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+pathname.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+pathname.o: $(hdrdir)/ruby/internal/attr/error.h
+pathname.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+pathname.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+pathname.o: $(hdrdir)/ruby/internal/attr/format.h
+pathname.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+pathname.o: $(hdrdir)/ruby/internal/attr/noalias.h
+pathname.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+pathname.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+pathname.o: $(hdrdir)/ruby/internal/attr/noinline.h
+pathname.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+pathname.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+pathname.o: $(hdrdir)/ruby/internal/attr/pure.h
+pathname.o: $(hdrdir)/ruby/internal/attr/restrict.h
+pathname.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+pathname.o: $(hdrdir)/ruby/internal/attr/warning.h
+pathname.o: $(hdrdir)/ruby/internal/attr/weakref.h
+pathname.o: $(hdrdir)/ruby/internal/cast.h
+pathname.o: $(hdrdir)/ruby/internal/compiler_is.h
+pathname.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+pathname.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+pathname.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+pathname.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+pathname.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+pathname.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+pathname.o: $(hdrdir)/ruby/internal/compiler_since.h
+pathname.o: $(hdrdir)/ruby/internal/config.h
+pathname.o: $(hdrdir)/ruby/internal/constant_p.h
+pathname.o: $(hdrdir)/ruby/internal/core.h
+pathname.o: $(hdrdir)/ruby/internal/core/rarray.h
+pathname.o: $(hdrdir)/ruby/internal/core/rbasic.h
+pathname.o: $(hdrdir)/ruby/internal/core/rbignum.h
+pathname.o: $(hdrdir)/ruby/internal/core/rclass.h
+pathname.o: $(hdrdir)/ruby/internal/core/rdata.h
+pathname.o: $(hdrdir)/ruby/internal/core/rfile.h
+pathname.o: $(hdrdir)/ruby/internal/core/rhash.h
+pathname.o: $(hdrdir)/ruby/internal/core/robject.h
+pathname.o: $(hdrdir)/ruby/internal/core/rregexp.h
+pathname.o: $(hdrdir)/ruby/internal/core/rstring.h
+pathname.o: $(hdrdir)/ruby/internal/core/rstruct.h
+pathname.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+pathname.o: $(hdrdir)/ruby/internal/ctype.h
+pathname.o: $(hdrdir)/ruby/internal/dllexport.h
+pathname.o: $(hdrdir)/ruby/internal/dosish.h
+pathname.o: $(hdrdir)/ruby/internal/error.h
+pathname.o: $(hdrdir)/ruby/internal/eval.h
+pathname.o: $(hdrdir)/ruby/internal/event.h
+pathname.o: $(hdrdir)/ruby/internal/fl_type.h
+pathname.o: $(hdrdir)/ruby/internal/gc.h
+pathname.o: $(hdrdir)/ruby/internal/glob.h
+pathname.o: $(hdrdir)/ruby/internal/globals.h
+pathname.o: $(hdrdir)/ruby/internal/has/attribute.h
+pathname.o: $(hdrdir)/ruby/internal/has/builtin.h
+pathname.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+pathname.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+pathname.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+pathname.o: $(hdrdir)/ruby/internal/has/extension.h
+pathname.o: $(hdrdir)/ruby/internal/has/feature.h
+pathname.o: $(hdrdir)/ruby/internal/has/warning.h
+pathname.o: $(hdrdir)/ruby/internal/intern/array.h
+pathname.o: $(hdrdir)/ruby/internal/intern/bignum.h
+pathname.o: $(hdrdir)/ruby/internal/intern/class.h
+pathname.o: $(hdrdir)/ruby/internal/intern/compar.h
+pathname.o: $(hdrdir)/ruby/internal/intern/complex.h
+pathname.o: $(hdrdir)/ruby/internal/intern/cont.h
+pathname.o: $(hdrdir)/ruby/internal/intern/dir.h
+pathname.o: $(hdrdir)/ruby/internal/intern/enum.h
+pathname.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+pathname.o: $(hdrdir)/ruby/internal/intern/error.h
+pathname.o: $(hdrdir)/ruby/internal/intern/eval.h
+pathname.o: $(hdrdir)/ruby/internal/intern/file.h
+pathname.o: $(hdrdir)/ruby/internal/intern/gc.h
+pathname.o: $(hdrdir)/ruby/internal/intern/hash.h
+pathname.o: $(hdrdir)/ruby/internal/intern/io.h
+pathname.o: $(hdrdir)/ruby/internal/intern/load.h
+pathname.o: $(hdrdir)/ruby/internal/intern/marshal.h
+pathname.o: $(hdrdir)/ruby/internal/intern/numeric.h
+pathname.o: $(hdrdir)/ruby/internal/intern/object.h
+pathname.o: $(hdrdir)/ruby/internal/intern/parse.h
+pathname.o: $(hdrdir)/ruby/internal/intern/proc.h
+pathname.o: $(hdrdir)/ruby/internal/intern/process.h
+pathname.o: $(hdrdir)/ruby/internal/intern/random.h
+pathname.o: $(hdrdir)/ruby/internal/intern/range.h
+pathname.o: $(hdrdir)/ruby/internal/intern/rational.h
+pathname.o: $(hdrdir)/ruby/internal/intern/re.h
+pathname.o: $(hdrdir)/ruby/internal/intern/ruby.h
+pathname.o: $(hdrdir)/ruby/internal/intern/select.h
+pathname.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+pathname.o: $(hdrdir)/ruby/internal/intern/signal.h
+pathname.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+pathname.o: $(hdrdir)/ruby/internal/intern/string.h
+pathname.o: $(hdrdir)/ruby/internal/intern/struct.h
+pathname.o: $(hdrdir)/ruby/internal/intern/thread.h
+pathname.o: $(hdrdir)/ruby/internal/intern/time.h
+pathname.o: $(hdrdir)/ruby/internal/intern/variable.h
+pathname.o: $(hdrdir)/ruby/internal/intern/vm.h
+pathname.o: $(hdrdir)/ruby/internal/interpreter.h
+pathname.o: $(hdrdir)/ruby/internal/iterator.h
+pathname.o: $(hdrdir)/ruby/internal/memory.h
+pathname.o: $(hdrdir)/ruby/internal/method.h
+pathname.o: $(hdrdir)/ruby/internal/module.h
+pathname.o: $(hdrdir)/ruby/internal/newobj.h
+pathname.o: $(hdrdir)/ruby/internal/rgengc.h
+pathname.o: $(hdrdir)/ruby/internal/scan_args.h
+pathname.o: $(hdrdir)/ruby/internal/special_consts.h
+pathname.o: $(hdrdir)/ruby/internal/static_assert.h
+pathname.o: $(hdrdir)/ruby/internal/stdalign.h
+pathname.o: $(hdrdir)/ruby/internal/stdbool.h
+pathname.o: $(hdrdir)/ruby/internal/symbol.h
+pathname.o: $(hdrdir)/ruby/internal/token_paste.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/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/gcc_version_since.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
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index dc4a7c0220..e6fb90277d 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -35,6 +35,13 @@ class Pathname
SEPARATOR_PAT = /#{Regexp.quote File::SEPARATOR}/
end
+ if File.dirname('A:') == 'A:.' # DOSish drive letter
+ ABSOLUTE_PATH = /\A(?:[A-Za-z]:|#{SEPARATOR_PAT})/o
+ else
+ ABSOLUTE_PATH = /\A#{SEPARATOR_PAT}/o
+ end
+ private_constant :ABSOLUTE_PATH
+
# :startdoc:
# chop_basename(path) -> [pre-basename, basename] or nil
@@ -222,7 +229,7 @@ class Pathname
# p.absolute?
# #=> false
def absolute?
- !relative?
+ ABSOLUTE_PATH.match? @path
end
# The opposite of Pathname#absolute?
@@ -237,11 +244,7 @@ class Pathname
# p.relative?
# #=> true
def relative?
- path = @path
- while r = chop_basename(path)
- path, = r
- end
- path == ''
+ !absolute?
end
#
@@ -502,6 +505,9 @@ class Pathname
#
# 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
diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c
index 0f4854580e..55577d7da7 100644
--- a/ext/pathname/pathname.c
+++ b/ext/pathname/pathname.c
@@ -138,7 +138,7 @@ path_freeze(VALUE self)
static VALUE
path_taint(VALUE self)
{
- rb_warning("Pathname#taint is deprecated and will be removed in Ruby 3.2.");
+ rb_warn("Pathname#taint is deprecated and will be removed in Ruby 3.2.");
return self;
}
@@ -151,7 +151,7 @@ path_taint(VALUE self)
static VALUE
path_untaint(VALUE self)
{
- rb_warning("Pathname#untaint is deprecated and will be removed in Ruby 3.2.");
+ rb_warn("Pathname#untaint is deprecated and will be removed in Ruby 3.2.");
return self;
}
@@ -554,7 +554,7 @@ path_mtime(VALUE self)
/*
* call-seq:
- * pathname.chmod -> integer
+ * pathname.chmod(mode_int) -> integer
*
* Changes file permissions.
*
@@ -568,7 +568,7 @@ path_chmod(VALUE self, VALUE mode)
/*
* call-seq:
- * pathname.lchmod -> integer
+ * pathname.lchmod(mode_int) -> integer
*
* Same as Pathname.chmod, but does not follow symbolic links.
*
@@ -582,7 +582,7 @@ path_lchmod(VALUE self, VALUE mode)
/*
* call-seq:
- * pathname.chown -> integer
+ * pathname.chown(owner_int, group_int) -> integer
*
* Change owner and group of the file.
*
@@ -596,7 +596,7 @@ path_chown(VALUE self, VALUE owner, VALUE group)
/*
* call-seq:
- * pathname.lchown -> integer
+ * pathname.lchown(owner_int, group_int) -> integer
*
* Same as Pathname.chown, but does not follow symbolic links.
*
@@ -610,8 +610,8 @@ path_lchown(VALUE self, VALUE owner, VALUE group)
/*
* call-seq:
- * pathname.fnmatch(pattern, [flags]) -> string
- * pathname.fnmatch?(pattern, [flags]) -> string
+ * pathname.fnmatch(pattern, [flags]) -> true or false
+ * pathname.fnmatch?(pattern, [flags]) -> true or false
*
* Return +true+ if the receiver matches the given pattern.
*
@@ -657,6 +657,13 @@ path_make_link(VALUE self, VALUE old)
}
/*
+ * call-seq:
+ * pathname.open()
+ * pathname.open(mode="r" [, opt]) -> file
+ * pathname.open([mode [, perm]] [, opt]) -> file
+ * pathname.open(mode="r" [, opt]) {|file| block } -> obj
+ * pathname.open([mode [, perm]] [, opt]) {|file| block } -> obj
+ *
* Opens the file for reading or writing.
*
* See File.open.
@@ -1482,6 +1489,8 @@ path_f_pathname(VALUE self, VALUE str)
* - #binread(*args)
* - #readlines(*args)
* - #sysopen(*args)
+ * - #write(*args)
+ * - #binwrite(*args)
*
* === Utilities
*
@@ -1503,6 +1512,10 @@ path_f_pathname(VALUE self, VALUE str)
void
Init_pathname(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
InitVM(pathname);
rb_cPathname = rb_define_class("Pathname", rb_cObject);
diff --git a/ext/pathname/pathname.gemspec b/ext/pathname/pathname.gemspec
new file mode 100644
index 0000000000..8593f9e9c7
--- /dev/null
+++ b/ext/pathname/pathname.gemspec
@@ -0,0 +1,25 @@
+Gem::Specification.new do |spec|
+ spec.name = "pathname"
+ spec.version = "0.1.0"
+ spec.authors = ["Tanaka Akira"]
+ spec.email = ["akr@fsij.org"]
+
+ spec.summary = %q{Representation of the name of a file or directory on the filesystem}
+ spec.description = %q{Representation of the name of a file or directory on the filesystem}
+ spec.homepage = "https://github.com/ruby/pathname"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+ spec.extensions = %w[ext/pathname/extconf.rb]
+end
diff --git a/ext/psych/depend b/ext/psych/depend
index dc358eaed3..2017319fd1 100644
--- a/ext/psych/depend
+++ b/ext/psych/depend
@@ -4,8 +4,157 @@ $(OBJS): $(YAML_H)
psych.o: $(RUBY_EXTCONF_H)
psych.o: $(arch_hdrdir)/ruby/config.h
psych.o: $(hdrdir)/ruby.h
+psych.o: $(hdrdir)/ruby/internal/anyargs.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych.o: $(hdrdir)/ruby/internal/assume.h
+psych.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych.o: $(hdrdir)/ruby/internal/attr/const.h
+psych.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych.o: $(hdrdir)/ruby/internal/attr/error.h
+psych.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych.o: $(hdrdir)/ruby/internal/attr/format.h
+psych.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych.o: $(hdrdir)/ruby/internal/cast.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych.o: $(hdrdir)/ruby/internal/config.h
+psych.o: $(hdrdir)/ruby/internal/constant_p.h
+psych.o: $(hdrdir)/ruby/internal/core.h
+psych.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych.o: $(hdrdir)/ruby/internal/core/robject.h
+psych.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych.o: $(hdrdir)/ruby/internal/ctype.h
+psych.o: $(hdrdir)/ruby/internal/dllexport.h
+psych.o: $(hdrdir)/ruby/internal/dosish.h
+psych.o: $(hdrdir)/ruby/internal/error.h
+psych.o: $(hdrdir)/ruby/internal/eval.h
+psych.o: $(hdrdir)/ruby/internal/event.h
+psych.o: $(hdrdir)/ruby/internal/fl_type.h
+psych.o: $(hdrdir)/ruby/internal/gc.h
+psych.o: $(hdrdir)/ruby/internal/glob.h
+psych.o: $(hdrdir)/ruby/internal/globals.h
+psych.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych.o: $(hdrdir)/ruby/internal/has/extension.h
+psych.o: $(hdrdir)/ruby/internal/has/feature.h
+psych.o: $(hdrdir)/ruby/internal/has/warning.h
+psych.o: $(hdrdir)/ruby/internal/intern/array.h
+psych.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych.o: $(hdrdir)/ruby/internal/intern/class.h
+psych.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych.o: $(hdrdir)/ruby/internal/intern/error.h
+psych.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych.o: $(hdrdir)/ruby/internal/intern/file.h
+psych.o: $(hdrdir)/ruby/internal/intern/gc.h
+psych.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych.o: $(hdrdir)/ruby/internal/intern/io.h
+psych.o: $(hdrdir)/ruby/internal/intern/load.h
+psych.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych.o: $(hdrdir)/ruby/internal/intern/object.h
+psych.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych.o: $(hdrdir)/ruby/internal/intern/process.h
+psych.o: $(hdrdir)/ruby/internal/intern/random.h
+psych.o: $(hdrdir)/ruby/internal/intern/range.h
+psych.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych.o: $(hdrdir)/ruby/internal/intern/re.h
+psych.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych.o: $(hdrdir)/ruby/internal/intern/select.h
+psych.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych.o: $(hdrdir)/ruby/internal/intern/string.h
+psych.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych.o: $(hdrdir)/ruby/internal/intern/time.h
+psych.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych.o: $(hdrdir)/ruby/internal/interpreter.h
+psych.o: $(hdrdir)/ruby/internal/iterator.h
+psych.o: $(hdrdir)/ruby/internal/memory.h
+psych.o: $(hdrdir)/ruby/internal/method.h
+psych.o: $(hdrdir)/ruby/internal/module.h
+psych.o: $(hdrdir)/ruby/internal/newobj.h
+psych.o: $(hdrdir)/ruby/internal/rgengc.h
+psych.o: $(hdrdir)/ruby/internal/scan_args.h
+psych.o: $(hdrdir)/ruby/internal/special_consts.h
+psych.o: $(hdrdir)/ruby/internal/static_assert.h
+psych.o: $(hdrdir)/ruby/internal/stdalign.h
+psych.o: $(hdrdir)/ruby/internal/stdbool.h
+psych.o: $(hdrdir)/ruby/internal/symbol.h
+psych.o: $(hdrdir)/ruby/internal/token_paste.h
+psych.o: $(hdrdir)/ruby/internal/value.h
+psych.o: $(hdrdir)/ruby/internal/value_type.h
+psych.o: $(hdrdir)/ruby/internal/variable.h
+psych.o: $(hdrdir)/ruby/internal/warning_push.h
+psych.o: $(hdrdir)/ruby/internal/xmalloc.h
psych.o: $(hdrdir)/ruby/assert.h
psych.o: $(hdrdir)/ruby/backward.h
+psych.o: $(hdrdir)/ruby/backward/2/assume.h
+psych.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych.o: $(hdrdir)/ruby/backward/2/bool.h
+psych.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+psych.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych.o: $(hdrdir)/ruby/backward/2/limits.h
+psych.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych.o: $(hdrdir)/ruby/defines.h
psych.o: $(hdrdir)/ruby/encoding.h
psych.o: $(hdrdir)/ruby/intern.h
@@ -24,8 +173,157 @@ psych.o: psych_yaml_tree.h
psych_emitter.o: $(RUBY_EXTCONF_H)
psych_emitter.o: $(arch_hdrdir)/ruby/config.h
psych_emitter.o: $(hdrdir)/ruby.h
+psych_emitter.o: $(hdrdir)/ruby/internal/anyargs.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych_emitter.o: $(hdrdir)/ruby/internal/assume.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/const.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/error.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/format.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych_emitter.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych_emitter.o: $(hdrdir)/ruby/internal/cast.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych_emitter.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych_emitter.o: $(hdrdir)/ruby/internal/config.h
+psych_emitter.o: $(hdrdir)/ruby/internal/constant_p.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/robject.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych_emitter.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych_emitter.o: $(hdrdir)/ruby/internal/ctype.h
+psych_emitter.o: $(hdrdir)/ruby/internal/dllexport.h
+psych_emitter.o: $(hdrdir)/ruby/internal/dosish.h
+psych_emitter.o: $(hdrdir)/ruby/internal/error.h
+psych_emitter.o: $(hdrdir)/ruby/internal/eval.h
+psych_emitter.o: $(hdrdir)/ruby/internal/event.h
+psych_emitter.o: $(hdrdir)/ruby/internal/fl_type.h
+psych_emitter.o: $(hdrdir)/ruby/internal/gc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/glob.h
+psych_emitter.o: $(hdrdir)/ruby/internal/globals.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/extension.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/feature.h
+psych_emitter.o: $(hdrdir)/ruby/internal/has/warning.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/array.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/class.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/error.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/file.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/gc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/io.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/load.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/object.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/process.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/random.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/range.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/re.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/select.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/string.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/time.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych_emitter.o: $(hdrdir)/ruby/internal/interpreter.h
+psych_emitter.o: $(hdrdir)/ruby/internal/iterator.h
+psych_emitter.o: $(hdrdir)/ruby/internal/memory.h
+psych_emitter.o: $(hdrdir)/ruby/internal/method.h
+psych_emitter.o: $(hdrdir)/ruby/internal/module.h
+psych_emitter.o: $(hdrdir)/ruby/internal/newobj.h
+psych_emitter.o: $(hdrdir)/ruby/internal/rgengc.h
+psych_emitter.o: $(hdrdir)/ruby/internal/scan_args.h
+psych_emitter.o: $(hdrdir)/ruby/internal/special_consts.h
+psych_emitter.o: $(hdrdir)/ruby/internal/static_assert.h
+psych_emitter.o: $(hdrdir)/ruby/internal/stdalign.h
+psych_emitter.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_emitter.o: $(hdrdir)/ruby/internal/symbol.h
+psych_emitter.o: $(hdrdir)/ruby/internal/token_paste.h
+psych_emitter.o: $(hdrdir)/ruby/internal/value.h
+psych_emitter.o: $(hdrdir)/ruby/internal/value_type.h
+psych_emitter.o: $(hdrdir)/ruby/internal/variable.h
+psych_emitter.o: $(hdrdir)/ruby/internal/warning_push.h
+psych_emitter.o: $(hdrdir)/ruby/internal/xmalloc.h
psych_emitter.o: $(hdrdir)/ruby/assert.h
psych_emitter.o: $(hdrdir)/ruby/backward.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/assume.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/bool.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/limits.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych_emitter.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych_emitter.o: $(hdrdir)/ruby/defines.h
psych_emitter.o: $(hdrdir)/ruby/encoding.h
psych_emitter.o: $(hdrdir)/ruby/intern.h
@@ -44,8 +342,157 @@ psych_emitter.o: psych_yaml_tree.h
psych_parser.o: $(RUBY_EXTCONF_H)
psych_parser.o: $(arch_hdrdir)/ruby/config.h
psych_parser.o: $(hdrdir)/ruby.h
+psych_parser.o: $(hdrdir)/ruby/internal/anyargs.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych_parser.o: $(hdrdir)/ruby/internal/assume.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/const.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/error.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/format.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych_parser.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych_parser.o: $(hdrdir)/ruby/internal/cast.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych_parser.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych_parser.o: $(hdrdir)/ruby/internal/config.h
+psych_parser.o: $(hdrdir)/ruby/internal/constant_p.h
+psych_parser.o: $(hdrdir)/ruby/internal/core.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/robject.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych_parser.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych_parser.o: $(hdrdir)/ruby/internal/ctype.h
+psych_parser.o: $(hdrdir)/ruby/internal/dllexport.h
+psych_parser.o: $(hdrdir)/ruby/internal/dosish.h
+psych_parser.o: $(hdrdir)/ruby/internal/error.h
+psych_parser.o: $(hdrdir)/ruby/internal/eval.h
+psych_parser.o: $(hdrdir)/ruby/internal/event.h
+psych_parser.o: $(hdrdir)/ruby/internal/fl_type.h
+psych_parser.o: $(hdrdir)/ruby/internal/gc.h
+psych_parser.o: $(hdrdir)/ruby/internal/glob.h
+psych_parser.o: $(hdrdir)/ruby/internal/globals.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/extension.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/feature.h
+psych_parser.o: $(hdrdir)/ruby/internal/has/warning.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/array.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/class.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/error.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/file.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/gc.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/io.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/load.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/object.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/process.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/random.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/range.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/re.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/select.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/string.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/time.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych_parser.o: $(hdrdir)/ruby/internal/interpreter.h
+psych_parser.o: $(hdrdir)/ruby/internal/iterator.h
+psych_parser.o: $(hdrdir)/ruby/internal/memory.h
+psych_parser.o: $(hdrdir)/ruby/internal/method.h
+psych_parser.o: $(hdrdir)/ruby/internal/module.h
+psych_parser.o: $(hdrdir)/ruby/internal/newobj.h
+psych_parser.o: $(hdrdir)/ruby/internal/rgengc.h
+psych_parser.o: $(hdrdir)/ruby/internal/scan_args.h
+psych_parser.o: $(hdrdir)/ruby/internal/special_consts.h
+psych_parser.o: $(hdrdir)/ruby/internal/static_assert.h
+psych_parser.o: $(hdrdir)/ruby/internal/stdalign.h
+psych_parser.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_parser.o: $(hdrdir)/ruby/internal/symbol.h
+psych_parser.o: $(hdrdir)/ruby/internal/token_paste.h
+psych_parser.o: $(hdrdir)/ruby/internal/value.h
+psych_parser.o: $(hdrdir)/ruby/internal/value_type.h
+psych_parser.o: $(hdrdir)/ruby/internal/variable.h
+psych_parser.o: $(hdrdir)/ruby/internal/warning_push.h
+psych_parser.o: $(hdrdir)/ruby/internal/xmalloc.h
psych_parser.o: $(hdrdir)/ruby/assert.h
psych_parser.o: $(hdrdir)/ruby/backward.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/assume.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/bool.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/limits.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych_parser.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych_parser.o: $(hdrdir)/ruby/defines.h
psych_parser.o: $(hdrdir)/ruby/encoding.h
psych_parser.o: $(hdrdir)/ruby/intern.h
@@ -64,8 +511,157 @@ psych_parser.o: psych_yaml_tree.h
psych_to_ruby.o: $(RUBY_EXTCONF_H)
psych_to_ruby.o: $(arch_hdrdir)/ruby/config.h
psych_to_ruby.o: $(hdrdir)/ruby.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/anyargs.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/assume.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/const.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/error.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/format.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/cast.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/config.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/constant_p.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/robject.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/ctype.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/dllexport.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/dosish.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/error.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/eval.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/event.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/fl_type.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/gc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/glob.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/globals.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/extension.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/feature.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/has/warning.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/array.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/class.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/error.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/file.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/gc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/io.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/load.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/object.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/process.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/random.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/range.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/re.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/string.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/time.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/interpreter.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/iterator.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/memory.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/method.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/module.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/newobj.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/rgengc.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/scan_args.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/special_consts.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/static_assert.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/stdalign.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/symbol.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/token_paste.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/value.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/value_type.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/variable.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/warning_push.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/xmalloc.h
psych_to_ruby.o: $(hdrdir)/ruby/assert.h
psych_to_ruby.o: $(hdrdir)/ruby/backward.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/assume.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/bool.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/limits.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych_to_ruby.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych_to_ruby.o: $(hdrdir)/ruby/defines.h
psych_to_ruby.o: $(hdrdir)/ruby/encoding.h
psych_to_ruby.o: $(hdrdir)/ruby/intern.h
@@ -84,8 +680,157 @@ psych_to_ruby.o: psych_yaml_tree.h
psych_yaml_tree.o: $(RUBY_EXTCONF_H)
psych_yaml_tree.o: $(arch_hdrdir)/ruby/config.h
psych_yaml_tree.o: $(hdrdir)/ruby.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/anyargs.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/assume.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/artificial.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/cold.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/const.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/error.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/format.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noalias.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noinline.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/pure.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/restrict.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/warning.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/attr/weakref.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/cast.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/compiler_since.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/config.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/constant_p.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rarray.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rbasic.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rbignum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rclass.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rdata.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rfile.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rhash.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/robject.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rregexp.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rstring.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rstruct.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/ctype.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/dllexport.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/dosish.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/error.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/eval.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/event.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/fl_type.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/gc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/glob.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/globals.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/attribute.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/builtin.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/extension.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/feature.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/has/warning.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/array.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/bignum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/class.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/compar.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/complex.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/cont.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/dir.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/enum.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/error.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/eval.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/file.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/gc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/hash.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/io.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/load.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/marshal.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/numeric.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/object.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/parse.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/proc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/process.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/random.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/range.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/rational.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/re.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/ruby.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/signal.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/string.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/struct.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/thread.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/time.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/variable.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/vm.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/interpreter.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/iterator.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/memory.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/method.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/module.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/newobj.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/rgengc.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/scan_args.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/special_consts.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/static_assert.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdalign.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdbool.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/symbol.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/token_paste.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/value.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/value_type.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/variable.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/warning_push.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/xmalloc.h
psych_yaml_tree.o: $(hdrdir)/ruby/assert.h
psych_yaml_tree.o: $(hdrdir)/ruby/backward.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/assume.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/attributes.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/bool.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/inttypes.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/limits.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/long_long.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/stdalign.h
+psych_yaml_tree.o: $(hdrdir)/ruby/backward/2/stdarg.h
psych_yaml_tree.o: $(hdrdir)/ruby/defines.h
psych_yaml_tree.o: $(hdrdir)/ruby/encoding.h
psych_yaml_tree.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb
index c719b036d0..34d2218549 100644
--- a/ext/psych/lib/psych.rb
+++ b/ext/psych/lib/psych.rb
@@ -74,12 +74,15 @@ require 'psych/class_loader'
#
# ==== Reading from a string
#
-# Psych.load("--- a") # => 'a'
-# Psych.load("---\n - a\n - b") # => ['a', 'b']
+# Psych.safe_load("--- a") # => 'a'
+# Psych.safe_load("---\n - a\n - b") # => ['a', 'b']
+# # From a trusted string:
+# Psych.load("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n") # => 0..42
#
# ==== Reading from a file
#
-# Psych.load_file("database.yml")
+# Psych.safe_load_file("data.yml", permitted_classes: [Date])
+# Psych.load_file("trusted_database.yml")
#
# ==== Exception handling
#
@@ -230,9 +233,9 @@ require 'psych/class_loader'
module Psych
# The version of libyaml Psych is using
- LIBYAML_VERSION = Psych.libyaml_version.join '.'
+ LIBYAML_VERSION = Psych.libyaml_version.join('.').freeze
# Deprecation guard
- NOT_GIVEN = Object.new
+ NOT_GIVEN = Object.new.freeze
private_constant :NOT_GIVEN
###
@@ -268,7 +271,7 @@ module Psych
# YAML documents that are supplied via user input. Instead, please use the
# safe_load method.
#
- def self.load yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, symbolize_names: false
+ def self.unsafe_load yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: false, symbolize_names: false, freeze: false
if legacy_filename != NOT_GIVEN
warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load is deprecated. Use keyword argument like Psych.load(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
filename = legacy_filename
@@ -276,10 +279,9 @@ module Psych
result = parse(yaml, filename: filename)
return fallback unless result
- result = result.to_ruby if result
- symbolize_names!(result) if symbolize_names
- result
+ result.to_ruby(symbolize_names: symbolize_names, freeze: freeze)
end
+ class << self; alias :load :unsafe_load; end
###
# Safely load the yaml string in +yaml+. By default, only the following
@@ -325,7 +327,7 @@ 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, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_symbols = NOT_GIVEN, legacy_aliases = NOT_GIVEN, legacy_filename = NOT_GIVEN, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false
+ def self.safe_load yaml, legacy_permitted_classes = NOT_GIVEN, legacy_permitted_symbols = NOT_GIVEN, legacy_aliases = NOT_GIVEN, legacy_filename = NOT_GIVEN, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false
if legacy_permitted_classes != NOT_GIVEN
warn_with_uplevel 'Passing permitted_classes with the 2nd argument of Psych.safe_load is deprecated. Use keyword argument like Psych.safe_load(yaml, permitted_classes: ...) instead.', uplevel: 1 if $VERBOSE
permitted_classes = legacy_permitted_classes
@@ -353,12 +355,11 @@ module Psych
permitted_symbols.map(&:to_s))
scanner = ScalarScanner.new class_loader
visitor = if aliases
- Visitors::ToRuby.new scanner, class_loader
+ Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
else
- Visitors::NoAliasRuby.new scanner, class_loader
+ Visitors::NoAliasRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
end
result = visitor.accept result
- symbolize_names!(result) if symbolize_names
result
end
@@ -551,7 +552,7 @@ module Psych
# end
# list # => ['foo', 'bar']
#
- def self.load_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: []
+ def self.load_stream yaml, legacy_filename = NOT_GIVEN, filename: nil, fallback: [], **kwargs
if legacy_filename != NOT_GIVEN
warn_with_uplevel 'Passing filename with the 2nd argument of Psych.load_stream is deprecated. Use keyword argument like Psych.load_stream(yaml, filename: ...) instead.', uplevel: 1 if $VERBOSE
filename = legacy_filename
@@ -559,10 +560,10 @@ module Psych
result = if block_given?
parse_stream(yaml, filename: filename) do |node|
- yield node.to_ruby
+ yield node.to_ruby(**kwargs)
end
else
- parse_stream(yaml, filename: filename).children.map(&:to_ruby)
+ parse_stream(yaml, filename: filename).children.map { |node| node.to_ruby(**kwargs) }
end
return fallback if result.is_a?(Array) && result.empty?
@@ -573,50 +574,50 @@ module Psych
# Load the document contained in +filename+. Returns the yaml contained in
# +filename+ as a Ruby object, or if the file is empty, it returns
# the specified +fallback+ return value, which defaults to +false+.
- def self.load_file filename, fallback: false
+ #
+ # NOTE: This method *should not* be used to parse untrusted documents, such as
+ # YAML documents that are supplied via user input. Instead, please use the
+ # safe_load_file method.
+ def self.unsafe_load_file filename, **kwargs
+ File.open(filename, 'r:bom|utf-8') { |f|
+ self.unsafe_load f, filename: filename, **kwargs
+ }
+ end
+ class << self; alias :load_file :unsafe_load_file; end
+
+ ###
+ # Safely loads the document contained in +filename+. Returns the yaml contained in
+ # +filename+ as a Ruby object, or if the file is empty, it returns
+ # the specified +fallback+ return value, which defaults to +false+.
+ # See safe_load for options.
+ def self.safe_load_file filename, **kwargs
File.open(filename, 'r:bom|utf-8') { |f|
- self.load f, filename: filename, fallback: fallback
+ self.safe_load f, filename: filename, **kwargs
}
end
# :stopdoc:
- @domain_types = {}
def self.add_domain_type domain, type_tag, &block
key = ['tag', domain, type_tag].join ':'
- @domain_types[key] = [key, block]
- @domain_types["tag:#{type_tag}"] = [key, block]
+ domain_types[key] = [key, block]
+ domain_types["tag:#{type_tag}"] = [key, block]
end
def self.add_builtin_type type_tag, &block
domain = 'yaml.org,2002'
key = ['tag', domain, type_tag].join ':'
- @domain_types[key] = [key, block]
+ domain_types[key] = [key, block]
end
def self.remove_type type_tag
- @domain_types.delete type_tag
+ domain_types.delete type_tag
end
- @load_tags = {}
- @dump_tags = {}
def self.add_tag tag, klass
- @load_tags[tag] = klass.name
- @dump_tags[klass] = tag
+ load_tags[tag] = klass.name
+ dump_tags[klass] = tag
end
- def self.symbolize_names!(result)
- case result
- when Hash
- result.keys.each do |key|
- result[key.to_sym] = symbolize_names!(result.delete(key))
- end
- when Array
- result.map! { |r| symbolize_names!(r) }
- end
- result
- end
- private_class_method :symbolize_names!
-
# Workaround for emulating `warn '...', uplevel: 1` in Ruby 2.4 or lower.
def self.warn_with_uplevel(message, uplevel: 1)
at = parse_caller(caller[uplevel]).join(':')
@@ -633,9 +634,32 @@ module Psych
private_class_method :warn_with_uplevel, :parse_caller
class << self
- attr_accessor :load_tags
- attr_accessor :dump_tags
- attr_accessor :domain_types
+ if defined?(Ractor)
+ require 'forwardable'
+ extend Forwardable
+
+ class Config
+ attr_accessor :load_tags, :dump_tags, :domain_types
+ def initialize
+ @load_tags = {}
+ @dump_tags = {}
+ @domain_types = {}
+ end
+ end
+
+ def config
+ Ractor.current[:PsychConfig] ||= Config.new
+ end
+
+ def_delegators :config, :load_tags, :dump_tags, :domain_types, :load_tags=, :dump_tags=, :domain_types=
+ else
+ attr_accessor :load_tags
+ attr_accessor :dump_tags
+ attr_accessor :domain_types
+ end
end
+ self.load_tags = {}
+ self.dump_tags = {}
+ self.domain_types = {}
# :startdoc:
end
diff --git a/ext/psych/lib/psych/class_loader.rb b/ext/psych/lib/psych/class_loader.rb
index cfca86845a..a5d1a7a4a9 100644
--- a/ext/psych/lib/psych/class_loader.rb
+++ b/ext/psych/lib/psych/class_loader.rb
@@ -35,9 +35,11 @@ module Psych
constants.each do |const|
konst = const_get const
- define_method(const.to_s.downcase) do
- load konst
- end
+ class_eval <<~RUBY
+ def #{const.to_s.downcase}
+ load #{konst.inspect}
+ end
+ RUBY
end
private
@@ -69,7 +71,7 @@ module Psych
rescue
nil
end
- }.compact]
+ }.compact].freeze
class Restricted < ClassLoader
def initialize classes, symbols
diff --git a/ext/psych/lib/psych/handler.rb b/ext/psych/lib/psych/handler.rb
index 8f23e366fa..ad7249ff77 100644
--- a/ext/psych/lib/psych/handler.rb
+++ b/ext/psych/lib/psych/handler.rb
@@ -119,7 +119,7 @@ module Psych
# +tag+ is an associated tag or nil
# +plain+ is a boolean value
# +quoted+ is a boolean value
- # +style+ is an integer idicating the string style
+ # +style+ is an integer indicating the string style
#
# See the constants in Psych::Nodes::Scalar for the possible values of
# +style+
diff --git a/ext/psych/lib/psych/nodes/node.rb b/ext/psych/lib/psych/nodes/node.rb
index f59fb8916b..05cb08dac0 100644
--- a/ext/psych/lib/psych/nodes/node.rb
+++ b/ext/psych/lib/psych/nodes/node.rb
@@ -46,8 +46,8 @@ module Psych
# Convert this node to Ruby.
#
# See also Psych::Visitors::ToRuby
- def to_ruby
- Visitors::ToRuby.create.accept(self)
+ def to_ruby(symbolize_names: false, freeze: false)
+ Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze).accept(self)
end
alias :transform :to_ruby
diff --git a/ext/psych/lib/psych/nodes/scalar.rb b/ext/psych/lib/psych/nodes/scalar.rb
index e2616b6a84..5550b616a3 100644
--- a/ext/psych/lib/psych/nodes/scalar.rb
+++ b/ext/psych/lib/psych/nodes/scalar.rb
@@ -50,7 +50,7 @@ module Psych
# +tag+ is an associated tag or nil
# +plain+ is a boolean value
# +quoted+ is a boolean value
- # +style+ is an integer idicating the string style
+ # +style+ is an integer indicating the string style
#
# == See Also
#
diff --git a/ext/psych/lib/psych/scalar_scanner.rb b/ext/psych/lib/psych/scalar_scanner.rb
index cea2a453dd..d565a336e8 100644
--- a/ext/psych/lib/psych/scalar_scanner.rb
+++ b/ext/psych/lib/psych/scalar_scanner.rb
@@ -101,7 +101,7 @@ module Psych
###
# Parse and return an int from +string+
def parse_int string
- Integer(string.gsub(/[,]/, ''))
+ Integer(string.gsub(/[,_]/, ''))
end
###
diff --git a/ext/psych/lib/psych/versions.rb b/ext/psych/lib/psych/versions.rb
index 731ba9545e..acb21336c4 100644
--- a/ext/psych/lib/psych/versions.rb
+++ b/ext/psych/lib/psych/versions.rb
@@ -1,10 +1,10 @@
-
# frozen_string_literal: true
+
module Psych
# The version of Psych you are using
- VERSION = '3.1.0' unless defined?(::Psych::VERSION)
+ VERSION = '3.3.2'
if RUBY_ENGINE == 'jruby'
- DEFAULT_SNAKEYAML_VERSION = '1.23'.freeze
+ DEFAULT_SNAKEYAML_VERSION = '1.28'.freeze
end
end
diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index b72fb4a1dc..4de7f80d33 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -12,39 +12,44 @@ module Psych
###
# This class walks a YAML AST, converting each node to Ruby
class ToRuby < Psych::Visitors::Visitor
- def self.create
+ def self.create(symbolize_names: false, freeze: false)
class_loader = ClassLoader.new
scanner = ScalarScanner.new class_loader
- new(scanner, class_loader)
+ new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
end
attr_reader :class_loader
- def initialize ss, class_loader
+ def initialize ss, class_loader, symbolize_names: false, freeze: false
super()
@st = {}
@ss = ss
+ @load_tags = Psych.load_tags
@domain_types = Psych.domain_types
@class_loader = class_loader
+ @symbolize_names = symbolize_names
+ @freeze = freeze
end
def accept target
result = super
- return result if @domain_types.empty? || !target.tag
- key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
- key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/
+ unless @domain_types.empty? || !target.tag
+ key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
+ key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/
- if @domain_types.key? key
- value, block = @domain_types[key]
- return block.call value, result
+ if @domain_types.key? key
+ value, block = @domain_types[key]
+ result = block.call value, result
+ end
end
+ result = deduplicate(result).freeze if @freeze
result
end
def deserialize o
- if klass = resolve_class(Psych.load_tags[o.tag])
+ if klass = resolve_class(@load_tags[o.tag])
instance = klass.allocate
if instance.respond_to?(:init_with)
@@ -124,7 +129,7 @@ module Psych
end
def visit_Psych_Nodes_Sequence o
- if klass = resolve_class(Psych.load_tags[o.tag])
+ if klass = resolve_class(@load_tags[o.tag])
instance = klass.allocate
if instance.respond_to?(:init_with)
@@ -156,8 +161,8 @@ module Psych
end
def visit_Psych_Nodes_Mapping o
- if Psych.load_tags[o.tag]
- return revive(resolve_class(Psych.load_tags[o.tag]), o)
+ if @load_tags[o.tag]
+ return revive(resolve_class(@load_tags[o.tag]), o)
end
return revive_hash(register(o, {}), o) unless o.tag
@@ -322,6 +327,7 @@ module Psych
end
private
+
def register node, object
@st[node.anchor] = object if node.anchor
object
@@ -333,13 +339,12 @@ module Psych
list
end
- SHOVEL = '<<'
- def revive_hash hash, o
+ def revive_hash hash, o, tagged= false
o.children.each_slice(2) { |k,v|
- key = deduplicate(accept(k))
+ key = accept(k)
val = accept(v)
- if key == SHOVEL && k.tag != "tag:yaml.org,2002:str"
+ if key == '<<' && k.tag != "tag:yaml.org,2002:str"
case v
when Nodes::Alias, Nodes::Mapping
begin
@@ -361,6 +366,12 @@ module Psych
hash[key] = val
end
else
+ if !tagged && @symbolize_names && key.is_a?(String)
+ key = key.to_sym
+ elsif !@freeze
+ key = deduplicate(key)
+ end
+
hash[key] = val
end
@@ -371,6 +382,8 @@ module Psych
if RUBY_VERSION < '2.7'
def deduplicate key
if key.is_a?(String)
+ # It is important to untaint the string, otherwise it won't
+ # be deduplicated into an fstring, but simply frozen.
-(key.untaint)
else
key
@@ -391,7 +404,7 @@ module Psych
def revive klass, node
s = register(node, klass.allocate)
- init_with(s, revive_hash({}, node), node)
+ init_with(s, revive_hash({}, node, true), node)
end
def init_with o, h, node
diff --git a/ext/psych/lib/psych/visitors/visitor.rb b/ext/psych/lib/psych/visitors/visitor.rb
index 3f4ba64e57..21052aa66f 100644
--- a/ext/psych/lib/psych/visitors/visitor.rb
+++ b/ext/psych/lib/psych/visitors/visitor.rb
@@ -8,12 +8,26 @@ module Psych
private
- DISPATCH = Hash.new do |hash, klass|
- hash[klass] = "visit_#{klass.name.gsub('::', '_')}"
+ # @api private
+ def self.dispatch_cache
+ Hash.new do |hash, klass|
+ hash[klass] = :"visit_#{klass.name.gsub('::', '_')}"
+ end.compare_by_identity
+ end
+
+ if defined?(Ractor)
+ def dispatch
+ @dispatch_cache ||= (Ractor.current[:Psych_Visitors_Visitor] ||= Visitor.dispatch_cache)
+ end
+ else
+ DISPATCH = dispatch_cache
+ def dispatch
+ DISPATCH
+ end
end
def visit target
- send DISPATCH[target.class], target
+ send dispatch[target.class], target
end
end
end
diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb
index 79ca129b83..bf7c0bb8ca 100644
--- a/ext/psych/lib/psych/visitors/yaml_tree.rb
+++ b/ext/psych/lib/psych/visitors/yaml_tree.rb
@@ -80,7 +80,7 @@ module Psych
raise(TypeError, "Can't dump #{target.class}") unless method
h[klass] = method
- end
+ end.compare_by_identity
end
def start encoding = Nodes::Stream::UTF8
@@ -181,7 +181,7 @@ module Psych
end
def visit_Exception o
- dump_exception o, private_iv_get(o, 'mesg')
+ dump_exception o, o.message.to_s
end
def visit_NameError o
@@ -509,9 +509,9 @@ module Psych
def emit_coder c, o
case c.type
when :scalar
- @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, Nodes::Scalar::ANY
+ @emitter.scalar c.scalar, nil, c.tag, c.tag.nil?, false, c.style
when :seq
- @emitter.start_sequence nil, c.tag, c.tag.nil?, Nodes::Sequence::BLOCK
+ @emitter.start_sequence nil, c.tag, c.tag.nil?, c.style
c.seq.each do |thing|
accept thing
end
diff --git a/ext/psych/psych.c b/ext/psych/psych.c
index 3bb59bfc11..8af0bb6a5a 100644
--- a/ext/psych/psych.c
+++ b/ext/psych/psych.c
@@ -11,9 +11,9 @@ static VALUE libyaml_version(VALUE module)
yaml_get_version(&major, &minor, &patch);
- list[0] = INT2NUM((long)major);
- list[1] = INT2NUM((long)minor);
- list[2] = INT2NUM((long)patch);
+ list[0] = INT2NUM(major);
+ list[1] = INT2NUM(minor);
+ list[2] = INT2NUM(patch);
return rb_ary_new4((long)3, list);
}
@@ -22,6 +22,9 @@ VALUE mPsych;
void Init_psych(void)
{
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+ #endif
mPsych = rb_define_module("Psych");
rb_define_singleton_method(mPsych, "libyaml_version", libyaml_version, 0);
diff --git a/ext/psych/psych.gemspec b/ext/psych/psych.gemspec
index e0168af7d8..e9e36e6633 100644
--- a/ext/psych/psych.gemspec
+++ b/ext/psych/psych.gemspec
@@ -1,16 +1,14 @@
# -*- encoding: utf-8 -*-
# frozen_string_literal: true
-begin
- require_relative 'lib/psych/versions'
-rescue LoadError
- # for Ruby core repository
- require_relative 'versions'
+version_module = Module.new do
+ version_rb = File.join(__dir__, "lib/psych/versions.rb")
+ module_eval(File.read(version_rb), version_rb)
end
Gem::Specification.new do |s|
s.name = "psych"
- s.version = Psych::VERSION
+ s.version = version_module::Psych::VERSION
s.authors = ["Aaron Patterson", "SHIBATA Hiroshi", "Charles Oliver Nutter"]
s.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org", "headius@headius.com"]
s.summary = "Psych is a YAML parser and emitter"
@@ -25,7 +23,7 @@ DESCRIPTION
# for ruby core repository. It was generated by `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
s.files = [
- ".gitignore", ".travis.yml", "Gemfile", "Mavenfile", "README.md", "Rakefile", "bin/console",
+ ".gitignore", "Gemfile", "LICENSE", "Mavenfile", "README.md", "Rakefile", "bin/console",
"bin/setup", "ext/psych/depend", "ext/psych/extconf.rb", "ext/psych/psych.c", "ext/psych/psych.h",
"ext/psych/psych_emitter.c", "ext/psych/psych_emitter.h", "ext/psych/psych_parser.c", "ext/psych/psych_parser.h",
"ext/psych/psych_to_ruby.c", "ext/psych/psych_to_ruby.h", "ext/psych/psych_yaml_tree.c", "ext/psych/psych_yaml_tree.h",
@@ -48,7 +46,6 @@ DESCRIPTION
s.extra_rdoc_files = ["README.md"]
s.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
- s.rubygems_version = "2.5.1"
s.required_rubygems_version = Gem::Requirement.new(">= 0")
if RUBY_ENGINE == 'jruby'
@@ -62,7 +59,7 @@ DESCRIPTION
"lib/psych_jars.rb",
"lib/psych.jar"
]
- s.requirements = "jar org.yaml:snakeyaml, #{Psych::DEFAULT_SNAKEYAML_VERSION}"
+ s.requirements = "jar org.yaml:snakeyaml, #{version_module::Psych::DEFAULT_SNAKEYAML_VERSION}"
s.add_dependency 'jar-dependencies', '>= 0.1.7'
else
s.extensions = ["ext/psych/extconf.rb"]
diff --git a/ext/psych/psych_parser.c b/ext/psych/psych_parser.c
index fb1a917bb2..fd550b671a 100644
--- a/ext/psych/psych_parser.c
+++ b/ext/psych/psych_parser.c
@@ -27,7 +27,7 @@ static ID id_event_location;
static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read)
{
VALUE io = (VALUE)data;
- VALUE string = rb_funcall(io, id_read, 1, INT2NUM(size));
+ VALUE string = rb_funcall(io, id_read, 1, SIZET2NUM(size));
*read = 0;
@@ -89,9 +89,9 @@ static VALUE make_exception(yaml_parser_t * parser, VALUE path)
return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
path,
- INT2NUM(line),
- INT2NUM(column),
- INT2NUM(parser->problem_offset),
+ SIZET2NUM(line),
+ SIZET2NUM(column),
+ SIZET2NUM(parser->problem_offset),
parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
}
@@ -303,10 +303,10 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
rb_exc_raise(exception);
}
- start_line = INT2NUM((long)event.start_mark.line);
- start_column = INT2NUM((long)event.start_mark.column);
- end_line = INT2NUM((long)event.end_mark.line);
- end_column = INT2NUM((long)event.end_mark.column);
+ start_line = SIZET2NUM(event.start_mark.line);
+ start_column = SIZET2NUM(event.start_mark.column);
+ end_line = SIZET2NUM(event.end_mark.line);
+ end_column = SIZET2NUM(event.end_mark.column);
event_args[0] = handler;
event_args[1] = start_line;
@@ -321,7 +321,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
VALUE args[2];
args[0] = handler;
- args[1] = INT2NUM((long)event.data.stream_start.encoding);
+ args[1] = INT2NUM(event.data.stream_start.encoding);
rb_protect(protected_start_stream, (VALUE)args, &state);
}
break;
@@ -334,8 +334,8 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
VALUE version = event.data.document_start.version_directive ?
rb_ary_new3(
(long)2,
- INT2NUM((long)event.data.document_start.version_directive->major),
- INT2NUM((long)event.data.document_start.version_directive->minor)
+ INT2NUM(event.data.document_start.version_directive->major),
+ INT2NUM(event.data.document_start.version_directive->minor)
) : rb_ary_new();
if(event.data.document_start.tag_directives.start) {
@@ -418,7 +418,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
quoted_implicit =
event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue;
- style = INT2NUM((long)event.data.scalar.style);
+ style = INT2NUM(event.data.scalar.style);
args[0] = handler;
args[1] = val;
@@ -450,7 +450,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
implicit =
event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue;
- style = INT2NUM((long)event.data.sequence_start.style);
+ style = INT2NUM(event.data.sequence_start.style);
args[0] = handler;
args[1] = anchor;
@@ -483,7 +483,7 @@ static VALUE parse(int argc, VALUE *argv, VALUE self)
implicit =
event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue;
- style = INT2NUM((long)event.data.mapping_start.style);
+ style = INT2NUM(event.data.mapping_start.style);
args[0] = handler;
args[1] = anchor;
@@ -527,9 +527,9 @@ static VALUE mark(VALUE self)
TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser);
mark_klass = rb_const_get_at(cPsychParser, rb_intern("Mark"));
- args[0] = INT2NUM(parser->mark.index);
- args[1] = INT2NUM(parser->mark.line);
- args[2] = INT2NUM(parser->mark.column);
+ args[0] = SIZET2NUM(parser->mark.index);
+ args[1] = SIZET2NUM(parser->mark.line);
+ args[2] = SIZET2NUM(parser->mark.column);
return rb_class_new_instance(3, args, mark_klass);
}
diff --git a/ext/psych/psych_yaml_tree.c b/ext/psych/psych_yaml_tree.c
index 7aca9114c9..225655d127 100644
--- a/ext/psych/psych_yaml_tree.c
+++ b/ext/psych/psych_yaml_tree.c
@@ -2,23 +2,11 @@
VALUE cPsychVisitorsYamlTree;
-/*
- * call-seq: private_iv_get(target, prop)
- *
- * Get the private instance variable +prop+ from +target+
- */
-static VALUE private_iv_get(VALUE self, VALUE target, VALUE prop)
-{
- return rb_attr_get(target, rb_intern(StringValueCStr(prop)));
-}
-
void Init_psych_yaml_tree(void)
{
VALUE psych = rb_define_module("Psych");
VALUE visitors = rb_define_module_under(psych, "Visitors");
VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject);
cPsychVisitorsYamlTree = rb_define_class_under(visitors, "YAMLTree", visitor);
-
- rb_define_private_method(cPsychVisitorsYamlTree, "private_iv_get", private_iv_get, 2);
}
/* vim: set noet sws=4 sw=4: */
diff --git a/ext/psych/yaml/api.c b/ext/psych/yaml/api.c
index 95dc6b4de3..6add8b2661 100644
--- a/ext/psych/yaml/api.c
+++ b/ext/psych/yaml/api.c
@@ -118,7 +118,12 @@ yaml_string_join(
YAML_DECLARE(int)
yaml_stack_extend(void **start, void **top, void **end)
{
- void *new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2);
+ void *new_start;
+
+ if ((char *)*end - (char *)*start >= INT_MAX / 2)
+ return 0;
+
+ new_start = yaml_realloc(*start, ((char *)*end - (char *)*start)*2);
if (!new_start) return 0;
@@ -618,10 +623,10 @@ yaml_token_delete(yaml_token_t *token)
*/
static int
-yaml_check_utf8(yaml_char_t *start, size_t length)
+yaml_check_utf8(const yaml_char_t *start, size_t length)
{
- yaml_char_t *end = start+length;
- yaml_char_t *pointer = start;
+ const yaml_char_t *end = start+length;
+ const yaml_char_t *pointer = start;
while (pointer < end) {
unsigned char octet;
@@ -789,7 +794,7 @@ yaml_document_end_event_initialize(yaml_event_t *event, int implicit)
*/
YAML_DECLARE(int)
-yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor)
+yaml_alias_event_initialize(yaml_event_t *event, const yaml_char_t *anchor)
{
yaml_mark_t mark = { 0, 0, 0 };
yaml_char_t *anchor_copy = NULL;
@@ -814,8 +819,8 @@ yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor)
YAML_DECLARE(int)
yaml_scalar_event_initialize(yaml_event_t *event,
- yaml_char_t *anchor, yaml_char_t *tag,
- yaml_char_t *value, int length,
+ const yaml_char_t *anchor, const yaml_char_t *tag,
+ const yaml_char_t *value, int length,
int plain_implicit, int quoted_implicit,
yaml_scalar_style_t style)
{
@@ -868,7 +873,7 @@ error:
YAML_DECLARE(int)
yaml_sequence_start_event_initialize(yaml_event_t *event,
- yaml_char_t *anchor, yaml_char_t *tag, int implicit,
+ const yaml_char_t *anchor, const yaml_char_t *tag, int implicit,
yaml_sequence_style_t style)
{
yaml_mark_t mark = { 0, 0, 0 };
@@ -923,7 +928,7 @@ yaml_sequence_end_event_initialize(yaml_event_t *event)
YAML_DECLARE(int)
yaml_mapping_start_event_initialize(yaml_event_t *event,
- yaml_char_t *anchor, yaml_char_t *tag, int implicit,
+ const yaml_char_t *anchor, const yaml_char_t *tag, int implicit,
yaml_mapping_style_t style)
{
yaml_mark_t mark = { 0, 0, 0 };
@@ -1117,15 +1122,8 @@ error:
YAML_DECLARE(void)
yaml_document_delete(yaml_document_t *document)
{
- struct {
- yaml_error_type_t error;
- } context;
yaml_tag_directive_t *tag_directive;
- /* Eliminate a compliler warning. */
- context.error = YAML_NO_ERROR;
- (void)context.error;
-
assert(document); /* Non-NULL document object is expected. */
while (!STACK_EMPTY(&context, document->nodes)) {
@@ -1195,7 +1193,7 @@ yaml_document_get_root_node(yaml_document_t *document)
YAML_DECLARE(int)
yaml_document_add_scalar(yaml_document_t *document,
- yaml_char_t *tag, yaml_char_t *value, int length,
+ const yaml_char_t *tag, const yaml_char_t *value, int length,
yaml_scalar_style_t style)
{
struct {
@@ -1245,7 +1243,7 @@ error:
YAML_DECLARE(int)
yaml_document_add_sequence(yaml_document_t *document,
- yaml_char_t *tag, yaml_sequence_style_t style)
+ const yaml_char_t *tag, yaml_sequence_style_t style)
{
struct {
yaml_error_type_t error;
@@ -1290,7 +1288,7 @@ error:
YAML_DECLARE(int)
yaml_document_add_mapping(yaml_document_t *document,
- yaml_char_t *tag, yaml_mapping_style_t style)
+ const yaml_char_t *tag, yaml_mapping_style_t style)
{
struct {
yaml_error_type_t error;
diff --git a/ext/psych/yaml/config.h b/ext/psych/yaml/config.h
index da905133ff..4b1150f5e4 100644
--- a/ext/psych/yaml/config.h
+++ b/ext/psych/yaml/config.h
@@ -1,10 +1,80 @@
+/* include/config.h. Generated from config.h.in by configure. */
+/* include/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "yaml"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "https://github.com/yaml/libyaml/issues/new"
+
+/* Define to the full name of this package. */
#define PACKAGE_NAME "yaml"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "yaml 0.2.5"
+
+/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "yaml"
-#define PACKAGE_VERSION "0.2.1"
-#define PACKAGE_STRING "yaml 0.2.1"
-#define PACKAGE_BUGREPORT "https://github.com/yaml/libyaml/issues"
-#define PACKAGE_URL "https://github.com/yaml/libyaml"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.2.5"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.2.5"
+
+/* Define the major version number. */
#define YAML_VERSION_MAJOR 0
+
+/* Define the minor version number. */
#define YAML_VERSION_MINOR 2
-#define YAML_VERSION_PATCH 1
-#define YAML_VERSION_STRING "0.2.1"
+
+/* Define the patch version number. */
+#define YAML_VERSION_PATCH 5
+
+/* Define the version string. */
+#define YAML_VERSION_STRING "0.2.5"
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
diff --git a/ext/psych/yaml/dumper.c b/ext/psych/yaml/dumper.c
index 29fb9c0784..1fe940b674 100644
--- a/ext/psych/yaml/dumper.c
+++ b/ext/psych/yaml/dumper.c
@@ -131,7 +131,7 @@ yaml_emitter_dump(yaml_emitter_t *emitter, yaml_document_t *document)
assert(emitter->opened); /* Emitter should be opened. */
- emitter->anchors = yaml_malloc(sizeof(*(emitter->anchors))
+ emitter->anchors = (yaml_anchors_t*)yaml_malloc(sizeof(*(emitter->anchors))
* (document->nodes.top - document->nodes.start));
if (!emitter->anchors) goto error;
memset(emitter->anchors, 0, sizeof(*(emitter->anchors))
diff --git a/ext/psych/yaml/emitter.c b/ext/psych/yaml/emitter.c
index 92e21cdb73..796294ccdf 100644
--- a/ext/psych/yaml/emitter.c
+++ b/ext/psych/yaml/emitter.c
@@ -16,7 +16,7 @@
#define PUT(emitter,value) \
(FLUSH(emitter) \
&& (*(emitter->buffer.pointer++) = (yaml_char_t)(value), \
- emitter->column ++, \
+ emitter->column++, \
1))
/*
@@ -495,6 +495,7 @@ static int
yaml_emitter_emit_stream_start(yaml_emitter_t *emitter,
yaml_event_t *event)
{
+ emitter->open_ended = 0;
if (event->type == YAML_STREAM_START_EVENT)
{
if (!emitter->encoding) {
@@ -597,13 +598,20 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
if (!yaml_emitter_write_indent(emitter))
return 0;
}
+ emitter->open_ended = 0;
if (event->data.document_start.version_directive) {
implicit = 0;
if (!yaml_emitter_write_indicator(emitter, "%YAML", 1, 0, 0))
return 0;
- if (!yaml_emitter_write_indicator(emitter, "1.1", 1, 0, 0))
- return 0;
+ if (event->data.document_start.version_directive->minor == 1) {
+ if (!yaml_emitter_write_indicator(emitter, "1.1", 1, 0, 0))
+ return 0;
+ }
+ else {
+ if (!yaml_emitter_write_indicator(emitter, "1.2", 1, 0, 0))
+ return 0;
+ }
if (!yaml_emitter_write_indent(emitter))
return 0;
}
@@ -644,19 +652,25 @@ yaml_emitter_emit_document_start(yaml_emitter_t *emitter,
emitter->state = YAML_EMIT_DOCUMENT_CONTENT_STATE;
+ emitter->open_ended = 0;
return 1;
}
else if (event->type == YAML_STREAM_END_EVENT)
{
- if (emitter->open_ended)
+
+ /**
+ * This can happen if a block scalar with trailing empty lines
+ * is at the end of the stream
+ */
+ if (emitter->open_ended == 2)
{
if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
return 0;
+ emitter->open_ended = 0;
if (!yaml_emitter_write_indent(emitter))
return 0;
}
-
if (!yaml_emitter_flush(emitter))
return 0;
@@ -698,9 +712,12 @@ yaml_emitter_emit_document_end(yaml_emitter_t *emitter,
if (!event->data.document_end.implicit) {
if (!yaml_emitter_write_indicator(emitter, "...", 1, 0, 0))
return 0;
+ emitter->open_ended = 0;
if (!yaml_emitter_write_indent(emitter))
return 0;
}
+ else if (!emitter->open_ended)
+ emitter->open_ended = 1;
if (!yaml_emitter_flush(emitter))
return 0;
@@ -1006,6 +1023,8 @@ yaml_emitter_emit_alias(yaml_emitter_t *emitter, SHIM(yaml_event_t *event))
{
if (!yaml_emitter_process_anchor(emitter))
return 0;
+ if (emitter->simple_key_context)
+ if (!PUT(emitter, ' ')) return 0;
emitter->state = POP(emitter, emitter->states);
return 1;
@@ -1333,7 +1352,10 @@ static int
yaml_emitter_analyze_version_directive(yaml_emitter_t *emitter,
yaml_version_directive_t version_directive)
{
- if (version_directive.major != 1 || version_directive.minor != 1) {
+ if (version_directive.major != 1 || (
+ version_directive.minor != 1
+ && version_directive.minor != 2
+ )) {
return yaml_emitter_set_emitter_error(emitter,
"incompatible %YAML directive");
}
@@ -1803,7 +1825,6 @@ yaml_emitter_write_indicator(yaml_emitter_t *emitter,
emitter->whitespace = is_whitespace;
emitter->indention = (emitter->indention && is_indention);
- emitter->open_ended = 0;
return 1;
}
@@ -1904,7 +1925,17 @@ yaml_emitter_write_plain_scalar(yaml_emitter_t *emitter,
STRING_ASSIGN(string, value, length);
- if (!emitter->whitespace) {
+ /**
+ * Avoid trailing spaces for empty values in block mode.
+ * In flow mode, we still want the space to prevent ambiguous things
+ * like {a:}.
+ * Currently, the emitter forbids any plain empty scalar in flow mode
+ * (e.g. it outputs {a: ''} instead), so emitter->flow_level will
+ * never be true here.
+ * But if the emitter is ever changed to allow emitting empty values,
+ * the check for flow_level is already here.
+ */
+ if (!emitter->whitespace && (length || emitter->flow_level)) {
if (!PUT(emitter, ' ')) return 0;
}
@@ -2004,6 +2035,9 @@ yaml_emitter_write_single_quoted_scalar(yaml_emitter_t *emitter,
}
}
+ if (breaks)
+ if (!yaml_emitter_write_indent(emitter)) return 0;
+
if (!yaml_emitter_write_indicator(emitter, "'", 0, 0, 0))
return 0;
@@ -2203,7 +2237,7 @@ yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
else if (string.start == string.pointer)
{
chomp_hint = "+";
- emitter->open_ended = 1;
+ emitter->open_ended = 2;
}
else
{
@@ -2213,7 +2247,7 @@ yaml_emitter_write_block_scalar_hints(yaml_emitter_t *emitter,
if (IS_BREAK(string))
{
chomp_hint = "+";
- emitter->open_ended = 1;
+ emitter->open_ended = 2;
}
}
}
diff --git a/ext/psych/yaml/loader.c b/ext/psych/yaml/loader.c
index e5d90be9bc..bcf3aee8cb 100644
--- a/ext/psych/yaml/loader.c
+++ b/ext/psych/yaml/loader.c
@@ -38,26 +38,46 @@ static void
yaml_parser_delete_aliases(yaml_parser_t *parser);
/*
+ * Document loading context.
+ */
+struct loader_ctx {
+ int *start;
+ int *end;
+ int *top;
+};
+
+/*
* Composer functions.
*/
+static int
+yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx);
+
+static int
+yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event);
static int
-yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event);
+yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx);
static int
-yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event);
+yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx);
static int
-yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event);
+yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx);
static int
-yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event);
+yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx);
static int
-yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event);
+yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx);
static int
-yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event);
+yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx);
/*
* Load the next document of the stream.
@@ -162,59 +182,78 @@ yaml_parser_delete_aliases(yaml_parser_t *parser)
*/
static int
-yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *first_event)
+yaml_parser_load_document(yaml_parser_t *parser, yaml_event_t *event)
{
- yaml_event_t event;
+ struct loader_ctx ctx = { NULL, NULL, NULL };
- assert(first_event->type == YAML_DOCUMENT_START_EVENT);
+ assert(event->type == YAML_DOCUMENT_START_EVENT);
/* DOCUMENT-START is expected. */
parser->document->version_directive
- = first_event->data.document_start.version_directive;
+ = event->data.document_start.version_directive;
parser->document->tag_directives.start
- = first_event->data.document_start.tag_directives.start;
+ = event->data.document_start.tag_directives.start;
parser->document->tag_directives.end
- = first_event->data.document_start.tag_directives.end;
+ = event->data.document_start.tag_directives.end;
parser->document->start_implicit
- = first_event->data.document_start.implicit;
- parser->document->start_mark = first_event->start_mark;
-
- if (!yaml_parser_parse(parser, &event)) return 0;
-
- if (!yaml_parser_load_node(parser, &event)) return 0;
-
- if (!yaml_parser_parse(parser, &event)) return 0;
- assert(event.type == YAML_DOCUMENT_END_EVENT);
- /* DOCUMENT-END is expected. */
+ = event->data.document_start.implicit;
+ parser->document->start_mark = event->start_mark;
- parser->document->end_implicit = event.data.document_end.implicit;
- parser->document->end_mark = event.end_mark;
+ if (!STACK_INIT(parser, ctx, int*)) return 0;
+ if (!yaml_parser_load_nodes(parser, &ctx)) {
+ STACK_DEL(parser, ctx);
+ return 0;
+ }
+ STACK_DEL(parser, ctx);
return 1;
}
/*
- * Compose a node.
+ * Compose a node tree.
*/
static int
-yaml_parser_load_node(yaml_parser_t *parser, yaml_event_t *first_event)
+yaml_parser_load_nodes(yaml_parser_t *parser, struct loader_ctx *ctx)
{
- switch (first_event->type) {
- case YAML_ALIAS_EVENT:
- return yaml_parser_load_alias(parser, first_event);
- case YAML_SCALAR_EVENT:
- return yaml_parser_load_scalar(parser, first_event);
- case YAML_SEQUENCE_START_EVENT:
- return yaml_parser_load_sequence(parser, first_event);
- case YAML_MAPPING_START_EVENT:
- return yaml_parser_load_mapping(parser, first_event);
- default:
- assert(0); /* Could not happen. */
- return 0;
- }
+ yaml_event_t event;
- return 0;
+ do {
+ if (!yaml_parser_parse(parser, &event)) return 0;
+
+ switch (event.type) {
+ case YAML_ALIAS_EVENT:
+ if (!yaml_parser_load_alias(parser, &event, ctx)) return 0;
+ break;
+ case YAML_SCALAR_EVENT:
+ if (!yaml_parser_load_scalar(parser, &event, ctx)) return 0;
+ break;
+ case YAML_SEQUENCE_START_EVENT:
+ if (!yaml_parser_load_sequence(parser, &event, ctx)) return 0;
+ break;
+ case YAML_SEQUENCE_END_EVENT:
+ if (!yaml_parser_load_sequence_end(parser, &event, ctx))
+ return 0;
+ break;
+ case YAML_MAPPING_START_EVENT:
+ if (!yaml_parser_load_mapping(parser, &event, ctx)) return 0;
+ break;
+ case YAML_MAPPING_END_EVENT:
+ if (!yaml_parser_load_mapping_end(parser, &event, ctx))
+ return 0;
+ break;
+ default:
+ assert(0); /* Could not happen. */
+ return 0;
+ case YAML_DOCUMENT_END_EVENT:
+ break;
+ }
+ } while (event.type != YAML_DOCUMENT_END_EVENT);
+
+ parser->document->end_implicit = event.data.document_end.implicit;
+ parser->document->end_mark = event.end_mark;
+
+ return 1;
}
/*
@@ -253,26 +292,79 @@ yaml_parser_register_anchor(yaml_parser_t *parser,
}
/*
+ * Compose node into its parent in the stree.
+ */
+
+static int
+yaml_parser_load_node_add(yaml_parser_t *parser, struct loader_ctx *ctx,
+ int index)
+{
+ struct yaml_node_s *parent;
+ int parent_index;
+
+ if (STACK_EMPTY(parser, *ctx)) {
+ /* This is the root node, there's no tree to add it to. */
+ return 1;
+ }
+
+ parent_index = *((*ctx).top - 1);
+ parent = &parser->document->nodes.start[parent_index-1];
+
+ switch (parent->type) {
+ case YAML_SEQUENCE_NODE:
+ if (!STACK_LIMIT(parser, parent->data.sequence.items, INT_MAX-1))
+ return 0;
+ if (!PUSH(parser, parent->data.sequence.items, index))
+ return 0;
+ break;
+ case YAML_MAPPING_NODE: {
+ yaml_node_pair_t pair;
+ if (!STACK_EMPTY(parser, parent->data.mapping.pairs)) {
+ yaml_node_pair_t *p = parent->data.mapping.pairs.top - 1;
+ if (p->key != 0 && p->value == 0) {
+ p->value = index;
+ break;
+ }
+ }
+
+ pair.key = index;
+ pair.value = 0;
+ if (!STACK_LIMIT(parser, parent->data.mapping.pairs, INT_MAX-1))
+ return 0;
+ if (!PUSH(parser, parent->data.mapping.pairs, pair))
+ return 0;
+
+ break;
+ }
+ default:
+ assert(0); /* Could not happen. */
+ return 0;
+ }
+ return 1;
+}
+
+/*
* Compose a node corresponding to an alias.
*/
static int
-yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
+yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx)
{
- yaml_char_t *anchor = first_event->data.alias.anchor;
+ yaml_char_t *anchor = event->data.alias.anchor;
yaml_alias_data_t *alias_data;
for (alias_data = parser->aliases.start;
alias_data != parser->aliases.top; alias_data ++) {
if (strcmp((char *)alias_data->anchor, (char *)anchor) == 0) {
yaml_free(anchor);
- return alias_data->index;
+ return yaml_parser_load_node_add(parser, ctx, alias_data->index);
}
}
yaml_free(anchor);
return yaml_parser_set_composer_error(parser, "found undefined alias",
- first_event->start_mark);
+ event->start_mark);
}
/*
@@ -280,11 +372,12 @@ yaml_parser_load_alias(yaml_parser_t *parser, yaml_event_t *first_event)
*/
static int
-yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
+yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx)
{
yaml_node_t node;
int index;
- yaml_char_t *tag = first_event->data.scalar.tag;
+ yaml_char_t *tag = event->data.scalar.tag;
if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
@@ -294,23 +387,23 @@ yaml_parser_load_scalar(yaml_parser_t *parser, yaml_event_t *first_event)
if (!tag) goto error;
}
- SCALAR_NODE_INIT(node, tag, first_event->data.scalar.value,
- first_event->data.scalar.length, first_event->data.scalar.style,
- first_event->start_mark, first_event->end_mark);
+ SCALAR_NODE_INIT(node, tag, event->data.scalar.value,
+ event->data.scalar.length, event->data.scalar.style,
+ event->start_mark, event->end_mark);
if (!PUSH(parser, parser->document->nodes, node)) goto error;
index = (int)(parser->document->nodes.top - parser->document->nodes.start);
if (!yaml_parser_register_anchor(parser, index,
- first_event->data.scalar.anchor)) return 0;
+ event->data.scalar.anchor)) return 0;
- return index;
+ return yaml_parser_load_node_add(parser, ctx, index);
error:
yaml_free(tag);
- yaml_free(first_event->data.scalar.anchor);
- yaml_free(first_event->data.scalar.value);
+ yaml_free(event->data.scalar.anchor);
+ yaml_free(event->data.scalar.value);
return 0;
}
@@ -319,17 +412,17 @@ error:
*/
static int
-yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
+yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx)
{
- yaml_event_t event;
yaml_node_t node;
struct {
yaml_node_item_t *start;
yaml_node_item_t *end;
yaml_node_item_t *top;
} items = { NULL, NULL, NULL };
- int index, item_index;
- yaml_char_t *tag = first_event->data.sequence_start.tag;
+ int index;
+ yaml_char_t *tag = event->data.sequence_start.tag;
if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
@@ -342,48 +435,54 @@ yaml_parser_load_sequence(yaml_parser_t *parser, yaml_event_t *first_event)
if (!STACK_INIT(parser, items, yaml_node_item_t*)) goto error;
SEQUENCE_NODE_INIT(node, tag, items.start, items.end,
- first_event->data.sequence_start.style,
- first_event->start_mark, first_event->end_mark);
+ event->data.sequence_start.style,
+ event->start_mark, event->end_mark);
if (!PUSH(parser, parser->document->nodes, node)) goto error;
index = (int)(parser->document->nodes.top - parser->document->nodes.start);
if (!yaml_parser_register_anchor(parser, index,
- first_event->data.sequence_start.anchor)) return 0;
-
- if (!yaml_parser_parse(parser, &event)) return 0;
-
- while (event.type != YAML_SEQUENCE_END_EVENT) {
- if (!STACK_LIMIT(parser,
- parser->document->nodes.start[index-1].data.sequence.items,
- INT_MAX-1)) return 0;
- item_index = yaml_parser_load_node(parser, &event);
- if (!item_index) return 0;
- if (!PUSH(parser,
- parser->document->nodes.start[index-1].data.sequence.items,
- item_index)) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
- }
+ event->data.sequence_start.anchor)) return 0;
- parser->document->nodes.start[index-1].end_mark = event.end_mark;
+ if (!yaml_parser_load_node_add(parser, ctx, index)) return 0;
- return index;
+ if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0;
+ if (!PUSH(parser, *ctx, index)) return 0;
+
+ return 1;
error:
yaml_free(tag);
- yaml_free(first_event->data.sequence_start.anchor);
+ yaml_free(event->data.sequence_start.anchor);
return 0;
}
+static int
+yaml_parser_load_sequence_end(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx)
+{
+ int index;
+
+ assert(((*ctx).top - (*ctx).start) > 0);
+
+ index = *((*ctx).top - 1);
+ assert(parser->document->nodes.start[index-1].type == YAML_SEQUENCE_NODE);
+ parser->document->nodes.start[index-1].end_mark = event->end_mark;
+
+ (void)POP(parser, *ctx);
+
+ return 1;
+}
+
/*
* Compose a mapping node.
*/
static int
-yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
+yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx)
{
- yaml_event_t event;
yaml_node_t node;
struct {
yaml_node_pair_t *start;
@@ -391,8 +490,7 @@ yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
yaml_node_pair_t *top;
} pairs = { NULL, NULL, NULL };
int index;
- yaml_node_pair_t pair;
- yaml_char_t *tag = first_event->data.mapping_start.tag;
+ yaml_char_t *tag = event->data.mapping_start.tag;
if (!STACK_LIMIT(parser, parser->document->nodes, INT_MAX-1)) goto error;
@@ -405,40 +503,42 @@ yaml_parser_load_mapping(yaml_parser_t *parser, yaml_event_t *first_event)
if (!STACK_INIT(parser, pairs, yaml_node_pair_t*)) goto error;
MAPPING_NODE_INIT(node, tag, pairs.start, pairs.end,
- first_event->data.mapping_start.style,
- first_event->start_mark, first_event->end_mark);
+ event->data.mapping_start.style,
+ event->start_mark, event->end_mark);
if (!PUSH(parser, parser->document->nodes, node)) goto error;
index = (int)(parser->document->nodes.top - parser->document->nodes.start);
if (!yaml_parser_register_anchor(parser, index,
- first_event->data.mapping_start.anchor)) return 0;
+ event->data.mapping_start.anchor)) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
+ if (!yaml_parser_load_node_add(parser, ctx, index)) return 0;
- while (event.type != YAML_MAPPING_END_EVENT) {
- if (!STACK_LIMIT(parser,
- parser->document->nodes.start[index-1].data.mapping.pairs,
- INT_MAX-1)) return 0;
- pair.key = yaml_parser_load_node(parser, &event);
- if (!pair.key) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
- pair.value = yaml_parser_load_node(parser, &event);
- if (!pair.value) return 0;
- if (!PUSH(parser,
- parser->document->nodes.start[index-1].data.mapping.pairs,
- pair)) return 0;
- if (!yaml_parser_parse(parser, &event)) return 0;
- }
+ if (!STACK_LIMIT(parser, *ctx, INT_MAX-1)) return 0;
+ if (!PUSH(parser, *ctx, index)) return 0;
- parser->document->nodes.start[index-1].end_mark = event.end_mark;
-
- return index;
+ return 1;
error:
yaml_free(tag);
- yaml_free(first_event->data.mapping_start.anchor);
+ yaml_free(event->data.mapping_start.anchor);
return 0;
}
+static int
+yaml_parser_load_mapping_end(yaml_parser_t *parser, yaml_event_t *event,
+ struct loader_ctx *ctx)
+{
+ int index;
+
+ assert(((*ctx).top - (*ctx).start) > 0);
+
+ index = *((*ctx).top - 1);
+ assert(parser->document->nodes.start[index-1].type == YAML_MAPPING_NODE);
+ parser->document->nodes.start[index-1].end_mark = event->end_mark;
+
+ (void)POP(parser, *ctx);
+
+ return 1;
+}
diff --git a/ext/psych/yaml/parser.c b/ext/psych/yaml/parser.c
index 621f676bf2..ec2f8d3e05 100644
--- a/ext/psych/yaml/parser.c
+++ b/ext/psych/yaml/parser.c
@@ -1261,7 +1261,10 @@ yaml_parser_process_directives(yaml_parser_t *parser,
goto error;
}
if (token->data.version_directive.major != 1
- || token->data.version_directive.minor != 1) {
+ || (
+ token->data.version_directive.minor != 1
+ && token->data.version_directive.minor != 2
+ )) {
yaml_parser_set_parser_error(parser,
"found incompatible YAML document", token->start_mark);
goto error;
@@ -1316,6 +1319,8 @@ yaml_parser_process_directives(yaml_parser_t *parser,
STACK_DEL(parser, tag_directives);
}
+ if (!version_directive_ref)
+ yaml_free(version_directive);
return 1;
error:
diff --git a/ext/psych/yaml/scanner.c b/ext/psych/yaml/scanner.c
index 204593d910..bb5d201274 100644
--- a/ext/psych/yaml/scanner.c
+++ b/ext/psych/yaml/scanner.c
@@ -38,8 +38,8 @@
* BLOCK-END # Indentation decrease.
* FLOW-SEQUENCE-START # '['
* FLOW-SEQUENCE-END # ']'
- * BLOCK-SEQUENCE-START # '{'
- * BLOCK-SEQUENCE-END # '}'
+ * FLOW-MAPPING-START # '{'
+ * FLOW-MAPPING-END # '}'
* BLOCK-ENTRY # '-'
* FLOW-ENTRY # ','
* KEY # '?' or nothing (simple keys).
@@ -273,7 +273,7 @@
* The tokens BLOCK-SEQUENCE-START and BLOCK-MAPPING-START denote indentation
* increase that precedes a block collection (cf. the INDENT token in Python).
* The token BLOCK-END denote indentation decrease that ends a block collection
- * (cf. the DEDENT token in Python). However YAML has some syntax pecularities
+ * (cf. the DEDENT token in Python). However YAML has some syntax peculiarities
* that makes detections of these tokens more complex.
*
* The tokens BLOCK-ENTRY, KEY, and VALUE are used to represent the indicators
@@ -348,6 +348,7 @@
* SCALAR("another value",plain)
* KEY
* SCALAR("a mapping",plain)
+ * VALUE
* BLOCK-MAPPING-START
* KEY
* SCALAR("key 1",plain)
@@ -711,7 +712,7 @@ yaml_parser_scan_tag_handle(yaml_parser_t *parser, int directive,
yaml_mark_t start_mark, yaml_char_t **handle);
static int
-yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
+yaml_parser_scan_tag_uri(yaml_parser_t *parser, int uri_char, int directive,
yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri);
static int
@@ -2292,7 +2293,7 @@ yaml_parser_scan_tag_directive_value(yaml_parser_t *parser,
/* Scan a prefix. */
- if (!yaml_parser_scan_tag_uri(parser, 1, NULL, start_mark, &prefix_value))
+ if (!yaml_parser_scan_tag_uri(parser, 1, 1, NULL, start_mark, &prefix_value))
goto error;
/* Expect a whitespace or line break. */
@@ -2410,7 +2411,7 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token)
/* Consume the tag value. */
- if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
+ if (!yaml_parser_scan_tag_uri(parser, 1, 0, NULL, start_mark, &suffix))
goto error;
/* Check for '>' and eat it. */
@@ -2438,14 +2439,14 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token)
{
/* Scan the suffix now. */
- if (!yaml_parser_scan_tag_uri(parser, 0, NULL, start_mark, &suffix))
+ if (!yaml_parser_scan_tag_uri(parser, 0, 0, NULL, start_mark, &suffix))
goto error;
}
else
{
/* It wasn't a handle after all. Scan the rest of the tag. */
- if (!yaml_parser_scan_tag_uri(parser, 0, handle, start_mark, &suffix))
+ if (!yaml_parser_scan_tag_uri(parser, 0, 0, handle, start_mark, &suffix))
goto error;
/* Set the handle to '!'. */
@@ -2474,9 +2475,11 @@ yaml_parser_scan_tag(yaml_parser_t *parser, yaml_token_t *token)
if (!CACHE(parser, 1)) goto error;
if (!IS_BLANKZ(parser->buffer)) {
- yaml_parser_set_scanner_error(parser, "while scanning a tag",
- start_mark, "did not find expected whitespace or line break");
- goto error;
+ if (!parser->flow_level || !CHECK(parser->buffer, ',') ) {
+ yaml_parser_set_scanner_error(parser, "while scanning a tag",
+ start_mark, "did not find expected whitespace or line break");
+ goto error;
+ }
}
end_mark = parser->mark;
@@ -2565,7 +2568,7 @@ error:
*/
static int
-yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
+yaml_parser_scan_tag_uri(yaml_parser_t *parser, int uri_char, int directive,
yaml_char_t *head, yaml_mark_t start_mark, yaml_char_t **uri)
{
size_t length = head ? strlen((char *)head) : 0;
@@ -2601,8 +2604,11 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
* The set of characters that may appear in URI is as follows:
*
* '0'-'9', 'A'-'Z', 'a'-'z', '_', '-', ';', '/', '?', ':', '@', '&',
- * '=', '+', '$', ',', '.', '!', '~', '*', '\'', '(', ')', '[', ']',
- * '%'.
+ * '=', '+', '$', '.', '!', '~', '*', '\'', '(', ')', '%'.
+ *
+ * If we are inside a verbatim tag <...> (parameter uri_char is true)
+ * then also the following flow indicators are allowed:
+ * ',', '[', ']'
*/
while (IS_ALPHA(parser->buffer) || CHECK(parser->buffer, ';')
@@ -2610,12 +2616,15 @@ yaml_parser_scan_tag_uri(yaml_parser_t *parser, int directive,
|| CHECK(parser->buffer, ':') || CHECK(parser->buffer, '@')
|| CHECK(parser->buffer, '&') || CHECK(parser->buffer, '=')
|| CHECK(parser->buffer, '+') || CHECK(parser->buffer, '$')
- || CHECK(parser->buffer, ',') || CHECK(parser->buffer, '.')
+ || CHECK(parser->buffer, '.') || CHECK(parser->buffer, '%')
|| CHECK(parser->buffer, '!') || CHECK(parser->buffer, '~')
|| CHECK(parser->buffer, '*') || CHECK(parser->buffer, '\'')
|| CHECK(parser->buffer, '(') || CHECK(parser->buffer, ')')
- || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']')
- || CHECK(parser->buffer, '%'))
+ || (uri_char && (
+ CHECK(parser->buffer, ',')
+ || CHECK(parser->buffer, '[') || CHECK(parser->buffer, ']')
+ )
+ ))
{
/* Check if it is a URI-escape sequence. */
@@ -2860,7 +2869,7 @@ yaml_parser_scan_block_scalar(yaml_parser_t *parser, yaml_token_t *token,
if (!CACHE(parser, 1)) goto error;
- while ((int)parser->mark.column == indent && !IS_Z(parser->buffer))
+ while ((int)parser->mark.column == indent && !(IS_Z(parser->buffer)))
{
/*
* We are at the beginning of a non-empty line.
@@ -3278,7 +3287,7 @@ yaml_parser_scan_flow_scalar(yaml_parser_t *parser, yaml_token_t *token,
/* Check if we are at the end of the scalar. */
- /* Fix for crash unitialized value crash
+ /* Fix for crash uninitialized value crash
* Credit for the bug and input is to OSS Fuzz
* Credit for the fix to Alex Gaynor
*/
@@ -3430,11 +3439,22 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token)
while (!IS_BLANKZ(parser->buffer))
{
- /* Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13". */
+ /* Check for "x:" + one of ',?[]{}' in the flow context. TODO: Fix the test "spec-08-13".
+ * This is not completely according to the spec
+ * See http://yaml.org/spec/1.1/#id907281 9.1.3. Plain
+ */
if (parser->flow_level
&& CHECK(parser->buffer, ':')
- && !IS_BLANKZ_AT(parser->buffer, 1)) {
+ && (
+ CHECK_AT(parser->buffer, ',', 1)
+ || CHECK_AT(parser->buffer, '?', 1)
+ || CHECK_AT(parser->buffer, '[', 1)
+ || CHECK_AT(parser->buffer, ']', 1)
+ || CHECK_AT(parser->buffer, '{', 1)
+ || CHECK_AT(parser->buffer, '}', 1)
+ )
+ ) {
yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
start_mark, "found unexpected ':'");
goto error;
@@ -3444,8 +3464,8 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token)
if ((CHECK(parser->buffer, ':') && IS_BLANKZ_AT(parser->buffer, 1))
|| (parser->flow_level &&
- (CHECK(parser->buffer, ',') || CHECK(parser->buffer, ':')
- || CHECK(parser->buffer, '?') || CHECK(parser->buffer, '[')
+ (CHECK(parser->buffer, ',')
+ || CHECK(parser->buffer, '[')
|| CHECK(parser->buffer, ']') || CHECK(parser->buffer, '{')
|| CHECK(parser->buffer, '}'))))
break;
@@ -3512,7 +3532,7 @@ yaml_parser_scan_plain_scalar(yaml_parser_t *parser, yaml_token_t *token)
if (leading_blanks && (int)parser->mark.column < indent
&& IS_TAB(parser->buffer)) {
yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
- start_mark, "found a tab character that violate indentation");
+ start_mark, "found a tab character that violates indentation");
goto error;
}
diff --git a/ext/psych/yaml/yaml.h b/ext/psych/yaml/yaml.h
index f33a152594..f1b7bfde20 100644
--- a/ext/psych/yaml/yaml.h
+++ b/ext/psych/yaml/yaml.h
@@ -26,7 +26,9 @@ extern "C" {
/** The public API declaration. */
-#ifdef _WIN32
+#if defined(__MINGW32__)
+# define YAML_DECLARE(type) type
+#elif defined(_WIN32)
# if defined(YAML_DECLARE_STATIC)
# define YAML_DECLARE(type) type
# elif defined(YAML_DECLARE_EXPORT)
@@ -230,7 +232,7 @@ typedef enum yaml_token_type_e {
/** A BLOCK-SEQUENCE-START token. */
YAML_BLOCK_SEQUENCE_START_TOKEN,
- /** A BLOCK-SEQUENCE-END token. */
+ /** A BLOCK-MAPPING-START token. */
YAML_BLOCK_MAPPING_START_TOKEN,
/** A BLOCK-END token. */
YAML_BLOCK_END_TOKEN,
@@ -550,7 +552,7 @@ yaml_document_end_event_initialize(yaml_event_t *event, int implicit);
*/
YAML_DECLARE(int)
-yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor);
+yaml_alias_event_initialize(yaml_event_t *event, const yaml_char_t *anchor);
/**
* Create a SCALAR event.
@@ -576,8 +578,8 @@ yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor);
YAML_DECLARE(int)
yaml_scalar_event_initialize(yaml_event_t *event,
- yaml_char_t *anchor, yaml_char_t *tag,
- yaml_char_t *value, int length,
+ const yaml_char_t *anchor, const yaml_char_t *tag,
+ const yaml_char_t *value, int length,
int plain_implicit, int quoted_implicit,
yaml_scalar_style_t style);
@@ -599,7 +601,7 @@ yaml_scalar_event_initialize(yaml_event_t *event,
YAML_DECLARE(int)
yaml_sequence_start_event_initialize(yaml_event_t *event,
- yaml_char_t *anchor, yaml_char_t *tag, int implicit,
+ const yaml_char_t *anchor, const yaml_char_t *tag, int implicit,
yaml_sequence_style_t style);
/**
@@ -631,7 +633,7 @@ yaml_sequence_end_event_initialize(yaml_event_t *event);
YAML_DECLARE(int)
yaml_mapping_start_event_initialize(yaml_event_t *event,
- yaml_char_t *anchor, yaml_char_t *tag, int implicit,
+ const yaml_char_t *anchor, const yaml_char_t *tag, int implicit,
yaml_mapping_style_t style);
/**
@@ -663,7 +665,7 @@ yaml_event_delete(yaml_event_t *event);
/** The tag @c !!null with the only possible value: @c null. */
#define YAML_NULL_TAG "tag:yaml.org,2002:null"
-/** The tag @c !!bool with the values: @c true and @c falce. */
+/** The tag @c !!bool with the values: @c true and @c false. */
#define YAML_BOOL_TAG "tag:yaml.org,2002:bool"
/** The tag @c !!str for string values. */
#define YAML_STR_TAG "tag:yaml.org,2002:str"
@@ -894,7 +896,7 @@ yaml_document_get_root_node(yaml_document_t *document);
YAML_DECLARE(int)
yaml_document_add_scalar(yaml_document_t *document,
- yaml_char_t *tag, yaml_char_t *value, int length,
+ const yaml_char_t *tag, const yaml_char_t *value, int length,
yaml_scalar_style_t style);
/**
@@ -911,7 +913,7 @@ yaml_document_add_scalar(yaml_document_t *document,
YAML_DECLARE(int)
yaml_document_add_sequence(yaml_document_t *document,
- yaml_char_t *tag, yaml_sequence_style_t style);
+ const yaml_char_t *tag, yaml_sequence_style_t style);
/**
* Create a MAPPING node and attach it to the document.
@@ -927,7 +929,7 @@ yaml_document_add_sequence(yaml_document_t *document,
YAML_DECLARE(int)
yaml_document_add_mapping(yaml_document_t *document,
- yaml_char_t *tag, yaml_mapping_style_t style);
+ const yaml_char_t *tag, yaml_mapping_style_t style);
/**
* Add an item to a SEQUENCE node.
@@ -935,7 +937,7 @@ yaml_document_add_mapping(yaml_document_t *document,
* @param[in,out] document A document object.
* @param[in] sequence The sequence node id.
* @param[in] item The item node id.
-*
+ *
* @returns @c 1 if the function succeeded, @c 0 on error.
*/
@@ -950,7 +952,7 @@ yaml_document_append_sequence_item(yaml_document_t *document,
* @param[in] mapping The mapping node id.
* @param[in] key The key node id.
* @param[in] value The value node id.
-*
+ *
* @returns @c 1 if the function succeeded, @c 0 on error.
*/
@@ -1018,6 +1020,7 @@ typedef enum yaml_parser_state_e {
YAML_PARSE_DOCUMENT_CONTENT_STATE,
/** Expect DOCUMENT-END. */
YAML_PARSE_DOCUMENT_END_STATE,
+
/** Expect a block node. */
YAML_PARSE_BLOCK_NODE_STATE,
/** Expect a block node or indentless sequence. */
@@ -1028,6 +1031,7 @@ typedef enum yaml_parser_state_e {
YAML_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE,
/** Expect an entry of a block sequence. */
YAML_PARSE_BLOCK_SEQUENCE_ENTRY_STATE,
+
/** Expect an entry of an indentless sequence. */
YAML_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE,
/** Expect the first key of a block mapping. */
@@ -1038,6 +1042,7 @@ typedef enum yaml_parser_state_e {
YAML_PARSE_BLOCK_MAPPING_VALUE_STATE,
/** Expect the first entry of a flow sequence. */
YAML_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE,
+
/** Expect an entry of a flow sequence. */
YAML_PARSE_FLOW_SEQUENCE_ENTRY_STATE,
/** Expect a key of an ordered mapping. */
@@ -1049,6 +1054,7 @@ typedef enum yaml_parser_state_e {
/** Expect the first key of a flow mapping. */
YAML_PARSE_FLOW_MAPPING_FIRST_KEY_STATE,
/** Expect a key of a flow mapping. */
+
YAML_PARSE_FLOW_MAPPING_KEY_STATE,
/** Expect a value of a flow mapping. */
YAML_PARSE_FLOW_MAPPING_VALUE_STATE,
@@ -1203,7 +1209,7 @@ typedef struct yaml_parser_s {
/** The number of tokens fetched from the queue. */
size_t tokens_parsed;
- /* Does the tokens queue contain a token ready for dequeueing. */
+ /** Does the tokens queue contain a token ready for dequeueing. */
int token_available;
/** The indentation levels stack. */
@@ -1329,7 +1335,7 @@ yaml_parser_delete(yaml_parser_t *parser);
* Set a string input.
*
* Note that the @a input pointer must be valid while the @a parser object
- * exists. The application is responsible for destroing @a input after
+ * exists. The application is responsible for destroying @a input after
* destroying the @a parser.
*
* @param[in,out] parser A parser object.
@@ -1444,7 +1450,7 @@ yaml_parser_parse(yaml_parser_t *parser, yaml_event_t *event);
* @param[in,out] parser A parser object.
* @param[out] document An empty document object.
*
- * @return @c 1 if the function succeeded, @c 0 on error.
+ * @returns @c 1 if the function succeeded, @c 0 on error.
*/
YAML_DECLARE(int)
@@ -1487,6 +1493,7 @@ typedef enum yaml_emitter_state_e {
YAML_EMIT_DOCUMENT_CONTENT_STATE,
/** Expect DOCUMENT-END. */
YAML_EMIT_DOCUMENT_END_STATE,
+
/** Expect the first item of a flow sequence. */
YAML_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE,
/** Expect an item of a flow sequence. */
@@ -1497,6 +1504,7 @@ typedef enum yaml_emitter_state_e {
YAML_EMIT_FLOW_MAPPING_KEY_STATE,
/** Expect a value for a simple key of a flow mapping. */
YAML_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE,
+
/** Expect a value of a flow mapping. */
YAML_EMIT_FLOW_MAPPING_VALUE_STATE,
/** Expect the first item of a block sequence. */
@@ -1507,6 +1515,7 @@ typedef enum yaml_emitter_state_e {
YAML_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE,
/** Expect the key of a block mapping. */
YAML_EMIT_BLOCK_MAPPING_KEY_STATE,
+
/** Expect a value for a simple key of a block mapping. */
YAML_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE,
/** Expect a value of a block mapping. */
@@ -1515,6 +1524,18 @@ typedef enum yaml_emitter_state_e {
YAML_EMIT_END_STATE
} yaml_emitter_state_t;
+
+/* This is needed for C++ */
+
+typedef struct yaml_anchors_s {
+ /** The number of references. */
+ int references;
+ /** The anchor id. */
+ int anchor;
+ /** If the node has been emitted? */
+ int serialized;
+} yaml_anchors_t;
+
/**
* The emitter structure.
*
@@ -1546,7 +1567,7 @@ typedef struct yaml_emitter_s {
/** Write handler. */
yaml_write_handler_t *write_handler;
- /** A pointer for passing to the white handler. */
+ /** A pointer for passing to the write handler. */
void *write_handler_data;
/** Standard (string or file) output data. */
@@ -1713,7 +1734,7 @@ typedef struct yaml_emitter_s {
size_t length;
/** Does the scalar contain line breaks? */
int multiline;
- /** Can the scalar be expessed in the flow plain style? */
+ /** Can the scalar be expressed in the flow plain style? */
int flow_plain_allowed;
/** Can the scalar be expressed in the block plain style? */
int block_plain_allowed;
@@ -1740,14 +1761,7 @@ typedef struct yaml_emitter_s {
int closed;
/** The information associated with the document nodes. */
- struct {
- /** The number of references. */
- int references;
- /** The anchor id. */
- int anchor;
- /** If the node has been emitted? */
- int serialized;
- } *anchors;
+ yaml_anchors_t *anchors;
/** The last assigned anchor id. */
int last_anchor_id;
@@ -1936,10 +1950,10 @@ yaml_emitter_close(yaml_emitter_t *emitter);
/**
* Emit a YAML document.
*
- * The documen object may be generated using the yaml_parser_load() function
+ * The document object may be generated using the yaml_parser_load() function
* or the yaml_document_initialize() function. The emitter takes the
- * responsibility for the document object and destoys its content after
- * it is emitted. The document object is destroyedeven if the function fails.
+ * responsibility for the document object and destroys its content after
+ * it is emitted. The document object is destroyed even if the function fails.
*
* @param[in,out] emitter An emitter object.
* @param[in,out] document A document object.
diff --git a/ext/psych/yaml/yaml_private.h b/ext/psych/yaml/yaml_private.h
index f4f244cbc8..266a6bd3a7 100644
--- a/ext/psych/yaml/yaml_private.h
+++ b/ext/psych/yaml/yaml_private.h
@@ -2,8 +2,8 @@
#include RUBY_EXTCONF_H
#endif
-#if HAVE_CONFIG_H
-#include <config.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
#endif
#include <yaml.h>
@@ -175,14 +175,14 @@ yaml_string_join(
* Check the octet at the specified position.
*/
-#define CHECK_AT(string,octet,offset) \
+#define CHECK_AT(string,octet,offset) \
((string).pointer[offset] == (yaml_char_t)(octet))
/*
* Check the current octet in the buffer.
*/
-#define CHECK(string,octet) CHECK_AT((string),(octet),0)
+#define CHECK(string,octet) (CHECK_AT((string),(octet),0))
/*
* Check if the character at the specified position is an alphabetical
diff --git a/ext/pty/depend b/ext/pty/depend
index 1e89dc824c..23d6e6e329 100644
--- a/ext/pty/depend
+++ b/ext/pty/depend
@@ -2,8 +2,157 @@
pty.o: $(RUBY_EXTCONF_H)
pty.o: $(arch_hdrdir)/ruby/config.h
pty.o: $(hdrdir)/ruby.h
+pty.o: $(hdrdir)/ruby/internal/anyargs.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+pty.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+pty.o: $(hdrdir)/ruby/internal/assume.h
+pty.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+pty.o: $(hdrdir)/ruby/internal/attr/artificial.h
+pty.o: $(hdrdir)/ruby/internal/attr/cold.h
+pty.o: $(hdrdir)/ruby/internal/attr/const.h
+pty.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+pty.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+pty.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+pty.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+pty.o: $(hdrdir)/ruby/internal/attr/error.h
+pty.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+pty.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+pty.o: $(hdrdir)/ruby/internal/attr/format.h
+pty.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+pty.o: $(hdrdir)/ruby/internal/attr/noalias.h
+pty.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+pty.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+pty.o: $(hdrdir)/ruby/internal/attr/noinline.h
+pty.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+pty.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+pty.o: $(hdrdir)/ruby/internal/attr/pure.h
+pty.o: $(hdrdir)/ruby/internal/attr/restrict.h
+pty.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+pty.o: $(hdrdir)/ruby/internal/attr/warning.h
+pty.o: $(hdrdir)/ruby/internal/attr/weakref.h
+pty.o: $(hdrdir)/ruby/internal/cast.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+pty.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+pty.o: $(hdrdir)/ruby/internal/compiler_since.h
+pty.o: $(hdrdir)/ruby/internal/config.h
+pty.o: $(hdrdir)/ruby/internal/constant_p.h
+pty.o: $(hdrdir)/ruby/internal/core.h
+pty.o: $(hdrdir)/ruby/internal/core/rarray.h
+pty.o: $(hdrdir)/ruby/internal/core/rbasic.h
+pty.o: $(hdrdir)/ruby/internal/core/rbignum.h
+pty.o: $(hdrdir)/ruby/internal/core/rclass.h
+pty.o: $(hdrdir)/ruby/internal/core/rdata.h
+pty.o: $(hdrdir)/ruby/internal/core/rfile.h
+pty.o: $(hdrdir)/ruby/internal/core/rhash.h
+pty.o: $(hdrdir)/ruby/internal/core/robject.h
+pty.o: $(hdrdir)/ruby/internal/core/rregexp.h
+pty.o: $(hdrdir)/ruby/internal/core/rstring.h
+pty.o: $(hdrdir)/ruby/internal/core/rstruct.h
+pty.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+pty.o: $(hdrdir)/ruby/internal/ctype.h
+pty.o: $(hdrdir)/ruby/internal/dllexport.h
+pty.o: $(hdrdir)/ruby/internal/dosish.h
+pty.o: $(hdrdir)/ruby/internal/error.h
+pty.o: $(hdrdir)/ruby/internal/eval.h
+pty.o: $(hdrdir)/ruby/internal/event.h
+pty.o: $(hdrdir)/ruby/internal/fl_type.h
+pty.o: $(hdrdir)/ruby/internal/gc.h
+pty.o: $(hdrdir)/ruby/internal/glob.h
+pty.o: $(hdrdir)/ruby/internal/globals.h
+pty.o: $(hdrdir)/ruby/internal/has/attribute.h
+pty.o: $(hdrdir)/ruby/internal/has/builtin.h
+pty.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+pty.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+pty.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+pty.o: $(hdrdir)/ruby/internal/has/extension.h
+pty.o: $(hdrdir)/ruby/internal/has/feature.h
+pty.o: $(hdrdir)/ruby/internal/has/warning.h
+pty.o: $(hdrdir)/ruby/internal/intern/array.h
+pty.o: $(hdrdir)/ruby/internal/intern/bignum.h
+pty.o: $(hdrdir)/ruby/internal/intern/class.h
+pty.o: $(hdrdir)/ruby/internal/intern/compar.h
+pty.o: $(hdrdir)/ruby/internal/intern/complex.h
+pty.o: $(hdrdir)/ruby/internal/intern/cont.h
+pty.o: $(hdrdir)/ruby/internal/intern/dir.h
+pty.o: $(hdrdir)/ruby/internal/intern/enum.h
+pty.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+pty.o: $(hdrdir)/ruby/internal/intern/error.h
+pty.o: $(hdrdir)/ruby/internal/intern/eval.h
+pty.o: $(hdrdir)/ruby/internal/intern/file.h
+pty.o: $(hdrdir)/ruby/internal/intern/gc.h
+pty.o: $(hdrdir)/ruby/internal/intern/hash.h
+pty.o: $(hdrdir)/ruby/internal/intern/io.h
+pty.o: $(hdrdir)/ruby/internal/intern/load.h
+pty.o: $(hdrdir)/ruby/internal/intern/marshal.h
+pty.o: $(hdrdir)/ruby/internal/intern/numeric.h
+pty.o: $(hdrdir)/ruby/internal/intern/object.h
+pty.o: $(hdrdir)/ruby/internal/intern/parse.h
+pty.o: $(hdrdir)/ruby/internal/intern/proc.h
+pty.o: $(hdrdir)/ruby/internal/intern/process.h
+pty.o: $(hdrdir)/ruby/internal/intern/random.h
+pty.o: $(hdrdir)/ruby/internal/intern/range.h
+pty.o: $(hdrdir)/ruby/internal/intern/rational.h
+pty.o: $(hdrdir)/ruby/internal/intern/re.h
+pty.o: $(hdrdir)/ruby/internal/intern/ruby.h
+pty.o: $(hdrdir)/ruby/internal/intern/select.h
+pty.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+pty.o: $(hdrdir)/ruby/internal/intern/signal.h
+pty.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+pty.o: $(hdrdir)/ruby/internal/intern/string.h
+pty.o: $(hdrdir)/ruby/internal/intern/struct.h
+pty.o: $(hdrdir)/ruby/internal/intern/thread.h
+pty.o: $(hdrdir)/ruby/internal/intern/time.h
+pty.o: $(hdrdir)/ruby/internal/intern/variable.h
+pty.o: $(hdrdir)/ruby/internal/intern/vm.h
+pty.o: $(hdrdir)/ruby/internal/interpreter.h
+pty.o: $(hdrdir)/ruby/internal/iterator.h
+pty.o: $(hdrdir)/ruby/internal/memory.h
+pty.o: $(hdrdir)/ruby/internal/method.h
+pty.o: $(hdrdir)/ruby/internal/module.h
+pty.o: $(hdrdir)/ruby/internal/newobj.h
+pty.o: $(hdrdir)/ruby/internal/rgengc.h
+pty.o: $(hdrdir)/ruby/internal/scan_args.h
+pty.o: $(hdrdir)/ruby/internal/special_consts.h
+pty.o: $(hdrdir)/ruby/internal/static_assert.h
+pty.o: $(hdrdir)/ruby/internal/stdalign.h
+pty.o: $(hdrdir)/ruby/internal/stdbool.h
+pty.o: $(hdrdir)/ruby/internal/symbol.h
+pty.o: $(hdrdir)/ruby/internal/token_paste.h
+pty.o: $(hdrdir)/ruby/internal/value.h
+pty.o: $(hdrdir)/ruby/internal/value_type.h
+pty.o: $(hdrdir)/ruby/internal/variable.h
+pty.o: $(hdrdir)/ruby/internal/warning_push.h
+pty.o: $(hdrdir)/ruby/internal/xmalloc.h
pty.o: $(hdrdir)/ruby/assert.h
pty.o: $(hdrdir)/ruby/backward.h
+pty.o: $(hdrdir)/ruby/backward/2/assume.h
+pty.o: $(hdrdir)/ruby/backward/2/attributes.h
+pty.o: $(hdrdir)/ruby/backward/2/bool.h
+pty.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+pty.o: $(hdrdir)/ruby/backward/2/inttypes.h
+pty.o: $(hdrdir)/ruby/backward/2/limits.h
+pty.o: $(hdrdir)/ruby/backward/2/long_long.h
+pty.o: $(hdrdir)/ruby/backward/2/stdalign.h
+pty.o: $(hdrdir)/ruby/backward/2/stdarg.h
pty.o: $(hdrdir)/ruby/defines.h
pty.o: $(hdrdir)/ruby/encoding.h
pty.o: $(hdrdir)/ruby/intern.h
@@ -16,5 +165,13 @@ pty.o: $(hdrdir)/ruby/st.h
pty.o: $(hdrdir)/ruby/subst.h
pty.o: $(hdrdir)/ruby/util.h
pty.o: $(top_srcdir)/internal.h
+pty.o: $(top_srcdir)/internal/array.h
+pty.o: $(top_srcdir)/internal/compilers.h
+pty.o: $(top_srcdir)/internal/gc.h
+pty.o: $(top_srcdir)/internal/imemo.h
+pty.o: $(top_srcdir)/internal/process.h
+pty.o: $(top_srcdir)/internal/signal.h
+pty.o: $(top_srcdir)/internal/static_assert.h
+pty.o: $(top_srcdir)/internal/warnings.h
pty.o: pty.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb
index 7721a744c8..038bdf4d2c 100644
--- a/ext/pty/extconf.rb
+++ b/ext/pty/extconf.rb
@@ -10,9 +10,9 @@ if /mswin|mingw|bccwin/ !~ RUBY_PLATFORM
have_header("util.h") # OpenBSD openpty
have_header("pty.h")
have_header("pwd.h")
- have_library("util", "openpty")
+ util = have_library("util", "openpty")
if have_func("posix_openpt") or
- have_func("openpty") or
+ (util or have_func("openpty")) or
have_func("_getpty") or
have_func("ptsname") or
have_func("ioctl")
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index 4c6ae26127..e53871ede5 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -1,45 +1,51 @@
-#include "ruby/config.h"
+#include "ruby/config.h"
+
#ifdef RUBY_EXTCONF_H
-#include RUBY_EXTCONF_H
+# include RUBY_EXTCONF_H
#endif
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <fcntl.h>
-#include <errno.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <fcntl.h>
+
#ifdef HAVE_PWD_H
-#include <pwd.h>
+# include <pwd.h>
#endif
+
#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
+# include <sys/ioctl.h>
#endif
+
#ifdef HAVE_LIBUTIL_H
-#include <libutil.h>
+# include <libutil.h>
#endif
+
#ifdef HAVE_UTIL_H
-#include <util.h>
+# include <util.h>
#endif
+
#ifdef HAVE_PTY_H
-#include <pty.h>
+# include <pty.h>
#endif
+
#if defined(HAVE_SYS_PARAM_H)
- /* for __FreeBSD_version */
+ /* for __FreeBSD_version */
# include <sys/param.h>
#endif
+
#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
+# include <sys/wait.h>
#else
-#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
+# define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
#endif
-#include <ctype.h>
-
-#include "ruby/io.h"
-#include "internal.h"
-#include "ruby/util.h"
-#include <signal.h>
#ifdef HAVE_SYS_STROPTS_H
#include <sys/stropts.h>
#endif
@@ -48,6 +54,12 @@
#include <unistd.h>
#endif
+#include "internal.h"
+#include "internal/process.h"
+#include "internal/signal.h"
+#include "ruby/io.h"
+#include "ruby/util.h"
+
#define DEVICELEN 16
#ifndef HAVE_SETEUID
@@ -452,11 +464,11 @@ pty_close_pty(VALUE assoc)
/*
* call-seq:
* PTY.open => [master_io, slave_file]
- * PTY.open {|master_io, slave_file| ... } => block value
+ * PTY.open {|(master_io, slave_file)| ... } => block value
*
* Allocates a pty (pseudo-terminal).
*
- * In the block form, yields two arguments <tt>master_io, slave_file</tt>
+ * In the block form, yields an array of two elements (<tt>master_io, slave_file</tt>)
* and the value of the block is returned from +open+.
*
* The IO and File are both closed after the block completes if they haven't
@@ -682,7 +694,7 @@ static VALUE cPTY;
* Document-class: PTY
*
* Creates and manages pseudo terminals (PTYs). See also
- * http://en.wikipedia.org/wiki/Pseudo_terminal
+ * https://en.wikipedia.org/wiki/Pseudo_terminal
*
* PTY allows you to allocate new terminals using ::open or ::spawn a new
* terminal with a specific command.
diff --git a/ext/racc/cparse/cparse.c b/ext/racc/cparse/cparse.c
index ca74b80000..f71ed2bba9 100644
--- a/ext/racc/cparse/cparse.c
+++ b/ext/racc/cparse/cparse.c
@@ -605,7 +605,7 @@ parse_main(struct cparse_params *v, VALUE tok, VALUE val, int resume)
user_yyerror:
if (v->errstatus == 3) {
if (v->t == vFINAL_TOKEN) {
- v->retval = Qfalse;
+ v->retval = Qnil;
v->fin = CP_FIN_EOT;
return;
}
@@ -819,14 +819,16 @@ reduce0(RB_BLOCK_CALL_FUNC_ARGLIST(_, data))
void
Init_cparse(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
VALUE Racc, Parser;
- ID id_racc = rb_intern("Racc");
+ ID id_racc = rb_intern_const("Racc");
if (rb_const_defined(rb_cObject, id_racc)) {
Racc = rb_const_get(rb_cObject, id_racc);
- Parser = rb_const_get_at(Racc, rb_intern("Parser"));
+ Parser = rb_const_get_at(Racc, rb_intern_const("Parser"));
}
else {
Racc = rb_define_module("Racc");
@@ -846,16 +848,16 @@ Init_cparse(void)
RaccBug = rb_eRuntimeError;
- id_yydebug = rb_intern("@yydebug");
- id_nexttoken = rb_intern("next_token");
- id_onerror = rb_intern("on_error");
- id_noreduce = rb_intern("_reduce_none");
- id_errstatus = rb_intern("@racc_error_status");
-
- id_d_shift = rb_intern("racc_shift");
- id_d_reduce = rb_intern("racc_reduce");
- id_d_accept = rb_intern("racc_accept");
- id_d_read_token = rb_intern("racc_read_token");
- id_d_next_state = rb_intern("racc_next_state");
- id_d_e_pop = rb_intern("racc_e_pop");
+ id_yydebug = rb_intern_const("@yydebug");
+ id_nexttoken = rb_intern_const("next_token");
+ id_onerror = rb_intern_const("on_error");
+ id_noreduce = rb_intern_const("_reduce_none");
+ id_errstatus = rb_intern_const("@racc_error_status");
+
+ id_d_shift = rb_intern_const("racc_shift");
+ id_d_reduce = rb_intern_const("racc_reduce");
+ id_d_accept = rb_intern_const("racc_accept");
+ id_d_read_token = rb_intern_const("racc_read_token");
+ id_d_next_state = rb_intern_const("racc_next_state");
+ id_d_e_pop = rb_intern_const("racc_e_pop");
}
diff --git a/ext/racc/cparse/depend b/ext/racc/cparse/depend
index a156b32343..97d8445764 100644
--- a/ext/racc/cparse/depend
+++ b/ext/racc/cparse/depend
@@ -2,8 +2,157 @@
cparse.o: $(RUBY_EXTCONF_H)
cparse.o: $(arch_hdrdir)/ruby/config.h
cparse.o: $(hdrdir)/ruby.h
+cparse.o: $(hdrdir)/ruby/internal/anyargs.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+cparse.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+cparse.o: $(hdrdir)/ruby/internal/assume.h
+cparse.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+cparse.o: $(hdrdir)/ruby/internal/attr/artificial.h
+cparse.o: $(hdrdir)/ruby/internal/attr/cold.h
+cparse.o: $(hdrdir)/ruby/internal/attr/const.h
+cparse.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+cparse.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+cparse.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+cparse.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+cparse.o: $(hdrdir)/ruby/internal/attr/error.h
+cparse.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+cparse.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+cparse.o: $(hdrdir)/ruby/internal/attr/format.h
+cparse.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+cparse.o: $(hdrdir)/ruby/internal/attr/noalias.h
+cparse.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+cparse.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+cparse.o: $(hdrdir)/ruby/internal/attr/noinline.h
+cparse.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+cparse.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+cparse.o: $(hdrdir)/ruby/internal/attr/pure.h
+cparse.o: $(hdrdir)/ruby/internal/attr/restrict.h
+cparse.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+cparse.o: $(hdrdir)/ruby/internal/attr/warning.h
+cparse.o: $(hdrdir)/ruby/internal/attr/weakref.h
+cparse.o: $(hdrdir)/ruby/internal/cast.h
+cparse.o: $(hdrdir)/ruby/internal/compiler_is.h
+cparse.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+cparse.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+cparse.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+cparse.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+cparse.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+cparse.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+cparse.o: $(hdrdir)/ruby/internal/compiler_since.h
+cparse.o: $(hdrdir)/ruby/internal/config.h
+cparse.o: $(hdrdir)/ruby/internal/constant_p.h
+cparse.o: $(hdrdir)/ruby/internal/core.h
+cparse.o: $(hdrdir)/ruby/internal/core/rarray.h
+cparse.o: $(hdrdir)/ruby/internal/core/rbasic.h
+cparse.o: $(hdrdir)/ruby/internal/core/rbignum.h
+cparse.o: $(hdrdir)/ruby/internal/core/rclass.h
+cparse.o: $(hdrdir)/ruby/internal/core/rdata.h
+cparse.o: $(hdrdir)/ruby/internal/core/rfile.h
+cparse.o: $(hdrdir)/ruby/internal/core/rhash.h
+cparse.o: $(hdrdir)/ruby/internal/core/robject.h
+cparse.o: $(hdrdir)/ruby/internal/core/rregexp.h
+cparse.o: $(hdrdir)/ruby/internal/core/rstring.h
+cparse.o: $(hdrdir)/ruby/internal/core/rstruct.h
+cparse.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+cparse.o: $(hdrdir)/ruby/internal/ctype.h
+cparse.o: $(hdrdir)/ruby/internal/dllexport.h
+cparse.o: $(hdrdir)/ruby/internal/dosish.h
+cparse.o: $(hdrdir)/ruby/internal/error.h
+cparse.o: $(hdrdir)/ruby/internal/eval.h
+cparse.o: $(hdrdir)/ruby/internal/event.h
+cparse.o: $(hdrdir)/ruby/internal/fl_type.h
+cparse.o: $(hdrdir)/ruby/internal/gc.h
+cparse.o: $(hdrdir)/ruby/internal/glob.h
+cparse.o: $(hdrdir)/ruby/internal/globals.h
+cparse.o: $(hdrdir)/ruby/internal/has/attribute.h
+cparse.o: $(hdrdir)/ruby/internal/has/builtin.h
+cparse.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+cparse.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+cparse.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+cparse.o: $(hdrdir)/ruby/internal/has/extension.h
+cparse.o: $(hdrdir)/ruby/internal/has/feature.h
+cparse.o: $(hdrdir)/ruby/internal/has/warning.h
+cparse.o: $(hdrdir)/ruby/internal/intern/array.h
+cparse.o: $(hdrdir)/ruby/internal/intern/bignum.h
+cparse.o: $(hdrdir)/ruby/internal/intern/class.h
+cparse.o: $(hdrdir)/ruby/internal/intern/compar.h
+cparse.o: $(hdrdir)/ruby/internal/intern/complex.h
+cparse.o: $(hdrdir)/ruby/internal/intern/cont.h
+cparse.o: $(hdrdir)/ruby/internal/intern/dir.h
+cparse.o: $(hdrdir)/ruby/internal/intern/enum.h
+cparse.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+cparse.o: $(hdrdir)/ruby/internal/intern/error.h
+cparse.o: $(hdrdir)/ruby/internal/intern/eval.h
+cparse.o: $(hdrdir)/ruby/internal/intern/file.h
+cparse.o: $(hdrdir)/ruby/internal/intern/gc.h
+cparse.o: $(hdrdir)/ruby/internal/intern/hash.h
+cparse.o: $(hdrdir)/ruby/internal/intern/io.h
+cparse.o: $(hdrdir)/ruby/internal/intern/load.h
+cparse.o: $(hdrdir)/ruby/internal/intern/marshal.h
+cparse.o: $(hdrdir)/ruby/internal/intern/numeric.h
+cparse.o: $(hdrdir)/ruby/internal/intern/object.h
+cparse.o: $(hdrdir)/ruby/internal/intern/parse.h
+cparse.o: $(hdrdir)/ruby/internal/intern/proc.h
+cparse.o: $(hdrdir)/ruby/internal/intern/process.h
+cparse.o: $(hdrdir)/ruby/internal/intern/random.h
+cparse.o: $(hdrdir)/ruby/internal/intern/range.h
+cparse.o: $(hdrdir)/ruby/internal/intern/rational.h
+cparse.o: $(hdrdir)/ruby/internal/intern/re.h
+cparse.o: $(hdrdir)/ruby/internal/intern/ruby.h
+cparse.o: $(hdrdir)/ruby/internal/intern/select.h
+cparse.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+cparse.o: $(hdrdir)/ruby/internal/intern/signal.h
+cparse.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+cparse.o: $(hdrdir)/ruby/internal/intern/string.h
+cparse.o: $(hdrdir)/ruby/internal/intern/struct.h
+cparse.o: $(hdrdir)/ruby/internal/intern/thread.h
+cparse.o: $(hdrdir)/ruby/internal/intern/time.h
+cparse.o: $(hdrdir)/ruby/internal/intern/variable.h
+cparse.o: $(hdrdir)/ruby/internal/intern/vm.h
+cparse.o: $(hdrdir)/ruby/internal/interpreter.h
+cparse.o: $(hdrdir)/ruby/internal/iterator.h
+cparse.o: $(hdrdir)/ruby/internal/memory.h
+cparse.o: $(hdrdir)/ruby/internal/method.h
+cparse.o: $(hdrdir)/ruby/internal/module.h
+cparse.o: $(hdrdir)/ruby/internal/newobj.h
+cparse.o: $(hdrdir)/ruby/internal/rgengc.h
+cparse.o: $(hdrdir)/ruby/internal/scan_args.h
+cparse.o: $(hdrdir)/ruby/internal/special_consts.h
+cparse.o: $(hdrdir)/ruby/internal/static_assert.h
+cparse.o: $(hdrdir)/ruby/internal/stdalign.h
+cparse.o: $(hdrdir)/ruby/internal/stdbool.h
+cparse.o: $(hdrdir)/ruby/internal/symbol.h
+cparse.o: $(hdrdir)/ruby/internal/token_paste.h
+cparse.o: $(hdrdir)/ruby/internal/value.h
+cparse.o: $(hdrdir)/ruby/internal/value_type.h
+cparse.o: $(hdrdir)/ruby/internal/variable.h
+cparse.o: $(hdrdir)/ruby/internal/warning_push.h
+cparse.o: $(hdrdir)/ruby/internal/xmalloc.h
cparse.o: $(hdrdir)/ruby/assert.h
cparse.o: $(hdrdir)/ruby/backward.h
+cparse.o: $(hdrdir)/ruby/backward/2/assume.h
+cparse.o: $(hdrdir)/ruby/backward/2/attributes.h
+cparse.o: $(hdrdir)/ruby/backward/2/bool.h
+cparse.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+cparse.o: $(hdrdir)/ruby/backward/2/inttypes.h
+cparse.o: $(hdrdir)/ruby/backward/2/limits.h
+cparse.o: $(hdrdir)/ruby/backward/2/long_long.h
+cparse.o: $(hdrdir)/ruby/backward/2/stdalign.h
+cparse.o: $(hdrdir)/ruby/backward/2/stdarg.h
cparse.o: $(hdrdir)/ruby/defines.h
cparse.o: $(hdrdir)/ruby/intern.h
cparse.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/racc/cparse/extconf.rb b/ext/racc/cparse/extconf.rb
index 47b455d992..3b4f594b9d 100644
--- a/ext/racc/cparse/extconf.rb
+++ b/ext/racc/cparse/extconf.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: false
-# $Id: a9187b5bc40e6adf05e7b6ee5b370b39a3429ecd $
+#
require 'mkmf'
diff --git a/ext/rbconfig/sizeof/depend b/ext/rbconfig/sizeof/depend
index 9433dd4156..09b62961c0 100644
--- a/ext/rbconfig/sizeof/depend
+++ b/ext/rbconfig/sizeof/depend
@@ -16,8 +16,157 @@ sizes.c: $(top_srcdir)/tool/generic_erb.rb \
# AUTOGENERATED DEPENDENCIES START
limits.o: $(RUBY_EXTCONF_H)
limits.o: $(arch_hdrdir)/ruby/config.h
+limits.o: $(hdrdir)/ruby/internal/anyargs.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+limits.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+limits.o: $(hdrdir)/ruby/internal/assume.h
+limits.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+limits.o: $(hdrdir)/ruby/internal/attr/artificial.h
+limits.o: $(hdrdir)/ruby/internal/attr/cold.h
+limits.o: $(hdrdir)/ruby/internal/attr/const.h
+limits.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+limits.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+limits.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+limits.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+limits.o: $(hdrdir)/ruby/internal/attr/error.h
+limits.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+limits.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+limits.o: $(hdrdir)/ruby/internal/attr/format.h
+limits.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+limits.o: $(hdrdir)/ruby/internal/attr/noalias.h
+limits.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+limits.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+limits.o: $(hdrdir)/ruby/internal/attr/noinline.h
+limits.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+limits.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+limits.o: $(hdrdir)/ruby/internal/attr/pure.h
+limits.o: $(hdrdir)/ruby/internal/attr/restrict.h
+limits.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+limits.o: $(hdrdir)/ruby/internal/attr/warning.h
+limits.o: $(hdrdir)/ruby/internal/attr/weakref.h
+limits.o: $(hdrdir)/ruby/internal/cast.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+limits.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+limits.o: $(hdrdir)/ruby/internal/compiler_since.h
+limits.o: $(hdrdir)/ruby/internal/config.h
+limits.o: $(hdrdir)/ruby/internal/constant_p.h
+limits.o: $(hdrdir)/ruby/internal/core.h
+limits.o: $(hdrdir)/ruby/internal/core/rarray.h
+limits.o: $(hdrdir)/ruby/internal/core/rbasic.h
+limits.o: $(hdrdir)/ruby/internal/core/rbignum.h
+limits.o: $(hdrdir)/ruby/internal/core/rclass.h
+limits.o: $(hdrdir)/ruby/internal/core/rdata.h
+limits.o: $(hdrdir)/ruby/internal/core/rfile.h
+limits.o: $(hdrdir)/ruby/internal/core/rhash.h
+limits.o: $(hdrdir)/ruby/internal/core/robject.h
+limits.o: $(hdrdir)/ruby/internal/core/rregexp.h
+limits.o: $(hdrdir)/ruby/internal/core/rstring.h
+limits.o: $(hdrdir)/ruby/internal/core/rstruct.h
+limits.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+limits.o: $(hdrdir)/ruby/internal/ctype.h
+limits.o: $(hdrdir)/ruby/internal/dllexport.h
+limits.o: $(hdrdir)/ruby/internal/dosish.h
+limits.o: $(hdrdir)/ruby/internal/error.h
+limits.o: $(hdrdir)/ruby/internal/eval.h
+limits.o: $(hdrdir)/ruby/internal/event.h
+limits.o: $(hdrdir)/ruby/internal/fl_type.h
+limits.o: $(hdrdir)/ruby/internal/gc.h
+limits.o: $(hdrdir)/ruby/internal/glob.h
+limits.o: $(hdrdir)/ruby/internal/globals.h
+limits.o: $(hdrdir)/ruby/internal/has/attribute.h
+limits.o: $(hdrdir)/ruby/internal/has/builtin.h
+limits.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+limits.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+limits.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+limits.o: $(hdrdir)/ruby/internal/has/extension.h
+limits.o: $(hdrdir)/ruby/internal/has/feature.h
+limits.o: $(hdrdir)/ruby/internal/has/warning.h
+limits.o: $(hdrdir)/ruby/internal/intern/array.h
+limits.o: $(hdrdir)/ruby/internal/intern/bignum.h
+limits.o: $(hdrdir)/ruby/internal/intern/class.h
+limits.o: $(hdrdir)/ruby/internal/intern/compar.h
+limits.o: $(hdrdir)/ruby/internal/intern/complex.h
+limits.o: $(hdrdir)/ruby/internal/intern/cont.h
+limits.o: $(hdrdir)/ruby/internal/intern/dir.h
+limits.o: $(hdrdir)/ruby/internal/intern/enum.h
+limits.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+limits.o: $(hdrdir)/ruby/internal/intern/error.h
+limits.o: $(hdrdir)/ruby/internal/intern/eval.h
+limits.o: $(hdrdir)/ruby/internal/intern/file.h
+limits.o: $(hdrdir)/ruby/internal/intern/gc.h
+limits.o: $(hdrdir)/ruby/internal/intern/hash.h
+limits.o: $(hdrdir)/ruby/internal/intern/io.h
+limits.o: $(hdrdir)/ruby/internal/intern/load.h
+limits.o: $(hdrdir)/ruby/internal/intern/marshal.h
+limits.o: $(hdrdir)/ruby/internal/intern/numeric.h
+limits.o: $(hdrdir)/ruby/internal/intern/object.h
+limits.o: $(hdrdir)/ruby/internal/intern/parse.h
+limits.o: $(hdrdir)/ruby/internal/intern/proc.h
+limits.o: $(hdrdir)/ruby/internal/intern/process.h
+limits.o: $(hdrdir)/ruby/internal/intern/random.h
+limits.o: $(hdrdir)/ruby/internal/intern/range.h
+limits.o: $(hdrdir)/ruby/internal/intern/rational.h
+limits.o: $(hdrdir)/ruby/internal/intern/re.h
+limits.o: $(hdrdir)/ruby/internal/intern/ruby.h
+limits.o: $(hdrdir)/ruby/internal/intern/select.h
+limits.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+limits.o: $(hdrdir)/ruby/internal/intern/signal.h
+limits.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+limits.o: $(hdrdir)/ruby/internal/intern/string.h
+limits.o: $(hdrdir)/ruby/internal/intern/struct.h
+limits.o: $(hdrdir)/ruby/internal/intern/thread.h
+limits.o: $(hdrdir)/ruby/internal/intern/time.h
+limits.o: $(hdrdir)/ruby/internal/intern/variable.h
+limits.o: $(hdrdir)/ruby/internal/intern/vm.h
+limits.o: $(hdrdir)/ruby/internal/interpreter.h
+limits.o: $(hdrdir)/ruby/internal/iterator.h
+limits.o: $(hdrdir)/ruby/internal/memory.h
+limits.o: $(hdrdir)/ruby/internal/method.h
+limits.o: $(hdrdir)/ruby/internal/module.h
+limits.o: $(hdrdir)/ruby/internal/newobj.h
+limits.o: $(hdrdir)/ruby/internal/rgengc.h
+limits.o: $(hdrdir)/ruby/internal/scan_args.h
+limits.o: $(hdrdir)/ruby/internal/special_consts.h
+limits.o: $(hdrdir)/ruby/internal/static_assert.h
+limits.o: $(hdrdir)/ruby/internal/stdalign.h
+limits.o: $(hdrdir)/ruby/internal/stdbool.h
+limits.o: $(hdrdir)/ruby/internal/symbol.h
+limits.o: $(hdrdir)/ruby/internal/token_paste.h
+limits.o: $(hdrdir)/ruby/internal/value.h
+limits.o: $(hdrdir)/ruby/internal/value_type.h
+limits.o: $(hdrdir)/ruby/internal/variable.h
+limits.o: $(hdrdir)/ruby/internal/warning_push.h
+limits.o: $(hdrdir)/ruby/internal/xmalloc.h
limits.o: $(hdrdir)/ruby/assert.h
limits.o: $(hdrdir)/ruby/backward.h
+limits.o: $(hdrdir)/ruby/backward/2/assume.h
+limits.o: $(hdrdir)/ruby/backward/2/attributes.h
+limits.o: $(hdrdir)/ruby/backward/2/bool.h
+limits.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+limits.o: $(hdrdir)/ruby/backward/2/inttypes.h
+limits.o: $(hdrdir)/ruby/backward/2/limits.h
+limits.o: $(hdrdir)/ruby/backward/2/long_long.h
+limits.o: $(hdrdir)/ruby/backward/2/stdalign.h
+limits.o: $(hdrdir)/ruby/backward/2/stdarg.h
limits.o: $(hdrdir)/ruby/defines.h
limits.o: $(hdrdir)/ruby/intern.h
limits.o: $(hdrdir)/ruby/missing.h
@@ -27,8 +176,157 @@ limits.o: $(hdrdir)/ruby/subst.h
limits.o: limits.c
sizes.o: $(RUBY_EXTCONF_H)
sizes.o: $(arch_hdrdir)/ruby/config.h
+sizes.o: $(hdrdir)/ruby/internal/anyargs.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sizes.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sizes.o: $(hdrdir)/ruby/internal/assume.h
+sizes.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sizes.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sizes.o: $(hdrdir)/ruby/internal/attr/cold.h
+sizes.o: $(hdrdir)/ruby/internal/attr/const.h
+sizes.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sizes.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sizes.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sizes.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sizes.o: $(hdrdir)/ruby/internal/attr/error.h
+sizes.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sizes.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sizes.o: $(hdrdir)/ruby/internal/attr/format.h
+sizes.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sizes.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sizes.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sizes.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sizes.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sizes.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sizes.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sizes.o: $(hdrdir)/ruby/internal/attr/pure.h
+sizes.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sizes.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sizes.o: $(hdrdir)/ruby/internal/attr/warning.h
+sizes.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sizes.o: $(hdrdir)/ruby/internal/cast.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sizes.o: $(hdrdir)/ruby/internal/compiler_since.h
+sizes.o: $(hdrdir)/ruby/internal/config.h
+sizes.o: $(hdrdir)/ruby/internal/constant_p.h
+sizes.o: $(hdrdir)/ruby/internal/core.h
+sizes.o: $(hdrdir)/ruby/internal/core/rarray.h
+sizes.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sizes.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sizes.o: $(hdrdir)/ruby/internal/core/rclass.h
+sizes.o: $(hdrdir)/ruby/internal/core/rdata.h
+sizes.o: $(hdrdir)/ruby/internal/core/rfile.h
+sizes.o: $(hdrdir)/ruby/internal/core/rhash.h
+sizes.o: $(hdrdir)/ruby/internal/core/robject.h
+sizes.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sizes.o: $(hdrdir)/ruby/internal/core/rstring.h
+sizes.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sizes.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sizes.o: $(hdrdir)/ruby/internal/ctype.h
+sizes.o: $(hdrdir)/ruby/internal/dllexport.h
+sizes.o: $(hdrdir)/ruby/internal/dosish.h
+sizes.o: $(hdrdir)/ruby/internal/error.h
+sizes.o: $(hdrdir)/ruby/internal/eval.h
+sizes.o: $(hdrdir)/ruby/internal/event.h
+sizes.o: $(hdrdir)/ruby/internal/fl_type.h
+sizes.o: $(hdrdir)/ruby/internal/gc.h
+sizes.o: $(hdrdir)/ruby/internal/glob.h
+sizes.o: $(hdrdir)/ruby/internal/globals.h
+sizes.o: $(hdrdir)/ruby/internal/has/attribute.h
+sizes.o: $(hdrdir)/ruby/internal/has/builtin.h
+sizes.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sizes.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sizes.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sizes.o: $(hdrdir)/ruby/internal/has/extension.h
+sizes.o: $(hdrdir)/ruby/internal/has/feature.h
+sizes.o: $(hdrdir)/ruby/internal/has/warning.h
+sizes.o: $(hdrdir)/ruby/internal/intern/array.h
+sizes.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sizes.o: $(hdrdir)/ruby/internal/intern/class.h
+sizes.o: $(hdrdir)/ruby/internal/intern/compar.h
+sizes.o: $(hdrdir)/ruby/internal/intern/complex.h
+sizes.o: $(hdrdir)/ruby/internal/intern/cont.h
+sizes.o: $(hdrdir)/ruby/internal/intern/dir.h
+sizes.o: $(hdrdir)/ruby/internal/intern/enum.h
+sizes.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sizes.o: $(hdrdir)/ruby/internal/intern/error.h
+sizes.o: $(hdrdir)/ruby/internal/intern/eval.h
+sizes.o: $(hdrdir)/ruby/internal/intern/file.h
+sizes.o: $(hdrdir)/ruby/internal/intern/gc.h
+sizes.o: $(hdrdir)/ruby/internal/intern/hash.h
+sizes.o: $(hdrdir)/ruby/internal/intern/io.h
+sizes.o: $(hdrdir)/ruby/internal/intern/load.h
+sizes.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sizes.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sizes.o: $(hdrdir)/ruby/internal/intern/object.h
+sizes.o: $(hdrdir)/ruby/internal/intern/parse.h
+sizes.o: $(hdrdir)/ruby/internal/intern/proc.h
+sizes.o: $(hdrdir)/ruby/internal/intern/process.h
+sizes.o: $(hdrdir)/ruby/internal/intern/random.h
+sizes.o: $(hdrdir)/ruby/internal/intern/range.h
+sizes.o: $(hdrdir)/ruby/internal/intern/rational.h
+sizes.o: $(hdrdir)/ruby/internal/intern/re.h
+sizes.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sizes.o: $(hdrdir)/ruby/internal/intern/select.h
+sizes.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sizes.o: $(hdrdir)/ruby/internal/intern/signal.h
+sizes.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sizes.o: $(hdrdir)/ruby/internal/intern/string.h
+sizes.o: $(hdrdir)/ruby/internal/intern/struct.h
+sizes.o: $(hdrdir)/ruby/internal/intern/thread.h
+sizes.o: $(hdrdir)/ruby/internal/intern/time.h
+sizes.o: $(hdrdir)/ruby/internal/intern/variable.h
+sizes.o: $(hdrdir)/ruby/internal/intern/vm.h
+sizes.o: $(hdrdir)/ruby/internal/interpreter.h
+sizes.o: $(hdrdir)/ruby/internal/iterator.h
+sizes.o: $(hdrdir)/ruby/internal/memory.h
+sizes.o: $(hdrdir)/ruby/internal/method.h
+sizes.o: $(hdrdir)/ruby/internal/module.h
+sizes.o: $(hdrdir)/ruby/internal/newobj.h
+sizes.o: $(hdrdir)/ruby/internal/rgengc.h
+sizes.o: $(hdrdir)/ruby/internal/scan_args.h
+sizes.o: $(hdrdir)/ruby/internal/special_consts.h
+sizes.o: $(hdrdir)/ruby/internal/static_assert.h
+sizes.o: $(hdrdir)/ruby/internal/stdalign.h
+sizes.o: $(hdrdir)/ruby/internal/stdbool.h
+sizes.o: $(hdrdir)/ruby/internal/symbol.h
+sizes.o: $(hdrdir)/ruby/internal/token_paste.h
+sizes.o: $(hdrdir)/ruby/internal/value.h
+sizes.o: $(hdrdir)/ruby/internal/value_type.h
+sizes.o: $(hdrdir)/ruby/internal/variable.h
+sizes.o: $(hdrdir)/ruby/internal/warning_push.h
+sizes.o: $(hdrdir)/ruby/internal/xmalloc.h
sizes.o: $(hdrdir)/ruby/assert.h
sizes.o: $(hdrdir)/ruby/backward.h
+sizes.o: $(hdrdir)/ruby/backward/2/assume.h
+sizes.o: $(hdrdir)/ruby/backward/2/attributes.h
+sizes.o: $(hdrdir)/ruby/backward/2/bool.h
+sizes.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+sizes.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sizes.o: $(hdrdir)/ruby/backward/2/limits.h
+sizes.o: $(hdrdir)/ruby/backward/2/long_long.h
+sizes.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sizes.o: $(hdrdir)/ruby/backward/2/stdarg.h
sizes.o: $(hdrdir)/ruby/defines.h
sizes.o: $(hdrdir)/ruby/intern.h
sizes.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/readline/depend b/ext/readline/depend
index 2dde7fca58..a6ad681cd0 100644
--- a/ext/readline/depend
+++ b/ext/readline/depend
@@ -3,9 +3,158 @@ readline.o: $(RUBY_EXTCONF_H)
readline.o: $(arch_hdrdir)/ruby/config.h
readline.o: $(hdrdir)/ruby/assert.h
readline.o: $(hdrdir)/ruby/backward.h
+readline.o: $(hdrdir)/ruby/backward/2/assume.h
+readline.o: $(hdrdir)/ruby/backward/2/attributes.h
+readline.o: $(hdrdir)/ruby/backward/2/bool.h
+readline.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+readline.o: $(hdrdir)/ruby/backward/2/inttypes.h
+readline.o: $(hdrdir)/ruby/backward/2/limits.h
+readline.o: $(hdrdir)/ruby/backward/2/long_long.h
+readline.o: $(hdrdir)/ruby/backward/2/stdalign.h
+readline.o: $(hdrdir)/ruby/backward/2/stdarg.h
readline.o: $(hdrdir)/ruby/defines.h
readline.o: $(hdrdir)/ruby/encoding.h
readline.o: $(hdrdir)/ruby/intern.h
+readline.o: $(hdrdir)/ruby/internal/anyargs.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+readline.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+readline.o: $(hdrdir)/ruby/internal/assume.h
+readline.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+readline.o: $(hdrdir)/ruby/internal/attr/artificial.h
+readline.o: $(hdrdir)/ruby/internal/attr/cold.h
+readline.o: $(hdrdir)/ruby/internal/attr/const.h
+readline.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+readline.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+readline.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+readline.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+readline.o: $(hdrdir)/ruby/internal/attr/error.h
+readline.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+readline.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+readline.o: $(hdrdir)/ruby/internal/attr/format.h
+readline.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+readline.o: $(hdrdir)/ruby/internal/attr/noalias.h
+readline.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+readline.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+readline.o: $(hdrdir)/ruby/internal/attr/noinline.h
+readline.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+readline.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+readline.o: $(hdrdir)/ruby/internal/attr/pure.h
+readline.o: $(hdrdir)/ruby/internal/attr/restrict.h
+readline.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+readline.o: $(hdrdir)/ruby/internal/attr/warning.h
+readline.o: $(hdrdir)/ruby/internal/attr/weakref.h
+readline.o: $(hdrdir)/ruby/internal/cast.h
+readline.o: $(hdrdir)/ruby/internal/compiler_is.h
+readline.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+readline.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+readline.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+readline.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+readline.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+readline.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+readline.o: $(hdrdir)/ruby/internal/compiler_since.h
+readline.o: $(hdrdir)/ruby/internal/config.h
+readline.o: $(hdrdir)/ruby/internal/constant_p.h
+readline.o: $(hdrdir)/ruby/internal/core.h
+readline.o: $(hdrdir)/ruby/internal/core/rarray.h
+readline.o: $(hdrdir)/ruby/internal/core/rbasic.h
+readline.o: $(hdrdir)/ruby/internal/core/rbignum.h
+readline.o: $(hdrdir)/ruby/internal/core/rclass.h
+readline.o: $(hdrdir)/ruby/internal/core/rdata.h
+readline.o: $(hdrdir)/ruby/internal/core/rfile.h
+readline.o: $(hdrdir)/ruby/internal/core/rhash.h
+readline.o: $(hdrdir)/ruby/internal/core/robject.h
+readline.o: $(hdrdir)/ruby/internal/core/rregexp.h
+readline.o: $(hdrdir)/ruby/internal/core/rstring.h
+readline.o: $(hdrdir)/ruby/internal/core/rstruct.h
+readline.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+readline.o: $(hdrdir)/ruby/internal/ctype.h
+readline.o: $(hdrdir)/ruby/internal/dllexport.h
+readline.o: $(hdrdir)/ruby/internal/dosish.h
+readline.o: $(hdrdir)/ruby/internal/error.h
+readline.o: $(hdrdir)/ruby/internal/eval.h
+readline.o: $(hdrdir)/ruby/internal/event.h
+readline.o: $(hdrdir)/ruby/internal/fl_type.h
+readline.o: $(hdrdir)/ruby/internal/gc.h
+readline.o: $(hdrdir)/ruby/internal/glob.h
+readline.o: $(hdrdir)/ruby/internal/globals.h
+readline.o: $(hdrdir)/ruby/internal/has/attribute.h
+readline.o: $(hdrdir)/ruby/internal/has/builtin.h
+readline.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+readline.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+readline.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+readline.o: $(hdrdir)/ruby/internal/has/extension.h
+readline.o: $(hdrdir)/ruby/internal/has/feature.h
+readline.o: $(hdrdir)/ruby/internal/has/warning.h
+readline.o: $(hdrdir)/ruby/internal/intern/array.h
+readline.o: $(hdrdir)/ruby/internal/intern/bignum.h
+readline.o: $(hdrdir)/ruby/internal/intern/class.h
+readline.o: $(hdrdir)/ruby/internal/intern/compar.h
+readline.o: $(hdrdir)/ruby/internal/intern/complex.h
+readline.o: $(hdrdir)/ruby/internal/intern/cont.h
+readline.o: $(hdrdir)/ruby/internal/intern/dir.h
+readline.o: $(hdrdir)/ruby/internal/intern/enum.h
+readline.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+readline.o: $(hdrdir)/ruby/internal/intern/error.h
+readline.o: $(hdrdir)/ruby/internal/intern/eval.h
+readline.o: $(hdrdir)/ruby/internal/intern/file.h
+readline.o: $(hdrdir)/ruby/internal/intern/gc.h
+readline.o: $(hdrdir)/ruby/internal/intern/hash.h
+readline.o: $(hdrdir)/ruby/internal/intern/io.h
+readline.o: $(hdrdir)/ruby/internal/intern/load.h
+readline.o: $(hdrdir)/ruby/internal/intern/marshal.h
+readline.o: $(hdrdir)/ruby/internal/intern/numeric.h
+readline.o: $(hdrdir)/ruby/internal/intern/object.h
+readline.o: $(hdrdir)/ruby/internal/intern/parse.h
+readline.o: $(hdrdir)/ruby/internal/intern/proc.h
+readline.o: $(hdrdir)/ruby/internal/intern/process.h
+readline.o: $(hdrdir)/ruby/internal/intern/random.h
+readline.o: $(hdrdir)/ruby/internal/intern/range.h
+readline.o: $(hdrdir)/ruby/internal/intern/rational.h
+readline.o: $(hdrdir)/ruby/internal/intern/re.h
+readline.o: $(hdrdir)/ruby/internal/intern/ruby.h
+readline.o: $(hdrdir)/ruby/internal/intern/select.h
+readline.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+readline.o: $(hdrdir)/ruby/internal/intern/signal.h
+readline.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+readline.o: $(hdrdir)/ruby/internal/intern/string.h
+readline.o: $(hdrdir)/ruby/internal/intern/struct.h
+readline.o: $(hdrdir)/ruby/internal/intern/thread.h
+readline.o: $(hdrdir)/ruby/internal/intern/time.h
+readline.o: $(hdrdir)/ruby/internal/intern/variable.h
+readline.o: $(hdrdir)/ruby/internal/intern/vm.h
+readline.o: $(hdrdir)/ruby/internal/interpreter.h
+readline.o: $(hdrdir)/ruby/internal/iterator.h
+readline.o: $(hdrdir)/ruby/internal/memory.h
+readline.o: $(hdrdir)/ruby/internal/method.h
+readline.o: $(hdrdir)/ruby/internal/module.h
+readline.o: $(hdrdir)/ruby/internal/newobj.h
+readline.o: $(hdrdir)/ruby/internal/rgengc.h
+readline.o: $(hdrdir)/ruby/internal/scan_args.h
+readline.o: $(hdrdir)/ruby/internal/special_consts.h
+readline.o: $(hdrdir)/ruby/internal/static_assert.h
+readline.o: $(hdrdir)/ruby/internal/stdalign.h
+readline.o: $(hdrdir)/ruby/internal/stdbool.h
+readline.o: $(hdrdir)/ruby/internal/symbol.h
+readline.o: $(hdrdir)/ruby/internal/token_paste.h
+readline.o: $(hdrdir)/ruby/internal/value.h
+readline.o: $(hdrdir)/ruby/internal/value_type.h
+readline.o: $(hdrdir)/ruby/internal/variable.h
+readline.o: $(hdrdir)/ruby/internal/warning_push.h
+readline.o: $(hdrdir)/ruby/internal/xmalloc.h
readline.o: $(hdrdir)/ruby/io.h
readline.o: $(hdrdir)/ruby/missing.h
readline.o: $(hdrdir)/ruby/onigmo.h
diff --git a/ext/readline/depend-gem b/ext/readline/depend-gem
new file mode 100644
index 0000000000..df01bd2a86
--- /dev/null
+++ b/ext/readline/depend-gem
@@ -0,0 +1,4 @@
+# AUTOGENERATED DEPENDENCIES START
+readline.o: $(RUBY_EXTCONF_H)
+readline.o: readline.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/readline/readline-ext.gemspec b/ext/readline/readline-ext.gemspec
index 66db14d14a..55dd591e1a 100644
--- a/ext/readline/readline-ext.gemspec
+++ b/ext/readline/readline-ext.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "readline-ext"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 646be2b194..9f76f90e41 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -78,7 +78,7 @@ static ID id_special_prefixes;
#ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION
# define rl_username_completion_function username_completion_function
#else
-char *rl_username_completion_function(const char *, int);
+RUBY_EXTERN char *rl_username_completion_function(const char *, int);
#endif
#ifndef HAVE_RL_COMPLETION_MATCHES
# define rl_completion_matches completion_matches
@@ -689,7 +689,7 @@ readline_s_insert_text(VALUE self, VALUE str)
#endif
#if defined(HAVE_RL_DELETE_TEXT)
-int rl_delete_text(int, int);
+RUBY_EXTERN int rl_delete_text(int, int);
static const char *
str_subpos(const char *ptr, const char *end, long beg, long *sublen, rb_encoding *enc)
{
@@ -1148,7 +1148,7 @@ readline_s_get_screen_size(VALUE self)
#endif
#ifdef HAVE_RL_VI_EDITING_MODE
-int rl_vi_editing_mode(int, int);
+RUBY_EXTERN int rl_vi_editing_mode(int, int);
/*
* call-seq:
* Readline.vi_editing_mode -> nil
@@ -1187,7 +1187,7 @@ readline_s_vi_editing_mode_p(VALUE self)
#endif
#ifdef HAVE_RL_EMACS_EDITING_MODE
-int rl_emacs_editing_mode(int, int);
+RUBY_EXTERN int rl_emacs_editing_mode(int, int);
/*
* call-seq:
* Readline.emacs_editing_mode -> nil
@@ -1672,7 +1672,7 @@ readline_s_get_filename_quote_characters(VALUE self)
#endif
#ifdef HAVE_RL_REFRESH_LINE
-int rl_refresh_line(int, int);
+RUBY_EXTERN int rl_refresh_line(int, int);
/*
* call-seq:
* Readline.refresh_line -> nil
@@ -1919,7 +1919,7 @@ username_completion_proc_call(VALUE self, VALUE str)
}
#ifdef HAVE_RL_CLEAR_SIGNALS
-int rl_clear_signals(void);
+RUBY_EXTERN int rl_clear_signals(void);
#endif
#undef rb_intern
@@ -2060,7 +2060,7 @@ Init_readline(void)
* The history buffer. It extends Enumerable module, so it behaves
* just like an array.
* For example, gets the fifth content that the user input by
- * HISTORY[4].
+ * <code>HISTORY[4]</code>.
*/
rb_define_const(mReadline, "HISTORY", history);
diff --git a/ext/ripper/depend b/ext/ripper/depend
index 69759ec716..4ce522fbc3 100644
--- a/ext/ripper/depend
+++ b/ext/ripper/depend
@@ -22,6 +22,7 @@ ripper.y: $(srcdir)/tools/preproc.rb $(srcdir)/tools/dsl.rb $(top_srcdir)/parse.
$(Q) $(RUBY) $(top_srcdir)/tool/id2token.rb --path-separator=.$(PATH_SEPARATOR)./ \
--vpath=$(VPATH)$(PATH_SEPARATOR)$(top_srcdir) id.h $(top_srcdir)/parse.y > ripper.tmp.y
$(Q) $(RUBY) $(top_srcdir)/tool/pure_parser.rb ripper.tmp.y $(BISON)
+ $(Q) $(RM) ripper.tmp.y.bak
$(Q) $(RUBY) $(srcdir)/tools/preproc.rb ripper.tmp.y --output=$@
$(Q) $(RM) ripper.tmp.y
@@ -53,20 +54,199 @@ ripper.o: $(arch_hdrdir)/ruby/config.h
ripper.o: $(hdrdir)/ruby.h
ripper.o: $(hdrdir)/ruby/assert.h
ripper.o: $(hdrdir)/ruby/backward.h
+ripper.o: $(hdrdir)/ruby/backward/2/assume.h
+ripper.o: $(hdrdir)/ruby/backward/2/attributes.h
+ripper.o: $(hdrdir)/ruby/backward/2/bool.h
+ripper.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ripper.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ripper.o: $(hdrdir)/ruby/backward/2/limits.h
+ripper.o: $(hdrdir)/ruby/backward/2/long_long.h
+ripper.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ripper.o: $(hdrdir)/ruby/backward/2/stdarg.h
ripper.o: $(hdrdir)/ruby/defines.h
ripper.o: $(hdrdir)/ruby/encoding.h
ripper.o: $(hdrdir)/ruby/intern.h
+ripper.o: $(hdrdir)/ruby/internal/anyargs.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ripper.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ripper.o: $(hdrdir)/ruby/internal/assume.h
+ripper.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ripper.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ripper.o: $(hdrdir)/ruby/internal/attr/cold.h
+ripper.o: $(hdrdir)/ruby/internal/attr/const.h
+ripper.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ripper.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ripper.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ripper.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ripper.o: $(hdrdir)/ruby/internal/attr/error.h
+ripper.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ripper.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ripper.o: $(hdrdir)/ruby/internal/attr/format.h
+ripper.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ripper.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ripper.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ripper.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ripper.o: $(hdrdir)/ruby/internal/attr/pure.h
+ripper.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ripper.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ripper.o: $(hdrdir)/ruby/internal/attr/warning.h
+ripper.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ripper.o: $(hdrdir)/ruby/internal/cast.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ripper.o: $(hdrdir)/ruby/internal/compiler_since.h
+ripper.o: $(hdrdir)/ruby/internal/config.h
+ripper.o: $(hdrdir)/ruby/internal/constant_p.h
+ripper.o: $(hdrdir)/ruby/internal/core.h
+ripper.o: $(hdrdir)/ruby/internal/core/rarray.h
+ripper.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ripper.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ripper.o: $(hdrdir)/ruby/internal/core/rclass.h
+ripper.o: $(hdrdir)/ruby/internal/core/rdata.h
+ripper.o: $(hdrdir)/ruby/internal/core/rfile.h
+ripper.o: $(hdrdir)/ruby/internal/core/rhash.h
+ripper.o: $(hdrdir)/ruby/internal/core/robject.h
+ripper.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ripper.o: $(hdrdir)/ruby/internal/core/rstring.h
+ripper.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ripper.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ripper.o: $(hdrdir)/ruby/internal/ctype.h
+ripper.o: $(hdrdir)/ruby/internal/dllexport.h
+ripper.o: $(hdrdir)/ruby/internal/dosish.h
+ripper.o: $(hdrdir)/ruby/internal/error.h
+ripper.o: $(hdrdir)/ruby/internal/eval.h
+ripper.o: $(hdrdir)/ruby/internal/event.h
+ripper.o: $(hdrdir)/ruby/internal/fl_type.h
+ripper.o: $(hdrdir)/ruby/internal/gc.h
+ripper.o: $(hdrdir)/ruby/internal/glob.h
+ripper.o: $(hdrdir)/ruby/internal/globals.h
+ripper.o: $(hdrdir)/ruby/internal/has/attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/builtin.h
+ripper.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ripper.o: $(hdrdir)/ruby/internal/has/extension.h
+ripper.o: $(hdrdir)/ruby/internal/has/feature.h
+ripper.o: $(hdrdir)/ruby/internal/has/warning.h
+ripper.o: $(hdrdir)/ruby/internal/intern/array.h
+ripper.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ripper.o: $(hdrdir)/ruby/internal/intern/class.h
+ripper.o: $(hdrdir)/ruby/internal/intern/compar.h
+ripper.o: $(hdrdir)/ruby/internal/intern/complex.h
+ripper.o: $(hdrdir)/ruby/internal/intern/cont.h
+ripper.o: $(hdrdir)/ruby/internal/intern/dir.h
+ripper.o: $(hdrdir)/ruby/internal/intern/enum.h
+ripper.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ripper.o: $(hdrdir)/ruby/internal/intern/error.h
+ripper.o: $(hdrdir)/ruby/internal/intern/eval.h
+ripper.o: $(hdrdir)/ruby/internal/intern/file.h
+ripper.o: $(hdrdir)/ruby/internal/intern/gc.h
+ripper.o: $(hdrdir)/ruby/internal/intern/hash.h
+ripper.o: $(hdrdir)/ruby/internal/intern/io.h
+ripper.o: $(hdrdir)/ruby/internal/intern/load.h
+ripper.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ripper.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ripper.o: $(hdrdir)/ruby/internal/intern/object.h
+ripper.o: $(hdrdir)/ruby/internal/intern/parse.h
+ripper.o: $(hdrdir)/ruby/internal/intern/proc.h
+ripper.o: $(hdrdir)/ruby/internal/intern/process.h
+ripper.o: $(hdrdir)/ruby/internal/intern/random.h
+ripper.o: $(hdrdir)/ruby/internal/intern/range.h
+ripper.o: $(hdrdir)/ruby/internal/intern/rational.h
+ripper.o: $(hdrdir)/ruby/internal/intern/re.h
+ripper.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ripper.o: $(hdrdir)/ruby/internal/intern/select.h
+ripper.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ripper.o: $(hdrdir)/ruby/internal/intern/signal.h
+ripper.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ripper.o: $(hdrdir)/ruby/internal/intern/string.h
+ripper.o: $(hdrdir)/ruby/internal/intern/struct.h
+ripper.o: $(hdrdir)/ruby/internal/intern/thread.h
+ripper.o: $(hdrdir)/ruby/internal/intern/time.h
+ripper.o: $(hdrdir)/ruby/internal/intern/variable.h
+ripper.o: $(hdrdir)/ruby/internal/intern/vm.h
+ripper.o: $(hdrdir)/ruby/internal/interpreter.h
+ripper.o: $(hdrdir)/ruby/internal/iterator.h
+ripper.o: $(hdrdir)/ruby/internal/memory.h
+ripper.o: $(hdrdir)/ruby/internal/method.h
+ripper.o: $(hdrdir)/ruby/internal/module.h
+ripper.o: $(hdrdir)/ruby/internal/newobj.h
+ripper.o: $(hdrdir)/ruby/internal/rgengc.h
+ripper.o: $(hdrdir)/ruby/internal/scan_args.h
+ripper.o: $(hdrdir)/ruby/internal/special_consts.h
+ripper.o: $(hdrdir)/ruby/internal/static_assert.h
+ripper.o: $(hdrdir)/ruby/internal/stdalign.h
+ripper.o: $(hdrdir)/ruby/internal/stdbool.h
+ripper.o: $(hdrdir)/ruby/internal/symbol.h
+ripper.o: $(hdrdir)/ruby/internal/token_paste.h
+ripper.o: $(hdrdir)/ruby/internal/value.h
+ripper.o: $(hdrdir)/ruby/internal/value_type.h
+ripper.o: $(hdrdir)/ruby/internal/variable.h
+ripper.o: $(hdrdir)/ruby/internal/warning_push.h
+ripper.o: $(hdrdir)/ruby/internal/xmalloc.h
+ripper.o: $(hdrdir)/ruby/io.h
ripper.o: $(hdrdir)/ruby/missing.h
ripper.o: $(hdrdir)/ruby/onigmo.h
ripper.o: $(hdrdir)/ruby/oniguruma.h
+ripper.o: $(hdrdir)/ruby/ractor.h
ripper.o: $(hdrdir)/ruby/regex.h
ripper.o: $(hdrdir)/ruby/ruby.h
ripper.o: $(hdrdir)/ruby/st.h
ripper.o: $(hdrdir)/ruby/subst.h
ripper.o: $(hdrdir)/ruby/util.h
+ripper.o: $(top_srcdir)/constant.h
+ripper.o: $(top_srcdir)/id_table.h
ripper.o: $(top_srcdir)/internal.h
+ripper.o: $(top_srcdir)/internal/array.h
+ripper.o: $(top_srcdir)/internal/bignum.h
+ripper.o: $(top_srcdir)/internal/bits.h
+ripper.o: $(top_srcdir)/internal/compile.h
+ripper.o: $(top_srcdir)/internal/compilers.h
+ripper.o: $(top_srcdir)/internal/complex.h
+ripper.o: $(top_srcdir)/internal/error.h
+ripper.o: $(top_srcdir)/internal/fixnum.h
+ripper.o: $(top_srcdir)/internal/gc.h
+ripper.o: $(top_srcdir)/internal/hash.h
+ripper.o: $(top_srcdir)/internal/imemo.h
+ripper.o: $(top_srcdir)/internal/io.h
+ripper.o: $(top_srcdir)/internal/numeric.h
+ripper.o: $(top_srcdir)/internal/parse.h
+ripper.o: $(top_srcdir)/internal/rational.h
+ripper.o: $(top_srcdir)/internal/re.h
+ripper.o: $(top_srcdir)/internal/serial.h
+ripper.o: $(top_srcdir)/internal/static_assert.h
+ripper.o: $(top_srcdir)/internal/string.h
+ripper.o: $(top_srcdir)/internal/symbol.h
+ripper.o: $(top_srcdir)/internal/thread.h
+ripper.o: $(top_srcdir)/internal/util.h
+ripper.o: $(top_srcdir)/internal/variable.h
+ripper.o: $(top_srcdir)/internal/vm.h
+ripper.o: $(top_srcdir)/internal/warnings.h
ripper.o: $(top_srcdir)/node.h
ripper.o: $(top_srcdir)/regenc.h
+ripper.o: $(top_srcdir)/ruby_assert.h
ripper.o: $(top_srcdir)/symbol.h
ripper.o: ../../probes.h
ripper.o: eventids2.c
diff --git a/ext/ripper/eventids2.c b/ext/ripper/eventids2.c
index cdac2081e6..ac38663f2d 100644
--- a/ext/ripper/eventids2.c
+++ b/ext/ripper/eventids2.c
@@ -1,12 +1,20 @@
enum {
tIGNORED_NL = tLAST_TOKEN + 1,
+# define tIGNORED_NL ((enum yytokentype)tIGNORED_NL)
tCOMMENT,
+# define tCOMMENT ((enum yytokentype)tCOMMENT)
tEMBDOC_BEG,
+# define tEMBDOC_BEG ((enum yytokentype)tEMBDOC_BEG)
tEMBDOC,
+# define tEMBDOC ((enum yytokentype)tEMBDOC)
tEMBDOC_END,
+# define tEMBDOC_END ((enum yytokentype)tEMBDOC_END)
tHEREDOC_BEG,
+# define tHEREDOC_BEG ((enum yytokentype)tHEREDOC_BEG)
tHEREDOC_END,
- k__END__
+# define tHEREDOC_END ((enum yytokentype)tHEREDOC_END)
+ k__END__,
+# define k__END__ ((enum yytokentype)k__END__)
};
typedef struct {
diff --git a/ext/ripper/lib/ripper/lexer.rb b/ext/ripper/lib/ripper/lexer.rb
index 9f613c3475..1df1c022c7 100644
--- a/ext/ripper/lib/ripper/lexer.rb
+++ b/ext/ripper/lib/ripper/lexer.rb
@@ -14,17 +14,24 @@ require 'ripper/core'
class Ripper
# Tokenizes the Ruby program and returns an array of strings.
+ # The +filename+ and +lineno+ arguments are mostly ignored, since the
+ # return value is just the tokenized input.
+ # By default, this method does not handle syntax errors in +src+,
+ # use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+.
#
# p Ripper.tokenize("def m(a) nil end")
# # => ["def", " ", "m", "(", "a", ")", " ", "nil", " ", "end"]
#
- def Ripper.tokenize(src, filename = '-', lineno = 1)
- Lexer.new(src, filename, lineno).tokenize
+ def Ripper.tokenize(src, filename = '-', lineno = 1, **kw)
+ Lexer.new(src, filename, lineno).tokenize(**kw)
end
# Tokenizes the Ruby program and returns an array of an array,
# which is formatted like
# <code>[[lineno, column], type, token, state]</code>.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+.
#
# require 'ripper'
# require 'pp'
@@ -41,8 +48,8 @@ class Ripper
# [[1, 12], :on_sp, " ", END ],
# [[1, 13], :on_kw, "end", END ]]
#
- def Ripper.lex(src, filename = '-', lineno = 1)
- Lexer.new(src, filename, lineno).lex
+ def Ripper.lex(src, filename = '-', lineno = 1, **kw)
+ Lexer.new(src, filename, lineno).lex(**kw)
end
class Lexer < ::Ripper #:nodoc: internal use only
@@ -95,17 +102,17 @@ class Ripper
attr_reader :errors
- def tokenize
- parse().sort_by(&:pos).map(&:tok)
+ def tokenize(**kw)
+ parse(**kw).sort_by(&:pos).map(&:tok)
end
- def lex
- parse().sort_by(&:pos).map(&:to_a)
+ def lex(**kw)
+ parse(**kw).sort_by(&:pos).map(&:to_a)
end
# parse the code and returns elements including errors.
- def scan
- result = (parse() + errors + @stack.flatten).uniq.sort_by {|e| [*e.pos, (e.message ? -1 : 0)]}
+ def scan(**kw)
+ result = (parse(**kw) + errors + @stack.flatten).uniq.sort_by {|e| [*e.pos, (e.message ? -1 : 0)]}
result.each_with_index do |e, i|
if e.event == :on_parse_error and e.tok.empty? and (pre = result[i-1]) and
pre.pos[0] == e.pos[0] and (pre.pos[1] + pre.tok.size) == e.pos[1]
@@ -118,13 +125,20 @@ class Ripper
result
end
- def parse
+ def parse(raise_errors: false)
@errors = []
@buf = []
@stack = []
- super
+ super()
+ @buf = @stack.pop unless @stack.empty?
+ if raise_errors and !@errors.empty?
+ raise SyntaxError, @errors.map(&:message).join(' ;')
+ end
@buf.flatten!
- @buf
+ unless (result = @buf).empty?
+ result.concat(@buf) until (@buf = []; super(); @buf.flatten!; @buf.empty?)
+ end
+ result
end
private
@@ -172,14 +186,23 @@ class Ripper
end
def _push_token(tok)
- @buf.push Elem.new([lineno(), column()], __callee__, tok, state())
+ e = Elem.new([lineno(), column()], __callee__, tok, state())
+ @buf.push(e)
+ e
end
- def on_error(mesg)
+ def on_error1(mesg)
@errors.push Elem.new([lineno(), column()], __callee__, token(), state(), mesg)
end
- alias on_parse_error on_error
- alias compile_error on_error
+
+ def on_error2(mesg, elem)
+ @errors.push Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg)
+ end
+ PARSER_EVENTS.grep(/_error\z/) do |e|
+ arity = PARSER_EVENT_TABLE.fetch(e)
+ alias_method "on_#{e}", "on_error#{arity}"
+ end
+ alias compile_error on_error1
(SCANNER_EVENTS.map {|event|:"on_#{event}"} - private_instance_methods(false)).each do |event|
alias_method event, :_push_token
diff --git a/ext/ripper/lib/ripper/sexp.rb b/ext/ripper/lib/ripper/sexp.rb
index e71d52cd45..b1d553b1da 100644
--- a/ext/ripper/lib/ripper/sexp.rb
+++ b/ext/ripper/lib/ripper/sexp.rb
@@ -17,6 +17,10 @@ class Ripper
# Parses +src+ and create S-exp tree.
# Returns more readable tree rather than Ripper.sexp_raw.
# This method is mainly for developer use.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # returning +nil+ in such cases. Use the +raise_errors+ keyword
+ # to raise a SyntaxError for an error in +src+.
#
# require 'ripper'
# require 'pp'
@@ -28,15 +32,25 @@ class Ripper
# [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
# [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]]
#
- def Ripper.sexp(src, filename = '-', lineno = 1)
+ def Ripper.sexp(src, filename = '-', lineno = 1, raise_errors: false)
builder = SexpBuilderPP.new(src, filename, lineno)
sexp = builder.parse
- sexp unless builder.error?
+ if builder.error?
+ if raise_errors
+ raise SyntaxError, builder.error
+ end
+ else
+ sexp
+ end
end
# [EXPERIMENTAL]
# Parses +src+ and create S-exp tree.
# This method is mainly for developer use.
+ # The +filename+ argument is mostly ignored.
+ # By default, this method does not handle syntax errors in +src+,
+ # returning +nil+ in such cases. Use the +raise_errors+ keyword
+ # to raise a SyntaxError for an error in +src+.
#
# require 'ripper'
# require 'pp'
@@ -54,13 +68,21 @@ class Ripper
# nil,
# nil]]]]
#
- def Ripper.sexp_raw(src, filename = '-', lineno = 1)
+ def Ripper.sexp_raw(src, filename = '-', lineno = 1, raise_errors: false)
builder = SexpBuilder.new(src, filename, lineno)
sexp = builder.parse
- sexp unless builder.error?
+ if builder.error?
+ if raise_errors
+ raise SyntaxError, builder.error
+ end
+ else
+ sexp
+ end
end
class SexpBuilder < ::Ripper #:nodoc:
+ attr_reader :error
+
private
def dedent_element(e, width)
@@ -107,6 +129,13 @@ class Ripper
end
End
end
+
+ def on_error(mesg)
+ @error = mesg
+ end
+ remove_method :on_parse_error
+ alias on_parse_error on_error
+ alias compile_error on_error
end
class SexpBuilderPP < SexpBuilder #:nodoc:
diff --git a/ext/ripper/tools/dsl.rb b/ext/ripper/tools/dsl.rb
index d2b9715a71..49ff51711f 100644
--- a/ext/ripper/tools/dsl.rb
+++ b/ext/ripper/tools/dsl.rb
@@ -7,6 +7,9 @@
# v2 = dispatch0(void_stmt);
# $$ = dispatch2(stmts_add, v1, v2);
+$dollar = "$$"
+alias $$ $dollar
+
class DSL
def initialize(code, options)
@events = {}
diff --git a/ext/ripper/tools/preproc.rb b/ext/ripper/tools/preproc.rb
index 7639a901df..b838a78db7 100644
--- a/ext/ripper/tools/preproc.rb
+++ b/ext/ripper/tools/preproc.rb
@@ -45,7 +45,7 @@ def prelude(f, out)
while line = f.gets
case line
when /\A%%/
- out << '%%' << $/
+ out << "%%\n"
return
when /\A%token/
out << line.sub(/<\w+>/, '<val>')
@@ -79,15 +79,15 @@ def grammar(f, out)
while line = f.gets
case line
when %r</\*% *ripper(?:\[(.*?)\])?: *(.*?) *%\*/>
- out << DSL.new($2, ($1 || "").split(",")).generate << $/
+ out << DSL.new($2, ($1 || "").split(",")).generate << "\n"
when %r</\*%%%\*/>
- out << '#if 0' << $/
+ out << "#if 0\n"
when %r</\*%>
- out << '#endif' << $/
+ out << "#endif\n"
when %r<%\*/>
- out << $/
+ out << "\n"
when /\A%%/
- out << '%%' << $/
+ out << "%%\n"
return
else
out << line
diff --git a/ext/sdbm/_sdbm.c b/ext/sdbm/_sdbm.c
deleted file mode 100644
index 3a42b0e569..0000000000
--- a/ext/sdbm/_sdbm.c
+++ /dev/null
@@ -1,952 +0,0 @@
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain.
- *
- * core routines
- */
-
-#include "ruby/ruby.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#include "sdbm.h"
-
-/*
- * sdbm - ndbm work-alike hashed database library
- * tuning and portability constructs [not nearly enough]
- * author: oz@nexus.yorku.ca
- */
-
-#define BYTESIZ 8
-
-#ifdef BSD42
-#define SEEK_SET L_SET
-#define memset(s,c,n) bzero((s), (n)) /* only when c is zero */
-#define memcpy(s1,s2,n) bcopy((s2), (s1), (n))
-#define memcmp(s1,s2,n) bcmp((s1),(s2),(n))
-#endif
-
-/*
- * important tuning parms (hah)
- */
-
-#ifndef SEEDUPS
-#define SEEDUPS 1 /* always detect duplicates */
-#endif
-#ifndef BADMESS
-#define BADMESS 1 /* generate a message for worst case:
- cannot make room after SPLTMAX splits */
-#endif
-
-/*
- * misc
- */
-#ifdef DEBUG
-#define debug(x) printf x
-#else
-#define debug(x)
-#endif
-
-#ifdef BIG_E
-#define GET_SHORT(p, i) (((unsigned)((unsigned char *)(p))[(i)*2] << 8) + (((unsigned char *)(p))[(i)*2 + 1]))
-#define PUT_SHORT(p, i, s) (((unsigned char *)(p))[(i)*2] = (unsigned char)((s) >> 8), ((unsigned char *)(p))[(i)*2 + 1] = (unsigned char)(s))
-#else
-#define GET_SHORT(p, i) ((p)[(i)])
-#define PUT_SHORT(p, i, s) ((p)[(i)] = (s))
-#endif
-
-/*#include "pair.h"*/
-static int fitpair proto((char *, int));
-static void putpair proto((char *, datum, datum));
-static datum getpair proto((char *, datum));
-static int delpair proto((char *, datum));
-static int chkpage proto((char *));
-static datum getnkey proto((char *, int));
-static void splpage proto((char *, char *, long));
-#if SEEDUPS
-static int duppair proto((char *, datum));
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#ifdef DOSISH
-#include <io.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef BSD42
-#include <sys/file.h>
-#else
-#include <fcntl.h>
-/*#include <memory.h>*/
-#endif
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-#include <errno.h>
-#ifndef EPERM
-#define EPERM EACCES
-#endif
-#include <string.h>
-
-#ifdef __STDC__
-#include <stddef.h>
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/*
- * externals
- */
-#if !defined(__sun) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(errno)
-extern int errno;
-#endif
-
-/*
- * forward
- */
-static int getdbit proto((DBM *, long));
-static int setdbit proto((DBM *, long));
-static int getpage proto((DBM *, long));
-static datum getnext proto((DBM *));
-static int makroom proto((DBM *, long, int));
-
-/*
- * useful macros
- */
-#define bad(x) ((x).dptr == NULL || (x).dsize < 0)
-#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
-#define ioerr(db) ((db)->flags |= DBM_IOERR)
-
-#define OFF_PAG(off) (long) (off) * PBLKSIZ
-#define OFF_DIR(off) (long) (off) * DBLKSIZ
-
-static long masks[] = {
- 000000000000L, 000000000001L, 000000000003L,
- 000000000007L, 000000000017L, 000000000037L,
- 000000000077L, 000000000177L, 000000000377L,
- 000000000777L, 000000001777L, 000000003777L,
- 000000007777L, 000000017777L, 000000037777L,
- 000000077777L, 000000177777L, 000000377777L,
- 000000777777L, 000001777777L, 000003777777L,
- 000007777777L, 000017777777L, 000037777777L,
- 000077777777L, 000177777777L, 000377777777L,
- 000777777777L, 001777777777L, 003777777777L,
- 007777777777L, 017777777777L
-};
-
-datum nullitem = {NULL, 0};
-
-DBM *
-sdbm_open(register char *file, register int flags, register int mode)
-{
- register DBM *db;
- register char *dirname;
- register char *pagname;
- register size_t n;
-
- if (file == NULL || !*file)
- return errno = EINVAL, (DBM *) NULL;
-/*
- * need space for two separate filenames
- */
- n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
-
- if ((dirname = malloc(n)) == NULL)
- return errno = ENOMEM, (DBM *) NULL;
-/*
- * build the file names
- */
- dirname = strcat(strcpy(dirname, file), DIRFEXT);
- pagname = strcpy(dirname + strlen(dirname) + 1, file);
- pagname = strcat(pagname, PAGFEXT);
-
- db = sdbm_prep(dirname, pagname, flags, mode);
- free((char *) dirname);
- return db;
-}
-
-static int
-fd_set_cloexec(int fd)
-{
- /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
-#ifdef F_GETFD
- int flags, ret;
- flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
- if (flags == -1) {
- return -1;
- }
- if (2 < fd) {
- if (!(flags & FD_CLOEXEC)) {
- flags |= FD_CLOEXEC;
- ret = fcntl(fd, F_SETFD, flags);
- if (ret == -1) {
- return -1;
- }
- }
- }
-#endif
- return 0;
-}
-
-DBM *
-sdbm_prep(char *dirname, char *pagname, int flags, int mode)
-{
- register DBM *db;
- struct stat dstat;
-
- if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
- return errno = ENOMEM, (DBM *) NULL;
-
- db->pagf = -1;
- db->dirf = -1;
- db->flags = 0;
- db->hmask = 0;
- db->blkptr = 0;
- db->keyptr = 0;
-/*
- * adjust user flags so that WRONLY becomes RDWR,
- * as required by this package. Also set our internal
- * flag for RDONLY.
- */
- if (flags & O_WRONLY)
- flags = (flags & ~O_WRONLY) | O_RDWR;
- if (flags & O_RDONLY)
- db->flags = DBM_RDONLY;
-/*
- * open the files in sequence, and stat the dirfile.
- * If we fail anywhere, undo everything, return NULL.
- */
- flags |= O_BINARY;
-#ifdef O_CLOEXEC
- flags |= O_CLOEXEC;
-#endif
-
- if ((db->pagf = open(pagname, flags, mode)) == -1) goto err;
- if (fd_set_cloexec(db->pagf) == -1) goto err;
- if ((db->dirf = open(dirname, flags, mode)) == -1) goto err;
- if (fd_set_cloexec(db->dirf) == -1) goto err;
-/*
- * need the dirfile size to establish max bit number.
- */
- if (fstat(db->dirf, &dstat) == -1) goto err;
-/*
- * zero size: either a fresh database, or one with a single,
- * unsplit data page: dirpage is all zeros.
- */
- db->dirbno = (!dstat.st_size) ? 0 : -1;
- db->pagbno = -1;
- db->maxbno = dstat.st_size * (long) BYTESIZ;
-
- (void) memset(db->pagbuf, 0, PBLKSIZ);
- (void) memset(db->dirbuf, 0, DBLKSIZ);
-/*
- * success
- */
- return db;
-
- err:
- if (db->pagf != -1)
- (void) close(db->pagf);
- if (db->dirf != -1)
- (void) close(db->dirf);
- free((char *) db);
- return (DBM *) NULL;
-}
-
-void
-sdbm_close(register DBM *db)
-{
- if (db == NULL)
- errno = EINVAL;
- else {
- (void) close(db->dirf);
- (void) close(db->pagf);
- free((char *) db);
- }
-}
-
-datum
-sdbm_fetch(register DBM *db, datum key)
-{
- if (db == NULL || bad(key))
- return errno = EINVAL, nullitem;
-
- if (getpage(db, exhash(key)))
- return getpair(db->pagbuf, key);
-
- return ioerr(db), nullitem;
-}
-
-int
-sdbm_delete(register DBM *db, datum key)
-{
- if (db == NULL || bad(key))
- return errno = EINVAL, -1;
- if (sdbm_rdonly(db))
- return errno = EPERM, -1;
-
- if (getpage(db, exhash(key))) {
- if (!delpair(db->pagbuf, key))
- return -1;
-/*
- * update the page file
- */
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return ioerr(db), -1;
-
- return 0;
- }
-
- return ioerr(db), -1;
-}
-
-int
-sdbm_store(register DBM *db, datum key, datum val, int flags)
-{
- int need;
- register long hash;
-
- if (db == NULL || bad(key))
- return errno = EINVAL, -1;
- if (sdbm_rdonly(db))
- return errno = EPERM, -1;
-
- need = key.dsize + val.dsize;
-/*
- * is the pair too big (or too small) for this database ??
- */
- if (need < 0 || need > PAIRMAX)
- return errno = EINVAL, -1;
-
- if (getpage(db, (hash = exhash(key)))) {
-/*
- * if we need to replace, delete the key/data pair
- * first. If it is not there, ignore.
- */
- if (flags == DBM_REPLACE)
- (void) delpair(db->pagbuf, key);
-#if SEEDUPS
- else if (duppair(db->pagbuf, key))
- return 1;
-#endif
-/*
- * if we do not have enough room, we have to split.
- */
- if (!fitpair(db->pagbuf, need))
- if (!makroom(db, hash, need))
- return ioerr(db), -1;
-/*
- * we have enough room or split is successful. insert the key,
- * and update the page file.
- */
- (void) putpair(db->pagbuf, key, val);
-
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return ioerr(db), -1;
- /*
- * success
- */
- return 0;
- }
-
- return ioerr(db), -1;
-}
-
-/*
- * makroom - make room by splitting the overfull page
- * this routine will attempt to make room for SPLTMAX times before
- * giving up.
- */
-static int
-makroom(register DBM *db, long int hash, int need)
-{
- long newp;
- char twin[PBLKSIZ];
-#if defined _WIN32
- char zer[PBLKSIZ];
- long oldtail;
-#endif
- char *pag = db->pagbuf;
- char *new = twin;
- register int smax = SPLTMAX;
-
- do {
-/*
- * split the current page
- */
- (void) splpage(pag, new, db->hmask + 1);
-/*
- * address of the new page
- */
- newp = (hash & db->hmask) | (db->hmask + 1);
- debug(("newp: %ld\n", newp));
-/*
- * write delay, read avoidance/cache shuffle:
- * select the page for incoming pair: if key is to go to the new page,
- * write out the previous one, and copy the new one over, thus making
- * it the current page. If not, simply write the new page, and we are
- * still looking at the page of interest. current page is not updated
- * here, as sdbm_store will do so, after it inserts the incoming pair.
- */
-
-#if defined _WIN32
- /*
- * Fill hole with 0 if made it.
- * (hole is NOT read as 0)
- */
- oldtail = lseek(db->pagf, 0L, SEEK_END);
- memset(zer, 0, PBLKSIZ);
- while (OFF_PAG(newp) > oldtail) {
- if (lseek(db->pagf, 0L, SEEK_END) < 0 ||
- write(db->pagf, zer, PBLKSIZ) < 0) {
-
- return 0;
- }
- oldtail += PBLKSIZ;
- }
-#endif
-
- if (hash & (db->hmask + 1)) {
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return 0;
- db->pagbno = newp;
- (void) memcpy(pag, new, PBLKSIZ);
- }
- else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
- || write(db->pagf, new, PBLKSIZ) < 0)
- return 0;
-
- if (!setdbit(db, db->curbit))
- return 0;
-/*
- * see if we have enough room now
- */
- if (fitpair(pag, need))
- return 1;
-/*
- * try again... update curbit and hmask as getpage would have
- * done. because of our update of the current page, we do not
- * need to read in anything. BUT we have to write the current
- * [deferred] page out, as the window of failure is too great.
- */
- db->curbit = 2 * db->curbit +
- ((hash & (db->hmask + 1)) ? 2 : 1);
- db->hmask |= (db->hmask + 1);
-
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return 0;
-
- } while (--smax);
-/*
- * if we are here, this is real bad news. After SPLTMAX splits,
- * we still cannot fit the key. say goodnight.
- */
-#if BADMESS
- (void) (write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44) < 0);
-#endif
- return 0;
-
-}
-
-/*
- * the following two routines will break if
- * deletions aren't taken into account. (ndbm bug)
- */
-datum
-sdbm_firstkey(register DBM *db)
-{
- if (db == NULL)
- return errno = EINVAL, nullitem;
-/*
- * start at page 0
- */
- (void) memset(db->pagbuf, 0, PBLKSIZ);
- if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
- || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return ioerr(db), nullitem;
- db->pagbno = 0;
- db->blkptr = 0;
- db->keyptr = 0;
-
- return getnext(db);
-}
-
-datum
-sdbm_nextkey(register DBM *db)
-{
- if (db == NULL)
- return errno = EINVAL, nullitem;
- return getnext(db);
-}
-
-/*
- * all important binary trie traversal
- */
-static int
-getpage(register DBM *db, register long int hash)
-{
- register int hbit;
- register long dbit;
- register long pagb;
-
- dbit = 0;
- hbit = 0;
- while (dbit < db->maxbno && getdbit(db, dbit))
- dbit = 2 * dbit + ((hash & ((long) 1 << hbit++)) ? 2 : 1);
-
- debug(("dbit: %ld...", dbit));
-
- db->curbit = dbit;
- db->hmask = masks[hbit];
-
- pagb = hash & db->hmask;
-/*
- * see if the block we need is already in memory.
- * note: this lookaside cache has about 10% hit rate.
- */
- if (pagb != db->pagbno) {
-/*
- * note: here, we assume a "hole" is read as 0s.
- * if not, must zero pagbuf first.
- */
- (void) memset(db->pagbuf, 0, PBLKSIZ);
-
- if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
- || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return 0;
- if (!chkpage(db->pagbuf)) {
- return 0;
- }
- db->pagbno = pagb;
-
- debug(("pag read: %ld\n", pagb));
- }
- return 1;
-}
-
-static int
-getdbit(register DBM *db, register long int dbit)
-{
- register long c;
- register long dirb;
-
- c = dbit / BYTESIZ;
- dirb = c / DBLKSIZ;
-
- if (dirb != db->dirbno) {
- if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
- || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
- return 0;
- db->dirbno = dirb;
-
- debug(("dir read: %ld\n", dirb));
- }
-
- return db->dirbuf[c % DBLKSIZ] & (1 << (dbit % BYTESIZ));
-}
-
-static int
-setdbit(register DBM *db, register long int dbit)
-{
- register long c;
- register long dirb;
-
- c = dbit / BYTESIZ;
- dirb = c / DBLKSIZ;
-
- if (dirb != db->dirbno) {
- if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
- || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
- return 0;
- db->dirbno = dirb;
-
- debug(("dir read: %ld\n", dirb));
- }
-
- db->dirbuf[c % DBLKSIZ] |= (1 << (dbit % BYTESIZ));
-
- if (dbit >= db->maxbno)
- db->maxbno += (long) DBLKSIZ * BYTESIZ;
-
- if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
- || write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
- return 0;
-
- return 1;
-}
-
-/*
- * getnext - get the next key in the page, and if done with
- * the page, try the next page in sequence
- */
-static datum
-getnext(register DBM *db)
-{
- datum key;
-
- for (;;) {
- db->keyptr++;
- key = getnkey(db->pagbuf, db->keyptr);
- if (key.dptr != NULL)
- return key;
-/*
- * we either run out, or there is nothing on this page..
- * try the next one... If we lost our position on the
- * file, we will have to seek.
- */
- db->keyptr = 0;
- if (db->pagbno != db->blkptr++)
- if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
- break;
- db->pagbno = db->blkptr;
- if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
- break;
- if (!chkpage(db->pagbuf)) {
- break;
- }
- }
-
- return ioerr(db), nullitem;
-}
-
-/* pair.c */
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain.
- *
- * page-level routines
- */
-
-#ifndef BSD42
-/*#include <memory.h>*/
-#endif
-
-#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
-
-/*
- * forward
- */
-static int seepair proto((char *, int, char *, int));
-
-/*
- * page format:
- * +------------------------------+
- * ino | n | keyoff | datoff | keyoff |
- * +------------+--------+--------+
- * | datoff | - - - ----> |
- * +--------+---------------------+
- * | F R E E A R E A |
- * +--------------+---------------+
- * | <---- - - - | data |
- * +--------+-----+----+----------+
- * | key | data | key |
- * +--------+----------+----------+
- *
- * calculating the offsets for free area: if the number
- * of entries (ino[0]) is zero, the offset to the END of
- * the free area is the block size. Otherwise, it is the
- * nth (ino[ino[0]]) entry's offset.
- */
-
-static int
-fitpair(char *pag, int need)
-{
- register int n;
- register int off;
- register int free;
- register short *ino = (short *) pag;
-
- off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
- free = off - (n + 1) * (int)sizeof(short);
- need += 2 * (int)sizeof(short);
-
- debug(("free %d need %d\n", free, need));
-
- return need <= free;
-}
-
-static void
-putpair(char *pag, datum key, datum val)
-{
- register int n;
- register int off;
- register short *ino = (short *) pag;
-
- off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
-/*
- * enter the key first
- */
- off -= key.dsize;
- if (key.dsize)
- (void) memcpy(pag + off, key.dptr, key.dsize);
- PUT_SHORT(ino,n + 1,off);
-/*
- * now the data
- */
- off -= val.dsize;
- if (val.dsize)
- (void) memcpy(pag + off, val.dptr, val.dsize);
- PUT_SHORT(ino,n + 2,off);
-/*
- * adjust item count
- */
- PUT_SHORT(ino,0,GET_SHORT(ino,0) + 2);
-}
-
-static datum
-getpair(char *pag, datum key)
-{
- register int i;
- register int n;
- datum val;
- register short *ino = (short *) pag;
-
- if ((n = GET_SHORT(ino,0)) == 0)
- return nullitem;
-
- if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
- return nullitem;
-
- val.dptr = pag + GET_SHORT(ino,i + 1);
- val.dsize = GET_SHORT(ino,i) - GET_SHORT(ino,i + 1);
- return val;
-}
-
-#if SEEDUPS
-static int
-duppair(char *pag, datum key)
-{
- register short *ino = (short *) pag;
- return GET_SHORT(ino,0) > 0 &&
- seepair(pag, GET_SHORT(ino,0), key.dptr, key.dsize) > 0;
-}
-#endif
-
-static datum
-getnkey(char *pag, int num)
-{
- datum key;
- register int off;
- register short *ino = (short *) pag;
-
- num = num * 2 - 1;
- if (GET_SHORT(ino,0) == 0 || num > GET_SHORT(ino,0))
- return nullitem;
-
- off = (num > 1) ? GET_SHORT(ino,num - 1) : PBLKSIZ;
-
- key.dptr = pag + GET_SHORT(ino,num);
- key.dsize = off - GET_SHORT(ino,num);
-
- return key;
-}
-
-static int
-delpair(char *pag, datum key)
-{
- register int n;
- register int i;
- register short *ino = (short *) pag;
-
- if ((n = GET_SHORT(ino,0)) == 0)
- return 0;
-
- if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
- return 0;
-/*
- * found the key. if it is the last entry
- * [i.e. i == n - 1] we just adjust the entry count.
- * hard case: move all data down onto the deleted pair,
- * shift offsets onto deleted offsets, and adjust them.
- * [note: 0 < i < n]
- */
- if (i < n - 1) {
- register int m;
- register char *dst = pag + (i == 1 ? PBLKSIZ : GET_SHORT(ino,i - 1));
- register char *src = pag + GET_SHORT(ino,i + 1);
- register ptrdiff_t zoo = dst - src;
-
- debug(("free-up %"PRIdPTRDIFF" ", zoo));
-/*
- * shift data/keys down
- */
- m = GET_SHORT(ino,i + 1) - GET_SHORT(ino,n);
-#ifdef DUFF
-#define MOVB *--dst = *--src
-
- if (m > 0) {
- register int loop = (m + 8 - 1) >> 3;
-
- switch (m & (8 - 1)) {
- case 0: do {
- MOVB; case 7: MOVB;
- case 6: MOVB; case 5: MOVB;
- case 4: MOVB; case 3: MOVB;
- case 2: MOVB; case 1: MOVB;
- } while (--loop);
- }
- }
-#else
-#ifdef MEMMOVE
- memmove(dst-m, src-m, m);
-#else
- while (m--)
- *--dst = *--src;
-#endif
-#endif
-/*
- * adjust offset index up
- */
- while (i < n - 1) {
- PUT_SHORT(ino,i, GET_SHORT(ino,i + 2) + zoo);
- i++;
- }
- }
- PUT_SHORT(ino, 0, GET_SHORT(ino, 0) - 2);
- return 1;
-}
-
-/*
- * search for the key in the page.
- * return offset index in the range 0 < i < n.
- * return 0 if not found.
- */
-static int
-seepair(char *pag, register int n, register char *key, register int siz)
-{
- register int i;
- register int off = PBLKSIZ;
- register short *ino = (short *) pag;
-
- for (i = 1; i < n; i += 2) {
- if (siz == off - GET_SHORT(ino,i) &&
- memcmp(key, pag + GET_SHORT(ino,i), siz) == 0)
- return i;
- off = GET_SHORT(ino,i + 1);
- }
- return 0;
-}
-
-static void
-splpage(char *pag, char *new, long int sbit)
-{
- datum key;
- datum val;
-
- register int n;
- register int off = PBLKSIZ;
- char cur[PBLKSIZ];
- register short *ino = (short *) cur;
-
- (void) memcpy(cur, pag, PBLKSIZ);
- (void) memset(pag, 0, PBLKSIZ);
- (void) memset(new, 0, PBLKSIZ);
-
- n = GET_SHORT(ino,0);
- for (ino++; n > 0; ino += 2) {
- key.dptr = cur + GET_SHORT(ino,0);
- key.dsize = off - GET_SHORT(ino,0);
- val.dptr = cur + GET_SHORT(ino,1);
- val.dsize = GET_SHORT(ino,0) - GET_SHORT(ino,1);
-/*
- * select the page pointer (by looking at sbit) and insert
- */
- (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
-
- off = GET_SHORT(ino,1);
- n -= 2;
- }
-
- debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
- ((short *) new)[0] / 2,
- ((short *) pag)[0] / 2));
-}
-
-/*
- * check page sanity:
- * number of entries should be something
- * reasonable, and all offsets in the index should be in order.
- * this could be made more rigorous.
- */
-static int
-chkpage(char *pag)
-{
- register int n;
- register int off;
- register short *ino = (short *) pag;
-
- if ((n = GET_SHORT(ino,0)) < 0 || n > PBLKSIZ / (int)sizeof(short))
- return 0;
-
- if (n > 0) {
- off = PBLKSIZ;
- for (ino++; n > 0; ino += 2) {
- if (GET_SHORT(ino,0) > off || GET_SHORT(ino,1) > off ||
- GET_SHORT(ino,1) > GET_SHORT(ino,0))
- return 0;
- off = GET_SHORT(ino,1);
- n -= 2;
- }
- }
- return 1;
-}
-
-/* hash.c */
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain. keep it that way.
- *
- * hashing routine
- */
-
-/*
- * polynomial conversion ignoring overflows
- * [this seems to work remarkably well, in fact better
- * then the ndbm hash function. Replace at your own risk]
- * use: 65599 nice.
- * 65587 even better.
- */
-long
-sdbm_hash(register char *str, register int len)
-{
- register unsigned long n = 0;
-
-#ifdef DUFF
-
-#define HASHC n = *str++ + 65599 * n
-
- if (len > 0) {
- register int loop = (len + 8 - 1) >> 3;
-
- switch(len & (8 - 1)) {
- case 0: do {
- HASHC; case 7: HASHC;
- case 6: HASHC; case 5: HASHC;
- case 4: HASHC; case 3: HASHC;
- case 2: HASHC; case 1: HASHC;
- } while (--loop);
- }
-
- }
-#else
- while (len--)
- n = ((*str++) & 255) + 65587L * n;
-#endif
- return n;
-}
diff --git a/ext/sdbm/depend b/ext/sdbm/depend
deleted file mode 100644
index d475ecccef..0000000000
--- a/ext/sdbm/depend
+++ /dev/null
@@ -1,27 +0,0 @@
-# AUTOGENERATED DEPENDENCIES START
-_sdbm.o: $(RUBY_EXTCONF_H)
-_sdbm.o: $(arch_hdrdir)/ruby/config.h
-_sdbm.o: $(hdrdir)/ruby/assert.h
-_sdbm.o: $(hdrdir)/ruby/backward.h
-_sdbm.o: $(hdrdir)/ruby/defines.h
-_sdbm.o: $(hdrdir)/ruby/intern.h
-_sdbm.o: $(hdrdir)/ruby/missing.h
-_sdbm.o: $(hdrdir)/ruby/ruby.h
-_sdbm.o: $(hdrdir)/ruby/st.h
-_sdbm.o: $(hdrdir)/ruby/subst.h
-_sdbm.o: _sdbm.c
-_sdbm.o: sdbm.h
-init.o: $(RUBY_EXTCONF_H)
-init.o: $(arch_hdrdir)/ruby/config.h
-init.o: $(hdrdir)/ruby.h
-init.o: $(hdrdir)/ruby/assert.h
-init.o: $(hdrdir)/ruby/backward.h
-init.o: $(hdrdir)/ruby/defines.h
-init.o: $(hdrdir)/ruby/intern.h
-init.o: $(hdrdir)/ruby/missing.h
-init.o: $(hdrdir)/ruby/ruby.h
-init.o: $(hdrdir)/ruby/st.h
-init.o: $(hdrdir)/ruby/subst.h
-init.o: init.c
-init.o: sdbm.h
-# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/sdbm/extconf.rb b/ext/sdbm/extconf.rb
deleted file mode 100644
index bdf3e299e6..0000000000
--- a/ext/sdbm/extconf.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: false
-require 'mkmf'
-
-$defs << "-D""BADMESS=0"
-create_makefile("sdbm")
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
deleted file mode 100644
index 42292b99cd..0000000000
--- a/ext/sdbm/init.c
+++ /dev/null
@@ -1,1067 +0,0 @@
-/************************************************
-
- sdbminit.c -
-
- $Author$
- created at: Fri May 7 08:34:24 JST 1999
-
- Copyright (C) 1995-2001 Yukihiro Matsumoto
-
-************************************************/
-
-#include "ruby.h"
-
-#include "sdbm.h"
-#include <fcntl.h>
-#include <errno.h>
-
-/*
- * Document-class: SDBM
- *
- * SDBM provides a simple file-based key-value store, which can only store
- * String keys and values.
- *
- * Note that Ruby comes with the source code for SDBM, while the DBM and GDBM
- * standard libraries rely on external libraries and headers.
- *
- * === Examples
- *
- * Insert values:
- *
- * require 'sdbm'
- *
- * SDBM.open 'my_database' do |db|
- * db['apple'] = 'fruit'
- * db['pear'] = 'fruit'
- * db['carrot'] = 'vegetable'
- * db['tomato'] = 'vegetable'
- * end
- *
- * Bulk update:
- *
- * require 'sdbm'
- *
- * SDBM.open 'my_database' do |db|
- * db.update('peach' => 'fruit', 'tomato' => 'fruit')
- * end
- *
- * Retrieve values:
- *
- * require 'sdbm'
- *
- * SDBM.open 'my_database' do |db|
- * db.each do |key, value|
- * puts "Key: #{key}, Value: #{value}"
- * end
- * end
- *
- * Outputs:
- *
- * Key: apple, Value: fruit
- * Key: pear, Value: fruit
- * Key: carrot, Value: vegetable
- * Key: peach, Value: fruit
- * Key: tomato, Value: fruit
- */
-
-static VALUE rb_cDBM, rb_eDBMError;
-
-struct dbmdata {
- int di_size;
- DBM *di_dbm;
-};
-
-NORETURN(static void closed_sdbm(void));
-
-static void
-closed_sdbm(void)
-{
- rb_raise(rb_eDBMError, "closed SDBM file");
-}
-
-#define GetDBM(obj, dbmp) do {\
- TypedData_Get_Struct((obj), struct dbmdata, &sdbm_type, (dbmp));\
- if ((dbmp)->di_dbm == 0) closed_sdbm();\
-} while (0)
-
-#define GetDBM2(obj, dbmp, dbm) do {\
- GetDBM((obj), (dbmp));\
- (dbm) = (dbmp)->di_dbm;\
-} while (0)
-
-static void
-free_sdbm(void *ptr)
-{
- struct dbmdata *dbmp = ptr;
-
- if (dbmp->di_dbm) sdbm_close(dbmp->di_dbm);
- ruby_xfree(dbmp);
-}
-
-static size_t
-memsize_dbm(const void *ptr)
-{
- const struct dbmdata *dbmp = ptr;
- size_t size = sizeof(*dbmp);
- if (dbmp->di_dbm)
- size += sizeof(DBM);
- return size;
-}
-
-static const rb_data_type_t sdbm_type = {
- "sdbm",
- {0, free_sdbm, memsize_dbm,},
- 0, 0,
- RUBY_TYPED_FREE_IMMEDIATELY,
-};
-
-/*
- * call-seq:
- * sdbm.close -> nil
- *
- * Closes the database file.
- *
- * Raises SDBMError if the database is already closed.
- */
-static VALUE
-fsdbm_close(VALUE obj)
-{
- struct dbmdata *dbmp;
-
- GetDBM(obj, dbmp);
- sdbm_close(dbmp->di_dbm);
- dbmp->di_dbm = 0;
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * sdbm.closed? -> true or false
- *
- * Returns +true+ if the database is closed.
- */
-static VALUE
-fsdbm_closed(VALUE obj)
-{
- struct dbmdata *dbmp;
-
- TypedData_Get_Struct(obj, struct dbmdata, &sdbm_type, dbmp);
- if (dbmp->di_dbm == 0)
- return Qtrue;
-
- return Qfalse;
-}
-
-static VALUE
-fsdbm_alloc(VALUE klass)
-{
- struct dbmdata *dbmp;
-
- return TypedData_Make_Struct(klass, struct dbmdata, &sdbm_type, dbmp);
-}
-/*
- * call-seq:
- * SDBM.new(filename, mode = 0666)
- *
- * Creates a new database handle by opening the given +filename+. SDBM actually
- * uses two physical files, with extensions '.dir' and '.pag'. These extensions
- * will automatically be appended to the +filename+.
- *
- * If the file does not exist, a new file will be created using the given
- * +mode+, unless +mode+ is explicitly set to nil. In the latter case, no
- * database will be created.
- *
- * If the file exists, it will be opened in read/write mode. If this fails, it
- * will be opened in read-only mode.
- */
-static VALUE
-fsdbm_initialize(int argc, VALUE *argv, VALUE obj)
-{
- VALUE file, vmode;
- DBM *dbm;
- struct dbmdata *dbmp;
- int mode;
-
- TypedData_Get_Struct(obj, struct dbmdata, &sdbm_type, dbmp);
- if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
- mode = 0666; /* default value */
- }
- else if (NIL_P(vmode)) {
- mode = -1; /* return nil if DB not exist */
- }
- else {
- mode = NUM2INT(vmode);
- }
- FilePathValue(file);
-
- dbm = 0;
- if (mode >= 0)
- dbm = sdbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT, mode);
- if (!dbm)
- dbm = sdbm_open(RSTRING_PTR(file), O_RDWR, 0);
- if (!dbm)
- dbm = sdbm_open(RSTRING_PTR(file), O_RDONLY, 0);
-
- if (!dbm) {
- if (mode == -1) return Qnil;
- rb_sys_fail_str(file);
- }
-
- if (dbmp->di_dbm)
- sdbm_close(dbmp->di_dbm);
- dbmp->di_dbm = dbm;
- dbmp->di_size = -1;
-
- return obj;
-}
-
-/*
- * call-seq:
- * SDBM.open(filename, mode = 0666)
- * SDBM.open(filename, mode = 0666) { |sdbm| ... }
- *
- * If called without a block, this is the same as SDBM.new.
- *
- * If a block is given, the new database will be passed to the block and
- * will be safely closed after the block has executed.
- *
- * Example:
- *
- * require 'sdbm'
- *
- * SDBM.open('my_database') do |db|
- * db['hello'] = 'world'
- * end
- */
-static VALUE
-fsdbm_s_open(int argc, VALUE *argv, VALUE klass)
-{
- VALUE obj = fsdbm_alloc(klass);
-
- if (NIL_P(fsdbm_initialize(argc, argv, obj))) {
- return Qnil;
- }
-
- if (rb_block_given_p()) {
- return rb_ensure(rb_yield, obj, fsdbm_close, obj);
- }
-
- return obj;
-}
-
-static VALUE
-fsdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone)
-{
- datum key, value;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- ExportStringValue(keystr);
- key.dptr = RSTRING_PTR(keystr);
- key.dsize = RSTRING_LENINT(keystr);
-
- GetDBM2(obj, dbmp, dbm);
- value = sdbm_fetch(dbm, key);
- if (value.dptr == 0) {
- if (ifnone == Qnil && rb_block_given_p())
- return rb_yield(rb_external_str_new(key.dptr, key.dsize));
- return ifnone;
- }
- return rb_external_str_new(value.dptr, value.dsize);
-}
-
-/*
- * call-seq:
- * sdbm[key] -> value or nil
- *
- * Returns the +value+ in the database associated with the given +key+ string.
- *
- * If no value is found, returns +nil+.
- */
-static VALUE
-fsdbm_aref(VALUE obj, VALUE keystr)
-{
- return fsdbm_fetch(obj, keystr, Qnil);
-}
-
-/*
- * call-seq:
- * sdbm.fetch(key) -> value or nil
- * sdbm.fetch(key) { |key| ... }
- *
- * Returns the +value+ in the database associated with the given +key+ string.
- *
- * If a block is provided, the block will be called when there is no
- * +value+ associated with the given +key+. The +key+ will be passed in as an
- * argument to the block.
- *
- * If no block is provided and no value is associated with the given +key+,
- * then an IndexError will be raised.
- */
-static VALUE
-fsdbm_fetch_m(int argc, VALUE *argv, VALUE obj)
-{
- VALUE keystr, valstr, ifnone;
-
- rb_scan_args(argc, argv, "11", &keystr, &ifnone);
- valstr = fsdbm_fetch(obj, keystr, ifnone);
- if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
- rb_raise(rb_eIndexError, "key not found");
-
- return valstr;
-}
-
-/*
- * call-seq:
- * sdbm.key(value) -> key
- *
- * Returns the +key+ associated with the given +value+. If more than one
- * +key+ corresponds to the given +value+, then the first key to be found
- * will be returned. If no keys are found, +nil+ will be returned.
- */
-static VALUE
-fsdbm_key(VALUE obj, VALUE valstr)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- ExportStringValue(valstr);
- val.dptr = RSTRING_PTR(valstr);
- val.dsize = RSTRING_LENINT(valstr);
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- if (val.dsize == RSTRING_LEN(valstr) &&
- memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
- return rb_external_str_new(key.dptr, key.dsize);
- }
- return Qnil;
-}
-
-/*
- * :nodoc:
- */
-static VALUE
-fsdbm_index(VALUE hash, VALUE value)
-{
- rb_warn("SDBM#index is deprecated; use SDBM#key");
- return fsdbm_key(hash, value);
-}
-
-/* call-seq:
- * sdbm.select { |key, value| ... } -> Array
- *
- * Returns a new Array of key-value pairs for which the block returns +true+.
- *
- * Example:
- *
- * require 'sdbm'
- *
- * SDBM.open 'my_database' do |db|
- * db['apple'] = 'fruit'
- * db['pear'] = 'fruit'
- * db['spinach'] = 'vegetable'
- *
- * veggies = db.select do |key, value|
- * value == 'vegetable'
- * end #=> [["apple", "fruit"], ["pear", "fruit"]]
- * end
- */
-static VALUE
-fsdbm_select(VALUE obj)
-{
- VALUE new = rb_ary_new();
- datum key, val;
- DBM *dbm;
- struct dbmdata *dbmp;
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- VALUE assoc, v;
- val = sdbm_fetch(dbm, key);
- assoc = rb_assoc_new(rb_external_str_new(key.dptr, key.dsize),
- rb_external_str_new(val.dptr, val.dsize));
- v = rb_yield(assoc);
- if (RTEST(v)) {
- rb_ary_push(new, assoc);
- }
- GetDBM2(obj, dbmp, dbm);
- }
-
- return new;
-}
-
-/* call-seq:
- * sdbm.values_at(key, ...) -> Array
- *
- * Returns an Array of values corresponding to the given keys.
- */
-static VALUE
-fsdbm_values_at(int argc, VALUE *argv, VALUE obj)
-{
- VALUE new = rb_ary_new2(argc);
- int i;
-
- for (i=0; i<argc; i++) {
- rb_ary_push(new, fsdbm_fetch(obj, argv[i], Qnil));
- }
-
- return new;
-}
-
-static void
-fdbm_modify(VALUE obj)
-{
- if (OBJ_FROZEN(obj)) rb_error_frozen("SDBM");
-}
-
-/*
- * call-seq:
- * sdbm.delete(key) -> value or nil
- * sdbm.delete(key) { |key, value| ... }
- *
- * Deletes the key-value pair corresponding to the given +key+. If the
- * +key+ exists, the deleted value will be returned, otherwise +nil+.
- *
- * If a block is provided, the deleted +key+ and +value+ will be passed to
- * the block as arguments. If the +key+ does not exist in the database, the
- * value will be +nil+.
- */
-static VALUE
-fsdbm_delete(VALUE obj, VALUE keystr)
-{
- datum key, value;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE valstr;
-
- fdbm_modify(obj);
- ExportStringValue(keystr);
- key.dptr = RSTRING_PTR(keystr);
- key.dsize = RSTRING_LENINT(keystr);
-
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
-
- value = sdbm_fetch(dbm, key);
- if (value.dptr == 0) {
- if (rb_block_given_p()) return rb_yield(keystr);
- return Qnil;
- }
-
- /* need to save value before sdbm_delete() */
- valstr = rb_external_str_new(value.dptr, value.dsize);
-
- if (sdbm_delete(dbm, key)) {
- dbmp->di_size = -1;
- rb_raise(rb_eDBMError, "dbm_delete failed");
- }
- else if (dbmp->di_size >= 0) {
- dbmp->di_size--;
- }
- return valstr;
-}
-
-/*
- * call-seq:
- * sdbm.shift -> Array or nil
- *
- * Removes a key-value pair from the database and returns them as an
- * Array. If the database is empty, returns +nil+.
- */
-static VALUE
-fsdbm_shift(VALUE obj)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE keystr, valstr;
-
- fdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- key = sdbm_firstkey(dbm);
- if (!key.dptr) return Qnil;
- val = sdbm_fetch(dbm, key);
- keystr = rb_external_str_new(key.dptr, key.dsize);
- valstr = rb_external_str_new(val.dptr, val.dsize);
- sdbm_delete(dbm, key);
- if (dbmp->di_size >= 0) {
- dbmp->di_size--;
- }
-
- return rb_assoc_new(keystr, valstr);
-}
-
-/*
- * call-seq:
- * sdbm.delete_if { |key, value| ... } -> self
- * sdbm.reject! { |key, value| ... } -> self
- *
- * Iterates over the key-value pairs in the database, deleting those for
- * which the block returns +true+.
- */
-static VALUE
-fsdbm_delete_if(VALUE obj)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE keystr, valstr;
- VALUE ret, ary = rb_ary_new();
- long i;
- int status = 0, n;
-
- fdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- n = dbmp->di_size;
- dbmp->di_size = -1;
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- keystr = rb_external_str_new(key.dptr, key.dsize);
- valstr = rb_external_str_new(val.dptr, val.dsize);
- ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
- if (status != 0) break;
- if (RTEST(ret)) rb_ary_push(ary, keystr);
- GetDBM2(obj, dbmp, dbm);
- }
-
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- keystr = RARRAY_AREF(ary, i);
- ExportStringValue(keystr);
- key.dptr = RSTRING_PTR(keystr);
- key.dsize = RSTRING_LENINT(keystr);
- if (sdbm_delete(dbm, key)) {
- rb_raise(rb_eDBMError, "sdbm_delete failed");
- }
- }
- if (status) rb_jump_tag(status);
- if (n > 0) dbmp->di_size = n - RARRAY_LENINT(ary);
-
- return obj;
-}
-
-/*
- * call-seq:
- * sdbm.clear -> self
- *
- * Deletes all data from the database.
- */
-static VALUE
-fsdbm_clear(VALUE obj)
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- fdbm_modify(obj);
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
- while (key = sdbm_firstkey(dbm), key.dptr) {
- if (sdbm_delete(dbm, key)) {
- rb_raise(rb_eDBMError, "sdbm_delete failed");
- }
- }
- dbmp->di_size = 0;
-
- return obj;
-}
-
-/*
- * call-seq:
- * sdbm.invert -> Hash
- *
- * Returns a Hash in which the key-value pairs have been inverted.
- *
- * Example:
- *
- * require 'sdbm'
- *
- * SDBM.open 'my_database' do |db|
- * db.update('apple' => 'fruit', 'spinach' => 'vegetable')
- *
- * db.invert #=> {"fruit" => "apple", "vegetable" => "spinach"}
- * end
- */
-static VALUE
-fsdbm_invert(VALUE obj)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE keystr, valstr;
- VALUE hash = rb_hash_new();
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- keystr = rb_external_str_new(key.dptr, key.dsize);
- valstr = rb_external_str_new(val.dptr, val.dsize);
- rb_hash_aset(hash, valstr, keystr);
- }
- return hash;
-}
-
-/*
- * call-seq:
- * sdbm[key] = value -> value
- * sdbm.store(key, value) -> value
- *
- * Stores a new +value+ in the database with the given +key+ as an index.
- *
- * If the +key+ already exists, this will update the +value+ associated with
- * the +key+.
- *
- * Returns the given +value+.
- */
-static VALUE
-fsdbm_store(VALUE obj, VALUE keystr, VALUE valstr)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- if (valstr == Qnil) {
- fsdbm_delete(obj, keystr);
- return Qnil;
- }
-
- fdbm_modify(obj);
- ExportStringValue(keystr);
- ExportStringValue(valstr);
-
- key.dptr = RSTRING_PTR(keystr);
- key.dsize = RSTRING_LENINT(keystr);
-
- val.dptr = RSTRING_PTR(valstr);
- val.dsize = RSTRING_LENINT(valstr);
-
- GetDBM2(obj, dbmp, dbm);
- dbmp->di_size = -1;
- if (sdbm_store(dbm, key, val, DBM_REPLACE)) {
-#ifdef HAVE_DBM_CLAERERR
- sdbm_clearerr(dbm);
-#endif
- if (errno == EPERM) rb_sys_fail(0);
- rb_raise(rb_eDBMError, "sdbm_store failed");
- }
-
- return valstr;
-}
-
-static VALUE
-update_i(RB_BLOCK_CALL_FUNC_ARGLIST(pair, dbm))
-{
- const VALUE *ptr;
- Check_Type(pair, T_ARRAY);
- if (RARRAY_LEN(pair) < 2) {
- rb_raise(rb_eArgError, "pair must be [key, value]");
- }
- ptr = RARRAY_CONST_PTR(pair);
- fsdbm_store(dbm, ptr[0], ptr[1]);
- return Qnil;
-}
-
-/*
- * call-seq:
- * sdbm.update(pairs) -> self
- *
- * Insert or update key-value pairs.
- *
- * This method will work with any object which implements an each_pair
- * method, such as a Hash.
- */
-static VALUE
-fsdbm_update(VALUE obj, VALUE other)
-{
- rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
- return obj;
-}
-
-/*
- * call-seq:
- * sdbm.replace(pairs) -> self
- *
- * Empties the database, then inserts the given key-value pairs.
- *
- * This method will work with any object which implements an each_pair
- * method, such as a Hash.
- */
-static VALUE
-fsdbm_replace(VALUE obj, VALUE other)
-{
- fsdbm_clear(obj);
- rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
- return obj;
-}
-
-/*
- * call-seq:
- * sdbm.length -> integer
- * sdbm.size -> integer
- *
- * Returns the number of keys in the database.
- */
-static VALUE
-fsdbm_length(VALUE obj)
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
- int i = 0;
-
- GetDBM2(obj, dbmp, dbm);
- if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
-
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- i++;
- }
- dbmp->di_size = i;
-
- return INT2FIX(i);
-}
-
-/*
- * call-seq:
- * sdbm.empty? -> true or false
- *
- * Returns +true+ if the database is empty.
- */
-static VALUE
-fsdbm_empty_p(VALUE obj)
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- GetDBM(obj, dbmp);
- if (dbmp->di_size < 0) {
- dbm = dbmp->di_dbm;
-
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- return Qfalse;
- }
- }
- else {
- if (dbmp->di_size)
- return Qfalse;
- }
- return Qtrue;
-}
-
-/*
- * call-seq:
- * sdbm.each_value
- * sdbm.each_value { |value| ... }
- *
- * Iterates over each +value+ in the database.
- *
- * If no block is given, returns an Enumerator.
- */
-static VALUE
-fsdbm_each_value(VALUE obj)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- RETURN_ENUMERATOR(obj, 0, 0);
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- rb_yield(rb_external_str_new(val.dptr, val.dsize));
- GetDBM2(obj, dbmp, dbm);
- }
- return obj;
-}
-
-/*
- * call-seq:
- * sdbm.each_key
- * sdbm.each_key { |key| ... }
- *
- * Iterates over each +key+ in the database.
- *
- * If no block is given, returns an Enumerator.
- */
-static VALUE
-fsdbm_each_key(VALUE obj)
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- RETURN_ENUMERATOR(obj, 0, 0);
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- rb_yield(rb_external_str_new(key.dptr, key.dsize));
- GetDBM2(obj, dbmp, dbm);
- }
- return obj;
-}
-
-/*
- * call-seq:
- * sdbm.each
- * sdbm.each { |key, value| ... }
- * sdbm.each_pair
- * sdbm.each_pair { |key, value| ... }
- *
- * Iterates over each key-value pair in the database.
- *
- * If no block is given, returns an Enumerator.
- */
-static VALUE
-fsdbm_each_pair(VALUE obj)
-{
- datum key, val;
- DBM *dbm;
- struct dbmdata *dbmp;
- VALUE keystr, valstr;
-
- RETURN_ENUMERATOR(obj, 0, 0);
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- keystr = rb_external_str_new(key.dptr, key.dsize);
- valstr = rb_external_str_new(val.dptr, val.dsize);
- rb_yield(rb_assoc_new(keystr, valstr));
- GetDBM2(obj, dbmp, dbm);
- }
-
- return obj;
-}
-
-/*
- * call-seq:
- * sdbm.keys -> Array
- *
- * Returns a new Array containing the keys in the database.
- */
-static VALUE
-fsdbm_keys(VALUE obj)
-{
- datum key;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- rb_ary_push(ary, rb_external_str_new(key.dptr, key.dsize));
- }
-
- return ary;
-}
-
-/*
- * call-seq:
- * sdbm.values -> Array
- *
- * Returns a new Array containing the values in the database.
- */
-static VALUE
-fsdbm_values(VALUE obj)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- rb_ary_push(ary, rb_external_str_new(val.dptr, val.dsize));
- }
-
- return ary;
-}
-
-/*
- * call-seq:
- * sdbm.include?(key) -> true or false
- * sdbm.key?(key) -> true or false
- * sdbm.member?(key) -> true or false
- * sdbm.has_key?(key) -> true or false
- *
- * Returns +true+ if the database contains the given +key+.
- */
-static VALUE
-fsdbm_has_key(VALUE obj, VALUE keystr)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- ExportStringValue(keystr);
- key.dptr = RSTRING_PTR(keystr);
- key.dsize = RSTRING_LENINT(keystr);
-
- GetDBM2(obj, dbmp, dbm);
- val = sdbm_fetch(dbm, key);
- if (val.dptr) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq:
- * sdbm.value?(key) -> true or false
- * sdbm.has_value?(key) -> true or false
- *
- * Returns +true+ if the database contains the given +value+.
- */
-static VALUE
-fsdbm_has_value(VALUE obj, VALUE valstr)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
-
- ExportStringValue(valstr);
- val.dptr = RSTRING_PTR(valstr);
- val.dsize = RSTRING_LENINT(valstr);
-
- GetDBM2(obj, dbmp, dbm);
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- if (val.dsize == RSTRING_LENINT(valstr) &&
- memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
- return Qtrue;
- }
- return Qfalse;
-}
-
-/*
- * call-seq:
- * sdbm.to_a -> Array
- *
- * Returns a new Array containing each key-value pair in the database.
- *
- * Example:
- *
- * require 'sdbm'
- *
- * SDBM.open 'my_database' do |db|
- * db.update('apple' => 'fruit', 'spinach' => 'vegetable')
- *
- * db.to_a #=> [["apple", "fruit"], ["spinach", "vegetable"]]
- * end
- */
-static VALUE
-fsdbm_to_a(VALUE obj)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE ary;
-
- GetDBM2(obj, dbmp, dbm);
- ary = rb_ary_new();
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- rb_ary_push(ary, rb_assoc_new(rb_external_str_new(key.dptr, key.dsize),
- rb_external_str_new(val.dptr, val.dsize)));
- }
-
- return ary;
-}
-
-/*
- * call-seq:
- * sdbm.to_hash -> Hash
- *
- * Returns a new Hash containing each key-value pair in the database.
- */
-static VALUE
-fsdbm_to_hash(VALUE obj)
-{
- datum key, val;
- struct dbmdata *dbmp;
- DBM *dbm;
- VALUE hash;
-
- GetDBM2(obj, dbmp, dbm);
- hash = rb_hash_new();
- for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
- val = sdbm_fetch(dbm, key);
- rb_hash_aset(hash, rb_external_str_new(key.dptr, key.dsize),
- rb_external_str_new(val.dptr, val.dsize));
- }
-
- return hash;
-}
-
-/*
- * call-seq:
- * sdbm.reject { |key, value| ... } -> Hash
- *
- * Creates a new Hash using the key-value pairs from the database, then
- * calls Hash#reject with the given block, which returns a Hash with
- * only the key-value pairs for which the block returns +false+.
- */
-static VALUE
-fsdbm_reject(VALUE obj)
-{
- return rb_hash_delete_if(fsdbm_to_hash(obj));
-}
-
-void
-Init_sdbm(void)
-{
- rb_cDBM = rb_define_class("SDBM", rb_cObject);
- rb_eDBMError = rb_define_class("SDBMError", rb_eStandardError);
- /* Document-class: SDBMError
- * Exception class used to return errors from the sdbm library.
- */
- rb_include_module(rb_cDBM, rb_mEnumerable);
-
- rb_define_alloc_func(rb_cDBM, fsdbm_alloc);
- rb_define_singleton_method(rb_cDBM, "open", fsdbm_s_open, -1);
-
- rb_define_method(rb_cDBM, "initialize", fsdbm_initialize, -1);
- rb_define_method(rb_cDBM, "close", fsdbm_close, 0);
- rb_define_method(rb_cDBM, "closed?", fsdbm_closed, 0);
- rb_define_method(rb_cDBM, "[]", fsdbm_aref, 1);
- rb_define_method(rb_cDBM, "fetch", fsdbm_fetch_m, -1);
- rb_define_method(rb_cDBM, "[]=", fsdbm_store, 2);
- rb_define_method(rb_cDBM, "store", fsdbm_store, 2);
- rb_define_method(rb_cDBM, "index", fsdbm_index, 1);
- rb_define_method(rb_cDBM, "key", fsdbm_key, 1);
- rb_define_method(rb_cDBM, "select", fsdbm_select, 0);
- rb_define_method(rb_cDBM, "values_at", fsdbm_values_at, -1);
- rb_define_method(rb_cDBM, "length", fsdbm_length, 0);
- rb_define_method(rb_cDBM, "size", fsdbm_length, 0);
- rb_define_method(rb_cDBM, "empty?", fsdbm_empty_p, 0);
- rb_define_method(rb_cDBM, "each", fsdbm_each_pair, 0);
- rb_define_method(rb_cDBM, "each_value", fsdbm_each_value, 0);
- rb_define_method(rb_cDBM, "each_key", fsdbm_each_key, 0);
- rb_define_method(rb_cDBM, "each_pair", fsdbm_each_pair, 0);
- rb_define_method(rb_cDBM, "keys", fsdbm_keys, 0);
- rb_define_method(rb_cDBM, "values", fsdbm_values, 0);
- rb_define_method(rb_cDBM, "shift", fsdbm_shift, 0);
- rb_define_method(rb_cDBM, "delete", fsdbm_delete, 1);
- rb_define_method(rb_cDBM, "delete_if", fsdbm_delete_if, 0);
- rb_define_method(rb_cDBM, "reject!", fsdbm_delete_if, 0);
- rb_define_method(rb_cDBM, "reject", fsdbm_reject, 0);
- rb_define_method(rb_cDBM, "clear", fsdbm_clear, 0);
- rb_define_method(rb_cDBM,"invert", fsdbm_invert, 0);
- rb_define_method(rb_cDBM,"update", fsdbm_update, 1);
- rb_define_method(rb_cDBM,"replace", fsdbm_replace, 1);
-
- rb_define_method(rb_cDBM, "has_key?", fsdbm_has_key, 1);
- rb_define_method(rb_cDBM, "include?", fsdbm_has_key, 1);
- rb_define_method(rb_cDBM, "key?", fsdbm_has_key, 1);
- rb_define_method(rb_cDBM, "member?", fsdbm_has_key, 1);
- rb_define_method(rb_cDBM, "has_value?", fsdbm_has_value, 1);
- rb_define_method(rb_cDBM, "value?", fsdbm_has_value, 1);
-
- rb_define_method(rb_cDBM, "to_a", fsdbm_to_a, 0);
- rb_define_method(rb_cDBM, "to_hash", fsdbm_to_hash, 0);
-}
diff --git a/ext/sdbm/sdbm.gemspec b/ext/sdbm/sdbm.gemspec
deleted file mode 100644
index 6cf000b453..0000000000
--- a/ext/sdbm/sdbm.gemspec
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-Gem::Specification.new do |s|
- s.name = "sdbm"
- s.version = '1.0.0'
- s.summary = "Provides a simple file-based key-value store with String keys and values."
- s.description = "Provides a simple file-based key-value store with String keys and values."
-
- s.require_path = %w{lib}
- s.files = %w{ext/sdbm/_sdbm.c ext/sdbm/extconf.rb ext/sdbm/init.c ext/sdbm/sdbm.h}
- s.extensions = ["ext/sdbm/extconf.rb"]
- s.required_ruby_version = ">= 2.3.0"
-
- s.authors = ["Yukihiro Matsumoto"]
- s.email = ["matz@ruby-lang.org"]
- s.homepage = "https://github.com/ruby/sdbm"
- s.license = "BSD-2-Clause"
-
- s.add_development_dependency "test-unit"
- s.add_development_dependency "rake-compiler"
-end
diff --git a/ext/sdbm/sdbm.h b/ext/sdbm/sdbm.h
deleted file mode 100644
index c3b53c4a8f..0000000000
--- a/ext/sdbm/sdbm.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain.
- */
-#ifndef _SDBM_H_
-#define _SDBM_H_
-
-#include <stdio.h>
-
-#define DBLKSIZ 4096
-#define PBLKSIZ 1024
-#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
-#define SPLTMAX 10 /* maximum allowed splits */
- /* for a single insertion */
-#define DIRFEXT ".dir"
-#define PAGFEXT ".pag"
-
-typedef struct {
- int dirf; /* directory file descriptor */
- int pagf; /* page file descriptor */
- int flags; /* status/error flags, see below */
- int keyptr; /* current key for nextkey */
- off_t maxbno; /* size of dirfile in bits */
- long curbit; /* current bit number */
- long hmask; /* current hash mask */
- long blkptr; /* current block for nextkey */
- long blkno; /* current page to read/write */
- long pagbno; /* current page in pagbuf */
- char pagbuf[PBLKSIZ]; /* page file block buffer */
- long dirbno; /* current block in dirbuf */
- char dirbuf[DBLKSIZ]; /* directory file block buffer */
-} DBM;
-
-#define DBM_RDONLY 0x1 /* data base open read-only */
-#define DBM_IOERR 0x2 /* data base I/O error */
-
-/*
- * utility macros
- */
-#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY)
-#define sdbm_error(db) ((db)->flags & DBM_IOERR)
-
-#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
-
-#define sdbm_dirfno(db) ((db)->dirf)
-#define sdbm_pagfno(db) ((db)->pagf)
-
-typedef struct {
- char *dptr;
- int dsize;
-} datum;
-
-extern datum nullitem;
-
-#if defined(__STDC__)
-#define proto(p) p
-#else
-#define proto(p) ()
-#endif
-
-/*
- * flags to sdbm_store
- */
-#define DBM_INSERT 0
-#define DBM_REPLACE 1
-
-/*
- * ndbm interface
- */
-extern DBM *sdbm_open proto((char *, int, int));
-extern void sdbm_close proto((DBM *));
-extern datum sdbm_fetch proto((DBM *, datum));
-extern int sdbm_delete proto((DBM *, datum));
-extern int sdbm_store proto((DBM *, datum, datum, int));
-extern datum sdbm_firstkey proto((DBM *));
-extern datum sdbm_nextkey proto((DBM *));
-
-/*
- * other
- */
-extern DBM *sdbm_prep proto((char *, char *, int, int));
-extern long sdbm_hash proto((char *, int));
-
-#endif /* _SDBM_H_ */
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 84463af061..546a971760 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -2,7 +2,6 @@
#include <time.h>
-int rsock_cmsg_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
static VALUE sym_wait_readable, sym_wait_writable;
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
@@ -89,9 +88,9 @@ ancillary_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE vtype, VALUE
static VALUE
ancdata_new(int family, int level, int type, VALUE data)
{
- NEWOBJ_OF(obj, struct RObject, rb_cAncillaryData, T_OBJECT);
+ VALUE obj = rb_obj_alloc(rb_cAncillaryData);
StringValue(data);
- ancillary_initialize((VALUE)obj, INT2NUM(family), INT2NUM(level), INT2NUM(type), data);
+ ancillary_initialize(obj, INT2NUM(family), INT2NUM(level), INT2NUM(type), data);
return (VALUE)obj;
}
@@ -1429,10 +1428,7 @@ make_io_for_unix_rights(VALUE ctl, struct cmsghdr *cmh, char *msg_end)
if (fstat(fd, &stbuf) == -1)
rb_raise(rb_eSocket, "invalid fd in SCM_RIGHTS");
rb_update_max_fd(fd);
- if (rsock_cmsg_cloexec_state < 0)
- rsock_cmsg_cloexec_state = rsock_detect_cloexec(fd);
- if (rsock_cmsg_cloexec_state == 0 || fd <= 2)
- rb_maygvl_fd_fix_cloexec(fd);
+ rb_maygvl_fd_fix_cloexec(fd);
if (S_ISSOCK(stbuf.st_mode))
io = rsock_init_sock(rb_obj_alloc(rb_cSocket), fd);
else
diff --git a/ext/socket/depend b/ext/socket/depend
index e958b3dc5d..14cf6ab4f6 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -13,8 +13,157 @@ constdefs.c: constdefs.h
ancdata.o: $(RUBY_EXTCONF_H)
ancdata.o: $(arch_hdrdir)/ruby/config.h
ancdata.o: $(hdrdir)/ruby.h
+ancdata.o: $(hdrdir)/ruby/internal/anyargs.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ancdata.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ancdata.o: $(hdrdir)/ruby/internal/assume.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/cold.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/const.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/error.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/format.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/pure.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/warning.h
+ancdata.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ancdata.o: $(hdrdir)/ruby/internal/cast.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ancdata.o: $(hdrdir)/ruby/internal/compiler_since.h
+ancdata.o: $(hdrdir)/ruby/internal/config.h
+ancdata.o: $(hdrdir)/ruby/internal/constant_p.h
+ancdata.o: $(hdrdir)/ruby/internal/core.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rarray.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rclass.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rdata.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rfile.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rhash.h
+ancdata.o: $(hdrdir)/ruby/internal/core/robject.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rstring.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ancdata.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ancdata.o: $(hdrdir)/ruby/internal/ctype.h
+ancdata.o: $(hdrdir)/ruby/internal/dllexport.h
+ancdata.o: $(hdrdir)/ruby/internal/dosish.h
+ancdata.o: $(hdrdir)/ruby/internal/error.h
+ancdata.o: $(hdrdir)/ruby/internal/eval.h
+ancdata.o: $(hdrdir)/ruby/internal/event.h
+ancdata.o: $(hdrdir)/ruby/internal/fl_type.h
+ancdata.o: $(hdrdir)/ruby/internal/gc.h
+ancdata.o: $(hdrdir)/ruby/internal/glob.h
+ancdata.o: $(hdrdir)/ruby/internal/globals.h
+ancdata.o: $(hdrdir)/ruby/internal/has/attribute.h
+ancdata.o: $(hdrdir)/ruby/internal/has/builtin.h
+ancdata.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ancdata.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ancdata.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ancdata.o: $(hdrdir)/ruby/internal/has/extension.h
+ancdata.o: $(hdrdir)/ruby/internal/has/feature.h
+ancdata.o: $(hdrdir)/ruby/internal/has/warning.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/array.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/class.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/compar.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/complex.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/cont.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/dir.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/enum.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/error.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/eval.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/file.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/gc.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/hash.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/io.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/load.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/object.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/parse.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/proc.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/process.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/random.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/range.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/rational.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/re.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/select.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/signal.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/string.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/struct.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/thread.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/time.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/variable.h
+ancdata.o: $(hdrdir)/ruby/internal/intern/vm.h
+ancdata.o: $(hdrdir)/ruby/internal/interpreter.h
+ancdata.o: $(hdrdir)/ruby/internal/iterator.h
+ancdata.o: $(hdrdir)/ruby/internal/memory.h
+ancdata.o: $(hdrdir)/ruby/internal/method.h
+ancdata.o: $(hdrdir)/ruby/internal/module.h
+ancdata.o: $(hdrdir)/ruby/internal/newobj.h
+ancdata.o: $(hdrdir)/ruby/internal/rgengc.h
+ancdata.o: $(hdrdir)/ruby/internal/scan_args.h
+ancdata.o: $(hdrdir)/ruby/internal/special_consts.h
+ancdata.o: $(hdrdir)/ruby/internal/static_assert.h
+ancdata.o: $(hdrdir)/ruby/internal/stdalign.h
+ancdata.o: $(hdrdir)/ruby/internal/stdbool.h
+ancdata.o: $(hdrdir)/ruby/internal/symbol.h
+ancdata.o: $(hdrdir)/ruby/internal/token_paste.h
+ancdata.o: $(hdrdir)/ruby/internal/value.h
+ancdata.o: $(hdrdir)/ruby/internal/value_type.h
+ancdata.o: $(hdrdir)/ruby/internal/variable.h
+ancdata.o: $(hdrdir)/ruby/internal/warning_push.h
+ancdata.o: $(hdrdir)/ruby/internal/xmalloc.h
ancdata.o: $(hdrdir)/ruby/assert.h
ancdata.o: $(hdrdir)/ruby/backward.h
+ancdata.o: $(hdrdir)/ruby/backward/2/assume.h
+ancdata.o: $(hdrdir)/ruby/backward/2/attributes.h
+ancdata.o: $(hdrdir)/ruby/backward/2/bool.h
+ancdata.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ancdata.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ancdata.o: $(hdrdir)/ruby/backward/2/limits.h
+ancdata.o: $(hdrdir)/ruby/backward/2/long_long.h
+ancdata.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ancdata.o: $(hdrdir)/ruby/backward/2/stdarg.h
ancdata.o: $(hdrdir)/ruby/defines.h
ancdata.o: $(hdrdir)/ruby/encoding.h
ancdata.o: $(hdrdir)/ruby/intern.h
@@ -28,6 +177,17 @@ ancdata.o: $(hdrdir)/ruby/subst.h
ancdata.o: $(hdrdir)/ruby/thread.h
ancdata.o: $(hdrdir)/ruby/util.h
ancdata.o: $(top_srcdir)/internal.h
+ancdata.o: $(top_srcdir)/internal/array.h
+ancdata.o: $(top_srcdir)/internal/compilers.h
+ancdata.o: $(top_srcdir)/internal/error.h
+ancdata.o: $(top_srcdir)/internal/gc.h
+ancdata.o: $(top_srcdir)/internal/io.h
+ancdata.o: $(top_srcdir)/internal/serial.h
+ancdata.o: $(top_srcdir)/internal/static_assert.h
+ancdata.o: $(top_srcdir)/internal/string.h
+ancdata.o: $(top_srcdir)/internal/thread.h
+ancdata.o: $(top_srcdir)/internal/vm.h
+ancdata.o: $(top_srcdir)/internal/warnings.h
ancdata.o: ancdata.c
ancdata.o: constdefs.h
ancdata.o: rubysocket.h
@@ -35,8 +195,157 @@ ancdata.o: sockport.h
basicsocket.o: $(RUBY_EXTCONF_H)
basicsocket.o: $(arch_hdrdir)/ruby/config.h
basicsocket.o: $(hdrdir)/ruby.h
+basicsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+basicsocket.o: $(hdrdir)/ruby/internal/assume.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+basicsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+basicsocket.o: $(hdrdir)/ruby/internal/cast.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+basicsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+basicsocket.o: $(hdrdir)/ruby/internal/config.h
+basicsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+basicsocket.o: $(hdrdir)/ruby/internal/core.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+basicsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+basicsocket.o: $(hdrdir)/ruby/internal/ctype.h
+basicsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+basicsocket.o: $(hdrdir)/ruby/internal/dosish.h
+basicsocket.o: $(hdrdir)/ruby/internal/error.h
+basicsocket.o: $(hdrdir)/ruby/internal/eval.h
+basicsocket.o: $(hdrdir)/ruby/internal/event.h
+basicsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+basicsocket.o: $(hdrdir)/ruby/internal/gc.h
+basicsocket.o: $(hdrdir)/ruby/internal/glob.h
+basicsocket.o: $(hdrdir)/ruby/internal/globals.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+basicsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/gc.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+basicsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+basicsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+basicsocket.o: $(hdrdir)/ruby/internal/iterator.h
+basicsocket.o: $(hdrdir)/ruby/internal/memory.h
+basicsocket.o: $(hdrdir)/ruby/internal/method.h
+basicsocket.o: $(hdrdir)/ruby/internal/module.h
+basicsocket.o: $(hdrdir)/ruby/internal/newobj.h
+basicsocket.o: $(hdrdir)/ruby/internal/rgengc.h
+basicsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+basicsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+basicsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+basicsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+basicsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+basicsocket.o: $(hdrdir)/ruby/internal/symbol.h
+basicsocket.o: $(hdrdir)/ruby/internal/token_paste.h
+basicsocket.o: $(hdrdir)/ruby/internal/value.h
+basicsocket.o: $(hdrdir)/ruby/internal/value_type.h
+basicsocket.o: $(hdrdir)/ruby/internal/variable.h
+basicsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+basicsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
basicsocket.o: $(hdrdir)/ruby/assert.h
basicsocket.o: $(hdrdir)/ruby/backward.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+basicsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
basicsocket.o: $(hdrdir)/ruby/defines.h
basicsocket.o: $(hdrdir)/ruby/encoding.h
basicsocket.o: $(hdrdir)/ruby/intern.h
@@ -50,6 +359,17 @@ basicsocket.o: $(hdrdir)/ruby/subst.h
basicsocket.o: $(hdrdir)/ruby/thread.h
basicsocket.o: $(hdrdir)/ruby/util.h
basicsocket.o: $(top_srcdir)/internal.h
+basicsocket.o: $(top_srcdir)/internal/array.h
+basicsocket.o: $(top_srcdir)/internal/compilers.h
+basicsocket.o: $(top_srcdir)/internal/error.h
+basicsocket.o: $(top_srcdir)/internal/gc.h
+basicsocket.o: $(top_srcdir)/internal/io.h
+basicsocket.o: $(top_srcdir)/internal/serial.h
+basicsocket.o: $(top_srcdir)/internal/static_assert.h
+basicsocket.o: $(top_srcdir)/internal/string.h
+basicsocket.o: $(top_srcdir)/internal/thread.h
+basicsocket.o: $(top_srcdir)/internal/vm.h
+basicsocket.o: $(top_srcdir)/internal/warnings.h
basicsocket.o: basicsocket.c
basicsocket.o: constdefs.h
basicsocket.o: rubysocket.h
@@ -57,8 +377,157 @@ basicsocket.o: sockport.h
constants.o: $(RUBY_EXTCONF_H)
constants.o: $(arch_hdrdir)/ruby/config.h
constants.o: $(hdrdir)/ruby.h
+constants.o: $(hdrdir)/ruby/internal/anyargs.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+constants.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+constants.o: $(hdrdir)/ruby/internal/assume.h
+constants.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+constants.o: $(hdrdir)/ruby/internal/attr/artificial.h
+constants.o: $(hdrdir)/ruby/internal/attr/cold.h
+constants.o: $(hdrdir)/ruby/internal/attr/const.h
+constants.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+constants.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+constants.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+constants.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+constants.o: $(hdrdir)/ruby/internal/attr/error.h
+constants.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+constants.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+constants.o: $(hdrdir)/ruby/internal/attr/format.h
+constants.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+constants.o: $(hdrdir)/ruby/internal/attr/noalias.h
+constants.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+constants.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+constants.o: $(hdrdir)/ruby/internal/attr/noinline.h
+constants.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+constants.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+constants.o: $(hdrdir)/ruby/internal/attr/pure.h
+constants.o: $(hdrdir)/ruby/internal/attr/restrict.h
+constants.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+constants.o: $(hdrdir)/ruby/internal/attr/warning.h
+constants.o: $(hdrdir)/ruby/internal/attr/weakref.h
+constants.o: $(hdrdir)/ruby/internal/cast.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+constants.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+constants.o: $(hdrdir)/ruby/internal/compiler_since.h
+constants.o: $(hdrdir)/ruby/internal/config.h
+constants.o: $(hdrdir)/ruby/internal/constant_p.h
+constants.o: $(hdrdir)/ruby/internal/core.h
+constants.o: $(hdrdir)/ruby/internal/core/rarray.h
+constants.o: $(hdrdir)/ruby/internal/core/rbasic.h
+constants.o: $(hdrdir)/ruby/internal/core/rbignum.h
+constants.o: $(hdrdir)/ruby/internal/core/rclass.h
+constants.o: $(hdrdir)/ruby/internal/core/rdata.h
+constants.o: $(hdrdir)/ruby/internal/core/rfile.h
+constants.o: $(hdrdir)/ruby/internal/core/rhash.h
+constants.o: $(hdrdir)/ruby/internal/core/robject.h
+constants.o: $(hdrdir)/ruby/internal/core/rregexp.h
+constants.o: $(hdrdir)/ruby/internal/core/rstring.h
+constants.o: $(hdrdir)/ruby/internal/core/rstruct.h
+constants.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+constants.o: $(hdrdir)/ruby/internal/ctype.h
+constants.o: $(hdrdir)/ruby/internal/dllexport.h
+constants.o: $(hdrdir)/ruby/internal/dosish.h
+constants.o: $(hdrdir)/ruby/internal/error.h
+constants.o: $(hdrdir)/ruby/internal/eval.h
+constants.o: $(hdrdir)/ruby/internal/event.h
+constants.o: $(hdrdir)/ruby/internal/fl_type.h
+constants.o: $(hdrdir)/ruby/internal/gc.h
+constants.o: $(hdrdir)/ruby/internal/glob.h
+constants.o: $(hdrdir)/ruby/internal/globals.h
+constants.o: $(hdrdir)/ruby/internal/has/attribute.h
+constants.o: $(hdrdir)/ruby/internal/has/builtin.h
+constants.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+constants.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+constants.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+constants.o: $(hdrdir)/ruby/internal/has/extension.h
+constants.o: $(hdrdir)/ruby/internal/has/feature.h
+constants.o: $(hdrdir)/ruby/internal/has/warning.h
+constants.o: $(hdrdir)/ruby/internal/intern/array.h
+constants.o: $(hdrdir)/ruby/internal/intern/bignum.h
+constants.o: $(hdrdir)/ruby/internal/intern/class.h
+constants.o: $(hdrdir)/ruby/internal/intern/compar.h
+constants.o: $(hdrdir)/ruby/internal/intern/complex.h
+constants.o: $(hdrdir)/ruby/internal/intern/cont.h
+constants.o: $(hdrdir)/ruby/internal/intern/dir.h
+constants.o: $(hdrdir)/ruby/internal/intern/enum.h
+constants.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+constants.o: $(hdrdir)/ruby/internal/intern/error.h
+constants.o: $(hdrdir)/ruby/internal/intern/eval.h
+constants.o: $(hdrdir)/ruby/internal/intern/file.h
+constants.o: $(hdrdir)/ruby/internal/intern/gc.h
+constants.o: $(hdrdir)/ruby/internal/intern/hash.h
+constants.o: $(hdrdir)/ruby/internal/intern/io.h
+constants.o: $(hdrdir)/ruby/internal/intern/load.h
+constants.o: $(hdrdir)/ruby/internal/intern/marshal.h
+constants.o: $(hdrdir)/ruby/internal/intern/numeric.h
+constants.o: $(hdrdir)/ruby/internal/intern/object.h
+constants.o: $(hdrdir)/ruby/internal/intern/parse.h
+constants.o: $(hdrdir)/ruby/internal/intern/proc.h
+constants.o: $(hdrdir)/ruby/internal/intern/process.h
+constants.o: $(hdrdir)/ruby/internal/intern/random.h
+constants.o: $(hdrdir)/ruby/internal/intern/range.h
+constants.o: $(hdrdir)/ruby/internal/intern/rational.h
+constants.o: $(hdrdir)/ruby/internal/intern/re.h
+constants.o: $(hdrdir)/ruby/internal/intern/ruby.h
+constants.o: $(hdrdir)/ruby/internal/intern/select.h
+constants.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+constants.o: $(hdrdir)/ruby/internal/intern/signal.h
+constants.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+constants.o: $(hdrdir)/ruby/internal/intern/string.h
+constants.o: $(hdrdir)/ruby/internal/intern/struct.h
+constants.o: $(hdrdir)/ruby/internal/intern/thread.h
+constants.o: $(hdrdir)/ruby/internal/intern/time.h
+constants.o: $(hdrdir)/ruby/internal/intern/variable.h
+constants.o: $(hdrdir)/ruby/internal/intern/vm.h
+constants.o: $(hdrdir)/ruby/internal/interpreter.h
+constants.o: $(hdrdir)/ruby/internal/iterator.h
+constants.o: $(hdrdir)/ruby/internal/memory.h
+constants.o: $(hdrdir)/ruby/internal/method.h
+constants.o: $(hdrdir)/ruby/internal/module.h
+constants.o: $(hdrdir)/ruby/internal/newobj.h
+constants.o: $(hdrdir)/ruby/internal/rgengc.h
+constants.o: $(hdrdir)/ruby/internal/scan_args.h
+constants.o: $(hdrdir)/ruby/internal/special_consts.h
+constants.o: $(hdrdir)/ruby/internal/static_assert.h
+constants.o: $(hdrdir)/ruby/internal/stdalign.h
+constants.o: $(hdrdir)/ruby/internal/stdbool.h
+constants.o: $(hdrdir)/ruby/internal/symbol.h
+constants.o: $(hdrdir)/ruby/internal/token_paste.h
+constants.o: $(hdrdir)/ruby/internal/value.h
+constants.o: $(hdrdir)/ruby/internal/value_type.h
+constants.o: $(hdrdir)/ruby/internal/variable.h
+constants.o: $(hdrdir)/ruby/internal/warning_push.h
+constants.o: $(hdrdir)/ruby/internal/xmalloc.h
constants.o: $(hdrdir)/ruby/assert.h
constants.o: $(hdrdir)/ruby/backward.h
+constants.o: $(hdrdir)/ruby/backward/2/assume.h
+constants.o: $(hdrdir)/ruby/backward/2/attributes.h
+constants.o: $(hdrdir)/ruby/backward/2/bool.h
+constants.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+constants.o: $(hdrdir)/ruby/backward/2/inttypes.h
+constants.o: $(hdrdir)/ruby/backward/2/limits.h
+constants.o: $(hdrdir)/ruby/backward/2/long_long.h
+constants.o: $(hdrdir)/ruby/backward/2/stdalign.h
+constants.o: $(hdrdir)/ruby/backward/2/stdarg.h
constants.o: $(hdrdir)/ruby/defines.h
constants.o: $(hdrdir)/ruby/encoding.h
constants.o: $(hdrdir)/ruby/intern.h
@@ -72,6 +541,17 @@ constants.o: $(hdrdir)/ruby/subst.h
constants.o: $(hdrdir)/ruby/thread.h
constants.o: $(hdrdir)/ruby/util.h
constants.o: $(top_srcdir)/internal.h
+constants.o: $(top_srcdir)/internal/array.h
+constants.o: $(top_srcdir)/internal/compilers.h
+constants.o: $(top_srcdir)/internal/error.h
+constants.o: $(top_srcdir)/internal/gc.h
+constants.o: $(top_srcdir)/internal/io.h
+constants.o: $(top_srcdir)/internal/serial.h
+constants.o: $(top_srcdir)/internal/static_assert.h
+constants.o: $(top_srcdir)/internal/string.h
+constants.o: $(top_srcdir)/internal/thread.h
+constants.o: $(top_srcdir)/internal/vm.h
+constants.o: $(top_srcdir)/internal/warnings.h
constants.o: constants.c
constants.o: constdefs.c
constants.o: constdefs.h
@@ -80,8 +560,157 @@ constants.o: sockport.h
ifaddr.o: $(RUBY_EXTCONF_H)
ifaddr.o: $(arch_hdrdir)/ruby/config.h
ifaddr.o: $(hdrdir)/ruby.h
+ifaddr.o: $(hdrdir)/ruby/internal/anyargs.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ifaddr.o: $(hdrdir)/ruby/internal/assume.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/cold.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/const.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/error.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/format.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/pure.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/warning.h
+ifaddr.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ifaddr.o: $(hdrdir)/ruby/internal/cast.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ifaddr.o: $(hdrdir)/ruby/internal/compiler_since.h
+ifaddr.o: $(hdrdir)/ruby/internal/config.h
+ifaddr.o: $(hdrdir)/ruby/internal/constant_p.h
+ifaddr.o: $(hdrdir)/ruby/internal/core.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rarray.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rclass.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rdata.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rfile.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rhash.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/robject.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rstring.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ifaddr.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ifaddr.o: $(hdrdir)/ruby/internal/ctype.h
+ifaddr.o: $(hdrdir)/ruby/internal/dllexport.h
+ifaddr.o: $(hdrdir)/ruby/internal/dosish.h
+ifaddr.o: $(hdrdir)/ruby/internal/error.h
+ifaddr.o: $(hdrdir)/ruby/internal/eval.h
+ifaddr.o: $(hdrdir)/ruby/internal/event.h
+ifaddr.o: $(hdrdir)/ruby/internal/fl_type.h
+ifaddr.o: $(hdrdir)/ruby/internal/gc.h
+ifaddr.o: $(hdrdir)/ruby/internal/glob.h
+ifaddr.o: $(hdrdir)/ruby/internal/globals.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/attribute.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/builtin.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/extension.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/feature.h
+ifaddr.o: $(hdrdir)/ruby/internal/has/warning.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/array.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/class.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/compar.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/complex.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/cont.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/dir.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/enum.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/error.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/eval.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/file.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/gc.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/hash.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/io.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/load.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/object.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/parse.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/proc.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/process.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/random.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/range.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/rational.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/re.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/select.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/signal.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/string.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/struct.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/thread.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/time.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/variable.h
+ifaddr.o: $(hdrdir)/ruby/internal/intern/vm.h
+ifaddr.o: $(hdrdir)/ruby/internal/interpreter.h
+ifaddr.o: $(hdrdir)/ruby/internal/iterator.h
+ifaddr.o: $(hdrdir)/ruby/internal/memory.h
+ifaddr.o: $(hdrdir)/ruby/internal/method.h
+ifaddr.o: $(hdrdir)/ruby/internal/module.h
+ifaddr.o: $(hdrdir)/ruby/internal/newobj.h
+ifaddr.o: $(hdrdir)/ruby/internal/rgengc.h
+ifaddr.o: $(hdrdir)/ruby/internal/scan_args.h
+ifaddr.o: $(hdrdir)/ruby/internal/special_consts.h
+ifaddr.o: $(hdrdir)/ruby/internal/static_assert.h
+ifaddr.o: $(hdrdir)/ruby/internal/stdalign.h
+ifaddr.o: $(hdrdir)/ruby/internal/stdbool.h
+ifaddr.o: $(hdrdir)/ruby/internal/symbol.h
+ifaddr.o: $(hdrdir)/ruby/internal/token_paste.h
+ifaddr.o: $(hdrdir)/ruby/internal/value.h
+ifaddr.o: $(hdrdir)/ruby/internal/value_type.h
+ifaddr.o: $(hdrdir)/ruby/internal/variable.h
+ifaddr.o: $(hdrdir)/ruby/internal/warning_push.h
+ifaddr.o: $(hdrdir)/ruby/internal/xmalloc.h
ifaddr.o: $(hdrdir)/ruby/assert.h
ifaddr.o: $(hdrdir)/ruby/backward.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/assume.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/attributes.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/bool.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/limits.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/long_long.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ifaddr.o: $(hdrdir)/ruby/backward/2/stdarg.h
ifaddr.o: $(hdrdir)/ruby/defines.h
ifaddr.o: $(hdrdir)/ruby/encoding.h
ifaddr.o: $(hdrdir)/ruby/intern.h
@@ -95,6 +724,17 @@ ifaddr.o: $(hdrdir)/ruby/subst.h
ifaddr.o: $(hdrdir)/ruby/thread.h
ifaddr.o: $(hdrdir)/ruby/util.h
ifaddr.o: $(top_srcdir)/internal.h
+ifaddr.o: $(top_srcdir)/internal/array.h
+ifaddr.o: $(top_srcdir)/internal/compilers.h
+ifaddr.o: $(top_srcdir)/internal/error.h
+ifaddr.o: $(top_srcdir)/internal/gc.h
+ifaddr.o: $(top_srcdir)/internal/io.h
+ifaddr.o: $(top_srcdir)/internal/serial.h
+ifaddr.o: $(top_srcdir)/internal/static_assert.h
+ifaddr.o: $(top_srcdir)/internal/string.h
+ifaddr.o: $(top_srcdir)/internal/thread.h
+ifaddr.o: $(top_srcdir)/internal/vm.h
+ifaddr.o: $(top_srcdir)/internal/warnings.h
ifaddr.o: constdefs.h
ifaddr.o: ifaddr.c
ifaddr.o: rubysocket.h
@@ -102,8 +742,157 @@ ifaddr.o: sockport.h
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
init.o: $(hdrdir)/ruby.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/gc.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/rgengc.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/token_paste.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/assert.h
init.o: $(hdrdir)/ruby/backward.h
+init.o: $(hdrdir)/ruby/backward/2/assume.h
+init.o: $(hdrdir)/ruby/backward/2/attributes.h
+init.o: $(hdrdir)/ruby/backward/2/bool.h
+init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+init.o: $(hdrdir)/ruby/backward/2/inttypes.h
+init.o: $(hdrdir)/ruby/backward/2/limits.h
+init.o: $(hdrdir)/ruby/backward/2/long_long.h
+init.o: $(hdrdir)/ruby/backward/2/stdalign.h
+init.o: $(hdrdir)/ruby/backward/2/stdarg.h
init.o: $(hdrdir)/ruby/defines.h
init.o: $(hdrdir)/ruby/encoding.h
init.o: $(hdrdir)/ruby/intern.h
@@ -117,6 +906,17 @@ init.o: $(hdrdir)/ruby/subst.h
init.o: $(hdrdir)/ruby/thread.h
init.o: $(hdrdir)/ruby/util.h
init.o: $(top_srcdir)/internal.h
+init.o: $(top_srcdir)/internal/array.h
+init.o: $(top_srcdir)/internal/compilers.h
+init.o: $(top_srcdir)/internal/error.h
+init.o: $(top_srcdir)/internal/gc.h
+init.o: $(top_srcdir)/internal/io.h
+init.o: $(top_srcdir)/internal/serial.h
+init.o: $(top_srcdir)/internal/static_assert.h
+init.o: $(top_srcdir)/internal/string.h
+init.o: $(top_srcdir)/internal/thread.h
+init.o: $(top_srcdir)/internal/vm.h
+init.o: $(top_srcdir)/internal/warnings.h
init.o: constdefs.h
init.o: init.c
init.o: rubysocket.h
@@ -124,8 +924,157 @@ init.o: sockport.h
ipsocket.o: $(RUBY_EXTCONF_H)
ipsocket.o: $(arch_hdrdir)/ruby/config.h
ipsocket.o: $(hdrdir)/ruby.h
+ipsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ipsocket.o: $(hdrdir)/ruby/internal/assume.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+ipsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ipsocket.o: $(hdrdir)/ruby/internal/cast.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ipsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+ipsocket.o: $(hdrdir)/ruby/internal/config.h
+ipsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+ipsocket.o: $(hdrdir)/ruby/internal/core.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ipsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ipsocket.o: $(hdrdir)/ruby/internal/ctype.h
+ipsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+ipsocket.o: $(hdrdir)/ruby/internal/dosish.h
+ipsocket.o: $(hdrdir)/ruby/internal/error.h
+ipsocket.o: $(hdrdir)/ruby/internal/eval.h
+ipsocket.o: $(hdrdir)/ruby/internal/event.h
+ipsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+ipsocket.o: $(hdrdir)/ruby/internal/gc.h
+ipsocket.o: $(hdrdir)/ruby/internal/glob.h
+ipsocket.o: $(hdrdir)/ruby/internal/globals.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+ipsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/gc.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+ipsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+ipsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+ipsocket.o: $(hdrdir)/ruby/internal/iterator.h
+ipsocket.o: $(hdrdir)/ruby/internal/memory.h
+ipsocket.o: $(hdrdir)/ruby/internal/method.h
+ipsocket.o: $(hdrdir)/ruby/internal/module.h
+ipsocket.o: $(hdrdir)/ruby/internal/newobj.h
+ipsocket.o: $(hdrdir)/ruby/internal/rgengc.h
+ipsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+ipsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+ipsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+ipsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+ipsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+ipsocket.o: $(hdrdir)/ruby/internal/symbol.h
+ipsocket.o: $(hdrdir)/ruby/internal/token_paste.h
+ipsocket.o: $(hdrdir)/ruby/internal/value.h
+ipsocket.o: $(hdrdir)/ruby/internal/value_type.h
+ipsocket.o: $(hdrdir)/ruby/internal/variable.h
+ipsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+ipsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
ipsocket.o: $(hdrdir)/ruby/assert.h
ipsocket.o: $(hdrdir)/ruby/backward.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ipsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
ipsocket.o: $(hdrdir)/ruby/defines.h
ipsocket.o: $(hdrdir)/ruby/encoding.h
ipsocket.o: $(hdrdir)/ruby/intern.h
@@ -139,6 +1088,17 @@ ipsocket.o: $(hdrdir)/ruby/subst.h
ipsocket.o: $(hdrdir)/ruby/thread.h
ipsocket.o: $(hdrdir)/ruby/util.h
ipsocket.o: $(top_srcdir)/internal.h
+ipsocket.o: $(top_srcdir)/internal/array.h
+ipsocket.o: $(top_srcdir)/internal/compilers.h
+ipsocket.o: $(top_srcdir)/internal/error.h
+ipsocket.o: $(top_srcdir)/internal/gc.h
+ipsocket.o: $(top_srcdir)/internal/io.h
+ipsocket.o: $(top_srcdir)/internal/serial.h
+ipsocket.o: $(top_srcdir)/internal/static_assert.h
+ipsocket.o: $(top_srcdir)/internal/string.h
+ipsocket.o: $(top_srcdir)/internal/thread.h
+ipsocket.o: $(top_srcdir)/internal/vm.h
+ipsocket.o: $(top_srcdir)/internal/warnings.h
ipsocket.o: constdefs.h
ipsocket.o: ipsocket.c
ipsocket.o: rubysocket.h
@@ -146,8 +1106,157 @@ ipsocket.o: sockport.h
option.o: $(RUBY_EXTCONF_H)
option.o: $(arch_hdrdir)/ruby/config.h
option.o: $(hdrdir)/ruby.h
+option.o: $(hdrdir)/ruby/internal/anyargs.h
+option.o: $(hdrdir)/ruby/internal/arithmetic.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+option.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+option.o: $(hdrdir)/ruby/internal/assume.h
+option.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+option.o: $(hdrdir)/ruby/internal/attr/artificial.h
+option.o: $(hdrdir)/ruby/internal/attr/cold.h
+option.o: $(hdrdir)/ruby/internal/attr/const.h
+option.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+option.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+option.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+option.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+option.o: $(hdrdir)/ruby/internal/attr/error.h
+option.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+option.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+option.o: $(hdrdir)/ruby/internal/attr/format.h
+option.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+option.o: $(hdrdir)/ruby/internal/attr/noalias.h
+option.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+option.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+option.o: $(hdrdir)/ruby/internal/attr/noinline.h
+option.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+option.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+option.o: $(hdrdir)/ruby/internal/attr/pure.h
+option.o: $(hdrdir)/ruby/internal/attr/restrict.h
+option.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+option.o: $(hdrdir)/ruby/internal/attr/warning.h
+option.o: $(hdrdir)/ruby/internal/attr/weakref.h
+option.o: $(hdrdir)/ruby/internal/cast.h
+option.o: $(hdrdir)/ruby/internal/compiler_is.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+option.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+option.o: $(hdrdir)/ruby/internal/compiler_since.h
+option.o: $(hdrdir)/ruby/internal/config.h
+option.o: $(hdrdir)/ruby/internal/constant_p.h
+option.o: $(hdrdir)/ruby/internal/core.h
+option.o: $(hdrdir)/ruby/internal/core/rarray.h
+option.o: $(hdrdir)/ruby/internal/core/rbasic.h
+option.o: $(hdrdir)/ruby/internal/core/rbignum.h
+option.o: $(hdrdir)/ruby/internal/core/rclass.h
+option.o: $(hdrdir)/ruby/internal/core/rdata.h
+option.o: $(hdrdir)/ruby/internal/core/rfile.h
+option.o: $(hdrdir)/ruby/internal/core/rhash.h
+option.o: $(hdrdir)/ruby/internal/core/robject.h
+option.o: $(hdrdir)/ruby/internal/core/rregexp.h
+option.o: $(hdrdir)/ruby/internal/core/rstring.h
+option.o: $(hdrdir)/ruby/internal/core/rstruct.h
+option.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+option.o: $(hdrdir)/ruby/internal/ctype.h
+option.o: $(hdrdir)/ruby/internal/dllexport.h
+option.o: $(hdrdir)/ruby/internal/dosish.h
+option.o: $(hdrdir)/ruby/internal/error.h
+option.o: $(hdrdir)/ruby/internal/eval.h
+option.o: $(hdrdir)/ruby/internal/event.h
+option.o: $(hdrdir)/ruby/internal/fl_type.h
+option.o: $(hdrdir)/ruby/internal/gc.h
+option.o: $(hdrdir)/ruby/internal/glob.h
+option.o: $(hdrdir)/ruby/internal/globals.h
+option.o: $(hdrdir)/ruby/internal/has/attribute.h
+option.o: $(hdrdir)/ruby/internal/has/builtin.h
+option.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+option.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+option.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+option.o: $(hdrdir)/ruby/internal/has/extension.h
+option.o: $(hdrdir)/ruby/internal/has/feature.h
+option.o: $(hdrdir)/ruby/internal/has/warning.h
+option.o: $(hdrdir)/ruby/internal/intern/array.h
+option.o: $(hdrdir)/ruby/internal/intern/bignum.h
+option.o: $(hdrdir)/ruby/internal/intern/class.h
+option.o: $(hdrdir)/ruby/internal/intern/compar.h
+option.o: $(hdrdir)/ruby/internal/intern/complex.h
+option.o: $(hdrdir)/ruby/internal/intern/cont.h
+option.o: $(hdrdir)/ruby/internal/intern/dir.h
+option.o: $(hdrdir)/ruby/internal/intern/enum.h
+option.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+option.o: $(hdrdir)/ruby/internal/intern/error.h
+option.o: $(hdrdir)/ruby/internal/intern/eval.h
+option.o: $(hdrdir)/ruby/internal/intern/file.h
+option.o: $(hdrdir)/ruby/internal/intern/gc.h
+option.o: $(hdrdir)/ruby/internal/intern/hash.h
+option.o: $(hdrdir)/ruby/internal/intern/io.h
+option.o: $(hdrdir)/ruby/internal/intern/load.h
+option.o: $(hdrdir)/ruby/internal/intern/marshal.h
+option.o: $(hdrdir)/ruby/internal/intern/numeric.h
+option.o: $(hdrdir)/ruby/internal/intern/object.h
+option.o: $(hdrdir)/ruby/internal/intern/parse.h
+option.o: $(hdrdir)/ruby/internal/intern/proc.h
+option.o: $(hdrdir)/ruby/internal/intern/process.h
+option.o: $(hdrdir)/ruby/internal/intern/random.h
+option.o: $(hdrdir)/ruby/internal/intern/range.h
+option.o: $(hdrdir)/ruby/internal/intern/rational.h
+option.o: $(hdrdir)/ruby/internal/intern/re.h
+option.o: $(hdrdir)/ruby/internal/intern/ruby.h
+option.o: $(hdrdir)/ruby/internal/intern/select.h
+option.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+option.o: $(hdrdir)/ruby/internal/intern/signal.h
+option.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+option.o: $(hdrdir)/ruby/internal/intern/string.h
+option.o: $(hdrdir)/ruby/internal/intern/struct.h
+option.o: $(hdrdir)/ruby/internal/intern/thread.h
+option.o: $(hdrdir)/ruby/internal/intern/time.h
+option.o: $(hdrdir)/ruby/internal/intern/variable.h
+option.o: $(hdrdir)/ruby/internal/intern/vm.h
+option.o: $(hdrdir)/ruby/internal/interpreter.h
+option.o: $(hdrdir)/ruby/internal/iterator.h
+option.o: $(hdrdir)/ruby/internal/memory.h
+option.o: $(hdrdir)/ruby/internal/method.h
+option.o: $(hdrdir)/ruby/internal/module.h
+option.o: $(hdrdir)/ruby/internal/newobj.h
+option.o: $(hdrdir)/ruby/internal/rgengc.h
+option.o: $(hdrdir)/ruby/internal/scan_args.h
+option.o: $(hdrdir)/ruby/internal/special_consts.h
+option.o: $(hdrdir)/ruby/internal/static_assert.h
+option.o: $(hdrdir)/ruby/internal/stdalign.h
+option.o: $(hdrdir)/ruby/internal/stdbool.h
+option.o: $(hdrdir)/ruby/internal/symbol.h
+option.o: $(hdrdir)/ruby/internal/token_paste.h
+option.o: $(hdrdir)/ruby/internal/value.h
+option.o: $(hdrdir)/ruby/internal/value_type.h
+option.o: $(hdrdir)/ruby/internal/variable.h
+option.o: $(hdrdir)/ruby/internal/warning_push.h
+option.o: $(hdrdir)/ruby/internal/xmalloc.h
option.o: $(hdrdir)/ruby/assert.h
option.o: $(hdrdir)/ruby/backward.h
+option.o: $(hdrdir)/ruby/backward/2/assume.h
+option.o: $(hdrdir)/ruby/backward/2/attributes.h
+option.o: $(hdrdir)/ruby/backward/2/bool.h
+option.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+option.o: $(hdrdir)/ruby/backward/2/inttypes.h
+option.o: $(hdrdir)/ruby/backward/2/limits.h
+option.o: $(hdrdir)/ruby/backward/2/long_long.h
+option.o: $(hdrdir)/ruby/backward/2/stdalign.h
+option.o: $(hdrdir)/ruby/backward/2/stdarg.h
option.o: $(hdrdir)/ruby/defines.h
option.o: $(hdrdir)/ruby/encoding.h
option.o: $(hdrdir)/ruby/intern.h
@@ -161,6 +1270,17 @@ option.o: $(hdrdir)/ruby/subst.h
option.o: $(hdrdir)/ruby/thread.h
option.o: $(hdrdir)/ruby/util.h
option.o: $(top_srcdir)/internal.h
+option.o: $(top_srcdir)/internal/array.h
+option.o: $(top_srcdir)/internal/compilers.h
+option.o: $(top_srcdir)/internal/error.h
+option.o: $(top_srcdir)/internal/gc.h
+option.o: $(top_srcdir)/internal/io.h
+option.o: $(top_srcdir)/internal/serial.h
+option.o: $(top_srcdir)/internal/static_assert.h
+option.o: $(top_srcdir)/internal/string.h
+option.o: $(top_srcdir)/internal/thread.h
+option.o: $(top_srcdir)/internal/vm.h
+option.o: $(top_srcdir)/internal/warnings.h
option.o: constdefs.h
option.o: option.c
option.o: rubysocket.h
@@ -168,8 +1288,157 @@ option.o: sockport.h
raddrinfo.o: $(RUBY_EXTCONF_H)
raddrinfo.o: $(arch_hdrdir)/ruby/config.h
raddrinfo.o: $(hdrdir)/ruby.h
+raddrinfo.o: $(hdrdir)/ruby/internal/anyargs.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+raddrinfo.o: $(hdrdir)/ruby/internal/assume.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/artificial.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/cold.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/const.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/error.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/format.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/noalias.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/noinline.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/pure.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/restrict.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/warning.h
+raddrinfo.o: $(hdrdir)/ruby/internal/attr/weakref.h
+raddrinfo.o: $(hdrdir)/ruby/internal/cast.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+raddrinfo.o: $(hdrdir)/ruby/internal/compiler_since.h
+raddrinfo.o: $(hdrdir)/ruby/internal/config.h
+raddrinfo.o: $(hdrdir)/ruby/internal/constant_p.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rarray.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rbasic.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rbignum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rclass.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rdata.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rfile.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rhash.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/robject.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rregexp.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rstring.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rstruct.h
+raddrinfo.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+raddrinfo.o: $(hdrdir)/ruby/internal/ctype.h
+raddrinfo.o: $(hdrdir)/ruby/internal/dllexport.h
+raddrinfo.o: $(hdrdir)/ruby/internal/dosish.h
+raddrinfo.o: $(hdrdir)/ruby/internal/error.h
+raddrinfo.o: $(hdrdir)/ruby/internal/eval.h
+raddrinfo.o: $(hdrdir)/ruby/internal/event.h
+raddrinfo.o: $(hdrdir)/ruby/internal/fl_type.h
+raddrinfo.o: $(hdrdir)/ruby/internal/gc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/glob.h
+raddrinfo.o: $(hdrdir)/ruby/internal/globals.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/attribute.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/builtin.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/extension.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/feature.h
+raddrinfo.o: $(hdrdir)/ruby/internal/has/warning.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/array.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/bignum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/class.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/compar.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/complex.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/cont.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/dir.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/enum.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/error.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/eval.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/file.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/gc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/hash.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/io.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/load.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/marshal.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/numeric.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/object.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/parse.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/proc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/process.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/random.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/range.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/rational.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/re.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/ruby.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/select.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/signal.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/string.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/struct.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/thread.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/time.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/variable.h
+raddrinfo.o: $(hdrdir)/ruby/internal/intern/vm.h
+raddrinfo.o: $(hdrdir)/ruby/internal/interpreter.h
+raddrinfo.o: $(hdrdir)/ruby/internal/iterator.h
+raddrinfo.o: $(hdrdir)/ruby/internal/memory.h
+raddrinfo.o: $(hdrdir)/ruby/internal/method.h
+raddrinfo.o: $(hdrdir)/ruby/internal/module.h
+raddrinfo.o: $(hdrdir)/ruby/internal/newobj.h
+raddrinfo.o: $(hdrdir)/ruby/internal/rgengc.h
+raddrinfo.o: $(hdrdir)/ruby/internal/scan_args.h
+raddrinfo.o: $(hdrdir)/ruby/internal/special_consts.h
+raddrinfo.o: $(hdrdir)/ruby/internal/static_assert.h
+raddrinfo.o: $(hdrdir)/ruby/internal/stdalign.h
+raddrinfo.o: $(hdrdir)/ruby/internal/stdbool.h
+raddrinfo.o: $(hdrdir)/ruby/internal/symbol.h
+raddrinfo.o: $(hdrdir)/ruby/internal/token_paste.h
+raddrinfo.o: $(hdrdir)/ruby/internal/value.h
+raddrinfo.o: $(hdrdir)/ruby/internal/value_type.h
+raddrinfo.o: $(hdrdir)/ruby/internal/variable.h
+raddrinfo.o: $(hdrdir)/ruby/internal/warning_push.h
+raddrinfo.o: $(hdrdir)/ruby/internal/xmalloc.h
raddrinfo.o: $(hdrdir)/ruby/assert.h
raddrinfo.o: $(hdrdir)/ruby/backward.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/assume.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/attributes.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/bool.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/inttypes.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/limits.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/long_long.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/stdalign.h
+raddrinfo.o: $(hdrdir)/ruby/backward/2/stdarg.h
raddrinfo.o: $(hdrdir)/ruby/defines.h
raddrinfo.o: $(hdrdir)/ruby/encoding.h
raddrinfo.o: $(hdrdir)/ruby/intern.h
@@ -183,6 +1452,17 @@ raddrinfo.o: $(hdrdir)/ruby/subst.h
raddrinfo.o: $(hdrdir)/ruby/thread.h
raddrinfo.o: $(hdrdir)/ruby/util.h
raddrinfo.o: $(top_srcdir)/internal.h
+raddrinfo.o: $(top_srcdir)/internal/array.h
+raddrinfo.o: $(top_srcdir)/internal/compilers.h
+raddrinfo.o: $(top_srcdir)/internal/error.h
+raddrinfo.o: $(top_srcdir)/internal/gc.h
+raddrinfo.o: $(top_srcdir)/internal/io.h
+raddrinfo.o: $(top_srcdir)/internal/serial.h
+raddrinfo.o: $(top_srcdir)/internal/static_assert.h
+raddrinfo.o: $(top_srcdir)/internal/string.h
+raddrinfo.o: $(top_srcdir)/internal/thread.h
+raddrinfo.o: $(top_srcdir)/internal/vm.h
+raddrinfo.o: $(top_srcdir)/internal/warnings.h
raddrinfo.o: constdefs.h
raddrinfo.o: raddrinfo.c
raddrinfo.o: rubysocket.h
@@ -190,8 +1470,157 @@ raddrinfo.o: sockport.h
socket.o: $(RUBY_EXTCONF_H)
socket.o: $(arch_hdrdir)/ruby/config.h
socket.o: $(hdrdir)/ruby.h
+socket.o: $(hdrdir)/ruby/internal/anyargs.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+socket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+socket.o: $(hdrdir)/ruby/internal/assume.h
+socket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+socket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+socket.o: $(hdrdir)/ruby/internal/attr/cold.h
+socket.o: $(hdrdir)/ruby/internal/attr/const.h
+socket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+socket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+socket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+socket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+socket.o: $(hdrdir)/ruby/internal/attr/error.h
+socket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+socket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+socket.o: $(hdrdir)/ruby/internal/attr/format.h
+socket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+socket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+socket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+socket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+socket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+socket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+socket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+socket.o: $(hdrdir)/ruby/internal/attr/pure.h
+socket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+socket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+socket.o: $(hdrdir)/ruby/internal/attr/warning.h
+socket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+socket.o: $(hdrdir)/ruby/internal/cast.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+socket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+socket.o: $(hdrdir)/ruby/internal/compiler_since.h
+socket.o: $(hdrdir)/ruby/internal/config.h
+socket.o: $(hdrdir)/ruby/internal/constant_p.h
+socket.o: $(hdrdir)/ruby/internal/core.h
+socket.o: $(hdrdir)/ruby/internal/core/rarray.h
+socket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+socket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+socket.o: $(hdrdir)/ruby/internal/core/rclass.h
+socket.o: $(hdrdir)/ruby/internal/core/rdata.h
+socket.o: $(hdrdir)/ruby/internal/core/rfile.h
+socket.o: $(hdrdir)/ruby/internal/core/rhash.h
+socket.o: $(hdrdir)/ruby/internal/core/robject.h
+socket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+socket.o: $(hdrdir)/ruby/internal/core/rstring.h
+socket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+socket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+socket.o: $(hdrdir)/ruby/internal/ctype.h
+socket.o: $(hdrdir)/ruby/internal/dllexport.h
+socket.o: $(hdrdir)/ruby/internal/dosish.h
+socket.o: $(hdrdir)/ruby/internal/error.h
+socket.o: $(hdrdir)/ruby/internal/eval.h
+socket.o: $(hdrdir)/ruby/internal/event.h
+socket.o: $(hdrdir)/ruby/internal/fl_type.h
+socket.o: $(hdrdir)/ruby/internal/gc.h
+socket.o: $(hdrdir)/ruby/internal/glob.h
+socket.o: $(hdrdir)/ruby/internal/globals.h
+socket.o: $(hdrdir)/ruby/internal/has/attribute.h
+socket.o: $(hdrdir)/ruby/internal/has/builtin.h
+socket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+socket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+socket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+socket.o: $(hdrdir)/ruby/internal/has/extension.h
+socket.o: $(hdrdir)/ruby/internal/has/feature.h
+socket.o: $(hdrdir)/ruby/internal/has/warning.h
+socket.o: $(hdrdir)/ruby/internal/intern/array.h
+socket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+socket.o: $(hdrdir)/ruby/internal/intern/class.h
+socket.o: $(hdrdir)/ruby/internal/intern/compar.h
+socket.o: $(hdrdir)/ruby/internal/intern/complex.h
+socket.o: $(hdrdir)/ruby/internal/intern/cont.h
+socket.o: $(hdrdir)/ruby/internal/intern/dir.h
+socket.o: $(hdrdir)/ruby/internal/intern/enum.h
+socket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+socket.o: $(hdrdir)/ruby/internal/intern/error.h
+socket.o: $(hdrdir)/ruby/internal/intern/eval.h
+socket.o: $(hdrdir)/ruby/internal/intern/file.h
+socket.o: $(hdrdir)/ruby/internal/intern/gc.h
+socket.o: $(hdrdir)/ruby/internal/intern/hash.h
+socket.o: $(hdrdir)/ruby/internal/intern/io.h
+socket.o: $(hdrdir)/ruby/internal/intern/load.h
+socket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+socket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+socket.o: $(hdrdir)/ruby/internal/intern/object.h
+socket.o: $(hdrdir)/ruby/internal/intern/parse.h
+socket.o: $(hdrdir)/ruby/internal/intern/proc.h
+socket.o: $(hdrdir)/ruby/internal/intern/process.h
+socket.o: $(hdrdir)/ruby/internal/intern/random.h
+socket.o: $(hdrdir)/ruby/internal/intern/range.h
+socket.o: $(hdrdir)/ruby/internal/intern/rational.h
+socket.o: $(hdrdir)/ruby/internal/intern/re.h
+socket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+socket.o: $(hdrdir)/ruby/internal/intern/select.h
+socket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+socket.o: $(hdrdir)/ruby/internal/intern/signal.h
+socket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+socket.o: $(hdrdir)/ruby/internal/intern/string.h
+socket.o: $(hdrdir)/ruby/internal/intern/struct.h
+socket.o: $(hdrdir)/ruby/internal/intern/thread.h
+socket.o: $(hdrdir)/ruby/internal/intern/time.h
+socket.o: $(hdrdir)/ruby/internal/intern/variable.h
+socket.o: $(hdrdir)/ruby/internal/intern/vm.h
+socket.o: $(hdrdir)/ruby/internal/interpreter.h
+socket.o: $(hdrdir)/ruby/internal/iterator.h
+socket.o: $(hdrdir)/ruby/internal/memory.h
+socket.o: $(hdrdir)/ruby/internal/method.h
+socket.o: $(hdrdir)/ruby/internal/module.h
+socket.o: $(hdrdir)/ruby/internal/newobj.h
+socket.o: $(hdrdir)/ruby/internal/rgengc.h
+socket.o: $(hdrdir)/ruby/internal/scan_args.h
+socket.o: $(hdrdir)/ruby/internal/special_consts.h
+socket.o: $(hdrdir)/ruby/internal/static_assert.h
+socket.o: $(hdrdir)/ruby/internal/stdalign.h
+socket.o: $(hdrdir)/ruby/internal/stdbool.h
+socket.o: $(hdrdir)/ruby/internal/symbol.h
+socket.o: $(hdrdir)/ruby/internal/token_paste.h
+socket.o: $(hdrdir)/ruby/internal/value.h
+socket.o: $(hdrdir)/ruby/internal/value_type.h
+socket.o: $(hdrdir)/ruby/internal/variable.h
+socket.o: $(hdrdir)/ruby/internal/warning_push.h
+socket.o: $(hdrdir)/ruby/internal/xmalloc.h
socket.o: $(hdrdir)/ruby/assert.h
socket.o: $(hdrdir)/ruby/backward.h
+socket.o: $(hdrdir)/ruby/backward/2/assume.h
+socket.o: $(hdrdir)/ruby/backward/2/attributes.h
+socket.o: $(hdrdir)/ruby/backward/2/bool.h
+socket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+socket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+socket.o: $(hdrdir)/ruby/backward/2/limits.h
+socket.o: $(hdrdir)/ruby/backward/2/long_long.h
+socket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+socket.o: $(hdrdir)/ruby/backward/2/stdarg.h
socket.o: $(hdrdir)/ruby/defines.h
socket.o: $(hdrdir)/ruby/encoding.h
socket.o: $(hdrdir)/ruby/intern.h
@@ -205,6 +1634,17 @@ socket.o: $(hdrdir)/ruby/subst.h
socket.o: $(hdrdir)/ruby/thread.h
socket.o: $(hdrdir)/ruby/util.h
socket.o: $(top_srcdir)/internal.h
+socket.o: $(top_srcdir)/internal/array.h
+socket.o: $(top_srcdir)/internal/compilers.h
+socket.o: $(top_srcdir)/internal/error.h
+socket.o: $(top_srcdir)/internal/gc.h
+socket.o: $(top_srcdir)/internal/io.h
+socket.o: $(top_srcdir)/internal/serial.h
+socket.o: $(top_srcdir)/internal/static_assert.h
+socket.o: $(top_srcdir)/internal/string.h
+socket.o: $(top_srcdir)/internal/thread.h
+socket.o: $(top_srcdir)/internal/vm.h
+socket.o: $(top_srcdir)/internal/warnings.h
socket.o: constdefs.h
socket.o: rubysocket.h
socket.o: socket.c
@@ -212,8 +1652,157 @@ socket.o: sockport.h
sockssocket.o: $(RUBY_EXTCONF_H)
sockssocket.o: $(arch_hdrdir)/ruby/config.h
sockssocket.o: $(hdrdir)/ruby.h
+sockssocket.o: $(hdrdir)/ruby/internal/anyargs.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sockssocket.o: $(hdrdir)/ruby/internal/assume.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/const.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/error.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/format.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+sockssocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sockssocket.o: $(hdrdir)/ruby/internal/cast.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sockssocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+sockssocket.o: $(hdrdir)/ruby/internal/config.h
+sockssocket.o: $(hdrdir)/ruby/internal/constant_p.h
+sockssocket.o: $(hdrdir)/ruby/internal/core.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/robject.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sockssocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sockssocket.o: $(hdrdir)/ruby/internal/ctype.h
+sockssocket.o: $(hdrdir)/ruby/internal/dllexport.h
+sockssocket.o: $(hdrdir)/ruby/internal/dosish.h
+sockssocket.o: $(hdrdir)/ruby/internal/error.h
+sockssocket.o: $(hdrdir)/ruby/internal/eval.h
+sockssocket.o: $(hdrdir)/ruby/internal/event.h
+sockssocket.o: $(hdrdir)/ruby/internal/fl_type.h
+sockssocket.o: $(hdrdir)/ruby/internal/gc.h
+sockssocket.o: $(hdrdir)/ruby/internal/glob.h
+sockssocket.o: $(hdrdir)/ruby/internal/globals.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/extension.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/feature.h
+sockssocket.o: $(hdrdir)/ruby/internal/has/warning.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/array.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/class.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/error.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/file.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/gc.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/io.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/load.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/object.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/process.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/random.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/range.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/re.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/select.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/string.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/time.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+sockssocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+sockssocket.o: $(hdrdir)/ruby/internal/interpreter.h
+sockssocket.o: $(hdrdir)/ruby/internal/iterator.h
+sockssocket.o: $(hdrdir)/ruby/internal/memory.h
+sockssocket.o: $(hdrdir)/ruby/internal/method.h
+sockssocket.o: $(hdrdir)/ruby/internal/module.h
+sockssocket.o: $(hdrdir)/ruby/internal/newobj.h
+sockssocket.o: $(hdrdir)/ruby/internal/rgengc.h
+sockssocket.o: $(hdrdir)/ruby/internal/scan_args.h
+sockssocket.o: $(hdrdir)/ruby/internal/special_consts.h
+sockssocket.o: $(hdrdir)/ruby/internal/static_assert.h
+sockssocket.o: $(hdrdir)/ruby/internal/stdalign.h
+sockssocket.o: $(hdrdir)/ruby/internal/stdbool.h
+sockssocket.o: $(hdrdir)/ruby/internal/symbol.h
+sockssocket.o: $(hdrdir)/ruby/internal/token_paste.h
+sockssocket.o: $(hdrdir)/ruby/internal/value.h
+sockssocket.o: $(hdrdir)/ruby/internal/value_type.h
+sockssocket.o: $(hdrdir)/ruby/internal/variable.h
+sockssocket.o: $(hdrdir)/ruby/internal/warning_push.h
+sockssocket.o: $(hdrdir)/ruby/internal/xmalloc.h
sockssocket.o: $(hdrdir)/ruby/assert.h
sockssocket.o: $(hdrdir)/ruby/backward.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/assume.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/bool.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/limits.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sockssocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
sockssocket.o: $(hdrdir)/ruby/defines.h
sockssocket.o: $(hdrdir)/ruby/encoding.h
sockssocket.o: $(hdrdir)/ruby/intern.h
@@ -227,6 +1816,17 @@ sockssocket.o: $(hdrdir)/ruby/subst.h
sockssocket.o: $(hdrdir)/ruby/thread.h
sockssocket.o: $(hdrdir)/ruby/util.h
sockssocket.o: $(top_srcdir)/internal.h
+sockssocket.o: $(top_srcdir)/internal/array.h
+sockssocket.o: $(top_srcdir)/internal/compilers.h
+sockssocket.o: $(top_srcdir)/internal/error.h
+sockssocket.o: $(top_srcdir)/internal/gc.h
+sockssocket.o: $(top_srcdir)/internal/io.h
+sockssocket.o: $(top_srcdir)/internal/serial.h
+sockssocket.o: $(top_srcdir)/internal/static_assert.h
+sockssocket.o: $(top_srcdir)/internal/string.h
+sockssocket.o: $(top_srcdir)/internal/thread.h
+sockssocket.o: $(top_srcdir)/internal/vm.h
+sockssocket.o: $(top_srcdir)/internal/warnings.h
sockssocket.o: constdefs.h
sockssocket.o: rubysocket.h
sockssocket.o: sockport.h
@@ -234,8 +1834,157 @@ sockssocket.o: sockssocket.c
tcpserver.o: $(RUBY_EXTCONF_H)
tcpserver.o: $(arch_hdrdir)/ruby/config.h
tcpserver.o: $(hdrdir)/ruby.h
+tcpserver.o: $(hdrdir)/ruby/internal/anyargs.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+tcpserver.o: $(hdrdir)/ruby/internal/assume.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/artificial.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/cold.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/const.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/error.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/format.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/noalias.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/noinline.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/pure.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/restrict.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/warning.h
+tcpserver.o: $(hdrdir)/ruby/internal/attr/weakref.h
+tcpserver.o: $(hdrdir)/ruby/internal/cast.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+tcpserver.o: $(hdrdir)/ruby/internal/compiler_since.h
+tcpserver.o: $(hdrdir)/ruby/internal/config.h
+tcpserver.o: $(hdrdir)/ruby/internal/constant_p.h
+tcpserver.o: $(hdrdir)/ruby/internal/core.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rarray.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rbasic.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rbignum.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rclass.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rdata.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rfile.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rhash.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/robject.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rregexp.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rstring.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rstruct.h
+tcpserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+tcpserver.o: $(hdrdir)/ruby/internal/ctype.h
+tcpserver.o: $(hdrdir)/ruby/internal/dllexport.h
+tcpserver.o: $(hdrdir)/ruby/internal/dosish.h
+tcpserver.o: $(hdrdir)/ruby/internal/error.h
+tcpserver.o: $(hdrdir)/ruby/internal/eval.h
+tcpserver.o: $(hdrdir)/ruby/internal/event.h
+tcpserver.o: $(hdrdir)/ruby/internal/fl_type.h
+tcpserver.o: $(hdrdir)/ruby/internal/gc.h
+tcpserver.o: $(hdrdir)/ruby/internal/glob.h
+tcpserver.o: $(hdrdir)/ruby/internal/globals.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/attribute.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/builtin.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/extension.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/feature.h
+tcpserver.o: $(hdrdir)/ruby/internal/has/warning.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/array.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/bignum.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/class.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/compar.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/complex.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/cont.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/dir.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/enum.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/error.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/eval.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/file.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/gc.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/hash.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/io.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/load.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/marshal.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/numeric.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/object.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/parse.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/proc.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/process.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/random.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/range.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/rational.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/re.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/ruby.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/select.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/signal.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/string.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/struct.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/thread.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/time.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/variable.h
+tcpserver.o: $(hdrdir)/ruby/internal/intern/vm.h
+tcpserver.o: $(hdrdir)/ruby/internal/interpreter.h
+tcpserver.o: $(hdrdir)/ruby/internal/iterator.h
+tcpserver.o: $(hdrdir)/ruby/internal/memory.h
+tcpserver.o: $(hdrdir)/ruby/internal/method.h
+tcpserver.o: $(hdrdir)/ruby/internal/module.h
+tcpserver.o: $(hdrdir)/ruby/internal/newobj.h
+tcpserver.o: $(hdrdir)/ruby/internal/rgengc.h
+tcpserver.o: $(hdrdir)/ruby/internal/scan_args.h
+tcpserver.o: $(hdrdir)/ruby/internal/special_consts.h
+tcpserver.o: $(hdrdir)/ruby/internal/static_assert.h
+tcpserver.o: $(hdrdir)/ruby/internal/stdalign.h
+tcpserver.o: $(hdrdir)/ruby/internal/stdbool.h
+tcpserver.o: $(hdrdir)/ruby/internal/symbol.h
+tcpserver.o: $(hdrdir)/ruby/internal/token_paste.h
+tcpserver.o: $(hdrdir)/ruby/internal/value.h
+tcpserver.o: $(hdrdir)/ruby/internal/value_type.h
+tcpserver.o: $(hdrdir)/ruby/internal/variable.h
+tcpserver.o: $(hdrdir)/ruby/internal/warning_push.h
+tcpserver.o: $(hdrdir)/ruby/internal/xmalloc.h
tcpserver.o: $(hdrdir)/ruby/assert.h
tcpserver.o: $(hdrdir)/ruby/backward.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/assume.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/attributes.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/bool.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/inttypes.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/limits.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/long_long.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/stdalign.h
+tcpserver.o: $(hdrdir)/ruby/backward/2/stdarg.h
tcpserver.o: $(hdrdir)/ruby/defines.h
tcpserver.o: $(hdrdir)/ruby/encoding.h
tcpserver.o: $(hdrdir)/ruby/intern.h
@@ -249,6 +1998,17 @@ tcpserver.o: $(hdrdir)/ruby/subst.h
tcpserver.o: $(hdrdir)/ruby/thread.h
tcpserver.o: $(hdrdir)/ruby/util.h
tcpserver.o: $(top_srcdir)/internal.h
+tcpserver.o: $(top_srcdir)/internal/array.h
+tcpserver.o: $(top_srcdir)/internal/compilers.h
+tcpserver.o: $(top_srcdir)/internal/error.h
+tcpserver.o: $(top_srcdir)/internal/gc.h
+tcpserver.o: $(top_srcdir)/internal/io.h
+tcpserver.o: $(top_srcdir)/internal/serial.h
+tcpserver.o: $(top_srcdir)/internal/static_assert.h
+tcpserver.o: $(top_srcdir)/internal/string.h
+tcpserver.o: $(top_srcdir)/internal/thread.h
+tcpserver.o: $(top_srcdir)/internal/vm.h
+tcpserver.o: $(top_srcdir)/internal/warnings.h
tcpserver.o: constdefs.h
tcpserver.o: rubysocket.h
tcpserver.o: sockport.h
@@ -256,8 +2016,157 @@ tcpserver.o: tcpserver.c
tcpsocket.o: $(RUBY_EXTCONF_H)
tcpsocket.o: $(arch_hdrdir)/ruby/config.h
tcpsocket.o: $(hdrdir)/ruby.h
+tcpsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+tcpsocket.o: $(hdrdir)/ruby/internal/assume.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+tcpsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+tcpsocket.o: $(hdrdir)/ruby/internal/cast.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+tcpsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+tcpsocket.o: $(hdrdir)/ruby/internal/config.h
+tcpsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+tcpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+tcpsocket.o: $(hdrdir)/ruby/internal/ctype.h
+tcpsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+tcpsocket.o: $(hdrdir)/ruby/internal/dosish.h
+tcpsocket.o: $(hdrdir)/ruby/internal/error.h
+tcpsocket.o: $(hdrdir)/ruby/internal/eval.h
+tcpsocket.o: $(hdrdir)/ruby/internal/event.h
+tcpsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+tcpsocket.o: $(hdrdir)/ruby/internal/gc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/glob.h
+tcpsocket.o: $(hdrdir)/ruby/internal/globals.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+tcpsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/gc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+tcpsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+tcpsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+tcpsocket.o: $(hdrdir)/ruby/internal/iterator.h
+tcpsocket.o: $(hdrdir)/ruby/internal/memory.h
+tcpsocket.o: $(hdrdir)/ruby/internal/method.h
+tcpsocket.o: $(hdrdir)/ruby/internal/module.h
+tcpsocket.o: $(hdrdir)/ruby/internal/newobj.h
+tcpsocket.o: $(hdrdir)/ruby/internal/rgengc.h
+tcpsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+tcpsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+tcpsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+tcpsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+tcpsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+tcpsocket.o: $(hdrdir)/ruby/internal/symbol.h
+tcpsocket.o: $(hdrdir)/ruby/internal/token_paste.h
+tcpsocket.o: $(hdrdir)/ruby/internal/value.h
+tcpsocket.o: $(hdrdir)/ruby/internal/value_type.h
+tcpsocket.o: $(hdrdir)/ruby/internal/variable.h
+tcpsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+tcpsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
tcpsocket.o: $(hdrdir)/ruby/assert.h
tcpsocket.o: $(hdrdir)/ruby/backward.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+tcpsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
tcpsocket.o: $(hdrdir)/ruby/defines.h
tcpsocket.o: $(hdrdir)/ruby/encoding.h
tcpsocket.o: $(hdrdir)/ruby/intern.h
@@ -271,6 +2180,17 @@ tcpsocket.o: $(hdrdir)/ruby/subst.h
tcpsocket.o: $(hdrdir)/ruby/thread.h
tcpsocket.o: $(hdrdir)/ruby/util.h
tcpsocket.o: $(top_srcdir)/internal.h
+tcpsocket.o: $(top_srcdir)/internal/array.h
+tcpsocket.o: $(top_srcdir)/internal/compilers.h
+tcpsocket.o: $(top_srcdir)/internal/error.h
+tcpsocket.o: $(top_srcdir)/internal/gc.h
+tcpsocket.o: $(top_srcdir)/internal/io.h
+tcpsocket.o: $(top_srcdir)/internal/serial.h
+tcpsocket.o: $(top_srcdir)/internal/static_assert.h
+tcpsocket.o: $(top_srcdir)/internal/string.h
+tcpsocket.o: $(top_srcdir)/internal/thread.h
+tcpsocket.o: $(top_srcdir)/internal/vm.h
+tcpsocket.o: $(top_srcdir)/internal/warnings.h
tcpsocket.o: constdefs.h
tcpsocket.o: rubysocket.h
tcpsocket.o: sockport.h
@@ -278,8 +2198,157 @@ tcpsocket.o: tcpsocket.c
udpsocket.o: $(RUBY_EXTCONF_H)
udpsocket.o: $(arch_hdrdir)/ruby/config.h
udpsocket.o: $(hdrdir)/ruby.h
+udpsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+udpsocket.o: $(hdrdir)/ruby/internal/assume.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+udpsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+udpsocket.o: $(hdrdir)/ruby/internal/cast.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+udpsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+udpsocket.o: $(hdrdir)/ruby/internal/config.h
+udpsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+udpsocket.o: $(hdrdir)/ruby/internal/core.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+udpsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+udpsocket.o: $(hdrdir)/ruby/internal/ctype.h
+udpsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+udpsocket.o: $(hdrdir)/ruby/internal/dosish.h
+udpsocket.o: $(hdrdir)/ruby/internal/error.h
+udpsocket.o: $(hdrdir)/ruby/internal/eval.h
+udpsocket.o: $(hdrdir)/ruby/internal/event.h
+udpsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+udpsocket.o: $(hdrdir)/ruby/internal/gc.h
+udpsocket.o: $(hdrdir)/ruby/internal/glob.h
+udpsocket.o: $(hdrdir)/ruby/internal/globals.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+udpsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/gc.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+udpsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+udpsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+udpsocket.o: $(hdrdir)/ruby/internal/iterator.h
+udpsocket.o: $(hdrdir)/ruby/internal/memory.h
+udpsocket.o: $(hdrdir)/ruby/internal/method.h
+udpsocket.o: $(hdrdir)/ruby/internal/module.h
+udpsocket.o: $(hdrdir)/ruby/internal/newobj.h
+udpsocket.o: $(hdrdir)/ruby/internal/rgengc.h
+udpsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+udpsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+udpsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+udpsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+udpsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+udpsocket.o: $(hdrdir)/ruby/internal/symbol.h
+udpsocket.o: $(hdrdir)/ruby/internal/token_paste.h
+udpsocket.o: $(hdrdir)/ruby/internal/value.h
+udpsocket.o: $(hdrdir)/ruby/internal/value_type.h
+udpsocket.o: $(hdrdir)/ruby/internal/variable.h
+udpsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+udpsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
udpsocket.o: $(hdrdir)/ruby/assert.h
udpsocket.o: $(hdrdir)/ruby/backward.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+udpsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
udpsocket.o: $(hdrdir)/ruby/defines.h
udpsocket.o: $(hdrdir)/ruby/encoding.h
udpsocket.o: $(hdrdir)/ruby/intern.h
@@ -293,6 +2362,17 @@ udpsocket.o: $(hdrdir)/ruby/subst.h
udpsocket.o: $(hdrdir)/ruby/thread.h
udpsocket.o: $(hdrdir)/ruby/util.h
udpsocket.o: $(top_srcdir)/internal.h
+udpsocket.o: $(top_srcdir)/internal/array.h
+udpsocket.o: $(top_srcdir)/internal/compilers.h
+udpsocket.o: $(top_srcdir)/internal/error.h
+udpsocket.o: $(top_srcdir)/internal/gc.h
+udpsocket.o: $(top_srcdir)/internal/io.h
+udpsocket.o: $(top_srcdir)/internal/serial.h
+udpsocket.o: $(top_srcdir)/internal/static_assert.h
+udpsocket.o: $(top_srcdir)/internal/string.h
+udpsocket.o: $(top_srcdir)/internal/thread.h
+udpsocket.o: $(top_srcdir)/internal/vm.h
+udpsocket.o: $(top_srcdir)/internal/warnings.h
udpsocket.o: constdefs.h
udpsocket.o: rubysocket.h
udpsocket.o: sockport.h
@@ -300,8 +2380,157 @@ udpsocket.o: udpsocket.c
unixserver.o: $(RUBY_EXTCONF_H)
unixserver.o: $(arch_hdrdir)/ruby/config.h
unixserver.o: $(hdrdir)/ruby.h
+unixserver.o: $(hdrdir)/ruby/internal/anyargs.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+unixserver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+unixserver.o: $(hdrdir)/ruby/internal/assume.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/artificial.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/cold.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/const.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/error.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/format.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/noalias.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/noinline.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/pure.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/restrict.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/warning.h
+unixserver.o: $(hdrdir)/ruby/internal/attr/weakref.h
+unixserver.o: $(hdrdir)/ruby/internal/cast.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+unixserver.o: $(hdrdir)/ruby/internal/compiler_since.h
+unixserver.o: $(hdrdir)/ruby/internal/config.h
+unixserver.o: $(hdrdir)/ruby/internal/constant_p.h
+unixserver.o: $(hdrdir)/ruby/internal/core.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rarray.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rbasic.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rbignum.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rclass.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rdata.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rfile.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rhash.h
+unixserver.o: $(hdrdir)/ruby/internal/core/robject.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rregexp.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rstring.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rstruct.h
+unixserver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+unixserver.o: $(hdrdir)/ruby/internal/ctype.h
+unixserver.o: $(hdrdir)/ruby/internal/dllexport.h
+unixserver.o: $(hdrdir)/ruby/internal/dosish.h
+unixserver.o: $(hdrdir)/ruby/internal/error.h
+unixserver.o: $(hdrdir)/ruby/internal/eval.h
+unixserver.o: $(hdrdir)/ruby/internal/event.h
+unixserver.o: $(hdrdir)/ruby/internal/fl_type.h
+unixserver.o: $(hdrdir)/ruby/internal/gc.h
+unixserver.o: $(hdrdir)/ruby/internal/glob.h
+unixserver.o: $(hdrdir)/ruby/internal/globals.h
+unixserver.o: $(hdrdir)/ruby/internal/has/attribute.h
+unixserver.o: $(hdrdir)/ruby/internal/has/builtin.h
+unixserver.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+unixserver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+unixserver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+unixserver.o: $(hdrdir)/ruby/internal/has/extension.h
+unixserver.o: $(hdrdir)/ruby/internal/has/feature.h
+unixserver.o: $(hdrdir)/ruby/internal/has/warning.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/array.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/bignum.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/class.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/compar.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/complex.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/cont.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/dir.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/enum.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/error.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/eval.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/file.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/gc.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/hash.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/io.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/load.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/marshal.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/numeric.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/object.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/parse.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/proc.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/process.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/random.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/range.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/rational.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/re.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/ruby.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/select.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/signal.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/string.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/struct.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/thread.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/time.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/variable.h
+unixserver.o: $(hdrdir)/ruby/internal/intern/vm.h
+unixserver.o: $(hdrdir)/ruby/internal/interpreter.h
+unixserver.o: $(hdrdir)/ruby/internal/iterator.h
+unixserver.o: $(hdrdir)/ruby/internal/memory.h
+unixserver.o: $(hdrdir)/ruby/internal/method.h
+unixserver.o: $(hdrdir)/ruby/internal/module.h
+unixserver.o: $(hdrdir)/ruby/internal/newobj.h
+unixserver.o: $(hdrdir)/ruby/internal/rgengc.h
+unixserver.o: $(hdrdir)/ruby/internal/scan_args.h
+unixserver.o: $(hdrdir)/ruby/internal/special_consts.h
+unixserver.o: $(hdrdir)/ruby/internal/static_assert.h
+unixserver.o: $(hdrdir)/ruby/internal/stdalign.h
+unixserver.o: $(hdrdir)/ruby/internal/stdbool.h
+unixserver.o: $(hdrdir)/ruby/internal/symbol.h
+unixserver.o: $(hdrdir)/ruby/internal/token_paste.h
+unixserver.o: $(hdrdir)/ruby/internal/value.h
+unixserver.o: $(hdrdir)/ruby/internal/value_type.h
+unixserver.o: $(hdrdir)/ruby/internal/variable.h
+unixserver.o: $(hdrdir)/ruby/internal/warning_push.h
+unixserver.o: $(hdrdir)/ruby/internal/xmalloc.h
unixserver.o: $(hdrdir)/ruby/assert.h
unixserver.o: $(hdrdir)/ruby/backward.h
+unixserver.o: $(hdrdir)/ruby/backward/2/assume.h
+unixserver.o: $(hdrdir)/ruby/backward/2/attributes.h
+unixserver.o: $(hdrdir)/ruby/backward/2/bool.h
+unixserver.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+unixserver.o: $(hdrdir)/ruby/backward/2/inttypes.h
+unixserver.o: $(hdrdir)/ruby/backward/2/limits.h
+unixserver.o: $(hdrdir)/ruby/backward/2/long_long.h
+unixserver.o: $(hdrdir)/ruby/backward/2/stdalign.h
+unixserver.o: $(hdrdir)/ruby/backward/2/stdarg.h
unixserver.o: $(hdrdir)/ruby/defines.h
unixserver.o: $(hdrdir)/ruby/encoding.h
unixserver.o: $(hdrdir)/ruby/intern.h
@@ -315,6 +2544,17 @@ unixserver.o: $(hdrdir)/ruby/subst.h
unixserver.o: $(hdrdir)/ruby/thread.h
unixserver.o: $(hdrdir)/ruby/util.h
unixserver.o: $(top_srcdir)/internal.h
+unixserver.o: $(top_srcdir)/internal/array.h
+unixserver.o: $(top_srcdir)/internal/compilers.h
+unixserver.o: $(top_srcdir)/internal/error.h
+unixserver.o: $(top_srcdir)/internal/gc.h
+unixserver.o: $(top_srcdir)/internal/io.h
+unixserver.o: $(top_srcdir)/internal/serial.h
+unixserver.o: $(top_srcdir)/internal/static_assert.h
+unixserver.o: $(top_srcdir)/internal/string.h
+unixserver.o: $(top_srcdir)/internal/thread.h
+unixserver.o: $(top_srcdir)/internal/vm.h
+unixserver.o: $(top_srcdir)/internal/warnings.h
unixserver.o: constdefs.h
unixserver.o: rubysocket.h
unixserver.o: sockport.h
@@ -322,8 +2562,157 @@ unixserver.o: unixserver.c
unixsocket.o: $(RUBY_EXTCONF_H)
unixsocket.o: $(arch_hdrdir)/ruby/config.h
unixsocket.o: $(hdrdir)/ruby.h
+unixsocket.o: $(hdrdir)/ruby/internal/anyargs.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+unixsocket.o: $(hdrdir)/ruby/internal/assume.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/artificial.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/cold.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/const.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/error.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/format.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/noalias.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/noinline.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/pure.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/restrict.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/warning.h
+unixsocket.o: $(hdrdir)/ruby/internal/attr/weakref.h
+unixsocket.o: $(hdrdir)/ruby/internal/cast.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+unixsocket.o: $(hdrdir)/ruby/internal/compiler_since.h
+unixsocket.o: $(hdrdir)/ruby/internal/config.h
+unixsocket.o: $(hdrdir)/ruby/internal/constant_p.h
+unixsocket.o: $(hdrdir)/ruby/internal/core.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rarray.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rbasic.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rbignum.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rclass.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rdata.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rfile.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rhash.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/robject.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rregexp.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rstring.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rstruct.h
+unixsocket.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+unixsocket.o: $(hdrdir)/ruby/internal/ctype.h
+unixsocket.o: $(hdrdir)/ruby/internal/dllexport.h
+unixsocket.o: $(hdrdir)/ruby/internal/dosish.h
+unixsocket.o: $(hdrdir)/ruby/internal/error.h
+unixsocket.o: $(hdrdir)/ruby/internal/eval.h
+unixsocket.o: $(hdrdir)/ruby/internal/event.h
+unixsocket.o: $(hdrdir)/ruby/internal/fl_type.h
+unixsocket.o: $(hdrdir)/ruby/internal/gc.h
+unixsocket.o: $(hdrdir)/ruby/internal/glob.h
+unixsocket.o: $(hdrdir)/ruby/internal/globals.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/attribute.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/builtin.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/extension.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/feature.h
+unixsocket.o: $(hdrdir)/ruby/internal/has/warning.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/array.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/bignum.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/class.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/compar.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/complex.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/cont.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/dir.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/enum.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/error.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/eval.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/file.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/gc.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/hash.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/io.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/load.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/marshal.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/numeric.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/object.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/parse.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/proc.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/process.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/random.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/range.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/rational.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/re.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/ruby.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/select.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/signal.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/string.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/struct.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/thread.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/time.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/variable.h
+unixsocket.o: $(hdrdir)/ruby/internal/intern/vm.h
+unixsocket.o: $(hdrdir)/ruby/internal/interpreter.h
+unixsocket.o: $(hdrdir)/ruby/internal/iterator.h
+unixsocket.o: $(hdrdir)/ruby/internal/memory.h
+unixsocket.o: $(hdrdir)/ruby/internal/method.h
+unixsocket.o: $(hdrdir)/ruby/internal/module.h
+unixsocket.o: $(hdrdir)/ruby/internal/newobj.h
+unixsocket.o: $(hdrdir)/ruby/internal/rgengc.h
+unixsocket.o: $(hdrdir)/ruby/internal/scan_args.h
+unixsocket.o: $(hdrdir)/ruby/internal/special_consts.h
+unixsocket.o: $(hdrdir)/ruby/internal/static_assert.h
+unixsocket.o: $(hdrdir)/ruby/internal/stdalign.h
+unixsocket.o: $(hdrdir)/ruby/internal/stdbool.h
+unixsocket.o: $(hdrdir)/ruby/internal/symbol.h
+unixsocket.o: $(hdrdir)/ruby/internal/token_paste.h
+unixsocket.o: $(hdrdir)/ruby/internal/value.h
+unixsocket.o: $(hdrdir)/ruby/internal/value_type.h
+unixsocket.o: $(hdrdir)/ruby/internal/variable.h
+unixsocket.o: $(hdrdir)/ruby/internal/warning_push.h
+unixsocket.o: $(hdrdir)/ruby/internal/xmalloc.h
unixsocket.o: $(hdrdir)/ruby/assert.h
unixsocket.o: $(hdrdir)/ruby/backward.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/assume.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/attributes.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/bool.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/inttypes.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/limits.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/long_long.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/stdalign.h
+unixsocket.o: $(hdrdir)/ruby/backward/2/stdarg.h
unixsocket.o: $(hdrdir)/ruby/defines.h
unixsocket.o: $(hdrdir)/ruby/encoding.h
unixsocket.o: $(hdrdir)/ruby/intern.h
@@ -337,6 +2726,17 @@ unixsocket.o: $(hdrdir)/ruby/subst.h
unixsocket.o: $(hdrdir)/ruby/thread.h
unixsocket.o: $(hdrdir)/ruby/util.h
unixsocket.o: $(top_srcdir)/internal.h
+unixsocket.o: $(top_srcdir)/internal/array.h
+unixsocket.o: $(top_srcdir)/internal/compilers.h
+unixsocket.o: $(top_srcdir)/internal/error.h
+unixsocket.o: $(top_srcdir)/internal/gc.h
+unixsocket.o: $(top_srcdir)/internal/io.h
+unixsocket.o: $(top_srcdir)/internal/serial.h
+unixsocket.o: $(top_srcdir)/internal/static_assert.h
+unixsocket.o: $(top_srcdir)/internal/string.h
+unixsocket.o: $(top_srcdir)/internal/thread.h
+unixsocket.o: $(top_srcdir)/internal/vm.h
+unixsocket.o: $(top_srcdir)/internal/warnings.h
unixsocket.o: constdefs.h
unixsocket.o: rubysocket.h
unixsocket.o: sockport.h
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index 1a67e0013e..c86cc8f8c0 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -444,7 +444,6 @@ else
test_func = "socket(0,0,0)"
have_library("nsl", 't_open("", 0, (struct t_info *)NULL)', headers) # SunOS
have_library("socket", "socket(0,0,0)", headers) # SunOS
- have_library("anl", 'getaddrinfo_a', headers)
end
if have_func(test_func, headers)
@@ -506,7 +505,6 @@ EOF
unless have_func("gethostname((char *)0, 0)", headers)
have_func("uname((struct utsname *)NULL)", headers)
end
- have_func("getaddrinfo_a", headers)
ipv6 = false
default_ipv6 = /haiku/ !~ RUBY_PLATFORM
diff --git a/ext/socket/ifaddr.c b/ext/socket/ifaddr.c
index 26aa0c8082..1da259bd6f 100644
--- a/ext/socket/ifaddr.c
+++ b/ext/socket/ifaddr.c
@@ -459,7 +459,8 @@ rsock_init_sockifaddr(void)
*
* Socket::Ifaddr represents a result of getifaddrs() function.
*/
- rb_cSockIfaddr = rb_define_class_under(rb_cSocket, "Ifaddr", rb_cData);
+ rb_cSockIfaddr = rb_define_class_under(rb_cSocket, "Ifaddr", rb_cObject);
+ rb_undef_alloc_func(rb_cSockIfaddr);
rb_define_method(rb_cSockIfaddr, "inspect", ifaddr_inspect, 0);
rb_define_method(rb_cSockIfaddr, "name", ifaddr_name, 0);
rb_define_method(rb_cSockIfaddr, "ifindex", ifaddr_ifindex, 0);
diff --git a/ext/socket/init.c b/ext/socket/init.c
index 6d17ecfb4e..af46b8edaa 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -408,84 +408,30 @@ rsock_write_nonblock(VALUE sock, VALUE str, VALUE ex)
}
#endif /* MSG_DONTWAIT_RELIABLE */
-/* returns true if SOCK_CLOEXEC is supported */
-int rsock_detect_cloexec(int fd)
+static int
+rsock_socket0(int domain, int type, int proto)
{
#ifdef SOCK_CLOEXEC
- int flags = fcntl(fd, F_GETFD);
-
- if (flags == -1)
- rb_bug("rsock_detect_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
+ type |= SOCK_CLOEXEC;
+#endif
- if (flags & FD_CLOEXEC)
- return 1;
+#ifdef SOCK_NONBLOCK
+ type |= SOCK_NONBLOCK;
#endif
- return 0;
-}
-#ifdef SOCK_CLOEXEC
-static int
-rsock_socket0(int domain, int type, int proto)
-{
- int ret;
- static int cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
-
- if (cloexec_state > 0) { /* common path, if SOCK_CLOEXEC is defined */
- ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto);
- if (ret >= 0) {
- if (ret <= 2)
- goto fix_cloexec;
- goto update_max_fd;
- }
- }
- else if (cloexec_state < 0) { /* usually runs once only for detection */
- ret = socket(domain, type|SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT, proto);
- if (ret >= 0) {
- cloexec_state = rsock_detect_cloexec(ret);
- if (cloexec_state == 0 || ret <= 2)
- goto fix_cloexec;
- goto update_max_fd;
- }
- else if (ret == -1 && errno == EINVAL) {
- /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */
- ret = socket(domain, type, proto);
- if (ret != -1) {
- cloexec_state = 0;
- /* fall through to fix_cloexec */
- }
- }
- }
- else { /* cloexec_state == 0 */
- ret = socket(domain, type, proto);
- }
- if (ret == -1)
+ int result = socket(domain, type, proto);
+
+ if (result == -1)
return -1;
-fix_cloexec:
- rb_maygvl_fd_fix_cloexec(ret);
- if (RSOCK_NONBLOCK_DEFAULT) {
- rsock_make_fd_nonblock(ret);
- }
-update_max_fd:
- rb_update_max_fd(ret);
- return ret;
-}
-#else /* !SOCK_CLOEXEC */
-static int
-rsock_socket0(int domain, int type, int proto)
-{
- int ret = socket(domain, type, proto);
+ rb_fd_fix_cloexec(result);
- if (ret == -1)
- return -1;
- rb_fd_fix_cloexec(ret);
- if (RSOCK_NONBLOCK_DEFAULT) {
- rsock_make_fd_nonblock(ret);
- }
+#ifndef SOCK_NONBLOCK
+ rsock_make_fd_nonblock(result);
+#endif
- return ret;
+ return result;
}
-#endif /* !SOCK_CLOEXEC */
int
rsock_socket(int domain, int type, int proto)
@@ -505,7 +451,7 @@ rsock_socket(int domain, int type, int proto)
/* emulate blocking connect behavior on EINTR or non-blocking socket */
static int
-wait_connectable(int fd)
+wait_connectable(int fd, struct timeval *timeout)
{
int sockerr, revents;
socklen_t sockerrlen;
@@ -542,7 +488,7 @@ wait_connectable(int fd)
*
* Note: rb_wait_for_single_fd already retries on EINTR/ERESTART
*/
- revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, NULL);
+ revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, timeout);
if (revents < 0)
return -1;
@@ -557,6 +503,12 @@ wait_connectable(int fd)
* be defensive in case some platforms set SO_ERROR on the original,
* interrupted connect()
*/
+
+ /* when the connection timed out, no errno is set and revents is 0. */
+ if (timeout && revents == 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
case EINTR:
#ifdef ERESTART
case ERESTART:
@@ -604,7 +556,7 @@ socks_connect_blocking(void *data)
#endif
int
-rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
+rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks, struct timeval *timeout)
{
int status;
rb_blocking_function_t *func = connect_blocking;
@@ -628,7 +580,7 @@ rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
#ifdef EINPROGRESS
case EINPROGRESS:
#endif
- return wait_connectable(fd);
+ return wait_connectable(fd, timeout);
}
}
return status;
@@ -637,6 +589,10 @@ rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks)
void
rsock_make_fd_nonblock(int fd)
{
+#ifdef _WIN32
+ return;
+#endif
+
int flags;
#ifdef F_GETFL
flags = fcntl(fd, F_GETFL);
@@ -653,56 +609,34 @@ rsock_make_fd_nonblock(int fd)
}
static int
-cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len,
- int nonblock)
+cloexec_accept(int socket, struct sockaddr *address, socklen_t *address_len)
{
- int ret;
socklen_t len0 = 0;
-#ifdef HAVE_ACCEPT4
- static int try_accept4 = 1;
-#endif
- if (RSOCK_NONBLOCK_DEFAULT) {
- nonblock = 1;
- }
if (address_len) len0 = *address_len;
+
#ifdef HAVE_ACCEPT4
- if (try_accept4) {
- int flags = 0;
-#ifdef SOCK_CLOEXEC
- flags |= SOCK_CLOEXEC;
-#endif
+ int flags = SOCK_CLOEXEC;
+
#ifdef SOCK_NONBLOCK
- if (nonblock) {
- flags |= SOCK_NONBLOCK;
- }
+ flags |= SOCK_NONBLOCK;
#endif
- ret = accept4(socket, address, address_len, flags);
- /* accept4 is available since Linux 2.6.28, glibc 2.10. */
- if (ret != -1) {
- if (ret <= 2)
- rb_maygvl_fd_fix_cloexec(ret);
+
+ int result = accept4(socket, address, address_len, flags);
+ if (result == -1) return -1;
+
#ifndef SOCK_NONBLOCK
- if (nonblock) {
- rsock_make_fd_nonblock(ret);
- }
+ rsock_make_fd_nonblock(result);
#endif
- if (address_len && len0 < *address_len) *address_len = len0;
- return ret;
- }
- if (errno != ENOSYS) {
- return -1;
- }
- try_accept4 = 0;
- }
+#else
+ int result = accept(socket, address, address_len);
+ if (result == -1) return -1;
+
+ rb_maygvl_fd_fix_cloexec(result);
+ rsock_make_fd_nonblock(result);
#endif
- ret = accept(socket, address, address_len);
- if (ret == -1) return -1;
+
if (address_len && len0 < *address_len) *address_len = len0;
- rb_maygvl_fd_fix_cloexec(ret);
- if (nonblock) {
- rsock_make_fd_nonblock(ret);
- }
- return ret;
+ return result;
}
VALUE
@@ -712,7 +646,7 @@ rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr,
int fd2;
rb_io_set_nonblock(fptr);
- fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len, 1);
+ fd2 = cloexec_accept(fptr->fd, (struct sockaddr*)sockaddr, len);
if (fd2 < 0) {
int e = errno;
switch (e) {
@@ -744,7 +678,7 @@ static VALUE
accept_blocking(void *data)
{
struct accept_arg *arg = data;
- return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len, 0);
+ return (VALUE)cloexec_accept(arg->fd, arg->sockaddr, arg->len);
}
VALUE
diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c
index a2cb6e0e12..72fea789a5 100644
--- a/ext/socket/ipsocket.c
+++ b/ext/socket/ipsocket.c
@@ -19,6 +19,8 @@ struct inetsock_arg
} remote, local;
int type;
int fd;
+ VALUE resolv_timeout;
+ VALUE connect_timeout;
};
static VALUE
@@ -49,10 +51,20 @@ init_inetsock_internal(VALUE v)
int fd, status = 0, local = 0;
int family = AF_UNSPEC;
const char *syscall = 0;
+ VALUE connect_timeout = arg->connect_timeout;
+ struct timeval tv_storage;
+ struct timeval *tv = NULL;
+
+ if (!NIL_P(connect_timeout)) {
+ tv_storage = rb_time_interval(connect_timeout);
+ tv = &tv_storage;
+ }
arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv,
family, SOCK_STREAM,
(type == INET_SERVER) ? AI_PASSIVE : 0);
+
+
/*
* Maybe also accept a local address
*/
@@ -113,7 +125,7 @@ init_inetsock_internal(VALUE v)
if (status >= 0) {
status = rsock_connect(fd, res->ai_addr, res->ai_addrlen,
- (type == INET_SOCKS));
+ (type == INET_SOCKS), tv);
syscall = "connect(2)";
}
}
@@ -157,7 +169,8 @@ init_inetsock_internal(VALUE v)
VALUE
rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv,
- VALUE local_host, VALUE local_serv, int type)
+ VALUE local_host, VALUE local_serv, int type,
+ VALUE resolv_timeout, VALUE connect_timeout)
{
struct inetsock_arg arg;
arg.sock = sock;
@@ -169,6 +182,8 @@ rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv,
arg.local.res = 0;
arg.type = type;
arg.fd = -1;
+ arg.resolv_timeout = resolv_timeout;
+ arg.connect_timeout = connect_timeout;
return rb_ensure(init_inetsock_internal, (VALUE)&arg,
inetsock_cleanup, (VALUE)&arg);
}
diff --git a/ext/socket/option.c b/ext/socket/option.c
index 5ad44cdcd8..4b33b3f1d3 100644
--- a/ext/socket/option.c
+++ b/ext/socket/option.c
@@ -106,9 +106,9 @@ sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALU
VALUE
rsock_sockopt_new(int family, int level, int optname, VALUE data)
{
- NEWOBJ_OF(obj, struct RObject, rb_cSockOpt, T_OBJECT);
+ VALUE obj = rb_obj_alloc(rb_cSockOpt);
StringValue(data);
- sockopt_initialize((VALUE)obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data);
+ sockopt_initialize(obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data);
return (VALUE)obj;
}
diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c
index c4de1b09e1..d99edfe057 100644
--- a/ext/socket/raddrinfo.c
+++ b/ext/socket/raddrinfo.c
@@ -199,27 +199,6 @@ nogvl_getaddrinfo(void *arg)
}
#endif
-#ifdef HAVE_GETADDRINFO_A
-struct gai_suspend_arg
-{
- struct gaicb *req;
- struct timespec *timeout;
-};
-
-static void *
-nogvl_gai_suspend(void *arg)
-{
- int ret;
- struct gai_suspend_arg *ptr = arg;
- struct gaicb const *wait_reqs[1];
-
- wait_reqs[0] = ptr->req;
- ret = gai_suspend(wait_reqs, 1, ptr->timeout);
-
- return (void *)(VALUE)ret;
-}
-#endif
-
static int
numeric_getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
@@ -339,59 +318,6 @@ rb_getaddrinfo(const char *node, const char *service,
return ret;
}
-#ifdef HAVE_GETADDRINFO_A
-int
-rb_getaddrinfo_a(const char *node, const char *service,
- const struct addrinfo *hints,
- struct rb_addrinfo **res, struct timespec *timeout)
-{
- struct addrinfo *ai;
- int ret;
- int allocated_by_malloc = 0;
-
- ret = numeric_getaddrinfo(node, service, hints, &ai);
- if (ret == 0)
- allocated_by_malloc = 1;
- else {
- struct gai_suspend_arg arg;
- struct gaicb *reqs[1];
- struct gaicb req;
-
- req.ar_name = node;
- req.ar_service = service;
- req.ar_request = hints;
-
- reqs[0] = &req;
- ret = getaddrinfo_a(GAI_NOWAIT, reqs, 1, NULL);
- if (ret) return ret;
-
- arg.req = &req;
- arg.timeout = timeout;
-
- ret = (int)(VALUE)rb_thread_call_without_gvl(nogvl_gai_suspend, &arg, RUBY_UBF_IO, 0);
-
- if (ret) {
- /* on Ubuntu 18.04 (or other systems), gai_suspend(3) returns EAI_SYSTEM/ENOENT on timeout */
- if (ret == EAI_SYSTEM && errno == ENOENT) {
- return EAI_AGAIN;
- } else {
- return ret;
- }
- }
-
- ret = gai_error(reqs[0]);
- ai = reqs[0]->ar_result;
- }
-
- if (ret == 0) {
- *res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
- (*res)->allocated_by_malloc = allocated_by_malloc;
- (*res)->ai = ai;
- }
- return ret;
-}
-#endif
-
void
rb_freeaddrinfo(struct rb_addrinfo *ai)
{
@@ -600,42 +526,6 @@ rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_h
return res;
}
-#ifdef HAVE_GETADDRINFO_A
-static struct rb_addrinfo*
-rsock_getaddrinfo_a(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout)
-{
- struct rb_addrinfo* res = NULL;
- char *hostp, *portp;
- int error;
- char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
- int additional_flags = 0;
-
- hostp = host_str(host, hbuf, sizeof(hbuf), &additional_flags);
- portp = port_str(port, pbuf, sizeof(pbuf), &additional_flags);
-
- if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
- hints->ai_socktype = SOCK_DGRAM;
- }
- hints->ai_flags |= additional_flags;
-
- if (NIL_P(timeout)) {
- error = rb_getaddrinfo(hostp, portp, hints, &res);
- } else {
- struct timespec _timeout = rb_time_timespec_interval(timeout);
- error = rb_getaddrinfo_a(hostp, portp, hints, &res, &_timeout);
- }
-
- if (error) {
- if (hostp && hostp[strlen(hostp)-1] == '\n') {
- rb_raise(rb_eSocket, "newline at the end of hostname");
- }
- rsock_raise_socket_error("getaddrinfo_a", error);
- }
-
- return res;
-}
-#endif
-
int
rsock_fd_family(int fd)
{
@@ -941,15 +831,7 @@ call_getaddrinfo(VALUE node, VALUE service,
hints.ai_flags = NUM2INT(flags);
}
-#ifdef HAVE_GETADDRINFO_A
- if (NIL_P(timeout)) {
- res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
- } else {
- res = rsock_getaddrinfo_a(node, service, &hints, socktype_hack, timeout);
- }
-#else
res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
-#endif
if (res == NULL)
rb_raise(rb_eSocket, "host not found");
@@ -1913,7 +1795,7 @@ addrinfo_to_sockaddr(VALUE self)
* call-seq:
* addrinfo.canonname => string or nil
*
- * returns the canonical name as an string.
+ * returns the canonical name as a string.
*
* nil is returned if no canonical name.
*
@@ -2496,7 +2378,9 @@ addrinfo_s_getaddrinfo(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "24:", &node, &service, &family, &socktype,
&protocol, &flags, &opts);
rb_get_kwargs(opts, &id_timeout, 0, 1, &timeout);
- timeout = Qnil;
+ if (timeout == Qundef) {
+ timeout = Qnil;
+ }
return addrinfo_list_new(node, service, family, socktype, protocol, flags, timeout);
}
@@ -2684,7 +2568,7 @@ rsock_init_addrinfo(void)
*/
id_timeout = rb_intern("timeout");
- rb_cAddrinfo = rb_define_class("Addrinfo", rb_cData);
+ rb_cAddrinfo = rb_define_class("Addrinfo", rb_cObject);
rb_define_alloc_func(rb_cAddrinfo, addrinfo_s_allocate);
rb_define_method(rb_cAddrinfo, "initialize", addrinfo_initialize, -1);
rb_define_method(rb_cAddrinfo, "inspect", addrinfo_inspect, 0);
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
index 0ce77a5f6e..f0e4f3a4a0 100644
--- a/ext/socket/rubysocket.h
+++ b/ext/socket/rubysocket.h
@@ -1,12 +1,22 @@
#ifndef RUBY_SOCKET_H
#define RUBY_SOCKET_H 1
-#include "ruby/ruby.h"
-#include "ruby/io.h"
-#include "ruby/thread.h"
-#include "ruby/util.h"
-#include "internal.h"
+#include "ruby/config.h"
+#include RUBY_EXTCONF_H
+
+#if defined(__sun) || defined(_AIX)
+/* (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of T_DATA. Let
+ * us honour system definition by undefining ours.
+ *
+ * See also [ruby-core:4261]
+ */
+# include "ruby/ruby.h"
+# undef T_DATA
+#endif
+
+#include <errno.h>
#include <stdio.h>
+
#include <sys/types.h>
#include <sys/stat.h>
@@ -26,13 +36,7 @@
# if defined(_MSC_VER)
# undef HAVE_TYPE_STRUCT_SOCKADDR_DL
# endif
-/*
- * FIXME: failures if we make nonblocking the default
- * [ruby-core:89973] [ruby-core:89976] [ruby-core:89977] [Bug #14968]
- */
-# define RSOCK_NONBLOCK_DEFAULT (0)
#else
-# define RSOCK_NONBLOCK_DEFAULT (0)
# include <sys/socket.h>
# include <netinet/in.h>
# ifdef HAVE_NETINET_IN_SYSTM_H
@@ -56,12 +60,11 @@
#ifdef HAVE_NETPACKET_PACKET_H
# include <netpacket/packet.h>
#endif
+
#ifdef HAVE_NET_ETHERNET_H
# include <net/ethernet.h>
#endif
-#include <errno.h>
-
#ifdef HAVE_SYS_UN_H
# include <sys/un.h>
#endif
@@ -87,12 +90,15 @@
# endif
# include <ifaddrs.h>
#endif
+
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
+
#ifdef HAVE_SYS_SOCKIO_H
# include <sys/sockio.h>
#endif
+
#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif
@@ -100,16 +106,40 @@
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
+
#ifdef HAVE_SYS_UCRED_H
# include <sys/ucred.h>
#endif
+
#ifdef HAVE_UCRED_H
# include <ucred.h>
#endif
+
#ifdef HAVE_NET_IF_DL_H
# include <net/if_dl.h>
#endif
+#ifdef SOCKS5
+# include <socks.h>
+#endif
+
+#ifndef HAVE_GETADDRINFO
+# include "addrinfo.h"
+#endif
+
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/error.h"
+#include "internal/gc.h"
+#include "internal/io.h"
+#include "internal/thread.h"
+#include "internal/vm.h"
+#include "ruby/io.h"
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+#include "ruby/util.h"
+#include "sockport.h"
+
#ifndef HAVE_TYPE_SOCKLEN_T
typedef int socklen_t;
#endif
@@ -143,11 +173,6 @@ unsigned int if_nametoindex(const char *);
*/
#define pseudo_AF_FTIP pseudo_AF_RTIP
-#ifndef HAVE_GETADDRINFO
-# include "addrinfo.h"
-#endif
-
-#include "sockport.h"
#ifndef NI_MAXHOST
# define NI_MAXHOST 1025
@@ -229,7 +254,6 @@ typedef union {
#define INET_SOCKS 2
extern int rsock_do_not_reverse_lookup;
-extern int rsock_cmsg_cloexec_state;
#define FMODE_NOREVLOOKUP 0x100
/* common socket families only */
@@ -255,9 +279,7 @@ extern VALUE rb_eSocket;
#ifdef SOCKS
extern VALUE rb_cSOCKSSocket;
-# ifdef SOCKS5
-# include <socks.h>
-# else
+# ifndef SOCKS5
void SOCKSinit();
int Rconnect();
# endif
@@ -298,6 +320,7 @@ int rb_getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_
int rsock_fd_family(int fd);
struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags);
struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack);
+
VALUE rsock_fd_socket_addrinfo(int fd, struct sockaddr *addr, socklen_t len);
VALUE rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len);
@@ -323,7 +346,7 @@ int rsock_socket(int domain, int type, int proto);
int rsock_detect_cloexec(int fd);
VALUE rsock_init_sock(VALUE sock, int fd);
VALUE rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass);
-VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type);
+VALUE rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv, VALUE local_host, VALUE local_serv, int type, VALUE resolv_timeout, VALUE connect_timeout);
VALUE rsock_init_unixsock(VALUE sock, VALUE path, int server);
struct rsock_send_arg {
@@ -348,7 +371,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);
+int rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks, struct timeval *timeout);
VALUE rsock_s_accept(VALUE klass, int fd, struct sockaddr *sockaddr, socklen_t *len);
VALUE rsock_s_accept_nonblock(VALUE klass, VALUE ex, rb_io_t *fptr,
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index bfeb30340c..3d8c65032c 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -168,93 +168,47 @@ pair_yield(VALUE pair)
#endif
#if defined HAVE_SOCKETPAIR
-
-#ifdef SOCK_CLOEXEC
static int
-rsock_socketpair0(int domain, int type, int protocol, int sv[2])
+rsock_socketpair0(int domain, int type, int protocol, int descriptors[2])
{
- int ret;
- static int cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
- static const int default_flags = SOCK_CLOEXEC|RSOCK_NONBLOCK_DEFAULT;
+#ifdef SOCK_CLOEXEC
+ type |= SOCK_CLOEXEC;
+#endif
- if (cloexec_state > 0) { /* common path, if SOCK_CLOEXEC is defined */
- ret = socketpair(domain, type|default_flags, protocol, sv);
- if (ret == 0 && (sv[0] <= 2 || sv[1] <= 2)) {
- goto fix_cloexec; /* highly unlikely */
- }
- goto update_max_fd;
- }
- else if (cloexec_state < 0) { /* usually runs once only for detection */
- ret = socketpair(domain, type|default_flags, protocol, sv);
- if (ret == 0) {
- cloexec_state = rsock_detect_cloexec(sv[0]);
- if ((cloexec_state == 0) || (sv[0] <= 2 || sv[1] <= 2))
- goto fix_cloexec;
- goto update_max_fd;
- }
- else if (ret == -1 && errno == EINVAL) {
- /* SOCK_CLOEXEC is available since Linux 2.6.27. Linux 2.6.18 fails with EINVAL */
- ret = socketpair(domain, type, protocol, sv);
- if (ret != -1) {
- /* The reason of EINVAL may be other than SOCK_CLOEXEC.
- * So disable SOCK_CLOEXEC only if socketpair() succeeds without SOCK_CLOEXEC.
- * Ex. Socket.pair(:UNIX, 0xff) fails with EINVAL.
- */
- cloexec_state = 0;
- }
- }
- }
- else { /* cloexec_state == 0 */
- ret = socketpair(domain, type, protocol, sv);
- }
- if (ret == -1) {
- return -1;
- }
+#ifdef SOCK_NONBLOCK
+ type |= SOCK_NONBLOCK;
+#endif
-fix_cloexec:
- rb_maygvl_fd_fix_cloexec(sv[0]);
- rb_maygvl_fd_fix_cloexec(sv[1]);
- if (RSOCK_NONBLOCK_DEFAULT) {
- rsock_make_fd_nonblock(sv[0]);
- rsock_make_fd_nonblock(sv[1]);
- }
+ int result = socketpair(domain, type, protocol, descriptors);
-update_max_fd:
- rb_update_max_fd(sv[0]);
- rb_update_max_fd(sv[1]);
+ if (result == -1)
+ return -1;
- return ret;
-}
-#else /* !SOCK_CLOEXEC */
-static int
-rsock_socketpair0(int domain, int type, int protocol, int sv[2])
-{
- int ret = socketpair(domain, type, protocol, sv);
+#ifndef SOCK_CLOEXEC
+ rb_fd_fix_cloexec(descriptors[0]);
+ rb_fd_fix_cloexec(descriptors[1]);
+#endif
- if (ret == -1)
- return -1;
+#ifndef SOCK_NONBLOCK
+ rsock_make_fd_nonblock(descriptors[0]);
+ rsock_make_fd_nonblock(descriptors[1]);
+#endif
- rb_fd_fix_cloexec(sv[0]);
- rb_fd_fix_cloexec(sv[1]);
- if (RSOCK_NONBLOCK_DEFAULT) {
- rsock_make_fd_nonblock(sv[0]);
- rsock_make_fd_nonblock(sv[1]);
- }
- return ret;
+ return result;
}
-#endif /* !SOCK_CLOEXEC */
static int
-rsock_socketpair(int domain, int type, int protocol, int sv[2])
+rsock_socketpair(int domain, int type, int protocol, int descriptors[2])
{
- int ret;
+ int result;
+
+ result = rsock_socketpair0(domain, type, protocol, descriptors);
- ret = rsock_socketpair0(domain, type, protocol, sv);
- if (ret < 0 && rb_gc_for_fd(errno)) {
- ret = rsock_socketpair0(domain, type, protocol, sv);
+ if (result < 0 && rb_gc_for_fd(errno)) {
+ result = rsock_socketpair0(domain, type, protocol, descriptors);
}
- return ret;
+ return result;
}
/*
@@ -439,7 +393,7 @@ sock_connect(VALUE sock, VALUE addr)
addr = rb_str_new4(addr);
GetOpenFile(sock, fptr);
fd = fptr->fd;
- n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0);
+ n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, NULL);
if (n < 0) {
rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai);
}
@@ -1011,6 +965,7 @@ sock_sockaddr(struct sockaddr *addr, socklen_t len)
static VALUE
sock_s_gethostbyname(VALUE obj, VALUE host)
{
+ rb_warn("Socket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead.");
struct rb_addrinfo *res =
rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME);
return rsock_make_hostent(host, res, sock_sockaddr);
@@ -1050,6 +1005,8 @@ sock_s_gethostbyaddr(int argc, VALUE *argv, VALUE _)
VALUE ary, names;
int t = AF_INET;
+ rb_warn("Socket.gethostbyaddr is deprecated; use Addrinfo#getnameinfo instead.");
+
rb_scan_args(argc, argv, "11", &addr, &family);
StringValue(addr);
if (!NIL_P(family)) {
@@ -1227,6 +1184,7 @@ sock_s_getaddrinfo(int argc, VALUE *argv, VALUE _)
if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) {
norevlookup = rsock_do_not_reverse_lookup;
}
+
res = rsock_getaddrinfo(host, port, &hints, 0);
ret = make_addrinfo(res, norevlookup);
@@ -1936,6 +1894,8 @@ socket_s_ip_address_list(VALUE self)
void
Init_socket(void)
{
+ rb_ext_ractor_safe(true);
+
rsock_init_basicsocket();
/*
diff --git a/ext/socket/sockssocket.c b/ext/socket/sockssocket.c
index 82789eeaab..b8b7e12998 100644
--- a/ext/socket/sockssocket.c
+++ b/ext/socket/sockssocket.c
@@ -34,7 +34,7 @@ socks_init(VALUE sock, VALUE host, VALUE port)
init = 1;
}
- return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS);
+ return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS, Qnil, Qnil);
}
#ifdef SOCKS5
diff --git a/ext/socket/tcpserver.c b/ext/socket/tcpserver.c
index 1bbb31adcf..7634420e38 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);
+ return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER, Qnil, Qnil);
}
/*
diff --git a/ext/socket/tcpsocket.c b/ext/socket/tcpsocket.c
index 29a3eda45f..51e77a0de9 100644
--- a/ext/socket/tcpsocket.c
+++ b/ext/socket/tcpsocket.c
@@ -12,23 +12,42 @@
/*
* call-seq:
- * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil)
+ * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil, connect_timeout: nil)
*
* Opens a TCP connection to +remote_host+ on +remote_port+. If +local_host+
* and +local_port+ are specified, then those parameters are used on the local
* end to establish the connection.
+ *
+ * [:connect_timeout] specify the timeout in seconds.
*/
static VALUE
tcp_init(int argc, VALUE *argv, VALUE sock)
{
VALUE remote_host, remote_serv;
VALUE local_host, local_serv;
+ VALUE opt;
+ static ID keyword_ids[2];
+ VALUE kwargs[2];
+ VALUE resolv_timeout = Qnil;
+ VALUE connect_timeout = Qnil;
+
+ if (!keyword_ids[0]) {
+ CONST_ID(keyword_ids[0], "resolv_timeout");
+ CONST_ID(keyword_ids[1], "connect_timeout");
+ }
+
+ rb_scan_args(argc, argv, "22:", &remote_host, &remote_serv,
+ &local_host, &local_serv, &opt);
- rb_scan_args(argc, argv, "22", &remote_host, &remote_serv,
- &local_host, &local_serv);
+ if (!NIL_P(opt)) {
+ rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
+ if (kwargs[0] != Qundef) { resolv_timeout = kwargs[0]; }
+ if (kwargs[1] != Qundef) { connect_timeout = kwargs[1]; }
+ }
return rsock_init_inetsock(sock, remote_host, remote_serv,
- local_host, local_serv, INET_CLIENT);
+ local_host, local_serv, INET_CLIENT,
+ resolv_timeout, connect_timeout);
}
static VALUE
@@ -59,6 +78,7 @@ tcp_sockaddr(struct sockaddr *addr, socklen_t len)
static VALUE
tcp_s_gethostbyname(VALUE obj, VALUE host)
{
+ rb_warn("TCPSocket.gethostbyname is deprecated; use Addrinfo.getaddrinfo instead.");
struct rb_addrinfo *res =
rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME);
return rsock_make_hostent(host, res, tcp_sockaddr);
diff --git a/ext/socket/udpsocket.c b/ext/socket/udpsocket.c
index 6ef8242a1e..593f05522d 100644
--- a/ext/socket/udpsocket.c
+++ b/ext/socket/udpsocket.c
@@ -60,7 +60,7 @@ udp_connect_internal(VALUE v)
rb_io_check_closed(fptr = arg->fptr);
fd = fptr->fd;
for (res = arg->res->ai; res; res = res->ai_next) {
- if (rsock_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) {
+ if (rsock_connect(fd, res->ai_addr, res->ai_addrlen, 0, NULL) >= 0) {
return Qtrue;
}
}
diff --git a/ext/socket/unixsocket.c b/ext/socket/unixsocket.c
index 0c3a01d21e..857cfa6002 100644
--- a/ext/socket/unixsocket.c
+++ b/ext/socket/unixsocket.c
@@ -22,7 +22,7 @@ unixsock_connect_internal(VALUE a)
{
struct unixsock_arg *arg = (struct unixsock_arg *)a;
return (VALUE)rsock_connect(arg->fd, (struct sockaddr*)arg->sockaddr,
- arg->sockaddrlen, 0);
+ arg->sockaddrlen, 0, NULL);
}
static VALUE
@@ -455,11 +455,7 @@ retry:
#endif
rb_update_max_fd(fd);
-
- if (rsock_cmsg_cloexec_state < 0)
- rsock_cmsg_cloexec_state = rsock_detect_cloexec(fd);
- if (rsock_cmsg_cloexec_state == 0 || fd <= 2)
- rb_maygvl_fd_fix_cloexec(fd);
+ rb_maygvl_fd_fix_cloexec(fd);
if (klass == Qnil)
return INT2FIX(fd);
diff --git a/ext/stringio/depend b/ext/stringio/depend
index 02d468b306..5f4b0b53c0 100644
--- a/ext/stringio/depend
+++ b/ext/stringio/depend
@@ -2,8 +2,157 @@
stringio.o: $(RUBY_EXTCONF_H)
stringio.o: $(arch_hdrdir)/ruby/config.h
stringio.o: $(hdrdir)/ruby.h
+stringio.o: $(hdrdir)/ruby/internal/anyargs.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stringio.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stringio.o: $(hdrdir)/ruby/internal/assume.h
+stringio.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stringio.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stringio.o: $(hdrdir)/ruby/internal/attr/cold.h
+stringio.o: $(hdrdir)/ruby/internal/attr/const.h
+stringio.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stringio.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stringio.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stringio.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stringio.o: $(hdrdir)/ruby/internal/attr/error.h
+stringio.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stringio.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stringio.o: $(hdrdir)/ruby/internal/attr/format.h
+stringio.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stringio.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stringio.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stringio.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stringio.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stringio.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stringio.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stringio.o: $(hdrdir)/ruby/internal/attr/pure.h
+stringio.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stringio.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stringio.o: $(hdrdir)/ruby/internal/attr/warning.h
+stringio.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stringio.o: $(hdrdir)/ruby/internal/cast.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stringio.o: $(hdrdir)/ruby/internal/compiler_since.h
+stringio.o: $(hdrdir)/ruby/internal/config.h
+stringio.o: $(hdrdir)/ruby/internal/constant_p.h
+stringio.o: $(hdrdir)/ruby/internal/core.h
+stringio.o: $(hdrdir)/ruby/internal/core/rarray.h
+stringio.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stringio.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stringio.o: $(hdrdir)/ruby/internal/core/rclass.h
+stringio.o: $(hdrdir)/ruby/internal/core/rdata.h
+stringio.o: $(hdrdir)/ruby/internal/core/rfile.h
+stringio.o: $(hdrdir)/ruby/internal/core/rhash.h
+stringio.o: $(hdrdir)/ruby/internal/core/robject.h
+stringio.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stringio.o: $(hdrdir)/ruby/internal/core/rstring.h
+stringio.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stringio.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stringio.o: $(hdrdir)/ruby/internal/ctype.h
+stringio.o: $(hdrdir)/ruby/internal/dllexport.h
+stringio.o: $(hdrdir)/ruby/internal/dosish.h
+stringio.o: $(hdrdir)/ruby/internal/error.h
+stringio.o: $(hdrdir)/ruby/internal/eval.h
+stringio.o: $(hdrdir)/ruby/internal/event.h
+stringio.o: $(hdrdir)/ruby/internal/fl_type.h
+stringio.o: $(hdrdir)/ruby/internal/gc.h
+stringio.o: $(hdrdir)/ruby/internal/glob.h
+stringio.o: $(hdrdir)/ruby/internal/globals.h
+stringio.o: $(hdrdir)/ruby/internal/has/attribute.h
+stringio.o: $(hdrdir)/ruby/internal/has/builtin.h
+stringio.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stringio.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stringio.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stringio.o: $(hdrdir)/ruby/internal/has/extension.h
+stringio.o: $(hdrdir)/ruby/internal/has/feature.h
+stringio.o: $(hdrdir)/ruby/internal/has/warning.h
+stringio.o: $(hdrdir)/ruby/internal/intern/array.h
+stringio.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stringio.o: $(hdrdir)/ruby/internal/intern/class.h
+stringio.o: $(hdrdir)/ruby/internal/intern/compar.h
+stringio.o: $(hdrdir)/ruby/internal/intern/complex.h
+stringio.o: $(hdrdir)/ruby/internal/intern/cont.h
+stringio.o: $(hdrdir)/ruby/internal/intern/dir.h
+stringio.o: $(hdrdir)/ruby/internal/intern/enum.h
+stringio.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stringio.o: $(hdrdir)/ruby/internal/intern/error.h
+stringio.o: $(hdrdir)/ruby/internal/intern/eval.h
+stringio.o: $(hdrdir)/ruby/internal/intern/file.h
+stringio.o: $(hdrdir)/ruby/internal/intern/gc.h
+stringio.o: $(hdrdir)/ruby/internal/intern/hash.h
+stringio.o: $(hdrdir)/ruby/internal/intern/io.h
+stringio.o: $(hdrdir)/ruby/internal/intern/load.h
+stringio.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stringio.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stringio.o: $(hdrdir)/ruby/internal/intern/object.h
+stringio.o: $(hdrdir)/ruby/internal/intern/parse.h
+stringio.o: $(hdrdir)/ruby/internal/intern/proc.h
+stringio.o: $(hdrdir)/ruby/internal/intern/process.h
+stringio.o: $(hdrdir)/ruby/internal/intern/random.h
+stringio.o: $(hdrdir)/ruby/internal/intern/range.h
+stringio.o: $(hdrdir)/ruby/internal/intern/rational.h
+stringio.o: $(hdrdir)/ruby/internal/intern/re.h
+stringio.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stringio.o: $(hdrdir)/ruby/internal/intern/select.h
+stringio.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stringio.o: $(hdrdir)/ruby/internal/intern/signal.h
+stringio.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stringio.o: $(hdrdir)/ruby/internal/intern/string.h
+stringio.o: $(hdrdir)/ruby/internal/intern/struct.h
+stringio.o: $(hdrdir)/ruby/internal/intern/thread.h
+stringio.o: $(hdrdir)/ruby/internal/intern/time.h
+stringio.o: $(hdrdir)/ruby/internal/intern/variable.h
+stringio.o: $(hdrdir)/ruby/internal/intern/vm.h
+stringio.o: $(hdrdir)/ruby/internal/interpreter.h
+stringio.o: $(hdrdir)/ruby/internal/iterator.h
+stringio.o: $(hdrdir)/ruby/internal/memory.h
+stringio.o: $(hdrdir)/ruby/internal/method.h
+stringio.o: $(hdrdir)/ruby/internal/module.h
+stringio.o: $(hdrdir)/ruby/internal/newobj.h
+stringio.o: $(hdrdir)/ruby/internal/rgengc.h
+stringio.o: $(hdrdir)/ruby/internal/scan_args.h
+stringio.o: $(hdrdir)/ruby/internal/special_consts.h
+stringio.o: $(hdrdir)/ruby/internal/static_assert.h
+stringio.o: $(hdrdir)/ruby/internal/stdalign.h
+stringio.o: $(hdrdir)/ruby/internal/stdbool.h
+stringio.o: $(hdrdir)/ruby/internal/symbol.h
+stringio.o: $(hdrdir)/ruby/internal/token_paste.h
+stringio.o: $(hdrdir)/ruby/internal/value.h
+stringio.o: $(hdrdir)/ruby/internal/value_type.h
+stringio.o: $(hdrdir)/ruby/internal/variable.h
+stringio.o: $(hdrdir)/ruby/internal/warning_push.h
+stringio.o: $(hdrdir)/ruby/internal/xmalloc.h
stringio.o: $(hdrdir)/ruby/assert.h
stringio.o: $(hdrdir)/ruby/backward.h
+stringio.o: $(hdrdir)/ruby/backward/2/assume.h
+stringio.o: $(hdrdir)/ruby/backward/2/attributes.h
+stringio.o: $(hdrdir)/ruby/backward/2/bool.h
+stringio.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+stringio.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stringio.o: $(hdrdir)/ruby/backward/2/limits.h
+stringio.o: $(hdrdir)/ruby/backward/2/long_long.h
+stringio.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stringio.o: $(hdrdir)/ruby/backward/2/stdarg.h
stringio.o: $(hdrdir)/ruby/defines.h
stringio.o: $(hdrdir)/ruby/encoding.h
stringio.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index b31e801b2a..8df07e80f6 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -1,3 +1,4 @@
+/* -*- mode: c; indent-tabs-mode: t -*- */
/**********************************************************************
stringio.c -
@@ -11,7 +12,7 @@
**********************************************************************/
-#define STRINGIO_VERSION "0.1.0"
+#define STRINGIO_VERSION "3.0.1"
#include "ruby.h"
#include "ruby/io.h"
@@ -64,7 +65,7 @@ strio_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
n = strchr(n, '|');
}
e = strchr(++n, ':');
- len = e ? e - n : strlen(n);
+ len = e ? e - n : (long)strlen(n);
if (len > 0 && len <= ENCODING_MAXNAMELEN) {
if (e) {
memcpy(encname, n, len);
@@ -599,6 +600,14 @@ strio_closed_write(VALUE self)
return Qtrue;
}
+static struct StringIO *
+strio_to_read(VALUE self)
+{
+ struct StringIO *ptr = readable(self);
+ if (ptr->pos < RSTRING_LEN(ptr->string)) return ptr;
+ return NULL;
+}
+
/*
* call-seq:
* strio.eof -> true or false
@@ -610,8 +619,7 @@ strio_closed_write(VALUE self)
static VALUE
strio_eof(VALUE self)
{
- struct StringIO *ptr = readable(self);
- if (ptr->pos < RSTRING_LEN(ptr->string)) return Qfalse;
+ if (strio_to_read(self)) return Qfalse;
return Qtrue;
}
@@ -821,11 +829,11 @@ strio_get_sync(VALUE self)
static VALUE
strio_each_byte(VALUE self)
{
- struct StringIO *ptr = readable(self);
+ struct StringIO *ptr;
RETURN_ENUMERATOR(self, 0, 0);
- while (ptr->pos < RSTRING_LEN(ptr->string)) {
+ while ((ptr = strio_to_read(self)) != NULL) {
char c = RSTRING_PTR(ptr->string)[ptr->pos++];
rb_yield(CHR2FIX(c));
}
@@ -833,18 +841,6 @@ strio_each_byte(VALUE self)
}
/*
- * This is a deprecated alias for #each_byte.
- */
-static VALUE
-strio_bytes(VALUE self)
-{
- rb_warn("StringIO#bytes is deprecated; use #each_byte instead");
- if (!rb_block_given_p())
- return rb_enumeratorize(self, ID2SYM(rb_intern("each_byte")), 0, 0);
- return strio_each_byte(self);
-}
-
-/*
* call-seq:
* strio.getc -> string or nil
*
@@ -1058,18 +1054,6 @@ strio_each_char(VALUE self)
}
/*
- * This is a deprecated alias for #each_char.
- */
-static VALUE
-strio_chars(VALUE self)
-{
- rb_warn("StringIO#chars is deprecated; use #each_char instead");
- if (!rb_block_given_p())
- return rb_enumeratorize(self, ID2SYM(rb_intern("each_char")), 0, 0);
- return strio_each_char(self);
-}
-
-/*
* call-seq:
* strio.each_codepoint {|c| block } -> strio
* strio.each_codepoint -> anEnumerator
@@ -1088,31 +1072,15 @@ strio_each_codepoint(VALUE self)
ptr = readable(self);
enc = get_enc(ptr);
- for (;;) {
- if (ptr->pos >= RSTRING_LEN(ptr->string)) {
- return self;
- }
-
+ while ((ptr = strio_to_read(self)) != NULL) {
c = rb_enc_codepoint_len(RSTRING_PTR(ptr->string)+ptr->pos,
RSTRING_END(ptr->string), &n, enc);
- rb_yield(UINT2NUM(c));
ptr->pos += n;
+ rb_yield(UINT2NUM(c));
}
return self;
}
-/*
- * This is a deprecated alias for #each_codepoint.
- */
-static VALUE
-strio_codepoints(VALUE self)
-{
- rb_warn("StringIO#codepoints is deprecated; use #each_codepoint instead");
- if (!rb_block_given_p())
- return rb_enumeratorize(self, ID2SYM(rb_intern("each_codepoint")), 0, 0);
- return strio_each_codepoint(self);
-}
-
/* Boyer-Moore search: copied from regex.c */
static void
bm_init_skip(long *skip, const char *pat, long m)
@@ -1364,18 +1332,6 @@ strio_each(int argc, VALUE *argv, VALUE self)
}
/*
- * This is a deprecated alias for #each_line.
- */
-static VALUE
-strio_lines(int argc, VALUE *argv, VALUE self)
-{
- rb_warn("StringIO#lines is deprecated; use #each_line instead");
- if (!rb_block_given_p())
- return rb_enumeratorize(self, ID2SYM(rb_intern("each_line")), argc, argv);
- return strio_each(argc, argv, self);
-}
-
-/*
* call-seq:
* strio.readlines(sep=$/, chomp: false) -> array
* strio.readlines(limit, chomp: false) -> array
@@ -1429,13 +1385,18 @@ strio_write(VALUE self, VALUE str)
long len, olen;
rb_encoding *enc, *enc2;
rb_encoding *const ascii8bit = rb_ascii8bit_encoding();
+ rb_encoding *usascii = 0;
if (!RB_TYPE_P(str, T_STRING))
str = rb_obj_as_string(str);
enc = get_enc(ptr);
enc2 = rb_enc_get(str);
- if (enc != enc2 && enc != ascii8bit) {
- str = rb_str_conv_enc(str, enc2, enc);
+ if (enc != enc2 && enc != ascii8bit && enc != (usascii = rb_usascii_encoding())) {
+ VALUE converted = rb_str_conv_enc(str, enc2, enc);
+ if (converted == str && enc2 != ascii8bit && enc2 != usascii) { /* conversion failed */
+ rb_enc_check(rb_enc_from_encoding(enc), str);
+ }
+ str = converted;
}
len = RSTRING_LEN(str);
if (len == 0) return 0;
@@ -1532,7 +1493,6 @@ strio_read(int argc, VALUE *argv, VALUE self)
long len;
int binary = 0;
- rb_check_arity(argc, 0, 2);
switch (argc) {
case 2:
str = argv[1];
@@ -1572,6 +1532,8 @@ strio_read(int argc, VALUE *argv, VALUE self)
len -= ptr->pos;
}
break;
+ default:
+ rb_error_arity(argc, 0, 2);
}
if (NIL_P(str)) {
rb_encoding *enc = binary ? rb_ascii8bit_encoding() : get_enc(ptr);
@@ -1792,7 +1754,12 @@ void
Init_stringio(void)
{
#undef rb_intern
- VALUE StringIO = rb_define_class("StringIO", rb_cData);
+
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+ VALUE StringIO = rb_define_class("StringIO", rb_cObject);
rb_define_const(StringIO, "VERSION", rb_str_new_cstr(STRINGIO_VERSION));
@@ -1837,13 +1804,9 @@ Init_stringio(void)
rb_define_method(StringIO, "each", strio_each, -1);
rb_define_method(StringIO, "each_line", strio_each, -1);
- rb_define_method(StringIO, "lines", strio_lines, -1);
rb_define_method(StringIO, "each_byte", strio_each_byte, 0);
- rb_define_method(StringIO, "bytes", strio_bytes, 0);
rb_define_method(StringIO, "each_char", strio_each_char, 0);
- rb_define_method(StringIO, "chars", strio_chars, 0);
rb_define_method(StringIO, "each_codepoint", strio_each_codepoint, 0);
- rb_define_method(StringIO, "codepoints", strio_codepoints, 0);
rb_define_method(StringIO, "getc", strio_getc, 0);
rb_define_method(StringIO, "ungetc", strio_ungetc, 1);
rb_define_method(StringIO, "ungetbyte", strio_ungetbyte, 1);
diff --git a/ext/stringio/stringio.gemspec b/ext/stringio/stringio.gemspec
index a16c75753f..524d976cfb 100644
--- a/ext/stringio/stringio.gemspec
+++ b/ext/stringio/stringio.gemspec
@@ -22,13 +22,10 @@ Gem::Specification.new do |s|
s.extensions = ["ext/stringio/extconf.rb"]
s.files = ["README.md", "ext/stringio/extconf.rb", "ext/stringio/stringio.c"]
s.homepage = "https://github.com/ruby/stringio"
- s.licenses = ["BSD-2-Clause"]
+ s.licenses = ["Ruby", "BSD-2-Clause"]
s.required_ruby_version = ">= 2.5"
- s.rubygems_version = "2.6.11"
s.summary = "Pseudo IO on String"
# s.cert_chain = %w[certs/nobu.pem]
# s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
-
- s.add_development_dependency 'rake-compiler'
end
diff --git a/ext/strscan/depend b/ext/strscan/depend
index 212d386f83..f297134d3b 100644
--- a/ext/strscan/depend
+++ b/ext/strscan/depend
@@ -1,8 +1,158 @@
# AUTOGENERATED DEPENDENCIES START
strscan.o: $(RUBY_EXTCONF_H)
strscan.o: $(arch_hdrdir)/ruby/config.h
+strscan.o: $(hdrdir)/ruby/internal/anyargs.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+strscan.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+strscan.o: $(hdrdir)/ruby/internal/assume.h
+strscan.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+strscan.o: $(hdrdir)/ruby/internal/attr/artificial.h
+strscan.o: $(hdrdir)/ruby/internal/attr/cold.h
+strscan.o: $(hdrdir)/ruby/internal/attr/const.h
+strscan.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+strscan.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+strscan.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+strscan.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+strscan.o: $(hdrdir)/ruby/internal/attr/error.h
+strscan.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+strscan.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+strscan.o: $(hdrdir)/ruby/internal/attr/format.h
+strscan.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+strscan.o: $(hdrdir)/ruby/internal/attr/noalias.h
+strscan.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+strscan.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+strscan.o: $(hdrdir)/ruby/internal/attr/noinline.h
+strscan.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+strscan.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+strscan.o: $(hdrdir)/ruby/internal/attr/pure.h
+strscan.o: $(hdrdir)/ruby/internal/attr/restrict.h
+strscan.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+strscan.o: $(hdrdir)/ruby/internal/attr/warning.h
+strscan.o: $(hdrdir)/ruby/internal/attr/weakref.h
+strscan.o: $(hdrdir)/ruby/internal/cast.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+strscan.o: $(hdrdir)/ruby/internal/compiler_since.h
+strscan.o: $(hdrdir)/ruby/internal/config.h
+strscan.o: $(hdrdir)/ruby/internal/constant_p.h
+strscan.o: $(hdrdir)/ruby/internal/core.h
+strscan.o: $(hdrdir)/ruby/internal/core/rarray.h
+strscan.o: $(hdrdir)/ruby/internal/core/rbasic.h
+strscan.o: $(hdrdir)/ruby/internal/core/rbignum.h
+strscan.o: $(hdrdir)/ruby/internal/core/rclass.h
+strscan.o: $(hdrdir)/ruby/internal/core/rdata.h
+strscan.o: $(hdrdir)/ruby/internal/core/rfile.h
+strscan.o: $(hdrdir)/ruby/internal/core/rhash.h
+strscan.o: $(hdrdir)/ruby/internal/core/rmatch.h
+strscan.o: $(hdrdir)/ruby/internal/core/robject.h
+strscan.o: $(hdrdir)/ruby/internal/core/rregexp.h
+strscan.o: $(hdrdir)/ruby/internal/core/rstring.h
+strscan.o: $(hdrdir)/ruby/internal/core/rstruct.h
+strscan.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+strscan.o: $(hdrdir)/ruby/internal/ctype.h
+strscan.o: $(hdrdir)/ruby/internal/dllexport.h
+strscan.o: $(hdrdir)/ruby/internal/dosish.h
+strscan.o: $(hdrdir)/ruby/internal/error.h
+strscan.o: $(hdrdir)/ruby/internal/eval.h
+strscan.o: $(hdrdir)/ruby/internal/event.h
+strscan.o: $(hdrdir)/ruby/internal/fl_type.h
+strscan.o: $(hdrdir)/ruby/internal/gc.h
+strscan.o: $(hdrdir)/ruby/internal/glob.h
+strscan.o: $(hdrdir)/ruby/internal/globals.h
+strscan.o: $(hdrdir)/ruby/internal/has/attribute.h
+strscan.o: $(hdrdir)/ruby/internal/has/builtin.h
+strscan.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+strscan.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+strscan.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+strscan.o: $(hdrdir)/ruby/internal/has/extension.h
+strscan.o: $(hdrdir)/ruby/internal/has/feature.h
+strscan.o: $(hdrdir)/ruby/internal/has/warning.h
+strscan.o: $(hdrdir)/ruby/internal/intern/array.h
+strscan.o: $(hdrdir)/ruby/internal/intern/bignum.h
+strscan.o: $(hdrdir)/ruby/internal/intern/class.h
+strscan.o: $(hdrdir)/ruby/internal/intern/compar.h
+strscan.o: $(hdrdir)/ruby/internal/intern/complex.h
+strscan.o: $(hdrdir)/ruby/internal/intern/cont.h
+strscan.o: $(hdrdir)/ruby/internal/intern/dir.h
+strscan.o: $(hdrdir)/ruby/internal/intern/enum.h
+strscan.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+strscan.o: $(hdrdir)/ruby/internal/intern/error.h
+strscan.o: $(hdrdir)/ruby/internal/intern/eval.h
+strscan.o: $(hdrdir)/ruby/internal/intern/file.h
+strscan.o: $(hdrdir)/ruby/internal/intern/gc.h
+strscan.o: $(hdrdir)/ruby/internal/intern/hash.h
+strscan.o: $(hdrdir)/ruby/internal/intern/io.h
+strscan.o: $(hdrdir)/ruby/internal/intern/load.h
+strscan.o: $(hdrdir)/ruby/internal/intern/marshal.h
+strscan.o: $(hdrdir)/ruby/internal/intern/numeric.h
+strscan.o: $(hdrdir)/ruby/internal/intern/object.h
+strscan.o: $(hdrdir)/ruby/internal/intern/parse.h
+strscan.o: $(hdrdir)/ruby/internal/intern/proc.h
+strscan.o: $(hdrdir)/ruby/internal/intern/process.h
+strscan.o: $(hdrdir)/ruby/internal/intern/random.h
+strscan.o: $(hdrdir)/ruby/internal/intern/range.h
+strscan.o: $(hdrdir)/ruby/internal/intern/rational.h
+strscan.o: $(hdrdir)/ruby/internal/intern/re.h
+strscan.o: $(hdrdir)/ruby/internal/intern/ruby.h
+strscan.o: $(hdrdir)/ruby/internal/intern/select.h
+strscan.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+strscan.o: $(hdrdir)/ruby/internal/intern/signal.h
+strscan.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+strscan.o: $(hdrdir)/ruby/internal/intern/string.h
+strscan.o: $(hdrdir)/ruby/internal/intern/struct.h
+strscan.o: $(hdrdir)/ruby/internal/intern/thread.h
+strscan.o: $(hdrdir)/ruby/internal/intern/time.h
+strscan.o: $(hdrdir)/ruby/internal/intern/variable.h
+strscan.o: $(hdrdir)/ruby/internal/intern/vm.h
+strscan.o: $(hdrdir)/ruby/internal/interpreter.h
+strscan.o: $(hdrdir)/ruby/internal/iterator.h
+strscan.o: $(hdrdir)/ruby/internal/memory.h
+strscan.o: $(hdrdir)/ruby/internal/method.h
+strscan.o: $(hdrdir)/ruby/internal/module.h
+strscan.o: $(hdrdir)/ruby/internal/newobj.h
+strscan.o: $(hdrdir)/ruby/internal/rgengc.h
+strscan.o: $(hdrdir)/ruby/internal/scan_args.h
+strscan.o: $(hdrdir)/ruby/internal/special_consts.h
+strscan.o: $(hdrdir)/ruby/internal/static_assert.h
+strscan.o: $(hdrdir)/ruby/internal/stdalign.h
+strscan.o: $(hdrdir)/ruby/internal/stdbool.h
+strscan.o: $(hdrdir)/ruby/internal/symbol.h
+strscan.o: $(hdrdir)/ruby/internal/token_paste.h
+strscan.o: $(hdrdir)/ruby/internal/value.h
+strscan.o: $(hdrdir)/ruby/internal/value_type.h
+strscan.o: $(hdrdir)/ruby/internal/variable.h
+strscan.o: $(hdrdir)/ruby/internal/warning_push.h
+strscan.o: $(hdrdir)/ruby/internal/xmalloc.h
strscan.o: $(hdrdir)/ruby/assert.h
strscan.o: $(hdrdir)/ruby/backward.h
+strscan.o: $(hdrdir)/ruby/backward/2/assume.h
+strscan.o: $(hdrdir)/ruby/backward/2/attributes.h
+strscan.o: $(hdrdir)/ruby/backward/2/bool.h
+strscan.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+strscan.o: $(hdrdir)/ruby/backward/2/inttypes.h
+strscan.o: $(hdrdir)/ruby/backward/2/limits.h
+strscan.o: $(hdrdir)/ruby/backward/2/long_long.h
+strscan.o: $(hdrdir)/ruby/backward/2/stdalign.h
+strscan.o: $(hdrdir)/ruby/backward/2/stdarg.h
strscan.o: $(hdrdir)/ruby/defines.h
strscan.o: $(hdrdir)/ruby/encoding.h
strscan.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c
index b6d17992c9..e1426380b4 100644
--- a/ext/strscan/strscan.c
+++ b/ext/strscan/strscan.c
@@ -4,8 +4,8 @@
Copyright (c) 1999-2006 Minero Aoki
This program is free software.
- You can distribute/modify this program under the terms of
- the Ruby License. For details, see the file COPYING.
+ You can redistribute this program under the terms of the Ruby's or 2-clause
+ BSD License. For details, see the COPYING and LICENSE.txt files.
*/
#include "ruby/ruby.h"
@@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs);
#include <stdbool.h>
-#define STRSCAN_VERSION "1.0.3"
+#define STRSCAN_VERSION "3.0.1"
/* =======================================================================
Data Type Definitions
@@ -176,6 +176,7 @@ strscan_mark(void *ptr)
{
struct strscanner *p = ptr;
rb_gc_mark(p->str);
+ rb_gc_mark(p->regex);
}
static void
@@ -212,6 +213,7 @@ strscan_s_allocate(VALUE klass)
CLEAR_MATCH_STATUS(p);
onig_region_init(&(p->regs));
p->str = Qnil;
+ p->regex = Qnil;
return obj;
}
@@ -443,13 +445,10 @@ static VALUE
strscan_get_charpos(VALUE self)
{
struct strscanner *p;
- VALUE substr;
GET_SCANNER(self, p);
- substr = rb_funcall(p->str, id_byteslice, 2, INT2FIX(0), INT2NUM(p->curr));
-
- return rb_str_length(substr);
+ return LONG2NUM(rb_enc_strlen(S_PBEG(p), CURPTR(p), rb_enc_get(p->str)));
}
/*
@@ -473,7 +472,7 @@ strscan_set_pos(VALUE self, VALUE v)
if (i < 0) rb_raise(rb_eRangeError, "index out of range");
if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
p->curr = i;
- return INT2NUM(i);
+ return LONG2NUM(i);
}
static inline UChar *
@@ -848,9 +847,8 @@ adjust_registers_to_matched(struct strscanner *p)
* s.getch # => "b"
* s.getch # => nil
*
- * $KCODE = 'EUC'
- * s = StringScanner.new("\244\242")
- * s.getch # => "\244\242" # Japanese hira-kana "A" in EUC-JP
+ * s = StringScanner.new("\244\242".force_encoding("euc-jp"))
+ * s.getch # => "\x{A4A2}" # Japanese hira-kana "A" in EUC-JP
* s.getch # => nil
*/
static VALUE
@@ -885,10 +883,9 @@ strscan_getch(VALUE self)
* s.get_byte # => "b"
* s.get_byte # => nil
*
- * $KCODE = 'EUC'
- * s = StringScanner.new("\244\242")
- * s.get_byte # => "\244"
- * s.get_byte # => "\242"
+ * s = StringScanner.new("\244\242".force_encoding("euc-jp"))
+ * s.get_byte # => "\xA4"
+ * s.get_byte # => "\xA2"
* s.get_byte # => nil
*/
static VALUE
@@ -984,7 +981,7 @@ strscan_unscan(VALUE self)
}
/*
- * Returns +true+ iff the scan pointer is at the beginning of the line.
+ * Returns +true+ if and only if the scan pointer is at the beginning of the line.
*
* s = StringScanner.new("test\ntest\n")
* s.bol? # => true
@@ -1037,7 +1034,7 @@ strscan_empty_p(VALUE self)
}
/*
- * Returns true iff there is more data in the string. See #eos?.
+ * Returns true if and only if there is more data in the string. See #eos?.
* This method is obsolete; use #eos? instead.
*
* s = StringScanner.new('test string')
@@ -1054,7 +1051,7 @@ strscan_rest_p(VALUE self)
}
/*
- * Returns +true+ iff the last match was successful.
+ * Returns +true+ if and only if the last match was successful.
*
* s = StringScanner.new('test string')
* s.match?(/\w+/) # => 4
@@ -1091,8 +1088,9 @@ strscan_matched(VALUE self)
}
/*
- * Returns the size of the most recent match (see #matched), or +nil+ if there
- * was no recent match.
+ * Returns the size of the most recent match in bytes, or +nil+ if there
+ * was no recent match. This is different than <tt>matched.size</tt>,
+ * which will return the size in characters.
*
* s = StringScanner.new('test string')
* s.check /\w+/ # -> "test"
@@ -1107,7 +1105,7 @@ strscan_matched_size(VALUE self)
GET_SCANNER(self, p);
if (! MATCHED_P(p)) return Qnil;
- return INT2NUM(p->regs.end[0] - p->regs.beg[0]);
+ return LONG2NUM(p->regs.end[0] - p->regs.beg[0]);
}
static int
@@ -1169,7 +1167,7 @@ strscan_aref(VALUE self, VALUE idx)
idx = rb_sym2str(idx);
/* fall through */
case T_STRING:
- if (!p->regex) return Qnil;
+ if (!RTEST(p->regex)) return Qnil;
RSTRING_GETMEM(idx, name, i);
i = name_to_backref_number(&(p->regs), p->regex, name, name + i, rb_enc_get(idx));
break;
@@ -1536,7 +1534,7 @@ strscan_fixed_anchor_p(VALUE self)
*
* === Finding Where we Are
*
- * - #beginning_of_line? (#bol?)
+ * - #beginning_of_line? (<tt>#bol?</tt>)
* - #eos?
* - #rest?
* - #rest_size
@@ -1553,13 +1551,13 @@ strscan_fixed_anchor_p(VALUE self)
* - #matched
* - #matched?
* - #matched_size
- * - []
+ * - <tt>#[]</tt>
* - #pre_match
* - #post_match
*
* === Miscellaneous
*
- * - <<
+ * - <tt><<</tt>
* - #concat
* - #string
* - #string=
@@ -1570,6 +1568,10 @@ strscan_fixed_anchor_p(VALUE self)
void
Init_strscan(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
#undef rb_intern
ID id_scanerr = rb_intern("ScanError");
VALUE tmp;
diff --git a/ext/strscan/strscan.gemspec b/ext/strscan/strscan.gemspec
index 4759c6c860..5d8119ea4c 100644
--- a/ext/strscan/strscan.gemspec
+++ b/ext/strscan/strscan.gemspec
@@ -1,7 +1,18 @@
# frozen_string_literal: true
+#
+source_version = ["", "ext/strscan/"].find do |dir|
+ begin
+ break File.open(File.join(__dir__, "#{dir}strscan.c")) {|f|
+ f.gets("\n#define STRSCAN_VERSION ")
+ f.gets[/\s*"(.+)"/, 1]
+ }
+ rescue Errno::ENOENT
+ end
+end
+
Gem::Specification.new do |s|
s.name = "strscan"
- s.version = '1.0.3'
+ s.version = source_version
s.summary = "Provides lexical scanning operations on a String."
s.description = "Provides lexical scanning operations on a String."
@@ -13,8 +24,5 @@ Gem::Specification.new do |s|
s.authors = ["Minero Aoki", "Sutou Kouhei"]
s.email = [nil, "kou@cozmixng.org"]
s.homepage = "https://github.com/ruby/strscan"
- s.license = "BSD-2-Clause"
-
- s.add_development_dependency "rake-compiler"
- s.add_development_dependency "benchmark-driver"
+ s.licenses = ["Ruby", "BSD-2-Clause"]
end
diff --git a/ext/syslog/depend b/ext/syslog/depend
index a3f7db8371..4c0ef0ebac 100644
--- a/ext/syslog/depend
+++ b/ext/syslog/depend
@@ -1,8 +1,157 @@
# AUTOGENERATED DEPENDENCIES START
syslog.o: $(RUBY_EXTCONF_H)
syslog.o: $(arch_hdrdir)/ruby/config.h
+syslog.o: $(hdrdir)/ruby/internal/anyargs.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+syslog.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+syslog.o: $(hdrdir)/ruby/internal/assume.h
+syslog.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+syslog.o: $(hdrdir)/ruby/internal/attr/artificial.h
+syslog.o: $(hdrdir)/ruby/internal/attr/cold.h
+syslog.o: $(hdrdir)/ruby/internal/attr/const.h
+syslog.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+syslog.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+syslog.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+syslog.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+syslog.o: $(hdrdir)/ruby/internal/attr/error.h
+syslog.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+syslog.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+syslog.o: $(hdrdir)/ruby/internal/attr/format.h
+syslog.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+syslog.o: $(hdrdir)/ruby/internal/attr/noalias.h
+syslog.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+syslog.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+syslog.o: $(hdrdir)/ruby/internal/attr/noinline.h
+syslog.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+syslog.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+syslog.o: $(hdrdir)/ruby/internal/attr/pure.h
+syslog.o: $(hdrdir)/ruby/internal/attr/restrict.h
+syslog.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+syslog.o: $(hdrdir)/ruby/internal/attr/warning.h
+syslog.o: $(hdrdir)/ruby/internal/attr/weakref.h
+syslog.o: $(hdrdir)/ruby/internal/cast.h
+syslog.o: $(hdrdir)/ruby/internal/compiler_is.h
+syslog.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+syslog.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+syslog.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+syslog.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+syslog.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+syslog.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+syslog.o: $(hdrdir)/ruby/internal/compiler_since.h
+syslog.o: $(hdrdir)/ruby/internal/config.h
+syslog.o: $(hdrdir)/ruby/internal/constant_p.h
+syslog.o: $(hdrdir)/ruby/internal/core.h
+syslog.o: $(hdrdir)/ruby/internal/core/rarray.h
+syslog.o: $(hdrdir)/ruby/internal/core/rbasic.h
+syslog.o: $(hdrdir)/ruby/internal/core/rbignum.h
+syslog.o: $(hdrdir)/ruby/internal/core/rclass.h
+syslog.o: $(hdrdir)/ruby/internal/core/rdata.h
+syslog.o: $(hdrdir)/ruby/internal/core/rfile.h
+syslog.o: $(hdrdir)/ruby/internal/core/rhash.h
+syslog.o: $(hdrdir)/ruby/internal/core/robject.h
+syslog.o: $(hdrdir)/ruby/internal/core/rregexp.h
+syslog.o: $(hdrdir)/ruby/internal/core/rstring.h
+syslog.o: $(hdrdir)/ruby/internal/core/rstruct.h
+syslog.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+syslog.o: $(hdrdir)/ruby/internal/ctype.h
+syslog.o: $(hdrdir)/ruby/internal/dllexport.h
+syslog.o: $(hdrdir)/ruby/internal/dosish.h
+syslog.o: $(hdrdir)/ruby/internal/error.h
+syslog.o: $(hdrdir)/ruby/internal/eval.h
+syslog.o: $(hdrdir)/ruby/internal/event.h
+syslog.o: $(hdrdir)/ruby/internal/fl_type.h
+syslog.o: $(hdrdir)/ruby/internal/gc.h
+syslog.o: $(hdrdir)/ruby/internal/glob.h
+syslog.o: $(hdrdir)/ruby/internal/globals.h
+syslog.o: $(hdrdir)/ruby/internal/has/attribute.h
+syslog.o: $(hdrdir)/ruby/internal/has/builtin.h
+syslog.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+syslog.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+syslog.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+syslog.o: $(hdrdir)/ruby/internal/has/extension.h
+syslog.o: $(hdrdir)/ruby/internal/has/feature.h
+syslog.o: $(hdrdir)/ruby/internal/has/warning.h
+syslog.o: $(hdrdir)/ruby/internal/intern/array.h
+syslog.o: $(hdrdir)/ruby/internal/intern/bignum.h
+syslog.o: $(hdrdir)/ruby/internal/intern/class.h
+syslog.o: $(hdrdir)/ruby/internal/intern/compar.h
+syslog.o: $(hdrdir)/ruby/internal/intern/complex.h
+syslog.o: $(hdrdir)/ruby/internal/intern/cont.h
+syslog.o: $(hdrdir)/ruby/internal/intern/dir.h
+syslog.o: $(hdrdir)/ruby/internal/intern/enum.h
+syslog.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+syslog.o: $(hdrdir)/ruby/internal/intern/error.h
+syslog.o: $(hdrdir)/ruby/internal/intern/eval.h
+syslog.o: $(hdrdir)/ruby/internal/intern/file.h
+syslog.o: $(hdrdir)/ruby/internal/intern/gc.h
+syslog.o: $(hdrdir)/ruby/internal/intern/hash.h
+syslog.o: $(hdrdir)/ruby/internal/intern/io.h
+syslog.o: $(hdrdir)/ruby/internal/intern/load.h
+syslog.o: $(hdrdir)/ruby/internal/intern/marshal.h
+syslog.o: $(hdrdir)/ruby/internal/intern/numeric.h
+syslog.o: $(hdrdir)/ruby/internal/intern/object.h
+syslog.o: $(hdrdir)/ruby/internal/intern/parse.h
+syslog.o: $(hdrdir)/ruby/internal/intern/proc.h
+syslog.o: $(hdrdir)/ruby/internal/intern/process.h
+syslog.o: $(hdrdir)/ruby/internal/intern/random.h
+syslog.o: $(hdrdir)/ruby/internal/intern/range.h
+syslog.o: $(hdrdir)/ruby/internal/intern/rational.h
+syslog.o: $(hdrdir)/ruby/internal/intern/re.h
+syslog.o: $(hdrdir)/ruby/internal/intern/ruby.h
+syslog.o: $(hdrdir)/ruby/internal/intern/select.h
+syslog.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+syslog.o: $(hdrdir)/ruby/internal/intern/signal.h
+syslog.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+syslog.o: $(hdrdir)/ruby/internal/intern/string.h
+syslog.o: $(hdrdir)/ruby/internal/intern/struct.h
+syslog.o: $(hdrdir)/ruby/internal/intern/thread.h
+syslog.o: $(hdrdir)/ruby/internal/intern/time.h
+syslog.o: $(hdrdir)/ruby/internal/intern/variable.h
+syslog.o: $(hdrdir)/ruby/internal/intern/vm.h
+syslog.o: $(hdrdir)/ruby/internal/interpreter.h
+syslog.o: $(hdrdir)/ruby/internal/iterator.h
+syslog.o: $(hdrdir)/ruby/internal/memory.h
+syslog.o: $(hdrdir)/ruby/internal/method.h
+syslog.o: $(hdrdir)/ruby/internal/module.h
+syslog.o: $(hdrdir)/ruby/internal/newobj.h
+syslog.o: $(hdrdir)/ruby/internal/rgengc.h
+syslog.o: $(hdrdir)/ruby/internal/scan_args.h
+syslog.o: $(hdrdir)/ruby/internal/special_consts.h
+syslog.o: $(hdrdir)/ruby/internal/static_assert.h
+syslog.o: $(hdrdir)/ruby/internal/stdalign.h
+syslog.o: $(hdrdir)/ruby/internal/stdbool.h
+syslog.o: $(hdrdir)/ruby/internal/symbol.h
+syslog.o: $(hdrdir)/ruby/internal/token_paste.h
+syslog.o: $(hdrdir)/ruby/internal/value.h
+syslog.o: $(hdrdir)/ruby/internal/value_type.h
+syslog.o: $(hdrdir)/ruby/internal/variable.h
+syslog.o: $(hdrdir)/ruby/internal/warning_push.h
+syslog.o: $(hdrdir)/ruby/internal/xmalloc.h
syslog.o: $(hdrdir)/ruby/assert.h
syslog.o: $(hdrdir)/ruby/backward.h
+syslog.o: $(hdrdir)/ruby/backward/2/assume.h
+syslog.o: $(hdrdir)/ruby/backward/2/attributes.h
+syslog.o: $(hdrdir)/ruby/backward/2/bool.h
+syslog.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+syslog.o: $(hdrdir)/ruby/backward/2/inttypes.h
+syslog.o: $(hdrdir)/ruby/backward/2/limits.h
+syslog.o: $(hdrdir)/ruby/backward/2/long_long.h
+syslog.o: $(hdrdir)/ruby/backward/2/stdalign.h
+syslog.o: $(hdrdir)/ruby/backward/2/stdarg.h
syslog.o: $(hdrdir)/ruby/defines.h
syslog.o: $(hdrdir)/ruby/intern.h
syslog.o: $(hdrdir)/ruby/missing.h
diff --git a/ext/syslog/syslog.gemspec b/ext/syslog/syslog.gemspec
new file mode 100644
index 0000000000..8f73f5ad0d
--- /dev/null
+++ b/ext/syslog/syslog.gemspec
@@ -0,0 +1,23 @@
+Gem::Specification.new do |spec|
+ spec.name = "syslog"
+ spec.version = "0.1.0"
+ spec.authors = ["Akinori MUSHA"]
+ spec.email = ["knu@idaemons.org"]
+
+ spec.summary = %q{Ruby interface for the POSIX system logging facility.}
+ spec.description = %q{Ruby interface for the POSIX system logging facility.}
+ spec.homepage = "https://github.com/ruby/syslog"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.extensions = ["ext/syslog/extconf.rb"]
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/ext/win32/lib/Win32API.rb b/ext/win32/lib/Win32API.rb
deleted file mode 100644
index 97b29fbf74..0000000000
--- a/ext/win32/lib/Win32API.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# -*- ruby -*-
-# frozen_string_literal: true
-
-# for backward compatibility
-warn "Win32API is deprecated after Ruby 1.9.1; use fiddle directly instead", uplevel: 2
-
-require 'fiddle/import'
-
-class Win32API
- DLL = {}
- TYPEMAP = {"0" => Fiddle::TYPE_VOID, "S" => Fiddle::TYPE_VOIDP, "I" => Fiddle::TYPE_LONG}
- POINTER_TYPE = Fiddle::SIZEOF_VOIDP == Fiddle::SIZEOF_LONG_LONG ? 'q*' : 'l!*'
-
- WIN32_TYPES = "VPpNnLlIi"
- DL_TYPES = "0SSI"
-
- def initialize(dllname, func, import, export = "0", calltype = :stdcall)
- @proto = [import].join.tr(WIN32_TYPES, DL_TYPES).sub(/^(.)0*$/, '\1')
- import = @proto.chars.map {|win_type| TYPEMAP[win_type.tr(WIN32_TYPES, DL_TYPES)]}
- export = TYPEMAP[export.tr(WIN32_TYPES, DL_TYPES)]
- calltype = Fiddle::Importer.const_get(:CALL_TYPE_TO_ABI)[calltype]
-
- handle = DLL[dllname] ||=
- begin
- Fiddle.dlopen(dllname)
- rescue Fiddle::DLError
- raise unless File.extname(dllname).empty?
- Fiddle.dlopen(dllname + ".dll")
- end
-
- @func = Fiddle::Function.new(handle[func], import, export, calltype)
- rescue Fiddle::DLError => e
- raise LoadError, e.message, e.backtrace
- end
-
- def call(*args)
- import = @proto.split("")
- args.each_with_index do |x, i|
- args[i], = [x == 0 ? nil : x].pack("p").unpack(POINTER_TYPE) if import[i] == "S"
- args[i], = [x].pack("I").unpack("i") if import[i] == "I"
- end
- ret, = @func.call(*args)
- return ret || 0
- end
-
- alias Call call
-end
diff --git a/ext/win32/lib/win32/importer.rb b/ext/win32/lib/win32/importer.rb
deleted file mode 100644
index 2bef016c29..0000000000
--- a/ext/win32/lib/win32/importer.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: false
-require 'fiddle/import'
-
-module Win32
-end
-
-Win32.module_eval do
- Importer = Fiddle::Importer
-end
diff --git a/ext/win32/lib/win32/registry.rb b/ext/win32/lib/win32/registry.rb
index 451499b166..ffc2979179 100644
--- a/ext/win32/lib/win32/registry.rb
+++ b/ext/win32/lib/win32/registry.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: false
-require 'win32/importer'
+require 'fiddle/import'
module Win32
@@ -169,7 +169,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
#
class Error < ::StandardError
module Kernel32
- extend Importer
+ extend Fiddle::Importer
dlload "kernel32.dll"
end
FormatMessageW = Kernel32.extern "int FormatMessageW(int, void *, int, int, void *, int, void *)", :stdcall
@@ -225,7 +225,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
#
module API
include Constants
- extend Importer
+ extend Fiddle::Importer
dlload "advapi32.dll"
[
"long RegOpenKeyExW(void *, void *, long, long, void *)",
diff --git a/ext/win32/lib/win32/resolv.rb b/ext/win32/lib/win32/resolv.rb
index 1eb70d5dc6..d06658f0aa 100644
--- a/ext/win32/lib/win32/resolv.rb
+++ b/ext/win32/lib/win32/resolv.rb
@@ -42,19 +42,6 @@ begin
rescue LoadError
end
-if [nil].pack("p").size <= 4 # 32bit env
- begin
- f = Fiddle
- osid = f::Handle.new["rb_w32_osid"]
- rescue f::DLError # not ix86, cannot be Windows 9x
- else
- if f::Function.new(osid, [], f::TYPE_INT).call < 2 # VER_PLATFORM_WIN32_NT
- require_relative 'resolv9x'
- return
- end
- end
-end
-
module Win32
#====================================================================
# Windows NT
diff --git a/ext/win32/lib/win32/resolv9x.rb b/ext/win32/lib/win32/resolv9x.rb
deleted file mode 100644
index a409d59c0c..0000000000
--- a/ext/win32/lib/win32/resolv9x.rb
+++ /dev/null
@@ -1,253 +0,0 @@
-#====================================================================
-# Windows 9x
-#====================================================================
-module Win32
- module Resolv
- TCPIP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\MSTCP'
- DHCP_9X = 'SYSTEM\CurrentControlSet\Services\VxD\DHCP'
- WINDOWS = 'Software\Microsoft\Windows\CurrentVersion'
-
- class << self
- # private
-
- def get_hosts_dir
- Registry::HKEY_LOCAL_MACHINE.open(WINDOWS) do |reg|
- reg.read_s_expand('SystemRoot')
- end
- end
-
- def get_info
- search = []
- nameserver = []
- begin
- Registry::HKEY_LOCAL_MACHINE.open(TCPIP_9X) do |reg|
- if reg.read_s("EnableDNS") == "1"
- domain = reg.read_s("Domain")
- ns = reg.read_s("NameServer")
- slist = reg.read_s("SearchList")
- search << domain unless domain.empty?
- search.concat(slist.split(/,\s*/))
- nameserver.concat(ns.split(/[,\s]\s*/))
- end
- end
- rescue Registry::Error
- end
-
- dhcpinfo = get_dhcpinfo
- search.concat(dhcpinfo[0])
- nameserver.concat(dhcpinfo[1])
- [ search, nameserver ]
- end
-
- def get_dhcpinfo
- macaddrs = {}
- ipaddrs = {}
- WsControl.get_iflist.each do |index, macaddr, *ipaddr|
- macaddrs[macaddr] = 1
- ipaddr.each { |ipaddr| ipaddrs[ipaddr] = 1 }
- end
- iflist = [ macaddrs, ipaddrs ]
-
- search = []
- nameserver = []
- version = -1
- Registry::HKEY_LOCAL_MACHINE.open(DHCP_9X) do |reg|
- begin
- version = API.unpackdw(reg.read_bin("Version"))
- rescue Registry::Error
- end
-
- reg.each_key do |key, |
- catch(:not_used) do
- reg.open(key) do |regdi|
- dom, ns = get_dhcpinfo_key(version, regdi, iflist)
- search << dom if dom
- nameserver.concat(ns) if ns
- end
- end
- end
- end
- [ search, nameserver ]
- end
-
- def get_dhcpinfo_95(reg)
- dhcp = reg.read_bin("DhcpInfo")
- [
- API.unpackdw(dhcp[4..7]),
- API.unpackdw(dhcp[8..11]),
- 1,
- dhcp[45..50],
- reg.read_bin("OptionInfo"),
- ]
- end
-
- def get_dhcpinfo_98(reg)
- [
- API.unpackdw(reg.read_bin("DhcpIPAddress")),
- API.unpackdw(reg.read_bin("DhcpSubnetMask")),
- API.unpackdw(reg.read_bin("HardwareType")),
- reg.read_bin("HardwareAddress"),
- reg.read_bin("OptionInfo"),
- ]
- end
-
- def get_dhcpinfo_key(version, reg, iflist)
- info = case version
- when 1
- get_dhcpinfo_95(reg)
- when 2
- get_dhcpinfo_98(reg)
- else
- begin
- get_dhcpinfo_98(reg)
- rescue Registry::Error
- get_dhcpinfo_95(reg)
- end
- end
- ipaddr, netmask, hwtype, macaddr, opt = info
- throw :not_used unless
- ipaddr and ipaddr != 0 and
- netmask and netmask != 0 and
- macaddr and macaddr.size == 6 and
- hwtype == 1 and
- iflist[0][macaddr] and iflist[1][ipaddr]
-
- size = opt.size
- idx = 0
- while idx <= size
- opttype = opt[idx]
- optsize = opt[idx + 1]
- optval = opt[idx + 2, optsize]
- case opttype
- when 0xFF ## term
- break
- when 0x0F ## domain
- domain = optval.chomp("\0")
- when 0x06 ## dns
- nameserver = optval.scan(/..../).collect { |addr|
- "%d.%d.%d.%d" % addr.unpack('C4')
- }
- end
- idx += optsize + 2
- end
- [ domain, nameserver ]
- rescue Registry::Error
- throw :not_used
- end
- end
-
- module WsControl
- module WSock32
- extend Importer
- dlload "wsock32.dll"
- end
- WsControl = WSock32.extern "int WsControl(int, int, void *, void *, void *, void *)", :stdcall
- WSAGetLastError = WSock32.extern "int WSAGetLastError(void)", :stdcall
-
- MAX_TDI_ENTITIES = 512
- IPPROTO_TCP = 6
- WSCTL_TCP_QUERY_INFORMATION = 0
- INFO_CLASS_GENERIC = 0x100
- INFO_CLASS_PROTOCOL = 0x200
- INFO_TYPE_PROVIDER = 0x100
- ENTITY_LIST_ID = 0
- GENERIC_ENTITY = 0
- CL_NL_ENTITY = 0x301
- IF_ENTITY = 0x200
- ENTITY_TYPE_ID = 1
- CL_NL_IP = 0x303
- IF_MIB = 0x202
- IF_MIB_STATS_ID = 1
- IP_MIB_ADDRTABLE_ENTRY_ID = 0x102
-
- def self.wsctl(tei_entity, tei_instance,
- toi_class, toi_type, toi_id,
- buffsize)
- reqinfo = [
- ## TDIEntityID
- tei_entity, tei_instance,
- ## TDIObjectID
- toi_class, toi_type, toi_id,
- ## TCP_REQUEST_INFORMATION_EX
- ""
- ].pack('VVVVVa16')
- reqsize = API.packdw(reqinfo.size)
- buff = "\0" * buffsize
- buffsize = API.packdw(buffsize)
- result = WsControl.call(
- IPPROTO_TCP,
- WSCTL_TCP_QUERY_INFORMATION,
- reqinfo, reqsize,
- buff, buffsize)
- if result != 0
- raise RuntimeError, "WsControl failed.(#{result})"
- end
- [ buff, API.unpackdw(buffsize) ]
- end
- private_class_method :wsctl
-
- def self.get_iflist
- # Get TDI Entity List
- entities, size =
- wsctl(GENERIC_ENTITY, 0,
- INFO_CLASS_GENERIC,
- INFO_TYPE_PROVIDER,
- ENTITY_LIST_ID,
- MAX_TDI_ENTITIES * 8) # sizeof(TDIEntityID)
- entities = entities[0, size].
- scan(/.{8}/).
- collect { |e| e.unpack('VV') }
-
- # Get MIB Interface List
- iflist = []
- ifcount = 0
- entities.each do |entity, instance|
- if( (entity & IF_ENTITY)>0 )
- ifcount += 1
- etype, = wsctl(entity, instance,
- INFO_CLASS_GENERIC,
- INFO_TYPE_PROVIDER,
- ENTITY_TYPE_ID,
- 4)
- if( (API.unpackdw(etype) & IF_MIB)==IF_MIB )
- ifentry, = wsctl(entity, instance,
- INFO_CLASS_PROTOCOL,
- INFO_TYPE_PROVIDER,
- IF_MIB_STATS_ID,
- 21 * 4 + 8 + 130) # sizeof(IFEntry)
- iflist << [
- API.unpackdw(ifentry[0,4]),
- ifentry[20, 6]
- ]
- end
- end
- end
-
- # Get IP Addresses
- entities.each do |entity, instance|
- if entity == CL_NL_ENTITY
- etype, = wsctl(entity, instance,
- INFO_CLASS_GENERIC,
- INFO_TYPE_PROVIDER,
- ENTITY_TYPE_ID,
- 4)
- if API.unpackdw(etype) == CL_NL_IP
- ipentries, = wsctl(entity, instance,
- INFO_CLASS_PROTOCOL,
- INFO_TYPE_PROVIDER,
- IP_MIB_ADDRTABLE_ENTRY_ID,
- 24 * (ifcount+1)) # sizeof(IPAddrEntry)
- ipentries.scan(/.{24}/) do |ipentry|
- ipaddr, index = ipentry.unpack('VV')
- if ifitem = iflist.assoc(index)
- ifitem << ipaddr
- end
- end
- end
- end
- end
- iflist
- end
- end
- end
-end
diff --git a/ext/win32/lib/win32/sspi.rb b/ext/win32/lib/win32/sspi.rb
index 8103893d7f..a73819f24e 100644
--- a/ext/win32/lib/win32/sspi.rb
+++ b/ext/win32/lib/win32/sspi.rb
@@ -11,321 +11,328 @@
# Ruby Distribution License or GNU General Public License.
#
-require 'Win32API'
+require 'fiddle/import'
# Implements bindings to Win32 SSPI functions, focused on authentication to a proxy server over HTTP.
module Win32
- module SSPI
- # Specifies how credential structure requested will be used. Only SECPKG_CRED_OUTBOUND is used
- # here.
- SECPKG_CRED_INBOUND = 0x00000001
- SECPKG_CRED_OUTBOUND = 0x00000002
- SECPKG_CRED_BOTH = 0x00000003
-
- # Format of token. NETWORK format is used here.
- SECURITY_NATIVE_DREP = 0x00000010
- SECURITY_NETWORK_DREP = 0x00000000
-
- # InitializeSecurityContext Requirement flags
- ISC_REQ_REPLAY_DETECT = 0x00000004
- ISC_REQ_SEQUENCE_DETECT = 0x00000008
- ISC_REQ_CONFIDENTIALITY = 0x00000010
- ISC_REQ_USE_SESSION_KEY = 0x00000020
- ISC_REQ_PROMPT_FOR_CREDS = 0x00000040
- ISC_REQ_CONNECTION = 0x00000800
-
- # Win32 API Functions. Uses Win32API to bind methods to constants contained in class.
- module API
- # Can be called with AcquireCredentialsHandle.call()
- AcquireCredentialsHandle = Win32API.new("secur32", "AcquireCredentialsHandle", 'ppLpppppp', 'L')
- # Can be called with InitializeSecurityContext.call()
- InitializeSecurityContext = Win32API.new("secur32", "InitializeSecurityContext", 'pppLLLpLpppp', 'L')
- # Can be called with DeleteSecurityContext.call()
- DeleteSecurityContext = Win32API.new("secur32", "DeleteSecurityContext", 'P', 'L')
- # Can be called with FreeCredentialsHandle.call()
- FreeCredentialsHandle = Win32API.new("secur32", "FreeCredentialsHandle", 'P', 'L')
- end
-
- # SecHandle struct
- class SecurityHandle
- def upper
- @struct.unpack("LL")[1]
- end
-
- def lower
- @struct.unpack("LL")[0]
- end
-
- def to_p
- @struct ||= "\0" * 8
- end
- end
-
- # Some familiar aliases for the SecHandle structure
- CredHandle = CtxtHandle = SecurityHandle
-
- # TimeStamp struct
- class TimeStamp
- attr_reader :struct
-
- def to_p
- @struct ||= "\0" * 8
- end
- end
-
- # Creates binary representations of a SecBufferDesc structure,
- # including the SecBuffer contained inside.
- class SecurityBuffer
-
- SECBUFFER_TOKEN = 2 # Security token
-
- TOKENBUFSIZE = 12288
- SECBUFFER_VERSION = 0
-
- def initialize(buffer = nil)
- @buffer = buffer || "\0" * TOKENBUFSIZE
- @bufferSize = @buffer.length
- @type = SECBUFFER_TOKEN
- end
-
- def bufferSize
- unpack
- @bufferSize
- end
-
- def bufferType
- unpack
- @type
- end
-
- def token
- unpack
- @buffer
- end
-
- def to_p
- # Assumption is that when to_p is called we are going to get a packed structure. Therefore,
- # set @unpacked back to nil so we know to unpack when accessors are next accessed.
- @unpacked = nil
- # Assignment of inner structure to variable is very important here. Without it,
- # will not be able to unpack changes to the structure. Alternative, nested unpacks,
- # does not work (i.e. @struct.unpack("LLP12")[2].unpack("LLP12") results in "no associated pointer")
- @sec_buffer ||= [@bufferSize, @type, @buffer].pack("LLP")
- @struct ||= [SECBUFFER_VERSION, 1, @sec_buffer].pack("LLP")
- end
-
- private
-
- # Unpacks the SecurityBufferDesc structure into member variables. We
- # only want to do this once per struct, so the struct is deleted
- # after unpacking.
- def unpack
- if ! @unpacked && @sec_buffer && @struct
- @bufferSize, @type = @sec_buffer.unpack("LL")
- @buffer = @sec_buffer.unpack("LLP#{@bufferSize}")[2]
- @struct = nil
- @sec_buffer = nil
- @unpacked = true
- end
- end
- end
-
- # SEC_WINNT_AUTH_IDENTITY structure
- class Identity
- SEC_WINNT_AUTH_IDENTITY_ANSI = 0x1
-
- attr_accessor :user, :domain, :password
-
- def initialize(user = nil, domain = nil, password = nil)
- @user = user
- @domain = domain
- @password = password
- @flags = SEC_WINNT_AUTH_IDENTITY_ANSI
- end
-
- def to_p
- [@user, @user ? @user.length : 0,
- @domain, @domain ? @domain.length : 0,
- @password, @password ? @password.length : 0,
- @flags].pack("PLPLPLL")
- end
- end
-
- # Takes a return result from an SSPI function and interprets the value.
- class SSPIResult
- # Good results
- SEC_E_OK = 0x00000000
- SEC_I_CONTINUE_NEEDED = 0x00090312
-
- # These are generally returned by InitializeSecurityContext
- SEC_E_INSUFFICIENT_MEMORY = 0x80090300
- SEC_E_INTERNAL_ERROR = 0x80090304
- SEC_E_INVALID_HANDLE = 0x80090301
- SEC_E_INVALID_TOKEN = 0x80090308
- SEC_E_LOGON_DENIED = 0x8009030C
- SEC_E_NO_AUTHENTICATING_AUTHORITY = 0x80090311
- SEC_E_NO_CREDENTIALS = 0x8009030E
- SEC_E_TARGET_UNKNOWN = 0x80090303
- SEC_E_UNSUPPORTED_FUNCTION = 0x80090302
- SEC_E_WRONG_PRINCIPAL = 0x80090322
-
- # These are generally returned by AcquireCredentialsHandle
- SEC_E_NOT_OWNER = 0x80090306
- SEC_E_SECPKG_NOT_FOUND = 0x80090305
- SEC_E_UNKNOWN_CREDENTIALS = 0x8009030D
-
- @@map = {}
- constants.each { |v| @@map[self.const_get(v.to_s)] = v }
-
- attr_reader :value
-
- def initialize(value)
- # convert to unsigned long
- value = [value].pack("L").unpack("L").first
- raise "#{value.to_s(16)} is not a recognized result" unless @@map.has_key? value
- @value = value
- end
-
- def to_s
- @@map[@value].to_s
- end
-
- def ok?
- @value == SEC_I_CONTINUE_NEEDED || @value == SEC_E_OK
- end
-
- def ==(other)
- if other.is_a?(SSPIResult)
- @value == other.value
- elsif other.is_a?(Fixnum)
- @value == @@map[other]
- else
- false
- end
- end
- end
-
- # Handles "Negotiate" type authentication. Geared towards authenticating with a proxy server over HTTP
- class NegotiateAuth
- attr_accessor :credentials, :context, :contextAttributes, :user, :domain
-
- # Default request flags for SSPI functions
- REQUEST_FLAGS = ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION
-
- # NTLM tokens start with this header always. Encoding alone adds "==" and newline, so remove those
+ module SSPI
+ # Specifies how credential structure requested will be used. Only SECPKG_CRED_OUTBOUND is used
+ # here.
+ SECPKG_CRED_INBOUND = 0x00000001
+ SECPKG_CRED_OUTBOUND = 0x00000002
+ SECPKG_CRED_BOTH = 0x00000003
+
+ # Format of token. NETWORK format is used here.
+ SECURITY_NATIVE_DREP = 0x00000010
+ SECURITY_NETWORK_DREP = 0x00000000
+
+ # InitializeSecurityContext Requirement flags
+ ISC_REQ_REPLAY_DETECT = 0x00000004
+ ISC_REQ_SEQUENCE_DETECT = 0x00000008
+ ISC_REQ_CONFIDENTIALITY = 0x00000010
+ ISC_REQ_USE_SESSION_KEY = 0x00000020
+ ISC_REQ_PROMPT_FOR_CREDS = 0x00000040
+ ISC_REQ_CONNECTION = 0x00000800
+
+ # Win32 API Functions. Uses Win32API to bind methods to constants contained in class.
+ module API
+ extend Fiddle::Importer
+ dlload "secur32.dll"
+ [
+ # Can be called with AcquireCredentialsHandleA.call()
+ "unsigned long AcquireCredentialsHandleA(void *, void *, unsigned long, void *, void *, void *, void *, void *, void *)",
+ # Can be called with InitializeSecurityContextA.call()
+ "unsigned long InitializeSecurityContextA(void *, void *, void *, unsigned long, unsigned long, unsigned long, void *, unsigned long, void *, void *, void *, void *)",
+ # Can be called with DeleteSecurityContext.call()
+ "unsigned long DeleteSecurityContext(void *)",
+ # Can be called with FreeCredentialsHandle.call()
+ "unsigned long FreeCredentialsHandle(void *)"
+ ].each do |fn|
+ cfunc = extern fn, :stdcall
+ const_set cfunc.name.intern, cfunc
+ end
+ end
+
+ # SecHandle struct
+ class SecurityHandle
+ def upper
+ @struct.unpack("LL")[1]
+ end
+
+ def lower
+ @struct.unpack("LL")[0]
+ end
+
+ def to_p
+ @struct ||= "\0" * 8
+ end
+ end
+
+ # Some familiar aliases for the SecHandle structure
+ CredHandle = CtxtHandle = SecurityHandle
+
+ # TimeStamp struct
+ class TimeStamp
+ attr_reader :struct
+
+ def to_p
+ @struct ||= "\0" * 8
+ end
+ end
+
+ # Creates binary representations of a SecBufferDesc structure,
+ # including the SecBuffer contained inside.
+ class SecurityBuffer
+
+ SECBUFFER_TOKEN = 2 # Security token
+
+ TOKENBUFSIZE = 12288
+ SECBUFFER_VERSION = 0
+
+ def initialize(buffer = nil)
+ @buffer = buffer || "\0" * TOKENBUFSIZE
+ @bufferSize = @buffer.length
+ @type = SECBUFFER_TOKEN
+ end
+
+ def bufferSize
+ unpack
+ @bufferSize
+ end
+
+ def bufferType
+ unpack
+ @type
+ end
+
+ def token
+ unpack
+ @buffer
+ end
+
+ def to_p
+ # Assumption is that when to_p is called we are going to get a packed structure. Therefore,
+ # set @unpacked back to nil so we know to unpack when accessors are next accessed.
+ @unpacked = nil
+ # Assignment of inner structure to variable is very important here. Without it,
+ # will not be able to unpack changes to the structure. Alternative, nested unpacks,
+ # does not work (i.e. @struct.unpack("LLP12")[2].unpack("LLP12") results in "no associated pointer")
+ @sec_buffer ||= [@bufferSize, @type, @buffer].pack("LLP")
+ @struct ||= [SECBUFFER_VERSION, 1, @sec_buffer].pack("LLP")
+ end
+
+ private
+
+ # Unpacks the SecurityBufferDesc structure into member variables. We
+ # only want to do this once per struct, so the struct is deleted
+ # after unpacking.
+ def unpack
+ if ! @unpacked && @sec_buffer && @struct
+ @bufferSize, @type = @sec_buffer.unpack("LL")
+ @buffer = @sec_buffer.unpack("LLP#{@bufferSize}")[2]
+ @struct = nil
+ @sec_buffer = nil
+ @unpacked = true
+ end
+ end
+ end
+
+ # SEC_WINNT_AUTH_IDENTITY structure
+ class Identity
+ SEC_WINNT_AUTH_IDENTITY_ANSI = 0x1
+
+ attr_accessor :user, :domain, :password
+
+ def initialize(user = nil, domain = nil, password = nil)
+ @user = user
+ @domain = domain
+ @password = password
+ @flags = SEC_WINNT_AUTH_IDENTITY_ANSI
+ end
+
+ def to_p
+ [@user, @user ? @user.length : 0,
+ @domain, @domain ? @domain.length : 0,
+ @password, @password ? @password.length : 0,
+ @flags].pack("PLPLPLL")
+ end
+ end
+
+ # Takes a return result from an SSPI function and interprets the value.
+ class SSPIResult
+ # Good results
+ SEC_E_OK = 0x00000000
+ SEC_I_CONTINUE_NEEDED = 0x00090312
+
+ # These are generally returned by InitializeSecurityContext
+ SEC_E_INSUFFICIENT_MEMORY = 0x80090300
+ SEC_E_INTERNAL_ERROR = 0x80090304
+ SEC_E_INVALID_HANDLE = 0x80090301
+ SEC_E_INVALID_TOKEN = 0x80090308
+ SEC_E_LOGON_DENIED = 0x8009030C
+ SEC_E_NO_AUTHENTICATING_AUTHORITY = 0x80090311
+ SEC_E_NO_CREDENTIALS = 0x8009030E
+ SEC_E_TARGET_UNKNOWN = 0x80090303
+ SEC_E_UNSUPPORTED_FUNCTION = 0x80090302
+ SEC_E_WRONG_PRINCIPAL = 0x80090322
+
+ # These are generally returned by AcquireCredentialsHandle
+ SEC_E_NOT_OWNER = 0x80090306
+ SEC_E_SECPKG_NOT_FOUND = 0x80090305
+ SEC_E_UNKNOWN_CREDENTIALS = 0x8009030D
+
+ @@map = {}
+ constants.each { |v| @@map[self.const_get(v.to_s)] = v }
+
+ attr_reader :value
+
+ def initialize(value)
+ # convert to unsigned long
+ value = [value].pack("L").unpack("L").first
+ raise "#{value.to_s(16)} is not a recognized result" unless @@map.has_key? value
+ @value = value
+ end
+
+ def to_s
+ @@map[@value].to_s
+ end
+
+ def ok?
+ @value == SEC_I_CONTINUE_NEEDED || @value == SEC_E_OK
+ end
+
+ def ==(other)
+ if other.is_a?(SSPIResult)
+ @value == other.value
+ elsif other.is_a?(Fixnum)
+ @value == @@map[other]
+ else
+ false
+ end
+ end
+ end
+
+ # Handles "Negotiate" type authentication. Geared towards authenticating with a proxy server over HTTP
+ class NegotiateAuth
+ attr_accessor :credentials, :context, :contextAttributes, :user, :domain
+
+ # Default request flags for SSPI functions
+ REQUEST_FLAGS = ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONNECTION
+
+ # NTLM tokens start with this header always. Encoding alone adds "==" and newline, so remove those
B64_TOKEN_PREFIX = ["NTLMSSP"].pack("m").delete("=\n")
- # Given a connection and a request path, performs authentication as the current user and returns
- # the response from a GET request. The connnection should be a Net::HTTP object, and it should
- # have been constructed using the Net::HTTP.Proxy method, but anything that responds to "get" will work.
- # If a user and domain are given, will authenticate as the given user.
- # Returns the response received from the get method (usually Net::HTTPResponse)
- def NegotiateAuth.proxy_auth_get(http, path, user = nil, domain = nil)
- raise "http must respond to :get" unless http.respond_to?(:get)
- nego_auth = self.new user, domain
-
- resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
- if resp["Proxy-Authenticate"]
- resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(resp["Proxy-Authenticate"].split(" ").last.strip) }
- end
-
- resp
- end
-
- # Creates a new instance ready for authentication as the given user in the given domain.
- # Defaults to current user and domain as defined by ENV["USERDOMAIN"] and ENV["USERNAME"] if
- # no arguments are supplied.
- def initialize(user = nil, domain = nil)
- if user.nil? && domain.nil? && ENV["USERNAME"].nil? && ENV["USERDOMAIN"].nil?
- raise "A username or domain must be supplied since they cannot be retrieved from the environment"
- end
-
- @user = user || ENV["USERNAME"]
- @domain = domain || ENV["USERDOMAIN"]
- end
-
- # Gets the initial Negotiate token. Returns it as a base64 encoded string suitable for use in HTTP. Can
- # be easily decoded, however.
- def get_initial_token
- raise "This object is no longer usable because its resources have been freed." if @cleaned_up
- get_credentials
-
- outputBuffer = SecurityBuffer.new
- @context = CtxtHandle.new
- @contextAttributes = "\0" * 4
-
- result = SSPIResult.new(API::InitializeSecurityContext.call(@credentials.to_p, nil, nil,
- REQUEST_FLAGS,0, SECURITY_NETWORK_DREP, nil, 0, @context.to_p, outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p))
-
- if result.ok? then
- return encode_token(outputBuffer.token)
- else
- raise "Error: #{result.to_s}"
- end
- end
-
- # Takes a token and gets the next token in the Negotiate authentication chain. Token can be Base64 encoded or not.
- # The token can include the "Negotiate" header and it will be stripped.
- # Does not indicate if SEC_I_CONTINUE or SEC_E_OK was returned.
- # Token returned is Base64 encoded w/ all new lines removed.
- def complete_authentication(token)
- raise "This object is no longer usable because its resources have been freed." if @cleaned_up
-
- # Nil token OK, just set it to empty string
- token = "" if token.nil?
-
- if token.include? "Negotiate"
- # If the Negotiate prefix is passed in, assume we are seeing "Negotiate <token>" and get the token.
- token = token.split(" ").last
- end
-
- if token.include? B64_TOKEN_PREFIX
- # indicates base64 encoded token
+ # Given a connection and a request path, performs authentication as the current user and returns
+ # the response from a GET request. The connnection should be a Net::HTTP object, and it should
+ # have been constructed using the Net::HTTP.Proxy method, but anything that responds to "get" will work.
+ # If a user and domain are given, will authenticate as the given user.
+ # Returns the response received from the get method (usually Net::HTTPResponse)
+ def NegotiateAuth.proxy_auth_get(http, path, user = nil, domain = nil)
+ raise "http must respond to :get" unless http.respond_to?(:get)
+ nego_auth = self.new user, domain
+
+ resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.get_initial_token }
+ if resp["Proxy-Authenticate"]
+ resp = http.get path, { "Proxy-Authorization" => "Negotiate " + nego_auth.complete_authentication(resp["Proxy-Authenticate"].split(" ").last.strip) }
+ end
+
+ resp
+ end
+
+ # Creates a new instance ready for authentication as the given user in the given domain.
+ # Defaults to current user and domain as defined by ENV["USERDOMAIN"] and ENV["USERNAME"] if
+ # no arguments are supplied.
+ def initialize(user = nil, domain = nil)
+ if user.nil? && domain.nil? && ENV["USERNAME"].nil? && ENV["USERDOMAIN"].nil?
+ raise "A username or domain must be supplied since they cannot be retrieved from the environment"
+ end
+
+ @user = user || ENV["USERNAME"]
+ @domain = domain || ENV["USERDOMAIN"]
+ end
+
+ # Gets the initial Negotiate token. Returns it as a base64 encoded string suitable for use in HTTP. Can
+ # be easily decoded, however.
+ def get_initial_token
+ raise "This object is no longer usable because its resources have been freed." if @cleaned_up
+ get_credentials
+
+ outputBuffer = SecurityBuffer.new
+ @context = CtxtHandle.new
+ @contextAttributes = "\0" * 4
+
+ result = SSPIResult.new(API::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::AcquireCredentialsHandle.call(nil, "Negotiate", SECPKG_CRED_OUTBOUND, nil, @identity.to_p,
- nil, nil, @credentials.to_p, ts.to_p))
- raise "Error acquire credentials: #{result}" unless result.ok?
- end
-
- def encode_token(t)
- # encode64 will add newlines every 60 characters so we need to remove those.
+ end
+
+ outputBuffer = SecurityBuffer.new
+ result = SSPIResult.new(API::InitializeSecurityContext.call(@credentials.to_p, @context.to_p, nil,
+ REQUEST_FLAGS, 0, SECURITY_NETWORK_DREP, SecurityBuffer.new(token).to_p, 0,
+ @context.to_p,
+ outputBuffer.to_p, @contextAttributes, TimeStamp.new.to_p))
+
+ if result.ok? then
+ return encode_token(outputBuffer.token)
+ else
+ raise "Error: #{result.to_s}"
+ end
+ ensure
+ # need to make sure we don't clean up if we've already cleaned up.
+ clean_up unless @cleaned_up
+ end
+
+ private
+
+ def clean_up
+ # free structures allocated
+ @cleaned_up = true
+ API::FreeCredentialsHandle.call(@credentials.to_p)
+ API::DeleteSecurityContext.call(@context.to_p)
+ @context = nil
+ @credentials = nil
+ @contextAttributes = nil
+ end
+
+ # Gets credentials based on user, domain or both. If both are nil, an error occurs
+ def get_credentials
+ @credentials = CredHandle.new
+ ts = TimeStamp.new
+ @identity = Identity.new @user, @domain
+ result = SSPIResult.new(API::AcquireCredentialsHandleA.call(nil, "Negotiate", SECPKG_CRED_OUTBOUND, nil, @identity.to_p,
+ nil, nil, @credentials.to_p, ts.to_p))
+ raise "Error acquire credentials: #{result}" unless result.ok?
+ end
+
+ def encode_token(t)
+ # encode64 will add newlines every 60 characters so we need to remove those.
[t].pack("m").delete("\n")
- end
- end
- end
+ end
+ end
+ end
end
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
index 4f4550c5b9..59bae0e774 100644
--- a/ext/win32ole/win32ole.c
+++ b/ext/win32ole/win32ole.c
@@ -507,6 +507,7 @@ static UINT ole_encoding2cp(rb_encoding *enc)
ENC_MACHING_CP(enc, "GB2312", 20936);
ENC_MACHING_CP(enc, "GBK", 936);
ENC_MACHING_CP(enc, "IBM437", 437);
+ ENC_MACHING_CP(enc, "IBM720", 720);
ENC_MACHING_CP(enc, "IBM737", 737);
ENC_MACHING_CP(enc, "IBM775", 775);
ENC_MACHING_CP(enc, "IBM852", 852);
diff --git a/ext/win32ole/win32ole.gemspec b/ext/win32ole/win32ole.gemspec
new file mode 100644
index 0000000000..021625e44e
--- /dev/null
+++ b/ext/win32ole/win32ole.gemspec
@@ -0,0 +1,21 @@
+Gem::Specification.new do |spec|
+ spec.name = "win32ole"
+ spec.version = "1.8.8"
+ spec.authors = ["Masaki Suketa"]
+ spec.email = ["suke@ruby-lang.org"]
+
+ spec.summary = %q{Provides an interface for OLE Automation in Ruby}
+ spec.description = spec.summary
+ spec.homepage = "https://github.com/ruby/win32ole"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+
+ spec.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/ext/zlib/depend b/ext/zlib/depend
index 5ab5684fb0..5433affc69 100644
--- a/ext/zlib/depend
+++ b/ext/zlib/depend
@@ -2,8 +2,157 @@
zlib.o: $(RUBY_EXTCONF_H)
zlib.o: $(arch_hdrdir)/ruby/config.h
zlib.o: $(hdrdir)/ruby.h
+zlib.o: $(hdrdir)/ruby/internal/anyargs.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+zlib.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+zlib.o: $(hdrdir)/ruby/internal/assume.h
+zlib.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+zlib.o: $(hdrdir)/ruby/internal/attr/artificial.h
+zlib.o: $(hdrdir)/ruby/internal/attr/cold.h
+zlib.o: $(hdrdir)/ruby/internal/attr/const.h
+zlib.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+zlib.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+zlib.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+zlib.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+zlib.o: $(hdrdir)/ruby/internal/attr/error.h
+zlib.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+zlib.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+zlib.o: $(hdrdir)/ruby/internal/attr/format.h
+zlib.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+zlib.o: $(hdrdir)/ruby/internal/attr/noalias.h
+zlib.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+zlib.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+zlib.o: $(hdrdir)/ruby/internal/attr/noinline.h
+zlib.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+zlib.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+zlib.o: $(hdrdir)/ruby/internal/attr/pure.h
+zlib.o: $(hdrdir)/ruby/internal/attr/restrict.h
+zlib.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+zlib.o: $(hdrdir)/ruby/internal/attr/warning.h
+zlib.o: $(hdrdir)/ruby/internal/attr/weakref.h
+zlib.o: $(hdrdir)/ruby/internal/cast.h
+zlib.o: $(hdrdir)/ruby/internal/compiler_is.h
+zlib.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+zlib.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+zlib.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+zlib.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+zlib.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+zlib.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+zlib.o: $(hdrdir)/ruby/internal/compiler_since.h
+zlib.o: $(hdrdir)/ruby/internal/config.h
+zlib.o: $(hdrdir)/ruby/internal/constant_p.h
+zlib.o: $(hdrdir)/ruby/internal/core.h
+zlib.o: $(hdrdir)/ruby/internal/core/rarray.h
+zlib.o: $(hdrdir)/ruby/internal/core/rbasic.h
+zlib.o: $(hdrdir)/ruby/internal/core/rbignum.h
+zlib.o: $(hdrdir)/ruby/internal/core/rclass.h
+zlib.o: $(hdrdir)/ruby/internal/core/rdata.h
+zlib.o: $(hdrdir)/ruby/internal/core/rfile.h
+zlib.o: $(hdrdir)/ruby/internal/core/rhash.h
+zlib.o: $(hdrdir)/ruby/internal/core/robject.h
+zlib.o: $(hdrdir)/ruby/internal/core/rregexp.h
+zlib.o: $(hdrdir)/ruby/internal/core/rstring.h
+zlib.o: $(hdrdir)/ruby/internal/core/rstruct.h
+zlib.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+zlib.o: $(hdrdir)/ruby/internal/ctype.h
+zlib.o: $(hdrdir)/ruby/internal/dllexport.h
+zlib.o: $(hdrdir)/ruby/internal/dosish.h
+zlib.o: $(hdrdir)/ruby/internal/error.h
+zlib.o: $(hdrdir)/ruby/internal/eval.h
+zlib.o: $(hdrdir)/ruby/internal/event.h
+zlib.o: $(hdrdir)/ruby/internal/fl_type.h
+zlib.o: $(hdrdir)/ruby/internal/gc.h
+zlib.o: $(hdrdir)/ruby/internal/glob.h
+zlib.o: $(hdrdir)/ruby/internal/globals.h
+zlib.o: $(hdrdir)/ruby/internal/has/attribute.h
+zlib.o: $(hdrdir)/ruby/internal/has/builtin.h
+zlib.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+zlib.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+zlib.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+zlib.o: $(hdrdir)/ruby/internal/has/extension.h
+zlib.o: $(hdrdir)/ruby/internal/has/feature.h
+zlib.o: $(hdrdir)/ruby/internal/has/warning.h
+zlib.o: $(hdrdir)/ruby/internal/intern/array.h
+zlib.o: $(hdrdir)/ruby/internal/intern/bignum.h
+zlib.o: $(hdrdir)/ruby/internal/intern/class.h
+zlib.o: $(hdrdir)/ruby/internal/intern/compar.h
+zlib.o: $(hdrdir)/ruby/internal/intern/complex.h
+zlib.o: $(hdrdir)/ruby/internal/intern/cont.h
+zlib.o: $(hdrdir)/ruby/internal/intern/dir.h
+zlib.o: $(hdrdir)/ruby/internal/intern/enum.h
+zlib.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+zlib.o: $(hdrdir)/ruby/internal/intern/error.h
+zlib.o: $(hdrdir)/ruby/internal/intern/eval.h
+zlib.o: $(hdrdir)/ruby/internal/intern/file.h
+zlib.o: $(hdrdir)/ruby/internal/intern/gc.h
+zlib.o: $(hdrdir)/ruby/internal/intern/hash.h
+zlib.o: $(hdrdir)/ruby/internal/intern/io.h
+zlib.o: $(hdrdir)/ruby/internal/intern/load.h
+zlib.o: $(hdrdir)/ruby/internal/intern/marshal.h
+zlib.o: $(hdrdir)/ruby/internal/intern/numeric.h
+zlib.o: $(hdrdir)/ruby/internal/intern/object.h
+zlib.o: $(hdrdir)/ruby/internal/intern/parse.h
+zlib.o: $(hdrdir)/ruby/internal/intern/proc.h
+zlib.o: $(hdrdir)/ruby/internal/intern/process.h
+zlib.o: $(hdrdir)/ruby/internal/intern/random.h
+zlib.o: $(hdrdir)/ruby/internal/intern/range.h
+zlib.o: $(hdrdir)/ruby/internal/intern/rational.h
+zlib.o: $(hdrdir)/ruby/internal/intern/re.h
+zlib.o: $(hdrdir)/ruby/internal/intern/ruby.h
+zlib.o: $(hdrdir)/ruby/internal/intern/select.h
+zlib.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+zlib.o: $(hdrdir)/ruby/internal/intern/signal.h
+zlib.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+zlib.o: $(hdrdir)/ruby/internal/intern/string.h
+zlib.o: $(hdrdir)/ruby/internal/intern/struct.h
+zlib.o: $(hdrdir)/ruby/internal/intern/thread.h
+zlib.o: $(hdrdir)/ruby/internal/intern/time.h
+zlib.o: $(hdrdir)/ruby/internal/intern/variable.h
+zlib.o: $(hdrdir)/ruby/internal/intern/vm.h
+zlib.o: $(hdrdir)/ruby/internal/interpreter.h
+zlib.o: $(hdrdir)/ruby/internal/iterator.h
+zlib.o: $(hdrdir)/ruby/internal/memory.h
+zlib.o: $(hdrdir)/ruby/internal/method.h
+zlib.o: $(hdrdir)/ruby/internal/module.h
+zlib.o: $(hdrdir)/ruby/internal/newobj.h
+zlib.o: $(hdrdir)/ruby/internal/rgengc.h
+zlib.o: $(hdrdir)/ruby/internal/scan_args.h
+zlib.o: $(hdrdir)/ruby/internal/special_consts.h
+zlib.o: $(hdrdir)/ruby/internal/static_assert.h
+zlib.o: $(hdrdir)/ruby/internal/stdalign.h
+zlib.o: $(hdrdir)/ruby/internal/stdbool.h
+zlib.o: $(hdrdir)/ruby/internal/symbol.h
+zlib.o: $(hdrdir)/ruby/internal/token_paste.h
+zlib.o: $(hdrdir)/ruby/internal/value.h
+zlib.o: $(hdrdir)/ruby/internal/value_type.h
+zlib.o: $(hdrdir)/ruby/internal/variable.h
+zlib.o: $(hdrdir)/ruby/internal/warning_push.h
+zlib.o: $(hdrdir)/ruby/internal/xmalloc.h
zlib.o: $(hdrdir)/ruby/assert.h
zlib.o: $(hdrdir)/ruby/backward.h
+zlib.o: $(hdrdir)/ruby/backward/2/assume.h
+zlib.o: $(hdrdir)/ruby/backward/2/attributes.h
+zlib.o: $(hdrdir)/ruby/backward/2/bool.h
+zlib.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+zlib.o: $(hdrdir)/ruby/backward/2/inttypes.h
+zlib.o: $(hdrdir)/ruby/backward/2/limits.h
+zlib.o: $(hdrdir)/ruby/backward/2/long_long.h
+zlib.o: $(hdrdir)/ruby/backward/2/stdalign.h
+zlib.o: $(hdrdir)/ruby/backward/2/stdarg.h
zlib.o: $(hdrdir)/ruby/defines.h
zlib.o: $(hdrdir)/ruby/encoding.h
zlib.o: $(hdrdir)/ruby/intern.h
diff --git a/ext/zlib/extconf.rb b/ext/zlib/extconf.rb
index fd2f168522..76cd34582e 100644
--- a/ext/zlib/extconf.rb
+++ b/ext/zlib/extconf.rb
@@ -31,9 +31,12 @@ else
$extso << dll
$cleanfiles << "$(topdir)/#{dll}" << "$(ZIMPLIB)"
zmk = "\t$(MAKE) -f $(ZMKFILE) TOP=$(ZSRC)"
+ zopts = []
if $nmake
zmkfile = "$(ZSRC)/win32/Makefile.msc"
m = "#{zsrc}/win32/Makefile.msc"
+ # zopts << "USE_ASM=1"
+ zopts << "ARCH=#{RbConfig::CONFIG['target_cpu']}"
else
zmkfile = "$(ZSRC)/win32/Makefile.gcc"
m = "#{zsrc}/win32/Makefile.gcc"
@@ -55,9 +58,10 @@ else
addconf.push(
"ZMKFILE = #{zmkfile}\n",
"ZIMPLIB = #{zimplib}\n",
+ "ZOPTS = #{zopts.join(' ')}\n",
"$(TARGET_SO): $(ZIMPLIB)\n",
"$(ZIMPLIB):\n",
- "#{zmk} $@\n",
+ "#{zmk} $(ZOPTS) $@\n",
"install-so: $(topdir)/#{dll}",
"$(topdir)/#{dll}: $(ZIMPLIB)\n",
"\t$(Q) $(COPY) #{dll} $(@D)\n",
diff --git a/ext/zlib/extlibs b/ext/zlib/extlibs
new file mode 100644
index 0000000000..e79d699977
--- /dev/null
+++ b/ext/zlib/extlibs
@@ -0,0 +1,7 @@
+ver = 1.2.12
+pkg = zlib-$(ver)
+
+https://zlib.net/$(pkg).tar.gz \
+ md5:5fc414a9726be31427b440b434d05f78 \
+ sha512:cc2366fa45d5dfee1f983c8c51515e0cff959b61471e2e8d24350dea22d3f6fcc50723615a911b046ffc95f51ba337d39ae402131a55e6d1541d3b095d6c0a14 \
+ #
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 82e9fc42da..5dbeba6943 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 "1.1.0"
+#define RUBY_ZLIB_VERSION "2.0.0"
#ifndef RB_PASS_CALLED_KEYWORDS
# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
@@ -56,7 +56,10 @@ max_uint(long n)
#define MAX_UINT(n) (uInt)(n)
#endif
-static ID id_dictionaries;
+#define OPTHASH_GIVEN_P(opts) \
+ (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
+
+static ID id_dictionaries, id_read, id_buffer;
/*--------- Prototypes --------*/
@@ -130,7 +133,7 @@ static VALUE rb_inflate_s_allocate(VALUE);
static VALUE rb_inflate_initialize(int, VALUE*, VALUE);
static VALUE rb_inflate_s_inflate(VALUE, VALUE);
static void do_inflate(struct zstream*, VALUE);
-static VALUE rb_inflate_inflate(VALUE, VALUE);
+static VALUE rb_inflate_inflate(int, VALUE*, VALUE);
static VALUE rb_inflate_addstr(VALUE, VALUE);
static VALUE rb_inflate_sync(VALUE, VALUE);
static VALUE rb_inflate_sync_point_p(VALUE);
@@ -408,6 +411,15 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
if (NIL_P(str)) {
sum = func(sum, Z_NULL, 0);
}
+ else if (rb_obj_is_kind_of(str, rb_cIO)) {
+ VALUE buf;
+ VALUE buflen = INT2NUM(8192);
+
+ while (!NIL_P(buf = rb_funcall(str, id_read, 1, buflen))) {
+ StringValue(buf);
+ sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(buf), RSTRING_LEN(buf));
+ }
+ }
else {
StringValue(str);
sum = checksum_long(func, sum, (Bytef*)RSTRING_PTR(str), RSTRING_LEN(str));
@@ -423,6 +435,8 @@ do_checksum(int argc, VALUE *argv, uLong (*func)(uLong, const Bytef*, uInt))
* Calculates Adler-32 checksum for +string+, and returns updated value of
* +adler+. If +string+ is omitted, it returns the Adler-32 initial value. If
* +adler+ is omitted, it assumes that the initial value is given to +adler+.
+ * If +string+ is an IO instance, reads from the IO until the IO returns nil
+ * and returns Adler-32 of all read data.
*
* Example usage:
*
@@ -467,7 +481,9 @@ rb_zlib_adler32_combine(VALUE klass, VALUE adler1, VALUE adler2, VALUE len2)
*
* Calculates CRC checksum for +string+, and returns updated value of +crc+. If
* +string+ is omitted, it returns the CRC initial value. If +crc+ is omitted, it
- * assumes that the initial value is given to +crc+.
+ * assumes that the initial value is given to +crc+. If +string+ is an IO instance,
+ * reads from the IO until the IO returns nil and returns CRC checksum of all read
+ * data.
*
* FIXME: expression.
*/
@@ -546,8 +562,9 @@ struct zstream {
#define ZSTREAM_FLAG_CLOSING (1 << 3)
#define ZSTREAM_FLAG_GZFILE (1 << 4) /* disallows yield from expand_buffer for
gzip*/
-#define ZSTREAM_IN_PROGRESS (1 << 5)
-#define ZSTREAM_FLAG_UNUSED (1 << 6)
+#define ZSTREAM_REUSE_BUFFER (1 << 5)
+#define ZSTREAM_IN_PROGRESS (1 << 6)
+#define ZSTREAM_FLAG_UNUSED (1 << 7)
#define ZSTREAM_READY(z) ((z)->flags |= ZSTREAM_FLAG_READY)
#define ZSTREAM_IS_READY(z) ((z)->flags & ZSTREAM_FLAG_READY)
@@ -556,6 +573,8 @@ struct zstream {
#define ZSTREAM_IS_GZFILE(z) ((z)->flags & ZSTREAM_FLAG_GZFILE)
#define ZSTREAM_BUF_FILLED(z) (NIL_P((z)->buf) ? 0 : RSTRING_LEN((z)->buf))
+#define ZSTREAM_REUSE_BUFFER_P(z) ((z)->flags & ZSTREAM_REUSE_BUFFER)
+
#define ZSTREAM_EXPAND_BUFFER_OK 0
/* I think that more better value should be found,
@@ -635,13 +654,21 @@ zstream_expand_buffer(struct zstream *z)
if (buf_filled >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
int state = 0;
- rb_obj_reveal(z->buf, rb_cString);
+ if (!ZSTREAM_REUSE_BUFFER_P(z)) {
+ rb_obj_reveal(z->buf, rb_cString);
+ }
- rb_mutex_unlock(z->mutex);
+ rb_mutex_unlock(z->mutex);
rb_protect(rb_yield, z->buf, &state);
- rb_mutex_lock(z->mutex);
-
- z->buf = Qnil;
+ rb_mutex_lock(z->mutex);
+
+ if (ZSTREAM_REUSE_BUFFER_P(z)) {
+ rb_str_modify(z->buf);
+ rb_str_set_len(z->buf, 0);
+ }
+ else {
+ z->buf = Qnil;
+ }
zstream_expand_buffer_into(z, ZSTREAM_AVAIL_OUT_STEP_MAX);
if (state)
@@ -759,7 +786,9 @@ zstream_detach_buffer(struct zstream *z)
}
else {
dst = z->buf;
- rb_obj_reveal(dst, rb_cString);
+ if (!ZSTREAM_REUSE_BUFFER_P(z)) {
+ rb_obj_reveal(dst, rb_cString);
+ }
}
z->buf = Qnil;
@@ -1114,6 +1143,7 @@ loop:
if (args->jump_state)
rb_jump_tag(args->jump_state);
+
return Qnil;
}
@@ -1158,6 +1188,7 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush)
};
rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&args);
}
+
static VALUE
zstream_sync(struct zstream *z, Bytef *src, long len)
{
@@ -2056,8 +2087,8 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
* Document-method: Zlib::Inflate#inflate
*
* call-seq:
- * inflate(deflate_string) -> String
- * inflate(deflate_string) { |chunk| ... } -> nil
+ * inflate(deflate_string, buffer: nil) -> String
+ * inflate(deflate_string, buffer: nil) { |chunk| ... } -> nil
*
* Inputs +deflate_string+ into the inflate stream and returns the output from
* the stream. Calling this method, both the input and the output buffer of
@@ -2067,6 +2098,15 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
* If a block is given consecutive inflated chunks from the +deflate_string+
* are yielded to the block and +nil+ is returned.
*
+ * If a :buffer keyword argument is given and not nil:
+ *
+ * * The :buffer keyword should be a String, and will used as the output buffer.
+ * Using this option can reuse the memory required during inflation.
+ * * When not passing a block, the return value will be the same object as the
+ * :buffer keyword argument.
+ * * When passing a block, the yielded chunks will be the same value as the
+ * :buffer keyword argument.
+ *
* Raises a Zlib::NeedDict exception if a preset dictionary is needed to
* decompress. Set the dictionary by Zlib::Inflate#set_dictionary and then
* call this method again with an empty string to flush the stream:
@@ -2090,10 +2130,37 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
* See also Zlib::Inflate.new
*/
static VALUE
-rb_inflate_inflate(VALUE obj, VALUE src)
+rb_inflate_inflate(int argc, VALUE* argv, VALUE obj)
{
struct zstream *z = get_zstream(obj);
- VALUE dst;
+ VALUE dst, src, opts, buffer = Qnil;
+
+ if (OPTHASH_GIVEN_P(opts)) {
+ VALUE buf;
+ rb_get_kwargs(opts, &id_buffer, 0, 1, &buf);
+ if (buf != Qundef && buf != Qnil) {
+ buffer = StringValue(buf);
+ }
+ }
+ if (buffer != Qnil) {
+ if (!(ZSTREAM_REUSE_BUFFER_P(z) && z->buf == buffer)) {
+ long len = RSTRING_LEN(buffer);
+ if (len >= ZSTREAM_AVAIL_OUT_STEP_MAX) {
+ rb_str_modify(buffer);
+ }
+ else {
+ len = ZSTREAM_AVAIL_OUT_STEP_MAX - len;
+ rb_str_modify_expand(buffer, len);
+ }
+ rb_str_set_len(buffer, 0);
+ z->flags |= ZSTREAM_REUSE_BUFFER;
+ z->buf = buffer;
+ }
+ } else if (ZSTREAM_REUSE_BUFFER_P(z)) {
+ z->flags &= ~ZSTREAM_REUSE_BUFFER;
+ z->buf = Qnil;
+ }
+ rb_scan_args(argc, argv, "10", &src);
if (ZSTREAM_IS_FINISHED(z)) {
if (NIL_P(src)) {
@@ -2102,7 +2169,11 @@ rb_inflate_inflate(VALUE obj, VALUE src)
else {
StringValue(src);
zstream_append_buffer2(z, src);
- dst = rb_str_new(0, 0);
+ if (ZSTREAM_REUSE_BUFFER_P(z)) {
+ dst = rb_str_resize(buffer, 0);
+ } else {
+ dst = rb_str_new(0, 0);
+ }
}
}
else {
@@ -2254,7 +2325,7 @@ rb_inflate_set_dictionary(VALUE obj, VALUE dic)
#define OS_CODE OS_UNIX
#endif
-static ID id_write, id_read, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
+static ID id_write, id_readpartial, id_flush, id_seek, id_close, id_path, id_input;
static VALUE cGzError, cNoFooter, cCRCError, cLengthError;
@@ -3501,6 +3572,16 @@ rb_gzfile_path(VALUE obj)
return gz->path;
}
+static VALUE
+gzfile_initialize_path_partial(VALUE obj)
+{
+ struct gzfile* gz;
+ TypedData_Get_Struct(obj, struct gzfile, &gzfile_data_type, gz);
+ gz->path = rb_funcall(gz->io, id_path, 0);
+ rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
+ return Qnil;
+}
+
static void
rb_gzfile_ecopts(struct gzfile *gz, VALUE opts)
{
@@ -3609,8 +3690,8 @@ rb_gzwriter_initialize(int argc, VALUE *argv, VALUE obj)
rb_gzfile_ecopts(gz, opt);
if (rb_respond_to(io, id_path)) {
- gz->path = rb_funcall(gz->io, id_path, 0);
- rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
+ /* File#path may raise IOError in case when a path is unavailable */
+ rb_rescue2(gzfile_initialize_path_partial, obj, NULL, Qnil, rb_eIOError, (VALUE)0);
}
return obj;
@@ -3780,6 +3861,60 @@ rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
}
/*
+ * Document-method: Zlib::GzipReader.zcat
+ *
+ * call-seq:
+ * Zlib::GzipReader.zcat(io, options = {}, &block) => nil
+ * Zlib::GzipReader.zcat(io, options = {}) => string
+ *
+ * Decompresses all gzip data in the +io+, handling multiple gzip
+ * streams until the end of the +io+. There should not be any non-gzip
+ * data after the gzip streams.
+ *
+ * If a block is given, it is yielded strings of uncompressed data,
+ * and the method returns +nil+.
+ * If a block is not given, the method returns the concatenation of
+ * all uncompressed data in all gzip streams.
+ */
+static VALUE
+rb_gzreader_s_zcat(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE io, unused, obj, buf=0, tmpbuf;
+ long pos;
+
+ rb_check_arity(argc, 1, 2);
+ io = argv[0];
+
+ do {
+ obj = rb_funcallv(klass, rb_intern("new"), argc, argv);
+ if (rb_block_given_p()) {
+ rb_gzreader_each(0, 0, obj);
+ }
+ else {
+ if (!buf) {
+ buf = rb_str_new(0, 0);
+ }
+ tmpbuf = gzfile_read_all(get_gzfile(obj));
+ rb_str_cat(buf, RSTRING_PTR(tmpbuf), RSTRING_LEN(tmpbuf));
+ }
+
+ rb_gzreader_read(0, 0, obj);
+ pos = NUM2LONG(rb_funcall(io, rb_intern("pos"), 0));
+ unused = rb_gzreader_unused(obj);
+ rb_gzfile_finish(obj);
+ if (!NIL_P(unused)) {
+ pos -= NUM2LONG(rb_funcall(unused, rb_intern("length"), 0));
+ rb_funcall(io, rb_intern("pos="), 1, LONG2NUM(pos));
+ }
+ } while (pos < NUM2LONG(rb_funcall(io, rb_intern("size"), 0)));
+
+ if (rb_block_given_p()) {
+ return Qnil;
+ }
+ return buf;
+}
+
+/*
* Document-method: Zlib::GzipReader.new
*
* call-seq:
@@ -3817,8 +3952,8 @@ rb_gzreader_initialize(int argc, VALUE *argv, VALUE obj)
rb_gzfile_ecopts(gz, opt);
if (rb_respond_to(io, id_path)) {
- gz->path = rb_funcall(gz->io, id_path, 0);
- rb_define_singleton_method(obj, "path", rb_gzfile_path, 0);
+ /* File#path may raise IOError in case when a path is unavailable */
+ rb_rescue2(gzfile_initialize_path_partial, obj, NULL, Qnil, rb_eIOError, (VALUE)0);
}
return obj;
@@ -4006,20 +4141,6 @@ rb_gzreader_each_byte(VALUE obj)
}
/*
- * Document-method: Zlib::GzipReader#bytes
- *
- * This is a deprecated alias for <code>each_byte</code>.
- */
-static VALUE
-rb_gzreader_bytes(VALUE obj)
-{
- rb_warn("Zlib::GzipReader#bytes is deprecated; use #each_byte instead");
- if (!rb_block_given_p())
- return rb_enumeratorize(obj, ID2SYM(rb_intern("each_byte")), 0, 0);
- return rb_gzreader_each_byte(obj);
-}
-
-/*
* Document-method: Zlib::GzipReader#ungetc
*
* See Zlib::GzipReader documentation for a description.
@@ -4245,6 +4366,8 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj)
* Document-method: Zlib::GzipReader#gets
*
* See Zlib::GzipReader documentation for a description.
+ * However, note that this method can return +nil+ even if
+ * #eof? returns false, unlike the behavior of File#gets.
*/
static VALUE
rb_gzreader_gets(int argc, VALUE *argv, VALUE obj)
@@ -4292,20 +4415,6 @@ rb_gzreader_each(int argc, VALUE *argv, VALUE obj)
}
/*
- * Document-method: Zlib::GzipReader#lines
- *
- * This is a deprecated alias for <code>each_line</code>.
- */
-static VALUE
-rb_gzreader_lines(int argc, VALUE *argv, VALUE obj)
-{
- rb_warn("Zlib::GzipReader#lines is deprecated; use #each_line instead");
- if (!rb_block_given_p())
- return rb_enumeratorize(obj, ID2SYM(rb_intern("each_line")), argc, argv);
- return rb_gzreader_each(argc, argv, obj);
-}
-
-/*
* Document-method: Zlib::GzipReader#readlines
*
* See Zlib::GzipReader documentation for a description.
@@ -4355,8 +4464,6 @@ zlib_gzip_end(struct gzfile *gz)
zstream_end(&gz->z);
}
-#define OPTHASH_GIVEN_P(opts) \
- (argc > 0 && !NIL_P((opts) = rb_check_hash_type(argv[argc-1])) && (--argc, 1))
static ID id_level, id_strategy;
static VALUE zlib_gzip_run(VALUE arg);
@@ -4509,6 +4616,10 @@ zlib_gunzip_run(VALUE arg)
void
Init_zlib(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
#undef rb_intern
VALUE mZlib, cZStream, cDeflate, cInflate;
#if GZIP_SUPPORT
@@ -4604,7 +4715,7 @@ Init_zlib(void)
rb_define_alloc_func(cInflate, rb_inflate_s_allocate);
rb_define_method(cInflate, "initialize", rb_inflate_initialize, -1);
rb_define_method(cInflate, "add_dictionary", rb_inflate_add_dictionary, 1);
- rb_define_method(cInflate, "inflate", rb_inflate_inflate, 1);
+ rb_define_method(cInflate, "inflate", rb_inflate_inflate, -1);
rb_define_method(cInflate, "<<", rb_inflate_addstr, 1);
rb_define_method(cInflate, "sync", rb_inflate_sync, 1);
rb_define_method(cInflate, "sync_point?", rb_inflate_sync_point_p, 0);
@@ -4753,6 +4864,7 @@ Init_zlib(void)
rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
+ rb_define_singleton_method(cGzipReader, "zcat", rb_gzreader_s_zcat, -1);
rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
@@ -4765,14 +4877,12 @@ Init_zlib(void)
rb_define_method(cGzipReader, "readbyte", rb_gzreader_readbyte, 0);
rb_define_method(cGzipReader, "each_byte", rb_gzreader_each_byte, 0);
rb_define_method(cGzipReader, "each_char", rb_gzreader_each_char, 0);
- rb_define_method(cGzipReader, "bytes", rb_gzreader_bytes, 0);
rb_define_method(cGzipReader, "ungetc", rb_gzreader_ungetc, 1);
rb_define_method(cGzipReader, "ungetbyte", rb_gzreader_ungetbyte, 1);
rb_define_method(cGzipReader, "gets", rb_gzreader_gets, -1);
rb_define_method(cGzipReader, "readline", rb_gzreader_readline, -1);
rb_define_method(cGzipReader, "each", rb_gzreader_each, -1);
rb_define_method(cGzipReader, "each_line", rb_gzreader_each, -1);
- rb_define_method(cGzipReader, "lines", rb_gzreader_lines, -1);
rb_define_method(cGzipReader, "readlines", rb_gzreader_readlines, -1);
rb_define_method(cGzipReader, "external_encoding", rb_gzreader_external_encoding, 0);
@@ -4814,6 +4924,7 @@ Init_zlib(void)
id_level = rb_intern("level");
id_strategy = rb_intern("strategy");
+ id_buffer = rb_intern("buffer");
#endif /* GZIP_SUPPORT */
}
diff --git a/ext/zlib/zlib.gemspec b/ext/zlib/zlib.gemspec
index 4a77ae325e..1d35065921 100644
--- a/ext/zlib/zlib.gemspec
+++ b/ext/zlib/zlib.gemspec
@@ -20,9 +20,9 @@ Gem::Specification.new do |spec|
spec.summary = %q{Ruby interface for the zlib compression/decompression library}
spec.description = %q{Ruby interface for the zlib compression/decompression library}
spec.homepage = "https://github.com/ruby/zlib"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "ext/zlib/extconf.rb", "ext/zlib/zlib.c", "zlib.gemspec"]
+ spec.files = [".gitignore", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "ext/zlib/extconf.rb", "ext/zlib/zlib.c", "zlib.gemspec"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
diff --git a/file.c b/file.c
index 455e1182e7..e77042fe20 100644
--- a/file.c
+++ b/file.c
@@ -11,14 +11,22 @@
**********************************************************************/
+#include "ruby/internal/config.h"
+
#ifdef _WIN32
-#include "missing/file.h"
+# include "missing/file.h"
+# include "ruby.h"
#endif
+
+#include <ctype.h>
+#include <time.h>
+
#ifdef __CYGWIN__
-#include <windows.h>
-#include <sys/cygwin.h>
-#include <wchar.h>
+# include <windows.h>
+# include <sys/cygwin.h>
+# include <wchar.h>
#endif
+
#ifdef __APPLE__
# if !(defined(__has_feature) && defined(__has_attribute))
/* Maybe a bug in SDK of Xcode 10.2.1 */
@@ -28,21 +36,13 @@
# define API_AVAILABLE(...)
# define API_DEPRECATED(...)
# endif
-#include <CoreFoundation/CFString.h>
+# include <CoreFoundation/CFString.h>
#endif
-#include "id.h"
-#include "ruby/encoding.h"
-#include "ruby/io.h"
-#include "ruby/util.h"
-#include "ruby/thread.h"
-#include "internal.h"
-#include "dln.h"
-#include "encindex.h"
-
#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+# include <unistd.h>
#endif
+
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
@@ -60,77 +60,73 @@ int flock(int, int);
# define MAXPATHLEN 1024
#endif
-#include <ctype.h>
-
-#include <time.h>
-
#ifdef HAVE_UTIME_H
-#include <utime.h>
+# include <utime.h>
#elif defined HAVE_SYS_UTIME_H
-#include <sys/utime.h>
+# include <sys/utime.h>
#endif
#ifdef HAVE_PWD_H
-#include <pwd.h>
+# include <pwd.h>
#endif
#ifdef HAVE_SYS_SYSMACROS_H
-#include <sys/sysmacros.h>
+# include <sys/sysmacros.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_MKDEV_H
-#include <sys/mkdev.h>
+# include <sys/mkdev.h>
#endif
#if defined(HAVE_FCNTL_H)
-#include <fcntl.h>
+# include <fcntl.h>
#endif
#if defined(HAVE_SYS_TIME_H)
-#include <sys/time.h>
+# include <sys/time.h>
#endif
#if !defined HAVE_LSTAT && !defined lstat
-#define lstat stat
+# define lstat stat
#endif
/* define system APIs */
#ifdef _WIN32
-#include "win32/file.h"
-#define STAT(p, s) rb_w32_ustati128((p), (s))
-#undef lstat
-#define lstat(p, s) rb_w32_ulstati128((p), (s))
-#undef access
-#define access(p, m) rb_w32_uaccess((p), (m))
-#undef truncate
-#define truncate(p, n) rb_w32_utruncate((p), (n))
-#undef chmod
-#define chmod(p, m) rb_w32_uchmod((p), (m))
-#undef chown
-#define chown(p, o, g) rb_w32_uchown((p), (o), (g))
-#undef lchown
-#define lchown(p, o, g) rb_w32_ulchown((p), (o), (g))
-#undef utimensat
-#define utimensat(s, p, t, f) rb_w32_uutimensat((s), (p), (t), (f))
-#undef link
-#define link(f, t) rb_w32_ulink((f), (t))
-#undef unlink
-#define unlink(p) rb_w32_uunlink(p)
-#undef rename
-#define rename(f, t) rb_w32_urename((f), (t))
-#undef symlink
-#define symlink(s, l) rb_w32_usymlink((s), (l))
-
-#ifdef HAVE_REALPATH
+# include "win32/file.h"
+# define STAT(p, s) rb_w32_ustati128((p), (s))
+# undef lstat
+# define lstat(p, s) rb_w32_ulstati128((p), (s))
+# undef access
+# define access(p, m) rb_w32_uaccess((p), (m))
+# undef truncate
+# define truncate(p, n) rb_w32_utruncate((p), (n))
+# undef chmod
+# define chmod(p, m) rb_w32_uchmod((p), (m))
+# undef chown
+# define chown(p, o, g) rb_w32_uchown((p), (o), (g))
+# undef lchown
+# define lchown(p, o, g) rb_w32_ulchown((p), (o), (g))
+# undef utimensat
+# define utimensat(s, p, t, f) rb_w32_uutimensat((s), (p), (t), (f))
+# undef link
+# define link(f, t) rb_w32_ulink((f), (t))
+# undef unlink
+# define unlink(p) rb_w32_uunlink(p)
+# undef rename
+# define rename(f, t) rb_w32_urename((f), (t))
+# undef symlink
+# define symlink(s, l) rb_w32_usymlink((s), (l))
+
+# ifdef HAVE_REALPATH
/* Don't use native realpath(3) on Windows, as the check for
absolute paths does not work for drive letters. */
-#undef HAVE_REALPATH
-#endif
+# undef HAVE_REALPATH
+# endif
#else
-#define STAT(p, s) stat((p), (s))
+# define STAT(p, s) stat((p), (s))
#endif
#if defined _WIN32 || defined __APPLE__
@@ -143,7 +139,7 @@ int flock(int, int);
/* utime may fail if time is out-of-range for the FS [ruby-dev:38277] */
#if defined DOSISH || defined __CYGWIN__
-# define UTIME_EINVAL
+# define UTIME_EINVAL
#endif
/* Solaris 10 realpath(3) doesn't support File.realpath */
@@ -152,10 +148,29 @@ int flock(int, int);
#endif
#ifdef HAVE_REALPATH
-#include <limits.h>
-#include <stdlib.h>
+# include <limits.h>
+# include <stdlib.h>
#endif
+#include "dln.h"
+#include "encindex.h"
+#include "id.h"
+#include "internal.h"
+#include "internal/compilers.h"
+#include "internal/dir.h"
+#include "internal/error.h"
+#include "internal/file.h"
+#include "internal/io.h"
+#include "internal/load.h"
+#include "internal/object.h"
+#include "internal/process.h"
+#include "internal/thread.h"
+#include "internal/vm.h"
+#include "ruby/encoding.h"
+#include "ruby/io.h"
+#include "ruby/thread.h"
+#include "ruby/util.h"
+
VALUE rb_cFile;
VALUE rb_mFileTest;
VALUE rb_cStat;
@@ -253,46 +268,6 @@ rb_str_encode_ospath(VALUE path)
#ifdef __APPLE__
# define NORMALIZE_UTF8PATH 1
-
-# ifdef HAVE_WORKING_FORK
-static void
-rb_CFString_class_initialize_before_fork(void)
-{
- /*
- * Since macOS 13, CFString family API used in
- * rb_str_append_normalized_ospath may internally use Objective-C classes
- * (NSTaggedPointerString and NSPlaceholderMutableString) for small strings.
- *
- * On the other hand, Objective-C classes should not be used for the first
- * time in a fork()'ed but not exec()'ed process. Violations for this rule
- * can result deadlock during class initialization, so Objective-C runtime
- * conservatively crashes on such cases by default.
- *
- * Therefore, we need to use CFString API to initialize Objective-C classes
- * used internally *before* fork().
- *
- * For future changes, please note that this initialization process cannot
- * be done in ctor because NSTaggedPointerString in CoreFoundation is enabled
- * after CFStringInitializeTaggedStrings(), which is called during loading
- * Objective-C runtime after ctor.
- * For more details, see https://bugs.ruby-lang.org/issues/18912
- */
-
- /* 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);
-}
-# endif
-
static VALUE
rb_str_append_normalized_ospath(VALUE str, const char *ptr, long len)
{
@@ -707,7 +682,21 @@ rb_stat_mode(VALUE self)
static VALUE
rb_stat_nlink(VALUE self)
{
- return UINT2NUM(get_stat(self)->st_nlink);
+ /* struct stat::st_nlink is nlink_t in POSIX. Not the case for Windows. */
+ const struct stat *ptr = get_stat(self);
+
+ if (sizeof(ptr->st_nlink) <= sizeof(int)) {
+ return UINT2NUM((unsigned)ptr->st_nlink);
+ }
+ else if (sizeof(ptr->st_nlink) == sizeof(long)) {
+ return ULONG2NUM((unsigned long)ptr->st_nlink);
+ }
+ else if (sizeof(ptr->st_nlink) == sizeof(LONG_LONG)) {
+ return ULL2NUM((unsigned LONG_LONG)ptr->st_nlink);
+ }
+ else {
+ rb_bug(":FIXME: don't know what to do");
+ }
}
/*
@@ -1798,25 +1787,20 @@ rb_file_exist_p(VALUE obj, VALUE fname)
return Qtrue;
}
-/*
- * call-seq:
- * File.exists?(file_name) -> true or false
- *
- * Deprecated method. Don't use.
- */
+/* :nodoc: */
static VALUE
rb_file_exists_p(VALUE obj, VALUE fname)
{
- const char *s = "FileTest#";
+ const char *s = "FileTest#exist?";
if (obj == rb_mFileTest) {
- s = "FileTest.";
+ s = "FileTest.exist?";
}
else if (obj == rb_cFile ||
(RB_TYPE_P(obj, T_CLASS) &&
RTEST(rb_class_inherited_p(obj, rb_cFile)))) {
- s = "File.";
+ s = "File.exist?";
}
- rb_warning("%sexists? is a deprecated name, use %sexist? instead", s, s);
+ rb_warn_deprecated("%.*ss?", s, (int)(strlen(s)-1), s);
return rb_file_exist_p(obj, fname);
}
@@ -4405,7 +4389,6 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum
VALUE unresolved_path;
char *resolved_ptr = NULL;
VALUE resolved;
- struct stat st;
if (mode == RB_REALPATH_DIR) {
return rb_check_realpath_emulate(basedir, path, origenc, mode);
@@ -4436,14 +4419,17 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum
resolved = ospath_new(resolved_ptr, strlen(resolved_ptr), rb_filesystem_encoding());
free(resolved_ptr);
+# if !defined(__LINUX__) && !defined(__APPLE__)
/* As `resolved` is a String in the filesystem encoding, no
* conversion is needed */
+ struct stat st;
if (stat_without_gvl(RSTRING_PTR(resolved), &st) < 0) {
if (mode == RB_REALPATH_CHECK) {
return Qnil;
}
rb_sys_fail_path(unresolved_path);
}
+# endif
if (origenc && origenc != rb_enc_get(resolved)) {
if (!rb_enc_str_asciionly_p(resolved)) {
@@ -5315,14 +5301,7 @@ rb_f_test(int argc, VALUE *argv, VALUE _)
if (argc == 0) rb_check_arity(argc, 2, 3);
cmd = NUM2CHR(argv[0]);
if (cmd == 0) {
- unknown:
- /* unknown command */
- if (ISPRINT(cmd)) {
- rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd);
- }
- else {
- rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd);
- }
+ goto unknown;
}
if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
CHECK(1);
@@ -5448,7 +5427,15 @@ rb_f_test(int argc, VALUE *argv, VALUE _)
return Qfalse;
}
}
- goto unknown;
+ unknown:
+ /* unknown command */
+ if (ISPRINT(cmd)) {
+ rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd);
+ }
+ else {
+ rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd);
+ }
+ UNREACHABLE_RETURN(Qundef);
}
@@ -6171,7 +6158,7 @@ rb_is_absolute_path(const char *path)
#if ENABLE_PATH_CHECK
static int
-path_check_0(VALUE path, int execpath)
+path_check_0(VALUE path)
{
struct stat st;
const char *p0 = StringValueCStr(path);
@@ -6199,12 +6186,12 @@ path_check_0(VALUE path, int execpath)
#endif
if (STAT(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
#ifdef S_ISVTX
- && !(p && execpath && (st.st_mode & S_ISVTX))
+ && !(p && (st.st_mode & S_ISVTX))
#endif
&& !access(p0, W_OK)) {
- rb_enc_warn(enc, "Insecure world writable dir %s in %sPATH, mode 0%"
+ rb_enc_warn(enc, "Insecure world writable dir %s in PATH, mode 0%"
PRI_MODET_PREFIX"o",
- p0, (execpath ? "" : "LOAD_"), st.st_mode);
+ p0, st.st_mode);
if (p) *p = '/';
RB_GC_GUARD(path);
return 0;
@@ -6219,12 +6206,6 @@ path_check_0(VALUE path, int execpath)
}
#endif
-#if ENABLE_PATH_CHECK
-#define fpath_check(path) path_check_0((path), FALSE)
-#else
-#define fpath_check(path) 1
-#endif
-
int
rb_path_check(const char *path)
{
@@ -6240,7 +6221,7 @@ rb_path_check(const char *path)
if (!p) p = pend;
for (;;) {
- if (!path_check_0(rb_str_new(p0, p - p0), TRUE)) {
+ if (!path_check_0(rb_str_new(p0, p - p0))) {
return 0; /* not safe */
}
p0 = p + 1;
@@ -6321,13 +6302,6 @@ copy_path_class(VALUE path, VALUE orig)
}
int
-rb_find_file_ext_safe(VALUE *filep, const char *const *ext, int _level)
-{
- rb_warn("rb_find_file_ext_safe will be removed in Ruby 3.0");
- return rb_find_file_ext(filep, ext);
-}
-
-int
rb_find_file_ext(VALUE *filep, const char *const *ext)
{
const char *f = StringValueCStr(*filep);
@@ -6387,13 +6361,6 @@ rb_find_file_ext(VALUE *filep, const char *const *ext)
}
VALUE
-rb_find_file_safe(VALUE path, int _level)
-{
- rb_warn("rb_find_file_safe will be removed in Ruby 3.0");
- return rb_find_file(path);
-}
-
-VALUE
rb_find_file(VALUE path)
{
VALUE tmp, load_path;
@@ -6495,10 +6462,6 @@ const char ruby_null_device[] =
void
Init_File(void)
{
-#if defined(__APPLE__) && defined(HAVE_WORKING_FORK)
- rb_CFString_class_initialize_before_fork();
-#endif
-
VALUE separator;
rb_mFileTest = rb_define_module("FileTest");
diff --git a/gc.c b/gc.c
index 67a709ff79..5d0c342206 100644
--- a/gc.c
+++ b/gc.c
@@ -14,43 +14,34 @@
#define rb_data_object_alloc rb_data_object_alloc
#define rb_data_typed_object_alloc rb_data_typed_object_alloc
-#include "ruby/encoding.h"
-#include "ruby/io.h"
-#include "ruby/st.h"
-#include "ruby/re.h"
-#include "ruby/thread.h"
-#include "ruby/util.h"
-#include "ruby/debug.h"
-#include "internal.h"
-#include "eval_intern.h"
-#include "vm_core.h"
-#include "builtin.h"
-#include "gc.h"
-#include "constant.h"
-#include "ruby_atomic.h"
-#include "probes.h"
-#include "id_table.h"
-#include "symbol.h"
-#include <stdio.h>
-#include <stdarg.h>
-#include <setjmp.h>
-#include <sys/types.h>
-#include "ruby_assert.h"
-#include "debug_counter.h"
-#include "transient_heap.h"
-#include "mjit.h"
+#include "ruby/internal/config.h"
+#ifdef _WIN32
+# include "ruby/ruby.h"
+#endif
-#undef rb_data_object_wrap
+#include <signal.h>
+
+#define sighandler_t ruby_sighandler_t
+
+#ifndef _WIN32
+#include <unistd.h>
+#include <sys/mman.h>
+#endif
+
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdio.h>
#ifndef HAVE_MALLOC_USABLE_SIZE
# ifdef _WIN32
-# define HAVE_MALLOC_USABLE_SIZE
-# define malloc_usable_size(a) _msize(a)
+# define HAVE_MALLOC_USABLE_SIZE
+# define malloc_usable_size(a) _msize(a)
# elif defined HAVE_MALLOC_SIZE
-# define HAVE_MALLOC_USABLE_SIZE
-# define malloc_usable_size(a) malloc_size(a)
+# define HAVE_MALLOC_USABLE_SIZE
+# define malloc_usable_size(a) malloc_size(a)
# endif
#endif
+
#ifdef HAVE_MALLOC_USABLE_SIZE
# ifdef RUBY_ALTERNATIVE_MALLOC_HEADER
# include RUBY_ALTERNATIVE_MALLOC_HEADER
@@ -64,74 +55,79 @@
#endif
#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
+# include <sys/time.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
+# include <sys/resource.h>
#endif
#if defined _WIN32 || defined __CYGWIN__
-#include <windows.h>
+# include <windows.h>
#elif defined(HAVE_POSIX_MEMALIGN)
#elif defined(HAVE_MEMALIGN)
-#include <malloc.h>
+# include <malloc.h>
#endif
-#define rb_setjmp(env) RUBY_SETJMP(env)
-#define rb_jmp_buf rb_jmpbuf_t
-
-#if defined(_MSC_VER) && defined(_WIN64)
-#include <intrin.h>
-#pragma intrinsic(_umul128)
-#endif
-
-/* Expecting this struct to be eliminated by function inlinings */
-struct optional {
- bool left;
- size_t right;
-};
-
-static inline struct optional
-size_mul_overflow(size_t x, size_t y)
-{
- bool p;
- size_t z;
-#if 0
-
-#elif defined(HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW)
- p = __builtin_mul_overflow(x, y, &z);
-
-#elif defined(DSIZE_T)
- RB_GNUC_EXTENSION DSIZE_T dx = x;
- RB_GNUC_EXTENSION DSIZE_T dy = y;
- RB_GNUC_EXTENSION DSIZE_T dz = dx * dy;
- p = dz > SIZE_MAX;
- z = (size_t)dz;
+#include <sys/types.h>
-#elif defined(_MSC_VER) && defined(_WIN64)
- unsigned __int64 dp;
- unsigned __int64 dz = _umul128(x, y, &dp);
- p = (bool)dp;
- z = (size_t)dz;
+#include "constant.h"
+#include "debug_counter.h"
+#include "eval_intern.h"
+#include "gc.h"
+#include "id_table.h"
+#include "internal.h"
+#include "internal/class.h"
+#include "internal/complex.h"
+#include "internal/cont.h"
+#include "internal/error.h"
+#include "internal/eval.h"
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/imemo.h"
+#include "internal/io.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/proc.h"
+#include "internal/rational.h"
+#include "internal/sanitizers.h"
+#include "internal/struct.h"
+#include "internal/symbol.h"
+#include "internal/thread.h"
+#include "internal/variable.h"
+#include "internal/warnings.h"
+#include "mjit.h"
+#include "probes.h"
+#include "regint.h"
+#include "ruby/debug.h"
+#include "ruby/io.h"
+#include "ruby/re.h"
+#include "ruby/st.h"
+#include "ruby/thread.h"
+#include "ruby/util.h"
+#include "ruby_assert.h"
+#include "ruby_atomic.h"
+#include "symbol.h"
+#include "transient_heap.h"
+#include "vm_core.h"
+#include "vm_sync.h"
+#include "vm_callinfo.h"
+#include "ractor_core.h"
-#else
- /* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */
- p = (y != 0) && (x > SIZE_MAX / y);
- z = x * y;
+#include "builtin.h"
-#endif
- return (struct optional) { p, z, };
-}
+#define rb_setjmp(env) RUBY_SETJMP(env)
+#define rb_jmp_buf rb_jmpbuf_t
+#undef rb_data_object_wrap
-static inline struct optional
+static inline struct rbimpl_size_mul_overflow_tag
size_add_overflow(size_t x, size_t y)
{
size_t z;
bool p;
#if 0
-#elif defined(HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW)
+#elif __has_builtin(__builtin_add_overflow)
p = __builtin_add_overflow(x, y, &z);
#elif defined(DSIZE_T)
@@ -146,24 +142,24 @@ size_add_overflow(size_t x, size_t y)
p = z < y;
#endif
- return (struct optional) { p, z, };
+ return (struct rbimpl_size_mul_overflow_tag) { p, z, };
}
-static inline struct optional
+static inline struct rbimpl_size_mul_overflow_tag
size_mul_add_overflow(size_t x, size_t y, size_t z) /* x * y + z */
{
- struct optional t = size_mul_overflow(x, y);
- struct optional u = size_add_overflow(t.right, z);
- return (struct optional) { t.left || u.left, u.right };
+ struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y);
+ struct rbimpl_size_mul_overflow_tag u = size_add_overflow(t.right, z);
+ return (struct rbimpl_size_mul_overflow_tag) { t.left || u.left, u.right };
}
-static inline struct optional
+static inline struct rbimpl_size_mul_overflow_tag
size_mul_add_mul_overflow(size_t x, size_t y, size_t z, size_t w) /* x * y + z * w */
{
- struct optional t = size_mul_overflow(x, y);
- struct optional u = size_mul_overflow(z, w);
- struct optional v = size_add_overflow(t.right, u.right);
- return (struct optional) { t.left || u.left || v.left, v.right };
+ struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y);
+ struct rbimpl_size_mul_overflow_tag u = rbimpl_size_mul_overflow(z, w);
+ struct rbimpl_size_mul_overflow_tag v = size_add_overflow(t.right, u.right);
+ return (struct rbimpl_size_mul_overflow_tag) { t.left || u.left || v.left, v.right };
}
PRINTF_ARGS(NORETURN(static void gc_raise(VALUE, const char*, ...)), 2, 3);
@@ -171,7 +167,7 @@ PRINTF_ARGS(NORETURN(static void gc_raise(VALUE, const char*, ...)), 2, 3);
static inline size_t
size_mul_or_raise(size_t x, size_t y, VALUE exc)
{
- struct optional t = size_mul_overflow(x, y);
+ struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y);
if (LIKELY(!t.left)) {
return t.right;
}
@@ -197,7 +193,7 @@ rb_size_mul_or_raise(size_t x, size_t y, VALUE exc)
static inline size_t
size_mul_add_or_raise(size_t x, size_t y, size_t z, VALUE exc)
{
- struct optional t = size_mul_add_overflow(x, y, z);
+ struct rbimpl_size_mul_overflow_tag t = size_mul_add_overflow(x, y, z);
if (LIKELY(!t.left)) {
return t.right;
}
@@ -224,7 +220,7 @@ rb_size_mul_add_or_raise(size_t x, size_t y, size_t z, VALUE exc)
static inline size_t
size_mul_add_mul_or_raise(size_t x, size_t y, size_t z, size_t w, VALUE exc)
{
- struct optional t = size_mul_add_mul_overflow(x, y, z, w);
+ struct rbimpl_size_mul_overflow_tag t = size_mul_add_mul_overflow(x, y, z, w);
if (LIKELY(!t.left)) {
return t.right;
}
@@ -365,7 +361,6 @@ static ruby_gc_params_t gc_params = {
#define GC_DEBUG 0
#endif
-#if USE_RGENGC
/* RGENGC_DEBUG:
* 1: basic information
* 2: remember set operation
@@ -383,7 +378,7 @@ static ruby_gc_params_t gc_params = {
#if RGENGC_DEBUG < 0 && !defined(_MSC_VER)
# define RGENGC_DEBUG_ENABLED(level) (-(RGENGC_DEBUG) >= (level) && ruby_rgengc_debug >= (level))
#else
-# define RGENGC_DEBUG_ENABLED(level) ((RGENGC_DEBUG) >= (level))
+# define RGENGC_DEBUG_ENABLED(level) 0
#endif
int ruby_rgengc_debug;
@@ -438,22 +433,6 @@ int ruby_rgengc_debug;
#define RGENGC_FORCE_MAJOR_GC 0
#endif
-#else /* USE_RGENGC */
-
-#ifdef RGENGC_DEBUG
-#undef RGENGC_DEBUG
-#endif
-#define RGENGC_DEBUG 0
-#ifdef RGENGC_CHECK_MODE
-#undef RGENGC_CHECK_MODE
-#endif
-#define RGENGC_CHECK_MODE 0
-#define RGENGC_PROFILE 0
-#define RGENGC_ESTIMATE_OLDMALLOC 0
-#define RGENGC_FORCE_MAJOR_GC 0
-
-#endif /* USE_RGENGC */
-
#ifndef GC_PROFILE_MORE_DETAIL
#define GC_PROFILE_MORE_DETAIL 0
#endif
@@ -512,6 +491,7 @@ typedef enum {
GPR_FLAG_HAVE_FINALIZE = 0x4000,
GPR_FLAG_IMMEDIATE_MARK = 0x8000,
GPR_FLAG_FULL_MARK = 0x10000,
+ GPR_FLAG_COMPACT = 0x20000,
GPR_DEFAULT_REASON =
(GPR_FLAG_FULL_MARK | GPR_FLAG_IMMEDIATE_MARK |
@@ -527,6 +507,7 @@ typedef struct gc_profile_record {
size_t heap_total_objects;
size_t heap_use_size;
size_t heap_total_size;
+ size_t moved_objects;
#if GC_PROFILE_MORE_DETAIL
double gc_mark_time;
@@ -559,6 +540,16 @@ typedef struct gc_profile_record {
#endif
} gc_profile_record;
+#define FL_FROM_FREELIST FL_USER0
+
+struct RMoved {
+ VALUE flags;
+ VALUE dummy;
+ VALUE destination;
+};
+
+#define RMOVED(obj) ((struct RMoved *)(obj))
+
#if defined(_MSC_VER) || defined(__CYGWIN__)
#pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
#endif
@@ -654,12 +645,11 @@ typedef struct mark_stack {
} mark_stack_t;
typedef struct rb_heap_struct {
- RVALUE *freelist;
-
struct heap_page *free_pages;
- struct heap_page *using_page;
struct list_head pages;
struct heap_page *sweeping_page; /* iterator for .pages */
+ struct heap_page *compact_cursor;
+ size_t compact_cursor_index;
#if GC_ENABLE_INCREMENTAL_MARK
struct heap_page *pooled_pages;
#endif
@@ -692,9 +682,7 @@ typedef struct rb_objspace {
unsigned int during_compacting : 1;
unsigned int gc_stressful: 1;
unsigned int has_hook: 1;
-#if USE_RGENGC
unsigned int during_minor_gc : 1;
-#endif
#if GC_ENABLE_INCREMENTAL_MARK
unsigned int during_incremental_marking : 1;
#endif
@@ -711,11 +699,6 @@ typedef struct rb_objspace {
rb_atomic_t finalizing;
} atomic_flags;
- struct mark_func_data_struct {
- void *data;
- void (*mark_func)(VALUE v, void *data);
- } *mark_func_data;
-
mark_stack_t mark_stack;
size_t marked_slots;
@@ -747,10 +730,10 @@ typedef struct rb_objspace {
#endif
double invoke_time;
-#if USE_RGENGC
size_t minor_gc_count;
size_t major_gc_count;
size_t compact_count;
+ size_t read_barrier_faults;
#if RGENGC_PROFILE > 0
size_t total_generated_normal_object_count;
size_t total_generated_shady_object_count;
@@ -768,7 +751,6 @@ typedef struct rb_objspace {
size_t remembered_shady_object_count_types[RUBY_T_MASK];
#endif
#endif /* RGENGC_PROFILE */
-#endif /* USE_RGENGC */
/* temporary profiling space */
double gc_sweep_start_time;
@@ -785,7 +767,6 @@ typedef struct rb_objspace {
VALUE gc_stress_mode;
-#if USE_RGENGC
struct {
VALUE parent_object;
int need_major_gc;
@@ -809,6 +790,7 @@ typedef struct rb_objspace {
struct {
size_t considered_count_table[T_MASK];
size_t moved_count_table[T_MASK];
+ size_t total_moved;
} rcompactor;
#if GC_ENABLE_INCREMENTAL_MARK
@@ -817,7 +799,6 @@ typedef struct rb_objspace {
size_t step_slots;
} rincgc;
#endif
-#endif /* USE_RGENGC */
st_table *id_to_obj_tbl;
st_table *obj_to_id_tbl;
@@ -834,12 +815,11 @@ typedef struct rb_objspace {
enum {
HEAP_PAGE_ALIGN = (1UL << HEAP_PAGE_ALIGN_LOG),
HEAP_PAGE_ALIGN_MASK = (~(~0UL << HEAP_PAGE_ALIGN_LOG)),
- REQUIRED_SIZE_BY_MALLOC = (sizeof(size_t) * 5),
- HEAP_PAGE_SIZE = (HEAP_PAGE_ALIGN - REQUIRED_SIZE_BY_MALLOC),
+ HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN,
HEAP_PAGE_OBJ_LIMIT = (unsigned int)((HEAP_PAGE_SIZE - sizeof(struct heap_page_header))/sizeof(struct RVALUE)),
HEAP_PAGE_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_PAGE_SIZE, sizeof(struct RVALUE)), BITS_BITLENGTH),
HEAP_PAGE_BITMAP_SIZE = (BITS_SIZE * HEAP_PAGE_BITMAP_LIMIT),
- HEAP_PAGE_BITMAP_PLANES = USE_RGENGC ? 4 : 1 /* RGENGC: mark, unprotected, uncollectible, marking */
+ HEAP_PAGE_BITMAP_PLANES = 4 /* RGENGC: mark, unprotected, uncollectible, marking */
};
struct heap_page {
@@ -859,15 +839,11 @@ struct heap_page {
RVALUE *freelist;
struct list_node page_node;
-#if USE_RGENGC
bits_t wb_unprotected_bits[HEAP_PAGE_BITMAP_LIMIT];
-#endif
/* the following three bitmaps are cleared at the beginning of full GC */
bits_t mark_bits[HEAP_PAGE_BITMAP_LIMIT];
-#if USE_RGENGC
bits_t uncollectible_bits[HEAP_PAGE_BITMAP_LIMIT];
bits_t marking_bits[HEAP_PAGE_BITMAP_LIMIT];
-#endif
/* If set, the object is not movable */
bits_t pinned_bits[HEAP_PAGE_BITMAP_LIMIT];
@@ -890,11 +866,9 @@ struct heap_page {
/* getting bitmap */
#define GET_HEAP_MARK_BITS(x) (&GET_HEAP_PAGE(x)->mark_bits[0])
#define GET_HEAP_PINNED_BITS(x) (&GET_HEAP_PAGE(x)->pinned_bits[0])
-#if USE_RGENGC
#define GET_HEAP_UNCOLLECTIBLE_BITS(x) (&GET_HEAP_PAGE(x)->uncollectible_bits[0])
#define GET_HEAP_WB_UNPROTECTED_BITS(x) (&GET_HEAP_PAGE(x)->wb_unprotected_bits[0])
#define GET_HEAP_MARKING_BITS(x) (&GET_HEAP_PAGE(x)->marking_bits[0])
-#endif
/* Aliases */
#define rb_objspace (*rb_objspace_of(GET_VM()))
@@ -918,7 +892,6 @@ VALUE *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress;
#define heap_pages_deferred_final objspace->heap_pages.deferred_final
#define heap_eden (&objspace->eden_heap)
#define heap_tomb (&objspace->tomb_heap)
-#define dont_gc objspace->flags.dont_gc
#define during_gc objspace->flags.during_gc
#define finalizing objspace->atomic_flags.finalizing
#define finalizer_table objspace->finalizer_table
@@ -931,6 +904,18 @@ VALUE *ruby_initial_gc_stress_ptr = &ruby_initial_gc_stress;
#define stress_to_class 0
#endif
+#if 0
+#define dont_gc_on() (fprintf(stderr, "dont_gc_on@%s:%d\n", __FILE__, __LINE__), objspace->flags.dont_gc = 1)
+#define dont_gc_off() (fprintf(stderr, "dont_gc_off@%s:%d\n", __FILE__, __LINE__), objspace->flags.dont_gc = 0)
+#define dont_gc_set(b) (fprintf(stderr, "dont_gc_set(%d)@%s:%d\n", __FILE__, __LINE__), (int)b), objspace->flags.dont_gc = (b))
+#define dont_gc_val() (objspace->flags.dont_gc)
+#else
+#define dont_gc_on() (objspace->flags.dont_gc = 1)
+#define dont_gc_off() (objspace->flags.dont_gc = 0)
+#define dont_gc_set(b) (((int)b), objspace->flags.dont_gc = (b))
+#define dont_gc_val() (objspace->flags.dont_gc)
+#endif
+
static inline enum gc_mode
gc_mode_verify(enum gc_mode mode)
{
@@ -952,11 +937,7 @@ gc_mode_verify(enum gc_mode mode)
#define is_marking(objspace) (gc_mode(objspace) == gc_mode_marking)
#define is_sweeping(objspace) (gc_mode(objspace) == gc_mode_sweeping)
-#if USE_RGENGC
#define is_full_marking(objspace) ((objspace)->flags.during_minor_gc == FALSE)
-#else
-#define is_full_marking(objspace) TRUE
-#endif
#if GC_ENABLE_INCREMENTAL_MARK
#define is_incremental_marking(objspace) ((objspace)->flags.during_incremental_marking != FALSE)
#else
@@ -999,6 +980,7 @@ int ruby_gc_debug_indent = 0;
#endif
VALUE rb_mGC;
int ruby_disable_gc = 0;
+int ruby_enable_autocompact = 0;
void rb_iseq_mark(const rb_iseq_t *iseq);
void rb_iseq_update_references(rb_iseq_t *iseq);
@@ -1010,6 +992,8 @@ void rb_gcdebug_print_obj_condition(VALUE obj);
static VALUE define_final0(VALUE obj, VALUE block);
+NORETURN(static void *gc_vraise(void *ptr));
+NORETURN(static void gc_raise(VALUE exc, const char *fmt, ...));
NORETURN(static void negative_size_allocation_error(const char *));
static void init_mark_stack(mark_stack_t *stack);
@@ -1020,14 +1004,24 @@ static int garbage_collect(rb_objspace_t *, int reason);
static int gc_start(rb_objspace_t *objspace, int reason);
static void gc_rest(rb_objspace_t *objspace);
-static inline void gc_enter(rb_objspace_t *objspace, const char *event);
-static inline void gc_exit(rb_objspace_t *objspace, const char *event);
+
+enum gc_enter_event {
+ gc_enter_event_start,
+ gc_enter_event_mark_continue,
+ gc_enter_event_sweep_continue,
+ gc_enter_event_rest,
+ gc_enter_event_finalizer,
+ gc_enter_event_rb_memerror,
+};
+
+static inline void gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev);
+static inline void gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev);
static void gc_marks(rb_objspace_t *objspace, int full_mark);
static void gc_marks_start(rb_objspace_t *objspace, int full);
static int gc_marks_finish(rb_objspace_t *objspace);
static void gc_marks_rest(rb_objspace_t *objspace);
-static void gc_marks_step(rb_objspace_t *objspace, int slots);
+static void gc_marks_step(rb_objspace_t *objspace, size_t slots);
static void gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap);
static void gc_sweep(rb_objspace_t *objspace);
@@ -1094,12 +1088,7 @@ static inline void gc_prof_set_heap_info(rb_objspace_t *);
#endif
PRINTF_ARGS(static void gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...), 3, 4);
static const char *obj_info(VALUE obj);
-
-#define PUSH_MARK_FUNC_DATA(v) do { \
- struct mark_func_data_struct *prev_mark_func_data = objspace->mark_func_data; \
- objspace->mark_func_data = (v);
-
-#define POP_MARK_FUNC_DATA() objspace->mark_func_data = prev_mark_func_data;} while (0)
+static const char *obj_type_name(VALUE obj);
/*
* 1 - TSC (H/W Time Stamp Counter)
@@ -1213,6 +1202,14 @@ tick(void)
#define MEASURE_LINE(expr) expr
#endif /* USE_TICK_T */
+static inline void *
+asan_unpoison_object_temporary(VALUE obj)
+{
+ void *ptr = asan_poisoned_object_p(obj);
+ asan_unpoison_object(obj, false);
+ return ptr;
+}
+
#define FL_CHECK2(name, x, pred) \
((RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) ? \
(rb_bug(name": SPECIAL_CONST (%p)", (void *)(x)), 0) : (pred))
@@ -1224,7 +1221,6 @@ tick(void)
#define RVALUE_PIN_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), (obj))
#define RVALUE_PAGE_MARKED(page, obj) MARKED_IN_BITMAP((page)->mark_bits, (obj))
-#if USE_RGENGC
#define RVALUE_WB_UNPROTECTED_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), (obj))
#define RVALUE_UNCOLLECTIBLE_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(obj), (obj))
#define RVALUE_MARKING_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), (obj))
@@ -1248,103 +1244,105 @@ RVALUE_FLAGS_AGE(VALUE flags)
return (int)((flags & (FL_PROMOTED0 | FL_PROMOTED1)) >> RVALUE_AGE_SHIFT);
}
-#endif /* USE_RGENGC */
-
static int
check_rvalue_consistency_force(const VALUE obj, int terminate)
{
- rb_objspace_t *objspace = &rb_objspace;
int err = 0;
+ rb_objspace_t *objspace = &rb_objspace;
- if (SPECIAL_CONST_P(obj)) {
- fprintf(stderr, "check_rvalue_consistency: %p is a special const.\n", (void *)obj);
- err++;
- }
- else if (!is_pointer_to_heap(objspace, (void *)obj)) {
- /* check if it is in tomb_pages */
- struct heap_page *page = NULL;
- list_for_each(&heap_tomb->pages, page, page_node) {
- if (&page->start[0] <= (RVALUE *)obj &&
- (RVALUE *)obj < &page->start[page->total_slots]) {
- fprintf(stderr, "check_rvalue_consistency: %p is in a tomb_heap (%p).\n",
- (void *)obj, (void *)page);
- err++;
- goto skip;
- }
- }
- fprintf(stderr, "check_rvalue_consistency: %p is not a Ruby object.\n", (void *)obj);
- err++;
- skip:
- ;
- }
- else {
- const int wb_unprotected_bit = RVALUE_WB_UNPROTECTED_BITMAP(obj) != 0;
- const int uncollectible_bit = RVALUE_UNCOLLECTIBLE_BITMAP(obj) != 0;
- const int mark_bit = RVALUE_MARK_BITMAP(obj) != 0;
- const int marking_bit = RVALUE_MARKING_BITMAP(obj) != 0, remembered_bit = marking_bit;
- const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags);
-
- if (GET_HEAP_PAGE(obj)->flags.in_tomb) {
- fprintf(stderr, "check_rvalue_consistency: %s is in tomb page.\n", obj_info(obj));
- err++;
- }
- if (BUILTIN_TYPE(obj) == T_NONE) {
- fprintf(stderr, "check_rvalue_consistency: %s is T_NONE.\n", obj_info(obj));
- err++;
- }
- if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
- fprintf(stderr, "check_rvalue_consistency: %s is T_ZOMBIE.\n", obj_info(obj));
+ RB_VM_LOCK_ENTER_NO_BARRIER();
+ {
+ if (SPECIAL_CONST_P(obj)) {
+ fprintf(stderr, "check_rvalue_consistency: %p is a special const.\n", (void *)obj);
err++;
}
-
- obj_memsize_of((VALUE)obj, FALSE);
-
- /* check generation
- *
- * OLD == age == 3 && old-bitmap && mark-bit (except incremental marking)
- */
- if (age > 0 && wb_unprotected_bit) {
- fprintf(stderr, "check_rvalue_consistency: %s is not WB protected, but age is %d > 0.\n", obj_info(obj), age);
+ else if (!is_pointer_to_heap(objspace, (void *)obj)) {
+ /* check if it is in tomb_pages */
+ struct heap_page *page = NULL;
+ list_for_each(&heap_tomb->pages, page, page_node) {
+ if (&page->start[0] <= (RVALUE *)obj &&
+ (RVALUE *)obj < &page->start[page->total_slots]) {
+ fprintf(stderr, "check_rvalue_consistency: %p is in a tomb_heap (%p).\n",
+ (void *)obj, (void *)page);
+ err++;
+ goto skip;
+ }
+ }
+ bp();
+ fprintf(stderr, "check_rvalue_consistency: %p is not a Ruby object.\n", (void *)obj);
err++;
+ skip:
+ ;
}
+ else {
+ const int wb_unprotected_bit = RVALUE_WB_UNPROTECTED_BITMAP(obj) != 0;
+ const int uncollectible_bit = RVALUE_UNCOLLECTIBLE_BITMAP(obj) != 0;
+ const int mark_bit = RVALUE_MARK_BITMAP(obj) != 0;
+ const int marking_bit = RVALUE_MARKING_BITMAP(obj) != 0, remembered_bit = marking_bit;
+ const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags);
+
+ if (GET_HEAP_PAGE(obj)->flags.in_tomb) {
+ fprintf(stderr, "check_rvalue_consistency: %s is in tomb page.\n", obj_info(obj));
+ err++;
+ }
+ if (BUILTIN_TYPE(obj) == T_NONE) {
+ fprintf(stderr, "check_rvalue_consistency: %s is T_NONE.\n", obj_info(obj));
+ err++;
+ }
+ if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
+ fprintf(stderr, "check_rvalue_consistency: %s is T_ZOMBIE.\n", obj_info(obj));
+ err++;
+ }
- if (!is_marking(objspace) && uncollectible_bit && !mark_bit) {
- fprintf(stderr, "check_rvalue_consistency: %s is uncollectible, but is not marked while !gc.\n", obj_info(obj));
- err++;
- }
+ obj_memsize_of((VALUE)obj, FALSE);
- if (!is_full_marking(objspace)) {
- if (uncollectible_bit && age != RVALUE_OLD_AGE && !wb_unprotected_bit) {
- fprintf(stderr, "check_rvalue_consistency: %s is uncollectible, but not old (age: %d) and not WB unprotected.\n",
- obj_info(obj), age);
+ /* check generation
+ *
+ * OLD == age == 3 && old-bitmap && mark-bit (except incremental marking)
+ */
+ if (age > 0 && wb_unprotected_bit) {
+ fprintf(stderr, "check_rvalue_consistency: %s is not WB protected, but age is %d > 0.\n", obj_info(obj), age);
err++;
}
- if (remembered_bit && age != RVALUE_OLD_AGE) {
- fprintf(stderr, "check_rvalue_consistency: %s is remembered, but not old (age: %d).\n",
- obj_info(obj), age);
+
+ if (!is_marking(objspace) && uncollectible_bit && !mark_bit) {
+ fprintf(stderr, "check_rvalue_consistency: %s is uncollectible, but is not marked while !gc.\n", obj_info(obj));
err++;
}
- }
- /*
- * check coloring
- *
- * marking:false marking:true
- * marked:false white *invalid*
- * marked:true black grey
- */
- if (is_incremental_marking(objspace) && marking_bit) {
- if (!is_marking(objspace) && !mark_bit) {
- fprintf(stderr, "check_rvalue_consistency: %s is marking, but not marked.\n", obj_info(obj));
- err++;
+ if (!is_full_marking(objspace)) {
+ if (uncollectible_bit && age != RVALUE_OLD_AGE && !wb_unprotected_bit) {
+ fprintf(stderr, "check_rvalue_consistency: %s is uncollectible, but not old (age: %d) and not WB unprotected.\n",
+ obj_info(obj), age);
+ err++;
+ }
+ if (remembered_bit && age != RVALUE_OLD_AGE) {
+ fprintf(stderr, "check_rvalue_consistency: %s is remembered, but not old (age: %d).\n",
+ obj_info(obj), age);
+ err++;
+ }
+ }
+
+ /*
+ * check coloring
+ *
+ * marking:false marking:true
+ * marked:false white *invalid*
+ * marked:true black grey
+ */
+ if (is_incremental_marking(objspace) && marking_bit) {
+ if (!is_marking(objspace) && !mark_bit) {
+ fprintf(stderr, "check_rvalue_consistency: %s is marking, but not marked.\n", obj_info(obj));
+ err++;
+ }
}
}
}
+ RB_VM_LOCK_LEAVE_NO_BARRIER();
if (err > 0 && terminate) {
rb_bug("check_rvalue_consistency_force: there is %d errors.", err);
}
-
return err;
}
@@ -1397,7 +1395,6 @@ RVALUE_PINNED(VALUE obj)
return RVALUE_PIN_BITMAP(obj) != 0;
}
-#if USE_RGENGC
static inline int
RVALUE_WB_UNPROTECTED(VALUE obj)
{
@@ -1584,8 +1581,6 @@ RVALUE_WHITE_P(VALUE obj)
return RVALUE_MARKED(obj) == FALSE;
}
-#endif /* USE_RGENGC */
-
/*
--------------------------- ObjectSpace -----------------------------
*/
@@ -1603,7 +1598,7 @@ rb_objspace_alloc(void)
malloc_limit = gc_params.malloc_limit_min;
list_head_init(&objspace->eden_heap.pages);
list_head_init(&objspace->tomb_heap.pages);
- dont_gc = TRUE;
+ dont_gc_on();
return objspace;
}
@@ -1655,7 +1650,8 @@ heap_pages_expand_sorted_to(rb_objspace_t *objspace, size_t next_length)
struct heap_page **sorted;
size_t size = size_mul_or_raise(next_length, sizeof(struct heap_page *), rb_eRuntimeError);
- gc_report(3, objspace, "heap_pages_expand_sorted: next_length: %d, size: %d\n", (int)next_length, (int)size);
+ gc_report(3, objspace, "heap_pages_expand_sorted: next_length: %"PRIdSIZE", size: %"PRIdSIZE"\n",
+ next_length, size);
if (heap_pages_sorted_length > 0) {
sorted = (struct heap_page **)realloc(heap_pages_sorted, size);
@@ -1699,11 +1695,13 @@ heap_allocatable_pages_set(rb_objspace_t *objspace, size_t 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_memory_region(&page->freelist, sizeof(RVALUE*), false);
p->as.free.flags = 0;
@@ -1720,7 +1718,6 @@ heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj
}
asan_poison_object(obj);
-
gc_report(3, objspace, "heap_page_add_freeobj: add %p to freelist\n", (void *)obj);
}
@@ -1729,31 +1726,29 @@ heap_add_freepage(rb_heap_t *heap, struct heap_page *page)
{
asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
GC_ASSERT(page->free_slots != 0);
- if (page->freelist) {
- page->free_next = heap->free_pages;
- heap->free_pages = page;
- }
+ GC_ASSERT(page->freelist != NULL);
+
+ page->free_next = heap->free_pages;
+ heap->free_pages = page;
+
+ RUBY_DEBUG_LOG("page:%p freelist:%p", page, page->freelist);
+
asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
}
#if GC_ENABLE_INCREMENTAL_MARK
-static inline int
+static inline void
heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
{
asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
- if (page->freelist) {
- page->free_next = heap->pooled_pages;
- heap->pooled_pages = page;
- objspace->rincgc.pooled_slots += page->free_slots;
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+ GC_ASSERT(page->free_slots != 0);
+ GC_ASSERT(page->freelist != NULL);
- return TRUE;
- }
- else {
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+ page->free_next = heap->pooled_pages;
+ heap->pooled_pages = page;
+ objspace->rincgc.pooled_slots += page->free_slots;
- return FALSE;
- }
+ asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
}
#endif
@@ -1796,6 +1791,12 @@ heap_pages_free_unused_pages(rb_objspace_t *objspace)
j++;
}
}
+
+ struct heap_page *hipage = heap_pages_sorted[heap_allocated_pages - 1];
+ RVALUE *himem = hipage->start + hipage->total_slots;
+ GC_ASSERT(himem <= heap_pages_himem);
+ heap_pages_himem = himem;
+
GC_ASSERT(j == heap_allocated_pages);
}
}
@@ -1917,16 +1918,21 @@ heap_page_create(rb_objspace_t *objspace)
page = heap_page_allocate(objspace);
method = "allocate";
}
- if (0) fprintf(stderr, "heap_page_create: %s - %p, heap_allocated_pages: %d, heap_allocated_pages: %d, tomb->total_pages: %d\n",
- method, (void *)page, (int)heap_pages_sorted_length, (int)heap_allocated_pages, (int)heap_tomb->total_pages);
+ if (0) fprintf(stderr, "heap_page_create: %s - %p, "
+ "heap_allocated_pages: %"PRIdSIZE", "
+ "heap_allocated_pages: %"PRIdSIZE", "
+ "tomb->total_pages: %"PRIdSIZE"\n",
+ method, (void *)page, heap_pages_sorted_length, heap_allocated_pages, heap_tomb->total_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 == heap_eden && heap->sweeping_page));
page->flags.in_tomb = (heap == heap_tomb);
- list_add(&heap->pages, &page->page_node);
+ list_add_tail(&heap->pages, &page->page_node);
heap->total_pages++;
heap->total_slots += page->total_slots;
}
@@ -2002,15 +2008,17 @@ heap_set_increment(rb_objspace_t *objspace, size_t additional_pages)
heap_allocatable_pages_set(objspace, next_used_limit - used);
- gc_report(1, objspace, "heap_set_increment: heap_allocatable_pages is %d\n", (int)heap_allocatable_pages);
+ gc_report(1, objspace, "heap_set_increment: heap_allocatable_pages is %"PRIdSIZE"\n",
+ heap_allocatable_pages);
}
static int
heap_increment(rb_objspace_t *objspace, rb_heap_t *heap)
{
if (heap_allocatable_pages > 0) {
- gc_report(1, objspace, "heap_increment: heap_pages_sorted_length: %d, heap_pages_inc: %d, heap->total_pages: %d\n",
- (int)heap_pages_sorted_length, (int)heap_allocatable_pages, (int)heap->total_pages);
+ gc_report(1, objspace, "heap_increment: heap_pages_sorted_length: %"PRIdSIZE", "
+ "heap_pages_inc: %"PRIdSIZE", heap->total_pages: %"PRIdSIZE"\n",
+ heap_pages_sorted_length, heap_allocatable_pages, heap->total_pages);
GC_ASSERT(heap_allocatable_pages + heap_eden->total_pages <= heap_pages_sorted_length);
GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length);
@@ -2040,57 +2048,6 @@ heap_prepare(rb_objspace_t *objspace, rb_heap_t *heap)
}
}
-static RVALUE *
-heap_get_freeobj_from_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap)
-{
- struct heap_page *page;
- RVALUE *p;
-
- while (heap->free_pages == NULL) {
- heap_prepare(objspace, heap);
- }
- page = heap->free_pages;
- heap->free_pages = page->free_next;
- heap->using_page = page;
-
- GC_ASSERT(page->free_slots != 0);
- asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
- p = page->freelist;
- page->freelist = NULL;
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
- page->free_slots = 0;
- asan_unpoison_object((VALUE)p, true);
- return p;
-}
-
-static inline VALUE
-heap_get_freeobj_head(rb_objspace_t *objspace, rb_heap_t *heap)
-{
- RVALUE *p = heap->freelist;
- if (LIKELY(p != NULL)) {
- heap->freelist = p->as.free.next;
- }
- asan_unpoison_object((VALUE)p, true);
- return (VALUE)p;
-}
-
-static inline VALUE
-heap_get_freeobj(rb_objspace_t *objspace, rb_heap_t *heap)
-{
- RVALUE *p = heap->freelist;
-
- while (1) {
- if (LIKELY(p != NULL)) {
- asan_unpoison_object((VALUE)p, true);
- heap->freelist = p->as.free.next;
- return (VALUE)p;
- }
- else {
- p = heap_get_freeobj_from_next_freepage(objspace, heap);
- }
- }
-}
-
void
rb_objspace_set_event_hook(const rb_event_flag_t event)
{
@@ -2114,68 +2071,72 @@ gc_event_hook_body(rb_execution_context_t *ec, rb_objspace_t *objspace, const rb
#define gc_event_hook_available_p(objspace) ((objspace)->flags.has_hook)
#define gc_event_hook_needed_p(objspace, event) ((objspace)->hook_events & (event))
-#define gc_event_hook(objspace, event, data) do { \
+#define gc_event_hook_prep(objspace, event, data, prep) do { \
if (UNLIKELY(gc_event_hook_needed_p(objspace, event))) { \
+ prep; \
gc_event_hook_body(GET_EC(), (objspace), (event), (data)); \
} \
} while (0)
+#define gc_event_hook(objspace, event, data) gc_event_hook_prep(objspace, event, data, (void)0)
+
static inline VALUE
-newobj_init(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected, rb_objspace_t *objspace, VALUE obj)
+newobj_init(VALUE klass, VALUE flags, int wb_protected, rb_objspace_t *objspace, VALUE obj)
{
#if !__has_feature(memory_sanitizer)
GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
GC_ASSERT((flags & FL_WB_PROTECTED) == 0);
#endif
+ RVALUE *p = RANY(obj);
+ p->as.basic.flags = flags;
+ *((VALUE *)&p->as.basic.klass) = klass;
- /* OBJSETUP */
- struct RVALUE buf = {
- .as = {
- .values = {
- .basic = {
- .flags = flags,
- .klass = klass,
- },
- .v1 = v1,
- .v2 = v2,
- .v3 = v3,
- },
- },
- };
- MEMCPY(RANY(obj), &buf, RVALUE, 1);
+#if RACTOR_CHECK_MODE
+ rb_ractor_setup_belonging(obj);
+#endif
#if RGENGC_CHECK_MODE
- GC_ASSERT(RVALUE_MARKED(obj) == FALSE);
- GC_ASSERT(RVALUE_MARKING(obj) == FALSE);
- GC_ASSERT(RVALUE_OLD_P(obj) == FALSE);
- GC_ASSERT(RVALUE_WB_UNPROTECTED(obj) == FALSE);
+ p->as.values.v1 = p->as.values.v2 = p->as.values.v3 = 0;
- if (flags & FL_PROMOTED1) {
- if (RVALUE_AGE(obj) != 2) rb_bug("newobj: %s of age (%d) != 2.", obj_info(obj), RVALUE_AGE(obj));
- }
- else {
- if (RVALUE_AGE(obj) > 0) rb_bug("newobj: %s of age (%d) > 0.", obj_info(obj), RVALUE_AGE(obj));
+ RB_VM_LOCK_ENTER_NO_BARRIER();
+ {
+ check_rvalue_consistency(obj);
+
+ GC_ASSERT(RVALUE_MARKED(obj) == FALSE);
+ GC_ASSERT(RVALUE_MARKING(obj) == FALSE);
+ GC_ASSERT(RVALUE_OLD_P(obj) == FALSE);
+ GC_ASSERT(RVALUE_WB_UNPROTECTED(obj) == FALSE);
+
+ if (flags & FL_PROMOTED1) {
+ if (RVALUE_AGE(obj) != 2) rb_bug("newobj: %s of age (%d) != 2.", obj_info(obj), RVALUE_AGE(obj));
+ }
+ else {
+ if (RVALUE_AGE(obj) > 0) rb_bug("newobj: %s of age (%d) > 0.", obj_info(obj), RVALUE_AGE(obj));
+ }
+ if (rgengc_remembered(objspace, (VALUE)obj)) rb_bug("newobj: %s is remembered.", obj_info(obj));
}
- if (rgengc_remembered(objspace, (VALUE)obj)) rb_bug("newobj: %s is remembered.", obj_info(obj));
+ RB_VM_LOCK_LEAVE_NO_BARRIER();
#endif
-#if USE_RGENGC
if (UNLIKELY(wb_protected == FALSE)) {
- MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
+ ASSERT_vm_locking();
+ MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
}
-#endif
+
+ // TODO: make it atomic, or ractor local
+ objspace->total_allocated_objects++;
#if RGENGC_PROFILE
if (wb_protected) {
- objspace->profile.total_generated_normal_object_count++;
+ objspace->profile.total_generated_normal_object_count++;
#if RGENGC_PROFILE >= 2
- objspace->profile.generated_normal_object_count_types[BUILTIN_TYPE(obj)]++;
+ objspace->profile.generated_normal_object_count_types[BUILTIN_TYPE(obj)]++;
#endif
}
else {
- objspace->profile.total_generated_shady_object_count++;
+ objspace->profile.total_generated_shady_object_count++;
#if RGENGC_PROFILE >= 2
- objspace->profile.generated_shady_object_count_types[BUILTIN_TYPE(obj)]++;
+ objspace->profile.generated_shady_object_count_types[BUILTIN_TYPE(obj)]++;
#endif
}
#endif
@@ -2185,77 +2146,152 @@ newobj_init(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_prote
GC_ASSERT(!SPECIAL_CONST_P(obj)); /* check alignment */
#endif
- objspace->total_allocated_objects++;
-
gc_report(5, objspace, "newobj: %s\n", obj_info(obj));
#if RGENGC_OLD_NEWOBJ_CHECK > 0
{
- static int newobj_cnt = RGENGC_OLD_NEWOBJ_CHECK;
+ static int newobj_cnt = RGENGC_OLD_NEWOBJ_CHECK;
- if (!is_incremental_marking(objspace) &&
- flags & FL_WB_PROTECTED && /* do not promote WB unprotected objects */
- ! RB_TYPE_P(obj, T_ARRAY)) { /* array.c assumes that allocated objects are new */
- if (--newobj_cnt == 0) {
- newobj_cnt = RGENGC_OLD_NEWOBJ_CHECK;
+ if (!is_incremental_marking(objspace) &&
+ flags & FL_WB_PROTECTED && /* do not promote WB unprotected objects */
+ ! RB_TYPE_P(obj, T_ARRAY)) { /* array.c assumes that allocated objects are new */
+ if (--newobj_cnt == 0) {
+ newobj_cnt = RGENGC_OLD_NEWOBJ_CHECK;
- gc_mark_set(objspace, obj);
- RVALUE_AGE_SET_OLD(objspace, obj);
+ gc_mark_set(objspace, obj);
+ RVALUE_AGE_SET_OLD(objspace, obj);
- rb_gc_writebarrier_remember(obj);
- }
- }
+ rb_gc_writebarrier_remember(obj);
+ }
+ }
}
#endif
- check_rvalue_consistency(obj);
+ // RUBY_DEBUG_LOG("obj:%p (%s)", (void *)obj, obj_type_name(obj));
+ return obj;
+}
+
+static inline VALUE
+ractor_cached_freeobj(rb_objspace_t *objspace, rb_ractor_t *cr)
+{
+ RVALUE *p = cr->newobj_cache.freelist;
+
+ if (p) {
+ VALUE obj = (VALUE)p;
+ cr->newobj_cache.freelist = p->as.free.next;
+ asan_unpoison_object(obj, true);
+ return obj;
+ }
+ else {
+ return Qfalse;
+ }
+}
+
+static struct heap_page *
+heap_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ ASSERT_vm_locking();
+
+ struct heap_page *page;
+
+ while (heap->free_pages == NULL) {
+ heap_prepare(objspace, 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", page, page->freelist, page->free_slots);
+
+ asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+
+ return page;
+}
+
+static inline void
+ractor_cache_slots(rb_objspace_t *objspace, rb_ractor_t *cr)
+{
+ ASSERT_vm_locking();
+ GC_ASSERT(cr->newobj_cache.freelist == NULL);
+
+ struct heap_page *page = heap_next_freepage(objspace, heap_eden);
+
+ cr->newobj_cache.using_page = page;
+ cr->newobj_cache.freelist = page->freelist;
+ page->free_slots = 0;
+ page->freelist = NULL;
+
+ GC_ASSERT(RB_TYPE_P((VALUE)cr->newobj_cache.freelist, T_NONE));
+}
+
+static inline VALUE
+newobj_fill(VALUE obj, VALUE v1, VALUE v2, VALUE v3)
+{
+ RVALUE *p = (RVALUE *)obj;
+ p->as.values.v1 = v1;
+ p->as.values.v2 = v2;
+ p->as.values.v3 = v3;
return obj;
}
+ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected));
+
static inline VALUE
-newobj_slowpath(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace, int wb_protected)
+newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr, int wb_protected)
{
VALUE obj;
+ unsigned int lev;
- if (UNLIKELY(during_gc || ruby_gc_stressful)) {
- if (during_gc) {
- dont_gc = 1;
- during_gc = 0;
- rb_bug("object allocation during garbage collection phase");
- }
+ RB_VM_LOCK_ENTER_CR_LEV(cr, &lev);
+ {
+ if (UNLIKELY(during_gc || ruby_gc_stressful)) {
+ if (during_gc) {
+ dont_gc_on();
+ during_gc = 0;
+ rb_bug("object allocation during garbage collection phase");
+ }
- if (ruby_gc_stressful) {
- if (!garbage_collect(objspace, GPR_FLAG_NEWOBJ)) {
- rb_memerror();
- }
- }
+ if (ruby_gc_stressful) {
+ if (!garbage_collect(objspace, GPR_FLAG_NEWOBJ)) {
+ rb_memerror();
+ }
+ }
+ }
+
+ // allocate new slot
+ while ((obj = ractor_cached_freeobj(objspace, cr)) == Qfalse) {
+ ractor_cache_slots(objspace, cr);
+ }
+ GC_ASSERT(obj != 0);
+ newobj_init(klass, flags, wb_protected, objspace, obj);
+ gc_event_hook_prep(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj, newobj_fill(obj, 0, 0, 0));
}
+ RB_VM_LOCK_LEAVE_CR_LEV(cr, &lev);
- obj = heap_get_freeobj(objspace, heap_eden);
- newobj_init(klass, flags, v1, v2, v3, wb_protected, objspace, obj);
- gc_event_hook(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj);
return obj;
}
-NOINLINE(static VALUE newobj_slowpath_wb_protected(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace));
-NOINLINE(static VALUE newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace));
+NOINLINE(static VALUE newobj_slowpath_wb_protected(VALUE klass, VALUE flags,
+ rb_objspace_t *objspace, rb_ractor_t *cr));
+NOINLINE(static VALUE newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags,
+ rb_objspace_t *objspace, rb_ractor_t *cr));
static VALUE
-newobj_slowpath_wb_protected(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace)
+newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr)
{
- return newobj_slowpath(klass, flags, v1, v2, v3, objspace, TRUE);
+ return newobj_slowpath(klass, flags, objspace, cr, TRUE);
}
static VALUE
-newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, rb_objspace_t *objspace)
+newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_t *cr)
{
- return newobj_slowpath(klass, flags, v1, v2, v3, objspace, FALSE);
+ return newobj_slowpath(klass, flags, objspace, cr, FALSE);
}
static inline VALUE
-newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected)
+newobj_of0(VALUE klass, VALUE flags, int wb_protected, rb_ractor_t *cr)
{
- rb_objspace_t *objspace = &rb_objspace;
VALUE obj;
+ rb_objspace_t *objspace = &rb_objspace;
RB_DEBUG_COUNTER_INC(obj_newobj);
(void)RB_DEBUG_COUNTER_INC_IF(obj_newobj_wb_unprotected, !wb_protected);
@@ -2268,19 +2304,38 @@ newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protect
}
}
#endif
- if (!(during_gc ||
- ruby_gc_stressful ||
- gc_event_hook_available_p(objspace)) &&
- (obj = heap_get_freeobj_head(objspace, heap_eden)) != Qfalse) {
- return newobj_init(klass, flags, v1, v2, v3, wb_protected, objspace, obj);
+
+ if ((!UNLIKELY(during_gc ||
+ ruby_gc_stressful ||
+ gc_event_hook_available_p(objspace)) &&
+ wb_protected &&
+ (obj = ractor_cached_freeobj(objspace, cr)) != Qfalse)) {
+
+ newobj_init(klass, flags, wb_protected, objspace, obj);
}
else {
RB_DEBUG_COUNTER_INC(obj_newobj_slowpath);
- return wb_protected ?
- newobj_slowpath_wb_protected(klass, flags, v1, v2, v3, objspace) :
- newobj_slowpath_wb_unprotected(klass, flags, v1, v2, v3, objspace);
+ obj = wb_protected ?
+ newobj_slowpath_wb_protected(klass, flags, objspace, cr) :
+ newobj_slowpath_wb_unprotected(klass, flags, objspace, cr);
}
+
+ return obj;
+}
+
+static inline VALUE
+newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected)
+{
+ VALUE obj = newobj_of0(klass, flags, wb_protected, GET_RACTOR());
+ return newobj_fill(obj, v1, v2, v3);
+}
+
+static inline VALUE
+newobj_of_cr(rb_ractor_t *cr, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected)
+{
+ VALUE obj = newobj_of0(klass, flags, wb_protected, cr);
+ return newobj_fill(obj, v1, v2, v3);
}
VALUE
@@ -2297,6 +2352,13 @@ rb_wb_protected_newobj_of(VALUE klass, VALUE flags)
return newobj_of(klass, flags, 0, 0, 0, TRUE);
}
+VALUE
+rb_ec_wb_protected_newobj_of(rb_execution_context_t *ec, VALUE klass, VALUE flags)
+{
+ GC_ASSERT((flags & FL_WB_PROTECTED) == 0);
+ return newobj_of_cr(rb_ec_ractor_ptr(ec), klass, flags, 0, 0, 0, TRUE);
+}
+
/* for compatibility */
VALUE
@@ -2308,13 +2370,42 @@ rb_newobj(void)
VALUE
rb_newobj_of(VALUE klass, VALUE flags)
{
- return newobj_of(klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED);
+ if ((flags & RUBY_T_MASK) == T_OBJECT) {
+ return newobj_of(klass, (flags | ROBJECT_EMBED) & ~FL_WB_PROTECTED , Qundef, Qundef, Qundef, flags & FL_WB_PROTECTED);
+ } else {
+ return newobj_of(klass, flags & ~FL_WB_PROTECTED, 0, 0, 0, flags & FL_WB_PROTECTED);
+ }
}
#define UNEXPECTED_NODE(func) \
rb_bug(#func"(): GC does not handle T_NODE 0x%x(%p) 0x%"PRIxVALUE, \
BUILTIN_TYPE(obj), (void*)(obj), RBASIC(obj)->flags)
+const char *
+rb_imemo_name(enum imemo_type type)
+{
+ // put no default case to get a warning if an imemo type is missing
+ switch (type) {
+#define IMEMO_NAME(x) case imemo_##x: return #x;
+ IMEMO_NAME(env);
+ IMEMO_NAME(cref);
+ IMEMO_NAME(svar);
+ IMEMO_NAME(throw_data);
+ IMEMO_NAME(ifunc);
+ IMEMO_NAME(memo);
+ IMEMO_NAME(ment);
+ IMEMO_NAME(iseq);
+ IMEMO_NAME(tmpbuf);
+ IMEMO_NAME(ast);
+ IMEMO_NAME(parser_strterm);
+ IMEMO_NAME(callinfo);
+ IMEMO_NAME(callcache);
+ IMEMO_NAME(constcache);
+#undef IMEMO_NAME
+ }
+ return "unknown";
+}
+
#undef rb_imemo_new
VALUE
@@ -2388,18 +2479,20 @@ rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0,
#endif
VALUE
+rb_class_allocate_instance(VALUE klass)
+{
+ VALUE flags = T_OBJECT | ROBJECT_EMBED;
+ return newobj_of(klass, flags, Qundef, Qundef, Qundef, RGENGC_WB_PROTECTED_OBJECT);
+}
+
+VALUE
rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
{
+ RUBY_ASSERT_ALWAYS(dfree != (RUBY_DATA_FUNC)1);
if (klass) Check_Type(klass, T_CLASS);
return newobj_of(klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap, FALSE);
}
-#undef rb_data_object_alloc
-RUBY_ALIAS_FUNCTION(rb_data_object_alloc(VALUE klass, void *datap,
- RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree),
- rb_data_object_wrap, (klass, datap, dmark, dfree))
-
-
VALUE
rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
{
@@ -2411,15 +2504,11 @@ rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_
VALUE
rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type)
{
+ RUBY_ASSERT_ALWAYS(type);
if (klass) Check_Type(klass, T_CLASS);
return newobj_of(klass, T_DATA, (VALUE)type, (VALUE)1, (VALUE)datap, type->flags & RUBY_FL_WB_PROTECTED);
}
-#undef rb_data_typed_object_alloc
-RUBY_ALIAS_FUNCTION(rb_data_typed_object_alloc(VALUE klass, void *datap,
- const rb_data_type_t *type),
- rb_data_typed_object_wrap, (klass, datap, type))
-
VALUE
rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type)
{
@@ -2509,6 +2598,137 @@ rb_free_const_table(struct rb_id_table *tbl)
rb_id_table_free(tbl);
}
+static int
+free_iv_index_tbl_free_i(st_data_t key, st_data_t value, st_data_t data)
+{
+ xfree((void *)value);
+ return ST_CONTINUE;
+}
+
+static void
+iv_index_tbl_free(struct st_table *tbl)
+{
+ st_foreach(tbl, free_iv_index_tbl_free_i, 0);
+}
+
+// alive: if false, target pointers can be freed already.
+// To check it, we need objspace parameter.
+static void
+vm_ccs_free(struct rb_class_cc_entries *ccs, int alive, rb_objspace_t *objspace, VALUE klass)
+{
+ if (ccs->entries) {
+ for (int i=0; i<ccs->len; i++) {
+ const struct rb_callcache *cc = ccs->entries[i].cc;
+ if (!alive) {
+ void *ptr = asan_poisoned_object_p((VALUE)cc);
+ asan_unpoison_object((VALUE)cc, false);
+ // ccs can be free'ed.
+ if (is_pointer_to_heap(objspace, (void *)cc) &&
+ IMEMO_TYPE_P(cc, imemo_callcache) &&
+ cc->klass == klass) {
+ // OK. maybe target cc.
+ }
+ else {
+ if (ptr) {
+ asan_poison_object((VALUE)cc);
+ }
+ continue;
+ }
+ if (ptr) {
+ asan_poison_object((VALUE)cc);
+ }
+ }
+ vm_cc_invalidate(cc);
+ }
+ ruby_xfree(ccs->entries);
+ }
+ ruby_xfree(ccs);
+}
+
+void
+rb_vm_ccs_free(struct rb_class_cc_entries *ccs)
+{
+ RB_DEBUG_COUNTER_INC(ccs_free);
+ vm_ccs_free(ccs, TRUE, NULL, Qundef);
+}
+
+struct cc_tbl_i_data {
+ rb_objspace_t *objspace;
+ VALUE klass;
+ bool alive;
+};
+
+static enum rb_id_table_iterator_result
+cc_table_mark_i(ID id, VALUE ccs_ptr, void *data_ptr)
+{
+ struct cc_tbl_i_data *data = data_ptr;
+ struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
+ VM_ASSERT(vm_ccs_p(ccs));
+ VM_ASSERT(id == ccs->cme->called_id);
+
+ if (METHOD_ENTRY_INVALIDATED(ccs->cme)) {
+ rb_vm_ccs_free(ccs);
+ return ID_TABLE_DELETE;
+ }
+ else {
+ gc_mark(data->objspace, (VALUE)ccs->cme);
+
+ for (int i=0; i<ccs->len; i++) {
+ VM_ASSERT(data->klass == ccs->entries[i].cc->klass);
+ VM_ASSERT(ccs->cme == vm_cc_cme(ccs->entries[i].cc));
+
+ gc_mark(data->objspace, (VALUE)ccs->entries[i].ci);
+ gc_mark(data->objspace, (VALUE)ccs->entries[i].cc);
+ }
+ return ID_TABLE_CONTINUE;
+ }
+}
+
+static void
+cc_table_mark(rb_objspace_t *objspace, VALUE klass)
+{
+ struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
+ if (cc_tbl) {
+ struct cc_tbl_i_data data = {
+ .objspace = objspace,
+ .klass = klass,
+ };
+ rb_id_table_foreach(cc_tbl, cc_table_mark_i, &data);
+ }
+}
+
+static enum rb_id_table_iterator_result
+cc_table_free_i(VALUE ccs_ptr, void *data_ptr)
+{
+ struct cc_tbl_i_data *data = data_ptr;
+ struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
+ VM_ASSERT(vm_ccs_p(ccs));
+ vm_ccs_free(ccs, data->alive, data->objspace, data->klass);
+ return ID_TABLE_CONTINUE;
+}
+
+static void
+cc_table_free(rb_objspace_t *objspace, VALUE klass, bool alive)
+{
+ struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
+
+ if (cc_tbl) {
+ struct cc_tbl_i_data data = {
+ .objspace = objspace,
+ .klass = klass,
+ .alive = alive,
+ };
+ rb_id_table_foreach_values(cc_tbl, cc_table_free_i, &data);
+ rb_id_table_free(cc_tbl);
+ }
+}
+
+void
+rb_cc_table_free(VALUE klass)
+{
+ cc_table_free(&rb_objspace, klass, TRUE);
+}
+
static inline void
make_zombie(rb_objspace_t *objspace, VALUE obj, void (*dfree)(void *), void *data)
{
@@ -2518,26 +2738,31 @@ make_zombie(rb_objspace_t *objspace, VALUE obj, void (*dfree)(void *), void *dat
zombie->data = data;
zombie->next = heap_pages_deferred_final;
heap_pages_deferred_final = (VALUE)zombie;
+
+ struct heap_page *page = GET_HEAP_PAGE(obj);
+ page->final_slots++;
+ heap_pages_final_slots++;
}
static inline void
make_io_zombie(rb_objspace_t *objspace, VALUE obj)
{
rb_io_t *fptr = RANY(obj)->as.file.fptr;
- make_zombie(objspace, obj, (void (*)(void*))rb_io_fptr_finalize, fptr);
+ make_zombie(objspace, obj, rb_io_fptr_finalize_internal, fptr);
}
static void
obj_free_object_id(rb_objspace_t *objspace, VALUE obj)
{
- VALUE id;
+ ASSERT_vm_locking();
+ st_data_t o = (st_data_t)obj, id;
GC_ASSERT(FL_TEST(obj, FL_SEEN_OBJ_ID));
FL_UNSET(obj, FL_SEEN_OBJ_ID);
- if (st_delete(objspace->obj_to_id_tbl, (st_data_t *)&obj, &id)) {
+ if (st_delete(objspace->obj_to_id_tbl, &o, &id)) {
GC_ASSERT(id);
- st_delete(objspace->id_to_obj_tbl, (st_data_t *)&id, NULL);
+ st_delete(objspace->id_to_obj_tbl, &id, NULL);
}
else {
rb_bug("Object ID seen, but not in mapping table: %s\n", obj_info(obj));
@@ -2548,6 +2773,7 @@ static int
obj_free(rb_objspace_t *objspace, VALUE obj)
{
RB_DEBUG_COUNTER_INC(obj_free);
+ // RUBY_DEBUG_LOG("obj:%p (%s)", (void *)obj, obj_type_name(obj));
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_FREEOBJ, obj);
@@ -2558,6 +2784,8 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case T_FALSE:
rb_bug("obj_free() called for broken object");
break;
+ default:
+ break;
}
if (FL_TEST(obj, FL_EXIVAR)) {
@@ -2569,7 +2797,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
obj_free_object_id(objspace, obj);
}
-#if USE_RGENGC
if (RVALUE_WB_UNPROTECTED(obj)) CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
#if RGENGC_CHECK_MODE
@@ -2580,12 +2807,10 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
CHECK(RVALUE_UNCOLLECTIBLE);
#undef CHECK
#endif
-#endif
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- if ((RANY(obj)->as.basic.flags & ROBJECT_EMBED) ||
- RANY(obj)->as.object.as.heap.ivptr == NULL) {
+ if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) {
RB_DEBUG_COUNTER_INC(obj_obj_embed);
}
else if (ROBJ_TRANSIENT_P(obj)) {
@@ -2600,6 +2825,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case T_CLASS:
mjit_remove_class_serial(RCLASS_SERIAL(obj));
rb_id_table_free(RCLASS_M_TBL(obj));
+ cc_table_free(objspace, obj, FALSE);
if (RCLASS_IV_TBL(obj)) {
st_free_table(RCLASS_IV_TBL(obj));
}
@@ -2607,7 +2833,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
rb_free_const_table(RCLASS_CONST_TBL(obj));
}
if (RCLASS_IV_INDEX_TBL(obj)) {
- st_free_table(RCLASS_IV_INDEX_TBL(obj));
+ iv_index_tbl_free(RCLASS_IV_INDEX_TBL(obj));
}
if (RCLASS_EXT(obj)->subclasses) {
if (BUILTIN_TYPE(obj) == T_MODULE) {
@@ -2635,7 +2861,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
case T_HASH:
#if USE_DEBUG_COUNTER
- switch RHASH_SIZE(obj) {
+ switch (RHASH_SIZE(obj)) {
case 0:
RB_DEBUG_COUNTER_INC(obj_hash_empty);
break;
@@ -2774,9 +3000,10 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
case T_ICLASS:
/* Basically , T_ICLASS shares table with the module */
- if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
- rb_id_table_free(RCLASS_M_TBL(obj));
- }
+ if (RICLASS_OWNS_M_TBL_P(obj)) {
+ /* Method table is not shared for origin iclasses of classes */
+ rb_id_table_free(RCLASS_M_TBL(obj));
+ }
if (RCLASS_CALLABLE_M_TBL(obj) != NULL) {
rb_id_table_free(RCLASS_CALLABLE_M_TBL(obj));
}
@@ -2784,6 +3011,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
rb_class_detach_subclasses(obj);
RCLASS_EXT(obj)->subclasses = NULL;
}
+ cc_table_free(objspace, obj, FALSE);
rb_class_remove_from_module_subclasses(obj);
rb_class_remove_from_super_subclasses(obj);
xfree(RANY(obj)->as.klass.ptr);
@@ -2797,7 +3025,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
case T_BIGNUM:
- if (!(RBASIC(obj)->flags & BIGNUM_EMBED_FLAG) && BIGNUM_DIGITS(obj)) {
+ if (!BIGNUM_EMBED_P(obj) && BIGNUM_DIGITS(obj)) {
xfree(BIGNUM_DIGITS(obj));
RB_DEBUG_COUNTER_INC(obj_bignum_ptr);
}
@@ -2872,9 +3100,15 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case imemo_parser_strterm:
RB_DEBUG_COUNTER_INC(obj_imemo_parser_strterm);
break;
- default:
- /* unreachable */
- break;
+ case imemo_callinfo:
+ RB_DEBUG_COUNTER_INC(obj_imemo_callinfo);
+ break;
+ case imemo_callcache:
+ RB_DEBUG_COUNTER_INC(obj_imemo_callcache);
+ break;
+ case imemo_constcache:
+ RB_DEBUG_COUNTER_INC(obj_imemo_constcache);
+ break;
}
return 0;
@@ -2925,6 +3159,17 @@ Init_heap(void)
{
rb_objspace_t *objspace = &rb_objspace;
+#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
+ /* If Ruby's heap pages are not a multiple of the system page size, we
+ * cannot use mprotect for the read barrier, so we must disable automatic
+ * compaction. */
+ int pagesize;
+ pagesize = (int)sysconf(_SC_PAGE_SIZE);
+ if ((HEAP_PAGE_SIZE % pagesize) != 0) {
+ ruby_enable_autocompact = 0;
+ }
+#endif
+
objspace->next_object_id = INT2FIX(OBJ_ID_INITIAL);
objspace->id_to_obj_tbl = st_init_table(&object_id_hash_type);
objspace->obj_to_id_tbl = st_init_numtable();
@@ -3079,7 +3324,7 @@ internal_object_p(VALUE obj)
bool used_p = p->as.basic.flags;
if (used_p) {
- switch (BUILTIN_TYPE(p)) {
+ switch (BUILTIN_TYPE(obj)) {
case T_NODE:
UNEXPECTED_NODE(internal_object_p);
break;
@@ -3122,8 +3367,10 @@ os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
volatile VALUE v = (VALUE)p;
if (!internal_object_p(v)) {
if (!oes->of || rb_obj_is_kind_of(v, oes->of)) {
- rb_yield(v);
- oes->num++;
+ if (!rb_multi_ractor_p() || rb_ractor_shareable_p(v)) {
+ rb_yield(v);
+ oes->num++;
+ }
}
}
}
@@ -3241,6 +3488,57 @@ should_be_finalizable(VALUE obj)
* 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.
*
+ * The return value is an array <code>[0, aProc]</code>.
+ *
+ * The two recommended patterns are to either create the finaliser proc
+ * in a non-instance method where it can safely capture the needed state,
+ * or to use a custom callable object that stores the needed state
+ * explicitly as instance variables.
+ *
+ * class Foo
+ * def initialize(data_needed_for_finalization)
+ * ObjectSpace.define_finalizer(self, self.class.create_finalizer(data_needed_for_finalization))
+ * end
+ *
+ * def self.create_finalizer(data_needed_for_finalization)
+ * proc {
+ * puts "finalizing #{data_needed_for_finalization}"
+ * }
+ * end
+ * end
+ *
+ * class Bar
+ * class Remover
+ * def initialize(data_needed_for_finalization)
+ * @data_needed_for_finalization = data_needed_for_finalization
+ * end
+ *
+ * def call(id)
+ * puts "finalizing #{@data_needed_for_finalization}"
+ * end
+ * end
+ *
+ * def initialize(data_needed_for_finalization)
+ * ObjectSpace.define_finalizer(self, Remover.new(data_needed_for_finalization))
+ * end
+ * end
+ *
+ * Note that if your finalizer references the object to be
+ * finalized it will never be run on GC, although it will still be
+ * run at exit. You will get a warning if you capture the object
+ * to be finalized as the receiver of the finalizer.
+ *
+ * class CapturesSelf
+ * def initialize(name)
+ * ObjectSpace.define_finalizer(self, proc {
+ * # this finalizer will only be run on exit
+ * puts "finalizing #{name}"
+ * })
+ * end
+ * end
+ *
+ * Also note that finalization can be unpredictable and is never guaranteed
+ * to be run except on exit.
*/
static VALUE
@@ -3257,6 +3555,10 @@ define_final(int argc, VALUE *argv, VALUE os)
should_be_callable(block);
}
+ if (rb_callable_receiver(block) == obj) {
+ rb_warn("finalizer references object to be finalized");
+ }
+
return define_final0(obj, block);
}
@@ -3390,20 +3692,26 @@ finalize_list(rb_objspace_t *objspace, VALUE zombie)
run_final(objspace, zombie);
- GC_ASSERT(BUILTIN_TYPE(zombie) == T_ZOMBIE);
- if (FL_TEST(zombie, FL_SEEN_OBJ_ID)) {
- obj_free_object_id(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);
+ }
- RZOMBIE(zombie)->basic.flags = 0;
- if (LIKELY(heap_pages_final_slots)) heap_pages_final_slots--;
- page->final_slots--;
- page->free_slots++;
- heap_page_add_freeobj(objspace, GET_HEAP_PAGE(zombie), zombie);
+ RZOMBIE(zombie)->basic.flags = 0;
+ GC_ASSERT(heap_pages_final_slots > 0);
+ GC_ASSERT(page->final_slots > 0);
- objspace->profile.total_freed_objects++;
+ heap_pages_final_slots--;
+ page->final_slots--;
+ page->free_slots++;
+ heap_page_add_freeobj(objspace, GET_HEAP_PAGE(zombie), zombie);
+ objspace->profile.total_freed_objects++;
+ }
+ RB_VM_LOCK_LEAVE();
- zombie = next_zombie;
+ zombie = next_zombie;
}
}
@@ -3422,8 +3730,13 @@ gc_finalize_deferred(void *dmy)
{
rb_objspace_t *objspace = dmy;
if (ATOMIC_EXCHANGE(finalizing, 1)) return;
- finalize_deferred(objspace);
- ATOMIC_SET(finalizing, 0);
+
+ RB_VM_LOCK_ENTER();
+ {
+ finalize_deferred(objspace);
+ ATOMIC_SET(finalizing, 0);
+ }
+ RB_VM_LOCK_LEAVE();
}
static void
@@ -3452,6 +3765,8 @@ force_chain_object(st_data_t key, st_data_t val, st_data_t arg)
return ST_CONTINUE;
}
+bool rb_obj_is_main_ractor(VALUE gv);
+
void
rb_objspace_call_finalizer(rb_objspace_t *objspace)
{
@@ -3488,49 +3803,54 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
}
/* prohibit GC because force T_DATA finalizers can break an object graph consistency */
- dont_gc = 1;
+ dont_gc_on();
/* running data/file finalizers are part of garbage collection */
- gc_enter(objspace, "rb_objspace_call_finalizer");
+ unsigned int lock_lev;
+ gc_enter(objspace, gc_enter_event_finalizer, &lock_lev);
/* run data/file object's finalizers */
for (i = 0; i < heap_allocated_pages; i++) {
p = heap_pages_sorted[i]->start; pend = p + heap_pages_sorted[i]->total_slots;
while (p < pend) {
- void *poisoned = asan_poisoned_object_p((VALUE)p);
- asan_unpoison_object((VALUE)p, false);
- switch (BUILTIN_TYPE(p)) {
+ VALUE vp = (VALUE)p;
+ void *poisoned = asan_poisoned_object_p(vp);
+ asan_unpoison_object(vp, false);
+ switch (BUILTIN_TYPE(vp)) {
case T_DATA:
if (!DATA_PTR(p) || !RANY(p)->as.data.dfree) break;
- if (rb_obj_is_thread((VALUE)p)) break;
- if (rb_obj_is_mutex((VALUE)p)) break;
- if (rb_obj_is_fiber((VALUE)p)) break;
- p->as.free.flags = 0;
- if (RTYPEDDATA_P(p)) {
+ if (rb_obj_is_thread(vp)) break;
+ if (rb_obj_is_mutex(vp)) break;
+ if (rb_obj_is_fiber(vp)) break;
+ if (rb_obj_is_main_ractor(vp)) break;
+ if (RTYPEDDATA_P(vp)) {
RDATA(p)->dfree = RANY(p)->as.typeddata.type->function.dfree;
}
+ p->as.free.flags = 0;
if (RANY(p)->as.data.dfree == RUBY_DEFAULT_FREE) {
xfree(DATA_PTR(p));
}
else if (RANY(p)->as.data.dfree) {
- make_zombie(objspace, (VALUE)p, RANY(p)->as.data.dfree, RANY(p)->as.data.data);
+ make_zombie(objspace, vp, RANY(p)->as.data.dfree, RANY(p)->as.data.data);
}
break;
case T_FILE:
if (RANY(p)->as.file.fptr) {
- make_io_zombie(objspace, (VALUE)p);
+ make_io_zombie(objspace, vp);
}
break;
+ default:
+ break;
}
if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(p) == T_NONE);
- asan_poison_object((VALUE)p);
+ GC_ASSERT(BUILTIN_TYPE(vp) == T_NONE);
+ asan_poison_object(vp);
}
p++;
}
}
- gc_exit(objspace, "rb_objspace_call_finalizer");
+ gc_exit(objspace, gc_enter_event_finalizer, &lock_lev);
if (heap_pages_deferred_final) {
finalize_list(objspace, heap_pages_deferred_final);
@@ -3541,16 +3861,6 @@ rb_objspace_call_finalizer(rb_objspace_t *objspace)
ATOMIC_SET(finalizing, 0);
}
-PUREFUNC(static inline int is_id_value(rb_objspace_t *objspace, VALUE ptr));
-static inline int
-is_id_value(rb_objspace_t *objspace, VALUE ptr)
-{
- if (!is_pointer_to_heap(objspace, (void *)ptr)) return FALSE;
- if (BUILTIN_TYPE(ptr) > T_FIXNUM) return FALSE;
- if (BUILTIN_TYPE(ptr) == T_ICLASS) return FALSE;
- return TRUE;
-}
-
static inline int
heap_is_swept_object(rb_objspace_t *objspace, rb_heap_t *heap, VALUE ptr)
{
@@ -3589,8 +3899,11 @@ is_live_object(rb_objspace_t *objspace, VALUE ptr)
{
switch (BUILTIN_TYPE(ptr)) {
case T_NONE:
+ case T_MOVED:
case T_ZOMBIE:
return FALSE;
+ default:
+ break;
}
if (!is_garbage_object(objspace, ptr)) {
@@ -3646,6 +3959,8 @@ id2ref_obj_tbl(rb_objspace_t *objspace, VALUE objid)
* r = ObjectSpace._id2ref(s.object_id) #=> "I am a string"
* r == s #=> true
*
+ * On multi-ractor mode, if the object is not sharable, it raises
+ * RangeError.
*/
static VALUE
@@ -3682,7 +3997,13 @@ id2ref(VALUE objid)
if ((orig = id2ref_obj_tbl(objspace, objid)) != Qundef &&
is_live_object(objspace, orig)) {
- return orig;
+
+ if (!rb_multi_ractor_p() || rb_ractor_shareable_p(orig)) {
+ return orig;
+ }
+ else {
+ rb_raise(rb_eRangeError, "%+"PRIsVALUE" is id of the unshareable object on multi-ractor", rb_int2str(objid, 10));
+ }
}
if (rb_int_ge(objid, objspace->next_object_id)) {
@@ -3724,9 +4045,9 @@ cached_object_id(VALUE obj)
VALUE id;
rb_objspace_t *objspace = &rb_objspace;
+ RB_VM_LOCK_ENTER();
if (st_lookup(objspace->obj_to_id_tbl, (st_data_t)obj, &id)) {
GC_ASSERT(FL_TEST(obj, FL_SEEN_OBJ_ID));
- return id;
}
else {
GC_ASSERT(!FL_TEST(obj, FL_SEEN_OBJ_ID));
@@ -3734,12 +4055,15 @@ cached_object_id(VALUE obj)
id = objspace->next_object_id;
objspace->next_object_id = rb_int_plus(id, INT2FIX(OBJ_ID_INCREMENT));
+ VALUE already_disabled = rb_gc_disable_no_rest();
st_insert(objspace->obj_to_id_tbl, (st_data_t)obj, (st_data_t)id);
st_insert(objspace->id_to_obj_tbl, (st_data_t)id, (st_data_t)obj);
+ if (already_disabled == Qfalse) rb_objspace_gc_enable(objspace);
FL_SET(obj, FL_SEEN_OBJ_ID);
-
- return id;
}
+ RB_VM_LOCK_LEAVE();
+
+ return id;
}
static VALUE
@@ -3817,7 +4141,23 @@ rb_obj_id(VALUE obj)
return rb_find_object_id(obj, cached_object_id);
}
-#include "regint.h"
+static enum rb_id_table_iterator_result
+cc_table_memsize_i(VALUE ccs_ptr, void *data_ptr)
+{
+ size_t *total_size = data_ptr;
+ struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
+ *total_size += sizeof(*ccs);
+ *total_size += sizeof(ccs->entries[0]) * ccs->capa;
+ return ID_TABLE_CONTINUE;
+}
+
+static size_t
+cc_table_memsize(struct rb_id_table *cc_table)
+{
+ size_t total = rb_id_table_memsize(cc_table);
+ rb_id_table_foreach_values(cc_table, cc_table_memsize_i, &total);
+ return total;
+}
static size_t
obj_memsize_of(VALUE obj, int use_all_types)
@@ -3834,9 +4174,8 @@ obj_memsize_of(VALUE obj, int use_all_types)
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- if (!(RBASIC(obj)->flags & ROBJECT_EMBED) &&
- ROBJECT(obj)->as.heap.ivptr) {
- size += ROBJECT(obj)->as.heap.numiv * sizeof(VALUE);
+ if (!(RBASIC(obj)->flags & ROBJECT_EMBED)) {
+ size += ROBJECT_NUMIV(obj) * sizeof(VALUE);
}
break;
case T_MODULE:
@@ -3849,6 +4188,7 @@ obj_memsize_of(VALUE obj, int use_all_types)
size += st_memsize(RCLASS_IV_TBL(obj));
}
if (RCLASS_IV_INDEX_TBL(obj)) {
+ // TODO: more correct value
size += st_memsize(RCLASS_IV_INDEX_TBL(obj));
}
if (RCLASS(obj)->ptr->iv_tbl) {
@@ -3857,15 +4197,21 @@ obj_memsize_of(VALUE obj, int use_all_types)
if (RCLASS(obj)->ptr->const_tbl) {
size += rb_id_table_memsize(RCLASS(obj)->ptr->const_tbl);
}
+ if (RCLASS_CC_TBL(obj)) {
+ size += cc_table_memsize(RCLASS_CC_TBL(obj));
+ }
size += sizeof(rb_classext_t);
}
break;
case T_ICLASS:
- if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
+ if (RICLASS_OWNS_M_TBL_P(obj)) {
if (RCLASS_M_TBL(obj)) {
size += rb_id_table_memsize(RCLASS_M_TBL(obj));
}
}
+ if (RCLASS_EXT(obj) && RCLASS_CC_TBL(obj)) {
+ size += cc_table_memsize(RCLASS_CC_TBL(obj));
+ }
break;
case T_STRING:
size += rb_str_memsize(obj);
@@ -3994,7 +4340,7 @@ type_sym(size_t type)
COUNT_TYPE(T_ZOMBIE);
COUNT_TYPE(T_MOVED);
#undef COUNT_TYPE
- default: return INT2NUM(type); break;
+ default: return SIZET2NUM(type); break;
}
}
@@ -4059,17 +4405,18 @@ count_objects(int argc, VALUE *argv, VALUE os)
p = page->start; pend = p + page->total_slots;
for (;p < pend; p++) {
- void *poisoned = asan_poisoned_object_p((VALUE)p);
- asan_unpoison_object((VALUE)p, false);
+ VALUE vp = (VALUE)p;
+ void *poisoned = asan_poisoned_object_p(vp);
+ asan_unpoison_object(vp, false);
if (p->as.basic.flags) {
- counts[BUILTIN_TYPE(p)]++;
+ counts[BUILTIN_TYPE(vp)]++;
}
else {
freed++;
}
if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE((VALUE)p) == T_NONE);
- asan_poison_object((VALUE)p);
+ GC_ASSERT(BUILTIN_TYPE(vp) == T_NONE);
+ asan_poison_object(vp);
}
}
total += page->total_slots;
@@ -4120,13 +4467,369 @@ objspace_free_slots(rb_objspace_t *objspace)
static void
gc_setup_mark_bits(struct heap_page *page)
{
-#if USE_RGENGC
/* 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);
+
+static void
+lock_page_body(rb_objspace_t *objspace, struct heap_page_body *body)
+{
+#if defined(_WIN32)
+ DWORD old_protect;
+
+ if (!VirtualProtect(body, HEAP_PAGE_SIZE, PAGE_NOACCESS, &old_protect)) {
+#else
+ if(mprotect(body, HEAP_PAGE_SIZE, PROT_NONE)) {
+#endif
+ rb_bug("Couldn't protect page %p", (void *)body);
+ } else {
+ gc_report(5, objspace, "Protecting page in move %p\n", (void *)body);
+ }
+}
+
+static void
+unlock_page_body(rb_objspace_t *objspace, struct heap_page_body *body)
+{
+#if defined(_WIN32)
+ DWORD old_protect;
+
+ if (!VirtualProtect(body, HEAP_PAGE_SIZE, PAGE_READWRITE, &old_protect)) {
+#else
+ if(mprotect(body, HEAP_PAGE_SIZE, PROT_READ | PROT_WRITE)) {
+#endif
+ rb_bug("Couldn't unprotect page %p", (void *)body);
+ } else {
+ gc_report(5, objspace, "Unprotecting page in move %p\n", (void *)body);
+ }
+}
+
+static short
+try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page, VALUE dest)
+{
+ struct heap_page * cursor = heap->compact_cursor;
+ char from_freelist = 0;
+
+ GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest));
+
+ /* T_NONE objects came from the free list. If the object is *not* a
+ * T_NONE, it is an object that just got freed but hasn't been
+ * added to the freelist yet */
+
+ if (BUILTIN_TYPE(dest) == T_NONE) {
+ from_freelist = 1;
+ }
+
+ while(1) {
+ size_t index = heap->compact_cursor_index;
+
+ bits_t *mark_bits = cursor->mark_bits;
+ bits_t *pin_bits = cursor->pinned_bits;
+ RVALUE * p = cursor->start;
+ RVALUE * offset = p - NUM_IN_PAGE(p);
+
+ /* Find an object to move and move it. Movable objects must be
+ * marked, so we iterate using the marking bitmap */
+ for (size_t i = index; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
+ bits_t bits = mark_bits[i] & ~pin_bits[i];
+
+ if (bits) {
+ p = offset + i * BITS_BITLENGTH;
+
+ do {
+ if (bits & 1) {
+ /* We're trying to move "p" */
+ objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)p)]++;
+
+ if (gc_is_moveable_obj(objspace, (VALUE)p)) {
+ /* We were able to move "p" */
+ objspace->rcompactor.moved_count_table[BUILTIN_TYPE((VALUE)p)]++;
+ objspace->rcompactor.total_moved++;
+ gc_move(objspace, (VALUE)p, dest);
+ gc_pin(objspace, (VALUE)p);
+ heap->compact_cursor_index = i;
+ if (from_freelist) {
+ FL_SET((VALUE)p, FL_FROM_FREELIST);
+ }
+
+ return 1;
+ }
+ }
+ p++;
+ bits >>= 1;
+ } while (bits);
+ }
+ }
+
+ /* We couldn't find a movable object on the compact cursor, so lets
+ * move to the next page (previous page since we are traveling in the
+ * opposite direction of the sweep cursor) and look there. */
+
+ struct heap_page * next;
+
+ next = list_prev(&heap->pages, cursor, page_node);
+
+ /* Protect the current cursor since it probably has T_MOVED slots. */
+ lock_page_body(objspace, GET_PAGE_BODY(cursor->start));
+
+ heap->compact_cursor = next;
+ heap->compact_cursor_index = 0;
+ cursor = next;
+
+ // Cursors have met, lets quit. We set `heap->compact_cursor` equal
+ // to `heap->sweeping_page` so we know how far to iterate through
+ // the heap when unprotecting pages.
+ if (next == sweep_page) {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void
+gc_unprotect_pages(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ struct heap_page *cursor = heap->compact_cursor;
+
+ while(cursor) {
+ unlock_page_body(objspace, GET_PAGE_BODY(cursor->start));
+ cursor = list_next(&heap->pages, cursor, page_node);
+ }
+}
+
+static void gc_update_references(rb_objspace_t * objspace, rb_heap_t *heap);
+static void invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page);
+
+static void read_barrier_handler(intptr_t address)
+{
+ VALUE obj;
+ rb_objspace_t * objspace = &rb_objspace;
+
+ address -= address % sizeof(RVALUE);
+
+ obj = (VALUE)address;
+
+ RB_VM_LOCK_ENTER();
+ {
+ unlock_page_body(objspace, GET_PAGE_BODY(obj));
+
+ objspace->profile.read_barrier_faults++;
+
+ invalidate_moved_page(objspace, GET_HEAP_PAGE(obj));
+ }
+ RB_VM_LOCK_LEAVE();
+}
+
+#if defined(_WIN32)
+static LPTOP_LEVEL_EXCEPTION_FILTER old_handler;
+typedef void (*signal_handler)(int);
+static signal_handler old_sigsegv_handler;
+
+static LONG WINAPI read_barrier_signal(EXCEPTION_POINTERS * info)
+{
+ /* EXCEPTION_ACCESS_VIOLATION is what's raised by access to protected pages */
+ if (info->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) {
+ /* > The second array element specifies the virtual address of the inaccessible data.
+ * https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_record
+ *
+ * Use this address to invalidate the page */
+ read_barrier_handler((intptr_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
- /* clear mark bitmap */
- memset(&page->mark_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
+static struct sigaction old_sigbus_handler;
+static struct sigaction old_sigsegv_handler;
+
+static void
+read_barrier_signal(int sig, siginfo_t * info, void * data)
+{
+ // setup SEGV/BUS handlers for errors
+ struct sigaction prev_sigbus, prev_sigsegv;
+ sigaction(SIGBUS, &old_sigbus_handler, &prev_sigbus);
+ sigaction(SIGSEGV, &old_sigsegv_handler, &prev_sigsegv);
+
+ // enable SIGBUS/SEGV
+ sigset_t set, prev_set;
+ sigemptyset(&set);
+ sigaddset(&set, SIGBUS);
+ sigaddset(&set, SIGSEGV);
+ sigprocmask(SIG_UNBLOCK, &set, &prev_set);
+
+ // run handler
+ read_barrier_handler((intptr_t)info->si_addr);
+
+ // reset SEGV/BUS handlers
+ sigaction(SIGBUS, &prev_sigbus, NULL);
+ sigaction(SIGSEGV, &prev_sigsegv, NULL);
+ sigprocmask(SIG_SETMASK, &prev_set, NULL);
+}
+
+static void
+uninstall_handlers(void)
+{
+ sigaction(SIGBUS, &old_sigbus_handler, NULL);
+ sigaction(SIGSEGV, &old_sigsegv_handler, NULL);
+}
+
+static void
+install_handlers(void)
+{
+ struct sigaction action;
+ memset(&action, 0, sizeof(struct sigaction));
+ sigemptyset(&action.sa_mask);
+ action.sa_sigaction = read_barrier_signal;
+ action.sa_flags = SA_SIGINFO | SA_ONSTACK;
+
+ sigaction(SIGBUS, &action, &old_sigbus_handler);
+ sigaction(SIGSEGV, &action, &old_sigsegv_handler);
+}
#endif
+
+static void
+revert_stack_objects(VALUE stack_obj, void *ctx)
+{
+ rb_objspace_t * objspace = (rb_objspace_t*)ctx;
+
+ if (BUILTIN_TYPE(stack_obj) == T_MOVED) {
+ /* For now we'll revert the whole page if the object made it to the
+ * stack. I think we can change this to move just the one object
+ * back though */
+ invalidate_moved_page(objspace, GET_HEAP_PAGE(stack_obj));
+ }
+}
+
+static void
+check_stack_for_moved(rb_objspace_t *objspace)
+{
+ rb_execution_context_t *ec = GET_EC();
+ rb_vm_t *vm = rb_ec_vm_ptr(ec);
+ rb_vm_each_stack_value(vm, revert_stack_objects, (void*)objspace);
+}
+
+static void
+gc_compact_finish(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ GC_ASSERT(heap->sweeping_page == heap->compact_cursor);
+
+ gc_unprotect_pages(objspace, heap);
+ uninstall_handlers();
+
+ /* The mutator is allowed to run during incremental sweeping. T_MOVED
+ * objects can get pushed on the stack and when the compaction process
+ * finishes up, it may remove the read barrier before anything has a
+ * chance to read from the T_MOVED address. To fix this, we scan the stack
+ * then revert any moved objects that made it to the stack. */
+ check_stack_for_moved(objspace);
+
+ gc_update_references(objspace, heap);
+ heap->compact_cursor = NULL;
+ heap->compact_cursor_index = 0;
+ objspace->profile.compact_count++;
+ if (gc_prof_enabled(objspace)) {
+ gc_profile_record *record = gc_prof_record(objspace);
+ record->moved_objects = objspace->rcompactor.total_moved - record->moved_objects;
+ }
+ rb_clear_constant_cache();
+ objspace->flags.during_compacting = FALSE;
+}
+
+static int
+gc_fill_swept_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_page, int *freed_slots, int *empty_slots)
+{
+ /* Find any pinned but not marked objects and try to fill those slots */
+ int i;
+ int moved_slots = 0;
+ int finished_compacting = 0;
+ bits_t *mark_bits, *pin_bits;
+ bits_t bitset;
+ RVALUE *p, *offset;
+
+ mark_bits = sweep_page->mark_bits;
+ pin_bits = sweep_page->pinned_bits;
+
+ p = sweep_page->start;
+ offset = p - NUM_IN_PAGE(p);
+
+ struct heap_page * cursor = heap->compact_cursor;
+
+ unlock_page_body(objspace, GET_PAGE_BODY(cursor->start));
+
+ for (i=0; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
+ /* *Want to move* objects are pinned but not marked. */
+ bitset = pin_bits[i] & ~mark_bits[i];
+
+ if (bitset) {
+ p = offset + i * BITS_BITLENGTH;
+ do {
+ if (bitset & 1) {
+ VALUE dest = (VALUE)p;
+
+ GC_ASSERT(MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(dest), dest));
+ GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest));
+
+ CLEAR_IN_BITMAP(GET_HEAP_PINNED_BITS(dest), dest);
+
+ if (finished_compacting) {
+ if (BUILTIN_TYPE(dest) == T_NONE) {
+ (*empty_slots)++;
+ } else {
+ (*freed_slots)++;
+ }
+ (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)dest, sizeof(RVALUE));
+ heap_page_add_freeobj(objspace, sweep_page, dest);
+ } else {
+ /* Zombie slots don't get marked, but we can't reuse
+ * their memory until they have their finalizers run.*/
+ if (BUILTIN_TYPE(dest) != T_ZOMBIE) {
+ if(!try_move(objspace, heap, sweep_page, dest)) {
+ finished_compacting = 1;
+ (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
+ gc_report(5, objspace, "Quit compacting, couldn't find an object to move\n");
+ if (BUILTIN_TYPE(dest) == T_NONE) {
+ (*empty_slots)++;
+ } else {
+ (*freed_slots)++;
+ }
+ heap_page_add_freeobj(objspace, sweep_page, dest);
+ gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(dest));
+ } else {
+ moved_slots++;
+ }
+ }
+ }
+ }
+ p++;
+ bitset >>= 1;
+ } while (bitset);
+ }
+ }
+
+ lock_page_body(objspace, GET_PAGE_BODY(heap->compact_cursor->start));
+
+ return finished_compacting;
}
static inline int
@@ -4134,56 +4837,109 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
{
int i;
int empty_slots = 0, freed_slots = 0, final_slots = 0;
- RVALUE *p, *pend,*offset;
+ int was_compacting = 0;
+ RVALUE *p, *offset;
bits_t *bits, bitset;
gc_report(2, objspace, "page_sweep: start.\n");
+ if (heap->compact_cursor) {
+ if (sweep_page == heap->compact_cursor) {
+ /* The compaction cursor and sweep page met, so we need to quit compacting */
+ gc_report(5, objspace, "Quit compacting, mark and compact cursor met\n");
+ gc_compact_finish(objspace, heap);
+ } else {
+ /* We anticipate filling the page, so NULL out the freelist. */
+ asan_unpoison_memory_region(&sweep_page->freelist, sizeof(RVALUE*), false);
+ sweep_page->freelist = NULL;
+ asan_poison_memory_region(&sweep_page->freelist, sizeof(RVALUE*));
+ was_compacting = 1;
+ }
+ }
+
sweep_page->flags.before_sweep = FALSE;
- p = sweep_page->start; pend = p + sweep_page->total_slots;
+ p = sweep_page->start;
offset = p - NUM_IN_PAGE(p);
bits = sweep_page->mark_bits;
/* create guard : fill 1 out-of-range */
bits[BITMAP_INDEX(p)] |= BITMAP_BIT(p)-1;
- bits[BITMAP_INDEX(pend)] |= ~(BITMAP_BIT(pend) - 1);
+
+ int out_of_range_bits = (NUM_IN_PAGE(p) + sweep_page->total_slots) % BITS_BITLENGTH;
+ if (out_of_range_bits != 0) { // sizeof(RVALUE) == 64
+ bits[BITMAP_INDEX(p) + sweep_page->total_slots / BITS_BITLENGTH] |= ~(((bits_t)1 << out_of_range_bits) - 1);
+ }
for (i=0; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
bitset = ~bits[i];
if (bitset) {
p = offset + i * BITS_BITLENGTH;
do {
- asan_unpoison_object((VALUE)p, false);
+ VALUE vp = (VALUE)p;
+ asan_unpoison_object(vp, false);
if (bitset & 1) {
- switch (BUILTIN_TYPE(p)) {
- default: { /* majority case */
- gc_report(2, objspace, "page_sweep: free %p\n", (void *)p);
-#if USE_RGENGC && RGENGC_CHECK_MODE
- if (!is_full_marking(objspace)) {
- if (RVALUE_OLD_P((VALUE)p)) rb_bug("page_sweep: %p - old while minor GC.", (void *)p);
- if (rgengc_remembered_sweep(objspace, (VALUE)p)) rb_bug("page_sweep: %p - remembered.", (void *)p);
- }
-#endif
- if (obj_free(objspace, (VALUE)p)) {
- final_slots++;
- }
- else {
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
- heap_page_add_freeobj(objspace, sweep_page, (VALUE)p);
- gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info((VALUE)p));
- freed_slots++;
- asan_poison_object((VALUE)p);
- }
- break;
- }
+ switch (BUILTIN_TYPE(vp)) {
+ default: /* majority case */
+ gc_report(2, objspace, "page_sweep: free %p\n", (void *)p);
+#if RGENGC_CHECK_MODE
+ if (!is_full_marking(objspace)) {
+ if (RVALUE_OLD_P(vp)) rb_bug("page_sweep: %p - old while minor GC.", (void *)p);
+ if (rgengc_remembered_sweep(objspace, vp)) rb_bug("page_sweep: %p - remembered.", (void *)p);
+ }
+#endif
+ if (obj_free(objspace, vp)) {
+ final_slots++;
+ }
+ else {
+ if (heap->compact_cursor) {
+ /* We *want* to fill this slot */
+ MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(vp), vp);
+ } else {
+ (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
+ heap_page_add_freeobj(objspace, sweep_page, vp);
+ gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
+ freed_slots++;
+ }
+
+ }
+ break;
/* minor cases */
+ case T_MOVED:
+ if (objspace->flags.during_compacting) {
+ /* The sweep cursor shouldn't have made it to any
+ * T_MOVED slots while the compact flag is enabled.
+ * The sweep cursor and compact cursor move in
+ * opposite directions, and when they meet references will
+ * get updated and "during_compacting" should get disabled */
+ rb_bug("T_MOVED shouldn't be seen until compaction is finished\n");
+ }
+ gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
+ if (FL_TEST(vp, FL_FROM_FREELIST)) {
+ empty_slots++;
+ } else {
+ freed_slots++;
+ }
+ heap_page_add_freeobj(objspace, sweep_page, vp);
+ break;
case T_ZOMBIE:
/* already counted */
break;
case T_NONE:
- empty_slots++; /* already freed */
+ if (heap->compact_cursor) {
+ /* We *want* to fill this slot */
+ MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(vp), vp);
+ } else {
+ /* When we started sweeping this page, we were in
+ * compacting mode and nulled the free list for
+ * the page. But compaction finished, so we need to
+ * put any T_NONE slots back on the freelist. */
+ if (was_compacting) {
+ heap_page_add_freeobj(objspace, sweep_page, vp);
+ }
+ empty_slots++; /* already freed */
+ }
break;
}
}
@@ -4193,7 +4949,15 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
}
}
- gc_setup_mark_bits(sweep_page);
+ if (heap->compact_cursor) {
+ if (gc_fill_swept_page(objspace, heap, sweep_page, &freed_slots, &empty_slots)) {
+ gc_compact_finish(objspace, heap);
+ }
+ }
+
+ if (!heap->compact_cursor) {
+ gc_setup_mark_bits(sweep_page);
+ }
#if GC_PROFILE_MORE_DETAIL
if (gc_prof_enabled(objspace)) {
@@ -4202,15 +4966,13 @@ gc_page_sweep(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *sweep_
record->empty_objects += empty_slots;
}
#endif
- if (0) fprintf(stderr, "gc_page_sweep(%d): total_slots: %d, freed_slots: %d, empty_slots: %d, final_slots: %d\n",
- (int)rb_gc_count(),
- (int)sweep_page->total_slots,
+ if (0) fprintf(stderr, "gc_page_sweep(%"PRIdSIZE"): total_slots: %d, freed_slots: %d, empty_slots: %d, final_slots: %d\n",
+ rb_gc_count(),
+ sweep_page->total_slots,
freed_slots, empty_slots, final_slots);
sweep_page->free_slots = freed_slots + empty_slots;
objspace->profile.total_freed_objects += freed_slots;
- heap_pages_final_slots += final_slots;
- sweep_page->final_slots += final_slots;
if (heap_pages_deferred_final && !finalizing) {
rb_thread_t *th = GET_THREAD();
@@ -4272,19 +5034,11 @@ gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap)
heap->pooled_pages = NULL;
objspace->rincgc.pooled_slots = 0;
#endif
- if (heap->using_page) {
- struct heap_page *page = heap->using_page;
- asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
- RVALUE **p = &page->freelist;
- while (*p) {
- p = &(*p)->as.free.next;
- }
- *p = heap->freelist;
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
- heap->using_page = NULL;
+ rb_ractor_t *r = NULL;
+ list_for_each(&GET_VM()->ractor.set, r, vmlr_node) {
+ rb_gc_ractor_newobj_cache_clear(&r->newobj_cache);
}
- heap->freelist = NULL;
}
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
@@ -4323,6 +5077,8 @@ gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap)
{
struct heap_page *sweep_page = heap->sweeping_page;
int unlink_limit = 3;
+ int swept_slots = 0;
+
#if GC_ENABLE_INCREMENTAL_MARK
int need_pool = will_be_incremental_marking(objspace) ? TRUE : FALSE;
@@ -4338,8 +5094,9 @@ gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap)
#endif
do {
+ RUBY_DEBUG_LOG("sweep_page:%p", sweep_page);
int free_slots = gc_page_sweep(objspace, heap, sweep_page);
- heap->sweeping_page = list_next(&heap->pages, sweep_page, page_node);
+ heap->sweeping_page = list_next(&heap->pages, sweep_page, page_node);
if (sweep_page->final_slots + free_slots == sweep_page->total_slots &&
heap_pages_freeable_pages > 0 &&
@@ -4353,17 +5110,18 @@ gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap)
else if (free_slots > 0) {
#if GC_ENABLE_INCREMENTAL_MARK
if (need_pool) {
- if (heap_add_poolpage(objspace, heap, sweep_page)) {
- need_pool = FALSE;
- }
+ heap_add_poolpage(objspace, heap, sweep_page);
+ need_pool = FALSE;
}
else {
- heap_add_freepage(heap, sweep_page);
- break;
+ heap_add_freepage(heap, sweep_page);
+ swept_slots += free_slots;
+ if (swept_slots > 2048) {
+ break;
+ }
}
#else
- heap_add_freepage(heap, sweep_page);
- break;
+ heap_add_freepage(heap, sweep_page);
#endif
}
else {
@@ -4379,6 +5137,8 @@ gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap)
gc_prof_sweep_timer_stop(objspace);
#endif
+ GC_ASSERT(gc_mode(objspace) == gc_mode_sweeping ? heap->free_pages != NULL : 1);
+
return heap->free_pages != NULL;
}
@@ -4395,17 +5155,92 @@ gc_sweep_rest(rb_objspace_t *objspace)
static void
gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *heap)
{
- GC_ASSERT(dont_gc == FALSE);
+ GC_ASSERT(dont_gc_val() == FALSE);
if (!GC_ENABLE_LAZY_SWEEP) return;
- gc_enter(objspace, "sweep_continue");
-#if USE_RGENGC
- if (objspace->rgengc.need_major_gc == GPR_FLAG_NONE && heap_increment(objspace, heap)) {
- gc_report(3, objspace, "gc_sweep_continue: success heap_increment().\n");
- }
-#endif
+ unsigned int lock_lev;
+ gc_enter(objspace, gc_enter_event_sweep_continue, &lock_lev);
gc_sweep_step(objspace, heap);
- gc_exit(objspace, "sweep_continue");
+ gc_exit(objspace, gc_enter_event_sweep_continue, &lock_lev);
+}
+
+static void
+invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page)
+{
+ int i;
+ int empty_slots = 0, freed_slots = 0;
+ bits_t *mark_bits, *pin_bits;
+ bits_t bitset;
+ RVALUE *p, *offset;
+
+ mark_bits = page->mark_bits;
+ pin_bits = page->pinned_bits;
+
+ p = page->start;
+ offset = p - NUM_IN_PAGE(p);
+
+ for (i=0; 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];
+
+ if (bitset) {
+ p = offset + i * BITS_BITLENGTH;
+ 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);
+
+ if (FL_TEST(forwarding_object, FL_FROM_FREELIST)) {
+ empty_slots++; /* already freed */
+ } else {
+ freed_slots++;
+ }
+
+ gc_move(objspace, object, forwarding_object);
+ /* forwarding_object is now our actual object, and "object"
+ * is the free slot for the original page */
+ heap_page_add_freeobj(objspace, GET_HEAP_PAGE(object), 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++;
+ bitset >>= 1;
+ } while (bitset);
+ }
+ }
+
+ page->free_slots += (empty_slots + freed_slots);
+ objspace->profile.total_freed_objects += freed_slots;
+}
+
+static void
+gc_compact_start(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ heap->compact_cursor = list_tail(&heap->pages, struct heap_page, page_node);
+ heap->compact_cursor_index = 0;
+
+ if (gc_prof_enabled(objspace)) {
+ gc_profile_record *record = gc_prof_record(objspace);
+ record->moved_objects = objspace->rcompactor.total_moved;
+ }
+
+ memset(objspace->rcompactor.considered_count_table, 0, T_MASK * sizeof(size_t));
+ memset(objspace->rcompactor.moved_count_table, 0, T_MASK * sizeof(size_t));
+
+ /* Set up read barrier for pages containing MOVED objects */
+ install_handlers();
}
static void
@@ -4420,6 +5255,16 @@ gc_sweep(rb_objspace_t *objspace)
gc_prof_sweep_timer_start(objspace);
#endif
gc_sweep_start(objspace);
+ if (objspace->flags.during_compacting) {
+ struct heap_page *page = NULL;
+
+ list_for_each(&heap_eden->pages, page, page_node) {
+ page->flags.before_sweep = TRUE;
+ }
+
+ gc_compact_start(objspace, heap_eden);
+ }
+
gc_sweep_rest(objspace);
#if !GC_ENABLE_LAZY_SWEEP
gc_prof_sweep_timer_stop(objspace);
@@ -4429,6 +5274,10 @@ gc_sweep(rb_objspace_t *objspace)
struct heap_page *page = NULL;
gc_sweep_start(objspace);
+ if (ruby_enable_autocompact && is_full_marking(objspace)) {
+ gc_compact_start(objspace, heap_eden);
+ }
+
list_for_each(&heap_eden->pages, page, page_node) {
page->flags.before_sweep = TRUE;
}
@@ -4543,6 +5392,22 @@ free_stack_chunks(mark_stack_t *stack)
static void
push_mark_stack(mark_stack_t *stack, VALUE data)
{
+ VALUE obj = data;
+ switch (BUILTIN_TYPE(obj)) {
+ case T_NIL:
+ case T_FIXNUM:
+ case T_MOVED:
+ rb_bug("push_mark_stack() called for broken object");
+ break;
+
+ case T_NODE:
+ UNEXPECTED_NODE(push_mark_stack);
+ break;
+
+ default:
+ break;
+ }
+
if (stack->index == stack->limit) {
push_mark_stack_chunk(stack);
}
@@ -4739,13 +5604,12 @@ rb_gc_mark_values(long n, const VALUE *values)
}
static void
-gc_mark_and_pin_stack_values(rb_objspace_t *objspace, long n, const VALUE *values)
+gc_mark_stack_values(rb_objspace_t *objspace, long n, const VALUE *values)
{
long i;
for (i=0; i<n; i++) {
- /* skip MOVED objects that are on the stack */
- if (is_markable_object(objspace, values[i]) && T_MOVED != BUILTIN_TYPE(values[i])) {
+ if (is_markable_object(objspace, values[i])) {
gc_mark_and_pin(objspace, values[i]);
}
}
@@ -4755,7 +5619,7 @@ void
rb_gc_mark_vm_stack_values(long n, const VALUE *values)
{
rb_objspace_t *objspace = &rb_objspace;
- gc_mark_and_pin_stack_values(objspace, n, values);
+ gc_mark_stack_values(objspace, n, values);
}
static int
@@ -4803,11 +5667,19 @@ mark_set(rb_objspace_t *objspace, st_table *tbl)
st_foreach(tbl, mark_key, (st_data_t)objspace);
}
+static int
+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(objspace, (VALUE)value);
+ return ST_CONTINUE;
+}
+
static void
mark_finalizer_tbl(rb_objspace_t *objspace, st_table *tbl)
{
if (!tbl) return;
- st_foreach(tbl, mark_value, (st_data_t)objspace);
+ st_foreach(tbl, pin_value, (st_data_t)objspace);
}
void
@@ -4857,7 +5729,7 @@ mark_hash(rb_objspace_t *objspace, VALUE hash)
}
if (RHASH_AR_TABLE_P(hash)) {
- if (objspace->mark_func_data == NULL && RHASH_TRANSIENT_P(hash)) {
+ if (LIKELY(during_gc) && RHASH_TRANSIENT_P(hash)) {
rb_transient_heap_mark(hash, RHASH_AR_TABLE(hash));
}
}
@@ -5040,7 +5912,6 @@ gc_mark_maybe(rb_objspace_t *objspace, VALUE obj)
/* Garbage can live on the stack, so do not mark or pin */
switch (BUILTIN_TYPE(obj)) {
- case T_MOVED:
case T_ZOMBIE:
case T_NONE:
break;
@@ -5065,12 +5936,12 @@ rb_gc_mark_maybe(VALUE obj)
static inline int
gc_mark_set(rb_objspace_t *objspace, VALUE obj)
{
+ ASSERT_vm_locking();
if (RVALUE_MARKED(obj)) return 0;
MARK_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj);
return 1;
}
-#if USE_RGENGC
static int
gc_remember_unprotected(rb_objspace_t *objspace, VALUE obj)
{
@@ -5094,12 +5965,10 @@ gc_remember_unprotected(rb_objspace_t *objspace, VALUE obj)
return FALSE;
}
}
-#endif
static void
rgengc_check_relation(rb_objspace_t *objspace, VALUE obj)
{
-#if USE_RGENGC
const VALUE old_parent = objspace->rgengc.parent_object;
if (old_parent) { /* parent object is old */
@@ -5132,7 +6001,6 @@ rgengc_check_relation(rb_objspace_t *objspace, VALUE obj)
}
GC_ASSERT(old_parent == objspace->rgengc.parent_object);
-#endif
}
static void
@@ -5155,7 +6023,6 @@ gc_grey(rb_objspace_t *objspace, VALUE obj)
static void
gc_aging(rb_objspace_t *objspace, VALUE obj)
{
-#if USE_RGENGC
struct heap_page *page = GET_HEAP_PAGE(obj);
GC_ASSERT(RVALUE_MARKING(obj) == FALSE);
@@ -5172,25 +6039,40 @@ gc_aging(rb_objspace_t *objspace, VALUE obj)
}
}
check_rvalue_consistency(obj);
-#endif /* USE_RGENGC */
objspace->marked_slots++;
}
NOINLINE(static void gc_mark_ptr(rb_objspace_t *objspace, VALUE obj));
+static void reachable_objects_from_callback(VALUE obj);
static void
gc_mark_ptr(rb_objspace_t *objspace, VALUE obj)
{
- if (LIKELY(objspace->mark_func_data == NULL)) {
+ if (LIKELY(during_gc)) {
rgengc_check_relation(objspace, obj);
if (!gc_mark_set(objspace, obj)) return; /* already marked */
- if (RB_TYPE_P(obj, T_NONE)) rb_bug("try to mark T_NONE object"); /* check here will help debugging */
+
+ if (0) { // for debug GC marking miss
+ if (objspace->rgengc.parent_object) {
+ RUBY_DEBUG_LOG("%p (%s) parent:%p (%s)",
+ (void *)obj, obj_type_name(obj),
+ (void *)objspace->rgengc.parent_object, obj_type_name(objspace->rgengc.parent_object));
+ }
+ else {
+ RUBY_DEBUG_LOG("%p (%s)", (void *)obj, obj_type_name(obj));
+ }
+ }
+
+ if (UNLIKELY(RB_TYPE_P(obj, T_NONE))) {
+ rp(obj);
+ rb_bug("try to mark T_NONE object"); /* check here will help debugging */
+ }
gc_aging(objspace, obj);
gc_grey(objspace, obj);
}
else {
- objspace->mark_func_data->mark_func(obj, objspace->mark_func_data->data);
+ reachable_objects_from_callback(obj);
}
}
@@ -5199,7 +6081,9 @@ gc_pin(rb_objspace_t *objspace, VALUE obj)
{
GC_ASSERT(is_markable_object(objspace, obj));
if (UNLIKELY(objspace->flags.during_compacting)) {
- MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj);
+ if (LIKELY(during_gc)) {
+ MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj);
+ }
}
}
@@ -5243,14 +6127,12 @@ rb_objspace_marked_object_p(VALUE obj)
static inline void
gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj)
{
-#if USE_RGENGC
if (RVALUE_OLD_P(obj)) {
objspace->rgengc.parent_object = obj;
}
else {
objspace->rgengc.parent_object = Qfalse;
}
-#endif
}
static void
@@ -5260,11 +6142,16 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj)
case imemo_env:
{
const rb_env_t *env = (const rb_env_t *)obj;
- GC_ASSERT(VM_ENV_ESCAPED_P(env->ep));
- gc_mark_values(objspace, (long)env->env_size, env->env);
- VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
- gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env));
- gc_mark(objspace, (VALUE)env->iseq);
+
+ if (LIKELY(env->ep)) {
+ // just after newobj() can be NULL here.
+ GC_ASSERT(env->ep[VM_ENV_DATA_INDEX_ENV] == obj);
+ GC_ASSERT(VM_ENV_ESCAPED_P(env->ep));
+ gc_mark_values(objspace, (long)env->env_size, env->env);
+ VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
+ gc_mark(objspace, (VALUE)rb_vm_env_prev_env(env));
+ gc_mark(objspace, (VALUE)env->iseq);
+ }
}
return;
case imemo_cref:
@@ -5309,6 +6196,21 @@ gc_mark_imemo(rb_objspace_t *objspace, VALUE obj)
case imemo_parser_strterm:
rb_strterm_mark(obj);
return;
+ case imemo_callinfo:
+ return;
+ case imemo_callcache:
+ {
+ const struct rb_callcache *cc = (const struct rb_callcache *)obj;
+ // should not mark klass here
+ gc_mark(objspace, (VALUE)vm_cc_cme(cc));
+ }
+ return;
+ case imemo_constcache:
+ {
+ const struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)obj;
+ gc_mark(objspace, ice->value);
+ }
+ return;
#if VM_CHECK_MODE > 0
default:
VM_UNREACHABLE(gc_mark_imemo);
@@ -5346,6 +6248,9 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
case T_IMEMO:
gc_mark_imemo(objspace, obj);
return;
+
+ default:
+ break;
}
gc_mark(objspace, any->as.basic.klass);
@@ -5357,13 +6262,15 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
gc_mark(objspace, RCLASS_SUPER(obj));
}
if (!RCLASS_EXT(obj)) break;
+
mark_m_tbl(objspace, RCLASS_M_TBL(obj));
+ cc_table_mark(objspace, obj);
mark_tbl_no_pin(objspace, RCLASS_IV_TBL(obj));
mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
break;
case T_ICLASS:
- if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
+ if (RICLASS_OWNS_M_TBL_P(obj)) {
mark_m_tbl(objspace, RCLASS_M_TBL(obj));
}
if (RCLASS_SUPER(obj)) {
@@ -5371,6 +6278,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
}
if (!RCLASS_EXT(obj)) break;
mark_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
+ cc_table_mark(objspace, obj);
break;
case T_ARRAY:
@@ -5385,7 +6293,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
gc_mark(objspace, ptr[i]);
}
- if (objspace->mark_func_data == NULL) {
+ if (LIKELY(during_gc)) {
if (!FL_TEST_RAW(obj, RARRAY_EMBED_FLAG) &&
RARRAY_TRANSIENT_P(obj)) {
rb_transient_heap_mark(obj, ptr);
@@ -5420,22 +6328,21 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
{
const VALUE * const ptr = ROBJECT_IVPTR(obj);
- if (ptr) {
- uint32_t i, len = ROBJECT_NUMIV(obj);
- for (i = 0; i < len; i++) {
- gc_mark(objspace, ptr[i]);
- }
+ uint32_t i, len = ROBJECT_NUMIV(obj);
+ for (i = 0; i < len; i++) {
+ gc_mark(objspace, ptr[i]);
+ }
- if (objspace->mark_func_data == NULL &&
+ if (LIKELY(during_gc) &&
ROBJ_TRANSIENT_P(obj)) {
- rb_transient_heap_mark(obj, ptr);
- }
+ rb_transient_heap_mark(obj, ptr);
}
}
break;
case T_FILE:
if (any->as.file.fptr) {
+ gc_mark(objspace, any->as.file.fptr->self);
gc_mark(objspace, any->as.file.fptr->pathv);
gc_mark(objspace, any->as.file.fptr->tied_io_for_writing);
gc_mark(objspace, any->as.file.fptr->writeconv_asciicompat);
@@ -5476,7 +6383,7 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
gc_mark(objspace, ptr[i]);
}
- if (objspace->mark_func_data == NULL &&
+ if (LIKELY(during_gc) &&
RSTRUCT_TRANSIENT_P(obj)) {
rb_transient_heap_mark(obj, ptr);
}
@@ -5601,9 +6508,7 @@ gc_mark_roots(rb_objspace_t *objspace, const char **categoryp)
if (categoryp) *categoryp = "xxx";
-#if USE_RGENGC
objspace->rgengc.parent_object = Qfalse;
-#endif
#if PRINT_ROOT_TICKS
#define MARK_CHECKPOINT_PRINT_TICK(category) do { \
@@ -5745,8 +6650,10 @@ static int
allrefs_add(struct allrefs *data, VALUE obj)
{
struct reflist *refs;
+ st_data_t r;
- if (st_lookup(data->references, obj, (st_data_t *)&refs)) {
+ if (st_lookup(data->references, obj, &r)) {
+ refs = (struct reflist *)r;
reflist_add(refs, data->root_obj);
return 0;
}
@@ -5785,8 +6692,8 @@ objspace_allrefs(rb_objspace_t *objspace)
struct allrefs data;
struct mark_func_data_struct mfd;
VALUE obj;
- int prev_dont_gc = dont_gc;
- dont_gc = TRUE;
+ int prev_dont_gc = dont_gc_val();
+ dont_gc_on();
data.objspace = objspace;
data.references = st_init_numtable();
@@ -5807,12 +6714,12 @@ objspace_allrefs(rb_objspace_t *objspace)
}
free_stack_chunks(&data.mark_stack);
- dont_gc = prev_dont_gc;
+ dont_gc_set(prev_dont_gc);
return data.references;
}
static int
-objspace_allrefs_destruct_i(st_data_t key, st_data_t value, void *ptr)
+objspace_allrefs_destruct_i(st_data_t key, st_data_t value, st_data_t ptr)
{
struct reflist *refs = (struct reflist *)value;
reflist_destruct(refs);
@@ -5841,13 +6748,14 @@ allrefs_dump_i(st_data_t k, st_data_t v, st_data_t ptr)
static void
allrefs_dump(rb_objspace_t *objspace)
{
- fprintf(stderr, "[all refs] (size: %d)\n", (int)objspace->rgengc.allrefs_table->num_entries);
+ VALUE size = objspace->rgengc.allrefs_table->num_entries;
+ fprintf(stderr, "[all refs] (size: %"PRIuVALUE")\n", size);
st_foreach(objspace->rgengc.allrefs_table, allrefs_dump_i, 0);
}
#endif
static int
-gc_check_after_marks_i(st_data_t k, st_data_t v, void *ptr)
+gc_check_after_marks_i(st_data_t k, st_data_t v, st_data_t ptr)
{
VALUE obj = k;
struct reflist *refs = (struct reflist *)v;
@@ -5910,14 +6818,11 @@ struct verify_internal_consistency_struct {
size_t live_object_count;
size_t zombie_object_count;
-#if USE_RGENGC
VALUE parent;
size_t old_object_count;
size_t remembered_shady_count;
-#endif
};
-#if USE_RGENGC
static void
check_generation_i(const VALUE child, void *ptr)
{
@@ -5948,7 +6853,6 @@ check_color_i(const VALUE child, void *ptr)
data->err_count++;
}
}
-#endif
static void
check_children_i(const VALUE child, void *ptr)
@@ -5986,7 +6890,6 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v
rb_objspace_reachable_objects_from(obj, check_children_i, (void *)data);
}
-#if USE_RGENGC
/* check health of children */
if (RVALUE_OLD_P(obj)) data->old_object_count++;
if (RVALUE_WB_UNPROTECTED(obj) && RVALUE_UNCOLLECTIBLE(obj)) data->remembered_shady_count++;
@@ -6004,7 +6907,6 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v
rb_objspace_reachable_objects_from(obj, check_color_i, (void *)data);
}
}
-#endif
}
else {
if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
@@ -6024,7 +6926,6 @@ verify_internal_consistency_i(void *page_start, void *page_end, size_t stride, v
static int
gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
{
-#if USE_RGENGC
int i;
unsigned int has_remembered_shady = FALSE;
unsigned int has_remembered_old = FALSE;
@@ -6074,17 +6975,14 @@ gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
if (0) {
/* free_slots may not equal to free_objects */
if (page->free_slots != free_objects) {
- rb_bug("page %p's free_slots should be %d, but %d\n", (void *)page, (int)page->free_slots, free_objects);
+ rb_bug("page %p's free_slots should be %d, but %d\n", (void *)page, page->free_slots, free_objects);
}
}
if (page->final_slots != zombie_objects) {
- rb_bug("page %p's final_slots should be %d, but %d\n", (void *)page, (int)page->final_slots, zombie_objects);
+ rb_bug("page %p's final_slots should be %d, but %d\n", (void *)page, page->final_slots, zombie_objects);
}
return remembered_old_objects;
-#else
- return 0;
-#endif
}
static int
@@ -6097,13 +6995,14 @@ gc_verify_heap_pages_(rb_objspace_t *objspace, struct list_head *head)
asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
RVALUE *p = page->freelist;
while (p) {
- RVALUE *prev = p;
- asan_unpoison_object((VALUE)p, false);
- if (BUILTIN_TYPE(p) != T_NONE) {
- fprintf(stderr, "freelist slot expected to be T_NONE but was: %s\n", obj_info((VALUE)p));
+ VALUE vp = (VALUE)p;
+ VALUE prev = vp;
+ asan_unpoison_object(vp, false);
+ if (BUILTIN_TYPE(vp) != T_NONE) {
+ fprintf(stderr, "freelist slot expected to be T_NONE but was: %s\n", obj_info(vp));
}
p = p->as.free.next;
- asan_poison_object((VALUE)prev);
+ asan_poison_object(prev);
}
asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
@@ -6138,12 +7037,11 @@ static VALUE
gc_verify_internal_consistency_m(VALUE dummy)
{
gc_verify_internal_consistency(&rb_objspace);
-
return Qnil;
}
static void
-gc_verify_internal_consistency(rb_objspace_t *objspace)
+gc_verify_internal_consistency_(rb_objspace_t *objspace)
{
struct verify_internal_consistency_struct data = {0};
@@ -6168,24 +7066,28 @@ gc_verify_internal_consistency(rb_objspace_t *objspace)
/* check counters */
- if (!is_lazy_sweeping(heap_eden) && !finalizing) {
+ if (!is_lazy_sweeping(heap_eden) &&
+ !finalizing &&
+ ruby_single_main_ractor != NULL) {
if (objspace_live_slots(objspace) != data.live_object_count) {
- fprintf(stderr, "heap_pages_final_slots: %d, objspace->profile.total_freed_objects: %d\n",
- (int)heap_pages_final_slots, (int)objspace->profile.total_freed_objects);
- rb_bug("inconsistent live slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace_live_slots(objspace), data.live_object_count);
+ fprintf(stderr, "heap_pages_final_slots: %"PRIdSIZE", "
+ "objspace->profile.total_freed_objects: %"PRIdSIZE"\n",
+ heap_pages_final_slots, objspace->profile.total_freed_objects);
+ rb_bug("inconsistent live slot number: expect %"PRIuSIZE", but %"PRIuSIZE".",
+ objspace_live_slots(objspace), data.live_object_count);
}
}
-#if USE_RGENGC
if (!is_marking(objspace)) {
if (objspace->rgengc.old_objects != data.old_object_count) {
- rb_bug("inconsistent old slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace->rgengc.old_objects, data.old_object_count);
+ rb_bug("inconsistent old slot number: expect %"PRIuSIZE", but %"PRIuSIZE".",
+ objspace->rgengc.old_objects, data.old_object_count);
}
if (objspace->rgengc.uncollectible_wb_unprotected_objects != data.remembered_shady_count) {
- rb_bug("inconsistent old slot number: expect %"PRIuSIZE", but %"PRIuSIZE".", objspace->rgengc.uncollectible_wb_unprotected_objects, data.remembered_shady_count);
+ rb_bug("inconsistent number of wb unprotected objects: expect %"PRIuSIZE", but %"PRIuSIZE".",
+ objspace->rgengc.uncollectible_wb_unprotected_objects, data.remembered_shady_count);
}
}
-#endif
if (!finalizing) {
size_t list_count = 0;
@@ -6214,6 +7116,23 @@ gc_verify_internal_consistency(rb_objspace_t *objspace)
gc_report(5, objspace, "gc_verify_internal_consistency: OK\n");
}
+static void
+gc_verify_internal_consistency(rb_objspace_t *objspace)
+{
+ RB_VM_LOCK_ENTER();
+ {
+ rb_vm_barrier(); // stop other ractors
+
+ unsigned int prev_during_gc = during_gc;
+ during_gc = FALSE; // stop gc here
+ {
+ gc_verify_internal_consistency_(objspace);
+ }
+ during_gc = prev_during_gc;
+ }
+ RB_VM_LOCK_LEAVE();
+}
+
void
rb_gc_verify_internal_consistency(void)
{
@@ -6236,15 +7155,19 @@ gc_marks_start(rb_objspace_t *objspace, int full_mark)
gc_report(1, objspace, "gc_marks_start: (%s)\n", full_mark ? "full" : "minor");
gc_mode_transition(objspace, gc_mode_marking);
-#if USE_RGENGC
if (full_mark) {
#if GC_ENABLE_INCREMENTAL_MARK
objspace->rincgc.step_slots = (objspace->marked_slots * 2) / ((objspace->rincgc.pooled_slots / HEAP_PAGE_OBJ_LIMIT) + 1);
- if (0) fprintf(stderr, "objspace->marked_slots: %d, objspace->rincgc.pooled_page_num: %d, objspace->rincgc.step_slots: %d, \n",
- (int)objspace->marked_slots, (int)objspace->rincgc.pooled_slots, (int)objspace->rincgc.step_slots);
+ if (0) fprintf(stderr, "objspace->marked_slots: %"PRIdSIZE", "
+ "objspace->rincgc.pooled_page_num: %"PRIdSIZE", "
+ "objspace->rincgc.step_slots: %"PRIdSIZE", \n",
+ objspace->marked_slots, objspace->rincgc.pooled_slots, objspace->rincgc.step_slots);
#endif
objspace->flags.during_minor_gc = FALSE;
+ if (ruby_enable_autocompact) {
+ objspace->flags.during_compacting |= TRUE;
+ }
objspace->profile.major_gc_count++;
objspace->rgengc.uncollectible_wb_unprotected_objects = 0;
objspace->rgengc.old_objects = 0;
@@ -6259,11 +7182,11 @@ gc_marks_start(rb_objspace_t *objspace, int full_mark)
objspace->profile.minor_gc_count++;
rgengc_rememberset_mark(objspace, heap_eden);
}
-#endif
gc_mark_roots(objspace, NULL);
- gc_report(1, objspace, "gc_marks_start: (%s) end, stack in %d\n", full_mark ? "full" : "minor", (int)mark_stack_size(&objspace->mark_stack));
+ gc_report(1, objspace, "gc_marks_start: (%s) end, stack in %"PRIdSIZE"\n",
+ full_mark ? "full" : "minor", mark_stack_size(&objspace->mark_stack));
}
#if GC_ENABLE_INCREMENTAL_MARK
@@ -6329,13 +7252,15 @@ gc_marks_finish(rb_objspace_t *objspace)
}
if (RGENGC_CHECK_MODE && is_mark_stack_empty(&objspace->mark_stack) == 0) {
- rb_bug("gc_marks_finish: mark stack is not empty (%d).", (int)mark_stack_size(&objspace->mark_stack));
+ rb_bug("gc_marks_finish: mark stack is not empty (%"PRIdSIZE").",
+ mark_stack_size(&objspace->mark_stack));
}
gc_mark_roots(objspace, 0);
if (is_mark_stack_empty(&objspace->mark_stack) == FALSE) {
- gc_report(1, objspace, "gc_marks_finish: not empty (%d). retry.\n", (int)mark_stack_size(&objspace->mark_stack));
+ gc_report(1, objspace, "gc_marks_finish: not empty (%"PRIdSIZE"). retry.\n",
+ mark_stack_size(&objspace->mark_stack));
return FALSE;
}
@@ -6355,14 +7280,12 @@ gc_marks_finish(rb_objspace_t *objspace)
gc_verify_internal_consistency(objspace);
#endif
-#if USE_RGENGC
if (is_full_marking(objspace)) {
/* See the comment about RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR */
const double r = gc_params.oldobject_limit_factor;
objspace->rgengc.uncollectible_wb_unprotected_objects_limit = (size_t)(objspace->rgengc.uncollectible_wb_unprotected_objects * r);
objspace->rgengc.old_objects_limit = (size_t)(objspace->rgengc.old_objects * r);
}
-#endif
#if RGENGC_CHECK_MODE >= 4
gc_marks_check(objspace, gc_check_after_marks_i, "after_marks");
@@ -6376,11 +7299,15 @@ gc_marks_finish(rb_objspace_t *objspace)
size_t max_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_max_ratio);
size_t min_free_slots = (size_t)(total_slots * gc_params.heap_free_slots_min_ratio);
int full_marking = is_full_marking(objspace);
+ const int r_cnt = GET_VM()->ractor.cnt;
+ const int r_mul = r_cnt > 8 ? 8 : r_cnt; // upto 8
GC_ASSERT(heap->total_slots >= objspace->marked_slots);
/* setup free-able page counts */
- if (max_free_slots < gc_params.heap_init_slots) max_free_slots = gc_params.heap_init_slots;
+ if (max_free_slots < gc_params.heap_init_slots * r_mul) {
+ max_free_slots = gc_params.heap_init_slots * r_mul;
+ }
if (sweep_slots > max_free_slots) {
heap_pages_freeable_pages = (sweep_slots - max_free_slots) / HEAP_PAGE_OBJ_LIMIT;
@@ -6389,24 +7316,25 @@ gc_marks_finish(rb_objspace_t *objspace)
heap_pages_freeable_pages = 0;
}
- /* check free_min */
- if (min_free_slots < gc_params.heap_free_slots) min_free_slots = gc_params.heap_free_slots;
+ /* check free_min */
+ if (min_free_slots < gc_params.heap_free_slots * r_mul) {
+ min_free_slots = gc_params.heap_free_slots * r_mul;
+ }
-#if USE_RGENGC
if (sweep_slots < min_free_slots) {
if (!full_marking) {
if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) {
full_marking = TRUE;
/* do not update last_major_gc, because full marking is not done. */
- goto increment;
+ /* goto increment; */
}
else {
gc_report(1, objspace, "gc_marks_finish: next is full GC!!)\n");
objspace->rgengc.need_major_gc |= GPR_FLAG_MAJOR_BY_NOFREE;
}
}
- else {
- increment:
+ if (full_marking) {
+ /* increment: */
gc_report(1, objspace, "gc_marks_finish: heap_set_increment!!\n");
heap_set_increment(objspace, heap_extend_pages(objspace, sweep_slots, total_slots));
heap_increment(objspace, heap);
@@ -6430,19 +7358,15 @@ gc_marks_finish(rb_objspace_t *objspace)
objspace->rgengc.need_major_gc = GPR_FLAG_MAJOR_BY_FORCE;
}
- gc_report(1, objspace, "gc_marks_finish (marks %d objects, old %d objects, total %d slots, sweep %d slots, increment: %d, next GC: %s)\n",
- (int)objspace->marked_slots, (int)objspace->rgengc.old_objects, (int)heap->total_slots, (int)sweep_slots, (int)heap_allocatable_pages,
+ gc_report(1, objspace, "gc_marks_finish (marks %"PRIdSIZE" objects, "
+ "old %"PRIdSIZE" objects, total %"PRIdSIZE" slots, "
+ "sweep %"PRIdSIZE" slots, increment: %"PRIdSIZE", next GC: %s)\n",
+ objspace->marked_slots, objspace->rgengc.old_objects, heap->total_slots, sweep_slots, heap_allocatable_pages,
objspace->rgengc.need_major_gc ? "major" : "minor");
-#else /* USE_RGENGC */
- if (sweep_slots < min_free_slots) {
- gc_report(1, objspace, "gc_marks_finish: heap_set_increment!!\n");
- heap_set_increment(objspace, heap_extend_pages(objspace, sweep_slot, total_slot));
- heap_increment(objspace, heap);
- }
-#endif
}
rb_transient_heap_finish_marking();
+ rb_ractor_finish_marking();
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END_MARK, 0);
@@ -6450,7 +7374,7 @@ gc_marks_finish(rb_objspace_t *objspace)
}
static void
-gc_marks_step(rb_objspace_t *objspace, int slots)
+gc_marks_step(rb_objspace_t *objspace, size_t slots)
{
#if GC_ENABLE_INCREMENTAL_MARK
GC_ASSERT(is_marking(objspace));
@@ -6461,7 +7385,7 @@ gc_marks_step(rb_objspace_t *objspace, int slots)
gc_sweep(objspace);
}
}
- if (0) fprintf(stderr, "objspace->marked_slots: %d\n", (int)objspace->marked_slots);
+ if (0) fprintf(stderr, "objspace->marked_slots: %"PRIdSIZE"\n", objspace->marked_slots);
#endif
}
@@ -6491,40 +7415,39 @@ gc_marks_rest(rb_objspace_t *objspace)
static void
gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap)
{
- GC_ASSERT(dont_gc == FALSE);
+ GC_ASSERT(dont_gc_val() == FALSE);
#if GC_ENABLE_INCREMENTAL_MARK
- gc_enter(objspace, "marks_continue");
+ unsigned int lock_lev;
+ gc_enter(objspace, gc_enter_event_mark_continue, &lock_lev);
- PUSH_MARK_FUNC_DATA(NULL);
- {
- int slots = 0;
- const char *from;
+ int slots = 0;
+ const char *from;
- if (heap->pooled_pages) {
- while (heap->pooled_pages && slots < HEAP_PAGE_OBJ_LIMIT) {
- struct heap_page *page = heap_move_pooled_pages_to_free_pages(heap);
- slots += page->free_slots;
- }
- from = "pooled-pages";
- }
- else if (heap_increment(objspace, heap)) {
- slots = heap->free_pages->free_slots;
- from = "incremented-pages";
- }
+ if (heap->pooled_pages) {
+ while (heap->pooled_pages && slots < HEAP_PAGE_OBJ_LIMIT) {
+ struct heap_page *page = heap_move_pooled_pages_to_free_pages(heap);
+ slots += page->free_slots;
+ }
+ from = "pooled-pages";
+ }
+ else if (heap_increment(objspace, heap)) {
+ slots = heap->free_pages->free_slots;
+ from = "incremented-pages";
+ }
- if (slots > 0) {
- gc_report(2, objspace, "gc_marks_continue: provide %d slots from %s.\n", slots, from);
- gc_marks_step(objspace, (int)objspace->rincgc.step_slots);
- }
- else {
- gc_report(2, objspace, "gc_marks_continue: no more pooled pages (stack depth: %d).\n", (int)mark_stack_size(&objspace->mark_stack));
- gc_marks_rest(objspace);
- }
+ if (slots > 0) {
+ gc_report(2, objspace, "gc_marks_continue: provide %d slots from %s.\n",
+ slots, from);
+ gc_marks_step(objspace, objspace->rincgc.step_slots);
+ }
+ else {
+ gc_report(2, objspace, "gc_marks_continue: no more pooled pages (stack depth: %"PRIdSIZE").\n",
+ mark_stack_size(&objspace->mark_stack));
+ gc_marks_rest(objspace);
}
- POP_MARK_FUNC_DATA();
- gc_exit(objspace, "marks_continue");
+ gc_exit(objspace, gc_enter_event_mark_continue, &lock_lev);
#endif
}
@@ -6533,29 +7456,19 @@ gc_marks(rb_objspace_t *objspace, int full_mark)
{
gc_prof_mark_timer_start(objspace);
- PUSH_MARK_FUNC_DATA(NULL);
- {
- /* setup marking */
+ /* setup marking */
-#if USE_RGENGC
- gc_marks_start(objspace, full_mark);
- if (!is_incremental_marking(objspace)) {
- gc_marks_rest(objspace);
- }
+ gc_marks_start(objspace, full_mark);
+ if (!is_incremental_marking(objspace)) {
+ gc_marks_rest(objspace);
+ }
#if RGENGC_PROFILE > 0
- if (gc_prof_record(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
- record->old_objects = objspace->rgengc.old_objects;
- }
-#endif
-
-#else /* USE_RGENGC */
- gc_marks_start(objspace, TRUE);
- gc_marks_rest(objspace);
-#endif
+ if (gc_prof_record(objspace)) {
+ gc_profile_record *record = gc_prof_record(objspace);
+ record->old_objects = objspace->rgengc.old_objects;
}
- POP_MARK_FUNC_DATA();
+#endif
gc_prof_mark_timer_stop(objspace);
}
@@ -6570,7 +7483,6 @@ gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...)
va_list args;
const char *status = " ";
-#if USE_RGENGC
if (during_gc) {
status = is_full_marking(objspace) ? "+" : "-";
}
@@ -6582,7 +7494,6 @@ gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...)
status = "M";
}
}
-#endif
va_start(args, fmt);
vsnprintf(buf, 1024, fmt, args);
@@ -6593,8 +7504,6 @@ gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...)
}
}
-#if USE_RGENGC
-
/* bit operations */
static int
@@ -6763,7 +7672,11 @@ gc_writebarrier_generational(VALUE a, VALUE b, rb_objspace_t *objspace)
#if 1
/* mark `a' and remember (default behavior) */
if (!rgengc_remembered(objspace, a)) {
- rgengc_remember(objspace, a);
+ RB_VM_LOCK_ENTER_NO_BARRIER();
+ {
+ rgengc_remember(objspace, a);
+ }
+ RB_VM_LOCK_LEAVE_NO_BARRIER();
gc_report(1, objspace, "gc_writebarrier_generational: %s (remembered) -> %s\n", obj_info(a), obj_info(b));
}
#else
@@ -6823,6 +7736,10 @@ gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace)
gc_remember_unprotected(objspace, b);
}
}
+
+ if (UNLIKELY(objspace->flags.during_compacting)) {
+ MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(b), b);
+ }
}
}
#else
@@ -6838,16 +7755,22 @@ rb_gc_writebarrier(VALUE a, VALUE b)
if (RGENGC_CHECK_MODE && SPECIAL_CONST_P(b)) rb_bug("rb_gc_writebarrier: b is special const");
if (!is_incremental_marking(objspace)) {
- if (!RVALUE_OLD_P(a) || RVALUE_OLD_P(b)) {
- return;
- }
- else {
- gc_writebarrier_generational(a, b, objspace);
- }
+ if (!RVALUE_OLD_P(a) || RVALUE_OLD_P(b)) {
+ // do nothing
+ }
+ else {
+ gc_writebarrier_generational(a, b, objspace);
+ }
}
- else { /* slow path */
- gc_writebarrier_incremental(a, b, objspace);
+ else {
+ /* slow path */
+ RB_VM_LOCK_ENTER_NO_BARRIER();
+ {
+ gc_writebarrier_incremental(a, b, objspace);
+ }
+ RB_VM_LOCK_LEAVE_NO_BARRIER();
}
+ return;
}
void
@@ -6911,7 +7834,7 @@ static st_table *rgengc_unprotect_logging_table;
static int
rgengc_unprotect_logging_exit_func_i(st_data_t key, st_data_t val, st_data_t arg)
{
- fprintf(stderr, "%s\t%d\n", (char *)key, (int)val);
+ fprintf(stderr, "%s\t%"PRIuVALUE"\n", (char *)key, (VALUE)val);
return ST_CONTINUE;
}
@@ -6948,12 +7871,10 @@ rb_gc_unprotect_logging(void *objptr, const char *filename, int line)
st_insert(rgengc_unprotect_logging_table, (st_data_t)ptr, cnt);
}
}
-#endif /* USE_RGENGC */
void
rb_copy_wb_protected_attribute(VALUE dest, VALUE obj)
{
-#if USE_RGENGC
rb_objspace_t *objspace = &rb_objspace;
if (RVALUE_WB_UNPROTECTED(obj) && !RVALUE_WB_UNPROTECTED(dest)) {
@@ -6967,7 +7888,6 @@ rb_copy_wb_protected_attribute(VALUE dest, VALUE obj)
}
check_rvalue_consistency(dest);
-#endif
}
/* RGENGC analysis information */
@@ -6975,11 +7895,7 @@ rb_copy_wb_protected_attribute(VALUE dest, VALUE obj)
VALUE
rb_obj_rgengc_writebarrier_protected_p(VALUE obj)
{
-#if USE_RGENGC
return RVALUE_WB_UNPROTECTED(obj) ? Qfalse : Qtrue;
-#else
- return Qfalse;
-#endif
}
VALUE
@@ -6993,29 +7909,23 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max)
{
size_t n = 0;
static ID ID_marked;
-#if USE_RGENGC
static ID ID_wb_protected, ID_old, ID_marking, ID_uncollectible, ID_pinned;
-#endif
if (!ID_marked) {
#define I(s) ID_##s = rb_intern(#s);
I(marked);
-#if USE_RGENGC
I(wb_protected);
I(old);
I(marking);
I(uncollectible);
I(pinned);
-#endif
#undef I
}
-#if USE_RGENGC
if (RVALUE_WB_UNPROTECTED(obj) == 0 && 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;
-#endif
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;
@@ -7024,51 +7934,84 @@ rb_obj_gc_flags(VALUE obj, ID* flags, size_t max)
/* GC */
void
+rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache)
+{
+ struct heap_page *page = newobj_cache->using_page;
+ RVALUE *freelist = newobj_cache->freelist;
+ RUBY_DEBUG_LOG("ractor using_page:%p freelist:%p", page, freelist);
+
+ if (page && freelist) {
+ asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
+ if (page->freelist) {
+ RVALUE *p = page->freelist;
+ asan_unpoison_object((VALUE)p, false);
+ while (p->as.free.next) {
+ RVALUE *prev = p;
+ p = p->as.free.next;
+ asan_poison_object((VALUE)prev);
+ asan_unpoison_object((VALUE)p, false);
+ }
+ p->as.free.next = freelist;
+ asan_poison_object((VALUE)p);
+ }
+ else {
+ page->freelist = freelist;
+ }
+ asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
+ }
+
+ newobj_cache->using_page = NULL;
+ newobj_cache->freelist = NULL;
+}
+
+void
rb_gc_force_recycle(VALUE obj)
{
rb_objspace_t *objspace = &rb_objspace;
+ RB_VM_LOCK_ENTER();
+ {
+ int is_old = RVALUE_OLD_P(obj);
-#if USE_RGENGC
- int is_old = RVALUE_OLD_P(obj);
-
- gc_report(2, objspace, "rb_gc_force_recycle: %s\n", obj_info(obj));
+ gc_report(2, objspace, "rb_gc_force_recycle: %s\n", obj_info(obj));
- if (is_old) {
- if (RVALUE_MARKED(obj)) {
- objspace->rgengc.old_objects--;
- }
- }
- CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(obj), obj);
- CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
+ if (is_old) {
+ if (RVALUE_MARKED(obj)) {
+ objspace->rgengc.old_objects--;
+ }
+ }
+ CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(obj), obj);
+ CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
+ CLEAR_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj);
#if GC_ENABLE_INCREMENTAL_MARK
- if (is_incremental_marking(objspace)) {
- if (MARKED_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj)) {
- invalidate_mark_stack(&objspace->mark_stack, obj);
- CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
- }
- CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj);
- }
- else {
+ if (is_incremental_marking(objspace)) {
+ if (MARKED_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj)) {
+ invalidate_mark_stack(&objspace->mark_stack, obj);
+ CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
+ }
+ CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj);
+ }
+ else {
#endif
- if (is_old || !GET_HEAP_PAGE(obj)->flags.before_sweep) {
- CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj);
- }
- CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
+ if (is_old || GET_HEAP_PAGE(obj)->flags.before_sweep) {
+ CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj);
+ }
+ CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
#if GC_ENABLE_INCREMENTAL_MARK
- }
-#endif
+ }
#endif
- objspace->profile.total_freed_objects++;
+ objspace->profile.total_freed_objects++;
- heap_page_add_freeobj(objspace, GET_HEAP_PAGE(obj), obj);
+ heap_page_add_freeobj(objspace, GET_HEAP_PAGE(obj), obj);
- /* Disable counting swept_slots because there are no meaning.
- * if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(p), p)) {
- * objspace->heap.swept_slots++;
- * }
- */
+ /* Disable counting swept_slots because there are no meaning.
+ * if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(p), p)) {
+ * objspace->heap.swept_slots++;
+ * }
+ */
+ }
+ RB_VM_LOCK_LEAVE();
}
#ifndef MARK_OBJECT_ARY_BUCKET_SIZE
@@ -7078,15 +8021,19 @@ rb_gc_force_recycle(VALUE obj)
void
rb_gc_register_mark_object(VALUE obj)
{
- VALUE ary_ary = GET_VM()->mark_object_ary;
- VALUE ary = rb_ary_last(0, 0, ary_ary);
+ RB_VM_LOCK_ENTER();
+ {
+ VALUE ary_ary = GET_VM()->mark_object_ary;
+ VALUE ary = rb_ary_last(0, 0, ary_ary);
- if (ary == Qnil || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) {
- ary = rb_ary_tmp_new(MARK_OBJECT_ARY_BUCKET_SIZE);
- rb_ary_push(ary_ary, ary);
- }
+ if (ary == Qnil || RARRAY_LEN(ary) >= MARK_OBJECT_ARY_BUCKET_SIZE) {
+ ary = rb_ary_tmp_new(MARK_OBJECT_ARY_BUCKET_SIZE);
+ rb_ary_push(ary_ary, ary);
+ }
- rb_ary_push(ary, obj);
+ rb_ary_push(ary, obj);
+ }
+ RB_VM_LOCK_LEAVE();
}
void
@@ -7145,7 +8092,7 @@ enum {
static void
heap_ready_to_gc(rb_objspace_t *objspace, rb_heap_t *heap)
{
- if (!heap->freelist && !heap->free_pages) {
+ if (!heap->free_pages) {
if (!heap_increment(objspace, heap)) {
heap_set_increment(objspace, 1);
heap_increment(objspace, heap);
@@ -7156,7 +8103,7 @@ heap_ready_to_gc(rb_objspace_t *objspace, rb_heap_t *heap)
static int
ready_to_gc(rb_objspace_t *objspace)
{
- if (dont_gc || during_gc || ruby_disable_gc) {
+ if (dont_gc_val() || during_gc || ruby_disable_gc) {
heap_ready_to_gc(objspace, heap_eden);
return FALSE;
}
@@ -7211,12 +8158,12 @@ gc_reset_malloc_info(rb_objspace_t *objspace)
}
}
- if (0) fprintf(stderr, "%d\t%d\t%u\t%u\t%d\n",
- (int)rb_gc_count(),
- (int)objspace->rgengc.need_major_gc,
- (unsigned int)objspace->rgengc.oldmalloc_increase,
- (unsigned int)objspace->rgengc.oldmalloc_increase_limit,
- (unsigned int)gc_params.oldmalloc_limit_max);
+ if (0) fprintf(stderr, "%"PRIdSIZE"\t%d\t%"PRIuSIZE"\t%"PRIuSIZE"\t%"PRIdSIZE"\n",
+ rb_gc_count(),
+ objspace->rgengc.need_major_gc,
+ objspace->rgengc.oldmalloc_increase,
+ objspace->rgengc.oldmalloc_increase_limit,
+ gc_params.oldmalloc_limit_max);
}
else {
/* major GC */
@@ -7236,17 +8183,25 @@ gc_reset_malloc_info(rb_objspace_t *objspace)
static int
garbage_collect(rb_objspace_t *objspace, int reason)
{
+ int ret;
+
+ RB_VM_LOCK_ENTER();
+ {
#if GC_PROFILE_MORE_DETAIL
- objspace->profile.prepare_time = getrusage_time();
+ objspace->profile.prepare_time = getrusage_time();
#endif
- gc_rest(objspace);
+ gc_rest(objspace);
#if GC_PROFILE_MORE_DETAIL
- objspace->profile.prepare_time = getrusage_time() - objspace->profile.prepare_time;
+ objspace->profile.prepare_time = getrusage_time() - objspace->profile.prepare_time;
#endif
- return gc_start(objspace, reason);
+ ret = gc_start(objspace, reason);
+ }
+ RB_VM_LOCK_LEAVE();
+
+ return ret;
}
static int
@@ -7258,18 +8213,23 @@ gc_start(rb_objspace_t *objspace, int reason)
/* reason may be clobbered, later, so keep set immediate_sweep here */
objspace->flags.immediate_sweep = !!((unsigned)reason & GPR_FLAG_IMMEDIATE_SWEEP);
+ /* Explicitly enable compaction (GC.compact) */
+ objspace->flags.during_compacting = !!(reason & GPR_FLAG_COMPACT);
+
if (!heap_allocated_pages) return FALSE; /* heap is not ready */
if (!(reason & GPR_FLAG_METHOD) && !ready_to_gc(objspace)) return TRUE; /* GC is not allowed */
GC_ASSERT(gc_mode(objspace) == gc_mode_none);
GC_ASSERT(!is_lazy_sweeping(heap_eden));
GC_ASSERT(!is_incremental_marking(objspace));
+
+ unsigned int lock_lev;
+ gc_enter(objspace, gc_enter_event_start, &lock_lev);
+
#if RGENGC_CHECK_MODE >= 2
gc_verify_internal_consistency(objspace);
#endif
- gc_enter(objspace, "gc_start");
-
if (ruby_gc_stressful) {
int flag = FIXNUM_P(ruby_gc_stress_mode) ? FIX2INT(ruby_gc_stress_mode) : 0;
@@ -7280,7 +8240,6 @@ gc_start(rb_objspace_t *objspace, int reason)
objspace->flags.immediate_sweep = !(flag & (1<<gc_stress_no_immediate_sweep));
}
else {
-#if USE_RGENGC
if (objspace->rgengc.need_major_gc) {
reason |= objspace->rgengc.need_major_gc;
do_full_mark = TRUE;
@@ -7291,7 +8250,6 @@ gc_start(rb_objspace_t *objspace, int reason)
}
objspace->rgengc.need_major_gc = GPR_FLAG_NONE;
-#endif
}
if (do_full_mark && (reason & GPR_FLAG_MAJOR_MASK) == 0) {
@@ -7355,7 +8313,7 @@ gc_start(rb_objspace_t *objspace, int reason)
}
gc_prof_timer_stop(objspace);
- gc_exit(objspace, "gc_start");
+ gc_exit(objspace, gc_enter_event_start, &lock_lev);
return TRUE;
}
@@ -7366,19 +8324,18 @@ gc_rest(rb_objspace_t *objspace)
int sweeping = is_lazy_sweeping(heap_eden);
if (marking || sweeping) {
- gc_enter(objspace, "gc_rest");
+ unsigned int lock_lev;
+ gc_enter(objspace, gc_enter_event_rest, &lock_lev);
if (RGENGC_CHECK_MODE >= 2) gc_verify_internal_consistency(objspace);
if (is_incremental_marking(objspace)) {
- PUSH_MARK_FUNC_DATA(NULL);
- gc_marks_rest(objspace);
- POP_MARK_FUNC_DATA();
- }
+ gc_marks_rest(objspace);
+ }
if (is_lazy_sweeping(heap_eden)) {
gc_sweep_rest(objspace);
}
- gc_exit(objspace, "gc_rest");
+ gc_exit(objspace, gc_enter_event_rest, &lock_lev);
}
}
@@ -7393,12 +8350,10 @@ gc_current_status_fill(rb_objspace_t *objspace, char *buff)
int i = 0;
if (is_marking(objspace)) {
buff[i++] = 'M';
-#if USE_RGENGC
if (is_full_marking(objspace)) buff[i++] = 'F';
#if GC_ENABLE_INCREMENTAL_MARK
if (is_incremental_marking(objspace)) buff[i++] = 'I';
#endif
-#endif
}
else if (is_sweeping(objspace)) {
buff[i++] = 'S';
@@ -7465,31 +8420,77 @@ gc_record(rb_objspace_t *objspace, int direction, const char *event)
}
#endif /* PRINT_ENTER_EXIT_TICK */
-static inline void
-gc_enter(rb_objspace_t *objspace, const char *event)
+static const char *
+gc_enter_event_cstr(enum gc_enter_event event)
{
- GC_ASSERT(during_gc == 0);
+ switch (event) {
+ case gc_enter_event_start: return "start";
+ case gc_enter_event_mark_continue: return "mark_continue";
+ case gc_enter_event_sweep_continue: return "sweep_continue";
+ case gc_enter_event_rest: return "rest";
+ case gc_enter_event_finalizer: return "finalizer";
+ case gc_enter_event_rb_memerror: return "rb_memerror";
+ }
+ return NULL;
+}
+
+static void
+gc_enter_count(enum gc_enter_event event)
+{
+ switch (event) {
+ case gc_enter_event_start: RB_DEBUG_COUNTER_INC(gc_enter_start); break;
+ case gc_enter_event_mark_continue: RB_DEBUG_COUNTER_INC(gc_enter_mark_continue); break;
+ case gc_enter_event_sweep_continue: RB_DEBUG_COUNTER_INC(gc_enter_sweep_continue); break;
+ case gc_enter_event_rest: RB_DEBUG_COUNTER_INC(gc_enter_rest); break;
+ case gc_enter_event_finalizer: RB_DEBUG_COUNTER_INC(gc_enter_finalizer); break;
+ case gc_enter_event_rb_memerror: /* nothing */ break;
+ }
+}
+
+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_mark_continue:
+ // stop other ractors
+ rb_vm_barrier();
+ break;
+ default:
+ break;
+ }
+
+ gc_enter_count(event);
+ if (UNLIKELY(during_gc != 0)) rb_bug("during_gc != 0");
if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace);
mjit_gc_start_hook();
during_gc = TRUE;
- gc_report(1, objspace, "gc_enter: %s [%s]\n", event, gc_current_status(objspace));
- gc_record(objspace, 0, event);
+ RUBY_DEBUG_LOG("%s (%s)",gc_enter_event_cstr(event), gc_current_status(objspace));
+ gc_report(1, objspace, "gc_enter: %s [%s]\n", gc_enter_event_cstr(event), gc_current_status(objspace));
+ gc_record(objspace, 0, gc_enter_event_cstr(event));
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_ENTER, 0); /* TODO: which parameter should be passed? */
}
static inline void
-gc_exit(rb_objspace_t *objspace, const char *event)
+gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev)
{
GC_ASSERT(during_gc != 0);
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_EXIT, 0); /* TODO: which parameter should be passsed? */
- gc_record(objspace, 1, event);
- gc_report(1, objspace, "gc_exit: %s [%s]\n", event, gc_current_status(objspace));
+ gc_record(objspace, 1, gc_enter_event_cstr(event));
+ RUBY_DEBUG_LOG("%s (%s)", gc_enter_event_cstr(event), gc_current_status(objspace));
+ gc_report(1, objspace, "gc_exit: %s [%s]\n", gc_enter_event_cstr(event), gc_current_status(objspace));
during_gc = FALSE;
mjit_gc_exit_hook();
+ RB_VM_LOCK_LEAVE_LEV(lock_lev);
}
static void *
@@ -7502,7 +8503,7 @@ gc_with_gvl(void *ptr)
static int
garbage_collect_with_gvl(rb_objspace_t *objspace, int reason)
{
- if (dont_gc) return TRUE;
+ if (dont_gc_val()) return TRUE;
if (ruby_thread_has_gvl_p()) {
return garbage_collect(objspace, reason);
}
@@ -7522,7 +8523,7 @@ garbage_collect_with_gvl(rb_objspace_t *objspace, int reason)
}
static VALUE
-gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE immediate_mark, VALUE immediate_sweep)
+gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE immediate_mark, VALUE immediate_sweep, VALUE compact)
{
rb_objspace_t *objspace = &rb_objspace;
int reason = GPR_FLAG_FULL_MARK |
@@ -7530,9 +8531,14 @@ gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE
GPR_FLAG_IMMEDIATE_SWEEP |
GPR_FLAG_METHOD;
- 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;
+ /* For now, compact implies full mark / sweep, so ignore other flags */
+ if (RTEST(compact)) {
+ reason |= GPR_FLAG_COMPACT;
+ } else {
+ if (!RTEST(full_mark)) reason &= ~GPR_FLAG_FULL_MARK;
+ if (!RTEST(immediate_mark)) reason &= ~GPR_FLAG_IMMEDIATE_MARK;
+ if (!RTEST(immediate_sweep)) reason &= ~GPR_FLAG_IMMEDIATE_SWEEP;
+ }
garbage_collect(objspace, reason);
gc_finalize_deferred(objspace);
@@ -7543,9 +8549,7 @@ gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE
static int
gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
{
- if (SPECIAL_CONST_P(obj)) {
- return FALSE;
- }
+ GC_ASSERT(!SPECIAL_CONST_P(obj));
switch (BUILTIN_TYPE(obj)) {
case T_NONE:
@@ -7553,7 +8557,6 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
case T_MOVED:
case T_ZOMBIE:
return FALSE;
- break;
case T_SYMBOL:
if (DYNAMIC_SYM_P(obj) && (RSYMBOL(obj)->id & ~ID_SCOPE_MASK)) {
return FALSE;
@@ -7578,12 +8581,19 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
case T_NODE:
case T_CLASS:
if (FL_TEST(obj, FL_FINALIZE)) {
+ /* The finalizer table is a numtable. It looks up objects by address.
+ * We can't mark the keys in the finalizer table because that would
+ * prevent the objects from being collected. This check prevents
+ * objects that are keys in the finalizer table from being moved
+ * without directly pinning them. */
if (st_is_member(finalizer_table, obj)) {
return FALSE;
}
}
- return RVALUE_MARKED(obj) && !RVALUE_PINNED(obj);
- break;
+ GC_ASSERT(RVALUE_MARKED(obj));
+ GC_ASSERT(!RVALUE_PINNED(obj));
+
+ return TRUE;
default:
rb_bug("gc_is_moveable_obj: unreachable (%d)", (int)BUILTIN_TYPE(obj));
@@ -7594,7 +8604,7 @@ gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
}
static VALUE
-gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, VALUE moved_list)
+gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free)
{
int marked;
int wb_unprotected;
@@ -7606,7 +8616,7 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, VALUE moved_list)
gc_report(4, objspace, "Moving object: %p -> %p\n", (void*)scan, (void *)free);
GC_ASSERT(BUILTIN_TYPE(scan) != T_NONE);
- GC_ASSERT(BUILTIN_TYPE(free) == T_NONE);
+ GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(free), free));
/* Save off bits for current object. */
marked = rb_objspace_marked_object_p((VALUE)src);
@@ -7614,26 +8624,33 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, VALUE moved_list)
uncollectible = RVALUE_UNCOLLECTIBLE((VALUE)src);
marking = RVALUE_MARKING((VALUE)src);
- objspace->total_allocated_objects++;
-
/* Clear bits for eventual T_MOVED */
CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS((VALUE)src), (VALUE)src);
CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS((VALUE)src), (VALUE)src);
CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS((VALUE)src), (VALUE)src);
CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS((VALUE)src), (VALUE)src);
- if (FL_TEST(src, FL_EXIVAR)) {
+ if (FL_TEST((VALUE)src, FL_EXIVAR)) {
+ /* Same deal as below. Generic ivars are held in st tables.
+ * Resizing the table could cause a GC to happen and we can't allow it */
+ VALUE already_disabled = rb_gc_disable_no_rest();
rb_mv_generic_ivar((VALUE)src, (VALUE)dest);
+ if (already_disabled == Qfalse) rb_objspace_gc_enable(objspace);
}
- VALUE id;
+ st_data_t srcid = (st_data_t)src, id;
/* If the source object's object_id has been seen, we need to update
* the object to object id mapping. */
- if (st_lookup(objspace->obj_to_id_tbl, (VALUE)src, &id)) {
+ if (st_lookup(objspace->obj_to_id_tbl, srcid, &id)) {
gc_report(4, objspace, "Moving object with seen id: %p -> %p\n", (void *)src, (void *)dest);
- st_delete(objspace->obj_to_id_tbl, (st_data_t *)&src, 0);
- st_insert(objspace->obj_to_id_tbl, (VALUE)dest, id);
+ /* inserting in the st table can cause the GC to run. We need to
+ * prevent re-entry in to the GC since `gc_move` is running in the GC,
+ * so temporarily disable the GC around the st table mutation */
+ VALUE already_disabled = rb_gc_disable_no_rest();
+ st_delete(objspace->obj_to_id_tbl, &srcid, 0);
+ st_insert(objspace->obj_to_id_tbl, (st_data_t)dest, id);
+ if (already_disabled == Qfalse) rb_objspace_gc_enable(objspace);
}
/* Move the object */
@@ -7671,102 +8688,13 @@ gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, VALUE moved_list)
/* Assign forwarding address */
src->as.moved.flags = T_MOVED;
+ src->as.moved.dummy = Qundef;
src->as.moved.destination = (VALUE)dest;
- src->as.moved.next = moved_list;
GC_ASSERT(BUILTIN_TYPE((VALUE)dest) != T_NONE);
return (VALUE)src;
}
-struct heap_cursor {
- RVALUE *slot;
- size_t index;
- struct heap_page *page;
- rb_objspace_t * objspace;
-};
-
-static void
-advance_cursor(struct heap_cursor *free, struct heap_page **page_list)
-{
- if (free->slot == free->page->start + free->page->total_slots - 1) {
- free->index++;
- free->page = page_list[free->index];
- free->slot = free->page->start;
- }
- else {
- free->slot++;
- }
-}
-
-static void
-retreat_cursor(struct heap_cursor *scan, struct heap_page **page_list)
-{
- if (scan->slot == scan->page->start) {
- scan->index--;
- scan->page = page_list[scan->index];
- scan->slot = scan->page->start + scan->page->total_slots - 1;
- }
- else {
- scan->slot--;
- }
-}
-
-static int
-not_met(struct heap_cursor *free, struct heap_cursor *scan)
-{
- if (free->index < scan->index)
- return 1;
-
- if (free->index > scan->index)
- return 0;
-
- return free->slot < scan->slot;
-}
-
-static void
-init_cursors(rb_objspace_t *objspace, struct heap_cursor *free, struct heap_cursor *scan, struct heap_page **page_list)
-{
- struct heap_page *page;
- size_t total_pages = heap_eden->total_pages;
- page = page_list[0];
-
- free->index = 0;
- free->page = page;
- free->slot = page->start;
- free->objspace = objspace;
-
- page = page_list[total_pages - 1];
- scan->index = total_pages - 1;
- scan->page = page;
- scan->slot = page->start + page->total_slots - 1;
- scan->objspace = objspace;
-}
-
-static int
-count_pinned(struct heap_page *page)
-{
- int pinned = 0;
- int i;
-
- for (i = 0; i < HEAP_PAGE_BITMAP_LIMIT; i++) {
- pinned += popcount_bits(page->pinned_bits[i]);
- }
-
- return pinned;
-}
-
-static int
-compare_pinned(const void *left, const void *right, void *dummy)
-{
- struct heap_page *left_page;
- struct heap_page *right_page;
-
- left_page = *(struct heap_page * const *)left;
- right_page = *(struct heap_page * const *)right;
-
- return right_page->pinned_slots - left_page->pinned_slots;
-}
-
static int
compare_free_slots(const void *left, const void *right, void *dummy)
{
@@ -7776,114 +8704,39 @@ compare_free_slots(const void *left, const void *right, void *dummy)
left_page = *(struct heap_page * const *)left;
right_page = *(struct heap_page * const *)right;
- return right_page->free_slots - left_page->free_slots;
+ return left_page->free_slots - right_page->free_slots;
}
-typedef int page_compare_func_t(const void *, const void *, void *);
-
-static struct heap_page **
-allocate_page_list(rb_objspace_t *objspace, page_compare_func_t *comparator)
+static void
+gc_sort_heap_by_empty_slots(rb_objspace_t *objspace)
{
size_t total_pages = heap_eden->total_pages;
size_t size = size_mul_or_raise(total_pages, sizeof(struct heap_page *), rb_eRuntimeError);
struct heap_page *page = 0, **page_list = malloc(size);
- int i = 0;
+ size_t i = 0;
list_for_each(&heap_eden->pages, page, page_node) {
page_list[i++] = page;
- page->pinned_slots = count_pinned(page);
- GC_ASSERT(page != NULL);
+ assert(page != NULL);
}
- GC_ASSERT(total_pages > 0);
- GC_ASSERT((size_t)i == total_pages);
-
- ruby_qsort(page_list, total_pages, sizeof(struct heap_page *), comparator, NULL);
-
- return page_list;
-}
-
-static VALUE
-gc_compact_heap(rb_objspace_t *objspace, page_compare_func_t *comparator)
-{
- struct heap_cursor free_cursor;
- struct heap_cursor scan_cursor;
- struct heap_page **page_list;
- VALUE moved_list;
-
- moved_list = Qfalse;
- memset(objspace->rcompactor.considered_count_table, 0, T_MASK * sizeof(size_t));
- memset(objspace->rcompactor.moved_count_table, 0, T_MASK * sizeof(size_t));
-
- page_list = allocate_page_list(objspace, comparator);
-
- init_cursors(objspace, &free_cursor, &scan_cursor, page_list);
-
- /* Two finger algorithm */
- while (not_met(&free_cursor, &scan_cursor)) {
- /* Free cursor movement */
-
- /* Unpoison free_cursor slot */
- void *free_slot_poison = asan_poisoned_object_p((VALUE)free_cursor.slot);
- asan_unpoison_object((VALUE)free_cursor.slot, false);
-
- while (BUILTIN_TYPE(free_cursor.slot) != T_NONE && not_met(&free_cursor, &scan_cursor)) {
- /* Re-poison slot if it's not the one we want */
- if (free_slot_poison) {
- GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) == T_NONE);
- asan_poison_object((VALUE)free_cursor.slot);
- }
-
- advance_cursor(&free_cursor, page_list);
-
- /* Unpoison free_cursor slot */
- free_slot_poison = asan_poisoned_object_p((VALUE)free_cursor.slot);
- asan_unpoison_object((VALUE)free_cursor.slot, false);
- }
-
- /* Unpoison scan_cursor slot */
- void *scan_slot_poison = asan_poisoned_object_p((VALUE)scan_cursor.slot);
- asan_unpoison_object((VALUE)scan_cursor.slot, false);
-
- /* Scan cursor movement */
- objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++;
-
- while (!gc_is_moveable_obj(objspace, (VALUE)scan_cursor.slot) && not_met(&free_cursor, &scan_cursor)) {
-
- /* Re-poison slot if it's not the one we want */
- if (scan_slot_poison) {
- GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) == T_NONE);
- asan_poison_object((VALUE)scan_cursor.slot);
- }
-
- retreat_cursor(&scan_cursor, page_list);
-
- /* Unpoison scan_cursor slot */
- scan_slot_poison = asan_poisoned_object_p((VALUE)scan_cursor.slot);
- asan_unpoison_object((VALUE)scan_cursor.slot, false);
-
- objspace->rcompactor.considered_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++;
- }
-
- if (not_met(&free_cursor, &scan_cursor)) {
- objspace->rcompactor.moved_count_table[BUILTIN_TYPE((VALUE)scan_cursor.slot)]++;
-
- GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) == T_NONE);
- GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) != T_NONE);
- GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) != T_MOVED);
+ assert(total_pages > 0);
+ assert((size_t)i == total_pages);
- moved_list = gc_move(objspace, (VALUE)scan_cursor.slot, (VALUE)free_cursor.slot, moved_list);
+ /* Sort the heap so "filled pages" are first. `heap_add_page` adds to the
+ * head of the list, so empty pages will end up at the start of the heap */
+ ruby_qsort(page_list, total_pages, sizeof(struct heap_page *), compare_free_slots, NULL);
- GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) != T_MOVED);
- GC_ASSERT(BUILTIN_TYPE(free_cursor.slot) != T_NONE);
- GC_ASSERT(BUILTIN_TYPE(scan_cursor.slot) == T_MOVED);
+ /* Reset the eden heap */
+ list_head_init(&objspace->eden_heap.pages);
- advance_cursor(&free_cursor, page_list);
- retreat_cursor(&scan_cursor, page_list);
+ for (i = 0; i < total_pages; i++) {
+ list_add(&heap_eden->pages, &page_list[i]->page_node);
+ if (page_list[i]->free_slots != 0) {
+ heap_add_freepage(heap_eden, page_list[i]);
}
}
- free(page_list);
- return moved_list;
+ free(page_list);
}
static void
@@ -7908,11 +8761,9 @@ gc_ref_update_object(rb_objspace_t * objspace, VALUE v)
{
VALUE *ptr = ROBJECT_IVPTR(v);
- if (ptr) {
- uint32_t i, len = ROBJECT_NUMIV(v);
- for (i = 0; i < len; i++) {
- UPDATE_IF_MOVED(objspace, ptr[i]);
- }
+ uint32_t i, len = ROBJECT_NUMIV(v);
+ for (i = 0; i < len; i++) {
+ UPDATE_IF_MOVED(objspace, ptr[i]);
}
}
@@ -8100,8 +8951,33 @@ gc_ref_update_imemo(rb_objspace_t *objspace, VALUE obj)
case imemo_ast:
rb_ast_update_references((rb_ast_t *)obj);
break;
+ case imemo_callcache:
+ {
+ const struct rb_callcache *cc = (const struct rb_callcache *)obj;
+ if (cc->klass) {
+ UPDATE_IF_MOVED(objspace, cc->klass);
+ if (!is_live_object(objspace, cc->klass)) {
+ *((VALUE *)(&cc->klass)) = (VALUE)0;
+ }
+ }
+
+ if (cc->cme_) {
+ TYPED_UPDATE_IF_MOVED(objspace, struct rb_callable_method_entry_struct *, cc->cme_);
+ if (!is_live_object(objspace, (VALUE)cc->cme_)) {
+ *((struct rb_callable_method_entry_struct **)(&cc->cme_)) = (struct rb_callable_method_entry_struct *)0;
+ }
+ }
+ }
+ break;
+ case imemo_constcache:
+ {
+ const struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)obj;
+ UPDATE_IF_MOVED(objspace, ice->value);
+ }
+ break;
case imemo_parser_strterm:
case imemo_tmpbuf:
+ case imemo_callinfo:
break;
default:
rb_bug("not reachable %d", imemo_type(obj));
@@ -8129,7 +9005,7 @@ rb_gc_location(VALUE value)
VALUE destination;
- if (!SPECIAL_CONST_P((void *)value)) {
+ if (!SPECIAL_CONST_P(value)) {
void *poisoned = asan_poisoned_object_p(value);
asan_unpoison_object(value, false);
@@ -8175,6 +9051,39 @@ update_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
}
static enum rb_id_table_iterator_result
+update_cc_tbl_i(ID id, VALUE ccs_ptr, void *data)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)data;
+ struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
+ VM_ASSERT(vm_ccs_p(ccs));
+
+ if (gc_object_moved_p(objspace, (VALUE)ccs->cme)) {
+ ccs->cme = (const rb_callable_method_entry_t *)rb_gc_location((VALUE)ccs->cme);
+ }
+
+ for (int i=0; i<ccs->len; i++) {
+ if (gc_object_moved_p(objspace, (VALUE)ccs->entries[i].ci)) {
+ ccs->entries[i].ci = (struct rb_callinfo *)rb_gc_location((VALUE)ccs->entries[i].ci);
+ }
+ if (gc_object_moved_p(objspace, (VALUE)ccs->entries[i].cc)) {
+ ccs->entries[i].cc = (struct rb_callcache *)rb_gc_location((VALUE)ccs->entries[i].cc);
+ }
+ }
+
+ // do not replace
+ return ID_TABLE_CONTINUE;
+}
+
+static void
+update_cc_tbl(rb_objspace_t *objspace, VALUE klass)
+{
+ struct rb_id_table *tbl = RCLASS_CC_TBL(klass);
+ if (tbl) {
+ rb_id_table_foreach_with_replace(tbl, update_cc_tbl_i, 0, objspace);
+ }
+}
+
+static enum rb_id_table_iterator_result
update_const_table(VALUE value, void *data)
{
rb_const_entry_t *ce = (rb_const_entry_t *)value;
@@ -8207,12 +9116,26 @@ update_subclass_entries(rb_objspace_t *objspace, rb_subclass_entry_t *entry)
}
}
+static int
+update_iv_index_tbl_i(st_data_t key, st_data_t value, st_data_t arg)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)arg;
+ struct rb_iv_index_tbl_entry *ent = (struct rb_iv_index_tbl_entry *)value;
+ UPDATE_IF_MOVED(objspace, ent->class_value);
+ return ST_CONTINUE;
+}
+
static void
update_class_ext(rb_objspace_t *objspace, rb_classext_t *ext)
{
UPDATE_IF_MOVED(objspace, ext->origin_);
UPDATE_IF_MOVED(objspace, ext->refined_class);
update_subclass_entries(objspace, ext->subclasses);
+
+ // ext->iv_index_tbl
+ if (ext->iv_index_tbl) {
+ st_foreach(ext->iv_index_tbl, update_iv_index_tbl_i, (st_data_t)objspace);
+ }
}
static void
@@ -8220,7 +9143,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
{
RVALUE *any = RANY(obj);
- gc_report(4, objspace, "update-refs: %p ->", (void *)obj);
+ gc_report(4, objspace, "update-refs: %p ->\n", (void *)obj);
switch (BUILTIN_TYPE(obj)) {
case T_CLASS:
@@ -8230,13 +9153,17 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
}
if (!RCLASS_EXT(obj)) break;
update_m_tbl(objspace, RCLASS_M_TBL(obj));
+ update_cc_tbl(objspace, obj);
+
gc_update_tbl_refs(objspace, RCLASS_IV_TBL(obj));
+
update_class_ext(objspace, RCLASS_EXT(obj));
update_const_tbl(objspace, RCLASS_CONST_TBL(obj));
break;
case T_ICLASS:
- if (FL_TEST(obj, RICLASS_IS_ORIGIN)) {
+ if (FL_TEST(obj, RICLASS_IS_ORIGIN) &&
+ !FL_TEST(obj, RICLASS_ORIGIN_SHARED_MTBL)) {
update_m_tbl(objspace, RCLASS_M_TBL(obj));
}
if (RCLASS_SUPER((VALUE)obj)) {
@@ -8248,6 +9175,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
}
update_class_ext(objspace, RCLASS_EXT(obj));
update_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
+ update_cc_tbl(objspace, obj);
break;
case T_IMEMO:
@@ -8301,6 +9229,7 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
case T_FILE:
if (any->as.file.fptr) {
+ UPDATE_IF_MOVED(objspace, any->as.file.fptr->self);
UPDATE_IF_MOVED(objspace, any->as.file.fptr->pathv);
UPDATE_IF_MOVED(objspace, any->as.file.fptr->tied_io_for_writing);
UPDATE_IF_MOVED(objspace, any->as.file.fptr->writeconv_asciicompat);
@@ -8364,58 +9293,49 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
UPDATE_IF_MOVED(objspace, RBASIC(obj)->klass);
- gc_report(4, objspace, "update-refs: %p <-", (void *)obj);
+ gc_report(4, objspace, "update-refs: %p <-\n", (void *)obj);
}
static int
-gc_ref_update(void *vstart, void *vend, size_t stride, void * data)
+gc_ref_update(void *vstart, void *vend, size_t stride, rb_objspace_t * objspace, struct heap_page *page)
{
- rb_objspace_t * objspace;
- struct heap_page *page;
- short free_slots = 0;
-
VALUE v = (VALUE)vstart;
- objspace = (rb_objspace_t *)data;
- page = GET_HEAP_PAGE(v);
asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
- page->freelist = NULL;
asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
page->flags.has_uncollectible_shady_objects = FALSE;
page->flags.has_remembered_objects = FALSE;
/* For each object on the page */
for (; v != (VALUE)vend; v += stride) {
- if (!SPECIAL_CONST_P(v)) {
- void *poisoned = asan_poisoned_object_p(v);
- asan_unpoison_object(v, false);
+ void *poisoned = asan_poisoned_object_p(v);
+ asan_unpoison_object(v, false);
- switch (BUILTIN_TYPE(v)) {
- case T_NONE:
- heap_page_add_freeobj(objspace, page, v);
- free_slots++;
- break;
- case T_MOVED:
- break;
- case T_ZOMBIE:
- break;
- default:
- if (RVALUE_WB_UNPROTECTED(v)) {
- page->flags.has_uncollectible_shady_objects = TRUE;
- }
- if (RVALUE_PAGE_MARKING(page, v)) {
- page->flags.has_remembered_objects = TRUE;
+ switch (BUILTIN_TYPE(v)) {
+ case T_NONE:
+ case T_MOVED:
+ case T_ZOMBIE:
+ break;
+ default:
+ if (RVALUE_WB_UNPROTECTED(v)) {
+ page->flags.has_uncollectible_shady_objects = TRUE;
+ }
+ if (RVALUE_PAGE_MARKING(page, v)) {
+ page->flags.has_remembered_objects = TRUE;
+ }
+ if (page->flags.before_sweep) {
+ if (RVALUE_MARKED(v)) {
+ gc_update_object_references(objspace, v);
}
+ } else {
gc_update_object_references(objspace, v);
}
+ }
- if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(v) == T_NONE);
- asan_poison_object(v);
- }
+ if (poisoned) {
+ asan_poison_object(v);
}
}
- page->free_slots = free_slots;
return 0;
}
@@ -8423,14 +9343,26 @@ extern rb_symbols_t ruby_global_symbols;
#define global_symbols ruby_global_symbols
static void
-gc_update_references(rb_objspace_t * objspace)
+gc_update_references(rb_objspace_t * objspace, rb_heap_t *heap)
{
rb_execution_context_t *ec = GET_EC();
rb_vm_t *vm = rb_ec_vm_ptr(ec);
+ short should_set_mark_bits = 1;
+
+ struct heap_page *page = NULL;
- objspace_each_objects_without_setup(objspace, gc_ref_update, objspace);
+ list_for_each(&heap->pages, page, page_node) {
+ gc_ref_update(page->start, page->start + page->total_slots, sizeof(RVALUE), objspace, page);
+ if (page == heap->sweeping_page) {
+ should_set_mark_bits = 0;
+ }
+ if (should_set_mark_bits) {
+ gc_setup_mark_bits(page);
+ }
+ }
rb_vm_update_references(vm);
rb_transient_heap_update_references();
+ rb_gc_update_global_tbl();
global_symbols.ids = rb_gc_location(global_symbols.ids);
global_symbols.dsymbol_fstr_hash = rb_gc_location(global_symbols.dsymbol_fstr_hash);
gc_update_tbl_refs(objspace, objspace->obj_to_id_tbl);
@@ -8442,19 +9374,22 @@ gc_update_references(rb_objspace_t * objspace)
static VALUE type_sym(size_t type);
static VALUE
-gc_compact_stats(rb_objspace_t *objspace)
+gc_compact_stats(rb_execution_context_t *ec, 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();
for (i=0; i<T_MASK; i++) {
- rb_hash_aset(considered, type_sym(i), SIZET2NUM(objspace->rcompactor.considered_count_table[i]));
- }
+ if(objspace->rcompactor.considered_count_table[i]) {
+ rb_hash_aset(considered, type_sym(i), SIZET2NUM(objspace->rcompactor.considered_count_table[i]));
+ }
- for (i=0; i<T_MASK; i++) {
- rb_hash_aset(moved, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_count_table[i]));
+ if(objspace->rcompactor.moved_count_table[i]) {
+ rb_hash_aset(moved, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_count_table[i]));
+ }
}
rb_hash_aset(h, ID2SYM(rb_intern("considered")), considered);
@@ -8463,32 +9398,6 @@ gc_compact_stats(rb_objspace_t *objspace)
return h;
}
-static void gc_compact_after_gc(rb_objspace_t *objspace, int use_toward_empty, int use_double_pages, int use_verifier);
-
-static void
-gc_compact(rb_objspace_t *objspace, int use_toward_empty, int use_double_pages, int use_verifier)
-{
-
- objspace->flags.during_compacting = TRUE;
- {
- /* pin objects referenced by maybe pointers */
- garbage_collect(objspace, GPR_DEFAULT_REASON);
- /* compact */
- gc_compact_after_gc(objspace, use_toward_empty, use_double_pages, use_verifier);
- }
- objspace->flags.during_compacting = FALSE;
-}
-
-static VALUE
-rb_gc_compact(rb_execution_context_t *ec, VALUE self)
-{
- rb_objspace_t *objspace = &rb_objspace;
- if (dont_gc) return Qnil;
-
- gc_compact(objspace, FALSE, FALSE, FALSE);
- return gc_compact_stats(objspace);
-}
-
static void
root_obj_check_moved_i(const char *category, VALUE obj, void *data)
{
@@ -8523,7 +9432,9 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
case T_ZOMBIE:
break;
default:
- rb_objspace_reachable_objects_from(v, reachable_object_check_moved_i, (void *)v);
+ if (!rb_objspace_garbage_object_p(v)) {
+ rb_objspace_reachable_objects_from(v, reachable_object_check_moved_i, (void *)v);
+ }
}
if (poisoned) {
@@ -8537,151 +9448,42 @@ heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
}
static VALUE
-gc_check_references_for_moved(rb_objspace_t *objspace)
+gc_compact(rb_execution_context_t *ec, VALUE self)
{
- objspace_reachable_objects_from_root(objspace, root_obj_check_moved_i, NULL);
- objspace_each_objects(objspace, heap_check_moved_i, NULL);
- return Qnil;
-}
-
-static void
-gc_compact_after_gc(rb_objspace_t *objspace, int use_toward_empty, int use_double_pages, int use_verifier)
-{
- if (0) fprintf(stderr, "gc_compact_after_gc: %d,%d,%d\n", use_toward_empty, use_double_pages, use_verifier);
-
- mjit_gc_start_hook(); // prevent MJIT from running while moving pointers related to ISeq
-
- objspace->profile.compact_count++;
-
- if (use_verifier) {
- gc_verify_internal_consistency(objspace);
- }
+ /* Run GC with compaction enabled */
+ gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue);
- if (use_double_pages) {
- /* Double heap size */
- heap_add_pages(objspace, heap_eden, heap_allocated_pages);
- }
-
- VALUE moved_list_head;
- VALUE disabled = rb_objspace_gc_disable(objspace);
-
- if (use_toward_empty) {
- moved_list_head = gc_compact_heap(objspace, compare_free_slots);
- }
- else {
- moved_list_head = gc_compact_heap(objspace, compare_pinned);
- }
- heap_eden->freelist = NULL;
-
- gc_update_references(objspace);
- if (!RTEST(disabled)) rb_objspace_gc_enable(objspace);
-
- if (use_verifier) {
- gc_check_references_for_moved(objspace);
- }
-
- rb_clear_method_cache_by_class(rb_cObject);
- rb_clear_constant_cache();
- heap_eden->free_pages = NULL;
- heap_eden->using_page = NULL;
-
- /* For each moved slot */
- while (moved_list_head) {
- VALUE next_moved;
- struct heap_page *page;
-
- page = GET_HEAP_PAGE(moved_list_head);
- next_moved = RMOVED(moved_list_head)->next;
-
- /* clear the memory for that moved slot */
- RMOVED(moved_list_head)->flags = 0;
- RMOVED(moved_list_head)->destination = 0;
- RMOVED(moved_list_head)->next = 0;
- page->free_slots++;
- heap_page_add_freeobj(objspace, page, moved_list_head);
-
- if (page->free_slots == page->total_slots && heap_pages_freeable_pages > 0) {
- heap_pages_freeable_pages--;
- heap_unlink_page(objspace, heap_eden, page);
- heap_add_page(objspace, heap_tomb, page);
- }
- objspace->profile.total_freed_objects++;
- moved_list_head = next_moved;
- }
-
- /* Add any eden pages with free slots back to the free pages list */
- struct heap_page *page = NULL;
- list_for_each(&heap_eden->pages, page, page_node) {
- if (page->free_slots > 0) {
- heap_add_freepage(heap_eden, page);
- } else {
- page->free_next = NULL;
- }
- }
-
- /* Set up "using_page" if we have any pages with free slots */
- if (heap_eden->free_pages) {
- heap_eden->using_page = heap_eden->free_pages;
- heap_eden->free_pages = heap_eden->free_pages->free_next;
- }
-
- if (use_verifier) {
- gc_verify_internal_consistency(objspace);
- }
-
- mjit_gc_exit_hook(); // unlock MJIT here, because `rb_gc()` calls `mjit_gc_start_hook()` again.
+ return gc_compact_stats(ec, self);
}
-/*
- * call-seq:
- * GC.verify_compaction_references(toward: nil, double_heap: nil) -> nil
- *
- * Verify compaction reference consistency.
- *
- * This method is implementation specific. During compaction, objects that
- * were moved are replaced with T_MOVED objects. No object should have a
- * reference to a T_MOVED object after compaction.
- *
- * This function doubles the heap to ensure room to move all objects,
- * compacts the heap to make sure everything moves, updates all references,
- * then performs a full GC. If any object contains a reference to a T_MOVED
- * object, that object should be pushed on the mark stack, and will
- * make a SEGV.
- */
static VALUE
-gc_verify_compaction_references(int argc, VALUE *argv, VALUE mod)
+gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE double_heap, VALUE toward_empty)
{
rb_objspace_t *objspace = &rb_objspace;
- int use_toward_empty = FALSE;
- int use_double_pages = FALSE;
-
- if (dont_gc) return Qnil;
-
- VALUE opt = Qnil;
- static ID keyword_ids[2];
- VALUE kwvals[2];
- kwvals[1] = Qtrue;
+ /* Clear the heap. */
+ gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qfalse);
- rb_scan_args(argc, argv, "0:", &opt);
+ RB_VM_LOCK_ENTER();
+ {
+ gc_rest(objspace);
- if (!NIL_P(opt)) {
- if (!keyword_ids[0]) {
- keyword_ids[0] = rb_intern("toward");
- keyword_ids[1] = rb_intern("double_heap");
+ if (RTEST(double_heap)) {
+ heap_add_pages(objspace, heap_eden, heap_allocated_pages);
}
- rb_get_kwargs(opt, keyword_ids, 0, 2, kwvals);
- if (kwvals[0] != Qundef && rb_intern("empty") == rb_sym2id(kwvals[0])) {
- use_toward_empty = TRUE;
- }
- if (kwvals[1] != Qundef && RTEST(kwvals[1])) {
- use_double_pages = TRUE;
+ if (RTEST(toward_empty)) {
+ gc_sort_heap_by_empty_slots(objspace);
}
}
+ RB_VM_LOCK_LEAVE();
+
+ gc_start_internal(ec, self, Qtrue, Qtrue, Qtrue, Qtrue);
+
+ objspace_reachable_objects_from_root(objspace, root_obj_check_moved_i, NULL);
+ objspace_each_objects(objspace, heap_check_moved_i, NULL);
- gc_compact(objspace, use_toward_empty, use_double_pages, TRUE);
- return gc_compact_stats(objspace);
+ return gc_compact_stats(ec, self);
}
VALUE
@@ -8868,10 +9670,11 @@ enum gc_stat_sym {
gc_stat_sym_total_freed_objects,
gc_stat_sym_malloc_increase_bytes,
gc_stat_sym_malloc_increase_bytes_limit,
-#if USE_RGENGC
gc_stat_sym_minor_gc_count,
gc_stat_sym_major_gc_count,
gc_stat_sym_compact_count,
+ gc_stat_sym_read_barrier_faults,
+ gc_stat_sym_total_moved_objects,
gc_stat_sym_remembered_wb_unprotected_objects,
gc_stat_sym_remembered_wb_unprotected_objects_limit,
gc_stat_sym_old_objects,
@@ -8888,40 +9691,10 @@ enum gc_stat_sym {
gc_stat_sym_total_remembered_normal_object_count,
gc_stat_sym_total_remembered_shady_object_count,
#endif
-#endif
gc_stat_sym_last
};
-enum gc_stat_compat_sym {
- gc_stat_compat_sym_gc_stat_heap_used,
- gc_stat_compat_sym_heap_eden_page_length,
- gc_stat_compat_sym_heap_tomb_page_length,
- gc_stat_compat_sym_heap_increment,
- gc_stat_compat_sym_heap_length,
- gc_stat_compat_sym_heap_live_slot,
- gc_stat_compat_sym_heap_free_slot,
- gc_stat_compat_sym_heap_final_slot,
- gc_stat_compat_sym_heap_swept_slot,
-#if USE_RGENGC
- gc_stat_compat_sym_remembered_shady_object,
- gc_stat_compat_sym_remembered_shady_object_limit,
- gc_stat_compat_sym_old_object,
- gc_stat_compat_sym_old_object_limit,
-#endif
- gc_stat_compat_sym_total_allocated_object,
- gc_stat_compat_sym_total_freed_object,
- gc_stat_compat_sym_malloc_increase,
- gc_stat_compat_sym_malloc_limit,
-#if RGENGC_ESTIMATE_OLDMALLOC
- gc_stat_compat_sym_oldmalloc_increase,
- gc_stat_compat_sym_oldmalloc_limit,
-#endif
- gc_stat_compat_sym_last
-};
-
static VALUE gc_stat_symbols[gc_stat_sym_last];
-static VALUE gc_stat_compat_symbols[gc_stat_compat_sym_last];
-static VALUE gc_stat_compat_table;
static void
setup_gc_stat_symbols(void)
@@ -8945,10 +9718,11 @@ setup_gc_stat_symbols(void)
S(total_freed_objects);
S(malloc_increase_bytes);
S(malloc_increase_bytes_limit);
-#if USE_RGENGC
S(minor_gc_count);
S(major_gc_count);
S(compact_count);
+ S(read_barrier_faults);
+ S(total_moved_objects);
S(remembered_wb_unprotected_objects);
S(remembered_wb_unprotected_objects_limit);
S(old_objects);
@@ -8965,106 +9739,10 @@ setup_gc_stat_symbols(void)
S(total_remembered_normal_object_count);
S(total_remembered_shady_object_count);
#endif /* RGENGC_PROFILE */
-#endif /* USE_RGENGC */
#undef S
-#define S(s) gc_stat_compat_symbols[gc_stat_compat_sym_##s] = ID2SYM(rb_intern_const(#s))
- S(gc_stat_heap_used);
- S(heap_eden_page_length);
- S(heap_tomb_page_length);
- S(heap_increment);
- S(heap_length);
- S(heap_live_slot);
- S(heap_free_slot);
- S(heap_final_slot);
- S(heap_swept_slot);
-#if USE_RGEGC
- S(remembered_shady_object);
- S(remembered_shady_object_limit);
- S(old_object);
- S(old_object_limit);
-#endif
- S(total_allocated_object);
- S(total_freed_object);
- S(malloc_increase);
- S(malloc_limit);
-#if RGENGC_ESTIMATE_OLDMALLOC
- S(oldmalloc_increase);
- S(oldmalloc_limit);
-#endif
-#undef S
-
- {
- VALUE table = gc_stat_compat_table = rb_hash_new();
- rb_obj_hide(table);
- rb_gc_register_mark_object(table);
-
- /* compatibility layer for Ruby 2.1 */
-#define OLD_SYM(s) gc_stat_compat_symbols[gc_stat_compat_sym_##s]
-#define NEW_SYM(s) gc_stat_symbols[gc_stat_sym_##s]
- rb_hash_aset(table, OLD_SYM(gc_stat_heap_used), NEW_SYM(heap_allocated_pages));
- rb_hash_aset(table, OLD_SYM(heap_eden_page_length), NEW_SYM(heap_eden_pages));
- rb_hash_aset(table, OLD_SYM(heap_tomb_page_length), NEW_SYM(heap_tomb_pages));
- rb_hash_aset(table, OLD_SYM(heap_increment), NEW_SYM(heap_allocatable_pages));
- rb_hash_aset(table, OLD_SYM(heap_length), NEW_SYM(heap_sorted_length));
- rb_hash_aset(table, OLD_SYM(heap_live_slot), NEW_SYM(heap_live_slots));
- rb_hash_aset(table, OLD_SYM(heap_free_slot), NEW_SYM(heap_free_slots));
- rb_hash_aset(table, OLD_SYM(heap_final_slot), NEW_SYM(heap_final_slots));
-#if USE_RGEGC
- rb_hash_aset(table, OLD_SYM(remembered_shady_object), NEW_SYM(remembered_wb_unprotected_objects));
- rb_hash_aset(table, OLD_SYM(remembered_shady_object_limit), NEW_SYM(remembered_wb_unprotected_objects_limit));
- rb_hash_aset(table, OLD_SYM(old_object), NEW_SYM(old_objects));
- rb_hash_aset(table, OLD_SYM(old_object_limit), NEW_SYM(old_objects_limit));
-#endif
- rb_hash_aset(table, OLD_SYM(total_allocated_object), NEW_SYM(total_allocated_objects));
- rb_hash_aset(table, OLD_SYM(total_freed_object), NEW_SYM(total_freed_objects));
- rb_hash_aset(table, OLD_SYM(malloc_increase), NEW_SYM(malloc_increase_bytes));
- rb_hash_aset(table, OLD_SYM(malloc_limit), NEW_SYM(malloc_increase_bytes_limit));
-#if RGENGC_ESTIMATE_OLDMALLOC
- rb_hash_aset(table, OLD_SYM(oldmalloc_increase), NEW_SYM(oldmalloc_increase_bytes));
- rb_hash_aset(table, OLD_SYM(oldmalloc_limit), NEW_SYM(oldmalloc_increase_bytes_limit));
-#endif
-#undef OLD_SYM
-#undef NEW_SYM
- rb_obj_freeze(table);
- }
}
}
-static VALUE
-compat_key(VALUE key)
-{
- VALUE new_key = rb_hash_lookup(gc_stat_compat_table, key);
-
- if (!NIL_P(new_key)) {
- static int warned = 0;
- if (warned == 0) {
- rb_warn("GC.stat keys were changed from Ruby 2.1. "
- "In this case, you refer to obsolete `%"PRIsVALUE"' (new key is `%"PRIsVALUE"'). "
- "Please check <https://bugs.ruby-lang.org/issues/9924> for more information.",
- key, new_key);
- warned = 1;
- }
- }
-
- return new_key;
-}
-
-static VALUE
-default_proc_for_compat_func(RB_BLOCK_CALL_FUNC_ARGLIST(hash, _))
-{
- VALUE key, new_key;
-
- Check_Type(hash, T_HASH);
- rb_check_arity(argc, 2, 2);
- key = argv[1];
-
- if ((new_key = compat_key(key)) != Qnil) {
- return rb_hash_lookup(hash, new_key);
- }
-
- return Qnil;
-}
-
static size_t
gc_stat_internal(VALUE hash_or_sym)
{
@@ -9075,15 +9753,6 @@ gc_stat_internal(VALUE hash_or_sym)
if (RB_TYPE_P(hash_or_sym, T_HASH)) {
hash = hash_or_sym;
-
- if (NIL_P(RHASH_IFNONE(hash))) {
- static VALUE default_proc_for_compat = 0;
- if (default_proc_for_compat == 0) { /* TODO: it should be */
- default_proc_for_compat = rb_proc_new(default_proc_for_compat_func, Qnil);
- rb_gc_register_mark_object(default_proc_for_compat);
- }
- rb_hash_set_default_proc(hash, default_proc_for_compat);
- }
}
else if (SYMBOL_P(hash_or_sym)) {
key = hash_or_sym;
@@ -9098,7 +9767,6 @@ gc_stat_internal(VALUE hash_or_sym)
else if (hash != Qnil) \
rb_hash_aset(hash, gc_stat_symbols[gc_stat_sym_##name], SIZET2NUM(attr));
- again:
SET(count, objspace->profile.count);
/* implementation dependent counters */
@@ -9118,10 +9786,11 @@ gc_stat_internal(VALUE hash_or_sym)
SET(total_freed_objects, objspace->profile.total_freed_objects);
SET(malloc_increase_bytes, malloc_increase);
SET(malloc_increase_bytes_limit, malloc_limit);
-#if USE_RGENGC
SET(minor_gc_count, objspace->profile.minor_gc_count);
SET(major_gc_count, objspace->profile.major_gc_count);
SET(compact_count, objspace->profile.compact_count);
+ SET(read_barrier_faults, objspace->profile.read_barrier_faults);
+ SET(total_moved_objects, objspace->rcompactor.total_moved);
SET(remembered_wb_unprotected_objects, objspace->rgengc.uncollectible_wb_unprotected_objects);
SET(remembered_wb_unprotected_objects_limit, objspace->rgengc.uncollectible_wb_unprotected_objects_limit);
SET(old_objects, objspace->rgengc.old_objects);
@@ -9139,15 +9808,9 @@ gc_stat_internal(VALUE hash_or_sym)
SET(total_remembered_normal_object_count, objspace->profile.total_remembered_normal_object_count);
SET(total_remembered_shady_object_count, objspace->profile.total_remembered_shady_object_count);
#endif /* RGENGC_PROFILE */
-#endif /* USE_RGENGC */
#undef SET
if (!NIL_P(key)) { /* matched key should return above */
- VALUE new_key;
- if ((new_key = compat_key(key)) != Qnil) {
- key = new_key;
- goto again;
- }
rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
}
@@ -9231,9 +9894,9 @@ rb_gc_enable(void)
VALUE
rb_objspace_gc_enable(rb_objspace_t *objspace)
{
- int old = dont_gc;
+ int old = dont_gc_val();
- dont_gc = FALSE;
+ dont_gc_off();
return old ? Qtrue : Qfalse;
}
@@ -9253,8 +9916,8 @@ rb_gc_disable_no_rest(void)
static VALUE
gc_disable_no_rest(rb_objspace_t *objspace)
{
- int old = dont_gc;
- dont_gc = TRUE;
+ int old = dont_gc_val();
+ dont_gc_on();
return old ? Qtrue : Qfalse;
}
@@ -9278,6 +9941,29 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
return rb_gc_disable();
}
+static VALUE
+gc_set_auto_compact(rb_execution_context_t *ec, VALUE _, VALUE v)
+{
+#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
+ /* If Ruby's heap pages are not a multiple of the system page size, we
+ * cannot use mprotect for the read barrier, so we must disable automatic
+ * compaction. */
+ int pagesize;
+ pagesize = (int)sysconf(_SC_PAGE_SIZE);
+ if ((HEAP_PAGE_SIZE % pagesize) != 0) {
+ rb_raise(rb_eNotImpError, "Automatic compaction isn't available on this platform");
+ }
+#endif
+ ruby_enable_autocompact = RTEST(v);
+ return v;
+}
+
+static VALUE
+gc_get_auto_compact(rb_execution_context_t *ec, VALUE _)
+{
+ return ruby_enable_autocompact ? Qtrue : Qfalse;
+}
+
static int
get_envparam_size(const char *name, size_t *default_value, size_t lower_bound)
{
@@ -9367,13 +10053,15 @@ get_envparam_double(const char *name, double *default_value, double lower_bound,
}
}
else {
- accept:
- if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%f (default value: %f)\n", name, val, *default_value);
- *default_value = val;
- return 1;
+ goto accept;
}
}
return 0;
+
+ accept:
+ if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%f (default value: %f)\n", name, val, *default_value);
+ *default_value = val;
+ return 1;
}
static void
@@ -9437,18 +10125,11 @@ ruby_gc_set_params(void)
if (get_envparam_size("RUBY_GC_HEAP_FREE_SLOTS", &gc_params.heap_free_slots, 0)) {
/* ok */
}
- else if (get_envparam_size("RUBY_FREE_MIN", &gc_params.heap_free_slots, 0)) {
- rb_warn("RUBY_FREE_MIN is obsolete. Use RUBY_GC_HEAP_FREE_SLOTS instead.");
- }
/* RUBY_GC_HEAP_INIT_SLOTS */
if (get_envparam_size("RUBY_GC_HEAP_INIT_SLOTS", &gc_params.heap_init_slots, 0)) {
gc_set_initial_pages();
}
- else if (get_envparam_size("RUBY_HEAP_MIN_SLOTS", &gc_params.heap_init_slots, 0)) {
- rb_warn("RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead.");
- gc_set_initial_pages();
- }
get_envparam_double("RUBY_GC_HEAP_GROWTH_FACTOR", &gc_params.growth_factor, 1.0, 0.0, FALSE);
get_envparam_size ("RUBY_GC_HEAP_GROWTH_MAX_SLOTS", &gc_params.growth_max_slots, 0);
@@ -9477,18 +10158,30 @@ ruby_gc_set_params(void)
#endif
}
+static void
+reachable_objects_from_callback(VALUE obj)
+{
+ rb_ractor_t *cr = GET_RACTOR();
+ cr->mfd->mark_func(obj, cr->mfd->data);
+}
+
void
rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data)
{
rb_objspace_t *objspace = &rb_objspace;
+ if (during_gc) rb_bug("rb_objspace_reachable_objects_from() is not supported while during_gc == true");
+
if (is_markable_object(objspace, obj)) {
- struct mark_func_data_struct mfd;
- mfd.mark_func = func;
- mfd.data = data;
- PUSH_MARK_FUNC_DATA(&mfd);
+ rb_ractor_t *cr = GET_RACTOR();
+ struct gc_mark_func_data_struct mfd = {
+ .mark_func = func,
+ .data = data,
+ }, *prev_mfd = cr->mfd;
+
+ cr->mfd = &mfd;
gc_mark_children(objspace, obj);
- POP_MARK_FUNC_DATA();
+ cr->mfd = prev_mfd;
}
}
@@ -9515,18 +10208,21 @@ rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE,
static void
objspace_reachable_objects_from_root(rb_objspace_t *objspace, void (func)(const char *category, VALUE, void *), void *passing_data)
{
- struct root_objects_data data;
- struct mark_func_data_struct mfd;
-
- data.func = func;
- data.data = passing_data;
+ if (during_gc) rb_bug("objspace_reachable_objects_from_root() is not supported while during_gc == true");
- mfd.mark_func = root_objects_from;
- mfd.data = &data;
+ rb_ractor_t *cr = GET_RACTOR();
+ struct root_objects_data data = {
+ .func = func,
+ .data = passing_data,
+ };
+ struct gc_mark_func_data_struct mfd = {
+ .mark_func = root_objects_from,
+ .data = &data,
+ }, *prev_mfd = cr->mfd;
- PUSH_MARK_FUNC_DATA(&mfd);
+ cr->mfd = &mfd;
gc_mark_roots(objspace, &data.category);
- POP_MARK_FUNC_DATA();
+ cr->mfd = prev_mfd;
}
/*
@@ -9568,10 +10264,10 @@ gc_raise(VALUE exc, const char *fmt, ...)
/* Not in a ruby thread */
fprintf(stderr, "%s", "[FATAL] ");
vfprintf(stderr, fmt, ap);
- abort();
}
va_end(ap);
+ abort();
}
static void objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t size);
@@ -9589,6 +10285,8 @@ ruby_memerror_body(void *dummy)
return 0;
}
+NORETURN(static void ruby_memerror(void));
+RBIMPL_ATTR_MAYBE_UNUSED()
static void
ruby_memerror(void)
{
@@ -9602,9 +10300,9 @@ ruby_memerror(void)
else {
/* no ruby thread */
fprintf(stderr, "[FATAL] failed to allocate memory\n");
- exit(EXIT_FAILURE);
}
}
+ exit(EXIT_FAILURE);
}
void
@@ -9620,7 +10318,10 @@ rb_memerror(void)
sleep(60);
}
- if (during_gc) gc_exit(objspace, "rb_memerror");
+ if (during_gc) {
+ // TODO: OMG!! How to implement it?
+ gc_exit(objspace, gc_enter_event_rb_memerror, NULL);
+ }
exc = nomem_error;
if (!exc ||
@@ -9747,7 +10448,7 @@ objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, si
if (type == MEMOP_TYPE_MALLOC) {
retry:
- if (malloc_increase > malloc_limit && ruby_native_thread_p() && !dont_gc) {
+ if (malloc_increase > malloc_limit && ruby_native_thread_p() && !dont_gc_val()) {
if (ruby_thread_has_gvl_p() && is_lazy_sweeping(heap_eden)) {
gc_rest(objspace); /* gc_rest can reduce malloc_increase */
goto retry;
@@ -9772,12 +10473,12 @@ objspace_malloc_increase(rb_objspace_t *objspace, void *mem, size_t new_size, si
atomic_sub_nounderflow(&objspace->malloc_params.allocated_size, dec_size);
}
- if (0) fprintf(stderr, "increase - ptr: %p, type: %s, new_size: %d, old_size: %d\n",
+ 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",
- (int)new_size, (int)old_size);
+ new_size, old_size);
switch (type) {
case MEMOP_TYPE_MALLOC:
@@ -9841,8 +10542,6 @@ objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
info->gen = objspace->profile.count;
info->file = ruby_malloc_info_file;
info->line = info->file ? ruby_malloc_info_line : 0;
-#else
- info->file = NULL;
#endif
mem = info + 1;
}
@@ -9851,7 +10550,37 @@ objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
return mem;
}
-#define TRY_WITH_GC(alloc) do { \
+#if defined(__GNUC__) && RUBY_DEBUG
+#define RB_BUG_INSTEAD_OF_RB_MEMERROR
+#endif
+
+#ifdef RB_BUG_INSTEAD_OF_RB_MEMERROR
+#define TRY_WITH_GC(siz, expr) do { \
+ const gc_profile_record_flag gpr = \
+ GPR_FLAG_FULL_MARK | \
+ GPR_FLAG_IMMEDIATE_MARK | \
+ GPR_FLAG_IMMEDIATE_SWEEP | \
+ GPR_FLAG_MALLOC; \
+ objspace_malloc_gc_stress(objspace); \
+ \
+ if (LIKELY((expr))) { \
+ /* Success on 1st try */ \
+ } \
+ else if (!garbage_collect_with_gvl(objspace, gpr)) { \
+ /* @shyouhei thinks this doesn't happen */ \
+ rb_bug("TRY_WITH_GC: could not GC"); \
+ } \
+ else if ((expr)) { \
+ /* Success on 2nd try */ \
+ } \
+ else { \
+ rb_bug("TRY_WITH_GC: could not allocate:" \
+ "%"PRIdSIZE" bytes for %s", \
+ siz, # expr); \
+ } \
+ } while (0)
+#else
+#define TRY_WITH_GC(siz, alloc) do { \
objspace_malloc_gc_stress(objspace); \
if (!(alloc) && \
(!garbage_collect_with_gvl(objspace, GPR_FLAG_FULL_MARK | \
@@ -9861,9 +10590,10 @@ objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
ruby_memerror(); \
} \
} while (0)
+#endif
/* these shouldn't be called directly.
- * objspace_* functinos do not check allocation size.
+ * objspace_* functions do not check allocation size.
*/
static void *
objspace_xmalloc0(rb_objspace_t *objspace, size_t size)
@@ -9871,7 +10601,7 @@ objspace_xmalloc0(rb_objspace_t *objspace, size_t size)
void *mem;
size = objspace_malloc_prepare(objspace, size);
- TRY_WITH_GC(mem = malloc(size));
+ TRY_WITH_GC(size, mem = malloc(size));
RB_DEBUG_COUNTER_INC(heap_xmalloc);
return objspace_malloc_fixup(objspace, mem, size);
}
@@ -9942,7 +10672,7 @@ objspace_xrealloc(rb_objspace_t *objspace, void *ptr, size_t new_size, size_t ol
#endif
old_size = objspace_malloc_size(objspace, ptr, old_size);
- TRY_WITH_GC(mem = realloc(ptr, new_size));
+ TRY_WITH_GC(new_size, mem = realloc(ptr, new_size));
new_size = objspace_malloc_size(objspace, mem, new_size);
#if CALC_EXACT_MALLOC_SIZE
@@ -9974,7 +10704,7 @@ mmalloc_info_file_i(st_data_t key, st_data_t val, st_data_t dmy)
const char *file = (void *)key;
const size_t *data = (void *)val;
- fprintf(stderr, "%s\t%d\t%d\n", file, (int)data[0], (int)data[1]);
+ fprintf(stderr, "%s\t%"PRIdSIZE"\t%"PRIdSIZE"\n", file, data[0], data[1]);
return ST_CONTINUE;
}
@@ -9988,19 +10718,19 @@ rb_malloc_info_show_results(void)
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%d\t%d\n", (int)malloc_info_gen_cnt[i], (int)malloc_info_gen_size[i]);
+ fprintf(stderr, "more\t%"PRIdSIZE"\t%"PRIdSIZE"\n", malloc_info_gen_cnt[i], malloc_info_gen_size[i]);
}
else {
- fprintf(stderr, "%d\t%d\t%d\n", i, (int)malloc_info_gen_cnt[i], (int)malloc_info_gen_size[i]);
+ 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%d\n", (int)s, (int)malloc_info_size[i]);
+ fprintf(stderr, "%d\t%"PRIdSIZE"\n", s, malloc_info_size[i]);
}
- fprintf(stderr, "more\t%d\n", (int)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");
@@ -10049,14 +10779,15 @@ objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t old_size)
found:;
{
- st_data_t key = (st_data_t)info->file;
+ st_data_t key = (st_data_t)info->file, d;
size_t *data;
if (malloc_info_file_table == NULL) {
malloc_info_file_table = st_init_numtable_with_size(1024);
}
- if (st_lookup(malloc_info_file_table, key, (st_data_t *)&data)) {
+ if (st_lookup(malloc_info_file_table, key, &d)) {
/* hit */
+ data = (size_t *)d;
}
else {
data = malloc(xmalloc2_size(2, sizeof(size_t)));
@@ -10067,16 +10798,16 @@ objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t old_size)
data[0] ++;
data[1] += info->size;
};
-#if 0 /* verbose output */
- if (gen >= 2) {
+ if (0 && gen >= 2) { /* verbose output */
if (info->file) {
- fprintf(stderr, "free - size:%d, gen:%d, pos: %s:%d\n", (int)info->size, gen, info->file, (int)info->line);
+ fprintf(stderr, "free - size:%"PRIdSIZE", gen:%d, pos: %s:%"PRIdSIZE"\n",
+ info->size, gen, info->file, info->line);
}
else {
- fprintf(stderr, "free - size:%d, gen:%d\n", (int)info->size, gen);
+ fprintf(stderr, "free - size:%"PRIdSIZE", gen:%d\n",
+ info->size, gen);
}
}
-#endif
}
#endif
#endif
@@ -10123,7 +10854,7 @@ objspace_xcalloc(rb_objspace_t *objspace, size_t size)
void *mem;
size = objspace_malloc_prepare(objspace, size);
- TRY_WITH_GC(mem = calloc1(size));
+ TRY_WITH_GC(size, mem = calloc1(size));
return objspace_malloc_fixup(objspace, mem, size);
}
@@ -10237,8 +10968,6 @@ ruby_mimmalloc(size_t size)
info->gen = 0;
info->file = NULL;
info->line = 0;
-#else
- info->file = NULL;
#endif
mem = info + 1;
}
@@ -10431,7 +11160,6 @@ static const rb_data_type_t weakmap_type = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
-extern const struct st_hash_type rb_hashtype_ident;
static VALUE wmap_finalize(RB_BLOCK_CALL_FUNC_ARGLIST(objid, self));
static VALUE
@@ -10439,8 +11167,8 @@ wmap_allocate(VALUE klass)
{
struct weakmap *w;
VALUE obj = TypedData_Make_Struct(klass, struct weakmap, &weakmap_type, w);
- w->obj2wmap = st_init_table(&rb_hashtype_ident);
- w->wmap2obj = st_init_table(&rb_hashtype_ident);
+ w->obj2wmap = rb_init_identtable();
+ w->wmap2obj = rb_init_identtable();
w->final = rb_func_lambda_new(wmap_finalize, obj, 1, 1);
return obj;
}
@@ -10448,9 +11176,20 @@ wmap_allocate(VALUE klass)
static int
wmap_live_p(rb_objspace_t *objspace, VALUE obj)
{
- if (!FL_ABLE(obj)) return TRUE;
- if (!is_id_value(objspace, obj)) return FALSE;
- if (!is_live_object(objspace, obj)) return FALSE;
+ if (SPECIAL_CONST_P(obj)) return TRUE;
+ if (is_pointer_to_heap(objspace, (void *)obj)) {
+ void *poisoned = asan_unpoison_object_temporary(obj);
+
+ enum ruby_value_type t = BUILTIN_TYPE(obj);
+ int ret = (!(t == T_NONE || t >= T_FIXNUM || t == T_ICLASS) &&
+ is_live_object(objspace, obj));
+
+ if (poisoned) {
+ asan_poison_object(obj);
+ }
+
+ return ret;
+ }
return TRUE;
}
@@ -10718,21 +11457,21 @@ wmap_aset_update(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
/* Creates a weak reference from the given key to the given value */
static VALUE
-wmap_aset(VALUE self, VALUE wmap, VALUE orig)
+wmap_aset(VALUE self, VALUE key, VALUE value)
{
struct weakmap *w;
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
- if (FL_ABLE(orig)) {
- define_final0(orig, w->final);
+ if (FL_ABLE(value)) {
+ define_final0(value, w->final);
}
- if (FL_ABLE(wmap)) {
- define_final0(wmap, w->final);
+ if (FL_ABLE(key)) {
+ define_final0(key, w->final);
}
- st_update(w->obj2wmap, (st_data_t)orig, wmap_aset_update, wmap);
- st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig);
- return nonspecial_obj_id(orig);
+ st_update(w->obj2wmap, (st_data_t)value, wmap_aset_update, key);
+ st_insert(w->wmap2obj, (st_data_t)key, (st_data_t)value);
+ return nonspecial_obj_id(value);
}
/* Retrieves a weakly referenced object with the given key */
@@ -11116,6 +11855,7 @@ gc_profile_record_get(VALUE _)
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_SIZE")), SIZET2NUM(record->heap_use_size));
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_SIZE")), SIZET2NUM(record->heap_total_size));
rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_TOTAL_OBJECTS")), SIZET2NUM(record->heap_total_objects));
+ rb_hash_aset(prof, ID2SYM(rb_intern("MOVED_OBJECTS")), SIZET2NUM(record->moved_objects));
rb_hash_aset(prof, ID2SYM(rb_intern("GC_IS_MARKED")), Qtrue);
#if GC_PROFILE_MORE_DETAIL
rb_hash_aset(prof, ID2SYM(rb_intern("GC_MARK_TIME")), DBL2NUM(record->gc_mark_time));
@@ -11199,7 +11939,7 @@ gc_profile_dump_on(VALUE out, VALUE (*append)(VALUE, VALUE))
}
#if GC_PROFILE_MORE_DETAIL
- append(out, rb_str_new_cstr("\n\n" \
+ const char *str = "\n\n" \
"More detail.\n" \
"Prepare Time = Previously GC's rest sweep time\n"
"Index Flags Allocate Inc. Allocate Limit"
@@ -11213,7 +11953,8 @@ gc_profile_dump_on(VALUE out, VALUE (*append)(VALUE, VALUE))
#if GC_PROFILE_DETAIL_MEMORY
" MaxRSS(KB) MinorFLT MajorFLT"
#endif
- "\n"));
+ "\n";
+ append(out, rb_str_new_cstr(str));
for (i = 0; i < count; i++) {
record = &objspace->profile.records[i];
@@ -11473,10 +12214,23 @@ rb_raw_iseq_info(char *buff, const int buff_size, const rb_iseq_t *iseq)
}
}
+bool rb_ractor_p(VALUE rv);
+
+static int
+str_len_no_raise(VALUE str)
+{
+ long len = RSTRING_LEN(str);
+ if (len < 0) return 0;
+ if (len > INT_MAX) return INT_MAX;
+ return (int)len;
+}
+
const char *
rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
{
int pos = 0;
+ void *poisoned = asan_poisoned_object_p(obj);
+ asan_unpoison_object(obj, false);
#define BUFF_ARGS buff + pos, buff_size - pos
#define APPENDF(f) if ((pos += snprintf f) >= buff_size) goto end
@@ -11494,7 +12248,6 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
#define TF(c) ((c) != 0 ? "true" : "false")
#define C(c, s) ((c) != 0 ? (s) : " ")
const int type = BUILTIN_TYPE(obj);
-#if USE_RGENGC
const int age = RVALUE_FLAGS_AGE(RBASIC(obj)->flags);
if (is_pointer_to_heap(&rb_objspace, (void *)obj)) {
@@ -11513,12 +12266,6 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
(void *)obj, age,
obj_type_name(obj)));
}
-#else
- APPENDF((BUFF_ARGS, "%p [%s] %s",
- (void *)obj,
- C(RVALUE_MARK_BITMAP(obj), "M"),
- obj_type_name(obj)));
-#endif
if (internal_object_p(obj)) {
/* ignore */
@@ -11549,34 +12296,46 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
rb_obj_info(RARRAY(obj)->as.heap.aux.shared_root)));
}
else if (FL_TEST(obj, RARRAY_EMBED_FLAG)) {
- APPENDF((BUFF_ARGS, "[%s%s] len: %d (embed)",
+ APPENDF((BUFF_ARGS, "[%s%s] len: %ld (embed)",
C(ARY_EMBED_P(obj), "E"),
C(ARY_SHARED_P(obj), "S"),
- (int)RARRAY_LEN(obj)));
+ RARRAY_LEN(obj)));
}
else {
- APPENDF((BUFF_ARGS, "[%s%s%s] len: %d, capa:%d ptr:%p",
+ APPENDF((BUFF_ARGS, "[%s%s%s] len: %ld, capa:%ld ptr:%p",
C(ARY_EMBED_P(obj), "E"),
C(ARY_SHARED_P(obj), "S"),
C(RARRAY_TRANSIENT_P(obj), "T"),
- (int)RARRAY_LEN(obj),
- ARY_EMBED_P(obj) ? -1 : (int)RARRAY(obj)->as.heap.aux.capa,
+ RARRAY_LEN(obj),
+ ARY_EMBED_P(obj) ? -1L : RARRAY(obj)->as.heap.aux.capa,
(void *)RARRAY_CONST_PTR_TRANSIENT(obj)));
}
break;
case T_STRING: {
- APPENDF((BUFF_ARGS, "%s", RSTRING_PTR(obj)));
+ if (STR_SHARED_P(obj)) APPENDF((BUFF_ARGS, " [shared] "));
+ APPENDF((BUFF_ARGS, "%.*s", str_len_no_raise(obj), RSTRING_PTR(obj)));
break;
}
+ case T_SYMBOL: {
+ VALUE fstr = RSYMBOL(obj)->fstr;
+ ID id = RSYMBOL(obj)->id;
+ if (RB_TYPE_P(fstr, T_STRING)) {
+ APPENDF((BUFF_ARGS, ":%s id:%d", RSTRING_PTR(fstr), (unsigned int)id));
+ }
+ else {
+ APPENDF((BUFF_ARGS, "(%p) id:%d", (void *)fstr, (unsigned int)id));
+ }
+ break;
+ }
case T_MOVED: {
APPENDF((BUFF_ARGS, "-> %p", (void*)rb_gc_location(obj)));
break;
}
case T_HASH: {
- APPENDF((BUFF_ARGS, "[%c%c] %d",
+ APPENDF((BUFF_ARGS, "[%c%c] %"PRIdSIZE,
RHASH_AR_TABLE_P(obj) ? 'A' : 'S',
RHASH_TRANSIENT_P(obj) ? 'T' : ' ',
- (int)RHASH_SIZE(obj)));
+ RHASH_SIZE(obj)));
break;
}
case T_CLASS:
@@ -11586,6 +12345,9 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
if (!NIL_P(class_path)) {
APPENDF((BUFF_ARGS, "%s", RSTRING_PTR(class_path)));
}
+ else {
+ APPENDF((BUFF_ARGS, "(annon)"));
+ }
break;
}
case T_ICLASS:
@@ -11618,6 +12380,12 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
(iseq = vm_block_iseq(block)) != NULL) {
rb_raw_iseq_info(BUFF_ARGS, iseq);
}
+ else if (rb_ractor_p(obj)) {
+ rb_ractor_t *r = (void *)DATA_PTR(obj);
+ if (r) {
+ APPENDF((BUFF_ARGS, "r:%d", r->pub.id));
+ }
+ }
else {
const char * const type_name = rb_objspace_data_type_name(obj);
if (type_name) {
@@ -11627,35 +12395,28 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
break;
}
case T_IMEMO: {
- const char *imemo_name = "\0";
- switch (imemo_type(obj)) {
-#define IMEMO_NAME(x) case imemo_##x: imemo_name = #x; break;
- IMEMO_NAME(env);
- IMEMO_NAME(cref);
- IMEMO_NAME(svar);
- IMEMO_NAME(throw_data);
- IMEMO_NAME(ifunc);
- IMEMO_NAME(memo);
- IMEMO_NAME(ment);
- IMEMO_NAME(iseq);
- IMEMO_NAME(tmpbuf);
- IMEMO_NAME(ast);
- IMEMO_NAME(parser_strterm);
-#undef IMEMO_NAME
- default: UNREACHABLE;
- }
- APPENDF((BUFF_ARGS, "/%s", imemo_name));
+ APPENDF((BUFF_ARGS, "<%s> ", rb_imemo_name(imemo_type(obj))));
switch (imemo_type(obj)) {
case imemo_ment: {
const rb_method_entry_t *me = &RANY(obj)->as.imemo.ment;
if (me->def) {
- APPENDF((BUFF_ARGS, "(called_id: %s, type: %s, alias: %d, owner: %s, defined_class: %s)",
+ APPENDF((BUFF_ARGS, ":%s (%s%s%s%s) type:%s alias:%d owner:%p defined_class:%p",
rb_id2name(me->called_id),
+ METHOD_ENTRY_VISI(me) == METHOD_VISI_PUBLIC ? "pub" :
+ METHOD_ENTRY_VISI(me) == METHOD_VISI_PRIVATE ? "pri" : "pro",
+ METHOD_ENTRY_COMPLEMENTED(me) ? ",cmp" : "",
+ METHOD_ENTRY_CACHED(me) ? ",cc" : "",
+ METHOD_ENTRY_INVALIDATED(me) ? ",inv" : "",
rb_method_type_name(me->def->type),
- me->def->alias_count,
- obj_info(me->owner),
- obj_info(me->defined_class)));
+ me->def->alias_count,
+ (void *)me->owner, // obj_info(me->owner),
+ (void *)me->defined_class)); //obj_info(me->defined_class)));
+
+ if (me->def->type == VM_METHOD_TYPE_ISEQ) {
+ // APPENDF((BUFF_ARGS, " (iseq:%p)", (void *)me->def->body.iseq.iseqptr));
+ APPENDF((BUFF_ARGS, " (iseq:%s)", obj_info((VALUE)me->def->body.iseq.iseqptr)));
+ }
}
else {
APPENDF((BUFF_ARGS, "%s", rb_id2name(me->called_id)));
@@ -11667,6 +12428,27 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
rb_raw_iseq_info(BUFF_ARGS, iseq);
break;
}
+ case imemo_callinfo:
+ {
+ const struct rb_callinfo *ci = (const struct rb_callinfo *)obj;
+ APPENDF((BUFF_ARGS, "(mid:%s, flag:%x argc:%d, kwarg:%s)",
+ rb_id2name(vm_ci_mid(ci)),
+ vm_ci_flag(ci),
+ vm_ci_argc(ci),
+ vm_ci_kwarg(ci) ? "available" : "NULL"));
+ break;
+ }
+ case imemo_callcache:
+ {
+ const struct rb_callcache *cc = (const struct rb_callcache *)obj;
+ VALUE class_path = cc->klass ? rb_class_path_cached(cc->klass) : Qnil;
+
+ APPENDF((BUFF_ARGS, "(klass:%s, cme:%s (%p) call:%p",
+ NIL_P(class_path) ? "??" : RSTRING_PTR(class_path),
+ vm_cc_cme(cc) ? rb_id2name(vm_cc_cme(cc)->called_id) : "<NULL>",
+ (void *)vm_cc_cme(cc), (void *)vm_cc_call(cc)));
+ break;
+ }
default:
break;
}
@@ -11678,6 +12460,10 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
#undef C
}
end:
+ if (poisoned) {
+ asan_poison_object(obj);
+ }
+
return buff;
#undef APPENDF
#undef BUFF_ARGS
@@ -11722,7 +12508,7 @@ rb_obj_info_dump(VALUE obj)
fprintf(stderr, "rb_obj_info_dump: %s\n", rb_raw_obj_info(buff, 0x100, obj));
}
-void
+MJIT_FUNC_EXPORTED void
rb_obj_info_dump_loc(VALUE obj, const char *file, int line, const char *func)
{
char buff[0x100];
@@ -11754,12 +12540,10 @@ rb_gcdebug_print_obj_condition(VALUE obj)
fprintf(stderr, "marked? : %s\n", MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj) ? "true" : "false");
fprintf(stderr, "pinned? : %s\n", MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj) ? "true" : "false");
-#if USE_RGENGC
fprintf(stderr, "age? : %d\n", RVALUE_AGE(obj));
fprintf(stderr, "old? : %s\n", RVALUE_OLD_P(obj) ? "true" : "false");
fprintf(stderr, "WB-protected?: %s\n", RVALUE_WB_UNPROTECTED(obj) ? "false" : "true");
fprintf(stderr, "remembered? : %s\n", RVALUE_REMEMBERED(obj) ? "true" : "false");
-#endif
if (is_lazy_sweeping(heap_eden)) {
fprintf(stderr, "lazy sweeping?: true\n");
@@ -11840,9 +12624,9 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
*
* ObjectSpace also provides support for object finalizers, procs that will be
* called when a specific object is about to be destroyed by garbage
- * collection.
- *
- * require 'objspace'
+ * collection. See the documentation for
+ * <code>ObjectSpace.define_finalizer</code> for important information on
+ * how to use this method correctly.
*
* a = "A"
* b = "B"
@@ -11850,6 +12634,9 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
* ObjectSpace.define_finalizer(a, proc {|id| puts "Finalizer one on #{id}" })
* ObjectSpace.define_finalizer(b, proc {|id| puts "Finalizer two on #{id}" })
*
+ * a = nil
+ * b = nil
+ *
* _produces:_
*
* Finalizer two on 537763470
@@ -11895,13 +12682,14 @@ Init_GC(void)
VALUE gc_constants;
rb_mGC = rb_define_module("GC");
- load_gc();
gc_constants = rb_hash_new();
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("DEBUG")), GC_DEBUG ? Qtrue : Qfalse);
rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(sizeof(RVALUE)));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_OBJ_LIMIT")), SIZET2NUM(HEAP_PAGE_OBJ_LIMIT));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_SIZE")), SIZET2NUM(HEAP_PAGE_BITMAP_SIZE));
rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_PLANES")), SIZET2NUM(HEAP_PAGE_BITMAP_PLANES));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_SIZE")), SIZET2NUM(HEAP_PAGE_SIZE));
OBJ_FREEZE(gc_constants);
/* internal constants */
rb_define_const(rb_mGC, "INTERNAL_CONSTANTS", gc_constants);
@@ -11954,7 +12742,6 @@ Init_GC(void)
/* internal methods */
rb_define_singleton_method(rb_mGC, "verify_internal_consistency", gc_verify_internal_consistency_m, 0);
- rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);
rb_define_singleton_method(rb_mGC, "verify_transient_heap_internal_consistency", gc_verify_transient_heap_internal_consistency, 0);
#if MALLOC_ALLOCATED_SIZE
rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0);
diff --git a/gc.h b/gc.h
index 72e3935799..5d113cafce 100644
--- a/gc.h
+++ b/gc.h
@@ -1,6 +1,6 @@
-
#ifndef RUBY_GC_H
#define RUBY_GC_H 1
+#include "ruby/ruby.h"
#if defined(__x86_64__) && !defined(_ILP32) && defined(__GNUC__)
#define SET_MACHINE_STACK_END(p) __asm__ __volatile__ ("movq\t%%rsp, %0" : "=r" (*(p)))
@@ -16,6 +16,13 @@ NOINLINE(void rb_gc_set_stack_end(VALUE **stack_end_p));
#define USE_CONSERVATIVE_STACK_END
#endif
+#define RB_GC_SAVE_MACHINE_CONTEXT(th) \
+ do { \
+ FLUSH_REGISTER_WINDOWS; \
+ setjmp((th)->ec->machine.regs); \
+ SET_MACHINE_STACK_END(&(th)->ec->machine.stack_end); \
+ } while (0)
+
/* for GC debug */
#ifndef RUBY_MARK_FREE_DEBUG
@@ -61,7 +68,7 @@ rb_gc_debug_body(const char *mode, const char *msg, int st, void *ptr)
#define RUBY_GC_INFO if(0)printf
#endif
-#define RUBY_MARK_NO_PIN_UNLESS_NULL(ptr) do { \
+#define RUBY_MARK_MOVABLE_UNLESS_NULL(ptr) do { \
VALUE markobj = (ptr); \
if (RTEST(markobj)) {rb_gc_mark_movable(markobj);} \
} while (0)
diff --git a/gc.rb b/gc.rb
index fcfa48fbe1..8a00b406ce 100644
--- a/gc.rb
+++ b/gc.rb
@@ -31,11 +31,32 @@ module GC
# are not guaranteed to be future-compatible, and may be ignored if the
# underlying implementation does not support them.
def self.start full_mark: true, immediate_mark: true, immediate_sweep: true
- __builtin_gc_start_internal full_mark, immediate_mark, immediate_sweep
+ Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end
def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true
- __builtin_gc_start_internal full_mark, immediate_mark, immediate_sweep
+ Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
+ end
+
+ # call-seq:
+ # GC.auto_compact -> true or false
+ #
+ # Returns whether or not automatic compaction has been enabled.
+ #
+ def self.auto_compact
+ Primitive.gc_get_auto_compact
+ end
+
+ # call-seq:
+ # GC.auto_compact = flag
+ #
+ # Updates automatic compaction mode.
+ #
+ # When enabled, the compactor will execute on every major collection.
+ #
+ # Enabling compaction will degrade performance on major collections.
+ def self.auto_compact=(flag)
+ Primitive.gc_set_auto_compact(flag)
end
# call-seq:
@@ -49,7 +70,7 @@ module GC
# GC.enable #=> false
#
def self.enable
- __builtin_gc_enable
+ Primitive.gc_enable
end
# call-seq:
@@ -61,7 +82,7 @@ module GC
# GC.disable #=> false
# GC.disable #=> true
def self.disable
- __builtin_gc_disable
+ Primitive.gc_disable
end
# call-seq:
@@ -69,7 +90,7 @@ module GC
#
# Returns current status of GC stress mode.
def self.stress
- __builtin_gc_stress_get
+ Primitive.gc_stress_get
end
# call-seq:
@@ -87,7 +108,7 @@ module GC
# 0x02:: no immediate sweep
# 0x04:: full mark after malloc/calloc/realloc
def self.stress=(flag)
- __builtin_gc_stress_set_m flag
+ Primitive.gc_stress_set_m flag
end
# call-seq:
@@ -97,7 +118,7 @@ module GC
#
# It returns the number of times GC occurred since the process started.
def self.count
- __builtin_gc_count
+ Primitive.gc_count
end
# call-seq:
@@ -140,9 +161,13 @@ module GC
# The contents of the hash are implementation specific and may be changed in
# the future.
#
+ # 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 C Ruby.
def self.stat hash_or_key = nil
- __builtin_gc_stat hash_or_key
+ Primitive.gc_stat hash_or_key
end
# call-seq:
@@ -151,18 +176,65 @@ module GC
# GC.latest_gc_info(:major_by) -> :malloc
#
# Returns information about the most recent garbage collection.
+ #
+ # If the optional argument, hash, is given,
+ # it is overwritten and returned.
+ # This is intended to avoid probe effect.
def self.latest_gc_info hash_or_key = nil
- __builtin_gc_latest_gc_info hash_or_key
+ Primitive.gc_latest_gc_info hash_or_key
+ end
+
+ # call-seq:
+ # GC.latest_compact_info -> {:considered=>{:T_CLASS=>11}, :moved=>{:T_CLASS=>11}}
+ #
+ # Returns information about object moved in the most recent GC compaction.
+ #
+ # The returned hash has two keys :considered and :moved. The hash for
+ # :considered lists the number of objects that were considered for movement
+ # by the compactor, and the :moved hash lists the number of objects that
+ # were actually moved. Some objects can't be moved (maybe they were pinned)
+ # so these numbers can be used to calculate compaction efficiency.
+ def self.latest_compact_info
+ Primitive.gc_compact_stats
end
+ # call-seq:
+ # GC.compact
+ #
+ # This function compacts objects together in Ruby's heap. It eliminates
+ # unused space (or fragmentation) in the heap by moving objects in to that
+ # unused space. This function returns a hash which contains statistics about
+ # which objects were moved. See `GC.latest_gc_info` for details about
+ # compaction statistics.
+ #
+ # This method is implementation specific and not expected to be implemented
+ # in any implementation besides MRI.
def self.compact
- __builtin_rb_gc_compact
+ Primitive.gc_compact
+ end
+
+ # call-seq:
+ # GC.verify_compaction_references(toward: nil, double_heap: false) -> hash
+ #
+ # Verify compaction reference consistency.
+ #
+ # This method is implementation specific. During compaction, objects that
+ # were moved are replaced with T_MOVED objects. No object should have a
+ # reference to a T_MOVED object after compaction.
+ #
+ # This function doubles the heap to ensure room to move all objects,
+ # compacts the heap to make sure everything moves, updates all references,
+ # then performs a full GC. If any object contains a reference to a T_MOVED
+ # object, that object should be pushed on the mark stack, and will
+ # make a SEGV.
+ def self.verify_compaction_references(toward: nil, double_heap: false)
+ Primitive.gc_verify_compaction_references(double_heap, toward == :empty)
end
end
module ObjectSpace
def garbage_collect full_mark: true, immediate_mark: true, immediate_sweep: true
- __builtin_gc_start_internal full_mark, immediate_mark, immediate_sweep
+ Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end
module_function :garbage_collect
diff --git a/gem_prelude.rb b/gem_prelude.rb
index 1d0158d00a..c4debb6509 100644
--- a/gem_prelude.rb
+++ b/gem_prelude.rb
@@ -1,2 +1,11 @@
-require 'rubygems.rb' if defined?(Gem)
-require 'did_you_mean' if defined?(DidYouMean)
+begin
+ require 'rubygems'
+rescue LoadError
+ warn "`RubyGems' were not loaded."
+end if defined?(Gem)
+
+begin
+ require 'did_you_mean'
+rescue LoadError
+ warn "`did_you_mean' was not loaded."
+end if defined?(DidYouMean)
diff --git a/gems/bundled_gems b/gems/bundled_gems
index ce2dd1bdb8..4eda5f919a 100644
--- a/gems/bundled_gems
+++ b/gems/bundled_gems
@@ -1,6 +1,9 @@
-minitest 5.13.0 https://github.com/seattlerb/minitest
-net-telnet 0.2.0 https://github.com/ruby/net-telnet
-power_assert 1.1.7 https://github.com/k-tsj/power_assert
-rake 13.0.1 https://github.com/ruby/rake
-test-unit 3.3.4 https://github.com/test-unit/test-unit
-xmlrpc 0.3.0 https://github.com/ruby/xmlrpc
+# gem-name version-to-bundle repository-url [optional-commit-hash-to-test-or-defaults-to-v-version]
+minitest 5.14.2 https://github.com/seattlerb/minitest
+power_assert 1.2.0 https://github.com/ruby/power_assert
+rake 13.0.3 https://github.com/ruby/rake
+test-unit 3.3.7 https://github.com/test-unit/test-unit 3.3.7
+rexml 3.2.5 https://github.com/ruby/rexml
+rss 0.2.9 https://github.com/ruby/rss 0.2.9
+typeprof 0.15.2 https://github.com/ruby/typeprof
+rbs 1.4.0 https://github.com/ruby/rbs
diff --git a/goruby.c b/goruby.c
index ddb62562d4..e4119c56f7 100644
--- a/goruby.c
+++ b/goruby.c
@@ -49,10 +49,8 @@ goruby_options(int argc, char **argv)
close(infd);
return ret;
}
- else {
- no_irb:
- return ruby_options(argc, argv);
- }
+ no_irb:
+ return ruby_options(argc, argv);
}
int
diff --git a/hash.c b/hash.c
index 63b228f501..17d4186acf 100644
--- a/hash.c
+++ b/hash.c
@@ -11,17 +11,10 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/st.h"
-#include "ruby/util.h"
-#include "internal.h"
+#include "ruby/internal/config.h"
+
#include <errno.h>
-#include "probes.h"
-#include "id.h"
-#include "symbol.h"
-#include "debug_counter.h"
-#include "transient_heap.h"
-#include "ruby_assert.h"
+
#ifdef __APPLE__
# ifdef HAVE_CRT_EXTERNS_H
# include <crt_externs.h>
@@ -30,6 +23,27 @@
# endif
#endif
+#include "debug_counter.h"
+#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/bignum.h"
+#include "internal/class.h"
+#include "internal/cont.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/object.h"
+#include "internal/proc.h"
+#include "internal/symbol.h"
+#include "internal/time.h"
+#include "internal/vm.h"
+#include "probes.h"
+#include "ruby/st.h"
+#include "ruby/util.h"
+#include "ruby_assert.h"
+#include "symbol.h"
+#include "transient_heap.h"
+
#ifndef HASH_DEBUG
#define HASH_DEBUG 0
#endif
@@ -56,7 +70,7 @@ copy_default(struct RHash *hash, const struct RHash *hash2)
{
hash->basic.flags &= ~RHASH_PROC_DEFAULT;
hash->basic.flags |= hash2->basic.flags & RHASH_PROC_DEFAULT;
- RHASH_SET_IFNONE(hash, RHASH_IFNONE(hash2));
+ RHASH_SET_IFNONE(hash, RHASH_IFNONE((VALUE)hash2));
}
static VALUE
@@ -92,7 +106,7 @@ rb_hash_freeze(VALUE hash)
VALUE rb_cHash;
static VALUE envtbl;
-static ID id_hash, id_yield, id_default, id_flatten_bang;
+static ID id_hash, id_default, id_flatten_bang;
static ID id_hash_iter_lev;
VALUE
@@ -128,7 +142,11 @@ hash_recursive(VALUE obj, VALUE arg, int recurse)
VALUE
rb_hash(VALUE obj)
{
- VALUE hval = rb_exec_recursive_outer(hash_recursive, obj, 0);
+ VALUE hval = rb_check_funcall_basic_kw(obj, id_hash, rb_mKernel, 0, 0, 0);
+
+ if (hval == Qundef) {
+ hval = rb_exec_recursive_outer(hash_recursive, obj, 0);
+ }
while (!FIXNUM_P(hval)) {
if (RB_TYPE_P(hval, T_BIGNUM)) {
@@ -136,10 +154,12 @@ rb_hash(VALUE obj)
unsigned long ul;
sign = rb_integer_pack(hval, &ul, 1, sizeof(ul), 0,
INTEGER_PACK_NATIVE_BYTE_ORDER);
- ul &= (1UL << (sizeof(long)*CHAR_BIT-1)) - 1;
- if (sign < 0)
- return LONG2FIX(-(long)ul);
- return LONG2FIX((long)ul);
+ if (sign < 0) {
+ hval = LONG2FIX(ul | FIXNUM_MIN);
+ }
+ else {
+ hval = LONG2FIX(ul & FIXNUM_MAX);
+ }
}
hval = rb_to_int(hval);
}
@@ -174,45 +194,39 @@ any_hash(VALUE a, st_index_t (*other_func)(VALUE))
VALUE hval;
st_index_t hnum;
- if (SPECIAL_CONST_P(a)) {
+ switch (TYPE(a)) {
+ case T_SYMBOL:
if (STATIC_SYM_P(a)) {
hnum = a >> (RUBY_SPECIAL_SHIFT + ID_SCOPE_SHIFT);
hnum = rb_hash_start(hnum);
- goto out;
}
- else if (FLONUM_P(a)) {
- /* prevent pathological behavior: [Bug #10761] */
- goto flt;
- }
+ else {
+ hnum = RSYMBOL(a)->hashval;
+ }
+ break;
+ case T_FIXNUM:
+ case T_TRUE:
+ case T_FALSE:
+ case T_NIL:
hnum = rb_objid_hash((st_index_t)a);
- }
- else if (BUILTIN_TYPE(a) == T_STRING) {
+ break;
+ case T_STRING:
hnum = rb_str_hash(a);
- }
- else if (BUILTIN_TYPE(a) == T_SYMBOL) {
- hnum = RSYMBOL(a)->hashval;
- }
- else if (BUILTIN_TYPE(a) == T_BIGNUM) {
+ break;
+ case T_BIGNUM:
hval = rb_big_hash(a);
hnum = FIX2LONG(hval);
- }
- else if (BUILTIN_TYPE(a) == T_FLOAT) {
- flt:
+ break;
+ case T_FLOAT: /* prevent pathological behavior: [Bug #10761] */
hnum = rb_dbl_long_hash(rb_float_value(a));
- }
- else {
+ break;
+ default:
hnum = other_func(a);
}
- out:
-#if SIZEOF_LONG < SIZEOF_ST_INDEX_T
- if (hnum > 0)
- hnum &= (unsigned long)-1 >> 2;
+ if ((SIGNED_VALUE)hnum > 0)
+ hnum &= FIXNUM_MAX;
else
- hnum |= ~((unsigned long)-1 >> 2);
-#else
- hnum <<= 1;
- hnum = RSHIFT(hnum, 1);
-#endif
+ hnum |= FIXNUM_MIN;
return (long)hnum;
}
@@ -299,6 +313,9 @@ objid_hash(VALUE obj)
* implementations of Ruby. If you need a stable identifier across Ruby
* invocations and implementations you will need to generate one with a custom
* method.
+ *
+ * Certain core classes such as Integer use built-in hash calculations and
+ * do not call the #hash method when used as a hash key.
*--
* \private
*++
@@ -514,11 +531,13 @@ hash_verify_(VALUE hash, const char *file, int line)
HASH_ASSERT(RHASH_AR_TABLE_BOUND_RAW(hash) == 0);
}
+#if USE_TRANSIENT_HEAP
if (RHASH_TRANSIENT_P(hash)) {
volatile st_data_t MAYBE_UNUSED(key) = RHASH_AR_TABLE_REF(hash, 0)->key; /* read */
HASH_ASSERT(RHASH_AR_TABLE(hash) != NULL);
HASH_ASSERT(rb_transient_heap_managed_ptr_p(RHASH_AR_TABLE(hash)));
}
+#endif
return hash;
}
@@ -1268,15 +1287,14 @@ rb_hash_transient_heap_evacuate(VALUE hash, int promote)
return;
}
HASH_ASSERT(old_tab != NULL);
+ if (! promote) {
+ new_tab = rb_transient_heap_alloc(hash, sizeof(ar_table));
+ if (new_tab == NULL) promote = true;
+ }
if (promote) {
- promote:
new_tab = ruby_xmalloc(sizeof(ar_table));
RHASH_UNSET_TRANSIENT_FLAG(hash);
}
- else {
- new_tab = rb_transient_heap_alloc(hash, sizeof(ar_table));
- if (new_tab == NULL) goto promote;
- }
*new_tab = *old_tab;
hash_ar_table_set(hash, new_tab);
}
@@ -1418,7 +1436,7 @@ hash_iter_lev_inc(VALUE hash)
}
else {
lev += 1;
- RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | (lev << RHASH_LEV_SHIFT));
+ RBASIC(hash)->flags = ((RBASIC(hash)->flags & ~RHASH_LEV_MASK) | ((VALUE)lev << RHASH_LEV_SHIFT));
if (lev == RHASH_LEV_MAX) {
iter_lev_in_ivar_set(hash, lev);
}
@@ -1601,23 +1619,16 @@ rb_hash_modify_check(VALUE hash)
}
MJIT_FUNC_EXPORTED struct st_table *
-#if RHASH_CONVERT_TABLE_DEBUG
rb_hash_tbl_raw(VALUE hash, const char *file, int line)
{
return ar_force_convert_table(hash, file, line);
}
-#else
-rb_hash_tbl_raw(VALUE hash)
-{
- return ar_force_convert_table(hash, NULL, 0);
-}
-#endif
struct st_table *
rb_hash_tbl(VALUE hash, const char *file, int line)
{
OBJ_WB_UNPROTECT(hash);
- return RHASH_TBL_RAW(hash);
+ return rb_hash_tbl_raw(hash, file, line);
}
static void
@@ -1664,7 +1675,7 @@ struct update_arg {
typedef int (*tbl_update_func)(st_data_t *, st_data_t *, st_data_t, int);
int
-rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg)
+rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func, st_data_t arg)
{
if (RHASH_AR_TABLE_P(hash)) {
int result = ar_update(hash, (st_data_t)key, func, arg);
@@ -1728,37 +1739,33 @@ set_proc_default(VALUE hash, VALUE proc)
/*
* call-seq:
- * Hash.new -> new_hash
- * Hash.new(obj) -> new_hash
- * Hash.new {|hash, key| block } -> new_hash
- *
- * Returns a new, empty hash. If this hash is subsequently accessed by
- * a key that doesn't correspond to a hash entry, the value returned
- * depends on the style of <code>new</code> used to create the hash. In
- * the first form, the access returns <code>nil</code>. If
- * <i>obj</i> is specified, this single object will be used for
- * all <em>default values</em>. If a block is specified, it will be
- * called with the hash object and the key, and should return the
- * default value. It is the block's responsibility to store the value
- * in the hash if required.
- *
- * h = Hash.new("Go Fish")
- * h["a"] = 100
- * h["b"] = 200
- * h["a"] #=> 100
- * h["c"] #=> "Go Fish"
- * # The following alters the single default object
- * h["c"].upcase! #=> "GO FISH"
- * h["d"] #=> "GO FISH"
- * h.keys #=> ["a", "b"]
- *
- * # While this creates a new default object each time
- * h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
- * h["c"] #=> "Go Fish: c"
- * h["c"].upcase! #=> "GO FISH: C"
- * h["d"] #=> "Go Fish: d"
- * h.keys #=> ["c", "d"]
- *
+ * Hash.new(default_value = nil) -> new_hash
+ * Hash.new {|hash, key| ... } -> new_hash
+ *
+ * Returns a new empty \Hash object.
+ *
+ * The initial default value and initial default proc for the new hash
+ * depend on which form above was used. See {Default Values}[#class-Hash-label-Default+Values].
+ *
+ * If neither an argument nor a block given,
+ * initializes both the default value and the default proc to <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
@@ -1783,22 +1790,31 @@ rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
/*
* call-seq:
- * Hash[ key, value, ... ] -> new_hash
- * Hash[ [ [key, value], ... ] ] -> new_hash
- * Hash[ object ] -> new_hash
+ * Hash[] -> new_empty_hash
+ * Hash[hash] -> new_hash
+ * Hash[ [*2_element_arrays] ] -> new_hash
+ * Hash[*objects] -> new_hash
+ *
+ * Returns a new \Hash object populated with the given objects, if any.
+ * See Hash::new.
*
- * Creates a new hash populated with the given objects.
+ * With no argument, returns a new empty \Hash.
*
- * Similar to the literal <code>{ _key_ => _value_, ... }</code>. In the first
- * form, keys and values occur in pairs, so there must be an even number of
- * arguments.
+ * When the single given argument is a \Hash,
+ * returns a new \Hash populated with the entries from the given \Hash.
+ * h = {foo: 0, bar: 1, baz: 2}
+ * Hash[h] # => {:foo=>0, :bar=>1, :baz=>2}
*
- * The second and third form take a single argument which is either an array
- * of key-value pairs or an object convertible to a hash.
+ * When the single given argument is an \Array of 2-element Arrays,
+ * returns a new \Hash object wherein each 2-element array forms a key-value entry:
+ * Hash[ [ [:foo, 0], [:bar, 1] ] ] # => {:foo=>0, :bar=>1}
*
- * Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
- * Hash[ [ ["a", 100], ["b", 200] ] ] #=> {"a"=>100, "b"=>200}
- * Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
+ * When the argument count is an even number;
+ * returns a new \Hash object wherein each successive pair of arguments
+ * has become a key-value entry:
+ * Hash[:foo, 0, :bar, 1] # => {:foo=>0, :bar=>1}
+ *
+ * Raises an exception if the argument list does not conform to any of the above.
*/
static VALUE
@@ -1810,12 +1826,7 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
tmp = rb_hash_s_try_convert(Qnil, argv[0]);
if (!NIL_P(tmp)) {
hash = hash_alloc(klass);
- if (RHASH_AR_TABLE_P(tmp)) {
- ar_copy(hash, tmp);
- }
- else {
- RHASH_ST_TABLE_SET(hash, st_copy(RHASH_ST_TABLE(tmp)));
- }
+ hash_copy(hash, tmp);
return hash;
}
@@ -1857,7 +1868,7 @@ rb_hash_s_create(int argc, VALUE *argv, VALUE klass)
return hash;
}
-VALUE
+MJIT_FUNC_EXPORTED VALUE
rb_to_hash_type(VALUE hash)
{
return rb_convert_type_with_id(hash, T_HASH, "Hash", idTo_hash);
@@ -1872,14 +1883,16 @@ rb_check_hash_type(VALUE hash)
/*
* call-seq:
- * Hash.try_convert(obj) -> hash or nil
+ * Hash.try_convert(obj) -> obj, new_hash, or nil
*
- * Try to convert <i>obj</i> into a hash, using to_hash method.
- * Returns converted hash or nil if <i>obj</i> cannot be converted
- * for any reason.
+ * If +obj+ is a \Hash object, returns +obj+.
*
- * Hash.try_convert({1=>2}) # => {1=>2}
- * Hash.try_convert("1=>2") # => nil
+ * Otherwise if +obj+ responds to <tt>:to_hash</tt>,
+ * calls <tt>obj.to_hash</tt> and returns the result.
+ *
+ * Returns +nil+ if +obj+ does not respond to <tt>:to_hash</tt>
+ *
+ * Raises an exception unless <tt>obj.to_hash</tt> returns a \Hash object.
*/
static VALUE
rb_hash_s_try_convert(VALUE dummy, VALUE hash)
@@ -1952,22 +1965,14 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hsh.rehash -> hsh
- *
- * Rebuilds the hash based on the current hash values for each key. If
- * values of key objects have changed since they were inserted, this
- * method will reindex <i>hsh</i>. If Hash#rehash is
- * called while an iterator is traversing the hash, a
- * RuntimeError will be raised in the iterator.
- *
- * a = [ "a", "b" ]
- * c = [ "c", "d" ]
- * h = { a => 100, c => 300 }
- * h[a] #=> 100
- * a[0] = "z"
- * h[a] #=> nil
- * h.rehash #=> {["z", "b"]=>100, ["c", "d"]=>300}
- * h[a] #=> 100
+ * hash.rehash -> self
+ *
+ * Rebuilds the hash table by recomputing the hash index for each key;
+ * returns <tt>self</tt>.
+ *
+ * The hash table becomes invalid if the hash value of a key
+ * has changed after the entry was created.
+ * See {Modifying an Active Hash Key}[#class-Hash-label-Modifying+an+Active+Hash+Key].
*/
VALUE
@@ -2002,14 +2007,21 @@ rb_hash_rehash(VALUE hash)
return hash;
}
+static VALUE
+call_default_proc(VALUE proc, VALUE hash, VALUE key)
+{
+ VALUE args[2] = {hash, key};
+ return rb_proc_call_with_block(proc, 2, args, Qnil);
+}
+
VALUE
rb_hash_default_value(VALUE hash, VALUE key)
{
- if (rb_method_basic_definition_p(CLASS_OF(hash), id_default)) {
+ if (LIKELY(rb_method_basic_definition_p(CLASS_OF(hash), id_default))) {
VALUE ifnone = RHASH_IFNONE(hash);
if (!FL_TEST(hash, RHASH_PROC_DEFAULT)) return ifnone;
if (key == Qundef) return Qnil;
- return rb_funcall(ifnone, id_yield, 2, hash, key);
+ return call_default_proc(ifnone, hash, key);
}
else {
return rb_funcall(hash, id_default, 1, key);
@@ -2037,16 +2049,16 @@ rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
/*
* call-seq:
- * hsh[key] -> value
- *
- * Element Reference---Retrieves the <i>value</i> object corresponding
- * to the <i>key</i> object. If not found, returns the default value (see
- * Hash::new for details).
+ * hash[key] -> value
*
- * h = { "a" => 100, "b" => 200 }
- * h["a"] #=> 100
- * h["c"] #=> nil
+ * Returns the value associated with the given +key+, if found:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h[:foo] # => 0
*
+ * If +key+ is not found, returns a default value
+ * (see {Default Values}[#class-Hash-label-Default+Values]):
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h[:nosuch] # => nil
*/
VALUE
@@ -2083,31 +2095,26 @@ rb_hash_lookup(VALUE hash, VALUE key)
/*
* call-seq:
- * hsh.fetch(key [, default] ) -> obj
- * hsh.fetch(key) {| key | block } -> obj
+ * hash.fetch(key) -> object
+ * hash.fetch(key, default_value) -> object
+ * hash.fetch(key) {|key| ... } -> object
*
- * Returns a value from the hash for the given key. If the key can't be
- * found, there are several options: With no other arguments, it will
- * raise a KeyError exception; if <i>default</i> is given,
- * then that will be returned; if the optional code block is specified,
- * then that will be run and its result returned.
+ * Returns the value for the given +key+, if found.
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.fetch(:bar) # => 1
*
- * h = { "a" => 100, "b" => 200 }
- * h.fetch("a") #=> 100
- * h.fetch("z", "go fish") #=> "go fish"
- * h.fetch("z") { |el| "go fish, #{el}"} #=> "go fish, z"
+ * If +key+ is not found and no block was given,
+ * returns +default_value+:
+ * {}.fetch(:nosuch, :default) # => :default
+ * {}.fetch(:nosuch) # => nil
*
- * The following example shows that an exception is raised if the key
- * is not found and a default value is not supplied.
+ * If +key+ is not found and 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 = { "a" => 100, "b" => 200 }
- * h.fetch("z")
- *
- * <em>produces:</em>
- *
- * prog.rb:2:in `fetch': key not found (KeyError)
- * from prog.rb:2
+ * Raises KeyError if neither +default_value+ nor a block was given.
*
+ * Note that this method does not use the values of either #default or #default_proc.
*/
static VALUE
@@ -2154,59 +2161,49 @@ rb_hash_fetch(VALUE hash, VALUE key)
/*
* call-seq:
- * hsh.default(key=nil) -> obj
- *
- * Returns the default value, the value that would be returned by
- * <i>hsh</i>[<i>key</i>] if <i>key</i> did not exist in <i>hsh</i>.
- * See also Hash::new and Hash#default=.
- *
- * h = Hash.new #=> {}
- * h.default #=> nil
- * h.default(2) #=> nil
- *
- * h = Hash.new("cat") #=> {}
- * h.default #=> "cat"
- * h.default(2) #=> "cat"
- *
- * h = Hash.new {|h,k| h[k] = k.to_i*10} #=> {}
- * h.default #=> nil
- * h.default(2) #=> 20
+ * hash.default -> object
+ * hash.default(key) -> object
+ *
+ * Returns the default value for the given +key+.
+ * The returned value will be determined either by the default proc or by the default value.
+ * See {Default Values}[#class-Hash-label-Default+Values].
+ *
+ * With no argument, returns the current default value:
+ * h = {}
+ * h.default # => nil
+ *
+ * If +key+ is given, returns the default value for +key+,
+ * regardless of whether that key exists:
+ * h = Hash.new { |hash, key| hash[key] = "No key #{key}"}
+ * h[:foo] = "Hello"
+ * h.default(:foo) # => "No key foo"
*/
static VALUE
rb_hash_default(int argc, VALUE *argv, VALUE hash)
{
- VALUE args[2], ifnone;
+ VALUE ifnone;
rb_check_arity(argc, 0, 1);
ifnone = RHASH_IFNONE(hash);
if (FL_TEST(hash, RHASH_PROC_DEFAULT)) {
if (argc == 0) return Qnil;
- args[0] = hash;
- args[1] = argv[0];
- return rb_funcallv(ifnone, id_yield, 2, args);
+ return call_default_proc(ifnone, hash, argv[0]);
}
return ifnone;
}
/*
* call-seq:
- * hsh.default = obj -> obj
- *
- * Sets the default value, the value returned for a key that does not
- * exist in the hash. It is not possible to set the default to a
- * Proc that will be executed on each key lookup.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.default = "Go fish"
- * h["a"] #=> 100
- * h["z"] #=> "Go fish"
- * # This doesn't do what you might hope...
- * h.default = proc do |hash, key|
- * hash[key] = key + key
- * end
- * h[2] #=> #<Proc:0x401b3948@-:6>
- * h["cat"] #=> #<Proc:0x401b3948@-:6>
+ * hash.default = value -> object
+ *
+ * Sets the default value to +value+; returns +value+:
+ * h = {}
+ * h.default # => nil
+ * h.default = false # => false
+ * h.default # => false
+ *
+ * See {Default Values}[#class-Hash-label-Default+Values].
*/
static VALUE
@@ -2219,19 +2216,16 @@ rb_hash_set_default(VALUE hash, VALUE ifnone)
/*
* call-seq:
- * hsh.default_proc -> anObject
- *
- * If Hash::new was invoked with a block, return that
- * block, otherwise return <code>nil</code>.
- *
- * h = Hash.new {|h,k| h[k] = k*k } #=> {}
- * p = h.default_proc #=> #<Proc:0x401b3d08@-:1>
- * a = [] #=> []
- * p.call(a, 2)
- * a #=> [nil, nil, 4]
+ * hash.default_proc -> proc or nil
+ *
+ * Returns the default proc for +self+
+ * (see {Default Values}[#class-Hash-label-Default+Values]):
+ * h = {}
+ * h.default_proc # => nil
+ * h.default_proc = proc {|hash, key| "Default value for #{key}" }
+ * h.default_proc.class # => Proc
*/
-
static VALUE
rb_hash_default_proc(VALUE hash)
{
@@ -2243,15 +2237,16 @@ rb_hash_default_proc(VALUE hash)
/*
* call-seq:
- * hsh.default_proc = proc_obj or nil
- *
- * Sets the default proc to be executed on each failed key lookup.
- *
- * h.default_proc = proc do |hash, key|
- * hash[key] = key + key
- * end
- * h[2] #=> 4
- * h["cat"] #=> "catcat"
+ * hash.default_proc = proc -> proc
+ *
+ * Sets the default proc for +self+ to +proc+:
+ * (see {Default Values}[#class-Hash-label-Default+Values]):
+ * h = {}
+ * h.default_proc # => nil
+ * h.default_proc = proc { |hash, key| "Default value for #{key}" }
+ * h.default_proc.class # => Proc
+ * h.default_proc = nil
+ * h.default_proc # => nil
*/
VALUE
@@ -2289,16 +2284,15 @@ key_i(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hsh.key(value) -> key
+ * hash.key(value) -> key or nil
*
- * Returns the key of an occurrence of a given value. If the value is
- * not found, returns <code>nil</code>.
- *
- * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
- * h.key(200) #=> "b"
- * h.key(300) #=> "c"
- * h.key(999) #=> nil
+ * Returns the key for the first-found entry with the given +value+
+ * (see {Entry Order}[#class-Hash-label-Entry+Order]):
+ * h = {foo: 0, bar: 2, baz: 2}
+ * h.key(0) # => :foo
+ * h.key(2) # => :bar
*
+ * Returns +nil+ if so such value is found.
*/
static VALUE
@@ -2314,14 +2308,6 @@ rb_hash_key(VALUE hash, VALUE value)
return args[1];
}
-/* :nodoc: */
-static VALUE
-rb_hash_index(VALUE hash, VALUE value)
-{
- rb_warn_deprecated("Hash#index", "Hash#key");
- return rb_hash_key(hash, value);
-}
-
int
rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval)
{
@@ -2371,20 +2357,29 @@ rb_hash_delete(VALUE hash, VALUE key)
/*
* call-seq:
- * hsh.delete(key) -> value
- * hsh.delete(key) {| key | block } -> value
+ * hash.delete(key) -> value or nil
+ * hash.delete(key) {|key| ... } -> object
+ *
+ * Deletes the entry for the given +key+ and returns its associated value.
*
- * Deletes the key-value pair and returns the value from <i>hsh</i> whose
- * key is equal to <i>key</i>. If the key is not found, it returns
- * <em>nil</em>. If the optional code block is given and the
- * key is not found, pass in the key and return the result of
- * <i>block</i>.
+ * If no block is given and +key+ is found, deletes the entry and returns the associated value:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.delete(:bar) # => 1
+ * h # => {:foo=>0, :baz=>2}
*
- * h = { "a" => 100, "b" => 200 }
- * h.delete("a") #=> 100
- * h.delete("z") #=> nil
- * h.delete("z") { |el| "#{el} not found" } #=> "z not found"
+ * If no block given and +key+ is not found, returns +nil+.
*
+ * If a block is given and +key+ is found, ignores the block,
+ * deletes the entry, and returns the associated value:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.delete(:baz) { |key| raise 'Will never happen'} # => 2
+ * h # => {:foo=>0, :bar=>1}
+ *
+ * If a block is given and +key+ is not found,
+ * calls the block and returns the block's return value:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.delete(:nosuch) { |key| "Key #{key} not found" } # => "Key nosuch not found"
+ * h # => {:foo=>0, :bar=>1, :baz=>2}
*/
static VALUE
@@ -2425,15 +2420,17 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hsh.shift -> anArray or obj
+ * hash.shift -> [key, value] or default_value
*
- * Removes a key-value pair from <i>hsh</i> and returns it as the
- * two-item array <code>[</code> <i>key, value</i> <code>]</code>, or
- * the hash's default value if the hash is empty.
+ * Removes the first hash entry
+ * (see {Entry Order}[#class-Hash-label-Entry+Order]);
+ * returns a 2-element \Array containing the removed key and value:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.shift # => [:foo, 0]
+ * h # => {:bar=>1, :baz=>2}
*
- * h = { 1 => "a", 2 => "b", 3 => "c" }
- * h.shift #=> [1, "a"]
- * h #=> {2=>"b", 3=>"c"}
+ * Returns the default value if the hash is empty
+ * (see {Default Values}[#class-Hash-label-Default+Values]).
*/
static VALUE
@@ -2479,6 +2476,7 @@ static int
delete_if_i(VALUE key, VALUE value, VALUE hash)
{
if (RTEST(rb_yield_values(2, key, value))) {
+ rb_hash_modify(hash);
return ST_DELETE;
}
return ST_CONTINUE;
@@ -2492,17 +2490,19 @@ hash_enum_size(VALUE hash, VALUE args, VALUE eobj)
/*
* call-seq:
- * hsh.delete_if {| key, value | block } -> hsh
- * hsh.delete_if -> an_enumerator
- *
- * Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
- * evaluates to <code>true</code>.
- *
- * If no block is given, an enumerator is returned instead.
- *
- * h = { "a" => 100, "b" => 200, "c" => 300 }
- * h.delete_if {|key, value| key >= "b" } #=> {"a"=>100}
- *
+ * hash.delete_if {|key, value| ... } -> self
+ * hash.delete_if -> new_enumerator
+ *
+ * If a block given, calls the block with each key-value pair;
+ * deletes each entry for which the block returns a truthy value;
+ * returns +self+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.delete_if {|key, value| value > 0 } # => {:foo=>0}
+ *
+ * If no block given, returns a new \Enumerator:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.delete_if # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:delete_if>
+ * e.each { |key, value| value > 0 } # => {:foo=>0}
*/
VALUE
@@ -2518,11 +2518,20 @@ rb_hash_delete_if(VALUE hash)
/*
* call-seq:
- * hsh.reject! {| key, value | block } -> hsh or nil
- * hsh.reject! -> an_enumerator
+ * hash.reject! {|key, value| ... } -> self or nil
+ * hash.reject! -> new_enumerator
+ *
+ * Returns +self+, whose remaining entries are those
+ * for which the block returns +false+ or +nil+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.reject! {|key, value| value < 2 } # => {:baz=>2}
+ *
+ * Returns +nil+ if no entries are removed.
*
- * Equivalent to Hash#delete_if, but returns
- * <code>nil</code> if no changes were made.
+ * 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}
*/
VALUE
@@ -2550,16 +2559,20 @@ reject_i(VALUE key, VALUE value, VALUE result)
/*
* call-seq:
- * hsh.reject {|key, value| block} -> a_hash
- * hsh.reject -> an_enumerator
- *
- * Returns a new hash consisting of entries for which the block returns false.
- *
- * If no block is given, an enumerator is returned instead.
- *
- * h = { "a" => 100, "b" => 200, "c" => 300 }
- * h.reject {|k,v| k < "b"} #=> {"b" => 200, "c" => 300}
- * h.reject {|k,v| v > 100} #=> {"a" => 100}
+ * hash.reject {|key, value| ... } -> new_hash
+ * hash.reject -> new_enumerator
+ *
+ * Returns a new \Hash object whose entries are all those
+ * from +self+ for which the block returns +false+ or +nil+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = h.reject {|key, value| key.start_with?('b') }
+ * h1 # => {:foo=>0}
+ *
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.reject # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:reject>
+ * h1 = e.each {|key, value| key.start_with?('b') }
+ * h1 # => {:foo=>0}
*/
VALUE
@@ -2583,13 +2596,13 @@ rb_hash_reject(VALUE hash)
/*
* call-seq:
- * hsh.slice(*keys) -> a_hash
+ * hash.slice(*keys) -> new_hash
*
- * Returns a hash containing only the given keys and their values.
+ * Returns a new \Hash object containing the entries for the given +keys+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.slice(:baz, :foo) # => {:baz=>2, :foo=>0}
*
- * h = { a: 100, b: 200, c: 300 }
- * h.slice(:a) #=> {:a=>100}
- * h.slice(:b, :c, :d) #=> {:b=>200, :c=>300}
+ * Any given +keys+ that are not found are ignored.
*/
static VALUE
@@ -2614,14 +2627,44 @@ rb_hash_slice(int argc, VALUE *argv, VALUE hash)
}
/*
- * call-seq:
- * hsh.values_at(key, ...) -> array
+ * call-seq:
+ * hsh.except(*keys) -> a_hash
*
- * Return an array containing the values associated with the given keys.
- * Also see Hash.select.
+ * Returns a new \Hash excluding entries for the given +keys+:
+ * h = { a: 100, b: 200, c: 300 }
+ * h.except(:a) #=> {:b=>200, :c=>300}
*
- * h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
- * h.values_at("cow", "cat") #=> ["bovine", "feline"]
+ * Any given +keys+ that are not found are ignored.
+ */
+
+static VALUE
+rb_hash_except(int argc, VALUE *argv, VALUE hash)
+{
+ int i;
+ VALUE key, result;
+
+ result = hash_alloc(rb_cHash);
+ hash_copy(result, hash);
+
+ for (i = 0; i < argc; i++) {
+ key = argv[i];
+ rb_hash_delete(result, key);
+ }
+
+ return result;
+}
+
+/*
+ * call-seq:
+ * hash.values_at(*keys) -> new_array
+ *
+ * Returns a new \Array containing values for the given +keys+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.values_at(:baz, :foo) # => [2, 0]
+ *
+ * The {default values}[#class-Hash-label-Default+Values] are returned
+ * for any keys that are not found:
+ * h.values_at(:hello, :foo) # => [nil, 0]
*/
VALUE
@@ -2637,22 +2680,26 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
}
/*
- * call-seq:
- * hsh.fetch_values(key, ...) -> array
- * hsh.fetch_values(key, ...) { |key| block } -> array
+ * call-seq:
+ * hash.fetch_values(*keys) -> new_array
+ * hash.fetch_values(*keys) {|key| ... } -> new_array
+ *
+ * Returns a new \Array containing the values associated with the given keys *keys:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.fetch_values(:baz, :foo) # => [2, 0]
*
- * Returns an array containing the values associated with the given keys
- * but also raises KeyError when one of keys can't be found.
- * Also see Hash#values_at and Hash#fetch.
+ * Returns a new empty \Array if no arguments given.
*
- * h = { "cat" => "feline", "dog" => "canine", "cow" => "bovine" }
+ * When a block is given, calls the block with each missing key,
+ * treating the block's return value as the value for that key:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * values = h.fetch_values(:bar, :foo, :bad, :bam) {|key| key.to_s}
+ * values # => [1, 0, "bad", "bam"]
*
- * h.fetch_values("cow", "cat") #=> ["bovine", "feline"]
- * h.fetch_values("cow", "bird") # raises KeyError
- * h.fetch_values("cow", "bird") { |k| k.upcase } #=> ["bovine", "BIRD"]
+ * When no block is given, raises an exception if any given key is not found.
*/
-VALUE
+static VALUE
rb_hash_fetch_values(int argc, VALUE *argv, VALUE hash)
{
VALUE result = rb_ary_new2(argc);
@@ -2675,23 +2722,22 @@ select_i(VALUE key, VALUE value, VALUE result)
/*
* call-seq:
- * hsh.select {|key, value| block} -> a_hash
- * hsh.select -> an_enumerator
- * hsh.filter {|key, value| block} -> a_hash
- * hsh.filter -> an_enumerator
+ * hash.select {|key, value| ... } -> new_hash
+ * hash.select -> new_enumerator
*
- * Returns a new hash consisting of entries for which the block returns true.
- *
- * If no block is given, an enumerator is returned instead.
+ * Hash#filter is an alias for Hash#select.
*
- * h = { "a" => 100, "b" => 200, "c" => 300 }
- * h.select {|k,v| k > "a"} #=> {"b" => 200, "c" => 300}
- * h.select {|k,v| v < 200} #=> {"a" => 100}
+ * Returns a new \Hash object whose entries are those for which the block returns a truthy value:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.select {|key, value| value < 2 } # => {:foo=>0, :bar=>1}
*
- * Hash#filter is an alias for Hash#select.
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.select # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:select>
+ * e.each {|key, value| value < 2 } # => {:foo=>0, :bar=>1}
*/
-VALUE
+static VALUE
rb_hash_select(VALUE hash)
{
VALUE result;
@@ -2708,6 +2754,7 @@ static int
keep_if_i(VALUE key, VALUE value, VALUE hash)
{
if (!RTEST(rb_yield_values(2, key, value))) {
+ rb_hash_modify(hash);
return ST_DELETE;
}
return ST_CONTINUE;
@@ -2715,18 +2762,24 @@ keep_if_i(VALUE key, VALUE value, VALUE hash)
/*
* call-seq:
- * hsh.select! {| key, value | block } -> hsh or nil
- * hsh.select! -> an_enumerator
- * hsh.filter! {| key, value | block } -> hsh or nil
- * hsh.filter! -> an_enumerator
- *
- * Equivalent to Hash#keep_if, but returns
- * +nil+ if no changes were made.
+ * hash.select! {|key, value| ... } -> self or nil
+ * hash.select! -> new_enumerator
*
* Hash#filter! is an alias for Hash#select!.
+ *
+ * Returns +self+, whose entries are those for which the block returns a truthy value:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.select! {|key, value| value < 2 } => {:foo=>0, :bar=>1}
+ *
+ * Returns +nil+ if no entries were removed.
+ *
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.select! # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:select!>
+ * e.each { |key, value| value < 2 } # => {:foo=>0, :bar=>1}
*/
-VALUE
+static VALUE
rb_hash_select_bang(VALUE hash)
{
st_index_t n;
@@ -2742,18 +2795,22 @@ rb_hash_select_bang(VALUE hash)
/*
* call-seq:
- * hsh.keep_if {| key, value | block } -> hsh
- * hsh.keep_if -> an_enumerator
- *
- * Deletes every key-value pair from <i>hsh</i> for which <i>block</i>
- * evaluates to +false+.
- *
- * If no block is given, an enumerator is returned instead.
- *
- * See also Hash#select!.
+ * hash.keep_if {|key, value| ... } -> self
+ * hash.keep_if -> new_enumerator
+ *
+ * Calls the block for each key-value pair;
+ * retains the entry if the block returns a truthy value;
+ * otherwise deletes the entry; returns +self+.
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.keep_if { |key, value| key.start_with?('b') } # => {:bar=>1, :baz=>2}
+ *
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.keep_if # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:keep_if>
+ * e.each { |key, value| key.start_with?('b') } # => {:bar=>1, :baz=>2}
*/
-VALUE
+static VALUE
rb_hash_keep_if(VALUE hash)
{
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
@@ -2772,13 +2829,9 @@ clear_i(VALUE key, VALUE value, VALUE dummy)
/*
* call-seq:
- * hsh.clear -> hsh
- *
- * Removes all key-value pairs from <i>hsh</i>.
- *
- * h = { "a" => 100, "b" => 200 } #=> {"a"=>100, "b"=>200}
- * h.clear #=> {}
+ * hash.clear -> self
*
+ * Removes all hash entries; returns +self+.
*/
VALUE
@@ -2839,29 +2892,28 @@ NOINSERT_UPDATE_CALLBACK(hash_aset_str)
/*
* call-seq:
- * hsh[key] = value -> value
- * hsh.store(key, value) -> value
- *
- * == Element Assignment
- *
- * Associates the value given by +value+ with the key given by +key+.
- *
- * h = { "a" => 100, "b" => 200 }
- * h["a"] = 9
- * h["c"] = 4
- * h #=> {"a"=>9, "b"=>200, "c"=>4}
- * h.store("d", 42) #=> 42
- * h #=> {"a"=>9, "b"=>200, "c"=>4, "d"=>42}
- *
- * +key+ should not have its value changed while it is in use as a key (an
- * <tt>unfrozen String</tt> passed as a key will be duplicated and frozen).
- *
- * a = "a"
- * b = "b".freeze
- * h = { a => 100, b => 200 }
- * h.key(100).equal? a #=> false
- * h.key(200).equal? b #=> true
- *
+ * hash[key] = value -> value
+ * hash.store(key, value)
+ *
+ * Hash#store is an alias for Hash#[]=.
+
+ * Associates the given +value+ with the given +key+; returns +value+.
+ *
+ * If the given +key+ exists, replaces its value with the given +value+;
+ * the ordering is not affected
+ * (see {Entry Order}[#class-Hash-label-Entry+Order]):
+ * h = {foo: 0, bar: 1}
+ * h[:foo] = 2 # => 2
+ * h.store(:bar, 3) # => 3
+ * h # => {:foo=>2, :bar=>3}
+ *
+ * If +key+ does not exist, adds the +key+ and +value+;
+ * the new entry is last in the order
+ * (see {Entry Order}[#class-Hash-label-Entry+Order]):
+ * h = {foo: 0, bar: 1}
+ * h[:baz] = 2 # => 2
+ * h.store(:bat, 3) # => 3
+ * h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
*/
VALUE
@@ -2887,14 +2939,12 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val)
/*
* call-seq:
- * hsh.replace(other_hash) -> hsh
- *
- * Replaces the contents of <i>hsh</i> with the contents of
- * <i>other_hash</i>.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.replace({ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400}
+ * hash.replace(other_hash) -> self
*
+ * Replaces the entire contents of +self+ with the contents of +other_hash+;
+ * returns +self+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.replace({bat: 3, bam: 4}) # => {:bat=>3, :bam=>4}
*/
static VALUE
@@ -2937,16 +2987,11 @@ rb_hash_replace(VALUE hash, VALUE hash2)
/*
* call-seq:
- * hsh.length -> integer
- * hsh.size -> integer
- *
- * Returns the number of key-value pairs in the hash.
+ * hash.length -> integer
+ * hash.size -> integer
*
- * h = { "d" => 100, "a" => 200, "v" => 300, "e" => 400 }
- * h.size #=> 4
- * h.delete("a") #=> 200
- * h.size #=> 3
- * h.length #=> 3
+ * Returns the count of entries in +self+:
+ * {foo: 0, bar: 1, baz: 2}.length # => 3
*
* Hash#length is an alias for Hash#size.
*/
@@ -2965,12 +3010,11 @@ rb_hash_size_num(VALUE hash)
/*
* call-seq:
- * hsh.empty? -> true or false
- *
- * Returns <code>true</code> if <i>hsh</i> contains no key-value pairs.
- *
- * {}.empty? #=> true
+ * hash.empty? -> true or false
*
+ * Returns +true+ if there are no hash entries, +false+ otherwise:
+ * {}.empty? # => true
+ * {foo: 0, bar: 1, baz: 2}.empty? # => false
*/
static VALUE
@@ -2988,21 +3032,26 @@ each_value_i(VALUE key, VALUE value, VALUE _)
/*
* call-seq:
- * hsh.each_value {| value | block } -> hsh
- * hsh.each_value -> an_enumerator
- *
- * Calls <i>block</i> once for each key in <i>hsh</i>, passing the
- * value as a parameter.
- *
- * If no block is given, an enumerator is returned instead.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.each_value {|value| puts value }
- *
- * <em>produces:</em>
- *
- * 100
- * 200
+ * hash.each_value {|value| ... } -> self
+ * hash.each_value -> new_enumerator
+ *
+ * Calls the given block with each value; returns +self+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.each_value {|value| puts value } # => {:foo=>0, :bar=>1, :baz=>2}
+ * Output:
+ * 0
+ * 1
+ * 2
+ *
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.each_value # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:each_value>
+ * h1 = e.each {|value| puts value }
+ * h1 # => {:foo=>0, :bar=>1, :baz=>2}
+ * Output:
+ * 0
+ * 1
+ * 2
*/
static VALUE
@@ -3022,21 +3071,26 @@ each_key_i(VALUE key, VALUE value, VALUE _)
/*
* call-seq:
- * hsh.each_key {| key | block } -> hsh
- * hsh.each_key -> an_enumerator
- *
- * Calls <i>block</i> once for each key in <i>hsh</i>, passing the key
- * as a parameter.
- *
- * If no block is given, an enumerator is returned instead.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.each_key {|key| puts key }
- *
- * <em>produces:</em>
- *
- * a
- * b
+ * hash.each_key {|key| ... } -> self
+ * hash.each_key -> new_enumerator
+ *
+ * Calls the given block with each key; returns +self+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.each_key {|key| puts key } # => {:foo=>0, :bar=>1, :baz=>2}
+ * Output:
+ * foo
+ * bar
+ * baz
+ *
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.each_key # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:each_key>
+ * h1 = e.each {|key| puts key }
+ * h1 # => {:foo=>0, :bar=>1, :baz=>2}
+ * Output:
+ * foo
+ * bar
+ * baz
*/
static VALUE
rb_hash_each_key(VALUE hash)
@@ -3065,37 +3119,65 @@ each_pair_i_fast(VALUE key, VALUE value, VALUE _)
/*
* call-seq:
- * hsh.each {| key, value | block } -> hsh
- * hsh.each_pair {| key, value | block } -> hsh
- * hsh.each -> an_enumerator
- * hsh.each_pair -> an_enumerator
- *
- * Calls <i>block</i> once for each key in <i>hsh</i>, passing the key-value
- * pair as parameters.
- *
- * If no block is given, an enumerator is returned instead.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.each {|key, value| puts "#{key} is #{value}" }
- *
- * <em>produces:</em>
- *
- * a is 100
- * b is 200
- *
+ * hash.each {|key, value| ... } -> self
+ * hash.each_pair {|key, value| ... } -> self
+ * hash.each -> new_enumerator
+ * hash.each_pair -> new_enumerator
+ *
+ * Hash#each is an alias for Hash#each_pair.
+
+ * Calls the given block with each key-value pair; returns +self+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.each_pair {|key, value| puts "#{key}: #{value}"} # => {:foo=>0, :bar=>1, :baz=>2}
+ * Output:
+ * foo: 0
+ * bar: 1
+ * baz: 2
+ *
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.each_pair # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:each_pair>
+ * h1 = e.each {|key, value| puts "#{key}: #{value}"}
+ * h1 # => {:foo=>0, :bar=>1, :baz=>2}
+ * Output:
+ * foo: 0
+ * bar: 1
+ * baz: 2
*/
static VALUE
rb_hash_each_pair(VALUE hash)
{
RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
- if (rb_block_arity() > 1)
+ if (rb_block_pair_yield_optimizable())
rb_hash_foreach(hash, each_pair_i_fast, 0);
else
rb_hash_foreach(hash, each_pair_i, 0);
return hash;
}
+struct transform_keys_args{
+ VALUE trans;
+ VALUE result;
+ int block_given;
+};
+
+static int
+transform_keys_hash_i(VALUE key, VALUE value, VALUE transarg)
+{
+ struct transform_keys_args *p = (void *)transarg;
+ VALUE trans = p->trans, result = p->result;
+ VALUE new_key = rb_hash_lookup2(trans, key, Qundef);
+ if (new_key == Qundef) {
+ if (p->block_given)
+ new_key = rb_yield(key);
+ else
+ new_key = key;
+ }
+ rb_hash_aset(result, new_key, value);
+ return ST_CONTINUE;
+}
+
static int
transform_keys_i(VALUE key, VALUE value, VALUE result)
{
@@ -3106,68 +3188,125 @@ transform_keys_i(VALUE key, VALUE value, VALUE result)
/*
* call-seq:
- * hsh.transform_keys {|key| block } -> new_hash
- * hsh.transform_keys -> an_enumerator
- *
- * Returns a new hash with the results of running the block once for
- * every key.
- * This method does not change the values.
- *
- * h = { a: 1, b: 2, c: 3 }
- * h.transform_keys {|k| k.to_s } #=> { "a" => 1, "b" => 2, "c" => 3 }
- * h.transform_keys(&:to_s) #=> { "a" => 1, "b" => 2, "c" => 3 }
- * h.transform_keys.with_index {|k, i| "#{k}.#{i}" }
- * #=> { "a.0" => 1, "b.1" => 2, "c.2" => 3 }
- *
- * If no block is given, an enumerator is returned instead.
+ * hash.transform_keys {|key| ... } -> new_hash
+ * hash.transform_keys(hash2) -> new_hash
+ * hash.transform_keys(hash2) {|other_key| ...} -> new_hash
+ * hash.transform_keys -> new_enumerator
+ *
+ * Returns a new \Hash object; each entry has:
+ * * A key provided by the block.
+ * * The value from +self+.
+ *
+ * An optional hash argument can be provided to map keys to new keys.
+ * Any key not given will be mapped using the provided block,
+ * or remain the same if no block is given.
+ *
+ * Transform keys:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = h.transform_keys {|key| key.to_s }
+ * h1 # => {"foo"=>0, "bar"=>1, "baz"=>2}
+ *
+ * h.transform_keys(foo: :bar, bar: :foo)
+ * #=> {bar: 0, foo: 1, baz: 2}
+ *
+ * h.transform_keys(foo: :hello, &:to_s)
+ * #=> {:hello=>0, "bar"=>1, "baz"=>2}
+ *
+ * Overwrites values for duplicate keys:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = h.transform_keys {|key| :bat }
+ * h1 # => {:bat=>2}
+ *
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.transform_keys # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:transform_keys>
+ * h1 = e.each { |key| key.to_s }
+ * h1 # => {"foo"=>0, "bar"=>1, "baz"=>2}
*/
static VALUE
-rb_hash_transform_keys(VALUE hash)
+rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash)
{
VALUE result;
+ struct transform_keys_args transarg = {0};
- RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
+ argc = rb_check_arity(argc, 0, 1);
+ if (argc > 0) {
+ transarg.trans = to_hash(argv[0]);
+ transarg.block_given = rb_block_given_p();
+ }
+ else {
+ RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
+ }
result = rb_hash_new();
if (!RHASH_EMPTY_P(hash)) {
- rb_hash_foreach(hash, transform_keys_i, result);
+ if (transarg.trans) {
+ transarg.result = result;
+ rb_hash_foreach(hash, transform_keys_hash_i, (VALUE)&transarg);
+ }
+ else {
+ rb_hash_foreach(hash, transform_keys_i, result);
+ }
}
return result;
}
-static VALUE rb_hash_flatten(int argc, VALUE *argv, VALUE hash);
+static int flatten_i(VALUE key, VALUE val, VALUE ary);
/*
* call-seq:
- * hsh.transform_keys! {|key| block } -> hsh
- * hsh.transform_keys! -> an_enumerator
+ * hash.transform_keys! {|key| ... } -> self
+ * hash.transform_keys!(hash2) -> self
+ * hash.transform_keys!(hash2) {|other_key| ...} -> self
+ * hash.transform_keys! -> new_enumerator
*
- * Invokes the given block once for each key in <i>hsh</i>, replacing it
- * with the new key returned by the block, and then returns <i>hsh</i>.
- * This method does not change the values.
- *
- * h = { a: 1, b: 2, c: 3 }
- * h.transform_keys! {|k| k.to_s } #=> { "a" => 1, "b" => 2, "c" => 3 }
- * h.transform_keys!(&:to_sym) #=> { a: 1, b: 2, c: 3 }
- * h.transform_keys!.with_index {|k, i| "#{k}.#{i}" }
- * #=> { "a.0" => 1, "b.1" => 2, "c.2" => 3 }
- *
- * If no block is given, an enumerator is returned instead.
+ * Same as Hash#transform_keys but modifies the receiver in place
+ * instead of returning a new hash.
*/
static VALUE
-rb_hash_transform_keys_bang(VALUE hash)
+rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
{
- RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
+ VALUE trans = 0;
+ int block_given = 0;
+
+ argc = rb_check_arity(argc, 0, 1);
+ if (argc > 0) {
+ trans = to_hash(argv[0]);
+ block_given = rb_block_given_p();
+ }
+ else {
+ RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
+ }
rb_hash_modify_check(hash);
if (!RHASH_TABLE_EMPTY_P(hash)) {
long i;
- VALUE pairs = rb_hash_flatten(0, NULL, hash);
- rb_hash_clear(hash);
+ VALUE new_keys = hash_alloc(0);
+ VALUE pairs = rb_ary_tmp_new(RHASH_SIZE(hash) * 2);
+ rb_hash_foreach(hash, flatten_i, pairs);
for (i = 0; i < RARRAY_LEN(pairs); i += 2) {
- VALUE key = RARRAY_AREF(pairs, i), new_key = rb_yield(key),
- val = RARRAY_AREF(pairs, i+1);
+ VALUE key = RARRAY_AREF(pairs, i), new_key, val;
+
+ if (!trans) {
+ new_key = rb_yield(key);
+ }
+ else if ((new_key = rb_hash_lookup2(trans, key, Qundef)) != Qundef) {
+ /* use the transformed key */
+ }
+ else if (block_given) {
+ new_key = rb_yield(key);
+ }
+ else {
+ new_key = key;
+ }
+ val = RARRAY_AREF(pairs, i+1);
+ if (!hash_stlike_lookup(new_keys, key, NULL)) {
+ rb_hash_stlike_delete(hash, &key, NULL);
+ }
rb_hash_aset(hash, new_key, val);
+ rb_hash_aset(new_keys, new_key, Qnil);
}
+ rb_ary_clear(pairs);
+ rb_hash_clear(new_keys);
}
return hash;
}
@@ -3183,26 +3322,30 @@ transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t arg
{
VALUE new_value = rb_yield((VALUE)*value);
VALUE hash = (VALUE)argp;
+ rb_hash_modify(hash);
RB_OBJ_WRITE(hash, value, new_value);
return ST_CONTINUE;
}
/*
* call-seq:
- * hsh.transform_values {|value| block } -> new_hash
- * hsh.transform_values -> an_enumerator
- *
- * Returns a new hash with the results of running the block once for
- * every value.
- * This method does not change the keys.
- *
- * h = { a: 1, b: 2, c: 3 }
- * h.transform_values {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 }
- * h.transform_values(&:to_s) #=> { a: "1", b: "2", c: "3" }
- * h.transform_values.with_index {|v, i| "#{v}.#{i}" }
- * #=> { a: "1.0", b: "2.1", c: "3.2" }
- *
- * If no block is given, an enumerator is returned instead.
+ * hash.transform_values {|value| ... } -> new_hash
+ * hash.transform_values -> new_enumerator
+ *
+ * Returns a new \Hash object; each entry has:
+ * * A key from +self+.
+ * * A value provided by the block.
+ *
+ * Transform values:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = h.transform_values {|value| value * 100}
+ * h1 # => {:foo=>0, :bar=>100, :baz=>200}
+ *
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.transform_values # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:transform_values>
+ * h1 = e.each { |value| value * 100}
+ * h1 # => {:foo=>0, :bar=>100, :baz=>200}
*/
static VALUE
rb_hash_transform_values(VALUE hash)
@@ -3222,20 +3365,18 @@ rb_hash_transform_values(VALUE hash)
/*
* call-seq:
- * hsh.transform_values! {|value| block } -> hsh
- * hsh.transform_values! -> an_enumerator
- *
- * Invokes the given block once for each value in <i>hsh</i>, replacing it
- * with the new value returned by the block, and then returns <i>hsh</i>.
- * This method does not change the keys.
- *
- * h = { a: 1, b: 2, c: 3 }
- * h.transform_values! {|v| v * v + 1 } #=> { a: 2, b: 5, c: 10 }
- * h.transform_values!(&:to_s) #=> { a: "2", b: "5", c: "10" }
- * h.transform_values!.with_index {|v, i| "#{v}.#{i}" }
- * #=> { a: "2.0", b: "5.1", c: "10.2" }
- *
- * If no block is given, an enumerator is returned instead.
+ * hash.transform_values! {|value| ... } -> self
+ * hash.transform_values! -> new_enumerator
+ *
+ * Returns +self+, whose keys are unchanged, and whose values are determined by the given block.
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_values! {|value| value * 100} # => {:foo=>0, :bar=>100, :baz=>200}
+ *
+ * Returns a new \Enumerator if no block given:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * e = h.transform_values! # => #<Enumerator: {:foo=>0, :bar=>100, :baz=>200}:transform_values!>
+ * h1 = e.each {|value| value * 100}
+ * h1 # => {:foo=>0, :bar=>100, :baz=>200}
*/
static VALUE
rb_hash_transform_values_bang(VALUE hash)
@@ -3259,13 +3400,12 @@ to_a_i(VALUE key, VALUE value, VALUE ary)
/*
* call-seq:
- * hsh.to_a -> array
- *
- * Converts <i>hsh</i> to a nested array of <code>[</code> <i>key,
- * value</i> <code>]</code> arrays.
+ * hash.to_a -> new_array
*
- * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
- * h.to_a #=> [["c", 300], ["a", 100], ["d", 400]]
+ * Returns a new \Array of 2-element \Array objects;
+ * each nested \Array contains a key-value pair from +self+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.to_a # => [[:foo, 0], [:bar, 1], [:baz, 2]]
*/
static VALUE
@@ -3313,14 +3453,14 @@ inspect_hash(VALUE hash, VALUE dummy, int recur)
}
/*
- * call-seq:
- * hsh.to_s -> string
- * hsh.inspect -> string
+ * call-seq:
+ * hash.inspect -> new_string
*
- * Return the contents of this hash as a string.
+ * Returns a new \String containing the hash entries:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.inspect # => "{:foo=>0, :bar=>1, :baz=>2}"
*
- * h = { "c" => 300, "a" => 100, "d" => 400, "c" => 300 }
- * h.to_s #=> "{\"c\"=>300, \"a\"=>100, \"d\"=>400}"
+ * Hash#to_s is an alias for Hash#inspect.
*/
static VALUE
@@ -3332,12 +3472,11 @@ rb_hash_inspect(VALUE hash)
}
/*
- * call-seq:
- * hsh.to_hash => hsh
+ * call-seq:
+ * hash.to_hash -> self
*
- * Returns +self+.
+ * Returns +self+.
*/
-
static VALUE
rb_hash_to_hash(VALUE hash)
{
@@ -3379,14 +3518,21 @@ rb_hash_to_h_block(VALUE hash)
/*
* call-seq:
- * hsh.to_h -> hsh or new_hash
- * hsh.to_h {|key, value| block } -> new_hash
+ * hash.to_h -> self or new_hash
+ * hash.to_h {|key, value| ... } -> new_hash
+ *
+ * For an instance of \Hash, returns +self+.
*
- * Returns +self+. If called on a subclass of Hash, converts
- * the receiver to a Hash object.
+ * For a subclass of \Hash, returns a new \Hash
+ * containing the content of +self+.
*
- * If a block is given, the results of the block on each pair of
- * the receiver will be used as pairs.
+ * When a block is given, returns a new \Hash object
+ * whose content is based on the block;
+ * the block should return a 2-element \Array object
+ * specifying the key-value pair to be included in the returned \Array:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = h.to_h {|key, value| [value, key] }
+ * h1 # => {0=>:foo, 1=>:bar, 2=>:baz}
*/
static VALUE
@@ -3411,14 +3557,11 @@ keys_i(VALUE key, VALUE value, VALUE ary)
/*
* call-seq:
- * hsh.keys -> array
- *
- * Returns a new array populated with the keys from this hash. See also
- * Hash#values.
- *
- * h = { "a" => 100, "b" => 200, "c" => 300, "d" => 400 }
- * h.keys #=> ["a", "b", "c", "d"]
+ * hash.keys -> new_array
*
+ * Returns a new \Array containing all keys in +self+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.keys # => [:foo, :bar, :baz]
*/
MJIT_FUNC_EXPORTED VALUE
@@ -3458,14 +3601,11 @@ values_i(VALUE key, VALUE value, VALUE ary)
/*
* call-seq:
- * hsh.values -> array
- *
- * Returns a new array populated with the values from <i>hsh</i>. See
- * also Hash#keys.
- *
- * h = { "a" => 100, "b" => 200, "c" => 300 }
- * h.values #=> [100, 200, 300]
+ * hash.values -> new_array
*
+ * Returns a new \Array containing all values in +self+:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.values # => [0, 1, 2]
*/
VALUE
@@ -3493,6 +3633,7 @@ rb_hash_values(VALUE hash)
}
rb_ary_set_len(values, size);
}
+
else {
rb_hash_foreach(hash, values_i, values);
}
@@ -3502,21 +3643,14 @@ rb_hash_values(VALUE hash)
/*
* call-seq:
- * hsh.has_key?(key) -> true or false
- * hsh.include?(key) -> true or false
- * hsh.key?(key) -> true or false
- * hsh.member?(key) -> true or false
- *
- * Returns <code>true</code> if the given key is present in <i>hsh</i>.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.has_key?("a") #=> true
- * h.has_key?("z") #=> false
- *
- * Note that #include? and #member? do not test member
- * equality using <code>==</code> as do other Enumerables.
+ * hash.include?(key) -> true or false
+ * hash.has_key?(key) -> true or false
+ * hash.key?(key) -> true or false
+ * hash.member?(key) -> true or false
+
+ * Methods #has_key?, #key?, and #member? are aliases for \#include?.
*
- * See also Enumerable#include?
+ * Returns +true+ if +key+ is a key in +self+, otherwise +false+.
*/
MJIT_FUNC_EXPORTED VALUE
@@ -3544,15 +3678,9 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hsh.has_value?(value) -> true or false
- * hsh.value?(value) -> true or false
+ * hash.has_value?(value) -> true or false
*
- * Returns <code>true</code> if the given value is present for some key
- * in <i>hsh</i>.
- *
- * h = { "a" => 100, "b" => 200 }
- * h.value?(100) #=> true
- * h.value?(999) #=> false
+ * Returns +true+ if +value+ is a value in +self+, otherwise +false+.
*/
static VALUE
@@ -3649,26 +3777,21 @@ hash_equal(VALUE hash1, VALUE hash2, int eql)
/*
* call-seq:
- * hsh == other_hash -> true or false
- *
- * Equality---Two hashes are equal if they each contain the same number
- * of keys and if each key-value pair is equal to (according to
- * Object#==) the corresponding elements in the other hash.
+ * hash == object -> true or false
*
- * h1 = { "a" => 1, "c" => 2 }
- * h2 = { 7 => 35, "c" => 2, "a" => 1 }
- * h3 = { "a" => 1, "c" => 2, 7 => 35 }
- * h4 = { "a" => 1, "d" => 2, "f" => 35 }
- * h1 == h2 #=> false
- * h2 == h3 #=> true
- * h3 == h4 #=> false
+ * Returns +true+ if all of the following are true:
+ * * +object+ is a \Hash object.
+ * * +hash+ and +object+ have the same keys (regardless of order).
+ * * For each key +key+, <tt>hash[key] == object[key]</tt>.
*
- * The orders of each hashes are not compared.
- *
- * h1 = { "a" => 1, "c" => 2 }
- * h2 = { "c" => 2, "a" => 1 }
- * h1 == h2 #=> true
+ * Otherwise, returns +false+.
*
+ * Equal:
+ * h1 = {foo: 0, bar: 1, baz: 2}
+ * h2 = {foo: 0, bar: 1, baz: 2}
+ * h1 == h2 # => true
+ * h3 = {baz: 2, bar: 1, foo: 0}
+ * h1 == h3 # => true
*/
static VALUE
@@ -3679,11 +3802,21 @@ rb_hash_equal(VALUE hash1, VALUE hash2)
/*
* call-seq:
- * hash.eql?(other) -> true or false
+ * hash.eql? object -> true or false
+ *
+ * Returns +true+ if all of the following are true:
+ * * +object+ is a \Hash object.
+ * * +hash+ and +object+ have the same keys (regardless of order).
+ * * For each key +key+, <tt>h[key] eql? object[key]</tt>.
*
- * Returns <code>true</code> if <i>hash</i> and <i>other</i> are
- * both hashes with the same content.
- * The orders of each hashes are not compared.
+ * Otherwise, returns +false+.
+ *
+ * Equal:
+ * h1 = {foo: 0, bar: 1, baz: 2}
+ * h2 = {foo: 0, bar: 1, baz: 2}
+ * h1.eql? h2 # => true
+ * h3 = {baz: 2, bar: 1, foo: 0}
+ * h1.eql? h3 # => true
*/
static VALUE
@@ -3706,12 +3839,16 @@ hash_i(VALUE key, VALUE val, VALUE arg)
/*
* call-seq:
- * hsh.hash -> integer
+ * hash.hash -> an_integer
*
- * Compute a hash-code for this hash. Two hashes with the same content
- * will have the same hash code (and will compare using <code>eql?</code>).
+ * Returns the \Integer hash-code for the hash.
*
- * See also Object#hash.
+ * Two \Hash objects have the same hash-code if their content is the same
+ * (regardless or order):
+ * h1 = {foo: 0, bar: 1, baz: 2}
+ * h2 = {baz: 2, bar: 1, foo: 0}
+ * h2.hash == h1.hash # => true
+ * h2.eql? h1 # => true
*/
static VALUE
@@ -3736,32 +3873,17 @@ rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
/*
* call-seq:
- * hsh.invert -> new_hash
- *
- * Returns a new hash created by using <i>hsh</i>'s values as keys, and
- * the keys as values.
- * If a key with the same value already exists in the <i>hsh</i>, then
- * the last one defined will be used, the earlier value(s) will be discarded.
- *
- * h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
- * h.invert #=> {0=>"a", 100=>"m", 200=>"d", 300=>"y"}
- *
- * If there is no key with the same value, Hash#invert is involutive.
+ * hash.invert -> new_hash
*
- * h = { a: 1, b: 3, c: 4 }
- * h.invert.invert == h #=> true
- *
- * The condition, no key with the same value, can be tested by comparing
- * the size of inverted hash.
- *
- * # no key with the same value
- * h = { a: 1, b: 3, c: 4 }
- * h.size == h.invert.size #=> true
- *
- * # two (or more) keys has the same value
- * h = { a: 1, b: 3, c: 1 }
- * h.size == h.invert.size #=> false
+ * Returns a new \Hash object with the each key-value pair inverted:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = h.invert
+ * h1 # => {0=>:foo, 1=>:bar, 2=>:baz}
*
+ * Overwrites any repeated new keys:
+ * (see {Entry Order}[#class-Hash-label-Entry+Order]):
+ * h = {foo: 0, bar: 0, baz: 0}
+ * h.invert # => {0=>:baz}
*/
static VALUE
@@ -3825,45 +3947,52 @@ rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
/*
* call-seq:
- * hsh.merge!(other_hash1, other_hash2, ...) -> hsh
- * hsh.update(other_hash1, other_hash2, ...) -> hsh
- * hsh.merge!(other_hash1, other_hash2, ...) {|key, oldval, newval| block}
- * -> hsh
- * hsh.update(other_hash1, other_hash2, ...) {|key, oldval, newval| block}
- * -> hsh
- *
- * Adds the contents of the given hashes to the receiver.
- *
- * If no block is given, entries with duplicate keys are overwritten
- * with the values from each +other_hash+ successively,
- * otherwise the value for each duplicate key is determined by
- * calling the block with the key, its value in the receiver and
- * its value in each +other_hash+.
- *
- * h1 = { "a" => 100, "b" => 200 }
- * h1.merge! #=> {"a"=>100, "b"=>200}
- * h1 #=> {"a"=>100, "b"=>200}
- *
- * h1 = { "a" => 100, "b" => 200 }
- * h2 = { "b" => 246, "c" => 300 }
- * h1.merge!(h2) #=> {"a"=>100, "b"=>246, "c"=>300}
- * h1 #=> {"a"=>100, "b"=>246, "c"=>300}
- *
- * h1 = { "a" => 100, "b" => 200 }
- * h2 = { "b" => 246, "c" => 300 }
- * h3 = { "b" => 357, "d" => 400 }
- * h1.merge!(h2, h3)
- * #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400}
- * h1 #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400}
- *
- * h1 = { "a" => 100, "b" => 200 }
- * h2 = { "b" => 246, "c" => 300 }
- * h3 = { "b" => 357, "d" => 400 }
- * h1.merge!(h2, h3) {|key, v1, v2| v1 }
- * #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}
- * h1 #=> {"a"=>100, "b"=>200, "c"=>300, "d"=>400}
- *
- * Hash#update is an alias for Hash#merge!.
+ * hash.merge! -> self
+ * hash.merge!(*other_hashes) -> self
+ * hash.merge!(*other_hashes) { |key, old_value, new_value| ... } -> self
+ *
+ * Merges each of +other_hashes+ into +self+; returns +self+.
+ *
+ * Each argument in +other_hashes+ must be a \Hash.
+ *
+ * \Method #update is an alias for \#merge!.
+ *
+ * With arguments and no block:
+ * * Returns +self+, after the given hashes are merged into it.
+ * * The given hashes are merged left to right.
+ * * Each new entry is added at the end.
+ * * Each duplicate-key entry's value overwrites the previous value.
+ *
+ * Example:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = {bat: 3, bar: 4}
+ * h2 = {bam: 5, bat:6}
+ * h.merge!(h1, h2) # => {:foo=>0, :bar=>4, :baz=>2, :bat=>6, :bam=>5}
+ *
+ * With arguments and a block:
+ * * Returns +self+, after the given hashes are merged.
+ * * The given hashes are merged left to right.
+ * * Each new-key entry is added at the end.
+ * * For each duplicate key:
+ * * Calls the block with the key and the old and new values.
+ * * The block's return value becomes the new value for the entry.
+ *
+ * Example:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = {bat: 3, bar: 4}
+ * h2 = {bam: 5, bat:6}
+ * h3 = h.merge!(h1, h2) { |key, old_value, new_value| old_value + new_value }
+ * h3 # => {:foo=>0, :bar=>5, :baz=>2, :bat=>9, :bam=>5}
+ *
+ * With no arguments:
+ * * Returns +self+, unmodified.
+ * * The block, if given, is ignored.
+ *
+ * Example:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.merge # => {:foo=>0, :bar=>1, :baz=>2}
+ * h1 = h.merge! { |key, old_value, new_value| raise 'Cannot happen' }
+ * h1 # => {:foo=>0, :bar=>1, :baz=>2}
*/
static VALUE
@@ -3941,33 +4070,53 @@ rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
/*
* call-seq:
- * hsh.merge(other_hash1, other_hash2, ...) -> new_hash
- * hsh.merge(other_hash1, other_hash2, ...) {|key, oldval, newval| block}
- * -> new_hash
- *
- * Returns a new hash that combines the contents of the receiver and
- * the contents of the given hashes.
- *
- * If no block is given, entries with duplicate keys are overwritten
- * with the values from each +other_hash+ successively,
- * otherwise the value for each duplicate key is determined by
- * calling the block with the key, its value in the receiver and
- * its value in each +other_hash+.
- *
- * When called without any argument, returns a copy of the receiver.
- *
- * h1 = { "a" => 100, "b" => 200 }
- * h2 = { "b" => 246, "c" => 300 }
- * h3 = { "b" => 357, "d" => 400 }
- * h1.merge #=> {"a"=>100, "b"=>200}
- * h1.merge(h2) #=> {"a"=>100, "b"=>246, "c"=>300}
- * h1.merge(h2, h3) #=> {"a"=>100, "b"=>357, "c"=>300, "d"=>400}
- * h1.merge(h2) {|key, oldval, newval| newval - oldval}
- * #=> {"a"=>100, "b"=>46, "c"=>300}
- * h1.merge(h2, h3) {|key, oldval, newval| newval - oldval}
- * #=> {"a"=>100, "b"=>311, "c"=>300, "d"=>400}
- * h1 #=> {"a"=>100, "b"=>200}
- *
+ * hash.merge -> copy_of_self
+ * hash.merge(*other_hashes) -> new_hash
+ * hash.merge(*other_hashes) { |key, old_value, new_value| ... } -> new_hash
+ *
+ * Returns the new \Hash formed by merging each of +other_hashes+
+ * into a copy of +self+.
+ *
+ * Each argument in +other_hashes+ must be a \Hash.
+ *
+ * ---
+ *
+ * With arguments and no block:
+ * * Returns the new \Hash object formed by merging each successive
+ * \Hash in +other_hashes+ into +self+.
+ * * Each new-key entry is added at the end.
+ * * Each duplicate-key entry's value overwrites the previous value.
+ *
+ * Example:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = {bat: 3, bar: 4}
+ * h2 = {bam: 5, bat:6}
+ * h.merge(h1, h2) # => {:foo=>0, :bar=>4, :baz=>2, :bat=>6, :bam=>5}
+ *
+ * With arguments and a block:
+ * * Returns a new \Hash object that is the merge of +self+ and each given hash.
+ * * The given hashes are merged left to right.
+ * * Each new-key entry is added at the end.
+ * * For each duplicate key:
+ * * Calls the block with the key and the old and new values.
+ * * The block's return value becomes the new value for the entry.
+ *
+ * Example:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h1 = {bat: 3, bar: 4}
+ * h2 = {bam: 5, bat:6}
+ * h3 = h.merge(h1, h2) { |key, old_value, new_value| old_value + new_value }
+ * h3 # => {:foo=>0, :bar=>5, :baz=>2, :bat=>9, :bam=>5}
+ *
+ * With no arguments:
+ * * Returns a copy of +self+.
+ * * The block, if given, is ignored.
+ *
+ * Example:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.merge # => {:foo=>0, :bar=>1, :baz=>2}
+ * h1 = h.merge { |key, old_value, new_value| raise 'Cannot happen' }
+ * h1 # => {:foo=>0, :bar=>1, :baz=>2}
*/
static VALUE
@@ -4017,16 +4166,13 @@ assoc_i(VALUE key, VALUE val, VALUE arg)
/*
* call-seq:
- * hash.assoc(obj) -> an_array or nil
+ * hash.assoc(key) -> new_array or nil
*
- * Searches through the hash comparing _obj_ with the key using <code>==</code>.
- * Returns the key-value pair (two elements array) or +nil+
- * if no match is found. See Array#assoc.
+ * If the given +key+ is found, returns a 2-element \Array containing that key and its value:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.assoc(:bar) # => [:bar, 1]
*
- * h = {"colors" => ["red", "blue", "green"],
- * "letters" => ["a", "b", "c" ]}
- * h.assoc("letters") #=> ["letters", ["a", "b", "c"]]
- * h.assoc("foo") #=> nil
+ * Returns +nil+ if key +key+ is not found.
*/
VALUE
@@ -4079,15 +4225,15 @@ rassoc_i(VALUE key, VALUE val, VALUE arg)
/*
* call-seq:
- * hash.rassoc(obj) -> an_array or nil
+ * hash.rassoc(value) -> new_array or nil
*
- * Searches through the hash comparing _obj_ with the value using <code>==</code>.
- * Returns the first key-value pair (two-element array) that matches. See
- * also Array#rassoc.
+ * Returns a new 2-element \Array consisting of the key and value
+ * of the first-found entry whose value is <tt>==</tt> to value
+ * (see {Entry Order}[#class-Hash-label-Entry+Order]):
+ * h = {foo: 0, bar: 1, baz: 1}
+ * h.rassoc(1) # => [:bar, 1]
*
- * a = {1=> "one", 2 => "two", 3 => "three", "ii" => "two"}
- * a.rassoc("two") #=> [2, "two"]
- * a.rassoc("four") #=> nil
+ * Returns +nil+ if no such value found.
*/
VALUE
@@ -4115,18 +4261,33 @@ flatten_i(VALUE key, VALUE val, VALUE ary)
/*
* call-seq:
- * hash.flatten -> an_array
- * hash.flatten(level) -> an_array
- *
- * Returns a new array that is a one-dimensional flattening of this
- * hash. That is, for every key or value that is an array, extract
- * its elements into the new array. Unlike Array#flatten, this
- * method does not flatten recursively by default. The optional
- * <i>level</i> argument determines the level of recursion to flatten.
- *
- * a = {1=> "one", 2 => [2,"two"], 3 => "three"}
- * a.flatten # => [1, "one", 2, [2, "two"], 3, "three"]
- * a.flatten(2) # => [1, "one", 2, 2, "two", 3, "three"]
+ * hash.flatten -> new_array
+ * hash.flatten(level) -> new_array
+ *
+ * Returns a new \Array object that is a 1-dimensional flattening of +self+.
+ *
+ * ---
+ *
+ * By default, nested Arrays are not flattened:
+ * h = {foo: 0, bar: [:bat, 3], baz: 2}
+ * h.flatten # => [:foo, 0, :bar, [:bat, 3], :baz, 2]
+ *
+ * Takes the depth of recursive flattening from \Integer argument +level+:
+ * h = {foo: 0, bar: [:bat, [:baz, [:bat, ]]]}
+ * h.flatten(1) # => [:foo, 0, :bar, [:bat, [:baz, [:bat]]]]
+ * h.flatten(2) # => [:foo, 0, :bar, :bat, [:baz, [:bat]]]
+ * h.flatten(3) # => [:foo, 0, :bar, :bat, :baz, [:bat]]
+ * h.flatten(4) # => [:foo, 0, :bar, :bat, :baz, :bat]
+ *
+ * When +level+ is negative, flattens all nested Arrays:
+ * h = {foo: 0, bar: [:bat, [:baz, [:bat, ]]]}
+ * h.flatten(-1) # => [:foo, 0, :bar, :bat, :baz, :bat]
+ * h.flatten(-2) # => [:foo, 0, :bar, :bat, :baz, :bat]
+ *
+ * When +level+ is zero, returns the equivalent of #to_a :
+ * h = {foo: 0, bar: [:bat, 3], baz: 2}
+ * h.flatten(0) # => [[:foo, 0], [:bar, [:bat, 3]], [:baz, 2]]
+ * h.flatten(0) == h.to_a # => true
*/
static VALUE
@@ -4182,14 +4343,12 @@ set_if_not_nil(VALUE key, VALUE value, VALUE hash)
/*
* call-seq:
- * hsh.compact -> new_hash
- *
- * Returns a new hash with the nil values/key pairs removed
- *
- * h = { a: 1, b: false, c: nil }
- * h.compact #=> { a: 1, b: false }
- * h #=> { a: 1, b: false, c: nil }
+ * hash.compact -> new_hash
*
+ * Returns a copy of +self+ with all +nil+-valued entries removed:
+ * h = {foo: 0, bar: nil, baz: 2, bat: nil}
+ * h1 = h.compact
+ * h1 # => {:foo=>0, :baz=>2}
*/
static VALUE
@@ -4204,14 +4363,13 @@ rb_hash_compact(VALUE hash)
/*
* call-seq:
- * hsh.compact! -> hsh or nil
+ * hash.compact! -> self or nil
*
- * Removes all nil values from the hash.
- * Returns nil if no changes were made, otherwise returns the hash.
- *
- * h = { a: 1, b: false, c: nil }
- * h.compact! #=> { a: 1, b: false }
+ * Returns +self+ with all its +nil+-valued entries removed (in place):
+ * h = {foo: 0, bar: nil, baz: 2, bat: nil}
+ * h.compact! # => {:foo=>0, :baz=>2}
*
+ * Returns +nil+ if no entries were removed.
*/
static VALUE
@@ -4232,18 +4390,30 @@ static st_table *rb_init_identtable_with_size(st_index_t size);
/*
* call-seq:
- * hsh.compare_by_identity -> hsh
- *
- * Makes <i>hsh</i> compare its keys by their identity, i.e. it
- * will consider exact same objects as same keys.
- *
- * h1 = { "a" => 100, "b" => 200, :c => "c" }
- * h1["a"] #=> 100
- * h1.compare_by_identity
- * h1.compare_by_identity? #=> true
- * h1["a".dup] #=> nil # different objects.
- * h1[:c] #=> "c" # same symbols are all same.
- *
+ * hash.compare_by_identity -> self
+ *
+ * Sets +self+ to consider only identity in comparing keys;
+ * two keys are considered the same only if they are the same object;
+ * returns +self+.
+ *
+ * By default, these two object are considered to be the same key,
+ * so +s1+ will overwrite +s0+:
+ * s0 = 'x'
+ * s1 = 'x'
+ * h = {}
+ * h.compare_by_identity? # => false
+ * h[s0] = 0
+ * h[s1] = 1
+ * h # => {"x"=>1}
+ *
+ * After calling \#compare_by_identity, the keys are considered to be different,
+ * and therefore do not overwrite each other:
+ * h = {}
+ * h.compare_by_identity # => {}
+ * h.compare_by_identity? # => true
+ * h[s0] = 0
+ * h[s1] = 1
+ * h # => {"x"=>0, "x"=>1}
*/
static VALUE
@@ -4272,11 +4442,9 @@ rb_hash_compare_by_id(VALUE hash)
/*
* call-seq:
- * hsh.compare_by_identity? -> true or false
- *
- * Returns <code>true</code> if <i>hsh</i> will compare its keys by
- * their identity. Also see Hash#compare_by_identity.
+ * hash.compare_by_identity? -> true or false
*
+ * Returns +true+ if #compare_by_identity has been called, +false+ otherwise.
*/
MJIT_FUNC_EXPORTED VALUE
@@ -4345,10 +4513,31 @@ any_p_i_pattern(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hsh.any? [{ |(key, value)| block }] -> true or false
- * hsh.any?(pattern) -> true or false
- *
- * See also Enumerable#any?
+ * hash.any? -> true or false
+ * hash.any?(object) -> true or false
+ * hash.any? {|key, value| ... } -> true or false
+ *
+ * Returns +true+ if any element satisfies a given criterion;
+ * +false+ otherwise.
+ *
+ * With no argument and no block,
+ * returns +true+ if +self+ is non-empty; +false+ if empty.
+ *
+ * With argument +object+ and no block,
+ * returns +true+ if for any key +key+
+ * <tt>h.assoc(key) == object</tt>:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.any?([:bar, 1]) # => true
+ * h.any?([:bar, 0]) # => false
+ * h.any?([:baz, 1]) # => false
+ *
+ * With no argument and a block,
+ * calls the block with each key-value pair;
+ * returns +true+ if the block returns any truthy value,
+ * +false+ otherwise:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.any? {|key, value| value < 3 } # => true
+ * h.any? {|key, value| value > 3 } # => false
*/
static VALUE
@@ -4372,7 +4561,7 @@ rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
/* yields pairs, never false */
return Qtrue;
}
- if (rb_block_arity() > 1)
+ if (rb_block_pair_yield_optimizable())
rb_hash_foreach(hash, any_p_i_fast, (VALUE)args);
else
rb_hash_foreach(hash, any_p_i, (VALUE)args);
@@ -4381,22 +4570,32 @@ rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
}
/*
- * call-seq:
- * hsh.dig(key, ...) -> object
- *
- * Extracts the nested value specified by the sequence of <i>key</i>
- * objects by calling +dig+ at each step, returning +nil+ if any
- * intermediate step is +nil+.
- *
- * h = { foo: {bar: {baz: 1}}}
- *
- * h.dig(:foo, :bar, :baz) #=> 1
- * h.dig(:foo, :zot, :xyz) #=> nil
- *
- * g = { foo: [10, 11, 12] }
- * g.dig(:foo, 1) #=> 11
- * g.dig(:foo, 1, 0) #=> TypeError: Integer does not have #dig method
- * g.dig(:foo, :bar) #=> TypeError: no implicit conversion of Symbol into Integer
+ * call-seq:
+ * hash.dig(key, *identifiers) -> object
+ *
+ * Finds and returns the object in nested objects
+ * that is specified by +key+ and +identifiers+.
+ * The nested objects may be instances of various classes.
+ * See {Dig Methods}[rdoc-ref:doc/dig_methods.rdoc].
+ *
+ * Nested Hashes:
+ * h = {foo: {bar: {baz: 2}}}
+ * h.dig(:foo) # => {:bar=>{:baz=>2}}
+ * h.dig(:foo, :bar) # => {:bar=>{:baz=>2}}
+ * h.dig(:foo, :bar, :baz) # => 2
+ * h.dig(:foo, :bar, :BAZ) # => nil
+ *
+ * Nested Hashes and Arrays:
+ * h = {foo: {bar: [:a, :b, :c]}}
+ * h.dig(:foo, :bar, 2) # => :c
+ *
+ * This method will use the {default values}[#class-Hash-label-Default+Values]
+ * for keys that are not present:
+ * h = {foo: {bar: [:a, :b, :c]}}
+ * h.dig(:hello) # => nil
+ * h.default_proc = -> (hash, _key) { hash }
+ * h.dig(:hello, :world) # => h
+ * h.dig(:hello, :world, :foo, :bar, 2) # => :c
*/
static VALUE
@@ -4430,17 +4629,15 @@ hash_le(VALUE hash1, VALUE hash2)
}
/*
- * call-seq:
- * hash <= other -> true or false
- *
- * Returns <code>true</code> if <i>hash</i> is subset of
- * <i>other</i> or equals to <i>other</i>.
- *
- * h1 = {a:1, b:2}
- * h2 = {a:1, b:2, c:3}
- * h1 <= h2 #=> true
- * h2 <= h1 #=> false
- * h1 <= h1 #=> true
+ * call-seq:
+ * hash <= other_hash -> true or false
+ *
+ * Returns +true+ if +hash+ is a subset of +other_hash+, +false+ otherwise:
+ * h1 = {foo: 0, bar: 1}
+ * h2 = {foo: 0, bar: 1, baz: 2}
+ * h1 <= h2 # => true
+ * h2 <= h1 # => false
+ * h1 <= h1 # => true
*/
static VALUE
rb_hash_le(VALUE hash, VALUE other)
@@ -4451,17 +4648,15 @@ rb_hash_le(VALUE hash, VALUE other)
}
/*
- * call-seq:
- * hash < other -> true or false
- *
- * Returns <code>true</code> if <i>hash</i> is subset of
- * <i>other</i>.
- *
- * h1 = {a:1, b:2}
- * h2 = {a:1, b:2, c:3}
- * h1 < h2 #=> true
- * h2 < h1 #=> false
- * h1 < h1 #=> false
+ * call-seq:
+ * hash < other_hash -> true or false
+ *
+ * Returns +true+ if +hash+ is a proper subset of +other_hash+, +false+ otherwise:
+ * h1 = {foo: 0, bar: 1}
+ * h2 = {foo: 0, bar: 1, baz: 2}
+ * h1 < h2 # => true
+ * h2 < h1 # => false
+ * h1 < h1 # => false
*/
static VALUE
rb_hash_lt(VALUE hash, VALUE other)
@@ -4472,17 +4667,15 @@ rb_hash_lt(VALUE hash, VALUE other)
}
/*
- * call-seq:
- * hash >= other -> true or false
- *
- * Returns <code>true</code> if <i>other</i> is subset of
- * <i>hash</i> or equals to <i>hash</i>.
- *
- * h1 = {a:1, b:2}
- * h2 = {a:1, b:2, c:3}
- * h1 >= h2 #=> false
- * h2 >= h1 #=> true
- * h1 >= h1 #=> true
+ * call-seq:
+ * hash >= other_hash -> true or false
+ *
+ * Returns +true+ if +hash+ is a superset of +other_hash+, +false+ otherwise:
+ * h1 = {foo: 0, bar: 1, baz: 2}
+ * h2 = {foo: 0, bar: 1}
+ * h1 >= h2 # => true
+ * h2 >= h1 # => false
+ * h1 >= h1 # => true
*/
static VALUE
rb_hash_ge(VALUE hash, VALUE other)
@@ -4493,17 +4686,15 @@ rb_hash_ge(VALUE hash, VALUE other)
}
/*
- * call-seq:
- * hash > other -> true or false
- *
- * Returns <code>true</code> if <i>other</i> is subset of
- * <i>hash</i>.
- *
- * h1 = {a:1, b:2}
- * h2 = {a:1, b:2, c:3}
- * h1 > h2 #=> false
- * h2 > h1 #=> true
- * h1 > h1 #=> false
+ * call-seq:
+ * hash > other_hash -> true or false
+ *
+ * Returns +true+ if +hash+ is a proper superset of +other_hash+, +false+ otherwise:
+ * h1 = {foo: 0, bar: 1, baz: 2}
+ * h2 = {foo: 0, bar: 1}
+ * h1 > h2 # => true
+ * h2 > h1 # => false
+ * h1 > h1 # => false
*/
static VALUE
rb_hash_gt(VALUE hash, VALUE other)
@@ -4521,22 +4712,21 @@ hash_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(key, hash))
}
/*
- * call-seq:
- * hash.to_proc -> proc
- *
- * Returns a Proc which maps keys to values.
- *
- * h = {a:1, b:2}
- * hp = h.to_proc
- * hp.call(:a) #=> 1
- * hp.call(:b) #=> 2
- * hp.call(:c) #=> nil
- * [:a, :b, :c].map(&h) #=> [1, 2, nil]
+ * call-seq:
+ * hash.to_proc -> proc
+ *
+ * Returns a \Proc object that maps a key to its value:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * proc = h.to_proc
+ * proc.class # => Proc
+ * proc.call(:foo) # => 0
+ * proc.call(:bar) # => 1
+ * proc.call(:nosuch) # => nil
*/
static VALUE
rb_hash_to_proc(VALUE hash)
{
- return rb_func_proc_new(hash_proc_call, hash);
+ return rb_func_lambda_new(hash_proc_call, hash, 1, 1);
}
static VALUE
@@ -4636,22 +4826,7 @@ static char **my_environ;
#undef environ
#define environ my_environ
#undef getenv
-static char *(*w32_getenv)(const char*);
-static char *
-w32_getenv_unknown(const char *name)
-{
- char *(*func)(const char*);
- if (rb_locale_encindex() == rb_ascii8bit_encindex()) {
- func = rb_w32_getenv;
- }
- else {
- func = rb_w32_ugetenv;
- }
- /* atomic assignment in flat memory model */
- return (w32_getenv = func)(name);
-}
-static char *(*w32_getenv)(const char*) = w32_getenv_unknown;
-#define getenv(n) w32_getenv(n)
+#define getenv(n) rb_w32_ugetenv(n)
#elif defined(__APPLE__)
#undef environ
#define environ (*_NSGetEnviron())
@@ -4670,20 +4845,20 @@ extern char **environ;
#define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
#endif
-static VALUE
-env_enc_str_new(const char *ptr, long len, rb_encoding *enc)
+static inline rb_encoding *
+env_encoding()
{
#ifdef _WIN32
- rb_encoding *internal = rb_default_internal_encoding();
- const int ecflags = ECONV_INVALID_REPLACE | ECONV_UNDEF_REPLACE;
- rb_encoding *utf8 = rb_utf8_encoding();
- VALUE str = rb_enc_str_new(NULL, 0, (internal ? internal : enc));
- if (NIL_P(rb_str_cat_conv_enc_opts(str, 0, ptr, len, utf8, ecflags, Qnil))) {
- rb_str_initialize(str, ptr, len, NULL);
- }
+ return rb_utf8_encoding();
#else
- VALUE str = rb_external_str_new_with_enc(ptr, len, enc);
+ return rb_locale_encoding();
#endif
+}
+
+static VALUE
+env_enc_str_new(const char *ptr, long len, rb_encoding *enc)
+{
+ VALUE str = rb_external_str_new_with_enc(ptr, len, enc);
rb_obj_freeze(str);
return str;
@@ -4698,7 +4873,7 @@ env_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
static VALUE
env_str_new(const char *ptr, long len)
{
- return env_enc_str_new(ptr, len, rb_locale_encoding());
+ return env_enc_str_new(ptr, len, env_encoding());
}
static VALUE
@@ -4709,48 +4884,24 @@ env_str_new2(const char *ptr)
}
static const char TZ_ENV[] = "TZ";
-extern bool ruby_tz_uptodate_p;
-
-static rb_encoding *
-env_encoding_for(const char *name, const char *ptr)
-{
- if (ENVMATCH(name, PATH_ENV)) {
- return rb_filesystem_encoding();
- }
- else {
- return rb_locale_encoding();
- }
-}
static VALUE
env_name_new(const char *name, const char *ptr)
{
- return env_enc_str_new_cstr(ptr, env_encoding_for(name, ptr));
+ return env_enc_str_new_cstr(ptr, env_encoding());
}
static void *
get_env_cstr(
-#ifdef _WIN32
- volatile VALUE *pstr,
-#else
VALUE str,
-#endif
const char *name)
{
-#ifdef _WIN32
- VALUE str = *pstr;
-#endif
char *var;
rb_encoding *enc = rb_enc_get(str);
if (!rb_enc_asciicompat(enc)) {
rb_raise(rb_eArgError, "bad environment variable %s: ASCII incompatible encoding: %s",
name, rb_enc_name(enc));
}
-#ifdef _WIN32
- if (!rb_enc_str_asciionly_p(str)) {
- *pstr = str = rb_str_conv_enc(str, NULL, rb_utf8_encoding());
- }
-#endif
var = RSTRING_PTR(str);
if (memchr(var, '\0', RSTRING_LEN(str))) {
rb_raise(rb_eArgError, "bad environment variable %s: contains null byte", name);
@@ -4758,13 +4909,8 @@ get_env_cstr(
return rb_str_fill_terminator(str, 1); /* ASCII compatible */
}
-#ifdef _WIN32
-#define get_env_ptr(var, val) \
- (var = get_env_cstr(&(val), #var))
-#else
#define get_env_ptr(var, val) \
(var = get_env_cstr(val, #var))
-#endif
static inline const char *
env_name(volatile VALUE *s)
@@ -4779,14 +4925,9 @@ env_name(volatile VALUE *s)
static VALUE env_aset(VALUE nm, VALUE val);
-static VALUE
-env_delete(VALUE name)
+static void
+reset_by_modified_env(const char *nam)
{
- const char *nam, *val;
-
- nam = env_name(name);
- val = getenv(nam);
-
/*
* ENV['TZ'] = nil has a special meaning.
* TZ is no longer considered up-to-date and ruby call tzset() as needed.
@@ -4794,16 +4935,22 @@ env_delete(VALUE name)
* This hack might works only on Linux glibc.
*/
if (ENVMATCH(nam, TZ_ENV)) {
- ruby_tz_uptodate_p = FALSE;
+ ruby_reset_timezone();
}
+}
+
+static VALUE
+env_delete(VALUE name)
+{
+ const char *nam = env_name(name);
+ const char *val = getenv(nam);
+
+ reset_by_modified_env(nam);
if (val) {
VALUE value = env_str_new2(val);
ruby_setenv(nam, 0);
- if (ENVMATCH(nam, PATH_ENV)) {
- RB_GC_GUARD(name);
- }
return value;
}
return Qnil;
@@ -4811,24 +4958,28 @@ env_delete(VALUE name)
/*
* call-seq:
- * ENV.delete(name) -> value
- * ENV.delete(name) { |name| block } -> value
+ * ENV.delete(name) -> value
+ * ENV.delete(name) { |name| block } -> value
+ * ENV.delete(missing_name) -> nil
+ * ENV.delete(missing_name) { |name| block } -> block_value
*
* Deletes the environment variable with +name+ if it exists and returns its value:
* ENV['foo'] = '0'
* ENV.delete('foo') # => '0'
- * Returns +nil+ if the named environment variable does not exist:
- * ENV.delete('foo') # => nil
+ *
+ * If a block is not given and the named environment variable does not exist, returns +nil+.
+ *
* If a block given and the environment variable does not exist,
- * yields +name+ to the block and returns +nil+:
- * ENV.delete('foo') { |name| puts name } # => nil
- * foo
+ * yields +name+ to the block and returns the value of the block:
+ * ENV.delete('foo') { |name| name * 2 } # => "foofoo"
+ *
* If a block given and the environment variable exists,
* deletes the environment variable and returns its value (ignoring the block):
* ENV['foo'] = '0'
- * ENV.delete('foo') { |name| fail 'ignored' } # => "0"
+ * ENV.delete('foo') { |name| raise 'ignored' } # => "0"
+ *
* Raises an exception if +name+ is invalid.
- * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values].
+ * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values].
*/
static VALUE
env_delete_m(VALUE obj, VALUE name)
@@ -4836,7 +4987,7 @@ env_delete_m(VALUE obj, VALUE name)
VALUE val;
val = env_delete(name);
- if (NIL_P(val) && rb_block_given_p()) rb_yield(name);
+ if (NIL_P(val) && rb_block_given_p()) val = rb_yield(name);
return val;
}
@@ -4847,11 +4998,10 @@ env_delete_m(VALUE obj, VALUE name)
* Returns the value for the environment variable +name+ if it exists:
* ENV['foo'] = '0'
* ENV['foo'] # => "0"
- * Returns nil if the named variable does not exist:
- * ENV.clear
- * ENV['foo'] # => nil
+ * Returns +nil+ if the named variable does not exist.
+ *
* Raises an exception if +name+ is invalid.
- * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values].
+ * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values].
*/
static VALUE
rb_f_getenv(VALUE obj, VALUE name)
@@ -4889,7 +5039,7 @@ rb_f_getenv(VALUE obj, VALUE name)
* and neither default value nor block is given:
* ENV.fetch('foo') # Raises KeyError (key not found: "foo")
* Raises an exception if +name+ is invalid.
- * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values].
+ * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values].
*/
static VALUE
env_fetch(int argc, VALUE *argv, VALUE _)
@@ -4919,7 +5069,7 @@ env_fetch(int argc, VALUE *argv, VALUE _)
int
rb_env_path_tainted(void)
{
- rb_warning("rb_env_path_tainted is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("rb_env_path_tainted", "3.2");
return 0;
}
@@ -5157,7 +5307,7 @@ ruby_unsetenv(const char *name)
/*
* call-seq:
- * ENV[name] = value -> value
+ * ENV[name] = value -> value
* ENV.store(name, value) -> value
*
* ENV.store is an alias for ENV.[]=.
@@ -5222,27 +5372,26 @@ env_aset(VALUE nm, VALUE val)
get_env_ptr(value, val);
ruby_setenv(name, value);
- if (ENVMATCH(name, PATH_ENV)) {
- RB_GC_GUARD(nm);
- }
- else if (ENVMATCH(name, TZ_ENV)) {
- ruby_tz_uptodate_p = FALSE;
- }
+ reset_by_modified_env(name);
return val;
}
static VALUE
-env_keys(void)
+env_keys(int raw)
{
char **env;
VALUE ary;
+ rb_encoding *enc = raw ? 0 : rb_locale_encoding();
ary = rb_ary_new();
env = GET_ENVIRON(environ);
while (*env) {
char *s = strchr(*env, '=');
if (s) {
- rb_ary_push(ary, env_str_new(*env, s-*env));
+ const char *p = *env;
+ size_t l = s - p;
+ VALUE e = raw ? rb_utf8_str_new(p, l) : env_enc_str_new(p, l, enc);
+ rb_ary_push(ary, e);
}
env++;
}
@@ -5252,7 +5401,7 @@ env_keys(void)
/*
* call-seq:
- * ENV.keys -> Array
+ * ENV.keys -> array of names
*
* Returns all variable names in an Array:
* ENV.replace('foo' => '0', 'bar' => '1')
@@ -5260,15 +5409,13 @@ env_keys(void)
* The order of the names is OS-dependent.
* See {About Ordering}[#class-ENV-label-About+Ordering].
*
- * Returns the empty Array if ENV is empty:
- * ENV.clear
- * ENV.keys # => []
+ * Returns the empty Array if ENV is empty.
*/
static VALUE
env_f_keys(VALUE _)
{
- return env_keys();
+ return env_keys(FALSE);
}
static VALUE
@@ -5290,7 +5437,7 @@ rb_env_size(VALUE ehash, VALUE args, VALUE eobj)
/*
* call-seq:
* ENV.each_key { |name| block } -> ENV
- * ENV.each_key -> Enumerator
+ * ENV.each_key -> an_enumerator
*
* Yields each environment variable name:
* ENV.replace('foo' => '0', 'bar' => '1') # => ENV
@@ -5311,7 +5458,7 @@ env_each_key(VALUE ehash)
long i;
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
- keys = env_keys();
+ keys = env_keys(FALSE);
for (i=0; i<RARRAY_LEN(keys); i++) {
rb_yield(RARRAY_AREF(keys, i));
}
@@ -5339,7 +5486,7 @@ env_values(void)
/*
* call-seq:
- * ENV.values -> Array
+ * ENV.values -> array of values
*
* Returns all environment variable values in an Array:
* ENV.replace('foo' => '0', 'bar' => '1')
@@ -5347,9 +5494,7 @@ env_values(void)
* The order of the values is OS-dependent.
* See {About Ordering}[#class-ENV-label-About+Ordering].
*
- * Returns the empty Array if ENV is empty:
- * ENV.clear
- * ENV.values # => []
+ * Returns the empty Array if ENV is empty.
*/
static VALUE
env_f_values(VALUE _)
@@ -5360,7 +5505,7 @@ env_f_values(VALUE _)
/*
* call-seq:
* ENV.each_value { |value| block } -> ENV
- * ENV.each_value -> Enumerator
+ * ENV.each_value -> an_enumerator
*
* Yields each environment variable value:
* ENV.replace('foo' => '0', 'bar' => '1') # => ENV
@@ -5391,11 +5536,11 @@ env_each_value(VALUE ehash)
/*
* call-seq:
* ENV.each { |name, value| block } -> ENV
- * ENV.each -> Enumerator
+ * ENV.each -> an_enumerator
* ENV.each_pair { |name, value| block } -> ENV
- * ENV.each_pair -> Enumerator
+ * ENV.each_pair -> an_enumerator
*
- * Yields each environment variable name and its value as a 2-element Array:
+ * Yields each environment variable name and its value as a 2-element \Array:
* h = {}
* ENV.each_pair { |name, value| h[name] = value } # => ENV
* h # => {"bar"=>"1", "foo"=>"0"}
@@ -5427,7 +5572,7 @@ env_each_pair(VALUE ehash)
}
FREE_ENVIRON(environ);
- if (rb_block_arity() > 1) {
+ if (rb_block_pair_yield_optimizable()) {
for (i=0; i<RARRAY_LEN(ary); i+=2) {
rb_yield_values(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, i+1));
}
@@ -5443,12 +5588,13 @@ env_each_pair(VALUE ehash)
/*
* call-seq:
* ENV.reject! { |name, value| block } -> ENV or nil
- * ENV.reject! -> Enumerator
+ * ENV.reject! -> an_enumerator
*
* Similar to ENV.delete_if, but returns +nil+ if no changes were made.
*
- * Deletes each environment variable for which the block returns a truthy value,
- * returning ENV (if any deletions) or +nil+ (if not):
+ * Yields each environment variable name and its value as a 2-element Array,
+ * deleting each environment variable for which the block returns a truthy value,
+ * and returning ENV (if any deletions) or +nil+ (if not):
* ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
* ENV.reject! { |name, value| name.start_with?('b') } # => ENV
* ENV # => {"foo"=>"0"}
@@ -5469,7 +5615,7 @@ env_reject_bang(VALUE ehash)
int del = 0;
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
- keys = env_keys();
+ keys = env_keys(FALSE);
RBASIC_CLEAR_CLASS(keys);
for (i=0; i<RARRAY_LEN(keys); i++) {
VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
@@ -5488,11 +5634,22 @@ env_reject_bang(VALUE ehash)
/*
* call-seq:
* ENV.delete_if { |name, value| block } -> ENV
- * ENV.delete_if -> Enumerator
+ * ENV.delete_if -> an_enumerator
*
- * Deletes every environment variable for which the block evaluates to +true+.
+ * Yields each environment variable name and its value as a 2-element Array,
+ * deleting each environment variable for which the block returns a truthy value,
+ * and returning ENV (regardless of whether any deletions):
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * ENV.delete_if { |name, value| name.start_with?('b') } # => ENV
+ * ENV # => {"foo"=>"0"}
+ * ENV.delete_if { |name, value| name.start_with?('b') } # => ENV
*
- * If no block is given an enumerator is returned instead.
+ * Returns an Enumerator if no block given:
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * e = ENV.delete_if # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:delete_if!>
+ * e.each { |name, value| name.start_with?('b') } # => ENV
+ * ENV # => {"foo"=>"0"}
+ * e.each { |name, value| name.start_with?('b') } # => ENV
*/
static VALUE
env_delete_if(VALUE ehash)
@@ -5504,10 +5661,20 @@ env_delete_if(VALUE ehash)
/*
* call-seq:
- * ENV.values_at(name, ...) -> Array
+ * ENV.values_at(*names) -> array of values
*
- * Returns an array containing the environment variable values associated with
- * the given names. See also ENV.select.
+ * Returns an Array containing the environment variable values associated with
+ * the given names:
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * ENV.values_at('foo', 'baz') # => ["0", "2"]
+ *
+ * Returns +nil+ in the Array for each name that is not an ENV name:
+ * ENV.values_at('foo', 'bat', 'bar', 'bam') # => ["0", nil, "1", nil]
+ *
+ * Returns an empty \Array if no names given.
+ *
+ * Raises an exception if any name is invalid.
+ * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values].
*/
static VALUE
env_values_at(int argc, VALUE *argv, VALUE _)
@@ -5524,16 +5691,24 @@ env_values_at(int argc, VALUE *argv, VALUE _)
/*
* call-seq:
- * ENV.select { |name, value| block } -> Hash
- * ENV.select -> Enumerator
- * ENV.filter { |name, value| block } -> Hash
- * ENV.filter -> Enumerator
+ * ENV.select { |name, value| block } -> hash of name/value pairs
+ * ENV.select -> an_enumerator
+ * ENV.filter { |name, value| block } -> hash of name/value pairs
+ * ENV.filter -> an_enumerator
*
- * Returns a copy of the environment for entries where the block returns true.
+ * ENV.filter is an alias for ENV.select.
*
- * Returns an Enumerator if no block was given.
+ * Yields each environment variable name and its value as a 2-element Array,
+ * returning a Hash of the names and values for which the block returns a truthy value:
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * ENV.select { |name, value| name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"}
+ * ENV.filter { |name, value| name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"}
*
- * ENV.filter is an alias for ENV.select.
+ * Returns an Enumerator if no block given:
+ * e = ENV.select # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:select>
+ * e.each { |name, value | name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"}
+ * e = ENV.filter # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:filter>
+ * e.each { |name, value | name.start_with?('b') } # => {"bar"=>"1", "baz"=>"2"}
*/
static VALUE
env_select(VALUE ehash)
@@ -5544,7 +5719,7 @@ env_select(VALUE ehash)
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
result = rb_hash_new();
- keys = env_keys();
+ keys = env_keys(FALSE);
for (i = 0; i < RARRAY_LEN(keys); ++i) {
VALUE key = RARRAY_AREF(keys, i);
VALUE val = rb_f_getenv(Qnil, key);
@@ -5562,13 +5737,39 @@ env_select(VALUE ehash)
/*
* call-seq:
* ENV.select! { |name, value| block } -> ENV or nil
- * ENV.select! -> Enumerator
+ * ENV.select! -> an_enumerator
* ENV.filter! { |name, value| block } -> ENV or nil
- * ENV.filter! -> Enumerator
- *
- * Equivalent to ENV.keep_if but returns +nil+ if no changes were made.
+ * ENV.filter! -> an_enumerator
*
* ENV.filter! is an alias for ENV.select!.
+ *
+ * Yields each environment variable name and its value as a 2-element Array,
+ * deleting each entry for which the block returns +false+ or +nil+,
+ * and returning ENV if any deletions made, or +nil+ otherwise:
+ *
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * ENV.select! { |name, value| name.start_with?('b') } # => ENV
+ * ENV # => {"bar"=>"1", "baz"=>"2"}
+ * ENV.select! { |name, value| true } # => nil
+ *
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * ENV.filter! { |name, value| name.start_with?('b') } # => ENV
+ * ENV # => {"bar"=>"1", "baz"=>"2"}
+ * ENV.filter! { |name, value| true } # => nil
+ *
+ * Returns an Enumerator if no block given:
+ *
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * e = ENV.select! # => #<Enumerator: {"bar"=>"1", "baz"=>"2"}:select!>
+ * e.each { |name, value| name.start_with?('b') } # => ENV
+ * ENV # => {"bar"=>"1", "baz"=>"2"}
+ * e.each { |name, value| true } # => nil
+ *
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * e = ENV.filter! # => #<Enumerator: {"bar"=>"1", "baz"=>"2"}:filter!>
+ * e.each { |name, value| name.start_with?('b') } # => ENV
+ * ENV # => {"bar"=>"1", "baz"=>"2"}
+ * e.each { |name, value| true } # => nil
*/
static VALUE
env_select_bang(VALUE ehash)
@@ -5578,7 +5779,7 @@ env_select_bang(VALUE ehash)
int del = 0;
RETURN_SIZED_ENUMERATOR(ehash, 0, 0, rb_env_size);
- keys = env_keys();
+ keys = env_keys(FALSE);
RBASIC_CLEAR_CLASS(keys);
for (i=0; i<RARRAY_LEN(keys); i++) {
VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
@@ -5597,11 +5798,20 @@ env_select_bang(VALUE ehash)
/*
* call-seq:
* ENV.keep_if { |name, value| block } -> ENV
- * ENV.keep_if -> Enumerator
+ * ENV.keep_if -> an_enumerator
*
- * Deletes every environment variable where the block evaluates to +false+.
+ * Yields each environment variable name and its value as a 2-element Array,
+ * deleting each environment variable for which the block returns +false+ or +nil+,
+ * and returning ENV:
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * ENV.keep_if { |name, value| name.start_with?('b') } # => ENV
+ * ENV # => {"bar"=>"1", "baz"=>"2"}
*
- * Returns an enumerator if no block was given.
+ * Returns an Enumerator if no block given:
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * e = ENV.keep_if # => #<Enumerator: {"bar"=>"1", "baz"=>"2", "foo"=>"0"}:keep_if>
+ * e.each { |name, value| name.start_with?('b') } # => ENV
+ * ENV # => {"bar"=>"1", "baz"=>"2"}
*/
static VALUE
env_keep_if(VALUE ehash)
@@ -5612,12 +5822,16 @@ env_keep_if(VALUE ehash)
}
/*
- * call-seq:
- * ENV.slice(*keys) -> a_hash
- *
- * Returns a hash containing only the given keys from ENV and their values.
- *
- * ENV.slice("TERM","HOME") #=> {"TERM"=>"xterm-256color", "HOME"=>"/Users/rhc"}
+ * call-seq:
+ * ENV.slice(*names) -> hash of name/value pairs
+ *
+ * Returns a Hash of the given ENV names and their corresponding values:
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2', 'bat' => '3')
+ * ENV.slice('foo', 'baz') # => {"foo"=>"0", "baz"=>"2"}
+ * ENV.slice('baz', 'foo') # => {"baz"=>"2", "foo"=>"0"}
+ * Raises an exception if any of the +names+ is invalid
+ * (see {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]):
+ * ENV.slice('foo', 'bar', :bat) # Raises TypeError (no implicit conversion of Symbol into String)
*/
static VALUE
env_slice(int argc, VALUE *argv, VALUE _)
@@ -5646,12 +5860,11 @@ rb_env_clear(void)
VALUE keys;
long i;
- keys = env_keys();
+ keys = env_keys(TRUE);
for (i=0; i<RARRAY_LEN(keys); i++) {
- VALUE val = rb_f_getenv(Qnil, RARRAY_AREF(keys, i));
- if (!NIL_P(val)) {
- env_delete(RARRAY_AREF(keys, i));
- }
+ VALUE key = RARRAY_AREF(keys, i);
+ const char *nam = RSTRING_PTR(key);
+ ruby_setenv(nam, 0);
}
RB_GC_GUARD(keys);
return envtbl;
@@ -5677,7 +5890,8 @@ env_clear(VALUE _)
* call-seq:
* ENV.to_s -> "ENV"
*
- * Returns "ENV"
+ * Returns String 'ENV':
+ * ENV.to_s # => "ENV"
*/
static VALUE
env_to_s(VALUE _)
@@ -5687,9 +5901,11 @@ env_to_s(VALUE _)
/*
* call-seq:
- * ENV.inspect -> string
+ * ENV.inspect -> a_string
*
- * Returns the contents of the environment as a String.
+ * Returns the contents of the environment as a String:
+ * ENV.replace('foo' => '0', 'bar' => '1')
+ * ENV.inspect # => "{\"bar\"=>\"1\", \"foo\"=>\"0\"}"
*/
static VALUE
env_inspect(VALUE _)
@@ -5722,12 +5938,12 @@ env_inspect(VALUE _)
/*
* call-seq:
- * ENV.to_a -> Array
- *
- * Converts the environment variables into an array of names and value arrays.
- *
- * ENV.to_a # => [["TERM", "xterm-color"], ["SHELL", "/bin/bash"], ...]
+ * ENV.to_a -> array of 2-element arrays
*
+ * Returns the contents of ENV as an Array of 2-element Arrays,
+ * each of which is a name/value pair:
+ * ENV.replace('foo' => '0', 'bar' => '1')
+ * ENV.to_a # => [["bar", "1"], ["foo", "0"]]
*/
static VALUE
env_to_a(VALUE _)
@@ -5751,10 +5967,11 @@ env_to_a(VALUE _)
/*
* call-seq:
- * ENV.rehash
+ * ENV.rehash -> nil
+ *
+ * (Provided for compatibility with Hash.)
*
- * Re-hashing the environment variables does nothing. It is provided for
- * compatibility with Hash.
+ * Does not modify ENV; returns +nil+.
*/
static VALUE
env_none(VALUE _)
@@ -5764,10 +5981,13 @@ env_none(VALUE _)
/*
* call-seq:
- * ENV.length
- * ENV.size
+ * ENV.length -> an_integer
+ * ENV.size -> an_integer
*
- * Returns the number of environment variables.
+ * Returns the count of environment variables:
+ * ENV.replace('foo' => '0', 'bar' => '1')
+ * ENV.length # => 2
+ * ENV.size # => 2
*/
static VALUE
env_size(VALUE _)
@@ -5786,7 +6006,11 @@ env_size(VALUE _)
* call-seq:
* ENV.empty? -> true or false
*
- * Returns true when there are no environment variables
+ * Returns +true+ when there are no environment variables, +false+ otherwise:
+ * ENV.clear
+ * ENV.empty? # => true
+ * ENV['foo'] = '0'
+ * ENV.empty? # => false
*/
static VALUE
env_empty_p(VALUE _)
@@ -5839,17 +6063,16 @@ env_has_key(VALUE env, VALUE key)
/*
* call-seq:
- * ENV.assoc(name) -> Array or nil
+ * ENV.assoc(name) -> [name, value] or nil
*
* Returns a 2-element Array containing the name and value of the environment variable
* for +name+ if it exists:
* ENV.replace('foo' => '0', 'bar' => '1')
- * ENV.assoc('foo') # => ['foo' '0']
- * Returns +nil+ if +name+ is a valid String and there is no such environment variable:
- * ENV.assoc('baz') # => false
- * Returns +nil+ if +name+ is the empty String or is a String containing character <code>'='</code>:
- * ENV.assoc('') # => false
- * ENV.assoc('=') # => false
+ * ENV.assoc('foo') # => ['foo', '0']
+ * Returns +nil+ if +name+ is a valid String and there is no such environment variable.
+ *
+ * Returns +nil+ if +name+ is the empty String or is a String containing character <code>'='</code>.
+ *
* Raises an exception if +name+ is a String containing the NUL character <code>"\0"</code>:
* ENV.assoc("\0") # Raises ArgumentError (bad environment variable name: contains null byte)
* Raises an exception if +name+ has an encoding that is not ASCII-compatible:
@@ -5871,10 +6094,15 @@ env_assoc(VALUE env, VALUE key)
/*
* call-seq:
- * ENV.value?(value) -> true or false
+ * ENV.value?(value) -> true or false
* ENV.has_value?(value) -> true or false
*
- * Returns +true+ if there is an environment variable with the given +value+.
+ * Returns +true+ if +value+ is the value for some environment variable name, +false+ otherwise:
+ * ENV.replace('foo' => '0', 'bar' => '1')
+ * ENV.value?('0') # => true
+ * ENV.has_value?('0') # => true
+ * ENV.value?('2') # => false
+ * ENV.has_value?('2') # => false
*/
static VALUE
env_has_value(VALUE dmy, VALUE obj)
@@ -5901,10 +6129,17 @@ env_has_value(VALUE dmy, VALUE obj)
/*
* call-seq:
- * ENV.rassoc(value)
+ * ENV.rassoc(value) -> [name, value] or nil
*
- * Returns an Array of the name and value of the environment variable with
- * +value+ or +nil+ if the value cannot be found.
+ * Returns a 2-element Array containing the name and value of the
+ * *first* *found* environment variable that has value +value+, if one
+ * exists:
+ * ENV.replace('foo' => '0', 'bar' => '0')
+ * ENV.rassoc('0') # => ["bar", "0"]
+ * The order in which environment variables are examined is OS-dependent.
+ * See {About Ordering}[#class-ENV-label-About+Ordering].
+ *
+ * Returns +nil+ if there is no such environment variable.
*/
static VALUE
env_rassoc(VALUE dmy, VALUE obj)
@@ -5934,16 +6169,17 @@ env_rassoc(VALUE dmy, VALUE obj)
* call-seq:
* ENV.key(value) -> name or nil
*
- * Returns the name of the first environment variable with +value+ if it exists:
- * ENV.replace('foo' => '0', 'bar' => '1')
- * ENV.key('0') # =>'foo'
+ * Returns the name of the first environment variable with +value+, if it exists:
+ * ENV.replace('foo' => '0', 'bar' => '0')
+ * ENV.key('0') # => "foo"
* The order in which environment variables are examined is OS-dependent.
* See {About Ordering}[#class-ENV-label-About+Ordering].
*
- * Returns +nil+ if there is no such value:
- * ENV.key('2') # => nil
- * Raises an exception if +value+ is not a String:
+ * Returns +nil+ if there is no such value.
+ *
+ * Raises an exception if +value+ is invalid:
* ENV.key(Object.new) # raises TypeError (no implicit conversion of Object into String)
+ * See {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values].
*/
static VALUE
env_key(VALUE dmy, VALUE value)
@@ -5969,19 +6205,6 @@ env_key(VALUE dmy, VALUE value)
return Qnil;
}
-/*
- * call-seq:
- * ENV.index(value) -> key
- *
- * Deprecated method that is equivalent to ENV.key
- */
-static VALUE
-env_index(VALUE dmy, VALUE value)
-{
- rb_warn_deprecated("ENV.index", "ENV.key");
- return env_key(dmy, value);
-}
-
static VALUE
env_to_hash(void)
{
@@ -6004,10 +6227,11 @@ env_to_hash(void)
/*
* call-seq:
- * ENV.to_hash -> hash
- *
- * Creates a hash with a copy of the environment variables.
+ * ENV.to_hash -> hash of name/value pairs
*
+ * Returns a Hash containing all name/value pairs from ENV:
+ * ENV.replace('foo' => '0', 'bar' => '1')
+ * ENV.to_hash # => {"bar"=>"1", "foo"=>"0"}
*/
static VALUE
@@ -6018,11 +6242,21 @@ env_f_to_hash(VALUE _)
/*
* call-seq:
- * ENV.to_h -> hash
- * ENV.to_h {|name, value| block } -> hash
- *
- * Creates a hash with a copy of the environment variables.
+ * ENV.to_h -> hash of name/value pairs
+ * ENV.to_h {|name, value| block } -> hash of name/value pairs
*
+ * With no block, returns a Hash containing all name/value pairs from ENV:
+ * ENV.replace('foo' => '0', 'bar' => '1')
+ * ENV.to_h # => {"bar"=>"1", "foo"=>"0"}
+ * With a block, returns a Hash whose items are determined by the block.
+ * Each name/value pair in ENV is yielded to the block.
+ * The block must return a 2-element Array (name/value pair)
+ * that is added to the return Hash as a key and value:
+ * ENV.to_h { |name, value| [name.to_sym, value.to_i] } # => {:bar=>1, :foo=>0}
+ * Raises an exception if the block does not return an Array:
+ * ENV.to_h { |name, value| name } # Raises TypeError (wrong element type String (expected array))
+ * Raises an exception if the block returns an Array of the wrong size:
+ * ENV.to_h { |name, value| [name] } # Raises ArgumentError (element has wrong array length (expected 2, was 1))
*/
static VALUE
env_to_h(VALUE _)
@@ -6035,12 +6269,42 @@ env_to_h(VALUE _)
}
/*
+ * call-seq:
+ * ENV.except(*keys) -> a_hash
+ *
+ * Returns a hash except the given keys from ENV and their values.
+ *
+ * ENV #=> {"LANG"=>"en_US.UTF-8", "TERM"=>"xterm-256color", "HOME"=>"/Users/rhc"}
+ * ENV.except("TERM","HOME") #=> {"LANG"=>"en_US.UTF-8"}
+ */
+static VALUE
+env_except(int argc, VALUE *argv, VALUE _)
+{
+ int i;
+ VALUE key, hash = env_to_hash();
+
+ for (i = 0; i < argc; i++) {
+ key = argv[i];
+ rb_hash_delete(hash, key);
+ }
+
+ return hash;
+}
+
+/*
* call-seq:
- * ENV.reject { |name, value| block } -> Hash
- * ENV.reject -> Enumerator
+ * ENV.reject { |name, value| block } -> hash of name/value pairs
+ * ENV.reject -> an_enumerator
*
- * Same as ENV.delete_if, but works on (and returns) a copy of the
- * environment.
+ * Yields each environment variable name and its value as a 2-element Array.
+ * Returns a Hash whose items are determined by the block.
+ * When the block returns a truthy value, the name/value pair is added to the return Hash;
+ * otherwise the pair is ignored:
+ * ENV.replace('foo' => '0', 'bar' => '1', 'baz' => '2')
+ * ENV.reject { |name, value| name.start_with?('b') } # => {"foo"=>"0"}
+ * Returns an Enumerator if no block given:
+ * e = ENV.reject
+ * e.each { |name, value| name.start_with?('b') } # => {"foo"=>"0"}
*/
static VALUE
env_reject(VALUE _)
@@ -6048,18 +6312,19 @@ env_reject(VALUE _)
return rb_hash_delete_if(env_to_hash());
}
+NORETURN(static VALUE env_freeze(VALUE self));
/*
* call-seq:
- * ENV.freeze -> raises TypeError
+ * ENV.freeze
*
- * Ruby does not allow ENV to be frozen, so calling ENV.freeze
- * raises TypeError.
+ * Raises an exception:
+ * ENV.freeze # Raises TypeError (cannot freeze ENV)
*/
static VALUE
env_freeze(VALUE self)
{
rb_raise(rb_eTypeError, "cannot freeze ENV");
- return self; /* Not reached */
+ UNREACHABLE_RETURN(self);
}
/*
@@ -6075,9 +6340,7 @@ env_freeze(VALUE self)
* Exactly which environment variable is "first" is OS-dependent.
* See {About Ordering}[#class-ENV-label-About+Ordering].
*
- * Returns +nil+ if the environment is empty:
- * ENV.clear
- * ENV.shift # => nil
+ * Returns +nil+ if the environment is empty.
*/
static VALUE
env_shift(VALUE _)
@@ -6101,10 +6364,18 @@ env_shift(VALUE _)
/*
* call-seq:
- * ENV.invert -> Hash
+ * ENV.invert -> hash of value/name pairs
*
- * Returns a new hash created by using environment variable names as values
- * and values as names.
+ * Returns a Hash whose keys are the ENV values,
+ * and whose values are the corresponding ENV names:
+ * ENV.replace('foo' => '0', 'bar' => '1')
+ * ENV.invert # => {"1"=>"bar", "0"=>"foo"}
+ * For a duplicate ENV value, overwrites the hash entry:
+ * ENV.replace('foo' => '0', 'bar' => '0')
+ * ENV.invert # => {"0"=>"foo"}
+ * Note that the order of the ENV processing is OS-dependent,
+ * which means that the order of overwriting is also OS-dependent.
+ * See {About Ordering}[#class-ENV-label-About+Ordering].
*/
static VALUE
env_invert(VALUE _)
@@ -6118,13 +6389,16 @@ keylist_delete(VALUE keys, VALUE key)
long keylen, elen;
const char *keyptr, *eptr;
RSTRING_GETMEM(key, keyptr, keylen);
+ /* Don't stop at first key, as it is possible to have
+ multiple environment values with the same key.
+ */
for (long i=0; i<RARRAY_LEN(keys); i++) {
VALUE e = RARRAY_AREF(keys, i);
RSTRING_GETMEM(e, eptr, elen);
if (elen != keylen) continue;
if (!ENVNMATCH(keyptr, eptr, elen)) continue;
rb_ary_delete_at(keys, i);
- return;
+ i--;
}
}
@@ -6150,8 +6424,11 @@ env_replace_i(VALUE key, VALUE val, VALUE keys)
* ENV.replace('foo' => '0', 'bar' => '1') # => ENV
* ENV.to_hash # => {"bar"=>"1", "foo"=>"0"}
*
- * Raises an exception if a name or value is invalid.
- * See {Invalid Names and Values}[#class-ENV-label-Invalid-Names+and+Values].
+ * Raises an exception if a name or value is invalid
+ * (see {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]):
+ * ENV.replace('foo' => '0', :bar => '1') # Raises TypeError (no implicit conversion of Symbol into String)
+ * ENV.replace('foo' => '0', 'bar' => 1) # Raises TypeError (no implicit conversion of Integer into String)
+ * ENV.to_hash # => {"bar"=>"1", "foo"=>"0"}
*/
static VALUE
env_replace(VALUE env, VALUE hash)
@@ -6159,7 +6436,7 @@ env_replace(VALUE env, VALUE hash)
VALUE keys;
long i;
- keys = env_keys();
+ keys = env_keys(TRUE);
if (env == hash) return env;
hash = to_hash(hash);
rb_hash_foreach(hash, env_replace_i, keys);
@@ -6191,15 +6468,39 @@ env_update_block_i(VALUE key, VALUE val, VALUE _)
/*
* call-seq:
- * ENV.update(hash) -> ENV
- * ENV.update(hash) { |name, old_value, new_value| block } -> ENV
- * ENV.merge!(hash) -> ENV
- * ENV.merge!(hash) { |name, old_value, new_value| block } -> ENV
- *
- * Adds the contents of +hash+ to the environment variables. If no block is
- * specified entries with duplicate keys are overwritten, otherwise the value
- * of each duplicate name is determined by calling the block with the key, its
- * value from the environment and its value from the hash.
+ * ENV.update(hash) -> ENV
+ * ENV.update(hash) { |name, env_val, hash_val| block } -> ENV
+ * ENV.merge!(hash) -> ENV
+ * ENV.merge!(hash) { |name, env_val, hash_val| block } -> ENV
+ *
+ * ENV.update is an alias for ENV.merge!.
+ *
+ * Adds to ENV each key/value pair in the given +hash+; returns ENV:
+ * ENV.replace('foo' => '0', 'bar' => '1')
+ * ENV.merge!('baz' => '2', 'bat' => '3') # => {"bar"=>"1", "bat"=>"3", "baz"=>"2", "foo"=>"0"}
+ * Deletes the ENV entry for a hash value that is +nil+:
+ * ENV.merge!('baz' => nil, 'bat' => nil) # => {"bar"=>"1", "foo"=>"0"}
+ * For an already-existing name, if no block given, overwrites the ENV value:
+ * ENV.merge!('foo' => '4') # => {"bar"=>"1", "foo"=>"4"}
+ * For an already-existing name, if block given,
+ * yields the name, its ENV value, and its hash value;
+ * the block's return value becomes the new name:
+ * ENV.merge!('foo' => '5') { |name, env_val, hash_val | env_val + hash_val } # => {"bar"=>"1", "foo"=>"45"}
+ * Raises an exception if a name or value is invalid
+ * (see {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]);
+ * ENV.replace('foo' => '0', 'bar' => '1')
+ * ENV.merge!('foo' => '6', :bar => '7', 'baz' => '9') # Raises TypeError (no implicit conversion of Symbol into String)
+ * ENV # => {"bar"=>"1", "foo"=>"6"}
+ * ENV.merge!('foo' => '7', 'bar' => 8, 'baz' => '9') # Raises TypeError (no implicit conversion of Integer into String)
+ * ENV # => {"bar"=>"1", "foo"=>"7"}
+ * Raises an exception if the block returns an invalid name:
+ * (see {Invalid Names and Values}[#class-ENV-label-Invalid+Names+and+Values]):
+ * ENV.merge!('bat' => '8', 'foo' => '9') { |name, env_val, hash_val | 10 } # Raises TypeError (no implicit conversion of Integer into String)
+ * ENV # => {"bar"=>"1", "bat"=>"8", "foo"=>"7"}
+ *
+ * Note that for the exceptions above,
+ * hash pairs preceding an invalid name or value are processed normally;
+ * those following are ignored.
*/
static VALUE
env_update(VALUE env, VALUE hash)
@@ -6213,79 +6514,225 @@ env_update(VALUE env, VALUE hash)
}
/*
- * A Hash is a dictionary-like collection of unique keys and their values.
- * Also called associative arrays, they are similar to Arrays, but where an
- * Array uses integers as its index, a Hash allows you to use any object
- * type.
+ * A \Hash maps each of its unique keys to a specific value.
*
- * Hashes enumerate their values in the order that the corresponding keys
- * were inserted.
+ * A \Hash has certain similarities to an \Array, but:
+ * - An \Array index is always an \Integer.
+ * - A \Hash key can be (almost) any object.
*
- * A Hash can be easily created by using its implicit form:
+ * === \Hash \Data Syntax
*
- * grades = { "Jane Doe" => 10, "Jim Doe" => 6 }
+ * The older syntax for \Hash data uses the "hash rocket," <tt>=></tt>:
*
- * Hashes allow an alternate syntax for keys that are symbols.
- * Instead of
+ * h = {:foo => 0, :bar => 1, :baz => 2}
+ * h # => {:foo=>0, :bar=>1, :baz=>2}
*
- * options = { :font_size => 10, :font_family => "Arial" }
+ * Alternatively, but only for a \Hash key that's a \Symbol,
+ * you can use a newer JSON-style syntax,
+ * where each bareword becomes a \Symbol:
*
- * You could write it as:
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h # => {:foo=>0, :bar=>1, :baz=>2}
*
- * options = { font_size: 10, font_family: "Arial" }
+ * You can also use a \String in place of a bareword:
*
- * Each named key is a symbol you can access in hash:
+ * h = {'foo': 0, 'bar': 1, 'baz': 2}
+ * h # => {:foo=>0, :bar=>1, :baz=>2}
*
- * options[:font_size] # => 10
+ * And you can mix the styles:
*
- * A Hash can also be created through its ::new method:
+ * h = {foo: 0, :bar => 1, 'baz': 2}
+ * h # => {:foo=>0, :bar=>1, :baz=>2}
*
- * grades = Hash.new
- * grades["Dorothy Doe"] = 9
+ * But it's an error to try the JSON-style syntax
+ * for a key that's not a bareword or a String:
*
- * Hashes have a <em>default value</em> that is returned when accessing
- * keys that do not exist in the hash. If no default is set +nil+ is used.
- * You can set the default value by sending it as an argument to Hash.new:
+ * # Raises SyntaxError (syntax error, unexpected ':', expecting =>):
+ * h = {0: 'zero'}
*
- * grades = Hash.new(0)
+ * === Common Uses
*
- * Or by using the #default= method:
+ * You can use a \Hash to give names to objects:
*
- * grades = {"Timmy Doe" => 8}
- * grades.default = 0
+ * person = {name: 'Matz', language: 'Ruby'}
+ * person # => {:name=>"Matz", :language=>"Ruby"}
*
- * Accessing a value in a Hash requires using its key:
+ * You can use a \Hash to give names to method arguments:
*
- * puts grades["Jane Doe"] # => 0
+ * def some_method(hash)
+ * p hash
+ * end
+ * some_method({foo: 0, bar: 1, baz: 2}) # => {:foo=>0, :bar=>1, :baz=>2}
*
- * === Common Uses
+ * Note: when the last argument in a method call is a \Hash,
+ * the curly braces may be omitted:
*
- * Hashes are an easy way to represent data structures, such as
+ * some_method(foo: 0, bar: 1, baz: 2) # => {:foo=>0, :bar=>1, :baz=>2}
*
- * books = {}
- * books[:matz] = "The Ruby Programming Language"
- * books[:black] = "The Well-Grounded Rubyist"
+ * You can use a \Hash to initialize an object:
*
- * Hashes are also commonly used as a way to have named parameters in
- * functions. Note that no brackets are used below. If a hash is the last
- * argument on a method call, no braces are needed, thus creating a really
- * clean interface:
+ * class Dev
+ * attr_accessor :name, :language
+ * def initialize(hash)
+ * self.name = hash[:name]
+ * self.language = hash[:language]
+ * end
+ * end
+ * matz = Dev.new(name: 'Matz', language: 'Ruby')
+ * matz # => #<Dev: @name="Matz", @language="Ruby">
*
- * Person.create(name: "John Doe", age: 27)
+ * === Creating a \Hash
*
- * def self.create(params)
- * @name = params[:name]
- * @age = params[:age]
- * end
+ * Here are three ways to create a \Hash:
+ *
+ * - \Method <tt>Hash.new</tt>
+ * - \Method <tt>Hash[]</tt>
+ * - Literal form: <tt>{}</tt>.
+ *
+ * ---
+ *
+ * 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:
*
- * === Hash Keys
+ * h = Hash[]
+ * h # => {}
*
- * Two objects refer to the same hash key when their <code>hash</code> value
+ * Create a \Hash with initial entries:
+ *
+ * h = Hash[foo: 0, bar: 1, baz: 2]
+ * h # => {:foo=>0, :bar=>1, :baz=>2}
+ *
+ * ---
+ *
+ * You can create a \Hash by using its literal form (curly braces).
+ *
+ * Create an empty \Hash:
+ *
+ * h = {}
+ * h # => {}
+ *
+ * Create a \Hash with initial entries:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h # => {:foo=>0, :bar=>1, :baz=>2}
+ *
+ *
+ * === \Hash Value Basics
+ *
+ * The simplest way to retrieve a \Hash value (instance method #[]):
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h[:foo] # => 0
+ *
+ * The simplest way to create or update a \Hash value (instance method #[]=):
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h[:bat] = 3 # => 3
+ * h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3}
+ * h[:foo] = 4 # => 4
+ * h # => {:foo=>4, :bar=>1, :baz=>2, :bat=>3}
+ *
+ * The simplest way to delete a \Hash entry (instance method #delete):
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.delete(:bar) # => 1
+ * h # => {:foo=>0, :baz=>2}
+ *
+ * === Entry Order
+ *
+ * A \Hash object presents its entries in the order of their creation. This is seen in:
+ *
+ * - Iterative methods such as <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>.
+ *
+ * A new \Hash has its initial ordering per the given entries:
+ *
+ * h = Hash[foo: 0, bar: 1]
+ * h # => {:foo=>0, :bar=>1}
+ *
+ * New entries are added at the end:
+ *
+ * h[:baz] = 2
+ * h # => {:foo=>0, :bar=>1, :baz=>2}
+ *
+ * Updating a value does not affect the order:
+ *
+ * h[:baz] = 3
+ * h # => {:foo=>0, :bar=>1, :baz=>3}
+ *
+ * But re-creating a deleted entry can affect the order:
+ *
+ * h.delete(:foo)
+ * h[:foo] = 5
+ * h # => {:bar=>1, :baz=>3, :foo=>5}
+ *
+ * === \Hash Keys
+ *
+ * ==== \Hash Key Equivalence
+ *
+ * Two objects are treated as the same \hash key when their <code>hash</code> value
* is identical and the two objects are <code>eql?</code> to each other.
*
- * A user-defined class may be used as a hash key if the <code>hash</code>
- * and <code>eql?</code> methods are overridden to provide meaningful
- * behavior. By default, separate instances refer to separate hash keys.
+ * ==== Modifying an Active \Hash Key
+ *
+ * Modifying a \Hash key while it is in use damages the hash's index.
+ *
+ * This \Hash has keys that are Arrays:
+ *
+ * a0 = [ :foo, :bar ]
+ * a1 = [ :baz, :bat ]
+ * h = {a0 => 0, a1 => 1}
+ * h.include?(a0) # => true
+ * h[a0] # => 0
+ * a0.hash # => 110002110
+ *
+ * Modifying array element <tt>a0[0]</tt> changes its hash value:
+ *
+ * a0[0] = :bam
+ * a0.hash # => 1069447059
+ *
+ * And damages the \Hash index:
+ *
+ * h.include?(a0) # => false
+ * h[a0] # => nil
+ *
+ * You can repair the hash index using method +rehash+:
+ *
+ * h.rehash # => {[:bam, :bar]=>0, [:baz, :bat]=>1}
+ * h.include?(a0) # => true
+ * h[a0] # => 0
+ *
+ * A \String key is always safe.
+ * That's because an unfrozen \String
+ * passed as a key will be replaced by a duplicated and frozen \String:
+ *
+ * s = 'foo'
+ * s.frozen? # => false
+ * h = {s => 0}
+ * first_key = h.keys.first
+ * first_key.frozen? # => true
+ *
+ * ==== User-Defined \Hash Keys
+ *
+ * To be useable as a \Hash key, objects must implement the methods <code>hash</code> and <code>eql?</code>.
+ * Note: this requirement does not apply if the \Hash uses #compare_by_id since comparison will then rely on
+ * the keys' object id instead of <code>hash</code> and <code>eql?</code>.
+ *
+ * \Object defines basic implementation for <code>hash</code> and <code>eq?</code> that makes each object
+ * a distinct key. Typically, user-defined classes will want to override these methods to provide meaningful
+ * behavior, or for example inherit \Struct that has useful definitions for these.
*
* A typical implementation of <code>hash</code> is based on the
* object's data while <code>eql?</code> is usually aliased to the overridden
@@ -6300,8 +6747,8 @@ env_update(VALUE env, VALUE hash)
* end
*
* def ==(other)
- * self.class === other and
- * other.author == @author and
+ * self.class === other &&
+ * other.author == @author &&
* other.title == @title
* end
*
@@ -6322,18 +6769,97 @@ env_update(VALUE env, VALUE hash)
*
* reviews.length #=> 1
*
- * See also Object#hash and Object#eql?
+ * === Default Values
+ *
+ * The methods #[], #values_at and #dig need to return the value associated to a certain key.
+ * When that key is not found, that value will be determined by its default proc (if any)
+ * or else its default (initially `nil`).
+ *
+ * You can retrieve the default value with method #default:
+ *
+ * h = Hash.new
+ * h.default # => nil
+ *
+ * You can set the default value by passing an argument to method Hash.new or
+ * with method #default=
+ *
+ * h = Hash.new(-1)
+ * h.default # => -1
+ * h.default = 0
+ * h.default # => 0
+ *
+ * This default value is returned for #[], #values_at and #dig when a key is
+ * not found:
+ *
+ * counts = {foo: 42}
+ * counts.default # => nil (default)
+ * counts[:foo] = 42
+ * counts[:bar] # => nil
+ * counts.default = 0
+ * counts[:bar] # => 0
+ * counts.values_at(:foo, :bar, :baz) # => [42, 0, 0]
+ * counts.dig(:bar) # => 0
+ *
+ * Note that the default value is used without being duplicated. It is not advised to set
+ * the default value to a mutable object:
+ *
+ * synonyms = Hash.new([])
+ * synonyms[:hello] # => []
+ * synonyms[:hello] << :hi # => [:hi], but this mutates the default!
+ * synonyms.default # => [:hi]
+ * synonyms[:world] << :universe
+ * synonyms[:world] # => [:hi, :universe], oops
+ * synonyms.keys # => [], oops
+ *
+ * To use a mutable object as default, it is recommended to use a default proc
+ *
+ * ==== Default \Proc
+ *
+ * When the default proc for a \Hash is set (i.e., not +nil+),
+ * the default value returned by method #[] is determined by the default proc alone.
+ *
+ * You can retrieve the default proc with method #default_proc:
+ *
+ * h = Hash.new
+ * h.default_proc # => nil
+ *
+ * You can set the default proc by calling Hash.new with a block or
+ * calling the method #default_proc=
+ *
+ * h = Hash.new { |hash, key| "Default value for #{key}" }
+ * h.default_proc.class # => Proc
+ * h.default_proc = proc { |hash, key| "Default value for #{key.inspect}" }
+ * h.default_proc.class # => Proc
+ *
+ * When the default proc is set (i.e., not +nil+)
+ * and method #[] is called with with a non-existent key,
+ * #[] calls the default proc with both the \Hash object itself and the missing key,
+ * then returns the proc's return value:
+ *
+ * h = Hash.new { |hash, key| "Default value for #{key}" }
+ * h[:nosuch] # => "Default value for nosuch"
+ *
+ * Note that in the example above no entry for key +:nosuch+ is created:
+ *
+ * h.include?(:nosuch) # => false
+ *
+ * However, the proc itself can add a new entry:
+ *
+ * synonyms = Hash.new { |hash, key| hash[key] = [] }
+ * synonyms.include?(:hello) # => false
+ * synonyms[:hello] << :hi # => [:hi]
+ * synonyms[:world] << :universe # => [:universe]
+ * synonyms.keys # => [:hello, :world]
+ *
+ * Note that setting the default proc will clear the default value and vice versa.
*/
void
Init_Hash(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
- id_hash = rb_intern("hash");
- id_yield = rb_intern("yield");
- id_default = rb_intern("default");
- id_flatten_bang = rb_intern("flatten!");
+ id_hash = rb_intern_const("hash");
+ id_default = rb_intern_const("default");
+ id_flatten_bang = rb_intern_const("flatten!");
id_hash_iter_lev = rb_make_internal_id();
rb_cHash = rb_define_class("Hash", rb_cObject);
@@ -6366,7 +6892,6 @@ Init_Hash(void)
rb_define_method(rb_cHash, "default_proc", rb_hash_default_proc, 0);
rb_define_method(rb_cHash, "default_proc=", rb_hash_set_default_proc, 1);
rb_define_method(rb_cHash, "key", rb_hash_key, 1);
- rb_define_method(rb_cHash, "index", rb_hash_index, 1);
rb_define_method(rb_cHash, "size", rb_hash_size, 0);
rb_define_method(rb_cHash, "length", rb_hash_size, 0);
rb_define_method(rb_cHash, "empty?", rb_hash_empty_p, 0);
@@ -6376,8 +6901,8 @@ Init_Hash(void)
rb_define_method(rb_cHash, "each_pair", rb_hash_each_pair, 0);
rb_define_method(rb_cHash, "each", rb_hash_each_pair, 0);
- rb_define_method(rb_cHash, "transform_keys", rb_hash_transform_keys, 0);
- rb_define_method(rb_cHash, "transform_keys!", rb_hash_transform_keys_bang, 0);
+ rb_define_method(rb_cHash, "transform_keys", rb_hash_transform_keys, -1);
+ rb_define_method(rb_cHash, "transform_keys!", rb_hash_transform_keys_bang, -1);
rb_define_method(rb_cHash, "transform_values", rb_hash_transform_values, 0);
rb_define_method(rb_cHash, "transform_values!", rb_hash_transform_values_bang, 0);
@@ -6397,6 +6922,7 @@ Init_Hash(void)
rb_define_method(rb_cHash, "reject", rb_hash_reject, 0);
rb_define_method(rb_cHash, "reject!", rb_hash_reject_bang, 0);
rb_define_method(rb_cHash, "slice", rb_hash_slice, -1);
+ rb_define_method(rb_cHash, "except", rb_hash_except, -1);
rb_define_method(rb_cHash, "clear", rb_hash_clear, 0);
rb_define_method(rb_cHash, "invert", rb_hash_invert, 0);
rb_define_method(rb_cHash, "update", rb_hash_update, -1);
@@ -6532,6 +7058,7 @@ Init_Hash(void)
rb_define_singleton_method(envtbl, "delete_if", env_delete_if, 0);
rb_define_singleton_method(envtbl, "keep_if", env_keep_if, 0);
rb_define_singleton_method(envtbl, "slice", env_slice, -1);
+ rb_define_singleton_method(envtbl, "except", env_except, -1);
rb_define_singleton_method(envtbl, "clear", env_clear, 0);
rb_define_singleton_method(envtbl, "reject", env_reject, 0);
rb_define_singleton_method(envtbl, "reject!", env_reject_bang, 0);
@@ -6550,7 +7077,6 @@ Init_Hash(void)
rb_define_singleton_method(envtbl, "to_a", env_to_a, 0);
rb_define_singleton_method(envtbl, "to_s", env_to_s, 0);
rb_define_singleton_method(envtbl, "key", env_key, 1);
- rb_define_singleton_method(envtbl, "index", env_index, 1);
rb_define_singleton_method(envtbl, "size", env_size, 0);
rb_define_singleton_method(envtbl, "length", env_size, 0);
rb_define_singleton_method(envtbl, "empty?", env_empty_p, 0);
diff --git a/id_table.c b/id_table.c
index f566582479..840ab46ee3 100644
--- a/id_table.c
+++ b/id_table.c
@@ -7,6 +7,7 @@
#endif
#if ID_TABLE_DEBUG == 0
+#undef NDEBUG
#define NDEBUG
#endif
#include "ruby_assert.h"
@@ -229,7 +230,7 @@ rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
int index = hash_table_index(tbl, key);
if (index >= 0) {
- *valp = tbl->items[index].val;
+ *valp = tbl->items[index].val;
return TRUE;
}
else {
@@ -273,9 +274,8 @@ rb_id_table_foreach_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_fu
for (i=0; i<capa; i++) {
if (ITEM_KEY_ISSET(tbl, i)) {
- const id_key_t key = ITEM_GET_KEY(tbl, i);
enum rb_id_table_iterator_result ret = (*func)(Qundef, tbl->items[i].val, data);
- assert(key != 0);
+ assert(ITEM_GET_KEY(tbl, i));
if (ret == ID_TABLE_REPLACE) {
VALUE val = tbl->items[i].val;
diff --git a/id_table.h b/id_table.h
index abd9eb5f38..f3dc681d17 100644
--- a/id_table.h
+++ b/id_table.h
@@ -1,5 +1,7 @@
#ifndef RUBY_ID_TABLE_H
#define RUBY_ID_TABLE_H 1
+#include "ruby/internal/config.h"
+#include <stddef.h>
#include "ruby/ruby.h"
struct rb_id_table;
diff --git a/include/ruby.h b/include/ruby.h
index 076b5ce258..31c1df3c5e 100644
--- a/include/ruby.h
+++ b/include/ruby.h
@@ -1,28 +1,33 @@
-/**********************************************************************
-
- ruby.h -
-
- $Author$
- created at: Sun 10 12:06:15 Jun JST 2007
-
- Copyright (C) 2007-2008 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_H
+#ifndef RUBY_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_H 1
-
+/**
+ * @file
+ * @author $Author$
+ * @date Sun 10 12:06:15 Jun JST 2007
+ * @copyright 2007-2008 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#define HAVE_RUBY_ATOMIC_H 1
+#define HAVE_RUBY_DEBUG_H 1
#define HAVE_RUBY_DEFINES_H 1
#define HAVE_RUBY_ENCODING_H 1
#define HAVE_RUBY_INTERN_H 1
#define HAVE_RUBY_IO_H 1
+#define HAVE_RUBY_MEMORY_VIEW_H 1
#define HAVE_RUBY_MISSING_H 1
+#define HAVE_RUBY_ONIGMO_H 1
#define HAVE_RUBY_ONIGURUMA_H 1
+#define HAVE_RUBY_RACTOR_H 1
+#define HAVE_RUBY_RANDOM_H 1
#define HAVE_RUBY_RE_H 1
#define HAVE_RUBY_REGEX_H 1
#define HAVE_RUBY_RUBY_H 1
#define HAVE_RUBY_ST_H 1
#define HAVE_RUBY_THREAD_H 1
+#define HAVE_RUBY_THREAD_NATIVE_H 1
#define HAVE_RUBY_UTIL_H 1
#define HAVE_RUBY_VERSION_H 1
#define HAVE_RUBY_VM_H 1
diff --git a/include/ruby/assert.h b/include/ruby/assert.h
index d19d8e4e32..9b70d7103e 100644
--- a/include/ruby/assert.h
+++ b/include/ruby/assert.h
@@ -1,54 +1,234 @@
-#ifndef RUBY_ASSERT_H
+#ifndef RUBY_ASSERT_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_ASSERT_H
+/**
+ * @file
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @date Wed May 18 00:21:44 JST 1994
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ * @warning Symbols prefixed with either `RBIMPL` or `rbimpl` are
+ * implementation details. Don't take them as canon. They could
+ * rapidly appear then vanish. The name (path) of this header file
+ * is also an implementation detail. Do not expect it to persist
+ * at the place it is now. Developers are free to move it anywhere
+ * anytime at will.
+ * @note To ruby-core: remember that this header can be possibly
+ * recursively included from extension libraries written in C++.
+ * Do not expect for instance `__VA_ARGS__` is always available.
+ * We assume C99 for ruby itself but we don't assume languages of
+ * extension libraries. They could be written in C++98.
+ */
+#include "ruby/internal/assume.h"
+#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/backward/2/assume.h"
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
+/* RUBY_NDEBUG is very simple: after everything described below are done,
+ * define it with either NDEBUG is undefined (=0) or defined (=1). It is truly
+ * subordinate.
+ *
+ * RUBY_DEBUG versus NDEBUG is complicated. Assertions shall be:
+ *
+ * | -UNDEBUG | -DNDEBUG
+ * ---------------+----------+---------
+ * -URUBY_DEBUG | (*1) | disabled
+ * -DRUBY_DEBUG=0 | disabled | disabled
+ * -DRUBY_DEBUG=1 | enabled | (*2)
+ * -DRUBY_DEBUG | enabled | (*2)
+ *
+ * where:
+ *
+ * - (*1): Assertions shall be silently disabled, no warnings, in favour of
+ * commit 21991e6ca59274e41a472b5256bd3245f6596c90.
+ *
+ * - (*2): Compile-time warnings shall be issued.
+ */
-NORETURN(void rb_assert_failure(const char *, int, const char *, const char *));
-#ifdef RUBY_FUNCTION_NAME_STRING
-# define RUBY_ASSERT_FAIL(expr) \
- rb_assert_failure(__FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING, expr)
+/** @cond INTERNAL_MACRO */
+
+/*
+ * Pro tip: `!!RUBY_DEBUG-1` expands to...
+ *
+ * - `!!(-1)` (== `!0` == `1`) when RUBY_DEBUG is defined to be empty,
+ * - `(!!0)-1` (== `0-1` == `-1`) when RUBY_DEBUG is defined as 0, and
+ * - `(!!n)-1` (== `1-1` == `0`) when RUBY_DEBUG is defined as something else.
+ */
+#if ! defined(RUBY_DEBUG)
+# define RBIMPL_RUBY_DEBUG 0
+#elif !!RUBY_DEBUG-1 < 0
+# define RBIMPL_RUBY_DEBUG 0
#else
-# define RUBY_ASSERT_FAIL(expr) \
- rb_assert_failure(__FILE__, __LINE__, NULL, expr)
+# define RBIMPL_RUBY_DEBUG 1
#endif
-#define RUBY_ASSERT_MESG(expr, mesg) \
- ((expr) ? (void)0 : RUBY_ASSERT_FAIL(mesg))
-#ifdef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P
-# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \
- ((RUBY_DEBUG+0) ? RUBY_ASSERT_MESG((expr), mesg) : \
- __builtin_choose_expr( \
- __builtin_constant_p(cond), \
- __builtin_choose_expr(cond, RUBY_ASSERT_MESG(expr, mesg), (void)0), \
- RUBY_ASSERT_MESG(!(cond) || (expr), mesg)))
+
+/*
+ * ISO/IEC 9899 (all past versions) says that "If NDEBUG is defined as a macro
+ * name at the point in the source file where <assert.h> is included, ..."
+ * which means we must not take its defined value into account.
+ */
+#if defined(NDEBUG)
+# define RBIMPL_NDEBUG 1
#else
-# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \
- RUBY_ASSERT_MESG(!((RUBY_DEBUG+0) || (cond)) || (expr), mesg)
+# define RBIMPL_NDEBUG 0
#endif
-#define RUBY_ASSERT(expr) RUBY_ASSERT_MESG_WHEN((!RUBY_NDEBUG+0), expr, #expr)
-#define RUBY_ASSERT_WHEN(cond, expr) RUBY_ASSERT_MESG_WHEN(cond, expr, #expr)
-#define RUBY_ASSERT_ALWAYS(expr) RUBY_ASSERT_MESG_WHEN(TRUE, expr, #expr)
-#ifndef RUBY_DEBUG
+/** @endcond */
+
+/* Here we go... */
+#undef RUBY_DEBUG
+#undef RUBY_NDEBUG
+#undef NDEBUG
+#if defined(__DOXYGEN__)
+# /** Define this macro when you want assertions. */
# define RUBY_DEBUG 0
-#endif
-#ifndef RUBY_NDEBUG
-# ifdef NDEBUG
-# define RUBY_NDEBUG 1
+# /** Define this macro when you don't want assertions. */
+# define NDEBUG
+# /** This macro is basically the same as #NDEBUG */
+# define RUBY_NDEBUG 1
+
+#elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 0)
+# /* Assertions disabled as per request, no conflicts. */
+# define RUBY_DEBUG 0
+# define RUBY_NDEBUG 1
+# define NDEBUG
+
+#elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 1)
+# /* Assertions enabled as per request, no conflicts. */
+# define RUBY_DEBUG 1
+# define RUBY_NDEBUG 0
+# /* keep NDEBUG undefined */
+
+#elif (RBIMPL_NDEBUG == 0) && (RBIMPL_RUBY_DEBUG == 0)
+# /* The (*1) situation in avobe diagram. */
+# define RUBY_DEBUG 0
+# define RUBY_NDEBUG 1
+# define NDEBUG
+
+#elif (RBIMPL_NDEBUG == 1) && (RBIMPL_RUBY_DEBUG == 1)
+# /* The (*2) situation in above diagram. */
+# define RUBY_DEBUG 1
+# define RUBY_NDEBUG 0
+# /* keep NDEBUG undefined */
+
+# if defined(_MSC_VER)
+# pragma message("NDEBUG is ignored because RUBY_DEBUG>0.")
+# elif defined(__GNUC__)
+# pragma GCC warning "NDEBUG is ignored because RUBY_DEBUG>0."
# else
-# define RUBY_NDEBUG 0
+# error NDEBUG is ignored because RUBY_DEBUG>0.
# endif
#endif
+#undef RBIMPL_NDEBUG
+#undef RBIMPL_RUBY_DEBUG
+
+/** @cond INTERNAL_MACRO */
+#define RBIMPL_ASSERT_NOTHING RBIMPL_CAST((void)0)
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_COLD()
+void rb_assert_failure(const char *file, int line, const char *name, const char *expr);
+RBIMPL_SYMBOL_EXPORT_END()
+
+#ifdef RUBY_FUNCTION_NAME_STRING
+# define RBIMPL_ASSERT_FUNC RUBY_FUNCTION_NAME_STRING
+#else
+# define RBIMPL_ASSERT_FUNC RBIMPL_CAST((const char *)0)
+#endif
+
+/** @endcond */
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
+/**
+ * Prints the given message, and terminates the entire process abnormally.
+ *
+ * @param mesg The message to display.
+ */
+#define RUBY_ASSERT_FAIL(mesg) \
+ rb_assert_failure(__FILE__, __LINE__, RBIMPL_ASSERT_FUNC, mesg)
+
+/**
+ * Asserts that the expression is truthy. If not aborts with the message.
+ *
+ * @param expr What supposedly evaluates to true.
+ * @param mesg The message to display on failure.
+ */
+#define RUBY_ASSERT_MESG(expr, mesg) \
+ (RB_LIKELY(expr) ? RBIMPL_ASSERT_NOTHING : RUBY_ASSERT_FAIL(mesg))
+
+/**
+ * A variant of #RUBY_ASSERT that does not interface with #RUBY_DEBUG.
+ *
+ * @copydetails #RUBY_ASSERT
+ */
+#define RUBY_ASSERT_ALWAYS(expr) RUBY_ASSERT_MESG((expr), #expr)
+
+/**
+ * Asserts that the given expression is truthy iff #RUBY_DEBUG is truthy.
+ *
+ * @param expr What supposedly evaluates to true.
+ */
+#if RUBY_DEBUG
+# define RUBY_ASSERT(expr) RUBY_ASSERT_MESG((expr), #expr)
+#else
+# define RUBY_ASSERT(expr) RBIMPL_ASSERT_NOTHING
#endif
-} /* extern "C" { */
+
+/**
+ * A variant of #RUBY_ASSERT that interfaces with #NDEBUG instead of
+ * #RUBY_DEBUG. This almost resembles `assert` C standard macro, except minor
+ * implementation details.
+ *
+ * @copydetails #RUBY_ASSERT
+ */
+/* Currently `RUBY_DEBUG == ! defined(NDEBUG)` is always true. There is no
+ * difference any longer between this one and `RUBY_ASSERT`. */
+#if defined(NDEBUG)
+# define RUBY_ASSERT_NDEBUG(expr) RBIMPL_ASSERT_NOTHING
+#else
+# define RUBY_ASSERT_NDEBUG(expr) RUBY_ASSERT_MESG((expr), #expr)
#endif
+/**
+ * @copydoc #RUBY_ASSERT_WHEN
+ * @param mesg The message to display on failure.
+ */
+#if RUBY_DEBUG
+# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) RUBY_ASSERT_MESG((expr), (mesg))
+#else
+# define RUBY_ASSERT_MESG_WHEN(cond, expr, mesg) \
+ ((cond) ? RUBY_ASSERT_MESG((expr), (mesg)) : RBIMPL_ASSERT_NOTHING)
#endif
+
+/**
+ * A variant of #RUBY_ASSERT that asserts when either #RUBY_DEBUG or `cond`
+ * parameter is truthy.
+ *
+ * @param cond Extra condition that shall hold for assertion to take effect.
+ * @param expr What supposedly evaluates to true.
+ */
+#define RUBY_ASSERT_WHEN(cond, expr) RUBY_ASSERT_MESG_WHEN((cond), (expr), #expr)
+
+/**
+ * This is either #RUBY_ASSERT or #RBIMPL_ASSUME, depending on #RUBY_DEBUG.
+ *
+ * @copydetails #RUBY_ASSERT
+ */
+#if RUBY_DEBUG
+# define RBIMPL_ASSERT_OR_ASSUME(expr) RUBY_ASSERT_ALWAYS(expr)
+#elif RBIMPL_COMPILER_BEFORE(Clang, 7, 0, 0)
+# /* See commit 67d259c5dccd31fe49d417fec169977712ffdf10 */
+# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING
+#elif defined(RUBY_ASSERT_NOASSUME)
+# /* See commit d300a734414ef6de7e8eb563b7cc4389c455ed08 */
+# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING
+#elif ! defined(RBIMPL_HAVE___ASSUME)
+# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING
+#else
+# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSUME(expr)
+#endif
+
+#endif /* RUBY_ASSERT_H */
diff --git a/include/ruby/atomic.h b/include/ruby/atomic.h
new file mode 100644
index 0000000000..a898c30ddf
--- /dev/null
+++ b/include/ruby/atomic.h
@@ -0,0 +1,236 @@
+#ifndef RUBY_ATOMIC_H
+#define RUBY_ATOMIC_H
+
+/*
+ * - RUBY_ATOMIC_CAS, RUBY_ATOMIC_EXCHANGE, RUBY_ATOMIC_FETCH_*:
+ * return the old * value.
+ * - RUBY_ATOMIC_ADD, RUBY_ATOMIC_SUB, RUBY_ATOMIC_INC, RUBY_ATOMIC_DEC, RUBY_ATOMIC_OR, RUBY_ATOMIC_SET:
+ * may be void.
+ */
+#if 0
+#elif defined HAVE_GCC_ATOMIC_BUILTINS
+typedef unsigned int rb_atomic_t;
+# define RUBY_ATOMIC_FETCH_ADD(var, val) __atomic_fetch_add(&(var), (val), __ATOMIC_SEQ_CST)
+# define RUBY_ATOMIC_FETCH_SUB(var, val) __atomic_fetch_sub(&(var), (val), __ATOMIC_SEQ_CST)
+# define RUBY_ATOMIC_OR(var, val) __atomic_fetch_or(&(var), (val), __ATOMIC_SEQ_CST)
+# define RUBY_ATOMIC_EXCHANGE(var, val) __atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST)
+# define RUBY_ATOMIC_CAS(var, oldval, newval) RB_GNUC_EXTENSION_BLOCK( \
+ __typeof__(var) oldvaldup = (oldval); /* oldval should not be modified */ \
+ __atomic_compare_exchange_n(&(var), &oldvaldup, (newval), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \
+ oldvaldup )
+
+# define RUBY_ATOMIC_GENERIC_MACRO 1
+
+#elif defined HAVE_GCC_SYNC_BUILTINS
+/* @shyouhei hack to support atomic operations in case of gcc. Gcc
+ * has its own pseudo-insns to support them. See info, or
+ * http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html */
+
+typedef unsigned int rb_atomic_t; /* Anything OK */
+# define RUBY_ATOMIC_FETCH_ADD(var, val) __sync_fetch_and_add(&(var), (val))
+# define RUBY_ATOMIC_FETCH_SUB(var, val) __sync_fetch_and_sub(&(var), (val))
+# define RUBY_ATOMIC_OR(var, val) __sync_fetch_and_or(&(var), (val))
+# define RUBY_ATOMIC_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val))
+# define RUBY_ATOMIC_CAS(var, oldval, newval) __sync_val_compare_and_swap(&(var), (oldval), (newval))
+
+# define RUBY_ATOMIC_GENERIC_MACRO 1
+
+#elif defined _WIN32
+#if RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0)
+#pragma intrinsic(_InterlockedOr)
+#endif
+typedef LONG rb_atomic_t;
+
+# define RUBY_ATOMIC_SET(var, val) InterlockedExchange(&(var), (val))
+# define RUBY_ATOMIC_INC(var) InterlockedIncrement(&(var))
+# define RUBY_ATOMIC_DEC(var) InterlockedDecrement(&(var))
+# define RUBY_ATOMIC_FETCH_ADD(var, val) InterlockedExchangeAdd(&(var), (val))
+# define RUBY_ATOMIC_FETCH_SUB(var, val) InterlockedExchangeAdd(&(var), -(LONG)(val))
+#if defined __GNUC__
+# define RUBY_ATOMIC_OR(var, val) __asm__("lock\n\t" "orl\t%1, %0" : "=m"(var) : "Ir"(val))
+#elif RBIMPL_COMPILER_BEFORE(MSVC, 13, 0, 0)
+# define RUBY_ATOMIC_OR(var, val) rb_w32_atomic_or(&(var), (val))
+static inline void
+rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val)
+{
+#ifdef _M_IX86
+ __asm mov eax, var;
+ __asm mov ecx, val;
+ __asm lock or [eax], ecx;
+#else
+#error unsupported architecture
+#endif
+}
+#else
+# define RUBY_ATOMIC_OR(var, val) _InterlockedOr(&(var), (val))
+#endif
+# define RUBY_ATOMIC_EXCHANGE(var, val) InterlockedExchange(&(var), (val))
+# define RUBY_ATOMIC_CAS(var, oldval, newval) InterlockedCompareExchange(&(var), (newval), (oldval))
+# 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 (rb_atomic_t)InterlockedCompareExchange((PVOID *)var, (PVOID)newval, (PVOID)oldval);
+}
+# undef RUBY_ATOMIC_CAS
+# define RUBY_ATOMIC_CAS(var, oldval, newval) rb_w32_atomic_cas(&(var), (oldval), (newval))
+# endif
+# ifdef _M_AMD64
+# define RUBY_ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd64((LONG_LONG *)&(var), (val))
+# define RUBY_ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd64((LONG_LONG *)&(var), -(LONG)(val))
+# define RUBY_ATOMIC_SIZE_INC(var) InterlockedIncrement64(&(var))
+# define RUBY_ATOMIC_SIZE_DEC(var) InterlockedDecrement64(&(var))
+# define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange64(&(var), (val))
+# define RUBY_ATOMIC_SIZE_CAS(var, oldval, newval) InterlockedCompareExchange64(&(var), (newval), (oldval))
+# else
+# define RUBY_ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd((LONG *)&(var), (val))
+# define RUBY_ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd((LONG *)&(var), -(LONG)(val))
+# define RUBY_ATOMIC_SIZE_INC(var) InterlockedIncrement((LONG *)&(var))
+# define RUBY_ATOMIC_SIZE_DEC(var) InterlockedDecrement((LONG *)&(var))
+# define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange((LONG *)&(var), (val))
+# endif
+
+# ifdef InterlockedExchangePointer
+# define RUBY_ATOMIC_PTR_EXCHANGE(var, val) InterlockedExchangePointer((PVOID volatile *)&(var), (PVOID)(val))
+# endif /* See below for definitions of other situations */
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+#include <atomic.h>
+typedef unsigned int rb_atomic_t;
+
+# define RUBY_ATOMIC_INC(var) atomic_inc_uint(&(var))
+# define RUBY_ATOMIC_DEC(var) atomic_dec_uint(&(var))
+# define RUBY_ATOMIC_FETCH_ADD(var, val) rb_atomic_fetch_add(&(var), (val))
+# define RUBY_ATOMIC_FETCH_SUB(var, val) rb_atomic_fetch_sub(&(var), (val))
+# define RUBY_ATOMIC_ADD(var, val) atomic_add_uint(&(var), (val))
+# define RUBY_ATOMIC_SUB(var, val) atomic_sub_uint(&(var), (val))
+# define RUBY_ATOMIC_OR(var, val) atomic_or_uint(&(var), (val))
+# define RUBY_ATOMIC_EXCHANGE(var, val) atomic_swap_uint(&(var), (val))
+# define RUBY_ATOMIC_CAS(var, oldval, newval) atomic_cas_uint(&(var), (oldval), (newval))
+
+static inline rb_atomic_t
+rb_atomic_fetch_add(volatile rb_atomic_t *var, rb_atomic_t val)
+{
+ return atomic_add_int_nv(var, val) - val;
+}
+
+static inline rb_atomic_t
+rb_atomic_fetch_sub(volatile rb_atomic_t *var, rb_atomic_t val)
+{
+ return atomic_add_int_nv(var, (rb_atomic_t)(-(int)val)) + val;
+}
+
+# if defined(_LP64) || defined(_I32LPx)
+# define RUBY_ATOMIC_SIZE_ADD(var, val) atomic_add_long(&(var), (val))
+# define RUBY_ATOMIC_SIZE_SUB(var, val) atomic_add_long(&(var), -(val))
+# define RUBY_ATOMIC_SIZE_INC(var) atomic_inc_ulong(&(var))
+# define RUBY_ATOMIC_SIZE_DEC(var) atomic_dec_ulong(&(var))
+# define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) atomic_swap_ulong(&(var), (val))
+# define RUBY_ATOMIC_SIZE_CAS(var, oldval, val) atomic_cas_ulong(&(var), (oldval), (val))
+# else
+# define RUBY_ATOMIC_SIZE_ADD(var, val) atomic_add_int(&(var), (val))
+# define RUBY_ATOMIC_SIZE_SUB(var, val) atomic_add_int(&(var), -(val))
+# define RUBY_ATOMIC_SIZE_INC(var) atomic_inc_uint(&(var))
+# define RUBY_ATOMIC_SIZE_DEC(var) atomic_dec_uint(&(var))
+# define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) atomic_swap_uint(&(var), (val))
+# endif
+
+#else
+# error No atomic operation found
+#endif
+
+#ifndef RUBY_ATOMIC_SET
+# define RUBY_ATOMIC_SET(var, val) (void)RUBY_ATOMIC_EXCHANGE(var, val)
+#endif
+
+#ifndef RUBY_ATOMIC_ADD
+# define RUBY_ATOMIC_ADD(var, val) (void)RUBY_ATOMIC_FETCH_ADD(var, val)
+#endif
+
+#ifndef RUBY_ATOMIC_SUB
+# define RUBY_ATOMIC_SUB(var, val) (void)RUBY_ATOMIC_FETCH_SUB(var, val)
+#endif
+
+#ifndef RUBY_ATOMIC_INC
+# define RUBY_ATOMIC_INC(var) RUBY_ATOMIC_ADD(var, 1)
+#endif
+
+#ifndef RUBY_ATOMIC_DEC
+# define RUBY_ATOMIC_DEC(var) RUBY_ATOMIC_SUB(var, 1)
+#endif
+
+#ifndef RUBY_ATOMIC_SIZE_INC
+# define RUBY_ATOMIC_SIZE_INC(var) RUBY_ATOMIC_INC(var)
+#endif
+
+#ifndef RUBY_ATOMIC_SIZE_DEC
+# define RUBY_ATOMIC_SIZE_DEC(var) RUBY_ATOMIC_DEC(var)
+#endif
+
+#ifndef RUBY_ATOMIC_SIZE_EXCHANGE
+# define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val)
+#endif
+
+#ifndef RUBY_ATOMIC_SIZE_CAS
+# define RUBY_ATOMIC_SIZE_CAS(var, oldval, val) RUBY_ATOMIC_CAS(var, oldval, val)
+#endif
+
+#ifndef RUBY_ATOMIC_SIZE_ADD
+# define RUBY_ATOMIC_SIZE_ADD(var, val) RUBY_ATOMIC_ADD(var, val)
+#endif
+
+#ifndef RUBY_ATOMIC_SIZE_SUB
+# define RUBY_ATOMIC_SIZE_SUB(var, val) RUBY_ATOMIC_SUB(var, val)
+#endif
+
+#if RUBY_ATOMIC_GENERIC_MACRO
+# ifndef RUBY_ATOMIC_PTR_EXCHANGE
+# define RUBY_ATOMIC_PTR_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val)
+# endif
+
+# ifndef RUBY_ATOMIC_PTR_CAS
+# define RUBY_ATOMIC_PTR_CAS(var, oldval, newval) RUBY_ATOMIC_CAS(var, oldval, newval)
+# endif
+
+# ifndef RUBY_ATOMIC_VALUE_EXCHANGE
+# define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val)
+# endif
+
+# ifndef RUBY_ATOMIC_VALUE_CAS
+# define RUBY_ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_CAS(var, oldval, val)
+# endif
+#endif
+
+#ifndef RUBY_ATOMIC_PTR_EXCHANGE
+# if SIZEOF_VOIDP == SIZEOF_SIZE_T
+# define RUBY_ATOMIC_PTR_EXCHANGE(var, val) (void *)RUBY_ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val))
+# else
+# error No atomic exchange for void*
+# endif
+#endif
+
+#ifndef RUBY_ATOMIC_PTR_CAS
+# if SIZEOF_VOIDP == SIZEOF_SIZE_T
+# define RUBY_ATOMIC_PTR_CAS(var, oldval, val) (void *)RUBY_ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val))
+# else
+# error No atomic compare-and-set for void*
+# endif
+#endif
+
+#ifndef RUBY_ATOMIC_VALUE_EXCHANGE
+# if SIZEOF_VALUE == SIZEOF_SIZE_T
+# define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val))
+# else
+# error No atomic exchange for VALUE
+# endif
+#endif
+
+#ifndef RUBY_ATOMIC_VALUE_CAS
+# if SIZEOF_VALUE == SIZEOF_SIZE_T
+# define RUBY_ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val))
+# else
+# error No atomic compare-and-set for VALUE
+# endif
+#endif
+
+#endif /* RUBY_ATOMIC_H */
diff --git a/include/ruby/backward.h b/include/ruby/backward.h
index 863edf0ed5..350a58ee95 100644
--- a/include/ruby/backward.h
+++ b/include/ruby/backward.h
@@ -1,13 +1,16 @@
-#ifndef RUBY_RUBY_BACKWARD_H
+#ifndef RUBY_RUBY_BACKWARD_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_RUBY_BACKWARD_H 1
-
-#define RClass RClassDeprecated
-#ifndef __cplusplus
-DEPRECATED_TYPE(("RClass is internal use only"),
-struct RClass {
- struct RBasic basic;
-});
-#endif
+/**
+ * @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.
+ */
+#include "ruby/internal/value.h"
+#include "ruby/internal/interpreter.h"
+#include "ruby/backward/2/attributes.h"
#define DECLARE_DEPRECATED_FEATURE(ver, func) \
NORETURN(ERRORFUNC(("deprecated since "#ver), DEPRECATED(void func(void))))
@@ -60,12 +63,9 @@ DECLARE_DEPRECATED_INTERNAL_FEATURE(rb_generic_ivar_table);
NORETURN(ERRORFUNC(("internal function"), VALUE rb_mod_const_missing(VALUE, VALUE)));
/* from version.c */
-#ifndef RUBY_SHOW_COPYRIGHT_TO_DIE
-# define RUBY_SHOW_COPYRIGHT_TO_DIE 1
-#endif
-#if RUBY_SHOW_COPYRIGHT_TO_DIE
+#if defined(RUBY_SHOW_COPYRIGHT_TO_DIE) && !!(RUBY_SHOW_COPYRIGHT_TO_DIE+0)
/* for source code backward compatibility */
-DEPRECATED(static inline int ruby_show_copyright_to_die(int));
+RBIMPL_ATTR_DEPRECATED(("since 2.4"))
static inline int
ruby_show_copyright_to_die(int exitcode)
{
diff --git a/include/ruby/backward/2/assume.h b/include/ruby/backward/2/assume.h
new file mode 100644
index 0000000000..3fbb81439a
--- /dev/null
+++ b/include/ruby/backward/2/assume.h
@@ -0,0 +1,43 @@
+#ifndef RUBY_BACKWARD2_ASSUME_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_ASSUME_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 #ASSUME / #RB_LIKELY / #UNREACHABLE
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/assume.h"
+#include "ruby/internal/has/builtin.h"
+
+#undef ASSUME /* Kill config.h definition */
+#undef UNREACHABLE /* Kill config.h definition */
+#define ASSUME RBIMPL_ASSUME
+#define UNREACHABLE RBIMPL_UNREACHABLE()
+#define UNREACHABLE_RETURN RBIMPL_UNREACHABLE_RETURN
+
+/* likely */
+#if RBIMPL_HAS_BUILTIN(__builtin_expect)
+# define RB_LIKELY(x) (__builtin_expect(!!(x), 1))
+# define RB_UNLIKELY(x) (__builtin_expect(!!(x), 0))
+
+#else
+# define RB_LIKELY(x) (x)
+# define RB_UNLIKELY(x) (x)
+#endif
+
+#endif /* RUBY_BACKWARD2_ASSUME_H */
diff --git a/include/ruby/backward/2/attributes.h b/include/ruby/backward/2/attributes.h
new file mode 100644
index 0000000000..eaff9e3381
--- /dev/null
+++ b/include/ruby/backward/2/attributes.h
@@ -0,0 +1,170 @@
+#ifndef RUBY_BACKWARD2_ATTRIBUTES_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_ATTRIBUTES_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 Various attribute-related macros.
+ *
+ * ### Q&A ###
+ *
+ * - Q: Why are the macros defined in this header file so inconsistent in
+ * style?
+ *
+ * - A: Don't know. Don't blame me. Backward compatibility is the key here.
+ * I'm just preserving what they have been.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/attr/alloc_size.h"
+#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/deprecated.h"
+#include "ruby/internal/attr/error.h"
+#include "ruby/internal/attr/forceinline.h"
+#include "ruby/internal/attr/format.h"
+#include "ruby/internal/attr/maybe_unused.h"
+#include "ruby/internal/attr/noinline.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/attr/restrict.h"
+#include "ruby/internal/attr/returns_nonnull.h"
+#include "ruby/internal/attr/warning.h"
+#include "ruby/internal/has/attribute.h"
+
+/* function attributes */
+#undef CONSTFUNC
+#define CONSTFUNC(x) RBIMPL_ATTR_CONST() x
+
+#undef PUREFUNC
+#define PUREFUNC(x) RBIMPL_ATTR_PURE() x
+
+#undef DEPRECATED
+#define DEPRECATED(x) RBIMPL_ATTR_DEPRECATED(("")) x
+
+#undef DEPRECATED_BY
+#define DEPRECATED_BY(n,x) RBIMPL_ATTR_DEPRECATED(("by: " # n)) x
+
+#undef DEPRECATED_TYPE
+#if defined(__GNUC__)
+# define DEPRECATED_TYPE(mesg, decl) \
+ _Pragma("message \"DEPRECATED_TYPE is deprecated\""); \
+ decl RBIMPL_ATTR_DEPRECATED(mseg)
+#elif defined(_MSC_VER)
+# pragma deprecated(DEPRECATED_TYPE)
+# define DEPRECATED_TYPE(mesg, decl) \
+ __pragma(message(__FILE__"("STRINGIZE(__LINE__)"): warning: " \
+ "DEPRECATED_TYPE is deprecated")) \
+ decl RBIMPL_ATTR_DEPRECATED(mseg)
+#else
+# define DEPRECATED_TYPE(mesg, decl) \
+ <-<-"DEPRECATED_TYPE is deprecated"->->
+#endif
+
+#undef RUBY_CXX_DEPRECATED
+#define RUBY_CXX_DEPRECATED(mseg) RBIMPL_ATTR_DEPRECATED((mseg))
+
+#undef NOINLINE
+#define NOINLINE(x) RBIMPL_ATTR_NOINLINE() x
+
+#ifndef MJIT_HEADER
+# undef ALWAYS_INLINE
+# define ALWAYS_INLINE(x) RBIMPL_ATTR_FORCEINLINE() x
+#endif
+
+#undef ERRORFUNC
+#define ERRORFUNC(mesg, x) RBIMPL_ATTR_ERROR(mesg) x
+#if RBIMPL_HAS_ATTRIBUTE(error)
+# define HAVE_ATTRIBUTE_ERRORFUNC 1
+#else
+# define HAVE_ATTRIBUTE_ERRORFUNC 0
+#endif
+
+#undef WARNINGFUNC
+#define WARNINGFUNC(mesg, x) RBIMPL_ATTR_WARNING(mesg) x
+#if RBIMPL_HAS_ATTRIBUTE(warning)
+# define HAVE_ATTRIBUTE_WARNINGFUNC 1
+#else
+# define HAVE_ATTRIBUTE_WARNINGFUNC 0
+#endif
+
+/*
+ cold attribute for code layout improvements
+ RUBY_FUNC_ATTRIBUTE not used because MSVC does not like nested func macros
+ */
+#undef COLDFUNC
+#define COLDFUNC RBIMPL_ATTR_COLD()
+
+#define PRINTF_ARGS(decl, string_index, first_to_check) \
+ RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, (string_index), (first_to_check)) \
+ decl
+
+#undef RUBY_ATTR_ALLOC_SIZE
+#define RUBY_ATTR_ALLOC_SIZE RBIMPL_ATTR_ALLOC_SIZE
+
+#undef RUBY_ATTR_MALLOC
+#define RUBY_ATTR_MALLOC RBIMPL_ATTR_RESTRICT()
+
+#undef RUBY_ATTR_RETURNS_NONNULL
+#define RUBY_ATTR_RETURNS_NONNULL RBIMPL_ATTR_RETURNS_NONNULL()
+
+#ifndef FUNC_MINIMIZED
+#define FUNC_MINIMIZED(x) x
+#endif
+
+#ifndef FUNC_UNOPTIMIZED
+#define FUNC_UNOPTIMIZED(x) x
+#endif
+
+#ifndef RUBY_ALIAS_FUNCTION_TYPE
+#define RUBY_ALIAS_FUNCTION_TYPE(type, prot, name, args) \
+ FUNC_MINIMIZED(type prot) {return (type)name args;}
+#endif
+
+#ifndef RUBY_ALIAS_FUNCTION_VOID
+#define RUBY_ALIAS_FUNCTION_VOID(prot, name, args) \
+ FUNC_MINIMIZED(void prot) {name args;}
+#endif
+
+#ifndef RUBY_ALIAS_FUNCTION
+#define RUBY_ALIAS_FUNCTION(prot, name, args) \
+ RUBY_ALIAS_FUNCTION_TYPE(VALUE, prot, name, args)
+#endif
+
+#undef RUBY_FUNC_NONNULL
+#define RUBY_FUNC_NONNULL(n, x) RBIMPL_ATTR_NONNULL(n) x
+
+#undef NORETURN
+#define NORETURN(x) RBIMPL_ATTR_NORETURN() x
+#define NORETURN_STYLE_NEW
+
+#ifndef PACKED_STRUCT
+# define PACKED_STRUCT(x) x
+#endif
+
+#ifndef PACKED_STRUCT_UNALIGNED
+# if UNALIGNED_WORD_ACCESS
+# define PACKED_STRUCT_UNALIGNED(x) PACKED_STRUCT(x)
+# else
+# define PACKED_STRUCT_UNALIGNED(x) x
+# endif
+#endif
+
+#undef RB_UNUSED_VAR
+#define RB_UNUSED_VAR(x) x RBIMPL_ATTR_MAYBE_UNUSED()
+
+#endif /* RUBY_BACKWARD2_ATTRIBUTES_H */
diff --git a/include/ruby/backward/2/bool.h b/include/ruby/backward/2/bool.h
new file mode 100644
index 0000000000..53164eb3b8
--- /dev/null
+++ b/include/ruby/backward/2/bool.h
@@ -0,0 +1,37 @@
+#ifndef RUBY_BACKWARD2_BOOL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_BOOL_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 old #TRUE / #FALSE
+ */
+#include "ruby/internal/stdbool.h"
+
+#ifndef FALSE
+# define FALSE false
+#elif FALSE
+# error FALSE must be false
+#endif
+
+#ifndef TRUE
+# define TRUE true
+#elif ! TRUE
+# error TRUE must be true
+#endif
+
+#endif /* RUBY_BACKWARD2_BOOL_H */
diff --git a/include/ruby/backward/2/gcc_version_since.h b/include/ruby/backward/2/gcc_version_since.h
new file mode 100644
index 0000000000..2a5b76c102
--- /dev/null
+++ b/include/ruby/backward/2/gcc_version_since.h
@@ -0,0 +1,38 @@
+#ifndef RUBY_BACKWARD2_GCC_VERSION_SINCE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_GCC_VERSION_SINCE_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 old #GCC_VERSION_SINCE
+ */
+#include "ruby/internal/compiler_since.h"
+
+#ifndef GCC_VERSION_SINCE
+#define GCC_VERSION_SINCE(x, y, z) RBIMPL_COMPILER_SINCE(GCC, (x), (y), (z))
+#endif
+
+#ifndef GCC_VERSION_BEFORE
+#define GCC_VERSION_BEFORE(x, y, z) \
+ (RBIMPL_COMPILER_BEFORE(GCC, (x), (y), (z)) || \
+ (RBIMPL_COMPILER_IS(GCC) && \
+ ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \
+ ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \
+ (RBIMPL_COMPILER_VERSION_PATCH == (z))))))
+#endif
+
+#endif /* RUBY_BACKWARD2_GCC_VERSION_SINCE_H */
diff --git a/include/ruby/backward/2/inttypes.h b/include/ruby/backward/2/inttypes.h
new file mode 100644
index 0000000000..c1e376a107
--- /dev/null
+++ b/include/ruby/backward/2/inttypes.h
@@ -0,0 +1,132 @@
+#ifndef RUBY_BACKWARD2_INTTYPES_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_INTTYPES_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 C99 shim for `<inttypes.h>`
+ */
+#include "ruby/internal/config.h" /* PRI_LL_PREFIX etc. are here */
+
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#include "ruby/internal/value.h" /* PRI_VALUE_PREFIX is here. */
+
+#ifndef PRI_INT_PREFIX
+# define PRI_INT_PREFIX ""
+#endif
+
+#ifndef PRI_LONG_PREFIX
+# define PRI_LONG_PREFIX "l"
+#endif
+
+#ifndef PRI_SHORT_PREFIX
+# define PRI_SHORT_PREFIX "h"
+#endif
+
+#ifdef PRI_64_PREFIX
+# /* Take that. */
+#elif SIZEOF_LONG == 8
+# define PRI_64_PREFIX PRI_LONG_PREFIX
+#elif SIZEOF_LONG_LONG == 8
+# define PRI_64_PREFIX PRI_LL_PREFIX
+#endif
+
+#ifndef PRIdPTR
+# define PRIdPTR PRI_PTR_PREFIX"d"
+# define PRIiPTR PRI_PTR_PREFIX"i"
+# define PRIoPTR PRI_PTR_PREFIX"o"
+# define PRIuPTR PRI_PTR_PREFIX"u"
+# define PRIxPTR PRI_PTR_PREFIX"x"
+# define PRIXPTR PRI_PTR_PREFIX"X"
+#endif
+
+#ifndef RUBY_PRI_VALUE_MARK
+# define RUBY_PRI_VALUE_MARK "\v"
+#endif
+
+#if defined PRIdPTR && !defined PRI_VALUE_PREFIX
+# define PRIdVALUE PRIdPTR
+# define PRIoVALUE PRIoPTR
+# define PRIuVALUE PRIuPTR
+# define PRIxVALUE PRIxPTR
+# define PRIXVALUE PRIXPTR
+# define PRIsVALUE PRIiPTR"" RUBY_PRI_VALUE_MARK
+#else
+# define PRIdVALUE PRI_VALUE_PREFIX"d"
+# define PRIoVALUE PRI_VALUE_PREFIX"o"
+# define PRIuVALUE PRI_VALUE_PREFIX"u"
+# define PRIxVALUE PRI_VALUE_PREFIX"x"
+# define PRIXVALUE PRI_VALUE_PREFIX"X"
+# define PRIsVALUE PRI_VALUE_PREFIX"i" RUBY_PRI_VALUE_MARK
+#endif
+
+#ifndef PRI_VALUE_PREFIX
+# define PRI_VALUE_PREFIX ""
+#endif
+
+#ifdef PRI_TIMET_PREFIX
+# /* Take that. */
+#elif SIZEOF_TIME_T == SIZEOF_INT
+# define PRI_TIMET_PREFIX
+#elif SIZEOF_TIME_T == SIZEOF_LONG
+# define PRI_TIMET_PREFIX "l"
+#elif SIZEOF_TIME_T == SIZEOF_LONG_LONG
+# define PRI_TIMET_PREFIX PRI_LL_PREFIX
+#endif
+
+#ifdef PRI_PTRDIFF_PREFIX
+# /* Take that. */
+#elif SIZEOF_PTRDIFF_T == SIZEOF_INT
+# define PRI_PTRDIFF_PREFIX ""
+#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
+# define PRI_PTRDIFF_PREFIX "l"
+#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
+# define PRI_PTRDIFF_PREFIX PRI_LL_PREFIX
+#endif
+
+#ifndef PRIdPTRDIFF
+# define PRIdPTRDIFF PRI_PTRDIFF_PREFIX"d"
+# define PRIiPTRDIFF PRI_PTRDIFF_PREFIX"i"
+# define PRIoPTRDIFF PRI_PTRDIFF_PREFIX"o"
+# define PRIuPTRDIFF PRI_PTRDIFF_PREFIX"u"
+# define PRIxPTRDIFF PRI_PTRDIFF_PREFIX"x"
+# define PRIXPTRDIFF PRI_PTRDIFF_PREFIX"X"
+#endif
+
+#ifdef PRI_SIZE_PREFIX
+# /* Take that. */
+#elif SIZEOF_SIZE_T == SIZEOF_INT
+# define PRI_SIZE_PREFIX ""
+#elif SIZEOF_SIZE_T == SIZEOF_LONG
+# define PRI_SIZE_PREFIX "l"
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+# define PRI_SIZE_PREFIX PRI_LL_PREFIX
+#endif
+
+#ifndef PRIdSIZE
+# define PRIdSIZE PRI_SIZE_PREFIX"d"
+# define PRIiSIZE PRI_SIZE_PREFIX"i"
+# define PRIoSIZE PRI_SIZE_PREFIX"o"
+# define PRIuSIZE PRI_SIZE_PREFIX"u"
+# define PRIxSIZE PRI_SIZE_PREFIX"x"
+# define PRIXSIZE PRI_SIZE_PREFIX"X"
+#endif
+
+#endif /* RUBY_BACKWARD2_INTTYPES_H */
diff --git a/include/ruby/backward/2/limits.h b/include/ruby/backward/2/limits.h
new file mode 100644
index 0000000000..e38009b01a
--- /dev/null
+++ b/include/ruby/backward/2/limits.h
@@ -0,0 +1,100 @@
+#ifndef RUBY_BACKWARD2_LIMITS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_LIMITS_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 Historical shim for `<limits.h>`.
+ *
+ * The macros in this header file are obsolescent. Does anyone really need our
+ * own definition of #CHAR_BIT today?
+ */
+#include "ruby/internal/config.h"
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include "ruby/backward/2/long_long.h"
+
+#ifndef LONG_MAX
+# /* assuming 32bit(2's complement) long */
+# define LONG_MAX 2147483647L
+#endif
+
+#ifndef LONG_MIN
+# define LONG_MIN (-LONG_MAX-1)
+#endif
+
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+#ifdef LLONG_MAX
+# /* Take that. */
+#elif defined(LONG_LONG_MAX)
+# define LLONG_MAX LONG_LONG_MAX
+#elif defined(_I64_MAX)
+# define LLONG_MAX _I64_MAX
+#else
+# /* assuming 64bit(2's complement) long long */
+# define LLONG_MAX 9223372036854775807LL
+#endif
+
+#ifdef LLONG_MIN
+# /* Take that. */
+#elif defined(LONG_LONG_MIN)
+# define LLONG_MIN LONG_LONG_MIN
+#elif defined(_I64_MAX)
+# define LLONG_MIN _I64_MIN
+#else
+# define LLONG_MIN (-LLONG_MAX-1)
+#endif
+
+#ifdef SIZE_MAX
+# /* Take that. */
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+# define SIZE_MAX ULLONG_MAX
+# define SIZE_MIN ULLONG_MIN
+#elif SIZEOF_SIZE_T == SIZEOF_LONG
+# define SIZE_MAX ULONG_MAX
+# define SIZE_MIN ULONG_MIN
+#elif SIZEOF_SIZE_T == SIZEOF_INT
+# define SIZE_MAX UINT_MAX
+# define SIZE_MIN UINT_MIN
+#else
+# define SIZE_MAX USHRT_MAX
+# define SIZE_MIN USHRT_MIN
+#endif
+
+#ifdef SSIZE_MAX
+# /* Take that. */
+#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+# define SSIZE_MAX LLONG_MAX
+# define SSIZE_MIN LLONG_MIN
+#elif SIZEOF_SIZE_T == SIZEOF_LONG
+# define SSIZE_MAX LONG_MAX
+# define SSIZE_MIN LONG_MIN
+#elif SIZEOF_SIZE_T == SIZEOF_INT
+# define SSIZE_MAX INT_MAX
+# define SSIZE_MIN INT_MIN
+#else
+# define SSIZE_MAX SHRT_MAX
+# define SSIZE_MIN SHRT_MIN
+#endif
+
+#endif /* RUBY_BACKWARD2_LIMITS_H */
diff --git a/include/ruby/backward/2/long_long.h b/include/ruby/backward/2/long_long.h
new file mode 100644
index 0000000000..83eabb459c
--- /dev/null
+++ b/include/ruby/backward/2/long_long.h
@@ -0,0 +1,65 @@
+#ifndef RUBY_BACKWARD2_LONG_LONG_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_LONG_LONG_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 old #LONG_LONG
+ *
+ * No known compiler that can compile today's ruby lacks long long.
+ * Historically MSVC was one of such compiler, but it implemented long long a
+ * while ago (some time back in 2013). The macros are for backwards
+ * compatibility only.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/has/warning.h"
+#include "ruby/internal/warning_push.h"
+
+#if RBIMPL_HAS_WARNING("-Wc++11-long-long")
+# define HAVE_TRUE_LONG_LONG 1
+# define LONG_LONG \
+ RBIMPL_WARNING_PUSH() \
+ RBIMPL_WARNING_IGNORED(-Wc++11-long-long) \
+ long long \
+ RBIMPL_WARNING_POP()
+
+#elif RBIMPL_HAS_WARNING("-Wlong-long")
+# define HAVE_TRUE_LONG_LONG 1
+# define LONG_LONG \
+ RBIMPL_WARNING_PUSH() \
+ RBIMPL_WARNING_IGNORED(-Wlong-long) \
+ long long \
+ RBIMPL_WARNING_POP()
+
+#elif defined(HAVE_LONG_LONG)
+# define HAVE_TRUE_LONG_LONG 1
+# define LONG_LONG long long
+
+#elif SIZEOF___INT64 > 0
+# define HAVE_LONG_LONG 1
+# define LONG_LONG __int64
+# undef SIZEOF_LONG_LONG
+# define SIZEOF_LONG_LONG SIZEOF___INT64
+
+#else
+# error Hello! Ruby developers believe this message must not happen.
+# error If you encounter this message, can you file a bug report?
+# error Remember to attach a detailed description of your environment.
+# error Thank you!
+#endif
+
+#endif /* RBIMPL_BACKWARD2_LONG_LONG_H */
diff --git a/include/ruby/backward/2/r_cast.h b/include/ruby/backward/2/r_cast.h
new file mode 100644
index 0000000000..4600699a9e
--- /dev/null
+++ b/include/ruby/backward/2/r_cast.h
@@ -0,0 +1,33 @@
+#ifndef RUBY_BACKWARD2_R_CAST_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_R_CAST_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 old #R_CAST
+ *
+ * Nobody is actively using this macro.
+ */
+#define R_CAST(st) (struct st*)
+#define RMOVED(obj) (R_CAST(RMoved)(obj))
+
+#if defined(__GNUC__)
+# warning R_CAST and RMOVED are deprecated
+#elif defined(_MSC_VER)
+# pragma message("warning: R_CAST and RMOVED are deprecated")
+#endif
+#endif /* RUBY_BACKWARD2_R_CAST_H */
diff --git a/include/ruby/backward/2/rmodule.h b/include/ruby/backward/2/rmodule.h
new file mode 100644
index 0000000000..a3e2d39f35
--- /dev/null
+++ b/include/ruby/backward/2/rmodule.h
@@ -0,0 +1,37 @@
+#ifndef RUBY_BACKWARD2_RMODULE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_RMODULE_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 Orphan macros.
+ *
+ * These macros seems broken since at least 2011. Nobody (except ruby itself
+ * who is implementing the internals) could have used those macros for a while.
+ * Kept public as-is here to keep some theoretical backwards compatibility.
+ */
+#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m)
+#define RMODULE_CONST_TBL(m) RCLASS_CONST_TBL(m)
+#define RMODULE_M_TBL(m) RCLASS_M_TBL(m)
+#define RMODULE_SUPER(m) RCLASS_SUPER(m)
+
+#if defined(__GNUC__)
+# warning RMODULE_* macros are deprecated
+#elif defined(_MSC_VER)
+# pragma message("warning: RMODULE_* macros are deprecated")
+#endif
+#endif /* RUBY_BACKWARD2_RMODULE_H */
diff --git a/include/ruby/backward/2/stdalign.h b/include/ruby/backward/2/stdalign.h
new file mode 100644
index 0000000000..2d3c333bde
--- /dev/null
+++ b/include/ruby/backward/2/stdalign.h
@@ -0,0 +1,30 @@
+#ifndef RUBY_BACKWARD2_STDALIGN_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_STDALIGN_H
+/**
+ * @file
+ * @author Ruby developers <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 #RUBY_ALIGNAS / #RUBY_ALIGNOF
+ */
+#include "ruby/internal/stdalign.h"
+
+#undef RUBY_ALIGNAS
+#undef RUBY_ALIGNOF
+#define RUBY_ALIGNAS RBIMPL_ALIGNAS
+#define RUBY_ALIGNOF RBIMPL_ALIGNOF
+
+#endif /* RUBY_BACKWARD2_STDALIGN_H */
diff --git a/include/ruby/backward/2/stdarg.h b/include/ruby/backward/2/stdarg.h
new file mode 100644
index 0000000000..c2a9ca1e2f
--- /dev/null
+++ b/include/ruby/backward/2/stdarg.h
@@ -0,0 +1,47 @@
+#ifndef RUBY_BACKWARD2_STDARG_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_BACKWARD2_STDARG_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 old #_
+ *
+ * Nobody should ever use these macros any longer. No konwn compilers lack
+ * prototypes today. It's 21st century. Just forget them.
+ */
+
+#undef _
+#ifdef HAVE_PROTOTYPES
+# define _(args) args
+#else
+# define _(args) ()
+#endif
+
+#undef __
+#ifdef HAVE_STDARG_PROTOTYPES
+# define __(args) args
+#else
+# define __(args) ()
+#endif
+
+#ifdef __cplusplus
+#define ANYARGS ...
+#else
+#define ANYARGS
+#endif
+
+#endif /* RUBY_BACKWARD2_STDARG_H */
diff --git a/include/ruby/backward/classext.h b/include/ruby/backward/classext.h
deleted file mode 100644
index 9d5747316a..0000000000
--- a/include/ruby/backward/classext.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#if defined __GNUC__
-#warning use of RClass internals is deprecated
-#elif defined _MSC_VER
-#pragma message("warning: use of RClass internals is deprecated")
-#endif
-
-#ifndef RUBY_BACKWARD_CLASSEXT_H
-#define RUBY_BACKWARD_CLASSEXT_H 1
-
-typedef struct rb_deprecated_classext_struct {
- VALUE super;
-} rb_deprecated_classext_t;
-
-#undef RCLASS_SUPER(c)
-#define RCLASS_EXT(c) ((rb_deprecated_classext_t *)RCLASS(c)->ptr)
-#define RCLASS_SUPER(c) (RCLASS(c)->super)
-
-#endif /* RUBY_BACKWARD_CLASSEXT_H */
diff --git a/include/ruby/backward/cxxanyargs.hpp b/include/ruby/backward/cxxanyargs.hpp
index 3585f678b8..bc5745d850 100644
--- a/include/ruby/backward/cxxanyargs.hpp
+++ b/include/ruby/backward/cxxanyargs.hpp
@@ -1,7 +1,6 @@
-#ifndef RUBY_BACKWARD_CXXANYARGS_HPP // -*- C++ -*-
+#ifndef RUBY_BACKWARD_CXXANYARGS_HPP //-*-C++-*-vi:ft=cpp
#define RUBY_BACKWARD_CXXANYARGS_HPP
/// @file
-/// @brief Provides old prototypes for C++ programs.
/// @author \@shyouhei
/// @copyright This file is a part of the programming language Ruby.
/// Permission is hereby granted, to either redistribute and/or
@@ -10,39 +9,54 @@
/// @note DO NOT MODERNIZE THIS FILE! As the file name implies it is
/// meant to be a backwards compatibility shim. Please stick to
/// C++ 98 and never use newer features, like `constexpr`.
+/// @brief Provides old prototypes for C++ programs.
+#include "ruby/internal/config.h"
+#include "ruby/internal/intern/class.h"
+#include "ruby/internal/intern/cont.h"
+#include "ruby/internal/intern/hash.h"
+#include "ruby/internal/intern/proc.h"
+#include "ruby/internal/intern/thread.h"
+#include "ruby/internal/intern/variable.h"
+#include "ruby/internal/intern/vm.h"
+#include "ruby/internal/iterator.h"
+#include "ruby/internal/method.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/variable.h"
+#include "ruby/backward/2/stdarg.h"
+#include "ruby/st.h"
+
+extern "C++" {
+
+#ifdef HAVE_NULLPTR
+#include <cstddef>
+#endif
/// @brief The main namespace.
/// @note The name "ruby" might already be taken, but that must not be a
/// problem because namespaces are allowed to reopen.
namespace ruby {
-/// @brief Backwards compatibility layer.
+/// Backwards compatibility layer.
namespace backward {
-/// @brief Provides ANYARGS deprecation warnings.
-///
-/// In C, ANYARGS means there is no function prototype. Literally anything,
-/// even including nothing, can be a valid ANYARGS. So passing a correctly
-/// prototyped function pointer to an ANYARGS-ed function parameter is valid,
-/// at the same time passing an ANYARGS-ed function pointer to a granular typed
-/// function parameter is also valid. However on the other hand in C++,
-/// ANYARGS doesn't actually mean any number of arguments. C++'s ANYARGS means
-/// _variadic_ number of arguments. This is incompatible with ordinal, correct
-/// function prototypes.
+/// Provides ANYARGS deprecation warnings. In C, ANYARGS means there is no
+/// function prototype. Literally anything, even including nothing, can be a
+/// valid ANYARGS. So passing a correctly prototyped function pointer to an
+/// ANYARGS-ed function parameter is valid, at the same time passing an
+/// ANYARGS-ed function pointer to a granular typed function parameter is also
+/// valid. However on the other hand in C++, ANYARGS doesn't actually mean any
+/// number of arguments. C++'s ANYARGS means _variadic_ number of arguments.
+/// This is incompatible with ordinal, correct function prototypes.
///
/// Luckily, function prototypes being distinct each other means they can be
/// overloaded. We can provide a compatibility layer for older Ruby APIs which
/// used to have ANYARGS. This namespace includes such attempts.
namespace cxxanyargs {
-/// @brief ANYARGS-ed function type.
-typedef VALUE type(ANYARGS);
-
-/// @brief ANYARGS-ed function type, void variant.
-typedef void void_type(ANYARGS);
-
-/// @brief ANYARGS-ed function type, int variant.
-typedef int int_type(ANYARGS);
+typedef VALUE type(ANYARGS); ///< ANYARGS-ed function type.
+typedef void void_type(ANYARGS); ///< ANYARGS-ed function type, void variant.
+typedef int int_type(ANYARGS); ///< ANYARGS-ed function type, int variant.
+typedef VALUE onearg_type(VALUE); ///< Single-argumented function type.
/// @name Hooking global variables
/// @{
@@ -64,13 +78,6 @@ rb_define_virtual_variable(const char *q, type *w, void_type *e)
}
RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
-/// @brief Define a function-backended global variable.
-/// @param[in] q Name of the variable.
-/// @param[in] w Getter function.
-/// @param[in] e Setter function.
-/// @note Both functions can be nullptr.
-/// @see rb_define_hooked_variable()
-/// @deprecated Use glanular typed overload instead.
inline void
rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, void_type *e)
{
@@ -79,13 +86,6 @@ rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, void_type *e)
}
RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
-/// @brief Define a function-backended global variable.
-/// @param[in] q Name of the variable.
-/// @param[in] w Getter function.
-/// @param[in] e Setter function.
-/// @note Both functions can be nullptr.
-/// @see rb_define_hooked_variable()
-/// @deprecated Use glanular typed overload instead.
inline void
rb_define_virtual_variable(const char *q, type *w, rb_gvar_setter_t *e)
{
@@ -93,6 +93,36 @@ rb_define_virtual_variable(const char *q, type *w, rb_gvar_setter_t *e)
::rb_define_virtual_variable(q, r, e);
}
+#ifdef HAVE_NULLPTR
+inline void
+rb_define_virtual_variable(const char *q, rb_gvar_getter_t *w, std::nullptr_t e)
+{
+ ::rb_define_virtual_variable(q, w, e);
+}
+
+RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
+inline void
+rb_define_virtual_variable(const char *q, type *w, std::nullptr_t e)
+{
+ rb_gvar_getter_t *r = reinterpret_cast<rb_gvar_getter_t *>(w);
+ ::rb_define_virtual_variable(q, r, e);
+}
+
+inline void
+rb_define_virtual_variable(const char *q, std::nullptr_t w, rb_gvar_setter_t *e)
+{
+ ::rb_define_virtual_variable(q, w, e);
+}
+
+RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
+inline void
+rb_define_virtual_variable(const char *q, std::nullptr_t w, void_type *e)
+{
+ rb_gvar_setter_t *r = reinterpret_cast<rb_gvar_setter_t *>(e);
+ ::rb_define_virtual_variable(q, w, r);
+}
+#endif
+
RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @brief Define a function-backended global variable.
/// @param[in] q Name of the variable.
@@ -111,14 +141,6 @@ rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
}
RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
-/// @brief Define a function-backended global variable.
-/// @param[in] q Name of the variable.
-/// @param[in] w Variable storage.
-/// @param[in] e Getter function.
-/// @param[in] r Setter function.
-/// @note Both functions can be nullptr.
-/// @see rb_define_virtual_variable()
-/// @deprecated Use glanular typed overload instead.
inline void
rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, void_type *r)
{
@@ -127,14 +149,6 @@ rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, void_typ
}
RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
-/// @brief Define a function-backended global variable.
-/// @param[in] q Name of the variable.
-/// @param[in] w Variable storage.
-/// @param[in] e Getter function.
-/// @param[in] r Setter function.
-/// @note Both functions can be nullptr.
-/// @see rb_define_virtual_variable()
-/// @deprecated Use glanular typed overload instead.
inline void
rb_define_hooked_variable(const char *q, VALUE *w, type *e, rb_gvar_setter_t *r)
{
@@ -142,6 +156,36 @@ rb_define_hooked_variable(const char *q, VALUE *w, type *e, rb_gvar_setter_t *r)
::rb_define_hooked_variable(q, w, t, r);
}
+#ifdef HAVE_NULLPTR
+inline void
+rb_define_hooked_variable(const char *q, VALUE *w, rb_gvar_getter_t *e, std::nullptr_t r)
+{
+ ::rb_define_hooked_variable(q, w, e, r);
+}
+
+RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
+inline void
+rb_define_hooked_variable(const char *q, VALUE *w, type *e, std::nullptr_t r)
+{
+ rb_gvar_getter_t *y = reinterpret_cast<rb_gvar_getter_t *>(e);
+ ::rb_define_hooked_variable(q, w, y, r);
+}
+
+inline void
+rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, rb_gvar_setter_t *r)
+{
+ ::rb_define_hooked_variable(q, w, e, r);
+}
+
+RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
+inline void
+rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, void_type *r)
+{
+ rb_gvar_setter_t *y = reinterpret_cast<rb_gvar_setter_t *>(r);
+ ::rb_define_hooked_variable(q, w, e, y);
+}
+#endif
+
/// @}
/// @name Exceptions and tag jumps
/// @{
@@ -157,12 +201,20 @@ RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @deprecated This function is obsolated since long before 2.x era. Do not
/// use it any longer. rb_block_call() is provided instead.
inline VALUE
-rb_iterate(VALUE(*q)(VALUE), VALUE w, type *e, VALUE r)
+rb_iterate(onearg_type *q, VALUE w, type *e, VALUE r)
{
rb_block_call_func_t t = reinterpret_cast<rb_block_call_func_t>(e);
return ::rb_iterate(q, w, t, r);
}
+#ifdef HAVE_NULLPTR
+inline VALUE
+rb_iterate(onearg_type *q, VALUE w, std::nullptr_t e, VALUE r)
+{
+ return ::rb_iterate(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.
@@ -181,6 +233,14 @@ rb_block_call(VALUE q, ID w, int e, const VALUE *r, type *t, VALUE y)
return ::rb_block_call(q, w, e, r, u, y);
}
+#ifdef HAVE_NULLPTR
+inline VALUE
+rb_block_call(VALUE q, ID w, int e, const VALUE *r, std::nullptr_t t, VALUE y)
+{
+ return ::rb_block_call(q, w, e, r, t, y);
+}
+#endif
+
RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @brief An equivalent of `rescue` clause.
/// @param[in] q A function that can raise.
@@ -272,6 +332,14 @@ rb_catch(const char *q, type *w, VALUE e)
return ::rb_catch(q, r, e);
}
+#ifdef HAVE_NULLPTR
+inline VALUE
+rb_catch(const char *q, std::nullptr_t w, VALUE e)
+{
+ return ::rb_catch(q, w, e);
+}
+#endif
+
RUBY_CXX_DEPRECATED("Use of ANYARGS in this function is deprecated")
/// @brief An equivalent of `Kernel#catch`.
/// @param[in] q The "tag" object.
@@ -433,7 +501,183 @@ rb_ivar_foreach(VALUE q, int_type *w, VALUE e)
}
/// @}
-}}}
+
+/// Driver for *_define_method. ::rb_define_method function for instance takes
+/// a pointer to ANYARGS-ed functions, which in fact varies 18 different
+/// prototypes. We still need to preserve ANYARGS for storages but why not
+/// check the consistencies if possible. In C++ a function has its own
+/// prototype, which is a compile-time constant (static type) by nature. We
+/// can list up all the possible input types and provide warnings for other
+/// cases. This is such attempt.
+namespace define_method {
+
+/// Type of ::rb_f_notimplement().
+typedef VALUE notimpl_type(int, const VALUE *, VALUE, VALUE);
+
+/// @brief Template metaprogramming to generate function prototypes.
+/// @tparam T Type of method id (`ID` or `const char*` in practice).
+/// @tparam F Definition driver e.g. ::rb_define_method.
+template<typename T, void (*F)(VALUE klass, T mid, type *func, int arity)>
+struct driver {
+
+ /// @brief Defines a method
+ /// @tparam N Arity of the function.
+ /// @tparam U The function in question
+ template<int N, typename U>
+ struct engine {
+
+ /* :TODO: Following deprecation attribute renders tons of warnings (one
+ * per every method definitions), which is annoying. Of course
+ * annoyance is the core feature of deprecation warnings... But that
+ * could be too much, especially when the warnings happen inside of
+ * machine-generated programs. And SWIG is known to do such thing.
+ * The new (granular) API was introduced in API version 2.7. As of
+ * this writing the version is 2.8. Let's warn this later, some time
+ * during 3.x. Hopefully codes in old (ANYARGS-ed) format should be
+ * less than now. */
+#if (RUBY_API_VERSION_MAJOR * 100 + RUBY_API_VERSION_MINOR) >= 301
+ RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated")
+#endif
+ /// @copydoc define(VALUE klass, T mid, U func)
+ /// @deprecated Pass corrctly typed function instead.
+ static inline void
+ define(VALUE klass, T mid, type func)
+ {
+ F(klass, mid, func, N);
+ }
+
+ /// @brief Defines klass#mid as func, whose arity is N.
+ /// @param[in] klass Where the method lives.
+ /// @param[in] mid Name of the method to define.
+ /// @param[in] func Function that implements klass#mid.
+ static inline void
+ define(VALUE klass, T mid, U func)
+ {
+ F(klass, mid, reinterpret_cast<type *>(func), N);
+ }
+
+ /// @copydoc define(VALUE klass, T mid, U func)
+ static inline void
+ define(VALUE klass, T mid, notimpl_type func)
+ {
+ F(klass, mid, reinterpret_cast<type *>(func), N);
+ }
+ };
+
+ /// @cond INTERNAL_MACRO
+ template<int N, bool = false> struct specific : public engine<N, type *> {};
+ template<bool b> struct specific<15, b> : public engine<15, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<14, b> : public engine<14, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<13, b> : public engine<13, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<12, b> : public engine<12, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<11, b> : public engine<11, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<10, b> : public engine<10, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 9, b> : public engine< 9, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 8, b> : public engine< 8, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 7, b> : public engine< 7, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 6, b> : public engine< 6, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 5, b> : public engine< 5, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 4, b> : public engine< 4, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 3, b> : public engine< 3, VALUE(*)(VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 2, b> : public engine< 2, VALUE(*)(VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 1, b> : public engine< 1, VALUE(*)(VALUE, VALUE)> {};
+ template<bool b> struct specific< 0, b> : public engine< 0, VALUE(*)(VALUE)> {};
+ template<bool b> struct specific<-1, b> : public engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)> {
+ using engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)>::define;
+ static inline void define(VALUE c, T m, VALUE(*f)(int argc, const VALUE *argv, VALUE self)) { F(c, m, reinterpret_cast<type *>(f), -1); }
+ };
+ template<bool b> struct specific<-2, b> : public engine<-2, VALUE(*)(VALUE, VALUE)> {};
+ /// @endcond
+};
+
+/* We could perhaps merge this struct into the one above using variadic
+ * template parameters if we could assume C++11, but sadly we cannot. */
+template<typename T, void (*F)(T mid, type func, int arity)>
+struct driver0 {
+ template<int N, typename U>
+ struct engine {
+ RUBY_CXX_DEPRECATED("use of ANYARGS is deprecated")
+ static inline void
+ define(T mid, type func)
+ {
+ F(mid, func, N);
+ }
+ static inline void
+ define(T mid, U func)
+ {
+ F(mid, reinterpret_cast<type *>(func), N);
+ }
+ static inline void
+ define(T mid, notimpl_type func)
+ {
+ F(mid, reinterpret_cast<type *>(func), N);
+ }
+ };
+ /// @cond INTERNAL_MACRO
+ template<int N, bool = false> struct specific : public engine<N, type *> {};
+ template<bool b> struct specific<15, b> : public engine<15, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<14, b> : public engine<14, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<13, b> : public engine<13, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<12, b> : public engine<12, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<11, b> : public engine<11, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific<10, b> : public engine<10, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 9, b> : public engine< 9, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 8, b> : public engine< 8, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 7, b> : public engine< 7, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 6, b> : public engine< 6, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 5, b> : public engine< 5, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 4, b> : public engine< 4, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 3, b> : public engine< 3, VALUE(*)(VALUE, VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 2, b> : public engine< 2, VALUE(*)(VALUE, VALUE, VALUE)> {};
+ template<bool b> struct specific< 1, b> : public engine< 1, VALUE(*)(VALUE, VALUE)> {};
+ template<bool b> struct specific< 0, b> : public engine< 0, VALUE(*)(VALUE)> {};
+ template<bool b> struct specific<-1, b> : public engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)> {
+ using engine<-1, VALUE(*)(int argc, VALUE *argv, VALUE self)>::define;
+ static inline void define(T m, VALUE(*f)(int argc, const VALUE *argv, VALUE self)) { F(m, reinterpret_cast<type *>(f), -1); }
+ };
+ template<bool b> struct specific<-2, b> : public engine<-2, VALUE(*)(VALUE, VALUE)> {};
+ /// @endcond
+};
+
+struct rb_define_method : public driver <const char *, ::rb_define_method> {}; ///< Dispatches appropriate driver for ::rb_define_method.
+struct rb_define_method_id : public driver <ID, ::rb_define_method_id> {}; ///< Dispatches appropriate driver for ::rb_define_method_id.
+struct rb_define_private_method : public driver <const char *, ::rb_define_private_method> {}; ///< Dispatches appropriate driver for ::rb_define_private_method.
+struct rb_define_protected_method : public driver <const char *, ::rb_define_protected_method> {}; ///< Dispatches appropriate driver for ::rb_define_protected_method.
+struct rb_define_singleton_method : public driver <const char *, ::rb_define_singleton_method> {}; ///< Dispatches appropriate driver for ::rb_define_singleton_method.
+struct rb_define_module_function : public driver <const char *, ::rb_define_module_function> {}; ///< Dispatches appropriate driver for ::rb_define_module_function.
+struct rb_define_global_function : public driver0<const char *, ::rb_define_global_function> {}; ///< Dispatches appropriate driver for ::rb_define_global_function.
+
+/// @brief Defines klass\#mid.
+/// @param klass Where the method lives.
+/// @copydetails #rb_define_global_function(mid, func, arity)
+#define rb_define_method(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_method::specific<arity>::define(klass, mid, func)
+
+/// @copydoc #rb_define_method(klass, mid, func, arity)
+#define rb_define_method_id(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_method_id::specific<arity>::define(klass, mid, func)
+
+/// @brief Defines klass\#mid and makes it private.
+/// @copydetails #rb_define_method(klass, mid, func, arity)
+#define rb_define_private_method(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_private_method::specific<arity>::define(klass, mid, func)
+
+/// @brief Defines klass\#mid and makes it protected.
+/// @copydetails #rb_define_method
+#define rb_define_protected_method(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_protected_method::specific<arity>::define(klass, mid, func)
+
+/// @brief Defines klass.mid.(klass, mid, func, arity)
+/// @copydetails #rb_define_method
+#define rb_define_singleton_method(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_singleton_method::specific<arity>::define(klass, mid, func)
+
+/// @brief Defines klass\#mid and makes it a module function.
+/// @copydetails #rb_define_method(klass, mid, func, arity)
+#define rb_define_module_function(klass, mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_module_function::specific<arity>::define(klass, mid, func)
+
+/// @brief Defines ::rb_mKernel \#mid.
+/// @param mid Name of the defining method.
+/// @param func Implementation of \#mid.
+/// @param arity Arity of \#mid.
+#define rb_define_global_function(mid, func, arity) ruby::backward::cxxanyargs::define_method::rb_define_global_function::specific<arity>::define(mid, func)
+
+}}}}}
using namespace ruby::backward::cxxanyargs;
#endif // RUBY_BACKWARD_CXXANYARGS_HPP
diff --git a/include/ruby/backward/rubyio.h b/include/ruby/backward/rubyio.h
deleted file mode 100644
index a6e3a7c78b..0000000000
--- a/include/ruby/backward/rubyio.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#if defined __GNUC__
-#warning use "ruby/io.h" instead of "rubyio.h"
-#elif defined _MSC_VER
-#pragma message("warning: use \"ruby/io.h\" instead of \"rubyio.h\"")
-#endif
-#include "ruby/io.h"
diff --git a/include/ruby/backward/rubysig.h b/include/ruby/backward/rubysig.h
deleted file mode 100644
index 58b13cab1c..0000000000
--- a/include/ruby/backward/rubysig.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/**********************************************************************
-
- rubysig.h -
-
- $Author$
- $Date$
- created at: Wed Aug 16 01:15:38 JST 1995
-
- Copyright (C) 1993-2008 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#if defined __GNUC__
-#warning rubysig.h is obsolete
-#elif defined _MSC_VER
-#pragma message("warning: rubysig.h is obsolete")
-#endif
-
-#ifndef RUBYSIG_H
-#define RUBYSIG_H
-#include "ruby/ruby.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
-
-#define RUBY_CRITICAL(statements) do {statements;} while (0)
-#define DEFER_INTS (0)
-#define ENABLE_INTS (1)
-#define ALLOW_INTS do {CHECK_INTS;} while (0)
-#define CHECK_INTS rb_thread_check_ints()
-
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
-
-#endif
diff --git a/include/ruby/backward/st.h b/include/ruby/backward/st.h
deleted file mode 100644
index 3e36d44cf8..0000000000
--- a/include/ruby/backward/st.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#if defined __GNUC__
-#warning use "ruby/st.h" instead of bare "st.h"
-#elif defined _MSC_VER
-#pragma message("warning: use \"ruby/st.h\" instead of bare \"st.h\"")
-#endif
-#include "ruby/st.h"
diff --git a/include/ruby/backward/util.h b/include/ruby/backward/util.h
deleted file mode 100644
index 11d32a2da8..0000000000
--- a/include/ruby/backward/util.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#if defined __GNUC__
-#warning use "ruby/util.h" instead of bare "util.h"
-#elif defined _MSC_VER
-#pragma message("warning: use \"ruby/util.h\" instead of bare \"util.h\"")
-#endif
-#include "ruby/util.h"
diff --git a/include/ruby/debug.h b/include/ruby/debug.h
index 8a831e61ab..16891e8458 100644
--- a/include/ruby/debug.h
+++ b/include/ruby/debug.h
@@ -1,25 +1,20 @@
-/**********************************************************************
-
- ruby/debug.h -
-
- $Author: ko1 $
- created at: Tue Nov 20 20:35:08 2012
-
- Copyright (C) 2012 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RB_DEBUG_H
+#ifndef RB_DEBUG_H /*-*-C++-*-vi:se ft=cpp:*/
#define RB_DEBUG_H 1
+/**
+ * @file
+ * @author $Author: ko1 $
+ * @date Tue Nov 20 20:35:08 2012
+ * @copyright Copyright (C) 2012 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/event.h"
+#include "ruby/internal/value.h"
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
+RBIMPL_SYMBOL_EXPORT_BEGIN()
/* Note: This file contains experimental APIs. */
/* APIs can be replaced at Ruby 2.0.1 or later */
@@ -103,13 +98,6 @@ typedef enum {
void rb_add_event_hook2(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag);
void rb_thread_add_event_hook2(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data, rb_event_hook_flag_t hook_flag);
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_DEBUG_H */
diff --git a/include/ruby/defines.h b/include/ruby/defines.h
index dc71d65100..d632a69fc1 100644
--- a/include/ruby/defines.h
+++ b/include/ruby/defines.h
@@ -1,135 +1,28 @@
-/************************************************
-
- defines.h -
-
- $Author$
- created at: Wed May 18 00:21:44 JST 1994
-
-************************************************/
-
-#ifndef RUBY_DEFINES_H
+#ifndef RUBY_DEFINES_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_DEFINES_H 1
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-#include "ruby/config.h"
-#ifdef RUBY_EXTCONF_H
-#include RUBY_EXTCONF_H
-#endif
-
-/* function attributes */
-#ifndef CONSTFUNC
-# define CONSTFUNC(x) x
-#endif
-#ifndef PUREFUNC
-# define PUREFUNC(x) x
-#endif
-#ifndef DEPRECATED
-# define DEPRECATED(x) x
-#endif
-#ifndef DEPRECATED_BY
-# define DEPRECATED_BY(n,x) DEPRECATED(x)
-#endif
-#ifndef DEPRECATED_TYPE
-# define DEPRECATED_TYPE(mesg, decl) decl
-#endif
-#ifndef RUBY_CXX_DEPRECATED
-# define RUBY_CXX_DEPRECATED(mesg) /* nothing */
-#endif
-#ifndef NOINLINE
-# define NOINLINE(x) x
-#endif
-#ifndef ALWAYS_INLINE
-# define ALWAYS_INLINE(x) x
-#endif
-#ifndef ERRORFUNC
-# define HAVE_ATTRIBUTE_ERRORFUNC 0
-# define ERRORFUNC(mesg, x) x
-#else
-# define HAVE_ATTRIBUTE_ERRORFUNC 1
-#endif
-#ifndef WARNINGFUNC
-# define HAVE_ATTRIBUTE_WARNINGFUNC 0
-# define WARNINGFUNC(mesg, x) x
-#else
-# define HAVE_ATTRIBUTE_WARNINGFUNC 1
-#endif
-
-#ifndef GCC_VERSION_SINCE
-# if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
-# define GCC_VERSION_SINCE(major, minor, patchlevel) \
- ((__GNUC__ > (major)) || \
- ((__GNUC__ == (major) && \
- ((__GNUC_MINOR__ > (minor)) || \
- (__GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))))))
-# else
-# define GCC_VERSION_SINCE(major, minor, patchlevel) 0
-# endif
-#endif
-#ifndef GCC_VERSION_BEFORE
-# if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
-# define GCC_VERSION_BEFORE(major, minor, patchlevel) \
- ((__GNUC__ < (major)) || \
- ((__GNUC__ == (major) && \
- ((__GNUC_MINOR__ < (minor)) || \
- (__GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ <= (patchlevel))))))
-# else
-# define GCC_VERSION_BEFORE(major, minor, patchlevel) 0
-# endif
-#endif
-
-/* likely */
-#if __GNUC__ >= 3
-#define RB_LIKELY(x) (__builtin_expect(!!(x), 1))
-#define RB_UNLIKELY(x) (__builtin_expect(!!(x), 0))
-#else /* __GNUC__ >= 3 */
-#define RB_LIKELY(x) (x)
-#define RB_UNLIKELY(x) (x)
-#endif /* __GNUC__ >= 3 */
-
-/*
- cold attribute for code layout improvements
- RUBY_FUNC_ATTRIBUTE not used because MSVC does not like nested func macros
+/**
+ * @file
+ * @author $Author$
+ * @date Wed May 18 00:21:44 JST 1994
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
*/
-#if defined(__clang__) || GCC_VERSION_SINCE(4, 3, 0)
-#define COLDFUNC __attribute__((cold))
-#else
-#define COLDFUNC
-#endif
-#ifdef __GNUC__
-#if defined __MINGW_PRINTF_FORMAT
-#define PRINTF_ARGS(decl, string_index, first_to_check) \
- decl __attribute__((format(__MINGW_PRINTF_FORMAT, string_index, first_to_check)))
-#else
-#define PRINTF_ARGS(decl, string_index, first_to_check) \
- decl __attribute__((format(printf, string_index, first_to_check)))
-#endif
-#else
-#define PRINTF_ARGS(decl, string_index, first_to_check) decl
-#endif
-
-#ifdef __GNUC__
-#define RB_GNUC_EXTENSION __extension__
-#define RB_GNUC_EXTENSION_BLOCK(x) __extension__ ({ x; })
-#else
-#define RB_GNUC_EXTENSION
-#define RB_GNUC_EXTENSION_BLOCK(x) (x)
-#endif
+#include "ruby/internal/config.h"
/* AC_INCLUDES_DEFAULT */
#include <stdio.h>
+
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
+
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
+
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
@@ -138,24 +31,30 @@ extern "C" {
# include <stdlib.h>
# endif
#endif
+
#ifdef HAVE_STRING_H
# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
+
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
+
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
+
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
+
#ifdef HAVE_STDALIGN_H
# include <stdalign.h>
#endif
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -165,377 +64,46 @@ extern "C" {
#endif
#ifdef RUBY_USE_SETJMPEX
-#include <setjmpex.h>
-#endif
-
+# include <setjmpex.h>
+#endif
+
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/xmalloc.h"
+#include "ruby/backward/2/assume.h"
+#include "ruby/backward/2/attributes.h"
+#include "ruby/backward/2/bool.h"
+#include "ruby/backward/2/gcc_version_since.h"
+#include "ruby/backward/2/long_long.h"
+#include "ruby/backward/2/stdalign.h"
+#include "ruby/backward/2/stdarg.h"
+#include "ruby/internal/dosish.h"
#include "ruby/missing.h"
#define RUBY
-#ifdef __cplusplus
-# ifndef HAVE_PROTOTYPES
-# define HAVE_PROTOTYPES 1
-# endif
-# ifndef HAVE_STDARG_PROTOTYPES
-# define HAVE_STDARG_PROTOTYPES 1
-# endif
-#endif
-
-#undef _
-#ifdef HAVE_PROTOTYPES
-# define _(args) args
-#else
-# define _(args) ()
-#endif
-
-#undef __
-#ifdef HAVE_STDARG_PROTOTYPES
-# define __(args) args
-#else
-# define __(args) ()
-#endif
-
-#ifdef __cplusplus
-#define ANYARGS ...
+#ifdef __GNUC__
+# define RB_GNUC_EXTENSION __extension__
+# define RB_GNUC_EXTENSION_BLOCK(x) __extension__ ({ x; })
#else
-#define ANYARGS
-#endif
-
-#ifndef RUBY_SYMBOL_EXPORT_BEGIN
-# define RUBY_SYMBOL_EXPORT_BEGIN /* begin */
-# define RUBY_SYMBOL_EXPORT_END /* end */
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
-
-#define xmalloc ruby_xmalloc
-#define xmalloc2 ruby_xmalloc2
-#define xcalloc ruby_xcalloc
-#define xrealloc ruby_xrealloc
-#define xrealloc2 ruby_xrealloc2
-#define xfree ruby_xfree
-
-#if GCC_VERSION_SINCE(4,3,0)
-# define RUBY_ATTR_ALLOC_SIZE(params) __attribute__ ((alloc_size params))
-#elif defined(__has_attribute)
-# if __has_attribute(alloc_size)
-# define RUBY_ATTR_ALLOC_SIZE(params) __attribute__((__alloc_size__ params))
-# endif
-#endif
-#ifndef RUBY_ATTR_ALLOC_SIZE
-# define RUBY_ATTR_ALLOC_SIZE(params)
-#endif
-
-#ifdef __has_attribute
-# if __has_attribute(malloc)
-# define RUBY_ATTR_MALLOC __attribute__((__malloc__))
-# endif
-#endif
-#ifndef RUBY_ATTR_MALLOC
-# define RUBY_ATTR_MALLOC
-#endif
-
-#ifdef __has_attribute
-# if __has_attribute(returns_nonnull)
-# define RUBY_ATTR_RETURNS_NONNULL __attribute__((__returns_nonnull__))
-# endif
-#endif
-#ifndef RUBY_ATTR_RETURNS_NONNULL
-# define RUBY_ATTR_RETURNS_NONNULL
-#endif
-
-void *ruby_xmalloc(size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1));
-void *ruby_xmalloc2(size_t,size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1,2));
-void *ruby_xcalloc(size_t,size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1,2));
-void *ruby_xrealloc(void*,size_t) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2));
-void *ruby_xrealloc2(void*,size_t,size_t) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2,3));
-void ruby_xfree(void*);
-
-#ifndef USE_GC_MALLOC_OBJ_INFO_DETAILS
-#define USE_GC_MALLOC_OBJ_INFO_DETAILS 0
-#endif
-
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
-
-void *ruby_xmalloc_body(size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1));
-void *ruby_xmalloc2_body(size_t,size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1,2));
-void *ruby_xcalloc_body(size_t,size_t) RUBY_ATTR_MALLOC RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((1,2));
-void *ruby_xrealloc_body(void*,size_t) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2));
-void *ruby_xrealloc2_body(void*,size_t,size_t) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2,3));
-
-#define ruby_xmalloc(s1) ruby_xmalloc_with_location(s1, __FILE__, __LINE__)
-#define ruby_xmalloc2(s1, s2) ruby_xmalloc2_with_location(s1, s2, __FILE__, __LINE__)
-#define ruby_xcalloc(s1, s2) ruby_xcalloc_with_location(s1, s2, __FILE__, __LINE__)
-#define ruby_xrealloc(ptr, s1) ruby_xrealloc_with_location(ptr, s1, __FILE__, __LINE__)
-#define ruby_xrealloc2(ptr, s1, s2) ruby_xrealloc2_with_location(ptr, s1, s2, __FILE__, __LINE__)
-
-extern const char *ruby_malloc_info_file;
-extern int ruby_malloc_info_line;
-
-static inline void *
-ruby_xmalloc_with_location(size_t s, const char *file, int line)
-{
- void *ptr;
- ruby_malloc_info_file = file;
- ruby_malloc_info_line = line;
- ptr = ruby_xmalloc_body(s);
- ruby_malloc_info_file = NULL;
- return ptr;
-}
-
-static inline void *
-ruby_xmalloc2_with_location(size_t s1, size_t s2, const char *file, int line)
-{
- void *ptr;
- ruby_malloc_info_file = file;
- ruby_malloc_info_line = line;
- ptr = ruby_xmalloc2_body(s1, s2);
- ruby_malloc_info_file = NULL;
- return ptr;
-}
-
-static inline void *
-ruby_xcalloc_with_location(size_t s1, size_t s2, const char *file, int line)
-{
- void *ptr;
- ruby_malloc_info_file = file;
- ruby_malloc_info_line = line;
- ptr = ruby_xcalloc_body(s1, s2);
- ruby_malloc_info_file = NULL;
- return ptr;
-}
-
-static inline void *
-ruby_xrealloc_with_location(void *ptr, size_t s, const char *file, int line)
-{
- void *rptr;
- ruby_malloc_info_file = file;
- ruby_malloc_info_line = line;
- rptr = ruby_xrealloc_body(ptr, s);
- ruby_malloc_info_file = NULL;
- return rptr;
-}
-
-static inline void *
-ruby_xrealloc2_with_location(void *ptr, size_t s1, size_t s2, const char *file, int line)
-{
- void *rptr;
- ruby_malloc_info_file = file;
- ruby_malloc_info_line = line;
- rptr = ruby_xrealloc2_body(ptr, s1, s2);
- ruby_malloc_info_file = NULL;
- return rptr;
-}
-#endif
-
-#define STRINGIZE(expr) STRINGIZE0(expr)
-#ifndef STRINGIZE0
-#define STRINGIZE0(expr) #expr
-#endif
-
-#ifdef HAVE_LONG_LONG
-# define HAVE_TRUE_LONG_LONG 1
-#endif
-
-#if SIZEOF_LONG_LONG > 0
-# define LONG_LONG long long
-#elif SIZEOF___INT64 > 0
-# define HAVE_LONG_LONG 1
-# define LONG_LONG __int64
-# undef SIZEOF_LONG_LONG
-# define SIZEOF_LONG_LONG SIZEOF___INT64
-#endif
-
-#ifdef __CYGWIN__
-#undef _WIN32
-#endif
-
-#if defined(_WIN32)
-/*
- DOSISH mean MS-Windows style filesystem.
- But you should use more precise macros like DOSISH_DRIVE_LETTER, PATH_SEP,
- ENV_IGNORECASE or CASEFOLD_FILESYSTEM.
- */
-#define DOSISH 1
-# define DOSISH_DRIVE_LETTER
-#endif
-
-#ifdef AC_APPLE_UNIVERSAL_BUILD
-#undef WORDS_BIGENDIAN
-#ifdef __BIG_ENDIAN__
-#define WORDS_BIGENDIAN
-#endif
-#endif
-
-#ifdef _WIN32
-#include "ruby/win32.h"
-#endif
-
-#ifdef RUBY_EXPORT
-#undef RUBY_EXTERN
-
-#ifndef FALSE
-# define FALSE 0
-#elif FALSE
-# error FALSE must be false
-#endif
-#ifndef TRUE
-# define TRUE 1
-#elif !TRUE
-# error TRUE must be true
-#endif
-
-#endif
-
-#ifndef RUBY_FUNC_EXPORTED
-#define RUBY_FUNC_EXPORTED
-#endif
-
-/* These macros are used for functions which are exported only for MJIT
- and NOT ensured to be exported in future versions. */
-#define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED
-#define MJIT_SYMBOL_EXPORT_BEGIN RUBY_SYMBOL_EXPORT_BEGIN
-#define MJIT_SYMBOL_EXPORT_END RUBY_SYMBOL_EXPORT_END
-
-#if defined(MJIT_HEADER) && defined(_MSC_VER)
-# undef MJIT_FUNC_EXPORTED
-# define MJIT_FUNC_EXPORTED static
-#endif
-
-#ifndef RUBY_EXTERN
-#define RUBY_EXTERN extern
-#endif
-
-#ifndef EXTERN
-# if defined __GNUC__
-# define EXTERN _Pragma("message \"EXTERN is deprecated, use RUBY_EXTERN instead\""); \
- RUBY_EXTERN
-# elif defined _MSC_VER
-# define EXTERN __pragma(message(__FILE__"("STRINGIZE(__LINE__)"): warning: "\
- "EXTERN is deprecated, use RUBY_EXTERN instead")); \
- RUBY_EXTERN
-# else
-# define EXTERN <-<-"EXTERN is deprecated, use RUBY_EXTERN instead"->->
-# endif
+# define RB_GNUC_EXTENSION
+# define RB_GNUC_EXTENSION_BLOCK(x) (x)
#endif
+/* :FIXME: Can someone tell us why is this macro defined here? @shyouhei
+ * thinks this is a truly internal macro but cannot move around because he
+ * doesn't understand the reason of this arrangement. */
#ifndef RUBY_MBCHAR_MAXSIZE
-#define RUBY_MBCHAR_MAXSIZE INT_MAX
- /* MB_CUR_MAX will not work well in C locale */
+# define RUBY_MBCHAR_MAXSIZE INT_MAX
+# /* MB_CUR_MAX will not work well in C locale */
#endif
#if defined(__sparc)
+RBIMPL_SYMBOL_EXPORT_BEGIN()
void rb_sparc_flush_register_windows(void);
-# define FLUSH_REGISTER_WINDOWS rb_sparc_flush_register_windows()
-#else
-# define FLUSH_REGISTER_WINDOWS ((void)0)
-#endif
-
-#if defined(DOSISH)
-#define PATH_SEP ";"
-#else
-#define PATH_SEP ":"
-#endif
-#define PATH_SEP_CHAR PATH_SEP[0]
-
-#define PATH_ENV "PATH"
-
-#if defined(DOSISH)
-#define ENV_IGNORECASE
-#endif
-
-#ifndef CASEFOLD_FILESYSTEM
-# if defined DOSISH
-# define CASEFOLD_FILESYSTEM 1
-# else
-# define CASEFOLD_FILESYSTEM 0
-# endif
-#endif
-
-#ifndef DLEXT_MAXLEN
-#define DLEXT_MAXLEN 4
-#endif
-
-#ifndef RUBY_PLATFORM
-#define RUBY_PLATFORM "unknown-unknown"
-#endif
-
-#ifndef FUNC_MINIMIZED
-#define FUNC_MINIMIZED(x) x
-#endif
-#ifndef FUNC_UNOPTIMIZED
-#define FUNC_UNOPTIMIZED(x) x
-#endif
-#ifndef RUBY_ALIAS_FUNCTION_TYPE
-#define RUBY_ALIAS_FUNCTION_TYPE(type, prot, name, args) \
- FUNC_MINIMIZED(type prot) {return (type)name args;}
-#endif
-#ifndef RUBY_ALIAS_FUNCTION_VOID
-#define RUBY_ALIAS_FUNCTION_VOID(prot, name, args) \
- FUNC_MINIMIZED(void prot) {name args;}
-#endif
-#ifndef RUBY_ALIAS_FUNCTION
-#define RUBY_ALIAS_FUNCTION(prot, name, args) \
- RUBY_ALIAS_FUNCTION_TYPE(VALUE, prot, name, args)
-#endif
-#ifndef RUBY_FUNC_NONNULL
-#define RUBY_FUNC_NONNULL(n, x) x
-#endif
-
-#ifndef UNALIGNED_WORD_ACCESS
-# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
- defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
- defined(__powerpc64__) || \
- defined(__aarch64__) || \
- defined(__mc68020__)
-# define UNALIGNED_WORD_ACCESS 1
-# else
-# define UNALIGNED_WORD_ACCESS 0
-# endif
-#endif
-#ifndef PACKED_STRUCT
-# define PACKED_STRUCT(x) x
-#endif
-#ifndef PACKED_STRUCT_UNALIGNED
-# if UNALIGNED_WORD_ACCESS
-# define PACKED_STRUCT_UNALIGNED(x) PACKED_STRUCT(x)
-# else
-# define PACKED_STRUCT_UNALIGNED(x) x
-# endif
-#endif
-
-#ifndef RUBY_ALIGNAS
-#define RUBY_ALIGNAS(x) /* x */
-#endif
-
-#ifdef RUBY_ALIGNOF
-/* OK, take that definition */
-#elif defined(__cplusplus) && (__cplusplus >= 201103L)
-#define RUBY_ALIGNOF alignof
-#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
-#define RUBY_ALIGNOF _Alignof
-#else
-#define RUBY_ALIGNOF(type) ((size_t)offsetof(struct { char f1; type f2; }, f2))
-#endif
-
-#define NORETURN_STYLE_NEW 1
-#ifdef NORETURN
-/* OK, take that definition */
-#elif defined(__cplusplus) && (__cplusplus >= 201103L)
-#define NORETURN(x) [[ noreturn ]] x
-#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
-#define NORETURN(x) _Noreturn x
+RBIMPL_SYMBOL_EXPORT_END()
+# define FLUSH_REGISTER_WINDOWS rb_sparc_flush_register_windows()
#else
-#define NORETURN(x) x
-#endif
-
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
+# define FLUSH_REGISTER_WINDOWS ((void)0)
#endif
#endif /* RUBY_DEFINES_H */
diff --git a/include/ruby/encoding.h b/include/ruby/encoding.h
index 93939ee7db..07e6c9a671 100644
--- a/include/ruby/encoding.h
+++ b/include/ruby/encoding.h
@@ -1,33 +1,22 @@
-/**********************************************************************
-
- encoding.h -
-
- $Author: matz $
- created at: Thu May 24 11:49:41 JST 2007
-
- Copyright (C) 2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_ENCODING_H
+#ifndef RUBY_ENCODING_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_ENCODING_H 1
-
-#ifdef RUBY_INTERNAL_H
-#error "Include this file before internal.h"
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
+/**
+ * @file
+ * @author $Author: matz $
+ * @date Thu May 24 11:49:41 JST 2007
+ * @copyright Copyright (C) 2007 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#include "ruby/internal/config.h"
#include <stdarg.h>
#include "ruby/ruby.h"
#include "ruby/oniguruma.h"
+#include "ruby/internal/dllexport.h"
-RUBY_SYMBOL_EXPORT_BEGIN
+RBIMPL_SYMBOL_EXPORT_BEGIN()
enum ruby_encoding_consts {
RUBY_ENCODING_INLINE_MAX = 127,
@@ -138,6 +127,8 @@ void rb_enc_copy(VALUE dst, VALUE src);
VALUE rb_enc_str_new(const char*, long, rb_encoding*);
VALUE rb_enc_str_new_cstr(const char*, rb_encoding*);
VALUE rb_enc_str_new_static(const char*, long, rb_encoding*);
+VALUE rb_enc_interned_str(const char *, long, rb_encoding *);
+VALUE rb_enc_interned_str_cstr(const char *, rb_encoding *);
VALUE rb_enc_reg_new(const char*, long, rb_encoding*, int);
PRINTF_ARGS(VALUE rb_enc_sprintf(rb_encoding *, const char*, ...), 2, 3);
VALUE rb_enc_vsprintf(rb_encoding *, const char*, va_list);
@@ -417,13 +408,6 @@ enum ruby_econv_flag_type {
/* end of flags for rb_econv_convert */
RUBY_ECONV_FLAGS_PLACEHOLDER};
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_ENCODING_H */
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 2f60fb569e..2480e2e703 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -1,1230 +1,64 @@
-/**********************************************************************
-
- intern.h -
-
- $Author$
- created at: Thu Jun 10 14:22:17 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
-#ifndef RUBY_INTERN_H
+#ifndef RUBY_INTERN_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_INTERN_H 1
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-#if !defined(__has_attribute)
-#define __has_attribute(x) 0
-#endif
-
+/**
+ * @file
+ * @author $Author$
+ * @date Thu Jun 10 14:22:17 JST 1993
+ * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#include "ruby/internal/config.h"
#include "ruby/defines.h"
-#ifdef RUBY_EXTCONF_H
-#include RUBY_EXTCONF_H
-#endif
-#ifdef HAVE_STDARG_PROTOTYPES
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
+#include <stdarg.h>
#include "ruby/st.h"
-/* On mswin, MJIT header transformation can't be used since cl.exe can't output
- preprocessed output preserving macros. So this `MJIT_STATIC` is needed
- to force non-static function to static on MJIT header to avoid symbol conflict. */
-#ifdef MJIT_HEADER
-# define MJIT_STATIC static
-#else
-# define MJIT_STATIC
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
-
/*
* Functions and variables that are used by more than one source file of
* the kernel.
*/
-#define UNLIMITED_ARGUMENTS (-1)
-
-/* array.c */
-void rb_mem_clear(VALUE*, long);
-VALUE rb_assoc_new(VALUE, VALUE);
-VALUE rb_check_array_type(VALUE);
-VALUE rb_ary_new(void);
-VALUE rb_ary_new_capa(long capa);
-VALUE rb_ary_new_from_args(long n, ...);
-VALUE rb_ary_new_from_values(long n, const VALUE *elts);
-VALUE rb_ary_tmp_new(long);
-void rb_ary_free(VALUE);
-void rb_ary_modify(VALUE);
-VALUE rb_ary_freeze(VALUE);
-VALUE rb_ary_shared_with_p(VALUE, VALUE);
-VALUE rb_ary_aref(int, const VALUE*, VALUE);
-VALUE rb_ary_subseq(VALUE, long, long);
-void rb_ary_store(VALUE, long, VALUE);
-VALUE rb_ary_dup(VALUE);
-VALUE rb_ary_resurrect(VALUE ary);
-VALUE rb_ary_to_ary(VALUE);
-VALUE rb_ary_to_s(VALUE);
-VALUE rb_ary_cat(VALUE, const VALUE *, long);
-VALUE rb_ary_push(VALUE, VALUE);
-VALUE rb_ary_pop(VALUE);
-VALUE rb_ary_shift(VALUE);
-VALUE rb_ary_unshift(VALUE, VALUE);
-VALUE rb_ary_entry(VALUE, long);
-VALUE rb_ary_each(VALUE);
-VALUE rb_ary_join(VALUE, VALUE);
-VALUE rb_ary_reverse(VALUE);
-VALUE rb_ary_rotate(VALUE, long);
-VALUE rb_ary_sort(VALUE);
-VALUE rb_ary_sort_bang(VALUE);
-VALUE rb_ary_delete(VALUE, VALUE);
-VALUE rb_ary_delete_at(VALUE, long);
-VALUE rb_ary_clear(VALUE);
-VALUE rb_ary_plus(VALUE, VALUE);
-VALUE rb_ary_concat(VALUE, VALUE);
-VALUE rb_ary_assoc(VALUE, VALUE);
-VALUE rb_ary_rassoc(VALUE, VALUE);
-VALUE rb_ary_includes(VALUE, VALUE);
-VALUE rb_ary_cmp(VALUE, VALUE);
-VALUE rb_ary_replace(VALUE copy, VALUE orig);
-VALUE rb_get_values_at(VALUE, long, int, const VALUE*, VALUE(*)(VALUE,long));
-VALUE rb_ary_resize(VALUE ary, long len);
-#define rb_ary_new2 rb_ary_new_capa
-#define rb_ary_new3 rb_ary_new_from_args
-#define rb_ary_new4 rb_ary_new_from_values
-/* bignum.c */
-VALUE rb_big_new(size_t, int);
-int rb_bigzero_p(VALUE x);
-VALUE rb_big_clone(VALUE);
-void rb_big_2comp(VALUE);
-VALUE rb_big_norm(VALUE);
-void rb_big_resize(VALUE big, size_t len);
-VALUE rb_cstr_to_inum(const char*, int, int);
-VALUE rb_str_to_inum(VALUE, int, int);
-VALUE rb_cstr2inum(const char*, int);
-VALUE rb_str2inum(VALUE, int);
-VALUE rb_big2str(VALUE, int);
-long rb_big2long(VALUE);
-#define rb_big2int(x) rb_big2long(x)
-unsigned long rb_big2ulong(VALUE);
-#define rb_big2uint(x) rb_big2ulong(x)
-#if HAVE_LONG_LONG
-LONG_LONG rb_big2ll(VALUE);
-unsigned LONG_LONG rb_big2ull(VALUE);
-#endif /* HAVE_LONG_LONG */
-void rb_big_pack(VALUE val, unsigned long *buf, long num_longs);
-VALUE rb_big_unpack(unsigned long *buf, long num_longs);
-int rb_uv_to_utf8(char[6],unsigned long);
-VALUE rb_dbl2big(double);
-double rb_big2dbl(VALUE);
-VALUE rb_big_cmp(VALUE, VALUE);
-VALUE rb_big_eq(VALUE, VALUE);
-VALUE rb_big_eql(VALUE, VALUE);
-VALUE rb_big_plus(VALUE, VALUE);
-VALUE rb_big_minus(VALUE, VALUE);
-VALUE rb_big_mul(VALUE, VALUE);
-VALUE rb_big_div(VALUE, VALUE);
-VALUE rb_big_idiv(VALUE, VALUE);
-VALUE rb_big_modulo(VALUE, VALUE);
-VALUE rb_big_divmod(VALUE, VALUE);
-VALUE rb_big_pow(VALUE, VALUE);
-VALUE rb_big_and(VALUE, VALUE);
-VALUE rb_big_or(VALUE, VALUE);
-VALUE rb_big_xor(VALUE, VALUE);
-VALUE rb_big_lshift(VALUE, VALUE);
-VALUE rb_big_rshift(VALUE, VALUE);
-
-/* For rb_integer_pack and rb_integer_unpack: */
-/* "MS" in MSWORD and MSBYTE means "most significant" */
-/* "LS" in LSWORD and LSBYTE means "least significant" */
-#define INTEGER_PACK_MSWORD_FIRST 0x01
-#define INTEGER_PACK_LSWORD_FIRST 0x02
-#define INTEGER_PACK_MSBYTE_FIRST 0x10
-#define INTEGER_PACK_LSBYTE_FIRST 0x20
-#define INTEGER_PACK_NATIVE_BYTE_ORDER 0x40
-#define INTEGER_PACK_2COMP 0x80
-#define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION 0x400
-/* For rb_integer_unpack: */
-#define INTEGER_PACK_FORCE_BIGNUM 0x100
-#define INTEGER_PACK_NEGATIVE 0x200
-/* Combinations: */
-#define INTEGER_PACK_LITTLE_ENDIAN \
- (INTEGER_PACK_LSWORD_FIRST | \
- INTEGER_PACK_LSBYTE_FIRST)
-#define INTEGER_PACK_BIG_ENDIAN \
- (INTEGER_PACK_MSWORD_FIRST | \
- INTEGER_PACK_MSBYTE_FIRST)
-int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags);
-VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags);
-size_t rb_absint_size(VALUE val, int *nlz_bits_ret);
-size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret);
-int rb_absint_singlebit_p(VALUE val);
-
-/* rational.c */
-VALUE rb_rational_raw(VALUE, VALUE);
-#define rb_rational_raw1(x) rb_rational_raw((x), INT2FIX(1))
-#define rb_rational_raw2(x,y) rb_rational_raw((x), (y))
-VALUE rb_rational_new(VALUE, VALUE);
-#define rb_rational_new1(x) rb_rational_new((x), INT2FIX(1))
-#define rb_rational_new2(x,y) rb_rational_new((x), (y))
-VALUE rb_Rational(VALUE, VALUE);
-#define rb_Rational1(x) rb_Rational((x), INT2FIX(1))
-#define rb_Rational2(x,y) rb_Rational((x), (y))
-VALUE rb_rational_num(VALUE rat);
-VALUE rb_rational_den(VALUE rat);
-VALUE rb_flt_rationalize_with_prec(VALUE, VALUE);
-VALUE rb_flt_rationalize(VALUE);
-/* complex.c */
-VALUE rb_complex_raw(VALUE, VALUE);
-#define rb_complex_raw1(x) rb_complex_raw((x), INT2FIX(0))
-#define rb_complex_raw2(x,y) rb_complex_raw((x), (y))
-VALUE rb_complex_new(VALUE, VALUE);
-#define rb_complex_new1(x) rb_complex_new((x), INT2FIX(0))
-#define rb_complex_new2(x,y) rb_complex_new((x), (y))
-VALUE rb_complex_new_polar(VALUE abs, VALUE arg);
-DEPRECATED_BY(rb_complex_new_polar, VALUE rb_complex_polar(VALUE abs, VALUE arg));
-VALUE rb_complex_real(VALUE z);
-VALUE rb_complex_imag(VALUE z);
-VALUE rb_complex_plus(VALUE x, VALUE y);
-VALUE rb_complex_minus(VALUE x, VALUE y);
-VALUE rb_complex_mul(VALUE x, VALUE y);
-VALUE rb_complex_div(VALUE x, VALUE y);
-VALUE rb_complex_uminus(VALUE z);
-VALUE rb_complex_conjugate(VALUE z);
-VALUE rb_complex_abs(VALUE z);
-VALUE rb_complex_arg(VALUE z);
-VALUE rb_complex_pow(VALUE base, VALUE exp);
-VALUE rb_dbl_complex_new(double real, double imag);
-#define rb_complex_add rb_complex_plus
-#define rb_complex_sub rb_complex_minus
-#define rb_complex_nagate rb_complex_uminus
-
-VALUE rb_Complex(VALUE, VALUE);
-#define rb_Complex1(x) rb_Complex((x), INT2FIX(0))
-#define rb_Complex2(x,y) rb_Complex((x), (y))
-/* class.c */
-VALUE rb_class_new(VALUE);
-VALUE rb_mod_init_copy(VALUE, VALUE);
-VALUE rb_singleton_class_clone(VALUE);
-void rb_singleton_class_attached(VALUE,VALUE);
-void rb_check_inheritable(VALUE);
-VALUE rb_define_class_id(ID, VALUE);
-VALUE rb_define_class_id_under(VALUE, ID, VALUE);
-VALUE rb_module_new(void);
-VALUE rb_define_module_id(ID);
-VALUE rb_define_module_id_under(VALUE, ID);
-VALUE rb_mod_included_modules(VALUE);
-VALUE rb_mod_include_p(VALUE, VALUE);
-VALUE rb_mod_ancestors(VALUE);
-VALUE rb_class_instance_methods(int, const VALUE*, VALUE);
-VALUE rb_class_public_instance_methods(int, const VALUE*, VALUE);
-VALUE rb_class_protected_instance_methods(int, const VALUE*, VALUE);
-VALUE rb_class_private_instance_methods(int, const VALUE*, VALUE);
-VALUE rb_obj_singleton_methods(int, const VALUE*, VALUE);
-void rb_define_method_id(VALUE, ID, VALUE (*)(ANYARGS), int);
-void rb_undef(VALUE, ID);
-void rb_define_protected_method(VALUE, const char*, VALUE (*)(ANYARGS), int);
-void rb_define_private_method(VALUE, const char*, VALUE (*)(ANYARGS), int);
-void rb_define_singleton_method(VALUE, const char*, VALUE(*)(ANYARGS), int);
-VALUE rb_singleton_class(VALUE);
-/* compar.c */
-int rb_cmpint(VALUE, VALUE, VALUE);
-NORETURN(void rb_cmperr(VALUE, VALUE));
-/* cont.c */
-VALUE rb_fiber_new(rb_block_call_func_t, VALUE);
-VALUE rb_fiber_resume(VALUE fib, int argc, const VALUE *argv);
-VALUE rb_fiber_resume_kw(VALUE fib, int argc, const VALUE *argv, int kw_splat);
-VALUE rb_fiber_yield(int argc, const VALUE *argv);
-VALUE rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat);
-VALUE rb_fiber_current(void);
-VALUE rb_fiber_alive_p(VALUE);
-/* enum.c */
-VALUE rb_enum_values_pack(int, const VALUE*);
-/* enumerator.c */
-VALUE rb_enumeratorize(VALUE, VALUE, int, const VALUE *);
-typedef VALUE rb_enumerator_size_func(VALUE, VALUE, VALUE);
-VALUE rb_enumeratorize_with_size(VALUE, VALUE, int, const VALUE *, rb_enumerator_size_func *);
-VALUE rb_enumeratorize_with_size_kw(VALUE, VALUE, int, const VALUE *, rb_enumerator_size_func *, int);
-#ifndef RUBY_EXPORT
-#define rb_enumeratorize_with_size(obj, id, argc, argv, size_fn) \
- rb_enumeratorize_with_size(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn))
-#define rb_enumeratorize_with_size_kw(obj, id, argc, argv, size_fn, kw_splat) \
- rb_enumeratorize_with_size_kw(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn), kw_splat)
-#endif
-#define SIZED_ENUMERATOR(obj, argc, argv, size_fn) \
- rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), \
- (argc), (argv), (size_fn))
-#define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \
- rb_enumeratorize_with_size_kw((obj), ID2SYM(rb_frame_this_func()), \
- (argc), (argv), (size_fn), (kw_splat))
-#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) do { \
- if (!rb_block_given_p()) \
- return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \
- } while (0)
-#define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \
- if (!rb_block_given_p()) \
- return SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat); \
- } while (0)
-#define RETURN_ENUMERATOR(obj, argc, argv) RETURN_SIZED_ENUMERATOR(obj, argc, argv, 0)
-#define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, 0, kw_splat)
-typedef struct {
- VALUE begin;
- VALUE end;
- VALUE step;
- int exclude_end;
-} rb_arithmetic_sequence_components_t;
-int rb_arithmetic_sequence_extract(VALUE, rb_arithmetic_sequence_components_t *);
-/* error.c */
-VALUE rb_exc_new(VALUE, const char*, long);
-VALUE rb_exc_new_cstr(VALUE, const char*);
-VALUE rb_exc_new_str(VALUE, VALUE);
-#define rb_exc_new2 rb_exc_new_cstr
-#define rb_exc_new3 rb_exc_new_str
-PRINTF_ARGS(NORETURN(void rb_loaderror(const char*, ...)), 1, 2);
-PRINTF_ARGS(NORETURN(void rb_loaderror_with_path(VALUE path, const char*, ...)), 2, 3);
-PRINTF_ARGS(NORETURN(void rb_name_error(ID, const char*, ...)), 2, 3);
-PRINTF_ARGS(NORETURN(void rb_name_error_str(VALUE, const char*, ...)), 2, 3);
-PRINTF_ARGS(NORETURN(void rb_frozen_error_raise(VALUE, const char*, ...)), 2, 3);
-NORETURN(void rb_invalid_str(const char*, const char*));
-NORETURN(void rb_error_frozen(const char*));
-NORETURN(void rb_error_frozen_object(VALUE));
-void rb_error_untrusted(VALUE);
-void rb_check_frozen(VALUE);
-void rb_check_trusted(VALUE);
-#define rb_check_frozen_internal(obj) do { \
- VALUE frozen_obj = (obj); \
- if (RB_UNLIKELY(RB_OBJ_FROZEN(frozen_obj))) { \
- rb_error_frozen_object(frozen_obj); \
- } \
- } while (0)
-#ifdef __GNUC__
-#define rb_check_frozen(obj) __extension__({rb_check_frozen_internal(obj);})
-#else
-static inline void
-rb_check_frozen_inline(VALUE obj)
-{
- rb_check_frozen_internal(obj);
-}
-#define rb_check_frozen(obj) rb_check_frozen_inline(obj)
-static inline void
-rb_check_trusted_inline(VALUE obj)
-{
- rb_check_trusted(obj);
-}
-#define rb_check_trusted(obj) rb_check_trusted_inline(obj)
-#endif
-void rb_check_copyable(VALUE obj, VALUE orig);
-
-#define RB_OBJ_INIT_COPY(obj, orig) \
- ((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1))
-#define OBJ_INIT_COPY(obj, orig) RB_OBJ_INIT_COPY(obj, orig)
-
-/* eval.c */
-int rb_sourceline(void);
-const char *rb_sourcefile(void);
-VALUE rb_check_funcall(VALUE, ID, int, const VALUE*);
-VALUE rb_check_funcall_kw(VALUE, ID, int, const VALUE*, int);
-
-NORETURN(MJIT_STATIC void rb_error_arity(int, int, int));
-static inline int
-rb_check_arity(int argc, int min, int max)
-{
- if ((argc < min) || (max != UNLIMITED_ARGUMENTS && argc > max))
- rb_error_arity(argc, min, max);
- return argc;
-}
-#define rb_check_arity rb_check_arity /* for ifdef */
-
-#if defined(NFDBITS) && defined(HAVE_RB_FD_INIT)
-typedef struct {
- int maxfd;
- fd_set *fdset;
-} rb_fdset_t;
-
-void rb_fd_init(rb_fdset_t *);
-void rb_fd_term(rb_fdset_t *);
-void rb_fd_zero(rb_fdset_t *);
-void rb_fd_set(int, rb_fdset_t *);
-void rb_fd_clr(int, rb_fdset_t *);
-int rb_fd_isset(int, const rb_fdset_t *);
-void rb_fd_copy(rb_fdset_t *, const fd_set *, int);
-void rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src);
-
-struct timeval;
-int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *);
-
-#define rb_fd_ptr(f) ((f)->fdset)
-#define rb_fd_max(f) ((f)->maxfd)
-
-#elif defined(_WIN32)
-
-typedef struct {
- int capa;
- fd_set *fdset;
-} rb_fdset_t;
-
-void rb_fd_init(rb_fdset_t *);
-void rb_fd_term(rb_fdset_t *);
-#define rb_fd_zero(f) ((f)->fdset->fd_count = 0)
-void rb_fd_set(int, rb_fdset_t *);
-#define rb_fd_clr(n, f) rb_w32_fdclr((n), (f)->fdset)
-#define rb_fd_isset(n, f) rb_w32_fdisset((n), (f)->fdset)
-#define rb_fd_copy(d, s, n) rb_w32_fd_copy((d), (s), (n))
-void rb_w32_fd_copy(rb_fdset_t *, const fd_set *, int);
-#define rb_fd_dup(d, s) rb_w32_fd_dup((d), (s))
-void rb_w32_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src);
-static inline int
-rb_fd_select(int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
-{
- return rb_w32_select(n,
- rfds ? rfds->fdset : NULL,
- wfds ? wfds->fdset : NULL,
- efds ? efds->fdset : NULL,
- timeout);
-}
-#define rb_fd_resize(n, f) ((void)(f))
-
-#define rb_fd_ptr(f) ((f)->fdset)
-#define rb_fd_max(f) ((f)->fdset->fd_count)
-
-#else
-
-typedef fd_set rb_fdset_t;
-#define rb_fd_zero(f) FD_ZERO(f)
-#define rb_fd_set(n, f) FD_SET((n), (f))
-#define rb_fd_clr(n, f) FD_CLR((n), (f))
-#define rb_fd_isset(n, f) FD_ISSET((n), (f))
-#define rb_fd_copy(d, s, n) (*(d) = *(s))
-#define rb_fd_dup(d, s) (*(d) = *(s))
-#define rb_fd_resize(n, f) ((void)(f))
-#define rb_fd_ptr(f) (f)
-#define rb_fd_init(f) FD_ZERO(f)
-#define rb_fd_init_copy(d, s) (*(d) = *(s))
-#define rb_fd_term(f) ((void)(f))
-#define rb_fd_max(f) FD_SETSIZE
-#define rb_fd_select(n, rfds, wfds, efds, timeout) select((n), (rfds), (wfds), (efds), (timeout))
-
-#endif
-
-NORETURN(void rb_exc_raise(VALUE));
-NORETURN(void rb_exc_fatal(VALUE));
-NORETURN(VALUE rb_f_exit(int, const VALUE*));
-NORETURN(VALUE rb_f_abort(int, const VALUE*));
-void rb_remove_method(VALUE, const char*);
-void rb_remove_method_id(VALUE, ID);
-#define HAVE_RB_DEFINE_ALLOC_FUNC 1
-typedef VALUE (*rb_alloc_func_t)(VALUE);
-void rb_define_alloc_func(VALUE, rb_alloc_func_t);
-void rb_undef_alloc_func(VALUE);
-rb_alloc_func_t rb_get_alloc_func(VALUE);
-void rb_clear_constant_cache(void);
-void rb_clear_method_cache_by_class(VALUE);
-void rb_alias(VALUE, ID, ID);
-void rb_attr(VALUE,ID,int,int,int);
-int rb_method_boundp(VALUE, ID, int);
-int rb_method_basic_definition_p(VALUE, ID);
-VALUE rb_eval_cmd(VALUE, VALUE, int);
-VALUE rb_eval_cmd_kw(VALUE, VALUE, int);
-int rb_obj_respond_to(VALUE, ID, int);
-int rb_respond_to(VALUE, ID);
-NORETURN(VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker));
-#if !defined(RUBY_EXPORT) && defined(_WIN32)
-RUBY_EXTERN VALUE (*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE marker);
-#define rb_f_notimplement (*rb_f_notimplement_)
-#endif
-NORETURN(void rb_interrupt(void));
-VALUE rb_apply(VALUE, ID, VALUE);
-void rb_backtrace(void);
-ID rb_frame_this_func(void);
-VALUE rb_obj_instance_eval(int, const VALUE*, VALUE);
-VALUE rb_obj_instance_exec(int, const VALUE*, VALUE);
-VALUE rb_mod_module_eval(int, const VALUE*, VALUE);
-VALUE rb_mod_module_exec(int, const VALUE*, VALUE);
-void rb_load(VALUE, int);
-void rb_load_protect(VALUE, int, int*);
-NORETURN(void rb_jump_tag(int));
-int rb_provided(const char*);
-int rb_feature_provided(const char *, const char **);
-void rb_provide(const char*);
-VALUE rb_f_require(VALUE, VALUE);
-VALUE rb_require_safe(VALUE, int); /* Remove in 3.0 */
-VALUE rb_require_string(VALUE);
-void rb_obj_call_init(VALUE, int, const VALUE*);
-void rb_obj_call_init_kw(VALUE, int, const VALUE*, int);
-VALUE rb_class_new_instance(int, const VALUE*, VALUE);
-VALUE rb_class_new_instance_kw(int, const VALUE*, VALUE, int);
-VALUE rb_block_proc(void);
-VALUE rb_block_lambda(void);
-VALUE rb_proc_new(rb_block_call_func_t, VALUE);
-VALUE rb_obj_is_proc(VALUE);
-VALUE rb_proc_call(VALUE, VALUE);
-VALUE rb_proc_call_kw(VALUE, VALUE, int);
-VALUE rb_proc_call_with_block(VALUE, int argc, const VALUE *argv, VALUE);
-VALUE rb_proc_call_with_block_kw(VALUE, int argc, const VALUE *argv, VALUE, int);
-int rb_proc_arity(VALUE);
-VALUE rb_proc_lambda_p(VALUE);
-VALUE rb_binding_new(void);
-VALUE rb_obj_method(VALUE, VALUE);
-VALUE rb_obj_is_method(VALUE);
-VALUE rb_method_call(int, const VALUE*, VALUE);
-VALUE rb_method_call_kw(int, const VALUE*, VALUE, int);
-VALUE rb_method_call_with_block(int, const VALUE *, VALUE, VALUE);
-VALUE rb_method_call_with_block_kw(int, const VALUE *, VALUE, VALUE, int);
-int rb_mod_method_arity(VALUE, ID);
-int rb_obj_method_arity(VALUE, ID);
-VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*);
-void rb_set_end_proc(void (*)(VALUE), VALUE);
-void rb_thread_schedule(void);
-void rb_thread_wait_fd(int);
-int rb_thread_fd_writable(int);
-void rb_thread_fd_close(int);
-int rb_thread_alone(void);
-void rb_thread_sleep(int);
-void rb_thread_sleep_forever(void);
-void rb_thread_sleep_deadly(void);
-VALUE rb_thread_stop(void);
-VALUE rb_thread_wakeup(VALUE);
-VALUE rb_thread_wakeup_alive(VALUE);
-VALUE rb_thread_run(VALUE);
-VALUE rb_thread_kill(VALUE);
-VALUE rb_thread_create(VALUE (*)(void *), void*);
-int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *);
-void rb_thread_wait_for(struct timeval);
-VALUE rb_thread_current(void);
-VALUE rb_thread_main(void);
-VALUE rb_thread_local_aref(VALUE, ID);
-VALUE rb_thread_local_aset(VALUE, ID, VALUE);
-void rb_thread_atfork(void);
-void rb_thread_atfork_before_exec(void);
-VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE);
-VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE);
-VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE);
-VALUE rb_exec_recursive_paired_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE);
-/* dir.c */
-VALUE rb_dir_getwd(void);
-/* file.c */
-VALUE rb_file_s_expand_path(int, const VALUE *);
-VALUE rb_file_expand_path(VALUE, VALUE);
-VALUE rb_file_s_absolute_path(int, const VALUE *);
-VALUE rb_file_absolute_path(VALUE, VALUE);
-VALUE rb_file_dirname(VALUE fname);
-int rb_find_file_ext_safe(VALUE*, const char* const*, int); /* Remove in 3.0 */
-VALUE rb_find_file_safe(VALUE, int); /* Remove in 3.0 */
-int rb_find_file_ext(VALUE*, const char* const*);
-VALUE rb_find_file(VALUE);
-VALUE rb_file_directory_p(VALUE,VALUE);
-VALUE rb_str_encode_ospath(VALUE);
-int rb_is_absolute_path(const char *);
-/* gc.c */
-COLDFUNC NORETURN(void rb_memerror(void));
-PUREFUNC(int rb_during_gc(void));
-void rb_gc_mark_locations(const VALUE*, const VALUE*);
-void rb_mark_tbl(struct st_table*);
-void rb_mark_tbl_no_pin(struct st_table*);
-void rb_mark_set(struct st_table*);
-void rb_mark_hash(struct st_table*);
-void rb_gc_update_tbl_refs(st_table *ptr);
-void rb_gc_mark_maybe(VALUE);
-void rb_gc_mark(VALUE);
-void rb_gc_mark_movable(VALUE);
-VALUE rb_gc_location(VALUE);
-void rb_gc_force_recycle(VALUE);
-void rb_gc(void);
-void rb_gc_copy_finalizer(VALUE,VALUE);
-VALUE rb_gc_enable(void);
-VALUE rb_gc_disable(void);
-VALUE rb_gc_start(void);
-VALUE rb_define_finalizer(VALUE, VALUE);
-VALUE rb_undefine_finalizer(VALUE);
-size_t rb_gc_count(void);
-size_t rb_gc_stat(VALUE);
-VALUE rb_gc_latest_gc_info(VALUE);
-void rb_gc_adjust_memory_usage(ssize_t);
-/* hash.c */
-void rb_st_foreach_safe(struct st_table *, int (*)(st_data_t, st_data_t, st_data_t), st_data_t);
-#define st_foreach_safe rb_st_foreach_safe
-VALUE rb_check_hash_type(VALUE);
-void rb_hash_foreach(VALUE, int (*)(VALUE, VALUE, VALUE), VALUE);
-VALUE rb_hash(VALUE);
-VALUE rb_hash_new(void);
-VALUE rb_hash_dup(VALUE);
-VALUE rb_hash_freeze(VALUE);
-VALUE rb_hash_aref(VALUE, VALUE);
-VALUE rb_hash_lookup(VALUE, VALUE);
-VALUE rb_hash_lookup2(VALUE, VALUE, VALUE);
-VALUE rb_hash_fetch(VALUE, VALUE);
-VALUE rb_hash_aset(VALUE, VALUE, VALUE);
-VALUE rb_hash_clear(VALUE);
-VALUE rb_hash_delete_if(VALUE);
-VALUE rb_hash_delete(VALUE,VALUE);
-VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone);
-void rb_hash_bulk_insert(long, const VALUE *, VALUE);
-typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value);
-VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func);
-struct st_table *rb_hash_tbl(VALUE, const char *file, int line);
-int rb_path_check(const char*);
-int rb_env_path_tainted(void);
-VALUE rb_env_clear(void);
-VALUE rb_hash_size(VALUE);
-void rb_hash_free(VALUE);
-/* io.c */
-#define rb_defout rb_stdout
-RUBY_EXTERN VALUE rb_fs;
-RUBY_EXTERN VALUE rb_output_fs;
-RUBY_EXTERN VALUE rb_rs;
-RUBY_EXTERN VALUE rb_default_rs;
-RUBY_EXTERN VALUE rb_output_rs;
-VALUE rb_io_write(VALUE, VALUE);
-VALUE rb_io_gets(VALUE);
-VALUE rb_io_getbyte(VALUE);
-VALUE rb_io_ungetc(VALUE, VALUE);
-VALUE rb_io_ungetbyte(VALUE, VALUE);
-VALUE rb_io_close(VALUE);
-VALUE rb_io_flush(VALUE);
-VALUE rb_io_eof(VALUE);
-VALUE rb_io_binmode(VALUE);
-VALUE rb_io_ascii8bit_binmode(VALUE);
-VALUE rb_io_addstr(VALUE, VALUE);
-VALUE rb_io_printf(int, const VALUE*, VALUE);
-VALUE rb_io_print(int, const VALUE*, VALUE);
-VALUE rb_io_puts(int, const VALUE*, VALUE);
-VALUE rb_io_fdopen(int, int, const char*);
-VALUE rb_io_get_io(VALUE);
-VALUE rb_file_open(const char*, const char*);
-VALUE rb_file_open_str(VALUE, const char*);
-VALUE rb_gets(void);
-void rb_write_error(const char*);
-void rb_write_error2(const char*, long);
-void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds);
-int rb_pipe(int *pipes);
-int rb_reserved_fd_p(int fd);
-int rb_cloexec_open(const char *pathname, int flags, mode_t mode);
-int rb_cloexec_dup(int oldfd);
-int rb_cloexec_dup2(int oldfd, int newfd);
-int rb_cloexec_pipe(int fildes[2]);
-int rb_cloexec_fcntl_dupfd(int fd, int minfd);
-#define RB_RESERVED_FD_P(fd) rb_reserved_fd_p(fd)
-void rb_update_max_fd(int fd);
-void rb_fd_fix_cloexec(int fd);
-/* marshal.c */
-VALUE rb_marshal_dump(VALUE, VALUE);
-VALUE rb_marshal_load(VALUE);
-void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE));
-/* numeric.c */
-NORETURN(void rb_num_zerodiv(void));
-#define RB_NUM_COERCE_FUNCS_NEED_OPID 1
-VALUE rb_num_coerce_bin(VALUE, VALUE, ID);
-VALUE rb_num_coerce_cmp(VALUE, VALUE, ID);
-VALUE rb_num_coerce_relop(VALUE, VALUE, ID);
-VALUE rb_num_coerce_bit(VALUE, VALUE, ID);
-VALUE rb_num2fix(VALUE);
-VALUE rb_fix2str(VALUE, int);
-CONSTFUNC(VALUE rb_dbl_cmp(double, double));
-/* object.c */
-int rb_eql(VALUE, VALUE);
-VALUE rb_any_to_s(VALUE);
-VALUE rb_inspect(VALUE);
-VALUE rb_obj_is_instance_of(VALUE, VALUE);
-VALUE rb_obj_is_kind_of(VALUE, VALUE);
-VALUE rb_obj_alloc(VALUE);
-VALUE rb_obj_clone(VALUE);
-VALUE rb_obj_dup(VALUE);
-VALUE rb_obj_init_copy(VALUE,VALUE);
-VALUE rb_obj_taint(VALUE);
-PUREFUNC(VALUE rb_obj_tainted(VALUE));
-VALUE rb_obj_untaint(VALUE);
-VALUE rb_obj_untrust(VALUE);
-PUREFUNC(VALUE rb_obj_untrusted(VALUE));
-VALUE rb_obj_trust(VALUE);
-VALUE rb_obj_freeze(VALUE);
-PUREFUNC(VALUE rb_obj_frozen_p(VALUE));
-VALUE rb_obj_id(VALUE);
-VALUE rb_memory_id(VALUE);
-VALUE rb_obj_class(VALUE);
-PUREFUNC(VALUE rb_class_real(VALUE));
-PUREFUNC(VALUE rb_class_inherited_p(VALUE, VALUE));
-VALUE rb_class_superclass(VALUE);
-VALUE rb_class_get_superclass(VALUE);
-VALUE rb_convert_type(VALUE,int,const char*,const char*);
-VALUE rb_check_convert_type(VALUE,int,const char*,const char*);
-VALUE rb_check_to_integer(VALUE, const char *);
-VALUE rb_check_to_float(VALUE);
-VALUE rb_to_int(VALUE);
-VALUE rb_check_to_int(VALUE);
-VALUE rb_Integer(VALUE);
-VALUE rb_to_float(VALUE);
-VALUE rb_Float(VALUE);
-VALUE rb_String(VALUE);
-VALUE rb_Array(VALUE);
-VALUE rb_Hash(VALUE);
-double rb_cstr_to_dbl(const char*, int);
-double rb_str_to_dbl(VALUE, int);
-/* parse.y */
-ID rb_id_attrset(ID);
-CONSTFUNC(int rb_is_const_id(ID));
-CONSTFUNC(int rb_is_global_id(ID));
-CONSTFUNC(int rb_is_instance_id(ID));
-CONSTFUNC(int rb_is_attrset_id(ID));
-CONSTFUNC(int rb_is_class_id(ID));
-CONSTFUNC(int rb_is_local_id(ID));
-CONSTFUNC(int rb_is_junk_id(ID));
-int rb_symname_p(const char*);
-int rb_sym_interned_p(VALUE);
-VALUE rb_backref_get(void);
-void rb_backref_set(VALUE);
-VALUE rb_lastline_get(void);
-void rb_lastline_set(VALUE);
-/* process.c */
-void rb_last_status_set(int status, rb_pid_t pid);
-VALUE rb_last_status_get(void);
-int rb_proc_exec(const char*);
-NORETURN(VALUE rb_f_exec(int, const VALUE*));
-rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags);
-void rb_syswait(rb_pid_t pid);
-rb_pid_t rb_spawn(int, const VALUE*);
-rb_pid_t rb_spawn_err(int, const VALUE*, char*, size_t);
-VALUE rb_proc_times(VALUE);
-VALUE rb_detach_process(rb_pid_t pid);
-/* range.c */
-VALUE rb_range_new(VALUE, VALUE, int);
-VALUE rb_range_beg_len(VALUE, long*, long*, long, int);
-int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp);
-/* random.c */
-unsigned int rb_genrand_int32(void);
-double rb_genrand_real(void);
-void rb_reset_random_seed(void);
-VALUE rb_random_bytes(VALUE rnd, long n);
-VALUE rb_random_int(VALUE rnd, VALUE max);
-unsigned int rb_random_int32(VALUE rnd);
-double rb_random_real(VALUE rnd);
-unsigned long rb_random_ulong_limited(VALUE rnd, unsigned long limit);
-unsigned long rb_genrand_ulong_limited(unsigned long i);
-/* re.c */
-#define rb_memcmp memcmp
-int rb_memcicmp(const void*,const void*,long);
-void rb_match_busy(VALUE);
-VALUE rb_reg_nth_defined(int, VALUE);
-VALUE rb_reg_nth_match(int, VALUE);
-int rb_reg_backref_number(VALUE match, VALUE backref);
-VALUE rb_reg_last_match(VALUE);
-VALUE rb_reg_match_pre(VALUE);
-VALUE rb_reg_match_post(VALUE);
-VALUE rb_reg_match_last(VALUE);
-#define HAVE_RB_REG_NEW_STR 1
-VALUE rb_reg_new_str(VALUE, int);
-VALUE rb_reg_new(const char *, long, int);
-VALUE rb_reg_alloc(void);
-VALUE rb_reg_init_str(VALUE re, VALUE s, int options);
-VALUE rb_reg_match(VALUE, VALUE);
-VALUE rb_reg_match2(VALUE);
-int rb_reg_options(VALUE);
-/* ruby.c */
-#define rb_argv rb_get_argv()
-RUBY_EXTERN VALUE rb_argv0;
-VALUE rb_get_argv(void);
-void *rb_load_file(const char*);
-void *rb_load_file_str(VALUE);
-/* signal.c */
-VALUE rb_f_kill(int, const VALUE*);
-#ifdef POSIX_SIGNAL
-#define posix_signal ruby_posix_signal
-RETSIGTYPE (*posix_signal(int, RETSIGTYPE (*)(int)))(int);
-#endif
-const char *ruby_signal_name(int);
-void ruby_default_signal(int);
-/* sprintf.c */
-VALUE rb_f_sprintf(int, const VALUE*);
-PRINTF_ARGS(VALUE rb_sprintf(const char*, ...), 1, 2);
-VALUE rb_vsprintf(const char*, va_list);
-PRINTF_ARGS(VALUE rb_str_catf(VALUE, const char*, ...), 2, 3);
-VALUE rb_str_vcatf(VALUE, const char*, va_list);
-VALUE rb_str_format(int, const VALUE *, VALUE);
-/* string.c */
-VALUE rb_str_new(const char*, long);
-VALUE rb_str_new_cstr(const char*);
-VALUE rb_str_new_shared(VALUE);
-VALUE rb_str_new_frozen(VALUE);
-VALUE rb_str_new_with_class(VALUE, const char*, long);
-VALUE rb_tainted_str_new_cstr(const char*);
-VALUE rb_tainted_str_new(const char*, long);
-VALUE rb_external_str_new(const char*, long);
-VALUE rb_external_str_new_cstr(const char*);
-VALUE rb_locale_str_new(const char*, long);
-VALUE rb_locale_str_new_cstr(const char*);
-VALUE rb_filesystem_str_new(const char*, long);
-VALUE rb_filesystem_str_new_cstr(const char*);
-VALUE rb_str_buf_new(long);
-VALUE rb_str_buf_new_cstr(const char*);
-VALUE rb_str_buf_new2(const char*);
-VALUE rb_str_tmp_new(long);
-VALUE rb_usascii_str_new(const char*, long);
-VALUE rb_usascii_str_new_cstr(const char*);
-VALUE rb_utf8_str_new(const char*, long);
-VALUE rb_utf8_str_new_cstr(const char*);
-VALUE rb_str_new_static(const char *, long);
-VALUE rb_usascii_str_new_static(const char *, long);
-VALUE rb_utf8_str_new_static(const char *, long);
-void rb_str_free(VALUE);
-void rb_str_shared_replace(VALUE, VALUE);
-VALUE rb_str_buf_append(VALUE, VALUE);
-VALUE rb_str_buf_cat(VALUE, const char*, long);
-VALUE rb_str_buf_cat2(VALUE, const char*);
-VALUE rb_str_buf_cat_ascii(VALUE, const char*);
-VALUE rb_obj_as_string(VALUE);
-VALUE rb_check_string_type(VALUE);
-void rb_must_asciicompat(VALUE);
-VALUE rb_str_dup(VALUE);
-VALUE rb_str_resurrect(VALUE str);
-VALUE rb_str_locktmp(VALUE);
-VALUE rb_str_unlocktmp(VALUE);
-VALUE rb_str_dup_frozen(VALUE);
-#define rb_str_dup_frozen rb_str_new_frozen
-VALUE rb_str_plus(VALUE, VALUE);
-VALUE rb_str_times(VALUE, VALUE);
-long rb_str_sublen(VALUE, long);
-VALUE rb_str_substr(VALUE, long, long);
-VALUE rb_str_subseq(VALUE, long, long);
-char *rb_str_subpos(VALUE, long, long*);
-void rb_str_modify(VALUE);
-void rb_str_modify_expand(VALUE, long);
-VALUE rb_str_freeze(VALUE);
-void rb_str_set_len(VALUE, long);
-VALUE rb_str_resize(VALUE, long);
-VALUE rb_str_cat(VALUE, const char*, long);
-VALUE rb_str_cat_cstr(VALUE, const char*);
-VALUE rb_str_cat2(VALUE, const char*);
-VALUE rb_str_append(VALUE, VALUE);
-VALUE rb_str_concat(VALUE, VALUE);
-st_index_t rb_memhash(const void *ptr, long len);
-st_index_t rb_hash_start(st_index_t);
-st_index_t rb_hash_uint32(st_index_t, uint32_t);
-st_index_t rb_hash_uint(st_index_t, st_index_t);
-st_index_t rb_hash_end(st_index_t);
-#define rb_hash_uint32(h, i) st_hash_uint32((h), (i))
-#define rb_hash_uint(h, i) st_hash_uint((h), (i))
-#define rb_hash_end(h) st_hash_end(h)
-st_index_t rb_str_hash(VALUE);
-int rb_str_hash_cmp(VALUE,VALUE);
-int rb_str_comparable(VALUE, VALUE);
-int rb_str_cmp(VALUE, VALUE);
-VALUE rb_str_equal(VALUE str1, VALUE str2);
-VALUE rb_str_drop_bytes(VALUE, long);
-void rb_str_update(VALUE, long, long, VALUE);
-VALUE rb_str_replace(VALUE, VALUE);
-VALUE rb_str_inspect(VALUE);
-VALUE rb_str_dump(VALUE);
-VALUE rb_str_split(VALUE, const char*);
-rb_gvar_setter_t rb_str_setter;
-VALUE rb_str_intern(VALUE);
-VALUE rb_sym_to_s(VALUE);
-long rb_str_strlen(VALUE);
-VALUE rb_str_length(VALUE);
-long rb_str_offset(VALUE, long);
-PUREFUNC(size_t rb_str_capacity(VALUE));
-VALUE rb_str_ellipsize(VALUE, long);
-VALUE rb_str_scrub(VALUE, VALUE);
-/* symbol.c */
-VALUE rb_sym_all_symbols(void);
-
-#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P
-#define rb_str_new(str, len) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \
- rb_str_new_static((str), (len)) : \
- rb_str_new((str), (len)) \
-)
-#define rb_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str)) ? \
- rb_str_new_static((str), (long)strlen(str)) : \
- rb_str_new_cstr(str) \
-)
-#define rb_usascii_str_new(str, len) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \
- rb_usascii_str_new_static((str), (len)) : \
- rb_usascii_str_new((str), (len)) \
-)
-#define rb_utf8_str_new(str, len) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \
- rb_utf8_str_new_static((str), (len)) : \
- rb_utf8_str_new((str), (len)) \
-)
-#define rb_tainted_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str)) ? \
- rb_tainted_str_new((str), (long)strlen(str)) : \
- rb_tainted_str_new_cstr(str) \
-)
-#define rb_usascii_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str)) ? \
- rb_usascii_str_new_static((str), (long)strlen(str)) : \
- rb_usascii_str_new_cstr(str) \
-)
-#define rb_utf8_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str)) ? \
- rb_utf8_str_new_static((str), (long)strlen(str)) : \
- rb_utf8_str_new_cstr(str) \
-)
-#define rb_external_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str)) ? \
- rb_external_str_new((str), (long)strlen(str)) : \
- rb_external_str_new_cstr(str) \
-)
-#define rb_locale_str_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str)) ? \
- rb_locale_str_new((str), (long)strlen(str)) : \
- rb_locale_str_new_cstr(str) \
-)
-#define rb_str_buf_new_cstr(str) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str)) ? \
- rb_str_buf_cat(rb_str_buf_new((long)strlen(str)), \
- (str), (long)strlen(str)) : \
- rb_str_buf_new_cstr(str) \
-)
-#define rb_str_cat_cstr(str, ptr) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(ptr)) ? \
- rb_str_cat((str), (ptr), (long)strlen(ptr)) : \
- rb_str_cat_cstr((str), (ptr)) \
-)
-#define rb_exc_new_cstr(klass, ptr) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(ptr)) ? \
- rb_exc_new((klass), (ptr), (long)strlen(ptr)) : \
- rb_exc_new_cstr((klass), (ptr)) \
-)
-#endif
-#define rb_str_new2 rb_str_new_cstr
-#define rb_str_new3 rb_str_new_shared
-#define rb_str_new4 rb_str_new_frozen
-#define rb_str_new5 rb_str_new_with_class
-#define rb_tainted_str_new2 rb_tainted_str_new_cstr
-#define rb_str_buf_new2 rb_str_buf_new_cstr
-#define rb_usascii_str_new2 rb_usascii_str_new_cstr
-#define rb_str_buf_cat rb_str_cat
-#define rb_str_buf_cat2 rb_str_cat_cstr
-#define rb_str_cat2 rb_str_cat_cstr
-#define rb_strlen_lit(str) (sizeof(str "") - 1)
-#define rb_str_new_lit(str) rb_str_new_static((str), rb_strlen_lit(str))
-#define rb_usascii_str_new_lit(str) rb_usascii_str_new_static((str), rb_strlen_lit(str))
-#define rb_utf8_str_new_lit(str) rb_utf8_str_new_static((str), rb_strlen_lit(str))
-#define rb_enc_str_new_lit(str, enc) rb_enc_str_new_static((str), rb_strlen_lit(str), (enc))
-#define rb_str_new_literal(str) rb_str_new_lit(str)
-#define rb_usascii_str_new_literal(str) rb_usascii_str_new_lit(str)
-#define rb_utf8_str_new_literal(str) rb_utf8_str_new_lit(str)
-#define rb_enc_str_new_literal(str, enc) rb_enc_str_new_lit(str, enc)
-
-/* struct.c */
-VALUE rb_struct_new(VALUE, ...);
-VALUE rb_struct_define(const char*, ...);
-VALUE rb_struct_define_under(VALUE, const char*, ...);
-VALUE rb_struct_alloc(VALUE, VALUE);
-VALUE rb_struct_initialize(VALUE, VALUE);
-VALUE rb_struct_aref(VALUE, VALUE);
-VALUE rb_struct_aset(VALUE, VALUE, VALUE);
-VALUE rb_struct_getmember(VALUE, ID);
-VALUE rb_struct_s_members(VALUE);
-VALUE rb_struct_members(VALUE);
-VALUE rb_struct_size(VALUE s);
-VALUE rb_struct_alloc_noinit(VALUE);
-VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t, ...);
-VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...);
-
-/* thread.c */
-typedef void rb_unblock_function_t(void *);
-typedef VALUE rb_blocking_function_t(void *);
-void rb_thread_check_ints(void);
-int rb_thread_interrupted(VALUE thval);
-
-#define RUBY_UBF_IO ((rb_unblock_function_t *)-1)
-#define RUBY_UBF_PROCESS ((rb_unblock_function_t *)-1)
-VALUE rb_mutex_new(void);
-VALUE rb_mutex_locked_p(VALUE mutex);
-VALUE rb_mutex_trylock(VALUE mutex);
-VALUE rb_mutex_lock(VALUE mutex);
-VALUE rb_mutex_unlock(VALUE mutex);
-VALUE rb_mutex_sleep(VALUE self, VALUE timeout);
-VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg);
-/* time.c */
-struct timespec;
-void rb_timespec_now(struct timespec *);
-VALUE rb_time_new(time_t, long);
-VALUE rb_time_nano_new(time_t, long);
-VALUE rb_time_timespec_new(const struct timespec *, int);
-VALUE rb_time_num_new(VALUE, VALUE);
-struct timeval rb_time_interval(VALUE num);
-struct timeval rb_time_timeval(VALUE time);
-struct timespec rb_time_timespec(VALUE time);
-struct timespec rb_time_timespec_interval(VALUE num);
-VALUE rb_time_utc_offset(VALUE time);
-/* variable.c */
-VALUE rb_mod_name(VALUE);
-VALUE rb_class_path(VALUE);
-VALUE rb_class_path_cached(VALUE);
-void rb_set_class_path(VALUE, VALUE, const char*);
-void rb_set_class_path_string(VALUE, VALUE, VALUE);
-VALUE rb_path_to_class(VALUE);
-VALUE rb_path2class(const char*);
-VALUE rb_class_name(VALUE);
-VALUE rb_autoload_load(VALUE, ID);
-VALUE rb_autoload_p(VALUE, ID);
-VALUE rb_f_trace_var(int, const VALUE*);
-VALUE rb_f_untrace_var(int, const VALUE*);
-VALUE rb_f_global_variables(void);
-void rb_alias_variable(ID, ID);
-void rb_copy_generic_ivar(VALUE,VALUE);
-void rb_free_generic_ivar(VALUE);
-VALUE rb_ivar_get(VALUE, ID);
-VALUE rb_ivar_set(VALUE, ID, VALUE);
-VALUE rb_ivar_defined(VALUE, ID);
-void rb_ivar_foreach(VALUE, int (*)(ID, VALUE, st_data_t), st_data_t);
-st_index_t rb_ivar_count(VALUE);
-VALUE rb_attr_get(VALUE, ID);
-VALUE rb_obj_instance_variables(VALUE);
-VALUE rb_obj_remove_instance_variable(VALUE, VALUE);
-void *rb_mod_const_at(VALUE, void*);
-void *rb_mod_const_of(VALUE, void*);
-VALUE rb_const_list(void*);
-VALUE rb_mod_constants(int, const VALUE *, VALUE);
-VALUE rb_mod_remove_const(VALUE, VALUE);
-int rb_const_defined(VALUE, ID);
-int rb_const_defined_at(VALUE, ID);
-int rb_const_defined_from(VALUE, ID);
-VALUE rb_const_get(VALUE, ID);
-VALUE rb_const_get_at(VALUE, ID);
-VALUE rb_const_get_from(VALUE, ID);
-void rb_const_set(VALUE, ID, VALUE);
-VALUE rb_const_remove(VALUE, ID);
-#if 0 /* EXPERIMENTAL: remove if no problem */
-NORETURN(VALUE rb_mod_const_missing(VALUE,VALUE));
-#endif
-VALUE rb_cvar_defined(VALUE, ID);
-void rb_cvar_set(VALUE, ID, VALUE);
-VALUE rb_cvar_get(VALUE, ID);
-void rb_cv_set(VALUE, const char*, VALUE);
-VALUE rb_cv_get(VALUE, const char*);
-void rb_define_class_variable(VALUE, const char*, VALUE);
-VALUE rb_mod_class_variables(int, const VALUE*, VALUE);
-VALUE rb_mod_remove_cvar(VALUE, VALUE);
-
-ID rb_frame_callee(void);
-int rb_frame_method_id_and_class(ID *idp, VALUE *klassp);
-VALUE rb_str_succ(VALUE);
-VALUE rb_time_succ(VALUE);
-VALUE rb_make_backtrace(void);
-VALUE rb_make_exception(int, const VALUE*);
-
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-extern "C++" {
-#endif
-
-#if defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P)
-# define rb_f_notimplement_p(f) __builtin_types_compatible_p(__typeof__(f),__typeof__(rb_f_notimplement))
-#else
-# define rb_f_notimplement_p(f) 0
-#endif
-
-#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) && !defined(_WIN32) && !defined(__CYGWIN__)
-#if defined(__has_attribute) && __has_attribute(transparent_union) && __has_attribute(unused) && __has_attribute(weakref) && __has_attribute(nonnull)
-#define RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,funcargs) \
- __attribute__((__unused__,__weakref__(#def),__nonnull__ nonnull))static void defname(RB_UNWRAP_MACRO decl,VALUE(*func)funcargs,int arity);
-#endif
-#endif
-
-#if defined(RB_METHOD_DEFINITION_DECL_C) || defined(__cplusplus)
-#ifndef RB_METHOD_DEFINITION_DECL_C
-#define RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,funcargs) \
- static inline void defname(RB_UNWRAP_MACRO decl,VALUE(*func)funcargs,int arity) \
- { \
- def(RB_UNWRAP_MACRO vars,(VALUE(*)(ANYARGS))(func),arity); \
- }
-#endif
-
-#define RB_UNWRAP_MACRO(...) __VA_ARGS__
-
-#ifdef __cplusplus
-#define RB_METHOD_DEFINITION_DECL_CXX_BEGIN(def) template <int Arity> struct def##_tmpl {};
-#define RB_METHOD_DEFINITION_DECL_CXX(def,defname,decl,vars,funcargs,arity) \
- template <> struct def##_tmpl<arity> { \
- static void define(RB_UNWRAP_MACRO decl, VALUE (*func)funcargs) {::defname(RB_UNWRAP_MACRO vars, func, arity);} \
- static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(...)) {::defname(RB_UNWRAP_MACRO vars, reinterpret_cast<VALUE(*)funcargs>(func), arity);} \
- };
-#else
-#define RB_METHOD_DEFINITION_DECL_CXX_BEGIN(def) /* nothing */
-#define RB_METHOD_DEFINITION_DECL_CXX(def,defname,decl,vars,funcargs,arity) /* nothing */
-#endif
-#define RB_METHOD_DEFINITION_DECL_1(def,nonnull,defname,arity,decl,vars,funcargs) \
- RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,funcargs) \
- RB_METHOD_DEFINITION_DECL_CXX(def,defname,decl,vars,funcargs,arity)
-
-#define RB_METHOD_DEFINITION_DECL(def,nonnull,decl,vars) \
-RB_METHOD_DEFINITION_DECL_CXX_BEGIN(def) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##0 ,0 ,decl,vars,(VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##1 ,1 ,decl,vars,(VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##2 ,2 ,decl,vars,(VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##3 ,3 ,decl,vars,(VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##4 ,4 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##5 ,5 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##6 ,6 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##7 ,7 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##8 ,8 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##9 ,9 ,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##10,10,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##11,11,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##12,12,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##13,13,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##14,14,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##15,15,decl,vars,(VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_M3(def,nonnull,def##m3,decl,vars) \
-RB_METHOD_DEFINITION_DECL_1(def,nonnull,def##m2,-2,decl,vars,(VALUE,VALUE)) \
-RB_METHOD_DEFINITION_DECL_M1(def,nonnull,def##m1,decl,vars) /* END */
-#ifdef __cplusplus
-#define RB_METHOD_DEFINITION_DECL_M1(def,nonnull,defname,decl,vars) \
- RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(int,VALUE*,VALUE)) \
- RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(int,const VALUE*,VALUE)) \
- RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(int,const VALUE*,VALUE,VALUE)) \
- RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(...)) \
- template <> struct def##_tmpl<-1> { \
- static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(int,VALUE*,VALUE)) {::defname(RB_UNWRAP_MACRO vars, func, -1);} \
- static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(int,const VALUE*,VALUE)) {::defname(RB_UNWRAP_MACRO vars, func, -1);} \
- static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(int,const VALUE*,VALUE,VALUE)) {::defname(RB_UNWRAP_MACRO vars, func, -1);} \
- static void define(RB_UNWRAP_MACRO decl, VALUE (*func)(...)) {::defname(RB_UNWRAP_MACRO vars, func, -1);} \
- };
-#define RB_METHOD_DEFINITION_DECL_M3(def,nonnull,defname,decl,vars) /* nothing */
-#else
-#define RB_METHOD_DEFINITION_DECL_M1(def,nonnull,defname,decl,vars) \
- RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,(int,union{VALUE*x;const VALUE*y;}__attribute__((__transparent_union__)),VALUE))
-#define RB_METHOD_DEFINITION_DECL_M3(def,nonnull,defname,decl,vars) \
- RB_METHOD_DEFINITION_DECL_C(def,nonnull,defname,decl,vars,())
-#endif
-
-#endif
-
-#ifdef RB_METHOD_DEFINITION_DECL
-
-RB_METHOD_DEFINITION_DECL(rb_define_method_id, (3), (VALUE klass, ID name), (klass, name))
-#ifdef __cplusplus
-#define rb_define_method_id(m, n, f, a) rb_define_method_id_tmpl<a>::define(m, n, f)
-#else
-#define rb_define_method_id_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_method_id15,rb_define_method_idm3)
-#define rb_define_method_id_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_method_id14,rb_define_method_id_choose_prototype15(n))
-#define rb_define_method_id_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_method_id13,rb_define_method_id_choose_prototype14(n))
-#define rb_define_method_id_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_method_id12,rb_define_method_id_choose_prototype13(n))
-#define rb_define_method_id_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_method_id11,rb_define_method_id_choose_prototype12(n))
-#define rb_define_method_id_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_method_id10,rb_define_method_id_choose_prototype11(n))
-#define rb_define_method_id_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_method_id9, rb_define_method_id_choose_prototype10(n))
-#define rb_define_method_id_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_method_id8, rb_define_method_id_choose_prototype9(n))
-#define rb_define_method_id_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_method_id7, rb_define_method_id_choose_prototype8(n))
-#define rb_define_method_id_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_method_id6, rb_define_method_id_choose_prototype7(n))
-#define rb_define_method_id_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_method_id5, rb_define_method_id_choose_prototype6(n))
-#define rb_define_method_id_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_method_id4, rb_define_method_id_choose_prototype5(n))
-#define rb_define_method_id_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_method_id3, rb_define_method_id_choose_prototype4(n))
-#define rb_define_method_id_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_method_id2, rb_define_method_id_choose_prototype3(n))
-#define rb_define_method_id_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_method_id1, rb_define_method_id_choose_prototype2(n))
-#define rb_define_method_id_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_method_id0, rb_define_method_id_choose_prototype1(n))
-#define rb_define_method_id_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_method_idm1,rb_define_method_id_choose_prototype0(n))
-#define rb_define_method_id_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_method_idm2,rb_define_method_id_choose_prototypem1(n))
-#define rb_define_method_id_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_method_idm3,rb_define_method_id_choose_prototypem2(n))
-#define rb_define_method_id(klass, mid, func, arity) rb_define_method_id_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity));
-#endif
-
-RB_METHOD_DEFINITION_DECL(rb_define_protected_method, (2,3), (VALUE klass, const char *name), (klass, name))
-#ifdef __cplusplus
-#define rb_define_protected_method(m, n, f, a) rb_define_protected_method_tmpl<a>::define(m, n, f)
-#else
-#define rb_define_protected_method_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_protected_method15,rb_define_protected_methodm3)
-#define rb_define_protected_method_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_protected_method14,rb_define_protected_method_choose_prototype15(n))
-#define rb_define_protected_method_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_protected_method13,rb_define_protected_method_choose_prototype14(n))
-#define rb_define_protected_method_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_protected_method12,rb_define_protected_method_choose_prototype13(n))
-#define rb_define_protected_method_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_protected_method11,rb_define_protected_method_choose_prototype12(n))
-#define rb_define_protected_method_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_protected_method10,rb_define_protected_method_choose_prototype11(n))
-#define rb_define_protected_method_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_protected_method9, rb_define_protected_method_choose_prototype10(n))
-#define rb_define_protected_method_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_protected_method8, rb_define_protected_method_choose_prototype9(n))
-#define rb_define_protected_method_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_protected_method7, rb_define_protected_method_choose_prototype8(n))
-#define rb_define_protected_method_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_protected_method6, rb_define_protected_method_choose_prototype7(n))
-#define rb_define_protected_method_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_protected_method5, rb_define_protected_method_choose_prototype6(n))
-#define rb_define_protected_method_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_protected_method4, rb_define_protected_method_choose_prototype5(n))
-#define rb_define_protected_method_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_protected_method3, rb_define_protected_method_choose_prototype4(n))
-#define rb_define_protected_method_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_protected_method2, rb_define_protected_method_choose_prototype3(n))
-#define rb_define_protected_method_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_protected_method1, rb_define_protected_method_choose_prototype2(n))
-#define rb_define_protected_method_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_protected_method0, rb_define_protected_method_choose_prototype1(n))
-#define rb_define_protected_method_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_protected_methodm1,rb_define_protected_method_choose_prototype0(n))
-#define rb_define_protected_method_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_protected_methodm2,rb_define_protected_method_choose_prototypem1(n))
-#define rb_define_protected_method_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_protected_methodm3,rb_define_protected_method_choose_prototypem2(n))
-#define rb_define_protected_method(klass, mid, func, arity) rb_define_protected_method_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity));
-#endif
-
-RB_METHOD_DEFINITION_DECL(rb_define_private_method, (2,3), (VALUE klass, const char *name), (klass, name))
-#ifdef __cplusplus
-#define rb_define_private_method(m, n, f, a) rb_define_private_method_tmpl<a>::define(m, n, f)
-#else
-#define rb_define_private_method_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_private_method15,rb_define_private_methodm3)
-#define rb_define_private_method_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_private_method14,rb_define_private_method_choose_prototype15(n))
-#define rb_define_private_method_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_private_method13,rb_define_private_method_choose_prototype14(n))
-#define rb_define_private_method_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_private_method12,rb_define_private_method_choose_prototype13(n))
-#define rb_define_private_method_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_private_method11,rb_define_private_method_choose_prototype12(n))
-#define rb_define_private_method_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_private_method10,rb_define_private_method_choose_prototype11(n))
-#define rb_define_private_method_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_private_method9, rb_define_private_method_choose_prototype10(n))
-#define rb_define_private_method_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_private_method8, rb_define_private_method_choose_prototype9(n))
-#define rb_define_private_method_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_private_method7, rb_define_private_method_choose_prototype8(n))
-#define rb_define_private_method_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_private_method6, rb_define_private_method_choose_prototype7(n))
-#define rb_define_private_method_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_private_method5, rb_define_private_method_choose_prototype6(n))
-#define rb_define_private_method_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_private_method4, rb_define_private_method_choose_prototype5(n))
-#define rb_define_private_method_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_private_method3, rb_define_private_method_choose_prototype4(n))
-#define rb_define_private_method_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_private_method2, rb_define_private_method_choose_prototype3(n))
-#define rb_define_private_method_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_private_method1, rb_define_private_method_choose_prototype2(n))
-#define rb_define_private_method_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_private_method0, rb_define_private_method_choose_prototype1(n))
-#define rb_define_private_method_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_private_methodm1,rb_define_private_method_choose_prototype0(n))
-#define rb_define_private_method_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_private_methodm2,rb_define_private_method_choose_prototypem1(n))
-#define rb_define_private_method_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_private_methodm3,rb_define_private_method_choose_prototypem2(n))
-#define rb_define_private_method(klass, mid, func, arity) rb_define_private_method_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity));
-#endif
-
-RB_METHOD_DEFINITION_DECL(rb_define_singleton_method, (2,3), (VALUE klass, const char *name), (klass, name))
-#ifdef __cplusplus
-#define rb_define_singleton_method(m, n, f, a) rb_define_singleton_method_tmpl<a>::define(m, n, f)
-#else
-#define rb_define_singleton_method_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_singleton_method15,rb_define_singleton_methodm3)
-#define rb_define_singleton_method_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_singleton_method14,rb_define_singleton_method_choose_prototype15(n))
-#define rb_define_singleton_method_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_singleton_method13,rb_define_singleton_method_choose_prototype14(n))
-#define rb_define_singleton_method_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_singleton_method12,rb_define_singleton_method_choose_prototype13(n))
-#define rb_define_singleton_method_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_singleton_method11,rb_define_singleton_method_choose_prototype12(n))
-#define rb_define_singleton_method_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_singleton_method10,rb_define_singleton_method_choose_prototype11(n))
-#define rb_define_singleton_method_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_singleton_method9, rb_define_singleton_method_choose_prototype10(n))
-#define rb_define_singleton_method_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_singleton_method8, rb_define_singleton_method_choose_prototype9(n))
-#define rb_define_singleton_method_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_singleton_method7, rb_define_singleton_method_choose_prototype8(n))
-#define rb_define_singleton_method_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_singleton_method6, rb_define_singleton_method_choose_prototype7(n))
-#define rb_define_singleton_method_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_singleton_method5, rb_define_singleton_method_choose_prototype6(n))
-#define rb_define_singleton_method_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_singleton_method4, rb_define_singleton_method_choose_prototype5(n))
-#define rb_define_singleton_method_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_singleton_method3, rb_define_singleton_method_choose_prototype4(n))
-#define rb_define_singleton_method_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_singleton_method2, rb_define_singleton_method_choose_prototype3(n))
-#define rb_define_singleton_method_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_singleton_method1, rb_define_singleton_method_choose_prototype2(n))
-#define rb_define_singleton_method_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_singleton_method0, rb_define_singleton_method_choose_prototype1(n))
-#define rb_define_singleton_method_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_singleton_methodm1,rb_define_singleton_method_choose_prototype0(n))
-#define rb_define_singleton_method_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_singleton_methodm2,rb_define_singleton_method_choose_prototypem1(n))
-#define rb_define_singleton_method_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_singleton_methodm3,rb_define_singleton_method_choose_prototypem2(n))
-#define rb_define_singleton_method(klass, mid, func, arity) rb_define_singleton_method_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity));
-#endif
-
-#endif
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C++" { */
-#endif
+#include "ruby/internal/intern/array.h"
+#include "ruby/internal/intern/bignum.h"
+#include "ruby/internal/intern/class.h"
+#include "ruby/internal/intern/compar.h"
+#include "ruby/internal/intern/complex.h"
+#include "ruby/internal/intern/cont.h"
+#include "ruby/internal/intern/dir.h"
+#include "ruby/internal/intern/enum.h"
+#include "ruby/internal/intern/enumerator.h"
+#include "ruby/internal/intern/error.h"
+#include "ruby/internal/intern/eval.h"
+#include "ruby/internal/intern/file.h"
+#include "ruby/internal/intern/gc.h"
+#include "ruby/internal/intern/hash.h"
+#include "ruby/internal/intern/io.h"
+#include "ruby/internal/intern/load.h"
+#include "ruby/internal/intern/marshal.h"
+#include "ruby/internal/intern/numeric.h"
+#include "ruby/internal/intern/object.h"
+#include "ruby/internal/intern/parse.h"
+#include "ruby/internal/intern/proc.h"
+#include "ruby/internal/intern/process.h"
+#include "ruby/internal/intern/random.h"
+#include "ruby/internal/intern/range.h"
+#include "ruby/internal/intern/rational.h"
+#include "ruby/internal/intern/re.h"
+#include "ruby/internal/intern/ruby.h"
+#include "ruby/internal/intern/select.h"
+#include "ruby/internal/intern/signal.h"
+#include "ruby/internal/intern/sprintf.h"
+#include "ruby/internal/intern/string.h"
+#include "ruby/internal/intern/struct.h"
+#include "ruby/internal/intern/thread.h"
+#include "ruby/internal/intern/time.h"
+#include "ruby/internal/intern/variable.h"
+#include "ruby/internal/intern/vm.h"
#endif /* RUBY_INTERN_H */
diff --git a/include/ruby/internal/anyargs.h b/include/ruby/internal/anyargs.h
new file mode 100644
index 0000000000..f09a4e72e9
--- /dev/null
+++ b/include/ruby/internal/anyargs.h
@@ -0,0 +1,375 @@
+#ifndef RBIMPL_ANYARGS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ANYARGS_H
+/**
+ * @file
+ * @author Ruby developers <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 Function overloads to issue warnings around #ANYARGS.
+ *
+ * For instance ::rb_define_method takes a pointer to #ANYARGS -ed functions,
+ * which in fact varies 18 different prototypes. We still need to preserve
+ * #ANYARGS for storages but why not check the consistencies if possible. With
+ * those complex macro overlays defined in this header file, use of a function
+ * pointer gets checked against the corresponding arity argument.
+ *
+ * ### Q&A ###
+ *
+ * - Q: Where did the magic number "18" came from in the description above?
+ *
+ * - A: Count the case branch of `vm_method.c:call_cfunc_invoker_func()`. Note
+ * also that the 18 branches has lasted for at least 25 years. See also
+ * commit 200e0ee2fd3c1c006c528874a88f684447215524.
+ *
+ * - Q: What is this `__weakref__` thing?
+ *
+ * - A: That is a kind of function overloading mechanism that GCC provides. In
+ * this case for instance `rb_define_method_00` is an alias of
+ * ::rb_define_method, with a strong type.
+ *
+ * - Q: What is this `__transparent_union__` thing?
+ *
+ * A: That is another kind of function overloading mechanism that GCC
+ * provides. In this case the attributed function pointer is either
+ * `VALUE(*)(int,VALUE*,VALUE)` or `VALUE(*)(int,const VALUE*,VALUE)`.
+ *
+ * This is better than `void*` or #ANYARGS because we can reject all other
+ * possibilities than the two.
+ *
+ * - Q: What does this #rb_define_method macro mean?
+ *
+ * - A: It selects appropriate alias of the ::rb_define_method function,
+ * depending on the last (arity) argument.
+ *
+ * - Q: Why the special case for ::rb_f_notimplement ?
+ *
+ * - A: Function pointer to ::rb_f_notimplement is special cased in
+ * `vm_method.c:rb_add_method_cfunc()`. That should be handled by the
+ * `__builtin_choose_expr` chain inside of #rb_define_method macro
+ * expansion. In order to do so, comparison like
+ * `(func == rb_f_notimplement)` is inappropriate for
+ * `__builtin_choose_expr`'s expression (which must be a compile-time
+ * integer constant but the address of ::rb_f_notimplement is not fixed
+ * until the linker). Instead we are using
+ * `__builtin_types_compatible_p`, and in doing so we need to distinguish
+ * ::rb_f_notimplement from others, by type.
+ */
+#include "ruby/internal/attr/maybe_unused.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/weakref.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/config.h"
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/intern/class.h"
+#include "ruby/internal/intern/vm.h"
+#include "ruby/internal/method.h"
+#include "ruby/internal/value.h"
+#include "ruby/backward/2/stdarg.h"
+
+#if defined(__cplusplus)
+# include "ruby/backward/cxxanyargs.hpp"
+
+#elif defined(_WIN32) || defined(__CYGWIN__)
+# /* Skip due to [Bug #16134] */
+
+#elif ! RBIMPL_HAS_ATTRIBUTE(transparent_union)
+# /* :TODO: improve here, please find a way to support. */
+
+#elif ! defined(HAVE_VA_ARGS_MACRO)
+# /* :TODO: improve here, please find a way to support. */
+
+#else
+# /** @cond INTERNAL_MACRO */
+# if ! defined(HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P)
+# define RBIMPL_CFUNC_IS_rb_f_notimplement(f) 0
+# else
+# define RBIMPL_CFUNC_IS_rb_f_notimplement(f) \
+ __builtin_types_compatible_p( \
+ __typeof__(f), \
+ __typeof__(rb_f_notimplement))
+# endif
+
+# if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
+# define RBIMPL_ANYARGS_DISPATCH(expr, truthy, falsy) (falsy)
+# else
+# define RBIMPL_ANYARGS_DISPATCH(expr, truthy, falsy) \
+ __builtin_choose_expr( \
+ __builtin_choose_expr( \
+ __builtin_constant_p(expr), \
+ (expr), 0), \
+ (truthy), (falsy))
+# endif
+
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_singleton_method_m2, rb_define_singleton_method_m3)
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_singleton_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m2(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_singleton_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_m1(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_singleton_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_00(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_singleton_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_01(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_singleton_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_02(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_singleton_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_03(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_singleton_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_04(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_singleton_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_05(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_singleton_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_06(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_singleton_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_07(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_singleton_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_08(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_singleton_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_09(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_singleton_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_10(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_singleton_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_11(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_singleton_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_12(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_singleton_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_13(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_singleton_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_14(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_protected_method_m2, rb_define_protected_method_m3)
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_protected_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m2(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_protected_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_m1(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_protected_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_00(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_protected_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_01(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_protected_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_02(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_protected_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_03(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_protected_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_04(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_protected_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_05(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_protected_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_06(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_protected_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_07(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_protected_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_08(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_protected_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_09(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_protected_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_10(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_protected_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_11(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_protected_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_12(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_protected_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_13(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_protected_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_14(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_private_method_m2, rb_define_private_method_m3)
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_private_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m2(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_private_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_m1(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_private_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_00(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_private_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_01(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_private_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_02(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_private_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_03(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_private_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_04(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_private_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_05(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_private_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_06(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_private_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_07(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_private_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_08(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_private_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_09(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_private_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_10(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_private_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_11(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_private_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_12(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_private_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_13(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_private_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_14(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_module_function_m2, rb_define_module_function_m3)
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_module_function_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m2(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_module_function_00, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_m1(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_module_function_01, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_00(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_module_function_02, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_01(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_module_function_03, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_02(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_module_function_04, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_03(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_module_function_05, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_04(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_module_function_06, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_05(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_module_function_07, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_06(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_module_function_08, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_07(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_module_function_09, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_08(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_module_function_10, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_09(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_module_function_11, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_10(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_module_function_12, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_11(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_module_function_13, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_12(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_module_function_14, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_13(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_module_function_15, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_14(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_global_function_m2, rb_define_global_function_m3)
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_global_function_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m2(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_global_function_00, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_m1(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_global_function_01, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_00(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_global_function_02, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_01(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_global_function_03, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_02(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_global_function_04, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_03(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_global_function_05, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_04(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_global_function_06, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_05(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_global_function_07, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_06(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_global_function_08, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_07(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_global_function_09, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_08(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_global_function_10, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_09(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_global_function_11, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_10(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_global_function_12, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_11(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_global_function_13, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_12(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_global_function_14, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_13(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_global_function_15, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_14(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_method_id_m2, rb_define_method_id_m3)
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_method_id_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m2(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_method_id_00, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_m1(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_method_id_01, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_00(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_method_id_02, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_01(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_method_id_03, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_02(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_method_id_04, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_03(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_method_id_05, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_04(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_method_id_06, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_05(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_method_id_07, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_06(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_method_id_08, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_07(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_method_id_09, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_08(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_method_id_10, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_09(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_method_id_11, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_10(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_method_id_12, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_11(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_method_id_13, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_12(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_method_id_14, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_13(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_method_id_15, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_14(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_m2(n) RBIMPL_ANYARGS_DISPATCH((n) == -2, rb_define_method_m2, rb_define_method_m3)
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_m1(n) RBIMPL_ANYARGS_DISPATCH((n) == -1, rb_define_method_m1, RBIMPL_ANYARGS_DISPATCH_rb_define_method_m2(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_00(n) RBIMPL_ANYARGS_DISPATCH((n) == 0, rb_define_method_00, RBIMPL_ANYARGS_DISPATCH_rb_define_method_m1(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_01(n) RBIMPL_ANYARGS_DISPATCH((n) == 1, rb_define_method_01, RBIMPL_ANYARGS_DISPATCH_rb_define_method_00(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_02(n) RBIMPL_ANYARGS_DISPATCH((n) == 2, rb_define_method_02, RBIMPL_ANYARGS_DISPATCH_rb_define_method_01(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_03(n) RBIMPL_ANYARGS_DISPATCH((n) == 3, rb_define_method_03, RBIMPL_ANYARGS_DISPATCH_rb_define_method_02(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_04(n) RBIMPL_ANYARGS_DISPATCH((n) == 4, rb_define_method_04, RBIMPL_ANYARGS_DISPATCH_rb_define_method_03(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_05(n) RBIMPL_ANYARGS_DISPATCH((n) == 5, rb_define_method_05, RBIMPL_ANYARGS_DISPATCH_rb_define_method_04(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_06(n) RBIMPL_ANYARGS_DISPATCH((n) == 6, rb_define_method_06, RBIMPL_ANYARGS_DISPATCH_rb_define_method_05(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_07(n) RBIMPL_ANYARGS_DISPATCH((n) == 7, rb_define_method_07, RBIMPL_ANYARGS_DISPATCH_rb_define_method_06(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_08(n) RBIMPL_ANYARGS_DISPATCH((n) == 8, rb_define_method_08, RBIMPL_ANYARGS_DISPATCH_rb_define_method_07(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_09(n) RBIMPL_ANYARGS_DISPATCH((n) == 9, rb_define_method_09, RBIMPL_ANYARGS_DISPATCH_rb_define_method_08(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_10(n) RBIMPL_ANYARGS_DISPATCH((n) == 10, rb_define_method_10, RBIMPL_ANYARGS_DISPATCH_rb_define_method_09(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_11(n) RBIMPL_ANYARGS_DISPATCH((n) == 11, rb_define_method_11, RBIMPL_ANYARGS_DISPATCH_rb_define_method_10(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_12(n) RBIMPL_ANYARGS_DISPATCH((n) == 12, rb_define_method_12, RBIMPL_ANYARGS_DISPATCH_rb_define_method_11(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n) RBIMPL_ANYARGS_DISPATCH((n) == 13, rb_define_method_13, RBIMPL_ANYARGS_DISPATCH_rb_define_method_12(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n) RBIMPL_ANYARGS_DISPATCH((n) == 14, rb_define_method_14, RBIMPL_ANYARGS_DISPATCH_rb_define_method_13(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n) RBIMPL_ANYARGS_DISPATCH((n) == 15, rb_define_method_15, RBIMPL_ANYARGS_DISPATCH_rb_define_method_14(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_singleton_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method_15(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_protected_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method_15(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_private_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_private_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_private_method_15(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_module_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_module_function_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_module_function_15(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_global_function(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_global_function_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_global_function_15(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method_id(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_id_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_method_id_15(n))
+# define RBIMPL_ANYARGS_DISPATCH_rb_define_method(n, f) RBIMPL_ANYARGS_DISPATCH(RBIMPL_CFUNC_IS_rb_f_notimplement(f), rb_define_method_m3, RBIMPL_ANYARGS_DISPATCH_rb_define_method_15(n))
+# define RBIMPL_ANYARGS_ATTRSET(sym) RBIMPL_ATTR_MAYBE_UNUSED() RBIMPL_ATTR_NONNULL() RBIMPL_ATTR_WEAKREF(sym)
+# define RBIMPL_ANYARGS_DECL(sym, ...) \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m3(__VA_ARGS__, VALUE(*)(ANYARGS), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m2(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _m1(__VA_ARGS__, VALUE(*)(int, union { VALUE *x; const VALUE *y; } __attribute__((__transparent_union__)), VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _00(__VA_ARGS__, VALUE(*)(VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _01(__VA_ARGS__, VALUE(*)(VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _02(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _03(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _04(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _05(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _06(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _07(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _08(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _09(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _10(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _11(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _12(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _13(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _14(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int); \
+RBIMPL_ANYARGS_ATTRSET(sym) static void sym ## _15(__VA_ARGS__, VALUE(*)(VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE, VALUE), int);
+RBIMPL_ANYARGS_DECL(rb_define_singleton_method, VALUE, const char *)
+RBIMPL_ANYARGS_DECL(rb_define_protected_method, VALUE, const char *)
+RBIMPL_ANYARGS_DECL(rb_define_private_method, VALUE, const char *)
+RBIMPL_ANYARGS_DECL(rb_define_module_function, VALUE, const char *)
+RBIMPL_ANYARGS_DECL(rb_define_global_function, const char *)
+RBIMPL_ANYARGS_DECL(rb_define_method_id, VALUE, ID)
+RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *)
+/** @endcond */
+
+/**
+ * @brief Defines klass\#mid.
+ * @see ::rb_define_method
+ * @param klass Where the method lives.
+ * @param mid Name of the defining method.
+ * @param func Implementation of klass\#mid.
+ * @param arity Arity of klass\#mid.
+ */
+#define rb_define_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_method((arity), (func))((klass), (mid), (func), (arity))
+
+/**
+ * @brief Defines klass\#mid.
+ * @see ::rb_define_method_id
+ * @param klass Where the method lives.
+ * @param mid Name of the defining method.
+ * @param func Implementation of klass\#mid.
+ * @param arity Arity of klass\#mid.
+ */
+#define rb_define_method_id(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_method_id((arity), (func))((klass), (mid), (func), (arity))
+
+/**
+ * @brief Defines obj.mid.
+ * @see ::rb_define_singleton_method
+ * @param obj Where the method lives.
+ * @param mid Name of the defining method.
+ * @param func Implementation of obj.mid.
+ * @param arity Arity of obj.mid.
+ */
+#define rb_define_singleton_method(obj, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_singleton_method((arity), (func))((obj), (mid), (func), (arity))
+
+/**
+ * @brief Defines klass\#mid and make it protected.
+ * @see ::rb_define_protected_method
+ * @param klass Where the method lives.
+ * @param mid Name of the defining method.
+ * @param func Implementation of klass\#mid.
+ * @param arity Arity of klass\#mid.
+ */
+#define rb_define_protected_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_protected_method((arity), (func))((klass), (mid), (func), (arity))
+
+/**
+ * @brief Defines klass\#mid and make it private.
+ * @see ::rb_define_private_method
+ * @param klass Where the method lives.
+ * @param mid Name of the defining method.
+ * @param func Implementation of klass\#mid.
+ * @param arity Arity of klass\#mid.
+ */
+#define rb_define_private_method(klass, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_private_method((arity), (func))((klass), (mid), (func), (arity))
+
+/**
+ * @brief Defines mod\#mid and make it a module function.
+ * @see ::rb_define_module_function
+ * @param mod Where the method lives.
+ * @param mid Name of the defining method.
+ * @param func Implementation of mod\#mid.
+ * @param arity Arity of mod\#mid.
+ */
+#define rb_define_module_function(mod, mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_module_function((arity), (func))((mod), (mid), (func), (arity))
+
+/**
+ * @brief Defines ::rb_mKerbel \#mid.
+ * @see ::rb_define_gobal_function
+ * @param mid Name of the defining method.
+ * @param func Implementation of ::rb_mKernel \#mid.
+ * @param arity Arity of ::rb_mKernel \#mid.
+ */
+#define rb_define_global_function(mid, func, arity) RBIMPL_ANYARGS_DISPATCH_rb_define_global_function((arity), (func))((mid), (func), (arity))
+
+#endif /* __cplusplus */
+
+/**
+ * This macro is to properly cast a function parameter of *_define_method
+ * family. It has been around since 1.x era so you can maximize backwards
+ * compatibility by using it.
+ *
+ * ```CXX
+ * rb_define_method(klass, "method", RUBY_METHOD_FUNC(func), arity);
+ * ```
+ *
+ * @param func A pointer to a function that implements a method.
+ */
+#if ! defined(RUBY_DEVEL)
+# define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func))
+
+#elif ! RUBY_DEVEL
+# define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func))
+
+#elif ! defined(rb_define_method)
+# define RUBY_METHOD_FUNC(func) RBIMPL_CAST((VALUE (*)(ANYARGS))(func))
+
+#else
+# define RUBY_METHOD_FUNC(func) (func)
+
+#endif
+
+#endif /* RBIMPL_ANYARGS_H */
diff --git a/include/ruby/internal/arithmetic.h b/include/ruby/internal/arithmetic.h
new file mode 100644
index 0000000000..c3806db444
--- /dev/null
+++ b/include/ruby/internal/arithmetic.h
@@ -0,0 +1,38 @@
+#ifndef RBIMPL_ARITHMETIC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_H
+/**
+ * @file
+ * @author Ruby developers <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 Conversion between C's arithmtic types and Ruby's numeric types.
+ */
+#include "ruby/internal/arithmetic/char.h"
+#include "ruby/internal/arithmetic/double.h"
+#include "ruby/internal/arithmetic/fixnum.h"
+#include "ruby/internal/arithmetic/gid_t.h"
+#include "ruby/internal/arithmetic/int.h"
+#include "ruby/internal/arithmetic/intptr_t.h"
+#include "ruby/internal/arithmetic/long.h"
+#include "ruby/internal/arithmetic/long_long.h"
+#include "ruby/internal/arithmetic/mode_t.h"
+#include "ruby/internal/arithmetic/off_t.h"
+#include "ruby/internal/arithmetic/pid_t.h"
+#include "ruby/internal/arithmetic/short.h"
+#include "ruby/internal/arithmetic/size_t.h"
+#include "ruby/internal/arithmetic/st_data_t.h"
+#include "ruby/internal/arithmetic/uid_t.h"
+#endif /* RBIMPL_ARITHMETIC_H */
diff --git a/include/ruby/internal/arithmetic/char.h b/include/ruby/internal/arithmetic/char.h
new file mode 100644
index 0000000000..3033639a43
--- /dev/null
+++ b/include/ruby/internal/arithmetic/char.h
@@ -0,0 +1,58 @@
+#ifndef RBIMPL_ARITHMETIC_CHAR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_CHAR_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 Arithmetic conversion between C's `char` and Ruby's.
+ */
+#include "ruby/internal/arithmetic/int.h" /* NUM2INT is here, but */
+#include "ruby/internal/arithmetic/long.h" /* INT2FIX is here.*/
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/core/rstring.h"
+#include "ruby/internal/value_type.h"
+
+#define RB_NUM2CHR rb_num2char_inline
+#define NUM2CHR RB_NUM2CHR
+#define CHR2FIX RB_CHR2FIX
+
+/** @cond INTERNAL_MACRO */
+#define RB_CHR2FIX RB_CHR2FIX
+/** @endcond */
+
+RBIMPL_ATTR_CONST_UNLESS_DEBUG()
+RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RB_CHR2FIX(unsigned char c)
+{
+ return RB_INT2FIX(c);
+}
+
+static inline char
+rb_num2char_inline(VALUE x)
+{
+ if (RB_TYPE_P(x, RUBY_T_STRING) && (RSTRING_LEN(x)>=1))
+ return RSTRING_PTR(x)[0];
+ else
+ return RBIMPL_CAST((char)RB_NUM2INT(x));
+}
+
+#endif /* RBIMPL_ARITHMETIC_CHAR_H */
diff --git a/include/ruby/internal/arithmetic/double.h b/include/ruby/internal/arithmetic/double.h
new file mode 100644
index 0000000000..69d8630dbb
--- /dev/null
+++ b/include/ruby/internal/arithmetic/double.h
@@ -0,0 +1,39 @@
+#ifndef RBIMPL_ARITHMETIC_DOUBLE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_DOUBLE_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 Arithmetic conversion between C's `double` and Ruby's.
+ */
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+#define NUM2DBL rb_num2dbl
+#define RFLOAT_VALUE rb_float_value
+#define DBL2NUM rb_float_new
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+double rb_num2dbl(VALUE);
+RBIMPL_ATTR_PURE()
+double rb_float_value(VALUE);
+VALUE rb_float_new(double);
+VALUE rb_float_new_in_heap(double);
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_ARITHMETIC_DOUBLE_H */
diff --git a/include/ruby/internal/arithmetic/fixnum.h b/include/ruby/internal/arithmetic/fixnum.h
new file mode 100644
index 0000000000..68544b760b
--- /dev/null
+++ b/include/ruby/internal/arithmetic/fixnum.h
@@ -0,0 +1,44 @@
+#ifndef RBIMPL_ARITHMETIC_FIXNUM_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_FIXNUM_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 Handling of integers formerly known as Fixnums.
+ */
+#include "ruby/backward/2/limits.h"
+
+#define FIXABLE RB_FIXABLE
+#define FIXNUM_MAX RUBY_FIXNUM_MAX
+#define FIXNUM_MIN RUBY_FIXNUM_MIN
+#define NEGFIXABLE RB_NEGFIXABLE
+#define POSFIXABLE RB_POSFIXABLE
+
+/*
+ * FIXABLE can be applied to anything, from double to intmax_t. The problem is
+ * double. On a 64bit system RUBY_FIXNUM_MAX is 4,611,686,018,427,387,903,
+ * which is not representable by a double. The nearest value that a double can
+ * represent is 4,611,686,018,427,387,904, which is not fixable. The
+ * seemingly-stragne "< FIXNUM_MAX + 1" expression below is due to this.
+ */
+#define RB_POSFIXABLE(_) ((_) < RUBY_FIXNUM_MAX + 1)
+#define RB_NEGFIXABLE(_) ((_) >= RUBY_FIXNUM_MIN)
+#define RB_FIXABLE(_) (RB_POSFIXABLE(_) && RB_NEGFIXABLE(_))
+#define RUBY_FIXNUM_MAX (LONG_MAX / 2)
+#define RUBY_FIXNUM_MIN (LONG_MIN / 2)
+
+#endif /* RBIMPL_ARITHMETIC_FIXNUM_H */
diff --git a/include/ruby/internal/arithmetic/gid_t.h b/include/ruby/internal/arithmetic/gid_t.h
new file mode 100644
index 0000000000..32e3578bd2
--- /dev/null
+++ b/include/ruby/internal/arithmetic/gid_t.h
@@ -0,0 +1,34 @@
+#ifndef RBIMPL_ARITHMETIC_GID_T_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_GID_T_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 Arithmetic conversion between C's `gid_t` and Ruby's.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/arithmetic/long.h"
+
+#ifndef GIDT2NUM
+# define GIDT2NUM RB_LONG2NUM
+#endif
+
+#ifndef NUM2GIDT
+# define NUM2GIDT RB_NUM2LONG
+#endif
+
+#endif /* RBIMPL_ARITHMETIC_GID_T_H */
diff --git a/include/ruby/internal/arithmetic/int.h b/include/ruby/internal/arithmetic/int.h
new file mode 100644
index 0000000000..346fa9258b
--- /dev/null
+++ b/include/ruby/internal/arithmetic/int.h
@@ -0,0 +1,163 @@
+#ifndef RBIMPL_ARITHMETIC_INT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_INT_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 Arithmetic conversion between C's `int` and Ruby's.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/arithmetic/fixnum.h"
+#include "ruby/internal/arithmetic/intptr_t.h"
+#include "ruby/internal/arithmetic/long.h"
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/compiler_is.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/special_consts.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/warning_push.h"
+#include "ruby/assert.h"
+
+#define RB_INT2NUM rb_int2num_inline
+#define RB_NUM2INT rb_num2int_inline
+#define RB_UINT2NUM rb_uint2num_inline
+
+#define FIX2INT RB_FIX2INT
+#define FIX2UINT RB_FIX2UINT
+#define INT2NUM RB_INT2NUM
+#define NUM2INT RB_NUM2INT
+#define NUM2UINT RB_NUM2UINT
+#define UINT2NUM RB_UINT2NUM
+
+/** @cond INTERNAL_MACRO */
+#define RB_FIX2INT RB_FIX2INT
+#define RB_NUM2UINT RB_NUM2UINT
+#define RB_FIX2UINT RB_FIX2UINT
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+long rb_num2int(VALUE);
+long rb_fix2int(VALUE);
+unsigned long rb_num2uint(VALUE);
+unsigned long rb_fix2uint(VALUE);
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+RB_FIX2INT(VALUE x)
+{
+ /* "FIX2INT raises a TypeError if passed nil", says rubyspec. Not sure if
+ * that is a desired behaviour but just preserve backwards compatilibily.
+ */
+#if 0
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
+#endif
+ long ret;
+
+ if /* constexpr */ (sizeof(int) < sizeof(long)) {
+ ret = rb_fix2int(x);
+ }
+ else {
+ ret = RB_FIX2LONG(x);
+ }
+
+ return RBIMPL_CAST((int)ret);
+}
+
+static inline int
+rb_num2int_inline(VALUE x)
+{
+ long ret;
+
+ if /* constexpr */ (sizeof(int) == sizeof(long)) {
+ ret = RB_NUM2LONG(x);
+ }
+ else if (RB_FIXNUM_P(x)) {
+ ret = rb_fix2int(x);
+ }
+ else {
+ ret = rb_num2int(x);
+ }
+
+ return RBIMPL_CAST((int)ret);
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline unsigned int
+RB_NUM2UINT(VALUE x)
+{
+ unsigned long ret;
+
+ if /* constexpr */ (sizeof(int) < sizeof(long)) {
+ ret = rb_num2uint(x);
+ }
+ else {
+ ret = RB_NUM2ULONG(x);
+ }
+
+ return RBIMPL_CAST((unsigned int)ret);
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline unsigned int
+RB_FIX2UINT(VALUE x)
+{
+#if 0 /* Ditto for RB_FIX2INT. */
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
+#endif
+ unsigned long ret;
+
+ if /* constexpr */ (sizeof(int) < sizeof(long)) {
+ ret = rb_fix2uint(x);
+ }
+ else {
+ ret = RB_FIX2ULONG(x);
+ }
+
+ return RBIMPL_CAST((unsigned int)ret);
+}
+
+RBIMPL_WARNING_PUSH()
+#if RBIMPL_COMPILER_IS(GCC)
+RBIMPL_WARNING_IGNORED(-Wtype-limits) /* We can ignore them here. */
+#elif RBIMPL_HAS_WARNING("-Wtautological-constant-out-of-range-compare")
+RBIMPL_WARNING_IGNORED(-Wtautological-constant-out-of-range-compare)
+#endif
+
+static inline VALUE
+rb_int2num_inline(int v)
+{
+ if (RB_FIXABLE(v))
+ return RB_INT2FIX(v);
+ else
+ return rb_int2big(v);
+}
+
+static inline VALUE
+rb_uint2num_inline(unsigned int v)
+{
+ if (RB_POSFIXABLE(v))
+ return RB_LONG2FIX(v);
+ else
+ return rb_uint2big(v);
+}
+
+RBIMPL_WARNING_POP()
+
+#endif /* RBIMPL_ARITHMETIC_INT_H */
diff --git a/include/ruby/internal/arithmetic/intptr_t.h b/include/ruby/internal/arithmetic/intptr_t.h
new file mode 100644
index 0000000000..442c87144c
--- /dev/null
+++ b/include/ruby/internal/arithmetic/intptr_t.h
@@ -0,0 +1,42 @@
+#ifndef RBIMPL_ARITHMETIC_INTPTR_T_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_INTPTR_T_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 Arithmetic conversion between C's `intptr_t` and Ruby's.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include "ruby/internal/value.h"
+#include "ruby/internal/dllexport.h"
+
+#define rb_int_new rb_int2inum
+#define rb_uint_new rb_uint2inum
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE rb_int2big(intptr_t i);
+VALUE rb_int2inum(intptr_t i);
+VALUE rb_uint2big(uintptr_t i);
+VALUE rb_uint2inum(uintptr_t i);
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_ARITHMETIC_INTPTR_T_H */
diff --git a/include/ruby/internal/arithmetic/long.h b/include/ruby/internal/arithmetic/long.h
new file mode 100644
index 0000000000..aff7d68478
--- /dev/null
+++ b/include/ruby/internal/arithmetic/long.h
@@ -0,0 +1,244 @@
+#ifndef RBIMPL_ARITHMETIC_LONG_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_LONG_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 Arithmetic conversion between C's `long` and Ruby's.
+ *
+ * ### Q&A ###
+ *
+ * - Q: Why are INT2FIX etc. here, not in `int.h`?
+ *
+ * - A: Because they are in fact handling `long`. It seems someone did not
+ * understand the difference of `int` and `long` when they designed those
+ * macros.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/arithmetic/fixnum.h" /* FIXABLE */
+#include "ruby/internal/arithmetic/intptr_t.h" /* rb_int2big etc.*/
+#include "ruby/internal/assume.h"
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/special_consts.h" /* FIXNUM_FLAG */
+#include "ruby/internal/value.h"
+#include "ruby/assert.h"
+
+#define FIX2LONG RB_FIX2LONG
+#define FIX2ULONG RB_FIX2ULONG
+#define INT2FIX RB_INT2FIX
+#define LONG2FIX RB_INT2FIX
+#define LONG2NUM RB_LONG2NUM
+#define NUM2LONG RB_NUM2LONG
+#define NUM2ULONG RB_NUM2ULONG
+#define RB_FIX2LONG rb_fix2long
+#define RB_FIX2ULONG rb_fix2ulong
+#define RB_LONG2FIX RB_INT2FIX
+#define RB_LONG2NUM rb_long2num_inline
+#define RB_NUM2LONG rb_num2long_inline
+#define RB_NUM2ULONG rb_num2ulong_inline
+#define RB_ULONG2NUM rb_ulong2num_inline
+#define ULONG2NUM RB_ULONG2NUM
+#define rb_fix_new RB_INT2FIX
+#define rb_long2int rb_long2int_inline
+
+/** @cond INTERNAL_MACRO */
+#define RB_INT2FIX RB_INT2FIX
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_COLD()
+void rb_out_of_int(SIGNED_VALUE num);
+
+long rb_num2long(VALUE num);
+unsigned long rb_num2ulong(VALUE num);
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_CONST_UNLESS_DEBUG()
+RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RB_INT2FIX(long i)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(i));
+
+ /* :NOTE: VALUE can be wider than long. As j being unsigned, 2j+1 is fully
+ * defined. Also it can be compiled into a single LEA instruction. */
+ const unsigned long j = i;
+ const unsigned long k = 2 * j + RUBY_FIXNUM_FLAG;
+ const long l = k;
+ const SIGNED_VALUE m = l; /* Sign extend */
+ const VALUE n = m;
+
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(n));
+ return n;
+}
+
+static inline int
+rb_long2int_inline(long n)
+{
+ int i = RBIMPL_CAST((int)n);
+
+ if /* constexpr */ (sizeof(long) <= sizeof(int)) {
+ RBIMPL_ASSUME(i == n);
+ }
+
+ if (i != n)
+ rb_out_of_int(n);
+
+ return i;
+}
+
+RBIMPL_ATTR_CONST_UNLESS_DEBUG()
+RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+static inline long
+rbimpl_fix2long_by_idiv(VALUE x)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
+
+ /* :NOTE: VALUE can be wider than long. (x-1)/2 never overflows because
+ * RB_FIXNUM_P(x) holds. Also it has no portability issue like y>>1
+ * below. */
+ const SIGNED_VALUE y = x - RUBY_FIXNUM_FLAG;
+ const SIGNED_VALUE z = y / 2;
+ const long w = RBIMPL_CAST((long)z);
+
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w));
+ return w;
+}
+
+RBIMPL_ATTR_CONST_UNLESS_DEBUG()
+RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+static inline long
+rbimpl_fix2long_by_shift(VALUE x)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
+
+ /* :NOTE: VALUE can be wider than long. If right shift is arithmetic, this
+ * is noticeably faster than above. */
+ const SIGNED_VALUE y = x;
+ const SIGNED_VALUE z = y >> 1;
+ const long w = RBIMPL_CAST((long)z);
+
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(w));
+ return w;
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+static inline bool
+rbimpl_right_shift_is_arithmetic_p(void)
+{
+ return (-1 >> 1) == -1;
+}
+
+RBIMPL_ATTR_CONST_UNLESS_DEBUG()
+RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+static inline long
+rb_fix2long(VALUE x)
+{
+ if /* constexpr */ (rbimpl_right_shift_is_arithmetic_p()) {
+ return rbimpl_fix2long_by_shift(x);
+ }
+ else {
+ return rbimpl_fix2long_by_idiv(x);
+ }
+}
+
+RBIMPL_ATTR_CONST_UNLESS_DEBUG()
+RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+static inline unsigned long
+rb_fix2ulong(VALUE x)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXNUM_P(x));
+ return rb_fix2long(x);
+}
+
+static inline long
+rb_num2long_inline(VALUE x)
+{
+ if (RB_FIXNUM_P(x))
+ return RB_FIX2LONG(x);
+ else
+ return rb_num2long(x);
+}
+
+static inline unsigned long
+rb_num2ulong_inline(VALUE x)
+{
+ /* This (negative fixnum would become a large unsigned long while negative
+ * bignum is an exception) has been THE behaviour of NUM2ULONG since the
+ * beginning. It is strange, but we can no longer change how it works at
+ * this moment. We have to get by with it. See also:
+ * https://bugs.ruby-lang.org/issues/9089 */
+ if (RB_FIXNUM_P(x))
+ return RB_FIX2ULONG(x);
+ else
+ return rb_num2ulong(x);
+}
+
+static inline VALUE
+rb_long2num_inline(long v)
+{
+ if (RB_FIXABLE(v))
+ return RB_LONG2FIX(v);
+ else
+ return rb_int2big(v);
+}
+
+static inline VALUE
+rb_ulong2num_inline(unsigned long v)
+{
+ if (RB_POSFIXABLE(v))
+ return RB_LONG2FIX(v);
+ else
+ return rb_uint2big(v);
+}
+
+/**
+ * @cond INTERNAL_MACRO
+ *
+ * Following overload is necessary because sometimes INT2FIX is used as a enum
+ * value (e.g. `enum { FOO = INT2FIX(0) };`). THIS IS NG in theory because a
+ * VALUE does not fit into an enum (which must be a signed int). But we cannot
+ * break existing codes.
+ */
+#if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14
+# /* C++ can write constexpr as enum values. */
+
+#elif ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
+# undef INT2FIX
+# define INT2FIX(i) (RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG)
+
+#else
+# undef INT2FIX
+# define INT2FIX(i) \
+ __builtin_choose_expr( \
+ __builtin_constant_p(i), \
+ RBIMPL_CAST((VALUE)(i)) << 1 | RUBY_FIXNUM_FLAG, \
+ RB_INT2FIX(i))
+#endif
+/** @endcond */
+
+#endif /* RBIMPL_ARITHMETIC_LONG_H */
diff --git a/include/ruby/internal/arithmetic/long_long.h b/include/ruby/internal/arithmetic/long_long.h
new file mode 100644
index 0000000000..96ffb37d57
--- /dev/null
+++ b/include/ruby/internal/arithmetic/long_long.h
@@ -0,0 +1,53 @@
+#ifndef RBIMPL_ARITHMETIC_LONG_LONG_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_LONG_LONG_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 Arithmetic conversion between C's `long long` and Ruby's.
+ */
+#include "ruby/internal/value.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/special_consts.h"
+#include "ruby/backward/2/long_long.h"
+
+#define RB_LL2NUM rb_ll2inum
+#define RB_ULL2NUM rb_ull2inum
+#define LL2NUM RB_LL2NUM
+#define ULL2NUM RB_ULL2NUM
+#define RB_NUM2LL rb_num2ll_inline
+#define RB_NUM2ULL rb_num2ull
+#define NUM2LL RB_NUM2LL
+#define NUM2ULL RB_NUM2ULL
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE rb_ll2inum(LONG_LONG);
+VALUE rb_ull2inum(unsigned LONG_LONG);
+LONG_LONG rb_num2ll(VALUE);
+unsigned LONG_LONG rb_num2ull(VALUE);
+RBIMPL_SYMBOL_EXPORT_END()
+
+static inline LONG_LONG
+rb_num2ll_inline(VALUE x)
+{
+ if (RB_FIXNUM_P(x))
+ return RB_FIX2LONG(x);
+ else
+ return rb_num2ll(x);
+}
+
+#endif /* RBIMPL_ARITHMETIC_LONG_LONG_H */
diff --git a/include/ruby/internal/arithmetic/mode_t.h b/include/ruby/internal/arithmetic/mode_t.h
new file mode 100644
index 0000000000..ee47eb8221
--- /dev/null
+++ b/include/ruby/internal/arithmetic/mode_t.h
@@ -0,0 +1,34 @@
+#ifndef RBIMPL_ARITHMETIC_MODE_T_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_MODE_T_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 Arithmetic conversion between C's `mode_t` and Ruby's.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/arithmetic/int.h"
+
+#ifndef NUM2MODET
+# define NUM2MODET RB_NUM2INT
+#endif
+
+#ifndef MODET2NUM
+# define MODET2NUM RB_INT2NUM
+#endif
+
+#endif /* RBIMPL_ARITHMETIC_MODE_T_H */
diff --git a/include/ruby/internal/arithmetic/off_t.h b/include/ruby/internal/arithmetic/off_t.h
new file mode 100644
index 0000000000..84ec807e3d
--- /dev/null
+++ b/include/ruby/internal/arithmetic/off_t.h
@@ -0,0 +1,49 @@
+#ifndef RBIMPL_ARITHMETIC_OFF_T_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_OFF_T_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 Arithmetic conversion between C's `off_t` and Ruby's.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/arithmetic/int.h"
+#include "ruby/internal/arithmetic/long.h"
+#include "ruby/internal/arithmetic/long_long.h"
+#include "ruby/backward/2/long_long.h"
+
+#ifdef OFFT2NUM
+# /* take that. */
+#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG
+# define OFFT2NUM RB_LL2NUM
+#elif SIZEOF_OFF_T == SIZEOF_LONG
+# define OFFT2NUM RB_LONG2NUM
+#else
+# define OFFT2NUM RB_INT2NUM
+#endif
+
+#ifdef NUM2OFFT
+# /* take that. */
+#elif SIZEOF_OFF_T == SIZEOF_LONG_LONG
+# define NUM2OFFT RB_NUM2LL
+#elif SIZEOF_OFF_T == SIZEOF_LONG
+# define NUM2OFFT RB_NUM2LONG
+#else
+# define NUM2OFFT RB_NUM2INT
+#endif
+
+#endif /* RBIMPL_ARITHMETIC_OFF_T_H */
diff --git a/include/ruby/internal/arithmetic/pid_t.h b/include/ruby/internal/arithmetic/pid_t.h
new file mode 100644
index 0000000000..eaca402776
--- /dev/null
+++ b/include/ruby/internal/arithmetic/pid_t.h
@@ -0,0 +1,34 @@
+#ifndef RBIMPL_ARITHMETIC_PID_T_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_PID_T_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 Arithmetic conversion between C's `pid_t` and Ruby's.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/arithmetic/long.h"
+
+#ifndef PIDT2NUM
+# define PIDT2NUM RB_LONG2NUM
+#endif
+
+#ifndef NUM2PIDT
+# define NUM2PIDT RB_NUM2LONG
+#endif
+
+#endif /* RBIMPL_ARITHMETIC_PID_T_H */
diff --git a/include/ruby/internal/arithmetic/short.h b/include/ruby/internal/arithmetic/short.h
new file mode 100644
index 0000000000..ef213a8d3e
--- /dev/null
+++ b/include/ruby/internal/arithmetic/short.h
@@ -0,0 +1,54 @@
+#ifndef RBIMPL_ARITHMETIC_SHORT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_SHORT_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 Arithmetic conversion between C's `short` and Ruby's.
+ *
+ * Shyouhei wonders: why there is no SHORT2NUM, given there are both
+ * #USHORT2NUM and #CHR2FIX?
+ */
+#include "ruby/internal/value.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/special_consts.h"
+
+#define RB_NUM2SHORT rb_num2short_inline
+#define RB_NUM2USHORT rb_num2ushort
+#define NUM2SHORT RB_NUM2SHORT
+#define NUM2USHORT RB_NUM2USHORT
+#define USHORT2NUM RB_INT2FIX
+#define RB_FIX2SHORT rb_fix2short
+#define FIX2SHORT RB_FIX2SHORT
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+short rb_num2short(VALUE);
+unsigned short rb_num2ushort(VALUE);
+short rb_fix2short(VALUE);
+unsigned short rb_fix2ushort(VALUE);
+RBIMPL_SYMBOL_EXPORT_END()
+
+static inline short
+rb_num2short_inline(VALUE x)
+{
+ if (RB_FIXNUM_P(x))
+ return rb_fix2short(x);
+ else
+ return rb_num2short(x);
+}
+
+#endif /* RBIMPL_ARITHMETIC_SOHRT_H */
diff --git a/include/ruby/internal/arithmetic/size_t.h b/include/ruby/internal/arithmetic/size_t.h
new file mode 100644
index 0000000000..0458f1f5f3
--- /dev/null
+++ b/include/ruby/internal/arithmetic/size_t.h
@@ -0,0 +1,56 @@
+#ifndef RBIMPL_ARITHMETIC_SIZE_T_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_SIZE_T_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 Arithmetic conversion between C's `size_t` and Ruby's.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/arithmetic/int.h"
+#include "ruby/internal/arithmetic/long.h"
+#include "ruby/internal/arithmetic/long_long.h"
+#include "ruby/backward/2/long_long.h"
+
+#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+# define RB_SIZE2NUM RB_ULL2NUM
+# define RB_SSIZE2NUM RB_LL2NUM
+#elif SIZEOF_SIZE_T == SIZEOF_LONG
+# define RB_SIZE2NUM RB_ULONG2NUM
+# define RB_SSIZE2NUM RB_LONG2NUM
+#else
+# define RB_SIZE2NUM RB_UINT2NUM
+# define RB_SSIZE2NUM RB_INT2NUM
+#endif
+
+#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+# define RB_NUM2SIZE RB_NUM2ULL
+# define RB_NUM2SSIZE RB_NUM2LL
+#elif SIZEOF_SIZE_T == SIZEOF_LONG
+# define RB_NUM2SIZE RB_NUM2ULONG
+# define RB_NUM2SSIZE RB_NUM2LONG
+#else
+# define RB_NUM2SIZE RB_NUM2UINT
+# define RB_NUM2SSIZE RB_NUM2INT
+#endif
+
+#define NUM2SIZET RB_NUM2SIZE
+#define SIZET2NUM RB_SIZE2NUM
+#define NUM2SSIZET RB_NUM2SSIZE
+#define SSIZET2NUM RB_SSIZE2NUM
+
+#endif /* RBIMPL_ARITHMETIC_SIZE_T_H */
diff --git a/include/ruby/internal/arithmetic/st_data_t.h b/include/ruby/internal/arithmetic/st_data_t.h
new file mode 100644
index 0000000000..93a5ccb7a1
--- /dev/null
+++ b/include/ruby/internal/arithmetic/st_data_t.h
@@ -0,0 +1,59 @@
+#ifndef RBIMPL_ARITHMERIC_ST_DATA_T_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMERIC_ST_DATA_T_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 Arithmetic conversion between C's `st_data_t` and Ruby's.
+ */
+#include "ruby/internal/arithmetic/fixnum.h"
+#include "ruby/internal/arithmetic/long.h"
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/value.h"
+#include "ruby/assert.h"
+#include "ruby/st.h"
+
+#define ST2FIX RB_ST2FIX
+/** @cond INTERNAL_MACRO */
+#define RB_ST2FIX RB_ST2FIX
+/** @endcond */
+
+RBIMPL_ATTR_CONST_UNLESS_DEBUG()
+RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(CXX14)
+RBIMPL_ATTR_ARTIFICIAL()
+/* See also [ruby-core:84395] [Bug #14218] [ruby-core:82687] [Bug #13877] */
+static inline VALUE
+RB_ST2FIX(st_data_t i)
+{
+ SIGNED_VALUE x = i;
+
+ if (x >= 0) {
+ x &= RUBY_FIXNUM_MAX;
+ }
+ else {
+ x |= RUBY_FIXNUM_MIN;
+ }
+
+ RBIMPL_ASSERT_OR_ASSUME(RB_FIXABLE(x));
+ unsigned long y = RBIMPL_CAST((unsigned long)x);
+ return RB_LONG2FIX(y);
+}
+
+#endif /* RBIMPL_ARITHMERIC_ST_DATA_T_H */
diff --git a/include/ruby/internal/arithmetic/uid_t.h b/include/ruby/internal/arithmetic/uid_t.h
new file mode 100644
index 0000000000..bdcf42f049
--- /dev/null
+++ b/include/ruby/internal/arithmetic/uid_t.h
@@ -0,0 +1,34 @@
+#ifndef RBIMPL_ARITHMETIC_UID_T_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ARITHMETIC_UID_T_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 Arithmetic conversion between C's `uid_t` and Ruby's.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/arithmetic/long.h"
+
+#ifndef UIDT2NUM
+# define UIDT2NUM RB_LONG2NUM
+#endif
+
+#ifndef NUM2UIDT
+# define NUM2UIDT RB_NUM2LONG
+#endif
+
+#endif /* RBIMPL_ARITHMETIC_UID_T_H */
diff --git a/include/ruby/internal/assume.h b/include/ruby/internal/assume.h
new file mode 100644
index 0000000000..e95b2fb12a
--- /dev/null
+++ b/include/ruby/internal/assume.h
@@ -0,0 +1,90 @@
+#ifndef RBIMPL_ASSUME_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ASSUME_H
+/**
+ * @file
+ * @author Ruby developers <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_ASSUME / #RBIMPL_UNREACHABLE.
+ *
+ * These macros must be defined at once because:
+ *
+ * - #RBIMPL_ASSUME could fallback to #RBIMPL_UNREACHABLE.
+ * - #RBIMPL_UNREACHABLE could fallback to #RBIMPL_ASSUME.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/builtin.h"
+#include "ruby/internal/warning_push.h"
+
+/** @cond INTERNAL_MACRO */
+#if RBIMPL_COMPILER_SINCE(MSVC, 13, 10, 0)
+# define RBIMPL_HAVE___ASSUME
+
+#elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0)
+# define RBIMPL_HAVE___ASSUME
+#endif
+/** @endcond */
+
+/** Wraps (or simulates) `__builtin_unreachable`. */
+#if RBIMPL_HAS_BUILTIN(__builtin_unreachable)
+# define RBIMPL_UNREACHABLE_RETURN(_) __builtin_unreachable()
+
+#elif defined(RBIMPL_HAVE___ASSUME)
+# define RBIMPL_UNREACHABLE_RETURN(_) return (__assume(0), (_))
+
+#else
+# define RBIMPL_UNREACHABLE_RETURN(_) return (_)
+#endif
+
+/** Wraps (or simulates) `__builtin_unreachable`. */
+#if RBIMPL_HAS_BUILTIN(__builtin_unreachable)
+# define RBIMPL_UNREACHABLE __builtin_unreachable
+
+#elif defined(RBIMPL_HAVE___ASSUME)
+# define RBIMPL_UNREACHABLE() __assume(0)
+#endif
+
+/** Wraps (or simulates) `__assume`. */
+#if RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0)
+# /* icc warnings are false positives. Ignore them. */
+# /* "warning #2261: __assume expression with side effects discarded" */
+# define RBIMPL_ASSUME(expr) \
+ RBIMPL_WARNING_PUSH() \
+ RBIMPL_WARNING_IGNORED(2261) \
+ __assume(expr) \
+ RBIMPL_WARNING_POP()
+
+#elif defined(RBIMPL_HAVE___ASSUME)
+# define RBIMPL_ASSUME __assume
+
+#elif RBIMPL_HAS_BUILTIN(__builtin_assume)
+# define RBIMPL_ASSUME __builtin_assume
+
+#elif ! defined(RBIMPL_UNREACHABLE)
+# define RBIMPL_ASSUME(_) RBIMPL_CAST((void)(_))
+
+#else
+# define RBIMPL_ASSUME(_) \
+ (RB_LIKELY(!!(_)) ? RBIMPL_CAST((void)0) : RBIMPL_UNREACHABLE())
+#endif
+
+#if ! defined(RBIMPL_UNREACHABLE)
+# define RBIMPL_UNREACHABLE() RBIMPL_ASSUME(0)
+#endif
+
+#endif /* RBIMPL_ASSUME_H */
diff --git a/include/ruby/internal/attr/alloc_size.h b/include/ruby/internal/attr/alloc_size.h
new file mode 100644
index 0000000000..ea96feec99
--- /dev/null
+++ b/include/ruby/internal/attr/alloc_size.h
@@ -0,0 +1,32 @@
+#ifndef RBIMPL_ATTR_ALLOC_SIZE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_ALLOC_SIZE_H
+/**
+ * @file
+ * @author Ruby developers <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_ALLOC_SIZE.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((alloc_size))` */
+#if RBIMPL_HAS_ATTRIBUTE(alloc_size)
+# define RBIMPL_ATTR_ALLOC_SIZE(tuple) __attribute__((__alloc_size__ tuple))
+#else
+# define RBIMPL_ATTR_ALLOC_SIZE(tuple) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_ALLOC_SIZE_H */
diff --git a/include/ruby/internal/attr/artificial.h b/include/ruby/internal/attr/artificial.h
new file mode 100644
index 0000000000..fa9a3814cc
--- /dev/null
+++ b/include/ruby/internal/attr/artificial.h
@@ -0,0 +1,46 @@
+#ifndef RBIMPL_ATTR_ARTIFICIAL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_ARTIFICIAL_H
+/**
+ * @file
+ * @author Ruby developers <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_ARTIFICIAL.
+ *
+ * ### Q&A ###
+ *
+ * - Q: What is this attribute? I don't get what GCC manual is talking about.
+ *
+ * - A: In short it is an attribute to manipulate GDB backtraces. The
+ * attribute makes the best sense when it comes with
+ * __attribute__((always_inline)). When a function annotated with this
+ * attribute gets inlined, and when you somehow look at a backtrace which
+ * includes such inlined call site, then the backtrace shows the caller
+ * and not the callee. This is handy for instance when an identical
+ * function is inlined more than once in a single big function. On such
+ * case it gets vital to know where the inlining happened in the callee.
+ * See also https://stackoverflow.com/a/21936099
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((artificial))` */
+#if RBIMPL_HAS_ATTRIBUTE(artificial)
+# define RBIMPL_ATTR_ARTIFICIAL() __attribute__((__artificial__))
+#else
+# define RBIMPL_ATTR_ARTIFICIAL() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_ARTIFICIAL_H */
diff --git a/include/ruby/internal/attr/cold.h b/include/ruby/internal/attr/cold.h
new file mode 100644
index 0000000000..fcee507456
--- /dev/null
+++ b/include/ruby/internal/attr/cold.h
@@ -0,0 +1,37 @@
+#ifndef RBIMPL_ATTR_COLD_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_COLD_H
+/**
+ * @file
+ * @author Ruby developers <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_COLD.
+ */
+#include "ruby/internal/compiler_is.h"
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((cold))` */
+#if RBIMPL_COMPILER_IS(SunPro)
+# /* Recent SunPro has __has_attribute, and is borken. */
+# /* It reports it has attribute cold, reality isn't (warnings issued). */
+# define RBIMPL_ATTR_COLD() /* void */
+#elif RBIMPL_HAS_ATTRIBUTE(cold)
+# define RBIMPL_ATTR_COLD() __attribute__((__cold__))
+#else
+# define RBIMPL_ATTR_COLD() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_COLD_H */
diff --git a/include/ruby/internal/attr/const.h b/include/ruby/internal/attr/const.h
new file mode 100644
index 0000000000..d5b8da0c2d
--- /dev/null
+++ b/include/ruby/internal/attr/const.h
@@ -0,0 +1,46 @@
+#ifndef RBIMPL_ATTR_CONST_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_CONST_H
+/**
+ * @file
+ * @author Ruby developers <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_CONST.
+ */
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/has/declspec_attribute.h"
+
+/** Wraps (or simulates) `__attribute__((const))` */
+#if RBIMPL_HAS_ATTRIBUTE(const)
+# define RBIMPL_ATTR_CONST() __attribute__((__const__))
+#elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias)
+# /* If a function can be a const, that is also a noalias. */
+# define RBIMPL_ATTR_CONST() __declspec(noalias)
+#elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0)
+# define RBIMPL_ATTR_CONST() _Pragma("no_side_effect")
+#else
+# define RBIMPL_ATTR_CONST() /* void */
+#endif
+
+/** Enables #RBIMPL_ATTR_CONST iff. ! #RUBY_DEBUG. */
+#if !RUBY_DEBUG
+# define RBIMPL_ATTR_CONST_UNLESS_DEBUG() RBIMPL_ATTR_CONST()
+#else
+# define RBIMPL_ATTR_CONST_UNLESS_DEBUG() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_CONST_H */
diff --git a/include/ruby/internal/attr/constexpr.h b/include/ruby/internal/attr/constexpr.h
new file mode 100644
index 0000000000..96b010ce6f
--- /dev/null
+++ b/include/ruby/internal/attr/constexpr.h
@@ -0,0 +1,85 @@
+#ifndef RBIMPL_ATTR_CONSTEXPR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_CONSTEXPR_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 #RBIMPL_ATTR_CONSTEXPR.
+ */
+#include "ruby/internal/has/feature.h"
+#include "ruby/internal/compiler_is.h"
+#include "ruby/internal/token_paste.h"
+
+/** @cond INTERNAL_MACRO */
+#if ! defined(__cplusplus)
+# /* Makes no sense. */
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 0
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0
+
+#elif defined(__cpp_constexpr)
+# /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cpp_constexpr >= 200704L)
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cpp_constexpr >= 201304L)
+
+#elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0)
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 00)
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 00)
+
+#elif RBIMPL_COMPILER_SINCE(SunPro, 5, 13, 0)
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cplusplus >= 201103L)
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cplusplus >= 201402L)
+
+#elif RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0)
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 (__cplusplus >= 201103L)
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 (__cplusplus >= 201402L)
+
+#elif RBIMPL_HAS_FEATURE(cxx_relaxed_constexpr)
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 1
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 1
+
+#elif RBIMPL_HAS_FEATURE(cxx_constexpr)
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 1
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0
+
+#else
+# /* :FIXME: icpc must have constexpr but don't know how to detect. */
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX11 0
+# define RBIMPL_HAS_ATTR_CONSTEXPR_CXX14 0
+#endif
+/** @endcond */
+
+/** Wraps (or simulates) C++11 `constexpr`. */
+#if RBIMPL_HAS_ATTR_CONSTEXPR_CXX14
+# define RBIMPL_ATTR_CONSTEXPR(_) constexpr
+
+#elif RBIMPL_HAS_ATTR_CONSTEXPR_CXX11
+# define RBIMPL_ATTR_CONSTEXPR(_) RBIMPL_TOKEN_PASTE(RBIMPL_ATTR_CONSTEXPR_, _)
+# define RBIMPL_ATTR_CONSTEXPR_CXX11 constexpr
+# define RBIMPL_ATTR_CONSTEXPR_CXX14 /* void */
+
+#else
+# define RBIMPL_ATTR_CONSTEXPR(_) /* void */
+#endif
+
+/** Enables #RBIMPL_ATTR_CONSTEXPR iff. ! #RUBY_DEBUG. */
+#if !RUBY_DEBUG
+# define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_) RBIMPL_ATTR_CONSTEXPR(_)
+#else
+# define RBIMPL_ATTR_CONSTEXPR_UNLESS_DEBUG(_) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_CONSTEXPR_H */
diff --git a/include/ruby/internal/attr/deprecated.h b/include/ruby/internal/attr/deprecated.h
new file mode 100644
index 0000000000..38a7deeaaa
--- /dev/null
+++ b/include/ruby/internal/attr/deprecated.h
@@ -0,0 +1,63 @@
+#ifndef RBIMPL_ATTR_DEPRECATED_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_DEPRECATED_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_DEPRECATED.
+ */
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/has/c_attribute.h"
+#include "ruby/internal/has/cpp_attribute.h"
+#include "ruby/internal/has/declspec_attribute.h"
+#include "ruby/internal/has/extension.h"
+
+/** Wraps (or simulates) `[[deprecated]]` */
+#if RBIMPL_HAS_EXTENSION(attribute_deprecated_with_message)
+# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
+
+#elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(GCC, 10, 1, 0) /* && RBIMPL_COMPILER_BEFORE(GCC, 10, X, Y) */
+# /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95302 */
+# define RBIMPL_ATTR_DEPRECATED(msg) /* disable until they fix this bug */
+
+#elif RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0)
+# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
+
+#elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0)
+# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__ msg))
+
+#elif RBIMPL_HAS_ATTRIBUTE(deprecated) /* but not with message. */
+# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__))
+
+#elif RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0)
+# define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated msg)
+
+#elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(deprecated)
+# define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated)
+
+#elif RBIMPL_HAS_CPP_ATTRIBUTE(deprecated)
+# define RBIMPL_ATTR_DEPRECATED(msg) [[deprecated msg]]
+
+#elif RBIMPL_HAS_C_ATTRIBUTE(deprecated)
+# define RBIMPL_ATTR_DEPRECATED(msg) [[deprecated msg]]
+
+#else
+# define RBIMPL_ATTR_DEPRECATED(msg) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_DEPRECATED_H */
diff --git a/include/ruby/internal/attr/diagnose_if.h b/include/ruby/internal/attr/diagnose_if.h
new file mode 100644
index 0000000000..6a79e904b7
--- /dev/null
+++ b/include/ruby/internal/attr/diagnose_if.h
@@ -0,0 +1,42 @@
+#ifndef RBIMPL_ATTR_DIAGNOSE_IF_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_DIAGNOSE_IF_H
+/**
+ * @file
+ * @author Ruby developers <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_DIAGNOSE_IF.
+ */
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/warning_push.h"
+
+/** Wraps (or simulates) `__attribute__((diagnose_if))` */
+#if RBIMPL_COMPILER_BEFORE(Clang, 5, 0, 0)
+# /* https://bugs.llvm.org/show_bug.cgi?id=34319 */
+# define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) /* void */
+
+#elif RBIMPL_HAS_ATTRIBUTE(diagnose_if)
+# define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) \
+ RBIMPL_WARNING_PUSH() \
+ RBIMPL_WARNING_IGNORED(-Wgcc-compat) \
+ __attribute__((__diagnose_if__(_, __, ___))) \
+ RBIMPL_WARNING_POP()
+
+#else
+# define RBIMPL_ATTR_DIAGNOSE_IF(_, __, ___) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_DIAGNOSE_IF_H */
diff --git a/include/ruby/internal/attr/enum_extensibility.h b/include/ruby/internal/attr/enum_extensibility.h
new file mode 100644
index 0000000000..6faa58185a
--- /dev/null
+++ b/include/ruby/internal/attr/enum_extensibility.h
@@ -0,0 +1,32 @@
+#ifndef RBIMPL_ATTR_ENUM_EXTENSIBILITY_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_ENUM_EXTENSIBILITY_H
+/**
+ * @file
+ * @author Ruby developers <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 #RBIMPL_ATTR_ENUM_EXTENSIBILITY.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((enum_extensibility))` */
+#if RBIMPL_HAS_ATTRIBUTE(enum_extensibility)
+# define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_) __attribute__((__enum_extensibility__(_)))
+#else
+# define RBIMPL_ATTR_ENUM_EXTENSIBILITY(_) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_ENUM_EXTENSIBILITY_H */
diff --git a/include/ruby/internal/attr/error.h b/include/ruby/internal/attr/error.h
new file mode 100644
index 0000000000..da19b73c2b
--- /dev/null
+++ b/include/ruby/internal/attr/error.h
@@ -0,0 +1,32 @@
+#ifndef RBIMPL_ATTR_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_ERROR_H
+/**
+ * @file
+ * @author Ruby developers <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_ERROR.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((error))` */
+#if RBIMPL_HAS_ATTRIBUTE(error)
+# define RBIMPL_ATTR_ERROR(msg) __attribute__((__error__ msg))
+#else
+# define RBIMPL_ATTR_ERROR(msg) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_ERROR_H */
diff --git a/include/ruby/internal/attr/flag_enum.h b/include/ruby/internal/attr/flag_enum.h
new file mode 100644
index 0000000000..148384d842
--- /dev/null
+++ b/include/ruby/internal/attr/flag_enum.h
@@ -0,0 +1,33 @@
+#ifndef RBIMPL_ATTR_FLAG_ENUM_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_FLAG_ENUM_H
+/**
+ * @file
+ * @author Ruby developers <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_FLAG_ENUM.
+ * @see https://clang.llvm.org/docs/AttributeReference.html#flag_enum
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((flag_enum)` */
+#if RBIMPL_HAS_ATTRIBUTE(flag_enum)
+# define RBIMPL_ATTR_FLAG_ENUM() __attribute__((__flag_enum__))
+#else
+# define RBIMPL_ATTR_FLAG_ENUM() /* void */
+#endif
+
+#endif /* RBIMPLATTR_FLAG_ENUM_H */
diff --git a/include/ruby/internal/attr/forceinline.h b/include/ruby/internal/attr/forceinline.h
new file mode 100644
index 0000000000..6b31f1016f
--- /dev/null
+++ b/include/ruby/internal/attr/forceinline.h
@@ -0,0 +1,40 @@
+#ifndef RBIMPL_ATTR_FORCEINLINE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_FORCEINLINE_H
+/**
+ * @file
+ * @author Ruby developers <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_FORCEINLINE.
+ */
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/attribute.h"
+
+/**
+ * Wraps (or simulates) `__forceinline`. MSVC complains on declarations like
+ * `static inline __forceinline void foo()`. It seems MSVC's `inline` and
+ * `__forceinline` are mutually exclusive. We have to mimic that behaviour for
+ * non-MSVC compilers.
+ */
+#if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0)
+# define RBIMPL_ATTR_FORCEINLINE() __forceinline
+#elif RBIMPL_HAS_ATTRIBUTE(always_inline)
+# define RBIMPL_ATTR_FORCEINLINE() __attribute__((__always_inline__)) inline
+#else
+# define RBIMPL_ATTR_FORCEINLINE() inline
+#endif
+
+#endif /* RBIMPL_ATTR_FORCEINLINE_H */
diff --git a/include/ruby/internal/attr/format.h b/include/ruby/internal/attr/format.h
new file mode 100644
index 0000000000..fcbf7b6cfe
--- /dev/null
+++ b/include/ruby/internal/attr/format.h
@@ -0,0 +1,38 @@
+#ifndef RBIMPL_ATTR_FORMAT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_FORMAT_H
+/**
+ * @file
+ * @author Ruby developers <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_FORMAT.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((format))` */
+#if RBIMPL_HAS_ATTRIBUTE(format)
+# define RBIMPL_ATTR_FORMAT(x, y, z) __attribute__((__format__(x, y, z)))
+#else
+# define RBIMPL_ATTR_FORMAT(x, y, z) /* void */
+#endif
+
+#if defined(__MINGW_PRINTF_FORMAT)
+# define RBIMPL_PRINTF_FORMAT __MINGW_PRINTF_FORMAT
+#else
+# define RBIMPL_PRINTF_FORMAT __printf__
+#endif
+
+#endif /* RBIMPL_ATTR_FORMAT_H */
diff --git a/include/ruby/internal/attr/maybe_unused.h b/include/ruby/internal/attr/maybe_unused.h
new file mode 100644
index 0000000000..f46d1bc670
--- /dev/null
+++ b/include/ruby/internal/attr/maybe_unused.h
@@ -0,0 +1,38 @@
+#ifndef RBIMPL_ATTR_MAYBE_UNUSED_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_MAYBE_UNUSED_H
+/**
+ * @file
+ * @author Ruby developers <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_MAYBE_UNUSED.
+ */
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/has/c_attribute.h"
+#include "ruby/internal/has/cpp_attribute.h"
+
+/** Wraps (or simulates) `[[maybe_unused]]` */
+#if RBIMPL_HAS_CPP_ATTRIBUTE(maybe_unused)
+# define RBIMPL_ATTR_MAYBE_UNUSED() [[maybe_unused]]
+#elif RBIMPL_HAS_C_ATTRIBUTE(maybe_unused)
+# define RBIMPL_ATTR_MAYBE_UNUSED() [[maybe_unused]]
+#elif RBIMPL_HAS_ATTRIBUTE(unused)
+# define RBIMPL_ATTR_MAYBE_UNUSED() __attribute__((__unused__))
+#else
+# define RBIMPL_ATTR_MAYBE_UNUSED() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_MAYBE_UNUSED */
diff --git a/include/ruby/internal/attr/noalias.h b/include/ruby/internal/attr/noalias.h
new file mode 100644
index 0000000000..63324b7184
--- /dev/null
+++ b/include/ruby/internal/attr/noalias.h
@@ -0,0 +1,58 @@
+#ifndef RBIMPL_ATTR_NOALIAS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_NOALIAS_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_NOALIAS.
+ *
+ * ### Q&A ###
+ *
+ * - Q: There are seemingly similar attributes named #RBIMPL_ATTR_CONST,
+ * #RBIMPL_ATTR_PURE, and #RBIMPL_ATTR_NOALIAS. What are the difference?
+ *
+ * - A: Allowed operations are different.
+ *
+ * - #RBIMPL_ATTR_CONST ... Functions attributed by this are not allowed to
+ * read/write _any_ pointers at all (there are exceptional situations
+ * when reading a pointer is possible but forget that; they are too
+ * exceptional to be useful). Just remember that everything pointer-
+ * related are NG.
+ *
+ * - #RBIMPL_ATTR_PURE ... Functions attributed by this can read any
+ * nonvolatile pointers, but no writes are allowed at all. The ability
+ * to read _any_ nonvolatile pointers makes it possible to mark ::VALUE-
+ * taking functions as being pure, as long as they are read-only.
+ *
+ * - #RBIMPL_ATTR_NOALIAS ... Can both read/write, but only through
+ * pointers passed to the function as parameters. This is a typical
+ * situation when you create a C++ non-static member function which only
+ * concerns `this`. No global variables are allowed to read/write. So
+ * this is not a super-set of being pure. If you want to read something,
+ * that has to be passed to the function as a pointer. ::VALUE -taking
+ * functions thus cannot be attributed as such.
+ */
+#include "ruby/internal/has/declspec_attribute.h"
+
+/** Wraps (or simulates) `__declspec((noalias))` */
+#if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noalias)
+# define RBIMPL_ATTR_NOALIAS() __declspec(noalias)
+#else
+# define RBIMPL_ATTR_NOALIAS() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_NOALIAS_H */
diff --git a/include/ruby/internal/attr/nodiscard.h b/include/ruby/internal/attr/nodiscard.h
new file mode 100644
index 0000000000..5fd71b1c23
--- /dev/null
+++ b/include/ruby/internal/attr/nodiscard.h
@@ -0,0 +1,45 @@
+#ifndef RBIMPL_ATTR_NODISCARD_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_NODISCARD_H
+/**
+ * @file
+ * @author Ruby developers <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_NODISCARD.
+ */
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/has/c_attribute.h"
+#include "ruby/internal/has/cpp_attribute.h"
+
+/**
+ * Wraps (or simulates) `[[nodiscard]]`. In C++ (at least since C++20) a
+ * nodiscard attribute can have a message why the result shall not be ignoed.
+ * However GCC attribute and SAL annotation cannot take them.
+ */
+#if RBIMPL_HAS_CPP_ATTRIBUTE(nodiscard)
+# define RBIMPL_ATTR_NODISCARD() [[nodiscard]]
+#elif RBIMPL_HAS_C_ATTRIBUTE(nodiscard)
+# define RBIMPL_ATTR_NODISCARD() [[nodiscard]]
+#elif RBIMPL_HAS_ATTRIBUTE(warn_unused_result)
+# define RBIMPL_ATTR_NODISCARD() __attribute__((__warn_unused_result__))
+#elif defined(_Check_return_)
+# /* Take SAL definition. */
+# define RBIMPL_ATTR_NODISCARD() _Check_return_
+#else
+# define RBIMPL_ATTR_NODISCARD() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_NODISCARD_H */
diff --git a/include/ruby/internal/attr/noexcept.h b/include/ruby/internal/attr/noexcept.h
new file mode 100644
index 0000000000..968a7742b9
--- /dev/null
+++ b/include/ruby/internal/attr/noexcept.h
@@ -0,0 +1,91 @@
+#ifndef RBIMPL_ATTR_NOEXCEPT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_NOEXCEPT_H
+/**
+ * @file
+ * @author Ruby developers <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_NOEXCEPT.
+ *
+ * This isn't actually an attribute in C++ but who cares...
+ *
+ * Mainly due to aesthetic reasons, this one is rarely used in the project.
+ * But can be handy on occasions, especially when a function's noexcept-ness
+ * depends on its calling functions.
+ *
+ * ### Q&A ###
+ *
+ * - Q: Can a function that raises Ruby exceptions be attributed `noexcept`?
+ *
+ * - A: Yes. `noexcept` is about C++ exceptions, not Ruby's. They don't
+ * interface each other. You can safely attribute a function that raises
+ * Ruby exceptions as `noexcept`.
+ *
+ * - Q: How, then, can I assert that a function I wrote doesn't raise any Ruby
+ * exceptions?
+ *
+ * - A: `__attribute__((__leaf__))` is for that purpose. A function attributed
+ * as leaf can still throw C++ exceptions, but not Ruby's. Note however,
+ * that it's extremely difficult -- if not impossible -- to assert that a
+ * function doesn't raise any Ruby exceptions at all. Use of that
+ * attribute is not recommended; mere mortals can't properly use that by
+ * hand.
+ *
+ * - Q: Does it make sense to attribute an inline function `noexcept`?
+ *
+ * - A: I thought so before. But no, I don't think they are useful any longer.
+ *
+ * - When an inline function attributed `noexcept` actually doesn't throw
+ * any exceptions at all: these days I don't see any difference in
+ * generated assembly by adding/removing this attribute. C++ compilers
+ * get smarter and smarter. Today they can infer if it actually throws
+ * or not without any annotations by humans (correct me if I'm wrong).
+ *
+ * - When an inline function attributed `noexcepr` actually _does_ throw an
+ * exception: they have to call `std::terminate` then (C++ standard
+ * mandates so). This means exception handling routines are actually
+ * enforced, not omitted. This doesn't impact runtime performance (The
+ * Itanium C++ ABI has zero-cost exception handling), but does impact on
+ * generated binary size. This is bad.
+ */
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/feature.h"
+
+/** Wraps (or simulates) C++11 `noexcept` */
+#if ! defined(__cplusplus)
+# /* Doesn't make sense. */
+# define RBIMPL_ATTR_NOEXCEPT(_) /* void */
+
+#elif RBIMPL_HAS_FEATURE(cxx_noexcept)
+# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_))
+
+#elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__
+# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_))
+
+#elif defined(__INTEL_CXX11_MODE__)
+# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_))
+
+#elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0)
+# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_))
+
+#elif __cplusplus >= 201103L
+# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_))
+
+#else
+# define RBIMPL_ATTR_NOEXCEPT(_) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_NOEXCEPT_H */
diff --git a/include/ruby/internal/attr/noinline.h b/include/ruby/internal/attr/noinline.h
new file mode 100644
index 0000000000..619f99a171
--- /dev/null
+++ b/include/ruby/internal/attr/noinline.h
@@ -0,0 +1,35 @@
+#ifndef RBIMPL_ATTR_NOINLINE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_NOINLINE_H
+/**
+ * @file
+ * @author Ruby developers <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_NOINLINE.
+ */
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/has/declspec_attribute.h"
+
+/** Wraps (or simulates) `__declspec(noinline)` */
+#if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noinline)
+# define RBIMPL_ATTR_NOINLINE() __declspec(noinline)
+#elif RBIMPL_HAS_ATTRIBUTE(noinline)
+# define RBIMPL_ATTR_NOINLINE() __attribute__((__noinline__))
+#else
+# define RBIMPL_ATTR_NOINLINE() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_NOINLINE_H */
diff --git a/include/ruby/internal/attr/nonnull.h b/include/ruby/internal/attr/nonnull.h
new file mode 100644
index 0000000000..cfced0bf74
--- /dev/null
+++ b/include/ruby/internal/attr/nonnull.h
@@ -0,0 +1,32 @@
+#ifndef RBIMPL_ATTR_NONNULL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_NONNULL_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_NONNULL.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((nonnull))` */
+#if RBIMPL_HAS_ATTRIBUTE(nonnull)
+# define RBIMPL_ATTR_NONNULL(list) __attribute__((__nonnull__ list))
+#else
+# define RBIMPL_ATTR_NONNULL(list) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_NONNULL_H */
diff --git a/include/ruby/internal/attr/noreturn.h b/include/ruby/internal/attr/noreturn.h
new file mode 100644
index 0000000000..f741167c12
--- /dev/null
+++ b/include/ruby/internal/attr/noreturn.h
@@ -0,0 +1,48 @@
+#ifndef RBIMPL_ATTR_NORETURN_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_NORETURN_H
+/**
+ * @file
+ * @author Ruby developers <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_NORETURN.
+ */
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/has/cpp_attribute.h"
+#include "ruby/internal/has/declspec_attribute.h"
+
+/** Wraps (or simulates) `[[noreturn]]` */
+#if RBIMPL_HAS_DECLSPEC_ATTRIBUTE(noreturn)
+# define RBIMPL_ATTR_NORETURN() __declspec(noreturn)
+
+#elif RBIMPL_HAS_ATTRIBUTE(noreturn)
+# define RBIMPL_ATTR_NORETURN() __attribute__((__noreturn__))
+
+#elif RBIMPL_HAS_CPP_ATTRIBUTE(noreturn)
+# define RBIMPL_ATTR_NORETURN() [[noreturn]]
+
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112)
+# define RBIMPL_ATTR_NORETURN() _Noreturn
+
+#elif defined(_Noreturn)
+# /* glibc <sys/cdefs.h> has this macro. */
+# define RBIMPL_ATTR_NORETURN() _Noreturn
+
+#else
+# define RBIMPL_ATTR_NORETURN() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_NORETURN_H */
diff --git a/include/ruby/internal/attr/pure.h b/include/ruby/internal/attr/pure.h
new file mode 100644
index 0000000000..1a10540ef3
--- /dev/null
+++ b/include/ruby/internal/attr/pure.h
@@ -0,0 +1,43 @@
+#ifndef RBIMPL_ATTR_PURE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_PURE_H
+/**
+ * @file
+ * @author Ruby developers <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_PURE.
+ */
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/attribute.h"
+#include "ruby/assert.h"
+
+/** Wraps (or simulates) `__attribute__((pure))` */
+#if RBIMPL_HAS_ATTRIBUTE(pure)
+# define RBIMPL_ATTR_PURE() __attribute__((__pure__))
+#elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0)
+# define RBIMPL_ATTR_PURE() _Pragma("does_not_write_global_data")
+#else
+# define RBIMPL_ATTR_PURE() /* void */
+#endif
+
+/** Enables #RBIMPL_ATTR_PURE iff. ! #RUBY_DEBUG. */
+#if !RUBY_DEBUG
+# define RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_PURE()
+#else
+# define RBIMPL_ATTR_PURE_UNLESS_DEBUG() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_PURE_H */
diff --git a/include/ruby/internal/attr/restrict.h b/include/ruby/internal/attr/restrict.h
new file mode 100644
index 0000000000..3f4b7db165
--- /dev/null
+++ b/include/ruby/internal/attr/restrict.h
@@ -0,0 +1,45 @@
+#ifndef RBIMPL_ATTR_RESTRICT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_RESTRICT_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_RESTRICT.
+ */
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/token_paste.h"
+
+/* :FIXME: config.h includes conflicting `#define restrict`. MSVC can be
+ * detected using `RBIMPL_COMPILER_SINCE()`, but Clang & family cannot use
+ * `__has_declspec_attribute()` which involves macro substitution. */
+
+/** Wraps (or simulates) `__declspec(restrict)` */
+#if RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0)
+# define RBIMPL_ATTR_RESTRICT() __declspec(RBIMPL_TOKEN_PASTE(re, strict))
+
+#elif RBIMPL_HAS_ATTRIBUTE(malloc)
+# define RBIMPL_ATTR_RESTRICT() __attribute__((__malloc__))
+
+#elif RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0)
+# define RBIMPL_ATTR_RESTRICT() _Pragma("returns_new_memory")
+
+#else
+# define RBIMPL_ATTR_RESTRICT() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_RESTRICT_H */
diff --git a/include/ruby/internal/attr/returns_nonnull.h b/include/ruby/internal/attr/returns_nonnull.h
new file mode 100644
index 0000000000..91c7be15cd
--- /dev/null
+++ b/include/ruby/internal/attr/returns_nonnull.h
@@ -0,0 +1,37 @@
+#ifndef RBIMPL_ATTR_RETURNS_NONNULL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_RETURNS_NONNULL_H
+/**
+ * @file
+ * @author Ruby developers <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_RETURNS_NONNULL.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((returns_nonnull))` */
+#if defined(_Ret_nonnull_)
+# /* Take SAL definition. */
+# define RBIMPL_ATTR_RETURNS_NONNULL() _Ret_nonnull_
+
+#elif RBIMPL_HAS_ATTRIBUTE(returns_nonnull)
+# define RBIMPL_ATTR_RETURNS_NONNULL() __attribute__((__returns_nonnull__))
+
+#else
+# define RBIMPL_ATTR_RETURNS_NONNULL() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_RETURNS_NONNULL_H */
diff --git a/include/ruby/internal/attr/warning.h b/include/ruby/internal/attr/warning.h
new file mode 100644
index 0000000000..fb6b214828
--- /dev/null
+++ b/include/ruby/internal/attr/warning.h
@@ -0,0 +1,32 @@
+#ifndef RBIMPL_ATTR_WARNING_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_WARNING_H
+/**
+ * @file
+ * @author Ruby developers <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_WARNING.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((warning))` */
+#if RBIMPL_HAS_ATTRIBUTE(warning)
+# define RBIMPL_ATTR_WARNING(msg) __attribute__((__warning__ msg))
+#else
+# define RBIMPL_ATTR_WARNING(msg) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_WARNING_H */
diff --git a/include/ruby/internal/attr/weakref.h b/include/ruby/internal/attr/weakref.h
new file mode 100644
index 0000000000..59dba678fa
--- /dev/null
+++ b/include/ruby/internal/attr/weakref.h
@@ -0,0 +1,32 @@
+#ifndef RBIMPL_ATTR_WEAKREF_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_WEAKREF_H
+/**
+ * @file
+ * @author Ruby developers <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_WEAKREF.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((weakref))` */
+#if RBIMPL_HAS_ATTRIBUTE(weakref)
+# define RBIMPL_ATTR_WEAKREF(sym) __attribute__((__weakref__(# sym)))
+#else
+# define RBIMPL_ATTR_WEAKREF(sym) /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_WEAKREF_H */
diff --git a/include/ruby/internal/cast.h b/include/ruby/internal/cast.h
new file mode 100644
index 0000000000..065a5d01c2
--- /dev/null
+++ b/include/ruby/internal/cast.h
@@ -0,0 +1,53 @@
+#ifndef RBIMPL_CAST_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_CAST_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_CAST.
+ * @cond INTERNAL_MACRO
+ *
+ * This casting macro makes sense only inside of other macros that are part of
+ * public headers. They could be used from C++, and C-style casts could issue
+ * warnings. Ruby internals are pure C so they should not bother.
+ */
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/warning.h"
+#include "ruby/internal/warning_push.h"
+
+#if ! defined(__cplusplus)
+# define RBIMPL_CAST(expr) (expr)
+
+#elif RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0)
+# /* g++ has -Wold-style-cast since 1997 or so, but its _Pragma is broken. */
+# /* See https://gcc.godbolt.org/z/XWhU6J */
+# define RBIMPL_CAST(expr) (expr)
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+
+#elif RBIMPL_HAS_WARNING("-Wold-style-cast")
+# define RBIMPL_CAST(expr) \
+ RBIMPL_WARNING_PUSH() \
+ RBIMPL_WARNING_IGNORED(-Wold-style-cast) \
+ (expr) \
+ RBIMPL_WARNING_POP()
+
+#else
+# define RBIMPL_CAST(expr) (expr)
+#endif
+/** @endcond */
+
+#endif /* RBIMPL_CAST_H */
diff --git a/include/ruby/internal/compiler_is.h b/include/ruby/internal/compiler_is.h
new file mode 100644
index 0000000000..776d7add4f
--- /dev/null
+++ b/include/ruby/internal/compiler_is.h
@@ -0,0 +1,45 @@
+#ifndef RBIMPL_COMPILER_IS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_COMPILER_IS_H
+/**
+ * @file
+ * @author Ruby developers <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_COMPILER_IS.
+ */
+
+/**
+ * @brief Checks if the compiler is of given brand.
+ * @param cc Compiler brand, like `MSVC`.
+ * @retval true It is.
+ * @retval false It isn't.
+ */
+#define RBIMPL_COMPILER_IS(cc) RBIMPL_COMPILER_IS_ ## cc
+
+#include "ruby/internal/compiler_is/apple.h"
+#include "ruby/internal/compiler_is/clang.h"
+#include "ruby/internal/compiler_is/gcc.h"
+#include "ruby/internal/compiler_is/intel.h"
+#include "ruby/internal/compiler_is/msvc.h"
+#include "ruby/internal/compiler_is/sunpro.h"
+/* :TODO: Other possible compilers to support:
+ *
+ * - IBM XL: recent XL are clang-backended so some tweaks like we do for
+ * Apple's might be needed.
+ *
+ * - ARM's armclang: ditto, it can be clang-backended. */
+
+#endif /* RBIMPL_COMPILER_IS_H */
diff --git a/include/ruby/internal/compiler_is/apple.h b/include/ruby/internal/compiler_is/apple.h
new file mode 100644
index 0000000000..5a5f558254
--- /dev/null
+++ b/include/ruby/internal/compiler_is/apple.h
@@ -0,0 +1,41 @@
+#ifndef RBIMPL_COMPILER_IS_APPLE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_COMPILER_IS_APPLE_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_COMPILER_IS_Apple.
+ *
+ * Apple ships clang. Problem is, its `__clang_major__` etc. are not the
+ * upstream LLVM version, but XCode's. We have to think Apple's is distinct
+ * from LLVM's, when it comes to compiler detection business in this header
+ * file.
+ */
+#if ! defined(__clang__)
+# define RBIMPL_COMPILER_IS_Apple 0
+
+#elif ! defined(__apple_build_version__)
+# define RBIMPL_COMPILER_IS_Apple 0
+
+#else
+# define RBIMPL_COMPILER_IS_Apple 1
+# define RBIMPL_COMPILER_VERSION_MAJOR __clang_major__
+# define RBIMPL_COMPILER_VERSION_MINOR __clang_minor__
+# define RBIMPL_COMPILER_VERSION_PATCH __clang_patchlevel__
+#endif
+
+#endif /* RBIMPL_COMPILER_IS_APPLE_H */
diff --git a/include/ruby/internal/compiler_is/clang.h b/include/ruby/internal/compiler_is/clang.h
new file mode 100644
index 0000000000..30655f2f25
--- /dev/null
+++ b/include/ruby/internal/compiler_is/clang.h
@@ -0,0 +1,38 @@
+#ifndef RBIMPL_COMPILER_IS_CLANG_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_COMPILER_IS_CLANG_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_COMPILER_IS_Clang.
+ */
+#include "ruby/internal/compiler_is/apple.h"
+
+#if ! defined(__clang__)
+# define RBIMPL_COMPILER_IS_Clang 0
+
+#elif RBIMPL_COMPILER_IS(Apple)
+# define RBIMPL_COMPILER_IS_Clang 0
+
+#else
+# define RBIMPL_COMPILER_IS_Clang 1
+# define RBIMPL_COMPILER_VERSION_MAJOR __clang_major__
+# define RBIMPL_COMPILER_VERSION_MINOR __clang_minor__
+# define RBIMPL_COMPILER_VERSION_PATCH __clang_patchlevel__
+#endif
+
+#endif /* RBIMPL_COMPILER_IS_CLANG_H */
diff --git a/include/ruby/internal/compiler_is/gcc.h b/include/ruby/internal/compiler_is/gcc.h
new file mode 100644
index 0000000000..6eabfb61a2
--- /dev/null
+++ b/include/ruby/internal/compiler_is/gcc.h
@@ -0,0 +1,46 @@
+#ifndef RBIMPL_COMPILER_IS_GCC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_COMPILER_IS_GCC_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_COMPILER_IS_GCC.
+ */
+#include "ruby/internal/compiler_is/apple.h"
+#include "ruby/internal/compiler_is/clang.h"
+#include "ruby/internal/compiler_is/intel.h"
+
+#if ! defined(__GNUC__)
+# define RBIMPL_COMPILER_IS_GCC 0
+
+#elif RBIMPL_COMPILER_IS(Apple)
+# define RBIMPL_COMPILER_IS_GCC 0
+
+#elif RBIMPL_COMPILER_IS(Clang)
+# define RBIMPL_COMPILER_IS_GCC 0
+
+#elif RBIMPL_COMPILER_IS(Intel)
+# define RBIMPL_COMPILER_IS_GCC 0
+
+#else
+# define RBIMPL_COMPILER_IS_GCC 1
+# define RBIMPL_COMPILER_VERSION_MAJOR __GNUC__
+# define RBIMPL_COMPILER_VERSION_MINOR __GNUC_MINOR__
+# define RBIMPL_COMPILER_VERSION_PATCH __GNUC_PATCHLEVEL__
+#endif
+
+#endif /* RBIMPL_COMPILER_IS_GCC_H */
diff --git a/include/ruby/internal/compiler_is/intel.h b/include/ruby/internal/compiler_is/intel.h
new file mode 100644
index 0000000000..ada120485e
--- /dev/null
+++ b/include/ruby/internal/compiler_is/intel.h
@@ -0,0 +1,41 @@
+#ifndef RBIMPL_COMPILER_IS_INTEL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_COMPILER_IS_INTEL_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_COMPILER_IS_Intel.
+ */
+#if ! defined(__INTEL_COMPILER)
+# define RBIMPL_COMPILER_IS_Intel 0
+
+#elif ! defined(__INTEL_COMPILER_UPDATE)
+# define RBIMPL_COMPILER_IS_Intel 1
+# /* __INTEL_COMPILER = XXYZ */
+# define RBIMPL_COMPILER_VERSION_MAJOR (__INTEL_COMPILER / 100)
+# define RBIMPL_COMPILER_VERSION_MINOR (__INTEL_COMPILER % 100 / 10)
+# define RBIMPL_COMPILER_VERSION_PATCH (__INTEL_COMPILER % 10)
+
+#else
+# define RBIMPL_COMPILER_IS_Intel 1
+# /* __INTEL_COMPILER = XXYZ */
+# define RBIMPL_COMPILER_VERSION_MAJOR (__INTEL_COMPILER / 100)
+# define RBIMPL_COMPILER_VERSION_MINOR (__INTEL_COMPILER % 100 / 10)
+# define RBIMPL_COMPILER_VERSION_PATCH __INTEL_COMPILER_UPDATE
+#endif
+
+#endif /* RBIMPL_COMPILER_IS_INTEL_H */
diff --git a/include/ruby/internal/compiler_is/msvc.h b/include/ruby/internal/compiler_is/msvc.h
new file mode 100644
index 0000000000..60189da1a3
--- /dev/null
+++ b/include/ruby/internal/compiler_is/msvc.h
@@ -0,0 +1,57 @@
+#ifndef RBIMPL_COMPILER_IS_MSVC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_COMPILER_IS_MSVC_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_COMPILER_IS_MSVC.
+ */
+#include "ruby/internal/compiler_is/clang.h"
+#include "ruby/internal/compiler_is/intel.h"
+
+#if ! defined(_MSC_VER)
+# define RBIMPL_COMPILER_IS_MSVC 0
+
+#elif RBIMPL_COMPILER_IS(Clang)
+# define RBIMPL_COMPILER_IS_MSVC 0
+
+#elif RBIMPL_COMPILER_IS(Intel)
+# define RBIMPL_COMPILER_IS_MSVC 0
+
+#elif _MSC_VER >= 1400
+# define RBIMPL_COMPILER_IS_MSVC 1
+# /* _MSC_FULL_VER = XXYYZZZZZ */
+# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 10000000)
+# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 10000000 / 100000)
+# define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 100000)
+
+#elif defined(_MSC_FULL_VER)
+# define RBIMPL_COMPILER_IS_MSVC 1
+# /* _MSC_FULL_VER = XXYYZZZZ */
+# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_FULL_VER / 1000000)
+# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_FULL_VER % 1000000 / 10000)
+# define RBIMPL_COMPILER_VERSION_PATCH (_MSC_FULL_VER % 10000)
+
+#else
+# define RBIMPL_COMPILER_IS_MSVC 1
+# /* _MSC_VER = XXYY */
+# define RBIMPL_COMPILER_VERSION_MAJOR (_MSC_VER / 100)
+# define RBIMPL_COMPILER_VERSION_MINOR (_MSC_VER % 100)
+# define RBIMPL_COMPILER_VERSION_PATCH 0
+#endif
+
+#endif /* RBIMPL_COMPILER_IS_MSVC_H */
diff --git a/include/ruby/internal/compiler_is/sunpro.h b/include/ruby/internal/compiler_is/sunpro.h
new file mode 100644
index 0000000000..2eb7b892f2
--- /dev/null
+++ b/include/ruby/internal/compiler_is/sunpro.h
@@ -0,0 +1,55 @@
+#ifndef RBIMPL_COMPILER_IS_SUNPRO_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_COMPILER_IS_SUNPRO_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_COMPILER_IS_SunPro.
+ */
+#if ! (defined(__SUNPRO_C) || defined(__SUNPRO_CC))
+# define RBIMPL_COMPILER_IS_SunPro 0
+
+#elif defined(__SUNPRO_C) && __SUNPRO_C >= 0x5100
+# define RBIMPL_COMPILER_IS_SunPro 1
+# /* __SUNPRO_C = 0xXYYZ */
+# define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_C >> 12)
+# define RBIMPL_COMPILER_VERSION_MINOR ((__SUNPRO_C >> 8 & 0xF) * 10 + (__SUNPRO_C >> 4 & 0xF))
+# define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_C & 0xF)
+
+#elif defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5100
+# define RBIMPL_COMPILER_IS_SunPro 1
+# /* __SUNPRO_CC = 0xXYYZ */
+# define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_CC >> 12)
+# define RBIMPL_COMPILER_VERSION_MINOR ((__SUNPRO_CC >> 8 & 0xF) * 10 + (__SUNPRO_CC >> 4 & 0xF))
+# define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_CC & 0xF)
+
+#elif defined(__SUNPRO_C)
+# define RBIMPL_COMPILER_IS_SunPro 1
+# /* __SUNPRO_C = 0xXYZ */
+# define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_C >> 8)
+# define RBIMPL_COMPILER_VERSION_MINOR (__SUNPRO_C >> 4 & 0xF)
+# define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_C & 0xF)
+
+#else
+# define RBIMPL_COMPILER_IS_SunPro 1
+# /* __SUNPRO_CC = 0xXYZ */
+# define RBIMPL_COMPILER_VERSION_MAJOR (__SUNPRO_CC >> 8)
+# define RBIMPL_COMPILER_VERSION_MINOR (__SUNPRO_CC >> 4 & 0xF)
+# define RBIMPL_COMPILER_VERSION_PATCH (__SUNPRO_CC & 0xF)
+#endif
+
+#endif /* RBIMPL_COMPILER_IS_SUNPRO_H */
diff --git a/include/ruby/internal/compiler_since.h b/include/ruby/internal/compiler_since.h
new file mode 100644
index 0000000000..92abb8acc8
--- /dev/null
+++ b/include/ruby/internal/compiler_since.h
@@ -0,0 +1,61 @@
+#ifndef RBIMPL_COMPILER_SINCE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_COMPILER_SINCE_H
+/**
+ * @file
+ * @author Ruby developers <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_COMPILER_SINCE.
+ */
+#include "ruby/internal/compiler_is.h"
+
+/**
+ * @brief Checks if the compiler is of given brand and is newer than or equal
+ * to the passed version.
+ * @param cc Compiler brand, like `MSVC`.
+ * @param x Major version.
+ * @param y Minor version.
+ * @param z Patchlevel.
+ * @retval true cc >= x.y.z.
+ * @retval false oherwise.
+ */
+#define RBIMPL_COMPILER_SINCE(cc, x, y, z) \
+ (RBIMPL_COMPILER_IS(cc) && \
+ ((RBIMPL_COMPILER_VERSION_MAJOR > (x)) || \
+ ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \
+ ((RBIMPL_COMPILER_VERSION_MINOR > (y)) || \
+ ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \
+ (RBIMPL_COMPILER_VERSION_PATCH >= (z)))))))
+
+/**
+ * @brief Checks if the compiler is of given brand and is older than the
+ * passed version.
+ * @param cc Compiler brand, like `MSVC`.
+ * @param x Major version.
+ * @param y Minor version.
+ * @param z Patchlevel.
+ * @retval true cc < x.y.z.
+ * @retval false oherwise.
+ */
+#define RBIMPL_COMPILER_BEFORE(cc, x, y, z) \
+ (RBIMPL_COMPILER_IS(cc) && \
+ ((RBIMPL_COMPILER_VERSION_MAJOR < (x)) || \
+ ((RBIMPL_COMPILER_VERSION_MAJOR == (x)) && \
+ ((RBIMPL_COMPILER_VERSION_MINOR < (y)) || \
+ ((RBIMPL_COMPILER_VERSION_MINOR == (y)) && \
+ (RBIMPL_COMPILER_VERSION_PATCH < (z)))))))
+
+#endif /* RBIMPL_COMPILER_SINCE_H */
diff --git a/include/ruby/internal/config.h b/include/ruby/internal/config.h
new file mode 100644
index 0000000000..67d7e0156f
--- /dev/null
+++ b/include/ruby/internal/config.h
@@ -0,0 +1,144 @@
+#ifndef RBIMPL_CONFIG_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_CONFIG_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 Thin wrapper to ruby/config.h
+ */
+#include "ruby/config.h"
+
+#ifdef RUBY_EXTCONF_H
+# include RUBY_EXTCONF_H
+#endif
+
+#include "ruby/internal/compiler_since.h"
+
+#undef HAVE_PROTOTYPES
+#define HAVE_PROTOTYPES 1
+
+#undef HAVE_STDARG_PROTOTYPES
+#define HAVE_STDARG_PROTOTYPES 1
+
+#undef TOKEN_PASTE
+#define TOKEN_PASTE(x,y) x##y
+
+#if defined(__cplusplus)
+#/* __builtin_choose_expr and __builtin_types_compatible aren't available
+# * on C++. See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */
+# undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P
+# undef HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P
+
+/* HAVE_VA_ARGS_MACRO is for C. C++ situations might be different. */
+# undef HAVE_VA_ARGS_MACRO
+# if __cplusplus >= 201103L
+# define HAVE_VA_ARGS_MACRO
+# elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__
+# define HAVE_VA_ARGS_MACRO
+# elif defined(__INTEL_CXX11_MODE__)
+# define HAVE_VA_ARGS_MACRO
+# elif RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0)
+# define HAVE_VA_ARGS_MACRO
+# else
+# /* NG, not known. */
+# endif
+#endif
+
+#if RBIMPL_COMPILER_BEFORE(GCC, 4, 9, 0)
+# /* See https://bugs.ruby-lang.org/issues/14221 */
+# undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P
+#endif
+
+#if RBIMPL_COMPILER_BEFORE(GCC, 5, 0, 0)
+# /* GCC 4.9.2 reportedly has this feature and is broken. The function is not
+# * officially documented below. Seems we should not use it.
+# * https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Other-Builtins.html */
+# undef HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN
+#endif
+
+#if defined(__SUNPRO_CC)
+# /* Oracle Developer Studio 12.5: GCC compatibility guide says it supports
+# * statement expressions. But to our knowledge they support the extension
+# * only for C and not for C++. Prove me wrong. Am happy to support them if
+# * there is a way. */
+# undef HAVE_STMT_AND_DECL_IN_EXPR
+#endif
+
+#ifndef STRINGIZE0
+# define STRINGIZE(expr) STRINGIZE0(expr)
+# define STRINGIZE0(expr) #expr
+#endif
+
+#ifdef AC_APPLE_UNIVERSAL_BUILD
+# undef WORDS_BIGENDIAN
+# ifdef __BIG_ENDIAN__
+# define WORDS_BIGENDIAN
+# endif
+#endif
+
+#ifndef DLEXT_MAXLEN
+# define DLEXT_MAXLEN 4
+#endif
+
+#ifndef RUBY_PLATFORM
+# define RUBY_PLATFORM "unknown-unknown"
+#endif
+
+#ifdef UNALIGNED_WORD_ACCESS
+# /* Take that. */
+#elif defined(__i386)
+# define UNALIGNED_WORD_ACCESS 1
+#elif defined(__i386__)
+# define UNALIGNED_WORD_ACCESS 1
+#elif defined(_M_IX86)
+# define UNALIGNED_WORD_ACCESS 1
+#elif defined(__x86_64)
+# define UNALIGNED_WORD_ACCESS 1
+#elif defined(__x86_64__)
+# define UNALIGNED_WORD_ACCESS 1
+#elif defined(_M_AMD64)
+# define UNALIGNED_WORD_ACCESS 1
+#elif defined(__powerpc64__)
+# define UNALIGNED_WORD_ACCESS 1
+#elif defined(__aarch64__)
+# define UNALIGNED_WORD_ACCESS 1
+#elif defined(__mc68020__)
+# define UNALIGNED_WORD_ACCESS 1
+#else
+# define UNALIGNED_WORD_ACCESS 0
+#endif
+
+/* Detection of __VA_OPT__ */
+#if ! defined(HAVE_VA_ARGS_MACRO)
+# undef HAVE___VA_OPT__
+
+#else
+# /* Idea taken from: https://stackoverflow.com/a/48045656 */
+# define RBIMPL_TEST3(q, w, e, ...) e
+# define RBIMPL_TEST2(...) RBIMPL_TEST3(__VA_OPT__(,),1,0,0)
+# define RBIMPL_TEST1() RBIMPL_TEST2("ruby")
+# if RBIMPL_TEST1()
+# define HAVE___VA_OPT__
+# else
+# undef HAVE___VA_OPT__
+# endif
+# undef RBIMPL_TEST1
+# undef RBIMPL_TEST2
+# undef RBIMPL_TEST3
+#endif /* HAVE_VA_ARGS_MACRO */
+
+#endif /* RBIMPL_CONFIG_H */
diff --git a/include/ruby/internal/constant_p.h b/include/ruby/internal/constant_p.h
new file mode 100644
index 0000000000..e54a8d85b9
--- /dev/null
+++ b/include/ruby/internal/constant_p.h
@@ -0,0 +1,37 @@
+#ifndef RBIMPL_CONSTANT_P_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_CONSTANT_P_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_CONSTANT_P.
+ *
+ * Note that __builtin_constant_p can be applicable inside of inline functions,
+ * according to GCC manual. Clang lacks that feature, though.
+ *
+ * @see https://bugs.llvm.org/show_bug.cgi?id=4898
+ * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
+ */
+#include "ruby/internal/has/builtin.h"
+
+#if RBIMPL_HAS_BUILTIN(__builtin_constant_p)
+# define RBIMPL_CONSTANT_P(expr) __builtin_constant_p(expr)
+#else
+# define RBIMPL_CONSTANT_P(expr) 0
+#endif
+
+#endif /* RBIMPL_CONSTANT_P_H */
diff --git a/include/ruby/internal/core.h b/include/ruby/internal/core.h
new file mode 100644
index 0000000000..53a00a4603
--- /dev/null
+++ b/include/ruby/internal/core.h
@@ -0,0 +1,35 @@
+#ifndef RBIMPL_CORE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_CORE_H
+/**
+ * @file
+ * @author Ruby developers <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 Core data structures, definitions and manupulations.
+ */
+#include "ruby/internal/core/rarray.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/core/rbignum.h"
+#include "ruby/internal/core/rclass.h"
+#include "ruby/internal/core/rdata.h"
+#include "ruby/internal/core/rfile.h"
+#include "ruby/internal/core/rhash.h"
+#include "ruby/internal/core/robject.h"
+#include "ruby/internal/core/rregexp.h"
+#include "ruby/internal/core/rstring.h"
+#include "ruby/internal/core/rstruct.h"
+#include "ruby/internal/core/rtypeddata.h"
+#endif /* RBIMPL_CORE_H */
diff --git a/include/ruby/internal/core/rarray.h b/include/ruby/internal/core/rarray.h
new file mode 100644
index 0000000000..938e2dc897
--- /dev/null
+++ b/include/ruby/internal/core/rarray.h
@@ -0,0 +1,270 @@
+#ifndef RBIMPL_RARRAY_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RARRAY_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 struct ::RArray.
+ */
+#include "ruby/internal/arithmetic/long.h"
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/attr/maybe_unused.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/rgengc.h"
+#include "ruby/internal/stdbool.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+#include "ruby/assert.h"
+
+#ifndef USE_TRANSIENT_HEAP
+# define USE_TRANSIENT_HEAP 1
+#endif
+
+#define RARRAY(obj) RBIMPL_CAST((struct RArray *)(obj))
+#define RARRAY_EMBED_FLAG RARRAY_EMBED_FLAG
+#define RARRAY_EMBED_LEN_MASK RARRAY_EMBED_LEN_MASK
+#define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX
+#define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT
+#if USE_TRANSIENT_HEAP
+# define RARRAY_TRANSIENT_FLAG RARRAY_TRANSIENT_FLAG
+#else
+# define RARRAY_TRANSIENT_FLAG 0
+#endif
+#define RARRAY_LEN rb_array_len
+#define RARRAY_CONST_PTR rb_array_const_ptr
+#define RARRAY_CONST_PTR_TRANSIENT rb_array_const_ptr_transient
+
+/** @cond INTERNAL_MACRO */
+#if defined(__fcc__) || defined(__fcc_version) || \
+ defined(__FCC__) || defined(__FCC_VERSION)
+/* workaround for old version of Fujitsu C Compiler (fcc) */
+# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x))
+#else
+# define FIX_CONST_VALUE_PTR(x) (x)
+#endif
+
+#define RARRAY_EMBED_LEN RARRAY_EMBED_LEN
+#define RARRAY_LENINT RARRAY_LENINT
+#define RARRAY_TRANSIENT_P RARRAY_TRANSIENT_P
+#define RARRAY_ASET RARRAY_ASET
+#define RARRAY_PTR RARRAY_PTR
+/** @endcond */
+
+enum ruby_rarray_flags {
+ RARRAY_EMBED_FLAG = RUBY_FL_USER1,
+ /* RUBY_FL_USER2 is for ELTS_SHARED */
+ RARRAY_EMBED_LEN_MASK = RUBY_FL_USER4 | RUBY_FL_USER3
+#if USE_TRANSIENT_HEAP
+ ,
+ RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13
+#endif
+};
+
+enum ruby_rarray_consts {
+ RARRAY_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 3,
+ RARRAY_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE)
+};
+
+struct RArray {
+ struct RBasic basic;
+ union {
+ struct {
+ long len;
+ union {
+ long capa;
+#if defined(__clang__) /* <- clang++ is sane */ || \
+ !defined(__cplusplus) /* <- C99 is sane */ || \
+ (__cplusplus > 199711L) /* <- C++11 is sane */
+ const
+#endif
+ VALUE shared_root;
+ } aux;
+ const VALUE *ptr;
+ } heap;
+ const VALUE ary[RARRAY_EMBED_LEN_MAX];
+ } as;
+};
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE *rb_ary_ptr_use_start(VALUE ary);
+void rb_ary_ptr_use_end(VALUE a);
+#if USE_TRANSIENT_HEAP
+void rb_ary_detransient(VALUE a);
+#endif
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline long
+RARRAY_EMBED_LEN(VALUE ary)
+{
+ RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
+ RBIMPL_ASSERT_OR_ASSUME(RB_FL_ANY_RAW(ary, RARRAY_EMBED_FLAG));
+
+ VALUE f = RBASIC(ary)->flags;
+ f &= RARRAY_EMBED_LEN_MASK;
+ f >>= RARRAY_EMBED_LEN_SHIFT;
+ return RBIMPL_CAST((long)f);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+static inline long
+rb_array_len(VALUE a)
+{
+ RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
+
+ if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) {
+ return RARRAY_EMBED_LEN(a);
+ }
+ else {
+ return RARRAY(a)->as.heap.len;
+ }
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+RARRAY_LENINT(VALUE ary)
+{
+ return rb_long2int(RARRAY_LEN(ary));
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RARRAY_TRANSIENT_P(VALUE ary)
+{
+ RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
+
+#if USE_TRANSIENT_HEAP
+ return RB_FL_ANY_RAW(ary, RARRAY_TRANSIENT_FLAG);
+#else
+ return false;
+#endif
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+/* internal function. do not use this function */
+static inline const VALUE *
+rb_array_const_ptr_transient(VALUE a)
+{
+ RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
+
+ if (RB_FL_ANY_RAW(a, RARRAY_EMBED_FLAG)) {
+ return FIX_CONST_VALUE_PTR(RARRAY(a)->as.ary);
+ }
+ else {
+ return FIX_CONST_VALUE_PTR(RARRAY(a)->as.heap.ptr);
+ }
+}
+
+#if ! USE_TRANSIENT_HEAP
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+#endif
+/* internal function. do not use this function */
+static inline const VALUE *
+rb_array_const_ptr(VALUE a)
+{
+ RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
+
+#if USE_TRANSIENT_HEAP
+ if (RARRAY_TRANSIENT_P(a)) {
+ rb_ary_detransient(a);
+ }
+#endif
+ return rb_array_const_ptr_transient(a);
+}
+
+/* internal function. do not use this function */
+static inline VALUE *
+rb_array_ptr_use_start(VALUE a,
+ RBIMPL_ATTR_MAYBE_UNUSED()
+ int allow_transient)
+{
+ RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
+
+#if USE_TRANSIENT_HEAP
+ if (!allow_transient) {
+ if (RARRAY_TRANSIENT_P(a)) {
+ rb_ary_detransient(a);
+ }
+ }
+#endif
+
+ return rb_ary_ptr_use_start(a);
+}
+
+/* internal function. do not use this function */
+static inline void
+rb_array_ptr_use_end(VALUE a,
+ RBIMPL_ATTR_MAYBE_UNUSED()
+ int allow_transient)
+{
+ RBIMPL_ASSERT_TYPE(a, RUBY_T_ARRAY);
+ rb_ary_ptr_use_end(a);
+}
+
+#define RBIMPL_RARRAY_STMT(flag, ary, var, expr) do { \
+ RBIMPL_ASSERT_TYPE((ary), RUBY_T_ARRAY); \
+ const VALUE rbimpl_ary = (ary); \
+ VALUE *var = rb_array_ptr_use_start(rbimpl_ary, (flag)); \
+ expr; \
+ rb_array_ptr_use_end(rbimpl_ary, (flag)); \
+} while (0)
+
+#define RARRAY_PTR_USE_START(a) rb_array_ptr_use_start(a, 0)
+#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0)
+#define RARRAY_PTR_USE(ary, ptr_name, expr) \
+ RBIMPL_RARRAY_STMT(0, ary, ptr_name, expr)
+
+#define RARRAY_PTR_USE_START_TRANSIENT(a) rb_array_ptr_use_start(a, 1)
+#define RARRAY_PTR_USE_END_TRANSIENT(a) rb_array_ptr_use_end(a, 1)
+#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) \
+ RBIMPL_RARRAY_STMT(1, ary, ptr_name, expr)
+
+static inline VALUE *
+RARRAY_PTR(VALUE ary)
+{
+ RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
+
+ VALUE tmp = RB_OBJ_WB_UNPROTECT_FOR(ARRAY, ary);
+ return RBIMPL_CAST((VALUE *)RARRAY_CONST_PTR(tmp));
+}
+
+static inline void
+RARRAY_ASET(VALUE ary, long i, VALUE v)
+{
+ RARRAY_PTR_USE_TRANSIENT(ary, ptr,
+ RB_OBJ_WRITE(ary, &ptr[i], v));
+}
+
+/*
+ * :FIXME: we want to convert RARRAY_AREF into an inline function (to add rooms
+ * for more sanity checks). However there were situations where the address of
+ * this macro is taken i.e. &RARRAY_AREF(...). They cannot be possible if this
+ * is not a macro. Such usages are abuse, and we eliminated them internally.
+ * However we are afraid of similar things to remain in the wild. This macro
+ * remains as it is due to that. If we could warn such usages we can set a
+ * transition path, but currently no way is found to do so.
+ */
+#define RARRAY_AREF(a, i) RARRAY_CONST_PTR_TRANSIENT(a)[i]
+
+#endif /* RBIMPL_RARRAY_H */
diff --git a/include/ruby/internal/core/rbasic.h b/include/ruby/internal/core/rbasic.h
new file mode 100644
index 0000000000..a6093c047a
--- /dev/null
+++ b/include/ruby/internal/core/rbasic.h
@@ -0,0 +1,85 @@
+#ifndef RBIMPL_RBASIC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RBASIC_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 struct ::RBasic.
+ */
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/attr/forceinline.h"
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/special_consts.h"
+#include "ruby/internal/value.h"
+#include "ruby/assert.h"
+
+#define RBASIC(obj) RBIMPL_CAST((struct RBasic *)(obj))
+#define RBASIC_CLASS RBASIC_CLASS
+#define RVALUE_EMBED_LEN_MAX RVALUE_EMBED_LEN_MAX
+
+/** @cond INTERNAL_MACRO */
+#define RBIMPL_EMBED_LEN_MAX_OF(T) \
+ RBIMPL_CAST((int)(sizeof(VALUE[RVALUE_EMBED_LEN_MAX]) / (sizeof(T))))
+/** @endcond */
+
+enum ruby_rvalue_flags { RVALUE_EMBED_LEN_MAX = 3 };
+
+struct
+RUBY_ALIGNAS(SIZEOF_VALUE)
+RBasic {
+ VALUE flags; /**< @see enum ::ruby_fl_type. */
+ const VALUE klass;
+
+#ifdef __cplusplus
+ public:
+ RBIMPL_ATTR_CONSTEXPR(CXX11)
+ RBIMPL_ATTR_ARTIFICIAL()
+ RBIMPL_ATTR_FORCEINLINE()
+ RBIMPL_ATTR_NOALIAS()
+ /**
+ * We need to define this explicit constructor because the field `klass` is
+ * const-qualified above, which effectively defines the implicit default
+ * constructor as "deleted" (as of C++11) -- No way but to define one by
+ * ourselves.
+ */
+ RBasic() :
+ flags(RBIMPL_VALUE_NULL),
+ klass(RBIMPL_VALUE_NULL)
+ {
+ }
+#endif
+};
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE rb_obj_hide(VALUE obj);
+VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RBASIC_CLASS(VALUE obj)
+{
+ RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj));
+ return RBASIC(obj)->klass;
+}
+
+#endif /* RBIMPL_RBASIC_H */
diff --git a/include/ruby/internal/core/rbignum.h b/include/ruby/internal/core/rbignum.h
new file mode 100644
index 0000000000..89db566501
--- /dev/null
+++ b/include/ruby/internal/core/rbignum.h
@@ -0,0 +1,51 @@
+#ifndef RBIMPL_RBIGNUM_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RBIGNUM_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 Routines to manipulate struct ::RBignum.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+#include "ruby/internal/stdbool.h"
+
+#define RBIGNUM_SIGN rb_big_sign
+
+/** @cond INTERNAL_MACRO */
+#define RBIGNUM_POSITIVE_P RBIGNUM_POSITIVE_P
+#define RBIGNUM_NEGATIVE_P RBIGNUM_NEGATIVE_P
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+int rb_big_sign(VALUE num);
+RBIMPL_SYMBOL_EXPORT_END()
+
+static inline bool
+RBIGNUM_POSITIVE_P(VALUE b) {
+ RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM);
+ return RBIGNUM_SIGN(b);
+}
+
+static inline bool
+RBIGNUM_NEGATIVE_P(VALUE b) {
+ RBIMPL_ASSERT_TYPE(b, RUBY_T_BIGNUM);
+ return ! RBIGNUM_POSITIVE_P(b);
+}
+
+#endif /* RBIMPL_RBIGNUM_H */
diff --git a/include/ruby/internal/core/rclass.h b/include/ruby/internal/core/rclass.h
new file mode 100644
index 0000000000..0aa6b1290e
--- /dev/null
+++ b/include/ruby/internal/core/rclass.h
@@ -0,0 +1,47 @@
+#ifndef RBIMPL_RCLASS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RCLASS_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 Routines to manipulate struct ::RClass.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/cast.h"
+
+#define RMODULE_IS_OVERLAID RMODULE_IS_OVERLAID
+#define RMODULE_IS_REFINEMENT RMODULE_IS_REFINEMENT
+#define RMODULE_INCLUDED_INTO_REFINEMENT RMODULE_INCLUDED_INTO_REFINEMENT
+
+#define RCLASS(obj) RBIMPL_CAST((struct RClass *)(obj))
+#define RMODULE RCLASS
+#define RCLASS_SUPER rb_class_get_superclass
+
+enum ruby_rmodule_flags {
+ RMODULE_IS_OVERLAID = RUBY_FL_USER2,
+ RMODULE_IS_REFINEMENT = RUBY_FL_USER3,
+ RMODULE_INCLUDED_INTO_REFINEMENT = RUBY_FL_USER4
+};
+
+struct RClass; /* Opaque, declared here for RCLASS() macro. */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE rb_class_get_superclass(VALUE);
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_RCLASS_H */
diff --git a/include/ruby/internal/core/rdata.h b/include/ruby/internal/core/rdata.h
new file mode 100644
index 0000000000..ca44a931dc
--- /dev/null
+++ b/include/ruby/internal/core/rdata.h
@@ -0,0 +1,184 @@
+#ifndef RBIMPL_RDATA_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RDATA_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 struct ::RData.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
+
+#include "ruby/internal/attr/deprecated.h"
+#include "ruby/internal/attr/warning.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/token_paste.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+#include "ruby/defines.h"
+
+#ifdef RUBY_UNTYPED_DATA_WARNING
+# /* Take that. */
+#elif defined(RUBY_EXPORT)
+# define RUBY_UNTYPED_DATA_WARNING 1
+#else
+# define RUBY_UNTYPED_DATA_WARNING 0
+#endif
+
+/** @cond INTERNAL_MACRO */
+#define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f))
+#define RBIMPL_ATTRSET_UNTYPED_DATA_FUNC() \
+ RBIMPL_ATTR_WARNING(("untyped Data is unsafe; use TypedData instead")) \
+ RBIMPL_ATTR_DEPRECATED(("by TypedData"))
+/** @endcond */
+
+#define RDATA(obj) RBIMPL_CAST((struct RData *)(obj))
+#define DATA_PTR(obj) RDATA(obj)->data
+#define RUBY_MACRO_SELECT RBIMPL_TOKEN_PASTE
+#define RUBY_DEFAULT_FREE RBIMPL_DATA_FUNC(-1)
+#define RUBY_NEVER_FREE RBIMPL_DATA_FUNC(0)
+#define RUBY_UNTYPED_DATA_FUNC(f) f RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
+
+/*
+#define RUBY_DATA_FUNC(func) ((void (*)(void*))(func))
+*/
+typedef void (*RUBY_DATA_FUNC)(void*);
+
+struct RData {
+ struct RBasic basic;
+ RUBY_DATA_FUNC dmark;
+ RUBY_DATA_FUNC dfree;
+ void *data;
+};
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
+VALUE rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree);
+RUBY_EXTERN VALUE rb_cObject;
+RBIMPL_SYMBOL_EXPORT_END()
+
+#define Data_Wrap_Struct(klass, mark, free, sval) \
+ rb_data_object_wrap( \
+ (klass), \
+ (sval), \
+ RBIMPL_DATA_FUNC(mark), \
+ RBIMPL_DATA_FUNC(free))
+
+#define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \
+ VALUE result = rb_data_object_zalloc( \
+ (klass), \
+ (size), \
+ RBIMPL_DATA_FUNC(mark), \
+ RBIMPL_DATA_FUNC(free)); \
+ (sval) = RBIMPL_CAST((type *)DATA_PTR(result)); \
+ RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
+
+#ifdef HAVE_STMT_AND_DECL_IN_EXPR
+#define Data_Make_Struct(klass, type, mark, free, sval) \
+ RB_GNUC_EXTENSION({ \
+ Data_Make_Struct0( \
+ data_struct_obj, \
+ klass, \
+ type, \
+ sizeof(type), \
+ mark, \
+ free, \
+ sval); \
+ data_struct_obj; \
+ })
+#else
+#define Data_Make_Struct(klass, type, mark, free, sval) \
+ rb_data_object_make( \
+ (klass), \
+ RBIMPL_DATA_FUNC(mark), \
+ RBIMPL_DATA_FUNC(free), \
+ RBIMPL_CAST((void **)&(sval)), \
+ sizeof(type))
+#endif
+
+#define Data_Get_Struct(obj, type, sval) \
+ ((sval) = RBIMPL_CAST((type*)rb_data_object_get(obj)))
+
+RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
+static inline VALUE
+rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free)
+{
+ return rb_data_object_wrap(klass, ptr, mark, free);
+}
+
+static inline void *
+rb_data_object_get(VALUE obj)
+{
+ Check_Type(obj, RUBY_T_DATA);
+ return DATA_PTR(obj);
+}
+
+RBIMPL_ATTRSET_UNTYPED_DATA_FUNC()
+static inline void *
+rb_data_object_get_warning(VALUE obj)
+{
+ return rb_data_object_get(obj);
+}
+
+#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
+# define rb_data_object_wrap_warning(klass, ptr, mark, free) \
+ RB_GNUC_EXTENSION( \
+ __builtin_choose_expr( \
+ __builtin_constant_p(klass) && !(klass), \
+ rb_data_object_wrap(klass, ptr, mark, free), \
+ (rb_data_object_wrap_warning)(klass, ptr, mark, free)))
+#endif
+
+static inline VALUE
+rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size)
+{
+ Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap);
+ return result;
+}
+
+RBIMPL_ATTR_DEPRECATED(("by: rb_data_object_wrap"))
+static inline VALUE
+rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
+{
+ return rb_data_object_wrap(klass, data, dmark, dfree);
+}
+
+RBIMPL_ATTR_DEPRECATED(("by: rb_cObject. Will be removed in 3.1."))
+RBIMPL_ATTR_PURE()
+static inline VALUE
+rb_cData(void)
+{
+ return rb_cObject;
+}
+#define rb_cData rb_cData()
+
+#define rb_data_object_wrap_0 rb_data_object_wrap
+#define rb_data_object_wrap_1 rb_data_object_wrap_warning
+#define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_, RUBY_UNTYPED_DATA_WARNING)
+#define rb_data_object_get_0 rb_data_object_get
+#define rb_data_object_get_1 rb_data_object_get_warning
+#define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_, RUBY_UNTYPED_DATA_WARNING)
+#define rb_data_object_make_0 rb_data_object_make
+#define rb_data_object_make_1 rb_data_object_make_warning
+#define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_, RUBY_UNTYPED_DATA_WARNING)
+#endif /* RBIMPL_RDATA_H */
diff --git a/include/ruby/internal/core/rfile.h b/include/ruby/internal/core/rfile.h
new file mode 100644
index 0000000000..464625b2bd
--- /dev/null
+++ b/include/ruby/internal/core/rfile.h
@@ -0,0 +1,36 @@
+#ifndef RBIMPL_RFILE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RFILE_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 struct ::RFile.
+ */
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/cast.h"
+
+/* rb_io_t is in ruby/io.h. The header file has historically not been included
+ * into ruby/ruby.h. We follow that tradition. */
+struct rb_io_t;
+
+struct RFile {
+ struct RBasic basic;
+ struct rb_io_t *fptr;
+};
+
+#define RFILE(obj) RBIMPL_CAST((struct RFile *)(obj))
+#endif /* RBIMPL_RFILE_H */
diff --git a/include/ruby/internal/core/rhash.h b/include/ruby/internal/core/rhash.h
new file mode 100644
index 0000000000..9bedf0af80
--- /dev/null
+++ b/include/ruby/internal/core/rhash.h
@@ -0,0 +1,62 @@
+#ifndef RBIMPL_RHASH_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RHASH_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 Routines to manipulate struct ::RHash.
+ *
+ * Shyouhei really suffered agnish over placement of macros in this file. They
+ * are half-brken. The situation (as of wriring) is:
+ *
+ * - #RHASH_TBL: works.
+ * - #RHASH_ITER_LEV: compile-time error.
+ * - #RHASH_IFNONE: compile-time error.
+ * - #RHASH_SIZE: works.
+ * - #RHASH_EMPTY_P: works.
+ * - #RHASH_SET_IFNONE: works (why... given you cannot query).
+ *
+ * Shyouhei stopped thinking. Let them be as is.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
+
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY
+# include "ruby/backward.h"
+#endif
+
+#define RHASH_TBL(h) rb_hash_tbl(h, __FILE__, __LINE__)
+#define RHASH_ITER_LEV(h) rb_hash_iter_lev(h)
+#define RHASH_IFNONE(h) rb_hash_ifnone(h)
+#define RHASH_SIZE(h) rb_hash_size_num(h)
+#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)
+#define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone)
+
+struct st_table; /* in ruby/st.h */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+size_t rb_hash_size_num(VALUE hash);
+struct st_table *rb_hash_tbl(VALUE, const char *file, int line);
+VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone);
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_RHASH_H */
diff --git a/include/ruby/internal/core/rmatch.h b/include/ruby/internal/core/rmatch.h
new file mode 100644
index 0000000000..03ab5e5d82
--- /dev/null
+++ b/include/ruby/internal/core/rmatch.h
@@ -0,0 +1,73 @@
+#ifndef RBIMPL_RMATCH_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RMATCH_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 struct ::RMatch.
+ */
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/attr/returns_nonnull.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+#include "ruby/assert.h"
+
+#define RMATCH(obj) RBIMPL_CAST((struct RMatch *)(obj))
+/** @cond INTERNAL_MACRO */
+#define RMATCH_REGS RMATCH_REGS
+/** @endcond */
+
+struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */
+struct re_registers; /* Also in onigmo.h */
+
+/* @shyouhei wonders: is anyone actively using this typedef ...? */
+typedef struct re_pattern_buffer Regexp;
+
+struct rmatch_offset {
+ long beg;
+ long end;
+};
+
+struct rmatch {
+ struct re_registers regs;
+
+ struct rmatch_offset *char_offset;
+ int char_offset_num_allocated;
+};
+
+struct RMatch {
+ struct RBasic basic;
+ VALUE str;
+ struct rmatch *rmatch;
+ VALUE regexp; /* RRegexp */
+};
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_RETURNS_NONNULL()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline struct re_registers *
+RMATCH_REGS(VALUE match)
+{
+ RBIMPL_ASSERT_TYPE(match, RUBY_T_MATCH);
+ RBIMPL_ASSERT_OR_ASSUME(RMATCH(match)->rmatch != NULL);
+ return &RMATCH(match)->rmatch->regs;
+}
+
+#endif /* RBIMPL_RMATCH_H */
diff --git a/include/ruby/internal/core/robject.h b/include/ruby/internal/core/robject.h
new file mode 100644
index 0000000000..c352c87a40
--- /dev/null
+++ b/include/ruby/internal/core/robject.h
@@ -0,0 +1,96 @@
+#ifndef RBIMPL_ROBJECT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ROBJECT_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 struct ::RObject.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/deprecated.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+
+#define ROBJECT(obj) RBIMPL_CAST((struct RObject *)(obj))
+#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX
+#define ROBJECT_EMBED ROBJECT_EMBED
+/** @cond INTERNAL_MACRO */
+#define ROBJECT_NUMIV ROBJECT_NUMIV
+#define ROBJECT_IVPTR ROBJECT_IVPTR
+#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL
+/** @endcond */
+
+enum ruby_robject_flags { ROBJECT_EMBED = RUBY_FL_USER1 };
+
+enum ruby_robject_consts { ROBJECT_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(VALUE) };
+
+struct st_table;
+
+struct RObject {
+ struct RBasic basic;
+ union {
+ struct {
+ uint32_t numiv;
+ VALUE *ivptr;
+ struct st_table *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
+ } heap;
+ VALUE ary[ROBJECT_EMBED_LEN_MAX];
+ } as;
+};
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline uint32_t
+ROBJECT_NUMIV(VALUE obj)
+{
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+
+ if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) {
+ return ROBJECT_EMBED_LEN_MAX;
+ }
+ else {
+ return ROBJECT(obj)->as.heap.numiv;
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE *
+ROBJECT_IVPTR(VALUE obj)
+{
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+
+ struct RObject *const ptr = ROBJECT(obj);
+
+ if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) {
+ return ptr->as.ary;
+ }
+ else {
+ return ptr->as.heap.ivptr;
+ }
+}
+
+#endif /* RBIMPL_ROBJECT_H */
diff --git a/include/ruby/internal/core/rregexp.h b/include/ruby/internal/core/rregexp.h
new file mode 100644
index 0000000000..f289ee1dda
--- /dev/null
+++ b/include/ruby/internal/core/rregexp.h
@@ -0,0 +1,84 @@
+#ifndef RBIMPL_RREGEXP_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RREGEXP_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 struct ::RRegexp.
+ */
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/core/rstring.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+
+#define RREGEXP(obj) RBIMPL_CAST((struct RRegexp *)(obj))
+#define RREGEXP_PTR(obj) (RREGEXP(obj)->ptr)
+/** @cond INTERNAL_MACRO */
+#define RREGEXP_SRC RREGEXP_SRC
+#define RREGEXP_SRC_PTR RREGEXP_SRC_PTR
+#define RREGEXP_SRC_LEN RREGEXP_SRC_LEN
+#define RREGEXP_SRC_END RREGEXP_SRC_END
+/** @endcond */
+
+struct re_patter_buffer; /* a.k.a. OnigRegexType, defined in onigmo.h */
+
+struct RRegexp {
+ struct RBasic basic;
+ struct re_pattern_buffer *ptr;
+ const VALUE src;
+ unsigned long usecnt;
+};
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RREGEXP_SRC(VALUE rexp)
+{
+ RBIMPL_ASSERT_TYPE(rexp, RUBY_T_REGEXP);
+ VALUE ret = RREGEXP(rexp)->src;
+ RBIMPL_ASSERT_TYPE(ret, RUBY_T_STRING);
+ return ret;
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline char *
+RREGEXP_SRC_PTR(VALUE rexp)
+{
+ return RSTRING_PTR(RREGEXP_SRC(rexp));
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline long
+RREGEXP_SRC_LEN(VALUE rexp)
+{
+ return RSTRING_LEN(RREGEXP_SRC(rexp));
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline char *
+RREGEXP_SRC_END(VALUE rexp)
+{
+ return RSTRING_END(RREGEXP_SRC(rexp));
+}
+
+#endif /* RBIMPL_RREGEXP_H */
diff --git a/include/ruby/internal/core/rstring.h b/include/ruby/internal/core/rstring.h
new file mode 100644
index 0000000000..d073da1d2c
--- /dev/null
+++ b/include/ruby/internal/core/rstring.h
@@ -0,0 +1,215 @@
+#ifndef RBIMPL_RSTRING_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RSTRING_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 struct ::RString.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/arithmetic/long.h"
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/value_type.h"
+#include "ruby/internal/warning_push.h"
+#include "ruby/assert.h"
+
+#define RSTRING(obj) RBIMPL_CAST((struct RString *)(obj))
+#define RSTRING_NOEMBED RSTRING_NOEMBED
+#define RSTRING_EMBED_LEN_MASK RSTRING_EMBED_LEN_MASK
+#define RSTRING_EMBED_LEN_SHIFT RSTRING_EMBED_LEN_SHIFT
+#define RSTRING_EMBED_LEN_MAX RSTRING_EMBED_LEN_MAX
+#define RSTRING_FSTR RSTRING_FSTR
+
+/** @cond INTERNAL_MACRO */
+#define RSTRING_EMBED_LEN RSTRING_EMBED_LEN
+#define RSTRING_LEN RSTRING_LEN
+#define RSTRING_LENINT RSTRING_LENINT
+#define RSTRING_PTR RSTRING_PTR
+#define RSTRING_END RSTRING_END
+/** @endcond */
+
+#define StringValue(v) rb_string_value(&(v))
+#define StringValuePtr(v) rb_string_value_ptr(&(v))
+#define StringValueCStr(v) rb_string_value_cstr(&(v))
+#define SafeStringValue(v) StringValue(v)
+#define ExportStringValue(v) do { \
+ StringValue(v); \
+ (v) = rb_str_export(v); \
+} while (0)
+
+enum ruby_rstring_flags {
+ RSTRING_NOEMBED = RUBY_FL_USER1,
+ RSTRING_EMBED_LEN_MASK = RUBY_FL_USER2 | RUBY_FL_USER3 | RUBY_FL_USER4 |
+ RUBY_FL_USER5 | RUBY_FL_USER6,
+ /* Actually, string encodings are also encoded into the flags, using
+ * remaining bits.*/
+ RSTRING_FSTR = RUBY_FL_USER17
+};
+
+enum ruby_rstring_consts {
+ RSTRING_EMBED_LEN_SHIFT = RUBY_FL_USHIFT + 2,
+ RSTRING_EMBED_LEN_MAX = RBIMPL_EMBED_LEN_MAX_OF(char) - 1
+};
+
+struct RString {
+ struct RBasic basic;
+ union {
+ struct {
+ long len;
+ char *ptr;
+ union {
+ long capa;
+ VALUE shared;
+ } aux;
+ } heap;
+ char ary[RSTRING_EMBED_LEN_MAX + 1];
+ } as;
+};
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE rb_str_to_str(VALUE);
+VALUE rb_string_value(volatile VALUE*);
+char *rb_string_value_ptr(volatile VALUE*);
+char *rb_string_value_cstr(volatile VALUE*);
+VALUE rb_str_export(VALUE);
+VALUE rb_str_export_locale(VALUE);
+
+RBIMPL_ATTR_ERROR(("rb_check_safe_str() and Check_SafeStr() are obsolete; use StringValue() instead"))
+void rb_check_safe_str(VALUE);
+#define Check_SafeStr(v) rb_check_safe_str(RBIMPL_CAST((VALUE)(v)))
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline long
+RSTRING_EMBED_LEN(VALUE str)
+{
+ RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING);
+ RBIMPL_ASSERT_OR_ASSUME(! RB_FL_ANY_RAW(str, RSTRING_NOEMBED));
+
+ VALUE f = RBASIC(str)->flags;
+ f &= RSTRING_EMBED_LEN_MASK;
+ f >>= RSTRING_EMBED_LEN_SHIFT;
+ return RBIMPL_CAST((long)f);
+}
+
+RBIMPL_WARNING_PUSH()
+#if RBIMPL_COMPILER_IS(Intel)
+RBIMPL_WARNING_IGNORED(413)
+#endif
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline struct RString
+rbimpl_rstring_getmem(VALUE str)
+{
+ RBIMPL_ASSERT_TYPE(str, RUBY_T_STRING);
+
+ if (RB_FL_ANY_RAW(str, RSTRING_NOEMBED)) {
+ return *RSTRING(str);
+ }
+ else {
+ /* Expecting compilers to optimize this on-stack struct away. */
+ struct RString retval;
+ retval.as.heap.len = RSTRING_EMBED_LEN(str);
+ retval.as.heap.ptr = RSTRING(str)->as.ary;
+ return retval;
+ }
+}
+
+RBIMPL_WARNING_POP()
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline long
+RSTRING_LEN(VALUE str)
+{
+ return rbimpl_rstring_getmem(str).as.heap.len;
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline char *
+RSTRING_PTR(VALUE str)
+{
+ char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr;
+
+ if (RB_UNLIKELY(! ptr)) {
+ /* :BEWARE: @shyouhei thinks that currently, there are rooms for this
+ * function to return NULL. In the 20th century that was a pointless
+ * concern. However struct RString can hold fake strings nowadays. It
+ * seems no check against NULL are exercised around handling of them
+ * (one of such usages is located in marshal.c, which scares
+ * @shyouhei). Better check here for maximum safety.
+ *
+ * Also, this is not rb_warn() because RSTRING_PTR() can be called
+ * during GC (see what obj_info() does). rb_warn() needs to allocate
+ * Ruby objects. That is not possible at this moment. */
+ fprintf(stderr, "%s\n",
+ "RSTRING_PTR is returning NULL!! "
+ "SIGSEGV is highly expected to follow immediately. "
+ "If you could reproduce, attach your debugger here, "
+ "and look at the passed string."
+ );
+ }
+
+ return ptr;
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline char *
+RSTRING_END(VALUE str)
+{
+ struct RString buf = rbimpl_rstring_getmem(str);
+
+ if (RB_UNLIKELY(! buf.as.heap.ptr)) {
+ /* Ditto. */
+ fprintf(stderr, "%s\n",
+ "RSTRING_END is returning NULL!! "
+ "SIGSEGV is highly expected to follow immediately. "
+ "If you could reproduce, attach your debugger here, "
+ "and look at the passed string."
+ );
+ }
+
+ return &buf.as.heap.ptr[buf.as.heap.len];
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+RSTRING_LENINT(VALUE str)
+{
+ return rb_long2int(RSTRING_LEN(str));
+}
+
+#ifdef HAVE_STMT_AND_DECL_IN_EXPR
+# define RSTRING_GETMEM(str, ptrvar, lenvar) \
+ __extension__ ({ \
+ struct RString rbimpl_str = rbimpl_rstring_getmem(str); \
+ (ptrvar) = rbimpl_str.as.heap.ptr; \
+ (lenvar) = rbimpl_str.as.heap.len; \
+ })
+#else
+# define RSTRING_GETMEM(str, ptrvar, lenvar) \
+ ((ptrvar) = RSTRING_PTR(str), \
+ (lenvar) = RSTRING_LEN(str))
+#endif /* HAVE_STMT_AND_DECL_IN_EXPR */
+#endif /* RBIMPL_RSTRING_H */
diff --git a/include/ruby/internal/core/rstruct.h b/include/ruby/internal/core/rstruct.h
new file mode 100644
index 0000000000..17454f7cbe
--- /dev/null
+++ b/include/ruby/internal/core/rstruct.h
@@ -0,0 +1,73 @@
+#ifndef RBIMPL_RSTRUCT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RSTRUCT_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 Routines to manipulate struct ::RStruct.
+ */
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+#include "ruby/internal/arithmetic/long.h"
+#include "ruby/internal/arithmetic/int.h"
+#if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY
+# include "ruby/backward.h"
+#endif
+
+#define RSTRUCT_PTR(st) rb_struct_ptr(st)
+/** @cond INTERNAL_MACRO */
+#define RSTRUCT_LEN RSTRUCT_LEN
+#define RSTRUCT_SET RSTRUCT_SET
+#define RSTRUCT_GET RSTRUCT_GET
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE rb_struct_size(VALUE s);
+VALUE rb_struct_aref(VALUE, VALUE);
+VALUE rb_struct_aset(VALUE, VALUE, VALUE);
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline long
+RSTRUCT_LEN(VALUE st)
+{
+ RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT);
+
+ return RB_NUM2LONG(rb_struct_size(st));
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RSTRUCT_SET(VALUE st, int k, VALUE v)
+{
+ RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT);
+
+ return rb_struct_aset(st, INT2NUM(k), (v));
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RSTRUCT_GET(VALUE st, int k)
+{
+ RBIMPL_ASSERT_TYPE(st, RUBY_T_STRUCT);
+
+ return rb_struct_aref(st, INT2NUM(k));
+}
+
+#endif /* RBIMPL_RSTRUCT_H */
diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h
new file mode 100644
index 0000000000..c038e6f2b8
--- /dev/null
+++ b/include/ruby/internal/core/rtypeddata.h
@@ -0,0 +1,186 @@
+#ifndef RBIMPL_RTYPEDDATA_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RTYPEDDATA_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 struct ::RTypedData.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
+
+#include "ruby/internal/assume.h"
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/core/rdata.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/error.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/stdbool.h"
+#include "ruby/internal/value_type.h"
+
+#define HAVE_TYPE_RB_DATA_TYPE_T 1
+#define HAVE_RB_DATA_TYPE_T_FUNCTION 1
+#define HAVE_RB_DATA_TYPE_T_PARENT 1
+#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
+#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE
+#define RTYPEDDATA(obj) RBIMPL_CAST((struct RTypedData *)(obj))
+#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)
+#define Check_TypedStruct(v, t) \
+ rb_check_typeddata(RBIMPL_CAST((VALUE)(v)), (t))
+
+/** @cond INTERNAL_MACRO */
+#define RTYPEDDATA_P RTYPEDDATA_P
+#define RTYPEDDATA_TYPE RTYPEDDATA_TYPE
+#define RUBY_TYPED_FREE_IMMEDIATELY RUBY_TYPED_FREE_IMMEDIATELY
+#define RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE
+#define RUBY_TYPED_WB_PROTECTED RUBY_TYPED_WB_PROTECTED
+#define RUBY_TYPED_PROMOTED1 RUBY_TYPED_PROMOTED1
+/** @endcond */
+
+/* bits for rb_data_type_struct::flags */
+enum rbimpl_typeddata_flags {
+ RUBY_TYPED_FREE_IMMEDIATELY = 1,
+ RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE,
+ RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */
+ RUBY_TYPED_PROMOTED1 = RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */
+};
+
+typedef struct rb_data_type_struct rb_data_type_t;
+
+struct rb_data_type_struct {
+ const char *wrap_struct_name;
+ struct {
+ RUBY_DATA_FUNC dmark;
+ RUBY_DATA_FUNC dfree;
+ size_t (*dsize)(const void *);
+ RUBY_DATA_FUNC dcompact;
+ void *reserved[1]; /* For future extension.
+ This array *must* be filled with ZERO. */
+ } function;
+ const rb_data_type_t *parent;
+ void *data; /* This area can be used for any purpose
+ by a programmer who define the type. */
+ VALUE flags; /* RUBY_FL_WB_PROTECTED */
+};
+
+struct RTypedData {
+ struct RBasic basic;
+ const rb_data_type_t *type;
+ VALUE typed_flag; /* 1 or not */
+ void *data;
+};
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *);
+VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type);
+int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
+int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type);
+void *rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type);
+RBIMPL_SYMBOL_EXPORT_END()
+
+#define TypedData_Wrap_Struct(klass,data_type,sval)\
+ rb_data_typed_object_wrap((klass),(sval),(data_type))
+
+#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \
+ VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \
+ (sval) = RBIMPL_CAST((type *)RTYPEDDATA_DATA(result)); \
+ RBIMPL_CAST(/*suppress unused variable warnings*/(void)(sval))
+
+#ifdef HAVE_STMT_AND_DECL_IN_EXPR
+#define TypedData_Make_Struct(klass, type, data_type, sval) \
+ RB_GNUC_EXTENSION({ \
+ TypedData_Make_Struct0( \
+ data_struct_obj, \
+ klass, \
+ type, \
+ sizeof(type), \
+ data_type, \
+ sval); \
+ data_struct_obj; \
+ })
+#else
+#define TypedData_Make_Struct(klass, type, data_type, sval) \
+ rb_data_typed_object_make( \
+ (klass), \
+ (data_type), \
+ RBIMPL_CAST((void **)&(sval)), \
+ sizeof(type))
+#endif
+
+#define TypedData_Get_Struct(obj,type,data_type,sval) \
+ ((sval) = RBIMPL_CAST((type *)rb_check_typeddata((obj), (data_type))))
+
+RBIMPL_ATTR_PURE()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+rbimpl_rtypeddata_p(VALUE obj)
+{
+ return RTYPEDDATA(obj)->typed_flag == 1;
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+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
+
+ return rbimpl_rtypeddata_p(obj);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+static inline const struct rb_data_type_struct *
+RTYPEDDATA_TYPE(VALUE obj)
+{
+#if RUBY_DEBUG
+ if (RB_UNLIKELY(! RTYPEDDATA_P(obj))) {
+ rb_unexpected_type(obj, RUBY_T_DATA);
+ RBIMPL_UNREACHABLE_RETURN(NULL);
+ }
+#endif
+
+ return RTYPEDDATA(obj)->type;
+}
+
+static inline VALUE
+rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size)
+{
+ TypedData_Make_Struct0(result, klass, void, size, type, *datap);
+ return result;
+}
+
+RBIMPL_ATTR_DEPRECATED(("by: rb_data_typed_object_wrap"))
+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
new file mode 100644
index 0000000000..aea3e0ca3d
--- /dev/null
+++ b/include/ruby/internal/ctype.h
@@ -0,0 +1,203 @@
+#ifndef RBIMPL_CTYPE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_CTYPE_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 Our own, locale independent, character handling routines.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <ctype.h>
+#endif
+
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/dllexport.h"
+
+#ifndef ISPRINT
+# define ISASCII rb_isascii
+# define ISPRINT rb_isprint
+# define ISGRAPH rb_isgraph
+# define ISSPACE rb_isspace
+# define ISUPPER rb_isupper
+# define ISLOWER rb_islower
+# define ISALNUM rb_isalnum
+# define ISALPHA rb_isalpha
+# define ISDIGIT rb_isdigit
+# define ISXDIGIT rb_isxdigit
+# define ISBLANK rb_isblank
+# define ISCNTRL rb_iscntrl
+# define ISPUNCT rb_ispunct
+#endif
+
+#define TOUPPER rb_toupper
+#define TOLOWER rb_tolower
+#define STRCASECMP st_locale_insensitive_strcasecmp
+#define STRNCASECMP st_locale_insensitive_strncasecmp
+#define STRTOUL ruby_strtoul
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+/* locale insensitive functions */
+int st_locale_insensitive_strcasecmp(const char *s1, const char *s2);
+int st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n);
+unsigned long ruby_strtoul(const char *str, char **endptr, int base);
+RBIMPL_SYMBOL_EXPORT_END()
+
+/*
+ * We are making the functions below to return `int` instead of `bool`. They
+ * have been as such since their birth at 5f237d79033b2109afb768bc889611fa9630.
+ */
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isascii(int c)
+{
+ return '\0' <= c && c <= '\x7f';
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isupper(int c)
+{
+ return 'A' <= c && c <= 'Z';
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_islower(int c)
+{
+ return 'a' <= c && c <= 'z';
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isalpha(int c)
+{
+ return rb_isupper(c) || rb_islower(c);
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isdigit(int c)
+{
+ return '0' <= c && c <= '9';
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isalnum(int c)
+{
+ return rb_isalpha(c) || rb_isdigit(c);
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isxdigit(int c)
+{
+ return rb_isdigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isblank(int c)
+{
+ return c == ' ' || c == '\t';
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isspace(int c)
+{
+ return c == ' ' || ('\t' <= c && c <= '\r');
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_iscntrl(int c)
+{
+ return ('\0' <= c && c < ' ') || c == '\x7f';
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isprint(int c)
+{
+ return ' ' <= c && c <= '\x7e';
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_ispunct(int c)
+{
+ return !rb_isalnum(c);
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_isgraph(int c)
+{
+ return '!' <= c && c <= '\x7e';
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_tolower(int c)
+{
+ return rb_isupper(c) ? (c|0x20) : c;
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline int
+rb_toupper(int c)
+{
+ return rb_islower(c) ? (c&0x5f) : c;
+}
+
+#endif /* RBIMPL_CTYPE_H */
diff --git a/include/ruby/internal/dllexport.h b/include/ruby/internal/dllexport.h
new file mode 100644
index 0000000000..1488140854
--- /dev/null
+++ b/include/ruby/internal/dllexport.h
@@ -0,0 +1,92 @@
+#ifndef RBIMPL_DLLEXPORT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_DLLEXPORT_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 Tewaking visibility of C variables/functions.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/compiler_is.h"
+
+/* For MinGW, we need __declspec(dllimport) for RUBY_EXTERN on MJIT.
+ mswin's RUBY_EXTERN already has that. See also: win32/Makefile.sub */
+#undef RUBY_EXTERN
+#if defined(MJIT_HEADER) && defined(_WIN32)
+# define RUBY_EXTERN extern __declspec(dllimport)
+#elif defined(RUBY_EXPORT)
+# define RUBY_EXTERN extern
+#elif defined(_WIN32)
+# define RUBY_EXTERN extern __declspec(dllimport)
+#else
+# define RUBY_EXTERN extern
+#endif
+
+#ifndef RUBY_SYMBOL_EXPORT_BEGIN
+# define RUBY_SYMBOL_EXPORT_BEGIN /* begin */
+#endif
+
+#ifndef RUBY_SYMBOL_EXPORT_END
+# define RUBY_SYMBOL_EXPORT_END /* end */
+#endif
+
+#ifndef RUBY_FUNC_EXPORTED
+# define RUBY_FUNC_EXPORTED /* void */
+#endif
+
+/* These macros are used for functions which are exported only for MJIT
+ and NOT ensured to be exported in future versions. */
+
+#if ! defined(MJIT_HEADER)
+# define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED
+#elif ! RBIMPL_COMPILER_IS(MSVC)
+# define MJIT_FUNC_EXPORTED RUBY_FUNC_EXPORTED
+#else
+# define MJIT_FUNC_EXPORTED static
+#endif
+
+#define MJIT_SYMBOL_EXPORT_BEGIN RUBY_SYMBOL_EXPORT_BEGIN
+#define MJIT_SYMBOL_EXPORT_END RUBY_SYMBOL_EXPORT_END
+
+/* On mswin, MJIT header transformation can't be used since cl.exe can't output
+ preprocessed output preserving macros. So this `MJIT_STATIC` is needed
+ to force non-static function to static on MJIT header to avoid symbol conflict. */
+#ifdef MJIT_HEADER
+# define MJIT_STATIC static
+#else
+# define MJIT_STATIC
+#endif
+
+/** Shortcut macro equivalent to `RUBY_SYMBOL_EXPORT_BEGIN extern "C" {`.
+ * \@shyouhei finds it handy. */
+#if defined(__DOXYGEN__)
+# define RBIMPL_SYMBOL_EXPORT_BEGIN() /* void */
+#elif defined(__cplusplus)
+# define RBIMPL_SYMBOL_EXPORT_BEGIN() RUBY_SYMBOL_EXPORT_BEGIN extern "C" {
+#else
+# define RBIMPL_SYMBOL_EXPORT_BEGIN() RUBY_SYMBOL_EXPORT_BEGIN
+#endif
+
+/** Counterpart of #RBIMPL_SYMBOL_EXPORT_BEGIN */
+#if defined(__DOXYGEN__)
+# define RBIMPL_SYMBOL_EXPORT_END() /* void */
+#elif defined(__cplusplus)
+# define RBIMPL_SYMBOL_EXPORT_END() } RUBY_SYMBOL_EXPORT_END
+#else
+# define RBIMPL_SYMBOL_EXPORT_END() RUBY_SYMBOL_EXPORT_END
+#endif
+#endif /* RBIMPL_DLLEXPORT_H */
diff --git a/include/ruby/internal/dosish.h b/include/ruby/internal/dosish.h
new file mode 100644
index 0000000000..eb71e36505
--- /dev/null
+++ b/include/ruby/internal/dosish.h
@@ -0,0 +1,63 @@
+#ifndef RBIMPL_DOSISH_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_DOSISH_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 Support for so-called dosish systems.
+ */
+#ifdef __CYGWIN__
+#undef _WIN32
+#endif
+
+#if defined(_WIN32)
+/*
+ DOSISH mean MS-Windows style filesystem.
+ But you should use more precise macros like DOSISH_DRIVE_LETTER, PATH_SEP,
+ ENV_IGNORECASE or CASEFOLD_FILESYSTEM.
+ */
+#define DOSISH 1
+# define DOSISH_DRIVE_LETTER
+#endif
+
+#ifdef _WIN32
+#include "ruby/win32.h"
+#endif
+
+#if defined(DOSISH)
+#define PATH_SEP ";"
+#else
+#define PATH_SEP ":"
+#endif
+
+#define PATH_SEP_CHAR PATH_SEP[0]
+
+#define PATH_ENV "PATH"
+
+#if defined(DOSISH)
+#define ENV_IGNORECASE
+#endif
+
+#ifndef CASEFOLD_FILESYSTEM
+# if defined DOSISH
+# define CASEFOLD_FILESYSTEM 1
+# else
+# define CASEFOLD_FILESYSTEM 0
+# endif
+#endif
+
+#endif /* RBIMPL_DOSISH_H */
diff --git a/include/ruby/internal/error.h b/include/ruby/internal/error.h
new file mode 100644
index 0000000000..7e9d5c4167
--- /dev/null
+++ b/include/ruby/internal/error.h
@@ -0,0 +1,84 @@
+#ifndef RBIMPL_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ERROR_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 Declares ::rb_raise().
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/backward/2/attributes.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+VALUE rb_errinfo(void);
+void rb_set_errinfo(VALUE);
+
+typedef enum {
+ RB_WARN_CATEGORY_NONE,
+ RB_WARN_CATEGORY_DEPRECATED,
+ RB_WARN_CATEGORY_EXPERIMENTAL,
+ RB_WARN_CATEGORY_ALL_BITS = 0x6 /* no RB_WARN_CATEGORY_NONE bit */
+} rb_warning_category_t;
+
+/* for rb_readwrite_sys_fail first argument */
+enum rb_io_wait_readwrite {RB_IO_WAIT_READABLE, RB_IO_WAIT_WRITABLE};
+#define RB_IO_WAIT_READABLE RB_IO_WAIT_READABLE
+#define RB_IO_WAIT_WRITABLE RB_IO_WAIT_WRITABLE
+
+PRINTF_ARGS(NORETURN(void rb_raise(VALUE, const char*, ...)), 2, 3);
+PRINTF_ARGS(NORETURN(void rb_fatal(const char*, ...)), 1, 2);
+COLDFUNC PRINTF_ARGS(NORETURN(void rb_bug(const char*, ...)), 1, 2);
+NORETURN(void rb_bug_errno(const char*, int));
+NORETURN(void rb_sys_fail(const char*));
+NORETURN(void rb_sys_fail_str(VALUE));
+NORETURN(void rb_mod_sys_fail(VALUE, const char*));
+NORETURN(void rb_mod_sys_fail_str(VALUE, VALUE));
+NORETURN(void rb_readwrite_sys_fail(enum rb_io_wait_readwrite, const char*));
+NORETURN(void rb_iter_break(void));
+NORETURN(void rb_iter_break_value(VALUE));
+NORETURN(void rb_exit(int));
+NORETURN(void rb_notimplement(void));
+VALUE rb_syserr_new(int, const char *);
+VALUE rb_syserr_new_str(int n, VALUE arg);
+NORETURN(void rb_syserr_fail(int, const char*));
+NORETURN(void rb_syserr_fail_str(int, VALUE));
+NORETURN(void rb_mod_syserr_fail(VALUE, int, const char*));
+NORETURN(void rb_mod_syserr_fail_str(VALUE, int, VALUE));
+NORETURN(void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite, int, const char*));
+NORETURN(void rb_unexpected_type(VALUE,int));
+
+VALUE *rb_ruby_verbose_ptr(void);
+VALUE *rb_ruby_debug_ptr(void);
+#define ruby_verbose (*rb_ruby_verbose_ptr())
+#define ruby_debug (*rb_ruby_debug_ptr())
+
+/* reports if `-W' specified */
+PRINTF_ARGS(void rb_warning(const char*, ...), 1, 2);
+PRINTF_ARGS(void rb_category_warning(rb_warning_category_t, const char*, ...), 2, 3);
+PRINTF_ARGS(void rb_compile_warning(const char *, int, const char*, ...), 3, 4);
+PRINTF_ARGS(void rb_category_compile_warn(rb_warning_category_t, const char *, int, const char*, ...), 4, 5);
+PRINTF_ARGS(void rb_sys_warning(const char*, ...), 1, 2);
+/* reports always */
+COLDFUNC PRINTF_ARGS(void rb_warn(const char*, ...), 1, 2);
+COLDFUNC PRINTF_ARGS(void rb_category_warn(rb_warning_category_t, const char*, ...), 2, 3);
+PRINTF_ARGS(void rb_compile_warn(const char *, int, const char*, ...), 3, 4);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_ERROR_H */
diff --git a/include/ruby/internal/eval.h b/include/ruby/internal/eval.h
new file mode 100644
index 0000000000..934611fbb9
--- /dev/null
+++ b/include/ruby/internal/eval.h
@@ -0,0 +1,50 @@
+#ifndef RBIMPL_EVAL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_EVAL_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 Declares ::rb_eval_string().
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+VALUE rb_eval_string(const char*);
+VALUE rb_eval_string_protect(const char*, int*);
+VALUE rb_eval_string_wrap(const char*, int*);
+VALUE rb_funcall(VALUE, ID, int, ...);
+VALUE rb_funcallv(VALUE, ID, int, const VALUE*);
+VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE*, int);
+VALUE rb_funcallv_public(VALUE, ID, int, const VALUE*);
+VALUE rb_funcallv_public_kw(VALUE, ID, int, const VALUE*, int);
+#define rb_funcall2 rb_funcallv
+#define rb_funcall3 rb_funcallv_public
+VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*);
+VALUE rb_funcall_passing_block_kw(VALUE, ID, int, const VALUE*, int);
+VALUE rb_funcall_with_block(VALUE, ID, int, const VALUE*, VALUE);
+VALUE rb_funcall_with_block_kw(VALUE, ID, int, const VALUE*, VALUE, int);
+VALUE rb_call_super(int, const VALUE*);
+VALUE rb_call_super_kw(int, const VALUE*, int);
+VALUE rb_current_receiver(void);
+int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *);
+VALUE rb_extract_keywords(VALUE *orighash);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_EVAL_H */
diff --git a/include/ruby/internal/event.h b/include/ruby/internal/event.h
new file mode 100644
index 0000000000..f20e01dc01
--- /dev/null
+++ b/include/ruby/internal/event.h
@@ -0,0 +1,75 @@
+#ifndef RBIMPL_EVENT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_EVENT_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 Debugging and tracing APIs.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* traditional set_trace_func events */
+#define RUBY_EVENT_NONE 0x0000
+#define RUBY_EVENT_LINE 0x0001
+#define RUBY_EVENT_CLASS 0x0002
+#define RUBY_EVENT_END 0x0004
+#define RUBY_EVENT_CALL 0x0008
+#define RUBY_EVENT_RETURN 0x0010
+#define RUBY_EVENT_C_CALL 0x0020
+#define RUBY_EVENT_C_RETURN 0x0040
+#define RUBY_EVENT_RAISE 0x0080
+#define RUBY_EVENT_ALL 0x00ff
+
+/* for TracePoint extended events */
+#define RUBY_EVENT_B_CALL 0x0100
+#define RUBY_EVENT_B_RETURN 0x0200
+#define RUBY_EVENT_THREAD_BEGIN 0x0400
+#define RUBY_EVENT_THREAD_END 0x0800
+#define RUBY_EVENT_FIBER_SWITCH 0x1000
+#define RUBY_EVENT_SCRIPT_COMPILED 0x2000
+#define RUBY_EVENT_TRACEPOINT_ALL 0xffff
+
+/* special events */
+#define RUBY_EVENT_RESERVED_FOR_INTERNAL_USE 0x030000
+
+/* internal events */
+#define RUBY_INTERNAL_EVENT_SWITCH 0x040000
+#define RUBY_EVENT_SWITCH 0x040000 /* obsolete name. this macro is for compatibility */
+ /* 0x080000 */
+#define RUBY_INTERNAL_EVENT_NEWOBJ 0x100000
+#define RUBY_INTERNAL_EVENT_FREEOBJ 0x200000
+#define RUBY_INTERNAL_EVENT_GC_START 0x400000
+#define RUBY_INTERNAL_EVENT_GC_END_MARK 0x800000
+#define RUBY_INTERNAL_EVENT_GC_END_SWEEP 0x1000000
+#define RUBY_INTERNAL_EVENT_GC_ENTER 0x2000000
+#define RUBY_INTERNAL_EVENT_GC_EXIT 0x4000000
+#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK 0x7f00000
+#define RUBY_INTERNAL_EVENT_MASK 0xffff0000
+
+typedef uint32_t rb_event_flag_t;
+typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass);
+
+#define RB_EVENT_HOOKS_HAVE_CALLBACK_DATA 1
+void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
+int rb_remove_event_hook(rb_event_hook_func_t func);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_EVENT_H */
diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h
new file mode 100644
index 0000000000..455448fe8d
--- /dev/null
+++ b/include/ruby/internal/fl_type.h
@@ -0,0 +1,471 @@
+#ifndef RBIMPL_FL_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_FL_TYPE_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 enum ::ruby_fl_type.
+ */
+#include "ruby/internal/config.h" /* for ENUM_OVER_INT */
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/flag_enum.h"
+#include "ruby/internal/attr/forceinline.h"
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/special_consts.h"
+#include "ruby/internal/stdbool.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+#include "ruby/assert.h"
+#include "ruby/defines.h"
+
+/** @cond INTERNAL_MACRO */
+#ifdef ENUM_OVER_INT
+# define RBIMPL_WIDER_ENUM 1
+#elif SIZEOF_INT * CHAR_BIT > 12+19+1
+# define RBIMPL_WIDER_ENUM 1
+#else
+# define RBIMPL_WIDER_ENUM 0
+#endif
+/** @endcond */
+
+#define FL_SINGLETON RBIMPL_CAST((VALUE)RUBY_FL_SINGLETON)
+#define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED)
+#define FL_PROMOTED0 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED0)
+#define FL_PROMOTED1 RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED1)
+#define FL_FINALIZE RBIMPL_CAST((VALUE)RUBY_FL_FINALIZE)
+#define FL_TAINT RBIMPL_CAST((VALUE)RUBY_FL_TAINT)
+#define FL_SHAREABLE RBIMPL_CAST((VALUE)RUBY_FL_SHAREABLE)
+#define FL_UNTRUSTED RBIMPL_CAST((VALUE)RUBY_FL_UNTRUSTED)
+#define FL_SEEN_OBJ_ID RBIMPL_CAST((VALUE)RUBY_FL_SEEN_OBJ_ID)
+#define FL_EXIVAR RBIMPL_CAST((VALUE)RUBY_FL_EXIVAR)
+#define FL_FREEZE RBIMPL_CAST((VALUE)RUBY_FL_FREEZE)
+
+#define FL_USHIFT RBIMPL_CAST((VALUE)RUBY_FL_USHIFT)
+
+#define FL_USER0 RBIMPL_CAST((VALUE)RUBY_FL_USER0)
+#define FL_USER1 RBIMPL_CAST((VALUE)RUBY_FL_USER1)
+#define FL_USER2 RBIMPL_CAST((VALUE)RUBY_FL_USER2)
+#define FL_USER3 RBIMPL_CAST((VALUE)RUBY_FL_USER3)
+#define FL_USER4 RBIMPL_CAST((VALUE)RUBY_FL_USER4)
+#define FL_USER5 RBIMPL_CAST((VALUE)RUBY_FL_USER5)
+#define FL_USER6 RBIMPL_CAST((VALUE)RUBY_FL_USER6)
+#define FL_USER7 RBIMPL_CAST((VALUE)RUBY_FL_USER7)
+#define FL_USER8 RBIMPL_CAST((VALUE)RUBY_FL_USER8)
+#define FL_USER9 RBIMPL_CAST((VALUE)RUBY_FL_USER9)
+#define FL_USER10 RBIMPL_CAST((VALUE)RUBY_FL_USER10)
+#define FL_USER11 RBIMPL_CAST((VALUE)RUBY_FL_USER11)
+#define FL_USER12 RBIMPL_CAST((VALUE)RUBY_FL_USER12)
+#define FL_USER13 RBIMPL_CAST((VALUE)RUBY_FL_USER13)
+#define FL_USER14 RBIMPL_CAST((VALUE)RUBY_FL_USER14)
+#define FL_USER15 RBIMPL_CAST((VALUE)RUBY_FL_USER15)
+#define FL_USER16 RBIMPL_CAST((VALUE)RUBY_FL_USER16)
+#define FL_USER17 RBIMPL_CAST((VALUE)RUBY_FL_USER17)
+#define FL_USER18 RBIMPL_CAST((VALUE)RUBY_FL_USER18)
+#define FL_USER19 RBIMPL_CAST((VALUE)(unsigned int)RUBY_FL_USER19)
+
+#define ELTS_SHARED RUBY_ELTS_SHARED
+#define RUBY_ELTS_SHARED RUBY_ELTS_SHARED
+#define RB_OBJ_FREEZE rb_obj_freeze_inline
+
+/** @cond INTERNAL_MACRO */
+#define RB_FL_ABLE RB_FL_ABLE
+#define RB_FL_ALL RB_FL_ALL
+#define RB_FL_ALL_RAW RB_FL_ALL_RAW
+#define RB_FL_ANY RB_FL_ANY
+#define RB_FL_ANY_RAW RB_FL_ANY_RAW
+#define RB_FL_REVERSE RB_FL_REVERSE
+#define RB_FL_REVERSE_RAW RB_FL_REVERSE_RAW
+#define RB_FL_SET RB_FL_SET
+#define RB_FL_SET_RAW RB_FL_SET_RAW
+#define RB_FL_TEST RB_FL_TEST
+#define RB_FL_TEST_RAW RB_FL_TEST_RAW
+#define RB_FL_UNSET RB_FL_UNSET
+#define RB_FL_UNSET_RAW RB_FL_UNSET_RAW
+#define RB_OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW
+#define RB_OBJ_FROZEN RB_OBJ_FROZEN
+#define RB_OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW
+#define RB_OBJ_INFECT RB_OBJ_INFECT
+#define RB_OBJ_INFECT_RAW RB_OBJ_INFECT_RAW
+#define RB_OBJ_TAINT RB_OBJ_TAINT
+#define RB_OBJ_TAINTABLE RB_OBJ_TAINTABLE
+#define RB_OBJ_TAINTED RB_OBJ_TAINTED
+#define RB_OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW
+#define RB_OBJ_TAINT_RAW RB_OBJ_TAINT_RAW
+#define RB_OBJ_UNTRUST RB_OBJ_UNTRUST
+#define RB_OBJ_UNTRUSTED RB_OBJ_UNTRUSTED
+/** @endcond */
+
+/**
+ * @defgroup deprecated_macros deprecated macro APIs
+ * @{
+ * These macros are deprecated. Prefer their `RB_`-prefixed versions.
+ */
+#define FL_ABLE RB_FL_ABLE
+#define FL_ALL RB_FL_ALL
+#define FL_ALL_RAW RB_FL_ALL_RAW
+#define FL_ANY RB_FL_ANY
+#define FL_ANY_RAW RB_FL_ANY_RAW
+#define FL_REVERSE RB_FL_REVERSE
+#define FL_REVERSE_RAW RB_FL_REVERSE_RAW
+#define FL_SET RB_FL_SET
+#define FL_SET_RAW RB_FL_SET_RAW
+#define FL_TEST RB_FL_TEST
+#define FL_TEST_RAW RB_FL_TEST_RAW
+#define FL_UNSET RB_FL_UNSET
+#define FL_UNSET_RAW RB_FL_UNSET_RAW
+#define OBJ_FREEZE RB_OBJ_FREEZE
+#define OBJ_FREEZE_RAW RB_OBJ_FREEZE_RAW
+#define OBJ_FROZEN RB_OBJ_FROZEN
+#define OBJ_FROZEN_RAW RB_OBJ_FROZEN_RAW
+#define OBJ_INFECT RB_OBJ_INFECT
+#define OBJ_INFECT_RAW RB_OBJ_INFECT_RAW
+#define OBJ_TAINT RB_OBJ_TAINT
+#define OBJ_TAINTABLE RB_OBJ_TAINTABLE
+#define OBJ_TAINTED RB_OBJ_TAINTED
+#define OBJ_TAINTED_RAW RB_OBJ_TAINTED_RAW
+#define OBJ_TAINT_RAW RB_OBJ_TAINT_RAW
+#define OBJ_UNTRUST RB_OBJ_UNTRUST
+#define OBJ_UNTRUSTED RB_OBJ_UNTRUSTED
+/** @} */
+
+/* This is an enum because GDB wants it (rather than a macro) */
+enum ruby_fl_ushift { RUBY_FL_USHIFT = 12 };
+
+/* > The expression that defines the value of an enumeration constant shall be
+ * > an integer constant expression that has a value representable as an `int`.
+ *
+ * -- ISO/IEC 9899:2018 section 6.7.2.2
+ *
+ * So ENUM_OVER_INT situation is an extension to the standard. Note however
+ * that we do not support 16 bit `int` environment. */
+RB_GNUC_EXTENSION
+enum
+RBIMPL_ATTR_FLAG_ENUM()
+ruby_fl_type {
+ RUBY_FL_WB_PROTECTED = (1<<5),
+ RUBY_FL_PROMOTED0 = (1<<5),
+ RUBY_FL_PROMOTED1 = (1<<6),
+ RUBY_FL_PROMOTED = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1,
+ RUBY_FL_FINALIZE = (1<<7),
+ RUBY_FL_TAINT = (1<<8),
+ RUBY_FL_SHAREABLE = (1<<8),
+ RUBY_FL_UNTRUSTED = RUBY_FL_TAINT,
+ RUBY_FL_SEEN_OBJ_ID = (1<<9),
+ RUBY_FL_EXIVAR = (1<<10),
+ RUBY_FL_FREEZE = (1<<11),
+
+#define RBIMPL_FL_USER_N(n) RUBY_FL_USER##n = (1<<(RUBY_FL_USHIFT+n))
+ RBIMPL_FL_USER_N(0),
+ RBIMPL_FL_USER_N(1),
+ RBIMPL_FL_USER_N(2),
+ RBIMPL_FL_USER_N(3),
+ RBIMPL_FL_USER_N(4),
+ RBIMPL_FL_USER_N(5),
+ RBIMPL_FL_USER_N(6),
+ RBIMPL_FL_USER_N(7),
+ RBIMPL_FL_USER_N(8),
+ RBIMPL_FL_USER_N(9),
+ RBIMPL_FL_USER_N(10),
+ RBIMPL_FL_USER_N(11),
+ RBIMPL_FL_USER_N(12),
+ RBIMPL_FL_USER_N(13),
+ RBIMPL_FL_USER_N(14),
+ RBIMPL_FL_USER_N(15),
+ RBIMPL_FL_USER_N(16),
+ RBIMPL_FL_USER_N(17),
+ RBIMPL_FL_USER_N(18),
+#if ENUM_OVER_INT
+ RBIMPL_FL_USER_N(19),
+#else
+# define RUBY_FL_USER19 (RBIMPL_VALUE_ONE<<(RUBY_FL_USHIFT+19))
+#endif
+#undef RBIMPL_FL_USER_N
+#undef RBIMPL_WIDER_ENUM
+
+ RUBY_ELTS_SHARED = RUBY_FL_USER2,
+ RUBY_FL_SINGLETON = RUBY_FL_USER0,
+};
+
+enum { RUBY_FL_DUPPED = RUBY_T_MASK | RUBY_FL_EXIVAR | RUBY_FL_TAINT };
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+void rb_obj_infect(VALUE victim, VALUE carrier);
+void rb_freeze_singleton_class(VALUE klass);
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_FORCEINLINE()
+static bool
+RB_FL_ABLE(VALUE obj)
+{
+ if (RB_SPECIAL_CONST_P(obj)) {
+ return false;
+ }
+ else if (RB_TYPE_P(obj, RUBY_T_NODE)) {
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RB_FL_TEST_RAW(VALUE obj, VALUE flags)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj));
+ return RBASIC(obj)->flags & flags;
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RB_FL_TEST(VALUE obj, VALUE flags)
+{
+ if (RB_FL_ABLE(obj)) {
+ return RB_FL_TEST_RAW(obj, flags);
+ }
+ else {
+ return RBIMPL_VALUE_NULL;
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_FL_ANY_RAW(VALUE obj, VALUE flags)
+{
+ return RB_FL_TEST_RAW(obj, flags);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_FL_ANY(VALUE obj, VALUE flags)
+{
+ return RB_FL_TEST(obj, flags);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_FL_ALL_RAW(VALUE obj, VALUE flags)
+{
+ return RB_FL_TEST_RAW(obj, flags) == flags;
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_FL_ALL(VALUE obj, VALUE flags)
+{
+ return RB_FL_TEST(obj, flags) == flags;
+}
+
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+rbimpl_fl_set_raw_raw(struct RBasic *obj, VALUE flags)
+{
+ obj->flags |= flags;
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_FL_SET_RAW(VALUE obj, VALUE flags)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj));
+ rbimpl_fl_set_raw_raw(RBASIC(obj), flags);
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_FL_SET(VALUE obj, VALUE flags)
+{
+ if (RB_FL_ABLE(obj)) {
+ RB_FL_SET_RAW(obj, flags);
+ }
+}
+
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+rbimpl_fl_unset_raw_raw(struct RBasic *obj, VALUE flags)
+{
+ obj->flags &= ~flags;
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_FL_UNSET_RAW(VALUE obj, VALUE flags)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj));
+ rbimpl_fl_unset_raw_raw(RBASIC(obj), flags);
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_FL_UNSET(VALUE obj, VALUE flags)
+{
+ if (RB_FL_ABLE(obj)) {
+ RB_FL_UNSET_RAW(obj, flags);
+ }
+}
+
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+rbimpl_fl_reverse_raw_raw(struct RBasic *obj, VALUE flags)
+{
+ obj->flags ^= flags;
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_FL_REVERSE_RAW(VALUE obj, VALUE flags)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj));
+ rbimpl_fl_reverse_raw_raw(RBASIC(obj), flags);
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_FL_REVERSE(VALUE obj, VALUE flags)
+{
+ if (RB_FL_ABLE(obj)) {
+ RB_FL_REVERSE_RAW(obj, flags);
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_OBJ_TAINTABLE(VALUE obj)
+{
+ if (! RB_FL_ABLE(obj)) {
+ return false;
+ }
+ else if (RB_TYPE_P(obj, RUBY_T_BIGNUM)) {
+ return false;
+ }
+ else if (RB_TYPE_P(obj, RUBY_T_FLOAT)) {
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RB_OBJ_TAINTED_RAW(VALUE obj)
+{
+ return RB_FL_TEST_RAW(obj, RUBY_FL_TAINT);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_OBJ_TAINTED(VALUE obj)
+{
+ return RB_FL_ANY(obj, RUBY_FL_TAINT);
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_OBJ_TAINT_RAW(VALUE obj)
+{
+ RB_FL_SET_RAW(obj, RUBY_FL_TAINT);
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_OBJ_TAINT(VALUE obj)
+{
+ if (RB_OBJ_TAINTABLE(obj)) {
+ RB_OBJ_TAINT_RAW(obj);
+ }
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_OBJ_INFECT_RAW(VALUE dst, VALUE src)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_OBJ_TAINTABLE(dst));
+ RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(src));
+ RB_FL_SET_RAW(dst, RB_OBJ_TAINTED_RAW(src));
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_OBJ_INFECT(VALUE dst, VALUE src)
+{
+ if (RB_OBJ_TAINTABLE(dst) && RB_FL_ABLE(src)) {
+ RB_OBJ_INFECT_RAW(dst, src);
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+/* It is intentional not to return bool here. There is a place in ruby core
+ * (namely class.c:singleton_class_of()) where return value of this function is
+ * verbatimly passed to RB_FL_SET_RAW. */
+static inline VALUE
+RB_OBJ_FROZEN_RAW(VALUE obj)
+{
+ return RB_FL_TEST_RAW(obj, RUBY_FL_FREEZE);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_OBJ_FROZEN(VALUE obj)
+{
+ if (! RB_FL_ABLE(obj)) {
+ return true;
+ }
+ else {
+ return RB_OBJ_FROZEN_RAW(obj);
+ }
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+RB_OBJ_FREEZE_RAW(VALUE obj)
+{
+ RB_FL_SET_RAW(obj, RUBY_FL_FREEZE);
+}
+
+static inline void
+rb_obj_freeze_inline(VALUE x)
+{
+ if (RB_FL_ABLE(x)) {
+ RB_OBJ_FREEZE_RAW(x);
+ if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) {
+ rb_freeze_singleton_class(x);
+ }
+ }
+}
+
+#endif /* RBIMPL_FL_TYPE_H */
diff --git a/include/ruby/internal/gc.h b/include/ruby/internal/gc.h
new file mode 100644
index 0000000000..d94f8a3736
--- /dev/null
+++ b/include/ruby/internal/gc.h
@@ -0,0 +1,57 @@
+#ifndef RBIMPL_GC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_GC_H
+/**
+ * @file
+ * @author Ruby developers <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 Registering values to the GC.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * Inform the garbage collector that `valptr` points to a live Ruby object that
+ * should not be moved. Note that extensions should use this API on global
+ * constants instead of assuming constants defined in Ruby are always alive.
+ * Ruby code can remove global constants.
+ */
+void rb_gc_register_address(VALUE *valptr);
+
+/**
+ * An alias for `rb_gc_register_address()`.
+ */
+void rb_global_variable(VALUE *);
+
+/**
+ * Inform the garbage collector that a pointer previously passed to
+ * `rb_gc_register_address()` no longer points to a live Ruby object.
+ */
+void rb_gc_unregister_address(VALUE *valptr);
+
+/**
+ * Inform the garbage collector that `object` is a live Ruby object that should
+ * not be moved.
+ *
+ * See also: rb_gc_register_address()
+ */
+void rb_gc_register_mark_object(VALUE object);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_GC_H */
diff --git a/include/ruby/internal/glob.h b/include/ruby/internal/glob.h
new file mode 100644
index 0000000000..b78bb75b88
--- /dev/null
+++ b/include/ruby/internal/glob.h
@@ -0,0 +1,35 @@
+#ifndef RBIMPL_GLOB_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_GLOB_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 Declares ::rb_glob().
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+typedef int ruby_glob_func(const char*,VALUE, void*);
+void rb_glob(const char*,void(*)(const char*,VALUE,void*),VALUE);
+int ruby_glob(const char*,int,ruby_glob_func*,VALUE);
+int ruby_brace_glob(const char*,int,ruby_glob_func*,VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_GLOB_H */
diff --git a/include/ruby/internal/globals.h b/include/ruby/internal/globals.h
new file mode 100644
index 0000000000..ddd731349e
--- /dev/null
+++ b/include/ruby/internal/globals.h
@@ -0,0 +1,157 @@
+#ifndef RBIMPL_GLOBALS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_GLOBALS_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 Ruby-level global variables / constants, visible from C.
+ */
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/special_consts.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+#define RUBY_INTEGER_UNIFICATION 1
+
+RUBY_EXTERN VALUE rb_mKernel;
+RUBY_EXTERN VALUE rb_mComparable;
+RUBY_EXTERN VALUE rb_mEnumerable;
+RUBY_EXTERN VALUE rb_mErrno;
+RUBY_EXTERN VALUE rb_mFileTest;
+RUBY_EXTERN VALUE rb_mGC;
+RUBY_EXTERN VALUE rb_mMath;
+RUBY_EXTERN VALUE rb_mProcess;
+RUBY_EXTERN VALUE rb_mWaitReadable;
+RUBY_EXTERN VALUE rb_mWaitWritable;
+
+RUBY_EXTERN VALUE rb_cBasicObject;
+RUBY_EXTERN VALUE rb_cObject;
+RUBY_EXTERN VALUE rb_cArray;
+RUBY_EXTERN VALUE rb_cBinding;
+RUBY_EXTERN VALUE rb_cClass;
+RUBY_EXTERN VALUE rb_cDir;
+RUBY_EXTERN VALUE rb_cEncoding;
+RUBY_EXTERN VALUE rb_cEnumerator;
+RUBY_EXTERN VALUE rb_cFalseClass;
+RUBY_EXTERN VALUE rb_cFile;
+RUBY_EXTERN VALUE rb_cComplex;
+RUBY_EXTERN VALUE rb_cFloat;
+RUBY_EXTERN VALUE rb_cHash;
+RUBY_EXTERN VALUE rb_cIO;
+RUBY_EXTERN VALUE rb_cInteger;
+RUBY_EXTERN VALUE rb_cMatch;
+RUBY_EXTERN VALUE rb_cMethod;
+RUBY_EXTERN VALUE rb_cModule;
+RUBY_EXTERN VALUE rb_cNameErrorMesg;
+RUBY_EXTERN VALUE rb_cNilClass;
+RUBY_EXTERN VALUE rb_cNumeric;
+RUBY_EXTERN VALUE rb_cProc;
+RUBY_EXTERN VALUE rb_cRandom;
+RUBY_EXTERN VALUE rb_cRange;
+RUBY_EXTERN VALUE rb_cRational;
+RUBY_EXTERN VALUE rb_cRegexp;
+RUBY_EXTERN VALUE rb_cStat;
+RUBY_EXTERN VALUE rb_cString;
+RUBY_EXTERN VALUE rb_cStruct;
+RUBY_EXTERN VALUE rb_cSymbol;
+RUBY_EXTERN VALUE rb_cThread;
+RUBY_EXTERN VALUE rb_cTime;
+RUBY_EXTERN VALUE rb_cTrueClass;
+RUBY_EXTERN VALUE rb_cUnboundMethod;
+
+RUBY_EXTERN VALUE rb_eException;
+RUBY_EXTERN VALUE rb_eStandardError;
+RUBY_EXTERN VALUE rb_eSystemExit;
+RUBY_EXTERN VALUE rb_eInterrupt;
+RUBY_EXTERN VALUE rb_eSignal;
+RUBY_EXTERN VALUE rb_eFatal;
+RUBY_EXTERN VALUE rb_eArgError;
+RUBY_EXTERN VALUE rb_eEOFError;
+RUBY_EXTERN VALUE rb_eIndexError;
+RUBY_EXTERN VALUE rb_eStopIteration;
+RUBY_EXTERN VALUE rb_eKeyError;
+RUBY_EXTERN VALUE rb_eRangeError;
+RUBY_EXTERN VALUE rb_eIOError;
+RUBY_EXTERN VALUE rb_eRuntimeError;
+RUBY_EXTERN VALUE rb_eFrozenError;
+RUBY_EXTERN VALUE rb_eSecurityError;
+RUBY_EXTERN VALUE rb_eSystemCallError;
+RUBY_EXTERN VALUE rb_eThreadError;
+RUBY_EXTERN VALUE rb_eTypeError;
+RUBY_EXTERN VALUE rb_eZeroDivError;
+RUBY_EXTERN VALUE rb_eNotImpError;
+RUBY_EXTERN VALUE rb_eNoMemError;
+RUBY_EXTERN VALUE rb_eNoMethodError;
+RUBY_EXTERN VALUE rb_eFloatDomainError;
+RUBY_EXTERN VALUE rb_eLocalJumpError;
+RUBY_EXTERN VALUE rb_eSysStackError;
+RUBY_EXTERN VALUE rb_eRegexpError;
+RUBY_EXTERN VALUE rb_eEncodingError;
+RUBY_EXTERN VALUE rb_eEncCompatError;
+RUBY_EXTERN VALUE rb_eNoMatchingPatternError;
+
+RUBY_EXTERN VALUE rb_eScriptError;
+RUBY_EXTERN VALUE rb_eNameError;
+RUBY_EXTERN VALUE rb_eSyntaxError;
+RUBY_EXTERN VALUE rb_eLoadError;
+
+RUBY_EXTERN VALUE rb_eMathDomainError;
+
+RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr;
+
+RBIMPL_ATTR_PURE()
+static inline VALUE
+rb_class_of(VALUE obj)
+{
+ if (! RB_SPECIAL_CONST_P(obj)) {
+ return RBASIC_CLASS(obj);
+ }
+ else if (obj == RUBY_Qfalse) {
+ return rb_cFalseClass;
+ }
+ else if (obj == RUBY_Qnil) {
+ return rb_cNilClass;
+ }
+ else if (obj == RUBY_Qtrue) {
+ return rb_cTrueClass;
+ }
+ else if (RB_FIXNUM_P(obj)) {
+ return rb_cInteger;
+ }
+ else if (RB_STATIC_SYM_P(obj)) {
+ return rb_cSymbol;
+ }
+ else if (RB_FLONUM_P(obj)) {
+ return rb_cFloat;
+ }
+
+#if !RUBY_DEBUG
+ RBIMPL_UNREACHABLE_RETURN(Qfalse);
+#else
+ RUBY_ASSERT_FAIL("unexpected type");
+#endif
+}
+
+#define CLASS_OF rb_class_of
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_GLOBALS_H */
diff --git a/include/ruby/internal/has/attribute.h b/include/ruby/internal/has/attribute.h
new file mode 100644
index 0000000000..512f061dc5
--- /dev/null
+++ b/include/ruby/internal/has/attribute.h
@@ -0,0 +1,164 @@
+#ifndef RBIMPL_HAS_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_HAS_ATTRIBUTE_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_HAS_ATTRIBUTE.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/token_paste.h"
+
+#if defined(__has_attribute)
+# if __has_attribute(pure) || RBIMPL_COMPILER_IS(GCC)
+# /* FreeBSD's <sys/cdefs.h> defines its own *broken* version of
+# * __has_attribute. Cygwin copied that content to be a victim of the
+# * broken-ness. We don't take them into account. */
+# define RBIMPL_HAVE___HAS_ATTRIBUTE 1
+# endif
+#endif
+
+/** Wraps (or simulates) `__has_attribute`. */
+#if defined(RBIMPL_HAVE___HAS_ATTRIBUTE)
+# define RBIMPL_HAS_ATTRIBUTE(_) __has_attribute(_)
+
+#elif RBIMPL_COMPILER_IS(GCC)
+# /* GCC <= 4 lack __has_attribute predefined macro, while have attributes
+# * themselves. We can simulate the macro like the following: */
+# define RBIMPL_HAS_ATTRIBUTE(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_ATTRIBUTE_, _)
+# define RBIMPL_HAS_ATTRIBUTE_aligned RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0)
+# define RBIMPL_HAS_ATTRIBUTE_alloc_size RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0)
+# define RBIMPL_HAS_ATTRIBUTE_artificial RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0)
+# define RBIMPL_HAS_ATTRIBUTE_always_inline RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0)
+# define RBIMPL_HAS_ATTRIBUTE_cdecl RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0)
+# define RBIMPL_HAS_ATTRIBUTE_cold RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0)
+# define RBIMPL_HAS_ATTRIBUTE_const RBIMPL_COMPILER_SINCE(GCC, 2, 6, 0)
+# define RBIMPL_HAS_ATTRIBUTE_deprecated RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0)
+# define RBIMPL_HAS_ATTRIBUTE_dllexport RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0)
+# define RBIMPL_HAS_ATTRIBUTE_dllimport RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0)
+# define RBIMPL_HAS_ATTRIBUTE_error RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0)
+# define RBIMPL_HAS_ATTRIBUTE_format RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0)
+# define RBIMPL_HAS_ATTRIBUTE_hot RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0)
+# define RBIMPL_HAS_ATTRIBUTE_leaf RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0)
+# define RBIMPL_HAS_ATTRIBUTE_malloc RBIMPL_COMPILER_SINCE(GCC, 3, 0, 0)
+# define RBIMPL_HAS_ATTRIBUTE_no_address_safety_analysis RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0)
+# define RBIMPL_HAS_ATTRIBUTE_no_sanitize_address RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0)
+# define RBIMPL_HAS_ATTRIBUTE_no_sanitize_undefined RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(GCC, 3, 1, 0)
+# define RBIMPL_HAS_ATTRIBUTE_nonnull RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0)
+# define RBIMPL_HAS_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(GCC, 2, 5, 0)
+# define RBIMPL_HAS_ATTRIBUTE_nothrow RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0)
+# define RBIMPL_HAS_ATTRIBUTE_pure RBIMPL_COMPILER_SINCE(GCC, 2,96, 0)
+# define RBIMPL_HAS_ATTRIBUTE_returns_nonnull RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_returns_twice RBIMPL_COMPILER_SINCE(GCC, 4, 1, 0)
+# define RBIMPL_HAS_ATTRIBUTE_stdcall RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0)
+# define RBIMPL_HAS_ATTRIBUTE_unused RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0)
+# define RBIMPL_HAS_ATTRIBUTE_visibility RBIMPL_COMPILER_SINCE(GCC, 3, 3, 0)
+# define RBIMPL_HAS_ATTRIBUTE_warn_unused_result RBIMPL_COMPILER_SINCE(GCC, 3, 4, 0)
+# define RBIMPL_HAS_ATTRIBUTE_warning RBIMPL_COMPILER_SINCE(GCC, 4, 3, 0)
+# define RBIMPL_HAS_ATTRIBUTE_weak RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0)
+# /* Note that "0, 0, 0" might be inaccurate. */
+
+#elif RBIMPL_COMPILER_IS(SunPro)
+# /* Oracle Solaris Studio 12.4 (cc version 5.11) introduced __has_attribute.
+# * Before that, following attributes were available. */
+# /* See https://docs.oracle.com/cd/F24633_01/index.html */
+# define RBIMPL_HAS_ATTRIBUTE(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_ATTRIBUTE_, _)
+# define RBIMPL_HAS_ATTRIBUTE_alias RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_aligned RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_always_inline RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0)
+# define RBIMPL_HAS_ATTRIBUTE_const RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_constructor RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_destructor RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_malloc RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_packed RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_pure RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_returns_twice RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0)
+# define RBIMPL_HAS_ATTRIBUTE_vector_size RBIMPL_COMPILER_SINCE(SunPro, 5, 10, 0)
+# define RBIMPL_HAS_ATTRIBUTE_visibility RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+# define RBIMPL_HAS_ATTRIBUTE_weak RBIMPL_COMPILER_SINCE(SunPro, 5, 9, 0)
+
+#elif defined (_MSC_VER)
+# define RBIMPL_HAS_ATTRIBUTE(_) 0
+# /* Fallback below doesn't work: see win32/Makefile.sub */
+
+#else
+# /* Take config.h definition when available. */
+# define RBIMPL_HAS_ATTRIBUTE(_) (RBIMPL_TOKEN_PASTE(RBIMPL_HAS_ATTRIBUTE_, _)+0)
+# ifdef ALWAYS_INLINE
+# define RBIMPL_HAS_ATTRIBUTE_always_inline 1
+# endif
+# ifdef FUNC_CDECL
+# define RBIMPL_HAS_ATTRIBUTE_cdecl 1
+# endif
+# ifdef CONSTFUNC
+# define RBIMPL_HAS_ATTRIBUTE_const 1
+# endif
+# ifdef DEPRECATED
+# define RBIMPL_HAS_ATTRIBUTE_deprecated 1
+# endif
+# ifdef ERRORFUNC
+# define RBIMPL_HAS_ATTRIBUTE_error 1
+# endif
+# ifdef FUNC_FASTCALL
+# define RBIMPL_HAS_ATTRIBUTE_fastcall 1
+# endif
+# ifdef PUREFUNC
+# define RBIMPL_HAS_ATTRIBUTE_pure 1
+# endif
+# ifdef NO_ADDRESS_SAFETY_ANALYSIS
+# define RBIMPL_HAS_ATTRIBUTE_no_address_safety_analysis 1
+# endif
+# ifdef NO_SANITIZE
+# define RBIMPL_HAS_ATTRIBUTE_no_sanitize 1
+# endif
+# ifdef NO_SANITIZE_ADDRESS
+# define RBIMPL_HAS_ATTRIBUTE_no_sanitize_address 1
+# endif
+# ifdef NOINLINE
+# define RBIMPL_HAS_ATTRIBUTE_noinline 1
+# endif
+# ifdef RBIMPL_FUNC_NONNULL
+# define RBIMPL_HAS_ATTRIBUTE_nonnull 1
+# endif
+# ifdef NORETURN
+# define RBIMPL_HAS_ATTRIBUTE_noreturn 1
+# endif
+# ifdef FUNC_OPTIMIZED
+# define RBIMPL_HAS_ATTRIBUTE_optimize 1
+# endif
+# ifdef FUNC_STDCALL
+# define RBIMPL_HAS_ATTRIBUTE_stdcall 1
+# endif
+# ifdef MAYBE_UNUSED
+# define RBIMPL_HAS_ATTRIBUTE_unused 1
+# endif
+# ifdef WARN_UNUSED_RESULT
+# define RBIMPL_HAS_ATTRIBUTE_warn_unused_result 1
+# endif
+# ifdef WARNINGFUNC
+# define RBIMPL_HAS_ATTRIBUTE_warning 1
+# endif
+# ifdef WEAK
+# define RBIMPL_HAS_ATTRIBUTE_weak 1
+# endif
+#endif
+
+#endif /* RBIMPL_HAS_ATTRIBUTE_H */
diff --git a/include/ruby/internal/has/builtin.h b/include/ruby/internal/has/builtin.h
new file mode 100644
index 0000000000..18cfc69e19
--- /dev/null
+++ b/include/ruby/internal/has/builtin.h
@@ -0,0 +1,105 @@
+#ifndef RBIMPL_HAS_BUILTIN_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_HAS_BUILTIN_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_HAS_BUILTIN.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/token_paste.h"
+
+#if defined(__has_builtin)
+# if RBIMPL_COMPILER_IS(Intel)
+# /* :TODO: Intel C Compiler has __has_builtin (since 19.1 maybe?), and is
+# * reportedly broken. We have to skip them. However the situation can
+# * change. They might improve someday. We need to revisit here later. */
+# elif RBIMPL_COMPILER_IS(GCC) && ! __has_builtin(__builtin_alloca)
+# /* FreeBSD's <sys/cdefs.h> defines its own *broken* version of
+# * __has_builtin. Cygwin copied that content to be a victim of the
+# * broken-ness. We don't take them into account. */
+# else
+# define RBIMPL_HAVE___HAS_BUILTIN 1
+# endif
+#endif
+
+/** Wraps (or simulates) `__has_builtin`. */
+#if defined(RBIMPL_HAVE___HAS_BUILTIN)
+# define RBIMPL_HAS_BUILTIN(_) __has_builtin(_)
+
+#elif RBIMPL_COMPILER_IS(GCC)
+# /* :FIXME: Historically GCC has had tons of builtins, but it implemented
+# * __has_builtin only since GCC 10. This section can be made more
+# * granular. */
+# /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970 */
+# define RBIMPL_HAS_BUILTIN(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_BUILTIN_, _)
+# define RBIMPL_HAS_BUILTIN___builtin_add_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_alloca RBIMPL_COMPILER_SINCE(GCC, 0, 0, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align RBIMPL_COMPILER_SINCE(GCC, 6, 1, 0)
+# /* See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52624 for bswap16. */
+# define RBIMPL_HAS_BUILTIN___builtin_bswap16 RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_bswap32 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_bswap64 RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_clz RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_clzl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_clzll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_constant_p RBIMPL_COMPILER_SINCE(GCC, 2,95, 3)
+# define RBIMPL_HAS_BUILTIN___builtin_ctz RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_ctzl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_ctzll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_expect RBIMPL_COMPILER_SINCE(GCC, 3, 0, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_mul_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_mul_overflow_p RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_popcount RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_popcountl RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_popcountll RBIMPL_COMPILER_SINCE(GCC, 3, 6, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_sub_overflow RBIMPL_COMPILER_SINCE(GCC, 5, 1, 0)
+# define RBIMPL_HAS_BUILTIN___builtin_unreachable RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0)
+# /* Note that "0, 0, 0" might be inaccurate. */
+
+#elif RBIMPL_COMPILER_IS(MSVC)
+# /* MSVC has UNREACHABLE, but that is not __builtin_unreachable. */
+# define RBIMPL_HAS_BUILTIN(_) 0
+
+#else
+# /* Take config.h definition when available */
+# define RBIMPL_HAS_BUILTIN(_) (RBIMPL_TOKEN_PASTE(RBIMPL_HAS_BUILTIN_, _)+0)
+# define RBIMPL_HAS_BUILTIN___builtin_add_overflow HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW
+# define RBIMPL_HAS_BUILTIN___builtin_alloca_with_align HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN
+# define RBIMPL_HAS_BUILTIN___builtin_assume_aligned HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
+# define RBIMPL_HAS_BUILTIN___builtin_bswap16 HAVE_BUILTIN___BUILTIN_BSWAP16
+# define RBIMPL_HAS_BUILTIN___builtin_bswap32 HAVE_BUILTIN___BUILTIN_BSWAP32
+# define RBIMPL_HAS_BUILTIN___builtin_bswap64 HAVE_BUILTIN___BUILTIN_BSWAP64
+# define RBIMPL_HAS_BUILTIN___builtin_clz HAVE_BUILTIN___BUILTIN_CLZ
+# define RBIMPL_HAS_BUILTIN___builtin_clzl HAVE_BUILTIN___BUILTIN_CLZL
+# define RBIMPL_HAS_BUILTIN___builtin_clzll HAVE_BUILTIN___BUILTIN_CLZLL
+# define RBIMPL_HAS_BUILTIN___builtin_constant_p HAVE_BUILTIN___BUILTIN_CONSTANT_P
+# define RBIMPL_HAS_BUILTIN___builtin_ctz HAVE_BUILTIN___BUILTIN_CTZ
+# define RBIMPL_HAS_BUILTIN___builtin_ctzll HAVE_BUILTIN___BUILTIN_CTZLL
+# define RBIMPL_HAS_BUILTIN___builtin_expect HAVE_BUILTIN___BUILTIN_EXPECT
+# define RBIMPL_HAS_BUILTIN___builtin_mul_overflow HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW
+# define RBIMPL_HAS_BUILTIN___builtin_mul_overflow_p HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P
+# define RBIMPL_HAS_BUILTIN___builtin_popcount HAVE_BUILTIN___BUILTIN_POPCOUNT
+# define RBIMPL_HAS_BUILTIN___builtin_popcountll HAVE_BUILTIN___BUILTIN_POPCOUNTLL
+# define RBIMPL_HAS_BUILTIN___builtin_sub_overflow HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW
+# if defined(UNREACHABLE)
+# define RBIMPL_HAS_BUILTIN___builtin_unreachable 1
+# endif
+#endif
+
+#endif /* RBIMPL_HAS_BUILTIN_H */
diff --git a/include/ruby/internal/has/c_attribute.h b/include/ruby/internal/has/c_attribute.h
new file mode 100644
index 0000000000..b7eb94d22a
--- /dev/null
+++ b/include/ruby/internal/has/c_attribute.h
@@ -0,0 +1,38 @@
+#ifndef RBIMPL_HAS_C_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_HAS_C_ATTRIBUTE_H
+/**
+ * @file
+ * @author Ruby developers <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_HAS_C_ATTRIBUTE.
+ */
+
+/** Wraps (or simulates) `__has_c_attribute`. */
+#if defined(__cplusplus)
+# /* Makes no sense. */
+# define RBIMPL_HAS_C_ATTRIBUTE(_) 0
+
+#elif defined(__has_c_attribute)
+# define RBIMPL_HAS_C_ATTRIBUTE(_) __has_c_attribute(_)
+
+#else
+# /* As of writing everything that lacks __has_c_attribute also completely
+# * lacks C2x attributes as well. Might change in future? */
+# define RBIMPL_HAS_C_ATTRIBUTE(_) 0
+#endif
+
+#endif /* RBIMPL_HAS_C_ATTRIBUTE_H */
diff --git a/include/ruby/internal/has/cpp_attribute.h b/include/ruby/internal/has/cpp_attribute.h
new file mode 100644
index 0000000000..255f611d70
--- /dev/null
+++ b/include/ruby/internal/has/cpp_attribute.h
@@ -0,0 +1,87 @@
+#ifndef RBIMPL_HAS_CPP_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_HAS_CPP_ATTRIBUTE_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_HAS_CPP_ATTRIBUTE.
+ */
+#include "ruby/internal/compiler_is.h"
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/token_paste.h"
+
+/** @cond INTERNAL_MACRO */
+#if RBIMPL_COMPILER_IS(SunPro)
+# /* Oracle Developer Studio 12.5's C++ preprocessor is reportedly broken. We
+# * could simulate __has_cpp_attribute like below, but don't know the exact
+# * list of which version supported which attribute. Just kill everything for
+# * now. If you can please :FIXME: */
+# /* https://unicode-org.atlassian.net/browse/ICU-12893 */
+# /* https://github.com/boostorg/config/pull/95 */
+# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) 0
+
+#elif defined(__has_cpp_attribute)
+# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) __has_cpp_attribute(_)
+
+#elif RBIMPL_COMPILER_IS(MSVC)
+# /* MSVC has never updated its __cplusplus since forever (unless specified
+# * explicitly by a compiler flag). They also lack __has_cpp_attribute until
+# * 2019. However, they do have attributes since 2015 or so. */
+# /* https://docs.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance */
+# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_CPP_ATTRIBUTE_, _)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 0)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_carries_dependency 200809 * RBIMPL_COMPILER_SINCE(MSVC, 19, 00, 0)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(MSVC, 19, 10, 0)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_fallthrough 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 10, 0)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_maybe_unused 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 0)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_nodiscard 201603 * RBIMPL_COMPILER_SINCE(MSVC, 19, 11, 0)
+
+#elif RBIMPL_COMPILER_BEFORE(Clang, 3, 6, 0)
+# /* Clang 3.6.0 introduced __has_cpp_attribute. Prior to that following
+# * attributes were already there. */
+# /* https://clang.llvm.org/cxx_status.html */
+# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_CPP_ATTRIBUTE_, _)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(Clang, 3, 3, 0)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(Clang, 3, 4, 0)
+
+#elif RBIMPL_COMPILER_BEFORE(GCC, 5, 0, 0)
+# /* GCC 5+ have __has_cpp_attribute, while 4.x had following attributes. */
+# /* https://gcc.gnu.org/projects/cxx-status.html */
+# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_CPP_ATTRIBUTE_, _)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_noreturn 200809 * RBIMPL_COMPILER_SINCE(GCC, 4, 8, 0)
+# define RBIMPL_HAS_CPP_ATTRIBUTE_deprecated 201309 * RBIMPL_COMPILER_SINCE(GCC, 4, 9, 0)
+
+#else
+# /* :FIXME:
+# * Candidate compilers to list here:
+# * - icpc: They have __INTEL_CXX11_MODE__.
+# */
+# define RBIMPL_HAS_CPP_ATTRIBUTE0(_) 0
+#endif
+/** @endcond */
+
+/** Wraps (or simulates) `__has_cpp_attribute`. */
+#if ! defined(__cplusplus)
+# /* Makes no sense. */
+# define RBIMPL_HAS_CPP_ATTRIBUTE(_) 0
+#else
+# /* GCC needs workarounds. See https://gcc.godbolt.org/z/jdz3pa */
+# define RBIMPL_HAS_CPP_ATTRIBUTE(_) \
+ ((RBIMPL_HAS_CPP_ATTRIBUTE0(_) <= __cplusplus) ? RBIMPL_HAS_CPP_ATTRIBUTE0(_) : 0)
+#endif
+
+#endif /* RBIMPL_HAS_CPP_ATTRIBUTE_H */
diff --git a/include/ruby/internal/has/declspec_attribute.h b/include/ruby/internal/has/declspec_attribute.h
new file mode 100644
index 0000000000..02610338b8
--- /dev/null
+++ b/include/ruby/internal/has/declspec_attribute.h
@@ -0,0 +1,48 @@
+#ifndef RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_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_HAS_DECLSPEC_ATTRIBUTE.
+ */
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/token_paste.h"
+
+/** Wraps (or simulates) `__has_declspec_attribute`. */
+#if defined(__has_declspec_attribute)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE(_) __has_declspec_attribute(_)
+#else
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE(_) RBIMPL_TOKEN_PASTE(RBIMPL_HAS_DECLSPEC_ATTRIBUTE_, _)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_align RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_deprecated RBIMPL_COMPILER_SINCE(MSVC,13, 0, 0)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_dllexport RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_dllimport RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_empty_bases RBIMPL_COMPILER_SINCE(MSVC,19, 0, 23918)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noalias RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noinline RBIMPL_COMPILER_SINCE(MSVC,13, 0, 0)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_noreturn RBIMPL_COMPILER_SINCE(MSVC,11, 0, 0)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_nothrow RBIMPL_COMPILER_SINCE(MSVC, 8, 0, 0)
+# define RBIMPL_HAS_DECLSPEC_ATTRIBUTE_restrict RBIMPL_COMPILER_SINCE(MSVC,14, 0, 0)
+# /* Note that "8, 0, 0" might be inaccurate. */
+# if ! defined(__cplusplus)
+# /* Clang has this in both C/C++, but MSVC has this in C++ only.*/
+# undef RBIMPL_HAS_DECLSPEC_ATTRIBUTE_nothrow
+# endif
+#endif
+
+#endif /* RBIMPL_HAS_DECLSPEC_ATTRIBUTE_H */
diff --git a/include/ruby/internal/has/extension.h b/include/ruby/internal/has/extension.h
new file mode 100644
index 0000000000..9ceb365ab9
--- /dev/null
+++ b/include/ruby/internal/has/extension.h
@@ -0,0 +1,33 @@
+#ifndef RBIMPL_HAS_EXTENSION_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_HAS_EXTENSION_H
+/**
+ * @file
+ * @author Ruby developers <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_HAS_EXTENSION.
+ */
+#include "ruby/internal/has/feature.h"
+
+/** Wraps (or simulates) `__has_extension`. */
+#if defined(__has_extension)
+# define RBIMPL_HAS_EXTENSION(_) __has_extension(_)
+#else
+# /* Pre-3.0 clang had __has_feature but not __has_extension. */
+# define RBIMPL_HAS_EXTENSION(_) RBIMPL_HAS_FEATURE(_)
+#endif
+
+#endif /* RBIMPL_HAS_EXTENSION_H */
diff --git a/include/ruby/internal/has/feature.h b/include/ruby/internal/has/feature.h
new file mode 100644
index 0000000000..b827590c00
--- /dev/null
+++ b/include/ruby/internal/has/feature.h
@@ -0,0 +1,31 @@
+#ifndef RBIMPL_HAS_FEATURE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_HAS_FEATURE_H
+/**
+ * @file
+ * @author Ruby developers <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_HAS_FEATURE.
+ */
+
+/** Wraps (or simulates) `__has_feature`. */
+#if defined(__has_feature)
+# define RBIMPL_HAS_FEATURE(_) __has_feature(_)
+#else
+# define RBIMPL_HAS_FEATURE(_) 0
+#endif
+
+#endif /* RBIMPL_HAS_FEATURE_H */
diff --git a/include/ruby/internal/has/warning.h b/include/ruby/internal/has/warning.h
new file mode 100644
index 0000000000..03975ecc2f
--- /dev/null
+++ b/include/ruby/internal/has/warning.h
@@ -0,0 +1,31 @@
+#ifndef RBIMPL_HAS_WARNING_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_HAS_WARNING_H
+/**
+ * @file
+ * @author Ruby developers <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_HAS_WARNING.
+ */
+
+/** Wraps (or simulates) `__has_warning`. */
+#if defined(__has_warning)
+# define RBIMPL_HAS_WARNING(_) __has_warning(_)
+#else
+# define RBIMPL_HAS_WARNING(_) 0
+#endif
+
+#endif /* RBIMPL_HAS_WARNING_H */
diff --git a/include/ruby/internal/intern/array.h b/include/ruby/internal/intern/array.h
new file mode 100644
index 0000000000..aafe0d1350
--- /dev/null
+++ b/include/ruby/internal/intern/array.h
@@ -0,0 +1,78 @@
+#ifndef RBIMPL_INTERN_ARRAY_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_ARRAY_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_cArray.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* array.c */
+void rb_mem_clear(VALUE*, long);
+VALUE rb_assoc_new(VALUE, VALUE);
+VALUE rb_check_array_type(VALUE);
+VALUE rb_ary_new(void);
+VALUE rb_ary_new_capa(long capa);
+VALUE rb_ary_new_from_args(long n, ...);
+VALUE rb_ary_new_from_values(long n, const VALUE *elts);
+VALUE rb_ary_tmp_new(long);
+void rb_ary_free(VALUE);
+void rb_ary_modify(VALUE);
+VALUE rb_ary_freeze(VALUE);
+VALUE rb_ary_shared_with_p(VALUE, VALUE);
+VALUE rb_ary_aref(int, const VALUE*, VALUE);
+VALUE rb_ary_subseq(VALUE, long, long);
+void rb_ary_store(VALUE, long, VALUE);
+VALUE rb_ary_dup(VALUE);
+VALUE rb_ary_resurrect(VALUE ary);
+VALUE rb_ary_to_ary(VALUE);
+VALUE rb_ary_to_s(VALUE);
+VALUE rb_ary_cat(VALUE, const VALUE *, long);
+VALUE rb_ary_push(VALUE, VALUE);
+VALUE rb_ary_pop(VALUE);
+VALUE rb_ary_shift(VALUE);
+VALUE rb_ary_unshift(VALUE, VALUE);
+VALUE rb_ary_entry(VALUE, long);
+VALUE rb_ary_each(VALUE);
+VALUE rb_ary_join(VALUE, VALUE);
+VALUE rb_ary_reverse(VALUE);
+VALUE rb_ary_rotate(VALUE, long);
+VALUE rb_ary_sort(VALUE);
+VALUE rb_ary_sort_bang(VALUE);
+VALUE rb_ary_delete(VALUE, VALUE);
+VALUE rb_ary_delete_at(VALUE, long);
+VALUE rb_ary_clear(VALUE);
+VALUE rb_ary_plus(VALUE, VALUE);
+VALUE rb_ary_concat(VALUE, VALUE);
+VALUE rb_ary_assoc(VALUE, VALUE);
+VALUE rb_ary_rassoc(VALUE, VALUE);
+VALUE rb_ary_includes(VALUE, VALUE);
+VALUE rb_ary_cmp(VALUE, VALUE);
+VALUE rb_ary_replace(VALUE copy, VALUE orig);
+VALUE rb_get_values_at(VALUE, long, int, const VALUE*, VALUE(*)(VALUE,long));
+VALUE rb_ary_resize(VALUE ary, long len);
+#define rb_ary_new2 rb_ary_new_capa
+#define rb_ary_new3 rb_ary_new_from_args
+#define rb_ary_new4 rb_ary_new_from_values
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_ARRAY_H */
diff --git a/include/ruby/internal/intern/bignum.h b/include/ruby/internal/intern/bignum.h
new file mode 100644
index 0000000000..1ac92e9c90
--- /dev/null
+++ b/include/ruby/internal/intern/bignum.h
@@ -0,0 +1,105 @@
+#ifndef RBIMPL_INTERN_BIGNUM_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_BIGNUM_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 so-called rb_cBignum.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
+
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/backward/2/long_long.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* bignum.c */
+VALUE rb_big_new(size_t, int);
+int rb_bigzero_p(VALUE x);
+VALUE rb_big_clone(VALUE);
+void rb_big_2comp(VALUE);
+VALUE rb_big_norm(VALUE);
+void rb_big_resize(VALUE big, size_t len);
+VALUE rb_cstr_to_inum(const char*, int, int);
+VALUE rb_str_to_inum(VALUE, int, int);
+VALUE rb_cstr2inum(const char*, int);
+VALUE rb_str2inum(VALUE, int);
+VALUE rb_big2str(VALUE, int);
+long rb_big2long(VALUE);
+#define rb_big2int(x) rb_big2long(x)
+unsigned long rb_big2ulong(VALUE);
+#define rb_big2uint(x) rb_big2ulong(x)
+#if HAVE_LONG_LONG
+LONG_LONG rb_big2ll(VALUE);
+unsigned LONG_LONG rb_big2ull(VALUE);
+#endif /* HAVE_LONG_LONG */
+void rb_big_pack(VALUE val, unsigned long *buf, long num_longs);
+VALUE rb_big_unpack(unsigned long *buf, long num_longs);
+int rb_uv_to_utf8(char[6],unsigned long);
+VALUE rb_dbl2big(double);
+double rb_big2dbl(VALUE);
+VALUE rb_big_cmp(VALUE, VALUE);
+VALUE rb_big_eq(VALUE, VALUE);
+VALUE rb_big_eql(VALUE, VALUE);
+VALUE rb_big_plus(VALUE, VALUE);
+VALUE rb_big_minus(VALUE, VALUE);
+VALUE rb_big_mul(VALUE, VALUE);
+VALUE rb_big_div(VALUE, VALUE);
+VALUE rb_big_idiv(VALUE, VALUE);
+VALUE rb_big_modulo(VALUE, VALUE);
+VALUE rb_big_divmod(VALUE, VALUE);
+VALUE rb_big_pow(VALUE, VALUE);
+VALUE rb_big_and(VALUE, VALUE);
+VALUE rb_big_or(VALUE, VALUE);
+VALUE rb_big_xor(VALUE, VALUE);
+VALUE rb_big_lshift(VALUE, VALUE);
+VALUE rb_big_rshift(VALUE, VALUE);
+
+/* For rb_integer_pack and rb_integer_unpack: */
+/* "MS" in MSWORD and MSBYTE means "most significant" */
+/* "LS" in LSWORD and LSBYTE means "least significant" */
+#define INTEGER_PACK_MSWORD_FIRST 0x01
+#define INTEGER_PACK_LSWORD_FIRST 0x02
+#define INTEGER_PACK_MSBYTE_FIRST 0x10
+#define INTEGER_PACK_LSBYTE_FIRST 0x20
+#define INTEGER_PACK_NATIVE_BYTE_ORDER 0x40
+#define INTEGER_PACK_2COMP 0x80
+#define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION 0x400
+/* For rb_integer_unpack: */
+#define INTEGER_PACK_FORCE_BIGNUM 0x100
+#define INTEGER_PACK_NEGATIVE 0x200
+/* Combinations: */
+#define INTEGER_PACK_LITTLE_ENDIAN \
+ (INTEGER_PACK_LSWORD_FIRST | \
+ INTEGER_PACK_LSBYTE_FIRST)
+#define INTEGER_PACK_BIG_ENDIAN \
+ (INTEGER_PACK_MSWORD_FIRST | \
+ INTEGER_PACK_MSBYTE_FIRST)
+int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags);
+VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags);
+size_t rb_absint_size(VALUE val, int *nlz_bits_ret);
+size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret);
+int rb_absint_singlebit_p(VALUE val);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_BIGNUM_H */
diff --git a/include/ruby/internal/intern/class.h b/include/ruby/internal/intern/class.h
new file mode 100644
index 0000000000..d3be80d283
--- /dev/null
+++ b/include/ruby/internal/intern/class.h
@@ -0,0 +1,57 @@
+#ifndef RBIMPL_INTERN_CLASS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_CLASS_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_cClass/::rb_cModule.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/backward/2/stdarg.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* class.c */
+VALUE rb_class_new(VALUE);
+VALUE rb_mod_init_copy(VALUE, VALUE);
+VALUE rb_singleton_class_clone(VALUE);
+void rb_singleton_class_attached(VALUE,VALUE);
+void rb_check_inheritable(VALUE);
+VALUE rb_define_class_id(ID, VALUE);
+VALUE rb_define_class_id_under(VALUE, ID, VALUE);
+VALUE rb_module_new(void);
+VALUE rb_define_module_id(ID);
+VALUE rb_define_module_id_under(VALUE, ID);
+VALUE rb_mod_included_modules(VALUE);
+VALUE rb_mod_include_p(VALUE, VALUE);
+VALUE rb_mod_ancestors(VALUE);
+VALUE rb_class_instance_methods(int, const VALUE*, VALUE);
+VALUE rb_class_public_instance_methods(int, const VALUE*, VALUE);
+VALUE rb_class_protected_instance_methods(int, const VALUE*, VALUE);
+VALUE rb_class_private_instance_methods(int, const VALUE*, VALUE);
+VALUE rb_obj_singleton_methods(int, const VALUE*, VALUE);
+void rb_define_method_id(VALUE, ID, VALUE (*)(ANYARGS), int);
+void rb_undef(VALUE, ID);
+void rb_define_protected_method(VALUE, const char*, VALUE (*)(ANYARGS), int);
+void rb_define_private_method(VALUE, const char*, VALUE (*)(ANYARGS), int);
+void rb_define_singleton_method(VALUE, const char*, VALUE(*)(ANYARGS), int);
+VALUE rb_singleton_class(VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_CLASS_H */
diff --git a/include/ruby/internal/intern/compar.h b/include/ruby/internal/intern/compar.h
new file mode 100644
index 0000000000..d226ca37b1
--- /dev/null
+++ b/include/ruby/internal/intern/compar.h
@@ -0,0 +1,34 @@
+#ifndef RBIMPL_INTERN_COMPAR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_COMPAR_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_mComparable.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* compar.c */
+int rb_cmpint(VALUE, VALUE, VALUE);
+NORETURN(void rb_cmperr(VALUE, VALUE));
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_COMPAR_H */
diff --git a/include/ruby/internal/intern/complex.h b/include/ruby/internal/intern/complex.h
new file mode 100644
index 0000000000..70343221f6
--- /dev/null
+++ b/include/ruby/internal/intern/complex.h
@@ -0,0 +1,60 @@
+#ifndef RBIMPL_INTERN_COMPLEX_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_COMPLEX_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_cComplex.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* complex.c */
+VALUE rb_complex_raw(VALUE, VALUE);
+#define rb_complex_raw1(x) rb_complex_raw((x), INT2FIX(0))
+#define rb_complex_raw2(x,y) rb_complex_raw((x), (y))
+VALUE rb_complex_new(VALUE, VALUE);
+#define rb_complex_new1(x) rb_complex_new((x), INT2FIX(0))
+#define rb_complex_new2(x,y) rb_complex_new((x), (y))
+VALUE rb_complex_new_polar(VALUE abs, VALUE arg);
+DEPRECATED_BY(rb_complex_new_polar, VALUE rb_complex_polar(VALUE abs, VALUE arg));
+VALUE rb_complex_real(VALUE z);
+VALUE rb_complex_imag(VALUE z);
+VALUE rb_complex_plus(VALUE x, VALUE y);
+VALUE rb_complex_minus(VALUE x, VALUE y);
+VALUE rb_complex_mul(VALUE x, VALUE y);
+VALUE rb_complex_div(VALUE x, VALUE y);
+VALUE rb_complex_uminus(VALUE z);
+VALUE rb_complex_conjugate(VALUE z);
+VALUE rb_complex_abs(VALUE z);
+VALUE rb_complex_arg(VALUE z);
+VALUE rb_complex_pow(VALUE base, VALUE exp);
+VALUE rb_dbl_complex_new(double real, double imag);
+#define rb_complex_add rb_complex_plus
+#define rb_complex_sub rb_complex_minus
+#define rb_complex_nagate rb_complex_uminus
+
+VALUE rb_Complex(VALUE, VALUE);
+#define rb_Complex1(x) rb_Complex((x), INT2FIX(0))
+#define rb_Complex2(x,y) rb_Complex((x), (y))
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_COMPLEX_H */
diff --git a/include/ruby/internal/intern/cont.h b/include/ruby/internal/intern/cont.h
new file mode 100644
index 0000000000..cfa5630af2
--- /dev/null
+++ b/include/ruby/internal/intern/cont.h
@@ -0,0 +1,41 @@
+#ifndef RBIMPL_INTERN_CONT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_CONT_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_cFiber.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/iterator.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* cont.c */
+VALUE rb_fiber_new(rb_block_call_func_t, VALUE);
+VALUE rb_fiber_new_kw(rb_block_call_func_t, VALUE, int kw_splat);
+VALUE rb_fiber_resume(VALUE fib, int argc, const VALUE *argv);
+VALUE rb_fiber_resume_kw(VALUE fib, int argc, const VALUE *argv, int kw_splat);
+VALUE rb_fiber_yield(int argc, const VALUE *argv);
+VALUE rb_fiber_yield_kw(int argc, const VALUE *argv, int kw_splat);
+VALUE rb_fiber_current(void);
+VALUE rb_fiber_alive_p(VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_CONT_H */
diff --git a/include/ruby/internal/intern/dir.h b/include/ruby/internal/intern/dir.h
new file mode 100644
index 0000000000..936f4e1f36
--- /dev/null
+++ b/include/ruby/internal/intern/dir.h
@@ -0,0 +1,33 @@
+#ifndef RBIMPL_INTERN_DIR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_DIR_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_cDir.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* dir.c */
+VALUE rb_dir_getwd(void);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_DIR_H */
diff --git a/include/ruby/internal/intern/enum.h b/include/ruby/internal/intern/enum.h
new file mode 100644
index 0000000000..17c20c1c0a
--- /dev/null
+++ b/include/ruby/internal/intern/enum.h
@@ -0,0 +1,33 @@
+#ifndef RBIMPL_INTERN_ENUM_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_ENUM_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_mEnumerable.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* enum.c */
+VALUE rb_enum_values_pack(int, const VALUE*);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_ENUM_H */
diff --git a/include/ruby/internal/intern/enumerator.h b/include/ruby/internal/intern/enumerator.h
new file mode 100644
index 0000000000..c81485155c
--- /dev/null
+++ b/include/ruby/internal/intern/enumerator.h
@@ -0,0 +1,80 @@
+#ifndef RBIMPL_INTERN_ENUMERATOR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_ENUMERATOR_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_cEnumerator.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/intern/eval.h" /* rb_frame_this_func */
+#include "ruby/internal/iterator.h" /* rb_block_given_p */
+#include "ruby/internal/symbol.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+typedef VALUE rb_enumerator_size_func(VALUE, VALUE, VALUE);
+
+typedef struct {
+ VALUE begin;
+ VALUE end;
+ VALUE step;
+ int exclude_end;
+} rb_arithmetic_sequence_components_t;
+
+/* enumerator.c */
+VALUE rb_enumeratorize(VALUE, VALUE, int, const VALUE *);
+VALUE rb_enumeratorize_with_size(VALUE, VALUE, int, const VALUE *, rb_enumerator_size_func *);
+VALUE rb_enumeratorize_with_size_kw(VALUE, VALUE, int, const VALUE *, rb_enumerator_size_func *, int);
+int rb_arithmetic_sequence_extract(VALUE, rb_arithmetic_sequence_components_t *);
+VALUE rb_arithmetic_sequence_beg_len_step(VALUE, long *begp, long *lenp, long *stepp, long len, int err);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#ifndef RUBY_EXPORT
+# define rb_enumeratorize_with_size(obj, id, argc, argv, size_fn) \
+ rb_enumeratorize_with_size(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn))
+# define rb_enumeratorize_with_size_kw(obj, id, argc, argv, size_fn, kw_splat) \
+ rb_enumeratorize_with_size_kw(obj, id, argc, argv, (rb_enumerator_size_func *)(size_fn), kw_splat)
+#endif
+
+#define SIZED_ENUMERATOR(obj, argc, argv, size_fn) \
+ rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), \
+ (argc), (argv), (size_fn))
+
+#define SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) \
+ rb_enumeratorize_with_size_kw((obj), ID2SYM(rb_frame_this_func()), \
+ (argc), (argv), (size_fn), (kw_splat))
+
+#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) do { \
+ if (!rb_block_given_p()) \
+ return SIZED_ENUMERATOR(obj, argc, argv, size_fn); \
+ } while (0)
+
+#define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \
+ if (!rb_block_given_p()) \
+ return SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat); \
+ } while (0)
+
+#define RETURN_ENUMERATOR(obj, argc, argv) \
+ RETURN_SIZED_ENUMERATOR(obj, argc, argv, 0)
+
+#define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) \
+ RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, 0, kw_splat)
+
+#endif /* RBIMPL_INTERN_ENUMERATOR_H */
diff --git a/include/ruby/internal/intern/error.h b/include/ruby/internal/intern/error.h
new file mode 100644
index 0000000000..aa9fe2daba
--- /dev/null
+++ b/include/ruby/internal/intern/error.h
@@ -0,0 +1,82 @@
+#ifndef RBIMPL_INTERN_ERROR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_ERROR_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_eException.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/backward/2/assume.h"
+#include "ruby/backward/2/attributes.h"
+
+#define UNLIMITED_ARGUMENTS (-1)
+#define rb_exc_new2 rb_exc_new_cstr
+#define rb_exc_new3 rb_exc_new_str
+#define rb_check_trusted rb_check_trusted
+#define rb_check_trusted_inline rb_check_trusted
+#define rb_check_arity rb_check_arity
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* error.c */
+VALUE rb_exc_new(VALUE, const char*, long);
+VALUE rb_exc_new_cstr(VALUE, const char*);
+VALUE rb_exc_new_str(VALUE, VALUE);
+PRINTF_ARGS(NORETURN(void rb_loaderror(const char*, ...)), 1, 2);
+PRINTF_ARGS(NORETURN(void rb_loaderror_with_path(VALUE path, const char*, ...)), 2, 3);
+PRINTF_ARGS(NORETURN(void rb_name_error(ID, const char*, ...)), 2, 3);
+PRINTF_ARGS(NORETURN(void rb_name_error_str(VALUE, const char*, ...)), 2, 3);
+PRINTF_ARGS(NORETURN(void rb_frozen_error_raise(VALUE, const char*, ...)), 2, 3);
+NORETURN(void rb_invalid_str(const char*, const char*));
+NORETURN(void rb_error_frozen(const char*));
+NORETURN(void rb_error_frozen_object(VALUE));
+void rb_error_untrusted(VALUE);
+void rb_check_frozen(VALUE);
+void rb_check_trusted(VALUE);
+void rb_check_copyable(VALUE obj, VALUE orig);
+NORETURN(MJIT_STATIC void rb_error_arity(int, int, int));
+RBIMPL_SYMBOL_EXPORT_END()
+
+/* Does anyone use this? Remain not deleted for compatibility. */
+#define rb_check_frozen_internal(obj) do { \
+ VALUE frozen_obj = (obj); \
+ if (RB_UNLIKELY(RB_OBJ_FROZEN(frozen_obj))) { \
+ rb_error_frozen_object(frozen_obj); \
+ } \
+ } while (0)
+
+static inline void
+rb_check_frozen_inline(VALUE obj)
+{
+ if (RB_UNLIKELY(RB_OBJ_FROZEN(obj))) {
+ rb_error_frozen_object(obj);
+ }
+}
+#define rb_check_frozen rb_check_frozen_inline
+
+static inline int
+rb_check_arity(int argc, int min, int max)
+{
+ if ((argc < min) || (max != UNLIMITED_ARGUMENTS && argc > max))
+ rb_error_arity(argc, min, max);
+ return argc;
+}
+
+#endif /* RBIMPL_INTERN_ERROR_H */
diff --git a/include/ruby/internal/intern/eval.h b/include/ruby/internal/intern/eval.h
new file mode 100644
index 0000000000..11957053d7
--- /dev/null
+++ b/include/ruby/internal/intern/eval.h
@@ -0,0 +1,59 @@
+#ifndef RBIMPL_INTERN_EVAL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_EVAL_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 Pre-1.9 era evaluator APIs (now considered miscellaneous).
+ */
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* eval.c */
+RBIMPL_ATTR_NORETURN()
+void rb_exc_raise(VALUE);
+
+RBIMPL_ATTR_NORETURN()
+void rb_exc_fatal(VALUE);
+
+RBIMPL_ATTR_NORETURN()
+VALUE rb_f_exit(int, const VALUE*);
+
+RBIMPL_ATTR_NORETURN()
+VALUE rb_f_abort(int, const VALUE*);
+
+RBIMPL_ATTR_NORETURN()
+void rb_interrupt(void);
+ID rb_frame_this_func(void);
+
+RBIMPL_ATTR_NORETURN()
+void rb_jump_tag(int);
+void rb_obj_call_init(VALUE, int, const VALUE*);
+void rb_obj_call_init_kw(VALUE, int, const VALUE*, int);
+VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*);
+ID rb_frame_callee(void);
+VALUE rb_make_exception(int, const VALUE*);
+
+/* eval_jump.c */
+void rb_set_end_proc(void (*)(VALUE), VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_EVAL_H */
diff --git a/include/ruby/internal/intern/file.h b/include/ruby/internal/intern/file.h
new file mode 100644
index 0000000000..9ebefece66
--- /dev/null
+++ b/include/ruby/internal/intern/file.h
@@ -0,0 +1,42 @@
+#ifndef RBIMPL_INTERN_FILE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_FILE_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_cFile.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* file.c */
+VALUE rb_file_s_expand_path(int, const VALUE *);
+VALUE rb_file_expand_path(VALUE, VALUE);
+VALUE rb_file_s_absolute_path(int, const VALUE *);
+VALUE rb_file_absolute_path(VALUE, VALUE);
+VALUE rb_file_dirname(VALUE fname);
+int rb_find_file_ext(VALUE*, const char* const*);
+VALUE rb_find_file(VALUE);
+VALUE rb_file_directory_p(VALUE,VALUE);
+VALUE rb_str_encode_ospath(VALUE);
+int rb_is_absolute_path(const char *);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_FILE_H */
diff --git a/include/ruby/internal/intern/gc.h b/include/ruby/internal/intern/gc.h
new file mode 100644
index 0000000000..30759e0ded
--- /dev/null
+++ b/include/ruby/internal/intern/gc.h
@@ -0,0 +1,57 @@
+#ifndef RBIMPL_INTERN_GC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_GC_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_mGC.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/backward/2/attributes.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* gc.c */
+COLDFUNC NORETURN(void rb_memerror(void));
+PUREFUNC(int rb_during_gc(void));
+void rb_gc_mark_locations(const VALUE*, const VALUE*);
+void rb_mark_tbl(struct st_table*);
+void rb_mark_tbl_no_pin(struct st_table*);
+void rb_mark_set(struct st_table*);
+void rb_mark_hash(struct st_table*);
+void rb_gc_update_tbl_refs(st_table *ptr);
+void rb_gc_mark_maybe(VALUE);
+void rb_gc_mark(VALUE);
+void rb_gc_mark_movable(VALUE);
+VALUE rb_gc_location(VALUE);
+void rb_gc_force_recycle(VALUE);
+void rb_gc(void);
+void rb_gc_copy_finalizer(VALUE,VALUE);
+VALUE rb_gc_enable(void);
+VALUE rb_gc_disable(void);
+VALUE rb_gc_start(void);
+VALUE rb_define_finalizer(VALUE, VALUE);
+VALUE rb_undefine_finalizer(VALUE);
+size_t rb_gc_count(void);
+size_t rb_gc_stat(VALUE);
+VALUE rb_gc_latest_gc_info(VALUE);
+void rb_gc_adjust_memory_usage(ssize_t);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_GC_H */
diff --git a/include/ruby/internal/intern/hash.h b/include/ruby/internal/intern/hash.h
new file mode 100644
index 0000000000..c7a27c2cfa
--- /dev/null
+++ b/include/ruby/internal/intern/hash.h
@@ -0,0 +1,59 @@
+#ifndef RBIMPL_INTERN_HASH_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_HASH_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_cHash.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/st.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* hash.c */
+void rb_st_foreach_safe(struct st_table *, int (*)(st_data_t, st_data_t, st_data_t), st_data_t);
+#define st_foreach_safe rb_st_foreach_safe
+VALUE rb_check_hash_type(VALUE);
+void rb_hash_foreach(VALUE, int (*)(VALUE, VALUE, VALUE), VALUE);
+VALUE rb_hash(VALUE);
+VALUE rb_hash_new(void);
+VALUE rb_hash_dup(VALUE);
+VALUE rb_hash_freeze(VALUE);
+VALUE rb_hash_aref(VALUE, VALUE);
+VALUE rb_hash_lookup(VALUE, VALUE);
+VALUE rb_hash_lookup2(VALUE, VALUE, VALUE);
+VALUE rb_hash_fetch(VALUE, VALUE);
+VALUE rb_hash_aset(VALUE, VALUE, VALUE);
+VALUE rb_hash_clear(VALUE);
+VALUE rb_hash_delete_if(VALUE);
+VALUE rb_hash_delete(VALUE,VALUE);
+VALUE rb_hash_set_ifnone(VALUE hash, VALUE ifnone);
+void rb_hash_bulk_insert(long, const VALUE *, VALUE);
+typedef VALUE rb_hash_update_func(VALUE newkey, VALUE oldkey, VALUE value);
+VALUE rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func);
+struct st_table *rb_hash_tbl(VALUE, const char *file, int line);
+int rb_path_check(const char*);
+int rb_env_path_tainted(void);
+VALUE rb_env_clear(void);
+VALUE rb_hash_size(VALUE);
+void rb_hash_free(VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_HASH_H */
diff --git a/include/ruby/internal/intern/io.h b/include/ruby/internal/intern/io.h
new file mode 100644
index 0000000000..d2f2e53486
--- /dev/null
+++ b/include/ruby/internal/intern/io.h
@@ -0,0 +1,70 @@
+#ifndef RBIMPL_INTERN_IO_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_IO_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_cIO.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* io.c */
+#define rb_defout rb_stdout
+RUBY_EXTERN VALUE rb_fs;
+RUBY_EXTERN VALUE rb_output_fs;
+RUBY_EXTERN VALUE rb_rs;
+RUBY_EXTERN VALUE rb_default_rs;
+RUBY_EXTERN VALUE rb_output_rs;
+VALUE rb_io_write(VALUE, VALUE);
+VALUE rb_io_gets(VALUE);
+VALUE rb_io_getbyte(VALUE);
+VALUE rb_io_ungetc(VALUE, VALUE);
+VALUE rb_io_ungetbyte(VALUE, VALUE);
+VALUE rb_io_close(VALUE);
+VALUE rb_io_flush(VALUE);
+VALUE rb_io_eof(VALUE);
+VALUE rb_io_binmode(VALUE);
+VALUE rb_io_ascii8bit_binmode(VALUE);
+VALUE rb_io_addstr(VALUE, VALUE);
+VALUE rb_io_printf(int, const VALUE*, VALUE);
+VALUE rb_io_print(int, const VALUE*, VALUE);
+VALUE rb_io_puts(int, const VALUE*, VALUE);
+VALUE rb_io_fdopen(int, int, const char*);
+VALUE rb_io_get_io(VALUE);
+VALUE rb_file_open(const char*, const char*);
+VALUE rb_file_open_str(VALUE, const char*);
+VALUE rb_gets(void);
+void rb_write_error(const char*);
+void rb_write_error2(const char*, long);
+void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds);
+int rb_pipe(int *pipes);
+int rb_reserved_fd_p(int fd);
+int rb_cloexec_open(const char *pathname, int flags, mode_t mode);
+int rb_cloexec_dup(int oldfd);
+int rb_cloexec_dup2(int oldfd, int newfd);
+int rb_cloexec_pipe(int fildes[2]);
+int rb_cloexec_fcntl_dupfd(int fd, int minfd);
+#define RB_RESERVED_FD_P(fd) rb_reserved_fd_p(fd)
+void rb_update_max_fd(int fd);
+void rb_fd_fix_cloexec(int fd);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_IO_H */
diff --git a/include/ruby/internal/intern/load.h b/include/ruby/internal/intern/load.h
new file mode 100644
index 0000000000..2cc5be0ebe
--- /dev/null
+++ b/include/ruby/internal/intern/load.h
@@ -0,0 +1,44 @@
+#ifndef RBIMPL_INTERN_LOAD_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_LOAD_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_f_require().
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* load.c */
+void rb_load(VALUE, int);
+void rb_load_protect(VALUE, int, int*);
+int rb_provided(const char*);
+int rb_feature_provided(const char *, const char **);
+void rb_provide(const char*);
+VALUE rb_f_require(VALUE, VALUE);
+VALUE rb_require_string(VALUE);
+
+// extension configuration
+void rb_ext_ractor_safe(bool flag);
+#define RB_EXT_RACTOR_SAFE(f) rb_ext_ractor_safe(f)
+#define HAVE_RB_EXT_RACTOR_SAFE 1
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_LOAD_H */
diff --git a/include/ruby/internal/intern/marshal.h b/include/ruby/internal/intern/marshal.h
new file mode 100644
index 0000000000..6b0243244e
--- /dev/null
+++ b/include/ruby/internal/intern/marshal.h
@@ -0,0 +1,35 @@
+#ifndef RBIMPL_INTERN_MARSHAL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_MARSHAL_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_mMarshal.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* marshal.c */
+VALUE rb_marshal_dump(VALUE, VALUE);
+VALUE rb_marshal_load(VALUE);
+void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE), VALUE (*loader)(VALUE, VALUE));
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_MARSHAL_H */
diff --git a/include/ruby/internal/intern/numeric.h b/include/ruby/internal/intern/numeric.h
new file mode 100644
index 0000000000..effc583756
--- /dev/null
+++ b/include/ruby/internal/intern/numeric.h
@@ -0,0 +1,42 @@
+#ifndef RBIMPL_INTERN_NUMERIC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_NUMERIC_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_cNumeric.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/backward/2/attributes.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* numeric.c */
+NORETURN(void rb_num_zerodiv(void));
+#define RB_NUM_COERCE_FUNCS_NEED_OPID 1
+VALUE rb_num_coerce_bin(VALUE, VALUE, ID);
+VALUE rb_num_coerce_cmp(VALUE, VALUE, ID);
+VALUE rb_num_coerce_relop(VALUE, VALUE, ID);
+VALUE rb_num_coerce_bit(VALUE, VALUE, ID);
+VALUE rb_num2fix(VALUE);
+VALUE rb_fix2str(VALUE, int);
+CONSTFUNC(VALUE rb_dbl_cmp(double, double));
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_NUMERIC_H */
diff --git a/include/ruby/internal/intern/object.h b/include/ruby/internal/intern/object.h
new file mode 100644
index 0000000000..d55178584b
--- /dev/null
+++ b/include/ruby/internal/intern/object.h
@@ -0,0 +1,90 @@
+#ifndef RBIMPL_INTERN_OBJECT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_OBJECT_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_cObject.
+ */
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+#define RB_OBJ_INIT_COPY(obj, orig) \
+ ((obj) != (orig) && (rb_obj_init_copy((obj), (orig)), 1))
+#define OBJ_INIT_COPY(obj, orig) RB_OBJ_INIT_COPY(obj, orig)
+
+VALUE rb_class_new_instance_pass_kw(int, const VALUE *, VALUE);
+VALUE rb_class_new_instance(int, const VALUE*, VALUE);
+VALUE rb_class_new_instance_kw(int, const VALUE*, VALUE, int);
+
+/* object.c */
+int rb_eql(VALUE, VALUE);
+VALUE rb_any_to_s(VALUE);
+VALUE rb_inspect(VALUE);
+VALUE rb_obj_is_instance_of(VALUE, VALUE);
+VALUE rb_obj_is_kind_of(VALUE, VALUE);
+VALUE rb_obj_alloc(VALUE);
+VALUE rb_obj_clone(VALUE);
+VALUE rb_obj_dup(VALUE);
+VALUE rb_obj_init_copy(VALUE,VALUE);
+VALUE rb_obj_taint(VALUE);
+
+RBIMPL_ATTR_PURE()
+VALUE rb_obj_tainted(VALUE);
+VALUE rb_obj_untaint(VALUE);
+VALUE rb_obj_untrust(VALUE);
+
+RBIMPL_ATTR_PURE()
+VALUE rb_obj_untrusted(VALUE);
+VALUE rb_obj_trust(VALUE);
+VALUE rb_obj_freeze(VALUE);
+
+RBIMPL_ATTR_PURE()
+VALUE rb_obj_frozen_p(VALUE);
+
+VALUE rb_obj_id(VALUE);
+VALUE rb_memory_id(VALUE);
+VALUE rb_obj_class(VALUE);
+
+RBIMPL_ATTR_PURE()
+VALUE rb_class_real(VALUE);
+
+RBIMPL_ATTR_PURE()
+VALUE rb_class_inherited_p(VALUE, VALUE);
+VALUE rb_class_superclass(VALUE);
+VALUE rb_class_get_superclass(VALUE);
+VALUE rb_convert_type(VALUE,int,const char*,const char*);
+VALUE rb_check_convert_type(VALUE,int,const char*,const char*);
+VALUE rb_check_to_integer(VALUE, const char *);
+VALUE rb_check_to_float(VALUE);
+VALUE rb_to_int(VALUE);
+VALUE rb_check_to_int(VALUE);
+VALUE rb_Integer(VALUE);
+VALUE rb_to_float(VALUE);
+VALUE rb_Float(VALUE);
+VALUE rb_String(VALUE);
+VALUE rb_Array(VALUE);
+VALUE rb_Hash(VALUE);
+double rb_cstr_to_dbl(const char*, int);
+double rb_str_to_dbl(VALUE, int);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_OBJECT_H */
diff --git a/include/ruby/internal/intern/parse.h b/include/ruby/internal/intern/parse.h
new file mode 100644
index 0000000000..4a5b8cb147
--- /dev/null
+++ b/include/ruby/internal/intern/parse.h
@@ -0,0 +1,64 @@
+#ifndef RBIMPL_INTERN_PARSE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_PARSE_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_cSymbol.
+ */
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* parse.y */
+ID rb_id_attrset(ID);
+
+RBIMPL_ATTR_CONST()
+int rb_is_const_id(ID);
+
+RBIMPL_ATTR_CONST()
+int rb_is_global_id(ID);
+
+RBIMPL_ATTR_CONST()
+int rb_is_instance_id(ID);
+
+RBIMPL_ATTR_CONST()
+int rb_is_attrset_id(ID);
+
+RBIMPL_ATTR_CONST()
+int rb_is_class_id(ID);
+
+RBIMPL_ATTR_CONST()
+int rb_is_local_id(ID);
+
+RBIMPL_ATTR_CONST()
+int rb_is_junk_id(ID);
+int rb_symname_p(const char*);
+int rb_sym_interned_p(VALUE);
+VALUE rb_backref_get(void);
+void rb_backref_set(VALUE);
+VALUE rb_lastline_get(void);
+void rb_lastline_set(VALUE);
+
+/* symbol.c */
+VALUE rb_sym_all_symbols(void);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_PARSE_H */
diff --git a/include/ruby/internal/intern/proc.h b/include/ruby/internal/intern/proc.h
new file mode 100644
index 0000000000..d6f77cbd4d
--- /dev/null
+++ b/include/ruby/internal/intern/proc.h
@@ -0,0 +1,53 @@
+#ifndef RBIMPL_INTERN_PROC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_PROC_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_cProc.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/iterator.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* proc.c */
+VALUE rb_block_proc(void);
+VALUE rb_block_lambda(void);
+VALUE rb_proc_new(rb_block_call_func_t, VALUE);
+VALUE rb_obj_is_proc(VALUE);
+VALUE rb_proc_call(VALUE, VALUE);
+VALUE rb_proc_call_kw(VALUE, VALUE, int);
+VALUE rb_proc_call_with_block(VALUE, int argc, const VALUE *argv, VALUE);
+VALUE rb_proc_call_with_block_kw(VALUE, int argc, const VALUE *argv, VALUE, int);
+int rb_proc_arity(VALUE);
+VALUE rb_proc_lambda_p(VALUE);
+VALUE rb_binding_new(void);
+VALUE rb_obj_method(VALUE, VALUE);
+VALUE rb_obj_is_method(VALUE);
+VALUE rb_method_call(int, const VALUE*, VALUE);
+VALUE rb_method_call_kw(int, const VALUE*, VALUE, int);
+VALUE rb_method_call_with_block(int, const VALUE *, VALUE, VALUE);
+VALUE rb_method_call_with_block_kw(int, const VALUE *, VALUE, VALUE, int);
+int rb_mod_method_arity(VALUE, ID);
+int rb_obj_method_arity(VALUE, ID);
+VALUE rb_protect(VALUE (*)(VALUE), VALUE, int*);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_PROC_H */
diff --git a/include/ruby/internal/intern/process.h b/include/ruby/internal/intern/process.h
new file mode 100644
index 0000000000..2b1005a205
--- /dev/null
+++ b/include/ruby/internal/intern/process.h
@@ -0,0 +1,46 @@
+#ifndef RBIMPL_INTERN_PROCESS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_PROCESS_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_mProcess.
+ */
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/config.h" /* rb_pid_t is defined here. */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* process.c */
+void rb_last_status_set(int status, rb_pid_t pid);
+VALUE rb_last_status_get(void);
+int rb_proc_exec(const char*);
+
+RBIMPL_ATTR_NORETURN()
+VALUE rb_f_exec(int, const VALUE*);
+rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags);
+void rb_syswait(rb_pid_t pid);
+rb_pid_t rb_spawn(int, const VALUE*);
+rb_pid_t rb_spawn_err(int, const VALUE*, char*, size_t);
+VALUE rb_proc_times(VALUE);
+VALUE rb_detach_process(rb_pid_t pid);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_PROCESS_H */
diff --git a/include/ruby/internal/intern/random.h b/include/ruby/internal/intern/random.h
new file mode 100644
index 0000000000..25c52f4ce4
--- /dev/null
+++ b/include/ruby/internal/intern/random.h
@@ -0,0 +1,45 @@
+#ifndef RBIMPL_INTERN_RANDOM_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_RANDOM_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 MT19937 backended pseudo random number generator.
+ * @see Matsumoto, M., Nishimura, T., "Mersenne Twister: A 623-
+ * dimensionally equidistributed uniform pseudorandom number
+ * generator", ACM Trans. on Modeling and Computer Simulation, 8
+ * (1): pp 3-30, 1998. https://doi.org/10.1145/272991.272995
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* random.c */
+unsigned int rb_genrand_int32(void);
+double rb_genrand_real(void);
+void rb_reset_random_seed(void);
+VALUE rb_random_bytes(VALUE rnd, long n);
+VALUE rb_random_int(VALUE rnd, VALUE max);
+unsigned int rb_random_int32(VALUE rnd);
+double rb_random_real(VALUE rnd);
+unsigned long rb_random_ulong_limited(VALUE rnd, unsigned long limit);
+unsigned long rb_genrand_ulong_limited(unsigned long i);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_RANDOM_H */
diff --git a/include/ruby/internal/intern/range.h b/include/ruby/internal/intern/range.h
new file mode 100644
index 0000000000..7ca47915e2
--- /dev/null
+++ b/include/ruby/internal/intern/range.h
@@ -0,0 +1,35 @@
+#ifndef RBIMPL_INTERN_RANGE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_RANGE_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_cRange.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* range.c */
+VALUE rb_range_new(VALUE, VALUE, int);
+VALUE rb_range_beg_len(VALUE, long*, long*, long, int);
+int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_RANGE_H */
diff --git a/include/ruby/internal/intern/rational.h b/include/ruby/internal/intern/rational.h
new file mode 100644
index 0000000000..30a87ff31f
--- /dev/null
+++ b/include/ruby/internal/intern/rational.h
@@ -0,0 +1,46 @@
+#ifndef RBIMPL_INTERN_RATIONAL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_RATIONAL_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_cRational.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/arithmetic/long.h" /* INT2FIX is here. */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* rational.c */
+VALUE rb_rational_raw(VALUE, VALUE);
+#define rb_rational_raw1(x) rb_rational_raw((x), INT2FIX(1))
+#define rb_rational_raw2(x,y) rb_rational_raw((x), (y))
+VALUE rb_rational_new(VALUE, VALUE);
+#define rb_rational_new1(x) rb_rational_new((x), INT2FIX(1))
+#define rb_rational_new2(x,y) rb_rational_new((x), (y))
+VALUE rb_Rational(VALUE, VALUE);
+#define rb_Rational1(x) rb_Rational((x), INT2FIX(1))
+#define rb_Rational2(x,y) rb_Rational((x), (y))
+VALUE rb_rational_num(VALUE rat);
+VALUE rb_rational_den(VALUE rat);
+VALUE rb_flt_rationalize_with_prec(VALUE, VALUE);
+VALUE rb_flt_rationalize(VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_RATIONAL_H */
diff --git a/include/ruby/internal/intern/re.h b/include/ruby/internal/intern/re.h
new file mode 100644
index 0000000000..dd7baef954
--- /dev/null
+++ b/include/ruby/internal/intern/re.h
@@ -0,0 +1,50 @@
+#ifndef RBIMPL_INTERN_RE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_RE_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_cRegexp.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* re.c */
+#define rb_memcmp memcmp
+int rb_memcicmp(const void*,const void*,long);
+void rb_match_busy(VALUE);
+VALUE rb_reg_nth_defined(int, VALUE);
+VALUE rb_reg_nth_match(int, VALUE);
+int rb_reg_backref_number(VALUE match, VALUE backref);
+VALUE rb_reg_last_match(VALUE);
+VALUE rb_reg_match_pre(VALUE);
+VALUE rb_reg_match_post(VALUE);
+VALUE rb_reg_match_last(VALUE);
+#define HAVE_RB_REG_NEW_STR 1
+VALUE rb_reg_new_str(VALUE, int);
+VALUE rb_reg_new(const char *, long, int);
+VALUE rb_reg_alloc(void);
+VALUE rb_reg_init_str(VALUE re, VALUE s, int options);
+VALUE rb_reg_match(VALUE, VALUE);
+VALUE rb_reg_match2(VALUE);
+int rb_reg_options(VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_RE_H */
diff --git a/include/ruby/internal/intern/ruby.h b/include/ruby/internal/intern/ruby.h
new file mode 100644
index 0000000000..9d9a71cf7a
--- /dev/null
+++ b/include/ruby/internal/intern/ruby.h
@@ -0,0 +1,37 @@
+#ifndef RBIMPL_INTERN_RUBY_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_RUBY_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 Process-global APIs.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* ruby.c */
+#define rb_argv rb_get_argv()
+RUBY_EXTERN VALUE rb_argv0;
+VALUE rb_get_argv(void);
+void *rb_load_file(const char*);
+void *rb_load_file_str(VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_RUBY_H */
diff --git a/include/ruby/internal/intern/select.h b/include/ruby/internal/intern/select.h
new file mode 100644
index 0000000000..43d4cf354c
--- /dev/null
+++ b/include/ruby/internal/intern/select.h
@@ -0,0 +1,52 @@
+#ifndef RBIMPL_INTERN_SELECT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_SELECT_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 to provide ::rb_fd_select().
+ * @note Functions and structs defined in this header file are not
+ * necessarily ruby-specific. They don't need ::VALUE etc.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h> /* for NFDBITS (BSD Net/2) */
+#endif
+
+#include "ruby/internal/dllexport.h"
+
+/* thread.c */
+#if defined(NFDBITS) && defined(HAVE_RB_FD_INIT)
+# include "ruby/internal/intern/select/largesize.h"
+#elif defined(_WIN32)
+# include "ruby/internal/intern/select/win32.h"
+# define rb_fd_resize(n, f) ((void)(f))
+#else
+# include "ruby/internal/intern/select/posix.h"
+# define rb_fd_resize(n, f) ((void)(f))
+#endif
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+struct timeval;
+
+int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_SELECT_H */
diff --git a/include/ruby/internal/intern/select/largesize.h b/include/ruby/internal/intern/select/largesize.h
new file mode 100644
index 0000000000..ba56a159b1
--- /dev/null
+++ b/include/ruby/internal/intern/select/largesize.h
@@ -0,0 +1,103 @@
+#ifndef RBIMPL_INTERN_SELECT_LARGESIZE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_SELECT_LARGESIZE_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 to provide ::rb_fd_select().
+ *
+ * Several Unix platforms support file descriptors bigger than FD_SETSIZE in
+ * `select(2)` system call.
+ *
+ * - Linux 2.2.12 (?)
+ *
+ * - NetBSD 1.2 (src/sys/kern/sys_generic.c:1.25)
+ * `select(2)` documents how to allocate fd_set dynamically.
+ * http://netbsd.gw.com/cgi-bin/man-cgi?select++NetBSD-4.0
+ *
+ * - FreeBSD 2.2 (src/sys/kern/sys_generic.c:1.19)
+ *
+ * - OpenBSD 2.0 (src/sys/kern/sys_generic.c:1.4)
+ * `select(2)` documents how to allocate fd_set dynamically.
+ * http://www.openbsd.org/cgi-bin/man.cgi?query=select&manpath=OpenBSD+4.4
+ *
+ * - HP-UX documents how to allocate fd_set dynamically.
+ * http://docs.hp.com/en/B2355-60105/select.2.html
+ *
+ * - Solaris 8 has `select_large_fdset`
+ *
+ * - Mac OS X 10.7 (Lion)
+ * `select(2)` returns `EINVAL` if `nfds` is greater than `FD_SET_SIZE` and
+ * `_DARWIN_UNLIMITED_SELECT` (or `_DARWIN_C_SOURCE`) isn't defined.
+ * http://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/_index.html
+ *
+ * When `fd_set` is not big enough to hold big file descriptors, it should be
+ * allocated dynamically. Note that this assumes `fd_set` is structured as
+ * bitmap.
+ *
+ * `rb_fd_init` allocates the memory.
+ * `rb_fd_term` frees the memory.
+ * `rb_fd_set` may re-allocate bitmap.
+ *
+ * So `rb_fd_set` doesn't reject file descriptors bigger than `FD_SETSIZE`.
+ */
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/dllexport.h"
+
+/**@cond INTERNAL_MACRO */
+#define rb_fd_ptr rb_fd_ptr
+#define rb_fd_max rb_fd_max
+/** @endcond */
+
+struct timeval;
+
+typedef struct {
+ int maxfd;
+ fd_set *fdset;
+} rb_fdset_t;
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+void rb_fd_init(rb_fdset_t *);
+void rb_fd_term(rb_fdset_t *);
+void rb_fd_zero(rb_fdset_t *);
+void rb_fd_set(int, rb_fdset_t *);
+void rb_fd_clr(int, rb_fdset_t *);
+int rb_fd_isset(int, const rb_fdset_t *);
+void rb_fd_copy(rb_fdset_t *, const fd_set *, int);
+void rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src);
+int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *);
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_PURE()
+/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+static inline fd_set *
+rb_fd_ptr(const rb_fdset_t *f)
+{
+ return f->fdset;
+}
+
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_PURE()
+static inline int
+rb_fd_max(const rb_fdset_t *f)
+{
+ return f->maxfd;
+}
+
+#endif /* RBIMPL_INTERN_SELECT_LARGESIZE_H */
diff --git a/include/ruby/internal/intern/select/posix.h b/include/ruby/internal/intern/select/posix.h
new file mode 100644
index 0000000000..0bf68ae204
--- /dev/null
+++ b/include/ruby/internal/intern/select/posix.h
@@ -0,0 +1,82 @@
+#ifndef RBIMPL_INTERN_SELECT_POSIX_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_SELECT_POSIX_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 to provide ::rb_fd_select().
+ */
+#include "ruby/internal/config.h"
+
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h> /* for select(2) (modern POSIX) */
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h> /* for select(2) (archaic UNIX) */
+#endif
+
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/attr/const.h"
+
+typedef fd_set rb_fdset_t;
+
+#define rb_fd_zero FD_ZERO
+#define rb_fd_set FD_SET
+#define rb_fd_clr FD_CLR
+#define rb_fd_isset FD_ISSET
+#define rb_fd_init FD_ZERO
+#define rb_fd_select select
+/**@cond INTERNAL_MACRO */
+#define rb_fd_copy rb_fd_copy
+#define rb_fd_dup rb_fd_dup
+#define rb_fd_ptr rb_fd_ptr
+#define rb_fd_max rb_fd_max
+/** @endcond */
+
+static inline void
+rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int n)
+{
+ *dst = *src;
+}
+
+static inline void
+rb_fd_dup(rb_fdset_t *dst, const fd_set *src)
+{
+ *dst = *src;
+}
+
+RBIMPL_ATTR_PURE()
+/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+static inline fd_set *
+rb_fd_ptr(rb_fdset_t *f)
+{
+ return f;
+}
+
+RBIMPL_ATTR_CONST()
+static inline int
+rb_fd_max(const rb_fdset_t *f)
+{
+ return FD_SETSIZE;
+}
+
+/* :FIXME: What are these? They don't exist for shibling implementations. */
+#define rb_fd_init_copy(d, s) (*(d) = *(s))
+#define rb_fd_term(f) ((void)(f))
+
+#endif /* RBIMPL_INTERN_SELECT_POSIX_H */
diff --git a/include/ruby/internal/intern/select/win32.h b/include/ruby/internal/intern/select/win32.h
new file mode 100644
index 0000000000..ef75a0f760
--- /dev/null
+++ b/include/ruby/internal/intern/select/win32.h
@@ -0,0 +1,124 @@
+#ifndef RBIMPL_INTERN_SELECT_WIN32_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_SELECT_WIN32_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 to provide ::rb_fd_select().
+ */
+#include "ruby/internal/dosish.h" /* for rb_w32_select */
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/assert.h"
+
+/**@cond INTERNAL_MACRO */
+#define rb_fd_zero rb_fd_zero
+#define rb_fd_clr rb_fd_clr
+#define rb_fd_isset rb_fd_isset
+#define rb_fd_copy rb_fd_copy
+#define rb_fd_dup rb_fd_dup
+#define rb_fd_ptr rb_fd_ptr
+#define rb_fd_max rb_fd_max
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+struct timeval;
+
+typedef struct {
+ int capa;
+ fd_set *fdset;
+} rb_fdset_t;
+
+void rb_fd_init(rb_fdset_t *);
+void rb_fd_term(rb_fdset_t *);
+void rb_fd_set(int, rb_fdset_t *);
+void rb_w32_fd_copy(rb_fdset_t *, const fd_set *, int);
+void rb_w32_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NOALIAS()
+static inline void
+rb_fd_zero(rb_fdset_t *f)
+{
+ f->fdset->fd_count = 0;
+}
+
+RBIMPL_ATTR_NONNULL(())
+static inline void
+rb_fd_clr(int n, rb_fdset_t *f)
+{
+ rb_w32_fdclr(n, f->fdset);
+}
+
+RBIMPL_ATTR_NONNULL(())
+static inline int
+rb_fd_isset(int n, rb_fdset_t *f)
+{
+ return rb_w32_fdisset(n, f->fdset);
+}
+
+RBIMPL_ATTR_NONNULL(())
+static inline void
+rb_fd_copy(rb_fdset_t *dst, const fd_set *src, int n)
+{
+ rb_w32_fd_copy(dst, src, n);
+}
+
+RBIMPL_ATTR_NONNULL(())
+static inline void
+rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src)
+{
+ rb_w32_fd_dup(dst, src);
+}
+
+static inline int
+rb_fd_select(int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
+{
+ return rb_w32_select(
+ n,
+ rfds ? rfds->fdset : NULL,
+ wfds ? wfds->fdset : NULL,
+ efds ? efds->fdset : NULL,
+ timeout);
+}
+
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_PURE()
+/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+static inline fd_set *
+rb_fd_ptr(const rb_fdset_t *f)
+{
+ return f->fdset;
+}
+
+RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_PURE()
+static inline int
+rb_fd_max(const rb_fdset_t *f)
+{
+ const fd_set *p = f->fdset;
+
+ RBIMPL_ASSERT_OR_ASSUME(p);
+ return p->fd_count;
+}
+
+#endif /* RBIMPL_INTERN_SELECT_WIN32_H */
diff --git a/include/ruby/internal/intern/signal.h b/include/ruby/internal/intern/signal.h
new file mode 100644
index 0000000000..8739c51f53
--- /dev/null
+++ b/include/ruby/internal/intern/signal.h
@@ -0,0 +1,39 @@
+#ifndef RBIMPL_INTERN_SIGNAL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_SIGNAL_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 Signal handling APIs.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* signal.c */
+VALUE rb_f_kill(int, const VALUE*);
+#ifdef POSIX_SIGNAL
+#define posix_signal ruby_posix_signal
+void (*posix_signal(int, void (*)(int)))(int);
+#endif
+const char *ruby_signal_name(int);
+void ruby_default_signal(int);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_SIGNAL_H */
diff --git a/include/ruby/internal/intern/sprintf.h b/include/ruby/internal/intern/sprintf.h
new file mode 100644
index 0000000000..2c90548353
--- /dev/null
+++ b/include/ruby/internal/intern/sprintf.h
@@ -0,0 +1,43 @@
+#ifndef RBIMPL_INTERN_SPRINTF_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_SPRINTF_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 Our own private printf(3).
+ */
+#include "ruby/internal/attr/format.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* sprintf.c */
+VALUE rb_f_sprintf(int, const VALUE*);
+
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
+VALUE rb_sprintf(const char*, ...);
+VALUE rb_vsprintf(const char*, va_list);
+
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+VALUE rb_str_catf(VALUE, const char*, ...);
+VALUE rb_str_vcatf(VALUE, const char*, va_list);
+VALUE rb_str_format(int, const VALUE *, VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_SPRINTF_H */
diff --git a/include/ruby/internal/intern/string.h b/include/ruby/internal/intern/string.h
new file mode 100644
index 0000000000..a590b2043e
--- /dev/null
+++ b/include/ruby/internal/intern/string.h
@@ -0,0 +1,298 @@
+#ifndef RBIMPL_INTERN_STRING_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_STRING_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_cString.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/constant_p.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/variable.h" /* rb_gvar_setter_t */
+#include "ruby/st.h" /* st_index_t */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* string.c */
+VALUE rb_str_new(const char*, long);
+VALUE rb_str_new_cstr(const char*);
+VALUE rb_str_new_shared(VALUE);
+VALUE rb_str_new_frozen(VALUE);
+VALUE rb_str_new_with_class(VALUE, const char*, long);
+VALUE rb_tainted_str_new_cstr(const char*);
+VALUE rb_tainted_str_new(const char*, long);
+VALUE rb_external_str_new(const char*, long);
+VALUE rb_external_str_new_cstr(const char*);
+VALUE rb_locale_str_new(const char*, long);
+VALUE rb_locale_str_new_cstr(const char*);
+VALUE rb_filesystem_str_new(const char*, long);
+VALUE rb_filesystem_str_new_cstr(const char*);
+VALUE rb_str_buf_new(long);
+VALUE rb_str_buf_new_cstr(const char*);
+VALUE rb_str_buf_new2(const char*);
+VALUE rb_str_tmp_new(long);
+VALUE rb_usascii_str_new(const char*, long);
+VALUE rb_usascii_str_new_cstr(const char*);
+VALUE rb_utf8_str_new(const char*, long);
+VALUE rb_utf8_str_new_cstr(const char*);
+/**
+ * *_str_new_static functions are intended for C string literals.
+ * They require memory in the range [ptr, ptr+len] to always be readable.
+ * Note that this range covers a total of len + 1 bytes.
+ */
+VALUE rb_str_new_static(const char *ptr, long len);
+VALUE rb_usascii_str_new_static(const char *ptr, long len);
+VALUE rb_utf8_str_new_static(const char *ptr, long len);
+VALUE rb_str_to_interned_str(VALUE);
+VALUE rb_interned_str(const char *, long);
+VALUE rb_interned_str_cstr(const char *);
+void rb_str_free(VALUE);
+void rb_str_shared_replace(VALUE, VALUE);
+VALUE rb_str_buf_append(VALUE, VALUE);
+VALUE rb_str_buf_cat(VALUE, const char*, long);
+VALUE rb_str_buf_cat2(VALUE, const char*);
+VALUE rb_str_buf_cat_ascii(VALUE, const char*);
+VALUE rb_obj_as_string(VALUE);
+VALUE rb_check_string_type(VALUE);
+void rb_must_asciicompat(VALUE);
+VALUE rb_str_dup(VALUE);
+VALUE rb_str_resurrect(VALUE str);
+VALUE rb_str_locktmp(VALUE);
+VALUE rb_str_unlocktmp(VALUE);
+VALUE rb_str_dup_frozen(VALUE);
+#define rb_str_dup_frozen rb_str_new_frozen
+VALUE rb_str_plus(VALUE, VALUE);
+VALUE rb_str_times(VALUE, VALUE);
+long rb_str_sublen(VALUE, long);
+VALUE rb_str_substr(VALUE, long, long);
+VALUE rb_str_subseq(VALUE, long, long);
+char *rb_str_subpos(VALUE, long, long*);
+void rb_str_modify(VALUE);
+void rb_str_modify_expand(VALUE, long);
+VALUE rb_str_freeze(VALUE);
+void rb_str_set_len(VALUE, long);
+VALUE rb_str_resize(VALUE, long);
+VALUE rb_str_cat(VALUE, const char*, long);
+VALUE rb_str_cat_cstr(VALUE, const char*);
+VALUE rb_str_cat2(VALUE, const char*);
+VALUE rb_str_append(VALUE, VALUE);
+VALUE rb_str_concat(VALUE, VALUE);
+st_index_t rb_memhash(const void *ptr, long len);
+st_index_t rb_hash_start(st_index_t);
+st_index_t rb_hash_uint32(st_index_t, uint32_t);
+st_index_t rb_hash_uint(st_index_t, st_index_t);
+st_index_t rb_hash_end(st_index_t);
+#define rb_hash_uint32(h, i) st_hash_uint32((h), (i))
+#define rb_hash_uint(h, i) st_hash_uint((h), (i))
+#define rb_hash_end(h) st_hash_end(h)
+st_index_t rb_str_hash(VALUE);
+int rb_str_hash_cmp(VALUE,VALUE);
+int rb_str_comparable(VALUE, VALUE);
+int rb_str_cmp(VALUE, VALUE);
+VALUE rb_str_equal(VALUE str1, VALUE str2);
+VALUE rb_str_drop_bytes(VALUE, long);
+void rb_str_update(VALUE, long, long, VALUE);
+VALUE rb_str_replace(VALUE, VALUE);
+VALUE rb_str_inspect(VALUE);
+VALUE rb_str_dump(VALUE);
+VALUE rb_str_split(VALUE, const char*);
+rb_gvar_setter_t rb_str_setter;
+VALUE rb_str_intern(VALUE);
+VALUE rb_sym_to_s(VALUE);
+long rb_str_strlen(VALUE);
+VALUE rb_str_length(VALUE);
+long rb_str_offset(VALUE, long);
+RBIMPL_ATTR_PURE()
+size_t rb_str_capacity(VALUE);
+VALUE rb_str_ellipsize(VALUE, long);
+VALUE rb_str_scrub(VALUE, VALUE);
+VALUE rb_str_succ(VALUE);
+
+RBIMPL_ATTR_NONNULL(())
+static inline long
+rbimpl_strlen(const char *str)
+{
+ return RBIMPL_CAST((long)strlen(str));
+}
+
+static inline VALUE
+rbimpl_str_new_cstr(const char *str)
+{
+ long len = rbimpl_strlen(str);
+ return rb_str_new_static(str, len);
+}
+
+static inline VALUE
+rbimpl_tainted_str_new_cstr(const char *str)
+{
+ long len = rbimpl_strlen(str);
+ return rb_tainted_str_new(str, len);
+}
+
+static inline VALUE
+rbimpl_usascii_str_new_cstr(const char *str)
+{
+ long len = rbimpl_strlen(str);
+ return rb_usascii_str_new_static(str, len);
+}
+
+static inline VALUE
+rbimpl_utf8_str_new_cstr(const char *str)
+{
+ long len = rbimpl_strlen(str);
+ return rb_utf8_str_new_static(str, len);
+}
+
+static inline VALUE
+rbimpl_external_str_new_cstr(const char *str)
+{
+ long len = rbimpl_strlen(str);
+ return rb_external_str_new(str, len);
+}
+
+static inline VALUE
+rbimpl_locale_str_new_cstr(const char *str)
+{
+ long len = rbimpl_strlen(str);
+ return rb_locale_str_new(str, len);
+}
+
+static inline VALUE
+rbimpl_str_buf_new_cstr(const char *str)
+{
+ long len = rbimpl_strlen(str);
+ VALUE buf = rb_str_buf_new(len);
+ return rb_str_buf_cat(buf, str, len);
+}
+
+static inline VALUE
+rbimpl_str_cat_cstr(VALUE buf, const char *str)
+{
+ long len = rbimpl_strlen(str);
+ return rb_str_cat(buf, str, len);
+}
+
+static inline VALUE
+rbimpl_exc_new_cstr(VALUE exc, const char *str)
+{
+ long len = rbimpl_strlen(str);
+ return rb_exc_new(exc, str, len);
+}
+
+#define rb_str_new(str, len) \
+ ((RBIMPL_CONSTANT_P(str) && \
+ RBIMPL_CONSTANT_P(len) ? \
+ rb_str_new_static : \
+ rb_str_new) ((str), (len)))
+
+#define rb_str_new_cstr(str) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_str_new_cstr : \
+ rb_str_new_cstr) (str))
+
+#define rb_usascii_str_new(str, len) \
+ ((RBIMPL_CONSTANT_P(str) && \
+ RBIMPL_CONSTANT_P(len) ? \
+ rb_usascii_str_new_static : \
+ rb_usascii_str_new) ((str), (len)))
+
+#define rb_utf8_str_new(str, len) \
+ ((RBIMPL_CONSTANT_P(str) && \
+ RBIMPL_CONSTANT_P(len) ? \
+ rb_utf8_str_new_static : \
+ rb_utf8_str_new) ((str), (len)))
+
+#define rb_tainted_str_new_cstr(str) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_tainted_str_new_cstr : \
+ rb_tainted_str_new_cstr) (str))
+
+#define rb_usascii_str_new_cstr(str) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_usascii_str_new_cstr : \
+ rb_usascii_str_new_cstr) (str))
+
+#define rb_utf8_str_new_cstr(str) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_utf8_str_new_cstr : \
+ rb_utf8_str_new_cstr) (str))
+
+#define rb_external_str_new_cstr(str) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_external_str_new_cstr : \
+ rb_external_str_new_cstr) (str))
+
+#define rb_locale_str_new_cstr(str) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_locale_str_new_cstr : \
+ rb_locale_str_new_cstr) (str))
+
+#define rb_str_buf_new_cstr(str) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_str_buf_new_cstr : \
+ rb_str_buf_new_cstr) (str))
+
+#define rb_str_cat_cstr(buf, str) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_str_cat_cstr : \
+ rb_str_cat_cstr) ((buf), (str)))
+
+#define rb_exc_new_cstr(exc, str) \
+ ((RBIMPL_CONSTANT_P(str) ? \
+ rbimpl_exc_new_cstr : \
+ rb_exc_new_cstr) ((exc), (str)))
+
+#define rb_str_new2 rb_str_new_cstr
+#define rb_str_new3 rb_str_new_shared
+#define rb_str_new4 rb_str_new_frozen
+#define rb_str_new5 rb_str_new_with_class
+#define rb_tainted_str_new2 rb_tainted_str_new_cstr
+#define rb_str_buf_new2 rb_str_buf_new_cstr
+#define rb_usascii_str_new2 rb_usascii_str_new_cstr
+#define rb_str_buf_cat rb_str_cat
+#define rb_str_buf_cat2 rb_str_cat_cstr
+#define rb_str_cat2 rb_str_cat_cstr
+#define rb_strlen_lit(str) (sizeof(str "") - 1)
+#define rb_str_new_lit(str) rb_str_new_static((str), rb_strlen_lit(str))
+#define rb_usascii_str_new_lit(str) rb_usascii_str_new_static((str), rb_strlen_lit(str))
+#define rb_utf8_str_new_lit(str) rb_utf8_str_new_static((str), rb_strlen_lit(str))
+#define rb_enc_str_new_lit(str, enc) rb_enc_str_new_static((str), rb_strlen_lit(str), (enc))
+#define rb_str_new_literal(str) rb_str_new_lit(str)
+#define rb_usascii_str_new_literal(str) rb_usascii_str_new_lit(str)
+#define rb_utf8_str_new_literal(str) rb_utf8_str_new_lit(str)
+#define rb_enc_str_new_literal(str, enc) rb_enc_str_new_lit(str, enc)
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_STRING_H */
diff --git a/include/ruby/internal/intern/struct.h b/include/ruby/internal/intern/struct.h
new file mode 100644
index 0000000000..8818da96c7
--- /dev/null
+++ b/include/ruby/internal/intern/struct.h
@@ -0,0 +1,47 @@
+#ifndef RBIMPL_INTERN_STRUCT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_STRUCT_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_cStruct.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/intern/vm.h" /* rb_alloc_func_t */
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* struct.c */
+VALUE rb_struct_new(VALUE, ...);
+VALUE rb_struct_define(const char*, ...);
+VALUE rb_struct_define_under(VALUE, const char*, ...);
+VALUE rb_struct_alloc(VALUE, VALUE);
+VALUE rb_struct_initialize(VALUE, VALUE);
+VALUE rb_struct_aref(VALUE, VALUE);
+VALUE rb_struct_aset(VALUE, VALUE, VALUE);
+VALUE rb_struct_getmember(VALUE, ID);
+VALUE rb_struct_s_members(VALUE);
+VALUE rb_struct_members(VALUE);
+VALUE rb_struct_size(VALUE s);
+VALUE rb_struct_alloc_noinit(VALUE);
+VALUE rb_struct_define_without_accessor(const char *, VALUE, rb_alloc_func_t, ...);
+VALUE rb_struct_define_without_accessor_under(VALUE outer, const char *class_name, VALUE super, rb_alloc_func_t alloc, ...);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_STRUCT_H */
diff --git a/include/ruby/internal/intern/thread.h b/include/ruby/internal/intern/thread.h
new file mode 100644
index 0000000000..a12a371058
--- /dev/null
+++ b/include/ruby/internal/intern/thread.h
@@ -0,0 +1,76 @@
+#ifndef RBIMPL_INTERN_THREAD_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_THREAD_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_cThread.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+struct timeval;
+
+/* thread.c */
+void rb_thread_schedule(void);
+void rb_thread_wait_fd(int);
+int rb_thread_fd_writable(int);
+void rb_thread_fd_close(int);
+int rb_thread_alone(void);
+void rb_thread_sleep(int);
+void rb_thread_sleep_forever(void);
+void rb_thread_sleep_deadly(void);
+VALUE rb_thread_stop(void);
+VALUE rb_thread_wakeup(VALUE);
+VALUE rb_thread_wakeup_alive(VALUE);
+VALUE rb_thread_run(VALUE);
+VALUE rb_thread_kill(VALUE);
+VALUE rb_thread_create(VALUE (*)(void *), void*);
+void rb_thread_wait_for(struct timeval);
+VALUE rb_thread_current(void);
+VALUE rb_thread_main(void);
+VALUE rb_thread_local_aref(VALUE, ID);
+VALUE rb_thread_local_aset(VALUE, ID, VALUE);
+void rb_thread_atfork(void);
+void rb_thread_atfork_before_exec(void);
+VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE);
+VALUE rb_exec_recursive_paired(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE);
+VALUE rb_exec_recursive_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE);
+VALUE rb_exec_recursive_paired_outer(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE,VALUE);
+
+typedef void rb_unblock_function_t(void *);
+typedef VALUE rb_blocking_function_t(void *);
+void rb_thread_check_ints(void);
+int rb_thread_interrupted(VALUE thval);
+
+#define RUBY_UBF_IO RBIMPL_CAST((rb_unblock_function_t *)-1)
+#define RUBY_UBF_PROCESS RBIMPL_CAST((rb_unblock_function_t *)-1)
+VALUE rb_mutex_new(void);
+VALUE rb_mutex_locked_p(VALUE mutex);
+VALUE rb_mutex_trylock(VALUE mutex);
+VALUE rb_mutex_lock(VALUE mutex);
+VALUE rb_mutex_unlock(VALUE mutex);
+VALUE rb_mutex_sleep(VALUE self, VALUE timeout);
+VALUE rb_mutex_synchronize(VALUE mutex, VALUE (*func)(VALUE arg), VALUE arg);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_THREAD_H */
diff --git a/include/ruby/internal/intern/time.h b/include/ruby/internal/intern/time.h
new file mode 100644
index 0000000000..c7ae6ec2f5
--- /dev/null
+++ b/include/ruby/internal/intern/time.h
@@ -0,0 +1,51 @@
+#ifndef RBIMPL_INTERN_TIME_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_TIME_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_cTime.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef HAVE_TIME_H
+# include <time.h> /* for time_t */
+#endif
+
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+struct timespec;
+struct timeval;
+
+/* time.c */
+void rb_timespec_now(struct timespec *);
+VALUE rb_time_new(time_t, long);
+VALUE rb_time_nano_new(time_t, long);
+VALUE rb_time_timespec_new(const struct timespec *, int);
+VALUE rb_time_num_new(VALUE, VALUE);
+struct timeval rb_time_interval(VALUE num);
+struct timeval rb_time_timeval(VALUE time);
+struct timespec rb_time_timespec(VALUE time);
+struct timespec rb_time_timespec_interval(VALUE num);
+VALUE rb_time_utc_offset(VALUE time);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_TIME_H */
diff --git a/include/ruby/internal/intern/variable.h b/include/ruby/internal/intern/variable.h
new file mode 100644
index 0000000000..8210662fa0
--- /dev/null
+++ b/include/ruby/internal/intern/variable.h
@@ -0,0 +1,83 @@
+#ifndef RBIMPL_INTERN_VARIABLE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_VARIABLE_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 names inside of a Ruby program.
+ */
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/st.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* variable.c */
+VALUE rb_mod_name(VALUE);
+VALUE rb_class_path(VALUE);
+VALUE rb_class_path_cached(VALUE);
+void rb_set_class_path(VALUE, VALUE, const char*);
+void rb_set_class_path_string(VALUE, VALUE, VALUE);
+VALUE rb_path_to_class(VALUE);
+VALUE rb_path2class(const char*);
+VALUE rb_class_name(VALUE);
+VALUE rb_autoload_load(VALUE, ID);
+VALUE rb_autoload_p(VALUE, ID);
+VALUE rb_f_trace_var(int, const VALUE*);
+VALUE rb_f_untrace_var(int, const VALUE*);
+VALUE rb_f_global_variables(void);
+void rb_alias_variable(ID, ID);
+void rb_copy_generic_ivar(VALUE,VALUE);
+void rb_free_generic_ivar(VALUE);
+VALUE rb_ivar_get(VALUE, ID);
+VALUE rb_ivar_set(VALUE, ID, VALUE);
+VALUE rb_ivar_defined(VALUE, ID);
+void rb_ivar_foreach(VALUE, int (*)(ID, VALUE, st_data_t), st_data_t);
+st_index_t rb_ivar_count(VALUE);
+VALUE rb_attr_get(VALUE, ID);
+VALUE rb_obj_instance_variables(VALUE);
+VALUE rb_obj_remove_instance_variable(VALUE, VALUE);
+void *rb_mod_const_at(VALUE, void*);
+void *rb_mod_const_of(VALUE, void*);
+VALUE rb_const_list(void*);
+VALUE rb_mod_constants(int, const VALUE *, VALUE);
+VALUE rb_mod_remove_const(VALUE, VALUE);
+int rb_const_defined(VALUE, ID);
+int rb_const_defined_at(VALUE, ID);
+int rb_const_defined_from(VALUE, ID);
+VALUE rb_const_get(VALUE, ID);
+VALUE rb_const_get_at(VALUE, ID);
+VALUE rb_const_get_from(VALUE, ID);
+void rb_const_set(VALUE, ID, VALUE);
+VALUE rb_const_remove(VALUE, ID);
+#if 0 /* EXPERIMENTAL: remove if no problem */
+RBIMPL_ATTR_NORETURN()
+VALUE rb_mod_const_missing(VALUE,VALUE);
+#endif
+VALUE rb_cvar_defined(VALUE, ID);
+void rb_cvar_set(VALUE, ID, VALUE);
+VALUE rb_cvar_get(VALUE, ID);
+void rb_cv_set(VALUE, const char*, VALUE);
+VALUE rb_cv_get(VALUE, const char*);
+void rb_define_class_variable(VALUE, const char*, VALUE);
+VALUE rb_mod_class_variables(int, const VALUE*, VALUE);
+VALUE rb_mod_remove_cvar(VALUE, VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_VARIABLE_H */
diff --git a/include/ruby/internal/intern/vm.h b/include/ruby/internal/intern/vm.h
new file mode 100644
index 0000000000..706f160ad8
--- /dev/null
+++ b/include/ruby/internal/intern/vm.h
@@ -0,0 +1,77 @@
+#ifndef RBIMPL_INTERN_VM_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_VM_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_cRubyVM.
+ */
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* vm.c */
+int rb_sourceline(void);
+const char *rb_sourcefile(void);
+int rb_frame_method_id_and_class(ID *idp, VALUE *klassp);
+
+/* vm_eval.c */
+VALUE rb_check_funcall(VALUE, ID, int, const VALUE*);
+VALUE rb_check_funcall_kw(VALUE, ID, int, const VALUE*, int);
+void rb_remove_method(VALUE, const char*);
+void rb_remove_method_id(VALUE, ID);
+
+VALUE rb_eval_cmd_kw(VALUE, VALUE, int);
+VALUE rb_apply(VALUE, ID, VALUE);
+
+VALUE rb_obj_instance_eval(int, const VALUE*, VALUE);
+VALUE rb_obj_instance_exec(int, const VALUE*, VALUE);
+VALUE rb_mod_module_eval(int, const VALUE*, VALUE);
+VALUE rb_mod_module_exec(int, const VALUE*, VALUE);
+
+/* vm_method.c */
+#define HAVE_RB_DEFINE_ALLOC_FUNC 1
+typedef VALUE (*rb_alloc_func_t)(VALUE);
+void rb_define_alloc_func(VALUE, rb_alloc_func_t);
+void rb_undef_alloc_func(VALUE);
+rb_alloc_func_t rb_get_alloc_func(VALUE);
+void rb_clear_constant_cache(void);
+void rb_clear_method_cache_by_class(VALUE);
+void rb_alias(VALUE, ID, ID);
+void rb_attr(VALUE,ID,int,int,int);
+int rb_method_boundp(VALUE, ID, int);
+int rb_method_basic_definition_p(VALUE, ID);
+
+int rb_obj_respond_to(VALUE, ID, int);
+int rb_respond_to(VALUE, ID);
+
+RBIMPL_ATTR_NORETURN()
+VALUE rb_f_notimplement(int argc, const VALUE *argv, VALUE obj, VALUE marker);
+#if !defined(RUBY_EXPORT) && defined(_WIN32)
+RUBY_EXTERN VALUE (*const rb_f_notimplement_)(int, const VALUE *, VALUE, VALUE marker);
+#define rb_f_notimplement (*rb_f_notimplement_)
+#endif
+
+/* vm_backtrace.c */
+void rb_backtrace(void);
+VALUE rb_make_backtrace(void);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_VM_H */
diff --git a/include/ruby/internal/interpreter.h b/include/ruby/internal/interpreter.h
new file mode 100644
index 0000000000..29dee60aab
--- /dev/null
+++ b/include/ruby/internal/interpreter.h
@@ -0,0 +1,93 @@
+#ifndef RBIMPL_INTERPRETER_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERPRETER_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 Interpreter embedding APIs.
+ */
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/**
+ * @defgroup embed CRuby Embedding APIs
+ * CRuby interpreter APIs. These are APIs to embed MRI interpreter into your
+ * program.
+ * These functions are not a part of Ruby extension library API.
+ * Extension libraries of Ruby should not depend on these functions.
+ * @{
+ */
+
+/** @defgroup ruby1 ruby(1) implementation
+ * A part of the implementation of ruby(1) command.
+ * Other programs that embed Ruby interpreter do not always need to use these
+ * functions.
+ * @{
+ */
+
+void ruby_sysinit(int *argc, char ***argv);
+void ruby_init(void);
+void* ruby_options(int argc, char** argv);
+int ruby_executable_node(void *n, int *status);
+int ruby_run_node(void *n);
+
+/* version.c */
+void ruby_show_version(void);
+#ifndef ruby_show_copyright
+void ruby_show_copyright(void);
+#endif
+
+/*! A convenience macro to call ruby_init_stack(). Must be placed just after
+ * variable declarations */
+#define RUBY_INIT_STACK \
+ VALUE variable_in_this_stack_frame; \
+ ruby_init_stack(&variable_in_this_stack_frame);
+/*! @} */
+
+void ruby_init_stack(volatile VALUE*);
+
+int ruby_setup(void);
+int ruby_cleanup(volatile int);
+
+void ruby_finalize(void);
+
+RBIMPL_ATTR_NORETURN()
+void ruby_stop(int);
+
+int ruby_stack_check(void);
+size_t ruby_stack_length(VALUE**);
+
+int ruby_exec_node(void *n);
+
+void ruby_script(const char* name);
+void ruby_set_script_name(VALUE name);
+
+void ruby_prog_init(void);
+void ruby_set_argv(int, char**);
+void *ruby_process_options(int, char**);
+void ruby_init_loadpath(void);
+void ruby_incpush(const char*);
+void ruby_sig_finalize(void);
+
+/*! @} */
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERPRETER_H */
diff --git a/include/ruby/internal/iterator.h b/include/ruby/internal/iterator.h
new file mode 100644
index 0000000000..99c0831b13
--- /dev/null
+++ b/include/ruby/internal/iterator.h
@@ -0,0 +1,65 @@
+#ifndef RBIMPL_ITERATOR_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ITERATOR_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 Block related APIs.
+ */
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+#define RB_BLOCK_CALL_FUNC_STRICT 1
+#define RUBY_BLOCK_CALL_FUNC_TAKES_BLOCKARG 1
+#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \
+ VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg
+typedef VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg));
+typedef rb_block_call_func *rb_block_call_func_t;
+
+VALUE rb_each(VALUE);
+VALUE rb_yield(VALUE);
+VALUE rb_yield_values(int n, ...);
+VALUE rb_yield_values2(int n, const VALUE *argv);
+VALUE rb_yield_values_kw(int n, const VALUE *argv, int kw_splat);
+VALUE rb_yield_splat(VALUE);
+VALUE rb_yield_splat_kw(VALUE, int);
+VALUE rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); /* rb_block_call_func */
+int rb_keyword_given_p(void);
+int rb_block_given_p(void);
+void rb_need_block(void);
+VALUE rb_iterate(VALUE(*)(VALUE),VALUE,rb_block_call_func_t,VALUE);
+VALUE rb_block_call(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE);
+VALUE rb_block_call_kw(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE,int);
+VALUE rb_rescue(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE);
+VALUE rb_rescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,...);
+VALUE rb_vrescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,va_list);
+VALUE rb_ensure(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE),VALUE);
+VALUE rb_catch(const char*,rb_block_call_func_t,VALUE);
+VALUE rb_catch_obj(VALUE,rb_block_call_func_t,VALUE);
+
+RBIMPL_ATTR_NORETURN()
+void rb_throw(const char*,VALUE);
+
+RBIMPL_ATTR_NORETURN()
+void rb_throw_obj(VALUE,VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_ITERATOR_H */
diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h
new file mode 100644
index 0000000000..46dfcadd10
--- /dev/null
+++ b/include/ruby/internal/memory.h
@@ -0,0 +1,281 @@
+#ifndef RBIMPL_MEMORY_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_MEMORY_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 Memory management stuff.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+#ifdef HAVE_ALLOCA_H
+# include <alloca.h>
+#endif
+
+#if defined(_MSC_VER) && defined(_WIN64)
+# include <intrin.h>
+# pragma intrinsic(_umul128)
+#endif
+
+#include "ruby/internal/attr/alloc_size.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/attr/restrict.h"
+#include "ruby/internal/attr/returns_nonnull.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/has/builtin.h"
+#include "ruby/internal/stdalign.h"
+#include "ruby/internal/stdbool.h"
+#include "ruby/internal/xmalloc.h"
+#include "ruby/backward/2/limits.h"
+#include "ruby/backward/2/long_long.h"
+#include "ruby/backward/2/assume.h"
+#include "ruby/defines.h"
+
+/* Make alloca work the best possible way. */
+#if defined(alloca)
+# /* Take that. */
+#elif RBIMPL_HAS_BUILTIN(__builtin_alloca)
+# define alloca __builtin_alloca
+#elif defined(_AIX)
+# pragma alloca
+#elif defined(__cplusplus)
+extern "C" void *alloca(size_t);
+#else
+extern void *alloca();
+#endif
+
+#if defined(HAVE_INT128_T) && SIZEOF_SIZE_T <= 8
+# define DSIZE_T uint128_t
+#elif SIZEOF_SIZE_T * 2 <= SIZEOF_LONG_LONG
+# define DSIZE_T unsigned LONG_LONG
+#endif
+
+#ifdef C_ALLOCA
+# define RUBY_ALLOCV_LIMIT 0
+#else
+# define RUBY_ALLOCV_LIMIT 1024
+#endif
+
+#ifdef __GNUC__
+#define RB_GC_GUARD(v) \
+ (*__extension__ ({ \
+ volatile VALUE *rb_gc_guarded_ptr = &(v); \
+ __asm__("" : : "m"(rb_gc_guarded_ptr)); \
+ rb_gc_guarded_ptr; \
+ }))
+#elif defined _MSC_VER
+#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr(&(v)))
+#else
+#define HAVE_RB_GC_GUARDED_PTR_VAL 1
+#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr_val(&(v),(v)))
+#endif
+
+/* Casts needed because void* is NOT compaible with others in C++. */
+#define RB_ALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xmalloc2((n), sizeof(type)))
+#define RB_ALLOC(type) RBIMPL_CAST((type *)ruby_xmalloc(sizeof(type)))
+#define RB_ZALLOC_N(type,n) RBIMPL_CAST((type *)ruby_xcalloc((n), sizeof(type)))
+#define RB_ZALLOC(type) (RB_ZALLOC_N(type, 1))
+#define RB_REALLOC_N(var,type,n) \
+ ((var) = RBIMPL_CAST((type *)ruby_xrealloc2((void *)(var), (n), sizeof(type))))
+
+#define ALLOCA_N(type,n) \
+ RBIMPL_CAST((type *)(!(n) ? NULL : alloca(rbimpl_size_mul_or_raise(sizeof(type), (n)))))
+
+/* allocates _n_ bytes temporary buffer and stores VALUE including it
+ * in _v_. _n_ may be evaluated twice. */
+#define RB_ALLOCV(v, n) \
+ ((n) < RUBY_ALLOCV_LIMIT ? \
+ ((v) = 0, !(n) ? NULL : alloca(n)) : \
+ rb_alloc_tmp_buffer(&(v), (n)))
+#define RB_ALLOCV_N(type, v, n) \
+ RBIMPL_CAST((type *) \
+ (((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \
+ ((v) = 0, !(n) ? NULL : alloca((n) * sizeof(type))) : \
+ rb_alloc_tmp_buffer2(&(v), (n), sizeof(type))))
+#define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v))
+
+#define MEMZERO(p,type,n) memset((p), 0, rbimpl_size_mul_or_raise(sizeof(type), (n)))
+#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
+#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
+#define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), rbimpl_size_mul_or_raise(sizeof(type), (n)))
+
+#define ALLOC_N RB_ALLOC_N
+#define ALLOC RB_ALLOC
+#define ZALLOC_N RB_ZALLOC_N
+#define ZALLOC RB_ZALLOC
+#define REALLOC_N RB_REALLOC_N
+#define ALLOCV RB_ALLOCV
+#define ALLOCV_N RB_ALLOCV_N
+#define ALLOCV_END RB_ALLOCV_END
+
+/* Expecting this struct to be eliminated by function inlinings */
+struct rbimpl_size_mul_overflow_tag {
+ bool left;
+ size_t right;
+};
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+RBIMPL_ATTR_RESTRICT()
+RBIMPL_ATTR_RETURNS_NONNULL()
+RBIMPL_ATTR_ALLOC_SIZE((2))
+void *rb_alloc_tmp_buffer(volatile VALUE *store, long len);
+
+RBIMPL_ATTR_RESTRICT()
+RBIMPL_ATTR_RETURNS_NONNULL()
+RBIMPL_ATTR_ALLOC_SIZE((2,3))
+void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t len,size_t count);
+
+void rb_free_tmp_buffer(volatile VALUE *store);
+
+RBIMPL_ATTR_NORETURN()
+void ruby_malloc_size_overflow(size_t, size_t);
+
+#ifdef HAVE_RB_GC_GUARDED_PTR_VAL
+volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val);
+#endif
+RBIMPL_SYMBOL_EXPORT_END()
+
+#ifdef _MSC_VER
+# pragma optimize("", off)
+
+static inline volatile VALUE *
+rb_gc_guarded_ptr(volatile VALUE *ptr)
+{
+ return ptr;
+}
+
+# pragma optimize("", on)
+#endif
+
+/* Does anyone use it? Just here for backwards compatibility. */
+static inline int
+rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c)
+{
+#ifdef DSIZE_T
+ RB_GNUC_EXTENSION DSIZE_T da, db, c2;
+ da = a;
+ db = b;
+ c2 = da * db;
+ if (c2 > max) return 1;
+ *c = RBIMPL_CAST((size_t)c2);
+#else
+ if (b != 0 && a > max / b) return 1;
+ *c = a * b;
+#endif
+ return 0;
+}
+
+#if 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()
+static inline struct rbimpl_size_mul_overflow_tag
+rbimpl_size_mul_overflow(size_t x, size_t y)
+{
+ struct rbimpl_size_mul_overflow_tag ret = { false, 0, };
+
+#if RBIMPL_HAS_BUILTIN(__builtin_mul_overflow)
+ ret.left = __builtin_mul_overflow(x, y, &ret.right);
+
+#elif defined(DSIZE_T)
+ RB_GNUC_EXTENSION DSIZE_T dx = x;
+ RB_GNUC_EXTENSION DSIZE_T dy = y;
+ RB_GNUC_EXTENSION DSIZE_T dz = dx * dy;
+ ret.left = dz > SIZE_MAX;
+ ret.right = RBIMPL_CAST((size_t)dz);
+
+#elif defined(_MSC_VER) && defined(_WIN64)
+ unsigned __int64 dp = 0;
+ unsigned __int64 dz = _umul128(x, y, &dp);
+ ret.left = RBIMPL_CAST((bool)dp);
+ ret.right = RBIMPL_CAST((size_t)dz);
+
+#else
+ /* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap */
+ ret.left = (y != 0) && (x > SIZE_MAX / y);
+ ret.right = x * y;
+#endif
+
+ return ret;
+}
+
+static inline size_t
+rbimpl_size_mul_or_raise(size_t x, size_t y)
+{
+ struct rbimpl_size_mul_overflow_tag size =
+ rbimpl_size_mul_overflow(x, y);
+
+ if (RB_LIKELY(! size.left)) {
+ return size.right;
+ }
+ else {
+ ruby_malloc_size_overflow(x, y);
+ RBIMPL_UNREACHABLE_RETURN(0);
+ }
+}
+
+static inline void *
+rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize)
+{
+ const size_t total_size = rbimpl_size_mul_or_raise(count, elsize);
+ const size_t cnt = (total_size + sizeof(VALUE) - 1) / sizeof(VALUE);
+ return rb_alloc_tmp_buffer_with_count(store, total_size, cnt);
+}
+
+#ifndef __MINGW32__
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+RBIMPL_ATTR_RETURNS_NONNULL()
+/* At least since 2004, glibc's <string.h> annotates memcpy to be
+ * __attribute__((__nonnull__(1, 2))). However it is safe to pass NULL to the
+ * source pointer, if n is 0. Let's wrap memcpy. */
+static inline void *
+ruby_nonempty_memcpy(void *dest, const void *src, size_t n)
+{
+ if (n) {
+ return memcpy(dest, src, n);
+ }
+ else {
+ return dest;
+ }
+}
+RBIMPL_SYMBOL_EXPORT_END()
+#undef memcpy
+#define memcpy ruby_nonempty_memcpy
+#endif
+
+#endif /* RBIMPL_MEMORY_H */
diff --git a/include/ruby/internal/method.h b/include/ruby/internal/method.h
new file mode 100644
index 0000000000..67600e8732
--- /dev/null
+++ b/include/ruby/internal/method.h
@@ -0,0 +1,39 @@
+#ifndef RBIMPL_METHOD_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_METHOD_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 Creation and modification of Ruby methods.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/backward/2/stdarg.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+void rb_define_method(VALUE,const char*,VALUE(*)(ANYARGS),int);
+void rb_define_module_function(VALUE,const char*,VALUE(*)(ANYARGS),int);
+void rb_define_global_function(const char*,VALUE(*)(ANYARGS),int);
+
+void rb_undef_method(VALUE,const char*);
+void rb_define_alias(VALUE,const char*,const char*);
+void rb_define_attr(VALUE,const char*,int,int);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_METHOD_H */
diff --git a/include/ruby/internal/module.h b/include/ruby/internal/module.h
new file mode 100644
index 0000000000..0f2dfdb1be
--- /dev/null
+++ b/include/ruby/internal/module.h
@@ -0,0 +1,39 @@
+#ifndef RBIMPL_MODULE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_MODULE_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 Creation and modification of Ruby modules.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+VALUE rb_define_class(const char*,VALUE);
+VALUE rb_define_module(const char*);
+VALUE rb_define_class_under(VALUE, const char*, VALUE);
+VALUE rb_define_module_under(VALUE, const char*);
+
+void rb_include_module(VALUE,VALUE);
+void rb_extend_object(VALUE,VALUE);
+void rb_prepend_module(VALUE,VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_MODULE_H */
diff --git a/include/ruby/internal/newobj.h b/include/ruby/internal/newobj.h
new file mode 100644
index 0000000000..684226e54b
--- /dev/null
+++ b/include/ruby/internal/newobj.h
@@ -0,0 +1,73 @@
+#ifndef RBIMPL_NEWOBJ_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_NEWOBJ_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 #NEWOBJ.
+ */
+#include "ruby/internal/cast.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/special_consts.h"
+#include "ruby/internal/value.h"
+#include "ruby/assert.h"
+
+#define RB_NEWOBJ(obj,type) type *(obj) = RBIMPL_CAST((type *)rb_newobj())
+#define RB_NEWOBJ_OF(obj,type,klass,flags) type *(obj) = RBIMPL_CAST((type *)rb_newobj_of(klass, flags))
+
+#define NEWOBJ RB_NEWOBJ
+#define NEWOBJ_OF RB_NEWOBJ_OF /* core has special NEWOBJ_OF() in internal.h */
+#define OBJSETUP rb_obj_setup /* use NEWOBJ_OF instead of NEWOBJ()+OBJSETUP() */
+#define CLONESETUP rb_clone_setup
+#define DUPSETUP rb_dup_setup
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+VALUE rb_newobj(void);
+VALUE rb_newobj_of(VALUE, VALUE);
+VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type);
+VALUE rb_obj_class(VALUE);
+VALUE rb_singleton_class_clone(VALUE);
+void rb_singleton_class_attached(VALUE,VALUE);
+void rb_copy_generic_ivar(VALUE,VALUE);
+RBIMPL_SYMBOL_EXPORT_END()
+
+static inline void
+rb_clone_setup(VALUE clone, VALUE obj)
+{
+ RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj));
+ RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(clone));
+
+ const VALUE flags = RUBY_FL_PROMOTED0 | RUBY_FL_PROMOTED1 | RUBY_FL_FINALIZE;
+ rb_obj_setup(clone, rb_singleton_class_clone(obj),
+ RB_FL_TEST_RAW(obj, ~flags));
+ rb_singleton_class_attached(RBASIC_CLASS(clone), clone);
+ if (RB_FL_TEST(obj, RUBY_FL_EXIVAR)) rb_copy_generic_ivar(clone, obj);
+}
+
+static inline void
+rb_dup_setup(VALUE dup, VALUE obj)
+{
+ RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj));
+ RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(dup));
+
+ rb_obj_setup(dup, rb_obj_class(obj), RB_FL_TEST_RAW(obj, RUBY_FL_DUPPED));
+ if (RB_FL_TEST(obj, RUBY_FL_EXIVAR)) rb_copy_generic_ivar(dup, obj);
+}
+
+#endif /* RBIMPL_NEWOBJ_H */
diff --git a/include/ruby/internal/rgengc.h b/include/ruby/internal/rgengc.h
new file mode 100644
index 0000000000..2681d41844
--- /dev/null
+++ b/include/ruby/internal/rgengc.h
@@ -0,0 +1,199 @@
+#ifndef RBIMPL_RGENGC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_RGENGC_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 RGENGC write-barrier APIs.
+ * @see Sasada, K., "Gradual write-barrier insertion into a Ruby
+ * interpreter", in proceedings of the 2019 ACM SIGPLAN
+ * International Symposium on Memory Management (ISMM 2019), pp
+ * 115-121, 2019. https://doi.org/10.1145/3315573.3329986
+ */
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/special_consts.h"
+#include "ruby/internal/stdbool.h"
+#include "ruby/internal/value.h"
+#include "ruby/assert.h"
+#include "ruby/backward/2/attributes.h"
+
+#undef USE_RGENGC
+#define USE_RGENGC 1
+
+#ifndef USE_RINCGC
+# define USE_RINCGC 1
+#endif
+
+#ifndef USE_RGENGC_LOGGING_WB_UNPROTECT
+# define USE_RGENGC_LOGGING_WB_UNPROTECT 0
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_ARRAY
+# define RGENGC_WB_PROTECTED_ARRAY 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_HASH
+# define RGENGC_WB_PROTECTED_HASH 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_STRUCT
+# define RGENGC_WB_PROTECTED_STRUCT 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_STRING
+# define RGENGC_WB_PROTECTED_STRING 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_OBJECT
+# define RGENGC_WB_PROTECTED_OBJECT 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_REGEXP
+# define RGENGC_WB_PROTECTED_REGEXP 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_CLASS
+# define RGENGC_WB_PROTECTED_CLASS 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_FLOAT
+# define RGENGC_WB_PROTECTED_FLOAT 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_COMPLEX
+# define RGENGC_WB_PROTECTED_COMPLEX 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_RATIONAL
+# define RGENGC_WB_PROTECTED_RATIONAL 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_BIGNUM
+# define RGENGC_WB_PROTECTED_BIGNUM 1
+#endif
+
+#ifndef RGENGC_WB_PROTECTED_NODE_CREF
+# define RGENGC_WB_PROTECTED_NODE_CREF 1
+#endif
+
+/**
+ * @name Write barrier (WB) interfaces:
+ * @{
+ *
+ * @note The following core interfaces can be changed in the future. Please
+ * catch up if you want to insert WB into C-extensions correctly.
+ */
+
+/**
+ * WB for new reference from `a' to `b'. Write `b' into `*slot'. `slot' is a
+ * pointer in `a'.
+ */
+#define RB_OBJ_WRITE(a, slot, b) \
+ RBIMPL_CAST(rb_obj_write((VALUE)(a), (VALUE *)(slot), (VALUE)(b), __FILE__, __LINE__))
+/**
+ * WB for new reference from `a' to `b'. This doesn't write any values, but
+ * only a WB declaration. `oldv' is replaced value with `b' (not used in
+ * current Ruby).
+ */
+#define RB_OBJ_WRITTEN(a, oldv, b) \
+ RBIMPL_CAST(rb_obj_written((VALUE)(a), (VALUE)(oldv), (VALUE)(b), __FILE__, __LINE__))
+/** @} */
+
+#define OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW
+#define OBJ_PROMOTED RB_OBJ_PROMOTED
+#define OBJ_WB_UNPROTECT RB_OBJ_WB_UNPROTECT
+
+#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__)
+#define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \
+ (RGENGC_WB_PROTECTED_##type ? OBJ_WB_UNPROTECT(obj) : obj)
+#define RGENGC_LOGGING_WB_UNPROTECT rb_gc_unprotect_logging
+
+/** @cond INTERNAL_MACRO */
+#define RB_OBJ_PROMOTED_RAW RB_OBJ_PROMOTED_RAW
+#define RB_OBJ_PROMOTED RB_OBJ_PROMOTED
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+void rb_gc_writebarrier(VALUE a, VALUE b);
+void rb_gc_writebarrier_unprotect(VALUE obj);
+#if USE_RGENGC_LOGGING_WB_UNPROTECT
+void rb_gc_unprotect_logging(void *objptr, const char *filename, int line);
+#endif
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_OBJ_PROMOTED_RAW(VALUE obj)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RB_FL_ABLE(obj));
+ return RB_FL_ANY_RAW(obj, RUBY_FL_PROMOTED);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_OBJ_PROMOTED(VALUE obj)
+{
+ if (! RB_FL_ABLE(obj)) {
+ return false;
+ }
+ else {
+ return RB_OBJ_PROMOTED_RAW(obj);
+ }
+}
+
+static inline VALUE
+rb_obj_wb_unprotect(VALUE x, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line))
+{
+#if USE_RGENGC_LOGGING_WB_UNPROTECT
+ RGENGC_LOGGING_WB_UNPROTECT(RBIMPL_CAST((void *)x), filename, line);
+#endif
+ rb_gc_writebarrier_unprotect(x);
+ return x;
+}
+
+static inline VALUE
+rb_obj_written(VALUE a, RB_UNUSED_VAR(VALUE oldv), VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line))
+{
+#if USE_RGENGC_LOGGING_WB_UNPROTECT
+ RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line);
+#endif
+
+ if (!RB_SPECIAL_CONST_P(b)) {
+ rb_gc_writebarrier(a, b);
+ }
+
+ return a;
+}
+
+static inline VALUE
+rb_obj_write(VALUE a, VALUE *slot, VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line))
+{
+#ifdef RGENGC_LOGGING_WRITE
+ RGENGC_LOGGING_WRITE(a, slot, b, filename, line);
+#endif
+
+ *slot = b;
+
+ rb_obj_written(a, RUBY_Qundef /* ignore `oldv' now */, b, filename, line);
+ return a;
+}
+
+#endif /* RBIMPL_RGENGC_H */
diff --git a/include/ruby/internal/scan_args.h b/include/ruby/internal/scan_args.h
new file mode 100644
index 0000000000..d9329e7e98
--- /dev/null
+++ b/include/ruby/internal/scan_args.h
@@ -0,0 +1,401 @@
+#ifndef RBIMPL_SCAN_ARGS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_SCAN_ARGS_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 Compile-time static implementation of ::rb_scan_args().
+ *
+ * This is a beast. It statically analyses the argument spec string, and
+ * expands the assignment of variables into dedicated codes.
+ */
+#include "ruby/internal/attr/diagnose_if.h"
+#include "ruby/internal/attr/error.h"
+#include "ruby/internal/attr/forceinline.h"
+#include "ruby/internal/attr/noreturn.h"
+#include "ruby/internal/config.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/intern/array.h" /* rb_ary_new_from_values */
+#include "ruby/internal/intern/error.h" /* rb_error_arity */
+#include "ruby/internal/intern/hash.h" /* rb_hash_dup */
+#include "ruby/internal/intern/proc.h" /* rb_block_proc */
+#include "ruby/internal/iterator.h" /* rb_block_given_p / rb_keyword_given_p */
+#include "ruby/internal/static_assert.h"
+#include "ruby/internal/stdbool.h"
+#include "ruby/internal/value.h"
+#include "ruby/assert.h"
+
+#define RB_SCAN_ARGS_PASS_CALLED_KEYWORDS 0
+#define RB_SCAN_ARGS_KEYWORDS 1
+#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS 3
+#define RB_NO_KEYWORDS 0
+#define RB_PASS_KEYWORDS 1
+#define RB_PASS_CALLED_KEYWORDS rb_keyword_given_p()
+/* rb_scan_args() format allows ':' for optional hash */
+#define HAVE_RB_SCAN_ARGS_OPTIONAL_HASH 1
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+int rb_scan_args(int, const VALUE*, const char*, ...);
+int rb_scan_args_kw(int, int, const VALUE*, const char*, ...);
+
+RBIMPL_ATTR_ERROR(("bad scan arg format"))
+void rb_scan_args_bad_format(const char*);
+
+RBIMPL_ATTR_ERROR(("variable argument length doesn't match"))
+void rb_scan_args_length_mismatch(const char*,int);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+/* If we could use constexpr the following macros could be inline functions
+ * ... but sadly we cannot. */
+
+#define rb_scan_args_isdigit(c) (RBIMPL_CAST((unsigned char)((c)-'0'))<10)
+
+#define rb_scan_args_count_end(fmt, ofs, vari) \
+ ((fmt)[ofs] ? -1 : (vari))
+
+#define rb_scan_args_count_block(fmt, ofs, vari) \
+ ((fmt)[ofs]!='&' ? \
+ rb_scan_args_count_end(fmt, ofs, vari) : \
+ rb_scan_args_count_end(fmt, (ofs)+1, (vari)+1))
+
+#define rb_scan_args_count_hash(fmt, ofs, vari) \
+ ((fmt)[ofs]!=':' ? \
+ rb_scan_args_count_block(fmt, ofs, vari) : \
+ rb_scan_args_count_block(fmt, (ofs)+1, (vari)+1))
+
+#define rb_scan_args_count_trail(fmt, ofs, vari) \
+ (!rb_scan_args_isdigit((fmt)[ofs]) ? \
+ rb_scan_args_count_hash(fmt, ofs, vari) : \
+ rb_scan_args_count_hash(fmt, (ofs)+1, (vari)+((fmt)[ofs]-'0')))
+
+#define rb_scan_args_count_var(fmt, ofs, vari) \
+ ((fmt)[ofs]!='*' ? \
+ rb_scan_args_count_trail(fmt, ofs, vari) : \
+ rb_scan_args_count_trail(fmt, (ofs)+1, (vari)+1))
+
+#define rb_scan_args_count_opt(fmt, ofs, vari) \
+ (!rb_scan_args_isdigit((fmt)[ofs]) ? \
+ rb_scan_args_count_var(fmt, ofs, vari) : \
+ rb_scan_args_count_var(fmt, (ofs)+1, (vari)+(fmt)[ofs]-'0'))
+
+#define rb_scan_args_count_lead(fmt, ofs, vari) \
+ (!rb_scan_args_isdigit((fmt)[ofs]) ? \
+ rb_scan_args_count_var(fmt, ofs, vari) : \
+ rb_scan_args_count_opt(fmt, (ofs)+1, (vari)+(fmt)[ofs]-'0'))
+
+#define rb_scan_args_count(fmt) rb_scan_args_count_lead(fmt, 0, 0)
+
+#if RBIMPL_HAS_ATTRIBUTE(diagnose_if)
+# /* Assertions done in the attribute. */
+# define rb_scan_args_verify(fmt, varc) RBIMPL_ASSERT_NOTHING
+#else
+# /* At one sight it _seems_ the expressions below could be written using
+# * static assrtions. The reality is no, they don't. Because fmt is a string
+# * literal, any operations against fmt cannot produce the "integer constant
+# * expression"s, as defined in ISO/IEC 9899:2018 section 6.6 paragraph #6.
+# * Static assertions need such integer constant expressions as defined in
+# * ISO/IEC 9899:2018 section 6.7.10 paragraph #3.
+# *
+# * GCC nonetheless constant-folds this into no-op, though. */
+# define rb_scan_args_verify(fmt, varc) \
+ (sizeof(char[1-2*(rb_scan_args_count(fmt)<0)])!=1 ? \
+ rb_scan_args_bad_format(fmt) : \
+ sizeof(char[1-2*(rb_scan_args_count(fmt)!=(varc))])!=1 ? \
+ rb_scan_args_length_mismatch(fmt, varc) : \
+ RBIMPL_ASSERT_NOTHING)
+#endif
+
+static inline bool
+rb_scan_args_keyword_p(int kw_flag, VALUE last)
+{
+ switch (kw_flag) {
+ case RB_SCAN_ARGS_PASS_CALLED_KEYWORDS:
+ return !! rb_keyword_given_p();
+ case RB_SCAN_ARGS_KEYWORDS:
+ return true;
+ case RB_SCAN_ARGS_LAST_HASH_KEYWORDS:
+ return RB_TYPE_P(last, T_HASH);
+ default:
+ return false;
+ }
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static bool
+rb_scan_args_lead_p(const char *fmt)
+{
+ return rb_scan_args_isdigit(fmt[0]);
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static int
+rb_scan_args_n_lead(const char *fmt)
+{
+ return (rb_scan_args_lead_p(fmt) ? fmt[0]-'0' : 0);
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static bool
+rb_scan_args_opt_p(const char *fmt)
+{
+ return (rb_scan_args_lead_p(fmt) && rb_scan_args_isdigit(fmt[1]));
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static int
+rb_scan_args_n_opt(const char *fmt)
+{
+ return (rb_scan_args_opt_p(fmt) ? fmt[1]-'0' : 0);
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static int
+rb_scan_args_var_idx(const char *fmt)
+{
+ return (!rb_scan_args_lead_p(fmt) ? 0 : !rb_scan_args_isdigit(fmt[1]) ? 1 : 2);
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static bool
+rb_scan_args_f_var(const char *fmt)
+{
+ return (fmt[rb_scan_args_var_idx(fmt)]=='*');
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static int
+rb_scan_args_trail_idx(const char *fmt)
+{
+ const int idx = rb_scan_args_var_idx(fmt);
+ return idx+(fmt[idx]=='*');
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static int
+rb_scan_args_n_trail(const char *fmt)
+{
+ const int idx = rb_scan_args_trail_idx(fmt);
+ return (rb_scan_args_isdigit(fmt[idx]) ? fmt[idx]-'0' : 0);
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static int
+rb_scan_args_hash_idx(const char *fmt)
+{
+ const int idx = rb_scan_args_trail_idx(fmt);
+ return idx+rb_scan_args_isdigit(fmt[idx]);
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static bool
+rb_scan_args_f_hash(const char *fmt)
+{
+ return (fmt[rb_scan_args_hash_idx(fmt)]==':');
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static int
+rb_scan_args_block_idx(const char *fmt)
+{
+ const int idx = rb_scan_args_hash_idx(fmt);
+ return idx+(fmt[idx]==':');
+}
+
+RBIMPL_ATTR_FORCEINLINE()
+static bool
+rb_scan_args_f_block(const char *fmt)
+{
+ return (fmt[rb_scan_args_block_idx(fmt)]=='&');
+}
+
+# if 0
+RBIMPL_ATTR_FORCEINLINE()
+static int
+rb_scan_args_end_idx(const char *fmt)
+{
+ const int idx = rb_scan_args_block_idx(fmt);
+ return idx+(fmt[idx]=='&');
+}
+# endif
+
+/* NOTE: Use `char *fmt` instead of `const char *fmt` because of clang's bug*/
+/* https://bugs.llvm.org/show_bug.cgi?id=38095 */
+# define rb_scan_args0(argc, argv, fmt, varc, vars) \
+ rb_scan_args_set(RB_SCAN_ARGS_PASS_CALLED_KEYWORDS, argc, argv, \
+ rb_scan_args_n_lead(fmt), \
+ rb_scan_args_n_opt(fmt), \
+ rb_scan_args_n_trail(fmt), \
+ rb_scan_args_f_var(fmt), \
+ rb_scan_args_f_hash(fmt), \
+ rb_scan_args_f_block(fmt), \
+ (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc)
+# define rb_scan_args_kw0(kw_flag, argc, argv, fmt, varc, vars) \
+ rb_scan_args_set(kw_flag, argc, argv, \
+ rb_scan_args_n_lead(fmt), \
+ rb_scan_args_n_opt(fmt), \
+ rb_scan_args_n_trail(fmt), \
+ rb_scan_args_f_var(fmt), \
+ rb_scan_args_f_hash(fmt), \
+ rb_scan_args_f_block(fmt), \
+ (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc)
+
+RBIMPL_ATTR_FORCEINLINE()
+static int
+rb_scan_args_set(int kw_flag, int argc, const VALUE *argv,
+ int n_lead, int n_opt, int n_trail,
+ bool f_var, bool f_hash, bool f_block,
+ VALUE *vars[], RB_UNUSED_VAR(const char *fmt), RB_UNUSED_VAR(int varc))
+ RBIMPL_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) < 0, "bad scan arg format", "error")
+ RBIMPL_ATTR_DIAGNOSE_IF(rb_scan_args_count(fmt) != varc, "variable argument length doesn't match", "error")
+{
+ int i, argi = 0, vari = 0;
+ VALUE *var, hash = Qnil;
+#define rb_scan_args_next_param() vars[vari++]
+ const int n_mand = n_lead + n_trail;
+
+ /* capture an option hash - phase 1: pop from the argv */
+ if (f_hash && argc > 0) {
+ VALUE last = argv[argc - 1];
+ if (rb_scan_args_keyword_p(kw_flag, last)) {
+ hash = rb_hash_dup(last);
+ argc--;
+ }
+ }
+
+ if (argc < n_mand) {
+ goto argc_error;
+ }
+
+ /* capture leading mandatory arguments */
+ for (i = 0; i < n_lead; i++) {
+ var = rb_scan_args_next_param();
+ if (var) *var = argv[argi];
+ argi++;
+ }
+
+ /* capture optional arguments */
+ for (i = 0; i < n_opt; i++) {
+ var = rb_scan_args_next_param();
+ if (argi < argc - n_trail) {
+ if (var) *var = argv[argi];
+ argi++;
+ }
+ else {
+ if (var) *var = Qnil;
+ }
+ }
+
+ /* capture variable length arguments */
+ if (f_var) {
+ int n_var = argc - argi - n_trail;
+
+ var = rb_scan_args_next_param();
+ if (0 < n_var) {
+ if (var) *var = rb_ary_new_from_values(n_var, &argv[argi]);
+ argi += n_var;
+ }
+ else {
+ if (var) *var = rb_ary_new();
+ }
+ }
+
+ /* capture trailing mandatory arguments */
+ for (i = 0; i < n_trail; i++) {
+ var = rb_scan_args_next_param();
+ if (var) *var = argv[argi];
+ argi++;
+ }
+
+ /* capture an option hash - phase 2: assignment */
+ if (f_hash) {
+ var = rb_scan_args_next_param();
+ if (var) *var = hash;
+ }
+
+ /* capture iterator block */
+ if (f_block) {
+ var = rb_scan_args_next_param();
+ if (rb_block_given_p()) {
+ *var = rb_block_proc();
+ }
+ else {
+ *var = Qnil;
+ }
+ }
+
+ if (argi == argc) {
+ return argc;
+ }
+
+ argc_error:
+ rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
+ UNREACHABLE_RETURN(-1);
+#undef rb_scan_args_next_param
+}
+
+#if ! defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
+# /* skip */
+
+#elif ! defined(HAVE_VA_ARGS_MACRO)
+# /* skip */
+
+#elif ! defined(__OPTIMIZE__)
+# /* skip */
+
+#elif defined(HAVE___VA_OPT__)
+# define rb_scan_args(argc, argvp, fmt, ...) \
+ __builtin_choose_expr( \
+ __builtin_constant_p(fmt), \
+ rb_scan_args0( \
+ argc, argvp, fmt, \
+ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \
+ ((VALUE*[]){__VA_ARGS__})), \
+ (rb_scan_args)(argc, argvp, fmt __VA_OPT__(, __VA_ARGS__)))
+# define rb_scan_args_kw(kw_flag, argc, argvp, fmt, ...) \
+ __builtin_choose_expr( \
+ __builtin_constant_p(fmt), \
+ rb_scan_args_kw0( \
+ kw_flag, argc, argvp, fmt, \
+ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \
+ ((VALUE*[]){__VA_ARGS__})), \
+ (rb_scan_args_kw)(kw_flag, argc, argvp, fmt __VA_OPT__(, __VA_ARGS__)))
+
+#elif defined(__STRICT_ANSI__)
+# /* skip */
+
+#elif defined(__GNUC__)
+# define rb_scan_args(argc, argvp, fmt, ...) \
+ __builtin_choose_expr( \
+ __builtin_constant_p(fmt), \
+ rb_scan_args0( \
+ argc, argvp, fmt, \
+ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \
+ ((VALUE*[]){__VA_ARGS__})), \
+ (rb_scan_args)(argc, argvp, fmt, __VA_ARGS__))
+# define rb_scan_args_kw(kw_flag, argc, argvp, fmt, ...) \
+ __builtin_choose_expr( \
+ __builtin_constant_p(fmt), \
+ rb_scan_args_kw0( \
+ kw_flag, argc, argvp, fmt, \
+ (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \
+ ((VALUE*[]){__VA_ARGS__})), \
+ (rb_scan_args_kw)(kw_flag, argc, argvp, fmt, __VA_ARGS__ /**/))
+#endif
+
+#endif /* RBIMPL_SCAN_ARGS_H */
diff --git a/include/ruby/internal/special_consts.h b/include/ruby/internal/special_consts.h
new file mode 100644
index 0000000000..f36a230af2
--- /dev/null
+++ b/include/ruby/internal/special_consts.h
@@ -0,0 +1,204 @@
+#ifndef RBIMPL_SPECIAL_CONSTS_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_SPECIAL_CONSTS_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 enum ::ruby_special_consts.
+ * @see Sasada, K., "A Lighweight Representation of Floting-Point
+ * Numbers on Ruby Interpreter", in proceedings of 10th JSSST
+ * SIGPPL Workshop on Programming and Programming Languages
+ * (PPL2008), pp. 9-16, 2008.
+ */
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/const.h"
+#include "ruby/internal/attr/constexpr.h"
+#include "ruby/internal/attr/enum_extensibility.h"
+#include "ruby/internal/stdbool.h"
+#include "ruby/internal/value.h"
+
+#if defined(USE_FLONUM)
+# /* Take that. */
+#elif SIZEOF_VALUE >= SIZEOF_DOUBLE
+# define USE_FLONUM 1
+#else
+# define USE_FLONUM 0
+#endif
+
+#define RTEST RB_TEST
+
+#define FIXNUM_P RB_FIXNUM_P
+#define IMMEDIATE_P RB_IMMEDIATE_P
+#define NIL_P RB_NIL_P
+#define SPECIAL_CONST_P RB_SPECIAL_CONST_P
+#define STATIC_SYM_P RB_STATIC_SYM_P
+
+#define Qfalse RUBY_Qfalse
+#define Qnil RUBY_Qnil
+#define Qtrue RUBY_Qtrue
+#define Qundef RUBY_Qundef
+
+/** @cond INTERNAL_MACRO */
+#define FIXNUM_FLAG RUBY_FIXNUM_FLAG
+#define FLONUM_FLAG RUBY_FLONUM_FLAG
+#define FLONUM_MASK RUBY_FLONUM_MASK
+#define FLONUM_P RB_FLONUM_P
+#define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK
+#define SYMBOL_FLAG RUBY_SYMBOL_FLAG
+
+#define RB_FIXNUM_P RB_FIXNUM_P
+#define RB_FLONUM_P RB_FLONUM_P
+#define RB_IMMEDIATE_P RB_IMMEDIATE_P
+#define RB_NIL_P RB_NIL_P
+#define RB_SPECIAL_CONST_P RB_SPECIAL_CONST_P
+#define RB_STATIC_SYM_P RB_STATIC_SYM_P
+#define RB_TEST RB_TEST
+/** @endcond */
+
+/** special constants - i.e. non-zero and non-fixnum constants */
+enum
+RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed)
+ruby_special_consts {
+#if USE_FLONUM
+ RUBY_Qfalse = 0x00, /* ...0000 0000 */
+ RUBY_Qtrue = 0x14, /* ...0001 0100 */
+ RUBY_Qnil = 0x08, /* ...0000 1000 */
+ RUBY_Qundef = 0x34, /* ...0011 0100 */
+ RUBY_IMMEDIATE_MASK = 0x07, /* ...0000 0111 */
+ RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */
+ RUBY_FLONUM_MASK = 0x03, /* ...0000 0011 */
+ RUBY_FLONUM_FLAG = 0x02, /* ...xxxx xx10 */
+ RUBY_SYMBOL_FLAG = 0x0c, /* ...xxxx 1100 */
+#else
+ RUBY_Qfalse = 0x00, /* ...0000 0000 */
+ RUBY_Qtrue = 0x02, /* ...0000 0010 */
+ RUBY_Qnil = 0x04, /* ...0000 0100 */
+ RUBY_Qundef = 0x06, /* ...0000 0110 */
+ RUBY_IMMEDIATE_MASK = 0x03, /* ...0000 0011 */
+ RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */
+ RUBY_FLONUM_MASK = 0x00, /* any values ANDed with FLONUM_MASK cannot be FLONUM_FLAG */
+ RUBY_FLONUM_FLAG = 0x02, /* ...0000 0010 */
+ RUBY_SYMBOL_FLAG = 0x0e, /* ...0000 1110 */
+#endif
+
+ RUBY_SPECIAL_SHIFT = 8 /** Least significant 8 bits are reserved. */
+};
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+/*
+ * :NOTE: rbimpl_test HAS to be `__attribute__((const))` in order for clang to
+ * properly deduce `__builtin_assume()`.
+ */
+static inline bool
+RB_TEST(VALUE obj)
+{
+ /*
+ * Qfalse: ....0000 0000
+ * Qnil: ....0000 1000
+ * ~Qnil: ....1111 0111
+ * v ....xxxx xxxx
+ * ----------------------------
+ * RTEST(v) ....xxxx 0xxx
+ *
+ * RTEST(v) can be 0 if and only if (v == Qfalse || v == Qnil).
+ */
+ return obj & ~RUBY_Qnil;
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_NIL_P(VALUE obj)
+{
+ return obj == RUBY_Qnil;
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_FIXNUM_P(VALUE obj)
+{
+ return obj & RUBY_FIXNUM_FLAG;
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX14)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_STATIC_SYM_P(VALUE obj)
+{
+ RBIMPL_ATTR_CONSTEXPR(CXX14)
+ const VALUE mask = ~(RBIMPL_VALUE_FULL << RUBY_SPECIAL_SHIFT);
+ return (obj & mask) == RUBY_SYMBOL_FLAG;
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_FLONUM_P(VALUE obj)
+{
+#if USE_FLONUM
+ return (obj & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG;
+#else
+ return false;
+#endif
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_IMMEDIATE_P(VALUE obj)
+{
+ return obj & RUBY_IMMEDIATE_MASK;
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_SPECIAL_CONST_P(VALUE obj)
+{
+ return RB_IMMEDIATE_P(obj) || ! RB_TEST(obj);
+}
+
+RBIMPL_ATTR_CONST()
+RBIMPL_ATTR_CONSTEXPR(CXX11)
+/* This function is to mimic old rb_special_const_p macro but have anyone
+ * actually used its return value? Wasn't it just something no one needed? */
+static inline VALUE
+rb_special_const_p(VALUE obj)
+{
+ return RB_SPECIAL_CONST_P(obj) * RUBY_Qtrue;
+}
+
+/**
+ * @cond INTERNAL_MACRO
+ * See [ruby-dev:27513] for the following macros.
+ */
+#define RUBY_Qfalse RBIMPL_CAST((VALUE)RUBY_Qfalse)
+#define RUBY_Qtrue RBIMPL_CAST((VALUE)RUBY_Qtrue)
+#define RUBY_Qnil RBIMPL_CAST((VALUE)RUBY_Qnil)
+#define RUBY_Qundef RBIMPL_CAST((VALUE)RUBY_Qundef)
+/** @endcond */
+
+#endif /* RBIMPL_SPECIAL_CONSTS_H */
diff --git a/include/ruby/internal/static_assert.h b/include/ruby/internal/static_assert.h
new file mode 100644
index 0000000000..d4bdadf196
--- /dev/null
+++ b/include/ruby/internal/static_assert.h
@@ -0,0 +1,77 @@
+#ifndef RBIMPL_STATIC_ASSERT_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_STATIC_ASSERT_H
+/**
+ * @file
+ * @author Ruby developers <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_STATIC_ASSERT.
+ */
+#include <assert.h>
+#include "ruby/internal/has/extension.h"
+#include "ruby/internal/compiler_since.h"
+
+/** @cond INTERNAL_MACRO */
+#if defined(__cplusplus) && defined(__cpp_static_assert)
+# /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */
+# define RBIMPL_STATIC_ASSERT0 static_assert
+
+#elif defined(__cplusplus) && RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0)
+# define RBIMPL_STATIC_ASSERT0 static_assert
+
+#elif defined(__INTEL_CXX11_MODE__)
+# define RBIMPL_STATIC_ASSERT0 static_assert
+
+#elif defined(__cplusplus) && __cplusplus >= 201103L
+# define RBIMPL_STATIC_ASSERT0 static_assert
+
+#elif defined(__cplusplus) && RBIMPL_HAS_EXTENSION(cxx_static_assert)
+# define RBIMPL_STATIC_ASSERT0 __extension__ static_assert
+
+#elif defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__
+# define RBIMPL_STATIC_ASSERT0 __extension__ static_assert
+
+#elif defined(__STDC_VERSION__) && RBIMPL_HAS_EXTENSION(c_static_assert)
+# define RBIMPL_STATIC_ASSERT0 __extension__ _Static_assert
+
+#elif defined(__STDC_VERSION__) && RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0)
+# define RBIMPL_STATIC_ASSERT0 __extension__ _Static_assert
+
+#elif defined(static_assert)
+# /* Take <assert.h> definition */
+# define RBIMPL_STATIC_ASSERT0 static_assert
+#endif
+/** @endcond */
+
+/**
+ * @brief Wraps (or simulates) `static_assert`
+ * @param name Valid C/C++ identifier, describing the assertion.
+ * @param expr Expression to assert.
+ * @note `name` shall not be a string literal.
+ */
+#if defined(__DOXYGEN__)
+# define RBIMPL_STATIC_ASSERT static_assert
+
+#elif defined(RBIMPL_STATIC_ASSERT0)
+# define RBIMPL_STATIC_ASSERT(name, expr) \
+ RBIMPL_STATIC_ASSERT0(expr, # name ": " # expr)
+
+#else
+# define RBIMPL_STATIC_ASSERT(name, expr) \
+ typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)]
+#endif
+
+#endif /* RBIMPL_STATIC_ASSERT_H */
diff --git a/include/ruby/internal/stdalign.h b/include/ruby/internal/stdalign.h
new file mode 100644
index 0000000000..02eb7ab959
--- /dev/null
+++ b/include/ruby/internal/stdalign.h
@@ -0,0 +1,133 @@
+#ifndef RBIMPL_STDALIGN_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_STDALIGN_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_ALIGNAS / #RBIMPL_ALIGNOF
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
+
+#include "ruby/internal/compiler_is.h"
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/has/declspec_attribute.h"
+#include "ruby/internal/has/feature.h"
+
+/**
+ * Wraps (or simulates) `alignas`. This is C++11's `alignas` and is _different_
+ * from C11 `_Alignas`. For instance,
+ *
+ * ```CXX
+ * typedef struct alignas(128) foo { int foo } foo;
+ * ```
+ *
+ * is a valid C++ while
+ *
+ * ```C
+ * typedef struct _Alignas(128) foo { int foo } foo;
+ * ```
+ *
+ * is an invalid C because:
+ *
+ * - You cannot `struct _Alignas`.
+ * - A `typedef` cannot have alignments.
+ */
+#if defined(__cplusplus) && RBIMPL_HAS_FEATURE(cxx_alignas)
+# define RBIMPL_ALIGNAS alignas
+
+#elif defined(__cplusplus) && (__cplusplus >= 201103L)
+# define RBIMPL_ALIGNAS alignas
+
+#elif defined(__INTEL_CXX11_MODE__)
+# define RBIMPL_ALIGNAS alignas
+
+#elif defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define RBIMPL_ALIGNAS alignas
+
+#elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(align)
+# define RBIMPL_ALIGNAS(_) __declspec(align(_))
+
+#elif RBIMPL_HAS_ATTRIBUTE(aligned)
+# define RBIMPL_ALIGNAS(_) __attribute__((__aligned__(_)))
+
+#else
+# define RBIMPL_ALIGNAS(_) /* void */
+#endif
+
+/**
+ * Wraps (or simulates) `alignof`.
+ *
+ * We want C11's `_Alignof`. However in spite of its clear language, compilers
+ * (including GCC and clang) tend to have buggy implementations. We have to
+ * avoid such things to resort to our own version.
+ *
+ * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023
+ * @see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560
+ * @see https://bugs.llvm.org/show_bug.cgi?id=26547
+ */
+#if defined(__cplusplus)
+# /* C++11 `alignof()` can be buggy. */
+# /* see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69560 */
+# /* But don't worry, we can use templates. */
+# define RBIMPL_ALIGNOF(T) (static_cast<size_t>(ruby::rbimpl_alignof<T>::value))
+
+namespace ruby {
+template<typename T>
+struct rbimpl_alignof {
+ typedef struct {
+ char _;
+ T t;
+ } type;
+
+ enum {
+ value = offsetof(type, t)
+ };
+};
+}
+
+#elif RBIMPL_COMPILER_IS(MSVC)
+# /* Windows have no alignment glitch.*/
+# define RBIMPL_ALIGNOF __alignof
+
+#elif defined(HAVE__ALIGNOF)
+# /* Autoconf detected availability of a sane `_Alignof()`. */
+# define RBIMPL_ALIGNOF(T) RB_GNUC_EXTENSION(_Alignof(T))
+
+#else
+# /* :BEWARE: This is the last resort. If your compiler somehow supports
+# * querying the alignment of a type, you definitely should use that instead.
+# * There are 2 known pitfalls for this fallback implementation:
+# *
+# * First, it is either an undefined behaviour (C) or an explicit error (C++)
+# * to define a struct inside of `offsetof`. C compilers tend to accept such
+# * things, but AFAIK C++ has no room to allow.
+# *
+# * Second, there exist T such that `struct { char _; T t; }` is invalid. A
+# * known example is when T is a struct with a flexible array member. Such
+# * struct cannot be enclosed into another one.
+# */
+# /* see: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2083.htm */
+# /* see: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2350.htm */
+# define RBIMPL_ALIGNOF(T) offsetof(struct { char _; T t; }, t)
+
+#endif
+
+#endif /* RBIMPL_STDALIGN_H */
diff --git a/include/ruby/internal/stdbool.h b/include/ruby/internal/stdbool.h
new file mode 100644
index 0000000000..0cd5103a05
--- /dev/null
+++ b/include/ruby/internal/stdbool.h
@@ -0,0 +1,51 @@
+#ifndef RBIMPL_STDBOOL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_STDBOOL_H
+/**
+ * @file
+ * @author Ruby developers <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 C99 shim for <stdbool.h>
+ */
+#include "ruby/internal/config.h"
+
+#if defined(__bool_true_false_are_defined)
+# /* Take that. */
+
+#elif defined(__cplusplus)
+# /* bool is a keyword in C++. */
+# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L)
+# include <cstdbool>
+# endif
+#
+# ifndef __bool_true_false_are_defined
+# define __bool_true_false_are_defined
+# endif
+
+#elif defined(HAVE_STDBOOL_H)
+# /* Take stdbool.h definition. */
+# include <stdbool.h>
+
+#else
+typedef unsigned char _Bool;
+# /* See also http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2229.htm */
+# define bool _Bool
+# define true ((_Bool)+1)
+# define false ((_Bool)+0)
+# define __bool_true_false_are_defined
+#endif
+
+#endif /* RBIMPL_STDBOOL_H */
diff --git a/include/ruby/internal/symbol.h b/include/ruby/internal/symbol.h
new file mode 100644
index 0000000000..762f1e8f9b
--- /dev/null
+++ b/include/ruby/internal/symbol.h
@@ -0,0 +1,114 @@
+#ifndef RBIMPL_SYMBOL_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_SYMBOL_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 #rb_intern
+ */
+#include "ruby/internal/config.h"
+
+#ifdef HAVE_STDDEF_H
+# include <stddef.h>
+#endif
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/attr/noalias.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/constant_p.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/has/builtin.h"
+#include "ruby/internal/value.h"
+
+#define RB_ID2SYM rb_id2sym
+#define RB_SYM2ID rb_sym2id
+#define ID2SYM RB_ID2SYM
+#define SYM2ID RB_SYM2ID
+#define CONST_ID_CACHE RUBY_CONST_ID_CACHE
+#define CONST_ID RUBY_CONST_ID
+
+/** @cond INTERNAL_MACRO */
+#define rb_intern_const rb_intern_const
+/** @endcond */
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+ID rb_sym2id(VALUE);
+VALUE rb_id2sym(ID);
+ID rb_intern(const char*);
+ID rb_intern2(const char*, long);
+ID rb_intern_str(VALUE str);
+const char *rb_id2name(ID);
+ID rb_check_id(volatile VALUE *);
+ID rb_to_id(VALUE);
+VALUE rb_id2str(ID);
+VALUE rb_sym2str(VALUE);
+VALUE rb_to_symbol(VALUE name);
+VALUE rb_check_symbol(volatile VALUE *namep);
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_PURE()
+RBIMPL_ATTR_NONNULL(())
+static inline ID
+rb_intern_const(const char *str)
+{
+ size_t len = strlen(str);
+ return rb_intern2(str, RBIMPL_CAST((long)len));
+}
+
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL(())
+static inline ID
+rbimpl_intern_const(ID *ptr, const char *str)
+{
+ while (! *ptr) {
+ *ptr = rb_intern_const(str);
+ }
+
+ return *ptr;
+}
+
+/* Does anyone use it? Preserved for backward compat. */
+#define RUBY_CONST_ID_CACHE(result, str) \
+ { \
+ static ID rb_intern_id_cache; \
+ rbimpl_intern_const(&rb_intern_id_cache, (str)); \
+ result rb_intern_id_cache; \
+ }
+#define RUBY_CONST_ID(var, str) \
+ do { \
+ static ID rbimpl_id; \
+ (var) = rbimpl_intern_const(&rbimpl_id, (str)); \
+ } while (0)
+
+#if defined(HAVE_STMT_AND_DECL_IN_EXPR)
+/* __builtin_constant_p and statement expression is available
+ * since gcc-2.7.2.3 at least. */
+#define rb_intern(str) \
+ (RBIMPL_CONSTANT_P(str) ? \
+ __extension__ ({ \
+ static ID rbimpl_id; \
+ rbimpl_intern_const(&rbimpl_id, (str)); \
+ }) : \
+ (rb_intern)(str))
+#endif
+
+#endif /* RBIMPL_SYMBOL_H */
diff --git a/include/ruby/internal/token_paste.h b/include/ruby/internal/token_paste.h
new file mode 100644
index 0000000000..c42f7a67ef
--- /dev/null
+++ b/include/ruby/internal/token_paste.h
@@ -0,0 +1,75 @@
+#ifndef RBIMPL_TOKEN_PASTE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_TOKEN_PASTE_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_TOKEN_PASTE.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/warning.h"
+#include "ruby/internal/warning_push.h"
+
+/* :TODO: add your compiler here. There are many compilers that can suppress
+ * warnings via pragmas, but not all of them accept such things inside of `#if`
+ * and variants' conditions. And such nitpicking behavours tend not be
+ * documented. Please improve this file when you are really sure about your
+ * compiler's behaviour. */
+
+#if RBIMPL_COMPILER_SINCE(GCC, 4, 2, 0)
+# /* GCC is one of such compiler who cannot write `_Pragma` inside of a `#if`.
+# * Cannot but globally kill everything. This is of course a very bad thing.
+# * If you know how to reroute this please tell us. */
+# /* https://gcc.godbolt.org/z/K2xr7X */
+# define RBIMPL_TOKEN_PASTE(x, y) TOKEN_PASTE(x, y)
+# pragma GCC diagnostic ignored "-Wundef"
+# /* > warning: "symbol" is not defined, evaluates to 0 [-Wundef] */
+
+#elif RBIMPL_COMPILER_IS(Intel)
+# /* Ditto for icc. */
+# /* https://gcc.godbolt.org/z/pTwDxE */
+# define RBIMPL_TOKEN_PASTE(x, y) TOKEN_PASTE(x, y)
+# pragma warning(disable: 193)
+# /* > warning #193: zero used for undefined preprocessing identifier */
+
+#elif RBIMPL_COMPILER_BEFORE(MSVC, 19, 14, 26428)
+# /* :FIXME: is 19.14 the exact version they supported this? */
+# define RBIMPL_TOKEN_PASTE(x, y) TOKEN_PASTE(x, y)
+# pragma warning(disable: 4668)
+# /* > warning C4668: 'symbol' is not defined as a preprocessor macro */
+
+#elif RBIMPL_COMPILER_IS(MSVC)
+# define RBIMPL_TOKEN_PASTE(x, y) \
+ RBIMPL_WARNING_PUSH() \
+ RBIMPL_WARNING_IGNORED(4668) \
+ TOKEN_PASTE(x, y) \
+ RBIMPL_WARNING_POP()
+
+#elif RBIMPL_HAS_WARNING("-Wundef")
+# define RBIMPL_TOKEN_PASTE(x, y) \
+ RBIMPL_WARNING_PUSH() \
+ RBIMPL_WARNING_IGNORED(-Wundef) \
+ TOKEN_PASTE(x, y) \
+ RBIMPL_WARNING_POP()
+
+#else
+# /* No way. */
+# define RBIMPL_TOKEN_PASTE(x, y) TOKEN_PASTE(x, y)
+#endif
+
+#endif /* RBIMPL_TOKEN_PASTE_H */
diff --git a/include/ruby/internal/value.h b/include/ruby/internal/value.h
new file mode 100644
index 0000000000..b87fe140af
--- /dev/null
+++ b/include/ruby/internal/value.h
@@ -0,0 +1,66 @@
+#ifndef RBIMPL_VALUE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_VALUE_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 ::VALUE and ::ID.
+ */
+#include "ruby/internal/static_assert.h"
+#include "ruby/backward/2/long_long.h"
+#include "ruby/backward/2/limits.h"
+
+#if defined HAVE_UINTPTR_T && 0
+typedef uintptr_t VALUE;
+typedef uintptr_t ID;
+# define SIGNED_VALUE intptr_t
+# define SIZEOF_VALUE SIZEOF_UINTPTR_T
+# undef PRI_VALUE_PREFIX
+# define RBIMPL_VALUE_NULL UINTPTR_C(0)
+# define RBIMPL_VALUE_ONE UINTPTR_C(1)
+# define RBIMPL_VALUE_FULL UINTPTR_MAX
+
+#elif SIZEOF_LONG == SIZEOF_VOIDP
+typedef unsigned long VALUE;
+typedef unsigned long ID;
+# define SIGNED_VALUE long
+# define SIZEOF_VALUE SIZEOF_LONG
+# define PRI_VALUE_PREFIX "l"
+# define RBIMPL_VALUE_NULL 0UL
+# define RBIMPL_VALUE_ONE 1UL
+# define RBIMPL_VALUE_FULL ULONG_MAX
+
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+typedef unsigned LONG_LONG VALUE;
+typedef unsigned LONG_LONG ID;
+# define SIGNED_VALUE LONG_LONG
+# define LONG_LONG_VALUE 1
+# define SIZEOF_VALUE SIZEOF_LONG_LONG
+# define PRI_VALUE_PREFIX PRI_LL_PREFIX
+# define RBIMPL_VALUE_NULL 0ULL
+# define RBIMPL_VALUE_ONE 1ULL
+# define RBIMPL_VALUE_FULL ULLONG_MAX
+
+#else
+# error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
+#endif
+
+RBIMPL_STATIC_ASSERT(sizeof_int, SIZEOF_INT == sizeof(int));
+RBIMPL_STATIC_ASSERT(sizeof_long, SIZEOF_LONG == sizeof(long));
+RBIMPL_STATIC_ASSERT(sizeof_long_long, SIZEOF_LONG_LONG == sizeof(LONG_LONG));
+RBIMPL_STATIC_ASSERT(sizeof_voidp, SIZEOF_VOIDP == sizeof(void *));
+#endif /* RBIMPL_VALUE_H */
diff --git a/include/ruby/internal/value_type.h b/include/ruby/internal/value_type.h
new file mode 100644
index 0000000000..6f24f08910
--- /dev/null
+++ b/include/ruby/internal/value_type.h
@@ -0,0 +1,354 @@
+#ifndef RBIMPL_VALUE_TYPE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_VALUE_TYPE_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 enum ::ruby_value_type.
+ */
+#include "ruby/internal/assume.h"
+#include "ruby/internal/attr/artificial.h"
+#include "ruby/internal/attr/cold.h"
+#include "ruby/internal/attr/enum_extensibility.h"
+#include "ruby/internal/attr/forceinline.h"
+#include "ruby/internal/attr/pure.h"
+#include "ruby/internal/cast.h"
+#include "ruby/internal/constant_p.h"
+#include "ruby/internal/core/rbasic.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/has/builtin.h"
+#include "ruby/internal/special_consts.h"
+#include "ruby/internal/stdbool.h"
+#include "ruby/internal/value.h"
+#include "ruby/assert.h"
+
+#if defined(T_DATA)
+/*
+ * :!BEWARE!: (Recent?) Solaris' <nfs/nfs.h> have conflicting definition of
+ * T_DATA. Let us stop here. Please have a workaround like this:
+ *
+ * ```C
+ * #include <ruby/ruby.h> // <- Include this one first.
+ * #undef T_DATA // <- ... and stick to RUBY_T_DATA forever.
+ * #include <nfs/nfs.h> // <- OS-provided T_DATA introduced.
+ * ```
+ *
+ * See also [ruby-core:4261]
+ */
+# error Bail out due to conflicting definition of T_DATA.
+#endif
+
+#define T_ARRAY RUBY_T_ARRAY
+#define T_BIGNUM RUBY_T_BIGNUM
+#define T_CLASS RUBY_T_CLASS
+#define T_COMPLEX RUBY_T_COMPLEX
+#define T_DATA RUBY_T_DATA
+#define T_FALSE RUBY_T_FALSE
+#define T_FILE RUBY_T_FILE
+#define T_FIXNUM RUBY_T_FIXNUM
+#define T_FLOAT RUBY_T_FLOAT
+#define T_HASH RUBY_T_HASH
+#define T_ICLASS RUBY_T_ICLASS
+#define T_IMEMO RUBY_T_IMEMO
+#define T_MASK RUBY_T_MASK
+#define T_MATCH RUBY_T_MATCH
+#define T_MODULE RUBY_T_MODULE
+#define T_MOVED RUBY_T_MOVED
+#define T_NIL RUBY_T_NIL
+#define T_NODE RUBY_T_NODE
+#define T_NONE RUBY_T_NONE
+#define T_OBJECT RUBY_T_OBJECT
+#define T_RATIONAL RUBY_T_RATIONAL
+#define T_REGEXP RUBY_T_REGEXP
+#define T_STRING RUBY_T_STRING
+#define T_STRUCT RUBY_T_STRUCT
+#define T_SYMBOL RUBY_T_SYMBOL
+#define T_TRUE RUBY_T_TRUE
+#define T_UNDEF RUBY_T_UNDEF
+#define T_ZOMBIE RUBY_T_ZOMBIE
+
+#define BUILTIN_TYPE RB_BUILTIN_TYPE
+#define DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
+#define RB_INTEGER_TYPE_P rb_integer_type_p
+#define SYMBOL_P RB_SYMBOL_P
+#define rb_type_p RB_TYPE_P
+
+/** @cond INTERNAL_MACRO */
+#define RB_BUILTIN_TYPE RB_BUILTIN_TYPE
+#define RB_DYNAMIC_SYM_P RB_DYNAMIC_SYM_P
+#define RB_FLOAT_TYPE_P RB_FLOAT_TYPE_P
+#define RB_SYMBOL_P RB_SYMBOL_P
+#define RB_TYPE_P RB_TYPE_P
+#define Check_Type Check_Type
+
+#if !RUBY_DEBUG
+# define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P((v), (t)))
+#else
+# define RBIMPL_ASSERT_TYPE Check_Type
+#endif
+/** @endcond */
+
+#define TYPE(_) RBIMPL_CAST((int)rb_type(_))
+
+/** C-level type of an object. */
+enum
+RBIMPL_ATTR_ENUM_EXTENSIBILITY(closed)
+ruby_value_type {
+ RUBY_T_NONE = 0x00, /**< Non-object (sweeped etc.) */
+
+ RUBY_T_OBJECT = 0x01, /**< @see struct ::RObject */
+ RUBY_T_CLASS = 0x02, /**< @see struct ::RClass and ::rb_cClass */
+ RUBY_T_MODULE = 0x03, /**< @see struct ::RClass and ::rb_cModule */
+ RUBY_T_FLOAT = 0x04, /**< @see struct ::RFloat */
+ RUBY_T_STRING = 0x05, /**< @see struct ::RString */
+ RUBY_T_REGEXP = 0x06, /**< @see struct ::RRegexp */
+ RUBY_T_ARRAY = 0x07, /**< @see struct ::RArray */
+ RUBY_T_HASH = 0x08, /**< @see struct ::RHash */
+ RUBY_T_STRUCT = 0x09, /**< @see struct ::RStruct */
+ RUBY_T_BIGNUM = 0x0a, /**< @see struct ::RBignum */
+ RUBY_T_FILE = 0x0b, /**< @see struct ::RFile */
+ RUBY_T_DATA = 0x0c, /**< @see struct ::RTypedData */
+ RUBY_T_MATCH = 0x0d, /**< @see struct ::RMatch */
+ RUBY_T_COMPLEX = 0x0e, /**< @see struct ::RComplex */
+ RUBY_T_RATIONAL = 0x0f, /**< @see struct ::RRational */
+
+ RUBY_T_NIL = 0x11, /**< @see ::RUBY_Qnil */
+ RUBY_T_TRUE = 0x12, /**< @see ::RUBY_Qfalse */
+ RUBY_T_FALSE = 0x13, /**< @see ::RUBY_Qtrue */
+ RUBY_T_SYMBOL = 0x14, /**< @see struct ::RSymbol */
+ RUBY_T_FIXNUM = 0x15, /**< Integers formerly known as Fixnums. */
+ RUBY_T_UNDEF = 0x16, /**< @see ::RUBY_Qundef */
+
+ RUBY_T_IMEMO = 0x1a, /**< @see struct ::RIMemo */
+ RUBY_T_NODE = 0x1b, /**< @see struct ::RNode */
+ RUBY_T_ICLASS = 0x1c, /**< Hidden classes known as IClasses. */
+ RUBY_T_ZOMBIE = 0x1d, /**< @see struct ::RZombie */
+ RUBY_T_MOVED = 0x1e, /**< @see struct ::RMoved */
+
+ RUBY_T_MASK = 0x1f
+};
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+RBIMPL_ATTR_COLD()
+void rb_check_type(VALUE obj, int t);
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline enum ruby_value_type
+RB_BUILTIN_TYPE(VALUE obj)
+{
+ RBIMPL_ASSERT_OR_ASSUME(! RB_SPECIAL_CONST_P(obj));
+
+ VALUE ret = RBASIC(obj)->flags & RUBY_T_MASK;
+ return RBIMPL_CAST((enum ruby_value_type)ret);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+static inline bool
+rb_integer_type_p(VALUE obj)
+{
+ if (RB_FIXNUM_P(obj)) {
+ return true;
+ }
+ else if (RB_SPECIAL_CONST_P(obj)) {
+ return false;
+ }
+ else {
+ return RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM;
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+static inline enum ruby_value_type
+rb_type(VALUE obj)
+{
+ if (! RB_SPECIAL_CONST_P(obj)) {
+ return RB_BUILTIN_TYPE(obj);
+ }
+ else if (obj == RUBY_Qfalse) {
+ return RUBY_T_FALSE;
+ }
+ else if (obj == RUBY_Qnil) {
+ return RUBY_T_NIL;
+ }
+ else if (obj == RUBY_Qtrue) {
+ return RUBY_T_TRUE;
+ }
+ else if (obj == RUBY_Qundef) {
+ return RUBY_T_UNDEF;
+ }
+ else if (RB_FIXNUM_P(obj)) {
+ return RUBY_T_FIXNUM;
+ }
+ else if (RB_STATIC_SYM_P(obj)) {
+ return RUBY_T_SYMBOL;
+ }
+ else {
+ RBIMPL_ASSUME(RB_FLONUM_P(obj));
+ return RUBY_T_FLOAT;
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_FLOAT_TYPE_P(VALUE obj)
+{
+ if (RB_FLONUM_P(obj)) {
+ return true;
+ }
+ else if (RB_SPECIAL_CONST_P(obj)) {
+ return false;
+ }
+ else {
+ return RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT;
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_DYNAMIC_SYM_P(VALUE obj)
+{
+ if (RB_SPECIAL_CONST_P(obj)) {
+ return false;
+ }
+ else {
+ return RB_BUILTIN_TYPE(obj) == RUBY_T_SYMBOL;
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_SYMBOL_P(VALUE obj)
+{
+ return RB_STATIC_SYM_P(obj) || RB_DYNAMIC_SYM_P(obj);
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_FORCEINLINE()
+static bool
+rbimpl_RB_TYPE_P_fastpath(VALUE obj, enum ruby_value_type t)
+{
+ if (t == RUBY_T_TRUE) {
+ return obj == RUBY_Qtrue;
+ }
+ else if (t == RUBY_T_FALSE) {
+ return obj == RUBY_Qfalse;
+ }
+ else if (t == RUBY_T_NIL) {
+ return obj == RUBY_Qnil;
+ }
+ else if (t == RUBY_T_UNDEF) {
+ return obj == RUBY_Qundef;
+ }
+ else if (t == RUBY_T_FIXNUM) {
+ return RB_FIXNUM_P(obj);
+ }
+ else if (t == RUBY_T_SYMBOL) {
+ return RB_SYMBOL_P(obj);
+ }
+ else if (t == RUBY_T_FLOAT) {
+ return RB_FLOAT_TYPE_P(obj);
+ }
+ else if (RB_SPECIAL_CONST_P(obj)) {
+ return false;
+ }
+ else if (t == RB_BUILTIN_TYPE(obj)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline bool
+RB_TYPE_P(VALUE obj, enum ruby_value_type t)
+{
+ if (RBIMPL_CONSTANT_P(t)) {
+ return rbimpl_RB_TYPE_P_fastpath(obj, t);
+ }
+ else {
+ return t == rb_type(obj);
+ }
+}
+
+/** @cond INTERNAL_MACRO */
+/* Clang, unlike GCC, cannot propagate __builtin_constant_p beyond function
+ * boundary. */
+#if defined(__clang__)
+# undef RB_TYPE_P
+# define RB_TYPE_P(obj, t) \
+ (RBIMPL_CONSTANT_P(t) ? \
+ rbimpl_RB_TYPE_P_fastpath((obj), (t)) : \
+ (RB_TYPE_P)((obj), (t)))
+#endif
+
+/* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE
+ * in inline function and caller function
+ * See also 8998c06461ea0bef11b3aeb30b6d2ab71c8762ba
+ */
+#if RBIMPL_COMPILER_BEFORE(Clang, 4, 0, 0)
+# undef rb_integer_type_p
+# define rb_integer_type_p(obj) \
+ __extension__ ({ \
+ const VALUE integer_type_obj = (obj); \
+ (RB_FIXNUM_P(integer_type_obj) || \
+ (!RB_SPECIAL_CONST_P(integer_type_obj) && \
+ RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \
+ })
+#endif
+/** @endcond */
+
+RBIMPL_ATTR_PURE()
+RBIMPL_ATTR_ARTIFICIAL()
+/* Defined in ruby/internal/core/rtypeddata.h */
+static inline bool rbimpl_rtypeddata_p(VALUE obj);
+
+RBIMPL_ATTR_ARTIFICIAL()
+static inline void
+Check_Type(VALUE v, enum ruby_value_type t)
+{
+ if (RB_UNLIKELY(! RB_TYPE_P(v, t))) {
+ goto slowpath;
+ }
+ else if (t != RUBY_T_DATA) {
+ goto fastpath;
+ }
+ else if (rbimpl_rtypeddata_p(v)) {
+ /* The intention itself is not necessarily clear to me, but at least it
+ * is intentional to rule out typed data here. See commit
+ * a7c32bf81d3391cfb78cfda278f469717d0fb794. */
+ goto slowpath;
+ }
+ else {
+ goto fastpath;
+ }
+
+ fastpath:
+ return;
+
+ slowpath: /* <- :TODO: mark this label as cold. */
+ rb_check_type(v, t);
+}
+
+#endif /* RBIMPL_VALUE_TYPE_H */
diff --git a/include/ruby/internal/variable.h b/include/ruby/internal/variable.h
new file mode 100644
index 0000000000..b0cfa61a62
--- /dev/null
+++ b/include/ruby/internal/variable.h
@@ -0,0 +1,62 @@
+#ifndef RBIMPL_VARIABLE_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_VARIABLE_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 C-function backended Ruby-global variables.
+ */
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/attr/noreturn.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+typedef VALUE rb_gvar_getter_t(ID id, VALUE *data);
+typedef void rb_gvar_setter_t(VALUE val, ID id, VALUE *data);
+typedef void rb_gvar_marker_t(VALUE *var);
+
+rb_gvar_getter_t rb_gvar_undef_getter;
+rb_gvar_setter_t rb_gvar_undef_setter;
+rb_gvar_marker_t rb_gvar_undef_marker;
+
+rb_gvar_getter_t rb_gvar_val_getter;
+rb_gvar_setter_t rb_gvar_val_setter;
+rb_gvar_marker_t rb_gvar_val_marker;
+
+rb_gvar_getter_t rb_gvar_var_getter;
+rb_gvar_setter_t rb_gvar_var_setter;
+rb_gvar_marker_t rb_gvar_var_marker;
+
+RBIMPL_ATTR_NORETURN()
+rb_gvar_setter_t rb_gvar_readonly_setter;
+
+void rb_define_variable(const char*,VALUE*);
+void rb_define_virtual_variable(const char*,rb_gvar_getter_t*,rb_gvar_setter_t*);
+void rb_define_hooked_variable(const char*,VALUE*,rb_gvar_getter_t*,rb_gvar_setter_t*);
+void rb_define_readonly_variable(const char*,const VALUE*);
+void rb_define_const(VALUE,const char*,VALUE);
+void rb_define_global_const(const char*,VALUE);
+
+VALUE rb_gv_set(const char*, VALUE);
+VALUE rb_gv_get(const char*);
+VALUE rb_iv_get(VALUE, const char*);
+VALUE rb_iv_set(VALUE, const char*, VALUE);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_VARIABLE_H */
diff --git a/include/ruby/internal/warning_push.h b/include/ruby/internal/warning_push.h
new file mode 100644
index 0000000000..b8a21aaeab
--- /dev/null
+++ b/include/ruby/internal/warning_push.h
@@ -0,0 +1,91 @@
+#ifndef RBIMPL_WARNING_PUSH_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_WARNING_PUSH_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_WARNING_PUSH.
+ * @cond INTERNAL_MACRO
+ *
+ * ### Q&A ###
+ *
+ * Q: Why all the macros defined in this file are function-like macros?
+ *
+ * A: Sigh. This is because of Doxgen. Its `SKIP_FUNCTION_MACROS = YES`
+ * configuration setting requests us that if we want it to ignore these
+ * macros, then we have to do two things: (1) let them be defined as
+ * function-like macros, and (2) place them separately in their own line,
+ * like below:
+ *
+ * ```CXX
+ * // NG -- foo's type considered something like `unsigned int`.
+ * RBIMPL_WARNING_PUSH
+ * int foo(void);
+ * RBIMPL_WARNING_POP
+ *
+ * // OK -- the macros are ignored by Doxygen.
+ * RBIMPL_WARNING_PUSH()
+ * int foo(void);
+ * RBIMPL_WARNING_POP()
+ * ```
+ */
+#include "ruby/internal/compiler_is.h"
+#include "ruby/internal/compiler_since.h"
+
+#if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0)
+# /* Not sure exactly when but it seems VC++ 6.0 is a version with it.*/
+# define RBIMPL_WARNING_PUSH() __pragma(warning(push))
+# define RBIMPL_WARNING_POP() __pragma(warning(pop))
+# define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag))
+# define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag))
+
+#elif RBIMPL_COMPILER_SINCE(Intel, 13, 0, 0)
+# define RBIMPL_WARNING_PUSH() __pragma(warning(push))
+# define RBIMPL_WARNING_POP() __pragma(warning(pop))
+# define RBIMPL_WARNING_ERROR(flag) __pragma(warning(error: flag))
+# define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag))
+
+#elif RBIMPL_COMPILER_IS(Clang) || RBIMPL_COMPILER_IS(Apple)
+# /* Not sure exactly when but it seems LLVM 2.6.0 is a version with it. */
+# define RBIMPL_WARNING_PRAGMA0(x) _Pragma(# x)
+# define RBIMPL_WARNING_PRAGMA1(x) RBIMPL_WARNING_PRAGMA0(clang diagnostic x)
+# define RBIMPL_WARNING_PRAGMA2(x, y) RBIMPL_WARNING_PRAGMA1(x # y)
+# define RBIMPL_WARNING_PUSH() RBIMPL_WARNING_PRAGMA1(push)
+# define RBIMPL_WARNING_POP() RBIMPL_WARNING_PRAGMA1(pop)
+# define RBIMPL_WARNING_ERROR(flag) RBIMPL_WARNING_PRAGMA2(error, flag)
+# define RBIMPL_WARNING_IGNORED(flag) RBIMPL_WARNING_PRAGMA2(ignored, flag)
+
+#elif RBIMPL_COMPILER_SINCE(GCC, 4, 6, 0)
+# /* https://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Diagnostic-Pragmas.html */
+# define RBIMPL_WARNING_PRAGMA0(x) _Pragma(# x)
+# define RBIMPL_WARNING_PRAGMA1(x) RBIMPL_WARNING_PRAGMA0(GCC diagnostic x)
+# define RBIMPL_WARNING_PRAGMA2(x, y) RBIMPL_WARNING_PRAGMA1(x # y)
+# define RBIMPL_WARNING_PUSH() RBIMPL_WARNING_PRAGMA1(push)
+# define RBIMPL_WARNING_POP() RBIMPL_WARNING_PRAGMA1(pop)
+# define RBIMPL_WARNING_ERROR(flag) RBIMPL_WARNING_PRAGMA2(error, flag)
+# define RBIMPL_WARNING_IGNORED(flag) RBIMPL_WARNING_PRAGMA2(ignored, flag)
+
+#else
+# /* :FIXME: improve here */
+# define RBIMPL_WARNING_PUSH() /* void */
+# define RBIMPL_WARNING_POP() /* void */
+# define RBIMPL_WARNING_ERROR(flag) /* void */
+# define RBIMPL_WARNING_IGNORED(flag) /* void */
+#endif /* _MSC_VER */
+/** @endcond */
+
+#endif /* RBIMPL_WARNING_PUSH_H */
diff --git a/include/ruby/internal/xmalloc.h b/include/ruby/internal/xmalloc.h
new file mode 100644
index 0000000000..76da1eb099
--- /dev/null
+++ b/include/ruby/internal/xmalloc.h
@@ -0,0 +1,362 @@
+#ifndef RBIMPL_XMALLOC_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_XMALLOC_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 Declares ::ruby_xmalloc().
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#include "ruby/internal/attr/alloc_size.h"
+#include "ruby/internal/attr/nodiscard.h"
+#include "ruby/internal/attr/noexcept.h"
+#include "ruby/internal/attr/restrict.h"
+#include "ruby/internal/attr/returns_nonnull.h"
+#include "ruby/internal/dllexport.h"
+
+#ifndef USE_GC_MALLOC_OBJ_INFO_DETAILS
+# define USE_GC_MALLOC_OBJ_INFO_DETAILS 0
+#endif
+
+#define xmalloc ruby_xmalloc
+#define xmalloc2 ruby_xmalloc2
+#define xcalloc ruby_xcalloc
+#define xrealloc ruby_xrealloc
+#define xrealloc2 ruby_xrealloc2
+#define xfree ruby_xfree
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+RBIMPL_ATTR_NODISCARD()
+RBIMPL_ATTR_RESTRICT()
+RBIMPL_ATTR_RETURNS_NONNULL()
+RBIMPL_ATTR_ALLOC_SIZE((1))
+/**
+ * Allocates a storage instance. It is largely the same as system malloc(),
+ * except:
+ *
+ * - It raises Ruby exceptions instead of returning NULL, and
+ * - In case of `ENOMEM` it tries to GC to make some room.
+ *
+ * @param[in] size Requested amount of memory.
+ * @exception rb_eNoMemError No space left for `size` bytes allocation.
+ * @return A valid pointer to an allocated storage instance; which has at
+ * least `size` bytes width, with appropriate alignment detected by
+ * the underlying malloc() routine.
+ * @note It doesn't return NULL.
+ * @note Unlike some malloc() implementations, it allocates something and
+ * returns a meaningful value even when `size` is equal to zero.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
+void *ruby_xmalloc(size_t size)
+RBIMPL_ATTR_NOEXCEPT(malloc(size))
+;
+
+RBIMPL_ATTR_NODISCARD()
+RBIMPL_ATTR_RESTRICT()
+RBIMPL_ATTR_RETURNS_NONNULL()
+RBIMPL_ATTR_ALLOC_SIZE((1,2))
+/**
+ * Identical to ruby_xmalloc(), except it allocates `nelems` * `elemsiz` bytes.
+ * This is needed because the multiplication could integer overflow. On such
+ * situations Ruby does not try to allocate at all but raises Ruby level
+ * exceptions instead. If there is no integer overflow the behaviour is
+ * exactly the same as `ruby_xmalloc(nelems*elemsiz)`.
+ *
+ * @param[in] nelems Number of elements.
+ * @param[in] elemsiz Size of an element.
+ * @exception rb_eNoMemError No space left for allocation.
+ * @exception rb_eArgError `nelems` * `elemsiz` would overflow.
+ * @return A valid pointer to an allocated storage instance; which has at
+ * least `nelems` * `elemsiz` bytes width, with appropriate
+ * alignment detected by the underlying malloc() routine.
+ * @note It doesn't return NULL.
+ * @note Unlike some malloc() implementations, it allocates something and
+ * returns a meaningful value even when `nelems` or `elemsiz` or
+ * both are zero.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
+void *ruby_xmalloc2(size_t nelems, size_t elemsiz)
+RBIMPL_ATTR_NOEXCEPT(malloc(nelems * elemsiz))
+;
+
+RBIMPL_ATTR_NODISCARD()
+RBIMPL_ATTR_RESTRICT()
+RBIMPL_ATTR_RETURNS_NONNULL()
+RBIMPL_ATTR_ALLOC_SIZE((1,2))
+/**
+ * Identical to ruby_xmalloc2(), except it zero-fills the region before it
+ * returns. This could also be seen as a routine identical to ruby_xmalloc(),
+ * except it calls calloc() instead of malloc() internally.
+ *
+ * @param[in] nelems Number of elements.
+ * @param[in] elemsiz Size of an element.
+ * @exception rb_eNoMemError No space left for allocation.
+ * @exception rb_eArgError `nelems` * `elemsiz` would overflow.
+ * @return A valid pointer to an allocated storage instance; which has at
+ * least `nelems` * `elemsiz` bytes width, with appropriate
+ * alignment detected by the underlying calloc() routine.
+ * @note It doesn't return NULL.
+ * @note Unlike some calloc() implementations, it allocates something and
+ * returns a meaningful value even when `nelems` or `elemsiz` or
+ * both are zero.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
+void *ruby_xcalloc(size_t nelems, size_t elemsiz)
+RBIMPL_ATTR_NOEXCEPT(calloc(nelems, elemsiz))
+;
+
+RBIMPL_ATTR_NODISCARD()
+RBIMPL_ATTR_RETURNS_NONNULL()
+RBIMPL_ATTR_ALLOC_SIZE((2))
+/**
+ * Resize the storage instance.
+ *
+ * @param[in] ptr A valid pointer to a storage instance that was
+ * previously returned from either ruby_xmalloc(),
+ * ruby_xmalloc2(), ruby_xcalloc(),
+ * ruby_xrealloc(), or ruby_xrealloc2().
+ * @param[in] newsiz Requested new amount of memory.
+ * @exception rb_eNoMemError No space left for `newsiz` bytes allocation.
+ * @retval ptr In case the function returns the passed pointer
+ * as-is, the storage instance that the pointer
+ * holds is either grown or shrunken to have at
+ * least `newsiz` bytes.
+ * @retval otherwise A valid pointer to a newly allocated storage
+ * instance which has at least `newsiz` bytes
+ * width, and holds previous contents of `ptr`. In
+ * this case `ptr` is invalidated as if it was
+ * passed to ruby_xfree().
+ * @note It doesn't return NULL.
+ * @warning Unlike some realloc() implementations, passing zero to `elemsiz`
+ * is not the same as calling ruby_xfree(), because this function
+ * never returns NULL. Something meaningful still returns then.
+ * @warning It is a failure not to check the return value. Do not assume
+ * anything on it. It could be either identical to, or distinct
+ * form the passed argument.
+ * @warning Do not assume anything on the alignment of the return value.
+ * There is no guarantee that it inherits the passed argument's
+ * one.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
+void *ruby_xrealloc(void *ptr, size_t newsiz)
+RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newsiz))
+;
+
+RBIMPL_ATTR_NODISCARD()
+RBIMPL_ATTR_RETURNS_NONNULL()
+RBIMPL_ATTR_ALLOC_SIZE((2,3))
+/**
+ * Identical to ruby_xrealloc(), except it resizes the given storage instance
+ * to `newelems` * `newsiz` bytes. This is needed because the multiplication
+ * could integer overflow. On such situations Ruby does not try to touch the
+ * contents of argument pointer at all but raises Ruby level exceptions
+ * instead. If there is no integer overflow the behaviour is exactly the same
+ * as `ruby_xrealloc(ptr,nelems*elemsiz)`.
+ *
+ * This is roughly the same as reallocarray() function that OpenBSD
+ * etc. provides, but also interacts with our GC.
+ *
+ * @param[in] ptr A valid pointer to a storage instance that was
+ * previously returned from either ruby_xmalloc(),
+ * ruby_xmalloc2(), ruby_xcalloc(),
+ * ruby_xrealloc(), or ruby_xrealloc2().
+
+ * @param[in] newelems Requested new number of elements.
+ * @param[in] newsiz Requested new size of each element.
+ * @exception rb_eNoMemError No space left for allocation.
+ * @exception rb_eArgError `newelems` * `newsiz` would overflow.
+ * @retval ptr In case the function returns the passed pointer
+ * as-is, the storage instance that the pointer
+ * holds is either grown or shrunken to have at
+ * least `newelems` * `newsiz` bytes.
+ * @retval otherwise A valid pointer to a newly allocated storage
+ * instance which has at least `newelems` *
+ * `newsiz` bytes width, and holds previous
+ * contents of `ptr`. In this case `ptr` is
+ * invalidated as if it was passed to ruby_xfree().
+ * @note It doesn't return NULL.
+ * @warning Unlike some realloc() implementations, passing zero to either
+ * `newelems` or `elemsiz` are not the same as calling
+ * ruby_xfree(), because this function never returns NULL.
+ * Something meaningful still returns then.
+ * @warning It is a failure not to check the return value. Do not assume
+ * anything on it. It could be either identical to, or distinct
+ * form the passed argument.
+ * @warning Do not assume anything on the alignment of the return value.
+ * There is no guarantee that it inherits the passed argument's
+ * one.
+ * @warning The return value shall be invalidated exactly once by either
+ * ruby_xfree(), ruby_xrealloc(), or ruby_xrealloc2(). It is a
+ * failure to pass it to system free(), because the system and Ruby
+ * might or might not share the same malloc() implementation.
+ */
+void *ruby_xrealloc2(void *ptr, size_t newelems, size_t newsiz)
+RBIMPL_ATTR_NOEXCEPT(realloc(ptr, newelems * newsiz))
+;
+
+/**
+ * Deallocates a storage instance.
+ *
+ * @param[out] ptr Either NULL, or a valid pointer previously returned from
+ * one of ruby_xmalloc(), ruby_xmalloc2(), ruby_xcalloc(),
+ * ruby_xrealloc(), or ruby_xrealloc2().
+ * @warning Every single storage instance that was previously allocated by
+ * either ruby_xmalloc(), ruby_xmalloc2(), ruby_xcalloc(),
+ * ruby_xrealloc(), or ruby_xrealloc2() shall be invalidated
+ * exactly once by either passing it to ruby_xfree(), or passing
+ * it to either ruby_xrealloc(), ruby_xrealloc2() then check the
+ * return value for invalidation.
+ * @warning Do not pass anything other than pointers described above. For
+ * instance pointers returned from malloc() or mmap() shall not be
+ * passed to this function, because the underlying memory
+ * management mechanism could differ.
+ * @warning Do not pass any invalid pointers to this function e.g. by
+ * calling it twice with a same argument.
+ */
+void ruby_xfree(void *ptr)
+RBIMPL_ATTR_NOEXCEPT(free(ptr))
+;
+
+#if USE_GC_MALLOC_OBJ_INFO_DETAILS || defined(__DOXYGEN)
+# 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 152f4ef763..a3de95f281 100644
--- a/include/ruby/io.h
+++ b/include/ruby/io.h
@@ -1,27 +1,16 @@
-/**********************************************************************
-
- rubyio.h -
-
- $Author$
- created at: Fri Nov 12 16:47:09 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_IO_H
+#ifndef RUBY_IO_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_IO_H 1
-
-#ifdef RUBY_INTERNAL_H
-#error "Include this file before internal.h"
-#endif
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
+/**
+ * @file
+ * @author $Author$
+ * @date Fri Nov 12 16:47:09 JST 1993
+ * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#include "ruby/internal/config.h"
#include <stdio.h>
#include "ruby/encoding.h"
@@ -30,7 +19,6 @@ extern "C" {
#include <stdio_ext.h>
#endif
-#include "ruby/config.h"
#include <errno.h>
#if defined(HAVE_POLL)
# ifdef _AIX
@@ -53,7 +41,14 @@ extern "C" {
# define RB_WAITFD_OUT 0x004
#endif
-RUBY_SYMBOL_EXPORT_BEGIN
+typedef enum {
+ RUBY_IO_READABLE = RB_WAITFD_IN,
+ RUBY_IO_WRITABLE = RB_WAITFD_OUT,
+ RUBY_IO_PRIORITY = RB_WAITFD_PRI,
+} rb_io_event_t;
+
+#include "ruby/internal/dllexport.h"
+RBIMPL_SYMBOL_EXPORT_BEGIN()
PACKED_STRUCT_UNALIGNED(struct rb_io_buffer_t {
char *ptr; /* off + len <= capa */
@@ -64,6 +59,8 @@ PACKED_STRUCT_UNALIGNED(struct rb_io_buffer_t {
typedef struct rb_io_buffer_t rb_io_buffer_t;
typedef struct rb_io_t {
+ VALUE self;
+
FILE *stdio_file; /* stdio ptr for read/write if available */
int fd; /* file descriptor */
int mode; /* mode flags: FMODE_XXXs */
@@ -124,11 +121,13 @@ typedef struct rb_io_enc_t rb_io_enc_t;
/* #define FMODE_INET 0x00400000 */
/* #define FMODE_INET6 0x00800000 */
-#define GetOpenFile(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr)
+#define RB_IO_POINTER(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr)
+#define GetOpenFile RB_IO_POINTER
-#define MakeOpenFile(obj, fp) do {\
+#define RB_IO_OPEN(obj, fp) do {\
(fp) = rb_io_make_open_file(obj);\
} while (0)
+#define MakeOpenFile RB_IO_OPEN
rb_io_t *rb_io_make_open_file(VALUE obj);
@@ -150,14 +149,17 @@ VALUE rb_io_get_io(VALUE io);
VALUE rb_io_check_io(VALUE io);
VALUE rb_io_get_write_io(VALUE io);
VALUE rb_io_set_write_io(VALUE io, VALUE w);
-int rb_io_wait_readable(int);
-int rb_io_wait_writable(int);
-int rb_wait_for_single_fd(int fd, int events, struct timeval *tv);
void rb_io_set_nonblock(rb_io_t *fptr);
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p);
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);
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size);
+int rb_io_wait_readable(int fd);
+int rb_io_wait_writable(int fd);
+int rb_wait_for_single_fd(int fd, int events, struct timeval *tv);
+
+VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout);
+
/* compatibility for ruby 1.8 and older */
#define rb_io_mode_flags(modestr) [<"rb_io_mode_flags() is obsolete; use rb_io_modestr_fmode()">]
#define rb_io_modenum_flags(oflags) [<"rb_io_modenum_flags() is obsolete; use rb_io_oflags_fmode()">]
@@ -173,13 +175,6 @@ VALUE rb_stat_new(const struct stat *);
/* gc.c */
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_IO_H */
diff --git a/include/ruby/memory_view.h b/include/ruby/memory_view.h
new file mode 100644
index 0000000000..4996cdbbb3
--- /dev/null
+++ b/include/ruby/memory_view.h
@@ -0,0 +1,165 @@
+#ifndef RUBY_MEMORY_VIEW_H
+#define RUBY_MEMORY_VIEW_H 1
+/**
+ * @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.
+ * @brief Memory View.
+ */
+
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/stdbool.h"
+#include "ruby/internal/value.h"
+#include "ruby/intern.h"
+
+enum ruby_memory_view_flags {
+ RUBY_MEMORY_VIEW_SIMPLE = 0,
+ RUBY_MEMORY_VIEW_WRITABLE = (1<<0),
+ RUBY_MEMORY_VIEW_FORMAT = (1<<1),
+ RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL = (1<<2),
+ RUBY_MEMORY_VIEW_STRIDES = (1<<3) | RUBY_MEMORY_VIEW_MULTI_DIMENSIONAL,
+ RUBY_MEMORY_VIEW_ROW_MAJOR = (1<<4) | RUBY_MEMORY_VIEW_STRIDES,
+ RUBY_MEMORY_VIEW_COLUMN_MAJOR = (1<<5) | RUBY_MEMORY_VIEW_STRIDES,
+ RUBY_MEMORY_VIEW_ANY_CONTIGUOUS = RUBY_MEMORY_VIEW_ROW_MAJOR | RUBY_MEMORY_VIEW_COLUMN_MAJOR,
+ RUBY_MEMORY_VIEW_INDIRECT = (1<<6) | RUBY_MEMORY_VIEW_STRIDES,
+};
+
+typedef struct {
+ char format;
+ unsigned native_size_p: 1;
+ unsigned little_endian_p: 1;
+ size_t offset;
+ size_t size;
+ size_t repeat;
+} rb_memory_view_item_component_t;
+
+typedef struct {
+ /* The original object that has the memory exported via this memory view.
+ * The consumer of this memory view has the responsibility to call rb_gc_mark
+ * for preventing this obj collected by GC. */
+ VALUE obj;
+
+ /* The pointer to the exported memory. */
+ void *data;
+
+ /* The number of bytes in data. */
+ ssize_t byte_size;
+
+ /* true for readonly memory, false for writable memory. */
+ bool readonly;
+
+ /* A string to describe the format of an element, or NULL for unsigned bytes.
+ * The format string is a sequence of the following pack-template specifiers:
+ *
+ * c, C, s, s!, S, S!, n, v, i, i!, I, I!, l, l!, L, L!,
+ * N, V, f, e, g, q, q!, Q, Q!, d, E, G, j, J, x
+ *
+ * For example, "dd" for an element that consists of two double values,
+ * and "CCC" for an element that consists of three bytes, such as
+ * an RGB color triplet.
+ *
+ * Also, the value endianness can be explicitly specified by '<' or '>'
+ * following a value type specifier.
+ *
+ * The items are packed contiguously. When you emulate the alignment of
+ * structure members, put '|' at the beginning of the format string,
+ * like "|iqc". On x86_64 Linux ABI, the size of the item by this format
+ * is 24 bytes instead of 13 bytes.
+ */
+ const char *format;
+
+ /* The number of bytes in each element.
+ * item_size should equal to rb_memory_view_item_size_from_format(format). */
+ ssize_t item_size;
+
+ struct {
+ /* The array of rb_memory_view_item_component_t that describes the
+ * item structure. rb_memory_view_prepare_item_desc and
+ * rb_memory_view_get_item allocate this memory if needed,
+ * and rb_memory_view_release frees it. */
+ const rb_memory_view_item_component_t *components;
+
+ /* The number of components in an item. */
+ size_t length;
+ } item_desc;
+
+ /* The number of dimension. */
+ ssize_t ndim;
+
+ /* ndim size array indicating the number of elements in each dimension.
+ * This can be NULL when ndim == 1. */
+ const ssize_t *shape;
+
+ /* ndim size array indicating the number of bytes to skip to go to the
+ * next element in each dimension. */
+ const ssize_t *strides;
+
+ /* The offset in each dimension when this memory view exposes a nested array.
+ * Or, NULL when this memory view exposes a flat array. */
+ const ssize_t *sub_offsets;
+
+ /* the private data for managing this exported memory */
+ void *const private;
+} rb_memory_view_t;
+
+typedef bool (* rb_memory_view_get_func_t)(VALUE obj, rb_memory_view_t *view, int flags);
+typedef bool (* rb_memory_view_release_func_t)(VALUE obj, rb_memory_view_t *view);
+typedef bool (* rb_memory_view_available_p_func_t)(VALUE obj);
+
+typedef struct {
+ rb_memory_view_get_func_t get_func;
+ rb_memory_view_release_func_t release_func;
+ rb_memory_view_available_p_func_t available_p_func;
+} rb_memory_view_entry_t;
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* memory_view.c */
+bool rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry);
+
+RBIMPL_ATTR_PURE()
+bool rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view);
+RBIMPL_ATTR_PURE()
+bool rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view);
+RBIMPL_ATTR_NOALIAS()
+void rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides);
+RBIMPL_ATTR_NOALIAS()
+bool rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly);
+ssize_t rb_memory_view_parse_item_format(const char *format,
+ rb_memory_view_item_component_t **members,
+ size_t *n_members, const char **err);
+ssize_t rb_memory_view_item_size_from_format(const char *format, const char **err);
+void *rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices);
+VALUE rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members);
+void rb_memory_view_prepare_item_desc(rb_memory_view_t *view);
+VALUE rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices);
+
+bool rb_memory_view_available_p(VALUE obj);
+bool rb_memory_view_get(VALUE obj, rb_memory_view_t* memory_view, int flags);
+bool rb_memory_view_release(rb_memory_view_t* memory_view);
+
+/* for testing */
+RUBY_EXTERN VALUE rb_memory_view_exported_object_registry;
+RUBY_EXTERN const rb_data_type_t rb_memory_view_exported_object_registry_data_type;
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_PURE()
+static inline bool
+rb_memory_view_is_contiguous(const rb_memory_view_t *view)
+{
+ if (rb_memory_view_is_row_major_contiguous(view)) {
+ return true;
+ }
+ else if (rb_memory_view_is_column_major_contiguous(view)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+#endif /* RUBY_BUFFER_H */
diff --git a/include/ruby/missing.h b/include/ruby/missing.h
index 03657042ce..f83f1b695c 100644
--- a/include/ruby/missing.h
+++ b/include/ruby/missing.h
@@ -1,42 +1,45 @@
-/************************************************
-
- missing.h - prototype for *.c in ./missing, and
- for missing timeval struct
-
- $Author$
- created at: Sat May 11 23:46:03 JST 2002
-
-************************************************/
-
-#ifndef RUBY_MISSING_H
+#ifndef RUBY_MISSING_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_MISSING_H 1
+/**
+ * @file
+ * @author $Author$
+ * @date Sat May 11 23:46:03 JST 2002
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ * @brief Prototype for *.c in ./missing, and for missing timeval struct.
+ */
+#include "ruby/internal/config.h"
+
+#ifdef STDC_HEADERS
+# include <stddef.h>
+#endif
#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
+# include <cmath>
+#else
+# include <math.h> /* for INFINITY and NAN */
#endif
-#include "ruby/config.h"
-#include <stddef.h>
-#include <math.h> /* for INFINITY and NAN */
#ifdef RUBY_ALTERNATIVE_MALLOC_HEADER
# include RUBY_ALTERNATIVE_MALLOC_HEADER
#endif
-#ifdef RUBY_EXTCONF_H
-#include RUBY_EXTCONF_H
-#endif
-#if !defined(HAVE_STRUCT_TIMEVAL) || !defined(HAVE_STRUCT_TIMESPEC)
#if defined(HAVE_TIME_H)
# include <time.h>
#endif
+
#if defined(HAVE_SYS_TIME_H)
# include <sys/time.h>
#endif
+
+#ifdef HAVE_IEEEFP_H
+# include <ieeefp.h>
#endif
+#include "ruby/internal/dllexport.h"
+
#ifndef M_PI
# define M_PI 3.14159265358979323846
#endif
@@ -44,11 +47,6 @@ extern "C" {
# define M_PI_2 (M_PI/2)
#endif
-#ifndef RUBY_SYMBOL_EXPORT_BEGIN
-# define RUBY_SYMBOL_EXPORT_BEGIN /* begin */
-# define RUBY_SYMBOL_EXPORT_END /* end */
-#endif
-
#if !defined(HAVE_STRUCT_TIMEVAL)
struct timeval {
time_t tv_sec; /* seconds */
@@ -57,6 +55,10 @@ struct timeval {
#endif /* HAVE_STRUCT_TIMEVAL */
#if !defined(HAVE_STRUCT_TIMESPEC)
+/* :BEWARE: @shyouhei warns that IT IS A WRONG IDEA to define our own version
+ * of struct timespec here. `clock_gettime` is a system call, and your kernel
+ * could expect something other than just `long` (results stack smashing if
+ * that happens). See also https://ewontfix.com/19/ */
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
@@ -70,14 +72,7 @@ struct timezone {
};
#endif
-#ifdef RUBY_EXPORT
-#undef RUBY_EXTERN
-#endif
-#ifndef RUBY_EXTERN
-#define RUBY_EXTERN extern
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
+RBIMPL_SYMBOL_EXPORT_BEGIN()
#ifndef HAVE_ACOSH
RUBY_EXTERN double acosh(double);
@@ -161,36 +156,35 @@ RUBY_EXTERN const union bytesequence4_or_float rb_nan;
# define HUGE_VAL ((double)INFINITY)
#endif
-#ifndef isinf
-# ifndef HAVE_ISINF
-# if defined(HAVE_FINITE) && defined(HAVE_ISNAN)
-# ifdef HAVE_IEEEFP_H
-# include <ieeefp.h>
-# endif
-# define isinf(x) (!finite(x) && !isnan(x))
-# elif defined(__cplusplus) && __cplusplus >= 201103L
-# include <cmath> // it must include constexpr bool isinf(double);
-# else
+#if defined(isinf)
+# /* Take that. */
+#elif defined(HAVE_ISINF)
+# /* Take that. */
+#elif defined(HAVE_FINITE) && defined(HAVE_ISNAN)
+# define isinf(x) (!finite(x) && !isnan(x))
+#elif defined(__cplusplus) && __cplusplus >= 201103L
+# // <cmath> must include constexpr bool isinf(double);
+#else
RUBY_EXTERN int isinf(double);
-# endif
-# endif
#endif
-#ifndef isnan
-# ifndef HAVE_ISNAN
-# if defined(__cplusplus) && __cplusplus >= 201103L
-# include <cmath> // it must include constexpr bool isnan(double);
-# else
+#if defined(isnan)
+# /* Take that. */
+#elif defined(HAVE_ISNAN)
+# /* Take that. */
+#elif defined(__cplusplus) && __cplusplus >= 201103L
+# // <cmath> must include constexpr bool isnan(double);
+#else
RUBY_EXTERN int isnan(double);
-# endif
-# endif
#endif
-#ifndef isfinite
-# ifndef HAVE_ISFINITE
-# define HAVE_ISFINITE 1
-# define isfinite(x) finite(x)
-# endif
+#if defined(isfinite)
+# /* Take that. */
+#elif defined(HAVE_ISFINITE)
+# /* Take that. */
+#else
+# define HAVE_ISFINITE 1
+# define isfinite(x) finite(x)
#endif
#ifndef HAVE_NAN
@@ -247,8 +241,8 @@ RUBY_EXTERN int ffs(int);
#endif
#ifdef BROKEN_CLOSE
-#include <sys/types.h>
-#include <sys/socket.h>
+# include <sys/types.h>
+# include <sys/socket.h>
RUBY_EXTERN int ruby_getpeername(int, struct sockaddr *, socklen_t *);
RUBY_EXTERN int ruby_getsockname(int, struct sockaddr *, socklen_t *);
RUBY_EXTERN int ruby_shutdown(int, int);
@@ -259,20 +253,14 @@ RUBY_EXTERN int ruby_close(int);
RUBY_EXTERN void setproctitle(const char *fmt, ...);
#endif
-#ifndef HAVE_EXPLICIT_BZERO
+#ifdef HAVE_EXPLICIT_BZERO
+# /* Take that. */
+#elif defined(SecureZeroMemory)
+# define explicit_bzero(b, len) SecureZeroMemory(b, len)
+#else
RUBY_EXTERN void explicit_bzero(void *b, size_t len);
-# if defined SecureZeroMemory
-# define explicit_bzero(b, len) SecureZeroMemory(b, len)
-# endif
#endif
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_MISSING_H */
diff --git a/include/ruby/ractor.h b/include/ruby/ractor.h
new file mode 100644
index 0000000000..1d6687456c
--- /dev/null
+++ b/include/ruby/ractor.h
@@ -0,0 +1,68 @@
+#ifndef RUBY_RACTOR_H
+#define RUBY_RACTOR_H 1
+
+/**
+ * @file
+ * @author Koichi Sasada
+ * @date Tue Nov 17 16:39:15 2020
+ * @copyright Copyright (C) 2020 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+
+struct rb_ractor_local_storage_type {
+ void (*mark)(void *ptr);
+ void (*free)(void *ptr);
+ // TODO: update
+};
+
+typedef struct rb_ractor_local_key_struct *rb_ractor_local_key_t;
+
+RUBY_SYMBOL_EXPORT_BEGIN
+RUBY_EXTERN VALUE rb_cRactor;
+
+VALUE rb_ractor_stdin(void);
+VALUE rb_ractor_stdout(void);
+VALUE rb_ractor_stderr(void);
+void rb_ractor_stdin_set(VALUE);
+void rb_ractor_stdout_set(VALUE);
+void rb_ractor_stderr_set(VALUE);
+
+rb_ractor_local_key_t rb_ractor_local_storage_value_newkey(void);
+VALUE rb_ractor_local_storage_value(rb_ractor_local_key_t key);
+bool rb_ractor_local_storage_value_lookup(rb_ractor_local_key_t key, VALUE *val);
+void rb_ractor_local_storage_value_set(rb_ractor_local_key_t key, VALUE val);
+
+RUBY_EXTERN const struct rb_ractor_local_storage_type rb_ractor_local_storage_type_free;
+#define RB_RACTOR_LOCAL_STORAGE_TYPE_FREE (&rb_ractor_local_storage_type_free)
+
+rb_ractor_local_key_t rb_ractor_local_storage_ptr_newkey(const struct rb_ractor_local_storage_type *type);
+void *rb_ractor_local_storage_ptr(rb_ractor_local_key_t key);
+void rb_ractor_local_storage_ptr_set(rb_ractor_local_key_t key, void *ptr);
+
+VALUE rb_ractor_make_shareable(VALUE obj);
+VALUE rb_ractor_make_shareable_copy(VALUE obj);
+
+RUBY_SYMBOL_EXPORT_END
+
+#define RB_OBJ_SHAREABLE_P(obj) FL_TEST_RAW((obj), RUBY_FL_SHAREABLE)
+
+static inline bool
+rb_ractor_shareable_p(VALUE obj)
+{
+ bool rb_ractor_shareable_p_continue(VALUE obj);
+
+ if (SPECIAL_CONST_P(obj)) {
+ return true;
+ }
+ else if (RB_OBJ_SHAREABLE_P(obj)) {
+ return true;
+ }
+ else {
+ return rb_ractor_shareable_p_continue(obj);
+ }
+}
+
+#endif /* RUBY_RACTOR_H */
diff --git a/include/ruby/random.h b/include/ruby/random.h
new file mode 100644
index 0000000000..56b2dd413f
--- /dev/null
+++ b/include/ruby/random.h
@@ -0,0 +1,92 @@
+#ifndef RUBY_RANDOM_H
+#define RUBY_RANDOM_H 1
+/**
+ * @file
+ * @date Sat May 7 11:51:14 JST 2016
+ * @copyright 2007-2020 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+
+#include "ruby/ruby.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+struct rb_random_struct {
+ VALUE seed;
+};
+typedef struct rb_random_struct rb_random_t;
+
+typedef void rb_random_init_func(rb_random_t *, const uint32_t *, size_t);
+typedef unsigned int rb_random_get_int32_func(rb_random_t *);
+typedef void rb_random_get_bytes_func(rb_random_t *, void *, size_t);
+typedef double rb_random_get_real_func(rb_random_t *, int);
+
+typedef struct {
+ size_t default_seed_bits;
+ rb_random_init_func *init;
+ rb_random_get_int32_func *get_int32;
+ rb_random_get_bytes_func *get_bytes;
+ rb_random_get_real_func *get_real;
+} rb_random_interface_t;
+
+#define RB_RANDOM_INTERFACE_DECLARE(prefix) \
+ static void prefix##_init(rb_random_t *, const uint32_t *, size_t); \
+ static unsigned int prefix##_get_int32(rb_random_t *); \
+ static void prefix##_get_bytes(rb_random_t *, void *, size_t)
+
+#define RB_RANDOM_INTERFACE_DECLARE_WITH_REAL(prefix) \
+ RB_RANDOM_INTERFACE_DECLARE(prefix); \
+ static double prefix##_get_real(rb_random_t *, int)
+
+#define RB_RANDOM_INTERFACE_DEFINE(prefix) \
+ prefix##_init, \
+ prefix##_get_int32, \
+ prefix##_get_bytes
+
+#define RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(prefix) \
+ RB_RANDOM_INTERFACE_DEFINE(prefix), \
+ prefix##_get_real
+
+#if defined _WIN32 && !defined __CYGWIN__
+typedef rb_data_type_t rb_random_data_type_t;
+# define RB_RANDOM_PARENT 0
+#else
+typedef const rb_data_type_t rb_random_data_type_t;
+# define RB_RANDOM_PARENT &rb_random_data_type
+#endif
+
+#define RB_RANDOM_DATA_INIT_PARENT(random_data) \
+ rbimpl_random_data_init_parent(&random_data)
+
+void rb_random_mark(void *ptr);
+void rb_random_base_init(rb_random_t *rnd);
+double rb_int_pair_to_real(uint32_t a, uint32_t b, int excl);
+void rb_rand_bytes_int32(rb_random_get_int32_func *, rb_random_t *, void *, size_t);
+RUBY_EXTERN const rb_data_type_t rb_random_data_type;
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+static inline const rb_random_interface_t *
+rb_rand_if(VALUE obj)
+{
+ RBIMPL_ASSERT_OR_ASSUME(RTYPEDDATA_P(obj));
+ const struct rb_data_type_struct *t = RTYPEDDATA_TYPE(obj);
+ const void *ret = t->data;
+ return RBIMPL_CAST((const rb_random_interface_t *)ret);
+}
+
+RBIMPL_ATTR_NOALIAS()
+static inline void
+rbimpl_random_data_init_parent(rb_random_data_type_t *random_data)
+{
+#if defined _WIN32 && !defined __CYGWIN__
+ random_data->parent = &rb_random_data_type;
+#endif
+}
+
+#endif /* RUBY_RANDOM_H */
diff --git a/include/ruby/re.h b/include/ruby/re.h
index 7102c7ace4..ec0f425db0 100644
--- a/include/ruby/re.h
+++ b/include/ruby/re.h
@@ -1,54 +1,24 @@
-/**********************************************************************
-
- re.h -
-
- $Author$
- created at: Thu Sep 30 14:18:32 JST 1993
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_RE_H
+#ifndef RUBY_RE_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_RE_H 1
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
+/**
+ * @file
+ * @author $Author$
+ * @date Thu Sep 30 14:18:32 JST 1993
+ * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#include "ruby/internal/config.h"
#include <sys/types.h>
#include <stdio.h>
#include "ruby/regex.h"
+#include "ruby/internal/core/rmatch.h"
+#include "ruby/internal/dllexport.h"
-RUBY_SYMBOL_EXPORT_BEGIN
-
-typedef struct re_pattern_buffer Regexp;
-
-struct rmatch_offset {
- long beg;
- long end;
-};
-
-struct rmatch {
- struct re_registers regs;
-
- struct rmatch_offset *char_offset;
- int char_offset_num_allocated;
-};
-
-struct RMatch {
- struct RBasic basic;
- VALUE str;
- struct rmatch *rmatch;
- VALUE regexp; /* RRegexp */
-};
-
-#define RMATCH(obj) (R_CAST(RMatch)(obj))
-#define RMATCH_REGS(obj) (&(R_CAST(RMatch)(obj))->rmatch->regs)
+RBIMPL_SYMBOL_EXPORT_BEGIN()
VALUE rb_reg_regcomp(VALUE);
long rb_reg_search(VALUE, VALUE, long, int);
@@ -59,13 +29,6 @@ VALUE rb_reg_quote(VALUE);
regex_t *rb_reg_prepare_re(VALUE re, VALUE str);
int rb_reg_region_copy(struct re_registers *, const struct re_registers *);
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_RE_H */
diff --git a/include/ruby/regex.h b/include/ruby/regex.h
index 024bed4a4e..22dae3231d 100644
--- a/include/ruby/regex.h
+++ b/include/ruby/regex.h
@@ -1,16 +1,14 @@
-/**********************************************************************
-
- regex.h -
-
- $Author$
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef ONIGURUMA_REGEX_H
+#ifndef ONIGURUMA_REGEX_H /*-*-C++-*-vi:se ft=cpp:*/
#define ONIGURUMA_REGEX_H 1
-
+/**
+ * @file
+ * @author $Author$
+ * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
#if defined(__cplusplus)
extern "C" {
#if 0
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index bd95d5b0b1..c68168d500 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1,69 +1,18 @@
-/**********************************************************************
-
- ruby/ruby.h -
-
- $Author$
- created at: Thu Jun 10 14:26:32 JST 1993
-
- Copyright (C) 1993-2008 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
-#ifndef RUBY_RUBY_H
+#ifndef RUBY_RUBY_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_RUBY_H 1
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-#include "ruby/config.h"
-#ifdef RUBY_EXTCONF_H
-#include RUBY_EXTCONF_H
-#endif
-
-#include "defines.h"
-#include "ruby/assert.h"
-
-/* For MinGW, we need __declspec(dllimport) for RUBY_EXTERN on MJIT.
- mswin's RUBY_EXTERN already has that. See also: win32/Makefile.sub */
-#if defined(MJIT_HEADER) && defined(_WIN32) && defined(__GNUC__)
-# undef RUBY_EXTERN
-# define RUBY_EXTERN extern __declspec(dllimport)
-#endif
-
-#if defined(__cplusplus)
-/* __builtin_choose_expr and __builtin_types_compatible aren't available
- * on C++. See https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */
-# undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P
-# undef HAVE_BUILTIN___BUILTIN_TYPES_COMPATIBLE_P
-#elif GCC_VERSION_BEFORE(4,8,6) /* Bug #14221 */
-# undef HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P
-#endif
-
-#ifndef ASSUME
-# ifdef UNREACHABLE
-# define ASSUME(x) (RB_LIKELY(!!(x)) ? (void)0 : UNREACHABLE)
-# else
-# define ASSUME(x) ((void)(x))
-# endif
-#endif
-#ifndef UNREACHABLE_RETURN
-# ifdef UNREACHABLE
-# define UNREACHABLE_RETURN(val) UNREACHABLE
-# else
-# define UNREACHABLE_RETURN(val) return (val)
-# endif
-#endif
-#ifndef UNREACHABLE
-# define UNREACHABLE ((void)0) /* unreachable */
-#endif
-
-#define RUBY_MACRO_SELECT(base, n) TOKEN_PASTE(base, n)
+/**
+ * @file
+ * @author $Author$
+ * @date Thu Jun 10 14:26:32 JST 1993
+ * @copyright Copyright (C) 1993-2008 Yukihiro Matsumoto
+ * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#include "ruby/internal/config.h"
#ifdef HAVE_INTRINSICS_H
# include <intrinsics.h>
@@ -71,1788 +20,50 @@ extern "C" {
#include <stdarg.h>
-RUBY_SYMBOL_EXPORT_BEGIN
-
-/* Make alloca work the best possible way. */
-#ifdef __GNUC__
-# ifndef alloca
-# define alloca __builtin_alloca
-# endif
-#else
-# ifdef HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
-#pragma alloca
-# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
-void *alloca();
-# endif
-# endif /* AIX */
-# endif /* HAVE_ALLOCA_H */
-#endif /* __GNUC__ */
-
-#if defined HAVE_UINTPTR_T && 0
-typedef uintptr_t VALUE;
-typedef uintptr_t ID;
-# define SIGNED_VALUE intptr_t
-# define SIZEOF_VALUE SIZEOF_UINTPTR_T
-# undef PRI_VALUE_PREFIX
-#elif SIZEOF_LONG == SIZEOF_VOIDP
-typedef unsigned long VALUE;
-typedef unsigned long ID;
-# define SIGNED_VALUE long
-# define SIZEOF_VALUE SIZEOF_LONG
-# define PRI_VALUE_PREFIX "l"
-#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
-typedef unsigned LONG_LONG VALUE;
-typedef unsigned LONG_LONG ID;
-# define SIGNED_VALUE LONG_LONG
-# define LONG_LONG_VALUE 1
-# define SIZEOF_VALUE SIZEOF_LONG_LONG
-# define PRI_VALUE_PREFIX PRI_LL_PREFIX
-#else
-# error ---->> ruby requires sizeof(void*) == sizeof(long) or sizeof(LONG_LONG) to be compiled. <<----
-#endif
-
-typedef char ruby_check_sizeof_int[SIZEOF_INT == sizeof(int) ? 1 : -1];
-typedef char ruby_check_sizeof_long[SIZEOF_LONG == sizeof(long) ? 1 : -1];
-#ifdef HAVE_LONG_LONG
-typedef char ruby_check_sizeof_long_long[SIZEOF_LONG_LONG == sizeof(LONG_LONG) ? 1 : -1];
-#endif
-typedef char ruby_check_sizeof_voidp[SIZEOF_VOIDP == sizeof(void*) ? 1 : -1];
-
-#ifndef PRI_INT_PREFIX
-#define PRI_INT_PREFIX ""
-#endif
-#ifndef PRI_LONG_PREFIX
-#define PRI_LONG_PREFIX "l"
-#endif
-#ifndef PRI_SHORT_PREFIX
-#define PRI_SHORT_PREFIX "h"
-#endif
-
-#ifndef PRI_64_PREFIX
-#if SIZEOF_LONG == 8
-#define PRI_64_PREFIX PRI_LONG_PREFIX
-#elif SIZEOF_LONG_LONG == 8
-#define PRI_64_PREFIX PRI_LL_PREFIX
-#endif
-#endif
-
-#ifndef PRIdPTR
-#define PRIdPTR PRI_PTR_PREFIX"d"
-#define PRIiPTR PRI_PTR_PREFIX"i"
-#define PRIoPTR PRI_PTR_PREFIX"o"
-#define PRIuPTR PRI_PTR_PREFIX"u"
-#define PRIxPTR PRI_PTR_PREFIX"x"
-#define PRIXPTR PRI_PTR_PREFIX"X"
-#endif
-
-#define RUBY_PRI_VALUE_MARK "\v"
-#if defined PRIdPTR && !defined PRI_VALUE_PREFIX
-#define PRIdVALUE PRIdPTR
-#define PRIoVALUE PRIoPTR
-#define PRIuVALUE PRIuPTR
-#define PRIxVALUE PRIxPTR
-#define PRIXVALUE PRIXPTR
-#define PRIsVALUE PRIiPTR"" RUBY_PRI_VALUE_MARK
-#else
-#define PRIdVALUE PRI_VALUE_PREFIX"d"
-#define PRIoVALUE PRI_VALUE_PREFIX"o"
-#define PRIuVALUE PRI_VALUE_PREFIX"u"
-#define PRIxVALUE PRI_VALUE_PREFIX"x"
-#define PRIXVALUE PRI_VALUE_PREFIX"X"
-#define PRIsVALUE PRI_VALUE_PREFIX"i" RUBY_PRI_VALUE_MARK
-#endif
-#ifndef PRI_VALUE_PREFIX
-# define PRI_VALUE_PREFIX ""
-#endif
-
-#ifndef PRI_TIMET_PREFIX
-# if SIZEOF_TIME_T == SIZEOF_INT
-# define PRI_TIMET_PREFIX
-# elif SIZEOF_TIME_T == SIZEOF_LONG
-# define PRI_TIMET_PREFIX "l"
-# elif SIZEOF_TIME_T == SIZEOF_LONG_LONG
-# define PRI_TIMET_PREFIX PRI_LL_PREFIX
-# endif
-#endif
-
-#if defined PRI_PTRDIFF_PREFIX
-#elif SIZEOF_PTRDIFF_T == SIZEOF_INT
-# define PRI_PTRDIFF_PREFIX ""
-#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
-# define PRI_PTRDIFF_PREFIX "l"
-#elif SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
-# define PRI_PTRDIFF_PREFIX PRI_LL_PREFIX
-#endif
-#define PRIdPTRDIFF PRI_PTRDIFF_PREFIX"d"
-#define PRIiPTRDIFF PRI_PTRDIFF_PREFIX"i"
-#define PRIoPTRDIFF PRI_PTRDIFF_PREFIX"o"
-#define PRIuPTRDIFF PRI_PTRDIFF_PREFIX"u"
-#define PRIxPTRDIFF PRI_PTRDIFF_PREFIX"x"
-#define PRIXPTRDIFF PRI_PTRDIFF_PREFIX"X"
-
-#if defined PRI_SIZE_PREFIX
-#elif SIZEOF_SIZE_T == SIZEOF_INT
-# define PRI_SIZE_PREFIX ""
-#elif SIZEOF_SIZE_T == SIZEOF_LONG
-# define PRI_SIZE_PREFIX "l"
-#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG
-# define PRI_SIZE_PREFIX PRI_LL_PREFIX
-#endif
-#define PRIdSIZE PRI_SIZE_PREFIX"d"
-#define PRIiSIZE PRI_SIZE_PREFIX"i"
-#define PRIoSIZE PRI_SIZE_PREFIX"o"
-#define PRIuSIZE PRI_SIZE_PREFIX"u"
-#define PRIxSIZE PRI_SIZE_PREFIX"x"
-#define PRIXSIZE PRI_SIZE_PREFIX"X"
-
-#ifdef __STDC__
-# include <limits.h>
-#else
-# ifndef LONG_MAX
-# ifdef HAVE_LIMITS_H
-# include <limits.h>
-# else
- /* assuming 32bit(2's complement) long */
-# define LONG_MAX 2147483647
-# endif
-# endif
-# ifndef LONG_MIN
-# define LONG_MIN (-LONG_MAX-1)
-# endif
-# ifndef CHAR_BIT
-# define CHAR_BIT 8
-# endif
-#endif
-
-#ifdef HAVE_LONG_LONG
-# ifndef LLONG_MAX
-# ifdef LONG_LONG_MAX
-# define LLONG_MAX LONG_LONG_MAX
-# else
-# ifdef _I64_MAX
-# define LLONG_MAX _I64_MAX
-# else
- /* assuming 64bit(2's complement) long long */
-# define LLONG_MAX 9223372036854775807LL
-# endif
-# endif
-# endif
-# ifndef LLONG_MIN
-# ifdef LONG_LONG_MIN
-# define LLONG_MIN LONG_LONG_MIN
-# else
-# ifdef _I64_MIN
-# define LLONG_MIN _I64_MIN
-# else
-# define LLONG_MIN (-LLONG_MAX-1)
-# endif
-# endif
-# endif
-#endif
-
-#define RUBY_FIXNUM_MAX (LONG_MAX>>1)
-#define RUBY_FIXNUM_MIN RSHIFT((long)LONG_MIN,1)
-#define FIXNUM_MAX RUBY_FIXNUM_MAX
-#define FIXNUM_MIN RUBY_FIXNUM_MIN
-
-#define RB_INT2FIX(i) (((VALUE)(i))<<1 | RUBY_FIXNUM_FLAG)
-#define INT2FIX(i) RB_INT2FIX(i)
-#define RB_LONG2FIX(i) RB_INT2FIX(i)
-#define LONG2FIX(i) RB_INT2FIX(i)
-#define rb_fix_new(v) RB_INT2FIX(v)
-VALUE rb_int2inum(intptr_t);
-
-#define rb_int_new(v) rb_int2inum(v)
-VALUE rb_uint2inum(uintptr_t);
-
-#define rb_uint_new(v) rb_uint2inum(v)
-
-#ifdef HAVE_LONG_LONG
-VALUE rb_ll2inum(LONG_LONG);
-#define LL2NUM(v) rb_ll2inum(v)
-VALUE rb_ull2inum(unsigned LONG_LONG);
-#define ULL2NUM(v) rb_ull2inum(v)
-#endif
-
-#ifndef OFFT2NUM
-#if SIZEOF_OFF_T > SIZEOF_LONG && defined(HAVE_LONG_LONG)
-# define OFFT2NUM(v) LL2NUM(v)
-#elif SIZEOF_OFF_T == SIZEOF_LONG
-# define OFFT2NUM(v) LONG2NUM(v)
-#else
-# define OFFT2NUM(v) INT2NUM(v)
-#endif
-#endif
-
-#if SIZEOF_SIZE_T > SIZEOF_LONG && defined(HAVE_LONG_LONG)
-# define SIZET2NUM(v) ULL2NUM(v)
-# define SSIZET2NUM(v) LL2NUM(v)
-#elif SIZEOF_SIZE_T == SIZEOF_LONG
-# define SIZET2NUM(v) ULONG2NUM(v)
-# define SSIZET2NUM(v) LONG2NUM(v)
-#else
-# define SIZET2NUM(v) UINT2NUM(v)
-# define SSIZET2NUM(v) INT2NUM(v)
-#endif
-
-#ifndef SIZE_MAX
-# if SIZEOF_SIZE_T > SIZEOF_LONG && defined(HAVE_LONG_LONG)
-# define SIZE_MAX ULLONG_MAX
-# define SIZE_MIN ULLONG_MIN
-# elif SIZEOF_SIZE_T == SIZEOF_LONG
-# define SIZE_MAX ULONG_MAX
-# define SIZE_MIN ULONG_MIN
-# elif SIZEOF_SIZE_T == SIZEOF_INT
-# define SIZE_MAX UINT_MAX
-# define SIZE_MIN UINT_MIN
-# else
-# define SIZE_MAX USHRT_MAX
-# define SIZE_MIN USHRT_MIN
-# endif
-#endif
-
-#ifndef SSIZE_MAX
-# if SIZEOF_SIZE_T > SIZEOF_LONG && defined(HAVE_LONG_LONG)
-# define SSIZE_MAX LLONG_MAX
-# define SSIZE_MIN LLONG_MIN
-# elif SIZEOF_SIZE_T == SIZEOF_LONG
-# define SSIZE_MAX LONG_MAX
-# define SSIZE_MIN LONG_MIN
-# elif SIZEOF_SIZE_T == SIZEOF_INT
-# define SSIZE_MAX INT_MAX
-# define SSIZE_MIN INT_MIN
-# else
-# define SSIZE_MAX SHRT_MAX
-# define SSIZE_MIN SHRT_MIN
-# endif
-#endif
-
-#if SIZEOF_INT < SIZEOF_VALUE
-NORETURN(void rb_out_of_int(SIGNED_VALUE num));
-#endif
-
-#if SIZEOF_INT < SIZEOF_LONG
-static inline int
-rb_long2int_inline(long n)
-{
- int i = (int)n;
- if ((long)i != n)
- rb_out_of_int(n);
-
- return i;
-}
-#define rb_long2int(n) rb_long2int_inline(n)
-#else
-#define rb_long2int(n) ((int)(n))
-#endif
-
-#ifndef PIDT2NUM
-#define PIDT2NUM(v) LONG2NUM(v)
-#endif
-#ifndef NUM2PIDT
-#define NUM2PIDT(v) NUM2LONG(v)
-#endif
-#ifndef UIDT2NUM
-#define UIDT2NUM(v) LONG2NUM(v)
-#endif
-#ifndef NUM2UIDT
-#define NUM2UIDT(v) NUM2LONG(v)
-#endif
-#ifndef GIDT2NUM
-#define GIDT2NUM(v) LONG2NUM(v)
-#endif
-#ifndef NUM2GIDT
-#define NUM2GIDT(v) NUM2LONG(v)
-#endif
-#ifndef NUM2MODET
-#define NUM2MODET(v) NUM2INT(v)
-#endif
-#ifndef MODET2NUM
-#define MODET2NUM(v) INT2NUM(v)
-#endif
-
-#define RB_FIX2LONG(x) ((long)RSHIFT((SIGNED_VALUE)(x),1))
-static inline long
-rb_fix2long(VALUE x)
-{
- return RB_FIX2LONG(x);
-}
-#define RB_FIX2ULONG(x) ((unsigned long)RB_FIX2LONG(x))
-static inline unsigned long
-rb_fix2ulong(VALUE x)
-{
- return RB_FIX2ULONG(x);
-}
-#define RB_FIXNUM_P(f) (((int)(SIGNED_VALUE)(f))&RUBY_FIXNUM_FLAG)
-#define RB_POSFIXABLE(f) ((f) < RUBY_FIXNUM_MAX+1)
-#define RB_NEGFIXABLE(f) ((f) >= RUBY_FIXNUM_MIN)
-#define RB_FIXABLE(f) (RB_POSFIXABLE(f) && RB_NEGFIXABLE(f))
-#define FIX2LONG(x) RB_FIX2LONG(x)
-#define FIX2ULONG(x) RB_FIX2ULONG(x)
-#define FIXNUM_P(f) RB_FIXNUM_P(f)
-#define POSFIXABLE(f) RB_POSFIXABLE(f)
-#define NEGFIXABLE(f) RB_NEGFIXABLE(f)
-#define FIXABLE(f) RB_FIXABLE(f)
-
-#define RB_IMMEDIATE_P(x) ((VALUE)(x) & RUBY_IMMEDIATE_MASK)
-#define IMMEDIATE_P(x) RB_IMMEDIATE_P(x)
-
-ID rb_sym2id(VALUE);
-VALUE rb_id2sym(ID);
-#define RB_STATIC_SYM_P(x) (((VALUE)(x)&~((~(VALUE)0)<<RUBY_SPECIAL_SHIFT)) == RUBY_SYMBOL_FLAG)
-#define RB_DYNAMIC_SYM_P(x) (!RB_SPECIAL_CONST_P(x) && RB_BUILTIN_TYPE(x) == (RUBY_T_SYMBOL))
-#define RB_SYMBOL_P(x) (RB_STATIC_SYM_P(x)||RB_DYNAMIC_SYM_P(x))
-#define RB_ID2SYM(x) (rb_id2sym(x))
-#define RB_SYM2ID(x) (rb_sym2id(x))
-#define STATIC_SYM_P(x) RB_STATIC_SYM_P(x)
-#define DYNAMIC_SYM_P(x) RB_DYNAMIC_SYM_P(x)
-#define SYMBOL_P(x) RB_SYMBOL_P(x)
-#define ID2SYM(x) RB_ID2SYM(x)
-#define SYM2ID(x) RB_SYM2ID(x)
-
-#ifndef USE_FLONUM
-#if SIZEOF_VALUE >= SIZEOF_DOUBLE
-#define USE_FLONUM 1
-#else
-#define USE_FLONUM 0
-#endif
-#endif
+#include "defines.h"
+#include "ruby/internal/anyargs.h"
+#include "ruby/internal/arithmetic.h"
+#include "ruby/internal/core.h"
+#include "ruby/internal/ctype.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/error.h"
+#include "ruby/internal/eval.h"
+#include "ruby/internal/event.h"
+#include "ruby/internal/fl_type.h"
+#include "ruby/internal/gc.h"
+#include "ruby/internal/glob.h"
+#include "ruby/internal/globals.h"
+#include "ruby/internal/has/warning.h"
+#include "ruby/internal/interpreter.h"
+#include "ruby/internal/iterator.h"
+#include "ruby/internal/memory.h"
+#include "ruby/internal/method.h"
+#include "ruby/internal/module.h"
+#include "ruby/internal/newobj.h"
+#include "ruby/internal/rgengc.h"
+#include "ruby/internal/scan_args.h"
+#include "ruby/internal/special_consts.h"
+#include "ruby/internal/symbol.h"
+#include "ruby/internal/value.h"
+#include "ruby/internal/value_type.h"
+#include "ruby/internal/variable.h"
+#include "ruby/assert.h"
+#include "ruby/backward/2/assume.h"
+#include "ruby/backward/2/inttypes.h"
+#include "ruby/backward/2/limits.h"
-#if USE_FLONUM
-#define RB_FLONUM_P(x) ((((int)(SIGNED_VALUE)(x))&RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG)
-#else
-#define RB_FLONUM_P(x) 0
-#endif
-#define FLONUM_P(x) RB_FLONUM_P(x)
+RBIMPL_SYMBOL_EXPORT_BEGIN()
/* Module#methods, #singleton_methods and so on return Symbols */
#define USE_SYMBOL_AS_METHOD_NAME 1
-/* special constants - i.e. non-zero and non-fixnum constants */
-enum ruby_special_consts {
-#if USE_FLONUM
- RUBY_Qfalse = 0x00, /* ...0000 0000 */
- RUBY_Qtrue = 0x14, /* ...0001 0100 */
- RUBY_Qnil = 0x08, /* ...0000 1000 */
- RUBY_Qundef = 0x34, /* ...0011 0100 */
-
- RUBY_IMMEDIATE_MASK = 0x07,
- RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */
- RUBY_FLONUM_MASK = 0x03,
- RUBY_FLONUM_FLAG = 0x02, /* ...xxxx xx10 */
- RUBY_SYMBOL_FLAG = 0x0c, /* ...0000 1100 */
-#else
- RUBY_Qfalse = 0, /* ...0000 0000 */
- RUBY_Qtrue = 2, /* ...0000 0010 */
- RUBY_Qnil = 4, /* ...0000 0100 */
- RUBY_Qundef = 6, /* ...0000 0110 */
-
- RUBY_IMMEDIATE_MASK = 0x03,
- RUBY_FIXNUM_FLAG = 0x01, /* ...xxxx xxx1 */
- RUBY_FLONUM_MASK = 0x00, /* any values ANDed with FLONUM_MASK cannot be FLONUM_FLAG */
- RUBY_FLONUM_FLAG = 0x02,
- RUBY_SYMBOL_FLAG = 0x0e, /* ...0000 1110 */
-#endif
- RUBY_SPECIAL_SHIFT = 8
-};
-
-#define RUBY_Qfalse ((VALUE)RUBY_Qfalse)
-#define RUBY_Qtrue ((VALUE)RUBY_Qtrue)
-#define RUBY_Qnil ((VALUE)RUBY_Qnil)
-#define RUBY_Qundef ((VALUE)RUBY_Qundef) /* undefined value for placeholder */
-#define Qfalse RUBY_Qfalse
-#define Qtrue RUBY_Qtrue
-#define Qnil RUBY_Qnil
-#define Qundef RUBY_Qundef
-#define IMMEDIATE_MASK RUBY_IMMEDIATE_MASK
-#define FIXNUM_FLAG RUBY_FIXNUM_FLAG
-#if USE_FLONUM
-#define FLONUM_MASK RUBY_FLONUM_MASK
-#define FLONUM_FLAG RUBY_FLONUM_FLAG
-#endif
-#define SYMBOL_FLAG RUBY_SYMBOL_FLAG
-
-#define RB_TEST(v) !(((VALUE)(v) & (VALUE)~RUBY_Qnil) == 0)
-#define RB_NIL_P(v) !((VALUE)(v) != RUBY_Qnil)
-#define RTEST(v) RB_TEST(v)
-#define NIL_P(v) RB_NIL_P(v)
-
-#define CLASS_OF(v) rb_class_of((VALUE)(v))
-
-enum ruby_value_type {
- RUBY_T_NONE = 0x00,
-
- RUBY_T_OBJECT = 0x01,
- RUBY_T_CLASS = 0x02,
- RUBY_T_MODULE = 0x03,
- RUBY_T_FLOAT = 0x04,
- RUBY_T_STRING = 0x05,
- RUBY_T_REGEXP = 0x06,
- RUBY_T_ARRAY = 0x07,
- RUBY_T_HASH = 0x08,
- RUBY_T_STRUCT = 0x09,
- RUBY_T_BIGNUM = 0x0a,
- RUBY_T_FILE = 0x0b,
- RUBY_T_DATA = 0x0c,
- RUBY_T_MATCH = 0x0d,
- RUBY_T_COMPLEX = 0x0e,
- RUBY_T_RATIONAL = 0x0f,
-
- RUBY_T_NIL = 0x11,
- RUBY_T_TRUE = 0x12,
- RUBY_T_FALSE = 0x13,
- RUBY_T_SYMBOL = 0x14,
- RUBY_T_FIXNUM = 0x15,
- RUBY_T_UNDEF = 0x16,
-
- RUBY_T_IMEMO = 0x1a, /*!< @see imemo_type */
- RUBY_T_NODE = 0x1b,
- RUBY_T_ICLASS = 0x1c,
- RUBY_T_ZOMBIE = 0x1d,
- RUBY_T_MOVED = 0x1e,
-
- RUBY_T_MASK = 0x1f
-};
-
-#define T_NONE RUBY_T_NONE
-#define T_NIL RUBY_T_NIL
-#define T_OBJECT RUBY_T_OBJECT
-#define T_CLASS RUBY_T_CLASS
-#define T_ICLASS RUBY_T_ICLASS
-#define T_MODULE RUBY_T_MODULE
-#define T_FLOAT RUBY_T_FLOAT
-#define T_STRING RUBY_T_STRING
-#define T_REGEXP RUBY_T_REGEXP
-#define T_ARRAY RUBY_T_ARRAY
-#define T_HASH RUBY_T_HASH
-#define T_STRUCT RUBY_T_STRUCT
-#define T_BIGNUM RUBY_T_BIGNUM
-#define T_FILE RUBY_T_FILE
-#define T_FIXNUM RUBY_T_FIXNUM
-#define T_TRUE RUBY_T_TRUE
-#define T_FALSE RUBY_T_FALSE
-#define T_DATA RUBY_T_DATA
-#define T_MATCH RUBY_T_MATCH
-#define T_SYMBOL RUBY_T_SYMBOL
-#define T_RATIONAL RUBY_T_RATIONAL
-#define T_COMPLEX RUBY_T_COMPLEX
-#define T_IMEMO RUBY_T_IMEMO
-#define T_UNDEF RUBY_T_UNDEF
-#define T_NODE RUBY_T_NODE
-#define T_ZOMBIE RUBY_T_ZOMBIE
-#define T_MOVED RUBY_T_MOVED
-#define T_MASK RUBY_T_MASK
-
-#define RB_BUILTIN_TYPE(x) (int)(((struct RBasic*)(x))->flags & RUBY_T_MASK)
-#define BUILTIN_TYPE(x) RB_BUILTIN_TYPE(x)
-
-static inline int rb_type(VALUE obj);
-#define TYPE(x) rb_type((VALUE)(x))
-
-#define RB_FLOAT_TYPE_P(obj) (\
- RB_FLONUM_P(obj) || \
- (!RB_SPECIAL_CONST_P(obj) && RB_BUILTIN_TYPE(obj) == RUBY_T_FLOAT))
-
-#define RB_TYPE_P(obj, type) ( \
- ((type) == RUBY_T_FIXNUM) ? RB_FIXNUM_P(obj) : \
- ((type) == RUBY_T_TRUE) ? ((obj) == RUBY_Qtrue) : \
- ((type) == RUBY_T_FALSE) ? ((obj) == RUBY_Qfalse) : \
- ((type) == RUBY_T_NIL) ? ((obj) == RUBY_Qnil) : \
- ((type) == RUBY_T_UNDEF) ? ((obj) == RUBY_Qundef) : \
- ((type) == RUBY_T_SYMBOL) ? RB_SYMBOL_P(obj) : \
- ((type) == RUBY_T_FLOAT) ? RB_FLOAT_TYPE_P(obj) : \
- (!RB_SPECIAL_CONST_P(obj) && RB_BUILTIN_TYPE(obj) == (type)))
-
-#ifdef __GNUC__
-#define RB_GC_GUARD(v) \
- (*__extension__ ({ \
- volatile VALUE *rb_gc_guarded_ptr = &(v); \
- __asm__("" : : "m"(rb_gc_guarded_ptr)); \
- rb_gc_guarded_ptr; \
- }))
-#elif defined _MSC_VER
-#pragma optimize("", off)
-static inline volatile VALUE *rb_gc_guarded_ptr(volatile VALUE *ptr) {return ptr;}
-#pragma optimize("", on)
-#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr(&(v)))
-#else
-volatile VALUE *rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val);
-#define HAVE_RB_GC_GUARDED_PTR_VAL 1
-#define RB_GC_GUARD(v) (*rb_gc_guarded_ptr_val(&(v),(v)))
-#endif
-
-#ifdef __GNUC__
-#define RB_UNUSED_VAR(x) x __attribute__ ((unused))
-#else
-#define RB_UNUSED_VAR(x) x
-#endif
-
-void rb_check_type(VALUE,int);
-#define Check_Type(v,t) rb_check_type((VALUE)(v),(t))
-
-VALUE rb_str_to_str(VALUE);
-VALUE rb_string_value(volatile VALUE*);
-char *rb_string_value_ptr(volatile VALUE*);
-char *rb_string_value_cstr(volatile VALUE*);
-
-#define StringValue(v) rb_string_value(&(v))
-#define StringValuePtr(v) rb_string_value_ptr(&(v))
-#define StringValueCStr(v) rb_string_value_cstr(&(v))
-
-void rb_check_safe_obj(VALUE);
-#define SafeStringValue(v) StringValue(v)
-#if GCC_VERSION_SINCE(4,4,0)
-void rb_check_safe_str(VALUE) __attribute__((error("rb_check_safe_str() and Check_SafeStr() are obsolete; use StringValue() instead")));
-# define Check_SafeStr(v) rb_check_safe_str((VALUE)(v))
-#else
-# define rb_check_safe_str(x) [<"rb_check_safe_str() is obsolete; use StringValue() instead">]
-# define Check_SafeStr(v) [<"Check_SafeStr() is obsolete; use StringValue() instead">]
-#endif
-
-VALUE rb_str_export(VALUE);
-#define ExportStringValue(v) do {\
- StringValue(v);\
- (v) = rb_str_export(v);\
-} while (0)
-VALUE rb_str_export_locale(VALUE);
-
VALUE rb_get_path(VALUE);
#define FilePathValue(v) (RB_GC_GUARD(v) = rb_get_path(v))
VALUE rb_get_path_no_checksafe(VALUE);
#define FilePathStringValue(v) ((v) = rb_get_path(v))
-/* Remove in 3.0 */
-#define RUBY_SAFE_LEVEL_MAX 1
-void rb_secure(int);
-int rb_safe_level(void);
-void rb_set_safe_level(int);
-#if GCC_VERSION_SINCE(4,4,0)
-int ruby_safe_level_2_error(void) __attribute__((error("$SAFE=2 to 4 are obsolete")));
-int ruby_safe_level_2_warning(void) __attribute__((const,warning("$SAFE=2 to 4 are obsolete")));
-# ifdef RUBY_EXPORT
-# define ruby_safe_level_2_warning() ruby_safe_level_2_error()
-# endif
-# if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
-# define RUBY_SAFE_LEVEL_INVALID_P(level) \
- __extension__(\
- __builtin_choose_expr(\
- __builtin_constant_p(level), \
- ((level) < 0 || RUBY_SAFE_LEVEL_MAX < (level)), 0))
-# define RUBY_SAFE_LEVEL_CHECK(level, type) \
- __extension__(__builtin_choose_expr(RUBY_SAFE_LEVEL_INVALID_P(level), ruby_safe_level_2_##type(), (level)))
-# else
-/* in gcc 4.8 or earlier, __builtin_choose_expr() does not consider
- * __builtin_constant_p(variable) a constant expression.
- */
-# define RUBY_SAFE_LEVEL_INVALID_P(level) \
- __extension__(__builtin_constant_p(level) && \
- ((level) < 0 || RUBY_SAFE_LEVEL_MAX < (level)))
-# define RUBY_SAFE_LEVEL_CHECK(level, type) \
- (RUBY_SAFE_LEVEL_INVALID_P(level) ? ruby_safe_level_2_##type() : (level))
-# endif
-# define rb_secure(level) rb_secure(RUBY_SAFE_LEVEL_CHECK(level, warning))
-# define rb_set_safe_level(level) rb_set_safe_level(RUBY_SAFE_LEVEL_CHECK(level, error))
-#endif
-void rb_set_safe_level_force(int);
-void rb_secure_update(VALUE);
-NORETURN(void rb_insecure_operation(void));
-
-VALUE rb_errinfo(void);
-void rb_set_errinfo(VALUE);
-
-long rb_num2long(VALUE);
-unsigned long rb_num2ulong(VALUE);
-static inline long
-rb_num2long_inline(VALUE x)
-{
- if (RB_FIXNUM_P(x))
- return RB_FIX2LONG(x);
- else
- return rb_num2long(x);
-}
-#define RB_NUM2LONG(x) rb_num2long_inline(x)
-#define NUM2LONG(x) RB_NUM2LONG(x)
-static inline unsigned long
-rb_num2ulong_inline(VALUE x)
-{
- if (RB_FIXNUM_P(x))
- return RB_FIX2ULONG(x);
- else
- return rb_num2ulong(x);
-}
-#define RB_NUM2ULONG(x) rb_num2ulong_inline(x)
-#define NUM2ULONG(x) RB_NUM2ULONG(x)
-#if SIZEOF_INT < SIZEOF_LONG
-long rb_num2int(VALUE);
-long rb_fix2int(VALUE);
-#define RB_FIX2INT(x) ((int)rb_fix2int((VALUE)(x)))
-
-static inline int
-rb_num2int_inline(VALUE x)
-{
- if (RB_FIXNUM_P(x))
- return (int)rb_fix2int(x);
- else
- return (int)rb_num2int(x);
-}
-#define RB_NUM2INT(x) rb_num2int_inline(x)
-
-unsigned long rb_num2uint(VALUE);
-#define RB_NUM2UINT(x) ((unsigned int)rb_num2uint(x))
-unsigned long rb_fix2uint(VALUE);
-#define RB_FIX2UINT(x) ((unsigned int)rb_fix2uint(x))
-#else /* SIZEOF_INT < SIZEOF_LONG */
-#define RB_NUM2INT(x) ((int)RB_NUM2LONG(x))
-#define RB_NUM2UINT(x) ((unsigned int)RB_NUM2ULONG(x))
-#define RB_FIX2INT(x) ((int)RB_FIX2LONG(x))
-#define RB_FIX2UINT(x) ((unsigned int)RB_FIX2ULONG(x))
-#endif /* SIZEOF_INT < SIZEOF_LONG */
-#define NUM2INT(x) RB_NUM2INT(x)
-#define NUM2UINT(x) RB_NUM2UINT(x)
-#define FIX2INT(x) RB_FIX2INT(x)
-#define FIX2UINT(x) RB_FIX2UINT(x)
-
-short rb_num2short(VALUE);
-unsigned short rb_num2ushort(VALUE);
-short rb_fix2short(VALUE);
-unsigned short rb_fix2ushort(VALUE);
-#define RB_FIX2SHORT(x) (rb_fix2short((VALUE)(x)))
-#define FIX2SHORT(x) RB_FIX2SHORT(x)
-static inline short
-rb_num2short_inline(VALUE x)
-{
- if (RB_FIXNUM_P(x))
- return rb_fix2short(x);
- else
- return rb_num2short(x);
-}
-
-#define RB_NUM2SHORT(x) rb_num2short_inline(x)
-#define RB_NUM2USHORT(x) rb_num2ushort(x)
-#define NUM2SHORT(x) RB_NUM2SHORT(x)
-#define NUM2USHORT(x) RB_NUM2USHORT(x)
-
-#ifdef HAVE_LONG_LONG
-LONG_LONG rb_num2ll(VALUE);
-unsigned LONG_LONG rb_num2ull(VALUE);
-static inline LONG_LONG
-rb_num2ll_inline(VALUE x)
-{
- if (RB_FIXNUM_P(x))
- return RB_FIX2LONG(x);
- else
- return rb_num2ll(x);
-}
-# define RB_NUM2LL(x) rb_num2ll_inline(x)
-# define RB_NUM2ULL(x) rb_num2ull(x)
-# define NUM2LL(x) RB_NUM2LL(x)
-# define NUM2ULL(x) RB_NUM2ULL(x)
-#endif
-
-#if !defined(NUM2OFFT)
-# if defined(HAVE_LONG_LONG) && SIZEOF_OFF_T > SIZEOF_LONG
-# define NUM2OFFT(x) ((off_t)NUM2LL(x))
-# else
-# define NUM2OFFT(x) NUM2LONG(x)
-# endif
-#endif
-
-#if defined(HAVE_LONG_LONG) && SIZEOF_SIZE_T > SIZEOF_LONG
-# define NUM2SIZET(x) ((size_t)NUM2ULL(x))
-# define NUM2SSIZET(x) ((ssize_t)NUM2LL(x))
-#else
-# define NUM2SIZET(x) NUM2ULONG(x)
-# define NUM2SSIZET(x) NUM2LONG(x)
-#endif
-
-double rb_num2dbl(VALUE);
-#define NUM2DBL(x) rb_num2dbl((VALUE)(x))
-
-VALUE rb_uint2big(uintptr_t);
-VALUE rb_int2big(intptr_t);
-
-VALUE rb_newobj(void);
-VALUE rb_newobj_of(VALUE, VALUE);
-VALUE rb_obj_setup(VALUE obj, VALUE klass, VALUE type);
-#define RB_NEWOBJ(obj,type) type *(obj) = (type*)rb_newobj()
-#define RB_NEWOBJ_OF(obj,type,klass,flags) type *(obj) = (type*)rb_newobj_of(klass, flags)
-#define NEWOBJ(obj,type) RB_NEWOBJ(obj,type)
-#define NEWOBJ_OF(obj,type,klass,flags) RB_NEWOBJ_OF(obj,type,klass,flags) /* core has special NEWOBJ_OF() in internal.h */
-#define OBJSETUP(obj,c,t) rb_obj_setup(obj, c, t) /* use NEWOBJ_OF instead of NEWOBJ()+OBJSETUP() */
-#define CLONESETUP(clone,obj) rb_clone_setup(clone,obj)
-#define DUPSETUP(dup,obj) rb_dup_setup(dup,obj)
-
-#ifndef USE_RGENGC
-#define USE_RGENGC 1
-#ifndef USE_RINCGC
-#define USE_RINCGC 1
-#endif
-#endif
-
-#if USE_RGENGC == 0
-#define USE_RINCGC 0
-#endif
-
-#ifndef RGENGC_WB_PROTECTED_ARRAY
-#define RGENGC_WB_PROTECTED_ARRAY 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_HASH
-#define RGENGC_WB_PROTECTED_HASH 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_STRUCT
-#define RGENGC_WB_PROTECTED_STRUCT 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_STRING
-#define RGENGC_WB_PROTECTED_STRING 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_OBJECT
-#define RGENGC_WB_PROTECTED_OBJECT 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_REGEXP
-#define RGENGC_WB_PROTECTED_REGEXP 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_CLASS
-#define RGENGC_WB_PROTECTED_CLASS 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_FLOAT
-#define RGENGC_WB_PROTECTED_FLOAT 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_COMPLEX
-#define RGENGC_WB_PROTECTED_COMPLEX 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_RATIONAL
-#define RGENGC_WB_PROTECTED_RATIONAL 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_BIGNUM
-#define RGENGC_WB_PROTECTED_BIGNUM 1
-#endif
-#ifndef RGENGC_WB_PROTECTED_NODE_CREF
-#define RGENGC_WB_PROTECTED_NODE_CREF 1
-#endif
-
-#ifdef __GNUC__
-__extension__
-#endif
-enum ruby_fl_type {
- RUBY_FL_WB_PROTECTED = (1<<5),
- RUBY_FL_PROMOTED0 = (1<<5),
- RUBY_FL_PROMOTED1 = (1<<6),
- RUBY_FL_PROMOTED = RUBY_FL_PROMOTED0|RUBY_FL_PROMOTED1,
- RUBY_FL_FINALIZE = (1<<7),
- RUBY_FL_TAINT = (1<<8),
- RUBY_FL_UNTRUSTED = RUBY_FL_TAINT,
- RUBY_FL_SEEN_OBJ_ID = (1<<9),
- RUBY_FL_EXIVAR = (1<<10),
- RUBY_FL_FREEZE = (1<<11),
-
- RUBY_FL_USHIFT = 12,
-
-#define RUBY_FL_USER_N(n) RUBY_FL_USER##n = (1<<(RUBY_FL_USHIFT+n))
- RUBY_FL_USER_N(0),
- RUBY_FL_USER_N(1),
- RUBY_FL_USER_N(2),
- RUBY_FL_USER_N(3),
- RUBY_FL_USER_N(4),
- RUBY_FL_USER_N(5),
- RUBY_FL_USER_N(6),
- RUBY_FL_USER_N(7),
- RUBY_FL_USER_N(8),
- RUBY_FL_USER_N(9),
- RUBY_FL_USER_N(10),
- RUBY_FL_USER_N(11),
- RUBY_FL_USER_N(12),
- RUBY_FL_USER_N(13),
- RUBY_FL_USER_N(14),
- RUBY_FL_USER_N(15),
- RUBY_FL_USER_N(16),
- RUBY_FL_USER_N(17),
- RUBY_FL_USER_N(18),
-#if defined ENUM_OVER_INT || SIZEOF_INT*CHAR_BIT>12+19+1
- RUBY_FL_USER_N(19),
-#else
-#define RUBY_FL_USER19 (((VALUE)1)<<(RUBY_FL_USHIFT+19))
-#endif
-
- RUBY_ELTS_SHARED = RUBY_FL_USER2,
- RUBY_FL_DUPPED = (RUBY_T_MASK|RUBY_FL_EXIVAR|RUBY_FL_TAINT),
- RUBY_FL_SINGLETON = RUBY_FL_USER0
-};
-
-struct RUBY_ALIGNAS(SIZEOF_VALUE) RBasic {
- VALUE flags;
- const VALUE klass;
-};
-
-VALUE rb_obj_hide(VALUE obj);
-VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */
-
-#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
-# define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \
- __extension__( \
- __builtin_choose_expr( \
- RGENGC_WB_PROTECTED_##type, \
- OBJ_WB_UNPROTECT((VALUE)(obj)), ((VALUE)(obj))))
-#else
-# define RB_OBJ_WB_UNPROTECT_FOR(type, obj) \
- (RGENGC_WB_PROTECTED_##type ? \
- OBJ_WB_UNPROTECT((VALUE)(obj)) : ((VALUE)(obj)))
-#endif
-
-#define RBASIC_CLASS(obj) (RBASIC(obj)->klass)
-
-#define RVALUE_EMBED_LEN_MAX RVALUE_EMBED_LEN_MAX
-enum ruby_rvalue_flags {
- RVALUE_EMBED_LEN_MAX = 3,
-};
-
-#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX
-#define ROBJECT_EMBED ROBJECT_EMBED
-enum ruby_robject_flags {
- ROBJECT_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX,
- ROBJECT_EMBED = RUBY_FL_USER1,
-
- ROBJECT_ENUM_END
-};
-
-struct RObject {
- struct RBasic basic;
- union {
- struct {
- uint32_t numiv;
- VALUE *ivptr;
- void *iv_index_tbl; /* shortcut for RCLASS_IV_INDEX_TBL(rb_obj_class(obj)) */
- } heap;
- VALUE ary[ROBJECT_EMBED_LEN_MAX];
- } as;
-};
-#define ROBJECT_NUMIV(o) \
- ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
- ROBJECT_EMBED_LEN_MAX : \
- ROBJECT(o)->as.heap.numiv)
-#define ROBJECT_IVPTR(o) \
- ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
- ROBJECT(o)->as.ary : \
- ROBJECT(o)->as.heap.ivptr)
-#define ROBJECT_IV_INDEX_TBL(o) \
- ((RBASIC(o)->flags & ROBJECT_EMBED) ? \
- RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \
- ROBJECT(o)->as.heap.iv_index_tbl)
-
-#define RCLASS_SUPER(c) rb_class_get_superclass(c)
-#define RMODULE_IV_TBL(m) RCLASS_IV_TBL(m)
-#define RMODULE_CONST_TBL(m) RCLASS_CONST_TBL(m)
-#define RMODULE_M_TBL(m) RCLASS_M_TBL(m)
-#define RMODULE_SUPER(m) RCLASS_SUPER(m)
-#define RMODULE_IS_OVERLAID RMODULE_IS_OVERLAID
-#define RMODULE_IS_REFINEMENT RMODULE_IS_REFINEMENT
-#define RMODULE_INCLUDED_INTO_REFINEMENT RMODULE_INCLUDED_INTO_REFINEMENT
-enum ruby_rmodule_flags {
- RMODULE_IS_OVERLAID = RUBY_FL_USER2,
- RMODULE_IS_REFINEMENT = RUBY_FL_USER3,
- RMODULE_INCLUDED_INTO_REFINEMENT = RUBY_FL_USER4,
-
- RMODULE_ENUM_END
-};
-
-PUREFUNC(double rb_float_value(VALUE));
-VALUE rb_float_new(double);
-VALUE rb_float_new_in_heap(double);
-
-#define RFLOAT_VALUE(v) rb_float_value(v)
-#define DBL2NUM(dbl) rb_float_new(dbl)
-
-#define RUBY_ELTS_SHARED RUBY_ELTS_SHARED
-#define ELTS_SHARED RUBY_ELTS_SHARED
-
-#define RSTRING_NOEMBED RSTRING_NOEMBED
-#define RSTRING_EMBED_LEN_MASK RSTRING_EMBED_LEN_MASK
-#define RSTRING_EMBED_LEN_SHIFT RSTRING_EMBED_LEN_SHIFT
-#define RSTRING_EMBED_LEN_MAX RSTRING_EMBED_LEN_MAX
-#define RSTRING_FSTR RSTRING_FSTR
-enum ruby_rstring_flags {
- RSTRING_NOEMBED = RUBY_FL_USER1,
- RSTRING_EMBED_LEN_MASK = (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|
- RUBY_FL_USER5|RUBY_FL_USER6),
- RSTRING_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+2),
- RSTRING_EMBED_LEN_MAX = (int)((sizeof(VALUE)*RVALUE_EMBED_LEN_MAX)/sizeof(char)-1),
- RSTRING_FSTR = RUBY_FL_USER17,
-
- RSTRING_ENUM_END
-};
-
-struct RString {
- struct RBasic basic;
- union {
- struct {
- long len;
- char *ptr;
- union {
- long capa;
- VALUE shared;
- } aux;
- } heap;
- char ary[RSTRING_EMBED_LEN_MAX + 1];
- } as;
-};
-#define RSTRING_EMBED_LEN(str) \
- (long)((RBASIC(str)->flags >> RSTRING_EMBED_LEN_SHIFT) & \
- (RSTRING_EMBED_LEN_MASK >> RSTRING_EMBED_LEN_SHIFT))
-#define RSTRING_LEN(str) \
- (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \
- RSTRING_EMBED_LEN(str) : \
- RSTRING(str)->as.heap.len)
-#define RSTRING_PTR(str) \
- (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \
- RSTRING(str)->as.ary : \
- RSTRING(str)->as.heap.ptr)
-#define RSTRING_END(str) \
- (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \
- (RSTRING(str)->as.ary + RSTRING_EMBED_LEN(str)) : \
- (RSTRING(str)->as.heap.ptr + RSTRING(str)->as.heap.len))
-#define RSTRING_LENINT(str) rb_long2int(RSTRING_LEN(str))
-#define RSTRING_GETMEM(str, ptrvar, lenvar) \
- (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \
- ((ptrvar) = RSTRING(str)->as.ary, (lenvar) = RSTRING_EMBED_LEN(str)) : \
- ((ptrvar) = RSTRING(str)->as.heap.ptr, (lenvar) = RSTRING(str)->as.heap.len))
-
-#ifndef USE_TRANSIENT_HEAP
-#define USE_TRANSIENT_HEAP 1
-#endif
-
-enum ruby_rarray_flags {
- RARRAY_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX,
- RARRAY_EMBED_FLAG = RUBY_FL_USER1,
- /* RUBY_FL_USER2 is for ELTS_SHARED */
- RARRAY_EMBED_LEN_MASK = (RUBY_FL_USER4|RUBY_FL_USER3),
- RARRAY_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+3),
-
-#if USE_TRANSIENT_HEAP
- RARRAY_TRANSIENT_FLAG = RUBY_FL_USER13,
-#define RARRAY_TRANSIENT_FLAG RARRAY_TRANSIENT_FLAG
-#else
-#define RARRAY_TRANSIENT_FLAG 0
-#endif
-
- RARRAY_ENUM_END
-};
-#define RARRAY_EMBED_FLAG (VALUE)RARRAY_EMBED_FLAG
-#define RARRAY_EMBED_LEN_MASK (VALUE)RARRAY_EMBED_LEN_MASK
-#define RARRAY_EMBED_LEN_MAX RARRAY_EMBED_LEN_MAX
-#define RARRAY_EMBED_LEN_SHIFT RARRAY_EMBED_LEN_SHIFT
-
-struct RArray {
- struct RBasic basic;
- union {
- struct {
- long len;
- union {
- long capa;
-#if defined(__clang__) /* <- clang++ is sane */ || \
- !defined(__cplusplus) /* <- C99 is sane */ || \
- (__cplusplus > 199711L) /* <- C++11 is sane */
- const
-#endif
- VALUE shared_root;
- } aux;
- const VALUE *ptr;
- } heap;
- const VALUE ary[RARRAY_EMBED_LEN_MAX];
- } as;
-};
-#define RARRAY_EMBED_LEN(a) \
- (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
- (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT))
-#define RARRAY_LEN(a) rb_array_len(a)
-#define RARRAY_LENINT(ary) rb_long2int(RARRAY_LEN(ary))
-#define RARRAY_CONST_PTR(a) rb_array_const_ptr(a)
-#define RARRAY_CONST_PTR_TRANSIENT(a) rb_array_const_ptr_transient(a)
-
-#if USE_TRANSIENT_HEAP
-#define RARRAY_TRANSIENT_P(ary) FL_TEST_RAW((ary), RARRAY_TRANSIENT_FLAG)
-#else
-#define RARRAY_TRANSIENT_P(ary) 0
-#endif
-
-#define RARRAY_PTR_USE_START_TRANSIENT(a) rb_array_ptr_use_start(a, 1)
-#define RARRAY_PTR_USE_END_TRANSIENT(a) rb_array_ptr_use_end(a, 1)
-
-#define RARRAY_PTR_USE_TRANSIENT(ary, ptr_name, expr) do { \
- const VALUE _ary = (ary); \
- VALUE *ptr_name = (VALUE *)RARRAY_PTR_USE_START_TRANSIENT(_ary); \
- expr; \
- RARRAY_PTR_USE_END_TRANSIENT(_ary); \
-} while (0)
-
-#define RARRAY_PTR_USE_START(a) rb_array_ptr_use_start(a, 0)
-#define RARRAY_PTR_USE_END(a) rb_array_ptr_use_end(a, 0)
-
-#define RARRAY_PTR_USE(ary, ptr_name, expr) do { \
- const VALUE _ary = (ary); \
- VALUE *ptr_name = (VALUE *)RARRAY_PTR_USE_START(_ary); \
- expr; \
- RARRAY_PTR_USE_END(_ary); \
-} while (0)
-
-#define RARRAY_AREF(a, i) (RARRAY_CONST_PTR_TRANSIENT(a)[i])
-#define RARRAY_ASET(a, i, v) do { \
- const VALUE _ary = (a); \
- const VALUE _v = (v); \
- VALUE *ptr = (VALUE *)RARRAY_PTR_USE_START_TRANSIENT(_ary); \
- RB_OBJ_WRITE(_ary, &ptr[i], _v); \
- RARRAY_PTR_USE_END_TRANSIENT(_ary); \
-} while (0)
-
-#define RARRAY_PTR(a) ((VALUE *)RARRAY_CONST_PTR(RB_OBJ_WB_UNPROTECT_FOR(ARRAY, a)))
-
-struct RRegexp {
- struct RBasic basic;
- struct re_pattern_buffer *ptr;
- const VALUE src;
- unsigned long usecnt;
-};
-#define RREGEXP_PTR(r) (RREGEXP(r)->ptr)
-#define RREGEXP_SRC(r) (RREGEXP(r)->src)
-#define RREGEXP_SRC_PTR(r) RSTRING_PTR(RREGEXP(r)->src)
-#define RREGEXP_SRC_LEN(r) RSTRING_LEN(RREGEXP(r)->src)
-#define RREGEXP_SRC_END(r) RSTRING_END(RREGEXP(r)->src)
-
-/* RHash is defined at internal.h */
-size_t rb_hash_size_num(VALUE hash);
-
-#define RHASH_TBL(h) rb_hash_tbl(h, __FILE__, __LINE__)
-#define RHASH_ITER_LEV(h) rb_hash_iter_lev(h)
-#define RHASH_IFNONE(h) rb_hash_ifnone(h)
-#define RHASH_SIZE(h) rb_hash_size_num(h)
-#define RHASH_EMPTY_P(h) (RHASH_SIZE(h) == 0)
-#define RHASH_SET_IFNONE(h, ifnone) rb_hash_set_ifnone((VALUE)h, ifnone)
-
-struct RFile {
- struct RBasic basic;
- struct rb_io_t *fptr;
-};
-
-struct RData {
- struct RBasic basic;
- void (*dmark)(void*);
- void (*dfree)(void*);
- void *data;
-};
-
-typedef struct rb_data_type_struct rb_data_type_t;
-
-struct rb_data_type_struct {
- const char *wrap_struct_name;
- struct {
- void (*dmark)(void*);
- void (*dfree)(void*);
- size_t (*dsize)(const void *);
- void (*dcompact)(void*);
- void *reserved[1]; /* For future extension.
- This array *must* be filled with ZERO. */
- } function;
- const rb_data_type_t *parent;
- void *data; /* This area can be used for any purpose
- by a programmer who define the type. */
- VALUE flags; /* RUBY_FL_WB_PROTECTED */
-};
-
-#define HAVE_TYPE_RB_DATA_TYPE_T 1
-#define HAVE_RB_DATA_TYPE_T_FUNCTION 1
-#define HAVE_RB_DATA_TYPE_T_PARENT 1
-
-struct RTypedData {
- struct RBasic basic;
- const rb_data_type_t *type;
- VALUE typed_flag; /* 1 or not */
- void *data;
-};
-
-#define DATA_PTR(dta) (RDATA(dta)->data)
-
-#define RTYPEDDATA_P(v) (RTYPEDDATA(v)->typed_flag == 1)
-#define RTYPEDDATA_TYPE(v) (RTYPEDDATA(v)->type)
-#define RTYPEDDATA_DATA(v) (RTYPEDDATA(v)->data)
-
-/*
-#define RUBY_DATA_FUNC(func) ((void (*)(void*))(func))
-*/
-typedef void (*RUBY_DATA_FUNC)(void*);
-
-#ifndef RUBY_UNTYPED_DATA_WARNING
-# if defined RUBY_EXPORT
-# define RUBY_UNTYPED_DATA_WARNING 1
-# else
-# define RUBY_UNTYPED_DATA_WARNING 0
-# endif
-#endif
-VALUE rb_data_object_wrap(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC);
-VALUE rb_data_object_zalloc(VALUE,size_t,RUBY_DATA_FUNC,RUBY_DATA_FUNC);
-VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *);
-VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type);
-int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
-int rb_typeddata_is_kind_of(VALUE, const rb_data_type_t *);
-void *rb_check_typeddata(VALUE, const rb_data_type_t *);
-#define Check_TypedStruct(v,t) rb_check_typeddata((VALUE)(v),(t))
-#define RUBY_DEFAULT_FREE ((RUBY_DATA_FUNC)-1)
-#define RUBY_NEVER_FREE ((RUBY_DATA_FUNC)0)
-#define RUBY_TYPED_DEFAULT_FREE RUBY_DEFAULT_FREE
-#define RUBY_TYPED_NEVER_FREE RUBY_NEVER_FREE
-
-/* bits for rb_data_type_struct::flags */
-#define RUBY_TYPED_FREE_IMMEDIATELY 1 /* TYPE field */
-#define RUBY_TYPED_WB_PROTECTED RUBY_FL_WB_PROTECTED /* THIS FLAG DEPENDS ON Ruby version */
-#define RUBY_TYPED_PROMOTED1 RUBY_FL_PROMOTED1 /* THIS FLAG DEPENDS ON Ruby version */
-
-#define Data_Wrap_Struct(klass,mark,free,sval)\
- rb_data_object_wrap((klass),(sval),(RUBY_DATA_FUNC)(mark),(RUBY_DATA_FUNC)(free))
-
-#define Data_Make_Struct0(result, klass, type, size, mark, free, sval) \
- VALUE result = rb_data_object_zalloc((klass), (size), \
- (RUBY_DATA_FUNC)(mark), \
- (RUBY_DATA_FUNC)(free)); \
- (void)((sval) = (type *)DATA_PTR(result));
-
-#ifdef __GNUC__
-#define Data_Make_Struct(klass,type,mark,free,sval) ({\
- Data_Make_Struct0(data_struct_obj, klass, type, sizeof(type), mark, free, sval); \
- data_struct_obj; \
-})
-#else
-#define Data_Make_Struct(klass,type,mark,free,sval) (\
- rb_data_object_make((klass),(RUBY_DATA_FUNC)(mark),(RUBY_DATA_FUNC)(free),(void **)&(sval),sizeof(type)) \
-)
-#endif
-
-#define TypedData_Wrap_Struct(klass,data_type,sval)\
- rb_data_typed_object_wrap((klass),(sval),(data_type))
-
-#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \
- VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \
- (void)((sval) = (type *)DATA_PTR(result));
-
-#ifdef __GNUC__
-#define TypedData_Make_Struct(klass, type, data_type, sval) ({\
- TypedData_Make_Struct0(data_struct_obj, klass, type, sizeof(type), data_type, sval); \
- data_struct_obj; \
-})
-#else
-#define TypedData_Make_Struct(klass, type, data_type, sval) (\
- rb_data_typed_object_make((klass),(data_type),(void **)&(sval),sizeof(type)) \
-)
-#endif
-
-#define Data_Get_Struct(obj,type,sval) \
- ((sval) = (type*)rb_data_object_get(obj))
-
-#define TypedData_Get_Struct(obj,type,data_type,sval) \
- ((sval) = (type*)rb_check_typeddata((obj), (data_type)))
-
-#define RSTRUCT_LEN(st) NUM2LONG(rb_struct_size(st))
-#define RSTRUCT_PTR(st) rb_struct_ptr(st)
-#define RSTRUCT_SET(st, idx, v) rb_struct_aset(st, INT2NUM(idx), (v))
-#define RSTRUCT_GET(st, idx) rb_struct_aref(st, INT2NUM(idx))
-
-int rb_big_sign(VALUE);
-#define RBIGNUM_SIGN(b) (rb_big_sign(b))
-#define RBIGNUM_POSITIVE_P(b) (RBIGNUM_SIGN(b)!=0)
-#define RBIGNUM_NEGATIVE_P(b) (RBIGNUM_SIGN(b)==0)
-
-#define R_CAST(st) (struct st*)
-#define RMOVED(obj) (R_CAST(RMoved)(obj))
-#define RBASIC(obj) (R_CAST(RBasic)(obj))
-#define ROBJECT(obj) (R_CAST(RObject)(obj))
-#define RCLASS(obj) (R_CAST(RClass)(obj))
-#define RMODULE(obj) RCLASS(obj)
-#define RSTRING(obj) (R_CAST(RString)(obj))
-#define RREGEXP(obj) (R_CAST(RRegexp)(obj))
-#define RARRAY(obj) (R_CAST(RArray)(obj))
-#define RDATA(obj) (R_CAST(RData)(obj))
-#define RTYPEDDATA(obj) (R_CAST(RTypedData)(obj))
-#define RFILE(obj) (R_CAST(RFile)(obj))
-
-#define FL_SINGLETON ((VALUE)RUBY_FL_SINGLETON)
-#define FL_WB_PROTECTED ((VALUE)RUBY_FL_WB_PROTECTED)
-#define FL_PROMOTED0 ((VALUE)RUBY_FL_PROMOTED0)
-#define FL_PROMOTED1 ((VALUE)RUBY_FL_PROMOTED1)
-#define FL_FINALIZE ((VALUE)RUBY_FL_FINALIZE)
-#define FL_TAINT ((VALUE)RUBY_FL_TAINT)
-#define FL_UNTRUSTED ((VALUE)RUBY_FL_UNTRUSTED)
-#define FL_SEEN_OBJ_ID ((VALUE)RUBY_FL_SEEN_OBJ_ID)
-#define FL_EXIVAR ((VALUE)RUBY_FL_EXIVAR)
-#define FL_FREEZE ((VALUE)RUBY_FL_FREEZE)
-
-#define FL_USHIFT ((VALUE)RUBY_FL_USHIFT)
-
-#define FL_USER0 ((VALUE)RUBY_FL_USER0)
-#define FL_USER1 ((VALUE)RUBY_FL_USER1)
-#define FL_USER2 ((VALUE)RUBY_FL_USER2)
-#define FL_USER3 ((VALUE)RUBY_FL_USER3)
-#define FL_USER4 ((VALUE)RUBY_FL_USER4)
-#define FL_USER5 ((VALUE)RUBY_FL_USER5)
-#define FL_USER6 ((VALUE)RUBY_FL_USER6)
-#define FL_USER7 ((VALUE)RUBY_FL_USER7)
-#define FL_USER8 ((VALUE)RUBY_FL_USER8)
-#define FL_USER9 ((VALUE)RUBY_FL_USER9)
-#define FL_USER10 ((VALUE)RUBY_FL_USER10)
-#define FL_USER11 ((VALUE)RUBY_FL_USER11)
-#define FL_USER12 ((VALUE)RUBY_FL_USER12)
-#define FL_USER13 ((VALUE)RUBY_FL_USER13)
-#define FL_USER14 ((VALUE)RUBY_FL_USER14)
-#define FL_USER15 ((VALUE)RUBY_FL_USER15)
-#define FL_USER16 ((VALUE)RUBY_FL_USER16)
-#define FL_USER17 ((VALUE)RUBY_FL_USER17)
-#define FL_USER18 ((VALUE)RUBY_FL_USER18)
-#define FL_USER19 ((VALUE)(unsigned int)RUBY_FL_USER19)
-
-#define RB_SPECIAL_CONST_P(x) (RB_IMMEDIATE_P(x) || !RB_TEST(x))
-#define SPECIAL_CONST_P(x) RB_SPECIAL_CONST_P(x)
-
-#define RB_FL_ABLE(x) (!RB_SPECIAL_CONST_P(x) && RB_BUILTIN_TYPE(x) != RUBY_T_NODE)
-#define RB_FL_TEST_RAW(x,f) (RBASIC(x)->flags&(f))
-#define RB_FL_TEST(x,f) (RB_FL_ABLE(x)?RB_FL_TEST_RAW((x),(f)):0)
-#define RB_FL_ANY_RAW(x,f) RB_FL_TEST_RAW((x),(f))
-#define RB_FL_ANY(x,f) RB_FL_TEST((x),(f))
-#define RB_FL_ALL_RAW(x,f) (RB_FL_TEST_RAW((x),(f)) == (f))
-#define RB_FL_ALL(x,f) (RB_FL_TEST((x),(f)) == (f))
-#define RB_FL_SET_RAW(x,f) (void)(RBASIC(x)->flags |= (f))
-#define RB_FL_SET(x,f) (RB_FL_ABLE(x) ? RB_FL_SET_RAW(x, f) : (void)0)
-#define RB_FL_UNSET_RAW(x,f) (void)(RBASIC(x)->flags &= ~(VALUE)(f))
-#define RB_FL_UNSET(x,f) (RB_FL_ABLE(x) ? RB_FL_UNSET_RAW(x, f) : (void)0)
-#define RB_FL_REVERSE_RAW(x,f) (void)(RBASIC(x)->flags ^= (f))
-#define RB_FL_REVERSE(x,f) (RB_FL_ABLE(x) ? RB_FL_REVERSE_RAW(x, f) : (void)0)
-
-#define RB_OBJ_TAINTABLE(x) (RB_FL_ABLE(x) && RB_BUILTIN_TYPE(x) != RUBY_T_BIGNUM && RB_BUILTIN_TYPE(x) != RUBY_T_FLOAT)
-#define RB_OBJ_TAINTED_RAW(x) RB_FL_TEST_RAW(x, RUBY_FL_TAINT)
-#define RB_OBJ_TAINTED(x) (!!RB_FL_TEST((x), RUBY_FL_TAINT))
-#define RB_OBJ_TAINT_RAW(x) RB_FL_SET_RAW(x, RUBY_FL_TAINT)
-#define RB_OBJ_TAINT(x) (RB_OBJ_TAINTABLE(x) ? RB_OBJ_TAINT_RAW(x) : (void)0)
-#define RB_OBJ_UNTRUSTED(x) RB_OBJ_TAINTED(x)
-#define RB_OBJ_UNTRUST(x) RB_OBJ_TAINT(x)
-#define RB_OBJ_INFECT_RAW(x,s) RB_FL_SET_RAW(x, RB_OBJ_TAINTED_RAW(s))
-#define RB_OBJ_INFECT(x,s) ( \
- (RB_OBJ_TAINTABLE(x) && RB_FL_ABLE(s)) ? \
- RB_OBJ_INFECT_RAW(x, s) : (void)0)
-
-#define RB_OBJ_FROZEN_RAW(x) (RBASIC(x)->flags&RUBY_FL_FREEZE)
-#define RB_OBJ_FROZEN(x) (!RB_FL_ABLE(x) || RB_OBJ_FROZEN_RAW(x))
-#define RB_OBJ_FREEZE_RAW(x) (void)(RBASIC(x)->flags |= RUBY_FL_FREEZE)
-#define RB_OBJ_FREEZE(x) rb_obj_freeze_inline((VALUE)x)
-
-/*!
- * \defgroup deprecated_macros deprecated macro APIs
- * \{
- * \par These macros are deprecated. Prefer their `RB_`-prefixed versions.
- */
-#define FL_ABLE(x) RB_FL_ABLE(x)
-#define FL_TEST_RAW(x,f) RB_FL_TEST_RAW(x,f)
-#define FL_TEST(x,f) RB_FL_TEST(x,f)
-#define FL_ANY_RAW(x,f) RB_FL_ANY_RAW(x,f)
-#define FL_ANY(x,f) RB_FL_ANY(x,f)
-#define FL_ALL_RAW(x,f) RB_FL_ALL_RAW(x,f)
-#define FL_ALL(x,f) RB_FL_ALL(x,f)
-#define FL_SET_RAW(x,f) RB_FL_SET_RAW(x,f)
-#define FL_SET(x,f) RB_FL_SET(x,f)
-#define FL_UNSET_RAW(x,f) RB_FL_UNSET_RAW(x,f)
-#define FL_UNSET(x,f) RB_FL_UNSET(x,f)
-#define FL_REVERSE_RAW(x,f) RB_FL_REVERSE_RAW(x,f)
-#define FL_REVERSE(x,f) RB_FL_REVERSE(x,f)
-
-#define OBJ_TAINTABLE(x) RB_OBJ_TAINTABLE(x)
-#define OBJ_TAINTED_RAW(x) RB_OBJ_TAINTED_RAW(x)
-#define OBJ_TAINTED(x) RB_OBJ_TAINTED(x)
-#define OBJ_TAINT_RAW(x) RB_OBJ_TAINT_RAW(x)
-#define OBJ_TAINT(x) RB_OBJ_TAINT(x)
-#define OBJ_UNTRUSTED(x) RB_OBJ_UNTRUSTED(x)
-#define OBJ_UNTRUST(x) RB_OBJ_UNTRUST(x)
-#define OBJ_INFECT_RAW(x,s) RB_OBJ_INFECT_RAW(x,s)
-#define OBJ_INFECT(x,s) RB_OBJ_INFECT(x,s)
-#define OBJ_FROZEN_RAW(x) RB_OBJ_FROZEN_RAW(x)
-#define OBJ_FROZEN(x) RB_OBJ_FROZEN(x)
-#define OBJ_FREEZE_RAW(x) RB_OBJ_FREEZE_RAW(x)
-#define OBJ_FREEZE(x) RB_OBJ_FREEZE(x)
-
-/* \} */
-
-void rb_freeze_singleton_class(VALUE klass);
-
-static inline void
-rb_obj_freeze_inline(VALUE x)
-{
- if (RB_FL_ABLE(x)) {
- RB_OBJ_FREEZE_RAW(x);
- if (RBASIC_CLASS(x) && !(RBASIC(x)->flags & RUBY_FL_SINGLETON)) {
- rb_freeze_singleton_class(x);
- }
- }
-}
-
-#if GCC_VERSION_SINCE(4,4,0)
-# define RUBY_UNTYPED_DATA_FUNC(func) func __attribute__((warning("untyped Data is unsafe; use TypedData instead")))
-#else
-# define RUBY_UNTYPED_DATA_FUNC(func) DEPRECATED(func)
-#endif
-
-#if defined(__GNUC__) && !defined(__NO_INLINE__)
-#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
-RUBY_UNTYPED_DATA_FUNC(static inline VALUE rb_data_object_wrap_warning(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC));
-#endif
-RUBY_UNTYPED_DATA_FUNC(static inline void *rb_data_object_get_warning(VALUE));
-
-static inline VALUE
-rb_data_object_wrap_warning(VALUE klass, void *ptr, RUBY_DATA_FUNC mark, RUBY_DATA_FUNC free)
-{
- return rb_data_object_wrap(klass, ptr, mark, free);
-}
-
-#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P)
-#define rb_data_object_wrap_warning(klass, ptr, mark, free) \
- __extension__( \
- __builtin_choose_expr( \
- __builtin_constant_p(klass) && !(klass), \
- rb_data_object_wrap(klass, ptr, mark, free), \
- rb_data_object_wrap_warning(klass, ptr, mark, free)))
-#endif
-#endif
-
-static inline void *
-rb_data_object_get(VALUE obj)
-{
- Check_Type(obj, RUBY_T_DATA);
- return ((struct RData *)obj)->data;
-}
-
-#if defined(__GNUC__) && !defined(__NO_INLINE__)
-static inline void *
-rb_data_object_get_warning(VALUE obj)
-{
- return rb_data_object_get(obj);
-}
-#endif
-
-static inline VALUE
-rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_func, void **datap, size_t size)
-{
- Data_Make_Struct0(result, klass, void, size, mark_func, free_func, *datap);
- return result;
-}
-
-static inline VALUE
-rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **datap, size_t size)
-{
- TypedData_Make_Struct0(result, klass, void, size, type, *datap);
- return result;
-}
-
-#ifndef rb_data_object_alloc
-DEPRECATED_BY(rb_data_object_wrap, static inline VALUE rb_data_object_alloc(VALUE,void*,RUBY_DATA_FUNC,RUBY_DATA_FUNC));
-static inline VALUE
-rb_data_object_alloc(VALUE klass, void *data, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
-{
- return rb_data_object_wrap(klass, data, dmark, dfree);
-}
-#endif
-
-#ifndef rb_data_typed_object_alloc
-DEPRECATED_BY(rb_data_typed_object_wrap, static inline VALUE rb_data_typed_object_alloc(VALUE,void*,const rb_data_type_t*));
-static inline VALUE
-rb_data_typed_object_alloc(VALUE klass, void *datap, const rb_data_type_t *type)
-{
- return rb_data_typed_object_wrap(klass, datap, type);
-}
-#endif
-
-#if defined(__GNUC__) && !defined(__NO_INLINE__)
-#define rb_data_object_wrap_0 rb_data_object_wrap
-#define rb_data_object_wrap_1 rb_data_object_wrap_warning
-#define rb_data_object_wrap RUBY_MACRO_SELECT(rb_data_object_wrap_, RUBY_UNTYPED_DATA_WARNING)
-#define rb_data_object_get_0 rb_data_object_get
-#define rb_data_object_get_1 rb_data_object_get_warning
-#define rb_data_object_get RUBY_MACRO_SELECT(rb_data_object_get_, RUBY_UNTYPED_DATA_WARNING)
-#define rb_data_object_make_0 rb_data_object_make
-#define rb_data_object_make_1 rb_data_object_make_warning
-#define rb_data_object_make RUBY_MACRO_SELECT(rb_data_object_make_, RUBY_UNTYPED_DATA_WARNING)
-#endif
-
-#if USE_RGENGC
-#define RB_OBJ_PROMOTED_RAW(x) RB_FL_ALL_RAW(x, RUBY_FL_PROMOTED)
-#define RB_OBJ_PROMOTED(x) (RB_SPECIAL_CONST_P(x) ? 0 : RB_OBJ_PROMOTED_RAW(x))
-#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__)
-
-void rb_gc_writebarrier(VALUE a, VALUE b);
-void rb_gc_writebarrier_unprotect(VALUE obj);
-
-#else /* USE_RGENGC */
-#define RB_OBJ_PROMOTED(x) 0
-#define RB_OBJ_WB_UNPROTECT(x) rb_obj_wb_unprotect(x, __FILE__, __LINE__)
-#endif
-#define OBJ_PROMOTED_RAW(x) RB_OBJ_PROMOTED_RAW(x)
-#define OBJ_PROMOTED(x) RB_OBJ_PROMOTED(x)
-#define OBJ_WB_UNPROTECT(x) RB_OBJ_WB_UNPROTECT(x)
-
-/* Write barrier (WB) interfaces:
- * - RB_OBJ_WRITE(a, slot, b): WB for new reference from `a' to `b'.
- * Write `b' into `*slot'. `slot' is a pointer in `a'.
- * - RB_OBJ_WRITTEN(a, oldv, b): WB for new reference from `a' to `b'.
- * This doesn't write any values, but only a WB declaration.
- * `oldv' is replaced value with `b' (not used in current Ruby).
- *
- * NOTE: The following core interfaces can be changed in the future.
- * Please catch up if you want to insert WB into C-extensions
- * correctly.
- */
-#define RB_OBJ_WRITE(a, slot, b) rb_obj_write((VALUE)(a), (VALUE *)(slot), (VALUE)(b), __FILE__, __LINE__)
-#define RB_OBJ_WRITTEN(a, oldv, b) rb_obj_written((VALUE)(a), (VALUE)(oldv), (VALUE)(b), __FILE__, __LINE__)
-
-#ifndef USE_RGENGC_LOGGING_WB_UNPROTECT
-#define USE_RGENGC_LOGGING_WB_UNPROTECT 0
-#endif
-
-#if USE_RGENGC_LOGGING_WB_UNPROTECT
-void rb_gc_unprotect_logging(void *objptr, const char *filename, int line);
-#define RGENGC_LOGGING_WB_UNPROTECT rb_gc_unprotect_logging
-#endif
-
-static inline VALUE
-rb_obj_wb_unprotect(VALUE x, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line))
-{
-#ifdef RGENGC_LOGGING_WB_UNPROTECT
- RGENGC_LOGGING_WB_UNPROTECT((void *)x, filename, line);
-#endif
-#if USE_RGENGC
- rb_gc_writebarrier_unprotect(x);
-#endif
- return x;
-}
-
-static inline VALUE
-rb_obj_written(VALUE a, RB_UNUSED_VAR(VALUE oldv), VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line))
-{
-#ifdef RGENGC_LOGGING_OBJ_WRITTEN
- RGENGC_LOGGING_OBJ_WRITTEN(a, oldv, b, filename, line);
-#endif
-
-#if USE_RGENGC
- if (!RB_SPECIAL_CONST_P(b)) {
- rb_gc_writebarrier(a, b);
- }
-#endif
-
- return a;
-}
-
-static inline VALUE
-rb_obj_write(VALUE a, VALUE *slot, VALUE b, RB_UNUSED_VAR(const char *filename), RB_UNUSED_VAR(int line))
-{
-#ifdef RGENGC_LOGGING_WRITE
- RGENGC_LOGGING_WRITE(a, slot, b, filename, line);
-#endif
-
- *slot = b;
-
-#if USE_RGENGC
- rb_obj_written(a, RUBY_Qundef /* ignore `oldv' now */, b, filename, line);
-#endif
- return a;
-}
-
-#define RUBY_INTEGER_UNIFICATION 1
-#define RB_INTEGER_TYPE_P(obj) rb_integer_type_p(obj)
-#if defined __GNUC__ && !GCC_VERSION_SINCE(4, 3, 0)
-/* clang 3.x (4.2 compatible) can't eliminate CSE of RB_BUILTIN_TYPE
- * in inline function and caller function */
-#define rb_integer_type_p(obj) \
- __extension__ ({ \
- const VALUE integer_type_obj = (obj); \
- (RB_FIXNUM_P(integer_type_obj) || \
- (!RB_SPECIAL_CONST_P(integer_type_obj) && \
- RB_BUILTIN_TYPE(integer_type_obj) == RUBY_T_BIGNUM)); \
- })
-#else
-static inline int
-rb_integer_type_p(VALUE obj)
-{
- return (RB_FIXNUM_P(obj) ||
- (!RB_SPECIAL_CONST_P(obj) &&
- RB_BUILTIN_TYPE(obj) == RUBY_T_BIGNUM));
-}
-#endif
-
-#if SIZEOF_INT < SIZEOF_LONG
-# define RB_INT2NUM(v) RB_INT2FIX((int)(v))
-# define RB_UINT2NUM(v) RB_LONG2FIX((unsigned int)(v))
-#else
-static inline VALUE
-rb_int2num_inline(int v)
-{
- if (RB_FIXABLE(v))
- return RB_INT2FIX(v);
- else
- return rb_int2big(v);
-}
-#define RB_INT2NUM(x) rb_int2num_inline(x)
-
-static inline VALUE
-rb_uint2num_inline(unsigned int v)
-{
- if (RB_POSFIXABLE(v))
- return RB_LONG2FIX(v);
- else
- return rb_uint2big(v);
-}
-#define RB_UINT2NUM(x) rb_uint2num_inline(x)
-#endif
-#define INT2NUM(x) RB_INT2NUM(x)
-#define UINT2NUM(x) RB_UINT2NUM(x)
-
-static inline VALUE
-rb_long2num_inline(long v)
-{
- if (RB_FIXABLE(v))
- return RB_LONG2FIX(v);
- else
- return rb_int2big(v);
-}
-#define RB_LONG2NUM(x) rb_long2num_inline(x)
-
-static inline VALUE
-rb_ulong2num_inline(unsigned long v)
-{
- if (RB_POSFIXABLE(v))
- return RB_LONG2FIX(v);
- else
- return rb_uint2big(v);
-}
-#define RB_ULONG2NUM(x) rb_ulong2num_inline(x)
-
-static inline char
-rb_num2char_inline(VALUE x)
-{
- if (RB_TYPE_P(x, RUBY_T_STRING) && (RSTRING_LEN(x)>=1))
- return RSTRING_PTR(x)[0];
- else
- return (char)(NUM2INT(x) & 0xff);
-}
-#define RB_NUM2CHR(x) rb_num2char_inline(x)
-
-#define RB_CHR2FIX(x) RB_INT2FIX((long)((x)&0xff))
-
-#define LONG2NUM(x) RB_LONG2NUM(x)
-#define ULONG2NUM(x) RB_ULONG2NUM(x)
-#define USHORT2NUM(x) RB_INT2FIX(x)
-#define NUM2CHR(x) RB_NUM2CHR(x)
-#define CHR2FIX(x) RB_CHR2FIX(x)
-
-#if SIZEOF_LONG < SIZEOF_VALUE
-#define RB_ST2FIX(h) RB_LONG2FIX((long)((h) > 0 ? (h) & (unsigned long)-1 >> 2 : (h) | ~((unsigned long)-1 >> 2)))
-#else
-#define RB_ST2FIX(h) RB_LONG2FIX((long)(h))
-#endif
-#define ST2FIX(h) RB_ST2FIX(h)
-
-#define RB_ALLOC_N(type,n) ((type*)ruby_xmalloc2((size_t)(n),sizeof(type)))
-#define RB_ALLOC(type) ((type*)ruby_xmalloc(sizeof(type)))
-#define RB_ZALLOC_N(type,n) ((type*)ruby_xcalloc((size_t)(n),sizeof(type)))
-#define RB_ZALLOC(type) (RB_ZALLOC_N(type,1))
-#define RB_REALLOC_N(var,type,n) ((var)=(type*)ruby_xrealloc2((char*)(var),(size_t)(n),sizeof(type)))
-
-#define ALLOC_N(type,n) RB_ALLOC_N(type,n)
-#define ALLOC(type) RB_ALLOC(type)
-#define ZALLOC_N(type,n) RB_ZALLOC_N(type,n)
-#define ZALLOC(type) RB_ZALLOC(type)
-#define REALLOC_N(var,type,n) RB_REALLOC_N(var,type,n)
-
-#if GCC_VERSION_BEFORE(4,9,5)
-/* GCC 4.9.2 reportedly has this feature and is broken.
- * The function is not officially documented below.
- * Seems we should not use it.
- * https://gcc.gnu.org/onlinedocs/gcc-4.9.4/gcc/Other-Builtins.html#Other-Builtins */
-# undef HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN
-#endif
-
-#if defined(HAVE_BUILTIN___BUILTIN_ALLOCA_WITH_ALIGN) && defined(RUBY_ALIGNOF)
-/* I don't know why but __builtin_alloca_with_align's second argument
- takes bits rather than bytes. */
-#define ALLOCA_N(type, n) \
- (type*)__builtin_alloca_with_align((sizeof(type)*(n)), \
- RUBY_ALIGNOF(type) * CHAR_BIT)
-#else
-#define ALLOCA_N(type,n) ((type*)alloca(sizeof(type)*(n)))
-#endif
-
-void *rb_alloc_tmp_buffer(volatile VALUE *store, long len) RUBY_ATTR_ALLOC_SIZE((2));
-void *rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t len,size_t count) RUBY_ATTR_ALLOC_SIZE((2,3));
-void rb_free_tmp_buffer(volatile VALUE *store);
-NORETURN(void ruby_malloc_size_overflow(size_t, size_t));
-#if HAVE_LONG_LONG && SIZEOF_SIZE_T * 2 <= SIZEOF_LONG_LONG
-# define DSIZE_T unsigned LONG_LONG
-#elif defined(HAVE_INT128_T)
-# define DSIZE_T uint128_t
-#endif
-static inline int
-rb_mul_size_overflow(size_t a, size_t b, size_t max, size_t *c)
-{
-#ifdef DSIZE_T
-# ifdef __GNUC__
- __extension__
-# endif
- DSIZE_T c2 = (DSIZE_T)a * (DSIZE_T)b;
- if (c2 > max) return 1;
- *c = (size_t)c2;
-#else
- if (b != 0 && a > max / b) return 1;
- *c = a * b;
-#endif
- return 0;
-}
-static inline void *
-rb_alloc_tmp_buffer2(volatile VALUE *store, long count, size_t elsize)
-{
- size_t cnt = (size_t)count;
- if (elsize == sizeof(VALUE)) {
- if (RB_UNLIKELY(cnt > LONG_MAX / sizeof(VALUE))) {
- ruby_malloc_size_overflow(cnt, elsize);
- }
- }
- else {
- size_t size, max = LONG_MAX - sizeof(VALUE) + 1;
- if (RB_UNLIKELY(rb_mul_size_overflow(cnt, elsize, max, &size))) {
- ruby_malloc_size_overflow(cnt, elsize);
- }
- cnt = (size + sizeof(VALUE) - 1) / sizeof(VALUE);
- }
- return rb_alloc_tmp_buffer_with_count(store, cnt * sizeof(VALUE), cnt);
-}
-/* allocates _n_ bytes temporary buffer and stores VALUE including it
- * in _v_. _n_ may be evaluated twice. */
-#ifdef C_ALLOCA
-# define RB_ALLOCV(v, n) rb_alloc_tmp_buffer(&(v), (n))
-# define RB_ALLOCV_N(type, v, n) \
- rb_alloc_tmp_buffer2(&(v), (n), sizeof(type))
-#else
-# define RUBY_ALLOCV_LIMIT 1024
-# define RB_ALLOCV(v, n) ((n) < RUBY_ALLOCV_LIMIT ? \
- ((v) = 0, alloca(n)) : \
- rb_alloc_tmp_buffer(&(v), (n)))
-# define RB_ALLOCV_N(type, v, n) \
- ((type*)(((size_t)(n) < RUBY_ALLOCV_LIMIT / sizeof(type)) ? \
- ((v) = 0, alloca((size_t)(n) * sizeof(type))) : \
- rb_alloc_tmp_buffer2(&(v), (long)(n), sizeof(type))))
-#endif
-#define RB_ALLOCV_END(v) rb_free_tmp_buffer(&(v))
-
-#define ALLOCV(v, n) RB_ALLOCV(v, n)
-#define ALLOCV_N(type, v, n) RB_ALLOCV_N(type, v, n)
-#define ALLOCV_END(v) RB_ALLOCV_END(v)
-
-#define MEMZERO(p,type,n) memset((p), 0, sizeof(type)*(size_t)(n))
-#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(size_t)(n))
-#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(size_t)(n))
-#define MEMCMP(p1,p2,type,n) memcmp((p1), (p2), sizeof(type)*(size_t)(n))
-#ifdef __GLIBC__
-static inline void *
-ruby_nonempty_memcpy(void *dest, const void *src, size_t n)
-{
- /* if nothing to be copied, src may be NULL */
- return (n ? memcpy(dest, src, n) : dest);
-}
-#define memcpy(p1,p2,n) ruby_nonempty_memcpy(p1, p2, n)
-#endif
-
-void rb_obj_infect(VALUE victim, VALUE carrier);
-
-typedef int ruby_glob_func(const char*,VALUE, void*);
-void rb_glob(const char*,void(*)(const char*,VALUE,void*),VALUE);
-int ruby_glob(const char*,int,ruby_glob_func*,VALUE);
-int ruby_brace_glob(const char*,int,ruby_glob_func*,VALUE);
-
-VALUE rb_define_class(const char*,VALUE);
-VALUE rb_define_module(const char*);
-VALUE rb_define_class_under(VALUE, const char*, VALUE);
-VALUE rb_define_module_under(VALUE, const char*);
-
-void rb_include_module(VALUE,VALUE);
-void rb_extend_object(VALUE,VALUE);
-void rb_prepend_module(VALUE,VALUE);
-
-typedef VALUE rb_gvar_getter_t(ID id, VALUE *data);
-typedef void rb_gvar_setter_t(VALUE val, ID id, VALUE *data);
-typedef void rb_gvar_marker_t(VALUE *var);
-
-rb_gvar_getter_t rb_gvar_undef_getter;
-rb_gvar_setter_t rb_gvar_undef_setter;
-rb_gvar_marker_t rb_gvar_undef_marker;
-
-rb_gvar_getter_t rb_gvar_val_getter;
-rb_gvar_setter_t rb_gvar_val_setter;
-rb_gvar_marker_t rb_gvar_val_marker;
-
-rb_gvar_getter_t rb_gvar_var_getter;
-rb_gvar_setter_t rb_gvar_var_setter;
-rb_gvar_marker_t rb_gvar_var_marker;
-
-NORETURN(rb_gvar_setter_t rb_gvar_readonly_setter);
-
-void rb_define_variable(const char*,VALUE*);
-void rb_define_virtual_variable(const char*,rb_gvar_getter_t*,rb_gvar_setter_t*);
-void rb_define_hooked_variable(const char*,VALUE*,rb_gvar_getter_t*,rb_gvar_setter_t*);
-void rb_define_readonly_variable(const char*,const VALUE*);
-void rb_define_const(VALUE,const char*,VALUE);
-void rb_define_global_const(const char*,VALUE);
-
-void rb_define_method(VALUE,const char*,VALUE(*)(ANYARGS),int);
-void rb_define_module_function(VALUE,const char*,VALUE(*)(ANYARGS),int);
-void rb_define_global_function(const char*,VALUE(*)(ANYARGS),int);
-
-void rb_undef_method(VALUE,const char*);
-void rb_define_alias(VALUE,const char*,const char*);
-void rb_define_attr(VALUE,const char*,int,int);
-
-void rb_global_variable(VALUE*);
-void rb_gc_register_mark_object(VALUE);
-void rb_gc_register_address(VALUE*);
-void rb_gc_unregister_address(VALUE*);
-
-ID rb_intern(const char*);
-ID rb_intern2(const char*, long);
-ID rb_intern_str(VALUE str);
-const char *rb_id2name(ID);
-ID rb_check_id(volatile VALUE *);
-ID rb_to_id(VALUE);
-VALUE rb_id2str(ID);
-VALUE rb_sym2str(VALUE);
-VALUE rb_to_symbol(VALUE name);
-VALUE rb_check_symbol(volatile VALUE *namep);
-
-#define RUBY_CONST_ID_CACHE_NB(result, str) \
- static ID rb_intern_id_cache; \
- if (!rb_intern_id_cache) \
- rb_intern_id_cache = rb_intern2((str), (long)strlen(str)); \
- result rb_intern_id_cache;
-#define RUBY_CONST_ID_CACHE(result, str) \
- { \
- RUBY_CONST_ID_CACHE_NB(result, str) \
- }
-#define RUBY_CONST_ID(var, str) \
- do RUBY_CONST_ID_CACHE((var) =, (str)) while (0)
-#define CONST_ID_CACHE(result, str) RUBY_CONST_ID_CACHE(result, str)
-#define CONST_ID(var, str) RUBY_CONST_ID(var, str)
#if defined(HAVE_BUILTIN___BUILTIN_CONSTANT_P) && defined(HAVE_STMT_AND_DECL_IN_EXPR)
-/* __builtin_constant_p and statement expression is available
- * since gcc-2.7.2.3 at least. */
-#define rb_intern(str) \
- (__builtin_constant_p(str) ? \
- __extension__ ({RUBY_CONST_ID_CACHE_NB((ID), (str))}) : \
- rb_intern(str))
-#define rb_intern_const(str) \
- (__builtin_constant_p(str) ? \
- __extension__ (rb_intern2((str), (long)strlen(str))) : \
- (rb_intern)(str))
-
# define rb_varargs_argc_check_runtime(argc, vargc) \
(((argc) <= (vargc)) ? (argc) : \
(rb_fatal("argc(%d) exceeds actual arguments(%d)", \
@@ -1876,9 +87,6 @@ ERRORFUNC((" argument length doesn't match"), int rb_varargs_bad_length(int,int)
# define rb_varargs_argc_check(argc, vargc) \
rb_varargs_argc_check_runtime(argc, vargc)
# endif
-
-#else
-#define rb_intern_const(str) rb_intern2((str), (long)strlen(str))
#endif
const char *rb_class2name(VALUE);
@@ -1886,350 +94,12 @@ const char *rb_obj_classname(VALUE);
void rb_p(VALUE);
-VALUE rb_eval_string(const char*);
-VALUE rb_eval_string_protect(const char*, int*);
-VALUE rb_eval_string_wrap(const char*, int*);
-VALUE rb_funcall(VALUE, ID, int, ...);
-VALUE rb_funcallv(VALUE, ID, int, const VALUE*);
-VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE*, int);
-VALUE rb_funcallv_public(VALUE, ID, int, const VALUE*);
-VALUE rb_funcallv_public_kw(VALUE, ID, int, const VALUE*, int);
-#define rb_funcall2 rb_funcallv
-#define rb_funcall3 rb_funcallv_public
-VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*);
-VALUE rb_funcall_passing_block_kw(VALUE, ID, int, const VALUE*, int);
-VALUE rb_funcall_with_block(VALUE, ID, int, const VALUE*, VALUE);
-VALUE rb_funcall_with_block_kw(VALUE, ID, int, const VALUE*, VALUE, int);
-int rb_scan_args(int, const VALUE*, const char*, ...);
-#define RB_SCAN_ARGS_PASS_CALLED_KEYWORDS 0
-#define RB_SCAN_ARGS_KEYWORDS 1
-#define RB_SCAN_ARGS_EMPTY_KEYWORDS 2 /* Will be removed in 3.0 */
-#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS 3
-int rb_scan_args_kw(int, int, const VALUE*, const char*, ...);
-VALUE rb_call_super(int, const VALUE*);
-VALUE rb_call_super_kw(int, const VALUE*, int);
-VALUE rb_current_receiver(void);
-int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *);
-VALUE rb_extract_keywords(VALUE *orighash);
-
-/* rb_scan_args() format allows ':' for optional hash */
-#define HAVE_RB_SCAN_ARGS_OPTIONAL_HASH 1
-
-VALUE rb_gv_set(const char*, VALUE);
-VALUE rb_gv_get(const char*);
-VALUE rb_iv_get(VALUE, const char*);
-VALUE rb_iv_set(VALUE, const char*, VALUE);
-
VALUE rb_equal(VALUE,VALUE);
-VALUE *rb_ruby_verbose_ptr(void);
-VALUE *rb_ruby_debug_ptr(void);
-#define ruby_verbose (*rb_ruby_verbose_ptr())
-#define ruby_debug (*rb_ruby_debug_ptr())
-
-/* for rb_readwrite_sys_fail first argument */
-enum rb_io_wait_readwrite {RB_IO_WAIT_READABLE, RB_IO_WAIT_WRITABLE};
-#define RB_IO_WAIT_READABLE RB_IO_WAIT_READABLE
-#define RB_IO_WAIT_WRITABLE RB_IO_WAIT_WRITABLE
-
-PRINTF_ARGS(NORETURN(void rb_raise(VALUE, const char*, ...)), 2, 3);
-PRINTF_ARGS(NORETURN(void rb_fatal(const char*, ...)), 1, 2);
-COLDFUNC PRINTF_ARGS(NORETURN(void rb_bug(const char*, ...)), 1, 2);
-NORETURN(void rb_bug_errno(const char*, int));
-NORETURN(void rb_sys_fail(const char*));
-NORETURN(void rb_sys_fail_str(VALUE));
-NORETURN(void rb_mod_sys_fail(VALUE, const char*));
-NORETURN(void rb_mod_sys_fail_str(VALUE, VALUE));
-NORETURN(void rb_readwrite_sys_fail(enum rb_io_wait_readwrite, const char*));
-NORETURN(void rb_iter_break(void));
-NORETURN(void rb_iter_break_value(VALUE));
-NORETURN(void rb_exit(int));
-NORETURN(void rb_notimplement(void));
-VALUE rb_syserr_new(int, const char *);
-VALUE rb_syserr_new_str(int n, VALUE arg);
-NORETURN(void rb_syserr_fail(int, const char*));
-NORETURN(void rb_syserr_fail_str(int, VALUE));
-NORETURN(void rb_mod_syserr_fail(VALUE, int, const char*));
-NORETURN(void rb_mod_syserr_fail_str(VALUE, int, VALUE));
-NORETURN(void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite, int, const char*));
-
-/* reports if `-W' specified */
-PRINTF_ARGS(void rb_warning(const char*, ...), 1, 2);
-PRINTF_ARGS(void rb_compile_warning(const char *, int, const char*, ...), 3, 4);
-PRINTF_ARGS(void rb_sys_warning(const char*, ...), 1, 2);
-/* reports always */
-COLDFUNC PRINTF_ARGS(void rb_warn(const char*, ...), 1, 2);
-PRINTF_ARGS(void rb_compile_warn(const char *, int, const char*, ...), 3, 4);
-
-#define RB_BLOCK_CALL_FUNC_STRICT 1
-#define RUBY_BLOCK_CALL_FUNC_TAKES_BLOCKARG 1
-#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg) \
- VALUE yielded_arg, VALUE callback_arg, int argc, const VALUE *argv, VALUE blockarg
-typedef VALUE rb_block_call_func(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg));
-typedef rb_block_call_func *rb_block_call_func_t;
-
-VALUE rb_each(VALUE);
-VALUE rb_yield(VALUE);
-VALUE rb_yield_values(int n, ...);
-VALUE rb_yield_values2(int n, const VALUE *argv);
-VALUE rb_yield_values_kw(int n, const VALUE *argv, int kw_splat);
-VALUE rb_yield_splat(VALUE);
-VALUE rb_yield_splat_kw(VALUE, int);
-VALUE rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)); /* rb_block_call_func */
-#define RB_NO_KEYWORDS 0
-#define RB_PASS_KEYWORDS 1
-#define RB_PASS_EMPTY_KEYWORDS 2 /* Will be removed in 3.0 */
-#define RB_PASS_CALLED_KEYWORDS 3
-int rb_keyword_given_p(void);
-int rb_block_given_p(void);
-void rb_need_block(void);
-VALUE rb_iterate(VALUE(*)(VALUE),VALUE,rb_block_call_func_t,VALUE);
-VALUE rb_block_call(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE);
-VALUE rb_block_call_kw(VALUE,ID,int,const VALUE*,rb_block_call_func_t,VALUE,int);
-VALUE rb_rescue(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE);
-VALUE rb_rescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,...);
-VALUE rb_vrescue2(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE,VALUE),VALUE,va_list);
-VALUE rb_ensure(VALUE(*)(VALUE),VALUE,VALUE(*)(VALUE),VALUE);
-VALUE rb_catch(const char*,rb_block_call_func_t,VALUE);
-VALUE rb_catch_obj(VALUE,rb_block_call_func_t,VALUE);
-NORETURN(void rb_throw(const char*,VALUE));
-NORETURN(void rb_throw_obj(VALUE,VALUE));
-
VALUE rb_require(const char*);
-RUBY_EXTERN VALUE rb_mKernel;
-RUBY_EXTERN VALUE rb_mComparable;
-RUBY_EXTERN VALUE rb_mEnumerable;
-RUBY_EXTERN VALUE rb_mErrno;
-RUBY_EXTERN VALUE rb_mFileTest;
-RUBY_EXTERN VALUE rb_mGC;
-RUBY_EXTERN VALUE rb_mMath;
-RUBY_EXTERN VALUE rb_mProcess;
-RUBY_EXTERN VALUE rb_mWaitReadable;
-RUBY_EXTERN VALUE rb_mWaitWritable;
-
-RUBY_EXTERN VALUE rb_cBasicObject;
-RUBY_EXTERN VALUE rb_cObject;
-RUBY_EXTERN VALUE rb_cArray;
-#ifndef RUBY_INTEGER_UNIFICATION
-RUBY_EXTERN VALUE rb_cBignum;
-#endif
-RUBY_EXTERN VALUE rb_cBinding;
-RUBY_EXTERN VALUE rb_cClass;
-RUBY_EXTERN VALUE rb_cCont;
-RUBY_EXTERN VALUE rb_cData;
-RUBY_EXTERN VALUE rb_cDir;
-RUBY_EXTERN VALUE rb_cEncoding;
-RUBY_EXTERN VALUE rb_cEnumerator;
-RUBY_EXTERN VALUE rb_cFalseClass;
-RUBY_EXTERN VALUE rb_cFile;
-#ifndef RUBY_INTEGER_UNIFICATION
-RUBY_EXTERN VALUE rb_cFixnum;
-#endif
-RUBY_EXTERN VALUE rb_cComplex;
-RUBY_EXTERN VALUE rb_cFloat;
-RUBY_EXTERN VALUE rb_cHash;
-RUBY_EXTERN VALUE rb_cIO;
-RUBY_EXTERN VALUE rb_cInteger;
-RUBY_EXTERN VALUE rb_cMatch;
-RUBY_EXTERN VALUE rb_cMethod;
-RUBY_EXTERN VALUE rb_cModule;
-RUBY_EXTERN VALUE rb_cNameErrorMesg;
-RUBY_EXTERN VALUE rb_cNilClass;
-RUBY_EXTERN VALUE rb_cNumeric;
-RUBY_EXTERN VALUE rb_cProc;
-RUBY_EXTERN VALUE rb_cRandom;
-RUBY_EXTERN VALUE rb_cRange;
-RUBY_EXTERN VALUE rb_cRational;
-RUBY_EXTERN VALUE rb_cRegexp;
-RUBY_EXTERN VALUE rb_cStat;
-RUBY_EXTERN VALUE rb_cString;
-RUBY_EXTERN VALUE rb_cStruct;
-RUBY_EXTERN VALUE rb_cSymbol;
-RUBY_EXTERN VALUE rb_cThread;
-RUBY_EXTERN VALUE rb_cTime;
-RUBY_EXTERN VALUE rb_cTrueClass;
-RUBY_EXTERN VALUE rb_cUnboundMethod;
-
-RUBY_EXTERN VALUE rb_eException;
-RUBY_EXTERN VALUE rb_eStandardError;
-RUBY_EXTERN VALUE rb_eSystemExit;
-RUBY_EXTERN VALUE rb_eInterrupt;
-RUBY_EXTERN VALUE rb_eSignal;
-RUBY_EXTERN VALUE rb_eFatal;
-RUBY_EXTERN VALUE rb_eArgError;
-RUBY_EXTERN VALUE rb_eEOFError;
-RUBY_EXTERN VALUE rb_eIndexError;
-RUBY_EXTERN VALUE rb_eStopIteration;
-RUBY_EXTERN VALUE rb_eKeyError;
-RUBY_EXTERN VALUE rb_eRangeError;
-RUBY_EXTERN VALUE rb_eIOError;
-RUBY_EXTERN VALUE rb_eRuntimeError;
-RUBY_EXTERN VALUE rb_eFrozenError;
-RUBY_EXTERN VALUE rb_eSecurityError;
-RUBY_EXTERN VALUE rb_eSystemCallError;
-RUBY_EXTERN VALUE rb_eThreadError;
-RUBY_EXTERN VALUE rb_eTypeError;
-RUBY_EXTERN VALUE rb_eZeroDivError;
-RUBY_EXTERN VALUE rb_eNotImpError;
-RUBY_EXTERN VALUE rb_eNoMemError;
-RUBY_EXTERN VALUE rb_eNoMethodError;
-RUBY_EXTERN VALUE rb_eFloatDomainError;
-RUBY_EXTERN VALUE rb_eLocalJumpError;
-RUBY_EXTERN VALUE rb_eSysStackError;
-RUBY_EXTERN VALUE rb_eRegexpError;
-RUBY_EXTERN VALUE rb_eEncodingError;
-RUBY_EXTERN VALUE rb_eEncCompatError;
-RUBY_EXTERN VALUE rb_eNoMatchingPatternError;
-
-RUBY_EXTERN VALUE rb_eScriptError;
-RUBY_EXTERN VALUE rb_eNameError;
-RUBY_EXTERN VALUE rb_eSyntaxError;
-RUBY_EXTERN VALUE rb_eLoadError;
-
-RUBY_EXTERN VALUE rb_eMathDomainError;
-
-RUBY_EXTERN VALUE rb_stdin, rb_stdout, rb_stderr;
-
-static inline VALUE
-rb_class_of(VALUE obj)
-{
- if (RB_IMMEDIATE_P(obj)) {
- if (RB_FIXNUM_P(obj)) return rb_cInteger;
- if (RB_FLONUM_P(obj)) return rb_cFloat;
- if (obj == RUBY_Qtrue) return rb_cTrueClass;
- if (RB_STATIC_SYM_P(obj)) return rb_cSymbol;
- }
- else if (!RB_TEST(obj)) {
- if (obj == RUBY_Qnil) return rb_cNilClass;
- if (obj == RUBY_Qfalse) return rb_cFalseClass;
- }
- return RBASIC(obj)->klass;
-}
-
-static inline int
-rb_type(VALUE obj)
-{
- if (RB_IMMEDIATE_P(obj)) {
- if (RB_FIXNUM_P(obj)) return RUBY_T_FIXNUM;
- if (RB_FLONUM_P(obj)) return RUBY_T_FLOAT;
- if (obj == RUBY_Qtrue) return RUBY_T_TRUE;
- if (RB_STATIC_SYM_P(obj)) return RUBY_T_SYMBOL;
- if (obj == RUBY_Qundef) return RUBY_T_UNDEF;
- }
- else if (!RB_TEST(obj)) {
- if (obj == RUBY_Qnil) return RUBY_T_NIL;
- if (obj == RUBY_Qfalse) return RUBY_T_FALSE;
- }
- return RB_BUILTIN_TYPE(obj);
-}
-
-#ifdef __GNUC__
-#define rb_type_p(obj, type) \
- __extension__ (__builtin_constant_p(type) ? RB_TYPE_P((obj), (type)) : \
- rb_type(obj) == (type))
-#else
-#define rb_type_p(obj, type) (rb_type(obj) == (type))
-#endif
-
-#ifdef __GNUC__
-#define rb_special_const_p(obj) \
- __extension__ ({ \
- VALUE special_const_obj = (obj); \
- (int)(RB_SPECIAL_CONST_P(special_const_obj) ? RUBY_Qtrue : RUBY_Qfalse); \
- })
-#else
-static inline int
-rb_special_const_p(VALUE obj)
-{
- if (RB_SPECIAL_CONST_P(obj)) return (int)RUBY_Qtrue;
- return (int)RUBY_Qfalse;
-}
-#endif
-
#include "ruby/intern.h"
-static inline void
-rb_clone_setup(VALUE clone, VALUE obj)
-{
- rb_obj_setup(clone, rb_singleton_class_clone(obj),
- RBASIC(obj)->flags & ~(FL_PROMOTED0|FL_PROMOTED1|FL_FINALIZE));
- rb_singleton_class_attached(RBASIC_CLASS(clone), clone);
- if (RB_FL_TEST(obj, RUBY_FL_EXIVAR)) rb_copy_generic_ivar(clone, obj);
-}
-
-static inline void
-rb_dup_setup(VALUE dup, VALUE obj)
-{
- rb_obj_setup(dup, rb_obj_class(obj), RB_FL_TEST_RAW(obj, RUBY_FL_DUPPED));
- if (RB_FL_TEST(obj, RUBY_FL_EXIVAR)) rb_copy_generic_ivar(dup, obj);
-}
-
-static inline long
-rb_array_len(VALUE a)
-{
- return (RBASIC(a)->flags & RARRAY_EMBED_FLAG) ?
- RARRAY_EMBED_LEN(a) : RARRAY(a)->as.heap.len;
-}
-
-#if defined(__fcc__) || defined(__fcc_version) || \
- defined(__FCC__) || defined(__FCC_VERSION)
-/* workaround for old version of Fujitsu C Compiler (fcc) */
-# define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x))
-#else
-# define FIX_CONST_VALUE_PTR(x) (x)
-#endif
-
-/* internal function. do not use this function */
-static inline const VALUE *
-rb_array_const_ptr_transient(VALUE a)
-{
- return FIX_CONST_VALUE_PTR((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ?
- RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr);
-}
-
-/* internal function. do not use this function */
-static inline const VALUE *
-rb_array_const_ptr(VALUE a)
-{
-#if USE_TRANSIENT_HEAP
- void rb_ary_detransient(VALUE a);
-
- if (RARRAY_TRANSIENT_P(a)) {
- rb_ary_detransient(a);
- }
-#endif
- return rb_array_const_ptr_transient(a);
-}
-
-/* internal function. do not use this function */
-static inline VALUE *
-rb_array_ptr_use_start(VALUE a, int allow_transient)
-{
- VALUE *rb_ary_ptr_use_start(VALUE ary);
-
-#if USE_TRANSIENT_HEAP
- if (!allow_transient) {
- if (RARRAY_TRANSIENT_P(a)) {
- void rb_ary_detransient(VALUE a);
- rb_ary_detransient(a);
- }
- }
-#endif
- (void)allow_transient;
-
- return rb_ary_ptr_use_start(a);
-}
-
-/* internal function. do not use this function */
-static inline void
-rb_array_ptr_use_end(VALUE a, int allow_transient)
-{
- void rb_ary_ptr_use_end(VALUE a);
- rb_ary_ptr_use_end(a);
- (void)allow_transient;
-}
-
#if defined(EXTLIB) && defined(USE_DLN_A_OUT)
/* hook for external modules */
static char *dln_libs_to_be_linked[] = { EXTLIB, 0 };
@@ -2239,438 +109,14 @@ static char *dln_libs_to_be_linked[] = { EXTLIB, 0 };
#define HAVE_NATIVETHREAD
int ruby_native_thread_p(void);
-/* traditional set_trace_func events */
-#define RUBY_EVENT_NONE 0x0000
-#define RUBY_EVENT_LINE 0x0001
-#define RUBY_EVENT_CLASS 0x0002
-#define RUBY_EVENT_END 0x0004
-#define RUBY_EVENT_CALL 0x0008
-#define RUBY_EVENT_RETURN 0x0010
-#define RUBY_EVENT_C_CALL 0x0020
-#define RUBY_EVENT_C_RETURN 0x0040
-#define RUBY_EVENT_RAISE 0x0080
-#define RUBY_EVENT_ALL 0x00ff
-
-/* for TracePoint extended events */
-#define RUBY_EVENT_B_CALL 0x0100
-#define RUBY_EVENT_B_RETURN 0x0200
-#define RUBY_EVENT_THREAD_BEGIN 0x0400
-#define RUBY_EVENT_THREAD_END 0x0800
-#define RUBY_EVENT_FIBER_SWITCH 0x1000
-#define RUBY_EVENT_SCRIPT_COMPILED 0x2000
-#define RUBY_EVENT_TRACEPOINT_ALL 0xffff
-
-/* special events */
-#define RUBY_EVENT_RESERVED_FOR_INTERNAL_USE 0x030000
-
-/* internal events */
-#define RUBY_INTERNAL_EVENT_SWITCH 0x040000
-#define RUBY_EVENT_SWITCH 0x040000 /* obsolete name. this macro is for compatibility */
- /* 0x080000 */
-#define RUBY_INTERNAL_EVENT_NEWOBJ 0x100000
-#define RUBY_INTERNAL_EVENT_FREEOBJ 0x200000
-#define RUBY_INTERNAL_EVENT_GC_START 0x400000
-#define RUBY_INTERNAL_EVENT_GC_END_MARK 0x800000
-#define RUBY_INTERNAL_EVENT_GC_END_SWEEP 0x1000000
-#define RUBY_INTERNAL_EVENT_GC_ENTER 0x2000000
-#define RUBY_INTERNAL_EVENT_GC_EXIT 0x4000000
-#define RUBY_INTERNAL_EVENT_OBJSPACE_MASK 0x7f00000
-#define RUBY_INTERNAL_EVENT_MASK 0xffff0000
-
-typedef uint32_t rb_event_flag_t;
-typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass);
-
-#define RB_EVENT_HOOKS_HAVE_CALLBACK_DATA 1
-void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data);
-int rb_remove_event_hook(rb_event_hook_func_t func);
-
-/* locale insensitive functions */
-
-static inline int rb_isascii(int c){ return '\0' <= c && c <= '\x7f'; }
-static inline int rb_isupper(int c){ return 'A' <= c && c <= 'Z'; }
-static inline int rb_islower(int c){ return 'a' <= c && c <= 'z'; }
-static inline int rb_isalpha(int c){ return rb_isupper(c) || rb_islower(c); }
-static inline int rb_isdigit(int c){ return '0' <= c && c <= '9'; }
-static inline int rb_isalnum(int c){ return rb_isalpha(c) || rb_isdigit(c); }
-static inline int rb_isxdigit(int c){ return rb_isdigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f'); }
-static inline int rb_isblank(int c){ return c == ' ' || c == '\t'; }
-static inline int rb_isspace(int c){ return c == ' ' || ('\t' <= c && c <= '\r'); }
-static inline int rb_iscntrl(int c){ return ('\0' <= c && c < ' ') || c == '\x7f'; }
-static inline int rb_isprint(int c){ return ' ' <= c && c <= '\x7e'; }
-static inline int rb_ispunct(int c){ return !rb_isalnum(c); }
-static inline int rb_isgraph(int c){ return '!' <= c && c <= '\x7e'; }
-static inline int rb_tolower(int c) { return rb_isupper(c) ? (c|0x20) : c; }
-static inline int rb_toupper(int c) { return rb_islower(c) ? (c&0x5f) : c; }
-
-#ifndef ISPRINT
-#define ISASCII(c) rb_isascii(c)
-#define ISPRINT(c) rb_isprint(c)
-#define ISGRAPH(c) rb_isgraph(c)
-#define ISSPACE(c) rb_isspace(c)
-#define ISUPPER(c) rb_isupper(c)
-#define ISLOWER(c) rb_islower(c)
-#define ISALNUM(c) rb_isalnum(c)
-#define ISALPHA(c) rb_isalpha(c)
-#define ISDIGIT(c) rb_isdigit(c)
-#define ISXDIGIT(c) rb_isxdigit(c)
-#define ISBLANK(c) rb_isblank(c)
-#define ISCNTRL(c) rb_iscntrl(c)
-#define ISPUNCT(c) rb_ispunct(c)
-#endif
-#define TOUPPER(c) rb_toupper(c)
-#define TOLOWER(c) rb_tolower(c)
-
-int st_locale_insensitive_strcasecmp(const char *s1, const char *s2);
-int st_locale_insensitive_strncasecmp(const char *s1, const char *s2, size_t n);
-#define STRCASECMP(s1, s2) (st_locale_insensitive_strcasecmp((s1), (s2)))
-#define STRNCASECMP(s1, s2, n) (st_locale_insensitive_strncasecmp((s1), (s2), (n)))
-
-unsigned long ruby_strtoul(const char *str, char **endptr, int base);
-#define STRTOUL(str, endptr, base) (ruby_strtoul((str), (endptr), (base)))
-
#define InitVM(ext) {void InitVM_##ext(void);InitVM_##ext();}
PRINTF_ARGS(int ruby_snprintf(char *str, size_t n, char const *fmt, ...), 3, 4);
int ruby_vsnprintf(char *str, size_t n, char const *fmt, va_list ap);
-/* -- Remove In 3.0, Only public for rb_scan_args optimized version -- */
-int rb_empty_keyword_given_p(void);
-
-#if defined(HAVE_BUILTIN___BUILTIN_CHOOSE_EXPR_CONSTANT_P) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__)
-# define rb_scan_args(argc,argvp,fmt,...) \
- __builtin_choose_expr(__builtin_constant_p(fmt), \
- rb_scan_args0(argc,argvp,fmt,\
- (sizeof((VALUE*[]){__VA_ARGS__})/sizeof(VALUE*)), \
- ((VALUE*[]){__VA_ARGS__})), \
- rb_scan_args(argc,argvp,fmt,##__VA_ARGS__))
-# if HAVE_ATTRIBUTE_ERRORFUNC
-ERRORFUNC(("bad scan arg format"), void rb_scan_args_bad_format(const char*));
-ERRORFUNC(("variable argument length doesn't match"), void rb_scan_args_length_mismatch(const char*,int));
-# else
-# define rb_scan_args_bad_format(fmt) ((void)0)
-# define rb_scan_args_length_mismatch(fmt, varc) ((void)0)
-# endif
-
-# define rb_scan_args_isdigit(c) ((unsigned char)((c)-'0')<10)
-
-# define rb_scan_args_count_end(fmt, ofs, vari) \
- (fmt[ofs] ? -1 : (vari))
-
-# define rb_scan_args_count_block(fmt, ofs, vari) \
- (fmt[ofs]!='&' ? \
- rb_scan_args_count_end(fmt, ofs, vari) : \
- rb_scan_args_count_end(fmt, ofs+1, vari+1))
-
-# define rb_scan_args_count_hash(fmt, ofs, vari) \
- (fmt[ofs]!=':' ? \
- rb_scan_args_count_block(fmt, ofs, vari) : \
- rb_scan_args_count_block(fmt, ofs+1, vari+1))
-
-# define rb_scan_args_count_trail(fmt, ofs, vari) \
- (!rb_scan_args_isdigit(fmt[ofs]) ? \
- rb_scan_args_count_hash(fmt, ofs, vari) : \
- rb_scan_args_count_hash(fmt, ofs+1, vari+(fmt[ofs]-'0')))
-
-# define rb_scan_args_count_var(fmt, ofs, vari) \
- (fmt[ofs]!='*' ? \
- rb_scan_args_count_trail(fmt, ofs, vari) : \
- rb_scan_args_count_trail(fmt, ofs+1, vari+1))
-
-# define rb_scan_args_count_opt(fmt, ofs, vari) \
- (!rb_scan_args_isdigit(fmt[ofs]) ? \
- rb_scan_args_count_var(fmt, ofs, vari) : \
- rb_scan_args_count_var(fmt, ofs+1, vari+fmt[ofs]-'0'))
-
-# define rb_scan_args_count_lead(fmt, ofs, vari) \
- (!rb_scan_args_isdigit(fmt[ofs]) ? \
- rb_scan_args_count_var(fmt, ofs, vari) : \
- rb_scan_args_count_opt(fmt, ofs+1, vari+fmt[ofs]-'0'))
-
-# define rb_scan_args_count(fmt) rb_scan_args_count_lead(fmt, 0, 0)
-
-# if defined(__has_attribute) && __has_attribute(diagnose_if)
-# define rb_scan_args_verify(fmt, varc) (void)0
-# else
-# define rb_scan_args_verify(fmt, varc) \
- (sizeof(char[1-2*(rb_scan_args_count(fmt)<0)])!=1 ? \
- rb_scan_args_bad_format(fmt) : \
- sizeof(char[1-2*(rb_scan_args_count(fmt)!=(varc))])!=1 ? \
- rb_scan_args_length_mismatch(fmt, varc) : \
- (void)0)
-# endif
-
-ALWAYS_INLINE(static int rb_scan_args_lead_p(const char *fmt));
-static inline int
-rb_scan_args_lead_p(const char *fmt)
-{
- return rb_scan_args_isdigit(fmt[0]);
-}
-
-ALWAYS_INLINE(static int rb_scan_args_n_lead(const char *fmt));
-static inline int
-rb_scan_args_n_lead(const char *fmt)
-{
- return (rb_scan_args_lead_p(fmt) ? fmt[0]-'0' : 0);
-}
-
-ALWAYS_INLINE(static int rb_scan_args_opt_p(const char *fmt));
-static inline int
-rb_scan_args_opt_p(const char *fmt)
-{
- return (rb_scan_args_lead_p(fmt) && rb_scan_args_isdigit(fmt[1]));
-}
-
-ALWAYS_INLINE(static int rb_scan_args_n_opt(const char *fmt));
-static inline int
-rb_scan_args_n_opt(const char *fmt)
-{
- return (rb_scan_args_opt_p(fmt) ? fmt[1]-'0' : 0);
-}
-
-ALWAYS_INLINE(static int rb_scan_args_var_idx(const char *fmt));
-static inline int
-rb_scan_args_var_idx(const char *fmt)
-{
- return (!rb_scan_args_lead_p(fmt) ? 0 : !rb_scan_args_isdigit(fmt[1]) ? 1 : 2);
-}
-
-ALWAYS_INLINE(static int rb_scan_args_f_var(const char *fmt));
-static inline int
-rb_scan_args_f_var(const char *fmt)
-{
- return (fmt[rb_scan_args_var_idx(fmt)]=='*');
-}
-
-ALWAYS_INLINE(static int rb_scan_args_trail_idx(const char *fmt));
-static inline int
-rb_scan_args_trail_idx(const char *fmt)
-{
- const int idx = rb_scan_args_var_idx(fmt);
- return idx+(fmt[idx]=='*');
-}
-
-ALWAYS_INLINE(static int rb_scan_args_n_trail(const char *fmt));
-static inline int
-rb_scan_args_n_trail(const char *fmt)
-{
- const int idx = rb_scan_args_trail_idx(fmt);
- return (rb_scan_args_isdigit(fmt[idx]) ? fmt[idx]-'0' : 0);
-}
-
-ALWAYS_INLINE(static int rb_scan_args_hash_idx(const char *fmt));
-static inline int
-rb_scan_args_hash_idx(const char *fmt)
-{
- const int idx = rb_scan_args_trail_idx(fmt);
- return idx+rb_scan_args_isdigit(fmt[idx]);
-}
-
-ALWAYS_INLINE(static int rb_scan_args_f_hash(const char *fmt));
-static inline int
-rb_scan_args_f_hash(const char *fmt)
-{
- return (fmt[rb_scan_args_hash_idx(fmt)]==':');
-}
-
-ALWAYS_INLINE(static int rb_scan_args_block_idx(const char *fmt));
-static inline int
-rb_scan_args_block_idx(const char *fmt)
-{
- const int idx = rb_scan_args_hash_idx(fmt);
- return idx+(fmt[idx]==':');
-}
-
-ALWAYS_INLINE(static int rb_scan_args_f_block(const char *fmt));
-static inline int
-rb_scan_args_f_block(const char *fmt)
-{
- return (fmt[rb_scan_args_block_idx(fmt)]=='&');
-}
-
-# if 0
-ALWAYS_INLINE(static int rb_scan_args_end_idx(const char *fmt));
-static inline int
-rb_scan_args_end_idx(const char *fmt)
-{
- const int idx = rb_scan_args_block_idx(fmt);
- return idx+(fmt[idx]=='&');
-}
-# endif
-
-/* NOTE: Use `char *fmt` instead of `const char *fmt` because of clang's bug*/
-/* https://bugs.llvm.org/show_bug.cgi?id=38095 */
-# define rb_scan_args0(argc, argv, fmt, varc, vars) \
- rb_scan_args_set(argc, argv, \
- rb_scan_args_n_lead(fmt), \
- rb_scan_args_n_opt(fmt), \
- rb_scan_args_n_trail(fmt), \
- rb_scan_args_f_var(fmt), \
- rb_scan_args_f_hash(fmt), \
- rb_scan_args_f_block(fmt), \
- (rb_scan_args_verify(fmt, varc), vars), (char *)fmt, varc)
-ALWAYS_INLINE(static int
-rb_scan_args_set(int argc, const VALUE *argv,
- int n_lead, int n_opt, int n_trail,
- int f_var, int f_hash, int f_block,
- VALUE *vars[], char *fmt, int varc));
-
-inline int
-rb_scan_args_set(int argc, const VALUE *argv,
- int n_lead, int n_opt, int n_trail,
- int f_var, int f_hash, int f_block,
- VALUE *vars[], RB_UNUSED_VAR(char *fmt), RB_UNUSED_VAR(int varc))
-# if defined(__has_attribute) && __has_attribute(diagnose_if)
- __attribute__((diagnose_if(rb_scan_args_count(fmt)<0,"bad scan arg format","error")))
- __attribute__((diagnose_if(rb_scan_args_count(fmt)!=varc,"variable argument length doesn't match","error")))
-# endif
-{
- int i, argi = 0, vari = 0, last_idx = -1;
- VALUE *var, hash = Qnil, last_hash = 0;
- const int n_mand = n_lead + n_trail;
- int keyword_given = rb_keyword_given_p();
- int empty_keyword_given = 0;
- VALUE tmp_buffer = 0;
-
- if (!keyword_given) {
- empty_keyword_given = rb_empty_keyword_given_p();
- }
-
- /* capture an option hash - phase 1: pop */
- /* Ignore final positional hash if empty keywords given */
- if (argc > 0 && !(f_hash && empty_keyword_given)) {
- VALUE last = argv[argc - 1];
-
- if (f_hash && n_mand < argc) {
- if (keyword_given) {
- if (!RB_TYPE_P(last, T_HASH)) {
- rb_warn("Keyword flag set when calling rb_scan_args, but last entry is not a hash");
- }
- else {
- hash = last;
- }
- }
- else if (NIL_P(last)) {
- /* For backwards compatibility, nil is taken as an empty
- option hash only if it is not ambiguous; i.e. '*' is
- not specified and arguments are given more than sufficient.
- This will be removed in Ruby 3. */
- if (!f_var && n_mand + n_opt < argc) {
- rb_warn("The last argument is nil, treating as empty keywords");
- argc--;
- }
- }
- else {
- hash = rb_check_hash_type(last);
- }
-
- /* Ruby 3: Remove if branch, as it will not attempt to split hashes */
- if (!NIL_P(hash)) {
- VALUE opts = rb_extract_keywords(&hash);
-
- if (!(last_hash = hash)) {
- if (!keyword_given) {
- /* Warn if treating positional as keyword, as in Ruby 3,
- this will be an error */
- rb_warn("Using the last argument as keyword parameters is deprecated");
- }
- argc--;
- }
- else {
- /* Warn if splitting either positional hash to keywords or keywords
- to positional hash, as in Ruby 3, no splitting will be done */
- rb_warn("The last argument is split into positional and keyword parameters");
- last_idx = argc - 1;
- }
- hash = opts ? opts : Qnil;
- }
- }
- else if (f_hash && keyword_given && n_mand == argc) {
- /* Warn if treating keywords as positional, as in Ruby 3, this will be an error */
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- }
- }
- if (f_hash && n_mand > 0 && n_mand == argc+1 && empty_keyword_given) {
- VALUE *ptr = (VALUE *)rb_alloc_tmp_buffer2(&tmp_buffer, argc+1, sizeof(VALUE));
- memcpy(ptr, argv, sizeof(VALUE)*argc);
- ptr[argc] = rb_hash_new();
- argc++;
- *(&argv) = ptr;
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- }
-
-
- if (argc < n_mand) {
- goto argc_error;
- }
-
- /* capture leading mandatory arguments */
- for (i = n_lead; i-- > 0; ) {
- var = vars[vari++];
- if (var) *var = (argi == last_idx) ? last_hash : argv[argi];
- argi++;
- }
- /* capture optional arguments */
- for (i = n_opt; i-- > 0; ) {
- var = vars[vari++];
- if (argi < argc - n_trail) {
- if (var) *var = (argi == last_idx) ? last_hash : argv[argi];
- argi++;
- }
- else {
- if (var) *var = Qnil;
- }
- }
- /* capture variable length arguments */
- if (f_var) {
- int n_var = argc - argi - n_trail;
-
- var = vars[vari++];
- if (0 < n_var) {
- if (var) {
- int f_last = (last_idx + 1 == argc - n_trail);
- *var = rb_ary_new4(n_var-f_last, &argv[argi]);
- if (f_last) rb_ary_push(*var, last_hash);
- }
- argi += n_var;
- }
- else {
- if (var) *var = rb_ary_new();
- }
- }
- /* capture trailing mandatory arguments */
- for (i = n_trail; i-- > 0; ) {
- var = vars[vari++];
- if (var) *var = (argi == last_idx) ? last_hash : argv[argi];
- argi++;
- }
- /* capture an option hash - phase 2: assignment */
- if (f_hash) {
- var = vars[vari++];
- if (var) *var = hash;
- }
- /* capture iterator block */
- if (f_block) {
- var = vars[vari++];
- if (rb_block_given_p()) {
- *var = rb_block_proc();
- }
- else {
- *var = Qnil;
- }
- }
-
- if (argi < argc) {
- argc_error:
- if (tmp_buffer) rb_free_tmp_buffer(&tmp_buffer);
- rb_error_arity(argc, n_mand, f_var ? UNLIMITED_ARGUMENTS : n_mand + n_opt);
- }
-
- if (tmp_buffer) rb_free_tmp_buffer(&tmp_buffer);
- return argc;
-}
-#endif
-
-#if defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__)
+#if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments")
+# /* Skip it; clang -pedantic doesn't like the following */
+#elif defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO) && defined(__OPTIMIZE__)
# define rb_yield_values(argc, ...) \
__extension__({ \
const int rb_yield_values_argc = (argc); \
@@ -2698,176 +144,10 @@ __extension__({ \
#include "ruby/subst.h"
#endif
-/**
- * @defgroup embed CRuby Embedding APIs
- * CRuby interpreter APIs. These are APIs to embed MRI interpreter into your
- * program.
- * These functions are not a part of Ruby extension library API.
- * Extension libraries of Ruby should not depend on these functions.
- * @{
- */
-
-/** @defgroup ruby1 ruby(1) implementation
- * A part of the implementation of ruby(1) command.
- * Other programs that embed Ruby interpreter do not always need to use these
- * functions.
- * @{
- */
-
-void ruby_sysinit(int *argc, char ***argv);
-void ruby_init(void);
-void* ruby_options(int argc, char** argv);
-int ruby_executable_node(void *n, int *status);
-int ruby_run_node(void *n);
-
-/* version.c */
-void ruby_show_version(void);
-void ruby_show_copyright(void);
-
-
-/*! A convenience macro to call ruby_init_stack(). Must be placed just after
- * variable declarations */
-#define RUBY_INIT_STACK \
- VALUE variable_in_this_stack_frame; \
- ruby_init_stack(&variable_in_this_stack_frame);
-/*! @} */
-
-void ruby_init_stack(volatile VALUE*);
-
-int ruby_setup(void);
-int ruby_cleanup(volatile int);
-
-void ruby_finalize(void);
-NORETURN(void ruby_stop(int));
-
-void ruby_set_stack_size(size_t);
-int ruby_stack_check(void);
-size_t ruby_stack_length(VALUE**);
-
-int ruby_exec_node(void *n);
-
-void ruby_script(const char* name);
-void ruby_set_script_name(VALUE name);
-
-void ruby_prog_init(void);
-void ruby_set_argv(int, char**);
-void *ruby_process_options(int, char**);
-void ruby_init_loadpath(void);
-void ruby_incpush(const char*);
-void ruby_sig_finalize(void);
-
-/*! @} */
-
#if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY
# include "ruby/backward.h"
#endif
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-extern "C++" {
-#endif
-
-#ifdef RB_METHOD_DEFINITION_DECL
-
-RB_METHOD_DEFINITION_DECL(rb_define_method, (2,3), (VALUE klass, const char *name), (klass, name))
-#ifdef __cplusplus
-#define rb_define_method(m, n, f, a) rb_define_method_tmpl<a>::define(m, n, f)
-#else
-#define rb_define_method_if_constexpr(x, t, f) __builtin_choose_expr(__builtin_choose_expr(__builtin_constant_p(x),(x),0),(t),(f))
-#define rb_define_method_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_method15,rb_define_methodm3)
-#define rb_define_method_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_method14,rb_define_method_choose_prototype15(n))
-#define rb_define_method_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_method13,rb_define_method_choose_prototype14(n))
-#define rb_define_method_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_method12,rb_define_method_choose_prototype13(n))
-#define rb_define_method_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_method11,rb_define_method_choose_prototype12(n))
-#define rb_define_method_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_method10,rb_define_method_choose_prototype11(n))
-#define rb_define_method_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_method9, rb_define_method_choose_prototype10(n))
-#define rb_define_method_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_method8, rb_define_method_choose_prototype9(n))
-#define rb_define_method_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_method7, rb_define_method_choose_prototype8(n))
-#define rb_define_method_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_method6, rb_define_method_choose_prototype7(n))
-#define rb_define_method_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_method5, rb_define_method_choose_prototype6(n))
-#define rb_define_method_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_method4, rb_define_method_choose_prototype5(n))
-#define rb_define_method_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_method3, rb_define_method_choose_prototype4(n))
-#define rb_define_method_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_method2, rb_define_method_choose_prototype3(n))
-#define rb_define_method_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_method1, rb_define_method_choose_prototype2(n))
-#define rb_define_method_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_method0, rb_define_method_choose_prototype1(n))
-#define rb_define_method_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_methodm1,rb_define_method_choose_prototype0(n))
-#define rb_define_method_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_methodm2,rb_define_method_choose_prototypem1(n))
-#define rb_define_method_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_methodm3,rb_define_method_choose_prototypem2(n))
-#define rb_define_method(klass, mid, func, arity) rb_define_method_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity));
-#endif
-
-RB_METHOD_DEFINITION_DECL(rb_define_module_function, (2,3), (VALUE klass, const char *name), (klass, name))
-#ifdef __cplusplus
-#define rb_define_module_function(m, n, f, a) rb_define_module_function_tmpl<a>::define(m, n, f)
-#else
-#define rb_define_module_function_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_module_function15,rb_define_module_functionm3)
-#define rb_define_module_function_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_module_function14,rb_define_module_function_choose_prototype15(n))
-#define rb_define_module_function_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_module_function13,rb_define_module_function_choose_prototype14(n))
-#define rb_define_module_function_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_module_function12,rb_define_module_function_choose_prototype13(n))
-#define rb_define_module_function_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_module_function11,rb_define_module_function_choose_prototype12(n))
-#define rb_define_module_function_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_module_function10,rb_define_module_function_choose_prototype11(n))
-#define rb_define_module_function_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_module_function9, rb_define_module_function_choose_prototype10(n))
-#define rb_define_module_function_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_module_function8, rb_define_module_function_choose_prototype9(n))
-#define rb_define_module_function_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_module_function7, rb_define_module_function_choose_prototype8(n))
-#define rb_define_module_function_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_module_function6, rb_define_module_function_choose_prototype7(n))
-#define rb_define_module_function_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_module_function5, rb_define_module_function_choose_prototype6(n))
-#define rb_define_module_function_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_module_function4, rb_define_module_function_choose_prototype5(n))
-#define rb_define_module_function_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_module_function3, rb_define_module_function_choose_prototype4(n))
-#define rb_define_module_function_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_module_function2, rb_define_module_function_choose_prototype3(n))
-#define rb_define_module_function_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_module_function1, rb_define_module_function_choose_prototype2(n))
-#define rb_define_module_function_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_module_function0, rb_define_module_function_choose_prototype1(n))
-#define rb_define_module_function_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_module_functionm1,rb_define_module_function_choose_prototype0(n))
-#define rb_define_module_function_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_module_functionm2,rb_define_module_function_choose_prototypem1(n))
-#define rb_define_module_function_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_module_functionm3,rb_define_module_function_choose_prototypem2(n))
-#define rb_define_module_function(klass, mid, func, arity) rb_define_module_function_choose_prototypem3((arity),(func))((klass),(mid),(func),(arity));
-#endif
-
-RB_METHOD_DEFINITION_DECL(rb_define_global_function, (1,2), (const char *name), (name))
-#ifdef __cplusplus
-#define rb_define_global_function(n, f, a) rb_define_global_function_tmpl<a>::define(n, f)
-#else
-#define rb_define_global_function_choose_prototype15(n) rb_define_method_if_constexpr((n)==15,rb_define_global_function15,rb_define_global_functionm3)
-#define rb_define_global_function_choose_prototype14(n) rb_define_method_if_constexpr((n)==14,rb_define_global_function14,rb_define_global_function_choose_prototype15(n))
-#define rb_define_global_function_choose_prototype13(n) rb_define_method_if_constexpr((n)==13,rb_define_global_function13,rb_define_global_function_choose_prototype14(n))
-#define rb_define_global_function_choose_prototype12(n) rb_define_method_if_constexpr((n)==12,rb_define_global_function12,rb_define_global_function_choose_prototype13(n))
-#define rb_define_global_function_choose_prototype11(n) rb_define_method_if_constexpr((n)==11,rb_define_global_function11,rb_define_global_function_choose_prototype12(n))
-#define rb_define_global_function_choose_prototype10(n) rb_define_method_if_constexpr((n)==10,rb_define_global_function10,rb_define_global_function_choose_prototype11(n))
-#define rb_define_global_function_choose_prototype9(n) rb_define_method_if_constexpr((n)== 9,rb_define_global_function9, rb_define_global_function_choose_prototype10(n))
-#define rb_define_global_function_choose_prototype8(n) rb_define_method_if_constexpr((n)== 8,rb_define_global_function8, rb_define_global_function_choose_prototype9(n))
-#define rb_define_global_function_choose_prototype7(n) rb_define_method_if_constexpr((n)== 7,rb_define_global_function7, rb_define_global_function_choose_prototype8(n))
-#define rb_define_global_function_choose_prototype6(n) rb_define_method_if_constexpr((n)== 6,rb_define_global_function6, rb_define_global_function_choose_prototype7(n))
-#define rb_define_global_function_choose_prototype5(n) rb_define_method_if_constexpr((n)== 5,rb_define_global_function5, rb_define_global_function_choose_prototype6(n))
-#define rb_define_global_function_choose_prototype4(n) rb_define_method_if_constexpr((n)== 4,rb_define_global_function4, rb_define_global_function_choose_prototype5(n))
-#define rb_define_global_function_choose_prototype3(n) rb_define_method_if_constexpr((n)== 3,rb_define_global_function3, rb_define_global_function_choose_prototype4(n))
-#define rb_define_global_function_choose_prototype2(n) rb_define_method_if_constexpr((n)== 2,rb_define_global_function2, rb_define_global_function_choose_prototype3(n))
-#define rb_define_global_function_choose_prototype1(n) rb_define_method_if_constexpr((n)== 1,rb_define_global_function1, rb_define_global_function_choose_prototype2(n))
-#define rb_define_global_function_choose_prototype0(n) rb_define_method_if_constexpr((n)== 0,rb_define_global_function0, rb_define_global_function_choose_prototype1(n))
-#define rb_define_global_function_choose_prototypem1(n) rb_define_method_if_constexpr((n)==-1,rb_define_global_functionm1,rb_define_global_function_choose_prototype0(n))
-#define rb_define_global_function_choose_prototypem2(n) rb_define_method_if_constexpr((n)==-2,rb_define_global_functionm2,rb_define_global_function_choose_prototypem1(n))
-#define rb_define_global_function_choose_prototypem3(n, f) rb_define_method_if_constexpr(rb_f_notimplement_p(f),rb_define_global_functionm3,rb_define_global_function_choose_prototypem2(n))
-#define rb_define_global_function(mid, func, arity) rb_define_global_function_choose_prototypem3((arity),(func))((mid),(func),(arity));
-#endif
-
-#endif
-
-#if defined(RUBY_DEVEL) && RUBY_DEVEL && (!defined(__cplusplus) || defined(RB_METHOD_DEFINITION_DECL))
-# define RUBY_METHOD_FUNC(func) (func)
-#else
-# define RUBY_METHOD_FUNC(func) ((VALUE (*)(ANYARGS))(func))
-#endif
-
-#ifdef __cplusplus
-#include "backward/cxxanyargs.hpp"
-
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C++" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_RUBY_H */
diff --git a/include/ruby/st.h b/include/ruby/st.h
index ea1637bd9f..1e4bb80686 100644
--- a/include/ruby/st.h
+++ b/include/ruby/st.h
@@ -1,7 +1,7 @@
/* This is a public domain general purpose hash table package
originally written by Peter Moore @ UCB.
- The hash table data strutures were redesigned and the package was
+ The hash table data structures were redesigned and the package was
rewritten by Vladimir Makarov <vmakarov@redhat.com>. */
#ifndef RUBY_ST_H
diff --git a/include/ruby/subst.h b/include/ruby/subst.h
index 1f0e6db5a4..cf48a3909c 100644
--- a/include/ruby/subst.h
+++ b/include/ruby/subst.h
@@ -1,5 +1,13 @@
-#ifndef RUBY_SUBST_H
+#ifndef RUBY_SUBST_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_SUBST_H 1
+/**
+ * @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.
+ */
#undef snprintf
#undef vsnprintf
diff --git a/include/ruby/thread.h b/include/ruby/thread.h
index d398cc127e..b05537badb 100644
--- a/include/ruby/thread.h
+++ b/include/ruby/thread.h
@@ -1,31 +1,23 @@
-/**********************************************************************
-
- thread.h -
-
- $Author: matz $
- created at: Tue Jul 10 17:35:43 JST 2012
-
- Copyright (C) 2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_THREAD_H
+#ifndef RUBY_THREAD_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_THREAD_H 1
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
+/**
+ * @file
+ * @author $Author: matz $
+ * @date Tue Jul 10 17:35:43 JST 2012
+ * @copyright Copyright (C) 2007 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
#include "ruby/intern.h"
+#include "ruby/internal/dllexport.h"
/* flags for rb_nogvl */
#define RB_NOGVL_INTR_FAIL (0x1)
#define RB_NOGVL_UBF_ASYNC_SAFE (0x2)
-RUBY_SYMBOL_EXPORT_BEGIN
+RBIMPL_SYMBOL_EXPORT_BEGIN()
void *rb_thread_call_with_gvl(void *(*func)(void *), void *data1);
@@ -45,13 +37,6 @@ void *rb_nogvl(void *(*func)(void *), void *data1,
#define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_AFTER 0x01
#define RUBY_CALL_WO_GVL_FLAG_SKIP_CHECK_INTS_
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_THREAD_H */
diff --git a/include/ruby/thread_native.h b/include/ruby/thread_native.h
index 8e500c5a13..7e08c2e97f 100644
--- a/include/ruby/thread_native.h
+++ b/include/ruby/thread_native.h
@@ -1,22 +1,21 @@
-/**********************************************************************
-
- thread_native.h -
-
- $Author: ko1 $
- created at: Wed May 14 19:37:31 2014
-
- Copyright (C) 2014 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_THREAD_NATIVE_H
+#ifndef RUBY_THREAD_NATIVE_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_THREAD_NATIVE_H 1
+/**
+ * @file
+ * @author $Author: ko1 $
+ * @date Wed May 14 19:37:31 2014
+ * @copyright Copyright (C) 2014 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
/*
* This file contains wrapper APIs for native thread primitives
* which Ruby interpreter uses.
*
- * Now, we only suppors pthread and Windows threads.
+ * Now, we only support pthread and Windows threads.
*
* If you want to use Ruby's Mutex and so on to synchronize Ruby Threads,
* please use Mutex directly.
@@ -32,10 +31,14 @@ typedef union rb_thread_lock_union {
CRITICAL_SECTION crit;
} rb_nativethread_lock_t;
+typedef struct rb_thread_cond_struct rb_nativethread_cond_t;
+
#elif defined(HAVE_PTHREAD_H)
+
#include <pthread.h>
typedef pthread_t rb_nativethread_id_t;
typedef pthread_mutex_t rb_nativethread_lock_t;
+typedef pthread_cond_t rb_nativethread_cond_t;
#else
#error "unsupported thread type"
@@ -51,6 +54,19 @@ void rb_nativethread_lock_destroy(rb_nativethread_lock_t *lock);
void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock);
void rb_nativethread_lock_unlock(rb_nativethread_lock_t *lock);
+void rb_native_mutex_lock(rb_nativethread_lock_t *lock);
+int rb_native_mutex_trylock(rb_nativethread_lock_t *lock);
+void rb_native_mutex_unlock(rb_nativethread_lock_t *lock);
+void rb_native_mutex_initialize(rb_nativethread_lock_t *lock);
+void rb_native_mutex_destroy(rb_nativethread_lock_t *lock);
+
+void rb_native_cond_signal(rb_nativethread_cond_t *cond);
+void rb_native_cond_broadcast(rb_nativethread_cond_t *cond);
+void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex);
+void rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec);
+void rb_native_cond_initialize(rb_nativethread_cond_t *cond);
+void rb_native_cond_destroy(rb_nativethread_cond_t *cond);
+
RUBY_SYMBOL_EXPORT_END
#endif
diff --git a/include/ruby/util.h b/include/ruby/util.h
index 3fecba8ebc..af022dacbd 100644
--- a/include/ruby/util.h
+++ b/include/ruby/util.h
@@ -1,51 +1,20 @@
-/**********************************************************************
-
- util.h -
-
- $Author$
- created at: Thu Mar 9 11:55:53 JST 1995
-
- Copyright (C) 1993-2007 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_UTIL_H
+#ifndef RUBY_UTIL_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_UTIL_H 1
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
+/**
+ * @file
+ * @author $Author$
+ * @date Thu Mar 9 11:55:53 JST 1995
+ * @copyright Copyright (C) 1993-2007 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#include "ruby/internal/config.h"
+#include "ruby/internal/dllexport.h"
#include "ruby/defines.h"
-#ifdef RUBY_EXTCONF_H
-#include RUBY_EXTCONF_H
-#endif
-#ifndef _
-#ifdef __cplusplus
-# ifndef HAVE_PROTOTYPES
-# define HAVE_PROTOTYPES 1
-# endif
-# ifndef HAVE_STDARG_PROTOTYPES
-# define HAVE_STDARG_PROTOTYPES 1
-# endif
-#endif
-#ifdef HAVE_PROTOTYPES
-# define _(args) args
-#else
-# define _(args) ()
-#endif
-#ifdef HAVE_STDARG_PROTOTYPES
-# define __(args) args
-#else
-# define __(args) ()
-#endif
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
+RBIMPL_SYMBOL_EXPORT_BEGIN()
#define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999)
/* an approximation of ceil(n * log10(2)), up to 65536 at least */
@@ -77,13 +46,6 @@ double ruby_strtod(const char *, char **);
void ruby_each_words(const char *, void (*)(const char*, int, void*), void *);
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_UTIL_H */
diff --git a/include/ruby/version.h b/include/ruby/version.h
index 64c5c614e0..924bfa8f91 100644
--- a/include/ruby/version.h
+++ b/include/ruby/version.h
@@ -1,17 +1,17 @@
-/**********************************************************************
-
- ruby/version.h -
-
- $Author$
- created at: Wed May 13 12:56:56 JST 2009
-
- Copyright (C) 1993-2009 Yukihiro Matsumoto
- Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
- Copyright (C) 2000 Information-technology Promotion Agency, Japan
-
-**********************************************************************/
-
-/*
+#ifndef RUBY_VERSION_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RUBY_VERSION_H 1
+/**
+ * @file
+ * @author $Author$
+ * @date Wed May 13 12:56:56 JST 2009
+ * @copyright Copyright (C) 1993-2009 Yukihiro Matsumoto
+ * @copyright Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ * @copyright Copyright (C) 2000 Information-technology Promotion Agency, Japan
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ *
* This file contains only
* - never-changeable information, and
* - interfaces accessible from extension libraries.
@@ -20,9 +20,6 @@
* check the features with mkmf.rb instead.
*/
-#ifndef RUBY_VERSION_H
-#define RUBY_VERSION_H 1
-
/* The origin. */
#define RUBY_AUTHOR "Yukihiro Matsumoto"
#define RUBY_BIRTH_YEAR 1993
@@ -30,20 +27,16 @@
#define RUBY_BIRTH_DAY 24
/* API version */
-#define RUBY_API_VERSION_MAJOR 2
-#define RUBY_API_VERSION_MINOR 7
+#define RUBY_API_VERSION_MAJOR 3
+#define RUBY_API_VERSION_MINOR 0
#define RUBY_API_VERSION_TEENY 0
#define RUBY_API_VERSION_CODE (RUBY_API_VERSION_MAJOR*10000+RUBY_API_VERSION_MINOR*100+RUBY_API_VERSION_TEENY)
#ifdef RUBY_EXTERN
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
+/* Internal note: this file could be included from verconf.mk _before_
+ * generating config.h, on Windows. The #ifdef above is to trick such
+ * situation. */
+RBIMPL_SYMBOL_EXPORT_BEGIN()
/*
* Interfaces from extension libraries.
@@ -61,14 +54,7 @@ RUBY_EXTERN const char ruby_description[];
RUBY_EXTERN const char ruby_copyright[];
RUBY_EXTERN const char ruby_engine[];
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif
#endif
diff --git a/include/ruby/vm.h b/include/ruby/vm.h
index b137a280c9..7bdd567453 100644
--- a/include/ruby/vm.h
+++ b/include/ruby/vm.h
@@ -1,25 +1,18 @@
-/**********************************************************************
-
- ruby/vm.h -
-
- $Author$
- created at: Sat May 31 15:17:36 2008
-
- Copyright (C) 2008 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_VM_H
+#ifndef RUBY_VM_H /*-*-C++-*-vi:se ft=cpp:*/
#define RUBY_VM_H 1
+/**
+ * @file
+ * @author $Author$
+ * @date Sat May 31 15:17:36 2008
+ * @copyright Copyright (C) 2008 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#include "ruby/internal/dllexport.h"
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
+RBIMPL_SYMBOL_EXPORT_BEGIN()
/* Place holder.
*
@@ -51,13 +44,6 @@ int ruby_vm_destruct(ruby_vm_t *vm);
*/
void ruby_vm_at_exit(void(*func)(ruby_vm_t *));
-RUBY_SYMBOL_EXPORT_END
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
+RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_VM_H */
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index b29470b0c4..00259485a2 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -138,18 +138,18 @@ typedef int clockid_t;
#undef stat
#undef fstat
#ifdef RUBY_EXPORT
-#define utime(_p, _t) rb_w32_utime(_p, _t)
+#define utime(_p, _t) rb_w32_uutime(_p, _t)
#undef HAVE_UTIMES
#define HAVE_UTIMES 1
-#define utimes(_p, _t) rb_w32_utimes(_p, _t)
+#define utimes(_p, _t) rb_w32_uutimes(_p, _t)
#undef HAVE_UTIMENSAT
#define HAVE_UTIMENSAT 1
#define AT_FDCWD -100
-#define utimensat(_d, _p, _t, _f) rb_w32_utimensat(_d, _p, _t, _f)
+#define utimensat(_d, _p, _t, _f) rb_w32_uutimensat(_d, _p, _t, _f)
#define lseek(_f, _o, _w) rb_w32_lseek(_f, _o, _w)
#define pipe(p) rb_w32_pipe(p)
-#define open rb_w32_open
+#define open rb_w32_uopen
#define close(h) rb_w32_close(h)
#define fclose(f) rb_w32_fclose(f)
#define read(f, b, s) rb_w32_read(f, b, s)
@@ -160,16 +160,16 @@ typedef int clockid_t;
#define Sleep(msec) (void)rb_w32_Sleep(msec)
#undef execv
-#define execv(path,argv) rb_w32_aspawn(P_OVERLAY,path,argv)
+#define execv(path,argv) rb_w32_uaspawn(P_OVERLAY,path,argv)
#undef isatty
#define isatty(h) rb_w32_isatty(h)
#undef mkdir
-#define mkdir(p, m) rb_w32_mkdir(p, m)
+#define mkdir(p, m) rb_w32_umkdir(p, m)
#undef rmdir
-#define rmdir(p) rb_w32_rmdir(p)
+#define rmdir(p) rb_w32_urmdir(p)
#undef unlink
-#define unlink(p) rb_w32_unlink(p)
+#define unlink(p) rb_w32_uunlink(p)
#endif /* RUBY_EXPORT */
/* same with stati64 except the size of st_ino and nanosecond timestamps */
@@ -191,7 +191,6 @@ struct stati128 {
long st_ctimensec;
};
-#if SIZEOF_OFF_T == 8
#define off_t __int64
#define stat stati128
#undef SIZEOF_STRUCT_STAT_ST_INO
@@ -201,15 +200,9 @@ struct stati128 {
#define HAVE_STRUCT_STAT_ST_MTIMENSEC
#define HAVE_STRUCT_STAT_ST_CTIMENSEC
#define fstat(fd,st) rb_w32_fstati128(fd,st)
-#define stati128(path, st) rb_w32_stati128(path,st)
-#else
-#define stat(path,st) rb_w32_stat(path,st)
-#define fstat(fd,st) rb_w32_fstat(fd,st)
-extern int rb_w32_stat(const char *, struct stat *);
-extern int rb_w32_fstat(int, struct stat *);
-#endif
-#define lstat(path,st) rb_w32_lstati128(path,st)
-#define access(path,mode) rb_w32_access(path,mode)
+#define stati128(path, st) rb_w32_ustati128(path,st)
+#define lstat(path,st) rb_w32_ulstati128(path,st)
+#define access(path,mode) rb_w32_uaccess(path,mode)
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
@@ -258,7 +251,6 @@ struct ifaddrs {
extern void rb_w32_sysinit(int *, char ***);
extern DWORD rb_w32_osid(void);
-extern rb_pid_t rb_w32_pipe_exec(const char *, const char *, int, int *, int *);
extern int flock(int fd, int oper);
extern int rb_w32_io_cancelable_p(int);
extern int rb_w32_is_socket(int);
@@ -294,10 +286,8 @@ extern struct servent *WSAAPI rb_w32_getservbyport(int, const char *);
extern int socketpair(int, int, int, int *);
extern int getifaddrs(struct ifaddrs **);
extern void freeifaddrs(struct ifaddrs *);
-extern char * rb_w32_getcwd(char *, int);
+extern char * rb_w32_ugetcwd(char *, int);
extern char * rb_w32_ugetenv(const char *);
-extern char * rb_w32_getenv(const char *);
-extern int rb_w32_rename(const char *, const char *);
extern int rb_w32_urename(const char *, const char *);
extern char **rb_w32_get_environ(void);
extern void rb_w32_free_environ(char **);
@@ -306,22 +296,15 @@ extern const char *WSAAPI rb_w32_inet_ntop(int,const void *,char *,size_t);
extern int WSAAPI rb_w32_inet_pton(int,const char *,void *);
extern DWORD rb_w32_osver(void);
-extern int chown(const char *, int, int);
extern int rb_w32_uchown(const char *, int, int);
-extern int link(const char *, const char *);
extern int rb_w32_ulink(const char *, const char *);
-extern ssize_t readlink(const char *, char *, size_t);
extern ssize_t rb_w32_ureadlink(const char *, char *, size_t);
extern ssize_t rb_w32_wreadlink(const WCHAR *, WCHAR *, size_t);
-extern int symlink(const char *src, const char *link);
extern int rb_w32_usymlink(const char *src, const char *link);
extern int gettimeofday(struct timeval *, struct timezone *);
extern int clock_gettime(clockid_t, struct timespec *);
extern int clock_getres(clockid_t, struct timespec *);
extern rb_pid_t waitpid (rb_pid_t, int *, int);
-extern rb_pid_t rb_w32_spawn(int, const char *, const char*);
-extern rb_pid_t rb_w32_aspawn(int, const char *, char *const *);
-extern rb_pid_t rb_w32_aspawn_flags(int, const char *, char *const *, DWORD);
extern rb_pid_t rb_w32_uspawn(int, const char *, const char*);
extern rb_pid_t rb_w32_uaspawn(int, const char *, char *const *);
extern rb_pid_t rb_w32_uaspawn_flags(int, const char *, char *const *, DWORD);
@@ -332,18 +315,12 @@ extern rb_pid_t rb_w32_getpid(void);
extern rb_pid_t rb_w32_getppid(void);
extern int rb_w32_isatty(int);
extern int rb_w32_uchdir(const char *);
-extern int rb_w32_mkdir(const char *, int);
extern int rb_w32_umkdir(const char *, int);
-extern int rb_w32_rmdir(const char *);
extern int rb_w32_urmdir(const char *);
-extern int rb_w32_unlink(const char *);
extern int rb_w32_uunlink(const char *);
extern int rb_w32_uchmod(const char *, int);
-extern int rb_w32_stati128(const char *, struct stati128 *);
extern int rb_w32_ustati128(const char *, struct stati128 *);
-extern int rb_w32_lstati128(const char *, struct stati128 *);
extern int rb_w32_ulstati128(const char *, struct stati128 *);
-extern int rb_w32_access(const char *, int);
extern int rb_w32_uaccess(const char *, int);
extern char rb_w32_fd_is_text(int);
extern int rb_w32_fstati128(int, struct stati128 *);
@@ -441,11 +418,7 @@ extern int rb_w32_utruncate(const char *path, off_t length);
#undef HAVE_TRUNCATE
#define HAVE_TRUNCATE 1
-#if defined HAVE_TRUNCATE64
-#define truncate truncate64
-#else
-#define truncate rb_w32_truncate
-#endif
+#define truncate rb_w32_utruncate
#if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1800
#define strtoll _strtoi64
@@ -714,13 +687,13 @@ extern char *rb_w32_strerror(int);
#define get_osfhandle(h) rb_w32_get_osfhandle(h)
#undef getcwd
-#define getcwd(b, s) rb_w32_getcwd(b, s)
+#define getcwd(b, s) rb_w32_ugetcwd(b, s)
#undef getenv
-#define getenv(n) rb_w32_getenv(n)
+#define getenv(n) rb_w32_ugetenv(n)
#undef rename
-#define rename(o, n) rb_w32_rename(o, n)
+#define rename(o, n) rb_w32_urename(o, n)
#undef times
#define times(t) rb_w32_times(t)
@@ -743,7 +716,6 @@ struct tm *localtime_r(const time_t *, struct tm *);
/* thread stuff */
int rb_w32_sleep(unsigned long msec);
-int rb_w32_open(const char *, int, ...);
int rb_w32_uopen(const char *, int, ...);
int rb_w32_wopen(const WCHAR *, int, ...);
int rb_w32_close(int);
@@ -752,11 +724,8 @@ int rb_w32_pipe(int[2]);
ssize_t rb_w32_read(int, void *, size_t);
ssize_t rb_w32_write(int, const void *, size_t);
off_t rb_w32_lseek(int, off_t, int);
-int rb_w32_utime(const char *, const struct utimbuf *);
int rb_w32_uutime(const char *, const struct utimbuf *);
-int rb_w32_utimes(const char *, const struct timeval *);
int rb_w32_uutimes(const char *, const struct timeval *);
-int rb_w32_utimensat(int /* must be AT_FDCWD */, const char *, const struct timespec *, int /* must be 0 */);
int rb_w32_uutimensat(int /* must be AT_FDCWD */, const char *, const struct timespec *, int /* must be 0 */);
long rb_w32_write_console(uintptr_t, int); /* use uintptr_t instead of VALUE because it's not defined yet here */
int WINAPI rb_w32_Sleep(unsigned long msec);
@@ -767,6 +736,27 @@ int rb_w32_unwrap_io_handle(int);
WCHAR *rb_w32_mbstr_to_wstr(UINT, const char *, int, long *);
char *rb_w32_wstr_to_mbstr(UINT, const WCHAR *, int, long *);
+DEPRECATED_BY(rb_w32_ugetcwd, char *rb_w32_getcwd(char *, int));
+DEPRECATED_BY(rb_w32_ugetenv, char *rb_w32_getenv(const char *));
+DEPRECATED_BY(rb_w32_urename, int rb_w32_rename(const char *, const char *));
+DEPRECATED_BY(rb_w32_uopen, int rb_w32_open(const char *, int, ...));
+DEPRECATED_BY(rb_w32_uchown, int chown(const char *, int, int));
+DEPRECATED_BY(rb_w32_ulink, int link(const char *, const char *));
+DEPRECATED_BY(rb_w32_ureadlink, ssize_t readlink(const char *, char *, size_t));
+DEPRECATED_BY(rb_w32_usymlink, int symlink(const char *src, const char *link));
+DEPRECATED_BY(rb_w32_umkdir, int rb_w32_mkdir(const char *, int));
+DEPRECATED_BY(rb_w32_urmdir, int rb_w32_rmdir(const char *));
+DEPRECATED_BY(rb_w32_uunlink, int rb_w32_unlink(const char *));
+DEPRECATED_BY(rb_w32_uutime, int rb_w32_utime(const char *, const struct utimbuf *));
+DEPRECATED_BY(rb_w32_uutimes, int rb_w32_utimes(const char *, const struct timeval *));
+DEPRECATED_BY(rb_w32_uutimensat, int rb_w32_utimensat(int, const char *, const struct timespec *, int));
+DEPRECATED_BY(rb_w32_ustati128, int rb_w32_stati128(const char *, struct stati128 *));
+DEPRECATED_BY(rb_w32_ulstati128, int rb_w32_lstati128(const char *, struct stati128 *));
+DEPRECATED_BY(rb_w32_uaccess, int rb_w32_access(const char *, int));
+DEPRECATED_BY(rb_w32_uspawn, rb_pid_t rb_w32_spawn(int, const char *, const char*));
+DEPRECATED_BY(rb_w32_uaspawn, rb_pid_t rb_w32_aspawn(int, const char *, char *const *));
+DEPRECATED_BY(rb_w32_uaspawn_flags, rb_pid_t rb_w32_aspawn_flags(int, const char *, char *const *, DWORD));
+
/*
== ***CAUTION***
Since this function is very dangerous, ((*NEVER*))
diff --git a/inits.c b/inits.c
index 79a6cf014e..f636748101 100644
--- a/inits.c
+++ b/inits.c
@@ -9,8 +9,10 @@
**********************************************************************/
-#include "internal.h"
+#include "internal/inits.h"
+#include "ruby.h"
#include "builtin.h"
+static void Init_builtin_prelude(void);
#include "prelude.rbinc"
#define CALL(n) {void Init_##n(void); Init_##n();}
@@ -18,6 +20,7 @@
void
rb_call_inits(void)
{
+ CALL(Thread_Mutex);
#if USE_TRANSIENT_HEAP
CALL(TransientHeap);
#endif
@@ -35,7 +38,6 @@ rb_call_inits(void)
CALL(String);
CALL(Exception);
CALL(eval);
- CALL(safe);
CALL(jump);
CALL(Numeric);
CALL(Bignum);
@@ -44,6 +46,7 @@ rb_call_inits(void)
CALL(Hash);
CALL(Struct);
CALL(Regexp);
+ CALL(pack);
CALL(transcode);
CALL(marshal);
CALL(Range);
@@ -56,27 +59,43 @@ rb_call_inits(void)
CALL(Proc);
CALL(Binding);
CALL(Math);
+ CALL(GC);
CALL(Enumerator);
+ CALL(Ractor);
CALL(VM);
CALL(ISeq);
CALL(Thread);
+ CALL(Scheduler);
CALL(process);
CALL(Cont);
CALL(Rational);
CALL(Complex);
+ CALL(MemoryView);
CALL(version);
+ CALL(vm_trace);
CALL(vm_stack_canary);
+ CALL(ast);
CALL(gc_stress);
// enable builtin loading
CALL(builtin);
+}
- CALL(GC);
- CALL(IO_nonblock);
- CALL(ast);
- CALL(vm_trace);
- CALL(pack);
- CALL(warning);
- load_prelude();
+void
+rb_call_builtin_inits(void)
+{
+#define BUILTIN(n) CALL(builtin_##n)
+ BUILTIN(gc);
+ BUILTIN(ractor);
+ BUILTIN(integer);
+ BUILTIN(io);
+ BUILTIN(dir);
+ BUILTIN(ast);
+ BUILTIN(trace_point);
+ BUILTIN(pack);
+ BUILTIN(warning);
+ BUILTIN(array);
+ BUILTIN(kernel);
+ Init_builtin_prelude();
}
#undef CALL
diff --git a/insns.def b/insns.def
index 71b9f44072..51e130786b 100644
--- a/insns.def
+++ b/insns.def
@@ -210,10 +210,10 @@ getinstancevariable
(ID id, IVC ic)
()
(VALUE val)
-/* "instance variable not initialized" warning can be hooked. */
-// attr bool leaf = false; /* has rb_warning() */
+/* Ractor crashes when it accesses class/module-level instances variables. */
+// attr bool leaf = false; /* has IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() */
{
- val = vm_getinstancevariable(GET_SELF(), id, ic);
+ val = vm_getinstancevariable(GET_ISEQ(), GET_SELF(), id, ic);
}
/* Set value of instance variable id of self to val. */
@@ -224,7 +224,7 @@ setinstancevariable
()
// attr bool leaf = false; /* has rb_check_frozen_internal() */
{
- vm_setinstancevariable(GET_SELF(), id, val, ic);
+ vm_setinstancevariable(GET_ISEQ(), GET_SELF(), id, val, ic);
}
/* Get value of class variable id of klass as val. */
@@ -236,7 +236,7 @@ getclassvariable
/* "class variable access from toplevel" warning can be hooked. */
// attr bool leaf = false; /* has rb_warning() */
{
- val = rb_cvar_get(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP()), id);
+ val = rb_cvar_get(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP(), 1), id);
}
/* Set value of class variable id of klass as val. */
@@ -249,7 +249,7 @@ setclassvariable
// attr bool leaf = false; /* has rb_warning() */
{
vm_ensure_not_refinement_module(GET_SELF());
- rb_cvar_set(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP()), id, val);
+ rb_cvar_set(vm_get_cvar_base(vm_get_cref(GET_EP()), GET_CFP(), 1), id, val);
}
/* Get constant variable id. If klass is Qnil and allow_nil is Qtrue, constants
@@ -288,25 +288,23 @@ setconstant
/* get global variable id. */
DEFINE_INSN
getglobal
-(GENTRY entry)
+(ID gid)
()
(VALUE val)
-// attr bool leaf = leafness_of_getglobal(entry);
+// attr bool leaf = false;
{
- struct rb_global_entry *gentry = (void *)entry;
- val = rb_gvar_get(gentry);
+ val = rb_gvar_get(gid);
}
/* set global variable id as val. */
DEFINE_INSN
setglobal
-(GENTRY entry)
+(ID gid)
(VALUE val)
()
-// attr bool leaf = leafness_of_setglobal(entry);
+// attr bool leaf = false;
{
- struct rb_global_entry *gentry = (void *)entry;
- rb_gvar_set(gentry, val);
+ rb_gvar_set(gid, val);
}
/**********************************************************/
@@ -365,7 +363,7 @@ putstring
()
(VALUE val)
{
- val = rb_str_resurrect(str);
+ val = rb_ec_str_resurrect(ec, str);
}
/* put concatenate strings */
@@ -375,7 +373,7 @@ concatstrings
(...)
(VALUE val)
/* This instruction can concat UTF-8 and binary strings, resulting in
- * Encoding::CompatiblityError. */
+ * Encoding::CompatibilityError. */
// attr bool leaf = false; /* has rb_enc_cr_str_buf_cat() */
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
{
@@ -392,16 +390,6 @@ tostring
val = rb_obj_as_string_result(str, val);
}
-/* Freeze (dynamically) created strings. if debug_info is given, set it. */
-DEFINE_INSN
-freezestring
-(VALUE debug_info)
-(VALUE str)
-(VALUE str)
-{
- vm_freezestring(str, debug_info);
-}
-
/* compile str to Regexp and push it.
opt is the option for the Regexp.
*/
@@ -438,7 +426,7 @@ newarray
(VALUE val)
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
{
- val = rb_ary_new4(num, STACK_ADDR_FROM_TOP(num));
+ val = rb_ec_ary_new_from_values(ec, num, STACK_ADDR_FROM_TOP(num));
}
/* put new array initialized with num values on the stack. There
@@ -775,11 +763,11 @@ send
(CALL_DATA cd, ISEQ blockiseq)
(...)
(VALUE val)
-// attr rb_snum_t sp_inc = sp_inc_of_sendish(&cd->ci);
+// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
{
- VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), &cd->ci, blockiseq, false);
- val = vm_sendish(ec, GET_CFP(), cd, bh, vm_search_method_wrap);
+ VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, false);
+ val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
if (val == Qundef) {
RESTORE_REGS();
@@ -794,11 +782,11 @@ opt_send_without_block
(...)
(VALUE val)
// attr bool handles_sp = true;
-// attr rb_snum_t sp_inc = sp_inc_of_sendish(&cd->ci);
+// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
{
VALUE bh = VM_BLOCK_HANDLER_NONE;
- val = vm_sendish(ec, GET_CFP(), cd, bh, vm_search_method_wrap);
+ val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_method);
if (val == Qundef) {
RESTORE_REGS();
@@ -827,7 +815,7 @@ opt_nil_p
(VALUE recv)
(VALUE val)
{
- val = vm_opt_nil_p(cd, recv);
+ val = vm_opt_nil_p(GET_ISEQ(), cd, recv);
if (val == Qundef) {
CALL_SIMPLE_METHOD();
@@ -881,11 +869,11 @@ invokesuper
(CALL_DATA cd, ISEQ blockiseq)
(...)
(VALUE val)
-// attr rb_snum_t sp_inc = sp_inc_of_sendish(&cd->ci);
+// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
{
- VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), &cd->ci, blockiseq, true);
- val = vm_sendish(ec, GET_CFP(), cd, bh, vm_search_super_method);
+ VALUE bh = vm_caller_setup_arg_block(ec, GET_CFP(), cd->ci, blockiseq, true);
+ val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_super);
if (val == Qundef) {
RESTORE_REGS();
@@ -900,15 +888,11 @@ invokeblock
(...)
(VALUE val)
// attr bool handles_sp = true;
-// attr rb_snum_t sp_inc = sp_inc_of_invokeblock(&cd->ci);
+// attr rb_snum_t sp_inc = sp_inc_of_invokeblock(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_invokeblock(ci);
{
- if (UNLIKELY(cd->cc.call != vm_invokeblock_i)) {
- cd->cc.call = vm_invokeblock_i; // check before setting to avoid CoW
- }
-
VALUE bh = VM_BLOCK_HANDLER_NONE;
- val = vm_sendish(ec, GET_CFP(), cd, bh, vm_search_invokeblock);
+ val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
if (val == Qundef) {
RESTORE_REGS();
@@ -977,7 +961,7 @@ jump
()
()
/* Same discussion as leave. */
-// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
{
RUBY_VM_CHECK_INTS(ec);
JUMP(dst);
@@ -990,7 +974,7 @@ branchif
(VALUE val)
()
/* Same discussion as jump. */
-// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
{
if (RTEST(val)) {
RUBY_VM_CHECK_INTS(ec);
@@ -1005,7 +989,7 @@ branchunless
(VALUE val)
()
/* Same discussion as jump. */
-// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
{
if (!RTEST(val)) {
RUBY_VM_CHECK_INTS(ec);
@@ -1020,7 +1004,7 @@ branchnil
(VALUE val)
()
/* Same discussion as jump. */
-// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
{
if (NIL_P(val)) {
RUBY_VM_CHECK_INTS(ec);
@@ -1039,9 +1023,10 @@ opt_getinlinecache
()
(VALUE val)
{
- if (vm_ic_hit_p(ic, GET_EP())) {
- val = ic->value;
- JUMP(dst);
+ struct iseq_inline_constant_cache_entry *ice = ic->entry;
+ if (ice && vm_ic_hit_p(ice, GET_EP())) {
+ val = ice->value;
+ JUMP(dst);
}
else {
val = Qnil;
@@ -1055,7 +1040,7 @@ opt_setinlinecache
(VALUE val)
(VALUE val)
{
- vm_ic_update(ic, val, GET_EP());
+ vm_ic_update(GET_ISEQ(), ic, val, GET_EP());
}
/* run iseq only once */
@@ -1167,7 +1152,7 @@ opt_eq
(VALUE recv, VALUE obj)
(VALUE val)
{
- val = opt_eq_func(recv, obj, cd);
+ val = opt_equality(GET_ISEQ(), recv, obj, cd);
if (val == Qundef) {
CALL_SIMPLE_METHOD();
@@ -1181,7 +1166,7 @@ opt_neq
(VALUE recv, VALUE obj)
(VALUE val)
{
- val = vm_opt_neq(cd, cd_eq, recv, obj);
+ val = vm_opt_neq(GET_ISEQ(), cd, cd_eq, recv, obj);
if (val == Qundef) {
CALL_SIMPLE_METHOD();
@@ -1431,7 +1416,7 @@ opt_not
(VALUE recv)
(VALUE val)
{
- val = vm_opt_not(cd, recv);
+ val = vm_opt_not(GET_ISEQ(), cd, recv);
if (val == Qundef) {
CALL_SIMPLE_METHOD();
@@ -1454,7 +1439,7 @@ opt_regexpmatch2
}
/* call native compiled method */
-DEFINE_INSN
+DEFINE_INSN_IF(SUPPORT_CALL_C_FUNCTION)
opt_call_c_function
(rb_insn_func_t funcptr)
()
@@ -1479,11 +1464,11 @@ DEFINE_INSN
invokebuiltin
(RB_BUILTIN bf)
(...)
-(VALUE ret)
+(VALUE val)
// attr bool leaf = false; /* anything can happen inside */
// attr rb_snum_t sp_inc = 1 - bf->argc;
{
- ret = vm_invoke_builtin(ec, reg_cfp, bf, STACK_ADDR_FROM_TOP(bf->argc));
+ val = vm_invoke_builtin(ec, reg_cfp, bf, STACK_ADDR_FROM_TOP(bf->argc));
}
/* call specific function with args (same parameters) */
@@ -1491,10 +1476,10 @@ DEFINE_INSN
opt_invokebuiltin_delegate
(RB_BUILTIN bf, rb_num_t index)
()
-(VALUE ret)
+(VALUE val)
// attr bool leaf = false; /* anything can happen inside */
{
- ret = vm_invoke_builtin_delegate(ec, reg_cfp, bf, (unsigned int)index);
+ val = vm_invoke_builtin_delegate(ec, reg_cfp, bf, (unsigned int)index);
}
/* call specific function with args (same parameters) and leave */
diff --git a/integer.rb b/integer.rb
new file mode 100644
index 0000000000..d18494f42f
--- /dev/null
+++ b/integer.rb
@@ -0,0 +1,150 @@
+class Integer
+ # call-seq:
+ # -int -> integer
+ #
+ # Returns +int+, negated.
+ def -@
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_int_uminus(self)'
+ end
+
+ # call-seq:
+ # ~int -> integer
+ #
+ # One's complement: returns a number where each bit is flipped.
+ #
+ # Inverts the bits in an Integer. As integers are conceptually of
+ # infinite length, the result acts as if it had an infinite number of
+ # one bits to the left. In hex representations, this is displayed
+ # as two periods to the left of the digits.
+ #
+ # sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA"
+ def ~
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_int_comp(self)'
+ end
+
+ def abs
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_int_abs(self)'
+ end
+
+ # call-seq:
+ # int.bit_length -> integer
+ #
+ # Returns the number of bits of the value of +int+.
+ #
+ # "Number of bits" means the bit position of the highest bit
+ # which is different from the sign bit
+ # (where the least significant bit has bit position 1).
+ # If there is no such bit (zero or minus one), zero is returned.
+ #
+ # I.e. this method returns <i>ceil(log2(int < 0 ? -int : int+1))</i>.
+ #
+ # (-2**1000-1).bit_length #=> 1001
+ # (-2**1000).bit_length #=> 1000
+ # (-2**1000+1).bit_length #=> 1000
+ # (-2**12-1).bit_length #=> 13
+ # (-2**12).bit_length #=> 12
+ # (-2**12+1).bit_length #=> 12
+ # -0x101.bit_length #=> 9
+ # -0x100.bit_length #=> 8
+ # -0xff.bit_length #=> 8
+ # -2.bit_length #=> 1
+ # -1.bit_length #=> 0
+ # 0.bit_length #=> 0
+ # 1.bit_length #=> 1
+ # 0xff.bit_length #=> 8
+ # 0x100.bit_length #=> 9
+ # (2**12-1).bit_length #=> 12
+ # (2**12).bit_length #=> 13
+ # (2**12+1).bit_length #=> 13
+ # (2**1000-1).bit_length #=> 1000
+ # (2**1000).bit_length #=> 1001
+ # (2**1000+1).bit_length #=> 1001
+ #
+ # This method can be used to detect overflow in Array#pack as follows:
+ #
+ # if n.bit_length < 32
+ # [n].pack("l") # no overflow
+ # else
+ # raise "overflow"
+ # end
+ def bit_length
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_int_bit_length(self)'
+ end
+
+ # call-seq:
+ # int.even? -> true or false
+ #
+ # Returns +true+ if +int+ is an even number.
+ def even?
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_int_even_p(self)'
+ end
+
+ # call-seq:
+ # int.integer? -> true
+ #
+ # Since +int+ is already an Integer, this always returns +true+.
+ def integer?
+ return true
+ end
+
+ def magnitude
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_int_abs(self)'
+ end
+
+ # call-seq:
+ # int.odd? -> true or false
+ #
+ # Returns +true+ if +int+ is an odd number.
+ def odd?
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_int_odd_p(self)'
+ end
+
+ # call-seq:
+ # int.ord -> self
+ #
+ # Returns the +int+ itself.
+ #
+ # 97.ord #=> 97
+ #
+ # This method is intended for compatibility to character literals
+ # in Ruby 1.9.
+ #
+ # For example, <code>?a.ord</code> returns 97 both in 1.8 and 1.9.
+ def ord
+ return self
+ end
+
+ # call-seq:
+ # int.to_i -> integer
+ #
+ # Since +int+ is already an Integer, returns +self+.
+ #
+ # #to_int is an alias for #to_i.
+ def to_i
+ return self
+ end
+
+ # call-seq:
+ # int.to_int -> integer
+ #
+ # Since +int+ is already an Integer, returns +self+.
+ def to_int
+ return self
+ end
+
+ # call-seq:
+ # int.zero? -> true or false
+ #
+ # Returns +true+ if +int+ has a zero value.
+ def zero?
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_int_zero_p(self)'
+ end
+end
diff --git a/internal.h b/internal.h
index b6cc07d5b9..c3b3a799b1 100644
--- a/internal.h
+++ b/internal.h
@@ -1,1438 +1,98 @@
-/**********************************************************************
-
- internal.h -
-
- $Author$
- created at: Tue May 17 11:42:20 JST 2011
-
- Copyright (C) 2011 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#ifndef RUBY_INTERNAL_H
+#ifndef RUBY_INTERNAL_H /*-*-C-*-vi:se ft=c:*/
#define RUBY_INTERNAL_H 1
+/**
+ * @file
+ * @author $Author$
+ * @date Tue May 17 11:42:20 JST 2011
+ * @copyright Copyright (C) 2011 Yukihiro Matsumoto
+ * @copyright This file is a part of the programming language Ruby.
+ * Permission is hereby granted, to either redistribute and/or
+ * modify this file, provided that the conditions mentioned in the
+ * file COPYING are met. Consult the file for details.
+ */
+#include "ruby/internal/config.h"
-#include "ruby.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-#ifdef HAVE_STDBOOL_H
-# include <stdbool.h>
-#else
-# include "missing/stdbool.h"
+#ifdef __cplusplus
+# error not for C++
#endif
-/* The most significant bit of the lower part of half-long integer.
- * If sizeof(long) == 4, this is 0x8000.
- * If sizeof(long) == 8, this is 0x80000000.
- */
-#define HALF_LONG_MSB ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2))
-
#define LIKELY(x) RB_LIKELY(x)
#define UNLIKELY(x) RB_UNLIKELY(x)
-#ifndef MAYBE_UNUSED
-# define MAYBE_UNUSED(x) x
-#endif
-
-#ifndef WARN_UNUSED_RESULT
-# define WARN_UNUSED_RESULT(x) x
-#endif
-
-#ifndef __has_feature
-# define __has_feature(x) 0
-#endif
-
-#ifndef __has_extension
-# define __has_extension __has_feature
-#endif
-
-#if 0
-#elif defined(NO_SANITIZE) && __has_feature(memory_sanitizer)
-# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
- NO_SANITIZE("memory", NO_SANITIZE("address", NOINLINE(x)))
-#elif defined(NO_SANITIZE)
-# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
- NO_SANITIZE("address", NOINLINE(x))
-#elif defined(NO_SANITIZE_ADDRESS)
-# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
- NO_SANITIZE_ADDRESS(NOINLINE(x))
-#elif defined(NO_ADDRESS_SAFETY_ANALYSIS)
-# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
- NO_ADDRESS_SAFETY_ANALYSIS(NOINLINE(x))
-#else
-# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) x
-#endif
-
-#if defined(NO_SANITIZE) && defined(__GNUC__) &&! defined(__clang__)
-/* GCC warns about unknown sanitizer, which is annoying. */
-#undef NO_SANITIZE
-#define NO_SANITIZE(x, y) \
- COMPILER_WARNING_PUSH; \
- COMPILER_WARNING_IGNORED(-Wattributes); \
- __attribute__((__no_sanitize__(x))) y; \
- COMPILER_WARNING_POP
-#endif
-
-#ifndef NO_SANITIZE
-# define NO_SANITIZE(x, y) y
-#endif
-
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-# include <valgrind/memcheck.h>
-# ifndef VALGRIND_MAKE_MEM_DEFINED
-# define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
-# endif
-# ifndef VALGRIND_MAKE_MEM_UNDEFINED
-# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
-# endif
-#else
-# define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
-# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
-#endif
-
#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0])))
-
-#ifndef MJIT_HEADER
-
-#ifdef HAVE_SANITIZER_ASAN_INTERFACE_H
-# include <sanitizer/asan_interface.h>
-#endif
-
-#if !__has_feature(address_sanitizer)
-# define __asan_poison_memory_region(x, y)
-# define __asan_unpoison_memory_region(x, y)
-# define __asan_region_is_poisoned(x, y) 0
-#endif
-
-#ifdef HAVE_SANITIZER_MSAN_INTERFACE_H
-# if __has_feature(memory_sanitizer)
-# include <sanitizer/msan_interface.h>
-# endif
-#endif
-
-#if !__has_feature(memory_sanitizer)
-# define __msan_allocated_memory(x, y) ((void)(x), (void)(y))
-# define __msan_poison(x, y) ((void)(x), (void)(y))
-# define __msan_unpoison(x, y) ((void)(x), (void)(y))
-# define __msan_unpoison_string(x) ((void)(x))
-#endif
-
-/*!
- * This function asserts that a (continuous) memory region from ptr to size
- * being "poisoned". Both read / write access to such memory region are
- * prohibited until properly unpoisoned. The region must be previously
- * allocated (do not pass a freed pointer here), but not necessarily be an
- * entire object that the malloc returns. You can punch hole a part of a
- * gigantic heap arena. This is handy when you do not free an allocated memory
- * region to reuse later: poison when you keep it unused, and unpoison when you
- * reuse.
- *
- * \param[in] ptr pointer to the beginning of the memory region to poison.
- * \param[in] size the length of the memory region to poison.
- */
-static inline void
-asan_poison_memory_region(const volatile void *ptr, size_t size)
-{
- __msan_poison(ptr, size);
- __asan_poison_memory_region(ptr, size);
-}
-
-/*!
- * This is a variant of asan_poison_memory_region that takes a VALUE.
- *
- * \param[in] obj target object.
- */
-static inline void
-asan_poison_object(VALUE obj)
-{
- MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
- asan_poison_memory_region(ptr, SIZEOF_VALUE);
-}
-
-#if !__has_feature(address_sanitizer)
-#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj))
-#else
-#define asan_poison_object_if(ptr, obj) do { \
- if (ptr) asan_poison_object(obj); \
- } while (0)
-#endif
-
-/*!
- * This function predicates if the given object is fully addressable or not.
- *
- * \param[in] obj target object.
- * \retval 0 the given object is fully addressable.
- * \retval otherwise pointer to first such byte who is poisoned.
- */
-static inline void *
-asan_poisoned_object_p(VALUE obj)
-{
- MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
- return __asan_region_is_poisoned(ptr, SIZEOF_VALUE);
-}
-
-/*!
- * This function asserts that a (formally poisoned) memory region from ptr to
- * size is now addressable. Write access to such memory region gets allowed.
- * However read access might or might not be possible depending on situations,
- * because the region can have contents of previous usages. That information
- * should be passed by the malloc_p flag. If that is true, the contents of the
- * region is _not_ fully defined (like the return value of malloc behaves).
- * Reading from there is NG; write something first. If malloc_p is false on
- * the other hand, that memory region is fully defined and can be read
- * immediately.
- *
- * \param[in] ptr pointer to the beginning of the memory region to unpoison.
- * \param[in] size the length of the memory region.
- * \param[in] malloc_p if the memory region is like a malloc's return value or not.
- */
-static inline void
-asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p)
-{
- __asan_unpoison_memory_region(ptr, size);
- if (malloc_p) {
- __msan_allocated_memory(ptr, size);
- }
- else {
- __msan_unpoison(ptr, size);
- }
-}
-
-/*!
- * This is a variant of asan_unpoison_memory_region that takes a VALUE.
- *
- * \param[in] obj target object.
- * \param[in] malloc_p if the memory region is like a malloc's return value or not.
- */
-static inline void
-asan_unpoison_object(VALUE obj, bool newobj_p)
-{
- MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
- asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p);
-}
-
-#endif
+#define roomof(x, y) (((x) + (y) - 1) / (y))
+#define type_roomof(x, y) roomof(sizeof(x), sizeof(y))
/* Prevent compiler from reordering access */
#define ACCESS_ONCE(type,x) (*((volatile type *)&(x)))
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
-# define STATIC_ASSERT(name, expr) _Static_assert(expr, #name ": " #expr)
-#elif GCC_VERSION_SINCE(4, 6, 0) || __has_extension(c_static_assert)
-# define STATIC_ASSERT(name, expr) RB_GNUC_EXTENSION _Static_assert(expr, #name ": " #expr)
-#else
-# define STATIC_ASSERT(name, expr) typedef int static_assert_##name##_check[1 - 2*!(expr)]
-#endif
-
-#define SIGNED_INTEGER_TYPE_P(int_type) (0 > ((int_type)0)-1)
-#define SIGNED_INTEGER_MAX(sint_type) \
- (sint_type) \
- ((((sint_type)1) << (sizeof(sint_type) * CHAR_BIT - 2)) | \
- ((((sint_type)1) << (sizeof(sint_type) * CHAR_BIT - 2)) - 1))
-#define SIGNED_INTEGER_MIN(sint_type) (-SIGNED_INTEGER_MAX(sint_type)-1)
-#define UNSIGNED_INTEGER_MAX(uint_type) (~(uint_type)0)
-
-#if SIGNEDNESS_OF_TIME_T < 0 /* signed */
-# define TIMET_MAX SIGNED_INTEGER_MAX(time_t)
-# define TIMET_MIN SIGNED_INTEGER_MIN(time_t)
-#elif SIGNEDNESS_OF_TIME_T > 0 /* unsigned */
-# define TIMET_MAX UNSIGNED_INTEGER_MAX(time_t)
-# define TIMET_MIN ((time_t)0)
-#endif
-#define TIMET_MAX_PLUS_ONE (2*(double)(TIMET_MAX/2+1))
-
-#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P
-#define MUL_OVERFLOW_P(a, b) \
- __builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0)
-#elif defined HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW
-#define MUL_OVERFLOW_P(a, b) \
- ({__typeof__(a) c; __builtin_mul_overflow((a), (b), &c);})
-#endif
-
-#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
- (a) == 0 ? 0 : \
- (a) == -1 ? (b) < -(max) : \
- (a) > 0 ? \
- ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
- ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
-
-#ifdef HAVE_BUILTIN___BUILTIN_MUL_OVERFLOW_P
-/* __builtin_mul_overflow_p can take bitfield */
-/* and GCC permits bitfields for integers other than int */
-#define MUL_OVERFLOW_FIXNUM_P(a, b) ({ \
- struct { long fixnum : SIZEOF_LONG * CHAR_BIT - 1; } c; \
- __builtin_mul_overflow_p((a), (b), c.fixnum); \
-})
-#else
-#define MUL_OVERFLOW_FIXNUM_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
-#endif
-
-#ifdef MUL_OVERFLOW_P
-#define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_P(a, b)
-#define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_P(a, b)
-#define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_P(a, b)
-#else
-#define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
-#define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
-#define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
-#endif
-
-#ifndef swap16
-# ifdef HAVE_BUILTIN___BUILTIN_BSWAP16
-# define swap16(x) __builtin_bswap16(x)
-# endif
-#endif
-
-#ifndef swap16
-# define swap16(x) ((uint16_t)((((x)&0xFF)<<8) | (((x)>>8)&0xFF)))
-#endif
-
-#ifndef swap32
-# ifdef HAVE_BUILTIN___BUILTIN_BSWAP32
-# define swap32(x) __builtin_bswap32(x)
-# endif
-#endif
-
-#ifndef swap32
-# define swap32(x) ((uint32_t)((((x)&0xFF)<<24) \
- |(((x)>>24)&0xFF) \
- |(((x)&0x0000FF00)<<8) \
- |(((x)&0x00FF0000)>>8) ))
-#endif
-
-#ifndef swap64
-# ifdef HAVE_BUILTIN___BUILTIN_BSWAP64
-# define swap64(x) __builtin_bswap64(x)
-# endif
-#endif
-
-#ifndef swap64
-# ifdef HAVE_INT64_T
-# define byte_in_64bit(n) ((uint64_t)0xff << (n))
-# define swap64(x) ((uint64_t)((((x)&byte_in_64bit(0))<<56) \
- |(((x)>>56)&0xFF) \
- |(((x)&byte_in_64bit(8))<<40) \
- |(((x)&byte_in_64bit(48))>>40) \
- |(((x)&byte_in_64bit(16))<<24) \
- |(((x)&byte_in_64bit(40))>>24) \
- |(((x)&byte_in_64bit(24))<<8) \
- |(((x)&byte_in_64bit(32))>>8)))
-# endif
-#endif
-
-static inline unsigned int
-nlz_int(unsigned int x)
-{
-#if defined(HAVE_BUILTIN___BUILTIN_CLZ)
- if (x == 0) return SIZEOF_INT * CHAR_BIT;
- return (unsigned int)__builtin_clz(x);
-#else
- unsigned int y;
-# if 64 < SIZEOF_INT * CHAR_BIT
- unsigned int n = 128;
-# elif 32 < SIZEOF_INT * CHAR_BIT
- unsigned int n = 64;
-# else
- unsigned int n = 32;
-# endif
-# if 64 < SIZEOF_INT * CHAR_BIT
- y = x >> 64; if (y) {n -= 64; x = y;}
-# endif
-# if 32 < SIZEOF_INT * CHAR_BIT
- y = x >> 32; if (y) {n -= 32; x = y;}
-# endif
- y = x >> 16; if (y) {n -= 16; x = y;}
- y = x >> 8; if (y) {n -= 8; x = y;}
- y = x >> 4; if (y) {n -= 4; x = y;}
- y = x >> 2; if (y) {n -= 2; x = y;}
- y = x >> 1; if (y) {return n - 2;}
- return (unsigned int)(n - x);
-#endif
-}
-
-static inline unsigned int
-nlz_long(unsigned long x)
-{
-#if defined(HAVE_BUILTIN___BUILTIN_CLZL)
- if (x == 0) return SIZEOF_LONG * CHAR_BIT;
- return (unsigned int)__builtin_clzl(x);
-#else
- unsigned long y;
-# if 64 < SIZEOF_LONG * CHAR_BIT
- unsigned int n = 128;
-# elif 32 < SIZEOF_LONG * CHAR_BIT
- unsigned int n = 64;
-# else
- unsigned int n = 32;
-# endif
-# if 64 < SIZEOF_LONG * CHAR_BIT
- y = x >> 64; if (y) {n -= 64; x = y;}
-# endif
-# if 32 < SIZEOF_LONG * CHAR_BIT
- y = x >> 32; if (y) {n -= 32; x = y;}
-# endif
- y = x >> 16; if (y) {n -= 16; x = y;}
- y = x >> 8; if (y) {n -= 8; x = y;}
- y = x >> 4; if (y) {n -= 4; x = y;}
- y = x >> 2; if (y) {n -= 2; x = y;}
- y = x >> 1; if (y) {return n - 2;}
- return (unsigned int)(n - x);
-#endif
-}
-
-#ifdef HAVE_LONG_LONG
-static inline unsigned int
-nlz_long_long(unsigned LONG_LONG x)
-{
-#if defined(HAVE_BUILTIN___BUILTIN_CLZLL)
- if (x == 0) return SIZEOF_LONG_LONG * CHAR_BIT;
- return (unsigned int)__builtin_clzll(x);
-#else
- unsigned LONG_LONG y;
-# if 64 < SIZEOF_LONG_LONG * CHAR_BIT
- unsigned int n = 128;
-# elif 32 < SIZEOF_LONG_LONG * CHAR_BIT
- unsigned int n = 64;
-# else
- unsigned int n = 32;
-# endif
-# if 64 < SIZEOF_LONG_LONG * CHAR_BIT
- y = x >> 64; if (y) {n -= 64; x = y;}
-# endif
-# if 32 < SIZEOF_LONG_LONG * CHAR_BIT
- y = x >> 32; if (y) {n -= 32; x = y;}
-# endif
- y = x >> 16; if (y) {n -= 16; x = y;}
- y = x >> 8; if (y) {n -= 8; x = y;}
- y = x >> 4; if (y) {n -= 4; x = y;}
- y = x >> 2; if (y) {n -= 2; x = y;}
- y = x >> 1; if (y) {return n - 2;}
- return (unsigned int)(n - x);
-#endif
-}
-#endif
-
-#ifdef HAVE_UINT128_T
-static inline unsigned int
-nlz_int128(uint128_t x)
-{
- uint128_t y;
- unsigned int n = 128;
- y = x >> 64; if (y) {n -= 64; x = y;}
- y = x >> 32; if (y) {n -= 32; x = y;}
- y = x >> 16; if (y) {n -= 16; x = y;}
- y = x >> 8; if (y) {n -= 8; x = y;}
- y = x >> 4; if (y) {n -= 4; x = y;}
- y = x >> 2; if (y) {n -= 2; x = y;}
- y = x >> 1; if (y) {return n - 2;}
- return (unsigned int)(n - x);
-}
-#endif
-
-static inline unsigned int
-nlz_intptr(uintptr_t x)
-{
-#if SIZEOF_UINTPTR_T == SIZEOF_INT
- return nlz_int(x);
-#elif SIZEOF_UINTPTR_T == SIZEOF_LONG
- return nlz_long(x);
-#elif SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG
- return nlz_long_long(x);
-#else
- #error no known integer type corresponds uintptr_t
- return /* sane compiler */ ~0;
-#endif
-}
-
-static inline unsigned int
-rb_popcount32(uint32_t x)
-{
-#ifdef HAVE_BUILTIN___BUILTIN_POPCOUNT
- return (unsigned int)__builtin_popcount(x);
-#else
- x = (x & 0x55555555) + (x >> 1 & 0x55555555);
- x = (x & 0x33333333) + (x >> 2 & 0x33333333);
- x = (x & 0x0f0f0f0f) + (x >> 4 & 0x0f0f0f0f);
- x = (x & 0x001f001f) + (x >> 8 & 0x001f001f);
- return (x & 0x0000003f) + (x >>16 & 0x0000003f);
-#endif
-}
-
-static inline int
-rb_popcount64(uint64_t x)
-{
-#ifdef HAVE_BUILTIN___BUILTIN_POPCOUNT
- return __builtin_popcountll(x);
-#else
- x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
- x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
- x = (x & 0x0707070707070707) + (x >> 4 & 0x0707070707070707);
- x = (x & 0x001f001f001f001f) + (x >> 8 & 0x001f001f001f001f);
- x = (x & 0x0000003f0000003f) + (x >>16 & 0x0000003f0000003f);
- return (x & 0x7f) + (x >>32 & 0x7f);
-#endif
-}
-
-static inline int
-rb_popcount_intptr(uintptr_t x)
-{
-#if SIZEOF_VOIDP == 8
- return rb_popcount64(x);
-#elif SIZEOF_VOIDP == 4
- return rb_popcount32(x);
-#endif
-}
-
-static inline int
-ntz_int32(uint32_t x)
-{
-#ifdef HAVE_BUILTIN___BUILTIN_CTZ
- return __builtin_ctz(x);
-#else
- return rb_popcount32((~x) & (x-1));
-#endif
-}
-
-static inline int
-ntz_int64(uint64_t x)
-{
-#ifdef HAVE_BUILTIN___BUILTIN_CTZLL
- return __builtin_ctzll(x);
-#else
- return rb_popcount64((~x) & (x-1));
-#endif
-}
-
-static inline int
-ntz_intptr(uintptr_t x)
-{
-#if SIZEOF_VOIDP == 8
- return ntz_int64(x);
-#elif SIZEOF_VOIDP == 4
- return ntz_int32(x);
-#endif
-}
-
-#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
-# define DLONG LONG_LONG
-# define DL2NUM(x) LL2NUM(x)
-#elif defined(HAVE_INT128_T)
-# define DLONG int128_t
-# define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x))
-VALUE rb_int128t2big(int128_t n);
-#endif
-
-static inline long
-rb_overflowed_fix_to_int(long x)
-{
- return (long)((unsigned long)(x >> 1) ^ (1LU << (SIZEOF_LONG * CHAR_BIT - 1)));
-}
-
-static inline VALUE
-rb_fix_plus_fix(VALUE x, VALUE y)
-{
-#ifdef HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW
- long lz;
- /* NOTE
- * (1) `LONG2FIX(FIX2LONG(x)+FIX2LONG(y))`
- + = `((lx*2+1)/2 + (ly*2+1)/2)*2+1`
- + = `lx*2 + ly*2 + 1`
- + = `(lx*2+1) + (ly*2+1) - 1`
- + = `x + y - 1`
- * (2) Fixnum's LSB is always 1.
- * It means you can always run `x - 1` without overflow.
- * (3) Of course `z = x + (y-1)` may overflow.
- * At that time true value is
- * * positive: 0b0 1xxx...1, and z = 0b1xxx...1
- * * nevative: 0b1 0xxx...1, and z = 0b0xxx...1
- * To convert this true value to long,
- * (a) Use arithmetic shift
- * * positive: 0b11xxx...
- * * negative: 0b00xxx...
- * (b) invert MSB
- * * positive: 0b01xxx...
- * * negative: 0b10xxx...
- */
- if (__builtin_add_overflow((long)x, (long)y-1, &lz)) {
- return rb_int2big(rb_overflowed_fix_to_int(lz));
- }
- else {
- return (VALUE)lz;
- }
-#else
- long lz = FIX2LONG(x) + FIX2LONG(y);
- return LONG2NUM(lz);
-#endif
-}
-
-static inline VALUE
-rb_fix_minus_fix(VALUE x, VALUE y)
-{
-#ifdef HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW
- long lz;
- if (__builtin_sub_overflow((long)x, (long)y-1, &lz)) {
- return rb_int2big(rb_overflowed_fix_to_int(lz));
- }
- else {
- return (VALUE)lz;
- }
-#else
- long lz = FIX2LONG(x) - FIX2LONG(y);
- return LONG2NUM(lz);
-#endif
-}
-
-/* arguments must be Fixnum */
-static inline VALUE
-rb_fix_mul_fix(VALUE x, VALUE y)
-{
- long lx = FIX2LONG(x);
- long ly = FIX2LONG(y);
-#ifdef DLONG
- return DL2NUM((DLONG)lx * (DLONG)ly);
-#else
- if (MUL_OVERFLOW_FIXNUM_P(lx, ly)) {
- return rb_big_mul(rb_int2big(lx), rb_int2big(ly));
- }
- else {
- return LONG2FIX(lx * ly);
- }
-#endif
-}
+#include "ruby/ruby.h"
-/*
- * This behaves different from C99 for negative arguments.
- * Note that div may overflow fixnum.
- */
-static inline void
-rb_fix_divmod_fix(VALUE a, VALUE b, VALUE *divp, VALUE *modp)
-{
- /* assume / and % comply C99.
- * ldiv(3) won't be inlined by GCC and clang.
- * I expect / and % are compiled as single idiv.
- */
- long x = FIX2LONG(a);
- long y = FIX2LONG(b);
- long div, mod;
- if (x == FIXNUM_MIN && y == -1) {
- if (divp) *divp = LONG2NUM(-FIXNUM_MIN);
- if (modp) *modp = LONG2FIX(0);
- return;
- }
- div = x / y;
- mod = x % y;
- if (y > 0 ? mod < 0 : mod > 0) {
- mod += y;
- div -= 1;
- }
- if (divp) *divp = LONG2FIX(div);
- if (modp) *modp = LONG2FIX(mod);
-}
+/* Following macros were formerly defined in this header but moved to somewhere
+ * else. In order to detect them we undef here. */
-/* div() for Ruby
- * This behaves different from C99 for negative arguments.
- */
-static inline VALUE
-rb_fix_div_fix(VALUE x, VALUE y)
-{
- VALUE div;
- rb_fix_divmod_fix(x, y, &div, NULL);
- return div;
-}
-
-/* mod() for Ruby
- * This behaves different from C99 for negative arguments.
- */
-static inline VALUE
-rb_fix_mod_fix(VALUE x, VALUE y)
-{
- VALUE mod;
- rb_fix_divmod_fix(x, y, NULL, &mod);
- return mod;
-}
+/* internal/array.h */
+#undef RARRAY_AREF
-#if defined(HAVE_UINT128_T) && defined(HAVE_LONG_LONG)
-# define bit_length(x) \
- (unsigned int) \
- (sizeof(x) <= SIZEOF_INT ? SIZEOF_INT * CHAR_BIT - nlz_int((unsigned int)(x)) : \
- sizeof(x) <= SIZEOF_LONG ? SIZEOF_LONG * CHAR_BIT - nlz_long((unsigned long)(x)) : \
- sizeof(x) <= SIZEOF_LONG_LONG ? SIZEOF_LONG_LONG * CHAR_BIT - nlz_long_long((unsigned LONG_LONG)(x)) : \
- SIZEOF_INT128_T * CHAR_BIT - nlz_int128((uint128_t)(x)))
-#elif defined(HAVE_UINT128_T)
-# define bit_length(x) \
- (unsigned int) \
- (sizeof(x) <= SIZEOF_INT ? SIZEOF_INT * CHAR_BIT - nlz_int((unsigned int)(x)) : \
- sizeof(x) <= SIZEOF_LONG ? SIZEOF_LONG * CHAR_BIT - nlz_long((unsigned long)(x)) : \
- SIZEOF_INT128_T * CHAR_BIT - nlz_int128((uint128_t)(x)))
-#elif defined(HAVE_LONG_LONG)
-# define bit_length(x) \
- (unsigned int) \
- (sizeof(x) <= SIZEOF_INT ? SIZEOF_INT * CHAR_BIT - nlz_int((unsigned int)(x)) : \
- sizeof(x) <= SIZEOF_LONG ? SIZEOF_LONG * CHAR_BIT - nlz_long((unsigned long)(x)) : \
- SIZEOF_LONG_LONG * CHAR_BIT - nlz_long_long((unsigned LONG_LONG)(x)))
-#else
-# define bit_length(x) \
- (unsigned int) \
- (sizeof(x) <= SIZEOF_INT ? SIZEOF_INT * CHAR_BIT - nlz_int((unsigned int)(x)) : \
- SIZEOF_LONG * CHAR_BIT - nlz_long((unsigned long)(x)))
-#endif
-
-#ifndef BDIGIT
-# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
-# define BDIGIT unsigned int
-# define SIZEOF_BDIGIT SIZEOF_INT
-# define BDIGIT_DBL unsigned LONG_LONG
-# define BDIGIT_DBL_SIGNED LONG_LONG
-# define PRI_BDIGIT_PREFIX ""
-# define PRI_BDIGIT_DBL_PREFIX PRI_LL_PREFIX
-# elif SIZEOF_INT*2 <= SIZEOF_LONG
-# define BDIGIT unsigned int
-# define SIZEOF_BDIGIT SIZEOF_INT
-# define BDIGIT_DBL unsigned long
-# define BDIGIT_DBL_SIGNED long
-# define PRI_BDIGIT_PREFIX ""
-# define PRI_BDIGIT_DBL_PREFIX "l"
-# elif SIZEOF_SHORT*2 <= SIZEOF_LONG
-# define BDIGIT unsigned short
-# define SIZEOF_BDIGIT SIZEOF_SHORT
-# define BDIGIT_DBL unsigned long
-# define BDIGIT_DBL_SIGNED long
-# define PRI_BDIGIT_PREFIX "h"
-# define PRI_BDIGIT_DBL_PREFIX "l"
-# else
-# define BDIGIT unsigned short
-# define SIZEOF_BDIGIT (SIZEOF_LONG/2)
-# define SIZEOF_ACTUAL_BDIGIT SIZEOF_LONG
-# define BDIGIT_DBL unsigned long
-# define BDIGIT_DBL_SIGNED long
-# define PRI_BDIGIT_PREFIX "h"
-# define PRI_BDIGIT_DBL_PREFIX "l"
-# endif
-#endif
-#ifndef SIZEOF_ACTUAL_BDIGIT
-# define SIZEOF_ACTUAL_BDIGIT SIZEOF_BDIGIT
-#endif
-
-#ifdef PRI_BDIGIT_PREFIX
-# define PRIdBDIGIT PRI_BDIGIT_PREFIX"d"
-# define PRIiBDIGIT PRI_BDIGIT_PREFIX"i"
-# define PRIoBDIGIT PRI_BDIGIT_PREFIX"o"
-# define PRIuBDIGIT PRI_BDIGIT_PREFIX"u"
-# define PRIxBDIGIT PRI_BDIGIT_PREFIX"x"
-# define PRIXBDIGIT PRI_BDIGIT_PREFIX"X"
-#endif
-
-#ifdef PRI_BDIGIT_DBL_PREFIX
-# define PRIdBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"d"
-# define PRIiBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"i"
-# define PRIoBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"o"
-# define PRIuBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"u"
-# define PRIxBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"x"
-# define PRIXBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"X"
-#endif
-
-#define BIGNUM_EMBED_LEN_NUMBITS 3
-#ifndef BIGNUM_EMBED_LEN_MAX
-# if (SIZEOF_VALUE*RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT) < (1 << BIGNUM_EMBED_LEN_NUMBITS)-1
-# define BIGNUM_EMBED_LEN_MAX (SIZEOF_VALUE*RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT)
-# else
-# define BIGNUM_EMBED_LEN_MAX ((1 << BIGNUM_EMBED_LEN_NUMBITS)-1)
-# endif
-#endif
-
-struct RBignum {
- struct RBasic basic;
- union {
- struct {
- size_t len;
- BDIGIT *digits;
- } heap;
- BDIGIT ary[BIGNUM_EMBED_LEN_MAX];
- } as;
-};
-#define BIGNUM_SIGN_BIT ((VALUE)FL_USER1)
-/* sign: positive:1, negative:0 */
-#define BIGNUM_SIGN(b) ((RBASIC(b)->flags & BIGNUM_SIGN_BIT) != 0)
-#define BIGNUM_SET_SIGN(b,sign) \
- ((sign) ? (RBASIC(b)->flags |= BIGNUM_SIGN_BIT) \
- : (RBASIC(b)->flags &= ~BIGNUM_SIGN_BIT))
-#define BIGNUM_POSITIVE_P(b) BIGNUM_SIGN(b)
-#define BIGNUM_NEGATIVE_P(b) (!BIGNUM_SIGN(b))
-#define BIGNUM_NEGATE(b) (RBASIC(b)->flags ^= BIGNUM_SIGN_BIT)
-
-#define BIGNUM_EMBED_FLAG ((VALUE)FL_USER2)
-#define BIGNUM_EMBED_LEN_MASK \
- (~(~(VALUE)0U << BIGNUM_EMBED_LEN_NUMBITS) << BIGNUM_EMBED_LEN_SHIFT)
-#define BIGNUM_EMBED_LEN_SHIFT \
- (FL_USHIFT+3) /* bit offset of BIGNUM_EMBED_LEN_MASK */
-#define BIGNUM_LEN(b) \
- ((RBASIC(b)->flags & BIGNUM_EMBED_FLAG) ? \
- (size_t)((RBASIC(b)->flags >> BIGNUM_EMBED_LEN_SHIFT) & \
- (BIGNUM_EMBED_LEN_MASK >> BIGNUM_EMBED_LEN_SHIFT)) : \
- RBIGNUM(b)->as.heap.len)
-/* LSB:BIGNUM_DIGITS(b)[0], MSB:BIGNUM_DIGITS(b)[BIGNUM_LEN(b)-1] */
-#define BIGNUM_DIGITS(b) \
- ((RBASIC(b)->flags & BIGNUM_EMBED_FLAG) ? \
- RBIGNUM(b)->as.ary : \
- RBIGNUM(b)->as.heap.digits)
-#define BIGNUM_LENINT(b) rb_long2int(BIGNUM_LEN(b))
-
-#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
-
-struct RRational {
- struct RBasic basic;
- VALUE num;
- VALUE den;
-};
-
-#define RRATIONAL(obj) (R_CAST(RRational)(obj))
-#define RRATIONAL_SET_NUM(rat, n) RB_OBJ_WRITE((rat), &((struct RRational *)(rat))->num,(n))
-#define RRATIONAL_SET_DEN(rat, d) RB_OBJ_WRITE((rat), &((struct RRational *)(rat))->den,(d))
-
-struct RFloat {
- struct RBasic basic;
- double float_value;
-};
-
-#define RFLOAT(obj) (R_CAST(RFloat)(obj))
-
-struct RComplex {
- struct RBasic basic;
- VALUE real;
- VALUE imag;
-};
-
-#define RCOMPLEX(obj) (R_CAST(RComplex)(obj))
-
-/* shortcut macro for internal only */
-#define RCOMPLEX_SET_REAL(cmp, r) RB_OBJ_WRITE((cmp), &((struct RComplex *)(cmp))->real,(r))
-#define RCOMPLEX_SET_IMAG(cmp, i) RB_OBJ_WRITE((cmp), &((struct RComplex *)(cmp))->imag,(i))
-
-enum ruby_rhash_flags {
- RHASH_PASS_AS_KEYWORDS = FL_USER1, /* FL 1 */
- RHASH_PROC_DEFAULT = FL_USER2, /* FL 2 */
- RHASH_ST_TABLE_FLAG = FL_USER3, /* FL 3 */
-#define RHASH_AR_TABLE_MAX_SIZE SIZEOF_VALUE
- RHASH_AR_TABLE_SIZE_MASK = (FL_USER4|FL_USER5|FL_USER6|FL_USER7), /* FL 4..7 */
- RHASH_AR_TABLE_SIZE_SHIFT = (FL_USHIFT+4),
- RHASH_AR_TABLE_BOUND_MASK = (FL_USER8|FL_USER9|FL_USER10|FL_USER11), /* FL 8..11 */
- RHASH_AR_TABLE_BOUND_SHIFT = (FL_USHIFT+8),
-
- // we can not put it in "enum" because it can exceed "int" range.
-#define RHASH_LEV_MASK (FL_USER13 | FL_USER14 | FL_USER15 | /* FL 13..19 */ \
- FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19)
-
-#if USE_TRANSIENT_HEAP
- RHASH_TRANSIENT_FLAG = FL_USER12, /* FL 12 */
-#endif
-
- RHASH_LEV_SHIFT = (FL_USHIFT + 13),
- RHASH_LEV_MAX = 127, /* 7 bits */
-
- RHASH_ENUM_END
-};
-
-#define RHASH_AR_TABLE_SIZE_RAW(h) \
- ((unsigned int)((RBASIC(h)->flags & RHASH_AR_TABLE_SIZE_MASK) >> RHASH_AR_TABLE_SIZE_SHIFT))
-
-void rb_hash_st_table_set(VALUE hash, st_table *st);
-
-#if 0 /* for debug */
-int rb_hash_ar_table_p(VALUE hash);
-struct ar_table_struct *rb_hash_ar_table(VALUE hash);
-st_table *rb_hash_st_table(VALUE hash);
-#define RHASH_AR_TABLE_P(hash) rb_hash_ar_table_p(hash)
-#define RHASH_AR_TABLE(h) rb_hash_ar_table(h)
-#define RHASH_ST_TABLE(h) rb_hash_st_table(h)
-#else
-#define RHASH_AR_TABLE_P(hash) (!FL_TEST_RAW((hash), RHASH_ST_TABLE_FLAG))
-#define RHASH_AR_TABLE(hash) (RHASH(hash)->as.ar)
-#define RHASH_ST_TABLE(hash) (RHASH(hash)->as.st)
-#endif
-
-#define RHASH(obj) (R_CAST(RHash)(obj))
-#define RHASH_ST_SIZE(h) (RHASH_ST_TABLE(h)->num_entries)
-#define RHASH_ST_TABLE_P(h) (!RHASH_AR_TABLE_P(h))
-#define RHASH_ST_CLEAR(h) (FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG), RHASH(h)->as.ar = NULL)
-
-#define RHASH_AR_TABLE_SIZE_MASK (VALUE)RHASH_AR_TABLE_SIZE_MASK
-#define RHASH_AR_TABLE_SIZE_SHIFT RHASH_AR_TABLE_SIZE_SHIFT
-#define RHASH_AR_TABLE_BOUND_MASK (VALUE)RHASH_AR_TABLE_BOUND_MASK
-#define RHASH_AR_TABLE_BOUND_SHIFT RHASH_AR_TABLE_BOUND_SHIFT
-
-#if USE_TRANSIENT_HEAP
-#define RHASH_TRANSIENT_P(hash) FL_TEST_RAW((hash), RHASH_TRANSIENT_FLAG)
-#define RHASH_SET_TRANSIENT_FLAG(h) FL_SET_RAW(h, RHASH_TRANSIENT_FLAG)
-#define RHASH_UNSET_TRANSIENT_FLAG(h) FL_UNSET_RAW(h, RHASH_TRANSIENT_FLAG)
-#else
-#define RHASH_TRANSIENT_P(hash) 0
-#define RHASH_SET_TRANSIENT_FLAG(h) ((void)0)
-#define RHASH_UNSET_TRANSIENT_FLAG(h) ((void)0)
-#endif
-
-#if SIZEOF_VALUE / RHASH_AR_TABLE_MAX_SIZE == 2
-typedef uint16_t ar_hint_t;
-#elif SIZEOF_VALUE / RHASH_AR_TABLE_MAX_SIZE == 1
-typedef unsigned char ar_hint_t;
-#else
-#error unsupported
-#endif
-
-struct RHash {
- struct RBasic basic;
- union {
- st_table *st;
- struct ar_table_struct *ar; /* possibly 0 */
- } as;
- const VALUE ifnone;
- union {
- ar_hint_t ary[RHASH_AR_TABLE_MAX_SIZE];
- VALUE word;
- } ar_hint;
-};
-
-#ifdef RHASH_IFNONE
-# undef RHASH_IFNONE
-# undef RHASH_SIZE
-
-# define RHASH_IFNONE(h) (RHASH(h)->ifnone)
-# define RHASH_SIZE(h) (RHASH_AR_TABLE_P(h) ? RHASH_AR_TABLE_SIZE_RAW(h) : RHASH_ST_SIZE(h))
-#endif /* ifdef RHASH_IFNONE */
-
-struct RMoved {
- VALUE flags;
- VALUE destination;
- VALUE next;
-};
-
-/* missing/setproctitle.c */
-#ifndef HAVE_SETPROCTITLE
-extern void ruby_init_setproctitle(int argc, char *argv[]);
-#endif
-
-#define RSTRUCT_EMBED_LEN_MAX RSTRUCT_EMBED_LEN_MAX
-#define RSTRUCT_EMBED_LEN_MASK RSTRUCT_EMBED_LEN_MASK
-#define RSTRUCT_EMBED_LEN_SHIFT RSTRUCT_EMBED_LEN_SHIFT
-
-enum {
- RSTRUCT_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX,
- RSTRUCT_EMBED_LEN_MASK = (RUBY_FL_USER2|RUBY_FL_USER1),
- RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1),
- RSTRUCT_TRANSIENT_FLAG = FL_USER3,
+/* internal/class.h */
+#undef RClass
+#undef RCLASS_SUPER
- RSTRUCT_ENUM_END
-};
+/* internal/gc.h */
+#undef NEWOBJ_OF
+#undef RB_NEWOBJ_OF
+#undef RB_OBJ_WRITE
-#if USE_TRANSIENT_HEAP
-#define RSTRUCT_TRANSIENT_P(st) FL_TEST_RAW((obj), RSTRUCT_TRANSIENT_FLAG)
-#define RSTRUCT_TRANSIENT_SET(st) FL_SET_RAW((st), RSTRUCT_TRANSIENT_FLAG)
-#define RSTRUCT_TRANSIENT_UNSET(st) FL_UNSET_RAW((st), RSTRUCT_TRANSIENT_FLAG)
-#else
-#define RSTRUCT_TRANSIENT_P(st) 0
-#define RSTRUCT_TRANSIENT_SET(st) ((void)0)
-#define RSTRUCT_TRANSIENT_UNSET(st) ((void)0)
-#endif
+/* internal/hash.h */
+#undef RHASH_IFNONE
+#undef RHASH_SIZE
+#undef RHASH_TBL
+#undef RHASH_EMPTY_P
-struct RStruct {
- struct RBasic basic;
- union {
- struct {
- long len;
- const VALUE *ptr;
- } heap;
- const VALUE ary[RSTRUCT_EMBED_LEN_MAX];
- } as;
-};
+/* internal/object.h */
+#undef ROBJECT_IV_INDEX_TBL
+/* internal/struct.h */
#undef RSTRUCT_LEN
#undef RSTRUCT_PTR
#undef RSTRUCT_SET
#undef RSTRUCT_GET
-#define RSTRUCT_EMBED_LEN(st) \
- (long)((RBASIC(st)->flags >> RSTRUCT_EMBED_LEN_SHIFT) & \
- (RSTRUCT_EMBED_LEN_MASK >> RSTRUCT_EMBED_LEN_SHIFT))
-#define RSTRUCT_LEN(st) rb_struct_len(st)
-#define RSTRUCT_LENINT(st) rb_long2int(RSTRUCT_LEN(st))
-#define RSTRUCT_CONST_PTR(st) rb_struct_const_ptr(st)
-#define RSTRUCT_PTR(st) ((VALUE *)RSTRUCT_CONST_PTR(RB_OBJ_WB_UNPROTECT_FOR(STRUCT, st)))
-#define RSTRUCT_SET(st, idx, v) RB_OBJ_WRITE(st, &RSTRUCT_CONST_PTR(st)[idx], (v))
-#define RSTRUCT_GET(st, idx) (RSTRUCT_CONST_PTR(st)[idx])
-#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
-
-static inline long
-rb_struct_len(VALUE st)
-{
- return (RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ?
- RSTRUCT_EMBED_LEN(st) : RSTRUCT(st)->as.heap.len;
-}
-
-static inline const VALUE *
-rb_struct_const_ptr(VALUE st)
-{
- return FIX_CONST_VALUE_PTR((RBASIC(st)->flags & RSTRUCT_EMBED_LEN_MASK) ?
- RSTRUCT(st)->as.ary : RSTRUCT(st)->as.heap.ptr);
-}
-
-static inline const VALUE *
-rb_struct_const_heap_ptr(VALUE st)
-{
- /* TODO: check embed on debug mode */
- return RSTRUCT(st)->as.heap.ptr;
-}
-
-/* class.c */
-
-struct rb_deprecated_classext_struct {
- char conflict[sizeof(VALUE) * 3];
-};
-
-struct rb_subclass_entry;
-typedef struct rb_subclass_entry rb_subclass_entry_t;
-
-struct rb_subclass_entry {
- VALUE klass;
- rb_subclass_entry_t *next;
-};
-
-#if defined(HAVE_LONG_LONG)
-typedef unsigned LONG_LONG rb_serial_t;
-#define SERIALT2NUM ULL2NUM
-#define PRI_SERIALT_PREFIX PRI_LL_PREFIX
-#define SIZEOF_SERIAL_T SIZEOF_LONG_LONG
-#elif defined(HAVE_UINT64_T)
-typedef uint64_t rb_serial_t;
-#define SERIALT2NUM SIZET2NUM
-#define PRI_SERIALT_PREFIX PRI_64_PREFIX
-#define SIZEOF_SERIAL_T SIZEOF_UINT64_T
-#else
-typedef unsigned long rb_serial_t;
-#define SERIALT2NUM ULONG2NUM
-#define PRI_SERIALT_PREFIX PRI_LONG_PREFIX
-#define SIZEOF_SERIAL_T SIZEOF_LONG
-#endif
-
-struct rb_classext_struct {
- struct st_table *iv_index_tbl;
- struct st_table *iv_tbl;
-#if SIZEOF_SERIAL_T == SIZEOF_VALUE /* otherwise m_tbl is in struct RClass */
- struct rb_id_table *m_tbl;
-#endif
- struct rb_id_table *const_tbl;
- struct rb_id_table *callable_m_tbl;
- rb_subclass_entry_t *subclasses;
- rb_subclass_entry_t **parent_subclasses;
- /**
- * In the case that this is an `ICLASS`, `module_subclasses` points to the link
- * in the module's `subclasses` list that indicates that the klass has been
- * included. Hopefully that makes sense.
- */
- rb_subclass_entry_t **module_subclasses;
-#if SIZEOF_SERIAL_T != SIZEOF_VALUE /* otherwise class_serial is in struct RClass */
- rb_serial_t class_serial;
-#endif
- const VALUE origin_;
- const VALUE refined_class;
- rb_alloc_func_t allocator;
- const VALUE includer;
-};
-
-typedef struct rb_classext_struct rb_classext_t;
-
-#undef RClass
-struct RClass {
- struct RBasic basic;
- VALUE super;
- rb_classext_t *ptr;
-#if SIZEOF_SERIAL_T == SIZEOF_VALUE
- /* Class serial is as wide as VALUE. Place it here. */
- rb_serial_t class_serial;
-#else
- /* Class serial does not fit into struct RClass. Place m_tbl instead. */
- struct rb_id_table *m_tbl;
-#endif
-};
-
-void rb_class_subclass_add(VALUE super, VALUE klass);
-void rb_class_remove_from_super_subclasses(VALUE);
-int rb_singleton_class_internal_p(VALUE sklass);
-
-#define RCLASS_EXT(c) (RCLASS(c)->ptr)
-#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl)
-#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl)
-#if SIZEOF_SERIAL_T == SIZEOF_VALUE
-# define RCLASS_M_TBL(c) (RCLASS_EXT(c)->m_tbl)
-#else
-# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
-#endif
-#define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl)
-#define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl)
-#define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_)
-#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class)
-#if SIZEOF_SERIAL_T == SIZEOF_VALUE
-# define RCLASS_SERIAL(c) (RCLASS(c)->class_serial)
-#else
-# define RCLASS_SERIAL(c) (RCLASS_EXT(c)->class_serial)
-#endif
-#define RCLASS_INCLUDER(c) (RCLASS_EXT(c)->includer)
-
-#define RCLASS_CLONED FL_USER6
-#define RICLASS_IS_ORIGIN FL_USER5
-#define RCLASS_REFINED_BY_ANY FL_USER7
-
-static inline void
-RCLASS_SET_ORIGIN(VALUE klass, VALUE origin)
-{
- RB_OBJ_WRITE(klass, &RCLASS_ORIGIN(klass), origin);
- if (klass != origin) FL_SET(origin, RICLASS_IS_ORIGIN);
-}
-
-static inline void
-RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass)
-{
- RB_OBJ_WRITE(iclass, &RCLASS_INCLUDER(iclass), klass);
-}
-
-#undef RCLASS_SUPER
-static inline VALUE
-RCLASS_SUPER(VALUE klass)
-{
- return RCLASS(klass)->super;
-}
-
-static inline VALUE
-RCLASS_SET_SUPER(VALUE klass, VALUE super)
-{
- if (super) {
- rb_class_remove_from_super_subclasses(klass);
- rb_class_subclass_add(super, klass);
- }
- RB_OBJ_WRITE(klass, &RCLASS(klass)->super, super);
- return super;
-}
-/* IMEMO: Internal memo object */
-
-#ifndef IMEMO_DEBUG
-#define IMEMO_DEBUG 0
-#endif
-
-struct RIMemo {
- VALUE flags;
- VALUE v0;
- VALUE v1;
- VALUE v2;
- VALUE v3;
-};
-
-enum imemo_type {
- imemo_env = 0,
- imemo_cref = 1, /*!< class reference */
- imemo_svar = 2, /*!< special variable */
- imemo_throw_data = 3,
- imemo_ifunc = 4, /*!< iterator function */
- imemo_memo = 5,
- imemo_ment = 6,
- imemo_iseq = 7,
- imemo_tmpbuf = 8,
- imemo_ast = 9,
- imemo_parser_strterm = 10
-};
-#define IMEMO_MASK 0x0f
-
-static inline enum imemo_type
-imemo_type(VALUE imemo)
-{
- return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK;
-}
-
-static inline int
-imemo_type_p(VALUE imemo, enum imemo_type imemo_type)
-{
- if (LIKELY(!RB_SPECIAL_CONST_P(imemo))) {
- /* fixed at compile time if imemo_type is given. */
- const VALUE mask = (IMEMO_MASK << FL_USHIFT) | RUBY_T_MASK;
- const VALUE expected_type = (imemo_type << FL_USHIFT) | T_IMEMO;
- /* fixed at runtime. */
- return expected_type == (RBASIC(imemo)->flags & mask);
- }
- else {
- return 0;
- }
-}
-
-VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
-
-/* FL_USER0 to FL_USER3 is for type */
-#define IMEMO_FL_USHIFT (FL_USHIFT + 4)
-#define IMEMO_FL_USER0 FL_USER4
-#define IMEMO_FL_USER1 FL_USER5
-#define IMEMO_FL_USER2 FL_USER6
-#define IMEMO_FL_USER3 FL_USER7
-#define IMEMO_FL_USER4 FL_USER8
-
-/* CREF (Class REFerence) is defined in method.h */
-
-/*! SVAR (Special VARiable) */
-struct vm_svar {
- VALUE flags;
- const VALUE cref_or_me; /*!< class reference or rb_method_entry_t */
- const VALUE lastline;
- const VALUE backref;
- const VALUE others;
-};
-
-
-#define THROW_DATA_CONSUMED IMEMO_FL_USER0
-
-/*! THROW_DATA */
-struct vm_throw_data {
- VALUE flags;
- VALUE reserved;
- const VALUE throw_obj;
- const struct rb_control_frame_struct *catch_frame;
- int throw_state;
-};
-
-#define THROW_DATA_P(err) RB_TYPE_P((VALUE)(err), T_IMEMO)
-
-/* IFUNC (Internal FUNCtion) */
-
-struct vm_ifunc_argc {
-#if SIZEOF_INT * 2 > SIZEOF_VALUE
- signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2;
- signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2;
-#else
- int min, max;
-#endif
-};
-
-/*! IFUNC (Internal FUNCtion) */
-struct vm_ifunc {
- VALUE flags;
- VALUE reserved;
- rb_block_call_func_t func;
- const void *data;
- struct vm_ifunc_argc argc;
-};
-
-#define IFUNC_NEW(a, b, c) ((struct vm_ifunc *)rb_imemo_new(imemo_ifunc, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0))
-struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
-static inline struct vm_ifunc *
-rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data)
-{
- return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS);
-}
-
-typedef struct rb_imemo_tmpbuf_struct {
- VALUE flags;
- VALUE reserved;
- VALUE *ptr; /* malloc'ed buffer */
- struct rb_imemo_tmpbuf_struct *next; /* next imemo */
- size_t cnt; /* buffer size in VALUE */
-} rb_imemo_tmpbuf_t;
-
-#define rb_imemo_tmpbuf_auto_free_pointer() rb_imemo_new(imemo_tmpbuf, 0, 0, 0, 0)
-rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
-
-#define RB_IMEMO_TMPBUF_PTR(v) \
- ((void *)(((const struct rb_imemo_tmpbuf_struct *)(v))->ptr))
-
-static inline void *
-rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr)
-{
- return ((rb_imemo_tmpbuf_t *)v)->ptr = ptr;
-}
-
-static inline VALUE
-rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str)
-{
- const void *src;
- VALUE imemo;
- rb_imemo_tmpbuf_t *tmpbuf;
- void *dst;
- size_t len;
-
- SafeStringValue(str);
- /* create tmpbuf to keep the pointer before xmalloc */
- imemo = rb_imemo_tmpbuf_auto_free_pointer();
- tmpbuf = (rb_imemo_tmpbuf_t *)imemo;
- len = RSTRING_LEN(str);
- src = RSTRING_PTR(str);
- dst = ruby_xmalloc(len);
- memcpy(dst, src, len);
- tmpbuf->ptr = dst;
- return imemo;
-}
-
-void rb_strterm_mark(VALUE obj);
-
-/*! MEMO
- *
- * @see imemo_type
- * */
-struct MEMO {
- VALUE flags;
- VALUE reserved;
- const VALUE v1;
- const VALUE v2;
- union {
- long cnt;
- long state;
- const VALUE value;
- void (*func)(void);
- } u3;
-};
-
-#define MEMO_V1_SET(m, v) RB_OBJ_WRITE((m), &(m)->v1, (v))
-#define MEMO_V2_SET(m, v) RB_OBJ_WRITE((m), &(m)->v2, (v))
-
-#define MEMO_CAST(m) ((struct MEMO *)m)
-
-#define MEMO_NEW(a, b, c) ((struct MEMO *)rb_imemo_new(imemo_memo, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0))
-
-#define roomof(x, y) (((x) + (y) - 1) / (y))
-#define type_roomof(x, y) roomof(sizeof(x), sizeof(y))
-#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value))
-#define NEW_MEMO_FOR(type, value) \
- ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value))
-#define NEW_PARTIAL_MEMO_FOR(type, value, member) \
- ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), \
- rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \
- MEMO_FOR(type, value))
-
-#define STRING_P(s) (RB_TYPE_P((s), T_STRING) && CLASS_OF(s) == rb_cString)
-
-#ifdef RUBY_INTEGER_UNIFICATION
-# define rb_cFixnum rb_cInteger
-# define rb_cBignum rb_cInteger
-#endif
-enum {
- cmp_opt_Fixnum,
- cmp_opt_String,
- cmp_opt_Float,
- cmp_optimizable_count
-};
+/* Also, we keep the following macros here. They are expected to be
+ * overridden in each headers. */
-struct cmp_opt_data {
- unsigned int opt_methods;
- unsigned int opt_inited;
-};
+/* internal/array.h */
+#define rb_ary_new_from_args(...) rb_nonexistent_symbol(__VA_ARGS__)
-#define NEW_CMP_OPT_MEMO(type, value) \
- NEW_PARTIAL_MEMO_FOR(type, value, cmp_opt)
-#define CMP_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(cmp_opt_,type))
-#define CMP_OPTIMIZABLE(data, type) \
- (((data).opt_inited & CMP_OPTIMIZABLE_BIT(type)) ? \
- ((data).opt_methods & CMP_OPTIMIZABLE_BIT(type)) : \
- (((data).opt_inited |= CMP_OPTIMIZABLE_BIT(type)), \
- rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \
- ((data).opt_methods |= CMP_OPTIMIZABLE_BIT(type))))
+/* internal/io.h */
+#define rb_io_fptr_finalize(...) rb_nonexistent_symbol(__VA_ARGS__)
-#define OPTIMIZED_CMP(a, b, data) \
- ((FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data, Fixnum)) ? \
- (((long)a > (long)b) ? 1 : ((long)a < (long)b) ? -1 : 0) : \
- (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data, String)) ? \
- rb_str_cmp(a, b) : \
- (RB_FLOAT_TYPE_P(a) && RB_FLOAT_TYPE_P(b) && CMP_OPTIMIZABLE(data, Float)) ? \
- rb_float_cmp(a, b) : \
- rb_cmpint(rb_funcallv(a, id_cmp, 1, &b), a, b))
+/* internal/string.h */
+#define rb_fstring_cstr(...) rb_nonexistent_symbol(__VA_ARGS__)
-/* ment is in method.h */
+/* internal/symbol.h */
+#define rb_sym_intern_ascii_cstr(...) rb_nonexistent_symbol(__VA_ARGS__)
-/* global variable */
+/* internal/vm.h */
+#define rb_funcallv(...) rb_nonexistent_symbol(__VA_ARGS__)
+#define rb_method_basic_definition_p(...) rb_nonexistent_symbol(__VA_ARGS__)
-struct rb_global_entry {
- struct rb_global_variable *var;
- ID id;
-};
-
-struct rb_global_entry *rb_global_entry(ID);
-VALUE rb_gvar_get(struct rb_global_entry *);
-VALUE rb_gvar_set(struct rb_global_entry *, VALUE);
-VALUE rb_gvar_defined(struct rb_global_entry *);
-
-/* array.c */
-
-#ifndef ARRAY_DEBUG
-#define ARRAY_DEBUG (0+RUBY_DEBUG)
-#endif
-
-#ifdef ARRAY_DEBUG
-#define RARRAY_PTR_IN_USE_FLAG FL_USER14
-#define ARY_PTR_USING_P(ary) FL_TEST_RAW((ary), RARRAY_PTR_IN_USE_FLAG)
-#else
-
-/* disable debug function */
-#undef RARRAY_PTR_USE_START_TRANSIENT
-#undef RARRAY_PTR_USE_END_TRANSIENT
-#define RARRAY_PTR_USE_START_TRANSIENT(a) ((VALUE *)RARRAY_CONST_PTR_TRANSIENT(a))
-#define RARRAY_PTR_USE_END_TRANSIENT(a)
-#define ARY_PTR_USING_P(ary) 0
-
-#endif
-
-#if USE_TRANSIENT_HEAP
-#define RARY_TRANSIENT_SET(ary) FL_SET_RAW((ary), RARRAY_TRANSIENT_FLAG);
-#define RARY_TRANSIENT_UNSET(ary) FL_UNSET_RAW((ary), RARRAY_TRANSIENT_FLAG);
-#else
-#undef RARRAY_TRANSIENT_P
-#define RARRAY_TRANSIENT_P(a) 0
-#define RARY_TRANSIENT_SET(ary) ((void)0)
-#define RARY_TRANSIENT_UNSET(ary) ((void)0)
-#endif
-
-
-VALUE rb_ary_last(int, const VALUE *, VALUE);
-void rb_ary_set_len(VALUE, long);
-void rb_ary_delete_same(VALUE, VALUE);
-VALUE rb_ary_tmp_new_fill(long capa);
-VALUE rb_ary_at(VALUE, VALUE);
-VALUE rb_ary_aref1(VALUE ary, VALUE i);
-size_t rb_ary_memsize(VALUE);
-VALUE rb_to_array_type(VALUE obj);
-VALUE rb_check_to_array(VALUE ary);
-VALUE rb_ary_tmp_new_from_values(VALUE, long, const VALUE *);
-VALUE rb_ary_behead(VALUE, long);
-#if defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO)
-#define rb_ary_new_from_args(n, ...) \
- __extension__ ({ \
- const VALUE args_to_new_ary[] = {__VA_ARGS__}; \
- if (__builtin_constant_p(n)) { \
- STATIC_ASSERT(rb_ary_new_from_args, numberof(args_to_new_ary) == (n)); \
- } \
- rb_ary_new_from_values(numberof(args_to_new_ary), args_to_new_ary); \
- })
-#endif
-
-static inline VALUE
-rb_ary_entry_internal(VALUE ary, long offset)
-{
- long len = RARRAY_LEN(ary);
- const VALUE *ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
- if (len == 0) return Qnil;
- if (offset < 0) {
- offset += len;
- if (offset < 0) return Qnil;
- }
- else if (len <= offset) {
- return Qnil;
- }
- return ptr[offset];
-}
/* MRI debug support */
+
+/* gc.c */
void rb_obj_info_dump(VALUE obj);
void rb_obj_info_dump_loc(VALUE obj, const char *file, int line, const char *func);
+
+/* debug.c */
+
+RUBY_SYMBOL_EXPORT_BEGIN
void ruby_debug_breakpoint(void);
+PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2);
+RUBY_SYMBOL_EXPORT_END
// show obj data structure without any side-effect
-#define rp(obj) rb_obj_info_dump_loc((VALUE)(obj), __FILE__, __LINE__, __func__)
+#define rp(obj) rb_obj_info_dump_loc((VALUE)(obj), __FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING)
// same as rp, but add message header
#define rp_m(msg, obj) do { \
@@ -1444,1277 +104,4 @@ void ruby_debug_breakpoint(void);
// but breakpoint is set in run.gdb, so `make gdb` can stop here.
#define bp() ruby_debug_breakpoint()
-/* bignum.c */
-extern const char ruby_digitmap[];
-double rb_big_fdiv_double(VALUE x, VALUE y);
-VALUE rb_big_uminus(VALUE x);
-VALUE rb_big_hash(VALUE);
-VALUE rb_big_odd_p(VALUE);
-VALUE rb_big_even_p(VALUE);
-size_t rb_big_size(VALUE);
-VALUE rb_integer_float_cmp(VALUE x, VALUE y);
-VALUE rb_integer_float_eq(VALUE x, VALUE y);
-VALUE rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception);
-VALUE rb_big_comp(VALUE x);
-VALUE rb_big_aref(VALUE x, VALUE y);
-VALUE rb_big_abs(VALUE x);
-VALUE rb_big_size_m(VALUE big);
-VALUE rb_big_bit_length(VALUE big);
-VALUE rb_big_remainder(VALUE x, VALUE y);
-VALUE rb_big_gt(VALUE x, VALUE y);
-VALUE rb_big_ge(VALUE x, VALUE y);
-VALUE rb_big_lt(VALUE x, VALUE y);
-VALUE rb_big_le(VALUE x, VALUE y);
-VALUE rb_int_powm(int const argc, VALUE * const argv, VALUE const num);
-
-/* class.c */
-VALUE rb_class_boot(VALUE);
-VALUE rb_class_inherited(VALUE, VALUE);
-VALUE rb_make_metaclass(VALUE, VALUE);
-VALUE rb_include_class_new(VALUE, VALUE);
-void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE);
-void rb_class_detach_subclasses(VALUE);
-void rb_class_detach_module_subclasses(VALUE);
-void rb_class_remove_from_module_subclasses(VALUE);
-VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj);
-VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj);
-VALUE rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj);
-VALUE rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj);
-VALUE rb_special_singleton_class(VALUE);
-VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach);
-VALUE rb_singleton_class_get(VALUE obj);
-void Init_class_hierarchy(void);
-
-int rb_class_has_methods(VALUE c);
-void rb_undef_methods_from(VALUE klass, VALUE super);
-
-/* compar.c */
-VALUE rb_invcmp(VALUE, VALUE);
-
-/* compile.c */
-struct rb_block;
-struct rb_iseq_struct;
-int rb_dvar_defined(ID, const struct rb_iseq_struct *);
-int rb_local_defined(ID, const struct rb_iseq_struct *);
-const char * rb_insns_name(int i);
-VALUE rb_insns_name_array(void);
-int rb_vm_insn_addr2insn(const void *);
-
-/* complex.c */
-VALUE rb_dbl_complex_new_polar_pi(double abs, double ang);
-
-struct rb_thread_struct;
-/* cont.c */
-struct rb_fiber_struct;
-VALUE rb_obj_is_fiber(VALUE);
-void rb_fiber_reset_root_local_storage(struct rb_thread_struct *);
-void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(VALUE), VALUE (*rollback_func)(VALUE));
-void rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber);
-
-/* debug.c */
-PRINTF_ARGS(void ruby_debug_printf(const char*, ...), 1, 2);
-
-/* dir.c */
-VALUE rb_dir_getwd_ospath(void);
-
-/* dmyext.c */
-void Init_enc(void);
-void Init_ext(void);
-
-/* encoding.c */
-ID rb_id_encoding(void);
-#ifdef RUBY_ENCODING_H
-rb_encoding *rb_enc_get_from_index(int index);
-rb_encoding *rb_enc_check_str(VALUE str1, VALUE str2);
-#endif
-int rb_encdb_replicate(const char *alias, const char *orig);
-int rb_encdb_alias(const char *alias, const char *orig);
-int rb_encdb_dummy(const char *name);
-void rb_encdb_declare(const char *name);
-void rb_enc_set_base(const char *name, const char *orig);
-int rb_enc_set_dummy(int index);
-void rb_encdb_set_unicode(int index);
-PUREFUNC(int rb_data_is_encoding(VALUE obj));
-
-/* enum.c */
-extern VALUE rb_cArithSeq;
-VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
-VALUE rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary);
-
-/* error.c */
-extern VALUE rb_eEAGAIN;
-extern VALUE rb_eEWOULDBLOCK;
-extern VALUE rb_eEINPROGRESS;
-void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args);
-NORETURN(void rb_async_bug_errno(const char *,int));
-const char *rb_builtin_type_name(int t);
-const char *rb_builtin_class_name(VALUE x);
-PRINTF_ARGS(void rb_warn_deprecated(const char *fmt, const char *suggest, ...), 1, 3);
-#ifdef RUBY_ENCODING_H
-VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*, va_list);
-PRINTF_ARGS(void rb_enc_warn(rb_encoding *enc, const char *fmt, ...), 2, 3);
-PRINTF_ARGS(void rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...), 2, 3);
-PRINTF_ARGS(void rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...), 3, 4);
-#endif
-
-typedef enum {
- RB_WARN_CATEGORY_NONE,
- RB_WARN_CATEGORY_DEPRECATED,
- RB_WARN_CATEGORY_EXPERIMENTAL,
- RB_WARN_CATEGORY_ALL_BITS = 0x6, /* no RB_WARN_CATEGORY_NONE bit */
-} rb_warning_category_t;
-rb_warning_category_t rb_warning_category_from_name(VALUE category);
-bool rb_warning_category_enabled_p(rb_warning_category_t category);
-
-#define rb_raise_cstr(etype, mesg) \
- rb_exc_raise(rb_exc_new_str(etype, rb_str_new_cstr(mesg)))
-#define rb_raise_static(etype, mesg) \
- rb_exc_raise(rb_exc_new_str(etype, rb_str_new_static(mesg, rb_strlen_lit(mesg))))
-
-VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method);
-#define rb_name_err_raise_str(mesg, recv, name) \
- rb_exc_raise(rb_name_err_new(mesg, recv, name))
-#define rb_name_err_raise(mesg, recv, name) \
- rb_name_err_raise_str(rb_fstring_cstr(mesg), (recv), (name))
-VALUE rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv);
-VALUE rb_key_err_new(VALUE mesg, VALUE recv, VALUE name);
-#define rb_key_err_raise(mesg, recv, name) \
- rb_exc_raise(rb_key_err_new(mesg, recv, name))
-PRINTF_ARGS(VALUE rb_warning_string(const char *fmt, ...), 1, 2);
-NORETURN(void rb_vraise(VALUE, const char *, va_list));
-
-/* eval.c */
-VALUE rb_refinement_module_get_refined_class(VALUE module);
-extern ID ruby_static_id_signo, ruby_static_id_status;
-void rb_class_modify_check(VALUE);
-#define id_signo ruby_static_id_signo
-#define id_status ruby_static_id_status
-NORETURN(VALUE rb_f_raise(int argc, VALUE *argv));
-
-/* eval_error.c */
-VALUE rb_get_backtrace(VALUE info);
-
-/* eval_jump.c */
-void rb_call_end_proc(VALUE data);
-void rb_mark_end_proc(void);
-
-/* file.c */
-extern const char ruby_null_device[];
-VALUE rb_home_dir_of(VALUE user, VALUE result);
-VALUE rb_default_home_dir(VALUE result);
-VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict);
-#ifdef RUBY_ENCODING_H
-VALUE rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *origenc);
-#endif
-void rb_file_const(const char*, VALUE);
-int rb_file_load_ok(const char *);
-VALUE rb_file_expand_path_fast(VALUE, VALUE);
-VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE);
-VALUE rb_get_path_check_to_string(VALUE);
-VALUE rb_get_path_check_convert(VALUE);
-void Init_File(void);
-int ruby_is_fd_loadable(int fd);
-
-#ifdef RUBY_FUNCTION_NAME_STRING
-# if defined __GNUC__ && __GNUC__ >= 4
-# pragma GCC visibility push(default)
-# endif
-NORETURN(void rb_sys_fail_path_in(const char *func_name, VALUE path));
-NORETURN(void rb_syserr_fail_path_in(const char *func_name, int err, VALUE path));
-# if defined __GNUC__ && __GNUC__ >= 4
-# pragma GCC visibility pop
-# endif
-# define rb_sys_fail_path(path) rb_sys_fail_path_in(RUBY_FUNCTION_NAME_STRING, path)
-# define rb_syserr_fail_path(err, path) rb_syserr_fail_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path))
-#else
-# define rb_sys_fail_path(path) rb_sys_fail_str(path)
-# define rb_syserr_fail_path(err, path) rb_syserr_fail_str((err), (path))
-#endif
-
-/* gc.c */
-extern VALUE *ruby_initial_gc_stress_ptr;
-extern int ruby_disable_gc;
-struct rb_objspace; /* in vm_core.h */
-void Init_heap(void);
-void *ruby_mimmalloc(size_t size) RUBY_ATTR_MALLOC;
-void ruby_mimfree(void *ptr);
-void rb_objspace_set_event_hook(const rb_event_flag_t event);
-VALUE rb_objspace_gc_enable(struct rb_objspace *);
-VALUE rb_objspace_gc_disable(struct rb_objspace *);
-#if USE_RGENGC
-void rb_gc_writebarrier_remember(VALUE obj);
-#else
-#define rb_gc_writebarrier_remember(obj) 0
-#endif
-void ruby_gc_set_params(void);
-void rb_copy_wb_protected_attribute(VALUE dest, VALUE obj);
-
-#if defined(HAVE_MALLOC_USABLE_SIZE) || defined(HAVE_MALLOC_SIZE) || defined(_WIN32)
-#define ruby_sized_xrealloc(ptr, new_size, old_size) ruby_xrealloc(ptr, new_size)
-#define ruby_sized_xrealloc2(ptr, new_count, element_size, old_count) ruby_xrealloc2(ptr, new_count, element_size)
-#define ruby_sized_xfree(ptr, size) ruby_xfree(ptr)
-#define SIZED_REALLOC_N(var,type,n,old_n) REALLOC_N(var, type, n)
-#else
-RUBY_SYMBOL_EXPORT_BEGIN
-void *ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2));
-void *ruby_sized_xrealloc2(void *ptr, size_t new_count, size_t element_size, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3));
-void ruby_sized_xfree(void *x, size_t size);
-RUBY_SYMBOL_EXPORT_END
-#define SIZED_REALLOC_N(var,type,n,old_n) ((var)=(type*)ruby_sized_xrealloc2((void*)(var), (n), sizeof(type), (old_n)))
-#endif
-
-/* optimized version of NEWOBJ() */
-#undef NEWOBJF_OF
-#undef RB_NEWOBJ_OF
-#define RB_NEWOBJ_OF(obj,type,klass,flags) \
- type *(obj) = (type*)(((flags) & FL_WB_PROTECTED) ? \
- rb_wb_protected_newobj_of(klass, (flags) & ~FL_WB_PROTECTED) : \
- rb_wb_unprotected_newobj_of(klass, flags))
-#define NEWOBJ_OF(obj,type,klass,flags) RB_NEWOBJ_OF(obj,type,klass,flags)
-
-#ifdef __has_attribute
-#if __has_attribute(alloc_align)
-__attribute__((__alloc_align__(1)))
-#endif
-#endif
-void *rb_aligned_malloc(size_t, size_t) RUBY_ATTR_MALLOC RUBY_ATTR_ALLOC_SIZE((2));
-
-size_t rb_size_mul_or_raise(size_t, size_t, VALUE); /* used in compile.c */
-size_t rb_size_mul_add_or_raise(size_t, size_t, size_t, VALUE); /* used in iseq.h */
-void *rb_xmalloc_mul_add(size_t, size_t, size_t) RUBY_ATTR_MALLOC;
-void *rb_xrealloc_mul_add(const void *, size_t, size_t, size_t);
-void *rb_xmalloc_mul_add_mul(size_t, size_t, size_t, size_t) RUBY_ATTR_MALLOC;
-void *rb_xcalloc_mul_add_mul(size_t, size_t, size_t, size_t) RUBY_ATTR_MALLOC;
-
-/* hash.c */
-#if RHASH_CONVERT_TABLE_DEBUG
-struct st_table *rb_hash_tbl_raw(VALUE hash, const char *file, int line);
-#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h, __FILE__, __LINE__)
-#else
-struct st_table *rb_hash_tbl_raw(VALUE hash);
-#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h)
-#endif
-
-VALUE rb_hash_new_with_size(st_index_t size);
-VALUE rb_hash_has_key(VALUE hash, VALUE key);
-VALUE rb_hash_default_value(VALUE hash, VALUE key);
-VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc);
-long rb_dbl_long_hash(double d);
-st_table *rb_init_identtable(void);
-VALUE rb_hash_compare_by_id_p(VALUE hash);
-VALUE rb_to_hash_type(VALUE obj);
-VALUE rb_hash_key_str(VALUE);
-VALUE rb_hash_keys(VALUE hash);
-VALUE rb_hash_values(VALUE hash);
-VALUE rb_hash_rehash(VALUE hash);
-VALUE rb_hash_resurrect(VALUE hash);
-int rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val);
-VALUE rb_hash_set_pair(VALUE hash, VALUE pair);
-
-int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval);
-int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval);
-RUBY_SYMBOL_EXPORT_BEGIN
-int rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg);
-RUBY_SYMBOL_EXPORT_END
-int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg);
-int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func func, st_data_t arg);
-
-/* inits.c */
-void rb_call_inits(void);
-
-/* io.c */
-void ruby_set_inplace_mode(const char *);
-void rb_stdio_set_default_encoding(void);
-VALUE rb_io_flush_raw(VALUE, int);
-#ifdef RUBY_IO_H
-size_t rb_io_memsize(const rb_io_t *);
-#endif
-int rb_stderr_tty_p(void);
-void rb_io_fptr_finalize_internal(void *ptr);
-#define rb_io_fptr_finalize rb_io_fptr_finalize_internal
-
-/* load.c */
-VALUE rb_get_expanded_load_path(void);
-int rb_require_internal(VALUE fname);
-NORETURN(void rb_load_fail(VALUE, const char*));
-
-/* loadpath.c */
-extern const char ruby_exec_prefix[];
-extern const char ruby_initial_load_paths[];
-
-/* localeinit.c */
-int Init_enc_set_filesystem_encoding(void);
-
-/* math.c */
-VALUE rb_math_atan2(VALUE, VALUE);
-VALUE rb_math_cos(VALUE);
-VALUE rb_math_cosh(VALUE);
-VALUE rb_math_exp(VALUE);
-VALUE rb_math_hypot(VALUE, VALUE);
-VALUE rb_math_log(int argc, const VALUE *argv);
-VALUE rb_math_sin(VALUE);
-VALUE rb_math_sinh(VALUE);
-
-/* mjit.c */
-
-#if USE_MJIT
-extern bool mjit_enabled;
-VALUE mjit_pause(bool wait_p);
-VALUE mjit_resume(void);
-void mjit_finish(bool close_handle_p);
-#else
-#define mjit_enabled 0
-static inline VALUE mjit_pause(bool wait_p){ return Qnil; } // unreachable
-static inline VALUE mjit_resume(void){ return Qnil; } // unreachable
-static inline void mjit_finish(bool close_handle_p){}
-#endif
-
-/* newline.c */
-void Init_newline(void);
-
-/* numeric.c */
-
-#define FIXNUM_POSITIVE_P(num) ((SIGNED_VALUE)(num) > (SIGNED_VALUE)INT2FIX(0))
-#define FIXNUM_NEGATIVE_P(num) ((SIGNED_VALUE)(num) < 0)
-#define FIXNUM_ZERO_P(num) ((num) == INT2FIX(0))
-
-#define INT_NEGATIVE_P(x) (FIXNUM_P(x) ? FIXNUM_NEGATIVE_P(x) : BIGNUM_NEGATIVE_P(x))
-
-#define FLOAT_ZERO_P(x) (RFLOAT_VALUE(x) == 0.0)
-
-#ifndef ROUND_DEFAULT
-# define ROUND_DEFAULT RUBY_NUM_ROUND_HALF_UP
-#endif
-enum ruby_num_rounding_mode {
- RUBY_NUM_ROUND_HALF_UP,
- RUBY_NUM_ROUND_HALF_EVEN,
- RUBY_NUM_ROUND_HALF_DOWN,
- RUBY_NUM_ROUND_DEFAULT = ROUND_DEFAULT
-};
-#define ROUND_TO(mode, even, up, down) \
- ((mode) == RUBY_NUM_ROUND_HALF_EVEN ? even : \
- (mode) == RUBY_NUM_ROUND_HALF_UP ? up : down)
-#define ROUND_FUNC(mode, name) \
- ROUND_TO(mode, name##_half_even, name##_half_up, name##_half_down)
-#define ROUND_CALL(mode, name, args) \
- ROUND_TO(mode, name##_half_even args, \
- name##_half_up args, name##_half_down args)
-
-int rb_num_to_uint(VALUE val, unsigned int *ret);
-VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl);
-double ruby_float_step_size(double beg, double end, double unit, int excl);
-int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless);
-double ruby_float_mod(double x, double y);
-int rb_num_negative_p(VALUE);
-VALUE rb_int_succ(VALUE num);
-VALUE rb_int_uminus(VALUE num);
-VALUE rb_float_uminus(VALUE num);
-VALUE rb_int_plus(VALUE x, VALUE y);
-VALUE rb_float_plus(VALUE x, VALUE y);
-VALUE rb_int_minus(VALUE x, VALUE y);
-VALUE rb_float_minus(VALUE x, VALUE y);
-VALUE rb_int_mul(VALUE x, VALUE y);
-VALUE rb_float_mul(VALUE x, VALUE y);
-VALUE rb_float_div(VALUE x, VALUE y);
-VALUE rb_int_idiv(VALUE x, VALUE y);
-VALUE rb_int_modulo(VALUE x, VALUE y);
-VALUE rb_int2str(VALUE num, int base);
-VALUE rb_fix_plus(VALUE x, VALUE y);
-VALUE rb_fix_aref(VALUE fix, VALUE idx);
-VALUE rb_int_gt(VALUE x, VALUE y);
-int rb_float_cmp(VALUE x, VALUE y);
-VALUE rb_float_gt(VALUE x, VALUE y);
-VALUE rb_int_ge(VALUE x, VALUE y);
-enum ruby_num_rounding_mode rb_num_get_rounding_option(VALUE opts);
-double rb_int_fdiv_double(VALUE x, VALUE y);
-VALUE rb_int_pow(VALUE x, VALUE y);
-VALUE rb_float_pow(VALUE x, VALUE y);
-VALUE rb_int_cmp(VALUE x, VALUE y);
-VALUE rb_int_equal(VALUE x, VALUE y);
-VALUE rb_int_divmod(VALUE x, VALUE y);
-VALUE rb_int_and(VALUE x, VALUE y);
-VALUE rb_int_lshift(VALUE x, VALUE y);
-VALUE rb_int_div(VALUE x, VALUE y);
-VALUE rb_int_abs(VALUE num);
-VALUE rb_int_odd_p(VALUE num);
-int rb_int_positive_p(VALUE num);
-int rb_int_negative_p(VALUE num);
-VALUE rb_num_pow(VALUE x, VALUE y);
-VALUE rb_float_ceil(VALUE num, int ndigits);
-VALUE rb_float_floor(VALUE x, int ndigits);
-
-static inline VALUE
-rb_num_compare_with_zero(VALUE num, ID mid)
-{
- VALUE zero = INT2FIX(0);
- VALUE r = rb_check_funcall(num, mid, 1, &zero);
- if (r == Qundef) {
- rb_cmperr(num, zero);
- }
- return r;
-}
-
-static inline int
-rb_num_positive_int_p(VALUE num)
-{
- const ID mid = '>';
-
- if (FIXNUM_P(num)) {
- if (rb_method_basic_definition_p(rb_cInteger, mid))
- return FIXNUM_POSITIVE_P(num);
- }
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- if (rb_method_basic_definition_p(rb_cInteger, mid))
- return BIGNUM_POSITIVE_P(num);
- }
- return RTEST(rb_num_compare_with_zero(num, mid));
-}
-
-
-static inline int
-rb_num_negative_int_p(VALUE num)
-{
- const ID mid = '<';
-
- if (FIXNUM_P(num)) {
- if (rb_method_basic_definition_p(rb_cInteger, mid))
- return FIXNUM_NEGATIVE_P(num);
- }
- else if (RB_TYPE_P(num, T_BIGNUM)) {
- if (rb_method_basic_definition_p(rb_cInteger, mid))
- return BIGNUM_NEGATIVE_P(num);
- }
- return RTEST(rb_num_compare_with_zero(num, mid));
-}
-
-
-VALUE rb_float_abs(VALUE flt);
-VALUE rb_float_equal(VALUE x, VALUE y);
-VALUE rb_float_eql(VALUE x, VALUE y);
-VALUE rb_flo_div_flo(VALUE x, VALUE y);
-
-#if USE_FLONUM
-#define RUBY_BIT_ROTL(v, n) (((v) << (n)) | ((v) >> ((sizeof(v) * 8) - n)))
-#define RUBY_BIT_ROTR(v, n) (((v) >> (n)) | ((v) << ((sizeof(v) * 8) - n)))
-#endif
-
-static inline double
-rb_float_flonum_value(VALUE v)
-{
-#if USE_FLONUM
- if (v != (VALUE)0x8000000000000002) { /* LIKELY */
- union {
- double d;
- VALUE v;
- } t;
-
- VALUE b63 = (v >> 63);
- /* e: xx1... -> 011... */
- /* xx0... -> 100... */
- /* ^b63 */
- t.v = RUBY_BIT_ROTR((2 - b63) | (v & ~(VALUE)0x03), 3);
- return t.d;
- }
-#endif
- return 0.0;
-}
-
-static inline double
-rb_float_noflonum_value(VALUE v)
-{
- return ((struct RFloat *)v)->float_value;
-}
-
-static inline double
-rb_float_value_inline(VALUE v)
-{
- if (FLONUM_P(v)) {
- return rb_float_flonum_value(v);
- }
- return rb_float_noflonum_value(v);
-}
-
-static inline VALUE
-rb_float_new_inline(double d)
-{
-#if USE_FLONUM
- union {
- double d;
- VALUE v;
- } t;
- int bits;
-
- t.d = d;
- bits = (int)((VALUE)(t.v >> 60) & 0x7);
- /* bits contains 3 bits of b62..b60. */
- /* bits - 3 = */
- /* b011 -> b000 */
- /* b100 -> b001 */
-
- if (t.v != 0x3000000000000000 /* 1.72723e-77 */ &&
- !((bits-3) & ~0x01)) {
- return (RUBY_BIT_ROTL(t.v, 3) & ~(VALUE)0x01) | 0x02;
- }
- else if (t.v == (VALUE)0) {
- /* +0.0 */
- return 0x8000000000000002;
- }
- /* out of range */
-#endif
- return rb_float_new_in_heap(d);
-}
-
-#define rb_float_value(v) rb_float_value_inline(v)
-#define rb_float_new(d) rb_float_new_inline(d)
-
-/* object.c */
-void rb_obj_copy_ivar(VALUE dest, VALUE obj);
-CONSTFUNC(VALUE rb_obj_equal(VALUE obj1, VALUE obj2));
-CONSTFUNC(VALUE rb_obj_not(VALUE obj));
-VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
-NORETURN(void rb_undefined_alloc(VALUE klass));
-double rb_num_to_dbl(VALUE val);
-VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound);
-VALUE rb_immutable_obj_clone(int, VALUE *, VALUE);
-VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2);
-VALUE rb_convert_type_with_id(VALUE,int,const char*,ID);
-VALUE rb_check_convert_type_with_id(VALUE,int,const char*,ID);
-int rb_bool_expected(VALUE, const char *);
-
-struct RBasicRaw {
- VALUE flags;
- VALUE klass;
-};
-
-#define RBASIC_CLEAR_CLASS(obj) memset(&(((struct RBasicRaw *)((VALUE)(obj)))->klass), 0, sizeof(VALUE))
-#define RBASIC_SET_CLASS_RAW(obj, cls) memcpy(&((struct RBasicRaw *)((VALUE)(obj)))->klass, &(cls), sizeof(VALUE))
-#define RBASIC_SET_CLASS(obj, cls) do { \
- VALUE _obj_ = (obj); \
- RB_OBJ_WRITE(_obj_, &((struct RBasicRaw *)(_obj_))->klass, cls); \
-} while (0)
-
-/* parse.y */
-#ifndef USE_SYMBOL_GC
-#define USE_SYMBOL_GC 1
-#endif
-VALUE rb_parser_set_yydebug(VALUE, VALUE);
-RUBY_SYMBOL_EXPORT_BEGIN
-VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int);
-RUBY_SYMBOL_EXPORT_END
-void *rb_parser_load_file(VALUE parser, VALUE name);
-int rb_is_const_name(VALUE name);
-int rb_is_class_name(VALUE name);
-int rb_is_instance_name(VALUE name);
-int rb_is_local_name(VALUE name);
-PUREFUNC(int rb_is_const_sym(VALUE sym));
-PUREFUNC(int rb_is_attrset_sym(VALUE sym));
-ID rb_make_internal_id(void);
-void rb_gc_free_dsymbol(VALUE);
-
-/* proc.c */
-VALUE rb_proc_location(VALUE self);
-st_index_t rb_hash_proc(st_index_t hash, VALUE proc);
-int rb_block_arity(void);
-int rb_block_min_max_arity(int *max);
-VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val);
-VALUE rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc);
-VALUE rb_block_to_s(VALUE self, const struct rb_block *block, const char *additional_info);
-
-/* process.c */
-#define RB_MAX_GROUPS (65536)
-
-struct waitpid_state;
-struct rb_execarg {
- union {
- struct {
- VALUE shell_script;
- } sh;
- struct {
- VALUE command_name;
- VALUE command_abspath; /* full path string or nil */
- VALUE argv_str;
- VALUE argv_buf;
- } cmd;
- } invoke;
- VALUE redirect_fds;
- VALUE envp_str;
- VALUE envp_buf;
- VALUE dup2_tmpbuf;
- unsigned use_shell : 1;
- unsigned pgroup_given : 1;
- unsigned umask_given : 1;
- unsigned unsetenv_others_given : 1;
- unsigned unsetenv_others_do : 1;
- unsigned close_others_given : 1;
- unsigned close_others_do : 1;
- unsigned chdir_given : 1;
- unsigned new_pgroup_given : 1;
- unsigned new_pgroup_flag : 1;
- unsigned uid_given : 1;
- unsigned gid_given : 1;
- unsigned exception : 1;
- unsigned exception_given : 1;
- struct waitpid_state *waitpid_state; /* for async process management */
- rb_pid_t pgroup_pgid; /* asis(-1), new pgroup(0), specified pgroup (0<V). */
- VALUE rlimit_limits; /* Qfalse or [[rtype, softlim, hardlim], ...] */
- mode_t umask_mask;
- rb_uid_t uid;
- rb_gid_t gid;
- int close_others_maxhint;
- VALUE fd_dup2;
- VALUE fd_close;
- VALUE fd_open;
- VALUE fd_dup2_child;
- VALUE env_modification; /* Qfalse or [[k1,v1], ...] */
- VALUE path_env;
- VALUE chdir_dir;
-};
-
-/* argv_str contains extra two elements.
- * The beginning one is for /bin/sh used by exec_with_sh.
- * The last one for terminating NULL used by execve.
- * See rb_exec_fillarg() in process.c. */
-#define ARGVSTR2ARGV(argv_str) ((char **)RB_IMEMO_TMPBUF_PTR(argv_str) + 1)
-
-static inline size_t
-ARGVSTR2ARGC(VALUE argv_str)
-{
- size_t i = 0;
- char *const *p = ARGVSTR2ARGV(argv_str);
- while (p[i++])
- ;
- return i - 1;
-}
-
-#ifdef HAVE_PWD_H
-VALUE rb_getlogin(void);
-VALUE rb_getpwdirnam_for_login(VALUE login); /* read as: "get pwd db home dir by username for login" */
-VALUE rb_getpwdiruid(void); /* read as: "get pwd db home dir for getuid()" */
-#endif
-
-rb_pid_t rb_fork_ruby(int *status);
-void rb_last_status_clear(void);
-
-/* range.c */
-#define RANGE_BEG(r) (RSTRUCT(r)->as.ary[0])
-#define RANGE_END(r) (RSTRUCT(r)->as.ary[1])
-#define RANGE_EXCL(r) (RSTRUCT(r)->as.ary[2])
-
-/* rational.c */
-VALUE rb_rational_canonicalize(VALUE x);
-VALUE rb_rational_uminus(VALUE self);
-VALUE rb_rational_plus(VALUE self, VALUE other);
-VALUE rb_rational_minus(VALUE self, VALUE other);
-VALUE rb_rational_mul(VALUE self, VALUE other);
-VALUE rb_rational_div(VALUE self, VALUE other);
-VALUE rb_lcm(VALUE x, VALUE y);
-VALUE rb_rational_reciprocal(VALUE x);
-VALUE rb_cstr_to_rat(const char *, int);
-VALUE rb_rational_abs(VALUE self);
-VALUE rb_rational_cmp(VALUE self, VALUE other);
-VALUE rb_rational_pow(VALUE self, VALUE other);
-VALUE rb_rational_floor(VALUE self, int ndigits);
-VALUE rb_numeric_quo(VALUE x, VALUE y);
-VALUE rb_float_numerator(VALUE x);
-VALUE rb_float_denominator(VALUE x);
-
-/* re.c */
-VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline);
-VALUE rb_reg_check_preprocess(VALUE);
-long rb_reg_search0(VALUE, VALUE, long, int, int);
-VALUE rb_reg_match_p(VALUE re, VALUE str, long pos);
-bool rb_reg_start_with_p(VALUE re, VALUE str);
-void rb_backref_set_string(VALUE string, long pos, long len);
-void rb_match_unbusy(VALUE);
-int rb_match_count(VALUE match);
-int rb_match_nth_defined(int nth, VALUE match);
-VALUE rb_reg_new_ary(VALUE ary, int options);
-
-/* signal.c */
-extern int ruby_enable_coredump;
-int rb_get_next_signal(void);
-
-/* string.c */
-VALUE rb_fstring(VALUE);
-VALUE rb_fstring_new(const char *ptr, long len);
-#define rb_fstring_lit(str) rb_fstring_new((str), rb_strlen_lit(str))
-#define rb_fstring_literal(str) rb_fstring_lit(str)
-VALUE rb_fstring_cstr(const char *str);
-#ifdef HAVE_BUILTIN___BUILTIN_CONSTANT_P
-# define rb_fstring_cstr(str) RB_GNUC_EXTENSION_BLOCK( \
- (__builtin_constant_p(str)) ? \
- rb_fstring_new((str), (long)strlen(str)) : \
- rb_fstring_cstr(str) \
-)
-#endif
-#ifdef RUBY_ENCODING_H
-VALUE rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc);
-#define rb_fstring_enc_lit(str, enc) rb_fstring_enc_new((str), rb_strlen_lit(str), (enc))
-#define rb_fstring_enc_literal(str, enc) rb_fstring_enc_lit(str, enc)
-#endif
-int rb_str_buf_cat_escaped_char(VALUE result, unsigned int c, int unicode_p);
-int rb_str_symname_p(VALUE);
-VALUE rb_str_quote_unprintable(VALUE);
-VALUE rb_id_quote_unprintable(ID);
-#define QUOTE(str) rb_str_quote_unprintable(str)
-#define QUOTE_ID(id) rb_id_quote_unprintable(id)
-char *rb_str_fill_terminator(VALUE str, const int termlen);
-void rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen);
-VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg);
-VALUE rb_str_chomp_string(VALUE str, VALUE chomp);
-#ifdef RUBY_ENCODING_H
-VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc);
-VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
- rb_encoding *from, int ecflags, VALUE ecopts);
-VALUE rb_enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl);
-VALUE rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc);
-#endif
-#define STR_NOEMBED FL_USER1
-#define STR_SHARED FL_USER2 /* = ELTS_SHARED */
-#define STR_EMBED_P(str) (!FL_TEST_RAW((str), STR_NOEMBED))
-#define STR_SHARED_P(s) FL_ALL_RAW((s), STR_NOEMBED|ELTS_SHARED)
-#define is_ascii_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)
-#define is_broken_string(str) (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN)
-size_t rb_str_memsize(VALUE);
-VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc);
-VALUE rb_sym_to_proc(VALUE sym);
-char *rb_str_to_cstr(VALUE str);
-VALUE rb_str_eql(VALUE str1, VALUE str2);
-VALUE rb_obj_as_string_result(VALUE str, VALUE obj);
-const char *ruby_escaped_char(int c);
-VALUE rb_str_opt_plus(VALUE, VALUE);
-
-/* expect tail call optimization */
-static inline VALUE
-rb_str_eql_internal(const VALUE str1, const VALUE str2)
-{
- const long len = RSTRING_LEN(str1);
- const char *ptr1, *ptr2;
-
- if (len != RSTRING_LEN(str2)) return Qfalse;
- if (!rb_str_comparable(str1, str2)) return Qfalse;
- if ((ptr1 = RSTRING_PTR(str1)) == (ptr2 = RSTRING_PTR(str2)))
- return Qtrue;
- if (memcmp(ptr1, ptr2, len) == 0)
- return Qtrue;
- return Qfalse;
-}
-
-/* symbol.c */
-#ifdef RUBY_ENCODING_H
-VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc);
-#endif
-VALUE rb_sym_intern_ascii(const char *ptr, long len);
-VALUE rb_sym_intern_ascii_cstr(const char *ptr);
-#ifdef __GNUC__
-#define rb_sym_intern_ascii_cstr(ptr) __extension__ ( \
-{ \
- (__builtin_constant_p(ptr)) ? \
- rb_sym_intern_ascii((ptr), (long)strlen(ptr)) : \
- rb_sym_intern_ascii_cstr(ptr); \
-})
-#endif
-VALUE rb_to_symbol_type(VALUE obj);
-
-/* struct.c */
-VALUE rb_struct_init_copy(VALUE copy, VALUE s);
-VALUE rb_struct_lookup(VALUE s, VALUE idx);
-VALUE rb_struct_s_keyword_init(VALUE klass);
-
-/* time.c */
-struct timeval rb_time_timeval(VALUE);
-
-/* thread.c */
-#define COVERAGE_INDEX_LINES 0
-#define COVERAGE_INDEX_BRANCHES 1
-#define COVERAGE_TARGET_LINES 1
-#define COVERAGE_TARGET_BRANCHES 2
-#define COVERAGE_TARGET_METHODS 4
-#define COVERAGE_TARGET_ONESHOT_LINES 8
-
-VALUE rb_obj_is_mutex(VALUE obj);
-VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
-void rb_thread_execute_interrupts(VALUE th);
-VALUE rb_get_coverages(void);
-int rb_get_coverage_mode(void);
-VALUE rb_default_coverage(int);
-VALUE rb_thread_shield_new(void);
-VALUE rb_thread_shield_wait(VALUE self);
-VALUE rb_thread_shield_release(VALUE self);
-VALUE rb_thread_shield_destroy(VALUE self);
-int rb_thread_to_be_killed(VALUE thread);
-void rb_mutex_allow_trap(VALUE self, int val);
-VALUE rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data);
-VALUE rb_mutex_owned_p(VALUE self);
-
-/* transcode.c */
-extern VALUE rb_cEncodingConverter;
-#ifdef RUBY_ENCODING_H
-size_t rb_econv_memsize(rb_econv_t *);
-#endif
-
-/* us_ascii.c */
-#ifdef RUBY_ENCODING_H
-extern rb_encoding OnigEncodingUS_ASCII;
-#endif
-
-/* util.c */
-char *ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve);
-char *ruby_hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve);
-
-/* utf_8.c */
-#ifdef RUBY_ENCODING_H
-extern rb_encoding OnigEncodingUTF_8;
-#endif
-
-/* variable.c */
-#if USE_TRANSIENT_HEAP
-#define ROBJECT_TRANSIENT_FLAG FL_USER13
-#define ROBJ_TRANSIENT_P(obj) FL_TEST_RAW((obj), ROBJECT_TRANSIENT_FLAG)
-#define ROBJ_TRANSIENT_SET(obj) FL_SET_RAW((obj), ROBJECT_TRANSIENT_FLAG)
-#define ROBJ_TRANSIENT_UNSET(obj) FL_UNSET_RAW((obj), ROBJECT_TRANSIENT_FLAG)
-#else
-#define ROBJ_TRANSIENT_P(obj) 0
-#define ROBJ_TRANSIENT_SET(obj) ((void)0)
-#define ROBJ_TRANSIENT_UNSET(obj) ((void)0)
-#endif
-void rb_gc_mark_global_tbl(void);
-size_t rb_generic_ivar_memsize(VALUE);
-VALUE rb_search_class_path(VALUE);
-VALUE rb_attr_delete(VALUE, ID);
-VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef);
-void rb_autoload_str(VALUE mod, ID id, VALUE file);
-VALUE rb_autoload_at_p(VALUE, ID, int);
-void rb_deprecate_constant(VALUE mod, const char *name);
-NORETURN(VALUE rb_mod_const_missing(VALUE,VALUE));
-rb_gvar_getter_t *rb_gvar_getter_function_of(const struct rb_global_entry *);
-rb_gvar_setter_t *rb_gvar_setter_function_of(const struct rb_global_entry *);
-bool rb_gvar_is_traced(const struct rb_global_entry *);
-void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_);
-
-/* vm_insnhelper.h */
-rb_serial_t rb_next_class_serial(void);
-
-/* vm.c */
-VALUE rb_obj_is_thread(VALUE obj);
-void rb_vm_mark(void *ptr);
-void Init_BareVM(void);
-void Init_vm_objects(void);
-PUREFUNC(VALUE rb_vm_top_self(void));
-void rb_vm_inc_const_missing_count(void);
-const void **rb_vm_get_insns_address_table(void);
-VALUE rb_source_location(int *pline);
-const char *rb_source_location_cstr(int *pline);
-MJIT_STATIC void rb_vm_pop_cfunc_frame(void);
-int rb_vm_add_root_module(ID id, VALUE module);
-void rb_vm_check_redefinition_by_prepend(VALUE klass);
-int rb_vm_check_optimizable_mid(VALUE mid);
-VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements);
-MJIT_STATIC VALUE ruby_vm_special_exception_copy(VALUE);
-PUREFUNC(st_table *rb_vm_fstring_table(void));
-
-
-/* vm_dump.c */
-void rb_print_backtrace(void);
-
-/* vm_eval.c */
-void Init_vm_eval(void);
-VALUE rb_adjust_argv_kw_splat(int *, const VALUE **, int *);
-VALUE rb_current_realfilepath(void);
-VALUE rb_check_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE);
-typedef void rb_check_funcall_hook(int, VALUE, ID, int, const VALUE *, VALUE);
-VALUE rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv,
- rb_check_funcall_hook *hook, VALUE arg);
-VALUE rb_check_funcall_with_hook_kw(VALUE recv, ID mid, int argc, const VALUE *argv,
- rb_check_funcall_hook *hook, VALUE arg, int kw_splat);
-const char *rb_type_str(enum ruby_value_type type);
-VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE);
-VALUE rb_yield_1(VALUE val);
-VALUE rb_yield_force_blockarg(VALUE values);
-VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
- rb_block_call_func_t bl_proc, int min_argc, int max_argc,
- VALUE data2);
-
-/* vm_insnhelper.c */
-VALUE rb_equal_opt(VALUE obj1, VALUE obj2);
-VALUE rb_eql_opt(VALUE obj1, VALUE obj2);
-void Init_vm_stack_canary(void);
-
-/* vm_method.c */
-void Init_eval_method(void);
-
-enum method_missing_reason {
- MISSING_NOENTRY = 0x00,
- MISSING_PRIVATE = 0x01,
- MISSING_PROTECTED = 0x02,
- MISSING_FCALL = 0x04,
- MISSING_VCALL = 0x08,
- MISSING_SUPER = 0x10,
- MISSING_MISSING = 0x20,
- MISSING_NONE = 0x40
-};
-struct rb_callable_method_entry_struct;
-struct rb_method_definition_struct;
-struct rb_execution_context_struct;
-struct rb_control_frame_struct;
-struct rb_calling_info;
-struct rb_call_data;
-/* I have several reasons to chose 64 here:
- *
- * - A cache line must be a power-of-two size.
- * - Setting this to anything less than or equal to 32 boosts nothing.
- * - I have never seen an architecture that has 128 byte L1 cache line.
- * - I know Intel Core and Sparc T4 at least uses 64.
- * - I know jemalloc internally has this exact same `#define CACHE_LINE 64`.
- * https://github.com/jemalloc/jemalloc/blob/dev/include/jemalloc/internal/jemalloc_internal_types.h
- */
-#define CACHELINE 64
-struct rb_call_cache {
- /* inline cache: keys */
- rb_serial_t method_state;
- rb_serial_t class_serial[
- (CACHELINE
- - sizeof(rb_serial_t) /* method_state */
- - sizeof(struct rb_callable_method_entry_struct *) /* me */
- - sizeof(uintptr_t) /* method_serial */
- - sizeof(enum method_missing_reason) /* aux */
- - sizeof(VALUE (*)( /* call */
- struct rb_execution_context_struct *e,
- struct rb_control_frame_struct *,
- struct rb_calling_info *,
- const struct rb_call_data *)))
- / sizeof(rb_serial_t)
- ];
-
- /* inline cache: values */
- const struct rb_callable_method_entry_struct *me;
- uintptr_t method_serial; /* me->def->method_serial */
-
- VALUE (*call)(struct rb_execution_context_struct *ec,
- struct rb_control_frame_struct *cfp,
- struct rb_calling_info *calling,
- struct rb_call_data *cd);
-
- union {
- unsigned int index; /* used by ivar */
- enum method_missing_reason method_missing_reason; /* used by method_missing */
- } aux;
-};
-STATIC_ASSERT(cachelined, sizeof(struct rb_call_cache) <= CACHELINE);
-struct rb_call_info {
- /* fixed at compile time */
- ID mid;
- unsigned int flag;
- int orig_argc;
-};
-struct rb_call_data {
- struct rb_call_cache cc;
- struct rb_call_info ci;
-};
-RUBY_FUNC_EXPORTED
-RUBY_FUNC_NONNULL(1, VALUE rb_funcallv_with_cc(struct rb_call_data*, VALUE, ID, int, const VALUE*));
-RUBY_FUNC_EXPORTED
-RUBY_FUNC_NONNULL(1, bool rb_method_basic_definition_p_with_cc(struct rb_call_data *, VALUE, ID));
-
-#ifdef __GNUC__
-# define rb_funcallv(recv, mid, argc, argv) \
- __extension__({ \
- static struct rb_call_data rb_funcallv_data; \
- rb_funcallv_with_cc(&rb_funcallv_data, recv, mid, argc, argv); \
- })
-# define rb_method_basic_definition_p(klass, mid) \
- __extension__({ \
- static struct rb_call_data rb_mbdp; \
- (klass == Qfalse) ? /* hidden object cannot be overridden */ true : \
- rb_method_basic_definition_p_with_cc(&rb_mbdp, klass, mid); \
- })
-#endif
-
-/* vm_backtrace.c */
-void Init_vm_backtrace(void);
-VALUE rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval);
-VALUE rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval);
-
-VALUE rb_make_backtrace(void);
-void rb_backtrace_print_as_bugreport(void);
-int rb_backtrace_p(VALUE obj);
-VALUE rb_backtrace_to_str_ary(VALUE obj);
-VALUE rb_backtrace_to_location_ary(VALUE obj);
-void rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output);
-
-#ifdef HAVE_PWD_H
-VALUE rb_getlogin(void);
-VALUE rb_getpwdirnam_for_login(VALUE login); /* read as: "get pwd db home dir by username for login" */
-VALUE rb_getpwdiruid(void); /* read as: "get pwd db home dir for getuid()" */
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
-const char *rb_objspace_data_type_name(VALUE obj);
-
-/* Temporary. This API will be removed (renamed). */
-VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd);
-
-/* array.c (export) */
-void rb_ary_detransient(VALUE a);
-VALUE *rb_ary_ptr_use_start(VALUE ary);
-void rb_ary_ptr_use_end(VALUE ary);
-
-/* bignum.c (export) */
-VALUE rb_big_mul_normal(VALUE x, VALUE y);
-VALUE rb_big_mul_balance(VALUE x, VALUE y);
-VALUE rb_big_mul_karatsuba(VALUE x, VALUE y);
-VALUE rb_big_mul_toom3(VALUE x, VALUE y);
-VALUE rb_big_sq_fast(VALUE x);
-VALUE rb_big_divrem_normal(VALUE x, VALUE y);
-VALUE rb_big2str_poweroftwo(VALUE x, int base);
-VALUE rb_big2str_generic(VALUE x, int base);
-VALUE rb_str2big_poweroftwo(VALUE arg, int base, int badcheck);
-VALUE rb_str2big_normal(VALUE arg, int base, int badcheck);
-VALUE rb_str2big_karatsuba(VALUE arg, int base, int badcheck);
-#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
-VALUE rb_big_mul_gmp(VALUE x, VALUE y);
-VALUE rb_big_divrem_gmp(VALUE x, VALUE y);
-VALUE rb_big2str_gmp(VALUE x, int base);
-VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
-#endif
-enum rb_int_parse_flags {
- RB_INT_PARSE_SIGN = 0x01,
- RB_INT_PARSE_UNDERSCORE = 0x02,
- RB_INT_PARSE_PREFIX = 0x04,
- RB_INT_PARSE_ALL = 0x07,
- RB_INT_PARSE_DEFAULT = 0x07
-};
-VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags);
-
-/* enumerator.c (export) */
-VALUE rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
- rb_enumerator_size_func *size_fn,
- VALUE beg, VALUE end, VALUE step, int excl);
-
-/* error.c (export) */
-int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
-NORETURN(void rb_unexpected_type(VALUE,int));
-#undef Check_Type
-#define Check_Type(v, t) \
- (!RB_TYPE_P((VALUE)(v), (t)) || \
- ((t) == RUBY_T_DATA && RTYPEDDATA_P(v)) ? \
- rb_unexpected_type((VALUE)(v), (t)) : (void)0)
-
-static inline int
-rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type)
-{
- return RB_TYPE_P(obj, T_DATA) && RTYPEDDATA_P(obj) && (RTYPEDDATA_TYPE(obj) == data_type);
-}
-#define rb_typeddata_is_instance_of rb_typeddata_is_instance_of_inline
-
-/* file.c (export) */
-#if defined HAVE_READLINK && defined RUBY_ENCODING_H
-VALUE rb_readlink(VALUE path, rb_encoding *enc);
-#endif
-#ifdef __APPLE__
-VALUE rb_str_normalize_ospath(const char *ptr, long len);
-#endif
-
-/* hash.c (export) */
-VALUE rb_hash_delete_entry(VALUE hash, VALUE key);
-VALUE rb_ident_hash_new(void);
-
-/* io.c (export) */
-void rb_maygvl_fd_fix_cloexec(int fd);
-int rb_gc_for_fd(int err);
-void rb_write_error_str(VALUE mesg);
-
-/* numeric.c (export) */
-VALUE rb_int_positive_pow(long x, unsigned long y);
-
-/* object.c (export) */
-int rb_opts_exception_p(VALUE opts, int default_value);
-
-/* process.c (export) */
-int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen);
-rb_pid_t rb_fork_async_signal_safe(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen);
-VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt);
-struct rb_execarg *rb_execarg_get(VALUE execarg_obj); /* dangerous. needs GC guard. */
-int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val);
-void rb_execarg_parent_start(VALUE execarg_obj);
-void rb_execarg_parent_end(VALUE execarg_obj);
-int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char* errmsg, size_t errmsg_buflen);
-VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash);
-void rb_execarg_setenv(VALUE execarg_obj, VALUE env);
-
-/* rational.c (export) */
-VALUE rb_gcd(VALUE x, VALUE y);
-VALUE rb_gcd_normal(VALUE self, VALUE other);
-#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
-VALUE rb_gcd_gmp(VALUE x, VALUE y);
-#endif
-
-/* signal.c (export) */
-int rb_grantpt(int fd);
-
-/* string.c (export) */
-VALUE rb_str_tmp_frozen_acquire(VALUE str);
-void rb_str_tmp_frozen_release(VALUE str, VALUE tmp);
-#ifdef RUBY_ENCODING_H
-/* internal use */
-VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc);
-#endif
-VALUE rb_str_upto_each(VALUE, VALUE, int, int (*each)(VALUE, VALUE), VALUE);
-VALUE rb_str_upto_endless_each(VALUE, int (*each)(VALUE, VALUE), VALUE);
-
-/* thread.c (export) */
-int ruby_thread_has_gvl_p(void); /* for ext/fiddle/closure.c */
-
-/* time.c (export) */
-void ruby_reset_leap_second_info(void);
-
-/* util.c (export) */
-extern const signed char ruby_digit36_to_number_table[];
-extern const char ruby_hexdigits[];
-extern unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
-
-/* variable.c (export) */
-void rb_mark_generic_ivar(VALUE);
-void rb_mv_generic_ivar(VALUE src, VALUE dst);
-VALUE rb_const_missing(VALUE klass, VALUE name);
-int rb_class_ivar_set(VALUE klass, ID vid, VALUE value);
-void rb_iv_tbl_copy(VALUE dst, VALUE src);
-
-/* gc.c (export) */
-VALUE rb_wb_protected_newobj_of(VALUE, VALUE);
-VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE);
-
-size_t rb_obj_memsize_of(VALUE);
-void rb_gc_verify_internal_consistency(void);
-
-#define RB_OBJ_GC_FLAGS_MAX 6
-size_t rb_obj_gc_flags(VALUE, ID[], size_t);
-void rb_gc_mark_values(long n, const VALUE *values);
-void rb_gc_mark_vm_stack_values(long n, const VALUE *values);
-
-#if IMEMO_DEBUG
-VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line);
-#define rb_imemo_new(type, v1, v2, v3, v0) rb_imemo_new_debug(type, v1, v2, v3, v0, __FILE__, __LINE__)
-#else
-VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
-#endif
-
-/* random.c */
-int ruby_fill_random_bytes(void *, size_t, int);
-
-RUBY_SYMBOL_EXPORT_END
-
-#define RUBY_DTRACE_CREATE_HOOK(name, arg) \
- RUBY_DTRACE_HOOK(name##_CREATE, arg)
-#define RUBY_DTRACE_HOOK(name, arg) \
-do { \
- if (UNLIKELY(RUBY_DTRACE_##name##_ENABLED())) { \
- int dtrace_line; \
- const char *dtrace_file = rb_source_location_cstr(&dtrace_line); \
- if (!dtrace_file) dtrace_file = ""; \
- RUBY_DTRACE_##name(arg, dtrace_file, dtrace_line); \
- } \
-} while (0)
-
-#define RB_OBJ_BUILTIN_TYPE(obj) rb_obj_builtin_type(obj)
-#define OBJ_BUILTIN_TYPE(obj) RB_OBJ_BUILTIN_TYPE(obj)
-#ifdef __GNUC__
-#define rb_obj_builtin_type(obj) \
-__extension__({ \
- VALUE arg_obj = (obj); \
- RB_SPECIAL_CONST_P(arg_obj) ? -1 : \
- RB_BUILTIN_TYPE(arg_obj); \
- })
-#else
-static inline int
-rb_obj_builtin_type(VALUE obj)
-{
- return RB_SPECIAL_CONST_P(obj) ? -1 :
- RB_BUILTIN_TYPE(obj);
-}
-#endif
-
-/* A macro for defining a flexible array, like: VALUE ary[FLEX_ARY_LEN]; */
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-# define FLEX_ARY_LEN /* VALUE ary[]; */
-#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
-# define FLEX_ARY_LEN 0 /* VALUE ary[0]; */
-#else
-# define FLEX_ARY_LEN 1 /* VALUE ary[1]; */
-#endif
-
-/*
- * For declaring bitfields out of non-unsigned int types:
- * struct date {
- * BITFIELD(enum months, month, 4);
- * ...
- * };
- */
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
-# define BITFIELD(type, name, size) type name : size
-#else
-# define BITFIELD(type, name, size) unsigned int name : size
-#endif
-
-#if defined(_MSC_VER)
-# define COMPILER_WARNING_PUSH __pragma(warning(push))
-# define COMPILER_WARNING_POP __pragma(warning(pop))
-# define COMPILER_WARNING_ERROR(flag) __pragma(warning(error: flag)))
-# define COMPILER_WARNING_IGNORED(flag) __pragma(warning(suppress: flag)))
-
-#elif defined(__clang__) /* clang 2.6 already had this feature */
-# define COMPILER_WARNING_PUSH _Pragma("clang diagnostic push")
-# define COMPILER_WARNING_POP _Pragma("clang diagnostic pop")
-# define COMPILER_WARNING_SPECIFIER(kind, msg) \
- clang diagnostic kind # msg
-# define COMPILER_WARNING_ERROR(flag) \
- COMPILER_WARNING_PRAGMA(COMPILER_WARNING_SPECIFIER(error, flag))
-# define COMPILER_WARNING_IGNORED(flag) \
- COMPILER_WARNING_PRAGMA(COMPILER_WARNING_SPECIFIER(ignored, flag))
-
-#elif GCC_VERSION_SINCE(4, 6, 0)
-/* https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Diagnostic-Pragmas.html */
-# define COMPILER_WARNING_PUSH _Pragma("GCC diagnostic push")
-# define COMPILER_WARNING_POP _Pragma("GCC diagnostic pop")
-# define COMPILER_WARNING_SPECIFIER(kind, msg) \
- GCC diagnostic kind # msg
-# define COMPILER_WARNING_ERROR(flag) \
- COMPILER_WARNING_PRAGMA(COMPILER_WARNING_SPECIFIER(error, flag))
-# define COMPILER_WARNING_IGNORED(flag) \
- COMPILER_WARNING_PRAGMA(COMPILER_WARNING_SPECIFIER(ignored, flag))
-
-#else /* other compilers to follow? */
-# define COMPILER_WARNING_PUSH /* nop */
-# define COMPILER_WARNING_POP /* nop */
-# define COMPILER_WARNING_ERROR(flag) /* nop */
-# define COMPILER_WARNING_IGNORED(flag) /* nop */
-#endif
-
-#define COMPILER_WARNING_PRAGMA(str) COMPILER_WARNING_PRAGMA_(str)
-#define COMPILER_WARNING_PRAGMA_(str) _Pragma(#str)
-
-#if defined(USE_UNALIGNED_MEMBER_ACCESS) && USE_UNALIGNED_MEMBER_ACCESS && \
- (defined(__clang__) || GCC_VERSION_SINCE(9, 0, 0))
-# define UNALIGNED_MEMBER_ACCESS(expr) __extension__({ \
- COMPILER_WARNING_PUSH; \
- COMPILER_WARNING_IGNORED(-Waddress-of-packed-member); \
- typeof(expr) unaligned_member_access_result = (expr); \
- COMPILER_WARNING_POP; \
- unaligned_member_access_result; \
-})
-#else
-# define UNALIGNED_MEMBER_ACCESS(expr) expr
-#endif
-#define UNALIGNED_MEMBER_PTR(ptr, mem) UNALIGNED_MEMBER_ACCESS(&(ptr)->mem)
-
-#undef RB_OBJ_WRITE
-#define RB_OBJ_WRITE(a, slot, b) UNALIGNED_MEMBER_ACCESS(rb_obj_write((VALUE)(a), (VALUE *)(slot), (VALUE)(b), __FILE__, __LINE__))
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-} /* extern "C" { */
-#endif
-
#endif /* RUBY_INTERNAL_H */
diff --git a/internal/array.h b/internal/array.h
new file mode 100644
index 0000000000..44c0efbbc1
--- /dev/null
+++ b/internal/array.h
@@ -0,0 +1,119 @@
+#ifndef INTERNAL_ARRAY_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_ARRAY_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.
+ * @brief Internal header for Array.
+ */
+#include "ruby/internal/config.h"
+#include <stddef.h> /* for size_t */
+#include "internal/static_assert.h" /* for STATIC_ASSERT */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/ruby.h" /* for RARRAY_LEN */
+
+#ifndef ARRAY_DEBUG
+# define ARRAY_DEBUG (0+RUBY_DEBUG)
+#endif
+
+#define RARRAY_PTR_IN_USE_FLAG FL_USER14
+
+/* array.c */
+VALUE rb_ary_last(int, const VALUE *, VALUE);
+void rb_ary_set_len(VALUE, long);
+void rb_ary_delete_same(VALUE, VALUE);
+VALUE rb_ary_tmp_new_fill(long capa);
+VALUE rb_ary_at(VALUE, VALUE);
+size_t rb_ary_memsize(VALUE);
+VALUE rb_to_array_type(VALUE obj);
+void rb_ary_cancel_sharing(VALUE ary);
+
+static inline VALUE rb_ary_entry_internal(VALUE ary, long offset);
+static inline bool ARY_PTR_USING_P(VALUE ary);
+static inline void RARY_TRANSIENT_SET(VALUE ary);
+static inline void RARY_TRANSIENT_UNSET(VALUE ary);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* array.c (export) */
+void rb_ary_detransient(VALUE a);
+VALUE *rb_ary_ptr_use_start(VALUE ary);
+void rb_ary_ptr_use_end(VALUE ary);
+RUBY_SYMBOL_EXPORT_END
+
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE rb_ary_tmp_new_from_values(VALUE, long, const VALUE *);
+VALUE rb_check_to_array(VALUE ary);
+VALUE rb_ary_behead(VALUE, long);
+VALUE rb_ary_aref1(VALUE ary, VALUE i);
+
+struct rb_execution_context_struct;
+VALUE rb_ec_ary_new_from_values(struct rb_execution_context_struct *ec, long n, const VALUE *elts);
+MJIT_SYMBOL_EXPORT_END
+
+static inline VALUE
+rb_ary_entry_internal(VALUE ary, long offset)
+{
+ long len = RARRAY_LEN(ary);
+ const VALUE *ptr = RARRAY_CONST_PTR_TRANSIENT(ary);
+ if (len == 0) return Qnil;
+ if (offset < 0) {
+ offset += len;
+ if (offset < 0) return Qnil;
+ }
+ else if (len <= offset) {
+ return Qnil;
+ }
+ return ptr[offset];
+}
+
+static inline bool
+ARY_PTR_USING_P(VALUE ary)
+{
+ return FL_TEST_RAW(ary, RARRAY_PTR_IN_USE_FLAG);
+}
+
+static inline void
+RARY_TRANSIENT_SET(VALUE ary)
+{
+#if USE_TRANSIENT_HEAP
+ FL_SET_RAW(ary, RARRAY_TRANSIENT_FLAG);
+#endif
+}
+
+static inline void
+RARY_TRANSIENT_UNSET(VALUE ary)
+{
+#if USE_TRANSIENT_HEAP
+ FL_UNSET_RAW(ary, RARRAY_TRANSIENT_FLAG);
+#endif
+}
+
+#undef rb_ary_new_from_args
+#if RBIMPL_HAS_WARNING("-Wgnu-zero-variadic-macro-arguments")
+# /* Skip it; clang -pedantic doesn't like the following */
+#elif defined(__GNUC__) && defined(HAVE_VA_ARGS_MACRO)
+#define rb_ary_new_from_args(n, ...) \
+ __extension__ ({ \
+ const VALUE args_to_new_ary[] = {__VA_ARGS__}; \
+ if (__builtin_constant_p(n)) { \
+ STATIC_ASSERT(rb_ary_new_from_args, numberof(args_to_new_ary) == (n)); \
+ } \
+ rb_ary_new_from_values(numberof(args_to_new_ary), args_to_new_ary); \
+ })
+#endif
+
+#undef RARRAY_AREF
+RBIMPL_ATTR_PURE_UNLESS_DEBUG()
+RBIMPL_ATTR_ARTIFICIAL()
+static inline VALUE
+RARRAY_AREF(VALUE ary, long i)
+{
+ RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
+
+ return RARRAY_CONST_PTR_TRANSIENT(ary)[i];
+}
+
+#endif /* INTERNAL_ARRAY_H */
diff --git a/internal/bignum.h b/internal/bignum.h
new file mode 100644
index 0000000000..95c1e6eacd
--- /dev/null
+++ b/internal/bignum.h
@@ -0,0 +1,246 @@
+#ifndef INTERNAL_BIGNUM_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_BIGNUM_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.
+ * @brief Internal header for Bignums.
+ */
+#include "ruby/internal/config.h" /* for HAVE_LIBGMP */
+#include <stddef.h> /* for size_t */
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h> /* for ssize_t (note: on Windows ssize_t is */
+#endif /* `#define`d in ruby/config.h) */
+
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/ruby.h" /* for struct RBasic */
+
+#ifndef BDIGIT
+# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
+# define BDIGIT unsigned int
+# define SIZEOF_BDIGIT SIZEOF_INT
+# define BDIGIT_DBL unsigned LONG_LONG
+# define BDIGIT_DBL_SIGNED LONG_LONG
+# define PRI_BDIGIT_PREFIX ""
+# define PRI_BDIGIT_DBL_PREFIX PRI_LL_PREFIX
+# elif SIZEOF_INT*2 <= SIZEOF_LONG
+# define BDIGIT unsigned int
+# define SIZEOF_BDIGIT SIZEOF_INT
+# define BDIGIT_DBL unsigned long
+# define BDIGIT_DBL_SIGNED long
+# define PRI_BDIGIT_PREFIX ""
+# define PRI_BDIGIT_DBL_PREFIX "l"
+# elif SIZEOF_SHORT*2 <= SIZEOF_LONG
+# define BDIGIT unsigned short
+# define SIZEOF_BDIGIT SIZEOF_SHORT
+# define BDIGIT_DBL unsigned long
+# define BDIGIT_DBL_SIGNED long
+# define PRI_BDIGIT_PREFIX "h"
+# define PRI_BDIGIT_DBL_PREFIX "l"
+# else
+# define BDIGIT unsigned short
+# define SIZEOF_BDIGIT (SIZEOF_LONG/2)
+# define SIZEOF_ACTUAL_BDIGIT SIZEOF_LONG
+# define BDIGIT_DBL unsigned long
+# define BDIGIT_DBL_SIGNED long
+# define PRI_BDIGIT_PREFIX "h"
+# define PRI_BDIGIT_DBL_PREFIX "l"
+# endif
+#endif
+
+#ifndef SIZEOF_ACTUAL_BDIGIT
+# define SIZEOF_ACTUAL_BDIGIT SIZEOF_BDIGIT
+#endif
+
+#ifdef PRI_BDIGIT_PREFIX
+# define PRIdBDIGIT PRI_BDIGIT_PREFIX"d"
+# define PRIiBDIGIT PRI_BDIGIT_PREFIX"i"
+# define PRIoBDIGIT PRI_BDIGIT_PREFIX"o"
+# define PRIuBDIGIT PRI_BDIGIT_PREFIX"u"
+# define PRIxBDIGIT PRI_BDIGIT_PREFIX"x"
+# define PRIXBDIGIT PRI_BDIGIT_PREFIX"X"
+#endif
+
+#ifdef PRI_BDIGIT_DBL_PREFIX
+# define PRIdBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"d"
+# define PRIiBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"i"
+# define PRIoBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"o"
+# define PRIuBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"u"
+# define PRIxBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"x"
+# define PRIXBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"X"
+#endif
+
+#define RBIGNUM(obj) ((struct RBignum *)(obj))
+#define BIGNUM_SIGN_BIT FL_USER1
+#define BIGNUM_EMBED_FLAG ((VALUE)FL_USER2)
+#define BIGNUM_EMBED_LEN_NUMBITS 3
+#define BIGNUM_EMBED_LEN_MASK \
+ (~(~(VALUE)0U << BIGNUM_EMBED_LEN_NUMBITS) << BIGNUM_EMBED_LEN_SHIFT)
+#define BIGNUM_EMBED_LEN_SHIFT \
+ (FL_USHIFT+3) /* bit offset of BIGNUM_EMBED_LEN_MASK */
+#ifndef BIGNUM_EMBED_LEN_MAX
+# if (SIZEOF_VALUE*RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT) < (1 << BIGNUM_EMBED_LEN_NUMBITS)-1
+# define BIGNUM_EMBED_LEN_MAX (SIZEOF_VALUE*RVALUE_EMBED_LEN_MAX/SIZEOF_ACTUAL_BDIGIT)
+# else
+# define BIGNUM_EMBED_LEN_MAX ((1 << BIGNUM_EMBED_LEN_NUMBITS)-1)
+# endif
+#endif
+
+enum rb_int_parse_flags {
+ RB_INT_PARSE_SIGN = 0x01,
+ RB_INT_PARSE_UNDERSCORE = 0x02,
+ RB_INT_PARSE_PREFIX = 0x04,
+ RB_INT_PARSE_ALL = 0x07,
+ RB_INT_PARSE_DEFAULT = 0x07,
+};
+
+struct RBignum {
+ struct RBasic basic;
+ union {
+ struct {
+ size_t len;
+ BDIGIT *digits;
+ } heap;
+ BDIGIT ary[BIGNUM_EMBED_LEN_MAX];
+ } as;
+};
+
+/* bignum.c */
+extern const char ruby_digitmap[];
+double rb_big_fdiv_double(VALUE x, VALUE y);
+VALUE rb_big_uminus(VALUE x);
+VALUE rb_big_hash(VALUE);
+VALUE rb_big_odd_p(VALUE);
+VALUE rb_big_even_p(VALUE);
+size_t rb_big_size(VALUE);
+VALUE rb_integer_float_cmp(VALUE x, VALUE y);
+VALUE rb_integer_float_eq(VALUE x, VALUE y);
+VALUE rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception);
+VALUE rb_big_comp(VALUE x);
+VALUE rb_big_aref(VALUE x, VALUE y);
+VALUE rb_big_abs(VALUE x);
+VALUE rb_big_size_m(VALUE big);
+VALUE rb_big_bit_length(VALUE big);
+VALUE rb_big_remainder(VALUE x, VALUE y);
+VALUE rb_big_gt(VALUE x, VALUE y);
+VALUE rb_big_ge(VALUE x, VALUE y);
+VALUE rb_big_lt(VALUE x, VALUE y);
+VALUE rb_big_le(VALUE x, VALUE y);
+VALUE rb_int_powm(int const argc, VALUE * const argv, VALUE const num);
+static inline bool BIGNUM_SIGN(VALUE b);
+static inline bool BIGNUM_POSITIVE_P(VALUE b);
+static inline bool BIGNUM_NEGATIVE_P(VALUE b);
+static inline void BIGNUM_SET_SIGN(VALUE b, bool sign);
+static inline void BIGNUM_NEGATE(VALUE b);
+static inline size_t BIGNUM_LEN(VALUE b);
+static inline BDIGIT *BIGNUM_DIGITS(VALUE b);
+static inline int BIGNUM_LENINT(VALUE b);
+static inline bool BIGNUM_EMBED_P(VALUE b);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* bignum.c (export) */
+VALUE rb_big_mul_normal(VALUE x, VALUE y);
+VALUE rb_big_mul_balance(VALUE x, VALUE y);
+VALUE rb_big_mul_karatsuba(VALUE x, VALUE y);
+VALUE rb_big_mul_toom3(VALUE x, VALUE y);
+VALUE rb_big_sq_fast(VALUE x);
+VALUE rb_big_divrem_normal(VALUE x, VALUE y);
+VALUE rb_big2str_poweroftwo(VALUE x, int base);
+VALUE rb_big2str_generic(VALUE x, int base);
+VALUE rb_str2big_poweroftwo(VALUE arg, int base, int badcheck);
+VALUE rb_str2big_normal(VALUE arg, int base, int badcheck);
+VALUE rb_str2big_karatsuba(VALUE arg, int base, int badcheck);
+#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
+VALUE rb_big_mul_gmp(VALUE x, VALUE y);
+VALUE rb_big_divrem_gmp(VALUE x, VALUE y);
+VALUE rb_big2str_gmp(VALUE x, int base);
+VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
+#endif
+VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags);
+RUBY_SYMBOL_EXPORT_END
+
+MJIT_SYMBOL_EXPORT_BEGIN
+#if defined(HAVE_INT128_T)
+VALUE rb_int128t2big(int128_t n);
+#endif
+MJIT_SYMBOL_EXPORT_END
+
+/* sign: positive:1, negative:0 */
+static inline bool
+BIGNUM_SIGN(VALUE b)
+{
+ return FL_TEST_RAW(b, BIGNUM_SIGN_BIT);
+}
+
+static inline bool
+BIGNUM_POSITIVE_P(VALUE b)
+{
+ return BIGNUM_SIGN(b);
+}
+
+static inline bool
+BIGNUM_NEGATIVE_P(VALUE b)
+{
+ return ! BIGNUM_POSITIVE_P(b);
+}
+
+static inline void
+BIGNUM_SET_SIGN(VALUE b, bool sign)
+{
+ if (sign) {
+ FL_SET_RAW(b, BIGNUM_SIGN_BIT);
+ }
+ else {
+ FL_UNSET_RAW(b, BIGNUM_SIGN_BIT);
+ }
+}
+
+static inline void
+BIGNUM_NEGATE(VALUE b)
+{
+ FL_REVERSE_RAW(b, BIGNUM_SIGN_BIT);
+}
+
+static inline size_t
+BIGNUM_LEN(VALUE b)
+{
+ if (! BIGNUM_EMBED_P(b)) {
+ return RBIGNUM(b)->as.heap.len;
+ }
+ else {
+ size_t ret = RBASIC(b)->flags;
+ ret &= BIGNUM_EMBED_LEN_MASK;
+ ret >>= BIGNUM_EMBED_LEN_SHIFT;
+ return ret;
+ }
+}
+
+static inline int
+BIGNUM_LENINT(VALUE b)
+{
+ return rb_long2int(BIGNUM_LEN(b));
+}
+
+/* LSB:BIGNUM_DIGITS(b)[0], MSB:BIGNUM_DIGITS(b)[BIGNUM_LEN(b)-1] */
+static inline BDIGIT *
+BIGNUM_DIGITS(VALUE b)
+{
+ if (BIGNUM_EMBED_P(b)) {
+ return RBIGNUM(b)->as.ary;
+ }
+ else {
+ return RBIGNUM(b)->as.heap.digits;
+ }
+}
+
+static inline bool
+BIGNUM_EMBED_P(VALUE b)
+{
+ return FL_TEST_RAW(b, BIGNUM_EMBED_FLAG);
+}
+
+#endif /* INTERNAL_BIGNUM_H */
diff --git a/internal/bits.h b/internal/bits.h
new file mode 100644
index 0000000000..746947bfc2
--- /dev/null
+++ b/internal/bits.h
@@ -0,0 +1,566 @@
+#ifndef INTERNAL_BITS_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_BITS_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.
+ * @brief Internal header for bitwise integer algorithms.
+ * @see Henry S. Warren Jr., "Hacker's Delight" (2nd ed.), 2013.
+ * @see SEI CERT C Coding Standard INT32-C. "Ensure that operations on
+ * signed integers do not result in overflow"
+ * @see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
+ * @see https://clang.llvm.org/docs/LanguageExtensions.html#builtin-rotateleft
+ * @see https://clang.llvm.org/docs/LanguageExtensions.html#builtin-rotateright
+ * @see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/byteswap-uint64-byteswap-ulong-byteswap-ushort
+ * @see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rotl-rotl64-rotr-rotr64
+ * @see https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64
+ * @see https://docs.microsoft.com/en-us/cpp/intrinsics/bitscanreverse-bitscanreverse64
+ * @see https://docs.microsoft.com/en-us/cpp/intrinsics/lzcnt16-lzcnt-lzcnt64
+ * @see https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64
+ * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_lzcnt_u32
+ * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_tzcnt_u32
+ * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_rotl64
+ * @see https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_rotr64
+ * @see https://stackoverflow.com/a/776523
+ */
+#include "ruby/internal/config.h"
+#include <limits.h> /* for CHAR_BITS */
+#include <stdint.h> /* for uintptr_t */
+#include "internal/compilers.h" /* for MSC_VERSION_SINCE */
+
+#if MSC_VERSION_SINCE(1310)
+# include <stdlib.h> /* for _byteswap_uint64 */
+#endif
+
+#if defined(HAVE_X86INTRIN_H) && ! defined(MJIT_HEADER)
+# /* Rule out MJIT_HEADER, which does not interface well with <immintrin.h> */
+# include <x86intrin.h> /* for _lzcnt_u64 */
+#elif MSC_VERSION_SINCE(1310)
+# include <intrin.h> /* for the following intrinsics */
+#endif
+
+#if defined(_MSC_VER) && defined(__AVX__)
+# pragma intrinsic(__popcnt)
+# pragma intrinsic(__popcnt64)
+#endif
+
+#if defined(_MSC_VER) && defined(__AVX2__)
+# pragma intrinsic(__lzcnt)
+# pragma intrinsic(__lzcnt64)
+#endif
+
+#if MSC_VERSION_SINCE(1310)
+# pragma intrinsic(_rotl)
+# pragma intrinsic(_rotr)
+# ifdef _WIN64
+# pragma intrinsic(_rotl64)
+# pragma intrinsic(_rotr64)
+# endif
+#endif
+
+#if MSC_VERSION_SINCE(1400)
+# pragma intrinsic(_BitScanForward)
+# pragma intrinsic(_BitScanReverse)
+# ifdef _WIN64
+# pragma intrinsic(_BitScanForward64)
+# pragma intrinsic(_BitScanReverse64)
+# endif
+#endif
+
+#include "ruby/ruby.h" /* for VALUE */
+#include "internal/static_assert.h" /* for STATIC_ASSERT */
+
+/* The most significant bit of the lower part of half-long integer.
+ * If sizeof(long) == 4, this is 0x8000.
+ * If sizeof(long) == 8, this is 0x80000000.
+ */
+#define HALF_LONG_MSB ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2))
+
+#define SIGNED_INTEGER_TYPE_P(T) (0 > ((T)0)-1)
+
+#define SIGNED_INTEGER_MIN(T) \
+ ((sizeof(T) == sizeof(int8_t)) ? ((T)INT8_MIN) : \
+ ((sizeof(T) == sizeof(int16_t)) ? ((T)INT16_MIN) : \
+ ((sizeof(T) == sizeof(int32_t)) ? ((T)INT32_MIN) : \
+ ((sizeof(T) == sizeof(int64_t)) ? ((T)INT64_MIN) : \
+ 0))))
+
+#define SIGNED_INTEGER_MAX(T) ((T)(SIGNED_INTEGER_MIN(T) ^ ((T)~(T)0)))
+
+#define UNSIGNED_INTEGER_MAX(T) ((T)~(T)0)
+
+#if __has_builtin(__builtin_mul_overflow_p)
+# define MUL_OVERFLOW_P(a, b) \
+ __builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0)
+#elif __has_builtin(__builtin_mul_overflow)
+# define MUL_OVERFLOW_P(a, b) \
+ __extension__ ({ __typeof__(a) c; __builtin_mul_overflow((a), (b), &c); })
+#endif
+
+#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
+ (a) == 0 ? 0 : \
+ (a) == -1 ? (b) < -(max) : \
+ (a) > 0 ? \
+ ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
+ ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
+
+#if __has_builtin(__builtin_mul_overflow_p)
+/* __builtin_mul_overflow_p can take bitfield */
+/* and GCC permits bitfields for integers other than int */
+# define MUL_OVERFLOW_FIXNUM_P(a, b) \
+ __extension__ ({ \
+ struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
+ __builtin_mul_overflow_p((a), (b), c.fixnum); \
+ })
+#else
+# define MUL_OVERFLOW_FIXNUM_P(a, b) \
+ MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
+#endif
+
+#ifdef MUL_OVERFLOW_P
+# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_P(a, b)
+# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_P(a, b)
+# define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_P(a, b)
+#else
+# define MUL_OVERFLOW_LONG_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
+# define MUL_OVERFLOW_LONG_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
+# define MUL_OVERFLOW_INT_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
+#endif
+
+#ifdef HAVE_UINT128_T
+# define bit_length(x) \
+ (unsigned int) \
+ (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \
+ sizeof(x) <= sizeof(int64_t) ? 64 - nlz_int64((uint64_t)(x)) : \
+ 128 - nlz_int128((uint128_t)(x)))
+#else
+# define bit_length(x) \
+ (unsigned int) \
+ (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \
+ 64 - nlz_int64((uint64_t)(x)))
+#endif
+
+#ifndef swap16
+# define swap16 ruby_swap16
+#endif
+
+#ifndef swap32
+# define swap32 ruby_swap32
+#endif
+
+#ifndef swap64
+# define swap64 ruby_swap64
+#endif
+
+static inline uint16_t ruby_swap16(uint16_t);
+static inline uint32_t ruby_swap32(uint32_t);
+static inline uint64_t ruby_swap64(uint64_t);
+static inline unsigned nlz_int(unsigned x);
+static inline unsigned nlz_long(unsigned long x);
+static inline unsigned nlz_long_long(unsigned long long x);
+static inline unsigned nlz_intptr(uintptr_t x);
+static inline unsigned nlz_int32(uint32_t x);
+static inline unsigned nlz_int64(uint64_t x);
+#ifdef HAVE_UINT128_T
+static inline unsigned nlz_int128(uint128_t x);
+#endif
+static inline unsigned rb_popcount32(uint32_t x);
+static inline unsigned rb_popcount64(uint64_t x);
+static inline unsigned rb_popcount_intptr(uintptr_t x);
+static inline int ntz_int32(uint32_t x);
+static inline int ntz_int64(uint64_t x);
+static inline int ntz_intptr(uintptr_t x);
+static inline VALUE RUBY_BIT_ROTL(VALUE, int);
+static inline VALUE RUBY_BIT_ROTR(VALUE, int);
+
+static inline uint16_t
+ruby_swap16(uint16_t x)
+{
+#if __has_builtin(__builtin_bswap16)
+ return __builtin_bswap16(x);
+
+#elif MSC_VERSION_SINCE(1310)
+ return _byteswap_ushort(x);
+
+#else
+ return (x << 8) | (x >> 8);
+
+#endif
+}
+
+static inline uint32_t
+ruby_swap32(uint32_t x)
+{
+#if __has_builtin(__builtin_bswap32)
+ return __builtin_bswap32(x);
+
+#elif MSC_VERSION_SINCE(1310)
+ return _byteswap_ulong(x);
+
+#else
+ x = ((x & 0x0000FFFF) << 16) | ((x & 0xFFFF0000) >> 16);
+ x = ((x & 0x00FF00FF) << 8) | ((x & 0xFF00FF00) >> 8);
+ return x;
+
+#endif
+}
+
+static inline uint64_t
+ruby_swap64(uint64_t x)
+{
+#if __has_builtin(__builtin_bswap64)
+ return __builtin_bswap64(x);
+
+#elif MSC_VERSION_SINCE(1310)
+ return _byteswap_uint64(x);
+
+#else
+ x = ((x & 0x00000000FFFFFFFFULL) << 32) | ((x & 0xFFFFFFFF00000000ULL) >> 32);
+ x = ((x & 0x0000FFFF0000FFFFULL) << 16) | ((x & 0xFFFF0000FFFF0000ULL) >> 16);
+ x = ((x & 0x00FF00FF00FF00FFULL) << 8) | ((x & 0xFF00FF00FF00FF00ULL) >> 8);
+ return x;
+
+#endif
+}
+
+static inline unsigned int
+nlz_int32(uint32_t x)
+{
+#if defined(_MSC_VER) && defined(__AVX2__)
+ /* Note: It seems there is no such thing like __LZCNT__ predefined in MSVC.
+ * AMD CPUs have had this instruction for decades (since K10) but for
+ * Intel, Haswell is the oldest one. We need to use __AVX2__ for maximum
+ * safety. */
+ return (unsigned int)__lzcnt(x);
+
+#elif defined(__x86_64__) && defined(__LZCNT__) && ! defined(MJIT_HEADER)
+ return (unsigned int)_lzcnt_u32(x);
+
+#elif MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */
+ unsigned long r;
+ return _BitScanReverse(&r, x) ? (31 - (int)r) : 32;
+
+#elif __has_builtin(__builtin_clz)
+ STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT == 32);
+ return x ? (unsigned int)__builtin_clz(x) : 32;
+
+#else
+ uint32_t y;
+ unsigned n = 32;
+ y = x >> 16; if (y) {n -= 16; x = y;}
+ y = x >> 8; if (y) {n -= 8; x = y;}
+ y = x >> 4; if (y) {n -= 4; x = y;}
+ y = x >> 2; if (y) {n -= 2; x = y;}
+ y = x >> 1; if (y) {return n - 2;}
+ return (unsigned int)(n - x);
+#endif
+}
+
+static inline unsigned int
+nlz_int64(uint64_t x)
+{
+#if defined(_MSC_VER) && defined(__AVX2__)
+ return (unsigned int)__lzcnt64(x);
+
+#elif defined(__x86_64__) && defined(__LZCNT__) && ! defined(MJIT_HEADER)
+ return (unsigned int)_lzcnt_u64(x);
+
+#elif defined(_WIN64) && MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */
+ unsigned long r;
+ return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64;
+
+#elif __has_builtin(__builtin_clzl)
+ if (x == 0) {
+ return 64;
+ }
+ else if (sizeof(long) * CHAR_BIT == 64) {
+ return (unsigned int)__builtin_clzl((unsigned long)x);
+ }
+ else if (sizeof(long long) * CHAR_BIT == 64) {
+ return (unsigned int)__builtin_clzll((unsigned long long)x);
+ }
+ else {
+ /* :FIXME: Is there a way to make this branch a compile-time error? */
+ UNREACHABLE_RETURN(~0);
+ }
+
+#else
+ uint64_t y;
+ unsigned int n = 64;
+ y = x >> 32; if (y) {n -= 32; x = y;}
+ y = x >> 16; if (y) {n -= 16; x = y;}
+ y = x >> 8; if (y) {n -= 8; x = y;}
+ y = x >> 4; if (y) {n -= 4; x = y;}
+ y = x >> 2; if (y) {n -= 2; x = y;}
+ y = x >> 1; if (y) {return n - 2;}
+ return (unsigned int)(n - x);
+
+#endif
+}
+
+#ifdef HAVE_UINT128_T
+static inline unsigned int
+nlz_int128(uint128_t x)
+{
+ uint64_t y = (uint64_t)(x >> 64);
+
+ if (x == 0) {
+ return 128;
+ }
+ else if (y == 0) {
+ return (unsigned int)nlz_int64(x) + 64;
+ }
+ else {
+ return (unsigned int)nlz_int64(y);
+ }
+}
+#endif
+
+static inline unsigned int
+nlz_int(unsigned int x)
+{
+ if (sizeof(unsigned int) * CHAR_BIT == 32) {
+ return nlz_int32((uint32_t)x);
+ }
+ else if (sizeof(unsigned int) * CHAR_BIT == 64) {
+ return nlz_int64((uint64_t)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline unsigned int
+nlz_long(unsigned long x)
+{
+ if (sizeof(unsigned long) * CHAR_BIT == 32) {
+ return nlz_int32((uint32_t)x);
+ }
+ else if (sizeof(unsigned long) * CHAR_BIT == 64) {
+ return nlz_int64((uint64_t)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline unsigned int
+nlz_long_long(unsigned long long x)
+{
+ if (sizeof(unsigned long long) * CHAR_BIT == 64) {
+ return nlz_int64((uint64_t)x);
+ }
+#ifdef HAVE_UINT128_T
+ else if (sizeof(unsigned long long) * CHAR_BIT == 128) {
+ return nlz_int128((uint128_t)x);
+ }
+#endif
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline unsigned int
+nlz_intptr(uintptr_t x)
+{
+ if (sizeof(uintptr_t) == sizeof(unsigned int)) {
+ return nlz_int((unsigned int)x);
+ }
+ if (sizeof(uintptr_t) == sizeof(unsigned long)) {
+ return nlz_long((unsigned long)x);
+ }
+ if (sizeof(uintptr_t) == sizeof(unsigned long long)) {
+ return nlz_long_long((unsigned long long)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline unsigned int
+rb_popcount32(uint32_t x)
+{
+#if defined(_MSC_VER) && defined(__AVX__)
+ /* Note: CPUs since Nehalem and Barcelona have had this instruction so SSE
+ * 4.2 should suffice, but it seems there is no such thing like __SSE_4_2__
+ * predefined macro in MSVC. They do have __AVX__ so use it instead. */
+ return (unsigned int)__popcnt(x);
+
+#elif __has_builtin(__builtin_popcount)
+ STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT >= 32);
+ return (unsigned int)__builtin_popcount(x);
+
+#else
+ x = (x & 0x55555555) + (x >> 1 & 0x55555555);
+ x = (x & 0x33333333) + (x >> 2 & 0x33333333);
+ x = (x & 0x0f0f0f0f) + (x >> 4 & 0x0f0f0f0f);
+ x = (x & 0x001f001f) + (x >> 8 & 0x001f001f);
+ x = (x & 0x0000003f) + (x >>16 & 0x0000003f);
+ return (unsigned int)x;
+
+#endif
+}
+
+static inline unsigned int
+rb_popcount64(uint64_t x)
+{
+#if defined(_MSC_VER) && defined(__AVX__)
+ return (unsigned int)__popcnt64(x);
+
+#elif __has_builtin(__builtin_popcount)
+ if (sizeof(long) * CHAR_BIT == 64) {
+ return (unsigned int)__builtin_popcountl((unsigned long)x);
+ }
+ else if (sizeof(long long) * CHAR_BIT == 64) {
+ return (unsigned int)__builtin_popcountll((unsigned long long)x);
+ }
+ else {
+ /* :FIXME: Is there a way to make this branch a compile-time error? */
+ UNREACHABLE_RETURN(~0);
+ }
+
+#else
+ x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
+ x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
+ x = (x & 0x0707070707070707) + (x >> 4 & 0x0707070707070707);
+ x = (x & 0x001f001f001f001f) + (x >> 8 & 0x001f001f001f001f);
+ x = (x & 0x0000003f0000003f) + (x >>16 & 0x0000003f0000003f);
+ x = (x & 0x000000000000007f) + (x >>32 & 0x000000000000007f);
+ return (unsigned int)x;
+
+#endif
+}
+
+static inline unsigned int
+rb_popcount_intptr(uintptr_t x)
+{
+ if (sizeof(uintptr_t) * CHAR_BIT == 64) {
+ return rb_popcount64((uint64_t)x);
+ }
+ else if (sizeof(uintptr_t) * CHAR_BIT == 32) {
+ return rb_popcount32((uint32_t)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline int
+ntz_int32(uint32_t x)
+{
+#if defined(__x86_64__) && defined(__BMI__) && ! defined(MJIT_HEADER)
+ return (unsigned)_tzcnt_u32(x);
+
+#elif MSC_VERSION_SINCE(1400)
+ /* :FIXME: Is there any way to issue TZCNT instead of BSF, apart from using
+ * assembly? Because issuing LZCNT seems possible (see nlz.h). */
+ unsigned long r;
+ return _BitScanForward(&r, x) ? (int)r : 32;
+
+#elif __has_builtin(__builtin_ctz)
+ STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT == 32);
+ return x ? (unsigned)__builtin_ctz(x) : 32;
+
+#else
+ return rb_popcount32((~x) & (x-1));
+
+#endif
+}
+
+static inline int
+ntz_int64(uint64_t x)
+{
+#if defined(__x86_64__) && defined(__BMI__) && ! defined(MJIT_HEADER)
+ return (unsigned)_tzcnt_u64(x);
+
+#elif defined(_WIN64) && MSC_VERSION_SINCE(1400)
+ unsigned long r;
+ return _BitScanForward64(&r, x) ? (int)r : 64;
+
+#elif __has_builtin(__builtin_ctzl)
+ if (x == 0) {
+ return 64;
+ }
+ else if (sizeof(long) * CHAR_BIT == 64) {
+ return (unsigned)__builtin_ctzl((unsigned long)x);
+ }
+ else if (sizeof(long long) * CHAR_BIT == 64) {
+ return (unsigned)__builtin_ctzll((unsigned long long)x);
+ }
+ else {
+ /* :FIXME: Is there a way to make this branch a compile-time error? */
+ UNREACHABLE_RETURN(~0);
+ }
+
+#else
+ return rb_popcount64((~x) & (x-1));
+
+#endif
+}
+
+static inline int
+ntz_intptr(uintptr_t x)
+{
+ if (sizeof(uintptr_t) * CHAR_BIT == 64) {
+ return ntz_int64((uint64_t)x);
+ }
+ else if (sizeof(uintptr_t) * CHAR_BIT == 32) {
+ return ntz_int32((uint32_t)x);
+ }
+ else {
+ UNREACHABLE_RETURN(~0);
+ }
+}
+
+static inline VALUE
+RUBY_BIT_ROTL(VALUE v, int n)
+{
+#if __has_builtin(__builtin_rotateleft32) && (SIZEOF_VALUE * CHAR_BIT == 32)
+ return __builtin_rotateleft32(v, n);
+
+#elif __has_builtin(__builtin_rotateleft64) && (SIZEOF_VALUE * CHAR_BIT == 64)
+ return __builtin_rotateleft64(v, n);
+
+#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 32)
+ return _rotl(v, n);
+
+#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64)
+ return _rotl64(v, n);
+
+#elif defined(_lrotl) && (SIZEOF_VALUE == SIZEOF_LONG)
+ return _lrotl(v, n);
+
+#else
+ const int m = (sizeof(VALUE) * CHAR_BIT) - 1;
+ return (v << (n & m)) | (v >> (-n & m));
+#endif
+}
+
+static inline VALUE
+RUBY_BIT_ROTR(VALUE v, int n)
+{
+#if __has_builtin(__builtin_rotateright32) && (SIZEOF_VALUE * CHAR_BIT == 32)
+ return __builtin_rotateright32(v, n);
+
+#elif __has_builtin(__builtin_rotateright64) && (SIZEOF_VALUE * CHAR_BIT == 64)
+ return __builtin_rotateright64(v, n);
+
+#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 32)
+ return _rotr(v, n);
+
+#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64)
+ return _rotr64(v, n);
+
+#elif defined(_lrotr) && (SIZEOF_VALUE == SIZEOF_LONG)
+ return _lrotr(v, n);
+
+#else
+ const int m = (sizeof(VALUE) * CHAR_BIT) - 1;
+ return (v << (-n & m)) | (v >> (n & m));
+#endif
+}
+
+#endif /* INTERNAL_BITS_H */
diff --git a/internal/class.h b/internal/class.h
new file mode 100644
index 0000000000..eade920ff0
--- /dev/null
+++ b/internal/class.h
@@ -0,0 +1,174 @@
+#ifndef INTERNAL_CLASS_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_CLASS_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.
+ * @brief Internal header for Class.
+ */
+#include "id_table.h" /* for struct rb_id_table */
+#include "internal/gc.h" /* for RB_OBJ_WRITE */
+#include "internal/serial.h" /* for rb_serial_t */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/intern.h" /* for rb_alloc_func_t */
+#include "ruby/ruby.h" /* for struct RBasic */
+
+#ifdef RCLASS_SUPER
+# undef RCLASS_SUPER
+#endif
+
+struct rb_subclass_entry {
+ VALUE klass;
+ struct rb_subclass_entry *next;
+};
+
+struct rb_iv_index_tbl_entry {
+ uint32_t index;
+ rb_serial_t class_serial;
+ VALUE class_value;
+};
+
+struct rb_classext_struct {
+ struct st_table *iv_index_tbl; // ID -> struct rb_iv_index_tbl_entry
+ struct st_table *iv_tbl;
+#if SIZEOF_SERIAL_T == SIZEOF_VALUE /* otherwise m_tbl is in struct RClass */
+ struct rb_id_table *m_tbl;
+#endif
+ struct rb_id_table *const_tbl;
+ struct rb_id_table *callable_m_tbl;
+ struct rb_id_table *cc_tbl; /* ID -> [[ci, cc1], cc2, ...] */
+ struct rb_subclass_entry *subclasses;
+ struct rb_subclass_entry **parent_subclasses;
+ /**
+ * In the case that this is an `ICLASS`, `module_subclasses` points to the link
+ * in the module's `subclasses` list that indicates that the klass has been
+ * included. Hopefully that makes sense.
+ */
+ struct rb_subclass_entry **module_subclasses;
+#if SIZEOF_SERIAL_T != SIZEOF_VALUE /* otherwise class_serial is in struct RClass */
+ rb_serial_t class_serial;
+#endif
+ const VALUE origin_;
+ const VALUE refined_class;
+ rb_alloc_func_t allocator;
+ const VALUE includer;
+};
+
+struct RClass {
+ struct RBasic basic;
+ VALUE super;
+ struct rb_classext_struct *ptr;
+#if SIZEOF_SERIAL_T == SIZEOF_VALUE
+ /* Class serial is as wide as VALUE. Place it here. */
+ rb_serial_t class_serial;
+#else
+ /* Class serial does not fit into struct RClass. Place m_tbl instead. */
+ struct rb_id_table *m_tbl;
+#endif
+};
+
+typedef struct rb_subclass_entry rb_subclass_entry_t;
+typedef struct rb_classext_struct rb_classext_t;
+
+#define RCLASS_EXT(c) (RCLASS(c)->ptr)
+#define RCLASS_IV_TBL(c) (RCLASS_EXT(c)->iv_tbl)
+#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl)
+#if SIZEOF_SERIAL_T == SIZEOF_VALUE
+# define RCLASS_M_TBL(c) (RCLASS_EXT(c)->m_tbl)
+#else
+# define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
+#endif
+#define RCLASS_CALLABLE_M_TBL(c) (RCLASS_EXT(c)->callable_m_tbl)
+#define RCLASS_CC_TBL(c) (RCLASS_EXT(c)->cc_tbl)
+#define RCLASS_IV_INDEX_TBL(c) (RCLASS_EXT(c)->iv_index_tbl)
+#define RCLASS_ORIGIN(c) (RCLASS_EXT(c)->origin_)
+#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class)
+#if SIZEOF_SERIAL_T == SIZEOF_VALUE
+# define RCLASS_SERIAL(c) (RCLASS(c)->class_serial)
+#else
+# define RCLASS_SERIAL(c) (RCLASS_EXT(c)->class_serial)
+#endif
+#define RCLASS_INCLUDER(c) (RCLASS_EXT(c)->includer)
+
+#define RICLASS_IS_ORIGIN FL_USER5
+#define RCLASS_CLONED FL_USER6
+#define RICLASS_ORIGIN_SHARED_MTBL FL_USER8
+
+/* class.c */
+void rb_class_subclass_add(VALUE super, VALUE klass);
+void rb_class_remove_from_super_subclasses(VALUE);
+int rb_singleton_class_internal_p(VALUE sklass);
+VALUE rb_class_boot(VALUE);
+VALUE rb_make_metaclass(VALUE, VALUE);
+VALUE rb_include_class_new(VALUE, VALUE);
+void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE);
+void rb_class_detach_subclasses(VALUE);
+void rb_class_detach_module_subclasses(VALUE);
+void rb_class_remove_from_module_subclasses(VALUE);
+VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj);
+VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj);
+VALUE rb_obj_private_methods(int argc, const VALUE *argv, VALUE obj);
+VALUE rb_obj_public_methods(int argc, const VALUE *argv, VALUE obj);
+VALUE rb_special_singleton_class(VALUE);
+VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach);
+VALUE rb_singleton_class_get(VALUE obj);
+int rb_class_has_methods(VALUE c);
+void rb_undef_methods_from(VALUE klass, VALUE super);
+
+static inline void RCLASS_SET_ORIGIN(VALUE klass, VALUE origin);
+static inline void RICLASS_SET_ORIGIN_SHARED_MTBL(VALUE iclass);
+static inline VALUE RCLASS_SUPER(VALUE klass);
+static inline VALUE RCLASS_SET_SUPER(VALUE klass, VALUE super);
+static inline void RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass);
+
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE rb_class_inherited(VALUE, VALUE);
+VALUE rb_keyword_error_new(const char *, VALUE);
+MJIT_SYMBOL_EXPORT_END
+
+static inline void
+RCLASS_SET_ORIGIN(VALUE klass, VALUE origin)
+{
+ RB_OBJ_WRITE(klass, &RCLASS_ORIGIN(klass), origin);
+ if (klass != origin) FL_SET(origin, RICLASS_IS_ORIGIN);
+}
+
+static inline void
+RICLASS_SET_ORIGIN_SHARED_MTBL(VALUE iclass)
+{
+ FL_SET(iclass, RICLASS_ORIGIN_SHARED_MTBL);
+}
+
+static inline bool
+RICLASS_OWNS_M_TBL_P(VALUE iclass)
+{
+ return FL_TEST_RAW(iclass, RICLASS_IS_ORIGIN | RICLASS_ORIGIN_SHARED_MTBL) == RICLASS_IS_ORIGIN;
+}
+
+static inline void
+RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass)
+{
+ RB_OBJ_WRITE(iclass, &RCLASS_INCLUDER(iclass), klass);
+}
+
+static inline VALUE
+RCLASS_SUPER(VALUE klass)
+{
+ return RCLASS(klass)->super;
+}
+
+static inline VALUE
+RCLASS_SET_SUPER(VALUE klass, VALUE super)
+{
+ if (super) {
+ rb_class_remove_from_super_subclasses(klass);
+ rb_class_subclass_add(super, klass);
+ }
+ RB_OBJ_WRITE(klass, &RCLASS(klass)->super, super);
+ return super;
+}
+
+#endif /* INTERNAL_CLASS_H */
diff --git a/internal/compar.h b/internal/compar.h
new file mode 100644
index 0000000000..888a3b5e1e
--- /dev/null
+++ b/internal/compar.h
@@ -0,0 +1,50 @@
+#ifndef INTERNAL_COMPAR_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_COMPAR_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.
+ * @brief Internal header for Comparable.
+ */
+#include "internal/vm.h" /* for rb_method_basic_definition_p */
+
+#define STRING_P(s) (RB_TYPE_P((s), T_STRING) && CLASS_OF(s) == rb_cString)
+
+enum {
+ cmp_opt_Integer,
+ cmp_opt_String,
+ cmp_opt_Float,
+ cmp_optimizable_count
+};
+
+struct cmp_opt_data {
+ unsigned int opt_methods;
+ unsigned int opt_inited;
+};
+
+#define NEW_CMP_OPT_MEMO(type, value) \
+ NEW_PARTIAL_MEMO_FOR(type, value, cmp_opt)
+#define CMP_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(cmp_opt_,type))
+#define CMP_OPTIMIZABLE(data, type) \
+ (((data).opt_inited & CMP_OPTIMIZABLE_BIT(type)) ? \
+ ((data).opt_methods & CMP_OPTIMIZABLE_BIT(type)) : \
+ (((data).opt_inited |= CMP_OPTIMIZABLE_BIT(type)), \
+ rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \
+ ((data).opt_methods |= CMP_OPTIMIZABLE_BIT(type))))
+
+#define OPTIMIZED_CMP(a, b, data) \
+ ((FIXNUM_P(a) && FIXNUM_P(b) && CMP_OPTIMIZABLE(data, Integer)) ? \
+ (((long)a > (long)b) ? 1 : ((long)a < (long)b) ? -1 : 0) : \
+ (STRING_P(a) && STRING_P(b) && CMP_OPTIMIZABLE(data, String)) ? \
+ rb_str_cmp(a, b) : \
+ (RB_FLOAT_TYPE_P(a) && RB_FLOAT_TYPE_P(b) && CMP_OPTIMIZABLE(data, Float)) ? \
+ rb_float_cmp(a, b) : \
+ rb_cmpint(rb_funcallv(a, id_cmp, 1, &b), a, b))
+
+/* compar.c */
+VALUE rb_invcmp(VALUE, VALUE);
+
+#endif /* INTERNAL_COMPAR_H */
diff --git a/internal/compile.h b/internal/compile.h
new file mode 100644
index 0000000000..9842e0f5e0
--- /dev/null
+++ b/internal/compile.h
@@ -0,0 +1,32 @@
+#ifndef INTERNAL_COMPILE_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_COMPILE_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.
+ * @brief Internal header for the compiler.
+ */
+#include "ruby/internal/config.h"
+#include <stddef.h> /* for size_t */
+#include "ruby/ruby.h" /* for rb_event_flag_t */
+
+struct rb_iseq_struct; /* in vm_core.h */
+
+/* compile.c */
+int rb_dvar_defined(ID, const struct rb_iseq_struct *);
+int rb_local_defined(ID, const struct rb_iseq_struct *);
+const char *rb_insns_name(int i);
+VALUE rb_insns_name_array(void);
+
+/* iseq.c */
+int rb_vm_insn_addr2insn(const void *);
+
+MJIT_SYMBOL_EXPORT_BEGIN
+/* iseq.c (export) */
+rb_event_flag_t rb_iseq_event_flags(const struct rb_iseq_struct *iseq, size_t pos);
+MJIT_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_COMPILE_H */
diff --git a/internal/compilers.h b/internal/compilers.h
new file mode 100644
index 0000000000..8a2f1d8d26
--- /dev/null
+++ b/internal/compilers.h
@@ -0,0 +1,108 @@
+#ifndef INTERNAL_COMPILERS_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_COMPILERS_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.
+ * @brief Internal header absorbing C compipler differences.
+ */
+#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/has/attribute.h"
+#include "ruby/internal/has/builtin.h"
+#include "ruby/internal/has/c_attribute.h"
+#include "ruby/internal/has/declspec_attribute.h"
+#include "ruby/internal/has/extension.h"
+#include "ruby/internal/has/feature.h"
+#include "ruby/internal/has/warning.h"
+#include "ruby/backward/2/gcc_version_since.h"
+
+#define MSC_VERSION_SINCE(_) RBIMPL_COMPILER_SINCE(MSVC, (_) / 100, (_) % 100, 0)
+#define MSC_VERSION_BEFORE(_) RBIMPL_COMPILER_BEFORE(MSVC, (_) / 100, (_) % 100, 0)
+
+#ifndef __has_attribute
+# define __has_attribute(...) RBIMPL_HAS_ATTRIBUTE(__VA_ARGS__)
+#endif
+
+#ifndef __has_c_attribute
+# /* As of writing everything that lacks __has_c_attribute also completely
+# * lacks C2x attributes as well. Might change in future? */
+# define __has_c_attribute(...) 0
+#endif
+
+#ifndef __has_declspec_attribute
+# define __has_declspec_attribute(...) RBIMPL_HAS_DECLSPEC_ATTRIBUTE(__VA_ARGS__)
+#endif
+
+#ifndef __has_builtin
+# define __has_builtin(...) RBIMPL_HAS_BUILTIN(__VA_ARGS__)
+#endif
+
+#ifndef __has_feature
+# define __has_feature(...) RBIMPL_HAS_FEATURE(__VA_ARGS__)
+#endif
+
+#ifndef __has_extension
+# define __has_extension(...) RBIMPL_HAS_EXTENSION(__VA_ARGS__)
+#endif
+
+#ifndef __has_warning
+# define __has_warning(...) RBIMPL_HAS_WARNING(__VA_ARGS__)
+#endif
+
+#ifndef __GNUC__
+# define __extension__ /* void */
+#endif
+
+#ifndef MAYBE_UNUSED
+# define MAYBE_UNUSED(x) x
+#endif
+
+#ifndef WARN_UNUSED_RESULT
+# define WARN_UNUSED_RESULT(x) x
+#endif
+
+#define RB_OBJ_BUILTIN_TYPE(obj) rb_obj_builtin_type(obj)
+#define OBJ_BUILTIN_TYPE(obj) RB_OBJ_BUILTIN_TYPE(obj)
+#ifdef __GNUC__
+#define rb_obj_builtin_type(obj) \
+__extension__({ \
+ VALUE arg_obj = (obj); \
+ RB_SPECIAL_CONST_P(arg_obj) ? -1 : \
+ (int)RB_BUILTIN_TYPE(arg_obj); \
+ })
+#else
+# include "ruby/ruby.h"
+static inline int
+rb_obj_builtin_type(VALUE obj)
+{
+ return RB_SPECIAL_CONST_P(obj) ? -1 :
+ (int)RB_BUILTIN_TYPE(obj);
+}
+#endif
+
+/* A macro for defining a flexible array, like: VALUE ary[FLEX_ARY_LEN]; */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEX_ARY_LEN /* VALUE ary[]; */
+#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
+# define FLEX_ARY_LEN 0 /* VALUE ary[0]; */
+#else
+# define FLEX_ARY_LEN 1 /* VALUE ary[1]; */
+#endif
+
+/*
+ * For declaring bitfields out of non-unsigned int types:
+ * struct date {
+ * BITFIELD(enum months, month, 4);
+ * ...
+ * };
+ */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define BITFIELD(type, name, size) type name : size
+#else
+# define BITFIELD(type, name, size) unsigned int name : size
+#endif
+
+#endif /* INTERNAL_COMPILERS_H */
diff --git a/internal/complex.h b/internal/complex.h
new file mode 100644
index 0000000000..9eae804ddb
--- /dev/null
+++ b/internal/complex.h
@@ -0,0 +1,30 @@
+#ifndef INTERNAL_COMPLEX_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_COMPLEX_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.
+ * @brief Internal header for Complex.
+ */
+#include "ruby/internal/value.h" /* for struct RBasic */
+
+struct RComplex {
+ struct RBasic basic;
+ VALUE real;
+ VALUE imag;
+};
+
+#define RCOMPLEX(obj) ((struct RComplex *)(obj))
+
+/* shortcut macro for internal only */
+#define RCOMPLEX_SET_REAL(cmp, r) RB_OBJ_WRITE((cmp), &RCOMPLEX(cmp)->real, (r))
+#define RCOMPLEX_SET_IMAG(cmp, i) RB_OBJ_WRITE((cmp), &RCOMPLEX(cmp)->imag, (i))
+
+/* complex.c */
+VALUE rb_dbl_complex_new_polar_pi(double abs, double ang);
+st_index_t rb_complex_hash(VALUE comp);
+
+#endif /* INTERNAL_COMPLEX_H */
diff --git a/internal/cont.h b/internal/cont.h
new file mode 100644
index 0000000000..9e49dd3c8e
--- /dev/null
+++ b/internal/cont.h
@@ -0,0 +1,26 @@
+#ifndef INTERNAL_CONT_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_CONT_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.
+ * @brief Internal header for Fiber.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+
+struct rb_thread_struct; /* in vm_core.h */
+struct rb_fiber_struct; /* in cont.c */
+
+/* cont.c */
+VALUE rb_obj_is_fiber(VALUE);
+void rb_fiber_reset_root_local_storage(struct rb_thread_struct *);
+void ruby_register_rollback_func_for_ensure(VALUE (*ensure_func)(VALUE), VALUE (*rollback_func)(VALUE));
+void rb_fiber_init_mjit_cont(struct rb_fiber_struct *fiber);
+
+VALUE rb_fiberptr_self(struct rb_fiber_struct *fiber);
+unsigned int rb_fiberptr_blocking(struct rb_fiber_struct *fiber);
+
+#endif /* INTERNAL_CONT_H */
diff --git a/internal/dir.h b/internal/dir.h
new file mode 100644
index 0000000000..ffbdb25208
--- /dev/null
+++ b/internal/dir.h
@@ -0,0 +1,17 @@
+#ifndef INTERNAL_DIR_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_DIR_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.
+ * @brief Internal header for Dir.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+
+/* dir.c */
+VALUE rb_dir_getwd_ospath(void);
+
+#endif /* INTERNAL_DIR_H */
diff --git a/internal/enc.h b/internal/enc.h
new file mode 100644
index 0000000000..0afc74db5d
--- /dev/null
+++ b/internal/enc.h
@@ -0,0 +1,20 @@
+#ifndef INTERNAL_ENC_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_ENC_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.
+ * @brief Internal header for Encoding.
+ */
+#include "ruby/encoding.h" /* for rb_encoding */
+
+/* us_ascii.c */
+extern rb_encoding OnigEncodingUS_ASCII;
+
+/* utf_8.c */
+extern rb_encoding OnigEncodingUTF_8;
+
+#endif /* INTERNAL_ENC_H */
diff --git a/internal/encoding.h b/internal/encoding.h
new file mode 100644
index 0000000000..c0cf061bd4
--- /dev/null
+++ b/internal/encoding.h
@@ -0,0 +1,31 @@
+#ifndef INTERNAL_ENCODING_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_ENCODING_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.
+ * @brief Internal header for Encoding.
+ */
+#include "ruby/ruby.h" /* for ID */
+#include "ruby/encoding.h" /* for rb_encoding */
+
+#define rb_enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
+
+/* encoding.c */
+ID rb_id_encoding(void);
+rb_encoding *rb_enc_get_from_index(int index);
+rb_encoding *rb_enc_check_str(VALUE str1, VALUE str2);
+int rb_encdb_replicate(const char *alias, const char *orig);
+int rb_encdb_alias(const char *alias, const char *orig);
+int rb_enc_autoload(rb_encoding *enc);
+int rb_encdb_dummy(const char *name);
+void rb_encdb_declare(const char *name);
+void rb_enc_set_base(const char *name, const char *orig);
+int rb_enc_set_dummy(int index);
+void rb_encdb_set_unicode(int index);
+PUREFUNC(int rb_data_is_encoding(VALUE obj));
+
+#endif /* INTERNAL_ENCODING_H */
diff --git a/internal/enum.h b/internal/enum.h
new file mode 100644
index 0000000000..50890f0c9f
--- /dev/null
+++ b/internal/enum.h
@@ -0,0 +1,19 @@
+#ifndef INTERNAL_ENUM_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_ENUM_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.
+ * @brief Internal header for Enumerable.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+
+/* enum.c */
+extern VALUE rb_cArithSeq;
+VALUE rb_f_send(int argc, VALUE *argv, VALUE recv);
+VALUE rb_nmin_run(VALUE obj, VALUE num, int by, int rev, int ary);
+
+#endif /* INTERNAL_ENUM_H */
diff --git a/internal/enumerator.h b/internal/enumerator.h
new file mode 100644
index 0000000000..2e20c37d9e
--- /dev/null
+++ b/internal/enumerator.h
@@ -0,0 +1,22 @@
+#ifndef INTERNAL_ENUMERATOR_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_ENUMERATOR_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.
+ * @brief Internal header for Enumerator.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+#include "ruby/intern.h" /* for rb_enumerator_size_func */
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* enumerator.c (export) */
+VALUE rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
+ rb_enumerator_size_func *size_fn,
+ VALUE beg, VALUE end, VALUE step, int excl);
+RUBY_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_ENUMERATOR_H */
diff --git a/internal/error.h b/internal/error.h
new file mode 100644
index 0000000000..0dd629f052
--- /dev/null
+++ b/internal/error.h
@@ -0,0 +1,124 @@
+#ifndef INTERNAL_ERROR_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_ERROR_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.
+ * @brief Internal header for Exception.
+ */
+#include "ruby/internal/config.h"
+#include <stdarg.h> /* for va_list */
+#include "internal/string.h" /* for rb_fstring_cstr */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/encoding.h" /* for rb_encoding */
+#include "ruby/intern.h" /* for rb_exc_raise */
+#include "ruby/ruby.h" /* for enum ruby_value_type */
+
+#ifdef Check_Type
+# undef Check_Type /* in ruby/ruby.h */
+#endif
+
+#ifdef rb_raise_static
+# undef rb_raise_static
+# undef rb_sys_fail_path
+# undef rb_syserr_fail_path
+#endif
+
+#define rb_raise_static(e, m) \
+ rb_raise_cstr_i((e), rb_str_new_static((m), rb_strlen_lit(m)))
+#ifdef RUBY_FUNCTION_NAME_STRING
+# define rb_sys_fail_path(path) rb_sys_fail_path_in(RUBY_FUNCTION_NAME_STRING, path)
+# define rb_syserr_fail_path(err, path) rb_syserr_fail_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path))
+# define rb_syserr_new_path(err, path) rb_syserr_new_path_in(RUBY_FUNCTION_NAME_STRING, (err), (path))
+#else
+# define rb_sys_fail_path(path) rb_sys_fail_str(path)
+# define rb_syserr_fail_path(err, path) rb_syserr_fail_str((err), (path))
+# define rb_syserr_new_path(err, path) rb_syserr_new_str((err), (path))
+#endif
+
+/* error.c */
+extern long rb_backtrace_length_limit;
+extern VALUE rb_eEAGAIN;
+extern VALUE rb_eEWOULDBLOCK;
+extern VALUE rb_eEINPROGRESS;
+void rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args);
+NORETURN(void rb_async_bug_errno(const char *,int));
+const char *rb_builtin_type_name(int t);
+const char *rb_builtin_class_name(VALUE x);
+PRINTF_ARGS(void rb_warn_deprecated(const char *fmt, const char *suggest, ...), 1, 3);
+PRINTF_ARGS(void rb_warn_deprecated_to_remove(const char *fmt, const char *removal, ...), 1, 3);
+VALUE rb_syntax_error_append(VALUE, VALUE, int, int, rb_encoding*, const char*, va_list);
+PRINTF_ARGS(void rb_enc_warn(rb_encoding *enc, const char *fmt, ...), 2, 3);
+PRINTF_ARGS(void rb_sys_enc_warning(rb_encoding *enc, const char *fmt, ...), 2, 3);
+PRINTF_ARGS(void rb_syserr_enc_warning(int err, rb_encoding *enc, const char *fmt, ...), 3, 4);
+rb_warning_category_t rb_warning_category_from_name(VALUE category);
+bool rb_warning_category_enabled_p(rb_warning_category_t category);
+VALUE rb_name_err_new(VALUE mesg, VALUE recv, VALUE method);
+VALUE rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv);
+VALUE rb_key_err_new(VALUE mesg, VALUE recv, VALUE name);
+PRINTF_ARGS(VALUE rb_warning_string(const char *fmt, ...), 1, 2);
+NORETURN(void rb_vraise(VALUE, const char *, va_list));
+NORETURN(static inline void rb_raise_cstr(VALUE etype, const char *mesg));
+NORETURN(static inline void rb_raise_cstr_i(VALUE etype, VALUE mesg));
+NORETURN(static inline void rb_name_err_raise_str(VALUE mesg, VALUE recv, VALUE name));
+NORETURN(static inline void rb_name_err_raise(const char *mesg, VALUE recv, VALUE name));
+NORETURN(static inline void rb_key_err_raise(VALUE mesg, VALUE recv, VALUE name));
+static inline void Check_Type(VALUE v, enum ruby_value_type t);
+static inline bool rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type);
+#define rb_typeddata_is_instance_of rb_typeddata_is_instance_of_inline
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* error.c (export) */
+int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
+#ifdef RUBY_FUNCTION_NAME_STRING
+NORETURN(void rb_sys_fail_path_in(const char *func_name, VALUE path));
+NORETURN(void rb_syserr_fail_path_in(const char *func_name, int err, VALUE path));
+VALUE rb_syserr_new_path_in(const char *func_name, int n, VALUE path);
+#endif
+RUBY_SYMBOL_EXPORT_END
+
+static inline void
+rb_raise_cstr_i(VALUE etype, VALUE mesg)
+{
+ VALUE exc = rb_exc_new_str(etype, mesg);
+ rb_exc_raise(exc);
+}
+
+static inline void
+rb_raise_cstr(VALUE etype, const char *mesg)
+{
+ VALUE str = rb_str_new_cstr(mesg);
+ rb_raise_cstr_i(etype, str);
+}
+
+static inline void
+rb_name_err_raise_str(VALUE mesg, VALUE recv, VALUE name)
+{
+ VALUE exc = rb_name_err_new(mesg, recv, name);
+ rb_exc_raise(exc);
+}
+
+static inline void
+rb_name_err_raise(const char *mesg, VALUE recv, VALUE name)
+{
+ VALUE str = rb_fstring_cstr(mesg);
+ rb_name_err_raise_str(str, recv, name);
+}
+
+static inline void
+rb_key_err_raise(VALUE mesg, VALUE recv, VALUE name)
+{
+ VALUE exc = rb_key_err_new(mesg, recv, name);
+ rb_exc_raise(exc);
+}
+
+static inline bool
+rb_typeddata_is_instance_of_inline(VALUE obj, const rb_data_type_t *data_type)
+{
+ return RB_TYPE_P(obj, T_DATA) && RTYPEDDATA_P(obj) && (RTYPEDDATA_TYPE(obj) == data_type);
+}
+
+#endif /* INTERNAL_ERROR_H */
diff --git a/internal/eval.h b/internal/eval.h
new file mode 100644
index 0000000000..8dae76b6f8
--- /dev/null
+++ b/internal/eval.h
@@ -0,0 +1,33 @@
+#ifndef INTERNAL_EVAL_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_EVAL_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.
+ * @brief Internal header for the evaluator.
+ * @note There also is eval_intern.h, which is evaluator's internal
+ * header (related to this file, but not the same role).
+ */
+#include "ruby/ruby.h" /* for ID */
+
+#define id_signo ruby_static_id_signo
+#define id_status ruby_static_id_status
+
+/* eval.c */
+extern ID ruby_static_id_signo;
+extern ID ruby_static_id_status;
+VALUE rb_refinement_module_get_refined_class(VALUE module);
+void rb_class_modify_check(VALUE);
+NORETURN(VALUE rb_f_raise(int argc, VALUE *argv));
+
+/* eval_error.c */
+VALUE rb_get_backtrace(VALUE info);
+
+/* eval_jump.c */
+void rb_call_end_proc(VALUE data);
+void rb_mark_end_proc(void);
+
+#endif /* INTERNAL_EVAL_H */
diff --git a/internal/file.h b/internal/file.h
new file mode 100644
index 0000000000..a93c1392f0
--- /dev/null
+++ b/internal/file.h
@@ -0,0 +1,39 @@
+#ifndef INTERNAL_FILE_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_FILE_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.
+ * @brief Internal header for File.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+#include "ruby/encoding.h" /* for rb_encodinng */
+
+/* file.c */
+extern const char ruby_null_device[];
+VALUE rb_home_dir_of(VALUE user, VALUE result);
+VALUE rb_default_home_dir(VALUE result);
+VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict);
+VALUE rb_check_realpath(VALUE basedir, VALUE path, rb_encoding *origenc);
+void rb_file_const(const char*, VALUE);
+int rb_file_load_ok(const char *);
+VALUE rb_file_expand_path_fast(VALUE, VALUE);
+VALUE rb_file_expand_path_internal(VALUE, VALUE, int, int, VALUE);
+VALUE rb_get_path_check_to_string(VALUE);
+VALUE rb_get_path_check_convert(VALUE);
+int ruby_is_fd_loadable(int fd);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* file.c (export) */
+#ifdef HAVE_READLINK
+VALUE rb_readlink(VALUE path, rb_encoding *enc);
+#endif
+#ifdef __APPLE__
+VALUE rb_str_normalize_ospath(const char *ptr, long len);
+#endif
+RUBY_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_FILE_H */
diff --git a/internal/fixnum.h b/internal/fixnum.h
new file mode 100644
index 0000000000..7e0e4be84c
--- /dev/null
+++ b/internal/fixnum.h
@@ -0,0 +1,185 @@
+#ifndef INTERNAL_FIXNUM_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_FIXNUM_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.
+ * @brief Internal header for Fixnums.
+ */
+#include "ruby/internal/config.h" /* for HAVE_LONG_LONG */
+#include <limits.h> /* for CHAR_BIT */
+#include "internal/compilers.h" /* for __has_builtin */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/intern.h" /* for rb_big_mul */
+#include "ruby/ruby.h" /* for RB_FIXABLE */
+
+#if HAVE_LONG_LONG && SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
+# define DLONG LONG_LONG
+# define DL2NUM(x) LL2NUM(x)
+#elif defined(HAVE_INT128_T)
+# define DLONG int128_t
+# define DL2NUM(x) (RB_FIXABLE(x) ? LONG2FIX(x) : rb_int128t2big(x))
+VALUE rb_int128t2big(int128_t n); /* in bignum.c */
+#endif
+
+static inline long rb_overflowed_fix_to_int(long x);
+static inline VALUE rb_fix_plus_fix(VALUE x, VALUE y);
+static inline VALUE rb_fix_minus_fix(VALUE x, VALUE y);
+static inline VALUE rb_fix_mul_fix(VALUE x, VALUE y);
+static inline void rb_fix_divmod_fix(VALUE x, VALUE y, VALUE *divp, VALUE *modp);
+static inline VALUE rb_fix_div_fix(VALUE x, VALUE y);
+static inline VALUE rb_fix_mod_fix(VALUE x, VALUE y);
+static inline bool FIXNUM_POSITIVE_P(VALUE num);
+static inline bool FIXNUM_NEGATIVE_P(VALUE num);
+static inline bool FIXNUM_ZERO_P(VALUE num);
+
+static inline long
+rb_overflowed_fix_to_int(long x)
+{
+ return (long)((unsigned long)(x >> 1) ^ (1LU << (SIZEOF_LONG * CHAR_BIT - 1)));
+}
+
+static inline VALUE
+rb_fix_plus_fix(VALUE x, VALUE y)
+{
+#if !__has_builtin(__builtin_add_overflow)
+ long lz = FIX2LONG(x) + FIX2LONG(y);
+ return LONG2NUM(lz);
+#else
+ long lz;
+ /* NOTE
+ * (1) `LONG2FIX(FIX2LONG(x)+FIX2LONG(y))`
+ + = `((lx*2+1)/2 + (ly*2+1)/2)*2+1`
+ + = `lx*2 + ly*2 + 1`
+ + = `(lx*2+1) + (ly*2+1) - 1`
+ + = `x + y - 1`
+ * (2) Fixnum's LSB is always 1.
+ * It means you can always run `x - 1` without overflow.
+ * (3) Of course `z = x + (y-1)` may overflow.
+ * At that time true value is
+ * * positive: 0b0 1xxx...1, and z = 0b1xxx...1
+ * * negative: 0b1 0xxx...1, and z = 0b0xxx...1
+ * To convert this true value to long,
+ * (a) Use arithmetic shift
+ * * positive: 0b11xxx...
+ * * negative: 0b00xxx...
+ * (b) invert MSB
+ * * positive: 0b01xxx...
+ * * negative: 0b10xxx...
+ */
+ if (__builtin_add_overflow((long)x, (long)y-1, &lz)) {
+ return rb_int2big(rb_overflowed_fix_to_int(lz));
+ }
+ else {
+ return (VALUE)lz;
+ }
+#endif
+}
+
+static inline VALUE
+rb_fix_minus_fix(VALUE x, VALUE y)
+{
+#if !__has_builtin(__builtin_sub_overflow)
+ long lz = FIX2LONG(x) - FIX2LONG(y);
+ return LONG2NUM(lz);
+#else
+ long lz;
+ if (__builtin_sub_overflow((long)x, (long)y-1, &lz)) {
+ return rb_int2big(rb_overflowed_fix_to_int(lz));
+ }
+ else {
+ return (VALUE)lz;
+ }
+#endif
+}
+
+/* arguments must be Fixnum */
+static inline VALUE
+rb_fix_mul_fix(VALUE x, VALUE y)
+{
+ long lx = FIX2LONG(x);
+ long ly = FIX2LONG(y);
+#ifdef DLONG
+ return DL2NUM((DLONG)lx * (DLONG)ly);
+#else
+ if (MUL_OVERFLOW_FIXNUM_P(lx, ly)) {
+ return rb_big_mul(rb_int2big(lx), rb_int2big(ly));
+ }
+ else {
+ return LONG2FIX(lx * ly);
+ }
+#endif
+}
+
+/*
+ * This behaves different from C99 for negative arguments.
+ * Note that div may overflow fixnum.
+ */
+static inline void
+rb_fix_divmod_fix(VALUE a, VALUE b, VALUE *divp, VALUE *modp)
+{
+ /* assume / and % comply C99.
+ * ldiv(3) won't be inlined by GCC and clang.
+ * I expect / and % are compiled as single idiv.
+ */
+ long x = FIX2LONG(a);
+ long y = FIX2LONG(b);
+ long div, mod;
+ if (x == FIXNUM_MIN && y == -1) {
+ if (divp) *divp = LONG2NUM(-FIXNUM_MIN);
+ if (modp) *modp = LONG2FIX(0);
+ return;
+ }
+ div = x / y;
+ mod = x % y;
+ if (y > 0 ? mod < 0 : mod > 0) {
+ mod += y;
+ div -= 1;
+ }
+ if (divp) *divp = LONG2FIX(div);
+ if (modp) *modp = LONG2FIX(mod);
+}
+
+/* div() for Ruby
+ * This behaves different from C99 for negative arguments.
+ */
+static inline VALUE
+rb_fix_div_fix(VALUE x, VALUE y)
+{
+ VALUE div;
+ rb_fix_divmod_fix(x, y, &div, NULL);
+ return div;
+}
+
+/* mod() for Ruby
+ * This behaves different from C99 for negative arguments.
+ */
+static inline VALUE
+rb_fix_mod_fix(VALUE x, VALUE y)
+{
+ VALUE mod;
+ rb_fix_divmod_fix(x, y, NULL, &mod);
+ return mod;
+}
+
+static inline bool
+FIXNUM_POSITIVE_P(VALUE num)
+{
+ return (SIGNED_VALUE)num > (SIGNED_VALUE)INT2FIX(0);
+}
+
+static inline bool
+FIXNUM_NEGATIVE_P(VALUE num)
+{
+ return (SIGNED_VALUE)num < 0;
+}
+
+static inline bool
+FIXNUM_ZERO_P(VALUE num)
+{
+ return num == INT2FIX(0);
+}
+#endif /* INTERNAL_FIXNUM_H */
diff --git a/internal/gc.h b/internal/gc.h
new file mode 100644
index 0000000000..d439f6d8f6
--- /dev/null
+++ b/internal/gc.h
@@ -0,0 +1,167 @@
+#ifndef INTERNAL_GC_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_GC_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.
+ * @brief Internal header for GC.
+ */
+#include "ruby/internal/config.h"
+
+#include <stddef.h> /* for size_t */
+
+#include "internal/compilers.h" /* for __has_attribute */
+#include "ruby/ruby.h" /* for rb_event_flag_t */
+
+struct rb_execution_context_struct; /* in vm_core.h */
+struct rb_objspace; /* in vm_core.h */
+
+#ifdef NEWOBJ_OF
+# undef NEWOBJ_OF
+# undef RB_NEWOBJ_OF
+# undef RB_OBJ_WRITE
+#endif
+
+/* optimized version of NEWOBJ() */
+#define RB_NEWOBJ_OF(var, T, c, f) \
+ T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \
+ rb_wb_protected_newobj_of((c), (f) & ~FL_WB_PROTECTED) : \
+ rb_wb_unprotected_newobj_of((c), (f)))
+
+#define RB_EC_NEWOBJ_OF(ec, var, T, c, f) \
+ T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \
+ rb_ec_wb_protected_newobj_of((ec), (c), (f) & ~FL_WB_PROTECTED) : \
+ rb_wb_unprotected_newobj_of((c), (f)))
+
+#define NEWOBJ_OF(var, T, c, f) RB_NEWOBJ_OF((var), T, (c), (f))
+#define RB_OBJ_GC_FLAGS_MAX 6 /* used in ext/objspace */
+
+#ifndef USE_UNALIGNED_MEMBER_ACCESS
+# define UNALIGNED_MEMBER_ACCESS(expr) (expr)
+#elif ! USE_UNALIGNED_MEMBER_ACCESS
+# define UNALIGNED_MEMBER_ACCESS(expr) (expr)
+#elif ! (__has_warning("-Waddress-of-packed-member") || GCC_VERSION_SINCE(9, 0, 0))
+# define UNALIGNED_MEMBER_ACCESS(expr) (expr)
+#else
+# include "internal/warnings.h"
+# define UNALIGNED_MEMBER_ACCESS(expr) __extension__({ \
+ COMPILER_WARNING_PUSH; \
+ COMPILER_WARNING_IGNORED(-Waddress-of-packed-member); \
+ __typeof__(expr) unaligned_member_access_result = (expr); \
+ COMPILER_WARNING_POP; \
+ unaligned_member_access_result; \
+})
+#endif
+
+#define UNALIGNED_MEMBER_PTR(ptr, mem) UNALIGNED_MEMBER_ACCESS(&(ptr)->mem)
+#define RB_OBJ_WRITE(a, slot, b) \
+ rb_obj_write((VALUE)(a), UNALIGNED_MEMBER_ACCESS((VALUE *)(slot)), \
+ (VALUE)(b), __FILE__, __LINE__)
+
+typedef struct ractor_newobj_cache {
+ struct RVALUE *freelist;
+ struct heap_page *using_page;
+} rb_ractor_newobj_cache_t;
+
+/* gc.c */
+extern VALUE *ruby_initial_gc_stress_ptr;
+extern int ruby_disable_gc;
+RUBY_ATTR_MALLOC void *ruby_mimmalloc(size_t size);
+void ruby_mimfree(void *ptr);
+void rb_objspace_set_event_hook(const rb_event_flag_t event);
+VALUE rb_objspace_gc_enable(struct rb_objspace *);
+VALUE rb_objspace_gc_disable(struct rb_objspace *);
+void ruby_gc_set_params(void);
+void rb_copy_wb_protected_attribute(VALUE dest, VALUE obj);
+#if __has_attribute(alloc_align)
+__attribute__((__alloc_align__(1)))
+#endif
+RUBY_ATTR_MALLOC void *rb_aligned_malloc(size_t, size_t) RUBY_ATTR_ALLOC_SIZE((2));
+size_t rb_size_mul_or_raise(size_t, size_t, VALUE); /* used in compile.c */
+size_t rb_size_mul_add_or_raise(size_t, size_t, size_t, VALUE); /* used in iseq.h */
+RUBY_ATTR_MALLOC void *rb_xmalloc_mul_add(size_t, size_t, size_t);
+void *rb_xrealloc_mul_add(const void *, size_t, size_t, size_t);
+RUBY_ATTR_MALLOC void *rb_xmalloc_mul_add_mul(size_t, size_t, size_t, size_t);
+RUBY_ATTR_MALLOC void *rb_xcalloc_mul_add_mul(size_t, size_t, size_t, size_t);
+static inline void *ruby_sized_xrealloc_inlined(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2));
+static inline void *ruby_sized_xrealloc2_inlined(void *ptr, size_t new_count, size_t elemsiz, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3));
+static inline void ruby_sized_xfree_inlined(void *ptr, size_t size);
+VALUE rb_class_allocate_instance(VALUE klass);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* gc.c (export) */
+const char *rb_objspace_data_type_name(VALUE obj);
+VALUE rb_wb_protected_newobj_of(VALUE, VALUE);
+VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE);
+VALUE rb_ec_wb_protected_newobj_of(struct rb_execution_context_struct *ec, VALUE klass, VALUE flags);
+size_t rb_obj_memsize_of(VALUE);
+void rb_gc_verify_internal_consistency(void);
+size_t rb_obj_gc_flags(VALUE, ID[], size_t);
+void rb_gc_mark_values(long n, const VALUE *values);
+void rb_gc_mark_vm_stack_values(long n, const VALUE *values);
+void *ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2));
+void *ruby_sized_xrealloc2(void *ptr, size_t new_count, size_t element_size, size_t old_count) RUBY_ATTR_RETURNS_NONNULL RUBY_ATTR_ALLOC_SIZE((2, 3));
+void ruby_sized_xfree(void *x, size_t size);
+void rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache);
+RUBY_SYMBOL_EXPORT_END
+
+MJIT_SYMBOL_EXPORT_BEGIN
+int rb_ec_stack_check(struct rb_execution_context_struct *ec);
+void rb_gc_writebarrier_remember(VALUE obj);
+const char *rb_obj_info(VALUE obj);
+MJIT_SYMBOL_EXPORT_END
+
+#if defined(HAVE_MALLOC_USABLE_SIZE) || defined(HAVE_MALLOC_SIZE) || defined(_WIN32)
+
+static inline void *
+ruby_sized_xrealloc_inlined(void *ptr, size_t new_size, size_t old_size)
+{
+ return ruby_xrealloc(ptr, new_size);
+}
+
+static inline void *
+ruby_sized_xrealloc2_inlined(void *ptr, size_t new_count, size_t elemsiz, size_t old_count)
+{
+ return ruby_xrealloc2(ptr, new_count, elemsiz);
+}
+
+static inline void
+ruby_sized_xfree_inlined(void *ptr, size_t size)
+{
+ ruby_xfree(ptr);
+}
+
+# define SIZED_REALLOC_N(x, y, z, w) REALLOC_N(x, y, z)
+
+#else
+
+static inline void *
+ruby_sized_xrealloc_inlined(void *ptr, size_t new_size, size_t old_size)
+{
+ return ruby_sized_xrealloc(ptr, new_size, old_size);
+}
+
+static inline void *
+ruby_sized_xrealloc2_inlined(void *ptr, size_t new_count, size_t elemsiz, size_t old_count)
+{
+ return ruby_sized_xrealloc2(ptr, new_count, elemsiz, old_count);
+}
+
+static inline void
+ruby_sized_xfree_inlined(void *ptr, size_t size)
+{
+ ruby_sized_xfree(ptr, size);
+}
+
+# define SIZED_REALLOC_N(v, T, m, n) \
+ ((v) = (T *)ruby_sized_xrealloc2((void *)(v), (m), sizeof(T), (n)))
+
+#endif /* HAVE_MALLOC_USABLE_SIZE */
+
+#define ruby_sized_xrealloc ruby_sized_xrealloc_inlined
+#define ruby_sized_xrealloc2 ruby_sized_xrealloc2_inlined
+#define ruby_sized_xfree ruby_sized_xfree_inlined
+#endif /* INTERNAL_GC_H */
diff --git a/internal/hash.h b/internal/hash.h
new file mode 100644
index 0000000000..a4677c581b
--- /dev/null
+++ b/internal/hash.h
@@ -0,0 +1,241 @@
+#ifndef INTERNAL_HASH_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_HASH_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.
+ * @brief Internal header for Hash.
+ */
+#include "ruby/internal/config.h"
+#include <stddef.h> /* for size_t */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/ruby.h" /* for struct RBasic */
+#include "ruby/st.h" /* for struct st_table */
+
+#define RHASH_AR_TABLE_MAX_SIZE SIZEOF_VALUE
+
+struct ar_table_struct;
+typedef unsigned char ar_hint_t;
+
+enum ruby_rhash_flags {
+ RHASH_PASS_AS_KEYWORDS = FL_USER1, /* FL 1 */
+ RHASH_PROC_DEFAULT = FL_USER2, /* FL 2 */
+ RHASH_ST_TABLE_FLAG = FL_USER3, /* FL 3 */
+ RHASH_AR_TABLE_SIZE_MASK = (FL_USER4|FL_USER5|FL_USER6|FL_USER7), /* FL 4..7 */
+ RHASH_AR_TABLE_SIZE_SHIFT = (FL_USHIFT+4),
+ RHASH_AR_TABLE_BOUND_MASK = (FL_USER8|FL_USER9|FL_USER10|FL_USER11), /* FL 8..11 */
+ RHASH_AR_TABLE_BOUND_SHIFT = (FL_USHIFT+8),
+
+#if USE_TRANSIENT_HEAP
+ RHASH_TRANSIENT_FLAG = FL_USER12, /* FL 12 */
+#endif
+
+ // we can not put it in "enum" because it can exceed "int" range.
+#define RHASH_LEV_MASK (FL_USER13 | FL_USER14 | FL_USER15 | /* FL 13..19 */ \
+ FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19)
+
+ RHASH_LEV_SHIFT = (FL_USHIFT + 13),
+ RHASH_LEV_MAX = 127, /* 7 bits */
+};
+
+struct RHash {
+ struct RBasic basic;
+ union {
+ st_table *st;
+ struct ar_table_struct *ar; /* possibly 0 */
+ } as;
+ const VALUE ifnone;
+ union {
+ ar_hint_t ary[RHASH_AR_TABLE_MAX_SIZE];
+ VALUE word;
+ } ar_hint;
+};
+
+#define RHASH(obj) ((struct RHash *)(obj))
+
+#ifdef RHASH_IFNONE
+# undef RHASH_IFNONE
+#endif
+
+#ifdef RHASH_SIZE
+# undef RHASH_SIZE
+#endif
+
+#ifdef RHASH_EMPTY_P
+# undef RHASH_EMPTY_P
+#endif
+
+/* hash.c */
+void rb_hash_st_table_set(VALUE hash, st_table *st);
+VALUE rb_hash_default_value(VALUE hash, VALUE key);
+VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc);
+long rb_dbl_long_hash(double d);
+st_table *rb_init_identtable(void);
+VALUE rb_to_hash_type(VALUE obj);
+VALUE rb_hash_key_str(VALUE);
+VALUE rb_hash_values(VALUE hash);
+VALUE rb_hash_rehash(VALUE hash);
+int rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val);
+VALUE rb_hash_set_pair(VALUE hash, VALUE pair);
+int rb_hash_stlike_delete(VALUE hash, st_data_t *pkey, st_data_t *pval);
+int rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg);
+int rb_hash_stlike_update(VALUE hash, st_data_t key, st_update_callback_func *func, st_data_t arg);
+extern st_table *rb_hash_st_table(VALUE hash);
+
+static inline unsigned RHASH_AR_TABLE_SIZE_RAW(VALUE h);
+static inline VALUE RHASH_IFNONE(VALUE h);
+static inline size_t RHASH_SIZE(VALUE h);
+static inline bool RHASH_EMPTY_P(VALUE h);
+static inline bool RHASH_AR_TABLE_P(VALUE h);
+static inline bool RHASH_ST_TABLE_P(VALUE h);
+static inline struct ar_table_struct *RHASH_AR_TABLE(VALUE h);
+static inline st_table *RHASH_ST_TABLE(VALUE h);
+static inline size_t RHASH_ST_SIZE(VALUE h);
+static inline void RHASH_ST_CLEAR(VALUE h);
+static inline bool RHASH_TRANSIENT_P(VALUE h);
+static inline void RHASH_SET_TRANSIENT_FLAG(VALUE h);
+static inline void RHASH_UNSET_TRANSIENT_FLAG(VALUE h);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* hash.c (export) */
+VALUE rb_hash_delete_entry(VALUE hash, VALUE key);
+VALUE rb_ident_hash_new(void);
+int rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg);
+RUBY_SYMBOL_EXPORT_END
+
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE rb_hash_new_with_size(st_index_t size);
+VALUE rb_hash_resurrect(VALUE hash);
+int rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval);
+VALUE rb_hash_keys(VALUE hash);
+VALUE rb_hash_has_key(VALUE hash, VALUE key);
+VALUE rb_hash_compare_by_id_p(VALUE hash);
+
+st_table *rb_hash_tbl_raw(VALUE hash, const char *file, int line);
+#define RHASH_TBL_RAW(h) rb_hash_tbl_raw(h, __FILE__, __LINE__)
+MJIT_SYMBOL_EXPORT_END
+
+#if 0 /* for debug */
+
+static inline bool
+RHASH_AR_TABLE_P(VALUE h)
+{
+ extern int rb_hash_ar_table_p(VALUE hash);
+ return rb_hash_ar_table_p(h)
+}
+
+static inline struct ar_table_struct *
+RHASH_AR_TABLE(VALUE h)
+{
+ extern struct ar_table_struct *rb_hash_ar_table(VALUE hash);
+ return rb_hash_ar_table(h)
+}
+
+static inline st_table *
+RHASH_ST_TABLE(VALUE h)
+{
+ return rb_hash_st_table(h)
+}
+
+#else
+
+static inline bool
+RHASH_AR_TABLE_P(VALUE h)
+{
+ return ! FL_TEST_RAW(h, RHASH_ST_TABLE_FLAG);
+}
+
+static inline struct ar_table_struct *
+RHASH_AR_TABLE(VALUE h)
+{
+ return RHASH(h)->as.ar;
+}
+
+static inline st_table *
+RHASH_ST_TABLE(VALUE h)
+{
+ return RHASH(h)->as.st;
+}
+
+#endif
+
+static inline VALUE
+RHASH_IFNONE(VALUE h)
+{
+ return RHASH(h)->ifnone;
+}
+
+static inline size_t
+RHASH_SIZE(VALUE h)
+{
+ if (RHASH_AR_TABLE_P(h)) {
+ return RHASH_AR_TABLE_SIZE_RAW(h);
+ }
+ else {
+ return RHASH_ST_SIZE(h);
+ }
+}
+
+static inline bool
+RHASH_EMPTY_P(VALUE h)
+{
+ return RHASH_SIZE(h) == 0;
+}
+
+static inline bool
+RHASH_ST_TABLE_P(VALUE h)
+{
+ return ! RHASH_AR_TABLE_P(h);
+}
+
+static inline size_t
+RHASH_ST_SIZE(VALUE h)
+{
+ return RHASH_ST_TABLE(h)->num_entries;
+}
+
+static inline void
+RHASH_ST_CLEAR(VALUE h)
+{
+ FL_UNSET_RAW(h, RHASH_ST_TABLE_FLAG);
+ RHASH(h)->as.ar = NULL;
+}
+
+static inline unsigned
+RHASH_AR_TABLE_SIZE_RAW(VALUE h)
+{
+ VALUE ret = FL_TEST_RAW(h, RHASH_AR_TABLE_SIZE_MASK);
+ ret >>= RHASH_AR_TABLE_SIZE_SHIFT;
+ return (unsigned)ret;
+}
+
+static inline bool
+RHASH_TRANSIENT_P(VALUE h)
+{
+#if USE_TRANSIENT_HEAP
+ return FL_TEST_RAW(h, RHASH_TRANSIENT_FLAG);
+#else
+ return false;
+#endif
+}
+
+static inline void
+RHASH_SET_TRANSIENT_FLAG(VALUE h)
+{
+#if USE_TRANSIENT_HEAP
+ FL_SET_RAW(h, RHASH_TRANSIENT_FLAG);
+#endif
+}
+
+static inline void
+RHASH_UNSET_TRANSIENT_FLAG(VALUE h)
+{
+#if USE_TRANSIENT_HEAP
+ FL_UNSET_RAW(h, RHASH_TRANSIENT_FLAG);
+#endif
+}
+
+#endif /* INTERNAL_HASH_H */
diff --git a/internal/imemo.h b/internal/imemo.h
new file mode 100644
index 0000000000..a9e2136ac4
--- /dev/null
+++ b/internal/imemo.h
@@ -0,0 +1,244 @@
+#ifndef INTERNAL_IMEMO_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_IMEMO_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.
+ * @brief IMEMO: Internal memo object.
+ */
+#include "ruby/internal/config.h"
+#include <stddef.h> /* for size_t */
+#include "internal/array.h" /* for rb_ary_tmp_new_fill */
+#include "internal/gc.h" /* for RB_OBJ_WRITE */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/ruby.h" /* for rb_block_call_func_t */
+
+#ifndef IMEMO_DEBUG
+# define IMEMO_DEBUG 0
+#endif
+
+#define IMEMO_MASK 0x0f
+
+/* FL_USER0 to FL_USER3 is for type */
+#define IMEMO_FL_USHIFT (FL_USHIFT + 4)
+#define IMEMO_FL_USER0 FL_USER4
+#define IMEMO_FL_USER1 FL_USER5
+#define IMEMO_FL_USER2 FL_USER6
+#define IMEMO_FL_USER3 FL_USER7
+#define IMEMO_FL_USER4 FL_USER8
+#define IMEMO_FL_USER5 FL_USER9
+
+enum imemo_type {
+ imemo_env = 0,
+ imemo_cref = 1, /*!< class reference */
+ imemo_svar = 2, /*!< special variable */
+ imemo_throw_data = 3,
+ imemo_ifunc = 4, /*!< iterator function */
+ imemo_memo = 5,
+ imemo_ment = 6,
+ imemo_iseq = 7,
+ imemo_tmpbuf = 8,
+ imemo_ast = 9,
+ imemo_parser_strterm = 10,
+ imemo_callinfo = 11,
+ imemo_callcache = 12,
+ imemo_constcache = 13,
+};
+
+/* CREF (Class REFerence) is defined in method.h */
+
+/*! SVAR (Special VARiable) */
+struct vm_svar {
+ VALUE flags;
+ const VALUE cref_or_me; /*!< class reference or rb_method_entry_t */
+ const VALUE lastline;
+ const VALUE backref;
+ const VALUE others;
+};
+
+/*! THROW_DATA */
+struct vm_throw_data {
+ VALUE flags;
+ VALUE reserved;
+ const VALUE throw_obj;
+ const struct rb_control_frame_struct *catch_frame;
+ int throw_state;
+};
+
+#define THROW_DATA_CONSUMED IMEMO_FL_USER0
+
+/* IFUNC (Internal FUNCtion) */
+
+struct vm_ifunc_argc {
+#if SIZEOF_INT * 2 > SIZEOF_VALUE
+ signed int min: (SIZEOF_VALUE * CHAR_BIT) / 2;
+ signed int max: (SIZEOF_VALUE * CHAR_BIT) / 2;
+#else
+ int min, max;
+#endif
+};
+
+/*! IFUNC (Internal FUNCtion) */
+struct vm_ifunc {
+ VALUE flags;
+ VALUE reserved;
+ rb_block_call_func_t func;
+ const void *data;
+ struct vm_ifunc_argc argc;
+};
+
+struct rb_imemo_tmpbuf_struct {
+ VALUE flags;
+ VALUE reserved;
+ VALUE *ptr; /* malloc'ed buffer */
+ struct rb_imemo_tmpbuf_struct *next; /* next imemo */
+ size_t cnt; /* buffer size in VALUE */
+};
+
+/*! MEMO
+ *
+ * @see imemo_type
+ * */
+struct MEMO {
+ VALUE flags;
+ VALUE reserved;
+ const VALUE v1;
+ const VALUE v2;
+ union {
+ long cnt;
+ long state;
+ const VALUE value;
+ void (*func)(void);
+ } u3;
+};
+
+/* ment is in method.h */
+
+#define THROW_DATA_P(err) imemo_throw_data_p((VALUE)err)
+#define MEMO_CAST(m) ((struct MEMO *)(m))
+#define MEMO_NEW(a, b, c) ((struct MEMO *)rb_imemo_new(imemo_memo, (VALUE)(a), (VALUE)(b), (VALUE)(c), 0))
+#define MEMO_FOR(type, value) ((type *)RARRAY_PTR(value))
+#define NEW_MEMO_FOR(type, value) \
+ ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), MEMO_FOR(type, value))
+#define NEW_PARTIAL_MEMO_FOR(type, value, member) \
+ ((value) = rb_ary_tmp_new_fill(type_roomof(type, VALUE)), \
+ rb_ary_set_len((value), offsetof(type, member) / sizeof(VALUE)), \
+ MEMO_FOR(type, value))
+
+typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
+VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
+rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
+struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
+void rb_strterm_mark(VALUE obj);
+static inline enum imemo_type imemo_type(VALUE imemo);
+static inline int imemo_type_p(VALUE imemo, enum imemo_type imemo_type);
+static inline bool imemo_throw_data_p(VALUE imemo);
+static inline struct vm_ifunc *rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data);
+static inline VALUE rb_imemo_tmpbuf_auto_free_pointer(void);
+static inline void *RB_IMEMO_TMPBUF_PTR(VALUE v);
+static inline void *rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr);
+static inline VALUE rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str);
+static inline void MEMO_V1_SET(struct MEMO *m, VALUE v);
+static inline void MEMO_V2_SET(struct MEMO *m, VALUE v);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+#if IMEMO_DEBUG
+VALUE rb_imemo_new_debug(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0, const char *file, int line);
+#define rb_imemo_new(type, v1, v2, v3, v0) rb_imemo_new_debug(type, v1, v2, v3, v0, __FILE__, __LINE__)
+#else
+VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
+#endif
+const char *rb_imemo_name(enum imemo_type type);
+RUBY_SYMBOL_EXPORT_END
+
+static inline enum imemo_type
+imemo_type(VALUE imemo)
+{
+ return (RBASIC(imemo)->flags >> FL_USHIFT) & IMEMO_MASK;
+}
+
+static inline int
+imemo_type_p(VALUE imemo, enum imemo_type imemo_type)
+{
+ if (LIKELY(!RB_SPECIAL_CONST_P(imemo))) {
+ /* fixed at compile time if imemo_type is given. */
+ const VALUE mask = (IMEMO_MASK << FL_USHIFT) | RUBY_T_MASK;
+ const VALUE expected_type = (imemo_type << FL_USHIFT) | T_IMEMO;
+ /* fixed at runtime. */
+ return expected_type == (RBASIC(imemo)->flags & mask);
+ }
+ else {
+ return 0;
+ }
+}
+
+#define IMEMO_TYPE_P(v, t) imemo_type_p((VALUE)v, t)
+
+static inline bool
+imemo_throw_data_p(VALUE imemo)
+{
+ return RB_TYPE_P(imemo, T_IMEMO);
+}
+
+static inline struct vm_ifunc *
+rb_vm_ifunc_proc_new(rb_block_call_func_t func, const void *data)
+{
+ return rb_vm_ifunc_new(func, data, 0, UNLIMITED_ARGUMENTS);
+}
+
+static inline VALUE
+rb_imemo_tmpbuf_auto_free_pointer(void)
+{
+ return rb_imemo_new(imemo_tmpbuf, 0, 0, 0, 0);
+}
+
+static inline void *
+RB_IMEMO_TMPBUF_PTR(VALUE v)
+{
+ const struct rb_imemo_tmpbuf_struct *p = (const void *)v;
+ return p->ptr;
+}
+
+static inline void *
+rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr)
+{
+ return ((rb_imemo_tmpbuf_t *)v)->ptr = ptr;
+}
+
+static inline VALUE
+rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str)
+{
+ const void *src;
+ VALUE imemo;
+ rb_imemo_tmpbuf_t *tmpbuf;
+ void *dst;
+ size_t len;
+
+ SafeStringValue(str);
+ /* create tmpbuf to keep the pointer before xmalloc */
+ imemo = rb_imemo_tmpbuf_auto_free_pointer();
+ tmpbuf = (rb_imemo_tmpbuf_t *)imemo;
+ len = RSTRING_LEN(str);
+ src = RSTRING_PTR(str);
+ dst = ruby_xmalloc(len);
+ memcpy(dst, src, len);
+ tmpbuf->ptr = dst;
+ return imemo;
+}
+
+static inline void
+MEMO_V1_SET(struct MEMO *m, VALUE v)
+{
+ RB_OBJ_WRITE(m, &m->v1, v);
+}
+
+static inline void
+MEMO_V2_SET(struct MEMO *m, VALUE v)
+{
+ RB_OBJ_WRITE(m, &m->v2, v);
+}
+
+#endif /* INTERNAL_IMEMO_H */
diff --git a/internal/inits.h b/internal/inits.h
new file mode 100644
index 0000000000..680c9cc1a5
--- /dev/null
+++ b/internal/inits.h
@@ -0,0 +1,51 @@
+#ifndef INTERNAL_INITS_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_INITS_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.
+ * @brief Internal header aggregating init functions.
+ */
+
+/* class.c */
+void Init_class_hierarchy(void);
+
+/* dmyext.c */
+void Init_enc(void);
+void Init_ext(void);
+
+/* file.c */
+void Init_File(void);
+
+/* gc.c */
+void Init_heap(void);
+
+/* localeinit.c */
+int Init_enc_set_filesystem_encoding(void);
+
+/* newline.c */
+void Init_newline(void);
+
+/* vm.c */
+void Init_BareVM(void);
+void Init_vm_objects(void);
+
+/* vm_backtrace.c */
+void Init_vm_backtrace(void);
+
+/* vm_eval.c */
+void Init_vm_eval(void);
+
+/* vm_insnhelper.c */
+void Init_vm_stack_canary(void);
+
+/* vm_method.c */
+void Init_eval_method(void);
+
+/* inits.c */
+void rb_call_inits(void);
+
+#endif /* INTERNAL_INITS_H */
diff --git a/internal/io.h b/internal/io.h
new file mode 100644
index 0000000000..b184cec439
--- /dev/null
+++ b/internal/io.h
@@ -0,0 +1,35 @@
+#ifndef INTERNAL_IO_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_IO_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.
+ * @brief Internal header for IO.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+#include "ruby/io.h" /* for rb_io_t */
+
+/* io.c */
+void ruby_set_inplace_mode(const char *);
+void rb_stdio_set_default_encoding(void);
+VALUE rb_io_flush_raw(VALUE, int);
+size_t rb_io_memsize(const rb_io_t *);
+int rb_stderr_tty_p(void);
+void rb_io_fptr_finalize_internal(void *ptr);
+#ifdef rb_io_fptr_finalize
+# undef rb_io_fptr_finalize
+#endif
+#define rb_io_fptr_finalize rb_io_fptr_finalize_internal
+VALUE rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* io.c (export) */
+void rb_maygvl_fd_fix_cloexec(int fd);
+int rb_gc_for_fd(int err);
+void rb_write_error_str(VALUE mesg);
+RUBY_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_IO_H */
diff --git a/internal/load.h b/internal/load.h
new file mode 100644
index 0000000000..37c1dee351
--- /dev/null
+++ b/internal/load.h
@@ -0,0 +1,19 @@
+#ifndef INTERNAL_LOAD_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_LOAD_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.
+ * @brief Internal header for require.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+
+/* load.c */
+VALUE rb_get_expanded_load_path(void);
+int rb_require_internal(VALUE fname);
+NORETURN(void rb_load_fail(VALUE, const char*));
+
+#endif /* INTERNAL_LOAD_H */
diff --git a/internal/loadpath.h b/internal/loadpath.h
new file mode 100644
index 0000000000..f89f6694cd
--- /dev/null
+++ b/internal/loadpath.h
@@ -0,0 +1,17 @@
+#ifndef INTERNAL_LOADPATH_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_LOADPATH_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.
+ * @brief Internal header for $LOAD_PATH.
+ */
+
+/* loadpath.c */
+extern const char ruby_exec_prefix[];
+extern const char ruby_initial_load_paths[];
+
+#endif /* INTERNAL_LOADPATH_H */
diff --git a/internal/math.h b/internal/math.h
new file mode 100644
index 0000000000..cd8d553790
--- /dev/null
+++ b/internal/math.h
@@ -0,0 +1,24 @@
+#ifndef INTERNAL_MATH_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_MATH_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.
+ * @brief Internal header for Math.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+
+/* math.c */
+VALUE rb_math_atan2(VALUE, VALUE);
+VALUE rb_math_cos(VALUE);
+VALUE rb_math_cosh(VALUE);
+VALUE rb_math_exp(VALUE);
+VALUE rb_math_hypot(VALUE, VALUE);
+VALUE rb_math_log(int argc, const VALUE *argv);
+VALUE rb_math_sin(VALUE);
+VALUE rb_math_sinh(VALUE);
+
+#endif /* INTERNAL_MATH_H */
diff --git a/internal/missing.h b/internal/missing.h
new file mode 100644
index 0000000000..0224075b3d
--- /dev/null
+++ b/internal/missing.h
@@ -0,0 +1,19 @@
+#ifndef INTERNAL_MISSING_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_MISSING_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.
+ * @brief Internal header corresponding missing.
+ */
+#include "ruby/internal/config.h" /* for HAVE_SETPROCTITLE */
+
+/* missing/setproctitle.c */
+#ifndef HAVE_SETPROCTITLE
+extern void ruby_init_setproctitle(int argc, char *argv[]);
+#endif
+
+#endif /* INTERNAL_MISSING_H */
diff --git a/internal/numeric.h b/internal/numeric.h
new file mode 100644
index 0000000000..32d5bd27fa
--- /dev/null
+++ b/internal/numeric.h
@@ -0,0 +1,255 @@
+#ifndef INTERNAL_NUMERIC_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_NUMERIC_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.
+ * @brief Internal header for Numeric.
+ */
+#include "internal/bignum.h" /* for BIGNUM_POSITIVE_P */
+#include "internal/bits.h" /* for RUBY_BIT_ROTL */
+#include "internal/fixnum.h" /* for FIXNUM_POSITIVE_P */
+#include "internal/vm.h" /* for rb_method_basic_definition_p */
+#include "ruby/intern.h" /* for rb_cmperr */
+#include "ruby/ruby.h" /* for USE_FLONUM */
+
+#define ROUND_TO(mode, even, up, down) \
+ ((mode) == RUBY_NUM_ROUND_HALF_EVEN ? even : \
+ (mode) == RUBY_NUM_ROUND_HALF_UP ? up : down)
+#define ROUND_FUNC(mode, name) \
+ ROUND_TO(mode, name##_half_even, name##_half_up, name##_half_down)
+#define ROUND_CALL(mode, name, args) \
+ ROUND_TO(mode, name##_half_even args, \
+ name##_half_up args, name##_half_down args)
+
+#ifndef ROUND_DEFAULT
+# define ROUND_DEFAULT RUBY_NUM_ROUND_HALF_UP
+#endif
+
+enum ruby_num_rounding_mode {
+ RUBY_NUM_ROUND_HALF_UP,
+ RUBY_NUM_ROUND_HALF_EVEN,
+ RUBY_NUM_ROUND_HALF_DOWN,
+ RUBY_NUM_ROUND_DEFAULT = ROUND_DEFAULT,
+};
+
+struct RFloat {
+ struct RBasic basic;
+ double float_value;
+};
+
+#define RFLOAT(obj) ((struct RFloat *)(obj))
+
+/* numeric.c */
+int rb_num_to_uint(VALUE val, unsigned int *ret);
+VALUE ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl);
+double ruby_float_step_size(double beg, double end, double unit, int excl);
+int ruby_float_step(VALUE from, VALUE to, VALUE step, int excl, int allow_endless);
+int rb_num_negative_p(VALUE);
+VALUE rb_int_succ(VALUE num);
+VALUE rb_float_uminus(VALUE num);
+VALUE rb_int_plus(VALUE x, VALUE y);
+VALUE rb_float_plus(VALUE x, VALUE y);
+VALUE rb_int_minus(VALUE x, VALUE y);
+VALUE rb_float_minus(VALUE x, VALUE y);
+VALUE rb_int_mul(VALUE x, VALUE y);
+VALUE rb_float_mul(VALUE x, VALUE y);
+VALUE rb_float_div(VALUE x, VALUE y);
+VALUE rb_int_idiv(VALUE x, VALUE y);
+VALUE rb_int_modulo(VALUE x, VALUE y);
+VALUE rb_int2str(VALUE num, int base);
+VALUE rb_fix_plus(VALUE x, VALUE y);
+VALUE rb_int_gt(VALUE x, VALUE y);
+VALUE rb_float_gt(VALUE x, VALUE y);
+VALUE rb_int_ge(VALUE x, VALUE y);
+enum ruby_num_rounding_mode rb_num_get_rounding_option(VALUE opts);
+double rb_int_fdiv_double(VALUE x, VALUE y);
+VALUE rb_int_pow(VALUE x, VALUE y);
+VALUE rb_float_pow(VALUE x, VALUE y);
+VALUE rb_int_cmp(VALUE x, VALUE y);
+VALUE rb_int_equal(VALUE x, VALUE y);
+VALUE rb_int_divmod(VALUE x, VALUE y);
+VALUE rb_int_and(VALUE x, VALUE y);
+VALUE rb_int_lshift(VALUE x, VALUE y);
+VALUE rb_int_div(VALUE x, VALUE y);
+int rb_int_positive_p(VALUE num);
+int rb_int_negative_p(VALUE num);
+VALUE rb_num_pow(VALUE x, VALUE y);
+VALUE rb_float_ceil(VALUE num, int ndigits);
+VALUE rb_float_floor(VALUE x, int ndigits);
+VALUE rb_float_abs(VALUE flt);
+static inline VALUE rb_num_compare_with_zero(VALUE num, ID mid);
+static inline int rb_num_positive_int_p(VALUE num);
+static inline int rb_num_negative_int_p(VALUE num);
+static inline double rb_float_flonum_value(VALUE v);
+static inline double rb_float_noflonum_value(VALUE v);
+static inline double rb_float_value_inline(VALUE v);
+static inline VALUE rb_float_new_inline(double d);
+static inline bool INT_POSITIVE_P(VALUE num);
+static inline bool INT_NEGATIVE_P(VALUE num);
+static inline bool FLOAT_ZERO_P(VALUE num);
+#define rb_float_value rb_float_value_inline
+#define rb_float_new rb_float_new_inline
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* numeric.c (export) */
+VALUE rb_int_positive_pow(long x, unsigned long y);
+RUBY_SYMBOL_EXPORT_END
+
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE rb_flo_div_flo(VALUE x, VALUE y);
+double ruby_float_mod(double x, double y);
+VALUE rb_float_equal(VALUE x, VALUE y);
+int rb_float_cmp(VALUE x, VALUE y);
+VALUE rb_float_eql(VALUE x, VALUE y);
+VALUE rb_fix_aref(VALUE fix, VALUE idx);
+VALUE rb_int_zero_p(VALUE num);
+VALUE rb_int_even_p(VALUE num);
+VALUE rb_int_odd_p(VALUE num);
+VALUE rb_int_abs(VALUE num);
+VALUE rb_int_bit_length(VALUE num);
+VALUE rb_int_uminus(VALUE num);
+VALUE rb_int_comp(VALUE num);
+MJIT_SYMBOL_EXPORT_END
+
+static inline bool
+INT_POSITIVE_P(VALUE num)
+{
+ if (FIXNUM_P(num)) {
+ return FIXNUM_POSITIVE_P(num);
+ }
+ else {
+ return BIGNUM_POSITIVE_P(num);
+ }
+}
+
+static inline bool
+INT_NEGATIVE_P(VALUE num)
+{
+ if (FIXNUM_P(num)) {
+ return FIXNUM_NEGATIVE_P(num);
+ }
+ else {
+ return BIGNUM_NEGATIVE_P(num);
+ }
+}
+
+static inline bool
+FLOAT_ZERO_P(VALUE num)
+{
+ return RFLOAT_VALUE(num) == 0.0;
+}
+
+static inline VALUE
+rb_num_compare_with_zero(VALUE num, ID mid)
+{
+ VALUE zero = INT2FIX(0);
+ VALUE r = rb_check_funcall(num, mid, 1, &zero);
+ if (r == Qundef) {
+ rb_cmperr(num, zero);
+ }
+ return r;
+}
+
+static inline int
+rb_num_positive_int_p(VALUE num)
+{
+ const ID mid = '>';
+
+ if (FIXNUM_P(num)) {
+ if (rb_method_basic_definition_p(rb_cInteger, mid))
+ return FIXNUM_POSITIVE_P(num);
+ }
+ else if (RB_TYPE_P(num, T_BIGNUM)) {
+ if (rb_method_basic_definition_p(rb_cInteger, mid))
+ return BIGNUM_POSITIVE_P(num);
+ }
+ return RTEST(rb_num_compare_with_zero(num, mid));
+}
+
+static inline int
+rb_num_negative_int_p(VALUE num)
+{
+ const ID mid = '<';
+
+ if (FIXNUM_P(num)) {
+ if (rb_method_basic_definition_p(rb_cInteger, mid))
+ return FIXNUM_NEGATIVE_P(num);
+ }
+ else if (RB_TYPE_P(num, T_BIGNUM)) {
+ if (rb_method_basic_definition_p(rb_cInteger, mid))
+ return BIGNUM_NEGATIVE_P(num);
+ }
+ return RTEST(rb_num_compare_with_zero(num, mid));
+}
+
+static inline double
+rb_float_flonum_value(VALUE v)
+{
+#if USE_FLONUM
+ if (v != (VALUE)0x8000000000000002) { /* LIKELY */
+ union {
+ double d;
+ VALUE v;
+ } t;
+
+ VALUE b63 = (v >> 63);
+ /* e: xx1... -> 011... */
+ /* xx0... -> 100... */
+ /* ^b63 */
+ t.v = RUBY_BIT_ROTR((2 - b63) | (v & ~(VALUE)0x03), 3);
+ return t.d;
+ }
+#endif
+ return 0.0;
+}
+
+static inline double
+rb_float_noflonum_value(VALUE v)
+{
+ return RFLOAT(v)->float_value;
+}
+
+static inline double
+rb_float_value_inline(VALUE v)
+{
+ if (FLONUM_P(v)) {
+ return rb_float_flonum_value(v);
+ }
+ return rb_float_noflonum_value(v);
+}
+
+static inline VALUE
+rb_float_new_inline(double d)
+{
+#if USE_FLONUM
+ union {
+ double d;
+ VALUE v;
+ } t;
+ int bits;
+
+ t.d = d;
+ bits = (int)((VALUE)(t.v >> 60) & 0x7);
+ /* bits contains 3 bits of b62..b60. */
+ /* bits - 3 = */
+ /* b011 -> b000 */
+ /* b100 -> b001 */
+
+ if (t.v != 0x3000000000000000 /* 1.72723e-77 */ &&
+ !((bits-3) & ~0x01)) {
+ return (RUBY_BIT_ROTL(t.v, 3) & ~(VALUE)0x01) | 0x02;
+ }
+ else if (t.v == (VALUE)0) {
+ /* +0.0 */
+ return 0x8000000000000002;
+ }
+ /* out of range */
+#endif
+ return rb_float_new_in_heap(d);
+}
+
+#endif /* INTERNAL_NUMERIC_H */
diff --git a/internal/object.h b/internal/object.h
new file mode 100644
index 0000000000..aa820128c7
--- /dev/null
+++ b/internal/object.h
@@ -0,0 +1,83 @@
+#ifndef INTERNAL_OBJECT_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_OBJECT_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.
+ * @brief Internal header for Object.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+#include "internal/class.h" /* for RCLASS_IV_INDEX_TBL */
+
+#ifdef ROBJECT_IV_INDEX_TBL
+# undef ROBJECT_IV_INDEX_TBL
+#endif
+
+/* object.c */
+VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
+NORETURN(void rb_undefined_alloc(VALUE klass));
+double rb_num_to_dbl(VALUE val);
+VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound);
+VALUE rb_immutable_obj_clone(int, VALUE *, VALUE);
+VALUE rb_check_convert_type_with_id(VALUE,int,const char*,ID);
+int rb_bool_expected(VALUE, const char *);
+static inline void RBASIC_CLEAR_CLASS(VALUE obj);
+static inline void RBASIC_SET_CLASS_RAW(VALUE obj, VALUE klass);
+static inline void RBASIC_SET_CLASS(VALUE obj, VALUE klass);
+static inline struct st_table *ROBJECT_IV_INDEX_TBL_inline(VALUE obj);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* object.c (export) */
+int rb_opts_exception_p(VALUE opts, int default_value);
+RUBY_SYMBOL_EXPORT_END
+
+MJIT_SYMBOL_EXPORT_BEGIN
+CONSTFUNC(VALUE rb_obj_equal(VALUE obj1, VALUE obj2));
+CONSTFUNC(VALUE rb_obj_not(VALUE obj));
+VALUE rb_obj_not_equal(VALUE obj1, VALUE obj2);
+void rb_obj_copy_ivar(VALUE dest, VALUE obj);
+VALUE rb_false(VALUE obj);
+VALUE rb_convert_type_with_id(VALUE v, int t, const char* nam, ID mid);
+VALUE rb_obj_size(VALUE self, VALUE args, VALUE obj);
+MJIT_SYMBOL_EXPORT_END
+
+static inline void
+RBASIC_SET_CLASS_RAW(VALUE obj, VALUE klass)
+{
+ struct { VALUE flags; VALUE klass; } *ptr = (void *)obj;
+ ptr->klass = klass;
+}
+
+static inline void
+RBASIC_CLEAR_CLASS(VALUE obj)
+{
+ RBASIC_SET_CLASS_RAW(obj, 0);
+}
+
+static inline void
+RBASIC_SET_CLASS(VALUE obj, VALUE klass)
+{
+ VALUE oldv = RBASIC_CLASS(obj);
+ RBASIC_SET_CLASS_RAW(obj, klass);
+ RB_OBJ_WRITTEN(obj, oldv, klass);
+}
+
+RBIMPL_ATTR_PURE()
+static inline struct st_table *
+ROBJECT_IV_INDEX_TBL_inline(VALUE obj)
+{
+ if (RB_FL_ANY_RAW(obj, ROBJECT_EMBED)) {
+ VALUE klass = rb_obj_class(obj);
+ return RCLASS_IV_INDEX_TBL(klass);
+ }
+ else {
+ const struct RObject *const ptr = ROBJECT(obj);
+ return ptr->as.heap.iv_index_tbl;
+ }
+}
+#define ROBJECT_IV_INDEX_TBL ROBJECT_IV_INDEX_TBL_inline
+
+#endif /* INTERNAL_OBJECT_H */
diff --git a/internal/parse.h b/internal/parse.h
new file mode 100644
index 0000000000..a37a39f84d
--- /dev/null
+++ b/internal/parse.h
@@ -0,0 +1,23 @@
+#ifndef INTERNAL_PARSE_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_PARSE_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.
+ * @brief Internal header for the parser.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+struct rb_iseq_struct; /* in vm_core.h */
+
+/* parse.y */
+VALUE rb_parser_set_yydebug(VALUE, VALUE);
+void *rb_parser_load_file(VALUE parser, VALUE name);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+VALUE rb_parser_set_context(VALUE, const struct rb_iseq_struct *, int);
+RUBY_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_PARSE_H */
diff --git a/internal/proc.h b/internal/proc.h
new file mode 100644
index 0000000000..5628a1f1c7
--- /dev/null
+++ b/internal/proc.h
@@ -0,0 +1,33 @@
+#ifndef INTERNAL_PROC_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_PROC_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.
+ * @brief Internal header for Proc.
+ */
+#include "ruby/ruby.h" /* for rb_block_call_func_t */
+#include "ruby/st.h" /* for st_index_t */
+struct rb_block; /* in vm_core.h */
+struct rb_iseq_struct; /* in vm_core.h */
+
+/* proc.c */
+VALUE rb_proc_location(VALUE self);
+st_index_t rb_hash_proc(st_index_t hash, VALUE proc);
+int rb_block_pair_yield_optimizable(void);
+int rb_block_arity(void);
+int rb_block_min_max_arity(int *max);
+VALUE rb_block_to_s(VALUE self, const struct rb_block *block, const char *additional_info);
+VALUE rb_callable_receiver(VALUE);
+
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val);
+VALUE rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc);
+VALUE rb_iseq_location(const struct rb_iseq_struct *iseq);
+VALUE rb_sym_to_proc(VALUE sym);
+MJIT_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_PROC_H */
diff --git a/internal/process.h b/internal/process.h
new file mode 100644
index 0000000000..904c9a5cea
--- /dev/null
+++ b/internal/process.h
@@ -0,0 +1,136 @@
+#ifndef INTERNAL_PROCESS_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_PROCESS_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.
+ * @brief Internal header for Process.
+ */
+#include "ruby/internal/config.h" /* for rb_pid_t */
+#include <stddef.h> /* for size_t */
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h> /* for mode_t */
+#endif
+
+#ifdef _WIN32
+# include "ruby/win32.h" /* for mode_t */
+#endif
+
+#include "ruby/ruby.h" /* for VALUE */
+#include "internal/imemo.h" /* for RB_IMEMO_TMPBUF_PTR */
+#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */
+
+#define RB_MAX_GROUPS (65536)
+
+struct waitpid_state;
+struct rb_execarg {
+ union {
+ struct {
+ VALUE shell_script;
+ } sh;
+ struct {
+ VALUE command_name;
+ VALUE command_abspath; /* full path string or nil */
+ VALUE argv_str;
+ VALUE argv_buf;
+ } cmd;
+ } invoke;
+ VALUE redirect_fds;
+ VALUE envp_str;
+ VALUE envp_buf;
+ VALUE dup2_tmpbuf;
+ unsigned use_shell : 1;
+ unsigned pgroup_given : 1;
+ unsigned umask_given : 1;
+ unsigned unsetenv_others_given : 1;
+ unsigned unsetenv_others_do : 1;
+ unsigned close_others_given : 1;
+ unsigned close_others_do : 1;
+ unsigned chdir_given : 1;
+ unsigned new_pgroup_given : 1;
+ unsigned new_pgroup_flag : 1;
+ unsigned uid_given : 1;
+ unsigned gid_given : 1;
+ unsigned exception : 1;
+ unsigned exception_given : 1;
+ struct waitpid_state *waitpid_state; /* for async process management */
+ rb_pid_t pgroup_pgid; /* asis(-1), new pgroup(0), specified pgroup (0<V). */
+ VALUE rlimit_limits; /* Qfalse or [[rtype, softlim, hardlim], ...] */
+ mode_t umask_mask;
+ rb_uid_t uid;
+ rb_gid_t gid;
+ int close_others_maxhint;
+ VALUE fd_dup2;
+ VALUE fd_close;
+ VALUE fd_open;
+ VALUE fd_dup2_child;
+ VALUE env_modification; /* Qfalse or [[k1,v1], ...] */
+ VALUE path_env;
+ VALUE chdir_dir;
+};
+
+/* process.c */
+rb_pid_t rb_fork_ruby(int *status);
+void rb_last_status_clear(void);
+static inline char **ARGVSTR2ARGV(VALUE argv_str);
+static inline size_t ARGVSTR2ARGC(VALUE argv_str);
+
+#ifdef HAVE_PWD_H
+VALUE rb_getlogin(void);
+VALUE rb_getpwdirnam_for_login(VALUE login); /* read as: "get pwd db home dir by username for login" */
+VALUE rb_getpwdiruid(void); /* read as: "get pwd db home dir for getuid()" */
+#endif
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* process.c (export) */
+int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen);
+rb_pid_t rb_fork_async_signal_safe(int *status, int (*chfunc)(void*, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen);
+VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt);
+struct rb_execarg *rb_execarg_get(VALUE execarg_obj); /* dangerous. needs GC guard. */
+int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val);
+void rb_execarg_parent_start(VALUE execarg_obj);
+void rb_execarg_parent_end(VALUE execarg_obj);
+int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char* errmsg, size_t errmsg_buflen);
+VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash);
+void rb_execarg_setenv(VALUE execarg_obj, VALUE env);
+RUBY_SYMBOL_EXPORT_END
+
+/* argv_str contains extra two elements.
+ * The beginning one is for /bin/sh used by exec_with_sh.
+ * The last one for terminating NULL used by execve.
+ * See rb_exec_fillarg() in process.c. */
+static inline char **
+ARGVSTR2ARGV(VALUE argv_str)
+{
+ char **buf = RB_IMEMO_TMPBUF_PTR(argv_str);
+ return &buf[1];
+}
+
+static inline size_t
+ARGVSTR2ARGC(VALUE argv_str)
+{
+ size_t i = 0;
+ char *const *p = ARGVSTR2ARGV(argv_str);
+ while (p[i++])
+ ;
+ return i - 1;
+}
+
+#ifdef HAVE_WORKING_FORK
+COMPILER_WARNING_PUSH
+#if __has_warning("-Wdeprecated-declarations") || RBIMPL_COMPILER_IS(GCC)
+COMPILER_WARNING_IGNORED(-Wdeprecated-declarations)
+#endif
+static inline rb_pid_t
+rb_fork(void)
+{
+ return fork();
+}
+COMPILER_WARNING_POP
+#endif
+
+#endif /* INTERNAL_PROCESS_H */
diff --git a/internal/random.h b/internal/random.h
new file mode 100644
index 0000000000..a92e65b8ba
--- /dev/null
+++ b/internal/random.h
@@ -0,0 +1,17 @@
+#ifndef INTERNAL_RANDOM_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_RANDOM_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.
+ * @brief Internal header for Random.
+ */
+#include <stddef.h> /* for size_t */
+
+/* random.c */
+int ruby_fill_random_bytes(void *, size_t, int);
+
+#endif /* INTERNAL_RANDOM_H */
diff --git a/internal/range.h b/internal/range.h
new file mode 100644
index 0000000000..4fe6037c89
--- /dev/null
+++ b/internal/range.h
@@ -0,0 +1,41 @@
+#ifndef INTERNAL_RANGE_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_RANGE_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.
+ * @brief Internal header for Range.
+ */
+#include "internal/struct.h" /* for RSTRUCT */
+
+/* range.c */
+static inline VALUE RANGE_BEG(VALUE r);
+static inline VALUE RANGE_END(VALUE r);
+static inline VALUE RANGE_EXCL(VALUE r);
+
+static inline VALUE
+RANGE_BEG(VALUE r)
+{
+ return RSTRUCT(r)->as.ary[0];
+}
+
+static inline VALUE
+RANGE_END(VALUE r)
+{
+ return RSTRUCT(r)->as.ary[1];
+}
+
+static inline VALUE
+RANGE_EXCL(VALUE r)
+{
+ return RSTRUCT(r)->as.ary[2];
+}
+
+VALUE
+rb_range_component_beg_len(VALUE b, VALUE e, int excl,
+ long *begp, long *lenp, long len, int err);
+
+#endif /* INTERNAL_RANGE_H */
diff --git a/internal/rational.h b/internal/rational.h
new file mode 100644
index 0000000000..6bbd2a9810
--- /dev/null
+++ b/internal/rational.h
@@ -0,0 +1,72 @@
+#ifndef INTERNAL_RATIONAL_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_RATIONAL_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.
+ * @brief Internal header for Rational.
+ */
+#include "ruby/internal/config.h" /* for HAVE_LIBGMP */
+#include "ruby/ruby.h" /* for struct RBasic */
+#include "internal/gc.h" /* for RB_OBJ_WRITE */
+#include "internal/numeric.h" /* for INT_POSITIVE_P */
+#include "ruby_assert.h" /* for assert */
+
+struct RRational {
+ struct RBasic basic;
+ VALUE num;
+ VALUE den;
+};
+
+#define RRATIONAL(obj) ((struct RRational *)(obj))
+
+/* rational.c */
+VALUE rb_rational_canonicalize(VALUE x);
+VALUE rb_rational_uminus(VALUE self);
+VALUE rb_rational_plus(VALUE self, VALUE other);
+VALUE rb_rational_minus(VALUE self, VALUE other);
+VALUE rb_rational_mul(VALUE self, VALUE other);
+VALUE rb_rational_div(VALUE self, VALUE other);
+VALUE rb_lcm(VALUE x, VALUE y);
+VALUE rb_rational_reciprocal(VALUE x);
+VALUE rb_cstr_to_rat(const char *, int);
+VALUE rb_rational_hash(VALUE self);
+VALUE rb_rational_abs(VALUE self);
+VALUE rb_rational_cmp(VALUE self, VALUE other);
+VALUE rb_rational_pow(VALUE self, VALUE other);
+VALUE rb_rational_floor(VALUE self, int ndigits);
+VALUE rb_numeric_quo(VALUE x, VALUE y);
+VALUE rb_float_numerator(VALUE x);
+VALUE rb_float_denominator(VALUE x);
+
+static inline void RATIONAL_SET_NUM(VALUE r, VALUE n);
+static inline void RATIONAL_SET_DEN(VALUE r, VALUE d);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* rational.c (export) */
+VALUE rb_gcd(VALUE x, VALUE y);
+VALUE rb_gcd_normal(VALUE self, VALUE other);
+#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
+VALUE rb_gcd_gmp(VALUE x, VALUE y);
+#endif
+RUBY_SYMBOL_EXPORT_END
+
+static inline void
+RATIONAL_SET_NUM(VALUE r, VALUE n)
+{
+ assert(RB_INTEGER_TYPE_P(n));
+ RB_OBJ_WRITE(r, &RRATIONAL(r)->num, n);
+}
+
+static inline void
+RATIONAL_SET_DEN(VALUE r, VALUE d)
+{
+ assert(RB_INTEGER_TYPE_P(d));
+ assert(INT_POSITIVE_P(d));
+ RB_OBJ_WRITE(r, &RRATIONAL(r)->den, d);
+}
+
+#endif /* INTERNAL_RATIONAL_H */
diff --git a/internal/re.h b/internal/re.h
new file mode 100644
index 0000000000..28fa3fb51c
--- /dev/null
+++ b/internal/re.h
@@ -0,0 +1,29 @@
+#ifndef INTERNAL_RE_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_RE_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.
+ * @brief Internal header for Regexp.
+ */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/ruby.h" /* for VALUE */
+
+/* re.c */
+VALUE rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline);
+VALUE rb_reg_check_preprocess(VALUE);
+long rb_reg_search0(VALUE, VALUE, long, int, int);
+VALUE rb_reg_match_p(VALUE re, VALUE str, long pos);
+bool rb_reg_start_with_p(VALUE re, VALUE str);
+void rb_backref_set_string(VALUE string, long pos, long len);
+void rb_match_unbusy(VALUE);
+int rb_match_count(VALUE match);
+int rb_match_nth_defined(int nth, VALUE match);
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE rb_reg_new_ary(VALUE ary, int options);
+MJIT_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_RE_H */
diff --git a/internal/sanitizers.h b/internal/sanitizers.h
new file mode 100644
index 0000000000..b4f5bdeda1
--- /dev/null
+++ b/internal/sanitizers.h
@@ -0,0 +1,191 @@
+#ifndef INTERNAL_SANITIZERS_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_SANITIZERS_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.
+ * @brief Internal header for ASAN / MSAN / etc.
+ */
+#include "ruby/internal/config.h"
+#include "internal/compilers.h" /* for __has_feature */
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+# include <valgrind/memcheck.h>
+#endif
+
+#ifdef HAVE_SANITIZER_ASAN_INTERFACE_H
+# include <sanitizer/asan_interface.h>
+#endif
+
+#ifdef HAVE_SANITIZER_MSAN_INTERFACE_H
+# if __has_feature(memory_sanitizer)
+# include <sanitizer/msan_interface.h>
+# endif
+#endif
+
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/ruby.h" /* for VALUE */
+
+#if 0
+#elif __has_feature(memory_sanitizer) && __has_feature(address_sanitizer)
+# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
+ __attribute__((__no_sanitize__("memory, address"), __noinline__)) x
+#elif __has_feature(address_sanitizer)
+# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
+ __attribute__((__no_sanitize__("address"), __noinline__)) x
+#elif defined(NO_SANITIZE_ADDRESS)
+# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
+ NO_SANITIZE_ADDRESS(NOINLINE(x))
+#elif defined(NO_ADDRESS_SAFETY_ANALYSIS)
+# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
+ NO_ADDRESS_SAFETY_ANALYSIS(NOINLINE(x))
+#else
+# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) x
+#endif
+
+#if defined(NO_SANITIZE) && RBIMPL_COMPILER_IS(GCC)
+/* GCC warns about unknown sanitizer, which is annoying. */
+# include "internal/warnings.h"
+# undef NO_SANITIZE
+# define NO_SANITIZE(x, y) \
+ COMPILER_WARNING_PUSH; \
+ COMPILER_WARNING_IGNORED(-Wattributes); \
+ __attribute__((__no_sanitize__(x))) y; \
+ COMPILER_WARNING_POP
+#endif
+
+#ifndef NO_SANITIZE
+# define NO_SANITIZE(x, y) y
+#endif
+
+#if !__has_feature(address_sanitizer)
+# define __asan_poison_memory_region(x, y)
+# define __asan_unpoison_memory_region(x, y)
+# define __asan_region_is_poisoned(x, y) 0
+#endif
+
+#if !__has_feature(memory_sanitizer)
+# define __msan_allocated_memory(x, y) ((void)(x), (void)(y))
+# define __msan_poison(x, y) ((void)(x), (void)(y))
+# define __msan_unpoison(x, y) ((void)(x), (void)(y))
+# define __msan_unpoison_string(x) ((void)(x))
+#endif
+
+#ifdef VALGRIND_MAKE_READABLE
+# define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
+#endif
+
+#ifdef VALGRIND_MAKE_WRITABLE
+# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
+#endif
+
+#ifndef VALGRIND_MAKE_MEM_DEFINED
+# define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
+#endif
+
+#ifndef VALGRIND_MAKE_MEM_UNDEFINED
+# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
+#endif
+
+#ifndef MJIT_HEADER
+
+/*!
+ * This function asserts that a (continuous) memory region from ptr to size
+ * being "poisoned". Both read / write access to such memory region are
+ * prohibited until properly unpoisoned. The region must be previously
+ * allocated (do not pass a freed pointer here), but not necessarily be an
+ * entire object that the malloc returns. You can punch hole a part of a
+ * gigantic heap arena. This is handy when you do not free an allocated memory
+ * region to reuse later: poison when you keep it unused, and unpoison when you
+ * reuse.
+ *
+ * \param[in] ptr pointer to the beginning of the memory region to poison.
+ * \param[in] size the length of the memory region to poison.
+ */
+static inline void
+asan_poison_memory_region(const volatile void *ptr, size_t size)
+{
+ __msan_poison(ptr, size);
+ __asan_poison_memory_region(ptr, size);
+}
+
+/*!
+ * This is a variant of asan_poison_memory_region that takes a VALUE.
+ *
+ * \param[in] obj target object.
+ */
+static inline void
+asan_poison_object(VALUE obj)
+{
+ MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
+ asan_poison_memory_region(ptr, SIZEOF_VALUE);
+}
+
+#if !__has_feature(address_sanitizer)
+#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj))
+#else
+#define asan_poison_object_if(ptr, obj) do { \
+ if (ptr) asan_poison_object(obj); \
+ } while (0)
+#endif
+
+/*!
+ * This function predicates if the given object is fully addressable or not.
+ *
+ * \param[in] obj target object.
+ * \retval 0 the given object is fully addressable.
+ * \retval otherwise pointer to first such byte who is poisoned.
+ */
+static inline void *
+asan_poisoned_object_p(VALUE obj)
+{
+ MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
+ return __asan_region_is_poisoned(ptr, SIZEOF_VALUE);
+}
+
+/*!
+ * This function asserts that a (formally poisoned) memory region from ptr to
+ * size is now addressable. Write access to such memory region gets allowed.
+ * However read access might or might not be possible depending on situations,
+ * because the region can have contents of previous usages. That information
+ * should be passed by the malloc_p flag. If that is true, the contents of the
+ * region is _not_ fully defined (like the return value of malloc behaves).
+ * Reading from there is NG; write something first. If malloc_p is false on
+ * the other hand, that memory region is fully defined and can be read
+ * immediately.
+ *
+ * \param[in] ptr pointer to the beginning of the memory region to unpoison.
+ * \param[in] size the length of the memory region.
+ * \param[in] malloc_p if the memory region is like a malloc's return value or not.
+ */
+static inline void
+asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p)
+{
+ __asan_unpoison_memory_region(ptr, size);
+ if (malloc_p) {
+ __msan_allocated_memory(ptr, size);
+ }
+ else {
+ __msan_unpoison(ptr, size);
+ }
+}
+
+/*!
+ * This is a variant of asan_unpoison_memory_region that takes a VALUE.
+ *
+ * \param[in] obj target object.
+ * \param[in] malloc_p if the memory region is like a malloc's return value or not.
+ */
+static inline void
+asan_unpoison_object(VALUE obj, bool newobj_p)
+{
+ MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
+ asan_unpoison_memory_region(ptr, SIZEOF_VALUE, newobj_p);
+}
+
+#endif /* MJIT_HEADER */
+
+#endif /* INTERNAL_SANITIZERS_H */
diff --git a/internal/scheduler.h b/internal/scheduler.h
new file mode 100644
index 0000000000..8314020220
--- /dev/null
+++ b/internal/scheduler.h
@@ -0,0 +1,44 @@
+#ifndef RUBY_SCHEDULER_H /*-*-C-*-vi:se ft=c:*/
+#define RUBY_SCHEDULER_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.
+ * @brief Internal header for Scheduler.
+ */
+#include "ruby/ruby.h"
+#include "ruby/intern.h"
+
+VALUE rb_scheduler_get();
+VALUE rb_scheduler_set(VALUE scheduler);
+
+VALUE rb_scheduler_current();
+VALUE rb_thread_scheduler_current(VALUE thread);
+
+VALUE rb_scheduler_timeout(struct timeval *timeout);
+
+VALUE rb_scheduler_close(VALUE scheduler);
+
+VALUE rb_scheduler_kernel_sleep(VALUE scheduler, VALUE duration);
+VALUE rb_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv);
+
+int rb_scheduler_supports_process_wait(VALUE scheduler);
+VALUE rb_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags);
+
+VALUE rb_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout);
+VALUE rb_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber);
+
+VALUE rb_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout);
+VALUE rb_scheduler_io_wait_readable(VALUE scheduler, VALUE io);
+VALUE rb_scheduler_io_wait_writable(VALUE scheduler, VALUE io);
+
+int rb_scheduler_supports_io_read(VALUE scheduler);
+VALUE rb_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length);
+
+int rb_scheduler_supports_io_write(VALUE scheduler);
+VALUE rb_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length);
+
+#endif /* RUBY_SCHEDULER_H */
diff --git a/internal/serial.h b/internal/serial.h
new file mode 100644
index 0000000000..977cb35477
--- /dev/null
+++ b/internal/serial.h
@@ -0,0 +1,24 @@
+#ifndef INTERNAL_SERIAL_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_SERIAL_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.
+ * @brief Internal header for rb_serial_t.
+ */
+#include "ruby/internal/config.h" /* for HAVE_LONG_LONG */
+#include "ruby/defines.h" /* for LONG_LONG */
+
+#ifndef HAVE_LONG_LONG
+# error need C99+
+#endif
+
+typedef unsigned LONG_LONG rb_serial_t;
+#define SERIALT2NUM ULL2NUM
+#define PRI_SERIALT_PREFIX PRI_LL_PREFIX
+#define SIZEOF_SERIAL_T SIZEOF_LONG_LONG
+
+#endif /* INTERNAL_SERIAL_H */
diff --git a/internal/signal.h b/internal/signal.h
new file mode 100644
index 0000000000..6b4672f15b
--- /dev/null
+++ b/internal/signal.h
@@ -0,0 +1,22 @@
+#ifndef INTERNAL_SIGNAL_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_SIGNAL_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.
+ * @brief Internal header for SignalException.
+ */
+
+/* signal.c */
+extern int ruby_enable_coredump;
+int rb_get_next_signal(void);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* signal.c (export) */
+int rb_grantpt(int fd);
+RUBY_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_SIGNAL_H */
diff --git a/internal/static_assert.h b/internal/static_assert.h
new file mode 100644
index 0000000000..284e410313
--- /dev/null
+++ b/internal/static_assert.h
@@ -0,0 +1,17 @@
+#ifndef INTERNAL_STATIC_ASSERT_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_STATIC_ASSERT_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.
+ * @brief C11 shim for _Static_assert.
+ */
+#include "ruby/internal/static_assert.h"
+#ifndef STATIC_ASSERT
+# define STATIC_ASSERT RBIMPL_STATIC_ASSERT
+#endif
+
+#endif /* INTERNAL_STATIC_ASSERT_H */
diff --git a/internal/string.h b/internal/string.h
new file mode 100644
index 0000000000..adc8385cb6
--- /dev/null
+++ b/internal/string.h
@@ -0,0 +1,141 @@
+#ifndef INTERNAL_STRING_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_STRING_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.
+ * @brief Internal header for String.
+ */
+#include "ruby/internal/config.h"
+#include <stddef.h> /* for size_t */
+#include "internal/compilers.h" /* for __has_builtin */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/encoding.h" /* for rb_encoding */
+#include "ruby/ruby.h" /* for VALUE */
+
+#define STR_NOEMBED FL_USER1
+#define STR_SHARED FL_USER2 /* = ELTS_SHARED */
+
+#ifdef rb_fstring_cstr
+# undef rb_fstring_cstr
+#endif
+
+/* string.c */
+VALUE rb_fstring(VALUE);
+VALUE rb_fstring_cstr(const char *str);
+VALUE rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc);
+int rb_str_buf_cat_escaped_char(VALUE result, unsigned int c, int unicode_p);
+int rb_str_symname_p(VALUE);
+VALUE rb_str_quote_unprintable(VALUE);
+char *rb_str_fill_terminator(VALUE str, const int termlen);
+void rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen);
+VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg);
+VALUE rb_str_chomp_string(VALUE str, VALUE chomp);
+VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc);
+VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len,
+ rb_encoding *from, int ecflags, VALUE ecopts);
+VALUE rb_enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl);
+VALUE rb_str_initialize(VALUE str, const char *ptr, long len, rb_encoding *enc);
+size_t rb_str_memsize(VALUE);
+char *rb_str_to_cstr(VALUE str);
+const char *ruby_escaped_char(int c);
+void rb_str_make_independent(VALUE str);
+int rb_enc_str_coderange_scan(VALUE str, rb_encoding *enc);
+
+static inline bool STR_EMBED_P(VALUE str);
+static inline bool STR_SHARED_P(VALUE str);
+static inline VALUE QUOTE(VALUE v);
+static inline VALUE QUOTE_ID(ID v);
+static inline bool is_ascii_string(VALUE str);
+static inline bool is_broken_string(VALUE str);
+static inline VALUE rb_str_eql_internal(const VALUE str1, const VALUE str2);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* string.c (export) */
+VALUE rb_str_tmp_frozen_acquire(VALUE str);
+void rb_str_tmp_frozen_release(VALUE str, VALUE tmp);
+VALUE rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encoding *enc);
+VALUE rb_str_upto_each(VALUE, VALUE, int, int (*each)(VALUE, VALUE), VALUE);
+VALUE rb_str_upto_endless_each(VALUE, int (*each)(VALUE, VALUE), VALUE);
+RUBY_SYMBOL_EXPORT_END
+
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE rb_fstring_new(const char *ptr, long len);
+VALUE rb_obj_as_string_result(VALUE str, VALUE obj);
+VALUE rb_str_opt_plus(VALUE x, VALUE y);
+VALUE rb_str_concat_literals(size_t num, const VALUE *strary);
+VALUE rb_str_eql(VALUE str1, VALUE str2);
+VALUE rb_id_quote_unprintable(ID);
+VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc);
+
+struct rb_execution_context_struct;
+VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str);
+MJIT_SYMBOL_EXPORT_END
+
+#define rb_fstring_lit(str) rb_fstring_new((str), rb_strlen_lit(str))
+#define rb_fstring_literal(str) rb_fstring_lit(str)
+#define rb_fstring_enc_lit(str, enc) rb_fstring_enc_new((str), rb_strlen_lit(str), (enc))
+#define rb_fstring_enc_literal(str, enc) rb_fstring_enc_lit(str, enc)
+
+static inline VALUE
+QUOTE(VALUE v)
+{
+ return rb_str_quote_unprintable(v);
+}
+
+static inline VALUE
+QUOTE_ID(ID i)
+{
+ return rb_id_quote_unprintable(i);
+}
+
+static inline bool
+STR_EMBED_P(VALUE str)
+{
+ return ! FL_TEST_RAW(str, STR_NOEMBED);
+}
+
+static inline bool
+STR_SHARED_P(VALUE str)
+{
+ return FL_ALL_RAW(str, STR_NOEMBED | ELTS_SHARED);
+}
+
+static inline bool
+is_ascii_string(VALUE str)
+{
+ return rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT;
+}
+
+static inline bool
+is_broken_string(VALUE str)
+{
+ return rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN;
+}
+
+/* expect tail call optimization */
+static inline VALUE
+rb_str_eql_internal(const VALUE str1, const VALUE str2)
+{
+ const long len = RSTRING_LEN(str1);
+ const char *ptr1, *ptr2;
+
+ if (len != RSTRING_LEN(str2)) return Qfalse;
+ if (!rb_str_comparable(str1, str2)) return Qfalse;
+ if ((ptr1 = RSTRING_PTR(str1)) == (ptr2 = RSTRING_PTR(str2)))
+ return Qtrue;
+ if (memcmp(ptr1, ptr2, len) == 0)
+ return Qtrue;
+ return Qfalse;
+}
+
+#if __has_builtin(__builtin_constant_p)
+# define rb_fstring_cstr(str) \
+ (__builtin_constant_p(str) ? \
+ rb_fstring_new((str), (long)strlen(str)) : \
+ (rb_fstring_cstr)(str))
+#endif
+#endif /* INTERNAL_STRING_H */
diff --git a/internal/struct.h b/internal/struct.h
new file mode 100644
index 0000000000..82b2738b69
--- /dev/null
+++ b/internal/struct.h
@@ -0,0 +1,154 @@
+#ifndef INTERNAL_STRUCT_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_STRUCT_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.
+ * @brief Internal header for Struct.
+ */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "internal/gc.h" /* for RB_OBJ_WRITE */
+#include "ruby/ruby.h" /* for struct RBasic */
+
+enum {
+ RSTRUCT_EMBED_LEN_MAX = RVALUE_EMBED_LEN_MAX,
+ RSTRUCT_EMBED_LEN_MASK = (RUBY_FL_USER2|RUBY_FL_USER1),
+ RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1),
+ RSTRUCT_TRANSIENT_FLAG = FL_USER3,
+};
+
+struct RStruct {
+ struct RBasic basic;
+ union {
+ struct {
+ long len;
+ const VALUE *ptr;
+ } heap;
+ const VALUE ary[RSTRUCT_EMBED_LEN_MAX];
+ } as;
+};
+
+#define RSTRUCT(obj) ((struct RStruct *)(obj))
+
+#ifdef RSTRUCT_LEN
+# undef RSTRUCT_LEN
+#endif
+
+#ifdef RSTRUCT_PTR
+# undef RSTRUCT_PTR
+#endif
+
+#ifdef RSTRUCT_SET
+# undef RSTRUCT_SET
+#endif
+
+#ifdef RSTRUCT_GET
+# undef RSTRUCT_GET
+#endif
+
+#define RSTRUCT_LEN internal_RSTRUCT_LEN
+#define RSTRUCT_SET internal_RSTRUCT_SET
+#define RSTRUCT_GET internal_RSTRUCT_GET
+
+/* struct.c */
+VALUE rb_struct_init_copy(VALUE copy, VALUE s);
+VALUE rb_struct_lookup(VALUE s, VALUE idx);
+VALUE rb_struct_s_keyword_init(VALUE klass);
+static inline const VALUE *rb_struct_const_heap_ptr(VALUE st);
+static inline bool RSTRUCT_TRANSIENT_P(VALUE st);
+static inline void RSTRUCT_TRANSIENT_SET(VALUE st);
+static inline void RSTRUCT_TRANSIENT_UNSET(VALUE st);
+static inline long RSTRUCT_EMBED_LEN(VALUE st);
+static inline long RSTRUCT_LEN(VALUE st);
+static inline int RSTRUCT_LENINT(VALUE st);
+static inline const VALUE *RSTRUCT_CONST_PTR(VALUE st);
+static inline void RSTRUCT_SET(VALUE st, long k, VALUE v);
+static inline VALUE RSTRUCT_GET(VALUE st, long k);
+
+static inline bool
+RSTRUCT_TRANSIENT_P(VALUE st)
+{
+#if USE_TRANSIENT_HEAP
+ return FL_TEST_RAW(st, RSTRUCT_TRANSIENT_FLAG);
+#else
+ return false;
+#endif
+}
+
+static inline void
+RSTRUCT_TRANSIENT_SET(VALUE st)
+{
+#if USE_TRANSIENT_HEAP
+ FL_SET_RAW(st, RSTRUCT_TRANSIENT_FLAG);
+#endif
+}
+
+static inline void
+RSTRUCT_TRANSIENT_UNSET(VALUE st)
+{
+#if USE_TRANSIENT_HEAP
+ FL_UNSET_RAW(st, RSTRUCT_TRANSIENT_FLAG);
+#endif
+}
+
+static inline long
+RSTRUCT_EMBED_LEN(VALUE st)
+{
+ long ret = FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK);
+ ret >>= RSTRUCT_EMBED_LEN_SHIFT;
+ return ret;
+}
+
+static inline long
+RSTRUCT_LEN(VALUE st)
+{
+ if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) {
+ return RSTRUCT_EMBED_LEN(st);
+ }
+ else {
+ return RSTRUCT(st)->as.heap.len;
+ }
+}
+
+static inline int
+RSTRUCT_LENINT(VALUE st)
+{
+ return rb_long2int(RSTRUCT_LEN(st));
+}
+
+static inline const VALUE *
+RSTRUCT_CONST_PTR(VALUE st)
+{
+ const struct RStruct *p = RSTRUCT(st);
+
+ if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) {
+ return p->as.ary;
+ }
+ else {
+ return p->as.heap.ptr;
+ }
+}
+
+static inline void
+RSTRUCT_SET(VALUE st, long k, VALUE v)
+{
+ RB_OBJ_WRITE(st, &RSTRUCT_CONST_PTR(st)[k], v);
+}
+
+static inline VALUE
+RSTRUCT_GET(VALUE st, long k)
+{
+ return RSTRUCT_CONST_PTR(st)[k];
+}
+
+static inline const VALUE *
+rb_struct_const_heap_ptr(VALUE st)
+{
+ /* TODO: check embed on debug mode */
+ return RSTRUCT(st)->as.heap.ptr;
+}
+
+#endif /* INTERNAL_STRUCT_H */
diff --git a/internal/symbol.h b/internal/symbol.h
new file mode 100644
index 0000000000..691df66228
--- /dev/null
+++ b/internal/symbol.h
@@ -0,0 +1,41 @@
+#ifndef INTERNAL_SYMBOL_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_SYMBOL_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.
+ * @brief Internal header for Symbol.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+#include "ruby/encoding.h" /* for rb_encoding */
+#include "internal/compilers.h" /* for __has_builtin */
+
+#ifdef rb_sym_intern_ascii_cstr
+# undef rb_sym_intern_ascii_cstr
+#endif
+
+/* symbol.c */
+VALUE rb_to_symbol_type(VALUE obj);
+VALUE rb_sym_intern(const char *ptr, long len, rb_encoding *enc);
+VALUE rb_sym_intern_ascii(const char *ptr, long len);
+VALUE rb_sym_intern_ascii_cstr(const char *ptr);
+int rb_is_const_name(VALUE name);
+int rb_is_class_name(VALUE name);
+int rb_is_instance_name(VALUE name);
+int rb_is_local_name(VALUE name);
+PUREFUNC(int rb_is_const_sym(VALUE sym));
+PUREFUNC(int rb_is_attrset_sym(VALUE sym));
+ID rb_make_internal_id(void);
+void rb_gc_free_dsymbol(VALUE);
+
+#if __has_builtin(__builtin_constant_p)
+#define rb_sym_intern_ascii_cstr(ptr) \
+ (__builtin_constant_p(ptr) ? \
+ rb_sym_intern_ascii((ptr), (long)strlen(ptr)) : \
+ rb_sym_intern_ascii_cstr(ptr))
+#endif
+
+#endif /* INTERNAL_SYMBOL_H */
diff --git a/internal/thread.h b/internal/thread.h
new file mode 100644
index 0000000000..09b8551b5c
--- /dev/null
+++ b/internal/thread.h
@@ -0,0 +1,54 @@
+#ifndef INTERNAL_THREAD_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_THREAD_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.
+ * @brief Internal header for Thread.
+ */
+#include "ruby/ruby.h" /* for VALUE */
+#include "ruby/intern.h" /* for rb_blocking_function_t */
+
+struct rb_thread_struct; /* in vm_core.h */
+
+/* thread.c */
+#define COVERAGE_INDEX_LINES 0
+#define COVERAGE_INDEX_BRANCHES 1
+#define COVERAGE_TARGET_LINES 1
+#define COVERAGE_TARGET_BRANCHES 2
+#define COVERAGE_TARGET_METHODS 4
+#define COVERAGE_TARGET_ONESHOT_LINES 8
+
+VALUE rb_obj_is_mutex(VALUE obj);
+VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
+void rb_thread_execute_interrupts(VALUE th);
+VALUE rb_get_coverages(void);
+int rb_get_coverage_mode(void);
+VALUE rb_default_coverage(int);
+VALUE rb_thread_shield_new(void);
+VALUE rb_thread_shield_wait(VALUE self);
+VALUE rb_thread_shield_release(VALUE self);
+VALUE rb_thread_shield_destroy(VALUE self);
+int rb_thread_to_be_killed(VALUE thread);
+void rb_mutex_allow_trap(VALUE self, int val);
+VALUE rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data);
+VALUE rb_mutex_owned_p(VALUE self);
+
+int rb_thread_wait_for_single_fd(int fd, int events, struct timeval * timeout);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* Temporary. This API will be removed (renamed). */
+VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd);
+
+/* thread.c (export) */
+int ruby_thread_has_gvl_p(void); /* for ext/fiddle/closure.c */
+RUBY_SYMBOL_EXPORT_END
+
+MJIT_SYMBOL_EXPORT_BEGIN
+int rb_threadptr_execute_interrupts(struct rb_thread_struct *th, int blocking_timing);
+MJIT_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_THREAD_H */
diff --git a/internal/time.h b/internal/time.h
new file mode 100644
index 0000000000..f9ac084603
--- /dev/null
+++ b/internal/time.h
@@ -0,0 +1,35 @@
+#ifndef INTERNAL_TIME_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_TIME_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.
+ * @brief Internal header for Time.
+ */
+#include "ruby/internal/config.h" /* for SIGNEDNESS_OF_TIME_T */
+#include "internal/bits.h" /* for SIGNED_INTEGER_MAX */
+#include "ruby/ruby.h" /* for VALUE */
+
+#if SIGNEDNESS_OF_TIME_T < 0 /* signed */
+# define TIMET_MAX SIGNED_INTEGER_MAX(time_t)
+# define TIMET_MIN SIGNED_INTEGER_MIN(time_t)
+#elif SIGNEDNESS_OF_TIME_T > 0 /* unsigned */
+# define TIMET_MAX UNSIGNED_INTEGER_MAX(time_t)
+# define TIMET_MIN ((time_t)0)
+#endif
+
+struct timeval; /* <- in <sys/time.h> or <winsock2.h> */
+
+/* time.c */
+struct timeval rb_time_timeval(VALUE);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* time.c (export) */
+void ruby_reset_leap_second_info(void);
+void ruby_reset_timezone(void);
+RUBY_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_TIME_H */
diff --git a/internal/transcode.h b/internal/transcode.h
new file mode 100644
index 0000000000..a60ac06d10
--- /dev/null
+++ b/internal/transcode.h
@@ -0,0 +1,21 @@
+#ifndef INTERNAL_TRANSCODE_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_TRANSCODE_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.
+ * @brief Internal header for Encoding::Converter.
+ */
+#include "ruby/internal/config.h"
+#include <stddef.h> /* for size_t */
+#include "ruby/ruby.h" /* for VALUE */
+#include "ruby/encoding.h" /* for rb_econv_t */
+
+/* transcode.c */
+extern VALUE rb_cEncodingConverter;
+size_t rb_econv_memsize(rb_econv_t *);
+
+#endif /* INTERNAL_TRANSCODE_H */
diff --git a/internal/util.h b/internal/util.h
new file mode 100644
index 0000000000..c28b884d32
--- /dev/null
+++ b/internal/util.h
@@ -0,0 +1,31 @@
+#ifndef INTERNAL_UTIL_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_UTIL_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.
+ * @brief Internal header corresponding util.c.
+ * @warning DO NOT ADD RANDOM GARBAGE HERE THIS FILE IS FOR util.c
+ */
+#include "ruby/internal/config.h"
+#include <stddef.h> /* for size_t */
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h> /* for ssize_t (note: on Windows ssize_t is */
+#endif /* `#define`d in ruby/config.h) */
+
+/* util.c */
+char *ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve);
+char *ruby_hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* util.c (export) */
+extern const signed char ruby_digit36_to_number_table[];
+extern const char ruby_hexdigits[];
+extern unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
+RUBY_SYMBOL_EXPORT_END
+
+#endif /* INTERNAL_UTIL_H */
diff --git a/internal/variable.h b/internal/variable.h
new file mode 100644
index 0000000000..057beccfcc
--- /dev/null
+++ b/internal/variable.h
@@ -0,0 +1,84 @@
+#ifndef INTERNAL_VARIABLE_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_VARIABLE_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.
+ * @brief Internal header for variables.
+ */
+#include "ruby/internal/config.h"
+#include <stddef.h> /* for size_t */
+#include "constant.h" /* for rb_const_entry_t */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "ruby/ruby.h" /* for VALUE */
+
+/* global variable */
+
+#define ROBJECT_TRANSIENT_FLAG FL_USER13
+
+/* variable.c */
+void rb_gc_mark_global_tbl(void);
+void rb_gc_update_global_tbl(void);
+size_t rb_generic_ivar_memsize(VALUE);
+VALUE rb_search_class_path(VALUE);
+VALUE rb_attr_delete(VALUE, ID);
+VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef);
+void rb_autoload_str(VALUE mod, ID id, VALUE file);
+VALUE rb_autoload_at_p(VALUE, ID, int);
+NORETURN(VALUE rb_mod_const_missing(VALUE,VALUE));
+rb_gvar_getter_t *rb_gvar_getter_function_of(ID);
+rb_gvar_setter_t *rb_gvar_setter_function_of(ID);
+void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_);
+void rb_gvar_ractor_local(const char *name);
+static inline bool ROBJ_TRANSIENT_P(VALUE obj);
+static inline void ROBJ_TRANSIENT_SET(VALUE obj);
+static inline void ROBJ_TRANSIENT_UNSET(VALUE obj);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+/* variable.c (export) */
+void rb_mark_generic_ivar(VALUE);
+void rb_mv_generic_ivar(VALUE src, VALUE dst);
+VALUE rb_const_missing(VALUE klass, VALUE name);
+int rb_class_ivar_set(VALUE klass, ID vid, VALUE value);
+void rb_iv_tbl_copy(VALUE dst, VALUE src);
+void rb_deprecate_constant(VALUE mod, const char *name);
+RUBY_SYMBOL_EXPORT_END
+
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE rb_gvar_get(ID);
+VALUE rb_gvar_set(ID, VALUE);
+VALUE rb_gvar_defined(ID);
+void rb_const_warn_if_deprecated(const rb_const_entry_t *, VALUE, ID);
+void rb_init_iv_list(VALUE obj);
+MJIT_SYMBOL_EXPORT_END
+
+static inline bool
+ROBJ_TRANSIENT_P(VALUE obj)
+{
+#if USE_TRANSIENT_HEAP
+ return FL_TEST_RAW(obj, ROBJECT_TRANSIENT_FLAG);
+#else
+ return false;
+#endif
+}
+
+static inline void
+ROBJ_TRANSIENT_SET(VALUE obj)
+{
+#if USE_TRANSIENT_HEAP
+ FL_SET_RAW(obj, ROBJECT_TRANSIENT_FLAG);
+#endif
+}
+
+static inline void
+ROBJ_TRANSIENT_UNSET(VALUE obj)
+{
+#if USE_TRANSIENT_HEAP
+ FL_UNSET_RAW(obj, ROBJECT_TRANSIENT_FLAG);
+#endif
+}
+
+#endif /* INTERNAL_VARIABLE_H */
diff --git a/internal/vm.h b/internal/vm.h
new file mode 100644
index 0000000000..689b4fa61f
--- /dev/null
+++ b/internal/vm.h
@@ -0,0 +1,131 @@
+#ifndef INTERNAL_VM_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_VM_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.
+ * @brief Internal header for RubyVM.
+ */
+#include "ruby/internal/stdbool.h" /* for bool */
+#include "internal/serial.h" /* for rb_serial_t */
+#include "internal/static_assert.h" /* for STATIC_ASSERT */
+#include "ruby/ruby.h" /* for ID */
+#include "ruby/st.h" /* for st_table */
+
+#ifdef rb_funcallv
+# undef rb_funcallv
+#endif
+
+#ifdef rb_method_basic_definition_p
+# undef rb_method_basic_definition_p
+#endif
+
+struct rb_callable_method_entry_struct; /* in method.h */
+struct rb_method_definition_struct; /* in method.h */
+struct rb_execution_context_struct; /* in vm_core.h */
+struct rb_control_frame_struct; /* in vm_core.h */
+struct rb_callinfo; /* in vm_core.h */
+
+enum method_missing_reason {
+ MISSING_NOENTRY = 0x00,
+ MISSING_PRIVATE = 0x01,
+ MISSING_PROTECTED = 0x02,
+ MISSING_FCALL = 0x04,
+ MISSING_VCALL = 0x08,
+ MISSING_SUPER = 0x10,
+ MISSING_MISSING = 0x20,
+ MISSING_NONE = 0x40
+};
+
+/* vm_insnhelper.h */
+rb_serial_t rb_next_class_serial(void);
+
+/* vm.c */
+VALUE rb_obj_is_thread(VALUE obj);
+void rb_vm_mark(void *ptr);
+void rb_vm_each_stack_value(void *ptr, void (*cb)(VALUE, void*), void *ctx);
+PUREFUNC(VALUE rb_vm_top_self(void));
+void rb_vm_inc_const_missing_count(void);
+const void **rb_vm_get_insns_address_table(void);
+VALUE rb_source_location(int *pline);
+const char *rb_source_location_cstr(int *pline);
+MJIT_STATIC void rb_vm_pop_cfunc_frame(void);
+int rb_vm_add_root_module(VALUE module);
+void rb_vm_check_redefinition_by_prepend(VALUE klass);
+int rb_vm_check_optimizable_mid(VALUE mid);
+VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements);
+MJIT_STATIC VALUE ruby_vm_special_exception_copy(VALUE);
+PUREFUNC(st_table *rb_vm_fstring_table(void));
+
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE vm_exec(struct rb_execution_context_struct *, bool); /* used in JIT-ed code */
+MJIT_SYMBOL_EXPORT_END
+
+/* vm_eval.c */
+VALUE rb_current_realfilepath(void);
+VALUE rb_check_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE);
+typedef void rb_check_funcall_hook(int, VALUE, ID, int, const VALUE *, VALUE);
+VALUE rb_check_funcall_with_hook(VALUE recv, ID mid, int argc, const VALUE *argv,
+ rb_check_funcall_hook *hook, VALUE arg);
+VALUE rb_check_funcall_with_hook_kw(VALUE recv, ID mid, int argc, const VALUE *argv,
+ rb_check_funcall_hook *hook, VALUE arg, int kw_splat);
+const char *rb_type_str(enum ruby_value_type type);
+VALUE rb_check_funcall_default(VALUE, ID, int, const VALUE *, VALUE);
+VALUE rb_check_funcall_basic_kw(VALUE, ID, VALUE, int, const VALUE*, int);
+VALUE rb_yield_1(VALUE val);
+VALUE rb_yield_force_blockarg(VALUE values);
+VALUE rb_lambda_call(VALUE obj, ID mid, int argc, const VALUE *argv,
+ rb_block_call_func_t bl_proc, int min_argc, int max_argc,
+ VALUE data2);
+void rb_check_stack_overflow(void);
+
+/* vm_insnhelper.c */
+VALUE rb_equal_opt(VALUE obj1, VALUE obj2);
+VALUE rb_eql_opt(VALUE obj1, VALUE obj2);
+
+struct rb_iseq_struct;
+MJIT_SYMBOL_EXPORT_BEGIN
+const struct rb_callcache *rb_vm_search_method_slowpath(const struct rb_callinfo *ci, VALUE klass);
+MJIT_SYMBOL_EXPORT_END
+
+/* vm_method.c */
+struct rb_execution_context_struct;
+MJIT_SYMBOL_EXPORT_BEGIN
+int rb_ec_obj_respond_to(struct rb_execution_context_struct *ec, VALUE obj, ID id, int priv);
+MJIT_SYMBOL_EXPORT_END
+
+/* vm_dump.c */
+void rb_print_backtrace(void);
+
+/* vm_backtrace.c */
+VALUE rb_vm_thread_backtrace(int argc, const VALUE *argv, VALUE thval);
+VALUE rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval);
+VALUE rb_vm_backtrace(int argc, const VALUE * argv, struct rb_execution_context_struct * ec);
+VALUE rb_vm_backtrace_locations(int argc, const VALUE * argv, struct rb_execution_context_struct * ec);
+VALUE rb_make_backtrace(void);
+void rb_backtrace_print_as_bugreport(void);
+int rb_backtrace_p(VALUE obj);
+VALUE rb_backtrace_to_str_ary(VALUE obj);
+VALUE rb_backtrace_to_location_ary(VALUE obj);
+void rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output);
+
+MJIT_SYMBOL_EXPORT_BEGIN
+VALUE rb_ec_backtrace_object(const struct rb_execution_context_struct *ec);
+void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self);
+MJIT_SYMBOL_EXPORT_END
+
+#define RUBY_DTRACE_CREATE_HOOK(name, arg) \
+ RUBY_DTRACE_HOOK(name##_CREATE, arg)
+#define RUBY_DTRACE_HOOK(name, arg) \
+do { \
+ if (UNLIKELY(RUBY_DTRACE_##name##_ENABLED())) { \
+ int dtrace_line; \
+ const char *dtrace_file = rb_source_location_cstr(&dtrace_line); \
+ if (!dtrace_file) dtrace_file = ""; \
+ RUBY_DTRACE_##name(arg, dtrace_file, dtrace_line); \
+ } \
+} while (0)
+#endif /* INTERNAL_VM_H */
diff --git a/internal/warnings.h b/internal/warnings.h
new file mode 100644
index 0000000000..63ded99d04
--- /dev/null
+++ b/internal/warnings.h
@@ -0,0 +1,17 @@
+#ifndef INTERNAL_WARNINGS_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_WARNINGS_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.
+ * @brief Internal header to suppres / mandate warnings.
+ */
+#include "ruby/internal/warning_push.h"
+#define COMPILER_WARNING_PUSH RBIMPL_WARNING_PUSH()
+#define COMPILER_WARNING_POP RBIMPL_WARNING_POP()
+#define COMPILER_WARNING_ERROR(flag) RBIMPL_WARNING_ERROR(flag)
+#define COMPILER_WARNING_IGNORED(flag) RBIMPL_WARNING_IGNORED(flag)
+#endif /* INTERNAL_WARNINGS_H */
diff --git a/io.c b/io.c
index be6c6b637f..caa4dd28f7 100644
--- a/io.c
+++ b/io.c
@@ -11,38 +11,33 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/io.h"
-#include "ruby/thread.h"
-#include "internal.h"
-#include "dln.h"
-#include "encindex.h"
-#include "id.h"
+#include "ruby/internal/config.h"
+
+#include "internal/scheduler.h"
+
+#ifdef _WIN32
+# include "ruby/ruby.h"
+# include "ruby/io.h"
+#endif
+
#include <ctype.h>
#include <errno.h>
-#include "ruby_atomic.h"
-#include "ccan/list/list.h"
+#include <stddef.h>
/* non-Linux poll may not work on all FDs */
#if defined(HAVE_POLL)
-# if defined(__linux__)
-# define USE_POLL 1
-# endif
-# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
-# define USE_POLL 1
-# endif
+# if defined(__linux__)
+# define USE_POLL 1
+# endif
+# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
+# define USE_POLL 1
+# endif
#endif
#ifndef USE_POLL
-# define USE_POLL 0
-#endif
-
-#if !USE_POLL
-# include "vm_core.h"
+# define USE_POLL 0
#endif
-#include "builtin.h"
-
#undef free
#define free(x) xfree(x)
@@ -119,7 +114,33 @@
# include <copyfile.h>
#endif
+#include "ruby/internal/stdbool.h"
+#include "ccan/list/list.h"
+#include "dln.h"
+#include "encindex.h"
+#include "id.h"
+#include "internal.h"
+#include "internal/encoding.h"
+#include "internal/error.h"
+#include "internal/inits.h"
+#include "internal/io.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/process.h"
+#include "internal/thread.h"
+#include "internal/transcode.h"
+#include "internal/variable.h"
+#include "ruby/io.h"
+#include "ruby/thread.h"
#include "ruby/util.h"
+#include "ruby_atomic.h"
+#include "ruby/ractor.h"
+
+#if !USE_POLL
+# include "vm_core.h"
+#endif
+
+#include "builtin.h"
#ifndef O_ACCMODE
#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
@@ -159,15 +180,6 @@ off_t __syscall(quad_t number, ...);
#define rename(f, t) rb_w32_urename((f), (t))
#endif
-#if defined(_WIN32)
-# define RUBY_PIPE_NONBLOCK_DEFAULT (0)
-#elif defined(O_NONBLOCK)
- /* disabled for [Bug #15356] (Rack::Deflater + rails) failure: */
-# define RUBY_PIPE_NONBLOCK_DEFAULT (0)
-#else /* any platforms where O_NONBLOCK does not exist? */
-# define RUBY_PIPE_NONBLOCK_DEFAULT (0)
-#endif
-
VALUE rb_cIO;
VALUE rb_eEOFError;
VALUE rb_eIOError;
@@ -203,6 +215,9 @@ static VALUE sym_DATA;
static VALUE sym_HOLE;
#endif
+static VALUE rb_io_initialize(int argc, VALUE *argv, VALUE io);
+static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path);
+
struct argf {
VALUE filename, current_file;
long last_lineno; /* $. */
@@ -294,13 +309,26 @@ rb_cloexec_open(const char *pathname, int flags, mode_t mode)
int ret;
static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
+ static const int retry_interval = 0;
+ static const int retry_max_count = 10000;
+
+ int retry_count = 0;
+
#ifdef O_CLOEXEC
/* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
flags |= O_CLOEXEC;
#elif defined O_NOINHERIT
flags |= O_NOINHERIT;
#endif
- ret = open(pathname, flags, mode);
+
+ while ((ret = open(pathname, flags, mode)) == -1) {
+ int e = errno;
+ if (e != EAGAIN && e != EWOULDBLOCK) break;
+ if (retry_count++ >= retry_max_count) break;
+
+ sleep(retry_interval);
+ }
+
if (ret < 0) return ret;
if (ret <= 2 || o_cloexec_state == 0) {
rb_maygvl_fd_fix_cloexec(ret);
@@ -375,44 +403,37 @@ rb_fd_set_nonblock(int fd)
}
int
-rb_cloexec_pipe(int fildes[2])
+rb_cloexec_pipe(int descriptors[2])
{
- int ret;
-
-#if defined(HAVE_PIPE2)
- static int try_pipe2 = 1;
- if (try_pipe2) {
- ret = pipe2(fildes, O_CLOEXEC | RUBY_PIPE_NONBLOCK_DEFAULT);
- if (ret != -1)
- return ret;
- /* pipe2 is available since Linux 2.6.27, glibc 2.9. */
- if (errno == ENOSYS) {
- try_pipe2 = 0;
- ret = pipe(fildes);
- }
- }
- else {
- ret = pipe(fildes);
- }
+#ifdef HAVE_PIPE2
+ int result = pipe2(descriptors, O_CLOEXEC | O_NONBLOCK);
#else
- ret = pipe(fildes);
+ int result = pipe(descriptors);
#endif
- if (ret < 0) return ret;
+
+ if (result < 0)
+ return result;
+
#ifdef __CYGWIN__
- if (ret == 0 && fildes[1] == -1) {
- close(fildes[0]);
- fildes[0] = -1;
- errno = ENFILE;
- return -1;
+ if (result == 0 && descriptors[1] == -1) {
+ close(descriptors[0]);
+ descriptors[0] = -1;
+ errno = ENFILE;
+ return -1;
}
#endif
- rb_maygvl_fd_fix_cloexec(fildes[0]);
- rb_maygvl_fd_fix_cloexec(fildes[1]);
- if (RUBY_PIPE_NONBLOCK_DEFAULT) {
- rb_fd_set_nonblock(fildes[0]);
- rb_fd_set_nonblock(fildes[1]);
- }
- return ret;
+
+#ifndef HAVE_PIPE2
+ rb_maygvl_fd_fix_cloexec(descriptors[0]);
+ rb_maygvl_fd_fix_cloexec(descriptors[1]);
+
+#ifndef _WIN32
+ rb_fd_set_nonblock(descriptors[0]);
+ rb_fd_set_nonblock(descriptors[1]);
+#endif
+#endif
+
+ return result;
}
int
@@ -503,6 +524,42 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd)
static int io_fflush(rb_io_t *);
static rb_io_t *flush_before_seek(rb_io_t *fptr);
+#define FMODE_PREP (1<<16)
+#define FMODE_SIGNAL_ON_EPIPE (1<<17)
+
+#define fptr_signal_on_epipe(fptr) \
+ (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
+
+#define fptr_set_signal_on_epipe(fptr, flag) \
+ ((flag) ? \
+ (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
+ (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
+
+extern ID ruby_static_id_signo;
+
+NORETURN(static void raise_on_write(rb_io_t *fptr, int e, VALUE errinfo));
+static void
+raise_on_write(rb_io_t *fptr, int e, VALUE errinfo)
+{
+#if defined EPIPE
+ if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
+ const VALUE sig =
+# if defined SIGPIPE
+ INT2FIX(SIGPIPE) - INT2FIX(0) +
+# endif
+ INT2FIX(0);
+ rb_ivar_set(errinfo, ruby_static_id_signo, sig);
+ }
+#endif
+ rb_exc_raise(errinfo);
+}
+
+#define rb_sys_fail_on_write(fptr) \
+ do { \
+ int e = errno; \
+ raise_on_write(fptr, e, rb_syserr_new_path(e, (fptr)->pathv)); \
+ } while (0)
+
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
@@ -852,7 +909,7 @@ static rb_io_t *
flush_before_seek(rb_io_t *fptr)
{
if (io_fflush(fptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
io_unread(fptr);
errno = 0;
return fptr;
@@ -876,13 +933,13 @@ rb_io_check_char_readable(rb_io_t *fptr)
}
if (fptr->wbuf.len) {
if (io_fflush(fptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
}
if (fptr->tied_io_for_writing) {
rb_io_t *wfptr;
GetOpenFile(fptr->tied_io_for_writing, wfptr);
if (io_fflush(wfptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(wfptr);
}
}
@@ -993,6 +1050,7 @@ io_alloc(VALUE klass)
#endif
struct io_internal_read_struct {
+ VALUE th;
int fd;
int nonblock;
void *buf;
@@ -1013,7 +1071,7 @@ struct io_internal_writev_struct {
};
#endif
-static int nogvl_wait_for_single_fd(int fd, short events);
+static int nogvl_wait_for_single_fd(VALUE th, int fd, short events);
static VALUE
internal_read_func(void *ptr)
{
@@ -1024,7 +1082,7 @@ retry:
if (r < 0 && !iis->nonblock) {
int e = errno;
if (e == EAGAIN || e == EWOULDBLOCK) {
- if (nogvl_wait_for_single_fd(iis->fd, RB_WAITFD_IN) != -1) {
+ if (nogvl_wait_for_single_fd(iis->th, iis->fd, RB_WAITFD_IN) != -1) {
goto retry;
}
errno = e;
@@ -1067,12 +1125,13 @@ internal_writev_func(void *ptr)
static ssize_t
rb_read_internal(int fd, void *buf, size_t count)
{
- struct io_internal_read_struct iis;
-
- iis.fd = fd;
- iis.nonblock = 0;
- iis.buf = buf;
- iis.capa = count;
+ struct io_internal_read_struct iis = {
+ .th = rb_thread_current(),
+ .fd = fd,
+ .nonblock = 0,
+ .buf = buf,
+ .capa = count
+ };
return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
}
@@ -1080,10 +1139,11 @@ rb_read_internal(int fd, void *buf, size_t count)
static ssize_t
rb_write_internal(int fd, const void *buf, size_t count)
{
- struct io_internal_write_struct iis;
- iis.fd = fd;
- iis.buf = buf;
- iis.capa = count;
+ struct io_internal_write_struct iis = {
+ .fd = fd,
+ .buf = buf,
+ .capa = count
+ };
return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
}
@@ -1091,10 +1151,11 @@ rb_write_internal(int fd, const void *buf, size_t count)
static ssize_t
rb_write_internal2(int fd, const void *buf, size_t count)
{
- struct io_internal_write_struct iis;
- iis.fd = fd;
- iis.buf = buf;
- iis.capa = count;
+ struct io_internal_write_struct iis = {
+ .fd = fd,
+ .buf = buf,
+ .capa = count
+ };
return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis,
RUBY_UBF_IO, NULL);
@@ -1104,10 +1165,11 @@ rb_write_internal2(int fd, const void *buf, size_t count)
static ssize_t
rb_writev_internal(int fd, const struct iovec *iov, int iovcnt)
{
- struct io_internal_writev_struct iis;
- iis.fd = fd;
- iis.iov = iov;
- iis.iovcnt = iovcnt;
+ struct io_internal_writev_struct iis = {
+ .fd = fd,
+ .iov = iov,
+ .iovcnt = iovcnt,
+ };
return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd);
}
@@ -1158,8 +1220,7 @@ io_flush_buffer_async2(VALUE arg)
rb_io_t *fptr = (rb_io_t *)arg;
VALUE ret;
- ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr,
- RUBY_UBF_IO, NULL);
+ ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr, RUBY_UBF_IO, NULL);
if (!ret) {
/* pending async interrupt is there. */
@@ -1200,61 +1261,137 @@ io_fflush(rb_io_t *fptr)
return 0;
}
+VALUE
+rb_io_wait(VALUE io, VALUE events, VALUE timeout)
+{
+ VALUE scheduler = rb_scheduler_current();
+
+ if (scheduler != Qnil) {
+ return rb_scheduler_io_wait(scheduler, io, events, timeout);
+ }
+
+ rb_io_t * fptr = NULL;
+ RB_IO_POINTER(io, fptr);
+
+ struct timeval tv_storage;
+ struct timeval *tv = NULL;
+
+ if (timeout != Qnil) {
+ tv_storage = rb_time_interval(timeout);
+ tv = &tv_storage;
+ }
+
+ int ready = rb_thread_wait_for_single_fd(fptr->fd, RB_NUM2INT(events), tv);
+
+ if (ready < 0) {
+ rb_sys_fail(0);
+ }
+
+ // Not sure if this is necessary:
+ rb_io_check_closed(fptr);
+
+ if (ready > 0) {
+ return RB_INT2NUM(ready);
+ } else {
+ return Qfalse;
+ }
+}
+
+static VALUE
+rb_io_from_fd(int fd)
+{
+ return prep_io(fd, FMODE_PREP, rb_cIO, NULL);
+}
+
int
rb_io_wait_readable(int f)
{
+ VALUE scheduler;
+
io_fd_check_closed(f);
+
+ scheduler = rb_scheduler_current();
switch (errno) {
case EINTR:
#if defined(ERESTART)
case ERESTART:
#endif
- rb_thread_check_ints();
- return TRUE;
+ rb_thread_check_ints();
+ return TRUE;
case EAGAIN:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
- rb_thread_wait_fd(f);
- return TRUE;
+ if (scheduler != Qnil) {
+ return RTEST(
+ rb_scheduler_io_wait_readable(scheduler, rb_io_from_fd(f))
+ );
+ } else {
+ rb_thread_wait_fd(f);
+ }
+ return TRUE;
default:
- return FALSE;
+ return FALSE;
}
}
int
rb_io_wait_writable(int f)
{
+ VALUE scheduler;
+
io_fd_check_closed(f);
+
+ scheduler = rb_scheduler_current();
switch (errno) {
case EINTR:
#if defined(ERESTART)
case ERESTART:
#endif
- /*
- * In old Linux, several special files under /proc and /sys don't handle
- * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
- * Otherwise, we face nasty hang up. Sigh.
- * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
- * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
- * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
- * Then rb_thread_check_ints() is enough.
- */
- rb_thread_check_ints();
- return TRUE;
+ /*
+ * In old Linux, several special files under /proc and /sys don't handle
+ * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
+ * Otherwise, we face nasty hang up. Sigh.
+ * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
+ * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
+ * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
+ * Then rb_thread_check_ints() is enough.
+ */
+ rb_thread_check_ints();
+ return TRUE;
case EAGAIN:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
- rb_thread_fd_writable(f);
- return TRUE;
+ if (scheduler != Qnil) {
+ return RTEST(
+ rb_scheduler_io_wait_writable(scheduler, rb_io_from_fd(f))
+ );
+ } else {
+ rb_thread_fd_writable(f);
+ }
+ return TRUE;
default:
- return FALSE;
+ return FALSE;
+ }
+}
+
+int
+rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
+{
+ VALUE scheduler = rb_scheduler_current();
+
+ if (scheduler != Qnil) {
+ return RTEST(
+ rb_scheduler_io_wait(scheduler, rb_io_from_fd(fd), RB_INT2NUM(events), rb_scheduler_timeout(timeout))
+ );
}
+
+ return rb_thread_wait_for_single_fd(fd, events, timeout);
}
static void
@@ -1406,12 +1543,24 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
rb_thread_check_ints();
if ((n = len) <= 0) return n;
+
+ VALUE scheduler = rb_scheduler_current();
+ if (scheduler != Qnil && rb_scheduler_supports_io_write(scheduler)) {
+ ssize_t length = RB_NUM2SSIZE(
+ rb_scheduler_io_write(scheduler, fptr->self, str, offset, len)
+ );
+
+ if (length < 0) rb_sys_fail_path(fptr->pathv);
+
+ return length;
+ }
+
if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
fptr->wbuf.off = 0;
fptr->wbuf.len = 0;
fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
- fptr->write_lock = rb_mutex_new();
+ fptr->write_lock = rb_mutex_new();
rb_mutex_allow_trap(fptr->write_lock, 1);
}
if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
@@ -1424,7 +1573,7 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
arg.ptr = ptr + offset;
arg.length = n;
if (fptr->write_lock) {
- r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
+ r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
}
else {
r = io_binwrite_string((VALUE)&arg);
@@ -1576,7 +1725,7 @@ io_write(VALUE io, VALUE str, int nosync)
rb_io_check_writable(fptr);
n = io_fwrite(str, fptr, nosync);
- if (n < 0L) rb_sys_fail_path(fptr->pathv);
+ if (n < 0L) rb_sys_fail_on_write(fptr);
return LONG2FIX(n);
}
@@ -1685,7 +1834,7 @@ io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
}
static long
-io_fwritev(int argc, VALUE *argv, rb_io_t *fptr)
+io_fwritev(int argc, const VALUE *argv, rb_io_t *fptr)
{
int i, converted, iovcnt = argc + 1;
long n;
@@ -1733,7 +1882,7 @@ iovcnt_ok(int iovcnt)
#endif /* HAVE_WRITEV */
static VALUE
-io_writev(int argc, VALUE *argv, VALUE io)
+io_writev(int argc, const VALUE *argv, VALUE io)
{
rb_io_t *fptr;
long n;
@@ -1763,7 +1912,7 @@ io_writev(int argc, VALUE *argv, VALUE io)
/* sync at last item */
n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
}
- if (n < 0L) rb_sys_fail_path(fptr->pathv);
+ if (n < 0L) rb_sys_fail_on_write(fptr);
total = rb_fix_plus(LONG2FIX(n), total);
}
@@ -1807,13 +1956,13 @@ rb_io_write(VALUE io, VALUE str)
}
static VALUE
-rb_io_writev(VALUE io, int argc, VALUE *argv)
+rb_io_writev(VALUE io, int argc, const VALUE *argv)
{
if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
- if (io != rb_stderr && RTEST(ruby_verbose)) {
+ if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) {
VALUE klass = CLASS_OF(io);
char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
- rb_warning("%+"PRIsVALUE"%c""write is outdated interface"
+ rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface"
" which accepts just one argument",
klass, sep);
}
@@ -1874,7 +2023,7 @@ rb_io_flush_raw(VALUE io, int sync)
if (fptr->mode & FMODE_WRITABLE) {
if (io_fflush(fptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
}
if (fptr->mode & FMODE_READABLE) {
io_unread(fptr);
@@ -2243,7 +2392,7 @@ rb_io_fsync(VALUE io)
GetOpenFile(io, fptr);
if (io_fflush(fptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
rb_sys_fail_path(fptr->pathv);
return INT2FIX(0);
@@ -2292,7 +2441,7 @@ rb_io_fdatasync(VALUE io)
GetOpenFile(io, fptr);
if (io_fflush(fptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
return INT2FIX(0);
@@ -2480,6 +2629,17 @@ bufread_call(VALUE arg)
static long
io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
{
+ VALUE scheduler = rb_scheduler_current();
+ if (scheduler != Qnil && rb_scheduler_supports_io_read(scheduler)) {
+ ssize_t length = RB_NUM2SSIZE(
+ rb_scheduler_io_read(scheduler, fptr->self, str, offset, size)
+ );
+
+ if (length < 0) rb_sys_fail_path(fptr->pathv);
+
+ return length;
+ }
+
long len;
struct bufread_arg arg;
@@ -2507,7 +2667,7 @@ remain_size(rb_io_t *fptr)
)
{
if (io_fflush(fptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
pos = lseek(fptr->fd, 0, SEEK_CUR);
if (st.st_size >= pos && pos >= 0) {
siz += st.st_size - pos;
@@ -2836,6 +2996,7 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
rb_io_set_nonblock(fptr);
}
io_setstrbuf(&str, len);
+ iis.th = rb_thread_current();
iis.fd = fptr->fd;
iis.nonblock = nonblock;
iis.buf = RSTRING_PTR(str);
@@ -3017,7 +3178,7 @@ io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
rb_io_check_writable(fptr);
if (io_fflush(fptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
rb_io_set_nonblock(fptr);
n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
@@ -3808,19 +3969,6 @@ rb_io_each_line(int argc, VALUE *argv, VALUE io)
}
/*
- * This is a deprecated alias for #each_line.
- */
-
-static VALUE
-rb_io_lines(int argc, VALUE *argv, VALUE io)
-{
- rb_warn_deprecated("IO#lines", "#each_line");
- if (!rb_block_given_p())
- return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
- return rb_io_each_line(argc, argv, io);
-}
-
-/*
* call-seq:
* ios.each_byte {|byte| block } -> ios
* ios.each_byte -> an_enumerator
@@ -3850,27 +3998,14 @@ rb_io_each_byte(VALUE io)
char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
fptr->rbuf.len--;
rb_yield(INT2FIX(*p & 0xff));
+ rb_io_check_byte_readable(fptr);
errno = 0;
}
- rb_io_check_byte_readable(fptr);
READ_CHECK(fptr);
} while (io_fillbuf(fptr) >= 0);
return io;
}
-/*
- * This is a deprecated alias for #each_byte.
- */
-
-static VALUE
-rb_io_bytes(VALUE io)
-{
- rb_warn_deprecated("IO#bytes", "#each_byte");
- if (!rb_block_given_p())
- return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
- return rb_io_each_byte(io);
-}
-
static VALUE
io_getc(rb_io_t *fptr, rb_encoding *enc)
{
@@ -4013,20 +4148,6 @@ rb_io_each_char(VALUE io)
}
/*
- * This is a deprecated alias for #each_char.
- */
-
-static VALUE
-rb_io_chars(VALUE io)
-{
- rb_warn_deprecated("IO#chars", "#each_char");
- if (!rb_block_given_p())
- return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
- return rb_io_each_char(io);
-}
-
-
-/*
* call-seq:
* ios.each_codepoint {|c| block } -> ios
* ios.codepoints {|c| block } -> ios
@@ -4098,6 +4219,7 @@ rb_io_each_codepoint(VALUE io)
fptr->cbuf.off += n;
fptr->cbuf.len -= n;
rb_yield(UINT2NUM(c));
+ rb_io_check_byte_readable(fptr);
}
}
NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
@@ -4114,8 +4236,7 @@ rb_io_each_codepoint(VALUE io)
rb_yield(UINT2NUM(c));
}
else if (MBCLEN_INVALID_P(r)) {
- invalid:
- rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
+ goto invalid;
}
else if (MBCLEN_NEEDMORE_P(r)) {
char cbuf[8], *p = cbuf;
@@ -4136,24 +4257,15 @@ rb_io_each_codepoint(VALUE io)
else {
continue;
}
+ rb_io_check_byte_readable(fptr);
}
return io;
-}
-
-/*
- * This is a deprecated alias for #each_codepoint.
- */
-static VALUE
-rb_io_codepoints(VALUE io)
-{
- rb_warn_deprecated("IO#codepoints", "#each_codepoint");
- if (!rb_block_given_p())
- return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
- return rb_io_each_codepoint(io);
+ invalid:
+ rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
+ UNREACHABLE_RETURN(Qundef);
}
-
/*
* call-seq:
* ios.getc -> string or nil
@@ -4224,11 +4336,12 @@ rb_io_getbyte(VALUE io)
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
READ_CHECK(fptr);
- if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
+ VALUE r_stdout = rb_ractor_stdout();
+ if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(r_stdout, T_FILE)) {
rb_io_t *ofp;
- GetOpenFile(rb_stdout, ofp);
+ GetOpenFile(r_stdout, ofp);
if (ofp->mode & FMODE_TTY) {
- rb_io_flush(rb_stdout);
+ rb_io_flush(r_stdout);
}
}
if (io_fillbuf(fptr) < 0) {
@@ -4323,7 +4436,6 @@ rb_io_ungetc(VALUE io, VALUE c)
GetOpenFile(io, fptr);
rb_io_check_char_readable(fptr);
- if (NIL_P(c)) return Qnil;
if (FIXNUM_P(c)) {
c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
}
@@ -4483,7 +4595,6 @@ rb_io_set_close_on_exec(VALUE io, VALUE arg)
#define rb_io_set_close_on_exec rb_f_notimplement
#endif
-#define FMODE_PREP (1<<16)
#define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
@@ -4814,9 +4925,9 @@ fptr_waitpid(rb_io_t *fptr, int nohang)
{
int status;
if (fptr->pid) {
- rb_last_status_clear();
- rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
- fptr->pid = 0;
+ rb_last_status_clear();
+ rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
+ fptr->pid = 0;
}
}
@@ -5482,8 +5593,7 @@ rb_io_modestr_fmode(const char *modestr)
fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
break;
default:
- error:
- rb_raise(rb_eArgError, "invalid access mode %s", modestr);
+ goto error;
}
while (*m) {
@@ -5517,6 +5627,10 @@ rb_io_modestr_fmode(const char *modestr)
goto error;
return fmode;
+
+ error:
+ rb_raise(rb_eArgError, "invalid access mode %s", modestr);
+ UNREACHABLE_RETURN(Qundef);
}
int
@@ -5929,6 +6043,18 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
#endif
SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
ecopts = Qnil;
+ if (fmode & FMODE_BINMODE) {
+#ifdef O_BINARY
+ oflags |= O_BINARY;
+#endif
+ if (!has_enc)
+ rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
+ }
+#if DEFAULT_TEXTMODE
+ else if (NIL_P(vmode)) {
+ fmode |= DEFAULT_TEXTMODE;
+ }
+#endif
}
else {
VALUE v;
@@ -6319,7 +6445,7 @@ pipe_finalize(rb_io_t *fptr, int noraise)
#if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
int status = 0;
if (fptr->stdio_file) {
- status = pclose(fptr->stdio_file);
+ status = pclose(fptr->stdio_file);
}
fptr->fd = -1;
fptr->stdio_file = 0;
@@ -6800,6 +6926,8 @@ pipe_close(VALUE io)
return Qnil;
}
+static VALUE popen_finish(VALUE port, VALUE klass);
+
/*
* call-seq:
* IO.popen([env,] cmd, mode="r" [, opt]) -> io
@@ -6889,10 +7017,7 @@ pipe_close(VALUE io)
static VALUE
rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
{
- const char *modestr;
- VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
- int oflags, fmode;
- convconfig_t convconfig;
+ VALUE pname, pmode = Qnil, opt = Qnil, env = Qnil;
if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
@@ -6908,6 +7033,16 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
rb_error_arity(argc + ex, 1 + ex, 2 + ex);
}
}
+ return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
+}
+
+VALUE
+rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt)
+{
+ const char *modestr;
+ VALUE tmp, execarg_obj = Qnil;
+ int oflags, fmode;
+ convconfig_t convconfig;
tmp = rb_check_array_type(pname);
if (!NIL_P(tmp)) {
@@ -6935,13 +7070,18 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
modestr = rb_io_oflags_modestr(oflags);
- port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
+ return pipe_open(execarg_obj, modestr, fmode, &convconfig);
+}
+
+static VALUE
+popen_finish(VALUE port, VALUE klass)
+{
if (NIL_P(port)) {
/* child */
if (rb_block_given_p()) {
rb_yield(Qnil);
- rb_io_flush(rb_stdout);
- rb_io_flush(rb_stderr);
+ rb_io_flush(rb_ractor_stdout());
+ rb_io_flush(rb_ractor_stderr());
_exit(0);
}
return Qnil;
@@ -7277,7 +7417,7 @@ io_reopen(VALUE io, VALUE nfile)
}
if (fptr->mode & FMODE_WRITABLE) {
if (io_fflush(fptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
}
else {
flush_before_seek(fptr);
@@ -7287,7 +7427,7 @@ io_reopen(VALUE io, VALUE nfile)
}
if (orig->mode & FMODE_WRITABLE) {
if (io_fflush(orig) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
}
/* copy rb_io_t structure */
@@ -7416,7 +7556,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
if (fptr->mode & FMODE_WRITABLE) {
if (io_fflush(fptr) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(fptr);
}
fptr->rbuf.off = fptr->rbuf.len = 0;
@@ -7424,7 +7564,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
rb_io_oflags_modestr(oflags),
fptr->stdio_file);
- if (e) rb_syserr_fail_path(e, fptr->pathv);
+ if (e) rb_syserr_fail_path(e, fptr->pathv);
fptr->fd = fileno(fptr->stdio_file);
rb_fd_fix_cloexec(fptr->fd);
#ifdef USE_SETVBUF
@@ -7530,7 +7670,7 @@ rb_f_printf(int argc, VALUE *argv, VALUE _)
if (argc == 0) return Qnil;
if (RB_TYPE_P(argv[0], T_STRING)) {
- out = rb_stdout;
+ out = rb_ractor_stdout();
}
else {
out = argv[0];
@@ -7543,11 +7683,11 @@ rb_f_printf(int argc, VALUE *argv, VALUE _)
}
static void
-rb_output_fs_setter(VALUE val, ID id, VALUE *var)
+deprecated_str_setter(VALUE val, ID id, VALUE *var)
{
rb_str_setter(val, id, &val);
if (!NIL_P(val)) {
- rb_warn_deprecated("`$,'", NULL);
+ rb_warn_deprecated("`%s'", NULL, rb_id2name(id));
}
*var = val;
}
@@ -7588,6 +7728,9 @@ rb_io_print(int argc, const VALUE *argv, VALUE out)
line = rb_lastline_get();
argv = &line;
}
+ if (argc > 1 && !NIL_P(rb_output_fs)) {
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
+ }
for (i=0; i<argc; i++) {
if (!NIL_P(rb_output_fs) && i>0) {
rb_io_write(out, rb_output_fs);
@@ -7627,7 +7770,7 @@ rb_io_print(int argc, const VALUE *argv, VALUE out)
static VALUE
rb_f_print(int argc, const VALUE *argv, VALUE _)
{
- rb_io_print(argc, argv, rb_stdout);
+ rb_io_print(argc, argv, rb_ractor_stdout());
return Qnil;
}
@@ -7678,10 +7821,11 @@ rb_io_putc(VALUE io, VALUE ch)
static VALUE
rb_f_putc(VALUE recv, VALUE ch)
{
- if (recv == rb_stdout) {
+ VALUE r_stdout = rb_ractor_stdout();
+ if (recv == r_stdout) {
return rb_io_putc(recv, ch);
}
- return rb_funcallv(rb_stdout, rb_intern("putc"), 1, &ch);
+ return rb_funcallv(r_stdout, rb_intern("putc"), 1, &ch);
}
@@ -7792,52 +7936,50 @@ rb_io_puts(int argc, const VALUE *argv, VALUE out)
static VALUE
rb_f_puts(int argc, VALUE *argv, VALUE recv)
{
- if (recv == rb_stdout) {
+ VALUE r_stdout = rb_ractor_stdout();
+ if (recv == r_stdout) {
return rb_io_puts(argc, argv, recv);
}
- return rb_funcallv(rb_stdout, rb_intern("puts"), argc, argv);
+ return rb_funcallv(r_stdout, rb_intern("puts"), argc, argv);
}
-void
-rb_p(VALUE obj) /* for debug print within C code */
+static VALUE
+rb_p_write(VALUE str)
{
VALUE args[2];
- args[0] = rb_obj_as_string(rb_inspect(obj));
+ args[0] = str;
args[1] = rb_default_rs;
- if (RB_TYPE_P(rb_stdout, T_FILE) &&
- rb_method_basic_definition_p(CLASS_OF(rb_stdout), id_write)) {
- io_writev(2, args, rb_stdout);
+ VALUE r_stdout = rb_ractor_stdout();
+ if (RB_TYPE_P(r_stdout, T_FILE) &&
+ rb_method_basic_definition_p(CLASS_OF(r_stdout), id_write)) {
+ io_writev(2, args, r_stdout);
}
else {
- rb_io_writev(rb_stdout, 2, args);
+ rb_io_writev(r_stdout, 2, args);
}
+ return Qnil;
}
-struct rb_f_p_arg {
- int argc;
- VALUE *argv;
-};
+void
+rb_p(VALUE obj) /* for debug print within C code */
+{
+ rb_p_write(rb_obj_as_string(rb_inspect(obj)));
+}
static VALUE
-rb_f_p_internal(VALUE arg)
+rb_p_result(int argc, const VALUE *argv)
{
- struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
- int argc = arg1->argc;
- VALUE *argv = arg1->argv;
- int i;
VALUE ret = Qnil;
- for (i=0; i<argc; i++) {
- rb_p(argv[i]);
- }
if (argc == 1) {
ret = argv[0];
}
else if (argc > 1) {
ret = rb_ary_new4(argc, argv);
}
- if (RB_TYPE_P(rb_stdout, T_FILE)) {
- rb_io_flush(rb_stdout);
+ VALUE r_stdout = rb_ractor_stdout();
+ if (RB_TYPE_P(r_stdout, T_FILE)) {
+ rb_io_flush(r_stdout);
}
return ret;
}
@@ -7863,11 +8005,12 @@ rb_f_p_internal(VALUE arg)
static VALUE
rb_f_p(int argc, VALUE *argv, VALUE self)
{
- struct rb_f_p_arg arg;
- arg.argc = argc;
- arg.argv = argv;
-
- return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
+ int i;
+ for (i=0; i<argc; i++) {
+ VALUE inspected = rb_obj_as_string(rb_inspect(argv[i]));
+ rb_uninterruptible(rb_p_write, inspected);
+ }
+ return rb_p_result(argc, argv);
}
/*
@@ -7899,7 +8042,7 @@ rb_obj_display(int argc, VALUE *argv, VALUE self)
{
VALUE out;
- out = (!rb_check_arity(argc, 0, 1) ? rb_stdout : argv[0]);
+ out = (!rb_check_arity(argc, 0, 1) ? rb_ractor_stdout() : argv[0]);
rb_io_write(out, self);
return Qnil;
@@ -7908,7 +8051,7 @@ rb_obj_display(int argc, VALUE *argv, VALUE self)
static int
rb_stderr_to_original_p(void)
{
- return (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
+ return (rb_ractor_stderr() == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
}
void
@@ -7926,7 +8069,7 @@ rb_write_error2(const char *mesg, long len)
}
}
else {
- rb_io_write(rb_stderr, rb_str_new(mesg, len));
+ rb_io_write(rb_ractor_stderr(), rb_str_new(mesg, len));
}
}
@@ -7954,7 +8097,7 @@ rb_write_error_str(VALUE mesg)
}
else {
/* may unlock GVL, and */
- rb_io_write(rb_stderr, mesg);
+ rb_io_write(rb_ractor_stderr(), mesg);
}
}
@@ -7977,10 +8120,41 @@ must_respond_to(ID mid, VALUE val, ID id)
}
static void
-stdout_setter(VALUE val, ID id, VALUE *variable)
+stdin_setter(VALUE val, ID id, VALUE *ptr)
+{
+ rb_ractor_stdin_set(val);
+}
+
+static VALUE
+stdin_getter(ID id, VALUE *ptr)
+{
+ return rb_ractor_stdin();
+}
+
+static void
+stdout_setter(VALUE val, ID id, VALUE *ptr)
{
must_respond_to(id_write, val, id);
- *variable = val;
+ rb_ractor_stdout_set(val);
+}
+
+static VALUE
+stdout_getter(ID id, VALUE *ptr)
+{
+ return rb_ractor_stdout();
+}
+
+static void
+stderr_setter(VALUE val, ID id, VALUE *ptr)
+{
+ must_respond_to(id_write, val, id);
+ rb_ractor_stderr_set(val);
+}
+
+static VALUE
+stderr_getter(ID id, VALUE *ptr)
+{
+ return rb_ractor_stderr();
}
static VALUE
@@ -7990,6 +8164,7 @@ prep_io(int fd, int fmode, VALUE klass, const char *path)
VALUE io = io_alloc(klass);
MakeOpenFile(io, fp);
+ fp->self = io;
fp->fd = fd;
fp->mode = fmode;
if (!io_check_tty(fp)) {
@@ -8032,6 +8207,24 @@ prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
return io;
}
+VALUE
+rb_io_prep_stdin(void)
+{
+ return prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
+}
+
+VALUE
+rb_io_prep_stdout(void)
+{
+ return prep_stdio(stdout, FMODE_WRITABLE|FMODE_SIGNAL_ON_EPIPE, rb_cIO, "<STDOUT>");
+}
+
+VALUE
+rb_io_prep_stderr(void)
+{
+ return prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
+}
+
FILE *
rb_io_stdio_file(rb_io_t *fptr)
{
@@ -8055,6 +8248,7 @@ static inline rb_io_t *
rb_io_fptr_new(void)
{
rb_io_t *fp = ALLOC(rb_io_t);
+ fp->self = Qnil;
fp->fd = -1;
fp->stdio_file = NULL;
fp->mode = 0;
@@ -8087,11 +8281,12 @@ rb_io_make_open_file(VALUE obj)
Check_Type(obj, T_FILE);
if (RFILE(obj)->fptr) {
- rb_io_close(obj);
- rb_io_fptr_finalize(RFILE(obj)->fptr);
- RFILE(obj)->fptr = 0;
+ rb_io_close(obj);
+ rb_io_fptr_finalize(RFILE(obj)->fptr);
+ RFILE(obj)->fptr = 0;
}
fp = rb_io_fptr_new();
+ fp->self = obj;
RFILE(obj)->fptr = fp;
return fp;
}
@@ -8292,6 +8487,7 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io)
fmode |= FMODE_PREP;
}
MakeOpenFile(io, fp);
+ fp->self = io;
fp->fd = fd;
fp->mode = fmode;
fp->encs = convconfig;
@@ -8614,8 +8810,10 @@ argf_next_argv(VALUE argf)
int stdout_binmode = 0;
int fmode;
- if (RB_TYPE_P(rb_stdout, T_FILE)) {
- GetOpenFile(rb_stdout, fptr);
+ VALUE r_stdout = rb_ractor_stdout();
+
+ if (RB_TYPE_P(r_stdout, T_FILE)) {
+ GetOpenFile(r_stdout, fptr);
if (fptr->mode & FMODE_BINMODE)
stdout_binmode = 1;
}
@@ -8666,8 +8864,8 @@ argf_next_argv(VALUE argf)
VALUE str;
int fw;
- if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) {
- rb_io_close(rb_stdout);
+ if (RB_TYPE_P(r_stdout, T_FILE) && r_stdout != orig_stdout) {
+ rb_io_close(r_stdout);
}
fstat(fr, &st);
str = filename;
@@ -8736,7 +8934,7 @@ argf_next_argv(VALUE argf)
}
#endif
write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
- rb_stdout = write_io;
+ rb_ractor_stdout_set(write_io);
if (stdout_binmode) rb_io_binmode(rb_stdout);
}
fmode = FMODE_READABLE;
@@ -8776,7 +8974,7 @@ argf_next_argv(VALUE argf)
ARGF.filename = rb_str_new2("-");
if (ARGF.inplace) {
rb_warn("Can't do inplace edit for stdio");
- rb_stdout = orig_stdout;
+ rb_ractor_stdout_set(orig_stdout);
}
}
if (ARGF.init_p == -1) ARGF.init_p = 1;
@@ -10052,7 +10250,8 @@ rb_f_syscall(int argc, VALUE *argv, VALUE _)
int i;
if (RTEST(ruby_verbose)) {
- rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
+ rb_category_warning(RB_WARN_CATEGORY_DEPRECATED,
+ "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
}
if (argc == 0)
@@ -10811,13 +11010,39 @@ maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
return FALSE;
}
+struct wait_for_single_fd {
+ VALUE scheduler;
+
+ int fd;
+ short events;
+
+ VALUE result;
+};
+
+static void *
+rb_thread_scheduler_wait_for_single_fd(void * _args)
+{
+ struct wait_for_single_fd *args = (struct wait_for_single_fd *)_args;
+
+ args->result = rb_scheduler_io_wait(args->scheduler, rb_io_from_fd(args->fd), INT2NUM(args->events), Qnil);
+
+ return NULL;
+}
+
#if USE_POLL
# define IOWAIT_SYSCALL "poll"
STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
static int
-nogvl_wait_for_single_fd(int fd, short events)
+nogvl_wait_for_single_fd(VALUE th, int fd, short events)
{
+ VALUE scheduler = rb_thread_scheduler_current(th);
+ if (scheduler != Qnil) {
+ struct wait_for_single_fd args = {.scheduler = scheduler, .fd = fd, .events = events};
+ rb_thread_call_with_gvl(rb_thread_scheduler_wait_for_single_fd, &args);
+ return RTEST(args.result);
+ }
+
struct pollfd fds;
fds.fd = fd;
@@ -10828,8 +11053,15 @@ nogvl_wait_for_single_fd(int fd, short events)
#else /* !USE_POLL */
# define IOWAIT_SYSCALL "select"
static int
-nogvl_wait_for_single_fd(int fd, short events)
+nogvl_wait_for_single_fd(VALUE th, int fd, short events)
{
+ VALUE scheduler = rb_thread_scheduler_current(th);
+ if (scheduler != Qnil) {
+ struct wait_for_single_fd args = {.scheduler = scheduler, .fd = fd, .events = events};
+ rb_thread_call_with_gvl(rb_thread_scheduler_wait_for_single_fd, &args);
+ return RTEST(args.result);
+ }
+
rb_fdset_t fds;
int ret;
@@ -10862,7 +11094,7 @@ maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
ret = rb_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN, NULL);
}
else {
- ret = nogvl_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN);
+ ret = nogvl_wait_for_single_fd(stp->th, stp->src_fd, RB_WAITFD_IN);
}
} while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
@@ -10880,7 +11112,7 @@ nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
int ret;
do {
- ret = nogvl_wait_for_single_fd(stp->dst_fd, RB_WAITFD_OUT);
+ ret = nogvl_wait_for_single_fd(stp->th, stp->dst_fd, RB_WAITFD_OUT);
} while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
if (ret < 0) {
@@ -10891,10 +11123,6 @@ nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
return 0;
}
-#if defined HAVE_COPY_FILE_RANGE || (defined __linux__ && defined __NR_copy_file_range)
-# define USE_COPY_FILE_RANGE
-#endif
-
#ifdef USE_COPY_FILE_RANGE
static ssize_t
@@ -11195,6 +11423,11 @@ nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
#ifdef ENOSYS
case ENOSYS:
#endif
+#ifdef EOPNOTSUP
+ /* some RedHat kernels may return EOPNOTSUP on an NFS mount.
+ see also: [Feature #16965] */
+ case EOPNOTSUP:
+#endif
return 0;
case EAGAIN:
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
@@ -11576,7 +11809,7 @@ copy_stream_body(VALUE arg)
read_buffered_data(RSTRING_PTR(str), len, src_fptr);
if (dst_fptr) { /* IO or filename */
if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
- rb_sys_fail(0);
+ rb_sys_fail_on_write(dst_fptr);
}
else /* others such as StringIO */
rb_io_write(dst_io, str);
@@ -12123,7 +12356,7 @@ argf_read(int argc, VALUE *argv, VALUE argf)
long slen = RSTRING_LEN(str);
if (slen < len) {
len -= slen;
- argv[0] = INT2NUM(len);
+ argv[0] = LONG2NUM(len);
goto retry;
}
}
@@ -12488,23 +12721,7 @@ argf_each_line(int argc, VALUE *argv, VALUE argf)
}
/*
- * This is a deprecated alias for #each_line.
- */
-
-static VALUE
-argf_lines(int argc, VALUE *argv, VALUE argf)
-{
- rb_warn_deprecated("ARGF#lines", "#each_line");
- if (!rb_block_given_p())
- return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
- return argf_each_line(argc, argv, argf);
-}
-
-/*
* call-seq:
- * ARGF.bytes {|byte| block } -> ARGF
- * ARGF.bytes -> an_enumerator
- *
* ARGF.each_byte {|byte| block } -> ARGF
* ARGF.each_byte -> an_enumerator
*
@@ -12535,19 +12752,6 @@ argf_each_byte(VALUE argf)
}
/*
- * This is a deprecated alias for #each_byte.
- */
-
-static VALUE
-argf_bytes(VALUE argf)
-{
- rb_warn_deprecated("ARGF#bytes", "#each_byte");
- if (!rb_block_given_p())
- return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
- return argf_each_byte(argf);
-}
-
-/*
* call-seq:
* ARGF.each_char {|char| block } -> ARGF
* ARGF.each_char -> an_enumerator
@@ -12574,19 +12778,6 @@ argf_each_char(VALUE argf)
}
/*
- * This is a deprecated alias for #each_char.
- */
-
-static VALUE
-argf_chars(VALUE argf)
-{
- rb_warn_deprecated("ARGF#chars", "#each_char");
- if (!rb_block_given_p())
- return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
- return argf_each_char(argf);
-}
-
-/*
* call-seq:
* ARGF.each_codepoint {|codepoint| block } -> ARGF
* ARGF.each_codepoint -> an_enumerator
@@ -12613,19 +12804,6 @@ argf_each_codepoint(VALUE argf)
}
/*
- * This is a deprecated alias for #each_codepoint.
- */
-
-static VALUE
-argf_codepoints(VALUE argf)
-{
- rb_warn_deprecated("ARGF#codepoints", "#each_codepoint");
- if (!rb_block_given_p())
- return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
- return argf_each_codepoint(argf);
-}
-
-/*
* call-seq:
* ARGF.filename -> String
* ARGF.path -> String
@@ -12871,7 +13049,7 @@ opt_i_set(VALUE val, ID id, VALUE *var)
void
ruby_set_inplace_mode(const char *suffix)
{
- ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_fstring_cstr(suffix);
+ ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_str_new(suffix, strlen(suffix));
}
/*
@@ -12935,53 +13113,55 @@ argf_write(VALUE argf, VALUE str)
}
void
-rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
+rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg)
{
- rb_readwrite_syserr_fail(writable, errno, mesg);
+ rb_readwrite_syserr_fail(waiting, errno, mesg);
}
void
-rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
+rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *mesg)
{
- VALUE arg;
+ VALUE arg, c = Qnil;
arg = mesg ? rb_str_new2(mesg) : Qnil;
- if (writable == RB_IO_WAIT_WRITABLE) {
+ switch (waiting) {
+ case RB_IO_WAIT_WRITABLE:
switch (n) {
case EAGAIN:
- rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitWritable));
+ c = rb_eEAGAINWaitWritable;
break;
#if EAGAIN != EWOULDBLOCK
case EWOULDBLOCK:
- rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitWritable));
+ c = rb_eEWOULDBLOCKWaitWritable;
break;
#endif
case EINPROGRESS:
- rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitWritable));
+ c = rb_eEINPROGRESSWaitWritable;
break;
default:
- rb_mod_sys_fail_str(rb_mWaitWritable, arg);
+ rb_mod_syserr_fail_str(rb_mWaitWritable, n, arg);
}
- }
- else if (writable == RB_IO_WAIT_READABLE) {
+ break;
+ case RB_IO_WAIT_READABLE:
switch (n) {
case EAGAIN:
- rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitReadable));
+ c = rb_eEAGAINWaitReadable;
break;
#if EAGAIN != EWOULDBLOCK
case EWOULDBLOCK:
- rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitReadable));
+ c = rb_eEWOULDBLOCKWaitReadable;
break;
#endif
case EINPROGRESS:
- rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitReadable));
+ c = rb_eEINPROGRESSWaitReadable;
break;
default:
- rb_mod_sys_fail_str(rb_mWaitReadable, arg);
+ rb_mod_syserr_fail_str(rb_mWaitReadable, n, arg);
}
+ break;
+ default:
+ rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
}
- else {
- rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
- }
+ rb_exc_raise(rb_class_new_instance(1, &arg, c));
}
static VALUE
@@ -13154,9 +13334,6 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
void
Init_IO(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
VALUE rb_cARGF;
#ifdef __CYGWIN__
#include <sys/cygwin.h>
@@ -13174,12 +13351,12 @@ Init_IO(void)
rb_eIOError = rb_define_class("IOError", rb_eStandardError);
rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
- id_write = rb_intern("write");
- id_read = rb_intern("read");
- id_getc = rb_intern("getc");
- id_flush = rb_intern("flush");
- id_readpartial = rb_intern("readpartial");
- id_set_encoding = rb_intern("set_encoding");
+ id_write = rb_intern_const("write");
+ id_read = rb_intern_const("read");
+ id_getc = rb_intern_const("getc");
+ id_flush = rb_intern_const("flush");
+ id_readpartial = rb_intern_const("readpartial");
+ id_set_encoding = rb_intern_const("set_encoding");
rb_define_global_function("syscall", rb_f_syscall, -1);
@@ -13202,6 +13379,10 @@ Init_IO(void)
rb_cIO = rb_define_class("IO", rb_cObject);
rb_include_module(rb_cIO, rb_mEnumerable);
+ rb_define_const(rb_cIO, "READABLE", INT2NUM(RUBY_IO_READABLE));
+ rb_define_const(rb_cIO, "WRITABLE", INT2NUM(RUBY_IO_WRITABLE));
+ rb_define_const(rb_cIO, "PRIORITY", INT2NUM(RUBY_IO_PRIORITY));
+
/* exception to wait for reading. see IO.select. */
rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
/* exception to wait for writing. see IO.select. */
@@ -13259,17 +13440,18 @@ Init_IO(void)
rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
rb_output_fs = Qnil;
- rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_output_fs_setter);
+ rb_define_hooked_variable("$,", &rb_output_fs, 0, deprecated_str_setter);
rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
rb_gc_register_mark_object(rb_default_rs);
rb_rs = rb_default_rs;
rb_output_rs = Qnil;
- rb_define_hooked_variable("$/", &rb_rs, 0, rb_str_setter);
- rb_define_hooked_variable("$-0", &rb_rs, 0, rb_str_setter);
- rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_str_setter);
+ rb_define_hooked_variable("$/", &rb_rs, 0, deprecated_str_setter);
+ rb_define_hooked_variable("$-0", &rb_rs, 0, deprecated_str_setter);
+ rb_define_hooked_variable("$\\", &rb_output_rs, 0, deprecated_str_setter);
rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
+ rb_gvar_ractor_local("$_");
rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
@@ -13284,10 +13466,6 @@ Init_IO(void)
rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
- rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
- rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
- rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
- rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
@@ -13372,13 +13550,24 @@ Init_IO(void)
rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
- rb_define_variable("$stdin", &rb_stdin);
- rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
- rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
- rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
- rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
- rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
- rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
+ rb_define_virtual_variable("$stdin", stdin_getter, stdin_setter);
+ rb_define_virtual_variable("$stdout", stdout_getter, stdout_setter);
+ rb_define_virtual_variable("$>", stdout_getter, stdout_setter);
+ rb_define_virtual_variable("$stderr", stderr_getter, stderr_setter);
+
+ rb_gvar_ractor_local("$stdin");
+ rb_gvar_ractor_local("$stdout");
+ rb_gvar_ractor_local("$>");
+ rb_gvar_ractor_local("$stderr");
+
+ rb_stdin = rb_io_prep_stdin();
+ rb_stdout = rb_io_prep_stdout();
+ rb_stderr = rb_io_prep_stderr();
+
+ rb_global_variable(&rb_stdin);
+ rb_global_variable(&rb_stdout);
+ rb_global_variable(&rb_stderr);
+
orig_stdout = rb_stdout;
orig_stderr = rb_stderr;
@@ -13415,10 +13604,6 @@ Init_IO(void)
rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
- rb_define_method(rb_cARGF, "lines", argf_lines, -1);
- rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
- rb_define_method(rb_cARGF, "chars", argf_chars, 0);
- rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
rb_define_method(rb_cARGF, "read", argf_read, -1);
rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
@@ -13480,6 +13665,8 @@ Init_IO(void)
ARGF.filename = rb_str_new2("-");
rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
+ rb_gvar_ractor_local("$-i");
+
rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
#if defined (_WIN32) || defined(__CYGWIN__)
@@ -13490,39 +13677,33 @@ Init_IO(void)
rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
- sym_mode = ID2SYM(rb_intern("mode"));
- sym_perm = ID2SYM(rb_intern("perm"));
- sym_flags = ID2SYM(rb_intern("flags"));
- sym_extenc = ID2SYM(rb_intern("external_encoding"));
- sym_intenc = ID2SYM(rb_intern("internal_encoding"));
+ sym_mode = ID2SYM(rb_intern_const("mode"));
+ sym_perm = ID2SYM(rb_intern_const("perm"));
+ sym_flags = ID2SYM(rb_intern_const("flags"));
+ sym_extenc = ID2SYM(rb_intern_const("external_encoding"));
+ sym_intenc = ID2SYM(rb_intern_const("internal_encoding"));
sym_encoding = ID2SYM(rb_id_encoding());
- sym_open_args = ID2SYM(rb_intern("open_args"));
- sym_textmode = ID2SYM(rb_intern("textmode"));
- sym_binmode = ID2SYM(rb_intern("binmode"));
- sym_autoclose = ID2SYM(rb_intern("autoclose"));
- sym_normal = ID2SYM(rb_intern("normal"));
- sym_sequential = ID2SYM(rb_intern("sequential"));
- sym_random = ID2SYM(rb_intern("random"));
- sym_willneed = ID2SYM(rb_intern("willneed"));
- sym_dontneed = ID2SYM(rb_intern("dontneed"));
- sym_noreuse = ID2SYM(rb_intern("noreuse"));
- sym_SET = ID2SYM(rb_intern("SET"));
- sym_CUR = ID2SYM(rb_intern("CUR"));
- sym_END = ID2SYM(rb_intern("END"));
+ sym_open_args = ID2SYM(rb_intern_const("open_args"));
+ sym_textmode = ID2SYM(rb_intern_const("textmode"));
+ sym_binmode = ID2SYM(rb_intern_const("binmode"));
+ sym_autoclose = ID2SYM(rb_intern_const("autoclose"));
+ sym_normal = ID2SYM(rb_intern_const("normal"));
+ sym_sequential = ID2SYM(rb_intern_const("sequential"));
+ sym_random = ID2SYM(rb_intern_const("random"));
+ sym_willneed = ID2SYM(rb_intern_const("willneed"));
+ sym_dontneed = ID2SYM(rb_intern_const("dontneed"));
+ sym_noreuse = ID2SYM(rb_intern_const("noreuse"));
+ sym_SET = ID2SYM(rb_intern_const("SET"));
+ sym_CUR = ID2SYM(rb_intern_const("CUR"));
+ sym_END = ID2SYM(rb_intern_const("END"));
#ifdef SEEK_DATA
- sym_DATA = ID2SYM(rb_intern("DATA"));
+ sym_DATA = ID2SYM(rb_intern_const("DATA"));
#endif
#ifdef SEEK_HOLE
- sym_HOLE = ID2SYM(rb_intern("HOLE"));
+ sym_HOLE = ID2SYM(rb_intern_const("HOLE"));
#endif
- sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
- sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
+ sym_wait_readable = ID2SYM(rb_intern_const("wait_readable"));
+ sym_wait_writable = ID2SYM(rb_intern_const("wait_writable"));
}
#include "io.rbinc"
-
-void
-Init_IO_nonblock(void)
-{
- load_io();
-}
diff --git a/io.rb b/io.rb
index 1b6dddf9e5..40873ea4fd 100644
--- a/io.rb
+++ b/io.rb
@@ -60,7 +60,7 @@ class IO
# return the symbol +:wait_readable+ instead. At EOF, it will return nil
# instead of raising EOFError.
def read_nonblock(len, buf = nil, exception: true)
- __builtin_io_read_nonblock(len, buf, exception)
+ Primitive.io_read_nonblock(len, buf, exception)
end
# call-seq:
@@ -118,6 +118,6 @@ class IO
# that write_nonblock should not raise an IO::WaitWritable exception, but
# return the symbol +:wait_writable+ instead.
def write_nonblock(buf, exception: true)
- __builtin_io_write_nonblock(buf, exception)
+ Primitive.io_write_nonblock(buf, exception)
end
end
diff --git a/iseq.c b/iseq.c
index 46066938c7..2d83bc3f06 100644
--- a/iseq.c
+++ b/iseq.c
@@ -9,25 +9,39 @@
**********************************************************************/
-#include "internal.h"
-#include "ruby/util.h"
-#include "eval_intern.h"
+#define RUBY_VM_INSNS_INFO 1
+/* #define RUBY_MARK_FREE_DEBUG 1 */
+
+#include "ruby/internal/config.h"
#ifdef HAVE_DLADDR
# include <dlfcn.h>
#endif
-#define RUBY_VM_INSNS_INFO 1
-/* #define RUBY_MARK_FREE_DEBUG 1 */
+#include "eval_intern.h"
#include "gc.h"
-#include "vm_core.h"
-#include "iseq.h"
#include "id_table.h"
-#include "builtin.h"
+#include "internal.h"
+#include "internal/bits.h"
+#include "internal/class.h"
+#include "internal/compile.h"
+#include "internal/error.h"
+#include "internal/file.h"
+#include "internal/hash.h"
+#include "internal/parse.h"
+#include "internal/sanitizers.h"
+#include "internal/symbol.h"
+#include "internal/thread.h"
+#include "internal/variable.h"
+#include "iseq.h"
+#include "mjit.h"
+#include "ruby/util.h"
+#include "vm_core.h"
+#include "vm_callinfo.h"
+#include "builtin.h"
#include "insns.inc"
#include "insns_info.inc"
-#include "mjit.h"
VALUE rb_cISeq;
static VALUE iseqw_new(const rb_iseq_t *iseq);
@@ -55,6 +69,8 @@ obj_resurrect(VALUE obj)
case T_HASH:
obj = rb_hash_resurrect(obj);
break;
+ default:
+ break;
}
}
return obj;
@@ -104,12 +120,6 @@ rb_iseq_free(const rb_iseq_t *iseq)
ruby_xfree((void *)body->is_entries);
if (body->call_data) {
- unsigned int i;
- struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size];
- for (i=0; i<body->ci_kw_size; i++) {
- const struct rb_call_info_kw_arg *kw_arg = kw_calls[i].ci_kw.kw_arg;
- ruby_xfree((void *)kw_arg);
- }
ruby_xfree(body->call_data);
}
ruby_xfree((void *)body->catch_table);
@@ -120,6 +130,7 @@ rb_iseq_free(const rb_iseq_t *iseq)
ruby_xfree((void *)body->param.keyword);
}
compile_data_free(ISEQ_COMPILE_DATA(iseq));
+ if (body->outer_variables) rb_id_table_free(body->outer_variables);
ruby_xfree(body);
}
@@ -171,6 +182,31 @@ iseq_extract_values(VALUE *code, size_t pos, iseq_value_itr_t * func, void *data
}
}
break;
+ case TS_IC:
+ {
+ IC ic = (IC)code[pos + op_no + 1];
+ if (ic->entry) {
+ VALUE nv = func(data, (VALUE)ic->entry);
+ if ((VALUE)ic->entry != nv) {
+ ic->entry = (void *)nv;
+ }
+ }
+ }
+ break;
+ case TS_IVC:
+ {
+ IVC ivc = (IVC)code[pos + op_no + 1];
+ if (ivc->entry) {
+ if (RB_TYPE_P(ivc->entry->class_value, T_NONE)) {
+ rb_bug("!! %u", ivc->entry->index);
+ }
+ VALUE nv = func(data, ivc->entry->class_value);
+ if (ivc->entry->class_value != nv) {
+ ivc->entry->class_value = nv;
+ }
+ }
+ }
+ break;
case TS_ISE:
{
union iseq_inline_storage_entry *const is = (union iseq_inline_storage_entry *)code[pos + op_no + 1];
@@ -198,7 +234,7 @@ rb_iseq_each_value(const rb_iseq_t *iseq, iseq_value_itr_t * func, void *data)
size_t n;
rb_vm_insns_translator_t *const translator =
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
- (FL_TEST(iseq, ISEQ_TRANSLATED)) ? rb_vm_insn_addr2insn2 :
+ (FL_TEST((VALUE)iseq, ISEQ_TRANSLATED)) ? rb_vm_insn_addr2insn2 :
#endif
rb_vm_insn_null_translator;
const struct rb_iseq_constant_body *const body = iseq->body;
@@ -234,7 +270,16 @@ rb_iseq_update_references(rb_iseq_t *iseq)
if (body->parent_iseq) {
body->parent_iseq = (struct rb_iseq_struct *)rb_gc_location((VALUE)body->parent_iseq);
}
- if (FL_TEST(iseq, ISEQ_MARKABLE_ISEQ)) {
+ if (body->call_data) {
+ for (unsigned int i=0; i<body->ci_size; i++) {
+ struct rb_call_data *cds = body->call_data;
+ if (!SPECIAL_CONST_P((VALUE)cds[i].ci)) {
+ cds[i].ci = (struct rb_callinfo *)rb_gc_location((VALUE)cds[i].ci);
+ }
+ cds[i].cc = (struct rb_callcache *)rb_gc_location((VALUE)cds[i].cc);
+ }
+ }
+ if (FL_TEST((VALUE)iseq, ISEQ_MARKABLE_ISEQ)) {
rb_iseq_each_value(iseq, update_each_insn_value, NULL);
VALUE *original_iseq = ISEQ_ORIGINAL_ISEQ(iseq);
if (original_iseq) {
@@ -293,7 +338,7 @@ rb_iseq_mark(const rb_iseq_t *iseq)
if (iseq->body) {
const struct rb_iseq_constant_body *const body = iseq->body;
- if (FL_TEST(iseq, ISEQ_MARKABLE_ISEQ)) {
+ if (FL_TEST((VALUE)iseq, ISEQ_MARKABLE_ISEQ)) {
rb_iseq_each_value(iseq, each_insn_value, NULL);
}
@@ -302,7 +347,27 @@ rb_iseq_mark(const rb_iseq_t *iseq)
rb_gc_mark_movable(body->location.label);
rb_gc_mark_movable(body->location.base_label);
rb_gc_mark_movable(body->location.pathobj);
- RUBY_MARK_NO_PIN_UNLESS_NULL((VALUE)body->parent_iseq);
+ RUBY_MARK_MOVABLE_UNLESS_NULL((VALUE)body->parent_iseq);
+
+ if (body->call_data) {
+ struct rb_call_data *cds = (struct rb_call_data *)body->call_data;
+ for (unsigned int i=0; i<body->ci_size; i++) {
+ const struct rb_callinfo *ci = cds[i].ci;
+ const struct rb_callcache *cc = cds[i].cc;
+
+ if (vm_ci_markable(ci)) {
+ rb_gc_mark_movable((VALUE)ci);
+ }
+ if (cc && vm_cc_markable(cc)) {
+ if (!vm_cc_invalidated_p(cc)) {
+ rb_gc_mark_movable((VALUE)cc);
+ }
+ else {
+ cds[i].cc = rb_vm_empty_cc();
+ }
+ }
+ }
+ }
if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) {
const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
@@ -329,12 +394,16 @@ rb_iseq_mark(const rb_iseq_t *iseq)
}
}
}
+
+#if USE_MJIT
+ mjit_mark_cc_entries(body);
+#endif
}
- if (FL_TEST_RAW(iseq, ISEQ_NOT_LOADED_YET)) {
+ if (FL_TEST_RAW((VALUE)iseq, ISEQ_NOT_LOADED_YET)) {
rb_gc_mark(iseq->aux.loader.obj);
}
- else if (FL_TEST_RAW(iseq, ISEQ_USE_COMPILE_DATA)) {
+ else if (FL_TEST_RAW((VALUE)iseq, ISEQ_USE_COMPILE_DATA)) {
const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
rb_iseq_mark_insn_storage(compile_data->insn.storage_head);
@@ -379,8 +448,6 @@ rb_iseq_memsize(const rb_iseq_t *iseq)
/* TODO: should we count original_iseq? */
if (ISEQ_EXECUTABLE_P(iseq) && body) {
- struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size];
-
size += sizeof(struct rb_iseq_constant_body);
size += body->iseq_size * sizeof(VALUE);
size += body->insns_info.size * (sizeof(struct iseq_insn_info_entry) + sizeof(unsigned int));
@@ -396,19 +463,7 @@ rb_iseq_memsize(const rb_iseq_t *iseq)
/* body->call_data */
size += body->ci_size * sizeof(struct rb_call_data);
- size += body->ci_kw_size * sizeof(struct rb_kwarg_call_data);
-
- if (kw_calls) {
- unsigned int i;
-
- for (i = 0; i < body->ci_kw_size; i++) {
- const struct rb_call_info_kw_arg *kw_arg = kw_calls[i].ci_kw.kw_arg;
-
- if (kw_arg) {
- size += rb_call_info_kw_arg_bytes(kw_arg->keyword_len);
- }
- }
- }
+ // TODO: should we count imemo_callinfo?
}
compile_data = ISEQ_COMPILE_DATA(iseq);
@@ -427,14 +482,11 @@ rb_iseq_memsize(const rb_iseq_t *iseq)
return size;
}
-static uintptr_t fresh_iseq_unique_id = 0; /* -- Remove In 3.0 -- */
-
struct rb_iseq_constant_body *
rb_iseq_constant_body_alloc(void)
{
struct rb_iseq_constant_body *iseq_body;
iseq_body = ZALLOC(struct rb_iseq_constant_body);
- iseq_body->iseq_unique_id = fresh_iseq_unique_id++; /* -- Remove In 3.0 -- */
return iseq_body;
}
@@ -539,8 +591,7 @@ new_arena(void)
static VALUE
prepare_iseq_build(rb_iseq_t *iseq,
VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_code_location_t *code_location, const int node_id,
- const rb_iseq_t *parent, enum iseq_type type,
- const rb_compile_option_t *option)
+ const rb_iseq_t *parent, int isolated_depth, enum iseq_type type, const rb_compile_option_t *option)
{
VALUE coverage = Qfalse;
VALUE err_info = Qnil;
@@ -567,12 +618,12 @@ prepare_iseq_build(rb_iseq_t *iseq,
ISEQ_COMPILE_DATA(iseq)->node.storage_head = ISEQ_COMPILE_DATA(iseq)->node.storage_current = new_arena();
ISEQ_COMPILE_DATA(iseq)->insn.storage_head = ISEQ_COMPILE_DATA(iseq)->insn.storage_current = new_arena();
+ ISEQ_COMPILE_DATA(iseq)->isolated_depth = isolated_depth;
ISEQ_COMPILE_DATA(iseq)->option = option;
-
ISEQ_COMPILE_DATA(iseq)->ivar_cache_table = NULL;
-
ISEQ_COMPILE_DATA(iseq)->builtin_function_table = GET_VM()->builtin_function_table;
+
if (option->coverage_enabled) {
VALUE coverages = rb_get_coverages();
if (RTEST(coverages)) {
@@ -595,6 +646,7 @@ void
rb_iseq_insns_info_encode_positions(const rb_iseq_t *iseq)
{
#if VM_INSN_INFO_TABLE_IMPL == 2
+ /* create succ_index_table */
struct rb_iseq_constant_body *const body = iseq->body;
int size = body->insns_info.size;
int max_pos = body->iseq_size;
@@ -637,13 +689,6 @@ finish_iseq_build(rb_iseq_t *iseq)
ISEQ_COMPILE_DATA_CLEAR(iseq);
compile_data_free(data);
-#if VM_INSN_INFO_TABLE_IMPL == 2 /* succinct bitvector */
- /* create succ_index_table */
- if (body->insns_info.succ_index_table == NULL) {
- rb_iseq_insns_info_encode_positions(iseq);
- }
-#endif
-
#if VM_CHECK_MODE > 0 && VM_INSN_INFO_TABLE_IMPL > 0
validate_get_insn_info(iseq);
#endif
@@ -655,6 +700,9 @@ finish_iseq_build(rb_iseq_t *iseq)
rb_exc_raise(err);
}
+ RB_DEBUG_COUNTER_INC(iseq_num);
+ RB_DEBUG_COUNTER_ADD(iseq_cd_num, iseq->body->ci_size);
+
rb_iseq_init_trace(iseq);
return Qtrue;
}
@@ -761,8 +809,8 @@ rb_iseq_t *
rb_iseq_new(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath,
const rb_iseq_t *parent, enum iseq_type type)
{
- return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, type,
- &COMPILE_OPTION_DEFAULT);
+ return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent,
+ 0, type, &COMPILE_OPTION_DEFAULT);
}
rb_iseq_t *
@@ -777,8 +825,8 @@ rb_iseq_new_top(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath
}
}
- return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, ISEQ_TYPE_TOP,
- &COMPILE_OPTION_DEFAULT);
+ return rb_iseq_new_with_opt(ast, name, path, realpath, INT2FIX(0), parent, 0,
+ ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT);
}
rb_iseq_t *
@@ -786,7 +834,14 @@ rb_iseq_new_main(const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_
{
return rb_iseq_new_with_opt(ast, rb_fstring_lit("<main>"),
path, realpath, INT2FIX(0),
- parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
+ parent, 0, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT);
+}
+
+rb_iseq_t *
+rb_iseq_new_eval(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth)
+{
+ return rb_iseq_new_with_opt(ast, name, path, realpath, first_lineno,
+ parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT);
}
static inline rb_iseq_t *
@@ -805,18 +860,23 @@ iseq_translate(rb_iseq_t *iseq)
rb_iseq_t *
rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath,
- VALUE first_lineno, const rb_iseq_t *parent,
- enum iseq_type type, const rb_compile_option_t *option)
+ VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth,
+ enum iseq_type type, const rb_compile_option_t *option)
{
const NODE *node = ast ? ast->root : 0;
/* TODO: argument check */
rb_iseq_t *iseq = iseq_alloc();
rb_compile_option_t new_opt;
- new_opt = option ? *option : COMPILE_OPTION_DEFAULT;
+ if (option) {
+ new_opt = *option;
+ }
+ else {
+ new_opt = COMPILE_OPTION_DEFAULT;
+ }
if (ast && ast->compile_option) rb_iseq_make_compile_option(&new_opt, ast->compile_option);
- prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1, parent, type, &new_opt);
+ prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1, parent, isolated_depth, type, &new_opt);
rb_iseq_compile_node(iseq, node);
finish_iseq_build(iseq);
@@ -835,12 +895,12 @@ rb_iseq_new_with_callback(
rb_iseq_t *iseq = iseq_alloc();
if (!option) option = &COMPILE_OPTION_DEFAULT;
- prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, type, option);
+ prepare_iseq_build(iseq, name, path, realpath, first_lineno, NULL, -1, parent, 0, type, option);
rb_iseq_compile_callback(iseq, ifunc);
finish_iseq_build(iseq);
- return iseq_translate(iseq);
+ return iseq;
}
const rb_iseq_t *
@@ -948,7 +1008,7 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt)
make_compile_option(&option, opt);
option.peephole_optimization = FALSE; /* because peephole optimization can modify original iseq */
prepare_iseq_build(iseq, name, path, realpath, first_lineno, &tmp_loc, NUM2INT(node_id),
- parent, (enum iseq_type)iseq_type, &option);
+ parent, 0, (enum iseq_type)iseq_type, &option);
rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body);
@@ -1016,7 +1076,7 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
else {
INITIALIZED VALUE label = rb_fstring_lit("<compiled>");
iseq = rb_iseq_new_with_opt(&ast->body, label, file, realpath, line,
- 0, ISEQ_TYPE_TOP, &option);
+ NULL, 0, ISEQ_TYPE_TOP, &option);
rb_ast_dispose(ast);
}
@@ -1258,7 +1318,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
parser = rb_parser_new();
rb_parser_set_context(parser, NULL, FALSE);
- ast = rb_parser_compile_file_path(parser, file, f, NUM2INT(line));
+ ast = (rb_ast_t *)rb_parser_load_file(parser, file);
if (!ast->body.root) exc = GET_EC()->errinfo;
rb_io_close(f);
@@ -1272,7 +1332,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
ret = iseqw_new(rb_iseq_new_with_opt(&ast->body, rb_fstring_lit("<main>"),
file,
rb_realpath_internal(Qnil, file, 1),
- line, NULL, ISEQ_TYPE_TOP, &option));
+ line, NULL, 0, ISEQ_TYPE_TOP, &option));
rb_ast_dispose(ast);
return ret;
}
@@ -1823,6 +1883,7 @@ local_var_name(const rb_iseq_t *diseq, VALUE level, VALUE op)
}
int rb_insn_unified_local_var_level(VALUE);
+VALUE rb_dump_literal(VALUE lit);
VALUE
rb_insn_operand_intern(const rb_iseq_t *iseq,
@@ -1898,7 +1959,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
break;
}
}
- ret = rb_inspect(op);
+ ret = rb_dump_literal(op);
if (CLASS_OF(op) == rb_cISeq) {
if (child) {
rb_ary_push(child, op);
@@ -1920,12 +1981,6 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
}
break;
}
- case TS_GENTRY:
- {
- struct rb_global_entry *entry = (struct rb_global_entry *)op;
- ret = rb_str_dup(rb_id2str(entry->id));
- }
- break;
case TS_IC:
case TS_IVC:
@@ -1936,24 +1991,25 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
case TS_CALLDATA:
{
struct rb_call_data *cd = (struct rb_call_data *)op;
- struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
VALUE ary = rb_ary_new();
+ ID mid = vm_ci_mid(ci);
- if (ci->mid) {
- rb_ary_push(ary, rb_sprintf("mid:%"PRIsVALUE, rb_id2str(ci->mid)));
+ if (mid) {
+ rb_ary_push(ary, rb_sprintf("mid:%"PRIsVALUE, rb_id2str(mid)));
}
- rb_ary_push(ary, rb_sprintf("argc:%d", ci->orig_argc));
+ rb_ary_push(ary, rb_sprintf("argc:%d", vm_ci_argc(ci)));
- if (ci->flag & VM_CALL_KWARG) {
- struct rb_call_info_kw_arg *kw_args = ((struct rb_call_info_with_kwarg *)ci)->kw_arg;
- VALUE kw_ary = rb_ary_new_from_values(kw_args->keyword_len, kw_args->keywords);
- rb_ary_push(ary, rb_sprintf("kw:[%"PRIsVALUE"]", rb_ary_join(kw_ary, rb_str_new2(","))));
+ if (vm_ci_flag(ci) & VM_CALL_KWARG) {
+ const struct rb_callinfo_kwarg *kw_args = vm_ci_kwarg(ci);
+ VALUE kw_ary = rb_ary_new_from_values(kw_args->keyword_len, kw_args->keywords);
+ rb_ary_push(ary, rb_sprintf("kw:[%"PRIsVALUE"]", rb_ary_join(kw_ary, rb_str_new2(","))));
}
- if (ci->flag) {
+ if (vm_ci_flag(ci)) {
VALUE flags = rb_ary_new();
-# define CALL_FLAG(n) if (ci->flag & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n))
+# define CALL_FLAG(n) if (vm_ci_flag(ci) & VM_CALL_##n) rb_ary_push(flags, rb_str_new2(#n))
CALL_FLAG(ARGS_SPLAT);
CALL_FLAG(ARGS_BLOCKARG);
CALL_FLAG(FCALL);
@@ -1965,6 +2021,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
CALL_FLAG(ZSUPER);
CALL_FLAG(KWARG);
CALL_FLAG(KW_SPLAT);
+ CALL_FLAG(KW_SPLAT_MUT);
CALL_FLAG(OPT_SEND); /* maybe not reachable */
rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|")));
}
@@ -2277,7 +2334,9 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
VALUE
rb_iseq_disasm(const rb_iseq_t *iseq)
{
- return rb_iseq_disasm_recursive(iseq, rb_str_new(0, 0));
+ VALUE str = rb_iseq_disasm_recursive(iseq, rb_str_new(0, 0));
+ rb_str_resize(str, RSTRING_LEN(str));
+ return str;
}
/*
@@ -2746,12 +2805,6 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
}
}
break;
- case TS_GENTRY:
- {
- struct rb_global_entry *entry = (struct rb_global_entry *)*seq;
- rb_ary_push(ary, ID2SYM(entry->id));
- }
- break;
case TS_IC:
case TS_IVC:
case TS_ISE:
@@ -2763,27 +2816,28 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
case TS_CALLDATA:
{
struct rb_call_data *cd = (struct rb_call_data *)*seq;
- struct rb_call_info *ci = &cd->ci;
+ const struct rb_callinfo *ci = cd->ci;
VALUE e = rb_hash_new();
- int orig_argc = ci->orig_argc;
+ int argc = vm_ci_argc(ci);
- rb_hash_aset(e, ID2SYM(rb_intern("mid")), ci->mid ? ID2SYM(ci->mid) : Qnil);
- rb_hash_aset(e, ID2SYM(rb_intern("flag")), UINT2NUM(ci->flag));
+ ID mid = vm_ci_mid(ci);
+ rb_hash_aset(e, ID2SYM(rb_intern("mid")), mid ? ID2SYM(mid) : Qnil);
+ rb_hash_aset(e, ID2SYM(rb_intern("flag")), UINT2NUM(vm_ci_flag(ci)));
- if (ci->flag & VM_CALL_KWARG) {
- struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci;
- int i;
- VALUE kw = rb_ary_new2((long)ci_kw->kw_arg->keyword_len);
+ if (vm_ci_flag(ci) & VM_CALL_KWARG) {
+ const struct rb_callinfo_kwarg *kwarg = vm_ci_kwarg(ci);
+ int i;
+ VALUE kw = rb_ary_new2((long)kwarg->keyword_len);
- orig_argc -= ci_kw->kw_arg->keyword_len;
- for (i = 0; i < ci_kw->kw_arg->keyword_len; i++) {
- rb_ary_push(kw, ci_kw->kw_arg->keywords[i]);
+ argc -= kwarg->keyword_len;
+ for (i = 0; i < kwarg->keyword_len; i++) {
+ rb_ary_push(kw, kwarg->keywords[i]);
}
rb_hash_aset(e, ID2SYM(rb_intern("kw_arg")), kw);
}
rb_hash_aset(e, ID2SYM(rb_intern("orig_argc")),
- INT2FIX(orig_argc));
+ INT2FIX(argc));
rb_ary_push(ary, e);
}
break;
@@ -3094,17 +3148,20 @@ rb_vm_encoded_insn_data_table_init(void)
encoded_insn_data = st_init_numtable_with_size(VM_INSTRUCTION_SIZE / 2);
for (insn = 0; insn < VM_INSTRUCTION_SIZE/2; insn++) {
- int traced_insn = (int)insn;
- if (traced_insn == BIN(opt_invokebuiltin_delegate_leave)) {
- traced_insn = BIN(opt_invokebuiltin_delegate); // to dispatch :return from leave
- }
st_data_t key1 = (st_data_t)INSN_CODE(insn);
- st_data_t key2 = (st_data_t)INSN_CODE(traced_insn + VM_INSTRUCTION_SIZE/2);
+ st_data_t key2 = (st_data_t)INSN_CODE(insn + VM_INSTRUCTION_SIZE/2);
insn_data[insn].insn = (int)insn;
insn_data[insn].insn_len = insn_len(insn);
- insn_data[insn].notrace_encoded_insn = (void *) key1;
- insn_data[insn].trace_encoded_insn = (void *) key2;
+
+ if (insn != BIN(opt_invokebuiltin_delegate_leave)) {
+ insn_data[insn].notrace_encoded_insn = (void *) key1;
+ insn_data[insn].trace_encoded_insn = (void *) key2;
+ }
+ else {
+ insn_data[insn].notrace_encoded_insn = (void *) INSN_CODE(BIN(opt_invokebuiltin_delegate));
+ insn_data[insn].trace_encoded_insn = (void *) INSN_CODE(BIN(opt_invokebuiltin_delegate) + VM_INSTRUCTION_SIZE/2);
+ }
st_add_direct(encoded_insn_data, key1, (st_data_t)&insn_data[insn]);
st_add_direct(encoded_insn_data, key2, (st_data_t)&insn_data[insn]);
@@ -3126,13 +3183,16 @@ rb_vm_insn_addr2insn(const void *addr)
}
static inline int
-encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon)
+encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon, bool remain_current_trace)
{
st_data_t key = (st_data_t)*iseq_encoded_insn;
st_data_t val;
if (st_lookup(encoded_insn_data, key, &val)) {
insn_data_t *e = (insn_data_t *)val;
+ if (remain_current_trace && key == (st_data_t)e->trace_encoded_insn) {
+ turnon = 1;
+ }
*iseq_encoded_insn = (VALUE) (turnon ? e->trace_encoded_insn : e->notrace_encoded_insn);
return e->insn_len;
}
@@ -3145,7 +3205,7 @@ rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos)
{
const struct rb_iseq_constant_body *const body = iseq->body;
VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
- encoded_iseq_trace_instrument(&iseq_encoded[pos], 0);
+ encoded_iseq_trace_instrument(&iseq_encoded[pos], 0, false);
}
static int
@@ -3174,7 +3234,7 @@ iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events,
if (pc_events & target_events) {
n++;
}
- pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events));
+ pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (target_events | iseq->aux.exec.global_trace_events), true);
}
if (n > 0) {
@@ -3239,7 +3299,7 @@ iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval)
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));
+ pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & (local_events | iseq->aux.exec.global_trace_events), false);
}
}
return n;
@@ -3291,7 +3351,7 @@ rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_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 & enabled_events);
+ pc += encoded_iseq_trace_instrument(&iseq_encoded[pc], pc_events & enabled_events, true);
}
}
}
diff --git a/iseq.h b/iseq.h
index 25c62a384f..bae534c71d 100644
--- a/iseq.h
+++ b/iseq.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_ISEQ_H
+#define RUBY_ISEQ_H 1
/**********************************************************************
iseq.h -
@@ -8,9 +10,8 @@
Copyright (C) 2004-2008 Koichi Sasada
**********************************************************************/
-
-#ifndef RUBY_ISEQ_H
-#define RUBY_ISEQ_H 1
+#include "internal/gc.h"
+#include "vm_core.h"
RUBY_EXTERN const int ruby_api_version[];
#define ISEQ_MAJOR_VERSION ((unsigned int)ruby_api_version[0])
@@ -23,14 +24,6 @@ typedef struct rb_iseq_struct rb_iseq_t;
extern const ID rb_iseq_shared_exc_local_tbl[];
-static inline size_t
-rb_call_info_kw_arg_bytes(int keyword_len)
-{
- return rb_size_mul_add_or_raise(
- keyword_len - 1, sizeof(VALUE), sizeof(struct rb_call_info_kw_arg),
- rb_eRuntimeError);
-}
-
#define ISEQ_COVERAGE(iseq) iseq->body->variable.coverage
#define ISEQ_COVERAGE_SET(iseq, cov) RB_OBJ_WRITE(iseq, &iseq->body->variable.coverage, cov)
#define ISEQ_LINE_COVERAGE(iseq) RARRAY_AREF(ISEQ_COVERAGE(iseq), COVERAGE_INDEX_LINES)
@@ -87,7 +80,7 @@ ISEQ_ORIGINAL_ISEQ_ALLOC(const rb_iseq_t *iseq, long size)
#define ISEQ_TRANSLATED IMEMO_FL_USER3
#define ISEQ_MARKABLE_ISEQ IMEMO_FL_USER4
-#define ISEQ_EXECUTABLE_P(iseq) (FL_TEST_RAW((iseq), ISEQ_NOT_LOADED_YET | ISEQ_USE_COMPILE_DATA) == 0)
+#define ISEQ_EXECUTABLE_P(iseq) (FL_TEST_RAW(((VALUE)iseq), ISEQ_NOT_LOADED_YET | ISEQ_USE_COMPILE_DATA) == 0)
struct iseq_compile_data {
/* GC is needed */
@@ -112,8 +105,8 @@ struct iseq_compile_data {
int last_line;
int label_no;
int node_level;
+ int isolated_depth;
unsigned int ci_index;
- unsigned int ci_kw_index;
const rb_compile_option_t *option;
struct rb_id_table *ivar_cache_table;
const struct rb_builtin_function *builtin_function_table;
diff --git a/kernel.rb b/kernel.rb
new file mode 100644
index 0000000000..04a371a7c8
--- /dev/null
+++ b/kernel.rb
@@ -0,0 +1,174 @@
+module Kernel
+ #
+ # call-seq:
+ # obj.class -> class
+ #
+ # Returns the class of <i>obj</i>. This method must always be called
+ # with an explicit receiver, as #class is also a reserved word in
+ # Ruby.
+ #
+ # 1.class #=> Integer
+ # self.class #=> Object
+ #--
+ # Equivalent to \c Object\#class in Ruby.
+ #
+ # Returns the class of \c obj, skipping singleton classes or module inclusions.
+ #++
+ #
+ def class
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_obj_class(self)'
+ end
+
+ #
+ # call-seq:
+ # obj.clone(freeze: nil) -> an_object
+ #
+ # Produces a shallow copy of <i>obj</i>---the instance variables of
+ # <i>obj</i> are copied, but not the objects they reference.
+ # #clone copies the frozen value state of <i>obj</i>, unless the
+ # +:freeze+ keyword argument is given with a false or true value.
+ # See also the discussion under Object#dup.
+ #
+ # class Klass
+ # attr_accessor :str
+ # end
+ # s1 = Klass.new #=> #<Klass:0x401b3a38>
+ # s1.str = "Hello" #=> "Hello"
+ # s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
+ # s2.str[1,4] = "i" #=> "i"
+ # s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
+ # s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
+ #
+ # This method may have class-specific behavior. If so, that
+ # behavior will be documented under the #+initialize_copy+ method of
+ # the class.
+ #
+ def clone(freeze: nil)
+ Primitive.rb_obj_clone2(freeze)
+ end
+
+ #
+ # call-seq:
+ # obj.frozen? -> true or false
+ #
+ # Returns the freeze status of <i>obj</i>.
+ #
+ # a = [ "a", "b", "c" ]
+ # a.freeze #=> ["a", "b", "c"]
+ # a.frozen? #=> true
+ #--
+ # Determines if the object is frozen. Equivalent to \c Object\#frozen? in Ruby.
+ # \param[in] obj the object to be determines
+ # \retval Qtrue if frozen
+ # \retval Qfalse if not frozen
+ #++
+ #
+ def frozen?
+ Primitive.attr! 'inline'
+ Primitive.cexpr! 'rb_obj_frozen_p(self)'
+ end
+
+ #
+ # call-seq:
+ # obj.tap {|x| block } -> obj
+ #
+ # Yields self to the block, and then returns self.
+ # The primary purpose of this method is to "tap into" a method chain,
+ # in order to perform operations on intermediate results within the chain.
+ #
+ # (1..10) .tap {|x| puts "original: #{x}" }
+ # .to_a .tap {|x| puts "array: #{x}" }
+ # .select {|x| x.even? } .tap {|x| puts "evens: #{x}" }
+ # .map {|x| x*x } .tap {|x| puts "squares: #{x}" }
+ #
+ #--
+ # \private
+ #++
+ #
+ def tap
+ yield(self)
+ self
+ end
+
+ #
+ # call-seq:
+ # obj.then {|x| block } -> an_object
+ #
+ # Yields self to the block and returns the result of the block.
+ #
+ # 3.next.then {|x| x**x }.to_s #=> "256"
+ #
+ # Good usage for +then+ is value piping in method chains:
+ #
+ # require 'open-uri'
+ # require 'json'
+ #
+ # construct_url(arguments).
+ # then {|url| open(url).read }.
+ # then {|response| JSON.parse(response) }
+ #
+ # When called without block, the method returns +Enumerator+,
+ # which can be used, for example, for conditional
+ # circuit-breaking:
+ #
+ # # meets condition, no-op
+ # 1.then.detect(&:odd?) # => 1
+ # # does not meet condition, drop value
+ # 2.then.detect(&:odd?) # => nil
+ #
+ def then
+ unless Primitive.block_given_p
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
+ end
+ yield(self)
+ end
+
+ #
+ # call-seq:
+ # obj.yield_self {|x| block } -> an_object
+ #
+ # Yields self to the block and returns the result of the block.
+ #
+ # "my string".yield_self {|s| s.upcase } #=> "MY STRING"
+ #
+ # Good usage for +then+ is value piping in method chains:
+ #
+ # require 'open-uri'
+ # require 'json'
+ #
+ # construct_url(arguments).
+ # then {|url| open(url).read }.
+ # then {|response| JSON.parse(response) }
+ #
+ def yield_self
+ unless Primitive.block_given_p
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
+ end
+ yield(self)
+ end
+
+ module_function
+
+ #
+ # call-seq:
+ # Float(arg, exception: true) -> float or nil
+ #
+ # Returns <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
+ # suppressed by passing <code>exception: false</code>.
+ #
+ # Float(1) #=> 1.0
+ # Float("123.456") #=> 123.456
+ # Float("123.0_badstring") #=> ArgumentError: invalid value for Float(): "123.0_badstring"
+ # Float(nil) #=> TypeError: can't convert nil into Float
+ # Float("123.0_badstring", exception: false) #=> nil
+ #
+ def Float(arg, exception: true)
+ Primitive.rb_f_float(arg, exception)
+ end
+end
diff --git a/lib/.document b/lib/.document
index 668152021d..0d612d1077 100644
--- a/lib/.document
+++ b/lib/.document
@@ -2,7 +2,7 @@
*.rb
-bundler
+# bundler # not in RDoc
cgi
csv
drb
@@ -11,7 +11,8 @@ irb
matrix
net
optparse
-racc
+racc/*.rb
+racc/rdoc
rdoc
rexml
rinda
diff --git a/lib/English.gemspec b/lib/English.gemspec
new file mode 100644
index 0000000000..ad6eb7aced
--- /dev/null
+++ b/lib/English.gemspec
@@ -0,0 +1,24 @@
+Gem::Specification.new do |spec|
+ spec.name = "english"
+ spec.version = "0.7.1"
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{Require 'English.rb' to reference global variables with less cryptic names.}
+ spec.description = %q{Require 'English.rb' to reference global variables with less cryptic names.}
+ spec.homepage = "https://github.com/ruby/English"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/abbrev.gemspec b/lib/abbrev.gemspec
new file mode 100644
index 0000000000..4edf0edaa3
--- /dev/null
+++ b/lib/abbrev.gemspec
@@ -0,0 +1,22 @@
+Gem::Specification.new do |spec|
+ spec.name = "abbrev"
+ spec.version = "0.1.0"
+ spec.authors = ["Akinori MUSHA"]
+ spec.email = ["knu@idaemons.org"]
+
+ spec.summary = %q{Calculates a set of unique abbreviations for a given set of strings}
+ spec.description = %q{Calculates a set of unique abbreviations for a given set of strings}
+ spec.homepage = "https://github.com/ruby/abbrev"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/base64.gemspec b/lib/base64.gemspec
new file mode 100644
index 0000000000..331ecc4491
--- /dev/null
+++ b/lib/base64.gemspec
@@ -0,0 +1,22 @@
+Gem::Specification.new do |spec|
+ spec.name = "base64"
+ spec.version = "0.1.0"
+ spec.authors = ["Yusuke Endoh"]
+ spec.email = ["mame@ruby-lang.org"]
+
+ spec.summary = %q{Support for encoding and decoding binary data using a Base64 representation.}
+ spec.description = %q{Support for encoding and decoding binary data using a Base64 representation.}
+ spec.homepage = "https://github.com/ruby/base64"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = 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/benchmark/benchmark.gemspec b/lib/benchmark/benchmark.gemspec
index 773cab19b0..031ccbe34a 100644
--- a/lib/benchmark/benchmark.gemspec
+++ b/lib/benchmark/benchmark.gemspec
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
spec.summary = %q{a performance benchmarking library}
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/benchmark"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/lib/benchmark/version.rb b/lib/benchmark/version.rb
index d74cc74ee7..90d1a3900c 100644
--- a/lib/benchmark/version.rb
+++ b/lib/benchmark/version.rb
@@ -1,3 +1,3 @@
module Benchmark
- VERSION = "0.1.0"
+ VERSION = "0.1.1"
end
diff --git a/lib/bundler.rb b/lib/bundler.rb
index df345539c8..1ab87ac299 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -34,15 +34,16 @@ require_relative "bundler/build_metadata"
# of loaded and required modules.
#
module Bundler
- environment_preserver = EnvironmentPreserver.new(ENV, EnvironmentPreserver::BUNDLER_KEYS)
+ environment_preserver = EnvironmentPreserver.from_env
ORIGINAL_ENV = environment_preserver.restore
- ENV.replace(environment_preserver.backup)
- SUDO_MUTEX = Mutex.new
+ environment_preserver.replace_with_backup
+ SUDO_MUTEX = Thread::Mutex.new
autoload :Definition, File.expand_path("bundler/definition", __dir__)
autoload :Dependency, File.expand_path("bundler/dependency", __dir__)
autoload :DepProxy, File.expand_path("bundler/dep_proxy", __dir__)
autoload :Deprecate, File.expand_path("bundler/deprecate", __dir__)
+ autoload :Digest, File.expand_path("bundler/digest", __dir__)
autoload :Dsl, File.expand_path("bundler/dsl", __dir__)
autoload :EndpointSpecification, File.expand_path("bundler/endpoint_specification", __dir__)
autoload :Env, File.expand_path("bundler/env", __dir__)
@@ -63,13 +64,13 @@ module Bundler
autoload :Resolver, File.expand_path("bundler/resolver", __dir__)
autoload :Retry, File.expand_path("bundler/retry", __dir__)
autoload :RubyDsl, File.expand_path("bundler/ruby_dsl", __dir__)
- autoload :RubyGemsGemInstaller, File.expand_path("bundler/rubygems_gem_installer", __dir__)
autoload :RubyVersion, File.expand_path("bundler/ruby_version", __dir__)
autoload :Runtime, File.expand_path("bundler/runtime", __dir__)
autoload :Settings, File.expand_path("bundler/settings", __dir__)
autoload :SharedHelpers, File.expand_path("bundler/shared_helpers", __dir__)
autoload :Source, File.expand_path("bundler/source", __dir__)
autoload :SourceList, File.expand_path("bundler/source_list", __dir__)
+ autoload :SourceMap, File.expand_path("bundler/source_map", __dir__)
autoload :SpecSet, File.expand_path("bundler/spec_set", __dir__)
autoload :StubSpecification, File.expand_path("bundler/stub_specification", __dir__)
autoload :UI, File.expand_path("bundler/ui", __dir__)
@@ -198,7 +199,7 @@ module Bundler
def frozen_bundle?
frozen = settings[:deployment]
- frozen ||= settings[:frozen] unless feature_flag.deployment_means_frozen?
+ frozen ||= settings[:frozen]
frozen
end
@@ -212,6 +213,12 @@ 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
@@ -230,8 +237,9 @@ module Bundler
end
if warning
- user_home = tmp_home_path(warning)
- Bundler.ui.warn "#{warning}\nBundler will use `#{user_home}' as your home directory temporarily.\n"
+ Bundler.ui.warn "#{warning}\n"
+ user_home = tmp_home_path
+ Bundler.ui.warn "Bundler will use `#{user_home}' as your home directory temporarily.\n"
user_home
else
Pathname.new(home)
@@ -285,7 +293,13 @@ module Bundler
def app_config_path
if app_config = ENV["BUNDLE_APP_CONFIG"]
- Pathname.new(app_config).expand_path(root)
+ app_config_pathname = Pathname.new(app_config)
+
+ if app_config_pathname.absolute?
+ app_config_pathname
+ else
+ app_config_pathname.expand_path(root)
+ end
else
root.join(".bundle")
end
@@ -347,7 +361,10 @@ EOF
env.delete_if {|k, _| k[0, 7] == "BUNDLE_" }
if env.key?("RUBYOPT")
- env["RUBYOPT"] = env["RUBYOPT"].sub "-rbundler/setup", ""
+ rubyopt = env["RUBYOPT"].split(" ")
+ rubyopt.delete("-r#{File.expand_path("bundler/setup", __dir__)}")
+ rubyopt.delete("-rbundler/setup")
+ env["RUBYOPT"] = rubyopt.join(" ")
end
if env.key?("RUBYLIB")
@@ -426,7 +443,7 @@ EOF
end
def local_platform
- return Gem::Platform::RUBY if settings[:force_ruby_platform]
+ return Gem::Platform::RUBY if settings[:force_ruby_platform] || Gem.platforms == [Gem::Platform::RUBY]
Gem::Platform.local
end
@@ -447,10 +464,14 @@ EOF
# system binaries. If you put '-n foo' in your .gemrc, RubyGems will
# install binstubs there instead. Unfortunately, RubyGems doesn't expose
# that directory at all, so rather than parse .gemrc ourselves, we allow
- # the directory to be set as well, via `bundle config set bindir foo`.
+ # the directory to be set as well, via `bundle config set --local bindir foo`.
Bundler.settings[:system_bindir] || Bundler.rubygems.gem_bindir
end
+ def preferred_gemfile_name
+ Bundler.settings[:init_gems_rb] ? "gems.rb" : "Gemfile"
+ end
+
def use_system_gems?
configured_bundle_path.use_system_gems?
end
@@ -512,7 +533,8 @@ EOF
Your user account isn't allowed to install to the system RubyGems.
You can cancel this installation and run:
- bundle install --path vendor/bundle
+ bundle config set --local path 'vendor/bundle'
+ bundle install
to install the gems into ./vendor/bundle/, or you can enter your password
and install the bundled gems to RubyGems using sudo.
@@ -588,6 +610,11 @@ EOF
reset_rubygems!
end
+ def reset_settings_and_root!
+ @settings = nil
+ @root = nil
+ end
+
def reset_paths!
@bin_path = nil
@bundler_major_version = nil
@@ -610,7 +637,13 @@ EOF
@rubygems = nil
end
- private
+ def configure_gem_home_and_path(path = bundle_path)
+ configure_gem_path
+ configure_gem_home(path)
+ Bundler.rubygems.clear_paths
+ end
+
+ private
def eval_yaml_gemspec(path, contents)
require_relative "bundler/psyched_yaml"
@@ -627,47 +660,29 @@ EOF
rescue ScriptError, StandardError => e
msg = "There was an error while loading `#{path.basename}`: #{e.message}"
- if e.is_a?(LoadError)
- msg += "\nDoes it try to require a relative path? That's been removed in Ruby 1.9"
- end
-
raise GemspecError, Dsl::DSLError.new(msg, path, e.backtrace, contents)
end
- def configure_gem_home_and_path
- configure_gem_path
- configure_gem_home
- bundle_path
- end
-
- def configure_gem_path(env = ENV)
- blank_home = env["GEM_HOME"].nil? || env["GEM_HOME"].empty?
- if !use_system_gems?
+ def configure_gem_path
+ unless use_system_gems?
# this needs to be empty string to cause
# PathSupport.split_gem_path to only load up the
# Bundler --path setting as the GEM_PATH.
- env["GEM_PATH"] = ""
- elsif blank_home
- possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path]
- paths = possibles.flatten.compact.uniq.reject(&:empty?)
- env["GEM_PATH"] = paths.join(File::PATH_SEPARATOR)
+ Bundler::SharedHelpers.set_env "GEM_PATH", ""
end
end
- def configure_gem_home
- Bundler::SharedHelpers.set_env "GEM_HOME", File.expand_path(bundle_path, root)
- Bundler.rubygems.clear_paths
+ def configure_gem_home(path)
+ Bundler::SharedHelpers.set_env "GEM_HOME", path.to_s
end
- def tmp_home_path(warning)
+ def tmp_home_path
Kernel.send(:require, "tmpdir")
SharedHelpers.filesystem_access(Dir.tmpdir) do
path = Bundler.tmp
at_exit { Bundler.rm_rf(path) }
path
end
- rescue RuntimeError => e
- raise e.exception("#{warning}\nBundler also failed to create a temporary home directory':\n#{e}")
end
# @param env [Hash]
diff --git a/lib/bundler/build_metadata.rb b/lib/bundler/build_metadata.rb
index 4dfad2f8d8..0846e82e06 100644
--- a/lib/bundler/build_metadata.rb
+++ b/lib/bundler/build_metadata.rb
@@ -27,19 +27,11 @@ module Bundler
# If Bundler has been installed without its .git directory and without a
# commit instance variable then we can't determine its commits SHA.
- git_dir = File.join(File.expand_path("../../..", __FILE__), ".git")
+ git_dir = File.join(File.expand_path("../../../..", __FILE__), ".git")
if File.directory?(git_dir)
return @git_commit_sha = Dir.chdir(git_dir) { `git rev-parse --short HEAD`.strip.freeze }
end
- # If Bundler is a submodule in RubyGems, get the submodule commit
- git_sub_dir = File.join(File.expand_path("../../../..", __FILE__), ".git")
- if File.directory?(git_sub_dir)
- return @git_commit_sha = Dir.chdir(git_sub_dir) do
- `git ls-tree --abbrev=8 HEAD bundler`.split(/\s/).fetch(2, "").strip.freeze
- end
- end
-
@git_commit_sha ||= "unknown"
end
diff --git a/lib/bundler/bundler.gemspec b/lib/bundler/bundler.gemspec
index 30a21f155f..38c533b0c1 100644
--- a/lib/bundler/bundler.gemspec
+++ b/lib/bundler/bundler.gemspec
@@ -24,19 +24,20 @@ Gem::Specification.new do |s|
if s.respond_to?(:metadata=)
s.metadata = {
- "bug_tracker_uri" => "https://github.com/bundler/bundler/issues",
- "changelog_uri" => "https://github.com/bundler/bundler/blob/master/CHANGELOG.md",
+ "bug_tracker_uri" => "https://github.com/rubygems/rubygems/issues?q=is%3Aopen+is%3Aissue+label%3ABundler",
+ "changelog_uri" => "https://github.com/rubygems/rubygems/blob/master/bundler/CHANGELOG.md",
"homepage_uri" => "https://bundler.io/",
- "source_code_uri" => "https://github.com/bundler/bundler/",
+ "source_code_uri" => "https://github.com/rubygems/rubygems/",
}
end
s.required_ruby_version = ">= 2.3.0"
s.required_rubygems_version = ">= 2.5.2"
- s.files = (Dir.glob("lib/bundler/**/*", File::FNM_DOTMATCH) + Dir.glob("man/bundler*") + Dir.glob("libexec/bundle*")).reject {|f| File.directory?(f) }
+ s.files = Dir.glob("lib/bundler{.rb,/**/*}", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
- s.files += ["lib/bundler.rb"]
+ # include the gemspec itself because warbler breaks w/o it
+ s.files += %w[lib/bundler/bundler.gemspec]
s.bindir = "libexec"
s.executables = %w[bundle bundler]
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index 443458f2d9..d271086b25 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -14,6 +14,7 @@ module Bundler
COMMAND_ALIASES = {
"check" => "c",
"install" => "i",
+ "plugin" => "",
"list" => "ls",
"exec" => ["e", "ex", "exe"],
"cache" => ["package", "pack"],
@@ -57,7 +58,7 @@ module Bundler
custom_gemfile = options[:gemfile] || Bundler.settings[:gemfile]
if custom_gemfile && !custom_gemfile.empty?
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", File.expand_path(custom_gemfile)
- Bundler.reset_paths!
+ Bundler.reset_settings_and_root!
end
Bundler.settings.set_command_option_if_given :retry, options[:retry]
@@ -72,14 +73,6 @@ module Bundler
Bundler.ui = UI::Shell.new(options)
Bundler.ui.level = "debug" if options["verbose"]
unprinted_warnings.each {|w| Bundler.ui.warn(w) }
-
- if ENV["RUBYGEMS_GEMDEPS"] && !ENV["RUBYGEMS_GEMDEPS"].empty?
- Bundler.ui.warn(
- "The RUBYGEMS_GEMDEPS environment variable is set. This enables RubyGems' " \
- "experimental Gemfile mode, which may conflict with Bundler and cause unexpected errors. " \
- "To remove this warning, unset RUBYGEMS_GEMDEPS.", :wrap => true
- )
- end
end
check_unknown_options!(:except => [:config, :exec])
@@ -122,16 +115,17 @@ module Bundler
else command = "bundle-#{cli}"
end
- man_path = File.expand_path("../../../man", __FILE__)
- man_pages = Hash[Dir.glob(File.join(man_path, "*")).grep(/.*\.\d*\Z/).collect do |f|
+ man_path = File.expand_path("man", __dir__)
+ man_pages = Hash[Dir.glob(File.join(man_path, "**", "*")).grep(/.*\.\d*\Z/).collect do |f|
[File.basename(f, ".*"), f]
end]
if man_pages.include?(command)
+ man_page = man_pages[command]
if Bundler.which("man") && man_path !~ %r{^file:/.+!/META-INF/jruby.home/.+}
- Kernel.exec "man #{man_pages[command]}"
+ Kernel.exec "man #{man_page}"
else
- puts File.read("#{man_path}/#{File.basename(man_pages[command])}.txt")
+ puts File.read("#{man_path}/#{File.basename(man_page)}.ronn")
end
elsif command_path = Bundler.which("bundler-#{cli}")
Kernel.exec(command_path, "--help")
@@ -190,6 +184,7 @@ module Bundler
method_option "install", :type => :boolean, :banner =>
"Runs 'bundle install' after removing the gems from the Gemfile"
def remove(*gems)
+ SharedHelpers.major_deprecation(2, "The `--install` flag has been deprecated. `bundle install` is triggered by default.") if ARGV.include?("--install")
require_relative "cli/remove"
Remove.new(gems, options).run
end
@@ -247,10 +242,12 @@ module Bundler
def install
SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force")
- %w[clean deployment frozen no-cache no-prune path shebang system without with].each do |option|
+ %w[clean deployment frozen no-prune path shebang system without with].each do |option|
remembered_flag_deprecation(option)
end
+ remembered_negative_flag_deprecation("no-deployment")
+
require_relative "cli/install"
Bundler.settings.temporary(:no_install => false) do
Install.new(options.dup).run
@@ -305,45 +302,25 @@ module Bundler
end
end
- unless Bundler.feature_flag.bundler_3_mode?
- desc "show GEM [OPTIONS]", "Shows all gems that are part of the bundle, or the path to a given gem"
- long_desc <<-D
- Show lists the names and versions of all gems that are required by your Gemfile.
- Calling show with [GEM] will list the exact location of that gem on your machine.
- D
- method_option "paths", :type => :boolean,
- :banner => "List the paths of all gems that are required by your Gemfile."
- method_option "outdated", :type => :boolean,
- :banner => "Show verbose output including whether gems are outdated."
- def show(gem_name = nil)
- if ARGV[0] == "show"
- rest = ARGV[1..-1]
-
- if flag = rest.find{|arg| ["--verbose", "--outdated"].include?(arg) }
- Bundler::SharedHelpers.major_deprecation(2, "the `#{flag}` flag to `bundle show` was undocumented and will be removed without replacement")
- else
- new_command = rest.find {|arg| !arg.start_with?("--") } ? "info" : "list"
-
- new_arguments = rest.map do |arg|
- next arg if arg != "--paths"
- next "--path" if new_command == "info"
- end
-
- old_argv = ARGV.join(" ")
- new_argv = [new_command, *new_arguments.compact].join(" ")
-
- Bundler::SharedHelpers.major_deprecation(2, "use `bundle #{new_argv}` instead of `bundle #{old_argv}`")
- end
- end
- require_relative "cli/show"
- Show.new(options, gem_name).run
- end
+ desc "show GEM [OPTIONS]", "Shows all gems that are part of the bundle, or the path to a given gem"
+ long_desc <<-D
+ Show lists the names and versions of all gems that are required by your Gemfile.
+ Calling show with [GEM] will list the exact location of that gem on your machine.
+ D
+ method_option "paths", :type => :boolean,
+ :banner => "List the paths of all gems that are required by your Gemfile."
+ method_option "outdated", :type => :boolean,
+ :banner => "Show verbose output including whether gems are outdated."
+ def show(gem_name = nil)
+ SharedHelpers.major_deprecation(2, "the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement") if ARGV.include?("--outdated")
+ require_relative "cli/show"
+ Show.new(options, gem_name).run
end
desc "list", "List all gems in the bundle"
method_option "name-only", :type => :boolean, :banner => "print only the gem names"
- method_option "only-group", :type => :string, :banner => "print gems from a particular group"
- method_option "without-group", :type => :string, :banner => "print all gems except from a group"
+ method_option "only-group", :type => :array, :default => [], :banner => "print gems from a given set of groups"
+ method_option "without-group", :type => :array, :default => [], :banner => "print all gems except from a given set of groups"
method_option "paths", :type => :boolean, :banner => "print the path to each gem in the bundle"
def list
require_relative "cli/list"
@@ -354,6 +331,7 @@ module Bundler
desc "info GEM [OPTIONS]", "Show information for the given gem"
method_option "path", :type => :boolean, :banner => "Print full path to gem"
+ method_option "version", :type => :boolean, :banner => "Print gem version"
def info(gem_name)
require_relative "cli/info"
Info.new(options, gem_name).run
@@ -375,6 +353,8 @@ module Bundler
"Make binstubs that can work without the Bundler runtime"
method_option "all", :type => :boolean, :banner =>
"Install binstubs for all gems"
+ method_option "all-platforms", :type => :boolean, :default => false, :banner =>
+ "Install binstubs for all platforms"
def binstubs(*gems)
require_relative "cli/binstubs"
Binstubs.new(options, gems).run
@@ -434,11 +414,18 @@ module Bundler
Outdated.new(options, gems).run
end
- desc "cache [OPTIONS]", "Locks and then caches all of the gems into vendor/cache"
- unless Bundler.feature_flag.cache_all?
- method_option "all", :type => :boolean,
- :banner => "Include all sources (including path and git)."
+ desc "fund [OPTIONS]", "Lists information about gems seeking funding assistance"
+ method_option "group", :aliases => "-g", :type => :array, :banner =>
+ "Fetch funding information for a specific group"
+ def fund
+ require_relative "cli/fund"
+ Fund.new(options).run
end
+
+ desc "cache [OPTIONS]", "Locks and then caches all of the gems into vendor/cache"
+ method_option "all", :type => :boolean,
+ :default => Bundler.feature_flag.cache_all?,
+ :banner => "Include all sources (including path and git)."
method_option "all-platforms", :type => :boolean, :banner => "Include gems for all platforms present in the lockfile, not only the current one"
method_option "cache-path", :type => :string, :banner =>
"Specify a different cache path than the default (vendor/cache)."
@@ -457,6 +444,18 @@ module Bundler
bundle without having to download any additional gems.
D
def cache
+ SharedHelpers.major_deprecation 2,
+ "The `--all` flag is deprecated because it relies on being " \
+ "remembered across bundler invocations, which bundler will no longer " \
+ "do in future versions. Instead please use `bundle config set cache_all true`, " \
+ "and stop using this flag" if ARGV.include?("--all")
+
+ SharedHelpers.major_deprecation 2,
+ "The `--path` flag is deprecated because its semantics are unclear. " \
+ "Use `bundle config cache_path` to configure the path of your cache of gems, " \
+ "and `bundle config path` to configure the path where your gems are installed, " \
+ "and stop using this flag" if ARGV.include?("--path")
+
require_relative "cli/cache"
Cache.new(options).run
end
@@ -464,7 +463,7 @@ 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 => false
+ method_option :keep_file_descriptors, :type => :boolean, :default => true
method_option :gemfile, :type => :string, :required => false
long_desc <<-D
Exec runs a command, providing it access to the gems in the bundle. While using
@@ -472,6 +471,10 @@ module Bundler
into the system wide RubyGems repository.
D
def exec(*args)
+ if ARGV.include?("--no-keep-file-descriptors")
+ SharedHelpers.major_deprecation(2, "The `--no-keep-file-descriptors` has been deprecated. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to")
+ end
+
require_relative "cli/exec"
Exec.new(options, args).run
end
@@ -486,8 +489,8 @@ module Bundler
By default, setting a configuration value sets it for all projects
on the machine.
- If a global setting is superceded by local configuration, this command
- will show the current value, as well as any superceded values and
+ If a global setting is superseded by local configuration, this command
+ will show the current value, as well as any superseded values and
where they were specified.
D
require_relative "cli/config"
@@ -550,7 +553,7 @@ module Bundler
method_option :version, :type => :boolean, :default => false, :aliases => "-v", :desc => "Set to show each gem version."
method_option :without, :type => :array, :default => [], :aliases => "-W", :banner => "GROUP[ GROUP...]", :desc => "Exclude gems that are part of the specified named group."
def viz
- SharedHelpers.major_deprecation 2, "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz"
+ SharedHelpers.major_deprecation 2, "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph"
require_relative "cli/viz"
Viz.new(options.dup).run
end
@@ -560,15 +563,23 @@ module Bundler
desc "gem NAME [OPTIONS]", "Creates a skeleton for creating a rubygem"
method_option :exe, :type => :boolean, :default => false, :aliases => ["--bin", "-b"], :desc => "Generate a binary executable for your library."
- method_option :coc, :type => :boolean, :desc => "Generate a code of conduct file. Set a default with `bundle config set gem.coc true`."
+ method_option :coc, :type => :boolean, :desc => "Generate a code of conduct file. Set a default with `bundle config set --global gem.coc true`."
method_option :edit, :type => :string, :aliases => "-e", :required => false, :banner => "EDITOR",
:lazy_default => [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? },
:desc => "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
method_option :ext, :type => :boolean, :default => false, :desc => "Generate the boilerplate for C extension code"
method_option :git, :type => :boolean, :default => true, :desc => "Initialize a git repo inside your library."
- method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set gem.mit true`."
- method_option :test, :type => :string, :lazy_default => "rspec", :aliases => "-t", :banner => "rspec",
- :desc => "Generate a test directory for your library, either rspec or minitest. Set a default with `bundle config set gem.test rspec`."
+ method_option :mit, :type => :boolean, :desc => "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
+ method_option :rubocop, :type => :boolean, :desc => "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true`."
+ method_option :changelog, :type => :boolean, :desc => "Generate changelog file. Set a default with `bundle config set --global gem.changelog true`."
+ method_option :test, :type => :string, :lazy_default => Bundler.settings["gem.test"] || "", :aliases => "-t", :banner => "Use the specified test framework for your library",
+ :desc => "Generate a test directory for your library, either rspec, minitest or test-unit. Set a default with `bundle config set --global gem.test (rspec|minitest|test-unit)`."
+ method_option :ci, :type => :string, :lazy_default => Bundler.settings["gem.ci"] || "",
+ :desc => "Generate CI configuration, either GitHub Actions, Travis CI, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|travis|gitlab|circle)`"
+ method_option :linter, :type => :string, :lazy_default => Bundler.settings["gem.linter"] || "",
+ :desc => "Add a linter and code formatter, either RuboCop or Standard. Set a default with `bundle config set --global gem.linter (rubocop|standard)`"
+ method_option :github_username, :type => :string, :default => Bundler.settings["gem.github_username"], :banner => "Set your username on GitHub", :desc => "Fill in GitHub username on README so that you don't have to do it manually. Set a default with `bundle config set --global gem.github_username <your_username>`."
+
def gem(name)
end
@@ -731,11 +742,11 @@ module Bundler
end
end
- private
+ private
# Automatically invoke `bundle install` and resume if
# Bundler.settings[:auto_install] exists. This is set through config cmd
- # `bundle config set auto_install 1`.
+ # `bundle config set --global auto_install 1`.
#
# Note that this method `nil`s out the global Definition object, so it
# should be called first, before you instantiate anything like an
@@ -808,20 +819,32 @@ 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)
option = current_command.options[name]
flag_name = option.switch_name
- name_index = ARGV.find {|arg| flag_name == arg }
+ flag_deprecation(name, flag_name, option)
+ end
+
+ def flag_deprecation(name, flag_name, option)
+ name_index = ARGV.find {|arg| flag_name == arg.split("=")[0] }
return unless name_index
value = options[name]
value = value.join(" ").to_s if option.type == :array
- Bundler::SharedHelpers.major_deprecation 2,\
+ Bundler::SharedHelpers.major_deprecation 2,
"The `#{flag_name}` flag is deprecated because it relies on being " \
"remembered across bundler invocations, which bundler will no longer " \
- "do in future versions. Instead please use `bundle config set #{name} " \
+ "do in future versions. Instead please use `bundle config set --local #{name.tr("-", "_")} " \
"'#{value}'`, and stop using this flag"
end
end
diff --git a/lib/bundler/cli/add.rb b/lib/bundler/cli/add.rb
index 07b951f1ef..5bcf30d82d 100644
--- a/lib/bundler/cli/add.rb
+++ b/lib/bundler/cli/add.rb
@@ -17,7 +17,7 @@ module Bundler
perform_bundle_install unless options["skip-install"]
end
- private
+ private
def perform_bundle_install
Installer.install(Bundler.root, Bundler.definition)
diff --git a/lib/bundler/cli/binstubs.rb b/lib/bundler/cli/binstubs.rb
index 266396eedc..639c01ff39 100644
--- a/lib/bundler/cli/binstubs.rb
+++ b/lib/bundler/cli/binstubs.rb
@@ -16,7 +16,11 @@ module Bundler
Bundler.settings.set_command_option_if_given :shebang, options["shebang"]
installer = Installer.new(Bundler.root, Bundler.definition)
- installer_opts = { :force => options[:force], :binstubs_cmd => true }
+ installer_opts = {
+ :force => options[:force],
+ :binstubs_cmd => true,
+ :all_platforms => options["all-platforms"],
+ }
if options[:all]
raise InvalidOption, "Cannot specify --all with specific gems" unless gems.empty?
@@ -38,7 +42,7 @@ module Bundler
if options[:standalone]
next Bundler.ui.warn("Sorry, Bundler can only be run via RubyGems.") if gem_name == "bundler"
Bundler.settings.temporary(:path => (Bundler.settings[:path] || Bundler.root)) do
- installer.generate_standalone_bundler_executable_stubs(spec)
+ installer.generate_standalone_bundler_executable_stubs(spec, installer_opts)
end
else
installer.generate_bundler_executable_stubs(spec, installer_opts)
diff --git a/lib/bundler/cli/cache.rb b/lib/bundler/cli/cache.rb
index 5e8420990f..c8698ed7e3 100644
--- a/lib/bundler/cli/cache.rb
+++ b/lib/bundler/cli/cache.rb
@@ -9,7 +9,7 @@ module Bundler
end
def run
- Bundler.ui.level = "error" if options[:quiet]
+ Bundler.ui.level = "warn" if options[:quiet]
Bundler.settings.set_command_option_if_given :path, options[:path]
Bundler.settings.set_command_option_if_given :cache_path, options["cache-path"]
@@ -24,12 +24,13 @@ module Bundler
end
end
- private
+ private
def install
require_relative "install"
options = self.options.dup
options["local"] = false if Bundler.settings[:cache_all_platforms]
+ options["no-cache"] = true
Bundler::CLI::Install.new(options).run
end
@@ -37,12 +38,6 @@ module Bundler
all = options.fetch(:all, Bundler.feature_flag.cache_all? || nil)
Bundler.settings.set_command_option_if_given :cache_all, all
-
- if Bundler.definition.has_local_dependencies? && !Bundler.feature_flag.cache_all?
- Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \
- "to cache them as well, please pass the --all flag. This will be the default " \
- "on Bundler 3.0."
- end
end
end
end
diff --git a/lib/bundler/cli/check.rb b/lib/bundler/cli/check.rb
index 19c0aaea06..65c51337d2 100644
--- a/lib/bundler/cli/check.rb
+++ b/lib/bundler/cli/check.rb
@@ -11,9 +11,11 @@ module Bundler
def run
Bundler.settings.set_command_option_if_given :path, options[:path]
+ definition = Bundler.definition
+ definition.validate_runtime!
+
begin
- definition = Bundler.definition
- definition.validate_runtime!
+ definition.resolve_only_locally!
not_installed = definition.missing_specs
rescue GemNotFound, VersionConflict
Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies."
diff --git a/lib/bundler/cli/clean.rb b/lib/bundler/cli/clean.rb
index 4a407fbae7..c6b0968e3e 100644
--- a/lib/bundler/cli/clean.rb
+++ b/lib/bundler/cli/clean.rb
@@ -13,7 +13,7 @@ module Bundler
Bundler.load.clean(options[:"dry-run"])
end
- protected
+ protected
def require_path_or_force
return unless Bundler.use_system_gems? && !options[:force]
diff --git a/lib/bundler/cli/common.rb b/lib/bundler/cli/common.rb
index cec7bcadb4..ba259143b7 100644
--- a/lib/bundler/cli/common.rb
+++ b/lib/bundler/cli/common.rb
@@ -14,6 +14,20 @@ module Bundler
Bundler.ui.info msg
end
+ def self.output_fund_metadata_summary
+ definition = Bundler.definition
+ current_dependencies = definition.requested_dependencies
+ current_specs = definition.specs
+
+ count = current_dependencies.count {|dep| current_specs[dep.name].first.metadata.key?("funding_uri") }
+
+ return if count.zero?
+
+ intro = count > 1 ? "#{count} installed gems you directly depend on are" : "#{count} installed gem you directly depend on is"
+ message = "#{intro} looking for funding.\n Run `bundle fund` for details"
+ Bundler.ui.info message
+ end
+
def self.output_without_groups_message(command)
return if Bundler.settings[:without].empty?
Bundler.ui.confirm without_groups_message(command)
@@ -22,10 +36,15 @@ module Bundler
def self.without_groups_message(command)
command_in_past_tense = command == :install ? "installed" : "updated"
groups = Bundler.settings[:without]
+ "Gems in the #{verbalize_groups(groups)} were not #{command_in_past_tense}."
+ end
+
+ def self.verbalize_groups(groups)
+ groups.map!{|g| "'#{g}'" }
group_list = [groups[0...-1].join(", "), groups[-1..-1]].
reject {|s| s.to_s.empty? }.join(" and ")
group_str = groups.size == 1 ? "group" : "groups"
- "Gems in the #{group_str} #{group_list} were not #{command_in_past_tense}."
+ "#{group_str} #{group_list}"
end
def self.select_spec(name, regex_match = nil)
@@ -39,7 +58,13 @@ module Bundler
case specs.count
when 0
- raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
+ dep_in_other_group = Bundler.definition.current_dependencies.find {|dep|dep.name == name }
+
+ if dep_in_other_group
+ raise GemNotFound, "Could not find gem '#{name}', because it's in the #{verbalize_groups(dep_in_other_group.groups)}, configured to be ignored."
+ else
+ raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
+ end
when 1
specs.first
else
@@ -69,6 +94,8 @@ module Bundler
end
def self.ensure_all_gems_in_lockfile!(names, locked_gems = Bundler.locked_gems)
+ return unless locked_gems
+
locked_names = locked_gems.specs.map(&:name).uniq
names.-(locked_names).each do |g|
raise GemNotFound, gem_not_found_message(g, locked_names)
diff --git a/lib/bundler/cli/console.rb b/lib/bundler/cli/console.rb
index 6e0dfe28af..97b8dc0663 100644
--- a/lib/bundler/cli/console.rb
+++ b/lib/bundler/cli/console.rb
@@ -12,7 +12,7 @@ module Bundler
Bundler::SharedHelpers.major_deprecation 2, "bundle console will be replaced " \
"by `bin/console` generated by `bundle gem <name>`"
- group ? Bundler.require(:default, *group.split.map!(&:to_sym)) : Bundler.require
+ group ? Bundler.require(:default, *group.split(" ").map!(&:to_sym)) : Bundler.require
ARGV.clear
console = get_console(Bundler.settings[:console] || "irb")
diff --git a/lib/bundler/cli/doctor.rb b/lib/bundler/cli/doctor.rb
index fcf139ed1e..43f1ca92e2 100644
--- a/lib/bundler/cli/doctor.rb
+++ b/lib/bundler/cli/doctor.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require "rbconfig"
+require "shellwords"
module Bundler
class CLI::Doctor
@@ -22,14 +23,14 @@ module Bundler
end
def dylibs_darwin(path)
- output = `/usr/bin/otool -L "#{path}"`.chomp
+ output = `/usr/bin/otool -L #{path.shellescape}`.chomp
dylibs = output.split("\n")[1..-1].map {|l| l.match(DARWIN_REGEX).captures[0] }.uniq
# ignore @rpath and friends
dylibs.reject {|dylib| dylib.start_with? "@" }
end
def dylibs_ldd(path)
- output = `/usr/bin/ldd "#{path}"`.chomp
+ output = `/usr/bin/ldd #{path.shellescape}`.chomp
output.split("\n").map do |l|
match = l.match(LDD_REGEX)
next if match.nil?
@@ -61,7 +62,7 @@ module Bundler
end
def run
- Bundler.ui.level = "error" if options[:quiet]
+ Bundler.ui.level = "warn" if options[:quiet]
Bundler.settings.validate!
check!
@@ -93,15 +94,18 @@ module Bundler
end
end
- private
+ private
def check_home_permissions
require "find"
files_not_readable_or_writable = []
files_not_rw_and_owned_by_different_user = []
files_not_owned_by_current_user_but_still_rw = []
+ broken_symlinks = []
Find.find(Bundler.bundle_path.to_s).each do |f|
- if !File.writable?(f) || !File.readable?(f)
+ if !File.exist?(f)
+ broken_symlinks << f
+ elsif !File.writable?(f) || !File.readable?(f)
if File.stat(f).uid != Process.uid
files_not_rw_and_owned_by_different_user << f
else
@@ -113,6 +117,13 @@ module Bundler
end
ok = true
+
+ if broken_symlinks.any?
+ Bundler.ui.warn "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{broken_symlinks.join("\n - ")}"
+
+ ok = false
+ end
+
if files_not_owned_by_current_user_but_still_rw.any?
Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
"user, but are still readable/writable. These files are:\n - #{files_not_owned_by_current_user_but_still_rw.join("\n - ")}"
diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb
index 0a1edbdbbd..42b602a055 100644
--- a/lib/bundler/cli/exec.rb
+++ b/lib/bundler/cli/exec.rb
@@ -12,12 +12,7 @@ module Bundler
@options = options
@cmd = args.shift
@args = args
-
- if !Bundler.current_ruby.jruby?
- @args << { :close_others => !options.keep_file_descriptors? }
- elsif options.keep_file_descriptors?
- Bundler.ui.warn "Ruby version #{RUBY_VERSION} defaults to keeping non-standard file descriptors on Kernel#exec."
- end
+ @args << { :close_others => !options.keep_file_descriptors? } unless Bundler.current_ruby.jruby?
end
def run
@@ -34,7 +29,7 @@ module Bundler
end
end
- private
+ private
def validate_cmd!
return unless cmd.nil?
@@ -63,10 +58,10 @@ module Bundler
Kernel.load(file)
rescue SystemExit, SignalException
raise
- rescue Exception => e # rubocop:disable Lint/RescueException
+ rescue Exception # rubocop:disable Lint/RescueException
Bundler.ui.error "bundler: failed to load command: #{cmd} (#{file})"
- backtrace = e.backtrace ? e.backtrace.take_while {|bt| !bt.start_with?(__FILE__) } : []
- abort "#{e.class}: #{e.message}\n #{backtrace.join("\n ")}"
+ Bundler::FriendlyErrors.disable!
+ raise
end
def process_title(file, args)
diff --git a/lib/bundler/cli/fund.rb b/lib/bundler/cli/fund.rb
new file mode 100644
index 0000000000..52db5aef68
--- /dev/null
+++ b/lib/bundler/cli/fund.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Bundler
+ class CLI::Fund
+ attr_reader :options
+
+ def initialize(options)
+ @options = options
+ end
+
+ def run
+ Bundler.definition.validate_runtime!
+
+ groups = Array(options[:group]).map(&:to_sym)
+
+ deps = if groups.any?
+ Bundler.definition.dependencies_for(groups)
+ else
+ Bundler.definition.current_dependencies
+ end
+
+ fund_info = deps.each_with_object([]) do |dep, arr|
+ spec = Bundler.definition.specs[dep.name].first
+ if spec.metadata.key?("funding_uri")
+ arr << "* #{spec.name} (#{spec.version})\n Funding: #{spec.metadata["funding_uri"]}"
+ end
+ end
+
+ if fund_info.empty?
+ Bundler.ui.info "None of the installed gems you directly depend on are looking for funding."
+ else
+ Bundler.ui.info fund_info.join("\n")
+ end
+ end
+ end
+end
diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb
index d3e5831759..2a74325fde 100644
--- a/lib/bundler/cli/gem.rb
+++ b/lib/bundler/cli/gem.rb
@@ -12,6 +12,7 @@ module Bundler
TEST_FRAMEWORK_VERSIONS = {
"rspec" => "3.0",
"minitest" => "5.0",
+ "test-unit" => "3.0",
}.freeze
attr_reader :options, :gem_name, :thor, :name, :target
@@ -38,11 +39,19 @@ module Bundler
constant_name = name.gsub(/-[_-]*(?![_-]|$)/) { "::" }.gsub(/([_-]+|(::)|^)(.|$)/) { $2.to_s + $3.upcase }
constant_array = constant_name.split("::")
- git_installed = Bundler.git_present?
+ use_git = Bundler.git_present? && options[:git]
- git_author_name = git_installed ? `git config user.name`.chomp : ""
- github_username = git_installed ? `git config github.user`.chomp : ""
- git_user_email = git_installed ? `git config user.email`.chomp : ""
+ git_author_name = use_git ? `git config user.name`.chomp : ""
+ git_username = use_git ? `git config github.user`.chomp : ""
+ git_user_email = use_git ? `git config user.email`.chomp : ""
+
+ github_username = if options[:github_username].nil?
+ git_username
+ elsif options[:github_username] == false
+ ""
+ else
+ options[:github_username]
+ end
config = {
:name => name,
@@ -57,14 +66,17 @@ module Bundler
:ext => options[:ext],
:exe => options[:exe],
:bundler_version => bundler_dependency_version,
+ :git => use_git,
:github_username => github_username.empty? ? "[USERNAME]" : github_username,
+ :required_ruby_version => required_ruby_version,
}
ensure_safe_gem_name(name, constant_array)
templates = {
- "Gemfile.tt" => "Gemfile",
+ "#{Bundler.preferred_gemfile_name}.tt" => Bundler.preferred_gemfile_name,
"lib/newgem.rb.tt" => "lib/#{namespaced_path}.rb",
"lib/newgem/version.rb.tt" => "lib/#{namespaced_path}/version.rb",
+ "sig/newgem.rbs.tt" => "sig/#{namespaced_path}.rbs",
"newgem.gemspec.tt" => "#{name}.gemspec",
"Rakefile.tt" => "Rakefile",
"README.md.tt" => "README.md",
@@ -77,14 +89,12 @@ module Bundler
bin/setup
]
- templates.merge!("gitignore.tt" => ".gitignore") if Bundler.git_present?
+ templates.merge!("gitignore.tt" => ".gitignore") if use_git
if test_framework = ask_and_set_test_framework
config[:test] = test_framework
config[:test_framework_version] = TEST_FRAMEWORK_VERSIONS[test_framework]
- templates.merge!("travis.yml.tt" => ".travis.yml")
-
case test_framework
when "rspec"
templates.merge!(
@@ -92,15 +102,33 @@ module Bundler
"spec/spec_helper.rb.tt" => "spec/spec_helper.rb",
"spec/newgem_spec.rb.tt" => "spec/#{namespaced_path}_spec.rb"
)
+ config[:test_task] = :spec
when "minitest"
templates.merge!(
- "test/test_helper.rb.tt" => "test/test_helper.rb",
- "test/newgem_test.rb.tt" => "test/#{namespaced_path}_test.rb"
+ "test/minitest/test_helper.rb.tt" => "test/test_helper.rb",
+ "test/minitest/newgem_test.rb.tt" => "test/#{namespaced_path}_test.rb"
)
+ config[:test_task] = :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
end
end
- config[:test_task] = config[:test] == "minitest" ? "test" : "spec"
+ config[:ci] = ask_and_set_ci
+ case config[:ci]
+ when "github"
+ templates.merge!("github/workflows/main.yml.tt" => ".github/workflows/main.yml")
+ when "travis"
+ templates.merge!("travis.yml.tt" => ".travis.yml")
+ when "gitlab"
+ templates.merge!("gitlab-ci.yml.tt" => ".gitlab-ci.yml")
+ when "circle"
+ templates.merge!("circleci/config.yml.tt" => ".circleci/config.yml")
+ end
if ask_and_set(:mit, "Do you want to license your code permissively under the MIT license?",
"This means that any other developer or company will be legally allowed to use your code " \
@@ -124,6 +152,30 @@ module Bundler
templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md")
end
+ if ask_and_set(:changelog, "Do you want to include a changelog?",
+ "A changelog is a file which contains a curated, chronologically ordered list of notable " \
+ "changes for each version of a project. To make it easier for users and contributors to" \
+ " see precisely what notable changes have been made between each release (or version) of" \
+ " the project. Whether consumers or developers, the end users of software are" \
+ " human beings who care about what's in the software. When the software changes, people " \
+ "want to know why and how. see https://keepachangelog.com")
+ config[:changelog] = true
+ Bundler.ui.info "Changelog enabled in config"
+ templates.merge!("CHANGELOG.md.tt" => "CHANGELOG.md")
+ end
+
+ config[:linter] = ask_and_set_linter
+ case config[:linter]
+ when "rubocop"
+ config[:linter_version] = rubocop_version
+ Bundler.ui.info "RuboCop enabled in config"
+ templates.merge!("rubocop.yml.tt" => ".rubocop.yml")
+ when "standard"
+ config[:linter_version] = standard_version
+ Bundler.ui.info "Standard enabled in config"
+ templates.merge!("standard.yml.tt" => ".standard.yml")
+ end
+
templates.merge!("exe/newgem.tt" => "exe/#{name}") if config[:exe]
if options[:ext]
@@ -134,24 +186,32 @@ module Bundler
)
end
+ if target.exist? && !target.directory?
+ Bundler.ui.error "Couldn't create a new gem named `#{gem_name}` because there's an existing file named `#{gem_name}`."
+ exit Bundler::BundlerError.all_errors[Bundler::GenericSystemCallError]
+ end
+
+ if use_git
+ Bundler.ui.info "Initializing git repo in #{target}"
+ require "shellwords"
+ `git init #{target.to_s.shellescape}`
+
+ config[:git_default_branch] = File.read("#{target}/.git/HEAD").split("/").last.chomp
+ end
+
templates.each do |src, dst|
destination = target.join(dst)
- SharedHelpers.filesystem_access(destination) do
- thor.template("newgem/#{src}", destination, config)
- end
+ thor.template("newgem/#{src}", destination, config)
end
executables.each do |file|
- SharedHelpers.filesystem_access(target.join(file)) do |path|
- executable = (path.stat.mode | 0o111)
- path.chmod(executable)
- end
+ path = target.join(file)
+ executable = (path.stat.mode | 0o111)
+ path.chmod(executable)
end
- if Bundler.git_present? && options[:git]
- Bundler.ui.info "Initializing git repo in #{target}"
+ if use_git
Dir.chdir(target) do
- `git init`
`git add .`
end
end
@@ -161,11 +221,9 @@ module Bundler
Bundler.ui.info "Gem '#{name}' was successfully created. " \
"For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html"
- rescue Errno::EEXIST => e
- raise GenericSystemCallError.new(e, "There was a conflict while creating the new gem.")
end
- private
+ private
def resolve_name(name)
SharedHelpers.pwd.join(name).basename.to_s
@@ -197,11 +255,12 @@ module Bundler
def ask_and_set_test_framework
test_framework = options[:test] || Bundler.settings["gem.test"]
- if test_framework.nil?
+ if test_framework.to_s.empty?
Bundler.ui.confirm "Do you want to generate tests with your gem?"
- result = Bundler.ui.ask "Type 'rspec' or 'minitest' to generate those test files now and " \
- "in the future. rspec/minitest/(none):"
- if result =~ /rspec|minitest/
+ Bundler.ui.info hint_text("test")
+
+ result = Bundler.ui.ask "Enter a test framework. rspec/minitest/test-unit/(none):"
+ if result =~ /rspec|minitest|test-unit/
test_framework = result
else
test_framework = false
@@ -212,9 +271,106 @@ module Bundler
Bundler.settings.set_global("gem.test", test_framework)
end
+ if options[:test] == Bundler.settings["gem.test"]
+ Bundler.ui.info "#{options[:test]} is already configured, ignoring --test flag."
+ end
+
test_framework
end
+ def hint_text(setting)
+ if Bundler.settings["gem.#{setting}"] == false
+ "Your choice will only be applied to this gem."
+ else
+ "Future `bundle gem` calls will use your choice. " \
+ "This setting can be changed anytime with `bundle config gem.#{setting}`."
+ end
+ end
+
+ def ask_and_set_ci
+ ci_template = options[:ci] || Bundler.settings["gem.ci"]
+
+ if ci_template.to_s.empty?
+ Bundler.ui.confirm "Do you want to set up continuous integration for your gem? " \
+ "Supported services:\n" \
+ "* CircleCI: https://circleci.com/\n" \
+ "* GitHub Actions: https://github.com/features/actions\n" \
+ "* GitLab CI: https://docs.gitlab.com/ee/ci/\n" \
+ "* Travis CI: https://travis-ci.org/\n" \
+ "\n"
+ Bundler.ui.info hint_text("ci")
+
+ result = Bundler.ui.ask "Enter a CI service. github/travis/gitlab/circle/(none):"
+ if result =~ /github|travis|gitlab|circle/
+ ci_template = result
+ else
+ ci_template = false
+ end
+ end
+
+ if Bundler.settings["gem.ci"].nil?
+ Bundler.settings.set_global("gem.ci", ci_template)
+ end
+
+ if options[:ci] == Bundler.settings["gem.ci"]
+ Bundler.ui.info "#{options[:ci]} is already configured, ignoring --ci flag."
+ end
+
+ ci_template
+ end
+
+ def ask_and_set_linter
+ linter_template = options[:linter] || Bundler.settings["gem.linter"]
+ linter_template = deprecated_rubocop_option if linter_template.nil?
+
+ if linter_template.to_s.empty?
+ Bundler.ui.confirm "Do you want to add a code linter and formatter to your gem? " \
+ "Supported Linters:\n" \
+ "* RuboCop: https://rubocop.org\n" \
+ "* Standard: https://github.com/testdouble/standard\n" \
+ "\n"
+ Bundler.ui.info hint_text("linter")
+
+ result = Bundler.ui.ask "Enter a linter. rubocop/standard/(none):"
+ if result =~ /rubocop|standard/
+ linter_template = result
+ else
+ linter_template = false
+ end
+ end
+
+ if Bundler.settings["gem.linter"].nil?
+ Bundler.settings.set_global("gem.linter", linter_template)
+ end
+
+ # Once gem.linter safely set, unset the deprecated gem.rubocop
+ unless Bundler.settings["gem.rubocop"].nil?
+ Bundler.settings.set_global("gem.rubocop", nil)
+ end
+
+ if options[:linter] == Bundler.settings["gem.linter"]
+ Bundler.ui.info "#{options[:linter]} is already configured, ignoring --linter flag."
+ end
+
+ linter_template
+ end
+
+ def deprecated_rubocop_option
+ if !options[:rubocop].nil?
+ if options[:rubocop]
+ Bundler::SharedHelpers.major_deprecation 2, "--rubocop is deprecated, use --linter=rubocop"
+ "rubocop"
+ else
+ Bundler::SharedHelpers.major_deprecation 2, "--no-rubocop is deprecated, use --linter"
+ false
+ end
+ elsif !Bundler.settings["gem.rubocop"].nil?
+ Bundler::SharedHelpers.major_deprecation 2,
+ "config gem.rubocop is deprecated; we've updated your config to use gem.linter instead"
+ Bundler.settings["gem.rubocop"] ? "rubocop" : false
+ end
+ end
+
def bundler_dependency_version
v = Gem::Version.new(Bundler::VERSION)
req = v.segments[0..1]
@@ -248,5 +404,30 @@ module Bundler
def open_editor(editor, file)
thor.run(%(#{editor} "#{file}"))
end
+
+ def required_ruby_version
+ if Gem.ruby_version < Gem::Version.new("2.4.a") then "2.3.0"
+ elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "2.4.0"
+ elsif Gem.ruby_version < Gem::Version.new("2.6.a") then "2.5.0"
+ else
+ "2.6.0"
+ end
+ end
+
+ def rubocop_version
+ if Gem.ruby_version < Gem::Version.new("2.4.a") then "0.81.0"
+ elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "1.12"
+ else
+ "1.21"
+ end
+ end
+
+ def standard_version
+ if Gem.ruby_version < Gem::Version.new("2.4.a") then "0.2.5"
+ elsif Gem.ruby_version < Gem::Version.new("2.5.a") then "1.0"
+ else
+ "1.3"
+ end
+ end
end
end
diff --git a/lib/bundler/cli/info.rb b/lib/bundler/cli/info.rb
index 4733675e8c..76c8cf60c0 100644
--- a/lib/bundler/cli/info.rb
+++ b/lib/bundler/cli/info.rb
@@ -18,11 +18,12 @@ module Bundler
if spec
return print_gem_path(spec) if @options[:path]
+ return print_gem_version(spec) if @options[:version]
print_gem_info(spec)
end
end
- private
+ private
def spec_for_gem(gem_name)
spec = Bundler.definition.specs.find {|s| s.name == gem_name }
@@ -39,23 +40,45 @@ module Bundler
raise GemNotFound, Bundler::CLI::Common.gem_not_found_message(gem_name, Bundler.definition.dependencies)
end
+ def print_gem_version(spec)
+ Bundler.ui.info spec.version.to_s
+ end
+
def print_gem_path(spec)
- path = if spec.name == "bundler"
- File.expand_path("../../../..", __FILE__)
+ name = spec.name
+ if name == "bundler"
+ path = File.expand_path("../../../..", __FILE__)
else
- spec.full_gem_path
+ path = spec.full_gem_path
+ if spec.deleted_gem?
+ return Bundler.ui.warn "The gem #{name} has been deleted. It was installed at: #{path}"
+ end
end
Bundler.ui.info path
end
def print_gem_info(spec)
+ metadata = spec.metadata
+ name = spec.name
gem_info = String.new
- gem_info << " * #{spec.name} (#{spec.version}#{spec.git_version})\n"
+ gem_info << " * #{name} (#{spec.version}#{spec.git_version})\n"
gem_info << "\tSummary: #{spec.summary}\n" if spec.summary
gem_info << "\tHomepage: #{spec.homepage}\n" if spec.homepage
+ gem_info << "\tDocumentation: #{metadata["documentation_uri"]}\n" if metadata.key?("documentation_uri")
+ gem_info << "\tSource Code: #{metadata["source_code_uri"]}\n" if metadata.key?("source_code_uri")
+ gem_info << "\tFunding: #{metadata["funding_uri"]}\n" if metadata.key?("funding_uri")
+ gem_info << "\tWiki: #{metadata["wiki_uri"]}\n" if metadata.key?("wiki_uri")
+ gem_info << "\tChangelog: #{metadata["changelog_uri"]}\n" if metadata.key?("changelog_uri")
+ gem_info << "\tBug Tracker: #{metadata["bug_tracker_uri"]}\n" if metadata.key?("bug_tracker_uri")
+ gem_info << "\tMailing List: #{metadata["mailing_list_uri"]}\n" if metadata.key?("mailing_list_uri")
gem_info << "\tPath: #{spec.full_gem_path}\n"
gem_info << "\tDefault Gem: yes" if spec.respond_to?(:default_gem?) && spec.default_gem?
+
+ if name != "bundler" && spec.deleted_gem?
+ return Bundler.ui.warn "The gem #{name} has been deleted. Gemspec information is still available though:\n#{gem_info}"
+ end
+
Bundler.ui.info gem_info
end
end
diff --git a/lib/bundler/cli/init.rb b/lib/bundler/cli/init.rb
index 65dd08dfe9..d851d02d42 100644
--- a/lib/bundler/cli/init.rb
+++ b/lib/bundler/cli/init.rb
@@ -38,10 +38,10 @@ module Bundler
puts "Writing new #{gemfile} to #{SharedHelpers.pwd}/#{gemfile}"
end
- private
+ private
def gemfile
- @gemfile ||= Bundler.settings[:init_gems_rb] ? "gems.rb" : "Gemfile"
+ @gemfile ||= Bundler.preferred_gemfile_name
end
end
end
diff --git a/lib/bundler/cli/inject.rb b/lib/bundler/cli/inject.rb
index b00675d348..8093a85283 100644
--- a/lib/bundler/cli/inject.rb
+++ b/lib/bundler/cli/inject.rb
@@ -44,7 +44,7 @@ module Bundler
end
end
- private
+ private
def last_version_number
definition = Bundler.definition(true)
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index ecd474971d..4c1915fea6 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -8,12 +8,10 @@ module Bundler
end
def run
- Bundler.ui.level = "error" if options[:quiet]
+ Bundler.ui.level = "warn" if options[:quiet]
warn_if_root
- normalize_groups
-
Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Bundler::FREEBSD
# Disable color in deployment mode
@@ -35,12 +33,8 @@ module Bundler
options[:local] = true if Bundler.app_cache.exist?
- if Bundler.feature_flag.deployment_means_frozen?
- Bundler.settings.set_command_option :deployment, true
- else
- Bundler.settings.set_command_option :deployment, true if options[:deployment]
- Bundler.settings.set_command_option :frozen, true if options[:frozen]
- end
+ Bundler.settings.set_command_option :deployment, true if options[:deployment]
+ Bundler.settings.set_command_option :frozen, true if options[:frozen]
end
# When install is called with --no-deployment, disable deployment mode
@@ -55,7 +49,7 @@ module Bundler
if options["binstubs"]
Bundler::SharedHelpers.major_deprecation 2,
- "The --binstubs option will be removed in favor of `bundle binstubs`"
+ "The --binstubs option will be removed in favor of `bundle binstubs --all`"
end
Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins?
@@ -64,7 +58,10 @@ module Bundler
definition.validate_runtime!
installer = Installer.install(Bundler.root, definition, options)
- Bundler.load.cache if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen_bundle?
+
+ Bundler.settings.temporary(:cache_all_platforms => options[:local] ? false : Bundler.settings[:cache_all_platforms]) do
+ Bundler.load.cache(nil, options[:local]) if Bundler.app_cache.exist? && !options["no-cache"] && !Bundler.frozen_bundle?
+ end
Bundler.ui.confirm "Bundle complete! #{dependencies_count_for(definition)}, #{gems_installed_for(definition)}."
Bundler::CLI::Common.output_without_groups_message(:install)
@@ -84,28 +81,17 @@ module Bundler
require_relative "clean"
Bundler::CLI::Clean.new(options).run
end
- rescue GemNotFound, VersionConflict => e
- if options[:local] && Bundler.app_cache.exist?
- Bundler.ui.warn "Some gems seem to be missing from your #{Bundler.settings.app_cache_path} directory."
- end
- unless Bundler.definition.has_rubygems_remotes?
- Bundler.ui.warn <<-WARN, :wrap => true
- Your Gemfile has no gem server sources. If you need gems that are \
- not already on your machine, add a line like this to your Gemfile:
- source 'https://rubygems.org'
- WARN
- end
- raise e
- rescue Gem::InvalidSpecificationException => e
+ Bundler::CLI::Common.output_fund_metadata_summary
+ rescue Gem::InvalidSpecificationException
Bundler.ui.warn "You have one or more invalid gemspecs that need to be fixed."
- raise e
+ raise
end
- private
+ private
def warn_if_root
- return if Bundler.settings[:silence_root_warning] || Bundler::WINDOWS || !Process.uid.zero?
+ return if Bundler.settings[:silence_root_warning] || Gem.win_platform? || !Process.uid.zero?
Bundler.ui.warn "Don't run Bundler as root. Bundler can ask for sudo " \
"if it is needed, and installing your bundle as root will break this " \
"application for all non-root users on this machine.", :wrap => true
@@ -165,6 +151,14 @@ module Bundler
options[:with] = with
options[:without] = without
+
+ unless Bundler.settings[:without] == options[:without] && Bundler.settings[:with] == options[:with]
+ # need to nil them out first to get around validation for backwards compatibility
+ Bundler.settings.set_command_option :without, nil
+ Bundler.settings.set_command_option :with, nil
+ Bundler.settings.set_command_option :without, options[:without] - options[:with]
+ Bundler.settings.set_command_option :with, options[:with]
+ end
end
def normalize_settings
@@ -191,13 +185,7 @@ module Bundler
Bundler.settings.set_command_option_if_given :clean, options["clean"]
- unless Bundler.settings[:without] == options[:without] && Bundler.settings[:with] == options[:with]
- # need to nil them out first to get around validation for backwards compatibility
- Bundler.settings.set_command_option :without, nil
- Bundler.settings.set_command_option :with, nil
- Bundler.settings.set_command_option :without, options[:without] - options[:with]
- Bundler.settings.set_command_option :with, options[:with]
- end
+ normalize_groups
options[:force] = options[:redownload]
end
diff --git a/lib/bundler/cli/issue.rb b/lib/bundler/cli/issue.rb
index 054ce76315..b891ecb1d2 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/bundler/bundler/blob/master/doc/TROUBLESHOOTING.md
+ https://github.com/rubygems/rubygems/blob/master/bundler/doc/TROUBLESHOOTING.md
2. Instructions for common Bundler uses can be found on the documentation
site: https://bundler.io/
@@ -20,9 +20,10 @@ module Bundler
Hopefully the troubleshooting steps above resolved your problem! If things
still aren't working the way you expect them to, please let us know so
- that we can diagnose and help fix the problem you're having. Please
- view the Filing Issues guide for more information:
- https://github.com/bundler/bundler/blob/master/doc/contributing/ISSUES.md
+ that we can diagnose and help fix the problem you're having, by filling
+ in the new issue form located at
+ https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md,
+ and copy and pasting the information below.
EOS
diff --git a/lib/bundler/cli/list.rb b/lib/bundler/cli/list.rb
index d1799196e7..f56bf5b86a 100644
--- a/lib/bundler/cli/list.rb
+++ b/lib/bundler/cli/list.rb
@@ -4,17 +4,25 @@ module Bundler
class CLI::List
def initialize(options)
@options = options
+ @without_group = options["without-group"].map(&:to_sym)
+ @only_group = options["only-group"].map(&:to_sym)
end
def run
- raise InvalidOption, "The `--only-group` and `--without-group` options cannot be used together" if @options["only-group"] && @options["without-group"]
+ raise InvalidOption, "The `--only-group` and `--without-group` options cannot be used together" if @only_group.any? && @without_group.any?
raise InvalidOption, "The `--name-only` and `--paths` options cannot be used together" if @options["name-only"] && @options[:paths]
- specs = if @options["only-group"] || @options["without-group"]
+ specs = if @only_group.any? || @without_group.any?
filtered_specs_by_groups
else
- Bundler.load.specs
+ begin
+ Bundler.load.specs
+ rescue GemNotFound => e
+ Bundler.ui.error e.message
+ Bundler.ui.warn "Install missing gems with `bundle install`."
+ exit 1
+ end
end.reject {|s| s.name == "bundler" }.sort_by(&:name)
return Bundler.ui.info "No gems in the Gemfile" if specs.empty?
@@ -29,12 +37,12 @@ module Bundler
Bundler.ui.info "Use `bundle info` to print more detailed information about a gem"
end
- private
+ private
def verify_group_exists(groups)
- raise InvalidOption, "`#{@options["without-group"]}` group could not be found." if @options["without-group"] && !groups.include?(@options["without-group"].to_sym)
-
- raise InvalidOption, "`#{@options["only-group"]}` group could not be found." if @options["only-group"] && !groups.include?(@options["only-group"].to_sym)
+ (@without_group + @only_group).each do |group|
+ raise InvalidOption, "`#{group}` group could not be found." unless groups.include?(group)
+ end
end
def filtered_specs_by_groups
@@ -44,10 +52,10 @@ module Bundler
verify_group_exists(groups)
show_groups =
- if @options["without-group"]
- groups.reject {|g| g == @options["without-group"].to_sym }
- elsif @options["only-group"]
- groups.select {|g| g == @options["only-group"].to_sym }
+ if @without_group.any?
+ groups.reject {|g| @without_group.include?(g) }
+ elsif @only_group.any?
+ groups.select {|g| @only_group.include?(g) }
else
groups
end.map(&:to_sym)
diff --git a/lib/bundler/cli/lock.rb b/lib/bundler/cli/lock.rb
index 7dd078b1ef..7d613a6644 100644
--- a/lib/bundler/cli/lock.rb
+++ b/lib/bundler/cli/lock.rb
@@ -21,9 +21,13 @@ module Bundler
Bundler::Fetcher.disable_endpoint = options["full-index"]
update = options[:update]
+ conservative = options[:conservative]
+
if update.is_a?(Array) # unlocking specific gems
Bundler::CLI::Common.ensure_all_gems_in_lockfile!(update)
- update = { :gems => update, :lock_shared_dependencies => options[:conservative] }
+ update = { :gems => update, :conservative => conservative }
+ elsif update
+ update = { :conservative => conservative } if conservative
end
definition = Bundler.definition(update)
diff --git a/lib/bundler/cli/open.rb b/lib/bundler/cli/open.rb
index df32e2f38b..ea504344f3 100644
--- a/lib/bundler/cli/open.rb
+++ b/lib/bundler/cli/open.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "shellwords"
-
module Bundler
class CLI::Open
attr_reader :options, :name
@@ -19,6 +17,7 @@ module Bundler
else
path = spec.full_gem_path
Dir.chdir(path) do
+ require "shellwords"
command = Shellwords.split(editor) + [path]
Bundler.with_original_env do
system(*command)
diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb
index 0b710e9782..d5183b060b 100644
--- a/lib/bundler/cli/outdated.rb
+++ b/lib/bundler/cli/outdated.rb
@@ -3,18 +3,16 @@
module Bundler
class CLI::Outdated
attr_reader :options, :gems, :options_include_groups, :filter_options_patch, :sources, :strict
- attr_accessor :outdated_gems_by_groups, :outdated_gems_list
+ attr_accessor :outdated_gems
def initialize(options, gems)
@options = options
@gems = gems
@sources = Array(options[:source])
- @filter_options_patch = options.keys &
- %w[filter-major filter-minor filter-patch]
+ @filter_options_patch = options.keys & %w[filter-major filter-minor filter-patch]
- @outdated_gems_by_groups = {}
- @outdated_gems_list = []
+ @outdated_gems = []
@options_include_groups = [:group, :groups].any? do |v|
options.keys.include?(v.to_s)
@@ -22,8 +20,7 @@ module Bundler
# the patch level options imply strict is also true. It wouldn't make
# sense otherwise.
- @strict = options["filter-strict"] ||
- Bundler::CLI::Common.patch_level_options(options).any?
+ @strict = options["filter-strict"] || Bundler::CLI::Common.patch_level_options(options).any?
end
def run
@@ -75,87 +72,67 @@ module Bundler
gemfile_specs + dependency_specs
end
- specs.sort_by(&:name).each do |current_spec|
- next if !gems.empty? && !gems.include?(current_spec.name)
+ specs.sort_by(&:name).uniq(&:name).each do |current_spec|
+ next unless gems.empty? || gems.include?(current_spec.name)
- dependency = current_dependencies[current_spec.name]
active_spec = retrieve_active_spec(definition, current_spec)
+ next unless active_spec
- next if active_spec.nil?
- next if filter_options_patch.any? &&
- !update_present_via_semver_portions(current_spec, active_spec, options)
+ next unless filter_options_patch.empty? || update_present_via_semver_portions(current_spec, active_spec, options)
gem_outdated = Gem::Version.new(active_spec.version) > Gem::Version.new(current_spec.version)
next unless gem_outdated || (current_spec.git_version != active_spec.git_version)
- groups = nil
+
+ dependency = current_dependencies[current_spec.name]
+ groups = ""
if dependency && !options[:parseable]
groups = dependency.groups.join(", ")
end
- outdated_gems_list << { :active_spec => active_spec,
- :current_spec => current_spec,
- :dependency => dependency,
- :groups => groups }
-
- outdated_gems_by_groups[groups] ||= []
- outdated_gems_by_groups[groups] << outdated_gems_list[-1]
+ outdated_gems << {
+ :active_spec => active_spec,
+ :current_spec => current_spec,
+ :dependency => dependency,
+ :groups => groups,
+ }
end
- if outdated_gems_list.empty?
- display_nothing_outdated_message
- else
+ if outdated_gems.empty?
unless options[:parseable]
- Bundler.ui.info(header_outdated_message)
+ Bundler.ui.info(nothing_outdated_message)
end
-
+ else
if options_include_groups
- ordered_groups = outdated_gems_by_groups.keys.compact.sort
- ordered_groups.insert(0, nil).each do |groups|
- gems = outdated_gems_by_groups[groups]
- contains_group = if groups
- groups.split(", ").include?(options[:group])
- else
- options[:group] == "group"
- end
+ relevant_outdated_gems = outdated_gems.group_by {|g| g[:groups] }.sort.flat_map do |groups, gems|
+ contains_group = groups.split(", ").include?(options[:group])
+ next unless options[:groups] || contains_group
- next if (!options[:groups] && !contains_group) || gems.nil?
+ gems
+ end.compact
- unless options[:parseable]
- Bundler.ui.info(header_group_message(groups))
+ if options[:parseable]
+ relevant_outdated_gems.each do |gems|
+ print_gems(gems)
end
-
- print_gems(gems)
+ else
+ print_gems_table(relevant_outdated_gems)
end
+ elsif options[:parseable]
+ print_gems(outdated_gems)
else
- print_gems(outdated_gems_list)
+ print_gems_table(outdated_gems)
end
exit 1
end
end
- private
+ private
def groups_text(group_text, groups)
"#{group_text}#{groups.split(",").size > 1 ? "s" : ""} \"#{groups}\""
end
- def header_outdated_message
- if options[:pre]
- "Outdated gems included in the bundle (including pre-releases):"
- else
- "Outdated gems included in the bundle:"
- end
- end
-
- def header_group_message(groups)
- if groups
- "===== #{groups_text("Group", groups)} ====="
- else
- "===== Without group ====="
- end
- end
-
def nothing_outdated_message
if filter_options_patch.any?
display = filter_options_patch.map do |o|
@@ -169,23 +146,16 @@ module Bundler
end
def retrieve_active_spec(definition, current_spec)
- if strict
- active_spec = definition.find_resolved_spec(current_spec)
- else
- active_specs = definition.find_indexed_specs(current_spec)
- if !current_spec.version.prerelease? && !options[:pre] && active_specs.size > 1
- active_specs.delete_if {|b| b.respond_to?(:version) && b.version.prerelease? }
- end
- active_spec = active_specs.last
- end
+ active_spec = definition.resolve.find_by_name_and_platform(current_spec.name, current_spec.platform)
+ return unless active_spec
- active_spec
- end
+ return active_spec if strict
- def display_nothing_outdated_message
- unless options[:parseable]
- Bundler.ui.info(nothing_outdated_message)
+ active_specs = active_spec.source.specs.search(current_spec.name).select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version)
+ if !current_spec.version.prerelease? && !options[:pre] && active_specs.size > 1
+ active_specs.delete_if {|b| b.respond_to?(:version) && b.version.prerelease? }
end
+ active_specs.last
end
def print_gems(gems_list)
@@ -199,6 +169,19 @@ module Bundler
end
end
+ def print_gems_table(gems_list)
+ data = gems_list.map do |gem|
+ gem_column_for(
+ gem[:current_spec],
+ gem[:active_spec],
+ gem[:dependency],
+ gem[:groups],
+ )
+ end
+
+ print_indented([table_header] + data)
+ end
+
def print_gem(current_spec, active_spec, dependency, groups)
spec_version = "#{active_spec.version}#{active_spec.git_version}"
spec_version += " (from #{active_spec.loaded_from})" if Bundler.ui.debug? && active_spec.loaded_from
@@ -213,7 +196,7 @@ module Bundler
output_message = if options[:parseable]
spec_outdated_info.to_s
- elsif options_include_groups || !groups
+ elsif options_include_groups || groups.empty?
" * #{spec_outdated_info}"
else
" * #{spec_outdated_info} in #{groups_text("group", groups)}"
@@ -222,14 +205,22 @@ module Bundler
Bundler.ui.info output_message.rstrip
end
+ def gem_column_for(current_spec, active_spec, dependency, groups)
+ current_version = "#{current_spec.version}#{current_spec.git_version}"
+ spec_version = "#{active_spec.version}#{active_spec.git_version}"
+ dependency = dependency.requirement if dependency
+
+ ret_val = [active_spec.name, current_version, spec_version, dependency.to_s, groups.to_s]
+ ret_val << active_spec.loaded_from.to_s if Bundler.ui.debug?
+ ret_val
+ end
+
def check_for_deployment_mode!
return unless Bundler.frozen_bundle?
- suggested_command = if Bundler.settings.locations("frozen")[:global]
+ suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any?
"bundle config unset frozen"
elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
"bundle config unset deployment"
- else
- "bundle install --no-deployment"
end
raise ProductionError, "You are trying to check outdated gems in " \
"deployment mode. Run `bundle outdated` elsewhere.\n" \
@@ -266,5 +257,34 @@ module Bundler
version_section = spec.version.segments[version_portion_index, 1]
version_section.to_a[0].to_i
end
+
+ def print_indented(matrix)
+ header = matrix[0]
+ data = matrix[1..-1]
+
+ column_sizes = Array.new(header.size) do |index|
+ matrix.max_by {|row| row[index].length }[index].length
+ end
+
+ Bundler.ui.info justify(header, column_sizes)
+
+ data.sort_by! {|row| row[0] }
+
+ data.each do |row|
+ Bundler.ui.info justify(row, column_sizes)
+ end
+ end
+
+ def table_header
+ header = ["Gem", "Current", "Latest", "Requested", "Groups"]
+ header << "Path" if Bundler.ui.debug?
+ header
+ end
+
+ def justify(row, sizes)
+ row.each_with_index.map do |element, index|
+ element.ljust(sizes[index])
+ end.join(" ").strip + "\n"
+ end
end
end
diff --git a/lib/bundler/cli/package.rb b/lib/bundler/cli/package.rb
deleted file mode 100644
index b31b67776d..0000000000
--- a/lib/bundler/cli/package.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler
- class CLI::Package
- attr_reader :options
-
- def initialize(options)
- @options = options
- end
-
- def run
- Bundler.ui.level = "error" if options[:quiet]
- Bundler.settings.set_command_option_if_given :path, options[:path]
- Bundler.settings.set_command_option_if_given :cache_path, options["cache-path"]
-
- setup_cache_all
- install
-
- # TODO: move cache contents here now that all bundles are locked
- custom_path = Bundler.settings[:path] if options[:path]
-
- Bundler.settings.temporary(:cache_all_platforms => options["all-platforms"]) do
- Bundler.load.cache(custom_path)
- end
- end
-
- private
-
- def install
- require_relative "install"
- options = self.options.dup
- options["local"] = false if Bundler.settings[:cache_all_platforms]
- Bundler::CLI::Install.new(options).run
- end
-
- def setup_cache_all
- all = options.fetch(:all, Bundler.feature_flag.cache_all? || nil)
-
- Bundler.settings.set_command_option_if_given :cache_all, all
-
- if Bundler.definition.has_local_dependencies? && !Bundler.feature_flag.cache_all?
- Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \
- "to package them as well, please pass the --all flag. This will be the default " \
- "on Bundler 3.0."
- end
- end
- end
-end
diff --git a/lib/bundler/cli/plugin.rb b/lib/bundler/cli/plugin.rb
index 1155c4ec9b..fe3f4412fa 100644
--- a/lib/bundler/cli/plugin.rb
+++ b/lib/bundler/cli/plugin.rb
@@ -23,6 +23,16 @@ module Bundler
Bundler::Plugin.install(plugins, options)
end
+ desc "uninstall PLUGINS", "Uninstall the plugins"
+ long_desc <<-D
+ Uninstall given list of plugins. To uninstall all the plugins, use -all option.
+ D
+ method_option "all", :type => :boolean, :default => nil, :banner =>
+ "Uninstall all the installed plugins. If no plugin is installed, then it does nothing."
+ def uninstall(*plugins)
+ Bundler::Plugin.uninstall(plugins, options)
+ end
+
desc "list", "List the installed plugins and available commands"
def list
Bundler::Plugin.list
diff --git a/lib/bundler/cli/pristine.rb b/lib/bundler/cli/pristine.rb
index 532b3e0b5b..d6654f8053 100644
--- a/lib/bundler/cli/pristine.rb
+++ b/lib/bundler/cli/pristine.rb
@@ -29,6 +29,11 @@ module Bundler
FileUtils.rm_rf spec.full_gem_path
when Source::Git
+ if source.local?
+ Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is locally overridden.")
+ next
+ end
+
source.remote!
if extension_cache_path = source.extension_cache_path(spec)
FileUtils.rm_rf extension_cache_path
diff --git a/lib/bundler/cli/remove.rb b/lib/bundler/cli/remove.rb
index cd6a2cec28..44a4d891dd 100644
--- a/lib/bundler/cli/remove.rb
+++ b/lib/bundler/cli/remove.rb
@@ -11,8 +11,7 @@ module Bundler
raise InvalidOption, "Please specify gems to remove." if @gems.empty?
Injector.remove(@gems, {})
-
- Installer.install(Bundler.root, Bundler.definition) if @options["install"]
+ Installer.install(Bundler.root, Bundler.definition)
end
end
end
diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb
index 3748c25b89..5eaaba1ef7 100644
--- a/lib/bundler/cli/show.rb
+++ b/lib/bundler/cli/show.rb
@@ -53,7 +53,7 @@ module Bundler
end
end
- private
+ private
def fetch_latest_specs
definition = Bundler.definition(true)
diff --git a/lib/bundler/cli/update.rb b/lib/bundler/cli/update.rb
index 529dd9c94d..95a8886ea5 100644
--- a/lib/bundler/cli/update.rb
+++ b/lib/bundler/cli/update.rb
@@ -9,7 +9,7 @@ module Bundler
end
def run
- Bundler.ui.level = "error" if options[:quiet]
+ Bundler.ui.level = "warn" if options[:quiet]
Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins?
@@ -27,9 +27,14 @@ module Bundler
raise InvalidOption, "Cannot specify --all along with specific options."
end
+ conservative = options[:conservative]
+
if full_update
- # We're doing a full update
- Bundler.definition(true)
+ if conservative
+ Bundler.definition(:conservative => conservative)
+ else
+ Bundler.definition(true)
+ end
else
unless Bundler.default_lockfile.exist?
raise GemfileLockNotFound, "This Bundle hasn't been installed yet. " \
@@ -43,7 +48,7 @@ module Bundler
end
Bundler.definition(:gems => gems, :sources => sources, :ruby => options[:ruby],
- :lock_shared_dependencies => options[:conservative],
+ :conservative => conservative,
:bundler => options[:bundler])
end
@@ -61,7 +66,7 @@ module Bundler
if locked_gems = Bundler.definition.locked_gems
previous_locked_info = locked_gems.specs.reduce({}) do |h, s|
- h[s.name] = { :spec => s, :version => s.version, :source => s.source.to_s }
+ h[s.name] = { :spec => s, :version => s.version, :source => s.source.identifier }
h
end
end
@@ -82,7 +87,7 @@ module Bundler
locked_spec = locked_info[:spec]
new_spec = Bundler.definition.specs[name].first
unless new_spec
- if Bundler.rubygems.platforms.none? {|p| locked_spec.match_platform(p) }
+ unless locked_spec.match_platform(Bundler.local_platform)
Bundler.ui.warn "Bundler attempted to update #{name} but it was not considered because it is for a different platform from the current one"
end
@@ -90,7 +95,7 @@ module Bundler
end
locked_source = locked_info[:source]
- new_source = new_spec.source.to_s
+ new_source = new_spec.source.identifier
next if locked_source != new_source
new_version = new_spec.version
@@ -106,6 +111,8 @@ module Bundler
Bundler.ui.confirm "Bundle updated!"
Bundler::CLI::Common.output_without_groups_message(:update)
Bundler::CLI::Common.output_post_install_messages installer.post_install_messages
+
+ Bundler::CLI::Common.output_fund_metadata_summary
end
end
end
diff --git a/lib/bundler/compact_index_client.rb b/lib/bundler/compact_index_client.rb
index a5120dbba4..d5dbeb3b10 100644
--- a/lib/bundler/compact_index_client.rb
+++ b/lib/bundler/compact_index_client.rb
@@ -5,7 +5,7 @@ require "set"
module Bundler
class CompactIndexClient
- DEBUG_MUTEX = Mutex.new
+ DEBUG_MUTEX = Thread::Mutex.new
def self.debug
return unless ENV["DEBUG_COMPACT_INDEX"]
DEBUG_MUTEX.synchronize { warn("[#{self}] #{yield}") }
@@ -25,7 +25,7 @@ module Bundler
@endpoints = Set.new
@info_checksums_by_name = {}
@parsed_checksums = false
- @mutex = Mutex.new
+ @mutex = Thread::Mutex.new
end
def execution_mode=(block)
@@ -87,7 +87,7 @@ module Bundler
@parsed_checksums = true
end
- private
+ private
def update(local_path, remote_path)
Bundler::CompactIndexClient.debug { "update(#{local_path}, #{remote_path})" }
diff --git a/lib/bundler/compact_index_client/cache.rb b/lib/bundler/compact_index_client/cache.rb
index f6105d3bb3..c2cd069ec1 100644
--- a/lib/bundler/compact_index_client/cache.rb
+++ b/lib/bundler/compact_index_client/cache.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_relative "gem_parser"
+
module Bundler
class CompactIndexClient
class Cache
@@ -83,7 +85,7 @@ module Bundler
gem_line ? parse_gem(gem_line) : nil
end
- private
+ private
def lines(path)
return [] unless path.file?
@@ -92,19 +94,9 @@ module Bundler
header ? lines[header + 1..-1] : lines
end
- def parse_gem(string)
- version_and_platform, rest = string.split(" ", 2)
- version, platform = version_and_platform.split("-", 2)
- dependencies, requirements = rest.split("|", 2).map {|s| s.split(",") } if rest
- dependencies = dependencies ? dependencies.map {|d| parse_dependency(d) } : []
- requirements = requirements ? requirements.map {|r| parse_dependency(r) } : []
- [version, platform, dependencies, requirements]
- end
-
- def parse_dependency(string)
- dependency = string.split(":")
- dependency[-1] = dependency[-1].split("&") if dependency.size > 1
- dependency
+ def parse_gem(line)
+ @dependency_parser ||= GemParser.new
+ @dependency_parser.parse(line)
end
def info_roots
diff --git a/lib/bundler/compact_index_client/gem_parser.rb b/lib/bundler/compact_index_client/gem_parser.rb
new file mode 100644
index 0000000000..e7bf4c6001
--- /dev/null
+++ b/lib/bundler/compact_index_client/gem_parser.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Bundler
+ class CompactIndexClient
+ if defined?(Gem::Resolver::APISet::GemParser)
+ GemParser = Gem::Resolver::APISet::GemParser
+ else
+ class GemParser
+ def parse(line)
+ version_and_platform, rest = line.split(" ", 2)
+ version, platform = version_and_platform.split("-", 2)
+ dependencies, requirements = rest.split("|", 2).map {|s| s.split(",") } if rest
+ dependencies = dependencies ? dependencies.map {|d| parse_dependency(d) } : []
+ requirements = requirements ? requirements.map {|d| parse_dependency(d) } : []
+ [version, platform, dependencies, requirements]
+ end
+
+ private
+
+ def parse_dependency(string)
+ dependency = string.split(":")
+ dependency[-1] = dependency[-1].split("&") if dependency.size > 1
+ dependency
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bundler/compact_index_client/updater.rb b/lib/bundler/compact_index_client/updater.rb
index 40232019bc..d9b9cec0d4 100644
--- a/lib/bundler/compact_index_client/updater.rb
+++ b/lib/bundler/compact_index_client/updater.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
require_relative "../vendored_fileutils"
-require "stringio"
-require "zlib"
module Bundler
class CompactIndexClient
@@ -22,13 +20,13 @@ module Bundler
def initialize(fetcher)
@fetcher = fetcher
- require "tmpdir"
+ require_relative "../vendored_tmpdir"
end
def update(local_path, remote_path, retrying = nil)
headers = {}
- Dir.mktmpdir("bundler-compact-index-") do |local_temp_dir|
+ Bundler::Dir.mktmpdir("bundler-compact-index-") do |local_temp_dir|
local_temp_path = Pathname.new(local_temp_dir).join(local_path.basename)
# first try to fetch any new bytes on the existing file
@@ -45,29 +43,27 @@ module Bundler
else
"bytes=#{local_temp_path.size}-"
end
- else
- # Fastly ignores Range when Accept-Encoding: gzip is set
- headers["Accept-Encoding"] = "gzip"
end
response = @fetcher.call(remote_path, headers)
return nil if response.is_a?(Net::HTTPNotModified)
content = response.body
- if response["Content-Encoding"] == "gzip"
- content = Zlib::GzipReader.new(StringIO.new(content)).read
- end
- SharedHelpers.filesystem_access(local_temp_path) do
+ etag = (response["ETag"] || "").gsub(%r{\AW/}, "")
+ correct_response = SharedHelpers.filesystem_access(local_temp_path) do
if response.is_a?(Net::HTTPPartialContent) && local_temp_path.size.nonzero?
local_temp_path.open("a") {|f| f << slice_body(content, 1..-1) }
+
+ etag_for(local_temp_path) == etag
else
- local_temp_path.open("w") {|f| f << content }
+ local_temp_path.open("wb") {|f| f << content }
+
+ etag.length.zero? || etag_for(local_temp_path) == etag
end
end
- response_etag = (response["ETag"] || "").gsub(%r{\AW/}, "")
- if etag_for(local_temp_path) == response_etag
+ if correct_response
SharedHelpers.filesystem_access(local_path) do
FileUtils.mv(local_temp_path, local_path)
end
@@ -75,16 +71,11 @@ module Bundler
end
if retrying
- raise MisMatchedChecksumError.new(remote_path, response_etag, etag_for(local_temp_path))
+ raise MisMatchedChecksumError.new(remote_path, etag, etag_for(local_temp_path))
end
update(local_path, remote_path, :retrying)
end
- rescue Errno::EACCES
- raise Bundler::PermissionError,
- "Bundler does not have write access to create a temp directory " \
- "within #{Dir.tmpdir}. Bundler must have write access to your " \
- "systems temp directory to function properly. "
rescue Zlib::GzipFile::Error
raise Bundler::HTTPError
end
@@ -100,11 +91,11 @@ module Bundler
def checksum_for_file(path)
return nil unless path.file?
- # This must use IO.read instead of Digest.file().hexdigest
+ # This must use File.read instead of Digest.file().hexdigest
# because we need to preserve \n line endings on windows when calculating
# the checksum
SharedHelpers.filesystem_access(path, :read) do
- SharedHelpers.digest(:MD5).hexdigest(IO.read(path))
+ SharedHelpers.digest(:MD5).hexdigest(File.read(path))
end
end
end
diff --git a/lib/bundler/current_ruby.rb b/lib/bundler/current_ruby.rb
index c132e8ecc0..f84d68e262 100644
--- a/lib/bundler/current_ruby.rb
+++ b/lib/bundler/current_ruby.rb
@@ -20,6 +20,7 @@ module Bundler
2.5
2.6
2.7
+ 3.0
].freeze
KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze
@@ -64,19 +65,19 @@ module Bundler
end
def mswin?
- Bundler::WINDOWS
+ Gem.win_platform?
end
def mswin64?
- Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64"
+ Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mswin64" && Bundler.local_platform.cpu == "x64"
end
def mingw?
- Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64"
+ Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu != "x64"
end
def x64_mingw?
- Bundler::WINDOWS && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64"
+ Gem.win_platform? && Bundler.local_platform != Gem::Platform::RUBY && Bundler.local_platform.os == "mingw32" && Bundler.local_platform.cpu == "x64"
end
(KNOWN_MINOR_VERSIONS + KNOWN_MAJOR_VERSIONS).each do |version|
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index d6fbb0b5b7..584f379256 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require_relative "lockfile_parser"
-require "set"
module Bundler
class Definition
@@ -57,10 +56,8 @@ module Bundler
@unlocking_bundler = false
@unlocking = unlock
else
- unlock = unlock.dup
@unlocking_bundler = unlock.delete(:bundler)
- unlock.delete_if {|_k, v| Array(v).empty? }
- @unlocking = !unlock.empty?
+ @unlocking = unlock.any? {|_k, v| !Array(v).empty? }
end
@dependencies = dependencies
@@ -76,7 +73,7 @@ module Bundler
@lockfile_contents = String.new
@locked_bundler_version = nil
@locked_ruby_version = nil
- @locked_specs_incomplete_for_platform = false
+ @new_platform = nil
if lockfile && File.exist?(lockfile)
@lockfile_contents = Bundler.read_file(lockfile)
@@ -106,27 +103,43 @@ module Bundler
@locked_platforms = []
end
- @unlock[:gems] ||= []
+ locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
+ @multisource_allowed = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? && Bundler.frozen_bundle?
+
+ if @multisource_allowed
+ unless sources.aggregate_global_source?
+ msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure."
+
+ Bundler::SharedHelpers.major_deprecation 2, msg
+ end
+
+ @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
+ end
+
@unlock[:sources] ||= []
@unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
@ruby_version.diff(locked_ruby_version_object)
end
@unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
- add_current_platform unless Bundler.frozen_bundle?
+ add_current_platform unless current_ruby_platform_locked? || Bundler.frozen_bundle?
converge_path_sources_to_gemspec_sources
@path_changes = converge_paths
@source_changes = converge_sources
- unless @unlock[:lock_shared_dependencies]
- eager_unlock = expand_dependencies(@unlock[:gems], true)
- @unlock[:gems] = @locked_specs.for(eager_unlock, [], false, false, false).map(&:name)
+ if @unlock[:conservative]
+ @unlock[:gems] ||= @dependencies.map(&:name)
+ else
+ eager_unlock = expand_dependencies(@unlock[:gems] || [], true)
+ @unlock[:gems] = @locked_specs.for(eager_unlock, false, false).map(&:name)
end
@dependency_changes = converge_dependencies
@local_changes = converge_locals
+ @locked_specs_incomplete_for_platform = !@locked_specs.for(requested_dependencies & expand_dependencies(locked_dependencies), true, true)
+
@requires = compute_requires
end
@@ -145,17 +158,21 @@ module Bundler
end
end
+ def resolve_only_locally!
+ @remote = false
+ sources.local_only!
+ resolve
+ end
+
def resolve_with_cache!
- raise "Specs already loaded" if @specs
sources.cached!
- specs
+ resolve
end
def resolve_remotely!
- raise "Specs already loaded" if @specs
@remote = true
sources.remote!
- specs
+ resolve
end
# For given dependency list returns a SpecSet with Gemspec of all the required
@@ -165,25 +182,7 @@ module Bundler
#
# @return [Bundler::SpecSet]
def specs
- @specs ||= begin
- begin
- specs = resolve.materialize(requested_dependencies)
- rescue GemNotFound => e # Handle yanked gem
- gem_name, gem_version = extract_gem_info(e)
- locked_gem = @locked_specs[gem_name].last
- raise if locked_gem.nil? || locked_gem.version.to_s != gem_version || !@remote
- raise GemNotFound, "Your bundle is locked to #{locked_gem}, but that version could not " \
- "be found in any of the sources listed in your Gemfile. If you haven't changed sources, " \
- "that means the author of #{locked_gem} has removed it. You'll need to update your bundle " \
- "to a version other than #{locked_gem} that hasn't been removed in order to install."
- end
- unless specs["bundler"].any?
- bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
- specs["bundler"] = bundler
- end
-
- specs
- end
+ @specs ||= materialize(requested_dependencies)
end
def new_specs
@@ -194,14 +193,8 @@ module Bundler
@locked_specs - specs
end
- def new_platform?
- @new_platform
- end
-
def missing_specs
- missing = []
- resolve.materialize(requested_dependencies, missing)
- missing
+ resolve.materialize(requested_dependencies).missing_specs
end
def missing_specs?
@@ -210,7 +203,6 @@ module Bundler
Bundler.ui.debug "The definition is missing #{missing.map(&:full_name)}"
true
rescue BundlerError => e
- @index = nil
@resolve = nil
@specs = nil
@gem_version_promoter = nil
@@ -220,21 +212,35 @@ module Bundler
end
def requested_specs
- @requested_specs ||= begin
- groups = requested_groups
- groups.map!(&:to_sym)
- specs_for(groups)
- end
+ specs_for(requested_groups)
+ end
+
+ def requested_dependencies
+ dependencies_for(requested_groups)
end
def current_dependencies
- dependencies.select(&:should_include?)
+ dependencies.select do |d|
+ d.should_include? && !d.gem_platforms(@platforms).empty?
+ end
+ end
+
+ def locked_dependencies
+ @locked_deps.values
end
def specs_for(groups)
- deps = dependencies.select {|d| (d.groups & groups).any? }
- deps.delete_if {|d| !d.should_include? }
- specs.for(expand_dependencies(deps))
+ return specs if groups.empty?
+ deps = dependencies_for(groups)
+ materialize(deps)
+ end
+
+ def dependencies_for(groups)
+ groups.map!(&:to_sym)
+ deps = current_dependencies.reject do |d|
+ (d.groups & groups).empty?
+ end
+ expand_dependencies(deps)
end
# Resolve all the dependencies specified in Gemfile. It ensures that
@@ -245,76 +251,20 @@ module Bundler
def resolve
@resolve ||= begin
last_resolve = converge_locked_specs
- resolve =
- if Bundler.frozen_bundle?
- Bundler.ui.debug "Frozen, using resolution from the lockfile"
- last_resolve
- elsif !unlocking? && nothing_changed?
- Bundler.ui.debug("Found no changes, using resolution from the lockfile")
- last_resolve
- else
- # Run a resolve against the locally available gems
- Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
- last_resolve.merge Resolver.resolve(expanded_dependencies, index, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
- end
-
- # filter out gems that _can_ be installed on multiple platforms, but don't need
- # to be
- resolve.for(expand_dependencies(dependencies, true), [], false, false, false)
- end
- end
-
- def index
- @index ||= Index.build do |idx|
- dependency_names = @dependencies.map(&:name)
-
- sources.all_sources.each do |source|
- source.dependency_names = dependency_names - pinned_spec_names(source)
- idx.add_source source.specs
- dependency_names.concat(source.unmet_deps).uniq!
- end
-
- double_check_for_index(idx, dependency_names)
- end
- end
-
- # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
- # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
- # but will not have found any versions of Bar from source B, which is a problem if the requested version
- # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
- # each spec we found, we add all possible versions from all sources to the index.
- def double_check_for_index(idx, dependency_names)
- pinned_names = pinned_spec_names
- loop do
- idxcount = idx.size
-
- names = :names # do this so we only have to traverse to get dependency_names from the index once
- unmet_dependency_names = lambda do
- return names unless names == :names
- new_names = sources.all_sources.map(&:dependency_names_to_double_check)
- return names = nil if new_names.compact!
- names = new_names.flatten(1).concat(dependency_names)
- names.uniq!
- names -= pinned_names
- names
- end
-
- sources.all_sources.each do |source|
- source.double_check_for(unmet_dependency_names)
+ if Bundler.frozen_bundle?
+ Bundler.ui.debug "Frozen, using resolution from the lockfile"
+ last_resolve
+ elsif !unlocking? && nothing_changed?
+ Bundler.ui.debug("Found no changes, using resolution from the lockfile")
+ last_resolve
+ else
+ # Run a resolve against the locally available gems
+ Bundler.ui.debug("Found changes from the lockfile, re-resolving dependencies because #{change_reason}")
+ expanded_dependencies = expand_dependencies(dependencies + metadata_dependencies, @remote)
+ Resolver.resolve(expanded_dependencies, source_requirements, last_resolve, gem_version_promoter, additional_base_requirements_for_resolve, platforms)
end
-
- break if idxcount == idx.size
end
end
- private :double_check_for_index
-
- def has_rubygems_remotes?
- sources.rubygems_sources.any? {|s| s.remotes.any? }
- end
-
- def has_local_dependencies?
- !sources.path_sources.empty? || !sources.git_sources.empty?
- end
def spec_git_paths
sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
@@ -396,12 +346,10 @@ module Bundler
"updated #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} to version control."
unless explicit_flag
- suggested_command = if Bundler.settings.locations("frozen")[:global]
+ suggested_command = if Bundler.settings.locations("frozen").keys.&([:global, :local]).any?
"bundle config unset frozen"
elsif Bundler.settings.locations("deployment").keys.&([:global, :local]).any?
"bundle config unset deployment"
- else
- "bundle install --no-deployment"
end
msg << "\n\nIf this is a development machine, remove the #{Bundler.default_gemfile} " \
"freeze \nby running `#{suggested_command}`."
@@ -416,44 +364,26 @@ module Bundler
added.concat new_platforms.map {|p| "* platform: #{p}" }
deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
- gemfile_sources = sources.lock_sources
-
- new_sources = gemfile_sources - @locked_sources
- deleted_sources = @locked_sources - gemfile_sources
-
- new_deps = @dependencies - @locked_deps.values
- deleted_deps = @locked_deps.values - @dependencies
-
- # Check if it is possible that the source is only changed thing
- if (new_deps.empty? && deleted_deps.empty?) && (!new_sources.empty? && !deleted_sources.empty?)
- new_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
- deleted_sources.reject! {|source| (source.path? && source.path.exist?) || equivalent_rubygems_remotes?(source) }
- end
-
- if @locked_sources != gemfile_sources
- if new_sources.any?
- added.concat new_sources.map {|source| "* source: #{source}" }
- end
-
- if deleted_sources.any?
- deleted.concat deleted_sources.map {|source| "* source: #{source}" }
- end
- end
+ new_deps = @dependencies - locked_dependencies
+ deleted_deps = locked_dependencies - @dependencies
added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
- if deleted_deps.any?
- deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" }
- end
+ deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
both_sources = Hash.new {|h, k| h[k] = [] }
@dependencies.each {|d| both_sources[d.name][0] = d }
- @locked_deps.each {|name, d| both_sources[name][1] = d.source }
+ 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 || sources.default_source
+ lock_source = lock_dep.source || sources.default_source
+ next if lock_source.include?(gemfile_source)
- both_sources.each do |name, (dep, lock_source)|
- next unless (dep.nil? && !lock_source.nil?) || (!dep.nil? && !lock_source.nil? && !lock_source.can_lock?(dep))
- gemfile_source_name = (dep && dep.source) || "no specified source"
- lockfile_source_name = lock_source || "no specified source"
- changed << "* #{name} from `#{gemfile_source_name}` to `#{lockfile_source_name}`"
+ gemfile_source_name = dep.source ? gemfile_source.identifier : "no specified source"
+ lockfile_source_name = lock_dep.source ? lock_source.identifier : "no specified source"
+ changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
end
reason = change_reason
@@ -497,15 +427,11 @@ module Bundler
end
def validate_platforms!
- return if @platforms.any? do |bundle_platform|
- Bundler.rubygems.platforms.any? do |local_platform|
- MatchPlatform.platforms_match?(bundle_platform, local_platform)
- end
- end
+ return if current_platform_locked?
raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
- "but your local platforms are #{Bundler.rubygems.platforms.map(&:to_s)}, and " \
- "there's no compatible match between those two lists."
+ "but your local platform is #{Bundler.local_platform}. " \
+ "Add the current platform to the lockfile with `bundle lock --add-platform #{Bundler.local_platform}` and try again."
end
def add_platform(platform)
@@ -518,16 +444,10 @@ module Bundler
raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
end
- def add_current_platform
- current_platforms.each {|platform| add_platform(platform) }
- end
-
- def find_resolved_spec(current_spec)
- specs.find_by_name_and_platform(current_spec.name, current_spec.platform)
- end
-
- def find_indexed_specs(current_spec)
- index[current_spec.name].select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version)
+ def most_specific_locked_platform
+ @platforms.min_by do |bundle_platform|
+ platform_specificity_match(bundle_platform, local_platform)
+ end
end
attr_reader :sources
@@ -541,14 +461,51 @@ module Bundler
@unlocking
end
- private
+ private
+
+ def materialize(dependencies)
+ specs = resolve.materialize(dependencies)
+ missing_specs = specs.missing_specs
+
+ if missing_specs.any?
+ missing_specs.each do |s|
+ locked_gem = @locked_specs[s.name].last
+ next if locked_gem.nil? || locked_gem.version != s.version || !@remote
+ raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
+ "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
+ "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
+ "removed in order to install."
+ end
- def current_platforms
- current_platform = Bundler.local_platform
- [].tap do |platforms|
- platforms << current_platform if Bundler.feature_flag.specific_platform?
- platforms << generic(current_platform)
+ raise GemNotFound, "Could not find #{missing_specs.map(&:full_name).join(", ")} in any of the sources"
end
+
+ unless specs["bundler"].any?
+ bundler = sources.metadata_source.specs.search(Gem::Dependency.new("bundler", VERSION)).last
+ specs["bundler"] = bundler
+ end
+
+ specs
+ end
+
+ def precompute_source_requirements_for_indirect_dependencies?
+ @remote && sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
+ end
+
+ def current_ruby_platform_locked?
+ return false unless generic_local_platform == Gem::Platform::RUBY
+
+ current_platform_locked?
+ end
+
+ def current_platform_locked?
+ @platforms.any? do |bundle_platform|
+ MatchPlatform.platforms_match?(bundle_platform, Bundler.local_platform)
+ end
+ end
+
+ def add_current_platform
+ add_platform(local_platform)
end
def change_reason
@@ -587,9 +544,9 @@ module Bundler
def dependencies_for_source_changed?(source, locked_source = source)
deps_for_source = @dependencies.select {|s| s.source == source }
- locked_deps_for_source = @locked_deps.values.select {|dep| dep.source == locked_source }
+ locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
- Set.new(deps_for_source) != Set.new(locked_deps_for_source)
+ deps_for_source.uniq.sort != locked_deps_for_source.sort
end
def specs_for_source_changed?(source)
@@ -648,36 +605,11 @@ module Bundler
end
end
- def converge_rubygems_sources
- return false if Bundler.feature_flag.disable_multisource?
-
- changes = false
-
- # Get the RubyGems sources from the Gemfile.lock
- locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
- # Get the RubyGems remotes from the Gemfile
- actual_remotes = sources.rubygems_remotes
-
- # If there is a RubyGems source in both
- if !locked_gem_sources.empty? && !actual_remotes.empty?
- locked_gem_sources.each do |locked_gem|
- # Merge the remotes from the Gemfile into the Gemfile.lock
- changes |= locked_gem.replace_remotes(actual_remotes, Bundler.settings[:allow_deployment_source_credential_changes])
- end
- end
-
- changes
- end
-
def converge_sources
- changes = false
-
- changes |= converge_rubygems_sources
-
# Replace the sources from the Gemfile with the sources from the Gemfile.lock,
# if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
# source in the Gemfile.lock, use the one from the Gemfile.
- changes |= sources.replace_sources!(@locked_sources)
+ changes = sources.replace_sources!(@locked_sources)
sources.all_sources.each do |source|
# If the source is unlockable and the current command allows an unlock of
@@ -695,28 +627,14 @@ module Bundler
end
def converge_dependencies
- frozen = Bundler.frozen_bundle?
- (@dependencies + @locked_deps.values).each do |dep|
- locked_source = @locked_deps[dep.name]
- # This is to make sure that if bundler is installing in deployment mode and
- # after locked_source and sources don't match, we still use locked_source.
- if frozen && !locked_source.nil? &&
- locked_source.respond_to?(:source) && locked_source.source.instance_of?(Source::Path) && locked_source.source.path.exist?
- dep.source = locked_source.source
- elsif dep.source
+ changes = false
+
+ @dependencies.each do |dep|
+ if dep.source
dep.source = sources.get(dep.source)
end
- if dep.source.is_a?(Source::Gemspec)
- dep.platforms.concat(@platforms.map {|p| Dependency::REVERSE_PLATFORM_MAP[p] }.flatten(1)).uniq!
- end
- end
- changes = false
- # We want to know if all match, but don't want to check all entries
- # This means we need to return false if any dependency doesn't match
- # the lock or doesn't exist in the lock.
- @dependencies.each do |dependency|
- unless locked_dep = @locked_deps[dependency.name]
+ unless locked_dep = @locked_deps[dep.name]
changes = true
next
end
@@ -727,11 +645,11 @@ module Bundler
# directive, the lockfile dependencies and resolved dependencies end up
# with a mismatch on #type. Work around that by setting the type on the
# dep from the lockfile.
- locked_dep.instance_variable_set(:@type, dependency.type)
+ locked_dep.instance_variable_set(:@type, dep.type)
# We already know the name matches from the hash lookup
# so we only need to check the requirement now
- changes ||= dependency.requirement != locked_dep.requirement
+ changes ||= dep.requirement != locked_dep.requirement
end
changes
@@ -741,47 +659,37 @@ module Bundler
# commonly happen if the Gemfile has changed since the lockfile was last
# generated
def converge_locked_specs
- deps = []
-
- # Build a list of dependencies that are the same in the Gemfile
- # and Gemfile.lock. If the Gemfile modified a dependency, but
- # the gem in the Gemfile.lock still satisfies it, this is fine
- # too.
- @dependencies.each do |dep|
- locked_dep = @locked_deps[dep.name]
+ resolve = converge_specs(@locked_specs)
- # If the locked_dep doesn't match the dependency we're looking for then we ignore the locked_dep
- locked_dep = nil unless locked_dep == dep
+ diff = nil
- if in_locked_deps?(dep, locked_dep) || satisfies_locked_spec?(dep)
- deps << dep
- elsif dep.source.is_a?(Source::Path) && dep.current_platform? && (!locked_dep || dep.source != locked_dep.source)
- @locked_specs.each do |s|
- @unlock[:gems] << s.name if s.source == dep.source
- end
+ # Now, we unlock any sources that do not have anymore gems pinned to it
+ sources.all_sources.each do |source|
+ next unless source.respond_to?(:unlock!)
- dep.source.unlock! if dep.source.respond_to?(:unlock!)
- dep.source.specs.each {|s| @unlock[:gems] << s.name }
+ unless resolve.any? {|s| s.source == source }
+ diff ||= @locked_specs.to_a - resolve.to_a
+ source.unlock! if diff.any? {|s| s.source == source }
end
end
- unlock_source_unlocks_spec = Bundler.feature_flag.unlock_source_unlocks_spec?
+ resolve
+ end
+ def converge_specs(specs)
+ deps = []
converged = []
- @locked_specs.each do |s|
+ specs.each do |s|
# Replace the locked dependency's source with the equivalent source from the Gemfile
dep = @dependencies.find {|d| s.satisfies?(d) }
- s.source = (dep && dep.source) || sources.get(s.source)
- # Don't add a spec to the list if its source is expired. For example,
- # if you change a Git gem to RubyGems.
- next if s.source.nil?
- next if @unlock[:sources].include?(s.source.name)
+ if dep && (!dep.source || s.source.include?(dep.source))
+ deps << dep
+ end
- # XXX This is a backwards-compatibility fix to preserve the ability to
- # unlock a single gem by passing its name via `--source`. See issue #3759
- # TODO: delete in Bundler 2
- next if unlock_source_unlocks_spec && @unlock[:sources].include?(s.name)
+ s.source = (dep && dep.source) || sources.get(s.source) || sources.default_source unless Bundler.frozen_bundle?
+
+ next if @unlock[:sources].include?(s.source.name)
# If the spec is from a path source and it doesn't exist anymore
# then we unlock it.
@@ -793,8 +701,8 @@ module Bundler
rescue PathError, GitError
# if we won't need the source (according to the lockfile),
# don't error if the path/git source isn't available
- next if @locked_specs.
- for(requested_dependencies, [], false, true, false).
+ next if specs.
+ for(requested_dependencies, false, true).
none? {|locked_spec| locked_spec.source == s.source }
raise
@@ -806,61 +714,23 @@ module Bundler
# commonly happens if the version changed in the gemspec
next unless new_spec
- new_runtime_deps = new_spec.dependencies.select {|d| d.type != :development }
- old_runtime_deps = s.dependencies.select {|d| d.type != :development }
- # If the dependencies of the path source have changed and locked spec can't satisfy new dependencies, unlock it
- next unless new_runtime_deps.sort == old_runtime_deps.sort || new_runtime_deps.all? {|d| satisfies_locked_spec?(d) }
-
s.dependencies.replace(new_spec.dependencies)
end
- converged << s
- end
-
- resolve = SpecSet.new(converged)
- @locked_specs_incomplete_for_platform = !resolve.for(expand_dependencies(deps), @unlock[:gems], true, true)
- resolve = resolve.for(expand_dependencies(deps, true), @unlock[:gems], false, false, false)
- diff = nil
-
- # Now, we unlock any sources that do not have anymore gems pinned to it
- sources.all_sources.each do |source|
- next unless source.respond_to?(:unlock!)
-
- unless resolve.any? {|s| s.source == source }
- diff ||= @locked_specs.to_a - resolve.to_a
- source.unlock! if diff.any? {|s| s.source == source }
+ if dep.nil? && requested_dependencies.find {|d| s.name == d.name }
+ @unlock[:gems] << s.name
+ else
+ converged << s
end
end
- resolve
- end
-
- def in_locked_deps?(dep, locked_dep)
- # Because the lockfile can't link a dep to a specific remote, we need to
- # treat sources as equivalent anytime the locked dep has all the remotes
- # that the Gemfile dep does.
- locked_dep && locked_dep.source && dep.source && locked_dep.source.include?(dep.source)
- end
-
- def satisfies_locked_spec?(dep)
- @locked_specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
- end
-
- # This list of dependencies is only used in #resolve, so it's OK to add
- # the metadata dependencies here
- def expanded_dependencies
- @expanded_dependencies ||= begin
- expand_dependencies(dependencies + metadata_dependencies, @remote)
- end
+ resolve = SpecSet.new(converged)
+ SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
end
def metadata_dependencies
@metadata_dependencies ||= begin
- ruby_versions = concat_ruby_version_requirements(@ruby_version)
- if ruby_versions.empty? || !@ruby_version.exact?
- concat_ruby_version_requirements(RubyVersion.system)
- concat_ruby_version_requirements(locked_ruby_version_object) unless @unlock[:ruby]
- end
+ ruby_versions = ruby_version_requirements(@ruby_version)
[
Dependency.new("Ruby\0", ruby_versions),
Dependency.new("RubyGems\0", Gem::VERSION),
@@ -868,83 +738,56 @@ module Bundler
end
end
- def concat_ruby_version_requirements(ruby_version, ruby_versions = [])
- return ruby_versions unless ruby_version
+ def ruby_version_requirements(ruby_version)
+ return [] unless ruby_version
if ruby_version.patchlevel
- ruby_versions << ruby_version.to_gem_version_with_patchlevel
+ [ruby_version.to_gem_version_with_patchlevel]
else
- ruby_versions.concat(ruby_version.versions.map do |version|
+ ruby_version.versions.map do |version|
requirement = Gem::Requirement.new(version)
if requirement.exact?
"~> #{version}.0"
else
requirement
end
- end)
+ end
end
end
def expand_dependencies(dependencies, remote = false)
- sorted_platforms = Resolver.sort_platforms(@platforms)
deps = []
dependencies.each do |dep|
dep = Dependency.new(dep, ">= 0") unless dep.respond_to?(:name)
- next if !remote && !dep.current_platform?
- platforms = dep.gem_platforms(sorted_platforms)
- if platforms.empty? && !Bundler.settings[:disable_platform_warnings]
- mapped_platforms = dep.expanded_platforms
- Bundler.ui.warn \
- "The dependency #{dep} will be unused by any of the platforms Bundler is installing for. " \
- "Bundler is installing for #{@platforms.join ", "} but the dependency " \
- "is only for #{mapped_platforms.join ", "}. " \
- "To add those platforms to the bundle, " \
- "run `bundle lock --add-platform #{mapped_platforms.join " "}`."
- end
- platforms.each do |p|
- deps << DepProxy.new(dep, p) if remote || p == generic_local_platform
- end
+ next unless remote || dep.current_platform?
+ target_platforms = dep.gem_platforms(remote ? @platforms : [generic_local_platform])
+ deps += expand_dependency_with_platforms(dep, target_platforms)
end
deps
end
- def requested_dependencies
- groups = requested_groups
- groups.map!(&:to_sym)
- dependencies.reject {|d| !d.should_include? || (d.groups & groups).empty? }
+ def expand_dependency_with_platforms(dep, platforms)
+ platforms.map do |p|
+ DepProxy.get_proxy(dep, p)
+ end
end
def source_requirements
- # Load all specs from remote sources
- index
-
# Record the specs available in each gem's source, so that those
# specs will be available later when the resolver knows where to
# look for that gemspec (or its dependencies)
- default = sources.default_source
- source_requirements = { :default => default }
- default = nil unless Bundler.feature_flag.disable_multisource?
- dependencies.each do |dep|
- next unless source = dep.source || default
- source_requirements[dep.name] = source
+ source_requirements = if precompute_source_requirements_for_indirect_dependencies?
+ { :default => sources.default_source }.merge(source_map.all_requirements)
+ else
+ { :default => Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
end
metadata_dependencies.each do |dep|
source_requirements[dep.name] = sources.metadata_source
end
+ source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source
source_requirements["bundler"] = sources.metadata_source # needs to come last to override
source_requirements
end
- def pinned_spec_names(skip = nil)
- pinned_names = []
- default = Bundler.feature_flag.disable_multisource? && sources.default_source
- @dependencies.each do |dep|
- next unless dep_source = dep.source || default
- next if dep_source == skip
- pinned_names << dep.name
- end
- pinned_names
- end
-
def requested_groups
groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
end
@@ -962,12 +805,6 @@ module Bundler
current == proposed
end
- def extract_gem_info(error)
- # This method will extract the error message like "Could not find foo-1.2.3 in any of the sources"
- # to an array. The first element will be the gem name (e.g. foo), the second will be the version number.
- error.message.scan(/Could not find (\w+)-(\d+(?:\.\d+)+)/).flatten
- end
-
def compute_requires
dependencies.reduce({}) do |requires, dep|
next requires unless dep.should_include?
@@ -980,23 +817,16 @@ module Bundler
end
def additional_base_requirements_for_resolve
- return [] unless @locked_gems && Bundler.feature_flag.only_update_to_newer_versions?
- dependencies_by_name = dependencies.inject({}) {|memo, dep| memo.update(dep.name => dep) }
- @locked_gems.specs.reduce({}) do |requirements, locked_spec|
+ return [] unless @locked_gems && unlocking? && !sources.expired_sources?(@locked_gems.sources)
+ converge_specs(@locked_gems.specs).map do |locked_spec|
name = locked_spec.name
- dependency = dependencies_by_name[name]
- next requirements if @locked_gems.dependencies[name] != dependency
- next requirements if dependency && dependency.source.is_a?(Source::Path)
dep = Gem::Dependency.new(name, ">= #{locked_spec.version}")
- requirements[name] = DepProxy.new(dep, locked_spec.platform)
- requirements
- end.values
+ DepProxy.get_proxy(dep, locked_spec.platform)
+ end
end
- def equivalent_rubygems_remotes?(source)
- return false unless source.is_a?(Source::Rubygems)
-
- Bundler.settings[:allow_deployment_source_credential_changes] && source.equivalent_remotes?(sources.rubygems_remotes)
+ def source_map
+ @source_map ||= SourceMap.new(sources, dependencies)
end
end
end
diff --git a/lib/bundler/dep_proxy.rb b/lib/bundler/dep_proxy.rb
index 6c32179ac1..a32dc37b49 100644
--- a/lib/bundler/dep_proxy.rb
+++ b/lib/bundler/dep_proxy.rb
@@ -4,19 +4,18 @@ module Bundler
class DepProxy
attr_reader :__platform, :dep
+ @proxies = {}
+
+ def self.get_proxy(dep, platform)
+ @proxies[[dep, platform]] ||= new(dep, platform).freeze
+ end
+
def initialize(dep, platform)
@dep = dep
@__platform = platform
end
- def hash
- @hash ||= [dep, __platform].hash
- end
-
- def ==(other)
- return false if other.class != self.class
- dep == other.dep && __platform == other.__platform
- end
+ private_class_method :new
alias_method :eql?, :==
@@ -39,7 +38,15 @@ module Bundler
s
end
- private
+ def dup
+ raise NoMethodError.new("DepProxy cannot be duplicated")
+ end
+
+ def clone
+ raise NoMethodError.new("DepProxy cannot be cloned")
+ end
+
+ private
def method_missing(*args, &blk)
@dep.send(*args, &blk)
diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb
index 6c2642163e..af07e8bc36 100644
--- a/lib/bundler/dependency.rb
+++ b/lib/bundler/dependency.rb
@@ -74,15 +74,6 @@ module Bundler
:x64_mingw_26 => Gem::Platform::X64_MINGW,
}.freeze
- REVERSE_PLATFORM_MAP = {}.tap do |reverse_platform_map|
- PLATFORM_MAP.each do |key, value|
- reverse_platform_map[value] ||= []
- reverse_platform_map[value] << key
- end
-
- reverse_platform_map.each {|_, platforms| platforms.freeze }
- end.freeze
-
def initialize(name, version, options = {}, &blk)
type = options["type"] || :runtime
super(name, version, type)
@@ -105,9 +96,11 @@ module Bundler
def gem_platforms(valid_platforms)
return valid_platforms if @platforms.empty?
+ valid_generic_platforms = valid_platforms.map {|p| [p, GemHelpers.generic(p)] }.to_h
@gem_platforms ||= expanded_platforms.compact.uniq
- valid_platforms & @gem_platforms
+ filtered_generic_platforms = valid_generic_platforms.values & @gem_platforms
+ valid_generic_platforms.select {|_, v| filtered_generic_platforms.include?(v) }.keys
end
def expanded_platforms
diff --git a/lib/bundler/digest.rb b/lib/bundler/digest.rb
new file mode 100644
index 0000000000..759f609416
--- /dev/null
+++ b/lib/bundler/digest.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+# This code was extracted from https://github.com/Solistra/ruby-digest which is under public domain
+module Bundler
+ module Digest
+ # The initial constant values for the 32-bit constant words A, B, C, D, and
+ # E, respectively.
+ SHA1_WORDS = [0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0].freeze
+
+ # The 8-bit field used for bitwise `AND` masking. Defaults to `0xFFFFFFFF`.
+ SHA1_MASK = 0xFFFFFFFF
+
+ class << self
+ def sha1(string)
+ unless string.is_a?(String)
+ raise TypeError, "can't convert #{string.class.inspect} into String"
+ end
+
+ buffer = string.b
+
+ words = SHA1_WORDS.dup
+ generate_split_buffer(buffer) do |chunk|
+ w = []
+ chunk.each_slice(4) do |a, b, c, d|
+ w << (((a << 8 | b) << 8 | c) << 8 | d)
+ end
+ a, b, c, d, e = *words
+ (16..79).each do |i|
+ w[i] = SHA1_MASK & rotate((w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]), 1)
+ end
+ 0.upto(79) do |i|
+ case i
+ when 0..19
+ f = ((b & c) | (~b & d))
+ k = 0x5A827999
+ when 20..39
+ f = (b ^ c ^ d)
+ k = 0x6ED9EBA1
+ when 40..59
+ f = ((b & c) | (b & d) | (c & d))
+ k = 0x8F1BBCDC
+ when 60..79
+ f = (b ^ c ^ d)
+ k = 0xCA62C1D6
+ end
+ t = SHA1_MASK & (SHA1_MASK & rotate(a, 5) + f + e + k + w[i])
+ a, b, c, d, e = t, a, SHA1_MASK & rotate(b, 30), c, d # rubocop:disable Style/ParallelAssignment
+ end
+ mutated = [a, b, c, d, e]
+ words.map!.with_index {|word, index| SHA1_MASK & (word + mutated[index]) }
+ end
+
+ words.pack("N*").unpack("H*").first
+ end
+
+ private
+
+ def generate_split_buffer(string, &block)
+ size = string.bytesize * 8
+ buffer = string.bytes << 128
+ buffer << 0 while buffer.size % 64 != 56
+ buffer.concat([size].pack("Q>").bytes)
+ buffer.each_slice(64, &block)
+ end
+
+ def rotate(value, spaces)
+ value << spaces | value >> (32 - spaces)
+ end
+ end
+ end
+end
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index 99a369281a..1108fc3b78 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -18,6 +18,8 @@ module Bundler
VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
platform platforms type source install_if gemfile].freeze
+ GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}.freeze
+
attr_reader :gemspecs
attr_accessor :dependencies
@@ -63,7 +65,7 @@ module Bundler
development_group = opts[:development_group] || :development
expanded_path = gemfile_root.join(path)
- gemspecs = Dir[File.join(expanded_path, "{,*}.gemspec")].map {|g| Bundler.load_gemspec(g) }.compact
+ gemspecs = Gem::Util.glob_files_in_dir("{,*}.gemspec", expanded_path).map {|g| Bundler.load_gemspec(g) }.compact
gemspecs.reject! {|s| s.name != name } if name
Index.sort_specs(gemspecs)
specs_by_name_and_version = gemspecs.group_by {|s| [s.name, s.version] }
@@ -75,8 +77,7 @@ module Bundler
@gemspecs << spec
- gem_platforms = Bundler::Dependency::REVERSE_PLATFORM_MAP[Bundler::GemHelpers.generic_local_platform]
- gem spec.name, :name => spec.name, :path => path, :glob => glob, :platforms => gem_platforms
+ gem spec.name, :name => spec.name, :path => path, :glob => glob
group(development_group) do
spec.development_dependencies.each do |dep|
@@ -104,8 +105,8 @@ module Bundler
if current = @dependencies.find {|d| d.name == dep.name }
deleted_dep = @dependencies.delete(current) if current.type == :development
- if current.requirement != dep.requirement
- unless deleted_dep
+ unless deleted_dep
+ if current.requirement != dep.requirement
return if dep.type == :development
update_prompt = ""
@@ -123,17 +124,14 @@ module Bundler
raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \
"You specified: #{current.name} (#{current.requirement}) and #{dep.name} (#{dep.requirement})" \
"#{update_prompt}"
+ else
+ Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \
+ "You should probably keep only one of them.\n" \
+ "Remove any duplicate entries and specify the gem only once.\n" \
+ "While it's not a problem now, it could cause errors if you change the version of one of them later."
end
- else
- Bundler.ui.warn "Your Gemfile lists the gem #{current.name} (#{current.requirement}) more than once.\n" \
- "You should probably keep only one of them.\n" \
- "Remove any duplicate entries and specify the gem only once.\n" \
- "While it's not a problem now, it could cause errors if you change the version of one of them later."
- end
-
- if current.source != dep.source
- unless deleted_dep
+ if current.source != dep.source
return if dep.type == :development
raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
"You specified that #{dep.name} (#{dep.requirement}) should come from " \
@@ -165,8 +163,7 @@ module Bundler
elsif block_given?
with_source(@sources.add_rubygems_source("remotes" => source), &blk)
else
- check_primary_source_safety(@sources)
- @sources.global_rubygems_source = source
+ @sources.add_global_rubygems_remote(source)
end
end
@@ -184,24 +181,14 @@ module Bundler
end
def path(path, options = {}, &blk)
- unless block_given?
- msg = "You can no longer specify a path source by itself. Instead, \n" \
- "either use the :path option on a gem, or specify the gems that \n" \
- "bundler should find in the path source by passing a block to \n" \
- "the path method, like: \n\n" \
- " path 'dir/containing/rails' do\n" \
- " gem 'rails'\n" \
- " end\n\n"
-
- raise DeprecatedError, msg if Bundler.feature_flag.disable_multisource?
- SharedHelpers.major_deprecation(2, msg.strip)
- end
-
source_options = normalize_hash(options).merge(
"path" => Pathname.new(path),
"root_path" => gemfile_root,
"gemspec" => gemspecs.find {|g| g.name == options["name"] }
)
+
+ source_options["global"] = true unless block_given?
+
source = @sources.add_path_source(source_options)
with_source(source, &blk)
end
@@ -223,7 +210,6 @@ module Bundler
def github(repo, options = {})
raise ArgumentError, "GitHub sources require a block" unless block_given?
- raise DeprecatedError, "The #github method has been removed" if Bundler.feature_flag.skip_default_git_sources?
github_uri = @git_sources["github"].call(repo)
git_options = normalize_hash(options).merge("uri" => github_uri)
git_source = @sources.add_git_source(git_options)
@@ -231,6 +217,7 @@ module Bundler
end
def to_definition(lockfile, unlock)
+ check_primary_source_safety
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles)
end
@@ -281,17 +268,29 @@ module Bundler
raise GemfileError, "Undefined local variable or method `#{name}' for Gemfile"
end
- private
+ def check_primary_source_safety
+ check_path_source_safety
+ check_rubygems_source_safety
+ end
- def add_git_sources
- return if Bundler.feature_flag.skip_default_git_sources?
+ private
+ def add_git_sources
git_source(:github) do |repo_name|
warn_deprecated_git_source(:github, <<-'RUBY'.strip, 'Change any "reponame" :github sources to "username/reponame".')
"https://github.com/#{repo_name}.git"
RUBY
- repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
- "https://github.com/#{repo_name}.git"
+ if repo_name =~ GITHUB_PULL_REQUEST_URL
+ {
+ "git" => "https://github.com/#{$1}.git",
+ "branch" => "refs/pull/#{$2}/head",
+ "ref" => nil,
+ "tag" => nil,
+ }
+ else
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
+ "https://github.com/#{repo_name}.git"
+ end
end
git_source(:gist) do |repo_name|
@@ -377,7 +376,11 @@ repo_name ||= user_name
git_name = (git_names & opts.keys).last
if @git_sources[git_name]
- opts["git"] = @git_sources[git_name].call(opts[git_name])
+ git_opts = @git_sources[git_name].call(opts[git_name])
+ git_opts = { "git" => git_opts } if git_opts.is_a?(String)
+ opts.merge!(git_opts) do |key, _gemfile_value, _git_source_value|
+ raise GemfileError, %(The :#{key} option can't be used with `#{git_name}: #{opts[git_name].inspect}`)
+ end
end
%w[git path].each do |type|
@@ -444,25 +447,46 @@ repo_name ||= user_name
end
end
- def check_primary_source_safety(source_list)
- return if source_list.rubygems_primary_remotes.empty? && source_list.global_rubygems_source.nil?
+ def check_path_source_safety
+ return if @sources.global_path_source.nil?
+
+ msg = "You can no longer specify a path source by itself. Instead, \n" \
+ "either use the :path option on a gem, or specify the gems that \n" \
+ "bundler should find in the path source by passing a block to \n" \
+ "the path method, like: \n\n" \
+ " path 'dir/containing/rails' do\n" \
+ " gem 'rails'\n" \
+ " end\n\n"
- if Bundler.feature_flag.disable_multisource?
+ SharedHelpers.major_deprecation(2, msg.strip)
+ end
+
+ def check_rubygems_source_safety
+ if @sources.implicit_global_source?
+ implicit_global_source_warning
+ elsif @sources.aggregate_global_source?
+ multiple_global_source_warning
+ end
+ end
+
+ def implicit_global_source_warning
+ Bundler::SharedHelpers.major_deprecation 2, "This Gemfile does not include an explicit global source. " \
+ "Not using an explicit global source may result in a different lockfile being generated depending on " \
+ "the gems you have installed locally before bundler is run. " \
+ "Instead, define a global source in your Gemfile like this: source \"https://rubygems.org\"."
+ end
+
+ def multiple_global_source_warning
+ if Bundler.feature_flag.bundler_3_mode?
msg = "This Gemfile contains multiple primary sources. " \
"Each source after the first must include a block to indicate which gems " \
"should come from that source"
- unless Bundler.feature_flag.bundler_2_mode?
- msg += ". To downgrade this error to a warning, run " \
- "`bundle config unset disable_multisource`"
- end
raise GemfileEvalError, msg
else
Bundler::SharedHelpers.major_deprecation 2, "Your Gemfile contains multiple primary sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
- "a block to indicate which gems should come from the secondary source. " \
- "To upgrade this warning to an error, run `bundle config set " \
- "disable_multisource true`."
+ "a block to indicate which gems should come from the secondary source."
end
end
@@ -571,7 +595,7 @@ The :#{name} git source is deprecated, and will be removed in the future.#{addit
end
end
- private
+ private
def parse_line_number_from_description
description = self.description
diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb
index 9a00b64e0e..476151ae56 100644
--- a/lib/bundler/endpoint_specification.rb
+++ b/lib/bundler/endpoint_specification.rb
@@ -104,7 +104,7 @@ module Bundler
@remote_specification = spec
end
- private
+ private
def local_specification_path
"#{base_dir}/specifications/#{full_name}.gemspec"
diff --git a/lib/bundler/env.rb b/lib/bundler/env.rb
index 17624b4fe9..00d4ef2196 100644
--- a/lib/bundler/env.rb
+++ b/lib/bundler/env.rb
@@ -105,7 +105,7 @@ module Bundler
out << [" User Home", Gem.user_home]
out << [" User Path", Gem.user_dir]
out << [" Bin Dir", Gem.bindir]
- if defined?(OpenSSL)
+ if defined?(OpenSSL::SSL)
out << ["OpenSSL"]
out << [" Compiled", OpenSSL::OPENSSL_VERSION] if defined?(OpenSSL::OPENSSL_VERSION)
out << [" Loaded", OpenSSL::OPENSSL_LIBRARY_VERSION] if defined?(OpenSSL::OPENSSL_LIBRARY_VERSION)
diff --git a/lib/bundler/environment_preserver.rb b/lib/bundler/environment_preserver.rb
index c9014badad..0f08e049d8 100644
--- a/lib/bundler/environment_preserver.rb
+++ b/lib/bundler/environment_preserver.rb
@@ -17,14 +17,41 @@ module Bundler
].map(&:freeze).freeze
BUNDLER_PREFIX = "BUNDLER_ORIG_".freeze
- # @param env [ENV]
+ def self.from_env
+ new(env_to_hash(ENV), BUNDLER_KEYS)
+ end
+
+ def self.env_to_hash(env)
+ to_hash = env.to_hash
+ return to_hash unless Gem.win_platform?
+
+ to_hash.each_with_object({}) {|(k,v), a| a[k.upcase] = v }
+ end
+
+ # @param env [Hash]
# @param keys [Array<String>]
def initialize(env, keys)
- @original = env.to_hash
+ @original = env
@keys = keys
@prefix = BUNDLER_PREFIX
end
+ # Replaces `ENV` with the bundler environment variables backed up
+ def replace_with_backup
+ unless Gem.win_platform?
+ ENV.replace(backup)
+ return
+ end
+
+ # Fallback logic for Windows below to workaround
+ # https://bugs.ruby-lang.org/issues/16798. Can be dropped once all
+ # supported rubies include the fix for that.
+
+ ENV.clear
+
+ backup.each {|k, v| ENV[k] = v }
+ end
+
# @return [Hash]
def backup
env = @original.clone
diff --git a/lib/bundler/errors.rb b/lib/bundler/errors.rb
index e471bce0b6..9ad7460e58 100644
--- a/lib/bundler/errors.rb
+++ b/lib/bundler/errors.rb
@@ -56,6 +56,7 @@ module Bundler
class SudoNotPermittedError < BundlerError; status_code(30); end
class ThreadCreationError < BundlerError; status_code(33); end
class APIResponseMismatchError < BundlerError; status_code(34); end
+ class APIResponseInvalidDependenciesError < BundlerError; status_code(35); end
class GemfileEvalError < GemfileError; end
class MarshalError < StandardError; end
@@ -74,10 +75,26 @@ module Bundler
end
end
+ def permission_type
+ case @permission_type
+ when :create
+ "executable permissions for all parent directories and write permissions for `#{parent_folder}`"
+ when :delete
+ permissions = "executable permissions for all parent directories and write permissions for `#{parent_folder}`"
+ permissions += ", and the same thing for all subdirectories inside #{@path}" if File.directory?(@path)
+ permissions
+ else
+ "#{@permission_type} permissions for that path"
+ end
+ end
+
+ def parent_folder
+ File.dirname(@path)
+ end
+
def message
"There was an error while trying to #{action} `#{@path}`. " \
- "It is likely that you need to grant #{@permission_type} permissions " \
- "for that path."
+ "It is likely that you need to grant #{permission_type}."
end
status_code(23)
@@ -121,7 +138,7 @@ module Bundler
class VirtualProtocolError < BundlerError
def message
- "There was an error relating to virtualization and file access." \
+ "There was an error relating to virtualization and file access. " \
"It is likely that you need to grant access to or mount some file system correctly."
end
diff --git a/lib/bundler/feature_flag.rb b/lib/bundler/feature_flag.rb
index 01739ec4aa..e441b941c2 100644
--- a/lib/bundler/feature_flag.rb
+++ b/lib/bundler/feature_flag.rb
@@ -27,25 +27,17 @@ module Bundler
(1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } }
- settings_flag(:allow_bundler_dependency_conflicts) { bundler_3_mode? }
settings_flag(:allow_offline_install) { bundler_3_mode? }
settings_flag(:auto_clean_without_path) { bundler_3_mode? }
- settings_flag(:auto_config_jobs) { bundler_3_mode? }
settings_flag(:cache_all) { bundler_3_mode? }
settings_flag(:default_install_uses_path) { bundler_3_mode? }
- settings_flag(:deployment_means_frozen) { bundler_3_mode? }
- settings_flag(:disable_multisource) { bundler_3_mode? }
settings_flag(:forget_cli_options) { bundler_3_mode? }
settings_flag(:global_gem_cache) { bundler_3_mode? }
- settings_flag(:only_update_to_newer_versions) { bundler_3_mode? }
settings_flag(:path_relative_to_cwd) { bundler_3_mode? }
settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") }
settings_flag(:print_only_version_number) { bundler_3_mode? }
settings_flag(:setup_makes_kernel_gem_public) { !bundler_3_mode? }
- settings_flag(:skip_default_git_sources) { bundler_3_mode? }
- settings_flag(:specific_platform) { bundler_3_mode? }
settings_flag(:suppress_install_using_messages) { bundler_3_mode? }
- settings_flag(:unlock_source_unlocks_spec) { !bundler_3_mode? }
settings_flag(:update_requires_all_flag) { bundler_4_mode? }
settings_flag(:use_gem_version_promoter_for_major_updates) { bundler_3_mode? }
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index caf33bcfc9..e3253a942f 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -28,7 +28,8 @@ module Bundler
" is a chance you are experiencing a man-in-the-middle attack, but" \
" most likely your system doesn't have the CA certificates needed" \
" for verification. For information about OpenSSL certificates, see" \
- " http://bit.ly/ruby-ssl. To connect without using SSL, edit your Gemfile" \
+ " https://railsapps.github.io/openssl-certificate-verify-failed.html." \
+ " To connect without using SSL, edit your Gemfile" \
" sources and change 'https' to 'http'."
end
end
@@ -47,7 +48,8 @@ module Bundler
remote_uri = filter_uri(remote_uri)
super "Authentication is required for #{remote_uri}.\n" \
"Please supply credentials for this source. You can do this by running:\n" \
- " bundle config set #{remote_uri} username:password"
+ "`bundle config set --global #{remote_uri} username:password`\n" \
+ "or by storing the credentials in the `#{Settings.key_for(remote_uri)}` environment variable"
end
end
# This error is raised if HTTP authentication is provided, but incorrect.
@@ -137,7 +139,6 @@ module Bundler
end
specs.each do |name, version, platform, dependencies, metadata|
- next if name == "bundler"
spec = if dependencies
EndpointSpecification.new(name, version, platform, dependencies, metadata)
else
@@ -216,7 +217,7 @@ module Bundler
"#<#{self.class}:0x#{object_id} uri=#{uri}>"
end
- private
+ private
FETCHERS = [CompactIndex, Dependency, Index].freeze
@@ -229,6 +230,7 @@ module Bundler
"BUILDBOX" => "buildbox",
"GO_SERVER_URL" => "go",
"SNAP_CI" => "snap",
+ "GITLAB_CI" => "gitlab",
"CI_NAME" => ENV["CI_NAME"],
"CI" => "ci",
}
@@ -302,7 +304,7 @@ module Bundler
store
end
- private
+ private
def remote_uri
@remote.uri
diff --git a/lib/bundler/fetcher/base.rb b/lib/bundler/fetcher/base.rb
index 27987f670a..16cc98273a 100644
--- a/lib/bundler/fetcher/base.rb
+++ b/lib/bundler/fetcher/base.rb
@@ -38,7 +38,7 @@ module Bundler
false
end
- private
+ private
def log_specs(debug_msg)
if Bundler.ui.debug?
diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb
index f36d76d4ae..bc69b884ec 100644
--- a/lib/bundler/fetcher/compact_index.rb
+++ b/lib/bundler/fetcher/compact_index.rb
@@ -83,7 +83,7 @@ module Bundler
true
end
- private
+ private
def compact_index_client
@compact_index_client ||=
@@ -111,7 +111,7 @@ module Bundler
def bundle_worker(func = nil)
@bundle_worker ||= begin
worker_name = "Compact Index (#{display_uri.host})"
- Bundler::Worker.new(Bundler.current_ruby.rbx? ? 1 : 25, worker_name, func)
+ Bundler::Worker.new(Bundler.settings.processor_count, worker_name, func)
end
@bundle_worker.tap do |worker|
worker.instance_variable_set(:@func, func) if func
diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb
index 498852c174..f2aad3a500 100644
--- a/lib/bundler/fetcher/downloader.rb
+++ b/lib/bundler/fetcher/downloader.rb
@@ -14,8 +14,10 @@ module Bundler
def fetch(uri, headers = {}, counter = 0)
raise HTTPError, "Too many redirects" if counter >= redirect_limit
+ filtered_uri = URICredentialsFilter.credential_filtered_uri(uri)
+
response = request(uri, headers)
- Bundler.ui.debug("HTTP #{response.code} #{response.message} #{uri}")
+ Bundler.ui.debug("HTTP #{response.code} #{response.message} #{filtered_uri}")
case response
when Net::HTTPSuccess, Net::HTTPNotModified
@@ -40,7 +42,7 @@ module Bundler
raise BadAuthenticationError, uri.host if uri.userinfo
raise AuthenticationRequiredError, uri.host
when Net::HTTPNotFound
- raise FallbackError, "Net::HTTPNotFound: #{URICredentialsFilter.credential_filtered_uri(uri)}"
+ raise FallbackError, "Net::HTTPNotFound: #{filtered_uri}"
else
raise HTTPError, "#{response.class}#{": #{response.body}" unless response.body.empty?}"
end
@@ -49,7 +51,9 @@ module Bundler
def request(uri, headers)
validate_uri_scheme!(uri)
- Bundler.ui.debug "HTTP GET #{uri}"
+ filtered_uri = URICredentialsFilter.credential_filtered_uri(uri)
+
+ Bundler.ui.debug "HTTP GET #{filtered_uri}"
req = Net::HTTP::Get.new uri.request_uri, headers
if uri.user
user = CGI.unescape(uri.user)
@@ -64,17 +68,16 @@ module Bundler
raise CertificateFailureError.new(uri)
rescue *HTTP_ERRORS => e
Bundler.ui.trace e
- case e.message
- when /host down:/, /getaddrinfo: nodename nor servname provided/
+ if e.is_a?(SocketError) || e.message =~ /host down:/
raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \
"connection and try again."
else
- raise HTTPError, "Network error while fetching #{URICredentialsFilter.credential_filtered_uri(uri)}" \
+ raise HTTPError, "Network error while fetching #{filtered_uri}" \
" (#{e})"
end
end
- private
+ private
def validate_uri_scheme!(uri)
return if uri.scheme =~ /\Ahttps?\z/
diff --git a/lib/bundler/fetcher/index.rb b/lib/bundler/fetcher/index.rb
index 034a225198..0d14c47aa7 100644
--- a/lib/bundler/fetcher/index.rb
+++ b/lib/bundler/fetcher/index.rb
@@ -1,14 +1,13 @@
# frozen_string_literal: true
require_relative "base"
-require "rubygems/remote_fetcher"
module Bundler
class Fetcher
class Index < Base
def specs(_gem_names)
Bundler.rubygems.fetch_all_remote_specs(remote)
- rescue Gem::RemoteFetcher::FetchError, OpenSSL::SSL::SSLError, Net::HTTPFatalError => e
+ rescue Gem::RemoteFetcher::FetchError => e
case e.message
when /certificate verify failed/
raise CertificateFailureError.new(display_uri)
@@ -19,8 +18,7 @@ module Bundler
raise BadAuthenticationError, remote_uri if remote_uri.userinfo
raise AuthenticationRequiredError, remote_uri
else
- Bundler.ui.trace e
- raise HTTPError, "Could not fetch specs from #{display_uri}"
+ raise HTTPError, "Could not fetch specs from #{display_uri} due to underlying error <#{e.message}>"
end
end
@@ -42,7 +40,7 @@ module Bundler
"Your network or your gem server is probably having issues right now."
end
- private
+ private
# cached gem specification path, if one exists
def gemspec_cached_path(spec_file_name)
diff --git a/lib/bundler/friendly_errors.rb b/lib/bundler/friendly_errors.rb
index 080697b02c..cc615db60c 100644
--- a/lib/bundler/friendly_errors.rb
+++ b/lib/bundler/friendly_errors.rb
@@ -4,7 +4,19 @@ require_relative "vendored_thor"
module Bundler
module FriendlyErrors
- module_function
+ module_function
+
+ def enable!
+ @disabled = false
+ end
+
+ def disabled?
+ @disabled
+ end
+
+ def disable!
+ @disabled = true
+ end
def log_error(error)
case error
@@ -23,13 +35,7 @@ module Bundler
Bundler.ui.error error.message
when LoadError
raise error unless error.message =~ /cannot load such file -- openssl|openssl.so|libcrypto.so/
- Bundler.ui.error "\nCould not load OpenSSL."
- Bundler.ui.warn <<-WARN, :wrap => true
- You must recompile Ruby with OpenSSL support or change the sources in your \
- Gemfile from 'https' to 'http'. Instructions for compiling with OpenSSL \
- using RVM are available at https://rvm.io/packages/openssl.
- WARN
- Bundler.ui.trace error
+ Bundler.ui.error "\nCould not load OpenSSL. #{error.class}: #{error}\n#{error.backtrace.join("\n ")}"
when Interrupt
Bundler.ui.error "\nQuitting..."
Bundler.ui.trace error
@@ -43,8 +49,6 @@ module Bundler
"Alternatively, you can increase the amount of memory the JVM is able to use by running Bundler with jruby -J-Xmx1024m -S bundle (JRuby defaults to 500MB)."
else request_issue_report_for(error)
end
- rescue StandardError
- raise error
end
def exit_status(error)
@@ -57,36 +61,8 @@ module Bundler
end
def request_issue_report_for(e)
- Bundler.ui.info <<-EOS.gsub(/^ {8}/, "")
+ Bundler.ui.error <<-EOS.gsub(/^ {8}/, ""), nil, nil
--- ERROR REPORT TEMPLATE -------------------------------------------------------
- # Error Report
-
- ## Questions
-
- Please fill out answers to these questions, it'll help us figure out
- why things are going wrong.
-
- - **What did you do?**
-
- I ran the command `#{$PROGRAM_NAME} #{ARGV.join(" ")}`
-
- - **What did you expect to happen?**
-
- I expected Bundler to...
-
- - **What happened instead?**
-
- Instead, what happened was...
-
- - **Have you tried any solutions posted on similar issues in our issue tracker, stack overflow, or google?**
-
- I tried...
-
- - **Have you read our issues document, https://github.com/bundler/bundler/blob/master/doc/contributing/ISSUES.md?**
-
- ...
-
- ## Backtrace
```
#{e.class}: #{e.message}
@@ -100,13 +76,12 @@ module Bundler
Bundler.ui.error "Unfortunately, an unexpected error occurred, and Bundler cannot continue."
- Bundler.ui.warn <<-EOS.gsub(/^ {8}/, "")
+ Bundler.ui.error <<-EOS.gsub(/^ {8}/, ""), nil, :yellow
First, try this link to see if there are any existing issue reports for this error:
#{issues_url(e)}
- If there aren't any reports for this error yet, please create copy and paste the report template above into a new issue. Don't forget to anonymize any private data! The new issue form is located at:
- https://github.com/bundler/bundler/issues/new
+ If there aren't any reports for this error yet, please fill in the new issue form located at #{new_issue_url}, and copy and paste the report template above in there.
EOS
end
@@ -114,16 +89,23 @@ module Bundler
message = exception.message.lines.first.tr(":", " ").chomp
message = message.split("-").first if exception.is_a?(Errno)
require "cgi"
- "https://github.com/bundler/bundler/search?q=" \
+ "https://github.com/rubygems/rubygems/search?q=" \
"#{CGI.escape(message)}&type=Issues"
end
+
+ def new_issue_url
+ "https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md"
+ end
end
def self.with_friendly_errors
+ FriendlyErrors.enable!
yield
rescue SignalException
raise
rescue Exception => e # rubocop:disable Lint/RescueException
+ raise if FriendlyErrors.disabled?
+
FriendlyErrors.log_error(e)
exit FriendlyErrors.exit_status(e)
end
diff --git a/lib/bundler/gem_helper.rb b/lib/bundler/gem_helper.rb
index 204dd24052..034f2e5960 100644
--- a/lib/bundler/gem_helper.rb
+++ b/lib/bundler/gem_helper.rb
@@ -15,6 +15,10 @@ module Bundler
new(opts[:dir], opts[:name]).install
end
+ def tag_prefix=(prefix)
+ instance.tag_prefix = prefix
+ end
+
def gemspec(&block)
gemspec = instance.gemspec
block.call(gemspec) if block
@@ -24,12 +28,15 @@ module Bundler
attr_reader :spec_path, :base, :gemspec
+ attr_writer :tag_prefix
+
def initialize(base = nil, name = nil)
- @base = (base ||= SharedHelpers.pwd)
- gemspecs = name ? [File.join(base, "#{name}.gemspec")] : Dir[File.join(base, "{,*}.gemspec")]
+ @base = File.expand_path(base || SharedHelpers.pwd)
+ gemspecs = name ? [File.join(@base, "#{name}.gemspec")] : Gem::Util.glob_files_in_dir("{,*}.gemspec", @base)
raise "Unable to determine name from existing gemspec. Use :name => 'gemname' in #install_tasks to manually set it." unless gemspecs.size == 1
@spec_path = gemspecs.first
@gemspec = Bundler.load_gemspec(@spec_path)
+ @tag_prefix = ""
end
def install
@@ -40,6 +47,11 @@ module Bundler
built_gem_path = build_gem
end
+ desc "Generate SHA512 checksum if #{name}-#{version}.gem into the checksums directory."
+ task "build:checksum" => "build" do
+ build_checksum(built_gem_path)
+ end
+
desc "Build and install #{name}-#{version}.gem into system gems."
task "install" => "build" do
install_gem(built_gem_path)
@@ -64,7 +76,7 @@ module Bundler
tag_version { git_push(args[:remote]) } unless already_tagged?
end
- task "release:rubygem_push" do
+ task "release:rubygem_push" => "build" do
rubygem_push(built_gem_path) if gem_push?
end
@@ -73,7 +85,7 @@ module Bundler
def build_gem
file_name = nil
- sh("#{gem_command} build -V #{spec_path.shellescape}".shellsplit) do
+ sh([*gem_command, "build", "-V", spec_path]) do
file_name = File.basename(built_gem_path)
SharedHelpers.filesystem_access(File.join(base, "pkg")) {|p| FileUtils.mkdir_p(p) }
FileUtils.mv(built_gem_path, "pkg")
@@ -84,36 +96,54 @@ module Bundler
def install_gem(built_gem_path = nil, local = false)
built_gem_path ||= build_gem
- cmd = "#{gem_command} install #{built_gem_path}"
- cmd += " --local" if local
- _, status = sh_with_status(cmd.shellsplit)
- unless status.success?
- raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output"
- end
+ cmd = [*gem_command, "install", built_gem_path.to_s]
+ cmd << "--local" if local
+ sh(cmd)
Bundler.ui.confirm "#{name} (#{version}) installed."
end
- protected
+ def build_checksum(built_gem_path = nil)
+ built_gem_path ||= build_gem
+ SharedHelpers.filesystem_access(File.join(base, "checksums")) {|p| FileUtils.mkdir_p(p) }
+ file_name = "#{File.basename(built_gem_path)}.sha512"
+ require "digest/sha2"
+ checksum = ::Digest::SHA512.new.hexdigest(built_gem_path.to_s)
+ target = File.join(base, "checksums", file_name)
+ File.write(target, checksum)
+ Bundler.ui.confirm "#{name} #{version} checksum written to checksums/#{file_name}."
+ end
+
+ protected
def rubygem_push(path)
- cmd = %W[#{gem_command} push #{path}]
+ cmd = [*gem_command, "push", path]
cmd << "--key" << gem_key if gem_key
cmd << "--host" << allowed_push_host if allowed_push_host
- unless allowed_push_host || Bundler.user_home.join(".gem/credentials").file?
- raise "Your rubygems.org credentials aren't set. Run `gem push` to set them."
- end
sh_with_input(cmd)
Bundler.ui.confirm "Pushed #{name} #{version} to #{gem_push_host}"
end
def built_gem_path
- Dir[File.join(base, "#{name}-*.gem")].sort_by {|f| File.mtime(f) }.last
+ Gem::Util.glob_files_in_dir("#{name}-*.gem", base).sort_by {|f| File.mtime(f) }.last
end
- def git_push(remote = "")
- perform_git_push remote
- perform_git_push "#{remote} --tags"
- Bundler.ui.confirm "Pushed git commits and tags."
+ def git_push(remote = nil)
+ remote ||= default_remote
+ sh("git push #{remote} refs/heads/#{current_branch}".shellsplit)
+ sh("git push #{remote} refs/tags/#{version_tag}".shellsplit)
+ Bundler.ui.confirm "Pushed git commits and release tag."
+ end
+
+ def default_remote
+ remote_for_branch, status = sh_with_status(%W[git config --get branch.#{current_branch}.remote])
+ return "origin" unless status.success?
+
+ remote_for_branch.strip
+ end
+
+ def current_branch
+ # We can replace this with `git branch --show-current` once we drop support for git < 2.22.0
+ sh(%w[git rev-parse --abbrev-ref HEAD]).gsub(%r{\Aheads/}, "").strip
end
def allowed_push_host
@@ -128,13 +158,6 @@ module Bundler
allowed_push_host || env_rubygems_host || "rubygems.org"
end
- def perform_git_push(options = "")
- cmd = "git push #{options}"
- out, status = sh_with_status(cmd.shellsplit)
- return if status.success?
- raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n"
- end
-
def already_tagged?
return false unless sh(%w[git tag]).split(/\n/).include?(version_tag)
Bundler.ui.confirm "Tag #{version_tag} has already been created."
@@ -168,7 +191,7 @@ module Bundler
end
def version_tag
- "v#{version}"
+ "#{@tag_prefix}v#{version}"
end
def name
@@ -185,8 +208,7 @@ module Bundler
def sh(cmd, &block)
out, status = sh_with_status(cmd, &block)
unless status.success?
- cmd = cmd.shelljoin if cmd.respond_to?(:shelljoin)
- raise(out.empty? ? "Running `#{cmd}` failed. Run this command directly for more detailed output." : out)
+ raise("Running `#{cmd.shelljoin}` failed with the following output:\n\n#{out}\n")
end
out
end
@@ -210,7 +232,7 @@ module Bundler
end
def gem_command
- ENV["GEM_COMMAND"] ? ENV["GEM_COMMAND"] : "gem"
+ ENV["GEM_COMMAND"]&.shellsplit || ["gem"]
end
end
end
diff --git a/lib/bundler/gem_helpers.rb b/lib/bundler/gem_helpers.rb
index be047f4397..b271b8d229 100644
--- a/lib/bundler/gem_helpers.rb
+++ b/lib/bundler/gem_helpers.rb
@@ -24,47 +24,44 @@ module Bundler
module_function :generic
def generic_local_platform
- generic(Bundler.local_platform)
+ generic(local_platform)
end
module_function :generic_local_platform
+ def local_platform
+ Bundler.local_platform
+ end
+ module_function :local_platform
+
def platform_specificity_match(spec_platform, user_platform)
spec_platform = Gem::Platform.new(spec_platform)
- return PlatformMatch::EXACT_MATCH if spec_platform == user_platform
- return PlatformMatch::WORST_MATCH if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY
-
- PlatformMatch.new(
- PlatformMatch.os_match(spec_platform, user_platform),
- PlatformMatch.cpu_match(spec_platform, user_platform),
- PlatformMatch.platform_version_match(spec_platform, user_platform)
- )
+
+ PlatformMatch.specificity_score(spec_platform, user_platform)
end
module_function :platform_specificity_match
def select_best_platform_match(specs, platform)
- specs.select {|spec| spec.match_platform(platform) }.
- min_by {|spec| platform_specificity_match(spec.platform, platform) }
+ matching = specs.select {|spec| spec.match_platform(platform) }
+ exact = matching.select {|spec| spec.platform == platform }
+ return exact if exact.any?
+
+ sorted_matching = matching.sort_by {|spec| platform_specificity_match(spec.platform, platform) }
+ exemplary_spec = sorted_matching.first
+
+ sorted_matching.take_while{|spec| same_specificity(platform, spec, exemplary_spec) && same_deps(spec, exemplary_spec) }
end
module_function :select_best_platform_match
- PlatformMatch = Struct.new(:os_match, :cpu_match, :platform_version_match)
class PlatformMatch
- def <=>(other)
- return nil unless other.is_a?(PlatformMatch)
-
- m = os_match <=> other.os_match
- return m unless m.zero?
-
- m = cpu_match <=> other.cpu_match
- return m unless m.zero?
+ def self.specificity_score(spec_platform, user_platform)
+ return -1 if spec_platform == user_platform
+ return 1_000_000 if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY
- m = platform_version_match <=> other.platform_version_match
- m
+ os_match(spec_platform, user_platform) +
+ cpu_match(spec_platform, user_platform) * 10 +
+ platform_version_match(spec_platform, user_platform) * 100
end
- EXACT_MATCH = new(-1, -1, -1).freeze
- WORST_MATCH = new(1_000_000, 1_000_000, 1_000_000).freeze
-
def self.os_match(spec_platform, user_platform)
if spec_platform.os == user_platform.os
0
@@ -95,5 +92,19 @@ module Bundler
end
end
end
+
+ def same_specificity(platform, spec, exemplary_spec)
+ platform_specificity_match(spec.platform, platform) == platform_specificity_match(exemplary_spec.platform, platform)
+ end
+ module_function :same_specificity
+
+ def same_deps(spec, exemplary_spec)
+ same_runtime_deps = spec.dependencies.sort == exemplary_spec.dependencies.sort
+ return same_runtime_deps unless spec.is_a?(Gem::Specification) && exemplary_spec.is_a?(Gem::Specification)
+
+ same_metadata_deps = spec.required_ruby_version == exemplary_spec.required_ruby_version && spec.required_rubygems_version == exemplary_spec.required_rubygems_version
+ same_runtime_deps && same_metadata_deps
+ end
+ module_function :same_deps
end
end
diff --git a/lib/bundler/gem_remote_fetcher.rb b/lib/bundler/gem_remote_fetcher.rb
deleted file mode 100644
index 9577535d63..0000000000
--- a/lib/bundler/gem_remote_fetcher.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require "rubygems/remote_fetcher"
-
-module Bundler
- # Adds support for setting custom HTTP headers when fetching gems from the
- # server.
- #
- # TODO: Get rid of this when and if gemstash only supports RubyGems versions
- # that contain https://github.com/rubygems/rubygems/commit/3db265cc20b2f813.
- class GemRemoteFetcher < Gem::RemoteFetcher
- attr_accessor :headers
-
- # Extracted from RubyGems 2.4.
- def fetch_http(uri, last_modified = nil, head = false, depth = 0)
- fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get
- # beginning of change
- response = request uri, fetch_type, last_modified do |req|
- headers.each {|k, v| req.add_field(k, v) } if headers
- end
- # end of change
-
- case response
- when Net::HTTPOK, Net::HTTPNotModified then
- response.uri = uri if response.respond_to? :uri
- head ? response : response.body
- when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther,
- Net::HTTPTemporaryRedirect then
- raise FetchError.new("too many redirects", uri) if depth > 10
-
- location = URI.parse response["Location"]
-
- if https?(uri) && !https?(location)
- raise FetchError.new("redirecting to non-https resource: #{location}", uri)
- end
-
- fetch_http(location, last_modified, head, depth + 1)
- else
- raise FetchError.new("bad response #{response.message} #{response.code}", uri)
- end
- end
- end
-end
diff --git a/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb
index 311b0cbbf3..3cce3f2139 100644
--- a/lib/bundler/gem_version_promoter.rb
+++ b/lib/bundler/gem_version_promoter.rb
@@ -7,7 +7,7 @@ module Bundler
# available dependency versions as found in its index, before returning it to
# to the resolution engine to select the best version.
class GemVersionPromoter
- DEBUG = ENV["DEBUG_RESOLVER"]
+ DEBUG = ENV["BUNDLER_DEBUG_RESOLVER"] || ENV["DEBUG_RESOLVER"]
attr_reader :level, :locked_specs, :unlock_gems
@@ -81,8 +81,8 @@ module Bundler
sort_dep_specs(spec_groups, locked_spec)
end.tap do |specs|
if DEBUG
- warn before_result
- warn " after sort_versions: #{debug_format_result(dep, specs).inspect}"
+ puts before_result
+ puts " after sort_versions: #{debug_format_result(dep, specs).inspect}"
end
end
end
@@ -98,7 +98,7 @@ module Bundler
level == :minor
end
- private
+ private
def filter_dep_specs(spec_groups, locked_spec)
res = spec_groups.select do |spec_group|
diff --git a/lib/bundler/graph.rb b/lib/bundler/graph.rb
index 5644e41079..8f52e2f0f0 100644
--- a/lib/bundler/graph.rb
+++ b/lib/bundler/graph.rb
@@ -27,7 +27,7 @@ module Bundler
GraphVizClient.new(self).run
end
- private
+ private
def _populate_relations
parent_dependencies = _groups.values.to_set.flatten
diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb
index 9166a92738..8930fca6d0 100644
--- a/lib/bundler/index.rb
+++ b/lib/bundler/index.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "set"
-
module Bundler
class Index
include Enumerable
@@ -65,11 +63,14 @@ module Bundler
def unsorted_search(query, base)
results = local_search(query, base)
- seen = results.map(&:full_name).to_set unless @sources.empty?
+ seen = results.map(&:full_name).uniq unless @sources.empty?
@sources.each do |source|
source.unsorted_search(query, base).each do |spec|
- results << spec if seen.add?(spec.full_name)
+ next if seen.include?(spec.full_name)
+
+ seen << spec.full_name
+ results << spec
end
end
@@ -121,10 +122,9 @@ module Bundler
names
end
- # returns a list of the dependencies
def unmet_dependency_names
dependency_names.select do |name|
- name != "bundler" && search(name).empty?
+ search(name).empty?
end
end
@@ -170,7 +170,7 @@ module Bundler
def dependencies_eql?(spec, other_spec)
deps = spec.dependencies.select {|d| d.type != :development }
other_deps = other_spec.dependencies.select {|d| d.type != :development }
- Set.new(deps) == Set.new(other_deps)
+ deps.sort == other_deps.sort
end
def add_source(index)
@@ -179,7 +179,7 @@ module Bundler
@sources.uniq! # need to use uniq! here instead of checking for the item before adding
end
- private
+ private
def specs_by_name(name)
@specs[name].values
@@ -195,7 +195,7 @@ module Bundler
if base # allow all platforms when searching from a lockfile
dependency.matches_spec?(spec)
else
- dependency.matches_spec?(spec) && Gem::Platform.match(spec.platform)
+ dependency.matches_spec?(spec) && Gem::Platform.match_spec?(spec)
end
end
diff --git a/lib/bundler/injector.rb b/lib/bundler/injector.rb
index 2cdda578e2..613bda4f84 100644
--- a/lib/bundler/injector.rb
+++ b/lib/bundler/injector.rb
@@ -74,7 +74,7 @@ module Bundler
end
end
- private
+ private
def conservative_version(spec)
version = spec.version
@@ -128,7 +128,7 @@ module Bundler
# evaluates a gemfile to remove the specified gem
# from it.
def remove_deps(gemfile_path)
- initial_gemfile = IO.readlines(gemfile_path)
+ initial_gemfile = File.readlines(gemfile_path)
Bundler.ui.info "Removing gems from #{gemfile_path}"
@@ -179,11 +179,22 @@ module Bundler
# @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
def remove_gems_from_gemfile(gems, gemfile_path)
patterns = /gem\s+(['"])#{Regexp.union(gems)}\1|gem\s*\((['"])#{Regexp.union(gems)}\2\)/
+ new_gemfile = []
+ multiline_removal = false
+ File.readlines(gemfile_path).each do |line|
+ match_data = line.match(patterns)
+ if match_data && is_not_within_comment?(line, match_data)
+ multiline_removal = line.rstrip.end_with?(",")
+ # skip lines which match the regex
+ next
+ end
- # remove lines which match the regex
- new_gemfile = IO.readlines(gemfile_path).reject {|line| line.match(patterns) }
+ # skip followup lines until line does not end with ','
+ new_gemfile << line unless multiline_removal
+ multiline_removal = line.rstrip.end_with?(",") if multiline_removal
+ end
- # remove lone \n and append them with other strings
+ # remove line \n and append them with other strings
new_gemfile.each_with_index do |_line, index|
if new_gemfile[index + 1] == "\n"
new_gemfile[index] += new_gemfile[index + 1]
@@ -196,6 +207,13 @@ module Bundler
new_gemfile.join.chomp
end
+ # @param [String] line Individual line of gemfile content.
+ # @param [MatchData] match_data Data about Regex match.
+ def is_not_within_comment?(line, match_data)
+ match_start_index = match_data.offset(0).first
+ !line[0..match_start_index].include?("#")
+ end
+
# @param [Array] gemfile Array of gemfile contents.
# @param [String] block_name Name of block name to look for.
def remove_nested_blocks(gemfile, block_name)
diff --git a/lib/bundler/inline.rb b/lib/bundler/inline.rb
index f1f77a7a9c..a718418fce 100644
--- a/lib/bundler/inline.rb
+++ b/lib/bundler/inline.rb
@@ -50,15 +50,16 @@ def gemfile(install = false, options = {}, &gemfile)
Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
builder = Bundler::Dsl.new
builder.instance_eval(&gemfile)
+ builder.check_primary_source_safety
- Bundler.settings.temporary(:frozen => false) do
+ Bundler.settings.temporary(:deployment => false, :frozen => false) do
definition = builder.to_definition(nil, true)
def definition.lock(*); end
definition.validate_runtime!
Bundler.ui = install ? ui : Bundler::UI::Silent.new
if install || definition.missing_specs?
- Bundler.settings.temporary(:inline => true, :disable_platform_warnings => true) do
+ Bundler.settings.temporary(:inline => true) do
installer = Bundler::Installer.install(Bundler.root, definition, :system => true)
installer.post_install_messages.each do |name, message|
Bundler.ui.info "Post-install message from #{name}:\n#{message}"
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 700f0a4737..63e02ba496 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "erb"
-require "rubygems/dependency_installer"
require_relative "worker"
require_relative "installer/parallel_installer"
require_relative "installer/standalone"
@@ -83,7 +81,6 @@ module Bundler
if resolve_if_needed(options)
ensure_specs_are_compatible!
- warn_on_incompatible_bundler_deps
load_plugins
options.delete(:jobs)
else
@@ -91,6 +88,8 @@ module Bundler
end
install(options)
+ Gem::Specification.reset # invalidate gem specification cache so that installed gems are immediately available
+
lock unless Bundler.frozen_bundle?
Standalone.new(options[:standalone], @definition).generate if options[:standalone]
end
@@ -135,12 +134,18 @@ module Bundler
next
end
- File.open(binstub_path, "w", 0o777 & ~File.umask) do |f|
- if RUBY_VERSION >= "2.6"
- f.puts ERB.new(template, :trim_mode => "-").result(binding)
- else
- f.puts ERB.new(template, nil, "-").result(binding)
- end
+ mode = Gem.win_platform? ? "wb:UTF-8" : "w"
+ require "erb"
+ content = if RUBY_VERSION >= "2.6"
+ ERB.new(template, :trim_mode => "-").result(binding)
+ else
+ ERB.new(template, nil, "-").result(binding)
+ end
+
+ File.write(binstub_path, content, :mode => mode, :perm => 0o777 & ~File.umask)
+ if Gem.win_platform? || options[:all_platforms]
+ prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
+ File.write("#{binstub_path}.cmd", prefix + content, :mode => mode)
end
end
@@ -159,7 +164,7 @@ module Bundler
end
end
- def generate_standalone_bundler_executable_stubs(spec)
+ def generate_standalone_bundler_executable_stubs(spec, options = {})
# double-assignment to avoid warnings about variables that will be used by ERB
bin_path = Bundler.bin_path
unless path = Bundler.settings[:path]
@@ -175,17 +180,24 @@ module Bundler
next if executable == "bundle"
executable_path = Pathname(spec.full_gem_path).join(spec.bindir, executable).relative_path_from(bin_path)
executable_path = executable_path
- File.open "#{bin_path}/#{executable}", "w", 0o755 do |f|
- if RUBY_VERSION >= "2.6"
- f.puts ERB.new(template, :trim_mode => "-").result(binding)
- else
- f.puts ERB.new(template, nil, "-").result(binding)
- end
+
+ mode = Gem.win_platform? ? "wb:UTF-8" : "w"
+ require "erb"
+ content = if RUBY_VERSION >= "2.6"
+ ERB.new(template, :trim_mode => "-").result(binding)
+ else
+ ERB.new(template, nil, "-").result(binding)
+ end
+
+ File.write("#{bin_path}/#{executable}", content, :mode => mode, :perm => 0o755)
+ if Gem.win_platform? || options[:all_platforms]
+ prefix = "@ruby -x \"%~f0\" %*\n@exit /b %ERRORLEVEL%\n\n"
+ File.write("#{bin_path}/#{executable}.cmd", prefix + content, :mode => mode)
end
end
end
- private
+ private
# the order that the resolver provides is significant, since
# dependencies might affect the installation of a gem.
@@ -202,27 +214,14 @@ module Bundler
return jobs
end
- return 1 unless can_install_in_parallel?
-
- auto_config_jobs = Bundler.feature_flag.auto_config_jobs?
if jobs = Bundler.settings[:jobs]
- if auto_config_jobs
- jobs
- else
- [jobs.pred, 1].max
- end
- elsif auto_config_jobs
- processor_count
- else
- 1
+ return jobs
end
- end
- def processor_count
- require "etc"
- Etc.nprocessors
- rescue StandardError
- 1
+ # Parallelization has some issues on Windows, so it's not yet the default
+ return 1 if Gem.win_platform?
+
+ Bundler.settings.processor_count
end
def load_plugins
@@ -238,6 +237,7 @@ module Bundler
end
end.flatten
Bundler.rubygems.load_plugin_files(path_plugin_files)
+ Bundler.rubygems.load_env_plugins
end
def ensure_specs_are_compatible!
@@ -258,26 +258,6 @@ module Bundler
end
end
- def warn_on_incompatible_bundler_deps
- bundler_version = Gem::Version.create(Bundler::VERSION)
- @definition.specs.each do |spec|
- spec.dependencies.each do |dep|
- next if dep.type == :development
- next unless dep.name == "bundler".freeze
- next if dep.requirement.satisfied_by?(bundler_version)
-
- Bundler.ui.warn "#{spec.name} (#{spec.version}) has dependency" \
- " #{SharedHelpers.pretty_dependency(dep)}" \
- ", which is unsatisfied by the current bundler version #{VERSION}" \
- ", so the dependency is being ignored"
- end
- end
- end
-
- def can_install_in_parallel?
- true
- end
-
def install_in_parallel(size, standalone, force = false)
spec_installations = ParallelInstaller.call(self, @definition.specs, size, standalone, force)
spec_installations.each do |installation|
@@ -296,7 +276,7 @@ module Bundler
# returns whether or not a re-resolve was needed
def resolve_if_needed(options)
- if !@definition.unlocking? && !options["force"] && !options["all-platforms"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
+ if !@definition.unlocking? && !options["force"] && !Bundler.settings[:inline] && Bundler.default_lockfile.file?
return false if @definition.nothing_changed? && !@definition.missing_specs?
end
diff --git a/lib/bundler/installer/gem_installer.rb b/lib/bundler/installer/gem_installer.rb
index 9689911d6c..1df86ccfbc 100644
--- a/lib/bundler/installer/gem_installer.rb
+++ b/lib/bundler/installer/gem_installer.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "shellwords"
-
module Bundler
class GemInstaller
attr_reader :spec, :standalone, :worker, :force, :installer
@@ -19,46 +17,35 @@ module Bundler
Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
generate_executable_stubs
return true, post_install_message
- rescue Bundler::InstallHookError, Bundler::SecurityError, APIResponseMismatchError
+ rescue Bundler::InstallHookError, Bundler::SecurityError, Bundler::APIResponseMismatchError
raise
rescue Errno::ENOSPC
return false, out_of_space_message
- rescue StandardError => e
+ rescue Bundler::BundlerError, Gem::InstallError, Bundler::APIResponseInvalidDependenciesError => e
return false, specific_failure_message(e)
end
- private
+ private
def specific_failure_message(e)
message = "#{e.class}: #{e.message}\n"
- message += " " + e.backtrace.join("\n ") + "\n\n" if Bundler.ui.debug?
+ message += " " + e.backtrace.join("\n ") + "\n\n"
message = message.lines.first + Bundler.ui.add_color(message.lines.drop(1).join, :clear)
message + Bundler.ui.add_color(failure_message, :red)
end
def failure_message
- return install_error_message if spec.source.options["git"]
- "#{install_error_message}\n#{gem_install_message}"
+ install_error_message
end
def install_error_message
"An error occurred while installing #{spec.name} (#{spec.version}), and Bundler cannot continue."
end
- def gem_install_message
- source = spec.source
- return unless source.respond_to?(:remotes)
-
- if source.remotes.size == 1
- "Make sure that `gem install #{spec.name} -v '#{spec.version}' --source '#{source.remotes.first}'` succeeds before bundling."
- else
- "Make sure that `gem install #{spec.name} -v '#{spec.version}'` succeeds before bundling."
- end
- end
-
def spec_settings
# Fetch the build settings, if there are any
if settings = Bundler.settings["build.#{spec.name}"]
+ require "shellwords"
Shellwords.shellsplit(settings)
end
end
diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb
index 391540af0b..5b6680e5e1 100644
--- a/lib/bundler/installer/parallel_installer.rb
+++ b/lib/bundler/installer/parallel_installer.rb
@@ -6,10 +6,11 @@ require_relative "gem_installer"
module Bundler
class ParallelInstaller
class SpecInstallation
- attr_accessor :spec, :name, :post_install_message, :state, :error
+ attr_accessor :spec, :name, :full_name, :post_install_message, :state, :error
def initialize(spec)
@spec = spec
@name = spec.name
+ @full_name = spec.full_name
@state = :none
@post_install_message = ""
@error = nil
@@ -27,13 +28,8 @@ module Bundler
state == :failed
end
- def installation_attempted?
- installed? || failed?
- end
-
- # Only true when spec in neither installed nor already enqueued
def ready_to_enqueue?
- !enqueued? && !installation_attempted?
+ state == :none
end
def has_post_install_message?
@@ -54,14 +50,11 @@ module Bundler
# Represents only the non-development dependencies, the ones that are
# itself and are in the total list.
def dependencies
- @dependencies ||= begin
- all_dependencies.reject {|dep| ignorable_dependency? dep }
- end
+ @dependencies ||= all_dependencies.reject {|dep| ignorable_dependency? dep }
end
def missing_lockfile_dependencies(all_spec_names)
- deps = all_dependencies.reject {|dep| ignorable_dependency? dep }
- deps.reject {|dep| all_spec_names.include? dep.name }
+ dependencies.reject {|dep| all_spec_names.include? dep.name }
end
# Represents all dependencies
@@ -70,7 +63,7 @@ module Bundler
end
def to_s
- "#<#{self.class} #{@spec.full_name} (#{state})>"
+ "#<#{self.class} #{full_name} (#{state})>"
end
end
@@ -93,18 +86,48 @@ module Bundler
def call
check_for_corrupt_lockfile
+ if @rake
+ do_install(@rake, 0)
+ Gem::Specification.reset
+ end
+
if @size > 1
install_with_worker
else
install_serially
end
- handle_error if @specs.any?(&:failed?)
+ check_for_unmet_dependencies
+
+ handle_error if failed_specs.any?
@specs
ensure
worker_pool && worker_pool.stop
end
+ def check_for_unmet_dependencies
+ unmet_dependencies = @specs.map do |s|
+ [
+ s,
+ s.dependencies.reject {|dep| @specs.any? {|spec| dep.matches_spec?(spec.spec) } },
+ ]
+ end.reject {|a| a.last.empty? }
+ return if unmet_dependencies.empty?
+
+ warning = []
+ warning << "Your lockfile doesn't include a valid resolution."
+ warning << "You can fix this by regenerating your lockfile or trying to manually editing the bad locked gems to a version that satisfies all dependencies."
+ warning << "The unmet dependencies are:"
+
+ unmet_dependencies.each do |spec, unmet_spec_dependencies|
+ unmet_spec_dependencies.each do |unmet_spec_dependency|
+ warning << "* #{unmet_spec_dependency}, depended upon #{spec.full_name}, unsatisfied by #{@specs.find {|s| s.name == unmet_spec_dependency.name && !unmet_spec_dependency.matches_spec?(s.spec) }.full_name}"
+ end
+ end
+
+ Bundler.ui.warn(warning.join("\n"))
+ end
+
def check_for_corrupt_lockfile
missing_dependencies = @specs.map do |s|
[
@@ -130,7 +153,11 @@ module Bundler
Bundler.ui.warn(warning.join("\n"))
end
- private
+ private
+
+ def failed_specs
+ @specs.select(&:failed?)
+ end
def install_with_worker
enqueue_specs
@@ -156,17 +183,13 @@ module Bundler
gem_installer = Bundler::GemInstaller.new(
spec_install.spec, @installer, @standalone, worker_num, @force
)
- success, message = begin
- gem_installer.install_from_spec
- rescue RuntimeError => e
- raise e, "#{e}\n\n#{require_tree_for_spec(spec_install.spec)}"
- end
+ success, message = gem_installer.install_from_spec
if success
spec_install.state = :installed
spec_install.post_install_message = message unless message.nil?
else
- spec_install.state = :failed
spec_install.error = "#{message}\n\n#{require_tree_for_spec(spec_install.spec)}"
+ spec_install.state = :failed
end
Plugin.hook(Plugin::Events::GEM_AFTER_INSTALL, spec_install)
spec_install
@@ -190,11 +213,11 @@ module Bundler
end
def handle_error
- errors = @specs.select(&:failed?).map(&:error)
+ errors = failed_specs.map(&:error)
if exception = errors.find {|e| e.is_a?(Bundler::BundlerError) }
raise exception
end
- raise Bundler::InstallError, errors.map(&:to_s).join("\n\n")
+ raise Bundler::InstallError, errors.join("\n\n")
end
def require_tree_for_spec(spec)
@@ -217,8 +240,6 @@ module Bundler
# are installed.
def enqueue_specs
@specs.select(&:ready_to_enqueue?).each do |spec|
- next if @rake && !@rake.installed? && spec.name != @rake.name
-
if spec.dependencies_installed? @specs
spec.state = :enqueued
worker_pool.enq spec
diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb
index e1beb25ad1..e8494b4bcd 100644
--- a/lib/bundler/installer/standalone.rb
+++ b/lib/bundler/installer/standalone.rb
@@ -3,7 +3,7 @@
module Bundler
class Standalone
def initialize(groups, definition)
- @specs = groups.empty? ? definition.requested_specs : definition.specs_for(groups.map(&:to_sym))
+ @specs = definition.specs_for(groups)
end
def generate
@@ -12,29 +12,31 @@ module Bundler
end
File.open File.join(bundler_path, "setup.rb"), "w" do |file|
file.puts "require 'rbconfig'"
- file.puts "ruby_engine = RUBY_ENGINE"
- file.puts "ruby_version = RbConfig::CONFIG[\"ruby_version\"]"
- file.puts "path = File.expand_path('..', __FILE__)"
+ file.puts reverse_rubygems_kernel_mixin
paths.each do |path|
- file.puts %($:.unshift "\#{path}/#{path}")
+ if Pathname.new(path).absolute?
+ file.puts %($:.unshift "#{path}")
+ else
+ file.puts %($:.unshift File.expand_path("\#{__dir__}/#{path}"))
+ end
end
end
end
- private
+ private
def paths
@specs.map do |spec|
next if spec.name == "bundler"
Array(spec.require_paths).map do |path|
- gem_path(path, spec).sub(version_dir, '#{ruby_engine}/#{ruby_version}')
+ gem_path(path, spec).sub(version_dir, '#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}')
# This is a static string intentionally. It's interpolated at a later time.
end
- end.flatten
+ end.flatten.compact
end
def version_dir
- "#{Bundler::RubyVersion.system.engine}/#{RbConfig::CONFIG["ruby_version"]}"
+ "#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}"
end
def bundler_path
@@ -43,10 +45,28 @@ module Bundler
def gem_path(path, spec)
full_path = Pathname.new(path).absolute? ? path : File.join(spec.full_gem_path, path)
- Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s
+ if spec.source.instance_of?(Source::Path)
+ full_path
+ else
+ Pathname.new(full_path).relative_path_from(Bundler.root.join(bundler_path)).to_s
+ end
rescue TypeError
error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
raise Gem::InvalidSpecificationException.new(error_message)
end
+
+ def reverse_rubygems_kernel_mixin
+ <<~END
+ kernel = (class << ::Kernel; self; end)
+ [kernel, ::Kernel].each do |k|
+ if k.private_method_defined?(:gem_original_require)
+ private_require = k.private_method_defined?(:require)
+ k.send(:remove_method, :require)
+ k.send(:define_method, :require, k.instance_method(:gem_original_require))
+ k.send(:private, :require) if private_require
+ end
+ end
+ END
+ end
end
end
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index 32c8bb9557..4eb228f314 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -4,22 +4,6 @@ require_relative "match_platform"
module Bundler
class LazySpecification
- Identifier = Struct.new(:name, :version, :source, :platform, :dependencies)
- class Identifier
- include Comparable
- def <=>(other)
- return unless other.is_a?(Identifier)
- [name, version, platform_string] <=> [other.name, other.version, other.platform_string]
- end
-
- protected
-
- def platform_string
- platform_string = platform.to_s
- platform_string == Index::RUBY ? Index::NULL : platform_string
- end
- end
-
include MatchPlatform
attr_reader :name, :version, :dependencies, :platform
@@ -46,8 +30,32 @@ module Bundler
identifier == other.identifier
end
+ def eql?(other)
+ identifier.eql?(other.identifier)
+ end
+
+ def hash
+ identifier.hash
+ end
+
+ ##
+ # Does this locked specification satisfy +dependency+?
+ #
+ # NOTE: Rubygems default requirement is ">= 0", which doesn't match
+ # prereleases of 0 versions, like "0.0.0.dev" or "0.0.0.SNAPSHOT". However,
+ # bundler users expect those to work. We need to make sure that Gemfile
+ # dependencies without explicit requirements (which use ">= 0" under the
+ # hood by default) are still valid for locked specs using this kind of
+ # versions. The method implements an ad-hoc fix for that. A better solution
+ # might be to change default rubygems requirement of dependencies to be ">=
+ # 0.A" but that's a major refactoring likely to break things. Hopefully we
+ # can attempt it in the future.
+ #
+
def satisfies?(dependency)
- @name == dependency.name && dependency.requirement.satisfied_by?(Gem::Version.new(@version))
+ effective_requirement = dependency.requirement == Gem::Requirement.default ? Gem::Requirement.new(">= 0.A") : dependency.requirement
+
+ @name == dependency.name && effective_requirement.satisfied_by?(Gem::Version.new(@version))
end
def to_lock
@@ -68,17 +76,25 @@ module Bundler
end
def __materialize__
- search_object = Bundler.feature_flag.specific_platform? || Bundler.settings[:force_ruby_platform] ? self : Dependency.new(name, version)
@specification = if source.is_a?(Source::Gemspec) && source.gemspec.name == name
source.gemspec.tap {|s| s.source = source }
else
- search = source.specs.search(search_object).last
- if search && Gem::Platform.new(search.platform) != Gem::Platform.new(platform) && !search.runtime_dependencies.-(dependencies.reject {|d| d.type == :development }).empty?
- Bundler.ui.warn "Unable to use the platform-specific (#{search.platform}) version of #{name} (#{version}) " \
- "because it has different dependencies from the #{platform} version. " \
- "To use the platform-specific version of the gem, run `bundle config set specific_platform true` and install again."
- search = source.specs.search(self).last
+ search_object = if source.is_a?(Source::Path)
+ Dependency.new(name, version)
+ else
+ ruby_platform_materializes_to_ruby_platform? ? self : Dependency.new(name, version)
+ end
+ platform_object = Gem::Platform.new(platform)
+ candidates = source.specs.search(search_object)
+ same_platform_candidates = candidates.select do |spec|
+ MatchPlatform.platforms_match?(spec.platform, platform_object)
end
+ installable_candidates = same_platform_candidates.select do |spec|
+ !spec.is_a?(EndpointSpecification) ||
+ (spec.required_ruby_version.satisfied_by?(Gem.ruby_version) &&
+ spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version))
+ end
+ search = installable_candidates.last || same_platform_candidates.last
search.dependencies = dependencies if search && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
search
end
@@ -97,7 +113,7 @@ module Bundler
end
def identifier
- @__identifier ||= Identifier.new(name, version, source, platform, dependencies)
+ @__identifier ||= [name, version, platform_string]
end
def git_version
@@ -105,7 +121,14 @@ module Bundler
" #{source.revision[0..6]}"
end
- private
+ protected
+
+ def platform_string
+ platform_string = platform.to_s
+ platform_string == Index::RUBY ? Index::NULL : platform_string
+ end
+
+ private
def to_ary
nil
@@ -118,5 +141,18 @@ module Bundler
@specification.send(method, *args, &blk)
end
+
+ #
+ # For backwards compatibility with existing lockfiles, if the most specific
+ # locked platform is RUBY, we keep the previous behaviour of resolving the
+ # best platform variant at materiliazation time. For previous bundler
+ # versions (before 2.2.0) this was always the case (except when the lockfile
+ # only included non-ruby platforms), but we're also keeping this behaviour
+ # on newer bundlers unless users generate the lockfile from scratch or
+ # explicitly add a more specific platform.
+ #
+ def ruby_platform_materializes_to_ruby_platform?
+ !Bundler.most_specific_locked_platform?(Gem::Platform::RUBY) || Bundler.settings[:force_ruby_platform]
+ end
end
end
diff --git a/lib/bundler/lockfile_generator.rb b/lib/bundler/lockfile_generator.rb
index 585077d18d..3bc6bd7339 100644
--- a/lib/bundler/lockfile_generator.rb
+++ b/lib/bundler/lockfile_generator.rb
@@ -25,7 +25,7 @@ module Bundler
out
end
- private
+ private
def add_sources
definition.send(:sources).lock_sources.each_with_index do |source, idx|
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index caabd524d4..6ff4910a36 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -1,16 +1,5 @@
# frozen_string_literal: true
-#--
-# Some versions of the Bundler 1.1 RC series introduced corrupted
-# lockfiles. There were two major problems:
-#
-# * multiple copies of the same GIT section appeared in the lockfile
-# * when this happened, those sections got multiple copies of gems
-# in those sections.
-#
-# As a result, Bundler 1.1 contains code that fixes the earlier
-# corruption. We will remove this fix-up code in Bundler 1.2.
-
module Bundler
class LockfileParser
attr_reader :sources, :dependencies, :specs, :platforms, :bundler_version, :ruby_version
@@ -64,8 +53,6 @@ module Bundler
@state = nil
@specs = {}
- @rubygems_aggregate = Source::Rubygems.new
-
if lockfile.match(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
raise LockfileError, "Your #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} contains merge conflicts.\n" \
"Run `git checkout HEAD -- #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)}` first to get a clean lock."
@@ -89,7 +76,6 @@ module Bundler
send("parse_#{@state}", line)
end
end
- @sources << @rubygems_aggregate unless Bundler.feature_flag.disable_multisource?
@specs = @specs.values.sort_by(&:identifier)
warn_for_outdated_bundler_version
rescue ArgumentError => e
@@ -100,6 +86,7 @@ module Bundler
def warn_for_outdated_bundler_version
return unless bundler_version
+ return if bundler_version.segments.last == "dev"
prerelease_text = bundler_version.prerelease? ? " --pre" : ""
current_version = Gem::Version.create(Bundler::VERSION)
return unless current_version < bundler_version
@@ -109,7 +96,7 @@ module Bundler
"bundler:#{bundler_version}#{prerelease_text}`.\n"
end
- private
+ private
TYPES = {
GIT => Bundler::Source::Git,
@@ -127,23 +114,11 @@ module Bundler
@sources << @current_source
when GIT
@current_source = TYPES[@type].from_lock(@opts)
- # Strip out duplicate GIT sections
- if @sources.include?(@current_source)
- @current_source = @sources.find {|s| s == @current_source }
- else
- @sources << @current_source
- end
+ @sources << @current_source
when GEM
- if Bundler.feature_flag.disable_multisource?
- @opts["remotes"] = @opts.delete("remote")
- @current_source = TYPES[@type].from_lock(@opts)
- @sources << @current_source
- else
- Array(@opts["remote"]).each do |url|
- @rubygems_aggregate.add_remote(url)
- end
- @current_source = @rubygems_aggregate
- end
+ @opts["remotes"] = Array(@opts.delete("remote")).reverse
+ @current_source = TYPES[@type].from_lock(@opts)
+ @sources << @current_source
when PLUGIN
@current_source = Plugin.source_from_lock(@opts)
@sources << @current_source
@@ -221,10 +196,9 @@ module Bundler
platform = platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
@current_spec = LazySpecification.new(name, version, platform)
@current_spec.source = @current_source
+ @current_source.add_dependency_names(name)
- # Avoid introducing multiple copies of the same spec (caused by
- # duplicate GIT sections)
- @specs[@current_spec.identifier] ||= @current_spec
+ @specs[@current_spec.identifier] = @current_spec
elsif spaces.size == 6
version = version.split(",").map(&:strip) if version
dep = Gem::Dependency.new(name, version)
diff --git a/lib/bundler/man/.document b/lib/bundler/man/.document
new file mode 100644
index 0000000000..fb66f13c33
--- /dev/null
+++ b/lib/bundler/man/.document
@@ -0,0 +1 @@
+# Ignore all files in this directory
diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1
new file mode 100644
index 0000000000..a94467e25f
--- /dev/null
+++ b/lib/bundler/man/bundle-add.1
@@ -0,0 +1,66 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-ADD" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
+.
+.SH "SYNOPSIS"
+\fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-git=GIT] [\-\-branch=BRANCH] [\-\-skip\-install] [\-\-strict] [\-\-optimistic]
+.
+.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"
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-version\fR, \fB\-v\fR
+Specify version requirements(s) for the added gem\.
+.
+.TP
+\fB\-\-group\fR, \fB\-g\fR
+Specify the group(s) for the added gem\. Multiple groups should be separated by commas\.
+.
+.TP
+\fB\-\-source\fR, , \fB\-s\fR
+Specify the source for the added gem\.
+.
+.TP
+\fB\-\-git\fR
+Specify the git source for the added gem\.
+.
+.TP
+\fB\-\-branch\fR
+Specify the git branch for the added gem\.
+.
+.TP
+\fB\-\-skip\-install\fR
+Adds the gem to the Gemfile but does not install it\.
+.
+.TP
+\fB\-\-optimistic\fR
+Adds optimistic declaration of version
+.
+.TP
+\fB\-\-strict\fR
+Adds strict declaration of version
+
diff --git a/man/bundle-add.ronn b/lib/bundler/man/bundle-add.1.ronn
index 26cbe55647..26cbe55647 100644
--- a/man/bundle-add.ronn
+++ b/lib/bundler/man/bundle-add.1.ronn
diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1
new file mode 100644
index 0000000000..6d1b1d4247
--- /dev/null
+++ b/lib/bundler/man/bundle-binstubs.1
@@ -0,0 +1,42 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-BINSTUBS" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
+.
+.SH "SYNOPSIS"
+\fBbundle binstubs\fR \fIGEM_NAME\fR [\-\-force] [\-\-path PATH] [\-\-standalone]
+.
+.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\.
+.
+.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
+Specify a different shebang executable name than the default (default \'ruby\')
+.
+.TP
+\fB\-\-all\fR
+Create binstubs for all gems in the bundle\.
+
diff --git a/lib/bundler/man/bundle-binstubs.1.ronn b/lib/bundler/man/bundle-binstubs.1.ronn
new file mode 100644
index 0000000000..a96186929f
--- /dev/null
+++ b/lib/bundler/man/bundle-binstubs.1.ronn
@@ -0,0 +1,41 @@
+bundle-binstubs(1) -- Install the binstubs of the listed gems
+=============================================================
+
+## SYNOPSIS
+
+`bundle binstubs` <GEM_NAME> [--force] [--path PATH] [--standalone]
+
+## DESCRIPTION
+
+Binstubs are scripts that wrap around executables. Bundler creates a
+small Ruby file (a binstub) that loads Bundler, runs the command,
+and puts it into `bin/`. Binstubs are a shortcut-or alternative-
+to always using `bundle exec`. This gives you a file that can be run
+directly, and one that will always run the correct gem version
+used by the application.
+
+For example, if you run `bundle binstubs rspec-core`, Bundler will create
+the file `bin/rspec`. That file will contain enough code to load Bundler,
+tell it to load the bundled gems, and then run rspec.
+
+This command generates binstubs for executables in `GEM_NAME`.
+Binstubs are put into `bin`, or the `--path` directory if one has been set.
+Calling binstubs with [GEM [GEM]] will create binstubs for all given gems.
+
+## OPTIONS
+
+* `--force`:
+ Overwrite existing binstubs if they exist.
+
+* `--path`:
+ The location to install the specified binstubs to. This defaults to `bin`.
+
+* `--standalone`:
+ Makes binstubs that can work without depending on Rubygems or Bundler at
+ runtime.
+
+* `--shebang`:
+ Specify a different shebang executable name than the default (default 'ruby')
+
+* `--all`:
+ Create binstubs for all gems in the bundle.
diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1
new file mode 100644
index 0000000000..acbdae0df2
--- /dev/null
+++ b/lib/bundler/man/bundle-cache.1
@@ -0,0 +1,55 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-CACHE" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
+.
+.SH "SYNOPSIS"
+\fBbundle cache\fR
+.
+.SH "DESCRIPTION"
+Copy all of the \fB\.gem\fR files needed to run the application into the \fBvendor/cache\fR directory\. In the future, when running [bundle install(1)][bundle\-install], use the gems in the cache in preference to the ones on \fBrubygems\.org\fR\.
+.
+.SH "GIT AND PATH GEMS"
+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\.
+.
+.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"
+By default, if you run \fBbundle install(1)\fR](bundle\-install\.1\.html) after running bundle cache(1) \fIbundle\-cache\.1\.html\fR, bundler will still connect to \fBrubygems\.org\fR to check whether a platform\-specific gem exists for any of the gems in \fBvendor/cache\fR\.
+.
+.P
+For instance, consider this Gemfile(5):
+.
+.IP "" 4
+.
+.nf
+
+source "https://rubygems\.org"
+
+gem "nokogiri"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+If you run \fBbundle cache\fR under C Ruby, bundler will retrieve the version of \fBnokogiri\fR for the \fB"ruby"\fR platform\. If you deploy to JRuby and run \fBbundle install\fR, bundler is forced to check to see whether a \fB"java"\fR platformed \fBnokogiri\fR exists\.
+.
+.P
+Even though the \fBnokogiri\fR gem for the Ruby platform is \fItechnically\fR acceptable on JRuby, it has a C extension that does not run on JRuby\. As a result, bundler will, by default, still connect to \fBrubygems\.org\fR to check whether it has a version of one of your gems more specific to your platform\.
+.
+.P
+This problem is also not limited to the \fB"java"\fR platform\. A similar (common) problem can happen when developing on Windows and deploying to Linux, or even when developing on OSX and deploying to Linux\.
+.
+.P
+If you know for sure that the gems packaged in \fBvendor/cache\fR are appropriate for the platform you are on, you can run \fBbundle install \-\-local\fR to skip checking for more appropriate gems, and use the ones in \fBvendor/cache\fR\.
+.
+.P
+One way to be sure that you have the right platformed versions of all your gems is to run \fBbundle cache\fR on an identical machine and check in the gems\. For instance, you can run \fBbundle cache\fR on an identical staging box during your staging process, and check in the \fBvendor/cache\fR before deploying to production\.
+.
+.P
+By default, bundle cache(1) \fIbundle\-cache\.1\.html\fR fetches and also installs the gems to the default location\. To package the dependencies to \fBvendor/cache\fR without installing them to the local install location, you can run \fBbundle cache \-\-no\-install\fR\.
diff --git a/man/bundle-cache.ronn b/lib/bundler/man/bundle-cache.1.ronn
index 383adb2ba3..383adb2ba3 100644
--- a/man/bundle-cache.ronn
+++ b/lib/bundler/man/bundle-cache.1.ronn
diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1
new file mode 100644
index 0000000000..e555c9b399
--- /dev/null
+++ b/lib/bundler/man/bundle-check.1
@@ -0,0 +1,31 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-CHECK" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
+.
+.SH "SYNOPSIS"
+\fBbundle check\fR [\-\-dry\-run] [\-\-gemfile=FILE] [\-\-path=PATH]
+.
+.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
+If not, the first missing gem is listed and Bundler exits status 1\.
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-dry\-run\fR
+Locks the [\fBGemfile(5)\fR][Gemfile(5)] before running the command\.
+.
+.TP
+\fB\-\-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/man/bundle-check.ronn b/lib/bundler/man/bundle-check.1.ronn
index f2846b8ff2..f2846b8ff2 100644
--- a/man/bundle-check.ronn
+++ b/lib/bundler/man/bundle-check.1.ronn
diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1
new file mode 100644
index 0000000000..d403247524
--- /dev/null
+++ b/lib/bundler/man/bundle-clean.1
@@ -0,0 +1,24 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-CLEAN" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
+.
+.SH "SYNOPSIS"
+\fBbundle clean\fR [\-\-dry\-run] [\-\-force]
+.
+.SH "DESCRIPTION"
+This command will remove all unused gems in your bundler directory\. This is useful when you have made many changes to your gem dependencies\.
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-dry\-run\fR
+Print the changes, but do not clean the unused gems\.
+.
+.TP
+\fB\-\-force\fR
+Force a clean even if \fB\-\-path\fR is not set\.
+
diff --git a/man/bundle-clean.ronn b/lib/bundler/man/bundle-clean.1.ronn
index de23991782..de23991782 100644
--- a/man/bundle-clean.ronn
+++ b/lib/bundler/man/bundle-clean.1.ronn
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
new file mode 100644
index 0000000000..976dae3aec
--- /dev/null
+++ b/lib/bundler/man/bundle-config.1
@@ -0,0 +1,496 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-CONFIG" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-config\fR \- Set bundler configuration options
+.
+.SH "SYNOPSIS"
+\fBbundle config\fR [list|get|set|unset] [\fIname\fR [\fIvalue\fR]]
+.
+.SH "DESCRIPTION"
+This command allows you to interact with Bundler\'s configuration system\.
+.
+.P
+Bundler loads configuration settings in this order:
+.
+.IP "1." 4
+Local config (\fB<project_root>/\.bundle/config\fR or \fB$BUNDLE_APP_CONFIG/config\fR)
+.
+.IP "2." 4
+Environmental variables (\fBENV\fR)
+.
+.IP "3." 4
+Global config (\fB~/\.bundle/config\fR)
+.
+.IP "4." 4
+Bundler default config
+.
+.IP "" 0
+.
+.P
+Executing \fBbundle config list\fR with will print a list of all bundler configuration for the current bundle, and where that configuration 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 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
+Executing \fBbundle config set \-\-global <name> <value>\fR works the same as above\.
+.
+.P
+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
+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
+Executing \fBbundle config unset \-\-local <name> <value>\fR will delete the configuration only from the local application\.
+.
+.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)\.
+.
+.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)\.
+.
+.P
+The options that can be configured are:
+.
+.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\.
+.
+.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\.
+.
+.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\.
+.
+.TP
+\fBwithout\fR
+A space\-separated list of groups referencing gems to skip during installation\.
+.
+.TP
+\fBwith\fR
+A space\-separated list of groups referencing gems to include during installation\.
+.
+.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
+A very common example, the \fBmysql\fR gem, requires Snow Leopard users to pass configuration flags to \fBgem install\fR to specify where to find the \fBmysql_config\fR executable\.
+.
+.IP "" 4
+.
+.nf
+
+gem install mysql \-\- \-\-with\-mysql\-config=/usr/local/mysql/bin/mysql_config
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Since the specific location of that executable can change from machine to machine, you can specify these flags on a per\-machine basis\.
+.
+.IP "" 4
+.
+.nf
+
+bundle config set \-\-global build\.mysql \-\-with\-mysql\-config=/usr/local/mysql/bin/mysql_config
+.
+.fi
+.
+.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_deployment_source_credential_changes\fR (\fBBUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES\fR): When in deployment mode, allow changing the credentials to a gem\'s source\. Ex: \fBhttps://some\.host\.com/gems/path/\fR \-> \fBhttps://user_name:password@some\.host\.com/gems/path\fR
+.
+.IP "\(bu" 4
+\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_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 1 on Windows, and to the the number of processors on other platforms\.
+.
+.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
+\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
+\fBsuppress_install_using_messages\fR (\fBBUNDLE_SUPPRESS_INSTALL_USING_MESSAGES\fR): Avoid printing \fBUsing \.\.\.\fR messages during installation when the version of a gem has not changed\.
+.
+.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
+\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 package(1) \fIbundle\-package\.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
+.
+.nf
+
+bundle config set \-\-local local\.GEM_NAME /path/to/local/git/repository
+.
+.fi
+.
+.IP "" 0
+.
+.P
+For example, in order to use a local Rack repository, a developer could call:
+.
+.IP "" 4
+.
+.nf
+
+bundle config set \-\-local local\.rack ~/Work/git/rack
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Now instead of checking out the remote git repository, the local override will be used\. Similar to a path source, every time the local git repository change, changes will be automatically picked up by Bundler\. This means a commit in the local git repo will update the revision in the \fBGemfile\.lock\fR to the local git repo revision\. This requires the same attention as git submodules\. Before pushing to the remote, you need to ensure the local override was pushed, otherwise you may point to a commit that only exists in your local machine\. You\'ll also need to CGI escape your usernames and passwords as well\.
+.
+.P
+Bundler does many checks to ensure a developer won\'t work with invalid references\. Particularly, we force a developer to specify a branch in the \fBGemfile\fR in order to use this feature\. If the branch specified in the \fBGemfile\fR and the current branch in the local git repository do not match, Bundler will abort\. This ensures that a developer is always working against the correct branches, and prevents accidental locking to a different branch\.
+.
+.P
+Finally, Bundler also ensures that the current revision in the \fBGemfile\.lock\fR exists in the local git repository\. By doing this, Bundler forces you to fetch the latest changes in the remotes\.
+.
+.SH "MIRRORS OF GEM SOURCES"
+Bundler supports overriding gem sources with mirrors\. This allows you to configure rubygems\.org as the gem source in your Gemfile while still using your mirror to fetch gems\.
+.
+.IP "" 4
+.
+.nf
+
+bundle config set \-\-global mirror\.SOURCE_URL MIRROR_URL
+.
+.fi
+.
+.IP "" 0
+.
+.P
+For example, to use a mirror of rubygems\.org hosted at rubygems\-mirror\.org:
+.
+.IP "" 4
+.
+.nf
+
+bundle config set \-\-global mirror\.http://rubygems\.org http://rubygems\-mirror\.org
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Each mirror also provides a fallback timeout setting\. If the mirror does not respond within the fallback timeout, Bundler will try to use the original server instead of the mirror\.
+.
+.IP "" 4
+.
+.nf
+
+bundle config set \-\-global mirror\.SOURCE_URL\.fallback_timeout TIMEOUT
+.
+.fi
+.
+.IP "" 0
+.
+.P
+For example, to fall back to rubygems\.org after 3 seconds:
+.
+.IP "" 4
+.
+.nf
+
+bundle config set \-\-global mirror\.https://rubygems\.org\.fallback_timeout 3
+.
+.fi
+.
+.IP "" 0
+.
+.P
+The default fallback timeout is 0\.1 seconds, but the setting can currently only accept whole seconds (for example, 1, 15, or 30)\.
+.
+.SH "CREDENTIALS FOR GEM SOURCES"
+Bundler allows you to configure credentials for any gem source, which allows you to avoid putting secrets into your Gemfile\.
+.
+.IP "" 4
+.
+.nf
+
+bundle config set \-\-global SOURCE_HOSTNAME USERNAME:PASSWORD
+.
+.fi
+.
+.IP "" 0
+.
+.P
+For example, to save the credentials of user \fBclaudette\fR for the gem source at \fBgems\.longerous\.com\fR, you would run:
+.
+.IP "" 4
+.
+.nf
+
+bundle config set \-\-global gems\.longerous\.com claudette:s00pers3krit
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Or you can set the credentials as an environment variable like this:
+.
+.IP "" 4
+.
+.nf
+
+export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+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
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Or you can set the credentials as an environment variable like so:
+.
+.IP "" 4
+.
+.nf
+
+export BUNDLE_GITHUB__COM=username:password
+.
+.fi
+.
+.IP "" 0
+.
+.P
+This is especially useful for private repositories on hosts such as Github, where you can use personal OAuth tokens:
+.
+.IP "" 4
+.
+.nf
+
+export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x\-oauth\-basic
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Note that any configured credentials will be redacted by informative commands such as \fBbundle config list\fR or \fBbundle config get\fR, unless you use the \fB\-\-parseable\fR flag\. This is to avoid unintentionally leaking credentials when copy\-pasting bundler output\.
+.
+.P
+Also note that to guarantee a sane mapping between valid environment variable names and valid host names, bundler makes the following transformations:
+.
+.IP "\(bu" 4
+Any \fB\-\fR characters in a host name are mapped to a triple dash (\fB___\fR) in the corresponding environment variable\.
+.
+.IP "\(bu" 4
+Any \fB\.\fR characters in a host name are mapped to a double dash (\fB__\fR) in the corresponding environment variable\.
+.
+.IP "" 0
+.
+.P
+This means that if you have a gem server named \fBmy\.gem\-host\.com\fR, you\'ll need to use the \fBBUNDLE_MY__GEM___HOST__COM\fR variable to configure credentials for it through ENV\.
+.
+.SH "CONFIGURE BUNDLER DIRECTORIES"
+Bundler\'s home, config, cache and plugin directories are able to be configured through environment variables\. The default location for Bundler\'s home directory is \fB~/\.bundle\fR, which all directories inherit from by default\. The following outlines the available environment variables and their default values
+.
+.IP "" 4
+.
+.nf
+
+BUNDLE_USER_HOME : $HOME/\.bundle
+BUNDLE_USER_CACHE : $BUNDLE_USER_HOME/cache
+BUNDLE_USER_CONFIG : $BUNDLE_USER_HOME/config
+BUNDLE_USER_PLUGIN : $BUNDLE_USER_HOME/plugin
+.
+.fi
+.
+.IP "" 0
+
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
new file mode 100644
index 0000000000..f412ee3aec
--- /dev/null
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -0,0 +1,396 @@
+bundle-config(1) -- Set bundler configuration options
+=====================================================
+
+## SYNOPSIS
+
+`bundle config` [list|get|set|unset] [<name> [<value>]]
+
+## DESCRIPTION
+
+This command allows you to interact with Bundler's configuration system.
+
+Bundler loads configuration settings in this order:
+
+1. Local config (`<project_root>/.bundle/config` or `$BUNDLE_APP_CONFIG/config`)
+2. Environmental variables (`ENV`)
+3. Global config (`~/.bundle/config`)
+4. Bundler default config
+
+Executing `bundle config list` with will print a list of all bundler
+configuration for the current bundle, and where that configuration
+was set.
+
+Executing `bundle config get <name>` will print the value of that configuration
+setting, and where it was set.
+
+Executing `bundle config set <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 set --global <name> <value>` works the same as above.
+
+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 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> <value>` will delete the
+configuration only from the local application.
+
+Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
+cause it to ignore all configuration.
+
+## REMEMBERING OPTIONS
+
+Flags passed to `bundle install` or the Bundler runtime, such as `--path foo` or
+`--without production`, are remembered between commands and saved to your local
+application's configuration (normally, `./.bundle/config`).
+
+However, this will be changed in bundler 3, so it's better not to rely on this
+behavior. If these options must be remembered, it's better to set them using
+`bundle config` (e.g., `bundle config set --local path foo`).
+
+The options that can be configured are:
+
+* `bin`:
+ Creates a directory (defaults to `~/bin`) and place any executables from the
+ gem there. These executables run in Bundler's context. If used, you might add
+ this directory to your environment's `PATH` variable. For instance, if the
+ `rails` gem comes with a `rails` executable, this flag will create a
+ `bin/rails` executable that ensures that all referred dependencies will be
+ resolved using the bundled gems.
+
+* `deployment`:
+ In deployment mode, Bundler will 'roll-out' the bundle for
+ `production` use. Please check carefully if you want to have this option
+ enabled in `development` or `test` environments.
+
+* `path`:
+ The location to install the specified gems to. This defaults to Rubygems'
+ setting. Bundler shares this location with Rubygems, `gem install ...` will
+ have gem installed there, too. Therefore, gems installed without a
+ `--path ...` setting will show up by calling `gem list`. Accordingly, gems
+ installed to other locations will not get listed.
+
+* `without`:
+ A space-separated list of groups referencing gems to skip during installation.
+
+* `with`:
+ A space-separated list of groups referencing gems to include during installation.
+
+## BUILD OPTIONS
+
+You can use `bundle config` to give Bundler the flags to pass to the gem
+installer every time bundler tries to install a particular gem.
+
+A very common example, the `mysql` gem, requires Snow Leopard users to
+pass configuration flags to `gem install` to specify where to find the
+`mysql_config` executable.
+
+ gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
+
+Since the specific location of that executable can change from machine
+to machine, you can specify these flags on a per-machine basis.
+
+ bundle config set --global build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config
+
+After running this command, every time bundler needs to install the
+`mysql` gem, it will pass along the flags you specified.
+
+## CONFIGURATION KEYS
+
+Configuration keys in bundler have two forms: the canonical form and the
+environment variable form.
+
+For instance, passing the `--without` flag to [bundle install(1)](bundle-install.1.html)
+prevents Bundler from installing certain groups specified in the Gemfile(5). Bundler
+persists this value in `app/.bundle/config` so that calls to `Bundler.setup`
+do not try to find gems from the `Gemfile` that you didn't install. Additionally,
+subsequent calls to [bundle install(1)](bundle-install.1.html) remember this setting
+and skip those groups.
+
+The canonical form of this configuration is `"without"`. To convert the canonical
+form to the environment variable form, capitalize it, and prepend `BUNDLE_`. The
+environment variable form of `"without"` is `BUNDLE_WITHOUT`.
+
+Any periods in the configuration keys must be replaced with two underscores when
+setting it via environment variables. The configuration key `local.rack` becomes
+the environment variable `BUNDLE_LOCAL__RACK`.
+
+## LIST OF AVAILABLE KEYS
+
+The following is a list of all configuration keys and their purpose. You can
+learn more about their operation in [bundle install(1)](bundle-install.1.html).
+
+* `allow_deployment_source_credential_changes` (`BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES`):
+ When in deployment mode, allow changing the credentials to a gem's source.
+ Ex: `https://some.host.com/gems/path/` -> `https://user_name:password@some.host.com/gems/path`
+* `allow_offline_install` (`BUNDLE_ALLOW_OFFLINE_INSTALL`):
+ Allow Bundler to use cached data when installing without network access.
+* `auto_clean_without_path` (`BUNDLE_AUTO_CLEAN_WITHOUT_PATH`):
+ Automatically run `bundle clean` after installing when an explicit `path`
+ has not been set and Bundler is not installing into the system gems.
+* `auto_install` (`BUNDLE_AUTO_INSTALL`):
+ Automatically run `bundle install` when gems are missing.
+* `bin` (`BUNDLE_BIN`):
+ Install executables from gems in the bundle to the specified directory.
+ Defaults to `false`.
+* `cache_all` (`BUNDLE_CACHE_ALL`):
+ Cache all gems, including path and git gems. This needs to be explicitly
+ configured on bundler 1 and bundler 2, but will be the default on bundler 3.
+* `cache_all_platforms` (`BUNDLE_CACHE_ALL_PLATFORMS`):
+ Cache gems for all platforms.
+* `cache_path` (`BUNDLE_CACHE_PATH`):
+ The directory that bundler will place cached gems in when running
+ <code>bundle package</code>, and that bundler will look in when installing gems.
+ Defaults to `vendor/cache`.
+* `clean` (`BUNDLE_CLEAN`):
+ Whether Bundler should run `bundle clean` automatically after
+ `bundle install`.
+* `console` (`BUNDLE_CONSOLE`):
+ The console that `bundle console` starts. Defaults to `irb`.
+* `default_install_uses_path` (`BUNDLE_DEFAULT_INSTALL_USES_PATH`):
+ Whether a `bundle install` without an explicit `--path` argument defaults
+ to installing gems in `.bundle`.
+* `deployment` (`BUNDLE_DEPLOYMENT`):
+ Disallow changes to the `Gemfile`. When the `Gemfile` is changed and the
+ lockfile has not been updated, running Bundler commands will be blocked.
+* `disable_checksum_validation` (`BUNDLE_DISABLE_CHECKSUM_VALIDATION`):
+ Allow installing gems even if they do not match the checksum provided by
+ RubyGems.
+* `disable_exec_load` (`BUNDLE_DISABLE_EXEC_LOAD`):
+ Stop Bundler from using `load` to launch an executable in-process in
+ `bundle exec`.
+* `disable_local_branch_check` (`BUNDLE_DISABLE_LOCAL_BRANCH_CHECK`):
+ Allow Bundler to use a local git override without a branch specified in the
+ Gemfile.
+* `disable_local_revision_check` (`BUNDLE_DISABLE_LOCAL_REVISION_CHECK`):
+ Allow Bundler to use a local git override without checking if the revision
+ present in the lockfile is present in the repository.
+* `disable_shared_gems` (`BUNDLE_DISABLE_SHARED_GEMS`):
+ Stop Bundler from accessing gems installed to RubyGems' normal location.
+* `disable_version_check` (`BUNDLE_DISABLE_VERSION_CHECK`):
+ Stop Bundler from checking if a newer Bundler version is available on
+ rubygems.org.
+* `force_ruby_platform` (`BUNDLE_FORCE_RUBY_PLATFORM`):
+ Ignore the current machine's platform and install only `ruby` platform gems.
+ As a result, gems with native extensions will be compiled from source.
+* `frozen` (`BUNDLE_FROZEN`):
+ Disallow changes to the `Gemfile`. When the `Gemfile` is changed and the
+ lockfile has not been updated, running Bundler commands will be blocked.
+ Defaults to `true` when `--deployment` is used.
+* `gem.github_username` (`BUNDLE_GEM__GITHUB_USERNAME`):
+ Sets a GitHub username or organization to be used in `README` file when you
+ create a new gem via `bundle gem` command. It can be overridden by passing an
+ explicit `--github-username` flag to `bundle gem`.
+* `gem.push_key` (`BUNDLE_GEM__PUSH_KEY`):
+ Sets the `--key` parameter for `gem push` when using the `rake release`
+ command with a private gemstash server.
+* `gemfile` (`BUNDLE_GEMFILE`):
+ The name of the file that bundler should use as the `Gemfile`. This location
+ of this file also sets the root of the project, which is used to resolve
+ relative paths in the `Gemfile`, among other things. By default, bundler
+ will search up from the current working directory until it finds a
+ `Gemfile`.
+* `global_gem_cache` (`BUNDLE_GLOBAL_GEM_CACHE`):
+ Whether Bundler should cache all gems globally, rather than locally to the
+ installing Ruby installation.
+* `ignore_messages` (`BUNDLE_IGNORE_MESSAGES`):
+ When set, no post install messages will be printed. To silence a single gem,
+ use dot notation like `ignore_messages.httparty true`.
+* `init_gems_rb` (`BUNDLE_INIT_GEMS_RB`):
+ Generate a `gems.rb` instead of a `Gemfile` when running `bundle init`.
+* `jobs` (`BUNDLE_JOBS`):
+ The number of gems Bundler can install in parallel. Defaults to 1 on Windows,
+ and to the the number of processors on other platforms.
+* `no_install` (`BUNDLE_NO_INSTALL`):
+ Whether `bundle package` should skip installing gems.
+* `no_prune` (`BUNDLE_NO_PRUNE`):
+ Whether Bundler should leave outdated gems unpruned when caching.
+* `path` (`BUNDLE_PATH`):
+ The location on disk where all gems in your bundle will be located regardless
+ of `$GEM_HOME` or `$GEM_PATH` values. Bundle gems not found in this location
+ will be installed by `bundle install`. Defaults to `Gem.dir`. When --deployment
+ is used, defaults to vendor/bundle.
+* `path.system` (`BUNDLE_PATH__SYSTEM`):
+ Whether Bundler will install gems into the default system path (`Gem.dir`).
+* `path_relative_to_cwd` (`BUNDLE_PATH_RELATIVE_TO_CWD`)
+ Makes `--path` relative to the CWD instead of the `Gemfile`.
+* `plugins` (`BUNDLE_PLUGINS`):
+ Enable Bundler's experimental plugin system.
+* `prefer_patch` (BUNDLE_PREFER_PATCH):
+ Prefer updating only to next patch version during updates. Makes `bundle update` calls equivalent to `bundler update --patch`.
+* `print_only_version_number` (`BUNDLE_PRINT_ONLY_VERSION_NUMBER`):
+ Print only version number from `bundler --version`.
+* `redirect` (`BUNDLE_REDIRECT`):
+ The number of redirects allowed for network requests. Defaults to `5`.
+* `retry` (`BUNDLE_RETRY`):
+ The number of times to retry failed network requests. Defaults to `3`.
+* `setup_makes_kernel_gem_public` (`BUNDLE_SETUP_MAKES_KERNEL_GEM_PUBLIC`):
+ Have `Bundler.setup` make the `Kernel#gem` method public, even though
+ RubyGems declares it as private.
+* `shebang` (`BUNDLE_SHEBANG`):
+ The program name that should be invoked for generated binstubs. Defaults to
+ the ruby install name used to generate the binstub.
+* `silence_deprecations` (`BUNDLE_SILENCE_DEPRECATIONS`):
+ Whether Bundler should silence deprecation warnings for behavior that will
+ be changed in the next major version.
+* `silence_root_warning` (`BUNDLE_SILENCE_ROOT_WARNING`):
+ Silence the warning Bundler prints when installing gems as root.
+* `ssl_ca_cert` (`BUNDLE_SSL_CA_CERT`):
+ Path to a designated CA certificate file or folder containing multiple
+ certificates for trusted CAs in PEM format.
+* `ssl_client_cert` (`BUNDLE_SSL_CLIENT_CERT`):
+ Path to a designated file containing a X.509 client certificate
+ and key in PEM format.
+* `ssl_verify_mode` (`BUNDLE_SSL_VERIFY_MODE`):
+ The SSL verification mode Bundler uses when making HTTPS requests.
+ Defaults to verify peer.
+* `suppress_install_using_messages` (`BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES`):
+ Avoid printing `Using ...` messages during installation when the version of
+ a gem has not changed.
+* `system_bindir` (`BUNDLE_SYSTEM_BINDIR`):
+ The location where RubyGems installs binstubs. Defaults to `Gem.bindir`.
+* `timeout` (`BUNDLE_TIMEOUT`):
+ The seconds allowed before timing out for network requests. Defaults to `10`.
+* `update_requires_all_flag` (`BUNDLE_UPDATE_REQUIRES_ALL_FLAG`):
+ Require passing `--all` to `bundle update` when everything should be updated,
+ and disallow passing no options to `bundle update`.
+* `user_agent` (`BUNDLE_USER_AGENT`):
+ The custom user agent fragment Bundler includes in API requests.
+* `with` (`BUNDLE_WITH`):
+ A `:`-separated list of groups whose gems bundler should install.
+* `without` (`BUNDLE_WITHOUT`):
+ A `:`-separated list of groups whose gems bundler should not install.
+
+In general, you should set these settings per-application by using the applicable
+flag to the [bundle install(1)](bundle-install.1.html) or [bundle package(1)](bundle-package.1.html) command.
+
+You can set them globally either via environment variables or `bundle config`,
+whichever is preferable for your setup. If you use both, environment variables
+will take preference over global settings.
+
+## LOCAL GIT REPOS
+
+Bundler also allows you to work against a git repository locally
+instead of using the remote version. This can be achieved by setting
+up a local override:
+
+ bundle config set --local local.GEM_NAME /path/to/local/git/repository
+
+For example, in order to use a local Rack repository, a developer could call:
+
+ bundle config set --local local.rack ~/Work/git/rack
+
+Now instead of checking out the remote git repository, the local
+override will be used. Similar to a path source, every time the local
+git repository change, changes will be automatically picked up by
+Bundler. This means a commit in the local git repo will update the
+revision in the `Gemfile.lock` to the local git repo revision. This
+requires the same attention as git submodules. Before pushing to
+the remote, you need to ensure the local override was pushed, otherwise
+you may point to a commit that only exists in your local machine.
+You'll also need to CGI escape your usernames and passwords as well.
+
+Bundler does many checks to ensure a developer won't work with
+invalid references. Particularly, we force a developer to specify
+a branch in the `Gemfile` in order to use this feature. If the branch
+specified in the `Gemfile` and the current branch in the local git
+repository do not match, Bundler will abort. This ensures that
+a developer is always working against the correct branches, and prevents
+accidental locking to a different branch.
+
+Finally, Bundler also ensures that the current revision in the
+`Gemfile.lock` exists in the local git repository. By doing this, Bundler
+forces you to fetch the latest changes in the remotes.
+
+## MIRRORS OF GEM SOURCES
+
+Bundler supports overriding gem sources with mirrors. This allows you to
+configure rubygems.org as the gem source in your Gemfile while still using your
+mirror to fetch gems.
+
+ bundle config set --global mirror.SOURCE_URL MIRROR_URL
+
+For example, to use a mirror of rubygems.org hosted at rubygems-mirror.org:
+
+ bundle config set --global mirror.http://rubygems.org http://rubygems-mirror.org
+
+Each mirror also provides a fallback timeout setting. If the mirror does not
+respond within the fallback timeout, Bundler will try to use the original
+server instead of the mirror.
+
+ bundle config set --global mirror.SOURCE_URL.fallback_timeout TIMEOUT
+
+For example, to fall back to rubygems.org after 3 seconds:
+
+ bundle config set --global mirror.https://rubygems.org.fallback_timeout 3
+
+The default fallback timeout is 0.1 seconds, but the setting can currently
+only accept whole seconds (for example, 1, 15, or 30).
+
+## CREDENTIALS FOR GEM SOURCES
+
+Bundler allows you to configure credentials for any gem source, which allows
+you to avoid putting secrets into your Gemfile.
+
+ bundle config set --global SOURCE_HOSTNAME USERNAME:PASSWORD
+
+For example, to save the credentials of user `claudette` for the gem source at
+`gems.longerous.com`, you would run:
+
+ bundle config set --global gems.longerous.com claudette:s00pers3krit
+
+Or you can set the credentials as an environment variable like this:
+
+ export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit"
+
+For gems with a git source with HTTP(S) URL you can specify credentials like so:
+
+ bundle config set --global https://github.com/rubygems/rubygems.git username:password
+
+Or you can set the credentials as an environment variable like so:
+
+ export BUNDLE_GITHUB__COM=username:password
+
+This is especially useful for private repositories on hosts such as Github,
+where you can use personal OAuth tokens:
+
+ export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x-oauth-basic
+
+Note that any configured credentials will be redacted by informative commands
+such as `bundle config list` or `bundle config get`, unless you use the
+`--parseable` flag. This is to avoid unintentionally leaking credentials when
+copy-pasting bundler output.
+
+Also note that to guarantee a sane mapping between valid environment variable
+names and valid host names, bundler makes the following transformations:
+
+* Any `-` characters in a host name are mapped to a triple dash (`___`) in the
+ corresponding environment variable.
+
+* Any `.` characters in a host name are mapped to a double dash (`__`) in the
+ corresponding environment variable.
+
+This means that if you have a gem server named `my.gem-host.com`, you'll need to
+use the `BUNDLE_MY__GEM___HOST__COM` variable to configure credentials for it
+through ENV.
+
+## CONFIGURE BUNDLER DIRECTORIES
+
+Bundler's home, config, cache and plugin directories are able to be configured
+through environment variables. The default location for Bundler's home directory is
+`~/.bundle`, which all directories inherit from by default. The following
+outlines the available environment variables and their default values
+
+ BUNDLE_USER_HOME : $HOME/.bundle
+ BUNDLE_USER_CACHE : $BUNDLE_USER_HOME/cache
+ BUNDLE_USER_CONFIG : $BUNDLE_USER_HOME/config
+ BUNDLE_USER_PLUGIN : $BUNDLE_USER_HOME/plugin
diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1
new file mode 100644
index 0000000000..87a7fe5f2f
--- /dev/null
+++ b/lib/bundler/man/bundle-doctor.1
@@ -0,0 +1,44 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-DOCTOR" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-doctor\fR \- Checks the bundle for common problems
+.
+.SH "SYNOPSIS"
+\fBbundle doctor\fR [\-\-quiet] [\-\-gemfile=GEMFILE]
+.
+.SH "DESCRIPTION"
+Checks your Gemfile and gem environment for common problems\. If issues are detected, Bundler prints them and exits status 1\. Otherwise, Bundler prints a success message and exits status 0\.
+.
+.P
+Examples of common problems caught by bundle\-doctor include:
+.
+.IP "\(bu" 4
+Invalid Bundler settings
+.
+.IP "\(bu" 4
+Mismatched Ruby versions
+.
+.IP "\(bu" 4
+Mismatched platforms
+.
+.IP "\(bu" 4
+Uninstalled gems
+.
+.IP "\(bu" 4
+Missing dependencies
+.
+.IP "" 0
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-quiet\fR
+Only output warnings and errors\.
+.
+.TP
+\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\.
+
diff --git a/man/bundle-doctor.ronn b/lib/bundler/man/bundle-doctor.1.ronn
index 271ee800ad..271ee800ad 100644
--- a/man/bundle-doctor.ronn
+++ b/lib/bundler/man/bundle-doctor.1.ronn
diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1
new file mode 100644
index 0000000000..69adfa7c92
--- /dev/null
+++ b/lib/bundler/man/bundle-exec.1
@@ -0,0 +1,165 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-EXEC" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-exec\fR \- Execute a command in the context of the bundle
+.
+.SH "SYNOPSIS"
+\fBbundle exec\fR [\-\-keep\-file\-descriptors] \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
+Essentially, if you would normally have run something like \fBrspec spec/my_spec\.rb\fR, and you want to use the gems specified in the [\fBGemfile(5)\fR][Gemfile(5)] and installed via bundle install(1) \fIbundle\-install\.1\.html\fR, you should run \fBbundle exec rspec spec/my_spec\.rb\fR\.
+.
+.P
+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
+Exec in Ruby 2\.0 began discarding non\-standard file descriptors\. When this flag is passed, exec will revert to the 1\.9 behaviour of passing all file descriptors to the new process\.
+.
+.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
+After using \fB\-\-binstubs\fR, \fBbin/rspec spec/my_spec\.rb\fR is identical to \fBbundle exec rspec spec/my_spec\.rb\fR\.
+.
+.SH "ENVIRONMENT MODIFICATIONS"
+\fBbundle exec\fR makes a number of changes to the shell environment, then executes the command you specify in full\.
+.
+.IP "\(bu" 4
+make sure that it\'s still possible to shell out to \fBbundle\fR from inside a command invoked by \fBbundle exec\fR (using \fB$BUNDLE_BIN_PATH\fR)
+.
+.IP "\(bu" 4
+put the directory containing executables (like \fBrails\fR, \fBrspec\fR, \fBrackup\fR) for your bundle on \fB$PATH\fR
+.
+.IP "\(bu" 4
+make sure that if bundler is invoked in the subshell, it uses the same \fBGemfile\fR (by setting \fBBUNDLE_GEMFILE\fR)
+.
+.IP "\(bu" 4
+add \fB\-rbundler/setup\fR to \fB$RUBYOPT\fR, which makes sure that Ruby programs invoked in the subshell can see the gems in the bundle
+.
+.IP "" 0
+.
+.P
+It also modifies Rubygems:
+.
+.IP "\(bu" 4
+disallow loading additional gems not in the bundle
+.
+.IP "\(bu" 4
+modify the \fBgem\fR method to be a no\-op if a gem matching the requirements is in the bundle, and to raise a \fBGem::LoadError\fR if it\'s not
+.
+.IP "\(bu" 4
+Define \fBGem\.refresh\fR to be a no\-op, since the source index is always frozen when using bundler, and to prevent gems from the system leaking into the environment
+.
+.IP "\(bu" 4
+Override \fBGem\.bin_path\fR to use the gems in the bundle, making system executables work
+.
+.IP "\(bu" 4
+Add all gems in the bundle into Gem\.loaded_specs
+.
+.IP "" 0
+.
+.P
+Finally, \fBbundle exec\fR also implicitly modifies \fBGemfile\.lock\fR if the lockfile and the Gemfile do not match\. Bundler needs the Gemfile to determine things such as a gem\'s groups, \fBautorequire\fR, and platforms, etc\., and that information isn\'t stored in the lockfile\. The Gemfile and lockfile must be synced in order to \fBbundle exec\fR successfully, so \fBbundle exec\fR updates the lockfile beforehand\.
+.
+.SS "Loading"
+By default, when attempting to \fBbundle exec\fR to a file with a ruby shebang, Bundler will \fBKernel\.load\fR that file instead of using \fBKernel\.exec\fR\. For the vast majority of cases, this is a performance improvement\. In a rare few cases, this could cause some subtle side\-effects (such as dependence on the exact contents of \fB$0\fR or \fB__FILE__\fR) and the optimization can be disabled by enabling the \fBdisable_exec_load\fR setting\.
+.
+.SS "Shelling out"
+Any Ruby code that opens a subshell (like \fBsystem\fR, backticks, or \fB%x{}\fR) will automatically use the current Bundler environment\. If you need to shell out to a Ruby command that is not part of your current bundle, use the \fBwith_clean_env\fR method with a block\. Any subshells created inside the block will be given the environment present before Bundler was activated\. For example, Homebrew commands run Ruby, but don\'t work inside a bundle:
+.
+.IP "" 4
+.
+.nf
+
+Bundler\.with_clean_env do
+ `brew install wget`
+end
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Using \fBwith_clean_env\fR is also necessary if you are shelling out to a different bundle\. Any Bundler commands run in a subshell will inherit the current Gemfile, so commands that need to run in the context of a different bundle also need to use \fBwith_clean_env\fR\.
+.
+.IP "" 4
+.
+.nf
+
+Bundler\.with_clean_env do
+ Dir\.chdir "/other/bundler/project" do
+ `bundle exec \./script`
+ end
+end
+.
+.fi
+.
+.IP "" 0
+.
+.P
+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\')
+.
+.fi
+.
+.IP "" 0
+.
+.SH "RUBYGEMS PLUGINS"
+At present, the Rubygems plugin system requires all files named \fBrubygems_plugin\.rb\fR on the load path of \fIany\fR installed gem when any Ruby code requires \fBrubygems\.rb\fR\. This includes executables installed into the system, like \fBrails\fR, \fBrackup\fR, and \fBrspec\fR\.
+.
+.P
+Since Rubygems plugins can contain arbitrary Ruby code, they commonly end up activating themselves or their dependencies\.
+.
+.P
+For instance, the \fBgemcutter 0\.5\fR gem depended on \fBjson_pure\fR\. If you had that version of gemcutter installed (even if you \fIalso\fR had a newer version without this problem), Rubygems would activate \fBgemcutter 0\.5\fR and \fBjson_pure <latest>\fR\.
+.
+.P
+If your Gemfile(5) also contained \fBjson_pure\fR (or a gem with a dependency on \fBjson_pure\fR), the latest version on your system might conflict with the version in your Gemfile(5), or the snapshot version in your \fBGemfile\.lock\fR\.
+.
+.P
+If this happens, bundler will say:
+.
+.IP "" 4
+.
+.nf
+
+You have already activated json_pure 1\.4\.6 but your Gemfile
+requires json_pure 1\.4\.3\. Consider using bundle exec\.
+.
+.fi
+.
+.IP "" 0
+.
+.P
+In this situation, you almost certainly want to remove the underlying gem with the problematic gem plugin\. In general, the authors of these plugins (in this case, the \fBgemcutter\fR gem) have released newer versions that are more careful in their plugins\.
+.
+.P
+You can find a list of all the gems containing gem plugins by running
+.
+.IP "" 4
+.
+.nf
+
+ruby \-rrubygems \-e "puts Gem\.find_files(\'rubygems_plugin\.rb\')"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+At the very least, you should remove all but the newest version of each gem plugin, and also remove all gem plugins that you aren\'t using (\fBgem uninstall gem_name\fR)\.
diff --git a/man/bundle-exec.ronn b/lib/bundler/man/bundle-exec.1.ronn
index dec3c7cb82..dec3c7cb82 100644
--- a/man/bundle-exec.ronn
+++ b/lib/bundler/man/bundle-exec.1.ronn
diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1
new file mode 100644
index 0000000000..fae5c34e7e
--- /dev/null
+++ b/lib/bundler/man/bundle-gem.1
@@ -0,0 +1,115 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-GEM" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
+.
+.SH "SYNOPSIS"
+\fBbundle gem\fR \fIGEM_NAME\fR \fIOPTIONS\fR
+.
+.SH "DESCRIPTION"
+Generates a directory named \fBGEM_NAME\fR with a \fBRakefile\fR, \fBGEM_NAME\.gemspec\fR, and other supporting files and directories that can be used to develop a rubygem with that name\.
+.
+.P
+Run \fBrake \-T\fR in the resulting project for a list of Rake tasks that can be used to test and publish the gem to rubygems\.org\.
+.
+.P
+The generated project skeleton can be customized with OPTIONS, as explained below\. Note that these options can also be specified via Bundler\'s global configuration file using the following names:
+.
+.IP "\(bu" 4
+\fBgem\.coc\fR
+.
+.IP "\(bu" 4
+\fBgem\.mit\fR
+.
+.IP "\(bu" 4
+\fBgem\.test\fR
+.
+.IP "" 0
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-exe\fR or \fB\-b\fR or \fB\-\-bin\fR
+Specify that Bundler should create a binary executable (as \fBexe/GEM_NAME\fR) in the generated rubygem project\. This binary will also be added to the \fBGEM_NAME\.gemspec\fR manifest\. This behavior is disabled by default\.
+.
+.TP
+\fB\-\-no\-exe\fR
+Do not create a binary (overrides \fB\-\-exe\fR specified in the global config)\.
+.
+.TP
+\fB\-\-coc\fR
+Add a \fBCODE_OF_CONDUCT\.md\fR file to the root of the generated project\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
+.
+.TP
+\fB\-\-no\-coc\fR
+Do not create a \fBCODE_OF_CONDUCT\.md\fR (overrides \fB\-\-coc\fR specified in the global config)\.
+.
+.TP
+\fB\-\-ext\fR
+Add boilerplate for C extension code to the generated project\. This behavior is disabled by default\.
+.
+.TP
+\fB\-\-no\-ext\fR
+Do not add C extension code (overrides \fB\-\-ext\fR specified in the global config)\.
+.
+.TP
+\fB\-\-mit\fR
+Add an MIT license to a \fBLICENSE\.txt\fR file in the root of the generated project\. Your name from the global git config is used for the copyright statement\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
+.
+.TP
+\fB\-\-no\-mit\fR
+Do not create a \fBLICENSE\.txt\fR (overrides \fB\-\-mit\fR specified in the global config)\.
+.
+.TP
+\fB\-t\fR, \fB\-\-test=minitest\fR, \fB\-\-test=rspec\fR, \fB\-\-test=test\-unit\fR
+Specify the test framework that Bundler should use when generating the project\. Acceptable values are \fBminitest\fR, \fBrspec\fR and \fBtest\-unit\fR\. The \fBGEM_NAME\.gemspec\fR will be configured and a skeleton test/spec directory will be created based on this option\. Given no option is specified:
+.
+.IP
+When Bundler is configured to generate tests, this defaults to Bundler\'s global config setting \fBgem\.test\fR\.
+.
+.IP
+When Bundler is configured to not generate tests, an interactive prompt will be displayed and the answer will be used for the current rubygem project\.
+.
+.IP
+When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
+.
+.TP
+\fB\-\-ci\fR, \fB\-\-ci=github\fR, \fB\-\-ci=travis\fR, \fB\-\-ci=gitlab\fR, \fB\-\-ci=circle\fR
+Specify the continuous integration service that Bundler should use when generating the project\. Acceptable values are \fBgithub\fR, \fBtravis\fR, \fBgitlab\fR and \fBcircle\fR\. A configuration file will be generated in the project directory\. Given no option is specified:
+.
+.IP
+When Bundler is configured to generate CI files, this defaults to Bundler\'s global config setting \fBgem\.ci\fR\.
+.
+.IP
+When Bundler is configured to not generate CI files, an interactive prompt will be displayed and the answer will be used for the current rubygem project\.
+.
+.IP
+When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
+.
+.TP
+\fB\-\-linter\fR, \fB\-\-linter=rubocop\fR, \fB\-\-linter=standard\fR
+Specify the linter and code formatter that Bundler should add to the project\'s development dependencies\. Acceptable values are \fBrubocop\fR and \fBstandard\fR\. A configuration file will be generated in the project directory\. Given no option is specified:
+.
+.IP
+When Bundler is configured to add a linter, this defaults to Bundler\'s global config setting \fBgem\.linter\fR\.
+.
+.IP
+When Bundler is configured not to add a linter, an interactive prompt will be displayed and the answer will be used for the current rubygem project\.
+.
+.IP
+When Bundler is unconfigured, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
+.
+.TP
+\fB\-e\fR, \fB\-\-edit[=EDITOR]\fR
+Open the resulting GEM_NAME\.gemspec in EDITOR, or the default editor if not specified\. The default is \fB$BUNDLER_EDITOR\fR, \fB$VISUAL\fR, or \fB$EDITOR\fR\.
+.
+.SH "SEE ALSO"
+.
+.IP "\(bu" 4
+bundle config(1) \fIbundle\-config\.1\.html\fR
+.
+.IP "" 0
+
diff --git a/lib/bundler/man/bundle-gem.1.ronn b/lib/bundler/man/bundle-gem.1.ronn
new file mode 100644
index 0000000000..61c741fb24
--- /dev/null
+++ b/lib/bundler/man/bundle-gem.1.ronn
@@ -0,0 +1,117 @@
+bundle-gem(1) -- Generate a project skeleton for creating a rubygem
+====================================================================
+
+## SYNOPSIS
+
+`bundle gem` <GEM_NAME> [OPTIONS]
+
+## DESCRIPTION
+
+Generates a directory named `GEM_NAME` with a `Rakefile`, `GEM_NAME.gemspec`,
+and other supporting files and directories that can be used to develop a
+rubygem with that name.
+
+Run `rake -T` in the resulting project for a list of Rake tasks that can be used
+to test and publish the gem to rubygems.org.
+
+The generated project skeleton can be customized with OPTIONS, as explained
+below. Note that these options can also be specified via Bundler's global
+configuration file using the following names:
+
+* `gem.coc`
+* `gem.mit`
+* `gem.test`
+
+## OPTIONS
+
+* `--exe` or `-b` or `--bin`:
+ Specify that Bundler should create a binary executable (as `exe/GEM_NAME`)
+ in the generated rubygem project. This binary will also be added to the
+ `GEM_NAME.gemspec` manifest. This behavior is disabled by default.
+
+* `--no-exe`:
+ Do not create a binary (overrides `--exe` specified in the global config).
+
+* `--coc`:
+ Add a `CODE_OF_CONDUCT.md` file to the root of the generated project. If
+ this option is unspecified, an interactive prompt will be displayed and the
+ answer will be saved in Bundler's global config for future `bundle gem` use.
+
+* `--no-coc`:
+ Do not create a `CODE_OF_CONDUCT.md` (overrides `--coc` specified in the
+ global config).
+
+* `--ext`:
+ Add boilerplate for C extension code to the generated project. This behavior
+ is disabled by default.
+
+* `--no-ext`:
+ Do not add C extension code (overrides `--ext` specified in the global
+ config).
+
+* `--mit`:
+ Add an MIT license to a `LICENSE.txt` file in the root of the generated
+ project. Your name from the global git config is used for the copyright
+ statement. If this option is unspecified, an interactive prompt will be
+ displayed and the answer will be saved in Bundler's global config for future
+ `bundle gem` use.
+
+* `--no-mit`:
+ Do not create a `LICENSE.txt` (overrides `--mit` specified in the global
+ config).
+
+* `-t`, `--test=minitest`, `--test=rspec`, `--test=test-unit`:
+ Specify the test framework that Bundler should use when generating the
+ project. Acceptable values are `minitest`, `rspec` and `test-unit`. The
+ `GEM_NAME.gemspec` will be configured and a skeleton test/spec directory will
+ be created based on this option. Given no option is specified:
+
+ When Bundler is configured to generate tests, this defaults to Bundler's
+ global config setting `gem.test`.
+
+ When Bundler is configured to not generate tests, an interactive prompt will
+ be displayed and the answer will be used for the current rubygem project.
+
+ When Bundler is unconfigured, an interactive prompt will be displayed and
+ the answer will be saved in Bundler's global config for future `bundle gem`
+ use.
+
+* `--ci`, `--ci=github`, `--ci=travis`, `--ci=gitlab`, `--ci=circle`:
+ Specify the continuous integration service that Bundler should use when
+ generating the project. Acceptable values are `github`, `travis`, `gitlab`
+ and `circle`. A configuration file will be generated in the project directory.
+ Given no option is specified:
+
+ When Bundler is configured to generate CI files, this defaults to Bundler's
+ global config setting `gem.ci`.
+
+ When Bundler is configured to not generate CI files, an interactive prompt
+ will be displayed and the answer will be used for the current rubygem project.
+
+ When Bundler is unconfigured, an interactive prompt will be displayed and
+ the answer will be saved in Bundler's global config for future `bundle gem`
+ use.
+
+* `--linter`, `--linter=rubocop`, `--linter=standard`:
+ Specify the linter and code formatter that Bundler should add to the
+ project's development dependencies. Acceptable values are `rubocop` and
+ `standard`. A configuration file will be generated in the project directory.
+ Given no option is specified:
+
+ When Bundler is configured to add a linter, this defaults to Bundler's
+ global config setting `gem.linter`.
+
+ When Bundler is configured not to add a linter, an interactive prompt
+ will be displayed and the answer will be used for the current rubygem project.
+
+ When Bundler is unconfigured, an interactive prompt will be displayed and
+ the answer will be saved in Bundler's global config for future `bundle gem`
+ use.
+
+* `-e`, `--edit[=EDITOR]`:
+ Open the resulting GEM_NAME.gemspec in EDITOR, or the default editor if not
+ specified. The default is `$BUNDLER_EDITOR`, `$VISUAL`, or `$EDITOR`.
+
+## SEE ALSO
+
+* [bundle config(1)](bundle-config.1.html)
diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1
new file mode 100644
index 0000000000..9e1400ec56
--- /dev/null
+++ b/lib/bundler/man/bundle-info.1
@@ -0,0 +1,20 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-INFO" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-info\fR \- Show information for the given gem in your bundle
+.
+.SH "SYNOPSIS"
+\fBbundle info\fR [GEM] [\-\-path]
+.
+.SH "DESCRIPTION"
+Print the basic information about the provided GEM such as homepage, version, path and summary\.
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-path\fR
+Print the path of the given gem
+
diff --git a/man/bundle-info.ronn b/lib/bundler/man/bundle-info.1.ronn
index 47e457aa3c..47e457aa3c 100644
--- a/man/bundle-info.ronn
+++ b/lib/bundler/man/bundle-info.1.ronn
diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1
new file mode 100644
index 0000000000..612d16031c
--- /dev/null
+++ b/lib/bundler/man/bundle-init.1
@@ -0,0 +1,25 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-INIT" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
+.
+.SH "SYNOPSIS"
+\fBbundle init\fR [\-\-gemspec=FILE]
+.
+.SH "DESCRIPTION"
+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
+Use the specified \.gemspec to create the [\fBGemfile(5)\fR][Gemfile(5)]
+.
+.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\.
+.
+.SH "SEE ALSO"
+Gemfile(5) \fIhttps://bundler\.io/man/gemfile\.5\.html\fR
diff --git a/man/bundle-init.ronn b/lib/bundler/man/bundle-init.1.ronn
index 9d3d97deea..9d3d97deea 100644
--- a/man/bundle-init.ronn
+++ b/lib/bundler/man/bundle-init.1.ronn
diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1
new file mode 100644
index 0000000000..ded4d6d64b
--- /dev/null
+++ b/lib/bundler/man/bundle-inject.1
@@ -0,0 +1,33 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-INJECT" "1" "December 2021" "" ""
+.
+.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
diff --git a/man/bundle-inject.ronn b/lib/bundler/man/bundle-inject.1.ronn
index f454341896..f454341896 100644
--- a/man/bundle-inject.ronn
+++ b/lib/bundler/man/bundle-inject.1.ronn
diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1
new file mode 100644
index 0000000000..6ccf100b4e
--- /dev/null
+++ b/lib/bundler/man/bundle-install.1
@@ -0,0 +1,338 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-INSTALL" "1" "December 2021" "" ""
+.
+.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] [\-\-quiet] [\-\-redownload] [\-\-retry=NUMBER] [\-\-shebang] [\-\-standalone[=GROUP[ GROUP\.\.\.]]] [\-\-system] [\-\-trust\-policy=POLICY] [\-\-with=GROUP[ GROUP\.\.\.]] [\-\-without=GROUP[ GROUP\.\.\.]]
+.
+.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
+If a \fBGemfile\.lock\fR does exist, and you have not updated your Gemfile(5), Bundler will fetch all remote sources, but use the dependencies specified in the \fBGemfile\.lock\fR instead of resolving dependencies\.
+.
+.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\.
+.
+.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
+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
+The maximum number of parallel download and install jobs\. The default is \fB1\fR\.
+.
+.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\-\-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\.
+.
+.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\.
+.
+.TP
+\fB\-\-quiet\fR
+Do not print progress information to the standard output\. Instead, Bundler will exit using a status code (\fB$?\fR)\.
+.
+.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]\.
+.
+.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
+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\.
+.
+.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\.
+.
+.IP "1." 4
+A \fBGemfile\.lock\fR is required\.
+.
+.IP
+To ensure that the same versions of the gems you developed with and tested with are also used in deployments, a \fBGemfile\.lock\fR is required\.
+.
+.IP
+This is mainly to ensure that you remember to check your \fBGemfile\.lock\fR into version control\.
+.
+.IP "2." 4
+The \fBGemfile\.lock\fR must be up to date
+.
+.IP
+In development, you can modify your Gemfile(5) and re\-run \fBbundle install\fR to \fIconservatively update\fR your \fBGemfile\.lock\fR snapshot\.
+.
+.IP
+In deployment, your \fBGemfile\.lock\fR should be up\-to\-date with changes made in your Gemfile(5)\.
+.
+.IP "3." 4
+Gems are installed to \fBvendor/bundle\fR not your default system location
+.
+.IP
+In development, it\'s convenient to share the gems used in your application with other applications and other scripts that run on the system\.
+.
+.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\.
+.
+.IP "" 0
+.
+.SH "SUDO USAGE"
+By default, Bundler installs gems to the same location as \fBgem install\fR\.
+.
+.P
+In some cases, that location may not be writable by your Unix user\. In that case, Bundler will stage everything in a temporary directory, then ask you for your \fBsudo\fR password in order to copy the gems into their system location\.
+.
+.P
+From your perspective, this is identical to installing the gems directly into the system\.
+.
+.P
+You should never use \fBsudo bundle install\fR\. This is because several other steps in \fBbundle install\fR must be performed as the current user:
+.
+.IP "\(bu" 4
+Updating your \fBGemfile\.lock\fR
+.
+.IP "\(bu" 4
+Updating your \fBvendor/cache\fR, if necessary
+.
+.IP "\(bu" 4
+Checking out private git repositories using your user\'s SSH keys
+.
+.IP "" 0
+.
+.P
+Of these three, the first two could theoretically be performed by \fBchown\fRing the resulting files to \fB$SUDO_USER\fR\. The third, however, can only be performed by invoking the \fBgit\fR command as the current user\. Therefore, git gems are downloaded and installed into \fB~/\.bundle\fR rather than $GEM_HOME or $BUNDLE_PATH\.
+.
+.P
+As a result, you should run \fBbundle install\fR as the current user, and Bundler will ask for your password if it is needed to put the gems into their final location\.
+.
+.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\.
+.
+.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)\.
+.
+.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
+\fBBundler offers a rock\-solid guarantee that the third\-party code you are running in development and testing is also the third\-party code you are running in production\. You can choose to exclude some of that code in different environments, but you will never be caught flat\-footed by different versions of third\-party code being used in different environments\.\fR
+.
+.P
+For a simple illustration, consider the following Gemfile(5):
+.
+.IP "" 4
+.
+.nf
+
+source \'https://rubygems\.org\'
+
+gem \'sinatra\'
+
+group :production do
+ gem \'rack\-perftools\-profiler\'
+end
+.
+.fi
+.
+.IP "" 0
+.
+.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\.
+.
+.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
+This also means that you cannot include different versions of the same gem in different groups, because doing so would result in different sets of dependencies used in development and production\. Because of the vagaries of the dependency resolution process, this usually affects more than the gems you list in your Gemfile(5), and can (surprisingly) radically change the gems you are using\.
+.
+.SH "THE GEMFILE\.LOCK"
+When you run \fBbundle install\fR, Bundler will persist the full names and versions of all gems that you used (including dependencies of the gems specified in the Gemfile(5)) into a file called \fBGemfile\.lock\fR\.
+.
+.P
+Bundler uses this file in all subsequent calls to \fBbundle install\fR, which guarantees that you always use the same exact code, even as your application moves across machines\.
+.
+.P
+Because of the way dependency resolution works, even a seemingly small change (for instance, an update to a point\-release of a dependency of a gem in your Gemfile(5)) can result in radically different gems being needed to satisfy all dependencies\.
+.
+.P
+As a result, you \fBSHOULD\fR check your \fBGemfile\.lock\fR into version control, in both applications and gems\. If you do not, every machine that checks out your repository (including your production server) will resolve all dependencies again, which will result in different versions of third\-party code being used if \fBany\fR of the gems in the Gemfile(5) or any of their dependencies have been updated\.
+.
+.P
+When Bundler first shipped, the \fBGemfile\.lock\fR was included in the \fB\.gitignore\fR file included with generated gems\. Over time, however, it became clear that this practice forces the pain of broken dependencies onto new contributors, while leaving existing contributors potentially unaware of the problem\. Since \fBbundle install\fR is usually the first step towards a contribution, the pain of broken dependencies would discourage new contributors from contributing\. As a result, we have revised our guidance for gem authors to now recommend checking in the lock for gems\.
+.
+.SH "CONSERVATIVE UPDATING"
+When you make a change to the Gemfile(5) and then run \fBbundle install\fR, Bundler will update only the gems that you modified\.
+.
+.P
+In other words, if a gem that you \fBdid not modify\fR worked before you called \fBbundle install\fR, it will continue to use the exact same versions of all dependencies as it used before the update\.
+.
+.P
+Let\'s take a look at an example\. Here\'s your original Gemfile(5):
+.
+.IP "" 4
+.
+.nf
+
+source \'https://rubygems\.org\'
+
+gem \'actionpack\', \'2\.3\.8\'
+gem \'activemerchant\'
+.
+.fi
+.
+.IP "" 0
+.
+.P
+In this case, both \fBactionpack\fR and \fBactivemerchant\fR depend on \fBactivesupport\fR\. The \fBactionpack\fR gem depends on \fBactivesupport 2\.3\.8\fR and \fBrack ~> 1\.1\.0\fR, while the \fBactivemerchant\fR gem depends on \fBactivesupport >= 2\.3\.2\fR, \fBbraintree >= 2\.0\.0\fR, and \fBbuilder >= 2\.0\.0\fR\.
+.
+.P
+When the dependencies are first resolved, Bundler will select \fBactivesupport 2\.3\.8\fR, which satisfies the requirements of both gems in your Gemfile(5)\.
+.
+.P
+Next, you modify your Gemfile(5) to:
+.
+.IP "" 4
+.
+.nf
+
+source \'https://rubygems\.org\'
+
+gem \'actionpack\', \'3\.0\.0\.rc\'
+gem \'activemerchant\'
+.
+.fi
+.
+.IP "" 0
+.
+.P
+The \fBactionpack 3\.0\.0\.rc\fR gem has a number of new dependencies, and updates the \fBactivesupport\fR dependency to \fB= 3\.0\.0\.rc\fR and the \fBrack\fR dependency to \fB~> 1\.2\.1\fR\.
+.
+.P
+When you run \fBbundle install\fR, Bundler notices that you changed the \fBactionpack\fR gem, but not the \fBactivemerchant\fR gem\. It evaluates the gems currently being used to satisfy its requirements:
+.
+.TP
+\fBactivesupport 2\.3\.8\fR
+also used to satisfy a dependency in \fBactivemerchant\fR, which is not being updated
+.
+.TP
+\fBrack ~> 1\.1\.0\fR
+not currently being used to satisfy another dependency
+.
+.P
+Because you did not explicitly ask to update \fBactivemerchant\fR, you would not expect it to suddenly stop working after updating \fBactionpack\fR\. However, satisfying the new \fBactivesupport 3\.0\.0\.rc\fR dependency of actionpack requires updating one of its dependencies\.
+.
+.P
+Even though \fBactivemerchant\fR declares a very loose dependency that theoretically matches \fBactivesupport 3\.0\.0\.rc\fR, Bundler treats gems in your Gemfile(5) that have not changed as an atomic unit together with their dependencies\. In this case, the \fBactivemerchant\fR dependency is treated as \fBactivemerchant 1\.7\.1 + activesupport 2\.3\.8\fR, so \fBbundle install\fR will report that it cannot update \fBactionpack\fR\.
+.
+.P
+To explicitly update \fBactionpack\fR, including its dependencies which other gems in the Gemfile(5) still depend on, run \fBbundle update actionpack\fR (see \fBbundle update(1)\fR)\.
+.
+.P
+\fBSummary\fR: In general, after making a change to the Gemfile(5) , you should first try to run \fBbundle install\fR, which will guarantee that no other gem in the Gemfile(5) is impacted by the change\. If that does not work, run bundle update(1) \fIbundle\-update\.1\.html\fR\.
+.
+.SH "SEE ALSO"
+.
+.IP "\(bu" 4
+Gem install docs \fIhttp://guides\.rubygems\.org/rubygems\-basics/#installing\-gems\fR
+.
+.IP "\(bu" 4
+Rubygems signing docs \fIhttp://guides\.rubygems\.org/security/\fR
+.
+.IP "" 0
+
diff --git a/lib/bundler/man/bundle-install.1.ronn b/lib/bundler/man/bundle-install.1.ronn
new file mode 100644
index 0000000000..5ea777f1d4
--- /dev/null
+++ b/lib/bundler/man/bundle-install.1.ronn
@@ -0,0 +1,405 @@
+bundle-install(1) -- Install the dependencies specified in your Gemfile
+=======================================================================
+
+## SYNOPSIS
+
+`bundle install` [--binstubs[=DIRECTORY]]
+ [--clean]
+ [--deployment]
+ [--frozen]
+ [--full-index]
+ [--gemfile=GEMFILE]
+ [--jobs=NUMBER]
+ [--local]
+ [--no-cache]
+ [--no-prune]
+ [--path PATH]
+ [--quiet]
+ [--redownload]
+ [--retry=NUMBER]
+ [--shebang]
+ [--standalone[=GROUP[ GROUP...]]]
+ [--system]
+ [--trust-policy=POLICY]
+ [--with=GROUP[ GROUP...]]
+ [--without=GROUP[ GROUP...]]
+
+## DESCRIPTION
+
+Install the gems specified in your Gemfile(5). If this is the first
+time you run bundle install (and a `Gemfile.lock` does not exist),
+Bundler will fetch all remote sources, resolve dependencies and
+install all needed gems.
+
+If a `Gemfile.lock` does exist, and you have not updated your Gemfile(5),
+Bundler will fetch all remote sources, but use the dependencies
+specified in the `Gemfile.lock` instead of resolving dependencies.
+
+If a `Gemfile.lock` does exist, and you have updated your Gemfile(5),
+Bundler will use the dependencies in the `Gemfile.lock` for all gems
+that you did not update, but will re-resolve the dependencies of
+gems that you did update. You can find more information about this
+update process below under [CONSERVATIVE UPDATING][].
+
+## OPTIONS
+
+The `--clean`, `--deployment`, `--frozen`, `--no-prune`, `--path`, `--shebang`,
+`--system`, `--without` and `--with` options are deprecated because they only
+make sense if they are applied to every subsequent `bundle install` run
+automatically and that requires `bundler` to silently remember them. Since
+`bundler` will no longer remember CLI flags in future versions, `bundle config`
+(see bundle-config(1)) should be used to apply them permanently.
+
+* `--binstubs[=<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.
+
+* `--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>`:
+ 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>]`:
+ The maximum number of parallel download and install jobs. The default
+ is `1`.
+
+* `--local`:
+ Do not attempt to connect to `rubygems.org`. Instead, Bundler will use the
+ gems already present in Rubygems' cache or in `vendor/cache`. Note that if an
+ appropriate platform-specific gem exists on `rubygems.org` it will not be
+ found.
+
+* `--no-cache`:
+ Do not update the cache in `vendor/cache` with the newly bundled gems. This
+ does not remove any gems in the cache but keeps the newly bundled gems from
+ being cached during the install.
+
+* `--no-prune`:
+ Don't remove stale gems from the cache when the installation finishes.
+
+ This option is deprecated in favor of the `no_prune` setting.
+
+* `--path=<path>`:
+ The location to install the specified gems to. This defaults to Rubygems'
+ setting. Bundler shares this location with Rubygems, `gem install ...` will
+ have gem installed there, too. Therefore, gems installed without a
+ `--path ...` setting will show up by calling `gem list`. Accordingly, gems
+ installed to other locations will not get listed.
+
+ This option is deprecated in favor of the `path` setting.
+
+* `--quiet`:
+ Do not print progress information to the standard output. Instead, Bundler
+ will exit using a status code (`$?`).
+
+* `--retry=[<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.
+ Bundler creates a directory named `bundle` and installs the bundle there. It
+ also generates a `bundle/bundler/setup.rb` file to replace Bundler's own setup
+ in the manner required. Using this option implicitly sets `path`, which is a
+ [remembered option][REMEMBERED OPTIONS].
+
+* `--system`:
+ Installs the gems specified in the bundle to the system's Rubygems location.
+ This overrides any previous configuration of `--path`.
+
+ This option is deprecated in favor of the `system` setting.
+
+* `--trust-policy=[<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.
+
+## DEPLOYMENT MODE
+
+Bundler's defaults are optimized for development. To switch to
+defaults optimized for deployment and for CI, use the `--deployment`
+flag. Do not activate deployment mode on development machines, as it
+will cause an error when the Gemfile(5) is modified.
+
+1. A `Gemfile.lock` is required.
+
+ To ensure that the same versions of the gems you developed with
+ and tested with are also used in deployments, a `Gemfile.lock`
+ is required.
+
+ This is mainly to ensure that you remember to check your
+ `Gemfile.lock` into version control.
+
+2. The `Gemfile.lock` must be up to date
+
+ In development, you can modify your Gemfile(5) and re-run
+ `bundle install` to [conservatively update][CONSERVATIVE UPDATING]
+ your `Gemfile.lock` snapshot.
+
+ In deployment, your `Gemfile.lock` should be up-to-date with
+ changes made in your Gemfile(5).
+
+3. Gems are installed to `vendor/bundle` not your default system location
+
+ In development, it's convenient to share the gems used in your
+ application with other applications and other scripts that run on
+ the system.
+
+ In deployment, isolation is a more important default. In addition,
+ the user deploying the application may not have permission to install
+ gems to the system, or the web server may not have permission to
+ read them.
+
+ As a result, `bundle install --deployment` installs gems to
+ the `vendor/bundle` directory in the application. This may be
+ overridden using the `--path` option.
+
+## SUDO USAGE
+
+By default, Bundler installs gems to the same location as `gem install`.
+
+In some cases, that location may not be writable by your Unix user. In
+that case, Bundler will stage everything in a temporary directory,
+then ask you for your `sudo` password in order to copy the gems into
+their system location.
+
+From your perspective, this is identical to installing the gems
+directly into the system.
+
+You should never use `sudo bundle install`. This is because several
+other steps in `bundle install` must be performed as the current user:
+
+* Updating your `Gemfile.lock`
+* Updating your `vendor/cache`, if necessary
+* Checking out private git repositories using your user's SSH keys
+
+Of these three, the first two could theoretically be performed by
+`chown`ing the resulting files to `$SUDO_USER`. The third, however,
+can only be performed by invoking the `git` command as
+the current user. Therefore, git gems are downloaded and installed
+into `~/.bundle` rather than $GEM_HOME or $BUNDLE_PATH.
+
+As a result, you should run `bundle install` as the current user,
+and Bundler will ask for your password if it is needed to put the
+gems into their final location.
+
+## INSTALLING GROUPS
+
+By default, `bundle install` will install all gems in all groups
+in your Gemfile(5), except those declared for a different platform.
+
+However, you can explicitly tell Bundler to skip installing
+certain groups with the `--without` option. This option takes
+a space-separated list of groups.
+
+While the `--without` option will skip _installing_ the gems in the
+specified groups, it will still _download_ those gems and use them to
+resolve the dependencies of every gem in your Gemfile(5).
+
+This is so that installing a different set of groups on another
+ machine (such as a production server) will not change the
+gems and versions that you have already developed and tested against.
+
+`Bundler offers a rock-solid guarantee that the third-party
+code you are running in development and testing is also the
+third-party code you are running in production. You can choose
+to exclude some of that code in different environments, but you
+will never be caught flat-footed by different versions of
+third-party code being used in different environments.`
+
+For a simple illustration, consider the following Gemfile(5):
+
+ source 'https://rubygems.org'
+
+ gem 'sinatra'
+
+ group :production do
+ gem 'rack-perftools-profiler'
+ end
+
+In this case, `sinatra` depends on any version of Rack (`>= 1.0`), while
+`rack-perftools-profiler` depends on 1.x (`~> 1.0`).
+
+When you run `bundle install --without production` in development, we
+look at the dependencies of `rack-perftools-profiler` as well. That way,
+you do not spend all your time developing against Rack 2.0, using new
+APIs unavailable in Rack 1.x, only to have Bundler switch to Rack 1.2
+when the `production` group _is_ used.
+
+This should not cause any problems in practice, because we do not
+attempt to `install` the gems in the excluded groups, and only evaluate
+as part of the dependency resolution process.
+
+This also means that you cannot include different versions of the same
+gem in different groups, because doing so would result in different
+sets of dependencies used in development and production. Because of
+the vagaries of the dependency resolution process, this usually
+affects more than the gems you list in your Gemfile(5), and can
+(surprisingly) radically change the gems you are using.
+
+## THE GEMFILE.LOCK
+
+When you run `bundle install`, Bundler will persist the full names
+and versions of all gems that you used (including dependencies of
+the gems specified in the Gemfile(5)) into a file called `Gemfile.lock`.
+
+Bundler uses this file in all subsequent calls to `bundle install`,
+which guarantees that you always use the same exact code, even
+as your application moves across machines.
+
+Because of the way dependency resolution works, even a
+seemingly small change (for instance, an update to a point-release
+of a dependency of a gem in your Gemfile(5)) can result in radically
+different gems being needed to satisfy all dependencies.
+
+As a result, you `SHOULD` check your `Gemfile.lock` into version
+control, in both applications and gems. If you do not, every machine that
+checks out your repository (including your production server) will resolve all
+dependencies again, which will result in different versions of
+third-party code being used if `any` of the gems in the Gemfile(5)
+or any of their dependencies have been updated.
+
+When Bundler first shipped, the `Gemfile.lock` was included in the `.gitignore`
+file included with generated gems. Over time, however, it became clear that
+this practice forces the pain of broken dependencies onto new contributors,
+while leaving existing contributors potentially unaware of the problem. Since
+`bundle install` is usually the first step towards a contribution, the pain of
+broken dependencies would discourage new contributors from contributing. As a
+result, we have revised our guidance for gem authors to now recommend checking
+in the lock for gems.
+
+## CONSERVATIVE UPDATING
+
+When you make a change to the Gemfile(5) and then run `bundle install`,
+Bundler will update only the gems that you modified.
+
+In other words, if a gem that you `did not modify` worked before
+you called `bundle install`, it will continue to use the exact
+same versions of all dependencies as it used before the update.
+
+Let's take a look at an example. Here's your original Gemfile(5):
+
+ source 'https://rubygems.org'
+
+ gem 'actionpack', '2.3.8'
+ gem 'activemerchant'
+
+In this case, both `actionpack` and `activemerchant` depend on
+`activesupport`. The `actionpack` gem depends on `activesupport 2.3.8`
+and `rack ~> 1.1.0`, while the `activemerchant` gem depends on
+`activesupport >= 2.3.2`, `braintree >= 2.0.0`, and `builder >= 2.0.0`.
+
+When the dependencies are first resolved, Bundler will select
+`activesupport 2.3.8`, which satisfies the requirements of both
+gems in your Gemfile(5).
+
+Next, you modify your Gemfile(5) to:
+
+ source 'https://rubygems.org'
+
+ gem 'actionpack', '3.0.0.rc'
+ gem 'activemerchant'
+
+The `actionpack 3.0.0.rc` gem has a number of new dependencies,
+and updates the `activesupport` dependency to `= 3.0.0.rc` and
+the `rack` dependency to `~> 1.2.1`.
+
+When you run `bundle install`, Bundler notices that you changed
+the `actionpack` gem, but not the `activemerchant` gem. It
+evaluates the gems currently being used to satisfy its requirements:
+
+ * `activesupport 2.3.8`:
+ also used to satisfy a dependency in `activemerchant`,
+ which is not being updated
+ * `rack ~> 1.1.0`:
+ not currently being used to satisfy another dependency
+
+Because you did not explicitly ask to update `activemerchant`,
+you would not expect it to suddenly stop working after updating
+`actionpack`. However, satisfying the new `activesupport 3.0.0.rc`
+dependency of actionpack requires updating one of its dependencies.
+
+Even though `activemerchant` declares a very loose dependency
+that theoretically matches `activesupport 3.0.0.rc`, Bundler treats
+gems in your Gemfile(5) that have not changed as an atomic unit
+together with their dependencies. In this case, the `activemerchant`
+dependency is treated as `activemerchant 1.7.1 + activesupport 2.3.8`,
+so `bundle install` will report that it cannot update `actionpack`.
+
+To explicitly update `actionpack`, including its dependencies
+which other gems in the Gemfile(5) still depend on, run
+`bundle update actionpack` (see `bundle update(1)`).
+
+`Summary`: In general, after making a change to the Gemfile(5) , you
+should first try to run `bundle install`, which will guarantee that no
+other gem in the Gemfile(5) is impacted by the change. If that
+does not work, run [bundle update(1)](bundle-update.1.html).
+
+## SEE ALSO
+
+* [Gem install docs](http://guides.rubygems.org/rubygems-basics/#installing-gems)
+* [Rubygems signing docs](http://guides.rubygems.org/security/)
diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1
new file mode 100644
index 0000000000..a697173af9
--- /dev/null
+++ b/lib/bundler/man/bundle-list.1
@@ -0,0 +1,50 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-LIST" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-list\fR \- List all the gems in the bundle
+.
+.SH "SYNOPSIS"
+\fBbundle list\fR [\-\-name\-only] [\-\-paths] [\-\-without\-group=GROUP[ GROUP\.\.\.]] [\-\-only\-group=GROUP[ GROUP\.\.\.]]
+.
+.SH "DESCRIPTION"
+Prints a list of all the gems in the bundle including their version\.
+.
+.P
+Example:
+.
+.P
+bundle list \-\-name\-only
+.
+.P
+bundle list \-\-paths
+.
+.P
+bundle list \-\-without\-group test
+.
+.P
+bundle list \-\-only\-group dev
+.
+.P
+bundle list \-\-only\-group dev test \-\-paths
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-name\-only\fR
+Print only the name of each gem\.
+.
+.TP
+\fB\-\-paths\fR
+Print the path to each gem in the bundle\.
+.
+.TP
+\fB\-\-without\-group=<list>\fR
+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\.
+
diff --git a/lib/bundler/man/bundle-list.1.ronn b/lib/bundler/man/bundle-list.1.ronn
new file mode 100644
index 0000000000..dc058ecd5f
--- /dev/null
+++ b/lib/bundler/man/bundle-list.1.ronn
@@ -0,0 +1,33 @@
+bundle-list(1) -- List all the gems in the bundle
+=========================================================================
+
+## SYNOPSIS
+
+`bundle list` [--name-only] [--paths] [--without-group=GROUP[ GROUP...]] [--only-group=GROUP[ GROUP...]]
+
+## DESCRIPTION
+
+Prints a list of all the gems in the bundle including their version.
+
+Example:
+
+bundle list --name-only
+
+bundle list --paths
+
+bundle list --without-group test
+
+bundle list --only-group dev
+
+bundle list --only-group dev test --paths
+
+## OPTIONS
+
+* `--name-only`:
+ Print only the name of each gem.
+* `--paths`:
+ Print the path to each gem in the bundle.
+* `--without-group=<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.
diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1
new file mode 100644
index 0000000000..ef515b0337
--- /dev/null
+++ b/lib/bundler/man/bundle-lock.1
@@ -0,0 +1,84 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-LOCK" "1" "December 2021" "" ""
+.
+.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]
+.
+.SH "DESCRIPTION"
+Lock the gems specified in Gemfile\.
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-update=<*gems>\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\-\-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
+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
+Add a new platform to the lockfile, re\-resolving for the addition of that platform\.
+.
+.TP
+\fB\-\-remove\-platform\fR
+Remove a platform from the lockfile\.
+.
+.TP
+\fB\-\-patch\fR
+If updating, prefer updating only to next patch version\.
+.
+.TP
+\fB\-\-minor\fR
+If updating, prefer updating only to next minor version\.
+.
+.TP
+\fB\-\-major\fR
+If updating, prefer updating to next major version (default)\.
+.
+.TP
+\fB\-\-strict\fR
+If updating, do not allow any gem to be updated past latest \-\-patch | \-\-minor | \-\-major\.
+.
+.TP
+\fB\-\-conservative\fR
+If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated\.
+.
+.SH "UPDATING ALL GEMS"
+If you run \fBbundle lock\fR with \fB\-\-update\fR option without list of gems, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\.
+.
+.SH "UPDATING A LIST OF GEMS"
+Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the gems that you specified locked to the versions in the \fBGemfile\.lock\fR\.
+.
+.P
+For instance, you only want to update \fBnokogiri\fR, run \fBbundle lock \-\-update nokogiri\fR\.
+.
+.P
+Bundler will update \fBnokogiri\fR and any of its dependencies, but leave the rest of the gems that you specified locked to the versions in the \fBGemfile\.lock\fR\.
+.
+.SH "SUPPORTING OTHER PLATFORMS"
+If you want your bundle to support platforms other than the one you\'re running locally, you can run \fBbundle lock \-\-add\-platform PLATFORM\fR to add PLATFORM to the lockfile, force bundler to re\-resolve and consider the new platform when picking gems, all without needing to have a machine that matches PLATFORM handy to install those platform\-specific gems on\.
+.
+.P
+For a full explanation of gem platforms, see \fBgem help platform\fR\.
+.
+.SH "PATCH LEVEL OPTIONS"
+See bundle update(1) \fIbundle\-update\.1\.html\fR for details\.
diff --git a/man/bundle-lock.ronn b/lib/bundler/man/bundle-lock.1.ronn
index 3aa5920f5a..3aa5920f5a 100644
--- a/man/bundle-lock.ronn
+++ b/lib/bundler/man/bundle-lock.1.ronn
diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1
new file mode 100644
index 0000000000..dd28566bdb
--- /dev/null
+++ b/lib/bundler/man/bundle-open.1
@@ -0,0 +1,32 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-OPEN" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
+.
+.SH "SYNOPSIS"
+\fBbundle open\fR [GEM]
+.
+.SH "DESCRIPTION"
+Opens the source directory of the provided GEM in your editor\.
+.
+.P
+For this to work the \fBEDITOR\fR or \fBBUNDLER_EDITOR\fR environment variable has to be set\.
+.
+.P
+Example:
+.
+.IP "" 4
+.
+.nf
+
+bundle open \'rack\'
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Will open the source directory for the \'rack\' gem in your bundle\.
diff --git a/man/bundle-open.ronn b/lib/bundler/man/bundle-open.1.ronn
index 497beac93f..497beac93f 100644
--- a/man/bundle-open.ronn
+++ b/lib/bundler/man/bundle-open.1.ronn
diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1
new file mode 100644
index 0000000000..b9d50a1c71
--- /dev/null
+++ b/lib/bundler/man/bundle-outdated.1
@@ -0,0 +1,155 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-OUTDATED" "1" "December 2021" "" ""
+.
+.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] [\-\-update\-strict] [\-\-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"
+.
+.TP
+\fB\-\-local\fR
+Do not attempt to fetch gems remotely and use the gem cache instead\.
+.
+.TP
+\fB\-\-pre\fR
+Check for newer pre\-release gems\.
+.
+.TP
+\fB\-\-source\fR
+Check against a specific source\.
+.
+.TP
+\fB\-\-strict\fR
+Only list newer versions allowed by your Gemfile requirements\.
+.
+.TP
+\fB\-\-parseable\fR, \fB\-\-porcelain\fR
+Use minimal formatting for more parseable output\.
+.
+.TP
+\fB\-\-group\fR
+List gems from a specific group\.
+.
+.TP
+\fB\-\-groups\fR
+List gems organized by groups\.
+.
+.TP
+\fB\-\-update\-strict\fR
+Strict conservative resolution, do not allow any gem to be updated past latest \-\-patch | \-\-minor| \-\-major\.
+.
+.TP
+\fB\-\-minor\fR
+Prefer updating only to next minor version\.
+.
+.TP
+\fB\-\-major\fR
+Prefer updating to next major version (default)\.
+.
+.TP
+\fB\-\-patch\fR
+Prefer updating only to next patch version\.
+.
+.TP
+\fB\-\-filter\-major\fR
+Only list major newer versions\.
+.
+.TP
+\fB\-\-filter\-minor\fR
+Only list minor newer versions\.
+.
+.TP
+\fB\-\-filter\-patch\fR
+Only list patch newer versions\.
+.
+.TP
+\fB\-\-only\-explicit\fR
+Only list gems specified in your Gemfile, not their dependencies\.
+.
+.SH "PATCH LEVEL OPTIONS"
+See bundle update(1) \fIbundle\-update\.1\.html\fR for details\.
+.
+.P
+One difference between the patch level options in \fBbundle update\fR and here is the \fB\-\-strict\fR option\. \fB\-\-strict\fR was already an option on outdated before the patch level options were added\. \fB\-\-strict\fR wasn\'t altered, and the \fB\-\-update\-strict\fR option on \fBoutdated\fR reflects what \fB\-\-strict\fR does on \fBbundle update\fR\.
+.
+.SH "FILTERING OUTPUT"
+The 3 filtering options do not affect the resolution of versions, merely what versions are shown in the output\.
+.
+.P
+If the regular output shows the following:
+.
+.IP "" 4
+.
+.nf
+
+* faker (newest 1\.6\.6, installed 1\.6\.5, requested ~> 1\.4) in groups "development, test"
+* hashie (newest 3\.4\.6, installed 1\.2\.0, requested = 1\.2\.0) in groups "default"
+* headless (newest 2\.3\.1, installed 2\.2\.3) in groups "test"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+\fB\-\-filter\-major\fR would only show:
+.
+.IP "" 4
+.
+.nf
+
+* hashie (newest 3\.4\.6, installed 1\.2\.0, requested = 1\.2\.0) in groups "default"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+\fB\-\-filter\-minor\fR would only show:
+.
+.IP "" 4
+.
+.nf
+
+* headless (newest 2\.3\.1, installed 2\.2\.3) in groups "test"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+\fB\-\-filter\-patch\fR would only show:
+.
+.IP "" 4
+.
+.nf
+
+* faker (newest 1\.6\.6, installed 1\.6\.5, requested ~> 1\.4) in groups "development, test"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Filter options can be combined\. \fB\-\-filter\-minor\fR and \fB\-\-filter\-patch\fR would show:
+.
+.IP "" 4
+.
+.nf
+
+* faker (newest 1\.6\.6, installed 1\.6\.5, requested ~> 1\.4) in groups "development, test"
+* headless (newest 2\.3\.1, installed 2\.2\.3) in groups "test"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Combining all three \fBfilter\fR options would be the same result as providing none of them\.
diff --git a/man/bundle-outdated.ronn b/lib/bundler/man/bundle-outdated.1.ronn
index a991d23789..a991d23789 100644
--- a/man/bundle-outdated.ronn
+++ b/lib/bundler/man/bundle-outdated.1.ronn
diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1
new file mode 100644
index 0000000000..b1c859f64b
--- /dev/null
+++ b/lib/bundler/man/bundle-platform.1
@@ -0,0 +1,61 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-PLATFORM" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-platform\fR \- Displays platform compatibility information
+.
+.SH "SYNOPSIS"
+\fBbundle platform\fR [\-\-ruby]
+.
+.SH "DESCRIPTION"
+\fBplatform\fR will display information from your Gemfile, Gemfile\.lock, and Ruby VM about your platform\.
+.
+.P
+For instance, using this Gemfile(5):
+.
+.IP "" 4
+.
+.nf
+
+source "https://rubygems\.org"
+
+ruby "1\.9\.3"
+
+gem "rack"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+If you run \fBbundle platform\fR on Ruby 1\.9\.3, it will display the following output:
+.
+.IP "" 4
+.
+.nf
+
+Your platform is: x86_64\-linux
+
+Your app has gems that work on these platforms:
+* ruby
+
+Your Gemfile specifies a Ruby version requirement:
+* ruby 1\.9\.3
+
+Your current platform satisfies the Ruby version requirement\.
+.
+.fi
+.
+.IP "" 0
+.
+.P
+\fBplatform\fR will list all the platforms in your \fBGemfile\.lock\fR as well as the \fBruby\fR directive if applicable from your Gemfile(5)\. It will also let you know if the \fBruby\fR directive requirement has been met\. If \fBruby\fR directive doesn\'t match the running Ruby VM, it will tell you what part does not\.
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-ruby\fR
+It will display the ruby directive information, so you don\'t have to parse it from the Gemfile(5)\.
+
diff --git a/man/bundle-platform.ronn b/lib/bundler/man/bundle-platform.1.ronn
index b5d3283fb6..b5d3283fb6 100644
--- a/man/bundle-platform.ronn
+++ b/lib/bundler/man/bundle-platform.1.ronn
diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1
new file mode 100644
index 0000000000..6e4a028666
--- /dev/null
+++ b/lib/bundler/man/bundle-pristine.1
@@ -0,0 +1,34 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-PRISTINE" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
+.
+.SH "SYNOPSIS"
+\fBbundle pristine\fR
+.
+.SH "DESCRIPTION"
+\fBpristine\fR restores the installed gems in the bundle to their pristine condition using the local gem cache from RubyGems\. For git gems, a forced checkout will be performed\.
+.
+.P
+For further explanation, \fBbundle pristine\fR ignores unpacked files on disk\. In other words, this command utilizes the local \fB\.gem\fR cache or the gem\'s git repository as if one were installing from scratch\.
+.
+.P
+Note: the Bundler gem cannot be restored to its original state with \fBpristine\fR\. One also cannot use \fBbundle pristine\fR on gems with a \'path\' option in the Gemfile, because bundler has no original copy it can restore from\.
+.
+.P
+When is it practical to use \fBbundle pristine\fR?
+.
+.P
+It comes in handy when a developer is debugging a gem\. \fBbundle pristine\fR is a great way to get rid of experimental changes to a gem that one may not want\.
+.
+.P
+Why use \fBbundle pristine\fR over \fBgem pristine \-\-all\fR?
+.
+.P
+Both commands are very similar\. For context: \fBbundle pristine\fR, without arguments, cleans all gems from the lockfile\. Meanwhile, \fBgem pristine \-\-all\fR cleans all installed gems for that Ruby version\.
+.
+.P
+If a developer forgets which gems in their project they might have been debugging, the Rubygems \fBgem pristine [GEMNAME]\fR command may be inconvenient\. One can avoid waiting for \fBgem pristine \-\-all\fR, and instead run \fBbundle pristine\fR\.
diff --git a/man/bundle-pristine.ronn b/lib/bundler/man/bundle-pristine.1.ronn
index e2d6b6a348..e2d6b6a348 100644
--- a/man/bundle-pristine.ronn
+++ b/lib/bundler/man/bundle-pristine.1.ronn
diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1
new file mode 100644
index 0000000000..0b4edd1414
--- /dev/null
+++ b/lib/bundler/man/bundle-remove.1
@@ -0,0 +1,31 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-REMOVE" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-remove\fR \- Removes gems from the Gemfile
+.
+.SH "SYNOPSIS"
+\fBbundle remove [GEM [GEM \.\.\.]] [\-\-install]\fR
+.
+.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/man/bundle-remove.ronn b/lib/bundler/man/bundle-remove.1.ronn
index 40a239b4a2..40a239b4a2 100644
--- a/man/bundle-remove.ronn
+++ b/lib/bundler/man/bundle-remove.1.ronn
diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1
new file mode 100644
index 0000000000..375699ddf0
--- /dev/null
+++ b/lib/bundler/man/bundle-show.1
@@ -0,0 +1,23 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-SHOW" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
+.
+.SH "SYNOPSIS"
+\fBbundle show\fR [GEM] [\-\-paths]
+.
+.SH "DESCRIPTION"
+Without the [GEM] option, \fBshow\fR will print a list of the names and versions of all gems that are required by your [\fBGemfile(5)\fR][Gemfile(5)], sorted by name\.
+.
+.P
+Calling show with [GEM] will list the exact location of that gem on your machine\.
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-paths\fR
+List the paths of all gems that are required by your [\fBGemfile(5)\fR][Gemfile(5)], sorted by gem name\.
+
diff --git a/man/bundle-show.ronn b/lib/bundler/man/bundle-show.1.ronn
index a6a59a1445..a6a59a1445 100644
--- a/man/bundle-show.ronn
+++ b/lib/bundler/man/bundle-show.1.ronn
diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1
new file mode 100644
index 0000000000..c08bc66ef0
--- /dev/null
+++ b/lib/bundler/man/bundle-update.1
@@ -0,0 +1,394 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-UPDATE" "1" "December 2021" "" ""
+.
+.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]
+.
+.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
+You would use \fBbundle update\fR to explicitly update the version of a gem\.
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-all\fR
+Update all gems specified in Gemfile\.
+.
+.TP
+\fB\-\-group=<name>\fR, \fB\-g=[<name>]\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
+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
+Do not attempt to fetch gems remotely and use the gem cache instead\.
+.
+.TP
+\fB\-\-ruby\fR
+Update the locked version of Ruby to the current version of Ruby\.
+.
+.TP
+\fB\-\-bundler\fR
+Update the locked version of bundler to the invoked bundler version\.
+.
+.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
+Specify the number of jobs to run in parallel\. The default is \fB1\fR\.
+.
+.TP
+\fB\-\-retry=[<number>]\fR
+Retry failed network or git requests for \fInumber\fR times\.
+.
+.TP
+\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
+\fB\-\-minor\fR
+Prefer updating only to next minor version\.
+.
+.TP
+\fB\-\-major\fR
+Prefer updating to next major version (default)\.
+.
+.TP
+\fB\-\-strict\fR
+Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR | \fB\-\-major\fR\.
+.
+.TP
+\fB\-\-conservative\fR
+Use bundle install conservative update behavior and do not allow indirect dependencies to be updated\.
+.
+.SH "UPDATING ALL GEMS"
+If you run \fBbundle update \-\-all\fR, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\.
+.
+.P
+Consider the following Gemfile(5):
+.
+.IP "" 4
+.
+.nf
+
+source "https://rubygems\.org"
+
+gem "rails", "3\.0\.0\.rc"
+gem "nokogiri"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+When you run bundle install(1) \fIbundle\-install\.1\.html\fR the first time, bundler will resolve all of the dependencies, all the way down, and install what you need:
+.
+.IP "" 4
+.
+.nf
+
+Fetching gem metadata from https://rubygems\.org/\.\.\.\.\.\.\.\.\.
+Resolving dependencies\.\.\.
+Installing builder 2\.1\.2
+Installing abstract 1\.0\.0
+Installing rack 1\.2\.8
+Using bundler 1\.7\.6
+Installing rake 10\.4\.0
+Installing polyglot 0\.3\.5
+Installing mime\-types 1\.25\.1
+Installing i18n 0\.4\.2
+Installing mini_portile 0\.6\.1
+Installing tzinfo 0\.3\.42
+Installing rack\-mount 0\.6\.14
+Installing rack\-test 0\.5\.7
+Installing treetop 1\.4\.15
+Installing thor 0\.14\.6
+Installing activesupport 3\.0\.0\.rc
+Installing erubis 2\.6\.6
+Installing activemodel 3\.0\.0\.rc
+Installing arel 0\.4\.0
+Installing mail 2\.2\.20
+Installing activeresource 3\.0\.0\.rc
+Installing actionpack 3\.0\.0\.rc
+Installing activerecord 3\.0\.0\.rc
+Installing actionmailer 3\.0\.0\.rc
+Installing railties 3\.0\.0\.rc
+Installing rails 3\.0\.0\.rc
+Installing nokogiri 1\.6\.5
+
+Bundle complete! 2 Gemfile dependencies, 26 gems total\.
+Use `bundle show [gemname]` to see where a bundled gem is installed\.
+.
+.fi
+.
+.IP "" 0
+.
+.P
+As you can see, even though you have two gems in the Gemfile(5), your application needs 26 different gems in order to run\. Bundler remembers the exact versions it installed in \fBGemfile\.lock\fR\. The next time you run bundle install(1) \fIbundle\-install\.1\.html\fR, bundler skips the dependency resolution and installs the same gems as it installed last time\.
+.
+.P
+After checking in the \fBGemfile\.lock\fR into version control and cloning it on another machine, running bundle install(1) \fIbundle\-install\.1\.html\fR will \fIstill\fR install the gems that you installed last time\. You don\'t need to worry that a new release of \fBerubis\fR or \fBmail\fR changes the gems you use\.
+.
+.P
+However, from time to time, you might want to update the gems you are using to the newest versions that still match the gems in your Gemfile(5)\.
+.
+.P
+To do this, run \fBbundle update \-\-all\fR, which will ignore the \fBGemfile\.lock\fR, and resolve all the dependencies again\. Keep in mind that this process can result in a significantly different set of the 25 gems, based on the requirements of new gems that the gem authors released since the last time you ran \fBbundle update \-\-all\fR\.
+.
+.SH "UPDATING A LIST OF GEMS"
+Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the gems that you specified locked to the versions in the \fBGemfile\.lock\fR\.
+.
+.P
+For instance, in the scenario above, imagine that \fBnokogiri\fR releases version \fB1\.4\.4\fR, and you want to update it \fIwithout\fR updating Rails and all of its dependencies\. To do this, run \fBbundle update nokogiri\fR\.
+.
+.P
+Bundler will update \fBnokogiri\fR and any of its dependencies, but leave alone Rails and its dependencies\.
+.
+.SH "OVERLAPPING DEPENDENCIES"
+Sometimes, multiple gems declared in your Gemfile(5) are satisfied by the same second\-level dependency\. For instance, consider the case of \fBthin\fR and \fBrack\-perftools\-profiler\fR\.
+.
+.IP "" 4
+.
+.nf
+
+source "https://rubygems\.org"
+
+gem "thin"
+gem "rack\-perftools\-profiler"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+The \fBthin\fR gem depends on \fBrack >= 1\.0\fR, while \fBrack\-perftools\-profiler\fR depends on \fBrack ~> 1\.0\fR\. If you run bundle install, you get:
+.
+.IP "" 4
+.
+.nf
+
+Fetching source index for https://rubygems\.org/
+Installing daemons (1\.1\.0)
+Installing eventmachine (0\.12\.10) with native extensions
+Installing open4 (1\.0\.1)
+Installing perftools\.rb (0\.4\.7) with native extensions
+Installing rack (1\.2\.1)
+Installing rack\-perftools_profiler (0\.0\.2)
+Installing thin (1\.2\.7) with native extensions
+Using bundler (1\.0\.0\.rc\.3)
+.
+.fi
+.
+.IP "" 0
+.
+.P
+In this case, the two gems have their own set of dependencies, but they share \fBrack\fR in common\. If you run \fBbundle update thin\fR, bundler will update \fBdaemons\fR, \fBeventmachine\fR and \fBrack\fR, which are dependencies of \fBthin\fR, but not \fBopen4\fR or \fBperftools\.rb\fR, which are dependencies of \fBrack\-perftools_profiler\fR\. Note that \fBbundle update thin\fR will update \fBrack\fR even though it\'s \fIalso\fR a dependency of \fBrack\-perftools_profiler\fR\.
+.
+.P
+In short, by default, when you update a gem using \fBbundle update\fR, bundler will update all dependencies of that gem, including those that are also dependencies of another gem\.
+.
+.P
+To prevent updating indirect dependencies, prior to version 1\.14 the only option was the \fBCONSERVATIVE UPDATING\fR behavior in bundle install(1) \fIbundle\-install\.1\.html\fR:
+.
+.P
+In this scenario, updating the \fBthin\fR version manually in the Gemfile(5), and then running bundle install(1) \fIbundle\-install\.1\.html\fR will only update \fBdaemons\fR and \fBeventmachine\fR, but not \fBrack\fR\. For more information, see the \fBCONSERVATIVE UPDATING\fR section of bundle install(1) \fIbundle\-install\.1\.html\fR\.
+.
+.P
+Starting with 1\.14, specifying the \fB\-\-conservative\fR option will also prevent indirect dependencies from being updated\.
+.
+.SH "PATCH LEVEL OPTIONS"
+Version 1\.14 introduced 4 patch\-level options that will influence how gem versions are resolved\. One of the following options can be used: \fB\-\-patch\fR, \fB\-\-minor\fR or \fB\-\-major\fR\. \fB\-\-strict\fR can be added to further influence resolution\.
+.
+.TP
+\fB\-\-patch\fR
+Prefer updating only to next patch version\.
+.
+.TP
+\fB\-\-minor\fR
+Prefer updating only to next minor version\.
+.
+.TP
+\fB\-\-major\fR
+Prefer updating to next major version (default)\.
+.
+.TP
+\fB\-\-strict\fR
+Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR | \fB\-\-major\fR\.
+.
+.P
+When Bundler is resolving what versions to use to satisfy declared requirements in the Gemfile or in parent gems, it looks up all available versions, filters out any versions that don\'t satisfy the requirement, and then, by default, sorts them from newest to oldest, considering them in that order\.
+.
+.P
+Providing one of the patch level options (e\.g\. \fB\-\-patch\fR) changes the sort order of the satisfying versions, causing Bundler to consider the latest \fB\-\-patch\fR or \fB\-\-minor\fR version available before other versions\. Note that versions outside the stated patch level could still be resolved to if necessary to find a suitable dependency graph\.
+.
+.P
+For example, if gem \'foo\' is locked at 1\.0\.2, with no gem requirement defined in the Gemfile, and versions 1\.0\.3, 1\.0\.4, 1\.1\.0, 1\.1\.1, 2\.0\.0 all exist, the default order of preference by default (\fB\-\-major\fR) will be "2\.0\.0, 1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2"\.
+.
+.P
+If the \fB\-\-patch\fR option is used, the order of preference will change to "1\.0\.4, 1\.0\.3, 1\.0\.2, 1\.1\.1, 1\.1\.0, 2\.0\.0"\.
+.
+.P
+If the \fB\-\-minor\fR option is used, the order of preference will change to "1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2, 2\.0\.0"\.
+.
+.P
+Combining the \fB\-\-strict\fR option with any of the patch level options will remove any versions beyond the scope of the patch level option, to ensure that no gem is updated that far\.
+.
+.P
+To continue the previous example, if both \fB\-\-patch\fR and \fB\-\-strict\fR options are used, the available versions for resolution would be "1\.0\.4, 1\.0\.3, 1\.0\.2"\. If \fB\-\-minor\fR and \fB\-\-strict\fR are used, it would be "1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2"\.
+.
+.P
+Gem requirements as defined in the Gemfile will still be the first determining factor for what versions are available\. If the gem requirement for \fBfoo\fR in the Gemfile is \'~> 1\.0\', that will accomplish the same thing as providing the \fB\-\-minor\fR and \fB\-\-strict\fR options\.
+.
+.SH "PATCH LEVEL EXAMPLES"
+Given the following gem specifications:
+.
+.IP "" 4
+.
+.nf
+
+foo 1\.4\.3, requires: ~> bar 2\.0
+foo 1\.4\.4, requires: ~> bar 2\.0
+foo 1\.4\.5, requires: ~> bar 2\.1
+foo 1\.5\.0, requires: ~> bar 2\.1
+foo 1\.5\.1, requires: ~> bar 3\.0
+bar with versions 2\.0\.3, 2\.0\.4, 2\.1\.0, 2\.1\.1, 3\.0\.0
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Gemfile:
+.
+.IP "" 4
+.
+.nf
+
+gem \'foo\'
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Gemfile\.lock:
+.
+.IP "" 4
+.
+.nf
+
+foo (1\.4\.3)
+ bar (~> 2\.0)
+bar (2\.0\.3)
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Cases:
+.
+.IP "" 4
+.
+.nf
+
+# Command Line Result
+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
+1 bundle update \-\-patch \'foo 1\.4\.5\', \'bar 2\.1\.1\'
+2 bundle update \-\-patch foo \'foo 1\.4\.5\', \'bar 2\.1\.1\'
+3 bundle update \-\-minor \'foo 1\.5\.1\', \'bar 3\.0\.0\'
+4 bundle update \-\-minor \-\-strict \'foo 1\.5\.0\', \'bar 2\.1\.1\'
+5 bundle update \-\-patch \-\-strict \'foo 1\.4\.4\', \'bar 2\.0\.4\'
+.
+.fi
+.
+.IP "" 0
+.
+.P
+In case 1, bar is upgraded to 2\.1\.1, a minor version increase, because the dependency from foo 1\.4\.5 required it\.
+.
+.P
+In case 2, only foo is requested to be unlocked, but bar is also allowed to move because it\'s not a declared dependency in the Gemfile\.
+.
+.P
+In case 3, bar goes up a whole major release, because a minor increase is preferred now for foo, and when it goes to 1\.5\.1, it requires 3\.0\.0 of bar\.
+.
+.P
+In case 4, foo is preferred up to a minor version, but 1\.5\.1 won\'t work because the \-\-strict flag removes bar 3\.0\.0 from consideration since it\'s a major increment\.
+.
+.P
+In case 5, both foo and bar have any minor or major increments removed from consideration because of the \-\-strict flag, so the most they can move is up to 1\.4\.4 and 2\.0\.4\.
+.
+.SH "RECOMMENDED WORKFLOW"
+In general, when working with an application managed with bundler, you should use the following workflow:
+.
+.IP "\(bu" 4
+After you create your Gemfile(5) for the first time, run
+.
+.IP
+$ bundle install
+.
+.IP "\(bu" 4
+Check the resulting \fBGemfile\.lock\fR into version control
+.
+.IP
+$ git add Gemfile\.lock
+.
+.IP "\(bu" 4
+When checking out this repository on another development machine, run
+.
+.IP
+$ bundle install
+.
+.IP "\(bu" 4
+When checking out this repository on a deployment machine, run
+.
+.IP
+$ bundle install \-\-deployment
+.
+.IP "\(bu" 4
+After changing the Gemfile(5) to reflect a new or update dependency, run
+.
+.IP
+$ bundle install
+.
+.IP "\(bu" 4
+Make sure to check the updated \fBGemfile\.lock\fR into version control
+.
+.IP
+$ git add Gemfile\.lock
+.
+.IP "\(bu" 4
+If bundle install(1) \fIbundle\-install\.1\.html\fR reports a conflict, manually update the specific gems that you changed in the Gemfile(5)
+.
+.IP
+$ bundle update rails thin
+.
+.IP "\(bu" 4
+If you want to update all the gems to the latest possible versions that still match the gems listed in the Gemfile(5), run
+.
+.IP
+$ bundle update \-\-all
+.
+.IP "" 0
+
diff --git a/lib/bundler/man/bundle-update.1.ronn b/lib/bundler/man/bundle-update.1.ronn
new file mode 100644
index 0000000000..3a16f29149
--- /dev/null
+++ b/lib/bundler/man/bundle-update.1.ronn
@@ -0,0 +1,350 @@
+bundle-update(1) -- Update your gems to the latest available versions
+=====================================================================
+
+## SYNOPSIS
+
+`bundle update` <*gems> [--all]
+ [--group=NAME]
+ [--source=NAME]
+ [--local]
+ [--ruby]
+ [--bundler[=VERSION]]
+ [--full-index]
+ [--jobs=JOBS]
+ [--quiet]
+ [--patch|--minor|--major]
+ [--redownload]
+ [--strict]
+ [--conservative]
+
+## DESCRIPTION
+
+Update the gems specified (all gems, if `--all` flag is used), ignoring
+the previously installed gems specified in the `Gemfile.lock`. In
+general, you should use [bundle install(1)](bundle-install.1.html) to install the same exact
+gems and versions across machines.
+
+You would use `bundle update` to explicitly update the version of a
+gem.
+
+## OPTIONS
+
+* `--all`:
+ Update all gems specified in Gemfile.
+
+* `--group=<name>`, `-g=[<name>]`:
+ 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>`:
+ The name of a `:git` or `:path` source used in the Gemfile(5). For
+ instance, with a `:git` source of `http://github.com/rails/rails.git`,
+ you would call `bundle update --source rails`
+
+* `--local`:
+ Do not attempt to fetch gems remotely and use the gem cache instead.
+
+* `--ruby`:
+ Update the locked version of Ruby to the current version of Ruby.
+
+* `--bundler`:
+ Update the locked version of bundler to the invoked bundler version.
+
+* `--full-index`:
+ Fall back to using the single-file index of all gems.
+
+* `--jobs=[<number>]`, `-j[<number>]`:
+ Specify the number of jobs to run in parallel. The default is `1`.
+
+* `--retry=[<number>]`:
+ Retry failed network or git requests for <number> times.
+
+* `--quiet`:
+ Only output warnings and errors.
+
+* `--redownload`:
+ Force downloading every gem.
+
+* `--patch`:
+ Prefer updating only to next patch version.
+
+* `--minor`:
+ Prefer updating only to next minor version.
+
+* `--major`:
+ Prefer updating to next major version (default).
+
+* `--strict`:
+ Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`.
+
+* `--conservative`:
+ Use bundle install conservative update behavior and do not allow indirect dependencies to be updated.
+
+## UPDATING ALL GEMS
+
+If you run `bundle update --all`, bundler will ignore
+any previously installed gems and resolve all dependencies again
+based on the latest versions of all gems available in the sources.
+
+Consider the following Gemfile(5):
+
+ source "https://rubygems.org"
+
+ gem "rails", "3.0.0.rc"
+ gem "nokogiri"
+
+When you run [bundle install(1)](bundle-install.1.html) the first time, bundler will resolve
+all of the dependencies, all the way down, and install what you need:
+
+ Fetching gem metadata from https://rubygems.org/.........
+ Resolving dependencies...
+ Installing builder 2.1.2
+ Installing abstract 1.0.0
+ Installing rack 1.2.8
+ Using bundler 1.7.6
+ Installing rake 10.4.0
+ Installing polyglot 0.3.5
+ Installing mime-types 1.25.1
+ Installing i18n 0.4.2
+ Installing mini_portile 0.6.1
+ Installing tzinfo 0.3.42
+ Installing rack-mount 0.6.14
+ Installing rack-test 0.5.7
+ Installing treetop 1.4.15
+ Installing thor 0.14.6
+ Installing activesupport 3.0.0.rc
+ Installing erubis 2.6.6
+ Installing activemodel 3.0.0.rc
+ Installing arel 0.4.0
+ Installing mail 2.2.20
+ Installing activeresource 3.0.0.rc
+ Installing actionpack 3.0.0.rc
+ Installing activerecord 3.0.0.rc
+ Installing actionmailer 3.0.0.rc
+ Installing railties 3.0.0.rc
+ Installing rails 3.0.0.rc
+ Installing nokogiri 1.6.5
+
+ Bundle complete! 2 Gemfile dependencies, 26 gems total.
+ Use `bundle show [gemname]` to see where a bundled gem is installed.
+
+As you can see, even though you have two gems in the Gemfile(5), your application
+needs 26 different gems in order to run. Bundler remembers the exact versions
+it installed in `Gemfile.lock`. The next time you run [bundle install(1)](bundle-install.1.html), bundler skips
+the dependency resolution and installs the same gems as it installed last time.
+
+After checking in the `Gemfile.lock` into version control and cloning it on another
+machine, running [bundle install(1)](bundle-install.1.html) will _still_ install the gems that you installed
+last time. You don't need to worry that a new release of `erubis` or `mail` changes
+the gems you use.
+
+However, from time to time, you might want to update the gems you are using to the
+newest versions that still match the gems in your Gemfile(5).
+
+To do this, run `bundle update --all`, which will ignore the `Gemfile.lock`, and resolve
+all the dependencies again. Keep in mind that this process can result in a significantly
+different set of the 25 gems, based on the requirements of new gems that the gem
+authors released since the last time you ran `bundle update --all`.
+
+## UPDATING A LIST OF GEMS
+
+Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the
+gems that you specified locked to the versions in the `Gemfile.lock`.
+
+For instance, in the scenario above, imagine that `nokogiri` releases version `1.4.4`, and
+you want to update it _without_ updating Rails and all of its dependencies. To do this,
+run `bundle update nokogiri`.
+
+Bundler will update `nokogiri` and any of its dependencies, but leave alone Rails and
+its dependencies.
+
+## OVERLAPPING DEPENDENCIES
+
+Sometimes, multiple gems declared in your Gemfile(5) are satisfied by the same
+second-level dependency. For instance, consider the case of `thin` and
+`rack-perftools-profiler`.
+
+ source "https://rubygems.org"
+
+ gem "thin"
+ gem "rack-perftools-profiler"
+
+The `thin` gem depends on `rack >= 1.0`, while `rack-perftools-profiler` depends
+on `rack ~> 1.0`. If you run bundle install, you get:
+
+ Fetching source index for https://rubygems.org/
+ Installing daemons (1.1.0)
+ Installing eventmachine (0.12.10) with native extensions
+ Installing open4 (1.0.1)
+ Installing perftools.rb (0.4.7) with native extensions
+ Installing rack (1.2.1)
+ Installing rack-perftools_profiler (0.0.2)
+ Installing thin (1.2.7) with native extensions
+ Using bundler (1.0.0.rc.3)
+
+In this case, the two gems have their own set of dependencies, but they share
+`rack` in common. If you run `bundle update thin`, bundler will update `daemons`,
+`eventmachine` and `rack`, which are dependencies of `thin`, but not `open4` or
+`perftools.rb`, which are dependencies of `rack-perftools_profiler`. Note that
+`bundle update thin` will update `rack` even though it's _also_ a dependency of
+`rack-perftools_profiler`.
+
+In short, by default, when you update a gem using `bundle update`, bundler will
+update all dependencies of that gem, including those that are also dependencies
+of another gem.
+
+To prevent updating indirect dependencies, prior to version 1.14 the only option
+was the `CONSERVATIVE UPDATING` behavior in [bundle install(1)](bundle-install.1.html):
+
+In this scenario, updating the `thin` version manually in the Gemfile(5),
+and then running [bundle install(1)](bundle-install.1.html) will only update `daemons` and `eventmachine`,
+but not `rack`. For more information, see the `CONSERVATIVE UPDATING` section
+of [bundle install(1)](bundle-install.1.html).
+
+Starting with 1.14, specifying the `--conservative` option will also prevent indirect
+dependencies from being updated.
+
+## PATCH LEVEL OPTIONS
+
+Version 1.14 introduced 4 patch-level options that will influence how gem
+versions are resolved. One of the following options can be used: `--patch`,
+`--minor` or `--major`. `--strict` can be added to further influence resolution.
+
+* `--patch`:
+ Prefer updating only to next patch version.
+
+* `--minor`:
+ Prefer updating only to next minor version.
+
+* `--major`:
+ Prefer updating to next major version (default).
+
+* `--strict`:
+ Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`.
+
+When Bundler is resolving what versions to use to satisfy declared
+requirements in the Gemfile or in parent gems, it looks up all
+available versions, filters out any versions that don't satisfy
+the requirement, and then, by default, sorts them from newest to
+oldest, considering them in that order.
+
+Providing one of the patch level options (e.g. `--patch`) changes the
+sort order of the satisfying versions, causing Bundler to consider the
+latest `--patch` or `--minor` version available before other versions.
+Note that versions outside the stated patch level could still be
+resolved to if necessary to find a suitable dependency graph.
+
+For example, if gem 'foo' is locked at 1.0.2, with no gem requirement
+defined in the Gemfile, and versions 1.0.3, 1.0.4, 1.1.0, 1.1.1, 2.0.0
+all exist, the default order of preference by default (`--major`) will
+be "2.0.0, 1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2".
+
+If the `--patch` option is used, the order of preference will change to
+"1.0.4, 1.0.3, 1.0.2, 1.1.1, 1.1.0, 2.0.0".
+
+If the `--minor` option is used, the order of preference will change to
+"1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2, 2.0.0".
+
+Combining the `--strict` option with any of the patch level options
+will remove any versions beyond the scope of the patch level option,
+to ensure that no gem is updated that far.
+
+To continue the previous example, if both `--patch` and `--strict`
+options are used, the available versions for resolution would be
+"1.0.4, 1.0.3, 1.0.2". If `--minor` and `--strict` are used, it would
+be "1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2".
+
+Gem requirements as defined in the Gemfile will still be the first
+determining factor for what versions are available. If the gem
+requirement for `foo` in the Gemfile is '~> 1.0', that will accomplish
+the same thing as providing the `--minor` and `--strict` options.
+
+## PATCH LEVEL EXAMPLES
+
+Given the following gem specifications:
+
+ foo 1.4.3, requires: ~> bar 2.0
+ foo 1.4.4, requires: ~> bar 2.0
+ foo 1.4.5, requires: ~> bar 2.1
+ foo 1.5.0, requires: ~> bar 2.1
+ foo 1.5.1, requires: ~> bar 3.0
+ bar with versions 2.0.3, 2.0.4, 2.1.0, 2.1.1, 3.0.0
+
+Gemfile:
+
+ gem 'foo'
+
+Gemfile.lock:
+
+ foo (1.4.3)
+ bar (~> 2.0)
+ bar (2.0.3)
+
+Cases:
+
+ # Command Line Result
+ ------------------------------------------------------------
+ 1 bundle update --patch 'foo 1.4.5', 'bar 2.1.1'
+ 2 bundle update --patch foo 'foo 1.4.5', 'bar 2.1.1'
+ 3 bundle update --minor 'foo 1.5.1', 'bar 3.0.0'
+ 4 bundle update --minor --strict 'foo 1.5.0', 'bar 2.1.1'
+ 5 bundle update --patch --strict 'foo 1.4.4', 'bar 2.0.4'
+
+In case 1, bar is upgraded to 2.1.1, a minor version increase, because
+the dependency from foo 1.4.5 required it.
+
+In case 2, only foo is requested to be unlocked, but bar is also
+allowed to move because it's not a declared dependency in the Gemfile.
+
+In case 3, bar goes up a whole major release, because a minor increase
+is preferred now for foo, and when it goes to 1.5.1, it requires 3.0.0
+of bar.
+
+In case 4, foo is preferred up to a minor version, but 1.5.1 won't work
+because the --strict flag removes bar 3.0.0 from consideration since
+it's a major increment.
+
+In case 5, both foo and bar have any minor or major increments removed
+from consideration because of the --strict flag, so the most they can
+move is up to 1.4.4 and 2.0.4.
+
+## RECOMMENDED WORKFLOW
+
+In general, when working with an application managed with bundler, you should
+use the following workflow:
+
+* After you create your Gemfile(5) for the first time, run
+
+ $ bundle install
+
+* Check the resulting `Gemfile.lock` into version control
+
+ $ git add Gemfile.lock
+
+* When checking out this repository on another development machine, run
+
+ $ bundle install
+
+* When checking out this repository on a deployment machine, run
+
+ $ bundle install --deployment
+
+* After changing the Gemfile(5) to reflect a new or update dependency, run
+
+ $ bundle install
+
+* Make sure to check the updated `Gemfile.lock` into version control
+
+ $ git add Gemfile.lock
+
+* If [bundle install(1)](bundle-install.1.html) reports a conflict, manually update the specific
+ gems that you changed in the Gemfile(5)
+
+ $ bundle update rails thin
+
+* If you want to update all the gems to the latest possible versions that
+ still match the gems listed in the Gemfile(5), run
+
+ $ bundle update --all
diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1
new file mode 100644
index 0000000000..f792aa6346
--- /dev/null
+++ b/lib/bundler/man/bundle-viz.1
@@ -0,0 +1,39 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE\-VIZ" "1" "December 2021" "" ""
+.
+.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\.
+.
+.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/man/bundle-viz.ronn b/lib/bundler/man/bundle-viz.1.ronn
index 701df5415e..701df5415e 100644
--- a/man/bundle-viz.ronn
+++ b/lib/bundler/man/bundle-viz.1.ronn
diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1
new file mode 100644
index 0000000000..b1458bf57b
--- /dev/null
+++ b/lib/bundler/man/bundle.1
@@ -0,0 +1,136 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "BUNDLE" "1" "December 2021" "" ""
+.
+.SH "NAME"
+\fBbundle\fR \- Ruby Dependency Management
+.
+.SH "SYNOPSIS"
+\fBbundle\fR COMMAND [\-\-no\-color] [\-\-verbose] [ARGS]
+.
+.SH "DESCRIPTION"
+Bundler manages an \fBapplication\'s dependencies\fR through its entire life across many machines systematically and repeatably\.
+.
+.P
+See the bundler website \fIhttps://bundler\.io\fR for information on getting started, and Gemfile(5) for more information on the \fBGemfile\fR format\.
+.
+.SH "OPTIONS"
+.
+.TP
+\fB\-\-no\-color\fR
+Print all output without color
+.
+.TP
+\fB\-\-retry\fR, \fB\-r\fR
+Specify the number of times you wish to attempt network commands
+.
+.TP
+\fB\-\-verbose\fR, \fB\-V\fR
+Print out additional logging information
+.
+.SH "BUNDLE COMMANDS"
+We divide \fBbundle\fR subcommands into primary commands and utilities:
+.
+.SH "PRIMARY COMMANDS"
+.
+.TP
+\fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR
+Install the gems specified by the \fBGemfile\fR or \fBGemfile\.lock\fR
+.
+.TP
+\fBbundle update(1)\fR \fIbundle\-update\.1\.html\fR
+Update dependencies to their latest versions
+.
+.TP
+\fBbundle package(1)\fR \fIbundle\-package\.1\.html\fR
+Package the \.gem files required by your application into the \fBvendor/cache\fR directory
+.
+.TP
+\fBbundle exec(1)\fR \fIbundle\-exec\.1\.html\fR
+Execute a script in the current bundle
+.
+.TP
+\fBbundle config(1)\fR \fIbundle\-config\.1\.html\fR
+Specify and read configuration options for Bundler
+.
+.TP
+\fBbundle help(1)\fR
+Display detailed help for each subcommand
+.
+.SH "UTILITIES"
+.
+.TP
+\fBbundle add(1)\fR \fIbundle\-add\.1\.html\fR
+Add the named gem to the Gemfile and run \fBbundle install\fR
+.
+.TP
+\fBbundle binstubs(1)\fR \fIbundle\-binstubs\.1\.html\fR
+Generate binstubs for executables in a gem
+.
+.TP
+\fBbundle check(1)\fR \fIbundle\-check\.1\.html\fR
+Determine whether the requirements for your application are installed and available to Bundler
+.
+.TP
+\fBbundle show(1)\fR \fIbundle\-show\.1\.html\fR
+Show the source location of a particular gem in the bundle
+.
+.TP
+\fBbundle outdated(1)\fR \fIbundle\-outdated\.1\.html\fR
+Show all of the outdated gems in the current bundle
+.
+.TP
+\fBbundle console(1)\fR
+Start an IRB session in the current bundle
+.
+.TP
+\fBbundle open(1)\fR \fIbundle\-open\.1\.html\fR
+Open an installed gem in the editor
+.
+.TP
+\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
+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
+\fBbundle gem(1)\fR \fIbundle\-gem\.1\.html\fR
+Create a simple gem, suitable for development with Bundler
+.
+.TP
+\fBbundle platform(1)\fR \fIbundle\-platform\.1\.html\fR
+Display platform compatibility information
+.
+.TP
+\fBbundle clean(1)\fR \fIbundle\-clean\.1\.html\fR
+Clean up unused gems in your Bundler directory
+.
+.TP
+\fBbundle doctor(1)\fR \fIbundle\-doctor\.1\.html\fR
+Display warnings about common problems
+.
+.TP
+\fBbundle remove(1)\fR \fIbundle\-remove\.1\.html\fR
+Removes gems from the Gemfile
+.
+.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 cache(1)\fR
+.
+.IP "\(bu" 4
+\fBbundle show(1)\fR
+.
+.IP "" 0
+
diff --git a/man/bundle.ronn b/lib/bundler/man/bundle.1.ronn
index 5b1712394a..5b1712394a 100644
--- a/man/bundle.ronn
+++ b/lib/bundler/man/bundle.1.ronn
diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5
new file mode 100644
index 0000000000..2e423522b7
--- /dev/null
+++ b/lib/bundler/man/gemfile.5
@@ -0,0 +1,712 @@
+.\" generated with Ronn/v0.7.3
+.\" http://github.com/rtomayko/ronn/tree/0.7.3
+.
+.TH "GEMFILE" "5" "December 2021" "" ""
+.
+.SH "NAME"
+\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
+.
+.SH "SYNOPSIS"
+A \fBGemfile\fR describes the gem dependencies required to execute associated Ruby code\.
+.
+.P
+Place the \fBGemfile\fR in the root of the directory containing the associated code\. For instance, in a Rails application, place the \fBGemfile\fR in the same directory as the \fBRakefile\fR\.
+.
+.SH "SYNTAX"
+A \fBGemfile\fR is evaluated as Ruby code, in a context which makes available a number of methods used to describe the gem requirements\.
+.
+.SH "GLOBAL SOURCES"
+At the top of the \fBGemfile\fR, add a line for the \fBRubygems\fR source that contains the gems listed in the \fBGemfile\fR\.
+.
+.IP "" 4
+.
+.nf
+
+source "https://rubygems\.org"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+It is possible, but not recommended as of Bundler 1\.7, to add multiple global \fBsource\fR lines\. Each of these \fBsource\fRs \fBMUST\fR be a valid Rubygems repository\.
+.
+.P
+Sources are checked for gems following the heuristics described in \fISOURCE PRIORITY\fR\. If a gem is found in more than one global source, Bundler will print a warning after installing the gem indicating which source was used, and listing the other sources where the gem is available\. A specific source can be selected for gems that need to use a non\-standard repository, suppressing this warning, by using the \fI\fB:source\fR option\fR or a \fI\fBsource\fR block\fR\.
+.
+.SS "CREDENTIALS"
+Some gem sources require a username and password\. Use bundle config(1) \fIbundle\-config\.1\.html\fR to set the username and password for any of the sources that need it\. The command must be run once on each computer that will install the Gemfile, but this keeps the credentials from being stored in plain text in version control\.
+.
+.IP "" 4
+.
+.nf
+
+bundle config gems\.example\.com user:password
+.
+.fi
+.
+.IP "" 0
+.
+.P
+For some sources, like a company Gemfury account, it may be easier to include the credentials in the Gemfile as part of the source URL\.
+.
+.IP "" 4
+.
+.nf
+
+source "https://user:password@gems\.example\.com"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Credentials in the source URL will take precedence over credentials set using \fBconfig\fR\.
+.
+.SH "RUBY"
+If your application requires a specific Ruby version or engine, specify your requirements using the \fBruby\fR method, with the following arguments\. All parameters are \fBOPTIONAL\fR unless otherwise specified\.
+.
+.SS "VERSION (required)"
+The version of Ruby that your application requires\. If your application requires an alternate Ruby engine, such as JRuby, Rubinius or TruffleRuby, this should be the Ruby version that the engine is compatible with\.
+.
+.IP "" 4
+.
+.nf
+
+ruby "1\.9\.3"
+.
+.fi
+.
+.IP "" 0
+.
+.SS "ENGINE"
+Each application \fImay\fR specify a Ruby engine\. If an engine is specified, an engine version \fImust\fR also be specified\.
+.
+.P
+What exactly is an Engine? \- A Ruby engine is an implementation of the Ruby language\.
+.
+.IP "\(bu" 4
+For background: the reference or original implementation of the Ruby programming language is called Matz\'s Ruby Interpreter \fIhttps://en\.wikipedia\.org/wiki/Ruby_MRI\fR, or MRI for short\. This is named after Ruby creator Yukihiro Matsumoto, also known as Matz\. MRI is also known as CRuby, because it is written in C\. MRI is the most widely used Ruby engine\.
+.
+.IP "\(bu" 4
+Other implementations \fIhttps://www\.ruby\-lang\.org/en/about/\fR of Ruby exist\. Some of the more well\-known implementations include Rubinius \fIhttps://rubinius\.com/\fR, and JRuby \fIhttp://jruby\.org/\fR\. Rubinius is an alternative implementation of Ruby written in Ruby\. JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine\.
+.
+.IP "" 0
+.
+.SS "ENGINE VERSION"
+Each application \fImay\fR specify a Ruby engine version\. If an engine version is specified, an engine \fImust\fR also be specified\. If the engine is "ruby" the engine version specified \fImust\fR match the Ruby version\.
+.
+.IP "" 4
+.
+.nf
+
+ruby "1\.8\.7", :engine => "jruby", :engine_version => "1\.6\.7"
+.
+.fi
+.
+.IP "" 0
+.
+.SS "PATCHLEVEL"
+Each application \fImay\fR specify a Ruby patchlevel\.
+.
+.IP "" 4
+.
+.nf
+
+ruby "2\.0\.0", :patchlevel => "247"
+.
+.fi
+.
+.IP "" 0
+.
+.SH "GEMS"
+Specify gem requirements using the \fBgem\fR method, with the following arguments\. All parameters are \fBOPTIONAL\fR unless otherwise specified\.
+.
+.SS "NAME (required)"
+For each gem requirement, list a single \fIgem\fR line\.
+.
+.IP "" 4
+.
+.nf
+
+gem "nokogiri"
+.
+.fi
+.
+.IP "" 0
+.
+.SS "VERSION"
+Each \fIgem\fR \fBMAY\fR have one or more version specifiers\.
+.
+.IP "" 4
+.
+.nf
+
+gem "nokogiri", ">= 1\.4\.2"
+gem "RedCloth", ">= 4\.1\.0", "< 4\.2\.0"
+.
+.fi
+.
+.IP "" 0
+.
+.SS "REQUIRE AS"
+Each \fIgem\fR \fBMAY\fR specify files that should be used when autorequiring via \fBBundler\.require\fR\. You may pass an array with multiple files or \fBtrue\fR if the file you want \fBrequired\fR has the same name as \fIgem\fR or \fBfalse\fR to prevent any file from being autorequired\.
+.
+.IP "" 4
+.
+.nf
+
+gem "redis", :require => ["redis/connection/hiredis", "redis"]
+gem "webmock", :require => false
+gem "byebug", :require => true
+.
+.fi
+.
+.IP "" 0
+.
+.P
+The argument defaults to the name of the gem\. For example, these are identical:
+.
+.IP "" 4
+.
+.nf
+
+gem "nokogiri"
+gem "nokogiri", :require => "nokogiri"
+gem "nokogiri", :require => true
+.
+.fi
+.
+.IP "" 0
+.
+.SS "GROUPS"
+Each \fIgem\fR \fBMAY\fR specify membership in one or more groups\. Any \fIgem\fR that does not specify membership in any group is placed in the \fBdefault\fR group\.
+.
+.IP "" 4
+.
+.nf
+
+gem "rspec", :group => :test
+gem "wirble", :groups => [:development, :test]
+.
+.fi
+.
+.IP "" 0
+.
+.P
+The Bundler runtime allows its two main methods, \fBBundler\.setup\fR and \fBBundler\.require\fR, to limit their impact to particular groups\.
+.
+.IP "" 4
+.
+.nf
+
+# setup adds gems to Ruby\'s load path
+Bundler\.setup # defaults to all groups
+require "bundler/setup" # same as Bundler\.setup
+Bundler\.setup(:default) # only set up the _default_ group
+Bundler\.setup(:test) # only set up the _test_ group (but `not` _default_)
+Bundler\.setup(:default, :test) # set up the _default_ and _test_ groups, but no others
+
+# require requires all of the gems in the specified groups
+Bundler\.require # defaults to the _default_ group
+Bundler\.require(:default) # identical
+Bundler\.require(:default, :test) # requires the _default_ and _test_ groups
+Bundler\.require(:test) # requires the _test_ group
+.
+.fi
+.
+.IP "" 0
+.
+.P
+The Bundler CLI allows you to specify a list of groups whose gems \fBbundle install\fR should not install with the \fBwithout\fR configuration\.
+.
+.P
+To specify multiple groups to ignore, specify a list of groups separated by spaces\.
+.
+.IP "" 4
+.
+.nf
+
+bundle config set \-\-local without test
+bundle config set \-\-local without development test
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Also, calling \fBBundler\.setup\fR with no parameters, or calling \fBrequire "bundler/setup"\fR will setup all groups except for the ones you excluded via \fB\-\-without\fR (since they are not available)\.
+.
+.P
+Note that on \fBbundle install\fR, bundler downloads and evaluates all gems, in order to create a single canonical list of all of the required gems and their dependencies\. This means that you cannot list different versions of the same gems in different groups\. For more details, see Understanding Bundler \fIhttps://bundler\.io/rationale\.html\fR\.
+.
+.SS "PLATFORMS"
+If a gem should only be used in a particular platform or set of platforms, you can specify them\. Platforms are essentially identical to groups, except that you do not need to use the \fB\-\-without\fR install\-time flag to exclude groups of gems for other platforms\.
+.
+.P
+There are a number of \fBGemfile\fR platforms:
+.
+.TP
+\fBruby\fR
+C Ruby (MRI), Rubinius or TruffleRuby, but \fBNOT\fR Windows
+.
+.TP
+\fBmri\fR
+Same as \fIruby\fR, but only C Ruby (MRI)
+.
+.TP
+\fBmingw\fR
+Windows 32 bit \'mingw32\' platform (aka RubyInstaller)
+.
+.TP
+\fBx64_mingw\fR
+Windows 64 bit \'mingw32\' platform (aka RubyInstaller x64)
+.
+.TP
+\fBrbx\fR
+Rubinius
+.
+.TP
+\fBjruby\fR
+JRuby
+.
+.TP
+\fBtruffleruby\fR
+TruffleRuby
+.
+.TP
+\fBmswin\fR
+Windows
+.
+.P
+You can restrict further by platform and version for all platforms \fIexcept\fR for \fBrbx\fR, \fBjruby\fR, \fBtruffleruby\fR and \fBmswin\fR\.
+.
+.P
+To specify a version in addition to a platform, append the version number without the delimiter to the platform\. For example, to specify that a gem should only be used on platforms with Ruby 2\.3, use:
+.
+.IP "" 4
+.
+.nf
+
+ruby_23
+.
+.fi
+.
+.IP "" 0
+.
+.P
+The full list of platforms and supported versions includes:
+.
+.TP
+\fBruby\fR
+1\.8, 1\.9, 2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
+.
+.TP
+\fBmri\fR
+1\.8, 1\.9, 2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
+.
+.TP
+\fBmingw\fR
+1\.8, 1\.9, 2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
+.
+.TP
+\fBx64_mingw\fR
+2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
+.
+.P
+As with groups, you can specify one or more platforms:
+.
+.IP "" 4
+.
+.nf
+
+gem "weakling", :platforms => :jruby
+gem "ruby\-debug", :platforms => :mri_18
+gem "nokogiri", :platforms => [:mri_18, :jruby]
+.
+.fi
+.
+.IP "" 0
+.
+.P
+All operations involving groups (\fBbundle install\fR \fIbundle\-install\.1\.html\fR, \fBBundler\.setup\fR, \fBBundler\.require\fR) behave exactly the same as if any groups not matching the current platform were explicitly excluded\.
+.
+.SS "SOURCE"
+You can select an alternate Rubygems repository for a gem using the \':source\' option\.
+.
+.IP "" 4
+.
+.nf
+
+gem "some_internal_gem", :source => "https://gems\.example\.com"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+This forces the gem to be loaded from this source and ignores any global sources declared at the top level of the file\. If the gem does not exist in this source, it will not be installed\.
+.
+.P
+Bundler will search for child dependencies of this gem by first looking in the source selected for the parent, but if they are not found there, it will fall back on global sources using the ordering described in \fISOURCE PRIORITY\fR\.
+.
+.P
+Selecting a specific source repository this way also suppresses the ambiguous gem warning described above in \fIGLOBAL SOURCES (#source)\fR\.
+.
+.P
+Using the \fB:source\fR option for an individual gem will also make that source available as a possible global source for any other gems which do not specify explicit sources\. Thus, when adding gems with explicit sources, it is recommended that you also ensure all other gems in the Gemfile are using explicit sources\.
+.
+.SS "GIT"
+If necessary, you can specify that a gem is located at a particular git repository using the \fB:git\fR parameter\. The repository can be accessed via several protocols:
+.
+.TP
+\fBHTTP(S)\fR
+gem "rails", :git => "https://github\.com/rails/rails\.git"
+.
+.TP
+\fBSSH\fR
+gem "rails", :git => "git@github\.com:rails/rails\.git"
+.
+.TP
+\fBgit\fR
+gem "rails", :git => "git://github\.com/rails/rails\.git"
+.
+.P
+If using SSH, the user that you use to run \fBbundle install\fR \fBMUST\fR have the appropriate keys available in their \fB$HOME/\.ssh\fR\.
+.
+.P
+\fBNOTE\fR: \fBhttp://\fR and \fBgit://\fR URLs should be avoided if at all possible\. These protocols are unauthenticated, so a man\-in\-the\-middle attacker can deliver malicious code and compromise your system\. HTTPS and SSH are strongly preferred\.
+.
+.P
+The \fBgroup\fR, \fBplatforms\fR, and \fBrequire\fR options are available and behave exactly the same as they would for a normal gem\.
+.
+.P
+A git repository \fBSHOULD\fR have at least one file, at the root of the directory containing the gem, with the extension \fB\.gemspec\fR\. This file \fBMUST\fR contain a valid gem specification, as expected by the \fBgem build\fR command\.
+.
+.P
+If a git repository does not have a \fB\.gemspec\fR, bundler will attempt to create one, but it will not contain any dependencies, executables, or C extension compilation instructions\. As a result, it may fail to properly integrate into your application\.
+.
+.P
+If a git repository does have a \fB\.gemspec\fR for the gem you attached it to, a version specifier, if provided, means that the git repository is only valid if the \fB\.gemspec\fR specifies a version matching the version specifier\. If not, bundler will print a warning\.
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", "2\.3\.8", :git => "https://github\.com/rails/rails\.git"
+# bundle install will fail, because the \.gemspec in the rails
+# repository\'s master branch specifies version 3\.0\.0
+.
+.fi
+.
+.IP "" 0
+.
+.P
+If a git repository does \fBnot\fR have a \fB\.gemspec\fR for the gem you attached it to, a version specifier \fBMUST\fR be provided\. Bundler will use this version in the simple \fB\.gemspec\fR it creates\.
+.
+.P
+Git repositories support a number of additional options\.
+.
+.TP
+\fBbranch\fR, \fBtag\fR, and \fBref\fR
+You \fBMUST\fR only specify at most one of these options\. The default is \fB:branch => "master"\fR\. For example:
+.
+.IP
+gem "rails", :git => "https://github\.com/rails/rails\.git", :branch => "5\-0\-stable"
+.
+.IP
+gem "rails", :git => "https://github\.com/rails/rails\.git", :tag => "v5\.0\.0"
+.
+.IP
+gem "rails", :git => "https://github\.com/rails/rails\.git", :ref => "4aded"
+.
+.TP
+\fBsubmodules\fR
+For reference, a git submodule \fIhttps://git\-scm\.com/book/en/v2/Git\-Tools\-Submodules\fR lets you have another git repository within a subfolder of your repository\. Specify \fB:submodules => true\fR to cause bundler to expand any submodules included in the git repository
+.
+.P
+If a git repository contains multiple \fB\.gemspecs\fR, each \fB\.gemspec\fR represents a gem located at the same place in the file system as the \fB\.gemspec\fR\.
+.
+.IP "" 4
+.
+.nf
+
+|~rails [git root]
+| |\-rails\.gemspec [rails gem located here]
+|~actionpack
+| |\-actionpack\.gemspec [actionpack gem located here]
+|~activesupport
+| |\-activesupport\.gemspec [activesupport gem located here]
+|\.\.\.
+.
+.fi
+.
+.IP "" 0
+.
+.P
+To install a gem located in a git repository, bundler changes to the directory containing the gemspec, runs \fBgem build name\.gemspec\fR and then installs the resulting gem\. The \fBgem build\fR command, which comes standard with Rubygems, evaluates the \fB\.gemspec\fR in the context of the directory in which it is located\.
+.
+.SS "GIT SOURCE"
+A custom git source can be defined via the \fBgit_source\fR method\. Provide the source\'s name as an argument, and a block which receives a single argument and interpolates it into a string to return the full repo address:
+.
+.IP "" 4
+.
+.nf
+
+git_source(:stash){ |repo_name| "https://stash\.corp\.acme\.pl/#{repo_name}\.git" }
+gem \'rails\', :stash => \'forks/rails\'
+.
+.fi
+.
+.IP "" 0
+.
+.P
+In addition, if you wish to choose a specific branch:
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", :stash => "forks/rails", :branch => "branch_name"
+.
+.fi
+.
+.IP "" 0
+.
+.SS "GITHUB"
+\fBNOTE\fR: This shorthand should be avoided until Bundler 2\.0, since it currently expands to an insecure \fBgit://\fR URL\. This allows a man\-in\-the\-middle attacker to compromise your system\.
+.
+.P
+If the git repository you want to use is hosted on GitHub and is public, you can use the :github shorthand to specify the github username and repository name (without the trailing "\.git"), separated by a slash\. If both the username and repository name are the same, you can omit one\.
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", :github => "rails/rails"
+gem "rails", :github => "rails"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Are both equivalent to
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", :git => "git://github\.com/rails/rails\.git"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Since the \fBgithub\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
+.
+.P
+You can also directly pass a pull request URL:
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", :github => "https://github\.com/rails/rails/pull/43753"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Which is equivalent to:
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", :github => "rails/rails", branch: "refs/pull/43753/head"
+.
+.fi
+.
+.IP "" 0
+.
+.SS "GIST"
+If the git repository you want to use is hosted as a Github Gist and is public, you can use the :gist shorthand to specify the gist identifier (without the trailing "\.git")\.
+.
+.IP "" 4
+.
+.nf
+
+gem "the_hatch", :gist => "4815162342"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Is equivalent to:
+.
+.IP "" 4
+.
+.nf
+
+gem "the_hatch", :git => "https://gist\.github\.com/4815162342\.git"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Since the \fBgist\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
+.
+.SS "BITBUCKET"
+If the git repository you want to use is hosted on Bitbucket and is public, you can use the :bitbucket shorthand to specify the bitbucket username and repository name (without the trailing "\.git"), separated by a slash\. If both the username and repository name are the same, you can omit one\.
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", :bitbucket => "rails/rails"
+gem "rails", :bitbucket => "rails"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Are both equivalent to
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", :git => "https://rails@bitbucket\.org/rails/rails\.git"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+Since the \fBbitbucket\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
+.
+.SS "PATH"
+You can specify that a gem is located in a particular location on the file system\. Relative paths are resolved relative to the directory containing the \fBGemfile\fR\.
+.
+.P
+Similar to the semantics of the \fB:git\fR option, the \fB:path\fR option requires that the directory in question either contains a \fB\.gemspec\fR for the gem, or that you specify an explicit version that bundler should use\.
+.
+.P
+Unlike \fB:git\fR, bundler does not compile C extensions for gems specified as paths\.
+.
+.IP "" 4
+.
+.nf
+
+gem "rails", :path => "vendor/rails"
+.
+.fi
+.
+.IP "" 0
+.
+.P
+If you would like to use multiple local gems directly from the filesystem, you can set a global \fBpath\fR option to the path containing the gem\'s files\. This will automatically load gemspec files from subdirectories\.
+.
+.IP "" 4
+.
+.nf
+
+path \'components\' do
+ gem \'admin_ui\'
+ gem \'public_ui\'
+end
+.
+.fi
+.
+.IP "" 0
+.
+.SH "BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS"
+The \fB:source\fR, \fB:git\fR, \fB:path\fR, \fB:group\fR, and \fB:platforms\fR options may be applied to a group of gems by using block form\.
+.
+.IP "" 4
+.
+.nf
+
+source "https://gems\.example\.com" do
+ gem "some_internal_gem"
+ gem "another_internal_gem"
+end
+
+git "https://github\.com/rails/rails\.git" do
+ gem "activesupport"
+ gem "actionpack"
+end
+
+platforms :ruby do
+ gem "ruby\-debug"
+ gem "sqlite3"
+end
+
+group :development, :optional => true do
+ gem "wirble"
+ gem "faker"
+end
+.
+.fi
+.
+.IP "" 0
+.
+.P
+In the case of the group block form the :optional option can be given to prevent a group from being installed unless listed in the \fB\-\-with\fR option given to the \fBbundle install\fR command\.
+.
+.P
+In the case of the \fBgit\fR block form, the \fB:ref\fR, \fB:branch\fR, \fB:tag\fR, and \fB:submodules\fR options may be passed to the \fBgit\fR method, and all gems in the block will inherit those options\.
+.
+.P
+The presence of a \fBsource\fR block in a Gemfile also makes that source available as a possible global source for any other gems which do not specify explicit sources\. Thus, when defining source blocks, it is recommended that you also ensure all other gems in the Gemfile are using explicit sources, either via source blocks or \fB:source\fR directives on individual gems\.
+.
+.SH "INSTALL_IF"
+The \fBinstall_if\fR method allows gems to be installed based on a proc or lambda\. This is especially useful for optional gems that can only be used if certain software is installed or some other conditions are met\.
+.
+.IP "" 4
+.
+.nf
+
+install_if \-> { RUBY_PLATFORM =~ /darwin/ } do
+ gem "pasteboard"
+end
+.
+.fi
+.
+.IP "" 0
+.
+.SH "GEMSPEC"
+The \fB\.gemspec\fR \fIhttp://guides\.rubygems\.org/specification\-reference/\fR file is where you provide metadata about your gem to Rubygems\. Some required Gemspec attributes include the name, description, and homepage of your gem\. This is also where you specify the dependencies your gem needs to run\.
+.
+.P
+If you wish to use Bundler to help install dependencies for a gem while it is being developed, use the \fBgemspec\fR method to pull in the dependencies listed in the \fB\.gemspec\fR file\.
+.
+.P
+The \fBgemspec\fR method adds any runtime dependencies as gem requirements in the default group\. It also adds development dependencies as gem requirements in the \fBdevelopment\fR group\. Finally, it adds a gem requirement on your project (\fB:path => \'\.\'\fR)\. In conjunction with \fBBundler\.setup\fR, this allows you to require project files in your test code as you would if the project were installed as a gem; you need not manipulate the load path manually or require project files via relative paths\.
+.
+.P
+The \fBgemspec\fR method supports optional \fB:path\fR, \fB:glob\fR, \fB:name\fR, and \fB:development_group\fR options, which control where bundler looks for the \fB\.gemspec\fR, the glob it uses to look for the gemspec (defaults to: "{,\fI,\fR/*}\.gemspec"), what named \fB\.gemspec\fR it uses (if more than one is present), and which group development dependencies are included in\.
+.
+.P
+When a \fBgemspec\fR dependency encounters version conflicts during resolution, the local version under development will always be selected \-\- even if there are remote versions that better match other requirements for the \fBgemspec\fR gem\.
+.
+.SH "SOURCE PRIORITY"
+When attempting to locate a gem to satisfy a gem requirement, bundler uses the following priority order:
+.
+.IP "1." 4
+The source explicitly attached to the gem (using \fB:source\fR, \fB:path\fR, or \fB:git\fR)
+.
+.IP "2." 4
+For implicit gems (dependencies of explicit gems), any source, git, or path repository declared on the parent\. This results in bundler prioritizing the ActiveSupport gem from the Rails git repository over ones from \fBrubygems\.org\fR
+.
+.IP "3." 4
+The sources specified via global \fBsource\fR lines, searching each source in your \fBGemfile\fR from last added to first added\.
+.
+.IP "" 0
+
diff --git a/lib/bundler/man/gemfile.5.ronn b/lib/bundler/man/gemfile.5.ronn
new file mode 100644
index 0000000000..20ce3242ae
--- /dev/null
+++ b/lib/bundler/man/gemfile.5.ronn
@@ -0,0 +1,525 @@
+Gemfile(5) -- A format for describing gem dependencies for Ruby programs
+========================================================================
+
+## SYNOPSIS
+
+A `Gemfile` describes the gem dependencies required to execute associated
+Ruby code.
+
+Place the `Gemfile` in the root of the directory containing the associated
+code. For instance, in a Rails application, place the `Gemfile` in the same
+directory as the `Rakefile`.
+
+## SYNTAX
+
+A `Gemfile` is evaluated as Ruby code, in a context which makes available
+a number of methods used to describe the gem requirements.
+
+## GLOBAL SOURCES
+
+At the top of the `Gemfile`, add a line for the `Rubygems` source that contains
+the gems listed in the `Gemfile`.
+
+ source "https://rubygems.org"
+
+It is possible, but not recommended as of Bundler 1.7, to add multiple global
+`source` lines. Each of these `source`s `MUST` be a valid Rubygems repository.
+
+Sources are checked for gems following the heuristics described in
+[SOURCE PRIORITY][]. If a gem is found in more than one global source, Bundler
+will print a warning after installing the gem indicating which source was used,
+and listing the other sources where the gem is available. A specific source can
+be selected for gems that need to use a non-standard repository, suppressing
+this warning, by using the [`:source` option](#SOURCE) or a
+[`source` block](#BLOCK-FORM-OF-SOURCE-GIT-PATH-GROUP-and-PLATFORMS).
+
+### CREDENTIALS
+
+Some gem sources require a username and password. Use [bundle config(1)](bundle-config.1.html) to set
+the username and password for any of the sources that need it. The command must
+be run once on each computer that will install the Gemfile, but this keeps the
+credentials from being stored in plain text in version control.
+
+ bundle config gems.example.com user:password
+
+For some sources, like a company Gemfury account, it may be easier to
+include the credentials in the Gemfile as part of the source URL.
+
+ source "https://user:password@gems.example.com"
+
+Credentials in the source URL will take precedence over credentials set using
+`config`.
+
+## RUBY
+
+If your application requires a specific Ruby version or engine, specify your
+requirements using the `ruby` method, with the following arguments.
+All parameters are `OPTIONAL` unless otherwise specified.
+
+### VERSION (required)
+
+The version of Ruby that your application requires. If your application
+requires an alternate Ruby engine, such as JRuby, Rubinius or TruffleRuby, this
+should be the Ruby version that the engine is compatible with.
+
+ ruby "1.9.3"
+
+### ENGINE
+
+Each application _may_ specify a Ruby engine. If an engine is specified, an
+engine version _must_ also be specified.
+
+What exactly is an Engine?
+ - A Ruby engine is an implementation of the Ruby language.
+
+ - For background: the reference or original implementation of the Ruby
+ programming language is called
+ [Matz's Ruby Interpreter](https://en.wikipedia.org/wiki/Ruby_MRI), or MRI
+ for short. This is named after Ruby creator Yukihiro Matsumoto,
+ also known as Matz. MRI is also known as CRuby, because it is written in C.
+ MRI is the most widely used Ruby engine.
+
+ - [Other implementations](https://www.ruby-lang.org/en/about/) of Ruby exist.
+ Some of the more well-known implementations include
+ [Rubinius](https://rubinius.com/), and [JRuby](http://jruby.org/).
+ Rubinius is an alternative implementation of Ruby written in Ruby.
+ JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine.
+
+### ENGINE VERSION
+
+Each application _may_ specify a Ruby engine version. If an engine version is
+specified, an engine _must_ also be specified. If the engine is "ruby" the
+engine version specified _must_ match the Ruby version.
+
+ ruby "1.8.7", :engine => "jruby", :engine_version => "1.6.7"
+
+### PATCHLEVEL
+
+Each application _may_ specify a Ruby patchlevel.
+
+ ruby "2.0.0", :patchlevel => "247"
+
+## GEMS
+
+Specify gem requirements using the `gem` method, with the following arguments.
+All parameters are `OPTIONAL` unless otherwise specified.
+
+### NAME (required)
+
+For each gem requirement, list a single _gem_ line.
+
+ gem "nokogiri"
+
+### VERSION
+
+Each _gem_ `MAY` have one or more version specifiers.
+
+ gem "nokogiri", ">= 1.4.2"
+ gem "RedCloth", ">= 4.1.0", "< 4.2.0"
+
+### REQUIRE AS
+
+Each _gem_ `MAY` specify files that should be used when autorequiring via
+`Bundler.require`. You may pass an array with multiple files or `true` if the file
+you want `required` has the same name as _gem_ or `false` to
+prevent any file from being autorequired.
+
+ gem "redis", :require => ["redis/connection/hiredis", "redis"]
+ gem "webmock", :require => false
+ gem "byebug", :require => true
+
+The argument defaults to the name of the gem. For example, these are identical:
+
+ gem "nokogiri"
+ gem "nokogiri", :require => "nokogiri"
+ gem "nokogiri", :require => true
+
+### GROUPS
+
+Each _gem_ `MAY` specify membership in one or more groups. Any _gem_ that does
+not specify membership in any group is placed in the `default` group.
+
+ gem "rspec", :group => :test
+ gem "wirble", :groups => [:development, :test]
+
+The Bundler runtime allows its two main methods, `Bundler.setup` and
+`Bundler.require`, to limit their impact to particular groups.
+
+ # setup adds gems to Ruby's load path
+ Bundler.setup # defaults to all groups
+ require "bundler/setup" # same as Bundler.setup
+ Bundler.setup(:default) # only set up the _default_ group
+ Bundler.setup(:test) # only set up the _test_ group (but `not` _default_)
+ Bundler.setup(:default, :test) # set up the _default_ and _test_ groups, but no others
+
+ # require requires all of the gems in the specified groups
+ Bundler.require # defaults to the _default_ group
+ Bundler.require(:default) # identical
+ Bundler.require(:default, :test) # requires the _default_ and _test_ groups
+ Bundler.require(:test) # requires the _test_ group
+
+The Bundler CLI allows you to specify a list of groups whose gems `bundle install` should
+not install with the `without` configuration.
+
+To specify multiple groups to ignore, specify a list of groups separated by spaces.
+
+ bundle config set --local without test
+ bundle config set --local without development test
+
+Also, calling `Bundler.setup` with no parameters, or calling `require "bundler/setup"`
+will setup all groups except for the ones you excluded via `--without` (since they
+are not available).
+
+Note that on `bundle install`, bundler downloads and evaluates all gems, in order to
+create a single canonical list of all of the required gems and their dependencies.
+This means that you cannot list different versions of the same gems in different
+groups. For more details, see [Understanding Bundler](https://bundler.io/rationale.html).
+
+### PLATFORMS
+
+If a gem should only be used in a particular platform or set of platforms, you can
+specify them. Platforms are essentially identical to groups, except that you do not
+need to use the `--without` install-time flag to exclude groups of gems for other
+platforms.
+
+There are a number of `Gemfile` platforms:
+
+ * `ruby`:
+ C Ruby (MRI), Rubinius or TruffleRuby, but `NOT` Windows
+ * `mri`:
+ Same as _ruby_, but only C Ruby (MRI)
+ * `mingw`:
+ Windows 32 bit 'mingw32' platform (aka RubyInstaller)
+ * `x64_mingw`:
+ Windows 64 bit 'mingw32' platform (aka RubyInstaller x64)
+ * `rbx`:
+ Rubinius
+ * `jruby`:
+ JRuby
+ * `truffleruby`:
+ TruffleRuby
+ * `mswin`:
+ Windows
+
+You can restrict further by platform and version for all platforms *except* for
+`rbx`, `jruby`, `truffleruby` and `mswin`.
+
+To specify a version in addition to a platform, append the version number without
+the delimiter to the platform. For example, to specify that a gem should only be
+used on platforms with Ruby 2.3, use:
+
+ ruby_23
+
+The full list of platforms and supported versions includes:
+
+ * `ruby`:
+ 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
+ * `mri`:
+ 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
+ * `mingw`:
+ 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
+ * `x64_mingw`:
+ 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
+
+As with groups, you can specify one or more platforms:
+
+ gem "weakling", :platforms => :jruby
+ gem "ruby-debug", :platforms => :mri_18
+ gem "nokogiri", :platforms => [:mri_18, :jruby]
+
+All operations involving groups ([`bundle install`](bundle-install.1.html), `Bundler.setup`,
+`Bundler.require`) behave exactly the same as if any groups not
+matching the current platform were explicitly excluded.
+
+### SOURCE
+
+You can select an alternate Rubygems repository for a gem using the ':source'
+option.
+
+ gem "some_internal_gem", :source => "https://gems.example.com"
+
+This forces the gem to be loaded from this source and ignores any global sources
+declared at the top level of the file. If the gem does not exist in this source,
+it will not be installed.
+
+Bundler will search for child dependencies of this gem by first looking in the
+source selected for the parent, but if they are not found there, it will fall
+back on global sources using the ordering described in [SOURCE PRIORITY][].
+
+Selecting a specific source repository this way also suppresses the ambiguous
+gem warning described above in
+[GLOBAL SOURCES (#source)](#GLOBAL-SOURCES).
+
+Using the `:source` option for an individual gem will also make that source
+available as a possible global source for any other gems which do not specify
+explicit sources. Thus, when adding gems with explicit sources, it is
+recommended that you also ensure all other gems in the Gemfile are using
+explicit sources.
+
+### GIT
+
+If necessary, you can specify that a gem is located at a particular
+git repository using the `:git` parameter. The repository can be accessed via
+several protocols:
+
+ * `HTTP(S)`:
+ gem "rails", :git => "https://github.com/rails/rails.git"
+ * `SSH`:
+ gem "rails", :git => "git@github.com:rails/rails.git"
+ * `git`:
+ gem "rails", :git => "git://github.com/rails/rails.git"
+
+If using SSH, the user that you use to run `bundle install` `MUST` have the
+appropriate keys available in their `$HOME/.ssh`.
+
+`NOTE`: `http://` and `git://` URLs should be avoided if at all possible. These
+protocols are unauthenticated, so a man-in-the-middle attacker can deliver
+malicious code and compromise your system. HTTPS and SSH are strongly
+preferred.
+
+The `group`, `platforms`, and `require` options are available and behave
+exactly the same as they would for a normal gem.
+
+A git repository `SHOULD` have at least one file, at the root of the
+directory containing the gem, with the extension `.gemspec`. This file
+`MUST` contain a valid gem specification, as expected by the `gem build`
+command.
+
+If a git repository does not have a `.gemspec`, bundler will attempt to
+create one, but it will not contain any dependencies, executables, or
+C extension compilation instructions. As a result, it may fail to properly
+integrate into your application.
+
+If a git repository does have a `.gemspec` for the gem you attached it
+to, a version specifier, if provided, means that the git repository is
+only valid if the `.gemspec` specifies a version matching the version
+specifier. If not, bundler will print a warning.
+
+ gem "rails", "2.3.8", :git => "https://github.com/rails/rails.git"
+ # bundle install will fail, because the .gemspec in the rails
+ # repository's master branch specifies version 3.0.0
+
+If a git repository does `not` have a `.gemspec` for the gem you attached
+it to, a version specifier `MUST` be provided. Bundler will use this
+version in the simple `.gemspec` it creates.
+
+Git repositories support a number of additional options.
+
+ * `branch`, `tag`, and `ref`:
+ You `MUST` only specify at most one of these options. The default
+ is `:branch => "master"`. For example:
+
+ gem "rails", :git => "https://github.com/rails/rails.git", :branch => "5-0-stable"
+
+ gem "rails", :git => "https://github.com/rails/rails.git", :tag => "v5.0.0"
+
+ gem "rails", :git => "https://github.com/rails/rails.git", :ref => "4aded"
+
+ * `submodules`:
+ For reference, a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules)
+ lets you have another git repository within a subfolder of your repository.
+ Specify `:submodules => true` to cause bundler to expand any
+ submodules included in the git repository
+
+If a git repository contains multiple `.gemspecs`, each `.gemspec`
+represents a gem located at the same place in the file system as
+the `.gemspec`.
+
+ |~rails [git root]
+ | |-rails.gemspec [rails gem located here]
+ |~actionpack
+ | |-actionpack.gemspec [actionpack gem located here]
+ |~activesupport
+ | |-activesupport.gemspec [activesupport gem located here]
+ |...
+
+To install a gem located in a git repository, bundler changes to
+the directory containing the gemspec, runs `gem build name.gemspec`
+and then installs the resulting gem. The `gem build` command,
+which comes standard with Rubygems, evaluates the `.gemspec` in
+the context of the directory in which it is located.
+
+### GIT SOURCE
+
+A custom git source can be defined via the `git_source` method. Provide the source's name
+as an argument, and a block which receives a single argument and interpolates it into a
+string to return the full repo address:
+
+ git_source(:stash){ |repo_name| "https://stash.corp.acme.pl/#{repo_name}.git" }
+ gem 'rails', :stash => 'forks/rails'
+
+In addition, if you wish to choose a specific branch:
+
+ gem "rails", :stash => "forks/rails", :branch => "branch_name"
+
+### GITHUB
+
+`NOTE`: This shorthand should be avoided until Bundler 2.0, since it
+currently expands to an insecure `git://` URL. This allows a
+man-in-the-middle attacker to compromise your system.
+
+If the git repository you want to use is hosted on GitHub and is public, you can use the
+:github shorthand to specify the github username and repository name (without the
+trailing ".git"), separated by a slash. If both the username and repository name are the
+same, you can omit one.
+
+ gem "rails", :github => "rails/rails"
+ gem "rails", :github => "rails"
+
+Are both equivalent to
+
+ gem "rails", :git => "git://github.com/rails/rails.git"
+
+Since the `github` method is a specialization of `git_source`, it accepts a `:branch` named argument.
+
+You can also directly pass a pull request URL:
+
+ gem "rails", :github => "https://github.com/rails/rails/pull/43753"
+
+Which is equivalent to:
+
+ gem "rails", :github => "rails/rails", branch: "refs/pull/43753/head"
+
+### GIST
+
+If the git repository you want to use is hosted as a Github Gist and is public, you can use
+the :gist shorthand to specify the gist identifier (without the trailing ".git").
+
+ gem "the_hatch", :gist => "4815162342"
+
+Is equivalent to:
+
+ gem "the_hatch", :git => "https://gist.github.com/4815162342.git"
+
+Since the `gist` method is a specialization of `git_source`, it accepts a `:branch` named argument.
+
+### BITBUCKET
+
+If the git repository you want to use is hosted on Bitbucket and is public, you can use the
+:bitbucket shorthand to specify the bitbucket username and repository name (without the
+trailing ".git"), separated by a slash. If both the username and repository name are the
+same, you can omit one.
+
+ gem "rails", :bitbucket => "rails/rails"
+ gem "rails", :bitbucket => "rails"
+
+Are both equivalent to
+
+ gem "rails", :git => "https://rails@bitbucket.org/rails/rails.git"
+
+Since the `bitbucket` method is a specialization of `git_source`, it accepts a `:branch` named argument.
+
+### PATH
+
+You can specify that a gem is located in a particular location
+on the file system. Relative paths are resolved relative to the
+directory containing the `Gemfile`.
+
+Similar to the semantics of the `:git` option, the `:path`
+option requires that the directory in question either contains
+a `.gemspec` for the gem, or that you specify an explicit
+version that bundler should use.
+
+Unlike `:git`, bundler does not compile C extensions for
+gems specified as paths.
+
+ gem "rails", :path => "vendor/rails"
+
+If you would like to use multiple local gems directly from the filesystem, you can set a global `path` option to the path containing the gem's files. This will automatically load gemspec files from subdirectories.
+
+ path 'components' do
+ gem 'admin_ui'
+ gem 'public_ui'
+ end
+
+## BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS
+
+The `:source`, `:git`, `:path`, `:group`, and `:platforms` options may be
+applied to a group of gems by using block form.
+
+ source "https://gems.example.com" do
+ gem "some_internal_gem"
+ gem "another_internal_gem"
+ end
+
+ git "https://github.com/rails/rails.git" do
+ gem "activesupport"
+ gem "actionpack"
+ end
+
+ platforms :ruby do
+ gem "ruby-debug"
+ gem "sqlite3"
+ end
+
+ group :development, :optional => true do
+ gem "wirble"
+ gem "faker"
+ end
+
+In the case of the group block form the :optional option can be given
+to prevent a group from being installed unless listed in the `--with`
+option given to the `bundle install` command.
+
+In the case of the `git` block form, the `:ref`, `:branch`, `:tag`,
+and `:submodules` options may be passed to the `git` method, and
+all gems in the block will inherit those options.
+
+The presence of a `source` block in a Gemfile also makes that source
+available as a possible global source for any other gems which do not specify
+explicit sources. Thus, when defining source blocks, it is
+recommended that you also ensure all other gems in the Gemfile are using
+explicit sources, either via source blocks or `:source` directives on
+individual gems.
+
+## INSTALL_IF
+
+The `install_if` method allows gems to be installed based on a proc or lambda.
+This is especially useful for optional gems that can only be used if certain
+software is installed or some other conditions are met.
+
+ install_if -> { RUBY_PLATFORM =~ /darwin/ } do
+ gem "pasteboard"
+ end
+
+## GEMSPEC
+
+The [`.gemspec`](http://guides.rubygems.org/specification-reference/) file is where
+ you provide metadata about your gem to Rubygems. Some required Gemspec
+ attributes include the name, description, and homepage of your gem. This is
+ also where you specify the dependencies your gem needs to run.
+
+If you wish to use Bundler to help install dependencies for a gem while it is
+being developed, use the `gemspec` method to pull in the dependencies listed in
+the `.gemspec` file.
+
+The `gemspec` method adds any runtime dependencies as gem requirements in the
+default group. It also adds development dependencies as gem requirements in the
+`development` group. Finally, it adds a gem requirement on your project (`:path
+=> '.'`). In conjunction with `Bundler.setup`, this allows you to require project
+files in your test code as you would if the project were installed as a gem; you
+need not manipulate the load path manually or require project files via relative
+paths.
+
+The `gemspec` method supports optional `:path`, `:glob`, `:name`, and `:development_group`
+options, which control where bundler looks for the `.gemspec`, the glob it uses to look
+for the gemspec (defaults to: "{,*,*/*}.gemspec"), what named `.gemspec` it uses
+(if more than one is present), and which group development dependencies are included in.
+
+When a `gemspec` dependency encounters version conflicts during resolution, the
+local version under development will always be selected -- even if there are
+remote versions that better match other requirements for the `gemspec` gem.
+
+## SOURCE PRIORITY
+
+When attempting to locate a gem to satisfy a gem requirement,
+bundler uses the following priority order:
+
+ 1. The source explicitly attached to the gem (using `:source`, `:path`, or
+ `:git`)
+ 2. For implicit gems (dependencies of explicit gems), any source, git, or path
+ repository declared on the parent. This results in bundler prioritizing the
+ ActiveSupport gem from the Rails git repository over ones from
+ `rubygems.org`
+ 3. The sources specified via global `source` lines, searching each source in
+ your `Gemfile` from last added to first added.
diff --git a/lib/bundler/man/index.txt b/lib/bundler/man/index.txt
new file mode 100644
index 0000000000..ef2956b2f9
--- /dev/null
+++ b/lib/bundler/man/index.txt
@@ -0,0 +1,25 @@
+Gemfile(5) gemfile.5
+bundle(1) bundle.1
+bundle-add(1) bundle-add.1
+bundle-binstubs(1) bundle-binstubs.1
+bundle-cache(1) bundle-cache.1
+bundle-check(1) bundle-check.1
+bundle-clean(1) bundle-clean.1
+bundle-config(1) bundle-config.1
+bundle-doctor(1) bundle-doctor.1
+bundle-exec(1) bundle-exec.1
+bundle-gem(1) bundle-gem.1
+bundle-info(1) bundle-info.1
+bundle-init(1) bundle-init.1
+bundle-inject(1) bundle-inject.1
+bundle-install(1) bundle-install.1
+bundle-list(1) bundle-list.1
+bundle-lock(1) bundle-lock.1
+bundle-open(1) bundle-open.1
+bundle-outdated(1) bundle-outdated.1
+bundle-platform(1) bundle-platform.1
+bundle-pristine(1) bundle-pristine.1
+bundle-remove(1) bundle-remove.1
+bundle-show(1) bundle-show.1
+bundle-update(1) bundle-update.1
+bundle-viz(1) bundle-viz.1
diff --git a/lib/bundler/mirror.rb b/lib/bundler/mirror.rb
index 0e554bcc3f..a63b45b47d 100644
--- a/lib/bundler/mirror.rb
+++ b/lib/bundler/mirror.rb
@@ -43,7 +43,7 @@ module Bundler
config.update_mirror(mirror)
end
- private
+ private
def fetch_valid_mirror_for(uri)
downcased = uri.to_s.downcase
@@ -158,7 +158,7 @@ module Bundler
end
end
- private
+ private
def wait_for_writtable_socket(socket, address, timeout)
if IO.select(nil, [socket], nil, timeout)
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index f4dd435df4..158c69e1a1 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -13,10 +13,11 @@ module Bundler
class MalformattedPlugin < PluginError; end
class UndefinedCommandError < PluginError; end
class UnknownSourceError < PluginError; end
+ class PluginInstallError < PluginError; end
PLUGIN_FILE_NAME = "plugins.rb".freeze
- module_function
+ module_function
def reset!
instance_variables.each {|i| remove_instance_variable(i) }
@@ -38,13 +39,37 @@ module Bundler
specs = Installer.new.install(names, options)
save_plugins names, specs
- rescue PluginError => e
- if specs
- specs_to_delete = Hash[specs.select {|k, _v| names.include?(k) && !index.commands.values.include?(k) }]
- specs_to_delete.values.each {|spec| Bundler.rm_rf(spec.full_gem_path) }
+ rescue PluginError
+ specs_to_delete = specs.select {|k, _v| names.include?(k) && !index.commands.values.include?(k) }
+ specs_to_delete.each_value {|spec| Bundler.rm_rf(spec.full_gem_path) }
+
+ raise
+ end
+
+ # Uninstalls plugins by the given names
+ #
+ # @param [Array<String>] names the names of plugins to be uninstalled
+ def uninstall(names, options)
+ if names.empty? && !options[:all]
+ Bundler.ui.error "No plugins to uninstall. Specify at least 1 plugin to uninstall.\n"\
+ "Use --all option to uninstall all the installed plugins."
+ return
end
- Bundler.ui.error "Failed to install plugin #{name}: #{e.message}\n #{e.backtrace.join("\n ")}"
+ names = index.installed_plugins if options[:all]
+ if names.any?
+ names.each do |name|
+ if index.installed?(name)
+ Bundler.rm_rf(index.plugin_path(name))
+ index.unregister_plugin(name)
+ Bundler.ui.info "Uninstalled plugin #{name}"
+ else
+ Bundler.ui.error "Plugin #{name} is not installed \n"
+ end
+ end
+ else
+ Bundler.ui.info "No plugins installed"
+ end
end
# List installed plugins and commands
@@ -80,6 +105,7 @@ module Bundler
else
builder.eval_gemfile(gemfile)
end
+ builder.check_primary_source_safety
definition = builder.to_definition(nil, true)
return if definition.dependencies.empty?
@@ -138,7 +164,7 @@ module Bundler
end
# To be called from Cli class to pass the command and argument to
- # approriate plugin class
+ # appropriate plugin class
def exec_command(command, args)
raise UndefinedCommandError, "Command `#{command}` not found" unless command? command
@@ -157,7 +183,7 @@ module Bundler
!index.source_plugin(name.to_s).nil?
end
- # @return [Class] that handles the source. The calss includes API::Source
+ # @return [Class] that handles the source. The class includes API::Source
def source(name)
raise UnknownSourceError, "Source #{name} not found" unless source? name
@@ -219,10 +245,11 @@ module Bundler
# @param [Array<String>] names of inferred source plugins that can be ignored
def save_plugins(plugins, specs, optional_plugins = [])
plugins.each do |name|
+ next if index.installed?(name)
+
spec = specs[name]
- validate_plugin! Pathname.new(spec.full_gem_path)
- installed = register_plugin(name, spec, optional_plugins.include?(name))
- Bundler.ui.info "Installed plugin #{name}" if installed
+
+ save_plugin(name, spec, optional_plugins.include?(name))
end
end
@@ -237,6 +264,22 @@ module Bundler
raise MalformattedPlugin, "#{PLUGIN_FILE_NAME} was not found in the plugin." unless plugin_file.file?
end
+ # Validates and registers a plugin.
+ #
+ # @param [String] name the name of the plugin
+ # @param [Specification] spec of installed plugin
+ # @param [Boolean] optional_plugin, removed if there is conflict with any
+ # other plugin (used for default source plugins)
+ #
+ # @raise [PluginInstallError] if validation or registration raises any error
+ def save_plugin(name, spec, optional_plugin = false)
+ validate_plugin! Pathname.new(spec.full_gem_path)
+ installed = register_plugin(name, spec, optional_plugin)
+ Bundler.ui.info "Installed plugin #{name}" if installed
+ rescue PluginError => e
+ raise PluginInstallError, "Failed to install plugin `#{spec.name}`, due to #{e.class} (#{e.message})"
+ end
+
# Runs the plugins.rb file in an isolated namespace, records the plugin
# actions it registers for and then passes the data to index to be stored.
#
@@ -283,6 +326,8 @@ module Bundler
#
# @param [String] name of the plugin
def load_plugin(name)
+ return unless name && !name.empty?
+
# Need to ensure before this that plugin root where the rest of gems
# are installed to be on load path to support plugin deps. Currently not
# done to avoid conflicts
diff --git a/lib/bundler/plugin/api/source.rb b/lib/bundler/plugin/api/source.rb
index 56e97f4aa4..32b1d0ee38 100644
--- a/lib/bundler/plugin/api/source.rb
+++ b/lib/bundler/plugin/api/source.rb
@@ -140,6 +140,13 @@ module Bundler
end
end
+ # Set internal representation to fetch the gems/specs locally.
+ #
+ # When this is called, the source should try to fetch the specs and
+ # install from the local system.
+ def local!
+ end
+
# Set internal representation to fetch the gems/specs from remote.
#
# When this is called, the source should try to fetch the specs and
@@ -237,6 +244,20 @@ module Bundler
specs.unmet_dependency_names
end
+ # Used by definition.
+ #
+ # Note: Do not override if you don't know what you are doing.
+ def spec_names
+ specs.spec_names
+ end
+
+ # Used by definition.
+ #
+ # Note: Do not override if you don't know what you are doing.
+ def add_dependency_names(names)
+ @dependencies |= Array(names)
+ end
+
# Note: Do not override if you don't know what you are doing.
def can_lock?(spec)
spec.source == self
@@ -260,8 +281,9 @@ module Bundler
end
def to_s
- "plugin source for #{options[:type]} with uri #{uri}"
+ "plugin source for #{@type} with uri #{@uri}"
end
+ alias_method :identifier, :to_s
# Note: Do not override if you don't know what you are doing.
def include?(other)
diff --git a/lib/bundler/plugin/dsl.rb b/lib/bundler/plugin/dsl.rb
index 4bfc8437e0..da751d1774 100644
--- a/lib/bundler/plugin/dsl.rb
+++ b/lib/bundler/plugin/dsl.rb
@@ -10,7 +10,7 @@ module Bundler
# So that we don't have to override all there methods to dummy ones
# explicitly.
# They will be handled by method_missing
- [:gemspec, :gem, :path, :install_if, :platforms, :env].each {|m| undef_method m }
+ [:gemspec, :gem, :install_if, :platforms, :env].each {|m| undef_method m }
# This lists the plugins that was added automatically and not specified by
# the user.
diff --git a/lib/bundler/plugin/index.rb b/lib/bundler/plugin/index.rb
index 2d70a046bb..29d33be718 100644
--- a/lib/bundler/plugin/index.rb
+++ b/lib/bundler/plugin/index.rb
@@ -71,6 +71,18 @@ module Bundler
raise
end
+ def unregister_plugin(name)
+ @commands.delete_if {|_, v| v == name }
+ @sources.delete_if {|_, v| v == name }
+ @hooks.each do |hook, names|
+ names.delete(name)
+ @hooks.delete(hook) if names.empty?
+ end
+ @plugin_paths.delete(name)
+ @load_paths.delete(name)
+ save_index
+ end
+
# Path of default index file
def index_file
Plugin.root.join("index")
@@ -124,7 +136,7 @@ module Bundler
@hooks[event] || []
end
- private
+ private
# Reads the index file from the directory and initializes the instance
# variables.
diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb
index bcea3f0e45..d7411fff45 100644
--- a/lib/bundler/plugin/installer.rb
+++ b/lib/bundler/plugin/installer.rb
@@ -16,15 +16,13 @@ module Bundler
version = options[:version] || [">= 0"]
- Bundler.settings.temporary(:disable_multisource => false) do
- if options[:git]
- install_git(names, version, options)
- elsif options[:local_git]
- install_local_git(names, version, options)
- else
- sources = options[:source] || Bundler.rubygems.sources
- install_rubygems(names, version, sources)
- end
+ if options[:git]
+ install_git(names, version, options)
+ elsif options[:local_git]
+ install_local_git(names, version, options)
+ else
+ sources = options[:source] || Bundler.rubygems.sources
+ install_rubygems(names, version, sources)
end
end
@@ -41,7 +39,7 @@ module Bundler
install_from_specs specs
end
- private
+ private
def check_sources_consistency!(options)
if options.key?(:git) && options.key?(:local_git)
@@ -79,10 +77,12 @@ module Bundler
source_list = SourceList.new
source_list.add_git_source(git_source_options) if git_source_options
- source_list.add_rubygems_source("remotes" => rubygems_source) if rubygems_source
+ Array(rubygems_source).each {|remote| source_list.add_global_rubygems_remote(remote) } if rubygems_source
deps = names.map {|name| Dependency.new name, version }
+ Bundler.configure_gem_home_and_path(Plugin.root)
+
definition = Definition.new(nil, deps, source_list, true)
install_definition(definition)
end
diff --git a/lib/bundler/plugin/installer/rubygems.rb b/lib/bundler/plugin/installer/rubygems.rb
index 7ae74fa93b..e144c14b24 100644
--- a/lib/bundler/plugin/installer/rubygems.rb
+++ b/lib/bundler/plugin/installer/rubygems.rb
@@ -8,7 +8,7 @@ module Bundler
"#{spec.name} #{spec.version}"
end
- private
+ private
def requires_sudo?
false # Will change on implementation of project level plugins
diff --git a/lib/bundler/plugin/source_list.rb b/lib/bundler/plugin/source_list.rb
index f0e212205f..547661cf2f 100644
--- a/lib/bundler/plugin/source_list.rb
+++ b/lib/bundler/plugin/source_list.rb
@@ -17,7 +17,11 @@ module Bundler
path_sources + git_sources + rubygems_sources + [metadata_source]
end
- private
+ def default_source
+ git_sources.first || global_rubygems_source
+ end
+
+ private
def rubygems_aggregate_class
Plugin::Installer::Rubygems
diff --git a/lib/bundler/psyched_yaml.rb b/lib/bundler/psyched_yaml.rb
index c086b7651c..463d52dc4a 100644
--- a/lib/bundler/psyched_yaml.rb
+++ b/lib/bundler/psyched_yaml.rb
@@ -1,11 +1,5 @@
# frozen_string_literal: true
-# Psych could be a gem, so try to ask for it
-begin
- gem "psych"
-rescue LoadError
-end if defined?(gem)
-
# Psych could be in the stdlib
# but it's too late if Syck is already loaded
begin
@@ -26,12 +20,3 @@ module Bundler
YamlLibrarySyntaxError = ::ArgumentError
end
end
-
-require_relative "deprecate"
-begin
- Bundler::Deprecate.skip_during do
- require "rubygems/safe_yaml"
- end
-rescue LoadError
- # it's OK if the file isn't there
-end
diff --git a/lib/bundler/remote_specification.rb b/lib/bundler/remote_specification.rb
index f87a09b9a6..89b69e1045 100644
--- a/lib/bundler/remote_specification.rb
+++ b/lib/bundler/remote_specification.rb
@@ -50,6 +50,8 @@ module Bundler
# once the remote gem is downloaded, the backend specification will
# be swapped out.
def __swap__(spec)
+ raise APIResponseInvalidDependenciesError unless spec.dependencies.all? {|d| d.is_a?(Gem::Dependency) }
+
SharedHelpers.ensure_same_dependencies(self, dependencies, spec.dependencies)
@_remote_specification = spec
end
@@ -76,7 +78,8 @@ module Bundler
deps = method_missing(:dependencies)
# allow us to handle when the specs dependencies are an array of array of string
- # see https://github.com/bundler/bundler/issues/5797
+ # in order to delay the crash to `#__swap__` where it results in a friendlier error
+ # see https://github.com/rubygems/bundler/issues/5797
deps = deps.map {|d| d.is_a?(Gem::Dependency) ? d : Gem::Dependency.new(*d) }
deps
@@ -88,7 +91,7 @@ module Bundler
" #{source.revision[0..6]}"
end
- private
+ private
def to_ary
nil
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index c7caf01c7d..5eb17a3921 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -5,6 +5,8 @@ module Bundler
require_relative "vendored_molinillo"
require_relative "resolver/spec_group"
+ include GemHelpers
+
# Figures out the best possible configuration of gems that satisfies
# the list of passed dependencies and any child dependencies without
# causing any gem activation errors.
@@ -15,16 +17,14 @@ module Bundler
# ==== Returns
# <GemBundle>,nil:: If the list of dependencies can be resolved, a
# collection of gemspecs is returned. Otherwise, nil is returned.
- def self.resolve(requirements, index, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
- platforms = Set.new(platforms) if platforms
+ def self.resolve(requirements, source_requirements = {}, base = [], gem_version_promoter = GemVersionPromoter.new, additional_base_requirements = [], platforms = nil)
base = SpecSet.new(base) unless base.is_a?(SpecSet)
- resolver = new(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
+ resolver = new(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
result = resolver.start(requirements)
- SpecSet.new(result)
+ SpecSet.new(SpecSet.new(result).for(requirements.reject{|dep| dep.name.end_with?("\0") }))
end
- def initialize(index, source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
- @index = index
+ def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms)
@source_requirements = source_requirements
@base = base
@resolver = Molinillo::Resolver.new(self, self)
@@ -32,14 +32,13 @@ module Bundler
@base_dg = Molinillo::DependencyGraph.new
@base.each do |ls|
dep = Dependency.new(ls.name, ls.version)
- @base_dg.add_vertex(ls.name, DepProxy.new(dep, ls.platform), true)
+ @base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true)
end
additional_base_requirements.each {|d| @base_dg.add_vertex(d.name, d) }
- @platforms = platforms
+ @platforms = platforms.reject {|p| p != Gem::Platform::RUBY && (platforms - [p]).any? {|pl| generic(pl) == p } }
+ @resolving_only_for_ruby = platforms == [Gem::Platform::RUBY]
@gem_version_promoter = gem_version_promoter
- @allow_bundler_dependency_conflicts = Bundler.feature_flag.allow_bundler_dependency_conflicts?
@use_gvp = Bundler.feature_flag.use_gem_version_promoter_for_major_updates? || !@gem_version_promoter.major?
- @lockfile_uses_separate_rubygems_sources = Bundler.feature_flag.disable_multisource?
end
def start(requirements)
@@ -49,7 +48,6 @@ module Bundler
verify_gemfile_dependencies_are_found!(requirements)
dg = @resolver.resolve(requirements, @base_dg)
dg.
- tap {|resolved| validate_resolved_specs!(resolved) }.
map(&:payload).
reject {|sg| sg.name.end_with?("\0") }.
map(&:to_specs).
@@ -75,12 +73,17 @@ module Bundler
return unless debug?
debug_info = yield
debug_info = debug_info.inspect unless debug_info.is_a?(String)
- warn debug_info.split("\n").map {|s| " " * depth + s }
+ puts debug_info.split("\n").map {|s| depth == 0 ? "BUNDLER: #{s}" : "BUNDLER(#{depth}): #{s}" }
end
def debug?
return @debug_mode if defined?(@debug_mode)
- @debug_mode = ENV["DEBUG_RESOLVER"] || ENV["DEBUG_RESOLVER_TREE"] || false
+ @debug_mode =
+ ENV["BUNDLER_DEBUG_RESOLVER"] ||
+ ENV["BUNDLER_DEBUG_RESOLVER_TREE"] ||
+ ENV["DEBUG_RESOLVER"] ||
+ ENV["DEBUG_RESOLVER_TREE"] ||
+ false
end
def before_resolution
@@ -101,18 +104,18 @@ module Bundler
specification.dependencies_for_activated_platforms
end
- def search_for(dependency)
- platform = dependency.__platform
- dependency = dependency.dep unless dependency.is_a? Gem::Dependency
- search = @search_for[dependency] ||= begin
- index = index_for(dependency)
- results = index.search(dependency, @base[dependency.name])
+ def search_for(dependency_proxy)
+ platform = dependency_proxy.__platform
+ dependency = dependency_proxy.dep
+ name = dependency.name
+ @search_for[dependency_proxy] ||= begin
+ results = results_for(dependency, @base[name])
- if vertex = @base_dg.vertex_named(dependency.name)
+ if vertex = @base_dg.vertex_named(name)
locked_requirement = vertex.payload.requirement
end
- if !@prerelease_specified[dependency.name] && (!@use_gvp || locked_requirement.nil?)
+ if !@prerelease_specified[name] && (!@use_gvp || locked_requirement.nil?)
# Move prereleases to the beginning of the list, so they're considered
# last during resolution.
pre, results = results.partition {|spec| spec.version.prerelease? }
@@ -131,9 +134,20 @@ module Bundler
end
nested.reduce([]) do |groups, (version, specs)|
next groups if locked_requirement && !locked_requirement.satisfied_by?(version)
- spec_group = SpecGroup.new(specs)
- spec_group.ignores_bundler_dependencies = @allow_bundler_dependency_conflicts
- groups << spec_group
+
+ specs_by_platform = Hash.new do |current_specs, current_platform|
+ current_specs[current_platform] = select_best_platform_match(specs, current_platform)
+ end
+
+ spec_group_ruby = SpecGroup.create_for(specs_by_platform, [Gem::Platform::RUBY], Gem::Platform::RUBY)
+ groups << spec_group_ruby if spec_group_ruby
+
+ next groups if @resolving_only_for_ruby
+
+ spec_group = SpecGroup.create_for(specs_by_platform, @platforms, platform)
+ groups << spec_group if spec_group
+
+ groups
end
else
[]
@@ -146,24 +160,18 @@ module Bundler
@gem_version_promoter.sort_versions(dependency, spec_groups)
end
end
- search.select {|sg| sg.for?(platform) }.each {|sg| sg.activate_platform!(platform) }
end
def index_for(dependency)
- source = @source_requirements[dependency.name]
- if source
- source.specs
- elsif @lockfile_uses_separate_rubygems_sources
- Index.build do |idx|
- if dependency.all_sources
- dependency.all_sources.each {|s| idx.add_source(s.specs) if s }
- else
- idx.add_source @source_requirements[:default].specs
- end
- end
- else
- @index
- end
+ source_for(dependency.name).specs
+ end
+
+ def source_for(name)
+ @source_requirements[name] || @source_requirements[:default]
+ end
+
+ def results_for(dependency, base)
+ index_for(dependency).search(dependency, base)
end
def name_for(dependency)
@@ -183,24 +191,15 @@ module Bundler
end
def requirement_satisfied_by?(requirement, activated, spec)
- return false unless requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
- spec.activate_platform!(requirement.__platform) if !@platforms || @platforms.include?(requirement.__platform)
- true
+ requirement.matches_spec?(spec) || spec.source.is_a?(Source::Gemspec)
end
- def relevant_sources_for_vertex(vertex)
- if vertex.root?
- [@source_requirements[vertex.name]]
- elsif @lockfile_uses_separate_rubygems_sources
- vertex.recursive_predecessors.map do |v|
- @source_requirements[v.name]
- end << @source_requirements[:default]
- end
+ def dependencies_equal?(dependencies, other_dependencies)
+ dependencies.map(&:dep) == other_dependencies.map(&:dep)
end
def sort_dependencies(dependencies, activated, conflicts)
dependencies.sort_by do |dependency|
- dependency.all_sources = relevant_sources_for_vertex(activated.vertex_named(dependency.name))
name = name_for(dependency)
vertex = activated.vertex_named(name)
[
@@ -215,19 +214,13 @@ module Bundler
end
end
- # Sort platforms from most general to most specific
- def self.sort_platforms(platforms)
- platforms.sort_by do |platform|
- platform_sort_key(platform)
- end
- end
-
def self.platform_sort_key(platform)
- return ["", "", ""] if Gem::Platform::RUBY == platform
- platform.to_a.map {|part| part || "" }
+ # Prefer specific platform to not specific platform
+ return ["99-LAST", "", "", ""] if Gem::Platform::RUBY == platform
+ ["00", *platform.to_a.map {|part| part || "" }]
end
- private
+ private
# returns an integer \in (-\infty, 0]
# a number closer to 0 means the dependency is less constraining
@@ -260,12 +253,6 @@ module Bundler
next if name == "bundler"
next unless search_for(requirement).empty?
- cache_message = begin
- " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
- rescue GemfileNotFound
- nil
- end
-
if (base = @base[name]) && !base.empty?
version = base.first.version
message = "You have requested:\n" \
@@ -274,18 +261,17 @@ module Bundler
"Try running `bundle update #{name}`\n\n" \
"If you are updating multiple gems in your Gemfile at once,\n" \
"try passing them all to `bundle update`"
- elsif source = @source_requirements[name]
- specs = source.specs[name]
+ else
+ source = source_for(name)
+ specs = source.specs.search(name)
versions_with_platforms = specs.map {|s| [s.version, s.platform] }
+ cache_message = begin
+ " or in gems cached in #{Bundler.settings.app_cache_path}" if Bundler.app_cache.exist?
+ rescue GemfileNotFound
+ nil
+ end
message = String.new("Could not find gem '#{SharedHelpers.pretty_dependency(requirement)}' in #{source}#{cache_message}.\n")
- message << if versions_with_platforms.any?
- "The source contains '#{name}' at: #{formatted_versions_with_platforms(versions_with_platforms)}"
- else
- "The source does not contain any versions of '#{name}'"
- end
- else
- message = "Could not find gem '#{requirement}' in any of the gem sources " \
- "listed in your Gemfile#{cache_message}."
+ message << "The source contains the following versions of '#{name}': #{formatted_versions_with_platforms(versions_with_platforms)}" if versions_with_platforms.any?
end
raise GemNotFound, message
end
@@ -305,10 +291,16 @@ module Bundler
def version_conflict_message(e)
# only show essential conflicts, if possible
conflicts = e.conflicts.dup
- conflicts.delete_if do |_name, conflict|
- deps = conflict.requirement_trees.map(&:last).flatten(1)
- !Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
+
+ if conflicts["bundler"]
+ conflicts.replace("bundler" => conflicts["bundler"])
+ else
+ conflicts.delete_if do |_name, conflict|
+ deps = conflict.requirement_trees.map(&:last).flatten(1)
+ !Bundler::VersionRanges.empty?(*Bundler::VersionRanges.for_many(deps.map(&:requirement)))
+ end
end
+
e = Molinillo::VersionConflict.new(conflicts, e.specification_provider) unless conflicts.empty?
solver_name = "Bundler"
@@ -336,32 +328,32 @@ module Bundler
:additional_message_for_conflict => lambda do |o, name, conflict|
if name == "bundler"
o << %(\n Current Bundler version:\n bundler (#{Bundler::VERSION}))
- other_bundler_required = !conflict.requirement.requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION))
- end
- if name == "bundler" && other_bundler_required
- o << "\n"
- o << "This Gemfile requires a different version of Bundler.\n"
- o << "Perhaps you need to update Bundler by running `gem install bundler`?\n"
- end
- if conflict.locked_requirement
+ conflict_dependency = conflict.requirement
+ conflict_requirement = conflict_dependency.requirement
+ other_bundler_required = !conflict_requirement.satisfied_by?(Gem::Version.new(Bundler::VERSION))
+
+ if other_bundler_required
+ o << "\n\n"
+
+ candidate_specs = source_for(:default_bundler).specs.search(conflict_dependency)
+ if candidate_specs.any?
+ target_version = candidate_specs.last.version
+ new_command = [File.basename($PROGRAM_NAME), "_#{target_version}_", *ARGV].join(" ")
+ o << "Your bundle requires a different version of Bundler than the one you're running.\n"
+ o << "Install the necessary version with `gem install bundler:#{target_version}` and rerun bundler using `#{new_command}`\n"
+ else
+ o << "Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.\n"
+ end
+ end
+ elsif conflict.locked_requirement
o << "\n"
o << %(Running `bundle update` will rebuild your snapshot from scratch, using only\n)
o << %(the gems in your Gemfile, which may resolve the conflict.\n)
elsif !conflict.existing
o << "\n"
- relevant_sources = if conflict.requirement.source
- [conflict.requirement.source]
- elsif conflict.requirement.all_sources
- conflict.requirement.all_sources
- elsif @lockfile_uses_separate_rubygems_sources
- # every conflict should have an explicit group of sources when we
- # enforce strict pinning
- raise "no source set for #{conflict}"
- else
- []
- end.compact.map(&:to_s).uniq.sort
+ relevant_source = conflict.requirement.source || source_for(name)
metadata_requirement = name.end_with?("\0")
@@ -374,12 +366,10 @@ module Bundler
end
o << " "
- o << if relevant_sources.empty?
- "in any of the sources.\n"
- elsif metadata_requirement
- "is not available in #{relevant_sources.join(" or ")}"
+ o << if metadata_requirement
+ "is not available in #{relevant_source}"
else
- "in any of the relevant sources:\n #{relevant_sources * "\n "}\n"
+ "in #{relevant_source}.\n"
end
end
end,
@@ -393,29 +383,5 @@ module Bundler
end
)
end
-
- def validate_resolved_specs!(resolved_specs)
- resolved_specs.each do |v|
- name = v.name
- next unless sources = relevant_sources_for_vertex(v)
- sources.compact!
- if default_index = sources.index(@source_requirements[:default])
- sources.delete_at(default_index)
- end
- sources.reject! {|s| s.specs[name].empty? }
- sources.uniq!
- next if sources.size <= 1
-
- multisource_disabled = Bundler.feature_flag.disable_multisource?
-
- msg = ["The gem '#{name}' was found in multiple relevant sources."]
- msg.concat sources.map {|s| " * #{s}" }.sort
- msg << "You #{multisource_disabled ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
- msg = msg.join("\n")
-
- raise SecurityError, msg if multisource_disabled
- Bundler.ui.warn "Warning: #{msg}"
- end
- end
end
end
diff --git a/lib/bundler/resolver/spec_group.rb b/lib/bundler/resolver/spec_group.rb
index e5772eed81..8f4fd18c46 100644
--- a/lib/bundler/resolver/spec_group.rb
+++ b/lib/bundler/resolver/spec_group.rb
@@ -3,61 +3,58 @@
module Bundler
class Resolver
class SpecGroup
- include GemHelpers
-
attr_accessor :name, :version, :source
- attr_accessor :ignores_bundler_dependencies
+ attr_accessor :activated_platforms
+
+ def self.create_for(specs, all_platforms, specific_platform)
+ specific_platform_specs = specs[specific_platform]
+ return unless specific_platform_specs.any?
+
+ platforms = all_platforms.select {|p| specs[p].any? }
+
+ new(specific_platform_specs.first, specs, platforms)
+ end
- def initialize(all_specs)
- raise ArgumentError, "cannot initialize with an empty value" unless exemplary_spec = all_specs.first
+ def initialize(exemplary_spec, specs, relevant_platforms)
+ @exemplary_spec = exemplary_spec
@name = exemplary_spec.name
@version = exemplary_spec.version
@source = exemplary_spec.source
- @activated_platforms = []
- @dependencies = nil
- @specs = Hash.new do |specs, platform|
- specs[platform] = select_best_platform_match(all_specs, platform)
+ @activated_platforms = relevant_platforms
+ @dependencies = Hash.new do |dependencies, platforms|
+ dependencies[platforms] = dependencies_for(platforms)
end
- @ignores_bundler_dependencies = true
+ @specs = specs
end
def to_specs
- @activated_platforms.map do |p|
- next unless s = @specs[p]
- lazy_spec = LazySpecification.new(name, version, s.platform, source)
- lazy_spec.dependencies.replace s.dependencies
- lazy_spec
- end.compact
- end
-
- def activate_platform!(platform)
- return unless for?(platform)
- return if @activated_platforms.include?(platform)
- @activated_platforms << platform
- end
+ activated_platforms.map do |p|
+ specs = @specs[p]
+ next unless specs.any?
- def for?(platform)
- spec = @specs[platform]
- !spec.nil?
+ specs.map do |s|
+ lazy_spec = LazySpecification.new(name, version, s.platform, source)
+ lazy_spec.dependencies.replace s.dependencies
+ lazy_spec
+ end
+ end.flatten.compact.uniq
end
def to_s
- @to_s ||= "#{name} (#{version})"
+ activated_platforms_string = sorted_activated_platforms.join(", ")
+ "#{name} (#{version}) (#{activated_platforms_string})"
end
def dependencies_for_activated_platforms
- dependencies = @activated_platforms.map {|p| __dependencies[p] }
- metadata_dependencies = @activated_platforms.map do |platform|
- metadata_dependencies(@specs[platform], platform)
- end
- dependencies.concat(metadata_dependencies).flatten
+ @dependencies[activated_platforms]
end
def ==(other)
return unless other.is_a?(SpecGroup)
name == other.name &&
version == other.version &&
+ sorted_activated_platforms == other.sorted_activated_platforms &&
source == other.source
end
@@ -65,40 +62,46 @@ module Bundler
return unless other.is_a?(SpecGroup)
name.eql?(other.name) &&
version.eql?(other.version) &&
+ sorted_activated_platforms.eql?(other.sorted_activated_platforms) &&
source.eql?(other.source)
end
def hash
- to_s.hash ^ source.hash
+ name.hash ^ version.hash ^ sorted_activated_platforms.hash ^ source.hash
end
- private
-
- def __dependencies
- @dependencies = Hash.new do |dependencies, platform|
- dependencies[platform] = []
- if spec = @specs[platform]
- spec.dependencies.each do |dep|
- next if dep.type == :development
- next if @ignores_bundler_dependencies && dep.name == "bundler".freeze
- dependencies[platform] << DepProxy.new(dep, platform)
- end
- end
- dependencies[platform]
+ protected
+
+ def sorted_activated_platforms
+ activated_platforms.sort_by(&:to_s)
+ end
+
+ private
+
+ def dependencies_for(platforms)
+ platforms.map do |platform|
+ __dependencies(platform) + metadata_dependencies(platform)
+ end.flatten
+ end
+
+ def __dependencies(platform)
+ dependencies = []
+ @specs[platform].first.dependencies.each do |dep|
+ next if dep.type == :development
+ dependencies << DepProxy.get_proxy(dep, platform)
end
+ dependencies
end
- def metadata_dependencies(spec, platform)
- return [] unless spec
- # Only allow endpoint specifications since they won't hit the network to
- # fetch the full gemspec when calling required_ruby_version
- return [] if !spec.is_a?(EndpointSpecification) && !spec.is_a?(Gem::Specification)
+ def metadata_dependencies(platform)
+ spec = @specs[platform].first
+ return [] unless spec.is_a?(Gem::Specification)
dependencies = []
if !spec.required_ruby_version.nil? && !spec.required_ruby_version.none?
- dependencies << DepProxy.new(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
+ dependencies << DepProxy.get_proxy(Gem::Dependency.new("Ruby\0", spec.required_ruby_version), platform)
end
if !spec.required_rubygems_version.nil? && !spec.required_rubygems_version.none?
- dependencies << DepProxy.new(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
+ dependencies << DepProxy.get_proxy(Gem::Dependency.new("RubyGems\0", spec.required_rubygems_version), platform)
end
dependencies
end
diff --git a/lib/bundler/retry.rb b/lib/bundler/retry.rb
index d64958ba70..2415ade200 100644
--- a/lib/bundler/retry.rb
+++ b/lib/bundler/retry.rb
@@ -32,7 +32,7 @@ module Bundler
end
alias_method :attempts, :attempt
- private
+ private
def run(&block)
@failed = false
@@ -49,7 +49,7 @@ module Bundler
raise e
end
return true unless name
- Bundler.ui.info "" unless Bundler.ui.debug? # Add new line incase dots preceded this
+ Bundler.ui.info "" unless Bundler.ui.debug? # Add new line in case dots preceded this
Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", Bundler.ui.debug?
end
diff --git a/lib/bundler/ruby_version.rb b/lib/bundler/ruby_version.rb
index 7e403ce6fc..491f8c55a4 100644
--- a/lib/bundler/ruby_version.rb
+++ b/lib/bundler/ruby_version.rb
@@ -123,7 +123,7 @@ module Bundler
@exact = versions.all? {|v| Gem::Requirement.create(v).exact? }
end
- private
+ private
def matches?(requirements, version)
# Handles RUBY_PATCHLEVEL of -1 for instances like ruby-head
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index eda826422f..a3efff1e86 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -47,14 +47,13 @@ module Gem
full_require_paths
end
- if method_defined?(:extension_dir)
- alias_method :rg_extension_dir, :extension_dir
- def extension_dir
- @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name)
- File.expand_path(File.join(extensions_dir, source.extension_dir_name))
- else
- rg_extension_dir
- end
+ alias_method :rg_extension_dir, :extension_dir
+ def extension_dir
+ @bundler_extension_dir ||= if source.respond_to?(:extension_dir_name)
+ unique_extension_dir = [source.extension_dir_name, File.basename(full_gem_path)].uniq.join("-")
+ File.expand_path(File.join(extensions_dir, unique_extension_dir))
+ else
+ rg_extension_dir
end
end
@@ -86,7 +85,11 @@ module Gem
dependencies - development_dependencies
end
- private
+ def deleted_gem?
+ !default_gem? && !File.directory?(full_gem_path)
+ end
+
+ private
def dependencies_to_gemfile(dependencies, group = nil)
gemfile = String.new
@@ -106,7 +109,7 @@ module Gem
end
class Dependency
- attr_accessor :source, :groups, :all_sources
+ attr_accessor :source, :groups
alias_method :eql?, :==
@@ -117,7 +120,7 @@ module Gem
end
def to_yaml_properties
- instance_variables.reject {|p| ["@source", "@groups", "@all_sources"].include?(p.to_s) }
+ instance_variables.reject {|p| ["@source", "@groups"].include?(p.to_s) }
end
def to_lock
@@ -130,20 +133,97 @@ module Gem
end
end
+ # comparison is done order independently since rubygems 3.2.0.rc.2
+ unless Gem::Requirement.new("> 1", "< 2") == Gem::Requirement.new("< 2", "> 1")
+ class Requirement
+ module OrderIndependentComparison
+ def ==(other)
+ if _requirements_sorted? && other._requirements_sorted?
+ super
+ else
+ _with_sorted_requirements == other._with_sorted_requirements
+ end
+ end
+
+ protected
+
+ def _requirements_sorted?
+ return @_are_requirements_sorted if defined?(@_are_requirements_sorted)
+ strings = as_list
+ @_are_requirements_sorted = strings == strings.sort
+ end
+
+ def _with_sorted_requirements
+ @_with_sorted_requirements ||= _requirements_sorted? ? self : self.class.new(as_list.sort)
+ end
+ end
+
+ prepend OrderIndependentComparison
+ end
+ end
+
+ if Gem::Requirement.new("~> 2.0").hash == Gem::Requirement.new("~> 2.0.0").hash
+ class Requirement
+ module CorrectHashForLambdaOperator
+ def hash
+ if requirements.any? {|r| r.first == "~>" }
+ requirements.map {|r| r.first == "~>" ? [r[0], r[1].to_s] : r }.sort.hash
+ else
+ super
+ end
+ end
+ end
+
+ prepend CorrectHashForLambdaOperator
+ end
+ end
+
+ require "rubygems/platform"
+
class Platform
JAVA = Gem::Platform.new("java") unless defined?(JAVA)
MSWIN = Gem::Platform.new("mswin32") unless defined?(MSWIN)
MSWIN64 = Gem::Platform.new("mswin64") unless defined?(MSWIN64)
MINGW = Gem::Platform.new("x86-mingw32") unless defined?(MINGW)
X64_MINGW = Gem::Platform.new("x64-mingw32") unless defined?(X64_MINGW)
+ end
+
+ 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
- undef_method :hash if method_defined? :hash
- def hash
- @cpu.hash ^ @os.hash ^ @version.hash
+ private
+
+ def match_platforms?(platform, platforms)
+ platforms.any? do |local_platform|
+ platform.nil? ||
+ local_platform == platform ||
+ (local_platform != Gem::Platform::RUBY && local_platform =~ platform)
+ end
+ end
end
+ end
- undef_method :eql? if method_defined? :eql?
- alias_method :eql?, :==
+ require "rubygems/util"
+
+ Util.singleton_class.module_eval do
+ if Util.singleton_methods.include?(:glob_files_in_dir) # since 3.0.0.beta.2
+ remove_method :glob_files_in_dir
+ end
+
+ def glob_files_in_dir(glob, base_path)
+ if RUBY_VERSION >= "2.5"
+ Dir.glob(glob, :base => base_path).map! {|f| File.expand_path(f, base_path) }
+ else
+ Dir.glob(File.join(base_path.to_s.gsub(/[\[\]]/, '\\\\\\&'), glob)).map! {|f| File.expand_path(f) }
+ end
+ end
end
end
diff --git a/lib/bundler/rubygems_gem_installer.rb b/lib/bundler/rubygems_gem_installer.rb
index b1076b4554..bb9f1cb3f5 100644
--- a/lib/bundler/rubygems_gem_installer.rb
+++ b/lib/bundler/rubygems_gem_installer.rb
@@ -4,14 +4,60 @@ require "rubygems/installer"
module Bundler
class RubyGemsGemInstaller < Gem::Installer
- unless respond_to?(:at)
- def self.at(*args)
- new(*args)
+ def check_executable_overwrite(filename)
+ # Bundler needs to install gems regardless of binstub overwriting
+ end
+
+ def install
+ pre_install_checks
+
+ run_pre_install_hooks
+
+ spec.loaded_from = spec_file
+
+ # Completely remove any previous gem files
+ strict_rm_rf gem_dir
+ strict_rm_rf spec.extension_dir
+
+ SharedHelpers.filesystem_access(gem_dir, :create) do
+ FileUtils.mkdir_p gem_dir, :mode => 0o755
+ end
+
+ extract_files
+
+ build_extensions
+ write_build_info_file
+ run_post_build_hooks
+
+ generate_bin
+ generate_plugins
+
+ write_spec
+
+ SharedHelpers.filesystem_access("#{gem_home}/cache", :write) do
+ write_cache_file
end
+
+ say spec.post_install_message unless spec.post_install_message.nil?
+
+ run_post_install_hooks
+
+ spec
end
- def check_executable_overwrite(filename)
- # Bundler needs to install gems regardless of binstub overwriting
+ def generate_plugins
+ return unless Gem::Installer.instance_methods(false).include?(:generate_plugins)
+
+ latest = Gem::Specification.stubs_for(spec.name).first
+ return if latest && latest.version > spec.version
+
+ ensure_writable_dir @plugins_dir
+
+ if spec.plugins.empty?
+ remove_plugins_for(spec, @plugins_dir)
+ else
+ regenerate_plugins_for(spec, @plugins_dir)
+ end
end
def pre_install_checks
@@ -20,7 +66,10 @@ module Bundler
def build_extensions
extension_cache_path = options[:bundler_extension_cache_path]
- return super unless extension_cache_path && extension_dir = Bundler.rubygems.spec_extension_dir(spec)
+ unless extension_cache_path && extension_dir = spec.extension_dir
+ require "shellwords" # compensate missing require in rubygems before version 3.2.25
+ return super
+ end
extension_dir = Pathname.new(extension_dir)
build_complete = SharedHelpers.filesystem_access(extension_cache_path.join("gem.build_complete"), :read, &:file?)
@@ -30,6 +79,7 @@ module Bundler
FileUtils.cp_r extension_cache_path, spec.extension_dir
end
else
+ require "shellwords" # compensate missing require in rubygems before version 3.2.25
super
if extension_dir.directory? # not made for gems without extensions
SharedHelpers.filesystem_access(extension_cache_path.parent, &:mkpath)
@@ -40,7 +90,18 @@ module Bundler
end
end
- private
+ private
+
+ def strict_rm_rf(dir)
+ # FileUtils.rm_rf should probably rise in case of permission issues like
+ # `rm -rf` does. However, it fails to delete the folder silently due to
+ # https://github.com/ruby/fileutils/issues/57. It should probably be fixed
+ # inside `fileutils` but for now I`m checking whether the folder was
+ # removed after it completes, and raising otherwise.
+ FileUtils.rm_rf dir
+
+ raise PermissionError.new(dir, :delete) if File.directory?(dir)
+ end
def validate_bundler_checksum(checksum)
return true if Bundler.settings[:disable_checksum_validation]
@@ -66,7 +127,7 @@ module Bundler
If you wish to continue installing the downloaded gem, and are certain it does not pose a \
security issue despite the mismatching checksum, do the following:
- 1. run `bundle config set disable_checksum_validation true` to turn off checksum verification
+ 1. run `bundle config set --local disable_checksum_validation true` to turn off checksum verification
2. run `bundle install`
(More info: The expected SHA256 checksum was #{checksum.inspect}, but the \
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index d97621cd92..f6d59baf15 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -34,10 +34,12 @@ module Bundler
end
def build_args
+ require "rubygems/command"
Gem::Command.build_args
end
def build_args=(args)
+ require "rubygems/command"
Gem::Command.build_args = args
end
@@ -84,16 +86,12 @@ module Bundler
def spec_missing_extensions?(spec, default = true)
return spec.missing_extensions? if spec.respond_to?(:missing_extensions?)
- return false if spec_default_gem?(spec)
+ return false if spec.default_gem?
return false if spec.extensions.empty?
default
end
- def spec_default_gem?(spec)
- spec.respond_to?(:default_gem?) && spec.default_gem?
- end
-
def spec_matches_for_glob(spec, glob)
return spec.matches_for_glob(glob) if spec.respond_to?(:matches_for_glob)
@@ -102,11 +100,6 @@ module Bundler
end.flatten(1)
end
- def spec_extension_dir(spec)
- return unless spec.respond_to?(:extension_dir)
- spec.extension_dir
- end
-
def stub_set_spec(stub, spec)
stub.instance_variable_set(:@spec, spec)
end
@@ -115,11 +108,6 @@ module Bundler
obj.to_s
end
- def platforms
- return [Gem::Platform::RUBY] if Bundler.settings[:force_ruby_platform]
- Gem.platforms
- end
-
def configuration
require_relative "psyched_yaml"
Gem.configuration
@@ -141,14 +129,10 @@ module Bundler
end
def inflate(obj)
- require "rubygems/util"
-
Gem::Util.inflate(obj)
end
def correct_for_windows_path(path)
- require "rubygems/util"
-
if Gem::Util.respond_to?(:correct_for_windows_path)
Gem::Util.correct_for_windows_path(path)
elsif path[0].chr == "/" && path[1].chr =~ /[a-z]/i && path[2].chr == ":"
@@ -223,11 +207,6 @@ module Bundler
Gem.bin_path(gem, bin, ver)
end
- def preserve_paths
- # this is a no-op outside of RubyGems 1.8
- yield
- end
-
def loaded_gem_paths
loaded_gem_paths = Gem.loaded_specs.map {|_, s| s.full_require_paths }
loaded_gem_paths.flatten
@@ -241,6 +220,10 @@ module Bundler
Gem.load_plugin_files(files) if Gem.respond_to?(:load_plugin_files)
end
+ def load_env_plugins
+ Gem.load_env_plugins if Gem.respond_to?(:load_env_plugins)
+ end
+
def ui=(obj)
Gem::DefaultUserInteraction.ui = obj
end
@@ -265,8 +248,6 @@ module Bundler
require "rubygems/security"
require_relative "psyched_yaml"
gem_from_path(path, security_policies[policy]).spec
- rescue Gem::Package::FormatError
- raise GemspecError, "Could not read gem at #{path}. It may be corrupted."
rescue Exception, Gem::Exception, Gem::Security::Exception => e # rubocop:disable Lint/RescueException
if e.is_a?(Gem::Security::Exception) ||
e.message =~ /unknown trust policy|unsigned gem/i ||
@@ -329,8 +310,13 @@ module Bundler
end
message = if spec.nil?
+ target_file = begin
+ Bundler.default_gemfile.basename
+ rescue GemfileNotFound
+ "inline Gemfile"
+ end
"#{dep.name} is not part of the bundle." \
- " Add it to your #{Bundler.default_gemfile.basename}."
+ " Add it to your #{target_file}."
else
"can't activate #{dep}, already activated #{spec.full_name}. " \
"Make sure all dependencies are added to Gemfile."
@@ -346,7 +332,7 @@ module Bundler
raise e
end
- # backwards compatibility shim, see https://github.com/bundler/bundler/issues/5102
+ # backwards compatibility shim, see https://github.com/rubygems/bundler/issues/5102
kernel_class.send(:public, :gem) if Bundler.feature_flag.setup_makes_kernel_gem_public?
end
end
@@ -422,6 +408,17 @@ module Bundler
# Replace or hook into RubyGems to provide a bundlerized view
# of the world.
def replace_entrypoints(specs)
+ specs_by_name = add_default_gems_to(specs)
+
+ replace_gem(specs, specs_by_name)
+ stub_rubygems(specs)
+ replace_bin_path(specs_by_name)
+
+ Gem.clear_paths
+ end
+
+ # Add default gems not already present in specs, and return them as a hash.
+ def add_default_gems_to(specs)
specs_by_name = specs.reduce({}) do |h, s|
h[s.name] = s
h
@@ -436,40 +433,7 @@ module Bundler
specs_by_name[default_spec_name] = default_spec
end
- replace_gem(specs, specs_by_name)
- stub_rubygems(specs)
- replace_bin_path(specs_by_name)
-
- Gem.clear_paths
- end
-
- # This backports base_dir which replaces installation path
- # RubyGems 1.8+
- def backport_base_dir
- redefine_method(Gem::Specification, :base_dir) do
- return Gem.dir unless loaded_from
- File.dirname File.dirname loaded_from
- end
- end
-
- def backport_cache_file
- redefine_method(Gem::Specification, :cache_dir) do
- @cache_dir ||= File.join base_dir, "cache"
- end
-
- redefine_method(Gem::Specification, :cache_file) do
- @cache_file ||= File.join cache_dir, "#{full_name}.gem"
- end
- end
-
- def backport_spec_file
- redefine_method(Gem::Specification, :spec_dir) do
- @spec_dir ||= File.join base_dir, "specifications"
- end
-
- redefine_method(Gem::Specification, :spec_file) do
- @spec_file ||= File.join spec_dir, "#{full_name}.gemspec"
- end
+ specs_by_name
end
def undo_replacements
@@ -536,14 +500,15 @@ module Bundler
end
def fetch_specs(remote, name)
+ require "rubygems/remote_fetcher"
path = remote.uri.to_s + "#{name}.#{Gem.marshal_version}.gz"
fetcher = gem_remote_fetcher
fetcher.headers = { "X-Gemfile-Source" => remote.original_uri.to_s } if remote.original_uri
string = fetcher.fetch_path(path)
Bundler.load_marshal(string)
- rescue Gem::RemoteFetcher::FetchError => e
+ rescue Gem::RemoteFetcher::FetchError
# it's okay for prerelease to fail
- raise e unless name == "prerelease_specs"
+ raise unless name == "prerelease_specs"
end
def fetch_all_remote_specs(remote)
@@ -553,20 +518,41 @@ module Bundler
specs.concat(pres)
end
- def download_gem(spec, uri, path)
+ def download_gem(spec, uri, cache_dir)
+ require "rubygems/remote_fetcher"
uri = Bundler.settings.mirror_for(uri)
fetcher = gem_remote_fetcher
fetcher.headers = { "X-Gemfile-Source" => spec.remote.original_uri.to_s } if spec.remote.original_uri
Bundler::Retry.new("download gem from #{uri}").attempts do
- fetcher.download(spec, uri, path)
+ gem_file_name = spec.file_name
+ local_gem_path = File.join cache_dir, gem_file_name
+ return if File.exist? local_gem_path
+
+ begin
+ remote_gem_path = uri + "gems/#{gem_file_name}"
+ remote_gem_path = remote_gem_path.to_s if provides?("< 3.2.0.rc.1")
+
+ SharedHelpers.filesystem_access(local_gem_path) do
+ fetcher.cache_update_path remote_gem_path, local_gem_path
+ end
+ rescue Gem::RemoteFetcher::FetchError
+ raise if spec.original_platform == spec.platform
+
+ original_gem_file_name = "#{spec.original_name}.gem"
+ raise if gem_file_name == original_gem_file_name
+
+ gem_file_name = original_gem_file_name
+ retry
+ end
end
+ rescue Gem::RemoteFetcher::FetchError => e
+ raise Bundler::HTTPError, "Could not download gem from #{uri} due to underlying error <#{e.message}>"
end
def gem_remote_fetcher
- require "resolv"
+ require "rubygems/remote_fetcher"
proxy = configuration[:http_proxy]
- dns = Resolv::DNS.new
- Gem::RemoteFetcher.new(proxy, dns)
+ Gem::RemoteFetcher.new(proxy)
end
def gem_from_path(path, policy = nil)
@@ -594,7 +580,6 @@ module Bundler
end
def all_specs
- require_relative "remote_specification"
Gem::Specification.stubs.map do |stub|
StubSpecification.from_stub(stub)
end
@@ -602,10 +587,10 @@ module Bundler
def backport_ext_builder_monitor
# So we can avoid requiring "rubygems/ext" in its entirety
- Gem.module_eval <<-RB, __FILE__, __LINE__ + 1
+ Gem.module_eval <<-RUBY, __FILE__, __LINE__ + 1
module Ext
end
- RB
+ RUBY
require "rubygems/ext/builder"
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index 93a801eb6c..c7276b0e25 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -12,22 +12,16 @@ module Bundler
def setup(*groups)
@definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle?
- groups.map!(&:to_sym)
-
# Has to happen first
clean_load_path
- specs = groups.any? ? @definition.specs_for(groups) : requested_specs
+ specs = @definition.specs_for(groups)
SharedHelpers.set_bundle_environment
Bundler.rubygems.replace_entrypoints(specs)
# Activate the specs
load_paths = specs.map do |spec|
- unless spec.loaded_from
- raise GemNotFound, "#{spec.full_name} is missing. Run `bundle install` to get it."
- end
-
check_for_activated_spec!(spec)
Bundler.rubygems.mark_loaded(spec)
@@ -43,14 +37,6 @@ module Bundler
self
end
- REQUIRE_ERRORS = [
- /^no such file to load -- (.+)$/i,
- /^Missing \w+ (?:file\s*)?([^\s]+.rb)$/i,
- /^Missing API definition file in (.+)$/i,
- /^cannot load such file -- (.+)$/i,
- /^dlopen\([^)]*\): Library not loaded: (.+)$/i,
- ].freeze
-
def require(*groups)
groups.map!(&:to_sym)
groups = [:default] if groups.empty?
@@ -79,16 +65,14 @@ module Bundler
end
end
rescue LoadError => e
- REQUIRE_ERRORS.find {|r| r =~ e.message }
- raise if dep.autorequire || $1 != required_file
+ raise if dep.autorequire || e.path != required_file
if dep.autorequire.nil? && dep.name.include?("-")
begin
namespaced_file = dep.name.tr("-", "/")
Kernel.require namespaced_file
rescue LoadError => e
- REQUIRE_ERRORS.find {|r| r =~ e.message }
- raise if $1 != namespaced_file
+ raise if e.path != namespaced_file
end
end
end
@@ -116,7 +100,7 @@ module Bundler
alias_method :gems, :specs
- def cache(custom_path = nil)
+ def cache(custom_path = nil, local = false)
cache_path = Bundler.app_cache(custom_path)
SharedHelpers.filesystem_access(cache_path) do |p|
FileUtils.mkdir_p(p)
@@ -124,7 +108,20 @@ module Bundler
Bundler.ui.info "Updating files in #{Bundler.settings.app_cache_path}"
- specs_to_cache = Bundler.settings[:cache_all_platforms] ? @definition.resolve.materialized_for_all_platforms : specs
+ specs_to_cache = if Bundler.settings[:cache_all_platforms]
+ @definition.resolve.materialized_for_all_platforms
+ else
+ begin
+ specs
+ rescue GemNotFound
+ if local
+ Bundler.ui.warn "Some gems seem to be missing from your #{Bundler.settings.app_cache_path} directory."
+ end
+
+ raise
+ end
+ end
+
specs_to_cache.each do |spec|
next if spec.name == "bundler"
next if spec.source.is_a?(Source::Gemspec)
@@ -165,7 +162,7 @@ module Bundler
spec_cache_paths = []
spec_gemspec_paths = []
spec_extension_paths = []
- specs.each do |spec|
+ Bundler.rubygems.add_default_gems_to(specs).values.each do |spec|
spec_gem_paths << spec.full_gem_path
# need to check here in case gems are nested like for the rails git repo
md = %r{(.+bundler/gems/.+-[a-f0-9]{7,12})}.match(spec.full_gem_path)
@@ -213,7 +210,7 @@ module Bundler
output
end
- private
+ private
def prune_gem_cache(resolve, cache_path)
cached = Dir["#{cache_path}/*.gem"]
@@ -268,7 +265,7 @@ module Bundler
return if manuals.empty?
Bundler::SharedHelpers.set_env "MANPATH", manuals.concat(
- ENV["MANPATH"].to_s.split(File::PATH_SEPARATOR)
+ ENV["MANPATH"] ? ENV["MANPATH"].to_s.split(File::PATH_SEPARATOR) : [""]
).uniq.join(File::PATH_SEPARATOR)
end
@@ -294,7 +291,7 @@ module Bundler
return unless activated_spec = Bundler.rubygems.loaded_specs(spec.name)
return if activated_spec.version == spec.version
- suggestion = if Bundler.rubygems.spec_default_gem?(activated_spec)
+ suggestion = if activated_spec.default_gem?
"Since #{spec.name} is a default gem, you can either remove your dependency on it" \
" or try updating to a newer version of bundler that supports #{spec.name} as a default gem."
else
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index afbb02397c..1ced590b6f 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -7,35 +7,34 @@ module Bundler
autoload :Validator, File.expand_path("settings/validator", __dir__)
BOOL_KEYS = %w[
- allow_bundler_dependency_conflicts
allow_deployment_source_credential_changes
allow_offline_install
auto_clean_without_path
auto_install
- auto_config_jobs
cache_all
cache_all_platforms
+ clean
default_install_uses_path
deployment
- deployment_means_frozen
disable_checksum_validation
disable_exec_load
disable_local_branch_check
- disable_multisource
- disable_platform_warnings
+ disable_local_revision_check
disable_shared_gems
disable_version_check
force_ruby_platform
forget_cli_options
frozen
+ gem.changelog
gem.coc
gem.mit
+ git.allow_insecure
global_gem_cache
ignore_messages
init_gems_rb
+ inline
no_install
no_prune
- only_update_to_newer_versions
path_relative_to_cwd
path.system
plugins
@@ -44,10 +43,7 @@ module Bundler
setup_makes_kernel_gem_public
silence_deprecations
silence_root_warning
- skip_default_git_sources
- specific_platform
suppress_install_using_messages
- unlock_source_unlocks_spec
update_requires_all_flag
use_gem_version_promoter_for_major_updates
].freeze
@@ -65,31 +61,42 @@ module Bundler
without
].freeze
+ STRING_KEYS = %w[
+ bin
+ cache_path
+ console
+ gem.ci
+ gem.github_username
+ gem.linter
+ gem.rubocop
+ gem.test
+ gemfile
+ path
+ shebang
+ system_bindir
+ trust-policy
+ ].freeze
+
DEFAULT_CONFIG = {
- :silence_deprecations => false,
- :disable_version_check => true,
- :prefer_patch => false,
- :redirect => 5,
- :retry => 3,
- :timeout => 10,
+ "BUNDLE_SILENCE_DEPRECATIONS" => false,
+ "BUNDLE_DISABLE_VERSION_CHECK" => true,
+ "BUNDLE_PREFER_PATCH" => false,
+ "BUNDLE_REDIRECT" => 5,
+ "BUNDLE_RETRY" => 3,
+ "BUNDLE_TIMEOUT" => 10,
}.freeze
def initialize(root = nil)
@root = root
@local_config = load_config(local_config_file)
+ @env_config = ENV.to_h.select {|key, _value| key =~ /\ABUNDLE_.+/ }
@global_config = load_config(global_config_file)
@temporary = {}
end
def [](name)
key = key_for(name)
- value = @temporary.fetch(key) do
- @local_config.fetch(key) do
- ENV.fetch(key) do
- @global_config.fetch(key) do
- DEFAULT_CONFIG.fetch(name) do
- nil
- end end end end end
+ value = configs.values.map {|config| config[key] }.compact.first
converted_value(value, name)
end
@@ -132,13 +139,11 @@ module Bundler
end
def all
- env_keys = ENV.keys.grep(/\ABUNDLE_.+/)
-
- keys = @temporary.keys | @global_config.keys | @local_config.keys | env_keys
+ keys = @temporary.keys | @global_config.keys | @local_config.keys | @env_config.keys
keys.map do |key|
- key.sub(/^BUNDLE_/, "").gsub(/__/, ".").downcase
- end
+ key.sub(/^BUNDLE_/, "").gsub(/___/, "-").gsub(/__/, ".").downcase
+ end.sort
end
def local_overrides
@@ -171,13 +176,11 @@ module Bundler
def locations(key)
key = key_for(key)
- locations = {}
- locations[:temporary] = @temporary[key] if @temporary.key?(key)
- locations[:local] = @local_config[key] if @local_config.key?(key)
- locations[:env] = ENV[key] if ENV[key]
- locations[:global] = @global_config[key] if @global_config.key?(key)
- locations[:default] = DEFAULT_CONFIG[key] if DEFAULT_CONFIG.key?(key)
- locations
+ configs.keys.inject({}) do |partial_locations, level|
+ value_on_level = configs[level][key]
+ partial_locations[level] = value_on_level unless value_on_level.nil?
+ partial_locations
+ end
end
def pretty_values_for(exposed_key)
@@ -185,39 +188,48 @@ module Bundler
locations = []
- if @temporary.key?(key)
- locations << "Set for the current command: #{converted_value(@temporary[key], exposed_key).inspect}"
+ if value = @temporary[key]
+ locations << "Set for the current command: #{printable_value(value, exposed_key).inspect}"
end
- if @local_config.key?(key)
- locations << "Set for your local app (#{local_config_file}): #{converted_value(@local_config[key], exposed_key).inspect}"
+ if value = @local_config[key]
+ locations << "Set for your local app (#{local_config_file}): #{printable_value(value, exposed_key).inspect}"
end
- if value = ENV[key]
- locations << "Set via #{key}: #{converted_value(value, exposed_key).inspect}"
+ if value = @env_config[key]
+ locations << "Set via #{key}: #{printable_value(value, exposed_key).inspect}"
end
- if @global_config.key?(key)
- locations << "Set for the current user (#{global_config_file}): #{converted_value(@global_config[key], exposed_key).inspect}"
+ if value = @global_config[key]
+ locations << "Set for the current user (#{global_config_file}): #{printable_value(value, exposed_key).inspect}"
end
return ["You have not configured a value for `#{exposed_key}`"] if locations.empty?
locations
end
+ def processor_count
+ require "etc"
+ Etc.nprocessors
+ rescue StandardError
+ 1
+ end
+
# for legacy reasons, in Bundler 2, we do not respect :disable_shared_gems
def path
- key = key_for(:path)
- path = ENV[key] || @global_config[key]
- if path && !@temporary.key?(key) && !@local_config.key?(key)
- return Path.new(path, false, false)
+ configs.each do |_level, settings|
+ path = value_for("path", settings)
+ path_system = value_for("path.system", settings)
+ disabled_shared_gems = value_for("disable_shared_gems", settings)
+ next if path.nil? && path_system.nil? && disabled_shared_gems.nil?
+ system_path = path_system || (disabled_shared_gems == false)
+ return Path.new(path, system_path)
end
- system_path = self["path.system"] || (self[:disable_shared_gems] == false)
- Path.new(self[:path], system_path, Bundler.feature_flag.default_install_uses_path?)
+ Path.new(nil, false)
end
- Path = Struct.new(:explicit_path, :system_path, :default_install_uses_path) do
+ Path = Struct.new(:explicit_path, :system_path) do
def path
path = base_path
path = File.join(path, Bundler.ruby_scope) unless use_system_gems?
@@ -227,7 +239,7 @@ module Bundler
def use_system_gems?
return true if system_path
return false if explicit_path
- !default_install_uses_path
+ !Bundler.feature_flag.default_install_uses_path?
end
def base_path
@@ -280,20 +292,32 @@ module Bundler
def validate!
all.each do |raw_key|
- [@local_config, ENV, @global_config].each do |settings|
- value = converted_value(settings[key_for(raw_key)], raw_key)
- Validator.validate!(raw_key, value, settings.to_hash.dup)
+ [@local_config, @env_config, @global_config].each do |settings|
+ value = value_for(raw_key, settings)
+ Validator.validate!(raw_key, value, settings.dup)
end
end
end
def key_for(key)
- key = Settings.normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
- key = key.to_s.gsub(".", "__").upcase
- "BUNDLE_#{key}"
+ self.class.key_for(key)
end
- private
+ private
+
+ def configs
+ {
+ :temporary => @temporary,
+ :local => @local_config,
+ :env => @env_config,
+ :global => @global_config,
+ :default => DEFAULT_CONFIG,
+ }
+ end
+
+ def value_for(name, config)
+ converted_value(config[key_for(name)], name)
+ end
def parent_setting_for(name)
split_specific_setting_for(name)[0]
@@ -311,6 +335,10 @@ module Bundler
BOOL_KEYS.include?(name.to_s) || BOOL_KEYS.include?(parent_setting_for(name.to_s))
end
+ def is_string(name)
+ STRING_KEYS.include?(name.to_s) || name.to_s.start_with?("local.") || name.to_s.start_with?("mirror.") || name.to_s.start_with?("build.")
+ end
+
def to_bool(value)
case value
when nil, /\A(false|f|no|n|0|)\z/i, false
@@ -328,6 +356,14 @@ module Bundler
ARRAY_KEYS.include?(key.to_s)
end
+ def is_credential(key)
+ key == "gem.push_key"
+ end
+
+ def is_userinfo(value)
+ value.include?(":")
+ end
+
def to_array(value)
return [] unless value
value.split(":").map(&:to_sym)
@@ -374,15 +410,38 @@ module Bundler
end
end
+ def printable_value(value, key)
+ converted = converted_value(value, key)
+ return converted unless converted.is_a?(String)
+
+ if is_string(key)
+ converted
+ elsif is_credential(key)
+ "[REDACTED]"
+ elsif is_userinfo(converted)
+ username, pass = converted.split(":", 2)
+
+ if pass == "x-oauth-basic"
+ username = "[REDACTED]"
+ else
+ pass = "[REDACTED]"
+ end
+
+ [username, pass].join(":")
+ else
+ converted
+ end
+ end
+
def global_config_file
if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
Pathname.new(ENV["BUNDLE_CONFIG"])
- else
- begin
- Bundler.user_bundle_path("config")
- rescue PermissionError, GenericSystemCallError
- nil
- end
+ elsif ENV["BUNDLE_USER_CONFIG"] && !ENV["BUNDLE_USER_CONFIG"].empty?
+ Pathname.new(ENV["BUNDLE_USER_CONFIG"])
+ elsif ENV["BUNDLE_USER_HOME"] && !ENV["BUNDLE_USER_HOME"].empty?
+ Pathname.new(ENV["BUNDLE_USER_HOME"]).join("config")
+ elsif Bundler.rubygems.user_home && !Bundler.rubygems.user_home.empty?
+ Pathname.new(Bundler.rubygems.user_home).join(".bundle/config")
end
end
@@ -396,7 +455,20 @@ module Bundler
valid_file = file.exist? && !file.size.zero?
return {} unless valid_file
require_relative "yaml_serializer"
- YAMLSerializer.load file.read
+ YAMLSerializer.load(file.read).inject({}) do |config, (k, v)|
+ new_k = k
+
+ if k.include?("-")
+ Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \
+ "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \
+ "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)."
+
+ new_k = k.gsub("-", "___")
+ end
+
+ config[new_k] = v
+ config
+ end
end
end
@@ -413,6 +485,12 @@ module Bundler
\z
/ix.freeze
+ def self.key_for(key)
+ key = normalize_uri(key).to_s if key.is_a?(String) && /https?:/ =~ key
+ key = key.to_s.gsub(".", "__").gsub("-", "___").upcase
+ "BUNDLE_#{key}"
+ end
+
# TODO: duplicates Rubygems#normalize_uri
# TODO: is this the correct place to validate mirror URIs?
def self.normalize_uri(uri)
diff --git a/lib/bundler/setup.rb b/lib/bundler/setup.rb
index 27911dc1ad..32e9b2d7c0 100644
--- a/lib/bundler/setup.rb
+++ b/lib/bundler/setup.rb
@@ -9,10 +9,10 @@ if Bundler::SharedHelpers.in_bundle?
begin
Bundler.ui.silence { Bundler.setup }
rescue Bundler::BundlerError => e
- Bundler.ui.warn "\e[31m#{e.message}\e[0m"
+ Bundler.ui.error e.message
Bundler.ui.warn e.backtrace.join("\n") if ENV["DEBUG"]
if e.is_a?(Bundler::GemNotFound)
- Bundler.ui.warn "\e[33mRun `bundle install` to install missing gems.\e[0m"
+ Bundler.ui.warn "Run `bundle install` to install missing gems."
end
exit e.status_code
end
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb
index 6e83bc5ff4..df1c136c56 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -152,13 +152,6 @@ module Bundler
Bundler.ui.warn message
end
- def trap(signal, override = false, &block)
- prior = Signal.trap(signal) do
- block.call
- prior.call unless override
- end
- end
-
def ensure_same_dependencies(spec, old_deps, new_deps)
new_deps = new_deps.reject {|d| d.type == :development }
old_deps = old_deps.reject {|d| d.type == :development }
@@ -194,11 +187,11 @@ module Bundler
return @md5_available if defined?(@md5_available)
@md5_available = begin
require "openssl"
- OpenSSL::Digest::MD5.digest("")
+ ::OpenSSL::Digest.digest("MD5", "")
true
rescue LoadError
true
- rescue OpenSSL::Digest::DigestError
+ rescue ::OpenSSL::Digest::DigestError
false
end
end
@@ -212,7 +205,7 @@ module Bundler
filesystem_access(gemfile_path) {|g| File.open(g, "w") {|file| file.puts contents } }
end
- private
+ private
def validate_bundle_path
path_separator = Bundler.rubygems.path_separator
@@ -327,12 +320,11 @@ module Bundler
end
def clean_load_path
- bundler_lib = bundler_ruby_lib
-
loaded_gem_paths = Bundler.rubygems.loaded_gem_paths
$LOAD_PATH.reject! do |p|
- next if resolve_path(p).start_with?(bundler_lib)
+ resolved_path = resolve_path(p)
+ next if $LOADED_FEATURES.any? {|lf| lf.start_with?(resolved_path) }
loaded_gem_paths.delete(p)
end
$LOAD_PATH.uniq!
diff --git a/lib/bundler/similarity_detector.rb b/lib/bundler/similarity_detector.rb
index bd9971f884..50e66b9cab 100644
--- a/lib/bundler/similarity_detector.rb
+++ b/lib/bundler/similarity_detector.rb
@@ -26,7 +26,7 @@ module Bundler
end
end
- protected
+ protected
# https://www.informit.com/articles/article.aspx?p=683059&seqNum=36
def levenshtein_distance(this, that, ins = 2, del = 2, sub = 1)
diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb
index 4b2e305bda..2a2b332cff 100644
--- a/lib/bundler/source.rb
+++ b/lib/bundler/source.rb
@@ -7,6 +7,7 @@ module Bundler
autoload :Metadata, File.expand_path("source/metadata", __dir__)
autoload :Path, File.expand_path("source/path", __dir__)
autoload :Rubygems, File.expand_path("source/rubygems", __dir__)
+ autoload :RubygemsAggregate, File.expand_path("source/rubygems_aggregate", __dir__)
attr_accessor :dependency_names
@@ -33,6 +34,18 @@ module Bundler
spec.source == self
end
+ def local!; end
+
+ def local_only!; end
+
+ def cached!; end
+
+ def remote!; end
+
+ def add_dependency_names(names)
+ @dependency_names = Array(dependency_names) | Array(names)
+ end
+
# it's possible that gems from one source depend on gems from some
# other source, so now we download gemspecs and iterate over those
# dependencies, looking for gems we don't have info on yet.
@@ -42,6 +55,10 @@ module Bundler
specs.dependency_names
end
+ def spec_names
+ specs.spec_names
+ end
+
def include?(other)
other == self
end
@@ -50,6 +67,10 @@ module Bundler
"#<#{self.class}:0x#{object_id} #{self}>"
end
+ def identifier
+ to_s
+ end
+
def path?
instance_of?(Bundler::Source::Path)
end
@@ -63,7 +84,7 @@ module Bundler
)
end
- private
+ private
def version_color(spec_version, locked_spec_version)
if Gem::Version.correct?(spec_version) && Gem::Version.correct?(locked_spec_version)
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index 7c1533ad90..a41a2f23e9 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -22,7 +22,7 @@ module Bundler
@uri = options["uri"] || ""
@safe_uri = URICredentialsFilter.credential_filtered_uri(@uri)
@branch = options["branch"]
- @ref = options["ref"] || options["branch"] || options["tag"] || "master"
+ @ref = options["ref"] || options["branch"] || options["tag"]
@submodules = options["submodules"]
@name = options["name"]
@version = options["version"].to_s.strip.gsub("-", ".pre.")
@@ -42,7 +42,7 @@ module Bundler
%w[ref branch tag submodules].each do |opt|
out << " #{opt}: #{options[opt]}\n" if options[opt]
end
- out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
+ out << " glob: #{@glob}\n" unless default_glob?
out << " specs:\n"
end
@@ -60,25 +60,35 @@ module Bundler
alias_method :==, :eql?
def to_s
- at = if local?
- path
- elsif user_ref = options["ref"]
- if ref =~ /\A[a-z0-9]{4,}\z/i
- shortref_for_display(user_ref)
+ begin
+ at = if local?
+ path
+ elsif user_ref = options["ref"]
+ if ref =~ /\A[a-z0-9]{4,}\z/i
+ shortref_for_display(user_ref)
+ else
+ user_ref
+ end
+ elsif ref
+ ref
else
- user_ref
+ git_proxy.branch
end
- else
- ref
+
+ rev = "at #{at}@#{shortref_for_display(revision)}"
+ rescue GitError
+ ""
end
- rev = begin
- "@#{shortref_for_display(revision)}"
- rescue GitError
- nil
- end
+ specifiers = [rev, glob_for_display].compact
+ suffix =
+ if specifiers.any?
+ " (#{specifiers.join(", ")})"
+ else
+ ""
+ end
- "#{@safe_uri} (at #{at}#{rev})"
+ "#{@safe_uri}#{suffix}"
end
def name
@@ -146,7 +156,7 @@ module Bundler
changed = cached_revision && cached_revision != git_proxy.revision
- if changed && !@unlocked && !git_proxy.contains?(cached_revision)
+ if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(cached_revision)
raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(cached_revision)} " \
"but the current branch in your local override for #{name} does not contain such commit. " \
"Please make sure your branch is up to date."
@@ -230,7 +240,11 @@ module Bundler
@allow_remote || @allow_cached
end
- private
+ def local?
+ @local
+ end
+
+ private
def serialize_gemspecs_in(destination)
destination = destination.expand_path(Bundler.root) if destination.relative?
@@ -256,10 +270,6 @@ module Bundler
cached_revision && super
end
- def local?
- @local
- end
-
def requires_checkout?
allow_git_ops? && !local? && !cached_revision_checked_out?
end
@@ -280,6 +290,14 @@ module Bundler
ref[0..11]
end
+ def glob_for_display
+ default_glob? ? nil : "glob: #{@glob}"
+ end
+
+ def default_glob?
+ @glob == DEFAULT_GLOB
+ end
+
def uri_hash
if uri =~ %r{^\w+://(\w+@)?}
# Downcase the domain component of the URI
@@ -289,7 +307,9 @@ module Bundler
# If there is no URI scheme, assume it is an ssh/git URI
input = uri
end
- SharedHelpers.digest(:SHA1).hexdigest(input)
+ # We use SHA1 here for historical reason and to preserve backward compatibility.
+ # But a transition to a simpler mangling algorithm would be welcome.
+ Bundler::Digest.sha1(input)
end
def cached_revision
diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb
index 7612eb16c6..745a7fe118 100644
--- a/lib/bundler/source/git/git_proxy.rb
+++ b/lib/bundler/source/git/git_proxy.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "shellwords"
-
module Bundler
class Source
class Git
@@ -17,8 +15,8 @@ module Bundler
class GitNotAllowedError < GitError
def initialize(command)
msg = String.new
- msg << "Bundler is trying to run a `git #{command}` at runtime. You probably need to run `bundle install`. However, "
- msg << "this error message could probably be more useful. Please submit a ticket at https://github.com/bundler/bundler/issues "
+ msg << "Bundler is trying to run `#{command}` at runtime. You probably need to run `bundle install`. However, "
+ msg << "this error message could probably be more useful. Please submit a ticket at https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md "
msg << "with steps to reproduce as well as the following\n\nCALLER: #{caller.join("\n")}"
super msg
end
@@ -27,21 +25,21 @@ module Bundler
class GitCommandError < GitError
attr_reader :command
- def initialize(command, path = nil, extra_info = nil)
+ def initialize(command, path, extra_info = nil)
@command = command
msg = String.new
- msg << "Git error: command `git #{command}` in directory #{SharedHelpers.pwd} has failed."
+ msg << "Git error: command `#{command}` in directory #{path} has failed."
msg << "\n#{extra_info}" if extra_info
- msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path && path.exist?
+ msg << "\nIf this error persists you could try removing the cache directory '#{path}'" if path.exist?
super msg
end
end
class MissingGitRevisionError < GitCommandError
- def initialize(command, path, ref, repo)
+ def initialize(command, destination_path, ref, repo)
msg = "Revision #{ref} does not exist in the repository #{repo}. Maybe you misspelled it?"
- super command, path, msg
+ super command, destination_path, msg
end
end
@@ -58,30 +56,21 @@ module Bundler
@ref = ref
@revision = revision
@git = git
- raise GitNotInstalledError.new if allow? && !Bundler.git_present?
end
def revision
- return @revision if @revision
-
- begin
- @revision ||= find_local_revision
- rescue GitCommandError => e
- raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
- end
-
- @revision
+ @revision ||= find_local_revision
end
def branch
- @branch ||= allowed_in_path do
- git("rev-parse --abbrev-ref HEAD").strip
+ @branch ||= allowed_with_path do
+ git("rev-parse", "--abbrev-ref", "HEAD", :dir => path).strip
end
end
def contains?(commit)
- allowed_in_path do
- result, status = git_null("branch --contains #{commit}")
+ allowed_with_path do
+ result, status = git_null("branch", "--contains", commit, :dir => path)
status.success? && result =~ /^\* (.*)$/
end
end
@@ -96,20 +85,22 @@ module Bundler
def checkout
return if path.exist? && has_revision_cached?
- extra_ref = "#{Shellwords.shellescape(ref)}:#{Shellwords.shellescape(ref)}" if ref && ref.start_with?("refs/")
+ extra_ref = "#{ref}:#{ref}" if ref && ref.start_with?("refs/")
Bundler.ui.info "Fetching #{URICredentialsFilter.credential_filtered_uri(uri)}"
+ configured_uri = configured_uri_for(uri).to_s
+
unless path.exist?
SharedHelpers.filesystem_access(path.dirname) do |p|
FileUtils.mkdir_p(p)
end
- git_retry %(clone #{uri_escaped_with_configured_credentials} "#{path}" --bare --no-hardlinks --quiet)
+ git_retry "clone", "--bare", "--no-hardlinks", "--quiet", "--", configured_uri, path.to_s
return unless extra_ref
end
- in_path do
- git_retry %(fetch --force --quiet --tags #{uri_escaped_with_configured_credentials} "refs/heads/*:refs/heads/*" #{extra_ref})
+ with_path do
+ git_retry(*["fetch", "--force", "--quiet", "--tags", "--", configured_uri, "refs/heads/*:refs/heads/*", extra_ref].compact, :dir => path)
end
end
@@ -123,68 +114,69 @@ module Bundler
SharedHelpers.filesystem_access(destination) do |p|
FileUtils.rm_rf(p)
end
- git_retry %(clone --no-checkout --quiet "#{path}" "#{destination}")
+ git_retry "clone", "--no-checkout", "--quiet", path.to_s, destination.to_s
File.chmod(((File.stat(destination).mode | 0o777) & ~File.umask), destination)
rescue Errno::EEXIST => e
- file_path = e.message[%r{.*?(/.*)}, 1]
+ file_path = e.message[%r{.*?((?:[a-zA-Z]:)?/.*)}, 1]
raise GitError, "Bundler could not install a gem because it needs to " \
"create a directory, but a file exists - #{file_path}. Please delete " \
"this file and try again."
end
end
# method 2
- SharedHelpers.chdir(destination) do
- git_retry %(fetch --force --quiet --tags "#{path}")
+ git_retry "fetch", "--force", "--quiet", "--tags", path.to_s, :dir => destination
- begin
- git "reset --hard #{@revision}"
- rescue GitCommandError => e
- raise MissingGitRevisionError.new(e.command, path, @revision, URICredentialsFilter.credential_filtered_uri(uri))
- end
+ begin
+ git "reset", "--hard", @revision, :dir => destination
+ rescue GitCommandError => e
+ raise MissingGitRevisionError.new(e.command, destination, @revision, URICredentialsFilter.credential_filtered_uri(uri))
+ end
- if submodules
- git_retry "submodule update --init --recursive"
- elsif Gem::Version.create(version) >= Gem::Version.create("2.9.0")
- git_retry "submodule deinit --all --force"
- end
+ if submodules
+ git_retry "submodule", "update", "--init", "--recursive", :dir => destination
+ elsif Gem::Version.create(version) >= Gem::Version.create("2.9.0")
+ inner_command = "git -C $toplevel submodule deinit --force $sm_path"
+ git_retry "submodule", "foreach", "--quiet", inner_command, :dir => destination
end
end
- private
+ private
- def git_null(command)
- command_with_no_credentials = URICredentialsFilter.credential_filtered_string(command, uri)
- raise GitNotAllowedError.new(command_with_no_credentials) unless allow?
+ def git_null(*command, dir: nil)
+ check_allowed(command)
out, status = SharedHelpers.with_clean_git_env do
- capture_and_ignore_stderr("git #{command}")
+ capture_and_ignore_stderr(*capture3_args_for(command, dir))
end
[URICredentialsFilter.credential_filtered_string(out, uri), status]
end
- def git_retry(command)
- Bundler::Retry.new("`git #{URICredentialsFilter.credential_filtered_string(command, uri)}`", GitNotAllowedError).attempts do
- git(command)
+ def git_retry(*command, dir: nil)
+ command_with_no_credentials = check_allowed(command)
+
+ Bundler::Retry.new("`#{command_with_no_credentials}` at #{dir || SharedHelpers.pwd}").attempts do
+ git(*command, :dir => dir)
end
end
- def git(command, check_errors = true, error_msg = nil)
- command_with_no_credentials = URICredentialsFilter.credential_filtered_string(command, uri)
- raise GitNotAllowedError.new(command_with_no_credentials) unless allow?
+ def git(*command, dir: nil)
+ command_with_no_credentials = check_allowed(command)
out, status = SharedHelpers.with_clean_git_env do
- capture_and_filter_stderr(uri, "git #{command}")
+ capture_and_filter_stderr(*capture3_args_for(command, dir))
end
- stdout_with_no_credentials = URICredentialsFilter.credential_filtered_string(out, uri)
- raise GitCommandError.new(command_with_no_credentials, path, error_msg) if check_errors && !status.success?
- stdout_with_no_credentials
+ filtered_out = URICredentialsFilter.credential_filtered_string(out, uri)
+
+ raise GitCommandError.new(command_with_no_credentials, dir || SharedHelpers.pwd, filtered_out) unless status.success?
+
+ filtered_out
end
def has_revision_cached?
return unless @revision
- in_path { git("cat-file -e #{@revision}") }
+ with_path { git("cat-file", "-e", @revision, :dir => path) }
true
rescue GitError
false
@@ -195,23 +187,11 @@ module Bundler
end
def find_local_revision
- allowed_in_path do
- git("rev-parse --verify #{Shellwords.shellescape(ref)}", true).strip
- end
- end
-
- # Escape the URI for git commands
- def uri_escaped_with_configured_credentials
- remote = configured_uri_for(uri)
- if Bundler::WINDOWS
- # Windows quoting requires double quotes only, with double quotes
- # inside the string escaped by being doubled.
- '"' + remote.gsub('"') { '""' } + '"'
- else
- # Bash requires single quoted strings, with the single quotes escaped
- # by ending the string, escaping the quote, and restarting the string.
- "'" + remote.gsub("'") { "'\\''" } + "'"
+ allowed_with_path do
+ git("rev-parse", "--verify", ref || "HEAD", :dir => path).strip
end
+ rescue GitCommandError => e
+ raise MissingGitRevisionError.new(e.command, path, ref, URICredentialsFilter.credential_filtered_uri(uri))
end
# Adds credentials to the URI as Fetcher#configured_uri_for does
@@ -227,32 +207,56 @@ module Bundler
end
def allow?
- @git ? @git.allow_git_ops? : true
+ allowed = @git ? @git.allow_git_ops? : true
+
+ raise GitNotInstalledError.new if allowed && !Bundler.git_present?
+
+ allowed
end
- def in_path(&blk)
+ def with_path(&blk)
checkout unless path.exist?
- _ = URICredentialsFilter # load it before we chdir
- SharedHelpers.chdir(path, &blk)
+ blk.call
end
- def allowed_in_path
- return in_path { yield } if allow?
+ def allowed_with_path
+ return with_path { yield } if allow?
raise GitError, "The git source #{uri} is not yet checked out. Please run `bundle install` before trying to start your application"
end
- def capture_and_filter_stderr(uri, cmd)
+ def check_allowed(command)
+ require "shellwords"
+ command_with_no_credentials = URICredentialsFilter.credential_filtered_string("git #{command.shelljoin}", uri)
+ raise GitNotAllowedError.new(command_with_no_credentials) unless allow?
+ command_with_no_credentials
+ end
+
+ def capture_and_filter_stderr(*cmd)
require "open3"
- return_value, captured_err, status = Open3.capture3(cmd)
- Bundler.ui.warn URICredentialsFilter.credential_filtered_string(captured_err, uri) if uri && !captured_err.empty?
+ return_value, captured_err, status = Open3.capture3(*cmd)
+ Bundler.ui.warn URICredentialsFilter.credential_filtered_string(captured_err, uri) unless captured_err.empty?
[return_value, status]
end
- def capture_and_ignore_stderr(cmd)
+ def capture_and_ignore_stderr(*cmd)
require "open3"
- return_value, _, status = Open3.capture3(cmd)
+ return_value, _, status = Open3.capture3(*cmd)
[return_value, status]
end
+
+ def capture3_args_for(cmd, dir)
+ return ["git", *cmd] unless dir
+
+ if Bundler.feature_flag.bundler_3_mode? || supports_minus_c?
+ ["git", "-C", dir.to_s, *cmd]
+ else
+ ["git", *cmd, { :chdir => dir.to_s }]
+ end
+ end
+
+ def supports_minus_c?
+ @supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5")
+ end
end
end
end
diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb
index 0867879861..50b65ce0ea 100644
--- a/lib/bundler/source/metadata.rb
+++ b/lib/bundler/source/metadata.rb
@@ -33,10 +33,6 @@ module Bundler
end
end
- def cached!; end
-
- def remote!; end
-
def options
{}
end
diff --git a/lib/bundler/source/path.rb b/lib/bundler/source/path.rb
index f98f5155fb..01f89b204d 100644
--- a/lib/bundler/source/path.rb
+++ b/lib/bundler/source/path.rb
@@ -82,7 +82,9 @@ module Bundler
end
def install(spec, options = {})
- print_using_message "Using #{version_message(spec)} from #{self}"
+ using_message = "Using #{version_message(spec)} from #{self}"
+ using_message += " and installing its executables" unless spec.executables.empty?
+ print_using_message using_message
generate_bin(spec, :disable_extensions => true)
nil # no post-install message
end
@@ -125,14 +127,18 @@ module Bundler
@expanded_original_path ||= expand(original_path)
end
- private
+ private
def expanded_path
@expanded_path ||= expand(path)
end
def expand(somepath)
- somepath.expand_path(root_path)
+ if Bundler.current_ruby.jruby? # TODO: Unify when https://github.com/rubygems/bundler/issues/7598 fixed upstream and all supported jrubies include the fix
+ somepath.expand_path(root_path).expand_path
+ else
+ somepath.expand_path(root_path)
+ end
rescue ArgumentError => e
Bundler.ui.debug(e)
raise PathError, "There was an error while trying to use the path " \
@@ -167,7 +173,7 @@ module Bundler
if File.directory?(expanded_path)
# We sort depth-first since `<<` will override the earlier-found specs
- Dir["#{expanded_path}/#{@glob}"].sort_by {|p| -p.split(File::SEPARATOR).size }.each do |file|
+ Gem::Util.glob_files_in_dir(@glob, expanded_path).sort_by {|p| -p.split(File::SEPARATOR).size }.each do |file|
next unless spec = load_gemspec(file)
spec.source = self
diff --git a/lib/bundler/source/path/installer.rb b/lib/bundler/source/path/installer.rb
index a0357ffa39..a70973bde7 100644
--- a/lib/bundler/source/path/installer.rb
+++ b/lib/bundler/source/path/installer.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_relative "../../rubygems_gem_installer"
+
module Bundler
class Source
class Path
@@ -26,23 +28,21 @@ module Bundler
end
def post_install
- SharedHelpers.chdir(@gem_dir) do
- run_hooks(:pre_install)
+ run_hooks(:pre_install)
- unless @disable_extensions
- build_extensions
- run_hooks(:post_build)
- end
+ unless @disable_extensions
+ build_extensions
+ run_hooks(:post_build)
+ end
- generate_bin unless spec.executables.nil? || spec.executables.empty?
+ generate_bin unless spec.executables.empty?
- run_hooks(:post_install)
- end
+ run_hooks(:post_install)
ensure
Bundler.rm_rf(@tmp_dir) if Bundler.requires_sudo?
end
- private
+ private
def generate_bin
super
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index 6c0de204e7..8bc3aa17e9 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -20,18 +20,38 @@ module Bundler
@dependency_names = []
@allow_remote = false
@allow_cached = false
+ @allow_local = options["allow_local"] || false
@caches = [cache_path, *Bundler.rubygems.gem_cache]
- Array(options["remotes"] || []).reverse_each {|r| add_remote(r) }
+ Array(options["remotes"]).reverse_each {|r| add_remote(r) }
+ end
+
+ def local_only!
+ @specs = nil
+ @allow_local = true
+ @allow_cached = false
+ @allow_remote = false
+ end
+
+ def local!
+ return if @allow_local
+
+ @specs = nil
+ @allow_local = true
end
def remote!
+ return if @allow_remote
+
@specs = nil
@allow_remote = true
end
def cached!
+ return if @allow_cached
+
@specs = nil
+ @allow_local = true
@allow_cached = true
end
@@ -49,9 +69,17 @@ module Bundler
o.is_a?(Rubygems) && (o.credless_remotes - credless_remotes).empty?
end
+ def multiple_remotes?
+ @remotes.size > 1
+ end
+
+ def no_remotes?
+ @remotes.size == 0
+ end
+
def can_lock?(spec)
- return super if Bundler.feature_flag.disable_multisource?
- spec.source.is_a?(Rubygems)
+ return super unless multiple_remotes?
+ include?(spec.source)
end
def options
@@ -73,12 +101,27 @@ module Bundler
def to_s
if remotes.empty?
"locally installed gems"
- else
- remote_names = remotes.map(&:to_s).join(", ")
+ elsif @allow_remote && @allow_cached && @allow_local
+ "rubygems repository #{remote_names}, cached gems or installed locally"
+ elsif @allow_remote && @allow_local
"rubygems repository #{remote_names} or installed locally"
+ elsif @allow_remote
+ "rubygems repository #{remote_names}"
+ elsif @allow_cached && @allow_local
+ "cached gems or installed locally"
+ else
+ "locally installed gems"
end
end
- alias_method :name, :to_s
+
+ def identifier
+ if remotes.empty?
+ "locally installed gems"
+ else
+ "rubygems repository #{remote_names}"
+ end
+ end
+ alias_method :name, :identifier
def specs
@specs ||= begin
@@ -87,7 +130,7 @@ module Bundler
# small_idx.use large_idx.
idx = @allow_remote ? remote_specs.dup : Index.new
idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote
- idx.use(installed_specs, :override_dupes)
+ idx.use(installed_specs, :override_dupes) if @allow_local
idx
end
end
@@ -96,7 +139,7 @@ module Bundler
force = opts[:force]
ensure_builtin_gems_cached = opts[:ensure_builtin_gems_cached]
- if ensure_builtin_gems_cached && builtin_gem?(spec)
+ if ensure_builtin_gems_cached && spec.default_gem?
if !cached_path(spec)
cached_built_in_gem(spec) unless spec.remote
force = true
@@ -105,7 +148,7 @@ module Bundler
end
end
- if (installed?(spec) || Plugin.installed?(spec.name)) && !force
+ if installed?(spec) && !force
print_using_message "Using #{version_message(spec)}"
return nil # no post-install message
end
@@ -123,7 +166,7 @@ module Bundler
begin
s = Bundler.rubygems.spec_from_gem(path, Bundler.settings["trust-policy"])
spec.__swap__(s)
- rescue StandardError
+ rescue Gem::Package::FormatError
Bundler.rm_rf(path)
raise
end
@@ -135,6 +178,7 @@ module Bundler
Bundler.ui.confirm message
path = cached_gem(spec)
+ raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
if requires_sudo?
install_path = Bundler.tmp(spec.full_name)
bin_path = install_path.join("bin")
@@ -145,20 +189,19 @@ module Bundler
Bundler.mkdir_p bin_path, :no_sudo => true unless spec.executables.empty? || Bundler.rubygems.provides?(">= 2.7.5")
- installed_spec = nil
- Bundler.rubygems.preserve_paths do
- installed_spec = Bundler::RubyGemsGemInstaller.at(
- path,
- :install_dir => install_path.to_s,
- :bin_dir => bin_path.to_s,
- :ignore_dependencies => true,
- :wrappers => true,
- :env_shebang => true,
- :build_args => opts[:build_args],
- :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
- :bundler_extension_cache_path => extension_cache_path(spec)
- ).install
- end
+ require_relative "../rubygems_gem_installer"
+
+ installed_spec = Bundler::RubyGemsGemInstaller.at(
+ path,
+ :install_dir => install_path.to_s,
+ :bin_dir => bin_path.to_s,
+ :ignore_dependencies => true,
+ :wrappers => true,
+ :env_shebang => true,
+ :build_args => opts[:build_args],
+ :bundler_expected_checksum => spec.respond_to?(:checksum) && spec.checksum,
+ :bundler_extension_cache_path => extension_cache_path(spec)
+ ).install
spec.full_gem_path = installed_spec.full_gem_path
# SUDO HAX
@@ -195,12 +238,8 @@ module Bundler
end
def cache(spec, custom_path = nil)
- if builtin_gem?(spec)
- cached_path = cached_built_in_gem(spec)
- else
- cached_path = cached_gem(spec)
- end
- raise GemNotFound, "Missing gem file '#{spec.full_name}.gem'." unless cached_path
+ cached_path = cached_gem(spec)
+ raise GemNotFound, "Missing gem file '#{spec.file_name}'." unless cached_path
return if File.dirname(cached_path) == Bundler.app_cache.to_s
Bundler.ui.info " * #{File.basename(cached_path)}"
FileUtils.cp(cached_path, Bundler.app_cache(custom_path))
@@ -227,25 +266,16 @@ module Bundler
@remotes.unshift(uri) unless @remotes.include?(uri)
end
- def equivalent_remotes?(other_remotes)
- other_remotes.map(&method(:remove_auth)) == @remotes.map(&method(:remove_auth))
- end
-
- def replace_remotes(other_remotes, allow_equivalent = false)
- return false if other_remotes == @remotes
-
- equivalent = allow_equivalent && equivalent_remotes?(other_remotes)
-
- @remotes = []
- other_remotes.reverse_each do |r|
- add_remote r.to_s
+ def spec_names
+ if @allow_remote && dependency_api_available?
+ remote_specs.spec_names
+ else
+ []
end
-
- !equivalent
end
def unmet_deps
- if @allow_remote && api_fetchers.any?
+ if @allow_remote && dependency_api_available?
remote_specs.unmet_dependency_names
else
[]
@@ -261,7 +291,7 @@ module Bundler
def double_check_for(unmet_dependency_names)
return unless @allow_remote
- return unless api_fetchers.any?
+ return unless dependency_api_available?
unmet_dependency_names = unmet_dependency_names.call
unless unmet_dependency_names.nil?
@@ -283,21 +313,32 @@ module Bundler
remote_specs.each do |spec|
case spec
when EndpointSpecification, Gem::Specification, StubSpecification, LazySpecification
- names.concat(spec.runtime_dependencies)
+ names.concat(spec.runtime_dependencies.map(&:name))
when RemoteSpecification # from the full index
return nil
else
raise "unhandled spec type (#{spec.inspect})"
end
end
- names.map!(&:name) if names
names
end
- protected
+ def dependency_api_available?
+ api_fetchers.any?
+ end
+
+ protected
+
+ def remote_names
+ remotes.map(&:to_s).join(", ")
+ end
def credless_remotes
- remotes.map(&method(:suppress_configured_credentials))
+ if Bundler.settings[:allow_deployment_source_credential_changes]
+ remotes.map(&method(:remove_auth))
+ else
+ remotes.map(&method(:suppress_configured_credentials))
+ end
end
def remotes_for_spec(spec)
@@ -312,14 +353,17 @@ module Bundler
end
def cached_gem(spec)
- cached_gem = cached_path(spec)
- unless cached_gem
- raise Bundler::GemNotFound, "Could not find #{spec.file_name} for installation"
+ if spec.default_gem?
+ cached_built_in_gem(spec)
+ else
+ cached_path(spec)
end
- cached_gem
end
def cached_path(spec)
+ global_cache_path = download_cache_path(spec)
+ @caches << global_cache_path if global_cache_path
+
possibilities = @caches.map {|p| "#{p}/#{spec.file_name}" }
possibilities.find {|p| File.exist?(p) }
end
@@ -354,7 +398,6 @@ module Bundler
def installed_specs
@installed_specs ||= Index.build do |idx|
Bundler.rubygems.all_specs.reverse_each do |spec|
- next if spec.name == "bundler"
spec.source = self
if Bundler.rubygems.spec_missing_extensions?(spec, false)
Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions"
@@ -367,16 +410,12 @@ module Bundler
def cached_specs
@cached_specs ||= begin
- idx = installed_specs.dup
+ idx = @allow_local ? installed_specs.dup : Index.new
Dir["#{cache_path}/*.gem"].each do |gemfile|
next if gemfile =~ /^bundler\-[\d\.]+?\.gem/
s ||= Bundler.rubygems.spec_from_gem(gemfile)
s.source = self
- if Bundler.rubygems.spec_missing_extensions?(s, false)
- Bundler.ui.debug "Source #{self} is ignoring #{s} because it is missing extensions"
- next
- end
idx << s
end
@@ -409,11 +448,11 @@ module Bundler
def fetch_names(fetchers, dependency_names, index, override_dupes)
fetchers.each do |f|
if dependency_names
- Bundler.ui.info "Fetching gem metadata from #{f.uri}", Bundler.ui.debug?
+ Bundler.ui.info "Fetching gem metadata from #{URICredentialsFilter.credential_filtered_uri(f.uri)}", Bundler.ui.debug?
index.use f.specs_with_retry(dependency_names, self), override_dupes
Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
else
- Bundler.ui.info "Fetching source index from #{f.uri}"
+ Bundler.ui.info "Fetching source index from #{URICredentialsFilter.credential_filtered_uri(f.uri)}"
index.use f.specs_with_retry(nil, self), override_dupes
end
end
@@ -424,19 +463,26 @@ module Bundler
spec.fetch_platform
- download_path = requires_sudo? ? Bundler.tmp(spec.full_name) : rubygems_dir
- gem_path = "#{rubygems_dir}/cache/#{spec.full_name}.gem"
+ cache_path = download_cache_path(spec) || default_cache_path_for(rubygems_dir)
+ gem_path = "#{cache_path}/#{spec.file_name}"
+
+ if requires_sudo?
+ download_path = Bundler.tmp(spec.full_name)
+ download_cache_path = default_cache_path_for(download_path)
+ else
+ download_cache_path = cache_path
+ end
- SharedHelpers.filesystem_access("#{download_path}/cache") do |p|
+ SharedHelpers.filesystem_access(download_cache_path) do |p|
FileUtils.mkdir_p(p)
end
- download_gem(spec, download_path)
+ download_gem(spec, download_cache_path)
if requires_sudo?
- SharedHelpers.filesystem_access("#{rubygems_dir}/cache") do |p|
+ SharedHelpers.filesystem_access(cache_path) do |p|
Bundler.mkdir_p(p)
end
- Bundler.sudo "mv #{download_path}/cache/#{spec.full_name}.gem #{gem_path}"
+ Bundler.sudo "mv #{download_cache_path}/#{spec.file_name} #{gem_path}"
end
gem_path
@@ -444,16 +490,8 @@ module Bundler
Bundler.rm_rf(download_path) if requires_sudo?
end
- def builtin_gem?(spec)
- # Ruby 2.1, where all included gems have this summary
- return true if spec.summary =~ /is bundled with Ruby/
-
- # Ruby 2.0, where gemspecs are stored in specifications/default/
- spec.loaded_from && spec.loaded_from.include?("specifications/default/")
- end
-
def installed?(spec)
- installed_specs[spec].any?
+ installed_specs[spec].any? && !spec.deleted_gem?
end
def requires_sudo?
@@ -464,11 +502,15 @@ module Bundler
Bundler.rubygems.gem_dir
end
+ def default_cache_path_for(dir)
+ "#{dir}/cache"
+ end
+
def cache_path
Bundler.app_cache
end
- private
+ private
# Checks if the requested spec exists in the global cache. If it does,
# we copy it to the download path, and if it does not, we download it.
@@ -476,45 +518,13 @@ module Bundler
# @param [Specification] spec
# the spec we want to download or retrieve from the cache.
#
- # @param [String] download_path
+ # @param [String] download_cache_path
# the local directory the .gem will end up in.
#
- def download_gem(spec, download_path)
- local_path = File.join(download_path, "cache/#{spec.full_name}.gem")
-
- if (cache_path = download_cache_path(spec)) && cache_path.file?
- SharedHelpers.filesystem_access(local_path) do
- FileUtils.cp(cache_path, local_path)
- end
- else
- uri = spec.remote.uri
- Bundler.ui.confirm("Fetching #{version_message(spec)}")
- rubygems_local_path = Bundler.rubygems.download_gem(spec, uri, download_path)
- if rubygems_local_path != local_path
- FileUtils.mv(rubygems_local_path, local_path)
- end
- cache_globally(spec, local_path)
- end
- end
-
- # Checks if the requested spec exists in the global cache. If it does
- # not, we create the relevant global cache subdirectory if it does not
- # exist and copy the spec from the local cache to the global cache.
- #
- # @param [Specification] spec
- # the spec we want to copy to the global cache.
- #
- # @param [String] local_cache_path
- # the local directory from which we want to copy the .gem.
- #
- def cache_globally(spec, local_cache_path)
- return unless cache_path = download_cache_path(spec)
- return if cache_path.exist?
-
- SharedHelpers.filesystem_access(cache_path.dirname, &:mkpath)
- SharedHelpers.filesystem_access(cache_path) do
- FileUtils.cp(local_cache_path, cache_path)
- end
+ def download_gem(spec, download_cache_path)
+ uri = spec.remote.uri
+ Bundler.ui.confirm("Fetching #{version_message(spec)}")
+ Bundler.rubygems.download_gem(spec, uri, download_cache_path)
end
# Returns the global cache path of the calling Rubygems::Source object.
@@ -533,7 +543,7 @@ module Bundler
return unless remote = spec.remote
return unless cache_slug = remote.cache_slug
- Bundler.user_cache.join("gems", cache_slug, spec.file_name)
+ Bundler.user_cache.join("gems", cache_slug)
end
def extension_cache_slug(spec)
diff --git a/lib/bundler/source/rubygems/remote.rb b/lib/bundler/source/rubygems/remote.rb
index 45ea61acb2..82c850ffbb 100644
--- a/lib/bundler/source/rubygems/remote.rb
+++ b/lib/bundler/source/rubygems/remote.rb
@@ -39,7 +39,7 @@ module Bundler
"rubygems remote at #{anonymized_uri}"
end
- private
+ private
def apply_auth(uri, auth)
if auth && uri.userinfo.nil?
diff --git a/lib/bundler/source/rubygems_aggregate.rb b/lib/bundler/source/rubygems_aggregate.rb
new file mode 100644
index 0000000000..99ef81ad54
--- /dev/null
+++ b/lib/bundler/source/rubygems_aggregate.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Bundler
+ class Source
+ class RubygemsAggregate
+ attr_reader :source_map, :sources
+
+ def initialize(sources, source_map)
+ @sources = sources
+ @source_map = source_map
+
+ @index = build_index
+ end
+
+ def specs
+ @index
+ end
+
+ def identifier
+ to_s
+ end
+
+ def to_s
+ "any of the sources"
+ end
+
+ private
+
+ def build_index
+ Index.build do |idx|
+ dependency_names = source_map.pinned_spec_names
+
+ sources.all_sources.each do |source|
+ source.dependency_names = dependency_names - source_map.pinned_spec_names(source)
+ idx.add_source source.specs
+ dependency_names.concat(source.unmet_deps).uniq!
+ end
+
+ double_check_for_index(idx, dependency_names)
+ end
+ end
+
+ # Suppose the gem Foo depends on the gem Bar. Foo exists in Source A. Bar has some versions that exist in both
+ # sources A and B. At this point, the API request will have found all the versions of Bar in source A,
+ # but will not have found any versions of Bar from source B, which is a problem if the requested version
+ # of Foo specifically depends on a version of Bar that is only found in source B. This ensures that for
+ # each spec we found, we add all possible versions from all sources to the index.
+ def double_check_for_index(idx, dependency_names)
+ pinned_names = source_map.pinned_spec_names
+
+ names = :names # do this so we only have to traverse to get dependency_names from the index once
+ unmet_dependency_names = lambda do
+ return names unless names == :names
+ new_names = sources.all_sources.map(&:dependency_names_to_double_check)
+ return names = nil if new_names.compact!
+ names = new_names.flatten(1).concat(dependency_names)
+ names.uniq!
+ names -= pinned_names
+ names
+ end
+
+ sources.all_sources.each do |source|
+ source.double_check_for(unmet_dependency_names)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index d3f649a12c..a4773397c7 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -1,30 +1,53 @@
# frozen_string_literal: true
-require "set"
-
module Bundler
class SourceList
attr_reader :path_sources,
:git_sources,
:plugin_sources,
- :global_rubygems_source,
+ :global_path_source,
:metadata_source
+ def global_rubygems_source
+ @global_rubygems_source ||= rubygems_aggregate_class.new("allow_local" => true)
+ end
+
def initialize
@path_sources = []
@git_sources = []
@plugin_sources = []
@global_rubygems_source = nil
- @rubygems_aggregate = rubygems_aggregate_class.new
+ @global_path_source = nil
@rubygems_sources = []
@metadata_source = Source::Metadata.new
+
+ @merged_gem_lockfile_sections = false
+ end
+
+ def merged_gem_lockfile_sections?
+ @merged_gem_lockfile_sections
+ end
+
+ def merged_gem_lockfile_sections!(replacement_source)
+ @merged_gem_lockfile_sections = true
+ @global_rubygems_source = replacement_source
+ end
+
+ def aggregate_global_source?
+ global_rubygems_source.multiple_remotes?
+ end
+
+ def implicit_global_source?
+ global_rubygems_source.no_remotes?
end
def add_path_source(options = {})
if options["gemspec"]
add_source_to_list Source::Gemspec.new(options), path_sources
else
- add_source_to_list Source::Path.new(options), path_sources
+ path_source = add_source_to_list Source::Path.new(options), path_sources
+ @global_path_source ||= path_source if options["global"]
+ path_source
end
end
@@ -35,32 +58,31 @@ module Bundler
end
def add_rubygems_source(options = {})
- add_source_to_list Source::Rubygems.new(options), @rubygems_sources
+ new_source = Source::Rubygems.new(options)
+ return @global_rubygems_source if @global_rubygems_source == new_source
+
+ add_source_to_list new_source, @rubygems_sources
end
def add_plugin_source(source, options = {})
add_source_to_list Plugin.source(source).new(options), @plugin_sources
end
- def global_rubygems_source=(uri)
- if Bundler.feature_flag.disable_multisource?
- @global_rubygems_source ||= rubygems_aggregate_class.new("remotes" => uri)
- end
- add_rubygems_remote(uri)
- end
-
- def add_rubygems_remote(uri)
- return if Bundler.feature_flag.disable_multisource?
- @rubygems_aggregate.add_remote(uri)
- @rubygems_aggregate
+ def add_global_rubygems_remote(uri)
+ global_rubygems_source.add_remote(uri)
+ global_rubygems_source
end
def default_source
- global_rubygems_source || @rubygems_aggregate
+ global_path_source || global_rubygems_source
end
def rubygems_sources
- @rubygems_sources + [default_source]
+ non_global_rubygems_sources + [global_rubygems_source]
+ end
+
+ def non_global_rubygems_sources
+ @rubygems_sources
end
def rubygems_remotes
@@ -71,37 +93,51 @@ module Bundler
path_sources + git_sources + plugin_sources + rubygems_sources + [metadata_source]
end
+ def non_default_explicit_sources
+ all_sources - [default_source, metadata_source]
+ end
+
def get(source)
- source_list_for(source).find {|s| equal_source?(source, s) || equivalent_source?(source, s) }
+ source_list_for(source).find {|s| equivalent_source?(source, s) }
end
def lock_sources
- lock_sources = (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
- if Bundler.feature_flag.disable_multisource?
- lock_sources + rubygems_sources.sort_by(&:to_s)
+ lock_other_sources + lock_rubygems_sources
+ end
+
+ def lock_other_sources
+ (path_sources + git_sources + plugin_sources).sort_by(&:identifier)
+ end
+
+ def lock_rubygems_sources
+ if merged_gem_lockfile_sections?
+ [combine_rubygems_sources]
else
- lock_sources << combine_rubygems_sources
+ rubygems_sources.sort_by(&:identifier)
end
end
# Returns true if there are changes
def replace_sources!(replacement_sources)
- return true if replacement_sources.empty?
+ return false if replacement_sources.empty?
- [path_sources, git_sources, plugin_sources].each do |source_list|
- source_list.map! do |source|
- replacement_sources.find {|s| s == source } || source
- end
- end
+ @rubygems_sources, @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
+ @global_rubygems_source = global_replacement_source(replacement_sources)
- replacement_rubygems = !Bundler.feature_flag.disable_multisource? &&
- replacement_sources.detect {|s| s.is_a?(Source::Rubygems) }
- @rubygems_aggregate = replacement_rubygems if replacement_rubygems
+ different_sources?(lock_sources, replacement_sources)
+ end
- return true if !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
- return true if replacement_rubygems && rubygems_remotes.to_set != replacement_rubygems.remotes.to_set
+ # Returns true if there are changes
+ def expired_sources?(replacement_sources)
+ return false if replacement_sources.empty?
+
+ lock_sources = dup_with_replaced_sources(replacement_sources).lock_sources
+
+ different_sources?(lock_sources, replacement_sources)
+ end
- false
+ def local_only!
+ all_sources.each(&:local_only!)
end
def cached!
@@ -112,11 +148,33 @@ module Bundler
all_sources.each(&:remote!)
end
- def rubygems_primary_remotes
- @rubygems_aggregate.remotes
+ private
+
+ def dup_with_replaced_sources(replacement_sources)
+ new_source_list = dup
+ new_source_list.replace_sources!(replacement_sources)
+ new_source_list
+ end
+
+ def map_sources(replacement_sources)
+ [@rubygems_sources, @path_sources, @git_sources, @plugin_sources].map do |sources|
+ sources.map do |source|
+ replacement_sources.find {|s| s == source } || source
+ end
+ end
end
- private
+ def global_replacement_source(replacement_sources)
+ replacement_source = replacement_sources.find {|s| s == global_rubygems_source }
+ return global_rubygems_source unless replacement_source
+
+ replacement_source.local!
+ replacement_source
+ end
+
+ def different_sources?(lock_sources, replacement_sources)
+ !equivalent_sources?(lock_sources, replacement_sources)
+ end
def rubygems_aggregate_class
Source::Rubygems
@@ -147,37 +205,17 @@ module Bundler
if source.uri =~ /^git\:/
Bundler.ui.warn "The git source `#{source.uri}` uses the `git` protocol, " \
"which transmits data without encryption. Disable this warning with " \
- "`bundle config set git.allow_insecure true`, or switch to the `https` " \
+ "`bundle config set --local git.allow_insecure true`, or switch to the `https` " \
"protocol to keep your data secure."
end
end
- def equal_sources?(lock_sources, replacement_sources)
- lock_sources.to_set == replacement_sources.to_set
- end
-
- def equal_source?(source, other_source)
- source == other_source
- end
-
- def equivalent_source?(source, other_source)
- return false unless Bundler.settings[:allow_deployment_source_credential_changes] && source.is_a?(Source::Rubygems)
-
- equivalent_rubygems_sources?([source], [other_source])
- end
-
def equivalent_sources?(lock_sources, replacement_sources)
- return false unless Bundler.settings[:allow_deployment_source_credential_changes]
-
- lock_rubygems_sources, lock_other_sources = lock_sources.partition {|s| s.is_a?(Source::Rubygems) }
- replacement_rubygems_sources, replacement_other_sources = replacement_sources.partition {|s| s.is_a?(Source::Rubygems) }
-
- equivalent_rubygems_sources?(lock_rubygems_sources, replacement_rubygems_sources) && equal_sources?(lock_other_sources, replacement_other_sources)
+ lock_sources.sort_by(&:identifier) == replacement_sources.sort_by(&:identifier)
end
- def equivalent_rubygems_sources?(lock_sources, replacement_sources)
- actual_remotes = replacement_sources.map(&:remotes).flatten.uniq
- lock_sources.all? {|s| s.equivalent_remotes?(actual_remotes) }
+ def equivalent_source?(source, other_source)
+ source == other_source
end
end
end
diff --git a/lib/bundler/source_map.rb b/lib/bundler/source_map.rb
new file mode 100644
index 0000000000..a554f26f76
--- /dev/null
+++ b/lib/bundler/source_map.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Bundler
+ class SourceMap
+ attr_reader :sources, :dependencies
+
+ def initialize(sources, dependencies)
+ @sources = sources
+ @dependencies = dependencies
+ end
+
+ def pinned_spec_names(skip = nil)
+ direct_requirements.reject {|_, source| source == skip }.keys
+ end
+
+ def all_requirements
+ requirements = direct_requirements.dup
+
+ unmet_deps = sources.non_default_explicit_sources.map do |source|
+ (source.spec_names - pinned_spec_names).each do |indirect_dependency_name|
+ previous_source = requirements[indirect_dependency_name]
+ if previous_source.nil?
+ requirements[indirect_dependency_name] = source
+ else
+ no_ambiguous_sources = Bundler.feature_flag.bundler_3_mode?
+
+ msg = ["The gem '#{indirect_dependency_name}' was found in multiple relevant sources."]
+ msg.concat [previous_source, source].map {|s| " * #{s}" }.sort
+ msg << "You #{no_ambiguous_sources ? :must : :should} add this gem to the source block for the source you wish it to be installed from."
+ msg = msg.join("\n")
+
+ raise SecurityError, msg if no_ambiguous_sources
+ Bundler.ui.warn "Warning: #{msg}"
+ end
+ end
+
+ source.unmet_deps
+ end
+
+ sources.default_source.add_dependency_names(unmet_deps.flatten - requirements.keys)
+
+ requirements
+ end
+
+ def direct_requirements
+ @direct_requirements ||= begin
+ requirements = {}
+ default = sources.default_source
+ dependencies.each do |dep|
+ dep_source = dep.source || default
+ dep_source.add_dependency_names(dep.name)
+ requirements[dep.name] = dep_source
+ end
+ requirements
+ end
+ end
+ end
+end
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index 463113ef8e..a19d18388a 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
-require "tsort"
-require "set"
+require_relative "vendored_tsort"
module Bundler
class SpecSet
@@ -12,31 +11,28 @@ module Bundler
@specs = specs
end
- def for(dependencies, skip = [], check = false, match_current_platform = false, raise_on_missing = true)
- handled = Set.new
+ def for(dependencies, check = false, match_current_platform = false)
+ handled = []
deps = dependencies.dup
specs = []
- skip += ["bundler"]
loop do
break unless dep = deps.shift
- next if !handled.add?(dep) || skip.include?(dep.name)
+ next if handled.any?{|d| d.name == dep.name && (match_current_platform || d.__platform == dep.__platform) } || dep.name == "bundler"
- if spec = spec_for_dependency(dep, match_current_platform)
- specs << spec
+ handled << dep
- spec.dependencies.each do |d|
+ specs_for_dep = spec_for_dependency(dep, match_current_platform)
+ if specs_for_dep.any?
+ match_current_platform ? specs += specs_for_dep : specs |= specs_for_dep
+
+ specs_for_dep.first.dependencies.each do |d|
next if d.type == :development
- d = DepProxy.new(d, dep.__platform) unless match_current_platform
+ d = DepProxy.get_proxy(d, dep.__platform) unless match_current_platform
deps << d
end
elsif check
return false
- elsif raise_on_missing
- others = lookup[dep.name] if match_current_platform
- message = "Unable to find a spec satisfying #{dep} in the set. Perhaps the lockfile is corrupted?"
- message += " Found #{others.join(", ")} that did not match the current platform." if others && !others.empty?
- raise GemNotFound, message
end
end
@@ -44,11 +40,7 @@ module Bundler
specs << spec
end
- check ? true : SpecSet.new(specs)
- end
-
- def valid_for?(deps)
- self.for(deps, [], true)
+ check ? true : specs
end
def [](key)
@@ -74,38 +66,35 @@ module Bundler
lookup.dup
end
- def materialize(deps, missing_specs = nil)
- materialized = self.for(deps, [], false, true, !missing_specs).to_a
- deps = materialized.map(&:name).uniq
+ def materialize(deps)
+ materialized = self.for(deps, false, true)
+
materialized.map! do |s|
next s unless s.is_a?(LazySpecification)
- s.source.dependency_names = deps if s.source.respond_to?(:dependency_names=)
- spec = s.__materialize__
- unless spec
- unless missing_specs
- raise GemNotFound, "Could not find #{s.full_name} in any of the sources"
- end
- missing_specs << s
- end
- spec
+ s.source.local!
+ s.__materialize__ || s
end
- SpecSet.new(missing_specs ? materialized.compact : materialized)
+ SpecSet.new(materialized)
end
# Materialize for all the specs in the spec set, regardless of what platform they're for
# This is in contrast to how for does platform filtering (and specifically different from how `materialize` calls `for` only for the current platform)
# @return [Array<Gem::Specification>]
def materialized_for_all_platforms
- names = @specs.map(&:name).uniq
@specs.map do |s|
next s unless s.is_a?(LazySpecification)
- s.source.dependency_names = names if s.source.respond_to?(:dependency_names=)
+ s.source.local!
+ s.source.remote!
spec = s.__materialize__
raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
spec
end
end
+ def missing_specs
+ @specs.select {|s| s.is_a?(LazySpecification) }
+ end
+
def merge(set)
arr = sorted.dup
set.each do |set_spec|
@@ -147,7 +136,7 @@ module Bundler
sorted.each(&b)
end
- private
+ private
def sorted
rake = @specs.find {|s| s.name == "rake" }
@@ -183,11 +172,7 @@ module Bundler
def spec_for_dependency(dep, match_current_platform)
specs_for_platforms = lookup[dep.name]
if match_current_platform
- Bundler.rubygems.platforms.reverse_each do |pl|
- match = GemHelpers.select_best_platform_match(specs_for_platforms, pl)
- return match if match
- end
- nil
+ GemHelpers.select_best_platform_match(specs_for_platforms.select{|s| Gem::Platform.match_spec?(s) }, Bundler.local_platform)
else
GemHelpers.select_best_platform_match(specs_for_platforms, dep.__platform)
end
diff --git a/lib/bundler/stub_specification.rb b/lib/bundler/stub_specification.rb
index d45f80a80a..fa071901e5 100644
--- a/lib/bundler/stub_specification.rb
+++ b/lib/bundler/stub_specification.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require_relative "remote_specification"
-
module Bundler
class StubSpecification < RemoteSpecification
def self.from_stub(stub)
@@ -28,9 +26,21 @@ module Bundler
# @!group Stub Delegates
- # This is defined directly to avoid having to load every installed spec
+ def manually_installed?
+ # This is for manually installed gems which are gems that were fixed in place after a
+ # failed installation. Once the issue was resolved, the user then manually created
+ # the gem specification using the instructions provided by `gem help install`
+ installed_by_version == Gem::Version.new(0)
+ end
+
+ # This is defined directly to avoid having to loading the full spec
def missing_extensions?
- stub.missing_extensions?
+ return false if default_gem?
+ return false if extensions.empty?
+ return false if File.exist? gem_build_complete_path
+ return false if manually_installed?
+
+ true
end
def activated
@@ -41,8 +51,16 @@ module Bundler
stub.instance_variable_set(:@activated, activated)
end
- def default_gem
- stub.default_gem
+ def extensions
+ stub.extensions
+ end
+
+ def gem_build_complete_path
+ File.join(extension_dir, "gem.build_complete")
+ end
+
+ def default_gem?
+ stub.default_gem?
end
def full_gem_path
@@ -71,7 +89,7 @@ module Bundler
stub.raw_require_paths
end
- private
+ private
def _remote_specification
@_remote_specification ||= begin
diff --git a/lib/bundler/templates/Executable.bundler b/lib/bundler/templates/Executable.bundler
index 69f26bb9c0..8009412ea2 100644
--- a/lib/bundler/templates/Executable.bundler
+++ b/lib/bundler/templates/Executable.bundler
@@ -60,16 +60,16 @@ m = Module.new do
Regexp.last_match(1)
end
- def bundler_version
- @bundler_version ||=
+ def bundler_requirement
+ @bundler_requirement ||=
env_var_version || cli_arg_version ||
- lockfile_version
+ bundler_requirement_for(lockfile_version)
end
- def bundler_requirement
- return "#{Gem::Requirement.default}.a" unless bundler_version
+ def bundler_requirement_for(version)
+ return "#{Gem::Requirement.default}.a" unless version
- bundler_gem_version = Gem::Version.new(bundler_version)
+ bundler_gem_version = Gem::Version.new(version)
requirement = bundler_gem_version.approximate_recommendation
diff --git a/lib/bundler/templates/Gemfile b/lib/bundler/templates/Gemfile
index 1afd2cce67..d41f2719b4 100644
--- a/lib/bundler/templates/Gemfile
+++ b/lib/bundler/templates/Gemfile
@@ -2,6 +2,6 @@
source "https://rubygems.org"
-git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
+git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
# gem "rails"
diff --git a/lib/bundler/templates/gems.rb b/lib/bundler/templates/gems.rb
index 547cd6e8d9..56a62a7a82 100644
--- a/lib/bundler/templates/gems.rb
+++ b/lib/bundler/templates/gems.rb
@@ -3,6 +3,6 @@
# A sample gems.rb
source "https://rubygems.org"
-git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
+git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
# gem "rails"
diff --git a/lib/bundler/templates/newgem/CHANGELOG.md.tt b/lib/bundler/templates/newgem/CHANGELOG.md.tt
new file mode 100644
index 0000000000..c9ea96d453
--- /dev/null
+++ b/lib/bundler/templates/newgem/CHANGELOG.md.tt
@@ -0,0 +1,5 @@
+## [Unreleased]
+
+## [0.1.0] - <%= Time.now.strftime('%F') %>
+
+- Initial release
diff --git a/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
index 7dfd14aab9..175b821a62 100644
--- a/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
+++ b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
@@ -2,73 +2,83 @@
## Our Pledge
-In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to making participation in our project and
-our community a harassment-free experience for everyone, regardless of age, body
-size, disability, ethnicity, gender identity and expression, level of experience,
-nationality, personal appearance, race, religion, or sexual identity and
-orientation.
+We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
-Examples of behavior that contributes to creating a positive environment
-include:
+Examples of behavior that contributes to a positive environment for our community include:
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the overall community
-Examples of unacceptable behavior by participants include:
+Examples of unacceptable behavior include:
-* The use of sexualized language or imagery and unwelcome sexual attention or
-advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
+* The use of sexualized language or imagery, and sexual attention or
+ advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
- address, without explicit permission
+* Publishing others' private information, such as a physical or email
+ address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
-## Our Responsibilities
+## Enforcement Responsibilities
-Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
-response to any instances of unacceptable behavior.
+Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
-Project maintainers have the right and responsibility to remove, edit, or
-reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct, or to ban temporarily or
-permanently any contributor for other behaviors that they deem inappropriate,
-threatening, offensive, or harmful.
+Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
-This Code of Conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community. Examples of
-representing a project or community include using an official project e-mail
-address, posting via an official social media account, or acting as an appointed
-representative at an online or offline event. Representation of a project may be
-further defined and clarified by project maintainers.
+This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
-Instances of abusive, harassing, or otherwise unacceptable behavior may be
-reported by contacting the project team at <%= config[:email] %>. All
-complaints will be reviewed and investigated and will result in a response that
-is deemed necessary and appropriate to the circumstances. The project team is
-obligated to maintain confidentiality with regard to the reporter of an incident.
-Further details of specific enforcement policies may be posted separately.
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at <%= config[:email] %>. All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of actions.
-Project maintainers who do not follow or enforce the Code of Conduct in good
-faith may face temporary or permanent repercussions as determined by other
-members of the project's leadership.
+**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the community.
## Attribution
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
-available at [https://contributor-covenant.org/version/1/4][version]
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
+available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
-[homepage]: https://contributor-covenant.org
-[version]: https://contributor-covenant.org/version/1/4/
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
diff --git a/lib/bundler/templates/newgem/Gemfile.tt b/lib/bundler/templates/newgem/Gemfile.tt
index 83878ec7f8..de82a63c5f 100644
--- a/lib/bundler/templates/newgem/Gemfile.tt
+++ b/lib/bundler/templates/newgem/Gemfile.tt
@@ -1,12 +1,23 @@
+# frozen_string_literal: true
+
source "https://rubygems.org"
# Specify your gem's dependencies in <%= config[:name] %>.gemspec
gemspec
-gem "rake", "~> 12.0"
+gem "rake", "~> 13.0"
<%- if config[:ext] -%>
+
gem "rake-compiler"
<%- end -%>
<%- if config[:test] -%>
+
gem "<%= config[:test] %>", "~> <%= config[:test_framework_version] %>"
<%- end -%>
+<%- if config[:linter] == "rubocop" -%>
+
+gem "rubocop", "~> <%= config[:linter_version] %>"
+<%- elsif config[:linter] == "standard" -%>
+
+gem "standard", "~> <%= config[:linter_version] %>"
+<%- end -%>
diff --git a/lib/bundler/templates/newgem/README.md.tt b/lib/bundler/templates/newgem/README.md.tt
index c2f5f9dca7..8fd87abe9a 100644
--- a/lib/bundler/templates/newgem/README.md.tt
+++ b/lib/bundler/templates/newgem/README.md.tt
@@ -28,21 +28,22 @@ TODO: Write usage instructions here
After checking out the repo, run `bin/setup` to install dependencies.<% if config[:test] %> Then, run `rake <%= config[:test].sub('mini', '').sub('rspec', 'spec') %>` to run the tests.<% end %> You can also run `bin/console` for an interactive prompt that will allow you to experiment.<% if config[:bin] %> Run `bundle exec <%= config[:name] %>` to use the gem in this directory, ignoring other installed copies of this gem.<% end %>
-To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
+To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
+<% if config[:git] -%>
## Contributing
-Bug reports and pull requests are welcome on GitHub at https://github.com/<%= config[:github_username] %>/<%= config[:name] %>.<% if config[:coc] %> This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/master/CODE_OF_CONDUCT.md).<% end %>
-
+Bug reports and pull requests are welcome on GitHub at https://github.com/<%= config[:github_username] %>/<%= config[:name] %>.<% if config[:coc] %> This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/<%= config[:git_default_branch] %>/CODE_OF_CONDUCT.md).<% end %>
+<% end -%>
<% if config[:mit] -%>
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
<% end -%>
-<% if config[:coc] -%>
+<% if config[:git] && config[:coc] -%>
## Code of Conduct
-Everyone interacting in the <%= config[:constant_name] %> project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/master/CODE_OF_CONDUCT.md).
+Everyone interacting in the <%= config[:constant_name] %> project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/<%= config[:github_username] %>/<%= config[:name] %>/blob/<%= config[:git_default_branch] %>/CODE_OF_CONDUCT.md).
<% end -%>
diff --git a/lib/bundler/templates/newgem/Rakefile.tt b/lib/bundler/templates/newgem/Rakefile.tt
index 099da6f3ec..00b91c8464 100644
--- a/lib/bundler/templates/newgem/Rakefile.tt
+++ b/lib/bundler/templates/newgem/Rakefile.tt
@@ -1,5 +1,9 @@
+# frozen_string_literal: true
+
require "bundler/gem_tasks"
-<% if config[:test] == "minitest" -%>
+<% default_task_names = [config[:test_task]].compact -%>
+<% case config[:test] -%>
+<% when "minitest", "test-unit" -%>
require "rake/testtask"
Rake::TestTask.new(:test) do |t|
@@ -8,22 +12,36 @@ Rake::TestTask.new(:test) do |t|
t.test_files = FileList["test/**/*_test.rb"]
end
-<% elsif config[:test] == "rspec" -%>
+<% when "rspec" -%>
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
<% end -%>
+<% if config[:linter] == "rubocop" -%>
+<% default_task_names << :rubocop -%>
+require "rubocop/rake_task"
+
+RuboCop::RakeTask.new
+
+<% elsif config[:linter] == "standard" -%>
+<% default_task_names << :standard -%>
+require "standard/rake"
+
+<% end -%>
<% if config[:ext] -%>
+<% default_task_names.unshift(:clobber, :compile) -%>
require "rake/extensiontask"
-task :build => :compile
+task build: :compile
Rake::ExtensionTask.new("<%= config[:underscored_name] %>") do |ext|
ext.lib_dir = "lib/<%= config[:namespaced_path] %>"
end
-task :default => [:clobber, :compile, :<%= config[:test_task] %>]
+<% end -%>
+<% if default_task_names.size == 1 -%>
+task default: <%= default_task_names.first.inspect %>
<% else -%>
-task :default => :<%= config[:test_task] %>
+task default: %i[<%= default_task_names.join(" ") %>]
<% end -%>
diff --git a/lib/bundler/templates/newgem/bin/console.tt b/lib/bundler/templates/newgem/bin/console.tt
index a27f82430f..08dfaaef69 100644
--- a/lib/bundler/templates/newgem/bin/console.tt
+++ b/lib/bundler/templates/newgem/bin/console.tt
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
require "bundler/setup"
require "<%= config[:namespaced_path] %>"
diff --git a/lib/bundler/templates/newgem/circleci/config.yml.tt b/lib/bundler/templates/newgem/circleci/config.yml.tt
new file mode 100644
index 0000000000..79fd0dcc0f
--- /dev/null
+++ b/lib/bundler/templates/newgem/circleci/config.yml.tt
@@ -0,0 +1,13 @@
+version: 2.1
+jobs:
+ build:
+ docker:
+ - image: ruby:<%= RUBY_VERSION %>
+ steps:
+ - checkout
+ - run:
+ name: Run the default task
+ command: |
+ gem install bundler -v <%= Bundler::VERSION %>
+ bundle install
+ bundle exec rake
diff --git a/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt b/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt
index 8cfc828f94..e918063ddf 100644
--- a/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt
+++ b/lib/bundler/templates/newgem/ext/newgem/extconf.rb.tt
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "mkmf"
create_makefile(<%= config[:makefile_path].inspect %>)
diff --git a/lib/bundler/templates/newgem/github/workflows/main.yml.tt b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
new file mode 100644
index 0000000000..6570d177af
--- /dev/null
+++ b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
@@ -0,0 +1,27 @@
+name: Ruby
+
+on:
+ push:
+ branches:
+ - <%= config[:git_default_branch] %>
+
+ pull_request:
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ name: Ruby ${{ matrix.ruby }}
+ strategy:
+ matrix:
+ ruby:
+ - '<%= RUBY_VERSION %>'
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler-cache: true
+ - name: Run the default task
+ run: bundle exec rake
diff --git a/lib/bundler/templates/newgem/gitlab-ci.yml.tt b/lib/bundler/templates/newgem/gitlab-ci.yml.tt
new file mode 100644
index 0000000000..0e71ff26a4
--- /dev/null
+++ b/lib/bundler/templates/newgem/gitlab-ci.yml.tt
@@ -0,0 +1,9 @@
+image: ruby:<%= RUBY_VERSION %>
+
+before_script:
+ - gem install bundler -v <%= Bundler::VERSION %>
+ - bundle install
+
+example_job:
+ script:
+ - bundle exec rake
diff --git a/lib/bundler/templates/newgem/lib/newgem.rb.tt b/lib/bundler/templates/newgem/lib/newgem.rb.tt
index fae6337c3e..caf6e32f4a 100644
--- a/lib/bundler/templates/newgem/lib/newgem.rb.tt
+++ b/lib/bundler/templates/newgem/lib/newgem.rb.tt
@@ -1,6 +1,8 @@
-require "<%= config[:namespaced_path] %>/version"
+# frozen_string_literal: true
+
+require_relative "<%= File.basename(config[:namespaced_path]) %>/version"
<%- if config[:ext] -%>
-require "<%= config[:namespaced_path] %>/<%= config[:underscored_name] %>"
+require_relative "<%= File.basename(config[:namespaced_path]) %>/<%= config[:underscored_name] %>"
<%- end -%>
<%- config[:constant_array].each_with_index do |c, i| -%>
diff --git a/lib/bundler/templates/newgem/lib/newgem/version.rb.tt b/lib/bundler/templates/newgem/lib/newgem/version.rb.tt
index 389daf5048..b5cd4cb232 100644
--- a/lib/bundler/templates/newgem/lib/newgem/version.rb.tt
+++ b/lib/bundler/templates/newgem/lib/newgem/version.rb.tt
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
<%- config[:constant_array].each_with_index do |c, i| -%>
<%= " " * i %>module <%= c %>
<%- end -%>
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index 9bb3d0ff50..82281ab674 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -1,20 +1,22 @@
-require_relative 'lib/<%=config[:namespaced_path]%>/version'
+# frozen_string_literal: true
+
+require_relative "lib/<%=config[:namespaced_path]%>/version"
Gem::Specification.new do |spec|
- spec.name = <%= config[:name].inspect %>
- spec.version = <%= config[:constant_name] %>::VERSION
- spec.authors = [<%= config[:author].inspect %>]
- spec.email = [<%= config[:email].inspect %>]
-
- spec.summary = %q{TODO: Write a short summary, because RubyGems requires one.}
- spec.description = %q{TODO: Write a longer description or delete this line.}
- spec.homepage = "TODO: Put your gem's website or public repo URL here."
+ spec.name = <%= config[:name].inspect %>
+ spec.version = <%= config[:constant_name] %>::VERSION
+ spec.authors = [<%= config[:author].inspect %>]
+ spec.email = [<%= config[:email].inspect %>]
+
+ spec.summary = "TODO: Write a short summary, because RubyGems requires one."
+ spec.description = "TODO: Write a longer description or delete this line."
+ spec.homepage = "TODO: Put your gem's website or public repo URL here."
<%- if config[:mit] -%>
- spec.license = "MIT"
+ spec.license = "MIT"
<%- end -%>
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.required_ruby_version = ">= <%= config[:required_ruby_version] %>"
- spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
+ spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
@@ -22,13 +24,21 @@ Gem::Specification.new do |spec|
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
+ `git ls-files -z`.split("\x0").reject do |f|
+ (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
+ end
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
<%- if config[:ext] -%>
- spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"]
+ spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"]
<%- end -%>
+
+ # Uncomment to register a new dependency of your gem
+ # spec.add_dependency "example-gem", "~> 1.0"
+
+ # For more information and examples about making a new gem, checkout our
+ # guide at: https://bundler.io/guides/creating_gem.html
end
diff --git a/lib/bundler/templates/newgem/rubocop.yml.tt b/lib/bundler/templates/newgem/rubocop.yml.tt
new file mode 100644
index 0000000000..9ecec78807
--- /dev/null
+++ b/lib/bundler/templates/newgem/rubocop.yml.tt
@@ -0,0 +1,13 @@
+AllCops:
+ TargetRubyVersion: <%= ::Gem::Version.new(config[:required_ruby_version]).segments[0..1].join(".") %>
+
+Style/StringLiterals:
+ Enabled: true
+ EnforcedStyle: double_quotes
+
+Style/StringLiteralsInInterpolation:
+ Enabled: true
+ EnforcedStyle: double_quotes
+
+Layout/LineLength:
+ Max: 120
diff --git a/lib/bundler/templates/newgem/sig/newgem.rbs.tt b/lib/bundler/templates/newgem/sig/newgem.rbs.tt
new file mode 100644
index 0000000000..eb7b380bbb
--- /dev/null
+++ b/lib/bundler/templates/newgem/sig/newgem.rbs.tt
@@ -0,0 +1,8 @@
+<%- config[:constant_array].each_with_index do |c, i| -%>
+<%= " " * i %>module <%= c %>
+<%- end -%>
+<%= " " * config[:constant_array].size %>VERSION: String
+<%= " " * config[:constant_array].size %># See the writing guide of rbs: https://github.com/ruby/rbs#guides
+<%- (config[:constant_array].size-1).downto(0) do |i| -%>
+<%= " " * i %>end
+<%- end -%>
diff --git a/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt b/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt
index c63b487830..82cada988c 100644
--- a/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt
+++ b/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
RSpec.describe <%= config[:constant_name] %> do
it "has a version number" do
expect(<%= config[:constant_name] %>::VERSION).not_to be nil
diff --git a/lib/bundler/templates/newgem/spec/spec_helper.rb.tt b/lib/bundler/templates/newgem/spec/spec_helper.rb.tt
index 805cf57e01..70c6d1fcde 100644
--- a/lib/bundler/templates/newgem/spec/spec_helper.rb.tt
+++ b/lib/bundler/templates/newgem/spec/spec_helper.rb.tt
@@ -1,4 +1,5 @@
-require "bundler/setup"
+# frozen_string_literal: true
+
require "<%= config[:namespaced_path] %>"
RSpec.configure do |config|
diff --git a/lib/bundler/templates/newgem/standard.yml.tt b/lib/bundler/templates/newgem/standard.yml.tt
new file mode 100644
index 0000000000..9e88fbbe8b
--- /dev/null
+++ b/lib/bundler/templates/newgem/standard.yml.tt
@@ -0,0 +1,2 @@
+# For available configuration options, see:
+# https://github.com/testdouble/standard
diff --git a/lib/bundler/templates/newgem/test/minitest/newgem_test.rb.tt b/lib/bundler/templates/newgem/test/minitest/newgem_test.rb.tt
new file mode 100644
index 0000000000..9e005d69a8
--- /dev/null
+++ b/lib/bundler/templates/newgem/test/minitest/newgem_test.rb.tt
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class <%= config[:constant_name] %>Test < Minitest::Test
+ def test_that_it_has_a_version_number
+ refute_nil ::<%= config[:constant_name] %>::VERSION
+ end
+
+ def test_it_does_something_useful
+ assert false
+ end
+end
diff --git a/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt b/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt
new file mode 100644
index 0000000000..e05c387bfa
--- /dev/null
+++ b/lib/bundler/templates/newgem/test/minitest/test_helper.rb.tt
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
+require "<%= config[:namespaced_path] %>"
+
+require "minitest/autorun"
diff --git a/lib/bundler/templates/newgem/test/newgem_test.rb.tt b/lib/bundler/templates/newgem/test/newgem_test.rb.tt
deleted file mode 100644
index f2af9f90e0..0000000000
--- a/lib/bundler/templates/newgem/test/newgem_test.rb.tt
+++ /dev/null
@@ -1,11 +0,0 @@
-require "test_helper"
-
-class <%= config[:constant_name] %>Test < Minitest::Test
- def test_that_it_has_a_version_number
- refute_nil ::<%= config[:constant_name] %>::VERSION
- end
-
- def test_it_does_something_useful
- assert false
- end
-end
diff --git a/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt b/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt
new file mode 100644
index 0000000000..5c61094e62
--- /dev/null
+++ b/lib/bundler/templates/newgem/test/test-unit/newgem_test.rb.tt
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class <%= config[:constant_name] %>Test < Test::Unit::TestCase
+ test "VERSION" do
+ assert do
+ ::<%= config[:constant_name] %>.const_defined?(:VERSION)
+ end
+ end
+
+ test "something useful" do
+ assert_equal("expected", "actual")
+ end
+end
diff --git a/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt b/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt
new file mode 100644
index 0000000000..6f633c6039
--- /dev/null
+++ b/lib/bundler/templates/newgem/test/test-unit/test_helper.rb.tt
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
+require "<%= config[:namespaced_path] %>"
+
+require "test-unit"
diff --git a/lib/bundler/templates/newgem/test/test_helper.rb.tt b/lib/bundler/templates/newgem/test/test_helper.rb.tt
deleted file mode 100644
index 7d7db165ec..0000000000
--- a/lib/bundler/templates/newgem/test/test_helper.rb.tt
+++ /dev/null
@@ -1,4 +0,0 @@
-$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
-require "<%= config[:namespaced_path] %>"
-
-require "minitest/autorun"
diff --git a/lib/bundler/ui/shell.rb b/lib/bundler/ui/shell.rb
index 92476be7d2..17777af4ac 100644
--- a/lib/bundler/ui/shell.rb
+++ b/lib/bundler/ui/shell.rb
@@ -28,17 +28,17 @@ module Bundler
tell_me(msg, :green, newline) if level("confirm")
end
- def warn(msg, newline = nil)
+ def warn(msg, newline = nil, color = :yellow)
return unless level("warn")
return if @warning_history.include? msg
@warning_history << msg
- tell_err(msg, :yellow, newline)
+ tell_err(msg, color, newline)
end
- def error(msg, newline = nil)
+ def error(msg, newline = nil, color = :red)
return unless level("error")
- tell_err(msg, :red, newline)
+ tell_err(msg, color, newline)
end
def debug(msg, newline = nil)
@@ -92,7 +92,7 @@ module Bundler
[]
end
- private
+ private
# valimism
def tell_me(msg, color = nil, newline = nil)
diff --git a/lib/bundler/uri_credentials_filter.rb b/lib/bundler/uri_credentials_filter.rb
index 9b9e9c2799..ccfaf0bc5d 100644
--- a/lib/bundler/uri_credentials_filter.rb
+++ b/lib/bundler/uri_credentials_filter.rb
@@ -2,12 +2,14 @@
module Bundler
module URICredentialsFilter
- module_function
+ module_function
def credential_filtered_uri(uri_to_anonymize)
return uri_to_anonymize if uri_to_anonymize.nil?
uri = uri_to_anonymize.dup
if uri.is_a?(String)
+ return uri if File.exist?(uri)
+
require_relative "vendored_uri"
uri = Bundler::URI(uri)
end
diff --git a/lib/bundler/vendor/.document b/lib/bundler/vendor/.document
new file mode 100644
index 0000000000..0c43bbd6b3
--- /dev/null
+++ b/lib/bundler/vendor/.document
@@ -0,0 +1 @@
+# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/connection_pool/LICENSE b/lib/bundler/vendor/connection_pool/LICENSE
new file mode 100644
index 0000000000..7673cbfb7a
--- /dev/null
+++ b/lib/bundler/vendor/connection_pool/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2011 Mike Perham
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
index fbcd26c765..984c1c3dcb 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
@@ -1,14 +1,18 @@
-require_relative 'connection_pool/version'
-require_relative 'connection_pool/timed_stack'
+require "timeout"
+require_relative "connection_pool/version"
+class Bundler::ConnectionPool
+ class Error < ::RuntimeError; end
+ class PoolShuttingDownError < ::Bundler::ConnectionPool::Error; end
+ class TimeoutError < ::Timeout::Error; end
+end
-# Generic connection pool class for e.g. sharing a limited number of network connections
-# among many threads. Note: Connections are lazily created.
+# Generic connection pool class for sharing a limited number of objects or network connections
+# among many threads. Note: pool elements are lazily created.
#
# Example usage with block (faster):
#
# @pool = Bundler::ConnectionPool.new { Redis.new }
-#
# @pool.with do |redis|
# redis.lpop('my-list') if redis.llen('my-list') > 0
# end
@@ -34,29 +38,23 @@ require_relative 'connection_pool/timed_stack'
class Bundler::ConnectionPool
DEFAULTS = {size: 5, timeout: 5}
- class Error < RuntimeError
- end
-
def self.wrap(options, &block)
Wrapper.new(options, &block)
end
def initialize(options = {}, &block)
- raise ArgumentError, 'Connection pool requires a block' unless block
+ raise ArgumentError, "Connection pool requires a block" unless block
options = DEFAULTS.merge(options)
- @size = options.fetch(:size)
+ @size = Integer(options.fetch(:size))
@timeout = options.fetch(:timeout)
@available = TimedStack.new(@size, &block)
- @key = :"current-#{@available.object_id}"
- @key_count = :"current-#{@available.object_id}-count"
+ @key = :"pool-#{@available.object_id}"
+ @key_count = :"pool-#{@available.object_id}-count"
end
-if Thread.respond_to?(:handle_interrupt)
-
- # MRI
def with(options = {})
Thread.handle_interrupt(Exception => :never) do
conn = checkout(options)
@@ -69,28 +67,15 @@ if Thread.respond_to?(:handle_interrupt)
end
end
end
-
-else
-
- # jruby 1.7.x
- def with(options = {})
- conn = checkout(options)
- begin
- yield conn
- ensure
- checkin
- end
- end
-
-end
+ alias then with
def checkout(options = {})
if ::Thread.current[@key]
- ::Thread.current[@key_count]+= 1
+ ::Thread.current[@key_count] += 1
::Thread.current[@key]
else
- ::Thread.current[@key_count]= 1
- ::Thread.current[@key]= @available.pop(options[:timeout] || @timeout)
+ ::Thread.current[@key_count] = 1
+ ::Thread.current[@key] = @available.pop(options[:timeout] || @timeout)
end
end
@@ -98,64 +83,44 @@ end
if ::Thread.current[@key]
if ::Thread.current[@key_count] == 1
@available.push(::Thread.current[@key])
- ::Thread.current[@key]= nil
+ ::Thread.current[@key] = nil
+ ::Thread.current[@key_count] = nil
else
- ::Thread.current[@key_count]-= 1
+ ::Thread.current[@key_count] -= 1
end
else
- raise Bundler::ConnectionPool::Error, 'no connections are checked out'
+ raise Bundler::ConnectionPool::Error, "no connections are checked out"
end
nil
end
+ ##
+ # Shuts down the Bundler::ConnectionPool by passing each connection to +block+ and
+ # then removing it from the pool. Attempting to checkout a connection after
+ # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+.
+
def shutdown(&block)
@available.shutdown(&block)
end
- # Size of this connection pool
- def size
- @size
+ ##
+ # Reloads the Bundler::ConnectionPool by passing each connection to +block+ and then
+ # removing it the pool. Subsequent checkouts will create new connections as
+ # needed.
+
+ def reload(&block)
+ @available.shutdown(reload: true, &block)
end
+ # Size of this connection pool
+ attr_reader :size
+
# Number of pool entries available for checkout at this instant.
def available
@available.length
end
-
- private
-
- class Wrapper < ::BasicObject
- METHODS = [:with, :pool_shutdown]
-
- def initialize(options = {}, &block)
- @pool = options.fetch(:pool) { ::Bundler::ConnectionPool.new(options, &block) }
- end
-
- def with(&block)
- @pool.with(&block)
- end
-
- def pool_shutdown(&block)
- @pool.shutdown(&block)
- end
-
- def pool_size
- @pool.size
- end
-
- def pool_available
- @pool.available
- end
-
- def respond_to?(id, *args)
- METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
- end
-
- def method_missing(name, *args, &block)
- with do |connection|
- connection.send(name, *args, &block)
- end
- end
- end
end
+
+require_relative "connection_pool/timed_stack"
+require_relative "connection_pool/wrapper"
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb
deleted file mode 100644
index 5a9c4a27bb..0000000000
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# Global monotonic clock from Concurrent Ruby 1.0.
-# Copyright (c) Jerry D'Antonio -- released under the MIT license.
-# Slightly modified; used with permission.
-# https://github.com/ruby-concurrency/concurrent-ruby
-
-require 'thread'
-
-class Bundler::ConnectionPool
-
- class_definition = Class.new do
-
- if defined?(Process::CLOCK_MONOTONIC)
-
- # @!visibility private
- def get_time
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
- end
-
- elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
-
- # @!visibility private
- def get_time
- java.lang.System.nanoTime() / 1_000_000_000.0
- end
-
- else
-
- # @!visibility private
- def initialize
- @mutex = Mutex.new
- @last_time = Time.now.to_f
- end
-
- # @!visibility private
- def get_time
- @mutex.synchronize do
- now = Time.now.to_f
- if @last_time < now
- @last_time = now
- else # clock has moved back in time
- @last_time += 0.000_001
- end
- end
- end
- end
- end
-
- ##
- # Clock that cannot be set and represents monotonic time since
- # some unspecified starting point.
- #
- # @!visibility private
- GLOBAL_MONOTONIC_CLOCK = class_definition.new
- private_constant :GLOBAL_MONOTONIC_CLOCK
-
- class << self
- ##
- # Returns the current time a tracked by the application monotonic clock.
- #
- # @return [Float] The current monotonic time when `since` not given else
- # the elapsed monotonic time between `since` and the current time
- def monotonic_time
- GLOBAL_MONOTONIC_CLOCK.get_time
- end
- end
-end
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb
index f3fe1e04ad..a7b1cf06a8 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,13 +1,3 @@
-require 'thread'
-require 'timeout'
-require_relative 'monotonic_time'
-
-##
-# Raised when you attempt to retrieve a connection from a pool that has been
-# shut down.
-
-class Bundler::ConnectionPool::PoolShuttingDownError < RuntimeError; end
-
##
# The TimedStack manages a pool of homogeneous connections (or any resource
# you wish to manage). Connections are created lazily up to a given maximum
@@ -25,7 +15,7 @@ class Bundler::ConnectionPool::PoolShuttingDownError < RuntimeError; end
#
# conn = ts.pop
# ts.pop timeout: 5
-# #=> raises Timeout::Error after 5 seconds
+# #=> raises Bundler::ConnectionPool::TimeoutError after 5 seconds
class Bundler::ConnectionPool::TimedStack
attr_reader :max
@@ -39,8 +29,8 @@ class Bundler::ConnectionPool::TimedStack
@created = 0
@que = []
@max = size
- @mutex = Mutex.new
- @resource = ConditionVariable.new
+ @mutex = Thread::Mutex.new
+ @resource = Thread::ConditionVariable.new
@shutdown_block = nil
end
@@ -59,12 +49,12 @@ class Bundler::ConnectionPool::TimedStack
@resource.broadcast
end
end
- alias_method :<<, :push
+ alias << push
##
# Retrieves a connection from the stack. If a connection is available it is
# immediately returned. If no connection is available within the given
- # timeout a Timeout::Error is raised.
+ # timeout a Bundler::ConnectionPool::TimeoutError is raised.
#
# +:timeout+ is the only checked entry in +options+ and is preferred over
# the +timeout+ argument (which will be removed in a future release). Other
@@ -74,7 +64,7 @@ class Bundler::ConnectionPool::TimedStack
options, timeout = timeout, 0.5 if Hash === timeout
timeout = options.fetch :timeout, timeout
- deadline = Bundler::ConnectionPool.monotonic_time + timeout
+ deadline = current_time + timeout
@mutex.synchronize do
loop do
raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
@@ -83,18 +73,20 @@ class Bundler::ConnectionPool::TimedStack
connection = try_create(options)
return connection if connection
- to_wait = deadline - Bundler::ConnectionPool.monotonic_time
- raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
+ to_wait = deadline - current_time
+ raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec" if to_wait <= 0
@resource.wait(@mutex, to_wait)
end
end
end
##
- # Shuts down the TimedStack which prevents connections from being checked
- # out. The +block+ is called once for each connection on the stack.
+ # Shuts down the TimedStack by passing each connection to +block+ and then
+ # removing it from the pool. Attempting to checkout a connection after
+ # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+ unless
+ # +:reload+ is +true+.
- def shutdown(&block)
+ def shutdown(reload: false, &block)
raise ArgumentError, "shutdown must receive a block" unless block_given?
@mutex.synchronize do
@@ -102,6 +94,7 @@ class Bundler::ConnectionPool::TimedStack
@resource.broadcast
shutdown_connections
+ @shutdown_block = nil if reload
end
end
@@ -121,6 +114,10 @@ class Bundler::ConnectionPool::TimedStack
private
+ def current_time
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ end
+
##
# This is an extension point for TimedStack and is called with a mutex.
#
@@ -149,6 +146,7 @@ class Bundler::ConnectionPool::TimedStack
conn = fetch_connection(options)
@shutdown_block.call(conn)
end
+ @created = 0
end
##
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 b149c0e242..56ebf69902 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.2.2"
+ VERSION = "2.3.0"
end
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb
new file mode 100644
index 0000000000..880170c06b
--- /dev/null
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb
@@ -0,0 +1,57 @@
+class Bundler::ConnectionPool
+ class Wrapper < ::BasicObject
+ METHODS = [:with, :pool_shutdown, :wrapped_pool]
+
+ def initialize(options = {}, &block)
+ @pool = options.fetch(:pool) { ::Bundler::ConnectionPool.new(options, &block) }
+ end
+
+ def wrapped_pool
+ @pool
+ end
+
+ def with(&block)
+ @pool.with(&block)
+ end
+
+ def pool_shutdown(&block)
+ @pool.shutdown(&block)
+ end
+
+ def pool_size
+ @pool.size
+ end
+
+ def pool_available
+ @pool.available
+ end
+
+ def respond_to?(id, *args)
+ METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
+ end
+
+ # rubocop:disable Style/MethodMissingSuper
+ # rubocop:disable Style/MissingRespondToMissing
+ if ::RUBY_VERSION >= "3.0.0"
+ def method_missing(name, *args, **kwargs, &block)
+ with do |connection|
+ connection.send(name, *args, **kwargs, &block)
+ end
+ end
+ elsif ::RUBY_VERSION >= "2.7.0"
+ ruby2_keywords def method_missing(name, *args, &block)
+ with do |connection|
+ connection.send(name, *args, &block)
+ end
+ end
+ else
+ def method_missing(name, *args, &block)
+ with do |connection|
+ connection.send(name, *args, &block)
+ end
+ end
+ end
+ # rubocop:enable Style/MethodMissingSuper
+ # rubocop:enable Style/MissingRespondToMissing
+ end
+end
diff --git a/lib/bundler/vendor/fileutils/LICENSE.txt b/lib/bundler/vendor/fileutils/LICENSE.txt
new file mode 100644
index 0000000000..a009caefea
--- /dev/null
+++ b/lib/bundler/vendor/fileutils/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/lib/bundler/vendor/fileutils/lib/fileutils/version.rb b/lib/bundler/vendor/fileutils/lib/fileutils/version.rb
deleted file mode 100644
index b8f616e4fb..0000000000
--- a/lib/bundler/vendor/fileutils/lib/fileutils/version.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::FileUtils
- VERSION = "1.3.0"
-end
diff --git a/lib/bundler/vendor/molinillo/LICENSE b/lib/bundler/vendor/molinillo/LICENSE
new file mode 100644
index 0000000000..01feffa088
--- /dev/null
+++ b/lib/bundler/vendor/molinillo/LICENSE
@@ -0,0 +1,9 @@
+This project is licensed under the MIT license.
+
+Copyright (c) 2014 Samuel E. Giddins segiddins@segiddins.me
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo.rb b/lib/bundler/vendor/molinillo/lib/molinillo.rb
index baedefe98b..a52b96deaf 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require_relative 'molinillo/compatibility'
require_relative 'molinillo/gem_metadata'
require_relative 'molinillo/errors'
require_relative 'molinillo/resolver'
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb b/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb
deleted file mode 100644
index 3eba8e4083..0000000000
--- a/lib/bundler/vendor/molinillo/lib/molinillo/compatibility.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler::Molinillo
- # Hacks needed for old Ruby versions.
- module Compatibility
- module_function
-
- if [].respond_to?(:flat_map)
- # Flat map
- # @param [Enumerable] enum an enumerable object
- # @block the block to flat-map with
- # @return The enum, flat-mapped
- def flat_map(enum, &blk)
- enum.flat_map(&blk)
- end
- else
- # Flat map
- # @param [Enumerable] enum an enumerable object
- # @block the block to flat-map with
- # @return The enum, flat-mapped
- def flat_map(enum, &blk)
- enum.map(&blk).flatten(1)
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb b/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb
index ec9c770a28..f8c695c1ed 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/delegates/specification_provider.rb
@@ -26,6 +26,13 @@ module Bundler::Molinillo
end
end
+ # (see Bundler::Molinillo::SpecificationProvider#dependencies_equal?)
+ def dependencies_equal?(dependencies, other_dependencies)
+ with_no_such_dependency_error_handling do
+ specification_provider.dependencies_equal?(dependencies, other_dependencies)
+ end
+ end
+
# (see Bundler::Molinillo::SpecificationProvider#name_for)
def name_for(dependency)
with_no_such_dependency_error_handling do
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
index 31578bb5bf..10a25d2f08 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
-require 'set'
-require 'tsort'
+require_relative '../../../../vendored_tsort'
require_relative 'dependency_graph/log'
require_relative 'dependency_graph/vertex'
@@ -18,7 +17,7 @@ module Bundler::Molinillo
vertices.values.each { |v| yield v }
end
- include TSort
+ include Bundler::TSort
# @!visibility private
alias tsort_each_node each
@@ -124,6 +123,7 @@ module Bundler::Molinillo
dot.join("\n")
end
+ # @param [DependencyGraph] other
# @return [Boolean] whether the two dependency graphs are equal, determined
# by a recursive traversal of each {#root_vertices} and its
# {Vertex#successors}
@@ -190,7 +190,7 @@ module Bundler::Molinillo
# @return [Edge] the added edge
def add_edge(origin, destination, requirement)
if destination.path_to?(origin)
- raise CircularDependencyError.new([origin, destination])
+ raise CircularDependencyError.new(path(destination, origin))
end
add_edge_no_circular(origin, destination, requirement)
end
@@ -219,5 +219,37 @@ module Bundler::Molinillo
def add_edge_no_circular(origin, destination, requirement)
log.add_edge_no_circular(self, origin.name, destination.name, requirement)
end
+
+ # Returns the path between two vertices
+ # @raise [ArgumentError] if there is no path between the vertices
+ # @param [Vertex] from
+ # @param [Vertex] to
+ # @return [Array<Vertex>] the shortest path from `from` to `to`
+ def path(from, to)
+ distances = Hash.new(vertices.size + 1)
+ distances[from.name] = 0
+ predecessors = {}
+ each do |vertex|
+ vertex.successors.each do |successor|
+ if distances[successor.name] > distances[vertex.name] + 1
+ distances[successor.name] = distances[vertex.name] + 1
+ predecessors[successor] = vertex
+ end
+ end
+ end
+
+ path = [to]
+ while before = predecessors[to]
+ path << before
+ to = before
+ break if to == from
+ end
+
+ unless path.last.equal?(from)
+ raise ArgumentError, "There is no path from #{from.name} to #{to.name}"
+ end
+
+ path.reverse
+ end
end
end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb
index fccfc78cc7..5b5da3e4f9 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/tag.rb
@@ -14,11 +14,11 @@ module Bundler::Molinillo
end
# (see Action#up)
- def up(_graph)
+ def up(graph)
end
# (see Action#down)
- def down(_graph)
+ def down(graph)
end
# @!group Tag
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb
index 41bc013143..1185a8ab05 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph/vertex.rb
@@ -59,7 +59,7 @@ module Bundler::Molinillo
# @param [Set<Vertex>] vertices the set to add the predecessors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is a
# {#descendent?}
- def _recursive_predecessors(vertices = Set.new)
+ def _recursive_predecessors(vertices = new_vertex_set)
incoming_edges.each do |edge|
vertex = edge.origin
next unless vertices.add?(vertex)
@@ -85,7 +85,7 @@ module Bundler::Molinillo
# @param [Set<Vertex>] vertices the set to add the successors to
# @return [Set<Vertex>] the vertices of {#graph} where `self` is an
# {#ancestor?}
- def _recursive_successors(vertices = Set.new)
+ def _recursive_successors(vertices = new_vertex_set)
outgoing_edges.each do |edge|
vertex = edge.destination
next unless vertices.add?(vertex)
@@ -128,7 +128,7 @@ module Bundler::Molinillo
# Is there a path from `self` to `other` following edges in the
# dependency graph?
- # @return true iff there is a path following edges within this {#graph}
+ # @return whether there is a path following edges within this {#graph}
def path_to?(other)
_path_to?(other)
end
@@ -138,7 +138,7 @@ module Bundler::Molinillo
# @param [Vertex] other the vertex to check if there's a path to
# @param [Set<Vertex>] visited the vertices of {#graph} that have been visited
# @return [Boolean] whether there is a path to `other` from `self`
- def _path_to?(other, visited = Set.new)
+ def _path_to?(other, visited = new_vertex_set)
return false unless visited.add?(self)
return true if equal?(other)
successors.any? { |v| v._path_to?(other, visited) }
@@ -147,12 +147,18 @@ module Bundler::Molinillo
# Is there a path from `other` to `self` following edges in the
# dependency graph?
- # @return true iff there is a path following edges within this {#graph}
+ # @return whether there is a path following edges within this {#graph}
def ancestor?(other)
other.path_to?(self)
end
alias is_reachable_from? ancestor?
+
+ def new_vertex_set
+ require 'set'
+ Set.new
+ end
+ private :new_vertex_set
end
end
end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb b/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
index 89c7c324d5..e210202b69 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/errors.rb
@@ -34,7 +34,7 @@ module Bundler::Molinillo
# An error caused by attempting to fulfil a dependency that was circular
#
- # @note This exception will be thrown iff a {Vertex} is added to a
+ # @note This exception will be thrown if and only if a {Vertex} is added to a
# {DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an
# existing {DependencyGraph::Vertex}
class CircularDependencyError < ResolverError
@@ -65,7 +65,7 @@ module Bundler::Molinillo
# @param [SpecificationProvider] specification_provider see {#specification_provider}
def initialize(conflicts, specification_provider)
pairs = []
- Compatibility.flat_map(conflicts.values.flatten, &:requirements).each do |conflicting|
+ conflicts.values.flat_map(&:requirements).each do |conflicting|
conflicting.each do |source, conflict_requirements|
conflict_requirements.each do |c|
pairs << [c, source]
@@ -121,7 +121,7 @@ module Bundler::Molinillo
t = ''.dup
depth = 2
tree.each do |req|
- t << ' ' * depth << req.to_s
+ t << ' ' * depth << printable_requirement.call(req)
unless tree.last == req
if spec = conflict.activated_by_name[name_for(req)]
t << %( was resolved to #{version_for_spec.call(spec)}, which)
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb b/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb
index 73f8fbf2ac..e13a781a50 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/gem_metadata.rb
@@ -2,5 +2,5 @@
module Bundler::Molinillo
# The version of Bundler::Molinillo.
- VERSION = '0.6.6'.freeze
+ VERSION = '0.7.0'.freeze
end
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb b/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
index fa094c1981..eeae79af3c 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/modules/specification_provider.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Bundler::Molinillo
- # Provides information about specifcations and dependencies to the resolver,
+ # Provides information about specifications and dependencies to the resolver,
# allowing the {Resolver} class to remain generic while still providing power
# and flexibility.
#
@@ -45,6 +45,17 @@ module Bundler::Molinillo
true
end
+ # Determines whether two arrays of dependencies are equal, and thus can be
+ # grouped.
+ #
+ # @param [Array<Object>] dependencies
+ # @param [Array<Object>] other_dependencies
+ # @return [Boolean] whether `dependencies` and `other_dependencies` should
+ # be considered equal.
+ def dependencies_equal?(dependencies, other_dependencies)
+ dependencies == other_dependencies
+ end
+
# Returns the name for the given `dependency`.
# @note This method should be 'pure', i.e. the return value should depend
# only on the `dependency` parameter.
diff --git a/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb b/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
index acf7777414..c689ca7635 100644
--- a/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
+++ b/lib/bundler/vendor/molinillo/lib/molinillo/resolution.rb
@@ -207,7 +207,7 @@ module Bundler::Molinillo
def start_resolution
@started_at = Time.now
- handle_missing_or_push_dependency_state(initial_state)
+ push_initial_state
debug { "Starting resolution (#{@started_at})\nUser-requested dependencies: #{original_requested}" }
resolver_ui.before_resolution
@@ -273,10 +273,10 @@ module Bundler::Molinillo
states.last
end
- # Creates the initial state for the resolution, based upon the
+ # Creates and pushes the initial state for the resolution, based upon the
# {#requested} dependencies
- # @return [DependencyState] the initial state for the resolution
- def initial_state
+ # @return [void]
+ def push_initial_state
graph = DependencyGraph.new.tap do |dg|
original_requested.each do |requested|
vertex = dg.add_vertex(name_for(requested), nil, true)
@@ -285,18 +285,7 @@ module Bundler::Molinillo
dg.tag(:initial_state)
end
- requirements = sort_dependencies(original_requested, graph, {})
- initial_requirement = requirements.shift
- DependencyState.new(
- initial_requirement && name_for(initial_requirement),
- requirements,
- graph,
- initial_requirement,
- possibilities_for_requirement(initial_requirement, graph),
- 0,
- {},
- []
- )
+ push_state_for_requirements(original_requested, true, graph)
end
# Unwinds the states stack because a conflict has been encountered
@@ -340,11 +329,11 @@ module Bundler::Molinillo
# Look for past conflicts that could be unwound to affect the
# requirement tree for the current conflict
+ all_reqs = last_detail_for_current_unwind.all_requirements
+ all_reqs_size = all_reqs.size
relevant_unused_unwinds = unused_unwind_options.select do |alternative|
- intersecting_requirements =
- last_detail_for_current_unwind.all_requirements &
- alternative.requirements_unwound_to_instead
- next if intersecting_requirements.empty?
+ diff_reqs = all_reqs - alternative.requirements_unwound_to_instead
+ next if diff_reqs.size == all_reqs_size
# Find the highest index unwind whilst looping through
current_detail = alternative if alternative > current_detail
alternative
@@ -355,13 +344,17 @@ module Bundler::Molinillo
state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 }
# Update the requirements_unwound_to_instead on any relevant unused unwinds
- relevant_unused_unwinds.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
- unwind_details.each { |d| d.requirements_unwound_to_instead << current_detail.state_requirement }
+ relevant_unused_unwinds.each do |d|
+ (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
+ end
+ unwind_details.each do |d|
+ (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
+ end
current_detail
end
- # @param [Array<Object>] array of requirements that combine to create a conflict
+ # @param [Array<Object>] binding_requirements array of requirements that combine to create a conflict
# @return [Array<UnwindDetails>] array of UnwindDetails that have a chance
# of resolving the passed requirements
def unwind_options_for_requirements(binding_requirements)
@@ -429,7 +422,7 @@ module Bundler::Molinillo
end
# @param [DependencyState] state
- # @param [Array] array of requirements
+ # @param [Array] binding_requirements array of requirements
# @return [Boolean] whether or not the given state has any possibilities
# that could satisfy the given requirements
def conflict_fixing_possibilities?(state, binding_requirements)
@@ -444,7 +437,8 @@ module Bundler::Molinillo
# Filter's a state's possibilities to remove any that would not fix the
# conflict we've just rewound from
- # @param [UnwindDetails] details of the conflict just unwound from
+ # @param [UnwindDetails] unwind_details details of the conflict just
+ # unwound from
# @return [void]
def filter_possibilities_after_unwind(unwind_details)
return unless state && !state.possibilities.empty?
@@ -458,7 +452,7 @@ module Bundler::Molinillo
# Filter's a state's possibilities to remove any that would not satisfy
# the requirements in the conflict we've just rewound from
- # @param [UnwindDetails] details of the conflict just unwound from
+ # @param [UnwindDetails] unwind_details details of the conflict just unwound from
# @return [void]
def filter_possibilities_for_primary_unwind(unwind_details)
unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
@@ -491,7 +485,7 @@ module Bundler::Molinillo
# Filter's a state's possibilities to remove any that would (eventually)
# create a requirement in the conflict we've just rewound from
- # @param [UnwindDetails] details of the conflict just unwound from
+ # @param [UnwindDetails] unwind_details details of the conflict just unwound from
# @return [void]
def filter_possibilities_for_parent_unwind(unwind_details)
unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
@@ -500,7 +494,7 @@ module Bundler::Molinillo
primary_unwinds = unwinds_to_state.select(&:unwinding_to_primary_requirement?).uniq
parent_unwinds = unwinds_to_state.uniq - primary_unwinds
- allowed_possibility_sets = Compatibility.flat_map(primary_unwinds) do |unwind|
+ allowed_possibility_sets = primary_unwinds.flat_map do |unwind|
states[unwind.state_index].possibilities.select do |possibility_set|
possibility_set.possibilities.any? do |poss|
possibility_satisfies_requirements?(poss, unwind.conflicting_requirements)
@@ -508,7 +502,7 @@ module Bundler::Molinillo
end
end
- requirements_to_avoid = Compatibility.flat_map(parent_unwinds, &:sub_dependencies_to_avoid)
+ requirements_to_avoid = parent_unwinds.flat_map(&:sub_dependencies_to_avoid)
state.possibilities.reject! do |possibility_set|
!allowed_possibility_sets.include?(possibility_set) &&
@@ -524,12 +518,12 @@ module Bundler::Molinillo
possible_binding_requirements = conflict.requirements.values.flatten(1).uniq
- # When there’s a `CircularDependency` error the conflicting requirement
- # (the one causing the circular) won’t be `conflict.requirement`
- # (which won’t be for the right state, because we won’t have created it,
- # because it’s circular).
- # We need to make sure we have that requirement in the conflict’s list,
- # otherwise we won’t be able to unwind properly, so we just return all
+ # When there's a `CircularDependency` error the conflicting requirement
+ # (the one causing the circular) won't be `conflict.requirement`
+ # (which won't be for the right state, because we won't have created it,
+ # because it's circular).
+ # We need to make sure we have that requirement in the conflict's list,
+ # otherwise we won't be able to unwind properly, so we just return all
# the requirements for the conflict.
return possible_binding_requirements if conflict.underlying_error
@@ -558,8 +552,8 @@ module Bundler::Molinillo
end
# @param [Object] requirement we wish to check
- # @param [Array] array of requirements
- # @param [Array] array of possibilities the requirements will be used to filter
+ # @param [Array] possible_binding_requirements array of requirements
+ # @param [Array] possibilities array of possibilities the requirements will be used to filter
# @return [Boolean] whether or not the given requirement is required to filter
# out all elements of the array of possibilities.
def binding_requirement_in_set?(requirement, possible_binding_requirements, possibilities)
@@ -568,6 +562,7 @@ module Bundler::Molinillo
end
end
+ # @param [Object] requirement
# @return [Object] the requirement that led to `requirement` being added
# to the list of requirements.
def parent_of(requirement)
@@ -577,6 +572,7 @@ module Bundler::Molinillo
parent_state.requirement
end
+ # @param [String] name
# @return [Object] the requirement that led to a version of a possibility
# with the given name being activated.
def requirement_for_existing_name(name)
@@ -585,6 +581,7 @@ module Bundler::Molinillo
states.find { |s| s.name == name }.requirement
end
+ # @param [Object] requirement
# @return [ResolutionState] the state whose `requirement` is the given
# `requirement`.
def find_state_for(requirement)
@@ -592,6 +589,7 @@ module Bundler::Molinillo
states.find { |i| requirement == i.requirement }
end
+ # @param [Object] underlying_error
# @return [Conflict] a {Conflict} that reflects the failure to activate
# the {#possibility} in conjunction with the current {#state}
def create_conflict(underlying_error = nil)
@@ -628,6 +626,7 @@ module Bundler::Molinillo
vertex.requirements.map { |r| requirement_tree_for(r) }
end
+ # @param [Object] requirement
# @return [Array<Object>] the list of requirements that led to
# `requirement` being required.
def requirement_tree_for(requirement)
@@ -673,9 +672,8 @@ module Bundler::Molinillo
attempt_to_filter_existing_spec(existing_vertex)
else
latest = possibility.latest_version
- # use reject!(!satisfied) for 1.8.7 compatibility
- possibility.possibilities.reject! do |possibility|
- !requirement_satisfied_by?(requirement, activated, possibility)
+ possibility.possibilities.select! do |possibility|
+ requirement_satisfied_by?(requirement, activated, possibility)
end
if possibility.latest_version.nil?
# ensure there's a possibility for better error messages
@@ -705,7 +703,7 @@ module Bundler::Molinillo
# Generates a filtered version of the existing vertex's `PossibilitySet` using the
# current state's `requirement`
- # @param [Object] existing vertex
+ # @param [Object] vertex existing vertex
# @return [PossibilitySet] filtered possibility set
def filtered_possibility_set(vertex)
PossibilitySet.new(vertex.payload.dependencies, vertex.payload.possibilities & possibility.possibilities)
@@ -730,7 +728,7 @@ module Bundler::Molinillo
end
# Requires the dependencies that the recently activated spec has
- # @param [Object] activated_possibility the PossibilitySet that has just been
+ # @param [Object] possibility_set the PossibilitySet that has just been
# activated
# @return [void]
def require_nested_dependencies_for(possibility_set)
@@ -749,6 +747,8 @@ module Bundler::Molinillo
# Pushes a new {DependencyState} that encapsulates both existing and new
# requirements
# @param [Array] new_requirements
+ # @param [Boolean] requires_sort
+ # @param [Object] new_activated
# @return [void]
def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated)
new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort
@@ -767,7 +767,8 @@ module Bundler::Molinillo
# Checks a proposed requirement with any existing locked requirement
# before generating an array of possibilities for it.
- # @param [Object] the proposed requirement
+ # @param [Object] requirement the proposed requirement
+ # @param [Object] activated
# @return [Array] possibilities
def possibilities_for_requirement(requirement, activated = self.activated)
return [] unless requirement
@@ -778,7 +779,8 @@ module Bundler::Molinillo
group_possibilities(search_for(requirement))
end
- # @param [Object] the proposed requirement
+ # @param [Object] requirement the proposed requirement
+ # @param [Object] activated
# @return [Array] possibility set containing only the locked requirement, if any
def locked_requirement_possibility_set(requirement, activated = self.activated)
all_possibilities = search_for(requirement)
@@ -797,15 +799,15 @@ module Bundler::Molinillo
# Build an array of PossibilitySets, with each element representing a group of
# dependency versions that all have the same sub-dependency version constraints
# and are contiguous.
- # @param [Array] an array of possibilities
- # @return [Array] an array of possibility sets
+ # @param [Array] possibilities an array of possibilities
+ # @return [Array<PossibilitySet>] an array of possibility sets
def group_possibilities(possibilities)
possibility_sets = []
current_possibility_set = nil
possibilities.reverse_each do |possibility|
dependencies = dependencies_for(possibility)
- if current_possibility_set && current_possibility_set.dependencies == dependencies
+ if current_possibility_set && dependencies_equal?(current_possibility_set.dependencies, dependencies)
current_possibility_set.possibilities.unshift(possibility)
else
possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility]))
diff --git a/lib/bundler/vendor/net-http-persistent/README.rdoc b/lib/bundler/vendor/net-http-persistent/README.rdoc
new file mode 100644
index 0000000000..4f95ad33ba
--- /dev/null
+++ b/lib/bundler/vendor/net-http-persistent/README.rdoc
@@ -0,0 +1,82 @@
+= net-http-persistent
+
+home :: https://github.com/drbrain/net-http-persistent
+rdoc :: http://docs.seattlerb.org/net-http-persistent
+
+== DESCRIPTION:
+
+Manages persistent connections using Net::HTTP including a thread pool for
+connecting to multiple hosts.
+
+Using persistent HTTP connections can dramatically increase the speed of HTTP.
+Creating a new HTTP connection for every request involves an extra TCP
+round-trip and causes TCP congestion avoidance negotiation to start over.
+
+Net::HTTP supports persistent connections with some API methods but does not
+make setting up a single persistent connection or managing multiple
+connections easy. Net::HTTP::Persistent wraps Net::HTTP and allows you to
+focus on how to make HTTP requests.
+
+== FEATURES/PROBLEMS:
+
+* Supports TLS with secure defaults
+* Thread-safe
+* Pure ruby
+
+== SYNOPSIS
+
+The following example will make two requests to the same server. The
+connection is kept alive between requests:
+
+ require 'net/http/persistent'
+
+ uri = URI 'http://example.com/awesome/web/service'
+
+ http = Net::HTTP::Persistent.new name: 'my_app_name'
+
+ # perform a GET
+ response = http.request uri
+
+ # create a POST
+ post_uri = uri + 'create'
+ post = Net::HTTP::Post.new post_uri.path
+ post.set_form_data 'some' => 'cool data'
+
+ # perform the POST, the URI is always required
+ response = http.request post_uri, post
+
+ # if you are done making http requests, or won't make requests for several
+ # minutes
+ http.shutdown
+
+Please see the documentation on Net::HTTP::Persistent for more information,
+including SSL connection verification, header handling and tunable options.
+
+== INSTALL:
+
+ gem install net-http-persistent
+
+== LICENSE:
+
+(The MIT License)
+
+Copyright (c) Eric Hodel, Aaron Patterson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb
index f9d1401062..beff6d658b 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
@@ -12,15 +12,11 @@ autoload :OpenSSL, 'openssl'
# servers you wish to talk to. For each host:port you communicate with a
# single persistent connection is created.
#
-# Multiple Bundler::Persistent::Net::HTTP::Persistent objects will share the same set of
-# connections.
+# Connections will be shared across threads through a connection pool to
+# increase reuse of connections.
#
-# For each thread you start a new connection will be created. A
-# Bundler::Persistent::Net::HTTP::Persistent connection will not be shared across threads.
-#
-# You can shut down the HTTP connections when done by calling #shutdown. You
-# should name your Bundler::Persistent::Net::HTTP::Persistent object if you intend to call this
-# method.
+# You can shut down any remaining HTTP connections when done by calling
+# #shutdown.
#
# Example:
#
@@ -28,7 +24,7 @@ autoload :OpenSSL, 'openssl'
#
# uri = Bundler::URI 'http://example.com/awesome/web/service'
#
-# http = Bundler::Persistent::Net::HTTP::Persistent.new name: 'my_app_name'
+# http = Bundler::Persistent::Net::HTTP::Persistent.new
#
# # perform a GET
# response = http.request uri
@@ -50,14 +46,14 @@ autoload :OpenSSL, 'openssl'
# to use Bundler::URI#request_uri not Bundler::URI#path. The request_uri contains the query
# params which are sent in the body for other requests.
#
-# == SSL
+# == TLS/SSL
#
-# SSL connections are automatically created depending upon the scheme of the
-# Bundler::URI. SSL connections are automatically verified against the default
+# TLS connections are automatically created depending upon the scheme of the
+# Bundler::URI. TLS connections are automatically verified against the default
# certificate store for your computer. You can override this by changing
# verify_mode or by specifying an alternate cert_store.
#
-# Here are the SSL settings, see the individual methods for documentation:
+# Here are the TLS settings, see the individual methods for documentation:
#
# #certificate :: This client's certificate
# #ca_file :: The certificate-authorities
@@ -67,7 +63,7 @@ autoload :OpenSSL, 'openssl'
# #private_key :: The client's SSL private key
# #reuse_ssl_sessions :: Reuse a previously opened SSL session for a new
# connection
-# #ssl_timeout :: SSL session lifetime
+# #ssl_timeout :: Session lifetime
# #ssl_version :: Which specific SSL version to use
# #verify_callback :: For server certificate verification
# #verify_depth :: Depth of certificate verification
@@ -96,14 +92,15 @@ autoload :OpenSSL, 'openssl'
#
# === Segregation
#
-# By providing an application name to ::new you can separate your connections
-# from the connections of other applications.
+# Each Bundler::Persistent::Net::HTTP::Persistent instance has its own pool of connections. There
+# is no sharing with other instances (as was true in earlier versions).
#
# === Idle Timeout
#
-# If a connection hasn't been used for this number of seconds it will automatically be
-# reset upon the next use to avoid attempting to send to a closed connection.
-# The default value is 5 seconds. nil means no timeout. Set through #idle_timeout.
+# If a connection hasn't been used for this number of seconds it will
+# automatically be reset upon the next use to avoid attempting to send to a
+# closed connection. The default value is 5 seconds. nil means no timeout.
+# Set through #idle_timeout.
#
# Reducing this value may help avoid the "too many connection resets" error
# when sending non-idempotent requests while increasing this value will cause
@@ -118,8 +115,9 @@ autoload :OpenSSL, 'openssl'
#
# The number of requests that should be made before opening a new connection.
# Typically many keep-alive capable servers tune this to 100 or less, so the
-# 101st request will fail with ECONNRESET. If unset (default), this value has no
-# effect, if set, connections will be reset on the request after max_requests.
+# 101st request will fail with ECONNRESET. If unset (default), this value has
+# no effect, if set, connections will be reset on the request after
+# max_requests.
#
# === Open Timeout
#
@@ -131,45 +129,6 @@ autoload :OpenSSL, 'openssl'
# Socket options may be set on newly-created connections. See #socket_options
# for details.
#
-# === Non-Idempotent Requests
-#
-# By default non-idempotent requests will not be retried per RFC 2616. By
-# setting retry_change_requests to true requests will automatically be retried
-# once.
-#
-# Only do this when you know that retrying a POST or other non-idempotent
-# request is safe for your application and will not create duplicate
-# resources.
-#
-# The recommended way to handle non-idempotent requests is the following:
-#
-# require 'bundler/vendor/net-http-persistent/lib/net/http/persistent'
-#
-# uri = Bundler::URI 'http://example.com/awesome/web/service'
-# post_uri = uri + 'create'
-#
-# http = Bundler::Persistent::Net::HTTP::Persistent.new name: 'my_app_name'
-#
-# post = Net::HTTP::Post.new post_uri.path
-# # ... fill in POST request
-#
-# begin
-# response = http.request post_uri, post
-# rescue Bundler::Persistent::Net::HTTP::Persistent::Error
-#
-# # POST failed, make a new request to verify the server did not process
-# # the request
-# exists_uri = uri + '...'
-# response = http.get exists_uri
-#
-# # Retry if it failed
-# retry if response.code == '404'
-# end
-#
-# The method of determining if the resource was created or not is unique to
-# the particular service you are using. Of course, you will want to add
-# protection from infinite looping.
-#
# === Connection Termination
#
# If you are done using the Bundler::Persistent::Net::HTTP::Persistent instance you may shut down
@@ -195,33 +154,27 @@ class Bundler::Persistent::Net::HTTP::Persistent
HAVE_OPENSSL = defined? OpenSSL::SSL # :nodoc:
##
- # The default connection pool size is 1/4 the allowed open files.
+ # The default connection pool size is 1/4 the allowed open files
+ # (<code>ulimit -n</code>) or 256 if your OS does not support file handle
+ # limits (typically windows).
- if Gem.win_platform? then
- DEFAULT_POOL_SIZE = 256
+ if Process.const_defined? :RLIMIT_NOFILE
+ open_file_limits = Process.getrlimit(Process::RLIMIT_NOFILE)
+
+ # Under JRuby on Windows Process responds to `getrlimit` but returns something that does not match docs
+ if open_file_limits.respond_to?(:first)
+ DEFAULT_POOL_SIZE = open_file_limits.first / 4
+ else
+ DEFAULT_POOL_SIZE = 256
+ end
else
- DEFAULT_POOL_SIZE = Process.getrlimit(Process::RLIMIT_NOFILE).first / 4
+ DEFAULT_POOL_SIZE = 256
end
##
# The version of Bundler::Persistent::Net::HTTP::Persistent you are using
- VERSION = '3.1.0'
-
- ##
- # Exceptions rescued for automatic retry on ruby 2.0.0. This overlaps with
- # the exception list for ruby 1.x.
-
- RETRIED_EXCEPTIONS = [ # :nodoc:
- (Net::ReadTimeout if Net.const_defined? :ReadTimeout),
- IOError,
- EOFError,
- Errno::ECONNRESET,
- Errno::ECONNABORTED,
- Errno::EPIPE,
- (OpenSSL::SSL::SSLError if HAVE_OPENSSL),
- Timeout::Error,
- ].compact
+ VERSION = '4.0.0'
##
# Error class for errors raised by Bundler::Persistent::Net::HTTP::Persistent. Various
@@ -349,6 +302,13 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_accessor :max_requests
##
+ # Number of retries to perform if a request fails.
+ #
+ # See also #max_retries=, Net::HTTP#max_retries=.
+
+ attr_reader :max_retries
+
+ ##
# The value sent in the Keep-Alive header. Defaults to 30. Not needed for
# HTTP/1.1 servers.
#
@@ -360,8 +320,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_accessor :keep_alive
##
- # A name for this connection. Allows you to keep your connections apart
- # from everybody else's.
+ # The name for this collection of persistent connections.
attr_reader :name
@@ -491,22 +450,10 @@ class Bundler::Persistent::Net::HTTP::Persistent
attr_reader :verify_mode
##
- # Enable retries of non-idempotent requests that change data (e.g. POST
- # requests) when the server has disconnected.
- #
- # This will in the worst case lead to multiple requests with the same data,
- # but it may be useful for some applications. Take care when enabling
- # this option to ensure it is safe to POST or perform other non-idempotent
- # requests to the server.
-
- attr_accessor :retry_change_requests
-
- ##
# Creates a new Bundler::Persistent::Net::HTTP::Persistent.
#
- # Set +name+ to keep your connections apart from everybody else's. Not
- # required currently, but highly recommended. Your library name should be
- # good enough. This parameter will be required in a future version.
+ # Set a +name+ for fun. Your library name should be good enough, but this
+ # otherwise has no purpose.
#
# +proxy+ may be set to a Bundler::URI::HTTP or :ENV to pick up proxy options from
# the environment. See proxy_from_env for details.
@@ -519,8 +466,9 @@ class Bundler::Persistent::Net::HTTP::Persistent
# proxy.password = 'hunter2'
#
# Set +pool_size+ to limit the maximum number of connections allowed.
- # Defaults to 1/4 the number of allowed file handles. You can have no more
- # than this many threads with active HTTP transactions.
+ # Defaults to 1/4 the number of allowed file handles or 256 if your OS does
+ # not support a limit on allowed file handles. You can have no more than
+ # this many threads with active HTTP transactions.
def initialize name: nil, proxy: nil, pool_size: DEFAULT_POOL_SIZE
@name = name
@@ -537,6 +485,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
@write_timeout = nil
@idle_timeout = 5
@max_requests = nil
+ @max_retries = 1
@socket_options = []
@ssl_generation = 0 # incremented when SSL session variables change
@@ -568,8 +517,6 @@ class Bundler::Persistent::Net::HTTP::Persistent
@reuse_ssl_sessions = OpenSSL::SSL.const_defined? :Session
end
- @retry_change_requests = false
-
self.proxy = proxy if proxy
end
@@ -630,7 +577,9 @@ class Bundler::Persistent::Net::HTTP::Persistent
net_http_args = [uri.hostname, uri.port]
- if @proxy_uri and not proxy_bypass? uri.hostname, uri.port then
+ # I'm unsure if uri.host or uri.hostname should be checked against
+ # the proxy bypass list.
+ if @proxy_uri and not proxy_bypass? uri.host, uri.port then
net_http_args.concat @proxy_args
else
net_http_args.concat [nil, nil, nil, nil]
@@ -650,9 +599,11 @@ class Bundler::Persistent::Net::HTTP::Persistent
reset connection
end
- http.read_timeout = @read_timeout if @read_timeout
- http.write_timeout = @write_timeout if @write_timeout && http.respond_to?(:write_timeout=)
- http.keep_alive_timeout = @idle_timeout if @idle_timeout
+ http.keep_alive_timeout = @idle_timeout if @idle_timeout
+ http.max_retries = @max_retries if http.respond_to?(:max_retries=)
+ http.read_timeout = @read_timeout if @read_timeout
+ http.write_timeout = @write_timeout if
+ @write_timeout && http.respond_to?(:write_timeout=)
return yield connection
rescue Errno::ECONNREFUSED
@@ -670,27 +621,14 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
##
- # Returns an error message containing the number of requests performed on
- # this connection
-
- def error_message connection
- connection.requests -= 1 # fixup
-
- age = Time.now - connection.last_use
-
- "after #{connection.requests} requests on #{connection.http.object_id}, " \
- "last used #{age} seconds ago"
- end
-
- ##
- # Bundler::URI::escape wrapper
+ # CGI::escape wrapper
def escape str
CGI.escape str if str
end
##
- # Bundler::URI::unescape wrapper
+ # CGI::unescape wrapper
def unescape str
CGI.unescape str if str
@@ -733,6 +671,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
def finish connection
connection.finish
+ connection.http.instance_variable_set :@last_communicated, nil
connection.http.instance_variable_set :@ssl_session, nil unless
@reuse_ssl_sessions
end
@@ -741,31 +680,31 @@ class Bundler::Persistent::Net::HTTP::Persistent
# Returns the HTTP protocol version for +uri+
def http_version uri
- @http_versions["#{uri.host}:#{uri.port}"]
+ @http_versions["#{uri.hostname}:#{uri.port}"]
end
##
- # Is +req+ idempotent according to RFC 2616?
+ # Adds "http://" to the String +uri+ if it is missing.
- def idempotent? req
- case req.method
- when 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PUT', 'TRACE' then
- true
- end
+ def normalize_uri uri
+ (uri =~ /^https?:/) ? uri : "http://#{uri}"
end
##
- # Is the request +req+ idempotent or is retry_change_requests allowed.
+ # Set the maximum number of retries for a request.
+ #
+ # Defaults to one retry.
+ #
+ # Set this to 0 to disable retries.
- def can_retry? req
- @retry_change_requests && !idempotent?(req)
- end
+ def max_retries= retries
+ retries = retries.to_int
- ##
- # Adds "http://" to the String +uri+ if it is missing.
+ raise ArgumentError, "max_retries must be positive" if retries < 0
- def normalize_uri uri
- (uri =~ /^https?:/) ? uri : "http://#{uri}"
+ @max_retries = retries
+
+ reconnect
end
##
@@ -806,7 +745,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
if @proxy_uri then
@proxy_args = [
- @proxy_uri.host,
+ @proxy_uri.hostname,
@proxy_uri.port,
unescape(@proxy_uri.user),
unescape(@proxy_uri.password),
@@ -881,14 +820,15 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
##
- # Forces reconnection of HTTP connections.
+ # Forces reconnection of all HTTP connections, including TLS/SSL
+ # connections.
def reconnect
@generation += 1
end
##
- # Forces reconnection of SSL connections.
+ # Forces reconnection of only TLS/SSL connections.
def reconnect_ssl
@ssl_generation += 1
@@ -921,14 +861,8 @@ class Bundler::Persistent::Net::HTTP::Persistent
# the response will not have been read).
#
# +req+ must be a Net::HTTPGenericRequest subclass (see Net::HTTP for a list).
- #
- # If there is an error and the request is idempotent according to RFC 2616
- # it will be retried automatically.
def request uri, req = nil, &block
- retried = false
- bad_response = false
-
uri = Bundler::URI uri
req = request_setup req || uri
response = nil
@@ -942,37 +876,12 @@ class Bundler::Persistent::Net::HTTP::Persistent
response = http.request req, &block
if req.connection_close? or
- (response.http_version <= '1.0' and
+ (response.http_version <= '1.0' and
not response.connection_keep_alive?) or
- response.connection_close? then
+ response.connection_close? then
finish connection
end
- rescue Net::HTTPBadResponse => e
- message = error_message connection
-
- finish connection
-
- raise Error, "too many bad responses #{message}" if
- bad_response or not can_retry? req
-
- bad_response = true
- retry
- rescue *RETRIED_EXCEPTIONS => e
- request_failed e, req, connection if
- retried or not can_retry? req
-
- reset connection
-
- retried = true
- retry
- rescue Errno::EINVAL, Errno::ETIMEDOUT => e # not retried on ruby 2
- request_failed e, req, connection if retried or not can_retry? req
-
- reset connection
-
- retried = true
- retry
- rescue Exception => e
+ rescue Exception # make sure to close the connection when it was interrupted
finish connection
raise
@@ -981,34 +890,19 @@ class Bundler::Persistent::Net::HTTP::Persistent
end
end
- @http_versions["#{uri.host}:#{uri.port}"] ||= response.http_version
+ @http_versions["#{uri.hostname}:#{uri.port}"] ||= response.http_version
response
end
##
- # Raises an Error for +exception+ which resulted from attempting the request
- # +req+ on the +connection+.
- #
- # Finishes the +connection+.
-
- def request_failed exception, req, connection # :nodoc:
- due_to = "(due to #{exception.message} - #{exception.class})"
- message = "too many connection resets #{due_to} #{error_message connection}"
-
- finish connection
-
- raise Error, message, exception.backtrace
- end
-
- ##
# Creates a GET request if +req_or_uri+ is a Bundler::URI and adds headers to the
# request.
#
# Returns the request.
def request_setup req_or_uri # :nodoc:
- req = if Bundler::URI === req_or_uri then
+ req = if req_or_uri.respond_to? 'request_uri' then
Net::HTTP::Get.new req_or_uri.request_uri
else
req_or_uri
@@ -1172,7 +1066,6 @@ application:
reconnect_ssl
end
-
end
require_relative 'persistent/connection'
diff --git a/lib/bundler/vendor/thor/LICENSE.md b/lib/bundler/vendor/thor/LICENSE.md
new file mode 100644
index 0000000000..ef80540b2a
--- /dev/null
+++ b/lib/bundler/vendor/thor/LICENSE.md
@@ -0,0 +1,20 @@
+Copyright (c) 2008 Yehuda Katz, Eric Hodel, et al.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/bundler/vendor/thor/lib/thor.rb b/lib/bundler/vendor/thor/lib/thor.rb
index 01c0b2f83c..0794dbb522 100644
--- a/lib/bundler/vendor/thor/lib/thor.rb
+++ b/lib/bundler/vendor/thor/lib/thor.rb
@@ -1,7 +1,7 @@
-require "set"
require_relative "thor/base"
class Bundler::Thor
+ $thor_runner ||= false
class << self
# Allows for custom "Command" package naming.
#
@@ -323,7 +323,7 @@ class Bundler::Thor
# ==== Parameters
# Symbol ...:: A list of commands that should be affected.
def stop_on_unknown_option!(*command_names)
- stop_on_unknown_option.merge(command_names)
+ @stop_on_unknown_option = stop_on_unknown_option | command_names
end
def stop_on_unknown_option?(command) #:nodoc:
@@ -337,29 +337,22 @@ class Bundler::Thor
# ==== Parameters
# Symbol ...:: A list of commands that should be affected.
def disable_required_check!(*command_names)
- disable_required_check.merge(command_names)
+ @disable_required_check = disable_required_check | command_names
end
def disable_required_check?(command) #:nodoc:
command && disable_required_check.include?(command.name.to_sym)
end
- def deprecation_warning(message) #:nodoc:
- unless ENV['THOR_SILENCE_DEPRECATION']
- warn "Deprecation warning: #{message}\n" +
- 'You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.'
- end
- end
-
protected
def stop_on_unknown_option #:nodoc:
- @stop_on_unknown_option ||= Set.new
+ @stop_on_unknown_option ||= []
end
# help command has the required check disabled by default.
def disable_required_check #:nodoc:
- @disable_required_check ||= Set.new([:help])
+ @disable_required_check ||= [:help]
end
# The method responsible for dispatching given the args.
@@ -405,7 +398,6 @@ class Bundler::Thor
# the namespace should be displayed as arguments.
#
def banner(command, namespace = nil, subcommand = false)
- $thor_runner ||= false
command.formatted_usage(self, $thor_runner, subcommand).split("\n").map do |formatted_usage|
"#{basename} #{formatted_usage}"
end.join("\n")
diff --git a/lib/bundler/vendor/thor/lib/thor/actions.rb b/lib/bundler/vendor/thor/lib/thor/actions.rb
index a5368d07f3..de9323b2db 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions.rb
@@ -219,7 +219,7 @@ class Bundler::Thor
contents = if is_uri
require "open-uri"
- open(path, "Accept" => "application/x-thor-template", &:read)
+ URI.open(path, "Accept" => "application/x-thor-template", &:read)
else
open(path, &:read)
end
diff --git a/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb b/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb
index 70504a2c1f..fb76fcdbe9 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/create_link.rb
@@ -33,7 +33,8 @@ class Bundler::Thor
# Boolean:: true if it is identical, false otherwise.
#
def identical?
- exists? && File.identical?(render, destination)
+ source = File.expand_path(render, File.dirname(destination))
+ exists? && File.identical?(source, destination)
end
def invoke!
diff --git a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
index afdbd53dd0..90a8d2e847 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
@@ -251,7 +251,8 @@ class Bundler::Thor
# 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.
+ # config<Hash>:: give :verbose => false to not log the status, and
+ # :force => true, to force the replacement regardless of runner behavior.
#
# ==== Example
#
@@ -262,9 +263,10 @@ class Bundler::Thor
# end
#
def gsub_file(path, flag, *args, &block)
- return unless behavior == :invoke
config = args.last.is_a?(Hash) ? args.pop : {}
+ return unless behavior == :invoke || config.fetch(:force, false)
+
path = File.expand_path(path, destination_root)
say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
diff --git a/lib/bundler/vendor/thor/lib/thor/base.rb b/lib/bundler/vendor/thor/lib/thor/base.rb
index 9ba5243378..8487f9590a 100644
--- a/lib/bundler/vendor/thor/lib/thor/base.rb
+++ b/lib/bundler/vendor/thor/lib/thor/base.rb
@@ -22,6 +22,15 @@ class Bundler::Thor
TEMPLATE_EXTNAME = ".tt"
+ class << self
+ def deprecation_warning(message) #:nodoc:
+ unless ENV['THOR_SILENCE_DEPRECATION']
+ warn "Deprecation warning: #{message}\n" +
+ 'You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.'
+ end
+ end
+ end
+
module Base
attr_accessor :options, :parent_options, :args
diff --git a/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb
deleted file mode 100644
index 0f6e2e0af2..0000000000
--- a/lib/bundler/vendor/thor/lib/thor/core_ext/io_binary_read.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class IO #:nodoc:
- class << self
- unless method_defined? :binread
- def binread(file, *args)
- raise ArgumentError, "wrong number of arguments (#{1 + args.size} for 1..3)" unless args.size < 3
- File.open(file, "rb") do |f|
- f.read(*args)
- end
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb
deleted file mode 100644
index 76f1e43c65..0000000000
--- a/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb
+++ /dev/null
@@ -1,129 +0,0 @@
-class Bundler::Thor
- module CoreExt
- class OrderedHash < ::Hash
- if RUBY_VERSION < "1.9"
- def initialize(*args, &block)
- super
- @keys = []
- end
-
- def initialize_copy(other)
- super
- # make a deep copy of keys
- @keys = other.keys
- end
-
- def []=(key, value)
- @keys << key unless key?(key)
- super
- end
-
- def delete(key)
- if key? key
- index = @keys.index(key)
- @keys.delete_at index
- end
- super
- end
-
- def delete_if
- super
- sync_keys!
- self
- end
-
- alias_method :reject!, :delete_if
-
- def reject(&block)
- dup.reject!(&block)
- end
-
- def keys
- @keys.dup
- end
-
- def values
- @keys.map { |key| self[key] }
- end
-
- def to_hash
- self
- end
-
- def to_a
- @keys.map { |key| [key, self[key]] }
- end
-
- def each_key
- return to_enum(:each_key) unless block_given?
- @keys.each { |key| yield(key) }
- self
- end
-
- def each_value
- return to_enum(:each_value) unless block_given?
- @keys.each { |key| yield(self[key]) }
- self
- end
-
- def each
- return to_enum(:each) unless block_given?
- @keys.each { |key| yield([key, self[key]]) }
- self
- end
-
- def each_pair
- return to_enum(:each_pair) unless block_given?
- @keys.each { |key| yield(key, self[key]) }
- self
- end
-
- alias_method :select, :find_all
-
- def clear
- super
- @keys.clear
- self
- end
-
- def shift
- k = @keys.first
- v = delete(k)
- [k, v]
- end
-
- def merge!(other_hash)
- if block_given?
- other_hash.each { |k, v| self[k] = key?(k) ? yield(k, self[k], v) : v }
- else
- other_hash.each { |k, v| self[k] = v }
- end
- self
- end
-
- alias_method :update, :merge!
-
- def merge(other_hash, &block)
- dup.merge!(other_hash, &block)
- end
-
- # When replacing with another hash, the initial order of our keys must come from the other hash -ordered or not.
- def replace(other)
- super
- @keys = other.keys
- self
- end
-
- def inspect
- "#<#{self.class} #{super}>"
- end
-
- private
-
- def sync_keys!
- @keys.delete_if { |k| !key?(k) }
- end
- end
- end
- end
-end
diff --git a/lib/bundler/vendor/thor/lib/thor/error.rb b/lib/bundler/vendor/thor/lib/thor/error.rb
index 1553afd201..7d57129b83 100644
--- a/lib/bundler/vendor/thor/lib/thor/error.rb
+++ b/lib/bundler/vendor/thor/lib/thor/error.rb
@@ -1,5 +1,5 @@
class Bundler::Thor
- Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable)
+ Correctable = if defined?(DidYouMean::SpellChecker) && defined?(DidYouMean::Correctable) # rubocop:disable Naming/ConstantName
# In order to support versions of Ruby that don't have keyword
# arguments, we need our own spell checker class that doesn't take key
# words. Even though this code wouldn't be hit because of the check
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
index d0f43e2d97..3a5d82cf29 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
@@ -30,7 +30,11 @@ class Bundler::Thor
arguments.each do |argument|
if !argument.default.nil?
- @assigns[argument.human_name] = argument.default
+ begin
+ @assigns[argument.human_name] = argument.default.dup
+ rescue TypeError # Compatibility shim for un-dup-able Fixnum in Ruby < 2.4
+ @assigns[argument.human_name] = argument.default
+ end
elsif argument.required?
@non_assigned_required << argument
end
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/options.rb b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
index 6d1342ee3c..3a8927d09c 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/options.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
@@ -133,15 +133,16 @@ class Bundler::Thor
protected
- def assign_result!(option, result)
- if option.repeatable && option.type == :hash
- (@assigns[option.human_name] ||= {}).merge!(result)
- elsif option.repeatable
- (@assigns[option.human_name] ||= []) << result
- else
- @assigns[option.human_name] = result
+ def assign_result!(option, result)
+ if option.repeatable && option.type == :hash
+ (@assigns[option.human_name] ||= {}).merge!(result)
+ elsif option.repeatable
+ (@assigns[option.human_name] ||= []) << result
+ else
+ @assigns[option.human_name] = result
+ end
end
- end
+
# Check if the current value in peek is a registered switch.
#
# Two booleans are returned. The first is true if the current value
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
index be48358cb1..2dddd4a53a 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
@@ -94,6 +94,8 @@ class Bundler::Thor
# say("I know you knew that.")
#
def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
+ return if quiet?
+
buffer = prepare_message(message, *color)
buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
@@ -230,8 +232,9 @@ class Bundler::Thor
paras = message.split("\n\n")
paras.map! do |unwrapped|
- counter = 0
- unwrapped.split(" ").inject do |memo, word|
+ words = unwrapped.split(" ")
+ counter = words.first.length
+ words.inject do |memo, word|
word = word.gsub(/\n\005/, "\n").gsub(/\005/, "\n")
counter = 0 if word.include? "\n"
if (counter + word.length + 1) < width
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/color.rb b/lib/bundler/vendor/thor/lib/thor/shell/color.rb
index 29f280202d..dc167ed3cc 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/color.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/color.rb
@@ -97,7 +97,11 @@ class Bundler::Thor
protected
def can_display_colors?
- stdout.tty? && !are_colors_disabled?
+ are_colors_supported? && !are_colors_disabled?
+ end
+
+ def are_colors_supported?
+ stdout.tty? && ENV["TERM"] != "dumb"
end
def are_colors_disabled?
diff --git a/lib/bundler/vendor/thor/lib/thor/version.rb b/lib/bundler/vendor/thor/lib/thor/version.rb
index 7750d27637..a3efa9f762 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.0.0"
+ VERSION = "1.1.0"
end
diff --git a/lib/bundler/vendor/tmpdir/lib/tmpdir.rb b/lib/bundler/vendor/tmpdir/lib/tmpdir.rb
new file mode 100644
index 0000000000..70d43e0c6b
--- /dev/null
+++ b/lib/bundler/vendor/tmpdir/lib/tmpdir.rb
@@ -0,0 +1,154 @@
+# frozen_string_literal: true
+#
+# tmpdir - retrieve temporary directory path
+#
+# $Id$
+#
+
+require_relative '../../fileutils/lib/fileutils'
+begin
+ require 'etc.so'
+rescue LoadError # rescue LoadError for miniruby
+end
+
+class Bundler::Dir < Dir
+
+ @systmpdir ||= defined?(Etc.systmpdir) ? Etc.systmpdir : '/tmp'
+
+ ##
+ # Returns the operating system's temporary file path.
+
+ def self.tmpdir
+ tmp = nil
+ ['TMPDIR', 'TMP', 'TEMP', ['system temporary path', @systmpdir], ['/tmp']*2, ['.']*2].each do |name, dir = ENV[name]|
+ next if !dir
+ dir = File.expand_path(dir)
+ stat = File.stat(dir) rescue next
+ case
+ when !stat.directory?
+ warn "#{name} is not a directory: #{dir}"
+ when !stat.writable?
+ warn "#{name} is not writable: #{dir}"
+ when stat.world_writable? && !stat.sticky?
+ warn "#{name} is world-writable: #{dir}"
+ else
+ tmp = dir
+ break
+ end
+ end
+ raise ArgumentError, "could not find a temporary directory" unless tmp
+ tmp
+ end
+
+ # Bundler::Dir.mktmpdir creates a temporary directory.
+ #
+ # The directory is created with 0700 permission.
+ # Application should not change the permission to make the temporary directory accessible from other users.
+ #
+ # The prefix and suffix of the name of the directory is specified by
+ # the optional first argument, <i>prefix_suffix</i>.
+ # - If it is not specified or nil, "d" is used as the prefix and no suffix is used.
+ # - If it is a string, it is used as the prefix and no suffix is used.
+ # - If it is an array, first element is used as the prefix and second element is used as a suffix.
+ #
+ # Bundler::Dir.mktmpdir {|dir| dir is ".../d..." }
+ # Bundler::Dir.mktmpdir("foo") {|dir| dir is ".../foo..." }
+ # Bundler::Dir.mktmpdir(["foo", "bar"]) {|dir| dir is ".../foo...bar" }
+ #
+ # The directory is created under Bundler::Dir.tmpdir or
+ # the optional second argument <i>tmpdir</i> if non-nil value is given.
+ #
+ # Bundler::Dir.mktmpdir {|dir| dir is "#{Bundler::Dir.tmpdir}/d..." }
+ # Bundler::Dir.mktmpdir(nil, "/var/tmp") {|dir| dir is "/var/tmp/d..." }
+ #
+ # If a block is given,
+ # it is yielded with the path of the directory.
+ # The directory and its contents are removed
+ # using Bundler::FileUtils.remove_entry before Bundler::Dir.mktmpdir returns.
+ # The value of the block is returned.
+ #
+ # Bundler::Dir.mktmpdir {|dir|
+ # # use the directory...
+ # open("#{dir}/foo", "w") { ... }
+ # }
+ #
+ # If a block is not given,
+ # The path of the directory is returned.
+ # In this case, Bundler::Dir.mktmpdir doesn't remove the directory.
+ #
+ # dir = Bundler::Dir.mktmpdir
+ # begin
+ # # use the directory...
+ # open("#{dir}/foo", "w") { ... }
+ # ensure
+ # # remove the directory.
+ # Bundler::FileUtils.remove_entry dir
+ # end
+ #
+ def self.mktmpdir(prefix_suffix=nil, *rest, **options)
+ base = nil
+ path = Tmpname.create(prefix_suffix || "d", *rest, **options) {|p, _, _, d|
+ base = d
+ mkdir(p, 0700)
+ }
+ if block_given?
+ begin
+ yield path.dup
+ ensure
+ unless base
+ stat = File.stat(File.dirname(path))
+ if stat.world_writable? and !stat.sticky?
+ raise ArgumentError, "parent directory is world writable but not sticky"
+ end
+ end
+ Bundler::FileUtils.remove_entry path
+ end
+ else
+ path
+ end
+ end
+
+ module Tmpname # :nodoc:
+ module_function
+
+ def tmpdir
+ Bundler::Dir.tmpdir
+ end
+
+ UNUSABLE_CHARS = "^,-.0-9A-Z_a-z~"
+
+ class << (RANDOM = Random.new)
+ MAX = 36**6 # < 0x100000000
+ def next
+ rand(MAX).to_s(36)
+ end
+ end
+ private_constant :RANDOM
+
+ def create(basename, tmpdir=nil, max_try: nil, **opts)
+ origdir = tmpdir
+ tmpdir ||= tmpdir()
+ n = nil
+ prefix, suffix = basename
+ prefix = (String.try_convert(prefix) or
+ raise ArgumentError, "unexpected prefix: #{prefix.inspect}")
+ prefix = prefix.delete(UNUSABLE_CHARS)
+ suffix &&= (String.try_convert(suffix) or
+ raise ArgumentError, "unexpected suffix: #{suffix.inspect}")
+ suffix &&= suffix.delete(UNUSABLE_CHARS)
+ begin
+ t = Time.now.strftime("%Y%m%d")
+ path = "#{prefix}#{t}-#{$$}-#{RANDOM.next}"\
+ "#{n ? %[-#{n}] : ''}#{suffix||''}"
+ path = File.join(tmpdir, path)
+ yield(path, n, opts, origdir)
+ rescue Errno::EEXIST
+ n ||= 0
+ n += 1
+ retry if !max_try or n < max_try
+ raise "cannot generate temporary name using `#{basename}' under `#{tmpdir}'"
+ end
+ path
+ end
+ end
+end
diff --git a/lib/bundler/vendor/tsort/LICENSE.txt b/lib/bundler/vendor/tsort/LICENSE.txt
new file mode 100644
index 0000000000..a009caefea
--- /dev/null
+++ b/lib/bundler/vendor/tsort/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/lib/bundler/vendor/tsort/lib/tsort.rb b/lib/bundler/vendor/tsort/lib/tsort.rb
new file mode 100644
index 0000000000..8454583295
--- /dev/null
+++ b/lib/bundler/vendor/tsort/lib/tsort.rb
@@ -0,0 +1,453 @@
+# frozen_string_literal: true
+
+#--
+# tsort.rb - provides a module for topological sorting and strongly connected components.
+#++
+#
+
+#
+# TSort implements topological sorting using Tarjan's algorithm for
+# strongly connected components.
+#
+# TSort is designed to be able to be used with any object which can be
+# interpreted as a directed graph.
+#
+# TSort requires two methods to interpret an object as a graph,
+# tsort_each_node and tsort_each_child.
+#
+# * tsort_each_node is used to iterate for all nodes over a graph.
+# * tsort_each_child is used to iterate for child nodes of a given node.
+#
+# The equality of nodes are defined by eql? and hash since
+# TSort uses Hash internally.
+#
+# == A Simple Example
+#
+# The following example demonstrates how to mix the TSort module into an
+# existing class (in this case, Hash). Here, we're treating each key in
+# the hash as a node in the graph, and so we simply alias the required
+# #tsort_each_node method to Hash's #each_key method. For each key in the
+# hash, the associated value is an array of the node's child nodes. This
+# choice in turn leads to our implementation of the required #tsort_each_child
+# method, which fetches the array of child nodes and then iterates over that
+# array using the user-supplied block.
+#
+# require 'tsort'
+#
+# class Hash
+# include TSort
+# alias tsort_each_node each_key
+# def tsort_each_child(node, &block)
+# fetch(node).each(&block)
+# end
+# end
+#
+# {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort
+# #=> [3, 2, 1, 4]
+#
+# {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components
+# #=> [[4], [2, 3], [1]]
+#
+# == A More Realistic Example
+#
+# A very simple `make' like tool can be implemented as follows:
+#
+# require 'tsort'
+#
+# class Make
+# def initialize
+# @dep = {}
+# @dep.default = []
+# end
+#
+# def rule(outputs, inputs=[], &block)
+# triple = [outputs, inputs, block]
+# outputs.each {|f| @dep[f] = [triple]}
+# @dep[triple] = inputs
+# end
+#
+# def build(target)
+# each_strongly_connected_component_from(target) {|ns|
+# if ns.length != 1
+# fs = ns.delete_if {|n| Array === n}
+# raise TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}")
+# end
+# n = ns.first
+# if Array === n
+# outputs, inputs, block = n
+# inputs_time = inputs.map {|f| File.mtime f}.max
+# begin
+# outputs_time = outputs.map {|f| File.mtime f}.min
+# rescue Errno::ENOENT
+# outputs_time = nil
+# end
+# if outputs_time == nil ||
+# inputs_time != nil && outputs_time <= inputs_time
+# sleep 1 if inputs_time != nil && inputs_time.to_i == Time.now.to_i
+# block.call
+# end
+# end
+# }
+# end
+#
+# def tsort_each_child(node, &block)
+# @dep[node].each(&block)
+# end
+# include TSort
+# end
+#
+# def command(arg)
+# print arg, "\n"
+# system arg
+# end
+#
+# m = Make.new
+# m.rule(%w[t1]) { command 'date > t1' }
+# m.rule(%w[t2]) { command 'date > t2' }
+# m.rule(%w[t3]) { command 'date > t3' }
+# m.rule(%w[t4], %w[t1 t3]) { command 'cat t1 t3 > t4' }
+# m.rule(%w[t5], %w[t4 t2]) { command 'cat t4 t2 > t5' }
+# m.build('t5')
+#
+# == Bugs
+#
+# * 'tsort.rb' is wrong name because this library uses
+# Tarjan's algorithm for strongly connected components.
+# Although 'strongly_connected_components.rb' is correct but too long.
+#
+# == References
+#
+# R. E. Tarjan, "Depth First Search and Linear Graph Algorithms",
+# <em>SIAM Journal on Computing</em>, Vol. 1, No. 2, pp. 146-160, June 1972.
+#
+module Bundler
+ module TSort
+ class Cyclic < StandardError
+ end
+
+ # Returns a topologically sorted array of nodes.
+ # The array is sorted from children to parents, i.e.
+ # the first element has no child and the last node has no parent.
+ #
+ # If there is a cycle, TSort::Cyclic is raised.
+ #
+ # class G
+ # include TSort
+ # def initialize(g)
+ # @g = g
+ # end
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
+ # def tsort_each_node(&b) @g.each_key(&b) end
+ # end
+ #
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
+ # p graph.tsort #=> [4, 2, 3, 1]
+ #
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
+ # p graph.tsort # raises TSort::Cyclic
+ #
+ def tsort
+ each_node = method(:tsort_each_node)
+ each_child = method(:tsort_each_child)
+ TSort.tsort(each_node, each_child)
+ end
+
+ # Returns a topologically sorted array of nodes.
+ # The array is sorted from children to parents, i.e.
+ # the first element has no child and the last node has no parent.
+ #
+ # The graph is represented by _each_node_ and _each_child_.
+ # _each_node_ should have +call+ method which yields for each node in the graph.
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
+ #
+ # If there is a cycle, TSort::Cyclic is raised.
+ #
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # p TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1]
+ #
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # p TSort.tsort(each_node, each_child) # raises TSort::Cyclic
+ #
+ def TSort.tsort(each_node, each_child)
+ TSort.tsort_each(each_node, each_child).to_a
+ end
+
+ # The iterator version of the #tsort method.
+ # <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 TSort.tsort_each(each_node, each_child) # :yields: node
+ return to_enum(__method__, each_node, each_child) unless block_given?
+
+ TSort.each_strongly_connected_component(each_node, each_child) {|component|
+ if component.size == 1
+ yield component.first
+ else
+ raise Cyclic.new("topological sort failed: #{component.inspect}")
+ end
+ }
+ end
+
+ # Returns strongly connected components as an array of arrays of nodes.
+ # The array is sorted from children to parents.
+ # Each elements of the array represents a strongly connected component.
+ #
+ # class G
+ # include TSort
+ # def initialize(g)
+ # @g = g
+ # end
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
+ # def tsort_each_node(&b) @g.each_key(&b) end
+ # end
+ #
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
+ # p graph.strongly_connected_components #=> [[4], [2], [3], [1]]
+ #
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
+ # p graph.strongly_connected_components #=> [[4], [2, 3], [1]]
+ #
+ def strongly_connected_components
+ each_node = method(:tsort_each_node)
+ each_child = method(:tsort_each_child)
+ TSort.strongly_connected_components(each_node, each_child)
+ end
+
+ # Returns strongly connected components as an array of arrays of nodes.
+ # The array is sorted from children to parents.
+ # Each elements of the array represents a strongly connected component.
+ #
+ # The graph is represented by _each_node_ and _each_child_.
+ # _each_node_ should have +call+ method which yields for each node in the graph.
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
+ #
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # p TSort.strongly_connected_components(each_node, each_child)
+ # #=> [[4], [2], [3], [1]]
+ #
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # p TSort.strongly_connected_components(each_node, each_child)
+ # #=> [[4], [2, 3], [1]]
+ #
+ def TSort.strongly_connected_components(each_node, each_child)
+ TSort.each_strongly_connected_component(each_node, each_child).to_a
+ end
+
+ # The iterator version of the #strongly_connected_components method.
+ # <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 TSort.each_strongly_connected_component(each_node, each_child) # :yields: nodes
+ return to_enum(__method__, each_node, each_child) unless block_given?
+
+ id_map = {}
+ stack = []
+ each_node.call {|node|
+ unless id_map.include? node
+ TSort.each_strongly_connected_component_from(node, each_child, id_map, stack) {|c|
+ yield c
+ }
+ end
+ }
+ nil
+ end
+
+ # Iterates over strongly connected component in the subgraph reachable from
+ # _node_.
+ #
+ # Return value is unspecified.
+ #
+ # #each_strongly_connected_component_from doesn't call #tsort_each_node.
+ #
+ # class G
+ # include TSort
+ # def initialize(g)
+ # @g = g
+ # end
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
+ # def tsort_each_node(&b) @g.each_key(&b) end
+ # end
+ #
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
+ # #=> [4]
+ # # [2]
+ #
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
+ # #=> [4]
+ # # [2, 3]
+ #
+ def each_strongly_connected_component_from(node, id_map={}, stack=[], &block) # :yields: nodes
+ TSort.each_strongly_connected_component_from(node, method(:tsort_each_child), id_map, stack, &block)
+ end
+
+ # Iterates over strongly connected components in a graph.
+ # The graph is represented by _node_ and _each_child_.
+ #
+ # _node_ is the first node.
+ # _each_child_ should have +call+ method which takes a node argument
+ # and yields for each child node.
+ #
+ # Return value is unspecified.
+ #
+ # #TSort.each_strongly_connected_component_from is a class method and
+ # it doesn't need a class to represent a graph which includes TSort.
+ #
+ # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
+ # each_child = lambda {|n, &b| graph[n].each(&b) }
+ # TSort.each_strongly_connected_component_from(1, each_child) {|scc|
+ # p scc
+ # }
+ # #=> [4]
+ # # [2, 3]
+ # # [1]
+ #
+ def TSort.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
+ return to_enum(__method__, node, each_child, id_map, stack) unless block_given?
+
+ minimum_id = node_id = id_map[node] = id_map.size
+ stack_length = stack.length
+ stack << node
+
+ each_child.call(node) {|child|
+ if id_map.include? child
+ child_id = id_map[child]
+ minimum_id = child_id if child_id && child_id < minimum_id
+ else
+ sub_minimum_id =
+ TSort.each_strongly_connected_component_from(child, each_child, id_map, stack) {|c|
+ yield c
+ }
+ minimum_id = sub_minimum_id if sub_minimum_id < minimum_id
+ end
+ }
+
+ if node_id == minimum_id
+ component = stack.slice!(stack_length .. -1)
+ component.each {|n| id_map[n] = nil}
+ yield component
+ end
+
+ minimum_id
+ end
+
+ # Should be implemented by a extended class.
+ #
+ # #tsort_each_node is used to iterate for all nodes over a graph.
+ #
+ def tsort_each_node # :yields: node
+ raise NotImplementedError.new
+ end
+
+ # Should be implemented by a extended class.
+ #
+ # #tsort_each_child is used to iterate for child nodes of _node_.
+ #
+ def tsort_each_child(node) # :yields: child
+ raise NotImplementedError.new
+ end
+ end
+end
diff --git a/lib/bundler/vendor/uri/LICENSE.txt b/lib/bundler/vendor/uri/LICENSE.txt
new file mode 100644
index 0000000000..a009caefea
--- /dev/null
+++ b/lib/bundler/vendor/uri/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/lib/bundler/vendored_persistent.rb b/lib/bundler/vendored_persistent.rb
index 045a761dac..dc9573e025 100644
--- a/lib/bundler/vendored_persistent.rb
+++ b/lib/bundler/vendored_persistent.rb
@@ -1,12 +1,5 @@
# frozen_string_literal: true
-# We forcibly require OpenSSL, because net/http/persistent will only autoload
-# it. On some Rubies, autoload fails but explicit require succeeds.
-begin
- require "openssl"
-rescue LoadError
- # some Ruby builds don't have OpenSSL
-end
module Bundler
module Persistent
module Net
diff --git a/lib/bundler/vendored_tmpdir.rb b/lib/bundler/vendored_tmpdir.rb
new file mode 100644
index 0000000000..43b4fa75fe
--- /dev/null
+++ b/lib/bundler/vendored_tmpdir.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+module Bundler; end
+require_relative "vendor/tmpdir/lib/tmpdir"
diff --git a/lib/bundler/vendored_tsort.rb b/lib/bundler/vendored_tsort.rb
new file mode 100644
index 0000000000..38aed0b5de
--- /dev/null
+++ b/lib/bundler/vendored_tsort.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+module Bundler; end
+require_relative "vendor/tsort/lib/tsort"
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index 85704816e4..863eeaae5f 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.1.4".freeze
+ VERSION = "2.2.33".freeze
def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i
diff --git a/lib/bundler/worker.rb b/lib/bundler/worker.rb
index 3471654b43..5e4ee21c51 100644
--- a/lib/bundler/worker.rb
+++ b/lib/bundler/worker.rb
@@ -21,12 +21,12 @@ module Bundler
# @param func [Proc] job to run in inside the worker pool
def initialize(size, name, func)
@name = name
- @request_queue = Queue.new
- @response_queue = Queue.new
+ @request_queue = Thread::Queue.new
+ @response_queue = Thread::Queue.new
@func = func
@size = size
@threads = nil
- SharedHelpers.trap("INT") { abort_threads }
+ @previous_interrupt_handler = nil
end
# Enqueue a request to be executed in the worker pool
@@ -48,7 +48,7 @@ module Bundler
stop_threads
end
- private
+ private
def process_queue(i)
loop do
@@ -68,13 +68,16 @@ module Bundler
# so as worker threads after retrieving it, shut themselves down
def stop_threads
return unless @threads
+
@threads.each { @request_queue.enq POISON }
@threads.each(&:join)
+
+ remove_interrupt_handler
+
@threads = nil
end
def abort_threads
- return unless @threads
Bundler.ui.debug("\n#{caller.join("\n")}")
@threads.each(&:exit)
exit 1
@@ -94,11 +97,23 @@ module Bundler
end
end.compact
+ add_interrupt_handler unless @threads.empty?
+
return if creation_errors.empty?
message = "Failed to create threads for the #{name} worker: #{creation_errors.map(&:to_s).uniq.join(", ")}"
raise ThreadCreationError, message if @threads.empty?
Bundler.ui.info message
end
+
+ def add_interrupt_handler
+ @previous_interrupt_handler = trap("INT") { abort_threads }
+ end
+
+ def remove_interrupt_handler
+ return unless @previous_interrupt_handler
+
+ trap "INT", @previous_interrupt_handler
+ end
end
end
diff --git a/lib/bundler/yaml_serializer.rb b/lib/bundler/yaml_serializer.rb
index 374b3bb5e3..d5ecbd4aef 100644
--- a/lib/bundler/yaml_serializer.rb
+++ b/lib/bundler/yaml_serializer.rb
@@ -3,7 +3,7 @@
module Bundler
# A stub yaml serializer that can handle only hashes and strings (as of now).
module YAMLSerializer
- module_function
+ module_function
def dump(hash)
yaml = String.new("---")
diff --git a/lib/cgi.rb b/lib/cgi.rb
index 4f16f309da..70b9d8c97b 100644
--- a/lib/cgi.rb
+++ b/lib/cgi.rb
@@ -288,6 +288,7 @@
#
class CGI
+ VERSION = "0.2.1"
end
require 'cgi/core'
diff --git a/lib/cgi/cgi.gemspec b/lib/cgi/cgi.gemspec
index 58bd77027d..1a883934e5 100644
--- a/lib/cgi/cgi.gemspec
+++ b/lib/cgi/cgi.gemspec
@@ -1,19 +1,23 @@
-begin
- require_relative "lib/cgi/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "cgi"
- spec.version = CGI::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
spec.summary = %q{Support for the Common Gateway Interface protocol.}
spec.description = %q{Support for the Common Gateway Interface protocol.}
spec.homepage = "https://github.com/ruby/cgi"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = ">= 2.5.0"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/lib/cgi/cookie.rb b/lib/cgi/cookie.rb
index 1a9c1a82c1..6b0d89ca3b 100644
--- a/lib/cgi/cookie.rb
+++ b/lib/cgi/cookie.rb
@@ -40,10 +40,6 @@ class CGI
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:
@@ -76,8 +72,8 @@ class CGI
@domain = nil
@expires = nil
if name.kind_of?(String)
- self.name = name
- self.path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
+ @name = name
+ @path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
@secure = false
@httponly = false
return super(value)
@@ -88,11 +84,11 @@ class CGI
raise ArgumentError, "`name' required"
end
- self.name = options["name"]
+ @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"]
+ @path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
+ @domain = options["domain"]
@expires = options["expires"]
@secure = options["secure"] == true
@httponly = options["httponly"] == true
@@ -101,35 +97,11 @@ class CGI
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
-
+ attr_accessor :name
# 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
-
+ attr_accessor :path
# 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
-
+ attr_accessor :domain
# Time at which this cookie expires, as a +Time+
attr_accessor :expires
# True if this cookie is secure; false otherwise
diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb
index 62e606837a..bec76e0749 100644
--- a/lib/cgi/core.rb
+++ b/lib/cgi/core.rb
@@ -188,28 +188,17 @@ class CGI
# 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 << "#{$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 << "Server: #{$CGI_ENV['SERVER_SOFTWARE']}#{EOL}"
buf << "Connection: close#{EOL}"
end
- buf << "Content-Type: #{_no_crlf_check(content_type)}#{EOL}"
+ buf << "Content-Type: #{content_type}#{EOL}"
if @output_cookies
- @output_cookies.each {|cookie| buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}" }
+ @output_cookies.each {|cookie| buf << "Set-Cookie: #{cookie}#{EOL}" }
end
return buf
end # _header_for_string
@@ -224,9 +213,9 @@ class CGI
## NPH
options.delete('nph') if defined?(MOD_RUBY)
if options.delete('nph') || nph?()
- protocol = _no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'
+ protocol = $CGI_ENV['SERVER_PROTOCOL'] || 'HTTP/1.0'
status = options.delete('status')
- status = HTTP_STATUS[status] || _no_crlf_check(status) || '200 OK'
+ status = HTTP_STATUS[status] || status || '200 OK'
buf << "#{protocol} #{status}#{EOL}"
buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
@@ -234,38 +223,38 @@ class CGI
end
## common headers
status = options.delete('status')
- buf << "Status: #{HTTP_STATUS[status] || _no_crlf_check(status)}#{EOL}" if status
+ buf << "Status: #{HTTP_STATUS[status] || status}#{EOL}" if status
server = options.delete('server')
- buf << "Server: #{_no_crlf_check(server)}#{EOL}" if server
+ buf << "Server: #{server}#{EOL}" if server
connection = options.delete('connection')
- buf << "Connection: #{_no_crlf_check(connection)}#{EOL}" if connection
+ buf << "Connection: #{connection}#{EOL}" if connection
type = options.delete('type')
- buf << "Content-Type: #{_no_crlf_check(type)}#{EOL}" #if type
+ buf << "Content-Type: #{type}#{EOL}" #if type
length = options.delete('length')
- buf << "Content-Length: #{_no_crlf_check(length)}#{EOL}" if length
+ buf << "Content-Length: #{length}#{EOL}" if length
language = options.delete('language')
- buf << "Content-Language: #{_no_crlf_check(language)}#{EOL}" if language
+ buf << "Content-Language: #{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}"
+ buf << "Set-Cookie: #{cookie}#{EOL}"
when Array
arr = cookie
- arr.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
+ arr.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
when Hash
hash = cookie
- hash.each_value {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
+ hash.each_value {|c| buf << "Set-Cookie: #{c}#{EOL}" }
end
end
if @output_cookies
- @output_cookies.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
+ @output_cookies.each {|c| buf << "Set-Cookie: #{c}#{EOL}" }
end
## other headers
options.each do |key, value|
- buf << "#{_no_crlf_check(key)}: #{_no_crlf_check(value)}#{EOL}"
+ buf << "#{key}: #{value}#{EOL}"
end
return buf
end # _header_for_hash
diff --git a/lib/cgi/version.rb b/lib/cgi/version.rb
deleted file mode 100644
index ee0c748069..0000000000
--- a/lib/cgi/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class CGI
- VERSION = "0.1.0.2"
-end
diff --git a/lib/csv.rb b/lib/csv.rb
index 8aa65868b7..056cfa2051 100644
--- a/lib/csv.rb
+++ b/lib/csv.rb
@@ -34,7 +34,7 @@
# I'm sure I'll miss something, but I'll try to mention most of the major
# differences I am aware of, to help others quickly get up to speed:
#
-# === CSV Parsing
+# === \CSV Parsing
#
# * This parser is m17n aware. See CSV for full details.
# * This library has a stricter parser and will throw MalformedCSVErrors on
@@ -103,85 +103,327 @@ require_relative "csv/writer"
using CSV::MatchP if CSV.const_defined?(:MatchP)
+# == \CSV
+# \CSV (comma-separated variables) data is a text representation of a table:
+# - A _row_ _separator_ delimits table rows.
+# A common row separator is the newline character <tt>"\n"</tt>.
+# - A _column_ _separator_ delimits fields in a row.
+# A common column separator is the comma character <tt>","</tt>.
#
-# This class provides a complete interface to CSV files and data. It offers
-# tools to enable you to read and write to and from Strings or IO objects, as
-# needed.
+# This \CSV \String, with row separator <tt>"\n"</tt>
+# and column separator <tt>","</tt>,
+# has three rows and two columns:
+# "foo,0\nbar,1\nbaz,2\n"
#
-# The most generic interface of the library is:
+# Despite the name \CSV, a \CSV representation can use different separators.
#
-# csv = CSV.new(string_or_io, **options)
+# For more about tables, see the Wikipedia article
+# "{Table (information)}[https://en.wikipedia.org/wiki/Table_(information)]",
+# especially its section
+# "{Simple table}[https://en.wikipedia.org/wiki/Table_(information)#Simple_table]"
#
-# # Reading: IO object should be open for read
-# csv.read # => array of rows
-# # or
-# csv.each do |row|
-# # ...
-# end
-# # or
-# row = csv.shift
+# == \Class \CSV
#
-# # Writing: IO object should be open for write
-# csv << row
+# Class \CSV provides methods for:
+# - Parsing \CSV data from a \String object, a \File (via its file path), or an \IO object.
+# - Generating \CSV data to a \String object.
#
-# There are several specialized class methods for one-statement reading or writing,
-# described in the Specialized Methods section.
+# To make \CSV available:
+# require 'csv'
#
-# If a String is passed into ::new, it is internally wrapped into a StringIO object.
+# All examples here assume that this has been done.
#
-# +options+ can be used for specifying the particular CSV flavor (column
-# separators, row separators, value quoting and so on), and for data conversion,
-# see Data Conversion section for the description of the latter.
+# == Keeping It Simple
#
-# == Specialized Methods
+# A \CSV object has dozens of instance methods that offer fine-grained control
+# of parsing and generating \CSV data.
+# For many needs, though, simpler approaches will do.
#
-# === Reading
+# This section summarizes the singleton methods in \CSV
+# that allow you to parse and generate without explicitly
+# creating \CSV objects.
+# For details, follow the links.
#
-# # From a file: all at once
-# arr_of_rows = CSV.read("path/to/file.csv", **options)
-# # iterator-style:
-# CSV.foreach("path/to/file.csv", **options) do |row|
-# # ...
-# end
+# === Simple Parsing
#
-# # From a string
-# arr_of_rows = CSV.parse("CSV,data,String", **options)
-# # or
-# CSV.parse("CSV,data,String", **options) do |row|
-# # ...
-# end
+# Parsing methods commonly return either of:
+# - An \Array of Arrays of Strings:
+# - The outer \Array is the entire "table".
+# - Each inner \Array is a row.
+# - Each \String is a field.
+# - A CSV::Table object. For details, see
+# {\CSV with Headers}[#class-CSV-label-CSV+with+Headers].
+#
+# ==== Parsing a \String
+#
+# The input to be parsed can be a string:
+# string = "foo,0\nbar,1\nbaz,2\n"
+#
+# \Method CSV.parse returns the entire \CSV data:
+# CSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+#
+# \Method CSV.parse_line returns only the first row:
+# CSV.parse_line(string) # => ["foo", "0"]
+#
+# \CSV extends class \String with instance method String#parse_csv,
+# which also returns only the first row:
+# string.parse_csv # => ["foo", "0"]
+#
+# ==== Parsing Via a \File Path
+#
+# The input to be parsed can be in a file:
+# string = "foo,0\nbar,1\nbaz,2\n"
+# path = 't.csv'
+# File.write(path, string)
+#
+# \Method CSV.read returns the entire \CSV data:
+# CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+#
+# \Method CSV.foreach iterates, passing each row to the given block:
+# CSV.foreach(path) do |row|
+# p row
+# end
+# Output:
+# ["foo", "0"]
+# ["bar", "1"]
+# ["baz", "2"]
+#
+# \Method CSV.table returns the entire \CSV data as a CSV::Table object:
+# CSV.table(path) # => #<CSV::Table mode:col_or_row row_count:3>
+#
+# ==== Parsing from an Open \IO Stream
+#
+# The input to be parsed can be in an open \IO stream:
+#
+# \Method CSV.read returns the entire \CSV data:
+# File.open(path) do |file|
+# CSV.read(file)
+# end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
#
-# === Writing
+# As does method CSV.parse:
+# File.open(path) do |file|
+# CSV.parse(file)
+# end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
#
-# # To a file
-# CSV.open("path/to/file.csv", "wb") do |csv|
-# csv << ["row", "of", "CSV", "data"]
-# csv << ["another", "row"]
-# # ...
+# \Method CSV.parse_line returns only the first row:
+# File.open(path) do |file|
+# CSV.parse_line(file)
+# end # => ["foo", "0"]
+#
+# \Method CSV.foreach iterates, passing each row to the given block:
+# File.open(path) do |file|
+# CSV.foreach(file) do |row|
+# p row
+# end
+# end
+# Output:
+# ["foo", "0"]
+# ["bar", "1"]
+# ["baz", "2"]
+#
+# \Method CSV.table returns the entire \CSV data as a CSV::Table object:
+# File.open(path) do |file|
+# CSV.table(file)
+# end # => #<CSV::Table mode:col_or_row row_count:3>
+#
+# === Simple Generating
+#
+# \Method CSV.generate returns a \String;
+# this example uses method CSV#<< to append the rows
+# that are to be generated:
+# output_string = CSV.generate do |csv|
+# csv << ['foo', 0]
+# csv << ['bar', 1]
+# csv << ['baz', 2]
# end
+# output_string # => "foo,0\nbar,1\nbaz,2\n"
+#
+# \Method CSV.generate_line returns a \String containing the single row
+# constructed from an \Array:
+# CSV.generate_line(['foo', '0']) # => "foo,0\n"
+#
+# \CSV extends class \Array with instance method <tt>Array#to_csv</tt>,
+# which forms an \Array into a \String:
+# ['foo', '0'].to_csv # => "foo,0\n"
#
-# # To a String
-# csv_string = CSV.generate do |csv|
-# csv << ["row", "of", "CSV", "data"]
-# csv << ["another", "row"]
-# # ...
+# === "Filtering" \CSV
+#
+# \Method CSV.filter provides a Unix-style filter for \CSV data.
+# The input data is processed to form the output data:
+# in_string = "foo,0\nbar,1\nbaz,2\n"
+# out_string = ''
+# CSV.filter(in_string, out_string) do |row|
+# row[0] = row[0].upcase
+# row[1] *= 4
# end
+# out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
+#
+# == \CSV Objects
+#
+# There are three ways to create a \CSV object:
+# - \Method CSV.new returns a new \CSV object.
+# - \Method CSV.instance returns a new or cached \CSV object.
+# - \Method \CSV() also returns a new or cached \CSV object.
+#
+# === Instance Methods
+#
+# \CSV has three groups of instance methods:
+# - Its own internally defined instance methods.
+# - Methods included by module Enumerable.
+# - Methods delegated to class IO. See below.
+#
+# ==== Delegated Methods
+#
+# For convenience, a CSV object will delegate to many methods in class IO.
+# (A few have wrapper "guard code" in \CSV.) You may call:
+# * IO#binmode
+# * #binmode?
+# * IO#close
+# * IO#close_read
+# * IO#close_write
+# * IO#closed?
+# * #eof
+# * #eof?
+# * IO#external_encoding
+# * IO#fcntl
+# * IO#fileno
+# * #flock
+# * IO#flush
+# * IO#fsync
+# * IO#internal_encoding
+# * #ioctl
+# * IO#isatty
+# * #path
+# * IO#pid
+# * IO#pos
+# * IO#pos=
+# * IO#reopen
+# * #rewind
+# * IO#seek
+# * #stat
+# * IO#string
+# * IO#sync
+# * IO#sync=
+# * IO#tell
+# * #to_i
+# * #to_io
+# * IO#truncate
+# * IO#tty?
+#
+# === Options
+#
+# The default values for options are:
+# DEFAULT_OPTIONS = {
+# # For both parsing and generating.
+# col_sep: ",",
+# row_sep: :auto,
+# quote_char: '"',
+# # For parsing.
+# field_size_limit: nil,
+# converters: nil,
+# unconverted_fields: nil,
+# headers: false,
+# return_headers: false,
+# header_converters: nil,
+# skip_blanks: false,
+# skip_lines: nil,
+# liberal_parsing: false,
+# nil_value: nil,
+# empty_value: "",
+# # For generating.
+# write_headers: nil,
+# quote_empty: true,
+# force_quotes: false,
+# write_converters: nil,
+# write_nil_value: nil,
+# write_empty_value: "",
+# strip: false,
+# }
+#
+# ==== Options for Parsing
+#
+# Options for parsing, described in detail below, include:
+# - +row_sep+: Specifies the row separator; used to delimit rows.
+# - +col_sep+: Specifies the column separator; used to delimit fields.
+# - +quote_char+: Specifies the quote character; used to quote fields.
+# - +field_size_limit+: Specifies the maximum field size allowed.
+# - +converters+: Specifies the field converters to be used.
+# - +unconverted_fields+: Specifies whether unconverted fields are to be available.
+# - +headers+: Specifies whether data contains headers,
+# or specifies the headers themselves.
+# - +return_headers+: Specifies whether headers are to be returned.
+# - +header_converters+: Specifies the header converters to be used.
+# - +skip_blanks+: Specifies whether blanks lines are to be ignored.
+# - +skip_lines+: Specifies how comments lines are to be recognized.
+# - +strip+: Specifies whether leading and trailing whitespace are
+# to be stripped from fields..
+# - +liberal_parsing+: Specifies whether \CSV should attempt to parse
+# non-compliant data.
+# - +nil_value+: Specifies the object that is to be substituted for each null (no-text) field.
+# - +empty_value+: Specifies the object that is to be substituted for each empty field.
+#
+# :include: ../doc/csv/options/common/row_sep.rdoc
+#
+# :include: ../doc/csv/options/common/col_sep.rdoc
+#
+# :include: ../doc/csv/options/common/quote_char.rdoc
+#
+# :include: ../doc/csv/options/parsing/field_size_limit.rdoc
+#
+# :include: ../doc/csv/options/parsing/converters.rdoc
+#
+# :include: ../doc/csv/options/parsing/unconverted_fields.rdoc
+#
+# :include: ../doc/csv/options/parsing/headers.rdoc
+#
+# :include: ../doc/csv/options/parsing/return_headers.rdoc
+#
+# :include: ../doc/csv/options/parsing/header_converters.rdoc
+#
+# :include: ../doc/csv/options/parsing/skip_blanks.rdoc
+#
+# :include: ../doc/csv/options/parsing/skip_lines.rdoc
+#
+# :include: ../doc/csv/options/parsing/strip.rdoc
+#
+# :include: ../doc/csv/options/parsing/liberal_parsing.rdoc
+#
+# :include: ../doc/csv/options/parsing/nil_value.rdoc
+#
+# :include: ../doc/csv/options/parsing/empty_value.rdoc
+#
+# ==== Options for Generating
+#
+# Options for generating, described in detail below, include:
+# - +row_sep+: Specifies the row separator; used to delimit rows.
+# - +col_sep+: Specifies the column separator; used to delimit fields.
+# - +quote_char+: Specifies the quote character; used to quote fields.
+# - +write_headers+: Specifies whether headers are to be written.
+# - +force_quotes+: Specifies whether each output field is to be quoted.
+# - +quote_empty+: Specifies whether each empty output field is to be quoted.
+# - +write_converters+: Specifies the field converters to be used in writing.
+# - +write_nil_value+: Specifies the object that is to be substituted for each +nil+-valued field.
+# - +write_empty_value+: Specifies the object that is to be substituted for each empty field.
+#
+# :include: ../doc/csv/options/common/row_sep.rdoc
+#
+# :include: ../doc/csv/options/common/col_sep.rdoc
+#
+# :include: ../doc/csv/options/common/quote_char.rdoc
#
-# === Shortcuts
+# :include: ../doc/csv/options/generating/write_headers.rdoc
#
-# # Core extensions for converting one line
-# csv_string = ["CSV", "data"].to_csv # to CSV
-# csv_array = "CSV,String".parse_csv # from CSV
+# :include: ../doc/csv/options/generating/force_quotes.rdoc
#
-# # CSV() method
-# CSV { |csv_out| csv_out << %w{my data here} } # to $stdout
-# CSV(csv = "") { |csv_str| csv_str << %w{my data here} } # to a String
-# CSV($stderr) { |csv_err| csv_err << %w{my data here} } # to $stderr
-# CSV($stdin) { |csv_in| csv_in.each { |row| p row } } # from $stdin
+# :include: ../doc/csv/options/generating/quote_empty.rdoc
#
-# == Data Conversion
+# :include: ../doc/csv/options/generating/write_converters.rdoc
#
-# === CSV with headers
+# :include: ../doc/csv/options/generating/write_nil_value.rdoc
+#
+# :include: ../doc/csv/options/generating/write_empty_value.rdoc
+#
+# === \CSV with Headers
#
# CSV allows to specify column names of CSV file, whether they are in data, or
# provided separately. If headers are specified, reading methods return an instance
@@ -203,24 +445,343 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
# data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary])
# data.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000">
#
-# === Typed data reading
-#
-# CSV allows to provide a set of data _converters_ e.g. transformations to try on input
-# data. Converter could be a symbol from CSV::Converters constant's keys, or lambda.
-#
-# # Without any converters:
-# CSV.parse('Bob,2018-03-01,100')
-# #=> [["Bob", "2018-03-01", "100"]]
-#
-# # With built-in converters:
-# CSV.parse('Bob,2018-03-01,100', converters: %i[numeric date])
-# #=> [["Bob", #<Date: 2018-03-01>, 100]]
-#
-# # With custom converters:
-# CSV.parse('Bob,2018-03-01,100', converters: [->(v) { Time.parse(v) rescue v }])
-# #=> [["Bob", 2018-03-01 00:00:00 +0200, "100"]]
+# === \Converters
+#
+# By default, each value (field or header) parsed by \CSV is formed into a \String.
+# You can use a _field_ _converter_ or _header_ _converter_
+# to intercept and modify the parsed values:
+# - See {Field Converters}[#class-CSV-label-Field+Converters].
+# - See {Header Converters}[#class-CSV-label-Header+Converters].
+#
+# Also by default, each value to be written during generation is written 'as-is'.
+# You can use a _write_ _converter_ to modify values before writing.
+# - See {Write Converters}[#class-CSV-label-Write+Converters].
+#
+# ==== Specifying \Converters
+#
+# You can specify converters for parsing or generating in the +options+
+# argument to various \CSV methods:
+# - Option +converters+ for converting parsed field values.
+# - Option +header_converters+ for converting parsed header values.
+# - Option +write_converters+ for converting values to be written (generated).
+#
+# There are three forms for specifying converters:
+# - A converter proc: executable code to be used for conversion.
+# - A converter name: the name of a stored converter.
+# - A converter list: an array of converter procs, converter names, and converter lists.
+#
+# ===== Converter Procs
+#
+# This converter proc, +strip_converter+, accepts a value +field+
+# and returns <tt>field.strip</tt>:
+# strip_converter = proc {|field| field.strip }
+# In this call to <tt>CSV.parse</tt>,
+# the keyword argument <tt>converters: string_converter</tt>
+# specifies that:
+# - \Proc +string_converter+ is to be called for each parsed field.
+# - The converter's return value is to replace the +field+ value.
+# Example:
+# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
+# array = CSV.parse(string, converters: strip_converter)
+# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+#
+# A converter proc can receive a second argument, +field_info+,
+# that contains details about the field.
+# This modified +strip_converter+ displays its arguments:
+# strip_converter = proc do |field, field_info|
+# p [field, field_info]
+# field.strip
+# end
+# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
+# array = CSV.parse(string, converters: strip_converter)
+# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+# Output:
+# [" foo ", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
+# [" 0 ", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
+# [" bar ", #<struct CSV::FieldInfo index=0, line=2, header=nil>]
+# [" 1 ", #<struct CSV::FieldInfo index=1, line=2, header=nil>]
+# [" baz ", #<struct CSV::FieldInfo index=0, line=3, header=nil>]
+# [" 2 ", #<struct CSV::FieldInfo index=1, line=3, header=nil>]
+# Each CSV::Info object shows:
+# - The 0-based field index.
+# - The 1-based line index.
+# - The field header, if any.
+#
+# ===== Stored \Converters
+#
+# A converter may be given a name and stored in a structure where
+# the parsing methods can find it by name.
+#
+# The storage structure for field converters is the \Hash CSV::Converters.
+# It has several built-in converter procs:
+# - <tt>:integer</tt>: converts each \String-embedded integer into a true \Integer.
+# - <tt>:float</tt>: converts each \String-embedded float into a true \Float.
+# - <tt>:date</tt>: converts each \String-embedded date into a true \Date.
+# - <tt>:date_time</tt>: converts each \String-embedded date-time into a true \DateTime
+# .
+# This example creates a converter proc, then stores it:
+# strip_converter = proc {|field| field.strip }
+# CSV::Converters[:strip] = strip_converter
+# Then the parsing method call can refer to the converter
+# by its name, <tt>:strip</tt>:
+# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
+# array = CSV.parse(string, converters: :strip)
+# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+#
+# The storage structure for header converters is the \Hash CSV::HeaderConverters,
+# which works in the same way.
+# It also has built-in converter procs:
+# - <tt>:downcase</tt>: Downcases each header.
+# - <tt>:symbol</tt>: Converts each header to a \Symbol.
+#
+# There is no such storage structure for write headers.
+#
+# ===== Converter Lists
+#
+# A _converter_ _list_ is an \Array that may include any assortment of:
+# - Converter procs.
+# - Names of stored converters.
+# - Nested converter lists.
+#
+# Examples:
+# numeric_converters = [:integer, :float]
+# date_converters = [:date, :date_time]
+# [numeric_converters, strip_converter]
+# [strip_converter, date_converters, :float]
+#
+# Like a converter proc, a converter list may be named and stored in either
+# \CSV::Converters or CSV::HeaderConverters:
+# CSV::Converters[:custom] = [strip_converter, date_converters, :float]
+# CSV::HeaderConverters[:custom] = [:downcase, :symbol]
+#
+# There are two built-in converter lists:
+# CSV::Converters[:numeric] # => [:integer, :float]
+# CSV::Converters[:all] # => [:date_time, :numeric]
+#
+# ==== Field \Converters
+#
+# With no conversion, all parsed fields in all rows become Strings:
+# string = "foo,0\nbar,1\nbaz,2\n"
+# ary = CSV.parse(string)
+# ary # => # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+#
+# When you specify a field converter, each parsed field is passed to the converter;
+# its return value becomes the stored value for the field.
+# A converter might, for example, convert an integer embedded in a \String
+# into a true \Integer.
+# (In fact, that's what built-in field converter +:integer+ does.)
+#
+# There are three ways to use field \converters.
+#
+# - Using option {converters}[#class-CSV-label-Option+converters] with a parsing method:
+# ary = CSV.parse(string, converters: :integer)
+# ary # => [0, 1, 2] # => [["foo", 0], ["bar", 1], ["baz", 2]]
+# - Using option {converters}[#class-CSV-label-Option+converters] with a new \CSV instance:
+# csv = CSV.new(string, converters: :integer)
+# # Field converters in effect:
+# csv.converters # => [:integer]
+# csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
+# - Using method #convert to add a field converter to a \CSV instance:
+# csv = CSV.new(string)
+# # Add a converter.
+# csv.convert(:integer)
+# csv.converters # => [:integer]
+# csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
+#
+# Installing a field converter does not affect already-read rows:
+# csv = CSV.new(string)
+# csv.shift # => ["foo", "0"]
+# # Add a converter.
+# csv.convert(:integer)
+# csv.converters # => [:integer]
+# csv.read # => [["bar", 1], ["baz", 2]]
+#
+# There are additional built-in \converters, and custom \converters are also supported.
+#
+# ===== Built-In Field \Converters
+#
+# The built-in field converters are in \Hash CSV::Converters:
+# - Each key is a field converter name.
+# - Each value is one of:
+# - A \Proc field converter.
+# - An \Array of field converter names.
+#
+# Display:
+# CSV::Converters.each_pair do |name, value|
+# if value.kind_of?(Proc)
+# p [name, value.class]
+# else
+# p [name, value]
+# end
+# end
+# Output:
+# [:integer, Proc]
+# [:float, Proc]
+# [:numeric, [:integer, :float]]
+# [:date, Proc]
+# [:date_time, Proc]
+# [:all, [:date_time, :numeric]]
+#
+# Each of these converters transcodes values to UTF-8 before attempting conversion.
+# If a value cannot be transcoded to UTF-8 the conversion will
+# fail and the value will remain unconverted.
+#
+# Converter +:integer+ converts each field that Integer() accepts:
+# data = '0,1,2,x'
+# # Without the converter
+# csv = CSV.parse_line(data)
+# csv # => ["0", "1", "2", "x"]
+# # With the converter
+# csv = CSV.parse_line(data, converters: :integer)
+# csv # => [0, 1, 2, "x"]
+#
+# Converter +:float+ converts each field that Float() accepts:
+# data = '1.0,3.14159,x'
+# # Without the converter
+# csv = CSV.parse_line(data)
+# csv # => ["1.0", "3.14159", "x"]
+# # With the converter
+# csv = CSV.parse_line(data, converters: :float)
+# csv # => [1.0, 3.14159, "x"]
+#
+# Converter +:numeric+ converts with both +:integer+ and +:float+..
+#
+# Converter +:date+ converts each field that Date::parse accepts:
+# data = '2001-02-03,x'
+# # Without the converter
+# csv = CSV.parse_line(data)
+# csv # => ["2001-02-03", "x"]
+# # With the converter
+# csv = CSV.parse_line(data, converters: :date)
+# csv # => [#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>, "x"]
+#
+# Converter +:date_time+ converts each field that DateTime::parse accepts:
+# data = '2020-05-07T14:59:00-05:00,x'
+# # Without the converter
+# csv = CSV.parse_line(data)
+# csv # => ["2020-05-07T14:59:00-05:00", "x"]
+# # With the converter
+# csv = CSV.parse_line(data, converters: :date_time)
+# csv # => [#<DateTime: 2020-05-07T14:59:00-05:00 ((2458977j,71940s,0n),-18000s,2299161j)>, "x"]
+#
+# Converter +:numeric+ converts with both +:date_time+ and +:numeric+..
+#
+# As seen above, method #convert adds \converters to a \CSV instance,
+# and method #converters returns an \Array of the \converters in effect:
+# csv = CSV.new('0,1,2')
+# csv.converters # => []
+# csv.convert(:integer)
+# csv.converters # => [:integer]
+# csv.convert(:date)
+# csv.converters # => [:integer, :date]
+#
+# ===== Custom Field \Converters
+#
+# You can define a custom field converter:
+# strip_converter = proc {|field| field.strip }
+# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
+# array = CSV.parse(string, converters: strip_converter)
+# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+# You can register the converter in \Converters \Hash,
+# which allows you to refer to it by name:
+# CSV::Converters[:strip] = strip_converter
+# string = " foo , 0 \n bar , 1 \n baz , 2 \n"
+# array = CSV.parse(string, converters: :strip)
+# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+#
+# ==== Header \Converters
+#
+# Header converters operate only on headers (and not on other rows).
+#
+# There are three ways to use header \converters;
+# these examples use built-in header converter +:dowhcase+,
+# which downcases each parsed header.
+#
+# - Option +header_converters+ with a singleton parsing method:
+# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
+# tbl = CSV.parse(string, headers: true, header_converters: :downcase)
+# tbl.class # => CSV::Table
+# tbl.headers # => ["name", "count"]
+#
+# - Option +header_converters+ with a new \CSV instance:
+# csv = CSV.new(string, header_converters: :downcase)
+# # Header converters in effect:
+# csv.header_converters # => [:downcase]
+# tbl = CSV.parse(string, headers: true)
+# tbl.headers # => ["Name", "Count"]
+#
+# - Method #header_convert adds a header converter to a \CSV instance:
+# csv = CSV.new(string)
+# # Add a header converter.
+# csv.header_convert(:downcase)
+# csv.header_converters # => [:downcase]
+# tbl = CSV.parse(string, headers: true)
+# tbl.headers # => ["Name", "Count"]
+#
+# ===== Built-In Header \Converters
+#
+# The built-in header \converters are in \Hash CSV::HeaderConverters.
+# The keys there are the names of the \converters:
+# CSV::HeaderConverters.keys # => [:downcase, :symbol]
+#
+# Converter +:downcase+ converts each header by downcasing it:
+# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
+# tbl = CSV.parse(string, headers: true, header_converters: :downcase)
+# tbl.class # => CSV::Table
+# tbl.headers # => ["name", "count"]
+#
+# Converter +:symbol+ converts each header by making it into a \Symbol:
+# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
+# tbl = CSV.parse(string, headers: true, header_converters: :symbol)
+# tbl.headers # => [:name, :count]
+# Details:
+# - Strips leading and trailing whitespace.
+# - Downcases the header.
+# - Replaces embedded spaces with underscores.
+# - Removes non-word characters.
+# - Makes the string into a \Symbol.
+#
+# ===== Custom Header \Converters
+#
+# You can define a custom header converter:
+# upcase_converter = proc {|header| header.upcase }
+# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+# table = CSV.parse(string, headers: true, header_converters: upcase_converter)
+# table # => #<CSV::Table mode:col_or_row row_count:4>
+# table.headers # => ["NAME", "VALUE"]
+# You can register the converter in \HeaderConverters \Hash,
+# which allows you to refer to it by name:
+# CSV::HeaderConverters[:upcase] = upcase_converter
+# table = CSV.parse(string, headers: true, header_converters: :upcase)
+# table # => #<CSV::Table mode:col_or_row row_count:4>
+# table.headers # => ["NAME", "VALUE"]
+#
+# ===== Write \Converters
+#
+# When you specify a write converter for generating \CSV,
+# each field to be written is passed to the converter;
+# its return value becomes the new value for the field.
+# A converter might, for example, strip whitespace from a field.
+#
+# Using no write converter (all fields unmodified):
+# output_string = CSV.generate do |csv|
+# csv << [' foo ', 0]
+# csv << [' bar ', 1]
+# csv << [' baz ', 2]
+# end
+# output_string # => " foo ,0\n bar ,1\n baz ,2\n"
+# Using option +write_converters+ with two custom write converters:
+# strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field }
+# upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field }
+# write_converters = [strip_converter, upcase_converter]
+# output_string = CSV.generate(write_converters: write_converters) do |csv|
+# csv << [' foo ', 0]
+# csv << [' bar ', 1]
+# csv << [' baz ', 2]
+# end
+# output_string # => "FOO,0\nBAR,1\nBAZ,2\n"
#
-# == CSV and Character Encodings (M17n or Multilingualization)
+# === Character Encodings (M17n or Multilingualization)
#
# This new CSV parser is m17n savvy. The parser works in the Encoding of the IO
# or String object being read from or written to. Your data is never transcoded
@@ -301,30 +862,12 @@ class CSV
# The encoding used by all converters.
ConverterEncoding = Encoding.find("UTF-8")
+ # A \Hash containing the names and \Procs for the built-in field converters.
+ # See {Built-In Field Converters}[#class-CSV-label-Built-In+Field+Converters].
#
- # This Hash holds the built-in converters of CSV that can be accessed by name.
- # You can select Converters with CSV.convert() or through the +options+ Hash
- # passed to CSV::new().
- #
- # <b><tt>:integer</tt></b>:: Converts any field Integer() accepts.
- # <b><tt>:float</tt></b>:: Converts any field Float() accepts.
- # <b><tt>:numeric</tt></b>:: A combination of <tt>:integer</tt>
- # and <tt>:float</tt>.
- # <b><tt>:date</tt></b>:: Converts any field Date::parse() accepts.
- # <b><tt>:date_time</tt></b>:: Converts any field DateTime::parse() accepts.
- # <b><tt>:all</tt></b>:: All built-in converters. A combination of
- # <tt>:date_time</tt> and <tt>:numeric</tt>.
- #
- # All built-in converters transcode field data to UTF-8 before attempting a
- # conversion. If your data cannot be transcoded to UTF-8 the conversion will
- # fail and the field will remain unchanged.
- #
- # This Hash is intentionally left unfrozen and users should feel free to add
- # values to it that can be accessed by all CSV objects.
- #
- # To add a combo field, the value should be an Array of names. Combo fields
- # can be nested with other combo fields.
- #
+ # This \Hash is intentionally left unfrozen, and may be extended with
+ # custom field converters.
+ # See {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters].
Converters = {
integer: lambda { |f|
Integer(f.encode(ConverterEncoding)) rescue f
@@ -352,27 +895,12 @@ class CSV
all: [:date_time, :numeric],
}
+ # A \Hash containing the names and \Procs for the built-in header converters.
+ # See {Built-In Header Converters}[#class-CSV-label-Built-In+Header+Converters].
#
- # This Hash holds the built-in header converters of CSV that can be accessed
- # by name. You can select HeaderConverters with CSV.header_convert() or
- # through the +options+ Hash passed to CSV::new().
- #
- # <b><tt>:downcase</tt></b>:: Calls downcase() on the header String.
- # <b><tt>:symbol</tt></b>:: Leading/trailing spaces are dropped, string is
- # downcased, remaining spaces are replaced with
- # underscores, non-word characters are dropped,
- # and finally to_sym() is called.
- #
- # All built-in header converters transcode header data to UTF-8 before
- # attempting a conversion. If your data cannot be transcoded to UTF-8 the
- # conversion will fail and the header will remain unchanged.
- #
- # This Hash is intentionally left unfrozen and users should feel free to add
- # values to it that can be accessed by all CSV objects.
- #
- # To add a combo field, the value should be an Array of names. Combo fields
- # can be nested with other combo fields.
- #
+ # This \Hash is intentionally left unfrozen, and may be extended with
+ # custom field converters.
+ # See {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters].
HeaderConverters = {
downcase: lambda { |h| h.encode(ConverterEncoding).downcase },
symbol: lambda { |h|
@@ -380,29 +908,13 @@ class CSV
gsub(/\s+/, "_").to_sym
}
}
-
- #
- # The options used when no overrides are given by calling code. They are:
- #
- # <b><tt>:col_sep</tt></b>:: <tt>","</tt>
- # <b><tt>:row_sep</tt></b>:: <tt>:auto</tt>
- # <b><tt>:quote_char</tt></b>:: <tt>'"'</tt>
- # <b><tt>:field_size_limit</tt></b>:: +nil+
- # <b><tt>:converters</tt></b>:: +nil+
- # <b><tt>:unconverted_fields</tt></b>:: +nil+
- # <b><tt>:headers</tt></b>:: +false+
- # <b><tt>:return_headers</tt></b>:: +false+
- # <b><tt>:header_converters</tt></b>:: +nil+
- # <b><tt>:skip_blanks</tt></b>:: +false+
- # <b><tt>:force_quotes</tt></b>:: +false+
- # <b><tt>:skip_lines</tt></b>:: +nil+
- # <b><tt>:liberal_parsing</tt></b>:: +false+
- # <b><tt>:quote_empty</tt></b>:: +true+
- #
+ # Default values for method options.
DEFAULT_OPTIONS = {
+ # For both parsing and generating.
col_sep: ",",
row_sep: :auto,
quote_char: '"',
+ # For parsing.
field_size_limit: nil,
converters: nil,
unconverted_fields: nil,
@@ -410,22 +922,62 @@ class CSV
return_headers: false,
header_converters: nil,
skip_blanks: false,
- force_quotes: false,
skip_lines: nil,
liberal_parsing: false,
+ nil_value: nil,
+ empty_value: "",
+ # For generating.
+ write_headers: nil,
quote_empty: true,
+ force_quotes: false,
+ write_converters: nil,
+ write_nil_value: nil,
+ write_empty_value: "",
+ strip: false,
}.freeze
class << self
+ # :call-seq:
+ # instance(string, **options)
+ # instance(io = $stdout, **options)
+ # instance(string, **options) {|csv| ... }
+ # instance(io = $stdout, **options) {|csv| ... }
+ #
+ # Creates or retrieves cached \CSV objects.
+ # For arguments and options, see CSV.new.
+ #
+ # ---
#
- # This method will return a CSV instance, just like CSV::new(), but the
- # instance will be cached and returned for all future calls to this method for
- # the same +data+ object (tested by Object#object_id()) with the same
- # +options+.
+ # With no block given, returns a \CSV object.
#
- # If a block is given, the instance is passed to the block and the return
- # value becomes the return value of the block.
+ # The first call to +instance+ creates and caches a \CSV object:
+ # s0 = 's0'
+ # csv0 = CSV.instance(s0)
+ # csv0.class # => CSV
#
+ # Subsequent calls to +instance+ with that _same_ +string+ or +io+
+ # retrieve that same cached object:
+ # csv1 = CSV.instance(s0)
+ # csv1.class # => CSV
+ # csv1.equal?(csv0) # => true # Same CSV object
+ #
+ # A subsequent call to +instance+ with a _different_ +string+ or +io+
+ # creates and caches a _different_ \CSV object.
+ # s1 = 's1'
+ # csv2 = CSV.instance(s1)
+ # csv2.equal?(csv0) # => false # Different CSV object
+ #
+ # All the cached objects remains available:
+ # csv3 = CSV.instance(s0)
+ # csv3.equal?(csv0) # true # Same CSV object
+ # csv4 = CSV.instance(s1)
+ # csv4.equal?(csv2) # true # Same CSV object
+ #
+ # ---
+ #
+ # When a block is given, calls the block with the created or retrieved
+ # \CSV object; returns the block's return value:
+ # CSV.instance(s0) {|csv| :foo } # => :foo
def instance(data = $stdout, **options)
# create a _signature_ for this method call, data object and options
sig = [data.object_id] +
@@ -442,30 +994,61 @@ class CSV
end
end
- #
# :call-seq:
- # filter( **options ) { |row| ... }
- # filter( input, **options ) { |row| ... }
- # filter( input, output, **options ) { |row| ... }
- #
- # This method is a convenience for building Unix-like filters for CSV data.
- # Each row is yielded to the provided block which can alter it as needed.
- # After the block returns, the row is appended to +output+ altered or not.
+ # filter(**options) {|row| ... }
+ # filter(in_string, **options) {|row| ... }
+ # filter(in_io, **options) {|row| ... }
+ # filter(in_string, out_string, **options) {|row| ... }
+ # filter(in_string, out_io, **options) {|row| ... }
+ # filter(in_io, out_string, **options) {|row| ... }
+ # filter(in_io, out_io, **options) {|row| ... }
#
- # The +input+ and +output+ arguments can be anything CSV::new() accepts
- # (generally String or IO objects). If not given, they default to
- # <tt>ARGF</tt> and <tt>$stdout</tt>.
+ # Reads \CSV input and writes \CSV output.
#
- # The +options+ parameter is also filtered down to CSV::new() after some
- # clever key parsing. Any key beginning with <tt>:in_</tt> or
- # <tt>:input_</tt> will have that leading identifier stripped and will only
- # be used in the +options+ Hash for the +input+ object. Keys starting with
- # <tt>:out_</tt> or <tt>:output_</tt> affect only +output+. All other keys
- # are assigned to both objects.
+ # For each input row:
+ # - Forms the data into:
+ # - A CSV::Row object, if headers are in use.
+ # - An \Array of Arrays, otherwise.
+ # - Calls the block with that object.
+ # - Appends the block's return value to the output.
#
- # The <tt>:output_row_sep</tt> +option+ defaults to
- # <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>).
+ # Arguments:
+ # * \CSV source:
+ # * Argument +in_string+, if given, should be a \String object;
+ # it will be put into a new StringIO object positioned at the beginning.
+ # * Argument +in_io+, if given, should be an IO object that is
+ # open for reading; on return, the IO object will be closed.
+ # * If neither +in_string+ nor +in_io+ is given,
+ # the input stream defaults to {ARGF}[https://ruby-doc.org/core/ARGF.html].
+ # * \CSV output:
+ # * Argument +out_string+, if given, should be a \String object;
+ # it will be put into a new StringIO object positioned at the beginning.
+ # * Argument +out_io+, if given, should be an IO object that is
+ # ppen for writing; on return, the IO object will be closed.
+ # * If neither +out_string+ nor +out_io+ is given,
+ # the output stream defaults to <tt>$stdout</tt>.
+ # * Argument +options+ should be keyword arguments.
+ # - Each argument name that is prefixed with +in_+ or +input_+
+ # is stripped of its prefix and is treated as an option
+ # for parsing the input.
+ # Option +input_row_sep+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>.
+ # - Each argument name that is prefixed with +out_+ or +output_+
+ # is stripped of its prefix and is treated as an option
+ # for generating the output.
+ # Option +output_row_sep+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>.
+ # - Each argument not prefixed as above is treated as an option
+ # both for parsing the input and for generating the output.
+ # - See {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
+ # and {Options for Generating}[#class-CSV-label-Options+for+Generating].
#
+ # Example:
+ # in_string = "foo,0\nbar,1\nbaz,2\n"
+ # out_string = ''
+ # CSV.filter(in_string, out_string) do |row|
+ # row[0] = row[0].upcase
+ # row[1] *= 4
+ # end
+ # out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
def filter(input=nil, output=nil, **options)
# parse options for input, output, or both
in_options, out_options = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR}
@@ -480,10 +1063,29 @@ class CSV
out_options[key] = value
end
end
+
# build input and output wrappers
- input = new(input || ARGF, **in_options)
+ input = new(input || ARGF, **in_options)
output = new(output || $stdout, **out_options)
+ # process headers
+ need_manual_header_output =
+ (in_options[:headers] and
+ out_options[:headers] == true and
+ out_options[:write_headers])
+ if need_manual_header_output
+ first_row = input.shift
+ if first_row
+ if first_row.is_a?(Row)
+ headers = first_row.headers
+ yield headers
+ output << headers
+ end
+ yield first_row
+ output << first_row
+ end
+ end
+
# read, yield, write
input.each do |row|
yield row
@@ -492,18 +1094,111 @@ class CSV
end
#
- # This method is intended as the primary interface for reading CSV files. You
- # pass a +path+ and any +options+ you wish to set for the read. Each row of
- # file will be passed to the provided +block+ in turn.
+ # :call-seq:
+ # foreach(path, mode='r', **options) {|row| ... )
+ # foreach(io, mode='r', **options {|row| ... )
+ # foreach(path, mode='r', headers: ..., **options) {|row| ... )
+ # foreach(io, mode='r', headers: ..., **options {|row| ... )
+ # foreach(path, mode='r', **options) -> new_enumerator
+ # foreach(io, mode='r', **options -> new_enumerator
+ #
+ # Calls the block with each row read from source +path+ or +io+.
+ #
+ # * Argument +path+, if given, must be the path to a file.
+ # :include: ../doc/csv/arguments/io.rdoc
+ # * Argument +mode+, if given, must be a \File mode
+ # See {Open Mode}[IO.html#method-c-new-label-Open+Mode].
+ # * Arguments <tt>**options</tt> must be keyword options.
+ # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
+ # * This method optionally accepts an additional <tt>:encoding</tt> option
+ # that you can use to specify the Encoding of the data read from +path+ or +io+.
+ # You must provide this unless your data is in the encoding
+ # given by <tt>Encoding::default_external</tt>.
+ # Parsing will use this to determine how to parse the data.
+ # You may provide a second Encoding to
+ # have the data transcoded as it is read. For example,
+ # encoding: 'UTF-32BE:UTF-8'
+ # would read +UTF-32BE+ data from the file
+ # but transcode it to +UTF-8+ before parsing.
+ #
+ # ====== Without Option +headers+
+ #
+ # Without option +headers+, returns each row as an \Array object.
+ #
+ # These examples assume prior execution of:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ #
+ # Read rows from a file at +path+:
+ # CSV.foreach(path) {|row| p row }
+ # Output:
+ # ["foo", "0"]
+ # ["bar", "1"]
+ # ["baz", "2"]
+ #
+ # Read rows from an \IO object:
+ # File.open(path) do |file|
+ # CSV.foreach(file) {|row| p row }
+ # end
+ #
+ # Output:
+ # ["foo", "0"]
+ # ["bar", "1"]
+ # ["baz", "2"]
+ #
+ # Returns a new \Enumerator if no block given:
+ # CSV.foreach(path) # => #<Enumerator: CSV:foreach("t.csv", "r")>
+ # CSV.foreach(File.open(path)) # => #<Enumerator: CSV:foreach(#<File:t.csv>, "r")>
+ #
+ # Issues a warning if an encoding is unsupported:
+ # CSV.foreach(File.open(path), encoding: 'foo:bar') {|row| }
+ # Output:
+ # warning: Unsupported encoding foo ignored
+ # warning: Unsupported encoding bar ignored
+ #
+ # ====== With Option +headers+
#
- # The +options+ parameter can be anything CSV::new() understands. This method
- # also understands an additional <tt>:encoding</tt> parameter that you can use
- # to specify the Encoding of the data in the file to be read. You must provide
- # this unless your data is in Encoding::default_external(). CSV will use this
- # to determine how to parse the data. You may provide a second Encoding to
- # have the data transcoded as it is read. For example,
- # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
- # but transcode it to UTF-8 before CSV parses it.
+ # With {option +headers+}[#class-CSV-label-Option+headers],
+ # returns each row as a CSV::Row object.
+ #
+ # These examples assume prior execution of:
+ # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ #
+ # Read rows from a file at +path+:
+ # CSV.foreach(path, headers: true) {|row| p row }
+ #
+ # Output:
+ # #<CSV::Row "Name":"foo" "Count":"0">
+ # #<CSV::Row "Name":"bar" "Count":"1">
+ # #<CSV::Row "Name":"baz" "Count":"2">
+ #
+ # Read rows from an \IO object:
+ # File.open(path) do |file|
+ # CSV.foreach(file, headers: true) {|row| p row }
+ # end
+ #
+ # Output:
+ # #<CSV::Row "Name":"foo" "Count":"0">
+ # #<CSV::Row "Name":"bar" "Count":"1">
+ # #<CSV::Row "Name":"baz" "Count":"2">
+ #
+ # ---
+ #
+ # Raises an exception if +path+ is a \String, but not the path to a readable file:
+ # # Raises Errno::ENOENT (No such file or directory @ rb_sysopen - nosuch.csv):
+ # CSV.foreach('nosuch.csv') {|row| }
+ #
+ # Raises an exception if +io+ is an \IO object, but not open for reading:
+ # io = File.open(path, 'w') {|row| }
+ # # Raises TypeError (no implicit conversion of nil into String):
+ # CSV.foreach(io) {|row| }
+ #
+ # Raises an exception if +mode+ is invalid:
+ # # Raises ArgumentError (invalid access mode nosuch):
+ # CSV.foreach(path, 'nosuch') {|row| }
#
def foreach(path, mode="r", **options, &block)
return to_enum(__method__, path, mode, **options) unless block_given?
@@ -514,29 +1209,71 @@ class CSV
#
# :call-seq:
- # generate( str, **options ) { |csv| ... }
- # generate( **options ) { |csv| ... }
+ # generate(csv_string, **options) {|csv| ... }
+ # generate(**options) {|csv| ... }
+ #
+ # * Argument +csv_string+, if given, must be a \String object;
+ # defaults to a new empty \String.
+ # * Arguments +options+, if given, should be generating options.
+ # See {Options for Generating}[#class-CSV-label-Options+for+Generating].
+ #
+ # ---
+ #
+ # Creates a new \CSV object via <tt>CSV.new(csv_string, **options)</tt>;
+ # calls the block with the \CSV object, which the block may modify;
+ # returns the \String generated from the \CSV object.
+ #
+ # Note that a passed \String *is* modified by this method.
+ # Pass <tt>csv_string</tt>.dup if the \String must be preserved.
+ #
+ # This method has one additional option: <tt>:encoding</tt>,
+ # which sets the base Encoding for the output if no no +str+ is specified.
+ # CSV needs this hint if you plan to output non-ASCII compatible data.
#
- # This method wraps a String you provide, or an empty default String, in a
- # CSV object which is passed to the provided block. You can use the block to
- # append CSV rows to the String and when the block exits, the final String
- # will be returned.
+ # ---
#
- # Note that a passed String *is* modified by this method. Call dup() before
- # passing if you need a new String.
+ # Add lines:
+ # input_string = "foo,0\nbar,1\nbaz,2\n"
+ # output_string = CSV.generate(input_string) do |csv|
+ # csv << ['bat', 3]
+ # csv << ['bam', 4]
+ # end
+ # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
+ # input_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
+ # output_string.equal?(input_string) # => true # Same string, modified
#
- # The +options+ parameter can be anything CSV::new() understands. This method
- # understands an additional <tt>:encoding</tt> parameter when not passed a
- # String to set the base Encoding for the output. CSV needs this hint if you
- # plan to output non-ASCII compatible data.
+ # Add lines into new string, preserving old string:
+ # input_string = "foo,0\nbar,1\nbaz,2\n"
+ # output_string = CSV.generate(input_string.dup) do |csv|
+ # csv << ['bat', 3]
+ # csv << ['bam', 4]
+ # end
+ # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
+ # input_string # => "foo,0\nbar,1\nbaz,2\n"
+ # output_string.equal?(input_string) # => false # Different strings
+ #
+ # Create lines from nothing:
+ # output_string = CSV.generate do |csv|
+ # csv << ['foo', 0]
+ # csv << ['bar', 1]
+ # csv << ['baz', 2]
+ # end
+ # output_string # => "foo,0\nbar,1\nbaz,2\n"
+ #
+ # ---
+ #
+ # Raises an exception if +csv_string+ is not a \String object:
+ # # Raises TypeError (no implicit conversion of Integer into String)
+ # CSV.generate(0)
#
def generate(str=nil, **options)
+ encoding = options[:encoding]
# add a default empty String, if none was given
if str
str = StringIO.new(str)
str.seek(0, IO::SEEK_END)
+ str.set_encoding(encoding) if encoding
else
- encoding = options[:encoding]
str = +""
str.force_encoding(encoding) if encoding
end
@@ -545,97 +1282,140 @@ class CSV
csv.string # return final String
end
+ # :call-seq:
+ # CSV.generate_line(ary)
+ # CSV.generate_line(ary, **options)
+ #
+ # Returns the \String created by generating \CSV from +ary+
+ # using the specified +options+.
+ #
+ # Argument +ary+ must be an \Array.
+ #
+ # Special options:
+ # * Option <tt>:row_sep</tt> defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
+ # (<tt>$/</tt>).:
+ # $INPUT_RECORD_SEPARATOR # => "\n"
+ # * This method accepts an additional option, <tt>:encoding</tt>, which sets the base
+ # Encoding for the output. This method will try to guess your Encoding from
+ # the first non-+nil+ field in +row+, if possible, but you may need to use
+ # this parameter as a backup plan.
+ #
+ # For other +options+,
+ # see {Options for Generating}[#class-CSV-label-Options+for+Generating].
#
- # This method is a shortcut for converting a single row (Array) into a CSV
- # String.
+ # ---
#
- # The +options+ parameter can be anything CSV::new() understands. This method
- # understands an additional <tt>:encoding</tt> parameter to set the base
- # Encoding for the output. This method will try to guess your Encoding from
- # the first non-+nil+ field in +row+, if possible, but you may need to use
- # this parameter as a backup plan.
+ # Returns the \String generated from an \Array:
+ # CSV.generate_line(['foo', '0']) # => "foo,0\n"
#
- # The <tt>:row_sep</tt> +option+ defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
- # (<tt>$/</tt>) when calling this method.
+ # ---
+ #
+ # Raises an exception if +ary+ is not an \Array:
+ # # Raises NoMethodError (undefined method `find' for :foo:Symbol)
+ # CSV.generate_line(:foo)
#
def generate_line(row, **options)
options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
str = +""
if options[:encoding]
str.force_encoding(options[:encoding])
- elsif field = row.find {|f| f.is_a?(String)}
- str.force_encoding(field.encoding)
+ else
+ fallback_encoding = nil
+ output_encoding = nil
+ row.each do |field|
+ next unless field.is_a?(String)
+ fallback_encoding ||= field.encoding
+ next if field.ascii_only?
+ output_encoding = field.encoding
+ break
+ end
+ output_encoding ||= fallback_encoding
+ if output_encoding
+ str.force_encoding(output_encoding)
+ end
end
(new(str, **options) << row).string
end
#
# :call-seq:
- # open( filename, mode = "rb", **options ) { |faster_csv| ... }
- # open( filename, **options ) { |faster_csv| ... }
- # open( filename, mode = "rb", **options )
- # open( filename, **options )
- #
- # This method opens an IO object, and wraps that with CSV. This is intended
- # as the primary interface for writing a CSV file.
- #
- # You must pass a +filename+ and may optionally add a +mode+ for Ruby's
- # open(). You may also pass an optional Hash containing any +options+
- # CSV::new() understands as the final argument.
- #
- # This method works like Ruby's open() call, in that it will pass a CSV object
- # to a provided block and close it when the block terminates, or it will
- # return the CSV object when no block is provided. (*Note*: This is different
- # from the Ruby 1.8 CSV library which passed rows to the block. Use
- # CSV::foreach() for that behavior.)
- #
- # You must provide a +mode+ with an embedded Encoding designator unless your
- # data is in Encoding::default_external(). CSV will check the Encoding of the
- # underlying IO object (set by the +mode+ you pass) to determine how to parse
- # the data. You may provide a second Encoding to have the data transcoded as
- # it is read just as you can with a normal call to IO::open(). For example,
- # <tt>"rb:UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file but
- # transcode it to UTF-8 before CSV parses it.
- #
- # An opened CSV object will delegate to many IO methods for convenience. You
- # may call:
- #
- # * binmode()
- # * binmode?()
- # * close()
- # * close_read()
- # * close_write()
- # * closed?()
- # * eof()
- # * eof?()
- # * external_encoding()
- # * fcntl()
- # * fileno()
- # * flock()
- # * flush()
- # * fsync()
- # * internal_encoding()
- # * ioctl()
- # * isatty()
- # * path()
- # * pid()
- # * pos()
- # * pos=()
- # * reopen()
- # * seek()
- # * stat()
- # * sync()
- # * sync=()
- # * tell()
- # * to_i()
- # * to_io()
- # * truncate()
- # * tty?()
+ # open(file_path, mode = "rb", **options ) -> new_csv
+ # open(io, mode = "rb", **options ) -> new_csv
+ # open(file_path, mode = "rb", **options ) { |csv| ... } -> object
+ # open(io, mode = "rb", **options ) { |csv| ... } -> object
+ #
+ # possible options elements:
+ # hash form:
+ # :invalid => nil # raise error on invalid byte sequence (default)
+ # :invalid => :replace # replace invalid byte sequence
+ # :undef => :replace # replace undefined conversion
+ # :replace => string # replacement string ("?" or "\uFFFD" if not specified)
+ #
+ # * Argument +path+, if given, must be the path to a file.
+ # :include: ../doc/csv/arguments/io.rdoc
+ # * Argument +mode+, if given, must be a \File mode
+ # See {Open Mode}[IO.html#method-c-new-label-Open+Mode].
+ # * Arguments <tt>**options</tt> must be keyword options.
+ # See {Options for Generating}[#class-CSV-label-Options+for+Generating].
+ # * This method optionally accepts an additional <tt>:encoding</tt> option
+ # that you can use to specify the Encoding of the data read from +path+ or +io+.
+ # You must provide this unless your data is in the encoding
+ # given by <tt>Encoding::default_external</tt>.
+ # Parsing will use this to determine how to parse the data.
+ # You may provide a second Encoding to
+ # have the data transcoded as it is read. For example,
+ # encoding: 'UTF-32BE:UTF-8'
+ # would read +UTF-32BE+ data from the file
+ # but transcode it to +UTF-8+ before parsing.
+ #
+ # ---
#
+ # These examples assume prior execution of:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ #
+ # ---
+ #
+ # With no block given, returns a new \CSV object.
+ #
+ # Create a \CSV object using a file path:
+ # csv = CSV.open(path)
+ # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
+ #
+ # Create a \CSV object using an open \File:
+ # csv = CSV.open(File.open(path))
+ # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
+ #
+ # ---
+ #
+ # With a block given, calls the block with the created \CSV object;
+ # returns the block's return value:
+ #
+ # Using a file path:
+ # csv = CSV.open(path) {|csv| p csv}
+ # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
+ # Output:
+ # #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
+ #
+ # Using an open \File:
+ # csv = CSV.open(File.open(path)) {|csv| p csv}
+ # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
+ # Output:
+ # #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
+ #
+ # ---
+ #
+ # Raises an exception if the argument is not a \String object or \IO object:
+ # # Raises TypeError (no implicit conversion of Symbol into String)
+ # CSV.open(:foo)
def open(filename, mode="r", **options)
# wrap a File opened with the remaining +args+ with no newline
# decorator
file_opts = {universal_newline: false}.merge(options)
+ options.delete(:invalid)
+ options.delete(:undef)
+ options.delete(:replace)
begin
f = File.open(filename, mode, **file_opts)
@@ -666,16 +1446,116 @@ class CSV
#
# :call-seq:
- # parse( str, **options ) { |row| ... }
- # parse( str, **options )
+ # parse(string) -> array_of_arrays
+ # parse(io) -> array_of_arrays
+ # parse(string, headers: ..., **options) -> csv_table
+ # parse(io, headers: ..., **options) -> csv_table
+ # parse(string, **options) {|row| ... }
+ # parse(io, **options) {|row| ... }
+ #
+ # Parses +string+ or +io+ using the specified +options+.
+ #
+ # - Argument +string+ should be a \String object;
+ # it will be put into a new StringIO object positioned at the beginning.
+ # :include: ../doc/csv/arguments/io.rdoc
+ # - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
+ #
+ # ====== Without Option +headers+
+ #
+ # Without {option +headers+}[#class-CSV-label-Option+headers] case.
#
- # This method can be used to easily parse CSV out of a String. You may either
- # provide a +block+ which will be called with each row of the String in turn,
- # or just use the returned Array of Arrays (when no +block+ is given).
+ # These examples assume prior execution of:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
#
- # You pass your +str+ to read from, and an optional +options+ containing
- # anything CSV::new() understands.
+ # ---
#
+ # With no block given, returns an \Array of Arrays formed from the source.
+ #
+ # Parse a \String:
+ # a_of_a = CSV.parse(string)
+ # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+ #
+ # Parse an open \File:
+ # a_of_a = File.open(path) do |file|
+ # CSV.parse(file)
+ # end
+ # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+ #
+ # ---
+ #
+ # With a block given, calls the block with each parsed row:
+ #
+ # Parse a \String:
+ # CSV.parse(string) {|row| p row }
+ #
+ # Output:
+ # ["foo", "0"]
+ # ["bar", "1"]
+ # ["baz", "2"]
+ #
+ # Parse an open \File:
+ # File.open(path) do |file|
+ # CSV.parse(file) {|row| p row }
+ # end
+ #
+ # Output:
+ # ["foo", "0"]
+ # ["bar", "1"]
+ # ["baz", "2"]
+ #
+ # ====== With Option +headers+
+ #
+ # With {option +headers+}[#class-CSV-label-Option+headers] case.
+ #
+ # These examples assume prior execution of:
+ # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ #
+ # ---
+ #
+ # With no block given, returns a CSV::Table object formed from the source.
+ #
+ # Parse a \String:
+ # csv_table = CSV.parse(string, headers: ['Name', 'Count'])
+ # csv_table # => #<CSV::Table mode:col_or_row row_count:5>
+ #
+ # Parse an open \File:
+ # csv_table = File.open(path) do |file|
+ # CSV.parse(file, headers: ['Name', 'Count'])
+ # end
+ # csv_table # => #<CSV::Table mode:col_or_row row_count:4>
+ #
+ # ---
+ #
+ # With a block given, calls the block with each parsed row,
+ # which has been formed into a CSV::Row object:
+ #
+ # Parse a \String:
+ # CSV.parse(string, headers: ['Name', 'Count']) {|row| p row }
+ #
+ # Output:
+ # # <CSV::Row "Name":"foo" "Count":"0">
+ # # <CSV::Row "Name":"bar" "Count":"1">
+ # # <CSV::Row "Name":"baz" "Count":"2">
+ #
+ # Parse an open \File:
+ # File.open(path) do |file|
+ # CSV.parse(file, headers: ['Name', 'Count']) {|row| p row }
+ # end
+ #
+ # Output:
+ # # <CSV::Row "Name":"foo" "Count":"0">
+ # # <CSV::Row "Name":"bar" "Count":"1">
+ # # <CSV::Row "Name":"baz" "Count":"2">
+ #
+ # ---
+ #
+ # Raises an exception if the argument is not a \String object or \IO object:
+ # # Raises NoMethodError (undefined method `close' for :foo:Symbol)
+ # CSV.parse(:foo)
def parse(str, **options, &block)
csv = new(str, **options)
@@ -689,44 +1569,117 @@ class CSV
end
end
+ # :call-seq:
+ # CSV.parse_line(string) -> new_array or nil
+ # CSV.parse_line(io) -> new_array or nil
+ # CSV.parse_line(string, **options) -> new_array or nil
+ # CSV.parse_line(io, **options) -> new_array or nil
+ # CSV.parse_line(string, headers: true, **options) -> csv_row or nil
+ # CSV.parse_line(io, headers: true, **options) -> csv_row or nil
+ #
+ # Returns the data created by parsing the first line of +string+ or +io+
+ # using the specified +options+.
+ #
+ # - Argument +string+ should be a \String object;
+ # it will be put into a new StringIO object positioned at the beginning.
+ # :include: ../doc/csv/arguments/io.rdoc
+ # - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
+ #
+ # ====== Without Option +headers+
+ #
+ # Without option +headers+, returns the first row as a new \Array.
+ #
+ # These examples assume prior execution of:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ #
+ # Parse the first line from a \String object:
+ # CSV.parse_line(string) # => ["foo", "0"]
#
- # This method is a shortcut for converting a single line of a CSV String into
- # an Array. Note that if +line+ contains multiple rows, anything beyond the
- # first row is ignored.
+ # Parse the first line from a File object:
+ # File.open(path) do |file|
+ # CSV.parse_line(file) # => ["foo", "0"]
+ # end # => ["foo", "0"]
#
- # The +options+ parameter can be anything CSV::new() understands.
+ # Returns +nil+ if the argument is an empty \String:
+ # CSV.parse_line('') # => nil
+ #
+ # ====== With Option +headers+
+ #
+ # With {option +headers+}[#class-CSV-label-Option+headers],
+ # returns the first row as a CSV::Row object.
+ #
+ # These examples assume prior execution of:
+ # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ #
+ # Parse the first line from a \String object:
+ # CSV.parse_line(string, headers: true) # => #<CSV::Row "Name":"foo" "Count":"0">
+ #
+ # Parse the first line from a File object:
+ # File.open(path) do |file|
+ # CSV.parse_line(file, headers: true)
+ # end # => #<CSV::Row "Name":"foo" "Count":"0">
+ #
+ # ---
+ #
+ # Raises an exception if the argument is +nil+:
+ # # Raises ArgumentError (Cannot parse nil as CSV):
+ # CSV.parse_line(nil)
#
def parse_line(line, **options)
- new(line, **options).shift
+ new(line, **options).each.first
end
#
- # Use to slurp a CSV file into an Array of Arrays. Pass the +path+ to the
- # file and any +options+ CSV::new() understands. This method also understands
- # an additional <tt>:encoding</tt> parameter that you can use to specify the
- # Encoding of the data in the file to be read. You must provide this unless
- # your data is in Encoding::default_external(). CSV will use this to determine
- # how to parse the data. You may provide a second Encoding to have the data
- # transcoded as it is read. For example,
- # <tt>encoding: "UTF-32BE:UTF-8"</tt> would read UTF-32BE data from the file
- # but transcode it to UTF-8 before CSV parses it.
+ # :call-seq:
+ # read(source, **options) -> array_of_arrays
+ # read(source, headers: true, **options) -> csv_table
#
+ # Opens the given +source+ with the given +options+ (see CSV.open),
+ # reads the source (see CSV#read), and returns the result,
+ # which will be either an \Array of Arrays or a CSV::Table.
+ #
+ # Without headers:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ # CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+ #
+ # With headers:
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ # CSV.read(path, headers: true) # => #<CSV::Table mode:col_or_row row_count:4>
def read(path, **options)
open(path, **options) { |csv| csv.read }
end
- # Alias for CSV::read().
+ # :call-seq:
+ # CSV.readlines(source, **options)
+ #
+ # Alias for CSV.read.
def readlines(path, **options)
read(path, **options)
end
+ # :call-seq:
+ # CSV.table(source, **options)
#
- # A shortcut for:
+ # Calls CSV.read with +source+, +options+, and certain default options:
+ # - +headers+: +true+
+ # - +converbers+: +:numeric+
+ # - +header_converters+: +:symbol+
#
- # CSV.read( path, { headers: true,
- # converters: :numeric,
- # header_converters: :symbol }.merge(options) )
+ # Returns a CSV::Table object.
#
+ # Example:
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ # CSV.table(path) # => #<CSV::Table mode:col_or_row row_count:4>
def table(path, **options)
default_options = {
headers: true,
@@ -738,185 +1691,43 @@ class CSV
end
end
+ # :call-seq:
+ # CSV.new(string)
+ # CSV.new(io)
+ # CSV.new(string, **options)
+ # CSV.new(io, **options)
+ #
+ # Returns the new \CSV object created using +string+ or +io+
+ # and the specified +options+.
#
- # This constructor will wrap either a String or IO object passed in +data+ for
- # reading and/or writing. In addition to the CSV instance methods, several IO
- # methods are delegated. (See CSV::open() for a complete list.) If you pass
- # a String for +data+, you can later retrieve it (after writing to it, for
- # example) with CSV.string().
- #
- # Note that a wrapped String will be positioned at the beginning (for
- # reading). If you want it at the end (for writing), use CSV::generate().
- # If you want any other positioning, pass a preset StringIO object instead.
- #
- # You may set any reading and/or writing preferences in the +options+ Hash.
- # Available options are:
- #
- # <b><tt>:col_sep</tt></b>:: The String placed between each field.
- # This String will be transcoded into
- # the data's Encoding before parsing.
- # <b><tt>:row_sep</tt></b>:: The String appended to the end of each
- # row. This can be set to the special
- # <tt>:auto</tt> setting, which requests
- # that CSV automatically discover this
- # from the data. Auto-discovery reads
- # ahead in the data looking for the next
- # <tt>"\r\n"</tt>, <tt>"\n"</tt>, or
- # <tt>"\r"</tt> sequence. A sequence
- # will be selected even if it occurs in
- # a quoted field, assuming that you
- # would have the same line endings
- # there. If none of those sequences is
- # found, +data+ is <tt>ARGF</tt>,
- # <tt>STDIN</tt>, <tt>STDOUT</tt>, or
- # <tt>STDERR</tt>, or the stream is only
- # available for output, the default
- # <tt>$INPUT_RECORD_SEPARATOR</tt>
- # (<tt>$/</tt>) is used. Obviously,
- # discovery takes a little time. Set
- # manually if speed is important. Also
- # note that IO objects should be opened
- # in binary mode on Windows if this
- # feature will be used as the
- # line-ending translation can cause
- # problems with resetting the document
- # position to where it was before the
- # read ahead. This String will be
- # transcoded into the data's Encoding
- # before parsing.
- # <b><tt>:quote_char</tt></b>:: The character used to quote fields.
- # This has to be a single character
- # String. This is useful for
- # application that incorrectly use
- # <tt>'</tt> as the quote character
- # instead of the correct <tt>"</tt>.
- # CSV will always consider a double
- # sequence of this character to be an
- # escaped quote. This String will be
- # transcoded into the data's Encoding
- # before parsing.
- # <b><tt>:field_size_limit</tt></b>:: This is a maximum size CSV will read
- # ahead looking for the closing quote
- # for a field. (In truth, it reads to
- # the first line ending beyond this
- # size.) If a quote cannot be found
- # within the limit CSV will raise a
- # MalformedCSVError, assuming the data
- # is faulty. You can use this limit to
- # prevent what are effectively DoS
- # attacks on the parser. However, this
- # limit can cause a legitimate parse to
- # fail and thus is set to +nil+, or off,
- # by default.
- # <b><tt>:converters</tt></b>:: An Array of names from the Converters
- # Hash and/or lambdas that handle custom
- # conversion. A single converter
- # doesn't have to be in an Array. All
- # built-in converters try to transcode
- # fields to UTF-8 before converting.
- # The conversion will fail if the data
- # cannot be transcoded, leaving the
- # field unchanged.
- # <b><tt>:unconverted_fields</tt></b>:: If set to +true+, an
- # unconverted_fields() method will be
- # added to all returned rows (Array or
- # CSV::Row) that will return the fields
- # as they were before conversion. Note
- # that <tt>:headers</tt> supplied by
- # Array or String were not fields of the
- # document and thus will have an empty
- # Array attached.
- # <b><tt>:headers</tt></b>:: If set to <tt>:first_row</tt> or
- # +true+, the initial row of the CSV
- # file will be treated as a row of
- # headers. If set to an Array, the
- # contents will be used as the headers.
- # If set to a String, the String is run
- # through a call of CSV::parse_line()
- # with the same <tt>:col_sep</tt>,
- # <tt>:row_sep</tt>, and
- # <tt>:quote_char</tt> as this instance
- # to produce an Array of headers. This
- # setting causes CSV#shift() to return
- # rows as CSV::Row objects instead of
- # Arrays and CSV#read() to return
- # CSV::Table objects instead of an Array
- # of Arrays.
- # <b><tt>:return_headers</tt></b>:: When +false+, header rows are silently
- # swallowed. If set to +true+, header
- # rows are returned in a CSV::Row object
- # with identical headers and
- # fields (save that the fields do not go
- # through the converters).
- # <b><tt>:write_headers</tt></b>:: When +true+ and <tt>:headers</tt> is
- # set, a header row will be added to the
- # output.
- # <b><tt>:header_converters</tt></b>:: Identical in functionality to
- # <tt>:converters</tt> save that the
- # conversions are only made to header
- # rows. All built-in converters try to
- # transcode headers to UTF-8 before
- # converting. The conversion will fail
- # if the data cannot be transcoded,
- # leaving the header unchanged.
- # <b><tt>:skip_blanks</tt></b>:: When setting a +true+ value, CSV will
- # skip over any empty rows. Note that
- # this setting will not skip rows that
- # contain column separators, even if
- # the rows contain no actual data. If
- # you want to skip rows that contain
- # separators but no content, consider
- # using <tt>:skip_lines</tt>, or
- # inspecting fields.compact.empty? on
- # each row.
- # <b><tt>:force_quotes</tt></b>:: When setting a +true+ value, CSV will
- # quote all CSV fields it creates.
- # <b><tt>:skip_lines</tt></b>:: When setting an object responding to
- # <tt>match</tt>, every line matching
- # it is considered a comment and ignored
- # during parsing. When set to a String,
- # it is first converted to a Regexp.
- # When set to +nil+ no line is considered
- # a comment. If the passed object does
- # not respond to <tt>match</tt>,
- # <tt>ArgumentError</tt> is thrown.
- # <b><tt>:liberal_parsing</tt></b>:: When setting a +true+ value, CSV will
- # attempt to parse input not conformant
- # with RFC 4180, such as double quotes
- # in unquoted fields.
- # <b><tt>:nil_value</tt></b>:: When set an object, any values of an
- # empty field is replaced by the set
- # object, not nil.
- # <b><tt>:empty_value</tt></b>:: When setting an object, any values of a
- # blank string field is replaced by
- # the set object.
- # <b><tt>:quote_empty</tt></b>:: When setting a +true+ value, CSV will
- # quote empty values with double quotes.
- # When +false+, CSV will emit an
- # empty string for an empty field value.
- # <b><tt>:write_converters</tt></b>:: Converts values on each line with the
- # specified <tt>Proc</tt> object(s),
- # which receive a <tt>String</tt> value
- # and return a <tt>String</tt> or +nil+
- # value.
- # When an array is specified, each
- # converter will be applied in order.
- # <b><tt>:write_nil_value</tt></b>:: When a <tt>String</tt> value, +nil+
- # value(s) on each line will be replaced
- # with the specified value.
- # <b><tt>:write_empty_value</tt></b>:: When a <tt>String</tt> or +nil+ value,
- # empty value(s) on each line will be
- # replaced with the specified value.
- # <b><tt>:strip</tt></b>:: When setting a +true+ value, CSV will
- # strip "\t\r\n\f\v" around the values.
- # If you specify a string instead of
- # +true+, CSV will strip string. The
- # length of the string must be 1.
- #
- # See CSV::DEFAULT_OPTIONS for the default settings.
- #
- # Options cannot be overridden in the instance methods for performance reasons,
- # so be sure to set what you want here.
+ # - Argument +string+ should be a \String object;
+ # it will be put into a new StringIO object positioned at the beginning.
+ # :include: ../doc/csv/arguments/io.rdoc
+ # - Argument +options+: See:
+ # * {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
+ # * {Options for Generating}[#class-CSV-label-Options+for+Generating]
+ # For performance reasons, the options cannot be overridden
+ # in a \CSV object, so those specified here will endure.
+ #
+ # In addition to the \CSV instance methods, several \IO methods are delegated.
+ # See {Delegated Methods}[#class-CSV-label-Delegated+Methods].
+ #
+ # ---
+ #
+ # Create a \CSV object from a \String object:
+ # csv = CSV.new('foo,0')
+ # csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
+ #
+ # Create a \CSV object from a \File object:
+ # File.write('t.csv', 'foo,0')
+ # csv = CSV.new(File.open('t.csv'))
+ # csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
+ #
+ # ---
+ #
+ # Raises an exception if the argument is +nil+:
+ # # Raises ArgumentError (Cannot parse nil as CSV):
+ # CSV.new(nil)
#
def initialize(data,
col_sep: ",",
@@ -1001,51 +1812,67 @@ class CSV
writer if @writer_options[:write_headers]
end
+ # :call-seq:
+ # csv.col_sep -> string
#
- # The encoded <tt>:col_sep</tt> used in parsing and writing.
- # See CSV::new for details.
- #
+ # Returns the encoded column separator; used for parsing and writing;
+ # see {Option +col_sep+}[#class-CSV-label-Option+col_sep]:
+ # CSV.new('').col_sep # => ","
def col_sep
parser.column_separator
end
+ # :call-seq:
+ # csv.row_sep -> string
#
- # The encoded <tt>:row_sep</tt> used in parsing and writing.
- # See CSV::new for details.
- #
+ # Returns the encoded row separator; used for parsing and writing;
+ # see {Option +row_sep+}[#class-CSV-label-Option+row_sep]:
+ # CSV.new('').row_sep # => "\n"
def row_sep
parser.row_separator
end
+ # :call-seq:
+ # csv.quote_char -> character
#
- # The encoded <tt>:quote_char</tt> used in parsing and writing.
- # See CSV::new for details.
- #
+ # Returns the encoded quote character; used for parsing and writing;
+ # see {Option +quote_char+}[#class-CSV-label-Option+quote_char]:
+ # CSV.new('').quote_char # => "\""
def quote_char
parser.quote_character
end
+ # :call-seq:
+ # csv.field_size_limit -> integer or nil
#
- # The limit for field size, if any.
- # See CSV::new for details.
- #
+ # Returns the limit for field size; used for parsing;
+ # see {Option +field_size_limit+}[#class-CSV-label-Option+field_size_limit]:
+ # CSV.new('').field_size_limit # => nil
def field_size_limit
parser.field_size_limit
end
+ # :call-seq:
+ # csv.skip_lines -> regexp or nil
#
- # The regex marking a line as a comment.
- # See CSV::new for details.
- #
+ # Returns the \Regexp used to identify comment lines; used for parsing;
+ # see {Option +skip_lines+}[#class-CSV-label-Option+skip_lines]:
+ # CSV.new('').skip_lines # => nil
def skip_lines
parser.skip_lines
end
- #
- # Returns the current list of converters in effect. See CSV::new for details.
- # Built-in converters will be returned by name, while others will be returned
- # as is.
- #
+ # :call-seq:
+ # csv.converters -> array
+ #
+ # Returns an \Array containing field converters;
+ # see {Field Converters}[#class-CSV-label-Field+Converters]:
+ # csv = CSV.new('')
+ # csv.converters # => []
+ # csv.convert(:integer)
+ # csv.converters # => [:integer]
+ # csv.convert(proc {|x| x.to_s })
+ # csv.converters
def converters
parser_fields_converter.map do |converter|
name = Converters.rassoc(converter)
@@ -1053,19 +1880,23 @@ class CSV
end
end
+ # :call-seq:
+ # csv.unconverted_fields? -> object
#
- # Returns +true+ if unconverted_fields() to parsed results.
- # See CSV::new for details.
- #
+ # Returns the value that determines whether unconverted fields are to be
+ # available; used for parsing;
+ # see {Option +unconverted_fields+}[#class-CSV-label-Option+unconverted_fields]:
+ # CSV.new('').unconverted_fields? # => nil
def unconverted_fields?
parser.unconverted_fields?
end
+ # :call-seq:
+ # csv.headers -> object
#
- # Returns +nil+ if headers will not be used, +true+ if they will but have not
- # yet been read, or the actual headers after they have been read.
- # See CSV::new for details.
- #
+ # Returns the value that determines whether headers are used; used for parsing;
+ # see {Option +headers+}[#class-CSV-label-Option+headers]:
+ # CSV.new('').headers # => nil
def headers
if @writer
@writer.headers
@@ -1077,27 +1908,33 @@ class CSV
raw_headers
end
end
+
+ # :call-seq:
+ # csv.return_headers? -> true or false
#
- # Returns +true+ if headers will be returned as a row of results.
- # See CSV::new for details.
- #
+ # Returns the value that determines whether headers are to be returned; used for parsing;
+ # see {Option +return_headers+}[#class-CSV-label-Option+return_headers]:
+ # CSV.new('').return_headers? # => false
def return_headers?
parser.return_headers?
end
+ # :call-seq:
+ # csv.write_headers? -> true or false
#
- # Returns +true+ if headers are written in output.
- # See CSV::new for details.
- #
+ # Returns the value that determines whether headers are to be written; used for generating;
+ # see {Option +write_headers+}[#class-CSV-label-Option+write_headers]:
+ # CSV.new('').write_headers? # => nil
def write_headers?
@writer_options[:write_headers]
end
+ # :call-seq:
+ # csv.header_converters -> array
#
- # Returns the current list of converters in effect for headers. See CSV::new
- # for details. Built-in converters will be returned by name, while others
- # will be returned as is.
- #
+ # Returns an \Array containing header converters; used for parsing;
+ # see {Header Converters}[#class-CSV-label-Header+Converters]:
+ # CSV.new('').header_converters # => []
def header_converters
header_fields_converter.map do |converter|
name = HeaderConverters.rassoc(converter)
@@ -1105,34 +1942,74 @@ class CSV
end
end
+ # :call-seq:
+ # csv.skip_blanks? -> true or false
#
- # Returns +true+ blank lines are skipped by the parser. See CSV::new
- # for details.
- #
+ # Returns the value that determines whether blank lines are to be ignored; used for parsing;
+ # see {Option +skip_blanks+}[#class-CSV-label-Option+skip_blanks]:
+ # CSV.new('').skip_blanks? # => false
def skip_blanks?
parser.skip_blanks?
end
- # Returns +true+ if all output fields are quoted. See CSV::new for details.
+ # :call-seq:
+ # csv.force_quotes? -> true or false
+ #
+ # Returns the value that determines whether all output fields are to be quoted;
+ # used for generating;
+ # see {Option +force_quotes+}[#class-CSV-label-Option+force_quotes]:
+ # CSV.new('').force_quotes? # => false
def force_quotes?
@writer_options[:force_quotes]
end
- # Returns +true+ if illegal input is handled. See CSV::new for details.
+ # :call-seq:
+ # csv.liberal_parsing? -> true or false
+ #
+ # Returns the value that determines whether illegal input is to be handled; used for parsing;
+ # see {Option +liberal_parsing+}[#class-CSV-label-Option+liberal_parsing]:
+ # CSV.new('').liberal_parsing? # => false
def liberal_parsing?
parser.liberal_parsing?
end
+ # :call-seq:
+ # csv.encoding -> endcoding
#
- # The Encoding CSV is parsing or writing in. This will be the Encoding you
- # receive parsed data in and/or the Encoding data will be written in.
- #
+ # Returns the encoding used for parsing and generating;
+ # see {Character Encodings (M17n or Multilingualization)}[#class-CSV-label-Character+Encodings+-28M17n+or+Multilingualization-29]:
+ # CSV.new('').encoding # => #<Encoding:UTF-8>
attr_reader :encoding
- #
- # The line number of the last row read from this file. Fields with nested
- # line-end characters will not affect this count.
- #
+ # :call-seq:
+ # csv.line_no -> integer
+ #
+ # Returns the count of the rows parsed or generated.
+ #
+ # Parsing:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ # CSV.open(path) do |csv|
+ # csv.each do |row|
+ # p [csv.lineno, row]
+ # end
+ # end
+ # Output:
+ # [1, ["foo", "0"]]
+ # [2, ["bar", "1"]]
+ # [3, ["baz", "2"]]
+ #
+ # Generating:
+ # CSV.generate do |csv|
+ # p csv.lineno; csv << ['foo', 0]
+ # p csv.lineno; csv << ['bar', 1]
+ # p csv.lineno; csv << ['baz', 2]
+ # end
+ # Output:
+ # 0
+ # 1
+ # 2
def lineno
if @writer
@writer.lineno
@@ -1141,9 +2018,22 @@ class CSV
end
end
- #
- # The last row read from this file.
- #
+ # :call-seq:
+ # csv.line -> array
+ #
+ # Returns the line most recently read:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ # CSV.open(path) do |csv|
+ # csv.each do |row|
+ # p [csv.lineno, csv.line]
+ # end
+ # end
+ # Output:
+ # [1, "foo,0\n"]
+ # [2, "bar,1\n"]
+ # [3, "baz,2\n"]
def line
parser.line
end
@@ -1219,13 +2109,56 @@ class CSV
### End Delegation ###
- #
- # The primary write method for wrapped Strings and IOs, +row+ (an Array or
- # CSV::Row) is converted to CSV and appended to the data source. When a
- # CSV::Row is passed, only the row's fields() are appended to the output.
- #
- # The data source must be open for writing.
- #
+ # :call-seq:
+ # csv << row -> self
+ #
+ # Appends a row to +self+.
+ #
+ # - Argument +row+ must be an \Array object or a CSV::Row object.
+ # - The output stream must be open for writing.
+ #
+ # ---
+ #
+ # Append Arrays:
+ # CSV.generate do |csv|
+ # csv << ['foo', 0]
+ # csv << ['bar', 1]
+ # csv << ['baz', 2]
+ # end # => "foo,0\nbar,1\nbaz,2\n"
+ #
+ # Append CSV::Rows:
+ # headers = []
+ # CSV.generate do |csv|
+ # csv << CSV::Row.new(headers, ['foo', 0])
+ # csv << CSV::Row.new(headers, ['bar', 1])
+ # csv << CSV::Row.new(headers, ['baz', 2])
+ # end # => "foo,0\nbar,1\nbaz,2\n"
+ #
+ # Headers in CSV::Row objects are not appended:
+ # headers = ['Name', 'Count']
+ # CSV.generate do |csv|
+ # csv << CSV::Row.new(headers, ['foo', 0])
+ # csv << CSV::Row.new(headers, ['bar', 1])
+ # csv << CSV::Row.new(headers, ['baz', 2])
+ # end # => "foo,0\nbar,1\nbaz,2\n"
+ #
+ # ---
+ #
+ # Raises an exception if +row+ is not an \Array or \CSV::Row:
+ # CSV.generate do |csv|
+ # # Raises NoMethodError (undefined method `collect' for :foo:Symbol)
+ # csv << :foo
+ # end
+ #
+ # Raises an exception if the output stream is not opened for writing:
+ # path = 't.csv'
+ # File.write(path, '')
+ # File.open(path) do |file|
+ # CSV.open(file) do |csv|
+ # # Raises IOError (not opened for writing)
+ # csv << ['foo', 0]
+ # end
+ # end
def <<(row)
writer << row
self
@@ -1233,58 +2166,216 @@ class CSV
alias_method :add_row, :<<
alias_method :puts, :<<
- #
# :call-seq:
- # convert( name )
- # convert { |field| ... }
- # convert { |field, field_info| ... }
- #
- # You can use this method to install a CSV::Converters built-in, or provide a
- # block that handles a custom conversion.
- #
- # If you provide a block that takes one argument, it will be passed the field
- # and is expected to return the converted value or the field itself. If your
- # block takes two arguments, it will also be passed a CSV::FieldInfo Struct,
- # containing details about the field. Again, the block should return a
- # converted field or the field itself.
- #
+ # convert(converter_name) -> array_of_procs
+ # convert {|field, field_info| ... } -> array_of_procs
+ #
+ # - With no block, installs a field converter (a \Proc).
+ # - With a block, defines and installs a custom field converter.
+ # - Returns the \Array of installed field converters.
+ #
+ # - Argument +converter_name+, if given, should be the name
+ # of an existing field converter.
+ #
+ # See {Field Converters}[#class-CSV-label-Field+Converters].
+ # ---
+ #
+ # With no block, installs a field converter:
+ # csv = CSV.new('')
+ # csv.convert(:integer)
+ # csv.convert(:float)
+ # csv.convert(:date)
+ # csv.converters # => [:integer, :float, :date]
+ #
+ # ---
+ #
+ # The block, if given, is called for each field:
+ # - Argument +field+ is the field value.
+ # - Argument +field_info+ is a CSV::FieldInfo object
+ # containing details about the field.
+ #
+ # The examples here assume the prior execution of:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ #
+ # Example giving a block:
+ # csv = CSV.open(path)
+ # csv.convert {|field, field_info| p [field, field_info]; field.upcase }
+ # csv.read # => [["FOO", "0"], ["BAR", "1"], ["BAZ", "2"]]
+ #
+ # Output:
+ # ["foo", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
+ # ["0", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
+ # ["bar", #<struct CSV::FieldInfo index=0, line=2, header=nil>]
+ # ["1", #<struct CSV::FieldInfo index=1, line=2, header=nil>]
+ # ["baz", #<struct CSV::FieldInfo index=0, line=3, header=nil>]
+ # ["2", #<struct CSV::FieldInfo index=1, line=3, header=nil>]
+ #
+ # The block need not return a \String object:
+ # csv = CSV.open(path)
+ # csv.convert {|field, field_info| field.to_sym }
+ # csv.read # => [[:foo, :"0"], [:bar, :"1"], [:baz, :"2"]]
+ #
+ # If +converter_name+ is given, the block is not called:
+ # csv = CSV.open(path)
+ # csv.convert(:integer) {|field, field_info| fail 'Cannot happen' }
+ # csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
+ #
+ # ---
+ #
+ # Raises a parse-time exception if +converter_name+ is not the name of a built-in
+ # field converter:
+ # csv = CSV.open(path)
+ # csv.convert(:nosuch) => [nil]
+ # # Raises NoMethodError (undefined method `arity' for nil:NilClass)
+ # csv.read
def convert(name = nil, &converter)
parser_fields_converter.add_converter(name, &converter)
end
- #
# :call-seq:
- # header_convert( name )
- # header_convert { |field| ... }
- # header_convert { |field, field_info| ... }
- #
- # Identical to CSV#convert(), but for header rows.
- #
- # Note that this method must be called before header rows are read to have any
- # effect.
- #
+ # header_convert(converter_name) -> array_of_procs
+ # header_convert {|header, field_info| ... } -> array_of_procs
+ #
+ # - With no block, installs a header converter (a \Proc).
+ # - With a block, defines and installs a custom header converter.
+ # - Returns the \Array of installed header converters.
+ #
+ # - Argument +converter_name+, if given, should be the name
+ # of an existing header converter.
+ #
+ # See {Header Converters}[#class-CSV-label-Header+Converters].
+ # ---
+ #
+ # With no block, installs a header converter:
+ # csv = CSV.new('')
+ # csv.header_convert(:symbol)
+ # csv.header_convert(:downcase)
+ # csv.header_converters # => [:symbol, :downcase]
+ #
+ # ---
+ #
+ # The block, if given, is called for each header:
+ # - Argument +header+ is the header value.
+ # - Argument +field_info+ is a CSV::FieldInfo object
+ # containing details about the header.
+ #
+ # The examples here assume the prior execution of:
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ #
+ # Example giving a block:
+ # csv = CSV.open(path, headers: true)
+ # csv.header_convert {|header, field_info| p [header, field_info]; header.upcase }
+ # table = csv.read
+ # table # => #<CSV::Table mode:col_or_row row_count:4>
+ # table.headers # => ["NAME", "VALUE"]
+ #
+ # Output:
+ # ["Name", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
+ # ["Value", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
+
+ # The block need not return a \String object:
+ # csv = CSV.open(path, headers: true)
+ # csv.header_convert {|header, field_info| header.to_sym }
+ # table = csv.read
+ # table.headers # => [:Name, :Value]
+ #
+ # If +converter_name+ is given, the block is not called:
+ # csv = CSV.open(path, headers: true)
+ # csv.header_convert(:downcase) {|header, field_info| fail 'Cannot happen' }
+ # table = csv.read
+ # table.headers # => ["name", "value"]
+ # ---
+ #
+ # Raises a parse-time exception if +converter_name+ is not the name of a built-in
+ # field converter:
+ # csv = CSV.open(path, headers: true)
+ # csv.header_convert(:nosuch)
+ # # Raises NoMethodError (undefined method `arity' for nil:NilClass)
+ # csv.read
def header_convert(name = nil, &converter)
header_fields_converter.add_converter(name, &converter)
end
include Enumerable
- #
- # Yields each row of the data source in turn.
- #
- # Support for Enumerable.
- #
- # The data source must be open for reading.
- #
+ # :call-seq:
+ # csv.each -> enumerator
+ # csv.each {|row| ...}
+ #
+ # Calls the block with each successive row.
+ # The data source must be opened for reading.
+ #
+ # Without headers:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string)
+ # csv.each do |row|
+ # p row
+ # end
+ # Output:
+ # ["foo", "0"]
+ # ["bar", "1"]
+ # ["baz", "2"]
+ #
+ # With headers:
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string, headers: true)
+ # csv.each do |row|
+ # p row
+ # end
+ # Output:
+ # <CSV::Row "Name":"foo" "Value":"0">
+ # <CSV::Row "Name":"bar" "Value":"1">
+ # <CSV::Row "Name":"baz" "Value":"2">
+ #
+ # ---
+ #
+ # Raises an exception if the source is not opened for reading:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string)
+ # csv.close
+ # # Raises IOError (not opened for reading)
+ # csv.each do |row|
+ # p row
+ # end
def each(&block)
parser_enumerator.each(&block)
end
- #
- # Slurps the remaining rows and returns an Array of Arrays.
- #
- # The data source must be open for reading.
- #
+ # :call-seq:
+ # csv.read -> array or csv_table
+ #
+ # Forms the remaining rows from +self+ into:
+ # - A CSV::Table object, if headers are in use.
+ # - An \Array of Arrays, otherwise.
+ #
+ # The data source must be opened for reading.
+ #
+ # Without headers:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ # csv = CSV.open(path)
+ # csv.read # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
+ #
+ # With headers:
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # path = 't.csv'
+ # File.write(path, string)
+ # csv = CSV.open(path, headers: true)
+ # csv.read # => #<CSV::Table mode:col_or_row row_count:4>
+ #
+ # ---
+ #
+ # Raises an exception if the source is not opened for reading:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string)
+ # csv.close
+ # # Raises IOError (not opened for reading)
+ # csv.read
def read
rows = to_a
if parser.use_headers?
@@ -1295,18 +2386,69 @@ class CSV
end
alias_method :readlines, :read
- # Returns +true+ if the next row read will be a header row.
+ # :call-seq:
+ # csv.header_row? -> true or false
+ #
+ # Returns +true+ if the next row to be read is a header row\;
+ # +false+ otherwise.
+ #
+ # Without headers:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string)
+ # csv.header_row? # => false
+ #
+ # With headers:
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string, headers: true)
+ # csv.header_row? # => true
+ # csv.shift # => #<CSV::Row "Name":"foo" "Value":"0">
+ # csv.header_row? # => false
+ #
+ # ---
+ #
+ # Raises an exception if the source is not opened for reading:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string)
+ # csv.close
+ # # Raises IOError (not opened for reading)
+ # csv.header_row?
def header_row?
parser.header_row?
end
- #
- # The primary read method for wrapped Strings and IOs, a single row is pulled
- # from the data source, parsed and returned as an Array of fields (if header
- # rows are not used) or a CSV::Row (when header rows are used).
- #
- # The data source must be open for reading.
- #
+ # :call-seq:
+ # csv.shift -> array, csv_row, or nil
+ #
+ # Returns the next row of data as:
+ # - An \Array if no headers are used.
+ # - A CSV::Row object if headers are used.
+ #
+ # The data source must be opened for reading.
+ #
+ # Without headers:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string)
+ # csv.shift # => ["foo", "0"]
+ # csv.shift # => ["bar", "1"]
+ # csv.shift # => ["baz", "2"]
+ # csv.shift # => nil
+ #
+ # With headers:
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string, headers: true)
+ # csv.shift # => #<CSV::Row "Name":"foo" "Value":"0">
+ # csv.shift # => #<CSV::Row "Name":"bar" "Value":"1">
+ # csv.shift # => #<CSV::Row "Name":"baz" "Value":"2">
+ # csv.shift # => nil
+ #
+ # ---
+ #
+ # Raises an exception if the source is not opened for reading:
+ # string = "foo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string)
+ # csv.close
+ # # Raises IOError (not opened for reading)
+ # csv.shift
def shift
if @eof_error
eof_error, @eof_error = @eof_error, nil
@@ -1321,10 +2463,14 @@ class CSV
alias_method :gets, :shift
alias_method :readline, :shift
+ # :call-seq:
+ # csv.inspect -> string
#
- # Returns a simplified description of the key CSV attributes in an
- # ASCII compatible String.
- #
+ # Returns a \String showing certain properties of +self+:
+ # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # csv = CSV.new(string, headers: true)
+ # s = csv.inspect
+ # s # => "#<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:\",\" row_sep:\"\\n\" quote_char:\"\\\"\" headers:true>"
def inspect
str = ["#<", self.class.to_s, " io_type:"]
# show type of wrapped IO
diff --git a/lib/csv/csv.gemspec b/lib/csv/csv.gemspec
index 98110bc13c..d0284728f7 100644
--- a/lib/csv/csv.gemspec
+++ b/lib/csv/csv.gemspec
@@ -16,27 +16,47 @@ Gem::Specification.new do |spec|
spec.summary = "CSV Reading and Writing"
spec.description = "The CSV library provides a complete interface to CSV files and data. It offers tools to enable you to read and write to and from Strings or IO objects, as needed."
spec.homepage = "https://github.com/ruby/csv"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = [
+ lib_path = "lib"
+ spec.require_paths = [lib_path]
+ files = []
+ lib_dir = File.join(__dir__, lib_path)
+ if File.exist?(lib_dir)
+ Dir.chdir(lib_dir) do
+ Dir.glob("**/*.rb").each do |file|
+ files << "lib/#{file}"
+ end
+ end
+ end
+ doc_dir = File.join(__dir__, "doc")
+ if File.exist?(doc_dir)
+ Dir.chdir(doc_dir) do
+ Dir.glob("**/*.rdoc").each do |rdoc_file|
+ files << "doc/#{rdoc_file}"
+ end
+ end
+ end
+ spec.files = files
+ spec.rdoc_options.concat(["--main", "README.md"])
+ rdoc_files = [
"LICENSE.txt",
"NEWS.md",
"README.md",
- "lib/csv.rb",
- "lib/csv/core_ext/array.rb",
- "lib/csv/core_ext/string.rb",
- "lib/csv/delete_suffix.rb",
- "lib/csv/fields_converter.rb",
- "lib/csv/match_p.rb",
- "lib/csv/parser.rb",
- "lib/csv/row.rb",
- "lib/csv/table.rb",
- "lib/csv/version.rb",
- "lib/csv/writer.rb",
]
- spec.require_paths = ["lib"]
- spec.required_ruby_version = ">= 2.3.0"
+ recipes_dir = File.join(doc_dir, "csv", "recipes")
+ if File.exist?(recipes_dir)
+ Dir.chdir(recipes_dir) do
+ Dir.glob("**/*.rdoc").each do |recipe_file|
+ rdoc_files << "doc/csv/recipes/#{recipe_file}"
+ end
+ end
+ end
+ spec.extra_rdoc_files = rdoc_files
+ spec.required_ruby_version = ">= 2.5.0"
+
+ # spec.add_dependency "stringio", ">= 0.1.3"
spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
spec.add_development_dependency "benchmark_driver"
diff --git a/lib/csv/fields_converter.rb b/lib/csv/fields_converter.rb
index a751c9ea1d..178ffb37bc 100644
--- a/lib/csv/fields_converter.rb
+++ b/lib/csv/fields_converter.rb
@@ -50,7 +50,7 @@ class CSV
fields.collect.with_index do |field, index|
if field.nil?
field = @nil_value
- elsif field.empty?
+ elsif field.is_a?(String) and field.empty?
field = @empty_value unless @empty_value_is_empty_string
end
@converters.each do |converter|
diff --git a/lib/csv/parser.rb b/lib/csv/parser.rb
index 42145f8923..2fb3b0a46e 100644
--- a/lib/csv/parser.rb
+++ b/lib/csv/parser.rb
@@ -446,6 +446,7 @@ class CSV
@strip = @options[:strip]
@escaped_strip = nil
@strip_value = nil
+ @rstrip_value = nil
if @strip.is_a?(String)
case @strip.length
when 0
@@ -460,6 +461,8 @@ class CSV
if @quote_character
@strip_value = Regexp.new(@escaped_strip +
"+".encode(@encoding))
+ @rstrip_value = Regexp.new(@escaped_strip +
+ "+\\z".encode(@encoding))
end
@need_robust_parsing = true
elsif @strip
@@ -467,6 +470,7 @@ class CSV
@escaped_strip = strip_values.encode(@encoding)
if @quote_character
@strip_value = Regexp.new("[#{strip_values}]+".encode(@encoding))
+ @rstrip_value = Regexp.new("[#{strip_values}]+\\z".encode(@encoding))
end
@need_robust_parsing = true
end
@@ -561,9 +565,6 @@ class CSV
unless @liberal_parsing
no_unquoted_values << @escaped_quote_character
end
- if @escaped_strip
- no_unquoted_values << @escaped_strip
- end
@unquoted_value = Regexp.new("[^".encode(@encoding) +
no_unquoted_values +
"]+".encode(@encoding))
@@ -707,7 +708,7 @@ class CSV
if SCANNER_TEST
class UnoptimizedStringIO
def initialize(string)
- @io = StringIO.new(string)
+ @io = StringIO.new(string, "rb:#{string.encoding}")
end
def gets(*args)
@@ -769,7 +770,7 @@ class CSV
def skip_needless_lines
return unless @skip_lines
- while true
+ until @scanner.eos?
@scanner.keep_start
line = @scanner.scan_all(@not_line_end) || "".encode(@encoding)
line << @row_separator if parse_row_end
@@ -784,6 +785,7 @@ class CSV
end
def skip_line?(line)
+ line = line.delete_suffix(@row_separator)
case @skip_lines
when String
line.include?(@skip_lines)
@@ -939,6 +941,7 @@ class CSV
if @liberal_parsing
quoted_value = parse_quoted_column_value
if quoted_value
+ @scanner.scan_all(@strip_value) if @strip_value
unquoted_value = parse_unquoted_column_value
if unquoted_value
if @double_quote_outside_quote
@@ -986,6 +989,9 @@ class CSV
end
end
value.gsub!(@backslash_quote_character, @quote_character) if @backslash_quote
+ if @rstrip_value
+ value.gsub!(@rstrip_value, "")
+ end
value
end
diff --git a/lib/csv/row.rb b/lib/csv/row.rb
index 4aa0f30911..0f465ea2a3 100644
--- a/lib/csv/row.rb
+++ b/lib/csv/row.rb
@@ -49,42 +49,82 @@ class CSV
def_delegators :@row, :empty?, :length, :size
def initialize_copy(other)
- super
- @row = @row.dup
+ super_return_value = super
+ @row = @row.collect(&:dup)
+ super_return_value
end
- # Returns +true+ if this is a header row.
+ # :call-seq:
+ # row.header_row? -> true or false
+ #
+ # Returns +true+ if this is a header row, +false+ otherwise.
def header_row?
@header_row
end
- # Returns +true+ if this is a field row.
+ # :call-seq:
+ # row.field_row? -> true or false
+ #
+ # Returns +true+ if this is a field row, +false+ otherwise.
def field_row?
not header_row?
end
- # Returns the headers of this row.
+ # :call-seq:
+ # row.headers
+ #
+ # Returns the headers for this row:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table.first
+ # row.headers # => ["Name", "Value"]
def headers
@row.map(&:first)
end
- #
# :call-seq:
- # field( header )
- # field( header, offset )
- # field( index )
+ # field(index)
+ # field(header)
+ # field(header, offset)
+ #
+ # Returns the field value for the given +index+ or +header+.
+ #
+ # ---
+ #
+ # Fetch field value by \Integer index:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.field(0) # => "foo"
+ # row.field(1) # => "bar"
+ #
+ # Counts backward from the last column if +index+ is negative:
+ # row.field(-1) # => "0"
+ # row.field(-2) # => "foo"
+ #
+ # Returns +nil+ if +index+ is out of range:
+ # row.field(2) # => nil
+ # row.field(-3) # => nil
+ #
+ # ---
#
- # This method will return the field value by +header+ or +index+. If a field
- # is not found, +nil+ is returned.
+ # Fetch field value by header (first found):
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.field('Name') # => "Foo"
#
- # When provided, +offset+ ensures that a header match occurs on or later
- # than the +offset+ index. You can use this to find duplicate headers,
- # without resorting to hard-coding exact indices.
+ # Fetch field value by header, ignoring +offset+ leading fields:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.field('Name', 2) # => "Baz"
#
+ # Returns +nil+ if the header does not exist.
def field(header_or_index, minimum_index = 0)
# locate the pair
finder = (header_or_index.is_a?(Integer) || header_or_index.is_a?(Range)) ? :[] : :assoc
- pair = @row[minimum_index..-1].send(finder, header_or_index)
+ pair = @row[minimum_index..-1].public_send(finder, header_or_index)
# return the field if we have a pair
if pair.nil?
@@ -97,16 +137,45 @@ class CSV
#
# :call-seq:
- # fetch( header )
- # fetch( header ) { |row| ... }
- # fetch( header, default )
- #
- # This method will fetch the field value by +header+. It has the same
- # behavior as Hash#fetch: if there is a field with the given +header+, its
- # value is returned. Otherwise, if a block is given, it is yielded the
- # +header+ and its result is returned; if a +default+ is given as the
- # second argument, it is returned; otherwise a KeyError is raised.
- #
+ # fetch(header)
+ # fetch(header, default)
+ # fetch(header) {|row| ... }
+ #
+ # Returns the field value as specified by +header+.
+ #
+ # ---
+ #
+ # With the single argument +header+, returns the field value
+ # for that header (first found):
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.fetch('Name') # => "Foo"
+ #
+ # Raises exception +KeyError+ if the header does not exist.
+ #
+ # ---
+ #
+ # With arguments +header+ and +default+ given,
+ # returns the field value for the header (first found)
+ # if the header exists, otherwise returns +default+:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.fetch('Name', '') # => "Foo"
+ # row.fetch(:nosuch, '') # => ""
+ #
+ # ---
+ #
+ # With argument +header+ and a block given,
+ # returns the field value for the header (first found)
+ # if the header exists; otherwise calls the block
+ # and returns its return value:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.fetch('Name') {|header| fail 'Cannot happen' } # => "Foo"
+ # row.fetch(:nosuch) {|header| "Header '#{header} not found'" } # => "Header 'nosuch not found'"
def fetch(header, *varargs)
raise ArgumentError, "Too many arguments" if varargs.length > 1
pair = @row.assoc(header)
@@ -123,7 +192,11 @@ class CSV
end
end
- # Returns +true+ if there is a field with the given +header+.
+ # :call-seq:
+ # row.has_key?(header)
+ #
+ # Returns +true+ if there is a field with the given +header+,
+ # +false+ otherwise.
def has_key?(header)
!!@row.assoc(header)
end
@@ -134,17 +207,56 @@ class CSV
#
# :call-seq:
- # []=( header, value )
- # []=( header, offset, value )
- # []=( index, value )
- #
- # Looks up the field by the semantics described in CSV::Row.field() and
- # assigns the +value+.
- #
- # Assigning past the end of the row with an index will set all pairs between
- # to <tt>[nil, nil]</tt>. Assigning to an unused header appends the new
- # pair.
- #
+ # row[index] = value -> value
+ # row[header, offset] = value -> value
+ # row[header] = value -> value
+ #
+ # Assigns the field value for the given +index+ or +header+;
+ # returns +value+.
+ #
+ # ---
+ #
+ # Assign field value by \Integer index:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row[0] = 'Bat'
+ # row[1] = 3
+ # row # => #<CSV::Row "Name":"Bat" "Value":3>
+ #
+ # Counts backward from the last column if +index+ is negative:
+ # row[-1] = 4
+ # row[-2] = 'Bam'
+ # row # => #<CSV::Row "Name":"Bam" "Value":4>
+ #
+ # Extends the row with <tt>nil:nil</tt> if positive +index+ is not in the row:
+ # row[4] = 5
+ # row # => #<CSV::Row "Name":"bad" "Value":4 nil:nil nil:nil nil:5>
+ #
+ # Raises IndexError if negative +index+ is too small (too far from zero).
+ #
+ # ---
+ #
+ # Assign field value by header (first found):
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row['Name'] = 'Bat'
+ # row # => #<CSV::Row "Name":"Bat" "Name":"Bar" "Name":"Baz">
+ #
+ # Assign field value by header, ignoring +offset+ leading fields:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row['Name', 2] = 4
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":4>
+ #
+ # Append new field by (new) header:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row['New'] = 6
+ # row# => #<CSV::Row "Name":"foo" "Value":"0" "New":6>
def []=(*args)
value = args.pop
@@ -167,17 +279,34 @@ class CSV
#
# :call-seq:
- # <<( field )
- # <<( header_and_field_array )
- # <<( header_and_field_hash )
- #
- # If a two-element Array is provided, it is assumed to be a header and field
- # and the pair is appended. A Hash works the same way with the key being
- # the header and the value being the field. Anything else is assumed to be
- # a lone field which is appended with a +nil+ header.
- #
- # This method returns the row for chaining.
- #
+ # row << [header, value] -> self
+ # row << hash -> self
+ # row << value -> self
+ #
+ # Adds a field to +self+; returns +self+:
+ #
+ # If the argument is a 2-element \Array <tt>[header, value]</tt>,
+ # a field is added with the given +header+ and +value+:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row << ['NAME', 'Bat']
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" "NAME":"Bat">
+ #
+ # If the argument is a \Hash, each <tt>key-value</tt> pair is added
+ # as a field with header +key+ and value +value+.
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row << {NAME: 'Bat', name: 'Bam'}
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" NAME:"Bat" name:"Bam">
+ #
+ # Otherwise, the given +value+ is added as a field with no header.
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row << 'Bag'
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bag">
def <<(arg)
if arg.is_a?(Array) and arg.size == 2 # appending a header and name
@row << arg
@@ -190,13 +319,15 @@ class CSV
self # for chaining
end
- #
- # A shortcut for appending multiple fields. Equivalent to:
- #
- # args.each { |arg| csv_row << arg }
- #
- # This method returns the row for chaining.
- #
+ # :call-seq:
+ # row.push(*values) ->self
+ #
+ # Appends each of the given +values+ to +self+ as a field; returns +self+:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.push('Bat', 'Bam')
+ # row # => #<CSV::Row "Name":"Foo" "Name":"Bar" "Name":"Baz" nil:"Bat" nil:"Bam">
def push(*args)
args.each { |arg| self << arg }
@@ -205,14 +336,39 @@ class CSV
#
# :call-seq:
- # delete( header )
- # delete( header, offset )
- # delete( index )
- #
- # Removes a pair from the row by +header+ or +index+. The pair is
- # located as described in CSV::Row.field(). The deleted pair is returned,
- # or +nil+ if a pair could not be found.
- #
+ # delete(index) -> [header, value] or nil
+ # delete(header) -> [header, value] or empty_array
+ # delete(header, offset) -> [header, value] or empty_array
+ #
+ # Removes a specified field from +self+; returns the 2-element \Array
+ # <tt>[header, value]</tt> if the field exists.
+ #
+ # If an \Integer argument +index+ is given,
+ # removes and returns the field at offset +index+,
+ # or returns +nil+ if the field does not exist:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.delete(1) # => ["Name", "Bar"]
+ # row.delete(50) # => nil
+ #
+ # Otherwise, if the single argument +header+ is given,
+ # removes and returns the first-found field with the given header,
+ # of returns a new empty \Array if the field does not exist:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.delete('Name') # => ["Name", "Foo"]
+ # row.delete('NAME') # => []
+ #
+ # If argument +header+ and \Integer argument +offset+ are given,
+ # removes and returns the first-found field with the given header
+ # whose +index+ is at least as large as +offset+:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.delete('Name', 1) # => ["Name", "Bar"]
+ # row.delete('NAME', 1) # => []
def delete(header_or_index, minimum_index = 0)
if header_or_index.is_a? Integer # by index
@row.delete_at(header_or_index)
@@ -223,15 +379,21 @@ class CSV
end
end
+ # :call-seq:
+ # row.delete_if {|header, value| ... } -> self
#
- # The provided +block+ is passed a header and field for each pair in the row
- # and expected to return +true+ or +false+, depending on whether the pair
- # should be deleted.
- #
- # This method returns the row for chaining.
+ # Removes fields from +self+ as selected by the block; returns +self+.
#
- # If no block is given, an Enumerator is returned.
+ # Removes each field for which the block returns a truthy value:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.delete_if {|header, value| value.start_with?('B') } # => true
+ # row # => #<CSV::Row "Name":"Foo">
+ # row.delete_if {|header, value| header.start_with?('B') } # => false
#
+ # If no block is given, returns a new Enumerator:
+ # row.delete_if # => #<Enumerator: #<CSV::Row "Name":"Foo">:delete_if>
def delete_if(&block)
return enum_for(__method__) { size } unless block_given?
@@ -240,14 +402,52 @@ class CSV
self # for chaining
end
- #
- # This method accepts any number of arguments which can be headers, indices,
- # Ranges of either, or two-element Arrays containing a header and offset.
- # Each argument will be replaced with a field lookup as described in
- # CSV::Row.field().
- #
- # If called with no arguments, all fields are returned.
- #
+ # :call-seq:
+ # self.fields(*specifiers)
+ #
+ # Returns field values per the given +specifiers+, which may be any mixture of:
+ # - \Integer index.
+ # - \Range of \Integer indexes.
+ # - 2-element \Array containing a header and offset.
+ # - Header.
+ # - \Range of headers.
+ #
+ # For +specifier+ in one of the first four cases above,
+ # returns the result of <tt>self.field(specifier)</tt>; see #field.
+ #
+ # Although there may be any number of +specifiers+,
+ # the examples here will illustrate one at a time.
+ #
+ # When the specifier is an \Integer +index+,
+ # returns <tt>self.field(index)</tt>L
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.fields(1) # => ["Bar"]
+ #
+ # When the specifier is a \Range of \Integers +range+,
+ # returns <tt>self.field(range)</tt>:
+ # row.fields(1..2) # => ["Bar", "Baz"]
+ #
+ # When the specifier is a 2-element \Array +array+,
+ # returns <tt>self.field(array)</tt>L
+ # row.fields('Name', 1) # => ["Foo", "Bar"]
+ #
+ # When the specifier is a header +header+,
+ # returns <tt>self.field(header)</tt>L
+ # row.fields('Name') # => ["Foo"]
+ #
+ # When the specifier is a \Range of headers +range+,
+ # forms a new \Range +new_range+ from the indexes of
+ # <tt>range.start</tt> and <tt>range.end</tt>,
+ # and returns <tt>self.field(new_range)</tt>:
+ # source = "Name,NAME,name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.fields('Name'..'NAME') # => ["Foo", "Bar"]
+ #
+ # Returns all fields if no argument given:
+ # row.fields # => ["Foo", "Bar", "Baz"]
def fields(*headers_and_or_indices)
if headers_and_or_indices.empty? # return all fields--no arguments
@row.map(&:last)
@@ -324,10 +524,21 @@ class CSV
@row == other
end
- #
- # Collapses the row into a simple Hash. Be warned that this discards field
- # order and clobbers duplicate fields.
- #
+ # :call-seq:
+ # row.to_h -> hash
+ #
+ # Returns the new \Hash formed by adding each header-value pair in +self+
+ # as a key-value pair in the \Hash.
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.to_h # => {"Name"=>"foo", "Value"=>"0"}
+ #
+ # Header order is preserved, but repeated headers are ignored:
+ # source = "Name,Name,Name\nFoo,Bar,Baz\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.to_h # => {"Name"=>"Foo"}
def to_h
hash = {}
each do |key, _value|
@@ -339,20 +550,35 @@ class CSV
alias_method :to_ary, :to_a
+ # :call-seq:
+ # row.to_csv -> csv_string
#
- # Returns the row as a CSV String. Headers are not used. Equivalent to:
- #
- # csv_row.fields.to_csv( options )
- #
+ # Returns the row as a \CSV String. Headers are not included:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.to_csv # => "foo,0\n"
def to_csv(**options)
fields.to_csv(**options)
end
alias_method :to_s, :to_csv
+ # :call-seq:
+ # row.dig(index_or_header, *identifiers) -> object
+ #
+ # Finds and returns the object in nested object that is specified
+ # by +index_or_header+ and +specifiers+.
#
- # Extracts the nested value specified by the sequence of +index+ or +header+ objects by calling dig at each step,
- # returning nil if any intermediate step is nil.
+ # The nested objects may be instances of various classes.
+ # See {Dig Methods}[https://docs.ruby-lang.org/en/master/doc/dig_methods_rdoc.html].
#
+ # Examples:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.dig(1) # => "0"
+ # row.dig('Value') # => "0"
+ # row.dig(5) # => nil
def dig(index_or_header, *indexes)
value = field(index_or_header)
if value.nil?
@@ -367,9 +593,17 @@ class CSV
end
end
- #
- # A summary of fields, by header, in an ASCII compatible String.
- #
+ # :call-seq:
+ # row.inspect -> string
+ #
+ # Returns an ASCII-compatible \String showing:
+ # - Class \CSV::Row.
+ # - Header-value pairs.
+ # Example:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # row = table[0]
+ # row.inspect # => "#<CSV::Row \"Name\":\"foo\" \"Value\":\"0\">"
def inspect
str = ["#<", self.class.to_s]
each do |header, field|
diff --git a/lib/csv/table.rb b/lib/csv/table.rb
index e6c1ee11fa..1ce0dd6daf 100644
--- a/lib/csv/table.rb
+++ b/lib/csv/table.rb
@@ -144,14 +144,91 @@ class CSV
end
end
- #
- # In the default mixed mode, this method returns rows for index access and
- # columns for header access. You can force the index association by first
- # calling by_col!() or by_row!().
- #
- # Columns are returned as an Array of values. Altering that Array has no
- # effect on the table.
- #
+ # :call-seq:
+ # table[n] -> row
+ # table[range] -> array_of_rows
+ # table[header] -> array_of_fields
+ #
+ # Returns data from the table; does not modify the table.
+ #
+ # ---
+ #
+ # The expression <tt>table[n]</tt>, where +n+ is a non-negative \Integer,
+ # returns the +n+th row of the table, if that row exists,
+ # and if the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
+ # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
+ # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
+ # table[1] # => #<CSV::Row "Name":"bar" "Value":"1">
+ #
+ # Counts backward from the last row if +n+ is negative:
+ # table[-1] # => #<CSV::Row "Name":"baz" "Value":"2">
+ #
+ # Returns +nil+ if +n+ is too large or too small:
+ # table[4] # => nil
+ # table[-4] => nil
+ #
+ # Raises an exception if the access mode is <tt>:row</tt>
+ # and +n+ is not an
+ # {Integer-convertible object}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Integer-Convertible+Objects].
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
+ # # Raises TypeError (no implicit conversion of String into Integer):
+ # table['Name']
+ #
+ # ---
+ #
+ # The expression <tt>table[range]</tt>, where +range+ is a Range object,
+ # returns rows from the table, beginning at row <tt>range.first</tt>,
+ # if those rows exist, and if the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
+ # rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1">
+ # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
+ # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
+ # rows = table[1..2] # => #<CSV::Row "Name":"bar" "Value":"1">
+ # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
+ #
+ # If there are too few rows, returns all from <tt>range.first</tt> to the end:
+ # rows = table[1..50] # => #<CSV::Row "Name":"bar" "Value":"1">
+ # rows # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
+ #
+ # Special case: if <tt>range.start == table.size</tt>, returns an empty \Array:
+ # table[table.size..50] # => []
+ #
+ # If <tt>range.end</tt> is negative, calculates the ending index from the end:
+ # rows = table[0..-1]
+ # rows # => [#<CSV::Row "Name":"foo" "Value":"0">, #<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
+ #
+ # If <tt>range.start</tt> is negative, calculates the starting index from the end:
+ # rows = table[-1..2]
+ # rows # => [#<CSV::Row "Name":"baz" "Value":"2">]
+ #
+ # If <tt>range.start</tt> is larger than <tt>table.size</tt>, returns +nil+:
+ # table[4..4] # => nil
+ #
+ # ---
+ #
+ # The expression <tt>table[header]</tt>, where +header+ is a \String,
+ # returns column values (\Array of \Strings) if the column exists
+ # and if the access mode is <tt>:col</tt> or <tt>:col_or_row</tt>:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
+ # table['Name'] # => ["foo", "bar", "baz"]
+ # table.by_col_or_row! # => #<CSV::Table mode:col_or_row row_count:4>
+ # col = table['Name']
+ # col # => ["foo", "bar", "baz"]
+ #
+ # Modifying the returned column values does not modify the table:
+ # col[0] = 'bat'
+ # col # => ["bat", "bar", "baz"]
+ # table['Name'] # => ["foo", "bar", "baz"]
+ #
+ # Returns an \Array of +nil+ values if there is no such column:
+ # table['Nosuch'] # => [nil, nil, nil]
def [](index_or_header)
if @mode == :row or # by index
(@mode == :col_or_row and (index_or_header.is_a?(Integer) or index_or_header.is_a?(Range)))
@@ -210,15 +287,58 @@ class CSV
end
end
- #
- # The mixed mode default is to treat a list of indices as row access,
- # returning the rows indicated. Anything else is considered columnar
- # access. For columnar access, the return set has an Array for each row
- # with the values indicated by the headers in each Array. You can force
- # column or row mode using by_col!() or by_row!().
- #
- # You cannot mix column and row access.
- #
+ # :call-seq:
+ # table.values_at(*indexes) -> array_of_rows
+ # table.values_at(*headers) -> array_of_columns_data
+ #
+ # If the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>,
+ # and each argument is either an \Integer or a \Range,
+ # returns rows.
+ # Otherwise, returns columns data.
+ #
+ # In either case, the returned values are in the order
+ # specified by the arguments. Arguments may be repeated.
+ #
+ # ---
+ #
+ # Returns rows as an \Array of \CSV::Row objects.
+ #
+ # No argument:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.values_at # => []
+ #
+ # One index:
+ # values = table.values_at(0)
+ # values # => [#<CSV::Row "Name":"foo" "Value":"0">]
+ #
+ # Two indexes:
+ # values = table.values_at(2, 0)
+ # values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
+ #
+ # One \Range:
+ # values = table.values_at(1..2)
+ # values # => [#<CSV::Row "Name":"bar" "Value":"1">, #<CSV::Row "Name":"baz" "Value":"2">]
+ #
+ # \Ranges and indexes:
+ # values = table.values_at(0..1, 1..2, 0, 2)
+ # pp values
+ # Output:
+ # [#<CSV::Row "Name":"foo" "Value":"0">,
+ # #<CSV::Row "Name":"bar" "Value":"1">,
+ # #<CSV::Row "Name":"bar" "Value":"1">,
+ # #<CSV::Row "Name":"baz" "Value":"2">,
+ # #<CSV::Row "Name":"foo" "Value":"0">,
+ # #<CSV::Row "Name":"baz" "Value":"2">]
+ #
+ # ---
+ #
+ # Returns columns data as row Arrays,
+ # each consisting of the specified columns data for that row:
+ # values = table.values_at('Name')
+ # values # => [["foo"], ["bar"], ["baz"]]
+ # values = table.values_at('Value', 'Name')
+ # values # => [["0", "foo"], ["1", "bar"], ["2", "baz"]]
def values_at(*indices_or_headers)
if @mode == :row or # by indices
( @mode == :col_or_row and indices_or_headers.all? do |index|
@@ -233,13 +353,20 @@ class CSV
end
end
+ # :call-seq:
+ # table << row_or_array -> self
#
- # Adds a new row to the bottom end of this table. You can provide an Array,
- # which will be converted to a CSV::Row (inheriting the table's headers()),
- # or a CSV::Row.
- #
- # This method returns the table for chaining.
+ # If +row_or_array+ is a \CSV::Row object,
+ # it is appended to the table:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table << CSV::Row.new(table.headers, ['bat', 3])
+ # table[3] # => #<CSV::Row "Name":"bat" "Value":3>
#
+ # If +row_or_array+ is an \Array, it is used to create a new
+ # \CSV::Row object which is then appended to the table:
+ # table << ['bam', 4]
+ # table[4] # => #<CSV::Row "Name":"bam" "Value":4>
def <<(row_or_array)
if row_or_array.is_a? Array # append Array
@table << Row.new(headers, row_or_array)
@@ -251,23 +378,67 @@ class CSV
end
#
- # A shortcut for appending multiple rows. Equivalent to:
- #
- # rows.each { |row| self << row }
- #
- # This method returns the table for chaining.
+ # :call-seq:
+ # table.push(*rows_or_arrays) -> self
#
+ # A shortcut for appending multiple rows. Equivalent to:
+ # rows.each {|row| self << row }
+ #
+ # Each argument may be either a \CSV::Row object or an \Array:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # rows = [
+ # CSV::Row.new(table.headers, ['bat', 3]),
+ # ['bam', 4]
+ # ]
+ # table.push(*rows)
+ # table[3..4] # => [#<CSV::Row "Name":"bat" "Value":3>, #<CSV::Row "Name":"bam" "Value":4>]
def push(*rows)
rows.each { |row| self << row }
self # for chaining
end
+ # :call-seq:
+ # table.delete(*indexes) -> deleted_values
+ # table.delete(*headers) -> deleted_values
+ #
+ # If the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>,
+ # and each argument is either an \Integer or a \Range,
+ # returns deleted rows.
+ # Otherwise, returns deleted columns data.
+ #
+ # In either case, the returned values are in the order
+ # specified by the arguments. Arguments may be repeated.
+ #
+ # ---
+ #
+ # Returns rows as an \Array of \CSV::Row objects.
#
- # Removes and returns the indicated columns or rows. In the default mixed
- # mode indices refer to rows and everything else is assumed to be a column
- # headers. Use by_col!() or by_row!() to force the lookup.
+ # One index:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # deleted_values = table.delete(0)
+ # deleted_values # => [#<CSV::Row "Name":"foo" "Value":"0">]
#
+ # Two indexes:
+ # table = CSV.parse(source, headers: true)
+ # deleted_values = table.delete(2, 0)
+ # deleted_values # => [#<CSV::Row "Name":"baz" "Value":"2">, #<CSV::Row "Name":"foo" "Value":"0">]
+ #
+ # ---
+ #
+ # Returns columns data as column Arrays.
+ #
+ # One header:
+ # table = CSV.parse(source, headers: true)
+ # deleted_values = table.delete('Name')
+ # deleted_values # => ["foo", "bar", "baz"]
+ #
+ # Two headers:
+ # table = CSV.parse(source, headers: true)
+ # deleted_values = table.delete('Value', 'Name')
+ # deleted_values # => [["0", "1", "2"], ["foo", "bar", "baz"]]
def delete(*indexes_or_headers)
if indexes_or_headers.empty?
raise ArgumentError, "wrong number of arguments (given 0, expected 1+)"
@@ -292,16 +463,32 @@ class CSV
end
end
- #
- # Removes any column or row for which the block returns +true+. In the
- # default mixed mode or row mode, iteration is the standard row major
- # walking of rows. In column mode, iteration will +yield+ two element
- # tuples containing the column name and an Array of values for that column.
- #
- # This method returns the table for chaining.
- #
- # If no block is given, an Enumerator is returned.
- #
+ # Removes rows or columns for which the block returns a truthy value;
+ # returns +self+.
+ #
+ # Removes rows when the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>;
+ # calls the block with each \CSV::Row object:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
+ # table.size # => 3
+ # table.delete_if {|row| row['Name'].start_with?('b') }
+ # table.size # => 1
+ #
+ # Removes columns when the access mode is <tt>:col</tt>;
+ # calls the block with each column as a 2-element array
+ # containing the header and an \Array of column fields:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
+ # table.headers.size # => 2
+ # table.delete_if {|column_data| column_data[1].include?('2') }
+ # table.headers.size # => 1
+ #
+ # Returns a new \Enumerator if no block is given:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.delete_if # => #<Enumerator: #<CSV::Table mode:col_or_row row_count:4>:delete_if>
def delete_if(&block)
return enum_for(__method__) { @mode == :row or @mode == :col_or_row ? size : headers.size } unless block_given?
@@ -319,15 +506,30 @@ class CSV
include Enumerable
- #
- # In the default mixed mode or row mode, iteration is the standard row major
- # walking of rows. In column mode, iteration will +yield+ two element
- # tuples containing the column name and an Array of values for that column.
- #
- # This method returns the table for chaining.
- #
- # If no block is given, an Enumerator is returned.
- #
+ # Calls the block with each row or column; returns +self+.
+ #
+ # When the access mode is <tt>:row</tt> or <tt>:col_or_row</tt>,
+ # calls the block with each \CSV::Row object:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # table.by_row! # => #<CSV::Table mode:row row_count:4>
+ # table.each {|row| p row }
+ # Output:
+ # #<CSV::Row "Name":"foo" "Value":"0">
+ # #<CSV::Row "Name":"bar" "Value":"1">
+ # #<CSV::Row "Name":"baz" "Value":"2">
+ #
+ # When the access mode is <tt>:col</tt>,
+ # calls the block with each column as a 2-element array
+ # containing the header and an \Array of column fields:
+ # table.by_col! # => #<CSV::Table mode:col row_count:4>
+ # table.each {|column_data| p column_data }
+ # Output:
+ # ["Name", ["foo", "bar", "baz"]]
+ # ["Value", ["0", "1", "2"]]
+ #
+ # Returns a new \Enumerator if no block is given:
+ # table.each # => #<Enumerator: #<CSV::Table mode:col row_count:4>:each>
def each(&block)
return enum_for(__method__) { @mode == :col ? headers.size : size } unless block_given?
@@ -340,7 +542,24 @@ class CSV
self # for chaining
end
- # Returns +true+ if all rows of this table ==() +other+'s rows.
+ # Returns +true+ if all each row of +self+ <tt>==</tt>
+ # the corresponding row of +other_table+, otherwise, +false+.
+ #
+ # The access mode does no affect the result.
+ #
+ # Equal tables:
+ # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
+ # table = CSV.parse(source, headers: true)
+ # other_table = CSV.parse(source, headers: true)
+ # table == other_table # => true
+ #
+ # Different row count:
+ # other_table.delete(2)
+ # table == other_table # => false
+ #
+ # Different last row:
+ # other_table << ['bat', 3]
+ # table == other_table # => false
def ==(other)
return @table == other.table if other.is_a? CSV::Table
@table == other
diff --git a/lib/csv/version.rb b/lib/csv/version.rb
index 072400fe01..51dc8433f3 100644
--- a/lib/csv/version.rb
+++ b/lib/csv/version.rb
@@ -2,5 +2,5 @@
class CSV
# The version of the installed library.
- VERSION = "3.1.2"
+ VERSION = "3.1.9"
end
diff --git a/lib/csv/writer.rb b/lib/csv/writer.rb
index 9243d23641..d49115fccf 100644
--- a/lib/csv/writer.rb
+++ b/lib/csv/writer.rb
@@ -43,8 +43,10 @@ class CSV
row = @fields_converter.convert(row, nil, lineno) if @fields_converter
+ i = -1
converted_row = row.collect do |field|
- quote(field)
+ i += 1
+ quote(field, i)
end
line = converted_row.join(@column_separator) + @row_separator
if @output_encoding
@@ -100,6 +102,33 @@ class CSV
end
end
+ def prepare_force_quotes_fields(force_quotes)
+ @force_quotes_fields = {}
+ force_quotes.each do |name_or_index|
+ case name_or_index
+ when Integer
+ index = name_or_index
+ @force_quotes_fields[index] = true
+ when String, Symbol
+ name = name_or_index.to_s
+ if @headers.nil?
+ message = ":headers is required when you use field name " +
+ "in :force_quotes: " +
+ "#{name_or_index.inspect}: #{force_quotes.inspect}"
+ raise ArgumentError, message
+ end
+ index = @headers.index(name)
+ next if index.nil?
+ @force_quotes_fields[index] = true
+ else
+ message = ":force_quotes element must be " +
+ "field index or field name: " +
+ "#{name_or_index.inspect}: #{force_quotes.inspect}"
+ raise ArgumentError, message
+ end
+ end
+ end
+
def prepare_format
@column_separator = @options[:column_separator].to_s.encode(@encoding)
row_separator = @options[:row_separator]
@@ -109,7 +138,17 @@ class CSV
@row_separator = row_separator.to_s.encode(@encoding)
end
@quote_character = @options[:quote_character]
- @force_quotes = @options[:force_quotes]
+ force_quotes = @options[:force_quotes]
+ if force_quotes.is_a?(Array)
+ prepare_force_quotes_fields(force_quotes)
+ @force_quotes = false
+ elsif force_quotes
+ @force_quotes_fields = nil
+ @force_quotes = true
+ else
+ @force_quotes_fields = nil
+ @force_quotes = false
+ end
unless @force_quotes
@quotable_pattern =
Regexp.new("[\r\n".encode(@encoding) +
@@ -147,16 +186,18 @@ class CSV
encoded_quote_character
end
- def quote(field)
+ def quote(field, i)
if @force_quotes
quote_field(field)
+ elsif @force_quotes_fields and @force_quotes_fields[i]
+ quote_field(field)
else
if field.nil? # represent +nil+ fields as empty unquoted fields
""
else
field = String(field) # Stringify fields
# represent empty fields as empty quoted fields
- if (@quote_empty and field.empty?) or @quotable_pattern.match?(field)
+ if (@quote_empty and field.empty?) or (field.valid_encoding? and @quotable_pattern.match?(field))
quote_field(field)
else
field # unquoted field
diff --git a/lib/debug.gemspec b/lib/debug.gemspec
new file mode 100644
index 0000000000..0c414d4827
--- /dev/null
+++ b/lib/debug.gemspec
@@ -0,0 +1,22 @@
+Gem::Specification.new do |spec|
+ spec.name = "debug"
+ spec.version = "0.2.1"
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{Debugging functionality for Ruby}
+ spec.description = %q{Debugging functionality for Ruby}
+ spec.homepage = "https://github.com/ruby/debug"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = []
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/debug.rb b/lib/debug.rb
index 6f519c6c77..bf63ccf34d 100644
--- a/lib/debug.rb
+++ b/lib/debug.rb
@@ -3,7 +3,10 @@
# Copyright (C) 2000 Information-technology Promotion Agency, Japan
# Copyright (C) 2000-2003 NAKAMURA, Hiroshi <nahi@ruby-lang.org>
-require 'continuation'
+if $SAFE > 0
+ STDERR.print "-r debug.rb is not available in safe mode\n"
+ exit 1
+end
require 'tracer'
require 'pp'
@@ -178,6 +181,9 @@ SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__ # :nodoc:
class DEBUGGER__
MUTEX = Thread::Mutex.new # :nodoc:
+ CONTINUATIONS_SUPPORTED = RUBY_ENGINE == 'ruby'
+
+ require 'continuation' if CONTINUATIONS_SUPPORTED
class Context # :nodoc:
DEBUG_LAST_CMD = []
@@ -375,8 +381,10 @@ class DEBUGGER__
def debug_command(file, line, id, binding)
MUTEX.lock
- unless defined?($debugger_restart) and $debugger_restart
- callcc{|c| $debugger_restart = c}
+ if CONTINUATIONS_SUPPORTED
+ unless defined?($debugger_restart) and $debugger_restart
+ callcc{|c| $debugger_restart = c}
+ end
end
set_last_thread(Thread.current)
frame_pos = 0
@@ -648,7 +656,11 @@ class DEBUGGER__
stdout.printf "%s\n", debug_eval($', binding).inspect
when /^\s*r(?:estart)?$/
- $debugger_restart.call
+ if CONTINUATIONS_SUPPORTED
+ $debugger_restart.call
+ else
+ stdout.print "Restart requires continuations.\n"
+ end
when /^\s*h(?:elp)?$/
debug_print_help()
@@ -1012,8 +1024,8 @@ EOHELP
#
# (rdb:1) DEBUGGER__.thread_list_all
# +1 #<Thread:0x007fb2320c03f0 run> debug_me.rb.rb:3
- # 2 #<Thread:0x007fb23218a538@debug_me.rb.rb:3 sleep>
- # 3 #<Thread:0x007fb23218b0f0@debug_me.rb.rb:3 sleep>
+ # 2 #<Thread:0x007fb23218a538 debug_me.rb.rb:3 sleep>
+ # 3 #<Thread:0x007fb23218b0f0 debug_me.rb.rb:3 sleep>
# [1, 2, 3]
#
# Your current thread is indicated by a <b>+</b>
@@ -1022,8 +1034,8 @@ EOHELP
#
# (rdb:1) th l
# +1 #<Thread:0x007f99328c0410 run> debug_me.rb:3
- # 2 #<Thread:0x007f9932938230@debug_me.rb:3 sleep> debug_me.rb:3
- # 3 #<Thread:0x007f9932938e10@debug_me.rb:3 sleep> debug_me.rb:3
+ # 2 #<Thread:0x007f9932938230 debug_me.rb:3 sleep> debug_me.rb:3
+ # 3 #<Thread:0x007f9932938e10 debug_me.rb:3 sleep> debug_me.rb:3
#
# See DEBUGGER__ for more usage.
@@ -1097,9 +1109,11 @@ EOHELP
stdout.printf "Debug.rb\n"
stdout.printf "Emacs support available.\n\n"
- RubyVM::InstructionSequence.compile_option = {
- trace_instruction: true
- }
+ if defined?(RubyVM::InstructionSequence)
+ RubyVM::InstructionSequence.compile_option = {
+ trace_instruction: true
+ }
+ end
set_trace_func proc { |event, file, line, id, binding, klass, *rest|
DEBUGGER__.context.trace_func event, file, line, id, binding, klass
}
diff --git a/lib/delegate.rb b/lib/delegate.rb
index 1587c7e3bb..a5ae605e9e 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -21,6 +21,8 @@
# SimpleDelegator's implementation serves as a nice example of the use of
# Delegator:
#
+# require 'delegate'
+#
# class SimpleDelegator < Delegator
# def __getobj__
# @delegate_sd_obj # return object we are delegating to, required
@@ -37,6 +39,8 @@
# Be advised, RDoc will not detect delegated methods.
#
class Delegator < BasicObject
+ VERSION = "0.2.0"
+
kernel = ::Kernel.dup
kernel.class_eval do
alias __raise__ raise
@@ -218,8 +222,8 @@ class Delegator < BasicObject
end
end
- def initialize_clone(obj) # :nodoc:
- self.__setobj__(obj.__getobj__.clone)
+ def initialize_clone(obj, freeze: nil) # :nodoc:
+ self.__setobj__(obj.__getobj__.clone(freeze: freeze))
end
def initialize_dup(obj) # :nodoc:
self.__setobj__(obj.__getobj__.dup)
@@ -253,6 +257,8 @@ end
# end
# end
#
+# require 'delegate'
+#
# class UserDecorator < SimpleDelegator
# def birth_year
# born_on.year
@@ -418,6 +424,21 @@ def DelegateClass(superclass, &block)
klass.define_singleton_method :protected_instance_methods do |all=true|
super(all) | superclass.protected_instance_methods
end
+ klass.define_singleton_method :instance_methods do |all=true|
+ super(all) | superclass.instance_methods
+ end
+ klass.define_singleton_method :public_instance_method do |name|
+ super(name)
+ rescue NameError
+ raise unless self.public_instance_methods.include?(name)
+ superclass.public_instance_method(name)
+ end
+ klass.define_singleton_method :instance_method do |name|
+ super(name)
+ rescue NameError
+ raise unless self.instance_methods.include?(name)
+ superclass.instance_method(name)
+ end
klass.module_eval(&block) if block
return klass
end
diff --git a/lib/delegate/delegate.gemspec b/lib/delegate/delegate.gemspec
index 268cc5a817..05d9ced175 100644
--- a/lib/delegate/delegate.gemspec
+++ b/lib/delegate/delegate.gemspec
@@ -1,19 +1,22 @@
-begin
- require_relative "lib/delegate/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "delegate"
- spec.version = Delegator::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
spec.summary = %q{Provides three abilities to delegate method calls to an object.}
spec.description = %q{Provides three abilities to delegate method calls to an object.}
spec.homepage = "https://github.com/ruby/delegate"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
@@ -24,4 +27,5 @@ Gem::Specification.new do |spec|
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
+ spec.required_ruby_version = '>= 2.7'
end
diff --git a/lib/delegate/version.rb b/lib/delegate/version.rb
deleted file mode 100644
index 456e8f772c..0000000000
--- a/lib/delegate/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class Delegator
- VERSION = "0.1.0"
-end
diff --git a/lib/did_you_mean.rb b/lib/did_you_mean.rb
index b8f92579ca..ab7e6b01a8 100644
--- a/lib/did_you_mean.rb
+++ b/lib/did_you_mean.rb
@@ -6,6 +6,7 @@ require_relative 'did_you_mean/spell_checkers/name_error_checkers'
require_relative 'did_you_mean/spell_checkers/method_name_checker'
require_relative 'did_you_mean/spell_checkers/key_error_checker'
require_relative 'did_you_mean/spell_checkers/null_checker'
+require_relative 'did_you_mean/spell_checkers/require_path_checker'
require_relative 'did_you_mean/formatters/plain_formatter'
require_relative 'did_you_mean/tree_spell_checker'
@@ -95,8 +96,9 @@ module DidYouMean
correct_error NameError, NameErrorCheckers
correct_error KeyError, KeyErrorChecker
correct_error NoMethodError, MethodNameChecker
+ correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0'
- # Returns the currenctly set formatter. By default, it is set to +DidYouMean::Formatter+.
+ # Returns the currently set formatter. By default, it is set to +DidYouMean::Formatter+.
def self.formatter
@@formatter
end
diff --git a/lib/did_you_mean/experimental/initializer_name_correction.rb b/lib/did_you_mean/experimental/initializer_name_correction.rb
deleted file mode 100644
index b59c98e774..0000000000
--- a/lib/did_you_mean/experimental/initializer_name_correction.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen-string-literal: true
-
-require_relative '../levenshtein'
-
-module DidYouMean
- module Experimental
- module InitializerNameCorrection
- def method_added(name)
- super
-
- distance = Levenshtein.distance(name.to_s, 'initialize')
- if distance != 0 && distance <= 2
- warn "warning: #{name} might be misspelled, perhaps you meant initialize?"
- end
- end
- end
-
- ::Class.prepend(InitializerNameCorrection)
- end
-end
diff --git a/lib/did_you_mean/experimental/ivar_name_correction.rb b/lib/did_you_mean/experimental/ivar_name_correction.rb
deleted file mode 100644
index 322e422c6b..0000000000
--- a/lib/did_you_mean/experimental/ivar_name_correction.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen-string-literal: true
-
-require_relative '../../did_you_mean'
-
-module DidYouMean
- module Experimental #:nodoc:
- class IvarNameCheckerBuilder #:nodoc:
- attr_reader :original_checker
-
- def initialize(original_checker) #:nodoc:
- @original_checker = original_checker
- end
-
- def new(no_method_error) #:nodoc:
- IvarNameChecker.new(no_method_error, original_checker: @original_checker)
- end
- end
-
- class IvarNameChecker #:nodoc:
- REPLS = {
- "(irb)" => -> { Readline::HISTORY.to_a.last }
- }
-
- TRACE = TracePoint.trace(:raise) do |tp|
- e = tp.raised_exception
-
- if SPELL_CHECKERS.include?(e.class.to_s) && !e.instance_variable_defined?(:@frame_binding)
- e.instance_variable_set(:@frame_binding, tp.binding)
- end
- end
-
- attr_reader :original_checker
-
- def initialize(no_method_error, original_checker: )
- @original_checker = original_checker.new(no_method_error)
-
- @location = no_method_error.backtrace_locations.first
- @ivar_names = no_method_error.frame_binding.receiver.instance_variables
-
- no_method_error.remove_instance_variable(:@frame_binding)
- end
-
- def corrections
- original_checker.corrections + ivar_name_corrections
- end
-
- def ivar_name_corrections
- @ivar_name_corrections ||= SpellChecker.new(dictionary: @ivar_names).correct(receiver_name.to_s)
- end
-
- private
-
- def receiver_name
- return unless @original_checker.receiver.nil?
-
- abs_path = @location.absolute_path
- lineno = @location.lineno
-
- /@(\w+)*\.#{@original_checker.method_name}/ =~ line(abs_path, lineno).to_s && $1
- end
-
- def line(abs_path, lineno)
- if REPLS[abs_path]
- REPLS[abs_path].call
- elsif File.exist?(abs_path)
- File.open(abs_path) do |file|
- file.detect { file.lineno == lineno }
- end
- end
- end
- end
- end
-
- NameError.send(:attr, :frame_binding)
- SPELL_CHECKERS['NoMethodError'] = Experimental::IvarNameCheckerBuilder.new(SPELL_CHECKERS['NoMethodError'])
-end
diff --git a/lib/did_you_mean/spell_checkers/method_name_checker.rb b/lib/did_you_mean/spell_checkers/method_name_checker.rb
index 3a38245f0c..0483127d6f 100644
--- a/lib/did_you_mean/spell_checkers/method_name_checker.rb
+++ b/lib/did_you_mean/spell_checkers/method_name_checker.rb
@@ -43,7 +43,12 @@ module DidYouMean
end
def corrections
- @corrections ||= SpellChecker.new(dictionary: RB_RESERVED_WORDS + method_names).correct(method_name) - names_to_exclude
+ @corrections ||= begin
+ dictionary = method_names
+ dictionary = RB_RESERVED_WORDS + dictionary if @private_call
+
+ SpellChecker.new(dictionary: dictionary).correct(method_name) - names_to_exclude
+ end
end
def method_names
diff --git a/lib/did_you_mean/spell_checkers/require_path_checker.rb b/lib/did_you_mean/spell_checkers/require_path_checker.rb
new file mode 100644
index 0000000000..aaf877b412
--- /dev/null
+++ b/lib/did_you_mean/spell_checkers/require_path_checker.rb
@@ -0,0 +1,35 @@
+# frozen-string-literal: true
+
+require_relative "../spell_checker"
+require_relative "../tree_spell_checker"
+
+module DidYouMean
+ class RequirePathChecker
+ attr_reader :path
+
+ INITIAL_LOAD_PATH = $LOAD_PATH.dup.freeze
+ ENV_SPECIFIC_EXT = ".#{RbConfig::CONFIG["DLEXT"]}"
+
+ private_constant :INITIAL_LOAD_PATH, :ENV_SPECIFIC_EXT
+
+ def self.requireables
+ @requireables ||= INITIAL_LOAD_PATH
+ .flat_map {|path| Dir.glob("**/???*{.rb,#{ENV_SPECIFIC_EXT}}", base: path) }
+ .map {|path| path.chomp!(".rb") || path.chomp!(ENV_SPECIFIC_EXT) }
+ end
+
+ def initialize(exception)
+ @path = exception.path
+ end
+
+ def corrections
+ @corrections ||= begin
+ threshold = path.size * 2
+ dictionary = self.class.requireables.reject {|str| str.size >= threshold }
+ spell_checker = path.include?("/") ? TreeSpellChecker : SpellChecker
+
+ spell_checker.new(dictionary: dictionary).correct(path).uniq
+ end
+ end
+ end
+end
diff --git a/lib/did_you_mean/tree_spell_checker.rb b/lib/did_you_mean/tree_spell_checker.rb
index 6a5b485413..799f07fcf0 100644
--- a/lib/did_you_mean/tree_spell_checker.rb
+++ b/lib/did_you_mean/tree_spell_checker.rb
@@ -1,137 +1,109 @@
+# frozen_string_literal: true
+
module DidYouMean
# spell checker for a dictionary that has a tree
# structure, see doc/tree_spell_checker_api.md
class TreeSpellChecker
- attr_reader :dictionary, :dimensions, :separator, :augment
+ attr_reader :dictionary, :separator, :augment
def initialize(dictionary:, separator: '/', augment: nil)
@dictionary = dictionary
@separator = separator
@augment = augment
- @dimensions = parse_dimensions
end
def correct(input)
- plausibles = plausible_dimensions input
- return no_idea(input) if plausibles.empty?
- suggestions = find_suggestions input, plausibles
- return no_idea(input) if suggestions.empty?
- suggestions
- end
+ plausibles = plausible_dimensions(input)
+ return fall_back_to_normal_spell_check(input) if plausibles.empty?
- private
+ suggestions = find_suggestions(input, plausibles)
+ return fall_back_to_normal_spell_check(input) if suggestions.empty?
- def parse_dimensions
- ParseDimensions.new(dictionary, separator).call
+ suggestions
end
- def find_suggestions(input, plausibles)
- states = plausibles[0].product(*plausibles[1..-1])
- paths = possible_paths states
- leaf = input.split(separator).last
- ideas = find_ideas(paths, leaf)
- ideas.compact.flatten
+ def dictionary_without_leaves
+ @dictionary_without_leaves ||= dictionary.map { |word| word.split(separator)[0..-2] }.uniq
end
- def no_idea(input)
- return [] unless augment
- ::DidYouMean::SpellChecker.new(dictionary: dictionary).correct(input)
+ def tree_depth
+ @tree_depth ||= dictionary_without_leaves.max { |a, b| a.size <=> b.size }.size
end
- def find_ideas(paths, leaf)
- paths.map do |path|
- names = find_leaves(path)
- ideas = CorrectElement.new.call names, leaf
- ideas_to_paths ideas, leaf, names, path
- end
+ def dimensions
+ @dimensions ||= tree_depth.times.map do |index|
+ dictionary_without_leaves.map { |element| element[index] }.compact.uniq
+ end
end
- def ideas_to_paths(ideas, leaf, names, path)
- return nil if ideas.empty?
- return [path + separator + leaf] if names.include? leaf
- ideas.map { |str| path + separator + str }
+ def find_leaves(path)
+ path_with_separator = "#{path}#{separator}"
+
+ dictionary
+ .select {|str| str.include?(path_with_separator) }
+ .map {|str| str.gsub(path_with_separator, '') }
end
- def find_leaves(path)
- dictionary.map do |str|
- next unless str.include? "#{path}#{separator}"
- str.gsub("#{path}#{separator}", '')
- end.compact
+ def plausible_dimensions(input)
+ input.split(separator)[0..-2]
+ .map
+ .with_index { |element, index| correct_element(dimensions[index], element) if dimensions[index] }
+ .compact
end
def possible_paths(states)
- states.map do |state|
- state.join separator
- end
+ states.map { |state| state.join(separator) }
end
- def plausible_dimensions(input)
- elements = input.split(separator)[0..-2]
- elements.each_with_index.map do |element, i|
- next if dimensions[i].nil?
- CorrectElement.new.call dimensions[i], element
- end.compact
- end
- end
+ private
- # parses the elements in each dimension
- class ParseDimensions
- def initialize(dictionary, separator)
- @dictionary = dictionary
- @separator = separator
+ def find_suggestions(input, plausibles)
+ states = plausibles[0].product(*plausibles[1..-1])
+ paths = possible_paths(states)
+ leaf = input.split(separator).last
+
+ find_ideas(paths, leaf)
end
- def call
- leafless = remove_leaves
- dimensions = find_elements leafless
- dimensions.map do |elements|
- elements.to_set.to_a
- end
+ def fall_back_to_normal_spell_check(input)
+ return [] unless augment
+
+ ::DidYouMean::SpellChecker.new(dictionary: dictionary).correct(input)
end
- private
+ def find_ideas(paths, leaf)
+ paths.flat_map do |path|
+ names = find_leaves(path)
+ ideas = correct_element(names, leaf)
- def remove_leaves
- dictionary.map do |a|
- elements = a.split(separator)
- elements[0..-2]
- end.to_set.to_a
+ ideas_to_paths(ideas, leaf, names, path)
+ end.compact
end
- def find_elements(leafless)
- max_elements = leafless.map(&:size).max
- dimensions = Array.new(max_elements) { [] }
- (0...max_elements).each do |i|
- leafless.each do |elements|
- dimensions[i] << elements[i] unless elements[i].nil?
- end
+ def ideas_to_paths(ideas, leaf, names, path)
+ if ideas.empty?
+ nil
+ elsif names.include?(leaf)
+ ["#{path}#{separator}#{leaf}"]
+ else
+ ideas.map {|str| "#{path}#{separator}#{str}" }
end
- dimensions
end
- attr_reader :dictionary, :separator
- end
+ def correct_element(names, element)
+ return names if names.size == 1
- # identifies the elements close to element
- class CorrectElement
- def initialize
- end
+ str = normalize(element)
- def call(names, element)
- return names if names.size == 1
- str = normalize element
- return [str] if names.include? str
- checker = ::DidYouMean::SpellChecker.new(dictionary: names)
- checker.correct(str)
- end
+ return [str] if names.include?(str)
- private
+ ::DidYouMean::SpellChecker.new(dictionary: names).correct(str)
+ end
- def normalize(leaf)
- str = leaf.dup
+ def normalize(str)
str.downcase!
- return str unless str.include? '@'
- str.tr!('@', ' ')
+ str.tr!('@', ' ') if str.include?('@')
+ str
end
end
end
diff --git a/lib/did_you_mean/version.rb b/lib/did_you_mean/version.rb
index 6d3dd3a694..9a53a3185a 100644
--- a/lib/did_you_mean/version.rb
+++ b/lib/did_you_mean/version.rb
@@ -1,3 +1,3 @@
module DidYouMean
- VERSION = "1.4.0"
+ VERSION = "1.5.0"
end
diff --git a/lib/drb/drb.gemspec b/lib/drb/drb.gemspec
new file mode 100644
index 0000000000..6b31e896c3
--- /dev/null
+++ b/lib/drb/drb.gemspec
@@ -0,0 +1,30 @@
+begin
+ require_relative "lib/drb/version"
+rescue LoadError # Fallback to load version file in ruby core repository
+ require_relative "version"
+end
+
+Gem::Specification.new do |spec|
+ spec.name = "drb"
+ spec.version = DRb::VERSION
+ spec.authors = ["Masatoshi SEKI"]
+ spec.email = ["seki@ruby-lang.org"]
+
+ spec.summary = %q{Distributed object system for Ruby}
+ spec.description = %q{Distributed object system for Ruby}
+ spec.homepage = "https://github.com/ruby/drb"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb
index 4d3ea364f1..3e23213911 100644
--- a/lib/drb/drb.rb
+++ b/lib/drb/drb.rb
@@ -1382,10 +1382,6 @@ module DRb
@@idconv = idconv
end
- def self.default_safe_level(level) # :nodoc:
- # Remove in Ruby 3.0
- end
-
# Set the default value of the :verbose option.
#
# See #new(). The initial default value is false.
@@ -1495,11 +1491,6 @@ module DRb
# The configuration of this DRbServer
attr_reader :config
- def safe_level # :nodoc:
- # Remove in Ruby 3.0
- 0
- end
-
# Set whether to operate in verbose mode.
#
# In verbose mode, failed calls are logged to stdout.
diff --git a/lib/drb/observer.rb b/lib/drb/observer.rb
index 3ee15331a1..0fb7301edf 100644
--- a/lib/drb/observer.rb
+++ b/lib/drb/observer.rb
@@ -13,7 +13,7 @@ module DRb
if defined? @observer_peers
@observer_peers.each do |observer, method|
begin
- observer.send(method, *arg)
+ observer.__send__(method, *arg)
rescue
delete_observer(observer)
end
diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb
index 3d528c6172..54ab1ef395 100644
--- a/lib/drb/ssl.rb
+++ b/lib/drb/ssl.rb
@@ -196,7 +196,7 @@ module DRb
if comment = self[:SSLCertComment]
cert.add_extension(ef.create_extension("nsComment", comment))
end
- cert.sign(rsa, OpenSSL::Digest::SHA256.new)
+ cert.sign(rsa, "SHA256")
@cert = cert
@pkey = rsa
diff --git a/lib/drb/version.rb b/lib/drb/version.rb
new file mode 100644
index 0000000000..e1f33cc65e
--- /dev/null
+++ b/lib/drb/version.rb
@@ -0,0 +1,3 @@
+module DRb
+ VERSION = "2.0.5"
+end
diff --git a/lib/erb.gemspec b/lib/erb.gemspec
new file mode 100644
index 0000000000..1cace278c1
--- /dev/null
+++ b/lib/erb.gemspec
@@ -0,0 +1,24 @@
+Gem::Specification.new do |spec|
+ spec.name = "erb"
+ spec.version = "2.2.0"
+ spec.authors = ["Masatoshi SEKI"]
+ spec.email = ["seki@ruby-lang.org"]
+
+ spec.summary = %q{An easy to use but powerful templating system for Ruby.}
+ spec.description = %q{An easy to use but powerful templating system for Ruby.}
+ spec.homepage = "https://github.com/ruby/erb"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.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 = "libexec"
+ spec.executables = ["erb"]
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "cgi"
+end
diff --git a/lib/fileutils.gemspec b/lib/fileutils.gemspec
index cd35c09dbc..53c32e7e3e 100644
--- a/lib/fileutils.gemspec
+++ b/lib/fileutils.gemspec
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
s.authors = ["Minero Aoki"]
s.email = [nil]
s.homepage = "https://github.com/ruby/fileutils"
- s.license = "BSD-2-Clause"
+ s.licenses = ["Ruby", "BSD-2-Clause"]
s.metadata = {
"source_code_uri" => "https://github.com/ruby/fileutils"
diff --git a/lib/fileutils.rb b/lib/fileutils.rb
index 04788e26ca..a2ad0c003e 100644
--- a/lib/fileutils.rb
+++ b/lib/fileutils.rb
@@ -102,7 +102,7 @@ end
# <tt>:verbose</tt> flags to methods in FileUtils.
#
module FileUtils
- VERSION = "1.4.1"
+ VERSION = "1.5.0"
def self.private_module_function(name) #:nodoc:
module_function name
@@ -208,7 +208,9 @@ module FileUtils
fu_output_message "mkdir -p #{mode ? ('-m %03o ' % mode) : ''}#{list.join ' '}" if verbose
return *list if noop
- list.map {|path| remove_trailing_slash(path)}.each do |path|
+ list.each do |item|
+ path = remove_trailing_slash(item)
+
# optimize for the most common case
begin
fu_mkdir path, mode
@@ -221,8 +223,9 @@ module FileUtils
until path == stack.last # dirname("/")=="/", dirname("C:/")=="C:/"
stack.push path
path = File.dirname(path)
+ break if File.directory?(path)
end
- stack.pop # root directory should exist
+ stack.pop if path == stack.last # root directory should exist
stack.reverse_each do |dir|
begin
fu_mkdir dir, mode
@@ -917,11 +920,8 @@ module FileUtils
private_module_function :apply_mask
def symbolic_modes_to_i(mode_sym, path) #:nodoc:
- mode = if File::Stat === path
- path.mode
- else
- File.stat(path).mode
- end
+ path = File.stat(path) unless File::Stat === path
+ mode = path.mode
mode_sym.split(/,/).inject(mode & 07777) do |current_mode, clause|
target, *actions = clause.split(/([=+-])/)
raise ArgumentError, "invalid file mode: #{mode_sym}" if actions.empty?
@@ -938,7 +938,7 @@ module FileUtils
when "x"
mask | 0111
when "X"
- if FileTest.directory? path
+ if path.directory?
mask | 0111
else
mask
@@ -1290,7 +1290,7 @@ module FileUtils
def entries
opts = {}
- opts[:encoding] = ::Encoding::UTF_8 if fu_windows?
+ opts[:encoding] = fu_windows? ? ::Encoding::UTF_8 : path.encoding
files = if Dir.respond_to?(:children)
Dir.children(path, **opts)
@@ -1560,7 +1560,15 @@ module FileUtils
def join(dir, base)
return File.path(dir) if not base or base == '.'
return File.path(base) if not dir or dir == '.'
- File.join(dir, base)
+ begin
+ File.join(dir, base)
+ rescue EncodingError
+ if fu_windows?
+ File.join(dir.encode(::Encoding::UTF_8), base.encode(::Encoding::UTF_8))
+ else
+ raise
+ end
+ end
end
if File::ALT_SEPARATOR
@@ -1615,7 +1623,7 @@ module FileUtils
def fu_output_message(msg) #:nodoc:
output = @fileutils_output if defined?(@fileutils_output)
- output ||= $stderr
+ output ||= $stdout
if defined?(@fileutils_label)
msg = @fileutils_label + msg
end
diff --git a/lib/find.gemspec b/lib/find.gemspec
new file mode 100644
index 0000000000..fff0f706cd
--- /dev/null
+++ b/lib/find.gemspec
@@ -0,0 +1,24 @@
+Gem::Specification.new do |spec|
+ spec.name = "find"
+ spec.version = "0.1.0"
+ spec.authors = ['Kazuki Tsujimoto']
+ spec.email = ['kazuki@callcc.net']
+
+ spec.summary = %q{This module supports top-down traversal of a set of file paths.}
+ spec.description = %q{This module supports top-down traversal of a set of file paths.}
+ spec.homepage = "https://github.com/ruby/find"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/forwardable.rb b/lib/forwardable.rb
index 4cfade470a..fb24b8c3e6 100644
--- a/lib/forwardable.rb
+++ b/lib/forwardable.rb
@@ -110,7 +110,10 @@
#
module Forwardable
require 'forwardable/impl'
- require "forwardable/version"
+
+ # Version of +forwardable.rb+
+ VERSION = "1.3.2"
+ FORWARDABLE_VERSION = VERSION
@debug = nil
class << self
@@ -186,7 +189,7 @@ 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'
+ mod.__send__(:ruby2_keywords, ali) if RUBY_VERSION >= '2.7'
ret
end
@@ -306,7 +309,7 @@ module SingleForwardable
gen = Forwardable._delegator_method(self, accessor, method, ali)
ret = instance_eval(&gen)
- singleton_class.send(:ruby2_keywords, ali) if RUBY_VERSION >= '2.7'
+ singleton_class.__send__(:ruby2_keywords, ali) if RUBY_VERSION >= '2.7'
ret
end
diff --git a/lib/forwardable/forwardable.gemspec b/lib/forwardable/forwardable.gemspec
index 2a3e637e26..523b8eec6f 100644
--- a/lib/forwardable/forwardable.gemspec
+++ b/lib/forwardable/forwardable.gemspec
@@ -1,22 +1,25 @@
-begin
- require_relative "lib/forwardable/version"
-rescue LoadError
- # for Ruby core repository
- require_relative "version"
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "forwardable"
- spec.version = Forwardable::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Keiju ISHITSUKA"]
spec.email = ["keiju@ruby-lang.org"]
spec.summary = %q{Provides delegation of specified methods to a designated object.}
spec.description = %q{Provides delegation of specified methods to a designated object.}
spec.homepage = "https://github.com/ruby/forwardable"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = ["forwardable.gemspec", "lib/forwardable.rb", "lib/forwardable/impl.rb", "lib/forwardable/version.rb"]
+ spec.required_ruby_version = '>= 2.4.0'
+ spec.files = ["forwardable.gemspec", "lib/forwardable.rb", "lib/forwardable/impl.rb"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
diff --git a/lib/forwardable/version.rb b/lib/forwardable/version.rb
deleted file mode 100644
index 8f3e1f510e..0000000000
--- a/lib/forwardable/version.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-module Forwardable
- # Version of +forwardable.rb+
- VERSION = "1.3.1"
- FORWARDABLE_VERSION = VERSION
-end
diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb
index ff7674f1cb..53b80ff16c 100644
--- a/lib/getoptlong.rb
+++ b/lib/getoptlong.rb
@@ -85,6 +85,9 @@
# hello -n 6 --name -- /tmp
#
class GetoptLong
+ # Version.
+ VERSION = "0.1.1"
+
#
# Orderings.
#
diff --git a/lib/getoptlong/getoptlong.gemspec b/lib/getoptlong/getoptlong.gemspec
index 5e218b8e93..9ebe3aed7e 100644
--- a/lib/getoptlong/getoptlong.gemspec
+++ b/lib/getoptlong/getoptlong.gemspec
@@ -1,19 +1,22 @@
-begin
- require_relative "lib/getoptlong/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "getoptlong"
- spec.version = GetoptLong::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
spec.summary = %q{GetoptLong for Ruby}
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/getoptlong"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/lib/getoptlong/version.rb b/lib/getoptlong/version.rb
deleted file mode 100644
index 6375fb8ad1..0000000000
--- a/lib/getoptlong/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class GetoptLong
- VERSION = "0.1.0"
-end
diff --git a/lib/ipaddr.gemspec b/lib/ipaddr.gemspec
index 2de9ef4881..5187f3be11 100644
--- a/lib/ipaddr.gemspec
+++ b/lib/ipaddr.gemspec
@@ -15,14 +15,10 @@ IPAddr provides a set of methods to manipulate an IP address.
Both IPv4 and IPv6 are supported.
DESCRIPTION
spec.homepage = "https://github.com/ruby/ipaddr"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "ipaddr.gemspec", "lib/ipaddr.rb"]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.files = ["LICENSE.txt", "README.md", "ipaddr.gemspec", "lib/ipaddr.rb"]
spec.require_paths = ["lib"]
- spec.add_development_dependency "bundler", "~> 1.15"
- spec.add_development_dependency "rake", "~> 10.0"
- spec.add_development_dependency "test-unit"
+ spec.required_ruby_version = ">= 2.3"
end
diff --git a/lib/irb.rb b/lib/irb.rb
index d8e1209f2c..93c4d25c92 100644
--- a/lib/irb.rb
+++ b/lib/irb.rb
@@ -60,7 +60,11 @@ require_relative "irb/easter-egg"
# -E enc Same as `ruby -E`
# -w Same as `ruby -w`
# -W[level=2] Same as `ruby -W`
-# --inspect Use `inspect' for output (default except for bc mode)
+# --context-mode n Set n[0-4] to method to create Binding Object,
+# when new workspace was created
+# --echo Show result(default)
+# --noecho Don't show result
+# --inspect Use `inspect' for output
# --noinspect Don't use inspect for output
# --multiline Use multiline editor module
# --nomultiline Don't use multiline editor module
@@ -68,19 +72,24 @@ require_relative "irb/easter-egg"
# --nosingleline Don't use singleline editor module
# --colorize Use colorization
# --nocolorize Don't use colorization
-# --prompt prompt-mode
-# --prompt-mode prompt-mode
+# --prompt prompt-mode/--prompt-mode prompt-mode
# Switch prompt mode. Pre-defined prompt modes are
# `default', `simple', `xmp' and `inf-ruby'
# --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
# Suppresses --multiline and --singleline.
-# --simple-prompt Simple prompt mode
+# --sample-book-mode/--simple-prompt
+# Simple prompt mode
# --noprompt No prompt mode
+# --single-irb Share self with sub-irb.
# --tracer Display trace for each execution of commands.
# --back-trace-limit n
# Display backtrace top n and tail n. The default
# value is 16.
-# -v, --version Print the version of irb
+# --verbose Show details
+# --noverbose Don't show details
+# -v, --version Print the version of irb
+# -h, --help Print help
+# -- Separate options of irb from the list of command-line args
#
# == Configuration
#
@@ -400,7 +409,7 @@ module IRB
irb.run(@CONF)
end
- # Calls each event hook of <code>IRB.conf[:TA_EXIT]</code> when the current session quits.
+ # Calls each event hook of <code>IRB.conf[:AT_EXIT]</code> when the current session quits.
def IRB.irb_at_exit
@CONF[:AT_EXIT].each{|hook| hook.call}
end
@@ -463,7 +472,7 @@ module IRB
conf[:IRB_RC].call(context) if conf[:IRB_RC]
conf[:MAIN_CONTEXT] = context
- trap("SIGINT") do
+ prev_trap = trap("SIGINT") do
signal_handle
end
@@ -472,6 +481,7 @@ module IRB
eval_input
end
ensure
+ trap("SIGINT", prev_trap)
conf[:AT_EXIT].each{|hook| hook.call}
end
end
@@ -525,7 +535,7 @@ module IRB
printf "Use \"exit\" to leave %s\n", @context.ap_name
end
else
- print "\n"
+ print "\n" if @context.prompting?
end
end
l
@@ -538,11 +548,28 @@ module IRB
signal_status(:IN_EVAL) do
begin
line.untaint if RUBY_VERSION < '2.7'
- @context.evaluate(line, line_no, exception: exc)
+ if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
+ IRB.set_measure_callback
+ end
+ if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
+ result = nil
+ last_proc = proc{ result = @context.evaluate(line, line_no, exception: exc) }
+ IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) { |chain, item|
+ _name, callback, arg = item
+ proc {
+ callback.(@context, line, line_no, arg, exception: exc) do
+ chain.call
+ end
+ }
+ }.call
+ @context.set_last_value(result)
+ else
+ @context.evaluate(line, line_no, exception: exc)
+ end
if @context.echo?
if assignment_expression?(line)
if @context.echo_on_assignment?
- output_value(@context.omit_on_assignment?)
+ output_value(@context.echo_on_assignment? == :truncate)
end
else
output_value
@@ -557,10 +584,35 @@ module IRB
next
end
handle_exception(exc)
+ @context.workspace.local_variable_set(:_, exc)
+ exc = nil
end
end
end
+ def convert_invalid_byte_sequence(str)
+ str = str.force_encoding(Encoding::ASCII_8BIT)
+ conv = Encoding::Converter.new(Encoding::ASCII_8BIT, Encoding::UTF_8)
+ dst = String.new
+ begin
+ ret = conv.primitive_convert(str, dst)
+ case ret
+ when :invalid_byte_sequence
+ conv.insert_output(conf.primitive_errinfo[3].dump[1..-2])
+ redo
+ when :undefined_conversion
+ c = conv.primitive_errinfo[3].dup.force_encoding(conv.primitive_errinfo[1])
+ conv.insert_output(c.dump[1..-2])
+ redo
+ when :incomplete_input
+ conv.insert_output(conv.primitive_errinfo[3].dump[1..-2])
+ when :finished
+ end
+ break
+ end while nil
+ dst
+ end
+
def handle_exception(exc)
if exc.backtrace && exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
!(SyntaxError === exc) && !(EncodingError === exc)
@@ -570,49 +622,44 @@ module IRB
irb_bug = false
end
- if STDOUT.tty?
- attr = ATTR_TTY
- print "#{attr[1]}Traceback#{attr[]} (most recent call last):\n"
- else
- attr = ATTR_PLAIN
- end
- messages = []
- lasts = []
- levels = 0
if exc.backtrace
- count = 0
- exc.backtrace.each do |m|
- m = @context.workspace.filter_backtrace(m) or next unless irb_bug
- count += 1
- if attr == ATTR_TTY
- m = sprintf("%9d: from %s", count, m)
+ order = nil
+ if '2.5.0' == RUBY_VERSION
+ # Exception#full_message doesn't have keyword arguments.
+ message = exc.full_message # the same of (highlight: true, order: bottom)
+ order = :bottom
+ elsif '2.5.1' <= RUBY_VERSION && RUBY_VERSION < '3.0.0'
+ if STDOUT.tty?
+ message = exc.full_message(order: :bottom)
+ order = :bottom
else
- m = "\tfrom #{m}"
+ message = exc.full_message(order: :top)
+ order = :top
end
- if messages.size < @context.back_trace_limit
- messages.push(m)
- elsif lasts.size < @context.back_trace_limit
- lasts.push(m).shift
- levels += 1
- end
- end
- end
- if attr == ATTR_TTY
- unless lasts.empty?
- puts lasts.reverse
- printf "... %d levels...\n", levels if levels > 0
- end
- puts messages.reverse
- end
- m = exc.to_s.split(/\n/)
- print "#{attr[1]}#{exc.class} (#{attr[4]}#{m.shift}#{attr[0, 1]})#{attr[]}\n"
- puts m.map {|s| "#{attr[1]}#{s}#{attr[]}\n"}
- if attr == ATTR_PLAIN
- puts messages
- unless lasts.empty?
- puts lasts
- printf "... %d levels...\n", levels if levels > 0
+ else # '3.0.0' <= RUBY_VERSION
+ message = exc.full_message(order: :top)
+ order = :top
end
+ message = convert_invalid_byte_sequence(message)
+ message = message.gsub(/((?:^\t.+$\n)+)/) { |m|
+ case order
+ when :top
+ lines = m.split("\n")
+ when :bottom
+ lines = m.split("\n").reverse
+ end
+ unless irb_bug
+ lines = lines.map { |l| @context.workspace.filter_backtrace(l) }.compact
+ if lines.size > @context.back_trace_limit
+ omit = lines.size - @context.back_trace_limit
+ lines = lines[0..(@context.back_trace_limit - 1)]
+ lines << "\t... %d levels..." % omit
+ end
+ end
+ lines = lines.reverse if order == :bottom
+ lines.map{ |l| l + "\n" }.join
+ }
+ puts message
end
print "Maybe IRB bug!\n" if irb_bug
end
@@ -761,7 +808,7 @@ module IRB
str = "%s...\e[0m" % lines.first
multiline_p = false
else
- str.gsub!(/(\A.*?\n).*/m, "\\1...")
+ str = str.gsub(/(\A.*?\n).*/m, "\\1...")
end
else
output_width = Reline::Unicode.calculate_width(@context.return_format % str, true)
diff --git a/lib/irb/cmd/fork.rb b/lib/irb/cmd/fork.rb
index 19c78fc910..7566d10be0 100644
--- a/lib/irb/cmd/fork.rb
+++ b/lib/irb/cmd/fork.rb
@@ -16,7 +16,7 @@ module IRB
module ExtendCommand
class Fork < Nop
def execute
- pid = send ExtendCommand.irb_original_method_name("fork")
+ pid = __send__ ExtendCommand.irb_original_method_name("fork")
unless pid
class << self
alias_method :exit, ExtendCommand.irb_original_method_name('exit')
diff --git a/lib/irb/cmd/info.rb b/lib/irb/cmd/info.rb
index 53ec71d754..d122c88b77 100644
--- a/lib/irb/cmd/info.rb
+++ b/lib/irb/cmd/info.rb
@@ -13,6 +13,7 @@ module IRB
str += "IRB version: #{IRB.version}\n"
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
+ str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
str
end
alias_method :to_s, :inspect
diff --git a/lib/irb/cmd/ls.rb b/lib/irb/cmd/ls.rb
new file mode 100644
index 0000000000..f163f4f9e6
--- /dev/null
+++ b/lib/irb/cmd/ls.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require "reline"
+require_relative "nop"
+require_relative "../color"
+
+# :stopdoc:
+module IRB
+ module ExtendCommand
+ class Ls < Nop
+ def execute(*arg, grep: nil)
+ o = Output.new(grep: grep)
+
+ obj = arg.empty? ? irb_context.workspace.main : arg.first
+ locals = arg.empty? ? irb_context.workspace.binding.local_variables : []
+ klass = (obj.class == Class || obj.class == Module ? obj : obj.class)
+
+ o.dump("constants", obj.constants) if obj.respond_to?(:constants)
+ o.dump("#{klass}.methods", obj.singleton_methods(false))
+ o.dump("#{klass}#methods", klass.public_instance_methods(false))
+ o.dump("instance variables", obj.instance_variables)
+ o.dump("class variables", klass.class_variables)
+ o.dump("locals", locals)
+ end
+
+ class Output
+ MARGIN = " "
+
+ def initialize(grep: nil)
+ @grep = grep
+ @line_width = screen_width - MARGIN.length # right padding
+ end
+
+ def dump(name, strs)
+ strs = strs.grep(@grep) if @grep
+ strs = strs.sort
+ return if strs.empty?
+
+ # Attempt a single line
+ print "#{Color.colorize(name, [:BOLD, :BLUE])}: "
+ if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length)
+ puts strs.join(MARGIN)
+ return
+ end
+ puts
+
+ # Dump with the largest # of columns that fits on a line
+ cols = strs.size
+ until fits_on_line?(strs, cols: cols, offset: MARGIN.length) || cols == 1
+ cols -= 1
+ end
+ widths = col_widths(strs, cols: cols)
+ strs.each_slice(cols) do |ss|
+ puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join
+ end
+ end
+
+ private
+
+ def fits_on_line?(strs, cols:, offset: 0)
+ width = col_widths(strs, cols: cols).sum + MARGIN.length * (cols - 1)
+ width <= @line_width - offset
+ end
+
+ def col_widths(strs, cols:)
+ cols.times.map do |col|
+ (col...strs.size).step(cols).map do |i|
+ strs[i].length
+ end.max
+ end
+ end
+
+ def screen_width
+ Reline.get_screen_size.last
+ rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
+ 80
+ end
+ end
+ private_constant :Output
+ end
+ end
+end
+# :startdoc:
diff --git a/lib/irb/cmd/measure.rb b/lib/irb/cmd/measure.rb
new file mode 100644
index 0000000000..58eaec2ded
--- /dev/null
+++ b/lib/irb/cmd/measure.rb
@@ -0,0 +1,40 @@
+require_relative "nop"
+
+# :stopdoc:
+module IRB
+ module ExtendCommand
+ class Measure < Nop
+ def initialize(*args)
+ super(*args)
+ end
+
+ def execute(type = nil, arg = nil, &block)
+ case type
+ when :off
+ IRB.conf[:MEASURE] = nil
+ IRB.unset_measure_callback(arg)
+ when :list
+ IRB.conf[:MEASURE_CALLBACKS].each do |type_name, _, arg_val|
+ puts "- #{type_name}" + (arg_val ? "(#{arg_val.inspect})" : '')
+ end
+ when :on
+ IRB.conf[:MEASURE] = true
+ added = IRB.set_measure_callback(type, arg)
+ puts "#{added[0]} is added." if added
+ else
+ if block_given?
+ IRB.conf[:MEASURE] = true
+ added = IRB.set_measure_callback(&block)
+ puts "#{added[0]} is added." if added
+ else
+ IRB.conf[:MEASURE] = true
+ added = IRB.set_measure_callback(type, arg)
+ puts "#{added[0]} is added." if added
+ end
+ end
+ nil
+ end
+ end
+ end
+end
+# :startdoc:
diff --git a/lib/irb/cmd/nop.rb b/lib/irb/cmd/nop.rb
index 9cf4337c28..d6f7a611a6 100644
--- a/lib/irb/cmd/nop.rb
+++ b/lib/irb/cmd/nop.rb
@@ -14,10 +14,16 @@ module IRB
module ExtendCommand
class Nop
-
- def self.execute(conf, *opts)
- command = new(conf)
- command.execute(*opts)
+ if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
+ def self.execute(conf, *opts, **kwargs, &block)
+ command = new(conf)
+ command.execute(*opts, **kwargs, &block)
+ end
+ else
+ def self.execute(conf, *opts, &block)
+ command = new(conf)
+ command.execute(*opts, &block)
+ end
end
def initialize(conf)
diff --git a/lib/irb/cmd/show_source.rb b/lib/irb/cmd/show_source.rb
new file mode 100644
index 0000000000..0bd40b7d4e
--- /dev/null
+++ b/lib/irb/cmd/show_source.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require_relative "nop"
+require_relative "../color"
+require_relative "../ruby-lex"
+
+# :stopdoc:
+module IRB
+ module ExtendCommand
+ class ShowSource < Nop
+ def execute(str = nil)
+ unless str.is_a?(String)
+ puts "Error: Expected a string but got #{str.inspect}"
+ return
+ end
+ source = find_source(str)
+ if source && File.exist?(source.file)
+ show_source(source)
+ else
+ puts "Error: Couldn't locate a definition for #{str}"
+ end
+ nil
+ end
+
+ private
+
+ # @param [IRB::ExtendCommand::ShowSource::Source] source
+ def show_source(source)
+ puts
+ puts "#{bold("From")}: #{source.file}:#{source.first_line}"
+ puts
+ code = IRB::Color.colorize_code(File.read(source.file))
+ puts code.lines[(source.first_line - 1)...source.last_line].join
+ puts
+ end
+
+ def find_source(str)
+ case str
+ when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name
+ eval(str, irb_context.workspace.binding) # trigger autoload
+ base = irb_context.workspace.binding.receiver.yield_self { |r| r.is_a?(Module) ? r : Object }
+ file, line = base.const_source_location(str) if base.respond_to?(:const_source_location) # Ruby 2.7+
+ when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
+ owner = eval(Regexp.last_match[:owner], irb_context.workspace.binding)
+ method = Regexp.last_match[:method]
+ if owner.respond_to?(:instance_method) && owner.instance_methods.include?(method.to_sym)
+ file, line = owner.instance_method(method).source_location
+ end
+ when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
+ receiver = eval(Regexp.last_match[:receiver] || 'self', irb_context.workspace.binding)
+ method = Regexp.last_match[:method]
+ file, line = receiver.method(method).source_location if receiver.respond_to?(method)
+ end
+ if file && line
+ Source.new(file: file, first_line: line, last_line: find_end(file, line))
+ end
+ end
+
+ def find_end(file, first_line)
+ return first_line unless File.exist?(file)
+ lex = RubyLex.new
+ code = +""
+ File.read(file).lines[(first_line - 1)..-1].each_with_index do |line, i|
+ _ltype, _indent, continue, code_block_open = lex.check_state(code << line)
+ if !continue && !code_block_open
+ return first_line + i
+ end
+ end
+ first_line
+ end
+
+ def bold(str)
+ Color.colorize(str, [:BOLD])
+ end
+
+ Source = Struct.new(
+ :file, # @param [String] - file name
+ :first_line, # @param [String] - first line
+ :last_line, # @param [String] - last line
+ keyword_init: true,
+ )
+ private_constant :Source
+ end
+ end
+end
+# :startdoc:
diff --git a/lib/irb/cmd/whereami.rb b/lib/irb/cmd/whereami.rb
new file mode 100644
index 0000000000..b3def11b93
--- /dev/null
+++ b/lib/irb/cmd/whereami.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require_relative "nop"
+
+# :stopdoc:
+module IRB
+ module ExtendCommand
+ class Whereami < Nop
+ def execute(*)
+ code = irb_context.workspace.code_around_binding
+ if code
+ puts code
+ else
+ puts "The current context doesn't have code."
+ end
+ end
+ end
+ end
+end
+# :startdoc:
diff --git a/lib/irb/color.rb b/lib/irb/color.rb
index 0f49291d85..cfbb3cc668 100644
--- a/lib/irb/color.rb
+++ b/lib/irb/color.rb
@@ -17,7 +17,7 @@ module IRB # :nodoc:
CYAN = 36
TOKEN_KEYWORDS = {
- on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__'],
+ on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__', '__ENCODING__'],
on_const: ['ENV'],
}
private_constant :TOKEN_KEYWORDS
@@ -60,6 +60,11 @@ module IRB # :nodoc:
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
@@ -67,6 +72,9 @@ module IRB # :nodoc:
end
private_constant :TOKEN_SEQ_EXPRS
+ ERROR_TOKENS = TOKEN_SEQ_EXPRS.keys.select { |k| k.to_s.end_with?('error') }
+ private_constant :ERROR_TOKENS
+
class << self
def colorable?
$stdout.tty? && supported? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
@@ -107,14 +115,20 @@ module IRB # :nodoc:
# 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)
+ def colorize_code(code, complete: true, ignore_error: false)
return code unless colorable?
symbol_state = SymbolState.new
colored = +''
length = 0
+ end_seen = false
scan(code, allow_last_error: !complete) do |token, str, expr|
+ # IRB::ColorPrinter skips colorizing fragments with any invalid token
+ if ignore_error && ERROR_TOKENS.include?(token)
+ return Reline::Unicode.escape_for_print(code)
+ end
+
in_symbol = symbol_state.scan_token(token)
str.each_line do |line|
line = Reline::Unicode.escape_for_print(line)
@@ -126,10 +140,11 @@ module IRB # :nodoc:
end
end
length += str.bytesize
+ end_seen = true if token == :on___end__
end
# give up colorizing incomplete Ripper tokens
- if length != code.bytesize
+ unless end_seen or length == code.bytesize
return Reline::Unicode.escape_for_print(code)
end
@@ -180,11 +195,12 @@ module IRB # :nodoc:
end
end
end
+ ensure
$VERBOSE = verbose
end
def dispatch_seq(token, expr, str, in_symbol:)
- if token == :on_parse_error or token == :compile_error
+ if ERROR_TOKENS.include?(token)
TOKEN_SEQ_EXPRS[token][0]
elsif in_symbol
[YELLOW]
diff --git a/lib/irb/color_printer.rb b/lib/irb/color_printer.rb
new file mode 100644
index 0000000000..30c6825750
--- /dev/null
+++ b/lib/irb/color_printer.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+require 'pp'
+require 'irb/color'
+
+module IRB
+ class ColorPrinter < ::PP
+ class << self
+ def pp(obj, out = $>, width = screen_width)
+ q = ColorPrinter.new(out, width)
+ q.guard_inspect_key {q.pp obj}
+ q.flush
+ out << "\n"
+ end
+
+ private
+
+ def screen_width
+ Reline.get_screen_size.last
+ rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
+ 79
+ end
+ end
+
+ def pp(obj)
+ if obj.is_a?(String)
+ # Avoid calling Ruby 2.4+ String#pretty_print that splits a string by "\n"
+ text(obj.inspect)
+ else
+ super
+ end
+ end
+
+ def text(str, width = nil)
+ unless str.is_a?(String)
+ str = str.inspect
+ end
+ width ||= str.length
+
+ case str
+ when /\A#</, '=', '>'
+ super(Color.colorize(str, [:GREEN]), width)
+ else
+ super(Color.colorize_code(str, ignore_error: true), width)
+ end
+ end
+ end
+end
diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb
index c9328e5c5a..d1bb82122e 100644
--- a/lib/irb/completion.rb
+++ b/lib/irb/completion.rb
@@ -7,7 +7,7 @@
# From Original Idea of shugo@ruby-lang.org
#
-autoload :RDoc, "rdoc"
+require_relative 'ruby-lex'
module IRB
module InputCompletor # :nodoc:
@@ -38,8 +38,69 @@ module IRB
BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{("
- CompletionProc = proc { |input|
- retrieve_completion_data(input).compact.map{ |i| i.encode(Encoding.default_external) }
+ def self.retrieve_files_to_require_from_load_path
+ @@files_from_load_path ||= $LOAD_PATH.flat_map { |path|
+ begin
+ Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: path)
+ rescue Errno::ENOENT
+ []
+ end
+ }.uniq.map { |path|
+ path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
+ }
+ end
+
+ def self.retrieve_files_to_require_relative_from_current_dir
+ @@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path|
+ path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '')
+ }
+ end
+
+ CompletionRequireProc = lambda { |target, preposing = nil, postposing = nil|
+ if target =~ /\A(['"])([^'"]+)\Z/
+ quote = $1
+ actual_target = $2
+ else
+ return nil # It's not String literal
+ end
+ tokens = RubyLex.ripper_lex_without_warning(preposing.gsub(/\s*\z/, ''))
+ tok = nil
+ tokens.reverse_each do |t|
+ unless [:on_lparen, :on_sp, :on_ignored_sp, :on_nl, :on_ignored_nl, :on_comment].include?(t.event)
+ tok = t
+ break
+ end
+ end
+ result = []
+ if tok && tok.event == :on_ident && tok.state == Ripper::EXPR_CMDARG
+ case tok.tok
+ when 'require'
+ result = retrieve_files_to_require_from_load_path.select { |path|
+ path.start_with?(actual_target)
+ }.map { |path|
+ quote + path
+ }
+ when 'require_relative'
+ result = retrieve_files_to_require_relative_from_current_dir.select { |path|
+ path.start_with?(actual_target)
+ }.map { |path|
+ quote + path
+ }
+ end
+ end
+ result
+ }
+
+ CompletionProc = lambda { |target, preposing = nil, postposing = nil|
+ if preposing && postposing
+ result = CompletionRequireProc.(target, preposing, postposing)
+ unless result
+ result = retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
+ end
+ result
+ else
+ retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) }
+ end
}
def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)
@@ -47,7 +108,7 @@ module IRB
when /^((["'`]).*\2)\.([^.]*)$/
# String
receiver = $1
- message = Regexp.quote($3)
+ message = $3
candidates = String.instance_methods.collect{|m| m.to_s}
if doc_namespace
@@ -59,7 +120,7 @@ module IRB
when /^(\/[^\/]*\/)\.([^.]*)$/
# Regexp
receiver = $1
- message = Regexp.quote($2)
+ message = $2
candidates = Regexp.instance_methods.collect{|m| m.to_s}
if doc_namespace
@@ -71,7 +132,7 @@ module IRB
when /^([^\]]*\])\.([^.]*)$/
# Array
receiver = $1
- message = Regexp.quote($2)
+ message = $2
candidates = Array.instance_methods.collect{|m| m.to_s}
if doc_namespace
@@ -83,7 +144,7 @@ module IRB
when /^([^\}]*\})\.([^.]*)$/
# Proc or Hash
receiver = $1
- message = Regexp.quote($2)
+ message = $2
proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
hash_candidates = Hash.instance_methods.collect{|m| m.to_s}
@@ -117,7 +178,7 @@ module IRB
when /^([A-Z].*)::([^:.]*)$/
# Constant or class methods
receiver = $1
- message = Regexp.quote($2)
+ message = $2
begin
candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
@@ -134,7 +195,7 @@ module IRB
# Symbol
receiver = $1
sep = $2
- message = Regexp.quote($3)
+ message = $3
candidates = Symbol.instance_methods.collect{|m| m.to_s}
if doc_namespace
@@ -147,7 +208,7 @@ module IRB
# Numeric
receiver = $~[:num]
sep = $~[:sep]
- message = Regexp.quote($~[:mes])
+ message = $~[:mes]
begin
instance = eval(receiver, bind)
@@ -169,7 +230,7 @@ module IRB
# Numeric(0xFFFF)
receiver = $1
sep = $2
- message = Regexp.quote($3)
+ message = $3
begin
instance = eval(receiver, bind)
@@ -201,7 +262,7 @@ module IRB
# variable.func or func.func
receiver = $1
sep = $2
- message = Regexp.quote($3)
+ message = $3
gv = eval("global_variables", bind).collect{|m| m.to_s}.push("true", "false", "nil")
lv = eval("local_variables", bind).collect{|m| m.to_s}
@@ -244,7 +305,7 @@ module IRB
# unknown(maybe String)
receiver = ""
- message = Regexp.quote($1)
+ message = $1
candidates = String.instance_methods(true).collect{|m| m.to_s}
if doc_namespace
@@ -266,13 +327,22 @@ module IRB
end
PerfectMatchedProc = ->(matched, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding) {
+ begin
+ require 'rdoc'
+ rescue LoadError
+ return
+ end
+
RDocRIDriver ||= RDoc::RI::Driver.new
+
if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
- IRB.send(:easter_egg)
+ IRB.__send__(:easter_egg)
return
end
+
namespace = retrieve_completion_data(matched, bind: bind, doc_namespace: true)
return unless namespace
+
if namespace.is_a?(Array)
out = RDoc::Markup::Document.new
namespace.each do |m|
@@ -294,7 +364,7 @@ module IRB
Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]
def self.select_message(receiver, message, candidates, sep = ".")
- candidates.grep(/^#{message}/).collect do |e|
+ candidates.grep(/^#{Regexp.quote(message)}/).collect do |e|
case e
when /^[a-zA-Z_]/
receiver + sep + e
diff --git a/lib/irb/context.rb b/lib/irb/context.rb
index 4f001729e1..0d358de6ff 100644
--- a/lib/irb/context.rb
+++ b/lib/irb/context.rb
@@ -131,12 +131,7 @@ module IRB
@echo_on_assignment = IRB.conf[:ECHO_ON_ASSIGNMENT]
if @echo_on_assignment.nil?
- @echo_on_assignment = true
- end
-
- @omit_on_assignment = IRB.conf[:OMIT_ON_ASSIGNMENT]
- if @omit_on_assignment.nil?
- @omit_on_assignment = true
+ @echo_on_assignment = :truncate
end
@newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]
@@ -256,27 +251,24 @@ module IRB
attr_accessor :echo
# Whether to echo for assignment expressions
#
- # Uses <code>IRB.conf[:ECHO_ON_ASSIGNMENT]</code> if available, or defaults to +true+.
+ # 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"
+ # #=> omgomgomgomgomgomgomgomgomgomg
attr_accessor :echo_on_assignment
- # Whether to omit echo for assignment expressions
- #
- # Uses <code>IRB.conf[:OMIT_ON_ASSIGNMENT]</code> if available, or defaults to +true+.
- #
- # a = [1] * 10
- # #=> [1, 1, 1, 1, 1, 1, 1, 1, ...
- # [1] * 10
- # #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
- # IRB.CurrentContext.omit_on_assignment = false
- # a = [1] * 10
- # #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
- # [1] * 10
- # #=> [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
- attr_accessor :omit_on_assignment
# Whether a newline is put before multiline output.
#
# Uses <code>IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]</code> if available,
@@ -325,7 +317,6 @@ module IRB
alias ignore_eof? ignore_eof
alias echo? echo
alias echo_on_assignment? echo_on_assignment
- alias omit_on_assignment? omit_on_assignment
alias newline_before_multiline_output? newline_before_multiline_output
# Returns whether messages are displayed or not.
diff --git a/lib/irb/easter-egg.rb b/lib/irb/easter-egg.rb
index 64869d85fa..3e79692de9 100644
--- a/lib/irb/easter-egg.rb
+++ b/lib/irb/easter-egg.rb
@@ -126,6 +126,7 @@ module IRB
print "\e[H" + buff
sleep 0.05
end
+ rescue Interrupt
ensure
print "\e[0m\e[?1049l"
end
@@ -134,4 +135,4 @@ module IRB
end
end
-IRB.send(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__
+IRB.__send__(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__
diff --git a/lib/irb/ext/loader.rb b/lib/irb/ext/loader.rb
index 1b683d88e5..af028996e7 100644
--- a/lib/irb/ext/loader.rb
+++ b/lib/irb/ext/loader.rb
@@ -31,8 +31,31 @@ module IRB # :nodoc:
load_file(path, priv)
end
+ if File.respond_to?(:absolute_path?)
+ def absolute_path?(path)
+ File.absolute_path?(path)
+ end
+ else
+ separator =
+ if File::ALT_SEPARATOR
+ "[#{Regexp.quote(File::SEPARATOR + File::ALT_SEPARATOR)}]"
+ else
+ File::SEPARATOR
+ end
+ ABSOLUTE_PATH_PATTERN = # :nodoc:
+ case Dir.pwd
+ when /\A\w:/, /\A#{separator}{2}/
+ /\A(?:\w:|#{separator})#{separator}/
+ else
+ /\A#{separator}/
+ end
+ def absolute_path?(path)
+ ABSOLUTE_PATH_PATTERN =~ path
+ end
+ end
+
def search_file_from_ruby_path(fn) # :nodoc:
- if /^#{Regexp.quote(File::Separator)}/ =~ fn
+ if absolute_path?(fn)
return fn if File.exist?(fn)
return nil
end
@@ -50,16 +73,18 @@ module IRB # :nodoc:
# See Irb#suspend_input_method for more information.
def source_file(path)
irb.suspend_name(path, File.basename(path)) do
- irb.suspend_input_method(FileInputMethod.new(path)) do
- |back_io|
- irb.signal_status(:IN_LOAD) do
- if back_io.kind_of?(FileInputMethod)
- irb.eval_input
- else
- begin
+ FileInputMethod.open(path) do |io|
+ irb.suspend_input_method(io) do
+ |back_io|
+ irb.signal_status(:IN_LOAD) do
+ if back_io.kind_of?(FileInputMethod)
irb.eval_input
- rescue LoadAbort
- print "load abort!!\n"
+ else
+ begin
+ irb.eval_input
+ rescue LoadAbort
+ print "load abort!!\n"
+ end
end
end
end
@@ -79,16 +104,18 @@ module IRB # :nodoc:
ws = WorkSpace.new
end
irb.suspend_workspace(ws) do
- irb.suspend_input_method(FileInputMethod.new(path)) do
- |back_io|
- irb.signal_status(:IN_LOAD) do
- if back_io.kind_of?(FileInputMethod)
- irb.eval_input
- else
- begin
+ FileInputMethod.open(path) do |io|
+ irb.suspend_input_method(io) do
+ |back_io|
+ irb.signal_status(:IN_LOAD) do
+ if back_io.kind_of?(FileInputMethod)
irb.eval_input
- rescue LoadAbort
- print "load abort!!\n"
+ else
+ begin
+ irb.eval_input
+ rescue LoadAbort
+ print "load abort!!\n"
+ end
end
end
end
diff --git a/lib/irb/ext/save-history.rb b/lib/irb/ext/save-history.rb
index ac358c8ccb..7acaebe36a 100644
--- a/lib/irb/ext/save-history.rb
+++ b/lib/irb/ext/save-history.rb
@@ -81,6 +81,8 @@ module IRB
end
}
end
+ @loaded_history_lines = history.size
+ @loaded_history_mtime = File.mtime(history_file)
end
end
@@ -105,12 +107,20 @@ module IRB
raise
end
- open(history_file, "w:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f|
+ if File.exist?(history_file) && @loaded_history_mtime &&
+ File.mtime(history_file) != @loaded_history_mtime
+ history = history[@loaded_history_lines..-1]
+ append_history = true
+ end
+
+ open(history_file, "#{append_history ? 'a' : 'w'}:#{IRB.conf[:LC_MESSAGES].encoding}", 0600) do |f|
hist = history.map{ |l| l.split("\n").join("\\\n") }
- begin
- hist = hist.last(num) if hist.size > num and num > 0
- rescue RangeError # bignum too big to convert into `long'
- # Do nothing because the bignum should be treated as inifinity
+ unless append_history
+ begin
+ hist = hist.last(num) if hist.size > num and num > 0
+ rescue RangeError # bignum too big to convert into `long'
+ # Do nothing because the bignum should be treated as inifinity
+ end
end
f.puts(hist)
end
diff --git a/lib/irb/extend-command.rb b/lib/irb/extend-command.rb
index 2f4fcfb5c6..339e9e6084 100644
--- a/lib/irb/extend-command.rb
+++ b/lib/irb/extend-command.rb
@@ -125,6 +125,26 @@ module IRB # :nodoc:
:irb_info, :Info, "irb/cmd/info"
],
+ [
+ :irb_ls, :Ls, "irb/cmd/ls",
+ [:ls, NO_OVERRIDE],
+ ],
+
+ [
+ :irb_measure, :Measure, "irb/cmd/measure",
+ [:measure, NO_OVERRIDE],
+ ],
+
+ [
+ :irb_show_source, :ShowSource, "irb/cmd/show_source",
+ [:show_source, NO_OVERRIDE],
+ ],
+
+ [
+ :irb_whereami, :Whereami, "irb/cmd/whereami",
+ [:whereami, NO_OVERRIDE],
+ ],
+
]
# Installs the default irb commands:
@@ -164,23 +184,24 @@ module IRB # :nodoc:
end
if load_file
+ kwargs = ", **kwargs" if RUBY_ENGINE == "ruby" && RUBY_VERSION >= "2.7.0"
line = __LINE__; eval %[
- def #{cmd_name}(*opts, &b)
+ def #{cmd_name}(*opts#{kwargs}, &b)
require "#{load_file}"
arity = ExtendCommand::#{cmd_class}.instance_method(:execute).arity
args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s }
- args << "*opts" if arity < 0
+ args << "*opts#{kwargs}" if arity < 0
args << "&block"
args = args.join(", ")
line = __LINE__; eval %[
- unless self.class.class_variable_defined?(:@@#{cmd_name}_)
- self.class.class_variable_set(:@@#{cmd_name}_, true)
- def #{cmd_name}_(\#{args})
+ unless singleton_class.class_variable_defined?(:@@#{cmd_name}_)
+ singleton_class.class_variable_set(:@@#{cmd_name}_, true)
+ def self.#{cmd_name}_(\#{args})
ExtendCommand::#{cmd_class}.execute(irb_context, \#{args})
end
end
], nil, __FILE__, line
- send :#{cmd_name}_, *opts, &b
+ __send__ :#{cmd_name}_, *opts#{kwargs}, &b
end
], nil, __FILE__, line
else
@@ -268,7 +289,7 @@ module IRB # :nodoc:
def #{cmd_name}(*opts, &b)
Context.module_eval {remove_method(:#{cmd_name})}
require "#{load_file}"
- send :#{cmd_name}, *opts, &b
+ __send__ :#{cmd_name}, *opts, &b
end
for ali in aliases
alias_method ali, cmd_name
@@ -291,8 +312,8 @@ module IRB # :nodoc:
module_eval %[
alias_method alias_name, base_method
def #{base_method}(*opts)
- send :#{extend_method}, *opts
- send :#{alias_name}, *opts
+ __send__ :#{extend_method}, *opts
+ __send__ :#{alias_name}, *opts
end
]
end
@@ -307,8 +328,8 @@ module IRB # :nodoc:
module_eval %[
alias_method alias_name, base_method
def #{base_method}(*opts)
- send :#{alias_name}, *opts
- send :#{extend_method}, *opts
+ __send__ :#{alias_name}, *opts
+ __send__ :#{extend_method}, *opts
end
]
end
diff --git a/lib/irb/init.rb b/lib/irb/init.rb
index 44383609bd..78ef2fa3c1 100644
--- a/lib/irb/init.rb
+++ b/lib/irb/init.rb
@@ -52,7 +52,6 @@ module IRB # :nodoc:
@CONF[:IGNORE_EOF] = false
@CONF[:ECHO] = nil
@CONF[:ECHO_ON_ASSIGNMENT] = nil
- @CONF[:OMIT_ON_ASSIGNMENT] = nil
@CONF[:VERBOSE] = nil
@CONF[:EVAL_HISTORY] = nil
@@ -109,14 +108,89 @@ module IRB # :nodoc:
@CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL)
@CONF[:AUTO_INDENT] = true
- @CONF[:CONTEXT_MODE] = 3 # use binding in function on TOPLEVEL_BINDING
+ @CONF[:CONTEXT_MODE] = 4 # use a copy of TOPLEVEL_BINDING
@CONF[:SINGLE_IRB] = false
+ @CONF[:MEASURE] = false
+ @CONF[:MEASURE_PROC] = {}
+ @CONF[:MEASURE_PROC][:TIME] = proc { |context, code, line_no, &block|
+ time = Time.now
+ result = block.()
+ now = Time.now
+ puts 'processing time: %fs' % (now - time) if IRB.conf[:MEASURE]
+ result
+ }
+ @CONF[:MEASURE_PROC][:STACKPROF] = proc { |context, code, line_no, arg, &block|
+ success = false
+ begin
+ require 'stackprof'
+ success = true
+ rescue LoadError
+ puts 'Please run "gem install stackprof" before measuring by StackProf.'
+ end
+ if success
+ result = nil
+ stackprof_result = StackProf.run(mode: arg ? arg : :cpu) do
+ result = block.()
+ end
+ StackProf::Report.new(stackprof_result).print_text if IRB.conf[:MEASURE]
+ result
+ else
+ block.()
+ end
+ }
+ @CONF[:MEASURE_CALLBACKS] = []
+
@CONF[:LC_MESSAGES] = Locale.new
@CONF[:AT_EXIT] = []
end
+ def IRB.set_measure_callback(type = nil, arg = nil, &block)
+ added = nil
+ if type
+ type_sym = type.upcase.to_sym
+ if IRB.conf[:MEASURE_PROC][type_sym]
+ added = [type_sym, IRB.conf[:MEASURE_PROC][type_sym], arg]
+ end
+ elsif IRB.conf[:MEASURE_PROC][:CUSTOM]
+ added = [:CUSTOM, IRB.conf[:MEASURE_PROC][:CUSTOM], arg]
+ elsif block_given?
+ added = [:BLOCK, block, arg]
+ found = IRB.conf[:MEASURE_CALLBACKS].find{ |m| m[0] == added[0] && m[2] == added[2] }
+ if found
+ found[1] = block
+ return added
+ else
+ IRB.conf[:MEASURE_CALLBACKS] << added
+ return added
+ end
+ else
+ added = [:TIME, IRB.conf[:MEASURE_PROC][:TIME], arg]
+ end
+ if added
+ found = IRB.conf[:MEASURE_CALLBACKS].find{ |m| m[0] == added[0] && m[2] == added[2] }
+ if found
+ # already added
+ nil
+ else
+ IRB.conf[:MEASURE_CALLBACKS] << added if added
+ added
+ end
+ else
+ nil
+ end
+ end
+
+ def IRB.unset_measure_callback(type = nil)
+ if type.nil?
+ IRB.conf[:MEASURE_CALLBACKS].clear
+ else
+ type_sym = type.upcase.to_sym
+ IRB.conf[:MEASURE_CALLBACKS].reject!{ |t, | t == type_sym }
+ end
+ end
+
def IRB.init_error
@CONF[:LC_MESSAGES].load("irb/error.rb")
end
@@ -132,7 +206,7 @@ module IRB # :nodoc:
$DEBUG = true
$VERBOSE = true
when "-w"
- $VERBOSE = true
+ Warning[:deprecated] = $VERBOSE = true
when /^-W(.+)?/
opt = $1 || argv.shift
case opt
@@ -141,7 +215,7 @@ module IRB # :nodoc:
when "1"
$VERBOSE = false
else
- $VERBOSE = true
+ Warning[:deprecated] = $VERBOSE = true
end
when /^-r(.+)?/
opt = $1 || argv.shift
@@ -178,10 +252,8 @@ module IRB # :nodoc:
@CONF[:ECHO_ON_ASSIGNMENT] = true
when "--noecho-on-assignment"
@CONF[:ECHO_ON_ASSIGNMENT] = false
- when "--omit-on-assignment"
- @CONF[:OMIT_ON_ASSIGNMENT] = true
- when "--noomit-on-assignment"
- @CONF[:OMIT_ON_ASSIGNMENT] = false
+ when "--truncate-echo-on-assignment"
+ @CONF[:ECHO_ON_ASSIGNMENT] = :truncate
when "--verbose"
@CONF[:VERBOSE] = true
when "--noverbose"
diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb
index 6e87488753..1854567a2d 100644
--- a/lib/irb/input-method.rb
+++ b/lib/irb/input-method.rb
@@ -83,7 +83,15 @@ module IRB
#
# See IO#eof? for more information.
def eof?
- @stdin.eof?
+ rs, = IO.select([@stdin], [], [], 0.00001)
+ if rs and rs[0]
+ 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
@@ -116,10 +124,22 @@ module IRB
# Use a File for IO with irb, see InputMethod
class FileInputMethod < InputMethod
+ class << self
+ def open(file, &block)
+ begin
+ io = new(file)
+ block.call(io)
+ ensure
+ io&.close
+ end
+ end
+ end
+
# Creates a new input method object
def initialize(file)
super
@io = IRB::MagicFile.open(file)
+ @external_encoding = @io.external_encoding
end
# The file name of this input method, usually given during initialization.
attr_reader :file_name
@@ -129,7 +149,7 @@ module IRB
#
# See IO#eof? for more information.
def eof?
- @io.eof?
+ @io.closed? || @io.eof?
end
# Reads the next line from this input method.
@@ -142,13 +162,17 @@ module IRB
# The external encoding for standard input.
def encoding
- @io.external_encoding
+ @external_encoding
end
# For debug message
def inspect
'FileInputMethod'
end
+
+ def close
+ @io.close
+ end
end
begin
@@ -256,6 +280,7 @@ module IRB
Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS
end
Reline.completion_append_character = nil
+ Reline.completer_quote_characters = ''
Reline.completion_proc = IRB::InputCompletor::CompletionProc
Reline.output_modifier_proc =
if IRB.conf[:USE_COLORIZE]
diff --git a/lib/irb/inspector.rb b/lib/irb/inspector.rb
index 671b32b6e8..c2f3b605db 100644
--- a/lib/irb/inspector.rb
+++ b/lib/irb/inspector.rb
@@ -100,29 +100,27 @@ module IRB # :nodoc:
# Proc to call when the input is evaluated and output in irb.
def inspect_value(v)
@inspect.call(v)
+ rescue
+ puts "(Object doesn't support #inspect)"
+ ''
end
end
Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s}
- Inspector.def_inspector([true, :p, :inspect]){|v|
- begin
- result = v.inspect
- if IRB.conf[:MAIN_CONTEXT]&.use_colorize? && Color.inspect_colorable?(v)
- result = Color.colorize_code(result)
- end
- result
- rescue NoMethodError
- puts "(Object doesn't support #inspect)"
- ''
- end
- }
- Inspector.def_inspector([:pp, :pretty_inspect], proc{require "pp"}){|v|
- result = v.pretty_inspect.chomp
+ Inspector.def_inspector([:p, :inspect]){|v|
+ result = v.inspect
if IRB.conf[:MAIN_CONTEXT]&.use_colorize? && Color.inspect_colorable?(v)
result = Color.colorize_code(result)
end
result
}
+ Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require "irb/color_printer"}){|v|
+ if IRB.conf[:MAIN_CONTEXT]&.use_colorize?
+ IRB::ColorPrinter.pp(v, '').chomp
+ else
+ v.pretty_inspect.chomp
+ end
+ }
Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v|
begin
YAML.dump(v)
diff --git a/lib/irb/irb.gemspec b/lib/irb/irb.gemspec
index af40a32452..38fee9d9fb 100644
--- a/lib/irb/irb.gemspec
+++ b/lib/irb/irb.gemspec
@@ -28,50 +28,8 @@ Gem::Specification.new do |spec|
"doc/irb/irb.rd.ja",
"exe/irb",
"irb.gemspec",
- "lib/irb.rb",
- "lib/irb/cmd/chws.rb",
- "lib/irb/cmd/fork.rb",
- "lib/irb/cmd/help.rb",
- "lib/irb/cmd/load.rb",
- "lib/irb/cmd/nop.rb",
- "lib/irb/cmd/pushws.rb",
- "lib/irb/cmd/subirb.rb",
- "lib/irb/color.rb",
- "lib/irb/completion.rb",
- "lib/irb/context.rb",
- "lib/irb/easter-egg.rb",
- "lib/irb/ext/change-ws.rb",
- "lib/irb/ext/history.rb",
- "lib/irb/ext/loader.rb",
- "lib/irb/ext/multi-irb.rb",
- "lib/irb/ext/save-history.rb",
- "lib/irb/ext/tracer.rb",
- "lib/irb/ext/use-loader.rb",
- "lib/irb/ext/workspaces.rb",
- "lib/irb/extend-command.rb",
- "lib/irb/frame.rb",
- "lib/irb/help.rb",
- "lib/irb/init.rb",
- "lib/irb/input-method.rb",
- "lib/irb/inspector.rb",
- "lib/irb/lc/error.rb",
- "lib/irb/lc/help-message",
- "lib/irb/lc/ja/encoding_aliases.rb",
- "lib/irb/lc/ja/error.rb",
- "lib/irb/lc/ja/help-message",
- "lib/irb/locale.rb",
- "lib/irb/magic-file.rb",
- "lib/irb/notifier.rb",
- "lib/irb/output-method.rb",
- "lib/irb/ruby-lex.rb",
- "lib/irb/ruby_logo.aa",
- "lib/irb/src_encoding.rb",
- "lib/irb/version.rb",
- "lib/irb/workspace.rb",
- "lib/irb/ws-for-case-2.rb",
- "lib/irb/xmp.rb",
"man/irb.1",
- ]
+ ] + Dir.glob("lib/**/*")
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
diff --git a/lib/irb/lc/help-message b/lib/irb/lc/help-message
index a80facc9c5..9c3ea859ad 100644
--- a/lib/irb/lc/help-message
+++ b/lib/irb/lc/help-message
@@ -10,7 +10,7 @@
#
#
Usage: irb.rb [options] [programfile] [arguments]
- -f Suppress read of ~/.irbrc
+ -f Suppress read of ~/.irbrc
-d Set $DEBUG to true (same as `ruby -d')
-r load-module Same as `ruby -r'
-I path Specify $LOAD_PATH directory
@@ -18,7 +18,7 @@ Usage: irb.rb [options] [programfile] [arguments]
-E enc Same as `ruby -E`
-w Same as `ruby -w`
-W[level=2] Same as `ruby -W`
- --context-mode n Set n[0-3] to method to create Binding Object,
+ --context-mode n Set n[0-4] to method to create Binding Object,
when new workspace was created
--echo Show result(default)
--noecho Don't show result
@@ -31,8 +31,8 @@ Usage: irb.rb [options] [programfile] [arguments]
--colorize Use colorization
--nocolorize Don't use colorization
--prompt prompt-mode/--prompt-mode prompt-mode
- Switch prompt mode. Pre-defined prompt modes are
- `default', `simple', `xmp' and `inf-ruby'
+ Switch prompt mode. Pre-defined prompt modes are
+ `default', `simple', `xmp' and `inf-ruby'
--inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
Suppresses --multiline and --singleline.
--sample-book-mode/--simple-prompt
@@ -41,8 +41,8 @@ Usage: irb.rb [options] [programfile] [arguments]
--single-irb Share self with sub-irb.
--tracer Display trace for each execution of commands.
--back-trace-limit n
- Display backtrace top n and tail n. The default
- value is 16.
+ Display backtrace top n and tail n. The default
+ value is 16.
--verbose Show details
--noverbose Don't show details
-v, --version Print the version of irb
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
index 7be77fd12e..82df06da2b 100644
--- a/lib/irb/ruby-lex.rb
+++ b/lib/irb/ruby-lex.rb
@@ -47,12 +47,26 @@ class RubyLex
@io = io
if @io.respond_to?(:check_termination)
@io.check_termination do |code|
- code.gsub!(/\s*\z/, '').concat("\n")
- ltype, indent, continue, code_block_open = check_state(code)
- if ltype or indent > 0 or continue or code_block_open
- false
+ if Reline::IOGate.in_pasting?
+ lex = RubyLex.new
+ rest = lex.check_termination_in_prev_line(code)
+ if rest
+ Reline.delete_text
+ rest.bytes.reverse_each do |c|
+ Reline.ungetc(c)
+ end
+ true
+ else
+ false
+ end
else
- true
+ code.gsub!(/\s*\z/, '').concat("\n")
+ ltype, indent, continue, code_block_open = check_state(code)
+ if ltype or indent > 0 or continue or code_block_open
+ false
+ else
+ true
+ end
end
end
end
@@ -60,11 +74,31 @@ class RubyLex
@io.dynamic_prompt do |lines|
lines << '' if lines.empty?
result = []
- lines.each_index { |i|
- c = lines[0..i].map{ |l| l + "\n" }.join
- ltype, indent, continue, code_block_open = check_state(c)
- result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + i)
- }
+ tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join)
+ code = String.new
+ partial_tokens = []
+ unprocessed_tokens = []
+ line_num_offset = 0
+ tokens.each do |t|
+ partial_tokens << t
+ unprocessed_tokens << t
+ if t[2].include?("\n")
+ t_str = t[2]
+ t_str.each_line("\n") do |s|
+ code << s << "\n"
+ ltype, indent, continue, code_block_open = check_state(code, partial_tokens)
+ result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
+ line_num_offset += 1
+ end
+ unprocessed_tokens = []
+ else
+ code << t[2]
+ end
+ end
+ unless unprocessed_tokens.empty?
+ ltype, indent, continue, code_block_open = check_state(code, unprocessed_tokens)
+ result << @prompt.call(ltype, indent, continue || code_block_open, @line_no + line_num_offset)
+ end
result
end
end
@@ -86,30 +120,78 @@ class RubyLex
end
end
- def ripper_lex_without_warning(code)
+ ERROR_TOKENS = [
+ :on_parse_error,
+ :compile_error,
+ :on_assign_error,
+ :on_alias_error,
+ :on_class_name_error,
+ :on_param_error
+ ]
+
+ def self.ripper_lex_without_warning(code)
verbose, $VERBOSE = $VERBOSE, nil
tokens = nil
- self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
- tokens = Ripper.lex(inner_code, '-', line_no)
+ compile_with_errors_suppressed(code) do |inner_code, line_no|
+ lexer = Ripper::Lexer.new(inner_code, '-', line_no)
+ if lexer.respond_to?(:scan) # Ruby 2.7+
+ tokens = []
+ pos_to_index = {}
+ lexer.scan.each do |t|
+ if pos_to_index.has_key?(t[0])
+ index = pos_to_index[t[0]]
+ found_tk = tokens[index]
+ if ERROR_TOKENS.include?(found_tk[1]) && !ERROR_TOKENS.include?(t[1])
+ tokens[index] = t
+ end
+ else
+ pos_to_index[t[0]] = tokens.size
+ tokens << t
+ end
+ end
+ else
+ tokens = lexer.parse
+ end
end
- $VERBOSE = verbose
tokens
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def find_prev_spaces(line_index)
+ return 0 if @tokens.size == 0
+ md = @tokens[0][2].match(/(\A +)/)
+ prev_spaces = md.nil? ? 0 : md[1].count(' ')
+ line_count = 0
+ @tokens.each_with_index do |t, i|
+ if t[2].include?("\n")
+ line_count += t[2].count("\n")
+ if line_count >= line_index
+ return prev_spaces
+ end
+ if (@tokens.size - 1) > i
+ md = @tokens[i + 1][2].match(/(\A +)/)
+ prev_spaces = md.nil? ? 0 : md[1].count(' ')
+ end
+ end
+ end
+ prev_spaces
end
def set_auto_indent(context)
if @io.respond_to?(:auto_indent) and context.auto_indent_mode
@io.auto_indent do |lines, line_index, byte_pointer, is_newline|
if is_newline
- md = lines[line_index - 1].match(/(\A +)/)
- prev_spaces = md.nil? ? 0 : md[1].count(' ')
- @tokens = ripper_lex_without_warning(lines[0..line_index].join("\n"))
+ @tokens = self.class.ripper_lex_without_warning(lines[0..line_index].join("\n"))
+ prev_spaces = find_prev_spaces(line_index)
depth_difference = check_newline_depth_difference
+ depth_difference = 0 if depth_difference < 0
prev_spaces + depth_difference * 2
else
code = line_index.zero? ? '' : lines[0..(line_index - 1)].map{ |l| l + "\n" }.join
last_line = lines[line_index]&.byteslice(0, byte_pointer)
code += last_line if last_line
- @tokens = ripper_lex_without_warning(code)
+ @tokens = self.class.ripper_lex_without_warning(code)
corresponding_token_depth = check_corresponding_token_depth
if corresponding_token_depth
corresponding_token_depth
@@ -121,12 +203,12 @@ class RubyLex
end
end
- def check_state(code)
- @tokens = ripper_lex_without_warning(code)
- ltype = process_literal_type
- indent = process_nesting_level
- continue = process_continue
- code_block_open = check_code_block(code)
+ def check_state(code, tokens = nil)
+ tokens = self.class.ripper_lex_without_warning(code) unless tokens
+ ltype = process_literal_type(tokens)
+ indent = process_nesting_level(tokens)
+ continue = process_continue(tokens)
+ code_block_open = check_code_block(code, tokens)
[ltype, indent, continue, code_block_open]
end
@@ -155,7 +237,10 @@ class RubyLex
throw :TERM_INPUT if @line == ''
else
@line_no += l.count("\n")
- next if l == "\n"
+ if l == "\n"
+ @exp_line_no += 1
+ next
+ end
@line.concat l
if @code_block_open or @ltype or @continue or @indent > 0
next
@@ -165,7 +250,7 @@ class RubyLex
@line.force_encoding(@io.encoding)
yield @line, @exp_line_no
end
- break if @io.eof?
+ raise TerminateLineInput if @io.eof?
@line = ''
@exp_line_no = @line_no
@@ -185,7 +270,7 @@ class RubyLex
end
code = @line + (line.nil? ? '' : line)
code.gsub!(/\s*\z/, '').concat("\n")
- @tokens = ripper_lex_without_warning(code)
+ @tokens = self.class.ripper_lex_without_warning(code)
@continue = process_continue
@code_block_open = check_code_block(code)
@indent = process_nesting_level
@@ -193,40 +278,46 @@ class RubyLex
line
end
- def process_continue
+ def process_continue(tokens = @tokens)
# last token is always newline
- if @tokens.size >= 2 and @tokens[-2][1] == :on_regexp_end
+ if tokens.size >= 2 and tokens[-2][1] == :on_regexp_end
# end of regexp literal
return false
- elsif @tokens.size >= 2 and @tokens[-2][1] == :on_semicolon
+ elsif tokens.size >= 2 and tokens[-2][1] == :on_semicolon
return false
- elsif @tokens.size >= 2 and @tokens[-2][1] == :on_kw and ['begin', 'else', 'ensure'].include?(@tokens[-2][2])
+ elsif tokens.size >= 2 and tokens[-2][1] == :on_kw and ['begin', 'else', 'ensure'].include?(tokens[-2][2])
return false
- elsif !@tokens.empty? and @tokens.last[2] == "\\\n"
+ elsif !tokens.empty? and tokens.last[2] == "\\\n"
return true
- elsif @tokens.size >= 1 and @tokens[-1][1] == :on_heredoc_end # "EOH\n"
+ elsif tokens.size >= 1 and tokens[-1][1] == :on_heredoc_end # "EOH\n"
return false
- elsif @tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and @tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME)
+ elsif tokens.size >= 2 and defined?(Ripper::EXPR_BEG) and tokens[-2][3].anybits?(Ripper::EXPR_BEG | Ripper::EXPR_FNAME) and tokens[-2][2] !~ /\A\.\.\.?\z/
# end of literal except for regexp
+ # endless range at end of line is not a continue
return true
end
false
end
- def check_code_block(code)
- return true if @tokens.empty?
- if @tokens.last[1] == :on_heredoc_beg
+ def check_code_block(code, tokens = @tokens)
+ return true if tokens.empty?
+ if tokens.last[1] == :on_heredoc_beg
return true
end
begin # check if parser error are available
verbose, $VERBOSE = $VERBOSE, nil
case RUBY_ENGINE
+ when 'ruby'
+ self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
+ RubyVM::InstructionSequence.compile(inner_code, nil, nil, line_no)
+ end
when 'jruby'
JRuby.compile_ir(code)
else
- self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
- RubyVM::InstructionSequence.compile(inner_code, nil, nil, line_no)
+ catch(:valid) do
+ eval("BEGIN { throw :valid, true }\n#{code}")
+ false
end
end
rescue EncodingError
@@ -282,7 +373,7 @@ class RubyLex
end
if defined?(Ripper::EXPR_BEG)
- last_lex_state = @tokens.last[3]
+ last_lex_state = tokens.last[3]
if last_lex_state.allbits?(Ripper::EXPR_BEG)
return false
elsif last_lex_state.allbits?(Ripper::EXPR_DOT)
@@ -301,10 +392,10 @@ class RubyLex
false
end
- def process_nesting_level
+ def process_nesting_level(tokens = @tokens)
indent = 0
in_oneliner_def = nil
- @tokens.each_with_index { |t, index|
+ tokens.each_with_index { |t, index|
# detecting one-liner method definition
if in_oneliner_def.nil?
if t[3].allbits?(Ripper::EXPR_ENDFN)
@@ -317,14 +408,12 @@ class RubyLex
if t[2] == '='
in_oneliner_def = :BODY
end
- elsif t[3].allbits?(Ripper::EXPR_END)
+ else
if in_oneliner_def == :BODY
# one-liner method definition
indent -= 1
end
in_oneliner_def = nil
- else
- in_oneliner_def = nil
end
end
@@ -334,17 +423,11 @@ class RubyLex
when :on_rbracket, :on_rbrace, :on_rparen
indent -= 1
when :on_kw
- next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
+ next if index > 0 and tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
case t[2]
when 'do'
- if index > 0 and @tokens[index - 1][3].anybits?(Ripper::EXPR_CMDARG | Ripper::EXPR_ENDFN | Ripper::EXPR_ARG)
- # method_with_block do; end
- indent += 1
- else
- # while cond do; end # also "until" or "for"
- # This "do" doesn't increment indent because "while" already
- # incremented.
- end
+ syntax_of_do = take_corresponding_syntax_to_kw_do(tokens, index)
+ indent += 1 if syntax_of_do == :method_calling
when 'def', 'case', 'for', 'begin', 'class', 'module'
indent += 1
when 'if', 'unless', 'while', 'until'
@@ -359,6 +442,83 @@ class RubyLex
indent
end
+ def is_method_calling?(tokens, index)
+ tk = tokens[index]
+ if tk[3].anybits?(Ripper::EXPR_CMDARG) and tk[1] == :on_ident
+ # The target method call to pass the block with "do".
+ return true
+ elsif tk[3].anybits?(Ripper::EXPR_ARG) and tk[1] == :on_ident
+ non_sp_index = tokens[0..(index - 1)].rindex{ |t| t[1] != :on_sp }
+ if non_sp_index
+ prev_tk = tokens[non_sp_index]
+ if prev_tk[3].anybits?(Ripper::EXPR_DOT) and prev_tk[1] == :on_period
+ # The target method call with receiver to pass the block with "do".
+ return true
+ end
+ end
+ end
+ false
+ end
+
+ def take_corresponding_syntax_to_kw_do(tokens, index)
+ syntax_of_do = nil
+ # Finding a syntax correnponding to "do".
+ index.downto(0) do |i|
+ tk = tokens[i]
+ # In "continue", the token isn't the corresponding syntax to "do".
+ non_sp_index = tokens[0..(i - 1)].rindex{ |t| t[1] != :on_sp }
+ first_in_fomula = false
+ if non_sp_index.nil?
+ first_in_fomula = true
+ elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index][1])
+ first_in_fomula = true
+ end
+ if is_method_calling?(tokens, i)
+ syntax_of_do = :method_calling
+ break if first_in_fomula
+ elsif tk[1] == :on_kw && %w{while until for}.include?(tk[2])
+ # A loop syntax in front of "do" found.
+ #
+ # while cond do # also "until" or "for"
+ # end
+ #
+ # This "do" doesn't increment indent because the loop syntax already
+ # incremented.
+ syntax_of_do = :loop_syntax
+ break if first_in_fomula
+ end
+ end
+ syntax_of_do
+ end
+
+ def is_the_in_correspond_to_a_for(tokens, index)
+ syntax_of_in = nil
+ # Finding a syntax correnponding to "do".
+ index.downto(0) do |i|
+ tk = tokens[i]
+ # In "continue", the token isn't the corresponding syntax to "do".
+ non_sp_index = tokens[0..(i - 1)].rindex{ |t| t[1] != :on_sp }
+ first_in_fomula = false
+ if non_sp_index.nil?
+ first_in_fomula = true
+ elsif [:on_ignored_nl, :on_nl, :on_comment].include?(tokens[non_sp_index][1])
+ first_in_fomula = true
+ end
+ if tk[1] == :on_kw && tk[2] == 'for'
+ # A loop syntax in front of "do" found.
+ #
+ # while cond do # also "until" or "for"
+ # end
+ #
+ # This "do" doesn't increment indent because the loop syntax already
+ # incremented.
+ syntax_of_in = :for
+ end
+ break if first_in_fomula
+ end
+ syntax_of_in
+ end
+
def check_newline_depth_difference
depth_difference = 0
open_brace_on_line = 0
@@ -376,20 +536,18 @@ class RubyLex
if t[2] == '='
in_oneliner_def = :BODY
end
- elsif t[3].allbits?(Ripper::EXPR_END)
+ else
if in_oneliner_def == :BODY
- # one[-liner method definition
+ # one-liner method definition
depth_difference -= 1
end
in_oneliner_def = nil
- else
- in_oneliner_def = nil
end
end
case t[1]
when :on_ignored_nl, :on_nl, :on_comment
- if index != (@tokens.size - 1)
+ if index != (@tokens.size - 1) and in_oneliner_def != :BODY
depth_difference = 0
open_brace_on_line = 0
end
@@ -407,14 +565,8 @@ class RubyLex
next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
case t[2]
when 'do'
- if index > 0 and @tokens[index - 1][3].anybits?(Ripper::EXPR_CMDARG | Ripper::EXPR_ENDFN | Ripper::EXPR_ARG)
- # method_with_block do; end
- depth_difference += 1
- else
- # while cond do; end # also "until" or "for"
- # This "do" doesn't increment indent because "while" already
- # incremented.
- end
+ syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
+ depth_difference += 1 if syntax_of_do == :method_calling
when 'def', 'case', 'for', 'begin', 'class', 'module'
depth_difference += 1
when 'if', 'unless', 'while', 'until', 'rescue'
@@ -422,8 +574,14 @@ class RubyLex
unless t[3].allbits?(Ripper::EXPR_LABEL)
depth_difference += 1
end
- when 'else', 'elsif', 'ensure', 'when', 'in'
+ when 'else', 'elsif', 'ensure', 'when'
depth_difference += 1
+ when 'in'
+ unless is_the_in_correspond_to_a_for(@tokens, index)
+ depth_difference += 1
+ end
+ when 'end'
+ depth_difference -= 1
end
end
end
@@ -451,7 +609,7 @@ class RubyLex
if t[2] == '='
in_oneliner_def = :BODY
end
- elsif t[3].allbits?(Ripper::EXPR_END)
+ else
if in_oneliner_def == :BODY
# one-liner method definition
if is_first_printable_of_line
@@ -462,18 +620,18 @@ class RubyLex
end
end
in_oneliner_def = nil
- else
- in_oneliner_def = nil
end
end
case t[1]
when :on_ignored_nl, :on_nl, :on_comment
- corresponding_token_depth = nil
- spaces_at_line_head = 0
- is_first_spaces_of_line = true
- is_first_printable_of_line = true
- open_brace_on_line = 0
+ if in_oneliner_def != :BODY
+ corresponding_token_depth = nil
+ spaces_at_line_head = 0
+ is_first_spaces_of_line = true
+ is_first_printable_of_line = true
+ open_brace_on_line = 0
+ end
next
when :on_sp
spaces_at_line_head = t[2].count(' ') if is_first_spaces_of_line
@@ -495,7 +653,12 @@ class RubyLex
when :on_kw
next if index > 0 and @tokens[index - 1][3].allbits?(Ripper::EXPR_FNAME)
case t[2]
- when 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
+ when 'do'
+ syntax_of_do = take_corresponding_syntax_to_kw_do(@tokens, index)
+ if syntax_of_do == :method_calling
+ spaces_of_nest.push(spaces_at_line_head)
+ end
+ when 'def', 'case', 'for', 'begin', 'class', 'module'
spaces_of_nest.push(spaces_at_line_head)
when 'rescue'
unless t[3].allbits?(Ripper::EXPR_LABEL)
@@ -523,12 +686,12 @@ class RubyLex
corresponding_token_depth
end
- def check_string_literal
+ def check_string_literal(tokens)
i = 0
start_token = []
end_type = []
- while i < @tokens.size
- t = @tokens[i]
+ while i < tokens.size
+ t = tokens[i]
case t[1]
when :on_tstring_beg
start_token << t
@@ -538,7 +701,7 @@ class RubyLex
end_type << :on_regexp_end
when :on_symbeg
acceptable_single_tokens = %i{on_ident on_const on_op on_cvar on_ivar on_gvar on_kw}
- if (i + 1) < @tokens.size and acceptable_single_tokens.all?{ |t| @tokens[i + 1][1] != t }
+ if (i + 1) < tokens.size and acceptable_single_tokens.all?{ |st| tokens[i + 1][1] != st }
start_token << t
end_type << :on_tstring_end
end
@@ -560,8 +723,8 @@ class RubyLex
start_token.last.nil? ? '' : start_token.last
end
- def process_literal_type
- start_token = check_string_literal
+ def process_literal_type(tokens = @tokens)
+ start_token = check_string_literal(tokens)
case start_token[1]
when :on_tstring_beg
case start_token[2]
@@ -590,5 +753,50 @@ class RubyLex
nil
end
end
+
+ def check_termination_in_prev_line(code)
+ tokens = self.class.ripper_lex_without_warning(code)
+ past_first_newline = false
+ index = tokens.rindex do |t|
+ # traverse first token before last line
+ if past_first_newline
+ if t.tok.include?("\n")
+ true
+ end
+ elsif t.tok.include?("\n")
+ past_first_newline = true
+ false
+ else
+ false
+ end
+ end
+ if index
+ first_token = nil
+ last_line_tokens = tokens[(index + 1)..(tokens.size - 1)]
+ last_line_tokens.each do |t|
+ unless [:on_sp, :on_ignored_sp, :on_comment].include?(t.event)
+ first_token = t
+ break
+ end
+ end
+ if first_token.nil?
+ return false
+ elsif first_token && first_token.state == Ripper::EXPR_DOT
+ return false
+ else
+ tokens_without_last_line = tokens[0..index]
+ ltype = process_literal_type(tokens_without_last_line)
+ indent = process_nesting_level(tokens_without_last_line)
+ continue = process_continue(tokens_without_last_line)
+ code_block_open = check_code_block(tokens_without_last_line.map(&:tok).join(''), tokens_without_last_line)
+ if ltype or indent > 0 or continue or code_block_open
+ return false
+ else
+ return last_line_tokens.map(&:tok).join('')
+ end
+ end
+ end
+ false
+ end
end
# :startdoc:
diff --git a/lib/irb/version.rb b/lib/irb/version.rb
index 8b61eb3ef9..0014bdda74 100644
--- a/lib/irb/version.rb
+++ b/lib/irb/version.rb
@@ -11,7 +11,7 @@
#
module IRB # :nodoc:
- VERSION = "1.2.6"
+ VERSION = "1.3.5"
@RELEASE_VERSION = VERSION
- @LAST_UPDATE_DATE = "2020-09-14"
+ @LAST_UPDATE_DATE = "2021-04-03"
end
diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb
index 794a511521..78d434d106 100644
--- a/lib/irb/workspace.rb
+++ b/lib/irb/workspace.rb
@@ -51,11 +51,13 @@ EOF
end
@binding = BINDING_QUEUE.pop
- when 3 # binding in function on TOPLEVEL_BINDING(default)
- @binding = eval("self.class.send(:remove_method, :irb_binding) if defined?(irb_binding); private; def irb_binding; binding; end; irb_binding",
+ when 3 # binding in function on TOPLEVEL_BINDING
+ @binding = eval("self.class.remove_method(:irb_binding) if defined?(irb_binding); private; def irb_binding; binding; end; irb_binding",
TOPLEVEL_BINDING,
__FILE__,
__LINE__ - 3)
+ when 4 # binding is a copy of TOPLEVEL_BINDING (default)
+ @binding = TOPLEVEL_BINDING.dup
end
end
@@ -126,6 +128,7 @@ EOF
def filter_backtrace(bt)
return nil if bt =~ /\/irb\/.*\.rb/
return nil if bt =~ /\/irb\.rb/
+ return nil if bt =~ /tool\/lib\/.*\.rb|runner\.rb/ # for tests in Ruby repository
case IRB.conf[:CONTEXT_MODE]
when 1
return nil if bt =~ %r!/tmp/irb-binding!
@@ -172,7 +175,7 @@ EOF
body = (start_pos..end_pos).map do |current_pos|
sprintf(fmt, pos == current_pos ? '=>' : '', current_pos + 1, lines[current_pos])
end.join("")
- "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear}\n"
+ "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear if use_colorize}\n"
end
def IRB.delete_caller
diff --git a/lib/logger.rb b/lib/logger.rb
index f0b99f75a2..5e88574aa5 100644
--- a/lib/logger.rb
+++ b/lib/logger.rb
@@ -349,8 +349,9 @@ class Logger
# === Args
#
# +logdev+::
- # The log device. This is a filename (String) or IO object (typically
- # +STDOUT+, +STDERR+, or an open file).
+ # The log device. This is a filename (String), IO object (typically
+ # +STDOUT+, +STDERR+, or an open file), +nil+ (it writes nothing) or
+ # +File::NULL+ (same as +nil+).
# +shift_age+::
# Number of old log files to keep, *or* frequency of rotation (+daily+,
# +weekly+ or +monthly+). Default value is 0, which disables log file
@@ -385,7 +386,7 @@ class Logger
self.datetime_format = datetime_format
self.formatter = formatter
@logdev = nil
- if logdev
+ if logdev && logdev != File::NULL
@logdev = LogDevice.new(logdev, shift_age: shift_age,
shift_size: shift_size,
shift_period_suffix: shift_period_suffix,
@@ -410,7 +411,7 @@ class Logger
# Reopen a log device.
#
def reopen(logdev = nil)
- @logdev.reopen(logdev)
+ @logdev&.reopen(logdev)
self
end
diff --git a/lib/logger/formatter.rb b/lib/logger/formatter.rb
index 852cffe033..6a135b6fab 100644
--- a/lib/logger/formatter.rb
+++ b/lib/logger/formatter.rb
@@ -12,7 +12,7 @@ class Logger
end
def call(severity, time, progname, msg)
- Format % [severity[0..0], format_datetime(time), $$, severity, progname,
+ Format % [severity[0..0], format_datetime(time), Process.pid, severity, progname,
msg2str(msg)]
end
diff --git a/lib/logger/log_device.rb b/lib/logger/log_device.rb
index fe7d54fb81..96d77b7b6a 100644
--- a/lib/logger/log_device.rb
+++ b/lib/logger/log_device.rb
@@ -135,7 +135,7 @@ class Logger
end
end
- if /mswin|mingw/ =~ RUBY_PLATFORM
+ if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
def lock_shift_log
yield
end
diff --git a/lib/logger/logger.gemspec b/lib/logger/logger.gemspec
index 8b3f70627a..cd6d97de3d 100644
--- a/lib/logger/logger.gemspec
+++ b/lib/logger/logger.gemspec
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
spec.summary = %q{Provides a simple logging utility for outputting messages.}
spec.description = %q{Provides a simple logging utility for outputting messages.}
spec.homepage = "https://github.com/ruby/logger"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec"]
spec.bindir = "exe"
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
spec.required_ruby_version = ">= 2.3.0"
spec.add_development_dependency "bundler", ">= 0"
- spec.add_development_dependency "rake", "~> 10.0"
+ spec.add_development_dependency "rake", ">= 12.3.3"
spec.add_development_dependency "test-unit"
spec.add_development_dependency "rdoc"
end
diff --git a/lib/logger/version.rb b/lib/logger/version.rb
index f90ce94e49..e0f71830d2 100644
--- a/lib/logger/version.rb
+++ b/lib/logger/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class Logger
- VERSION = "1.4.2"
+ VERSION = "1.4.3"
end
diff --git a/lib/matrix.rb b/lib/matrix.rb
index fc0e8ef2f7..32f1e233ce 100644
--- a/lib/matrix.rb
+++ b/lib/matrix.rb
@@ -38,7 +38,7 @@ module ExceptionForMatrix # :nodoc:
class ErrOperationNotDefined < StandardError
def initialize(vals)
if vals.is_a?(Array)
- super("Operation(#{vals[0]}) can\\'t be defined: #{vals[1]} op #{vals[2]}")
+ super("Operation(#{vals[0]}) can't be defined: #{vals[1]} op #{vals[2]}")
else
super(vals)
end
@@ -72,8 +72,8 @@ class Matrix
#
# Creates a matrix where each argument is a row.
# Matrix[ [25, 93], [-1, 66] ]
- # => 25 93
- # -1 66
+ # # => 25 93
+ # # -1 66
#
def Matrix.[](*rows)
rows(rows, false)
@@ -84,8 +84,8 @@ class Matrix
# of the matrix. If the optional argument +copy+ is false, use the given
# arrays as the internal structure of the matrix without copying.
# Matrix.rows([[25, 93], [-1, 66]])
- # => 25 93
- # -1 66
+ # # => 25 93
+ # # -1 66
#
def Matrix.rows(rows, copy = true)
rows = convert_to_array(rows, copy)
@@ -102,8 +102,8 @@ class Matrix
#
# Creates a matrix using +columns+ as an array of column vectors.
# Matrix.columns([[25, 93], [-1, 66]])
- # => 25 -1
- # 93 66
+ # # => 25 -1
+ # # 93 66
#
def Matrix.columns(columns)
rows(columns, false).transpose
@@ -116,9 +116,9 @@ class Matrix
# Returns an enumerator if no block is given.
#
# m = Matrix.build(2, 4) {|row, col| col - row }
- # => Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]]
+ # # => Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]]
# m = Matrix.build(3) { rand }
- # => a 3x3 matrix with random elements
+ # # => a 3x3 matrix with random elements
#
def Matrix.build(row_count, column_count = row_count)
row_count = CoercionHelper.coerce_to_int(row_count)
@@ -136,9 +136,9 @@ class Matrix
#
# Creates a matrix where the diagonal elements are composed of +values+.
# Matrix.diagonal(9, 5, -3)
- # => 9 0 0
- # 0 5 0
- # 0 0 -3
+ # # => 9 0 0
+ # # 0 5 0
+ # # 0 0 -3
#
def Matrix.diagonal(*values)
size = values.size
@@ -155,8 +155,8 @@ class Matrix
# Creates an +n+ by +n+ diagonal matrix where each diagonal element is
# +value+.
# Matrix.scalar(2, 5)
- # => 5 0
- # 0 5
+ # # => 5 0
+ # # 0 5
#
def Matrix.scalar(n, value)
diagonal(*Array.new(n, value))
@@ -165,8 +165,8 @@ class Matrix
#
# Creates an +n+ by +n+ identity matrix.
# Matrix.identity(2)
- # => 1 0
- # 0 1
+ # # => 1 0
+ # # 0 1
#
def Matrix.identity(n)
scalar(n, 1)
@@ -179,8 +179,8 @@ class Matrix
#
# Creates a zero matrix.
# Matrix.zero(2)
- # => 0 0
- # 0 0
+ # # => 0 0
+ # # 0 0
#
def Matrix.zero(row_count, column_count = row_count)
rows = Array.new(row_count){Array.new(column_count, 0)}
@@ -191,7 +191,7 @@ class Matrix
# Creates a single-row matrix where the values of that row are as given in
# +row+.
# Matrix.row_vector([4,5,6])
- # => 4 5 6
+ # # => 4 5 6
#
def Matrix.row_vector(row)
row = convert_to_array(row)
@@ -202,9 +202,9 @@ class Matrix
# Creates a single-column matrix where the values of that column are as given
# in +column+.
# Matrix.column_vector([4,5,6])
- # => 4
- # 5
- # 6
+ # # => 4
+ # # 5
+ # # 6
#
def Matrix.column_vector(column)
column = convert_to_array(column)
@@ -217,12 +217,12 @@ class Matrix
#
# m = Matrix.empty(2, 0)
# m == Matrix[ [], [] ]
- # => true
+ # # => true
# n = Matrix.empty(0, 3)
# n == Matrix.columns([ [], [], [] ])
- # => true
+ # # => true
# m * n
- # => Matrix[[0, 0, 0], [0, 0, 0]]
+ # # => Matrix[[0, 0, 0], [0, 0, 0]]
#
def Matrix.empty(row_count = 0, column_count = 0)
raise ArgumentError, "One size must be 0" if column_count != 0 && row_count != 0
@@ -276,6 +276,8 @@ class Matrix
new result, total_column_count
end
+ # :call-seq:
+ # Matrix.combine(*matrices) { |*elements| ... }
#
# Create a matrix by combining matrices entrywise, using the given block
#
@@ -301,12 +303,21 @@ class Matrix
new rows, x.column_count
end
+ # :call-seq:
+ # combine(*other_matrices) { |*elements| ... }
+ #
+ # Creates new matrix by combining with <i>other_matrices</i> entrywise,
+ # using the given block.
+ #
+ # x = Matrix[[6, 6], [4, 4]]
+ # y = Matrix[[1, 2], [3, 4]]
+ # x.combine(y) {|a, b| a - b} # => Matrix[[5, 4], [1, 0]]
def combine(*matrices, &block)
Matrix.combine(self, *matrices, &block)
end
#
- # Matrix.new is private; use Matrix.rows, columns, [], etc... to create.
+ # Matrix.new is private; use ::rows, ::columns, ::[], etc... to create.
#
def initialize(rows, column_count = rows[0].size)
# No checking is done at this point. rows must be an Array of Arrays.
@@ -491,8 +502,8 @@ class Matrix
# * :strict_upper: yields only elements above the diagonal
# * :upper: yields only elements on or above the diagonal
# Matrix[ [1,2], [3,4] ].collect { |e| e**2 }
- # => 1 4
- # 9 16
+ # # => 1 4
+ # # 9 16
#
def collect(which = :all, &block) # :yield: e
return to_enum(:collect, which) unless block_given?
@@ -521,7 +532,8 @@ class Matrix
alias map! collect!
def freeze
- @rows.freeze
+ @rows.each(&:freeze).freeze
+
super
end
@@ -537,9 +549,9 @@ class Matrix
# * :strict_upper: yields only elements above the diagonal
# * :upper: yields only elements on or above the diagonal
#
- # Matrix[ [1,2], [3,4] ].each { |e| puts e }
- # # => prints the numbers 1 to 4
- # Matrix[ [1,2], [3,4] ].each(:strict_lower).to_a # => [3]
+ # Matrix[ [1,2], [3,4] ].each { |e| puts e }
+ # # => prints the numbers 1 to 4
+ # Matrix[ [1,2], [3,4] ].each(:strict_lower).to_a # => [3]
#
def each(which = :all, &block) # :yield: e
return to_enum :each, which unless block_given?
@@ -688,8 +700,8 @@ class Matrix
# * row_range, col_range
#
# Matrix.diagonal(9, 5, -3).minor(0..1, 0..2)
- # => 9 0 0
- # 0 5 0
+ # # => 9 0 0
+ # # 0 5 0
#
# Like Array#[], negative indices count backward from the end of the
# row or column (-1 is the last element). Returns nil if the starting
@@ -732,9 +744,9 @@ class Matrix
# Returns the submatrix obtained by deleting the specified row and column.
#
# Matrix.diagonal(9, 5, -3, 4).first_minor(1, 2)
- # => 9 0 0
- # 0 0 0
- # 0 0 4
+ # # => 9 0 0
+ # # 0 0 0
+ # # 0 0 4
#
def first_minor(row, column)
raise RuntimeError, "first_minor of empty matrix is not defined" if empty?
@@ -761,7 +773,7 @@ class Matrix
# the first minor by (-1)**(row + column).
#
# Matrix.diagonal(9, 5, -3, 4).cofactor(1, 1)
- # => -108
+ # # => -108
#
def cofactor(row, column)
raise RuntimeError, "cofactor of empty matrix is not defined" if empty?
@@ -775,8 +787,8 @@ class Matrix
# Returns the adjugate of the matrix.
#
# Matrix[ [7,6],[3,9] ].adjugate
- # => 9 -6
- # -3 7
+ # # => 9 -6
+ # # -3 7
#
def adjugate
raise ErrDimensionMismatch unless square?
@@ -789,10 +801,10 @@ class Matrix
# Returns the Laplace expansion along given row or column.
#
# Matrix[[7,6], [3,9]].laplace_expansion(column: 1)
- # => 45
+ # # => 45
#
# Matrix[[Vector[1, 0], Vector[0, 1]], [2, 3]].laplace_expansion(row: 0)
- # => Vector[3, -2]
+ # # => Vector[3, -2]
#
#
def laplace_expansion(row: nil, column: nil)
@@ -879,11 +891,12 @@ class Matrix
#
def orthogonal?
raise ErrDimensionMismatch unless square?
- rows.each_with_index do |row, i|
- column_count.times do |j|
+
+ rows.each_with_index do |row_i, i|
+ rows.each_with_index do |row_j, j|
s = 0
row_count.times do |k|
- s += row[k] * rows[k][j]
+ s += row_i[k] * row_j[k]
end
return false unless s == (i == j ? 1 : 0)
end
@@ -972,11 +985,11 @@ class Matrix
#
def unitary?
raise ErrDimensionMismatch unless square?
- rows.each_with_index do |row, i|
- column_count.times do |j|
+ rows.each_with_index do |row_i, i|
+ rows.each_with_index do |row_j, j|
s = 0
row_count.times do |k|
- s += row[k].conj * rows[k][j]
+ s += row_i[k].conj * row_j[k]
end
return false unless s == (i == j ? 1 : 0)
end
@@ -1039,31 +1052,33 @@ class Matrix
#
# Matrix multiplication.
# Matrix[[2,4], [6,8]] * Matrix.identity(2)
- # => 2 4
- # 6 8
+ # # => 2 4
+ # # 6 8
#
def *(m) # m is matrix or vector or number
case(m)
when Numeric
- rows = @rows.collect {|row|
+ new_rows = @rows.collect {|row|
row.collect {|e| e * m }
}
- return new_matrix rows, column_count
+ return new_matrix new_rows, column_count
when Vector
m = self.class.column_vector(m)
r = self * m
return r.column(0)
when Matrix
raise ErrDimensionMismatch if column_count != m.row_count
-
- rows = Array.new(row_count) {|i|
- Array.new(m.column_count) {|j|
- (0 ... column_count).inject(0) do |vij, k|
- vij + self[i, k] * m[k, j]
+ m_rows = m.rows
+ new_rows = rows.map do |row_i|
+ Array.new(m.column_count) do |j|
+ vij = 0
+ column_count.times do |k|
+ vij += row_i[k] * m_rows[k][j]
end
- }
- }
- return new_matrix rows, m.column_count
+ vij
+ end
+ end
+ return new_matrix new_rows, m.column_count
else
return apply_through_coercion(m, __method__)
end
@@ -1072,8 +1087,8 @@ class Matrix
#
# Matrix addition.
# Matrix.scalar(2,5) + Matrix[[1,0], [-4,7]]
- # => 6 0
- # -4 12
+ # # => 6 0
+ # # -4 12
#
def +(m)
case m
@@ -1099,8 +1114,8 @@ class Matrix
#
# Matrix subtraction.
# Matrix[[1,5], [4,2]] - Matrix[[9,3], [-4,1]]
- # => -8 2
- # 8 1
+ # # => -8 2
+ # # 8 1
#
def -(m)
case m
@@ -1126,8 +1141,8 @@ class Matrix
#
# Matrix division (multiplication by the inverse).
# Matrix[[7,6], [3,9]] / Matrix[[2,9], [3,1]]
- # => -7 1
- # -3 -6
+ # # => -7 1
+ # # -3 -6
#
def /(other)
case other
@@ -1146,8 +1161,8 @@ class Matrix
#
# Hadamard product
# Matrix[[1,2], [3,4]].hadamard_product(Matrix[[1,2], [3,2]])
- # => 1 4
- # 9 8
+ # # => 1 4
+ # # 9 8
#
def hadamard_product(m)
combine(m){|a, b| a * b}
@@ -1157,8 +1172,8 @@ class Matrix
#
# Returns the inverse of the matrix.
# Matrix[[-1, -1], [0, -1]].inverse
- # => -1 1
- # 0 -1
+ # # => -1 1
+ # # 0 -1
#
def inverse
raise ErrDimensionMismatch unless square?
@@ -1216,29 +1231,52 @@ class Matrix
# Non integer exponents will be handled by diagonalizing the matrix.
#
# Matrix[[7,6], [3,9]] ** 2
- # => 67 96
- # 48 99
+ # # => 67 96
+ # # 48 99
#
- def **(other)
- case other
+ def **(exp)
+ case exp
when Integer
- x = self
- if other <= 0
- x = self.inverse
- return self.class.identity(self.column_count) if other == 0
- other = -other
- end
- z = nil
- loop do
- z = z ? z * x : x if other[0] == 1
- return z if (other >>= 1).zero?
- x *= x
+ case
+ when exp == 0
+ _make_sure_it_is_invertible = inverse
+ self.class.identity(column_count)
+ when exp < 0
+ inverse.power_int(-exp)
+ else
+ power_int(exp)
end
when Numeric
v, d, v_inv = eigensystem
- v * self.class.diagonal(*d.each(:diagonal).map{|e| e ** other}) * v_inv
+ v * self.class.diagonal(*d.each(:diagonal).map{|e| e ** exp}) * v_inv
+ else
+ raise ErrOperationNotDefined, ["**", self.class, exp.class]
+ end
+ end
+
+ protected def power_int(exp)
+ # assumes `exp` is an Integer > 0
+ #
+ # Previous algorithm:
+ # build M**2, M**4 = (M**2)**2, M**8, ... and multiplying those you need
+ # e.g. M**0b1011 = M**11 = M * M**2 * M**8
+ # ^ ^
+ # (highlighted the 2 out of 5 multiplications involving `M * x`)
+ #
+ # Current algorithm has same number of multiplications but with lower exponents:
+ # M**11 = M * (M * M**4)**2
+ # ^ ^ ^
+ # (highlighted the 3 out of 5 multiplications involving `M * x`)
+ #
+ # This should be faster for all (non nil-potent) matrices.
+ case
+ when exp == 1
+ self
+ when exp.odd?
+ self * power_int(exp - 1)
else
- raise ErrOperationNotDefined, ["**", self.class, other.class]
+ sqrt = power_int(exp / 2)
+ sqrt * sqrt
end
end
@@ -1246,6 +1284,11 @@ class Matrix
self
end
+ # Unary matrix negation.
+ #
+ # -Matrix[[1,5], [4,2]]
+ # # => -1 -5
+ # # -4 -2
def -@
collect {|e| -e }
end
@@ -1269,7 +1312,7 @@ class Matrix
# Consider using exact types like Rational or BigDecimal instead.
#
# Matrix[[7,6], [3,9]].determinant
- # => 45
+ # # => 45
#
def determinant
raise ErrDimensionMismatch unless square?
@@ -1377,7 +1420,7 @@ class Matrix
# Consider using exact types like Rational or BigDecimal instead.
#
# Matrix[[7,6], [3,9]].rank
- # => 2
+ # # => 2
#
def rank
# We currently use Bareiss' multistep integer-preserving gaussian elimination
@@ -1425,7 +1468,7 @@ class Matrix
#
# Returns the trace (sum of diagonal elements) of the matrix.
# Matrix[[7,6], [3,9]].trace
- # => 16
+ # # => 16
#
def trace
raise ErrDimensionMismatch unless square?
@@ -1438,12 +1481,12 @@ class Matrix
#
# Returns the transpose of the matrix.
# Matrix[[1,2], [3,4], [5,6]]
- # => 1 2
- # 3 4
- # 5 6
+ # # => 1 2
+ # # 3 4
+ # # 5 6
# Matrix[[1,2], [3,4], [5,6]].transpose
- # => 1 3 5
- # 2 4 6
+ # # => 1 3 5
+ # # 2 4 6
#
def transpose
return self.class.empty(column_count, 0) if row_count.zero?
@@ -1502,11 +1545,11 @@ class Matrix
#
# Returns the conjugate of the matrix.
# Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
- # => 1+2i i 0
- # 1 2 3
+ # # => 1+2i i 0
+ # # 1 2 3
# Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].conjugate
- # => 1-2i -i 0
- # 1 2 3
+ # # => 1-2i -i 0
+ # # 1 2 3
#
def conjugate
collect(&:conjugate)
@@ -1514,13 +1557,24 @@ class Matrix
alias_method :conj, :conjugate
#
+ # Returns the adjoint of the matrix.
+ #
+ # Matrix[ [i,1],[2,-i] ].adjoint
+ # # => -i 2
+ # # 1 i
+ #
+ def adjoint
+ conjugate.transpose
+ end
+
+ #
# Returns the imaginary part of the matrix.
# Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
- # => 1+2i i 0
- # 1 2 3
+ # # => 1+2i i 0
+ # # 1 2 3
# Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].imaginary
- # => 2i i 0
- # 0 0 0
+ # # => 2i i 0
+ # # 0 0 0
#
def imaginary
collect(&:imaginary)
@@ -1530,11 +1584,11 @@ class Matrix
#
# Returns the real part of the matrix.
# Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]]
- # => 1+2i i 0
- # 1 2 3
+ # # => 1+2i i 0
+ # # 1 2 3
# Matrix[[Complex(1,2), Complex(0,1), 0], [1, 2, 3]].real
- # => 1 0 0
- # 1 2 3
+ # # => 1 0 0
+ # # 1 2 3
#
def real
collect(&:real)
@@ -1544,7 +1598,7 @@ class Matrix
# Returns an array containing matrices corresponding to the real and imaginary
# parts of the matrix
#
- # m.rect == [m.real, m.imag] # ==> true for all matrices m
+ # m.rect == [m.real, m.imag] # ==> true for all matrices m
#
def rect
[real, imag]
@@ -1605,7 +1659,7 @@ class Matrix
# Deprecated.
#
- # Use map(&:to_f)
+ # Use <code>map(&:to_f)</code>
def elements_to_f
warn "Matrix#elements_to_f is deprecated, use map(&:to_f)", uplevel: 1
map(&:to_f)
@@ -1613,7 +1667,7 @@ class Matrix
# Deprecated.
#
- # Use map(&:to_i)
+ # Use <code>map(&:to_i)</code>
def elements_to_i
warn "Matrix#elements_to_i is deprecated, use map(&:to_i)", uplevel: 1
map(&:to_i)
@@ -1621,7 +1675,7 @@ class Matrix
# Deprecated.
#
- # Use map(&:to_r)
+ # Use <code>map(&:to_r)</code>
def elements_to_r
warn "Matrix#elements_to_r is deprecated, use map(&:to_r)", uplevel: 1
map(&:to_r)
@@ -1857,8 +1911,8 @@ end
# * #-@
#
# Vector functions:
-# * #inner_product(v), dot(v)
-# * #cross_product(v), cross(v)
+# * #inner_product(v), #dot(v)
+# * #cross_product(v), #cross(v)
# * #collect
# * #collect!
# * #magnitude
@@ -1923,7 +1977,7 @@ class Vector
#
# Return a zero vector.
#
- # Vector.zero(3) => Vector[0, 0, 0]
+ # Vector.zero(3) # => Vector[0, 0, 0]
#
def Vector.zero(size)
raise ArgumentError, "invalid size (#{size} for 0..)" if size < 0
@@ -2054,10 +2108,10 @@ class Vector
# Returns +true+ iff all of vectors are linearly independent.
#
# Vector.independent?(Vector[1,0], Vector[0,1])
- # => true
+ # # => true
#
# Vector.independent?(Vector[1,2], Vector[2,4])
- # => false
+ # # => false
#
def Vector.independent?(*vs)
vs.each do |v|
@@ -2072,10 +2126,10 @@ class Vector
# Returns +true+ iff all of vectors are linearly independent.
#
# Vector[1,0].independent?(Vector[0,1])
- # => true
+ # # => true
#
# Vector[1,2].independent?(Vector[2,4])
- # => false
+ # # => false
#
def independent?(*vs)
self.class.independent?(self, *vs)
@@ -2088,6 +2142,9 @@ class Vector
all?(&:zero?)
end
+ #
+ # Makes the matrix frozen and Ractor-shareable
+ #
def freeze
@elements.freeze
super
@@ -2212,7 +2269,7 @@ class Vector
#
# Returns the inner product of this vector with the other.
- # Vector[4,7].inner_product Vector[10,1] => 47
+ # Vector[4,7].inner_product Vector[10,1] # => 47
#
def inner_product(v)
raise ErrDimensionMismatch if size != v.size
@@ -2227,7 +2284,7 @@ class Vector
#
# Returns the cross product of this vector with the others.
- # Vector[1, 0, 0].cross_product Vector[0, 1, 0] => Vector[0, 0, 1]
+ # Vector[1, 0, 0].cross_product Vector[0, 1, 0] # => Vector[0, 0, 1]
#
# It is generalized to other dimensions to return a vector perpendicular
# to the arguments.
@@ -2282,7 +2339,7 @@ class Vector
#
# Returns the modulus (Pythagorean distance) of the vector.
- # Vector[5,8,2].r => 9.643650761
+ # Vector[5,8,2].r # => 9.643650761
#
def magnitude
Math.sqrt(@elements.inject(0) {|v, e| v + e.abs2})
@@ -2305,7 +2362,7 @@ class Vector
# Returns a new vector with the same direction but with norm 1.
# v = Vector[5,8,2].normalize
# # => Vector[0.5184758473652127, 0.8295613557843402, 0.20739033894608505]
- # v.norm => 1.0
+ # v.norm # => 1.0
#
def normalize
n = magnitude
diff --git a/lib/matrix/matrix.gemspec b/lib/matrix/matrix.gemspec
index 75f6b69a98..d2ff9ce7c6 100644
--- a/lib/matrix/matrix.gemspec
+++ b/lib/matrix/matrix.gemspec
@@ -16,9 +16,10 @@ Gem::Specification.new do |spec|
spec.summary = %q{An implementation of Matrix and Vector classes.}
spec.description = %q{An implementation of Matrix and Vector classes.}
spec.homepage = "https://github.com/ruby/matrix"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = ">= 2.5.0"
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/matrix.rb", "lib/matrix/eigenvalue_decomposition.rb", "lib/matrix/lup_decomposition.rb", "lib/matrix/version.rb", "matrix.gemspec"]
+ spec.files = [".gitignore", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/matrix.rb", "lib/matrix/eigenvalue_decomposition.rb", "lib/matrix/lup_decomposition.rb", "lib/matrix/version.rb", "matrix.gemspec"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
diff --git a/lib/matrix/version.rb b/lib/matrix/version.rb
index e6f91dae3c..4a8bc36aaa 100644
--- a/lib/matrix/version.rb
+++ b/lib/matrix/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class Matrix
- VERSION = "0.2.0"
+ VERSION = "0.3.1"
end
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 27bc9e5986..9468a2c6c4 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -207,8 +207,8 @@ module MakeMakefile
['RUBYCOMMONDIR', '$(vendordir)$(target_prefix)'],
['RUBYLIBDIR', '$(vendorlibdir)$(target_prefix)'],
['RUBYARCHDIR', '$(vendorarchdir)$(target_prefix)'],
- ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
- ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
+ ['HDRDIR', '$(vendorhdrdir)$(target_prefix)'],
+ ['ARCHHDRDIR', '$(vendorarchhdrdir)$(target_prefix)'],
]
else
dirs = [
@@ -216,8 +216,8 @@ module MakeMakefile
['RUBYCOMMONDIR', '$(sitedir)$(target_prefix)'],
['RUBYLIBDIR', '$(sitelibdir)$(target_prefix)'],
['RUBYARCHDIR', '$(sitearchdir)$(target_prefix)'],
- ['HDRDIR', '$(rubyhdrdir)/ruby$(target_prefix)'],
- ['ARCHHDRDIR', '$(rubyhdrdir)/$(arch)/ruby$(target_prefix)'],
+ ['HDRDIR', '$(sitehdrdir)$(target_prefix)'],
+ ['ARCHHDRDIR', '$(sitearchhdrdir)$(target_prefix)'],
]
end
dirs << ['target_prefix', (target_prefix ? "/#{target_prefix}" : "")]
@@ -784,7 +784,7 @@ int main() {printf("%"PRI_CONFTEST_PREFIX"#{neg ? 'd' : 'u'}\\n", conftest_const
if opt and !opt.empty?
[[:to_str], [:join, " "], [:to_s]].each do |meth, *args|
if opt.respond_to?(meth)
- break opt = opt.send(meth, *args)
+ break opt = opt.__send__(meth, *args)
end
end
opt = "#{opt} #{libs}"
@@ -982,7 +982,7 @@ SRC
if noun
[[:to_str], [:join, ","], [:to_s]].each do |meth, *args|
if noun.respond_to?(meth)
- break noun = noun.send(meth, *args)
+ break noun = noun.__send__(meth, *args)
end
end
unless noun.empty?
@@ -1942,7 +1942,7 @@ NULLCMD = #{CONFIG['NULLCMD']}
srcdir = #{srcdir.gsub(/\$\((srcdir)\)|\$\{(srcdir)\}/) {mkintpath(CONFIG[$1||$2]).unspace}}
topdir = #{mkintpath(topdir = $extmk ? CONFIG["topdir"] : $topdir).unspace}
hdrdir = #{(hdrdir = CONFIG["hdrdir"]) == topdir ? "$(topdir)" : mkintpath(hdrdir).unspace}
-arch_hdrdir = #{$arch_hdrdir.quote}
+arch_hdrdir = #{mkintpath($arch_hdrdir).unspace}
PATH_SEPARATOR = #{CONFIG['PATH_SEPARATOR']}
VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
}
@@ -1970,7 +1970,7 @@ VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
else
sep = ""
end
- possible_command = (proc {|s| s if /top_srcdir/ !~ s} unless $extmk)
+ possible_command = (proc {|s| s if /top_srcdir|tooldir/ !~ s} unless $extmk)
extconf_h = $extconf_h ? "-DRUBY_EXTCONF_H=\\\"$(RUBY_EXTCONF_H)\\\" " : $defs.join(" ") << " "
headers = %w[
$(hdrdir)/ruby.h
@@ -2034,11 +2034,6 @@ sitearch = #{CONFIG['sitearch']}
ruby_version = #{RbConfig::CONFIG['ruby_version']}
ruby = #{$ruby.sub(%r[\A#{Regexp.quote(RbConfig::CONFIG['bindir'])}(?=/|\z)]) {'$(bindir)'}}
RUBY = $(ruby#{sep})
-BUILTRUBY = #{if defined?($builtruby) && $builtruby
- $builtruby
- else
- File.join('$(bindir)', CONFIG["RUBY_INSTALL_NAME"] + CONFIG['EXEEXT'])
- end}
ruby_headers = #{headers.join(' ')}
RM = #{config_string('RM', &possible_command) || '$(RUBY) -run -e rm -- -f'}
@@ -2227,7 +2222,7 @@ RULES
message "creating Makefile\n"
MakeMakefile.rm_f "#{CONFTEST}*"
if CONFIG["DLEXT"] == $OBJEXT
- for lib in libs = $libs.split
+ for lib in libs = $libs.split(' ')
lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
end
$defs.push(format("-DEXTLIB='%s'", libs.join(",")))
@@ -2557,7 +2552,6 @@ site-install-rb: install-rb
$INCFLAGS << " -I$(hdrdir)/ruby/backward" unless $extmk
$INCFLAGS << " -I$(hdrdir) -I$(srcdir)"
$DLDFLAGS = with_config("dldflags", arg_config("DLDFLAGS", config["DLDFLAGS"])).dup
- config_string("ADDITIONAL_DLDFLAGS") {|flags| $DLDFLAGS << " " << flags} unless $extmk
$LIBEXT = config['LIBEXT'].dup
$OBJEXT = config["OBJEXT"].dup
$EXEEXT = config["EXEEXT"].dup
@@ -2828,7 +2822,12 @@ realclean: distclean
end
end
-include MakeMakefile
+# MakeMakefile::Global = #
+m = Module.new {
+ include(MakeMakefile)
+ private(*MakeMakefile.public_instance_methods(false))
+}
+include m
if not $extmk and /\A(extconf|makefile).rb\z/ =~ File.basename($0)
END {mkmf_failed($0)}
diff --git a/lib/mutex_m.gemspec b/lib/mutex_m.gemspec
index 409ed5b7b2..f614dcd9a0 100644
--- a/lib/mutex_m.gemspec
+++ b/lib/mutex_m.gemspec
@@ -14,9 +14,9 @@ Gem::Specification.new do |spec|
spec.summary = %q{Mixin to extend objects to be handled like a Mutex.}
spec.description = %q{Mixin to extend objects to be handled like a Mutex.}
spec.homepage = "https://github.com/ruby/mutex_m"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/mutex_m.rb", "mutex_m.gemspec"]
+ spec.files = ["Gemfile", "LICENSE.txt", "README.md", "Rakefile", "lib/mutex_m.rb", "mutex_m.gemspec"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb
index dd47934bea..18b6256595 100644
--- a/lib/mutex_m.rb
+++ b/lib/mutex_m.rb
@@ -40,7 +40,7 @@
#
module Mutex_m
- VERSION = "0.1.0"
+ VERSION = "0.1.1"
def Mutex_m.define_aliases(cl) # :nodoc:
cl.module_eval %q{
@@ -113,4 +113,5 @@ module Mutex_m
mu_initialize
super
end
+ ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true)
end
diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb
index 1e078453a8..2161d30d7c 100644
--- a/lib/net/ftp.rb
+++ b/lib/net/ftp.rb
@@ -17,7 +17,7 @@
require "socket"
require "monitor"
-require_relative "protocol"
+require "net/protocol"
require "time"
begin
require "openssl"
@@ -85,6 +85,7 @@ module Net
end
# :stopdoc:
+ VERSION = "0.1.2"
FTP_PORT = 21
CRLF = "\r\n"
DEFAULT_BLOCKSIZE = BufferedIO::BUFSIZE
@@ -186,16 +187,16 @@ module Net
# The available options are:
#
# port:: Port number (default value is 21)
- # ssl:: If options[:ssl] is true, then an attempt will be made
+ # ssl:: If +options+[:ssl] is true, then an attempt will be made
# to use SSL (now TLS) to connect to the server. For this
# to work OpenSSL [OSSL] and the Ruby OpenSSL [RSSL]
- # extensions need to be installed. If options[:ssl] is a
+ # extensions need to be installed. If +options+[:ssl] is a
# hash, it's passed to OpenSSL::SSL::SSLContext#set_params
# as parameters.
# private_data_connection:: If true, TLS is used for data connections.
- # Default: +true+ when options[:ssl] is true.
- # username:: Username for login. If options[:username] is the string
- # "anonymous" and the options[:password] is +nil+,
+ # Default: +true+ when +options+[:ssl] is true.
+ # username:: Username for login. If +options+[:username] is the string
+ # "anonymous" and the +options+[:password] is +nil+,
# "anonymous@" is used as a password.
# password:: Password for login.
# account:: Account information for ACCT.
@@ -337,14 +338,19 @@ module Net
# SOCKS_SERVER, then a SOCKSSocket is returned, else a Socket is
# returned.
def open_socket(host, port) # :nodoc:
- return Timeout.timeout(@open_timeout, OpenTimeout) {
- if defined? SOCKSSocket and ENV["SOCKS_SERVER"]
- @passive = true
+ if defined? SOCKSSocket and ENV["SOCKS_SERVER"]
+ @passive = true
+ Timeout.timeout(@open_timeout, OpenTimeout) do
SOCKSSocket.open(host, port)
- else
- Socket.tcp(host, port)
end
- }
+ else
+ begin
+ Socket.tcp host, port, nil, nil, connect_timeout: @open_timeout
+ rescue Errno::ETIMEDOUT #raise Net:OpenTimeout instead for compatibility with previous versions
+ raise Net::OpenTimeout, "Timeout to open TCP connection to "\
+ "#{host}:#{port} (exceeds #{@open_timeout} seconds)"
+ end
+ end
end
private :open_socket
@@ -549,18 +555,22 @@ module Net
def transfercmd(cmd, rest_offset = nil) # :nodoc:
if @passive
host, port = makepasv
- conn = open_socket(host, port)
- if @resume and rest_offset
- resp = sendcmd("REST " + rest_offset.to_s)
- if !resp.start_with?("3")
+ begin
+ conn = open_socket(host, port)
+ if @resume and rest_offset
+ resp = sendcmd("REST " + rest_offset.to_s)
+ if !resp.start_with?("3")
+ raise FTPReplyError, resp
+ end
+ end
+ resp = sendcmd(cmd)
+ # skip 2XX for some ftp servers
+ resp = getresp if resp.start_with?("2")
+ if !resp.start_with?("1")
raise FTPReplyError, resp
end
- end
- resp = sendcmd(cmd)
- # skip 2XX for some ftp servers
- resp = getresp if resp.start_with?("2")
- if !resp.start_with?("1")
- raise FTPReplyError, resp
+ ensure
+ conn.close if conn && $!
end
else
sock = makeport
@@ -1052,11 +1062,12 @@ module Net
TIME_PARSER = ->(value, local = false) {
unless /\A(?<year>\d{4})(?<month>\d{2})(?<day>\d{2})
(?<hour>\d{2})(?<min>\d{2})(?<sec>\d{2})
- (\.(?<fractions>\d+))?/x =~ value
+ (?:\.(?<fractions>\d{1,17}))?/x =~ value
+ value = value[0, 97] + "..." if value.size > 100
raise FTPProtoError, "invalid time-val: #{value}"
end
- usec = fractions.to_i * 10 ** (6 - fractions.to_s.size)
- Time.send(local ? :local : :utc, year, month, day, hour, min, sec, usec)
+ usec = ".#{fractions}".to_r * 1_000_000 if fractions
+ Time.public_send(local ? :local : :utc, year, month, day, hour, min, sec, usec)
}
FACT_PARSERS = Hash.new(CASE_DEPENDENT_PARSER)
FACT_PARSERS["size"] = DECIMAL_PARSER
@@ -1363,7 +1374,7 @@ module Net
end
#
- # Returns +true+ iff the connection is closed.
+ # Returns +true+ if and only if the connection is closed.
#
def closed?
@sock == nil or @sock.closed?
@@ -1377,7 +1388,7 @@ module Net
if !resp.start_with?("227")
raise FTPReplyError, resp
end
- if m = /\((?<host>\d+(,\d+){3}),(?<port>\d+,\d+)\)/.match(resp)
+ if m = /\((?<host>\d+(?:,\d+){3}),(?<port>\d+,\d+)\)/.match(resp)
if @use_pasv_ip
host = parse_pasv_ipv4_host(m["host"])
else
@@ -1398,9 +1409,9 @@ module Net
if !resp.start_with?("228")
raise FTPReplyError, resp
end
- if m = /\(4,4,(?<host>\d+(,\d+){3}),2,(?<port>\d+,\d+)\)/.match(resp)
+ if m = /\(4,4,(?<host>\d+(?:,\d+){3}),2,(?<port>\d+,\d+)\)/.match(resp)
return parse_pasv_ipv4_host(m["host"]), parse_pasv_port(m["port"])
- elsif m = /\(6,16,(?<host>\d+(,(\d+)){15}),2,(?<port>\d+,\d+)\)/.match(resp)
+ elsif m = /\(6,16,(?<host>\d+(?:,\d+){15}),2,(?<port>\d+,\d+)\)/.match(resp)
return parse_pasv_ipv6_host(m["host"]), parse_pasv_port(m["port"])
else
raise FTPProtoError, resp
diff --git a/lib/net/http.rb b/lib/net/http.rb
index 88a174a248..34fc635a4d 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -20,7 +20,7 @@
# See Net::HTTP for an overview and examples.
#
-require_relative 'protocol'
+require 'net/protocol'
require 'uri'
autoload :OpenSSL, 'openssl'
@@ -388,6 +388,7 @@ module Net #:nodoc:
class HTTP < Protocol
# :stopdoc:
+ VERSION = "0.1.1"
Revision = %q$Revision$.split[1]
HTTPVersion = '1.1'
begin
@@ -427,7 +428,7 @@ module Net #:nodoc:
#
# Gets the body text from the target and outputs it to $stdout. The
# target can either be specified as
- # (+uri+), or as (+host+, +path+, +port+ = 80); so:
+ # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so:
#
# Net::HTTP.get_print URI('http://www.example.com/index.html')
#
@@ -435,8 +436,12 @@ module Net #:nodoc:
#
# Net::HTTP.get_print 'www.example.com', '/index.html'
#
- def HTTP.get_print(uri_or_host, path = nil, port = nil)
- get_response(uri_or_host, path, port) {|res|
+ # you can also specify request headers:
+ #
+ # Net::HTTP.get_print URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' }
+ #
+ def HTTP.get_print(uri_or_host, path_or_headers = nil, port = nil)
+ get_response(uri_or_host, path_or_headers, port) {|res|
res.read_body do |chunk|
$stdout.print chunk
end
@@ -446,7 +451,7 @@ module Net #:nodoc:
# Sends a GET request to the target and returns the HTTP response
# as a string. The target can either be specified as
- # (+uri+), or as (+host+, +path+, +port+ = 80); so:
+ # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so:
#
# print Net::HTTP.get(URI('http://www.example.com/index.html'))
#
@@ -454,13 +459,17 @@ module Net #:nodoc:
#
# print Net::HTTP.get('www.example.com', '/index.html')
#
- def HTTP.get(uri_or_host, path = nil, port = nil)
- get_response(uri_or_host, path, port).body
+ # you can also specify request headers:
+ #
+ # Net::HTTP.get(URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' })
+ #
+ def HTTP.get(uri_or_host, path_or_headers = nil, port = nil)
+ get_response(uri_or_host, path_or_headers, port).body
end
# Sends a GET request to the target and returns the HTTP response
# as a Net::HTTPResponse object. The target can either be specified as
- # (+uri+), or as (+host+, +path+, +port+ = 80); so:
+ # (+uri+, +headers+), or as (+host+, +path+, +port+ = 80); so:
#
# res = Net::HTTP.get_response(URI('http://www.example.com/index.html'))
# print res.body
@@ -470,17 +479,23 @@ module Net #:nodoc:
# res = Net::HTTP.get_response('www.example.com', '/index.html')
# print res.body
#
- def HTTP.get_response(uri_or_host, path = nil, port = nil, &block)
- if path
+ # you can also specify request headers:
+ #
+ # Net::HTTP.get_response(URI('http://www.example.com/index.html'), { 'Accept' => 'text/html' })
+ #
+ def HTTP.get_response(uri_or_host, path_or_headers = nil, port = nil, &block)
+ if path_or_headers && !path_or_headers.is_a?(Hash)
host = uri_or_host
+ path = path_or_headers
new(host, port || HTTP.default_port).start {|http|
return http.request_get(path, &block)
}
else
uri = uri_or_host
+ headers = path_or_headers
start(uri.hostname, uri.port,
:use_ssl => uri.scheme == 'https') {|http|
- return http.request_get(uri, &block)
+ return http.request_get(uri, headers, &block)
}
end
end
@@ -571,7 +586,7 @@ module Net #:nodoc:
# _opt_ :: optional hash
#
# _opt_ sets following values by its accessor.
- # The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers,
+ # The keys are ipaddr, ca_file, ca_path, cert, cert_store, ciphers, keep_alive_timeout,
# close_on_empty_response, key, open_timeout, read_timeout, write_timeout, ssl_timeout,
# ssl_version, use_ssl, verify_callback, verify_depth and verify_mode.
# If you set :use_ssl as true, you can use https and default value of
@@ -836,6 +851,7 @@ module Net #:nodoc:
:@cert,
:@cert_store,
:@ciphers,
+ :@extra_chain_cert,
:@key,
:@ssl_timeout,
:@ssl_version,
@@ -844,6 +860,7 @@ module Net #:nodoc:
:@verify_callback,
:@verify_depth,
:@verify_mode,
+ :@verify_hostname,
]
SSL_ATTRIBUTES = [
:ca_file,
@@ -851,6 +868,7 @@ module Net #:nodoc:
:cert,
:cert_store,
:ciphers,
+ :extra_chain_cert,
:key,
:ssl_timeout,
:ssl_version,
@@ -859,6 +877,7 @@ module Net #:nodoc:
:verify_callback,
:verify_depth,
:verify_mode,
+ :verify_hostname,
]
# Sets path of a CA certification file in PEM format.
@@ -880,6 +899,10 @@ module Net #:nodoc:
# Sets the available ciphers. See OpenSSL::SSL::SSLContext#ciphers=
attr_accessor :ciphers
+ # Sets the extra X509 certificates to be added to the certificate chain.
+ # See OpenSSL::SSL::SSLContext#extra_chain_cert=
+ attr_accessor :extra_chain_cert
+
# Sets an OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
# (This method is appeared in Michal Rokos's OpenSSL extension.)
attr_accessor :key
@@ -908,6 +931,10 @@ module Net #:nodoc:
# OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER are acceptable.
attr_accessor :verify_mode
+ # Sets to check the server certificate is valid for the hostname.
+ # See OpenSSL::SSL::SSLContext#verify_hostname=
+ attr_accessor :verify_hostname
+
# Returns the X.509 certificates the server presented.
def peer_cert
if not use_ssl? or not @socket
@@ -986,9 +1013,11 @@ module Net #:nodoc:
ssl_parameters = Hash.new
iv_list = instance_variables
SSL_IVNAMES.each_with_index do |ivname, i|
- if iv_list.include?(ivname) and
+ if iv_list.include?(ivname)
value = instance_variable_get(ivname)
- ssl_parameters[SSL_ATTRIBUTES[i]] = value if value
+ unless value.nil?
+ ssl_parameters[SSL_ATTRIBUTES[i]] = value
+ end
end
end
@ssl_context = OpenSSL::SSL::SSLContext.new
@@ -1007,7 +1036,7 @@ module Net #:nodoc:
s.session = @ssl_session
end
ssl_socket_connect(s, @open_timeout)
- if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
+ if (@ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE) && @ssl_context.verify_hostname
s.post_connection_check(@address)
end
D "SSL established, protocol: #{s.ssl_version}, cipher: #{s.cipher[0]}"
diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb
index 8641be4eae..a8901e79cb 100644
--- a/lib/net/http/header.rb
+++ b/lib/net/http/header.rb
@@ -423,30 +423,50 @@ module Net::HTTPHeader
alias form_data= set_form_data
# Set an HTML form data set.
- # +params+ is the form data set; it is an Array of Arrays or a Hash
- # +enctype is the type to encode the form data set.
- # It is application/x-www-form-urlencoded or multipart/form-data.
- # +formopt+ is an optional hash to specify the detail.
+ # +params+ :: The form data to set, which should be an enumerable.
+ # See below for more details.
+ # +enctype+ :: The content type to use to encode the form submission,
+ # which should be application/x-www-form-urlencoded or
+ # multipart/form-data.
+ # +formopt+ :: An options hash, supporting the following options:
+ # :boundary :: The boundary of the multipart message. If
+ # not given, a random boundary will be used.
+ # :charset :: The charset of the form submission. All
+ # field names and values of non-file fields
+ # should be encoded with this charset.
#
- # boundary:: the boundary of the multipart message
- # charset:: the charset of the message. All names and the values of
- # non-file fields are encoded as the charset.
- #
- # Each item of params is an array and contains following items:
- # +name+:: the name of the field
- # +value+:: the value of the field, it should be a String or a File
- # +opt+:: an optional hash to specify additional information
+ # Each item of params should respond to +each+ and yield 2-3 arguments,
+ # or an array of 2-3 elements. The arguments yielded should be:
+ # * The name of the field.
+ # * The value of the field, it should be a String or a File or IO-like.
+ # * An options hash, supporting the following options, only
+ # used for file uploads:
+ # :filename :: The name of the file to use.
+ # :content_type :: The content type of the uploaded file.
#
# Each item is a file field or a normal field.
- # If +value+ is a File object or the +opt+ have a filename key,
+ # If +value+ is a File object or the +opt+ hash has a :filename key,
# the item is treated as a file field.
#
- # If Transfer-Encoding is set as chunked, this send the request in
+ # If Transfer-Encoding is set as chunked, this sends the request using
# chunked encoding. Because chunked encoding is HTTP/1.1 feature,
- # you must confirm the server to support HTTP/1.1 before sending it.
+ # you should confirm that the server supports HTTP/1.1 before using
+ # chunked encoding.
#
# Example:
- # http.set_form([["q", "ruby"], ["lang", "en"]])
+ # req.set_form([["q", "ruby"], ["lang", "en"]])
+ #
+ # req.set_form({"f"=>File.open('/path/to/filename')},
+ # "multipart/form-data",
+ # charset: "UTF-8",
+ # )
+ #
+ # req.set_form([["f",
+ # File.open('/path/to/filename.bar'),
+ # {filename: "other-filename.foo"}
+ # ]],
+ # "multipart/form-data",
+ # )
#
# See also RFC 2388, RFC 2616, HTML 4.01, and HTML5
#
diff --git a/lib/net/http/net-http.gemspec b/lib/net/http/net-http.gemspec
new file mode 100644
index 0000000000..f5ef4045e8
--- /dev/null
+++ b/lib/net/http/net-http.gemspec
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
+end
+
+Gem::Specification.new do |spec|
+ spec.name = name
+ spec.version = version
+ spec.authors = ["NARUSE, Yui"]
+ spec.email = ["naruse@airemix.jp"]
+
+ spec.summary = %q{HTTP client api for Ruby.}
+ spec.description = %q{HTTP client api for Ruby.}
+ spec.homepage = "https://github.com/ruby/net-http"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "net-protocol"
+ spec.add_dependency "uri"
+end
diff --git a/lib/net/imap.rb b/lib/net/imap.rb
index 94ef78198f..d45304f289 100644
--- a/lib/net/imap.rb
+++ b/lib/net/imap.rb
@@ -18,7 +18,7 @@ require "socket"
require "monitor"
require "digest/md5"
require "strscan"
-require_relative 'protocol'
+require 'net/protocol'
begin
require "openssl"
rescue LoadError
@@ -201,6 +201,8 @@ module Net
# Unicode", RFC 2152, May 1997.
#
class IMAP < Protocol
+ VERSION = "0.1.1"
+
include MonitorMixin
if defined?(OpenSSL::SSL)
include OpenSSL
@@ -1542,7 +1544,7 @@ module Net
class RawData # :nodoc:
def send_data(imap, tag)
- imap.send(:put_string, @data)
+ imap.__send__(:put_string, @data)
end
def validate
@@ -1557,7 +1559,7 @@ module Net
class Atom # :nodoc:
def send_data(imap, tag)
- imap.send(:put_string, @data)
+ imap.__send__(:put_string, @data)
end
def validate
@@ -1572,7 +1574,7 @@ module Net
class QuotedString # :nodoc:
def send_data(imap, tag)
- imap.send(:send_quoted_string, @data)
+ imap.__send__(:send_quoted_string, @data)
end
def validate
@@ -1587,7 +1589,7 @@ module Net
class Literal # :nodoc:
def send_data(imap, tag)
- imap.send(:send_literal, @data, tag)
+ imap.__send__(:send_literal, @data, tag)
end
def validate
@@ -1602,7 +1604,7 @@ module Net
class MessageSet # :nodoc:
def send_data(imap, tag)
- imap.send(:put_string, format_internal(@data))
+ imap.__send__(:put_string, format_internal(@data))
end
def validate
diff --git a/lib/net/net-ftp.gemspec b/lib/net/net-ftp.gemspec
new file mode 100644
index 0000000000..f5eb098135
--- /dev/null
+++ b/lib/net/net-ftp.gemspec
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
+end
+
+Gem::Specification.new do |spec|
+ spec.name = name
+ spec.version = version
+ spec.authors = ["Shugo Maeda"]
+ spec.email = ["shugo@ruby-lang.org"]
+
+ spec.summary = %q{Support for the File Transfer Protocol.}
+ spec.description = %q{Support for the File Transfer Protocol.}
+ spec.homepage = "https://github.com/ruby/net-ftp"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "net-protocol"
+ spec.add_dependency "time"
+end
diff --git a/lib/net/net-imap.gemspec b/lib/net/net-imap.gemspec
new file mode 100644
index 0000000000..d7c341cd92
--- /dev/null
+++ b/lib/net/net-imap.gemspec
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
+end
+
+Gem::Specification.new do |spec|
+ spec.name = name
+ spec.version = version
+ spec.authors = ["Shugo Maeda"]
+ spec.email = ["shugo@ruby-lang.org"]
+
+ spec.summary = %q{Ruby client api for Internet Message Access Protocol}
+ spec.description = %q{Ruby client api for Internet Message Access Protocol}
+ spec.homepage = "https://github.com/ruby/net-imap"
+ 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
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "net-protocol"
+ spec.add_dependency "digest"
+ spec.add_dependency "strscan"
+end
diff --git a/lib/net/net-pop.gemspec b/lib/net/net-pop.gemspec
new file mode 100644
index 0000000000..2a89f6086d
--- /dev/null
+++ b/lib/net/net-pop.gemspec
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
+end
+
+Gem::Specification.new do |spec|
+ spec.name = name
+ spec.version = version
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{Ruby client library for POP3.}
+ spec.description = %q{Ruby client library for POP3.}
+ spec.homepage = "https://github.com/ruby/net-pop"
+ 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 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "net-protocol"
+ spec.add_dependency "digest"
+ spec.add_dependency "timeout"
+end
diff --git a/lib/net/net-protocol.gemspec b/lib/net/net-protocol.gemspec
new file mode 100644
index 0000000000..767a7d48e2
--- /dev/null
+++ b/lib/net/net-protocol.gemspec
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
+end
+
+Gem::Specification.new do |spec|
+ spec.name = name
+ spec.version = version
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{The abstruct interface for net-* client.}
+ spec.description = %q{The abstruct interface for net-* client.}
+ spec.homepage = "https://github.com/ruby/net-protocol"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "timeout"
+ spec.add_dependency "io-wait"
+end
diff --git a/lib/net/net-smtp.gemspec b/lib/net/net-smtp.gemspec
new file mode 100644
index 0000000000..bd0a2dd84c
--- /dev/null
+++ b/lib/net/net-smtp.gemspec
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
+end
+
+Gem::Specification.new do |spec|
+ spec.name = name
+ spec.version = version
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{Simple Mail Transfer Protocol client library for Ruby.}
+ spec.description = %q{Simple Mail Transfer Protocol client library for Ruby.}
+ spec.homepage = "https://github.com/ruby/net-smtp"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = ">= 2.5.0"
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "net-protocol"
+ spec.add_dependency "digest"
+ spec.add_dependency "timeout"
+end
diff --git a/lib/net/pop.rb b/lib/net/pop.rb
index 8712345301..8e75846820 100644
--- a/lib/net/pop.rb
+++ b/lib/net/pop.rb
@@ -194,9 +194,8 @@ module Net
# String. Normally the unique-id is a hash of the message.
#
class POP3 < Protocol
-
- # svn revision of this library
- Revision = %q$Revision$.split[1]
+ # version of this library
+ VERSION = "0.1.1"
#
# Class Parameters
@@ -970,7 +969,7 @@ module Net
getok('UIDL')
table = {}
@socket.each_list_item do |line|
- num, uid = line.split
+ num, uid = line.split(' ')
table[num.to_i] = uid
end
return table
diff --git a/lib/net/pop/net-pop.gemspec b/lib/net/pop/net-pop.gemspec
deleted file mode 100644
index c1b0ffbd2b..0000000000
--- a/lib/net/pop/net-pop.gemspec
+++ /dev/null
@@ -1,27 +0,0 @@
-begin
- require_relative "lib/net/pop/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "net-pop"
- spec.version = Net::POP3::VERSION
- spec.authors = ["Yukihiro Matsumoto"]
- spec.email = ["matz@ruby-lang.org"]
-
- spec.summary = %q{Ruby client library for POP3.}
- spec.description = %q{Ruby client library for POP3.}
- spec.homepage = "https://github.com/ruby/net-pop"
- spec.license = "BSD-2-Clause"
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-end
diff --git a/lib/net/pop/version.rb b/lib/net/pop/version.rb
deleted file mode 100644
index ef5c295cc3..0000000000
--- a/lib/net/pop/version.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Net
- class Protocol; end
- class POP3 < Protocol
- VERSION = "0.1.0"
- end
-end
diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb
index 07fbc6a21f..edf2ed5a00 100644
--- a/lib/net/protocol.rb
+++ b/lib/net/protocol.rb
@@ -26,6 +26,8 @@ require 'io/wait'
module Net # :nodoc:
class Protocol #:nodoc: internal use only
+ VERSION = "0.1.1"
+
private
def Protocol.protocol_param(name, val)
module_eval(<<-End, __FILE__, __LINE__ + 1)
diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb
index 460ad08233..a97c0c3395 100644
--- a/lib/net/smtp.rb
+++ b/lib/net/smtp.rb
@@ -146,8 +146,8 @@ module Net
# The SMTP server will judge whether it should send or reject
# the SMTP session by inspecting the HELO domain.
#
- # Net::SMTP.start('your.smtp.server', 25,
- # 'mail.from.domain') { |smtp| ... }
+ # Net::SMTP.start('your.smtp.server', 25
+ # helo: 'mail.from.domain') { |smtp| ... }
#
# === SMTP Authentication
#
@@ -157,17 +157,18 @@ module Net
# SMTP.start/SMTP#start.
#
# # PLAIN
- # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
- # 'Your Account', 'Your Password', :plain)
+ # Net::SMTP.start('your.smtp.server', 25
+ # user: 'Your Account', secret: 'Your Password', authtype: :plain)
# # LOGIN
- # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
- # 'Your Account', 'Your Password', :login)
+ # Net::SMTP.start('your.smtp.server', 25
+ # user: 'Your Account', secret: 'Your Password', authtype: :login)
#
# # CRAM MD5
- # Net::SMTP.start('your.smtp.server', 25, 'mail.from.domain',
- # 'Your Account', 'Your Password', :cram_md5)
+ # Net::SMTP.start('your.smtp.server', 25
+ # user: 'Your Account', secret: 'Your Password', authtype: :cram_md5)
#
class SMTP < Protocol
+ VERSION = "0.2.1"
Revision = %q$Revision$.split[1]
@@ -190,8 +191,13 @@ module Net
alias default_ssl_port default_tls_port
end
- def SMTP.default_ssl_context
- OpenSSL::SSL::SSLContext.new
+ def SMTP.default_ssl_context(verify_peer=true)
+ context = OpenSSL::SSL::SSLContext.new
+ context.verify_mode = verify_peer ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
+ store = OpenSSL::X509::Store.new
+ store.set_default_paths
+ context.cert_store = store
+ context
end
#
@@ -217,8 +223,9 @@ module Net
@error_occurred = false
@debug_output = nil
@tls = false
- @starttls = false
- @ssl_context = nil
+ @starttls = :auto
+ @ssl_context_tls = nil
+ @ssl_context_starttls = nil
end
# Provide human-readable stringification of class state.
@@ -293,11 +300,11 @@ module Net
# Enables SMTP/TLS (SMTPS: SMTP over direct TLS connection) for
# this object. Must be called before the connection is established
# to have any effect. +context+ is a OpenSSL::SSL::SSLContext object.
- def enable_tls(context = SMTP.default_ssl_context)
+ def enable_tls(context = nil)
raise 'openssl library not installed' unless defined?(OpenSSL)
- raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @starttls
+ raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @starttls == :always
@tls = true
- @ssl_context = context
+ @ssl_context_tls = context
end
alias enable_ssl enable_tls
@@ -306,7 +313,7 @@ module Net
# connection is established to have any effect.
def disable_tls
@tls = false
- @ssl_context = nil
+ @ssl_context_tls = nil
end
alias disable_ssl disable_tls
@@ -330,27 +337,27 @@ module Net
# Enables SMTP/TLS (STARTTLS) for this object.
# +context+ is a OpenSSL::SSL::SSLContext object.
- def enable_starttls(context = SMTP.default_ssl_context)
+ def enable_starttls(context = nil)
raise 'openssl library not installed' unless defined?(OpenSSL)
raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls
@starttls = :always
- @ssl_context = context
+ @ssl_context_starttls = context
end
# Enables SMTP/TLS (STARTTLS) for this object if server accepts.
# +context+ is a OpenSSL::SSL::SSLContext object.
- def enable_starttls_auto(context = SMTP.default_ssl_context)
+ def enable_starttls_auto(context = nil)
raise 'openssl library not installed' unless defined?(OpenSSL)
raise ArgumentError, "SMTPS and STARTTLS is exclusive" if @tls
@starttls = :auto
- @ssl_context = context
+ @ssl_context_starttls = context
end
# Disables SMTP/TLS (STARTTLS) for this object. Must be called
# before the connection is established to have any effect.
def disable_starttls
@starttls = false
- @ssl_context = nil
+ @ssl_context_starttls = nil
end
# The address of the SMTP server to connect to.
@@ -401,11 +408,15 @@ module Net
#
#
+ # :call-seq:
+ # start(address, port = nil, helo: 'localhost', user: nil, secret: nil, authtype: nil, tls_verify: true, tls_hostname: nil) { |smtp| ... }
+ # start(address, port = nil, helo = 'localhost', user = nil, secret = nil, authtype = nil) { |smtp| ... }
+ #
# Creates a new Net::SMTP object and connects to the server.
#
# This method is equivalent to:
#
- # Net::SMTP.new(address, port).start(helo_domain, account, password, authtype)
+ # Net::SMTP.new(address, port).start(helo: helo_domain, user: account, secret: password, authtype: authtype, tls_verify: flag, tls_hostname: hostname)
#
# === Example
#
@@ -435,6 +446,9 @@ module Net
# or other authentication token; and +authtype+ is the authentication
# type, one of :plain, :login, or :cram_md5. See the discussion of
# SMTP Authentication in the overview notes.
+ # If +tls_verify+ is true, verify the server's certificate. The default is true.
+ # If the hostname in the server certificate is different from +address+,
+ # it can be specified with +tls_hostname+.
#
# === Errors
#
@@ -449,10 +463,16 @@ module Net
# * Net::ReadTimeout
# * IOError
#
- def SMTP.start(address, port = nil, helo = 'localhost',
- user = nil, secret = nil, authtype = nil,
- &block) # :yield: smtp
- new(address, port).start(helo, user, secret, authtype, &block)
+ def SMTP.start(address, port = nil, *args, helo: nil,
+ user: nil, secret: nil, password: nil, authtype: nil,
+ tls_verify: true, tls_hostname: nil,
+ &block)
+ raise ArgumentError, "wrong number of arguments (given #{args.size + 2}, expected 1..6)" if args.size > 4
+ helo ||= args[0] || 'localhost'
+ user ||= args[1]
+ secret ||= password || args[2]
+ authtype ||= args[3]
+ new(address, port).start(helo: helo, user: user, secret: secret, authtype: authtype, tls_verify: tls_verify, tls_hostname: tls_hostname, &block)
end
# +true+ if the SMTP session has been started.
@@ -461,6 +481,10 @@ module Net
end
#
+ # :call-seq:
+ # start(helo: 'localhost', user: nil, secret: nil, authtype: nil, tls_verify: true, tls_hostname: nil) { |smtp| ... }
+ # start(helo = 'localhost', user = nil, secret = nil, authtype = nil) { |smtp| ... }
+ #
# Opens a TCP connection and starts the SMTP session.
#
# === Parameters
@@ -473,6 +497,9 @@ module Net
# the type of authentication to attempt; it must be one of
# :login, :plain, and :cram_md5. See the notes on SMTP Authentication
# in the overview.
+ # If +tls_verify+ is true, verify the server's certificate. The default is true.
+ # If the hostname in the server certificate is different from +address+,
+ # it can be specified with +tls_hostname+.
#
# === Block Usage
#
@@ -487,7 +514,7 @@ module Net
#
# require 'net/smtp'
# smtp = Net::SMTP.new('smtp.mail.server', 25)
- # smtp.start(helo_domain, account, password, authtype) do |smtp|
+ # smtp.start(helo: helo_domain, user: account, secret: password, authtype: authtype) do |smtp|
# smtp.send_message msgstr, 'from@example.com', ['dest@example.com']
# end
#
@@ -511,8 +538,20 @@ module Net
# * Net::ReadTimeout
# * IOError
#
- def start(helo = 'localhost',
- user = nil, secret = nil, authtype = nil) # :yield: smtp
+ def start(*args, helo: nil,
+ user: nil, secret: nil, password: nil, authtype: nil, tls_verify: true, tls_hostname: nil)
+ raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0..4)" if args.size > 4
+ helo ||= args[0] || 'localhost'
+ user ||= args[1]
+ secret ||= password || args[2]
+ authtype ||= args[3]
+ if @tls && @ssl_context_tls.nil?
+ @ssl_context_tls = SMTP.default_ssl_context(tls_verify)
+ end
+ if @starttls && @ssl_context_starttls.nil?
+ @ssl_context_starttls = SMTP.default_ssl_context(tls_verify)
+ end
+ @tls_hostname = tls_hostname
if block_given?
begin
do_start helo, user, secret, authtype
@@ -549,16 +588,16 @@ module Net
tcp_socket(@address, @port)
end
logging "Connection opened: #{@address}:#{@port}"
- @socket = new_internet_message_io(tls? ? tlsconnect(s) : s)
+ @socket = new_internet_message_io(tls? ? tlsconnect(s, @ssl_context_tls) : s)
check_response critical { recv_response() }
do_helo helo_domain
- if starttls_always? or (capable_starttls? and starttls_auto?)
+ if ! tls? and (starttls_always? or (capable_starttls? and starttls_auto?))
unless capable_starttls?
raise SMTPUnsupportedCommand,
"STARTTLS is not supported on this server"
end
starttls
- @socket = new_internet_message_io(tlsconnect(s))
+ @socket = new_internet_message_io(tlsconnect(s, @ssl_context_starttls))
# helo response may be different after STARTTLS
do_helo helo_domain
end
@@ -576,14 +615,15 @@ module Net
OpenSSL::SSL::SSLSocket.new socket, context
end
- def tlsconnect(s)
+ def tlsconnect(s, context)
verified = false
- s = ssl_socket(s, @ssl_context)
+ s = ssl_socket(s, context)
logging "TLS connection started"
s.sync_close = true
+ s.hostname = @tls_hostname || @address if s.respond_to? :hostname=
ssl_socket_connect(s, @open_timeout)
- if @ssl_context.verify_mode != OpenSSL::SSL::VERIFY_NONE
- s.post_connection_check(@address)
+ if context.verify_mode && context.verify_mode != OpenSSL::SSL::VERIFY_NONE
+ s.post_connection_check(@tls_hostname || @address)
end
verified = true
s
@@ -725,7 +765,7 @@ module Net
def authenticate(user, secret, authtype = DEFAULT_AUTH_TYPE)
check_auth_method authtype
check_auth_args user, secret
- send auth_method(authtype), user, secret
+ public_send auth_method(authtype), user, secret
end
def auth_plain(user, secret)
@@ -1042,7 +1082,7 @@ module Net
return {} unless @string[3, 1] == '-'
h = {}
@string.lines.drop(1).each do |line|
- k, *v = line[4..-1].chomp.split
+ k, *v = line[4..-1].split(' ')
h[k] = v
end
h
diff --git a/lib/net/smtp/net-smtp.gemspec b/lib/net/smtp/net-smtp.gemspec
deleted file mode 100644
index 1dddfa7ca8..0000000000
--- a/lib/net/smtp/net-smtp.gemspec
+++ /dev/null
@@ -1,27 +0,0 @@
-begin
- require_relative "lib/net/smtp/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "net-smtp"
- spec.version = Net::SMTP::VERSION
- spec.authors = ["Yukihiro Matsumoto"]
- spec.email = ["matz@ruby-lang.org"]
-
- spec.summary = %q{Simple Mail Transfer Protocol client library for Ruby.}
- spec.description = %q{Simple Mail Transfer Protocol client library for Ruby.}
- spec.homepage = "https://github.com/ruby/net-smtp"
- spec.license = "BSD-2-Clause"
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-end
diff --git a/lib/net/smtp/version.rb b/lib/net/smtp/version.rb
deleted file mode 100644
index 7f5aaaa6db..0000000000
--- a/lib/net/smtp/version.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-module Net
- class Protocol; end
- class SMTP < Protocol
- VERSION = "0.1.0"
- end
-end
diff --git a/lib/observer.rb b/lib/observer.rb
index acfe654301..ef70e39dd8 100644
--- a/lib/observer.rb
+++ b/lib/observer.rb
@@ -111,7 +111,32 @@
# Current price: 112
# Current price: 79
# --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79
+#
+# === Usage with procs
+#
+# The +#notify_observers+ method can also be used with +proc+s by using
+# the +:call+ as +func+ parameter.
+#
+# The following example illustrates the use of a lambda:
+#
+# require 'observer'
+#
+# class Ticker
+# include Observable
+#
+# def run
+# # logic to retrieve the price (here 77.0)
+# changed
+# notify_observers(77.0)
+# end
+# end
+#
+# ticker = Ticker.new
+# warner = ->(price) { puts "New price received: #{price}" }
+# ticker.add_observer(warner, :call)
+# ticker.run
module Observable
+ VERSION = "0.1.1"
#
# Add +observer+ as an observer on this object. So that it will receive
@@ -194,7 +219,7 @@ module Observable
if defined? @observer_state and @observer_state
if defined? @observer_peers
@observer_peers.each do |k, v|
- k.send v, *arg
+ k.__send__(v, *arg)
end
end
@observer_state = false
diff --git a/lib/observer/observer.gemspec b/lib/observer/observer.gemspec
index 188c6bae76..46538e881a 100644
--- a/lib/observer/observer.gemspec
+++ b/lib/observer/observer.gemspec
@@ -1,19 +1,22 @@
-begin
- require_relative "lib/observer/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "observer"
- spec.version = Observer::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
spec.summary = %q{Implementation of the Observer object-oriented design pattern.}
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/observer"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/lib/observer/version.rb b/lib/observer/version.rb
deleted file mode 100644
index 92b5098774..0000000000
--- a/lib/observer/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module Observer
- VERSION = "0.1.0"
-end
diff --git a/lib/open-uri.gemspec b/lib/open-uri.gemspec
new file mode 100644
index 0000000000..853049f7ec
--- /dev/null
+++ b/lib/open-uri.gemspec
@@ -0,0 +1,26 @@
+Gem::Specification.new do |spec|
+ spec.name = "open-uri"
+ spec.version = "0.1.0"
+ spec.authors = ["Tanaka Akira"]
+ spec.email = ["akr@fsij.org"]
+
+ spec.summary = %q{An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP.}
+ spec.description = %q{An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP.}
+ spec.homepage = "https://github.com/ruby/open-uri"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "uri"
+ spec.add_dependency "stringio"
+ spec.add_dependency "time"
+end
diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index c52f67f525..421a82ed0d 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -3,27 +3,6 @@ require 'uri'
require 'stringio'
require 'time'
-module Kernel
- private
- alias open_uri_original_open open # :nodoc:
- class << self
- alias open_uri_original_open open # :nodoc:
- end
-
- def open(name, *rest, **kw, &block) # :nodoc:
- if (name.respond_to?(:open) && !name.respond_to?(:to_path)) ||
- (name.respond_to?(:to_str) &&
- %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name &&
- (uri = URI.parse(name)).respond_to?(:open))
- warn('calling URI.open via Kernel#open is deprecated, call URI.open directly or use URI#open', uplevel: 1)
- URI.open(name, *rest, **kw, &block)
- else
- open_uri_original_open(name, *rest, **kw, &block)
- end
- end
- module_function :open
-end
-
module URI
# Allows the opening of various resources including URIs.
#
@@ -49,9 +28,7 @@ module URI
(uri = URI.parse(name)).respond_to?(:open)
uri.open(*rest, &block)
else
- open_uri_original_open(name, *rest, &block)
- # After Kernel#open override is removed:
- #super
+ super
end
end
end
@@ -744,7 +721,7 @@ module OpenURI
OpenURI.open_uri(self, *rest, &block)
end
- # OpenURI::OpenRead#read([options]) reads a content referenced by self and
+ # OpenURI::OpenRead#read([ options ]) reads a content referenced by self and
# returns the content as string.
# The string is extended with OpenURI::Meta.
# The argument +options+ is same as OpenURI::OpenRead#open.
diff --git a/lib/open3.gemspec b/lib/open3.gemspec
new file mode 100644
index 0000000000..ad9485adc7
--- /dev/null
+++ b/lib/open3.gemspec
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
+end
+
+Gem::Specification.new do |spec|
+ spec.name = name
+ spec.version = version
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{Popen, but with stderr, too}
+ spec.description = spec.summary
+ spec.homepage = "https://github.com/ruby/open3"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = ">= 2.6.0"
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/open3.rb b/lib/open3.rb
index 5e725317a4..c574696bb1 100644
--- a/lib/open3.rb
+++ b/lib/open3.rb
@@ -30,6 +30,7 @@
#
module Open3
+ VERSION = "0.1.1"
# Open stdin, stdout, and stderr streams and start external executable.
# In addition, a thread to wait for the started process is created.
@@ -206,6 +207,13 @@ module Open3
opts[[:out, :err]] = out_w
popen_run(cmd, opts, [in_r, out_w], [in_w, out_r], &block)
+ ensure
+ if block
+ in_r.close
+ in_w.close
+ out_r.close
+ out_w.close
+ end
end
module_function :popen2e
diff --git a/lib/open3/open3.gemspec b/lib/open3/open3.gemspec
deleted file mode 100644
index 543416e427..0000000000
--- a/lib/open3/open3.gemspec
+++ /dev/null
@@ -1,29 +0,0 @@
-begin
- require_relative "lib/open3/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "open3"
- spec.version = Open3::VERSION
- spec.authors = ["Yukihiro Matsumoto"]
- spec.email = ["matz@ruby-lang.org"]
-
- spec.summary = %q{Popen, but with stderr, too}
- spec.description = spec.summary
- spec.homepage = "https://github.com/ruby/open3"
- spec.license = "BSD-2-Clause"
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- # Specify which files should be added to the gem when it is released.
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-end
diff --git a/lib/open3/version.rb b/lib/open3/version.rb
deleted file mode 100644
index c670b79ebc..0000000000
--- a/lib/open3/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module Open3
- VERSION = "0.1.0"
-end
diff --git a/lib/optparse.rb b/lib/optparse.rb
index 614ebc3eae..598ebd12bd 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -72,10 +72,10 @@
# require 'optparse'
#
# options = {}
-# OptionParser.new do |opts|
-# opts.banner = "Usage: example.rb [options]"
+# OptionParser.new do |parser|
+# parser.banner = "Usage: example.rb [options]"
#
-# opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
+# parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
# options[:verbose] = v
# end
# end.parse!
@@ -96,15 +96,15 @@
# def self.parse(options)
# args = Options.new("world")
#
-# opt_parser = OptionParser.new do |opts|
-# opts.banner = "Usage: example.rb [options]"
+# opt_parser = OptionParser.new do |parser|
+# parser.banner = "Usage: example.rb [options]"
#
-# opts.on("-nNAME", "--name=NAME", "Name to say hello to") do |n|
+# parser.on("-nNAME", "--name=NAME", "Name to say hello to") do |n|
# args.name = n
# end
#
-# opts.on("-h", "--help", "Prints this help") do
-# puts opts
+# parser.on("-h", "--help", "Prints this help") do
+# puts parser
# exit
# end
# end
@@ -241,10 +241,10 @@
# require 'optparse'
#
# params = {}
-# OptionParser.new do |opts|
-# opts.on('-a')
-# opts.on('-b NUM', Integer)
-# opts.on('-v', '--verbose')
+# OptionParser.new do |parser|
+# parser.on('-a')
+# parser.on('-b NUM', Integer)
+# parser.on('-v', '--verbose')
# end.parse!(into: params)
#
# p params
@@ -419,6 +419,8 @@
# have any questions, file a ticket at http://bugs.ruby-lang.org.
#
class OptionParser
+ OptionParser::Version = "0.1.1"
+
# :stopdoc:
NoArgument = [NO_ARGUMENT = :NONE, nil].freeze
RequiredArgument = [REQUIRED_ARGUMENT = :REQUIRED, true].freeze
@@ -1089,6 +1091,7 @@ XXX
@summary_width = width
@summary_indent = indent
@default_argv = ARGV
+ @require_exact = false
add_officious
yield self if block_given?
end
@@ -1162,6 +1165,10 @@ XXX
# Strings to be parsed in default.
attr_accessor :default_argv
+ # Whether to require that options match exactly (disallows providing
+ # abbreviated long option as short option).
+ attr_accessor :require_exact
+
#
# Heading banner preceding summary.
#
@@ -1303,13 +1310,16 @@ XXX
private :notwice
SPLAT_PROC = proc {|*a| a.length <= 1 ? a.first : a} # :nodoc:
+
+ # :call-seq:
+ # make_switch(params, block = nil)
#
# Creates an OptionParser::Switch from the parameters. The parsed argument
# value is passed to the given block, where it can be processed.
#
# See at the beginning of OptionParser for some full examples.
#
- # +opts+ can include the following elements:
+ # +params+ can include the following elements:
#
# [Argument style:]
# One of the following:
@@ -1496,11 +1506,16 @@ XXX
nolong
end
+ # :call-seq:
+ # define(*params, &block)
+ #
def define(*opts, &block)
top.append(*(sw = make_switch(opts, block)))
sw[0]
end
+ # :call-seq:
+ # on(*params, &block)
#
# Add option switch and handler. See #make_switch for an explanation of
# parameters.
@@ -1511,11 +1526,16 @@ XXX
end
alias def_option define
+ # :call-seq:
+ # define_head(*params, &block)
+ #
def define_head(*opts, &block)
top.prepend(*(sw = make_switch(opts, block)))
sw[0]
end
+ # :call-seq:
+ # on_head(*params, &block)
#
# Add option switch like with #on, but at head of summary.
#
@@ -1525,12 +1545,18 @@ XXX
end
alias def_head_option define_head
+ # :call-seq:
+ # define_tail(*params, &block)
+ #
def define_tail(*opts, &block)
base.append(*(sw = make_switch(opts, block)))
sw[0]
end
#
+ # :call-seq:
+ # on_tail(*params, &block)
+ #
# Add option switch like with #on, but at tail of summary.
#
def on_tail(*opts, &block)
@@ -1581,6 +1607,9 @@ XXX
opt.tr!('_', '-')
begin
sw, = complete(:long, opt, true)
+ if require_exact && !sw.long.include?(arg)
+ raise InvalidOption, arg
+ end
rescue ParseError
raise $!.set_option(arg, true)
end
@@ -1605,6 +1634,7 @@ XXX
val = arg.delete_prefix('-')
has_arg = true
rescue InvalidOption
+ raise if require_exact
# if no short options match, try completion with long
# options.
sw, = complete(:long, opt)
@@ -1616,7 +1646,12 @@ XXX
end
begin
opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
+ rescue ParseError
+ raise $!.set_option(arg, arg.length > 2)
+ else
raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
+ end
+ begin
argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
val = cb.call(val) if cb
setter.call(sw.switch_name, val) if setter
@@ -1747,7 +1782,7 @@ XXX
#
def visit(id, *args, &block)
@stack.reverse_each do |el|
- el.send(id, *args, &block)
+ el.__send__(id, *args, &block)
end
nil
end
diff --git a/lib/optparse/kwargs.rb b/lib/optparse/kwargs.rb
index ed58cc142b..5a2def4747 100644
--- a/lib/optparse/kwargs.rb
+++ b/lib/optparse/kwargs.rb
@@ -2,6 +2,9 @@
require 'optparse'
class OptionParser
+ # :call-seq:
+ # define_by_keywords(options, method, **params)
+ #
def define_by_keywords(options, meth, **opts)
meth.parameters.each do |type, name|
case type
diff --git a/lib/optparse/optparse.gemspec b/lib/optparse/optparse.gemspec
new file mode 100644
index 0000000000..831c787ac7
--- /dev/null
+++ b/lib/optparse/optparse.gemspec
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*OptionParser::Version\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
+end
+
+Gem::Specification.new do |spec|
+ spec.name = name
+ spec.version = version
+ spec.authors = ["Nobu Nakada"]
+ spec.email = ["nobu@ruby-lang.org"]
+
+ spec.summary = %q{OptionParser is a class for command-line option analysis.}
+ spec.description = %q{OptionParser is a class for command-line option analysis.}
+ spec.homepage = "https://github.com/ruby/optparse"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f|
+ f.match(%r{\A(?:(?:test|spec|features)/|Gemfile|\.(?:editor|git))})
+ }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/ostruct.rb b/lib/ostruct.rb
index c40c897ff6..a5a5140d10 100644
--- a/lib/ostruct.rb
+++ b/lib/ostruct.rb
@@ -36,9 +36,10 @@
# 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.
+# still be reached through the Object#send method or using [].
#
# measurements = OpenStruct.new("length (in inches)" => 24)
+# measurements[:"length (in inches)"] # => 24
# measurements.send("length (in inches)") # => 24
#
# message = OpenStruct.new(:queued? => true)
@@ -61,8 +62,9 @@
# first_pet # => #<OpenStruct name="Rowdy">
# first_pet == second_pet # => true
#
+# Ractor compatibility: A frozen OpenStruct with shareable values is itself shareable.
#
-# == Implementation
+# == Caveats
#
# An OpenStruct utilizes Ruby's method lookup structure to find and define the
# necessary methods for properties. This is accomplished through the methods
@@ -71,11 +73,41 @@
# This should be a consideration if there is a concern about the performance of
# the objects that are created, as there is much more overhead in the setting
# of these properties compared to using a Hash or a Struct.
+# Creating an open struct from a small Hash and accessing a few of the
+# entries can be 200 times slower than accessing the hash directly.
+#
+# This is a potential security issue; building OpenStruct from untrusted user data
+# (e.g. JSON web request) may be susceptible to a "symbol denial of service" attack
+# since the keys create methods and names of methods are never garbage collected.
+#
+# This may also be the source of incompatibilities between Ruby versions:
+#
+# o = OpenStruct.new
+# o.then # => nil in Ruby < 2.6, enumerator for Ruby >= 2.6
+#
+# Builtin methods may be overwritten this way, which may be a source of bugs
+# or security issues:
+#
+# o = OpenStruct.new
+# o.methods # => [:to_h, :marshal_load, :marshal_dump, :each_pair, ...
+# o.methods = [:foo, :bar]
+# o.methods # => [:foo, :bar]
+#
+# To help remedy clashes, OpenStruct uses only protected/private methods ending with `!`
+# and defines aliases for builtin public methods by adding a `!`:
+#
+# o = OpenStruct.new(make: 'Bentley', class: :luxury)
+# o.class # => :luxury
+# o.class! # => OpenStruct
+#
+# It is recommended (but not enforced) to not use fields ending in `!`;
+# Note that a subclass' methods may not be overwritten, nor can OpenStruct's own methods
+# ending with `!`.
+#
+# For all these reasons, consider not using OpenStruct at all.
#
-
-require_relative 'ostruct/version'
-
class OpenStruct
+ VERSION = "0.3.1"
#
# Creates a new OpenStruct object. By default, the resulting OpenStruct
@@ -92,19 +124,29 @@ class OpenStruct
# data # => #<OpenStruct country="Australia", capital="Canberra">
#
def initialize(hash=nil)
- @table = {}
if hash
- hash.each_pair do |k, v|
- k = k.to_sym
- @table[k] = v
- end
+ update_to_values!(hash)
+ else
+ @table = {}
end
end
# Duplicates an OpenStruct object's Hash table.
- def initialize_copy(orig) # :nodoc:
+ private def initialize_clone(orig) # :nodoc:
+ super # clones the singleton class for us
+ @table = @table.dup unless @table.frozen?
+ end
+
+ private def initialize_dup(orig) # :nodoc:
super
- @table = @table.dup
+ update_to_values!(@table)
+ end
+
+ private def update_to_values!(hash) # :nodoc:
+ @table = {}
+ hash.each_pair do |k, v|
+ set_ostruct_member_value!(k, v)
+ end
end
#
@@ -125,7 +167,7 @@ class OpenStruct
# # => {"country" => "AUSTRALIA", "capital" => "CANBERRA" }
#
def to_h(&block)
- if block_given?
+ if block
@table.to_h(&block)
else
@table.dup
@@ -153,31 +195,14 @@ class OpenStruct
#
# Provides marshalling support for use by the Marshal library.
#
- def marshal_dump
+ def marshal_dump # :nodoc:
@table
end
#
# Provides marshalling support for use by the Marshal library.
#
- def marshal_load(x)
- @table = x
- end
-
- #
- # Used internally to check if the OpenStruct is able to be
- # modified before granting access to the internal Hash table to be modified.
- #
- def modifiable? # :nodoc:
- begin
- @modifiable = true
- rescue
- exception_class = defined?(FrozenError) ? FrozenError : RuntimeError
- raise exception_class, "can't modify frozen #{self.class}", caller(3)
- end
- @table
- end
- private :modifiable?
+ alias_method :marshal_load, :update_to_values! # :nodoc:
#
# Used internally to defined properties on the
@@ -185,45 +210,42 @@ class OpenStruct
# define_singleton_method for both the getter method and the setter method.
#
def new_ostruct_member!(name) # :nodoc:
- name = name.to_sym
- unless singleton_class.method_defined?(name)
- define_singleton_method(name) { @table[name] }
- define_singleton_method("#{name}=") {|x| modifiable?[name] = x}
+ unless @table.key?(name) || is_method_protected!(name)
+ define_singleton_method!(name) { @table[name] }
+ define_singleton_method!("#{name}=") {|x| @table[name] = x}
end
- name
end
private :new_ostruct_member!
- def freeze
- @table.each_key {|key| new_ostruct_member!(key)}
- super
+ private def is_method_protected!(name) # :nodoc:
+ if !respond_to?(name, true)
+ false
+ elsif name.end_with?('!')
+ true
+ else
+ method!(name).owner < OpenStruct
+ end
end
- def respond_to_missing?(mid, include_private = false) # :nodoc:
- mname = mid.to_s.chomp("=").to_sym
- defined?(@table) && @table.key?(mname) || super
+ def freeze
+ @table.freeze
+ super
end
- def method_missing(mid, *args) # :nodoc:
+ private def method_missing(mid, *args) # :nodoc:
len = args.length
if mname = mid[/.*(?==\z)/m]
if len != 1
- raise ArgumentError, "wrong number of arguments (given #{len}, expected 1)", caller(1)
- end
- modifiable?[new_ostruct_member!(mname)] = args[0]
- elsif len == 0 # and /\A[a-z_]\w*\z/ =~ mid #
- if @table.key?(mid)
- new_ostruct_member!(mid) unless frozen?
- @table[mid]
+ raise! ArgumentError, "wrong number of arguments (given #{len}, expected 1)", caller(1)
end
- elsif @table.key?(mid)
- raise ArgumentError, "wrong number of arguments (given #{len}, expected 0)"
+ set_ostruct_member_value!(mname, args[0])
+ elsif len == 0
else
begin
super
rescue NoMethodError => err
err.backtrace.shift
- raise
+ raise!
end
end
end
@@ -232,7 +254,7 @@ class OpenStruct
# :call-seq:
# ostruct[name] -> object
#
- # Returns the value of an attribute.
+ # Returns the value of an attribute, or `nil` if there is no such attribute.
#
# require "ostruct"
# person = OpenStruct.new("name" => "John Smith", "age" => 70)
@@ -254,34 +276,32 @@ class OpenStruct
# person.age # => 42
#
def []=(name, value)
- modifiable?[new_ostruct_member!(name)] = value
+ name = name.to_sym
+ new_ostruct_member!(name)
+ @table[name] = value
end
+ alias_method :set_ostruct_member_value!, :[]=
+ private :set_ostruct_member_value!
- #
# :call-seq:
- # ostruct.dig(name, ...) -> object
+ # ostruct.dig(name, *identifiers) -> object
#
- # Extracts the nested value specified by the sequence of +name+
- # objects by calling +dig+ at each step, returning +nil+ if any
- # intermediate step is +nil+.
+ # Finds and returns the object in nested objects
+ # that is specified by +name+ and +identifiers+.
+ # The nested objects may be instances of various classes.
+ # See {Dig Methods}[rdoc-ref:doc/dig_methods.rdoc].
#
+ # Examples:
# require "ostruct"
# address = OpenStruct.new("city" => "Anytown NC", "zip" => 12345)
# person = OpenStruct.new("name" => "John Smith", "address" => address)
- #
- # person.dig(:address, "zip") # => 12345
- # person.dig(:business_address, "zip") # => nil
- #
- # data = OpenStruct.new(:array => [1, [2, 3]])
- #
- # data.dig(:array, 1, 0) # => 2
- # data.dig(:array, 0, 0) # TypeError: Integer does not have #dig method
- #
+ # person.dig(:address, "zip") # => 12345
+ # person.dig(:business_address, "zip") # => nil
def dig(name, *names)
begin
name = name.to_sym
rescue NoMethodError
- raise TypeError, "#{name} is not a symbol nor a string"
+ raise! TypeError, "#{name} is not a symbol nor a string"
end
@table.dig(name, *names)
end
@@ -294,7 +314,7 @@ class OpenStruct
#
# person = OpenStruct.new(name: "John", age: 70, pension: 300)
#
- # person.delete_field("age") # => 70
+ # person.delete_field!("age") # => 70
# person # => #<OpenStruct name="John", pension=300>
#
# Setting the value to +nil+ will not remove the attribute:
@@ -309,7 +329,7 @@ class OpenStruct
rescue NameError
end
@table.delete(sym) do
- raise NameError.new("no field `#{sym}' in #{self}", sym)
+ raise! NameError.new("no field `#{sym}' in #{self}", sym)
end
end
@@ -332,13 +352,13 @@ class OpenStruct
ids.pop
end
end
- ['#<', self.class, detail, '>'].join
+ ['#<', self.class!, detail, '>'].join
end
alias :to_s :inspect
attr_reader :table # :nodoc:
- protected :table
alias table! table
+ protected :table!
#
# Compares this object and +other+ for equality. An OpenStruct is equal to
@@ -369,11 +389,43 @@ class OpenStruct
end
# Computes a hash code for this OpenStruct.
- # Two OpenStruct objects with the same content will have the same hash code
- # (and will compare using #eql?).
- #
- # See also Object#hash.
- def hash
+ def hash # :nodoc:
@table.hash
end
+
+ #
+ # Provides marshalling support for use by the YAML library.
+ #
+ def encode_with(coder) # :nodoc:
+ @table.each_pair do |key, value|
+ coder[key.to_s] = value
+ end
+ if @table.size == 1 && @table.key?(:table) # support for legacy format
+ # in the very unlikely case of a single entry called 'table'
+ coder['legacy_support!'] = true # add a bogus second entry
+ end
+ end
+
+ #
+ # Provides marshalling support for use by the YAML library.
+ #
+ def init_with(coder) # :nodoc:
+ h = coder.map
+ if h.size == 1 # support for legacy format
+ key, val = h.first
+ if key == 'table'
+ h = val
+ end
+ end
+ update_to_values!(h)
+ end
+
+ # Make all public methods (builtin or our own) accessible with `!`:
+ instance_methods.each do |method|
+ new_name = "#{method}!"
+ alias_method new_name, method
+ end
+ # Other builtin private methods we use:
+ alias_method :raise!, :raise
+ private :raise!
end
diff --git a/lib/ostruct/ostruct.gemspec b/lib/ostruct/ostruct.gemspec
index 4f8507045e..f69a858aa2 100644
--- a/lib/ostruct/ostruct.gemspec
+++ b/lib/ostruct/ostruct.gemspec
@@ -1,24 +1,25 @@
# frozen_string_literal: true
-begin
- require_relative "lib/ostruct/version"
-rescue LoadError
- # for Ruby core repository
- require_relative "version"
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "ostruct"
- spec.version = OpenStruct::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Marc-Andre Lafortune"]
spec.email = ["ruby-core@marc-andre.ca"]
spec.summary = %q{Class to build custom data structures, similar to a Hash.}
spec.description = %q{Class to build custom data structures, similar to a Hash.}
spec.homepage = "https://github.com/ruby/ostruct"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = ">= 2.5.0"
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/ostruct.rb", "lib/ostruct/version.rb", "ostruct.gemspec"]
+ spec.files = [".gitignore", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/ostruct.rb", "ostruct.gemspec"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
diff --git a/lib/ostruct/version.rb b/lib/ostruct/version.rb
deleted file mode 100644
index 91a4044094..0000000000
--- a/lib/ostruct/version.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class OpenStruct
- VERSION = "0.2.0"
-end
diff --git a/lib/pp.gemspec b/lib/pp.gemspec
new file mode 100644
index 0000000000..b81df28bee
--- /dev/null
+++ b/lib/pp.gemspec
@@ -0,0 +1,27 @@
+Gem::Specification.new do |spec|
+ spec.name = "pp"
+ spec.version = "0.2.1"
+ spec.authors = ["Tanaka Akira"]
+ spec.email = ["akr@fsij.org"]
+
+ spec.summary = %q{Provides a PrettyPrinter for Ruby objects}
+ spec.description = %q{Provides a PrettyPrinter for Ruby objects}
+ spec.homepage = "https://github.com/ruby/pp"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = %w[
+ LICENSE.txt
+ lib/pp.rb
+ pp.gemspec
+ ]
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "prettyprint"
+end
diff --git a/lib/pp.rb b/lib/pp.rb
index 012b328aad..72480e5304 100644
--- a/lib/pp.rb
+++ b/lib/pp.rb
@@ -93,11 +93,25 @@ class PP < PrettyPrint
end
# :startdoc:
- @sharing_detection = false
- class << self
- # Returns the sharing detection flag as a boolean value.
- # It is false by default.
- attr_accessor :sharing_detection
+ if defined? ::Ractor
+ class << self
+ # Returns the sharing detection flag as a boolean value.
+ # It is false (nil) by default.
+ def sharing_detection
+ Ractor.current[:pp_sharing_detection]
+ end
+ # Sets the sharing detection flag to b.
+ def sharing_detection=(b)
+ Ractor.current[:pp_sharing_detection] = b
+ end
+ end
+ else
+ @sharing_detection = false
+ class << self
+ # Returns the sharing detection flag as a boolean value.
+ # It is false by default.
+ attr_accessor :sharing_detection
+ end
end
module PPMethods
@@ -223,16 +237,7 @@ class PP < PrettyPrint
else
sep.call
end
- case v.last
- when Hash
- if Hash.ruby2_keywords_hash?(v.last)
- yield(*v, **{})
- else
- yield(*v)
- end
- else
- yield(*v)
- end
+ RUBY_VERSION >= "3.0" ? yield(*v, **{}) : yield(*v)
}
end
diff --git a/lib/prettyprint.gemspec b/lib/prettyprint.gemspec
new file mode 100644
index 0000000000..eae2227d60
--- /dev/null
+++ b/lib/prettyprint.gemspec
@@ -0,0 +1,22 @@
+Gem::Specification.new do |spec|
+ spec.name = "prettyprint"
+ spec.version = "0.1.1"
+ spec.authors = ["Tanaka Akira"]
+ spec.email = ["akr@fsij.org"]
+
+ spec.summary = %q{Implements a pretty printing algorithm for readable structure.}
+ spec.description = %q{Implements a pretty printing algorithm for readable structure.}
+ spec.homepage = "https://github.com/ruby/prettyprint"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/prettyprint.rb b/lib/prettyprint.rb
index 2a3ca90dc1..188c2e6db0 100644
--- a/lib/prettyprint.rb
+++ b/lib/prettyprint.rb
@@ -102,7 +102,7 @@ class PrettyPrint
# The maximum width of a line, before it is separated in to a newline
#
- # This defaults to 79, and should be a Fixnum
+ # This defaults to 79, and should be an Integer
attr_reader :maxwidth
# The value that is appended to +output+ to add a new line.
@@ -110,7 +110,7 @@ class PrettyPrint
# This defaults to "\n", and should be String
attr_reader :newline
- # A lambda or Proc, that takes one argument, of a Fixnum, and returns
+ # A lambda or Proc, that takes one argument, of an Integer, and returns
# the corresponding number of spaces.
#
# By default this is:
@@ -340,7 +340,7 @@ class PrettyPrint
#
# Arguments:
# * +sep+ String of the separator
- # * +width+ Fixnum width of the +sep+
+ # * +width+ Integer width of the +sep+
# * +q+ parent PrettyPrint object, to base from
def initialize(sep, width, q)
@obj = sep
diff --git a/lib/prime.gemspec b/lib/prime.gemspec
index 6a9aa683e6..8369d4d3d5 100644
--- a/lib/prime.gemspec
+++ b/lib/prime.gemspec
@@ -8,20 +8,21 @@ end
Gem::Specification.new do |spec|
spec.name = "prime"
spec.version = Prime::VERSION
- spec.authors = ["Yuki Sonoda"]
- spec.email = ["yugui@yugui.jp"]
+ spec.authors = ["Marc-Andre Lafortune"]
+ spec.email = ["ruby-core@marc-andre.ca"]
spec.summary = %q{Prime numbers and factorization library.}
spec.description = %q{Prime numbers and factorization library.}
spec.homepage = "https://github.com/ruby/prime"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/prime.rb", "lib/prime/version.rb", "prime.gemspec"]
+ spec.files = [".gitignore", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/prime.rb", "prime.gemspec"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
- spec.add_development_dependency "bundler"
- spec.add_development_dependency "rake"
- spec.add_development_dependency "test-unit"
+ spec.required_ruby_version = ">= 2.5.0"
+
+ spec.add_dependency "singleton"
+ spec.add_dependency "forwardable"
end
diff --git a/lib/prime.rb b/lib/prime.rb
index 5be12f24f5..fd9d6ac7be 100644
--- a/lib/prime.rb
+++ b/lib/prime.rb
@@ -31,8 +31,14 @@ class Integer
end
# Returns true if +self+ is a prime number, else returns false.
+ # Not recommended for very big integers (> 10**23).
def prime?
return self >= 2 if self <= 3
+
+ if (bases = miller_rabin_bases)
+ return miller_rabin_test(bases)
+ end
+
return true if self == 5
return false unless 30.gcd(self) == 1
(7..Integer.sqrt(self)).step(30) do |p|
@@ -43,6 +49,73 @@ class Integer
true
end
+ MILLER_RABIN_BASES = [
+ [2],
+ [2,3],
+ [31,73],
+ [2,3,5],
+ [2,3,5,7],
+ [2,7,61],
+ [2,13,23,1662803],
+ [2,3,5,7,11],
+ [2,3,5,7,11,13],
+ [2,3,5,7,11,13,17],
+ [2,3,5,7,11,13,17,19,23],
+ [2,3,5,7,11,13,17,19,23,29,31,37],
+ [2,3,5,7,11,13,17,19,23,29,31,37,41],
+ ].map!(&:freeze).freeze
+ private_constant :MILLER_RABIN_BASES
+
+ private def miller_rabin_bases
+ # Miller-Rabin's complexity is O(k log^3n).
+ # So we can reduce the complexity by reducing the number of bases tested.
+ # Using values from https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test
+ i = case
+ when self < 0xffff then
+ # For small integers, Miller Rabin can be slower
+ # There is no mathematical significance to 0xffff
+ return nil
+ # when self < 2_047 then 0
+ when self < 1_373_653 then 1
+ when self < 9_080_191 then 2
+ when self < 25_326_001 then 3
+ when self < 3_215_031_751 then 4
+ when self < 4_759_123_141 then 5
+ when self < 1_122_004_669_633 then 6
+ when self < 2_152_302_898_747 then 7
+ when self < 3_474_749_660_383 then 8
+ when self < 341_550_071_728_321 then 9
+ when self < 3_825_123_056_546_413_051 then 10
+ when self < 318_665_857_834_031_151_167_461 then 11
+ when self < 3_317_044_064_679_887_385_961_981 then 12
+ else return nil
+ end
+ MILLER_RABIN_BASES[i]
+ end
+
+ private def miller_rabin_test(bases)
+ return false if even?
+
+ r = 0
+ d = self >> 1
+ while d.even?
+ d >>= 1
+ r += 1
+ end
+
+ self_minus_1 = self-1
+ bases.each do |a|
+ x = a.pow(d, self)
+ next if x == 1 || x == self_minus_1 || a == self
+
+ return false if r.times do
+ x = x.pow(2, self)
+ break if x == self_minus_1
+ end
+ end
+ true
+ end
+
# Iterates the given block over all prime numbers.
#
# See +Prime+#each for more details.
@@ -84,7 +157,7 @@ end
# There are few implementations of generator.
#
# [+Prime+::+EratosthenesGenerator+]
-# Uses eratosthenes' sieve.
+# Uses Eratosthenes' sieve.
# [+Prime+::+TrialDivisionGenerator+]
# Uses the trial division method.
# [+Prime+::+Generator23+]
@@ -96,7 +169,7 @@ end
class Prime
- VERSION = "0.1.1"
+ VERSION = "0.1.2"
include Enumerable
include Singleton
@@ -141,8 +214,22 @@ class Prime
generator.each(&block)
end
+ # Returns true if +obj+ is an Integer and is prime. Also returns
+ # true if +obj+ is a Module that is an ancestor of +Prime+.
+ # Otherwise returns false.
+ def include?(obj)
+ case obj
+ when Integer
+ prime?(obj)
+ when Module
+ Module.instance_method(:include?).bind(Prime).call(obj)
+ else
+ false
+ end
+ end
# Returns true if +value+ is a prime number, else returns false.
+ # Integer#prime? is much more performant.
#
# == Parameters
#
@@ -161,17 +248,23 @@ class Prime
# Re-composes a prime factorization and returns the product.
#
+ # For the decomposition:
+ #
+ # [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]],
+ #
+ # it returns:
+ #
+ # p_1**e_1 * p_2**e_2 * ... * p_n**e_n.
+ #
# == Parameters
- # +pd+:: Array of pairs of integers. The each internal
- # pair consists of a prime number -- a prime factor --
- # and a natural number -- an exponent.
+ # +pd+:: Array of pairs of integers.
+ # Each pair consists of a prime number -- a prime factor --
+ # and a natural number -- its exponent (multiplicity).
#
# == Example
- # For <tt>[[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]]</tt>, it returns:
- #
- # p_1**e_1 * p_2**e_2 * .... * p_n**e_n.
+ # Prime.int_from_prime_division([[3, 2], [5, 1]]) #=> 45
+ # 3**2 * 5 #=> 45
#
- # Prime.int_from_prime_division([[2,2], [3,1]]) #=> 12
def int_from_prime_division(pd)
pd.inject(1){|value, (prime, index)|
value * prime**index
@@ -180,27 +273,32 @@ class Prime
# Returns the factorization of +value+.
#
+ # For an arbitrary integer:
+ #
+ # p_1**e_1 * p_2**e_2 * ... * p_n**e_n,
+ #
+ # prime_division returns an array of pairs of integers:
+ #
+ # [[p_1, e_1], [p_2, e_2], ..., [p_n, e_n]].
+ #
+ # Each pair consists of a prime number -- a prime factor --
+ # and a natural number -- its exponent (multiplicity).
+ #
# == Parameters
# +value+:: An arbitrary integer.
# +generator+:: Optional. A pseudo-prime generator.
# +generator+.succ must return the next
- # pseudo-prime number in the ascending
- # order. It must generate all prime numbers,
- # but may also generate non prime numbers too.
+ # pseudo-prime number in ascending order.
+ # It must generate all prime numbers,
+ # but may also generate non-prime numbers, too.
#
# === Exceptions
# +ZeroDivisionError+:: when +value+ is zero.
#
# == Example
- # For an arbitrary integer:
- #
- # n = p_1**e_1 * p_2**e_2 * .... * p_n**e_n,
- #
- # prime_division(n) returns:
- #
- # [[p_1, e_1], [p_2, e_2], ...., [p_n, e_n]].
#
- # Prime.prime_division(12) #=> [[2,2], [3,1]]
+ # Prime.prime_division(45) #=> [[3, 2], [5, 1]]
+ # 3**2 * 5 #=> 45
#
def prime_division(value, generator = Prime::Generator23.new)
raise ZeroDivisionError if value == 0
diff --git a/lib/pstore.rb b/lib/pstore.rb
index 1180fd50a0..a46bcb84bc 100644
--- a/lib/pstore.rb
+++ b/lib/pstore.rb
@@ -92,6 +92,8 @@ require "digest"
# Needless to say, if you're storing valuable data with PStore, then you should
# backup the PStore files from time to time.
class PStore
+ VERSION = "0.1.1"
+
RDWR_ACCESS = {mode: IO::RDWR | IO::CREAT | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
RD_ACCESS = {mode: IO::RDONLY | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
WR_ACCESS = {mode: IO::WRONLY | IO::CREAT | IO::TRUNC | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
diff --git a/lib/pstore/pstore.gemspec b/lib/pstore/pstore.gemspec
index e781c77043..8425795afe 100644
--- a/lib/pstore/pstore.gemspec
+++ b/lib/pstore/pstore.gemspec
@@ -1,19 +1,22 @@
-begin
- require_relative "lib/pstore/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "pstore"
- spec.version = PStore::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
spec.summary = %q{Transactional File Storage for Ruby Objects}
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/pstore"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "https://github.com/ruby/pstore"
diff --git a/lib/pstore/version.rb b/lib/pstore/version.rb
deleted file mode 100644
index 0e7a3fbd15..0000000000
--- a/lib/pstore/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class PStore
- VERSION = "0.1.0"
-end
diff --git a/lib/racc/compat.rb b/lib/racc/compat.rb
index ccb033e2e0..62f4f630be 100644
--- a/lib/racc/compat.rb
+++ b/lib/racc/compat.rb
@@ -1,13 +1,14 @@
+#--
+#
#
-# $Id: 14fa1118eb3a23e85265e4f7afe2d5a297d69f9c $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-# For details of the GNU LGPL, see the file "COPYING".
+# You can distribute/modify this program under the same terms of ruby.
+# see the file "COPYING".
#
+#++
unless Object.method_defined?(:__send)
class Object
diff --git a/lib/racc/debugflags.rb b/lib/racc/debugflags.rb
index 1b5d2fe54c..ee34cf2314 100644
--- a/lib/racc/debugflags.rb
+++ b/lib/racc/debugflags.rb
@@ -1,13 +1,14 @@
+#--
+#
#
-# $Id: 74ff4369ce53c7f45cfc2644ce907785104ebf6e $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-# For details of LGPL, see the file "COPYING".
+# You can distribute/modify this program under the same terms of ruby.
+# see the file "COPYING".
#
+#++
module Racc
diff --git a/lib/racc/exception.rb b/lib/racc/exception.rb
index 0069ca3443..c11dc2e43e 100644
--- a/lib/racc/exception.rb
+++ b/lib/racc/exception.rb
@@ -1,11 +1,14 @@
+#--
+#
#
-# $Id: ebb9798ad0b211e031670a12a1ab154678c1c8f3 $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
# You can distribute/modify this program under the same terms of ruby.
# see the file "COPYING".
+#
+#++
module Racc
class Error < StandardError; end
diff --git a/lib/racc/grammar.rb b/lib/racc/grammar.rb
index 123f1f1834..3444dfcce3 100644
--- a/lib/racc/grammar.rb
+++ b/lib/racc/grammar.rb
@@ -1,11 +1,14 @@
+#--
+#
#
-# $Id: 3fcabd58bef02540bf78e8142469681cb9f975c2 $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
# You can distribute/modify this program under the same terms of ruby.
# see the file "COPYING".
+#
+#++
require 'racc/compat'
require 'racc/iset'
@@ -83,14 +86,15 @@ module Racc
end
def n_useless_nonterminals
- @n_useless_nonterminals ||=
- begin
- n = 0
- @symboltable.each_nonterminal do |sym|
- n += 1 if sym.useless?
- end
- n
- end
+ @n_useless_nonterminals ||= each_useless_nonterminal.count
+ end
+
+ def each_useless_nonterminal
+ return to_enum __method__ unless block_given?
+
+ @symboltable.each_nonterminal do |sym|
+ yield sym if sym.useless?
+ end
end
def useless_rule_exist?
@@ -98,14 +102,15 @@ module Racc
end
def n_useless_rules
- @n_useless_rules ||=
- begin
- n = 0
- each do |r|
- n += 1 if r.useless?
- end
- n
- end
+ @n_useless_rules ||= each_useless_rule.count
+ end
+
+ def each_useless_rule
+ return to_enum __method__ unless block_given?
+
+ each do |r|
+ yield r if r.useless?
+ end
end
def nfa
diff --git a/lib/racc/grammarfileparser.rb b/lib/racc/grammarfileparser.rb
index 5e7081f00a..419495113b 100644
--- a/lib/racc/grammarfileparser.rb
+++ b/lib/racc/grammarfileparser.rb
@@ -1,13 +1,14 @@
+#--
+#
#
-# $Id: 63bd084db2dce8a2c9760318faae6104717cead7 $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-# For details of the GNU LGPL, see the file "COPYING".
+# You can distribute/modify this program under the same terms of ruby.
+# see the file "COPYING".
#
+#++
require 'racc'
require 'racc/compat'
@@ -286,7 +287,7 @@ module Racc
end
def add_user_code(label, src)
- @result.params.send(USER_CODE_LABELS[label]).push src
+ @result.params.public_send(USER_CODE_LABELS[label]).push src
end
end
@@ -427,7 +428,7 @@ module Racc
$raccs_print_type = false
def scan_action
- buf = ''
+ buf = String.new
nest = 1
pre = nil
@in_block = 'action'
diff --git a/lib/racc/info.rb b/lib/racc/info.rb
index b7db7b6c9b..f599b13cbb 100644
--- a/lib/racc/info.rb
+++ b/lib/racc/info.rb
@@ -1,14 +1,17 @@
+#--
+#
#
-# $Id: 8ab2cb5341529fe5e35956bb1a1f42ec9b9c6f5a $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
# You can distribute/modify this program under the same terms of ruby.
# see the file "COPYING".
+#
+#++
module Racc
- VERSION = '1.4.16'
+ VERSION = '1.5.2'
Version = VERSION
Copyright = 'Copyright (c) 1999-2006 Minero Aoki'
end
diff --git a/lib/racc/iset.rb b/lib/racc/iset.rb
index 245bad8b50..339221d21b 100644
--- a/lib/racc/iset.rb
+++ b/lib/racc/iset.rb
@@ -1,13 +1,14 @@
+#--
+#
#
-# $Id: 31aa4331c08dfd4609c06eb5f94b7ef38dc708e1 $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-# For details of the GNU LGPL, see the file "COPYING".
+# You can distribute/modify this program under the same terms of ruby.
+# see the file "COPYING".
#
+#++
module Racc
diff --git a/lib/racc/logfilegenerator.rb b/lib/racc/logfilegenerator.rb
index 68593c41f6..2f5aa0c8b0 100644
--- a/lib/racc/logfilegenerator.rb
+++ b/lib/racc/logfilegenerator.rb
@@ -1,13 +1,14 @@
+#--
+#
#
-# $Id: 5e9d0a01b5d56fd9cdc3d5cb078b1a3e1bbaf779 $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-# For details of the GNU LGPL, see the file "COPYING".
+# You can distribute/modify this program under the same terms of ruby.
+# see the file "COPYING".
#
+#++
module Racc
diff --git a/lib/racc/parser-text.rb b/lib/racc/parser-text.rb
index 31b8e2c01f..7090c6a01a 100644
--- a/lib/racc/parser-text.rb
+++ b/lib/racc/parser-text.rb
@@ -31,7 +31,7 @@ end
# == Command-line Reference
#
# racc [-o<var>filename</var>] [--output-file=<var>filename</var>]
-# [-e<var>rubypath</var>] [--embedded=<var>rubypath</var>]
+# [-e<var>rubypath</var>] [--executable=<var>rubypath</var>]
# [-v] [--verbose]
# [-O<var>filename</var>] [--log-file=<var>filename</var>]
# [-g] [--debug]
@@ -43,7 +43,7 @@ end
# [-S] [--output-status]
# [--version] [--copyright] [--help] <var>grammarfile</var>
#
-# [+filename+]
+# [+grammarfile+]
# Racc grammar file. Any extension is permitted.
# [-o+outfile+, --output-file=+outfile+]
# A filename for output. default is <+filename+>.tab.rb
@@ -181,45 +181,39 @@ end
# Your own parser is completely yours.
module Racc
- unless defined?(Racc_No_Extentions)
- Racc_No_Extentions = false # :nodoc:
+ unless defined?(Racc_No_Extensions)
+ Racc_No_Extensions = false # :nodoc:
end
class Parser
Racc_Runtime_Version = ::Racc::VERSION
- Racc_Runtime_Revision = '$Id: 7adc21ee7a5690f10b7ff399b8af4e2717b9d94c $'
-
Racc_Runtime_Core_Version_R = ::Racc::VERSION
- Racc_Runtime_Core_Revision_R = '$Id: 7adc21ee7a5690f10b7ff399b8af4e2717b9d94c $'.split[1]
+
begin
if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby'
+ require 'jruby'
require 'racc/cparse-jruby.jar'
com.headius.racc.Cparse.new.load(JRuby.runtime, false)
else
require 'racc/cparse'
end
- # Racc_Runtime_Core_Version_C = (defined in extension)
- Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2]
+
unless new.respond_to?(:_racc_do_parse_c, true)
raise LoadError, 'old cparse.so'
end
- if Racc_No_Extentions
+ if Racc_No_Extensions
raise LoadError, 'selecting ruby version of racc runtime core'
end
Racc_Main_Parsing_Routine = :_racc_do_parse_c # :nodoc:
Racc_YY_Parse_Method = :_racc_yyparse_c # :nodoc:
Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C # :nodoc:
- Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C # :nodoc:
Racc_Runtime_Type = 'c' # :nodoc:
rescue LoadError
-puts $!
-puts $!.backtrace
Racc_Main_Parsing_Routine = :_racc_do_parse_rb
Racc_YY_Parse_Method = :_racc_yyparse_rb
Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R
- Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R
Racc_Runtime_Type = 'ruby'
end
@@ -332,7 +326,7 @@ puts $!.backtrace
# It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE].
class_eval %{
def yyparse(recv, mid)
- #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), true)
+ #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), false)
end
}
diff --git a/lib/racc/parser.rb b/lib/racc/parser.rb
index 56b4af9dea..df94e85eb7 100644
--- a/lib/racc/parser.rb
+++ b/lib/racc/parser.rb
@@ -29,7 +29,7 @@ end
# == Command-line Reference
#
# racc [-o<var>filename</var>] [--output-file=<var>filename</var>]
-# [-e<var>rubypath</var>] [--embedded=<var>rubypath</var>]
+# [-e<var>rubypath</var>] [--executable=<var>rubypath</var>]
# [-v] [--verbose]
# [-O<var>filename</var>] [--log-file=<var>filename</var>]
# [-g] [--debug]
@@ -41,7 +41,7 @@ end
# [-S] [--output-status]
# [--version] [--copyright] [--help] <var>grammarfile</var>
#
-# [+filename+]
+# [+grammarfile+]
# Racc grammar file. Any extension is permitted.
# [-o+outfile+, --output-file=+outfile+]
# A filename for output. default is <+filename+>.tab.rb
@@ -179,45 +179,39 @@ end
# Your own parser is completely yours.
module Racc
- unless defined?(Racc_No_Extentions)
- Racc_No_Extentions = false # :nodoc:
+ unless defined?(Racc_No_Extensions)
+ Racc_No_Extensions = false # :nodoc:
end
class Parser
Racc_Runtime_Version = ::Racc::VERSION
- Racc_Runtime_Revision = '$Id: e754525bd317344c4284fca6fdce0a425979ade1 $'
-
Racc_Runtime_Core_Version_R = ::Racc::VERSION
- Racc_Runtime_Core_Revision_R = '$Id: e754525bd317344c4284fca6fdce0a425979ade1 $'.split[1]
+
begin
if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby'
+ require 'jruby'
require 'racc/cparse-jruby.jar'
com.headius.racc.Cparse.new.load(JRuby.runtime, false)
else
require 'racc/cparse'
end
- # Racc_Runtime_Core_Version_C = (defined in extension)
- Racc_Runtime_Core_Revision_C = Racc_Runtime_Core_Id_C.split[2]
+
unless new.respond_to?(:_racc_do_parse_c, true)
raise LoadError, 'old cparse.so'
end
- if Racc_No_Extentions
+ if Racc_No_Extensions
raise LoadError, 'selecting ruby version of racc runtime core'
end
Racc_Main_Parsing_Routine = :_racc_do_parse_c # :nodoc:
Racc_YY_Parse_Method = :_racc_yyparse_c # :nodoc:
Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C # :nodoc:
- Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_C # :nodoc:
Racc_Runtime_Type = 'c' # :nodoc:
rescue LoadError
-puts $!
-puts $!.backtrace
Racc_Main_Parsing_Routine = :_racc_do_parse_rb
Racc_YY_Parse_Method = :_racc_yyparse_rb
Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R
- Racc_Runtime_Core_Revision = Racc_Runtime_Core_Revision_R
Racc_Runtime_Type = 'ruby'
end
@@ -330,7 +324,7 @@ puts $!.backtrace
# It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE].
class_eval %{
def yyparse(recv, mid)
- #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), true)
+ #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), false)
end
}
diff --git a/lib/racc/parserfilegenerator.rb b/lib/racc/parserfilegenerator.rb
index ee1262db29..fb6c209536 100644
--- a/lib/racc/parserfilegenerator.rb
+++ b/lib/racc/parserfilegenerator.rb
@@ -1,13 +1,15 @@
+#--
+#
#
-# $Id: fff07ebfd582f8dbc845e424908cb9f41f8bf42f $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
# You can distribute/modify this program under the same terms of ruby.
# see the file "COPYING".
+#
+#++
-require 'enumerator'
require 'racc/compat'
require 'racc/sourcetext'
require 'racc/parser-text'
@@ -235,7 +237,7 @@ module Racc
end
def unique_separator(id)
- sep = "...end #{id}/module_eval..."
+ sep = String.new "...end #{id}/module_eval..."
while @used_separator.key?(sep)
sep.concat sprintf('%02x', rand(255))
end
@@ -329,7 +331,7 @@ module Racc
# TODO: this can be made a LOT more clean with a simple split/map
sep = "\n"
nsep = ",\n"
- buf = ''
+ buf = String.new
com = ''
ncom = ','
co = com
@@ -339,7 +341,7 @@ module Racc
if buf.size > 66
@f.print sep; sep = nsep
@f.print "'", buf, "'"
- buf = ''
+ buf = String.new
co = com
end
end
diff --git a/lib/racc/racc.gemspec b/lib/racc/racc.gemspec
index 6beb16c5b4..5c345891ad 100644
--- a/lib/racc/racc.gemspec
+++ b/lib/racc/racc.gemspec
@@ -1,8 +1,14 @@
# -*- encoding: utf-8 -*-
+begin
+ require_relative "lib/racc/info"
+rescue LoadError # Fallback to load version file in ruby core repository
+ require_relative "info"
+end
+
Gem::Specification.new do |s|
s.name = "racc"
- s.version = "1.4.16"
+ s.version = Racc::VERSION
s.summary = "Racc is a LALR(1) parser generator"
s.description = <<DESC
Racc is a LALR(1) parser generator.
@@ -15,15 +21,15 @@ DESC
s.authors = ["Minero Aoki", "Aaron Patterson"]
s.email = [nil, "aaron@tenderlovemaking.com"]
s.homepage = "http://i.loveruby.net/en/projects/racc/"
- s.licenses = ["MIT"]
- s.executables = ["racc", "racc2y", "y2racc"]
+ s.licenses = ["Ruby", "BSD-2-Clause"]
+ s.executables = ["racc"]
s.files = [
- "COPYING", "ChangeLog", "DEPENDS", "Manifest.txt",
+ "COPYING", "ChangeLog",
"README.ja.rdoc", "README.rdoc", "Rakefile", "TODO", "bin/racc",
- "bin/racc2y", "bin/y2racc", "ext/racc/MANIFEST",
- "ext/racc/com/headius/racc/Cparse.java", "ext/racc/cparse.c",
- "ext/racc/depend", "ext/racc/extconf.rb", "fastcache/extconf.rb",
- "fastcache/fastcache.c", "lib/racc.rb", "lib/racc/compat.rb",
+ "ext/racc/MANIFEST",
+ "ext/racc/com/headius/racc/Cparse.java", "ext/racc/cparse/cparse.c",
+ "ext/racc/cparse/extconf.rb",
+ "lib/racc.rb", "lib/racc/compat.rb",
"lib/racc/debugflags.rb", "lib/racc/exception.rb",
"lib/racc/grammar.rb", "lib/racc/grammarfileparser.rb",
"lib/racc/info.rb", "lib/racc/iset.rb",
@@ -31,7 +37,7 @@ DESC
"lib/racc/parser.rb", "lib/racc/parserfilegenerator.rb",
"lib/racc/pre-setup", "lib/racc/sourcetext.rb",
"lib/racc/state.rb", "lib/racc/statetransitiontable.rb",
- "lib/racc/static.rb", "misc/dist.sh", "rdoc/en/NEWS.en.rdoc",
+ "lib/racc/static.rb", "rdoc/en/NEWS.en.rdoc",
"rdoc/en/grammar.en.rdoc", "rdoc/ja/NEWS.ja.rdoc",
"rdoc/ja/command.ja.html", "rdoc/ja/debug.ja.rdoc",
"rdoc/ja/grammar.ja.rdoc", "rdoc/ja/index.ja.html",
@@ -39,7 +45,7 @@ DESC
"sample/array.y", "sample/array2.y", "sample/calc-ja.y",
"sample/calc.y", "sample/conflict.y", "sample/hash.y",
"sample/lalr.y", "sample/lists.y", "sample/syntax.y",
- "sample/yyerr.y", "setup.rb", "tasks/doc.rb", "tasks/email.rb",
+ "sample/yyerr.y",
"test/assets/cadenza.y", "test/assets/cast.y",
"test/assets/chk.y", "test/assets/conf.y",
"test/assets/csspool.y", "test/assets/digraph.y",
@@ -82,12 +88,10 @@ DESC
"test/testscanner.rb", "web/racc.en.rhtml", "web/racc.ja.rhtml"
]
s.require_paths = ["lib"]
- s.rubygems_version = "3.1.0.pre1"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
- s.extensions = ["ext/racc/extconf.rb"]
s.rdoc_options = ["--main", "README.rdoc"]
s.extra_rdoc_files = [
- "Manifest.txt", "README.ja.rdoc", "README.rdoc",
+ "README.ja.rdoc", "README.rdoc",
"rdoc/en/NEWS.en.rdoc", "rdoc/en/grammar.en.rdoc",
"rdoc/ja/NEWS.ja.rdoc", "rdoc/ja/debug.ja.rdoc",
"rdoc/ja/grammar.ja.rdoc", "rdoc/ja/parser.ja.rdoc",
@@ -96,10 +100,8 @@ DESC
if RUBY_PLATFORM =~ /java/
s.files << 'lib/racc/cparse-jruby.jar'
+ s.platform = 'java'
+ else
+ s.extensions = ["ext/racc/cparse/extconf.rb"]
end
-
- s.add_development_dependency("rake-compiler", [">= 0.4.1"])
- s.add_development_dependency("minitest", ["~> 4.7"])
- s.add_development_dependency("rdoc", [">= 4.0", "< 7"])
- s.add_development_dependency("hoe", ["~> 3.18"])
end
diff --git a/lib/racc/sourcetext.rb b/lib/racc/sourcetext.rb
index b33ba29291..de52dcae9b 100644
--- a/lib/racc/sourcetext.rb
+++ b/lib/racc/sourcetext.rb
@@ -1,13 +1,14 @@
+#--
+#
#
-# $Id: 3b2d89d9ada2f5fcb043837dcc5c9631856d5b70 $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-# For details of LGPL, see the file "COPYING".
+# You can distribute/modify this program under the same terms of ruby.
+# see the file "COPYING".
#
+#++
module Racc
diff --git a/lib/racc/state.rb b/lib/racc/state.rb
index 51b1d83664..f85809fbeb 100644
--- a/lib/racc/state.rb
+++ b/lib/racc/state.rb
@@ -1,11 +1,14 @@
+#--
+#
#
-# $Id: 6bd3136439c94cb8d928917f5e0de9c593181527 $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
# You can distribute/modify this program under the same terms of ruby.
# see the file "COPYING".
+#
+#++
require 'racc/iset'
require 'racc/statetransitiontable'
diff --git a/lib/racc/statetransitiontable.rb b/lib/racc/statetransitiontable.rb
index 23df4102ec..4252ba0184 100644
--- a/lib/racc/statetransitiontable.rb
+++ b/lib/racc/statetransitiontable.rb
@@ -1,13 +1,14 @@
+#--
+#
#
-# $Id: 4c5f4311663b6d03050953d64d6a0e7905ff2216 $
#
# Copyright (c) 1999-2006 Minero Aoki
#
# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-# For details of LGPL, see the file "COPYING".
+# You can distribute/modify this program under the same terms of ruby.
+# see the file "COPYING".
#
+#++
require 'racc/parser'
@@ -196,7 +197,7 @@ module Racc
def mkmapexp(arr)
i = ii = 0
as = arr.size
- map = ''
+ map = String.new
maxdup = RE_DUP_MAX
curr = nil
while i < as
@@ -229,7 +230,7 @@ module Racc
map = '-' * 10240
# sort long to short
- entries.sort! {|a,b| b[0].size <=> a[0].size }
+ entries.sort_by!.with_index {|a,i| [-a[0].size, i] }
entries.each do |arr, chkval, expr, min, ptri|
if upper + arr.size > map.size
diff --git a/lib/rdoc.rb b/lib/rdoc.rb
index fc8ad9e144..2d3f8c1122 100644
--- a/lib/rdoc.rb
+++ b/lib/rdoc.rb
@@ -120,6 +120,27 @@ module RDoc
end
end
+ def self.home
+ rdoc_dir = begin
+ File.expand_path('~/.rdoc')
+ rescue ArgumentError
+ end
+
+ if File.directory?(rdoc_dir)
+ rdoc_dir
+ else
+ begin
+ # XDG
+ xdg_data_home = ENV["XDG_DATA_HOME"] || File.join(File.expand_path("~"), '.local', 'share')
+ unless File.exist?(xdg_data_home)
+ FileUtils.mkdir_p xdg_data_home
+ end
+ File.join xdg_data_home, "rdoc"
+ rescue Errno::EACCES
+ end
+ end
+ end
+
autoload :RDoc, 'rdoc/rdoc'
autoload :CrossReference, 'rdoc/cross_reference'
diff --git a/lib/rdoc/any_method.rb b/lib/rdoc/any_method.rb
index 9b0d309653..562e68461c 100644
--- a/lib/rdoc/any_method.rb
+++ b/lib/rdoc/any_method.rb
@@ -26,12 +26,6 @@ class RDoc::AnyMethod < RDoc::MethodAttr
attr_accessor :c_function
- ##
- # Different ways to call this method
-
- attr_reader :call_seq
-
- ##
# Parameters for this method
attr_accessor :params
@@ -94,6 +88,19 @@ class RDoc::AnyMethod < RDoc::MethodAttr
end
##
+ # Different ways to call this method
+
+ def call_seq
+ unless call_seq = _call_seq
+ call_seq = is_alias_for._call_seq if is_alias_for
+ end
+
+ return unless call_seq
+
+ deduplicate_call_seq(call_seq)
+ end
+
+ ##
# Sets the different ways you can call this method. If an empty +call_seq+
# is given nil is assumed.
#
@@ -312,5 +319,43 @@ class RDoc::AnyMethod < RDoc::MethodAttr
@superclass_method
end
-end
+ protected
+
+ ##
+ # call_seq without deduplication and alias lookup.
+
+ def _call_seq
+ @call_seq if defined?(@call_seq) && @call_seq
+ end
+
+ private
+
+ ##
+ # call_seq with alias examples information removed, if this
+ # method is an alias method.
+
+ def deduplicate_call_seq(call_seq)
+ return call_seq unless is_alias_for || !aliases.empty?
+
+ method_name = self.name
+ method_name = method_name[0, 1] if method_name =~ /\A\[/
+ entries = call_seq.split "\n"
+
+ ignore = aliases.map(&:name)
+ if is_alias_for
+ ignore << is_alias_for.name
+ ignore.concat is_alias_for.aliases.map(&:name)
+ end
+ ignore.map! { |n| n =~ /\A\[/ ? n[0, 1] : n}
+ ignore.delete(method_name)
+ ignore = Regexp.union(ignore)
+
+ matching = entries.reject do |entry|
+ entry =~ /^\w*\.?#{ignore}/ or
+ entry =~ /\s#{ignore}\s/
+ end
+
+ matching.join "\n"
+ end
+end
diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb
index 6caf0d6712..b3caa53aa1 100644
--- a/lib/rdoc/context.rb
+++ b/lib/rdoc/context.rb
@@ -992,11 +992,19 @@ class RDoc::Context < RDoc::CodeObject
##
# Instance methods
+
+ def instance_methods
+ @instance_methods ||= method_list.reject { |a| a.singleton }
+ end
+
+ ##
+ # Instance methods
#--
- # TODO rename to instance_methods
+ # TODO remove this later
def instance_method_list
- @instance_method_list ||= method_list.reject { |a| a.singleton }
+ warn '#instance_method_list is obsoleted, please use #instance_methods'
+ @instance_methods ||= method_list.reject { |a| a.singleton }
end
##
diff --git a/lib/rdoc/context/section.rb b/lib/rdoc/context/section.rb
index 11f9ceaf87..5fef4a9ffc 100644
--- a/lib/rdoc/context/section.rb
+++ b/lib/rdoc/context/section.rb
@@ -34,8 +34,6 @@ class RDoc::Context::Section
attr_reader :title
- @@sequence = "SEC00000"
-
##
# Creates a new section with +title+ and +comment+
@@ -43,9 +41,6 @@ class RDoc::Context::Section
@parent = parent
@title = title ? title.strip : title
- @@sequence = @@sequence.succ
- @sequence = @@sequence.dup
-
@comments = []
add_comment comment
@@ -233,13 +228,5 @@ class RDoc::Context::Section
end
end
- ##
- # Section sequence number (deprecated)
-
- def sequence
- warn "RDoc::Context::Section#sequence is deprecated, use #aref"
- @sequence
- end
-
end
diff --git a/lib/rdoc/cross_reference.rb b/lib/rdoc/cross_reference.rb
index 07ba14c5c3..99a64cd99a 100644
--- a/lib/rdoc/cross_reference.rb
+++ b/lib/rdoc/cross_reference.rb
@@ -19,7 +19,7 @@ class RDoc::CrossReference
#
# See CLASS_REGEXP_STR
- METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%|===|\[\]=?|<<|>>|-|\+|\*)(?:\([\w.+*/=<>-]*\))?'
+ METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%|===|\[\]=?|<<|>>|\+@|-@|-|\+|\*)(?:\([\w.+*/=<>-]*\))?'
##
# Regular expressions matching text that should potentially have
@@ -173,7 +173,7 @@ class RDoc::CrossReference
end unless ref
# Try a page name
- ref = @store.page name if not ref and name =~ /^\w+$/
+ ref = @store.page name if not ref and name =~ /^[\w.]+$/
ref = nil if RDoc::Alias === ref # external alias, can't link to it
diff --git a/lib/rdoc/erb_partial.rb b/lib/rdoc/erb_partial.rb
index 8dc2c46013..d6e3f41b7e 100644
--- a/lib/rdoc/erb_partial.rb
+++ b/lib/rdoc/erb_partial.rb
@@ -12,7 +12,7 @@ class RDoc::ERBPartial < ERB
def set_eoutvar compiler, eoutvar = '_erbout'
super
- compiler.pre_cmd = ["#{eoutvar} ||= ''"]
+ compiler.pre_cmd = ["#{eoutvar} ||= +''"]
end
end
diff --git a/lib/rdoc/erbio.rb b/lib/rdoc/erbio.rb
index 820a25ae01..0d5f96e133 100644
--- a/lib/rdoc/erbio.rb
+++ b/lib/rdoc/erbio.rb
@@ -20,11 +20,11 @@ class RDoc::ERBIO < ERB
##
# Defaults +eoutvar+ to 'io', otherwise is identical to ERB's initialize
- def initialize str, safe_level = nil, trim_mode = nil, eoutvar = 'io'
+ def initialize str, safe_level = nil, legacy_trim_mode = nil, legacy_eoutvar = 'io', trim_mode: nil, eoutvar: 'io'
if RUBY_VERSION >= '2.6'
super(str, trim_mode: trim_mode, eoutvar: eoutvar)
else
- super
+ super(str, safe_level, legacy_trim_mode, legacy_eoutvar)
end
end
diff --git a/lib/rdoc/generator/darkfish.rb b/lib/rdoc/generator/darkfish.rb
index c5d47ef355..b46861d009 100644
--- a/lib/rdoc/generator/darkfish.rb
+++ b/lib/rdoc/generator/darkfish.rb
@@ -4,7 +4,7 @@
require 'erb'
require 'fileutils'
require 'pathname'
-require 'rdoc/generator/markup'
+require_relative 'markup'
##
# Darkfish RDoc HTML Generator
@@ -779,9 +779,9 @@ class RDoc::Generator::Darkfish
end
if RUBY_VERSION >= '2.6'
- template = klass.new template, trim_mode: '<>', eoutvar: erbout
+ template = klass.new template, trim_mode: '-', eoutvar: erbout
else
- template = klass.new template, nil, '<>', erbout
+ template = klass.new template, nil, '-', erbout
end
@template_cache[file] = template
template
diff --git a/lib/rdoc/generator/pot.rb b/lib/rdoc/generator/pot.rb
index a12cba7505..bee1133b07 100644
--- a/lib/rdoc/generator/pot.rb
+++ b/lib/rdoc/generator/pot.rb
@@ -91,8 +91,8 @@ class RDoc::Generator::POT
extractor.extract
end
- require 'rdoc/generator/pot/message_extractor'
- require 'rdoc/generator/pot/po'
- require 'rdoc/generator/pot/po_entry'
+ require_relative 'pot/message_extractor'
+ require_relative 'pot/po'
+ require_relative 'pot/po_entry'
end
diff --git a/lib/rdoc/generator/template/darkfish/_head.rhtml b/lib/rdoc/generator/template/darkfish/_head.rhtml
index 8304310d4b..e61fce1b9a 100644
--- a/lib/rdoc/generator/template/darkfish/_head.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_head.rhtml
@@ -15,9 +15,8 @@
<link href="<%= asset_rel_prefix %>/css/fonts.css" rel="stylesheet">
<link href="<%= asset_rel_prefix %>/css/rdoc.css" rel="stylesheet">
-<% if @options.template_stylesheets.flatten.any? then %>
-<% @options.template_stylesheets.flatten.each do |stylesheet| %>
+<%- if @options.template_stylesheets.flatten.any? then -%>
+<%- @options.template_stylesheets.flatten.each do |stylesheet| -%>
<link href="<%= asset_rel_prefix %>/<%= File.basename stylesheet %>" rel="stylesheet">
-<% end %>
-<% end %>
-
+<%- end -%>
+<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml
index e889f8063d..22a12d9e95 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml
@@ -1,4 +1,4 @@
-<% if !svninfo.empty? then %>
+<%- if !svninfo.empty? then %>
<div id="file-svninfo-section" class="nav-section">
<h3>VCS Info</h3>
@@ -16,4 +16,4 @@
</dl>
</div>
</div>
-<% end %>
+<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
index fe54d8339f..530f25c762 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
@@ -2,8 +2,8 @@
<h3>Class and Module Index</h3>
<ul class="link-list">
- <% @modsort.each do |index_klass| %>
+ <%- @modsort.each do |index_klass| -%>
<li><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.full_name %></a>
- <% end %>
+ <%- end -%>
</ul>
</div>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml
index 2bd8efee99..7602076c96 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml
@@ -1,15 +1,15 @@
-<% unless klass.extends.empty? then %>
+<%- 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 %>
+ <%- 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 %>
+ <%- else -%>
<li><span class="extend"><%= ext.name %></span>
- <% end %>
- <% end %>
+ <%- end -%>
+ <%- end -%>
</ul>
</div>
-<% end %>
+<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml
index 0ba1d2be80..74869a4b51 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml
@@ -2,8 +2,8 @@
<h3>Defined In</h3>
<ul>
-<% klass.in_files.each do |tl| %>
+<%- klass.in_files.each do |tl| -%>
<li><%= h tl.relative_name %>
-<% end %>
+<%- end -%>
</ul>
</div>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml
index d141098ecd..5b600e5975 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml
@@ -1,15 +1,15 @@
-<% unless klass.includes.empty? then %>
+<%- 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 %>
+ <%- 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 %>
+ <%- else -%>
<li><span class="include"><%= inc.name %></span>
- <% end %>
- <% end %>
+ <%- end -%>
+ <%- end -%>
</ul>
</div>
-<% end %>
+<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml
index 1285bfd732..faed7e0a94 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml
@@ -2,14 +2,14 @@
<h3>Documentation</h3>
<ul>
- <% installed.each do |name, href, exists, type, _| %>
- <% next if type == :extra %>
+ <%- installed.each do |name, href, exists, type, _| -%>
+ <%- next if type == :extra -%>
<li class="folder">
- <% if exists then %>
+ <%- if exists then -%>
<a href="<%= href %>"><%= h name %></a>
- <% else %>
+ <%- else -%>
<%= h name %>
- <% end %>
- <% end %>
+ <%- end -%>
+ <%- end -%>
</ul>
</div>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml
index 45df08d8fe..5b4c295bed 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml
@@ -1,12 +1,12 @@
-<% unless klass.method_list.empty? then %>
+<%- 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 %>
+ <%- 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 %>
+<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
index 5f39825f08..8ec83abda2 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
@@ -1,12 +1,12 @@
-<% simple_files = @files.select { |f| f.text? } %>
-<% unless simple_files.empty? then %>
+<%- simple_files = @files.select { |f| f.text? } %>
+<%- unless simple_files.empty? then -%>
<div id="fileindex-section" class="nav-section">
<h3>Pages</h3>
<ul class="link-list">
- <% simple_files.each do |f| %>
+ <%- simple_files.each do |f| -%>
<li><a href="<%= rel_prefix %>/<%= f.path %>"><%= h f.page_name %></a>
- <% end %>
+ <%- end -%>
</ul>
</div>
-<% end %>
+<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml
index cc04852652..1420da3201 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml
@@ -1,11 +1,11 @@
-<% if klass.type == 'class' then %>
+<%- 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 %>
+ <%- 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 %>
+ <%- else -%>
<p class="link"><%= klass.superclass %>
- <% end %>
+ <%- end -%>
</div>
-<% end %>
+<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml
index 15ff78ba91..6dcd2ae81f 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml
@@ -1,11 +1,11 @@
-<% unless klass.sections.length == 1 then %>
+<%- 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| %>
+ <%- klass.sort_sections.each do |section| -%>
<li><a href="#<%= section.aref %>"><%= h section.title %></a></li>
- <% end %>
+ <%- end -%>
</ul>
</div>
-<% end %>
+<%- 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
index b58e6b3c61..bf70819f64 100644
--- a/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml
@@ -1,4 +1,4 @@
-<% comment = if current.respond_to? :comment_location then
+<%- comment = if current.respond_to? :comment_location then
current.comment_location
else
current.comment
@@ -10,9 +10,9 @@
<h3>Table of Contents</h3>
<ul class="link-list" role="directory">
-<% table.each do |heading| %>
+<%- table.each do |heading| -%>
<li><a href="#<%= heading.label current %>"><%= heading.plain_html %></a>
-<% end %>
+<%- end -%>
</ul>
</div>
-<% end %>
+<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/class.rhtml b/lib/rdoc/generator/template/darkfish/class.rhtml
index 7733095086..5d7b6a1b80 100644
--- a/lib/rdoc/generator/template/darkfish/class.rhtml
+++ b/lib/rdoc/generator/template/darkfish/class.rhtml
@@ -25,9 +25,9 @@
<%= klass.description %>
</section>
- <% klass.each_section do |section, constants, attributes| %>
+ <%- klass.each_section do |section, constants, attributes| -%>
<section id="<%= section.aref %>" class="documentation-section">
- <% if section.title then %>
+ <%- if section.title then -%>
<header class="documentation-section-title">
<h2>
<%= section.title %>
@@ -36,39 +36,39 @@
<a href="#top">&uarr; top</a>
</span>
</header>
- <% end %>
+ <%- end -%>
- <% if section.comment then %>
+ <%- if section.comment then -%>
<div>
<%= section.description %>
</div>
- <% end %>
+ <%- end -%>
- <% unless constants.empty? then %>
+ <%- unless constants.empty? then -%>
<section class="constants-list">
<header>
<h3>Constants</h3>
</header>
<dl>
- <% constants.each do |const| %>
+ <%- constants.each do |const| -%>
<dt id="<%= const.name %>"><%= const.name %>
- <% if const.comment then %>
+ <%- if const.comment then -%>
<dd><%= const.description.strip %>
- <% else %>
+ <%- else -%>
<dd class="missing-docs">(Not documented)
- <% end %>
- <% end %>
+ <%- end -%>
+ <%- end -%>
</dl>
</section>
- <% end %>
+ <%- end -%>
- <% unless attributes.empty? then %>
+ <%- unless attributes.empty? then -%>
<section class="attribute-method-details" class="method-section">
<header>
<h3>Attributes</h3>
</header>
- <% attributes.each do |attrib| %>
+ <%- 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
@@ -76,18 +76,18 @@
</div>
<div class="method-description">
- <% if attrib.comment then %>
+ <%- if attrib.comment then -%>
<%= attrib.description.strip %>
- <% else %>
+ <%- else -%>
<p class="missing-docs">(Not documented)
- <% end %>
+ <%- end -%>
</div>
</div>
- <% end %>
+ <%- end -%>
</section>
- <% end %>
+ <%- end -%>
- <% klass.methods_by_type(section).each do |type, visibilities|
+ <%- klass.methods_by_type(section).each do |type, visibilities|
next if visibilities.empty?
visibilities.each do |visibility, methods|
next if methods.empty? %>
@@ -96,38 +96,38 @@
<h3><%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods</h3>
</header>
- <% methods.each do |method| %>
+ <%- methods.each do |method| -%>
<div id="<%= method.aref %>" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>">
- <% if method.call_seq then %>
- <% method.call_seq.strip.split("\n").each_with_index do |call_seq, i| %>
+ <%- if (call_seq = method.call_seq) then -%>
+ <%- call_seq.strip.split("\n").each_with_index do |call_seq, i| -%>
<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 %>
+ <%- if i == 0 and method.token_stream then -%>
<span class="method-click-advice">click to toggle source</span>
- <% end %>
+ <%- end -%>
</div>
- <% end %>
- <% else %>
+ <%- end -%>
+ <%- 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 %>
+ <%- if method.token_stream then -%>
<span class="method-click-advice">click to toggle source</span>
- <% end %>
+ <%- end -%>
</div>
- <% end %>
+ <%- end -%>
<div class="method-description">
- <% if method.comment then %>
+ <%- if method.comment then -%>
<%= method.description.strip %>
- <% else %>
+ <%- else -%>
<p class="missing-docs">(Not documented)
- <% end %>
- <% if method.calls_super then %>
+ <%- end -%>
+ <%- if method.calls_super then -%>
<div class="method-calls-super">
Calls superclass method
<%=
@@ -135,16 +135,16 @@
method.formatter.link(method.superclass_method.full_name, method.superclass_method.full_name) : nil
%>
</div>
- <% end %>
+ <%- end -%>
- <% if method.token_stream then %>
+ <%- if method.token_stream then -%>
<div class="method-source-code" id="<%= method.html_name %>-source">
<pre><%= method.markup_code %></pre>
</div>
- <% end %>
+ <%- end -%>
</div>
- <% unless method.aliases.empty? then %>
+ <%- unless method.aliases.empty? then -%>
<div class="aliases">
Also aliased as: <%= method.aliases.map do |aka|
if aka.parent then # HACK lib/rexml/encodings
@@ -154,19 +154,19 @@
end
end.join ", " %>
</div>
- <% end %>
+ <%- end -%>
- <% if method.is_alias_for then %>
+ <%- 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 %>
+ <%- end -%>
</div>
- <% end %>
+ <%- end -%>
</section>
- <% end
+ <%- end
end %>
</section>
-<% end %>
+<%- end -%>
</main>
diff --git a/lib/rdoc/generator/template/darkfish/css/rdoc.css b/lib/rdoc/generator/template/darkfish/css/rdoc.css
index a52e44ff8f..ebe2e93af6 100644
--- a/lib/rdoc/generator/template/darkfish/css/rdoc.css
+++ b/lib/rdoc/generator/template/darkfish/css/rdoc.css
@@ -79,6 +79,25 @@ pre {
border-radius: 0.2em;
}
+table {
+ margin: 0;
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+
+table tr th, table tr td {
+ padding: 0.2em 0.4em;
+ border: 1px solid #ccc;
+}
+
+table tr th {
+ background-color: #eceaed;
+}
+
+table tr:nth-child(even) td {
+ background-color: #f5f4f6;
+}
+
/* @group Generic Classes */
.initially-hidden {
@@ -166,6 +185,7 @@ nav {
width: 260px;
font-family: Helvetica, sans-serif;
font-size: 14px;
+ border-right: 1px solid #ccc;
}
main {
@@ -276,7 +296,7 @@ ul.link-list .type {
-webkit-border-radius: 5px;
}
-dl.label-list dt {
+dl.note-list dt {
float: left;
margin-right: 1em;
}
diff --git a/lib/rdoc/generator/template/darkfish/index.rhtml b/lib/rdoc/generator/template/darkfish/index.rhtml
index 7d1c74807b..13fa3dcc7f 100644
--- a/lib/rdoc/generator/template/darkfish/index.rhtml
+++ b/lib/rdoc/generator/template/darkfish/index.rhtml
@@ -13,11 +13,10 @@
</nav>
<main role="main">
-<% if @options.main_page and
+<%- if @options.main_page and
main_page = @files.find { |f| f.full_name == @options.main_page } then %>
<%= main_page.description %>
-<% else %>
+<%- else -%>
<p>This is the API documentation for <%= @title %>.
-<% end %>
+<%- end -%>
</main>
-
diff --git a/lib/rdoc/generator/template/darkfish/servlet_root.rhtml b/lib/rdoc/generator/template/darkfish/servlet_root.rhtml
index 3a33659aea..cab3092b17 100644
--- a/lib/rdoc/generator/template/darkfish/servlet_root.rhtml
+++ b/lib/rdoc/generator/template/darkfish/servlet_root.rhtml
@@ -19,28 +19,28 @@
<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? %>
+<%- 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| %>
+ <%- extra_dirs.each do |name, href, exists, _, path| -%>
<li>
- <% if exists %>
+ <%- if exists -%>
<a href="<%= href %>"><%= h name %></a> (<%= h path %>)
- <% else %>
+ <%- else -%>
<%= h name %> (<%= h path %>; <i>not available</i>)
- <% end %>
+ <%- end -%>
</li>
- <% end %>
+ <%- end -%>
</ol>
-<% end %>
+<%- end -%>
-<% gems = installed.select { |_, _, _, type,| type == :gem } %>
-<% missing = gems.reject { |_, _, exists,| exists } %>
-<% unless missing.empty? then %>
+<%- gems = installed.select { |_, _, _, type,| type == :gem } -%>
+<%- missing = gems.reject { |_, _, exists,| exists } -%>
+<%- unless missing.empty? then -%>
<h2>Missing Gem Documentation</h2>
<p>You are missing documentation for some of your installed gems.
@@ -53,11 +53,10 @@
the following commands.
<ul>
- <% names = missing.map { |name,| name.sub(/-([^-]*)$/, '') }.uniq %>
- <% names.each do |name| %>
+ <%- names = missing.map { |name,| name.sub(/-([^-]*)$/, '') }.uniq -%>
+ <%- names.each do |name| -%>
<li><kbd>gem rdoc <%=h name %></kbd>
- <% end %>
+ <%- end -%>
</ul>
-<% end %>
+<%- end -%>
</main>
-
diff --git a/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml b/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
index 7ff1a9e93e..303d7016cc 100644
--- a/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
+++ b/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
@@ -2,11 +2,11 @@
<main role="main">
<h1 class="class"><%= h @title %></h1>
-<% simple_files = @files.select { |f| f.text? } %>
-<% unless simple_files.empty? then %>
+<%- simple_files = @files.select { |f| f.text? } -%>
+<%- unless simple_files.empty? then -%>
<h2 id="pages">Pages</h2>
<ul>
-<% simple_files.sort.each do |file| %>
+<%- simple_files.sort.each do |file| -%>
<li class="file">
<a href="<%= file.path %>"><%= h file.page_name %></a>
<%
@@ -14,45 +14,45 @@
table = file.parse(file.comment).table_of_contents
unless table.empty? then %>
<ul>
-<% table.each do |heading| %>
+<%- table.each do |heading| -%>
<li><a href="<%= file.path %>#<%= heading.aref %>"><%= heading.plain_html %></a>
-<% end %>
+<%- end -%>
</ul>
-<% end %>
+<%- end -%>
</li>
- <% end %>
+ <%- end -%>
</ul>
-<% end %>
+<%- end -%>
<h2 id="classes">Classes and Modules</h2>
<ul>
-<% @modsort.each do |klass| %>
+<%- @modsort.each do |klass| -%>
<li class="<%= klass.type %>">
<a href="<%= klass.path %>"><%= klass.full_name %></a>
-<% table = []
+<%- 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| %>
+<%- table.each do |item| -%>
<li><a href="<%= klass.path %>#<%= item.aref %>"><%= item.plain_html %></a>
-<% end %>
+<%- end -%>
</ul>
-<% end %>
+<%- end -%>
</li>
-<% end %>
+<%- end -%>
</ul>
<h2 id="methods">Methods</h2>
<ul>
-<% @store.all_classes_and_modules.map do |mod|
+<%- @store.all_classes_and_modules.map do |mod|
mod.method_list
end.flatten.sort.each do |method| %>
<li class="method">
<a href="<%= method.path %>"><%= h method.pretty_name %></a>
&mdash;
<span class="container"><%= method.parent.full_name %></span>
-<% end %>
+<%- end -%>
</ul>
</main>
diff --git a/lib/rdoc/i18n.rb b/lib/rdoc/i18n.rb
index af303858b9..a32fd848a0 100644
--- a/lib/rdoc/i18n.rb
+++ b/lib/rdoc/i18n.rb
@@ -5,6 +5,6 @@
module RDoc::I18n
autoload :Locale, 'rdoc/i18n/locale'
- require 'rdoc/i18n/text'
+ require_relative 'i18n/text'
end
diff --git a/lib/rdoc/markdown.rb b/lib/rdoc/markdown.rb
index 43c70c8de6..3442f76b1b 100644
--- a/lib/rdoc/markdown.rb
+++ b/lib/rdoc/markdown.rb
@@ -173,7 +173,7 @@
# The port to kpeg was performed by Eric Hodel and Evan Phoenix
#
# [dingus]: http://daringfireball.net/projects/markdown/dingus
-# [GFM]: http://github.github.com/github-flavored-markdown/
+# [GFM]: https://github.github.com/gfm/
# [pegmarkdown]: https://github.com/jgm/peg-markdown
# [PHPE]: http://michelf.com/projects/php-markdown/extra/#def-list
# [syntax]: http://daringfireball.net/projects/markdown/syntax
@@ -344,9 +344,8 @@ class RDoc::Markdown
end
def scan(reg)
- if m = reg.match(@string[@pos..-1])
- width = m.end(0)
- @pos += width
+ if m = reg.match(@string, @pos)
+ @pos = m.end(0)
return true
end
@@ -897,7 +896,7 @@ class RDoc::Markdown
return _tmp
end
- # Block = @BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)
+ # Block = @BlankLine* (BlockQuote | Verbatim | CodeFence | Table | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)
def _Block
_save = self.pos
@@ -923,6 +922,9 @@ class RDoc::Markdown
_tmp = apply(:_CodeFence)
break if _tmp
self.pos = _save2
+ _tmp = apply(:_Table)
+ break if _tmp
+ self.pos = _save2
_tmp = apply(:_Note)
break if _tmp
self.pos = _save2
@@ -1057,7 +1059,7 @@ class RDoc::Markdown
self.pos = _save3
break
end
- _tmp = scan(/\A(?-mix:#*)/)
+ _tmp = scan(/\G(?-mix:#*)/)
unless _tmp
self.pos = _save3
break
@@ -1097,7 +1099,7 @@ class RDoc::Markdown
_save = self.pos
while true # sequence
_text_start = self.pos
- _tmp = scan(/\A(?-mix:\#{1,6})/)
+ _tmp = scan(/\G(?-mix:\#{1,6})/)
if _tmp
text = get_text(_text_start)
end
@@ -1162,7 +1164,7 @@ class RDoc::Markdown
self.pos = _save3
break
end
- _tmp = scan(/\A(?-mix:#*)/)
+ _tmp = scan(/\G(?-mix:#*)/)
unless _tmp
self.pos = _save3
break
@@ -1222,7 +1224,7 @@ class RDoc::Markdown
_save = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:={1,})/)
+ _tmp = scan(/\G(?-mix:={1,})/)
unless _tmp
self.pos = _save
break
@@ -1243,7 +1245,7 @@ class RDoc::Markdown
_save = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:-{1,})/)
+ _tmp = scan(/\G(?-mix:-{1,})/)
unless _tmp
self.pos = _save
break
@@ -2127,7 +2129,7 @@ class RDoc::Markdown
self.pos = _save
break
end
- _tmp = scan(/\A(?-mix:[+*-])/)
+ _tmp = scan(/\G(?-mix:[+*-])/)
unless _tmp
self.pos = _save
break
@@ -9320,7 +9322,7 @@ class RDoc::Markdown
return _tmp
end
- # Inlines = (!@Endline Inline:i { i } | @Endline:c &Inline { c })+:chunks @Endline? { chunks }
+ # Inlines = (!@Endline Inline:i { i } | @Endline:c !(&{ github? } Ticks3 /[^`\n]*$/) &Inline { c })+:chunks @Endline? { chunks }
def _Inlines
_save = self.pos
@@ -9367,12 +9369,41 @@ class RDoc::Markdown
break
end
_save6 = self.pos
- _tmp = apply(:_Inline)
+
+ _save7 = self.pos
+ while true # sequence
+ _save8 = self.pos
+ _tmp = begin; github? ; end
+ self.pos = _save8
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ _tmp = apply(:_Ticks3)
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ _tmp = scan(/\G(?-mix:[^`\n]*$)/)
+ unless _tmp
+ self.pos = _save7
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
self.pos = _save6
unless _tmp
self.pos = _save5
break
end
+ _save9 = self.pos
+ _tmp = apply(:_Inline)
+ self.pos = _save9
+ unless _tmp
+ self.pos = _save5
+ break
+ end
@result = begin; c ; end
_tmp = true
unless _tmp
@@ -9390,61 +9421,90 @@ class RDoc::Markdown
_ary << @result
while true
- _save7 = self.pos
+ _save10 = self.pos
while true # choice
- _save8 = self.pos
+ _save11 = self.pos
while true # sequence
- _save9 = self.pos
+ _save12 = self.pos
_tmp = _Endline()
_tmp = _tmp ? nil : true
- self.pos = _save9
+ self.pos = _save12
unless _tmp
- self.pos = _save8
+ self.pos = _save11
break
end
_tmp = apply(:_Inline)
i = @result
unless _tmp
- self.pos = _save8
+ self.pos = _save11
break
end
@result = begin; i ; end
_tmp = true
unless _tmp
- self.pos = _save8
+ self.pos = _save11
end
break
end # end sequence
break if _tmp
- self.pos = _save7
+ self.pos = _save10
- _save10 = self.pos
+ _save13 = self.pos
while true # sequence
_tmp = _Endline()
c = @result
unless _tmp
- self.pos = _save10
+ self.pos = _save13
break
end
- _save11 = self.pos
+ _save14 = self.pos
+
+ _save15 = self.pos
+ while true # sequence
+ _save16 = self.pos
+ _tmp = begin; github? ; end
+ self.pos = _save16
+ unless _tmp
+ self.pos = _save15
+ break
+ end
+ _tmp = apply(:_Ticks3)
+ unless _tmp
+ self.pos = _save15
+ break
+ end
+ _tmp = scan(/\G(?-mix:[^`\n]*$)/)
+ unless _tmp
+ self.pos = _save15
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save14
+ unless _tmp
+ self.pos = _save13
+ break
+ end
+ _save17 = self.pos
_tmp = apply(:_Inline)
- self.pos = _save11
+ self.pos = _save17
unless _tmp
- self.pos = _save10
+ self.pos = _save13
break
end
@result = begin; c ; end
_tmp = true
unless _tmp
- self.pos = _save10
+ self.pos = _save13
end
break
end # end sequence
break if _tmp
- self.pos = _save7
+ self.pos = _save10
break
end # end choice
@@ -9461,11 +9521,11 @@ class RDoc::Markdown
self.pos = _save
break
end
- _save12 = self.pos
+ _save18 = self.pos
_tmp = _Endline()
unless _tmp
_tmp = true
- self.pos = _save12
+ self.pos = _save18
end
unless _tmp
self.pos = _save
@@ -9664,7 +9724,7 @@ class RDoc::Markdown
_save3 = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:_+)/)
+ _tmp = scan(/\G(?-mix:_+)/)
unless _tmp
self.pos = _save3
break
@@ -9694,7 +9754,7 @@ class RDoc::Markdown
_save6 = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:_+)/)
+ _tmp = scan(/\G(?-mix:_+)/)
unless _tmp
self.pos = _save6
break
@@ -9757,7 +9817,7 @@ class RDoc::Markdown
break
end
_text_start = self.pos
- _tmp = scan(/\A(?-mix:[:\\`|*_{}\[\]()#+.!><-])/)
+ _tmp = scan(/\G(?-mix:[:\\`|*_{}\[\]()#+.!><-])/)
if _tmp
text = get_text(_text_start)
end
@@ -9883,7 +9943,7 @@ class RDoc::Markdown
self.pos = _save5
break
end
- _tmp = scan(/\A(?-mix:={1,}|-{1,})/)
+ _tmp = scan(/\G(?-mix:={1,}|-{1,})/)
unless _tmp
self.pos = _save5
break
@@ -10035,7 +10095,7 @@ class RDoc::Markdown
_save1 = self.pos
while true # sequence
_text_start = self.pos
- _tmp = scan(/\A(?-mix:\*{4,})/)
+ _tmp = scan(/\G(?-mix:\*{4,})/)
if _tmp
text = get_text(_text_start)
end
@@ -10065,7 +10125,7 @@ class RDoc::Markdown
self.pos = _save3
break
end
- _tmp = scan(/\A(?-mix:\*+)/)
+ _tmp = scan(/\G(?-mix:\*+)/)
unless _tmp
self.pos = _save3
break
@@ -10112,7 +10172,7 @@ class RDoc::Markdown
_save1 = self.pos
while true # sequence
_text_start = self.pos
- _tmp = scan(/\A(?-mix:_{4,})/)
+ _tmp = scan(/\G(?-mix:_{4,})/)
if _tmp
text = get_text(_text_start)
end
@@ -10142,7 +10202,7 @@ class RDoc::Markdown
self.pos = _save3
break
end
- _tmp = scan(/\A(?-mix:_+)/)
+ _tmp = scan(/\G(?-mix:_+)/)
unless _tmp
self.pos = _save3
break
@@ -11503,7 +11563,7 @@ class RDoc::Markdown
_save1 = self.pos
while true # sequence
- _tmp = scan(/\A(?-mix:[A-Za-z]+)/)
+ _tmp = scan(/\G(?-mix:[A-Za-z]+)/)
unless _tmp
self.pos = _save1
break
@@ -11628,7 +11688,7 @@ class RDoc::Markdown
_save2 = self.pos
while true # sequence
- _tmp = scan(/\A(?i-mx:[\w+.\/!%~$-]+)/)
+ _tmp = scan(/\G(?i-mx:[\w+.\/!%~$-]+)/)
unless _tmp
self.pos = _save2
break
@@ -12492,7 +12552,7 @@ class RDoc::Markdown
self.pos = _save10
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save10
end
@@ -12629,7 +12689,7 @@ class RDoc::Markdown
self.pos = _save24
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save24
end
@@ -12806,7 +12866,7 @@ class RDoc::Markdown
self.pos = _save40
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save40
end
@@ -12943,7 +13003,7 @@ class RDoc::Markdown
self.pos = _save54
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save54
end
@@ -13120,7 +13180,7 @@ class RDoc::Markdown
self.pos = _save70
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save70
end
@@ -13257,7 +13317,7 @@ class RDoc::Markdown
self.pos = _save84
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save84
end
@@ -13434,7 +13494,7 @@ class RDoc::Markdown
self.pos = _save100
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save100
end
@@ -13571,7 +13631,7 @@ class RDoc::Markdown
self.pos = _save114
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save114
end
@@ -13748,7 +13808,7 @@ class RDoc::Markdown
self.pos = _save130
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save130
end
@@ -13885,7 +13945,7 @@ class RDoc::Markdown
self.pos = _save144
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save144
end
@@ -14537,7 +14597,7 @@ class RDoc::Markdown
_save = self.pos
while true # choice
- _tmp = scan(/\A(?-mix:[~*_`&\[\]()<!#\\'"])/)
+ _tmp = scan(/\G(?-mix:[~*_`&\[\]()<!#\\'"])/)
break if _tmp
self.pos = _save
_tmp = _ExtendedSpecialChar()
@@ -14642,13 +14702,13 @@ class RDoc::Markdown
_save = self.pos
while true # sequence
- _tmp = scan(/\A(?i-mx:&#x)/)
+ _tmp = scan(/\G(?i-mx:&#x)/)
unless _tmp
self.pos = _save
break
end
_text_start = self.pos
- _tmp = scan(/\A(?-mix:[0-9a-fA-F]+)/)
+ _tmp = scan(/\G(?-mix:[0-9a-fA-F]+)/)
if _tmp
text = get_text(_text_start)
end
@@ -14684,7 +14744,7 @@ class RDoc::Markdown
break
end
_text_start = self.pos
- _tmp = scan(/\A(?-mix:[0-9]+)/)
+ _tmp = scan(/\G(?-mix:[0-9]+)/)
if _tmp
text = get_text(_text_start)
end
@@ -14720,7 +14780,7 @@ class RDoc::Markdown
break
end
_text_start = self.pos
- _tmp = scan(/\A(?-mix:[A-Za-z0-9]+)/)
+ _tmp = scan(/\G(?-mix:[A-Za-z0-9]+)/)
if _tmp
text = get_text(_text_start)
end
@@ -14752,14 +14812,14 @@ class RDoc::Markdown
# NonindentSpace = / {0,3}/
def _NonindentSpace
- _tmp = scan(/\A(?-mix: {0,3})/)
+ _tmp = scan(/\G(?-mix: {0,3})/)
set_failed_rule :_NonindentSpace unless _tmp
return _tmp
end
# Indent = /\t| /
def _Indent
- _tmp = scan(/\A(?-mix:\t| )/)
+ _tmp = scan(/\G(?-mix:\t| )/)
set_failed_rule :_Indent unless _tmp
return _tmp
end
@@ -15701,7 +15761,7 @@ class RDoc::Markdown
self.pos = _save11
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save11
end
@@ -15782,7 +15842,7 @@ class RDoc::Markdown
self.pos = _save19
break
end
- _tmp = scan(/\A(?-mix:`+)/)
+ _tmp = scan(/\G(?-mix:`+)/)
unless _tmp
self.pos = _save19
end
@@ -15847,6 +15907,338 @@ class RDoc::Markdown
return _tmp
end
+ # Table = &{ github? } TableRow: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(:_TableRow)
+ 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
+
+ # TableRow = TableItem+:row "|" @Newline { row }
+ def _TableRow
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _ary = []
+ _tmp = apply(:_TableItem)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_TableItem)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save1
+ end
+ row = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("|")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = _Newline()
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; row ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TableRow unless _tmp
+ return _tmp
+ end
+
+ # TableItem = "|" < (!"|" !@Newline .)+ > { text.strip }
+ def _TableItem
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("|")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = match_string("|")
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _save4 = self.pos
+ _tmp = _Newline()
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save5 = self.pos
+ while true # sequence
+ _save6 = self.pos
+ _tmp = match_string("|")
+ _tmp = _tmp ? nil : true
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save7 = self.pos
+ _tmp = _Newline()
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text.strip ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TableItem unless _tmp
+ return _tmp
+ end
+
+ # TableLine = TableColumn+:line "|" @Newline { line }
+ def _TableLine
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _ary = []
+ _tmp = apply(:_TableColumn)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_TableColumn)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save1
+ end
+ line = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("|")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = _Newline()
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; line ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TableLine unless _tmp
+ return _tmp
+ end
+
+ # TableColumn = "|" < ("-"+ ":"? | ":" "-"*) > { text.start_with?(":") ? :left : text.end_with?(":") ? :right : nil }
+ def _TableColumn
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("|")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+
+ _save1 = self.pos
+ while true # choice
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = match_string("-")
+ if _tmp
+ while true
+ _tmp = match_string("-")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save3
+ end
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _save4 = self.pos
+ _tmp = match_string(":")
+ unless _tmp
+ _tmp = true
+ self.pos = _save4
+ end
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = match_string(":")
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ while true
+ _tmp = match_string("-")
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text.start_with?(":") ? :left :
+ text.end_with?(":") ? :right : nil
+ ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TableColumn unless _tmp
+ return _tmp
+ end
+
# DefinitionList = &{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }
def _DefinitionList
@@ -16046,7 +16438,7 @@ class RDoc::Markdown
Rules = {}
Rules[:_root] = rule_info("root", "Doc")
Rules[:_Doc] = rule_info("Doc", "BOM? Block*:a { RDoc::Markup::Document.new(*a.compact) }")
- Rules[:_Block] = rule_info("Block", "@BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)")
+ Rules[:_Block] = rule_info("Block", "@BlankLine* (BlockQuote | Verbatim | CodeFence | Table | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)")
Rules[:_Para] = rule_info("Para", "@NonindentSpace Inlines:a @BlankLine+ { paragraph a }")
Rules[:_Plain] = rule_info("Plain", "Inlines:a { paragraph a }")
Rules[:_AtxInline] = rule_info("AtxInline", "!@Newline !(@Sp /\#*/ @Sp @Newline) Inline")
@@ -16190,7 +16582,7 @@ class RDoc::Markdown
Rules[:_StyleClose] = rule_info("StyleClose", "\"<\" Spnl \"/\" (\"style\" | \"STYLE\") Spnl \">\"")
Rules[:_InStyleTags] = rule_info("InStyleTags", "StyleOpen (!StyleClose .)* StyleClose")
Rules[:_StyleBlock] = rule_info("StyleBlock", "< InStyleTags > @BlankLine* { if css? then RDoc::Markup::Raw.new text end }")
- Rules[:_Inlines] = rule_info("Inlines", "(!@Endline Inline:i { i } | @Endline:c &Inline { c })+:chunks @Endline? { chunks }")
+ Rules[:_Inlines] = rule_info("Inlines", "(!@Endline Inline:i { i } | @Endline:c !(&{ github? } Ticks3 /[^`\\n]*$/) &Inline { c })+:chunks @Endline? { chunks }")
Rules[:_Inline] = rule_info("Inline", "(Str | @Endline | UlOrStarLine | @Space | Strong | Emph | Strike | Image | Link | NoteReference | InlineNote | Code | RawHtml | Entity | EscapedChar | Symbol)")
Rules[:_Space] = rule_info("Space", "@Spacechar+ { \" \" }")
Rules[:_Str] = rule_info("Str", "@StartList:a < @NormalChar+ > { a = text } (StrChunk:c { a << c })* { a }")
@@ -16279,6 +16671,11 @@ class RDoc::Markdown
Rules[:_Notes] = rule_info("Notes", "(Note | SkipBlock)*")
Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "@StartList:a (!@BlankLine OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }")
Rules[:_CodeFence] = rule_info("CodeFence", "&{ github? } Ticks3 (@Sp StrChunk:format)? Spnl < ((!\"`\" Nonspacechar)+ | !Ticks3 /`+/ | Spacechar | @Newline)+ > Ticks3 @Sp @Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format.instance_of?(String) verbatim }")
+ Rules[:_Table] = rule_info("Table", "&{ github? } TableRow:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) }")
+ Rules[:_TableRow] = rule_info("TableRow", "TableItem+:row \"|\" @Newline { row }")
+ Rules[:_TableItem] = rule_info("TableItem", "\"|\" < (!\"|\" !@Newline .)+ > { text.strip }")
+ Rules[:_TableLine] = rule_info("TableLine", "TableColumn+:line \"|\" @Newline { line }")
+ Rules[:_TableColumn] = rule_info("TableColumn", "\"|\" < (\"-\"+ \":\"? | \":\" \"-\"*) > { text.start_with?(\":\") ? :left : text.end_with?(\":\") ? :right : nil }")
Rules[:_DefinitionList] = rule_info("DefinitionList", "&{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }")
Rules[:_DefinitionListItem] = rule_info("DefinitionListItem", "DefinitionListLabel+:label DefinitionListDefinition+:defns { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defns.shift) list_items.concat defns.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }")
Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "StrChunk:label @Sp @Newline { label }")
diff --git a/lib/rdoc/markdown/literals.rb b/lib/rdoc/markdown/literals.rb
index 31cd237f12..943c2d268a 100644
--- a/lib/rdoc/markdown/literals.rb
+++ b/lib/rdoc/markdown/literals.rb
@@ -174,9 +174,8 @@ class RDoc::Markdown::Literals
end
def scan(reg)
- if m = reg.match(@string[@pos..-1])
- width = m.end(0)
- @pos += width
+ if m = reg.match(@string, @pos)
+ @pos = m.end(0)
return true
end
@@ -366,14 +365,14 @@ class RDoc::Markdown::Literals
# Alphanumeric = /\p{Word}/
def _Alphanumeric
- _tmp = scan(/\A(?-mix:\p{Word})/)
+ _tmp = scan(/\G(?-mix:\p{Word})/)
set_failed_rule :_Alphanumeric unless _tmp
return _tmp
end
# AlphanumericAscii = /[A-Za-z0-9]/
def _AlphanumericAscii
- _tmp = scan(/\A(?-mix:[A-Za-z0-9])/)
+ _tmp = scan(/\G(?-mix:[A-Za-z0-9])/)
set_failed_rule :_AlphanumericAscii unless _tmp
return _tmp
end
@@ -387,21 +386,21 @@ class RDoc::Markdown::Literals
# Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/
def _Newline
- _tmp = scan(/\A(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/)
+ _tmp = scan(/\G(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/)
set_failed_rule :_Newline unless _tmp
return _tmp
end
# NonAlphanumeric = /\p{^Word}/
def _NonAlphanumeric
- _tmp = scan(/\A(?-mix:\p{^Word})/)
+ _tmp = scan(/\G(?-mix:\p{^Word})/)
set_failed_rule :_NonAlphanumeric unless _tmp
return _tmp
end
# Spacechar = /\t|\p{Zs}/
def _Spacechar
- _tmp = scan(/\A(?-mix:\t|\p{Zs})/)
+ _tmp = scan(/\G(?-mix:\t|\p{Zs})/)
set_failed_rule :_Spacechar unless _tmp
return _tmp
end
diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb
index fd59fca314..92aed757cf 100644
--- a/lib/rdoc/markup.rb
+++ b/lib/rdoc/markup.rb
@@ -843,6 +843,7 @@ https://github.com/ruby/rdoc/issues
autoload :List, 'rdoc/markup/list'
autoload :ListItem, 'rdoc/markup/list_item'
autoload :Paragraph, 'rdoc/markup/paragraph'
+ autoload :Table, 'rdoc/markup/table'
autoload :Raw, 'rdoc/markup/raw'
autoload :Rule, 'rdoc/markup/rule'
autoload :Verbatim, 'rdoc/markup/verbatim'
diff --git a/lib/rdoc/markup/attr_span.rb b/lib/rdoc/markup/attr_span.rb
index 63aace60d2..20ef11cd6d 100644
--- a/lib/rdoc/markup/attr_span.rb
+++ b/lib/rdoc/markup/attr_span.rb
@@ -7,16 +7,22 @@ class RDoc::Markup::AttrSpan
##
# Creates a new AttrSpan for +length+ characters
- def initialize(length)
+ def initialize(length, exclusive)
@attrs = Array.new(length, 0)
+ @exclusive = exclusive
end
##
# Toggles +bits+ from +start+ to +length+
def set_attrs(start, length, bits)
+ updated = false
for i in start ... (start+length)
- @attrs[i] |= bits
+ if (@exclusive & @attrs[i]) == 0 || (@exclusive & bits) != 0
+ @attrs[i] |= bits
+ updated = true
+ end
end
+ updated
end
##
diff --git a/lib/rdoc/markup/attribute_manager.rb b/lib/rdoc/markup/attribute_manager.rb
index f052bc8b01..50764510f3 100644
--- a/lib/rdoc/markup/attribute_manager.rb
+++ b/lib/rdoc/markup/attribute_manager.rb
@@ -59,6 +59,10 @@ class RDoc::Markup::AttributeManager
attr_reader :regexp_handlings
##
+ # A bits of exclusive maps
+ attr_reader :exclusive_bitmap
+
+ ##
# Creates a new attribute manager that understands bold, emphasized and
# teletype text.
@@ -68,17 +72,18 @@ class RDoc::Markup::AttributeManager
@protectable = %w[<]
@regexp_handlings = []
@word_pair_map = {}
+ @exclusive_bitmap = 0
@attributes = RDoc::Markup::Attributes.new
- add_word_pair "*", "*", :BOLD
- add_word_pair "_", "_", :EM
- add_word_pair "+", "+", :TT
+ add_word_pair "*", "*", :BOLD, true
+ add_word_pair "_", "_", :EM, true
+ add_word_pair "+", "+", :TT, true
- add_html "em", :EM
- add_html "i", :EM
- add_html "b", :BOLD
- add_html "tt", :TT
- add_html "code", :TT
+ add_html "em", :EM, true
+ add_html "i", :EM, true
+ add_html "b", :BOLD, true
+ add_html "tt", :TT, true
+ add_html "code", :TT, true
end
##
@@ -122,29 +127,67 @@ class RDoc::Markup::AttributeManager
res
end
+ 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)
+ def convert_attrs(str, attrs, exclusive = false)
+ convert_attrs_matching_word_pairs(str, attrs, exclusive)
+ convert_attrs_word_pair_map(str, attrs, exclusive)
+ end
+
+ def convert_attrs_matching_word_pairs(str, attrs, exclusive)
# first do matching ones
- tags = @matching_word_pairs.keys.join("")
+ tags = @matching_word_pairs.select { |start, bitmap|
+ if exclusive && exclusive?(bitmap)
+ true
+ elsif !exclusive && !exclusive?(bitmap)
+ true
+ else
+ false
+ end
+ }.keys
+ return if tags.empty?
+ all_tags = @matching_word_pairs.keys
- re = /(^|\W)([#{tags}])([#\\]?[\w:.\/-]+?\S?)\2(\W|$)/
+ re = /(^|\W|[#{all_tags.join("")}])([#{tags.join("")}])(\2*[#\\]?[\w:.\/\[\]-]+?\S?)\2(?!\2)([#{all_tags.join("")}]|\W|$)/
- 1 while str.gsub!(re) do
+ 1 while str.gsub!(re) { |orig|
attr = @matching_word_pairs[$2]
- attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr)
- $1 + NULL * $2.length + $3 + NULL * $2.length + $4
- end
+ attr_updated = attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr)
+ if attr_updated
+ $1 + NULL * $2.length + $3 + NULL * $2.length + $4
+ else
+ $1 + NON_PRINTING_START + $2 + NON_PRINTING_END + $3 + NON_PRINTING_START + $2 + NON_PRINTING_END + $4
+ end
+ }
+ str.delete!(NON_PRINTING_START + NON_PRINTING_END)
+ end
+ def convert_attrs_word_pair_map(str, attrs, exclusive)
# then non-matching
unless @word_pair_map.empty? then
@word_pair_map.each do |regexp, attr|
- str.gsub!(regexp) {
- attrs.set_attrs($`.length + $1.length, $2.length, attr)
- NULL * $1.length + $2 + NULL * $3.length
+ if !exclusive
+ next if exclusive?(attr)
+ else
+ next if !exclusive?(attr)
+ end
+ 1 while str.gsub!(regexp) { |orig|
+ updated = attrs.set_attrs($`.length + $1.length, $2.length, attr)
+ if updated
+ NULL * $1.length + $2 + NULL * $3.length
+ else
+ orig
+ end
}
end
end
@@ -153,10 +196,18 @@ class RDoc::Markup::AttributeManager
##
# Converts HTML tags to RDoc attributes
- def convert_html(str, attrs)
- tags = @html_tags.keys.join '|'
+ def convert_html(str, attrs, exclusive = false)
+ tags = @html_tags.select { |start, bitmap|
+ if exclusive && exclusive?(bitmap)
+ true
+ elsif !exclusive && !exclusive?(bitmap)
+ true
+ else
+ false
+ end
+ }.keys.join '|'
- 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) {
+ 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) { |orig|
attr = @html_tags[$1.downcase]
html_length = $1.length + 2
seq = NULL * html_length
@@ -168,8 +219,13 @@ class RDoc::Markup::AttributeManager
##
# Converts regexp handling sequences to RDoc attributes
- def convert_regexp_handlings str, attrs
+ def convert_regexp_handlings str, attrs, exclusive = false
@regexp_handlings.each do |regexp, attribute|
+ if exclusive
+ next if !exclusive?(attribute)
+ else
+ next if exclusive?(attribute)
+ end
str.scan(regexp) do
capture = $~.size == 1 ? 0 : 1
@@ -205,7 +261,7 @@ class RDoc::Markup::AttributeManager
#
# am.add_word_pair '*', '*', :BOLD
- def add_word_pair(start, stop, name)
+ def add_word_pair(start, stop, name, exclusive = false)
raise ArgumentError, "Word flags may not start with '<'" if
start[0,1] == '<'
@@ -220,6 +276,8 @@ class RDoc::Markup::AttributeManager
@protectable << start[0,1]
@protectable.uniq!
+
+ @exclusive_bitmap |= bitmap if exclusive
end
##
@@ -228,8 +286,10 @@ class RDoc::Markup::AttributeManager
#
# am.add_html 'em', :EM
- def add_html(tag, name)
- @html_tags[tag.downcase] = @attributes.bitmap_for name
+ def add_html(tag, name, exclusive = false)
+ bitmap = @attributes.bitmap_for name
+ @html_tags[tag.downcase] = bitmap
+ @exclusive_bitmap |= bitmap if exclusive
end
##
@@ -238,8 +298,10 @@ class RDoc::Markup::AttributeManager
#
# @am.add_regexp_handling(/((https?:)\S+\w)/, :HYPERLINK)
- def add_regexp_handling pattern, name
- @regexp_handlings << [pattern, @attributes.bitmap_for(name)]
+ def add_regexp_handling pattern, name, exclusive = false
+ bitmap = @attributes.bitmap_for(name)
+ @regexp_handlings << [pattern, bitmap]
+ @exclusive_bitmap |= bitmap if exclusive
end
##
@@ -250,8 +312,11 @@ class RDoc::Markup::AttributeManager
mask_protected_sequences
- @attrs = RDoc::Markup::AttrSpan.new @str.length
+ @attrs = RDoc::Markup::AttrSpan.new @str.length, @exclusive_bitmap
+ convert_attrs @str, @attrs, true
+ convert_html @str, @attrs, true
+ convert_regexp_handlings @str, @attrs, true
convert_attrs @str, @attrs
convert_html @str, @attrs
convert_regexp_handlings @str, @attrs
diff --git a/lib/rdoc/markup/formatter.rb b/lib/rdoc/markup/formatter.rb
index 6dff96c7d0..2bac76e838 100644
--- a/lib/rdoc/markup/formatter.rb
+++ b/lib/rdoc/markup/formatter.rb
@@ -156,7 +156,7 @@ class RDoc::Markup::Formatter
method_name = "handle_regexp_#{name}"
if respond_to? method_name then
- target.text = send method_name, target
+ target.text = public_send method_name, target
handled = true
end
end
diff --git a/lib/rdoc/markup/pre_process.rb b/lib/rdoc/markup/pre_process.rb
index d9e0dcac14..3080ae3578 100644
--- a/lib/rdoc/markup/pre_process.rb
+++ b/lib/rdoc/markup/pre_process.rb
@@ -178,7 +178,7 @@ class RDoc::Markup::PreProcess
blankline
when 'include' then
- filename = param.split.first
+ filename = param.split(' ', 2).first
include_file filename, prefix, encoding
when 'main' then
@options.main_page = param if @options.respond_to? :main_page
diff --git a/lib/rdoc/markup/table.rb b/lib/rdoc/markup/table.rb
new file mode 100644
index 0000000000..7bcb10aff3
--- /dev/null
+++ b/lib/rdoc/markup/table.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+##
+# A section of table
+
+class RDoc::Markup::Table
+ attr_accessor :header, :align, :body
+
+ def initialize header, align, body
+ @header, @align, @body = header, align, body
+ end
+
+ def == other
+ self.class == other.class and
+ @header == other.header and
+ @align == other.align and
+ @body == other.body
+ end
+
+ def accept visitor
+ visitor.accept_table @header, @body, @align
+ end
+
+ def pretty_print q # :nodoc:
+ q.group 2, '[Table: ', ']' do
+ q.group 2, '[Head: ', ']' do
+ q.seplist @header.zip(@align) do |text, align|
+ q.pp text
+ if align
+ q.text ":"
+ q.breakable
+ q.text align.to_s
+ end
+ end
+ end
+ q.breakable
+ q.group 2, '[Body: ', ']' do
+ q.seplist @body do |body|
+ q.group 2, '[', ']' do
+ q.seplist body do |text|
+ q.pp text
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb
index 9ae0fff8a7..8ae4dd4720 100644
--- a/lib/rdoc/markup/to_html.rb
+++ b/lib/rdoc/markup/to_html.rb
@@ -52,12 +52,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
@th = nil
@hard_break = "<br>\n"
- # external links
- @markup.add_regexp_handling(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/,
- :HYPERLINK)
-
- add_regexp_handling_RDOCLINK
- add_regexp_handling_TIDYLINK
+ init_regexp_handlings
init_tags
end
@@ -66,6 +61,24 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
#
# These methods are used by regexp handling markup added by RDoc::Markup#add_regexp_handling.
+ ##
+ # Adds regexp handlings.
+
+ def init_regexp_handlings
+ # external links
+ @markup.add_regexp_handling(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/,
+ :HYPERLINK)
+ init_link_notation_regexp_handlings
+ end
+
+ ##
+ # Adds regexp handlings about link notations.
+
+ def init_link_notation_regexp_handlings
+ add_regexp_handling_RDOCLINK
+ add_regexp_handling_TIDYLINK
+ end
+
def handle_RDOCLINK url # :nodoc:
case url
when /^rdoc-ref:/
@@ -301,6 +314,29 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
@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 << '>' << CGI.escapeHTML(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 << '>' << CGI.escapeHTML(text) << "</td>\n"
+ end
+ @res << "</tr>\n"
+ end
+ @res << "</tbody>\n</table>\n"
+ end
+
# :section: Utilities
##
@@ -321,6 +357,10 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
"<img src=\"#{url}\" />"
else
+ if scheme != 'link' and /\.(?:rb|rdoc|md)\z/i =~ url
+ url = url.sub(%r%\A([./]*)(.*)\z%) { "#$1#{$2.tr('.', '_')}.html" }
+ end
+
text = text.sub %r%^#{scheme}:/*%i, ''
text = text.sub %r%^[*\^](\d+)$%, '\1'
diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb
index 9314f04fae..a9fd09df41 100644
--- a/lib/rdoc/markup/to_html_crossref.rb
+++ b/lib/rdoc/markup/to_html_crossref.rb
@@ -39,10 +39,18 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
@hyperlink_all = @options.hyperlink_all
@show_hash = @options.show_hash
- crossref_re = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
+ @cross_reference = RDoc::CrossReference.new @context
+ end
+
+ def init_link_notation_regexp_handlings
+ add_regexp_handling_RDOCLINK
+
+ # The crossref must be linked before tidylink because Klass.method[:sym]
+ # will be processed as a tidylink first and will be broken.
+ crossref_re = @options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
@markup.add_regexp_handling crossref_re, :CROSSREF
- @cross_reference = RDoc::CrossReference.new @context
+ add_regexp_handling_TIDYLINK
end
##
@@ -54,7 +62,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
name = name[1..-1] unless @show_hash if name[0, 1] == '#'
- if name =~ /(.*[^#:])@/
+ if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])@/
text ||= "#{CGI.unescape $'} at <code>#{$1}</code>"
code = false
else
@@ -130,7 +138,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
# Creates an HTML link to +name+ with the given +text+.
def link name, text, code = true
- if name =~ /(.*[^#:])@/ then
+ if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])@/
name = $1
label = $'
end
@@ -144,7 +152,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
path = ref.as_href @from_path
if code and RDoc::CodeObject === ref and !(RDoc::TopLevel === ref)
- text = "<code>#{text}</code>"
+ text = "<code>#{CGI.escapeHTML text}</code>"
end
if path =~ /#/ then
diff --git a/lib/rdoc/markup/to_joined_paragraph.rb b/lib/rdoc/markup/to_joined_paragraph.rb
index 795f3f62ee..46e07c94ad 100644
--- a/lib/rdoc/markup/to_joined_paragraph.rb
+++ b/lib/rdoc/markup/to_joined_paragraph.rb
@@ -41,6 +41,7 @@ class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter
alias accept_raw ignore
alias accept_rule ignore
alias accept_verbatim ignore
+ alias accept_table ignore
end
diff --git a/lib/rdoc/markup/to_rdoc.rb b/lib/rdoc/markup/to_rdoc.rb
index 81b16c4973..3cdf4fd08b 100644
--- a/lib/rdoc/markup/to_rdoc.rb
+++ b/lib/rdoc/markup/to_rdoc.rb
@@ -238,6 +238,34 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
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
diff --git a/lib/rdoc/markup/to_table_of_contents.rb b/lib/rdoc/markup/to_table_of_contents.rb
index f68b90bcf6..eb8e8faa16 100644
--- a/lib/rdoc/markup/to_table_of_contents.rb
+++ b/lib/rdoc/markup/to_table_of_contents.rb
@@ -82,6 +82,7 @@ class RDoc::Markup::ToTableOfContents < RDoc::Markup::Formatter
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/options.rb b/lib/rdoc/options.rb
index 43494c85be..13b7ba5c6c 100644
--- a/lib/rdoc/options.rb
+++ b/lib/rdoc/options.rb
@@ -338,8 +338,9 @@ class RDoc::Options
attr_reader :visibility
- def initialize # :nodoc:
+ def initialize loaded_options = nil # :nodoc:
init_ivars
+ override loaded_options if loaded_options
end
def init_ivars # :nodoc:
@@ -417,6 +418,37 @@ class RDoc::Options
init_with map
end
+ def override map # :nodoc:
+ if map.has_key?('encoding')
+ encoding = map['encoding']
+ @encoding = encoding ? Encoding.find(encoding) : encoding
+ end
+
+ @charset = map['charset'] if map.has_key?('charset')
+ @exclude = map['exclude'] if map.has_key?('exclude')
+ @generator_name = map['generator_name'] if map.has_key?('generator_name')
+ @hyperlink_all = map['hyperlink_all'] if map.has_key?('hyperlink_all')
+ @line_numbers = map['line_numbers'] if map.has_key?('line_numbers')
+ @locale_name = map['locale_name'] if map.has_key?('locale_name')
+ @locale_dir = map['locale_dir'] if map.has_key?('locale_dir')
+ @main_page = map['main_page'] if map.has_key?('main_page')
+ @markup = map['markup'] if map.has_key?('markup')
+ @op_dir = map['op_dir'] if map.has_key?('op_dir')
+ @show_hash = map['show_hash'] if map.has_key?('show_hash')
+ @tab_width = map['tab_width'] if map.has_key?('tab_width')
+ @template_dir = map['template_dir'] if map.has_key?('template_dir')
+ @title = map['title'] if map.has_key?('title')
+ @visibility = map['visibility'] if map.has_key?('visibility')
+ @webcvs = map['webcvs'] if map.has_key?('webcvs')
+
+ if map.has_key?('rdoc_include')
+ @rdoc_include = sanitize_path map['rdoc_include']
+ end
+ if map.has_key?('static_path')
+ @static_path = sanitize_path map['static_path']
+ end
+ end
+
def == other # :nodoc:
self.class === other and
@encoding == other.encoding and
@@ -755,7 +787,7 @@ Usage: #{opt.program_name} [options] [names...]
opt.on("--[no-]force-update", "-U",
"Forces rdoc to scan all sources even if",
- "newer than the flag file.") do |value|
+ "no files are newer than the flag file.") do |value|
@force_update = value
end
diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb
index 597bcd6b9d..425bc48632 100644
--- a/lib/rdoc/parser.rb
+++ b/lib/rdoc/parser.rb
@@ -78,7 +78,7 @@ class RDoc::Parser
return true if s[0, 2] == Marshal.dump('')[0, 2] or s.index("\x00")
- mode = 'r:utf-8' # default source encoding has been chagened to utf-8
+ mode = 'r:utf-8' # default source encoding has been changed to utf-8
s.sub!(/\A#!.*\n/, '') # assume shebang line isn't longer than 1024.
encoding = s[/^\s*\#\s*(?:-\*-\s*)?(?:en)?coding:\s*([^\s;]+?)(?:-\*-|[\s;])/, 1]
mode = "rb:#{encoding}" if encoding
@@ -269,9 +269,9 @@ class RDoc::Parser
end
# simple must come first in order to show up last in the parsers list
-require 'rdoc/parser/simple'
-require 'rdoc/parser/c'
-require 'rdoc/parser/changelog'
-require 'rdoc/parser/markdown'
-require 'rdoc/parser/rd'
-require 'rdoc/parser/ruby'
+require_relative 'parser/simple'
+require_relative 'parser/c'
+require_relative 'parser/changelog'
+require_relative 'parser/markdown'
+require_relative 'parser/rd'
+require_relative 'parser/ruby'
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 8265712370..9d8db6cdee 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -210,48 +210,6 @@ class RDoc::Parser::C < RDoc::Parser
end
##
- # Removes duplicate call-seq entries for methods using the same
- # implementation.
-
- def deduplicate_call_seq
- @methods.each do |var_name, functions|
- class_name = @known_classes[var_name]
- next unless class_name
- class_obj = find_class var_name, class_name
-
- functions.each_value do |method_names|
- next if method_names.length == 1
-
- method_names.each do |method_name|
- deduplicate_method_name class_obj, method_name
- end
- end
- end
- end
-
- ##
- # If two ruby methods share a C implementation (and comment) this
- # deduplicates the examples in the call_seq for the method to reduce
- # confusion in the output.
-
- def deduplicate_method_name class_obj, method_name # :nodoc:
- return unless
- method = class_obj.method_list.find { |m| m.name == method_name }
- return unless call_seq = method.call_seq
-
- method_name = method_name[0, 1] if method_name =~ /\A\[/
-
- entries = call_seq.split "\n"
-
- matching = entries.select do |entry|
- entry =~ /^\w*\.?#{Regexp.escape method_name}/ or
- entry =~ /\s#{Regexp.escape method_name}\s/
- end
-
- method.call_seq = matching.join "\n"
- end
-
- ##
# Scans #content for rb_define_alias
def do_aliases
@@ -269,24 +227,30 @@ class RDoc::Parser::C < RDoc::Parser
end
class_obj = find_class var_name, class_name
-
- al = RDoc::Alias.new '', old_name, new_name, ''
- al.singleton = @singleton_classes.key? var_name
-
comment = find_alias_comment var_name, new_name, old_name
-
comment.normalize
-
- al.comment = comment
-
- al.record_location @top_level
-
- class_obj.add_alias al
- @stats.add_alias al
+ if comment.to_s.empty? and existing_method = class_obj.method_list.find { |m| m.name == old_name}
+ comment = existing_method.comment
+ end
+ add_alias(var_name, class_obj, old_name, new_name, comment)
end
end
##
+ # Add alias, either from a direct alias definition, or from two
+ # method that reference the same function.
+
+ def add_alias(var_name, class_obj, old_name, new_name, comment)
+ al = RDoc::Alias.new '', old_name, new_name, ''
+ al.singleton = @singleton_classes.key? var_name
+ al.comment = comment
+ al.record_location @top_level
+ class_obj.add_alias al
+ @stats.add_alias al
+ al
+ end
+
+ ##
# Scans #content for rb_attr and rb_define_attr
def do_attrs
@@ -354,7 +318,7 @@ class RDoc::Parser::C < RDoc::Parser
\s*"(?<module_name_1>\w+)"\s*
\)
|
- _under\s*\( # rb_define_module_under(module_under, module_name_1)
+ _under\s*\( # rb_define_module_under(module_under, module_name_2)
\s*(?<module_under>\w+),
\s*"(?<module_name_2>\w+)"
\s*\)
@@ -608,7 +572,7 @@ class RDoc::Parser::C < RDoc::Parser
((?>/\*.*?\*/\s*)?)
((?:(?:\w+)\s+)?
(?:intern\s+)?VALUE\s+(\w+)
- \s*(?:\([^)]*\))(?:[^;]|$))
+ \s*(?:\([^)]*\))(?:[^\);]|$))
| ((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+(\w+)\s+(\w+))
| ^\s*\#\s*define\s+(\w+)\s+(\w+)
}xm) do
@@ -1021,6 +985,10 @@ class RDoc::Parser::C < RDoc::Parser
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'
@@ -1249,8 +1217,6 @@ class RDoc::Parser::C < RDoc::Parser
do_aliases
do_attrs
- deduplicate_call_seq
-
@store.add_c_variables self
@top_level
diff --git a/lib/rdoc/parser/changelog.rb b/lib/rdoc/parser/changelog.rb
index 167892f543..9245d49376 100644
--- a/lib/rdoc/parser/changelog.rb
+++ b/lib/rdoc/parser/changelog.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-require 'time'
##
# A ChangeLog file parser.
@@ -106,15 +105,33 @@ class RDoc::Parser::ChangeLog < RDoc::Parser
entries.group_by do |title, _|
begin
time = @time_cache[title]
- (time || Time.parse(title)).strftime '%Y-%m-%d'
+ (time || parse_date(title)).strftime '%Y-%m-%d'
rescue NoMethodError, ArgumentError
time, = title.split ' ', 2
- Time.parse(time).strftime '%Y-%m-%d'
+ parse_date(time).strftime '%Y-%m-%d'
end
end
end
##
+ # Parse date in ISO-8601, RFC-2822, or default of Git
+
+ def parse_date(date)
+ case date
+ when /\A\s*(\d+)-(\d+)-(\d+)(?:[ T](\d+):(\d+):(\d+) *([-+]\d\d):?(\d\d))?\b/
+ Time.new($1, $2, $3, $4, $5, $6, ("#{$7}:#{$8}" if $7))
+ when /\A\s*\w{3}, +(\d+) (\w{3}) (\d+) (\d+):(\d+):(\d+) *(?:([-+]\d\d):?(\d\d))\b/
+ Time.new($3, $2, $1, $4, $5, $6, ("#{$7}:#{$8}" if $7))
+ when /\A\s*\w{3} (\w{3}) +(\d+) (\d+) (\d+):(\d+):(\d+) *(?:([-+]\d\d):?(\d\d))\b/
+ Time.new($3, $1, $2, $4, $5, $6, ("#{$7}:#{$8}" if $7))
+ when /\A\s*\w{3} (\w{3}) +(\d+) (\d+):(\d+):(\d+) (\d+)\b/
+ Time.new($6, $1, $2, $3, $4, $5)
+ else
+ raise ArgumentError, "bad date: #{date}"
+ end
+ end
+
+ ##
# Parses the entries in the ChangeLog.
#
# Returns an Array of each ChangeLog entry in order of parsing.
@@ -131,6 +148,13 @@ class RDoc::Parser::ChangeLog < RDoc::Parser
def parse_entries
@time_cache ||= {}
+
+ if /\A((?:.*\n){,3})commit\s/ =~ @content
+ class << self; prepend Git; end
+ parse_info($1)
+ return parse_entries
+ end
+
entries = []
entry_name = nil
entry_body = []
@@ -145,19 +169,10 @@ class RDoc::Parser::ChangeLog < RDoc::Parser
entry_name = $&
begin
- time = Time.parse entry_name
+ time = parse_date entry_name
@time_cache[entry_name] = time
- # HACK Ruby 1.8 does not raise ArgumentError for Time.parse "Other"
- entry_name = nil unless entry_name =~ /#{time.year}/
- rescue NoMethodError
- # HACK Ruby 2.1.2 and earlier raises NoMethodError if time part is absent
- entry_name.split ' ', 2
rescue ArgumentError
- if /out of range/ =~ $!.message
- Time.parse(entry_name.split(' ', 2)[0]) rescue entry_name = nil
- else
- entry_name = nil
- end
+ entry_name = nil
end
entry_body = []
@@ -190,6 +205,7 @@ class RDoc::Parser::ChangeLog < RDoc::Parser
def scan
@time_cache = {}
+
entries = parse_entries
grouped_entries = group_entries entries
@@ -200,5 +216,120 @@ class RDoc::Parser::ChangeLog < RDoc::Parser
@top_level
end
+ module Git
+ def parse_info(info)
+ /^\s*base-url\s*=\s*(.*\S)/ =~ info
+ @base_url = $1
+ end
+
+ def parse_entries
+ entries = []
+
+ @content.scan(/^commit\s+(\h{20})\h*\n((?:.+\n)*)\n((?: {4}.*\n+)*)/) do
+ entry_name, header, entry_body = $1, $2, $3.gsub(/^ {4}/, '')
+ # header = header.scan(/^ *(\S+?): +(.*)/).to_h
+ # date = header["CommitDate"] || header["Date"]
+ date = header[/^ *(?:Author)?Date: +(.*)/, 1]
+ author = header[/^ *Author: +(.*)/, 1]
+ begin
+ time = parse_date(header[/^ *CommitDate: +(.*)/, 1] || date)
+ @time_cache[entry_name] = time
+ author.sub!(/\s*<(.*)>/, '')
+ email = $1
+ entries << [entry_name, [author, email, date, entry_body]]
+ rescue ArgumentError
+ end
+ end
+
+ entries
+ end
+
+ def create_entries entries
+ # git log entries have no strictly itemized style like the old
+ # style, just assume Markdown.
+ entries.map do |commit, entry|
+ LogEntry.new(@base_url, commit, *entry)
+ end
+ end
+
+ LogEntry = Struct.new(:base, :commit, :author, :email, :date, :contents) do
+ HEADING_LEVEL = 3
+
+ def initialize(base, commit, author, email, date, contents)
+ case contents
+ when String
+ contents = RDoc::Markdown.parse(contents).parts.each do |body|
+ case body
+ when RDoc::Markup::Heading
+ body.level += HEADING_LEVEL + 1
+ end
+ end
+ case first = contents[0]
+ when RDoc::Markup::Paragraph
+ contents[0] = RDoc::Markup::Heading.new(HEADING_LEVEL + 1, first.text)
+ end
+ end
+ super
+ end
+
+ def level
+ HEADING_LEVEL
+ end
+
+ def aref
+ "label-#{commit}"
+ end
+
+ def label context = nil
+ aref
+ end
+
+ def text
+ case base
+ when nil
+ "#{date}"
+ when /%s/
+ "{#{date}}[#{base % commit}]"
+ else
+ "{#{date}}[#{base}#{commit}]"
+ end + " {#{author}}[mailto:#{email}]"
+ end
+
+ def accept visitor
+ visitor.accept_heading self
+ begin
+ if visitor.respond_to?(:code_object=)
+ code_object = visitor.code_object
+ visitor.code_object = self
+ end
+ contents.each do |body|
+ body.accept visitor
+ end
+ ensure
+ if visitor.respond_to?(:code_object)
+ visitor.code_object = code_object
+ end
+ end
+ end
+
+ def pretty_print q # :nodoc:
+ q.group(2, '[log_entry: ', ']') do
+ q.text commit
+ q.text ','
+ q.breakable
+ q.group(2, '[date: ', ']') { q.text date }
+ q.text ','
+ q.breakable
+ q.group(2, '[author: ', ']') { q.text author }
+ q.text ','
+ q.breakable
+ q.group(2, '[email: ', ']') { q.text email }
+ q.text ','
+ q.breakable
+ q.pp contents
+ end
+ end
+ end
+ end
end
diff --git a/lib/rdoc/rd/block_parser.rb b/lib/rdoc/rd/block_parser.rb
index be0b786bfc..462ba869a2 100644
--- a/lib/rdoc/rd/block_parser.rb
+++ b/lib/rdoc/rd/block_parser.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.2
# from Racc grammar file "".
#
diff --git a/lib/rdoc/rd/inline_parser.rb b/lib/rdoc/rd/inline_parser.rb
index a64102cac7..8f4c2c31ef 100644
--- a/lib/rdoc/rd/inline_parser.rb
+++ b/lib/rdoc/rd/inline_parser.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.2
# from Racc grammar file "".
#
diff --git a/lib/rdoc/rdoc.gemspec b/lib/rdoc/rdoc.gemspec
index 9b274c709a..7725e40b22 100644
--- a/lib/rdoc/rdoc.gemspec
+++ b/lib/rdoc/rdoc.gemspec
@@ -166,6 +166,7 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat
"lib/rdoc/markup/raw.rb",
"lib/rdoc/markup/regexp_handling.rb",
"lib/rdoc/markup/rule.rb",
+ "lib/rdoc/markup/table.rb",
"lib/rdoc/markup/to_ansi.rb",
"lib/rdoc/markup/to_bs.rb",
"lib/rdoc/markup/to_html.rb",
@@ -221,6 +222,7 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat
"lib/rdoc/tom_doc.rb",
"lib/rdoc/top_level.rb",
"lib/rdoc/version.rb",
+ "man/ri.1",
"rdoc.gemspec",
]
# files from .gitignore
@@ -241,6 +243,7 @@ RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentat
]
s.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
- s.rubygems_version = "2.5.2"
s.required_rubygems_version = Gem::Requirement.new(">= 2.2")
+
+ s.add_development_dependency("gettext")
end
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index f356c368ff..bb58513d2c 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -112,11 +112,17 @@ class RDoc::RDoc
file_list = normalized_file_list files, true, @options.exclude
- file_list = file_list.uniq
-
- file_list = remove_unparseable file_list
-
- file_list.sort
+ 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
##
@@ -160,8 +166,15 @@ class RDoc::RDoc
rescue Psych::SyntaxError
end
+ return RDoc::Options.new if options == false # Allow empty file.
+
raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless
- RDoc::Options === options
+ 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
@@ -254,11 +267,11 @@ option)
# read and strip comments
patterns = File.read(filename).gsub(/#.*/, '')
- result = []
+ result = {}
- patterns.split.each do |patt|
+ patterns.split(' ').each do |patt|
candidates = Dir.glob(File.join(in_dir, patt))
- result.concat normalized_file_list(candidates, false, @options.exclude)
+ result.update normalized_file_list(candidates, false, @options.exclude)
end
result
@@ -278,21 +291,21 @@ option)
def normalized_file_list(relative_files, force_doc = false,
exclude_pattern = nil)
- file_list = []
+ file_list = {}
relative_files.each do |rel_file_name|
+ rel_file_name = rel_file_name.sub(/^\.\//, '')
next if rel_file_name.end_with? 'created.rid'
next if exclude_pattern && exclude_pattern =~ rel_file_name
stat = File.stat rel_file_name rescue next
case type = stat.ftype
when "file" then
- next if last_modified = @last_modified[rel_file_name] and
- stat.mtime.to_i <= last_modified.to_i
+ mtime = (stat.mtime unless (last_modified = @last_modified[rel_file_name] and
+ stat.mtime.to_i <= last_modified.to_i))
if force_doc or RDoc::Parser.can_parse(rel_file_name) then
- file_list << rel_file_name.sub(/^\.\//, '')
- @last_modified[rel_file_name] = stat.mtime
+ file_list[rel_file_name] = mtime
end
when "directory" then
next if rel_file_name == "CVS" || rel_file_name == ".svn"
@@ -303,16 +316,16 @@ option)
dot_doc = File.join rel_file_name, RDoc::DOT_DOC_FILENAME
if File.file? dot_doc then
- file_list << parse_dot_doc_file(rel_file_name, dot_doc)
+ file_list.update(parse_dot_doc_file(rel_file_name, dot_doc))
else
- file_list << list_files_in_directory(rel_file_name)
+ file_list.update(list_files_in_directory(rel_file_name))
end
else
warn "rdoc can't parse the #{type} #{rel_file_name}"
end
end
- file_list.flatten
+ file_list
end
##
@@ -427,7 +440,7 @@ The internal error was:
# files for emacs and vim.
def remove_unparseable files
- files.reject do |file|
+ files.reject do |file, *|
file =~ /\.(?:class|eps|erb|scpt\.txt|svg|ttf|yml)$/i or
(file =~ /tags$/i and
File.open(file, 'rb') { |io|
@@ -561,6 +574,6 @@ rescue LoadError
end
# require built-in generators after discovery in case they've been replaced
-require 'rdoc/generator/darkfish'
-require 'rdoc/generator/ri'
-require 'rdoc/generator/pot'
+require_relative 'generator/darkfish'
+require_relative 'generator/ri'
+require_relative 'generator/pot'
diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb
index 46b98e99b5..a4b70b8f56 100644
--- a/lib/rdoc/ri/driver.rb
+++ b/lib/rdoc/ri/driver.rb
@@ -17,7 +17,7 @@ require 'rdoc'
##
# For RubyGems backwards compatibility
-require 'rdoc/ri/formatter'
+require_relative 'formatter'
##
# The RI driver implements the command-line ri tool.
@@ -356,7 +356,7 @@ or the PAGER environment variable.
end
end
- argv = ENV['RI'].to_s.split.concat argv
+ argv = ENV['RI'].to_s.split(' ').concat argv
opts.parse! argv
@@ -1228,7 +1228,7 @@ or the PAGER environment variable.
# +cache+ indicate if it is a class or instance method.
def load_method store, cache, klass, type, name
- methods = store.send(cache)[klass]
+ methods = store.public_send(cache)[klass]
return unless methods
@@ -1521,7 +1521,7 @@ or the PAGER environment variable.
pagers.compact.uniq.each do |pager|
next unless pager
- pager_cmd = pager.split.first
+ pager_cmd = pager.split(' ').first
next unless in_path? pager_cmd
@@ -1551,7 +1551,11 @@ or the PAGER environment variable.
# Starts a WEBrick server for ri.
def start_server
- require 'webrick'
+ begin
+ require 'webrick'
+ rescue LoadError
+ abort "webrick is not found. You may need to `gem install webrick` to install webrick."
+ end
server = WEBrick::HTTPServer.new :Port => @server
diff --git a/lib/rdoc/ri/paths.rb b/lib/rdoc/ri/paths.rb
index f76721d318..8e89b04e54 100644
--- a/lib/rdoc/ri/paths.rb
+++ b/lib/rdoc/ri/paths.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rdoc/rdoc'
+require_relative '../rdoc'
##
# The directories where ri data lives. Paths can be enumerated via ::each, or
@@ -12,23 +12,9 @@ module RDoc::RI::Paths
version = RbConfig::CONFIG['ruby_version']
- BASE = if RbConfig::CONFIG.key? 'ridir' then
- File.join RbConfig::CONFIG['ridir'], version
- else
- File.join RbConfig::CONFIG['datadir'], 'ri', version
- end
+ BASE = File.join RbConfig::CONFIG['ridir'], version
- homedir = begin
- File.expand_path('~')
- rescue ArgumentError
- end
-
- homedir ||= ENV['HOME'] ||
- ENV['USERPROFILE'] || ENV['HOMEPATH'] # for 1.8 compatibility
-
- HOMEDIR = if homedir then
- File.join homedir, ".rdoc"
- end
+ HOMEDIR = RDoc.home
#:startdoc:
##
diff --git a/lib/rdoc/ri/task.rb b/lib/rdoc/ri/task.rb
index 6a6ea572bf..1122ea3775 100644
--- a/lib/rdoc/ri/task.rb
+++ b/lib/rdoc/ri/task.rb
@@ -4,7 +4,7 @@ begin
rescue Gem::LoadError
end unless defined?(RDoc)
-require 'rdoc/task'
+require_relative '../task'
##
# RDoc::RI::Task creates ri data in <code>./.rdoc</code> for your project.
diff --git a/lib/rdoc/rubygems_hook.rb b/lib/rdoc/rubygems_hook.rb
index 90b0541fcf..f4aa9655ae 100644
--- a/lib/rdoc/rubygems_hook.rb
+++ b/lib/rdoc/rubygems_hook.rb
@@ -70,7 +70,7 @@ class RDoc::RubygemsHook
def self.load_rdoc
return if @rdoc_version
- require 'rdoc/rdoc'
+ require_relative 'rdoc'
@rdoc_version = Gem::Version.new ::RDoc::VERSION
end
@@ -158,7 +158,7 @@ class RDoc::RubygemsHook
case config_args = Gem.configuration[:rdoc]
when String then
- args = args.concat config_args.split
+ args = args.concat config_args.split(' ')
when Array then
args = args.concat config_args
end
diff --git a/lib/rdoc/servlet.rb b/lib/rdoc/servlet.rb
index e1d0f0ce82..0ab1eaf19d 100644
--- a/lib/rdoc/servlet.rb
+++ b/lib/rdoc/servlet.rb
@@ -3,7 +3,12 @@ require 'rdoc'
require 'erb'
require 'time'
require 'json'
-require 'webrick'
+
+begin
+ require 'webrick'
+rescue LoadError
+ abort "webrick is not found. You may need to `gem install webrick` to install webrick."
+end
##
# This is a WEBrick servlet that allows you to browse ri documentation.
diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb
index 0f6cd06e3c..5ba671ca1b 100644
--- a/lib/rdoc/store.rb
+++ b/lib/rdoc/store.rb
@@ -482,7 +482,7 @@ class RDoc::Store
when :gem then
parent = File.expand_path '..', @path
"gem #{File.basename parent}"
- when :home then '~/.rdoc'
+ when :home then RDoc.home
when :site then 'ruby site'
when :system then 'ruby core'
else @path
@@ -723,7 +723,7 @@ class RDoc::Store
def page name
@text_files_hash.each_value.find do |file|
- file.page_name == name
+ file.page_name == name or file.base_name == name
end
end
diff --git a/lib/rdoc/version.rb b/lib/rdoc/version.rb
index 335aec3e1a..b4203186f7 100644
--- a/lib/rdoc/version.rb
+++ b/lib/rdoc/version.rb
@@ -3,6 +3,6 @@ module RDoc
##
# RDoc version you are using
- VERSION = '6.2.1.1'
+ VERSION = '6.3.3'
end
diff --git a/lib/readline.gemspec b/lib/readline.gemspec
index 5c641a88a5..dddac020a4 100644
--- a/lib/readline.gemspec
+++ b/lib/readline.gemspec
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
library with "readline-ext" gem and is implemented by pure Ruby.
EOD
spec.homepage = 'https://github.com/ruby/readline'
- spec.license = 'Ruby license'
+ spec.license = 'Ruby'
spec.files = Dir['BSDL', 'COPYING', 'README.md', 'lib/readline.rb']
spec.require_paths = ['lib']
diff --git a/lib/reline.rb b/lib/reline.rb
index eb18d0d075..a7bd4d9280 100644
--- a/lib/reline.rb
+++ b/lib/reline.rb
@@ -36,7 +36,6 @@ module Reline
attr_accessor :config
attr_accessor :key_stroke
attr_accessor :line_editor
- attr_accessor :ambiguous_width
attr_accessor :last_incremental_search
attr_reader :output
@@ -44,6 +43,7 @@ module Reline
self.output = STDOUT
yield self
@completion_quote_character = nil
+ @bracketed_paste_finished = false
end
def encoding
@@ -199,7 +199,11 @@ module Reline
private def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination)
if ENV['RELINE_STDERR_TTY']
- $stderr.reopen(ENV['RELINE_STDERR_TTY'], 'w')
+ if Reline::IOGate.win?
+ $stderr = File.open(ENV['RELINE_STDERR_TTY'], 'a')
+ else
+ $stderr.reopen(ENV['RELINE_STDERR_TTY'], 'w')
+ end
$stderr.sync = true
$stderr.puts "Reline is used by #{Process.pid}"
end
@@ -235,13 +239,25 @@ module Reline
line_editor.rerender
begin
+ prev_pasting_state = false
loop do
+ prev_pasting_state = Reline::IOGate.in_pasting?
read_io(config.keyseq_timeout) { |inputs|
+ line_editor.set_pasting_state(Reline::IOGate.in_pasting?)
inputs.each { |c|
line_editor.input_key(c)
line_editor.rerender
}
+ if @bracketed_paste_finished
+ line_editor.rerender_all
+ @bracketed_paste_finished = false
+ end
}
+ if prev_pasting_state == true and not Reline::IOGate.in_pasting? and not line_editor.finished?
+ line_editor.set_pasting_state(false)
+ prev_pasting_state = false
+ line_editor.rerender_all
+ end
break if line_editor.finished?
end
Reline::IOGate.move_cursor_column(0)
@@ -269,8 +285,13 @@ module Reline
buffer = []
loop do
c = Reline::IOGate.getc
- buffer << c
- result = key_stroke.match_status(buffer)
+ if c == -1
+ result = :unmatched
+ @bracketed_paste_finished = true
+ else
+ buffer << c
+ result = key_stroke.match_status(buffer)
+ end
case result
when :matched
expanded = key_stroke.expand(buffer).map{ |expanded_c|
@@ -336,9 +357,14 @@ module Reline
end
end
+ def ambiguous_width
+ may_req_ambiguous_char_width unless defined? @ambiguous_width
+ @ambiguous_width
+ end
+
private def may_req_ambiguous_char_width
@ambiguous_width = 2 if Reline::IOGate == Reline::GeneralIO or STDOUT.is_a?(File)
- return if ambiguous_width
+ return if @ambiguous_width
Reline::IOGate.move_cursor_column(0)
begin
output.write "\u{25bd}"
@@ -420,6 +446,10 @@ module Reline
}
end
+ def self.ungetc(c)
+ Reline::IOGate.ungetc(c)
+ end
+
def self.line_editor
core.line_editor
end
diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb
index 80fccd74f9..b2d7e7d910 100644
--- a/lib/reline/ansi.rb
+++ b/lib/reline/ansi.rb
@@ -1,4 +1,5 @@
require 'io/console'
+require 'timeout'
class Reline::ANSI
def self.encoding
@@ -67,7 +68,7 @@ class Reline::ANSI
end
@@buf = []
- def self.getc
+ def self.inner_getc
unless @@buf.empty?
return @@buf.shift
end
@@ -80,6 +81,62 @@ class Reline::ANSI
nil
end
+ @@in_bracketed_paste_mode = false
+ START_BRACKETED_PASTE = String.new("\e[200~,", encoding: Encoding::ASCII_8BIT)
+ END_BRACKETED_PASTE = String.new("\e[200~.", encoding: Encoding::ASCII_8BIT)
+ def self.getc_with_bracketed_paste
+ buffer = String.new(encoding: Encoding::ASCII_8BIT)
+ buffer << inner_getc
+ while START_BRACKETED_PASTE.start_with?(buffer) or END_BRACKETED_PASTE.start_with?(buffer) do
+ if START_BRACKETED_PASTE == buffer
+ @@in_bracketed_paste_mode = true
+ return inner_getc
+ elsif END_BRACKETED_PASTE == buffer
+ @@in_bracketed_paste_mode = false
+ ungetc(-1)
+ return inner_getc
+ end
+ begin
+ succ_c = nil
+ Timeout.timeout(Reline.core.config.keyseq_timeout * 100) {
+ succ_c = inner_getc
+ }
+ rescue Timeout::Error
+ break
+ else
+ buffer << succ_c
+ end
+ end
+ buffer.bytes.reverse_each do |ch|
+ ungetc ch
+ end
+ inner_getc
+ end
+
+ def self.getc
+ if Reline.core.config.enable_bracketed_paste
+ getc_with_bracketed_paste
+ else
+ inner_getc
+ end
+ end
+
+ def self.in_pasting?
+ @@in_bracketed_paste_mode or (not Reline::IOGate.empty_buffer?)
+ end
+
+ def self.empty_buffer?
+ unless @@buf.empty?
+ return false
+ end
+ rs, = IO.select([@@input], [], [], 0.00001)
+ if rs and rs[0]
+ false
+ else
+ true
+ end
+ end
+
def self.ungetc(c)
@@buf.unshift(c)
end
@@ -115,7 +172,7 @@ class Reline::ANSI
def self.cursor_pos
begin
- res = ''
+ res = +''
m = nil
@@input.raw do |stdin|
@@output << "\e[6n"
diff --git a/lib/reline/config.rb b/lib/reline/config.rb
index 370d100414..63ab7b7402 100644
--- a/lib/reline/config.rb
+++ b/lib/reline/config.rb
@@ -34,9 +34,11 @@ class Reline::Config
show-all-if-unmodified
visible-stats
show-mode-in-prompt
- vi-cmd-mode-icon
- vi-ins-mode-icon
+ 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|
@@ -54,8 +56,8 @@ class Reline::Config
@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_icon = '(cmd)'
- @vi_ins_mode_icon = '(ins)'
+ @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
@@ -237,7 +239,7 @@ class Reline::Config
when 'completion-query-items'
@completion_query_items = value.to_i
when 'isearch-terminators'
- @isearch_terminators = instance_eval(value)
+ @isearch_terminators = retrieve_string(value)
when 'editing-mode'
case value
when 'emacs'
@@ -268,9 +270,9 @@ class Reline::Config
@show_mode_in_prompt = false
end
when 'vi-cmd-mode-string'
- @vi_cmd_mode_icon = retrieve_string(value)
+ @vi_cmd_mode_string = retrieve_string(value)
when 'vi-ins-mode-string'
- @vi_ins_mode_icon = retrieve_string(value)
+ @vi_ins_mode_string = retrieve_string(value)
when 'emacs-mode-string'
@emacs_mode_string = retrieve_string(value)
when *VARIABLE_NAMES then
diff --git a/lib/reline/general_io.rb b/lib/reline/general_io.rb
index 85f1f13eed..01a592e038 100644
--- a/lib/reline/general_io.rb
+++ b/lib/reline/general_io.rb
@@ -1,6 +1,10 @@
require 'timeout'
class Reline::GeneralIO
+ def self.reset
+ @@pasting = false
+ end
+
def self.encoding
RUBY_PLATFORM =~ /mswin|mingw/ ? Encoding::UTF_8 : Encoding::default_external
end
@@ -67,6 +71,20 @@ class Reline::GeneralIO
def self.set_winch_handler(&handler)
end
+ @@pasting = false
+
+ def self.in_pasting?
+ @@pasting
+ end
+
+ def self.start_pasting
+ @@pasting = true
+ end
+
+ def self.finish_pasting
+ @@pasting = false
+ end
+
def self.prep
end
diff --git a/lib/reline/key_actor/emacs.rb b/lib/reline/key_actor/emacs.rb
index 1e51d4fa18..cad97a7d04 100644
--- a/lib/reline/key_actor/emacs.rb
+++ b/lib/reline/key_actor/emacs.rb
@@ -307,7 +307,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base
# 152 M-^X
:ed_unassigned,
# 153 M-^Y
- :ed_unassigned,
+ :em_yank_pop,
# 154 M-^Z
:ed_unassigned,
# 155 M-^[
diff --git a/lib/reline/key_actor/vi_command.rb b/lib/reline/key_actor/vi_command.rb
index 54b4a60383..98146d2f77 100644
--- a/lib/reline/key_actor/vi_command.rb
+++ b/lib/reline/key_actor/vi_command.rb
@@ -17,7 +17,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
# 7 ^G
:ed_unassigned,
# 8 ^H
- :ed_delete_prev_char,
+ :ed_unassigned,
# 9 ^I
:ed_unassigned,
# 10 ^J
@@ -255,7 +255,7 @@ class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
# 126 ~
:vi_change_case,
# 127 ^?
- :ed_delete_prev_char,
+ :ed_unassigned,
# 128 M-^@
:ed_unassigned,
# 129 M-^A
diff --git a/lib/reline/kill_ring.rb b/lib/reline/kill_ring.rb
index 842fd04697..bb3684b42b 100644
--- a/lib/reline/kill_ring.rb
+++ b/lib/reline/kill_ring.rb
@@ -1,4 +1,6 @@
class Reline::KillRing
+ include Enumerable
+
module State
FRESH = :fresh
CONTINUED = :continued
@@ -110,4 +112,14 @@ class Reline::KillRing
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
index 9bdccae9c9..7d71e62d63 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -50,12 +50,48 @@ class Reline::LineEditor
CompletionJourneyData = Struct.new('CompletionJourneyData', :preposing, :postposing, :list, :pointer)
MenuInfo = Struct.new('MenuInfo', :target, :list)
+ PROMPT_LIST_CACHE_TIMEOUT = 0.5
+
def initialize(config, encoding)
@config = config
@completion_append_character = ''
reset_variables(encoding: encoding)
end
+ def set_pasting_state(in_pasting)
+ @in_pasting = in_pasting
+ end
+
+ def simplified_rendering?
+ if finished?
+ false
+ elsif @just_cursor_moving and not @rerender_all
+ true
+ else
+ not @rerender_all and not finished? and @in_pasting
+ end
+ end
+
+ private def check_mode_string
+ mode_string = nil
+ if @config.show_mode_in_prompt
+ if @config.editing_mode_is?(:vi_command)
+ mode_string = @config.vi_cmd_mode_string
+ elsif @config.editing_mode_is?(:vi_insert)
+ mode_string = @config.vi_ins_mode_string
+ elsif @config.editing_mode_is?(:emacs)
+ mode_string = @config.emacs_mode_string
+ else
+ mode_string = '?'
+ end
+ end
+ if mode_string != @prev_mode_string
+ @rerender_all = true
+ end
+ @prev_mode_string = mode_string
+ mode_string
+ end
+
private def check_multiline_prompt(buffer, prompt)
if @vi_arg
prompt = "(arg: #{@vi_arg}) "
@@ -66,38 +102,45 @@ class Reline::LineEditor
else
prompt = @prompt
end
+ if simplified_rendering?
+ mode_string = check_mode_string
+ prompt = mode_string + prompt if mode_string
+ return [prompt, calculate_width(prompt, true), [prompt] * buffer.size]
+ end
if @prompt_proc
- prompt_list = @prompt_proc.(buffer)
- prompt_list.map!{ prompt } if @vi_arg or @searching_prompt
- if @config.show_mode_in_prompt
- if @config.editing_mode_is?(:vi_command)
- mode_icon = @config.vi_cmd_mode_icon
- elsif @config.editing_mode_is?(:vi_insert)
- mode_icon = @config.vi_ins_mode_icon
- elsif @config.editing_mode_is?(:emacs)
- mode_icon = @config.emacs_mode_string
- else
- mode_icon = '?'
+ use_cached_prompt_list = false
+ if @cached_prompt_list
+ if @just_cursor_moving
+ use_cached_prompt_list = true
+ elsif Time.now.to_f < (@prompt_cache_time + PROMPT_LIST_CACHE_TIMEOUT) and buffer.size == @cached_prompt_list.size
+ use_cached_prompt_list = true
end
- prompt_list.map!{ |pr| mode_icon + pr }
end
+ use_cached_prompt_list = false if @rerender_all
+ if use_cached_prompt_list
+ prompt_list = @cached_prompt_list
+ else
+ prompt_list = @cached_prompt_list = @prompt_proc.(buffer)
+ @prompt_cache_time = Time.now.to_f
+ end
+ prompt_list.map!{ prompt } if @vi_arg or @searching_prompt
+ prompt_list = [prompt] if prompt_list.empty?
+ mode_string = check_mode_string
+ prompt_list = prompt_list.map{ |pr| mode_string + pr } if mode_string
prompt = prompt_list[@line_index]
+ prompt = prompt_list[0] if prompt.nil?
+ prompt = prompt_list.last if prompt.nil?
+ if buffer.size > prompt_list.size
+ (buffer.size - prompt_list.size).times do
+ prompt_list << prompt_list.last
+ end
+ end
prompt_width = calculate_width(prompt, true)
[prompt, prompt_width, prompt_list]
else
+ mode_string = check_mode_string
+ prompt = mode_string + prompt if mode_string
prompt_width = calculate_width(prompt, true)
- if @config.show_mode_in_prompt
- if @config.editing_mode_is?(:vi_command)
- mode_icon = @config.vi_cmd_mode_icon
- elsif @config.editing_mode_is?(:vi_insert)
- mode_icon = @config.vi_ins_mode_icon
- elsif @config.editing_mode_is?(:emacs)
- mode_icon = @config.emacs_mode_string
- else
- mode_icon = '?'
- end
- prompt = mode_icon + prompt
- end
[prompt, prompt_width, nil]
end
end
@@ -105,8 +148,16 @@ class Reline::LineEditor
def reset(prompt = '', encoding:)
@rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
@screen_size = Reline::IOGate.get_screen_size
+ @screen_height = @screen_size.first
reset_variables(prompt, encoding: encoding)
@old_trap = Signal.trap('SIGINT') {
+ if @scroll_partial_screen
+ move_cursor_down(@screen_height - (@line_index - @scroll_partial_screen) - 1)
+ else
+ move_cursor_down(@highest_in_all - @line_index - 1)
+ end
+ Reline::IOGate.move_cursor_column(0)
+ scroll_down(1)
@old_trap.call if @old_trap.respond_to?(:call) # can also be string, ex: "DEFAULT"
raise Interrupt
}
@@ -114,6 +165,7 @@ class Reline::LineEditor
@rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
old_screen_size = @screen_size
@screen_size = Reline::IOGate.get_screen_size
+ @screen_height = @screen_size.first
if old_screen_size.last < @screen_size.last # columns increase
@rerender_all = true
rerender
@@ -165,11 +217,12 @@ class Reline::LineEditor
@cleared = false
@rerender_all = false
@history_pointer = nil
- @kill_ring = Reline::KillRing.new
+ @kill_ring ||= Reline::KillRing.new
@vi_clipboard = ''
@vi_arg = nil
@waiting_proc = nil
@waiting_operator_proc = nil
+ @waiting_operator_vi_arg = nil
@completion_journey_data = nil
@completion_state = CompletionState::NORMAL
@perfect_matched = nil
@@ -177,7 +230,17 @@ class Reline::LineEditor
@first_prompt = true
@searching_prompt = nil
@first_char = true
+ @add_newline_to_end_of_buffer = false
+ @just_cursor_moving = nil
+ @cached_prompt_list = nil
+ @prompt_cache_time = nil
@eof = false
+ @continuous_insertion_buffer = String.new(encoding: @encoding)
+ @scroll_partial_screen = nil
+ @prev_mode_string = nil
+ @drop_terminate_spaces = false
+ @in_pasting = false
+ @auto_indent_proc = nil
reset_line
end
@@ -222,6 +285,7 @@ class Reline::LineEditor
@buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding))
@previous_line_index = @line_index
@line_index += 1
+ @just_cursor_moving = false
end
private def calculate_height_by_width(width)
@@ -262,28 +326,29 @@ class Reline::LineEditor
end
end
- private def calculate_nearest_cursor
- @cursor_max = calculate_width(line)
+ private def calculate_nearest_cursor(line_to_calc = @line, cursor = @cursor, started_from = @started_from, byte_pointer = @byte_pointer, update = true)
+ new_cursor_max = calculate_width(line_to_calc)
new_cursor = 0
new_byte_pointer = 0
height = 1
max_width = @screen_size.last
if @config.editing_mode_is?(:vi_command)
- last_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @line.bytesize)
+ last_byte_size = Reline::Unicode.get_prev_mbchar_size(line_to_calc, line_to_calc.bytesize)
if last_byte_size > 0
- last_mbchar = @line.byteslice(@line.bytesize - last_byte_size, last_byte_size)
+ last_mbchar = line_to_calc.byteslice(line_to_calc.bytesize - last_byte_size, last_byte_size)
last_width = Reline::Unicode.get_mbchar_width(last_mbchar)
- cursor_max = @cursor_max - last_width
+ end_of_line_cursor = new_cursor_max - last_width
else
- cursor_max = @cursor_max
+ end_of_line_cursor = new_cursor_max
end
else
- cursor_max = @cursor_max
+ end_of_line_cursor = new_cursor_max
end
- @line.encode(Encoding::UTF_8).grapheme_clusters.each do |gc|
- mbchar_width = Reline::Unicode.get_mbchar_width(gc)
+ line_to_calc.grapheme_clusters.each do |gc|
+ mbchar = gc.encode(Encoding::UTF_8)
+ mbchar_width = Reline::Unicode.get_mbchar_width(mbchar)
now = new_cursor + mbchar_width
- if now > cursor_max or now > @cursor
+ if now > end_of_line_cursor or now > cursor
break
end
new_cursor += mbchar_width
@@ -292,9 +357,21 @@ class Reline::LineEditor
end
new_byte_pointer += gc.bytesize
end
- @started_from = height - 1
- @cursor = new_cursor
- @byte_pointer = new_byte_pointer
+ new_started_from = height - 1
+ if update
+ @cursor = new_cursor
+ @cursor_max = new_cursor_max
+ @started_from = new_started_from
+ @byte_pointer = new_byte_pointer
+ else
+ [new_cursor, new_cursor_max, new_started_from, new_byte_pointer]
+ end
+ end
+
+ def rerender_all
+ @rerender_all = true
+ process_insert(force: true)
+ rerender
end
def rerender
@@ -302,178 +379,330 @@ class Reline::LineEditor
if @menu_info
scroll_down(@highest_in_all - @first_line_started_from)
@rerender_all = true
- @menu_info.list.sort!.each do |item|
- Reline::IOGate.move_cursor_column(0)
- @output.write item
- @output.flush
- scroll_down(1)
- end
- scroll_down(@highest_in_all - 1)
- move_cursor_up(@highest_in_all - 1 - @first_line_started_from)
+ end
+ if @menu_info
+ show_menu
@menu_info = nil
end
prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
if @cleared
- Reline::IOGate.clear_screen
+ clear_screen_buffer(prompt, prompt_list, prompt_width)
@cleared = false
- back = 0
- modify_lines(whole_lines).each_with_index do |line, index|
- if @prompt_proc
- pr = prompt_list[index]
- height = render_partial(pr, calculate_width(pr), line, false)
- else
- height = render_partial(prompt, prompt_width, line, false)
- end
- if index < (@buffer_of_lines.size - 1)
- move_cursor_down(height)
- back += height
- end
- end
- move_cursor_up(back)
- move_cursor_down(@first_line_started_from + @started_from)
- Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
return
end
- new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line))
- # FIXME: end of logical line sometimes breaks
- if @previous_line_index or new_highest_in_this != @highest_in_this
+ if @is_multiline and finished? and @scroll_partial_screen
+ # Re-output all code higher than the screen when finished.
+ Reline::IOGate.move_cursor_up(@first_line_started_from + @started_from - @scroll_partial_screen)
+ Reline::IOGate.move_cursor_column(0)
+ @scroll_partial_screen = nil
+ prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
if @previous_line_index
new_lines = whole_lines(index: @previous_line_index, line: @line)
else
new_lines = whole_lines
end
- prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines, prompt)
- all_height = calculate_height_by_lines(new_lines, prompt_list || prompt)
- diff = all_height - @highest_in_all
- move_cursor_down(@highest_in_all - @first_line_started_from - @started_from - 1)
- if diff > 0
- scroll_down(diff)
- move_cursor_up(all_height - 1)
- elsif diff < 0
- (-diff).times do
- Reline::IOGate.move_cursor_column(0)
- Reline::IOGate.erase_after_cursor
- move_cursor_up(1)
- end
- move_cursor_up(all_height - 1)
+ modify_lines(new_lines).each_with_index do |line, index|
+ @output.write "#{prompt_list ? prompt_list[index] : prompt}#{line}\n"
+ Reline::IOGate.erase_after_cursor
+ end
+ @output.flush
+ return
+ end
+ new_highest_in_this = calculate_height_by_width(prompt_width + calculate_width(@line.nil? ? '' : @line))
+ # FIXME: end of logical line sometimes breaks
+ rendered = false
+ if @add_newline_to_end_of_buffer
+ rerender_added_newline(prompt, prompt_width)
+ @add_newline_to_end_of_buffer = false
+ else
+ if @just_cursor_moving and not @rerender_all
+ rendered = just_move_cursor
+ @just_cursor_moving = false
+ return
+ elsif @previous_line_index or new_highest_in_this != @highest_in_this
+ rerender_changed_current_line
+ @previous_line_index = nil
+ rendered = true
+ elsif @rerender_all
+ rerender_all_lines
+ @rerender_all = false
+ rendered = true
else
- move_cursor_up(all_height - 1)
end
- @highest_in_all = all_height
- back = 0
- modify_lines(new_lines).each_with_index do |line, index|
- if @prompt_proc
- prompt = prompt_list[index]
- prompt_width = calculate_width(prompt, true)
- end
- height = render_partial(prompt, prompt_width, line, false)
- if index < (new_lines.size - 1)
- scroll_down(1)
- back += height
+ end
+ if @is_multiline
+ if finished?
+ # Always rerender on finish because output_modifier_proc may return a different output.
+ if @previous_line_index
+ new_lines = whole_lines(index: @previous_line_index, line: @line)
else
- back += height - 1
+ new_lines = whole_lines
+ end
+ line = modify_lines(new_lines)[@line_index]
+ prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines, prompt)
+ render_partial(prompt, prompt_width, line, @first_line_started_from)
+ move_cursor_down(@highest_in_all - (@first_line_started_from + @highest_in_this - 1) - 1)
+ scroll_down(1)
+ Reline::IOGate.move_cursor_column(0)
+ Reline::IOGate.erase_after_cursor
+ elsif not rendered
+ unless @in_pasting
+ line = modify_lines(whole_lines)[@line_index]
+ prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
+ render_partial(prompt, prompt_width, line, @first_line_started_from)
end
end
- move_cursor_up(back)
- if @previous_line_index
- @buffer_of_lines[@previous_line_index] = @line
- @line = @buffer_of_lines[@line_index]
+ @buffer_of_lines[@line_index] = @line
+ @rest_height = 0 if @scroll_partial_screen
+ else
+ line = modify_lines(whole_lines)[@line_index]
+ render_partial(prompt, prompt_width, line, 0)
+ if finished?
+ scroll_down(1)
+ Reline::IOGate.move_cursor_column(0)
+ Reline::IOGate.erase_after_cursor
end
- @first_line_started_from =
- if @line_index.zero?
- 0
+ end
+ end
+
+ private def calculate_scroll_partial_screen(highest_in_all, cursor_y)
+ if @screen_height < highest_in_all
+ old_scroll_partial_screen = @scroll_partial_screen
+ if cursor_y == 0
+ @scroll_partial_screen = 0
+ elsif cursor_y == (highest_in_all - 1)
+ @scroll_partial_screen = highest_in_all - @screen_height
+ else
+ if @scroll_partial_screen
+ if cursor_y <= @scroll_partial_screen
+ @scroll_partial_screen = cursor_y
+ elsif (@scroll_partial_screen + @screen_height - 1) < cursor_y
+ @scroll_partial_screen = cursor_y - (@screen_height - 1)
+ end
else
- calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
+ if cursor_y > (@screen_height - 1)
+ @scroll_partial_screen = cursor_y - (@screen_height - 1)
+ else
+ @scroll_partial_screen = 0
+ end
end
- if @prompt_proc
- prompt = prompt_list[@line_index]
- prompt_width = calculate_width(prompt, true)
end
- move_cursor_down(@first_line_started_from)
- calculate_nearest_cursor
- @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
- move_cursor_down(@started_from)
- Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
- @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
- @previous_line_index = nil
- rendered = true
- elsif @rerender_all
- move_cursor_up(@first_line_started_from + @started_from)
- Reline::IOGate.move_cursor_column(0)
- back = 0
- new_buffer = whole_lines
- prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt)
- new_buffer.each_with_index do |line, index|
- prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
- width = prompt_width + calculate_width(line)
- height = calculate_height_by_width(width)
- back += height
+ if @scroll_partial_screen != old_scroll_partial_screen
+ @rerender_all = true
end
- if back > @highest_in_all
- scroll_down(back - 1)
- move_cursor_up(back - 1)
- elsif back < @highest_in_all
- scroll_down(back)
- Reline::IOGate.erase_after_cursor
- (@highest_in_all - back - 1).times do
- scroll_down(1)
- Reline::IOGate.erase_after_cursor
- end
- move_cursor_up(@highest_in_all - 1)
+ else
+ if @scroll_partial_screen
+ @rerender_all = true
end
- modify_lines(new_buffer).each_with_index do |line, index|
- if @prompt_proc
- prompt = prompt_list[index]
- prompt_width = calculate_width(prompt, true)
- end
- render_partial(prompt, prompt_width, line, false)
- if index < (new_buffer.size - 1)
- move_cursor_down(1)
- end
+ @scroll_partial_screen = nil
+ end
+ end
+
+ private def rerender_added_newline(prompt, prompt_width)
+ scroll_down(1)
+ @buffer_of_lines[@previous_line_index] = @line
+ @line = @buffer_of_lines[@line_index]
+ unless @in_pasting
+ render_partial(prompt, prompt_width, @line, @first_line_started_from + @started_from + 1, with_control: false)
+ end
+ @cursor = @cursor_max = calculate_width(@line)
+ @byte_pointer = @line.bytesize
+ @highest_in_all += @highest_in_this
+ @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
+ @first_line_started_from += @started_from + 1
+ @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
+ @previous_line_index = nil
+ end
+
+ def just_move_cursor
+ prompt, prompt_width, prompt_list = check_multiline_prompt(@buffer_of_lines, prompt)
+ move_cursor_up(@started_from)
+ new_first_line_started_from =
+ if @line_index.zero?
+ 0
+ else
+ calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
end
- move_cursor_up(back - 1)
- if @prompt_proc
- prompt = prompt_list[@line_index]
- prompt_width = calculate_width(prompt, true)
- end
- @highest_in_all = back
- @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
- @first_line_started_from =
- if @line_index.zero?
- 0
- else
- calculate_height_by_lines(new_buffer[0..(@line_index - 1)], prompt_list || prompt)
- end
- @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
- move_cursor_down(@first_line_started_from + @started_from)
- Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ first_line_diff = new_first_line_started_from - @first_line_started_from
+ new_cursor, new_cursor_max, new_started_from, new_byte_pointer = calculate_nearest_cursor(@buffer_of_lines[@line_index], @cursor, @started_from, @byte_pointer, false)
+ new_started_from = calculate_height_by_width(prompt_width + new_cursor) - 1
+ calculate_scroll_partial_screen(@highest_in_all, new_first_line_started_from + new_started_from)
+ @previous_line_index = nil
+ if @rerender_all
+ @line = @buffer_of_lines[@line_index]
+ rerender_all_lines
@rerender_all = false
- rendered = true
+ true
+ else
+ @line = @buffer_of_lines[@line_index]
+ @first_line_started_from = new_first_line_started_from
+ @started_from = new_started_from
+ @cursor = new_cursor
+ @cursor_max = new_cursor_max
+ @byte_pointer = new_byte_pointer
+ move_cursor_down(first_line_diff + @started_from)
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ false
end
- line = modify_lines(whole_lines)[@line_index]
- if @is_multiline
- prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
- if finished?
- # Always rerender on finish because output_modifier_proc may return a different output.
- render_partial(prompt, prompt_width, line)
- scroll_down(1)
+ end
+
+ private def rerender_changed_current_line
+ if @previous_line_index
+ new_lines = whole_lines(index: @previous_line_index, line: @line)
+ else
+ new_lines = whole_lines
+ end
+ prompt, prompt_width, prompt_list = check_multiline_prompt(new_lines, prompt)
+ all_height = calculate_height_by_lines(new_lines, prompt_list || prompt)
+ diff = all_height - @highest_in_all
+ move_cursor_down(@highest_in_all - @first_line_started_from - @started_from - 1)
+ if diff > 0
+ scroll_down(diff)
+ move_cursor_up(all_height - 1)
+ elsif diff < 0
+ (-diff).times do
Reline::IOGate.move_cursor_column(0)
Reline::IOGate.erase_after_cursor
- elsif not rendered
- render_partial(prompt, prompt_width, line)
+ move_cursor_up(1)
end
+ move_cursor_up(all_height - 1)
else
- render_partial(prompt, prompt_width, line)
- if finished?
+ move_cursor_up(all_height - 1)
+ end
+ @highest_in_all = all_height
+ back = render_whole_lines(new_lines, prompt_list || prompt, prompt_width)
+ move_cursor_up(back)
+ if @previous_line_index
+ @buffer_of_lines[@previous_line_index] = @line
+ @line = @buffer_of_lines[@line_index]
+ end
+ @first_line_started_from =
+ if @line_index.zero?
+ 0
+ else
+ calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
+ end
+ if @prompt_proc
+ prompt = prompt_list[@line_index]
+ prompt_width = calculate_width(prompt, true)
+ end
+ move_cursor_down(@first_line_started_from)
+ calculate_nearest_cursor
+ @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
+ move_cursor_down(@started_from)
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
+ end
+
+ private def rerender_all_lines
+ move_cursor_up(@first_line_started_from + @started_from)
+ Reline::IOGate.move_cursor_column(0)
+ back = 0
+ new_buffer = whole_lines
+ prompt, prompt_width, prompt_list = check_multiline_prompt(new_buffer, prompt)
+ new_buffer.each_with_index do |line, index|
+ prompt_width = calculate_width(prompt_list[index], true) if @prompt_proc
+ width = prompt_width + calculate_width(line)
+ height = calculate_height_by_width(width)
+ back += height
+ end
+ old_highest_in_all = @highest_in_all
+ if @line_index.zero?
+ new_first_line_started_from = 0
+ else
+ new_first_line_started_from = calculate_height_by_lines(new_buffer[0..(@line_index - 1)], prompt_list || prompt)
+ end
+ new_started_from = calculate_height_by_width(prompt_width + @cursor) - 1
+ calculate_scroll_partial_screen(back, new_first_line_started_from + new_started_from)
+ if @scroll_partial_screen
+ move_cursor_up(@first_line_started_from + @started_from)
+ scroll_down(@screen_height - 1)
+ move_cursor_up(@screen_height)
+ Reline::IOGate.move_cursor_column(0)
+ elsif back > old_highest_in_all
+ scroll_down(back - 1)
+ move_cursor_up(back - 1)
+ elsif back < old_highest_in_all
+ scroll_down(back)
+ Reline::IOGate.erase_after_cursor
+ (old_highest_in_all - back - 1).times do
scroll_down(1)
- Reline::IOGate.move_cursor_column(0)
Reline::IOGate.erase_after_cursor
end
+ move_cursor_up(old_highest_in_all - 1)
+ end
+ render_whole_lines(new_buffer, prompt_list || prompt, prompt_width)
+ if @prompt_proc
+ prompt = prompt_list[@line_index]
+ prompt_width = calculate_width(prompt, true)
+ end
+ @highest_in_this = calculate_height_by_width(prompt_width + @cursor_max)
+ @highest_in_all = back
+ @first_line_started_from = new_first_line_started_from
+ @started_from = new_started_from
+ if @scroll_partial_screen
+ Reline::IOGate.move_cursor_up(@screen_height - (@first_line_started_from + @started_from - @scroll_partial_screen) - 1)
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ else
+ move_cursor_down(@first_line_started_from + @started_from - back + 1)
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ end
+ end
+
+ private def render_whole_lines(lines, prompt, prompt_width)
+ rendered_height = 0
+ modify_lines(lines).each_with_index do |line, index|
+ if prompt.is_a?(Array)
+ line_prompt = prompt[index]
+ prompt_width = calculate_width(line_prompt, true)
+ else
+ line_prompt = prompt
+ end
+ height = render_partial(line_prompt, prompt_width, line, rendered_height, with_control: false)
+ if index < (lines.size - 1)
+ if @scroll_partial_screen
+ if (@scroll_partial_screen - height) < rendered_height and (@scroll_partial_screen + @screen_height - 1) >= (rendered_height + height)
+ move_cursor_down(1)
+ end
+ else
+ scroll_down(1)
+ end
+ rendered_height += height
+ else
+ rendered_height += height - 1
+ end
end
+ rendered_height
end
- private def render_partial(prompt, prompt_width, line_to_render, with_control = true)
+ private def render_partial(prompt, prompt_width, line_to_render, this_started_from, with_control: true)
visual_lines, height = split_by_width(line_to_render.nil? ? prompt : prompt + line_to_render, @screen_size.last)
+ cursor_up_from_last_line = 0
+ # TODO: This logic would be sometimes buggy if this logical line isn't the current @line_index.
+ if @scroll_partial_screen
+ last_visual_line = this_started_from + (height - 1)
+ last_screen_line = @scroll_partial_screen + (@screen_height - 1)
+ if (@scroll_partial_screen - this_started_from) >= height
+ # Render nothing because this line is before the screen.
+ visual_lines = []
+ elsif this_started_from > last_screen_line
+ # Render nothing because this line is after the screen.
+ visual_lines = []
+ else
+ deleted_lines_before_screen = []
+ if @scroll_partial_screen > this_started_from and last_visual_line >= @scroll_partial_screen
+ # A part of visual lines are before the screen.
+ deleted_lines_before_screen = visual_lines.shift((@scroll_partial_screen - this_started_from) * 2)
+ deleted_lines_before_screen.compact!
+ end
+ if this_started_from <= last_screen_line and last_screen_line < last_visual_line
+ # A part of visual lines are after the screen.
+ visual_lines.pop((last_visual_line - last_screen_line) * 2)
+ end
+ move_cursor_up(deleted_lines_before_screen.size - @started_from)
+ cursor_up_from_last_line = @started_from - deleted_lines_before_screen.size
+ end
+ end
if with_control
if height > @highest_in_this
diff = height - @highest_in_this
@@ -488,13 +717,17 @@ class Reline::LineEditor
end
move_cursor_up(@started_from)
@started_from = calculate_height_by_width(prompt_width + @cursor) - 1
+ cursor_up_from_last_line = height - 1 - @started_from
+ end
+ if Reline::Unicode::CSI_REGEXP.match?(prompt + line_to_render)
+ @output.write "\e[0m" # clear character decorations
end
- Reline::IOGate.move_cursor_column(0)
visual_lines.each_with_index do |line, index|
+ Reline::IOGate.move_cursor_column(0)
if line.nil?
if calculate_width(visual_lines[index - 1], true) == Reline::IOGate.get_screen_size.last
# reaches the end of line
- if Reline::IOGate.win?
+ if Reline::IOGate.win? and Reline::IOGate.win_legacy_console?
# A newline is automatically inserted if a character is rendered at
# eol on command prompt.
else
@@ -512,7 +745,7 @@ class Reline::LineEditor
next
end
@output.write line
- if Reline::IOGate.win? and calculate_width(line, true) == Reline::IOGate.get_screen_size.last
+ if Reline::IOGate.win? and Reline::IOGate.win_legacy_console? and calculate_width(line, true) == Reline::IOGate.get_screen_size.last
# A newline is automatically inserted if a character is rendered at eol on command prompt.
@rest_height -= 1 if @rest_height > 0
end
@@ -522,14 +755,18 @@ class Reline::LineEditor
@pre_input_hook&.call
end
end
- Reline::IOGate.erase_after_cursor
+ unless visual_lines.empty?
+ Reline::IOGate.erase_after_cursor
+ Reline::IOGate.move_cursor_column(0)
+ end
if with_control
# Just after rendring, so the cursor is on the last line.
if finished?
Reline::IOGate.move_cursor_column(0)
else
# Moves up from bottom of lines to the cursor position.
- move_cursor_up(height - 1 - @started_from)
+ move_cursor_up(cursor_up_from_last_line)
+ # This logic is buggy if a fullwidth char is wrapped because there is only one halfwidth at end of a line.
Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
end
end
@@ -537,7 +774,7 @@ class Reline::LineEditor
end
private def modify_lines(before)
- return before if before.nil? || before.empty?
+ return before if before.nil? || before.empty? || simplified_rendering?
if after = @output_modifier_proc&.call("#{before.join("\n")}\n", complete: finished?)
after.lines("\n").map { |l| l.chomp('') }
@@ -546,6 +783,40 @@ class Reline::LineEditor
end
end
+ private def show_menu
+ scroll_down(@highest_in_all - @first_line_started_from)
+ @rerender_all = true
+ @menu_info.list.sort!.each do |item|
+ Reline::IOGate.move_cursor_column(0)
+ @output.write item
+ @output.flush
+ scroll_down(1)
+ end
+ scroll_down(@highest_in_all - 1)
+ move_cursor_up(@highest_in_all - 1 - @first_line_started_from)
+ end
+
+ private def clear_screen_buffer(prompt, prompt_list, prompt_width)
+ Reline::IOGate.clear_screen
+ back = 0
+ modify_lines(whole_lines).each_with_index do |line, index|
+ if @prompt_proc
+ pr = prompt_list[index]
+ height = render_partial(pr, calculate_width(pr), line, back, with_control: false)
+ else
+ height = render_partial(prompt, prompt_width, line, back, with_control: false)
+ end
+ if index < (@buffer_of_lines.size - 1)
+ move_cursor_down(height)
+ back += height
+ end
+ end
+ move_cursor_up(back)
+ move_cursor_down(@first_line_started_from + @started_from)
+ @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
+ Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+ end
+
def editing_mode
@config.editing_mode
end
@@ -565,7 +836,7 @@ class Reline::LineEditor
else
i&.start_with?(target)
end
- }
+ }.uniq
if is_menu
menu(target, list)
return nil
@@ -682,7 +953,8 @@ class Reline::LineEditor
if @waiting_operator_proc
if VI_MOTIONS.include?(method_symbol)
old_cursor, old_byte_pointer = @cursor, @byte_pointer
- block.()
+ @vi_arg = @waiting_operator_vi_arg if @waiting_operator_vi_arg > 1
+ block.(true)
unless @waiting_proc
cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer
@cursor, @byte_pointer = old_cursor, old_byte_pointer
@@ -690,27 +962,56 @@ class Reline::LineEditor
else
old_waiting_proc = @waiting_proc
old_waiting_operator_proc = @waiting_operator_proc
+ current_waiting_operator_proc = @waiting_operator_proc
@waiting_proc = proc { |k|
old_cursor, old_byte_pointer = @cursor, @byte_pointer
old_waiting_proc.(k)
cursor_diff, byte_pointer_diff = @cursor - old_cursor, @byte_pointer - old_byte_pointer
@cursor, @byte_pointer = old_cursor, old_byte_pointer
- @waiting_operator_proc.(cursor_diff, byte_pointer_diff)
+ current_waiting_operator_proc.(cursor_diff, byte_pointer_diff)
@waiting_operator_proc = old_waiting_operator_proc
}
end
else
# Ignores operator when not motion is given.
- block.()
+ block.(false)
end
@waiting_operator_proc = nil
+ @waiting_operator_vi_arg = nil
+ @vi_arg = nil
else
- block.()
+ block.(false)
end
end
private def argumentable?(method_obj)
- method_obj and method_obj.parameters.length != 1
+ method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :arg }
+ end
+
+ private def inclusive?(method_obj)
+ # If a motion method with the keyword argument "inclusive" follows the
+ # operator, it must contain the character at the cursor position.
+ method_obj and method_obj.parameters.any? { |param| param[0] == :key and param[1] == :inclusive }
+ end
+
+ def wrap_method_call(method_symbol, method_obj, key, with_operator = false)
+ if @config.editing_mode_is?(:emacs, :vi_insert) and @waiting_proc.nil? and @waiting_operator_proc.nil?
+ not_insertion = method_symbol != :ed_insert
+ process_insert(force: not_insertion)
+ end
+ if @vi_arg and argumentable?(method_obj)
+ if with_operator and inclusive?(method_obj)
+ method_obj.(key, arg: @vi_arg, inclusive: true)
+ else
+ method_obj.(key, arg: @vi_arg)
+ end
+ else
+ if with_operator and inclusive?(method_obj)
+ method_obj.(key, inclusive: true)
+ else
+ method_obj.(key)
+ end
+ end
end
private def process_key(key, method_symbol)
@@ -721,11 +1022,11 @@ class Reline::LineEditor
end
if method_symbol and key.is_a?(Symbol)
if @vi_arg and argumentable?(method_obj)
- run_for_operators(key, method_symbol) do
- method_obj.(key, arg: @vi_arg)
+ run_for_operators(key, method_symbol) do |with_operator|
+ wrap_method_call(method_symbol, method_obj, key, with_operator)
end
else
- method_obj&.(key)
+ wrap_method_call(method_symbol, method_obj, key) if method_obj
end
@kill_ring.process
@vi_arg = nil
@@ -734,15 +1035,15 @@ class Reline::LineEditor
ed_argument_digit(key)
else
if argumentable?(method_obj)
- run_for_operators(key, method_symbol) do
- method_obj.(key, arg: @vi_arg)
+ run_for_operators(key, method_symbol) do |with_operator|
+ wrap_method_call(method_symbol, method_obj, key, with_operator)
end
elsif @waiting_proc
@waiting_proc.(key)
elsif method_obj
- method_obj.(key)
+ wrap_method_call(method_symbol, method_obj, key)
else
- ed_insert(key)
+ ed_insert(key) unless @config.editing_mode_is?(:vi_command)
end
@kill_ring.process
@vi_arg = nil
@@ -752,15 +1053,15 @@ class Reline::LineEditor
@kill_ring.process
elsif method_obj
if method_symbol == :ed_argument_digit
- method_obj.(key)
+ wrap_method_call(method_symbol, method_obj, key)
else
- run_for_operators(key, method_symbol) do
- method_obj.(key)
+ run_for_operators(key, method_symbol) do |with_operator|
+ wrap_method_call(method_symbol, method_obj, key, with_operator)
end
end
@kill_ring.process
else
- ed_insert(key)
+ ed_insert(key) unless @config.editing_mode_is?(:vi_command)
end
end
@@ -803,6 +1104,7 @@ class Reline::LineEditor
end
def input_key(key)
+ @just_cursor_moving = nil
if key.char.nil?
if @first_char
@line = nil
@@ -810,6 +1112,7 @@ class Reline::LineEditor
finish
return
end
+ old_line = @line.dup
@first_char = false
completion_occurs = false
if @config.editing_mode_is?(:emacs, :vi_insert) and key.char == "\C-i".ord
@@ -817,6 +1120,7 @@ class Reline::LineEditor
result = call_completion_proc
if result.is_a?(Array)
completion_occurs = true
+ process_insert
complete(result)
end
end
@@ -825,6 +1129,7 @@ class Reline::LineEditor
result = call_completion_proc
if result.is_a?(Array)
completion_occurs = true
+ process_insert
move_completed_list(result, "\C-p".ord == key.char ? :up : :down)
end
end
@@ -836,15 +1141,43 @@ class Reline::LineEditor
unless completion_occurs
@completion_state = CompletionState::NORMAL
end
- if @is_multiline and @auto_indent_proc
+ if not @in_pasting and @just_cursor_moving.nil?
+ if @previous_line_index and @buffer_of_lines[@previous_line_index] == @line
+ @just_cursor_moving = true
+ elsif @previous_line_index.nil? and @buffer_of_lines[@line_index] == @line and old_line == @line
+ @just_cursor_moving = true
+ else
+ @just_cursor_moving = false
+ end
+ else
+ @just_cursor_moving = false
+ end
+ if @is_multiline and @auto_indent_proc and not simplified_rendering?
process_auto_indent
end
end
def call_completion_proc
result = retrieve_completion_block(true)
- slice = result[1]
- result = @completion_proc.(slice) if @completion_proc and slice
+ preposing, target, postposing = result
+ 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, preposing)
+ when 3..Float::INFINITY
+ result = @completion_proc.(target, preposing, postposing)
+ end
+ end
Reline.core.instance_variable_set(:@completion_quote_character, nil)
result
end
@@ -874,6 +1207,7 @@ class Reline::LineEditor
new_lines = whole_lines
end
new_indent = @auto_indent_proc.(new_lines, @line_index, @byte_pointer, @check_new_auto_indent)
+ new_indent = @cursor_max if new_indent&.> @cursor_max
if new_indent&.>= 0
md = new_lines[@line_index].match(/\A */)
prev_indent = md[0].count(' ')
@@ -891,8 +1225,16 @@ class Reline::LineEditor
end
def retrieve_completion_block(set_completion_quote_character = false)
- word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/
- quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/
+ if Reline.completer_word_break_characters.empty?
+ word_break_regexp = nil
+ else
+ word_break_regexp = /\A[#{Regexp.escape(Reline.completer_word_break_characters)}]/
+ end
+ if Reline.completer_quote_characters.empty?
+ quote_characters_regexp = nil
+ else
+ quote_characters_regexp = /\A[#{Regexp.escape(Reline.completer_quote_characters)}]/
+ end
before = @line.byteslice(0, @byte_pointer)
rest = nil
break_pointer = nil
@@ -913,14 +1255,14 @@ class Reline::LineEditor
elsif quote and slice.start_with?(escaped_quote)
# skip
i += 2
- elsif slice =~ quote_characters_regexp # find new "
+ elsif quote_characters_regexp and slice =~ quote_characters_regexp # find new "
rest = $'
quote = $&
closing_quote = /(?!\\)#{Regexp.escape(quote)}/
escaped_quote = /\\#{Regexp.escape(quote)}/
i += 1
break_pointer = i - 1
- elsif not quote and slice =~ word_break_regexp
+ elsif word_break_regexp and not quote and slice =~ word_break_regexp
rest = $'
i += 1
before = @line.byteslice(i, @byte_pointer - i)
@@ -948,6 +1290,19 @@ class Reline::LineEditor
end
target = before
end
+ if @is_multiline
+ if @previous_line_index
+ lines = whole_lines(index: @previous_line_index, line: @line)
+ else
+ lines = whole_lines
+ end
+ if @line_index > 0
+ preposing = lines[0..(@line_index - 1)].join("\n") + "\n" + preposing
+ end
+ if (lines.size - 1) > @line_index
+ postposing = postposing + "\n" + lines[(@line_index + 1)..-1].join("\n")
+ end
+ end
[preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
end
@@ -975,10 +1330,32 @@ class Reline::LineEditor
def delete_text(start = nil, length = nil)
if start.nil? and length.nil?
- @line&.clear
- @byte_pointer = 0
- @cursor = 0
- @cursor_max = 0
+ if @is_multiline
+ if @buffer_of_lines.size == 1
+ @line&.clear
+ @byte_pointer = 0
+ @cursor = 0
+ @cursor_max = 0
+ elsif @line_index == (@buffer_of_lines.size - 1) and @line_index > 0
+ @buffer_of_lines.pop
+ @line_index -= 1
+ @line = @buffer_of_lines[@line_index]
+ @byte_pointer = 0
+ @cursor = 0
+ @cursor_max = calculate_width(@line)
+ elsif @line_index < (@buffer_of_lines.size - 1)
+ @buffer_of_lines.delete_at(@line_index)
+ @line = @buffer_of_lines[@line_index]
+ @byte_pointer = 0
+ @cursor = 0
+ @cursor_max = calculate_width(@line)
+ end
+ else
+ @line&.clear
+ @byte_pointer = 0
+ @cursor = 0
+ @cursor_max = 0
+ end
elsif not start.nil? and not length.nil?
if @line
before = @line.byteslice(0, start)
@@ -1028,7 +1405,11 @@ class Reline::LineEditor
if @buffer_of_lines.size == 1 and @line.nil?
nil
else
- whole_lines.join("\n")
+ if @previous_line_index
+ whole_lines(index: @previous_line_index, line: @line).join("\n")
+ else
+ whole_lines.join("\n")
+ end
end
end
@@ -1038,6 +1419,7 @@ class Reline::LineEditor
def finish
@finished = true
+ @rerender_all = true
@config.reset
end
@@ -1066,48 +1448,75 @@ class Reline::LineEditor
private def key_newline(key)
if @is_multiline
+ if (@buffer_of_lines.size - 1) == @line_index and @line.bytesize == @byte_pointer
+ @add_newline_to_end_of_buffer = true
+ end
next_line = @line.byteslice(@byte_pointer, @line.bytesize - @byte_pointer)
cursor_line = @line.byteslice(0, @byte_pointer)
insert_new_line(cursor_line, next_line)
@cursor = 0
- @check_new_auto_indent = true
+ @check_new_auto_indent = true unless @in_pasting
end
end
private def ed_unassigned(key) end # do nothing
+ private def process_insert(force: false)
+ return if @continuous_insertion_buffer.empty? or (@in_pasting and not force)
+ width = Reline::Unicode.calculate_width(@continuous_insertion_buffer)
+ bytesize = @continuous_insertion_buffer.bytesize
+ if @cursor == @cursor_max
+ @line += @continuous_insertion_buffer
+ else
+ @line = byteinsert(@line, @byte_pointer, @continuous_insertion_buffer)
+ end
+ @byte_pointer += bytesize
+ @cursor += width
+ @cursor_max += width
+ @continuous_insertion_buffer.clear
+ end
+
private def ed_insert(key)
+ str = nil
+ width = nil
+ bytesize = nil
if key.instance_of?(String)
begin
key.encode(Encoding::UTF_8)
rescue Encoding::UndefinedConversionError
return
end
- width = Reline::Unicode.get_mbchar_width(key)
- if @cursor == @cursor_max
- @line += key
- else
- @line = byteinsert(@line, @byte_pointer, key)
- end
- @byte_pointer += key.bytesize
- @cursor += width
- @cursor_max += width
+ str = key
+ bytesize = key.bytesize
else
begin
key.chr.encode(Encoding::UTF_8)
rescue Encoding::UndefinedConversionError
return
end
- if @cursor == @cursor_max
- @line += key.chr
- else
- @line = byteinsert(@line, @byte_pointer, key.chr)
- end
- width = Reline::Unicode.get_mbchar_width(key.chr)
- @byte_pointer += 1
- @cursor += width
- @cursor_max += width
+ str = key.chr
+ bytesize = 1
+ end
+ if @in_pasting
+ @continuous_insertion_buffer << str
+ return
+ elsif not @continuous_insertion_buffer.empty?
+ process_insert
end
+ width = Reline::Unicode.get_mbchar_width(str)
+ if @cursor == @cursor_max
+ @line += str
+ else
+ @line = byteinsert(@line, @byte_pointer, str)
+ end
+ last_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
+ @byte_pointer += bytesize
+ last_mbchar = @line.byteslice((@byte_pointer - bytesize - last_byte_size), last_byte_size)
+ if last_byte_size != 0 and (last_mbchar + str).grapheme_clusters.size == 1
+ width = 0
+ end
+ @cursor += width
+ @cursor_max += width
end
alias_method :ed_digit, :ed_insert
alias_method :self_insert, :ed_insert
@@ -1164,6 +1573,7 @@ class Reline::LineEditor
arg -= 1
ed_prev_char(key, arg: arg) if arg > 0
end
+ alias_method :backward_char, :ed_prev_char
private def vi_first_print(key)
@byte_pointer, @cursor = Reline::Unicode.vi_first_print(@line)
@@ -1316,9 +1726,11 @@ class Reline::LineEditor
searcher = generate_searcher
searcher.resume(key)
@searching_prompt = "(reverse-i-search)`': "
+ termination_keys = ["\C-j".ord]
+ termination_keys.concat(@config.isearch_terminators&.chars&.map(&:ord)) if @config.isearch_terminators
@waiting_proc = ->(k) {
case k
- when "\C-j".ord
+ when *termination_keys
if @history_pointer
buffer = Reline::HISTORY[@history_pointer]
else
@@ -1337,6 +1749,8 @@ class Reline::LineEditor
@waiting_proc = nil
@cursor_max = calculate_width(@line)
@cursor = @byte_pointer = 0
+ @rerender_all = true
+ @cached_prompt_list = nil
searcher.resume(-1)
when "\C-g".ord
if @is_multiline
@@ -1380,6 +1794,8 @@ class Reline::LineEditor
@waiting_proc = nil
@cursor_max = calculate_width(@line)
@cursor = @byte_pointer = 0
+ @rerender_all = true
+ @cached_prompt_list = nil
searcher.resume(-1)
end
end
@@ -1432,7 +1848,7 @@ class Reline::LineEditor
@buffer_of_lines = Reline::HISTORY[@history_pointer].split("\n")
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
@line_index = line_no
- @line = @buffer_of_lines.last
+ @line = @buffer_of_lines[@line_index]
@rerender_all = true
else
@line = Reline::HISTORY[@history_pointer]
@@ -1480,7 +1896,7 @@ class Reline::LineEditor
@line_index = line_no
end
@buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
- @line = @buffer_of_lines.last
+ @line = @buffer_of_lines[@line_index]
@rerender_all = true
else
if @history_pointer.nil? and substr.empty?
@@ -1593,6 +2009,7 @@ class Reline::LineEditor
end
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)
@@ -1671,6 +2088,7 @@ class Reline::LineEditor
@cursor = 0
end
end
+ alias_method :kill_line, :em_kill_line
private def em_delete(key)
if (not @is_multiline and @line.empty?) or (@is_multiline and @line.empty? and @buffer_of_lines.size == 1)
@@ -1721,6 +2139,7 @@ class Reline::LineEditor
@byte_pointer += yanked.bytesize
end
end
+ alias_method :yank, :em_yank
private def em_yank_pop(key)
yanked, prev_yank = @kill_ring.yank_pop
@@ -1737,6 +2156,7 @@ class Reline::LineEditor
@byte_pointer += yanked.bytesize
end
end
+ alias_method :yank_pop, :em_yank_pop
private def ed_clear_screen(key)
@cleared = true
@@ -1867,9 +2287,10 @@ class Reline::LineEditor
@byte_pointer -= byte_size
@cursor -= width
@cursor_max -= width
- @kill_ring.append(deleted)
+ @kill_ring.append(deleted, true)
end
end
+ alias_method :unix_word_rubout, :em_kill_region
private def copy_for_vi(text)
if @config.editing_mode_is?(:vi_insert) or @config.editing_mode_is?(:vi_command)
@@ -1890,11 +2311,11 @@ class Reline::LineEditor
ed_prev_char(key)
@config.editing_mode = :vi_command
end
- alias_method :backward_char, :ed_prev_char
+ alias_method :vi_movement_mode, :vi_command_mode
private def vi_next_word(key, arg: 1)
if @line.bytesize > @byte_pointer
- byte_size, width = Reline::Unicode.vi_forward_word(@line, @byte_pointer)
+ byte_size, width = Reline::Unicode.vi_forward_word(@line, @byte_pointer, @drop_terminate_spaces)
@byte_pointer += byte_size
@cursor += width
end
@@ -1912,13 +2333,22 @@ class Reline::LineEditor
vi_prev_word(key, arg: arg) if arg > 0
end
- private def vi_end_word(key, arg: 1)
+ private def vi_end_word(key, arg: 1, inclusive: false)
if @line.bytesize > @byte_pointer
byte_size, width = Reline::Unicode.vi_forward_end_word(@line, @byte_pointer)
@byte_pointer += byte_size
@cursor += width
end
arg -= 1
+ if inclusive and arg.zero?
+ byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
+ if byte_size > 0
+ c = @line.byteslice(@byte_pointer, byte_size)
+ width = Reline::Unicode.get_mbchar_width(c)
+ @byte_pointer += byte_size
+ @cursor += width
+ end
+ end
vi_end_word(key, arg: arg) if arg > 0
end
@@ -1942,13 +2372,22 @@ class Reline::LineEditor
vi_prev_big_word(key, arg: arg) if arg > 0
end
- private def vi_end_big_word(key, arg: 1)
+ private def vi_end_big_word(key, arg: 1, inclusive: false)
if @line.bytesize > @byte_pointer
byte_size, width = Reline::Unicode.vi_big_forward_end_word(@line, @byte_pointer)
@byte_pointer += byte_size
@cursor += width
end
arg -= 1
+ if inclusive and arg.zero?
+ byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
+ if byte_size > 0
+ c = @line.byteslice(@byte_pointer, byte_size)
+ width = Reline::Unicode.get_mbchar_width(c)
+ @byte_pointer += byte_size
+ @cursor += width
+ end
+ end
vi_end_big_word(key, arg: arg) if arg > 0
end
@@ -2003,7 +2442,8 @@ class Reline::LineEditor
@cursor = 0
end
- private def vi_change_meta(key)
+ private def vi_change_meta(key, arg: 1)
+ @drop_terminate_spaces = true
@waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff|
if byte_pointer_diff > 0
@line, cut = byteslice!(@line, @byte_pointer, byte_pointer_diff)
@@ -2015,10 +2455,12 @@ class Reline::LineEditor
@cursor_max -= cursor_diff.abs
@byte_pointer += byte_pointer_diff if byte_pointer_diff < 0
@config.editing_mode = :vi_insert
+ @drop_terminate_spaces = false
}
+ @waiting_operator_vi_arg = arg
end
- private def vi_delete_meta(key)
+ private def vi_delete_meta(key, arg: 1)
@waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff|
if byte_pointer_diff > 0
@line, cut = byteslice!(@line, @byte_pointer, byte_pointer_diff)
@@ -2030,9 +2472,19 @@ class Reline::LineEditor
@cursor_max -= cursor_diff.abs
@byte_pointer += byte_pointer_diff if byte_pointer_diff < 0
}
+ @waiting_operator_vi_arg = arg
end
- private def vi_yank(key)
+ private def vi_yank(key, arg: 1)
+ @waiting_operator_proc = proc { |cursor_diff, byte_pointer_diff|
+ if byte_pointer_diff > 0
+ cut = @line.byteslice(@byte_pointer, byte_pointer_diff)
+ elsif byte_pointer_diff < 0
+ cut = @line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff)
+ end
+ copy_for_vi(cut)
+ }
+ @waiting_operator_vi_arg = arg
end
private def vi_list_or_eof(key)
@@ -2059,6 +2511,9 @@ class Reline::LineEditor
width = Reline::Unicode.get_mbchar_width(mbchar)
@cursor_max -= width
if @cursor > 0 and @cursor >= @cursor_max
+ byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @byte_pointer)
+ mbchar = @line.byteslice(@byte_pointer - byte_size, byte_size)
+ width = Reline::Unicode.get_mbchar_width(mbchar)
@byte_pointer -= byte_size
@cursor -= width
end
@@ -2092,11 +2547,23 @@ class Reline::LineEditor
private def vi_histedit(key)
path = Tempfile.open { |fp|
- fp.write @line
+ if @is_multiline
+ fp.write whole_lines.join("\n")
+ else
+ fp.write @line
+ end
fp.path
}
system("#{ENV['EDITOR']} #{path}")
- @line = File.read(path)
+ if @is_multiline
+ @buffer_of_lines = File.read(path).split("\n")
+ @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
+ @line_index = 0
+ @line = @buffer_of_lines[@line_index]
+ @rerender_all = true
+ else
+ @line = File.read(path)
+ end
finish
end
@@ -2155,7 +2622,7 @@ class Reline::LineEditor
byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
before = @line.byteslice(0, @byte_pointer)
remaining_point = @byte_pointer + byte_size
- after = @line.byteslice(remaining_point, @line.size - remaining_point)
+ after = @line.byteslice(remaining_point, @line.bytesize - remaining_point)
@line = before + k.chr + after
@cursor_max = calculate_width(@line)
@waiting_proc = nil
@@ -2166,7 +2633,7 @@ class Reline::LineEditor
end
before = @line.byteslice(0, @byte_pointer)
remaining_point = @byte_pointer + byte_size
- after = @line.byteslice(remaining_point, @line.size - remaining_point)
+ after = @line.byteslice(remaining_point, @line.bytesize - remaining_point)
replaced = k.chr * arg
@line = before + replaced + after
@byte_pointer += replaced.bytesize
@@ -2177,15 +2644,15 @@ class Reline::LineEditor
}
end
- private def vi_next_char(key, arg: 1)
- @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg) }
+ private def vi_next_char(key, arg: 1, inclusive: false)
+ @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, inclusive: inclusive) }
end
- private def vi_to_next_char(key, arg: 1)
- @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, true) }
+ private def vi_to_next_char(key, arg: 1, inclusive: false)
+ @waiting_proc = ->(key_for_proc) { search_next_char(key_for_proc, arg, need_prev_char: true, inclusive: inclusive) }
end
- private def search_next_char(key, arg, need_prev_char = false)
+ private def search_next_char(key, arg, need_prev_char: false, inclusive: false)
if key.instance_of?(String)
inputed_char = key
else
@@ -2222,6 +2689,15 @@ class Reline::LineEditor
@byte_pointer += byte_size
@cursor += width
end
+ if inclusive
+ byte_size = Reline::Unicode.get_next_mbchar_size(@line, @byte_pointer)
+ if byte_size > 0
+ c = @line.byteslice(@byte_pointer, byte_size)
+ width = Reline::Unicode.get_mbchar_width(c)
+ @byte_pointer += byte_size
+ @cursor += width
+ end
+ end
@waiting_proc = nil
end
@@ -2293,6 +2769,7 @@ class Reline::LineEditor
alias_method :set_mark, :em_set_mark
private def em_exchange_mark(key)
+ return unless @mark_pointer
new_pointer = [@byte_pointer, @line_index]
@previous_line_index = @line_index
@byte_pointer, @line_index = @mark_pointer
diff --git a/lib/reline/reline.gemspec b/lib/reline/reline.gemspec
index 1962f61def..763c0f8bc3 100644
--- a/lib/reline/reline.gemspec
+++ b/lib/reline/reline.gemspec
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
spec.homepage = 'https://github.com/ruby/reline'
spec.license = 'Ruby'
- spec.files = Dir['BSDL', 'COPYING', 'README.md', 'lib/**/*']
+ spec.files = Dir['BSDL', 'COPYING', 'README.md', 'license_of_rb-readline', 'lib/**/*']
spec.require_paths = ['lib']
spec.required_ruby_version = Gem::Requirement.new('>= 2.5')
@@ -23,4 +23,5 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'bundler'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'test-unit'
+ spec.add_development_dependency 'yamatanooroti', '>= 0.0.6'
end
diff --git a/lib/reline/unicode.rb b/lib/reline/unicode.rb
index cd8c27e85b..7dbe8a12a5 100644
--- a/lib/reline/unicode.rb
+++ b/lib/reline/unicode.rb
@@ -35,11 +35,16 @@ class Reline::Unicode
}
EscapedChars = EscapedPairs.keys.map(&:chr)
- CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
- OSC_REGEXP = /\e\]\d+(?:;[^;]+)*\a/
NON_PRINTING_START = "\1"
NON_PRINTING_END = "\2"
- WIDTH_SCANNER = /\G(?:#{NON_PRINTING_START}|#{NON_PRINTING_END}|#{CSI_REGEXP}|#{OSC_REGEXP}|\X)/
+ CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
+ OSC_REGEXP = /\e\]\d+(?:;[^;]+)*\a/
+ WIDTH_SCANNER = /\G(?:(#{NON_PRINTING_START})|(#{NON_PRINTING_END})|(#{CSI_REGEXP})|(#{OSC_REGEXP})|(\X))/o
+ NON_PRINTING_START_INDEX = 0
+ NON_PRINTING_END_INDEX = 1
+ CSI_REGEXP_INDEX = 2
+ OSC_REGEXP_INDEX = 3
+ GRAPHEME_CLUSTER_INDEX = 4
def self.get_mbchar_byte_size_by_first_char(c)
# Checks UTF-8 character byte size
@@ -72,20 +77,43 @@ class Reline::Unicode
}.join
end
+ require 'reline/unicode/east_asian_width'
+
+ 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 }
+ )
+ | (?<ambiguous_width>
+ #{EastAsianWidth::TYPE_A}
+ )
+ /x
+
def self.get_mbchar_width(mbchar)
- case mbchar.encode(Encoding::UTF_8)
- when *EscapedChars # ^ + char, such as ^M, ^H, ^[, ...
- 2
- when /^\u{2E3B}/ # THREE-EM DASH
- 3
- when /^\p{M}/
- 0
- when EastAsianWidth::TYPE_A
- Reline.ambiguous_width
- when EastAsianWidth::TYPE_F, EastAsianWidth::TYPE_W
- 2
- when EastAsianWidth::TYPE_H, EastAsianWidth::TYPE_NA, EastAsianWidth::TYPE_N
- 1
+ ord = mbchar.ord
+ if (0x00 <= ord and ord <= 0x1F)
+ return 2
+ elsif (0x20 <= ord and ord <= 0x7E)
+ 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] 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
@@ -97,13 +125,14 @@ class Reline::Unicode
rest = str.encode(Encoding::UTF_8)
in_zero_width = false
rest.scan(WIDTH_SCANNER) do |gc|
- case gc
- when NON_PRINTING_START
+ case
+ when gc[NON_PRINTING_START_INDEX]
in_zero_width = true
- when NON_PRINTING_END
+ when gc[NON_PRINTING_END_INDEX]
in_zero_width = false
- when CSI_REGEXP, OSC_REGEXP
- else
+ when gc[CSI_REGEXP_INDEX], gc[OSC_REGEXP_INDEX]
+ when gc[GRAPHEME_CLUSTER_INDEX]
+ gc = gc[GRAPHEME_CLUSTER_INDEX]
unless in_zero_width
width += get_mbchar_width(gc)
end
@@ -124,14 +153,17 @@ class Reline::Unicode
rest = str.encode(Encoding::UTF_8)
in_zero_width = false
rest.scan(WIDTH_SCANNER) do |gc|
- case gc
- when NON_PRINTING_START
+ case
+ when gc[NON_PRINTING_START_INDEX]
in_zero_width = true
- when NON_PRINTING_END
+ when gc[NON_PRINTING_END_INDEX]
in_zero_width = false
- when CSI_REGEXP, OSC_REGEXP
- lines.last << gc
- else
+ when gc[CSI_REGEXP_INDEX]
+ lines.last << gc[CSI_REGEXP_INDEX]
+ when gc[OSC_REGEXP_INDEX]
+ lines.last << gc[OSC_REGEXP_INDEX]
+ when gc[GRAPHEME_CLUSTER_INDEX]
+ gc = gc[GRAPHEME_CLUSTER_INDEX]
unless in_zero_width
mbchar_width = get_mbchar_width(gc)
if (width += mbchar_width) > max_width
@@ -427,8 +459,8 @@ class Reline::Unicode
[byte_size, width]
end
- def self.vi_forward_word(line, byte_pointer)
- if (line.bytesize - 1) > byte_pointer
+ def self.vi_forward_word(line, byte_pointer, drop_terminate_spaces = false)
+ if line.bytesize > byte_pointer
size = get_next_mbchar_size(line, byte_pointer)
mbchar = line.byteslice(byte_pointer, size)
if mbchar =~ /\w/
@@ -443,7 +475,7 @@ class Reline::Unicode
else
return [0, 0]
end
- while (line.bytesize - 1) > (byte_pointer + byte_size)
+ while line.bytesize > (byte_pointer + byte_size)
size = get_next_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size, size)
case started_by
@@ -457,7 +489,8 @@ class Reline::Unicode
width += get_mbchar_width(mbchar)
byte_size += size
end
- while (line.bytesize - 1) > (byte_pointer + byte_size)
+ return [byte_size, width] if drop_terminate_spaces
+ while line.bytesize > (byte_pointer + byte_size)
size = get_next_mbchar_size(line, byte_pointer + byte_size)
mbchar = line.byteslice(byte_pointer + byte_size, size)
break if mbchar =~ /\S/
@@ -591,5 +624,3 @@ class Reline::Unicode
[byte_size, width]
end
end
-
-require 'reline/unicode/east_asian_width'
diff --git a/lib/reline/unicode/east_asian_width.rb b/lib/reline/unicode/east_asian_width.rb
index b2749ab754..89bc9d9435 100644
--- a/lib/reline/unicode/east_asian_width.rb
+++ b/lib/reline/unicode/east_asian_width.rb
@@ -1,1145 +1,1164 @@
class Reline::Unicode::EastAsianWidth
# This is based on EastAsianWidth.txt
- # http://www.unicode.org/Public/12.1.0/ucd/EastAsianWidth.txt
+ # EastAsianWidth.txt
# Fullwidth
- TYPE_F = /^(
- \u{3000} |
- [\u{FF01}-\u{FF60}] |
- [\u{FFE0}-\u{FFE6}]
- )/x
+ TYPE_F = /^[#{ %W(
+ \u{3000}
+ \u{FF01}-\u{FF60}
+ \u{FFE0}-\u{FFE6}
+ ).join }]/
# Halfwidth
- TYPE_H = /^(
- \u{20A9} |
- [\u{FF61}-\u{FFBE}] |
- [\u{FFC2}-\u{FFC7}] |
- [\u{FFCA}-\u{FFCF}] |
- [\u{FFD2}-\u{FFD7}] |
- [\u{FFDA}-\u{FFDC}] |
- [\u{FFE8}-\u{FFEE}]
- )/x
+ TYPE_H = /^[#{ %W(
+ \u{20A9}
+ \u{FF61}-\u{FFBE}
+ \u{FFC2}-\u{FFC7}
+ \u{FFCA}-\u{FFCF}
+ \u{FFD2}-\u{FFD7}
+ \u{FFDA}-\u{FFDC}
+ \u{FFE8}-\u{FFEE}
+ ).join }]/
# Wide
- TYPE_W = /^(
- [\u{1100}-\u{115F}] |
- [\u{231A}-\u{231B}] |
- [\u{2329}-\u{232A}] |
- [\u{23E9}-\u{23EC}] |
- \u{23F0} |
- \u{23F3} |
- [\u{25FD}-\u{25FE}] |
- [\u{2614}-\u{2615}] |
- [\u{2648}-\u{2653}] |
- \u{267F} |
- \u{2693} |
- \u{26A1} |
- [\u{26AA}-\u{26AB}] |
- [\u{26BD}-\u{26BE}] |
- [\u{26C4}-\u{26C5}] |
- \u{26CE} |
- \u{26D4} |
- \u{26EA} |
- [\u{26F2}-\u{26F3}] |
- \u{26F5} |
- \u{26FA} |
- \u{26FD} |
- \u{2705} |
- [\u{270A}-\u{270B}] |
- \u{2728} |
- \u{274C} |
- \u{274E} |
- [\u{2753}-\u{2755}] |
- \u{2757} |
- [\u{2795}-\u{2797}] |
- \u{27B0} |
- \u{27BF} |
- [\u{2B1B}-\u{2B1C}] |
- \u{2B50} |
- \u{2B55} |
- [\u{2E80}-\u{2E99}] |
- [\u{2E9B}-\u{2EF3}] |
- [\u{2F00}-\u{2FD5}] |
- [\u{2FF0}-\u{2FFB}] |
- [\u{3001}-\u{303E}] |
- [\u{3041}-\u{3096}] |
- [\u{3099}-\u{30FF}] |
- [\u{3105}-\u{312F}] |
- [\u{3131}-\u{318E}] |
- [\u{3190}-\u{31BA}] |
- [\u{31C0}-\u{31E3}] |
- [\u{31F0}-\u{321E}] |
- [\u{3220}-\u{3247}] |
- [\u{3250}-\u{4DBF}] |
- [\u{4E00}-\u{A48C}] |
- [\u{A490}-\u{A4C6}] |
- [\u{A960}-\u{A97C}] |
- [\u{AC00}-\u{D7A3}] |
- [\u{F900}-\u{FAFF}] |
- [\u{FE10}-\u{FE19}] |
- [\u{FE30}-\u{FE52}] |
- [\u{FE54}-\u{FE66}] |
- [\u{FE68}-\u{FE6B}] |
- [\u{16FE0}-\u{16FE3}] |
- [\u{17000}-\u{187F7}] |
- [\u{18800}-\u{18AF2}] |
- [\u{1B000}-\u{1B11E}] |
- [\u{1B150}-\u{1B152}] |
- [\u{1B164}-\u{1B167}] |
- [\u{1B170}-\u{1B2FB}] |
- \u{1F004} |
- \u{1F0CF} |
- \u{1F18E} |
- [\u{1F191}-\u{1F19A}] |
- [\u{1F200}-\u{1F202}] |
- [\u{1F210}-\u{1F23B}] |
- [\u{1F240}-\u{1F248}] |
- [\u{1F250}-\u{1F251}] |
- [\u{1F260}-\u{1F265}] |
- [\u{1F300}-\u{1F320}] |
- [\u{1F32D}-\u{1F335}] |
- [\u{1F337}-\u{1F37C}] |
- [\u{1F37E}-\u{1F393}] |
- [\u{1F3A0}-\u{1F3CA}] |
- [\u{1F3CF}-\u{1F3D3}] |
- [\u{1F3E0}-\u{1F3F0}] |
- \u{1F3F4} |
- [\u{1F3F8}-\u{1F43E}] |
- \u{1F440} |
- [\u{1F442}-\u{1F4FC}] |
- [\u{1F4FF}-\u{1F53D}] |
- [\u{1F54B}-\u{1F54E}] |
- [\u{1F550}-\u{1F567}] |
- \u{1F57A} |
- [\u{1F595}-\u{1F596}] |
- \u{1F5A4} |
- [\u{1F5FB}-\u{1F64F}] |
- [\u{1F680}-\u{1F6C5}] |
- \u{1F6CC} |
- [\u{1F6D0}-\u{1F6D2}] |
- \u{1F6D5} |
- [\u{1F6EB}-\u{1F6EC}] |
- [\u{1F6F4}-\u{1F6FA}] |
- [\u{1F7E0}-\u{1F7EB}] |
- [\u{1F90D}-\u{1F971}] |
- [\u{1F973}-\u{1F976}] |
- [\u{1F97A}-\u{1F9A2}] |
- [\u{1F9A5}-\u{1F9AA}] |
- [\u{1F9AE}-\u{1F9CA}] |
- [\u{1F9CD}-\u{1F9FF}] |
- [\u{1FA70}-\u{1FA73}] |
- [\u{1FA78}-\u{1FA7A}] |
- [\u{1FA80}-\u{1FA82}] |
- [\u{1FA90}-\u{1FA95}] |
- [\u{20000}-\u{2FFFD}] |
- [\u{30000}-\u{3FFFD}]
- )/x
+ TYPE_W = /^[#{ %W(
+ \u{1100}-\u{115F}
+ \u{231A}-\u{231B}
+ \u{2329}-\u{232A}
+ \u{23E9}-\u{23EC}
+ \u{23F0}
+ \u{23F3}
+ \u{25FD}-\u{25FE}
+ \u{2614}-\u{2615}
+ \u{2648}-\u{2653}
+ \u{267F}
+ \u{2693}
+ \u{26A1}
+ \u{26AA}-\u{26AB}
+ \u{26BD}-\u{26BE}
+ \u{26C4}-\u{26C5}
+ \u{26CE}
+ \u{26D4}
+ \u{26EA}
+ \u{26F2}-\u{26F3}
+ \u{26F5}
+ \u{26FA}
+ \u{26FD}
+ \u{2705}
+ \u{270A}-\u{270B}
+ \u{2728}
+ \u{274C}
+ \u{274E}
+ \u{2753}-\u{2755}
+ \u{2757}
+ \u{2795}-\u{2797}
+ \u{27B0}
+ \u{27BF}
+ \u{2B1B}-\u{2B1C}
+ \u{2B50}
+ \u{2B55}
+ \u{2E80}-\u{2E99}
+ \u{2E9B}-\u{2EF3}
+ \u{2F00}-\u{2FD5}
+ \u{2FF0}-\u{2FFB}
+ \u{3001}-\u{303E}
+ \u{3041}-\u{3096}
+ \u{3099}-\u{30FF}
+ \u{3105}-\u{312F}
+ \u{3131}-\u{318E}
+ \u{3190}-\u{31E3}
+ \u{31F0}-\u{321E}
+ \u{3220}-\u{3247}
+ \u{3250}-\u{4DBF}
+ \u{4E00}-\u{A48C}
+ \u{A490}-\u{A4C6}
+ \u{A960}-\u{A97C}
+ \u{AC00}-\u{D7A3}
+ \u{F900}-\u{FAFF}
+ \u{FE10}-\u{FE19}
+ \u{FE30}-\u{FE52}
+ \u{FE54}-\u{FE66}
+ \u{FE68}-\u{FE6B}
+ \u{16FE0}-\u{16FE4}
+ \u{16FF0}-\u{16FF1}
+ \u{17000}-\u{187F7}
+ \u{18800}-\u{18CD5}
+ \u{18D00}-\u{18D08}
+ \u{1B000}-\u{1B11E}
+ \u{1B150}-\u{1B152}
+ \u{1B164}-\u{1B167}
+ \u{1B170}-\u{1B2FB}
+ \u{1F004}
+ \u{1F0CF}
+ \u{1F18E}
+ \u{1F191}-\u{1F19A}
+ \u{1F200}-\u{1F202}
+ \u{1F210}-\u{1F23B}
+ \u{1F240}-\u{1F248}
+ \u{1F250}-\u{1F251}
+ \u{1F260}-\u{1F265}
+ \u{1F300}-\u{1F320}
+ \u{1F32D}-\u{1F335}
+ \u{1F337}-\u{1F37C}
+ \u{1F37E}-\u{1F393}
+ \u{1F3A0}-\u{1F3CA}
+ \u{1F3CF}-\u{1F3D3}
+ \u{1F3E0}-\u{1F3F0}
+ \u{1F3F4}
+ \u{1F3F8}-\u{1F43E}
+ \u{1F440}
+ \u{1F442}-\u{1F4FC}
+ \u{1F4FF}-\u{1F53D}
+ \u{1F54B}-\u{1F54E}
+ \u{1F550}-\u{1F567}
+ \u{1F57A}
+ \u{1F595}-\u{1F596}
+ \u{1F5A4}
+ \u{1F5FB}-\u{1F64F}
+ \u{1F680}-\u{1F6C5}
+ \u{1F6CC}
+ \u{1F6D0}-\u{1F6D2}
+ \u{1F6D5}-\u{1F6D7}
+ \u{1F6EB}-\u{1F6EC}
+ \u{1F6F4}-\u{1F6FC}
+ \u{1F7E0}-\u{1F7EB}
+ \u{1F90C}-\u{1F93A}
+ \u{1F93C}-\u{1F945}
+ \u{1F947}-\u{1F978}
+ \u{1F97A}-\u{1F9CB}
+ \u{1F9CD}-\u{1F9FF}
+ \u{1FA70}-\u{1FA74}
+ \u{1FA78}-\u{1FA7A}
+ \u{1FA80}-\u{1FA86}
+ \u{1FA90}-\u{1FAA8}
+ \u{1FAB0}-\u{1FAB6}
+ \u{1FAC0}-\u{1FAC2}
+ \u{1FAD0}-\u{1FAD6}
+ \u{20000}-\u{2FFFD}
+ \u{30000}-\u{3FFFD}
+ ).join }]/
# Narrow
- TYPE_NA = /^(
- [\u{0020}-\u{007E}] |
- [\u{00A2}-\u{00A3}] |
- [\u{00A5}-\u{00A6}] |
- \u{00AC} |
- \u{00AF} |
- [\u{27E6}-\u{27ED}] |
- [\u{2985}-\u{2986}]
- )/x
+ TYPE_NA = /^[#{ %W(
+ \u{0020}-\u{007E}
+ \u{00A2}-\u{00A3}
+ \u{00A5}-\u{00A6}
+ \u{00AC}
+ \u{00AF}
+ \u{27E6}-\u{27ED}
+ \u{2985}-\u{2986}
+ ).join }]/
# Ambiguous
- TYPE_A = /^(
- \u{00A1} |
- \u{00A4} |
- [\u{00A7}-\u{00A8}] |
- \u{00AA} |
- [\u{00AD}-\u{00AE}] |
- [\u{00B0}-\u{00B4}] |
- [\u{00B6}-\u{00BA}] |
- [\u{00BC}-\u{00BF}] |
- \u{00C6} |
- \u{00D0} |
- [\u{00D7}-\u{00D8}] |
- [\u{00DE}-\u{00E1}] |
- \u{00E6} |
- [\u{00E8}-\u{00EA}] |
- [\u{00EC}-\u{00ED}] |
- \u{00F0} |
- [\u{00F2}-\u{00F3}] |
- [\u{00F7}-\u{00FA}] |
- \u{00FC} |
- \u{00FE} |
- \u{0101} |
- \u{0111} |
- \u{0113} |
- \u{011B} |
- [\u{0126}-\u{0127}] |
- \u{012B} |
- [\u{0131}-\u{0133}] |
- \u{0138} |
- [\u{013F}-\u{0142}] |
- \u{0144} |
- [\u{0148}-\u{014B}] |
- \u{014D} |
- [\u{0152}-\u{0153}] |
- [\u{0166}-\u{0167}] |
- \u{016B} |
- \u{01CE} |
- \u{01D0} |
- \u{01D2} |
- \u{01D4} |
- \u{01D6} |
- \u{01D8} |
- \u{01DA} |
- \u{01DC} |
- \u{0251} |
- \u{0261} |
- \u{02C4} |
- \u{02C7} |
- [\u{02C9}-\u{02CB}] |
- \u{02CD} |
- \u{02D0} |
- [\u{02D8}-\u{02DB}] |
- \u{02DD} |
- \u{02DF} |
- [\u{0300}-\u{036F}] |
- [\u{0391}-\u{03A1}] |
- [\u{03A3}-\u{03A9}] |
- [\u{03B1}-\u{03C1}] |
- [\u{03C3}-\u{03C9}] |
- \u{0401} |
- [\u{0410}-\u{044F}] |
- \u{0451} |
- \u{2010} |
- [\u{2013}-\u{2016}] |
- [\u{2018}-\u{2019}] |
- [\u{201C}-\u{201D}] |
- [\u{2020}-\u{2022}] |
- [\u{2024}-\u{2027}] |
- \u{2030} |
- [\u{2032}-\u{2033}] |
- \u{2035} |
- \u{203B} |
- \u{203E} |
- \u{2074} |
- \u{207F} |
- [\u{2081}-\u{2084}] |
- \u{20AC} |
- \u{2103} |
- \u{2105} |
- \u{2109} |
- \u{2113} |
- \u{2116} |
- [\u{2121}-\u{2122}] |
- \u{2126} |
- \u{212B} |
- [\u{2153}-\u{2154}] |
- [\u{215B}-\u{215E}] |
- [\u{2160}-\u{216B}] |
- [\u{2170}-\u{2179}] |
- \u{2189} |
- [\u{2190}-\u{2199}] |
- [\u{21B8}-\u{21B9}] |
- \u{21D2} |
- \u{21D4} |
- \u{21E7} |
- \u{2200} |
- [\u{2202}-\u{2203}] |
- [\u{2207}-\u{2208}] |
- \u{220B} |
- \u{220F} |
- \u{2211} |
- \u{2215} |
- \u{221A} |
- [\u{221D}-\u{2220}] |
- \u{2223} |
- \u{2225} |
- [\u{2227}-\u{222C}] |
- \u{222E} |
- [\u{2234}-\u{2237}] |
- [\u{223C}-\u{223D}] |
- \u{2248} |
- \u{224C} |
- \u{2252} |
- [\u{2260}-\u{2261}] |
- [\u{2264}-\u{2267}] |
- [\u{226A}-\u{226B}] |
- [\u{226E}-\u{226F}] |
- [\u{2282}-\u{2283}] |
- [\u{2286}-\u{2287}] |
- \u{2295} |
- \u{2299} |
- \u{22A5} |
- \u{22BF} |
- \u{2312} |
- [\u{2460}-\u{24E9}] |
- [\u{24EB}-\u{254B}] |
- [\u{2550}-\u{2573}] |
- [\u{2580}-\u{258F}] |
- [\u{2592}-\u{2595}] |
- [\u{25A0}-\u{25A1}] |
- [\u{25A3}-\u{25A9}] |
- [\u{25B2}-\u{25B3}] |
- [\u{25B6}-\u{25B7}] |
- [\u{25BC}-\u{25BD}] |
- [\u{25C0}-\u{25C1}] |
- [\u{25C6}-\u{25C8}] |
- \u{25CB} |
- [\u{25CE}-\u{25D1}] |
- [\u{25E2}-\u{25E5}] |
- \u{25EF} |
- [\u{2605}-\u{2606}] |
- \u{2609} |
- [\u{260E}-\u{260F}] |
- \u{261C} |
- \u{261E} |
- \u{2640} |
- \u{2642} |
- [\u{2660}-\u{2661}] |
- [\u{2663}-\u{2665}] |
- [\u{2667}-\u{266A}] |
- [\u{266C}-\u{266D}] |
- \u{266F} |
- [\u{269E}-\u{269F}] |
- \u{26BF} |
- [\u{26C6}-\u{26CD}] |
- [\u{26CF}-\u{26D3}] |
- [\u{26D5}-\u{26E1}] |
- \u{26E3} |
- [\u{26E8}-\u{26E9}] |
- [\u{26EB}-\u{26F1}] |
- \u{26F4} |
- [\u{26F6}-\u{26F9}] |
- [\u{26FB}-\u{26FC}] |
- [\u{26FE}-\u{26FF}] |
- \u{273D} |
- [\u{2776}-\u{277F}] |
- [\u{2B56}-\u{2B59}] |
- [\u{3248}-\u{324F}] |
- [\u{E000}-\u{F8FF}] |
- [\u{FE00}-\u{FE0F}] |
- \u{FFFD} |
- [\u{1F100}-\u{1F10A}] |
- [\u{1F110}-\u{1F12D}] |
- [\u{1F130}-\u{1F169}] |
- [\u{1F170}-\u{1F18D}] |
- [\u{1F18F}-\u{1F190}] |
- [\u{1F19B}-\u{1F1AC}] |
- [\u{E0100}-\u{E01EF}] |
- [\u{F0000}-\u{FFFFD}] |
- [\u{100000}-\u{10FFFD}]
- )/x
+ TYPE_A = /^[#{ %W(
+ \u{00A1}
+ \u{00A4}
+ \u{00A7}-\u{00A8}
+ \u{00AA}
+ \u{00AD}-\u{00AE}
+ \u{00B0}-\u{00B4}
+ \u{00B6}-\u{00BA}
+ \u{00BC}-\u{00BF}
+ \u{00C6}
+ \u{00D0}
+ \u{00D7}-\u{00D8}
+ \u{00DE}-\u{00E1}
+ \u{00E6}
+ \u{00E8}-\u{00EA}
+ \u{00EC}-\u{00ED}
+ \u{00F0}
+ \u{00F2}-\u{00F3}
+ \u{00F7}-\u{00FA}
+ \u{00FC}
+ \u{00FE}
+ \u{0101}
+ \u{0111}
+ \u{0113}
+ \u{011B}
+ \u{0126}-\u{0127}
+ \u{012B}
+ \u{0131}-\u{0133}
+ \u{0138}
+ \u{013F}-\u{0142}
+ \u{0144}
+ \u{0148}-\u{014B}
+ \u{014D}
+ \u{0152}-\u{0153}
+ \u{0166}-\u{0167}
+ \u{016B}
+ \u{01CE}
+ \u{01D0}
+ \u{01D2}
+ \u{01D4}
+ \u{01D6}
+ \u{01D8}
+ \u{01DA}
+ \u{01DC}
+ \u{0251}
+ \u{0261}
+ \u{02C4}
+ \u{02C7}
+ \u{02C9}-\u{02CB}
+ \u{02CD}
+ \u{02D0}
+ \u{02D8}-\u{02DB}
+ \u{02DD}
+ \u{02DF}
+ \u{0300}-\u{036F}
+ \u{0391}-\u{03A1}
+ \u{03A3}-\u{03A9}
+ \u{03B1}-\u{03C1}
+ \u{03C3}-\u{03C9}
+ \u{0401}
+ \u{0410}-\u{044F}
+ \u{0451}
+ \u{2010}
+ \u{2013}-\u{2016}
+ \u{2018}-\u{2019}
+ \u{201C}-\u{201D}
+ \u{2020}-\u{2022}
+ \u{2024}-\u{2027}
+ \u{2030}
+ \u{2032}-\u{2033}
+ \u{2035}
+ \u{203B}
+ \u{203E}
+ \u{2074}
+ \u{207F}
+ \u{2081}-\u{2084}
+ \u{20AC}
+ \u{2103}
+ \u{2105}
+ \u{2109}
+ \u{2113}
+ \u{2116}
+ \u{2121}-\u{2122}
+ \u{2126}
+ \u{212B}
+ \u{2153}-\u{2154}
+ \u{215B}-\u{215E}
+ \u{2160}-\u{216B}
+ \u{2170}-\u{2179}
+ \u{2189}
+ \u{2190}-\u{2199}
+ \u{21B8}-\u{21B9}
+ \u{21D2}
+ \u{21D4}
+ \u{21E7}
+ \u{2200}
+ \u{2202}-\u{2203}
+ \u{2207}-\u{2208}
+ \u{220B}
+ \u{220F}
+ \u{2211}
+ \u{2215}
+ \u{221A}
+ \u{221D}-\u{2220}
+ \u{2223}
+ \u{2225}
+ \u{2227}-\u{222C}
+ \u{222E}
+ \u{2234}-\u{2237}
+ \u{223C}-\u{223D}
+ \u{2248}
+ \u{224C}
+ \u{2252}
+ \u{2260}-\u{2261}
+ \u{2264}-\u{2267}
+ \u{226A}-\u{226B}
+ \u{226E}-\u{226F}
+ \u{2282}-\u{2283}
+ \u{2286}-\u{2287}
+ \u{2295}
+ \u{2299}
+ \u{22A5}
+ \u{22BF}
+ \u{2312}
+ \u{2460}-\u{24E9}
+ \u{24EB}-\u{254B}
+ \u{2550}-\u{2573}
+ \u{2580}-\u{258F}
+ \u{2592}-\u{2595}
+ \u{25A0}-\u{25A1}
+ \u{25A3}-\u{25A9}
+ \u{25B2}-\u{25B3}
+ \u{25B6}-\u{25B7}
+ \u{25BC}-\u{25BD}
+ \u{25C0}-\u{25C1}
+ \u{25C6}-\u{25C8}
+ \u{25CB}
+ \u{25CE}-\u{25D1}
+ \u{25E2}-\u{25E5}
+ \u{25EF}
+ \u{2605}-\u{2606}
+ \u{2609}
+ \u{260E}-\u{260F}
+ \u{261C}
+ \u{261E}
+ \u{2640}
+ \u{2642}
+ \u{2660}-\u{2661}
+ \u{2663}-\u{2665}
+ \u{2667}-\u{266A}
+ \u{266C}-\u{266D}
+ \u{266F}
+ \u{269E}-\u{269F}
+ \u{26BF}
+ \u{26C6}-\u{26CD}
+ \u{26CF}-\u{26D3}
+ \u{26D5}-\u{26E1}
+ \u{26E3}
+ \u{26E8}-\u{26E9}
+ \u{26EB}-\u{26F1}
+ \u{26F4}
+ \u{26F6}-\u{26F9}
+ \u{26FB}-\u{26FC}
+ \u{26FE}-\u{26FF}
+ \u{273D}
+ \u{2776}-\u{277F}
+ \u{2B56}-\u{2B59}
+ \u{3248}-\u{324F}
+ \u{E000}-\u{F8FF}
+ \u{FE00}-\u{FE0F}
+ \u{FFFD}
+ \u{1F100}-\u{1F10A}
+ \u{1F110}-\u{1F12D}
+ \u{1F130}-\u{1F169}
+ \u{1F170}-\u{1F18D}
+ \u{1F18F}-\u{1F190}
+ \u{1F19B}-\u{1F1AC}
+ \u{E0100}-\u{E01EF}
+ \u{F0000}-\u{FFFFD}
+ \u{100000}-\u{10FFFD}
+ ).join }]/
# Neutral
- TYPE_N = /^(
- [\u{0000}-\u{001F}] |
- [\u{007F}-\u{00A0}] |
- \u{00A9} |
- \u{00AB} |
- \u{00B5} |
- \u{00BB} |
- [\u{00C0}-\u{00C5}] |
- [\u{00C7}-\u{00CF}] |
- [\u{00D1}-\u{00D6}] |
- [\u{00D9}-\u{00DD}] |
- [\u{00E2}-\u{00E5}] |
- \u{00E7} |
- \u{00EB} |
- [\u{00EE}-\u{00EF}] |
- \u{00F1} |
- [\u{00F4}-\u{00F6}] |
- \u{00FB} |
- \u{00FD} |
- [\u{00FF}-\u{0100}] |
- [\u{0102}-\u{0110}] |
- \u{0112} |
- [\u{0114}-\u{011A}] |
- [\u{011C}-\u{0125}] |
- [\u{0128}-\u{012A}] |
- [\u{012C}-\u{0130}] |
- [\u{0134}-\u{0137}] |
- [\u{0139}-\u{013E}] |
- \u{0143} |
- [\u{0145}-\u{0147}] |
- \u{014C} |
- [\u{014E}-\u{0151}] |
- [\u{0154}-\u{0165}] |
- [\u{0168}-\u{016A}] |
- [\u{016C}-\u{01CD}] |
- \u{01CF} |
- \u{01D1} |
- \u{01D3} |
- \u{01D5} |
- \u{01D7} |
- \u{01D9} |
- \u{01DB} |
- [\u{01DD}-\u{0250}] |
- [\u{0252}-\u{0260}] |
- [\u{0262}-\u{02C3}] |
- [\u{02C5}-\u{02C6}] |
- \u{02C8} |
- \u{02CC} |
- [\u{02CE}-\u{02CF}] |
- [\u{02D1}-\u{02D7}] |
- \u{02DC} |
- \u{02DE} |
- [\u{02E0}-\u{02FF}] |
- [\u{0370}-\u{0377}] |
- [\u{037A}-\u{037F}] |
- [\u{0384}-\u{038A}] |
- \u{038C} |
- [\u{038E}-\u{0390}] |
- [\u{03AA}-\u{03B0}] |
- \u{03C2} |
- [\u{03CA}-\u{0400}] |
- [\u{0402}-\u{040F}] |
- \u{0450} |
- [\u{0452}-\u{052F}] |
- [\u{0531}-\u{0556}] |
- [\u{0559}-\u{058A}] |
- [\u{058D}-\u{058F}] |
- [\u{0591}-\u{05C7}] |
- [\u{05D0}-\u{05EA}] |
- [\u{05EF}-\u{05F4}] |
- [\u{0600}-\u{061C}] |
- [\u{061E}-\u{070D}] |
- [\u{070F}-\u{074A}] |
- [\u{074D}-\u{07B1}] |
- [\u{07C0}-\u{07FA}] |
- [\u{07FD}-\u{082D}] |
- [\u{0830}-\u{083E}] |
- [\u{0840}-\u{085B}] |
- \u{085E} |
- [\u{0860}-\u{086A}] |
- [\u{08A0}-\u{08B4}] |
- [\u{08B6}-\u{08BD}] |
- [\u{08D3}-\u{0983}] |
- [\u{0985}-\u{098C}] |
- [\u{098F}-\u{0990}] |
- [\u{0993}-\u{09A8}] |
- [\u{09AA}-\u{09B0}] |
- \u{09B2} |
- [\u{09B6}-\u{09B9}] |
- [\u{09BC}-\u{09C4}] |
- [\u{09C7}-\u{09C8}] |
- [\u{09CB}-\u{09CE}] |
- \u{09D7} |
- [\u{09DC}-\u{09DD}] |
- [\u{09DF}-\u{09E3}] |
- [\u{09E6}-\u{09FE}] |
- [\u{0A01}-\u{0A03}] |
- [\u{0A05}-\u{0A0A}] |
- [\u{0A0F}-\u{0A10}] |
- [\u{0A13}-\u{0A28}] |
- [\u{0A2A}-\u{0A30}] |
- [\u{0A32}-\u{0A33}] |
- [\u{0A35}-\u{0A36}] |
- [\u{0A38}-\u{0A39}] |
- \u{0A3C} |
- [\u{0A3E}-\u{0A42}] |
- [\u{0A47}-\u{0A48}] |
- [\u{0A4B}-\u{0A4D}] |
- \u{0A51} |
- [\u{0A59}-\u{0A5C}] |
- \u{0A5E} |
- [\u{0A66}-\u{0A76}] |
- [\u{0A81}-\u{0A83}] |
- [\u{0A85}-\u{0A8D}] |
- [\u{0A8F}-\u{0A91}] |
- [\u{0A93}-\u{0AA8}] |
- [\u{0AAA}-\u{0AB0}] |
- [\u{0AB2}-\u{0AB3}] |
- [\u{0AB5}-\u{0AB9}] |
- [\u{0ABC}-\u{0AC5}] |
- [\u{0AC7}-\u{0AC9}] |
- [\u{0ACB}-\u{0ACD}] |
- \u{0AD0} |
- [\u{0AE0}-\u{0AE3}] |
- [\u{0AE6}-\u{0AF1}] |
- [\u{0AF9}-\u{0AFF}] |
- [\u{0B01}-\u{0B03}] |
- [\u{0B05}-\u{0B0C}] |
- [\u{0B0F}-\u{0B10}] |
- [\u{0B13}-\u{0B28}] |
- [\u{0B2A}-\u{0B30}] |
- [\u{0B32}-\u{0B33}] |
- [\u{0B35}-\u{0B39}] |
- [\u{0B3C}-\u{0B44}] |
- [\u{0B47}-\u{0B48}] |
- [\u{0B4B}-\u{0B4D}] |
- [\u{0B56}-\u{0B57}] |
- [\u{0B5C}-\u{0B5D}] |
- [\u{0B5F}-\u{0B63}] |
- [\u{0B66}-\u{0B77}] |
- [\u{0B82}-\u{0B83}] |
- [\u{0B85}-\u{0B8A}] |
- [\u{0B8E}-\u{0B90}] |
- [\u{0B92}-\u{0B95}] |
- [\u{0B99}-\u{0B9A}] |
- \u{0B9C} |
- [\u{0B9E}-\u{0B9F}] |
- [\u{0BA3}-\u{0BA4}] |
- [\u{0BA8}-\u{0BAA}] |
- [\u{0BAE}-\u{0BB9}] |
- [\u{0BBE}-\u{0BC2}] |
- [\u{0BC6}-\u{0BC8}] |
- [\u{0BCA}-\u{0BCD}] |
- \u{0BD0} |
- \u{0BD7} |
- [\u{0BE6}-\u{0BFA}] |
- [\u{0C00}-\u{0C0C}] |
- [\u{0C0E}-\u{0C10}] |
- [\u{0C12}-\u{0C28}] |
- [\u{0C2A}-\u{0C39}] |
- [\u{0C3D}-\u{0C44}] |
- [\u{0C46}-\u{0C48}] |
- [\u{0C4A}-\u{0C4D}] |
- [\u{0C55}-\u{0C56}] |
- [\u{0C58}-\u{0C5A}] |
- [\u{0C60}-\u{0C63}] |
- [\u{0C66}-\u{0C6F}] |
- [\u{0C77}-\u{0C8C}] |
- [\u{0C8E}-\u{0C90}] |
- [\u{0C92}-\u{0CA8}] |
- [\u{0CAA}-\u{0CB3}] |
- [\u{0CB5}-\u{0CB9}] |
- [\u{0CBC}-\u{0CC4}] |
- [\u{0CC6}-\u{0CC8}] |
- [\u{0CCA}-\u{0CCD}] |
- [\u{0CD5}-\u{0CD6}] |
- \u{0CDE} |
- [\u{0CE0}-\u{0CE3}] |
- [\u{0CE6}-\u{0CEF}] |
- [\u{0CF1}-\u{0CF2}] |
- [\u{0D00}-\u{0D03}] |
- [\u{0D05}-\u{0D0C}] |
- [\u{0D0E}-\u{0D10}] |
- [\u{0D12}-\u{0D44}] |
- [\u{0D46}-\u{0D48}] |
- [\u{0D4A}-\u{0D4F}] |
- [\u{0D54}-\u{0D63}] |
- [\u{0D66}-\u{0D7F}] |
- [\u{0D82}-\u{0D83}] |
- [\u{0D85}-\u{0D96}] |
- [\u{0D9A}-\u{0DB1}] |
- [\u{0DB3}-\u{0DBB}] |
- \u{0DBD} |
- [\u{0DC0}-\u{0DC6}] |
- \u{0DCA} |
- [\u{0DCF}-\u{0DD4}] |
- \u{0DD6} |
- [\u{0DD8}-\u{0DDF}] |
- [\u{0DE6}-\u{0DEF}] |
- [\u{0DF2}-\u{0DF4}] |
- [\u{0E01}-\u{0E3A}] |
- [\u{0E3F}-\u{0E5B}] |
- [\u{0E81}-\u{0E82}] |
- \u{0E84} |
- [\u{0E86}-\u{0E8A}] |
- [\u{0E8C}-\u{0EA3}] |
- \u{0EA5} |
- [\u{0EA7}-\u{0EBD}] |
- [\u{0EC0}-\u{0EC4}] |
- \u{0EC6} |
- [\u{0EC8}-\u{0ECD}] |
- [\u{0ED0}-\u{0ED9}] |
- [\u{0EDC}-\u{0EDF}] |
- [\u{0F00}-\u{0F47}] |
- [\u{0F49}-\u{0F6C}] |
- [\u{0F71}-\u{0F97}] |
- [\u{0F99}-\u{0FBC}] |
- [\u{0FBE}-\u{0FCC}] |
- [\u{0FCE}-\u{0FDA}] |
- [\u{1000}-\u{10C5}] |
- \u{10C7} |
- \u{10CD} |
- [\u{10D0}-\u{10FF}] |
- [\u{1160}-\u{1248}] |
- [\u{124A}-\u{124D}] |
- [\u{1250}-\u{1256}] |
- \u{1258} |
- [\u{125A}-\u{125D}] |
- [\u{1260}-\u{1288}] |
- [\u{128A}-\u{128D}] |
- [\u{1290}-\u{12B0}] |
- [\u{12B2}-\u{12B5}] |
- [\u{12B8}-\u{12BE}] |
- \u{12C0} |
- [\u{12C2}-\u{12C5}] |
- [\u{12C8}-\u{12D6}] |
- [\u{12D8}-\u{1310}] |
- [\u{1312}-\u{1315}] |
- [\u{1318}-\u{135A}] |
- [\u{135D}-\u{137C}] |
- [\u{1380}-\u{1399}] |
- [\u{13A0}-\u{13F5}] |
- [\u{13F8}-\u{13FD}] |
- [\u{1400}-\u{169C}] |
- [\u{16A0}-\u{16F8}] |
- [\u{1700}-\u{170C}] |
- [\u{170E}-\u{1714}] |
- [\u{1720}-\u{1736}] |
- [\u{1740}-\u{1753}] |
- [\u{1760}-\u{176C}] |
- [\u{176E}-\u{1770}] |
- [\u{1772}-\u{1773}] |
- [\u{1780}-\u{17DD}] |
- [\u{17E0}-\u{17E9}] |
- [\u{17F0}-\u{17F9}] |
- [\u{1800}-\u{180E}] |
- [\u{1810}-\u{1819}] |
- [\u{1820}-\u{1878}] |
- [\u{1880}-\u{18AA}] |
- [\u{18B0}-\u{18F5}] |
- [\u{1900}-\u{191E}] |
- [\u{1920}-\u{192B}] |
- [\u{1930}-\u{193B}] |
- \u{1940} |
- [\u{1944}-\u{196D}] |
- [\u{1970}-\u{1974}] |
- [\u{1980}-\u{19AB}] |
- [\u{19B0}-\u{19C9}] |
- [\u{19D0}-\u{19DA}] |
- [\u{19DE}-\u{1A1B}] |
- [\u{1A1E}-\u{1A5E}] |
- [\u{1A60}-\u{1A7C}] |
- [\u{1A7F}-\u{1A89}] |
- [\u{1A90}-\u{1A99}] |
- [\u{1AA0}-\u{1AAD}] |
- [\u{1AB0}-\u{1ABE}] |
- [\u{1B00}-\u{1B4B}] |
- [\u{1B50}-\u{1B7C}] |
- [\u{1B80}-\u{1BF3}] |
- [\u{1BFC}-\u{1C37}] |
- [\u{1C3B}-\u{1C49}] |
- [\u{1C4D}-\u{1C88}] |
- [\u{1C90}-\u{1CBA}] |
- [\u{1CBD}-\u{1CC7}] |
- [\u{1CD0}-\u{1CFA}] |
- [\u{1D00}-\u{1DF9}] |
- [\u{1DFB}-\u{1F15}] |
- [\u{1F18}-\u{1F1D}] |
- [\u{1F20}-\u{1F45}] |
- [\u{1F48}-\u{1F4D}] |
- [\u{1F50}-\u{1F57}] |
- \u{1F59} |
- \u{1F5B} |
- \u{1F5D} |
- [\u{1F5F}-\u{1F7D}] |
- [\u{1F80}-\u{1FB4}] |
- [\u{1FB6}-\u{1FC4}] |
- [\u{1FC6}-\u{1FD3}] |
- [\u{1FD6}-\u{1FDB}] |
- [\u{1FDD}-\u{1FEF}] |
- [\u{1FF2}-\u{1FF4}] |
- [\u{1FF6}-\u{1FFE}] |
- [\u{2000}-\u{200F}] |
- [\u{2011}-\u{2012}] |
- \u{2017} |
- [\u{201A}-\u{201B}] |
- [\u{201E}-\u{201F}] |
- \u{2023} |
- [\u{2028}-\u{202F}] |
- \u{2031} |
- \u{2034} |
- [\u{2036}-\u{203A}] |
- [\u{203C}-\u{203D}] |
- [\u{203F}-\u{2064}] |
- [\u{2066}-\u{2071}] |
- [\u{2075}-\u{207E}] |
- \u{2080} |
- [\u{2085}-\u{208E}] |
- [\u{2090}-\u{209C}] |
- [\u{20A0}-\u{20A8}] |
- [\u{20AA}-\u{20AB}] |
- [\u{20AD}-\u{20BF}] |
- [\u{20D0}-\u{20F0}] |
- [\u{2100}-\u{2102}] |
- \u{2104} |
- [\u{2106}-\u{2108}] |
- [\u{210A}-\u{2112}] |
- [\u{2114}-\u{2115}] |
- [\u{2117}-\u{2120}] |
- [\u{2123}-\u{2125}] |
- [\u{2127}-\u{212A}] |
- [\u{212C}-\u{2152}] |
- [\u{2155}-\u{215A}] |
- \u{215F} |
- [\u{216C}-\u{216F}] |
- [\u{217A}-\u{2188}] |
- [\u{218A}-\u{218B}] |
- [\u{219A}-\u{21B7}] |
- [\u{21BA}-\u{21D1}] |
- \u{21D3} |
- [\u{21D5}-\u{21E6}] |
- [\u{21E8}-\u{21FF}] |
- \u{2201} |
- [\u{2204}-\u{2206}] |
- [\u{2209}-\u{220A}] |
- [\u{220C}-\u{220E}] |
- \u{2210} |
- [\u{2212}-\u{2214}] |
- [\u{2216}-\u{2219}] |
- [\u{221B}-\u{221C}] |
- [\u{2221}-\u{2222}] |
- \u{2224} |
- \u{2226} |
- \u{222D} |
- [\u{222F}-\u{2233}] |
- [\u{2238}-\u{223B}] |
- [\u{223E}-\u{2247}] |
- [\u{2249}-\u{224B}] |
- [\u{224D}-\u{2251}] |
- [\u{2253}-\u{225F}] |
- [\u{2262}-\u{2263}] |
- [\u{2268}-\u{2269}] |
- [\u{226C}-\u{226D}] |
- [\u{2270}-\u{2281}] |
- [\u{2284}-\u{2285}] |
- [\u{2288}-\u{2294}] |
- [\u{2296}-\u{2298}] |
- [\u{229A}-\u{22A4}] |
- [\u{22A6}-\u{22BE}] |
- [\u{22C0}-\u{2311}] |
- [\u{2313}-\u{2319}] |
- [\u{231C}-\u{2328}] |
- [\u{232B}-\u{23E8}] |
- [\u{23ED}-\u{23EF}] |
- [\u{23F1}-\u{23F2}] |
- [\u{23F4}-\u{2426}] |
- [\u{2440}-\u{244A}] |
- \u{24EA} |
- [\u{254C}-\u{254F}] |
- [\u{2574}-\u{257F}] |
- [\u{2590}-\u{2591}] |
- [\u{2596}-\u{259F}] |
- \u{25A2} |
- [\u{25AA}-\u{25B1}] |
- [\u{25B4}-\u{25B5}] |
- [\u{25B8}-\u{25BB}] |
- [\u{25BE}-\u{25BF}] |
- [\u{25C2}-\u{25C5}] |
- [\u{25C9}-\u{25CA}] |
- [\u{25CC}-\u{25CD}] |
- [\u{25D2}-\u{25E1}] |
- [\u{25E6}-\u{25EE}] |
- [\u{25F0}-\u{25FC}] |
- [\u{25FF}-\u{2604}] |
- [\u{2607}-\u{2608}] |
- [\u{260A}-\u{260D}] |
- [\u{2610}-\u{2613}] |
- [\u{2616}-\u{261B}] |
- \u{261D} |
- [\u{261F}-\u{263F}] |
- \u{2641} |
- [\u{2643}-\u{2647}] |
- [\u{2654}-\u{265F}] |
- \u{2662} |
- \u{2666} |
- \u{266B} |
- \u{266E} |
- [\u{2670}-\u{267E}] |
- [\u{2680}-\u{2692}] |
- [\u{2694}-\u{269D}] |
- \u{26A0} |
- [\u{26A2}-\u{26A9}] |
- [\u{26AC}-\u{26BC}] |
- [\u{26C0}-\u{26C3}] |
- \u{26E2} |
- [\u{26E4}-\u{26E7}] |
- [\u{2700}-\u{2704}] |
- [\u{2706}-\u{2709}] |
- [\u{270C}-\u{2727}] |
- [\u{2729}-\u{273C}] |
- [\u{273E}-\u{274B}] |
- \u{274D} |
- [\u{274F}-\u{2752}] |
- \u{2756} |
- [\u{2758}-\u{2775}] |
- [\u{2780}-\u{2794}] |
- [\u{2798}-\u{27AF}] |
- [\u{27B1}-\u{27BE}] |
- [\u{27C0}-\u{27E5}] |
- [\u{27EE}-\u{2984}] |
- [\u{2987}-\u{2B1A}] |
- [\u{2B1D}-\u{2B4F}] |
- [\u{2B51}-\u{2B54}] |
- [\u{2B5A}-\u{2B73}] |
- [\u{2B76}-\u{2B95}] |
- [\u{2B98}-\u{2C2E}] |
- [\u{2C30}-\u{2C5E}] |
- [\u{2C60}-\u{2CF3}] |
- [\u{2CF9}-\u{2D25}] |
- \u{2D27} |
- \u{2D2D} |
- [\u{2D30}-\u{2D67}] |
- [\u{2D6F}-\u{2D70}] |
- [\u{2D7F}-\u{2D96}] |
- [\u{2DA0}-\u{2DA6}] |
- [\u{2DA8}-\u{2DAE}] |
- [\u{2DB0}-\u{2DB6}] |
- [\u{2DB8}-\u{2DBE}] |
- [\u{2DC0}-\u{2DC6}] |
- [\u{2DC8}-\u{2DCE}] |
- [\u{2DD0}-\u{2DD6}] |
- [\u{2DD8}-\u{2DDE}] |
- [\u{2DE0}-\u{2E4F}] |
- \u{303F} |
- [\u{4DC0}-\u{4DFF}] |
- [\u{A4D0}-\u{A62B}] |
- [\u{A640}-\u{A6F7}] |
- [\u{A700}-\u{A7BF}] |
- [\u{A7C2}-\u{A7C6}] |
- [\u{A7F7}-\u{A82B}] |
- [\u{A830}-\u{A839}] |
- [\u{A840}-\u{A877}] |
- [\u{A880}-\u{A8C5}] |
- [\u{A8CE}-\u{A8D9}] |
- [\u{A8E0}-\u{A953}] |
- \u{A95F} |
- [\u{A980}-\u{A9CD}] |
- [\u{A9CF}-\u{A9D9}] |
- [\u{A9DE}-\u{A9FE}] |
- [\u{AA00}-\u{AA36}] |
- [\u{AA40}-\u{AA4D}] |
- [\u{AA50}-\u{AA59}] |
- [\u{AA5C}-\u{AAC2}] |
- [\u{AADB}-\u{AAF6}] |
- [\u{AB01}-\u{AB06}] |
- [\u{AB09}-\u{AB0E}] |
- [\u{AB11}-\u{AB16}] |
- [\u{AB20}-\u{AB26}] |
- [\u{AB28}-\u{AB2E}] |
- [\u{AB30}-\u{AB67}] |
- [\u{AB70}-\u{ABED}] |
- [\u{ABF0}-\u{ABF9}] |
- [\u{D7B0}-\u{D7C6}] |
- [\u{D7CB}-\u{D7FB}] |
- [\u{FB00}-\u{FB06}] |
- [\u{FB13}-\u{FB17}] |
- [\u{FB1D}-\u{FB36}] |
- [\u{FB38}-\u{FB3C}] |
- \u{FB3E} |
- [\u{FB40}-\u{FB41}] |
- [\u{FB43}-\u{FB44}] |
- [\u{FB46}-\u{FBC1}] |
- [\u{FBD3}-\u{FD3F}] |
- [\u{FD50}-\u{FD8F}] |
- [\u{FD92}-\u{FDC7}] |
- [\u{FDF0}-\u{FDFD}] |
- [\u{FE20}-\u{FE2F}] |
- [\u{FE70}-\u{FE74}] |
- [\u{FE76}-\u{FEFC}] |
- \u{FEFF} |
- [\u{FFF9}-\u{FFFC}] |
- [\u{10000}-\u{1000B}] |
- [\u{1000D}-\u{10026}] |
- [\u{10028}-\u{1003A}] |
- [\u{1003C}-\u{1003D}] |
- [\u{1003F}-\u{1004D}] |
- [\u{10050}-\u{1005D}] |
- [\u{10080}-\u{100FA}] |
- [\u{10100}-\u{10102}] |
- [\u{10107}-\u{10133}] |
- [\u{10137}-\u{1018E}] |
- [\u{10190}-\u{1019B}] |
- \u{101A0} |
- [\u{101D0}-\u{101FD}] |
- [\u{10280}-\u{1029C}] |
- [\u{102A0}-\u{102D0}] |
- [\u{102E0}-\u{102FB}] |
- [\u{10300}-\u{10323}] |
- [\u{1032D}-\u{1034A}] |
- [\u{10350}-\u{1037A}] |
- [\u{10380}-\u{1039D}] |
- [\u{1039F}-\u{103C3}] |
- [\u{103C8}-\u{103D5}] |
- [\u{10400}-\u{1049D}] |
- [\u{104A0}-\u{104A9}] |
- [\u{104B0}-\u{104D3}] |
- [\u{104D8}-\u{104FB}] |
- [\u{10500}-\u{10527}] |
- [\u{10530}-\u{10563}] |
- \u{1056F} |
- [\u{10600}-\u{10736}] |
- [\u{10740}-\u{10755}] |
- [\u{10760}-\u{10767}] |
- [\u{10800}-\u{10805}] |
- \u{10808} |
- [\u{1080A}-\u{10835}] |
- [\u{10837}-\u{10838}] |
- \u{1083C} |
- [\u{1083F}-\u{10855}] |
- [\u{10857}-\u{1089E}] |
- [\u{108A7}-\u{108AF}] |
- [\u{108E0}-\u{108F2}] |
- [\u{108F4}-\u{108F5}] |
- [\u{108FB}-\u{1091B}] |
- [\u{1091F}-\u{10939}] |
- \u{1093F} |
- [\u{10980}-\u{109B7}] |
- [\u{109BC}-\u{109CF}] |
- [\u{109D2}-\u{10A03}] |
- [\u{10A05}-\u{10A06}] |
- [\u{10A0C}-\u{10A13}] |
- [\u{10A15}-\u{10A17}] |
- [\u{10A19}-\u{10A35}] |
- [\u{10A38}-\u{10A3A}] |
- [\u{10A3F}-\u{10A48}] |
- [\u{10A50}-\u{10A58}] |
- [\u{10A60}-\u{10A9F}] |
- [\u{10AC0}-\u{10AE6}] |
- [\u{10AEB}-\u{10AF6}] |
- [\u{10B00}-\u{10B35}] |
- [\u{10B39}-\u{10B55}] |
- [\u{10B58}-\u{10B72}] |
- [\u{10B78}-\u{10B91}] |
- [\u{10B99}-\u{10B9C}] |
- [\u{10BA9}-\u{10BAF}] |
- [\u{10C00}-\u{10C48}] |
- [\u{10C80}-\u{10CB2}] |
- [\u{10CC0}-\u{10CF2}] |
- [\u{10CFA}-\u{10D27}] |
- [\u{10D30}-\u{10D39}] |
- [\u{10E60}-\u{10E7E}] |
- [\u{10F00}-\u{10F27}] |
- [\u{10F30}-\u{10F59}] |
- [\u{10FE0}-\u{10FF6}] |
- [\u{11000}-\u{1104D}] |
- [\u{11052}-\u{1106F}] |
- [\u{1107F}-\u{110C1}] |
- \u{110CD} |
- [\u{110D0}-\u{110E8}] |
- [\u{110F0}-\u{110F9}] |
- [\u{11100}-\u{11134}] |
- [\u{11136}-\u{11146}] |
- [\u{11150}-\u{11176}] |
- [\u{11180}-\u{111CD}] |
- [\u{111D0}-\u{111DF}] |
- [\u{111E1}-\u{111F4}] |
- [\u{11200}-\u{11211}] |
- [\u{11213}-\u{1123E}] |
- [\u{11280}-\u{11286}] |
- \u{11288} |
- [\u{1128A}-\u{1128D}] |
- [\u{1128F}-\u{1129D}] |
- [\u{1129F}-\u{112A9}] |
- [\u{112B0}-\u{112EA}] |
- [\u{112F0}-\u{112F9}] |
- [\u{11300}-\u{11303}] |
- [\u{11305}-\u{1130C}] |
- [\u{1130F}-\u{11310}] |
- [\u{11313}-\u{11328}] |
- [\u{1132A}-\u{11330}] |
- [\u{11332}-\u{11333}] |
- [\u{11335}-\u{11339}] |
- [\u{1133B}-\u{11344}] |
- [\u{11347}-\u{11348}] |
- [\u{1134B}-\u{1134D}] |
- \u{11350} |
- \u{11357} |
- [\u{1135D}-\u{11363}] |
- [\u{11366}-\u{1136C}] |
- [\u{11370}-\u{11374}] |
- [\u{11400}-\u{11459}] |
- \u{1145B} |
- [\u{1145D}-\u{1145F}] |
- [\u{11480}-\u{114C7}] |
- [\u{114D0}-\u{114D9}] |
- [\u{11580}-\u{115B5}] |
- [\u{115B8}-\u{115DD}] |
- [\u{11600}-\u{11644}] |
- [\u{11650}-\u{11659}] |
- [\u{11660}-\u{1166C}] |
- [\u{11680}-\u{116B8}] |
- [\u{116C0}-\u{116C9}] |
- [\u{11700}-\u{1171A}] |
- [\u{1171D}-\u{1172B}] |
- [\u{11730}-\u{1173F}] |
- [\u{11800}-\u{1183B}] |
- [\u{118A0}-\u{118F2}] |
- \u{118FF} |
- [\u{119A0}-\u{119A7}] |
- [\u{119AA}-\u{119D7}] |
- [\u{119DA}-\u{119E4}] |
- [\u{11A00}-\u{11A47}] |
- [\u{11A50}-\u{11AA2}] |
- [\u{11AC0}-\u{11AF8}] |
- [\u{11C00}-\u{11C08}] |
- [\u{11C0A}-\u{11C36}] |
- [\u{11C38}-\u{11C45}] |
- [\u{11C50}-\u{11C6C}] |
- [\u{11C70}-\u{11C8F}] |
- [\u{11C92}-\u{11CA7}] |
- [\u{11CA9}-\u{11CB6}] |
- [\u{11D00}-\u{11D06}] |
- [\u{11D08}-\u{11D09}] |
- [\u{11D0B}-\u{11D36}] |
- \u{11D3A} |
- [\u{11D3C}-\u{11D3D}] |
- [\u{11D3F}-\u{11D47}] |
- [\u{11D50}-\u{11D59}] |
- [\u{11D60}-\u{11D65}] |
- [\u{11D67}-\u{11D68}] |
- [\u{11D6A}-\u{11D8E}] |
- [\u{11D90}-\u{11D91}] |
- [\u{11D93}-\u{11D98}] |
- [\u{11DA0}-\u{11DA9}] |
- [\u{11EE0}-\u{11EF8}] |
- [\u{11FC0}-\u{11FF1}] |
- [\u{11FFF}-\u{12399}] |
- [\u{12400}-\u{1246E}] |
- [\u{12470}-\u{12474}] |
- [\u{12480}-\u{12543}] |
- [\u{13000}-\u{1342E}] |
- [\u{13430}-\u{13438}] |
- [\u{14400}-\u{14646}] |
- [\u{16800}-\u{16A38}] |
- [\u{16A40}-\u{16A5E}] |
- [\u{16A60}-\u{16A69}] |
- [\u{16A6E}-\u{16A6F}] |
- [\u{16AD0}-\u{16AED}] |
- [\u{16AF0}-\u{16AF5}] |
- [\u{16B00}-\u{16B45}] |
- [\u{16B50}-\u{16B59}] |
- [\u{16B5B}-\u{16B61}] |
- [\u{16B63}-\u{16B77}] |
- [\u{16B7D}-\u{16B8F}] |
- [\u{16E40}-\u{16E9A}] |
- [\u{16F00}-\u{16F4A}] |
- [\u{16F4F}-\u{16F87}] |
- [\u{16F8F}-\u{16F9F}] |
- [\u{1BC00}-\u{1BC6A}] |
- [\u{1BC70}-\u{1BC7C}] |
- [\u{1BC80}-\u{1BC88}] |
- [\u{1BC90}-\u{1BC99}] |
- [\u{1BC9C}-\u{1BCA3}] |
- [\u{1D000}-\u{1D0F5}] |
- [\u{1D100}-\u{1D126}] |
- [\u{1D129}-\u{1D1E8}] |
- [\u{1D200}-\u{1D245}] |
- [\u{1D2E0}-\u{1D2F3}] |
- [\u{1D300}-\u{1D356}] |
- [\u{1D360}-\u{1D378}] |
- [\u{1D400}-\u{1D454}] |
- [\u{1D456}-\u{1D49C}] |
- [\u{1D49E}-\u{1D49F}] |
- \u{1D4A2} |
- [\u{1D4A5}-\u{1D4A6}] |
- [\u{1D4A9}-\u{1D4AC}] |
- [\u{1D4AE}-\u{1D4B9}] |
- \u{1D4BB} |
- [\u{1D4BD}-\u{1D4C3}] |
- [\u{1D4C5}-\u{1D505}] |
- [\u{1D507}-\u{1D50A}] |
- [\u{1D50D}-\u{1D514}] |
- [\u{1D516}-\u{1D51C}] |
- [\u{1D51E}-\u{1D539}] |
- [\u{1D53B}-\u{1D53E}] |
- [\u{1D540}-\u{1D544}] |
- \u{1D546} |
- [\u{1D54A}-\u{1D550}] |
- [\u{1D552}-\u{1D6A5}] |
- [\u{1D6A8}-\u{1D7CB}] |
- [\u{1D7CE}-\u{1DA8B}] |
- [\u{1DA9B}-\u{1DA9F}] |
- [\u{1DAA1}-\u{1DAAF}] |
- [\u{1E000}-\u{1E006}] |
- [\u{1E008}-\u{1E018}] |
- [\u{1E01B}-\u{1E021}] |
- [\u{1E023}-\u{1E024}] |
- [\u{1E026}-\u{1E02A}] |
- [\u{1E100}-\u{1E12C}] |
- [\u{1E130}-\u{1E13D}] |
- [\u{1E140}-\u{1E149}] |
- [\u{1E14E}-\u{1E14F}] |
- [\u{1E2C0}-\u{1E2F9}] |
- \u{1E2FF} |
- [\u{1E800}-\u{1E8C4}] |
- [\u{1E8C7}-\u{1E8D6}] |
- [\u{1E900}-\u{1E94B}] |
- [\u{1E950}-\u{1E959}] |
- [\u{1E95E}-\u{1E95F}] |
- [\u{1EC71}-\u{1ECB4}] |
- [\u{1ED01}-\u{1ED3D}] |
- [\u{1EE00}-\u{1EE03}] |
- [\u{1EE05}-\u{1EE1F}] |
- [\u{1EE21}-\u{1EE22}] |
- \u{1EE24} |
- \u{1EE27} |
- [\u{1EE29}-\u{1EE32}] |
- [\u{1EE34}-\u{1EE37}] |
- \u{1EE39} |
- \u{1EE3B} |
- \u{1EE42} |
- \u{1EE47} |
- \u{1EE49} |
- \u{1EE4B} |
- [\u{1EE4D}-\u{1EE4F}] |
- [\u{1EE51}-\u{1EE52}] |
- \u{1EE54} |
- \u{1EE57} |
- \u{1EE59} |
- \u{1EE5B} |
- \u{1EE5D} |
- \u{1EE5F} |
- [\u{1EE61}-\u{1EE62}] |
- \u{1EE64} |
- [\u{1EE67}-\u{1EE6A}] |
- [\u{1EE6C}-\u{1EE72}] |
- [\u{1EE74}-\u{1EE77}] |
- [\u{1EE79}-\u{1EE7C}] |
- \u{1EE7E} |
- [\u{1EE80}-\u{1EE89}] |
- [\u{1EE8B}-\u{1EE9B}] |
- [\u{1EEA1}-\u{1EEA3}] |
- [\u{1EEA5}-\u{1EEA9}] |
- [\u{1EEAB}-\u{1EEBB}] |
- [\u{1EEF0}-\u{1EEF1}] |
- [\u{1F000}-\u{1F003}] |
- [\u{1F005}-\u{1F02B}] |
- [\u{1F030}-\u{1F093}] |
- [\u{1F0A0}-\u{1F0AE}] |
- [\u{1F0B1}-\u{1F0BF}] |
- [\u{1F0C1}-\u{1F0CE}] |
- [\u{1F0D1}-\u{1F0F5}] |
- [\u{1F10B}-\u{1F10C}] |
- [\u{1F12E}-\u{1F12F}] |
- [\u{1F16A}-\u{1F16C}] |
- [\u{1F1E6}-\u{1F1FF}] |
- [\u{1F321}-\u{1F32C}] |
- \u{1F336} |
- \u{1F37D} |
- [\u{1F394}-\u{1F39F}] |
- [\u{1F3CB}-\u{1F3CE}] |
- [\u{1F3D4}-\u{1F3DF}] |
- [\u{1F3F1}-\u{1F3F3}] |
- [\u{1F3F5}-\u{1F3F7}] |
- \u{1F43F} |
- \u{1F441} |
- [\u{1F4FD}-\u{1F4FE}] |
- [\u{1F53E}-\u{1F54A}] |
- \u{1F54F} |
- [\u{1F568}-\u{1F579}] |
- [\u{1F57B}-\u{1F594}] |
- [\u{1F597}-\u{1F5A3}] |
- [\u{1F5A5}-\u{1F5FA}] |
- [\u{1F650}-\u{1F67F}] |
- [\u{1F6C6}-\u{1F6CB}] |
- [\u{1F6CD}-\u{1F6CF}] |
- [\u{1F6D3}-\u{1F6D4}] |
- [\u{1F6E0}-\u{1F6EA}] |
- [\u{1F6F0}-\u{1F6F3}] |
- [\u{1F700}-\u{1F773}] |
- [\u{1F780}-\u{1F7D8}] |
- [\u{1F800}-\u{1F80B}] |
- [\u{1F810}-\u{1F847}] |
- [\u{1F850}-\u{1F859}] |
- [\u{1F860}-\u{1F887}] |
- [\u{1F890}-\u{1F8AD}] |
- [\u{1F900}-\u{1F90B}] |
- [\u{1FA00}-\u{1FA53}] |
- [\u{1FA60}-\u{1FA6D}] |
- \u{E0001} |
- [\u{E0020}-\u{E007F}]
- )/x
+ TYPE_N = /^[#{ %W(
+ \u{0000}-\u{001F}
+ \u{007F}-\u{00A0}
+ \u{00A9}
+ \u{00AB}
+ \u{00B5}
+ \u{00BB}
+ \u{00C0}-\u{00C5}
+ \u{00C7}-\u{00CF}
+ \u{00D1}-\u{00D6}
+ \u{00D9}-\u{00DD}
+ \u{00E2}-\u{00E5}
+ \u{00E7}
+ \u{00EB}
+ \u{00EE}-\u{00EF}
+ \u{00F1}
+ \u{00F4}-\u{00F6}
+ \u{00FB}
+ \u{00FD}
+ \u{00FF}-\u{0100}
+ \u{0102}-\u{0110}
+ \u{0112}
+ \u{0114}-\u{011A}
+ \u{011C}-\u{0125}
+ \u{0128}-\u{012A}
+ \u{012C}-\u{0130}
+ \u{0134}-\u{0137}
+ \u{0139}-\u{013E}
+ \u{0143}
+ \u{0145}-\u{0147}
+ \u{014C}
+ \u{014E}-\u{0151}
+ \u{0154}-\u{0165}
+ \u{0168}-\u{016A}
+ \u{016C}-\u{01CD}
+ \u{01CF}
+ \u{01D1}
+ \u{01D3}
+ \u{01D5}
+ \u{01D7}
+ \u{01D9}
+ \u{01DB}
+ \u{01DD}-\u{0250}
+ \u{0252}-\u{0260}
+ \u{0262}-\u{02C3}
+ \u{02C5}-\u{02C6}
+ \u{02C8}
+ \u{02CC}
+ \u{02CE}-\u{02CF}
+ \u{02D1}-\u{02D7}
+ \u{02DC}
+ \u{02DE}
+ \u{02E0}-\u{02FF}
+ \u{0370}-\u{0377}
+ \u{037A}-\u{037F}
+ \u{0384}-\u{038A}
+ \u{038C}
+ \u{038E}-\u{0390}
+ \u{03AA}-\u{03B0}
+ \u{03C2}
+ \u{03CA}-\u{0400}
+ \u{0402}-\u{040F}
+ \u{0450}
+ \u{0452}-\u{052F}
+ \u{0531}-\u{0556}
+ \u{0559}-\u{058A}
+ \u{058D}-\u{058F}
+ \u{0591}-\u{05C7}
+ \u{05D0}-\u{05EA}
+ \u{05EF}-\u{05F4}
+ \u{0600}-\u{061C}
+ \u{061E}-\u{070D}
+ \u{070F}-\u{074A}
+ \u{074D}-\u{07B1}
+ \u{07C0}-\u{07FA}
+ \u{07FD}-\u{082D}
+ \u{0830}-\u{083E}
+ \u{0840}-\u{085B}
+ \u{085E}
+ \u{0860}-\u{086A}
+ \u{08A0}-\u{08B4}
+ \u{08B6}-\u{08C7}
+ \u{08D3}-\u{0983}
+ \u{0985}-\u{098C}
+ \u{098F}-\u{0990}
+ \u{0993}-\u{09A8}
+ \u{09AA}-\u{09B0}
+ \u{09B2}
+ \u{09B6}-\u{09B9}
+ \u{09BC}-\u{09C4}
+ \u{09C7}-\u{09C8}
+ \u{09CB}-\u{09CE}
+ \u{09D7}
+ \u{09DC}-\u{09DD}
+ \u{09DF}-\u{09E3}
+ \u{09E6}-\u{09FE}
+ \u{0A01}-\u{0A03}
+ \u{0A05}-\u{0A0A}
+ \u{0A0F}-\u{0A10}
+ \u{0A13}-\u{0A28}
+ \u{0A2A}-\u{0A30}
+ \u{0A32}-\u{0A33}
+ \u{0A35}-\u{0A36}
+ \u{0A38}-\u{0A39}
+ \u{0A3C}
+ \u{0A3E}-\u{0A42}
+ \u{0A47}-\u{0A48}
+ \u{0A4B}-\u{0A4D}
+ \u{0A51}
+ \u{0A59}-\u{0A5C}
+ \u{0A5E}
+ \u{0A66}-\u{0A76}
+ \u{0A81}-\u{0A83}
+ \u{0A85}-\u{0A8D}
+ \u{0A8F}-\u{0A91}
+ \u{0A93}-\u{0AA8}
+ \u{0AAA}-\u{0AB0}
+ \u{0AB2}-\u{0AB3}
+ \u{0AB5}-\u{0AB9}
+ \u{0ABC}-\u{0AC5}
+ \u{0AC7}-\u{0AC9}
+ \u{0ACB}-\u{0ACD}
+ \u{0AD0}
+ \u{0AE0}-\u{0AE3}
+ \u{0AE6}-\u{0AF1}
+ \u{0AF9}-\u{0AFF}
+ \u{0B01}-\u{0B03}
+ \u{0B05}-\u{0B0C}
+ \u{0B0F}-\u{0B10}
+ \u{0B13}-\u{0B28}
+ \u{0B2A}-\u{0B30}
+ \u{0B32}-\u{0B33}
+ \u{0B35}-\u{0B39}
+ \u{0B3C}-\u{0B44}
+ \u{0B47}-\u{0B48}
+ \u{0B4B}-\u{0B4D}
+ \u{0B55}-\u{0B57}
+ \u{0B5C}-\u{0B5D}
+ \u{0B5F}-\u{0B63}
+ \u{0B66}-\u{0B77}
+ \u{0B82}-\u{0B83}
+ \u{0B85}-\u{0B8A}
+ \u{0B8E}-\u{0B90}
+ \u{0B92}-\u{0B95}
+ \u{0B99}-\u{0B9A}
+ \u{0B9C}
+ \u{0B9E}-\u{0B9F}
+ \u{0BA3}-\u{0BA4}
+ \u{0BA8}-\u{0BAA}
+ \u{0BAE}-\u{0BB9}
+ \u{0BBE}-\u{0BC2}
+ \u{0BC6}-\u{0BC8}
+ \u{0BCA}-\u{0BCD}
+ \u{0BD0}
+ \u{0BD7}
+ \u{0BE6}-\u{0BFA}
+ \u{0C00}-\u{0C0C}
+ \u{0C0E}-\u{0C10}
+ \u{0C12}-\u{0C28}
+ \u{0C2A}-\u{0C39}
+ \u{0C3D}-\u{0C44}
+ \u{0C46}-\u{0C48}
+ \u{0C4A}-\u{0C4D}
+ \u{0C55}-\u{0C56}
+ \u{0C58}-\u{0C5A}
+ \u{0C60}-\u{0C63}
+ \u{0C66}-\u{0C6F}
+ \u{0C77}-\u{0C8C}
+ \u{0C8E}-\u{0C90}
+ \u{0C92}-\u{0CA8}
+ \u{0CAA}-\u{0CB3}
+ \u{0CB5}-\u{0CB9}
+ \u{0CBC}-\u{0CC4}
+ \u{0CC6}-\u{0CC8}
+ \u{0CCA}-\u{0CCD}
+ \u{0CD5}-\u{0CD6}
+ \u{0CDE}
+ \u{0CE0}-\u{0CE3}
+ \u{0CE6}-\u{0CEF}
+ \u{0CF1}-\u{0CF2}
+ \u{0D00}-\u{0D0C}
+ \u{0D0E}-\u{0D10}
+ \u{0D12}-\u{0D44}
+ \u{0D46}-\u{0D48}
+ \u{0D4A}-\u{0D4F}
+ \u{0D54}-\u{0D63}
+ \u{0D66}-\u{0D7F}
+ \u{0D81}-\u{0D83}
+ \u{0D85}-\u{0D96}
+ \u{0D9A}-\u{0DB1}
+ \u{0DB3}-\u{0DBB}
+ \u{0DBD}
+ \u{0DC0}-\u{0DC6}
+ \u{0DCA}
+ \u{0DCF}-\u{0DD4}
+ \u{0DD6}
+ \u{0DD8}-\u{0DDF}
+ \u{0DE6}-\u{0DEF}
+ \u{0DF2}-\u{0DF4}
+ \u{0E01}-\u{0E3A}
+ \u{0E3F}-\u{0E5B}
+ \u{0E81}-\u{0E82}
+ \u{0E84}
+ \u{0E86}-\u{0E8A}
+ \u{0E8C}-\u{0EA3}
+ \u{0EA5}
+ \u{0EA7}-\u{0EBD}
+ \u{0EC0}-\u{0EC4}
+ \u{0EC6}
+ \u{0EC8}-\u{0ECD}
+ \u{0ED0}-\u{0ED9}
+ \u{0EDC}-\u{0EDF}
+ \u{0F00}-\u{0F47}
+ \u{0F49}-\u{0F6C}
+ \u{0F71}-\u{0F97}
+ \u{0F99}-\u{0FBC}
+ \u{0FBE}-\u{0FCC}
+ \u{0FCE}-\u{0FDA}
+ \u{1000}-\u{10C5}
+ \u{10C7}
+ \u{10CD}
+ \u{10D0}-\u{10FF}
+ \u{1160}-\u{1248}
+ \u{124A}-\u{124D}
+ \u{1250}-\u{1256}
+ \u{1258}
+ \u{125A}-\u{125D}
+ \u{1260}-\u{1288}
+ \u{128A}-\u{128D}
+ \u{1290}-\u{12B0}
+ \u{12B2}-\u{12B5}
+ \u{12B8}-\u{12BE}
+ \u{12C0}
+ \u{12C2}-\u{12C5}
+ \u{12C8}-\u{12D6}
+ \u{12D8}-\u{1310}
+ \u{1312}-\u{1315}
+ \u{1318}-\u{135A}
+ \u{135D}-\u{137C}
+ \u{1380}-\u{1399}
+ \u{13A0}-\u{13F5}
+ \u{13F8}-\u{13FD}
+ \u{1400}-\u{169C}
+ \u{16A0}-\u{16F8}
+ \u{1700}-\u{170C}
+ \u{170E}-\u{1714}
+ \u{1720}-\u{1736}
+ \u{1740}-\u{1753}
+ \u{1760}-\u{176C}
+ \u{176E}-\u{1770}
+ \u{1772}-\u{1773}
+ \u{1780}-\u{17DD}
+ \u{17E0}-\u{17E9}
+ \u{17F0}-\u{17F9}
+ \u{1800}-\u{180E}
+ \u{1810}-\u{1819}
+ \u{1820}-\u{1878}
+ \u{1880}-\u{18AA}
+ \u{18B0}-\u{18F5}
+ \u{1900}-\u{191E}
+ \u{1920}-\u{192B}
+ \u{1930}-\u{193B}
+ \u{1940}
+ \u{1944}-\u{196D}
+ \u{1970}-\u{1974}
+ \u{1980}-\u{19AB}
+ \u{19B0}-\u{19C9}
+ \u{19D0}-\u{19DA}
+ \u{19DE}-\u{1A1B}
+ \u{1A1E}-\u{1A5E}
+ \u{1A60}-\u{1A7C}
+ \u{1A7F}-\u{1A89}
+ \u{1A90}-\u{1A99}
+ \u{1AA0}-\u{1AAD}
+ \u{1AB0}-\u{1AC0}
+ \u{1B00}-\u{1B4B}
+ \u{1B50}-\u{1B7C}
+ \u{1B80}-\u{1BF3}
+ \u{1BFC}-\u{1C37}
+ \u{1C3B}-\u{1C49}
+ \u{1C4D}-\u{1C88}
+ \u{1C90}-\u{1CBA}
+ \u{1CBD}-\u{1CC7}
+ \u{1CD0}-\u{1CFA}
+ \u{1D00}-\u{1DF9}
+ \u{1DFB}-\u{1F15}
+ \u{1F18}-\u{1F1D}
+ \u{1F20}-\u{1F45}
+ \u{1F48}-\u{1F4D}
+ \u{1F50}-\u{1F57}
+ \u{1F59}
+ \u{1F5B}
+ \u{1F5D}
+ \u{1F5F}-\u{1F7D}
+ \u{1F80}-\u{1FB4}
+ \u{1FB6}-\u{1FC4}
+ \u{1FC6}-\u{1FD3}
+ \u{1FD6}-\u{1FDB}
+ \u{1FDD}-\u{1FEF}
+ \u{1FF2}-\u{1FF4}
+ \u{1FF6}-\u{1FFE}
+ \u{2000}-\u{200F}
+ \u{2011}-\u{2012}
+ \u{2017}
+ \u{201A}-\u{201B}
+ \u{201E}-\u{201F}
+ \u{2023}
+ \u{2028}-\u{202F}
+ \u{2031}
+ \u{2034}
+ \u{2036}-\u{203A}
+ \u{203C}-\u{203D}
+ \u{203F}-\u{2064}
+ \u{2066}-\u{2071}
+ \u{2075}-\u{207E}
+ \u{2080}
+ \u{2085}-\u{208E}
+ \u{2090}-\u{209C}
+ \u{20A0}-\u{20A8}
+ \u{20AA}-\u{20AB}
+ \u{20AD}-\u{20BF}
+ \u{20D0}-\u{20F0}
+ \u{2100}-\u{2102}
+ \u{2104}
+ \u{2106}-\u{2108}
+ \u{210A}-\u{2112}
+ \u{2114}-\u{2115}
+ \u{2117}-\u{2120}
+ \u{2123}-\u{2125}
+ \u{2127}-\u{212A}
+ \u{212C}-\u{2152}
+ \u{2155}-\u{215A}
+ \u{215F}
+ \u{216C}-\u{216F}
+ \u{217A}-\u{2188}
+ \u{218A}-\u{218B}
+ \u{219A}-\u{21B7}
+ \u{21BA}-\u{21D1}
+ \u{21D3}
+ \u{21D5}-\u{21E6}
+ \u{21E8}-\u{21FF}
+ \u{2201}
+ \u{2204}-\u{2206}
+ \u{2209}-\u{220A}
+ \u{220C}-\u{220E}
+ \u{2210}
+ \u{2212}-\u{2214}
+ \u{2216}-\u{2219}
+ \u{221B}-\u{221C}
+ \u{2221}-\u{2222}
+ \u{2224}
+ \u{2226}
+ \u{222D}
+ \u{222F}-\u{2233}
+ \u{2238}-\u{223B}
+ \u{223E}-\u{2247}
+ \u{2249}-\u{224B}
+ \u{224D}-\u{2251}
+ \u{2253}-\u{225F}
+ \u{2262}-\u{2263}
+ \u{2268}-\u{2269}
+ \u{226C}-\u{226D}
+ \u{2270}-\u{2281}
+ \u{2284}-\u{2285}
+ \u{2288}-\u{2294}
+ \u{2296}-\u{2298}
+ \u{229A}-\u{22A4}
+ \u{22A6}-\u{22BE}
+ \u{22C0}-\u{2311}
+ \u{2313}-\u{2319}
+ \u{231C}-\u{2328}
+ \u{232B}-\u{23E8}
+ \u{23ED}-\u{23EF}
+ \u{23F1}-\u{23F2}
+ \u{23F4}-\u{2426}
+ \u{2440}-\u{244A}
+ \u{24EA}
+ \u{254C}-\u{254F}
+ \u{2574}-\u{257F}
+ \u{2590}-\u{2591}
+ \u{2596}-\u{259F}
+ \u{25A2}
+ \u{25AA}-\u{25B1}
+ \u{25B4}-\u{25B5}
+ \u{25B8}-\u{25BB}
+ \u{25BE}-\u{25BF}
+ \u{25C2}-\u{25C5}
+ \u{25C9}-\u{25CA}
+ \u{25CC}-\u{25CD}
+ \u{25D2}-\u{25E1}
+ \u{25E6}-\u{25EE}
+ \u{25F0}-\u{25FC}
+ \u{25FF}-\u{2604}
+ \u{2607}-\u{2608}
+ \u{260A}-\u{260D}
+ \u{2610}-\u{2613}
+ \u{2616}-\u{261B}
+ \u{261D}
+ \u{261F}-\u{263F}
+ \u{2641}
+ \u{2643}-\u{2647}
+ \u{2654}-\u{265F}
+ \u{2662}
+ \u{2666}
+ \u{266B}
+ \u{266E}
+ \u{2670}-\u{267E}
+ \u{2680}-\u{2692}
+ \u{2694}-\u{269D}
+ \u{26A0}
+ \u{26A2}-\u{26A9}
+ \u{26AC}-\u{26BC}
+ \u{26C0}-\u{26C3}
+ \u{26E2}
+ \u{26E4}-\u{26E7}
+ \u{2700}-\u{2704}
+ \u{2706}-\u{2709}
+ \u{270C}-\u{2727}
+ \u{2729}-\u{273C}
+ \u{273E}-\u{274B}
+ \u{274D}
+ \u{274F}-\u{2752}
+ \u{2756}
+ \u{2758}-\u{2775}
+ \u{2780}-\u{2794}
+ \u{2798}-\u{27AF}
+ \u{27B1}-\u{27BE}
+ \u{27C0}-\u{27E5}
+ \u{27EE}-\u{2984}
+ \u{2987}-\u{2B1A}
+ \u{2B1D}-\u{2B4F}
+ \u{2B51}-\u{2B54}
+ \u{2B5A}-\u{2B73}
+ \u{2B76}-\u{2B95}
+ \u{2B97}-\u{2C2E}
+ \u{2C30}-\u{2C5E}
+ \u{2C60}-\u{2CF3}
+ \u{2CF9}-\u{2D25}
+ \u{2D27}
+ \u{2D2D}
+ \u{2D30}-\u{2D67}
+ \u{2D6F}-\u{2D70}
+ \u{2D7F}-\u{2D96}
+ \u{2DA0}-\u{2DA6}
+ \u{2DA8}-\u{2DAE}
+ \u{2DB0}-\u{2DB6}
+ \u{2DB8}-\u{2DBE}
+ \u{2DC0}-\u{2DC6}
+ \u{2DC8}-\u{2DCE}
+ \u{2DD0}-\u{2DD6}
+ \u{2DD8}-\u{2DDE}
+ \u{2DE0}-\u{2E52}
+ \u{303F}
+ \u{4DC0}-\u{4DFF}
+ \u{A4D0}-\u{A62B}
+ \u{A640}-\u{A6F7}
+ \u{A700}-\u{A7BF}
+ \u{A7C2}-\u{A7CA}
+ \u{A7F5}-\u{A82C}
+ \u{A830}-\u{A839}
+ \u{A840}-\u{A877}
+ \u{A880}-\u{A8C5}
+ \u{A8CE}-\u{A8D9}
+ \u{A8E0}-\u{A953}
+ \u{A95F}
+ \u{A980}-\u{A9CD}
+ \u{A9CF}-\u{A9D9}
+ \u{A9DE}-\u{A9FE}
+ \u{AA00}-\u{AA36}
+ \u{AA40}-\u{AA4D}
+ \u{AA50}-\u{AA59}
+ \u{AA5C}-\u{AAC2}
+ \u{AADB}-\u{AAF6}
+ \u{AB01}-\u{AB06}
+ \u{AB09}-\u{AB0E}
+ \u{AB11}-\u{AB16}
+ \u{AB20}-\u{AB26}
+ \u{AB28}-\u{AB2E}
+ \u{AB30}-\u{AB6B}
+ \u{AB70}-\u{ABED}
+ \u{ABF0}-\u{ABF9}
+ \u{D7B0}-\u{D7C6}
+ \u{D7CB}-\u{D7FB}
+ \u{FB00}-\u{FB06}
+ \u{FB13}-\u{FB17}
+ \u{FB1D}-\u{FB36}
+ \u{FB38}-\u{FB3C}
+ \u{FB3E}
+ \u{FB40}-\u{FB41}
+ \u{FB43}-\u{FB44}
+ \u{FB46}-\u{FBC1}
+ \u{FBD3}-\u{FD3F}
+ \u{FD50}-\u{FD8F}
+ \u{FD92}-\u{FDC7}
+ \u{FDF0}-\u{FDFD}
+ \u{FE20}-\u{FE2F}
+ \u{FE70}-\u{FE74}
+ \u{FE76}-\u{FEFC}
+ \u{FEFF}
+ \u{FFF9}-\u{FFFC}
+ \u{10000}-\u{1000B}
+ \u{1000D}-\u{10026}
+ \u{10028}-\u{1003A}
+ \u{1003C}-\u{1003D}
+ \u{1003F}-\u{1004D}
+ \u{10050}-\u{1005D}
+ \u{10080}-\u{100FA}
+ \u{10100}-\u{10102}
+ \u{10107}-\u{10133}
+ \u{10137}-\u{1018E}
+ \u{10190}-\u{1019C}
+ \u{101A0}
+ \u{101D0}-\u{101FD}
+ \u{10280}-\u{1029C}
+ \u{102A0}-\u{102D0}
+ \u{102E0}-\u{102FB}
+ \u{10300}-\u{10323}
+ \u{1032D}-\u{1034A}
+ \u{10350}-\u{1037A}
+ \u{10380}-\u{1039D}
+ \u{1039F}-\u{103C3}
+ \u{103C8}-\u{103D5}
+ \u{10400}-\u{1049D}
+ \u{104A0}-\u{104A9}
+ \u{104B0}-\u{104D3}
+ \u{104D8}-\u{104FB}
+ \u{10500}-\u{10527}
+ \u{10530}-\u{10563}
+ \u{1056F}
+ \u{10600}-\u{10736}
+ \u{10740}-\u{10755}
+ \u{10760}-\u{10767}
+ \u{10800}-\u{10805}
+ \u{10808}
+ \u{1080A}-\u{10835}
+ \u{10837}-\u{10838}
+ \u{1083C}
+ \u{1083F}-\u{10855}
+ \u{10857}-\u{1089E}
+ \u{108A7}-\u{108AF}
+ \u{108E0}-\u{108F2}
+ \u{108F4}-\u{108F5}
+ \u{108FB}-\u{1091B}
+ \u{1091F}-\u{10939}
+ \u{1093F}
+ \u{10980}-\u{109B7}
+ \u{109BC}-\u{109CF}
+ \u{109D2}-\u{10A03}
+ \u{10A05}-\u{10A06}
+ \u{10A0C}-\u{10A13}
+ \u{10A15}-\u{10A17}
+ \u{10A19}-\u{10A35}
+ \u{10A38}-\u{10A3A}
+ \u{10A3F}-\u{10A48}
+ \u{10A50}-\u{10A58}
+ \u{10A60}-\u{10A9F}
+ \u{10AC0}-\u{10AE6}
+ \u{10AEB}-\u{10AF6}
+ \u{10B00}-\u{10B35}
+ \u{10B39}-\u{10B55}
+ \u{10B58}-\u{10B72}
+ \u{10B78}-\u{10B91}
+ \u{10B99}-\u{10B9C}
+ \u{10BA9}-\u{10BAF}
+ \u{10C00}-\u{10C48}
+ \u{10C80}-\u{10CB2}
+ \u{10CC0}-\u{10CF2}
+ \u{10CFA}-\u{10D27}
+ \u{10D30}-\u{10D39}
+ \u{10E60}-\u{10E7E}
+ \u{10E80}-\u{10EA9}
+ \u{10EAB}-\u{10EAD}
+ \u{10EB0}-\u{10EB1}
+ \u{10F00}-\u{10F27}
+ \u{10F30}-\u{10F59}
+ \u{10FB0}-\u{10FCB}
+ \u{10FE0}-\u{10FF6}
+ \u{11000}-\u{1104D}
+ \u{11052}-\u{1106F}
+ \u{1107F}-\u{110C1}
+ \u{110CD}
+ \u{110D0}-\u{110E8}
+ \u{110F0}-\u{110F9}
+ \u{11100}-\u{11134}
+ \u{11136}-\u{11147}
+ \u{11150}-\u{11176}
+ \u{11180}-\u{111DF}
+ \u{111E1}-\u{111F4}
+ \u{11200}-\u{11211}
+ \u{11213}-\u{1123E}
+ \u{11280}-\u{11286}
+ \u{11288}
+ \u{1128A}-\u{1128D}
+ \u{1128F}-\u{1129D}
+ \u{1129F}-\u{112A9}
+ \u{112B0}-\u{112EA}
+ \u{112F0}-\u{112F9}
+ \u{11300}-\u{11303}
+ \u{11305}-\u{1130C}
+ \u{1130F}-\u{11310}
+ \u{11313}-\u{11328}
+ \u{1132A}-\u{11330}
+ \u{11332}-\u{11333}
+ \u{11335}-\u{11339}
+ \u{1133B}-\u{11344}
+ \u{11347}-\u{11348}
+ \u{1134B}-\u{1134D}
+ \u{11350}
+ \u{11357}
+ \u{1135D}-\u{11363}
+ \u{11366}-\u{1136C}
+ \u{11370}-\u{11374}
+ \u{11400}-\u{1145B}
+ \u{1145D}-\u{11461}
+ \u{11480}-\u{114C7}
+ \u{114D0}-\u{114D9}
+ \u{11580}-\u{115B5}
+ \u{115B8}-\u{115DD}
+ \u{11600}-\u{11644}
+ \u{11650}-\u{11659}
+ \u{11660}-\u{1166C}
+ \u{11680}-\u{116B8}
+ \u{116C0}-\u{116C9}
+ \u{11700}-\u{1171A}
+ \u{1171D}-\u{1172B}
+ \u{11730}-\u{1173F}
+ \u{11800}-\u{1183B}
+ \u{118A0}-\u{118F2}
+ \u{118FF}-\u{11906}
+ \u{11909}
+ \u{1190C}-\u{11913}
+ \u{11915}-\u{11916}
+ \u{11918}-\u{11935}
+ \u{11937}-\u{11938}
+ \u{1193B}-\u{11946}
+ \u{11950}-\u{11959}
+ \u{119A0}-\u{119A7}
+ \u{119AA}-\u{119D7}
+ \u{119DA}-\u{119E4}
+ \u{11A00}-\u{11A47}
+ \u{11A50}-\u{11AA2}
+ \u{11AC0}-\u{11AF8}
+ \u{11C00}-\u{11C08}
+ \u{11C0A}-\u{11C36}
+ \u{11C38}-\u{11C45}
+ \u{11C50}-\u{11C6C}
+ \u{11C70}-\u{11C8F}
+ \u{11C92}-\u{11CA7}
+ \u{11CA9}-\u{11CB6}
+ \u{11D00}-\u{11D06}
+ \u{11D08}-\u{11D09}
+ \u{11D0B}-\u{11D36}
+ \u{11D3A}
+ \u{11D3C}-\u{11D3D}
+ \u{11D3F}-\u{11D47}
+ \u{11D50}-\u{11D59}
+ \u{11D60}-\u{11D65}
+ \u{11D67}-\u{11D68}
+ \u{11D6A}-\u{11D8E}
+ \u{11D90}-\u{11D91}
+ \u{11D93}-\u{11D98}
+ \u{11DA0}-\u{11DA9}
+ \u{11EE0}-\u{11EF8}
+ \u{11FB0}
+ \u{11FC0}-\u{11FF1}
+ \u{11FFF}-\u{12399}
+ \u{12400}-\u{1246E}
+ \u{12470}-\u{12474}
+ \u{12480}-\u{12543}
+ \u{13000}-\u{1342E}
+ \u{13430}-\u{13438}
+ \u{14400}-\u{14646}
+ \u{16800}-\u{16A38}
+ \u{16A40}-\u{16A5E}
+ \u{16A60}-\u{16A69}
+ \u{16A6E}-\u{16A6F}
+ \u{16AD0}-\u{16AED}
+ \u{16AF0}-\u{16AF5}
+ \u{16B00}-\u{16B45}
+ \u{16B50}-\u{16B59}
+ \u{16B5B}-\u{16B61}
+ \u{16B63}-\u{16B77}
+ \u{16B7D}-\u{16B8F}
+ \u{16E40}-\u{16E9A}
+ \u{16F00}-\u{16F4A}
+ \u{16F4F}-\u{16F87}
+ \u{16F8F}-\u{16F9F}
+ \u{1BC00}-\u{1BC6A}
+ \u{1BC70}-\u{1BC7C}
+ \u{1BC80}-\u{1BC88}
+ \u{1BC90}-\u{1BC99}
+ \u{1BC9C}-\u{1BCA3}
+ \u{1D000}-\u{1D0F5}
+ \u{1D100}-\u{1D126}
+ \u{1D129}-\u{1D1E8}
+ \u{1D200}-\u{1D245}
+ \u{1D2E0}-\u{1D2F3}
+ \u{1D300}-\u{1D356}
+ \u{1D360}-\u{1D378}
+ \u{1D400}-\u{1D454}
+ \u{1D456}-\u{1D49C}
+ \u{1D49E}-\u{1D49F}
+ \u{1D4A2}
+ \u{1D4A5}-\u{1D4A6}
+ \u{1D4A9}-\u{1D4AC}
+ \u{1D4AE}-\u{1D4B9}
+ \u{1D4BB}
+ \u{1D4BD}-\u{1D4C3}
+ \u{1D4C5}-\u{1D505}
+ \u{1D507}-\u{1D50A}
+ \u{1D50D}-\u{1D514}
+ \u{1D516}-\u{1D51C}
+ \u{1D51E}-\u{1D539}
+ \u{1D53B}-\u{1D53E}
+ \u{1D540}-\u{1D544}
+ \u{1D546}
+ \u{1D54A}-\u{1D550}
+ \u{1D552}-\u{1D6A5}
+ \u{1D6A8}-\u{1D7CB}
+ \u{1D7CE}-\u{1DA8B}
+ \u{1DA9B}-\u{1DA9F}
+ \u{1DAA1}-\u{1DAAF}
+ \u{1E000}-\u{1E006}
+ \u{1E008}-\u{1E018}
+ \u{1E01B}-\u{1E021}
+ \u{1E023}-\u{1E024}
+ \u{1E026}-\u{1E02A}
+ \u{1E100}-\u{1E12C}
+ \u{1E130}-\u{1E13D}
+ \u{1E140}-\u{1E149}
+ \u{1E14E}-\u{1E14F}
+ \u{1E2C0}-\u{1E2F9}
+ \u{1E2FF}
+ \u{1E800}-\u{1E8C4}
+ \u{1E8C7}-\u{1E8D6}
+ \u{1E900}-\u{1E94B}
+ \u{1E950}-\u{1E959}
+ \u{1E95E}-\u{1E95F}
+ \u{1EC71}-\u{1ECB4}
+ \u{1ED01}-\u{1ED3D}
+ \u{1EE00}-\u{1EE03}
+ \u{1EE05}-\u{1EE1F}
+ \u{1EE21}-\u{1EE22}
+ \u{1EE24}
+ \u{1EE27}
+ \u{1EE29}-\u{1EE32}
+ \u{1EE34}-\u{1EE37}
+ \u{1EE39}
+ \u{1EE3B}
+ \u{1EE42}
+ \u{1EE47}
+ \u{1EE49}
+ \u{1EE4B}
+ \u{1EE4D}-\u{1EE4F}
+ \u{1EE51}-\u{1EE52}
+ \u{1EE54}
+ \u{1EE57}
+ \u{1EE59}
+ \u{1EE5B}
+ \u{1EE5D}
+ \u{1EE5F}
+ \u{1EE61}-\u{1EE62}
+ \u{1EE64}
+ \u{1EE67}-\u{1EE6A}
+ \u{1EE6C}-\u{1EE72}
+ \u{1EE74}-\u{1EE77}
+ \u{1EE79}-\u{1EE7C}
+ \u{1EE7E}
+ \u{1EE80}-\u{1EE89}
+ \u{1EE8B}-\u{1EE9B}
+ \u{1EEA1}-\u{1EEA3}
+ \u{1EEA5}-\u{1EEA9}
+ \u{1EEAB}-\u{1EEBB}
+ \u{1EEF0}-\u{1EEF1}
+ \u{1F000}-\u{1F003}
+ \u{1F005}-\u{1F02B}
+ \u{1F030}-\u{1F093}
+ \u{1F0A0}-\u{1F0AE}
+ \u{1F0B1}-\u{1F0BF}
+ \u{1F0C1}-\u{1F0CE}
+ \u{1F0D1}-\u{1F0F5}
+ \u{1F10B}-\u{1F10F}
+ \u{1F12E}-\u{1F12F}
+ \u{1F16A}-\u{1F16F}
+ \u{1F1AD}
+ \u{1F1E6}-\u{1F1FF}
+ \u{1F321}-\u{1F32C}
+ \u{1F336}
+ \u{1F37D}
+ \u{1F394}-\u{1F39F}
+ \u{1F3CB}-\u{1F3CE}
+ \u{1F3D4}-\u{1F3DF}
+ \u{1F3F1}-\u{1F3F3}
+ \u{1F3F5}-\u{1F3F7}
+ \u{1F43F}
+ \u{1F441}
+ \u{1F4FD}-\u{1F4FE}
+ \u{1F53E}-\u{1F54A}
+ \u{1F54F}
+ \u{1F568}-\u{1F579}
+ \u{1F57B}-\u{1F594}
+ \u{1F597}-\u{1F5A3}
+ \u{1F5A5}-\u{1F5FA}
+ \u{1F650}-\u{1F67F}
+ \u{1F6C6}-\u{1F6CB}
+ \u{1F6CD}-\u{1F6CF}
+ \u{1F6D3}-\u{1F6D4}
+ \u{1F6E0}-\u{1F6EA}
+ \u{1F6F0}-\u{1F6F3}
+ \u{1F700}-\u{1F773}
+ \u{1F780}-\u{1F7D8}
+ \u{1F800}-\u{1F80B}
+ \u{1F810}-\u{1F847}
+ \u{1F850}-\u{1F859}
+ \u{1F860}-\u{1F887}
+ \u{1F890}-\u{1F8AD}
+ \u{1F8B0}-\u{1F8B1}
+ \u{1F900}-\u{1F90B}
+ \u{1F93B}
+ \u{1F946}
+ \u{1FA00}-\u{1FA53}
+ \u{1FA60}-\u{1FA6D}
+ \u{1FB00}-\u{1FB92}
+ \u{1FB94}-\u{1FBCA}
+ \u{1FBF0}-\u{1FBF9}
+ \u{E0001}
+ \u{E0020}-\u{E007F}
+ ).join }]/
end
diff --git a/lib/reline/version.rb b/lib/reline/version.rb
index aa0ef18145..44db465a2f 100644
--- a/lib/reline/version.rb
+++ b/lib/reline/version.rb
@@ -1,3 +1,3 @@
module Reline
- VERSION = '0.1.5'
+ VERSION = '0.2.5'
end
diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb
index 2a406e39d3..6edc68e780 100644
--- a/lib/reline/windows.rb
+++ b/lib/reline/windows.rb
@@ -9,6 +9,10 @@ class Reline::Windows
true
end
+ def self.win_legacy_console?
+ @@legacy_console
+ end
+
RAW_KEYSTROKE_CONFIG = {
[224, 72] => :ed_prev_history, # ↑
[224, 80] => :ed_next_history, # ↓
@@ -94,6 +98,26 @@ class Reline::Windows
@@GetFileInformationByHandleEx = Win32API.new('kernel32', 'GetFileInformationByHandleEx', ['L', 'I', 'P', 'L'], 'I')
@@FillConsoleOutputAttribute = Win32API.new('kernel32', 'FillConsoleOutputAttribute', ['L', 'L', 'L', 'L', 'P'], 'L')
+ @@GetConsoleMode = Win32API.new('kernel32', 'GetConsoleMode', ['L', 'P'], 'L')
+ @@SetConsoleMode = Win32API.new('kernel32', 'SetConsoleMode', ['L', 'L'], 'L')
+ ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
+
+ private_class_method def self.getconsolemode
+ mode = "\000\000\000\000"
+ @@GetConsoleMode.call(@@hConsoleHandle, mode)
+ mode.unpack1('L')
+ end
+
+ private_class_method def self.setconsolemode(mode)
+ @@SetConsoleMode.call(@@hConsoleHandle, mode)
+ end
+
+ @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
+ #if @@legacy_console
+ # setconsolemode(getconsolemode() | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+ # @@legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
+ #end
+
@@input_buf = []
@@output_buf = []
@@ -199,6 +223,20 @@ class Reline::Windows
@@output_buf.unshift(c)
end
+ def self.in_pasting?
+ not self.empty_buffer?
+ end
+
+ def self.empty_buffer?
+ if not @@input_buf.empty?
+ false
+ elsif @@kbhit.call == 0
+ true
+ else
+ false
+ end
+ end
+
def self.get_screen_size
csbi = 0.chr * 22
@@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi)
@@ -219,7 +257,9 @@ class Reline::Windows
def self.move_cursor_up(val)
if val > 0
- @@SetConsoleCursorPosition.call(@@hConsoleHandle, (cursor_pos.y - val) * 65536 + cursor_pos.x)
+ y = cursor_pos.y - val
+ y = 0 if y < 0
+ @@SetConsoleCursorPosition.call(@@hConsoleHandle, y * 65536 + cursor_pos.x)
elsif val < 0
move_cursor_down(-val)
end
@@ -227,6 +267,9 @@ class Reline::Windows
def self.move_cursor_down(val)
if val > 0
+ 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)
@@ -239,10 +282,13 @@ class Reline::Windows
cursor = csbi[4, 4].unpack('L').first
written = 0.chr * 4
@@FillConsoleOutputCharacter.call(@@hConsoleHandle, 0x20, get_screen_size.last - cursor_pos.x, cursor, written)
+ @@FillConsoleOutputAttribute.call(@@hConsoleHandle, 0, get_screen_size.last - cursor_pos.x, cursor, written)
end
def self.scroll_down(val)
return if val.zero?
+ screen_height = get_screen_size.first
+ val = screen_height - 1 if val > (screen_height - 1)
scroll_rectangle = [0, val, get_screen_size.last, get_screen_size.first].pack('s4')
destination_origin = 0 # y * 65536 + x
fill = [' '.ord, 0].pack('SS')
diff --git a/lib/resolv-replace.gemspec b/lib/resolv-replace.gemspec
new file mode 100644
index 0000000000..0dadb19007
--- /dev/null
+++ b/lib/resolv-replace.gemspec
@@ -0,0 +1,24 @@
+Gem::Specification.new do |spec|
+ spec.name = "resolv-replace"
+ spec.version = "0.1.0"
+ spec.authors = ["Tanaka Akira"]
+ spec.email = ["akr@fsij.org"]
+
+ spec.summary = %q{Replace Socket DNS with Resolv.}
+ spec.description = %q{Replace Socket DNS with Resolv.}
+ spec.homepage = "https://github.com/ruby/resolv-replace"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "resolv"
+end
diff --git a/lib/resolv.gemspec b/lib/resolv.gemspec
new file mode 100644
index 0000000000..c6a0609b51
--- /dev/null
+++ b/lib/resolv.gemspec
@@ -0,0 +1,22 @@
+Gem::Specification.new do |spec|
+ spec.name = "resolv"
+ spec.version = "0.2.1"
+ spec.authors = ["Tanaka Akira"]
+ spec.email = ["akr@fsij.org"]
+
+ spec.summary = %q{Thread-aware DNS resolver library in Ruby.}
+ spec.description = %q{Thread-aware DNS resolver library in Ruby.}
+ spec.homepage = "https://github.com/ruby/resolv"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = []
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/resolv.rb b/lib/resolv.rb
index 45b2a9323b..b69c7045ca 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -767,6 +767,7 @@ class Resolv
end
def sender(msg, data, host, port=Port)
+ host = Addrinfo.ip(host).ip_address
lazy_initialize
sock = @socks_hash[host.index(':') ? "::" : "0.0.0.0"]
return nil if !sock
@@ -2459,13 +2460,38 @@ class Resolv
\z/x
##
+ # IPv6 link local address format fe80:b:c:d:e:f:g:h%em1
+ Regex_8HexLinkLocal = /\A
+ [Ff][Ee]80
+ (?::[0-9A-Fa-f]{1,4}){7}
+ %[0-9A-Za-z]+
+ \z/x
+
+ ##
+ # Compressed IPv6 link local address format fe80::b%em1
+
+ Regex_CompressedHexLinkLocal = /\A
+ [Ff][Ee]80:
+ (?:
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::
+ ((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
+ |
+ :((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)
+ )?
+ :[0-9A-Fa-f]{1,4}%[0-9A-Za-z.]+
+ \z/x
+
+ ##
# A composite IPv6 address Regexp.
Regex = /
(?:#{Regex_8Hex}) |
(?:#{Regex_CompressedHex}) |
(?:#{Regex_6Hex4Dec}) |
- (?:#{Regex_CompressedHex4Dec})/x
+ (?:#{Regex_CompressedHex4Dec}) |
+ (?:#{Regex_8HexLinkLocal}) |
+ (?:#{Regex_CompressedHexLinkLocal})
+ /x
##
# Creates a new IPv6 address from +arg+ which may be:
diff --git a/lib/rexml/attlistdecl.rb b/lib/rexml/attlistdecl.rb
deleted file mode 100644
index 44a91d66d6..0000000000
--- a/lib/rexml/attlistdecl.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: false
-#vim:ts=2 sw=2 noexpandtab:
-require_relative 'child'
-require_relative 'source'
-
-module REXML
- # This class needs:
- # * Documentation
- # * Work! Not all types of attlists are intelligently parsed, so we just
- # spew back out what we get in. This works, but it would be better if
- # we formatted the output ourselves.
- #
- # AttlistDecls provide *just* enough support to allow namespace
- # declarations. If you need some sort of generalized support, or have an
- # interesting idea about how to map the hideous, terrible design of DTD
- # AttlistDecls onto an intuitive Ruby interface, let me know. I'm desperate
- # for anything to make DTDs more palateable.
- class AttlistDecl < Child
- include Enumerable
-
- # What is this? Got me.
- attr_reader :element_name
-
- # Create an AttlistDecl, pulling the information from a Source. Notice
- # that this isn't very convenient; to create an AttlistDecl, you basically
- # have to format it yourself, and then have the initializer parse it.
- # Sorry, but for the foreseeable future, DTD support in REXML is pretty
- # weak on convenience. Have I mentioned how much I hate DTDs?
- def initialize(source)
- super()
- if (source.kind_of? Array)
- @element_name, @pairs, @contents = *source
- end
- end
-
- # Access the attlist attribute/value pairs.
- # value = attlist_decl[ attribute_name ]
- def [](key)
- @pairs[key]
- end
-
- # Whether an attlist declaration includes the given attribute definition
- # if attlist_decl.include? "xmlns:foobar"
- def include?(key)
- @pairs.keys.include? key
- end
-
- # Iterate over the key/value pairs:
- # attlist_decl.each { |attribute_name, attribute_value| ... }
- def each(&block)
- @pairs.each(&block)
- end
-
- # Write out exactly what we got in.
- def write out, indent=-1
- out << @contents
- end
-
- def node_type
- :attlistdecl
- end
- end
-end
diff --git a/lib/rexml/attribute.rb b/lib/rexml/attribute.rb
deleted file mode 100644
index 8933a013a2..0000000000
--- a/lib/rexml/attribute.rb
+++ /dev/null
@@ -1,205 +0,0 @@
-# frozen_string_literal: false
-require_relative "namespace"
-require_relative 'text'
-
-module REXML
- # Defines an Element Attribute; IE, a attribute=value pair, as in:
- # <element attribute="value"/>. Attributes can be in their own
- # namespaces. General users of REXML will not interact with the
- # Attribute class much.
- class Attribute
- include Node
- include Namespace
-
- # The element to which this attribute belongs
- attr_reader :element
- # The normalized value of this attribute. That is, the attribute with
- # entities intact.
- attr_writer :normalized
- PATTERN = /\s*(#{NAME_STR})\s*=\s*(["'])(.*?)\2/um
-
- NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um
-
- # Constructor.
- # FIXME: The parser doesn't catch illegal characters in attributes
- #
- # first::
- # Either: an Attribute, which this new attribute will become a
- # clone of; or a String, which is the name of this attribute
- # second::
- # If +first+ is an Attribute, then this may be an Element, or nil.
- # If nil, then the Element parent of this attribute is the parent
- # of the +first+ Attribute. If the first argument is a String,
- # then this must also be a String, and is the content of the attribute.
- # If this is the content, it must be fully normalized (contain no
- # illegal characters).
- # parent::
- # Ignored unless +first+ is a String; otherwise, may be the Element
- # parent of this attribute, or nil.
- #
- #
- # Attribute.new( attribute_to_clone )
- # Attribute.new( attribute_to_clone, parent_element )
- # Attribute.new( "attr", "attr_value" )
- # Attribute.new( "attr", "attr_value", parent_element )
- def initialize( first, second=nil, parent=nil )
- @normalized = @unnormalized = @element = nil
- if first.kind_of? Attribute
- self.name = first.expanded_name
- @unnormalized = first.value
- if second.kind_of? Element
- @element = second
- else
- @element = first.element
- end
- elsif first.kind_of? String
- @element = parent
- self.name = first
- @normalized = second.to_s
- else
- raise "illegal argument #{first.class.name} to Attribute constructor"
- end
- end
-
- # Returns the namespace of the attribute.
- #
- # e = Element.new( "elns:myelement" )
- # e.add_attribute( "nsa:a", "aval" )
- # e.add_attribute( "b", "bval" )
- # e.attributes.get_attribute( "a" ).prefix # -> "nsa"
- # e.attributes.get_attribute( "b" ).prefix # -> ""
- # a = Attribute.new( "x", "y" )
- # a.prefix # -> ""
- def prefix
- super
- end
-
- # Returns the namespace URL, if defined, or nil otherwise
- #
- # e = Element.new("el")
- # e.add_namespace("ns", "http://url")
- # e.add_attribute("ns:a", "b")
- # e.add_attribute("nsx:a", "c")
- # e.attribute("ns:a").namespace # => "http://url"
- # e.attribute("nsx:a").namespace # => nil
- #
- # This method always returns "" for no namespace attribute. Because
- # the default namespace doesn't apply to attribute names.
- #
- # From https://www.w3.org/TR/xml-names/#uniqAttrs
- #
- # > the default namespace does not apply to attribute names
- #
- # e = REXML::Element.new("el")
- # e.add_namespace("", "http://example.com/")
- # e.namespace # => "http://example.com/"
- # e.add_attribute("a", "b")
- # e.attribute("a").namespace # => ""
- def namespace arg=nil
- arg = prefix if arg.nil?
- if arg == ""
- ""
- else
- @element.namespace(arg)
- end
- end
-
- # Returns true if other is an Attribute and has the same name and value,
- # false otherwise.
- def ==( other )
- other.kind_of?(Attribute) and other.name==name and other.value==value
- end
-
- # Creates (and returns) a hash from both the name and value
- def hash
- name.hash + value.hash
- end
-
- # Returns this attribute out as XML source, expanding the name
- #
- # a = Attribute.new( "x", "y" )
- # a.to_string # -> "x='y'"
- # b = Attribute.new( "ns:x", "y" )
- # b.to_string # -> "ns:x='y'"
- def to_string
- if @element and @element.context and @element.context[:attribute_quote] == :quote
- %Q^#@expanded_name="#{to_s().gsub(/"/, '&quot;')}"^
- else
- "#@expanded_name='#{to_s().gsub(/'/, '&apos;')}'"
- end
- end
-
- def doctype
- if @element
- doc = @element.document
- doc.doctype if doc
- end
- end
-
- # Returns the attribute value, with entities replaced
- def to_s
- return @normalized if @normalized
-
- @normalized = Text::normalize( @unnormalized, doctype )
- @unnormalized = nil
- @normalized
- end
-
- # Returns the UNNORMALIZED value of this attribute. That is, entities
- # have been expanded to their values
- def value
- return @unnormalized if @unnormalized
- @unnormalized = Text::unnormalize( @normalized, doctype )
- @normalized = nil
- @unnormalized
- end
-
- # Returns a copy of this attribute
- def clone
- Attribute.new self
- end
-
- # Sets the element of which this object is an attribute. Normally, this
- # is not directly called.
- #
- # Returns this attribute
- def element=( element )
- @element = element
-
- if @normalized
- Text.check( @normalized, NEEDS_A_SECOND_CHECK, doctype )
- end
-
- self
- end
-
- # Removes this Attribute from the tree, and returns true if successful
- #
- # This method is usually not called directly.
- def remove
- @element.attributes.delete self.name unless @element.nil?
- end
-
- # Writes this attribute (EG, puts 'key="value"' to the output)
- def write( output, indent=-1 )
- output << to_string
- end
-
- def node_type
- :attribute
- end
-
- def inspect
- rv = ""
- write( rv )
- rv
- end
-
- def xpath
- path = @element.xpath
- path += "/@#{self.expanded_name}"
- return path
- end
- end
-end
-#vim:ts=2 sw=2 noexpandtab:
diff --git a/lib/rexml/cdata.rb b/lib/rexml/cdata.rb
deleted file mode 100644
index 997f5a08db..0000000000
--- a/lib/rexml/cdata.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: false
-require_relative "text"
-
-module REXML
- class CData < Text
- START = '<![CDATA['
- STOP = ']]>'
- ILLEGAL = /(\]\]>)/
-
- # Constructor. CData is data between <![CDATA[ ... ]]>
- #
- # _Examples_
- # CData.new( source )
- # CData.new( "Here is some CDATA" )
- # CData.new( "Some unprocessed data", respect_whitespace_TF, parent_element )
- def initialize( first, whitespace=true, parent=nil )
- super( first, whitespace, parent, false, true, ILLEGAL )
- end
-
- # Make a copy of this object
- #
- # _Examples_
- # c = CData.new( "Some text" )
- # d = c.clone
- # d.to_s # -> "Some text"
- def clone
- CData.new self
- end
-
- # Returns the content of this CData object
- #
- # _Examples_
- # c = CData.new( "Some text" )
- # c.to_s # -> "Some text"
- def to_s
- @string
- end
-
- def value
- @string
- end
-
- # == DEPRECATED
- # See the rexml/formatters package
- #
- # Generates XML output of this object
- #
- # output::
- # Where to write the string. Defaults to $stdout
- # indent::
- # The amount to indent this node by
- # transitive::
- # Ignored
- # ie_hack::
- # Ignored
- #
- # _Examples_
- # c = CData.new( " Some text " )
- # c.write( $stdout ) #-> <![CDATA[ Some text ]]>
- def write( output=$stdout, indent=-1, transitive=false, ie_hack=false )
- Kernel.warn( "#{self.class.name}.write is deprecated", uplevel: 1)
- indent( output, indent )
- output << START
- output << @string
- output << STOP
- end
- end
-end
diff --git a/lib/rexml/child.rb b/lib/rexml/child.rb
deleted file mode 100644
index cc6e9a4719..0000000000
--- a/lib/rexml/child.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-# frozen_string_literal: false
-require_relative "node"
-
-module REXML
- ##
- # A Child object is something contained by a parent, and this class
- # contains methods to support that. Most user code will not use this
- # class directly.
- class Child
- include Node
- attr_reader :parent # The Parent of this object
-
- # Constructor. Any inheritors of this class should call super to make
- # sure this method is called.
- # parent::
- # if supplied, the parent of this child will be set to the
- # supplied value, and self will be added to the parent
- def initialize( parent = nil )
- @parent = nil
- # Declare @parent, but don't define it. The next line sets the
- # parent.
- parent.add( self ) if parent
- end
-
- # Replaces this object with another object. Basically, calls
- # Parent.replace_child
- #
- # Returns:: self
- def replace_with( child )
- @parent.replace_child( self, child )
- self
- end
-
- # Removes this child from the parent.
- #
- # Returns:: self
- def remove
- unless @parent.nil?
- @parent.delete self
- end
- self
- end
-
- # Sets the parent of this child to the supplied argument.
- #
- # other::
- # Must be a Parent object. If this object is the same object as the
- # existing parent of this child, no action is taken. Otherwise, this
- # child is removed from the current parent (if one exists), and is added
- # to the new parent.
- # Returns:: The parent added
- def parent=( other )
- return @parent if @parent == other
- @parent.delete self if defined? @parent and @parent
- @parent = other
- end
-
- alias :next_sibling :next_sibling_node
- alias :previous_sibling :previous_sibling_node
-
- # Sets the next sibling of this child. This can be used to insert a child
- # after some other child.
- # a = Element.new("a")
- # b = a.add_element("b")
- # c = Element.new("c")
- # b.next_sibling = c
- # # => <a><b/><c/></a>
- def next_sibling=( other )
- parent.insert_after self, other
- end
-
- # Sets the previous sibling of this child. This can be used to insert a
- # child before some other child.
- # a = Element.new("a")
- # b = a.add_element("b")
- # c = Element.new("c")
- # b.previous_sibling = c
- # # => <a><b/><c/></a>
- def previous_sibling=(other)
- parent.insert_before self, other
- end
-
- # Returns:: the document this child belongs to, or nil if this child
- # belongs to no document
- def document
- return parent.document unless parent.nil?
- nil
- end
-
- # This doesn't yet handle encodings
- def bytes
- document.encoding
-
- to_s
- end
- end
-end
diff --git a/lib/rexml/comment.rb b/lib/rexml/comment.rb
deleted file mode 100644
index 52c58b46f6..0000000000
--- a/lib/rexml/comment.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: false
-require_relative "child"
-
-module REXML
- ##
- # Represents an XML comment; that is, text between \<!-- ... -->
- class Comment < Child
- include Comparable
- START = "<!--"
- STOP = "-->"
-
- # The content text
-
- attr_accessor :string
-
- ##
- # Constructor. The first argument can be one of three types:
- # @param first If String, the contents of this comment are set to the
- # argument. If Comment, the argument is duplicated. If
- # Source, the argument is scanned for a comment.
- # @param second If the first argument is a Source, this argument
- # should be nil, not supplied, or a Parent to be set as the parent
- # of this object
- def initialize( first, second = nil )
- super(second)
- if first.kind_of? String
- @string = first
- elsif first.kind_of? Comment
- @string = first.string
- end
- end
-
- def clone
- Comment.new self
- end
-
- # == DEPRECATED
- # See REXML::Formatters
- #
- # output::
- # Where to write the string
- # indent::
- # An integer. If -1, no indenting will be used; otherwise, the
- # indentation will be this number of spaces, and children will be
- # indented an additional amount.
- # transitive::
- # Ignored by this class. The contents of comments are never modified.
- # ie_hack::
- # Needed for conformity to the child API, but not used by this class.
- def write( output, indent=-1, transitive=false, ie_hack=false )
- Kernel.warn("Comment.write is deprecated. See REXML::Formatters", uplevel: 1)
- indent( output, indent )
- output << START
- output << @string
- output << STOP
- end
-
- alias :to_s :string
-
- ##
- # Compares this Comment to another; the contents of the comment are used
- # in the comparison.
- def <=>(other)
- other.to_s <=> @string
- end
-
- ##
- # Compares this Comment to another; the contents of the comment are used
- # in the comparison.
- def ==( other )
- other.kind_of? Comment and
- (other <=> self) == 0
- end
-
- def node_type
- :comment
- end
- end
-end
-#vim:ts=2 sw=2 noexpandtab:
diff --git a/lib/rexml/doctype.rb b/lib/rexml/doctype.rb
deleted file mode 100644
index a4e91529ac..0000000000
--- a/lib/rexml/doctype.rb
+++ /dev/null
@@ -1,320 +0,0 @@
-# frozen_string_literal: false
-require_relative "parent"
-require_relative "parseexception"
-require_relative "namespace"
-require_relative 'entity'
-require_relative 'attlistdecl'
-require_relative 'xmltokens'
-
-module REXML
- class ReferenceWriter
- def initialize(id_type,
- public_id_literal,
- system_literal,
- context=nil)
- @id_type = id_type
- @public_id_literal = public_id_literal
- @system_literal = system_literal
- if context and context[:prologue_quote] == :apostrophe
- @default_quote = "'"
- else
- @default_quote = "\""
- end
- end
-
- def write(output)
- output << " #{@id_type}"
- if @public_id_literal
- if @public_id_literal.include?("'")
- quote = "\""
- else
- quote = @default_quote
- end
- output << " #{quote}#{@public_id_literal}#{quote}"
- end
- if @system_literal
- if @system_literal.include?("'")
- quote = "\""
- elsif @system_literal.include?("\"")
- quote = "'"
- else
- quote = @default_quote
- end
- output << " #{quote}#{@system_literal}#{quote}"
- end
- end
- end
-
- # Represents an XML DOCTYPE declaration; that is, the contents of <!DOCTYPE
- # ... >. DOCTYPES can be used to declare the DTD of a document, as well as
- # being used to declare entities used in the document.
- class DocType < Parent
- include XMLTokens
- START = "<!DOCTYPE"
- STOP = ">"
- SYSTEM = "SYSTEM"
- PUBLIC = "PUBLIC"
- DEFAULT_ENTITIES = {
- 'gt'=>EntityConst::GT,
- 'lt'=>EntityConst::LT,
- 'quot'=>EntityConst::QUOT,
- "apos"=>EntityConst::APOS
- }
-
- # name is the name of the doctype
- # external_id is the referenced DTD, if given
- attr_reader :name, :external_id, :entities, :namespaces
-
- # Constructor
- #
- # dt = DocType.new( 'foo', '-//I/Hate/External/IDs' )
- # # <!DOCTYPE foo '-//I/Hate/External/IDs'>
- # dt = DocType.new( doctype_to_clone )
- # # Incomplete. Shallow clone of doctype
- #
- # +Note+ that the constructor:
- #
- # Doctype.new( Source.new( "<!DOCTYPE foo 'bar'>" ) )
- #
- # is _deprecated_. Do not use it. It will probably disappear.
- def initialize( first, parent=nil )
- @entities = DEFAULT_ENTITIES
- @long_name = @uri = nil
- if first.kind_of? String
- super()
- @name = first
- @external_id = parent
- elsif first.kind_of? DocType
- super( parent )
- @name = first.name
- @external_id = first.external_id
- @long_name = first.instance_variable_get(:@long_name)
- @uri = first.instance_variable_get(:@uri)
- elsif first.kind_of? Array
- super( parent )
- @name = first[0]
- @external_id = first[1]
- @long_name = first[2]
- @uri = first[3]
- elsif first.kind_of? Source
- super( parent )
- parser = Parsers::BaseParser.new( first )
- event = parser.pull
- if event[0] == :start_doctype
- @name, @external_id, @long_name, @uri, = event[1..-1]
- end
- else
- super()
- end
- end
-
- def node_type
- :doctype
- end
-
- def attributes_of element
- rv = []
- each do |child|
- child.each do |key,val|
- rv << Attribute.new(key,val)
- end if child.kind_of? AttlistDecl and child.element_name == element
- end
- rv
- end
-
- def attribute_of element, attribute
- att_decl = find do |child|
- child.kind_of? AttlistDecl and
- child.element_name == element and
- child.include? attribute
- end
- return nil unless att_decl
- att_decl[attribute]
- end
-
- def clone
- DocType.new self
- end
-
- # output::
- # Where to write the string
- # indent::
- # An integer. If -1, no indentation will be used; otherwise, the
- # indentation will be this number of spaces, and children will be
- # indented an additional amount.
- # transitive::
- # Ignored
- # ie_hack::
- # Ignored
- def write( output, indent=0, transitive=false, ie_hack=false )
- f = REXML::Formatters::Default.new
- indent( output, indent )
- output << START
- output << ' '
- output << @name
- if @external_id
- reference_writer = ReferenceWriter.new(@external_id,
- @long_name,
- @uri,
- context)
- reference_writer.write(output)
- end
- unless @children.empty?
- output << ' ['
- @children.each { |child|
- output << "\n"
- f.write( child, output )
- }
- output << "\n]"
- end
- output << STOP
- end
-
- def context
- if @parent
- @parent.context
- else
- nil
- end
- end
-
- def entity( name )
- @entities[name].unnormalized if @entities[name]
- end
-
- def add child
- super(child)
- @entities = DEFAULT_ENTITIES.clone if @entities == DEFAULT_ENTITIES
- @entities[ child.name ] = child if child.kind_of? Entity
- end
-
- # This method retrieves the public identifier identifying the document's
- # DTD.
- #
- # Method contributed by Henrik Martensson
- def public
- case @external_id
- when "SYSTEM"
- nil
- when "PUBLIC"
- strip_quotes(@long_name)
- end
- end
-
- # This method retrieves the system identifier identifying the document's DTD
- #
- # Method contributed by Henrik Martensson
- def system
- case @external_id
- when "SYSTEM"
- strip_quotes(@long_name)
- when "PUBLIC"
- @uri.kind_of?(String) ? strip_quotes(@uri) : nil
- end
- end
-
- # This method returns a list of notations that have been declared in the
- # _internal_ DTD subset. Notations in the external DTD subset are not
- # listed.
- #
- # Method contributed by Henrik Martensson
- def notations
- children().select {|node| node.kind_of?(REXML::NotationDecl)}
- end
-
- # Retrieves a named notation. Only notations declared in the internal
- # DTD subset can be retrieved.
- #
- # Method contributed by Henrik Martensson
- def notation(name)
- notations.find { |notation_decl|
- notation_decl.name == name
- }
- end
-
- private
-
- # Method contributed by Henrik Martensson
- def strip_quotes(quoted_string)
- quoted_string =~ /^[\'\"].*[\'\"]$/ ?
- quoted_string[1, quoted_string.length-2] :
- quoted_string
- end
- end
-
- # We don't really handle any of these since we're not a validating
- # parser, so we can be pretty dumb about them. All we need to be able
- # to do is spew them back out on a write()
-
- # This is an abstract class. You never use this directly; it serves as a
- # parent class for the specific declarations.
- class Declaration < Child
- def initialize src
- super()
- @string = src
- end
-
- def to_s
- @string+'>'
- end
-
- # == DEPRECATED
- # See REXML::Formatters
- #
- def write( output, indent )
- output << to_s
- end
- end
-
- public
- class ElementDecl < Declaration
- def initialize( src )
- super
- end
- end
-
- class ExternalEntity < Child
- def initialize( src )
- super()
- @entity = src
- end
- def to_s
- @entity
- end
- def write( output, indent )
- output << @entity
- end
- end
-
- class NotationDecl < Child
- attr_accessor :public, :system
- def initialize name, middle, pub, sys
- super(nil)
- @name = name
- @middle = middle
- @public = pub
- @system = sys
- end
-
- def to_s
- context = nil
- context = parent.context if parent
- notation = "<!NOTATION #{@name}"
- reference_writer = ReferenceWriter.new(@middle, @public, @system, context)
- reference_writer.write(notation)
- notation << ">"
- notation
- end
-
- def write( output, indent=-1 )
- output << to_s
- end
-
- # This method retrieves the name of the notation.
- #
- # Method contributed by Henrik Martensson
- def name
- @name
- end
- end
-end
diff --git a/lib/rexml/document.rb b/lib/rexml/document.rb
deleted file mode 100644
index adec293066..0000000000
--- a/lib/rexml/document.rb
+++ /dev/null
@@ -1,291 +0,0 @@
-# frozen_string_literal: false
-require_relative "security"
-require_relative "element"
-require_relative "xmldecl"
-require_relative "source"
-require_relative "comment"
-require_relative "doctype"
-require_relative "instruction"
-require_relative "rexml"
-require_relative "parseexception"
-require_relative "output"
-require_relative "parsers/baseparser"
-require_relative "parsers/streamparser"
-require_relative "parsers/treeparser"
-
-module REXML
- # Represents a full XML document, including PIs, a doctype, etc. A
- # Document has a single child that can be accessed by root().
- # Note that if you want to have an XML declaration written for a document
- # you create, you must add one; REXML documents do not write a default
- # declaration for you. See |DECLARATION| and |write|.
- class Document < Element
- # A convenient default XML declaration. If you want an XML declaration,
- # the easiest way to add one is mydoc << Document::DECLARATION
- # +DEPRECATED+
- # Use: mydoc << XMLDecl.default
- DECLARATION = XMLDecl.default
-
- # Constructor
- # @param source if supplied, must be a Document, String, or IO.
- # Documents have their context and Element attributes cloned.
- # Strings are expected to be valid XML documents. IOs are expected
- # to be sources of valid XML documents.
- # @param context if supplied, contains the context of the document;
- # this should be a Hash.
- def initialize( source = nil, context = {} )
- @entity_expansion_count = 0
- super()
- @context = context
- return if source.nil?
- if source.kind_of? Document
- @context = source.context
- super source
- else
- build( source )
- end
- end
-
- def node_type
- :document
- end
-
- # Should be obvious
- def clone
- Document.new self
- end
-
- # According to the XML spec, a root node has no expanded name
- def expanded_name
- ''
- #d = doc_type
- #d ? d.name : "UNDEFINED"
- end
-
- alias :name :expanded_name
-
- # We override this, because XMLDecls and DocTypes must go at the start
- # of the document
- def add( child )
- if child.kind_of? XMLDecl
- if @children[0].kind_of? XMLDecl
- @children[0] = child
- else
- @children.unshift child
- end
- child.parent = self
- elsif child.kind_of? DocType
- # Find first Element or DocType node and insert the decl right
- # before it. If there is no such node, just insert the child at the
- # end. If there is a child and it is an DocType, then replace it.
- insert_before_index = @children.find_index { |x|
- x.kind_of?(Element) || x.kind_of?(DocType)
- }
- if insert_before_index # Not null = not end of list
- if @children[ insert_before_index ].kind_of? DocType
- @children[ insert_before_index ] = child
- else
- @children[ insert_before_index-1, 0 ] = child
- end
- else # Insert at end of list
- @children << child
- end
- child.parent = self
- else
- rv = super
- raise "attempted adding second root element to document" if @elements.size > 1
- rv
- end
- end
- alias :<< :add
-
- def add_element(arg=nil, arg2=nil)
- rv = super
- raise "attempted adding second root element to document" if @elements.size > 1
- rv
- end
-
- # @return the root Element of the document, or nil if this document
- # has no children.
- def root
- elements[1]
- #self
- #@children.find { |item| item.kind_of? Element }
- end
-
- # @return the DocType child of the document, if one exists,
- # and nil otherwise.
- def doctype
- @children.find { |item| item.kind_of? DocType }
- end
-
- # @return the XMLDecl of this document; if no XMLDecl has been
- # set, the default declaration is returned.
- def xml_decl
- rv = @children[0]
- return rv if rv.kind_of? XMLDecl
- @children.unshift(XMLDecl.default)[0]
- end
-
- # @return the XMLDecl version of this document as a String.
- # If no XMLDecl has been set, returns the default version.
- def version
- xml_decl().version
- end
-
- # @return the XMLDecl encoding of this document as an
- # Encoding object.
- # If no XMLDecl has been set, returns the default encoding.
- def encoding
- xml_decl().encoding
- end
-
- # @return the XMLDecl standalone value of this document as a String.
- # If no XMLDecl has been set, returns the default setting.
- def stand_alone?
- xml_decl().stand_alone?
- end
-
- # :call-seq:
- # doc.write(output=$stdout, indent=-1, transtive=false, ie_hack=false, encoding=nil)
- # doc.write(options={:output => $stdout, :indent => -1, :transtive => false, :ie_hack => false, :encoding => nil})
- #
- # Write the XML tree out, optionally with indent. This writes out the
- # entire XML document, including XML declarations, doctype declarations,
- # and processing instructions (if any are given).
- #
- # A controversial point is whether Document should always write the XML
- # declaration (<?xml version='1.0'?>) whether or not one is given by the
- # user (or source document). REXML does not write one if one was not
- # specified, because it adds unnecessary bandwidth to applications such
- # as XML-RPC.
- #
- # Accept Nth argument style and options Hash style as argument.
- # The recommended style is options Hash style for one or more
- # arguments case.
- #
- # _Examples_
- # Document.new("<a><b/></a>").write
- #
- # output = ""
- # Document.new("<a><b/></a>").write(output)
- #
- # output = ""
- # Document.new("<a><b/></a>").write(:output => output, :indent => 2)
- #
- # See also the classes in the rexml/formatters package for the proper way
- # to change the default formatting of XML output.
- #
- # _Examples_
- #
- # output = ""
- # tr = Transitive.new
- # tr.write(Document.new("<a><b/></a>"), output)
- #
- # output::
- # output an object which supports '<< string'; this is where the
- # document will be written.
- # indent::
- # An integer. If -1, no indenting will be used; otherwise, the
- # indentation will be twice this number of spaces, and children will be
- # indented an additional amount. For a value of 3, every item will be
- # indented 3 more levels, or 6 more spaces (2 * 3). Defaults to -1
- # transitive::
- # If transitive is true and indent is >= 0, then the output will be
- # pretty-printed in such a way that the added whitespace does not affect
- # the absolute *value* of the document -- that is, it leaves the value
- # and number of Text nodes in the document unchanged.
- # ie_hack::
- # This hack inserts a space before the /> on empty tags to address
- # a limitation of Internet Explorer. Defaults to false
- # encoding::
- # Encoding name as String. Change output encoding to specified encoding
- # instead of encoding in XML declaration.
- # Defaults to nil. It means encoding in XML declaration is used.
- def write(*arguments)
- if arguments.size == 1 and arguments[0].class == Hash
- options = arguments[0]
-
- output = options[:output]
- indent = options[:indent]
- transitive = options[:transitive]
- ie_hack = options[:ie_hack]
- encoding = options[:encoding]
- else
- output, indent, transitive, ie_hack, encoding, = *arguments
- end
-
- output ||= $stdout
- indent ||= -1
- transitive = false if transitive.nil?
- ie_hack = false if ie_hack.nil?
- encoding ||= xml_decl.encoding
-
- if encoding != 'UTF-8' && !output.kind_of?(Output)
- output = Output.new( output, encoding )
- end
- formatter = if indent > -1
- if transitive
- require_relative "formatters/transitive"
- REXML::Formatters::Transitive.new( indent, ie_hack )
- else
- REXML::Formatters::Pretty.new( indent, ie_hack )
- end
- else
- REXML::Formatters::Default.new( ie_hack )
- end
- formatter.write( self, output )
- end
-
-
- def Document::parse_stream( source, listener )
- Parsers::StreamParser.new( source, listener ).parse
- end
-
- # Set the entity expansion limit. By default the limit is set to 10000.
- #
- # Deprecated. Use REXML::Security.entity_expansion_limit= instead.
- def Document::entity_expansion_limit=( val )
- Security.entity_expansion_limit = val
- end
-
- # Get the entity expansion limit. By default the limit is set to 10000.
- #
- # Deprecated. Use REXML::Security.entity_expansion_limit= instead.
- def Document::entity_expansion_limit
- return Security.entity_expansion_limit
- end
-
- # Set the entity expansion limit. By default the limit is set to 10240.
- #
- # Deprecated. Use REXML::Security.entity_expansion_text_limit= instead.
- def Document::entity_expansion_text_limit=( val )
- Security.entity_expansion_text_limit = val
- end
-
- # Get the entity expansion limit. By default the limit is set to 10240.
- #
- # Deprecated. Use REXML::Security.entity_expansion_text_limit instead.
- def Document::entity_expansion_text_limit
- return Security.entity_expansion_text_limit
- end
-
- attr_reader :entity_expansion_count
-
- def record_entity_expansion
- @entity_expansion_count += 1
- if @entity_expansion_count > Security.entity_expansion_limit
- raise "number of entity expansions exceeded, processing aborted."
- end
- end
-
- def document
- self
- end
-
- private
- def build( source )
- Parsers::TreeParser.new( source, self ).parse
- end
- end
-end
diff --git a/lib/rexml/dtd/attlistdecl.rb b/lib/rexml/dtd/attlistdecl.rb
deleted file mode 100644
index 1326cb21e4..0000000000
--- a/lib/rexml/dtd/attlistdecl.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: false
-require_relative "../child"
-module REXML
- module DTD
- class AttlistDecl < Child
- START = "<!ATTLIST"
- START_RE = /^\s*#{START}/um
- PATTERN_RE = /\s*(#{START}.*?>)/um
- end
- end
-end
diff --git a/lib/rexml/dtd/dtd.rb b/lib/rexml/dtd/dtd.rb
deleted file mode 100644
index 8b0f2d753a..0000000000
--- a/lib/rexml/dtd/dtd.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: false
-require_relative "elementdecl"
-require_relative "entitydecl"
-require_relative "../comment"
-require_relative "notationdecl"
-require_relative "attlistdecl"
-require_relative "../parent"
-
-module REXML
- module DTD
- class Parser
- def Parser.parse( input )
- case input
- when String
- parse_helper input
- when File
- parse_helper input.read
- end
- end
-
- # Takes a String and parses it out
- def Parser.parse_helper( input )
- contents = Parent.new
- while input.size > 0
- case input
- when ElementDecl.PATTERN_RE
- match = $&
- contents << ElementDecl.new( match )
- when AttlistDecl.PATTERN_RE
- matchdata = $~
- contents << AttlistDecl.new( matchdata )
- when EntityDecl.PATTERN_RE
- matchdata = $~
- contents << EntityDecl.new( matchdata )
- when Comment.PATTERN_RE
- matchdata = $~
- contents << Comment.new( matchdata )
- when NotationDecl.PATTERN_RE
- matchdata = $~
- contents << NotationDecl.new( matchdata )
- end
- end
- contents
- end
- end
- end
-end
diff --git a/lib/rexml/dtd/elementdecl.rb b/lib/rexml/dtd/elementdecl.rb
deleted file mode 100644
index 20ed023244..0000000000
--- a/lib/rexml/dtd/elementdecl.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: false
-require_relative "../child"
-module REXML
- module DTD
- class ElementDecl < Child
- START = "<!ELEMENT"
- START_RE = /^\s*#{START}/um
- # PATTERN_RE = /^\s*(#{START}.*?)>/um
- PATTERN_RE = /^\s*#{START}\s+((?:[:\w][-\.\w]*:)?[-!\*\.\w]*)(.*?)>/
- #\s*((((["']).*?\5)|[^\/'">]*)*?)(\/)?>/um, true)
-
- def initialize match
- @name = match[1]
- @rest = match[2]
- end
- end
- end
-end
diff --git a/lib/rexml/dtd/entitydecl.rb b/lib/rexml/dtd/entitydecl.rb
deleted file mode 100644
index 312df655ff..0000000000
--- a/lib/rexml/dtd/entitydecl.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: false
-require_relative "../child"
-module REXML
- module DTD
- class EntityDecl < Child
- START = "<!ENTITY"
- START_RE = /^\s*#{START}/um
- PUBLIC = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+PUBLIC\s+((["']).*?\3)\s+((["']).*?\5)\s*>/um
- SYSTEM = /^\s*#{START}\s+(?:%\s+)?(\w+)\s+SYSTEM\s+((["']).*?\3)(?:\s+NDATA\s+\w+)?\s*>/um
- PLAIN = /^\s*#{START}\s+(\w+)\s+((["']).*?\3)\s*>/um
- PERCENT = /^\s*#{START}\s+%\s+(\w+)\s+((["']).*?\3)\s*>/um
- # <!ENTITY name SYSTEM "...">
- # <!ENTITY name "...">
- def initialize src
- super()
- md = nil
- if src.match( PUBLIC )
- md = src.match( PUBLIC, true )
- @middle = "PUBLIC"
- @content = "#{md[2]} #{md[4]}"
- elsif src.match( SYSTEM )
- md = src.match( SYSTEM, true )
- @middle = "SYSTEM"
- @content = md[2]
- elsif src.match( PLAIN )
- md = src.match( PLAIN, true )
- @middle = ""
- @content = md[2]
- elsif src.match( PERCENT )
- md = src.match( PERCENT, true )
- @middle = ""
- @content = md[2]
- end
- raise ParseException.new("failed Entity match", src) if md.nil?
- @name = md[1]
- end
-
- def to_s
- rv = "<!ENTITY #@name "
- rv << "#@middle " if @middle.size > 0
- rv << @content
- rv
- end
-
- def write( output, indent )
- indent( output, indent )
- output << to_s
- end
-
- def EntityDecl.parse_source source, listener
- md = source.match( PATTERN_RE, true )
- thing = md[0].squeeze(" \t\n\r")
- listener.send inspect.downcase, thing
- end
- end
- end
-end
diff --git a/lib/rexml/dtd/notationdecl.rb b/lib/rexml/dtd/notationdecl.rb
deleted file mode 100644
index 04a9b08aa7..0000000000
--- a/lib/rexml/dtd/notationdecl.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: false
-require_relative "../child"
-module REXML
- module DTD
- class NotationDecl < Child
- START = "<!NOTATION"
- START_RE = /^\s*#{START}/um
- PUBLIC = /^\s*#{START}\s+(\w[\w-]*)\s+(PUBLIC)\s+((["']).*?\4)\s*>/um
- SYSTEM = /^\s*#{START}\s+(\w[\w-]*)\s+(SYSTEM)\s+((["']).*?\4)\s*>/um
- def initialize src
- super()
- if src.match( PUBLIC )
- md = src.match( PUBLIC, true )
- elsif src.match( SYSTEM )
- md = src.match( SYSTEM, true )
- else
- raise ParseException.new( "error parsing notation: no matching pattern", src )
- end
- @name = md[1]
- @middle = md[2]
- @rest = md[3]
- end
-
- def to_s
- "<!NOTATION #@name #@middle #@rest>"
- end
-
- def write( output, indent )
- indent( output, indent )
- output << to_s
- end
-
- def NotationDecl.parse_source source, listener
- md = source.match( PATTERN_RE, true )
- thing = md[0].squeeze(" \t\n\r")
- listener.send inspect.downcase, thing
- end
- end
- end
-end
diff --git a/lib/rexml/element.rb b/lib/rexml/element.rb
deleted file mode 100644
index c706a7c245..0000000000
--- a/lib/rexml/element.rb
+++ /dev/null
@@ -1,1269 +0,0 @@
-# frozen_string_literal: false
-require_relative "parent"
-require_relative "namespace"
-require_relative "attribute"
-require_relative "cdata"
-require_relative "xpath"
-require_relative "parseexception"
-
-module REXML
- # An implementation note about namespaces:
- # As we parse, when we find namespaces we put them in a hash and assign
- # them a unique ID. We then convert the namespace prefix for the node
- # to the unique ID. This makes namespace lookup much faster for the
- # cost of extra memory use. We save the namespace prefix for the
- # context node and convert it back when we write it.
- @@namespaces = {}
-
- # Represents a tagged XML element. Elements are characterized by
- # having children, attributes, and names, and can themselves be
- # children.
- class Element < Parent
- include Namespace
-
- UNDEFINED = "UNDEFINED"; # The default name
-
- # Mechanisms for accessing attributes and child elements of this
- # element.
- attr_reader :attributes, :elements
- # The context holds information about the processing environment, such as
- # whitespace handling.
- attr_accessor :context
-
- # Constructor
- # arg::
- # if not supplied, will be set to the default value.
- # If a String, the name of this object will be set to the argument.
- # If an Element, the object will be shallowly cloned; name,
- # attributes, and namespaces will be copied. Children will +not+ be
- # copied.
- # parent::
- # if supplied, must be a Parent, and will be used as
- # the parent of this object.
- # context::
- # If supplied, must be a hash containing context items. Context items
- # include:
- # * <tt>:respect_whitespace</tt> the value of this is :+all+ or an array of
- # strings being the names of the elements to respect
- # whitespace for. Defaults to :+all+.
- # * <tt>:compress_whitespace</tt> the value can be :+all+ or an array of
- # strings being the names of the elements to ignore whitespace on.
- # Overrides :+respect_whitespace+.
- # * <tt>:ignore_whitespace_nodes</tt> the value can be :+all+ or an array
- # of strings being the names of the elements in which to ignore
- # whitespace-only nodes. If this is set, Text nodes which contain only
- # whitespace will not be added to the document tree.
- # * <tt>:raw</tt> can be :+all+, or an array of strings being the names of
- # the elements to process in raw mode. In raw mode, special
- # characters in text is not converted to or from entities.
- def initialize( arg = UNDEFINED, parent=nil, context=nil )
- super(parent)
-
- @elements = Elements.new(self)
- @attributes = Attributes.new(self)
- @context = context
-
- if arg.kind_of? String
- self.name = arg
- elsif arg.kind_of? Element
- self.name = arg.expanded_name
- arg.attributes.each_attribute{ |attribute|
- @attributes << Attribute.new( attribute )
- }
- @context = arg.context
- end
- end
-
- def inspect
- rv = "<#@expanded_name"
-
- @attributes.each_attribute do |attr|
- rv << " "
- attr.write( rv, 0 )
- end
-
- if children.size > 0
- rv << "> ... </>"
- else
- rv << "/>"
- end
- end
-
-
- # Creates a shallow copy of self.
- # d = Document.new "<a><b/><b/><c><d/></c></a>"
- # new_a = d.root.clone
- # puts new_a # => "<a/>"
- def clone
- self.class.new self
- end
-
- # Evaluates to the root node of the document that this element
- # belongs to. If this element doesn't belong to a document, but does
- # belong to another Element, the parent's root will be returned, until the
- # earliest ancestor is found.
- #
- # Note that this is not the same as the document element.
- # In the following example, <a> is the document element, and the root
- # node is the parent node of the document element. You may ask yourself
- # why the root node is useful: consider the doctype and XML declaration,
- # and any processing instructions before the document element... they
- # are children of the root node, or siblings of the document element.
- # The only time this isn't true is when an Element is created that is
- # not part of any Document. In this case, the ancestor that has no
- # parent acts as the root node.
- # d = Document.new '<a><b><c/></b></a>'
- # a = d[1] ; c = a[1][1]
- # d.root_node == d # TRUE
- # a.root_node # namely, d
- # c.root_node # again, d
- def root_node
- parent.nil? ? self : parent.root_node
- end
-
- def root
- return elements[1] if self.kind_of? Document
- return self if parent.kind_of? Document or parent.nil?
- return parent.root
- end
-
- # Evaluates to the document to which this element belongs, or nil if this
- # element doesn't belong to a document.
- def document
- rt = root
- rt.parent if rt
- end
-
- # Evaluates to +true+ if whitespace is respected for this element. This
- # is the case if:
- # 1. Neither :+respect_whitespace+ nor :+compress_whitespace+ has any value
- # 2. The context has :+respect_whitespace+ set to :+all+ or
- # an array containing the name of this element, and
- # :+compress_whitespace+ isn't set to :+all+ or an array containing the
- # name of this element.
- # The evaluation is tested against +expanded_name+, and so is namespace
- # sensitive.
- def whitespace
- @whitespace = nil
- if @context
- if @context[:respect_whitespace]
- @whitespace = (@context[:respect_whitespace] == :all or
- @context[:respect_whitespace].include? expanded_name)
- end
- @whitespace = false if (@context[:compress_whitespace] and
- (@context[:compress_whitespace] == :all or
- @context[:compress_whitespace].include? expanded_name)
- )
- end
- @whitespace = true unless @whitespace == false
- @whitespace
- end
-
- def ignore_whitespace_nodes
- @ignore_whitespace_nodes = false
- if @context
- if @context[:ignore_whitespace_nodes]
- @ignore_whitespace_nodes =
- (@context[:ignore_whitespace_nodes] == :all or
- @context[:ignore_whitespace_nodes].include? expanded_name)
- end
- end
- end
-
- # Evaluates to +true+ if raw mode is set for this element. This
- # is the case if the context has :+raw+ set to :+all+ or
- # an array containing the name of this element.
- #
- # The evaluation is tested against +expanded_name+, and so is namespace
- # sensitive.
- def raw
- @raw = (@context and @context[:raw] and
- (@context[:raw] == :all or
- @context[:raw].include? expanded_name))
- @raw
- end
-
- #once :whitespace, :raw, :ignore_whitespace_nodes
-
- #################################################
- # Namespaces #
- #################################################
-
- # Evaluates to an +Array+ containing the prefixes (names) of all defined
- # namespaces at this context node.
- # doc = Document.new("<a xmlns:x='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
- # doc.elements['//b'].prefixes # -> ['x', 'y']
- def prefixes
- prefixes = []
- prefixes = parent.prefixes if parent
- prefixes |= attributes.prefixes
- return prefixes
- end
-
- def namespaces
- namespaces = {}
- namespaces = parent.namespaces if parent
- namespaces = namespaces.merge( attributes.namespaces )
- return namespaces
- end
-
- # Evaluates to the URI for a prefix, or the empty string if no such
- # namespace is declared for this element. Evaluates recursively for
- # ancestors. Returns the default namespace, if there is one.
- # prefix::
- # the prefix to search for. If not supplied, returns the default
- # namespace if one exists
- # Returns::
- # the namespace URI as a String, or nil if no such namespace
- # exists. If the namespace is undefined, returns an empty string
- # doc = Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
- # b = doc.elements['//b']
- # b.namespace # -> '1'
- # b.namespace("y") # -> '2'
- def namespace(prefix=nil)
- if prefix.nil?
- prefix = prefix()
- end
- if prefix == ''
- prefix = "xmlns"
- else
- prefix = "xmlns:#{prefix}" unless prefix[0,5] == 'xmlns'
- end
- ns = attributes[ prefix ]
- ns = parent.namespace(prefix) if ns.nil? and parent
- ns = '' if ns.nil? and prefix == 'xmlns'
- return ns
- end
-
- # Adds a namespace to this element.
- # prefix::
- # the prefix string, or the namespace URI if +uri+ is not
- # supplied
- # uri::
- # the namespace URI. May be nil, in which +prefix+ is used as
- # the URI
- # Evaluates to: this Element
- # a = Element.new("a")
- # a.add_namespace("xmlns:foo", "bar" )
- # a.add_namespace("foo", "bar") # shorthand for previous line
- # a.add_namespace("twiddle")
- # puts a #-> <a xmlns:foo='bar' xmlns='twiddle'/>
- def add_namespace( prefix, uri=nil )
- unless uri
- @attributes["xmlns"] = prefix
- else
- prefix = "xmlns:#{prefix}" unless prefix =~ /^xmlns:/
- @attributes[ prefix ] = uri
- end
- self
- end
-
- # Removes a namespace from this node. This only works if the namespace is
- # actually declared in this node. If no argument is passed, deletes the
- # default namespace.
- #
- # Evaluates to: this element
- # doc = Document.new "<a xmlns:foo='bar' xmlns='twiddle'/>"
- # doc.root.delete_namespace
- # puts doc # -> <a xmlns:foo='bar'/>
- # doc.root.delete_namespace 'foo'
- # puts doc # -> <a/>
- def delete_namespace namespace="xmlns"
- namespace = "xmlns:#{namespace}" unless namespace == 'xmlns'
- attribute = attributes.get_attribute(namespace)
- attribute.remove unless attribute.nil?
- self
- end
-
- #################################################
- # Elements #
- #################################################
-
- # Adds a child to this element, optionally setting attributes in
- # the element.
- # element::
- # optional. If Element, the element is added.
- # Otherwise, a new Element is constructed with the argument (see
- # Element.initialize).
- # attrs::
- # If supplied, must be a Hash containing String name,value
- # pairs, which will be used to set the attributes of the new Element.
- # Returns:: the Element that was added
- # el = doc.add_element 'my-tag'
- # el = doc.add_element 'my-tag', {'attr1'=>'val1', 'attr2'=>'val2'}
- # el = Element.new 'my-tag'
- # doc.add_element el
- def add_element element, attrs=nil
- raise "First argument must be either an element name, or an Element object" if element.nil?
- el = @elements.add(element)
- attrs.each do |key, value|
- el.attributes[key]=value
- end if attrs.kind_of? Hash
- el
- end
-
- # Deletes a child element.
- # element::
- # Must be an +Element+, +String+, or +Integer+. If Element,
- # the element is removed. If String, the element is found (via XPath)
- # and removed. <em>This means that any parent can remove any
- # descendant.<em> If Integer, the Element indexed by that number will be
- # removed.
- # Returns:: the element that was removed.
- # doc.delete_element "/a/b/c[@id='4']"
- # doc.delete_element doc.elements["//k"]
- # doc.delete_element 1
- def delete_element element
- @elements.delete element
- end
-
- # Evaluates to +true+ if this element has at least one child Element
- # doc = Document.new "<a><b/><c>Text</c></a>"
- # doc.root.has_elements # -> true
- # doc.elements["/a/b"].has_elements # -> false
- # doc.elements["/a/c"].has_elements # -> false
- def has_elements?
- !@elements.empty?
- end
-
- # Iterates through the child elements, yielding for each Element that
- # has a particular attribute set.
- # key::
- # the name of the attribute to search for
- # value::
- # the value of the attribute
- # max::
- # (optional) causes this method to return after yielding
- # for this number of matching children
- # name::
- # (optional) if supplied, this is an XPath that filters
- # the children to check.
- #
- # doc = Document.new "<a><b @id='1'/><c @id='2'/><d @id='1'/><e/></a>"
- # # Yields b, c, d
- # doc.root.each_element_with_attribute( 'id' ) {|e| p e}
- # # Yields b, d
- # doc.root.each_element_with_attribute( 'id', '1' ) {|e| p e}
- # # Yields b
- # doc.root.each_element_with_attribute( 'id', '1', 1 ) {|e| p e}
- # # Yields d
- # doc.root.each_element_with_attribute( 'id', '1', 0, 'd' ) {|e| p e}
- def each_element_with_attribute( key, value=nil, max=0, name=nil, &block ) # :yields: Element
- each_with_something( proc {|child|
- if value.nil?
- child.attributes[key] != nil
- else
- child.attributes[key]==value
- end
- }, max, name, &block )
- end
-
- # Iterates through the children, yielding for each Element that
- # has a particular text set.
- # text::
- # the text to search for. If nil, or not supplied, will iterate
- # over all +Element+ children that contain at least one +Text+ node.
- # max::
- # (optional) causes this method to return after yielding
- # for this number of matching children
- # name::
- # (optional) if supplied, this is an XPath that filters
- # the children to check.
- #
- # doc = Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
- # # Yields b, c, d
- # doc.each_element_with_text {|e|p e}
- # # Yields b, c
- # doc.each_element_with_text('b'){|e|p e}
- # # Yields b
- # doc.each_element_with_text('b', 1){|e|p e}
- # # Yields d
- # doc.each_element_with_text(nil, 0, 'd'){|e|p e}
- def each_element_with_text( text=nil, max=0, name=nil, &block ) # :yields: Element
- each_with_something( proc {|child|
- if text.nil?
- child.has_text?
- else
- child.text == text
- end
- }, max, name, &block )
- end
-
- # Synonym for Element.elements.each
- def each_element( xpath=nil, &block ) # :yields: Element
- @elements.each( xpath, &block )
- end
-
- # Synonym for Element.to_a
- # This is a little slower than calling elements.each directly.
- # xpath:: any XPath by which to search for elements in the tree
- # Returns:: an array of Elements that match the supplied path
- def get_elements( xpath )
- @elements.to_a( xpath )
- end
-
- # Returns the next sibling that is an element, or nil if there is
- # no Element sibling after this one
- # doc = Document.new '<a><b/>text<c/></a>'
- # doc.root.elements['b'].next_element #-> <c/>
- # doc.root.elements['c'].next_element #-> nil
- def next_element
- element = next_sibling
- element = element.next_sibling until element.nil? or element.kind_of? Element
- return element
- end
-
- # Returns the previous sibling that is an element, or nil if there is
- # no Element sibling prior to this one
- # doc = Document.new '<a><b/>text<c/></a>'
- # doc.root.elements['c'].previous_element #-> <b/>
- # doc.root.elements['b'].previous_element #-> nil
- def previous_element
- element = previous_sibling
- element = element.previous_sibling until element.nil? or element.kind_of? Element
- return element
- end
-
-
- #################################################
- # Text #
- #################################################
-
- # Evaluates to +true+ if this element has at least one Text child
- def has_text?
- not text().nil?
- end
-
- # A convenience method which returns the String value of the _first_
- # child text element, if one exists, and +nil+ otherwise.
- #
- # <em>Note that an element may have multiple Text elements, perhaps
- # separated by other children</em>. Be aware that this method only returns
- # the first Text node.
- #
- # This method returns the +value+ of the first text child node, which
- # ignores the +raw+ setting, so always returns normalized text. See
- # the Text::value documentation.
- #
- # doc = Document.new "<p>some text <b>this is bold!</b> more text</p>"
- # # The element 'p' has two text elements, "some text " and " more text".
- # doc.root.text #-> "some text "
- def text( path = nil )
- rv = get_text(path)
- return rv.value unless rv.nil?
- nil
- end
-
- # Returns the first child Text node, if any, or +nil+ otherwise.
- # This method returns the actual +Text+ node, rather than the String content.
- # doc = Document.new "<p>some text <b>this is bold!</b> more text</p>"
- # # The element 'p' has two text elements, "some text " and " more text".
- # doc.root.get_text.value #-> "some text "
- def get_text path = nil
- rv = nil
- if path
- element = @elements[ path ]
- rv = element.get_text unless element.nil?
- else
- rv = @children.find { |node| node.kind_of? Text }
- end
- return rv
- end
-
- # Sets the first Text child of this object. See text() for a
- # discussion about Text children.
- #
- # If a Text child already exists, the child is replaced by this
- # content. This means that Text content can be deleted by calling
- # this method with a nil argument. In this case, the next Text
- # child becomes the first Text child. In no case is the order of
- # any siblings disturbed.
- # text::
- # If a String, a new Text child is created and added to
- # this Element as the first Text child. If Text, the text is set
- # as the first Child element. If nil, then any existing first Text
- # child is removed.
- # Returns:: this Element.
- # doc = Document.new '<a><b/></a>'
- # doc.root.text = 'Sean' #-> '<a><b/>Sean</a>'
- # doc.root.text = 'Elliott' #-> '<a><b/>Elliott</a>'
- # doc.root.add_element 'c' #-> '<a><b/>Elliott<c/></a>'
- # doc.root.text = 'Russell' #-> '<a><b/>Russell<c/></a>'
- # doc.root.text = nil #-> '<a><b/><c/></a>'
- def text=( text )
- if text.kind_of? String
- text = Text.new( text, whitespace(), nil, raw() )
- elsif !text.nil? and !text.kind_of? Text
- text = Text.new( text.to_s, whitespace(), nil, raw() )
- end
- old_text = get_text
- if text.nil?
- old_text.remove unless old_text.nil?
- else
- if old_text.nil?
- self << text
- else
- old_text.replace_with( text )
- end
- end
- return self
- end
-
- # A helper method to add a Text child. Actual Text instances can
- # be added with regular Parent methods, such as add() and <<()
- # text::
- # if a String, a new Text instance is created and added
- # to the parent. If Text, the object is added directly.
- # Returns:: this Element
- # e = Element.new('a') #-> <e/>
- # e.add_text 'foo' #-> <e>foo</e>
- # e.add_text Text.new(' bar') #-> <e>foo bar</e>
- # Note that at the end of this example, the branch has <b>3</b> nodes; the 'e'
- # element and <b>2</b> Text node children.
- def add_text( text )
- if text.kind_of? String
- if @children[-1].kind_of? Text
- @children[-1] << text
- return
- end
- text = Text.new( text, whitespace(), nil, raw() )
- end
- self << text unless text.nil?
- return self
- end
-
- def node_type
- :element
- end
-
- def xpath
- path_elements = []
- cur = self
- path_elements << __to_xpath_helper( self )
- while cur.parent
- cur = cur.parent
- path_elements << __to_xpath_helper( cur )
- end
- return path_elements.reverse.join( "/" )
- end
-
- #################################################
- # Attributes #
- #################################################
-
- # Fetches an attribute value or a child.
- #
- # If String or Symbol is specified, it's treated as attribute
- # name. Attribute value as String or +nil+ is returned. This case
- # is shortcut of +attributes[name]+.
- #
- # If Integer is specified, it's treated as the index of
- # child. It returns Nth child.
- #
- # doc = REXML::Document.new("<a attr='1'><b/><c/></a>")
- # doc.root["attr"] # => "1"
- # doc.root.attributes["attr"] # => "1"
- # doc.root[1] # => <c/>
- def [](name_or_index)
- case name_or_index
- when String
- attributes[name_or_index]
- when Symbol
- attributes[name_or_index.to_s]
- else
- super
- end
- end
-
- def attribute( name, namespace=nil )
- prefix = nil
- if namespaces.respond_to? :key
- prefix = namespaces.key(namespace) if namespace
- else
- prefix = namespaces.index(namespace) if namespace
- end
- prefix = nil if prefix == 'xmlns'
-
- ret_val =
- attributes.get_attribute( "#{prefix ? prefix + ':' : ''}#{name}" )
-
- return ret_val unless ret_val.nil?
- return nil if prefix.nil?
-
- # now check that prefix'es namespace is not the same as the
- # default namespace
- return nil unless ( namespaces[ prefix ] == namespaces[ 'xmlns' ] )
-
- attributes.get_attribute( name )
-
- end
-
- # Evaluates to +true+ if this element has any attributes set, false
- # otherwise.
- def has_attributes?
- return !@attributes.empty?
- end
-
- # Adds an attribute to this element, overwriting any existing attribute
- # by the same name.
- # key::
- # can be either an Attribute or a String. If an Attribute,
- # the attribute is added to the list of Element attributes. If String,
- # the argument is used as the name of the new attribute, and the value
- # parameter must be supplied.
- # value::
- # Required if +key+ is a String, and ignored if the first argument is
- # an Attribute. This is a String, and is used as the value
- # of the new Attribute. This should be the unnormalized value of the
- # attribute (without entities).
- # Returns:: the Attribute added
- # e = Element.new 'e'
- # e.add_attribute( 'a', 'b' ) #-> <e a='b'/>
- # e.add_attribute( 'x:a', 'c' ) #-> <e a='b' x:a='c'/>
- # e.add_attribute Attribute.new('b', 'd') #-> <e a='b' x:a='c' b='d'/>
- def add_attribute( key, value=nil )
- if key.kind_of? Attribute
- @attributes << key
- else
- @attributes[key] = value
- end
- end
-
- # Add multiple attributes to this element.
- # hash:: is either a hash, or array of arrays
- # el.add_attributes( {"name1"=>"value1", "name2"=>"value2"} )
- # el.add_attributes( [ ["name1","value1"], ["name2"=>"value2"] ] )
- def add_attributes hash
- if hash.kind_of? Hash
- hash.each_pair {|key, value| @attributes[key] = value }
- elsif hash.kind_of? Array
- hash.each { |value| @attributes[ value[0] ] = value[1] }
- end
- end
-
- # Removes an attribute
- # key::
- # either an Attribute or a String. In either case, the
- # attribute is found by matching the attribute name to the argument,
- # and then removed. If no attribute is found, no action is taken.
- # Returns::
- # the attribute removed, or nil if this Element did not contain
- # a matching attribute
- # e = Element.new('E')
- # e.add_attribute( 'name', 'Sean' ) #-> <E name='Sean'/>
- # r = e.add_attribute( 'sur:name', 'Russell' ) #-> <E name='Sean' sur:name='Russell'/>
- # e.delete_attribute( 'name' ) #-> <E sur:name='Russell'/>
- # e.delete_attribute( r ) #-> <E/>
- def delete_attribute(key)
- attr = @attributes.get_attribute(key)
- attr.remove unless attr.nil?
- end
-
- #################################################
- # Other Utilities #
- #################################################
-
- # Get an array of all CData children.
- # IMMUTABLE
- def cdatas
- find_all { |child| child.kind_of? CData }.freeze
- end
-
- # Get an array of all Comment children.
- # IMMUTABLE
- def comments
- find_all { |child| child.kind_of? Comment }.freeze
- end
-
- # Get an array of all Instruction children.
- # IMMUTABLE
- def instructions
- find_all { |child| child.kind_of? Instruction }.freeze
- end
-
- # Get an array of all Text children.
- # IMMUTABLE
- def texts
- find_all { |child| child.kind_of? Text }.freeze
- end
-
- # == DEPRECATED
- # See REXML::Formatters
- #
- # Writes out this element, and recursively, all children.
- # output::
- # output an object which supports '<< string'; this is where the
- # document will be written.
- # indent::
- # An integer. If -1, no indenting will be used; otherwise, the
- # indentation will be this number of spaces, and children will be
- # indented an additional amount. Defaults to -1
- # transitive::
- # If transitive is true and indent is >= 0, then the output will be
- # pretty-printed in such a way that the added whitespace does not affect
- # the parse tree of the document
- # ie_hack::
- # This hack inserts a space before the /> on empty tags to address
- # a limitation of Internet Explorer. Defaults to false
- #
- # out = ''
- # doc.write( out ) #-> doc is written to the string 'out'
- # doc.write( $stdout ) #-> doc written to the console
- def write(output=$stdout, indent=-1, transitive=false, ie_hack=false)
- Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters", uplevel: 1)
- formatter = if indent > -1
- if transitive
- require_relative "formatters/transitive"
- REXML::Formatters::Transitive.new( indent, ie_hack )
- else
- REXML::Formatters::Pretty.new( indent, ie_hack )
- end
- else
- REXML::Formatters::Default.new( ie_hack )
- end
- formatter.write( self, output )
- end
-
-
- private
- def __to_xpath_helper node
- rv = node.expanded_name.clone
- if node.parent
- results = node.parent.find_all {|n|
- n.kind_of?(REXML::Element) and n.expanded_name == node.expanded_name
- }
- if results.length > 1
- idx = results.index( node )
- rv << "[#{idx+1}]"
- end
- end
- rv
- end
-
- # A private helper method
- def each_with_something( test, max=0, name=nil )
- num = 0
- @elements.each( name ){ |child|
- yield child if test.call(child) and num += 1
- return if max>0 and num == max
- }
- end
- end
-
- ########################################################################
- # ELEMENTS #
- ########################################################################
-
- # A class which provides filtering of children for Elements, and
- # XPath search support. You are expected to only encounter this class as
- # the <tt>element.elements</tt> object. Therefore, you are
- # _not_ expected to instantiate this yourself.
- class Elements
- include Enumerable
- # Constructor
- # parent:: the parent Element
- def initialize parent
- @element = parent
- end
-
- # Fetches a child element. Filters only Element children, regardless of
- # the XPath match.
- # index::
- # the search parameter. This is either an Integer, which
- # will be used to find the index'th child Element, or an XPath,
- # which will be used to search for the Element. <em>Because
- # of the nature of XPath searches, any element in the connected XML
- # document can be fetched through any other element.</em> <b>The
- # Integer index is 1-based, not 0-based.</b> This means that the first
- # child element is at index 1, not 0, and the +n+th element is at index
- # +n+, not <tt>n-1</tt>. This is because XPath indexes element children
- # starting from 1, not 0, and the indexes should be the same.
- # name::
- # optional, and only used in the first argument is an
- # Integer. In that case, the index'th child Element that has the
- # supplied name will be returned. Note again that the indexes start at 1.
- # Returns:: the first matching Element, or nil if no child matched
- # doc = Document.new '<a><b/><c id="1"/><c id="2"/><d/></a>'
- # doc.root.elements[1] #-> <b/>
- # doc.root.elements['c'] #-> <c id="1"/>
- # doc.root.elements[2,'c'] #-> <c id="2"/>
- def []( index, name=nil)
- if index.kind_of? Integer
- raise "index (#{index}) must be >= 1" if index < 1
- name = literalize(name) if name
- num = 0
- @element.find { |child|
- child.kind_of? Element and
- (name.nil? ? true : child.has_name?( name )) and
- (num += 1) == index
- }
- else
- return XPath::first( @element, index )
- #{ |element|
- # return element if element.kind_of? Element
- #}
- #return nil
- end
- end
-
- # Sets an element, replacing any previous matching element. If no
- # existing element is found ,the element is added.
- # index:: Used to find a matching element to replace. See []().
- # element::
- # The element to replace the existing element with
- # the previous element
- # Returns:: nil if no previous element was found.
- #
- # doc = Document.new '<a/>'
- # doc.root.elements[10] = Element.new('b') #-> <a><b/></a>
- # doc.root.elements[1] #-> <b/>
- # doc.root.elements[1] = Element.new('c') #-> <a><c/></a>
- # doc.root.elements['c'] = Element.new('d') #-> <a><d/></a>
- def []=( index, element )
- previous = self[index]
- if previous.nil?
- @element.add element
- else
- previous.replace_with element
- end
- return previous
- end
-
- # Returns +true+ if there are no +Element+ children, +false+ otherwise
- def empty?
- @element.find{ |child| child.kind_of? Element}.nil?
- end
-
- # Returns the index of the supplied child (starting at 1), or -1 if
- # the element is not a child
- # element:: an +Element+ child
- def index element
- rv = 0
- found = @element.find do |child|
- child.kind_of? Element and
- (rv += 1) and
- child == element
- end
- return rv if found == element
- return -1
- end
-
- # Deletes a child Element
- # element::
- # Either an Element, which is removed directly; an
- # xpath, where the first matching child is removed; or an Integer,
- # where the n'th Element is removed.
- # Returns:: the removed child
- # doc = Document.new '<a><b/><c/><c id="1"/></a>'
- # b = doc.root.elements[1]
- # doc.root.elements.delete b #-> <a><c/><c id="1"/></a>
- # doc.elements.delete("a/c[@id='1']") #-> <a><c/></a>
- # doc.root.elements.delete 1 #-> <a/>
- def delete element
- if element.kind_of? Element
- @element.delete element
- else
- el = self[element]
- el.remove if el
- end
- end
-
- # Removes multiple elements. Filters for Element children, regardless of
- # XPath matching.
- # xpath:: all elements matching this String path are removed.
- # Returns:: an Array of Elements that have been removed
- # doc = Document.new '<a><c/><c/><c/><c/></a>'
- # deleted = doc.elements.delete_all 'a/c' #-> [<c/>, <c/>, <c/>, <c/>]
- def delete_all( xpath )
- rv = []
- XPath::each( @element, xpath) {|element|
- rv << element if element.kind_of? Element
- }
- rv.each do |element|
- @element.delete element
- element.remove
- end
- return rv
- end
-
- # Adds an element
- # element::
- # if supplied, is either an Element, String, or
- # Source (see Element.initialize). If not supplied or nil, a
- # new, default Element will be constructed
- # Returns:: the added Element
- # a = Element.new('a')
- # a.elements.add(Element.new('b')) #-> <a><b/></a>
- # a.elements.add('c') #-> <a><b/><c/></a>
- def add element=nil
- if element.nil?
- Element.new("", self, @element.context)
- elsif not element.kind_of?(Element)
- Element.new(element, self, @element.context)
- else
- @element << element
- element.context = @element.context
- element
- end
- end
-
- alias :<< :add
-
- # Iterates through all of the child Elements, optionally filtering
- # them by a given XPath
- # xpath::
- # optional. If supplied, this is a String XPath, and is used to
- # filter the children, so that only matching children are yielded. Note
- # that XPaths are automatically filtered for Elements, so that
- # non-Element children will not be yielded
- # doc = Document.new '<a><b/><c/><d/>sean<b/><c/><d/></a>'
- # doc.root.elements.each {|e|p e} #-> Yields b, c, d, b, c, d elements
- # doc.root.elements.each('b') {|e|p e} #-> Yields b, b elements
- # doc.root.elements.each('child::node()') {|e|p e}
- # #-> Yields <b/>, <c/>, <d/>, <b/>, <c/>, <d/>
- # XPath.each(doc.root, 'child::node()', &block)
- # #-> Yields <b/>, <c/>, <d/>, sean, <b/>, <c/>, <d/>
- def each( xpath=nil )
- XPath::each( @element, xpath ) {|e| yield e if e.kind_of? Element }
- end
-
- def collect( xpath=nil )
- collection = []
- XPath::each( @element, xpath ) {|e|
- collection << yield(e) if e.kind_of?(Element)
- }
- collection
- end
-
- def inject( xpath=nil, initial=nil )
- first = true
- XPath::each( @element, xpath ) {|e|
- if (e.kind_of? Element)
- if (first and initial == nil)
- initial = e
- first = false
- else
- initial = yield( initial, e ) if e.kind_of? Element
- end
- end
- }
- initial
- end
-
- # Returns the number of +Element+ children of the parent object.
- # doc = Document.new '<a>sean<b/>elliott<b/>russell<b/></a>'
- # doc.root.size #-> 6, 3 element and 3 text nodes
- # doc.root.elements.size #-> 3
- def size
- count = 0
- @element.each {|child| count+=1 if child.kind_of? Element }
- count
- end
-
- # Returns an Array of Element children. An XPath may be supplied to
- # filter the children. Only Element children are returned, even if the
- # supplied XPath matches non-Element children.
- # doc = Document.new '<a>sean<b/>elliott<c/></a>'
- # doc.root.elements.to_a #-> [ <b/>, <c/> ]
- # doc.root.elements.to_a("child::node()") #-> [ <b/>, <c/> ]
- # XPath.match(doc.root, "child::node()") #-> [ sean, <b/>, elliott, <c/> ]
- def to_a( xpath=nil )
- rv = XPath.match( @element, xpath )
- return rv.find_all{|e| e.kind_of? Element} if xpath
- rv
- end
-
- private
- # Private helper class. Removes quotes from quoted strings
- def literalize name
- name = name[1..-2] if name[0] == ?' or name[0] == ?" #'
- name
- end
- end
-
- ########################################################################
- # ATTRIBUTES #
- ########################################################################
-
- # A class that defines the set of Attributes of an Element and provides
- # operations for accessing elements in that set.
- class Attributes < Hash
- # Constructor
- # element:: the Element of which this is an Attribute
- def initialize element
- @element = element
- end
-
- # Fetches an attribute value. If you want to get the Attribute itself,
- # use get_attribute()
- # name:: an XPath attribute name. Namespaces are relevant here.
- # Returns::
- # the String value of the matching attribute, or +nil+ if no
- # matching attribute was found. This is the unnormalized value
- # (with entities expanded).
- #
- # doc = Document.new "<a foo:att='1' bar:att='2' att='&lt;'/>"
- # doc.root.attributes['att'] #-> '<'
- # doc.root.attributes['bar:att'] #-> '2'
- def [](name)
- attr = get_attribute(name)
- return attr.value unless attr.nil?
- return nil
- end
-
- def to_a
- enum_for(:each_attribute).to_a
- end
-
- # Returns the number of attributes the owning Element contains.
- # doc = Document "<a x='1' y='2' foo:x='3'/>"
- # doc.root.attributes.length #-> 3
- def length
- c = 0
- each_attribute { c+=1 }
- c
- end
- alias :size :length
-
- # Iterates over the attributes of an Element. Yields actual Attribute
- # nodes, not String values.
- #
- # doc = Document.new '<a x="1" y="2"/>'
- # doc.root.attributes.each_attribute {|attr|
- # p attr.expanded_name+" => "+attr.value
- # }
- def each_attribute # :yields: attribute
- return to_enum(__method__) unless block_given?
- each_value do |val|
- if val.kind_of? Attribute
- yield val
- else
- val.each_value { |atr| yield atr }
- end
- end
- end
-
- # Iterates over each attribute of an Element, yielding the expanded name
- # and value as a pair of Strings.
- #
- # doc = Document.new '<a x="1" y="2"/>'
- # doc.root.attributes.each {|name, value| p name+" => "+value }
- def each
- return to_enum(__method__) unless block_given?
- each_attribute do |attr|
- yield [attr.expanded_name, attr.value]
- end
- end
-
- # Fetches an attribute
- # name::
- # the name by which to search for the attribute. Can be a
- # <tt>prefix:name</tt> namespace name.
- # Returns:: The first matching attribute, or nil if there was none. This
- # value is an Attribute node, not the String value of the attribute.
- # doc = Document.new '<a x:foo="1" foo="2" bar="3"/>'
- # doc.root.attributes.get_attribute("foo").value #-> "2"
- # doc.root.attributes.get_attribute("x:foo").value #-> "1"
- def get_attribute( name )
- attr = fetch( name, nil )
- if attr.nil?
- return nil if name.nil?
- # Look for prefix
- name =~ Namespace::NAMESPLIT
- prefix, n = $1, $2
- if prefix
- attr = fetch( n, nil )
- # check prefix
- if attr == nil
- elsif attr.kind_of? Attribute
- return attr if prefix == attr.prefix
- else
- attr = attr[ prefix ]
- return attr
- end
- end
- element_document = @element.document
- if element_document and element_document.doctype
- expn = @element.expanded_name
- expn = element_document.doctype.name if expn.size == 0
- attr_val = element_document.doctype.attribute_of(expn, name)
- return Attribute.new( name, attr_val ) if attr_val
- end
- return nil
- end
- if attr.kind_of? Hash
- attr = attr[ @element.prefix ]
- end
- return attr
- end
-
- # Sets an attribute, overwriting any existing attribute value by the
- # same name. Namespace is significant.
- # name:: the name of the attribute
- # value::
- # (optional) If supplied, the value of the attribute. If
- # nil, any existing matching attribute is deleted.
- # Returns::
- # Owning element
- # doc = Document.new "<a x:foo='1' foo='3'/>"
- # doc.root.attributes['y:foo'] = '2'
- # doc.root.attributes['foo'] = '4'
- # doc.root.attributes['x:foo'] = nil
- def []=( name, value )
- if value.nil? # Delete the named attribute
- attr = get_attribute(name)
- delete attr
- return
- end
-
- unless value.kind_of? Attribute
- if @element.document and @element.document.doctype
- value = Text::normalize( value, @element.document.doctype )
- else
- value = Text::normalize( value, nil )
- end
- value = Attribute.new(name, value)
- end
- value.element = @element
- old_attr = fetch(value.name, nil)
- if old_attr.nil?
- store(value.name, value)
- elsif old_attr.kind_of? Hash
- old_attr[value.prefix] = value
- elsif old_attr.prefix != value.prefix
- # Check for conflicting namespaces
- if value.prefix != "xmlns" and old_attr.prefix != "xmlns"
- old_namespace = old_attr.namespace
- new_namespace = value.namespace
- if old_namespace == new_namespace
- raise ParseException.new(
- "Namespace conflict in adding attribute \"#{value.name}\": "+
- "Prefix \"#{old_attr.prefix}\" = \"#{old_namespace}\" and "+
- "prefix \"#{value.prefix}\" = \"#{new_namespace}\"")
- end
- end
- store value.name, {old_attr.prefix => old_attr,
- value.prefix => value}
- else
- store value.name, value
- end
- return @element
- end
-
- # Returns an array of Strings containing all of the prefixes declared
- # by this set of # attributes. The array does not include the default
- # namespace declaration, if one exists.
- # doc = Document.new("<a xmlns='foo' xmlns:x='bar' xmlns:y='twee' "+
- # "z='glorp' p:k='gru'/>")
- # prefixes = doc.root.attributes.prefixes #-> ['x', 'y']
- def prefixes
- ns = []
- each_attribute do |attribute|
- ns << attribute.name if attribute.prefix == 'xmlns'
- end
- if @element.document and @element.document.doctype
- expn = @element.expanded_name
- expn = @element.document.doctype.name if expn.size == 0
- @element.document.doctype.attributes_of(expn).each {
- |attribute|
- ns << attribute.name if attribute.prefix == 'xmlns'
- }
- end
- ns
- end
-
- def namespaces
- namespaces = {}
- each_attribute do |attribute|
- namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
- end
- if @element.document and @element.document.doctype
- expn = @element.expanded_name
- expn = @element.document.doctype.name if expn.size == 0
- @element.document.doctype.attributes_of(expn).each {
- |attribute|
- namespaces[attribute.name] = attribute.value if attribute.prefix == 'xmlns' or attribute.name == 'xmlns'
- }
- end
- namespaces
- end
-
- # Removes an attribute
- # attribute::
- # either a String, which is the name of the attribute to remove --
- # namespaces are significant here -- or the attribute to remove.
- # Returns:: the owning element
- # doc = Document.new "<a y:foo='0' x:foo='1' foo='3' z:foo='4'/>"
- # doc.root.attributes.delete 'foo' #-> <a y:foo='0' x:foo='1' z:foo='4'/>"
- # doc.root.attributes.delete 'x:foo' #-> <a y:foo='0' z:foo='4'/>"
- # attr = doc.root.attributes.get_attribute('y:foo')
- # doc.root.attributes.delete attr #-> <a z:foo='4'/>"
- def delete( attribute )
- name = nil
- prefix = nil
- if attribute.kind_of? Attribute
- name = attribute.name
- prefix = attribute.prefix
- else
- attribute =~ Namespace::NAMESPLIT
- prefix, name = $1, $2
- prefix = '' unless prefix
- end
- old = fetch(name, nil)
- if old.kind_of? Hash # the supplied attribute is one of many
- old.delete(prefix)
- if old.size == 1
- repl = nil
- old.each_value{|v| repl = v}
- store name, repl
- end
- elsif old.nil?
- return @element
- else # the supplied attribute is a top-level one
- super(name)
- end
- @element
- end
-
- # Adds an attribute, overriding any existing attribute by the
- # same name. Namespaces are significant.
- # attribute:: An Attribute
- def add( attribute )
- self[attribute.name] = attribute
- end
-
- alias :<< :add
-
- # Deletes all attributes matching a name. Namespaces are significant.
- # name::
- # A String; all attributes that match this path will be removed
- # Returns:: an Array of the Attributes that were removed
- def delete_all( name )
- rv = []
- each_attribute { |attribute|
- rv << attribute if attribute.expanded_name == name
- }
- rv.each{ |attr| attr.remove }
- return rv
- end
-
- # The +get_attribute_ns+ method retrieves a method by its namespace
- # and name. Thus it is possible to reliably identify an attribute
- # even if an XML processor has changed the prefix.
- #
- # Method contributed by Henrik Martensson
- def get_attribute_ns(namespace, name)
- result = nil
- each_attribute() { |attribute|
- if name == attribute.name &&
- namespace == attribute.namespace() &&
- ( !namespace.empty? || !attribute.fully_expanded_name.index(':') )
- # foo will match xmlns:foo, but only if foo isn't also an attribute
- result = attribute if !result or !namespace.empty? or
- !attribute.fully_expanded_name.index(':')
- end
- }
- result
- end
- end
-end
diff --git a/lib/rexml/encoding.rb b/lib/rexml/encoding.rb
deleted file mode 100644
index da2d70d6c9..0000000000
--- a/lib/rexml/encoding.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: false
-module REXML
- module Encoding
- # ID ---> Encoding name
- attr_reader :encoding
- def encoding=(encoding)
- encoding = encoding.name if encoding.is_a?(Encoding)
- if encoding.is_a?(String)
- original_encoding = encoding
- encoding = find_encoding(encoding)
- unless encoding
- raise ArgumentError, "Bad encoding name #{original_encoding}"
- end
- end
- return false if defined?(@encoding) and encoding == @encoding
- if encoding
- @encoding = encoding.upcase
- else
- @encoding = 'UTF-8'
- end
- true
- end
-
- def encode(string)
- string.encode(@encoding)
- end
-
- def decode(string)
- string.encode(::Encoding::UTF_8, @encoding)
- end
-
- private
- def find_encoding(name)
- case name
- when /\Ashift-jis\z/i
- return "SHIFT_JIS"
- when /\ACP-(\d+)\z/
- name = "CP#{$1}"
- when /\AUTF-8\z/i
- return name
- end
- begin
- ::Encoding::Converter.search_convpath(name, 'UTF-8')
- rescue ::Encoding::ConverterNotFoundError
- return nil
- end
- name
- end
- end
-end
diff --git a/lib/rexml/entity.rb b/lib/rexml/entity.rb
deleted file mode 100644
index 89a9e84c57..0000000000
--- a/lib/rexml/entity.rb
+++ /dev/null
@@ -1,171 +0,0 @@
-# frozen_string_literal: false
-require_relative 'child'
-require_relative 'source'
-require_relative 'xmltokens'
-
-module REXML
- class Entity < Child
- include XMLTokens
- PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#"
- SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))}
- PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')}
- EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))"
- NDATADECL = "\\s+NDATA\\s+#{NAME}"
- PEREFERENCE = "%#{NAME};"
- ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))}
- PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})"
- ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))"
- PEDECL = "<!ENTITY\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>"
- GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>"
- ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um
-
- attr_reader :name, :external, :ref, :ndata, :pubid
-
- # Create a new entity. Simple entities can be constructed by passing a
- # name, value to the constructor; this creates a generic, plain entity
- # reference. For anything more complicated, you have to pass a Source to
- # the constructor with the entity definition, or use the accessor methods.
- # +WARNING+: There is no validation of entity state except when the entity
- # is read from a stream. If you start poking around with the accessors,
- # you can easily create a non-conformant Entity.
- #
- # e = Entity.new( 'amp', '&' )
- def initialize stream, value=nil, parent=nil, reference=false
- super(parent)
- @ndata = @pubid = @value = @external = nil
- if stream.kind_of? Array
- @name = stream[1]
- if stream[-1] == '%'
- @reference = true
- stream.pop
- else
- @reference = false
- end
- if stream[2] =~ /SYSTEM|PUBLIC/
- @external = stream[2]
- if @external == 'SYSTEM'
- @ref = stream[3]
- @ndata = stream[4] if stream.size == 5
- else
- @pubid = stream[3]
- @ref = stream[4]
- end
- else
- @value = stream[2]
- end
- else
- @reference = reference
- @external = nil
- @name = stream
- @value = value
- end
- end
-
- # Evaluates whether the given string matches an entity definition,
- # returning true if so, and false otherwise.
- def Entity::matches? string
- (ENTITYDECL =~ string) == 0
- end
-
- # Evaluates to the unnormalized value of this entity; that is, replacing
- # all entities -- both %ent; and &ent; entities. This differs from
- # +value()+ in that +value+ only replaces %ent; entities.
- def unnormalized
- document.record_entity_expansion unless document.nil?
- v = value()
- return nil if v.nil?
- @unnormalized = Text::unnormalize(v, parent)
- @unnormalized
- end
-
- #once :unnormalized
-
- # Returns the value of this entity unprocessed -- raw. This is the
- # normalized value; that is, with all %ent; and &ent; entities intact
- def normalized
- @value
- end
-
- # Write out a fully formed, correct entity definition (assuming the Entity
- # object itself is valid.)
- #
- # out::
- # An object implementing <TT>&lt;&lt;</TT> to which the entity will be
- # output
- # indent::
- # *DEPRECATED* and ignored
- def write out, indent=-1
- out << '<!ENTITY '
- out << '% ' if @reference
- out << @name
- out << ' '
- if @external
- out << @external << ' '
- if @pubid
- q = @pubid.include?('"')?"'":'"'
- out << q << @pubid << q << ' '
- end
- q = @ref.include?('"')?"'":'"'
- out << q << @ref << q
- out << ' NDATA ' << @ndata if @ndata
- else
- q = @value.include?('"')?"'":'"'
- out << q << @value << q
- end
- out << '>'
- end
-
- # Returns this entity as a string. See write().
- def to_s
- rv = ''
- write rv
- rv
- end
-
- PEREFERENCE_RE = /#{PEREFERENCE}/um
- # Returns the value of this entity. At the moment, only internal entities
- # are processed. If the value contains internal references (IE,
- # %blah;), those are replaced with their values. IE, if the doctype
- # contains:
- # <!ENTITY % foo "bar">
- # <!ENTITY yada "nanoo %foo; nanoo>
- # then:
- # doctype.entity('yada').value #-> "nanoo bar nanoo"
- def value
- if @value
- matches = @value.scan(PEREFERENCE_RE)
- rv = @value.clone
- if @parent
- sum = 0
- matches.each do |entity_reference|
- entity_value = @parent.entity( entity_reference[0] )
- if sum + entity_value.bytesize > Security.entity_expansion_text_limit
- raise "entity expansion has grown too large"
- else
- sum += entity_value.bytesize
- end
- rv.gsub!( /%#{entity_reference.join};/um, entity_value )
- end
- end
- return rv
- end
- nil
- end
- end
-
- # This is a set of entity constants -- the ones defined in the XML
- # specification. These are +gt+, +lt+, +amp+, +quot+ and +apos+.
- # CAUTION: these entities does not have parent and document
- module EntityConst
- # +>+
- GT = Entity.new( 'gt', '>' )
- # +<+
- LT = Entity.new( 'lt', '<' )
- # +&+
- AMP = Entity.new( 'amp', '&' )
- # +"+
- QUOT = Entity.new( 'quot', '"' )
- # +'+
- APOS = Entity.new( 'apos', "'" )
- end
-end
diff --git a/lib/rexml/formatters/default.rb b/lib/rexml/formatters/default.rb
deleted file mode 100644
index 811b2ff3d5..0000000000
--- a/lib/rexml/formatters/default.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-# frozen_string_literal: false
-
-module REXML
- module Formatters
- class Default
- # Prints out the XML document with no formatting -- except if ie_hack is
- # set.
- #
- # ie_hack::
- # If set to true, then inserts whitespace before the close of an empty
- # tag, so that IE's bad XML parser doesn't choke.
- def initialize( ie_hack=false )
- @ie_hack = ie_hack
- end
-
- # Writes the node to some output.
- #
- # node::
- # The node to write
- # output::
- # A class implementing <TT>&lt;&lt;</TT>. Pass in an Output object to
- # change the output encoding.
- def write( node, output )
- case node
-
- when Document
- if node.xml_decl.encoding != 'UTF-8' && !output.kind_of?(Output)
- output = Output.new( output, node.xml_decl.encoding )
- end
- write_document( node, output )
-
- when Element
- write_element( node, output )
-
- when Declaration, ElementDecl, NotationDecl, ExternalEntity, Entity,
- Attribute, AttlistDecl
- node.write( output,-1 )
-
- when Instruction
- write_instruction( node, output )
-
- when DocType, XMLDecl
- node.write( output )
-
- when Comment
- write_comment( node, output )
-
- when CData
- write_cdata( node, output )
-
- when Text
- write_text( node, output )
-
- else
- raise Exception.new("XML FORMATTING ERROR")
-
- end
- end
-
- protected
- def write_document( node, output )
- node.children.each { |child| write( child, output ) }
- end
-
- def write_element( node, output )
- output << "<#{node.expanded_name}"
-
- node.attributes.to_a.map { |a|
- Hash === a ? a.values : a
- }.flatten.sort_by {|attr| attr.name}.each do |attr|
- output << " "
- attr.write( output )
- end unless node.attributes.empty?
-
- if node.children.empty?
- output << " " if @ie_hack
- output << "/"
- else
- output << ">"
- node.children.each { |child|
- write( child, output )
- }
- output << "</#{node.expanded_name}"
- end
- output << ">"
- end
-
- def write_text( node, output )
- output << node.to_s()
- end
-
- def write_comment( node, output )
- output << Comment::START
- output << node.to_s
- output << Comment::STOP
- end
-
- def write_cdata( node, output )
- output << CData::START
- output << node.to_s
- output << CData::STOP
- end
-
- def write_instruction( node, output )
- output << Instruction::START
- output << node.target
- content = node.content
- if content
- output << ' '
- output << content
- end
- output << Instruction::STOP
- end
- end
- end
-end
diff --git a/lib/rexml/formatters/pretty.rb b/lib/rexml/formatters/pretty.rb
deleted file mode 100644
index 562ef9462e..0000000000
--- a/lib/rexml/formatters/pretty.rb
+++ /dev/null
@@ -1,142 +0,0 @@
-# frozen_string_literal: false
-require_relative 'default'
-
-module REXML
- module Formatters
- # Pretty-prints an XML document. This destroys whitespace in text nodes
- # and will insert carriage returns and indentations.
- #
- # TODO: Add an option to print attributes on new lines
- class Pretty < Default
-
- # If compact is set to true, then the formatter will attempt to use as
- # little space as possible
- attr_accessor :compact
- # The width of a page. Used for formatting text
- attr_accessor :width
-
- # Create a new pretty printer.
- #
- # output::
- # An object implementing '<<(String)', to which the output will be written.
- # indentation::
- # An integer greater than 0. The indentation of each level will be
- # this number of spaces. If this is < 1, the behavior of this object
- # is undefined. Defaults to 2.
- # ie_hack::
- # If true, the printer will insert whitespace before closing empty
- # tags, thereby allowing Internet Explorer's XML parser to
- # function. Defaults to false.
- def initialize( indentation=2, ie_hack=false )
- @indentation = indentation
- @level = 0
- @ie_hack = ie_hack
- @width = 80
- @compact = false
- end
-
- protected
- def write_element(node, output)
- output << ' '*@level
- output << "<#{node.expanded_name}"
-
- node.attributes.each_attribute do |attr|
- output << " "
- attr.write( output )
- end unless node.attributes.empty?
-
- if node.children.empty?
- if @ie_hack
- output << " "
- end
- output << "/"
- else
- output << ">"
- # If compact and all children are text, and if the formatted output
- # is less than the specified width, then try to print everything on
- # one line
- skip = false
- if compact
- if node.children.inject(true) {|s,c| s & c.kind_of?(Text)}
- string = ""
- old_level = @level
- @level = 0
- node.children.each { |child| write( child, string ) }
- @level = old_level
- if string.length < @width
- output << string
- skip = true
- end
- end
- end
- unless skip
- output << "\n"
- @level += @indentation
- node.children.each { |child|
- next if child.kind_of?(Text) and child.to_s.strip.length == 0
- write( child, output )
- output << "\n"
- }
- @level -= @indentation
- output << ' '*@level
- end
- output << "</#{node.expanded_name}"
- end
- output << ">"
- end
-
- def write_text( node, output )
- s = node.to_s()
- s.gsub!(/\s/,' ')
- s.squeeze!(" ")
- s = wrap(s, @width - @level)
- s = indent_text(s, @level, " ", true)
- output << (' '*@level + s)
- end
-
- def write_comment( node, output)
- output << ' ' * @level
- super
- end
-
- def write_cdata( node, output)
- output << ' ' * @level
- super
- end
-
- def write_document( node, output )
- # Ok, this is a bit odd. All XML documents have an XML declaration,
- # but it may not write itself if the user didn't specifically add it,
- # either through the API or in the input document. If it doesn't write
- # itself, then we don't need a carriage return... which makes this
- # logic more complex.
- node.children.each { |child|
- next if child == node.children[-1] and child.instance_of?(Text)
- unless child == node.children[0] or child.instance_of?(Text) or
- (child == node.children[1] and !node.children[0].writethis)
- output << "\n"
- end
- write( child, output )
- }
- end
-
- private
- def indent_text(string, level=1, style="\t", indentfirstline=true)
- return string if level < 0
- string.gsub(/\n/, "\n#{style*level}")
- end
-
- def wrap(string, width)
- parts = []
- while string.length > width and place = string.rindex(' ', width)
- parts << string[0...place]
- string = string[place+1..-1]
- end
- parts << string
- parts.join("\n")
- end
-
- end
- end
-end
-
diff --git a/lib/rexml/formatters/transitive.rb b/lib/rexml/formatters/transitive.rb
deleted file mode 100644
index 5ff51e10f3..0000000000
--- a/lib/rexml/formatters/transitive.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: false
-require_relative 'pretty'
-
-module REXML
- module Formatters
- # The Transitive formatter writes an XML document that parses to an
- # identical document as the source document. This means that no extra
- # whitespace nodes are inserted, and whitespace within text nodes is
- # preserved. Within these constraints, the document is pretty-printed,
- # with whitespace inserted into the metadata to introduce formatting.
- #
- # Note that this is only useful if the original XML is not already
- # formatted. Since this formatter does not alter whitespace nodes, the
- # results of formatting already formatted XML will be odd.
- class Transitive < Default
- def initialize( indentation=2, ie_hack=false )
- @indentation = indentation
- @level = 0
- @ie_hack = ie_hack
- end
-
- protected
- def write_element( node, output )
- output << "<#{node.expanded_name}"
-
- node.attributes.each_attribute do |attr|
- output << " "
- attr.write( output )
- end unless node.attributes.empty?
-
- output << "\n"
- output << ' '*@level
- if node.children.empty?
- output << " " if @ie_hack
- output << "/"
- else
- output << ">"
- # If compact and all children are text, and if the formatted output
- # is less than the specified width, then try to print everything on
- # one line
- @level += @indentation
- node.children.each { |child|
- write( child, output )
- }
- @level -= @indentation
- output << "</#{node.expanded_name}"
- output << "\n"
- output << ' '*@level
- end
- output << ">"
- end
-
- def write_text( node, output )
- output << node.to_s()
- end
- end
- end
-end
diff --git a/lib/rexml/functions.rb b/lib/rexml/functions.rb
deleted file mode 100644
index 77926bf2af..0000000000
--- a/lib/rexml/functions.rb
+++ /dev/null
@@ -1,447 +0,0 @@
-# frozen_string_literal: false
-module REXML
- # If you add a method, keep in mind two things:
- # (1) the first argument will always be a list of nodes from which to
- # filter. In the case of context methods (such as position), the function
- # should return an array with a value for each child in the array.
- # (2) all method calls from XML will have "-" replaced with "_".
- # Therefore, in XML, "local-name()" is identical (and actually becomes)
- # "local_name()"
- module Functions
- @@available_functions = {}
- @@context = nil
- @@namespace_context = {}
- @@variables = {}
-
- INTERNAL_METHODS = [
- :namespace_context,
- :namespace_context=,
- :variables,
- :variables=,
- :context=,
- :get_namespace,
- :send,
- ]
- class << self
- def singleton_method_added(name)
- unless INTERNAL_METHODS.include?(name)
- @@available_functions[name] = true
- end
- end
- end
-
- def Functions::namespace_context=(x) ; @@namespace_context=x ; end
- def Functions::variables=(x) ; @@variables=x ; end
- def Functions::namespace_context ; @@namespace_context ; end
- def Functions::variables ; @@variables ; end
-
- def Functions::context=(value); @@context = value; end
-
- def Functions::text( )
- if @@context[:node].node_type == :element
- return @@context[:node].find_all{|n| n.node_type == :text}.collect{|n| n.value}
- elsif @@context[:node].node_type == :text
- return @@context[:node].value
- else
- return false
- end
- end
-
- # Returns the last node of the given list of nodes.
- def Functions::last( )
- @@context[:size]
- end
-
- def Functions::position( )
- @@context[:index]
- end
-
- # Returns the size of the given list of nodes.
- def Functions::count( node_set )
- node_set.size
- end
-
- # Since REXML is non-validating, this method is not implemented as it
- # requires a DTD
- def Functions::id( object )
- end
-
- def Functions::local_name(node_set=nil)
- get_namespace(node_set) do |node|
- return node.local_name
- end
- ""
- end
-
- def Functions::namespace_uri( node_set=nil )
- get_namespace( node_set ) {|node| node.namespace}
- end
-
- def Functions::name( node_set=nil )
- get_namespace( node_set ) do |node|
- node.expanded_name
- end
- end
-
- # Helper method.
- def Functions::get_namespace( node_set = nil )
- if node_set == nil
- yield @@context[:node] if @@context[:node].respond_to?(:namespace)
- else
- if node_set.respond_to? :each
- result = []
- node_set.each do |node|
- result << yield(node) if node.respond_to?(:namespace)
- end
- result
- elsif node_set.respond_to? :namespace
- yield node_set
- end
- end
- end
-
- # A node-set is converted to a string by returning the string-value of the
- # node in the node-set that is first in document order. If the node-set is
- # empty, an empty string is returned.
- #
- # A number is converted to a string as follows
- #
- # NaN is converted to the string NaN
- #
- # positive zero is converted to the string 0
- #
- # negative zero is converted to the string 0
- #
- # positive infinity is converted to the string Infinity
- #
- # negative infinity is converted to the string -Infinity
- #
- # if the number is an integer, the number is represented in decimal form
- # as a Number with no decimal point and no leading zeros, preceded by a
- # minus sign (-) if the number is negative
- #
- # otherwise, the number is represented in decimal form as a Number
- # including a decimal point with at least one digit before the decimal
- # point and at least one digit after the decimal point, preceded by a
- # minus sign (-) if the number is negative; there must be no leading zeros
- # before the decimal point apart possibly from the one required digit
- # immediately before the decimal point; beyond the one required digit
- # after the decimal point there must be as many, but only as many, more
- # digits as are needed to uniquely distinguish the number from all other
- # IEEE 754 numeric values.
- #
- # The boolean false value is converted to the string false. The boolean
- # true value is converted to the string true.
- #
- # An object of a type other than the four basic types is converted to a
- # string in a way that is dependent on that type.
- def Functions::string( object=@@context[:node] )
- if object.respond_to?(:node_type)
- case object.node_type
- when :attribute
- object.value
- when :element
- string_value(object)
- when :document
- string_value(object.root)
- when :processing_instruction
- object.content
- else
- object.to_s
- end
- else
- case object
- when Array
- string(object[0])
- when Float
- if object.nan?
- "NaN"
- else
- integer = object.to_i
- if object == integer
- "%d" % integer
- else
- object.to_s
- end
- end
- else
- object.to_s
- end
- end
- end
-
- # A node-set is converted to a string by
- # returning the concatenation of the string-value
- # of each of the children of the node in the
- # node-set that is first in document order.
- # If the node-set is empty, an empty string is returned.
- def Functions::string_value( o )
- rv = ""
- o.children.each { |e|
- if e.node_type == :text
- rv << e.to_s
- elsif e.node_type == :element
- rv << string_value( e )
- end
- }
- rv
- end
-
- def Functions::concat( *objects )
- concatenated = ""
- objects.each do |object|
- concatenated << string(object)
- end
- concatenated
- end
-
- # Fixed by Mike Stok
- def Functions::starts_with( string, test )
- string(string).index(string(test)) == 0
- end
-
- # Fixed by Mike Stok
- def Functions::contains( string, test )
- string(string).include?(string(test))
- end
-
- # Kouhei fixed this
- def Functions::substring_before( string, test )
- ruby_string = string(string)
- ruby_index = ruby_string.index(string(test))
- if ruby_index.nil?
- ""
- else
- ruby_string[ 0...ruby_index ]
- end
- end
-
- # Kouhei fixed this too
- def Functions::substring_after( string, test )
- ruby_string = string(string)
- return $1 if ruby_string =~ /#{test}(.*)/
- ""
- end
-
- # Take equal portions of Mike Stok and Sean Russell; mix
- # vigorously, and pour into a tall, chilled glass. Serves 10,000.
- def Functions::substring( string, start, length=nil )
- ruby_string = string(string)
- ruby_length = if length.nil?
- ruby_string.length.to_f
- else
- number(length)
- end
- ruby_start = number(start)
-
- # Handle the special cases
- return '' if (
- ruby_length.nan? or
- ruby_start.nan? or
- ruby_start.infinite?
- )
-
- infinite_length = ruby_length.infinite? == 1
- ruby_length = ruby_string.length if infinite_length
-
- # Now, get the bounds. The XPath bounds are 1..length; the ruby bounds
- # are 0..length. Therefore, we have to offset the bounds by one.
- ruby_start = round(ruby_start) - 1
- ruby_length = round(ruby_length)
-
- if ruby_start < 0
- ruby_length += ruby_start unless infinite_length
- ruby_start = 0
- end
- return '' if ruby_length <= 0
- ruby_string[ruby_start,ruby_length]
- end
-
- # UNTESTED
- def Functions::string_length( string )
- string(string).length
- end
-
- # UNTESTED
- def Functions::normalize_space( string=nil )
- string = string(@@context[:node]) if string.nil?
- if string.kind_of? Array
- string.collect{|x| string.to_s.strip.gsub(/\s+/um, ' ') if string}
- else
- string.to_s.strip.gsub(/\s+/um, ' ')
- end
- end
-
- # This is entirely Mike Stok's beast
- def Functions::translate( string, tr1, tr2 )
- from = string(tr1)
- to = string(tr2)
-
- # the map is our translation table.
- #
- # if a character occurs more than once in the
- # from string then we ignore the second &
- # subsequent mappings
- #
- # if a character maps to nil then we delete it
- # in the output. This happens if the from
- # string is longer than the to string
- #
- # there's nothing about - or ^ being special in
- # http://www.w3.org/TR/xpath#function-translate
- # so we don't build ranges or negated classes
-
- map = Hash.new
- 0.upto(from.length - 1) { |pos|
- from_char = from[pos]
- unless map.has_key? from_char
- map[from_char] =
- if pos < to.length
- to[pos]
- else
- nil
- end
- end
- }
-
- if ''.respond_to? :chars
- string(string).chars.collect { |c|
- if map.has_key? c then map[c] else c end
- }.compact.join
- else
- string(string).unpack('U*').collect { |c|
- if map.has_key? c then map[c] else c end
- }.compact.pack('U*')
- end
- end
-
- def Functions::boolean(object=@@context[:node])
- case object
- when true, false
- object
- when Float
- return false if object.zero?
- return false if object.nan?
- true
- when Numeric
- not object.zero?
- when String
- not object.empty?
- when Array
- not object.empty?
- else
- object ? true : false
- end
- end
-
- # UNTESTED
- def Functions::not( object )
- not boolean( object )
- end
-
- # UNTESTED
- def Functions::true( )
- true
- end
-
- # UNTESTED
- def Functions::false( )
- false
- end
-
- # UNTESTED
- def Functions::lang( language )
- lang = false
- node = @@context[:node]
- attr = nil
- until node.nil?
- if node.node_type == :element
- attr = node.attributes["xml:lang"]
- unless attr.nil?
- lang = compare_language(string(language), attr)
- break
- else
- end
- end
- node = node.parent
- end
- lang
- end
-
- def Functions::compare_language lang1, lang2
- lang2.downcase.index(lang1.downcase) == 0
- end
-
- # a string that consists of optional whitespace followed by an optional
- # minus sign followed by a Number followed by whitespace is converted to
- # the IEEE 754 number that is nearest (according to the IEEE 754
- # round-to-nearest rule) to the mathematical value represented by the
- # string; any other string is converted to NaN
- #
- # boolean true is converted to 1; boolean false is converted to 0
- #
- # a node-set is first converted to a string as if by a call to the string
- # function and then converted in the same way as a string argument
- #
- # an object of a type other than the four basic types is converted to a
- # number in a way that is dependent on that type
- def Functions::number(object=@@context[:node])
- case object
- when true
- Float(1)
- when false
- Float(0)
- when Array
- number(string(object))
- when Numeric
- object.to_f
- else
- str = string(object)
- case str.strip
- when /\A\s*(-?(?:\d+(?:\.\d*)?|\.\d+))\s*\z/
- $1.to_f
- else
- Float::NAN
- end
- end
- end
-
- def Functions::sum( nodes )
- nodes = [nodes] unless nodes.kind_of? Array
- nodes.inject(0) { |r,n| r + number(string(n)) }
- end
-
- def Functions::floor( number )
- number(number).floor
- end
-
- def Functions::ceiling( number )
- number(number).ceil
- end
-
- def Functions::round( number )
- number = number(number)
- begin
- neg = number.negative?
- number = number.abs.round
- neg ? -number : number
- rescue FloatDomainError
- number
- end
- end
-
- def Functions::processing_instruction( node )
- node.node_type == :processing_instruction
- end
-
- def Functions::send(name, *args)
- if @@available_functions[name.to_sym]
- super
- else
- # TODO: Maybe, this is not XPath spec behavior.
- # This behavior must be reconsidered.
- XPath.match(@@context[:node], name.to_s)
- end
- end
- end
-end
diff --git a/lib/rexml/instruction.rb b/lib/rexml/instruction.rb
deleted file mode 100644
index 318741f03b..0000000000
--- a/lib/rexml/instruction.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "child"
-require_relative "source"
-
-module REXML
- # Represents an XML Instruction; IE, <? ... ?>
- # TODO: Add parent arg (3rd arg) to constructor
- class Instruction < Child
- START = "<?"
- STOP = "?>"
-
- # target is the "name" of the Instruction; IE, the "tag" in <?tag ...?>
- # content is everything else.
- attr_accessor :target, :content
-
- # Constructs a new Instruction
- # @param target can be one of a number of things. If String, then
- # the target of this instruction is set to this. If an Instruction,
- # then the Instruction is shallowly cloned (target and content are
- # copied).
- # @param content Must be either a String, or a Parent. Can only
- # be a Parent if the target argument is a Source. Otherwise, this
- # String is set as the content of this instruction.
- def initialize(target, content=nil)
- case target
- when String
- super()
- @target = target
- @content = content
- when Instruction
- super(content)
- @target = target.target
- @content = target.content
- else
- message =
- "processing instruction target must be String or REXML::Instruction: "
- message << "<#{target.inspect}>"
- raise ArgumentError, message
- end
- @content.strip! if @content
- end
-
- def clone
- Instruction.new self
- end
-
- # == DEPRECATED
- # See the rexml/formatters package
- #
- def write writer, indent=-1, transitive=false, ie_hack=false
- Kernel.warn( "#{self.class.name}.write is deprecated", uplevel: 1)
- indent(writer, indent)
- writer << START
- writer << @target
- if @content
- writer << ' '
- writer << @content
- end
- writer << STOP
- end
-
- # @return true if other is an Instruction, and the content and target
- # of the other matches the target and content of this object.
- def ==( other )
- other.kind_of? Instruction and
- other.target == @target and
- other.content == @content
- end
-
- def node_type
- :processing_instruction
- end
-
- def inspect
- "<?p-i #{target} ...?>"
- end
- end
-end
diff --git a/lib/rexml/light/node.rb b/lib/rexml/light/node.rb
deleted file mode 100644
index 01177c64d2..0000000000
--- a/lib/rexml/light/node.rb
+++ /dev/null
@@ -1,196 +0,0 @@
-# frozen_string_literal: false
-require_relative '../xmltokens'
-
-# [ :element, parent, name, attributes, children* ]
- # a = Node.new
- # a << "B" # => <a>B</a>
- # a.b # => <a>B<b/></a>
- # a.b[1] # => <a>B<b/><b/><a>
- # a.b[1]["x"] = "y" # => <a>B<b/><b x="y"/></a>
- # a.b[0].c # => <a>B<b><c/></b><b x="y"/></a>
- # a.b.c << "D" # => <a>B<b><c>D</c></b><b x="y"/></a>
-module REXML
- module Light
- # Represents a tagged XML element. Elements are characterized by
- # having children, attributes, and names, and can themselves be
- # children.
- class Node
- NAMESPLIT = /^(?:(#{XMLTokens::NCNAME_STR}):)?(#{XMLTokens::NCNAME_STR})/u
- PARENTS = [ :element, :document, :doctype ]
- # Create a new element.
- def initialize node=nil
- @node = node
- if node.kind_of? String
- node = [ :text, node ]
- elsif node.nil?
- node = [ :document, nil, nil ]
- elsif node[0] == :start_element
- node[0] = :element
- elsif node[0] == :start_doctype
- node[0] = :doctype
- elsif node[0] == :start_document
- node[0] = :document
- end
- end
-
- def size
- if PARENTS.include? @node[0]
- @node[-1].size
- else
- 0
- end
- end
-
- def each
- size.times { |x| yield( at(x+4) ) }
- end
-
- def name
- at(2)
- end
-
- def name=( name_str, ns=nil )
- pfx = ''
- pfx = "#{prefix(ns)}:" if ns
- _old_put(2, "#{pfx}#{name_str}")
- end
-
- def parent=( node )
- _old_put(1,node)
- end
-
- def local_name
- namesplit
- @name
- end
-
- def local_name=( name_str )
- _old_put( 1, "#@prefix:#{name_str}" )
- end
-
- def prefix( namespace=nil )
- prefix_of( self, namespace )
- end
-
- def namespace( prefix=prefix() )
- namespace_of( self, prefix )
- end
-
- def namespace=( namespace )
- @prefix = prefix( namespace )
- pfx = ''
- pfx = "#@prefix:" if @prefix.size > 0
- _old_put(1, "#{pfx}#@name")
- end
-
- def []( reference, ns=nil )
- if reference.kind_of? String
- pfx = ''
- pfx = "#{prefix(ns)}:" if ns
- at(3)["#{pfx}#{reference}"]
- elsif reference.kind_of? Range
- _old_get( Range.new(4+reference.begin, reference.end, reference.exclude_end?) )
- else
- _old_get( 4+reference )
- end
- end
-
- def =~( path )
- XPath.match( self, path )
- end
-
- # Doesn't handle namespaces yet
- def []=( reference, ns, value=nil )
- if reference.kind_of? String
- value = ns unless value
- at( 3 )[reference] = value
- elsif reference.kind_of? Range
- _old_put( Range.new(3+reference.begin, reference.end, reference.exclude_end?), ns )
- else
- if value
- _old_put( 4+reference, ns, value )
- else
- _old_put( 4+reference, ns )
- end
- end
- end
-
- # Append a child to this element, optionally under a provided namespace.
- # The namespace argument is ignored if the element argument is an Element
- # object. Otherwise, the element argument is a string, the namespace (if
- # provided) is the namespace the element is created in.
- def << element
- if node_type() == :text
- at(-1) << element
- else
- newnode = Node.new( element )
- newnode.parent = self
- self.push( newnode )
- end
- at(-1)
- end
-
- def node_type
- _old_get(0)
- end
-
- def text=( foo )
- replace = at(4).kind_of?(String)? 1 : 0
- self._old_put(4,replace, normalizefoo)
- end
-
- def root
- context = self
- context = context.at(1) while context.at(1)
- end
-
- def has_name?( name, namespace = '' )
- at(3) == name and namespace() == namespace
- end
-
- def children
- self
- end
-
- def parent
- at(1)
- end
-
- def to_s
-
- end
-
- private
-
- def namesplit
- return if @name.defined?
- at(2) =~ NAMESPLIT
- @prefix = '' || $1
- @name = $2
- end
-
- def namespace_of( node, prefix=nil )
- if not prefix
- name = at(2)
- name =~ NAMESPLIT
- prefix = $1
- end
- to_find = 'xmlns'
- to_find = "xmlns:#{prefix}" if not prefix.nil?
- ns = at(3)[ to_find ]
- ns ? ns : namespace_of( @node[0], prefix )
- end
-
- def prefix_of( node, namespace=nil )
- if not namespace
- name = node.name
- name =~ NAMESPLIT
- $1
- else
- ns = at(3).find { |k,v| v == namespace }
- ns ? ns : prefix_of( node.parent, namespace )
- end
- end
- end
- end
-end
diff --git a/lib/rexml/namespace.rb b/lib/rexml/namespace.rb
deleted file mode 100644
index 924edf9506..0000000000
--- a/lib/rexml/namespace.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: false
-
-require_relative 'xmltokens'
-
-module REXML
- # Adds named attributes to an object.
- module Namespace
- # The name of the object, valid if set
- attr_reader :name, :expanded_name
- # The expanded name of the object, valid if name is set
- attr_accessor :prefix
- include XMLTokens
- NAMESPLIT = /^(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})/u
-
- # Sets the name and the expanded name
- def name=( name )
- @expanded_name = name
- case name
- when NAMESPLIT
- if $1
- @prefix = $1
- else
- @prefix = ""
- @namespace = ""
- end
- @name = $2
- when ""
- @prefix = nil
- @namespace = nil
- @name = nil
- else
- message = "name must be \#{PREFIX}:\#{LOCAL_NAME} or \#{LOCAL_NAME}: "
- message += "<#{name.inspect}>"
- raise ArgumentError, message
- end
- end
-
- # Compares names optionally WITH namespaces
- def has_name?( other, ns=nil )
- if ns
- return (namespace() == ns and name() == other)
- elsif other.include? ":"
- return fully_expanded_name == other
- else
- return name == other
- end
- end
-
- alias :local_name :name
-
- # Fully expand the name, even if the prefix wasn't specified in the
- # source file.
- def fully_expanded_name
- ns = prefix
- return "#{ns}:#@name" if ns.size > 0
- return @name
- end
- end
-end
diff --git a/lib/rexml/node.rb b/lib/rexml/node.rb
deleted file mode 100644
index 081caba6cb..0000000000
--- a/lib/rexml/node.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: false
-require_relative "parseexception"
-require_relative "formatters/pretty"
-require_relative "formatters/default"
-
-module REXML
- # Represents a node in the tree. Nodes are never encountered except as
- # superclasses of other objects. Nodes have siblings.
- module Node
- # @return the next sibling (nil if unset)
- def next_sibling_node
- return nil if @parent.nil?
- @parent[ @parent.index(self) + 1 ]
- end
-
- # @return the previous sibling (nil if unset)
- def previous_sibling_node
- return nil if @parent.nil?
- ind = @parent.index(self)
- return nil if ind == 0
- @parent[ ind - 1 ]
- end
-
- # indent::
- # *DEPRECATED* This parameter is now ignored. See the formatters in the
- # REXML::Formatters package for changing the output style.
- def to_s indent=nil
- unless indent.nil?
- Kernel.warn( "#{self.class.name}.to_s(indent) parameter is deprecated", uplevel: 1)
- f = REXML::Formatters::Pretty.new( indent )
- f.write( self, rv = "" )
- else
- f = REXML::Formatters::Default.new
- f.write( self, rv = "" )
- end
- return rv
- end
-
- def indent to, ind
- if @parent and @parent.context and not @parent.context[:indentstyle].nil? then
- indentstyle = @parent.context[:indentstyle]
- else
- indentstyle = ' '
- end
- to << indentstyle*ind unless ind<1
- end
-
- def parent?
- false;
- end
-
-
- # Visit all subnodes of +self+ recursively
- def each_recursive(&block) # :yields: node
- self.elements.each {|node|
- block.call(node)
- node.each_recursive(&block)
- }
- end
-
- # Find (and return) first subnode (recursively) for which the block
- # evaluates to true. Returns +nil+ if none was found.
- def find_first_recursive(&block) # :yields: node
- each_recursive {|node|
- return node if block.call(node)
- }
- return nil
- end
-
- # Returns the position that +self+ holds in its parent's array, indexed
- # from 1.
- def index_in_parent
- parent.index(self)+1
- end
- end
-end
diff --git a/lib/rexml/output.rb b/lib/rexml/output.rb
deleted file mode 100644
index 88a5fb378d..0000000000
--- a/lib/rexml/output.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: false
-require_relative 'encoding'
-
-module REXML
- class Output
- include Encoding
-
- attr_reader :encoding
-
- def initialize real_IO, encd="iso-8859-1"
- @output = real_IO
- self.encoding = encd
-
- @to_utf = encoding != 'UTF-8'
-
- if encoding == "UTF-16"
- @output << "\ufeff".encode("UTF-16BE")
- self.encoding = "UTF-16BE"
- end
- end
-
- def <<( content )
- @output << (@to_utf ? self.encode(content) : content)
- end
-
- def to_s
- "Output[#{encoding}]"
- end
- end
-end
diff --git a/lib/rexml/parent.rb b/lib/rexml/parent.rb
deleted file mode 100644
index 6a53b37a12..0000000000
--- a/lib/rexml/parent.rb
+++ /dev/null
@@ -1,166 +0,0 @@
-# frozen_string_literal: false
-require_relative "child"
-
-module REXML
- # A parent has children, and has methods for accessing them. The Parent
- # class is never encountered except as the superclass for some other
- # object.
- class Parent < Child
- include Enumerable
-
- # Constructor
- # @param parent if supplied, will be set as the parent of this object
- def initialize parent=nil
- super(parent)
- @children = []
- end
-
- def add( object )
- object.parent = self
- @children << object
- object
- end
-
- alias :push :add
- alias :<< :push
-
- def unshift( object )
- object.parent = self
- @children.unshift object
- end
-
- def delete( object )
- found = false
- @children.delete_if {|c| c.equal?(object) and found = true }
- object.parent = nil if found
- found ? object : nil
- end
-
- def each(&block)
- @children.each(&block)
- end
-
- def delete_if( &block )
- @children.delete_if(&block)
- end
-
- def delete_at( index )
- @children.delete_at index
- end
-
- def each_index( &block )
- @children.each_index(&block)
- end
-
- # Fetches a child at a given index
- # @param index the Integer index of the child to fetch
- def []( index )
- @children[index]
- end
-
- alias :each_child :each
-
-
-
- # Set an index entry. See Array.[]=
- # @param index the index of the element to set
- # @param opt either the object to set, or an Integer length
- # @param child if opt is an Integer, this is the child to set
- # @return the parent (self)
- def []=( *args )
- args[-1].parent = self
- @children[*args[0..-2]] = args[-1]
- end
-
- # Inserts an child before another child
- # @param child1 this is either an xpath or an Element. If an Element,
- # child2 will be inserted before child1 in the child list of the parent.
- # If an xpath, child2 will be inserted before the first child to match
- # the xpath.
- # @param child2 the child to insert
- # @return the parent (self)
- def insert_before( child1, child2 )
- if child1.kind_of? String
- child1 = XPath.first( self, child1 )
- child1.parent.insert_before child1, child2
- else
- ind = index(child1)
- child2.parent.delete(child2) if child2.parent
- @children[ind,0] = child2
- child2.parent = self
- end
- self
- end
-
- # Inserts an child after another child
- # @param child1 this is either an xpath or an Element. If an Element,
- # child2 will be inserted after child1 in the child list of the parent.
- # If an xpath, child2 will be inserted after the first child to match
- # the xpath.
- # @param child2 the child to insert
- # @return the parent (self)
- def insert_after( child1, child2 )
- if child1.kind_of? String
- child1 = XPath.first( self, child1 )
- child1.parent.insert_after child1, child2
- else
- ind = index(child1)+1
- child2.parent.delete(child2) if child2.parent
- @children[ind,0] = child2
- child2.parent = self
- end
- self
- end
-
- def to_a
- @children.dup
- end
-
- # Fetches the index of a given child
- # @param child the child to get the index of
- # @return the index of the child, or nil if the object is not a child
- # of this parent.
- def index( child )
- count = -1
- @children.find { |i| count += 1 ; i.hash == child.hash }
- count
- end
-
- # @return the number of children of this parent
- def size
- @children.size
- end
-
- alias :length :size
-
- # Replaces one child with another, making sure the nodelist is correct
- # @param to_replace the child to replace (must be a Child)
- # @param replacement the child to insert into the nodelist (must be a
- # Child)
- def replace_child( to_replace, replacement )
- @children.map! {|c| c.equal?( to_replace ) ? replacement : c }
- to_replace.parent = nil
- replacement.parent = self
- end
-
- # Deeply clones this object. This creates a complete duplicate of this
- # Parent, including all descendants.
- def deep_clone
- cl = clone()
- each do |child|
- if child.kind_of? Parent
- cl << child.deep_clone
- else
- cl << child.clone
- end
- end
- cl
- end
-
- alias :children :to_a
-
- def parent?
- true
- end
- end
-end
diff --git a/lib/rexml/parseexception.rb b/lib/rexml/parseexception.rb
deleted file mode 100644
index 7b16cd1a41..0000000000
--- a/lib/rexml/parseexception.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: false
-module REXML
- class ParseException < RuntimeError
- attr_accessor :source, :parser, :continued_exception
-
- def initialize( message, source=nil, parser=nil, exception=nil )
- super(message)
- @source = source
- @parser = parser
- @continued_exception = exception
- end
-
- def to_s
- # Quote the original exception, if there was one
- if @continued_exception
- err = @continued_exception.inspect
- err << "\n"
- err << @continued_exception.backtrace.join("\n")
- err << "\n...\n"
- else
- err = ""
- end
-
- # Get the stack trace and error message
- err << super
-
- # Add contextual information
- if @source
- err << "\nLine: #{line}\n"
- err << "Position: #{position}\n"
- err << "Last 80 unconsumed characters:\n"
- err << @source.buffer[0..80].force_encoding("ASCII-8BIT").gsub(/\n/, ' ')
- end
-
- err
- end
-
- def position
- @source.current_line[0] if @source and defined? @source.current_line and
- @source.current_line
- end
-
- def line
- @source.current_line[2] if @source and defined? @source.current_line and
- @source.current_line
- end
-
- def context
- @source.current_line
- end
- end
-end
diff --git a/lib/rexml/parsers/baseparser.rb b/lib/rexml/parsers/baseparser.rb
deleted file mode 100644
index 305b120795..0000000000
--- a/lib/rexml/parsers/baseparser.rb
+++ /dev/null
@@ -1,694 +0,0 @@
-# frozen_string_literal: false
-require_relative '../parseexception'
-require_relative '../undefinednamespaceexception'
-require_relative '../source'
-require 'set'
-require "strscan"
-
-module REXML
- module Parsers
- # = Using the Pull Parser
- # <em>This API is experimental, and subject to change.</em>
- # parser = PullParser.new( "<a>text<b att='val'/>txet</a>" )
- # while parser.has_next?
- # res = parser.next
- # puts res[1]['att'] if res.start_tag? and res[0] == 'b'
- # end
- # See the PullEvent class for information on the content of the results.
- # The data is identical to the arguments passed for the various events to
- # the StreamListener API.
- #
- # Notice that:
- # parser = PullParser.new( "<a>BAD DOCUMENT" )
- # while parser.has_next?
- # res = parser.next
- # raise res[1] if res.error?
- # end
- #
- # Nat Price gave me some good ideas for the API.
- class BaseParser
- LETTER = '[:alpha:]'
- DIGIT = '[:digit:]'
-
- COMBININGCHAR = '' # TODO
- EXTENDER = '' # TODO
-
- NCNAME_STR= "[#{LETTER}_][-[:alnum:]._#{COMBININGCHAR}#{EXTENDER}]*"
- QNAME_STR= "(?:(#{NCNAME_STR}):)?(#{NCNAME_STR})"
- QNAME = /(#{QNAME_STR})/
-
- # Just for backward compatibility. For example, kramdown uses this.
- # It's not used in REXML.
- UNAME_STR= "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
-
- NAMECHAR = '[\-\w\.:]'
- NAME = "([\\w:]#{NAMECHAR}*)"
- NMTOKEN = "(?:#{NAMECHAR})+"
- NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*"
- REFERENCE = "&(?:#{NAME};|#\\d+;|#x[0-9a-fA-F]+;)"
- REFERENCE_RE = /#{REFERENCE}/
-
- DOCTYPE_START = /\A\s*<!DOCTYPE\s/um
- DOCTYPE_END = /\A\s*\]\s*>/um
- ATTRIBUTE_PATTERN = /\s*(#{QNAME_STR})\s*=\s*(["'])(.*?)\4/um
- COMMENT_START = /\A<!--/u
- COMMENT_PATTERN = /<!--(.*?)-->/um
- CDATA_START = /\A<!\[CDATA\[/u
- CDATA_END = /\A\s*\]\s*>/um
- CDATA_PATTERN = /<!\[CDATA\[(.*?)\]\]>/um
- XMLDECL_START = /\A<\?xml\s/u;
- XMLDECL_PATTERN = /<\?xml\s+(.*?)\?>/um
- INSTRUCTION_START = /\A<\?/u
- INSTRUCTION_PATTERN = /<\?#{NAME}(\s+.*?)?\?>/um
- TAG_MATCH = /\A<((?>#{QNAME_STR}))/um
- CLOSE_MATCH = /\A\s*<\/(#{QNAME_STR})\s*>/um
-
- VERSION = /\bversion\s*=\s*["'](.*?)['"]/um
- ENCODING = /\bencoding\s*=\s*["'](.*?)['"]/um
- STANDALONE = /\bstandalone\s*=\s*["'](.*?)['"]/um
-
- ENTITY_START = /\A\s*<!ENTITY/
- ELEMENTDECL_START = /\A\s*<!ELEMENT/um
- ELEMENTDECL_PATTERN = /\A\s*(<!ELEMENT.*?)>/um
- SYSTEMENTITY = /\A\s*(%.*?;)\s*$/um
- ENUMERATION = "\\(\\s*#{NMTOKEN}(?:\\s*\\|\\s*#{NMTOKEN})*\\s*\\)"
- NOTATIONTYPE = "NOTATION\\s+\\(\\s*#{NAME}(?:\\s*\\|\\s*#{NAME})*\\s*\\)"
- ENUMERATEDTYPE = "(?:(?:#{NOTATIONTYPE})|(?:#{ENUMERATION}))"
- ATTTYPE = "(CDATA|ID|IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS|#{ENUMERATEDTYPE})"
- ATTVALUE = "(?:\"((?:[^<&\"]|#{REFERENCE})*)\")|(?:'((?:[^<&']|#{REFERENCE})*)')"
- DEFAULTDECL = "(#REQUIRED|#IMPLIED|(?:(#FIXED\\s+)?#{ATTVALUE}))"
- ATTDEF = "\\s+#{NAME}\\s+#{ATTTYPE}\\s+#{DEFAULTDECL}"
- ATTDEF_RE = /#{ATTDEF}/
- ATTLISTDECL_START = /\A\s*<!ATTLIST/um
- ATTLISTDECL_PATTERN = /\A\s*<!ATTLIST\s+#{NAME}(?:#{ATTDEF})*\s*>/um
-
- TEXT_PATTERN = /\A([^<]*)/um
-
- # Entity constants
- PUBIDCHAR = "\x20\x0D\x0Aa-zA-Z0-9\\-()+,./:=?;!*@$_%#"
- SYSTEMLITERAL = %Q{((?:"[^"]*")|(?:'[^']*'))}
- PUBIDLITERAL = %Q{("[#{PUBIDCHAR}']*"|'[#{PUBIDCHAR}]*')}
- EXTERNALID = "(?:(?:(SYSTEM)\\s+#{SYSTEMLITERAL})|(?:(PUBLIC)\\s+#{PUBIDLITERAL}\\s+#{SYSTEMLITERAL}))"
- NDATADECL = "\\s+NDATA\\s+#{NAME}"
- PEREFERENCE = "%#{NAME};"
- ENTITYVALUE = %Q{((?:"(?:[^%&"]|#{PEREFERENCE}|#{REFERENCE})*")|(?:'([^%&']|#{PEREFERENCE}|#{REFERENCE})*'))}
- PEDEF = "(?:#{ENTITYVALUE}|#{EXTERNALID})"
- ENTITYDEF = "(?:#{ENTITYVALUE}|(?:#{EXTERNALID}(#{NDATADECL})?))"
- PEDECL = "<!ENTITY\\s+(%)\\s+#{NAME}\\s+#{PEDEF}\\s*>"
- GEDECL = "<!ENTITY\\s+#{NAME}\\s+#{ENTITYDEF}\\s*>"
- ENTITYDECL = /\s*(?:#{GEDECL})|(?:#{PEDECL})/um
-
- NOTATIONDECL_START = /\A\s*<!NOTATION/um
- EXTERNAL_ID_PUBLIC = /\A\s*PUBLIC\s+#{PUBIDLITERAL}\s+#{SYSTEMLITERAL}\s*/um
- EXTERNAL_ID_SYSTEM = /\A\s*SYSTEM\s+#{SYSTEMLITERAL}\s*/um
- PUBLIC_ID = /\A\s*PUBLIC\s+#{PUBIDLITERAL}\s*/um
-
- EREFERENCE = /&(?!#{NAME};)/
-
- DEFAULT_ENTITIES = {
- 'gt' => [/&gt;/, '&gt;', '>', />/],
- 'lt' => [/&lt;/, '&lt;', '<', /</],
- 'quot' => [/&quot;/, '&quot;', '"', /"/],
- "apos" => [/&apos;/, "&apos;", "'", /'/]
- }
-
- def initialize( source )
- self.stream = source
- @listeners = []
- end
-
- def add_listener( listener )
- @listeners << listener
- end
-
- attr_reader :source
-
- def stream=( source )
- @source = SourceFactory.create_from( source )
- @closed = nil
- @document_status = nil
- @tags = []
- @stack = []
- @entities = []
- @nsstack = []
- end
-
- def position
- if @source.respond_to? :position
- @source.position
- else
- # FIXME
- 0
- end
- end
-
- # Returns true if there are no more events
- def empty?
- return (@source.empty? and @stack.empty?)
- end
-
- # Returns true if there are more events. Synonymous with !empty?
- def has_next?
- return !(@source.empty? and @stack.empty?)
- end
-
- # Push an event back on the head of the stream. This method
- # has (theoretically) infinite depth.
- def unshift token
- @stack.unshift(token)
- end
-
- # Peek at the +depth+ event in the stack. The first element on the stack
- # is at depth 0. If +depth+ is -1, will parse to the end of the input
- # stream and return the last event, which is always :end_document.
- # Be aware that this causes the stream to be parsed up to the +depth+
- # event, so you can effectively pre-parse the entire document (pull the
- # entire thing into memory) using this method.
- def peek depth=0
- raise %Q[Illegal argument "#{depth}"] if depth < -1
- temp = []
- if depth == -1
- temp.push(pull()) until empty?
- else
- while @stack.size+temp.size < depth+1
- temp.push(pull())
- end
- end
- @stack += temp if temp.size > 0
- @stack[depth]
- end
-
- # Returns the next event. This is a +PullEvent+ object.
- def pull
- pull_event.tap do |event|
- @listeners.each do |listener|
- listener.receive event
- end
- end
- end
-
- def pull_event
- if @closed
- x, @closed = @closed, nil
- return [ :end_element, x ]
- end
- return [ :end_document ] if empty?
- return @stack.shift if @stack.size > 0
- #STDERR.puts @source.encoding
- #STDERR.puts "BUFFER = #{@source.buffer.inspect}"
- if @document_status == nil
- word = @source.match( /\A((?:\s+)|(?:<[^>]*>))/um )
- word = word[1] unless word.nil?
- #STDERR.puts "WORD = #{word.inspect}"
- case word
- when COMMENT_START
- return [ :comment, @source.match( COMMENT_PATTERN, true )[1] ]
- when XMLDECL_START
- #STDERR.puts "XMLDECL"
- results = @source.match( XMLDECL_PATTERN, true )[1]
- version = VERSION.match( results )
- version = version[1] unless version.nil?
- encoding = ENCODING.match(results)
- encoding = encoding[1] unless encoding.nil?
- if need_source_encoding_update?(encoding)
- @source.encoding = encoding
- end
- if encoding.nil? and /\AUTF-16(?:BE|LE)\z/i =~ @source.encoding
- encoding = "UTF-16"
- end
- standalone = STANDALONE.match(results)
- standalone = standalone[1] unless standalone.nil?
- return [ :xmldecl, version, encoding, standalone ]
- when INSTRUCTION_START
- return process_instruction
- when DOCTYPE_START
- base_error_message = "Malformed DOCTYPE"
- @source.match(DOCTYPE_START, true)
- @nsstack.unshift(curr_ns=Set.new)
- name = parse_name(base_error_message)
- if @source.match(/\A\s*\[/um, true)
- id = [nil, nil, nil]
- @document_status = :in_doctype
- elsif @source.match(/\A\s*>/um, true)
- id = [nil, nil, nil]
- @document_status = :after_doctype
- else
- id = parse_id(base_error_message,
- accept_external_id: true,
- accept_public_id: false)
- if id[0] == "SYSTEM"
- # For backward compatibility
- id[1], id[2] = id[2], nil
- end
- if @source.match(/\A\s*\[/um, true)
- @document_status = :in_doctype
- elsif @source.match(/\A\s*>/um, true)
- @document_status = :after_doctype
- else
- message = "#{base_error_message}: garbage after external ID"
- raise REXML::ParseException.new(message, @source)
- end
- end
- args = [:start_doctype, name, *id]
- if @document_status == :after_doctype
- @source.match(/\A\s*/um, true)
- @stack << [ :end_doctype ]
- end
- return args
- when /\A\s+/
- else
- @document_status = :after_doctype
- if @source.encoding == "UTF-8"
- @source.buffer.force_encoding(::Encoding::UTF_8)
- end
- end
- end
- if @document_status == :in_doctype
- md = @source.match(/\A\s*(.*?>)/um)
- case md[1]
- when SYSTEMENTITY
- match = @source.match( SYSTEMENTITY, true )[1]
- return [ :externalentity, match ]
-
- when ELEMENTDECL_START
- return [ :elementdecl, @source.match( ELEMENTDECL_PATTERN, true )[1] ]
-
- when ENTITY_START
- match = @source.match( ENTITYDECL, true ).to_a.compact
- match[0] = :entitydecl
- ref = false
- if match[1] == '%'
- ref = true
- match.delete_at 1
- end
- # Now we have to sort out what kind of entity reference this is
- if match[2] == 'SYSTEM'
- # External reference
- match[3] = match[3][1..-2] # PUBID
- match.delete_at(4) if match.size > 4 # Chop out NDATA decl
- # match is [ :entity, name, SYSTEM, pubid(, ndata)? ]
- elsif match[2] == 'PUBLIC'
- # External reference
- match[3] = match[3][1..-2] # PUBID
- match[4] = match[4][1..-2] # HREF
- match.delete_at(5) if match.size > 5 # Chop out NDATA decl
- # match is [ :entity, name, PUBLIC, pubid, href(, ndata)? ]
- else
- match[2] = match[2][1..-2]
- match.pop if match.size == 4
- # match is [ :entity, name, value ]
- end
- match << '%' if ref
- return match
- when ATTLISTDECL_START
- md = @source.match( ATTLISTDECL_PATTERN, true )
- raise REXML::ParseException.new( "Bad ATTLIST declaration!", @source ) if md.nil?
- element = md[1]
- contents = md[0]
-
- pairs = {}
- values = md[0].scan( ATTDEF_RE )
- values.each do |attdef|
- unless attdef[3] == "#IMPLIED"
- attdef.compact!
- val = attdef[3]
- val = attdef[4] if val == "#FIXED "
- pairs[attdef[0]] = val
- if attdef[0] =~ /^xmlns:(.*)/
- @nsstack[0] << $1
- end
- end
- end
- return [ :attlistdecl, element, pairs, contents ]
- when NOTATIONDECL_START
- base_error_message = "Malformed notation declaration"
- unless @source.match(/\A\s*<!NOTATION\s+/um, true)
- if @source.match(/\A\s*<!NOTATION\s*>/um)
- message = "#{base_error_message}: name is missing"
- else
- message = "#{base_error_message}: invalid declaration name"
- end
- raise REXML::ParseException.new(message, @source)
- end
- name = parse_name(base_error_message)
- id = parse_id(base_error_message,
- accept_external_id: true,
- accept_public_id: true)
- unless @source.match(/\A\s*>/um, true)
- message = "#{base_error_message}: garbage before end >"
- raise REXML::ParseException.new(message, @source)
- end
- return [:notationdecl, name, *id]
- when DOCTYPE_END
- @document_status = :after_doctype
- @source.match( DOCTYPE_END, true )
- return [ :end_doctype ]
- end
- end
- if @document_status == :after_doctype
- @source.match(/\A\s*/um, true)
- end
- begin
- @source.read if @source.buffer.size<2
- if @source.buffer[0] == ?<
- if @source.buffer[1] == ?/
- @nsstack.shift
- last_tag = @tags.pop
- md = @source.match( CLOSE_MATCH, true )
- if md and !last_tag
- message = "Unexpected top-level end tag (got '#{md[1]}')"
- raise REXML::ParseException.new(message, @source)
- end
- if md.nil? or last_tag != md[1]
- message = "Missing end tag for '#{last_tag}'"
- message << " (got '#{md[1]}')" if md
- raise REXML::ParseException.new(message, @source)
- end
- return [ :end_element, last_tag ]
- elsif @source.buffer[1] == ?!
- md = @source.match(/\A(\s*[^>]*>)/um)
- #STDERR.puts "SOURCE BUFFER = #{source.buffer}, #{source.buffer.size}"
- raise REXML::ParseException.new("Malformed node", @source) unless md
- if md[0][2] == ?-
- md = @source.match( COMMENT_PATTERN, true )
-
- case md[1]
- when /--/, /-\z/
- raise REXML::ParseException.new("Malformed comment", @source)
- end
-
- return [ :comment, md[1] ] if md
- else
- md = @source.match( CDATA_PATTERN, true )
- return [ :cdata, md[1] ] if md
- end
- raise REXML::ParseException.new( "Declarations can only occur "+
- "in the doctype declaration.", @source)
- elsif @source.buffer[1] == ??
- return process_instruction
- else
- # Get the next tag
- md = @source.match(TAG_MATCH, true)
- unless md
- raise REXML::ParseException.new("malformed XML: missing tag start", @source)
- end
- @document_status = :in_element
- prefixes = Set.new
- prefixes << md[2] if md[2]
- @nsstack.unshift(curr_ns=Set.new)
- attributes, closed = parse_attributes(prefixes, curr_ns)
- # Verify that all of the prefixes have been defined
- for prefix in prefixes
- unless @nsstack.find{|k| k.member?(prefix)}
- raise UndefinedNamespaceException.new(prefix,@source,self)
- end
- end
-
- if closed
- @closed = md[1]
- @nsstack.shift
- else
- @tags.push( md[1] )
- end
- return [ :start_element, md[1], attributes ]
- end
- else
- md = @source.match( TEXT_PATTERN, true )
- if md[0].length == 0
- @source.match( /(\s+)/, true )
- end
- #STDERR.puts "GOT #{md[1].inspect}" unless md[0].length == 0
- #return [ :text, "" ] if md[0].length == 0
- # unnormalized = Text::unnormalize( md[1], self )
- # return PullEvent.new( :text, md[1], unnormalized )
- return [ :text, md[1] ]
- end
- rescue REXML::UndefinedNamespaceException
- raise
- rescue REXML::ParseException
- raise
- rescue => error
- raise REXML::ParseException.new( "Exception parsing",
- @source, self, (error ? error : $!) )
- end
- return [ :dummy ]
- end
- private :pull_event
-
- def entity( reference, entities )
- value = nil
- value = entities[ reference ] if entities
- if not value
- value = DEFAULT_ENTITIES[ reference ]
- value = value[2] if value
- end
- unnormalize( value, entities ) if value
- end
-
- # Escapes all possible entities
- def normalize( input, entities=nil, entity_filter=nil )
- copy = input.clone
- # Doing it like this rather than in a loop improves the speed
- copy.gsub!( EREFERENCE, '&amp;' )
- entities.each do |key, value|
- copy.gsub!( value, "&#{key};" ) unless entity_filter and
- entity_filter.include?(entity)
- end if entities
- copy.gsub!( EREFERENCE, '&amp;' )
- DEFAULT_ENTITIES.each do |key, value|
- copy.gsub!( value[3], value[1] )
- end
- copy
- end
-
- # Unescapes all possible entities
- def unnormalize( string, entities=nil, filter=nil )
- rv = string.clone
- rv.gsub!( /\r\n?/, "\n" )
- matches = rv.scan( REFERENCE_RE )
- return rv if matches.size == 0
- rv.gsub!( /&#0*((?:\d+)|(?:x[a-fA-F0-9]+));/ ) {
- m=$1
- m = "0#{m}" if m[0] == ?x
- [Integer(m)].pack('U*')
- }
- matches.collect!{|x|x[0]}.compact!
- if matches.size > 0
- matches.each do |entity_reference|
- unless filter and filter.include?(entity_reference)
- entity_value = entity( entity_reference, entities )
- if entity_value
- re = /&#{entity_reference};/
- rv.gsub!( re, entity_value )
- else
- er = DEFAULT_ENTITIES[entity_reference]
- rv.gsub!( er[0], er[2] ) if er
- end
- end
- end
- rv.gsub!( /&amp;/, '&' )
- end
- rv
- end
-
- private
- def need_source_encoding_update?(xml_declaration_encoding)
- return false if xml_declaration_encoding.nil?
- return false if /\AUTF-16\z/i =~ xml_declaration_encoding
- true
- end
-
- def parse_name(base_error_message)
- md = @source.match(/\A\s*#{NAME}/um, true)
- unless md
- if @source.match(/\A\s*\S/um)
- message = "#{base_error_message}: invalid name"
- else
- message = "#{base_error_message}: name is missing"
- end
- raise REXML::ParseException.new(message, @source)
- end
- md[1]
- end
-
- def parse_id(base_error_message,
- accept_external_id:,
- accept_public_id:)
- if accept_external_id and (md = @source.match(EXTERNAL_ID_PUBLIC, true))
- pubid = system = nil
- pubid_literal = md[1]
- pubid = pubid_literal[1..-2] if pubid_literal # Remove quote
- system_literal = md[2]
- system = system_literal[1..-2] if system_literal # Remove quote
- ["PUBLIC", pubid, system]
- elsif accept_public_id and (md = @source.match(PUBLIC_ID, true))
- pubid = system = nil
- pubid_literal = md[1]
- pubid = pubid_literal[1..-2] if pubid_literal # Remove quote
- ["PUBLIC", pubid, nil]
- elsif accept_external_id and (md = @source.match(EXTERNAL_ID_SYSTEM, true))
- system = nil
- system_literal = md[1]
- system = system_literal[1..-2] if system_literal # Remove quote
- ["SYSTEM", nil, system]
- else
- details = parse_id_invalid_details(accept_external_id: accept_external_id,
- accept_public_id: accept_public_id)
- message = "#{base_error_message}: #{details}"
- raise REXML::ParseException.new(message, @source)
- end
- end
-
- def parse_id_invalid_details(accept_external_id:,
- accept_public_id:)
- public = /\A\s*PUBLIC/um
- system = /\A\s*SYSTEM/um
- if (accept_external_id or accept_public_id) and @source.match(/#{public}/um)
- if @source.match(/#{public}(?:\s+[^'"]|\s*[\[>])/um)
- return "public ID literal is missing"
- end
- unless @source.match(/#{public}\s+#{PUBIDLITERAL}/um)
- return "invalid public ID literal"
- end
- if accept_public_id
- if @source.match(/#{public}\s+#{PUBIDLITERAL}\s+[^'"]/um)
- return "system ID literal is missing"
- end
- unless @source.match(/#{public}\s+#{PUBIDLITERAL}\s+#{SYSTEMLITERAL}/um)
- return "invalid system literal"
- end
- "garbage after system literal"
- else
- "garbage after public ID literal"
- end
- elsif accept_external_id and @source.match(/#{system}/um)
- if @source.match(/#{system}(?:\s+[^'"]|\s*[\[>])/um)
- return "system literal is missing"
- end
- unless @source.match(/#{system}\s+#{SYSTEMLITERAL}/um)
- return "invalid system literal"
- end
- "garbage after system literal"
- else
- unless @source.match(/\A\s*(?:PUBLIC|SYSTEM)\s/um)
- return "invalid ID type"
- end
- "ID type is missing"
- end
- end
-
- def process_instruction
- match_data = @source.match(INSTRUCTION_PATTERN, true)
- unless match_data
- message = "Invalid processing instruction node"
- raise REXML::ParseException.new(message, @source)
- end
- [:processing_instruction, match_data[1], match_data[2]]
- end
-
- def parse_attributes(prefixes, curr_ns)
- attributes = {}
- closed = false
- match_data = @source.match(/^(.*?)(\/)?>/um, true)
- if match_data.nil?
- message = "Start tag isn't ended"
- raise REXML::ParseException.new(message, @source)
- end
-
- raw_attributes = match_data[1]
- closed = !match_data[2].nil?
- return attributes, closed if raw_attributes.nil?
- return attributes, closed if raw_attributes.empty?
-
- scanner = StringScanner.new(raw_attributes)
- until scanner.eos?
- if scanner.scan(/\s+/)
- break if scanner.eos?
- end
-
- pos = scanner.pos
- loop do
- break if scanner.scan(ATTRIBUTE_PATTERN)
- unless scanner.scan(QNAME)
- message = "Invalid attribute name: <#{scanner.rest}>"
- raise REXML::ParseException.new(message, @source)
- end
- name = scanner[0]
- unless scanner.scan(/\s*=\s*/um)
- message = "Missing attribute equal: <#{name}>"
- raise REXML::ParseException.new(message, @source)
- end
- quote = scanner.scan(/['"]/)
- unless quote
- message = "Missing attribute value start quote: <#{name}>"
- raise REXML::ParseException.new(message, @source)
- end
- unless scanner.scan(/.*#{Regexp.escape(quote)}/um)
- match_data = @source.match(/^(.*?)(\/)?>/um, true)
- if match_data
- scanner << "/" if closed
- scanner << ">"
- scanner << match_data[1]
- scanner.pos = pos
- closed = !match_data[2].nil?
- next
- end
- message =
- "Missing attribute value end quote: <#{name}>: <#{quote}>"
- raise REXML::ParseException.new(message, @source)
- end
- end
- name = scanner[1]
- prefix = scanner[2]
- local_part = scanner[3]
- # quote = scanner[4]
- value = scanner[5]
- if prefix == "xmlns"
- if local_part == "xml"
- if value != "http://www.w3.org/XML/1998/namespace"
- msg = "The 'xml' prefix must not be bound to any other namespace "+
- "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
- raise REXML::ParseException.new( msg, @source, self )
- end
- elsif local_part == "xmlns"
- msg = "The 'xmlns' prefix must not be declared "+
- "(http://www.w3.org/TR/REC-xml-names/#ns-decl)"
- raise REXML::ParseException.new( msg, @source, self)
- end
- curr_ns << local_part
- elsif prefix
- prefixes << prefix unless prefix == "xml"
- end
-
- if attributes.has_key?(name)
- msg = "Duplicate attribute #{name.inspect}"
- raise REXML::ParseException.new(msg, @source, self)
- end
-
- attributes[name] = value
- end
- return attributes, closed
- end
- end
- end
-end
-
-=begin
- case event[0]
- when :start_element
- when :text
- when :end_element
- when :processing_instruction
- when :cdata
- when :comment
- when :xmldecl
- when :start_doctype
- when :end_doctype
- when :externalentity
- when :elementdecl
- when :entity
- when :attlistdecl
- when :notationdecl
- when :end_doctype
- end
-=end
diff --git a/lib/rexml/parsers/lightparser.rb b/lib/rexml/parsers/lightparser.rb
deleted file mode 100644
index bdc08276a9..0000000000
--- a/lib/rexml/parsers/lightparser.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: false
-require_relative 'streamparser'
-require_relative 'baseparser'
-require_relative '../light/node'
-
-module REXML
- module Parsers
- class LightParser
- def initialize stream
- @stream = stream
- @parser = REXML::Parsers::BaseParser.new( stream )
- end
-
- def add_listener( listener )
- @parser.add_listener( listener )
- end
-
- def rewind
- @stream.rewind
- @parser.stream = @stream
- end
-
- def parse
- root = context = [ :document ]
- while true
- event = @parser.pull
- case event[0]
- when :end_document
- break
- when :start_element, :start_doctype
- new_node = event
- context << new_node
- new_node[1,0] = [context]
- context = new_node
- when :end_element, :end_doctype
- context = context[1]
- else
- new_node = event
- context << new_node
- new_node[1,0] = [context]
- end
- end
- root
- end
- end
-
- # An element is an array. The array contains:
- # 0 The parent element
- # 1 The tag name
- # 2 A hash of attributes
- # 3..-1 The child elements
- # An element is an array of size > 3
- # Text is a String
- # PIs are [ :processing_instruction, target, data ]
- # Comments are [ :comment, data ]
- # DocTypes are DocType structs
- # The root is an array with XMLDecls, Text, DocType, Array, Text
- end
-end
diff --git a/lib/rexml/parsers/pullparser.rb b/lib/rexml/parsers/pullparser.rb
deleted file mode 100644
index f8b232a2cd..0000000000
--- a/lib/rexml/parsers/pullparser.rb
+++ /dev/null
@@ -1,197 +0,0 @@
-# frozen_string_literal: false
-require 'forwardable'
-
-require_relative '../parseexception'
-require_relative 'baseparser'
-require_relative '../xmltokens'
-
-module REXML
- module Parsers
- # = Using the Pull Parser
- # <em>This API is experimental, and subject to change.</em>
- # parser = PullParser.new( "<a>text<b att='val'/>txet</a>" )
- # while parser.has_next?
- # res = parser.next
- # puts res[1]['att'] if res.start_tag? and res[0] == 'b'
- # end
- # See the PullEvent class for information on the content of the results.
- # The data is identical to the arguments passed for the various events to
- # the StreamListener API.
- #
- # Notice that:
- # parser = PullParser.new( "<a>BAD DOCUMENT" )
- # while parser.has_next?
- # res = parser.next
- # raise res[1] if res.error?
- # end
- #
- # Nat Price gave me some good ideas for the API.
- class PullParser
- include XMLTokens
- extend Forwardable
-
- def_delegators( :@parser, :has_next? )
- def_delegators( :@parser, :entity )
- def_delegators( :@parser, :empty? )
- def_delegators( :@parser, :source )
-
- def initialize stream
- @entities = {}
- @listeners = nil
- @parser = BaseParser.new( stream )
- @my_stack = []
- end
-
- def add_listener( listener )
- @listeners = [] unless @listeners
- @listeners << listener
- end
-
- def each
- while has_next?
- yield self.pull
- end
- end
-
- def peek depth=0
- if @my_stack.length <= depth
- (depth - @my_stack.length + 1).times {
- e = PullEvent.new(@parser.pull)
- @my_stack.push(e)
- }
- end
- @my_stack[depth]
- end
-
- def pull
- return @my_stack.shift if @my_stack.length > 0
-
- event = @parser.pull
- case event[0]
- when :entitydecl
- @entities[ event[1] ] =
- event[2] unless event[2] =~ /PUBLIC|SYSTEM/
- when :text
- unnormalized = @parser.unnormalize( event[1], @entities )
- event << unnormalized
- end
- PullEvent.new( event )
- end
-
- def unshift token
- @my_stack.unshift token
- end
- end
-
- # A parsing event. The contents of the event are accessed as an +Array?,
- # and the type is given either by the ...? methods, or by accessing the
- # +type+ accessor. The contents of this object vary from event to event,
- # but are identical to the arguments passed to +StreamListener+s for each
- # event.
- class PullEvent
- # The type of this event. Will be one of :tag_start, :tag_end, :text,
- # :processing_instruction, :comment, :doctype, :attlistdecl, :entitydecl,
- # :notationdecl, :entity, :cdata, :xmldecl, or :error.
- def initialize(arg)
- @contents = arg
- end
-
- def []( start, endd=nil)
- if start.kind_of? Range
- @contents.slice( start.begin+1 .. start.end )
- elsif start.kind_of? Numeric
- if endd.nil?
- @contents.slice( start+1 )
- else
- @contents.slice( start+1, endd )
- end
- else
- raise "Illegal argument #{start.inspect} (#{start.class})"
- end
- end
-
- def event_type
- @contents[0]
- end
-
- # Content: [ String tag_name, Hash attributes ]
- def start_element?
- @contents[0] == :start_element
- end
-
- # Content: [ String tag_name ]
- def end_element?
- @contents[0] == :end_element
- end
-
- # Content: [ String raw_text, String unnormalized_text ]
- def text?
- @contents[0] == :text
- end
-
- # Content: [ String text ]
- def instruction?
- @contents[0] == :processing_instruction
- end
-
- # Content: [ String text ]
- def comment?
- @contents[0] == :comment
- end
-
- # Content: [ String name, String pub_sys, String long_name, String uri ]
- def doctype?
- @contents[0] == :start_doctype
- end
-
- # Content: [ String text ]
- def attlistdecl?
- @contents[0] == :attlistdecl
- end
-
- # Content: [ String text ]
- def elementdecl?
- @contents[0] == :elementdecl
- end
-
- # Due to the wonders of DTDs, an entity declaration can be just about
- # anything. There's no way to normalize it; you'll have to interpret the
- # content yourself. However, the following is true:
- #
- # * If the entity declaration is an internal entity:
- # [ String name, String value ]
- # Content: [ String text ]
- def entitydecl?
- @contents[0] == :entitydecl
- end
-
- # Content: [ String text ]
- def notationdecl?
- @contents[0] == :notationdecl
- end
-
- # Content: [ String text ]
- def entity?
- @contents[0] == :entity
- end
-
- # Content: [ String text ]
- def cdata?
- @contents[0] == :cdata
- end
-
- # Content: [ String version, String encoding, String standalone ]
- def xmldecl?
- @contents[0] == :xmldecl
- end
-
- def error?
- @contents[0] == :error
- end
-
- def inspect
- @contents[0].to_s + ": " + @contents[1..-1].inspect
- end
- end
- end
-end
diff --git a/lib/rexml/parsers/sax2parser.rb b/lib/rexml/parsers/sax2parser.rb
deleted file mode 100644
index 6a24ce2227..0000000000
--- a/lib/rexml/parsers/sax2parser.rb
+++ /dev/null
@@ -1,273 +0,0 @@
-# frozen_string_literal: false
-require_relative 'baseparser'
-require_relative '../parseexception'
-require_relative '../namespace'
-require_relative '../text'
-
-module REXML
- module Parsers
- # SAX2Parser
- class SAX2Parser
- def initialize source
- @parser = BaseParser.new(source)
- @listeners = []
- @procs = []
- @namespace_stack = []
- @has_listeners = false
- @tag_stack = []
- @entities = {}
- end
-
- def source
- @parser.source
- end
-
- def add_listener( listener )
- @parser.add_listener( listener )
- end
-
- # Listen arguments:
- #
- # Symbol, Array, Block
- # Listen to Symbol events on Array elements
- # Symbol, Block
- # Listen to Symbol events
- # Array, Listener
- # Listen to all events on Array elements
- # Array, Block
- # Listen to :start_element events on Array elements
- # Listener
- # Listen to All events
- #
- # Symbol can be one of: :start_element, :end_element,
- # :start_prefix_mapping, :end_prefix_mapping, :characters,
- # :processing_instruction, :doctype, :attlistdecl, :elementdecl,
- # :entitydecl, :notationdecl, :cdata, :xmldecl, :comment
- #
- # There is an additional symbol that can be listened for: :progress.
- # This will be called for every event generated, passing in the current
- # stream position.
- #
- # Array contains regular expressions or strings which will be matched
- # against fully qualified element names.
- #
- # Listener must implement the methods in SAX2Listener
- #
- # Block will be passed the same arguments as a SAX2Listener method would
- # be, where the method name is the same as the matched Symbol.
- # See the SAX2Listener for more information.
- def listen( *args, &blok )
- if args[0].kind_of? Symbol
- if args.size == 2
- args[1].each { |match| @procs << [args[0], match, blok] }
- else
- add( [args[0], nil, blok] )
- end
- elsif args[0].kind_of? Array
- if args.size == 2
- args[0].each { |match| add( [nil, match, args[1]] ) }
- else
- args[0].each { |match| add( [ :start_element, match, blok ] ) }
- end
- else
- add([nil, nil, args[0]])
- end
- end
-
- def deafen( listener=nil, &blok )
- if listener
- @listeners.delete_if {|item| item[-1] == listener }
- @has_listeners = false if @listeners.size == 0
- else
- @procs.delete_if {|item| item[-1] == blok }
- end
- end
-
- def parse
- @procs.each { |sym,match,block| block.call if sym == :start_document }
- @listeners.each { |sym,match,block|
- block.start_document if sym == :start_document or sym.nil?
- }
- context = []
- while true
- event = @parser.pull
- case event[0]
- when :end_document
- handle( :end_document )
- break
- when :start_doctype
- handle( :doctype, *event[1..-1])
- when :end_doctype
- context = context[1]
- when :start_element
- @tag_stack.push(event[1])
- # find the observers for namespaces
- procs = get_procs( :start_prefix_mapping, event[1] )
- listeners = get_listeners( :start_prefix_mapping, event[1] )
- if procs or listeners
- # break out the namespace declarations
- # The attributes live in event[2]
- event[2].each {|n, v| event[2][n] = @parser.normalize(v)}
- nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ }
- nsdecl.collect! { |n, value| [ n[6..-1], value ] }
- @namespace_stack.push({})
- nsdecl.each do |n,v|
- @namespace_stack[-1][n] = v
- # notify observers of namespaces
- procs.each { |ob| ob.call( n, v ) } if procs
- listeners.each { |ob| ob.start_prefix_mapping(n, v) } if listeners
- end
- end
- event[1] =~ Namespace::NAMESPLIT
- prefix = $1
- local = $2
- uri = get_namespace(prefix)
- # find the observers for start_element
- procs = get_procs( :start_element, event[1] )
- listeners = get_listeners( :start_element, event[1] )
- # notify observers
- procs.each { |ob| ob.call( uri, local, event[1], event[2] ) } if procs
- listeners.each { |ob|
- ob.start_element( uri, local, event[1], event[2] )
- } if listeners
- when :end_element
- @tag_stack.pop
- event[1] =~ Namespace::NAMESPLIT
- prefix = $1
- local = $2
- uri = get_namespace(prefix)
- # find the observers for start_element
- procs = get_procs( :end_element, event[1] )
- listeners = get_listeners( :end_element, event[1] )
- # notify observers
- procs.each { |ob| ob.call( uri, local, event[1] ) } if procs
- listeners.each { |ob|
- ob.end_element( uri, local, event[1] )
- } if listeners
-
- namespace_mapping = @namespace_stack.pop
- # find the observers for namespaces
- procs = get_procs( :end_prefix_mapping, event[1] )
- listeners = get_listeners( :end_prefix_mapping, event[1] )
- if procs or listeners
- namespace_mapping.each do |ns_prefix, ns_uri|
- # notify observers of namespaces
- procs.each { |ob| ob.call( ns_prefix ) } if procs
- listeners.each { |ob| ob.end_prefix_mapping(ns_prefix) } if listeners
- end
- end
- when :text
- #normalized = @parser.normalize( event[1] )
- #handle( :characters, normalized )
- copy = event[1].clone
-
- esub = proc { |match|
- if @entities.has_key?($1)
- @entities[$1].gsub(Text::REFERENCE, &esub)
- else
- match
- end
- }
-
- copy.gsub!( Text::REFERENCE, &esub )
- copy.gsub!( Text::NUMERICENTITY ) {|m|
- m=$1
- m = "0#{m}" if m[0] == ?x
- [Integer(m)].pack('U*')
- }
- handle( :characters, copy )
- when :entitydecl
- handle_entitydecl( event )
- when :processing_instruction, :comment, :attlistdecl,
- :elementdecl, :cdata, :notationdecl, :xmldecl
- handle( *event )
- end
- handle( :progress, @parser.position )
- end
- end
-
- private
- def handle( symbol, *arguments )
- tag = @tag_stack[-1]
- procs = get_procs( symbol, tag )
- listeners = get_listeners( symbol, tag )
- # notify observers
- procs.each { |ob| ob.call( *arguments ) } if procs
- listeners.each { |l|
- l.send( symbol.to_s, *arguments )
- } if listeners
- end
-
- def handle_entitydecl( event )
- @entities[ event[1] ] = event[2] if event.size == 3
- parameter_reference_p = false
- case event[2]
- when "SYSTEM"
- if event.size == 5
- if event.last == "%"
- parameter_reference_p = true
- else
- event[4, 0] = "NDATA"
- end
- end
- when "PUBLIC"
- if event.size == 6
- if event.last == "%"
- parameter_reference_p = true
- else
- event[5, 0] = "NDATA"
- end
- end
- else
- parameter_reference_p = (event.size == 4)
- end
- event[1, 0] = event.pop if parameter_reference_p
- handle( event[0], event[1..-1] )
- end
-
- # The following methods are duplicates, but it is faster than using
- # a helper
- def get_procs( symbol, name )
- return nil if @procs.size == 0
- @procs.find_all do |sym, match, block|
- (
- (sym.nil? or symbol == sym) and
- ((name.nil? and match.nil?) or match.nil? or (
- (name == match) or
- (match.kind_of? Regexp and name =~ match)
- )
- )
- )
- end.collect{|x| x[-1]}
- end
- def get_listeners( symbol, name )
- return nil if @listeners.size == 0
- @listeners.find_all do |sym, match, block|
- (
- (sym.nil? or symbol == sym) and
- ((name.nil? and match.nil?) or match.nil? or (
- (name == match) or
- (match.kind_of? Regexp and name =~ match)
- )
- )
- )
- end.collect{|x| x[-1]}
- end
-
- def add( pair )
- if pair[-1].respond_to? :call
- @procs << pair unless @procs.include? pair
- else
- @listeners << pair unless @listeners.include? pair
- @has_listeners = true
- end
- end
-
- def get_namespace( prefix )
- uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) ||
- (@namespace_stack.find { |ns| not ns[nil].nil? })
- uris[-1][prefix] unless uris.nil? or 0 == uris.size
- end
- end
- end
-end
diff --git a/lib/rexml/parsers/streamparser.rb b/lib/rexml/parsers/streamparser.rb
deleted file mode 100644
index 9e0eb0b363..0000000000
--- a/lib/rexml/parsers/streamparser.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: false
-require_relative "baseparser"
-
-module REXML
- module Parsers
- class StreamParser
- def initialize source, listener
- @listener = listener
- @parser = BaseParser.new( source )
- @tag_stack = []
- end
-
- def add_listener( listener )
- @parser.add_listener( listener )
- end
-
- def parse
- # entity string
- while true
- event = @parser.pull
- case event[0]
- when :end_document
- unless @tag_stack.empty?
- tag_path = "/" + @tag_stack.join("/")
- raise ParseException.new("Missing end tag for '#{tag_path}'",
- @parser.source)
- end
- return
- when :start_element
- @tag_stack << event[1]
- attrs = event[2].each do |n, v|
- event[2][n] = @parser.unnormalize( v )
- end
- @listener.tag_start( event[1], attrs )
- when :end_element
- @listener.tag_end( event[1] )
- @tag_stack.pop
- when :text
- normalized = @parser.unnormalize( event[1] )
- @listener.text( normalized )
- when :processing_instruction
- @listener.instruction( *event[1,2] )
- when :start_doctype
- @listener.doctype( *event[1..-1] )
- when :end_doctype
- # FIXME: remove this condition for milestone:3.2
- @listener.doctype_end if @listener.respond_to? :doctype_end
- when :comment, :attlistdecl, :cdata, :xmldecl, :elementdecl
- @listener.send( event[0].to_s, *event[1..-1] )
- when :entitydecl, :notationdecl
- @listener.send( event[0].to_s, event[1..-1] )
- when :externalentity
- entity_reference = event[1]
- content = entity_reference.gsub(/\A%|;\z/, "")
- @listener.entity(content)
- end
- end
- end
- end
- end
-end
diff --git a/lib/rexml/parsers/treeparser.rb b/lib/rexml/parsers/treeparser.rb
deleted file mode 100644
index bf9a42545b..0000000000
--- a/lib/rexml/parsers/treeparser.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: false
-require_relative '../validation/validationexception'
-require_relative '../undefinednamespaceexception'
-
-module REXML
- module Parsers
- class TreeParser
- def initialize( source, build_context = Document.new )
- @build_context = build_context
- @parser = Parsers::BaseParser.new( source )
- end
-
- def add_listener( listener )
- @parser.add_listener( listener )
- end
-
- def parse
- tag_stack = []
- in_doctype = false
- entities = nil
- begin
- while true
- event = @parser.pull
- #STDERR.puts "TREEPARSER GOT #{event.inspect}"
- case event[0]
- when :end_document
- unless tag_stack.empty?
- raise ParseException.new("No close tag for #{@build_context.xpath}",
- @parser.source, @parser)
- end
- return
- when :start_element
- tag_stack.push(event[1])
- el = @build_context = @build_context.add_element( event[1] )
- event[2].each do |key, value|
- el.attributes[key]=Attribute.new(key,value,self)
- end
- when :end_element
- tag_stack.pop
- @build_context = @build_context.parent
- when :text
- if not in_doctype
- if @build_context[-1].instance_of? Text
- @build_context[-1] << event[1]
- else
- @build_context.add(
- Text.new(event[1], @build_context.whitespace, nil, true)
- ) unless (
- @build_context.ignore_whitespace_nodes and
- event[1].strip.size==0
- )
- end
- end
- when :comment
- c = Comment.new( event[1] )
- @build_context.add( c )
- when :cdata
- c = CData.new( event[1] )
- @build_context.add( c )
- when :processing_instruction
- @build_context.add( Instruction.new( event[1], event[2] ) )
- when :end_doctype
- in_doctype = false
- entities.each { |k,v| entities[k] = @build_context.entities[k].value }
- @build_context = @build_context.parent
- when :start_doctype
- doctype = DocType.new( event[1..-1], @build_context )
- @build_context = doctype
- entities = {}
- in_doctype = true
- when :attlistdecl
- n = AttlistDecl.new( event[1..-1] )
- @build_context.add( n )
- when :externalentity
- n = ExternalEntity.new( event[1] )
- @build_context.add( n )
- when :elementdecl
- n = ElementDecl.new( event[1] )
- @build_context.add(n)
- when :entitydecl
- entities[ event[1] ] = event[2] unless event[2] =~ /PUBLIC|SYSTEM/
- @build_context.add(Entity.new(event))
- when :notationdecl
- n = NotationDecl.new( *event[1..-1] )
- @build_context.add( n )
- when :xmldecl
- x = XMLDecl.new( event[1], event[2], event[3] )
- @build_context.add( x )
- end
- end
- rescue REXML::Validation::ValidationException
- raise
- rescue REXML::ParseException
- raise
- rescue
- raise ParseException.new( $!.message, @parser.source, @parser, $! )
- end
- end
- end
- end
-end
diff --git a/lib/rexml/parsers/ultralightparser.rb b/lib/rexml/parsers/ultralightparser.rb
deleted file mode 100644
index e0029f43da..0000000000
--- a/lib/rexml/parsers/ultralightparser.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: false
-require_relative 'streamparser'
-require_relative 'baseparser'
-
-module REXML
- module Parsers
- class UltraLightParser
- def initialize stream
- @stream = stream
- @parser = REXML::Parsers::BaseParser.new( stream )
- end
-
- def add_listener( listener )
- @parser.add_listener( listener )
- end
-
- def rewind
- @stream.rewind
- @parser.stream = @stream
- end
-
- def parse
- root = context = []
- while true
- event = @parser.pull
- case event[0]
- when :end_document
- break
- when :end_doctype
- context = context[1]
- when :start_element, :start_doctype
- context << event
- event[1,0] = [context]
- context = event
- when :end_element
- context = context[1]
- else
- context << event
- end
- end
- root
- end
- end
-
- # An element is an array. The array contains:
- # 0 The parent element
- # 1 The tag name
- # 2 A hash of attributes
- # 3..-1 The child elements
- # An element is an array of size > 3
- # Text is a String
- # PIs are [ :processing_instruction, target, data ]
- # Comments are [ :comment, data ]
- # DocTypes are DocType structs
- # The root is an array with XMLDecls, Text, DocType, Array, Text
- end
-end
diff --git a/lib/rexml/parsers/xpathparser.rb b/lib/rexml/parsers/xpathparser.rb
deleted file mode 100644
index d01d325e04..0000000000
--- a/lib/rexml/parsers/xpathparser.rb
+++ /dev/null
@@ -1,675 +0,0 @@
-# frozen_string_literal: false
-require_relative '../namespace'
-require_relative '../xmltokens'
-
-module REXML
- module Parsers
- # You don't want to use this class. Really. Use XPath, which is a wrapper
- # for this class. Believe me. You don't want to poke around in here.
- # There is strange, dark magic at work in this code. Beware. Go back! Go
- # back while you still can!
- class XPathParser
- include XMLTokens
- LITERAL = /^'([^']*)'|^"([^"]*)"/u
-
- def namespaces=( namespaces )
- Functions::namespace_context = namespaces
- @namespaces = namespaces
- end
-
- def parse path
- path = path.dup
- path.gsub!(/([\(\[])\s+/, '\1') # Strip ignorable spaces
- path.gsub!( /\s+([\]\)])/, '\1')
- parsed = []
- OrExpr(path, parsed)
- parsed
- end
-
- def predicate path
- parsed = []
- Predicate( "[#{path}]", parsed )
- parsed
- end
-
- def abbreviate( path )
- path = path.kind_of?(String) ? parse( path ) : path
- string = ""
- document = false
- while path.size > 0
- op = path.shift
- case op
- when :node
- when :attribute
- string << "/" if string.size > 0
- string << "@"
- when :child
- string << "/" if string.size > 0
- when :descendant_or_self
- string << "/"
- when :self
- string << "."
- when :parent
- string << ".."
- when :any
- string << "*"
- when :text
- string << "text()"
- when :following, :following_sibling,
- :ancestor, :ancestor_or_self, :descendant,
- :namespace, :preceding, :preceding_sibling
- string << "/" unless string.size == 0
- string << op.to_s.tr("_", "-")
- string << "::"
- when :qname
- prefix = path.shift
- name = path.shift
- string << prefix+":" if prefix.size > 0
- string << name
- when :predicate
- string << '['
- string << predicate_to_string( path.shift ) {|x| abbreviate( x ) }
- string << ']'
- when :document
- document = true
- when :function
- string << path.shift
- string << "( "
- string << predicate_to_string( path.shift[0] ) {|x| abbreviate( x )}
- string << " )"
- when :literal
- string << %Q{ "#{path.shift}" }
- else
- string << "/" unless string.size == 0
- string << "UNKNOWN("
- string << op.inspect
- string << ")"
- end
- end
- string = "/"+string if document
- return string
- end
-
- def expand( path )
- path = path.kind_of?(String) ? parse( path ) : path
- string = ""
- document = false
- while path.size > 0
- op = path.shift
- case op
- when :node
- string << "node()"
- when :attribute, :child, :following, :following_sibling,
- :ancestor, :ancestor_or_self, :descendant, :descendant_or_self,
- :namespace, :preceding, :preceding_sibling, :self, :parent
- string << "/" unless string.size == 0
- string << op.to_s.tr("_", "-")
- string << "::"
- when :any
- string << "*"
- when :qname
- prefix = path.shift
- name = path.shift
- string << prefix+":" if prefix.size > 0
- string << name
- when :predicate
- string << '['
- string << predicate_to_string( path.shift ) { |x| expand(x) }
- string << ']'
- when :document
- document = true
- else
- string << "/" unless string.size == 0
- string << "UNKNOWN("
- string << op.inspect
- string << ")"
- end
- end
- string = "/"+string if document
- return string
- end
-
- def predicate_to_string( path, &block )
- string = ""
- case path[0]
- when :and, :or, :mult, :plus, :minus, :neq, :eq, :lt, :gt, :lteq, :gteq, :div, :mod, :union
- op = path.shift
- case op
- when :eq
- op = "="
- when :lt
- op = "<"
- when :gt
- op = ">"
- when :lteq
- op = "<="
- when :gteq
- op = ">="
- when :neq
- op = "!="
- when :union
- op = "|"
- end
- left = predicate_to_string( path.shift, &block )
- right = predicate_to_string( path.shift, &block )
- string << " "
- string << left
- string << " "
- string << op.to_s
- string << " "
- string << right
- string << " "
- when :function
- path.shift
- name = path.shift
- string << name
- string << "( "
- string << predicate_to_string( path.shift, &block )
- string << " )"
- when :literal
- path.shift
- string << " "
- string << path.shift.inspect
- string << " "
- else
- string << " "
- string << yield( path )
- string << " "
- end
- return string.squeeze(" ")
- end
-
- private
- #LocationPath
- # | RelativeLocationPath
- # | '/' RelativeLocationPath?
- # | '//' RelativeLocationPath
- def LocationPath path, parsed
- path = path.lstrip
- if path[0] == ?/
- parsed << :document
- if path[1] == ?/
- parsed << :descendant_or_self
- parsed << :node
- path = path[2..-1]
- else
- path = path[1..-1]
- end
- end
- return RelativeLocationPath( path, parsed ) if path.size > 0
- end
-
- #RelativeLocationPath
- # | Step
- # | (AXIS_NAME '::' | '@' | '') AxisSpecifier
- # NodeTest
- # Predicate
- # | '.' | '..' AbbreviatedStep
- # | RelativeLocationPath '/' Step
- # | RelativeLocationPath '//' Step
- AXIS = /^(ancestor|ancestor-or-self|attribute|child|descendant|descendant-or-self|following|following-sibling|namespace|parent|preceding|preceding-sibling|self)::/
- def RelativeLocationPath path, parsed
- loop do
- original_path = path
- path = path.lstrip
-
- return original_path if path.empty?
-
- # (axis or @ or <child::>) nodetest predicate >
- # OR > / Step
- # (. or ..) >
- if path[0] == ?.
- if path[1] == ?.
- parsed << :parent
- parsed << :node
- path = path[2..-1]
- else
- parsed << :self
- parsed << :node
- path = path[1..-1]
- end
- else
- if path[0] == ?@
- parsed << :attribute
- path = path[1..-1]
- # Goto Nodetest
- elsif path =~ AXIS
- parsed << $1.tr('-','_').intern
- path = $'
- # Goto Nodetest
- else
- parsed << :child
- end
-
- n = []
- path = NodeTest( path, n)
-
- path = Predicate( path, n )
-
- parsed.concat(n)
- end
-
- original_path = path
- path = path.lstrip
- return original_path if path.empty?
-
- return original_path if path[0] != ?/
-
- if path[1] == ?/
- parsed << :descendant_or_self
- parsed << :node
- path = path[2..-1]
- else
- path = path[1..-1]
- end
- end
- end
-
- # Returns a 1-1 map of the nodeset
- # The contents of the resulting array are either:
- # true/false, if a positive match
- # String, if a name match
- #NodeTest
- # | ('*' | NCNAME ':' '*' | QNAME) NameTest
- # | '*' ':' NCNAME NameTest since XPath 2.0
- # | NODE_TYPE '(' ')' NodeType
- # | PI '(' LITERAL ')' PI
- # | '[' expr ']' Predicate
- PREFIX_WILDCARD = /^\*:(#{NCNAME_STR})/u
- LOCAL_NAME_WILDCARD = /^(#{NCNAME_STR}):\*/u
- QNAME = Namespace::NAMESPLIT
- NODE_TYPE = /^(comment|text|node)\(\s*\)/m
- PI = /^processing-instruction\(/
- def NodeTest path, parsed
- original_path = path
- path = path.lstrip
- case path
- when PREFIX_WILDCARD
- prefix = nil
- name = $1
- path = $'
- parsed << :qname
- parsed << prefix
- parsed << name
- when /^\*/
- path = $'
- parsed << :any
- when NODE_TYPE
- type = $1
- path = $'
- parsed << type.tr('-', '_').intern
- when PI
- path = $'
- literal = nil
- if path !~ /^\s*\)/
- path =~ LITERAL
- literal = $1
- path = $'
- raise ParseException.new("Missing ')' after processing instruction") if path[0] != ?)
- path = path[1..-1]
- end
- parsed << :processing_instruction
- parsed << (literal || '')
- when LOCAL_NAME_WILDCARD
- prefix = $1
- path = $'
- parsed << :namespace
- parsed << prefix
- when QNAME
- prefix = $1
- name = $2
- path = $'
- prefix = "" unless prefix
- parsed << :qname
- parsed << prefix
- parsed << name
- else
- path = original_path
- end
- return path
- end
-
- # Filters the supplied nodeset on the predicate(s)
- def Predicate path, parsed
- original_path = path
- path = path.lstrip
- return original_path unless path[0] == ?[
- predicates = []
- while path[0] == ?[
- path, expr = get_group(path)
- predicates << expr[1..-2] if expr
- end
- predicates.each{ |pred|
- preds = []
- parsed << :predicate
- parsed << preds
- OrExpr(pred, preds)
- }
- path
- end
-
- # The following return arrays of true/false, a 1-1 mapping of the
- # supplied nodeset, except for axe(), which returns a filtered
- # nodeset
-
- #| OrExpr S 'or' S AndExpr
- #| AndExpr
- def OrExpr path, parsed
- n = []
- rest = AndExpr( path, n )
- if rest != path
- while rest =~ /^\s*( or )/
- n = [ :or, n, [] ]
- rest = AndExpr( $', n[-1] )
- end
- end
- if parsed.size == 0 and n.size != 0
- parsed.replace(n)
- elsif n.size > 0
- parsed << n
- end
- rest
- end
-
- #| AndExpr S 'and' S EqualityExpr
- #| EqualityExpr
- def AndExpr path, parsed
- n = []
- rest = EqualityExpr( path, n )
- if rest != path
- while rest =~ /^\s*( and )/
- n = [ :and, n, [] ]
- rest = EqualityExpr( $', n[-1] )
- end
- end
- if parsed.size == 0 and n.size != 0
- parsed.replace(n)
- elsif n.size > 0
- parsed << n
- end
- rest
- end
-
- #| EqualityExpr ('=' | '!=') RelationalExpr
- #| RelationalExpr
- def EqualityExpr path, parsed
- n = []
- rest = RelationalExpr( path, n )
- if rest != path
- while rest =~ /^\s*(!?=)\s*/
- if $1[0] == ?!
- n = [ :neq, n, [] ]
- else
- n = [ :eq, n, [] ]
- end
- rest = RelationalExpr( $', n[-1] )
- end
- end
- if parsed.size == 0 and n.size != 0
- parsed.replace(n)
- elsif n.size > 0
- parsed << n
- end
- rest
- end
-
- #| RelationalExpr ('<' | '>' | '<=' | '>=') AdditiveExpr
- #| AdditiveExpr
- def RelationalExpr path, parsed
- n = []
- rest = AdditiveExpr( path, n )
- if rest != path
- while rest =~ /^\s*([<>]=?)\s*/
- if $1[0] == ?<
- sym = "lt"
- else
- sym = "gt"
- end
- sym << "eq" if $1[-1] == ?=
- n = [ sym.intern, n, [] ]
- rest = AdditiveExpr( $', n[-1] )
- end
- end
- if parsed.size == 0 and n.size != 0
- parsed.replace(n)
- elsif n.size > 0
- parsed << n
- end
- rest
- end
-
- #| AdditiveExpr ('+' | '-') MultiplicativeExpr
- #| MultiplicativeExpr
- def AdditiveExpr path, parsed
- n = []
- rest = MultiplicativeExpr( path, n )
- if rest != path
- while rest =~ /^\s*(\+|-)\s*/
- if $1[0] == ?+
- n = [ :plus, n, [] ]
- else
- n = [ :minus, n, [] ]
- end
- rest = MultiplicativeExpr( $', n[-1] )
- end
- end
- if parsed.size == 0 and n.size != 0
- parsed.replace(n)
- elsif n.size > 0
- parsed << n
- end
- rest
- end
-
- #| MultiplicativeExpr ('*' | S ('div' | 'mod') S) UnaryExpr
- #| UnaryExpr
- def MultiplicativeExpr path, parsed
- n = []
- rest = UnaryExpr( path, n )
- if rest != path
- while rest =~ /^\s*(\*| div | mod )\s*/
- if $1[0] == ?*
- n = [ :mult, n, [] ]
- elsif $1.include?( "div" )
- n = [ :div, n, [] ]
- else
- n = [ :mod, n, [] ]
- end
- rest = UnaryExpr( $', n[-1] )
- end
- end
- if parsed.size == 0 and n.size != 0
- parsed.replace(n)
- elsif n.size > 0
- parsed << n
- end
- rest
- end
-
- #| '-' UnaryExpr
- #| UnionExpr
- def UnaryExpr path, parsed
- path =~ /^(\-*)/
- path = $'
- if $1 and (($1.size % 2) != 0)
- mult = -1
- else
- mult = 1
- end
- parsed << :neg if mult < 0
-
- n = []
- path = UnionExpr( path, n )
- parsed.concat( n )
- path
- end
-
- #| UnionExpr '|' PathExpr
- #| PathExpr
- def UnionExpr path, parsed
- n = []
- rest = PathExpr( path, n )
- if rest != path
- while rest =~ /^\s*(\|)\s*/
- n = [ :union, n, [] ]
- rest = PathExpr( $', n[-1] )
- end
- end
- if parsed.size == 0 and n.size != 0
- parsed.replace( n )
- elsif n.size > 0
- parsed << n
- end
- rest
- end
-
- #| LocationPath
- #| FilterExpr ('/' | '//') RelativeLocationPath
- def PathExpr path, parsed
- path = path.lstrip
- n = []
- rest = FilterExpr( path, n )
- if rest != path
- if rest and rest[0] == ?/
- rest = RelativeLocationPath(rest, n)
- parsed.concat(n)
- return rest
- end
- end
- rest = LocationPath(rest, n) if rest =~ /\A[\/\.\@\[\w*]/
- parsed.concat(n)
- return rest
- end
-
- #| FilterExpr Predicate
- #| PrimaryExpr
- def FilterExpr path, parsed
- n = []
- path = PrimaryExpr( path, n )
- path = Predicate(path, n)
- parsed.concat(n)
- path
- end
-
- #| VARIABLE_REFERENCE
- #| '(' expr ')'
- #| LITERAL
- #| NUMBER
- #| FunctionCall
- VARIABLE_REFERENCE = /^\$(#{NAME_STR})/u
- NUMBER = /^(\d*\.?\d+)/
- NT = /^comment|text|processing-instruction|node$/
- def PrimaryExpr path, parsed
- case path
- when VARIABLE_REFERENCE
- varname = $1
- path = $'
- parsed << :variable
- parsed << varname
- #arry << @variables[ varname ]
- when /^(\w[-\w]*)(?:\()/
- fname = $1
- tmp = $'
- return path if fname =~ NT
- path = tmp
- parsed << :function
- parsed << fname
- path = FunctionCall(path, parsed)
- when NUMBER
- varname = $1.nil? ? $2 : $1
- path = $'
- parsed << :literal
- parsed << (varname.include?('.') ? varname.to_f : varname.to_i)
- when LITERAL
- varname = $1.nil? ? $2 : $1
- path = $'
- parsed << :literal
- parsed << varname
- when /^\(/ #/
- path, contents = get_group(path)
- contents = contents[1..-2]
- n = []
- OrExpr( contents, n )
- parsed.concat(n)
- end
- path
- end
-
- #| FUNCTION_NAME '(' ( expr ( ',' expr )* )? ')'
- def FunctionCall rest, parsed
- path, arguments = parse_args(rest)
- argset = []
- for argument in arguments
- args = []
- OrExpr( argument, args )
- argset << args
- end
- parsed << argset
- path
- end
-
- # get_group( '[foo]bar' ) -> ['bar', '[foo]']
- def get_group string
- ind = 0
- depth = 0
- st = string[0,1]
- en = (st == "(" ? ")" : "]")
- begin
- case string[ind,1]
- when st
- depth += 1
- when en
- depth -= 1
- end
- ind += 1
- end while depth > 0 and ind < string.length
- return nil unless depth==0
- [string[ind..-1], string[0..ind-1]]
- end
-
- def parse_args( string )
- arguments = []
- ind = 0
- inquot = false
- inapos = false
- depth = 1
- begin
- case string[ind]
- when ?"
- inquot = !inquot unless inapos
- when ?'
- inapos = !inapos unless inquot
- else
- unless inquot or inapos
- case string[ind]
- when ?(
- depth += 1
- if depth == 1
- string = string[1..-1]
- ind -= 1
- end
- when ?)
- depth -= 1
- if depth == 0
- s = string[0,ind].strip
- arguments << s unless s == ""
- string = string[ind+1..-1]
- end
- when ?,
- if depth == 1
- s = string[0,ind].strip
- arguments << s unless s == ""
- string = string[ind+1..-1]
- ind = -1
- end
- end
- end
- end
- ind += 1
- end while depth > 0 and ind < string.length
- return nil unless depth==0
- [string,arguments]
- end
- end
- end
-end
diff --git a/lib/rexml/quickpath.rb b/lib/rexml/quickpath.rb
deleted file mode 100644
index a0466b25d9..0000000000
--- a/lib/rexml/quickpath.rb
+++ /dev/null
@@ -1,266 +0,0 @@
-# frozen_string_literal: false
-require_relative 'functions'
-require_relative 'xmltokens'
-
-module REXML
- class QuickPath
- include Functions
- include XMLTokens
-
- # A base Hash object to be used when initializing a
- # default empty namespaces set.
- EMPTY_HASH = {}
-
- def QuickPath::first element, path, namespaces=EMPTY_HASH
- match(element, path, namespaces)[0]
- end
-
- def QuickPath::each element, path, namespaces=EMPTY_HASH, &block
- path = "*" unless path
- match(element, path, namespaces).each( &block )
- end
-
- def QuickPath::match element, path, namespaces=EMPTY_HASH
- raise "nil is not a valid xpath" unless path
- results = nil
- Functions::namespace_context = namespaces
- case path
- when /^\/([^\/]|$)/u
- # match on root
- path = path[1..-1]
- return [element.root.parent] if path == ''
- results = filter([element.root], path)
- when /^[-\w]*::/u
- results = filter([element], path)
- when /^\*/u
- results = filter(element.to_a, path)
- when /^[\[!\w:]/u
- # match on child
- children = element.to_a
- results = filter(children, path)
- else
- results = filter([element], path)
- end
- return results
- end
-
- # Given an array of nodes it filters the array based on the path. The
- # result is that when this method returns, the array will contain elements
- # which match the path
- def QuickPath::filter elements, path
- return elements if path.nil? or path == '' or elements.size == 0
- case path
- when /^\/\//u # Descendant
- return axe( elements, "descendant-or-self", $' )
- when /^\/?\b(\w[-\w]*)\b::/u # Axe
- return axe( elements, $1, $' )
- when /^\/(?=\b([:!\w][-\.\w]*:)?[-!\*\.\w]*\b([^:(]|$)|\*)/u # Child
- rest = $'
- results = []
- elements.each do |element|
- results |= filter( element.to_a, rest )
- end
- return results
- when /^\/?(\w[-\w]*)\(/u # / Function
- return function( elements, $1, $' )
- when Namespace::NAMESPLIT # Element name
- name = $2
- ns = $1
- rest = $'
- elements.delete_if do |element|
- !(element.kind_of? Element and
- (element.expanded_name == name or
- (element.name == name and
- element.namespace == Functions.namespace_context[ns])))
- end
- return filter( elements, rest )
- when /^\/\[/u
- matches = []
- elements.each do |element|
- matches |= predicate( element.to_a, path[1..-1] ) if element.kind_of? Element
- end
- return matches
- when /^\[/u # Predicate
- return predicate( elements, path )
- when /^\/?\.\.\./u # Ancestor
- return axe( elements, "ancestor", $' )
- when /^\/?\.\./u # Parent
- return filter( elements.collect{|e|e.parent}, $' )
- when /^\/?\./u # Self
- return filter( elements, $' )
- when /^\*/u # Any
- results = []
- elements.each do |element|
- results |= filter( [element], $' ) if element.kind_of? Element
- #if element.kind_of? Element
- # children = element.to_a
- # children.delete_if { |child| !child.kind_of?(Element) }
- # results |= filter( children, $' )
- #end
- end
- return results
- end
- return []
- end
-
- def QuickPath::axe( elements, axe_name, rest )
- matches = []
- matches = filter( elements.dup, rest ) if axe_name =~ /-or-self$/u
- case axe_name
- when /^descendant/u
- elements.each do |element|
- matches |= filter( element.to_a, "descendant-or-self::#{rest}" ) if element.kind_of? Element
- end
- when /^ancestor/u
- elements.each do |element|
- while element.parent
- matches << element.parent
- element = element.parent
- end
- end
- matches = filter( matches, rest )
- when "self"
- matches = filter( elements, rest )
- when "child"
- elements.each do |element|
- matches |= filter( element.to_a, rest ) if element.kind_of? Element
- end
- when "attribute"
- elements.each do |element|
- matches << element.attributes[ rest ] if element.kind_of? Element
- end
- when "parent"
- matches = filter(elements.collect{|element| element.parent}.uniq, rest)
- when "following-sibling"
- matches = filter(elements.collect{|element| element.next_sibling}.uniq,
- rest)
- when "previous-sibling"
- matches = filter(elements.collect{|element|
- element.previous_sibling}.uniq, rest )
- end
- return matches.uniq
- end
-
- OPERAND_ = '((?=(?:(?!and|or).)*[^\s<>=])[^\s<>=]+)'
- # A predicate filters a node-set with respect to an axis to produce a
- # new node-set. For each node in the node-set to be filtered, the
- # PredicateExpr is evaluated with that node as the context node, with
- # the number of nodes in the node-set as the context size, and with the
- # proximity position of the node in the node-set with respect to the
- # axis as the context position; if PredicateExpr evaluates to true for
- # that node, the node is included in the new node-set; otherwise, it is
- # not included.
- #
- # A PredicateExpr is evaluated by evaluating the Expr and converting
- # the result to a boolean. If the result is a number, the result will
- # be converted to true if the number is equal to the context position
- # and will be converted to false otherwise; if the result is not a
- # number, then the result will be converted as if by a call to the
- # boolean function. Thus a location path para[3] is equivalent to
- # para[position()=3].
- def QuickPath::predicate( elements, path )
- ind = 1
- bcount = 1
- while bcount > 0
- bcount += 1 if path[ind] == ?[
- bcount -= 1 if path[ind] == ?]
- ind += 1
- end
- ind -= 1
- predicate = path[1..ind-1]
- rest = path[ind+1..-1]
-
- # have to change 'a [=<>] b [=<>] c' into 'a [=<>] b and b [=<>] c'
- #
- predicate.gsub!(
- /#{OPERAND_}\s*([<>=])\s*#{OPERAND_}\s*([<>=])\s*#{OPERAND_}/u,
- '\1 \2 \3 and \3 \4 \5' )
- # Let's do some Ruby trickery to avoid some work:
- predicate.gsub!( /&/u, "&&" )
- predicate.gsub!( /=/u, "==" )
- predicate.gsub!( /@(\w[-\w.]*)/u, 'attribute("\1")' )
- predicate.gsub!( /\bmod\b/u, "%" )
- predicate.gsub!( /\b(\w[-\w.]*\()/u ) {
- fname = $1
- fname.gsub( /-/u, "_" )
- }
-
- Functions.pair = [ 0, elements.size ]
- results = []
- elements.each do |element|
- Functions.pair[0] += 1
- Functions.node = element
- res = eval( predicate )
- case res
- when true
- results << element
- when Integer
- results << element if Functions.pair[0] == res
- when String
- results << element
- end
- end
- return filter( results, rest )
- end
-
- def QuickPath::attribute( name )
- return Functions.node.attributes[name] if Functions.node.kind_of? Element
- end
-
- def QuickPath::name()
- return Functions.node.name if Functions.node.kind_of? Element
- end
-
- def QuickPath::method_missing( id, *args )
- begin
- Functions.send( id.id2name, *args )
- rescue Exception
- raise "METHOD: #{id.id2name}(#{args.join ', '})\n#{$!.message}"
- end
- end
-
- def QuickPath::function( elements, fname, rest )
- args = parse_args( elements, rest )
- Functions.pair = [0, elements.size]
- results = []
- elements.each do |element|
- Functions.pair[0] += 1
- Functions.node = element
- res = Functions.send( fname, *args )
- case res
- when true
- results << element
- when Integer
- results << element if Functions.pair[0] == res
- end
- end
- return results
- end
-
- def QuickPath::parse_args( element, string )
- # /.*?(?:\)|,)/
- arguments = []
- buffer = ""
- while string and string != ""
- c = string[0]
- string.sub!(/^./u, "")
- case c
- when ?,
- # if depth = 1, then we start a new argument
- arguments << evaluate( buffer )
- #arguments << evaluate( string[0..count] )
- when ?(
- # start a new method call
- function( element, buffer, string )
- buffer = ""
- when ?)
- # close the method call and return arguments
- return arguments
- else
- buffer << c
- end
- end
- ""
- end
- end
-end
diff --git a/lib/rexml/rexml.gemspec b/lib/rexml/rexml.gemspec
deleted file mode 100644
index 263f013aae..0000000000
--- a/lib/rexml/rexml.gemspec
+++ /dev/null
@@ -1,84 +0,0 @@
-begin
- require_relative "lib/rexml/rexml"
-rescue LoadError
- # for Ruby core repository
- require_relative "rexml"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "rexml"
- spec.version = REXML::VERSION
- spec.authors = ["Kouhei Sutou"]
- spec.email = ["kou@cozmixng.org"]
-
- spec.summary = %q{An XML toolkit for Ruby}
- spec.description = %q{An XML toolkit for Ruby}
- spec.homepage = "https://github.com/ruby/rexml"
- spec.license = "BSD-2-Clause"
-
- spec.files = [
- ".gitignore",
- ".travis.yml",
- "Gemfile",
- "LICENSE.txt",
- "NEWS.md",
- "README.md",
- "Rakefile",
- "lib/rexml/attlistdecl.rb",
- "lib/rexml/attribute.rb",
- "lib/rexml/cdata.rb",
- "lib/rexml/child.rb",
- "lib/rexml/comment.rb",
- "lib/rexml/doctype.rb",
- "lib/rexml/document.rb",
- "lib/rexml/dtd/attlistdecl.rb",
- "lib/rexml/dtd/dtd.rb",
- "lib/rexml/dtd/elementdecl.rb",
- "lib/rexml/dtd/entitydecl.rb",
- "lib/rexml/dtd/notationdecl.rb",
- "lib/rexml/element.rb",
- "lib/rexml/encoding.rb",
- "lib/rexml/entity.rb",
- "lib/rexml/formatters/default.rb",
- "lib/rexml/formatters/pretty.rb",
- "lib/rexml/formatters/transitive.rb",
- "lib/rexml/functions.rb",
- "lib/rexml/instruction.rb",
- "lib/rexml/light/node.rb",
- "lib/rexml/namespace.rb",
- "lib/rexml/node.rb",
- "lib/rexml/output.rb",
- "lib/rexml/parent.rb",
- "lib/rexml/parseexception.rb",
- "lib/rexml/parsers/baseparser.rb",
- "lib/rexml/parsers/lightparser.rb",
- "lib/rexml/parsers/pullparser.rb",
- "lib/rexml/parsers/sax2parser.rb",
- "lib/rexml/parsers/streamparser.rb",
- "lib/rexml/parsers/treeparser.rb",
- "lib/rexml/parsers/ultralightparser.rb",
- "lib/rexml/parsers/xpathparser.rb",
- "lib/rexml/quickpath.rb",
- "lib/rexml/rexml.rb",
- "lib/rexml/sax2listener.rb",
- "lib/rexml/security.rb",
- "lib/rexml/source.rb",
- "lib/rexml/streamlistener.rb",
- "lib/rexml/text.rb",
- "lib/rexml/undefinednamespaceexception.rb",
- "lib/rexml/validation/relaxng.rb",
- "lib/rexml/validation/validation.rb",
- "lib/rexml/validation/validationexception.rb",
- "lib/rexml/xmldecl.rb",
- "lib/rexml/xmltokens.rb",
- "lib/rexml/xpath.rb",
- "lib/rexml/xpath_parser.rb",
- "rexml.gemspec",
- ]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-
- spec.add_development_dependency "bundler"
- spec.add_development_dependency "rake"
-end
diff --git a/lib/rexml/rexml.rb b/lib/rexml/rexml.rb
deleted file mode 100644
index 3c991a1cfd..0000000000
--- a/lib/rexml/rexml.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-# REXML is an XML toolkit for Ruby[http://www.ruby-lang.org], in Ruby.
-#
-# REXML is a _pure_ Ruby, XML 1.0 conforming,
-# non-validating[http://www.w3.org/TR/2004/REC-xml-20040204/#sec-conformance]
-# toolkit with an intuitive API. REXML passes 100% of the non-validating Oasis
-# tests[http://www.oasis-open.org/committees/xml-conformance/xml-test-suite.shtml],
-# and provides tree, stream, SAX2, pull, and lightweight APIs. REXML also
-# includes a full XPath[http://www.w3c.org/tr/xpath] 1.0 implementation. Since
-# Ruby 1.8, REXML is included in the standard Ruby distribution.
-#
-# Main page:: http://www.germane-software.com/software/rexml
-# Author:: Sean Russell <serATgermaneHYPHENsoftwareDOTcom>
-# Date:: 2008/019
-# Version:: 3.1.7.3
-#
-# This API documentation can be downloaded from the REXML home page, or can
-# be accessed online[http://www.germane-software.com/software/rexml_doc]
-#
-# A tutorial is available in the REXML distribution in docs/tutorial.html,
-# or can be accessed
-# online[http://www.germane-software.com/software/rexml/docs/tutorial.html]
-module REXML
- COPYRIGHT = "Copyright © 2001-2008 Sean Russell <ser@germane-software.com>"
- DATE = "2008/019"
- VERSION = "3.2.3.1"
- REVISION = ""
-
- Copyright = COPYRIGHT
- Version = VERSION
-end
diff --git a/lib/rexml/sax2listener.rb b/lib/rexml/sax2listener.rb
deleted file mode 100644
index 5afdc80890..0000000000
--- a/lib/rexml/sax2listener.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# frozen_string_literal: false
-module REXML
- # A template for stream parser listeners.
- # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
- # processed; REXML doesn't yet handle doctype entity declarations, so you
- # have to parse them out yourself.
- # === Missing methods from SAX2
- # ignorable_whitespace
- # === Methods extending SAX2
- # +WARNING+
- # These methods are certainly going to change, until DTDs are fully
- # supported. Be aware of this.
- # start_document
- # end_document
- # doctype
- # elementdecl
- # attlistdecl
- # entitydecl
- # notationdecl
- # cdata
- # xmldecl
- # comment
- module SAX2Listener
- def start_document
- end
- def end_document
- end
- def start_prefix_mapping prefix, uri
- end
- def end_prefix_mapping prefix
- end
- def start_element uri, localname, qname, attributes
- end
- def end_element uri, localname, qname
- end
- def characters text
- end
- def processing_instruction target, data
- end
- # Handles a doctype declaration. Any attributes of the doctype which are
- # not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar">
- # @p name the name of the doctype; EG, "me"
- # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC"
- # @p long_name the supplied long name, or nil. EG, "foo"
- # @p uri the uri of the doctype, or nil. EG, "bar"
- def doctype name, pub_sys, long_name, uri
- end
- # If a doctype includes an ATTLIST declaration, it will cause this
- # method to be called. The content is the declaration itself, unparsed.
- # EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
- # attr CDATA #REQUIRED". This is the same for all of the .*decl
- # methods.
- def attlistdecl(element, pairs, contents)
- end
- # <!ELEMENT ...>
- def elementdecl content
- end
- # <!ENTITY ...>
- # The argument passed to this method is an array of the entity
- # declaration. It can be in a number of formats, but in general it
- # returns (example, result):
- # <!ENTITY % YN '"Yes"'>
- # ["%", "YN", "\"Yes\""]
- # <!ENTITY % YN 'Yes'>
- # ["%", "YN", "Yes"]
- # <!ENTITY WhatHeSaid "He said %YN;">
- # ["WhatHeSaid", "He said %YN;"]
- # <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
- # ["open-hatch", "SYSTEM", "http://www.textuality.com/boilerplate/OpenHatch.xml"]
- # <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
- # ["open-hatch", "PUBLIC", "-//Textuality//TEXT Standard open-hatch boilerplate//EN", "http://www.textuality.com/boilerplate/OpenHatch.xml"]
- # <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
- # ["hatch-pic", "SYSTEM", "../grafix/OpenHatch.gif", "NDATA", "gif"]
- def entitydecl declaration
- end
- # <!NOTATION ...>
- def notationdecl name, public_or_system, public_id, system_id
- end
- # Called when <![CDATA[ ... ]]> is encountered in a document.
- # @p content "..."
- def cdata content
- end
- # Called when an XML PI is encountered in the document.
- # EG: <?xml version="1.0" encoding="utf"?>
- # @p version the version attribute value. EG, "1.0"
- # @p encoding the encoding attribute value, or nil. EG, "utf"
- # @p standalone the standalone attribute value, or nil. EG, nil
- # @p spaced the declaration is followed by a line break
- def xmldecl version, encoding, standalone
- end
- # Called when a comment is encountered.
- # @p comment The content of the comment
- def comment comment
- end
- def progress position
- end
- end
-end
diff --git a/lib/rexml/security.rb b/lib/rexml/security.rb
deleted file mode 100644
index 99b7460772..0000000000
--- a/lib/rexml/security.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: false
-module REXML
- module Security
- @@entity_expansion_limit = 10_000
-
- # Set the entity expansion limit. By default the limit is set to 10000.
- def self.entity_expansion_limit=( val )
- @@entity_expansion_limit = val
- end
-
- # Get the entity expansion limit. By default the limit is set to 10000.
- def self.entity_expansion_limit
- return @@entity_expansion_limit
- end
-
- @@entity_expansion_text_limit = 10_240
-
- # Set the entity expansion limit. By default the limit is set to 10240.
- def self.entity_expansion_text_limit=( val )
- @@entity_expansion_text_limit = val
- end
-
- # Get the entity expansion limit. By default the limit is set to 10240.
- def self.entity_expansion_text_limit
- return @@entity_expansion_text_limit
- end
- end
-end
diff --git a/lib/rexml/source.rb b/lib/rexml/source.rb
deleted file mode 100644
index 90b370b989..0000000000
--- a/lib/rexml/source.rb
+++ /dev/null
@@ -1,298 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: false
-require_relative 'encoding'
-
-module REXML
- # Generates Source-s. USE THIS CLASS.
- class SourceFactory
- # Generates a Source object
- # @param arg Either a String, or an IO
- # @return a Source, or nil if a bad argument was given
- def SourceFactory::create_from(arg)
- if arg.respond_to? :read and
- arg.respond_to? :readline and
- arg.respond_to? :nil? and
- arg.respond_to? :eof?
- IOSource.new(arg)
- elsif arg.respond_to? :to_str
- require 'stringio'
- IOSource.new(StringIO.new(arg))
- elsif arg.kind_of? Source
- arg
- else
- raise "#{arg.class} is not a valid input stream. It must walk \n"+
- "like either a String, an IO, or a Source."
- end
- end
- end
-
- # A Source can be searched for patterns, and wraps buffers and other
- # objects and provides consumption of text
- class Source
- include Encoding
- # The current buffer (what we're going to read next)
- attr_reader :buffer
- # The line number of the last consumed text
- attr_reader :line
- attr_reader :encoding
-
- # Constructor
- # @param arg must be a String, and should be a valid XML document
- # @param encoding if non-null, sets the encoding of the source to this
- # value, overriding all encoding detection
- def initialize(arg, encoding=nil)
- @orig = @buffer = arg
- if encoding
- self.encoding = encoding
- else
- detect_encoding
- end
- @line = 0
- end
-
-
- # Inherited from Encoding
- # Overridden to support optimized en/decoding
- def encoding=(enc)
- return unless super
- encoding_updated
- end
-
- # Scans the source for a given pattern. Note, that this is not your
- # usual scan() method. For one thing, the pattern argument has some
- # requirements; for another, the source can be consumed. You can easily
- # confuse this method. Originally, the patterns were easier
- # to construct and this method more robust, because this method
- # generated search regexps on the fly; however, this was
- # computationally expensive and slowed down the entire REXML package
- # considerably, since this is by far the most commonly called method.
- # @param pattern must be a Regexp, and must be in the form of
- # /^\s*(#{your pattern, with no groups})(.*)/. The first group
- # will be returned; the second group is used if the consume flag is
- # set.
- # @param consume if true, the pattern returned will be consumed, leaving
- # everything after it in the Source.
- # @return the pattern, if found, or nil if the Source is empty or the
- # pattern is not found.
- def scan(pattern, cons=false)
- return nil if @buffer.nil?
- rv = @buffer.scan(pattern)
- @buffer = $' if cons and rv.size>0
- rv
- end
-
- def read
- end
-
- def consume( pattern )
- @buffer = $' if pattern.match( @buffer )
- end
-
- def match_to( char, pattern )
- return pattern.match(@buffer)
- end
-
- def match_to_consume( char, pattern )
- md = pattern.match(@buffer)
- @buffer = $'
- return md
- end
-
- def match(pattern, cons=false)
- md = pattern.match(@buffer)
- @buffer = $' if cons and md
- return md
- end
-
- # @return true if the Source is exhausted
- def empty?
- @buffer == ""
- end
-
- def position
- @orig.index( @buffer )
- end
-
- # @return the current line in the source
- def current_line
- lines = @orig.split
- res = lines.grep @buffer[0..30]
- res = res[-1] if res.kind_of? Array
- lines.index( res ) if res
- end
-
- private
- def detect_encoding
- buffer_encoding = @buffer.encoding
- detected_encoding = "UTF-8"
- begin
- @buffer.force_encoding("ASCII-8BIT")
- if @buffer[0, 2] == "\xfe\xff"
- @buffer[0, 2] = ""
- detected_encoding = "UTF-16BE"
- elsif @buffer[0, 2] == "\xff\xfe"
- @buffer[0, 2] = ""
- detected_encoding = "UTF-16LE"
- elsif @buffer[0, 3] == "\xef\xbb\xbf"
- @buffer[0, 3] = ""
- detected_encoding = "UTF-8"
- end
- ensure
- @buffer.force_encoding(buffer_encoding)
- end
- self.encoding = detected_encoding
- end
-
- def encoding_updated
- if @encoding != 'UTF-8'
- @buffer = decode(@buffer)
- @to_utf = true
- else
- @to_utf = false
- @buffer.force_encoding ::Encoding::UTF_8
- end
- end
- end
-
- # A Source that wraps an IO. See the Source class for method
- # documentation
- class IOSource < Source
- #attr_reader :block_size
-
- # block_size has been deprecated
- def initialize(arg, block_size=500, encoding=nil)
- @er_source = @source = arg
- @to_utf = false
- @pending_buffer = nil
-
- if encoding
- super("", encoding)
- else
- super(@source.read(3) || "")
- end
-
- if !@to_utf and
- @buffer.respond_to?(:force_encoding) and
- @source.respond_to?(:external_encoding) and
- @source.external_encoding != ::Encoding::UTF_8
- @force_utf8 = true
- else
- @force_utf8 = false
- end
- end
-
- def scan(pattern, cons=false)
- rv = super
- # You'll notice that this next section is very similar to the same
- # section in match(), but just a liiittle different. This is
- # because it is a touch faster to do it this way with scan()
- # than the way match() does it; enough faster to warrant duplicating
- # some code
- if rv.size == 0
- until @buffer =~ pattern or @source.nil?
- begin
- @buffer << readline
- rescue Iconv::IllegalSequence
- raise
- rescue
- @source = nil
- end
- end
- rv = super
- end
- rv.taint if RUBY_VERSION < '2.7'
- rv
- end
-
- def read
- begin
- @buffer << readline
- rescue Exception, NameError
- @source = nil
- end
- end
-
- def consume( pattern )
- match( pattern, true )
- end
-
- def match( pattern, cons=false )
- rv = pattern.match(@buffer)
- @buffer = $' if cons and rv
- while !rv and @source
- begin
- @buffer << readline
- rv = pattern.match(@buffer)
- @buffer = $' if cons and rv
- rescue
- @source = nil
- end
- end
- rv.taint if RUBY_VERSION < '2.7'
- rv
- end
-
- def empty?
- super and ( @source.nil? || @source.eof? )
- end
-
- def position
- @er_source.pos rescue 0
- end
-
- # @return the current line in the source
- def current_line
- begin
- pos = @er_source.pos # The byte position in the source
- lineno = @er_source.lineno # The XML < position in the source
- @er_source.rewind
- line = 0 # The \r\n position in the source
- begin
- while @er_source.pos < pos
- @er_source.readline
- line += 1
- end
- rescue
- end
- @er_source.seek(pos)
- rescue IOError
- pos = -1
- line = -1
- end
- [pos, lineno, line]
- end
-
- private
- def readline
- str = @source.readline(@line_break)
- if @pending_buffer
- if str.nil?
- str = @pending_buffer
- else
- str = @pending_buffer + str
- end
- @pending_buffer = nil
- end
- return nil if str.nil?
-
- if @to_utf
- decode(str)
- else
- str.force_encoding(::Encoding::UTF_8) if @force_utf8
- str
- end
- end
-
- def encoding_updated
- case @encoding
- when "UTF-16BE", "UTF-16LE"
- @source.binmode
- @source.set_encoding(@encoding, @encoding)
- end
- @line_break = encode(">")
- @pending_buffer, @buffer = @buffer, ""
- @pending_buffer.force_encoding(@encoding)
- super
- end
- end
-end
diff --git a/lib/rexml/streamlistener.rb b/lib/rexml/streamlistener.rb
deleted file mode 100644
index 30c8945179..0000000000
--- a/lib/rexml/streamlistener.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: false
-module REXML
- # A template for stream parser listeners.
- # Note that the declarations (attlistdecl, elementdecl, etc) are trivially
- # processed; REXML doesn't yet handle doctype entity declarations, so you
- # have to parse them out yourself.
- module StreamListener
- # Called when a tag is encountered.
- # @p name the tag name
- # @p attrs an array of arrays of attribute/value pairs, suitable for
- # use with assoc or rassoc. IE, <tag attr1="value1" attr2="value2">
- # will result in
- # tag_start( "tag", # [["attr1","value1"],["attr2","value2"]])
- def tag_start name, attrs
- end
- # Called when the end tag is reached. In the case of <tag/>, tag_end
- # will be called immediately after tag_start
- # @p the name of the tag
- def tag_end name
- end
- # Called when text is encountered in the document
- # @p text the text content.
- def text text
- end
- # Called when an instruction is encountered. EG: <?xsl sheet='foo'?>
- # @p name the instruction name; in the example, "xsl"
- # @p instruction the rest of the instruction. In the example,
- # "sheet='foo'"
- def instruction name, instruction
- end
- # Called when a comment is encountered.
- # @p comment The content of the comment
- def comment comment
- end
- # Handles a doctype declaration. Any attributes of the doctype which are
- # not supplied will be nil. # EG, <!DOCTYPE me PUBLIC "foo" "bar">
- # @p name the name of the doctype; EG, "me"
- # @p pub_sys "PUBLIC", "SYSTEM", or nil. EG, "PUBLIC"
- # @p long_name the supplied long name, or nil. EG, "foo"
- # @p uri the uri of the doctype, or nil. EG, "bar"
- def doctype name, pub_sys, long_name, uri
- end
- # Called when the doctype is done
- def doctype_end
- end
- # If a doctype includes an ATTLIST declaration, it will cause this
- # method to be called. The content is the declaration itself, unparsed.
- # EG, <!ATTLIST el attr CDATA #REQUIRED> will come to this method as "el
- # attr CDATA #REQUIRED". This is the same for all of the .*decl
- # methods.
- def attlistdecl element_name, attributes, raw_content
- end
- # <!ELEMENT ...>
- def elementdecl content
- end
- # <!ENTITY ...>
- # The argument passed to this method is an array of the entity
- # declaration. It can be in a number of formats, but in general it
- # returns (example, result):
- # <!ENTITY % YN '"Yes"'>
- # ["YN", "\"Yes\"", "%"]
- # <!ENTITY % YN 'Yes'>
- # ["YN", "Yes", "%"]
- # <!ENTITY WhatHeSaid "He said %YN;">
- # ["WhatHeSaid", "He said %YN;"]
- # <!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
- # ["open-hatch", "SYSTEM", "http://www.textuality.com/boilerplate/OpenHatch.xml"]
- # <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
- # ["open-hatch", "PUBLIC", "-//Textuality//TEXT Standard open-hatch boilerplate//EN", "http://www.textuality.com/boilerplate/OpenHatch.xml"]
- # <!ENTITY hatch-pic SYSTEM "../grafix/OpenHatch.gif" NDATA gif>
- # ["hatch-pic", "SYSTEM", "../grafix/OpenHatch.gif", "gif"]
- def entitydecl content
- end
- # <!NOTATION ...>
- def notationdecl content
- end
- # Called when %foo; is encountered in a doctype declaration.
- # @p content "foo"
- def entity content
- end
- # Called when <![CDATA[ ... ]]> is encountered in a document.
- # @p content "..."
- def cdata content
- end
- # Called when an XML PI is encountered in the document.
- # EG: <?xml version="1.0" encoding="utf"?>
- # @p version the version attribute value. EG, "1.0"
- # @p encoding the encoding attribute value, or nil. EG, "utf"
- # @p standalone the standalone attribute value, or nil. EG, nil
- def xmldecl version, encoding, standalone
- end
- end
-end
diff --git a/lib/rexml/text.rb b/lib/rexml/text.rb
deleted file mode 100644
index 050b09c97e..0000000000
--- a/lib/rexml/text.rb
+++ /dev/null
@@ -1,424 +0,0 @@
-# frozen_string_literal: false
-require_relative 'security'
-require_relative 'entity'
-require_relative 'doctype'
-require_relative 'child'
-require_relative 'doctype'
-require_relative 'parseexception'
-
-module REXML
- # Represents text nodes in an XML document
- class Text < Child
- include Comparable
- # The order in which the substitutions occur
- SPECIALS = [ /&(?!#?[\w-]+;)/u, /</u, />/u, /"/u, /'/u, /\r/u ]
- SUBSTITUTES = ['&amp;', '&lt;', '&gt;', '&quot;', '&apos;', '&#13;']
- # Characters which are substituted in written strings
- SLAICEPS = [ '<', '>', '"', "'", '&' ]
- SETUTITSBUS = [ /&lt;/u, /&gt;/u, /&quot;/u, /&apos;/u, /&amp;/u ]
-
- # If +raw+ is true, then REXML leaves the value alone
- attr_accessor :raw
-
- NEEDS_A_SECOND_CHECK = /(<|&((#{Entity::NAME});|(#0*((?:\d+)|(?:x[a-fA-F0-9]+)));)?)/um
- NUMERICENTITY = /&#0*((?:\d+)|(?:x[a-fA-F0-9]+));/
- VALID_CHAR = [
- 0x9, 0xA, 0xD,
- (0x20..0xD7FF),
- (0xE000..0xFFFD),
- (0x10000..0x10FFFF)
- ]
-
- if String.method_defined? :encode
- VALID_XML_CHARS = Regexp.new('^['+
- VALID_CHAR.map { |item|
- case item
- when Integer
- [item].pack('U').force_encoding('utf-8')
- when Range
- [item.first, '-'.ord, item.last].pack('UUU').force_encoding('utf-8')
- end
- }.join +
- ']*$')
- else
- VALID_XML_CHARS = /^(
- [\x09\x0A\x0D\x20-\x7E] # ASCII
- | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
- | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
- | [\xE1-\xEC\xEE][\x80-\xBF]{2} # straight 3-byte
- | \xEF[\x80-\xBE]{2} #
- | \xEF\xBF[\x80-\xBD] # excluding U+fffe and U+ffff
- | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
- | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
- | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
- | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
- )*$/nx;
- end
-
- # Constructor
- # +arg+ if a String, the content is set to the String. If a Text,
- # the object is shallowly cloned.
- #
- # +respect_whitespace+ (boolean, false) if true, whitespace is
- # respected
- #
- # +parent+ (nil) if this is a Parent object, the parent
- # will be set to this.
- #
- # +raw+ (nil) This argument can be given three values.
- # If true, then the value of used to construct this object is expected to
- # contain no unescaped XML markup, and REXML will not change the text. If
- # this value is false, the string may contain any characters, and REXML will
- # escape any and all defined entities whose values are contained in the
- # text. If this value is nil (the default), then the raw value of the
- # parent will be used as the raw value for this node. If there is no raw
- # value for the parent, and no value is supplied, the default is false.
- # Use this field if you have entities defined for some text, and you don't
- # want REXML to escape that text in output.
- # Text.new( "<&", false, nil, false ) #-> "&lt;&amp;"
- # Text.new( "&lt;&amp;", false, nil, false ) #-> "&amp;lt;&amp;amp;"
- # Text.new( "<&", false, nil, true ) #-> Parse exception
- # Text.new( "&lt;&amp;", false, nil, true ) #-> "&lt;&amp;"
- # # Assume that the entity "s" is defined to be "sean"
- # # and that the entity "r" is defined to be "russell"
- # Text.new( "sean russell" ) #-> "&s; &r;"
- # Text.new( "sean russell", false, nil, true ) #-> "sean russell"
- #
- # +entity_filter+ (nil) This can be an array of entities to match in the
- # supplied text. This argument is only useful if +raw+ is set to false.
- # Text.new( "sean russell", false, nil, false, ["s"] ) #-> "&s; russell"
- # Text.new( "sean russell", false, nil, true, ["s"] ) #-> "sean russell"
- # In the last example, the +entity_filter+ argument is ignored.
- #
- # +illegal+ INTERNAL USE ONLY
- def initialize(arg, respect_whitespace=false, parent=nil, raw=nil,
- entity_filter=nil, illegal=NEEDS_A_SECOND_CHECK )
-
- @raw = false
- @parent = nil
- @entity_filter = nil
-
- if parent
- super( parent )
- @raw = parent.raw
- end
-
- if arg.kind_of? String
- @string = arg.dup
- elsif arg.kind_of? Text
- @string = arg.instance_variable_get(:@string).dup
- @raw = arg.raw
- @entity_filter = arg.instance_variable_get(:@entity_filter)
- else
- raise "Illegal argument of type #{arg.type} for Text constructor (#{arg})"
- end
-
- @string.squeeze!(" \n\t") unless respect_whitespace
- @string.gsub!(/\r\n?/, "\n")
- @raw = raw unless raw.nil?
- @entity_filter = entity_filter if entity_filter
- clear_cache
-
- Text.check(@string, illegal, doctype) if @raw
- end
-
- def parent= parent
- super(parent)
- Text.check(@string, NEEDS_A_SECOND_CHECK, doctype) if @raw and @parent
- end
-
- # check for illegal characters
- def Text.check string, pattern, doctype
-
- # illegal anywhere
- if string !~ VALID_XML_CHARS
- if String.method_defined? :encode
- string.chars.each do |c|
- case c.ord
- when *VALID_CHAR
- else
- raise "Illegal character #{c.inspect} in raw string #{string.inspect}"
- end
- end
- else
- string.scan(/[\x00-\x7F]|[\x80-\xBF][\xC0-\xF0]*|[\xC0-\xF0]/n) do |c|
- case c.unpack('U')
- when *VALID_CHAR
- else
- raise "Illegal character #{c.inspect} in raw string #{string.inspect}"
- end
- end
- end
- end
-
- # context sensitive
- string.scan(pattern) do
- if $1[-1] != ?;
- raise "Illegal character #{$1.inspect} in raw string #{string.inspect}"
- elsif $1[0] == ?&
- if $5 and $5[0] == ?#
- case ($5[1] == ?x ? $5[2..-1].to_i(16) : $5[1..-1].to_i)
- when *VALID_CHAR
- else
- raise "Illegal character #{$1.inspect} in raw string #{string.inspect}"
- end
- # FIXME: below can't work but this needs API change.
- # elsif @parent and $3 and !SUBSTITUTES.include?($1)
- # if !doctype or !doctype.entities.has_key?($3)
- # raise "Undeclared entity '#{$1}' in raw string \"#{string}\""
- # end
- end
- end
- end
- end
-
- def node_type
- :text
- end
-
- def empty?
- @string.size==0
- end
-
-
- def clone
- return Text.new(self, true)
- end
-
-
- # Appends text to this text node. The text is appended in the +raw+ mode
- # of this text node.
- #
- # +returns+ the text itself to enable method chain like
- # 'text << "XXX" << "YYY"'.
- def <<( to_append )
- @string << to_append.gsub( /\r\n?/, "\n" )
- clear_cache
- self
- end
-
-
- # +other+ a String or a Text
- # +returns+ the result of (to_s <=> arg.to_s)
- def <=>( other )
- to_s() <=> other.to_s
- end
-
- def doctype
- if @parent
- doc = @parent.document
- doc.doctype if doc
- end
- end
-
- REFERENCE = /#{Entity::REFERENCE}/
- # Returns the string value of this text node. This string is always
- # escaped, meaning that it is a valid XML text node string, and all
- # entities that can be escaped, have been inserted. This method respects
- # the entity filter set in the constructor.
- #
- # # Assume that the entity "s" is defined to be "sean", and that the
- # # entity "r" is defined to be "russell"
- # t = Text.new( "< & sean russell", false, nil, false, ['s'] )
- # t.to_s #-> "&lt; &amp; &s; russell"
- # t = Text.new( "< & &s; russell", false, nil, false )
- # t.to_s #-> "&lt; &amp; &s; russell"
- # u = Text.new( "sean russell", false, nil, true )
- # u.to_s #-> "sean russell"
- def to_s
- return @string if @raw
- @normalized ||= Text::normalize( @string, doctype, @entity_filter )
- end
-
- def inspect
- @string.inspect
- end
-
- # Returns the string value of this text. This is the text without
- # entities, as it might be used programmatically, or printed to the
- # console. This ignores the 'raw' attribute setting, and any
- # entity_filter.
- #
- # # Assume that the entity "s" is defined to be "sean", and that the
- # # entity "r" is defined to be "russell"
- # t = Text.new( "< & sean russell", false, nil, false, ['s'] )
- # t.value #-> "< & sean russell"
- # t = Text.new( "< & &s; russell", false, nil, false )
- # t.value #-> "< & sean russell"
- # u = Text.new( "sean russell", false, nil, true )
- # u.value #-> "sean russell"
- def value
- @unnormalized ||= Text::unnormalize( @string, doctype )
- end
-
- # Sets the contents of this text node. This expects the text to be
- # unnormalized. It returns self.
- #
- # e = Element.new( "a" )
- # e.add_text( "foo" ) # <a>foo</a>
- # e[0].value = "bar" # <a>bar</a>
- # e[0].value = "<a>" # <a>&lt;a&gt;</a>
- def value=( val )
- @string = val.gsub( /\r\n?/, "\n" )
- clear_cache
- @raw = false
- end
-
- def wrap(string, width, addnewline=false)
- # Recursively wrap string at width.
- return string if string.length <= width
- place = string.rindex(' ', width) # Position in string with last ' ' before cutoff
- if addnewline then
- return "\n" + string[0,place] + "\n" + wrap(string[place+1..-1], width)
- else
- return string[0,place] + "\n" + wrap(string[place+1..-1], width)
- end
- end
-
- def indent_text(string, level=1, style="\t", indentfirstline=true)
- return string if level < 0
- new_string = ''
- string.each_line { |line|
- indent_string = style * level
- new_line = (indent_string + line).sub(/[\s]+$/,'')
- new_string << new_line
- }
- new_string.strip! unless indentfirstline
- return new_string
- end
-
- # == DEPRECATED
- # See REXML::Formatters
- #
- def write( writer, indent=-1, transitive=false, ie_hack=false )
- Kernel.warn("#{self.class.name}.write is deprecated. See REXML::Formatters", uplevel: 1)
- formatter = if indent > -1
- REXML::Formatters::Pretty.new( indent )
- else
- REXML::Formatters::Default.new
- end
- formatter.write( self, writer )
- end
-
- # FIXME
- # This probably won't work properly
- def xpath
- path = @parent.xpath
- path += "/text()"
- return path
- end
-
- # Writes out text, substituting special characters beforehand.
- # +out+ A String, IO, or any other object supporting <<( String )
- # +input+ the text to substitute and the write out
- #
- # z=utf8.unpack("U*")
- # ascOut=""
- # z.each{|r|
- # if r < 0x100
- # ascOut.concat(r.chr)
- # else
- # ascOut.concat(sprintf("&#x%x;", r))
- # end
- # }
- # puts ascOut
- def write_with_substitution out, input
- copy = input.clone
- # Doing it like this rather than in a loop improves the speed
- copy.gsub!( SPECIALS[0], SUBSTITUTES[0] )
- copy.gsub!( SPECIALS[1], SUBSTITUTES[1] )
- copy.gsub!( SPECIALS[2], SUBSTITUTES[2] )
- copy.gsub!( SPECIALS[3], SUBSTITUTES[3] )
- copy.gsub!( SPECIALS[4], SUBSTITUTES[4] )
- copy.gsub!( SPECIALS[5], SUBSTITUTES[5] )
- out << copy
- end
-
- private
- def clear_cache
- @normalized = nil
- @unnormalized = nil
- end
-
- # Reads text, substituting entities
- def Text::read_with_substitution( input, illegal=nil )
- copy = input.clone
-
- if copy =~ illegal
- raise ParseException.new( "malformed text: Illegal character #$& in \"#{copy}\"" )
- end if illegal
-
- copy.gsub!( /\r\n?/, "\n" )
- if copy.include? ?&
- copy.gsub!( SETUTITSBUS[0], SLAICEPS[0] )
- copy.gsub!( SETUTITSBUS[1], SLAICEPS[1] )
- copy.gsub!( SETUTITSBUS[2], SLAICEPS[2] )
- copy.gsub!( SETUTITSBUS[3], SLAICEPS[3] )
- copy.gsub!( SETUTITSBUS[4], SLAICEPS[4] )
- copy.gsub!( /&#0*((?:\d+)|(?:x[a-f0-9]+));/ ) {
- m=$1
- #m='0' if m==''
- m = "0#{m}" if m[0] == ?x
- [Integer(m)].pack('U*')
- }
- end
- copy
- end
-
- EREFERENCE = /&(?!#{Entity::NAME};)/
- # Escapes all possible entities
- def Text::normalize( input, doctype=nil, entity_filter=nil )
- copy = input.to_s
- # Doing it like this rather than in a loop improves the speed
- #copy = copy.gsub( EREFERENCE, '&amp;' )
- copy = copy.gsub( "&", "&amp;" )
- if doctype
- # Replace all ampersands that aren't part of an entity
- doctype.entities.each_value do |entity|
- copy = copy.gsub( entity.value,
- "&#{entity.name};" ) if entity.value and
- not( entity_filter and entity_filter.include?(entity.name) )
- end
- else
- # Replace all ampersands that aren't part of an entity
- DocType::DEFAULT_ENTITIES.each_value do |entity|
- copy = copy.gsub(entity.value, "&#{entity.name};" )
- end
- end
- copy
- end
-
- # Unescapes all possible entities
- def Text::unnormalize( string, doctype=nil, filter=nil, illegal=nil )
- sum = 0
- string.gsub( /\r\n?/, "\n" ).gsub( REFERENCE ) {
- s = Text.expand($&, doctype, filter)
- if sum + s.bytesize > Security.entity_expansion_text_limit
- raise "entity expansion has grown too large"
- else
- sum += s.bytesize
- end
- s
- }
- end
-
- def Text.expand(ref, doctype, filter)
- if ref[1] == ?#
- if ref[2] == ?x
- [ref[3...-1].to_i(16)].pack('U*')
- else
- [ref[2...-1].to_i].pack('U*')
- end
- elsif ref == '&amp;'
- '&'
- elsif filter and filter.include?( ref[1...-1] )
- ref
- elsif doctype
- doctype.entity( ref[1...-1] ) or ref
- else
- entity_value = DocType::DEFAULT_ENTITIES[ ref[1...-1] ]
- entity_value ? entity_value.value : ref
- end
- end
- end
-end
diff --git a/lib/rexml/undefinednamespaceexception.rb b/lib/rexml/undefinednamespaceexception.rb
deleted file mode 100644
index 492a098183..0000000000
--- a/lib/rexml/undefinednamespaceexception.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: false
-require_relative 'parseexception'
-module REXML
- class UndefinedNamespaceException < ParseException
- def initialize( prefix, source, parser )
- super( "Undefined prefix #{prefix} found" )
- end
- end
-end
diff --git a/lib/rexml/validation/relaxng.rb b/lib/rexml/validation/relaxng.rb
deleted file mode 100644
index f29a2c05e5..0000000000
--- a/lib/rexml/validation/relaxng.rb
+++ /dev/null
@@ -1,539 +0,0 @@
-# frozen_string_literal: false
-require_relative "validation"
-require_relative "../parsers/baseparser"
-
-module REXML
- module Validation
- # Implemented:
- # * empty
- # * element
- # * attribute
- # * text
- # * optional
- # * choice
- # * oneOrMore
- # * zeroOrMore
- # * group
- # * value
- # * interleave
- # * mixed
- # * ref
- # * grammar
- # * start
- # * define
- #
- # Not implemented:
- # * data
- # * param
- # * include
- # * externalRef
- # * notAllowed
- # * anyName
- # * nsName
- # * except
- # * name
- class RelaxNG
- include Validator
-
- INFINITY = 1.0 / 0.0
- EMPTY = Event.new( nil )
- TEXT = [:start_element, "text"]
- attr_accessor :current
- attr_accessor :count
- attr_reader :references
-
- # FIXME: Namespaces
- def initialize source
- parser = REXML::Parsers::BaseParser.new( source )
-
- @count = 0
- @references = {}
- @root = @current = Sequence.new(self)
- @root.previous = true
- states = [ @current ]
- begin
- event = parser.pull
- case event[0]
- when :start_element
- case event[1]
- when "empty"
- when "element", "attribute", "text", "value"
- states[-1] << event
- when "optional"
- states << Optional.new( self )
- states[-2] << states[-1]
- when "choice"
- states << Choice.new( self )
- states[-2] << states[-1]
- when "oneOrMore"
- states << OneOrMore.new( self )
- states[-2] << states[-1]
- when "zeroOrMore"
- states << ZeroOrMore.new( self )
- states[-2] << states[-1]
- when "group"
- states << Sequence.new( self )
- states[-2] << states[-1]
- when "interleave"
- states << Interleave.new( self )
- states[-2] << states[-1]
- when "mixed"
- states << Interleave.new( self )
- states[-2] << states[-1]
- states[-1] << TEXT
- when "define"
- states << [ event[2]["name"] ]
- when "ref"
- states[-1] << Ref.new( event[2]["name"] )
- when "anyName"
- states << AnyName.new( self )
- states[-2] << states[-1]
- when "nsName"
- when "except"
- when "name"
- when "data"
- when "param"
- when "include"
- when "grammar"
- when "start"
- when "externalRef"
- when "notAllowed"
- end
- when :end_element
- case event[1]
- when "element", "attribute"
- states[-1] << event
- when "zeroOrMore", "oneOrMore", "choice", "optional",
- "interleave", "group", "mixed"
- states.pop
- when "define"
- ref = states.pop
- @references[ ref.shift ] = ref
- #when "empty"
- end
- when :end_document
- states[-1] << event
- when :text
- states[-1] << event
- end
- end while event[0] != :end_document
- end
-
- def receive event
- validate( event )
- end
- end
-
- class State
- def initialize( context )
- @previous = []
- @events = []
- @current = 0
- @count = context.count += 1
- @references = context.references
- @value = false
- end
-
- def reset
- return if @current == 0
- @current = 0
- @events.each {|s| s.reset if s.kind_of? State }
- end
-
- def previous=( previous )
- @previous << previous
- end
-
- def next( event )
- #print "In next with #{event.inspect}. "
- #p @previous
- return @previous.pop.next( event ) if @events[@current].nil?
- expand_ref_in( @events, @current ) if @events[@current].class == Ref
- if ( @events[@current].kind_of? State )
- @current += 1
- @events[@current-1].previous = self
- return @events[@current-1].next( event )
- end
- if ( @events[@current].matches?(event) )
- @current += 1
- if @events[@current].nil?
- return @previous.pop
- elsif @events[@current].kind_of? State
- @current += 1
- @events[@current-1].previous = self
- return @events[@current-1]
- else
- return self
- end
- else
- return nil
- end
- end
-
- def to_s
- # Abbreviated:
- self.class.name =~ /(?:::)(\w)\w+$/
- # Full:
- #self.class.name =~ /(?:::)(\w+)$/
- "#$1.#@count"
- end
-
- def inspect
- "< #{to_s} #{@events.collect{|e|
- pre = e == @events[@current] ? '#' : ''
- pre + e.inspect unless self == e
- }.join(', ')} >"
- end
-
- def expected
- return [@events[@current]]
- end
-
- def <<( event )
- add_event_to_arry( @events, event )
- end
-
-
- protected
- def expand_ref_in( arry, ind )
- new_events = []
- @references[ arry[ind].to_s ].each{ |evt|
- add_event_to_arry(new_events,evt)
- }
- arry[ind,1] = new_events
- end
-
- def add_event_to_arry( arry, evt )
- evt = generate_event( evt )
- if evt.kind_of? String
- arry[-1].event_arg = evt if arry[-1].kind_of? Event and @value
- @value = false
- else
- arry << evt
- end
- end
-
- def generate_event( event )
- return event if event.kind_of? State or event.class == Ref
- evt = nil
- arg = nil
- case event[0]
- when :start_element
- case event[1]
- when "element"
- evt = :start_element
- arg = event[2]["name"]
- when "attribute"
- evt = :start_attribute
- arg = event[2]["name"]
- when "text"
- evt = :text
- when "value"
- evt = :text
- @value = true
- end
- when :text
- return event[1]
- when :end_document
- return Event.new( event[0] )
- else # then :end_element
- case event[1]
- when "element"
- evt = :end_element
- when "attribute"
- evt = :end_attribute
- end
- end
- return Event.new( evt, arg )
- end
- end
-
-
- class Sequence < State
- def matches?(event)
- @events[@current].matches?( event )
- end
- end
-
-
- class Optional < State
- def next( event )
- if @current == 0
- rv = super
- return rv if rv
- @prior = @previous.pop
- return @prior.next( event )
- end
- super
- end
-
- def matches?(event)
- @events[@current].matches?(event) ||
- (@current == 0 and @previous[-1].matches?(event))
- end
-
- def expected
- return [ @prior.expected, @events[0] ].flatten if @current == 0
- return [@events[@current]]
- end
- end
-
-
- class ZeroOrMore < Optional
- def next( event )
- expand_ref_in( @events, @current ) if @events[@current].class == Ref
- if ( @events[@current].matches?(event) )
- @current += 1
- if @events[@current].nil?
- @current = 0
- return self
- elsif @events[@current].kind_of? State
- @current += 1
- @events[@current-1].previous = self
- return @events[@current-1]
- else
- return self
- end
- else
- @prior = @previous.pop
- return @prior.next( event ) if @current == 0
- return nil
- end
- end
-
- def expected
- return [ @prior.expected, @events[0] ].flatten if @current == 0
- return [@events[@current]]
- end
- end
-
-
- class OneOrMore < State
- def initialize context
- super
- @ord = 0
- end
-
- def reset
- super
- @ord = 0
- end
-
- def next( event )
- expand_ref_in( @events, @current ) if @events[@current].class == Ref
- if ( @events[@current].matches?(event) )
- @current += 1
- @ord += 1
- if @events[@current].nil?
- @current = 0
- return self
- elsif @events[@current].kind_of? State
- @current += 1
- @events[@current-1].previous = self
- return @events[@current-1]
- else
- return self
- end
- else
- return @previous.pop.next( event ) if @current == 0 and @ord > 0
- return nil
- end
- end
-
- def matches?( event )
- @events[@current].matches?(event) ||
- (@current == 0 and @ord > 0 and @previous[-1].matches?(event))
- end
-
- def expected
- if @current == 0 and @ord > 0
- return [@previous[-1].expected, @events[0]].flatten
- else
- return [@events[@current]]
- end
- end
- end
-
-
- class Choice < State
- def initialize context
- super
- @choices = []
- end
-
- def reset
- super
- @events = []
- @choices.each { |c| c.each { |s| s.reset if s.kind_of? State } }
- end
-
- def <<( event )
- add_event_to_arry( @choices, event )
- end
-
- def next( event )
- # Make the choice if we haven't
- if @events.size == 0
- c = 0 ; max = @choices.size
- while c < max
- if @choices[c][0].class == Ref
- expand_ref_in( @choices[c], 0 )
- @choices += @choices[c]
- @choices.delete( @choices[c] )
- max -= 1
- else
- c += 1
- end
- end
- @events = @choices.find { |evt| evt[0].matches? event }
- # Remove the references
- # Find the events
- end
- unless @events
- @events = []
- return nil
- end
- super
- end
-
- def matches?( event )
- return @events[@current].matches?( event ) if @events.size > 0
- !@choices.find{|evt| evt[0].matches?(event)}.nil?
- end
-
- def expected
- return [@events[@current]] if @events.size > 0
- return @choices.collect do |x|
- if x[0].kind_of? State
- x[0].expected
- else
- x[0]
- end
- end.flatten
- end
-
- def inspect
- "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' or ')} >"
- end
-
- protected
- def add_event_to_arry( arry, evt )
- if evt.kind_of? State or evt.class == Ref
- arry << [evt]
- elsif evt[0] == :text
- if arry[-1] and
- arry[-1][-1].kind_of?( Event ) and
- arry[-1][-1].event_type == :text and @value
-
- arry[-1][-1].event_arg = evt[1]
- @value = false
- end
- else
- arry << [] if evt[0] == :start_element
- arry[-1] << generate_event( evt )
- end
- end
- end
-
-
- class Interleave < Choice
- def initialize context
- super
- @choice = 0
- end
-
- def reset
- @choice = 0
- end
-
- def next_current( event )
- # Expand references
- c = 0 ; max = @choices.size
- while c < max
- if @choices[c][0].class == Ref
- expand_ref_in( @choices[c], 0 )
- @choices += @choices[c]
- @choices.delete( @choices[c] )
- max -= 1
- else
- c += 1
- end
- end
- @events = @choices[@choice..-1].find { |evt| evt[0].matches? event }
- @current = 0
- if @events
- # reorder the choices
- old = @choices[@choice]
- idx = @choices.index( @events )
- @choices[@choice] = @events
- @choices[idx] = old
- @choice += 1
- end
-
- @events = [] unless @events
- end
-
-
- def next( event )
- # Find the next series
- next_current(event) unless @events[@current]
- return nil unless @events[@current]
-
- expand_ref_in( @events, @current ) if @events[@current].class == Ref
- if ( @events[@current].kind_of? State )
- @current += 1
- @events[@current-1].previous = self
- return @events[@current-1].next( event )
- end
- return @previous.pop.next( event ) if @events[@current].nil?
- if ( @events[@current].matches?(event) )
- @current += 1
- if @events[@current].nil?
- return self unless @choices[@choice].nil?
- return @previous.pop
- elsif @events[@current].kind_of? State
- @current += 1
- @events[@current-1].previous = self
- return @events[@current-1]
- else
- return self
- end
- else
- return nil
- end
- end
-
- def matches?( event )
- return @events[@current].matches?( event ) if @events[@current]
- !@choices[@choice..-1].find{|evt| evt[0].matches?(event)}.nil?
- end
-
- def expected
- return [@events[@current]] if @events[@current]
- return @choices[@choice..-1].collect do |x|
- if x[0].kind_of? State
- x[0].expected
- else
- x[0]
- end
- end.flatten
- end
-
- def inspect
- "< #{to_s} #{@choices.collect{|e| e.collect{|f|f.to_s}.join(', ')}.join(' and ')} >"
- end
- end
-
- class Ref
- def initialize value
- @value = value
- end
- def to_s
- @value
- end
- def inspect
- "{#{to_s}}"
- end
- end
- end
-end
diff --git a/lib/rexml/validation/validation.rb b/lib/rexml/validation/validation.rb
deleted file mode 100644
index 0ad6ada427..0000000000
--- a/lib/rexml/validation/validation.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-# frozen_string_literal: false
-require_relative 'validationexception'
-
-module REXML
- module Validation
- module Validator
- NILEVENT = [ nil ]
- def reset
- @current = @root
- @root.reset
- @root.previous = true
- @attr_stack = []
- self
- end
- def dump
- puts @root.inspect
- end
- def validate( event )
- @attr_stack = [] unless defined? @attr_stack
- match = @current.next(event)
- raise ValidationException.new( "Validation error. Expected: "+
- @current.expected.join( " or " )+" from #{@current.inspect} "+
- " but got #{Event.new( event[0], event[1] ).inspect}" ) unless match
- @current = match
-
- # Check for attributes
- case event[0]
- when :start_element
- @attr_stack << event[2]
- begin
- sattr = [:start_attribute, nil]
- eattr = [:end_attribute]
- text = [:text, nil]
- k, = event[2].find { |key,value|
- sattr[1] = key
- m = @current.next( sattr )
- if m
- # If the state has text children...
- if m.matches?( eattr )
- @current = m
- else
- text[1] = value
- m = m.next( text )
- text[1] = nil
- return false unless m
- @current = m if m
- end
- m = @current.next( eattr )
- if m
- @current = m
- true
- else
- false
- end
- else
- false
- end
- }
- event[2].delete(k) if k
- end while k
- when :end_element
- attrs = @attr_stack.pop
- raise ValidationException.new( "Validation error. Illegal "+
- " attributes: #{attrs.inspect}") if attrs.length > 0
- end
- end
- end
-
- class Event
- def initialize(event_type, event_arg=nil )
- @event_type = event_type
- @event_arg = event_arg
- end
-
- attr_reader :event_type
- attr_accessor :event_arg
-
- def done?
- @done
- end
-
- def single?
- return (@event_type != :start_element and @event_type != :start_attribute)
- end
-
- def matches?( event )
- return false unless event[0] == @event_type
- case event[0]
- when nil
- return true
- when :start_element
- return true if event[1] == @event_arg
- when :end_element
- return true
- when :start_attribute
- return true if event[1] == @event_arg
- when :end_attribute
- return true
- when :end_document
- return true
- when :text
- return (@event_arg.nil? or @event_arg == event[1])
-=begin
- when :processing_instruction
- false
- when :xmldecl
- false
- when :start_doctype
- false
- when :end_doctype
- false
- when :externalentity
- false
- when :elementdecl
- false
- when :entity
- false
- when :attlistdecl
- false
- when :notationdecl
- false
- when :end_doctype
- false
-=end
- else
- false
- end
- end
-
- def ==( other )
- return false unless other.kind_of? Event
- @event_type == other.event_type and @event_arg == other.event_arg
- end
-
- def to_s
- inspect
- end
-
- def inspect
- "#{@event_type.inspect}( #@event_arg )"
- end
- end
- end
-end
diff --git a/lib/rexml/validation/validationexception.rb b/lib/rexml/validation/validationexception.rb
deleted file mode 100644
index 78cd63fd04..0000000000
--- a/lib/rexml/validation/validationexception.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: false
-module REXML
- module Validation
- class ValidationException < RuntimeError
- def initialize msg
- super
- end
- end
- end
-end
diff --git a/lib/rexml/xmldecl.rb b/lib/rexml/xmldecl.rb
deleted file mode 100644
index d19407cefd..0000000000
--- a/lib/rexml/xmldecl.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: false
-
-require_relative 'encoding'
-require_relative 'source'
-
-module REXML
- # NEEDS DOCUMENTATION
- class XMLDecl < Child
- include Encoding
-
- DEFAULT_VERSION = "1.0"
- DEFAULT_ENCODING = "UTF-8"
- DEFAULT_STANDALONE = "no"
- START = "<?xml"
- STOP = "?>"
-
- attr_accessor :version, :standalone
- attr_reader :writeencoding, :writethis
-
- def initialize(version=DEFAULT_VERSION, encoding=nil, standalone=nil)
- @writethis = true
- @writeencoding = !encoding.nil?
- if version.kind_of? XMLDecl
- super()
- @version = version.version
- self.encoding = version.encoding
- @writeencoding = version.writeencoding
- @standalone = version.standalone
- @writethis = version.writethis
- else
- super()
- @version = version
- self.encoding = encoding
- @standalone = standalone
- end
- @version = DEFAULT_VERSION if @version.nil?
- end
-
- def clone
- XMLDecl.new(self)
- end
-
- # indent::
- # Ignored. There must be no whitespace before an XML declaration
- # transitive::
- # Ignored
- # ie_hack::
- # Ignored
- def write(writer, indent=-1, transitive=false, ie_hack=false)
- return nil unless @writethis or writer.kind_of? Output
- writer << START
- writer << " #{content encoding}"
- writer << STOP
- end
-
- def ==( other )
- other.kind_of?(XMLDecl) and
- other.version == @version and
- other.encoding == self.encoding and
- other.standalone == @standalone
- end
-
- def xmldecl version, encoding, standalone
- @version = version
- self.encoding = encoding
- @standalone = standalone
- end
-
- def node_type
- :xmldecl
- end
-
- alias :stand_alone? :standalone
- alias :old_enc= :encoding=
-
- def encoding=( enc )
- if enc.nil?
- self.old_enc = "UTF-8"
- @writeencoding = false
- else
- self.old_enc = enc
- @writeencoding = true
- end
- self.dowrite
- end
-
- # Only use this if you do not want the XML declaration to be written;
- # this object is ignored by the XML writer. Otherwise, instantiate your
- # own XMLDecl and add it to the document.
- #
- # Note that XML 1.1 documents *must* include an XML declaration
- def XMLDecl.default
- rv = XMLDecl.new( "1.0" )
- rv.nowrite
- rv
- end
-
- def nowrite
- @writethis = false
- end
-
- def dowrite
- @writethis = true
- end
-
- def inspect
- "#{START} ... #{STOP}"
- end
-
- private
- def content(enc)
- context = nil
- context = parent.context if parent
- if context and context[:prologue_quote] == :quote
- quote = "\""
- else
- quote = "'"
- end
-
- rv = "version=#{quote}#{@version}#{quote}"
- if @writeencoding or enc !~ /\Autf-8\z/i
- rv << " encoding=#{quote}#{enc}#{quote}"
- end
- if @standalone
- rv << " standalone=#{quote}#{@standalone}#{quote}"
- end
- rv
- end
- end
-end
diff --git a/lib/rexml/xmltokens.rb b/lib/rexml/xmltokens.rb
deleted file mode 100644
index 392b47b1d3..0000000000
--- a/lib/rexml/xmltokens.rb
+++ /dev/null
@@ -1,85 +0,0 @@
-# frozen_string_literal: false
-module REXML
- # Defines a number of tokens used for parsing XML. Not for general
- # consumption.
- module XMLTokens
- # From http://www.w3.org/TR/REC-xml/#sec-common-syn
- #
- # [4] NameStartChar ::=
- # ":" |
- # [A-Z] |
- # "_" |
- # [a-z] |
- # [#xC0-#xD6] |
- # [#xD8-#xF6] |
- # [#xF8-#x2FF] |
- # [#x370-#x37D] |
- # [#x37F-#x1FFF] |
- # [#x200C-#x200D] |
- # [#x2070-#x218F] |
- # [#x2C00-#x2FEF] |
- # [#x3001-#xD7FF] |
- # [#xF900-#xFDCF] |
- # [#xFDF0-#xFFFD] |
- # [#x10000-#xEFFFF]
- name_start_chars = [
- ":",
- "A-Z",
- "_",
- "a-z",
- "\\u00C0-\\u00D6",
- "\\u00D8-\\u00F6",
- "\\u00F8-\\u02FF",
- "\\u0370-\\u037D",
- "\\u037F-\\u1FFF",
- "\\u200C-\\u200D",
- "\\u2070-\\u218F",
- "\\u2C00-\\u2FEF",
- "\\u3001-\\uD7FF",
- "\\uF900-\\uFDCF",
- "\\uFDF0-\\uFFFD",
- "\\u{10000}-\\u{EFFFF}",
- ]
- # From http://www.w3.org/TR/REC-xml/#sec-common-syn
- #
- # [4a] NameChar ::=
- # NameStartChar |
- # "-" |
- # "." |
- # [0-9] |
- # #xB7 |
- # [#x0300-#x036F] |
- # [#x203F-#x2040]
- name_chars = name_start_chars + [
- "\\-",
- "\\.",
- "0-9",
- "\\u00B7",
- "\\u0300-\\u036F",
- "\\u203F-\\u2040",
- ]
- NAME_START_CHAR = "[#{name_start_chars.join('')}]"
- NAME_CHAR = "[#{name_chars.join('')}]"
- NAMECHAR = NAME_CHAR # deprecated. Use NAME_CHAR instead.
-
- # From http://www.w3.org/TR/xml-names11/#NT-NCName
- #
- # [6] NCNameStartChar ::= NameStartChar - ':'
- ncname_start_chars = name_start_chars - [":"]
- # From http://www.w3.org/TR/xml-names11/#NT-NCName
- #
- # [5] NCNameChar ::= NameChar - ':'
- ncname_chars = name_chars - [":"]
- NCNAME_STR = "[#{ncname_start_chars.join('')}][#{ncname_chars.join('')}]*"
- NAME_STR = "(?:#{NCNAME_STR}:)?#{NCNAME_STR}"
-
- NAME = "(#{NAME_START_CHAR}#{NAME_CHAR}*)"
- NMTOKEN = "(?:#{NAME_CHAR})+"
- NMTOKENS = "#{NMTOKEN}(\\s+#{NMTOKEN})*"
- REFERENCE = "(?:&#{NAME};|&#\\d+;|&#x[0-9a-fA-F]+;)"
-
- #REFERENCE = "(?:#{ENTITYREF}|#{CHARREF})"
- #ENTITYREF = "&#{NAME};"
- #CHARREF = "&#\\d+;|&#x[0-9a-fA-F]+;"
- end
-end
diff --git a/lib/rexml/xpath.rb b/lib/rexml/xpath.rb
deleted file mode 100644
index a0921bd8e1..0000000000
--- a/lib/rexml/xpath.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# frozen_string_literal: false
-require_relative 'functions'
-require_relative 'xpath_parser'
-
-module REXML
- # Wrapper class. Use this class to access the XPath functions.
- class XPath
- include Functions
- # A base Hash object, supposing to be used when initializing a
- # default empty namespaces set, but is currently unused.
- # TODO: either set the namespaces=EMPTY_HASH, or deprecate this.
- EMPTY_HASH = {}
-
- # Finds and returns the first node that matches the supplied xpath.
- # element::
- # The context element
- # path::
- # The xpath to search for. If not supplied or nil, returns the first
- # node matching '*'.
- # namespaces::
- # If supplied, a Hash which defines a namespace mapping.
- # variables::
- # If supplied, a Hash which maps $variables in the query
- # to values. This can be used to avoid XPath injection attacks
- # or to automatically handle escaping string values.
- #
- # XPath.first( node )
- # XPath.first( doc, "//b"} )
- # XPath.first( node, "a/x:b", { "x"=>"http://doofus" } )
- # XPath.first( node, '/book/publisher/text()=$publisher', {}, {"publisher"=>"O'Reilly"})
- def XPath::first(element, path=nil, namespaces=nil, variables={}, options={})
- raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
- raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
- parser = XPathParser.new(**options)
- parser.namespaces = namespaces
- parser.variables = variables
- path = "*" unless path
- element = [element] unless element.kind_of? Array
- parser.parse(path, element).flatten[0]
- end
-
- # Iterates over nodes that match the given path, calling the supplied
- # block with the match.
- # element::
- # The context element
- # path::
- # The xpath to search for. If not supplied or nil, defaults to '*'
- # namespaces::
- # If supplied, a Hash which defines a namespace mapping
- # variables::
- # If supplied, a Hash which maps $variables in the query
- # to values. This can be used to avoid XPath injection attacks
- # or to automatically handle escaping string values.
- #
- # XPath.each( node ) { |el| ... }
- # XPath.each( node, '/*[@attr='v']' ) { |el| ... }
- # XPath.each( node, 'ancestor::x' ) { |el| ... }
- # XPath.each( node, '/book/publisher/text()=$publisher', {}, {"publisher"=>"O'Reilly"}) \
- # {|el| ... }
- def XPath::each(element, path=nil, namespaces=nil, variables={}, options={}, &block)
- raise "The namespaces argument, if supplied, must be a hash object." unless namespaces.nil? or namespaces.kind_of?(Hash)
- raise "The variables argument, if supplied, must be a hash object." unless variables.kind_of?(Hash)
- parser = XPathParser.new(**options)
- parser.namespaces = namespaces
- parser.variables = variables
- path = "*" unless path
- element = [element] unless element.kind_of? Array
- parser.parse(path, element).each( &block )
- end
-
- # Returns an array of nodes matching a given XPath.
- def XPath::match(element, path=nil, namespaces=nil, variables={}, options={})
- parser = XPathParser.new(**options)
- parser.namespaces = namespaces
- parser.variables = variables
- path = "*" unless path
- element = [element] unless element.kind_of? Array
- parser.parse(path,element)
- end
- end
-end
diff --git a/lib/rexml/xpath_parser.rb b/lib/rexml/xpath_parser.rb
deleted file mode 100644
index b989725403..0000000000
--- a/lib/rexml/xpath_parser.rb
+++ /dev/null
@@ -1,968 +0,0 @@
-# frozen_string_literal: false
-
-require "pp"
-
-require_relative 'namespace'
-require_relative 'xmltokens'
-require_relative 'attribute'
-require_relative 'parsers/xpathparser'
-
-class Object
- # provides a unified +clone+ operation, for REXML::XPathParser
- # to use across multiple Object types
- def dclone
- clone
- end
-end
-class Symbol
- # provides a unified +clone+ operation, for REXML::XPathParser
- # to use across multiple Object types
- def dclone ; self ; end
-end
-class Integer
- # provides a unified +clone+ operation, for REXML::XPathParser
- # to use across multiple Object types
- def dclone ; self ; end
-end
-class Float
- # provides a unified +clone+ operation, for REXML::XPathParser
- # to use across multiple Object types
- def dclone ; self ; end
-end
-class Array
- # provides a unified +clone+ operation, for REXML::XPathParser
- # to use across multiple Object+ types
- def dclone
- klone = self.clone
- klone.clear
- self.each{|v| klone << v.dclone}
- klone
- end
-end
-
-module REXML
- # You don't want to use this class. Really. Use XPath, which is a wrapper
- # for this class. Believe me. You don't want to poke around in here.
- # There is strange, dark magic at work in this code. Beware. Go back! Go
- # back while you still can!
- class XPathParser
- include XMLTokens
- LITERAL = /^'([^']*)'|^"([^"]*)"/u
-
- DEBUG = (ENV["REXML_XPATH_PARSER_DEBUG"] == "true")
-
- def initialize(strict: false)
- @debug = DEBUG
- @parser = REXML::Parsers::XPathParser.new
- @namespaces = nil
- @variables = {}
- @nest = 0
- @strict = strict
- end
-
- def namespaces=( namespaces={} )
- Functions::namespace_context = namespaces
- @namespaces = namespaces
- end
-
- def variables=( vars={} )
- Functions::variables = vars
- @variables = vars
- end
-
- def parse path, nodeset
- path_stack = @parser.parse( path )
- match( path_stack, nodeset )
- end
-
- def get_first path, nodeset
- path_stack = @parser.parse( path )
- first( path_stack, nodeset )
- end
-
- def predicate path, nodeset
- path_stack = @parser.parse( path )
- match( path_stack, nodeset )
- end
-
- def []=( variable_name, value )
- @variables[ variable_name ] = value
- end
-
-
- # Performs a depth-first (document order) XPath search, and returns the
- # first match. This is the fastest, lightest way to return a single result.
- #
- # FIXME: This method is incomplete!
- def first( path_stack, node )
- return nil if path.size == 0
-
- case path[0]
- when :document
- # do nothing
- return first( path[1..-1], node )
- when :child
- for c in node.children
- r = first( path[1..-1], c )
- return r if r
- end
- when :qname
- name = path[2]
- if node.name == name
- return node if path.size == 3
- return first( path[3..-1], node )
- else
- return nil
- end
- when :descendant_or_self
- r = first( path[1..-1], node )
- return r if r
- for c in node.children
- r = first( path, c )
- return r if r
- end
- when :node
- return first( path[1..-1], node )
- when :any
- return first( path[1..-1], node )
- end
- return nil
- end
-
-
- def match(path_stack, nodeset)
- nodeset = nodeset.collect.with_index do |node, i|
- position = i + 1
- XPathNode.new(node, position: position)
- end
- result = expr(path_stack, nodeset)
- case result
- when Array # nodeset
- unnode(result)
- else
- [result]
- end
- end
-
- private
- def strict?
- @strict
- end
-
- # Returns a String namespace for a node, given a prefix
- # The rules are:
- #
- # 1. Use the supplied namespace mapping first.
- # 2. If no mapping was supplied, use the context node to look up the namespace
- def get_namespace( node, prefix )
- if @namespaces
- return @namespaces[prefix] || ''
- else
- return node.namespace( prefix ) if node.node_type == :element
- return ''
- end
- end
-
-
- # Expr takes a stack of path elements and a set of nodes (either a Parent
- # or an Array and returns an Array of matching nodes
- def expr( path_stack, nodeset, context=nil )
- enter(:expr, path_stack, nodeset) if @debug
- return nodeset if path_stack.length == 0 || nodeset.length == 0
- while path_stack.length > 0
- trace(:while, path_stack, nodeset) if @debug
- if nodeset.length == 0
- path_stack.clear
- return []
- end
- op = path_stack.shift
- case op
- when :document
- first_raw_node = nodeset.first.raw_node
- nodeset = [XPathNode.new(first_raw_node.root_node, position: 1)]
- when :self
- nodeset = step(path_stack) do
- [nodeset]
- end
- when :child
- nodeset = step(path_stack) do
- child(nodeset)
- end
- when :literal
- trace(:literal, path_stack, nodeset) if @debug
- return path_stack.shift
- when :attribute
- nodeset = step(path_stack, any_type: :attribute) do
- nodesets = []
- nodeset.each do |node|
- raw_node = node.raw_node
- next unless raw_node.node_type == :element
- attributes = raw_node.attributes
- next if attributes.empty?
- nodesets << attributes.each_attribute.collect.with_index do |attribute, i|
- XPathNode.new(attribute, position: i + 1)
- end
- end
- nodesets
- end
- when :namespace
- pre_defined_namespaces = {
- "xml" => "http://www.w3.org/XML/1998/namespace",
- }
- nodeset = step(path_stack, any_type: :namespace) do
- nodesets = []
- nodeset.each do |node|
- raw_node = node.raw_node
- case raw_node.node_type
- when :element
- if @namespaces
- nodesets << pre_defined_namespaces.merge(@namespaces)
- else
- nodesets << pre_defined_namespaces.merge(raw_node.namespaces)
- end
- when :attribute
- if @namespaces
- nodesets << pre_defined_namespaces.merge(@namespaces)
- else
- nodesets << pre_defined_namespaces.merge(raw_node.element.namespaces)
- end
- end
- end
- nodesets
- end
- when :parent
- nodeset = step(path_stack) do
- nodesets = []
- nodeset.each do |node|
- raw_node = node.raw_node
- if raw_node.node_type == :attribute
- parent = raw_node.element
- else
- parent = raw_node.parent
- end
- nodesets << [XPathNode.new(parent, position: 1)] if parent
- end
- nodesets
- end
- when :ancestor
- nodeset = step(path_stack) do
- nodesets = []
- # new_nodes = {}
- nodeset.each do |node|
- raw_node = node.raw_node
- new_nodeset = []
- while raw_node.parent
- raw_node = raw_node.parent
- # next if new_nodes.key?(node)
- new_nodeset << XPathNode.new(raw_node,
- position: new_nodeset.size + 1)
- # new_nodes[node] = true
- end
- nodesets << new_nodeset unless new_nodeset.empty?
- end
- nodesets
- end
- when :ancestor_or_self
- nodeset = step(path_stack) do
- nodesets = []
- # new_nodes = {}
- nodeset.each do |node|
- raw_node = node.raw_node
- next unless raw_node.node_type == :element
- new_nodeset = [XPathNode.new(raw_node, position: 1)]
- # new_nodes[node] = true
- while raw_node.parent
- raw_node = raw_node.parent
- # next if new_nodes.key?(node)
- new_nodeset << XPathNode.new(raw_node,
- position: new_nodeset.size + 1)
- # new_nodes[node] = true
- end
- nodesets << new_nodeset unless new_nodeset.empty?
- end
- nodesets
- end
- when :descendant_or_self
- nodeset = step(path_stack) do
- descendant(nodeset, true)
- end
- when :descendant
- nodeset = step(path_stack) do
- descendant(nodeset, false)
- end
- when :following_sibling
- nodeset = step(path_stack) do
- nodesets = []
- nodeset.each do |node|
- raw_node = node.raw_node
- next unless raw_node.respond_to?(:parent)
- next if raw_node.parent.nil?
- all_siblings = raw_node.parent.children
- current_index = all_siblings.index(raw_node)
- following_siblings = all_siblings[(current_index + 1)..-1]
- next if following_siblings.empty?
- nodesets << following_siblings.collect.with_index do |sibling, i|
- XPathNode.new(sibling, position: i + 1)
- end
- end
- nodesets
- end
- when :preceding_sibling
- nodeset = step(path_stack, order: :reverse) do
- nodesets = []
- nodeset.each do |node|
- raw_node = node.raw_node
- next unless raw_node.respond_to?(:parent)
- next if raw_node.parent.nil?
- all_siblings = raw_node.parent.children
- current_index = all_siblings.index(raw_node)
- preceding_siblings = all_siblings[0, current_index].reverse
- next if preceding_siblings.empty?
- nodesets << preceding_siblings.collect.with_index do |sibling, i|
- XPathNode.new(sibling, position: i + 1)
- end
- end
- nodesets
- end
- when :preceding
- nodeset = step(path_stack, order: :reverse) do
- unnode(nodeset) do |node|
- preceding(node)
- end
- end
- when :following
- nodeset = step(path_stack) do
- unnode(nodeset) do |node|
- following(node)
- end
- end
- when :variable
- var_name = path_stack.shift
- return [@variables[var_name]]
-
- when :eq, :neq, :lt, :lteq, :gt, :gteq
- left = expr( path_stack.shift, nodeset.dup, context )
- right = expr( path_stack.shift, nodeset.dup, context )
- res = equality_relational_compare( left, op, right )
- trace(op, left, right, res) if @debug
- return res
-
- when :or
- left = expr(path_stack.shift, nodeset.dup, context)
- return true if Functions.boolean(left)
- right = expr(path_stack.shift, nodeset.dup, context)
- return Functions.boolean(right)
-
- when :and
- left = expr(path_stack.shift, nodeset.dup, context)
- return false unless Functions.boolean(left)
- right = expr(path_stack.shift, nodeset.dup, context)
- return Functions.boolean(right)
-
- when :div, :mod, :mult, :plus, :minus
- left = expr(path_stack.shift, nodeset, context)
- right = expr(path_stack.shift, nodeset, context)
- left = unnode(left) if left.is_a?(Array)
- right = unnode(right) if right.is_a?(Array)
- left = Functions::number(left)
- right = Functions::number(right)
- case op
- when :div
- return left / right
- when :mod
- return left % right
- when :mult
- return left * right
- when :plus
- return left + right
- when :minus
- return left - right
- else
- raise "[BUG] Unexpected operator: <#{op.inspect}>"
- end
- when :union
- left = expr( path_stack.shift, nodeset, context )
- right = expr( path_stack.shift, nodeset, context )
- left = unnode(left) if left.is_a?(Array)
- right = unnode(right) if right.is_a?(Array)
- return (left | right)
- when :neg
- res = expr( path_stack, nodeset, context )
- res = unnode(res) if res.is_a?(Array)
- return -Functions.number(res)
- when :not
- when :function
- func_name = path_stack.shift.tr('-','_')
- arguments = path_stack.shift
-
- if nodeset.size != 1
- message = "[BUG] Node set size must be 1 for function call: "
- message += "<#{func_name}>: <#{nodeset.inspect}>: "
- message += "<#{arguments.inspect}>"
- raise message
- end
-
- node = nodeset.first
- if context
- target_context = context
- else
- target_context = {:size => nodeset.size}
- if node.is_a?(XPathNode)
- target_context[:node] = node.raw_node
- target_context[:index] = node.position
- else
- target_context[:node] = node
- target_context[:index] = 1
- end
- end
- args = arguments.dclone.collect do |arg|
- result = expr(arg, nodeset, target_context)
- result = unnode(result) if result.is_a?(Array)
- result
- end
- Functions.context = target_context
- return Functions.send(func_name, *args)
-
- else
- raise "[BUG] Unexpected path: <#{op.inspect}>: <#{path_stack.inspect}>"
- end
- end # while
- return nodeset
- ensure
- leave(:expr, path_stack, nodeset) if @debug
- end
-
- def step(path_stack, any_type: :element, order: :forward)
- nodesets = yield
- begin
- enter(:step, path_stack, nodesets) if @debug
- nodesets = node_test(path_stack, nodesets, any_type: any_type)
- while path_stack[0] == :predicate
- path_stack.shift # :predicate
- predicate_expression = path_stack.shift.dclone
- nodesets = evaluate_predicate(predicate_expression, nodesets)
- end
- if nodesets.size == 1
- ordered_nodeset = nodesets[0]
- else
- raw_nodes = []
- nodesets.each do |nodeset|
- nodeset.each do |node|
- if node.respond_to?(:raw_node)
- raw_nodes << node.raw_node
- else
- raw_nodes << node
- end
- end
- end
- ordered_nodeset = sort(raw_nodes, order)
- end
- new_nodeset = []
- ordered_nodeset.each do |node|
- # TODO: Remove duplicated
- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1)
- end
- new_nodeset
- ensure
- leave(:step, path_stack, new_nodeset) if @debug
- end
- end
-
- def node_test(path_stack, nodesets, any_type: :element)
- enter(:node_test, path_stack, nodesets) if @debug
- operator = path_stack.shift
- case operator
- when :qname
- prefix = path_stack.shift
- name = path_stack.shift
- new_nodesets = nodesets.collect do |nodeset|
- filter_nodeset(nodeset) do |node|
- raw_node = node.raw_node
- case raw_node.node_type
- when :element
- if prefix.nil?
- raw_node.name == name
- elsif prefix.empty?
- if strict?
- raw_node.name == name and raw_node.namespace == ""
- else
- # FIXME: This DOUBLES the time XPath searches take
- ns = get_namespace(raw_node, prefix)
- raw_node.name == name and raw_node.namespace == ns
- end
- else
- # FIXME: This DOUBLES the time XPath searches take
- ns = get_namespace(raw_node, prefix)
- raw_node.name == name and raw_node.namespace == ns
- end
- when :attribute
- if prefix.nil?
- raw_node.name == name
- elsif prefix.empty?
- raw_node.name == name and raw_node.namespace == ""
- else
- # FIXME: This DOUBLES the time XPath searches take
- ns = get_namespace(raw_node.element, prefix)
- raw_node.name == name and raw_node.namespace == ns
- end
- else
- false
- end
- end
- end
- when :namespace
- prefix = path_stack.shift
- new_nodesets = nodesets.collect do |nodeset|
- filter_nodeset(nodeset) do |node|
- raw_node = node.raw_node
- case raw_node.node_type
- when :element
- namespaces = @namespaces || raw_node.namespaces
- raw_node.namespace == namespaces[prefix]
- when :attribute
- namespaces = @namespaces || raw_node.element.namespaces
- raw_node.namespace == namespaces[prefix]
- else
- false
- end
- end
- end
- when :any
- new_nodesets = nodesets.collect do |nodeset|
- filter_nodeset(nodeset) do |node|
- raw_node = node.raw_node
- raw_node.node_type == any_type
- end
- end
- when :comment
- new_nodesets = nodesets.collect do |nodeset|
- filter_nodeset(nodeset) do |node|
- raw_node = node.raw_node
- raw_node.node_type == :comment
- end
- end
- when :text
- new_nodesets = nodesets.collect do |nodeset|
- filter_nodeset(nodeset) do |node|
- raw_node = node.raw_node
- raw_node.node_type == :text
- end
- end
- when :processing_instruction
- target = path_stack.shift
- new_nodesets = nodesets.collect do |nodeset|
- filter_nodeset(nodeset) do |node|
- raw_node = node.raw_node
- (raw_node.node_type == :processing_instruction) and
- (target.empty? or (raw_node.target == target))
- end
- end
- when :node
- new_nodesets = nodesets.collect do |nodeset|
- filter_nodeset(nodeset) do |node|
- true
- end
- end
- else
- message = "[BUG] Unexpected node test: " +
- "<#{operator.inspect}>: <#{path_stack.inspect}>"
- raise message
- end
- new_nodesets
- ensure
- leave(:node_test, path_stack, new_nodesets) if @debug
- end
-
- def filter_nodeset(nodeset)
- new_nodeset = []
- nodeset.each do |node|
- next unless yield(node)
- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1)
- end
- new_nodeset
- end
-
- def evaluate_predicate(expression, nodesets)
- enter(:predicate, expression, nodesets) if @debug
- new_nodesets = nodesets.collect do |nodeset|
- new_nodeset = []
- subcontext = { :size => nodeset.size }
- nodeset.each_with_index do |node, index|
- if node.is_a?(XPathNode)
- subcontext[:node] = node.raw_node
- subcontext[:index] = node.position
- else
- subcontext[:node] = node
- subcontext[:index] = index + 1
- end
- result = expr(expression.dclone, [node], subcontext)
- trace(:predicate_evaluate, expression, node, subcontext, result) if @debug
- result = result[0] if result.kind_of? Array and result.length == 1
- if result.kind_of? Numeric
- if result == node.position
- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1)
- end
- elsif result.instance_of? Array
- if result.size > 0 and result.inject(false) {|k,s| s or k}
- if result.size > 0
- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1)
- end
- end
- else
- if result
- new_nodeset << XPathNode.new(node, position: new_nodeset.size + 1)
- end
- end
- end
- new_nodeset
- end
- new_nodesets
- ensure
- leave(:predicate, new_nodesets) if @debug
- end
-
- def trace(*args)
- indent = " " * @nest
- PP.pp(args, "").each_line do |line|
- puts("#{indent}#{line}")
- end
- end
-
- def enter(tag, *args)
- trace(:enter, tag, *args)
- @nest += 1
- end
-
- def leave(tag, *args)
- @nest -= 1
- trace(:leave, tag, *args)
- end
-
- # Reorders an array of nodes so that they are in document order
- # It tries to do this efficiently.
- #
- # FIXME: I need to get rid of this, but the issue is that most of the XPath
- # interpreter functions as a filter, which means that we lose context going
- # in and out of function calls. If I knew what the index of the nodes was,
- # I wouldn't have to do this. Maybe add a document IDX for each node?
- # Problems with mutable documents. Or, rewrite everything.
- def sort(array_of_nodes, order)
- new_arry = []
- array_of_nodes.each { |node|
- node_idx = []
- np = node.node_type == :attribute ? node.element : node
- while np.parent and np.parent.node_type == :element
- node_idx << np.parent.index( np )
- np = np.parent
- end
- new_arry << [ node_idx.reverse, node ]
- }
- ordered = new_arry.sort_by do |index, node|
- if order == :forward
- index
- else
- -index
- end
- end
- ordered.collect do |_index, node|
- node
- end
- end
-
- def descendant(nodeset, include_self)
- nodesets = []
- nodeset.each do |node|
- new_nodeset = []
- new_nodes = {}
- descendant_recursive(node.raw_node, new_nodeset, new_nodes, include_self)
- nodesets << new_nodeset unless new_nodeset.empty?
- end
- nodesets
- end
-
- def descendant_recursive(raw_node, new_nodeset, new_nodes, include_self)
- if include_self
- return if new_nodes.key?(raw_node)
- new_nodeset << XPathNode.new(raw_node, position: new_nodeset.size + 1)
- new_nodes[raw_node] = true
- end
-
- node_type = raw_node.node_type
- if node_type == :element or node_type == :document
- raw_node.children.each do |child|
- descendant_recursive(child, new_nodeset, new_nodes, true)
- end
- end
- end
-
- # Builds a nodeset of all of the preceding nodes of the supplied node,
- # in reverse document order
- # preceding:: includes every element in the document that precedes this node,
- # except for ancestors
- def preceding(node)
- ancestors = []
- parent = node.parent
- while parent
- ancestors << parent
- parent = parent.parent
- end
-
- precedings = []
- preceding_node = preceding_node_of(node)
- while preceding_node
- if ancestors.include?(preceding_node)
- ancestors.delete(preceding_node)
- else
- precedings << XPathNode.new(preceding_node,
- position: precedings.size + 1)
- end
- preceding_node = preceding_node_of(preceding_node)
- end
- precedings
- end
-
- def preceding_node_of( node )
- psn = node.previous_sibling_node
- if psn.nil?
- if node.parent.nil? or node.parent.class == Document
- return nil
- end
- return node.parent
- #psn = preceding_node_of( node.parent )
- end
- while psn and psn.kind_of? Element and psn.children.size > 0
- psn = psn.children[-1]
- end
- psn
- end
-
- def following(node)
- followings = []
- following_node = next_sibling_node(node)
- while following_node
- followings << XPathNode.new(following_node,
- position: followings.size + 1)
- following_node = following_node_of(following_node)
- end
- followings
- end
-
- def following_node_of( node )
- if node.kind_of? Element and node.children.size > 0
- return node.children[0]
- end
- return next_sibling_node(node)
- end
-
- def next_sibling_node(node)
- psn = node.next_sibling_node
- while psn.nil?
- if node.parent.nil? or node.parent.class == Document
- return nil
- end
- node = node.parent
- psn = node.next_sibling_node
- end
- return psn
- end
-
- def child(nodeset)
- nodesets = []
- nodeset.each do |node|
- raw_node = node.raw_node
- node_type = raw_node.node_type
- # trace(:child, node_type, node)
- case node_type
- when :element
- nodesets << raw_node.children.collect.with_index do |child_node, i|
- XPathNode.new(child_node, position: i + 1)
- end
- when :document
- new_nodeset = []
- raw_node.children.each do |child|
- case child
- when XMLDecl, Text
- # Ignore
- else
- new_nodeset << XPathNode.new(child, position: new_nodeset.size + 1)
- end
- end
- nodesets << new_nodeset unless new_nodeset.empty?
- end
- end
- nodesets
- end
-
- def norm b
- case b
- when true, false
- return b
- when 'true', 'false'
- return Functions::boolean( b )
- when /^\d+(\.\d+)?$/, Numeric
- return Functions::number( b )
- else
- return Functions::string( b )
- end
- end
-
- def equality_relational_compare(set1, op, set2)
- set1 = unnode(set1) if set1.is_a?(Array)
- set2 = unnode(set2) if set2.is_a?(Array)
-
- if set1.kind_of? Array and set2.kind_of? Array
- # If both objects to be compared are node-sets, then the
- # comparison will be true if and only if there is a node in the
- # first node-set and a node in the second node-set such that the
- # result of performing the comparison on the string-values of
- # the two nodes is true.
- set1.product(set2).any? do |node1, node2|
- node_string1 = Functions.string(node1)
- node_string2 = Functions.string(node2)
- compare(node_string1, op, node_string2)
- end
- elsif set1.kind_of? Array or set2.kind_of? Array
- # If one is nodeset and other is number, compare number to each item
- # in nodeset s.t. number op number(string(item))
- # If one is nodeset and other is string, compare string to each item
- # in nodeset s.t. string op string(item)
- # If one is nodeset and other is boolean, compare boolean to each item
- # in nodeset s.t. boolean op boolean(item)
- if set1.kind_of? Array
- a = set1
- b = set2
- else
- a = set2
- b = set1
- end
-
- case b
- when true, false
- each_unnode(a).any? do |unnoded|
- compare(Functions.boolean(unnoded), op, b)
- end
- when Numeric
- each_unnode(a).any? do |unnoded|
- compare(Functions.number(unnoded), op, b)
- end
- when /\A\d+(\.\d+)?\z/
- b = Functions.number(b)
- each_unnode(a).any? do |unnoded|
- compare(Functions.number(unnoded), op, b)
- end
- else
- b = Functions::string(b)
- each_unnode(a).any? do |unnoded|
- compare(Functions::string(unnoded), op, b)
- end
- end
- else
- # If neither is nodeset,
- # If op is = or !=
- # If either boolean, convert to boolean
- # If either number, convert to number
- # Else, convert to string
- # Else
- # Convert both to numbers and compare
- compare(set1, op, set2)
- end
- end
-
- def value_type(value)
- case value
- when true, false
- :boolean
- when Numeric
- :number
- when String
- :string
- else
- raise "[BUG] Unexpected value type: <#{value.inspect}>"
- end
- end
-
- def normalize_compare_values(a, operator, b)
- a_type = value_type(a)
- b_type = value_type(b)
- case operator
- when :eq, :neq
- if a_type == :boolean or b_type == :boolean
- a = Functions.boolean(a) unless a_type == :boolean
- b = Functions.boolean(b) unless b_type == :boolean
- elsif a_type == :number or b_type == :number
- a = Functions.number(a) unless a_type == :number
- b = Functions.number(b) unless b_type == :number
- else
- a = Functions.string(a) unless a_type == :string
- b = Functions.string(b) unless b_type == :string
- end
- when :lt, :lteq, :gt, :gteq
- a = Functions.number(a) unless a_type == :number
- b = Functions.number(b) unless b_type == :number
- else
- message = "[BUG] Unexpected compare operator: " +
- "<#{operator.inspect}>: <#{a.inspect}>: <#{b.inspect}>"
- raise message
- end
- [a, b]
- end
-
- def compare(a, operator, b)
- a, b = normalize_compare_values(a, operator, b)
- case operator
- when :eq
- a == b
- when :neq
- a != b
- when :lt
- a < b
- when :lteq
- a <= b
- when :gt
- a > b
- when :gteq
- a >= b
- else
- message = "[BUG] Unexpected compare operator: " +
- "<#{operator.inspect}>: <#{a.inspect}>: <#{b.inspect}>"
- raise message
- end
- end
-
- def each_unnode(nodeset)
- return to_enum(__method__, nodeset) unless block_given?
- nodeset.each do |node|
- if node.is_a?(XPathNode)
- unnoded = node.raw_node
- else
- unnoded = node
- end
- yield(unnoded)
- end
- end
-
- def unnode(nodeset)
- each_unnode(nodeset).collect do |unnoded|
- unnoded = yield(unnoded) if block_given?
- unnoded
- end
- end
- end
-
- # @private
- class XPathNode
- attr_reader :raw_node, :context
- def initialize(node, context=nil)
- if node.is_a?(XPathNode)
- @raw_node = node.raw_node
- else
- @raw_node = node
- end
- @context = context || {}
- end
-
- def position
- @context[:position]
- end
- end
-end
diff --git a/lib/rinda/rinda.gemspec b/lib/rinda/rinda.gemspec
new file mode 100644
index 0000000000..0c13e3c2df
--- /dev/null
+++ b/lib/rinda/rinda.gemspec
@@ -0,0 +1,28 @@
+Gem::Specification.new do |spec|
+ spec.name = "rinda"
+ spec.version = "0.1.1"
+ spec.authors = ["Masatoshi SEKI"]
+ spec.email = ["seki@ruby-lang.org"]
+
+ spec.summary = %q{The Linda distributed computing paradigm in Ruby.}
+ spec.description = %q{The Linda distributed computing paradigm in Ruby.}
+ spec.homepage = "https://github.com/ruby/rinda"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "drb"
+ spec.add_dependency "ipaddr"
+ spec.add_dependency "forwardable"
+end
diff --git a/lib/rss.rb b/lib/rss.rb
deleted file mode 100644
index 1438d97bd3..0000000000
--- a/lib/rss.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: false
-##
-# = RSS reading and writing
-#
-# Really Simple Syndication (RSS) is a family of formats that describe 'feeds,'
-# specially constructed XML documents that allow an interested person to
-# subscribe and receive updates from a particular web service. This portion of
-# the standard library provides tooling to read and create these feeds.
-#
-# The standard library supports RSS 0.91, 1.0, 2.0, and Atom, a related format.
-# Here are some links to the standards documents for these formats:
-#
-# * RSS
-# * 0.9.1[http://www.rssboard.org/rss-0-9-1-netscape]
-# * 1.0[http://web.resource.org/rss/1.0/]
-# * 2.0[http://www.rssboard.org/rss-specification]
-# * Atom[http://tools.ietf.org/html/rfc4287]
-#
-# == Consuming RSS
-#
-# If you'd like to read someone's RSS feed with your Ruby code, you've come to
-# the right place. It's really easy to do this, but we'll need the help of
-# open-uri:
-#
-# require 'rss'
-# require 'open-uri'
-#
-# url = 'http://www.ruby-lang.org/en/feeds/news.rss'
-# open(url) do |rss|
-# feed = RSS::Parser.parse(rss)
-# puts "Title: #{feed.channel.title}"
-# feed.items.each do |item|
-# puts "Item: #{item.title}"
-# end
-# end
-#
-# As you can see, the workhorse is RSS::Parser#parse, which takes the source of
-# the feed and a parameter that performs validation on the feed. We get back an
-# object that has all of the data from our feed, accessible through methods.
-# This example shows getting the title out of the channel element, and looping
-# through the list of items.
-#
-# == Producing RSS
-#
-# Producing our own RSS feeds is easy as well. Let's make a very basic feed:
-#
-# require "rss"
-#
-# rss = RSS::Maker.make("atom") do |maker|
-# maker.channel.author = "matz"
-# maker.channel.updated = Time.now.to_s
-# maker.channel.about = "http://www.ruby-lang.org/en/feeds/news.rss"
-# maker.channel.title = "Example Feed"
-#
-# maker.items.new_item do |item|
-# item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/"
-# item.title = "Ruby 1.9.2-p136 is released"
-# item.updated = Time.now.to_s
-# end
-# end
-#
-# puts rss
-#
-# As you can see, this is a very Builder-like DSL. This code will spit out an
-# Atom feed with one item. If we needed a second item, we'd make another block
-# with maker.items.new_item and build a second one.
-#
-# == Copyright
-#
-# Copyright (c) 2003-2007 Kouhei Sutou <kou@cozmixng.org>
-#
-# You can redistribute it and/or modify it under the same terms as Ruby.
-#
-# There is an additional tutorial by the author of RSS at:
-# http://www.cozmixng.org/~rwiki/?cmd=view;name=RSS+Parser%3A%3ATutorial.en
-
-module RSS
-end
-
-require "rss/version"
-
-require 'rss/1.0'
-require 'rss/2.0'
-require 'rss/atom'
-require 'rss/content'
-require 'rss/dublincore'
-require 'rss/image'
-require 'rss/itunes'
-require 'rss/slash'
-require 'rss/syndication'
-require 'rss/taxonomy'
-require 'rss/trackback'
-
-require "rss/maker"
diff --git a/lib/rss/0.9.rb b/lib/rss/0.9.rb
deleted file mode 100644
index 219ccefcdb..0000000000
--- a/lib/rss/0.9.rb
+++ /dev/null
@@ -1,462 +0,0 @@
-# frozen_string_literal: false
-require_relative "parser"
-
-module RSS
-
- ##
- # = RSS 0.9 support
- #
- # RSS has three different versions. This module contains support for version
- # 0.9.1[http://www.rssboard.org/rss-0-9-1-netscape].
- #
- # == Producing RSS 0.9
- #
- # Producing our own RSS feeds is easy as well. Let's make a very basic feed:
- #
- # require "rss"
- #
- # rss = RSS::Maker.make("0.91") do |maker|
- # maker.channel.language = "en"
- # maker.channel.author = "matz"
- # maker.channel.updated = Time.now.to_s
- # maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss"
- # maker.channel.title = "Example Feed"
- # maker.channel.description = "A longer description of my feed."
- # maker.image.url = "http://www.ruby-lang.org/images/logo.gif"
- # maker.image.title = "An image"
- # maker.items.new_item do |item|
- # item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/"
- # item.title = "Ruby 1.9.2-p136 is released"
- # item.updated = Time.now.to_s
- # end
- # end
- #
- # puts rss
- #
- # As you can see, this is a very Builder-like DSL. This code will spit out an
- # RSS 0.9 feed with one item. If we needed a second item, we'd make another
- # block with maker.items.new_item and build a second one.
- module RSS09
- NSPOOL = {}
- ELEMENTS = []
-
- def self.append_features(klass)
- super
-
- klass.install_must_call_validator('', "")
- end
- end
-
- class Rss < Element
-
- include RSS09
- include RootElementMixin
-
- %w(channel).each do |name|
- install_have_child_element(name, "", nil)
- end
-
- attr_writer :feed_version
- alias_method(:rss_version, :feed_version)
- alias_method(:rss_version=, :feed_version=)
-
- def initialize(feed_version, version=nil, encoding=nil, standalone=nil)
- super
- @feed_type = "rss"
- end
-
- def items
- if @channel
- @channel.items
- else
- []
- end
- end
-
- def image
- if @channel
- @channel.image
- else
- nil
- end
- end
-
- def textinput
- if @channel
- @channel.textInput
- else
- nil
- end
- end
-
- def setup_maker_elements(maker)
- super
- items.each do |item|
- item.setup_maker(maker.items)
- end
- image.setup_maker(maker) if image
- textinput.setup_maker(maker) if textinput
- end
-
- private
- def _attrs
- [
- ["version", true, "feed_version"],
- ]
- end
-
- class Channel < Element
-
- include RSS09
-
- [
- ["title", nil, :text],
- ["link", nil, :text],
- ["description", nil, :text],
- ["language", nil, :text],
- ["copyright", "?", :text],
- ["managingEditor", "?", :text],
- ["webMaster", "?", :text],
- ["rating", "?", :text],
- ["pubDate", "?", :date, :rfc822],
- ["lastBuildDate", "?", :date, :rfc822],
- ["docs", "?", :text],
- ["cloud", "?", :have_attribute],
- ["skipDays", "?", :have_child],
- ["skipHours", "?", :have_child],
- ["image", nil, :have_child],
- ["item", "*", :have_children],
- ["textInput", "?", :have_child],
- ].each do |name, occurs, type, *args|
- __send__("install_#{type}_element", name, "", occurs, name, *args)
- end
- alias date pubDate
- alias date= pubDate=
-
- private
- def maker_target(maker)
- maker.channel
- end
-
- def setup_maker_elements(channel)
- super
- [
- [skipDays, "day"],
- [skipHours, "hour"],
- ].each do |skip, key|
- if skip
- skip.__send__("#{key}s").each do |val|
- target_skips = channel.__send__("skip#{key.capitalize}s")
- new_target = target_skips.__send__("new_#{key}")
- new_target.content = val.content
- end
- end
- end
- end
-
- def not_need_to_call_setup_maker_variables
- %w(image textInput)
- end
-
- class SkipDays < Element
- include RSS09
-
- [
- ["day", "*"]
- ].each do |name, occurs|
- install_have_children_element(name, "", occurs)
- end
-
- class Day < Element
- include RSS09
-
- content_setup
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.content = args[0]
- end
- end
-
- end
-
- end
-
- class SkipHours < Element
- include RSS09
-
- [
- ["hour", "*"]
- ].each do |name, occurs|
- install_have_children_element(name, "", occurs)
- end
-
- class Hour < Element
- include RSS09
-
- content_setup(:integer)
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.content = args[0]
- end
- end
- end
-
- end
-
- class Image < Element
-
- include RSS09
-
- %w(url title link).each do |name|
- install_text_element(name, "", nil)
- end
- [
- ["width", :integer],
- ["height", :integer],
- ["description"],
- ].each do |name, type|
- install_text_element(name, "", "?", name, type)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.url = args[0]
- self.title = args[1]
- self.link = args[2]
- self.width = args[3]
- self.height = args[4]
- self.description = args[5]
- end
- end
-
- private
- def maker_target(maker)
- maker.image
- end
- end
-
- class Cloud < Element
-
- include RSS09
-
- [
- ["domain", "", true],
- ["port", "", true, :integer],
- ["path", "", true],
- ["registerProcedure", "", true],
- ["protocol", "", true],
- ].each do |name, uri, required, type|
- install_get_attribute(name, uri, required, type)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.domain = args[0]
- self.port = args[1]
- self.path = args[2]
- self.registerProcedure = args[3]
- self.protocol = args[4]
- end
- end
- end
-
- class Item < Element
-
- include RSS09
-
- [
- ["title", '?', :text],
- ["link", '?', :text],
- ["description", '?', :text],
- ["category", '*', :have_children, "categories"],
- ["source", '?', :have_child],
- ["enclosure", '?', :have_child],
- ].each do |tag, occurs, type, *args|
- __send__("install_#{type}_element", tag, "", occurs, tag, *args)
- end
-
- private
- def maker_target(items)
- if items.respond_to?("items")
- # For backward compatibility
- items = items.items
- end
- items.new_item
- end
-
- def setup_maker_element(item)
- super
- @enclosure.setup_maker(item) if @enclosure
- @source.setup_maker(item) if @source
- end
-
- class Source < Element
-
- include RSS09
-
- [
- ["url", "", true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required)
- end
-
- content_setup
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.url = args[0]
- self.content = args[1]
- end
- end
-
- private
- def maker_target(item)
- item.source
- end
-
- def setup_maker_attributes(source)
- source.url = url
- source.content = content
- end
- end
-
- class Enclosure < Element
-
- include RSS09
-
- [
- ["url", "", true],
- ["length", "", true, :integer],
- ["type", "", true],
- ].each do |name, uri, required, type|
- install_get_attribute(name, uri, required, type)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.url = args[0]
- self.length = args[1]
- self.type = args[2]
- end
- end
-
- private
- def maker_target(item)
- item.enclosure
- end
-
- def setup_maker_attributes(enclosure)
- enclosure.url = url
- enclosure.length = length
- enclosure.type = type
- end
- end
-
- class Category < Element
-
- include RSS09
-
- [
- ["domain", "", false]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required)
- end
-
- content_setup
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.domain = args[0]
- self.content = args[1]
- end
- end
-
- private
- def maker_target(item)
- item.new_category
- end
-
- def setup_maker_attributes(category)
- category.domain = domain
- category.content = content
- end
-
- end
-
- end
-
- class TextInput < Element
-
- include RSS09
-
- %w(title description name link).each do |name|
- install_text_element(name, "", nil)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.title = args[0]
- self.description = args[1]
- self.name = args[2]
- self.link = args[3]
- end
- end
-
- private
- def maker_target(maker)
- maker.textinput
- end
- end
-
- end
-
- end
-
- RSS09::ELEMENTS.each do |name|
- BaseListener.install_get_text_element("", name, name)
- end
-
- module ListenerMixin
- private
- def initial_start_rss(tag_name, prefix, attrs, ns)
- check_ns(tag_name, prefix, ns, "", false)
-
- @rss = Rss.new(attrs['version'], @version, @encoding, @standalone)
- @rss.do_validate = @do_validate
- @rss.xml_stylesheets = @xml_stylesheets
- @last_element = @rss
- pr = Proc.new do |text, tags|
- @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate
- end
- @proc_stack.push(pr)
- end
-
- end
-
-end
diff --git a/lib/rss/1.0.rb b/lib/rss/1.0.rb
deleted file mode 100644
index c8f92fb54e..0000000000
--- a/lib/rss/1.0.rb
+++ /dev/null
@@ -1,485 +0,0 @@
-# frozen_string_literal: false
-require_relative "parser"
-
-module RSS
-
- ##
- # = RSS 1.0 support
- #
- # RSS has three different versions. This module contains support for version
- # 1.0[http://web.resource.org/rss/1.0/]
- #
- # == Producing RSS 1.0
- #
- # Producing our own RSS feeds is easy as well. Let's make a very basic feed:
- #
- # require "rss"
- #
- # rss = RSS::Maker.make("1.0") do |maker|
- # maker.channel.language = "en"
- # maker.channel.author = "matz"
- # maker.channel.about = "About my feed."
- # maker.channel.updated = Time.now.to_s
- # maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss"
- # maker.channel.title = "Example Feed"
- # maker.channel.description = "A longer description of my feed."
- # maker.items.new_item do |item|
- # item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/"
- # item.title = "Ruby 1.9.2-p136 is released"
- # item.updated = Time.now.to_s
- # end
- # end
- #
- # puts rss
- #
- # As you can see, this is a very Builder-like DSL. This code will spit out an
- # RSS 1.0 feed with one item. If we needed a second item, we'd make another
- # block with maker.items.new_item and build a second one.
- module RSS10
- NSPOOL = {}
- ELEMENTS = []
-
- def self.append_features(klass)
- super
-
- klass.install_must_call_validator('', ::RSS::URI)
- end
-
- end
-
- class RDF < Element
-
- include RSS10
- include RootElementMixin
-
- class << self
-
- def required_uri
- URI
- end
-
- end
-
- @tag_name = 'RDF'
-
- PREFIX = 'rdf'
- URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-
- install_ns('', ::RSS::URI)
- install_ns(PREFIX, URI)
-
- [
- ["channel", nil],
- ["image", "?"],
- ["item", "+", :children],
- ["textinput", "?"],
- ].each do |tag, occurs, type|
- type ||= :child
- __send__("install_have_#{type}_element", tag, ::RSS::URI, occurs)
- end
-
- alias_method(:rss_version, :feed_version)
- def initialize(version=nil, encoding=nil, standalone=nil)
- super('1.0', version, encoding, standalone)
- @feed_type = "rss"
- end
-
- def full_name
- tag_name_with_prefix(PREFIX)
- end
-
- class Li < Element
-
- include RSS10
-
- class << self
- def required_uri
- URI
- end
- end
-
- [
- ["resource", [URI, ""], true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.resource = args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(PREFIX)
- end
- end
-
- class Seq < Element
-
- include RSS10
-
- Li = ::RSS::RDF::Li
-
- class << self
- def required_uri
- URI
- end
- end
-
- @tag_name = 'Seq'
-
- install_have_children_element("li", URI, "*")
- install_must_call_validator('rdf', ::RSS::RDF::URI)
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- @li = args[0] if args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(PREFIX)
- end
-
- def setup_maker(target)
- lis.each do |li|
- target << li.resource
- end
- end
- end
-
- class Bag < Element
-
- include RSS10
-
- Li = ::RSS::RDF::Li
-
- class << self
- def required_uri
- URI
- end
- end
-
- @tag_name = 'Bag'
-
- install_have_children_element("li", URI, "*")
- install_must_call_validator('rdf', URI)
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- @li = args[0] if args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(PREFIX)
- end
-
- def setup_maker(target)
- lis.each do |li|
- target << li.resource
- end
- end
- end
-
- class Channel < Element
-
- include RSS10
-
- class << self
-
- def required_uri
- ::RSS::URI
- end
-
- end
-
- [
- ["about", URI, true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, nil, nil,
- "#{PREFIX}:#{name}")
- end
-
- [
- ['title', nil, :text],
- ['link', nil, :text],
- ['description', nil, :text],
- ['image', '?', :have_child],
- ['items', nil, :have_child],
- ['textinput', '?', :have_child],
- ].each do |tag, occurs, type|
- __send__("install_#{type}_element", tag, ::RSS::URI, occurs)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.about = args[0]
- end
- end
-
- private
- def maker_target(maker)
- maker.channel
- end
-
- def setup_maker_attributes(channel)
- channel.about = about
- end
-
- class Image < Element
-
- include RSS10
-
- class << self
-
- def required_uri
- ::RSS::URI
- end
-
- end
-
- [
- ["resource", URI, true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, nil, nil,
- "#{PREFIX}:#{name}")
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.resource = args[0]
- end
- end
- end
-
- class Textinput < Element
-
- include RSS10
-
- class << self
-
- def required_uri
- ::RSS::URI
- end
-
- end
-
- [
- ["resource", URI, true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, nil, nil,
- "#{PREFIX}:#{name}")
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.resource = args[0]
- end
- end
- end
-
- class Items < Element
-
- include RSS10
-
- Seq = ::RSS::RDF::Seq
-
- class << self
-
- def required_uri
- ::RSS::URI
- end
-
- end
-
- install_have_child_element("Seq", URI, nil)
- install_must_call_validator('rdf', URI)
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.Seq = args[0]
- end
- self.Seq ||= Seq.new
- end
-
- def resources
- if @Seq
- @Seq.lis.collect do |li|
- li.resource
- end
- else
- []
- end
- end
- end
- end
-
- class Image < Element
-
- include RSS10
-
- class << self
-
- def required_uri
- ::RSS::URI
- end
-
- end
-
- [
- ["about", URI, true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, nil, nil,
- "#{PREFIX}:#{name}")
- end
-
- %w(title url link).each do |name|
- install_text_element(name, ::RSS::URI, nil)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.about = args[0]
- end
- end
-
- private
- def maker_target(maker)
- maker.image
- end
- end
-
- class Item < Element
-
- include RSS10
-
- class << self
-
- def required_uri
- ::RSS::URI
- end
-
- end
-
-
- [
- ["about", URI, true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, nil, nil,
- "#{PREFIX}:#{name}")
- end
-
- [
- ["title", nil],
- ["link", nil],
- ["description", "?"],
- ].each do |tag, occurs|
- install_text_element(tag, ::RSS::URI, occurs)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.about = args[0]
- end
- end
-
- private
- def maker_target(items)
- if items.respond_to?("items")
- # For backward compatibility
- items = items.items
- end
- items.new_item
- end
- end
-
- class Textinput < Element
-
- include RSS10
-
- class << self
-
- def required_uri
- ::RSS::URI
- end
-
- end
-
- [
- ["about", URI, true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, nil, nil,
- "#{PREFIX}:#{name}")
- end
-
- %w(title description name link).each do |name|
- install_text_element(name, ::RSS::URI, nil)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.about = args[0]
- end
- end
-
- private
- def maker_target(maker)
- maker.textinput
- end
- end
-
- end
-
- RSS10::ELEMENTS.each do |name|
- BaseListener.install_get_text_element(URI, name, name)
- end
-
- module ListenerMixin
- private
- def initial_start_RDF(tag_name, prefix, attrs, ns)
- check_ns(tag_name, prefix, ns, RDF::URI, false)
-
- @rss = RDF.new(@version, @encoding, @standalone)
- @rss.do_validate = @do_validate
- @rss.xml_stylesheets = @xml_stylesheets
- @last_element = @rss
- pr = Proc.new do |text, tags|
- @rss.validate_for_stream(tags, @ignore_unknown_element) if @do_validate
- end
- @proc_stack.push(pr)
- end
- end
-
-end
diff --git a/lib/rss/2.0.rb b/lib/rss/2.0.rb
deleted file mode 100644
index 13f9ade918..0000000000
--- a/lib/rss/2.0.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-# frozen_string_literal: false
-require "rss/0.9"
-
-module RSS
-
- ##
- # = RSS 2.0 support
- #
- # RSS has three different versions. This module contains support for version
- # 2.0[http://www.rssboard.org/rss-specification]
- #
- # == Producing RSS 2.0
- #
- # Producing our own RSS feeds is easy as well. Let's make a very basic feed:
- #
- # require "rss"
- #
- # rss = RSS::Maker.make("2.0") do |maker|
- # maker.channel.language = "en"
- # maker.channel.author = "matz"
- # maker.channel.updated = Time.now.to_s
- # maker.channel.link = "http://www.ruby-lang.org/en/feeds/news.rss"
- # maker.channel.title = "Example Feed"
- # maker.channel.description = "A longer description of my feed."
- # maker.items.new_item do |item|
- # item.link = "http://www.ruby-lang.org/en/news/2010/12/25/ruby-1-9-2-p136-is-released/"
- # item.title = "Ruby 1.9.2-p136 is released"
- # item.updated = Time.now.to_s
- # end
- # end
- #
- # puts rss
- #
- # As you can see, this is a very Builder-like DSL. This code will spit out an
- # RSS 2.0 feed with one item. If we needed a second item, we'd make another
- # block with maker.items.new_item and build a second one.
- class Rss
-
- class Channel
-
- [
- ["generator"],
- ["ttl", :integer],
- ].each do |name, type|
- install_text_element(name, "", "?", name, type)
- end
-
- [
- %w(category categories),
- ].each do |name, plural_name|
- install_have_children_element(name, "", "*", name, plural_name)
- end
-
- [
- ["image", "?"],
- ["language", "?"],
- ].each do |name, occurs|
- install_model(name, "", occurs)
- end
-
- Category = Item::Category
-
- class Item
-
- [
- ["comments", "?"],
- ["author", "?"],
- ].each do |name, occurs|
- install_text_element(name, "", occurs)
- end
-
- [
- ["pubDate", '?'],
- ].each do |name, occurs|
- install_date_element(name, "", occurs, name, 'rfc822')
- end
- alias date pubDate
- alias date= pubDate=
-
- [
- ["guid", '?'],
- ].each do |name, occurs|
- install_have_child_element(name, "", occurs)
- end
-
- private
- alias _setup_maker_element setup_maker_element
- def setup_maker_element(item)
- _setup_maker_element(item)
- @guid.setup_maker(item) if @guid
- end
-
- class Guid < Element
-
- include RSS09
-
- [
- ["isPermaLink", "", false, :boolean]
- ].each do |name, uri, required, type|
- install_get_attribute(name, uri, required, type)
- end
-
- content_setup
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.isPermaLink = args[0]
- self.content = args[1]
- end
- end
-
- alias_method :_PermaLink?, :PermaLink?
- private :_PermaLink?
- def PermaLink?
- perma = _PermaLink?
- perma or perma.nil?
- end
-
- private
- def maker_target(item)
- item.guid
- end
-
- def setup_maker_attributes(guid)
- guid.isPermaLink = isPermaLink
- guid.content = content
- end
- end
-
- end
-
- end
-
- end
-
- RSS09::ELEMENTS.each do |name|
- BaseListener.install_get_text_element("", name, name)
- end
-
-end
diff --git a/lib/rss/atom.rb b/lib/rss/atom.rb
deleted file mode 100644
index 48c27330d0..0000000000
--- a/lib/rss/atom.rb
+++ /dev/null
@@ -1,1025 +0,0 @@
-# frozen_string_literal: false
-require_relative 'parser'
-
-module RSS
- ##
- # Atom is an XML-based document format that is used to describe 'feeds' of related information.
- # A typical use is in a news feed where the information is periodically updated and which users
- # can subscribe to. The Atom format is described in http://tools.ietf.org/html/rfc4287
- #
- # The Atom module provides support in reading and creating feeds.
- #
- # See the RSS module for examples consuming and creating feeds.
- module Atom
-
- ##
- # The Atom URI W3C Namespace
-
- URI = "http://www.w3.org/2005/Atom"
-
- ##
- # The XHTML URI W3C Namespace
-
- XHTML_URI = "http://www.w3.org/1999/xhtml"
-
- module CommonModel
- NSPOOL = {}
- ELEMENTS = []
-
- def self.append_features(klass)
- super
- klass.install_must_call_validator("atom", URI)
- [
- ["lang", :xml],
- ["base", :xml],
- ].each do |name, uri, required|
- klass.install_get_attribute(name, uri, required, [nil, :inherit])
- end
- klass.class_eval do
- class << self
- # Returns the Atom URI W3C Namespace
- def required_uri
- URI
- end
-
- # Returns true
- def need_parent?
- true
- end
- end
- end
- end
- end
-
- module ContentModel
- module ClassMethods
- def content_type
- @content_type ||= nil
- end
- end
-
- class << self
- def append_features(klass)
- super
- klass.extend(ClassMethods)
- klass.content_setup(klass.content_type, klass.tag_name)
- end
- end
-
- def maker_target(target)
- target
- end
-
- private
- def setup_maker_element_writer
- "#{self.class.name.split(/::/).last.downcase}="
- end
-
- def setup_maker_element(target)
- target.__send__(setup_maker_element_writer, content)
- super
- end
- end
-
- module URIContentModel
- class << self
- def append_features(klass)
- super
- klass.class_eval do
- @content_type = [nil, :uri]
- include(ContentModel)
- end
- end
- end
- end
-
- # The TextConstruct module is used to define a Text construct Atom element,
- # which is used to store small quantities of human-readable text.
- #
- # The TextConstruct has a type attribute, e.g. text, html, xhtml
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#text.constructs
- module TextConstruct
- def self.append_features(klass)
- super
- klass.class_eval do
- [
- ["type", ""],
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, :text_type)
- end
-
- content_setup
- add_need_initialize_variable("xhtml")
-
- class << self
- def xml_getter
- "xhtml"
- end
-
- def xml_setter
- "xhtml="
- end
- end
- end
- end
-
- attr_writer :xhtml
-
- # Returns or builds the XHTML content.
- def xhtml
- return @xhtml if @xhtml.nil?
- if @xhtml.is_a?(XML::Element) and
- [@xhtml.name, @xhtml.uri] == ["div", XHTML_URI]
- return @xhtml
- end
-
- children = @xhtml
- children = [children] unless children.is_a?(Array)
- XML::Element.new("div", nil, XHTML_URI,
- {"xmlns" => XHTML_URI}, children)
- end
-
- # Returns true if type is "xhtml".
- def have_xml_content?
- @type == "xhtml"
- end
-
- # Raises a MissingTagError or NotExpectedTagError
- # if the element is not properly formatted.
- def atom_validate(ignore_unknown_element, tags, uri)
- if have_xml_content?
- if @xhtml.nil?
- raise MissingTagError.new("div", tag_name)
- end
- unless [@xhtml.name, @xhtml.uri] == ["div", XHTML_URI]
- raise NotExpectedTagError.new(@xhtml.name, @xhtml.uri, tag_name)
- end
- end
- end
-
- private
- def maker_target(target)
- target.__send__(self.class.name.split(/::/).last.downcase) {|x| x}
- end
-
- def setup_maker_attributes(target)
- target.type = type
- target.content = content
- target.xml_content = @xhtml
- end
- end
-
- # The PersonConstruct module is used to define a person Atom element that can be
- # used to describe a person, corporation or similar entity.
- #
- # The PersonConstruct has a Name, Uri and Email child elements.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#atomPersonConstruct
- module PersonConstruct
-
- # Adds attributes for name, uri, and email to the +klass+
- def self.append_features(klass)
- super
- klass.class_eval do
- [
- ["name", nil],
- ["uri", "?"],
- ["email", "?"],
- ].each do |tag, occurs|
- install_have_attribute_element(tag, URI, occurs, nil, :content)
- end
- end
- end
-
- def maker_target(target)
- target.__send__("new_#{self.class.name.split(/::/).last.downcase}")
- end
-
- # The name of the person or entity.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.name
- class Name < RSS::Element
- include CommonModel
- include ContentModel
- end
-
- # The URI of the person or entity.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.uri
- class Uri < RSS::Element
- include CommonModel
- include URIContentModel
- end
-
- # The email of the person or entity.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.email
- class Email < RSS::Element
- include CommonModel
- include ContentModel
- end
- end
-
- # Element used to describe an Atom date and time in the ISO 8601 format
- #
- # Examples:
- # * 2013-03-04T15:30:02Z
- # * 2013-03-04T10:30:02-05:00
- module DateConstruct
- def self.append_features(klass)
- super
- klass.class_eval do
- @content_type = :w3cdtf
- include(ContentModel)
- end
- end
-
- # Raises NotAvailableValueError if element content is nil
- def atom_validate(ignore_unknown_element, tags, uri)
- raise NotAvailableValueError.new(tag_name, "") if content.nil?
- end
- end
-
- module DuplicateLinkChecker
- # Checks if there are duplicate links with the same type and hreflang attributes
- # that have an alternate (or empty) rel attribute
- #
- # Raises a TooMuchTagError if there are duplicates found
- def validate_duplicate_links(links)
- link_infos = {}
- links.each do |link|
- rel = link.rel || "alternate"
- next unless rel == "alternate"
- key = [link.hreflang, link.type]
- if link_infos.has_key?(key)
- raise TooMuchTagError.new("link", tag_name)
- end
- link_infos[key] = true
- end
- end
- end
-
- # Defines the top-level element of an Atom Feed Document.
- # It consists of a number of children Entry elements,
- # and has the following attributes:
- #
- # * author
- # * categories
- # * category
- # * content
- # * contributor
- # * entries (aliased as items)
- # * entry
- # * generator
- # * icon
- # * id
- # * link
- # * logo
- # * rights
- # * subtitle
- # * title
- # * updated
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.feed
- class Feed < RSS::Element
- include RootElementMixin
- include CommonModel
- include DuplicateLinkChecker
-
- install_ns('', URI)
-
- [
- ["author", "*", :children],
- ["category", "*", :children, "categories"],
- ["contributor", "*", :children],
- ["generator", "?"],
- ["icon", "?", nil, :content],
- ["id", nil, nil, :content],
- ["link", "*", :children],
- ["logo", "?"],
- ["rights", "?"],
- ["subtitle", "?", nil, :content],
- ["title", nil, nil, :content],
- ["updated", nil, nil, :content],
- ["entry", "*", :children, "entries"],
- ].each do |tag, occurs, type, *args|
- type ||= :child
- __send__("install_have_#{type}_element",
- tag, URI, occurs, tag, *args)
- end
-
- # Creates a new Atom feed
- def initialize(version=nil, encoding=nil, standalone=nil)
- super("1.0", version, encoding, standalone)
- @feed_type = "atom"
- @feed_subtype = "feed"
- end
-
- alias_method :items, :entries
-
- # Returns true if there are any authors for the feed or any of the Entry
- # child elements have an author
- def have_author?
- authors.any? {|author| !author.to_s.empty?} or
- entries.any? {|entry| entry.have_author?(false)}
- end
-
- private
- def atom_validate(ignore_unknown_element, tags, uri)
- unless have_author?
- raise MissingTagError.new("author", tag_name)
- end
- validate_duplicate_links(links)
- end
-
- def have_required_elements?
- super and have_author?
- end
-
- def maker_target(maker)
- maker.channel
- end
-
- def setup_maker_element(channel)
- prev_dc_dates = channel.dc_dates.to_a.dup
- super
- channel.about = id.content if id
- channel.dc_dates.replace(prev_dc_dates)
- end
-
- def setup_maker_elements(channel)
- super
- items = channel.maker.items
- entries.each do |entry|
- entry.setup_maker(items)
- end
- end
-
- # PersonConstruct that contains information regarding the author
- # of a Feed or Entry.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.author
- class Author < RSS::Element
- include CommonModel
- include PersonConstruct
- end
-
- # Contains information about a category associated with a Feed or Entry.
- # It has the following attributes:
- #
- # * term
- # * scheme
- # * label
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.category
- class Category < RSS::Element
- include CommonModel
-
- [
- ["term", "", true],
- ["scheme", "", false, [nil, :uri]],
- ["label", ""],
- ].each do |name, uri, required, type|
- install_get_attribute(name, uri, required, type)
- end
-
- private
- def maker_target(target)
- target.new_category
- end
- end
-
- # PersonConstruct that contains information regarding the
- # contributors of a Feed or Entry.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.contributor
- class Contributor < RSS::Element
- include CommonModel
- include PersonConstruct
- end
-
- # Contains information on the agent used to generate the feed.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.generator
- class Generator < RSS::Element
- include CommonModel
- include ContentModel
-
- [
- ["uri", "", false, [nil, :uri]],
- ["version", ""],
- ].each do |name, uri, required, type|
- install_get_attribute(name, uri, required, type)
- end
-
- private
- def setup_maker_attributes(target)
- target.generator do |generator|
- generator.uri = uri if uri
- generator.version = version if version
- end
- end
- end
-
- # Defines an image that provides a visual identification for a eed.
- # The image should have an aspect ratio of 1:1.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.icon
- class Icon < RSS::Element
- include CommonModel
- include URIContentModel
- end
-
- # Defines the Universally Unique Identifier (UUID) for a Feed or Entry.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.id
- class Id < RSS::Element
- include CommonModel
- include URIContentModel
- end
-
- # Defines a reference to a Web resource. It has the following
- # attributes:
- #
- # * href
- # * rel
- # * type
- # * hreflang
- # * title
- # * length
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.link
- class Link < RSS::Element
- include CommonModel
-
- [
- ["href", "", true, [nil, :uri]],
- ["rel", ""],
- ["type", ""],
- ["hreflang", ""],
- ["title", ""],
- ["length", ""],
- ].each do |name, uri, required, type|
- install_get_attribute(name, uri, required, type)
- end
-
- private
- def maker_target(target)
- target.new_link
- end
- end
-
- # Defines an image that provides a visual identification for the Feed.
- # The image should have an aspect ratio of 2:1 (horizontal:vertical).
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.logo
- class Logo < RSS::Element
- include CommonModel
- include URIContentModel
-
- def maker_target(target)
- target.maker.image
- end
-
- private
- def setup_maker_element_writer
- "url="
- end
- end
-
- # TextConstruct that contains copyright information regarding
- # the content in an Entry or Feed. It should not be used to
- # convey machine readable licensing information.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.rights
- class Rights < RSS::Element
- include CommonModel
- include TextConstruct
- end
-
- # TextConstruct that conveys a description or subtitle for a Feed.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.subtitle
- class Subtitle < RSS::Element
- include CommonModel
- include TextConstruct
- end
-
- # TextConstruct that conveys a description or title for a Feed or Entry.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.title
- class Title < RSS::Element
- include CommonModel
- include TextConstruct
- end
-
- # DateConstruct indicating the most recent time when a Feed or
- # Entry was modified in a way the publisher considers
- # significant.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.updated
- class Updated < RSS::Element
- include CommonModel
- include DateConstruct
- end
-
- # Defines a child Atom Entry element of an Atom Feed element.
- # It has the following attributes:
- #
- # * author
- # * category
- # * categories
- # * content
- # * contributor
- # * id
- # * link
- # * published
- # * rights
- # * source
- # * summary
- # * title
- # * updated
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.entry
- class Entry < RSS::Element
- include CommonModel
- include DuplicateLinkChecker
-
- [
- ["author", "*", :children],
- ["category", "*", :children, "categories"],
- ["content", "?", :child],
- ["contributor", "*", :children],
- ["id", nil, nil, :content],
- ["link", "*", :children],
- ["published", "?", :child, :content],
- ["rights", "?", :child],
- ["source", "?"],
- ["summary", "?", :child],
- ["title", nil],
- ["updated", nil, :child, :content],
- ].each do |tag, occurs, type, *args|
- type ||= :attribute
- __send__("install_have_#{type}_element",
- tag, URI, occurs, tag, *args)
- end
-
- # Returns whether any of the following are true:
- #
- # * There are any authors in the feed
- # * If the parent element has an author and the +check_parent+
- # parameter was given.
- # * There is a source element that has an author
- def have_author?(check_parent=true)
- authors.any? {|author| !author.to_s.empty?} or
- (check_parent and @parent and @parent.have_author?) or
- (source and source.have_author?)
- end
-
- private
- def atom_validate(ignore_unknown_element, tags, uri)
- unless have_author?
- raise MissingTagError.new("author", tag_name)
- end
- validate_duplicate_links(links)
- end
-
- def have_required_elements?
- super and have_author?
- end
-
- def maker_target(items)
- if items.respond_to?("items")
- # For backward compatibility
- items = items.items
- end
- items.new_item
- end
-
- # Feed::Author
- Author = Feed::Author
- # Feed::Category
- Category = Feed::Category
-
- # Contains or links to the content of the Entry.
- # It has the following attributes:
- #
- # * type
- # * src
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.content
- class Content < RSS::Element
- include CommonModel
-
- class << self
- def xml_setter
- "xml="
- end
-
- def xml_getter
- "xml"
- end
- end
-
- [
- ["type", ""],
- ["src", "", false, [nil, :uri]],
- ].each do |name, uri, required, type|
- install_get_attribute(name, uri, required, type)
- end
-
- content_setup
- add_need_initialize_variable("xml")
-
- # Returns the element content in XML.
- attr_writer :xml
-
- # Returns true if the element has inline XML content.
- def have_xml_content?
- inline_xhtml? or inline_other_xml?
- end
-
- # Returns or builds the element content in XML.
- def xml
- return @xml unless inline_xhtml?
- return @xml if @xml.nil?
- if @xml.is_a?(XML::Element) and
- [@xml.name, @xml.uri] == ["div", XHTML_URI]
- return @xml
- end
-
- children = @xml
- children = [children] unless children.is_a?(Array)
- XML::Element.new("div", nil, XHTML_URI,
- {"xmlns" => XHTML_URI}, children)
- end
-
- # Returns the element content in XHTML.
- def xhtml
- if inline_xhtml?
- xml
- else
- nil
- end
- end
-
- # Raises a MissingAttributeError, NotAvailableValueError,
- # MissingTagError or NotExpectedTagError if the element is
- # not properly formatted.
- def atom_validate(ignore_unknown_element, tags, uri)
- if out_of_line?
- raise MissingAttributeError.new(tag_name, "type") if @type.nil?
- unless (content.nil? or content.empty?)
- raise NotAvailableValueError.new(tag_name, content)
- end
- elsif inline_xhtml?
- if @xml.nil?
- raise MissingTagError.new("div", tag_name)
- end
- unless @xml.name == "div" and @xml.uri == XHTML_URI
- raise NotExpectedTagError.new(@xml.name, @xml.uri, tag_name)
- end
- end
- end
-
- # Returns true if the element contains inline content
- # that has a text or HTML media type, or no media type at all.
- def inline_text?
- !out_of_line? and [nil, "text", "html"].include?(@type)
- end
-
- # Returns true if the element contains inline content that
- # has a HTML media type.
- def inline_html?
- return false if out_of_line?
- @type == "html" or mime_split == ["text", "html"]
- end
-
- # Returns true if the element contains inline content that
- # has a XHTML media type.
- def inline_xhtml?
- !out_of_line? and @type == "xhtml"
- end
-
- # Returns true if the element contains inline content that
- # has a MIME media type.
- def inline_other?
- return false if out_of_line?
- media_type, subtype = mime_split
- return false if media_type.nil? or subtype.nil?
- true
- end
-
- # Returns true if the element contains inline content that
- # has a text media type.
- def inline_other_text?
- return false unless inline_other?
- return false if inline_other_xml?
-
- media_type, = mime_split
- return true if "text" == media_type.downcase
- false
- end
-
- # Returns true if the element contains inline content that
- # has a XML media type.
- def inline_other_xml?
- return false unless inline_other?
-
- media_type, subtype = mime_split
- normalized_mime_type = "#{media_type}/#{subtype}".downcase
- if /(?:\+xml|^xml)$/ =~ subtype or
- %w(text/xml-external-parsed-entity
- application/xml-external-parsed-entity
- application/xml-dtd).find {|x| x == normalized_mime_type}
- return true
- end
- false
- end
-
- # Returns true if the element contains inline content
- # encoded in base64.
- def inline_other_base64?
- inline_other? and !inline_other_text? and !inline_other_xml?
- end
-
- # Returns true if the element contains linked content.
- def out_of_line?
- not @src.nil?
- end
-
- # Splits the type attribute into an array, e.g. ["text", "xml"]
- def mime_split
- media_type = subtype = nil
- if /\A\s*([a-z]+)\/([a-z\+]+)\s*(?:;.*)?\z/i =~ @type.to_s
- media_type = $1.downcase
- subtype = $2.downcase
- end
- [media_type, subtype]
- end
-
- # Returns true if the content needs to be encoded in base64.
- def need_base64_encode?
- inline_other_base64?
- end
-
- private
- def empty_content?
- out_of_line? or super
- end
- end
-
- # Feed::Contributor
- Contributor = Feed::Contributor
- # Feed::Id
- Id = Feed::Id
- # Feed::Link
- Link = Feed::Link
-
- # DateConstruct that usually indicates the time of the initial
- # creation of an Entry.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.published
- class Published < RSS::Element
- include CommonModel
- include DateConstruct
- end
-
- # Feed::Rights
- Rights = Feed::Rights
-
- # Defines a Atom Source element. It has the following attributes:
- #
- # * author
- # * category
- # * categories
- # * content
- # * contributor
- # * generator
- # * icon
- # * id
- # * link
- # * logo
- # * rights
- # * subtitle
- # * title
- # * updated
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.source
- class Source < RSS::Element
- include CommonModel
-
- [
- ["author", "*", :children],
- ["category", "*", :children, "categories"],
- ["contributor", "*", :children],
- ["generator", "?"],
- ["icon", "?"],
- ["id", "?", nil, :content],
- ["link", "*", :children],
- ["logo", "?"],
- ["rights", "?"],
- ["subtitle", "?"],
- ["title", "?"],
- ["updated", "?", nil, :content],
- ].each do |tag, occurs, type, *args|
- type ||= :attribute
- __send__("install_have_#{type}_element",
- tag, URI, occurs, tag, *args)
- end
-
- # Returns true if the Source element has an author.
- def have_author?
- !author.to_s.empty?
- end
-
- # Feed::Author
- Author = Feed::Author
- # Feed::Category
- Category = Feed::Category
- # Feed::Contributor
- Contributor = Feed::Contributor
- # Feed::Generator
- Generator = Feed::Generator
- # Feed::Icon
- Icon = Feed::Icon
- # Feed::Id
- Id = Feed::Id
- # Feed::Link
- Link = Feed::Link
- # Feed::Logo
- Logo = Feed::Logo
- # Feed::Rights
- Rights = Feed::Rights
- # Feed::Subtitle
- Subtitle = Feed::Subtitle
- # Feed::Title
- Title = Feed::Title
- # Feed::Updated
- Updated = Feed::Updated
- end
-
- # TextConstruct that describes a summary of the Entry.
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.summary
- class Summary < RSS::Element
- include CommonModel
- include TextConstruct
- end
-
- # Feed::Title
- Title = Feed::Title
- # Feed::Updated
- Updated = Feed::Updated
- end
- end
-
- # Defines a top-level Atom Entry element,
- # used as the document element of a stand-alone Atom Entry Document.
- # It has the following attributes:
- #
- # * author
- # * category
- # * categories
- # * content
- # * contributor
- # * id
- # * link
- # * published
- # * rights
- # * source
- # * summary
- # * title
- # * updated
- #
- # Reference: https://validator.w3.org/feed/docs/rfc4287.html#element.entry]
- class Entry < RSS::Element
- include RootElementMixin
- include CommonModel
- include DuplicateLinkChecker
-
- [
- ["author", "*", :children],
- ["category", "*", :children, "categories"],
- ["content", "?"],
- ["contributor", "*", :children],
- ["id", nil, nil, :content],
- ["link", "*", :children],
- ["published", "?", :child, :content],
- ["rights", "?"],
- ["source", "?"],
- ["summary", "?"],
- ["title", nil],
- ["updated", nil, nil, :content],
- ].each do |tag, occurs, type, *args|
- type ||= :attribute
- __send__("install_have_#{type}_element",
- tag, URI, occurs, tag, *args)
- end
-
- # Creates a new Atom Entry element.
- def initialize(version=nil, encoding=nil, standalone=nil)
- super("1.0", version, encoding, standalone)
- @feed_type = "atom"
- @feed_subtype = "entry"
- end
-
- # Returns the Entry in an array.
- def items
- [self]
- end
-
- # Sets up the +maker+ for constructing Entry elements.
- def setup_maker(maker)
- maker = maker.maker if maker.respond_to?("maker")
- super(maker)
- end
-
- # Returns where there are any authors present or there is a
- # source with an author.
- def have_author?
- authors.any? {|author| !author.to_s.empty?} or
- (source and source.have_author?)
- end
-
- private
- def atom_validate(ignore_unknown_element, tags, uri)
- unless have_author?
- raise MissingTagError.new("author", tag_name)
- end
- validate_duplicate_links(links)
- end
-
- def have_required_elements?
- super and have_author?
- end
-
- def maker_target(maker)
- maker.items.new_item
- end
-
- # Feed::Entry::Author
- Author = Feed::Entry::Author
- # Feed::Entry::Category
- Category = Feed::Entry::Category
- # Feed::Entry::Content
- Content = Feed::Entry::Content
- # Feed::Entry::Contributor
- Contributor = Feed::Entry::Contributor
- # Feed::Entry::Id
- Id = Feed::Entry::Id
- # Feed::Entry::Link
- Link = Feed::Entry::Link
- # Feed::Entry::Published
- Published = Feed::Entry::Published
- # Feed::Entry::Rights
- Rights = Feed::Entry::Rights
- # Feed::Entry::Source
- Source = Feed::Entry::Source
- # Feed::Entry::Summary
- Summary = Feed::Entry::Summary
- # Feed::Entry::Title
- Title = Feed::Entry::Title
- # Feed::Entry::Updated
- Updated = Feed::Entry::Updated
- end
- end
-
- Atom::CommonModel::ELEMENTS.each do |name|
- BaseListener.install_get_text_element(Atom::URI, name, "#{name}=")
- end
-
- module ListenerMixin
- private
- def initial_start_feed(tag_name, prefix, attrs, ns)
- check_ns(tag_name, prefix, ns, Atom::URI, false)
-
- @rss = Atom::Feed.new(@version, @encoding, @standalone)
- @rss.do_validate = @do_validate
- @rss.xml_stylesheets = @xml_stylesheets
- @rss.lang = attrs["xml:lang"]
- @rss.base = attrs["xml:base"]
- @last_element = @rss
- pr = Proc.new do |text, tags|
- @rss.validate_for_stream(tags) if @do_validate
- end
- @proc_stack.push(pr)
- end
-
- def initial_start_entry(tag_name, prefix, attrs, ns)
- check_ns(tag_name, prefix, ns, Atom::URI, false)
-
- @rss = Atom::Entry.new(@version, @encoding, @standalone)
- @rss.do_validate = @do_validate
- @rss.xml_stylesheets = @xml_stylesheets
- @rss.lang = attrs["xml:lang"]
- @rss.base = attrs["xml:base"]
- @last_element = @rss
- pr = Proc.new do |text, tags|
- @rss.validate_for_stream(tags) if @do_validate
- end
- @proc_stack.push(pr)
- end
- end
-end
diff --git a/lib/rss/content.rb b/lib/rss/content.rb
deleted file mode 100644
index 78c18d103c..0000000000
--- a/lib/rss/content.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss"
-
-module RSS
- # The prefix for the Content XML namespace.
- CONTENT_PREFIX = 'content'
- # The URI of the Content specification.
- CONTENT_URI = "http://purl.org/rss/1.0/modules/content/"
-
- module ContentModel
- extend BaseModel
-
- ELEMENTS = ["#{CONTENT_PREFIX}_encoded"]
-
- def self.append_features(klass)
- super
-
- klass.install_must_call_validator(CONTENT_PREFIX, CONTENT_URI)
- ELEMENTS.each do |full_name|
- name = full_name[(CONTENT_PREFIX.size + 1)..-1]
- klass.install_text_element(name, CONTENT_URI, "?", full_name)
- end
- end
- end
-
- prefix_size = CONTENT_PREFIX.size + 1
- ContentModel::ELEMENTS.each do |full_name|
- name = full_name[prefix_size..-1]
- BaseListener.install_get_text_element(CONTENT_URI, name, full_name)
- end
-end
-
-require 'rss/content/1.0'
-require 'rss/content/2.0'
diff --git a/lib/rss/content/1.0.rb b/lib/rss/content/1.0.rb
deleted file mode 100644
index 1367dfe092..0000000000
--- a/lib/rss/content/1.0.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: false
-require 'rss/1.0'
-
-module RSS
- RDF.install_ns(CONTENT_PREFIX, CONTENT_URI)
-
- class RDF
- class Item; include ContentModel; end
- end
-end
diff --git a/lib/rss/content/2.0.rb b/lib/rss/content/2.0.rb
deleted file mode 100644
index 3b468248ac..0000000000
--- a/lib/rss/content/2.0.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: false
-require "rss/2.0"
-
-module RSS
- Rss.install_ns(CONTENT_PREFIX, CONTENT_URI)
-
- class Rss
- class Channel
- class Item; include ContentModel; end
- end
- end
-end
diff --git a/lib/rss/converter.rb b/lib/rss/converter.rb
deleted file mode 100644
index d372e06725..0000000000
--- a/lib/rss/converter.rb
+++ /dev/null
@@ -1,171 +0,0 @@
-# frozen_string_literal: false
-require_relative "utils"
-
-module RSS
-
- class Converter
-
- include Utils
-
- def initialize(to_enc, from_enc=nil)
- if "".respond_to?(:encode)
- @to_encoding = to_enc
- return
- end
- normalized_to_enc = to_enc.downcase.gsub(/-/, '_')
- from_enc ||= 'utf-8'
- normalized_from_enc = from_enc.downcase.gsub(/-/, '_')
- if normalized_to_enc == normalized_from_enc
- def_same_enc()
- else
- def_diff_enc = "def_to_#{normalized_to_enc}_from_#{normalized_from_enc}"
- if respond_to?(def_diff_enc)
- __send__(def_diff_enc)
- else
- def_else_enc(to_enc, from_enc)
- end
- end
- end
-
- def convert(value)
- if value.is_a?(String) and value.respond_to?(:encode)
- value.encode(@to_encoding)
- else
- value
- end
- end
-
- def def_convert(depth=0)
- instance_eval(<<-EOC, *get_file_and_line_from_caller(depth))
- def convert(value)
- if value.kind_of?(String)
- #{yield('value')}
- else
- value
- end
- end
- EOC
- end
-
- def def_iconv_convert(to_enc, from_enc, depth=0)
- begin
- require "iconv"
- @iconv = Iconv.new(to_enc, from_enc)
- def_convert(depth+1) do |value|
- <<-EOC
- begin
- @iconv.iconv(#{value})
- rescue Iconv::Failure
- raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}")
- end
- EOC
- end
- rescue LoadError, ArgumentError, SystemCallError
- raise UnknownConversionMethodError.new(to_enc, from_enc)
- end
- end
-
- def def_else_enc(to_enc, from_enc)
- def_iconv_convert(to_enc, from_enc, 0)
- end
-
- def def_same_enc()
- def_convert do |value|
- value
- end
- end
-
- def def_uconv_convert_if_can(meth, to_enc, from_enc, nkf_arg)
- begin
- require "uconv"
- def_convert(1) do |value|
- <<-EOC
- begin
- Uconv.#{meth}(#{value})
- rescue Uconv::Error
- raise ConversionError.new(#{value}, "#{to_enc}", "#{from_enc}")
- end
- EOC
- end
- rescue LoadError
- require 'nkf'
- if NKF.const_defined?(:UTF8)
- def_convert(1) do |value|
- "NKF.nkf(#{nkf_arg.dump}, #{value})"
- end
- else
- def_iconv_convert(to_enc, from_enc, 1)
- end
- end
- end
-
- def def_to_euc_jp_from_utf_8
- def_uconv_convert_if_can('u8toeuc', 'EUC-JP', 'UTF-8', '-We')
- end
-
- def def_to_utf_8_from_euc_jp
- def_uconv_convert_if_can('euctou8', 'UTF-8', 'EUC-JP', '-Ew')
- end
-
- def def_to_shift_jis_from_utf_8
- def_uconv_convert_if_can('u8tosjis', 'Shift_JIS', 'UTF-8', '-Ws')
- end
-
- def def_to_utf_8_from_shift_jis
- def_uconv_convert_if_can('sjistou8', 'UTF-8', 'Shift_JIS', '-Sw')
- end
-
- def def_to_euc_jp_from_shift_jis
- require "nkf"
- def_convert do |value|
- "NKF.nkf('-Se', #{value})"
- end
- end
-
- def def_to_shift_jis_from_euc_jp
- require "nkf"
- def_convert do |value|
- "NKF.nkf('-Es', #{value})"
- end
- end
-
- def def_to_euc_jp_from_iso_2022_jp
- require "nkf"
- def_convert do |value|
- "NKF.nkf('-Je', #{value})"
- end
- end
-
- def def_to_iso_2022_jp_from_euc_jp
- require "nkf"
- def_convert do |value|
- "NKF.nkf('-Ej', #{value})"
- end
- end
-
- def def_to_utf_8_from_iso_8859_1
- def_convert do |value|
- "#{value}.unpack('C*').pack('U*')"
- end
- end
-
- def def_to_iso_8859_1_from_utf_8
- def_convert do |value|
- <<-EOC
- array_utf8 = #{value}.unpack('U*')
- array_enc = []
- array_utf8.each do |num|
- if num <= 0xFF
- array_enc << num
- else
- array_enc.concat "&\#\#{num};".unpack('C*')
- end
- end
- array_enc.pack('C*')
- EOC
- end
- end
-
- end
-
-end
diff --git a/lib/rss/dublincore.rb b/lib/rss/dublincore.rb
deleted file mode 100644
index 85b836d3bf..0000000000
--- a/lib/rss/dublincore.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss"
-
-module RSS
- # The prefix for the Dublin Core XML namespace.
- DC_PREFIX = 'dc'
- # The URI of the Dublin Core specification.
- DC_URI = "http://purl.org/dc/elements/1.1/"
-
- module BaseDublinCoreModel
- def append_features(klass)
- super
-
- return if klass.instance_of?(Module)
- DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
- plural = plural_name || "#{name}s"
- full_name = "#{DC_PREFIX}_#{name}"
- full_plural_name = "#{DC_PREFIX}_#{plural}"
- klass_name = "DublinCore#{Utils.to_class_name(name)}"
- klass.install_must_call_validator(DC_PREFIX, DC_URI)
- klass.install_have_children_element(name, DC_URI, "*",
- full_name, full_plural_name)
- klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0))
- remove_method :#{full_name}
- remove_method :#{full_name}=
- remove_method :set_#{full_name}
-
- def #{full_name}
- @#{full_name}.first and @#{full_name}.first.value
- end
-
- def #{full_name}=(new_value)
- @#{full_name}[0] = Utils.new_with_value_if_need(#{klass_name}, new_value)
- end
- alias set_#{full_name} #{full_name}=
- EOC
- end
- klass.module_eval(<<-EOC, *get_file_and_line_from_caller(0))
- if method_defined?(:date)
- alias date_without_#{DC_PREFIX}_date= date=
-
- def date=(value)
- self.date_without_#{DC_PREFIX}_date = value
- self.#{DC_PREFIX}_date = value
- end
- else
- alias date #{DC_PREFIX}_date
- alias date= #{DC_PREFIX}_date=
- end
-
- # For backward compatibility
- alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list
- EOC
- end
- end
-
- module DublinCoreModel
-
- extend BaseModel
- extend BaseDublinCoreModel
-
- TEXT_ELEMENTS = {
- "title" => nil,
- "description" => nil,
- "creator" => nil,
- "subject" => nil,
- "publisher" => nil,
- "contributor" => nil,
- "type" => nil,
- "format" => nil,
- "identifier" => nil,
- "source" => nil,
- "language" => nil,
- "relation" => nil,
- "coverage" => nil,
- "rights" => "rights_list"
- }
-
- DATE_ELEMENTS = {
- "date" => "w3cdtf",
- }
-
- ELEMENT_NAME_INFOS = DublinCoreModel::TEXT_ELEMENTS.to_a
- DublinCoreModel::DATE_ELEMENTS.each do |name, |
- ELEMENT_NAME_INFOS << [name, nil]
- end
-
- ELEMENTS = TEXT_ELEMENTS.keys + DATE_ELEMENTS.keys
-
- ELEMENTS.each do |name, plural_name|
- module_eval(<<-EOC, *get_file_and_line_from_caller(0))
- class DublinCore#{Utils.to_class_name(name)} < Element
- include RSS10
-
- content_setup
-
- class << self
- def required_prefix
- DC_PREFIX
- end
-
- def required_uri
- DC_URI
- end
- end
-
- @tag_name = #{name.dump}
-
- alias_method(:value, :content)
- alias_method(:value=, :content=)
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.content = args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(DC_PREFIX)
- end
-
- def maker_target(target)
- target.new_#{name}
- end
-
- def setup_maker_attributes(#{name})
- #{name}.content = content
- end
- end
- EOC
- end
-
- DATE_ELEMENTS.each do |name, type|
- tag_name = "#{DC_PREFIX}:#{name}"
- module_eval(<<-EOC, *get_file_and_line_from_caller(0))
- class DublinCore#{Utils.to_class_name(name)} < Element
- remove_method(:content=)
- remove_method(:value=)
-
- date_writer("content", #{type.dump}, #{tag_name.dump})
-
- alias_method(:value=, :content=)
- end
- EOC
- end
- end
-
- # For backward compatibility
- DublincoreModel = DublinCoreModel
-
- DublinCoreModel::ELEMENTS.each do |name|
- class_name = Utils.to_class_name(name)
- BaseListener.install_class_name(DC_URI, name, "DublinCore#{class_name}")
- end
-
- DublinCoreModel::ELEMENTS.collect! {|name| "#{DC_PREFIX}_#{name}"}
-end
-
-require 'rss/dublincore/1.0'
-require 'rss/dublincore/2.0'
-require_relative 'dublincore/atom'
diff --git a/lib/rss/dublincore/1.0.rb b/lib/rss/dublincore/1.0.rb
deleted file mode 100644
index 1d96fab9b9..0000000000
--- a/lib/rss/dublincore/1.0.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: false
-require "rss/1.0"
-
-module RSS
- RDF.install_ns(DC_PREFIX, DC_URI)
-
- class RDF
- class Channel; include DublinCoreModel; end
- class Image; include DublinCoreModel; end
- class Item; include DublinCoreModel; end
- class Textinput; include DublinCoreModel; end
- end
-end
diff --git a/lib/rss/dublincore/2.0.rb b/lib/rss/dublincore/2.0.rb
deleted file mode 100644
index e3011fef6a..0000000000
--- a/lib/rss/dublincore/2.0.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: false
-require "rss/2.0"
-
-module RSS
- Rss.install_ns(DC_PREFIX, DC_URI)
-
- class Rss
- class Channel
- include DublinCoreModel
- class Item; include DublinCoreModel; end
- end
- end
-end
diff --git a/lib/rss/dublincore/atom.rb b/lib/rss/dublincore/atom.rb
deleted file mode 100644
index 1cfcdec677..0000000000
--- a/lib/rss/dublincore/atom.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: false
-require_relative "../atom"
-
-module RSS
- module Atom
- Feed.install_ns(DC_PREFIX, DC_URI)
-
- class Feed
- include DublinCoreModel
- class Entry; include DublinCoreModel; end
- end
-
- class Entry
- include DublinCoreModel
- end
- end
-end
diff --git a/lib/rss/image.rb b/lib/rss/image.rb
deleted file mode 100644
index 837f7d18f4..0000000000
--- a/lib/rss/image.rb
+++ /dev/null
@@ -1,198 +0,0 @@
-# frozen_string_literal: false
-require 'rss/1.0'
-require_relative 'dublincore'
-
-module RSS
-
- # The prefix for the Image XML namespace.
- IMAGE_PREFIX = 'image'
- # The URI for the Image specification.
- IMAGE_URI = 'http://purl.org/rss/1.0/modules/image/'
-
- RDF.install_ns(IMAGE_PREFIX, IMAGE_URI)
-
- # This constant holds strings which contain the names of
- # image elements, with the appropriate prefix.
- IMAGE_ELEMENTS = []
-
- %w(item favicon).each do |name|
- class_name = Utils.to_class_name(name)
- BaseListener.install_class_name(IMAGE_URI, name, "Image#{class_name}")
- IMAGE_ELEMENTS << "#{IMAGE_PREFIX}_#{name}"
- end
-
- module ImageModelUtils
- def validate_one_tag_name(ignore_unknown_element, name, tags)
- if !ignore_unknown_element
- invalid = tags.find {|tag| tag != name}
- raise UnknownTagError.new(invalid, IMAGE_URI) if invalid
- end
- raise TooMuchTagError.new(name, tag_name) if tags.size > 1
- end
- end
-
- module ImageItemModel
- include ImageModelUtils
- extend BaseModel
-
- def self.append_features(klass)
- super
-
- klass.install_have_child_element("item", IMAGE_URI, "?",
- "#{IMAGE_PREFIX}_item")
- klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI)
- end
-
- class ImageItem < Element
- include RSS10
- include DublinCoreModel
-
- @tag_name = "item"
-
- class << self
- def required_prefix
- IMAGE_PREFIX
- end
-
- def required_uri
- IMAGE_URI
- end
- end
-
- install_must_call_validator(IMAGE_PREFIX, IMAGE_URI)
-
- [
- ["about", ::RSS::RDF::URI, true],
- ["resource", ::RSS::RDF::URI, false],
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, nil, nil,
- "#{::RSS::RDF::PREFIX}:#{name}")
- end
-
- %w(width height).each do |tag|
- full_name = "#{IMAGE_PREFIX}_#{tag}"
- disp_name = "#{IMAGE_PREFIX}:#{tag}"
- install_text_element(tag, IMAGE_URI, "?",
- full_name, :integer, disp_name)
- BaseListener.install_get_text_element(IMAGE_URI, tag, full_name)
- end
-
- alias width= image_width=
- alias width image_width
- alias height= image_height=
- alias height image_height
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.about = args[0]
- self.resource = args[1]
- end
- end
-
- def full_name
- tag_name_with_prefix(IMAGE_PREFIX)
- end
-
- private
- def maker_target(target)
- target.image_item
- end
-
- def setup_maker_attributes(item)
- item.about = self.about
- item.resource = self.resource
- end
- end
- end
-
- module ImageFaviconModel
- include ImageModelUtils
- extend BaseModel
-
- def self.append_features(klass)
- super
-
- unless klass.class == Module
- klass.install_have_child_element("favicon", IMAGE_URI, "?",
- "#{IMAGE_PREFIX}_favicon")
- klass.install_must_call_validator(IMAGE_PREFIX, IMAGE_URI)
- end
- end
-
- class ImageFavicon < Element
- include RSS10
- include DublinCoreModel
-
- @tag_name = "favicon"
-
- class << self
- def required_prefix
- IMAGE_PREFIX
- end
-
- def required_uri
- IMAGE_URI
- end
- end
-
- [
- ["about", ::RSS::RDF::URI, true, ::RSS::RDF::PREFIX],
- ["size", IMAGE_URI, true, IMAGE_PREFIX],
- ].each do |name, uri, required, prefix|
- install_get_attribute(name, uri, required, nil, nil,
- "#{prefix}:#{name}")
- end
-
- AVAILABLE_SIZES = %w(small medium large)
- alias_method :set_size, :size=
- private :set_size
- def size=(new_value)
- if @do_validate and !new_value.nil?
- new_value = new_value.strip
- unless AVAILABLE_SIZES.include?(new_value)
- attr_name = "#{IMAGE_PREFIX}:size"
- raise NotAvailableValueError.new(full_name, new_value, attr_name)
- end
- end
- set_size(new_value)
- end
-
- alias image_size= size=
- alias image_size size
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.about = args[0]
- self.size = args[1]
- end
- end
-
- def full_name
- tag_name_with_prefix(IMAGE_PREFIX)
- end
-
- private
- def maker_target(target)
- target.image_favicon
- end
-
- def setup_maker_attributes(favicon)
- favicon.about = self.about
- favicon.size = self.size
- end
- end
-
- end
-
- class RDF
- class Channel; include ImageFaviconModel; end
- class Item; include ImageItemModel; end
- end
-
-end
diff --git a/lib/rss/itunes.rb b/lib/rss/itunes.rb
deleted file mode 100644
index bc3e25448a..0000000000
--- a/lib/rss/itunes.rb
+++ /dev/null
@@ -1,425 +0,0 @@
-# frozen_string_literal: false
-require 'rss/2.0'
-
-module RSS
- # The prefix for the iTunes XML namespace.
- ITUNES_PREFIX = 'itunes'
- # The URI of the iTunes specification.
- ITUNES_URI = 'http://www.itunes.com/dtds/podcast-1.0.dtd'
-
- Rss.install_ns(ITUNES_PREFIX, ITUNES_URI)
-
- module ITunesModelUtils
- include Utils
-
- def def_class_accessor(klass, name, type, *args)
- normalized_name = name.gsub(/-/, "_")
- full_name = "#{ITUNES_PREFIX}_#{normalized_name}"
- klass_name = "ITunes#{Utils.to_class_name(normalized_name)}"
-
- case type
- when :element, :attribute
- klass::ELEMENTS << full_name
- def_element_class_accessor(klass, name, full_name, klass_name, *args)
- when :elements
- klass::ELEMENTS << full_name
- def_elements_class_accessor(klass, name, full_name, klass_name, *args)
- else
- klass.install_must_call_validator(ITUNES_PREFIX, ITUNES_URI)
- klass.install_text_element(normalized_name, ITUNES_URI, "?",
- full_name, type, name)
- end
- end
-
- def def_element_class_accessor(klass, name, full_name, klass_name,
- recommended_attribute_name=nil)
- klass.install_have_child_element(name, ITUNES_PREFIX, "?", full_name)
- end
-
- def def_elements_class_accessor(klass, name, full_name, klass_name,
- plural_name, recommended_attribute_name=nil)
- full_plural_name = "#{ITUNES_PREFIX}_#{plural_name}"
- klass.install_have_children_element(name, ITUNES_PREFIX, "*",
- full_name, full_plural_name)
- end
- end
-
- module ITunesBaseModel
- extend ITunesModelUtils
-
- ELEMENTS = []
-
- ELEMENT_INFOS = [["author"],
- ["block", :yes_other],
- ["explicit", :explicit_clean_other],
- ["keywords", :csv],
- ["subtitle"],
- ["summary"]]
- end
-
- module ITunesChannelModel
- extend BaseModel
- extend ITunesModelUtils
- include ITunesBaseModel
-
- ELEMENTS = []
-
- class << self
- def append_features(klass)
- super
-
- return if klass.instance_of?(Module)
- ELEMENT_INFOS.each do |name, type, *additional_infos|
- def_class_accessor(klass, name, type, *additional_infos)
- end
- end
- end
-
- ELEMENT_INFOS = [
- ["category", :elements, "categories", "text"],
- ["image", :attribute, "href"],
- ["owner", :element],
- ["new-feed-url"],
- ] + ITunesBaseModel::ELEMENT_INFOS
-
- class ITunesCategory < Element
- include RSS09
-
- @tag_name = "category"
-
- class << self
- def required_prefix
- ITUNES_PREFIX
- end
-
- def required_uri
- ITUNES_URI
- end
- end
-
- [
- ["text", "", true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required)
- end
-
- ITunesCategory = self
- install_have_children_element("category", ITUNES_URI, "*",
- "#{ITUNES_PREFIX}_category",
- "#{ITUNES_PREFIX}_categories")
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.text = args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(ITUNES_PREFIX)
- end
-
- private
- def maker_target(categories)
- if text or !itunes_categories.empty?
- categories.new_category
- else
- nil
- end
- end
-
- def setup_maker_attributes(category)
- category.text = text if text
- end
-
- def setup_maker_elements(category)
- super(category)
- itunes_categories.each do |sub_category|
- sub_category.setup_maker(category)
- end
- end
- end
-
- class ITunesImage < Element
- include RSS09
-
- @tag_name = "image"
-
- class << self
- def required_prefix
- ITUNES_PREFIX
- end
-
- def required_uri
- ITUNES_URI
- end
- end
-
- [
- ["href", "", true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required)
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.href = args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(ITUNES_PREFIX)
- end
-
- private
- def maker_target(target)
- if href
- target.itunes_image {|image| image}
- else
- nil
- end
- end
-
- def setup_maker_attributes(image)
- image.href = href
- end
- end
-
- class ITunesOwner < Element
- include RSS09
-
- @tag_name = "owner"
-
- class << self
- def required_prefix
- ITUNES_PREFIX
- end
-
- def required_uri
- ITUNES_URI
- end
- end
-
- install_must_call_validator(ITUNES_PREFIX, ITUNES_URI)
- [
- ["name"],
- ["email"],
- ].each do |name,|
- ITunesBaseModel::ELEMENT_INFOS << name
- install_text_element(name, ITUNES_URI, nil, "#{ITUNES_PREFIX}_#{name}")
- end
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.itunes_name = args[0]
- self.itunes_email = args[1]
- end
- end
-
- def full_name
- tag_name_with_prefix(ITUNES_PREFIX)
- end
-
- private
- def maker_target(target)
- target.itunes_owner
- end
-
- def setup_maker_element(owner)
- super(owner)
- owner.itunes_name = itunes_name
- owner.itunes_email = itunes_email
- end
- end
- end
-
- module ITunesItemModel
- extend BaseModel
- extend ITunesModelUtils
- include ITunesBaseModel
-
- class << self
- def append_features(klass)
- super
-
- return if klass.instance_of?(Module)
- ELEMENT_INFOS.each do |name, type|
- def_class_accessor(klass, name, type)
- end
- end
- end
-
- ELEMENT_INFOS = ITunesBaseModel::ELEMENT_INFOS +
- [["duration", :element, "content"]]
-
- class ITunesDuration < Element
- include RSS09
-
- @tag_name = "duration"
-
- class << self
- def required_prefix
- ITUNES_PREFIX
- end
-
- def required_uri
- ITUNES_URI
- end
-
- def parse(duration, do_validate=true)
- if do_validate and /\A(?:
- \d?\d:[0-5]\d:[0-5]\d|
- [0-5]?\d:[0-5]\d|
- \d+
- )\z/x !~ duration
- raise ArgumentError,
- "must be one of HH:MM:SS, H:MM:SS, MM:SS, M:SS, S+: " +
- duration.inspect
- end
-
- if duration.include?(':')
- components = duration.split(':')
- components[3..-1] = nil if components.size > 3
-
- components.unshift("00") until components.size == 3
- components.collect do |component|
- component.to_i
- end
- else
- seconds_to_components(duration.to_i)
- end
- end
-
- def construct(hours, minutes, seconds)
- components = [minutes, seconds]
- if components.include?(nil)
- nil
- else
- components.unshift(hours) if hours and hours > 0
- components.collect do |component|
- "%02d" % component
- end.join(':')
- end
- end
-
- private
- def seconds_to_components(total_seconds)
- hours = total_seconds / (60 * 60)
- minutes = (total_seconds / 60) % 60
- seconds = total_seconds % 60
- [hours, minutes, seconds]
- end
- end
-
- content_setup
- alias_method(:value, :content)
- remove_method(:content=)
-
- attr_reader :hour, :minute, :second
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- args = args[0] if args.size == 1 and args[0].is_a?(Array)
- if args.size == 1
- self.content = args[0]
- elsif args.size > 3
- raise ArgumentError,
- "must be (do_validate, params), (content), " +
- "(minute, second), ([minute, second]), " +
- "(hour, minute, second) or ([hour, minute, second]): " +
- args.inspect
- else
- @second, @minute, @hour = args.reverse
- update_content
- end
- end
- end
-
- def content=(value)
- if value.nil?
- @content = nil
- elsif value.is_a?(self.class)
- self.content = value.content
- else
- begin
- @hour, @minute, @second = self.class.parse(value, @do_validate)
- rescue ArgumentError
- raise NotAvailableValueError.new(tag_name, value)
- end
- @content = value
- end
- end
- alias_method(:value=, :content=)
-
- def hour=(hour)
- @hour = @do_validate ? Integer(hour) : hour.to_i
- update_content
- hour
- end
-
- def minute=(minute)
- @minute = @do_validate ? Integer(minute) : minute.to_i
- update_content
- minute
- end
-
- def second=(second)
- @second = @do_validate ? Integer(second) : second.to_i
- update_content
- second
- end
-
- def full_name
- tag_name_with_prefix(ITUNES_PREFIX)
- end
-
- private
- def update_content
- @content = self.class.construct(hour, minute, second)
- end
-
- def maker_target(target)
- if @content
- target.itunes_duration {|duration| duration}
- else
- nil
- end
- end
-
- def setup_maker_element(duration)
- super(duration)
- duration.content = @content
- end
- end
- end
-
- class Rss
- class Channel
- include ITunesChannelModel
- class Item; include ITunesItemModel; end
- end
- end
-
- element_infos =
- ITunesChannelModel::ELEMENT_INFOS + ITunesItemModel::ELEMENT_INFOS
- element_infos.each do |name, type|
- case type
- when :element, :elements, :attribute
- class_name = Utils.to_class_name(name)
- BaseListener.install_class_name(ITUNES_URI, name, "ITunes#{class_name}")
- else
- accessor_base = "#{ITUNES_PREFIX}_#{name.gsub(/-/, '_')}"
- BaseListener.install_get_text_element(ITUNES_URI, name, accessor_base)
- end
- end
-end
diff --git a/lib/rss/maker.rb b/lib/rss/maker.rb
deleted file mode 100644
index e32de81806..0000000000
--- a/lib/rss/maker.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss"
-
-module RSS
- ##
- #
- # Provides a set of builders for various RSS objects
- #
- # * Feeds
- # * RSS 0.91
- # * RSS 1.0
- # * RSS 2.0
- # * Atom 1.0
- #
- # * Elements
- # * Atom::Entry
-
- module Maker
-
- # Collection of supported makers
- MAKERS = {}
-
- class << self
- # Builder for an RSS object
- # Creates an object of the type passed in +args+
- #
- # Executes the +block+ to populate elements of the created RSS object
- def make(version, &block)
- self[version].make(&block)
- end
-
- # Returns the maker for the +version+
- def [](version)
- maker_info = maker(version)
- raise UnsupportedMakerVersionError.new(version) if maker_info.nil?
- maker_info[:maker]
- end
-
- # Adds a maker to the set of supported makers
- def add_maker(version, normalized_version, maker)
- MAKERS[version] = {:maker => maker, :version => normalized_version}
- end
-
- # Returns collection of supported maker versions
- def versions
- MAKERS.keys.uniq.sort
- end
-
- # Returns collection of supported makers
- def makers
- MAKERS.values.collect { |info| info[:maker] }.uniq
- end
-
- # Returns true if the version is supported
- def supported?(version)
- versions.include?(version)
- end
-
- private
- # Can I remove this method?
- def maker(version)
- MAKERS[version]
- end
- end
- end
-end
-
-require_relative "maker/1.0"
-require_relative "maker/2.0"
-require_relative "maker/feed"
-require_relative "maker/entry"
-require_relative "maker/content"
-require_relative "maker/dublincore"
-require_relative "maker/slash"
-require_relative "maker/syndication"
-require_relative "maker/taxonomy"
-require_relative "maker/trackback"
-require_relative "maker/image"
-require_relative "maker/itunes"
diff --git a/lib/rss/maker/0.9.rb b/lib/rss/maker/0.9.rb
deleted file mode 100644
index eb35fc14e1..0000000000
--- a/lib/rss/maker/0.9.rb
+++ /dev/null
@@ -1,509 +0,0 @@
-# frozen_string_literal: false
-require_relative "../0.9"
-
-require_relative "base"
-
-module RSS
- module Maker
-
- class RSS09 < RSSBase
-
- def initialize(feed_version)
- super
- @feed_type = "rss"
- end
-
- private
- def make_feed
- Rss.new(@feed_version, @version, @encoding, @standalone)
- end
-
- def setup_elements(rss)
- setup_channel(rss)
- end
-
- class Channel < ChannelBase
- def to_feed(rss)
- channel = Rss::Channel.new
- setup_values(channel)
- _not_set_required_variables = not_set_required_variables
- if _not_set_required_variables.empty?
- rss.channel = channel
- set_parent(channel, rss)
- setup_items(rss)
- setup_image(rss)
- setup_textinput(rss)
- setup_other_elements(rss, channel)
- rss
- else
- raise NotSetError.new("maker.channel", _not_set_required_variables)
- end
- end
-
- private
- def setup_items(rss)
- @maker.items.to_feed(rss)
- end
-
- def setup_image(rss)
- @maker.image.to_feed(rss)
- end
-
- def setup_textinput(rss)
- @maker.textinput.to_feed(rss)
- end
-
- def variables
- super + ["pubDate"]
- end
-
- def required_variable_names
- %w(link language)
- end
-
- def not_set_required_variables
- vars = super
- vars << "description" unless description {|d| d.have_required_values?}
- vars << "title" unless title {|t| t.have_required_values?}
- vars
- end
-
- class SkipDays < SkipDaysBase
- def to_feed(rss, channel)
- unless @days.empty?
- skipDays = Rss::Channel::SkipDays.new
- channel.skipDays = skipDays
- set_parent(skipDays, channel)
- @days.each do |day|
- day.to_feed(rss, skipDays.days)
- end
- end
- end
-
- class Day < DayBase
- def to_feed(rss, days)
- day = Rss::Channel::SkipDays::Day.new
- set = setup_values(day)
- if set
- days << day
- set_parent(day, days)
- setup_other_elements(rss, day)
- end
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
- end
-
- class SkipHours < SkipHoursBase
- def to_feed(rss, channel)
- unless @hours.empty?
- skipHours = Rss::Channel::SkipHours.new
- channel.skipHours = skipHours
- set_parent(skipHours, channel)
- @hours.each do |hour|
- hour.to_feed(rss, skipHours.hours)
- end
- end
- end
-
- class Hour < HourBase
- def to_feed(rss, hours)
- hour = Rss::Channel::SkipHours::Hour.new
- set = setup_values(hour)
- if set
- hours << hour
- set_parent(hour, hours)
- setup_other_elements(rss, hour)
- end
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
- end
-
- class Cloud < CloudBase
- def to_feed(*args)
- end
- end
-
- class Categories < CategoriesBase
- def to_feed(*args)
- end
-
- class Category < CategoryBase
- end
- end
-
- class Links < LinksBase
- def to_feed(rss, channel)
- return if @links.empty?
- @links.first.to_feed(rss, channel)
- end
-
- class Link < LinkBase
- def to_feed(rss, channel)
- if have_required_values?
- channel.link = href
- else
- raise NotSetError.new("maker.channel.link",
- not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(href)
- end
- end
- end
-
- class Authors < AuthorsBase
- def to_feed(rss, channel)
- end
-
- class Author < AuthorBase
- def to_feed(rss, channel)
- end
- end
- end
-
- class Contributors < ContributorsBase
- def to_feed(rss, channel)
- end
-
- class Contributor < ContributorBase
- end
- end
-
- class Generator < GeneratorBase
- def to_feed(rss, channel)
- end
- end
-
- class Copyright < CopyrightBase
- def to_feed(rss, channel)
- channel.copyright = content if have_required_values?
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
-
- class Description < DescriptionBase
- def to_feed(rss, channel)
- channel.description = content if have_required_values?
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
-
- class Title < TitleBase
- def to_feed(rss, channel)
- channel.title = content if have_required_values?
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
- end
-
- class Image < ImageBase
- def to_feed(rss)
- image = Rss::Channel::Image.new
- set = setup_values(image)
- if set
- image.link = link
- rss.channel.image = image
- set_parent(image, rss.channel)
- setup_other_elements(rss, image)
- elsif required_element?
- raise NotSetError.new("maker.image", not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(url title link)
- end
-
- def required_element?
- true
- end
- end
-
- class Items < ItemsBase
- def to_feed(rss)
- if rss.channel
- normalize.each do |item|
- item.to_feed(rss)
- end
- setup_other_elements(rss, rss.items)
- end
- end
-
- class Item < ItemBase
- def to_feed(rss)
- item = Rss::Channel::Item.new
- setup_values(item)
- _not_set_required_variables = not_set_required_variables
- if _not_set_required_variables.empty?
- rss.items << item
- set_parent(item, rss.channel)
- setup_other_elements(rss, item)
- elsif variable_is_set?
- raise NotSetError.new("maker.items", _not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- []
- end
-
- def not_set_required_variables
- vars = super
- if @maker.feed_version == "0.91"
- vars << "title" unless title {|t| t.have_required_values?}
- vars << "link" unless link
- end
- vars
- end
-
- class Guid < GuidBase
- def to_feed(*args)
- end
- end
-
- class Enclosure < EnclosureBase
- def to_feed(*args)
- end
- end
-
- class Source < SourceBase
- def to_feed(*args)
- end
-
- class Authors < AuthorsBase
- def to_feed(*args)
- end
-
- class Author < AuthorBase
- end
- end
-
- class Categories < CategoriesBase
- def to_feed(*args)
- end
-
- class Category < CategoryBase
- end
- end
-
- class Contributors < ContributorsBase
- def to_feed(*args)
- end
-
- class Contributor < ContributorBase
- end
- end
-
- class Generator < GeneratorBase
- def to_feed(*args)
- end
- end
-
- class Icon < IconBase
- def to_feed(*args)
- end
- end
-
- class Links < LinksBase
- def to_feed(*args)
- end
-
- class Link < LinkBase
- end
- end
-
- class Logo < LogoBase
- def to_feed(*args)
- end
- end
-
- class Rights < RightsBase
- def to_feed(*args)
- end
- end
-
- class Subtitle < SubtitleBase
- def to_feed(*args)
- end
- end
-
- class Title < TitleBase
- def to_feed(*args)
- end
- end
- end
-
- class Categories < CategoriesBase
- def to_feed(*args)
- end
-
- class Category < CategoryBase
- end
- end
-
- class Authors < AuthorsBase
- def to_feed(*args)
- end
-
- class Author < AuthorBase
- end
- end
-
- class Links < LinksBase
- def to_feed(rss, item)
- return if @links.empty?
- @links.first.to_feed(rss, item)
- end
-
- class Link < LinkBase
- def to_feed(rss, item)
- if have_required_values?
- item.link = href
- else
- raise NotSetError.new("maker.link",
- not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(href)
- end
- end
- end
-
- class Contributors < ContributorsBase
- def to_feed(rss, item)
- end
-
- class Contributor < ContributorBase
- end
- end
-
- class Rights < RightsBase
- def to_feed(rss, item)
- end
- end
-
- class Description < DescriptionBase
- def to_feed(rss, item)
- item.description = content if have_required_values?
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
-
- class Content < ContentBase
- def to_feed(rss, item)
- end
- end
-
- class Title < TitleBase
- def to_feed(rss, item)
- item.title = content if have_required_values?
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
- end
- end
-
- class Textinput < TextinputBase
- def to_feed(rss)
- textInput = Rss::Channel::TextInput.new
- set = setup_values(textInput)
- if set
- rss.channel.textInput = textInput
- set_parent(textInput, rss.channel)
- setup_other_elements(rss, textInput)
- end
- end
-
- private
- def required_variable_names
- %w(title description name link)
- end
- end
- end
-
- class RSS091 < RSS09
- def initialize(feed_version="0.91")
- super
- end
-
- class Channel < RSS09::Channel
- end
-
- class Items < RSS09::Items
- class Item < RSS09::Items::Item
- end
- end
-
- class Image < RSS09::Image
- end
-
- class Textinput < RSS09::Textinput
- end
- end
-
- class RSS092 < RSS09
- def initialize(feed_version="0.92")
- super
- end
-
- class Channel < RSS09::Channel
- end
-
- class Items < RSS09::Items
- class Item < RSS09::Items::Item
- end
- end
-
- class Image < RSS09::Image
- end
-
- class Textinput < RSS09::Textinput
- end
- end
-
- add_maker("0.9", "0.92", RSS092)
- add_maker("0.91", "0.91", RSS091)
- add_maker("0.92", "0.92", RSS092)
- add_maker("rss0.9", "0.92", RSS092)
- add_maker("rss0.91", "0.91", RSS091)
- add_maker("rss0.92", "0.92", RSS092)
- end
-end
diff --git a/lib/rss/maker/1.0.rb b/lib/rss/maker/1.0.rb
deleted file mode 100644
index 3934f9536c..0000000000
--- a/lib/rss/maker/1.0.rb
+++ /dev/null
@@ -1,436 +0,0 @@
-# frozen_string_literal: false
-require_relative "../1.0"
-
-require_relative "base"
-
-module RSS
- module Maker
-
- class RSS10 < RSSBase
-
- def initialize(feed_version="1.0")
- super
- @feed_type = "rss"
- end
-
- private
- def make_feed
- RDF.new(@version, @encoding, @standalone)
- end
-
- def setup_elements(rss)
- setup_channel(rss)
- setup_image(rss)
- setup_items(rss)
- setup_textinput(rss)
- end
-
- class Channel < ChannelBase
- include SetupDefaultLanguage
-
- def to_feed(rss)
- set_default_values do
- _not_set_required_variables = not_set_required_variables
- if _not_set_required_variables.empty?
- channel = RDF::Channel.new(@about)
- setup_values(channel)
- channel.dc_dates.clear
- rss.channel = channel
- set_parent(channel, rss)
- setup_items(rss)
- setup_image(rss)
- setup_textinput(rss)
- setup_other_elements(rss, channel)
- else
- raise NotSetError.new("maker.channel", _not_set_required_variables)
- end
- end
- end
-
- private
- def setup_items(rss)
- items = RDF::Channel::Items.new
- seq = items.Seq
- set_parent(items, seq)
- target_items = @maker.items.normalize
- raise NotSetError.new("maker", ["items"]) if target_items.empty?
- target_items.each do |item|
- li = RDF::Channel::Items::Seq::Li.new(item.link)
- seq.lis << li
- set_parent(li, seq)
- end
- rss.channel.items = items
- set_parent(rss.channel, items)
- end
-
- def setup_image(rss)
- if @maker.image.have_required_values?
- image = RDF::Channel::Image.new(@maker.image.url)
- rss.channel.image = image
- set_parent(image, rss.channel)
- end
- end
-
- def setup_textinput(rss)
- if @maker.textinput.have_required_values?
- textinput = RDF::Channel::Textinput.new(@maker.textinput.link)
- rss.channel.textinput = textinput
- set_parent(textinput, rss.channel)
- end
- end
-
- def required_variable_names
- %w(about link)
- end
-
- def not_set_required_variables
- vars = super
- vars << "description" unless description {|d| d.have_required_values?}
- vars << "title" unless title {|t| t.have_required_values?}
- vars
- end
-
- class SkipDays < SkipDaysBase
- def to_feed(*args)
- end
-
- class Day < DayBase
- end
- end
-
- class SkipHours < SkipHoursBase
- def to_feed(*args)
- end
-
- class Hour < HourBase
- end
- end
-
- class Cloud < CloudBase
- def to_feed(*args)
- end
- end
-
- class Categories < CategoriesBase
- def to_feed(*args)
- end
-
- class Category < CategoryBase
- end
- end
-
- class Links < LinksBase
- def to_feed(rss, channel)
- return if @links.empty?
- @links.first.to_feed(rss, channel)
- end
-
- class Link < LinkBase
- def to_feed(rss, channel)
- if have_required_values?
- channel.link = href
- else
- raise NotSetError.new("maker.channel.link",
- not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(href)
- end
- end
- end
-
- class Authors < AuthorsBase
- def to_feed(rss, channel)
- end
-
- class Author < AuthorBase
- def to_feed(rss, channel)
- end
- end
- end
-
- class Contributors < ContributorsBase
- def to_feed(rss, channel)
- end
-
- class Contributor < ContributorBase
- end
- end
-
- class Generator < GeneratorBase
- def to_feed(rss, channel)
- end
- end
-
- class Copyright < CopyrightBase
- def to_feed(rss, channel)
- end
- end
-
- class Description < DescriptionBase
- def to_feed(rss, channel)
- channel.description = content if have_required_values?
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
-
- class Title < TitleBase
- def to_feed(rss, channel)
- channel.title = content if have_required_values?
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
- end
-
- class Image < ImageBase
- def to_feed(rss)
- if @url
- image = RDF::Image.new(@url)
- set = setup_values(image)
- if set
- rss.image = image
- set_parent(image, rss)
- setup_other_elements(rss, image)
- end
- end
- end
-
- def have_required_values?
- super and @maker.channel.have_required_values?
- end
-
- private
- def variables
- super + ["link"]
- end
-
- def required_variable_names
- %w(url title link)
- end
- end
-
- class Items < ItemsBase
- def to_feed(rss)
- if rss.channel
- normalize.each do |item|
- item.to_feed(rss)
- end
- setup_other_elements(rss, rss.items)
- end
- end
-
- class Item < ItemBase
- def to_feed(rss)
- set_default_values do
- item = RDF::Item.new(link)
- set = setup_values(item)
- if set
- item.dc_dates.clear
- rss.items << item
- set_parent(item, rss)
- setup_other_elements(rss, item)
- elsif !have_required_values?
- raise NotSetError.new("maker.item", not_set_required_variables)
- end
- end
- end
-
- private
- def required_variable_names
- %w(link)
- end
-
- def variables
- super + %w(link)
- end
-
- def not_set_required_variables
- set_default_values do
- vars = super
- vars << "title" unless title {|t| t.have_required_values?}
- vars
- end
- end
-
- class Guid < GuidBase
- def to_feed(*args)
- end
- end
-
- class Enclosure < EnclosureBase
- def to_feed(*args)
- end
- end
-
- class Source < SourceBase
- def to_feed(*args)
- end
-
- class Authors < AuthorsBase
- def to_feed(*args)
- end
-
- class Author < AuthorBase
- end
- end
-
- class Categories < CategoriesBase
- def to_feed(*args)
- end
-
- class Category < CategoryBase
- end
- end
-
- class Contributors < ContributorsBase
- def to_feed(*args)
- end
-
- class Contributor < ContributorBase
- end
- end
-
- class Generator < GeneratorBase
- def to_feed(*args)
- end
- end
-
- class Icon < IconBase
- def to_feed(*args)
- end
- end
-
- class Links < LinksBase
- def to_feed(*args)
- end
-
- class Link < LinkBase
- end
- end
-
- class Logo < LogoBase
- def to_feed(*args)
- end
- end
-
- class Rights < RightsBase
- def to_feed(*args)
- end
- end
-
- class Subtitle < SubtitleBase
- def to_feed(*args)
- end
- end
-
- class Title < TitleBase
- def to_feed(*args)
- end
- end
- end
-
- class Categories < CategoriesBase
- def to_feed(*args)
- end
-
- class Category < CategoryBase
- end
- end
-
- class Authors < AuthorsBase
- def to_feed(*args)
- end
-
- class Author < AuthorBase
- end
- end
-
- class Links < LinksBase
- def to_feed(*args)
- end
-
- class Link < LinkBase
- end
- end
-
- class Contributors < ContributorsBase
- def to_feed(rss, item)
- end
-
- class Contributor < ContributorBase
- end
- end
-
- class Rights < RightsBase
- def to_feed(rss, item)
- end
- end
-
- class Description < DescriptionBase
- def to_feed(rss, item)
- item.description = content if have_required_values?
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
-
- class Content < ContentBase
- def to_feed(rss, item)
- end
- end
-
- class Title < TitleBase
- def to_feed(rss, item)
- item.title = content if have_required_values?
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
- end
- end
-
- class Textinput < TextinputBase
- def to_feed(rss)
- if @link
- textinput = RDF::Textinput.new(@link)
- set = setup_values(textinput)
- if set
- rss.textinput = textinput
- set_parent(textinput, rss)
- setup_other_elements(rss, textinput)
- end
- end
- end
-
- def have_required_values?
- super and @maker.channel.have_required_values?
- end
-
- private
- def required_variable_names
- %w(title description name link)
- end
- end
- end
-
- add_maker("1.0", "1.0", RSS10)
- add_maker("rss1.0", "1.0", RSS10)
- end
-end
diff --git a/lib/rss/maker/2.0.rb b/lib/rss/maker/2.0.rb
deleted file mode 100644
index 43d00226b7..0000000000
--- a/lib/rss/maker/2.0.rb
+++ /dev/null
@@ -1,224 +0,0 @@
-# frozen_string_literal: false
-require_relative "../2.0"
-
-require_relative "0.9"
-
-module RSS
- module Maker
-
- class RSS20 < RSS09
-
- def initialize(feed_version="2.0")
- super
- end
-
- class Channel < RSS09::Channel
-
- private
- def required_variable_names
- %w(link)
- end
-
- class SkipDays < RSS09::Channel::SkipDays
- class Day < RSS09::Channel::SkipDays::Day
- end
- end
-
- class SkipHours < RSS09::Channel::SkipHours
- class Hour < RSS09::Channel::SkipHours::Hour
- end
- end
-
- class Cloud < RSS09::Channel::Cloud
- def to_feed(rss, channel)
- cloud = Rss::Channel::Cloud.new
- set = setup_values(cloud)
- if set
- channel.cloud = cloud
- set_parent(cloud, channel)
- setup_other_elements(rss, cloud)
- end
- end
-
- private
- def required_variable_names
- %w(domain port path registerProcedure protocol)
- end
- end
-
- class Categories < RSS09::Channel::Categories
- def to_feed(rss, channel)
- @categories.each do |category|
- category.to_feed(rss, channel)
- end
- end
-
- class Category < RSS09::Channel::Categories::Category
- def to_feed(rss, channel)
- category = Rss::Channel::Category.new
- set = setup_values(category)
- if set
- channel.categories << category
- set_parent(category, channel)
- setup_other_elements(rss, category)
- end
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
- end
-
- class Generator < GeneratorBase
- def to_feed(rss, channel)
- channel.generator = content
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
- end
-
- class Image < RSS09::Image
- private
- def required_element?
- false
- end
- end
-
- class Items < RSS09::Items
- class Item < RSS09::Items::Item
- private
- def required_variable_names
- []
- end
-
- def not_set_required_variables
- vars = super
- if !title {|t| t.have_required_values?} and
- !description {|d| d.have_required_values?}
- vars << "title or description"
- end
- vars
- end
-
- def variables
- super + ["pubDate"]
- end
-
- class Guid < RSS09::Items::Item::Guid
- def to_feed(rss, item)
- guid = Rss::Channel::Item::Guid.new
- set = setup_values(guid)
- if set
- item.guid = guid
- set_parent(guid, item)
- setup_other_elements(rss, guid)
- end
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
-
- class Enclosure < RSS09::Items::Item::Enclosure
- def to_feed(rss, item)
- enclosure = Rss::Channel::Item::Enclosure.new
- set = setup_values(enclosure)
- if set
- item.enclosure = enclosure
- set_parent(enclosure, item)
- setup_other_elements(rss, enclosure)
- end
- end
-
- private
- def required_variable_names
- %w(url length type)
- end
- end
-
- class Source < RSS09::Items::Item::Source
- def to_feed(rss, item)
- source = Rss::Channel::Item::Source.new
- set = setup_values(source)
- if set
- item.source = source
- set_parent(source, item)
- setup_other_elements(rss, source)
- end
- end
-
- private
- def required_variable_names
- %w(url content)
- end
-
- class Links < RSS09::Items::Item::Source::Links
- def to_feed(rss, source)
- return if @links.empty?
- @links.first.to_feed(rss, source)
- end
-
- class Link < RSS09::Items::Item::Source::Links::Link
- def to_feed(rss, source)
- source.url = href
- end
- end
- end
- end
-
- class Categories < RSS09::Items::Item::Categories
- def to_feed(rss, item)
- @categories.each do |category|
- category.to_feed(rss, item)
- end
- end
-
- class Category < RSS09::Items::Item::Categories::Category
- def to_feed(rss, item)
- category = Rss::Channel::Item::Category.new
- set = setup_values(category)
- if set
- item.categories << category
- set_parent(category, item)
- setup_other_elements(rss)
- end
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
- end
-
- class Authors < RSS09::Items::Item::Authors
- def to_feed(rss, item)
- return if @authors.empty?
- @authors.first.to_feed(rss, item)
- end
-
- class Author < RSS09::Items::Item::Authors::Author
- def to_feed(rss, item)
- item.author = name
- end
- end
- end
- end
- end
-
- class Textinput < RSS09::Textinput
- end
- end
-
- add_maker("2.0", "2.0", RSS20)
- add_maker("rss2.0", "2.0", RSS20)
- end
-end
diff --git a/lib/rss/maker/atom.rb b/lib/rss/maker/atom.rb
deleted file mode 100644
index cdd1d8753e..0000000000
--- a/lib/rss/maker/atom.rb
+++ /dev/null
@@ -1,173 +0,0 @@
-# frozen_string_literal: false
-require_relative "../atom"
-
-require_relative "base"
-
-module RSS
- module Maker
- module AtomPersons
- module_function
- def def_atom_persons(klass, name, maker_name, plural=nil)
- plural ||= "#{name}s"
- klass_name = Utils.to_class_name(name)
- plural_klass_name = Utils.to_class_name(plural)
-
- klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class #{plural_klass_name} < #{plural_klass_name}Base
- class #{klass_name} < #{klass_name}Base
- def to_feed(feed, current)
- #{name} = feed.class::#{klass_name}.new
- set = setup_values(#{name})
- unless set
- raise NotSetError.new(#{maker_name.dump},
- not_set_required_variables)
- end
- current.#{plural} << #{name}
- set_parent(#{name}, current)
- setup_other_elements(#{name})
- end
-
- private
- def required_variable_names
- %w(name)
- end
- end
- end
-EOC
- end
- end
-
- module AtomTextConstruct
- class << self
- def def_atom_text_construct(klass, name, maker_name, klass_name=nil,
- atom_klass_name=nil)
- klass_name ||= Utils.to_class_name(name)
- atom_klass_name ||= Utils.to_class_name(name)
-
- klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class #{klass_name} < #{klass_name}Base
- include #{self.name}
- def to_feed(feed, current)
- #{name} = current.class::#{atom_klass_name}.new
- if setup_values(#{name})
- current.#{name} = #{name}
- set_parent(#{name}, current)
- setup_other_elements(feed)
- elsif variable_is_set?
- raise NotSetError.new(#{maker_name.dump},
- not_set_required_variables)
- end
- end
- end
- EOC
- end
- end
-
- private
- def required_variable_names
- if type == "xhtml"
- %w(xml_content)
- else
- %w(content)
- end
- end
-
- def variables
- if type == "xhtml"
- super + %w(xhtml)
- else
- super
- end
- end
- end
-
- module AtomCategory
- def to_feed(feed, current)
- category = feed.class::Category.new
- set = setup_values(category)
- if set
- current.categories << category
- set_parent(category, current)
- setup_other_elements(feed)
- else
- raise NotSetError.new(self.class.not_set_name,
- not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(term)
- end
-
- def variables
- super + ["term", "scheme"]
- end
- end
-
- module AtomLink
- def to_feed(feed, current)
- link = feed.class::Link.new
- set = setup_values(link)
- if set
- current.links << link
- set_parent(link, current)
- setup_other_elements(feed)
- else
- raise NotSetError.new(self.class.not_set_name,
- not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(href)
- end
- end
-
- module AtomGenerator
- def to_feed(feed, current)
- generator = current.class::Generator.new
- if setup_values(generator)
- current.generator = generator
- set_parent(generator, current)
- setup_other_elements(feed)
- elsif variable_is_set?
- raise NotSetError.new(self.class.not_set_name,
- not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(content)
- end
- end
-
- module AtomLogo
- def to_feed(feed, current)
- logo = current.class::Logo.new
- class << logo
- alias_method(:uri=, :content=)
- end
- set = setup_values(logo)
- class << logo
- remove_method(:uri=)
- end
- if set
- current.logo = logo
- set_parent(logo, current)
- setup_other_elements(feed)
- elsif variable_is_set?
- raise NotSetError.new(self.class.not_set_name,
- not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(uri)
- end
- end
- end
-end
diff --git a/lib/rss/maker/base.rb b/lib/rss/maker/base.rb
deleted file mode 100644
index 17537b7006..0000000000
--- a/lib/rss/maker/base.rb
+++ /dev/null
@@ -1,945 +0,0 @@
-# frozen_string_literal: false
-require 'forwardable'
-
-require_relative '../rss'
-
-module RSS
- module Maker
- class Base
- extend Utils::InheritedReader
-
- OTHER_ELEMENTS = []
- NEED_INITIALIZE_VARIABLES = []
-
- class << self
- def other_elements
- inherited_array_reader("OTHER_ELEMENTS")
- end
- def need_initialize_variables
- inherited_array_reader("NEED_INITIALIZE_VARIABLES")
- end
-
- def inherited_base
- ::RSS::Maker::Base
- end
-
- def inherited(subclass)
- subclass.const_set(:OTHER_ELEMENTS, [])
- subclass.const_set(:NEED_INITIALIZE_VARIABLES, [])
- end
-
- def add_other_element(variable_name)
- self::OTHER_ELEMENTS << variable_name
- end
-
- def add_need_initialize_variable(variable_name, init_value=nil,
- &init_block)
- init_value ||= init_block
- self::NEED_INITIALIZE_VARIABLES << [variable_name, init_value]
- end
-
- def def_array_element(name, plural=nil, klass_name=nil)
- include Enumerable
- extend Forwardable
-
- plural ||= "#{name}s"
- klass_name ||= Utils.to_class_name(name)
- def_delegators("@#{plural}", :<<, :[], :[]=, :first, :last)
- def_delegators("@#{plural}", :push, :pop, :shift, :unshift)
- def_delegators("@#{plural}", :each, :size, :empty?, :clear)
-
- add_need_initialize_variable(plural) {[]}
-
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def new_#{name}
- #{name} = self.class::#{klass_name}.new(@maker)
- @#{plural} << #{name}
- if block_given?
- yield #{name}
- else
- #{name}
- end
- end
- alias new_child new_#{name}
-
- def to_feed(*args)
- @#{plural}.each do |#{name}|
- #{name}.to_feed(*args)
- end
- end
-
- def replace(elements)
- @#{plural}.replace(elements.to_a)
- end
- EOC
- end
-
- def def_classed_element_without_accessor(name, class_name=nil)
- class_name ||= Utils.to_class_name(name)
- add_other_element(name)
- add_need_initialize_variable(name) do |object|
- object.send("make_#{name}")
- end
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- private
- def setup_#{name}(feed, current)
- @#{name}.to_feed(feed, current)
- end
-
- def make_#{name}
- self.class::#{class_name}.new(@maker)
- end
- EOC
- end
-
- def def_classed_element(name, class_name=nil, attribute_name=nil)
- def_classed_element_without_accessor(name, class_name)
- if attribute_name
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def #{name}
- if block_given?
- yield(@#{name})
- else
- @#{name}.#{attribute_name}
- end
- end
-
- def #{name}=(new_value)
- @#{name}.#{attribute_name} = new_value
- end
- EOC
- else
- attr_reader name
- end
- end
-
- def def_classed_elements(name, attribute, plural_class_name=nil,
- plural_name=nil, new_name=nil)
- plural_name ||= "#{name}s"
- new_name ||= name
- def_classed_element(plural_name, plural_class_name)
- local_variable_name = "_#{name}"
- new_value_variable_name = "new_value"
- additional_setup_code = nil
- if block_given?
- additional_setup_code = yield(local_variable_name,
- new_value_variable_name)
- end
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def #{name}
- #{local_variable_name} = #{plural_name}.first
- #{local_variable_name} ? #{local_variable_name}.#{attribute} : nil
- end
-
- def #{name}=(#{new_value_variable_name})
- #{local_variable_name} =
- #{plural_name}.first || #{plural_name}.new_#{new_name}
- #{additional_setup_code}
- #{local_variable_name}.#{attribute} = #{new_value_variable_name}
- end
- EOC
- end
-
- def def_other_element(name)
- attr_accessor name
- def_other_element_without_accessor(name)
- end
-
- def def_other_element_without_accessor(name)
- add_need_initialize_variable(name)
- add_other_element(name)
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def setup_#{name}(feed, current)
- if !@#{name}.nil? and current.respond_to?(:#{name}=)
- current.#{name} = @#{name}
- end
- end
- EOC
- end
-
- def def_csv_element(name, type=nil)
- def_other_element_without_accessor(name)
- attr_reader(name)
- converter = ""
- if type == :integer
- converter = "{|v| Integer(v)}"
- end
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def #{name}=(value)
- @#{name} = Utils::CSV.parse(value)#{converter}
- end
- EOC
- end
- end
-
- attr_reader :maker
- def initialize(maker)
- @maker = maker
- @default_values_are_set = false
- initialize_variables
- end
-
- def have_required_values?
- not_set_required_variables.empty?
- end
-
- def variable_is_set?
- variables.any? {|var| not __send__(var).nil?}
- end
-
- private
- def initialize_variables
- self.class.need_initialize_variables.each do |variable_name, init_value|
- if init_value.nil?
- value = nil
- else
- if init_value.respond_to?(:call)
- value = init_value.call(self)
- elsif init_value.is_a?(String)
- # just for backward compatibility
- value = instance_eval(init_value, __FILE__, __LINE__)
- else
- value = init_value
- end
- end
- instance_variable_set("@#{variable_name}", value)
- end
- end
-
- def setup_other_elements(feed, current=nil)
- current ||= current_element(feed)
- self.class.other_elements.each do |element|
- __send__("setup_#{element}", feed, current)
- end
- end
-
- def current_element(feed)
- feed
- end
-
- def set_default_values(&block)
- return yield if @default_values_are_set
-
- begin
- @default_values_are_set = true
- _set_default_values(&block)
- ensure
- @default_values_are_set = false
- end
- end
-
- def _set_default_values(&block)
- yield
- end
-
- def setup_values(target)
- set = false
- if have_required_values?
- variables.each do |var|
- setter = "#{var}="
- if target.respond_to?(setter)
- value = __send__(var)
- unless value.nil?
- target.__send__(setter, value)
- set = true
- end
- end
- end
- end
- set
- end
-
- def set_parent(target, parent)
- target.parent = parent if target.class.need_parent?
- end
-
- def variables
- self.class.need_initialize_variables.find_all do |name, init|
- # init == "nil" is just for backward compatibility
- init.nil? or init == "nil"
- end.collect do |name, init|
- name
- end
- end
-
- def not_set_required_variables
- required_variable_names.find_all do |var|
- __send__(var).nil?
- end
- end
-
- def required_variables_are_set?
- required_variable_names.each do |var|
- return false if __send__(var).nil?
- end
- true
- end
- end
-
- module AtomPersonConstructBase
- def self.append_features(klass)
- super
-
- klass.class_eval(<<-EOC, __FILE__, __LINE__ + 1)
- %w(name uri email).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- EOC
- end
- end
-
- module AtomTextConstructBase
- module EnsureXMLContent
- class << self
- def included(base)
- super
- base.class_eval do
- %w(type content xml_content).each do |element|
- attr_reader element
- attr_writer element if element != "xml_content"
- add_need_initialize_variable(element)
- end
-
- alias_method(:xhtml, :xml_content)
- end
- end
- end
-
- def ensure_xml_content(content)
- xhtml_uri = ::RSS::Atom::XHTML_URI
- unless content.is_a?(RSS::XML::Element) and
- ["div", xhtml_uri] == [content.name, content.uri]
- children = content
- children = [children] unless content.is_a?(Array)
- children = set_xhtml_uri_as_default_uri(children)
- content = RSS::XML::Element.new("div", nil, xhtml_uri,
- {"xmlns" => xhtml_uri},
- children)
- end
- content
- end
-
- def xml_content=(content)
- @xml_content = ensure_xml_content(content)
- end
-
- def xhtml=(content)
- self.xml_content = content
- end
-
- private
- def set_xhtml_uri_as_default_uri(children)
- children.collect do |child|
- if child.is_a?(RSS::XML::Element) and
- child.prefix.nil? and child.uri.nil?
- RSS::XML::Element.new(child.name, nil, ::RSS::Atom::XHTML_URI,
- child.attributes.dup,
- set_xhtml_uri_as_default_uri(child.children))
- else
- child
- end
- end
- end
- end
-
- def self.append_features(klass)
- super
-
- klass.class_eval do
- include EnsureXMLContent
- end
- end
- end
-
- module SetupDefaultDate
- private
- def _set_default_values
- keep = {
- :date => date,
- :dc_dates => dc_dates.to_a.dup,
- }
- _date = _parse_date_if_needed(date)
- if _date and !dc_dates.any? {|dc_date| dc_date.value == _date}
- dc_date = self.class::DublinCoreDates::DublinCoreDate.new(self)
- dc_date.value = _date.dup
- dc_dates.unshift(dc_date)
- end
- self.date ||= self.dc_date
- super
- ensure
- self.date = keep[:date]
- dc_dates.replace(keep[:dc_dates])
- end
-
- def _parse_date_if_needed(date_value)
- date_value = Time.parse(date_value) if date_value.is_a?(String)
- date_value
- end
- end
-
- module SetupDefaultLanguage
- private
- def _set_default_values
- keep = {
- :dc_languages => dc_languages.to_a.dup,
- }
- _language = language
- if _language and
- !dc_languages.any? {|dc_language| dc_language.value == _language}
- dc_language = self.class::DublinCoreLanguages::DublinCoreLanguage.new(self)
- dc_language.value = _language.dup
- dc_languages.unshift(dc_language)
- end
- super
- ensure
- dc_languages.replace(keep[:dc_languages])
- end
- end
-
- class RSSBase < Base
- class << self
- def make(*args, &block)
- new(*args).make(&block)
- end
- end
-
- %w(xml_stylesheets channel image items textinput).each do |element|
- attr_reader element
- add_need_initialize_variable(element) do |object|
- object.send("make_#{element}")
- end
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- private
- def setup_#{element}(feed)
- @#{element}.to_feed(feed)
- end
-
- def make_#{element}
- self.class::#{Utils.to_class_name(element)}.new(self)
- end
- EOC
- end
-
- attr_reader :feed_version
- alias_method(:rss_version, :feed_version)
- attr_accessor :version, :encoding, :standalone
-
- def initialize(feed_version)
- super(self)
- @feed_type = nil
- @feed_subtype = nil
- @feed_version = feed_version
- @version = "1.0"
- @encoding = "UTF-8"
- @standalone = nil
- end
-
- def make
- yield(self)
- to_feed
- end
-
- def to_feed
- feed = make_feed
- setup_xml_stylesheets(feed)
- setup_elements(feed)
- setup_other_elements(feed)
- feed.validate
- feed
- end
-
- private
- remove_method :make_xml_stylesheets
- def make_xml_stylesheets
- XMLStyleSheets.new(self)
- end
- end
-
- class XMLStyleSheets < Base
- def_array_element("xml_stylesheet", nil, "XMLStyleSheet")
-
- class XMLStyleSheet < Base
-
- ::RSS::XMLStyleSheet::ATTRIBUTES.each do |attribute|
- attr_accessor attribute
- add_need_initialize_variable(attribute)
- end
-
- def to_feed(feed)
- xss = ::RSS::XMLStyleSheet.new
- guess_type_if_need(xss)
- set = setup_values(xss)
- if set
- feed.xml_stylesheets << xss
- end
- end
-
- private
- def guess_type_if_need(xss)
- if @type.nil?
- xss.href = @href
- @type = xss.type
- end
- end
-
- def required_variable_names
- %w(href type)
- end
- end
- end
-
- class ChannelBase < Base
- include SetupDefaultDate
-
- %w(cloud categories skipDays skipHours).each do |name|
- def_classed_element(name)
- end
-
- %w(generator copyright description title).each do |name|
- def_classed_element(name, nil, "content")
- end
-
- [
- ["link", "href", Proc.new {|target,| "#{target}.href = 'self'"}],
- ["author", "name"],
- ["contributor", "name"],
- ].each do |name, attribute, additional_setup_maker|
- def_classed_elements(name, attribute, &additional_setup_maker)
- end
-
- %w(id about language
- managingEditor webMaster rating docs ttl).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
-
- %w(date lastBuildDate).each do |date_element|
- attr_reader date_element
- add_need_initialize_variable(date_element)
- end
-
- def date=(_date)
- @date = _parse_date_if_needed(_date)
- end
-
- def lastBuildDate=(_date)
- @lastBuildDate = _parse_date_if_needed(_date)
- end
-
- def pubDate
- date
- end
-
- def pubDate=(date)
- self.date = date
- end
-
- def updated
- date
- end
-
- def updated=(date)
- self.date = date
- end
-
- alias_method(:rights, :copyright)
- alias_method(:rights=, :copyright=)
-
- alias_method(:subtitle, :description)
- alias_method(:subtitle=, :description=)
-
- def icon
- image_favicon.about
- end
-
- def icon=(url)
- image_favicon.about = url
- end
-
- def logo
- maker.image.url
- end
-
- def logo=(url)
- maker.image.url = url
- end
-
- class SkipDaysBase < Base
- def_array_element("day")
-
- class DayBase < Base
- %w(content).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- end
- end
-
- class SkipHoursBase < Base
- def_array_element("hour")
-
- class HourBase < Base
- %w(content).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- end
- end
-
- class CloudBase < Base
- %w(domain port path registerProcedure protocol).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- end
-
- class CategoriesBase < Base
- def_array_element("category", "categories")
-
- class CategoryBase < Base
- %w(domain content label).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
-
- alias_method(:term, :domain)
- alias_method(:term=, :domain=)
- alias_method(:scheme, :content)
- alias_method(:scheme=, :content=)
- end
- end
-
- class LinksBase < Base
- def_array_element("link")
-
- class LinkBase < Base
- %w(href rel type hreflang title length).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- end
- end
-
- class AuthorsBase < Base
- def_array_element("author")
-
- class AuthorBase < Base
- include AtomPersonConstructBase
- end
- end
-
- class ContributorsBase < Base
- def_array_element("contributor")
-
- class ContributorBase < Base
- include AtomPersonConstructBase
- end
- end
-
- class GeneratorBase < Base
- %w(uri version content).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- end
-
- class CopyrightBase < Base
- include AtomTextConstructBase
- end
-
- class DescriptionBase < Base
- include AtomTextConstructBase
- end
-
- class TitleBase < Base
- include AtomTextConstructBase
- end
- end
-
- class ImageBase < Base
- %w(title url width height description).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
-
- def link
- @maker.channel.link
- end
- end
-
- class ItemsBase < Base
- def_array_element("item")
-
- attr_accessor :do_sort, :max_size
-
- def initialize(maker)
- super
- @do_sort = false
- @max_size = -1
- end
-
- def normalize
- if @max_size >= 0
- sort_if_need[0...@max_size]
- else
- sort_if_need[0..@max_size]
- end
- end
-
- private
- def sort_if_need
- if @do_sort.respond_to?(:call)
- @items.sort do |x, y|
- @do_sort.call(x, y)
- end
- elsif @do_sort
- @items.sort do |x, y|
- y <=> x
- end
- else
- @items
- end
- end
-
- class ItemBase < Base
- include SetupDefaultDate
-
- %w(guid enclosure source categories content).each do |name|
- def_classed_element(name)
- end
-
- %w(rights description title).each do |name|
- def_classed_element(name, nil, "content")
- end
-
- [
- ["author", "name"],
- ["link", "href", Proc.new {|target,| "#{target}.href = 'alternate'"}],
- ["contributor", "name"],
- ].each do |name, attribute|
- def_classed_elements(name, attribute)
- end
-
- %w(comments id published).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
-
- %w(date).each do |date_element|
- attr_reader date_element
- add_need_initialize_variable(date_element)
- end
-
- def date=(_date)
- @date = _parse_date_if_needed(_date)
- end
-
- def pubDate
- date
- end
-
- def pubDate=(date)
- self.date = date
- end
-
- def updated
- date
- end
-
- def updated=(date)
- self.date = date
- end
-
- alias_method(:summary, :description)
- alias_method(:summary=, :description=)
-
- def <=>(other)
- _date = date || dc_date
- _other_date = other.date || other.dc_date
- if _date and _other_date
- _date <=> _other_date
- elsif _date
- 1
- elsif _other_date
- -1
- else
- 0
- end
- end
-
- class GuidBase < Base
- %w(isPermaLink content).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
-
- def permanent_link?
- isPermaLink
- end
-
- def permanent_link=(bool)
- self.isPermaLink = bool
- end
- end
-
- class EnclosureBase < Base
- %w(url length type).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- end
-
- class SourceBase < Base
- include SetupDefaultDate
-
- %w(authors categories contributors generator icon
- logo rights subtitle title).each do |name|
- def_classed_element(name)
- end
-
- [
- ["link", "href"],
- ].each do |name, attribute|
- def_classed_elements(name, attribute)
- end
-
- %w(id content).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
-
- alias_method(:url, :link)
- alias_method(:url=, :link=)
-
- %w(date).each do |date_element|
- attr_reader date_element
- add_need_initialize_variable(date_element)
- end
-
- def date=(_date)
- @date = _parse_date_if_needed(_date)
- end
-
- def updated
- date
- end
-
- def updated=(date)
- self.date = date
- end
-
- private
- AuthorsBase = ChannelBase::AuthorsBase
- CategoriesBase = ChannelBase::CategoriesBase
- ContributorsBase = ChannelBase::ContributorsBase
- GeneratorBase = ChannelBase::GeneratorBase
-
- class IconBase < Base
- %w(url).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- end
-
- LinksBase = ChannelBase::LinksBase
-
- class LogoBase < Base
- %w(uri).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- end
-
- class RightsBase < Base
- include AtomTextConstructBase
- end
-
- class SubtitleBase < Base
- include AtomTextConstructBase
- end
-
- class TitleBase < Base
- include AtomTextConstructBase
- end
- end
-
- CategoriesBase = ChannelBase::CategoriesBase
- AuthorsBase = ChannelBase::AuthorsBase
- LinksBase = ChannelBase::LinksBase
- ContributorsBase = ChannelBase::ContributorsBase
-
- class RightsBase < Base
- include AtomTextConstructBase
- end
-
- class DescriptionBase < Base
- include AtomTextConstructBase
- end
-
- class ContentBase < Base
- include AtomTextConstructBase::EnsureXMLContent
-
- %w(src).each do |element|
- attr_accessor(element)
- add_need_initialize_variable(element)
- end
-
- def xml_content=(content)
- content = ensure_xml_content(content) if inline_xhtml?
- @xml_content = content
- end
-
- alias_method(:xml, :xml_content)
- alias_method(:xml=, :xml_content=)
-
- def inline_text?
- [nil, "text", "html"].include?(@type)
- end
-
- def inline_html?
- @type == "html"
- end
-
- def inline_xhtml?
- @type == "xhtml"
- end
-
- def inline_other?
- !out_of_line? and ![nil, "text", "html", "xhtml"].include?(@type)
- end
-
- def inline_other_text?
- return false if @type.nil? or out_of_line?
- /\Atext\//i.match(@type) ? true : false
- end
-
- def inline_other_xml?
- return false if @type.nil? or out_of_line?
- /[\+\/]xml\z/i.match(@type) ? true : false
- end
-
- def inline_other_base64?
- return false if @type.nil? or out_of_line?
- @type.include?("/") and !inline_other_text? and !inline_other_xml?
- end
-
- def out_of_line?
- not @src.nil? and @content.nil?
- end
- end
-
- class TitleBase < Base
- include AtomTextConstructBase
- end
- end
- end
-
- class TextinputBase < Base
- %w(title description name link).each do |element|
- attr_accessor element
- add_need_initialize_variable(element)
- end
- end
- end
-end
diff --git a/lib/rss/maker/content.rb b/lib/rss/maker/content.rb
deleted file mode 100644
index b3f4e5036e..0000000000
--- a/lib/rss/maker/content.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: false
-require_relative '../content'
-require_relative '1.0'
-require_relative '2.0'
-
-module RSS
- module Maker
- module ContentModel
- def self.append_features(klass)
- super
-
- ::RSS::ContentModel::ELEMENTS.each do |name|
- klass.def_other_element(name)
- end
- end
- end
-
- class ItemsBase
- class ItemBase; include ContentModel; end
- end
- end
-end
diff --git a/lib/rss/maker/dublincore.rb b/lib/rss/maker/dublincore.rb
deleted file mode 100644
index beea3134b4..0000000000
--- a/lib/rss/maker/dublincore.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-# frozen_string_literal: false
-require_relative '../dublincore'
-require_relative '1.0'
-
-module RSS
- module Maker
- module DublinCoreModel
- def self.append_features(klass)
- super
-
- ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
- plural_name ||= "#{name}s"
- full_name = "#{RSS::DC_PREFIX}_#{name}"
- full_plural_name = "#{RSS::DC_PREFIX}_#{plural_name}"
- plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
- klass.def_classed_elements(full_name, "value", plural_klass_name,
- full_plural_name, name)
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def new_#{full_name}(value=nil)
- _#{full_name} = #{full_plural_name}.new_#{name}
- _#{full_name}.value = value
- if block_given?
- yield _#{full_name}
- else
- _#{full_name}
- end
- end
- EOC
- end
-
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- # For backward compatibility
- alias #{DC_PREFIX}_rightses #{DC_PREFIX}_rights_list
- EOC
- end
-
- ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
- plural_name ||= "#{name}s"
- full_name ||= "#{DC_PREFIX}_#{name}"
- full_plural_name ||= "#{DC_PREFIX}_#{plural_name}"
- klass_name = Utils.to_class_name(name)
- full_klass_name = "DublinCore#{klass_name}"
- plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class #{plural_klass_name}Base < Base
- def_array_element(#{name.dump}, #{full_plural_name.dump},
- #{full_klass_name.dump})
-
- class #{full_klass_name}Base < Base
- attr_accessor :value
- add_need_initialize_variable("value")
- alias_method(:content, :value)
- alias_method(:content=, :value=)
-
- def have_required_values?
- @value
- end
-
- def to_feed(feed, current)
- if value and current.respond_to?(:#{full_name})
- new_item = current.class::#{full_klass_name}.new(value)
- current.#{full_plural_name} << new_item
- end
- end
- end
- #{klass_name}Base = #{full_klass_name}Base
- end
- EOC
- end
-
- def self.install_dublin_core(klass)
- ::RSS::DublinCoreModel::ELEMENT_NAME_INFOS.each do |name, plural_name|
- plural_name ||= "#{name}s"
- klass_name = Utils.to_class_name(name)
- full_klass_name = "DublinCore#{klass_name}"
- plural_klass_name = "DublinCore#{Utils.to_class_name(plural_name)}"
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class #{plural_klass_name} < #{plural_klass_name}Base
- class #{full_klass_name} < #{full_klass_name}Base
- end
- #{klass_name} = #{full_klass_name}
- end
-EOC
- end
- end
- end
-
- class ChannelBase
- include DublinCoreModel
- end
-
- class ImageBase; include DublinCoreModel; end
- class ItemsBase
- class ItemBase
- include DublinCoreModel
- end
- end
- class TextinputBase; include DublinCoreModel; end
-
- makers.each do |maker|
- maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class Channel
- DublinCoreModel.install_dublin_core(self)
- end
-
- class Image
- DublinCoreModel.install_dublin_core(self)
- end
-
- class Items
- class Item
- DublinCoreModel.install_dublin_core(self)
- end
- end
-
- class Textinput
- DublinCoreModel.install_dublin_core(self)
- end
- EOC
- end
- end
-end
diff --git a/lib/rss/maker/entry.rb b/lib/rss/maker/entry.rb
deleted file mode 100644
index ccdf9608ae..0000000000
--- a/lib/rss/maker/entry.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: false
-require_relative "atom"
-require_relative "feed"
-
-module RSS
- module Maker
- module Atom
- class Entry < RSSBase
- def initialize(feed_version="1.0")
- super
- @feed_type = "atom"
- @feed_subtype = "entry"
- end
-
- private
- def make_feed
- ::RSS::Atom::Entry.new(@version, @encoding, @standalone)
- end
-
- def setup_elements(entry)
- setup_items(entry)
- end
-
- class Channel < ChannelBase
- class SkipDays < SkipDaysBase
- class Day < DayBase
- end
- end
-
- class SkipHours < SkipHoursBase
- class Hour < HourBase
- end
- end
-
- class Cloud < CloudBase
- end
-
- Categories = Feed::Channel::Categories
- Links = Feed::Channel::Links
- Authors = Feed::Channel::Authors
- Contributors = Feed::Channel::Contributors
-
- class Generator < GeneratorBase
- include AtomGenerator
-
- def self.not_set_name
- "maker.channel.generator"
- end
- end
-
- Copyright = Feed::Channel::Copyright
-
- class Description < DescriptionBase
- end
-
- Title = Feed::Channel::Title
- end
-
- class Image < ImageBase
- end
-
- class Items < ItemsBase
- def to_feed(entry)
- (normalize.first || Item.new(@maker)).to_feed(entry)
- end
-
- class Item < ItemBase
- def to_feed(entry)
- set_default_values do
- setup_values(entry)
- entry.dc_dates.clear
- setup_other_elements(entry)
- unless have_required_values?
- raise NotSetError.new("maker.item", not_set_required_variables)
- end
- end
- end
-
- private
- def required_variable_names
- %w(id updated)
- end
-
- def variables
- super + ["updated"]
- end
-
- def variable_is_set?
- super or !authors.empty?
- end
-
- def not_set_required_variables
- set_default_values do
- vars = super
- if authors.all? {|author| !author.have_required_values?}
- vars << "author"
- end
- vars << "title" unless title {|t| t.have_required_values?}
- vars
- end
- end
-
- def _set_default_values
- keep = {
- :authors => authors.to_a.dup,
- :contributors => contributors.to_a.dup,
- :categories => categories.to_a.dup,
- :id => id,
- :links => links.to_a.dup,
- :rights => @rights,
- :title => @title,
- :updated => updated,
- }
- authors.replace(@maker.channel.authors) if keep[:authors].empty?
- if keep[:contributors].empty?
- contributors.replace(@maker.channel.contributors)
- end
- if keep[:categories].empty?
- categories.replace(@maker.channel.categories)
- end
- self.id ||= link || @maker.channel.id
- links.replace(@maker.channel.links) if keep[:links].empty?
- unless keep[:rights].variable_is_set?
- @maker.channel.rights {|r| @rights = r}
- end
- unless keep[:title].variable_is_set?
- @maker.channel.title {|t| @title = t}
- end
- self.updated ||= @maker.channel.updated
- super
- ensure
- authors.replace(keep[:authors])
- contributors.replace(keep[:contributors])
- categories.replace(keep[:categories])
- links.replace(keep[:links])
- self.id = keep[:id]
- @rights = keep[:rights]
- @title = keep[:title]
- self.updated = keep[:updated]
- end
-
- Guid = Feed::Items::Item::Guid
- Enclosure = Feed::Items::Item::Enclosure
- Source = Feed::Items::Item::Source
- Categories = Feed::Items::Item::Categories
- Authors = Feed::Items::Item::Authors
- Contributors = Feed::Items::Item::Contributors
- Links = Feed::Items::Item::Links
- Rights = Feed::Items::Item::Rights
- Description = Feed::Items::Item::Description
- Title = Feed::Items::Item::Title
- Content = Feed::Items::Item::Content
- end
- end
-
- class Textinput < TextinputBase
- end
- end
- end
-
- add_maker("atom:entry", "1.0", Atom::Entry)
- add_maker("atom1.0:entry", "1.0", Atom::Entry)
- end
-end
diff --git a/lib/rss/maker/feed.rb b/lib/rss/maker/feed.rb
deleted file mode 100644
index 72ee704d6a..0000000000
--- a/lib/rss/maker/feed.rb
+++ /dev/null
@@ -1,427 +0,0 @@
-# frozen_string_literal: false
-require_relative "atom"
-
-module RSS
- module Maker
- module Atom
- class Feed < RSSBase
- def initialize(feed_version="1.0")
- super
- @feed_type = "atom"
- @feed_subtype = "feed"
- end
-
- private
- def make_feed
- ::RSS::Atom::Feed.new(@version, @encoding, @standalone)
- end
-
- def setup_elements(feed)
- setup_channel(feed)
- setup_image(feed)
- setup_items(feed)
- end
-
- class Channel < ChannelBase
- include SetupDefaultLanguage
-
- def to_feed(feed)
- set_default_values do
- setup_values(feed)
- feed.dc_dates.clear
- setup_other_elements(feed)
- if image_favicon.about
- icon = feed.class::Icon.new
- icon.content = image_favicon.about
- feed.icon = icon
- end
- unless have_required_values?
- raise NotSetError.new("maker.channel",
- not_set_required_variables)
- end
- end
- end
-
- def have_required_values?
- super and
- (!authors.empty? or
- @maker.items.any? {|item| !item.authors.empty?})
- end
-
- private
- def required_variable_names
- %w(id updated)
- end
-
- def variables
- super + %w(id updated)
- end
-
- def variable_is_set?
- super or !authors.empty?
- end
-
- def not_set_required_variables
- vars = super
- if authors.empty? and
- @maker.items.all? {|item| item.author.to_s.empty?}
- vars << "author"
- end
- vars << "title" unless title {|t| t.have_required_values?}
- vars
- end
-
- def _set_default_values(&block)
- keep = {
- :id => id,
- }
- self.id ||= about
- super(&block)
- ensure
- self.id = keep[:id]
- end
-
- class SkipDays < SkipDaysBase
- def to_feed(*args)
- end
-
- class Day < DayBase
- end
- end
-
- class SkipHours < SkipHoursBase
- def to_feed(*args)
- end
-
- class Hour < HourBase
- end
- end
-
- class Cloud < CloudBase
- def to_feed(*args)
- end
- end
-
- class Categories < CategoriesBase
- class Category < CategoryBase
- include AtomCategory
-
- def self.not_set_name
- "maker.channel.category"
- end
- end
- end
-
- class Links < LinksBase
- class Link < LinkBase
- include AtomLink
-
- def self.not_set_name
- "maker.channel.link"
- end
- end
- end
-
- AtomPersons.def_atom_persons(self, "author", "maker.channel.author")
- AtomPersons.def_atom_persons(self, "contributor",
- "maker.channel.contributor")
-
- class Generator < GeneratorBase
- include AtomGenerator
-
- def self.not_set_name
- "maker.channel.generator"
- end
- end
-
- AtomTextConstruct.def_atom_text_construct(self, "rights",
- "maker.channel.copyright",
- "Copyright")
- AtomTextConstruct.def_atom_text_construct(self, "subtitle",
- "maker.channel.description",
- "Description")
- AtomTextConstruct.def_atom_text_construct(self, "title",
- "maker.channel.title")
- end
-
- class Image < ImageBase
- def to_feed(feed)
- logo = feed.class::Logo.new
- class << logo
- alias_method(:url=, :content=)
- end
- set = setup_values(logo)
- class << logo
- remove_method(:url=)
- end
- if set
- feed.logo = logo
- set_parent(logo, feed)
- setup_other_elements(feed, logo)
- elsif variable_is_set?
- raise NotSetError.new("maker.image", not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(url)
- end
- end
-
- class Items < ItemsBase
- def to_feed(feed)
- normalize.each do |item|
- item.to_feed(feed)
- end
- setup_other_elements(feed, feed.entries)
- end
-
- class Item < ItemBase
- def to_feed(feed)
- set_default_values do
- entry = feed.class::Entry.new
- set = setup_values(entry)
- entry.dc_dates.clear
- setup_other_elements(feed, entry)
- if set
- feed.entries << entry
- set_parent(entry, feed)
- elsif variable_is_set?
- raise NotSetError.new("maker.item", not_set_required_variables)
- end
- end
- end
-
- def have_required_values?
- set_default_values do
- super and title {|t| t.have_required_values?}
- end
- end
-
- private
- def required_variable_names
- %w(id updated)
- end
-
- def variables
- super + ["updated"]
- end
-
- def not_set_required_variables
- vars = super
- vars << "title" unless title {|t| t.have_required_values?}
- vars
- end
-
- def _set_default_values(&block)
- keep = {
- :id => id,
- }
- self.id ||= link
- super(&block)
- ensure
- self.id = keep[:id]
- end
-
- class Guid < GuidBase
- def to_feed(feed, current)
- end
- end
-
- class Enclosure < EnclosureBase
- def to_feed(feed, current)
- end
- end
-
- class Source < SourceBase
- def to_feed(feed, current)
- source = current.class::Source.new
- setup_values(source)
- current.source = source
- set_parent(source, current)
- setup_other_elements(feed, source)
- current.source = nil if source.to_s == "<source/>"
- end
-
- private
- def required_variable_names
- []
- end
-
- def variables
- super + ["updated"]
- end
-
- AtomPersons.def_atom_persons(self, "author",
- "maker.item.source.author")
- AtomPersons.def_atom_persons(self, "contributor",
- "maker.item.source.contributor")
-
- class Categories < CategoriesBase
- class Category < CategoryBase
- include AtomCategory
-
- def self.not_set_name
- "maker.item.source.category"
- end
- end
- end
-
- class Generator < GeneratorBase
- include AtomGenerator
-
- def self.not_set_name
- "maker.item.source.generator"
- end
- end
-
- class Icon < IconBase
- def to_feed(feed, current)
- icon = current.class::Icon.new
- class << icon
- alias_method(:url=, :content=)
- end
- set = setup_values(icon)
- class << icon
- remove_method(:url=)
- end
- if set
- current.icon = icon
- set_parent(icon, current)
- setup_other_elements(feed, icon)
- elsif variable_is_set?
- raise NotSetError.new("maker.item.source.icon",
- not_set_required_variables)
- end
- end
-
- private
- def required_variable_names
- %w(url)
- end
- end
-
- class Links < LinksBase
- class Link < LinkBase
- include AtomLink
-
- def self.not_set_name
- "maker.item.source.link"
- end
- end
- end
-
- class Logo < LogoBase
- include AtomLogo
-
- def self.not_set_name
- "maker.item.source.logo"
- end
- end
-
- maker_name_base = "maker.item.source."
- maker_name = "#{maker_name_base}rights"
- AtomTextConstruct.def_atom_text_construct(self, "rights",
- maker_name)
- maker_name = "#{maker_name_base}subtitle"
- AtomTextConstruct.def_atom_text_construct(self, "subtitle",
- maker_name)
- maker_name = "#{maker_name_base}title"
- AtomTextConstruct.def_atom_text_construct(self, "title",
- maker_name)
- end
-
- class Categories < CategoriesBase
- class Category < CategoryBase
- include AtomCategory
-
- def self.not_set_name
- "maker.item.category"
- end
- end
- end
-
- AtomPersons.def_atom_persons(self, "author", "maker.item.author")
- AtomPersons.def_atom_persons(self, "contributor",
- "maker.item.contributor")
-
- class Links < LinksBase
- class Link < LinkBase
- include AtomLink
-
- def self.not_set_name
- "maker.item.link"
- end
- end
- end
-
- AtomTextConstruct.def_atom_text_construct(self, "rights",
- "maker.item.rights")
- AtomTextConstruct.def_atom_text_construct(self, "summary",
- "maker.item.description",
- "Description")
- AtomTextConstruct.def_atom_text_construct(self, "title",
- "maker.item.title")
-
- class Content < ContentBase
- def to_feed(feed, current)
- content = current.class::Content.new
- if setup_values(content)
- content.src = nil if content.src and content.content
- current.content = content
- set_parent(content, current)
- setup_other_elements(feed, content)
- elsif variable_is_set?
- raise NotSetError.new("maker.item.content",
- not_set_required_variables)
- end
- end
-
- alias_method(:xml, :xml_content)
-
- private
- def required_variable_names
- if out_of_line?
- %w(type)
- elsif xml_type?
- %w(xml_content)
- else
- %w(content)
- end
- end
-
- def variables
- if out_of_line?
- super
- elsif xml_type?
- super + %w(xml)
- else
- super
- end
- end
-
- def xml_type?
- _type = type
- return false if _type.nil?
- _type == "xhtml" or
- /(?:\+xml|\/xml)$/i =~ _type or
- %w(text/xml-external-parsed-entity
- application/xml-external-parsed-entity
- application/xml-dtd).include?(_type.downcase)
- end
- end
- end
- end
-
- class Textinput < TextinputBase
- end
- end
- end
-
- add_maker("atom", "1.0", Atom::Feed)
- add_maker("atom:feed", "1.0", Atom::Feed)
- add_maker("atom1.0", "1.0", Atom::Feed)
- add_maker("atom1.0:feed", "1.0", Atom::Feed)
- end
-end
diff --git a/lib/rss/maker/image.rb b/lib/rss/maker/image.rb
deleted file mode 100644
index e3e62d8b9e..0000000000
--- a/lib/rss/maker/image.rb
+++ /dev/null
@@ -1,112 +0,0 @@
-# frozen_string_literal: false
-require_relative '../image'
-require_relative '1.0'
-require_relative 'dublincore'
-
-module RSS
- module Maker
- module ImageItemModel
- def self.append_features(klass)
- super
-
- name = "#{RSS::IMAGE_PREFIX}_item"
- klass.def_classed_element(name)
- end
-
- def self.install_image_item(klass)
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class ImageItem < ImageItemBase
- DublinCoreModel.install_dublin_core(self)
- end
-EOC
- end
-
- class ImageItemBase < Base
- include Maker::DublinCoreModel
-
- attr_accessor :about, :resource, :image_width, :image_height
- add_need_initialize_variable("about")
- add_need_initialize_variable("resource")
- add_need_initialize_variable("image_width")
- add_need_initialize_variable("image_height")
- alias width= image_width=
- alias width image_width
- alias height= image_height=
- alias height image_height
-
- def have_required_values?
- @about
- end
-
- def to_feed(feed, current)
- if current.respond_to?(:image_item=) and have_required_values?
- item = current.class::ImageItem.new
- setup_values(item)
- setup_other_elements(item)
- current.image_item = item
- end
- end
- end
- end
-
- module ImageFaviconModel
- def self.append_features(klass)
- super
-
- name = "#{RSS::IMAGE_PREFIX}_favicon"
- klass.def_classed_element(name)
- end
-
- def self.install_image_favicon(klass)
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class ImageFavicon < ImageFaviconBase
- DublinCoreModel.install_dublin_core(self)
- end
- EOC
- end
-
- class ImageFaviconBase < Base
- include Maker::DublinCoreModel
-
- attr_accessor :about, :image_size
- add_need_initialize_variable("about")
- add_need_initialize_variable("image_size")
- alias size image_size
- alias size= image_size=
-
- def have_required_values?
- @about and @image_size
- end
-
- def to_feed(feed, current)
- if current.respond_to?(:image_favicon=) and have_required_values?
- favicon = current.class::ImageFavicon.new
- setup_values(favicon)
- setup_other_elements(favicon)
- current.image_favicon = favicon
- end
- end
- end
- end
-
- class ChannelBase; include Maker::ImageFaviconModel; end
-
- class ItemsBase
- class ItemBase; include Maker::ImageItemModel; end
- end
-
- makers.each do |maker|
- maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class Channel
- ImageFaviconModel.install_image_favicon(self)
- end
-
- class Items
- class Item
- ImageItemModel.install_image_item(self)
- end
- end
- EOC
- end
- end
-end
diff --git a/lib/rss/maker/itunes.rb b/lib/rss/maker/itunes.rb
deleted file mode 100644
index 28cca32021..0000000000
--- a/lib/rss/maker/itunes.rb
+++ /dev/null
@@ -1,243 +0,0 @@
-# frozen_string_literal: false
-require_relative '../itunes'
-require_relative '2.0'
-
-module RSS
- module Maker
- module ITunesBaseModel
- def def_class_accessor(klass, name, type, *args)
- name = name.gsub(/-/, "_").gsub(/^itunes_/, '')
- full_name = "#{RSS::ITUNES_PREFIX}_#{name}"
- case type
- when nil
- klass.def_other_element(full_name)
- when :yes_other
- def_yes_other_accessor(klass, full_name)
- when :explicit_clean_other
- def_explicit_clean_other_accessor(klass, full_name)
- when :csv
- def_csv_accessor(klass, full_name)
- when :element, :attribute
- recommended_attribute_name, = *args
- klass_name = "ITunes#{Utils.to_class_name(name)}"
- klass.def_classed_element(full_name, klass_name,
- recommended_attribute_name)
- when :elements
- plural_name, recommended_attribute_name = args
- plural_name ||= "#{name}s"
- full_plural_name = "#{RSS::ITUNES_PREFIX}_#{plural_name}"
- klass_name = "ITunes#{Utils.to_class_name(name)}"
- plural_klass_name = "ITunes#{Utils.to_class_name(plural_name)}"
- def_elements_class_accessor(klass, name, full_name, full_plural_name,
- klass_name, plural_klass_name,
- recommended_attribute_name)
- end
- end
-
- def def_yes_other_accessor(klass, full_name)
- klass.def_other_element(full_name)
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def #{full_name}?
- Utils::YesOther.parse(@#{full_name})
- end
- EOC
- end
-
- def def_explicit_clean_other_accessor(klass, full_name)
- klass.def_other_element(full_name)
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def #{full_name}?
- Utils::ExplicitCleanOther.parse(#{full_name})
- end
- EOC
- end
-
- def def_csv_accessor(klass, full_name)
- klass.def_csv_element(full_name)
- end
-
- def def_elements_class_accessor(klass, name, full_name, full_plural_name,
- klass_name, plural_klass_name,
- recommended_attribute_name=nil)
- if recommended_attribute_name
- klass.def_classed_elements(full_name, recommended_attribute_name,
- plural_klass_name, full_plural_name)
- else
- klass.def_classed_element(full_plural_name, plural_klass_name)
- end
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def new_#{full_name}(text=nil)
- #{full_name} = @#{full_plural_name}.new_#{name}
- #{full_name}.text = text
- if block_given?
- yield #{full_name}
- else
- #{full_name}
- end
- end
- EOC
- end
- end
-
- module ITunesChannelModel
- extend ITunesBaseModel
-
- class << self
- def append_features(klass)
- super
-
- ::RSS::ITunesChannelModel::ELEMENT_INFOS.each do |name, type, *args|
- def_class_accessor(klass, name, type, *args)
- end
- end
- end
-
- class ITunesCategoriesBase < Base
- def_array_element("category", "itunes_categories",
- "ITunesCategory")
- class ITunesCategoryBase < Base
- attr_accessor :text
- add_need_initialize_variable("text")
- def_array_element("category", "itunes_categories",
- "ITunesCategory")
-
- def have_required_values?
- text
- end
-
- alias_method :to_feed_for_categories, :to_feed
- def to_feed(feed, current)
- if text and current.respond_to?(:itunes_category)
- new_item = current.class::ITunesCategory.new(text)
- to_feed_for_categories(feed, new_item)
- current.itunes_categories << new_item
- end
- end
- end
- end
-
- class ITunesImageBase < Base
- add_need_initialize_variable("href")
- attr_accessor("href")
-
- def to_feed(feed, current)
- if @href and current.respond_to?(:itunes_image)
- current.itunes_image ||= current.class::ITunesImage.new
- current.itunes_image.href = @href
- end
- end
- end
-
- class ITunesOwnerBase < Base
- %w(itunes_name itunes_email).each do |name|
- add_need_initialize_variable(name)
- attr_accessor(name)
- end
-
- def to_feed(feed, current)
- if current.respond_to?(:itunes_owner=)
- _not_set_required_variables = not_set_required_variables
- if (required_variable_names - _not_set_required_variables).empty?
- return
- end
-
- unless have_required_values?
- raise NotSetError.new("maker.channel.itunes_owner",
- _not_set_required_variables)
- end
- current.itunes_owner ||= current.class::ITunesOwner.new
- current.itunes_owner.itunes_name = @itunes_name
- current.itunes_owner.itunes_email = @itunes_email
- end
- end
-
- private
- def required_variable_names
- %w(itunes_name itunes_email)
- end
- end
- end
-
- module ITunesItemModel
- extend ITunesBaseModel
-
- class << self
- def append_features(klass)
- super
-
- ::RSS::ITunesItemModel::ELEMENT_INFOS.each do |name, type, *args|
- def_class_accessor(klass, name, type, *args)
- end
- end
- end
-
- class ITunesDurationBase < Base
- attr_reader :content
- add_need_initialize_variable("content")
-
- %w(hour minute second).each do |name|
- attr_reader(name)
- add_need_initialize_variable(name, 0)
- end
-
- def content=(content)
- if content.nil?
- @hour, @minute, @second, @content = nil
- else
- @hour, @minute, @second =
- ::RSS::ITunesItemModel::ITunesDuration.parse(content)
- @content = content
- end
- end
-
- def hour=(hour)
- @hour = Integer(hour)
- update_content
- end
-
- def minute=(minute)
- @minute = Integer(minute)
- update_content
- end
-
- def second=(second)
- @second = Integer(second)
- update_content
- end
-
- def to_feed(feed, current)
- if @content and current.respond_to?(:itunes_duration=)
- current.itunes_duration ||= current.class::ITunesDuration.new
- current.itunes_duration.content = @content
- end
- end
-
- private
- def update_content
- components = [@hour, @minute, @second]
- @content =
- ::RSS::ITunesItemModel::ITunesDuration.construct(*components)
- end
- end
- end
-
- class ChannelBase
- include Maker::ITunesChannelModel
- class ITunesCategories < ITunesCategoriesBase
- class ITunesCategory < ITunesCategoryBase
- ITunesCategory = self
- end
- end
-
- class ITunesImage < ITunesImageBase; end
- class ITunesOwner < ITunesOwnerBase; end
- end
-
- class ItemsBase
- class ItemBase
- include Maker::ITunesItemModel
- class ITunesDuration < ITunesDurationBase; end
- end
- end
- end
-end
diff --git a/lib/rss/maker/slash.rb b/lib/rss/maker/slash.rb
deleted file mode 100644
index 473991903f..0000000000
--- a/lib/rss/maker/slash.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: false
-require_relative '../slash'
-require_relative '1.0'
-
-module RSS
- module Maker
- module SlashModel
- def self.append_features(klass)
- super
-
- ::RSS::SlashModel::ELEMENT_INFOS.each do |name, type|
- full_name = "#{RSS::SLASH_PREFIX}_#{name}"
- case type
- when :csv_integer
- klass.def_csv_element(full_name, :integer)
- else
- klass.def_other_element(full_name)
- end
- end
-
- klass.module_eval do
- alias_method(:slash_hit_parades, :slash_hit_parade)
- alias_method(:slash_hit_parades=, :slash_hit_parade=)
- end
- end
- end
-
- class ItemsBase
- class ItemBase
- include SlashModel
- end
- end
- end
-end
diff --git a/lib/rss/maker/syndication.rb b/lib/rss/maker/syndication.rb
deleted file mode 100644
index 9fd0efe99e..0000000000
--- a/lib/rss/maker/syndication.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: false
-require_relative '../syndication'
-require_relative '1.0'
-
-module RSS
- module Maker
- module SyndicationModel
- def self.append_features(klass)
- super
-
- ::RSS::SyndicationModel::ELEMENTS.each do |name|
- klass.def_other_element(name)
- end
- end
- end
-
- class ChannelBase; include SyndicationModel; end
- end
-end
diff --git a/lib/rss/maker/taxonomy.rb b/lib/rss/maker/taxonomy.rb
deleted file mode 100644
index f9858922da..0000000000
--- a/lib/rss/maker/taxonomy.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-# frozen_string_literal: false
-require_relative '../taxonomy'
-require_relative '1.0'
-require_relative 'dublincore'
-
-module RSS
- module Maker
- module TaxonomyTopicsModel
- def self.append_features(klass)
- super
-
- klass.def_classed_element("#{RSS::TAXO_PREFIX}_topics",
- "TaxonomyTopics")
- end
-
- def self.install_taxo_topics(klass)
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class TaxonomyTopics < TaxonomyTopicsBase
- def to_feed(feed, current)
- if current.respond_to?(:taxo_topics)
- topics = current.class::TaxonomyTopics.new
- bag = topics.Bag
- @resources.each do |resource|
- bag.lis << RDF::Bag::Li.new(resource)
- end
- current.taxo_topics = topics
- end
- end
- end
-EOC
- end
-
- class TaxonomyTopicsBase < Base
- attr_reader :resources
- def_array_element("resource")
- remove_method :new_resource
- end
- end
-
- module TaxonomyTopicModel
- def self.append_features(klass)
- super
-
- class_name = "TaxonomyTopics"
- klass.def_classed_elements("#{TAXO_PREFIX}_topic", "value", class_name)
- end
-
- def self.install_taxo_topic(klass)
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class TaxonomyTopics < TaxonomyTopicsBase
- class TaxonomyTopic < TaxonomyTopicBase
- DublinCoreModel.install_dublin_core(self)
- TaxonomyTopicsModel.install_taxo_topics(self)
-
- def to_feed(feed, current)
- if current.respond_to?(:taxo_topics)
- topic = current.class::TaxonomyTopic.new(value)
- topic.taxo_link = value
- taxo_topics.to_feed(feed, topic) if taxo_topics
- current.taxo_topics << topic
- setup_other_elements(feed, topic)
- end
- end
- end
- end
-EOC
- end
-
- class TaxonomyTopicsBase < Base
- def_array_element("topic", nil, "TaxonomyTopic")
- alias_method(:new_taxo_topic, :new_topic) # For backward compatibility
-
- class TaxonomyTopicBase < Base
- include DublinCoreModel
- include TaxonomyTopicsModel
-
- attr_accessor :value
- add_need_initialize_variable("value")
- alias_method(:taxo_link, :value)
- alias_method(:taxo_link=, :value=)
-
- def have_required_values?
- @value
- end
- end
- end
- end
-
- class RSSBase
- include TaxonomyTopicModel
- end
-
- class ChannelBase
- include TaxonomyTopicsModel
- end
-
- class ItemsBase
- class ItemBase
- include TaxonomyTopicsModel
- end
- end
-
- makers.each do |maker|
- maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- TaxonomyTopicModel.install_taxo_topic(self)
-
- class Channel
- TaxonomyTopicsModel.install_taxo_topics(self)
- end
-
- class Items
- class Item
- TaxonomyTopicsModel.install_taxo_topics(self)
- end
- end
- EOC
- end
- end
-end
diff --git a/lib/rss/maker/trackback.rb b/lib/rss/maker/trackback.rb
deleted file mode 100644
index f78b4058f9..0000000000
--- a/lib/rss/maker/trackback.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: false
-require_relative '../trackback'
-require_relative '1.0'
-require_relative '2.0'
-
-module RSS
- module Maker
- module TrackBackModel
- def self.append_features(klass)
- super
-
- klass.def_other_element("#{RSS::TRACKBACK_PREFIX}_ping")
- klass.def_classed_elements("#{RSS::TRACKBACK_PREFIX}_about", "value",
- "TrackBackAbouts")
- end
-
- class TrackBackAboutsBase < Base
- def_array_element("about", nil, "TrackBackAbout")
-
- class TrackBackAboutBase < Base
- attr_accessor :value
- add_need_initialize_variable("value")
-
- alias_method(:resource, :value)
- alias_method(:resource=, :value=)
- alias_method(:content, :value)
- alias_method(:content=, :value=)
-
- def have_required_values?
- @value
- end
-
- def to_feed(feed, current)
- if current.respond_to?(:trackback_abouts) and have_required_values?
- about = current.class::TrackBackAbout.new
- setup_values(about)
- setup_other_elements(about)
- current.trackback_abouts << about
- end
- end
- end
- end
- end
-
- class ItemsBase
- class ItemBase; include TrackBackModel; end
- end
-
- makers.each do |maker|
- maker.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- class Items
- class Item
- class TrackBackAbouts < TrackBackAboutsBase
- class TrackBackAbout < TrackBackAboutBase
- end
- end
- end
- end
- EOC
- end
- end
-end
diff --git a/lib/rss/parser.rb b/lib/rss/parser.rb
deleted file mode 100644
index e1bcfc53e3..0000000000
--- a/lib/rss/parser.rb
+++ /dev/null
@@ -1,589 +0,0 @@
-# frozen_string_literal: false
-require "forwardable"
-require "open-uri"
-
-require_relative "rss"
-require_relative "xml"
-
-module RSS
-
- class NotWellFormedError < Error
- attr_reader :line, :element
-
- # Create a new NotWellFormedError for an error at +line+
- # in +element+. If a block is given the return value of
- # the block ends up in the error message.
- def initialize(line=nil, element=nil)
- message = "This is not well formed XML"
- if element or line
- message << "\nerror occurred"
- message << " in #{element}" if element
- message << " at about #{line} line" if line
- end
- message << "\n#{yield}" if block_given?
- super(message)
- end
- end
-
- class XMLParserNotFound < Error
- def initialize
- super("available XML parser was not found in " <<
- "#{AVAILABLE_PARSER_LIBRARIES.inspect}.")
- end
- end
-
- class NotValidXMLParser < Error
- def initialize(parser)
- super("#{parser} is not an available XML parser. " <<
- "Available XML parser" <<
- (AVAILABLE_PARSERS.size > 1 ? "s are " : " is ") <<
- "#{AVAILABLE_PARSERS.inspect}.")
- end
- end
-
- class NSError < InvalidRSSError
- attr_reader :tag, :prefix, :uri
- def initialize(tag, prefix, require_uri)
- @tag, @prefix, @uri = tag, prefix, require_uri
- super("prefix <#{prefix}> doesn't associate uri " <<
- "<#{require_uri}> in tag <#{tag}>")
- end
- end
-
- class Parser
-
- extend Forwardable
-
- class << self
-
- @@default_parser = nil
-
- def default_parser
- @@default_parser || AVAILABLE_PARSERS.first
- end
-
- # Set @@default_parser to new_value if it is one of the
- # available parsers. Else raise NotValidXMLParser error.
- def default_parser=(new_value)
- if AVAILABLE_PARSERS.include?(new_value)
- @@default_parser = new_value
- else
- raise NotValidXMLParser.new(new_value)
- end
- end
-
- def parse(rss, *args)
- if args.last.is_a?(Hash)
- options = args.pop
- else
- options = {}
- end
- do_validate = boolean_argument(args[0], options[:validate], true)
- ignore_unknown_element =
- boolean_argument(args[1], options[:ignore_unknown_element], true)
- parser_class = args[2] || options[:parser_class] || default_parser
- parser = new(rss, parser_class)
- parser.do_validate = do_validate
- parser.ignore_unknown_element = ignore_unknown_element
- parser.parse
- end
-
- private
- def boolean_argument(positioned_value, option_value, default)
- value = positioned_value
- if value.nil? and not option_value.nil?
- value = option_value
- end
- value = default if value.nil?
- value
- end
- end
-
- def_delegators(:@parser, :parse, :rss,
- :ignore_unknown_element,
- :ignore_unknown_element=, :do_validate,
- :do_validate=)
-
- def initialize(rss, parser_class=self.class.default_parser)
- @parser = parser_class.new(normalize_rss(rss))
- end
-
- private
-
- # Try to get the XML associated with +rss+.
- # Return +rss+ if it already looks like XML, or treat it as a URI,
- # or a file to get the XML,
- def normalize_rss(rss)
- return rss if maybe_xml?(rss)
-
- uri = to_uri(rss)
-
- if uri.respond_to?(:read)
- uri.read
- elsif (RUBY_VERSION >= '2.7' || !rss.tainted?) and File.readable?(rss)
- File.open(rss) {|f| f.read}
- else
- rss
- end
- end
-
- # maybe_xml? tests if source is a string that looks like XML.
- def maybe_xml?(source)
- source.is_a?(String) and /</ =~ source
- end
-
- # Attempt to convert rss to a URI, but just return it if
- # there's a ::URI::Error
- def to_uri(rss)
- return rss if rss.is_a?(::URI::Generic)
-
- begin
- ::URI.parse(rss)
- rescue ::URI::Error
- rss
- end
- end
- end
-
- class BaseParser
-
- class << self
- def raise_for_undefined_entity?
- listener.raise_for_undefined_entity?
- end
- end
-
- def initialize(rss)
- @listener = self.class.listener.new
- @rss = rss
- end
-
- def rss
- @listener.rss
- end
-
- def ignore_unknown_element
- @listener.ignore_unknown_element
- end
-
- def ignore_unknown_element=(new_value)
- @listener.ignore_unknown_element = new_value
- end
-
- def do_validate
- @listener.do_validate
- end
-
- def do_validate=(new_value)
- @listener.do_validate = new_value
- end
-
- def parse
- if @listener.rss.nil?
- _parse
- end
- @listener.rss
- end
-
- end
-
- class BaseListener
-
- extend Utils
-
- class << self
-
- @@accessor_bases = {}
- @@registered_uris = {}
- @@class_names = {}
-
- # return the setter for the uri, tag_name pair, or nil.
- def setter(uri, tag_name)
- _getter = getter(uri, tag_name)
- if _getter
- "#{_getter}="
- else
- nil
- end
- end
-
- def getter(uri, tag_name)
- (@@accessor_bases[uri] || {})[tag_name]
- end
-
- # return the tag_names for setters associated with uri
- def available_tags(uri)
- (@@accessor_bases[uri] || {}).keys
- end
-
- # register uri against this name.
- def register_uri(uri, name)
- @@registered_uris[name] ||= {}
- @@registered_uris[name][uri] = nil
- end
-
- # test if this uri is registered against this name
- def uri_registered?(uri, name)
- @@registered_uris[name].has_key?(uri)
- end
-
- # record class_name for the supplied uri and tag_name
- def install_class_name(uri, tag_name, class_name)
- @@class_names[uri] ||= {}
- @@class_names[uri][tag_name] = class_name
- end
-
- # retrieve class_name for the supplied uri and tag_name
- # If it doesn't exist, capitalize the tag_name
- def class_name(uri, tag_name)
- name = (@@class_names[uri] || {})[tag_name]
- return name if name
-
- tag_name = tag_name.gsub(/[_\-]([a-z]?)/) {$1.upcase}
- tag_name[0, 1].upcase + tag_name[1..-1]
- end
-
- def install_get_text_element(uri, name, accessor_base)
- install_accessor_base(uri, name, accessor_base)
- def_get_text_element(uri, name, *get_file_and_line_from_caller(1))
- end
-
- def raise_for_undefined_entity?
- true
- end
-
- private
- # set the accessor for the uri, tag_name pair
- def install_accessor_base(uri, tag_name, accessor_base)
- @@accessor_bases[uri] ||= {}
- @@accessor_bases[uri][tag_name] = accessor_base.chomp("=")
- end
-
- def def_get_text_element(uri, element_name, file, line)
- register_uri(uri, element_name)
- method_name = "start_#{element_name}"
- unless private_method_defined?(method_name)
- define_method(method_name) do |name, prefix, attrs, ns|
- uri = _ns(ns, prefix)
- if self.class.uri_registered?(uri, element_name)
- start_get_text_element(name, prefix, ns, uri)
- else
- start_else_element(name, prefix, attrs, ns)
- end
- end
- private(method_name)
- end
- end
- end
- end
-
- module ListenerMixin
- attr_reader :rss
-
- attr_accessor :ignore_unknown_element
- attr_accessor :do_validate
-
- def initialize
- @rss = nil
- @ignore_unknown_element = true
- @do_validate = true
- @ns_stack = [{"xml" => :xml}]
- @tag_stack = [[]]
- @text_stack = ['']
- @proc_stack = []
- @last_element = nil
- @version = @encoding = @standalone = nil
- @xml_stylesheets = []
- @xml_child_mode = false
- @xml_element = nil
- @last_xml_element = nil
- end
-
- # set instance vars for version, encoding, standalone
- def xmldecl(version, encoding, standalone)
- @version, @encoding, @standalone = version, encoding, standalone
- end
-
- def instruction(name, content)
- if name == "xml-stylesheet"
- params = parse_pi_content(content)
- if params.has_key?("href")
- @xml_stylesheets << XMLStyleSheet.new(params)
- end
- end
- end
-
- def tag_start(name, attributes)
- @text_stack.push('')
-
- ns = @ns_stack.last.dup
- attrs = {}
- attributes.each do |n, v|
- if /\Axmlns(?:\z|:)/ =~ n
- ns[$POSTMATCH] = v
- else
- attrs[n] = v
- end
- end
- @ns_stack.push(ns)
-
- prefix, local = split_name(name)
- @tag_stack.last.push([_ns(ns, prefix), local])
- @tag_stack.push([])
- if @xml_child_mode
- previous = @last_xml_element
- element_attrs = attributes.dup
- unless previous
- ns.each do |ns_prefix, value|
- next if ns_prefix == "xml"
- key = ns_prefix.empty? ? "xmlns" : "xmlns:#{ns_prefix}"
- element_attrs[key] ||= value
- end
- end
- next_element = XML::Element.new(local,
- prefix.empty? ? nil : prefix,
- _ns(ns, prefix),
- element_attrs)
- previous << next_element if previous
- @last_xml_element = next_element
- pr = Proc.new do |text, tags|
- if previous
- @last_xml_element = previous
- else
- @xml_element = @last_xml_element
- @last_xml_element = nil
- end
- end
- @proc_stack.push(pr)
- else
- if @rss.nil? and respond_to?("initial_start_#{local}", true)
- __send__("initial_start_#{local}", local, prefix, attrs, ns.dup)
- elsif respond_to?("start_#{local}", true)
- __send__("start_#{local}", local, prefix, attrs, ns.dup)
- else
- start_else_element(local, prefix, attrs, ns.dup)
- end
- end
- end
-
- def tag_end(name)
- if DEBUG
- p "end tag #{name}"
- p @tag_stack
- end
- text = @text_stack.pop
- tags = @tag_stack.pop
- pr = @proc_stack.pop
- pr.call(text, tags) unless pr.nil?
- @ns_stack.pop
- end
-
- def text(data)
- if @xml_child_mode
- @last_xml_element << data if @last_xml_element
- else
- @text_stack.last << data
- end
- end
-
- private
- def _ns(ns, prefix)
- ns.fetch(prefix, "")
- end
-
- CONTENT_PATTERN = /\s*([^=]+)=(["'])([^\2]+?)\2/
- # Extract the first name="value" pair from content.
- # Works with single quotes according to the constant
- # CONTENT_PATTERN. Return a Hash.
- def parse_pi_content(content)
- params = {}
- content.scan(CONTENT_PATTERN) do |name, quote, value|
- params[name] = value
- end
- params
- end
-
- def start_else_element(local, prefix, attrs, ns)
- class_name = self.class.class_name(_ns(ns, prefix), local)
- current_class = @last_element.class
- if known_class?(current_class, class_name)
- next_class = current_class.const_get(class_name)
- start_have_something_element(local, prefix, attrs, ns, next_class)
- else
- if !@do_validate or @ignore_unknown_element
- @proc_stack.push(setup_next_element_in_unknown_element)
- else
- parent = "ROOT ELEMENT???"
- if current_class.tag_name
- parent = current_class.tag_name
- end
- raise NotExpectedTagError.new(local, _ns(ns, prefix), parent)
- end
- end
- end
-
- if Module.method(:const_defined?).arity == -1
- def known_class?(target_class, class_name)
- class_name and
- (target_class.const_defined?(class_name, false) or
- target_class.constants.include?(class_name.to_sym))
- end
- else
- def known_class?(target_class, class_name)
- class_name and
- (target_class.const_defined?(class_name) or
- target_class.constants.include?(class_name))
- end
- end
-
- NAMESPLIT = /^(?:([\w:][-\w.]*):)?([\w:][-\w.]*)/
- def split_name(name)
- name =~ NAMESPLIT
- [$1 || '', $2]
- end
-
- def check_ns(tag_name, prefix, ns, require_uri, ignore_unknown_element=nil)
- if _ns(ns, prefix) == require_uri
- true
- else
- if ignore_unknown_element.nil?
- ignore_unknown_element = @ignore_unknown_element
- end
-
- if ignore_unknown_element
- false
- elsif @do_validate
- raise NSError.new(tag_name, prefix, require_uri)
- else
- # Force bind required URI with prefix
- @ns_stack.last[prefix] = require_uri
- true
- end
- end
- end
-
- def start_get_text_element(tag_name, prefix, ns, required_uri)
- pr = Proc.new do |text, tags|
- setter = self.class.setter(required_uri, tag_name)
- if setter and @last_element.respond_to?(setter)
- if @do_validate
- getter = self.class.getter(required_uri, tag_name)
- if @last_element.__send__(getter)
- raise TooMuchTagError.new(tag_name, @last_element.tag_name)
- end
- end
- @last_element.__send__(setter, text.to_s)
- else
- if @do_validate and !@ignore_unknown_element
- raise NotExpectedTagError.new(tag_name, _ns(ns, prefix),
- @last_element.tag_name)
- end
- end
- end
- @proc_stack.push(pr)
- end
-
- def start_have_something_element(tag_name, prefix, attrs, ns, klass)
- if check_ns(tag_name, prefix, ns, klass.required_uri)
- attributes = collect_attributes(tag_name, prefix, attrs, ns, klass)
- @proc_stack.push(setup_next_element(tag_name, klass, attributes))
- else
- @proc_stack.push(setup_next_element_in_unknown_element)
- end
- end
-
- def collect_attributes(tag_name, prefix, attrs, ns, klass)
- attributes = {}
- klass.get_attributes.each do |a_name, a_uri, required, element_name|
- if a_uri.is_a?(String) or !a_uri.respond_to?(:include?)
- a_uri = [a_uri]
- end
- unless a_uri == [""]
- for prefix, uri in ns
- if a_uri.include?(uri)
- val = attrs["#{prefix}:#{a_name}"]
- break if val
- end
- end
- end
- if val.nil? and a_uri.include?("")
- val = attrs[a_name]
- end
-
- if @do_validate and required and val.nil?
- unless a_uri.include?("")
- for prefix, uri in ns
- if a_uri.include?(uri)
- a_name = "#{prefix}:#{a_name}"
- end
- end
- end
- raise MissingAttributeError.new(tag_name, a_name)
- end
-
- attributes[a_name] = val
- end
- attributes
- end
-
- def setup_next_element(tag_name, klass, attributes)
- previous = @last_element
- next_element = klass.new(@do_validate, attributes)
- previous.set_next_element(tag_name, next_element)
- @last_element = next_element
- @last_element.parent = previous if klass.need_parent?
- @xml_child_mode = @last_element.have_xml_content?
-
- Proc.new do |text, tags|
- p(@last_element.class) if DEBUG
- if @xml_child_mode
- @last_element.content = @xml_element.to_s
- xml_setter = @last_element.class.xml_setter
- @last_element.__send__(xml_setter, @xml_element)
- @xml_element = nil
- @xml_child_mode = false
- else
- if klass.have_content?
- if @last_element.need_base64_encode?
- text = text.lstrip.unpack("m").first
- end
- @last_element.content = text
- end
- end
- if @do_validate
- @last_element.validate_for_stream(tags, @ignore_unknown_element)
- end
- @last_element = previous
- end
- end
-
- def setup_next_element_in_unknown_element
- current_element, @last_element = @last_element, nil
- Proc.new {@last_element = current_element}
- end
- end
-
- unless const_defined? :AVAILABLE_PARSER_LIBRARIES
- # The list of all available libraries for parsing.
- AVAILABLE_PARSER_LIBRARIES = [
- ["rss/xmlparser", :XMLParserParser],
- ["rss/xmlscanner", :XMLScanParser],
- ["rss/rexmlparser", :REXMLParser],
- ]
- end
-
- # The list of all available parsers, in constant form.
- AVAILABLE_PARSERS = []
-
- AVAILABLE_PARSER_LIBRARIES.each do |lib, parser|
- begin
- require lib
- AVAILABLE_PARSERS.push(const_get(parser))
- rescue LoadError
- end
- end
-
- if AVAILABLE_PARSERS.empty?
- raise XMLParserNotFound
- end
-end
diff --git a/lib/rss/rexmlparser.rb b/lib/rss/rexmlparser.rb
deleted file mode 100644
index ef0595e447..0000000000
--- a/lib/rss/rexmlparser.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: false
-require "rexml/document"
-require "rexml/streamlistener"
-
-module RSS
-
- class REXMLParser < BaseParser
-
- class << self
- def listener
- REXMLListener
- end
- end
-
- private
- def _parse
- begin
- REXML::Document.parse_stream(@rss, @listener)
- rescue RuntimeError => e
- raise NotWellFormedError.new{e.message}
- rescue REXML::ParseException => e
- context = e.context
- line = context[0] if context
- raise NotWellFormedError.new(line){e.message}
- end
- end
-
- end
-
- class REXMLListener < BaseListener
-
- include REXML::StreamListener
- include ListenerMixin
-
- class << self
- def raise_for_undefined_entity?
- false
- end
- end
-
- def xmldecl(version, encoding, standalone)
- super(version, encoding, standalone == "yes")
- # Encoding is converted to UTF-8 when REXML parse XML.
- @encoding = 'UTF-8'
- end
-
- alias_method(:cdata, :text)
- end
-
-end
diff --git a/lib/rss/rss.gemspec b/lib/rss/rss.gemspec
deleted file mode 100644
index 04f2b2f42d..0000000000
--- a/lib/rss/rss.gemspec
+++ /dev/null
@@ -1,80 +0,0 @@
-begin
- require_relative "lib/rss/version"
-rescue LoadError
- # for Ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "rss"
- spec.version = RSS::VERSION
- spec.authors = ["Kouhei Sutou"]
- spec.email = ["kou@cozmixng.org"]
-
- spec.summary = %q{Family of libraries that support various formats of XML "feeds".}
- spec.description = %q{Family of libraries that support various formats of XML "feeds".}
- spec.homepage = "https://github.com/ruby/rss"
- spec.license = "BSD-2-Clause"
-
- spec.files = [
- ".gitignore",
- ".travis.yml",
- "Gemfile",
- "LICENSE.txt",
- "NEWS.md",
- "README.md",
- "Rakefile",
- "lib/rss.rb",
- "lib/rss/0.9.rb",
- "lib/rss/1.0.rb",
- "lib/rss/2.0.rb",
- "lib/rss/atom.rb",
- "lib/rss/content.rb",
- "lib/rss/content/1.0.rb",
- "lib/rss/content/2.0.rb",
- "lib/rss/converter.rb",
- "lib/rss/dublincore.rb",
- "lib/rss/dublincore/1.0.rb",
- "lib/rss/dublincore/2.0.rb",
- "lib/rss/dublincore/atom.rb",
- "lib/rss/image.rb",
- "lib/rss/itunes.rb",
- "lib/rss/maker.rb",
- "lib/rss/maker/0.9.rb",
- "lib/rss/maker/1.0.rb",
- "lib/rss/maker/2.0.rb",
- "lib/rss/maker/atom.rb",
- "lib/rss/maker/base.rb",
- "lib/rss/maker/content.rb",
- "lib/rss/maker/dublincore.rb",
- "lib/rss/maker/entry.rb",
- "lib/rss/maker/feed.rb",
- "lib/rss/maker/image.rb",
- "lib/rss/maker/itunes.rb",
- "lib/rss/maker/slash.rb",
- "lib/rss/maker/syndication.rb",
- "lib/rss/maker/taxonomy.rb",
- "lib/rss/maker/trackback.rb",
- "lib/rss/parser.rb",
- "lib/rss/rexmlparser.rb",
- "lib/rss/rss.rb",
- "lib/rss/slash.rb",
- "lib/rss/syndication.rb",
- "lib/rss/taxonomy.rb",
- "lib/rss/trackback.rb",
- "lib/rss/utils.rb",
- "lib/rss/version.rb",
- "lib/rss/xml-stylesheet.rb",
- "lib/rss/xml.rb",
- "lib/rss/xmlparser.rb",
- "lib/rss/xmlscanner.rb",
- "rss.gemspec",
- ]
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-
- spec.add_development_dependency "bundler"
- spec.add_development_dependency "rake"
- spec.add_development_dependency "test-unit"
-end
diff --git a/lib/rss/rss.rb b/lib/rss/rss.rb
deleted file mode 100644
index daa0837e9c..0000000000
--- a/lib/rss/rss.rb
+++ /dev/null
@@ -1,1342 +0,0 @@
-# frozen_string_literal: false
-require "time"
-
-class Time
- class << self
- unless respond_to?(:w3cdtf)
- # This method converts a W3CDTF string date/time format to Time object.
- #
- # The W3CDTF format is defined here: http://www.w3.org/TR/NOTE-datetime
- #
- # Time.w3cdtf('2003-02-15T13:50:05-05:00')
- # # => 2003-02-15 10:50:05 -0800
- # Time.w3cdtf('2003-02-15T13:50:05-05:00').class
- # # => Time
- def w3cdtf(date)
- if /\A\s*
- (-?\d+)-(\d\d)-(\d\d)
- (?:T
- (\d\d):(\d\d)(?::(\d\d))?
- (\.\d+)?
- (Z|[+-]\d\d:\d\d)?)?
- \s*\z/ix =~ date and (($5 and $8) or (!$5 and !$8))
- datetime = [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i]
- usec = 0
- usec = $7.to_f * 1000000 if $7
- zone = $8
- if zone
- off = zone_offset(zone, datetime[0])
- datetime = apply_offset(*(datetime + [off]))
- datetime << usec
- time = Time.utc(*datetime)
- force_zone!(time, zone, off)
- time
- else
- datetime << usec
- Time.local(*datetime)
- end
- else
- raise ArgumentError.new("invalid date: #{date.inspect}")
- end
- end
- end
- end
-
- unless method_defined?(:w3cdtf)
- # This method converts a Time object to a String. The String contains the
- # time in W3CDTF date/time format.
- #
- # The W3CDTF format is defined here: http://www.w3.org/TR/NOTE-datetime
- #
- # Time.now.w3cdtf
- # # => "2013-08-26T14:12:10.817124-07:00"
- def w3cdtf
- if usec.zero?
- fraction_digits = 0
- else
- fraction_digits = strftime('%6N').index(/0*\z/)
- end
- xmlschema(fraction_digits)
- end
- end
-end
-
-
-require "English"
-require_relative "utils"
-require_relative "converter"
-require_relative "xml-stylesheet"
-
-module RSS
- # The URI of the RSS 1.0 specification
- URI = "http://purl.org/rss/1.0/"
-
- DEBUG = false # :nodoc:
-
- # The basic error all other RSS errors stem from. Rescue this error if you
- # want to handle any given RSS error and you don't care about the details.
- class Error < StandardError; end
-
- # RSS, being an XML-based format, has namespace support. If two namespaces are
- # declared with the same name, an OverlappedPrefixError will be raised.
- class OverlappedPrefixError < Error
- attr_reader :prefix
- def initialize(prefix)
- @prefix = prefix
- end
- end
-
- # The InvalidRSSError error is the base class for a variety of errors
- # related to a poorly-formed RSS feed. Rescue this error if you only
- # care that a file could be invalid, but don't care how it is invalid.
- class InvalidRSSError < Error; end
-
- # Since RSS is based on XML, it must have opening and closing tags that
- # match. If they don't, a MissingTagError will be raised.
- class MissingTagError < InvalidRSSError
- attr_reader :tag, :parent
- def initialize(tag, parent)
- @tag, @parent = tag, parent
- super("tag <#{tag}> is missing in tag <#{parent}>")
- end
- end
-
- # Some tags must only exist a specific number of times in a given RSS feed.
- # If a feed has too many occurrences of one of these tags, a TooMuchTagError
- # will be raised.
- class TooMuchTagError < InvalidRSSError
- attr_reader :tag, :parent
- def initialize(tag, parent)
- @tag, @parent = tag, parent
- super("tag <#{tag}> is too much in tag <#{parent}>")
- end
- end
-
- # Certain attributes are required on specific tags in an RSS feed. If a feed
- # is missing one of these attributes, a MissingAttributeError is raised.
- class MissingAttributeError < InvalidRSSError
- attr_reader :tag, :attribute
- def initialize(tag, attribute)
- @tag, @attribute = tag, attribute
- super("attribute <#{attribute}> is missing in tag <#{tag}>")
- end
- end
-
- # RSS does not allow for free-form tag names, so if an RSS feed contains a
- # tag that we don't know about, an UnknownTagError is raised.
- class UnknownTagError < InvalidRSSError
- attr_reader :tag, :uri
- def initialize(tag, uri)
- @tag, @uri = tag, uri
- super("tag <#{tag}> is unknown in namespace specified by uri <#{uri}>")
- end
- end
-
- # Raised when an unexpected tag is encountered.
- class NotExpectedTagError < InvalidRSSError
- attr_reader :tag, :uri, :parent
- def initialize(tag, uri, parent)
- @tag, @uri, @parent = tag, uri, parent
- super("tag <{#{uri}}#{tag}> is not expected in tag <#{parent}>")
- end
- end
- # For backward compatibility :X
- NotExceptedTagError = NotExpectedTagError # :nodoc:
-
- # Attributes are in key-value form, and if there's no value provided for an
- # attribute, a NotAvailableValueError will be raised.
- class NotAvailableValueError < InvalidRSSError
- attr_reader :tag, :value, :attribute
- def initialize(tag, value, attribute=nil)
- @tag, @value, @attribute = tag, value, attribute
- message = "value <#{value}> of "
- message << "attribute <#{attribute}> of " if attribute
- message << "tag <#{tag}> is not available."
- super(message)
- end
- end
-
- # Raised when an unknown conversion error occurs.
- class UnknownConversionMethodError < Error
- attr_reader :to, :from
- def initialize(to, from)
- @to = to
- @from = from
- super("can't convert to #{to} from #{from}.")
- end
- end
- # for backward compatibility
- UnknownConvertMethod = UnknownConversionMethodError # :nodoc:
-
- # Raised when a conversion failure occurs.
- class ConversionError < Error
- attr_reader :string, :to, :from
- def initialize(string, to, from)
- @string = string
- @to = to
- @from = from
- super("can't convert #{@string} to #{to} from #{from}.")
- end
- end
-
- # Raised when a required variable is not set.
- class NotSetError < Error
- attr_reader :name, :variables
- def initialize(name, variables)
- @name = name
- @variables = variables
- super("required variables of #{@name} are not set: #{@variables.join(', ')}")
- end
- end
-
- # Raised when a RSS::Maker attempts to use an unknown maker.
- class UnsupportedMakerVersionError < Error
- attr_reader :version
- def initialize(version)
- @version = version
- super("Maker doesn't support version: #{@version}")
- end
- end
-
- module BaseModel
- include Utils
-
- def install_have_child_element(tag_name, uri, occurs, name=nil, type=nil)
- name ||= tag_name
- add_need_initialize_variable(name)
- install_model(tag_name, uri, occurs, name)
-
- writer_type, reader_type = type
- def_corresponded_attr_writer name, writer_type
- def_corresponded_attr_reader name, reader_type
- install_element(name) do |n, elem_name|
- <<-EOC
- if @#{n}
- "\#{@#{n}.to_s(need_convert, indent)}"
- else
- ''
- end
-EOC
- end
- end
- alias_method(:install_have_attribute_element, :install_have_child_element)
-
- def install_have_children_element(tag_name, uri, occurs, name=nil, plural_name=nil)
- name ||= tag_name
- plural_name ||= "#{name}s"
- add_have_children_element(name, plural_name)
- add_plural_form(name, plural_name)
- install_model(tag_name, uri, occurs, plural_name, true)
-
- def_children_accessor(name, plural_name)
- install_element(name, "s") do |n, elem_name|
- <<-EOC
- rv = []
- @#{n}.each do |x|
- value = "\#{x.to_s(need_convert, indent)}"
- rv << value if /\\A\\s*\\z/ !~ value
- end
- rv.join("\n")
-EOC
- end
- end
-
- def install_text_element(tag_name, uri, occurs, name=nil, type=nil,
- disp_name=nil)
- name ||= tag_name
- disp_name ||= name
- self::ELEMENTS << name unless self::ELEMENTS.include?(name)
- add_need_initialize_variable(name)
- install_model(tag_name, uri, occurs, name)
-
- def_corresponded_attr_writer(name, type, disp_name)
- def_corresponded_attr_reader(name, type || :convert)
- install_element(name) do |n, elem_name|
- <<-EOC
- if respond_to?(:#{n}_content)
- content = #{n}_content
- else
- content = @#{n}
- end
- if content
- rv = "\#{indent}<#{elem_name}>"
- value = html_escape(content)
- if need_convert
- rv << convert(value)
- else
- rv << value
- end
- rv << "</#{elem_name}>"
- rv
- else
- ''
- end
-EOC
- end
- end
-
- def install_date_element(tag_name, uri, occurs, name=nil, type=nil, disp_name=nil)
- name ||= tag_name
- type ||= :w3cdtf
- disp_name ||= name
- self::ELEMENTS << name
- add_need_initialize_variable(name)
- install_model(tag_name, uri, occurs, name)
-
- # accessor
- convert_attr_reader name
- date_writer(name, type, disp_name)
-
- install_element(name) do |n, elem_name|
- <<-EOC
- if @#{n}
- rv = "\#{indent}<#{elem_name}>"
- value = html_escape(@#{n}.#{type})
- if need_convert
- rv << convert(value)
- else
- rv << value
- end
- rv << "</#{elem_name}>"
- rv
- else
- ''
- end
-EOC
- end
-
- end
-
- private
- def install_element(name, postfix="")
- elem_name = name.sub('_', ':')
- method_name = "#{name}_element#{postfix}"
- add_to_element_method(method_name)
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{method_name}(need_convert=true, indent='')
- #{yield(name, elem_name)}
- end
- private :#{method_name}
-EOC
- end
-
- def inherit_convert_attr_reader(*attrs)
- attrs.each do |attr|
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{attr}_without_inherit
- convert(@#{attr})
- end
-
- def #{attr}
- if @#{attr}
- #{attr}_without_inherit
- elsif @parent
- @parent.#{attr}
- else
- nil
- end
- end
-EOC
- end
- end
-
- def uri_convert_attr_reader(*attrs)
- attrs.each do |attr|
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{attr}_without_base
- convert(@#{attr})
- end
-
- def #{attr}
- value = #{attr}_without_base
- return nil if value.nil?
- if /\\A[a-z][a-z0-9+.\\-]*:/i =~ value
- value
- else
- "\#{base}\#{value}"
- end
- end
-EOC
- end
- end
-
- def convert_attr_reader(*attrs)
- attrs.each do |attr|
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{attr}
- convert(@#{attr})
- end
-EOC
- end
- end
-
- def explicit_clean_other_attr_reader(*attrs)
- attrs.each do |attr|
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- attr_reader(:#{attr})
- def #{attr}?
- ExplicitCleanOther.parse(@#{attr})
- end
- EOC
- end
- end
-
- def yes_other_attr_reader(*attrs)
- attrs.each do |attr|
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- attr_reader(:#{attr})
- def #{attr}?
- Utils::YesOther.parse(@#{attr})
- end
- EOC
- end
- end
-
- def csv_attr_reader(*attrs)
- separator = nil
- if attrs.last.is_a?(Hash)
- options = attrs.pop
- separator = options[:separator]
- end
- separator ||= ", "
- attrs.each do |attr|
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- attr_reader(:#{attr})
- def #{attr}_content
- if @#{attr}.nil?
- @#{attr}
- else
- @#{attr}.join(#{separator.dump})
- end
- end
- EOC
- end
- end
-
- def date_writer(name, type, disp_name=name)
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{name}=(new_value)
- if new_value.nil?
- @#{name} = new_value
- elsif new_value.kind_of?(Time)
- @#{name} = new_value.dup
- else
- if @do_validate
- begin
- @#{name} = Time.__send__('#{type}', new_value)
- rescue ArgumentError
- raise NotAvailableValueError.new('#{disp_name}', new_value)
- end
- else
- @#{name} = nil
- if /\\A\\s*\\z/ !~ new_value.to_s
- begin
- unless Date._parse(new_value, false).empty?
- @#{name} = Time.parse(new_value)
- end
- rescue ArgumentError
- end
- end
- end
- end
-
- # Is it need?
- if @#{name}
- class << @#{name}
- undef_method(:to_s)
- alias_method(:to_s, :#{type})
- end
- end
-
- end
-EOC
- end
-
- def integer_writer(name, disp_name=name)
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{name}=(new_value)
- if new_value.nil?
- @#{name} = new_value
- else
- if @do_validate
- begin
- @#{name} = Integer(new_value)
- rescue ArgumentError
- raise NotAvailableValueError.new('#{disp_name}', new_value)
- end
- else
- @#{name} = new_value.to_i
- end
- end
- end
-EOC
- end
-
- def positive_integer_writer(name, disp_name=name)
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{name}=(new_value)
- if new_value.nil?
- @#{name} = new_value
- else
- if @do_validate
- begin
- tmp = Integer(new_value)
- raise ArgumentError if tmp <= 0
- @#{name} = tmp
- rescue ArgumentError
- raise NotAvailableValueError.new('#{disp_name}', new_value)
- end
- else
- @#{name} = new_value.to_i
- end
- end
- end
-EOC
- end
-
- def boolean_writer(name, disp_name=name)
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{name}=(new_value)
- if new_value.nil?
- @#{name} = new_value
- else
- if @do_validate and
- ![true, false, "true", "false"].include?(new_value)
- raise NotAvailableValueError.new('#{disp_name}', new_value)
- end
- if [true, false].include?(new_value)
- @#{name} = new_value
- else
- @#{name} = new_value == "true"
- end
- end
- end
-EOC
- end
-
- def text_type_writer(name, disp_name=name)
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{name}=(new_value)
- if @do_validate and
- !["text", "html", "xhtml", nil].include?(new_value)
- raise NotAvailableValueError.new('#{disp_name}', new_value)
- end
- @#{name} = new_value
- end
-EOC
- end
-
- def content_writer(name, disp_name=name)
- klass_name = "self.class::#{Utils.to_class_name(name)}"
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{name}=(new_value)
- if new_value.is_a?(#{klass_name})
- @#{name} = new_value
- else
- @#{name} = #{klass_name}.new
- @#{name}.content = new_value
- end
- end
-EOC
- end
-
- def explicit_clean_other_writer(name, disp_name=name)
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def #{name}=(value)
- value = (value ? "yes" : "no") if [true, false].include?(value)
- @#{name} = value
- end
- EOC
- end
-
- def yes_other_writer(name, disp_name=name)
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def #{name}=(new_value)
- if [true, false].include?(new_value)
- new_value = new_value ? "yes" : "no"
- end
- @#{name} = new_value
- end
- EOC
- end
-
- def csv_writer(name, disp_name=name)
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def #{name}=(new_value)
- @#{name} = Utils::CSV.parse(new_value)
- end
- EOC
- end
-
- def csv_integer_writer(name, disp_name=name)
- module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- def #{name}=(new_value)
- @#{name} = Utils::CSV.parse(new_value) {|v| Integer(v)}
- end
- EOC
- end
-
- def def_children_accessor(accessor_name, plural_name)
- module_eval(<<-EOC, *get_file_and_line_from_caller(2))
- def #{plural_name}
- @#{accessor_name}
- end
-
- def #{accessor_name}(*args)
- if args.empty?
- @#{accessor_name}.first
- else
- @#{accessor_name}[*args]
- end
- end
-
- def #{accessor_name}=(*args)
- receiver = self.class.name
- warn("Don't use `\#{receiver}\##{accessor_name} = XXX'/" \
- "`\#{receiver}\#set_#{accessor_name}(XXX)'. " \
- "Those APIs are not sense of Ruby. " \
- "Use `\#{receiver}\##{plural_name} << XXX' instead of them.", uplevel: 1)
- if args.size == 1
- @#{accessor_name}.push(args[0])
- else
- @#{accessor_name}.__send__("[]=", *args)
- end
- end
- alias_method(:set_#{accessor_name}, :#{accessor_name}=)
-EOC
- end
- end
-
- module SetupMaker
- def setup_maker(maker)
- target = maker_target(maker)
- unless target.nil?
- setup_maker_attributes(target)
- setup_maker_element(target)
- setup_maker_elements(target)
- end
- end
-
- private
- def maker_target(maker)
- nil
- end
-
- def setup_maker_attributes(target)
- end
-
- def setup_maker_element(target)
- self.class.need_initialize_variables.each do |var|
- value = __send__(var)
- next if value.nil?
- if value.respond_to?("setup_maker") and
- !not_need_to_call_setup_maker_variables.include?(var)
- value.setup_maker(target)
- else
- setter = "#{var}="
- if target.respond_to?(setter)
- target.__send__(setter, value)
- end
- end
- end
- end
-
- def not_need_to_call_setup_maker_variables
- []
- end
-
- def setup_maker_elements(parent)
- self.class.have_children_elements.each do |name, plural_name|
- if parent.respond_to?(plural_name)
- target = parent.__send__(plural_name)
- __send__(plural_name).each do |elem|
- elem.setup_maker(target)
- end
- end
- end
- end
- end
-
- class Element
- extend BaseModel
- include Utils
- extend Utils::InheritedReader
- include SetupMaker
-
- INDENT = " "
-
- MUST_CALL_VALIDATORS = {}
- MODELS = []
- GET_ATTRIBUTES = []
- HAVE_CHILDREN_ELEMENTS = []
- TO_ELEMENT_METHODS = []
- NEED_INITIALIZE_VARIABLES = []
- PLURAL_FORMS = {}
-
- class << self
- def must_call_validators
- inherited_hash_reader("MUST_CALL_VALIDATORS")
- end
- def models
- inherited_array_reader("MODELS")
- end
- def get_attributes
- inherited_array_reader("GET_ATTRIBUTES")
- end
- def have_children_elements
- inherited_array_reader("HAVE_CHILDREN_ELEMENTS")
- end
- def to_element_methods
- inherited_array_reader("TO_ELEMENT_METHODS")
- end
- def need_initialize_variables
- inherited_array_reader("NEED_INITIALIZE_VARIABLES")
- end
- def plural_forms
- inherited_hash_reader("PLURAL_FORMS")
- end
-
- def inherited_base
- ::RSS::Element
- end
-
- def inherited(klass)
- klass.const_set(:MUST_CALL_VALIDATORS, {})
- klass.const_set(:MODELS, [])
- klass.const_set(:GET_ATTRIBUTES, [])
- klass.const_set(:HAVE_CHILDREN_ELEMENTS, [])
- klass.const_set(:TO_ELEMENT_METHODS, [])
- klass.const_set(:NEED_INITIALIZE_VARIABLES, [])
- klass.const_set(:PLURAL_FORMS, {})
-
- tag_name = klass.name.split(/::/).last
- tag_name[0, 1] = tag_name[0, 1].downcase
- klass.instance_variable_set(:@tag_name, tag_name)
- klass.instance_variable_set(:@have_content, false)
- end
-
- def install_must_call_validator(prefix, uri)
- self::MUST_CALL_VALIDATORS[uri] = prefix
- end
-
- def install_model(tag, uri, occurs=nil, getter=nil, plural=false)
- getter ||= tag
- if m = self::MODELS.find {|t, u, o, g, p| t == tag and u == uri}
- m[2] = occurs
- else
- self::MODELS << [tag, uri, occurs, getter, plural]
- end
- end
-
- def install_get_attribute(name, uri, required=true,
- type=nil, disp_name=nil,
- element_name=nil)
- disp_name ||= name
- element_name ||= name
- writer_type, reader_type = type
- def_corresponded_attr_writer name, writer_type, disp_name
- def_corresponded_attr_reader name, reader_type
- if type == :boolean and /^is/ =~ name
- alias_method "#{$POSTMATCH}?", name
- end
- self::GET_ATTRIBUTES << [name, uri, required, element_name]
- add_need_initialize_variable(disp_name)
- end
-
- def def_corresponded_attr_writer(name, type=nil, disp_name=nil)
- disp_name ||= name
- case type
- when :integer
- integer_writer name, disp_name
- when :positive_integer
- positive_integer_writer name, disp_name
- when :boolean
- boolean_writer name, disp_name
- when :w3cdtf, :rfc822, :rfc2822
- date_writer name, type, disp_name
- when :text_type
- text_type_writer name, disp_name
- when :content
- content_writer name, disp_name
- when :explicit_clean_other
- explicit_clean_other_writer name, disp_name
- when :yes_other
- yes_other_writer name, disp_name
- when :csv
- csv_writer name
- when :csv_integer
- csv_integer_writer name
- else
- attr_writer name
- end
- end
-
- def def_corresponded_attr_reader(name, type=nil)
- case type
- when :inherit
- inherit_convert_attr_reader name
- when :uri
- uri_convert_attr_reader name
- when :explicit_clean_other
- explicit_clean_other_attr_reader name
- when :yes_other
- yes_other_attr_reader name
- when :csv
- csv_attr_reader name
- when :csv_integer
- csv_attr_reader name, :separator => ","
- else
- convert_attr_reader name
- end
- end
-
- def content_setup(type=nil, disp_name=nil)
- writer_type, reader_type = type
- def_corresponded_attr_writer :content, writer_type, disp_name
- def_corresponded_attr_reader :content, reader_type
- @have_content = true
- end
-
- def have_content?
- @have_content
- end
-
- def add_have_children_element(variable_name, plural_name)
- self::HAVE_CHILDREN_ELEMENTS << [variable_name, plural_name]
- end
-
- def add_to_element_method(method_name)
- self::TO_ELEMENT_METHODS << method_name
- end
-
- def add_need_initialize_variable(variable_name)
- self::NEED_INITIALIZE_VARIABLES << variable_name
- end
-
- def add_plural_form(singular, plural)
- self::PLURAL_FORMS[singular] = plural
- end
-
- def required_prefix
- nil
- end
-
- def required_uri
- ""
- end
-
- def need_parent?
- false
- end
-
- def install_ns(prefix, uri)
- if self::NSPOOL.has_key?(prefix)
- raise OverlappedPrefixError.new(prefix)
- end
- self::NSPOOL[prefix] = uri
- end
-
- def tag_name
- @tag_name
- end
- end
-
- attr_accessor :parent, :do_validate
-
- def initialize(do_validate=true, attrs=nil)
- @parent = nil
- @converter = nil
- if attrs.nil? and (do_validate.is_a?(Hash) or do_validate.is_a?(Array))
- do_validate, attrs = true, do_validate
- end
- @do_validate = do_validate
- initialize_variables(attrs || {})
- end
-
- def tag_name
- self.class.tag_name
- end
-
- def full_name
- tag_name
- end
-
- def converter=(converter)
- @converter = converter
- targets = children.dup
- self.class.have_children_elements.each do |variable_name, plural_name|
- targets.concat(__send__(plural_name))
- end
- targets.each do |target|
- target.converter = converter unless target.nil?
- end
- end
-
- def convert(value)
- if @converter
- @converter.convert(value)
- else
- value
- end
- end
-
- def valid?(ignore_unknown_element=true)
- validate(ignore_unknown_element)
- true
- rescue RSS::Error
- false
- end
-
- def validate(ignore_unknown_element=true)
- do_validate = @do_validate
- @do_validate = true
- validate_attribute
- __validate(ignore_unknown_element)
- ensure
- @do_validate = do_validate
- end
-
- def validate_for_stream(tags, ignore_unknown_element=true)
- validate_attribute
- __validate(ignore_unknown_element, tags, false)
- end
-
- def to_s(need_convert=true, indent='')
- if self.class.have_content?
- return "" if !empty_content? and !content_is_set?
- rv = tag(indent) do |next_indent|
- if empty_content?
- ""
- else
- xmled_content
- end
- end
- else
- rv = tag(indent) do |next_indent|
- self.class.to_element_methods.collect do |method_name|
- __send__(method_name, false, next_indent)
- end
- end
- end
- rv = convert(rv) if need_convert
- rv
- end
-
- def have_xml_content?
- false
- end
-
- def need_base64_encode?
- false
- end
-
- def set_next_element(tag_name, next_element)
- klass = next_element.class
- prefix = ""
- prefix << "#{klass.required_prefix}_" if klass.required_prefix
- key = "#{prefix}#{tag_name.gsub(/-/, '_')}"
- if self.class.plural_forms.has_key?(key)
- ary = __send__("#{self.class.plural_forms[key]}")
- ary << next_element
- else
- __send__("#{key}=", next_element)
- end
- end
-
- protected
- def have_required_elements?
- self.class::MODELS.all? do |tag, uri, occurs, getter|
- if occurs.nil? or occurs == "+"
- child = __send__(getter)
- if child.is_a?(Array)
- children = child
- children.any? {|c| c.have_required_elements?}
- else
- not child.nil?
- end
- else
- true
- end
- end
- end
-
- private
- def initialize_variables(attrs)
- normalized_attrs = {}
- attrs.each do |key, value|
- normalized_attrs[key.to_s] = value
- end
- self.class.need_initialize_variables.each do |variable_name|
- value = normalized_attrs[variable_name.to_s]
- if value
- __send__("#{variable_name}=", value)
- else
- instance_variable_set("@#{variable_name}", nil)
- end
- end
- initialize_have_children_elements
- @content = normalized_attrs["content"] if self.class.have_content?
- end
-
- def initialize_have_children_elements
- self.class.have_children_elements.each do |variable_name, plural_name|
- instance_variable_set("@#{variable_name}", [])
- end
- end
-
- def tag(indent, additional_attrs={}, &block)
- next_indent = indent + INDENT
-
- attrs = collect_attrs
- return "" if attrs.nil?
-
- return "" unless have_required_elements?
-
- attrs.update(additional_attrs)
- start_tag = make_start_tag(indent, next_indent, attrs.dup)
-
- if block
- content = block.call(next_indent)
- else
- content = []
- end
-
- if content.is_a?(String)
- content = [content]
- start_tag << ">"
- end_tag = "</#{full_name}>"
- else
- content = content.reject{|x| x.empty?}
- if content.empty?
- return "" if attrs.empty?
- end_tag = "/>"
- else
- start_tag << ">\n"
- end_tag = "\n#{indent}</#{full_name}>"
- end
- end
-
- start_tag + content.join("\n") + end_tag
- end
-
- def make_start_tag(indent, next_indent, attrs)
- start_tag = ["#{indent}<#{full_name}"]
- unless attrs.empty?
- start_tag << attrs.collect do |key, value|
- %Q[#{h key}="#{h value}"]
- end.join("\n#{next_indent}")
- end
- start_tag.join(" ")
- end
-
- def collect_attrs
- attrs = {}
- _attrs.each do |name, required, alias_name|
- value = __send__(alias_name || name)
- return nil if required and value.nil?
- next if value.nil?
- return nil if attrs.has_key?(name)
- attrs[name] = value
- end
- attrs
- end
-
- def tag_name_with_prefix(prefix)
- "#{prefix}:#{tag_name}"
- end
-
- # For backward compatibility
- def calc_indent
- ''
- end
-
- def children
- rv = []
- self.class.models.each do |name, uri, occurs, getter|
- value = __send__(getter)
- next if value.nil?
- value = [value] unless value.is_a?(Array)
- value.each do |v|
- rv << v if v.is_a?(Element)
- end
- end
- rv
- end
-
- def _tags
- rv = []
- self.class.models.each do |name, uri, occurs, getter, plural|
- value = __send__(getter)
- next if value.nil?
- if plural and value.is_a?(Array)
- rv.concat([[uri, name]] * value.size)
- else
- rv << [uri, name]
- end
- end
- rv
- end
-
- def _attrs
- self.class.get_attributes.collect do |name, uri, required, element_name|
- [element_name, required, name]
- end
- end
-
- def __validate(ignore_unknown_element, tags=_tags, recursive=true)
- if recursive
- children.compact.each do |child|
- child.validate
- end
- end
- must_call_validators = self.class.must_call_validators
- tags = tag_filter(tags.dup)
- p tags if DEBUG
- must_call_validators.each do |uri, prefix|
- _validate(ignore_unknown_element, tags[uri], uri)
- meth = "#{prefix}_validate"
- if !prefix.empty? and respond_to?(meth, true)
- __send__(meth, ignore_unknown_element, tags[uri], uri)
- end
- end
- end
-
- def validate_attribute
- _attrs.each do |a_name, required, alias_name|
- value = instance_variable_get("@#{alias_name || a_name}")
- if required and value.nil?
- raise MissingAttributeError.new(tag_name, a_name)
- end
- __send__("#{alias_name || a_name}=", value)
- end
- end
-
- def _validate(ignore_unknown_element, tags, uri, models=self.class.models)
- count = 1
- do_redo = false
- not_shift = false
- tag = nil
- models = models.find_all {|model| model[1] == uri}
- element_names = models.collect {|model| model[0]}
- if tags
- tags_size = tags.size
- tags = tags.sort_by {|x| element_names.index(x) || tags_size}
- end
-
- models.each_with_index do |model, i|
- name, _, occurs, = model
-
- if DEBUG
- p "before"
- p tags
- p model
- end
-
- if not_shift
- not_shift = false
- elsif tags
- tag = tags.shift
- end
-
- if DEBUG
- p "mid"
- p count
- end
-
- case occurs
- when '?'
- if count > 2
- raise TooMuchTagError.new(name, tag_name)
- else
- if name == tag
- do_redo = true
- else
- not_shift = true
- end
- end
- when '*'
- if name == tag
- do_redo = true
- else
- not_shift = true
- end
- when '+'
- if name == tag
- do_redo = true
- else
- if count > 1
- not_shift = true
- else
- raise MissingTagError.new(name, tag_name)
- end
- end
- else
- if name == tag
- if models[i+1] and models[i+1][0] != name and
- tags and tags.first == name
- raise TooMuchTagError.new(name, tag_name)
- end
- else
- raise MissingTagError.new(name, tag_name)
- end
- end
-
- if DEBUG
- p "after"
- p not_shift
- p do_redo
- p tag
- end
-
- if do_redo
- do_redo = false
- count += 1
- redo
- else
- count = 1
- end
-
- end
-
- if !ignore_unknown_element and !tags.nil? and !tags.empty?
- raise NotExpectedTagError.new(tags.first, uri, tag_name)
- end
-
- end
-
- def tag_filter(tags)
- rv = {}
- tags.each do |tag|
- rv[tag[0]] = [] unless rv.has_key?(tag[0])
- rv[tag[0]].push(tag[1])
- end
- rv
- end
-
- def empty_content?
- false
- end
-
- def content_is_set?
- if have_xml_content?
- __send__(self.class.xml_getter)
- else
- content
- end
- end
-
- def xmled_content
- if have_xml_content?
- __send__(self.class.xml_getter).to_s
- else
- _content = content
- _content = [_content].pack("m0") if need_base64_encode?
- h(_content)
- end
- end
- end
-
- module RootElementMixin
-
- include XMLStyleSheetMixin
-
- attr_reader :output_encoding
- attr_reader :feed_type, :feed_subtype, :feed_version
- attr_accessor :version, :encoding, :standalone
- def initialize(feed_version, version=nil, encoding=nil, standalone=nil)
- super()
- @feed_type = nil
- @feed_subtype = nil
- @feed_version = feed_version
- @version = version || '1.0'
- @encoding = encoding
- @standalone = standalone
- @output_encoding = nil
- end
-
- def feed_info
- [@feed_type, @feed_version, @feed_subtype]
- end
-
- def output_encoding=(enc)
- @output_encoding = enc
- self.converter = Converter.new(@output_encoding, @encoding)
- end
-
- def setup_maker(maker)
- maker.version = version
- maker.encoding = encoding
- maker.standalone = standalone
-
- xml_stylesheets.each do |xss|
- xss.setup_maker(maker)
- end
-
- super
- end
-
- def to_feed(type, &block)
- Maker.make(type) do |maker|
- setup_maker(maker)
- block.call(maker) if block
- end
- end
-
- def to_rss(type, &block)
- to_feed("rss#{type}", &block)
- end
-
- def to_atom(type, &block)
- to_feed("atom:#{type}", &block)
- end
-
- def to_xml(type=nil, &block)
- if type.nil? or same_feed_type?(type)
- to_s
- else
- to_feed(type, &block).to_s
- end
- end
-
- private
- def same_feed_type?(type)
- if /^(atom|rss)?(\d+\.\d+)?(?::(.+))?$/i =~ type
- feed_type = ($1 || @feed_type).downcase
- feed_version = $2 || @feed_version
- feed_subtype = $3 || @feed_subtype
- [feed_type, feed_version, feed_subtype] == feed_info
- else
- false
- end
- end
-
- def tag(indent, attrs={}, &block)
- rv = super(indent, ns_declarations.merge(attrs), &block)
- return rv if rv.empty?
- "#{xmldecl}#{xml_stylesheet_pi}#{rv}"
- end
-
- def xmldecl
- rv = %Q[<?xml version="#{@version}"]
- if @output_encoding or @encoding
- rv << %Q[ encoding="#{@output_encoding or @encoding}"]
- end
- rv << %Q[ standalone="yes"] if @standalone
- rv << "?>\n"
- rv
- end
-
- def ns_declarations
- decls = {}
- self.class::NSPOOL.collect do |prefix, uri|
- prefix = ":#{prefix}" unless prefix.empty?
- decls["xmlns#{prefix}"] = uri
- end
- decls
- end
-
- def maker_target(target)
- target
- end
- end
-end
diff --git a/lib/rss/slash.rb b/lib/rss/slash.rb
deleted file mode 100644
index 0055fc9f88..0000000000
--- a/lib/rss/slash.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: false
-require 'rss/1.0'
-
-module RSS
- # The prefix for the Slash XML namespace.
- SLASH_PREFIX = 'slash'
- # The URI of the Slash specification.
- SLASH_URI = "http://purl.org/rss/1.0/modules/slash/"
-
- RDF.install_ns(SLASH_PREFIX, SLASH_URI)
-
- module SlashModel
- extend BaseModel
-
- ELEMENT_INFOS = \
- [
- ["section"],
- ["department"],
- ["comments", :positive_integer],
- ["hit_parade", :csv_integer],
- ]
-
- class << self
- def append_features(klass)
- super
-
- return if klass.instance_of?(Module)
- klass.install_must_call_validator(SLASH_PREFIX, SLASH_URI)
- ELEMENT_INFOS.each do |name, type, *additional_infos|
- full_name = "#{SLASH_PREFIX}_#{name}"
- klass.install_text_element(full_name, SLASH_URI, "?",
- full_name, type, name)
- end
-
- klass.module_eval do
- alias_method(:slash_hit_parades, :slash_hit_parade)
- undef_method(:slash_hit_parade)
- alias_method(:slash_hit_parade, :slash_hit_parade_content)
- end
- end
- end
- end
-
- class RDF
- class Item; include SlashModel; end
- end
-
- SlashModel::ELEMENT_INFOS.each do |name, type|
- accessor_base = "#{SLASH_PREFIX}_#{name}"
- BaseListener.install_get_text_element(SLASH_URI, name, accessor_base)
- end
-end
diff --git a/lib/rss/syndication.rb b/lib/rss/syndication.rb
deleted file mode 100644
index 8f9620f9f3..0000000000
--- a/lib/rss/syndication.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: false
-require "rss/1.0"
-
-module RSS
- # The prefix for the Syndication XML namespace.
- SY_PREFIX = 'sy'
- # The URI of the Syndication specification.
- SY_URI = "http://purl.org/rss/1.0/modules/syndication/"
-
- RDF.install_ns(SY_PREFIX, SY_URI)
-
- module SyndicationModel
-
- extend BaseModel
-
- ELEMENTS = []
-
- def self.append_features(klass)
- super
-
- klass.install_must_call_validator(SY_PREFIX, SY_URI)
- klass.module_eval do
- [
- ["updatePeriod"],
- ["updateFrequency", :positive_integer]
- ].each do |name, type|
- install_text_element(name, SY_URI, "?",
- "#{SY_PREFIX}_#{name}", type,
- "#{SY_PREFIX}:#{name}")
- end
-
- %w(updateBase).each do |name|
- install_date_element(name, SY_URI, "?",
- "#{SY_PREFIX}_#{name}", 'w3cdtf',
- "#{SY_PREFIX}:#{name}")
- end
- end
-
- klass.module_eval(<<-EOC, __FILE__, __LINE__ + 1)
- alias_method(:_sy_updatePeriod=, :sy_updatePeriod=)
- def sy_updatePeriod=(new_value)
- new_value = new_value.strip
- validate_sy_updatePeriod(new_value) if @do_validate
- self._sy_updatePeriod = new_value
- end
- EOC
- end
-
- private
- SY_UPDATEPERIOD_AVAILABLE_VALUES = %w(hourly daily weekly monthly yearly)
- def validate_sy_updatePeriod(value) # :nodoc:
- unless SY_UPDATEPERIOD_AVAILABLE_VALUES.include?(value)
- raise NotAvailableValueError.new("updatePeriod", value)
- end
- end
- end
-
- class RDF
- class Channel; include SyndicationModel; end
- end
-
- prefix_size = SY_PREFIX.size + 1
- SyndicationModel::ELEMENTS.uniq!
- SyndicationModel::ELEMENTS.each do |full_name|
- name = full_name[prefix_size..-1]
- BaseListener.install_get_text_element(SY_URI, name, full_name)
- end
-
-end
diff --git a/lib/rss/taxonomy.rb b/lib/rss/taxonomy.rb
deleted file mode 100644
index 50688ee6c1..0000000000
--- a/lib/rss/taxonomy.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-# frozen_string_literal: false
-require "rss/1.0"
-require_relative "dublincore"
-
-module RSS
- # The prefix for the Taxonomy XML namespace.
- TAXO_PREFIX = "taxo"
- # The URI for the specification of the Taxonomy XML namespace.
- TAXO_URI = "http://purl.org/rss/1.0/modules/taxonomy/"
-
- RDF.install_ns(TAXO_PREFIX, TAXO_URI)
-
- # The listing of all the taxonomy elements, with the appropriate namespace.
- TAXO_ELEMENTS = []
-
- %w(link).each do |name|
- full_name = "#{TAXO_PREFIX}_#{name}"
- BaseListener.install_get_text_element(TAXO_URI, name, full_name)
- TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}"
- end
-
- %w(topic topics).each do |name|
- class_name = Utils.to_class_name(name)
- BaseListener.install_class_name(TAXO_URI, name, "Taxonomy#{class_name}")
- TAXO_ELEMENTS << "#{TAXO_PREFIX}_#{name}"
- end
-
- module TaxonomyTopicsModel
- extend BaseModel
-
- def self.append_features(klass)
- super
-
- klass.install_must_call_validator(TAXO_PREFIX, TAXO_URI)
- %w(topics).each do |name|
- klass.install_have_child_element(name, TAXO_URI, "?",
- "#{TAXO_PREFIX}_#{name}")
- end
- end
-
- class TaxonomyTopics < Element
- include RSS10
-
- Bag = ::RSS::RDF::Bag
-
- class << self
- def required_prefix
- TAXO_PREFIX
- end
-
- def required_uri
- TAXO_URI
- end
- end
-
- @tag_name = "topics"
-
- install_have_child_element("Bag", RDF::URI, nil)
- install_must_call_validator('rdf', RDF::URI)
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.Bag = args[0]
- end
- self.Bag ||= Bag.new
- end
-
- def full_name
- tag_name_with_prefix(TAXO_PREFIX)
- end
-
- def maker_target(target)
- target.taxo_topics
- end
-
- def resources
- if @Bag
- @Bag.lis.collect do |li|
- li.resource
- end
- else
- []
- end
- end
- end
- end
-
- module TaxonomyTopicModel
- extend BaseModel
-
- def self.append_features(klass)
- super
- var_name = "#{TAXO_PREFIX}_topic"
- klass.install_have_children_element("topic", TAXO_URI, "*", var_name)
- end
-
- class TaxonomyTopic < Element
- include RSS10
-
- include DublinCoreModel
- include TaxonomyTopicsModel
-
- class << self
- def required_prefix
- TAXO_PREFIX
- end
-
- def required_uri
- TAXO_URI
- end
- end
-
- @tag_name = "topic"
-
- install_get_attribute("about", ::RSS::RDF::URI, true, nil, nil,
- "#{RDF::PREFIX}:about")
- install_text_element("link", TAXO_URI, "?", "#{TAXO_PREFIX}_link")
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.about = args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(TAXO_PREFIX)
- end
-
- def maker_target(target)
- target.new_taxo_topic
- end
- end
- end
-
- class RDF
- include TaxonomyTopicModel
- class Channel
- include TaxonomyTopicsModel
- end
- class Item; include TaxonomyTopicsModel; end
- end
-end
diff --git a/lib/rss/trackback.rb b/lib/rss/trackback.rb
deleted file mode 100644
index 1a3c3849b5..0000000000
--- a/lib/rss/trackback.rb
+++ /dev/null
@@ -1,291 +0,0 @@
-# frozen_string_literal: false
-# This file contains the implementation of trackbacks. It is entirely internal
-# and not useful to outside developers.
-require 'rss/1.0'
-require 'rss/2.0'
-
-module RSS # :nodoc: all
-
- TRACKBACK_PREFIX = 'trackback'
- TRACKBACK_URI = 'http://madskills.com/public/xml/rss/module/trackback/'
-
- RDF.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI)
- Rss.install_ns(TRACKBACK_PREFIX, TRACKBACK_URI)
-
- module TrackBackUtils
- private
- def trackback_validate(ignore_unknown_element, tags, uri)
- return if tags.nil?
- if tags.find {|tag| tag == "about"} and
- !tags.find {|tag| tag == "ping"}
- raise MissingTagError.new("#{TRACKBACK_PREFIX}:ping", tag_name)
- end
- end
- end
-
- module BaseTrackBackModel
-
- ELEMENTS = %w(ping about)
-
- def append_features(klass)
- super
-
- unless klass.class == Module
- klass.module_eval {include TrackBackUtils}
-
- klass.install_must_call_validator(TRACKBACK_PREFIX, TRACKBACK_URI)
- %w(ping).each do |name|
- var_name = "#{TRACKBACK_PREFIX}_#{name}"
- klass_name = "TrackBack#{Utils.to_class_name(name)}"
- klass.install_have_child_element(name, TRACKBACK_URI, "?", var_name)
- klass.module_eval(<<-EOC, __FILE__, __LINE__)
- remove_method :#{var_name}
- def #{var_name}
- @#{var_name} and @#{var_name}.value
- end
-
- remove_method :#{var_name}=
- def #{var_name}=(value)
- @#{var_name} = Utils.new_with_value_if_need(#{klass_name}, value)
- end
- EOC
- end
-
- [%w(about s)].each do |name, postfix|
- var_name = "#{TRACKBACK_PREFIX}_#{name}"
- klass_name = "TrackBack#{Utils.to_class_name(name)}"
- klass.install_have_children_element(name, TRACKBACK_URI, "*",
- var_name)
- klass.module_eval(<<-EOC, __FILE__, __LINE__)
- remove_method :#{var_name}
- def #{var_name}(*args)
- if args.empty?
- @#{var_name}.first and @#{var_name}.first.value
- else
- ret = @#{var_name}.__send__("[]", *args)
- if ret.is_a?(Array)
- ret.collect {|x| x.value}
- else
- ret.value
- end
- end
- end
-
- remove_method :#{var_name}=
- remove_method :set_#{var_name}
- def #{var_name}=(*args)
- if args.size == 1
- item = Utils.new_with_value_if_need(#{klass_name}, args[0])
- @#{var_name}.push(item)
- else
- new_val = args.last
- if new_val.is_a?(Array)
- new_val = new_value.collect do |val|
- Utils.new_with_value_if_need(#{klass_name}, val)
- end
- else
- new_val = Utils.new_with_value_if_need(#{klass_name}, new_val)
- end
- @#{var_name}.__send__("[]=", *(args[0..-2] + [new_val]))
- end
- end
- alias set_#{var_name} #{var_name}=
- EOC
- end
- end
- end
- end
-
- module TrackBackModel10
- extend BaseModel
- extend BaseTrackBackModel
-
- class TrackBackPing < Element
- include RSS10
-
- class << self
-
- def required_prefix
- TRACKBACK_PREFIX
- end
-
- def required_uri
- TRACKBACK_URI
- end
-
- end
-
- @tag_name = "ping"
-
- [
- ["resource", ::RSS::RDF::URI, true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, nil, nil,
- "#{::RSS::RDF::PREFIX}:#{name}")
- end
-
- alias_method(:value, :resource)
- alias_method(:value=, :resource=)
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.resource = args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(TRACKBACK_PREFIX)
- end
- end
-
- class TrackBackAbout < Element
- include RSS10
-
- class << self
-
- def required_prefix
- TRACKBACK_PREFIX
- end
-
- def required_uri
- TRACKBACK_URI
- end
-
- end
-
- @tag_name = "about"
-
- [
- ["resource", ::RSS::RDF::URI, true]
- ].each do |name, uri, required|
- install_get_attribute(name, uri, required, nil, nil,
- "#{::RSS::RDF::PREFIX}:#{name}")
- end
-
- alias_method(:value, :resource)
- alias_method(:value=, :resource=)
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.resource = args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(TRACKBACK_PREFIX)
- end
-
- private
- def maker_target(abouts)
- abouts.new_about
- end
-
- def setup_maker_attributes(about)
- about.resource = self.resource
- end
-
- end
- end
-
- module TrackBackModel20
- extend BaseModel
- extend BaseTrackBackModel
-
- class TrackBackPing < Element
- include RSS09
-
- @tag_name = "ping"
-
- content_setup
-
- class << self
-
- def required_prefix
- TRACKBACK_PREFIX
- end
-
- def required_uri
- TRACKBACK_URI
- end
-
- end
-
- alias_method(:value, :content)
- alias_method(:value=, :content=)
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.content = args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(TRACKBACK_PREFIX)
- end
-
- end
-
- class TrackBackAbout < Element
- include RSS09
-
- @tag_name = "about"
-
- content_setup
-
- class << self
-
- def required_prefix
- TRACKBACK_PREFIX
- end
-
- def required_uri
- TRACKBACK_URI
- end
-
- end
-
- alias_method(:value, :content)
- alias_method(:value=, :content=)
-
- def initialize(*args)
- if Utils.element_initialize_arguments?(args)
- super
- else
- super()
- self.content = args[0]
- end
- end
-
- def full_name
- tag_name_with_prefix(TRACKBACK_PREFIX)
- end
-
- end
- end
-
- class RDF
- class Item; include TrackBackModel10; end
- end
-
- class Rss
- class Channel
- class Item; include TrackBackModel20; end
- end
- end
-
- BaseTrackBackModel::ELEMENTS.each do |name|
- class_name = Utils.to_class_name(name)
- BaseListener.install_class_name(TRACKBACK_URI, name,
- "TrackBack#{class_name}")
- end
-
- BaseTrackBackModel::ELEMENTS.collect! {|name| "#{TRACKBACK_PREFIX}_#{name}"}
-end
diff --git a/lib/rss/utils.rb b/lib/rss/utils.rb
deleted file mode 100644
index 9203df9a9b..0000000000
--- a/lib/rss/utils.rb
+++ /dev/null
@@ -1,200 +0,0 @@
-# frozen_string_literal: false
-module RSS
-
- ##
- # RSS::Utils is a module that holds various utility functions that are used
- # across many parts of the rest of the RSS library. Like most modules named
- # some variant of 'util', its methods are probably not particularly useful
- # to those who aren't developing the library itself.
- module Utils
- module_function
-
- # Given a +name+ in a name_with_underscores or a name-with-dashes format,
- # returns the CamelCase version of +name+.
- #
- # If the +name+ is already CamelCased, nothing happens.
- #
- # Examples:
- #
- # require 'rss/utils'
- #
- # RSS::Utils.to_class_name("sample_name")
- # # => "SampleName"
- # RSS::Utils.to_class_name("with-dashes")
- # # => "WithDashes"
- # RSS::Utils.to_class_name("CamelCase")
- # # => "CamelCase"
- def to_class_name(name)
- name.split(/[_\-]/).collect do |part|
- "#{part[0, 1].upcase}#{part[1..-1]}"
- end.join("")
- end
-
- # Returns an array of two elements: the filename where the calling method
- # is located, and the line number where it is defined.
- #
- # Takes an optional argument +i+, which specifies how many callers up the
- # stack to look.
- #
- # Examples:
- #
- # require 'rss/utils'
- #
- # def foo
- # p RSS::Utils.get_file_and_line_from_caller
- # p RSS::Utils.get_file_and_line_from_caller(1)
- # end
- #
- # def bar
- # foo
- # end
- #
- # def baz
- # bar
- # end
- #
- # baz
- # # => ["test.rb", 5]
- # # => ["test.rb", 9]
- #
- # If +i+ is not given, or is the default value of 0, it attempts to figure
- # out the correct value. This is useful when in combination with
- # instance_eval. For example:
- #
- # require 'rss/utils'
- #
- # def foo
- # p RSS::Utils.get_file_and_line_from_caller(1)
- # end
- #
- # def bar
- # foo
- # end
- #
- # instance_eval <<-RUBY, *RSS::Utils.get_file_and_line_from_caller
- # def baz
- # bar
- # end
- # RUBY
- #
- # baz
- #
- # # => ["test.rb", 8]
- def get_file_and_line_from_caller(i=0)
- file, line, = caller[i].split(':')
- line = line.to_i
- line += 1 if i.zero?
- [file, line]
- end
-
- # Takes a string +s+ with some HTML in it, and escapes '&', '"', '<' and '>', by
- # replacing them with the appropriate entities.
- #
- # This method is also aliased to h, for convenience.
- #
- # Examples:
- #
- # require 'rss/utils'
- #
- # RSS::Utils.html_escape("Dungeons & Dragons")
- # # => "Dungeons &amp; Dragons"
- # RSS::Utils.h(">_>")
- # # => "&gt;_&gt;"
- def html_escape(s)
- s.to_s.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
- end
- alias h html_escape
-
- # If +value+ is an instance of class +klass+, return it, else
- # create a new instance of +klass+ with value +value+.
- def new_with_value_if_need(klass, value)
- if value.is_a?(klass)
- value
- else
- klass.new(value)
- end
- end
-
- # This method is used inside of several different objects to determine
- # if special behavior is needed in the constructor.
- #
- # Special behavior is needed if the array passed in as +args+ has
- # +true+ or +false+ as its value, and if the second element of +args+
- # is a hash.
- def element_initialize_arguments?(args)
- [true, false].include?(args[0]) and args[1].is_a?(Hash)
- end
-
- module ExplicitCleanOther
- module_function
- def parse(value)
- if [true, false, nil].include?(value)
- value
- else
- case value.to_s
- when /\Aexplicit|yes|true\z/i
- true
- when /\Aclean|no|false\z/i
- false
- else
- nil
- end
- end
- end
- end
-
- module YesOther
- module_function
- def parse(value)
- if [true, false].include?(value)
- value
- else
- /\Ayes\z/i.match(value.to_s) ? true : false
- end
- end
- end
-
- module CSV
- module_function
- def parse(value, &block)
- if value.is_a?(String)
- value = value.strip.split(/\s*,\s*/)
- value = value.collect(&block) if block_given?
- value
- else
- value
- end
- end
- end
-
- module InheritedReader
- def inherited_reader(constant_name)
- base_class = inherited_base
- result = base_class.const_get(constant_name)
- found_base_class = false
- ancestors.reverse_each do |klass|
- if found_base_class
- if klass.const_defined?(constant_name)
- result = yield(result, klass.const_get(constant_name))
- end
- else
- found_base_class = klass == base_class
- end
- end
- result
- end
-
- def inherited_array_reader(constant_name)
- inherited_reader(constant_name) do |result, current|
- current + result
- end
- end
-
- def inherited_hash_reader(constant_name)
- inherited_reader(constant_name) do |result, current|
- result.merge(current)
- end
- end
- end
- end
-end
diff --git a/lib/rss/version.rb b/lib/rss/version.rb
deleted file mode 100644
index f0a8894e79..0000000000
--- a/lib/rss/version.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-module RSS
- # The current version of RSS
- VERSION = "0.2.8"
-end
diff --git a/lib/rss/xml-stylesheet.rb b/lib/rss/xml-stylesheet.rb
deleted file mode 100644
index 175c95fbcd..0000000000
--- a/lib/rss/xml-stylesheet.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-# frozen_string_literal: false
-require_relative "utils"
-
-module RSS
-
- module XMLStyleSheetMixin
- attr_accessor :xml_stylesheets
- def initialize(*args)
- super
- @xml_stylesheets = []
- end
-
- private
- def xml_stylesheet_pi
- xsss = @xml_stylesheets.collect do |xss|
- pi = xss.to_s
- pi = nil if /\A\s*\z/ =~ pi
- pi
- end.compact
- xsss.push("") unless xsss.empty?
- xsss.join("\n")
- end
- end
-
- class XMLStyleSheet
-
- include Utils
-
- ATTRIBUTES = %w(href type title media charset alternate)
-
- GUESS_TABLE = {
- "xsl" => "text/xsl",
- "css" => "text/css",
- }
-
- attr_accessor(*ATTRIBUTES)
- attr_accessor(:do_validate)
- def initialize(*attrs)
- if attrs.size == 1 and
- (attrs.first.is_a?(Hash) or attrs.first.is_a?(Array))
- attrs = attrs.first
- end
- @do_validate = true
- ATTRIBUTES.each do |attr|
- __send__("#{attr}=", nil)
- end
- vars = ATTRIBUTES.dup
- vars.unshift(:do_validate)
- attrs.each do |name, value|
- if vars.include?(name.to_s)
- __send__("#{name}=", value)
- end
- end
- end
-
- def to_s
- rv = ""
- if @href
- rv << %Q[<?xml-stylesheet]
- ATTRIBUTES.each do |name|
- if __send__(name)
- rv << %Q[ #{name}="#{h __send__(name)}"]
- end
- end
- rv << %Q[?>]
- end
- rv
- end
-
- remove_method(:href=)
- def href=(value)
- @href = value
- if @href and @type.nil?
- @type = guess_type(@href)
- end
- @href
- end
-
- remove_method(:alternate=)
- def alternate=(value)
- if value.nil? or /\A(?:yes|no)\z/ =~ value
- @alternate = value
- else
- if @do_validate
- args = ["?xml-stylesheet?", %Q[alternate="#{value}"]]
- raise NotAvailableValueError.new(*args)
- end
- end
- @alternate
- end
-
- def setup_maker(maker)
- xss = maker.xml_stylesheets.new_xml_stylesheet
- ATTRIBUTES.each do |attr|
- xss.__send__("#{attr}=", __send__(attr))
- end
- end
-
- private
- def guess_type(filename)
- /\.([^.]+)$/ =~ filename
- GUESS_TABLE[$1]
- end
-
- end
-end
diff --git a/lib/rss/xml.rb b/lib/rss/xml.rb
deleted file mode 100644
index b74630295f..0000000000
--- a/lib/rss/xml.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: false
-require_relative "utils"
-
-module RSS
- module XML
- class Element
- include Enumerable
-
- attr_reader :name, :prefix, :uri, :attributes, :children
- def initialize(name, prefix=nil, uri=nil, attributes={}, children=[])
- @name = name
- @prefix = prefix
- @uri = uri
- @attributes = attributes
- if children.is_a?(String) or !children.respond_to?(:each)
- @children = [children]
- else
- @children = children
- end
- end
-
- def [](name)
- @attributes[name]
- end
-
- def []=(name, value)
- @attributes[name] = value
- end
-
- def <<(child)
- @children << child
- end
-
- def each(&block)
- @children.each(&block)
- end
-
- def ==(other)
- other.kind_of?(self.class) and
- @name == other.name and
- @uri == other.uri and
- @attributes == other.attributes and
- @children == other.children
- end
-
- def to_s
- rv = "<#{full_name}"
- attributes.each do |key, value|
- rv << " #{Utils.html_escape(key)}=\"#{Utils.html_escape(value)}\""
- end
- if children.empty?
- rv << "/>"
- else
- rv << ">"
- children.each do |child|
- rv << child.to_s
- end
- rv << "</#{full_name}>"
- end
- rv
- end
-
- def full_name
- if @prefix
- "#{@prefix}:#{@name}"
- else
- @name
- end
- end
- end
- end
-end
diff --git a/lib/rss/xmlparser.rb b/lib/rss/xmlparser.rb
deleted file mode 100644
index cb2dd2afdd..0000000000
--- a/lib/rss/xmlparser.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-# frozen_string_literal: false
-begin
- require "xml/parser"
-rescue LoadError
- require "xmlparser"
-end
-
-begin
- require "xml/encoding-ja"
-rescue LoadError
- require "xmlencoding-ja"
- if defined?(Kconv)
- module XMLEncoding_ja
- class SJISHandler
- include Kconv
- end
- end
- end
-end
-
-module XML
- class Parser
- unless defined?(Error)
- # This error is legacy, so we just set it to the new one
- Error = ::XMLParserError # :nodoc:
- end
- end
-end
-
-module RSS
-
- class REXMLLikeXMLParser < ::XML::Parser
-
- include ::XML::Encoding_ja
-
- def listener=(listener)
- @listener = listener
- end
-
- def startElement(name, attrs)
- @listener.tag_start(name, attrs)
- end
-
- def endElement(name)
- @listener.tag_end(name)
- end
-
- def character(data)
- @listener.text(data)
- end
-
- def xmlDecl(version, encoding, standalone)
- @listener.xmldecl(version, encoding, standalone == 1)
- end
-
- def processingInstruction(target, content)
- @listener.instruction(target, content)
- end
-
- end
-
- class XMLParserParser < BaseParser
-
- class << self
- def listener
- XMLParserListener
- end
- end
-
- private
- def _parse
- begin
- parser = REXMLLikeXMLParser.new
- parser.listener = @listener
- parser.parse(@rss)
- rescue ::XML::Parser::Error => e
- raise NotWellFormedError.new(parser.line){e.message}
- end
- end
-
- end
-
- class XMLParserListener < BaseListener
-
- include ListenerMixin
-
- def xmldecl(version, encoding, standalone)
- super
- # Encoding is converted to UTF-8 when XMLParser parses XML.
- @encoding = 'UTF-8'
- end
-
- end
-
-end
diff --git a/lib/rss/xmlscanner.rb b/lib/rss/xmlscanner.rb
deleted file mode 100644
index 6e3b13d2f5..0000000000
--- a/lib/rss/xmlscanner.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-# frozen_string_literal: false
-require 'xmlscan/scanner'
-require 'stringio'
-
-module RSS
-
- class XMLScanParser < BaseParser
-
- class << self
- def listener
- XMLScanListener
- end
- end
-
- private
- def _parse
- begin
- if @rss.is_a?(String)
- input = StringIO.new(@rss)
- else
- input = @rss
- end
- scanner = XMLScan::XMLScanner.new(@listener)
- scanner.parse(input)
- rescue XMLScan::Error => e
- lineno = e.lineno || scanner.lineno || input.lineno
- raise NotWellFormedError.new(lineno){e.message}
- end
- end
-
- end
-
- class XMLScanListener < BaseListener
-
- include XMLScan::Visitor
- include ListenerMixin
-
- ENTITIES = {
- 'lt' => '<',
- 'gt' => '>',
- 'amp' => '&',
- 'quot' => '"',
- 'apos' => '\''
- }
-
- def on_xmldecl_version(str)
- @version = str
- end
-
- def on_xmldecl_encoding(str)
- @encoding = str
- end
-
- def on_xmldecl_standalone(str)
- @standalone = str
- end
-
- def on_xmldecl_end
- xmldecl(@version, @encoding, @standalone == "yes")
- end
-
- alias_method(:on_pi, :instruction)
- alias_method(:on_chardata, :text)
- alias_method(:on_cdata, :text)
-
- def on_etag(name)
- tag_end(name)
- end
-
- def on_entityref(ref)
- text(entity(ref))
- end
-
- def on_charref(code)
- text([code].pack('U'))
- end
-
- alias_method(:on_charref_hex, :on_charref)
-
- def on_stag(name)
- @attrs = {}
- end
-
- def on_attribute(name)
- @attrs[name] = @current_attr = ''
- end
-
- def on_attr_value(str)
- @current_attr << str
- end
-
- def on_attr_entityref(ref)
- @current_attr << entity(ref)
- end
-
- def on_attr_charref(code)
- @current_attr << [code].pack('U')
- end
-
- alias_method(:on_attr_charref_hex, :on_attr_charref)
-
- def on_stag_end(name)
- tag_start(name, @attrs)
- end
-
- def on_stag_end_empty(name)
- tag_start(name, @attrs)
- tag_end(name)
- end
-
- private
- def entity(ref)
- ent = ENTITIES[ref]
- if ent
- ent
- else
- wellformed_error("undefined entity: #{ref}")
- end
- end
- end
-
-end
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index f8ca70385e..6a7e56fa3c 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-# -*- ruby -*-
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
@@ -9,15 +8,15 @@
require 'rbconfig'
module Gem
- VERSION = "3.1.6".freeze
+ VERSION = "3.2.33".freeze
end
# Must be first since it unloads the prelude from 1.9.2
-require 'rubygems/compatibility'
+require_relative 'rubygems/compatibility'
-require 'rubygems/defaults'
-require 'rubygems/deprecate'
-require 'rubygems/errors'
+require_relative 'rubygems/defaults'
+require_relative 'rubygems/deprecate'
+require_relative 'rubygems/errors'
##
# RubyGems is the Ruby standard for publishing and managing third party
@@ -43,10 +42,10 @@ require 'rubygems/errors'
#
# == RubyGems Plugins
#
-# As of RubyGems 1.3.2, RubyGems will load plugins installed in gems or
+# RubyGems will load plugins in the latest version of each installed gem or
# $LOAD_PATH. Plugins must be named 'rubygems_plugin' (.rb, .so, etc) and
-# placed at the root of your gem's #require_path. Plugins are discovered via
-# Gem::find_files and then loaded.
+# placed at the root of your gem's #require_path. Plugins are installed at a
+# special location and loaded on boot.
#
# For an example plugin, see the {Graph gem}[https://github.com/seattlerb/graph]
# which adds a `gem graph` command.
@@ -120,6 +119,10 @@ module Gem
# to avoid deprecation warnings in Ruby 2.7.
UNTAINT = RUBY_VERSION < '2.7' ? :untaint.to_sym : proc{}
+ # When https://bugs.ruby-lang.org/issues/17259 is available, there is no need to override Kernel#warn
+ KERNEL_WARN_IGNORES_INTERNAL_ENTRIES = RUBY_ENGINE == "truffleruby" ||
+ (RUBY_ENGINE == "ruby" && RUBY_VERSION >= '3.0')
+
##
# An Array of Regexps that match windows Ruby platforms.
@@ -148,6 +151,7 @@ module Gem
doc
extensions
gems
+ plugins
specifications
].freeze
@@ -174,7 +178,7 @@ module Gem
@configuration = nil
@gemdeps = nil
@loaded_specs = {}
- LOADED_SPECS_MUTEX = Mutex.new
+ LOADED_SPECS_MUTEX = Thread::Mutex.new
@path_to_default_spec_map = {}
@platforms = []
@ruby = nil
@@ -245,9 +249,6 @@ module Gem
# you to specify specific gem versions.
def self.bin_path(name, exec_name = nil, *requirements)
- # TODO: fails test_self_bin_path_bin_file_gone_in_latest
- # Gem::Specification.find_by_name(name, *requirements).bin_file exec_name
-
requirements = Gem::Requirement.default if
requirements.empty?
@@ -271,7 +272,7 @@ module Gem
unless spec = specs.first
msg = "can't find gem #{dep} with executable #{exec_name}"
- if name == "bundler" && bundler_message = Gem::BundlerVersionFinder.missing_version_message
+ if dep.filters_bundler? && bundler_message = Gem::BundlerVersionFinder.missing_version_message
msg = bundler_message
end
raise Gem::GemNotFoundException, msg
@@ -318,6 +319,13 @@ module Gem
end
##
+ # The path were rubygems plugins are to be installed.
+
+ def self.plugindir(install_dir=Gem.dir)
+ File.join install_dir, 'plugins'
+ end
+
+ ##
# Reset the +dir+ and +path+ values. The next time +dir+ or +path+
# is requested, the values will be calculated from scratch. This is
# mainly used by the unit tests to provide test isolation.
@@ -330,13 +338,6 @@ module Gem
end
##
- # The path to standard location of the user's .gemrc file.
-
- def self.config_file
- @config_file ||= File.join Gem.user_home, '.gemrc'
- end
-
- ##
# The standard configuration object for gems.
def self.configuration
@@ -393,11 +394,11 @@ module Gem
target[k] = v
when Array
unless Gem::Deprecate.skip
- warn <<-eowarn
+ warn <<-EOWARN
Array values in the parameter to `Gem.paths=` are deprecated.
Please use a String or nil.
An Array (#{env.inspect}) was passed in from #{caller[3]}
- eowarn
+ EOWARN
end
target[k] = v.join File::PATH_SEPARATOR
end
@@ -411,8 +412,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
##
# The path where gems are to be installed.
- #--
- # FIXME deprecate these once everything else has been done -ebh
def self.dir
paths.home
@@ -465,7 +464,10 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
subdirs.each do |name|
subdir = File.join dir, name
next if File.exist? subdir
- FileUtils.mkdir_p subdir, **options rescue nil
+ begin
+ FileUtils.mkdir_p subdir, **options
+ rescue SystemCallError
+ end
end
ensure
File.umask old_umask
@@ -502,7 +504,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
gem_specifications = @gemdeps ? Gem.loaded_specs.values : Gem::Specification.stubs
- files.concat gem_specifications.map { |spec|
+ files.concat gem_specifications.map {|spec|
spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}")
}.flatten
@@ -517,7 +519,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
glob_with_suffixes = "#{glob}#{Gem.suffix_pattern}"
$LOAD_PATH.map do |load_path|
Gem::Util.glob_files_in_dir(glob_with_suffixes, load_path)
- end.flatten.select { |file| File.file? file.tap(&Gem::UNTAINT) }
+ end.flatten.select {|file| File.file? file.tap(&Gem::UNTAINT) }
end
##
@@ -537,7 +539,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
files = find_files_from_load_path glob if check_load_path
- files.concat Gem::Specification.latest_specs(true).map { |spec|
+ files.concat Gem::Specification.latest_specs(true).map {|spec|
spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}")
}.flatten
@@ -549,86 +551,15 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
##
- # Finds the user's home directory.
- #--
- # Some comments from the ruby-talk list regarding finding the home
- # directory:
- #
- # I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
- # to be depending on HOME in those code samples. I propose that
- # it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
- # least on Win32).
- #++
- #--
- #
- #++
-
- def self.find_home
- Dir.home.dup
- rescue
- if Gem.win_platform?
- File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/')
- else
- File.expand_path "/"
- end
- end
-
- private_class_method :find_home
-
- # TODO: remove in RubyGems 4.0
-
- ##
- # Zlib::GzipReader wrapper that unzips +data+.
-
- def self.gunzip(data)
- Gem::Util.gunzip data
- end
-
- class << self
-
- extend Gem::Deprecate
- deprecate :gunzip, "Gem::Util.gunzip", 2018, 12
-
- end
-
- ##
- # Zlib::GzipWriter wrapper that zips +data+.
-
- def self.gzip(data)
- Gem::Util.gzip data
- end
-
- class << self
-
- extend Gem::Deprecate
- deprecate :gzip, "Gem::Util.gzip", 2018, 12
-
- end
-
- ##
- # A Zlib::Inflate#inflate wrapper
-
- def self.inflate(data)
- Gem::Util.inflate data
- end
-
- class << self
-
- extend Gem::Deprecate
- deprecate :inflate, "Gem::Util.inflate", 2018, 12
-
- end
-
- ##
# Top level install helper method. Allows you to install gems interactively:
#
# % irb
# >> Gem.install "minitest"
- # Fetching: minitest-3.0.1.gem (100%)
+ # Fetching: minitest-5.14.0.gem (100%)
# => [#<Gem::Specification:0x1013b4528 @name="minitest", ...>]
def self.install(name, version = Gem::Requirement.default, *options)
- require "rubygems/dependency_installer"
+ require_relative "rubygems/dependency_installer"
inst = Gem::DependencyInstaller.new(*options)
inst.install name, version
inst.installed_gems
@@ -687,37 +618,19 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.load_yaml
return if @yaml_loaded
- return unless defined?(gem)
-
- begin
- gem 'psych', '>= 2.0.0'
- rescue Gem::LoadError
- # It's OK if the user does not have the psych gem installed. We will
- # attempt to require the stdlib version
- end
begin
# Try requiring the gem version *or* stdlib version of psych.
require 'psych'
rescue ::LoadError
- # If we can't load psych, thats fine, go on.
+ # If we can't load psych, that's fine, go on.
else
- # If 'yaml' has already been required, then we have to
- # be sure to switch it over to the newly loaded psych.
- if defined?(YAML::ENGINE) && YAML::ENGINE.yamler != "psych"
- YAML::ENGINE.yamler = "psych"
- end
-
- require 'rubygems/psych_additions'
- require 'rubygems/psych_tree'
+ require_relative 'rubygems/psych_additions'
+ require_relative 'rubygems/psych_tree'
end
require 'yaml'
- require 'rubygems/safe_yaml'
-
- # Now that we're sure some kind of yaml library is loaded, pull
- # in our hack to deal with Syck's DefaultKey ugliness.
- require 'rubygems/syck_hack'
+ require_relative 'rubygems/safe_yaml'
@yaml_loaded = true
end
@@ -887,18 +800,18 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
##
# Safely write a file in binary mode on all platforms.
def self.write_binary(path, data)
- open(path, 'wb') do |io|
- begin
- io.flock(File::LOCK_EX)
- rescue *WRITE_BINARY_ERRORS
- end
+ File.open(path, File::RDWR | File::CREAT | File::BINARY | File::LOCK_EX) do |io|
+ io.write data
+ end
+ rescue *WRITE_BINARY_ERRORS
+ File.open(path, 'wb') do |io|
io.write data
end
rescue Errno::ENOLCK # NFS
if Thread.main != Thread.current
raise
else
- open(path, 'wb') do |io|
+ File.open(path, 'wb') do |io|
io.write data
end
end
@@ -909,8 +822,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.ruby
if @ruby.nil?
- @ruby = File.join(RbConfig::CONFIG['bindir'],
- "#{RbConfig::CONFIG['ruby_install_name']}#{RbConfig::CONFIG['EXEEXT']}")
+ @ruby = RbConfig.ruby
@ruby = "\"#{@ruby}\"" if @ruby =~ /\s/
end
@@ -1023,21 +935,38 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
@suffix_pattern ||= "{#{suffixes.join(',')}}"
end
+ ##
+ # Regexp for require-able path suffixes.
+
def self.suffix_regexp
@suffix_regexp ||= /#{Regexp.union(suffixes)}\z/
end
##
+ # Glob pattern for require-able plugin suffixes.
+
+ def self.plugin_suffix_pattern
+ @plugin_suffix_pattern ||= "_plugin#{suffix_pattern}"
+ end
+
+ ##
+ # Regexp for require-able plugin suffixes.
+
+ def self.plugin_suffix_regexp
+ @plugin_suffix_regexp ||= /_plugin#{suffix_regexp}\z/
+ end
+
+ ##
# Suffixes for require-able paths.
def self.suffixes
@suffixes ||= ['',
'.rb',
- *%w(DLEXT DLEXT2).map do |key|
+ *%w[DLEXT DLEXT2].map do |key|
val = RbConfig::CONFIG[key]
next unless val and not val.empty?
".#{val}"
- end
+ end,
].compact.uniq
end
@@ -1061,7 +990,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Lazily loads DefaultUserInteraction and returns the default UI.
def self.ui
- require 'rubygems/user_interaction'
+ require_relative 'rubygems/user_interaction'
Gem::DefaultUserInteraction.ui
end
@@ -1074,24 +1003,17 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
paths.flatten!
paths.compact!
hash = { "GEM_HOME" => home, "GEM_PATH" => paths.empty? ? home : paths.join(File::PATH_SEPARATOR) }
- hash.delete_if { |_, v| v.nil? }
+ hash.delete_if {|_, v| v.nil? }
self.paths = hash
end
##
- # The home directory for the user.
-
- def self.user_home
- @user_home ||= find_home.tap(&Gem::UNTAINT)
- end
-
- ##
# Is this a windows platform?
def self.win_platform?
if @@win_platform.nil?
ruby_platform = RbConfig::CONFIG['host_os']
- @@win_platform = !!WIN_PATTERNS.find { |r| ruby_platform =~ r }
+ @@win_platform = !!WIN_PATTERNS.find {|r| ruby_platform =~ r }
end
@@win_platform
@@ -1125,15 +1047,11 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
##
- # Find the 'rubygems_plugin' files in the latest installed gems and load
- # them
+ # Find rubygems plugin files in the standard location and load them
def self.load_plugins
- # Remove this env var by at least 3.0
- if ENV['RUBYGEMS_LOAD_ALL_PLUGINS']
- load_plugin_files find_files('rubygems_plugin', false)
- else
- load_plugin_files find_latest_files('rubygems_plugin', false)
+ Gem.path.each do |gem_path|
+ load_plugin_files Gem::Util.glob_files_in_dir("*#{Gem.plugin_suffix_pattern}", plugindir(gem_path))
end
end
@@ -1141,19 +1059,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Find all 'rubygems_plugin' files in $LOAD_PATH and load them
def self.load_env_plugins
- path = "rubygems_plugin"
-
- files = []
- glob = "#{path}#{Gem.suffix_pattern}"
- $LOAD_PATH.each do |load_path|
- globbed = Gem::Util.glob_files_in_dir(glob, load_path)
-
- globbed.each do |load_path_file|
- files << load_path_file if File.file?(load_path_file.tap(&Gem::UNTAINT))
- end
- end
-
- load_plugin_files files
+ load_plugin_files find_files_from_load_path("rubygems_plugin")
end
##
@@ -1186,7 +1092,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
if path == "-"
Gem::Util.traverse_parents Dir.pwd do |directory|
- dep_file = GEM_DEP_FILES.find { |f| File.file?(f) }
+ dep_file = GEM_DEP_FILES.find {|f| File.file?(f) }
next unless dep_file
@@ -1204,42 +1110,25 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(path)
- require 'rubygems/user_interaction'
- Gem::DefaultUserInteraction.use_ui(ui) do
- require "bundler"
- begin
- Bundler.ui.silence do
- @gemdeps = Bundler.setup
+ require_relative 'rubygems/user_interaction'
+ require "bundler"
+ begin
+ Gem::DefaultUserInteraction.use_ui(ui) do
+ begin
+ Bundler.ui.silence do
+ @gemdeps = Bundler.setup
+ end
+ ensure
+ Gem::DefaultUserInteraction.ui.close
end
- ensure
- Gem::DefaultUserInteraction.ui.close
end
- @gemdeps.requested_specs.map(&:to_spec).sort_by(&:name)
- end
-
- rescue => e
- case e
- when Gem::LoadError, Gem::UnsatisfiableDependencyError, (defined?(Bundler::GemNotFound) ? Bundler::GemNotFound : Gem::LoadError)
+ rescue Bundler::BundlerError => e
warn e.message
- warn "You may need to `gem install -g` to install missing gems"
+ warn "You may need to `bundle install` to install missing gems"
warn ""
- else
- raise
end
end
- class << self
-
- ##
- # TODO remove with RubyGems 4.0
-
- alias detect_gemdeps use_gemdeps # :nodoc:
-
- extend Gem::Deprecate
- deprecate :detect_gemdeps, "Gem.use_gemdeps", 2018, 12
-
- end
-
##
# If the SOURCE_DATE_EPOCH environment variable is set, returns it's value.
# Otherwise, returns the time that `Gem.source_date_epoch_string` was
@@ -1284,6 +1173,11 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# methods, and then we switch over to `class << self` here. Pick one or the
# other.
class << self
+ ##
+ # RubyGems distributors (like operating system package managers) can
+ # disable RubyGems update by setting this to error message printed to
+ # end-users on gem update --system instead of actual update.
+ attr_accessor :disable_system_update_message
##
# Hash of loaded Gem::Specification keyed by name
@@ -1309,7 +1203,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
#
def register_default_spec(spec)
- extended_require_paths = spec.require_paths.map {|f| f + "/"}
+ extended_require_paths = spec.require_paths.map {|f| f + "/" }
new_format = extended_require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } }
if new_format
@@ -1323,6 +1217,8 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
next unless $~
end
+ spec.activate if already_loaded?(file)
+
@path_to_default_spec_map[file] = spec
@path_to_default_spec_map[file.sub(suffix_regexp, "")] = spec
end
@@ -1388,6 +1284,17 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
attr_reader :pre_uninstall_hooks
+ private
+
+ def already_loaded?(file)
+ $LOADED_FEATURES.any? do |feature_path|
+ feature_path.end_with?(file) && default_gem_load_paths.any? {|load_path_entry| feature_path == "#{load_path_entry}/#{file}" }
+ end
+ end
+
+ def default_gem_load_paths
+ @default_gem_load_paths ||= $LOAD_PATH[load_path_insert_index..-1]
+ end
end
##
@@ -1413,23 +1320,13 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
autoload :Specification, File.expand_path('rubygems/specification', __dir__)
autoload :Util, File.expand_path('rubygems/util', __dir__)
autoload :Version, File.expand_path('rubygems/version', __dir__)
-
- require "rubygems/specification"
end
-require 'rubygems/exceptions'
+require_relative 'rubygems/exceptions'
# REFACTOR: This should be pulled out into some kind of hacks file.
begin
##
- # Defaults the operating system (or packager) wants to provide for RubyGems.
-
- require 'rubygems/defaults/operating_system'
-rescue LoadError
-end
-
-begin
- ##
# Defaults the Ruby implementation wants to provide for RubyGems
require "rubygems/defaults/#{RUBY_ENGINE}"
@@ -1440,8 +1337,22 @@ end
# Loads the default specs.
Gem::Specification.load_defaults
-require 'rubygems/core_ext/kernel_gem'
-require 'rubygems/core_ext/kernel_require'
-require 'rubygems/core_ext/kernel_warn'
+require_relative 'rubygems/core_ext/kernel_gem'
+require_relative 'rubygems/core_ext/kernel_require'
+require_relative 'rubygems/core_ext/kernel_warn'
-Gem.use_gemdeps
+begin
+ ##
+ # Defaults the operating system (or packager) wants to provide for RubyGems.
+
+ require 'rubygems/defaults/operating_system'
+rescue LoadError
+ # Ignored
+rescue StandardError => e
+ msg = "#{e.message}\n" \
+ "Loading the rubygems/defaults/operating_system.rb file caused an error. " \
+ "This file is owned by your OS, not by rubygems upstream. " \
+ "Please find out which OS package this file belongs to and follow the guidelines from your OS to report " \
+ "the problem and ask for help."
+ raise e.class, msg
+end
diff --git a/lib/rubygems/available_set.rb b/lib/rubygems/available_set.rb
index 2e9d9496f6..499483d9e9 100644
--- a/lib/rubygems/available_set.rb
+++ b/lib/rubygems/available_set.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
class Gem::AvailableSet
-
include Enumerable
Tuple = Struct.new(:spec, :source)
@@ -70,11 +69,11 @@ class Gem::AvailableSet
end
def all_specs
- @set.map { |t| t.spec }
+ @set.map {|t| t.spec }
end
def match_platform!
- @set.reject! { |t| !Gem::Platform.match(t.spec.platform) }
+ @set.reject! {|t| !Gem::Platform.match_spec?(t.spec) }
@sorted = nil
self
end
@@ -91,7 +90,7 @@ class Gem::AvailableSet
end
def source_for(spec)
- f = @set.find { |t| t.spec == spec }
+ f = @set.find {|t| t.spec == spec }
f.source
end
@@ -160,7 +159,6 @@ class Gem::AvailableSet
end
def inject_into_list(dep_list)
- @set.each { |t| dep_list.add t.spec }
+ @set.each {|t| dep_list.add t.spec }
end
-
end
diff --git a/lib/rubygems/basic_specification.rb b/lib/rubygems/basic_specification.rb
index 339953eb29..665b87fc0e 100644
--- a/lib/rubygems/basic_specification.rb
+++ b/lib/rubygems/basic_specification.rb
@@ -4,7 +4,6 @@
# used by both Specification and StubSpecification.
class Gem::BasicSpecification
-
##
# Allows installation of extensions for git: gems.
@@ -39,10 +38,8 @@ class Gem::BasicSpecification
end
class << self
-
extend Gem::Deprecate
- deprecate :default_specifications_dir, "Gem.default_specifications_dir", 2020, 02
-
+ rubygems_deprecate :default_specifications_dir, "Gem.default_specifications_dir"
end
##
@@ -274,10 +271,16 @@ class Gem::BasicSpecification
# Return all files in this gem that match for +glob+.
def matches_for_glob(glob) # TODO: rename?
- # TODO: do we need these?? Kill it
glob = File.join(self.lib_dirs_glob, glob)
- Dir[glob].map { |f| f.tap(&Gem::UNTAINT) } # FIX our tests are broken, run w/ SAFE=1
+ Dir[glob].map {|f| f.tap(&Gem::UNTAINT) } # FIX our tests are broken, run w/ SAFE=1
+ end
+
+ ##
+ # Returns the list of plugins in this spec.
+
+ def plugins
+ matches_for_glob("rubygems#{Gem.plugin_suffix_pattern}")
end
##
@@ -329,15 +332,14 @@ class Gem::BasicSpecification
def have_file?(file, suffixes)
return true if raw_require_paths.any? do |path|
base = File.join(gems_dir, full_name, path.tap(&Gem::UNTAINT), file).tap(&Gem::UNTAINT)
- suffixes.any? { |suf| File.file? base + suf }
+ suffixes.any? {|suf| File.file? base + suf }
end
if have_extensions?
base = File.join extension_dir, file
- suffixes.any? { |suf| File.file? base + suf }
+ suffixes.any? {|suf| File.file? base + suf }
else
false
end
end
-
end
diff --git a/lib/rubygems/bundler_version_finder.rb b/lib/rubygems/bundler_version_finder.rb
index 38da7738a8..9ce0a2378e 100644
--- a/lib/rubygems/bundler_version_finder.rb
+++ b/lib/rubygems/bundler_version_finder.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "rubygems/util"
-
module Gem::BundlerVersionFinder
def self.bundler_version
version, _ = bundler_version_with_reason
@@ -44,9 +42,9 @@ To install the missing version, run `gem install bundler:#{vr.first}`
def self.filter!(specs)
return unless bundler_version = self.bundler_version
- specs.reject! { |spec| spec.version.segments.first != bundler_version.segments.first }
+ specs.reject! {|spec| spec.version.segments.first != bundler_version.segments.first }
- exact_match_index = specs.find_index { |spec| spec.version == bundler_version }
+ exact_match_index = specs.find_index {|spec| spec.version == bundler_version }
return unless exact_match_index
specs.unshift(specs.delete_at(exact_match_index))
@@ -82,12 +80,19 @@ To install the missing version, run `gem install bundler:#{vr.first}`
def self.lockfile_contents
gemfile = ENV["BUNDLE_GEMFILE"]
gemfile = nil if gemfile && gemfile.empty?
- Gem::Util.traverse_parents Dir.pwd do |directory|
- next unless gemfile = Gem::GEM_DEP_FILES.find { |f| File.file?(f.tap(&Gem::UNTAINT)) }
- gemfile = File.join directory, gemfile
- break
- end unless gemfile
+ unless gemfile
+ begin
+ Gem::Util.traverse_parents(Dir.pwd) do |directory|
+ next unless gemfile = Gem::GEM_DEP_FILES.find {|f| File.file?(f.tap(&Gem::UNTAINT)) }
+
+ gemfile = File.join directory, gemfile
+ break
+ end
+ rescue Errno::ENOENT
+ return
+ end
+ end
return unless gemfile
diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb
index 32ec0f8ba6..abdaa8e7c6 100644
--- a/lib/rubygems/command.rb
+++ b/lib/rubygems/command.rb
@@ -5,9 +5,9 @@
# See LICENSE.txt for permissions.
#++
-require 'optparse'
-require 'rubygems/requirement'
-require 'rubygems/user_interaction'
+require_relative 'optparse'
+require_relative 'requirement'
+require_relative 'user_interaction'
##
# Base class for all Gem commands. When creating a new gem command, define
@@ -17,10 +17,9 @@ require 'rubygems/user_interaction'
# A very good example to look at is Gem::Commands::ContentsCommand
class Gem::Command
-
include Gem::UserInteraction
- OptionParser.accept Symbol do |value|
+ Gem::OptionParser.accept Symbol do |value|
value.to_sym
end
@@ -77,7 +76,7 @@ class Gem::Command
when Array
@extra_args = value
when String
- @extra_args = value.split
+ @extra_args = value.split(' ')
end
end
@@ -125,7 +124,7 @@ class Gem::Command
@program_name = "gem #{command}"
@defaults = defaults
@options = defaults.dup
- @option_groups = Hash.new { |h,k| h[k] = [] }
+ @option_groups = Hash.new {|h,k| h[k] = [] }
@deprecated_options = { command => {} }
@parser = nil
@when_invoked = nil
@@ -162,7 +161,7 @@ class Gem::Command
if errors and !errors.empty?
msg << ", here is why:\n"
- errors.each { |x| msg << " #{x.wordy}\n" }
+ errors.each {|x| msg << " #{x.wordy}\n" }
else
if required_by and gem != required_by
msg << " (required by #{required_by}) in any repository"
@@ -174,8 +173,7 @@ class Gem::Command
alert_error msg
unless suppress_suggestions
- suggestions = Gem::SpecFetcher.fetcher.suggest_gems_from_name gem_name
-
+ suggestions = Gem::SpecFetcher.fetcher.suggest_gems_from_name(gem_name, :latest, 10)
unless suggestions.empty?
alert_error "Possible alternatives: #{suggestions.join(", ")}"
end
@@ -193,7 +191,7 @@ class Gem::Command
"Please specify at least one gem name (e.g. gem build GEMNAME)"
end
- args.select { |arg| arg !~ /^-/ }
+ args.select {|arg| arg !~ /^-/ }
end
##
@@ -346,7 +344,7 @@ class Gem::Command
##
# Add a command-line option and handler to the command.
#
- # See OptionParser#make_switch for an explanation of +opts+.
+ # See Gem::OptionParser#make_switch for an explanation of +opts+.
#
# +handler+ will be called with two values, the value of the argument and
# the options hash.
@@ -357,6 +355,8 @@ class Gem::Command
def add_option(*opts, &handler) # :yields: value, options
group_name = Symbol === opts.first ? opts.shift : :options
+ raise "Do not pass an empty string in opts" if opts.include?("")
+
@option_groups[group_name] << [opts, handler]
end
@@ -365,7 +365,7 @@ class Gem::Command
def remove_option(name)
@option_groups.each do |_, option_list|
- option_list.reject! { |args, _| args.any? { |x| x.is_a?(String) && x =~ /^#{name}/ } }
+ option_list.reject! {|args, _| args.any? {|x| x.is_a?(String) && x =~ /^#{name}/ } }
end
end
@@ -418,7 +418,7 @@ class Gem::Command
def merge_options(new_options)
@options = @defaults.clone
- new_options.each { |k,v| @options[k] = v }
+ new_options.each {|k,v| @options[k] = v }
end
##
@@ -457,7 +457,7 @@ class Gem::Command
until extra.empty? do
ex = []
ex << extra.shift
- ex << extra.shift if extra.first.to_s =~ /^[^-]/
+ ex << extra.shift if extra.first.to_s =~ /^[^-]/ # rubocop:disable Performance/StartWith
result << ex if handles?(ex)
end
@@ -466,6 +466,10 @@ class Gem::Command
result
end
+ def deprecated?
+ false
+ end
+
private
def option_is_deprecated?(option)
@@ -493,7 +497,7 @@ class Gem::Command
configure_options "", regular_options
- @option_groups.sort_by { |n,_| n.to_s }.each do |group_name, option_list|
+ @option_groups.sort_by {|n,_| n.to_s }.each do |group_name, option_list|
@parser.separator nil
configure_options group_name, option_list
end
@@ -536,7 +540,7 @@ class Gem::Command
# command.
def create_option_parser
- @parser = OptionParser.new
+ @parser = Gem::OptionParser.new
add_parser_options
@@ -621,8 +625,7 @@ class Gem::Command
# :stopdoc:
HELP = <<-HELP.freeze
-RubyGems is a sophisticated package manager for Ruby. This is a
-basic help message containing pointers to more information.
+RubyGems is a package manager for Ruby.
Usage:
gem -h/--help
@@ -633,6 +636,7 @@ basic help message containing pointers to more information.
gem install rake
gem list --local
gem build package.gemspec
+ gem push package-0.0.1.gem
gem help install
Further help:
@@ -650,7 +654,6 @@ basic help message containing pointers to more information.
HELP
# :startdoc:
-
end
##
diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb
index 8ad723be55..cb07757700 100644
--- a/lib/rubygems/command_manager.rb
+++ b/lib/rubygems/command_manager.rb
@@ -5,9 +5,9 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/command'
-require 'rubygems/user_interaction'
-require 'rubygems/text'
+require_relative 'command'
+require_relative 'user_interaction'
+require_relative 'text'
##
# The command manager registers and installs all the individual sub-commands
@@ -32,7 +32,6 @@ require 'rubygems/text'
# See Gem::Command for instructions on writing gem commands.
class Gem::CommandManager
-
include Gem::Text
include Gem::UserInteraction
@@ -74,7 +73,9 @@ class Gem::CommandManager
].freeze
ALIAS_COMMANDS = {
- 'i' => 'install'
+ 'i' => 'install',
+ 'login' => 'signin',
+ 'logout' => 'signout',
}.freeze
##
@@ -138,7 +139,7 @@ class Gem::CommandManager
# Return a sorted list of all command names as strings.
def command_names
- @commands.keys.collect {|key| key.to_s}.sort
+ @commands.keys.collect {|key| key.to_s }.sort
end
##
@@ -175,6 +176,7 @@ class Gem::CommandManager
else
cmd_name = args.shift.downcase
cmd = find_command cmd_name
+ cmd.deprecation_warning if cmd.deprecated?
cmd.invoke_with_build_args args, build_args
end
end
@@ -202,9 +204,9 @@ class Gem::CommandManager
def find_command_possibilities(cmd_name)
len = cmd_name.length
- found = command_names.select { |name| cmd_name == name[0, len] }
+ found = command_names.select {|name| cmd_name == name[0, len] }
- exact = found.find { |name| name == cmd_name }
+ exact = found.find {|name| name == cmd_name }
exact ? [exact] : found
end
@@ -230,5 +232,4 @@ class Gem::CommandManager
ui.backtrace e
end
end
-
end
diff --git a/lib/rubygems/commands/build_command.rb b/lib/rubygems/commands/build_command.rb
index e2b5def1e8..6d1a057dfa 100644
--- a/lib/rubygems/commands/build_command.rb
+++ b/lib/rubygems/commands/build_command.rb
@@ -1,12 +1,16 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/package'
+require_relative '../command'
+require_relative '../package'
+require_relative '../version_option'
class Gem::Commands::BuildCommand < Gem::Command
+ include Gem::VersionOption
def initialize
super 'build', 'Build a gem from a gemspec'
+ add_platform_option
+
add_option '--force', 'skip validation of the spec' do |value, options|
options[:force] = true
end
@@ -19,7 +23,7 @@ class Gem::Commands::BuildCommand < Gem::Command
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|
+ 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
end
@@ -57,14 +61,18 @@ Gems can be saved to a specified filename with the output option:
end
def execute
- gem_name = get_one_optional_argument || find_gemspec
- build_gem(gem_name)
+ if build_path = options[:build_path]
+ Dir.chdir(build_path) { build_gem }
+ return
+ end
+
+ build_gem
end
private
- def find_gemspec
- gemspecs = Dir.glob("*.gemspec").sort
+ def find_gemspec(glob = "*.gemspec")
+ gemspecs = Dir.glob(glob).sort
if gemspecs.size > 1
alert_error "Multiple gemspecs found: #{gemspecs}, please specify one"
@@ -74,28 +82,19 @@ Gems can be saved to a specified filename with the output option:
gemspecs.first
end
- def build_gem(gem_name)
- gemspec = File.exist?(gem_name) ? gem_name : "#{gem_name}.gemspec"
-
- if File.exist?(gemspec)
- spec = Gem::Specification.load(gemspec)
-
- if options[:build_path]
- Dir.chdir(File.dirname(gemspec)) do
- spec = Gem::Specification.load(File.basename(gemspec))
- build_package(spec)
- end
- else
- build_package(spec)
- end
+ def build_gem
+ gemspec = resolve_gem_name
+ if gemspec
+ build_package(gemspec)
else
- alert_error "Gemspec file not found: #{gemspec}"
+ alert_error error_message
terminate_interaction(1)
end
end
- def build_package(spec)
+ def build_package(gemspec)
+ spec = Gem::Specification.load(gemspec)
if spec
Gem::Package.build(
spec,
@@ -109,4 +108,25 @@ Gems can be saved to a specified filename with the output option:
end
end
+ def resolve_gem_name
+ return find_gemspec unless gem_name
+
+ if File.exist?(gem_name)
+ gem_name
+ else
+ find_gemspec("#{gem_name}.gemspec") || find_gemspec(gem_name)
+ end
+ end
+
+ def error_message
+ if gem_name
+ "Couldn't find a gemspec file matching '#{gem_name}' in #{Dir.pwd}"
+ else
+ "Couldn't find a gemspec file in #{Dir.pwd}"
+ end
+ end
+
+ def gem_name
+ get_one_optional_argument
+ end
end
diff --git a/lib/rubygems/commands/cert_command.rb b/lib/rubygems/commands/cert_command.rb
index 72400f3edd..b59564d575 100644
--- a/lib/rubygems/commands/cert_command.rb
+++ b/lib/rubygems/commands/cert_command.rb
@@ -1,50 +1,15 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/security'
-begin
- require 'openssl'
-rescue LoadError => e
- raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
- e.message =~ / -- openssl$/
-end
+require_relative '../command'
+require_relative '../security'
class Gem::Commands::CertCommand < Gem::Command
-
def initialize
super 'cert', 'Manage RubyGems certificates and signing settings',
:add => [], :remove => [], :list => [], :build => [], :sign => []
- OptionParser.accept OpenSSL::X509::Certificate do |certificate_file|
- begin
- certificate = OpenSSL::X509::Certificate.new File.read certificate_file
- rescue Errno::ENOENT
- raise OptionParser::InvalidArgument, "#{certificate_file}: does not exist"
- rescue OpenSSL::X509::CertificateError
- raise OptionParser::InvalidArgument,
- "#{certificate_file}: invalid X509 certificate"
- end
- [certificate, certificate_file]
- end
-
- OptionParser.accept OpenSSL::PKey::RSA do |key_file|
- begin
- passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE']
- key = OpenSSL::PKey::RSA.new File.read(key_file), passphrase
- rescue Errno::ENOENT
- raise OptionParser::InvalidArgument, "#{key_file}: does not exist"
- rescue OpenSSL::PKey::RSAError
- raise OptionParser::InvalidArgument, "#{key_file}: invalid RSA key"
- end
-
- raise OptionParser::InvalidArgument,
- "#{key_file}: private key not found" unless key.private?
-
- key
- end
-
- add_option('-a', '--add CERT', OpenSSL::X509::Certificate,
- 'Add a trusted certificate.') do |(cert, _), options|
- options[:add] << cert
+ add_option('-a', '--add CERT',
+ 'Add a trusted certificate.') do |cert_file, options|
+ options[:add] << open_cert(cert_file)
end
add_option('-l', '--list [FILTER]',
@@ -67,21 +32,26 @@ class Gem::Commands::CertCommand < Gem::Command
options[:build] << email_address
end
- add_option('-C', '--certificate CERT', OpenSSL::X509::Certificate,
- 'Signing certificate for --sign') do |(cert, cert_file), options|
- options[:issuer_cert] = cert
+ add_option('-C', '--certificate CERT',
+ 'Signing certificate for --sign') do |cert_file, options|
+ options[:issuer_cert] = open_cert(cert_file)
options[:issuer_cert_file] = cert_file
end
- add_option('-K', '--private-key KEY', OpenSSL::PKey::RSA,
- 'Key for --sign or --build') do |key, options|
- options[:key] = key
+ add_option('-K', '--private-key KEY',
+ 'Key for --sign or --build') do |key_file, options|
+ options[:key] = open_private_key(key_file)
+ end
+
+ add_option('-A', '--key-algorithm ALGORITHM',
+ 'Select which key algorithm to use for --build') do |algorithm, options|
+ options[:key_algorithm] = algorithm
end
add_option('-s', '--sign CERT',
'Signs CERT with the key from -K',
'and the certificate from -C') do |cert_file, options|
- raise OptionParser::InvalidArgument, "#{cert_file}: does not exist" unless
+ raise Gem::OptionParser::InvalidArgument, "#{cert_file}: does not exist" unless
File.file? cert_file
options[:sign] << cert_file
@@ -104,7 +74,39 @@ class Gem::Commands::CertCommand < Gem::Command
say "Added '#{certificate.subject}'"
end
+ def check_openssl
+ return if Gem::HAVE_OPENSSL
+
+ alert_error "OpenSSL library is required for the cert command"
+ terminate_interaction 1
+ end
+
+ def open_cert(certificate_file)
+ check_openssl
+ OpenSSL::X509::Certificate.new File.read certificate_file
+ rescue Errno::ENOENT
+ raise Gem::OptionParser::InvalidArgument, "#{certificate_file}: does not exist"
+ rescue OpenSSL::X509::CertificateError
+ raise Gem::OptionParser::InvalidArgument,
+ "#{certificate_file}: invalid X509 certificate"
+ end
+
+ def open_private_key(key_file)
+ check_openssl
+ passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE']
+ key = OpenSSL::PKey.read File.read(key_file), passphrase
+ raise Gem::OptionParser::InvalidArgument,
+ "#{key_file}: private key not found" unless key.private?
+ key
+ rescue Errno::ENOENT
+ raise Gem::OptionParser::InvalidArgument, "#{key_file}: does not exist"
+ rescue OpenSSL::PKey::PKeyError, ArgumentError
+ raise Gem::OptionParser::InvalidArgument, "#{key_file}: invalid RSA, DSA, or EC key"
+ end
+
def execute
+ check_openssl
+
options[:add].each do |certificate|
add_certificate certificate
end
@@ -173,7 +175,8 @@ class Gem::Commands::CertCommand < Gem::Command
raise Gem::CommandLineError,
"Passphrase and passphrase confirmation don't match" unless passphrase == passphrase_confirmation
- key = Gem::Security.create_key
+ algorithm = options[:key_algorithm] || Gem::Security::DEFAULT_KEY_ALGORITHM
+ key = Gem::Security.create_key(algorithm)
key_path = Gem::Security.write key, "gem-private_key.pem", 0600, passphrase
return key, key_path
@@ -186,7 +189,7 @@ class Gem::Commands::CertCommand < Gem::Command
subject = certificate.subject.to_s
subject.downcase.index filter
end.sort_by do |certificate, _|
- certificate.subject.to_a.map { |name, data,| [name, data] }
+ certificate.subject.to_a.map {|name, data,| [name, data] }
end.each do |certificate, path|
yield certificate, path
end
@@ -258,13 +261,14 @@ For further reading on signing gems see `ri Gem::Security`.
key_file = File.join Gem.default_key_path
key = File.read key_file
passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE']
- options[:key] = OpenSSL::PKey::RSA.new key, passphrase
+ options[:key] = OpenSSL::PKey.read key, passphrase
+
rescue Errno::ENOENT
alert_error \
"--private-key not specified and ~/.gem/gem-private_key.pem does not exist"
terminate_interaction 1
- rescue OpenSSL::PKey::RSAError
+ rescue OpenSSL::PKey::PKeyError
alert_error \
"--private-key not specified and ~/.gem/gem-private_key.pem is not valid"
@@ -318,5 +322,4 @@ For further reading on signing gems see `ri Gem::Security`.
# It's simple, but is all we need
email =~ /\A.+@.+\z/
end
-
-end if defined?(OpenSSL::SSL)
+end
diff --git a/lib/rubygems/commands/check_command.rb b/lib/rubygems/commands/check_command.rb
index 7905b8ab69..3b6b97ae3b 100644
--- a/lib/rubygems/commands/check_command.rb
+++ b/lib/rubygems/commands/check_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/validator'
-require 'rubygems/doctor'
+require_relative '../command'
+require_relative '../version_option'
+require_relative '../validator'
+require_relative '../doctor'
class Gem::Commands::CheckCommand < Gem::Command
-
include Gem::VersionOption
def initialize
@@ -90,5 +89,4 @@ specifications and will clean up gems that have been partially uninstalled.
def usage # :nodoc:
"#{program_name} [OPTIONS] [GEMNAME ...]"
end
-
end
diff --git a/lib/rubygems/commands/cleanup_command.rb b/lib/rubygems/commands/cleanup_command.rb
index fedaec8448..c965085880 100644
--- a/lib/rubygems/commands/cleanup_command.rb
+++ b/lib/rubygems/commands/cleanup_command.rb
@@ -1,20 +1,25 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/dependency_list'
-require 'rubygems/uninstaller'
+require_relative '../command'
+require_relative '../dependency_list'
+require_relative '../uninstaller'
class Gem::Commands::CleanupCommand < Gem::Command
-
def initialize
super 'cleanup',
'Clean up old versions of installed gems',
:force => false, :install_dir => Gem.dir,
:check_dev => true
- add_option('-n', '-d', '--dryrun',
+ add_option('-n', '-d', '--dry-run',
+ 'Do not uninstall gems') do |value, options|
+ options[:dryrun] = true
+ end
+
+ add_option(:Deprecated, '--dryrun',
'Do not uninstall gems') do |value, options|
options[:dryrun] = true
end
+ deprecate_option('--dryrun', extra_msg: 'Use --dry-run instead')
add_option('-D', '--[no-]check-development',
'Check development dependencies while uninstalling',
@@ -42,7 +47,7 @@ class Gem::Commands::CleanupCommand < Gem::Command
end
def defaults_str # :nodoc:
- "--no-dryrun"
+ "--no-dry-run"
end
def description # :nodoc:
@@ -69,7 +74,7 @@ If no gems are named all gems in GEM_HOME are cleaned.
until done do
clean_gems
- this_set = @gems_to_cleanup.map { |spec| spec.full_name }.sort
+ this_set = @gems_to_cleanup.map {|spec| spec.full_name }.sort
done = this_set.empty? || last_set == this_set
@@ -82,7 +87,7 @@ If no gems are named all gems in GEM_HOME are cleaned.
say "Clean up complete"
verbose do
- skipped = @default_gems.map { |spec| spec.full_name }
+ skipped = @default_gems.map {|spec| spec.full_name }
"Skipped default gems: #{skipped.join ', '}"
end
@@ -99,7 +104,7 @@ If no gems are named all gems in GEM_HOME are cleaned.
@full = Gem::DependencyList.from_specs
deplist = Gem::DependencyList.new
- @gems_to_cleanup.each { |spec| deplist.add spec }
+ @gems_to_cleanup.each {|spec| deplist.add spec }
deps = deplist.strongly_connected_components.flatten
@@ -181,5 +186,4 @@ If no gems are named all gems in GEM_HOME are cleaned.
# 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 26d6828fe6..716022c458 100644
--- a/lib/rubygems/commands/contents_command.rb
+++ b/lib/rubygems/commands/contents_command.rb
@@ -1,10 +1,8 @@
# frozen_string_literal: true
-require 'English'
-require 'rubygems/command'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../version_option'
class Gem::Commands::ContentsCommand < Gem::Command
-
include Gem::VersionOption
def initialize
@@ -106,7 +104,8 @@ prefix or only the files that are requireable.
spec.files.map do |file|
case file
when /\A#{spec.bindir}\//
- [RbConfig::CONFIG['bindir'], $POSTMATCH]
+ # $' is POSTMATCH
+ [RbConfig::CONFIG['bindir'], $']
when /\.so\z/
[RbConfig::CONFIG['archdir'], file]
else
@@ -167,7 +166,7 @@ prefix or only the files that are requireable.
end
def spec_for(name)
- spec = Gem::Specification.find_all_by_name(name, @version).last
+ spec = Gem::Specification.find_all_by_name(name, @version).first
return spec if spec
@@ -175,7 +174,7 @@ prefix or only the files that are requireable.
if Gem.configuration.verbose
say "\nDirectories searched:"
- @spec_dirs.sort.each { |dir| say dir }
+ @spec_dirs.sort.each {|dir| say dir }
end
return nil
@@ -186,5 +185,4 @@ prefix or only the files that are requireable.
[i, File.join(i, "specifications")]
end.flatten
end
-
end
diff --git a/lib/rubygems/commands/dependency_command.rb b/lib/rubygems/commands/dependency_command.rb
index 00ab19bed4..7d217076a5 100644
--- a/lib/rubygems/commands/dependency_command.rb
+++ b/lib/rubygems/commands/dependency_command.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../version_option'
class Gem::Commands::DependencyCommand < Gem::Command
-
include Gem::LocalRemoteOptions
include Gem::VersionOption
@@ -59,14 +58,14 @@ use with other commands.
ss, = fetcher.spec_for_dependency dependency
- ss.map { |spec, _| spec }
+ ss.map {|spec, _| spec }
end
def fetch_specs(name_pattern, dependency) # :nodoc:
specs = []
if local?
- specs.concat Gem::Specification.stubs.find_all { |spec|
+ specs.concat Gem::Specification.stubs.find_all {|spec|
name_pattern =~ spec.name and
dependency.requirement.satisfied_by? spec.version
}.map(&:to_spec)
@@ -92,7 +91,7 @@ use with other commands.
def display_pipe(specs) # :nodoc:
specs.each do |spec|
unless spec.dependencies.empty?
- spec.dependencies.sort_by { |dep| dep.name }.each do |dep|
+ spec.dependencies.sort_by {|dep| dep.name }.each do |dep|
say "#{dep.name} --version '#{dep.requirement}'"
end
end
@@ -156,7 +155,7 @@ use with other commands.
response = String.new
response << ' ' * level + "Gem #{spec.full_name}\n"
unless spec.dependencies.empty?
- spec.dependencies.sort_by { |dep| dep.name }.each do |dep|
+ spec.dependencies.sort_by {|dep| dep.name }.each do |dep|
response << ' ' * level + " #{dep}\n"
end
end
@@ -168,11 +167,11 @@ use with other commands.
ss, _ = fetcher.spec_for_dependency dependency
- ss.map { |s,o| s }
+ ss.map {|s,o| s }
end
def reverse_dependencies(specs) # :nodoc:
- reverse = Hash.new { |h, k| h[k] = [] }
+ reverse = Hash.new {|h, k| h[k] = [] }
return reverse unless options[:reverse_dependencies]
@@ -215,5 +214,4 @@ use with other commands.
/\A#{Regexp.union(*args)}/
end
end
-
end
diff --git a/lib/rubygems/commands/environment_command.rb b/lib/rubygems/commands/environment_command.rb
index c98a77ac2e..b6eeb620bd 100644
--- a/lib/rubygems/commands/environment_command.rb
+++ b/lib/rubygems/commands/environment_command.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::EnvironmentCommand < Gem::Command
-
def initialize
super 'environment', 'Display information about the RubyGems environment'
end
@@ -127,7 +126,7 @@ lib/rubygems/defaults/operating_system.rb
out << " - RUBYGEMS PLATFORMS:\n"
Gem.platforms.each do |platform|
- out << " - #{platform}\n"
+ out << " - #{platform}\n"
end
out << " - GEM PATHS:\n"
@@ -172,5 +171,4 @@ lib/rubygems/defaults/operating_system.rb
return nil
end
-
end
diff --git a/lib/rubygems/commands/fetch_command.rb b/lib/rubygems/commands/fetch_command.rb
index 66562d7fb7..373851643d 100644
--- a/lib/rubygems/commands/fetch_command.rb
+++ b/lib/rubygems/commands/fetch_command.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../version_option'
class Gem::Commands::FetchCommand < Gem::Command
-
include Gem::LocalRemoteOptions
include Gem::VersionOption
@@ -57,11 +56,11 @@ then repackaging it.
Gem::SpecFetcher.fetcher.spec_for_dependency dep
if platform
- filtered = specs_and_sources.select { |s,| s.platform == platform }
+ filtered = specs_and_sources.select {|s,| s.platform == platform }
specs_and_sources = filtered unless filtered.empty?
end
- spec, source = specs_and_sources.max_by { |s,| s.version }
+ spec, source = specs_and_sources.max_by {|s,| s }
if spec.nil?
show_lookup_failure gem_name, version, errors, options[:domain]
@@ -73,5 +72,4 @@ then repackaging it.
say "Downloaded #{spec.full_name}"
end
end
-
end
diff --git a/lib/rubygems/commands/generate_index_command.rb b/lib/rubygems/commands/generate_index_command.rb
index 6dccdcb946..87200dab91 100644
--- a/lib/rubygems/commands/generate_index_command.rb
+++ b/lib/rubygems/commands/generate_index_command.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/indexer'
+require_relative '../command'
+require_relative '../indexer'
##
# Generates a index files for use as a gem server.
@@ -8,7 +8,6 @@ require 'rubygems/indexer'
# See `gem help generate_index`
class Gem::Commands::GenerateIndexCommand < Gem::Command
-
def initialize
super 'generate_index',
'Generates the index files for a gem server directory',
@@ -83,5 +82,4 @@ Marshal::MINOR_VERSION constants. It is used to ensure compatibility.
end
end
end
-
end
diff --git a/lib/rubygems/commands/help_command.rb b/lib/rubygems/commands/help_command.rb
index 259e8b5622..7f3383c9f3 100644
--- a/lib/rubygems/commands/help_command.rb
+++ b/lib/rubygems/commands/help_command.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::HelpCommand < Gem::Command
-
# :stopdoc:
EXAMPLES = <<-EOF.freeze
Some examples of 'gem' usage.
@@ -324,7 +323,7 @@ platform.
margin_width = 4
- desc_width = @command_manager.command_names.map { |n| n.size }.max + 4
+ desc_width = @command_manager.command_names.map {|n| n.size }.max + 4
summary_width = 80 - margin_width - desc_width
wrap_indent = ' ' * (margin_width + desc_width)
@@ -333,6 +332,8 @@ platform.
@command_manager.command_names.each do |cmd_name|
command = @command_manager[cmd_name]
+ next if command.deprecated?
+
summary =
if command
command.summary
@@ -370,5 +371,4 @@ platform.
alert_warning "Unknown command #{command_name}. Try: gem help commands"
end
end
-
end
diff --git a/lib/rubygems/commands/info_command.rb b/lib/rubygems/commands/info_command.rb
index 6a737b178b..3f2dd4ae0b 100644
--- a/lib/rubygems/commands/info_command.rb
+++ b/lib/rubygems/commands/info_command.rb
@@ -1,14 +1,18 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/commands/query_command'
+require_relative '../command'
+require_relative '../query_utils'
-class Gem::Commands::InfoCommand < Gem::Commands::QueryCommand
+class Gem::Commands::InfoCommand < Gem::Command
+ include Gem::QueryUtils
def initialize
- super "info", "Show information for the given gem"
+ super "info", "Show information for the given gem",
+ :name => //, :domain => :local, :details => false, :versions => true,
+ :installed => nil, :version => Gem::Requirement.default
+
+ add_query_options
- remove_option('--name-matches')
remove_option('-d')
defaults[:details] = true
@@ -31,5 +35,4 @@ class Gem::Commands::InfoCommand < Gem::Commands::QueryCommand
def defaults_str
"--local"
end
-
end
diff --git a/lib/rubygems/commands/install_command.rb b/lib/rubygems/commands/install_command.rb
index 753ff33eb5..7af5060129 100644
--- a/lib/rubygems/commands/install_command.rb
+++ b/lib/rubygems/commands/install_command.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/install_update_options'
-require 'rubygems/dependency_installer'
-require 'rubygems/local_remote_options'
-require 'rubygems/validator'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../install_update_options'
+require_relative '../dependency_installer'
+require_relative '../local_remote_options'
+require_relative '../validator'
+require_relative '../version_option'
##
# Gem installer command line tool
@@ -12,7 +12,6 @@ require 'rubygems/version_option'
# See `gem help install`
class Gem::Commands::InstallCommand < Gem::Command
-
attr_reader :installed_specs # :nodoc:
include Gem::VersionOption
@@ -128,7 +127,7 @@ You can use `i` command instead of `install`.
end
def usage # :nodoc:
- "#{program_name} GEMNAME [GEMNAME ...] [options] -- --build-flags"
+ "#{program_name} [options] GEMNAME [GEMNAME ...] -- --build-flags"
end
def check_install_dir # :nodoc:
@@ -170,7 +169,7 @@ You can use `i` command instead of `install`.
end
def install_from_gemdeps # :nodoc:
- require 'rubygems/request_set'
+ require_relative '../request_set'
rs = Gem::RequestSet.new
specs = rs.install_from_gemdeps options do |req, inst|
@@ -218,7 +217,7 @@ You can use `i` command instead of `install`.
gem_version ||= options[:version]
domain = options[:domain]
domain = :local unless options[:suggest_alternate]
- supress_suggestions = (domain == :local)
+ suppress_suggestions = (domain == :local)
begin
install_gem gem_name, gem_version
@@ -226,11 +225,11 @@ You can use `i` command instead of `install`.
alert_error "Error installing #{gem_name}:\n\t#{e.message}"
exit_code |= 1
rescue Gem::GemNotFoundException => e
- show_lookup_failure e.name, e.version, e.errors, supress_suggestions
+ show_lookup_failure e.name, e.version, e.errors, suppress_suggestions
exit_code |= 2
rescue Gem::UnsatisfiableDependencyError => e
- show_lookup_failure e.name, e.version, e.errors, supress_suggestions,
+ show_lookup_failure e.name, e.version, e.errors, suppress_suggestions,
"'#{gem_name}' (#{gem_version})"
exit_code |= 2
@@ -245,11 +244,11 @@ You can use `i` command instead of `install`.
def load_hooks # :nodoc:
if options[:install_as_default]
- require 'rubygems/install_default_message'
+ require_relative '../install_default_message'
else
- require 'rubygems/install_message'
+ require_relative '../install_message'
end
- require 'rubygems/rdoc'
+ require_relative '../rdoc'
end
def show_install_errors(errors) # :nodoc:
@@ -258,7 +257,8 @@ You can use `i` command instead of `install`.
errors.each do |x|
return unless Gem::SourceFetchProblem === x
- msg = "Unable to pull data from '#{x.source.uri}': #{x.error.message}"
+ require_relative "../uri"
+ msg = "Unable to pull data from '#{Gem::Uri.new(x.source.uri).redacted}': #{x.error.message}"
alert_warning msg
end
@@ -270,5 +270,4 @@ You can use `i` command instead of `install`.
gems = @installed_specs.length == 1 ? 'gem' : 'gems'
say "#{@installed_specs.length} #{gems} installed"
end
-
end
diff --git a/lib/rubygems/commands/list_command.rb b/lib/rubygems/commands/list_command.rb
index cd21543537..dea11111c9 100644
--- a/lib/rubygems/commands/list_command.rb
+++ b/lib/rubygems/commands/list_command.rb
@@ -1,17 +1,19 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/commands/query_command'
+require_relative '../command'
+require_relative '../query_utils'
##
-# An alternate to Gem::Commands::QueryCommand that searches for gems starting
-# with the supplied argument.
+# Searches for gems starting with the supplied argument.
-class Gem::Commands::ListCommand < Gem::Commands::QueryCommand
+class Gem::Commands::ListCommand < Gem::Command
+ include Gem::QueryUtils
def initialize
- super 'list', 'Display local gems whose name matches REGEXP'
+ super 'list', 'Display local gems whose name matches REGEXP',
+ :name => //, :domain => :local, :details => false, :versions => true,
+ :installed => nil, :version => Gem::Requirement.default
- remove_option('--name-matches')
+ add_query_options
end
def arguments # :nodoc:
@@ -36,5 +38,4 @@ To search for remote gems use the search command.
def usage # :nodoc:
"#{program_name} [REGEXP ...]"
end
-
end
diff --git a/lib/rubygems/commands/lock_command.rb b/lib/rubygems/commands/lock_command.rb
index ebb402a8bd..cb6229a2cb 100644
--- a/lib/rubygems/commands/lock_command.rb
+++ b/lib/rubygems/commands/lock_command.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::LockCommand < Gem::Command
-
def initialize
super 'lock', 'Generate a lockdown list of gems',
:strict => false
@@ -104,7 +103,6 @@ lock it down to the exact version.
File.join path, "specifications", "#{gem_full_name}.gemspec"
end
- gemspecs.find { |path| File.exist? path }
+ gemspecs.find {|path| File.exist? path }
end
-
end
diff --git a/lib/rubygems/commands/mirror_command.rb b/lib/rubygems/commands/mirror_command.rb
index 4e2a41fa33..7daa47e2f0 100644
--- a/lib/rubygems/commands/mirror_command.rb
+++ b/lib/rubygems/commands/mirror_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
unless defined? Gem::Commands::MirrorCommand
class Gem::Commands::MirrorCommand < Gem::Command
-
def initialize
super('mirror', 'Mirror all gem files (requires rubygems-mirror)')
begin
@@ -22,6 +21,5 @@ The mirror command has been moved to the rubygems-mirror gem.
def execute
alert_error "Install the rubygems-mirror gem for the mirror command"
end
-
end
end
diff --git a/lib/rubygems/commands/open_command.rb b/lib/rubygems/commands/open_command.rb
index 8eaeb64ba9..1e616fd68f 100644
--- a/lib/rubygems/commands/open_command.rb
+++ b/lib/rubygems/commands/open_command.rb
@@ -1,11 +1,8 @@
# frozen_string_literal: true
-require 'English'
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/util'
+require_relative '../command'
+require_relative '../version_option'
class Gem::Commands::OpenCommand < Gem::Command
-
include Gem::VersionOption
def initialize
@@ -39,7 +36,7 @@ class Gem::Commands::OpenCommand < Gem::Command
end
def usage # :nodoc:
- "#{program_name} GEMNAME [-e COMMAND]"
+ "#{program_name} [-e COMMAND] GEMNAME"
end
def get_env_editor
@@ -84,5 +81,4 @@ class Gem::Commands::OpenCommand < Gem::Command
say "Unable to find gem '#{name}'"
end
-
end
diff --git a/lib/rubygems/commands/outdated_command.rb b/lib/rubygems/commands/outdated_command.rb
index 035eaffcbc..162d338320 100644
--- a/lib/rubygems/commands/outdated_command.rb
+++ b/lib/rubygems/commands/outdated_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/spec_fetcher'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../spec_fetcher'
+require_relative '../version_option'
class Gem::Commands::OutdatedCommand < Gem::Command
-
include Gem::LocalRemoteOptions
include Gem::VersionOption
@@ -30,5 +29,4 @@ update the gems with the update or install commands.
say "#{spec.name} (#{spec.version} < #{remote_version})"
end
end
-
end
diff --git a/lib/rubygems/commands/owner_command.rb b/lib/rubygems/commands/owner_command.rb
index f8e68c48e7..0a5665228f 100644
--- a/lib/rubygems/commands/owner_command.rb
+++ b/lib/rubygems/commands/owner_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/gemcutter_utilities'
-require 'rubygems/text'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../gemcutter_utilities'
+require_relative '../text'
class Gem::Commands::OwnerCommand < Gem::Command
-
include Gem::Text
include Gem::LocalRemoteOptions
include Gem::GemcutterUtilities
@@ -54,7 +53,7 @@ permission to.
def execute
@host = options[:host]
- sign_in
+ sign_in(scope: get_owner_scope)
name = get_one_gem_name
add_owners name, options[:add]
@@ -103,11 +102,17 @@ permission to.
private
def send_owner_request(method, name, owner)
- rubygems_api_request method, "api/v1/gems/#{name}/owners" do |request|
+ rubygems_api_request method, "api/v1/gems/#{name}/owners", scope: get_owner_scope(method: method) do |request|
request.set_form_data 'email' => owner
request.add_field "Authorization", api_key
- request.add_field "OTP", options[:otp] if options[:otp]
end
end
+ def get_owner_scope(method: nil)
+ if method == :post || options.any? && options[:add].any?
+ :add_owner
+ elsif method == :delete || options.any? && options[:remove].any?
+ :remove_owner
+ end
+ end
end
diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb
index 2248a821c8..13979b0a59 100644
--- a/lib/rubygems/commands/pristine_command.rb
+++ b/lib/rubygems/commands/pristine_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/package'
-require 'rubygems/installer'
-require 'rubygems/version_option'
+require_relative '../command'
+require_relative '../package'
+require_relative '../installer'
+require_relative '../version_option'
class Gem::Commands::PristineCommand < Gem::Command
-
include Gem::VersionOption
def initialize
@@ -40,12 +39,22 @@ class Gem::Commands::PristineCommand < Gem::Command
options[:only_executables] = value
end
+ add_option('--only-plugins',
+ 'Only restore plugins') do |value, options|
+ options[:only_plugins] = value
+ end
+
add_option('-E', '--[no-]env-shebang',
'Rewrite executables with a shebang',
'of /usr/bin/env') do |value, options|
options[:env_shebang] = value
end
+ add_option('-i', '--install-dir DIR',
+ 'Gem repository to get binstubs and plugins installed') do |value, options|
+ options[:install_dir] = File.expand_path(value)
+ end
+
add_option('-n', '--bindir DIR',
'Directory where executables are',
'located') do |value, options|
@@ -126,15 +135,15 @@ extensions will be restored.
end
end
- unless spec.extensions.empty? or options[:extensions] or options[:only_executables]
+ unless spec.extensions.empty? or options[:extensions] or options[:only_executables] or options[:only_plugins]
say "Skipped #{spec.full_name}, it needs to compile an extension"
next
end
gem = spec.cache_file
- unless File.exist? gem or options[:only_executables]
- require 'rubygems/remote_fetcher'
+ unless File.exist? gem or options[:only_executables] or options[:only_plugins]
+ require_relative '../remote_fetcher'
say "Cached gem for #{spec.full_name} not found, attempting to fetch..."
@@ -159,19 +168,23 @@ extensions will be restored.
end
bin_dir = options[:bin_dir] if options[:bin_dir]
+ install_dir = options[:install_dir] if options[:install_dir]
installer_options = {
:wrappers => true,
:force => true,
- :install_dir => spec.base_dir,
+ :install_dir => install_dir || spec.base_dir,
:env_shebang => env_shebang,
:build_args => spec.build_args,
- :bin_dir => bin_dir
+ :bin_dir => bin_dir,
}
if options[:only_executables]
installer = Gem::Installer.for_spec(spec, installer_options)
installer.generate_bin
+ elsif options[:only_plugins]
+ installer = Gem::Installer.for_spec(spec, installer_options)
+ installer.generate_plugins
else
installer = Gem::Installer.at(gem, installer_options)
installer.install
@@ -180,5 +193,4 @@ extensions will be restored.
say "Restored #{spec.full_name}"
end
end
-
end
diff --git a/lib/rubygems/commands/push_command.rb b/lib/rubygems/commands/push_command.rb
index 41e6c7ec30..1864b4b095 100644
--- a/lib/rubygems/commands/push_command.rb
+++ b/lib/rubygems/commands/push_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/gemcutter_utilities'
-require 'rubygems/package'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../gemcutter_utilities'
+require_relative '../package'
class Gem::Commands::PushCommand < Gem::Command
-
include Gem::LocalRemoteOptions
include Gem::GemcutterUtilities
@@ -52,26 +51,17 @@ The push command will use ~/.gem/credentials to authenticate to a server, but yo
gem_name = get_one_gem_name
default_gem_server, push_host = get_hosts_for(gem_name)
- default_host = nil
- user_defined_host = nil
-
- if @user_defined_host
- user_defined_host = options[:host]
- else
- default_host = options[:host]
- end
-
- @host = if user_defined_host
- user_defined_host
+ @host = if @user_defined_host
+ options[:host]
elsif default_gem_server
default_gem_server
elsif push_host
push_host
else
- default_host
+ options[:host]
end
- sign_in @host
+ sign_in @host, scope: get_push_scope
send_gem(gem_name)
end
@@ -79,36 +69,7 @@ The push command will use ~/.gem/credentials to authenticate to a server, but yo
def send_gem(name)
args = [:post, "api/v1/gems"]
- latest_rubygems_version = Gem.latest_rubygems_version
-
- if latest_rubygems_version < Gem.rubygems_version and
- Gem.rubygems_version.prerelease? and
- Gem::Version.new('2.0.0.rc.2') != Gem.rubygems_version
- alert_error <<-ERROR
-You are using a beta release of RubyGems (#{Gem::VERSION}) which is not
-allowed to push gems. Please downgrade or upgrade to a release version.
-
-The latest released RubyGems version is #{latest_rubygems_version}
-
-You can upgrade or downgrade to the latest release version with:
-
- gem update --system=#{latest_rubygems_version}
-
- ERROR
- terminate_interaction 1
- end
-
- gem_data = Gem::Package.new(name)
-
- unless @host
- @host = gem_data.spec.metadata['default_gem_server']
- end
-
- push_host = nil
-
- if gem_data.spec.metadata.has_key?('allowed_push_host')
- push_host = gem_data.spec.metadata['allowed_push_host']
- end
+ _, push_host = get_hosts_for(name)
@host ||= push_host
@@ -125,12 +86,11 @@ You can upgrade or downgrade to the latest release version with:
private
def send_push_request(name, args)
- rubygems_api_request(*args) do |request|
+ rubygems_api_request(*args, scope: get_push_scope) do |request|
request.body = Gem.read_binary name
request.add_field "Content-Length", request.body.size
request.add_field "Content-Type", "application/octet-stream"
request.add_field "Authorization", api_key
- request.add_field "OTP", options[:otp] if options[:otp]
end
end
@@ -139,8 +99,11 @@ You can upgrade or downgrade to the latest release version with:
[
gem_metadata["default_gem_server"],
- gem_metadata["allowed_push_host"]
+ gem_metadata["allowed_push_host"],
]
end
+ def get_push_scope
+ :push_rubygem
+ end
end
diff --git a/lib/rubygems/commands/query_command.rb b/lib/rubygems/commands/query_command.rb
index 4fb23bc6c1..5896bec44e 100644
--- a/lib/rubygems/commands/query_command.rb
+++ b/lib/rubygems/commands/query_command.rb
@@ -1,15 +1,21 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/spec_fetcher'
-require 'rubygems/version_option'
-require 'rubygems/text'
+require_relative '../command'
+require_relative '../query_utils'
+require_relative '../deprecate'
class Gem::Commands::QueryCommand < Gem::Command
+ extend Gem::Deprecate
+ rubygems_deprecate_command
- include Gem::Text
- include Gem::LocalRemoteOptions
- include Gem::VersionOption
+ include Gem::QueryUtils
+
+ alias warning_without_suggested_alternatives deprecation_warning
+ def deprecation_warning
+ warning_without_suggested_alternatives
+
+ message = "It is recommended that you use `gem search` or `gem list` instead.\n"
+ alert_warning message unless Gem::Deprecate.skip
+ end
def initialize(name = 'query',
summary = 'Query gem information in local or remote repositories')
@@ -17,55 +23,13 @@ class Gem::Commands::QueryCommand < Gem::Command
:name => //, :domain => :local, :details => false, :versions => true,
:installed => nil, :version => Gem::Requirement.default
- add_option('-i', '--[no-]installed',
- 'Check for installed gem') do |value, options|
- options[:installed] = value
- end
-
- add_option('-I', 'Equivalent to --no-installed') do |value, options|
- options[:installed] = false
- end
-
- add_version_option command, "for use with --installed"
-
add_option('-n', '--name-matches REGEXP',
'Name of gem(s) to query on matches the',
'provided REGEXP') do |value, options|
options[:name] = /#{value}/i
end
- add_option('-d', '--[no-]details',
- 'Display detailed information of gem(s)') do |value, options|
- options[:details] = value
- end
-
- add_option('--[no-]versions',
- 'Display only gem names') do |value, options|
- options[:versions] = value
- options[:details] = false unless value
- end
-
- add_option('-a', '--all',
- 'Display all gem versions') do |value, options|
- options[:all] = value
- end
-
- add_option('-e', '--exact',
- 'Name of gem(s) to query on matches the',
- 'provided STRING') do |value, options|
- options[:exact] = value
- end
-
- add_option('--[no-]prerelease',
- 'Display prerelease versions') do |value, options|
- options[:prerelease] = value
- end
-
- add_local_remote_options
- end
-
- def defaults_str # :nodoc:
- "--local --name-matches // --no-details --versions --no-installed"
+ add_query_options
end
def description # :nodoc:
@@ -76,298 +40,4 @@ You should really use the list and search commands instead. This command
is too hard to use.
EOF
end
-
- def execute
- gem_names = Array(options[:name])
-
- if !args.empty?
- gem_names = options[:exact] ? args.map{|arg| /\A#{Regexp.escape(arg)}\Z/ } : args.map{|arg| /#{arg}/i }
- end
-
- terminate_interaction(check_installed_gems(gem_names)) if check_installed_gems?
-
- gem_names.each { |n| show_gems(n) }
- end
-
- private
-
- def check_installed_gems(gem_names)
- exit_code = 0
-
- if args.empty? && !gem_name?
- alert_error "You must specify a gem name"
- exit_code = 4
- elsif gem_names.count > 1
- alert_error "You must specify only ONE gem!"
- exit_code = 4
- else
- installed = installed?(gem_names.first, options[:version])
- installed = !installed unless options[:installed]
-
- say(installed)
- exit_code = 1 if !installed
- end
-
- exit_code
- end
-
- def check_installed_gems?
- !options[:installed].nil?
- end
-
- def gem_name?
- !options[:name].source.empty?
- end
-
- def prerelease
- options[:prerelease]
- end
-
- def show_prereleases?
- prerelease.nil? || prerelease
- end
-
- def args
- options[:args].to_a
- end
-
- def display_header(type)
- if (ui.outs.tty? and Gem.configuration.verbose) or both?
- say
- say "*** #{type} GEMS ***"
- say
- end
- end
-
- #Guts of original execute
- def show_gems(name)
- show_local_gems(name) if local?
- show_remote_gems(name) if remote?
- end
-
- def show_local_gems(name, req = Gem::Requirement.default)
- display_header("LOCAL")
-
- specs = Gem::Specification.find_all do |s|
- s.name =~ name and req =~ s.version
- end
-
- dep = Gem::Deprecate.skip_during { Gem::Dependency.new name, req }
- specs.select! do |s|
- dep.match?(s.name, s.version, show_prereleases?)
- end
-
- spec_tuples = specs.map do |spec|
- [spec.name_tuple, spec]
- end
-
- output_query_results(spec_tuples)
- end
-
- def show_remote_gems(name)
- display_header("REMOTE")
-
- fetcher = Gem::SpecFetcher.fetcher
-
- spec_tuples = if name.respond_to?(:source) && name.source.empty?
- fetcher.detect(specs_type) { true }
- else
- fetcher.detect(specs_type) do |name_tuple|
- name === name_tuple.name
- end
- end
-
- output_query_results(spec_tuples)
- end
-
- def specs_type
- if options[:all]
- if options[:prerelease]
- :complete
- else
- :released
- end
- elsif options[:prerelease]
- :prerelease
- else
- :latest
- end
- end
-
- ##
- # Check if gem +name+ version +version+ is installed.
-
- def installed?(name, req = Gem::Requirement.default)
- Gem::Specification.any? { |s| s.name =~ name and req =~ s.version }
- end
-
- def output_query_results(spec_tuples)
- output = []
- versions = Hash.new { |h,name| h[name] = [] }
-
- spec_tuples.each do |spec_tuple, source|
- versions[spec_tuple.name] << [spec_tuple, source]
- end
-
- versions = versions.sort_by do |(n,_),_|
- n.downcase
- end
-
- output_versions output, versions
-
- say output.join(options[:details] ? "\n\n" : "\n")
- end
-
- def output_versions(output, versions)
- versions.each do |gem_name, matching_tuples|
- matching_tuples = matching_tuples.sort_by { |n,_| n.version }.reverse
-
- platforms = Hash.new { |h,version| h[version] = [] }
-
- matching_tuples.each do |n, _|
- platforms[n.version] << n.platform if n.platform
- end
-
- seen = {}
-
- matching_tuples.delete_if do |n,_|
- if seen[n.version]
- true
- else
- seen[n.version] = true
- false
- end
- end
-
- output << clean_text(make_entry(matching_tuples, platforms))
- end
- end
-
- def entry_details(entry, detail_tuple, specs, platforms)
- return unless options[:details]
-
- name_tuple, spec = detail_tuple
-
- spec = spec.fetch_spec(name_tuple)if spec.respond_to?(:fetch_spec)
-
- entry << "\n"
-
- spec_platforms entry, platforms
- spec_authors entry, spec
- spec_homepage entry, spec
- spec_license entry, spec
- spec_loaded_from entry, spec, specs
- spec_summary entry, spec
- end
-
- def entry_versions(entry, name_tuples, platforms, specs)
- return unless options[:versions]
-
- list =
- if platforms.empty? or options[:details]
- name_tuples.map { |n| n.version }.uniq
- else
- platforms.sort.reverse.map do |version, pls|
- out = version.to_s
-
- if options[:domain] == :local
- default = specs.any? do |s|
- !s.is_a?(Gem::Source) && s.version == version && s.default_gem?
- end
- out = "default: #{out}" if default
- end
-
- if pls != [Gem::Platform::RUBY]
- platform_list = [pls.delete(Gem::Platform::RUBY), *pls.sort].compact
- out = platform_list.unshift(out).join(' ')
- end
-
- out
- end
- end
-
- entry << " (#{list.join ', '})"
- end
-
- def make_entry(entry_tuples, platforms)
- detail_tuple = entry_tuples.first
-
- name_tuples, specs = entry_tuples.flatten.partition do |item|
- Gem::NameTuple === item
- end
-
- entry = [name_tuples.first.name]
-
- entry_versions(entry, name_tuples, platforms, specs)
- entry_details(entry, detail_tuple, specs, platforms)
-
- entry.join
- end
-
- def spec_authors(entry, spec)
- authors = "Author#{spec.authors.length > 1 ? 's' : ''}: ".dup
- authors << spec.authors.join(', ')
- entry << format_text(authors, 68, 4)
- end
-
- def spec_homepage(entry, spec)
- return if spec.homepage.nil? or spec.homepage.empty?
-
- entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4)
- end
-
- def spec_license(entry, spec)
- return if spec.license.nil? or spec.license.empty?
-
- licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: ".dup
- licenses << spec.licenses.join(', ')
- entry << "\n" << format_text(licenses, 68, 4)
- end
-
- def spec_loaded_from(entry, spec, specs)
- return unless spec.loaded_from
-
- if specs.length == 1
- default = spec.default_gem? ? ' (default)' : nil
- entry << "\n" << " Installed at#{default}: #{spec.base_dir}"
- else
- label = 'Installed at'
- specs.each do |s|
- version = s.version.to_s
- version << ', default' if s.default_gem?
- entry << "\n" << " #{label} (#{version}): #{s.base_dir}"
- label = ' ' * label.length
- end
- end
- end
-
- def spec_platforms(entry, platforms)
- non_ruby = platforms.any? do |_, pls|
- pls.any? { |pl| pl != Gem::Platform::RUBY }
- end
-
- return unless non_ruby
-
- if platforms.length == 1
- title = platforms.values.length == 1 ? 'Platform' : 'Platforms'
- entry << " #{title}: #{platforms.values.sort.join(', ')}\n"
- else
- entry << " Platforms:\n"
-
- sorted_platforms = platforms.sort_by { |version,| version }
-
- sorted_platforms.each do |version, pls|
- label = " #{version}: "
- data = format_text pls.sort.join(', '), 68, label.length
- data[0, label.length] = label
- entry << data << "\n"
- end
- end
- end
-
- def spec_summary(entry, spec)
- summary = truncate_text(spec.summary, "the summary for #{spec.full_name}")
- entry << "\n\n" << format_text(summary, 68, 4)
- end
-
end
diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb
index ff9e1ffcfa..305c80ccfe 100644
--- a/lib/rubygems/commands/rdoc_command.rb
+++ b/lib/rubygems/commands/rdoc_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/rdoc'
+require_relative '../command'
+require_relative '../version_option'
+require_relative '../rdoc'
require 'fileutils'
class Gem::Commands::RdocCommand < Gem::Command
-
include Gem::VersionOption
def initialize
@@ -93,5 +92,4 @@ Use --overwrite to force rebuilding of documentation.
end
end
end
-
end
diff --git a/lib/rubygems/commands/search_command.rb b/lib/rubygems/commands/search_command.rb
index c9cb1f2d43..488d777939 100644
--- a/lib/rubygems/commands/search_command.rb
+++ b/lib/rubygems/commands/search_command.rb
@@ -1,15 +1,16 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/commands/query_command'
+require_relative '../command'
+require_relative '../query_utils'
-class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand
+class Gem::Commands::SearchCommand < Gem::Command
+ include Gem::QueryUtils
def initialize
- super 'search', 'Display remote gems whose name matches REGEXP'
+ super 'search', 'Display remote gems whose name matches REGEXP',
+ :name => //, :domain => :remote, :details => false, :versions => true,
+ :installed => nil, :version => Gem::Requirement.default
- remove_option '--name-matches'
-
- defaults[:domain] = :remote
+ add_query_options
end
def arguments # :nodoc:
@@ -36,5 +37,4 @@ To list local gems use the list command.
def usage # :nodoc:
"#{program_name} [REGEXP]"
end
-
end
diff --git a/lib/rubygems/commands/server_command.rb b/lib/rubygems/commands/server_command.rb
index e91a8e5176..79c682e8f4 100644
--- a/lib/rubygems/commands/server_command.rb
+++ b/lib/rubygems/commands/server_command.rb
@@ -1,17 +1,20 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/server'
+require_relative '../command'
+require_relative '../server'
+require_relative '../deprecate'
class Gem::Commands::ServerCommand < Gem::Command
+ extend Gem::Deprecate
+ rubygems_deprecate_command
def initialize
super 'server', 'Documentation and gem repository HTTP server',
:port => 8808, :gemdir => [], :daemon => false
- OptionParser.accept :Port do |port|
+ Gem::OptionParser.accept :Port do |port|
if port =~ /\A\d+\z/
port = Integer port
- raise OptionParser::InvalidArgument, "#{port}: not a port number" if
+ raise Gem::OptionParser::InvalidArgument, "#{port}: not a port number" if
port > 65535
port
@@ -19,7 +22,7 @@ class Gem::Commands::ServerCommand < Gem::Command
begin
Socket.getservbyname port
rescue SocketError
- raise OptionParser::InvalidArgument, "#{port}: no such named service"
+ raise Gem::OptionParser::InvalidArgument, "#{port}: no such named service"
end
end
end
@@ -82,5 +85,4 @@ You can set up a shortcut to gem server documentation using the URL:
options[:gemdir] = Gem.path if options[:gemdir].empty?
Gem::Server.run options
end
-
end
diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb
index 579776df7e..894f94b484 100644
--- a/lib/rubygems/commands/setup_command.rb
+++ b/lib/rubygems/commands/setup_command.rb
@@ -1,14 +1,13 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
##
# Installs RubyGems itself. This command is ordinarily only available from a
# RubyGems checkout or tarball.
class Gem::Commands::SetupCommand < Gem::Command
-
- HISTORY_HEADER = /^===\s*[\d.a-zA-Z]+\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/.freeze
- VERSION_MATCHER = /^===\s*([\d.a-zA-Z]+)\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/.freeze
+ HISTORY_HEADER = /^#\s*[\d.a-zA-Z]+\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/.freeze
+ VERSION_MATCHER = /^#\s*([\d.a-zA-Z]+)\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/.freeze
ENV_PATHS = %w[/usr/bin/env /bin/env].freeze
@@ -16,11 +15,12 @@ class Gem::Commands::SetupCommand < Gem::Command
require 'tmpdir'
super 'setup', 'Install RubyGems',
- :format_executable => true, :document => %w[ri],
+ :format_executable => false, :document => %w[ri],
:force => true,
:site_or_vendor => 'sitelibdir',
:destdir => '', :prefix => '', :previous_version => '',
- :regenerate_binstubs => true
+ :regenerate_binstubs => true,
+ :regenerate_plugins => true
add_option '--previous-version=VERSION',
'Previous version of RubyGems',
@@ -89,6 +89,11 @@ class Gem::Commands::SetupCommand < Gem::Command
options[:regenerate_binstubs] = value
end
+ add_option '--[no-]regenerate-plugins',
+ 'Regenerate gem plugins' do |value, options|
+ options[:regenerate_plugins] = value
+ end
+
add_option '-f', '--[no-]force',
'Forcefully overwrite binstubs' do |value, options|
options[:force] = value
@@ -144,13 +149,6 @@ By default, this RubyGems will install gem as:
def execute
@verbose = Gem.configuration.really_verbose
- install_destdir = options[:destdir]
-
- unless install_destdir.empty?
- ENV['GEM_HOME'] ||= File.join(install_destdir,
- Gem.default_dir.gsub(/^[a-zA-Z]:/, ''))
- end
-
check_ruby_version
require 'fileutils'
@@ -161,7 +159,8 @@ By default, this RubyGems will install gem as:
end
extend MakeDirs
- lib_dir, bin_dir = make_destination_dirs install_destdir
+ lib_dir, bin_dir = make_destination_dirs
+ man_dir = generate_default_man_dir
install_lib lib_dir
@@ -171,6 +170,9 @@ By default, this RubyGems will install gem as:
remove_old_lib_files lib_dir
+ # Can be removed one we drop support for bundler 2.2.3 (the last version installing man files to man_dir)
+ remove_old_man_files man_dir if man_dir && File.exist?(man_dir)
+
install_default_bundler_gem bin_dir
if mode = options[:dir_mode]
@@ -180,7 +182,8 @@ By default, this RubyGems will install gem as:
say "RubyGems #{Gem::VERSION} installed"
- regenerate_binstubs if options[:regenerate_binstubs]
+ regenerate_binstubs(bin_dir) if options[:regenerate_binstubs]
+ regenerate_plugins(bin_dir) if options[:regenerate_plugins]
uninstall_old_gemcutter
@@ -205,7 +208,7 @@ By default, this RubyGems will install gem as:
say
say "RubyGems installed the following executables:"
- say bin_file_names.map { |name| "\t#{name}\n" }
+ say bin_file_names.map {|name| "\t#{name}\n" }
say
unless bin_file_names.grep(/#{File::SEPARATOR}gem$/)
@@ -248,35 +251,32 @@ By default, this RubyGems will install gem as:
say "Installing #{tool} executable" if @verbose
Dir.chdir path do
- bin_files = Dir['*']
+ bin_file = "gem"
- bin_files -= %w[update_rubygems]
+ dest_file = target_bin_path(bin_dir, bin_file)
+ bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}"
- bin_files.each do |bin_file|
- dest_file = target_bin_path(bin_dir, bin_file)
- bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}"
+ begin
+ bin = File.readlines bin_file
+ bin[0] = shebang
- begin
- bin = File.readlines bin_file
- bin[0] = shebang
-
- File.open bin_tmp_file, 'w' do |fp|
- fp.puts bin.join
- end
-
- install bin_tmp_file, dest_file, :mode => prog_mode
- bin_file_names << dest_file
- ensure
- rm bin_tmp_file
+ File.open bin_tmp_file, 'w' do |fp|
+ fp.puts bin.join
end
- next unless Gem.win_platform?
+ install bin_tmp_file, dest_file, :mode => prog_mode
+ bin_file_names << dest_file
+ ensure
+ rm bin_tmp_file
+ end
+
+ next unless Gem.win_platform?
- begin
- bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat"
+ begin
+ bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat"
- File.open bin_cmd_file, 'w' do |file|
- file.puts <<-TEXT
+ File.open bin_cmd_file, 'w' do |file|
+ file.puts <<-TEXT
@ECHO OFF
IF NOT "%~f0" == "~f0" GOTO :WinNT
@"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9
@@ -284,12 +284,11 @@ By default, this RubyGems will install gem as:
:WinNT
@"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
TEXT
- end
-
- install bin_cmd_file, "#{dest_file}.bat", :mode => prog_mode
- ensure
- rm bin_cmd_file
end
+
+ install bin_cmd_file, "#{dest_file}.bat", :mode => prog_mode
+ ensure
+ rm bin_cmd_file
end
end
end
@@ -305,35 +304,16 @@ By default, this RubyGems will install gem as:
end
end
- def install_file(file, dest_dir)
- dest_file = File.join dest_dir, file
- dest_dir = File.dirname dest_file
- unless File.directory? dest_dir
- mkdir_p dest_dir, :mode => 0755
- end
-
- install file, dest_file, :mode => options[:data_mode] || 0644
- end
-
def install_lib(lib_dir)
libs = { 'RubyGems' => 'lib' }
libs['Bundler'] = 'bundler/lib'
libs.each do |tool, path|
say "Installing #{tool}" if @verbose
- lib_files = rb_files_in path
- lib_files.concat(template_files) if tool == 'Bundler'
-
- pem_files = pem_files_in path
+ lib_files = files_in path
Dir.chdir path do
- lib_files.each do |lib_file|
- install_file lib_file, lib_dir
- end
-
- pem_files.each do |pem_file|
- install_file pem_file, lib_dir
- end
+ install_file_list(lib_files, lib_dir)
end
end
end
@@ -357,7 +337,7 @@ By default, this RubyGems will install gem as:
rm_rf dir
end
- require 'rubygems/rdoc'
+ require_relative '../rdoc'
fake_spec = Gem::Specification.new 'rubygems', Gem::VERSION
def fake_spec.full_gem_path
@@ -380,17 +360,10 @@ By default, this RubyGems will install gem as:
end
def install_default_bundler_gem(bin_dir)
- specs_dir = Gem.default_specifications_dir
- specs_dir = File.join(options[:destdir], specs_dir) unless Gem.win_platform?
+ specs_dir = File.join(default_dir, "specifications", "default")
mkdir_p specs_dir, :mode => 0755
- # Workaround for non-git environment.
- gemspec = File.open('bundler/bundler.gemspec', 'rb'){|f| f.read.gsub(/`git ls-files -z`/, "''") }
- File.open('bundler/bundler.gemspec', 'w'){|f| f.write gemspec }
-
- bundler_spec = Gem::Specification.load("bundler/bundler.gemspec")
- bundler_spec.files = Dir.chdir("bundler") { Dir["{*.md,{lib,exe,man}/**/*}"] }
- bundler_spec.executables -= %w[bundler bundle_ruby]
+ bundler_spec = Dir.chdir("bundler") { Gem::Specification.load("bundler.gemspec") }
# Remove bundler-*.gemspec in default specification directory.
Dir.entries(specs_dir).
@@ -402,8 +375,20 @@ By default, this RubyGems will install gem as:
bundler_spec = Gem::Specification.load(default_spec_path)
+ # The base_dir value for a specification is inferred by walking up from the
+ # folder where the spec was `loaded_from`. In the case of default gems, we
+ # walk up two levels, because they live at `specifications/default/`, whereas
+ # in the case of regular gems we walk up just one level because they live at
+ # `specifications/`. However, in this case, the gem we are installing is
+ # misdetected as a regular gem, when it's a default gem in reality. This is
+ # because when there's a `:destdir`, the `loaded_from` path has changed and
+ # doesn't match `Gem.default_specifications_dir` which is the criteria to
+ # tag a gem as a default gem. So, in that case, write the correct
+ # `@base_dir` directly.
+ bundler_spec.instance_variable_set(:@base_dir, File.dirname(File.dirname(specs_dir)))
+
# Remove gemspec that was same version of vendored bundler.
- normal_gemspec = File.join(Gem.default_dir, "specifications", "bundler-#{bundler_spec.version}.gemspec")
+ normal_gemspec = File.join(default_dir, "specifications", "bundler-#{bundler_spec.version}.gemspec")
if File.file? normal_gemspec
File.delete normal_gemspec
end
@@ -416,19 +401,26 @@ By default, this RubyGems will install gem as:
end
bundler_bin_dir = bundler_spec.bin_dir
- bundler_bin_dir = File.join(options[:destdir], bundler_bin_dir) unless Gem.win_platform?
mkdir_p bundler_bin_dir, :mode => 0755
bundler_spec.executables.each do |e|
cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_bin_dir, e)
end
- require 'rubygems/installer'
+ require_relative '../installer'
Dir.chdir("bundler") do
built_gem = Gem::Package.build(bundler_spec)
begin
- installer = Gem::Installer.at(built_gem, env_shebang: options[:env_shebang], format_executable: options[:format_executable], force: options[:force], install_as_default: true, bin_dir: bin_dir, wrappers: true)
- installer.install
+ Gem::Installer.at(
+ built_gem,
+ env_shebang: options[:env_shebang],
+ format_executable: options[:format_executable],
+ force: options[:force],
+ install_as_default: true,
+ bin_dir: bin_dir,
+ install_dir: default_dir,
+ wrappers: true
+ ).install
ensure
FileUtils.rm_f built_gem
end
@@ -439,11 +431,11 @@ By default, this RubyGems will install gem as:
say "Bundler #{bundler_spec.version} installed"
end
- def make_destination_dirs(install_destdir)
+ def make_destination_dirs
lib_dir, bin_dir = Gem.default_rubygems_dirs
unless lib_dir
- lib_dir, bin_dir = generate_default_dirs(install_destdir)
+ lib_dir, bin_dir = generate_default_dirs
end
mkdir_p lib_dir, :mode => 0755
@@ -452,7 +444,20 @@ By default, this RubyGems will install gem as:
return lib_dir, bin_dir
end
- def generate_default_dirs(install_destdir)
+ def generate_default_man_dir
+ prefix = options[:prefix]
+
+ if prefix.empty?
+ man_dir = RbConfig::CONFIG['mandir']
+ return unless man_dir
+ else
+ man_dir = File.join prefix, 'man'
+ end
+
+ prepend_destdir_if_present(man_dir)
+ end
+
+ def generate_default_dirs
prefix = options[:prefix]
site_or_vendor = options[:site_or_vendor]
@@ -476,39 +481,13 @@ By default, this RubyGems will install gem as:
end
end
- unless install_destdir.empty?
- lib_dir = File.join install_destdir, lib_dir.gsub(/^[a-zA-Z]:/, '')
- bin_dir = File.join install_destdir, bin_dir.gsub(/^[a-zA-Z]:/, '')
- end
-
- [lib_dir, bin_dir]
- end
-
- def pem_files_in(dir)
- Dir.chdir dir do
- Dir[File.join('**', '*pem')]
- end
- end
-
- def rb_files_in(dir)
- Dir.chdir dir do
- Dir[File.join('**', '*rb')]
- end
- end
-
- # for installation of bundler as default gems
- def template_files
- Dir.chdir "bundler/lib" do
- (Dir[File.join('bundler', 'templates', '**', '{*,.*}')]).
- select{|f| !File.directory?(f)}
- end
+ [prepend_destdir_if_present(lib_dir), prepend_destdir_if_present(bin_dir)]
end
- # for cleanup old bundler files
- def template_files_in(dir)
+ def files_in(dir)
Dir.chdir dir do
- (Dir[File.join('templates', '**', '{*,.*}')]).
- select{|f| !File.directory?(f)}
+ Dir.glob(File.join('**', '*'), File::FNM_DOTMATCH).
+ select{|f| !File.directory?(f) }
end
end
@@ -539,7 +518,7 @@ abort "#{deprecation_message}"
next unless Gem.win_platform?
File.open "#{old_bin_path}.bat", 'w' do |fp|
- fp.puts %{@ECHO.#{deprecation_message}}
+ fp.puts %(@ECHO.#{deprecation_message})
end
end
end
@@ -548,31 +527,43 @@ abort "#{deprecation_message}"
lib_dirs = { File.join(lib_dir, 'rubygems') => 'lib/rubygems' }
lib_dirs[File.join(lib_dir, 'bundler')] = 'bundler/lib/bundler'
lib_dirs.each do |old_lib_dir, new_lib_dir|
- lib_files = rb_files_in(new_lib_dir)
- lib_files.concat(template_files_in(new_lib_dir)) if new_lib_dir =~ /bundler/
+ lib_files = files_in(new_lib_dir)
- old_lib_files = rb_files_in(old_lib_dir)
- old_lib_files.concat(template_files_in(old_lib_dir)) if old_lib_dir =~ /bundler/
+ old_lib_files = files_in(old_lib_dir)
to_remove = old_lib_files - lib_files
+ gauntlet_rubygems = File.join(lib_dir, 'gauntlet_rubygems.rb')
+ to_remove << gauntlet_rubygems if File.exist? gauntlet_rubygems
+
to_remove.delete_if do |file|
file.start_with? 'defaults'
end
- Dir.chdir old_lib_dir do
- to_remove.each do |file|
- FileUtils.rm_f file
+ remove_file_list(to_remove, old_lib_dir)
+ end
+ end
- warn "unable to remove old file #{file} please remove it by hand" if
- File.exist? file
- end
- end
+ def remove_old_man_files(old_man_dir)
+ old_man1_dir = "#{old_man_dir}/man1"
+
+ if File.exist?(old_man1_dir)
+ man1_to_remove = Dir.chdir(old_man1_dir) { Dir["bundle*.1{,.txt,.ronn}"] }
+
+ remove_file_list(man1_to_remove, old_man1_dir)
+ end
+
+ old_man5_dir = "#{old_man_dir}/man5"
+
+ if File.exist?(old_man5_dir)
+ man5_to_remove = Dir.chdir(old_man5_dir) { Dir["gemfile.5{,.txt,.ronn}"] }
+
+ remove_file_list(man5_to_remove, old_man5_dir)
end
end
def show_release_notes
- release_notes = File.join Dir.pwd, 'History.txt'
+ release_notes = File.join Dir.pwd, 'CHANGELOG.md'
release_notes =
if File.exist? release_notes
@@ -580,8 +571,6 @@ abort "#{deprecation_message}"
history.force_encoding Encoding::UTF_8
- history = history.sub(/^# coding:.*?(?=^=)/m, '')
-
text = history.split(HISTORY_HEADER)
text.shift # correct an off-by-one generated by split
version_lines = history.scan(HISTORY_HEADER)
@@ -605,7 +594,7 @@ abort "#{deprecation_message}"
end
def uninstall_old_gemcutter
- require 'rubygems/uninstaller'
+ require_relative '../uninstaller'
ui = Gem::Uninstaller.new('gemcutter', :all => true, :ignore => true,
:version => '< 0.4')
@@ -613,11 +602,12 @@ abort "#{deprecation_message}"
rescue Gem::InstallError
end
- def regenerate_binstubs
- require "rubygems/commands/pristine_command"
+ def regenerate_binstubs(bindir)
+ require_relative "pristine_command"
say "Regenerating binstubs"
args = %w[--all --only-executables --silent]
+ args << "--bindir=#{bindir}"
if options[:env_shebang]
args << "--env-shebang"
end
@@ -626,8 +616,66 @@ abort "#{deprecation_message}"
command.invoke(*args)
end
+ def regenerate_plugins(bindir)
+ require_relative "pristine_command"
+ say "Regenerating plugins"
+
+ args = %w[--all --only-plugins --silent]
+ args << "--bindir=#{bindir}"
+ args << "--install-dir=#{default_dir}"
+
+ command = Gem::Commands::PristineCommand.new
+ command.invoke(*args)
+ end
+
private
+ def default_dir
+ prefix = options[:prefix]
+
+ if prefix.empty?
+ dir = Gem.default_dir
+ else
+ dir = prefix
+ end
+
+ prepend_destdir_if_present(dir)
+ end
+
+ def prepend_destdir_if_present(path)
+ destdir = options[:destdir]
+ return path if destdir.empty?
+
+ File.join(options[:destdir], path.gsub(/^[a-zA-Z]:/, ''))
+ end
+
+ def install_file_list(files, dest_dir)
+ files.each do |file|
+ install_file file, dest_dir
+ end
+ end
+
+ def install_file(file, dest_dir)
+ dest_file = File.join dest_dir, file
+ dest_dir = File.dirname dest_file
+ unless File.directory? dest_dir
+ mkdir_p dest_dir, :mode => 0755
+ end
+
+ install file, dest_file, :mode => options[:data_mode] || 0644
+ end
+
+ def remove_file_list(files, dir)
+ Dir.chdir dir do
+ files.each do |file|
+ FileUtils.rm_f file
+
+ warn "unable to remove old file #{file} please remove it by hand" if
+ File.exist? file
+ end
+ end
+ end
+
def target_bin_path(bin_dir, bin_file)
bin_file_formatted = if options[:format_executable]
Gem.default_exec_format % bin_file
@@ -640,5 +688,4 @@ abort "#{deprecation_message}"
def bin_file_names
@bin_file_names ||= []
end
-
end
diff --git a/lib/rubygems/commands/signin_command.rb b/lib/rubygems/commands/signin_command.rb
index 7c4b5ceb69..23bb2f937f 100644
--- a/lib/rubygems/commands/signin_command.rb
+++ b/lib/rubygems/commands/signin_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/gemcutter_utilities'
+require_relative '../command'
+require_relative '../gemcutter_utilities'
class Gem::Commands::SigninCommand < Gem::Command
-
include Gem::GemcutterUtilities
def initialize
@@ -31,5 +30,4 @@ class Gem::Commands::SigninCommand < Gem::Command
def execute
sign_in options[:host]
end
-
end
diff --git a/lib/rubygems/commands/signout_command.rb b/lib/rubygems/commands/signout_command.rb
index 2d7329c590..c9485e0c1b 100644
--- a/lib/rubygems/commands/signout_command.rb
+++ b/lib/rubygems/commands/signout_command.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::SignoutCommand < Gem::Command
-
def initialize
super 'signout', 'Sign out from all the current sessions.'
end
@@ -29,5 +28,4 @@ class Gem::Commands::SignoutCommand < Gem::Command
say 'You have successfully signed out from all sessions.'
end
end
-
end
diff --git a/lib/rubygems/commands/sources_command.rb b/lib/rubygems/commands/sources_command.rb
index ca9d425232..9e74f3c47d 100644
--- a/lib/rubygems/commands/sources_command.rb
+++ b/lib/rubygems/commands/sources_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/remote_fetcher'
-require 'rubygems/spec_fetcher'
-require 'rubygems/local_remote_options'
+require_relative '../command'
+require_relative '../remote_fetcher'
+require_relative '../spec_fetcher'
+require_relative '../local_remote_options'
class Gem::Commands::SourcesCommand < Gem::Command
-
include Gem::LocalRemoteOptions
def initialize
@@ -35,6 +34,10 @@ class Gem::Commands::SourcesCommand < Gem::Command
options[:update] = value
end
+ add_option '-f', '--[no-]force', "Do not show any confirmation prompts and behave as if 'yes' was always answered" do |value, options|
+ options[:force] = value
+ end
+
add_proxy_option
end
@@ -72,7 +75,7 @@ class Gem::Commands::SourcesCommand < Gem::Command
Do you want to add this source?
QUESTION
- terminate_interaction 1 unless ask_yes_no question
+ terminate_interaction 1 unless options[:force] || ask_yes_no(question)
end
end
@@ -87,7 +90,7 @@ https://rubygems.org is recommended for security over #{uri}
Do you want to add this insecure source?
QUESTION
- terminate_interaction 1 unless ask_yes_no question
+ terminate_interaction 1 unless options[:force] || ask_yes_no(question)
end
end
@@ -220,5 +223,4 @@ To remove a source use the --remove argument:
say "*** Unable to remove #{desc} source cache ***"
end
end
-
end
diff --git a/lib/rubygems/commands/specification_command.rb b/lib/rubygems/commands/specification_command.rb
index 7326822ad7..473b6e7b19 100644
--- a/lib/rubygems/commands/specification_command.rb
+++ b/lib/rubygems/commands/specification_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/version_option'
-require 'rubygems/package'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../version_option'
+require_relative '../package'
class Gem::Commands::SpecificationCommand < Gem::Command
-
include Gem::LocalRemoteOptions
include Gem::VersionOption
@@ -119,7 +118,7 @@ Specific fields in the specification can be extracted in YAML format:
dep.prerelease = options[:prerelease]
found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dep
- specs.push(*found.map { |spec,| spec })
+ specs.push(*found.map {|spec,| spec })
end
if specs.empty?
@@ -127,8 +126,14 @@ Specific fields in the specification can be extracted in YAML format:
terminate_interaction 1
end
+ platform = get_platform_from_requirements(options)
+
+ if platform
+ specs = specs.select{|s| s.platform.to_s == platform }
+ end
+
unless options[:all]
- specs = [specs.max_by { |s| s.version }]
+ specs = [specs.max_by {|s| s.version }]
end
specs.each do |s|
@@ -143,5 +148,4 @@ Specific fields in the specification can be extracted in YAML format:
say "\n"
end
end
-
end
diff --git a/lib/rubygems/commands/stale_command.rb b/lib/rubygems/commands/stale_command.rb
index 89bafeae98..62a97966f1 100644
--- a/lib/rubygems/commands/stale_command.rb
+++ b/lib/rubygems/commands/stale_command.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::StaleCommand < Gem::Command
-
def initialize
super('stale', 'List gems along with access times')
end
@@ -33,9 +32,8 @@ longer using.
end
end
- gem_to_atime.sort_by { |_, atime| atime }.each do |name, atime|
+ gem_to_atime.sort_by {|_, atime| atime }.each do |name, atime|
say "#{name} at #{atime.strftime '%c'}"
end
end
-
end
diff --git a/lib/rubygems/commands/uninstall_command.rb b/lib/rubygems/commands/uninstall_command.rb
index c1a9dbba32..467c8bf7ed 100644
--- a/lib/rubygems/commands/uninstall_command.rb
+++ b/lib/rubygems/commands/uninstall_command.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/uninstaller'
+require_relative '../command'
+require_relative '../version_option'
+require_relative '../uninstaller'
require 'fileutils'
##
@@ -10,7 +10,6 @@ require 'fileutils'
# See `gem help uninstall`
class Gem::Commands::UninstallCommand < Gem::Command
-
include Gem::VersionOption
def initialize
@@ -82,7 +81,7 @@ class Gem::Commands::UninstallCommand < Gem::Command
'Uninstall gem from the vendor directory.',
'Only for use by gem repackagers.') do |value, options|
unless Gem.vendor_dir
- raise OptionParser::InvalidOption.new 'your platform is not supported'
+ raise Gem::OptionParser::InvalidOption.new 'your platform is not supported'
end
alert_warning 'Use your OS package manager to uninstall vendor gems'
@@ -136,7 +135,7 @@ that is a dependency of an existing gem. You can use the
end
def uninstall_all
- specs = Gem::Specification.reject { |spec| spec.default_gem? }
+ specs = Gem::Specification.reject {|spec| spec.default_gem? }
specs.each do |spec|
options[:version] = spec.version
@@ -195,5 +194,4 @@ that is a dependency of an existing gem. You can use the
def uninstall(gem_name)
Gem::Uninstaller.new(gem_name, options).uninstall
end
-
end
diff --git a/lib/rubygems/commands/unpack_command.rb b/lib/rubygems/commands/unpack_command.rb
index 09829d873c..3f1708375f 100644
--- a/lib/rubygems/commands/unpack_command.rb
+++ b/lib/rubygems/commands/unpack_command.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/version_option'
-require 'rubygems/security_option'
-require 'rubygems/remote_fetcher'
-require 'rubygems/package'
+require_relative '../command'
+require_relative '../version_option'
+require_relative '../security_option'
+require_relative '../remote_fetcher'
+require_relative '../package'
# forward-declare
@@ -13,7 +13,6 @@ module Gem::Security # :nodoc:
end
class Gem::Commands::UnpackCommand < Gem::Command
-
include Gem::VersionOption
include Gem::SecurityOption
@@ -157,7 +156,7 @@ command help for an example.
specs = dependency.matching_specs
- selected = specs.max_by { |s| s.version }
+ selected = specs.max_by {|s| s.version }
return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless
selected
@@ -173,5 +172,4 @@ command help for an example.
path
end
-
end
diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb
index e8031a259d..bb356fd610 100644
--- a/lib/rubygems/commands/update_command.rb
+++ b/lib/rubygems/commands/update_command.rb
@@ -1,16 +1,15 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/command_manager'
-require 'rubygems/dependency_installer'
-require 'rubygems/install_update_options'
-require 'rubygems/local_remote_options'
-require 'rubygems/spec_fetcher'
-require 'rubygems/version_option'
-require 'rubygems/install_message' # must come before rdoc for messaging
-require 'rubygems/rdoc'
+require_relative '../command'
+require_relative '../command_manager'
+require_relative '../dependency_installer'
+require_relative '../install_update_options'
+require_relative '../local_remote_options'
+require_relative '../spec_fetcher'
+require_relative '../version_option'
+require_relative '../install_message' # must come before rdoc for messaging
+require_relative '../rdoc'
class Gem::Commands::UpdateCommand < Gem::Command
-
include Gem::InstallUpdateOptions
include Gem::LocalRemoteOptions
include Gem::VersionOption
@@ -26,7 +25,7 @@ class Gem::Commands::UpdateCommand < Gem::Command
add_install_update_options
- OptionParser.accept Gem::Version do |value|
+ Gem::OptionParser.accept Gem::Version do |value|
Gem::Version.new value
value
@@ -73,8 +72,13 @@ command to remove old versions.
say "Latest version already installed. Done."
terminate_interaction
end
+ end
- options[:user_install] = false
+ def check_oldest_rubygems(version) # :nodoc:
+ if oldest_supported_version > version
+ alert_error "rubygems #{version} is not supported on #{RUBY_VERSION}. The oldest version supported by this ruby is #{oldest_supported_version}"
+ terminate_interaction 1
+ end
end
def check_update_arguments # :nodoc:
@@ -90,9 +94,10 @@ command to remove old versions.
return
end
- hig = highest_installed_gems
-
- gems_to_update = which_to_update hig, options[:args].uniq
+ gems_to_update = which_to_update(
+ highest_installed_gems,
+ options[:args].uniq
+ )
if options[:explain]
say "Gems to update:"
@@ -108,7 +113,7 @@ command to remove old versions.
updated = update_gems gems_to_update
- updated_names = updated.map { |spec| spec.name }
+ updated_names = updated.map {|spec| spec.name }
not_updated_names = options[:args].uniq - updated_names
if updated.empty?
@@ -127,7 +132,7 @@ command to remove old versions.
spec_tuples, errors = fetcher.search_for_dependency dependency
- error = errors.find { |e| e.respond_to? :exception }
+ error = errors.find {|e| e.respond_to? :exception }
raise error if error
@@ -137,6 +142,9 @@ command to remove old versions.
def highest_installed_gems # :nodoc:
hig = {} # highest installed gems
+ # Get only gem specifications installed as --user-install
+ Gem::Specification.dirs = Gem.user_dir if options[:user_install]
+
Gem::Specification.each do |spec|
if hig[spec.name].nil? or hig[spec.name].version < spec.version
hig[spec.name] = spec
@@ -166,10 +174,33 @@ command to remove old versions.
update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}"
Dir.chdir update_dir do
- say "Installing RubyGems #{version}"
+ say "Installing RubyGems #{version}" unless options[:silent]
+
+ installed = preparing_gem_layout_for(version) do
+ system Gem.ruby, '--disable-gems', 'setup.rb', *args
+ end
+
+ say "RubyGems system software updated" if installed unless options[:silent]
+ end
+ end
- installed = system Gem.ruby, '--disable-gems', 'setup.rb', *args
- say "RubyGems system software updated" if installed
+ def preparing_gem_layout_for(version)
+ if Gem::Version.new(version) >= Gem::Version.new("3.2.a")
+ yield
+ else
+ require "tmpdir"
+ tmpdir = Dir.mktmpdir
+ FileUtils.mv Gem.plugindir, tmpdir
+
+ status = yield
+
+ if status
+ FileUtils.rm_rf tmpdir
+ else
+ FileUtils.mv File.join(tmpdir, "plugins"), Gem.plugindir
+ end
+
+ status
end
end
@@ -190,7 +221,7 @@ command to remove old versions.
rubygems_update.version = version
hig = {
- 'rubygems-update' => rubygems_update
+ 'rubygems-update' => rubygems_update,
}
gems_to_update = which_to_update hig, options[:args], :system
@@ -206,14 +237,14 @@ command to remove old versions.
end
def update_gem(name, version = Gem::Requirement.default)
- return if @updated.any? { |spec| spec.name == name }
+ return if @updated.any? {|spec| spec.name == name }
update_options = options.dup
update_options[:prerelease] = version.prerelease?
@installer = Gem::DependencyInstaller.new update_options
- say "Updating #{name}"
+ say "Updating #{name}" unless options[:system] && options[:silent]
begin
@installer.install name, Gem::Requirement.new(version)
rescue Gem::InstallError, Gem::DependencyError => e
@@ -237,12 +268,19 @@ command to remove old versions.
# Update RubyGems software to the latest version.
def update_rubygems
+ if Gem.disable_system_update_message
+ alert_error Gem.disable_system_update_message
+ terminate_interaction 1
+ end
+
check_update_arguments
version, requirement = rubygems_target_version
check_latest_rubygems version
+ check_oldest_rubygems version
+
update_gem 'rubygems-update', version
installed_gems = Gem::Specification.find_all_by_name 'rubygems-update', requirement
@@ -253,6 +291,7 @@ command to remove old versions.
def update_rubygems_arguments # :nodoc:
args = []
+ args << '--silent' if options[:silent]
args << '--prefix' << Gem.prefix if Gem.prefix
args << '--no-document' unless options[:document].include?('rdoc') || options[:document].include?('ri')
args << '--no-format-executable' if options[:no_format_executable]
@@ -267,7 +306,7 @@ command to remove old versions.
highest_installed_gems.each do |l_name, l_spec|
next if not gem_names.empty? and
- gem_names.none? { |name| name == l_spec.name }
+ gem_names.none? {|name| name == l_spec.name }
highest_remote_tup = highest_remote_name_tuple l_spec
highest_remote_ver = highest_remote_tup.version
@@ -281,4 +320,28 @@ command to remove old versions.
result
end
+ private
+
+ #
+ # Oldest version we support downgrading to. This is the version that
+ # originally ships with the first patch version of each ruby, because we never
+ # test each ruby against older rubygems, so we can't really guarantee it
+ # works. Version list can be checked here: https://stdgems.org/rubygems
+ #
+ def oldest_supported_version
+ @oldest_supported_version ||=
+ if Gem.ruby_version > Gem::Version.new("3.0.a")
+ Gem::Version.new("3.2.3")
+ elsif Gem.ruby_version > Gem::Version.new("2.7.a")
+ Gem::Version.new("3.1.2")
+ elsif Gem.ruby_version > Gem::Version.new("2.6.a")
+ Gem::Version.new("3.0.1")
+ elsif Gem.ruby_version > Gem::Version.new("2.5.a")
+ Gem::Version.new("2.7.3")
+ elsif Gem.ruby_version > Gem::Version.new("2.4.a")
+ Gem::Version.new("2.6.8")
+ else
+ Gem::Version.new("2.5.2")
+ end
+ end
end
diff --git a/lib/rubygems/commands/which_command.rb b/lib/rubygems/commands/which_command.rb
index fca463a1ef..44e87a2b98 100644
--- a/lib/rubygems/commands/which_command.rb
+++ b/lib/rubygems/commands/which_command.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/command'
+require_relative '../command'
class Gem::Commands::WhichCommand < Gem::Command
-
def initialize
super 'which', 'Find the location of a library file you can require',
:search_gems_first => false, :show_all => false
@@ -85,5 +84,4 @@ requiring to see why it does not behave as you expect.
def usage # :nodoc:
"#{program_name} FILE [FILE ...]"
end
-
end
diff --git a/lib/rubygems/commands/yank_command.rb b/lib/rubygems/commands/yank_command.rb
index 3ca05756f6..cad78aec5f 100644
--- a/lib/rubygems/commands/yank_command.rb
+++ b/lib/rubygems/commands/yank_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/command'
-require 'rubygems/local_remote_options'
-require 'rubygems/version_option'
-require 'rubygems/gemcutter_utilities'
+require_relative '../command'
+require_relative '../local_remote_options'
+require_relative '../version_option'
+require_relative '../gemcutter_utilities'
class Gem::Commands::YankCommand < Gem::Command
-
include Gem::LocalRemoteOptions
include Gem::VersionOption
include Gem::GemcutterUtilities
@@ -25,7 +24,7 @@ data you will need to change them immediately and yank your gem.
end
def usage # :nodoc:
- "#{program_name} GEM -v VERSION [-p PLATFORM] [--key KEY_NAME] [--host HOST]"
+ "#{program_name} -v VERSION [-p PLATFORM] [--key KEY_NAME] [--host HOST] GEM"
end
def initialize
@@ -48,7 +47,7 @@ data you will need to change them immediately and yank your gem.
def execute
@host = options[:host]
- sign_in @host
+ sign_in @host, scope: get_yank_scope
version = get_version_from_requirements(options[:version])
platform = get_platform_from_requirements(options)
@@ -73,9 +72,8 @@ data you will need to change them immediately and yank your gem.
def yank_api_request(method, version, platform, api)
name = get_one_gem_name
- response = rubygems_api_request(method, api, host) do |request|
+ response = rubygems_api_request(method, api, host, scope: get_yank_scope) do |request|
request.add_field("Authorization", api_key)
- request.add_field("OTP", options[:otp]) if options[:otp]
data = {
'gem_name' => name,
@@ -94,8 +92,7 @@ data you will need to change them immediately and yank your gem.
nil
end
- def get_platform_from_requirements(requirements)
- Gem.platforms[1].to_s if requirements.key? :added_platform
+ def get_yank_scope
+ :yank_rubygem
end
-
end
diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb
index 54d8a9c152..60c1d50ba9 100644
--- a/lib/rubygems/config_file.rb
+++ b/lib/rubygems/config_file.rb
@@ -5,7 +5,7 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/user_interaction'
+require_relative 'user_interaction'
require 'rbconfig'
##
@@ -37,7 +37,6 @@ require 'rbconfig'
# - per environment (gemrc files listed in the GEMRC environment variable)
class Gem::ConfigFile
-
include Gem::UserInteraction
DEFAULT_BACKTRACE = false
@@ -46,6 +45,7 @@ class Gem::ConfigFile
DEFAULT_UPDATE_SOURCES = true
DEFAULT_CONCURRENT_DOWNLOADS = 8
DEFAULT_CERT_EXPIRATION_LENGTH_DAYS = 365
+ DEFAULT_IPV4_FALLBACK_ENABLED = false
##
# For Ruby packagers to set configuration defaults. Set in
@@ -142,6 +142,12 @@ class Gem::ConfigFile
attr_accessor :cert_expiration_length_days
##
+ # == Experimental ==
+ # Fallback to IPv4 when IPv6 is not reachable or slow (default: false)
+
+ attr_accessor :ipv4_fallback_enabled
+
+ ##
# Path name of directory or file of openssl client certificate, used for remote https connection with client authentication
attr_reader :ssl_client_cert
@@ -176,6 +182,7 @@ class Gem::ConfigFile
@update_sources = DEFAULT_UPDATE_SOURCES
@concurrent_downloads = DEFAULT_CONCURRENT_DOWNLOADS
@cert_expiration_length_days = DEFAULT_CERT_EXPIRATION_LENGTH_DAYS
+ @ipv4_fallback_enabled = ENV['IPV4_FALLBACK_ENABLED'] == 'true' || DEFAULT_IPV4_FALLBACK_ENABLED
operating_system_config = Marshal.load Marshal.dump(OPERATING_SYSTEM_DEFAULTS)
platform_config = Marshal.load Marshal.dump(PLATFORM_DEFAULTS)
@@ -204,6 +211,7 @@ class Gem::ConfigFile
@disable_default_gem_server = @hash[:disable_default_gem_server] if @hash.key? :disable_default_gem_server
@sources = @hash[:sources] if @hash.key? :sources
@cert_expiration_length_days = @hash[:cert_expiration_length_days] if @hash.key? :cert_expiration_length_days
+ @ipv4_fallback_enabled = @hash[:ipv4_fallback_enabled] if @hash.key? :ipv4_fallback_enabled
@ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode
@ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert
@@ -261,7 +269,12 @@ if you believe they were disclosed to a third party.
# Location of RubyGems.org credentials
def credentials_path
- File.join Gem.user_home, '.gem', 'credentials'
+ credentials = File.join Gem.user_home, '.gem', 'credentials'
+ if File.exist? credentials
+ credentials
+ else
+ File.join Gem.data_home, "gem", "credentials"
+ end
end
def load_api_keys
@@ -307,7 +320,8 @@ if you believe they were disclosed to a third party.
config = load_file(credentials_path).merge(host => api_key)
dirname = File.dirname credentials_path
- Dir.mkdir(dirname) unless File.exist? dirname
+ require 'fileutils'
+ FileUtils.mkdir_p(dirname)
Gem.load_yaml
@@ -429,7 +443,7 @@ if you believe they were disclosed to a third party.
yaml_hash[:ssl_client_cert] =
@hash[:ssl_client_cert] if @hash.key? :ssl_client_cert
- keys = yaml_hash.keys.map { |key| key.to_s }
+ keys = yaml_hash.keys.map {|key| key.to_s }
keys << 'debug'
re = Regexp.union(*keys)
@@ -444,6 +458,9 @@ if you believe they were disclosed to a third party.
# Writes out this config file, replacing its source.
def write
+ require 'fileutils'
+ FileUtils.mkdir_p File.dirname(config_file_name)
+
File.open config_file_name, 'w' do |io|
io.write to_yaml
end
@@ -488,5 +505,4 @@ if you believe they were disclosed to a third party.
end
end
end
-
end
diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb
index 115ae0cb50..4b867c55e9 100644
--- a/lib/rubygems/core_ext/kernel_require.rb
+++ b/lib/rubygems/core_ext/kernel_require.rb
@@ -17,6 +17,8 @@ module Kernel
private :gem_original_require
end
+ file = Gem::KERNEL_WARN_IGNORES_INTERNAL_ENTRIES ? "<internal:#{__FILE__}>" : __FILE__
+ module_eval <<'RUBY', file, __LINE__ + 1
##
# When RubyGems is required, Kernel#require is replaced with our own which
# is capable of loading gems on demand.
@@ -130,7 +132,7 @@ module Kernel
# Ok, now find a gem that has no conflicts, starting
# at the highest version.
- valid = found_specs.find { |s| !s.has_conflicts? }
+ valid = found_specs.find {|s| !s.has_conflicts? }
unless valid
le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
@@ -148,7 +150,7 @@ module Kernel
RUBYGEMS_ACTIVATION_MONITOR.enter
begin
- if load_error.message.end_with?(path) and Gem.try_activate(path)
+ if load_error.path == path and Gem.try_activate(path)
require_again = true
end
ensure
@@ -166,6 +168,7 @@ module Kernel
end
end
end
+RUBY
private :require
diff --git a/lib/rubygems/core_ext/kernel_warn.rb b/lib/rubygems/core_ext/kernel_warn.rb
index dfc577df0b..3373cfdd3b 100644
--- a/lib/rubygems/core_ext/kernel_warn.rb
+++ b/lib/rubygems/core_ext/kernel_warn.rb
@@ -1,27 +1,25 @@
# frozen_string_literal: true
# `uplevel` keyword argument of Kernel#warn is available since ruby 2.5.
-if RUBY_VERSION >= "2.5"
+if RUBY_VERSION >= "2.5" && !Gem::KERNEL_WARN_IGNORES_INTERNAL_ENTRIES
module Kernel
- path = "#{__dir__}/" # Frames to be skipped start with this path.
+ rubygems_path = "#{__dir__}/" # Frames to be skipped start with this path.
- original_warn = method(:warn)
+ original_warn = instance_method(:warn)
remove_method :warn
class << self
-
remove_method :warn
-
end
module_function define_method(:warn) {|*messages, **kw|
unless uplevel = kw[:uplevel]
if Gem.java_platform?
- return original_warn.call(*messages)
+ return original_warn.bind(self).call(*messages)
else
- return original_warn.call(*messages, **kw)
+ return original_warn.bind(self).call(*messages, **kw)
end
end
@@ -40,16 +38,17 @@ if RUBY_VERSION >= "2.5"
start += 1
- unless loc.path.start_with?(path)
- # Non-rubygems frames
- uplevel -= 1
+ if path = loc.path
+ unless path.start_with?(rubygems_path) or path.start_with?('<internal:')
+ # Non-rubygems frames
+ uplevel -= 1
+ end
end
end
- uplevel = start
+ kw[:uplevel] = start
end
- kw[:uplevel] = uplevel
- original_warn.call(*messages, **kw)
+ original_warn.bind(self).call(*messages, **kw)
}
end
end
diff --git a/lib/rubygems/core_ext/tcpsocket_init.rb b/lib/rubygems/core_ext/tcpsocket_init.rb
new file mode 100644
index 0000000000..2a79b63bd6
--- /dev/null
+++ b/lib/rubygems/core_ext/tcpsocket_init.rb
@@ -0,0 +1,52 @@
+require 'socket'
+
+module CoreExtensions
+ module TCPSocketExt
+ def self.prepended(base)
+ base.prepend Initializer
+ end
+
+ module Initializer
+ CONNECTION_TIMEOUT = 5
+ IPV4_DELAY_SECONDS = 0.1
+
+ def initialize(host, serv, *rest)
+ mutex = Thread::Mutex.new
+ addrs = []
+ threads = []
+ cond_var = Thread::ConditionVariable.new
+
+ Addrinfo.foreach(host, serv, nil, :STREAM) do |addr|
+ Thread.report_on_exception = false if defined? Thread.report_on_exception = ()
+
+ threads << Thread.new(addr) do
+ # give head start to ipv6 addresses
+ sleep IPV4_DELAY_SECONDS if addr.ipv4?
+
+ # raises Errno::ECONNREFUSED when ip:port is unreachable
+ Socket.tcp(addr.ip_address, serv, connect_timeout: CONNECTION_TIMEOUT).close
+ mutex.synchronize do
+ addrs << addr.ip_address
+ cond_var.signal
+ end
+ end
+ end
+
+ mutex.synchronize do
+ timeout_time = CONNECTION_TIMEOUT + Time.now.to_f
+ while addrs.empty? && (remaining_time = timeout_time - Time.now.to_f) > 0
+ cond_var.wait(mutex, remaining_time)
+ end
+
+ host = addrs.shift unless addrs.empty?
+ end
+
+ threads.each {|t| t.kill.join if t.alive? }
+
+ super(host, serv, *rest)
+ end
+ end
+ end
+end
+
+TCPSocket.prepend CoreExtensions::TCPSocketExt
diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb
index d4ff4a262c..923b60f31f 100644
--- a/lib/rubygems/defaults.rb
+++ b/lib/rubygems/defaults.rb
@@ -20,7 +20,13 @@ module Gem
# specified in the environment
def self.default_spec_cache_dir
- File.join Gem.user_home, '.gem', 'specs'
+ default_spec_cache_dir = File.join Gem.user_home, '.gem', 'specs'
+
+ unless File.exist?(default_spec_cache_dir)
+ default_spec_cache_dir = File.join Gem.data_home, 'gem', 'specs'
+ end
+
+ default_spec_cache_dir
end
##
@@ -32,13 +38,13 @@ module Gem
[
File.dirname(RbConfig::CONFIG['sitedir']),
'Gems',
- RbConfig::CONFIG['ruby_version']
+ RbConfig::CONFIG['ruby_version'],
]
else
[
RbConfig::CONFIG['rubylibprefix'],
'gems',
- RbConfig::CONFIG['ruby_version']
+ RbConfig::CONFIG['ruby_version'],
]
end
@@ -67,19 +73,95 @@ module Gem
# Path to specification files of default gems.
def self.default_specifications_dir
- File.join(Gem.default_dir, "specifications", "default")
+ @default_specifications_dir ||= File.join(Gem.default_dir, "specifications", "default")
+ end
+
+ ##
+ # Finds the user's home directory.
+ #--
+ # Some comments from the ruby-talk list regarding finding the home
+ # directory:
+ #
+ # I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
+ # to be depending on HOME in those code samples. I propose that
+ # it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
+ # least on Win32).
+ #++
+ #--
+ #
+ #++
+
+ def self.find_home
+ Dir.home.dup
+ rescue
+ if Gem.win_platform?
+ File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/')
+ else
+ File.expand_path "/"
+ end
+ end
+
+ private_class_method :find_home
+
+ ##
+ # The home directory for the user.
+
+ def self.user_home
+ @user_home ||= find_home.tap(&Gem::UNTAINT)
end
##
# Path for gems in the user's home directory
def self.user_dir
- parts = [Gem.user_home, '.gem', ruby_engine]
+ gem_dir = File.join(Gem.user_home, ".gem")
+ gem_dir = File.join(Gem.data_home, "gem") unless File.exist?(gem_dir)
+ parts = [gem_dir, ruby_engine]
parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty?
File.join parts
end
##
+ # The path to standard location of the user's configuration directory.
+
+ def self.config_home
+ @config_home ||= (ENV["XDG_CONFIG_HOME"] || File.join(Gem.user_home, '.config'))
+ end
+
+ ##
+ # Finds the user's config file
+
+ def self.find_config_file
+ gemrc = File.join Gem.user_home, '.gemrc'
+ if File.exist? gemrc
+ gemrc
+ else
+ File.join Gem.config_home, "gem", "gemrc"
+ end
+ end
+
+ ##
+ # The path to standard location of the user's .gemrc file.
+
+ def self.config_file
+ @config_file ||= find_config_file.tap(&Gem::UNTAINT)
+ end
+
+ ##
+ # The path to standard location of the user's cache directory.
+
+ def self.cache_home
+ @cache_home ||= (ENV["XDG_CACHE_HOME"] || File.join(Gem.user_home, '.cache'))
+ end
+
+ ##
+ # The path to standard location of the user's data directory.
+
+ def self.data_home
+ @data_home ||= (ENV["XDG_DATA_HOME"] || File.join(Gem.user_home, '.local', 'share'))
+ end
+
+ ##
# How String Gem paths should be split. Overridable for esoteric platforms.
def self.path_separator
@@ -115,8 +197,8 @@ module Gem
# The default directory for binaries
def self.default_bindir
- if defined? RUBY_FRAMEWORK_VERSION # mac framework support
- '/usr/bin'
+ if defined? RUBY_FRAMEWORK_VERSION # mac framework support
+ '/usr/local/bin'
else # generic install
RbConfig::CONFIG['bindir']
end
@@ -130,14 +212,26 @@ module Gem
# The default signing key path
def self.default_key_path
- File.join Gem.user_home, ".gem", "gem-private_key.pem"
+ default_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem"
+
+ unless File.exist?(default_key_path)
+ default_key_path = File.join Gem.data_home, "gem", "gem-private_key.pem"
+ end
+
+ default_key_path
end
##
# The default signing certificate chain path
def self.default_cert_path
- File.join Gem.user_home, ".gem", "gem-public_cert.pem"
+ default_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem"
+
+ unless File.exist?(default_cert_path)
+ default_cert_path = File.join Gem.data_home, "gem", "gem-public_cert.pem"
+ end
+
+ default_cert_path
end
##
diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb
index 0c58815c85..3721204ab2 100644
--- a/lib/rubygems/dependency.rb
+++ b/lib/rubygems/dependency.rb
@@ -2,11 +2,7 @@
##
# The Dependency class holds a Gem name and a Gem::Requirement.
-require "rubygems/bundler_version_finder"
-require "rubygems/requirement"
-
class Gem::Dependency
-
##
# Valid dependency types.
#--
@@ -281,11 +277,11 @@ class Gem::Dependency
requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
end.map(&:to_spec)
- Gem::BundlerVersionFinder.filter!(matches) if name == "bundler".freeze && !requirement.specific?
+ Gem::BundlerVersionFinder.filter!(matches) if filters_bundler?
if platform_only
matches.reject! do |spec|
- spec.nil? || !Gem::Platform.match(spec.platform)
+ spec.nil? || !Gem::Platform.match_spec?(spec)
end
end
@@ -299,6 +295,10 @@ class Gem::Dependency
@requirement.specific?
end
+ def filters_bundler?
+ name == "bundler".freeze && !specific?
+ end
+
def to_specs
matches = matching_specs true
@@ -322,13 +322,13 @@ class Gem::Dependency
def to_spec
matches = self.to_specs.compact
- active = matches.find { |spec| spec.activated? }
+ active = matches.find {|spec| spec.activated? }
return active if active
return matches.first if prerelease?
# Move prereleases to the end of the list for >= 0 requirements
- pre, matches = matches.partition { |spec| spec.version.prerelease? }
+ pre, matches = matches.partition {|spec| spec.version.prerelease? }
matches += pre if requirement == Gem::Requirement.default
matches.first
@@ -347,5 +347,4 @@ class Gem::Dependency
:released
end
end
-
end
diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb
index 6d45688888..913bba32eb 100644
--- a/lib/rubygems/dependency_installer.rb
+++ b/lib/rubygems/dependency_installer.rb
@@ -1,19 +1,17 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/dependency_list'
-require 'rubygems/package'
-require 'rubygems/installer'
-require 'rubygems/spec_fetcher'
-require 'rubygems/user_interaction'
-require 'rubygems/source'
-require 'rubygems/available_set'
-require 'rubygems/deprecate'
+require_relative '../rubygems'
+require_relative 'dependency_list'
+require_relative 'package'
+require_relative 'installer'
+require_relative 'spec_fetcher'
+require_relative 'user_interaction'
+require_relative 'available_set'
+require_relative 'deprecate'
##
# Installs a gem along with all its dependencies from local and remote gems.
class Gem::DependencyInstaller
-
include Gem::UserInteraction
extend Gem::Deprecate
@@ -29,7 +27,7 @@ class Gem::DependencyInstaller
:wrappers => true,
:build_args => nil,
:build_docs_in_background => false,
- :install_as_default => false
+ :install_as_default => false,
}.freeze
##
@@ -107,27 +105,6 @@ class Gem::DependencyInstaller
end
##
- # Creates an AvailableSet to install from based on +dep_or_name+ and
- # +version+
-
- def available_set_for(dep_or_name, version) # :nodoc:
- if String === dep_or_name
- Gem::Deprecate.skip_during do
- find_spec_by_name_and_version dep_or_name, version, @prerelease
- end
- else
- dep = dep_or_name.dup
- dep.prerelease = @prerelease
- @available = Gem::Deprecate.skip_during do
- find_gems_with_sources dep
- end
- end
-
- @available.pick_best!
- end
- deprecate :available_set_for, :none, 2019, 12
-
- ##
# Indicated, based on the requested domain, if local
# gems should be considered.
@@ -216,57 +193,7 @@ class Gem::DependencyInstaller
set
end
- deprecate :find_gems_with_sources, :none, 2019, 12
-
- ##
- # Finds a spec and the source_uri it came from for gem +gem_name+ and
- # +version+. Returns an Array of specs and sources required for
- # installation of the gem.
-
- def find_spec_by_name_and_version(gem_name,
- version = Gem::Requirement.default,
- prerelease = false)
- set = Gem::AvailableSet.new
-
- if consider_local?
- if gem_name =~ /\.gem$/ and File.file? gem_name
- src = Gem::Source::SpecificFile.new(gem_name)
- set.add src.spec, src
- elsif gem_name =~ /\.gem$/
- Dir[gem_name].each do |name|
- begin
- src = Gem::Source::SpecificFile.new name
- set.add src.spec, src
- rescue Gem::Package::FormatError
- end
- end
- else
- local = Gem::Source::Local.new
-
- if s = local.find_gem(gem_name, version)
- set.add s, local
- end
- end
- end
-
- if set.empty?
- dep = Gem::Dependency.new gem_name, version
- dep.prerelease = true if prerelease
-
- set = Gem::Deprecate.skip_during do
- find_gems_with_sources(dep, true)
- end
-
- set.match_platform!
- end
-
- if set.empty?
- raise Gem::SpecificGemNotFoundException.new(gem_name, version, @errors)
- end
-
- @available = set
- end
- deprecate :find_spec_by_name_and_version, :none, 2019, 12
+ rubygems_deprecate :find_gems_with_sources
def in_background(what) # :nodoc:
fork_happened = false
@@ -356,10 +283,10 @@ class Gem::DependencyInstaller
request_set.development_shallow = @dev_shallow
request_set.soft_missing = @force
request_set.prerelease = @prerelease
- request_set.remote = false unless consider_remote?
installer_set = Gem::Resolver::InstallerSet.new @domain
- installer_set.ignore_installed = @only_install_dir
+ installer_set.ignore_installed = (@minimal_deps == false) || @only_install_dir
+ installer_set.force = @force
if consider_local?
if dep_or_name =~ /\.gem$/ and File.file? dep_or_name
@@ -380,6 +307,7 @@ class Gem::DependencyInstaller
dependency =
if spec = installer_set.local?(dep_or_name)
+ installer_set.remote = nil if spec.dependencies.none?
Gem::Dependency.new spec.name, version
elsif String === dep_or_name
Gem::Dependency.new dep_or_name, version
@@ -394,6 +322,7 @@ class Gem::DependencyInstaller
installer_set.add_always_install dependency
request_set.always_install = installer_set.always_install
+ request_set.remote = installer_set.consider_remote?
if @ignore_dependencies
installer_set.ignore_dependencies = true
@@ -407,5 +336,4 @@ class Gem::DependencyInstaller
request_set
end
-
end
diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb
index db7a2f5ada..10e08fc703 100644
--- a/lib/rubygems/dependency_list.rb
+++ b/lib/rubygems/dependency_list.rb
@@ -5,8 +5,8 @@
# See LICENSE.txt for permissions.
#++
-require 'tsort'
-require 'rubygems/deprecate'
+require_relative 'tsort'
+require_relative 'deprecate'
##
# Gem::DependencyList is used for installing and uninstalling gems in the
@@ -17,11 +17,10 @@ require 'rubygems/deprecate'
# this class necessary anymore? Especially #ok?, #why_not_ok?
class Gem::DependencyList
-
attr_reader :specs
include Enumerable
- include TSort
+ include Gem::TSort
##
# Allows enabling/disabling use of development dependencies
@@ -101,11 +100,11 @@ class Gem::DependencyList
end
def find_name(full_name)
- @specs.find { |spec| spec.full_name == full_name }
+ @specs.find {|spec| spec.full_name == full_name }
end
def inspect # :nodoc:
- "%s %p>" % [super[0..-2], map { |s| s.full_name }]
+ "%s %p>" % [super[0..-2], map {|s| s.full_name }]
end
##
@@ -116,7 +115,7 @@ class Gem::DependencyList
end
def why_not_ok?(quick = false)
- unsatisfied = Hash.new { |h,k| h[k] = [] }
+ unsatisfied = Hash.new {|h,k| h[k] = [] }
each do |spec|
spec.runtime_dependencies.each do |dep|
inst = Gem::Specification.any? do |installed_spec|
@@ -124,7 +123,7 @@ class Gem::DependencyList
dep.requirement.satisfied_by? installed_spec.version
end
- unless inst or @specs.find { |s| s.satisfies_requirement? dep }
+ unless inst or @specs.find {|s| s.satisfies_requirement? dep }
unsatisfied[spec.name] << dep
return unsatisfied if quick
end
@@ -184,7 +183,7 @@ class Gem::DependencyList
# Removes the gemspec matching +full_name+ from the dependency list
def remove_by_name(full_name)
- @specs.delete_if { |spec| spec.full_name == full_name }
+ @specs.delete_if {|spec| spec.full_name == full_name }
end
##
@@ -192,7 +191,7 @@ class Gem::DependencyList
# gemspecs that have a dependency satisfied by the named gemspec.
def spec_predecessors
- result = Hash.new { |h,k| h[k] = [] }
+ result = Hash.new {|h,k| h[k] = [] }
specs = @specs.sort.reverse
@@ -238,7 +237,6 @@ class Gem::DependencyList
# +ignored+.
def active_count(specs, ignored)
- specs.count { |spec| ignored[spec.full_name].nil? }
+ specs.count {|spec| ignored[spec.full_name].nil? }
end
-
end
diff --git a/lib/rubygems/deprecate.rb b/lib/rubygems/deprecate.rb
index 8accfb6174..8c822cda95 100644
--- a/lib/rubygems/deprecate.rb
+++ b/lib/rubygems/deprecate.rb
@@ -41,6 +41,10 @@ module Gem::Deprecate
Gem::Deprecate.skip = original
end
+ def self.next_rubygems_major_version # :nodoc:
+ Gem::Version.new(Gem.rubygems_version.segments.first).bump
+ end
+
##
# Simple deprecation method that deprecates +name+ by wrapping it up
# in a dummy method. It warns on each call to the dummy method
@@ -56,15 +60,58 @@ module Gem::Deprecate
target = klass ? "#{self}." : "#{self.class}#"
msg = [ "NOTE: #{target}#{name} is deprecated",
repl == :none ? " with no replacement" : "; use #{repl} instead",
- ". It will be removed on or after %4d-%02d-01." % [year, month],
+ ". It will be removed on or after %4d-%02d." % [year, month],
"\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}",
]
warn "#{msg.join}." unless Gem::Deprecate.skip
send old, *args, &block
end
+ ruby2_keywords name if respond_to?(:ruby2_keywords, true)
+ end
+ end
+
+ ##
+ # Simple deprecation method that deprecates +name+ by wrapping it up
+ # in a dummy method. It warns on each call to the dummy method
+ # telling the user of +repl+ (unless +repl+ is :none) and the
+ # Rubygems version that it is planned to go away.
+
+ def rubygems_deprecate(name, replacement=:none)
+ class_eval do
+ old = "_deprecated_#{name}"
+ alias_method old, name
+ define_method name do |*args, &block|
+ klass = self.kind_of? Module
+ target = klass ? "#{self}." : "#{self.class}#"
+ msg = [ "NOTE: #{target}#{name} is deprecated",
+ replacement == :none ? " with no replacement" : "; use #{replacement} instead",
+ ". It will be removed in Rubygems #{Gem::Deprecate.next_rubygems_major_version}",
+ "\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}",
+ ]
+ warn "#{msg.join}." unless Gem::Deprecate.skip
+ send old, *args, &block
+ end
+ ruby2_keywords name if respond_to?(:ruby2_keywords, true)
+ end
+ end
+
+ # Deprecation method to deprecate Rubygems commands
+ def rubygems_deprecate_command
+ class_eval do
+ define_method "deprecated?" do
+ true
+ end
+
+ define_method "deprecation_warning" do
+ msg = [ "#{self.command} command is deprecated",
+ ". It will be removed in Rubygems #{Gem::Deprecate.next_rubygems_major_version}.\n",
+ ]
+
+ alert_warning "#{msg.join}" unless Gem::Deprecate.skip
+ end
end
end
- module_function :deprecate, :skip_during
+ module_function :rubygems_deprecate, :rubygems_deprecate_command, :skip_during
end
diff --git a/lib/rubygems/doctor.rb b/lib/rubygems/doctor.rb
index 661ae5a4e1..41bcda9804 100644
--- a/lib/rubygems/doctor.rb
+++ b/lib/rubygems/doctor.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/user_interaction'
+require_relative '../rubygems'
+require_relative 'user_interaction'
##
# Cleans up after a partially-failed uninstall or for an invalid
@@ -12,7 +12,6 @@ require 'rubygems/user_interaction'
# removing the bogus specification.
class Gem::Doctor
-
include Gem::UserInteraction
##
@@ -26,11 +25,12 @@ class Gem::Doctor
['doc', ''],
['extensions', ''],
['gems', ''],
+ ['plugins', ''],
].freeze
missing =
Gem::REPOSITORY_SUBDIRECTORIES.sort -
- REPOSITORY_EXTENSION_MAP.map { |(k,_)| k }.sort
+ REPOSITORY_EXTENSION_MAP.map {|(k,_)| k }.sort
raise "Update REPOSITORY_EXTENSION_MAP, missing: #{missing.join ', '}" unless
missing.empty?
@@ -52,7 +52,7 @@ class Gem::Doctor
# Specs installed in this gem repository
def installed_specs # :nodoc:
- @installed_specs ||= Gem::Specification.map { |s| s.full_name }
+ @installed_specs ||= Gem::Specification.map {|s| s.full_name }
end
##
@@ -112,6 +112,7 @@ class Gem::Doctor
next if installed_specs.include? basename
next if /^rubygems-\d/ =~ basename
next if 'specifications' == sub_directory and 'default' == basename
+ next if 'plugins' == sub_directory and Gem.plugin_suffix_regexp =~ basename
type = File.directory?(child) ? 'directory' : 'file'
@@ -127,5 +128,4 @@ class Gem::Doctor
rescue Errno::ENOENT
# ignore
end
-
end
diff --git a/lib/rubygems/errors.rb b/lib/rubygems/errors.rb
index 2cd18e2e20..86f0d1da14 100644
--- a/lib/rubygems/errors.rb
+++ b/lib/rubygems/errors.rb
@@ -13,13 +13,11 @@ module Gem
# already activated gems or that RubyGems is otherwise unable to activate.
class LoadError < ::LoadError
-
# Name of gem
attr_accessor :name
# Version requirement of gem
attr_accessor :requirement
-
end
##
@@ -27,15 +25,15 @@ 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)
+ def initialize(name, requirement, extra_message=nil)
@name = name
@requirement = requirement
+ @extra_message = extra_message
end
def message # :nodoc:
build_message +
- "Checked in 'GEM_PATH=#{Gem.path.join(File::PATH_SEPARATOR)}', execute `gem env` for more information"
+ "Checked in 'GEM_PATH=#{Gem.path.join(File::PATH_SEPARATOR)}' #{@extra_message}, execute `gem env` for more information"
end
private
@@ -44,7 +42,6 @@ module Gem
total = Gem::Specification.stubs.size
"Could not find '#{name}' (#{requirement}) among #{total} total gem(s)\n"
end
-
end
##
@@ -52,7 +49,6 @@ module Gem
# not the requested version. Instead of rescuing from this class, make sure to
# rescue from the superclass Gem::LoadError to catch all types of load errors.
class MissingSpecVersionError < MissingSpecError
-
attr_reader :specs
def initialize(name, requirement, specs)
@@ -69,13 +65,11 @@ module Gem
names = specs.map(&:full_name)
"Could not find '#{name}' (#{requirement}) - did find: [#{names.join ','}]\n"
end
-
end
# Raised when there are conflicting gem specs loaded
class ConflictError < LoadError
-
##
# A Hash mapping conflicting specifications to the dependencies that
# caused the conflict
@@ -100,7 +94,6 @@ module Gem
super("Unable to activate #{target.full_name}, because #{reason}")
end
-
end
class ErrorReason; end
@@ -112,7 +105,6 @@ module Gem
# in figuring out why a gem couldn't be installed.
#
class PlatformMismatch < ErrorReason
-
##
# the name of the gem
attr_reader :name
@@ -150,7 +142,6 @@ module Gem
@platforms.size == 1 ? '' : 's',
@platforms.join(' ,')]
end
-
end
##
@@ -158,7 +149,6 @@ module Gem
# data from a source
class SourceFetchProblem < ErrorReason
-
##
# Creates a new SourceFetchProblem for the given +source+ and +error+.
@@ -181,14 +171,12 @@ module Gem
# An English description of the error.
def wordy
- @source.uri.password = 'REDACTED' unless @source.uri.password.nil?
- "Unable to download data from #{@source.uri} - #{@error.message}"
+ "Unable to download data from #{Gem::Uri.new(@source.uri).redacted} - #{@error.message}"
end
##
# The "exception" alias allows you to call raise on a SourceFetchProblem.
alias exception error
-
end
end
diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb
index 3924f9dde6..5f20dfaed0 100644
--- a/lib/rubygems/exceptions.rb
+++ b/lib/rubygems/exceptions.rb
@@ -1,22 +1,11 @@
# frozen_string_literal: true
-require 'rubygems/deprecate'
+require_relative 'deprecate'
##
# Base exception class for RubyGems. All exception raised by RubyGems are a
# subclass of this one.
-class Gem::Exception < RuntimeError
-
- ##
- #--
- # TODO: remove in RubyGems 4, nobody sets this
-
- attr_accessor :source_exception # :nodoc:
-
- extend Gem::Deprecate
- deprecate :source_exception, :none, 2018, 12
-
-end
+class Gem::Exception < RuntimeError; end
class Gem::CommandLineError < Gem::Exception; end
@@ -30,7 +19,6 @@ class Gem::DependencyRemovalException < Gem::Exception; end
# and #conflicting_dependencies
class Gem::DependencyResolutionError < Gem::DependencyError
-
attr_reader :conflict
def initialize(conflict)
@@ -43,25 +31,20 @@ class Gem::DependencyResolutionError < Gem::DependencyError
def conflicting_dependencies
@conflict.conflicting_dependencies
end
-
end
##
# Raised when attempting to uninstall a gem that isn't in GEM_HOME.
class Gem::GemNotInHomeException < Gem::Exception
-
attr_accessor :spec
-
end
###
# Raised when removing a gem with the uninstall command fails
class Gem::UninstallError < Gem::Exception
-
attr_accessor :spec
-
end
class Gem::DocumentError < Gem::Exception; end
@@ -75,7 +58,6 @@ class Gem::EndOfYAMLException < Gem::Exception; end
# operating on the given directory.
class Gem::FilePermissionError < Gem::Exception
-
attr_reader :directory
def initialize(directory)
@@ -83,15 +65,12 @@ class Gem::FilePermissionError < Gem::Exception
super "You don't have write permissions for the #{directory} directory."
end
-
end
##
# Used to raise parsing and loading errors
class Gem::FormatException < Gem::Exception
-
attr_accessor :file_path
-
end
class Gem::GemNotFoundException < Gem::Exception; end
@@ -100,7 +79,6 @@ class Gem::GemNotFoundException < Gem::Exception; end
# Raised by the DependencyInstaller when a specific gem cannot be found
class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException
-
##
# Creates a new SpecificGemNotFoundException for a gem with the given +name+
# and +version+. Any +errors+ encountered when attempting to find the gem
@@ -128,7 +106,6 @@ class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException
# Errors encountered attempting to find the gem.
attr_reader :errors
-
end
##
@@ -136,7 +113,6 @@ end
# inability to find a valid possible spec for a request.
class Gem::ImpossibleDependenciesError < Gem::Exception
-
attr_reader :conflicts
attr_reader :request
@@ -164,17 +140,14 @@ class Gem::ImpossibleDependenciesError < Gem::Exception
def dependency
@request.dependency
end
-
end
class Gem::InstallError < Gem::Exception; end
class Gem::RuntimeRequirementNotMetError < Gem::InstallError
-
attr_accessor :suggestion
def message
[suggestion, super].compact.join("\n\t")
end
-
end
##
@@ -216,7 +189,6 @@ class Gem::VerificationError < Gem::Exception; end
# exit_code
class Gem::SystemExitException < SystemExit
-
##
# The exit code for the process
@@ -230,7 +202,6 @@ class Gem::SystemExitException < SystemExit
super "Exiting RubyGems with exit_code #{exit_code}"
end
-
end
##
@@ -238,7 +209,6 @@ end
# there is no spec.
class Gem::UnsatisfiableDependencyError < Gem::DependencyError
-
##
# The unsatisfiable dependency. This is a
# Gem::Resolver::DependencyRequest, not a Gem::Dependency
@@ -256,7 +226,7 @@ class Gem::UnsatisfiableDependencyError < Gem::DependencyError
def initialize(dep, platform_mismatch=nil)
if platform_mismatch and !platform_mismatch.empty?
- plats = platform_mismatch.map { |x| x.platform.to_s }.sort.uniq
+ plats = platform_mismatch.map {|x| x.platform.to_s }.sort.uniq
super "Unable to resolve dependency: No match for '#{dep}' on this platform. Found: #{plats.join(', ')}"
else
if dep.explicit?
@@ -283,10 +253,10 @@ class Gem::UnsatisfiableDependencyError < Gem::DependencyError
def version
@dependency.requirement
end
-
end
##
# Backwards compatible typo'd exception class for early RubyGems 2.0.x
Gem::UnsatisfiableDepedencyError = Gem::UnsatisfiableDependencyError # :nodoc:
+Gem.deprecate_constant :UnsatisfiableDepedencyError
diff --git a/lib/rubygems/ext.rb b/lib/rubygems/ext.rb
index 35a486606a..bdd5bd9d82 100644
--- a/lib/rubygems/ext.rb
+++ b/lib/rubygems/ext.rb
@@ -10,9 +10,9 @@
module Gem::Ext; end
-require 'rubygems/ext/build_error'
-require 'rubygems/ext/builder'
-require 'rubygems/ext/configure_builder'
-require 'rubygems/ext/ext_conf_builder'
-require 'rubygems/ext/rake_builder'
-require 'rubygems/ext/cmake_builder'
+require_relative 'ext/build_error'
+require_relative 'ext/builder'
+require_relative 'ext/configure_builder'
+require_relative 'ext/ext_conf_builder'
+require_relative 'ext/rake_builder'
+require_relative 'ext/cmake_builder'
diff --git a/lib/rubygems/ext/build_error.rb b/lib/rubygems/ext/build_error.rb
index 6dffddb5cc..8ef57ed91a 100644
--- a/lib/rubygems/ext/build_error.rb
+++ b/lib/rubygems/ext/build_error.rb
@@ -2,5 +2,7 @@
##
# Raised when there is an error while building extensions.
+require_relative '../exceptions'
+
class Gem::Ext::BuildError < Gem::InstallError
end
diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb
index a8bd4c8d1b..c1a1bc9c00 100644
--- a/lib/rubygems/ext/builder.rb
+++ b/lib/rubygems/ext/builder.rb
@@ -5,20 +5,11 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/user_interaction'
+require_relative '../user_interaction'
class Gem::Ext::Builder
-
include Gem::UserInteraction
- ##
- # The builder shells-out to run various commands after changing the
- # directory. This means multiple installations cannot be allowed to build
- # extensions in parallel as they may change each other's directories leading
- # to broken extensions or failed installations.
-
- CHDIR_MUTEX = Mutex.new # :nodoc:
-
attr_accessor :build_args # :nodoc:
def self.class_name
@@ -26,51 +17,54 @@ class Gem::Ext::Builder
$1.downcase
end
- def self.make(dest_path, results)
- unless File.exist? 'Makefile'
+ def self.make(dest_path, results, make_dir = Dir.pwd)
+ unless File.exist? File.join(make_dir, 'Makefile')
raise Gem::InstallError, 'Makefile not found'
end
# try to find make program from Ruby configure arguments first
RbConfig::CONFIG['configure_args'] =~ /with-make-prog\=(\w+)/
- make_program = ENV['MAKE'] || ENV['make'] || $1
- unless make_program
- make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make'
+ make_program_name = ENV['MAKE'] || ENV['make'] || $1
+ unless make_program_name
+ make_program_name = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make'
end
+ make_program = Shellwords.split(make_program_name)
- destdir = '"DESTDIR=%s"' % ENV['DESTDIR']
+ # The installation of the bundled gems is failed when DESTDIR is empty in mswin platform.
+ destdir = (/\bnmake/i !~ make_program_name || ENV['DESTDIR'] && ENV['DESTDIR'] != "") ? 'DESTDIR=%s' % ENV['DESTDIR'] : ''
['clean', '', 'install'].each do |target|
# Pass DESTDIR via command line to override what's in MAKEFLAGS
cmd = [
- make_program,
+ *make_program,
destdir,
- target
- ].join(' ').rstrip
+ target,
+ ].reject(&:empty?)
begin
- run(cmd, results, "make #{target}".rstrip)
+ run(cmd, results, "make #{target}".rstrip, make_dir)
rescue Gem::InstallError
raise unless target == 'clean' # ignore clean failure
end
end
end
- def self.run(command, results, command_name = nil)
+ def self.run(command, results, command_name = nil, dir = Dir.pwd)
verbose = Gem.configuration.really_verbose
begin
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
if verbose
- puts("current directory: #{Dir.pwd}")
+ puts("current directory: #{dir}")
p(command)
end
- results << "current directory: #{Dir.pwd}"
- results << (command.respond_to?(:shelljoin) ? command.shelljoin : command)
+ results << "current directory: #{dir}"
+ require "shellwords"
+ results << command.shelljoin
require "open3"
# Set $SOURCE_DATE_EPOCH for the subprocess.
env = {'SOURCE_DATE_EPOCH' => Gem.source_date_epoch_string}
- output, status = Open3.capture2e(env, *command)
+ output, status = Open3.capture2e(env, *command, :chdir => dir)
if verbose
puts output
else
@@ -162,22 +156,10 @@ EOF
begin
FileUtils.mkdir_p dest_path
- CHDIR_MUTEX.synchronize do
- pwd = Dir.getwd
- Dir.chdir extension_dir
- begin
- results = builder.build(extension, dest_path,
- results, @build_args, lib_dir)
-
- verbose { results.join("\n") }
- ensure
- begin
- Dir.chdir pwd
- rescue SystemCallError
- Dir.chdir dest_path
- end
- end
- end
+ results = builder.build(extension, dest_path,
+ results, @build_args, lib_dir, extension_dir)
+
+ verbose { results.join("\n") }
write_gem_make_out results.join "\n"
rescue => e
@@ -202,6 +184,7 @@ EOF
dest_path = @spec.extension_dir
+ require "fileutils"
FileUtils.rm_f @spec.gem_build_complete_path
@spec.extensions.each do |extension|
@@ -227,5 +210,4 @@ EOF
destination
end
-
end
diff --git a/lib/rubygems/ext/cmake_builder.rb b/lib/rubygems/ext/cmake_builder.rb
index 829b88d1bb..e47cabef84 100644
--- a/lib/rubygems/ext/cmake_builder.rb
+++ b/lib/rubygems/ext/cmake_builder.rb
@@ -1,19 +1,16 @@
# frozen_string_literal: true
-require 'rubygems/command'
class Gem::Ext::CmakeBuilder < Gem::Ext::Builder
+ def self.build(extension, dest_path, results, args=[], lib_dir=nil, cmake_dir=Dir.pwd)
+ unless File.exist?(File.join(cmake_dir, 'Makefile'))
+ require_relative '../command'
+ cmd = ["cmake", ".", "-DCMAKE_INSTALL_PREFIX=#{dest_path}", *Gem::Command.build_args]
- def self.build(extension, dest_path, results, args=[], lib_dir=nil)
- unless File.exist?('Makefile')
- cmd = "cmake . -DCMAKE_INSTALL_PREFIX=#{dest_path}"
- cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty?
-
- run cmd, results
+ run cmd, results, class_name, cmake_dir
end
- make dest_path, results
+ make dest_path, results, cmake_dir
results
end
-
end
diff --git a/lib/rubygems/ext/configure_builder.rb b/lib/rubygems/ext/configure_builder.rb
index 7d105c9bd3..eb2f9fce61 100644
--- a/lib/rubygems/ext/configure_builder.rb
+++ b/lib/rubygems/ext/configure_builder.rb
@@ -6,18 +6,15 @@
#++
class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder
+ def self.build(extension, dest_path, results, args=[], lib_dir=nil, configure_dir=Dir.pwd)
+ unless File.exist?(File.join(configure_dir, 'Makefile'))
+ cmd = ["sh", "./configure", "--prefix=#{dest_path}", *args]
- def self.build(extension, dest_path, results, args=[], lib_dir=nil)
- unless File.exist?('Makefile')
- cmd = "sh ./configure --prefix=#{dest_path}"
- cmd << " #{args.join ' '}" unless args.empty?
-
- run cmd, results
+ run cmd, results, class_name, configure_dir
end
- make dest_path, results
+ make dest_path, results, configure_dir
results
end
-
end
diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb
index 88be7ecfe8..3ca3463615 100644
--- a/lib/rubygems/ext/ext_conf_builder.rb
+++ b/lib/rubygems/ext/ext_conf_builder.rb
@@ -5,16 +5,12 @@
# See LICENSE.txt for permissions.
#++
-require 'fileutils'
-require 'tempfile'
-require 'shellwords'
-
class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
+ def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd)
+ require 'fileutils'
+ require 'tempfile'
- FileEntry = FileUtils::Entry_ # :nodoc:
-
- def self.build(extension, dest_path, results, args=[], lib_dir=nil)
- tmp_dest = Dir.mktmpdir(".gem.", ".")
+ tmp_dest = Dir.mktmpdir(".gem.", extension_dir)
# Some versions of `mktmpdir` return absolute paths, which will break make
# if the paths contain spaces. However, on Ruby 1.9.x on Windows, relative
@@ -25,11 +21,11 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
# spaces do not work.
#
# Details: https://github.com/rubygems/rubygems/issues/977#issuecomment-171544940
- tmp_dest = get_relative_path(tmp_dest)
+ tmp_dest_relative = get_relative_path(tmp_dest.clone, extension_dir)
- Tempfile.open %w"siteconf .rb", "." do |siteconf|
+ Tempfile.open %w[siteconf .rb], extension_dir do |siteconf|
siteconf.puts "require 'rbconfig'"
- siteconf.puts "dest_path = #{tmp_dest.dump}"
+ siteconf.puts "dest_path = #{tmp_dest_relative.dump}"
%w[sitearchdir sitelibdir].each do |dir|
siteconf.puts "RbConfig::MAKEFILE_CONFIG['#{dir}'] = dest_path"
siteconf.puts "RbConfig::CONFIG['#{dir}'] = dest_path"
@@ -40,19 +36,23 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
destdir = ENV["DESTDIR"]
begin
+ # workaround for https://github.com/oracle/truffleruby/issues/2115
+ siteconf_path = RUBY_ENGINE == "truffleruby" ? siteconf.path.dup : siteconf.path
+ require "shellwords"
cmd = Gem.ruby.shellsplit << "-I" << File.expand_path("../../..", __FILE__) <<
- "-r" << get_relative_path(siteconf.path) << File.basename(extension)
+ "-r" << get_relative_path(siteconf_path, extension_dir) << File.basename(extension)
cmd.push(*args)
begin
- run(cmd, results) do |s, r|
- if File.exist? 'mkmf.log'
+ run(cmd, results, class_name, extension_dir) do |s, r|
+ mkmf_log = File.join(extension_dir, 'mkmf.log')
+ if File.exist? mkmf_log
unless s.success?
r << "To see why this extension failed to compile, please check" \
" the mkmf.log which can be found here:\n"
r << " " + File.join(dest_path, 'mkmf.log') + "\n"
end
- FileUtils.mv 'mkmf.log', dest_path
+ FileUtils.mv mkmf_log, dest_path
end
end
siteconf.unlink
@@ -60,18 +60,20 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
ENV["DESTDIR"] = nil
- make dest_path, results
+ make dest_path, results, extension_dir
+
+ if tmp_dest_relative
+ full_tmp_dest = File.join(extension_dir, tmp_dest_relative)
- if tmp_dest
# TODO remove in RubyGems 3
if Gem.install_extension_in_lib and lib_dir
FileUtils.mkdir_p lib_dir
- entries = Dir.entries(tmp_dest) - %w[. ..]
- entries = entries.map { |entry| File.join tmp_dest, entry }
+ entries = Dir.entries(full_tmp_dest) - %w[. ..]
+ entries = entries.map {|entry| File.join full_tmp_dest, entry }
FileUtils.cp_r entries, lib_dir, :remove_destination => true
end
- FileEntry.new(tmp_dest).traverse do |ent|
+ FileUtils::Entry_.new(full_tmp_dest).traverse do |ent|
destent = ent.class.new(dest_path, ent.rel)
destent.exist? or FileUtils.mv(ent.path, destent.path)
end
@@ -89,9 +91,8 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
private
- def self.get_relative_path(path)
- path[0..Dir.pwd.length - 1] = '.' if path.start_with?(Dir.pwd)
+ def self.get_relative_path(path, base)
+ path[0..base.length - 1] = '.' if path.start_with?(base)
path
end
-
end
diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb
index 077f080c07..fed98e741c 100644
--- a/lib/rubygems/ext/rake_builder.rb
+++ b/lib/rubygems/ext/rake_builder.rb
@@ -5,31 +5,28 @@
# See LICENSE.txt for permissions.
#++
-require "shellwords"
-
class Gem::Ext::RakeBuilder < Gem::Ext::Builder
-
- def self.build(extension, dest_path, results, args=[], lib_dir=nil)
+ def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd)
if File.basename(extension) =~ /mkrf_conf/i
- run([Gem.ruby, File.basename(extension), *args], results)
+ run([Gem.ruby, File.basename(extension), *args], results, class_name, extension_dir)
end
rake = ENV['rake']
if rake
+ require "shellwords"
rake = rake.shellsplit
else
begin
- rake = [Gem.ruby, "-I#{File.expand_path("..", __dir__)}", "-rrubygems", Gem.bin_path('rake', 'rake')]
+ rake = [Gem.ruby, "-I#{File.expand_path("../..", __dir__)}", "-rrubygems", Gem.bin_path('rake', 'rake')]
rescue Gem::Exception
rake = [Gem.default_exec_format % 'rake']
end
end
rake_args = ["RUBYARCHDIR=#{dest_path}", "RUBYLIBDIR=#{dest_path}", *args]
- run(rake + rake_args, results)
+ run(rake + rake_args, results, class_name, extension_dir)
results
end
-
end
diff --git a/lib/rubygems/gem_runner.rb b/lib/rubygems/gem_runner.rb
index 4159d81389..55b5a7d067 100644
--- a/lib/rubygems/gem_runner.rb
+++ b/lib/rubygems/gem_runner.rb
@@ -5,10 +5,9 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
-require 'rubygems/command_manager'
-require 'rubygems/config_file'
-require 'rubygems/deprecate'
+require_relative '../rubygems'
+require_relative 'command_manager'
+require_relative 'deprecate'
##
# Load additional plugins from $LOAD_PATH
@@ -25,14 +24,9 @@ Gem.load_env_plugins rescue nil
# classes they call directly.
class Gem::GemRunner
-
- def initialize(options={})
- if !options.empty? && !Gem::Deprecate.skip
- Kernel.warn "NOTE: passing options to Gem::GemRunner.new is deprecated with no replacement. It will be removed on or after 2016-10-01."
- end
-
- @command_manager_class = options[:command_manager] || Gem::CommandManager
- @config_file_class = options[:config_file] || Gem::ConfigFile
+ def initialize
+ @command_manager_class = Gem::CommandManager
+ @config_file_class = Gem::ConfigFile
end
##
@@ -80,7 +74,6 @@ class Gem::GemRunner
Gem.use_paths Gem.configuration[:gemhome], Gem.configuration[:gempath]
Gem::Command.extra_args = Gem.configuration[:gem]
end
-
end
Gem.load_plugins
diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb
index 2950d94dc1..0968e1a6f9 100644
--- a/lib/rubygems/gemcutter_utilities.rb
+++ b/lib/rubygems/gemcutter_utilities.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/remote_fetcher'
-require 'rubygems/text'
+require_relative 'remote_fetcher'
+require_relative 'text'
##
# Utility methods for using the RubyGems API.
@@ -8,10 +8,12 @@ require 'rubygems/text'
module Gem::GemcutterUtilities
ERROR_CODE = 1
+ API_SCOPES = %i[index_rubygems push_rubygem yank_rubygem add_owner remove_owner access_webhooks show_dashboard].freeze
include Gem::Text
attr_writer :host
+ attr_writer :scope
##
# Add the --key option
@@ -19,7 +21,7 @@ module Gem::GemcutterUtilities
def add_key_option
add_option('-k', '--key KEYNAME', Symbol,
'Use the given API key',
- 'from ~/.gem/credentials') do |value,options|
+ "from #{Gem.configuration.credentials_path}") do |value,options|
options[:key] = value
end
end
@@ -29,7 +31,8 @@ module Gem::GemcutterUtilities
def add_otp_option
add_option('--otp CODE',
- 'Digit code for multifactor authentication') do |value, options|
+ 'Digit code for multifactor authentication',
+ 'You can also use the environment variable GEM_HOST_OTP_CODE') do |value, options|
options[:otp] = value
end
end
@@ -50,6 +53,13 @@ module Gem::GemcutterUtilities
end
##
+ # The OTP code from the command options or from the user's configuration.
+
+ def otp
+ options[:otp] || ENV["GEM_HOST_OTP_CODE"]
+ end
+
+ ##
# The host to connect to either from the RUBYGEMS_HOST environment variable
# or from the user's configuration
@@ -72,7 +82,7 @@ module Gem::GemcutterUtilities
#
# If +allowed_push_host+ metadata is present, then it will only allow that host.
- def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, &block)
+ def rubygems_api_request(method, path, host = nil, allowed_push_host = nil, scope: nil, &block)
require 'net/http'
self.host = host if host
@@ -92,14 +102,18 @@ module Gem::GemcutterUtilities
end
uri = URI.parse "#{self.host}/#{path}"
+ response = request_with_otp(method, uri, &block)
- request_method = Net::HTTP.const_get method.to_s.capitalize
- response = Gem::RemoteFetcher.fetcher.request(uri, request_method, &block)
- return response unless mfa_unauthorized?(response)
+ if mfa_unauthorized?(response)
+ ask_otp
+ response = request_with_otp(method, uri, &block)
+ end
- Gem::RemoteFetcher.fetcher.request(uri, request_method) do |req|
- req.add_field "OTP", get_otp
- block.call(req)
+ if api_key_forbidden?(response)
+ update_scope(scope)
+ request_with_otp(method, uri, &block)
+ else
+ response
end
end
@@ -107,24 +121,37 @@ module Gem::GemcutterUtilities
response.kind_of?(Net::HTTPUnauthorized) && response.body.start_with?('You have enabled multifactor authentication')
end
- def get_otp
- say 'You have enabled multi-factor authentication. Please enter OTP code.'
- ask 'Code: '
+ def update_scope(scope)
+ sign_in_host = self.host
+ pretty_host = pretty_host(sign_in_host)
+ update_scope_params = { scope => true }
+
+ say "The existing key doesn't have access of #{scope} on #{pretty_host}. Please sign in to update access."
+
+ email = ask " Email: "
+ password = ask_for_password "Password: "
+
+ response = rubygems_api_request(:put, "api/v1/api_key",
+ sign_in_host, scope: scope) do |request|
+ request.basic_auth email, password
+ request["OTP"] = otp if otp
+ request.body = URI.encode_www_form({:api_key => api_key }.merge(update_scope_params))
+ end
+
+ with_response response do |resp|
+ say "Added #{scope} scope to the existing API key"
+ end
end
##
# Signs in with the RubyGems API at +sign_in_host+ and sets the rubygems API
# key.
- def sign_in(sign_in_host = nil)
+ def sign_in(sign_in_host = nil, scope: nil)
sign_in_host ||= self.host
return if api_key
- pretty_host = if Gem::DEFAULT_HOST == sign_in_host
- 'RubyGems.org'
- else
- sign_in_host
- end
+ pretty_host = pretty_host(sign_in_host)
say "Enter your #{pretty_host} credentials."
say "Don't have an account yet? " +
@@ -134,14 +161,18 @@ module Gem::GemcutterUtilities
password = ask_for_password "Password: "
say "\n"
- response = rubygems_api_request(:get, "api/v1/api_key",
- sign_in_host) do |request|
+ key_name = get_key_name(scope)
+ scope_params = get_scope_params(scope)
+
+ response = rubygems_api_request(:post, "api/v1/api_key",
+ sign_in_host, scope: scope) do |request|
request.basic_auth email, password
- request.add_field "OTP", options[:otp] if options[:otp]
+ request["OTP"] = otp if otp
+ request.body = URI.encode_www_form({ name: key_name }.merge(scope_params))
end
with_response response do |resp|
- say "Signed in."
+ say "Signed in with API key: #{key_name}."
set_api_key host, resp.body
end
end
@@ -195,4 +226,62 @@ module Gem::GemcutterUtilities
end
end
+ private
+
+ def request_with_otp(method, uri, &block)
+ request_method = Net::HTTP.const_get method.to_s.capitalize
+
+ Gem::RemoteFetcher.fetcher.request(uri, request_method) do |req|
+ req["OTP"] = otp if otp
+ block.call(req)
+ end
+ end
+
+ def ask_otp
+ say 'You have enabled multi-factor authentication. Please enter OTP code.'
+ options[:otp] = ask 'Code: '
+ end
+
+ def pretty_host(host)
+ if Gem::DEFAULT_HOST == host
+ 'RubyGems.org'
+ else
+ host
+ end
+ end
+
+ def get_scope_params(scope)
+ scope_params = {}
+
+ if scope
+ scope_params = { scope => true }
+ else
+ say "Please select scopes you want to enable for the API key (y/n)"
+ API_SCOPES.each do |scope|
+ selected = ask "#{scope} [y/N]: "
+ scope_params[scope] = true if selected =~ /^[yY](es)?$/
+ end
+ say "\n"
+ end
+
+ scope_params
+ end
+
+ def get_key_name(scope)
+ hostname = Socket.gethostname || "unknown-host"
+ user = ENV["USER"] || ENV["USERNAME"] || "unknown-user"
+ ts = Time.now.strftime("%Y%m%d%H%M%S")
+ default_key_name = "#{hostname}-#{user}-#{ts}"
+
+ key_name = ask "API Key name [#{default_key_name}]: " unless scope
+ if key_name.nil? || key_name.empty?
+ default_key_name
+ else
+ key_name
+ end
+ end
+
+ def api_key_forbidden?(response)
+ response.kind_of?(Net::HTTPForbidden) && response.body.start_with?("The API key doesn't have access")
+ end
end
diff --git a/lib/rubygems/indexer.rb b/lib/rubygems/indexer.rb
index 4d199868fb..6e8dade640 100644
--- a/lib/rubygems/indexer.rb
+++ b/lib/rubygems/indexer.rb
@@ -1,27 +1,12 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/package'
-require 'time'
+require_relative '../rubygems'
+require_relative 'package'
require 'tmpdir'
-rescue_exceptions = [LoadError]
-begin
- require 'bundler/errors'
-rescue LoadError # this rubygems + old ruby
-else # this rubygems + ruby trunk with bundler
- rescue_exceptions << Bundler::GemfileNotFound
-end
-begin
- gem 'builder'
- require 'builder/xchar'
-rescue *rescue_exceptions
-end
-
##
# Top level class for building the gem repository index.
class Gem::Indexer
-
include Gem::UserInteraction
##
@@ -62,11 +47,6 @@ class Gem::Indexer
require 'tmpdir'
require 'zlib'
- unless defined?(Builder::XChar)
- raise "Gem::Indexer requires that the XML Builder library be installed:" +
- "\n\tgem install builder"
- end
-
options = { :build_modern => true }.merge options
@build_modern = options[:build_modern]
@@ -156,7 +136,7 @@ class Gem::Indexer
say "Generating #{name} index"
Gem.time "Generated #{name} index" do
- open(file, 'wb') do |io|
+ File.open(file, 'wb') do |io|
specs = index.map do |*spec|
# We have to splat here because latest_specs is an array, while the
# others are hashes.
@@ -383,7 +363,7 @@ class Gem::Indexer
end
specs = map_gems_to_specs updated_gems
- prerelease, released = specs.partition { |s| s.version.prerelease? }
+ prerelease, released = specs.partition {|s| s.version.prerelease? }
files = build_marshal_gemspecs specs
@@ -442,5 +422,4 @@ class Gem::Indexer
Marshal.dump specs_index, io
end
end
-
end
diff --git a/lib/rubygems/install_default_message.rb b/lib/rubygems/install_default_message.rb
index f68fd2fd04..052ef528e1 100644
--- a/lib/rubygems/install_default_message.rb
+++ b/lib/rubygems/install_default_message.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/user_interaction'
+require_relative '../rubygems'
+require_relative 'user_interaction'
##
# A post-install hook that displays "Successfully installed
diff --git a/lib/rubygems/install_message.rb b/lib/rubygems/install_message.rb
index 3c13888a84..861ead3770 100644
--- a/lib/rubygems/install_message.rb
+++ b/lib/rubygems/install_message.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/user_interaction'
+require_relative '../rubygems'
+require_relative 'user_interaction'
##
# A default post-install hook that displays "Successfully installed
diff --git a/lib/rubygems/install_update_options.rb b/lib/rubygems/install_update_options.rb
index 38a0682958..d890c526bc 100644
--- a/lib/rubygems/install_update_options.rb
+++ b/lib/rubygems/install_update_options.rb
@@ -5,8 +5,8 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
-require 'rubygems/security_option'
+require_relative '../rubygems'
+require_relative 'security_option'
##
# Mixin methods for install and update options for Gem::Commands
@@ -25,12 +25,12 @@ module Gem::InstallUpdateOptions
end
add_option(:"Install/Update", '-n', '--bindir DIR',
- 'Directory where executables are',
- 'located') do |value, options|
+ 'Directory where executables will be',
+ 'placed when the gem is installed') do |value, options|
options[:bin_dir] = File.expand_path(value)
end
- add_option(:"Install/Update", '--document [TYPES]', Array,
+ add_option(:"Install/Update", '--document [TYPES]', Array,
'Generate documentation for installed gems',
'List the documentation types you wish to',
'generate. For example: rdoc,ri') do |value, options|
@@ -51,7 +51,7 @@ module Gem::InstallUpdateOptions
'Install gem into the vendor directory.',
'Only for use by gem repackagers.') do |value, options|
unless Gem.vendor_dir
- raise OptionParser::InvalidOption.new 'your platform is not supported'
+ raise Gem::OptionParser::InvalidOption.new 'your platform is not supported'
end
options[:vendor] = true
@@ -88,7 +88,7 @@ module Gem::InstallUpdateOptions
options[:ignore_dependencies] = value
end
- add_option(:"Install/Update", '--[no-]format-executable',
+ add_option(:"Install/Update", '--[no-]format-executable',
'Make installed executable names match Ruby.',
'If Ruby is ruby18, foo_exec will be',
'foo_exec18') do |value, options|
@@ -122,10 +122,10 @@ module Gem::InstallUpdateOptions
options[:minimal_deps] = true
end
- add_option(:"Install/Update", "--minimal-deps",
+ add_option(:"Install/Update", "--[no-]minimal-deps",
"Don't upgrade any dependencies that already",
"meet version requirements") do |value, options|
- options[:minimal_deps] = true
+ options[:minimal_deps] = value
end
add_option(:"Install/Update", "--[no-]post-install-message",
@@ -143,7 +143,7 @@ module Gem::InstallUpdateOptions
unless v
message = v ? v : "(tried #{Gem::GEM_DEP_FILES.join ', '})"
- raise OptionParser::InvalidArgument,
+ raise Gem::OptionParser::InvalidArgument,
"cannot find gem dependencies file #{message}"
end
@@ -154,7 +154,7 @@ module Gem::InstallUpdateOptions
'Omit the named groups (comma separated)',
'when installing from a gem dependencies',
'file') do |v,o|
- options[:without_groups].concat v.map { |without| without.intern }
+ options[:without_groups].concat v.map {|without| without.intern }
end
add_option(:"Install/Update", '--default',
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index ad39ec81bf..8e3965ef92 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -5,13 +5,12 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/command'
-require 'rubygems/exceptions'
-require 'rubygems/deprecate'
-require 'rubygems/package'
-require 'rubygems/ext'
-require 'rubygems/user_interaction'
-require 'fileutils'
+require_relative 'installer_uninstaller_utils'
+require_relative 'exceptions'
+require_relative 'deprecate'
+require_relative 'package'
+require_relative 'ext'
+require_relative 'user_interaction'
##
# The installer installs the files contained in the .gem into the Gem.home.
@@ -27,7 +26,6 @@ require 'fileutils'
# file. See Gem.pre_install and Gem.post_install for details.
class Gem::Installer
-
extend Gem::Deprecate
##
@@ -43,10 +41,7 @@ class Gem::Installer
include Gem::UserInteraction
- ##
- # Filename of the gem being installed.
-
- attr_reader :gem
+ include Gem::InstallerUninstallerUtils
##
# The directory a gem's executables will be installed into
@@ -72,20 +67,28 @@ class Gem::Installer
@path_warning = false
- @install_lock = Mutex.new
-
class << self
+ #
+ # Changes in rubygems to lazily loading `rubygems/command` (in order to
+ # lazily load `optparse` as a side effect) affect bundler's custom installer
+ # which uses `Gem::Command` without requiring it (up until bundler 2.2.29).
+ # This hook is to compensate for that missing require.
+ #
+ # TODO: Remove when rubygems no longer supports running on bundler older
+ # than 2.2.29.
- ##
- # True if we've warned about PATH not including Gem.bindir
+ def inherited(klass)
+ if klass.name == "Bundler::RubyGemsGemInstaller"
+ require "rubygems/command"
+ end
- attr_accessor :path_warning
+ super(klass)
+ end
##
- # Certain aspects of the install process are not thread-safe. This lock is
- # used to allow multiple threads to install Gems at the same time.
+ # True if we've warned about PATH not including Gem.bindir
- attr_reader :install_lock
+ attr_accessor :path_warning
##
# Overrides the executable format.
@@ -100,7 +103,6 @@ class Gem::Installer
def exec_format
@exec_format ||= Gem.default_exec_format
end
-
end
##
@@ -113,7 +115,6 @@ class Gem::Installer
end
class FakePackage
-
attr_accessor :spec
attr_accessor :dir_mode
@@ -139,7 +140,6 @@ class Gem::Installer
def copy_to(path)
end
-
end
##
@@ -180,15 +180,7 @@ class Gem::Installer
require 'fileutils'
@options = options
- if package.is_a? String
- security_policy = options[:security_policy]
- @package = Gem::Package.new package, security_policy
- if $VERBOSE
- warn "constructing an Installer object with a string is deprecated. Please use Gem::Installer.at (called from: #{caller.first})"
- end
- else
- @package = package
- end
+ @package = package
process_options
@@ -199,6 +191,7 @@ class Gem::Installer
if options[:user_install]
@gem_home = Gem.user_dir
@bin_dir = Gem.bindir gem_home unless options[:bin_dir]
+ @plugins_dir = Gem.plugindir(gem_home)
check_that_user_bin_dir_is_in_path
end
end
@@ -300,8 +293,6 @@ class Gem::Installer
def install
pre_install_checks
- FileUtils.rm_f File.join gem_home, 'specifications', spec.spec_name
-
run_pre_install_hooks
# Set loaded_from to ensure extension_dir is correct
@@ -330,6 +321,7 @@ class Gem::Installer
end
generate_bin
+ generate_plugins
unless @options[:install_as_default]
write_spec
@@ -340,7 +332,7 @@ class Gem::Installer
say spec.post_install_message if options[:post_install_message] && !spec.post_install_message.nil?
- Gem::Installer.install_lock.synchronize { Gem::Specification.reset }
+ Gem::Specification.reset
run_post_install_hooks
@@ -419,7 +411,7 @@ class Gem::Installer
def installation_satisfies_dependency?(dependency)
return true if @options[:development] and dependency.type == :development
- return true if installed_specs.detect { |s| dependency.matches_spec? s }
+ return true if installed_specs.detect {|s| dependency.matches_spec? s }
return false if @only_install_dir
not dependency.matching_specs.empty?
end
@@ -431,7 +423,7 @@ class Gem::Installer
@gem_dir = directory
extract_files
end
- deprecate :unpack, :none, 2020, 04
+ rubygems_deprecate :unpack
##
# The location of the spec file that is installed.
@@ -446,7 +438,7 @@ class Gem::Installer
#
def default_spec_file
- File.join Gem.default_specifications_dir, "#{spec.full_name}.gemspec"
+ File.join gem_home, "specifications", "default", "#{spec.full_name}.gemspec"
end
##
@@ -454,13 +446,9 @@ class Gem::Installer
# specifications directory.
def write_spec
- File.open spec_file, 'w' do |file|
- spec.installed_by_version = Gem.rubygems_version
-
- file.puts spec.to_ruby_for_cache
+ spec.installed_by_version = Gem.rubygems_version
- file.fsync rescue nil # for filesystems without fsync(2)
- end
+ Gem.write_binary(spec_file, spec.to_ruby_for_cache)
end
##
@@ -468,9 +456,7 @@ class Gem::Installer
# specifications/default directory.
def write_default_spec
- File.open(default_spec_file, "w") do |file|
- file.puts spec.to_ruby
- end
+ Gem.write_binary(default_spec_file, spec.to_ruby)
end
##
@@ -491,27 +477,28 @@ class Gem::Installer
def generate_bin # :nodoc:
return if spec.executables.nil? or spec.executables.empty?
- begin
- Dir.mkdir @bin_dir, *[options[:dir_mode] && 0755].compact
- rescue SystemCallError
- raise unless File.directory? @bin_dir
- end
-
- raise Gem::FilePermissionError.new(@bin_dir) unless File.writable? @bin_dir
+ ensure_writable_dir @bin_dir
spec.executables.each do |filename|
filename.tap(&Gem::UNTAINT)
bin_path = File.join gem_dir, spec.bindir, filename
unless File.exist? bin_path
- # TODO change this to a more useful warning
- warn "`#{bin_path}` does not exist, maybe `gem pristine #{spec.name}` will fix it?"
+ if File.symlink? bin_path
+ alert_warning "`#{bin_path}` is dangling symlink pointing to `#{File.readlink bin_path}`"
+ else
+ alert_warning "`#{bin_path}` does not exist, maybe `gem pristine #{spec.name}` will fix it?"
+ end
next
end
mode = File.stat(bin_path).mode
dir_mode = options[:prog_mode] || (mode | 0111)
- FileUtils.chmod dir_mode, bin_path unless dir_mode == mode
+
+ unless dir_mode == mode
+ require 'fileutils'
+ FileUtils.chmod dir_mode, bin_path
+ end
check_executable_overwrite filename
@@ -520,7 +507,19 @@ class Gem::Installer
else
generate_bin_symlink filename, @bin_dir
end
+ end
+ end
+
+ def generate_plugins # :nodoc:
+ latest = Gem::Specification.latest_spec_for(spec.name)
+ return if latest && latest.version > spec.version
+ ensure_writable_dir @plugins_dir
+
+ if spec.plugins.empty?
+ remove_plugins_for(spec, @plugins_dir)
+ else
+ regenerate_plugins_for(spec, @plugins_dir)
end
end
@@ -534,6 +533,7 @@ 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
File.open bin_script_path, 'wb', 0755 do |file|
@@ -587,9 +587,9 @@ class Gem::Installer
def shebang(bin_file_name)
ruby_name = RbConfig::CONFIG['ruby_install_name'] if @env_shebang
path = File.join gem_dir, spec.bindir, bin_file_name
- first_line = File.open(path, "rb") {|file| file.gets}
+ first_line = File.open(path, "rb") {|file| file.gets } || ""
- if /\A#!/ =~ first_line
+ if first_line.start_with?("#!")
# Preserve extra words on shebang line, like "-w". Thanks RPA.
shebang = first_line.sub(/\A\#!.*?ruby\S*((\s+\S+)+)/, "#!#{Gem.ruby}")
opts = $1
@@ -641,27 +641,6 @@ class Gem::Installer
end
end
- def ensure_required_ruby_version_met # :nodoc:
- if rrv = spec.required_ruby_version
- ruby_version = Gem.ruby_version
- unless rrv.satisfied_by? ruby_version
- raise Gem::RuntimeRequirementNotMetError,
- "#{spec.name} requires Ruby version #{rrv}. The current ruby version is #{ruby_version}."
- end
- end
- end
-
- def ensure_required_rubygems_version_met # :nodoc:
- if rrgv = spec.required_rubygems_version
- unless rrgv.satisfied_by? Gem.rubygems_version
- rg_version = Gem::VERSION
- raise Gem::RuntimeRequirementNotMetError,
- "#{spec.name} requires RubyGems version #{rrgv}. The current RubyGems version is #{rg_version}. " +
- "Try 'gem update --system' to update RubyGems itself."
- end
- end
- end
-
def ensure_dependencies_met # :nodoc:
deps = spec.runtime_dependencies
deps |= spec.development_dependencies if @development
@@ -677,13 +656,14 @@ class Gem::Installer
:env_shebang => false,
:force => false,
:only_install_dir => false,
- :post_install_message => true
+ :post_install_message => true,
}.merge options
@env_shebang = options[:env_shebang]
@force = options[:force]
@install_dir = options[:install_dir]
@gem_home = options[:install_dir] || Gem.dir
+ @plugins_dir = Gem.plugindir(@gem_home)
@ignore_dependencies = options[:ignore_dependencies]
@format_executable = options[:format_executable]
@wrappers = options[:wrappers]
@@ -696,23 +676,25 @@ class Gem::Installer
@development = options[:development]
@build_root = options[:build_root]
- @build_args = options[:build_args] || Gem::Command.build_args
+ @build_args = options[:build_args]
unless @build_root.nil?
- require 'pathname'
- @build_root = Pathname.new(@build_root).expand_path
- @bin_dir = File.join(@build_root, options[:bin_dir] || Gem.bindir(@gem_home))
- @gem_home = File.join(@build_root, @gem_home)
- alert_warning "You build with buildroot.\n Build root: #{@build_root}\n Bin dir: #{@bin_dir}\n Gem home: #{@gem_home}"
+ @bin_dir = File.join(@build_root, @bin_dir.gsub(/^[a-zA-Z]:/, ''))
+ @gem_home = File.join(@build_root, @gem_home.gsub(/^[a-zA-Z]:/, ''))
+ @plugins_dir = File.join(@build_root, @plugins_dir.gsub(/^[a-zA-Z]:/, ''))
+ alert_warning "You build with buildroot.\n Build root: #{@build_root}\n Bin dir: #{@bin_dir}\n Gem home: #{@gem_home}\n Plugins dir: #{@plugins_dir}"
end
end
def check_that_user_bin_dir_is_in_path # :nodoc:
+ return if self.class.path_warning
+
user_bin_dir = @bin_dir || Gem.bindir(gem_home)
- user_bin_dir = user_bin_dir.gsub(File::SEPARATOR, File::ALT_SEPARATOR) if
- File::ALT_SEPARATOR
+ user_bin_dir = user_bin_dir.tr(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
path = ENV['PATH']
+ path = path.tr(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
+
if Gem.win_platform?
path = path.downcase
user_bin_dir = user_bin_dir.downcase
@@ -722,10 +704,8 @@ class Gem::Installer
unless path.include? user_bin_dir
unless !Gem.win_platform? && (path.include? user_bin_dir.sub(ENV['HOME'], '~'))
- unless self.class.path_warning
- alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
- self.class.path_warning = true
- end
+ alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
+ self.class.path_warning = true
end
end
end
@@ -748,6 +728,10 @@ class Gem::Installer
raise Gem::InstallError, "#{spec} has an invalid extensions"
end
+ if spec.platform.to_s =~ /\R/
+ raise Gem::InstallError, "#{spec.platform} is an invalid platform"
+ end
+
unless spec.specification_version.to_s =~ /\A\d+\z/
raise Gem::InstallError, "#{spec} has an invalid specification_version"
end
@@ -777,7 +761,7 @@ class Gem::Installer
#
require 'rubygems'
-
+#{gemdeps_load(spec.name)}
version = "#{Gem::Requirement.default_prerelease}"
str = ARGV.first
@@ -798,6 +782,15 @@ end
TEXT
end
+ def gemdeps_load(name)
+ return '' if name == "bundler"
+
+ <<-TEXT
+
+Gem.use_gemdeps
+TEXT
+ end
+
##
# return the stub script text used to launch the true Ruby script
@@ -810,7 +803,7 @@ TEXT
ruby_exe = "ruby.exe" if ruby_exe.empty?
if File.exist?(File.join bindir, ruby_exe)
- # stub & ruby.exe withing same folder. Portable
+ # stub & ruby.exe within same folder. Portable
<<-TEXT
@ECHO OFF
@"%~dp0#{ruby_exe}" "%~dpn0" %*
@@ -839,24 +832,12 @@ 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
builder.build_extensions
end
##
- # Logs the build +output+ in +build_dir+, then raises Gem::Ext::BuildError.
- #
- # TODO: Delete this for RubyGems 4. It remains for API compatibility
-
- def extension_build_error(build_dir, output, backtrace = nil) # :nodoc:
- builder = Gem::Ext::Builder.new spec, @build_args
-
- builder.build_error build_dir, output, backtrace
- end
- deprecate :extension_build_error, :none, 2018, 12
-
- ##
# Reads the file index and extracts each file into the gem directory.
#
# Ensures that files can't be installed outside the gem directory.
@@ -896,6 +877,13 @@ TEXT
end
##
+ # Filename of the gem being installed.
+
+ def gem
+ @package.gem.path
+ end
+
+ ##
# Performs various checks before installing the gem such as the install
# repository is writable and its directories exist, required Ruby and
# rubygems versions are met and that dependencies are installed.
@@ -921,8 +909,6 @@ TEXT
return true if @force
- ensure_required_ruby_version_met
- ensure_required_rubygems_version_met
ensure_dependencies_met unless @ignore_dependencies
true
@@ -933,7 +919,7 @@ TEXT
# extensions.
def write_build_info_file
- return if @build_args.empty?
+ return if build_args.empty?
build_info_dir = File.join gem_home, 'build_info'
@@ -943,7 +929,7 @@ TEXT
build_info_file = File.join build_info_dir, "#{spec.full_name}.info"
File.open build_info_file, 'w' do |io|
- @build_args.each do |arg|
+ build_args.each do |arg|
io.puts arg
end
end
@@ -959,4 +945,22 @@ TEXT
@package.copy_to cache_file
end
+ def ensure_writable_dir(dir) # :nodoc:
+ begin
+ Dir.mkdir dir, *[options[:dir_mode] && 0755].compact
+ rescue SystemCallError
+ raise unless File.directory? dir
+ end
+
+ raise Gem::FilePermissionError.new(dir) unless File.writable? dir
+ end
+
+ private
+
+ def build_args
+ @build_args ||= begin
+ require_relative "command"
+ Gem::Command.build_args
+ end
+ end
end
diff --git a/lib/rubygems/installer_test_case.rb b/lib/rubygems/installer_test_case.rb
deleted file mode 100644
index f48466d3ea..0000000000
--- a/lib/rubygems/installer_test_case.rb
+++ /dev/null
@@ -1,233 +0,0 @@
-# frozen_string_literal: true
-require 'rubygems/test_case'
-require 'rubygems/installer'
-
-class Gem::Installer
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :bin_dir
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :build_args
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :gem_dir
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :force
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :format
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :gem_home
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :env_shebang
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :ignore_dependencies
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :format_executable
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :security_policy
-
- ##
- # Available through requiring rubygems/installer_test_case
-
- attr_writer :wrappers
-
-end
-
-##
-# A test case for Gem::Installer.
-
-class Gem::InstallerTestCase < Gem::TestCase
-
- def setup
- super
-
- Gem::Installer.path_warning = false
- end
-
- ##
- # The path where installed executables live
-
- def util_inst_bindir
- File.join @gemhome, "bin"
- end
-
- ##
- # Adds an executable named "executable" to +spec+ with the given +shebang+.
- #
- # The executable is also written to the bin dir in @tmpdir and the installed
- # gem directory for +spec+.
-
- def util_make_exec(spec = @spec, shebang = "#!/usr/bin/ruby", bindir = "bin")
- spec.executables = %w[executable]
- spec.bindir = bindir
-
- exec_path = spec.bin_file "executable"
- write_file exec_path do |io|
- io.puts shebang
- end
-
- bin_path = File.join @tempdir, "bin", "executable"
- write_file bin_path do |io|
- io.puts shebang
- end
- end
-
- ##
- # Creates the following instance variables:
- #
- # @spec::
- # a spec named 'a', intended for regular installs
- #
- # @gem::
- # the path to a built gem from @spec
- #
- # And returns a Gem::Installer for the @spec that installs into @gemhome
-
- def setup_base_installer
- @gem = setup_base_gem
- util_installer @spec, @gemhome
- end
-
- ##
- # Creates the following instance variables:
- #
- # @spec::
- # a spec named 'a', intended for regular installs
- #
- # And returns a gem built for the @spec
-
- def setup_base_gem
- @spec = setup_base_spec
- util_build_gem @spec
- @spec.cache_file
- end
-
- ##
- # Sets up a generic specification for testing the rubygems installer
- #
- # And returns it
-
- def setup_base_spec
- quick_gem 'a' do |spec|
- util_make_exec spec
- end
- end
-
- ##
- # Creates the following instance variables:
- #
- # @spec::
- # a spec named 'a', intended for regular installs
- # @user_spec::
- # a spec named 'b', intended for user installs
- #
- # @gem::
- # the path to a built gem from @spec
- # @user_gem::
- # the path to a built gem from @user_spec
- #
- # And returns a Gem::Installer for the @user_spec that installs into Gem.user_dir
-
- def setup_base_user_installer
- @user_spec = quick_gem 'b' do |spec|
- util_make_exec spec
- end
-
- util_build_gem @user_spec
-
- @user_gem = @user_spec.cache_file
-
- util_installer @user_spec, Gem.user_dir, :user
- end
-
- ##
- # Sets up the base @gem, builds it and returns an installer for it.
- #
- def util_setup_installer
- @gem = setup_base_gem
-
- util_setup_gem
- end
-
- ##
- # Builds the @spec gem and returns an installer for it. The built gem
- # includes:
- #
- # bin/executable
- # lib/code.rb
- # ext/a/mkrf_conf.rb
-
- def util_setup_gem(ui = @ui)
- @spec.files << File.join('lib', 'code.rb')
- @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb')
-
- Dir.chdir @tempdir do
- FileUtils.mkdir_p 'bin'
- FileUtils.mkdir_p 'lib'
- FileUtils.mkdir_p File.join('ext', 'a')
-
- File.open File.join('bin', 'executable'), 'w' do |f|
- f.puts "raise 'ran executable'"
- end
-
- File.open File.join('lib', 'code.rb'), 'w' do |f|
- f.puts '1'
- end
-
- File.open File.join('ext', 'a', 'mkrf_conf.rb'), 'w' do |f|
- f << <<-EOF
- File.open 'Rakefile', 'w' do |rf| rf.puts "task :default" end
- EOF
- end
-
- yield @spec if block_given?
-
- use_ui ui do
- FileUtils.rm_f @gem
-
- @gem = Gem::Package.build @spec
- end
- end
-
- Gem::Installer.at @gem
- end
-
- ##
- # Creates an installer for +spec+ that will install into +gem_home+. If
- # +user+ is true a user-install will be performed.
-
- def util_installer(spec, gem_home, user=false)
- Gem::Installer.at(spec.cache_file,
- :install_dir => gem_home,
- :user_install => user)
- end
-
-end
diff --git a/lib/rubygems/installer_uninstaller_utils.rb b/lib/rubygems/installer_uninstaller_utils.rb
new file mode 100644
index 0000000000..2c8b7c635e
--- /dev/null
+++ b/lib/rubygems/installer_uninstaller_utils.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+##
+# Helper methods for both Gem::Installer and Gem::Uninstaller
+
+module Gem::InstallerUninstallerUtils
+
+ def regenerate_plugins_for(spec, plugins_dir)
+ plugins = spec.plugins
+ return if plugins.empty?
+
+ require 'pathname'
+
+ spec.plugins.each do |plugin|
+ plugin_script_path = File.join plugins_dir, "#{spec.name}_plugin#{File.extname(plugin)}"
+
+ File.open plugin_script_path, 'wb' do |file|
+ file.puts "require_relative '#{Pathname.new(plugin).relative_path_from(Pathname.new(plugins_dir))}'"
+ end
+
+ verbose plugin_script_path
+ end
+ end
+
+ def remove_plugins_for(spec, plugins_dir)
+ FileUtils.rm_f Gem::Util.glob_files_in_dir("#{spec.name}#{Gem.plugin_suffix_pattern}", plugins_dir)
+ end
+
+end
diff --git a/lib/rubygems/local_remote_options.rb b/lib/rubygems/local_remote_options.rb
index c940f50ad6..0b8b0ee1a6 100644
--- a/lib/rubygems/local_remote_options.rb
+++ b/lib/rubygems/local_remote_options.rb
@@ -6,7 +6,7 @@
#++
require 'uri'
-require 'rubygems'
+require_relative '../rubygems'
##
# Mixin methods for local and remote Gem::Command options.
@@ -14,19 +14,19 @@ require 'rubygems'
module Gem::LocalRemoteOptions
##
- # Allows OptionParser to handle HTTP URIs.
+ # Allows Gem::OptionParser to handle HTTP URIs.
def accept_uri_http
- OptionParser.accept URI::HTTP do |value|
+ Gem::OptionParser.accept URI::HTTP do |value|
begin
uri = URI.parse value
rescue URI::InvalidURIError
- raise OptionParser::InvalidArgument, value
+ raise Gem::OptionParser::InvalidArgument, value
end
valid_uri_schemes = ["http", "https", "file", "s3"]
unless valid_uri_schemes.include?(uri.scheme)
- msg = "Invalid uri scheme for #{value}\nPreface URLs with one of #{valid_uri_schemes.map{|s| "#{s}://"}}"
+ msg = "Invalid uri scheme for #{value}\nPreface URLs with one of #{valid_uri_schemes.map{|s| "#{s}://" }}"
raise ArgumentError, msg
end
diff --git a/lib/rubygems/mock_gem_ui.rb b/lib/rubygems/mock_gem_ui.rb
index 9ece75881c..914ecb9a71 100644
--- a/lib/rubygems/mock_gem_ui.rb
+++ b/lib/rubygems/mock_gem_ui.rb
@@ -1,32 +1,27 @@
# frozen_string_literal: true
-require 'rubygems/user_interaction'
+require_relative 'user_interaction'
##
# This Gem::StreamUI subclass records input and output to StringIO for
# retrieval during tests.
class Gem::MockGemUi < Gem::StreamUI
-
##
# Raised when you haven't provided enough input to your MockGemUi
class InputEOFError < RuntimeError
-
def initialize(question)
super "Out of input for MockGemUi on #{question.inspect}"
end
-
end
class TermError < RuntimeError
-
attr_reader :exit_code
def initialize(exit_code)
super
@exit_code = exit_code
end
-
end
class SystemExitException < RuntimeError; end
@@ -87,5 +82,4 @@ class Gem::MockGemUi < Gem::StreamUI
raise TermError, status if status != 0
raise SystemExitException
end
-
end
diff --git a/lib/rubygems/name_tuple.rb b/lib/rubygems/name_tuple.rb
index dc1a1bbaa0..3d0afa3094 100644
--- a/lib/rubygems/name_tuple.rb
+++ b/lib/rubygems/name_tuple.rb
@@ -4,10 +4,7 @@
# Represents a gem of name +name+ at +version+ of +platform+. These
# wrap the data returned from the indexes.
-require 'rubygems/platform'
-
class Gem::NameTuple
-
def initialize(name, version, platform="ruby")
@name = name
@version = version
@@ -26,7 +23,7 @@ class Gem::NameTuple
# NameTuple objects.
def self.from_list(list)
- list.map { |t| new(*t) }
+ list.map {|t| new(*t) }
end
##
@@ -34,7 +31,7 @@ class Gem::NameTuple
# [name, version, platform] tuples.
def self.to_basic(list)
- list.map { |t| t.to_a }
+ list.map {|t| t.to_a }
end
##
@@ -62,7 +59,7 @@ class Gem::NameTuple
# Indicate if this NameTuple matches the current platform.
def match_platform?
- Gem::Platform.match @platform
+ Gem::Platform.match_gem? @platform, @name
end
##
@@ -121,5 +118,4 @@ class Gem::NameTuple
def hash
to_a.hash
end
-
end
diff --git a/lib/rubygems/openssl.rb b/lib/rubygems/openssl.rb
new file mode 100644
index 0000000000..c44f619c4c
--- /dev/null
+++ b/lib/rubygems/openssl.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+autoload :OpenSSL, "openssl"
+
+module Gem
+ HAVE_OPENSSL = defined? OpenSSL::SSL # :nodoc:
+end
diff --git a/lib/rubygems/optparse.rb b/lib/rubygems/optparse.rb
new file mode 100644
index 0000000000..65be9f6b74
--- /dev/null
+++ b/lib/rubygems/optparse.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require_relative 'optparse/lib/optparse'
diff --git a/lib/rubygems/optparse/.document b/lib/rubygems/optparse/.document
new file mode 100644
index 0000000000..0c43bbd6b3
--- /dev/null
+++ b/lib/rubygems/optparse/.document
@@ -0,0 +1 @@
+# Vendored files do not need to be documented
diff --git a/lib/rubygems/optparse/COPYING b/lib/rubygems/optparse/COPYING
new file mode 100644
index 0000000000..48e5a96de7
--- /dev/null
+++ b/lib/rubygems/optparse/COPYING
@@ -0,0 +1,56 @@
+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:
+
+1. You may make and give away verbatim copies of the source form of the
+ software without restriction, provided that you duplicate all of the
+ original copyright notices and associated disclaimers.
+
+2. You may modify your copy of the software in any way, provided that
+ you do at least ONE of the following:
+
+ a. place your modifications in the Public Domain or otherwise
+ make them Freely Available, such as by posting said
+ modifications to Usenet or an equivalent medium, or by allowing
+ the author to include your modifications in the software.
+
+ b. use the modified software only within your corporation or
+ organization.
+
+ c. give non-standard binaries non-standard names, with
+ instructions on where to get the original software distribution.
+
+ d. make other distribution arrangements with the author.
+
+3. You may distribute the software in object code or binary form,
+ provided that you do at least ONE of the following:
+
+ a. distribute the binaries and library files of the software,
+ together with instructions (in the manual page or equivalent)
+ on where to get the original distribution.
+
+ b. accompany the distribution with the machine-readable source of
+ the software.
+
+ c. give non-standard binaries non-standard names, with
+ instructions on where to get the original software distribution.
+
+ d. make other distribution arrangements with the author.
+
+4. You may modify and include the part of the software into any other
+ software (possibly commercial). But some files in the distribution
+ are not written by the author, so that they are not under these terms.
+
+ For the list of those files and their copying conditions, see the
+ file LEGAL.
+
+5. The scripts and library files supplied as input to or produced as
+ output from the software do not automatically fall under the
+ copyright of the software, but belong to whomever generated them,
+ and may be sold commercially, and may be aggregated with this
+ software.
+
+6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE.
diff --git a/lib/rubygems/optparse/lib/optionparser.rb b/lib/rubygems/optparse/lib/optionparser.rb
new file mode 100644
index 0000000000..4b9b40d82a
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optionparser.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+require_relative 'optparse'
diff --git a/lib/rubygems/optparse/lib/optparse.rb b/lib/rubygems/optparse/lib/optparse.rb
new file mode 100644
index 0000000000..e4b1c61f79
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse.rb
@@ -0,0 +1,2230 @@
+# frozen_string_literal: true
+#
+# optparse.rb - command-line option analysis with the Gem::OptionParser class.
+#
+# Author:: Nobu Nakada
+# Documentation:: Nobu Nakada and Gavin Sinclair.
+#
+# See Gem::OptionParser for documentation.
+#
+
+
+#--
+# == Developer Documentation (not for RDoc output)
+#
+# === Class tree
+#
+# - Gem::OptionParser:: front end
+# - Gem::OptionParser::Switch:: each switches
+# - Gem::OptionParser::List:: options list
+# - Gem::OptionParser::ParseError:: errors on parsing
+# - Gem::OptionParser::AmbiguousOption
+# - Gem::OptionParser::NeedlessArgument
+# - Gem::OptionParser::MissingArgument
+# - Gem::OptionParser::InvalidOption
+# - Gem::OptionParser::InvalidArgument
+# - Gem::OptionParser::AmbiguousArgument
+#
+# === Object relationship diagram
+#
+# +--------------+
+# | Gem::OptionParser |<>-----+
+# +--------------+ | +--------+
+# | ,-| Switch |
+# on_head -------->+---------------+ / +--------+
+# accept/reject -->| List |<|>-
+# | |<|>- +----------+
+# on ------------->+---------------+ `-| argument |
+# : : | class |
+# +---------------+ |==========|
+# on_tail -------->| | |pattern |
+# +---------------+ |----------|
+# Gem::OptionParser.accept ->| DefaultList | |converter |
+# reject |(shared between| +----------+
+# | all instances)|
+# +---------------+
+#
+#++
+#
+# == Gem::OptionParser
+#
+# === New to \Gem::OptionParser?
+#
+# See the {Tutorial}[./doc/optparse/tutorial_rdoc.html].
+#
+# === Introduction
+#
+# Gem::OptionParser is a class for command-line option analysis. It is much more
+# advanced, yet also easier to use, than GetoptLong, and is a more Ruby-oriented
+# solution.
+#
+# === Features
+#
+# 1. The argument specification and the code to handle it are written in the
+# same place.
+# 2. It can output an option summary; you don't need to maintain this string
+# separately.
+# 3. Optional and mandatory arguments are specified very gracefully.
+# 4. Arguments can be automatically converted to a specified class.
+# 5. Arguments can be restricted to a certain set.
+#
+# All of these features are demonstrated in the examples below. See
+# #make_switch for full documentation.
+#
+# === Minimal example
+#
+# require 'rubygems/optparse/lib/optparse'
+#
+# options = {}
+# Gem::OptionParser.new do |parser|
+# parser.banner = "Usage: example.rb [options]"
+#
+# parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
+# options[:verbose] = v
+# end
+# end.parse!
+#
+# p options
+# p ARGV
+#
+# === Generating Help
+#
+# Gem::OptionParser can be used to automatically generate help for the commands you
+# write:
+#
+# require 'rubygems/optparse/lib/optparse'
+#
+# Options = Struct.new(:name)
+#
+# class Parser
+# def self.parse(options)
+# args = Options.new("world")
+#
+# opt_parser = Gem::OptionParser.new do |parser|
+# parser.banner = "Usage: example.rb [options]"
+#
+# parser.on("-nNAME", "--name=NAME", "Name to say hello to") do |n|
+# args.name = n
+# end
+#
+# parser.on("-h", "--help", "Prints this help") do
+# puts parser
+# exit
+# end
+# end
+#
+# opt_parser.parse!(options)
+# return args
+# end
+# end
+# options = Parser.parse %w[--help]
+#
+# #=>
+# # Usage: example.rb [options]
+# # -n, --name=NAME Name to say hello to
+# # -h, --help Prints this help
+#
+# === Required Arguments
+#
+# For options that require an argument, option specification strings may include an
+# option name in all caps. If an option is used without the required argument,
+# an exception will be raised.
+#
+# require 'rubygems/optparse/lib/optparse'
+#
+# options = {}
+# Gem::OptionParser.new do |parser|
+# parser.on("-r", "--require LIBRARY",
+# "Require the LIBRARY before executing your script") do |lib|
+# puts "You required #{lib}!"
+# end
+# end.parse!
+#
+# Used:
+#
+# $ ruby optparse-test.rb -r
+# optparse-test.rb:9:in `<main>': missing argument: -r (Gem::OptionParser::MissingArgument)
+# $ ruby optparse-test.rb -r my-library
+# You required my-library!
+#
+# === Type Coercion
+#
+# Gem::OptionParser supports the ability to coerce command line arguments
+# into objects for us.
+#
+# Gem::OptionParser comes with a few ready-to-use kinds of type
+# coercion. They are:
+#
+# - Date -- Anything accepted by +Date.parse+
+# - DateTime -- Anything accepted by +DateTime.parse+
+# - Time -- Anything accepted by +Time.httpdate+ or +Time.parse+
+# - URI -- Anything accepted by +URI.parse+
+# - Shellwords -- Anything accepted by +Shellwords.shellwords+
+# - String -- Any non-empty string
+# - Integer -- Any integer. Will convert octal. (e.g. 124, -3, 040)
+# - Float -- Any float. (e.g. 10, 3.14, -100E+13)
+# - Numeric -- Any integer, float, or rational (1, 3.4, 1/3)
+# - DecimalInteger -- Like +Integer+, but no octal format.
+# - OctalInteger -- Like +Integer+, but no decimal format.
+# - DecimalNumeric -- Decimal integer or float.
+# - TrueClass -- Accepts '+, yes, true, -, no, false' and
+# defaults as +true+
+# - FalseClass -- Same as +TrueClass+, but defaults to +false+
+# - Array -- Strings separated by ',' (e.g. 1,2,3)
+# - Regexp -- Regular expressions. Also includes options.
+#
+# We can also add our own coercions, which we will cover below.
+#
+# ==== Using Built-in Conversions
+#
+# As an example, the built-in +Time+ conversion is used. The other built-in
+# conversions behave in the same way.
+# Gem::OptionParser will attempt to parse the argument
+# as a +Time+. If it succeeds, that time will be passed to the
+# handler block. Otherwise, an exception will be raised.
+#
+# require 'rubygems/optparse/lib/optparse'
+# require 'rubygems/optparse/lib/optparse/time'
+# Gem::OptionParser.new do |parser|
+# parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
+# p time
+# end
+# end.parse!
+#
+# Used:
+#
+# $ ruby optparse-test.rb -t nonsense
+# ... invalid argument: -t nonsense (Gem::OptionParser::InvalidArgument)
+# $ ruby optparse-test.rb -t 10-11-12
+# 2010-11-12 00:00:00 -0500
+# $ ruby optparse-test.rb -t 9:30
+# 2014-08-13 09:30:00 -0400
+#
+# ==== Creating Custom Conversions
+#
+# The +accept+ method on Gem::OptionParser may be used to create converters.
+# It specifies which conversion block to call whenever a class is specified.
+# The example below uses it to fetch a +User+ object before the +on+ handler receives it.
+#
+# require 'rubygems/optparse/lib/optparse'
+#
+# User = Struct.new(:id, :name)
+#
+# def find_user id
+# not_found = ->{ raise "No User Found for id #{id}" }
+# [ User.new(1, "Sam"),
+# User.new(2, "Gandalf") ].find(not_found) do |u|
+# u.id == id
+# end
+# end
+#
+# op = Gem::OptionParser.new
+# op.accept(User) do |user_id|
+# find_user user_id.to_i
+# end
+#
+# op.on("--user ID", User) do |user|
+# puts user
+# end
+#
+# op.parse!
+#
+# Used:
+#
+# $ ruby optparse-test.rb --user 1
+# #<struct User id=1, name="Sam">
+# $ 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)
+#
+# === Store options to a Hash
+#
+# The +into+ option of +order+, +parse+ and so on methods stores command line options into a Hash.
+#
+# require 'rubygems/optparse/lib/optparse'
+#
+# options = {}
+# Gem::OptionParser.new do |parser|
+# parser.on('-a')
+# parser.on('-b NUM', Integer)
+# parser.on('-v', '--verbose')
+# end.parse!(into: options)
+#
+# p options
+#
+# Used:
+#
+# $ ruby optparse-test.rb -a
+# {:a=>true}
+# $ ruby optparse-test.rb -a -v
+# {:a=>true, :verbose=>true}
+# $ ruby optparse-test.rb -a -b 100
+# {:a=>true, :b=>100}
+#
+# === Complete example
+#
+# The following example is a complete Ruby program. You can run it and see the
+# effect of specifying various options. This is probably the best way to learn
+# the features of +optparse+.
+#
+# require 'rubygems/optparse/lib/optparse'
+# require 'rubygems/optparse/lib/optparse/time'
+# require 'ostruct'
+# require 'pp'
+#
+# class OptparseExample
+# Version = '1.0.0'
+#
+# CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
+# CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
+#
+# class ScriptOptions
+# attr_accessor :library, :inplace, :encoding, :transfer_type,
+# :verbose, :extension, :delay, :time, :record_separator,
+# :list
+#
+# def initialize
+# self.library = []
+# self.inplace = false
+# self.encoding = "utf8"
+# self.transfer_type = :auto
+# self.verbose = false
+# end
+#
+# def define_options(parser)
+# parser.banner = "Usage: example.rb [options]"
+# parser.separator ""
+# parser.separator "Specific options:"
+#
+# # add additional options
+# perform_inplace_option(parser)
+# delay_execution_option(parser)
+# execute_at_time_option(parser)
+# specify_record_separator_option(parser)
+# list_example_option(parser)
+# specify_encoding_option(parser)
+# optional_option_argument_with_keyword_completion_option(parser)
+# boolean_verbose_option(parser)
+#
+# parser.separator ""
+# parser.separator "Common options:"
+# # No argument, shows at tail. This will print an options summary.
+# # Try it and see!
+# parser.on_tail("-h", "--help", "Show this message") do
+# puts parser
+# exit
+# end
+# # Another typical switch to print the version.
+# parser.on_tail("--version", "Show version") do
+# puts Version
+# exit
+# end
+# end
+#
+# def perform_inplace_option(parser)
+# # Specifies an optional option argument
+# parser.on("-i", "--inplace [EXTENSION]",
+# "Edit ARGV files in place",
+# "(make backup if EXTENSION supplied)") do |ext|
+# self.inplace = true
+# self.extension = ext || ''
+# self.extension.sub!(/\A\.?(?=.)/, ".") # Ensure extension begins with dot.
+# end
+# end
+#
+# def delay_execution_option(parser)
+# # Cast 'delay' argument to a Float.
+# parser.on("--delay N", Float, "Delay N seconds before executing") do |n|
+# self.delay = n
+# end
+# end
+#
+# def execute_at_time_option(parser)
+# # Cast 'time' argument to a Time object.
+# parser.on("-t", "--time [TIME]", Time, "Begin execution at given time") do |time|
+# self.time = time
+# end
+# end
+#
+# def specify_record_separator_option(parser)
+# # Cast to octal integer.
+# parser.on("-F", "--irs [OCTAL]", Gem::OptionParser::OctalInteger,
+# "Specify record separator (default \\0)") do |rs|
+# self.record_separator = rs
+# end
+# end
+#
+# def list_example_option(parser)
+# # List of arguments.
+# parser.on("--list x,y,z", Array, "Example 'list' of arguments") do |list|
+# self.list = list
+# end
+# end
+#
+# def specify_encoding_option(parser)
+# # Keyword completion. We are specifying a specific set of arguments (CODES
+# # and CODE_ALIASES - notice the latter is a Hash), and the user may provide
+# # the shortest unambiguous text.
+# code_list = (CODE_ALIASES.keys + CODES).join(', ')
+# parser.on("--code CODE", CODES, CODE_ALIASES, "Select encoding",
+# "(#{code_list})") do |encoding|
+# self.encoding = encoding
+# end
+# end
+#
+# def optional_option_argument_with_keyword_completion_option(parser)
+# # Optional '--type' option argument with keyword completion.
+# parser.on("--type [TYPE]", [:text, :binary, :auto],
+# "Select transfer type (text, binary, auto)") do |t|
+# self.transfer_type = t
+# end
+# end
+#
+# def boolean_verbose_option(parser)
+# # Boolean switch.
+# parser.on("-v", "--[no-]verbose", "Run verbosely") do |v|
+# self.verbose = v
+# end
+# end
+# end
+#
+# #
+# # Return a structure describing the options.
+# #
+# def parse(args)
+# # The options specified on the command line will be collected in
+# # *options*.
+#
+# @options = ScriptOptions.new
+# @args = Gem::OptionParser.new do |parser|
+# @options.define_options(parser)
+# parser.parse!(args)
+# end
+# @options
+# end
+#
+# attr_reader :parser, :options
+# end # class OptparseExample
+#
+# example = OptparseExample.new
+# options = example.parse(ARGV)
+# pp options # example.options
+# pp ARGV
+#
+# === Shell Completion
+#
+# For modern shells (e.g. bash, zsh, etc.), you can use shell
+# completion for command line options.
+#
+# === Further documentation
+#
+# The above examples, along with the accompanying
+# {Tutorial}[./doc/optparse/tutorial_rdoc.html],
+# should be enough to learn how to use this class.
+# If you have any questions, file a ticket at http://bugs.ruby-lang.org.
+#
+class Gem::OptionParser
+ Gem::OptionParser::Version = "0.2.0"
+
+ # :stopdoc:
+ NoArgument = [NO_ARGUMENT = :NONE, nil].freeze
+ RequiredArgument = [REQUIRED_ARGUMENT = :REQUIRED, true].freeze
+ OptionalArgument = [OPTIONAL_ARGUMENT = :OPTIONAL, false].freeze
+ # :startdoc:
+
+ #
+ # Keyword completion module. This allows partial arguments to be specified
+ # and resolved against a list of acceptable values.
+ #
+ module Completion
+ def self.regexp(key, icase)
+ Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'), icase)
+ end
+
+ def self.candidate(key, icase = false, pat = nil, &block)
+ pat ||= Completion.regexp(key, icase)
+ candidates = []
+ block.call do |k, *v|
+ (if Regexp === k
+ kn = ""
+ k === key
+ else
+ kn = defined?(k.id2name) ? k.id2name : k
+ pat === kn
+ end) or next
+ v << k if v.empty?
+ candidates << [k, v, kn]
+ end
+ candidates
+ end
+
+ def candidate(key, icase = false, pat = nil)
+ Completion.candidate(key, icase, pat, &method(:each))
+ end
+
+ public
+ def complete(key, icase = false, pat = nil)
+ candidates = candidate(key, icase, pat, &method(:each)).sort_by {|k, v, kn| kn.size}
+ if candidates.size == 1
+ canon, sw, * = candidates[0]
+ elsif candidates.size > 1
+ canon, sw, cn = candidates.shift
+ candidates.each do |k, v, kn|
+ next if sw == v
+ if String === cn and String === kn
+ if cn.rindex(kn, 0)
+ canon, sw, cn = k, v, kn
+ next
+ elsif kn.rindex(cn, 0)
+ next
+ end
+ end
+ throw :ambiguous, key
+ end
+ end
+ if canon
+ block_given? or return key, *sw
+ yield(key, *sw)
+ end
+ end
+
+ def convert(opt = nil, val = nil, *)
+ val
+ end
+ end
+
+
+ #
+ # Map from option/keyword string to object with completion.
+ #
+ class OptionMap < Hash
+ include Completion
+ end
+
+
+ #
+ # Individual switch class. Not important to the user.
+ #
+ # Defined within Switch are several Switch-derived classes: NoArgument,
+ # RequiredArgument, etc.
+ #
+ class Switch
+ attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block
+
+ #
+ # Guesses argument style from +arg+. Returns corresponding
+ # Gem::OptionParser::Switch class (OptionalArgument, etc.).
+ #
+ def self.guess(arg)
+ case arg
+ when ""
+ t = self
+ when /\A=?\[/
+ t = Switch::OptionalArgument
+ when /\A\s+\[/
+ t = Switch::PlacedArgument
+ else
+ t = Switch::RequiredArgument
+ end
+ self >= t or incompatible_argument_styles(arg, t)
+ t
+ end
+
+ def self.incompatible_argument_styles(arg, t)
+ raise(ArgumentError, "#{arg}: incompatible argument styles\n #{self}, #{t}",
+ ParseError.filter_backtrace(caller(2)))
+ end
+
+ def self.pattern
+ NilClass
+ end
+
+ def initialize(pattern = nil, conv = nil,
+ short = nil, long = nil, arg = nil,
+ desc = ([] if short or long), block = nil, &_block)
+ raise if Array === pattern
+ block ||= _block
+ @pattern, @conv, @short, @long, @arg, @desc, @block =
+ pattern, conv, short, long, arg, desc, block
+ end
+
+ #
+ # Parses +arg+ and returns rest of +arg+ and matched portion to the
+ # argument pattern. Yields when the pattern doesn't match substring.
+ #
+ def parse_arg(arg) # :nodoc:
+ pattern or return nil, [arg]
+ unless m = pattern.match(arg)
+ yield(InvalidArgument, arg)
+ return arg, []
+ end
+ if String === m
+ m = [s = m]
+ else
+ m = m.to_a
+ s = m[0]
+ return nil, m unless String === s
+ end
+ raise InvalidArgument, arg unless arg.rindex(s, 0)
+ return nil, m if s.length == arg.length
+ yield(InvalidArgument, arg) # didn't match whole arg
+ return arg[s.length..-1], m
+ end
+ private :parse_arg
+
+ #
+ # Parses argument, converts and returns +arg+, +block+ and result of
+ # conversion. Yields at semi-error condition instead of raising an
+ # exception.
+ #
+ def conv_arg(arg, val = []) # :nodoc:
+ if conv
+ val = conv.call(*val)
+ else
+ val = proc {|v| v}.call(*val)
+ end
+ return arg, block, val
+ end
+ private :conv_arg
+
+ #
+ # Produces the summary text. Each line of the summary is yielded to the
+ # block (without newline).
+ #
+ # +sdone+:: Already summarized short style options keyed hash.
+ # +ldone+:: Already summarized long style options keyed hash.
+ # +width+:: Width of left side (option part). In other words, the right
+ # side (description part) starts after +width+ columns.
+ # +max+:: Maximum width of left side -> the options are filled within
+ # +max+ columns.
+ # +indent+:: Prefix string indents all summarized lines.
+ #
+ def summarize(sdone = {}, ldone = {}, width = 1, max = width - 1, indent = "")
+ sopts, lopts = [], [], nil
+ @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short
+ @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long
+ return if sopts.empty? and lopts.empty? # completely hidden
+
+ left = [sopts.join(', ')]
+ right = desc.dup
+
+ while s = lopts.shift
+ l = left[-1].length + s.length
+ l += arg.length if left.size == 1 && arg
+ l < max or sopts.empty? or left << +''
+ left[-1] << (left[-1].empty? ? ' ' * 4 : ', ') << s
+ end
+
+ if arg
+ left[0] << (left[1] ? arg.sub(/\A(\[?)=/, '\1') + ',' : arg)
+ end
+ mlen = left.collect {|ss| ss.length}.max.to_i
+ while mlen > width and l = left.shift
+ mlen = left.collect {|ss| ss.length}.max.to_i if l.length == mlen
+ if l.length < width and (r = right[0]) and !r.empty?
+ l = l.to_s.ljust(width) + ' ' + r
+ right.shift
+ end
+ yield(indent + l)
+ end
+
+ while begin l = left.shift; r = right.shift; l or r end
+ l = l.to_s.ljust(width) + ' ' + r if r and !r.empty?
+ yield(indent + l)
+ end
+
+ self
+ end
+
+ def add_banner(to) # :nodoc:
+ unless @short or @long
+ s = desc.join
+ to << " [" + s + "]..." unless s.empty?
+ end
+ to
+ end
+
+ def match_nonswitch?(str) # :nodoc:
+ @pattern =~ str unless @short or @long
+ end
+
+ #
+ # Main name of the switch.
+ #
+ def switch_name
+ (long.first || short.first).sub(/\A-+(?:\[no-\])?/, '')
+ end
+
+ def compsys(sdone, ldone) # :nodoc:
+ sopts, lopts = [], []
+ @short.each {|s| sdone.fetch(s) {sopts << s}; sdone[s] = true} if @short
+ @long.each {|s| ldone.fetch(s) {lopts << s}; ldone[s] = true} if @long
+ return if sopts.empty? and lopts.empty? # completely hidden
+
+ (sopts+lopts).each do |opt|
+ # "(-x -c -r)-l[left justify]"
+ if /^--\[no-\](.+)$/ =~ opt
+ o = $1
+ yield("--#{o}", desc.join(""))
+ yield("--no-#{o}", desc.join(""))
+ else
+ yield("#{opt}", desc.join(""))
+ end
+ end
+ end
+
+ #
+ # Switch that takes no arguments.
+ #
+ class NoArgument < self
+
+ #
+ # Raises an exception if any arguments given.
+ #
+ def parse(arg, argv)
+ yield(NeedlessArgument, arg) if arg
+ conv_arg(arg)
+ end
+
+ def self.incompatible_argument_styles(*)
+ end
+
+ def self.pattern
+ Object
+ end
+ end
+
+ #
+ # Switch that takes an argument.
+ #
+ class RequiredArgument < self
+
+ #
+ # Raises an exception if argument is not present.
+ #
+ def parse(arg, argv)
+ unless arg
+ raise MissingArgument if argv.empty?
+ arg = argv.shift
+ end
+ conv_arg(*parse_arg(arg, &method(:raise)))
+ end
+ end
+
+ #
+ # Switch that can omit argument.
+ #
+ class OptionalArgument < self
+
+ #
+ # Parses argument if given, or uses default value.
+ #
+ def parse(arg, argv, &error)
+ if arg
+ conv_arg(*parse_arg(arg, &error))
+ else
+ conv_arg(arg)
+ end
+ end
+ end
+
+ #
+ # Switch that takes an argument, which does not begin with '-'.
+ #
+ class PlacedArgument < self
+
+ #
+ # Returns nil if argument is not present or begins with '-'.
+ #
+ def parse(arg, argv, &error)
+ if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
+ return nil, block, nil
+ end
+ opt = (val = parse_arg(val, &error))[1]
+ val = conv_arg(*val)
+ if opt and !arg
+ argv.shift
+ else
+ val[0] = nil
+ end
+ val
+ end
+ end
+ end
+
+ #
+ # Simple option list providing mapping from short and/or long option
+ # string to Gem::OptionParser::Switch and mapping from acceptable argument to
+ # matching pattern and converter pair. Also provides summary feature.
+ #
+ class List
+ # Map from acceptable argument types to pattern and converter pairs.
+ attr_reader :atype
+
+ # Map from short style option switches to actual switch objects.
+ attr_reader :short
+
+ # Map from long style option switches to actual switch objects.
+ attr_reader :long
+
+ # List of all switches and summary string.
+ attr_reader :list
+
+ #
+ # Just initializes all instance variables.
+ #
+ def initialize
+ @atype = {}
+ @short = OptionMap.new
+ @long = OptionMap.new
+ @list = []
+ end
+
+ #
+ # See Gem::OptionParser.accept.
+ #
+ def accept(t, pat = /.*/m, &block)
+ if pat
+ pat.respond_to?(:match) or
+ raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2))
+ else
+ pat = t if t.respond_to?(:match)
+ end
+ unless block
+ block = pat.method(:convert).to_proc if pat.respond_to?(:convert)
+ end
+ @atype[t] = [pat, block]
+ end
+
+ #
+ # See Gem::OptionParser.reject.
+ #
+ def reject(t)
+ @atype.delete(t)
+ end
+
+ #
+ # Adds +sw+ according to +sopts+, +lopts+ and +nlopts+.
+ #
+ # +sw+:: Gem::OptionParser::Switch instance to be added.
+ # +sopts+:: Short style option list.
+ # +lopts+:: Long style option list.
+ # +nlopts+:: Negated long style options list.
+ #
+ def update(sw, sopts, lopts, nsw = nil, nlopts = nil) # :nodoc:
+ sopts.each {|o| @short[o] = sw} if sopts
+ lopts.each {|o| @long[o] = sw} if lopts
+ nlopts.each {|o| @long[o] = nsw} if nsw and nlopts
+ used = @short.invert.update(@long.invert)
+ @list.delete_if {|o| Switch === o and !used[o]}
+ end
+ private :update
+
+ #
+ # Inserts +switch+ at the head of the list, and associates short, long
+ # and negated long options. Arguments are:
+ #
+ # +switch+:: Gem::OptionParser::Switch instance to be inserted.
+ # +short_opts+:: List of short style options.
+ # +long_opts+:: List of long style options.
+ # +nolong_opts+:: List of long style options with "no-" prefix.
+ #
+ # prepend(switch, short_opts, long_opts, nolong_opts)
+ #
+ def prepend(*args)
+ update(*args)
+ @list.unshift(args[0])
+ end
+
+ #
+ # Appends +switch+ at the tail of the list, and associates short, long
+ # and negated long options. Arguments are:
+ #
+ # +switch+:: Gem::OptionParser::Switch instance to be inserted.
+ # +short_opts+:: List of short style options.
+ # +long_opts+:: List of long style options.
+ # +nolong_opts+:: List of long style options with "no-" prefix.
+ #
+ # append(switch, short_opts, long_opts, nolong_opts)
+ #
+ def append(*args)
+ update(*args)
+ @list.push(args[0])
+ end
+
+ #
+ # Searches +key+ in +id+ list. The result is returned or yielded if a
+ # block is given. If it isn't found, nil is returned.
+ #
+ def search(id, key)
+ if list = __send__(id)
+ val = list.fetch(key) {return nil}
+ block_given? ? yield(val) : val
+ end
+ end
+
+ #
+ # Searches list +id+ for +opt+ and the optional patterns for completion
+ # +pat+. If +icase+ is true, the search is case insensitive. The result
+ # is returned or yielded if a block is given. If it isn't found, nil is
+ # returned.
+ #
+ def complete(id, opt, icase = false, *pat, &block)
+ __send__(id).complete(opt, icase, *pat, &block)
+ end
+
+ def get_candidates(id)
+ yield __send__(id).keys
+ end
+
+ #
+ # Iterates over each option, passing the option to the +block+.
+ #
+ def each_option(&block)
+ list.each(&block)
+ end
+
+ #
+ # Creates the summary table, passing each line to the +block+ (without
+ # newline). The arguments +args+ are passed along to the summarize
+ # method which is called on every option.
+ #
+ def summarize(*args, &block)
+ sum = []
+ list.reverse_each do |opt|
+ if opt.respond_to?(:summarize) # perhaps Gem::OptionParser::Switch
+ s = []
+ opt.summarize(*args) {|l| s << l}
+ sum.concat(s.reverse)
+ elsif !opt or opt.empty?
+ sum << ""
+ elsif opt.respond_to?(:each_line)
+ sum.concat([*opt.each_line].reverse)
+ else
+ sum.concat([*opt.each].reverse)
+ end
+ end
+ sum.reverse_each(&block)
+ end
+
+ def add_banner(to) # :nodoc:
+ list.each do |opt|
+ if opt.respond_to?(:add_banner)
+ opt.add_banner(to)
+ end
+ end
+ to
+ end
+
+ def compsys(*args, &block) # :nodoc:
+ list.each do |opt|
+ if opt.respond_to?(:compsys)
+ opt.compsys(*args, &block)
+ end
+ end
+ end
+ end
+
+ #
+ # Hash with completion search feature. See Gem::OptionParser::Completion.
+ #
+ class CompletingHash < Hash
+ include Completion
+
+ #
+ # Completion for hash key.
+ #
+ def match(key)
+ *values = fetch(key) {
+ raise AmbiguousArgument, catch(:ambiguous) {return complete(key)}
+ }
+ return key, *values
+ end
+ end
+
+ # :stopdoc:
+
+ #
+ # Enumeration of acceptable argument styles. Possible values are:
+ #
+ # NO_ARGUMENT:: The switch takes no arguments. (:NONE)
+ # REQUIRED_ARGUMENT:: The switch requires an argument. (:REQUIRED)
+ # OPTIONAL_ARGUMENT:: The switch requires an optional argument. (:OPTIONAL)
+ #
+ # Use like --switch=argument (long style) or -Xargument (short style). For
+ # short style, only portion matched to argument pattern is treated as
+ # argument.
+ #
+ ArgumentStyle = {}
+ NoArgument.each {|el| ArgumentStyle[el] = Switch::NoArgument}
+ RequiredArgument.each {|el| ArgumentStyle[el] = Switch::RequiredArgument}
+ OptionalArgument.each {|el| ArgumentStyle[el] = Switch::OptionalArgument}
+ ArgumentStyle.freeze
+
+ #
+ # Switches common used such as '--', and also provides default
+ # argument classes
+ #
+ DefaultList = List.new
+ DefaultList.short['-'] = Switch::NoArgument.new {}
+ DefaultList.long[''] = Switch::NoArgument.new {throw :terminate}
+
+
+ COMPSYS_HEADER = <<'XXX' # :nodoc:
+
+typeset -A opt_args
+local context state line
+
+_arguments -s -S \
+XXX
+
+ def compsys(to, name = File.basename($0)) # :nodoc:
+ to << "#compdef #{name}\n"
+ to << COMPSYS_HEADER
+ visit(:compsys, {}, {}) {|o, d|
+ to << %Q[ "#{o}[#{d.gsub(/[\"\[\]]/, '\\\\\&')}]" \\\n]
+ }
+ to << " '*:file:_files' && return 0\n"
+ end
+
+ #
+ # Default options for ARGV, which never appear in option summary.
+ #
+ Officious = {}
+
+ #
+ # --help
+ # Shows option summary.
+ #
+ Officious['help'] = proc do |parser|
+ Switch::NoArgument.new do |arg|
+ puts parser.help
+ exit
+ end
+ end
+
+ #
+ # --*-completion-bash=WORD
+ # Shows candidates for command line completion.
+ #
+ Officious['*-completion-bash'] = proc do |parser|
+ Switch::RequiredArgument.new do |arg|
+ puts parser.candidate(arg)
+ exit
+ end
+ end
+
+ #
+ # --*-completion-zsh[=NAME:FILE]
+ # Creates zsh completion file.
+ #
+ Officious['*-completion-zsh'] = proc do |parser|
+ Switch::OptionalArgument.new do |arg|
+ parser.compsys(STDOUT, arg)
+ exit
+ end
+ end
+
+ #
+ # --version
+ # Shows version string if Version is defined.
+ #
+ Officious['version'] = proc do |parser|
+ Switch::OptionalArgument.new do |pkg|
+ if pkg
+ begin
+ require 'rubygems/optparse/lib/optparse/version'
+ rescue LoadError
+ else
+ show_version(*pkg.split(/,/)) or
+ abort("#{parser.program_name}: no version found in package #{pkg}")
+ exit
+ end
+ end
+ v = parser.ver or abort("#{parser.program_name}: version unknown")
+ puts v
+ exit
+ end
+ end
+
+ # :startdoc:
+
+ #
+ # Class methods
+ #
+
+ #
+ # Initializes a new instance and evaluates the optional block in context
+ # of the instance. Arguments +args+ are passed to #new, see there for
+ # description of parameters.
+ #
+ # This method is *deprecated*, its behavior corresponds to the older #new
+ # method.
+ #
+ def self.with(*args, &block)
+ opts = new(*args)
+ opts.instance_eval(&block)
+ opts
+ end
+
+ #
+ # Returns an incremented value of +default+ according to +arg+.
+ #
+ def self.inc(arg, default = nil)
+ case arg
+ when Integer
+ arg.nonzero?
+ when nil
+ default.to_i + 1
+ end
+ end
+ def inc(*args)
+ self.class.inc(*args)
+ end
+
+ #
+ # Initializes the instance and yields itself if called with a block.
+ #
+ # +banner+:: Banner message.
+ # +width+:: Summary width.
+ # +indent+:: Summary indent.
+ #
+ def initialize(banner = nil, width = 32, indent = ' ' * 4)
+ @stack = [DefaultList, List.new, List.new]
+ @program_name = nil
+ @banner = banner
+ @summary_width = width
+ @summary_indent = indent
+ @default_argv = ARGV
+ @require_exact = false
+ add_officious
+ yield self if block_given?
+ end
+
+ def add_officious # :nodoc:
+ list = base()
+ Officious.each do |opt, block|
+ list.long[opt] ||= block.call(self)
+ end
+ end
+
+ #
+ # Terminates option parsing. Optional parameter +arg+ is a string pushed
+ # back to be the first non-option argument.
+ #
+ def terminate(arg = nil)
+ self.class.terminate(arg)
+ end
+ def self.terminate(arg = nil)
+ throw :terminate, arg
+ end
+
+ @stack = [DefaultList]
+ def self.top() DefaultList end
+
+ #
+ # Directs to accept specified class +t+. The argument string is passed to
+ # the block in which it should be converted to the desired class.
+ #
+ # +t+:: Argument class specifier, any object including Class.
+ # +pat+:: Pattern for argument, defaults to +t+ if it responds to match.
+ #
+ # accept(t, pat, &block)
+ #
+ def accept(*args, &blk) top.accept(*args, &blk) end
+ #
+ # See #accept.
+ #
+ def self.accept(*args, &blk) top.accept(*args, &blk) end
+
+ #
+ # Directs to reject specified class argument.
+ #
+ # +t+:: Argument class specifier, any object including Class.
+ #
+ # reject(t)
+ #
+ def reject(*args, &blk) top.reject(*args, &blk) end
+ #
+ # See #reject.
+ #
+ def self.reject(*args, &blk) top.reject(*args, &blk) end
+
+ #
+ # Instance methods
+ #
+
+ # Heading banner preceding summary.
+ attr_writer :banner
+
+ # Program name to be emitted in error message and default banner,
+ # defaults to $0.
+ attr_writer :program_name
+
+ # Width for option list portion of summary. Must be Numeric.
+ attr_accessor :summary_width
+
+ # Indentation for summary. Must be String (or have + String method).
+ attr_accessor :summary_indent
+
+ # Strings to be parsed in default.
+ attr_accessor :default_argv
+
+ # Whether to require that options match exactly (disallows providing
+ # abbreviated long option as short option).
+ attr_accessor :require_exact
+
+ #
+ # Heading banner preceding summary.
+ #
+ def banner
+ unless @banner
+ @banner = +"Usage: #{program_name} [options]"
+ visit(:add_banner, @banner)
+ end
+ @banner
+ end
+
+ #
+ # Program name to be emitted in error message and default banner, defaults
+ # to $0.
+ #
+ def program_name
+ @program_name || File.basename($0, '.*')
+ end
+
+ # for experimental cascading :-)
+ alias set_banner banner=
+ alias set_program_name program_name=
+ alias set_summary_width summary_width=
+ alias set_summary_indent summary_indent=
+
+ # Version
+ attr_writer :version
+ # Release code
+ attr_writer :release
+
+ #
+ # Version
+ #
+ def version
+ (defined?(@version) && @version) || (defined?(::Version) && ::Version)
+ end
+
+ #
+ # Release code
+ #
+ def release
+ (defined?(@release) && @release) || (defined?(::Release) && ::Release) || (defined?(::RELEASE) && ::RELEASE)
+ end
+
+ #
+ # Returns version string from program_name, version and release.
+ #
+ def ver
+ if v = version
+ str = +"#{program_name} #{[v].join('.')}"
+ str << " (#{v})" if v = release
+ str
+ end
+ end
+
+ def warn(mesg = $!)
+ super("#{program_name}: #{mesg}")
+ end
+
+ def abort(mesg = $!)
+ super("#{program_name}: #{mesg}")
+ end
+
+ #
+ # Subject of #on / #on_head, #accept / #reject
+ #
+ def top
+ @stack[-1]
+ end
+
+ #
+ # Subject of #on_tail.
+ #
+ def base
+ @stack[1]
+ end
+
+ #
+ # Pushes a new List.
+ #
+ def new
+ @stack.push(List.new)
+ if block_given?
+ yield self
+ else
+ self
+ end
+ end
+
+ #
+ # Removes the last List.
+ #
+ def remove
+ @stack.pop
+ end
+
+ #
+ # Puts option summary into +to+ and returns +to+. Yields each line if
+ # a block is given.
+ #
+ # +to+:: Output destination, which must have method <<. Defaults to [].
+ # +width+:: Width of left side, defaults to @summary_width.
+ # +max+:: Maximum length allowed for left side, defaults to +width+ - 1.
+ # +indent+:: Indentation, defaults to @summary_indent.
+ #
+ def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk)
+ nl = "\n"
+ blk ||= proc {|l| to << (l.index(nl, -1) ? l : l + nl)}
+ visit(:summarize, {}, {}, width, max, indent, &blk)
+ to
+ end
+
+ #
+ # Returns option summary string.
+ #
+ def help; summarize("#{banner}".sub(/\n?\z/, "\n")) end
+ alias to_s help
+
+ #
+ # Returns option summary list.
+ #
+ def to_a; summarize("#{banner}".split(/^/)) end
+
+ #
+ # Checks if an argument is given twice, in which case an ArgumentError is
+ # raised. Called from Gem::OptionParser#switch only.
+ #
+ # +obj+:: New argument.
+ # +prv+:: Previously specified argument.
+ # +msg+:: Exception message.
+ #
+ def notwice(obj, prv, msg) # :nodoc:
+ unless !prv or prv == obj
+ raise(ArgumentError, "argument #{msg} given twice: #{obj}",
+ ParseError.filter_backtrace(caller(2)))
+ end
+ obj
+ end
+ private :notwice
+
+ SPLAT_PROC = proc {|*a| a.length <= 1 ? a.first : a} # :nodoc:
+
+ # :call-seq:
+ # make_switch(params, block = nil)
+ #
+ # :include: ../doc/optparse/creates_option.rdoc
+ #
+ def make_switch(opts, block = nil)
+ short, long, nolong, style, pattern, conv, not_pattern, not_conv, not_style = [], [], []
+ ldesc, sdesc, desc, arg = [], [], []
+ default_style = Switch::NoArgument
+ default_pattern = nil
+ klass = nil
+ q, a = nil
+ has_arg = false
+
+ opts.each do |o|
+ # argument class
+ next if search(:atype, o) do |pat, c|
+ klass = notwice(o, klass, 'type')
+ if not_style and not_style != Switch::NoArgument
+ not_pattern, not_conv = pat, c
+ else
+ default_pattern, conv = pat, c
+ end
+ end
+
+ # directly specified pattern(any object possible to match)
+ if (!(String === o || Symbol === o)) and o.respond_to?(:match)
+ pattern = notwice(o, pattern, 'pattern')
+ if pattern.respond_to?(:convert)
+ conv = pattern.method(:convert).to_proc
+ else
+ conv = SPLAT_PROC
+ end
+ next
+ end
+
+ # anything others
+ case o
+ when Proc, Method
+ block = notwice(o, block, 'block')
+ when Array, Hash
+ case pattern
+ when CompletingHash
+ when nil
+ pattern = CompletingHash.new
+ conv = pattern.method(:convert).to_proc if pattern.respond_to?(:convert)
+ else
+ raise ArgumentError, "argument pattern given twice"
+ end
+ o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
+ when Module
+ raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
+ when *ArgumentStyle.keys
+ style = notwice(ArgumentStyle[o], style, 'style')
+ when /^--no-([^\[\]=\s]*)(.+)?/
+ q, a = $1, $2
+ o = notwice(a ? Object : TrueClass, klass, 'type')
+ not_pattern, not_conv = search(:atype, o) unless not_style
+ not_style = (not_style || default_style).guess(arg = a) if a
+ default_style = Switch::NoArgument
+ default_pattern, conv = search(:atype, FalseClass) unless default_pattern
+ ldesc << "--no-#{q}"
+ (q = q.downcase).tr!('_', '-')
+ long << "no-#{q}"
+ nolong << q
+ when /^--\[no-\]([^\[\]=\s]*)(.+)?/
+ q, a = $1, $2
+ o = notwice(a ? Object : TrueClass, klass, 'type')
+ if a
+ default_style = default_style.guess(arg = a)
+ default_pattern, conv = search(:atype, o) unless default_pattern
+ end
+ ldesc << "--[no-]#{q}"
+ (o = q.downcase).tr!('_', '-')
+ long << o
+ not_pattern, not_conv = search(:atype, FalseClass) unless not_style
+ not_style = Switch::NoArgument
+ nolong << "no-#{o}"
+ when /^--([^\[\]=\s]*)(.+)?/
+ q, a = $1, $2
+ if a
+ o = notwice(NilClass, klass, 'type')
+ default_style = default_style.guess(arg = a)
+ default_pattern, conv = search(:atype, o) unless default_pattern
+ end
+ ldesc << "--#{q}"
+ (o = q.downcase).tr!('_', '-')
+ long << o
+ when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
+ q, a = $1, $2
+ o = notwice(Object, klass, 'type')
+ if a
+ default_style = default_style.guess(arg = a)
+ default_pattern, conv = search(:atype, o) unless default_pattern
+ else
+ has_arg = true
+ end
+ sdesc << "-#{q}"
+ short << Regexp.new(q)
+ when /^-(.)(.+)?/
+ q, a = $1, $2
+ if a
+ o = notwice(NilClass, klass, 'type')
+ default_style = default_style.guess(arg = a)
+ default_pattern, conv = search(:atype, o) unless default_pattern
+ end
+ sdesc << "-#{q}"
+ short << q
+ when /^=/
+ style = notwice(default_style.guess(arg = o), style, 'style')
+ default_pattern, conv = search(:atype, Object) unless default_pattern
+ else
+ desc.push(o)
+ end
+ end
+
+ default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
+ if !(short.empty? and long.empty?)
+ if has_arg and default_style == Switch::NoArgument
+ default_style = Switch::RequiredArgument
+ end
+ s = (style || default_style).new(pattern || default_pattern,
+ conv, sdesc, ldesc, arg, desc, block)
+ elsif !block
+ if style or pattern
+ raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
+ end
+ s = desc
+ else
+ short << pattern
+ s = (style || default_style).new(pattern,
+ conv, nil, nil, arg, desc, block)
+ end
+ return s, short, long,
+ (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
+ nolong
+ end
+
+ # :call-seq:
+ # define(*params, &block)
+ #
+ # :include: ../doc/optparse/creates_option.rdoc
+ #
+ def define(*opts, &block)
+ top.append(*(sw = make_switch(opts, block)))
+ sw[0]
+ end
+
+ # :call-seq:
+ # on(*params, &block)
+ #
+ # :include: ../doc/optparse/creates_option.rdoc
+ #
+ def on(*opts, &block)
+ define(*opts, &block)
+ self
+ end
+ alias def_option define
+
+ # :call-seq:
+ # define_head(*params, &block)
+ #
+ # :include: ../doc/optparse/creates_option.rdoc
+ #
+ def define_head(*opts, &block)
+ top.prepend(*(sw = make_switch(opts, block)))
+ sw[0]
+ end
+
+ # :call-seq:
+ # on_head(*params, &block)
+ #
+ # :include: ../doc/optparse/creates_option.rdoc
+ #
+ # The new option is added at the head of the summary.
+ #
+ def on_head(*opts, &block)
+ define_head(*opts, &block)
+ self
+ end
+ alias def_head_option define_head
+
+ # :call-seq:
+ # define_tail(*params, &block)
+ #
+ # :include: ../doc/optparse/creates_option.rdoc
+ #
+ def define_tail(*opts, &block)
+ base.append(*(sw = make_switch(opts, block)))
+ sw[0]
+ end
+
+ #
+ # :call-seq:
+ # on_tail(*params, &block)
+ #
+ # :include: ../doc/optparse/creates_option.rdoc
+ #
+ # The new option is added at the tail of the summary.
+ #
+ def on_tail(*opts, &block)
+ define_tail(*opts, &block)
+ self
+ end
+ alias def_tail_option define_tail
+
+ #
+ # Add separator in summary.
+ #
+ def separator(string)
+ top.append(string, nil, nil)
+ end
+
+ #
+ # Parses command line arguments +argv+ in order. When a block is given,
+ # each non-option argument is yielded. When optional +into+ keyword
+ # argument is provided, the parsed option values are stored there via
+ # <code>[]=</code> method (so it can be Hash, or OpenStruct, or other
+ # similar object).
+ #
+ # Returns the rest of +argv+ left unparsed.
+ #
+ def order(*argv, into: nil, &nonopt)
+ argv = argv[0].dup if argv.size == 1 and Array === argv[0]
+ order!(argv, into: into, &nonopt)
+ end
+
+ #
+ # Same as #order, but removes switches destructively.
+ # Non-option arguments remain in +argv+.
+ #
+ def order!(argv = default_argv, into: nil, &nonopt)
+ setter = ->(name, val) {into[name.to_sym] = val} if into
+ parse_in_order(argv, setter, &nonopt)
+ end
+
+ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
+ opt, arg, val, rest = nil
+ nonopt ||= proc {|a| throw :terminate, a}
+ argv.unshift(arg) if arg = catch(:terminate) {
+ while arg = argv.shift
+ case arg
+ # long option
+ when /\A--([^=]*)(?:=(.*))?/m
+ opt, rest = $1, $2
+ opt.tr!('_', '-')
+ begin
+ sw, = complete(:long, opt, true)
+ if require_exact && !sw.long.include?(arg)
+ raise InvalidOption, arg
+ end
+ rescue ParseError
+ raise $!.set_option(arg, true)
+ end
+ begin
+ opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
+ val = cb.call(val) if cb
+ setter.call(sw.switch_name, val) if setter
+ rescue ParseError
+ raise $!.set_option(arg, rest)
+ end
+
+ # short option
+ when /\A-(.)((=).*|.+)?/m
+ eq, rest, opt = $3, $2, $1
+ has_arg, val = eq, rest
+ begin
+ sw, = search(:short, opt)
+ unless sw
+ begin
+ sw, = complete(:short, opt)
+ # short option matched.
+ val = arg.delete_prefix('-')
+ has_arg = true
+ rescue InvalidOption
+ raise if require_exact
+ # if no short options match, try completion with long
+ # options.
+ sw, = complete(:long, opt)
+ eq ||= !rest
+ end
+ end
+ rescue ParseError
+ raise $!.set_option(arg, true)
+ end
+ begin
+ opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
+ rescue ParseError
+ raise $!.set_option(arg, arg.length > 2)
+ else
+ raise InvalidOption, arg if has_arg and !eq and arg == "-#{opt}"
+ end
+ begin
+ argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
+ val = cb.call(val) if cb
+ setter.call(sw.switch_name, val) if setter
+ rescue ParseError
+ raise $!.set_option(arg, arg.length > 2)
+ end
+
+ # non-option argument
+ else
+ catch(:prune) do
+ visit(:each_option) do |sw0|
+ sw = sw0
+ sw.block.call(arg) if Switch === sw and sw.match_nonswitch?(arg)
+ end
+ nonopt.call(arg)
+ end
+ end
+ end
+
+ nil
+ }
+
+ visit(:search, :short, nil) {|sw| sw.block.call(*argv) if !sw.pattern}
+
+ argv
+ end
+ private :parse_in_order
+
+ #
+ # Parses command line arguments +argv+ in permutation mode and returns
+ # list of non-option arguments. When optional +into+ keyword
+ # argument is provided, the parsed option values are stored there via
+ # <code>[]=</code> method (so it can be Hash, or OpenStruct, or other
+ # similar object).
+ #
+ def permute(*argv, into: nil)
+ argv = argv[0].dup if argv.size == 1 and Array === argv[0]
+ permute!(argv, into: into)
+ end
+
+ #
+ # Same as #permute, but removes switches destructively.
+ # Non-option arguments remain in +argv+.
+ #
+ def permute!(argv = default_argv, into: nil)
+ nonopts = []
+ order!(argv, into: into, &nonopts.method(:<<))
+ argv[0, 0] = nonopts
+ argv
+ end
+
+ #
+ # Parses command line arguments +argv+ in order when environment variable
+ # POSIXLY_CORRECT is set, and in permutation mode otherwise.
+ # When optional +into+ keyword argument is provided, the parsed option
+ # values are stored there via <code>[]=</code> method (so it can be Hash,
+ # or OpenStruct, or other similar object).
+ #
+ def parse(*argv, into: nil)
+ argv = argv[0].dup if argv.size == 1 and Array === argv[0]
+ parse!(argv, into: into)
+ end
+
+ #
+ # Same as #parse, but removes switches destructively.
+ # Non-option arguments remain in +argv+.
+ #
+ def parse!(argv = default_argv, into: nil)
+ if ENV.include?('POSIXLY_CORRECT')
+ order!(argv, into: into)
+ else
+ permute!(argv, into: into)
+ end
+ end
+
+ #
+ # Wrapper method for getopts.rb.
+ #
+ # params = ARGV.getopts("ab:", "foo", "bar:", "zot:Z;zot option")
+ # # params["a"] = true # -a
+ # # params["b"] = "1" # -b1
+ # # params["foo"] = "1" # --foo
+ # # params["bar"] = "x" # --bar x
+ # # params["zot"] = "z" # --zot Z
+ #
+ def getopts(*args)
+ argv = Array === args.first ? args.shift : default_argv
+ single_options, *long_options = *args
+
+ result = {}
+
+ single_options.scan(/(.)(:)?/) do |opt, val|
+ if val
+ result[opt] = nil
+ define("-#{opt} VAL")
+ else
+ result[opt] = false
+ define("-#{opt}")
+ end
+ end if single_options
+
+ long_options.each do |arg|
+ arg, desc = arg.split(';', 2)
+ opt, val = arg.split(':', 2)
+ if val
+ result[opt] = val.empty? ? nil : val
+ define("--#{opt}=#{result[opt] || "VAL"}", *[desc].compact)
+ else
+ result[opt] = false
+ define("--#{opt}", *[desc].compact)
+ end
+ end
+
+ parse_in_order(argv, result.method(:[]=))
+ result
+ end
+
+ #
+ # See #getopts.
+ #
+ def self.getopts(*args)
+ new.getopts(*args)
+ end
+
+ #
+ # Traverses @stack, sending each element method +id+ with +args+ and
+ # +block+.
+ #
+ def visit(id, *args, &block) # :nodoc:
+ @stack.reverse_each do |el|
+ el.__send__(id, *args, &block)
+ end
+ nil
+ end
+ private :visit
+
+ #
+ # Searches +key+ in @stack for +id+ hash and returns or yields the result.
+ #
+ def search(id, key) # :nodoc:
+ block_given = block_given?
+ visit(:search, id, key) do |k|
+ return block_given ? yield(k) : k
+ end
+ end
+ private :search
+
+ #
+ # Completes shortened long style option switch and returns pair of
+ # canonical switch and switch descriptor Gem::OptionParser::Switch.
+ #
+ # +typ+:: Searching table.
+ # +opt+:: Searching key.
+ # +icase+:: Search case insensitive if true.
+ # +pat+:: Optional pattern for completion.
+ #
+ def complete(typ, opt, icase = false, *pat) # :nodoc:
+ if pat.empty?
+ search(typ, opt) {|sw| return [sw, opt]} # exact match or...
+ end
+ ambiguous = catch(:ambiguous) {
+ visit(:complete, typ, opt, icase, *pat) {|o, *sw| return sw}
+ }
+ exc = ambiguous ? AmbiguousOption : InvalidOption
+ raise exc.new(opt, additional: self.method(:additional_message).curry[typ])
+ end
+ private :complete
+
+ #
+ # Returns additional info.
+ #
+ def additional_message(typ, opt)
+ return unless typ and opt and defined?(DidYouMean::SpellChecker)
+ all_candidates = []
+ visit(:get_candidates, typ) do |candidates|
+ all_candidates.concat(candidates)
+ end
+ all_candidates.select! {|cand| cand.is_a?(String) }
+ checker = DidYouMean::SpellChecker.new(dictionary: all_candidates)
+ suggestions = all_candidates & checker.correct(opt)
+ if DidYouMean.respond_to?(:formatter)
+ DidYouMean.formatter.message_for(suggestions)
+ else
+ "\nDid you mean? #{suggestions.join("\n ")}"
+ end
+ end
+
+ def candidate(word)
+ list = []
+ case word
+ when '-'
+ long = short = true
+ when /\A--/
+ word, arg = word.split(/=/, 2)
+ argpat = Completion.regexp(arg, false) if arg and !arg.empty?
+ long = true
+ when /\A-/
+ short = true
+ end
+ pat = Completion.regexp(word, long)
+ visit(:each_option) do |opt|
+ next unless Switch === opt
+ opts = (long ? opt.long : []) + (short ? opt.short : [])
+ opts = Completion.candidate(word, true, pat, &opts.method(:each)).map(&:first) if pat
+ if /\A=/ =~ opt.arg
+ opts.map! {|sw| sw + "="}
+ if arg and CompletingHash === opt.pattern
+ if opts = opt.pattern.candidate(arg, false, argpat)
+ opts.map!(&:last)
+ end
+ end
+ end
+ list.concat(opts)
+ end
+ list
+ end
+
+ #
+ # Loads options from file names as +filename+. Does nothing when the file
+ # is not present. Returns whether successfully loaded.
+ #
+ # +filename+ defaults to basename of the program without suffix in a
+ # directory ~/.options, then the basename with '.options' suffix
+ # under XDG and Haiku standard places.
+ #
+ def load(filename = nil)
+ unless filename
+ basename = File.basename($0, '.*')
+ return true if load(File.expand_path(basename, '~/.options')) rescue nil
+ basename << ".options"
+ return [
+ # XDG
+ ENV['XDG_CONFIG_HOME'],
+ '~/.config',
+ *ENV['XDG_CONFIG_DIRS']&.split(File::PATH_SEPARATOR),
+
+ # Haiku
+ '~/config/settings',
+ ].any? {|dir|
+ next if !dir or dir.empty?
+ load(File.expand_path(basename, dir)) rescue nil
+ }
+ end
+ begin
+ parse(*IO.readlines(filename).each {|s| s.chomp!})
+ true
+ rescue Errno::ENOENT, Errno::ENOTDIR
+ false
+ end
+ end
+
+ #
+ # Parses environment variable +env+ or its uppercase with splitting like a
+ # shell.
+ #
+ # +env+ defaults to the basename of the program.
+ #
+ def environment(env = File.basename($0, '.*'))
+ env = ENV[env] || ENV[env.upcase] or return
+ require 'shellwords'
+ parse(*Shellwords.shellwords(env))
+ end
+
+ #
+ # Acceptable argument classes
+ #
+
+ #
+ # Any string and no conversion. This is fall-back.
+ #
+ accept(Object) {|s,|s or s.nil?}
+
+ accept(NilClass) {|s,|s}
+
+ #
+ # Any non-empty string, and no conversion.
+ #
+ accept(String, /.+/m) {|s,*|s}
+
+ #
+ # Ruby/C-like integer, octal for 0-7 sequence, binary for 0b, hexadecimal
+ # for 0x, and decimal for others; with optional sign prefix. Converts to
+ # Integer.
+ #
+ decimal = '\d+(?:_\d+)*'
+ binary = 'b[01]+(?:_[01]+)*'
+ hex = 'x[\da-f]+(?:_[\da-f]+)*'
+ octal = "0(?:[0-7]+(?:_[0-7]+)*|#{binary}|#{hex})?"
+ integer = "#{octal}|#{decimal}"
+
+ accept(Integer, %r"\A[-+]?(?:#{integer})\z"io) {|s,|
+ begin
+ Integer(s)
+ rescue ArgumentError
+ raise Gem::OptionParser::InvalidArgument, s
+ end if s
+ }
+
+ #
+ # Float number format, and converts to Float.
+ #
+ float = "(?:#{decimal}(?=(.)?)(?:\\.(?:#{decimal})?)?|\\.#{decimal})(?:E[-+]?#{decimal})?"
+ floatpat = %r"\A[-+]?#{float}\z"io
+ accept(Float, floatpat) {|s,| s.to_f if s}
+
+ #
+ # Generic numeric format, converts to Integer for integer format, Float
+ # for float format, and Rational for rational format.
+ #
+ real = "[-+]?(?:#{octal}|#{float})"
+ accept(Numeric, /\A(#{real})(?:\/(#{real}))?\z/io) {|s, d, f, n,|
+ if n
+ Rational(d, n)
+ elsif f
+ Float(s)
+ else
+ Integer(s)
+ end
+ }
+
+ #
+ # Decimal integer format, to be converted to Integer.
+ #
+ DecimalInteger = /\A[-+]?#{decimal}\z/io
+ accept(DecimalInteger, DecimalInteger) {|s,|
+ begin
+ Integer(s, 10)
+ rescue ArgumentError
+ raise Gem::OptionParser::InvalidArgument, s
+ end if s
+ }
+
+ #
+ # Ruby/C like octal/hexadecimal/binary integer format, to be converted to
+ # Integer.
+ #
+ OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))\z/io
+ accept(OctalInteger, OctalInteger) {|s,|
+ begin
+ Integer(s, 8)
+ rescue ArgumentError
+ raise Gem::OptionParser::InvalidArgument, s
+ end if s
+ }
+
+ #
+ # Decimal integer/float number format, to be converted to Integer for
+ # integer format, Float for float format.
+ #
+ DecimalNumeric = floatpat # decimal integer is allowed as float also.
+ accept(DecimalNumeric, floatpat) {|s, f|
+ begin
+ if f
+ Float(s)
+ else
+ Integer(s)
+ end
+ rescue ArgumentError
+ raise Gem::OptionParser::InvalidArgument, s
+ end if s
+ }
+
+ #
+ # Boolean switch, which means whether it is present or not, whether it is
+ # absent or not with prefix no-, or it takes an argument
+ # yes/no/true/false/+/-.
+ #
+ yesno = CompletingHash.new
+ %w[- no false].each {|el| yesno[el] = false}
+ %w[+ yes true].each {|el| yesno[el] = true}
+ yesno['nil'] = false # should be nil?
+ accept(TrueClass, yesno) {|arg, val| val == nil or val}
+ #
+ # Similar to TrueClass, but defaults to false.
+ #
+ accept(FalseClass, yesno) {|arg, val| val != nil and val}
+
+ #
+ # List of strings separated by ",".
+ #
+ accept(Array) do |s, |
+ if s
+ s = s.split(',').collect {|ss| ss unless ss.empty?}
+ end
+ s
+ end
+
+ #
+ # Regular expression with options.
+ #
+ accept(Regexp, %r"\A/((?:\\.|[^\\])*)/([[:alpha:]]+)?\z|.*") do |all, s, o|
+ f = 0
+ if o
+ f |= Regexp::IGNORECASE if /i/ =~ o
+ f |= Regexp::MULTILINE if /m/ =~ o
+ f |= Regexp::EXTENDED if /x/ =~ o
+ k = o.delete("imx")
+ k = nil if k.empty?
+ end
+ Regexp.new(s || all, f, k)
+ end
+
+ #
+ # Exceptions
+ #
+
+ #
+ # Base class of exceptions from Gem::OptionParser.
+ #
+ class ParseError < RuntimeError
+ # Reason which caused the error.
+ Reason = 'parse error'
+
+ def initialize(*args, additional: nil)
+ @additional = additional
+ @arg0, = args
+ @args = args
+ @reason = nil
+ end
+
+ attr_reader :args
+ attr_writer :reason
+ attr_accessor :additional
+
+ #
+ # Pushes back erred argument(s) to +argv+.
+ #
+ def recover(argv)
+ argv[0, 0] = @args
+ argv
+ end
+
+ def self.filter_backtrace(array)
+ unless $DEBUG
+ array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~))
+ end
+ array
+ end
+
+ def set_backtrace(array)
+ super(self.class.filter_backtrace(array))
+ end
+
+ def set_option(opt, eq)
+ if eq
+ @args[0] = opt
+ else
+ @args.unshift(opt)
+ end
+ self
+ end
+
+ #
+ # Returns error reason. Override this for I18N.
+ #
+ def reason
+ @reason || self.class::Reason
+ end
+
+ def inspect
+ "#<#{self.class}: #{args.join(' ')}>"
+ end
+
+ #
+ # Default stringizing method to emit standard error message.
+ #
+ def message
+ "#{reason}: #{args.join(' ')}#{additional[@arg0] if additional}"
+ end
+
+ alias to_s message
+ end
+
+ #
+ # Raises when ambiguously completable string is encountered.
+ #
+ class AmbiguousOption < ParseError
+ const_set(:Reason, 'ambiguous option')
+ end
+
+ #
+ # Raises when there is an argument for a switch which takes no argument.
+ #
+ class NeedlessArgument < ParseError
+ const_set(:Reason, 'needless argument')
+ end
+
+ #
+ # Raises when a switch with mandatory argument has no argument.
+ #
+ class MissingArgument < ParseError
+ const_set(:Reason, 'missing argument')
+ end
+
+ #
+ # Raises when switch is undefined.
+ #
+ class InvalidOption < ParseError
+ const_set(:Reason, 'invalid option')
+ end
+
+ #
+ # Raises when the given argument does not match required format.
+ #
+ class InvalidArgument < ParseError
+ const_set(:Reason, 'invalid argument')
+ end
+
+ #
+ # Raises when the given argument word can't be completed uniquely.
+ #
+ class AmbiguousArgument < InvalidArgument
+ const_set(:Reason, 'ambiguous argument')
+ end
+
+ #
+ # Miscellaneous
+ #
+
+ #
+ # Extends command line arguments array (ARGV) to parse itself.
+ #
+ module Arguable
+
+ #
+ # Sets Gem::OptionParser object, when +opt+ is +false+ or +nil+, methods
+ # Gem::OptionParser::Arguable#options and Gem::OptionParser::Arguable#options= are
+ # undefined. Thus, there is no ways to access the Gem::OptionParser object
+ # via the receiver object.
+ #
+ def options=(opt)
+ unless @optparse = opt
+ class << self
+ undef_method(:options)
+ undef_method(:options=)
+ end
+ end
+ end
+
+ #
+ # Actual Gem::OptionParser object, automatically created if nonexistent.
+ #
+ # If called with a block, yields the Gem::OptionParser object and returns the
+ # result of the block. If an Gem::OptionParser::ParseError exception occurs
+ # in the block, it is rescued, a error message printed to STDERR and
+ # +nil+ returned.
+ #
+ def options
+ @optparse ||= Gem::OptionParser.new
+ @optparse.default_argv = self
+ block_given? or return @optparse
+ begin
+ yield @optparse
+ rescue ParseError
+ @optparse.warn $!
+ nil
+ end
+ end
+
+ #
+ # Parses +self+ destructively in order and returns +self+ containing the
+ # rest arguments left unparsed.
+ #
+ def order!(&blk) options.order!(self, &blk) end
+
+ #
+ # Parses +self+ destructively in permutation mode and returns +self+
+ # containing the rest arguments left unparsed.
+ #
+ def permute!() options.permute!(self) end
+
+ #
+ # Parses +self+ destructively and returns +self+ containing the
+ # rest arguments left unparsed.
+ #
+ def parse!() options.parse!(self) end
+
+ #
+ # Substitution of getopts is possible as follows. Also see
+ # Gem::OptionParser#getopts.
+ #
+ # def getopts(*args)
+ # ($OPT = ARGV.getopts(*args)).each do |opt, val|
+ # eval "$OPT_#{opt.gsub(/[^A-Za-z0-9_]/, '_')} = val"
+ # end
+ # rescue Gem::OptionParser::ParseError
+ # end
+ #
+ def getopts(*args)
+ options.getopts(self, *args)
+ end
+
+ #
+ # Initializes instance variable.
+ #
+ def self.extend_object(obj)
+ super
+ obj.instance_eval {@optparse = nil}
+ end
+ def initialize(*args)
+ super
+ @optparse = nil
+ end
+ end
+
+ #
+ # Acceptable argument classes. Now contains DecimalInteger, OctalInteger
+ # and DecimalNumeric. See Acceptable argument classes (in source code).
+ #
+ module Acceptables
+ const_set(:DecimalInteger, Gem::OptionParser::DecimalInteger)
+ const_set(:OctalInteger, Gem::OptionParser::OctalInteger)
+ const_set(:DecimalNumeric, Gem::OptionParser::DecimalNumeric)
+ end
+end
+
+# ARGV is arguable by Gem::OptionParser
+ARGV.extend(Gem::OptionParser::Arguable)
diff --git a/lib/rubygems/optparse/lib/optparse/ac.rb b/lib/rubygems/optparse/lib/optparse/ac.rb
new file mode 100644
index 0000000000..ff2f4c2dc3
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/ac.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: false
+require 'rubygems/optparse/lib/optparse'
+
+class Gem::OptionParser::AC < Gem::OptionParser
+ private
+
+ def _check_ac_args(name, block)
+ unless /\A\w[-\w]*\z/ =~ name
+ raise ArgumentError, name
+ end
+ unless block
+ raise ArgumentError, "no block given", ParseError.filter_backtrace(caller)
+ end
+ end
+
+ ARG_CONV = proc {|val| val.nil? ? true : val}
+
+ def _ac_arg_enable(prefix, name, help_string, block)
+ _check_ac_args(name, block)
+
+ sdesc = []
+ ldesc = ["--#{prefix}-#{name}"]
+ desc = [help_string]
+ q = name.downcase
+ ac_block = proc {|val| block.call(ARG_CONV.call(val))}
+ enable = Switch::PlacedArgument.new(nil, ARG_CONV, sdesc, ldesc, nil, desc, ac_block)
+ disable = Switch::NoArgument.new(nil, proc {false}, sdesc, ldesc, nil, desc, ac_block)
+ top.append(enable, [], ["enable-" + q], disable, ['disable-' + q])
+ enable
+ end
+
+ public
+
+ def ac_arg_enable(name, help_string, &block)
+ _ac_arg_enable("enable", name, help_string, block)
+ end
+
+ def ac_arg_disable(name, help_string, &block)
+ _ac_arg_enable("disable", name, help_string, block)
+ end
+
+ def ac_arg_with(name, help_string, &block)
+ _check_ac_args(name, block)
+
+ sdesc = []
+ ldesc = ["--with-#{name}"]
+ desc = [help_string]
+ q = name.downcase
+ with = Switch::PlacedArgument.new(*search(:atype, String), sdesc, ldesc, nil, desc, block)
+ without = Switch::NoArgument.new(nil, proc {}, sdesc, ldesc, nil, desc, block)
+ top.append(with, [], ["with-" + q], without, ['without-' + q])
+ with
+ end
+end
diff --git a/lib/rubygems/optparse/lib/optparse/date.rb b/lib/rubygems/optparse/lib/optparse/date.rb
new file mode 100644
index 0000000000..11131e92c2
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/date.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: false
+require 'rubygems/optparse/lib/optparse'
+require 'date'
+
+Gem::OptionParser.accept(DateTime) do |s,|
+ begin
+ DateTime.parse(s) if s
+ rescue ArgumentError
+ raise Gem::OptionParser::InvalidArgument, s
+ end
+end
+Gem::OptionParser.accept(Date) do |s,|
+ begin
+ Date.parse(s) if s
+ rescue ArgumentError
+ raise Gem::OptionParser::InvalidArgument, s
+ end
+end
diff --git a/lib/rubygems/optparse/lib/optparse/kwargs.rb b/lib/rubygems/optparse/lib/optparse/kwargs.rb
new file mode 100644
index 0000000000..9290344c39
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/kwargs.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+require 'rubygems/optparse/lib/optparse'
+
+class Gem::OptionParser
+ # :call-seq:
+ # define_by_keywords(options, method, **params)
+ #
+ # :include: ../../doc/optparse/creates_option.rdoc
+ #
+ def define_by_keywords(options, meth, **opts)
+ meth.parameters.each do |type, name|
+ case type
+ when :key, :keyreq
+ op, cl = *(type == :key ? %w"[ ]" : ["", ""])
+ define("--#{name}=#{op}#{name.upcase}#{cl}", *opts[name]) do |o|
+ options[name] = o
+ end
+ end
+ end
+ options
+ end
+end
diff --git a/lib/rubygems/optparse/lib/optparse/shellwords.rb b/lib/rubygems/optparse/lib/optparse/shellwords.rb
new file mode 100644
index 0000000000..60dd91990c
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/shellwords.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: false
+# -*- ruby -*-
+
+require 'shellwords'
+require 'rubygems/optparse/lib/optparse'
+
+Gem::OptionParser.accept(Shellwords) {|s,| Shellwords.shellwords(s)}
diff --git a/lib/rubygems/optparse/lib/optparse/time.rb b/lib/rubygems/optparse/lib/optparse/time.rb
new file mode 100644
index 0000000000..cb19f6e998
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/time.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: false
+require 'rubygems/optparse/lib/optparse'
+require 'time'
+
+Gem::OptionParser.accept(Time) do |s,|
+ begin
+ (Time.httpdate(s) rescue Time.parse(s)) if s
+ rescue
+ raise Gem::OptionParser::InvalidArgument, s
+ end
+end
diff --git a/lib/rubygems/optparse/lib/optparse/uri.rb b/lib/rubygems/optparse/lib/optparse/uri.rb
new file mode 100644
index 0000000000..088f309992
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/uri.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: false
+# -*- ruby -*-
+
+require 'rubygems/optparse/lib/optparse'
+require 'uri'
+
+Gem::OptionParser.accept(URI) {|s,| URI.parse(s) if s}
diff --git a/lib/rubygems/optparse/lib/optparse/version.rb b/lib/rubygems/optparse/lib/optparse/version.rb
new file mode 100644
index 0000000000..5d79e9db44
--- /dev/null
+++ b/lib/rubygems/optparse/lib/optparse/version.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: false
+# Gem::OptionParser internal utility
+
+class << Gem::OptionParser
+ def show_version(*pkgs)
+ progname = ARGV.options.program_name
+ result = false
+ show = proc do |klass, cname, version|
+ str = "#{progname}"
+ unless klass == ::Object and cname == :VERSION
+ version = version.join(".") if Array === version
+ str << ": #{klass}" unless klass == Object
+ str << " version #{version}"
+ end
+ [:Release, :RELEASE].find do |rel|
+ if klass.const_defined?(rel)
+ str << " (#{klass.const_get(rel)})"
+ end
+ end
+ puts str
+ result = true
+ end
+ if pkgs.size == 1 and pkgs[0] == "all"
+ self.search_const(::Object, /\AV(?:ERSION|ersion)\z/) do |klass, cname, version|
+ unless cname[1] == ?e and klass.const_defined?(:Version)
+ show.call(klass, cname.intern, version)
+ end
+ end
+ else
+ pkgs.each do |pkg|
+ begin
+ pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)}
+ v = case
+ when pkg.const_defined?(:Version)
+ pkg.const_get(n = :Version)
+ when pkg.const_defined?(:VERSION)
+ pkg.const_get(n = :VERSION)
+ else
+ n = nil
+ "unknown"
+ end
+ show.call(pkg, n, v)
+ rescue NameError
+ end
+ end
+ end
+ result
+ end
+
+ def each_const(path, base = ::Object)
+ path.split(/::|\//).inject(base) do |klass, name|
+ raise NameError, path unless Module === klass
+ klass.constants.grep(/#{name}/i) do |c|
+ klass.const_defined?(c) or next
+ klass.const_get(c)
+ end
+ end
+ end
+
+ def search_const(klass, name)
+ klasses = [klass]
+ while klass = klasses.shift
+ klass.constants.each do |cname|
+ klass.const_defined?(cname) or next
+ const = klass.const_get(cname)
+ yield klass, cname, const if name === cname
+ klasses << const if Module === const and const != ::Object
+ end
+ end
+ end
+end
diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb
index 813ab9da33..94705914af 100644
--- a/lib/rubygems/package.rb
+++ b/lib/rubygems/package.rb
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# frozen_string_literal: true
#--
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
@@ -8,7 +7,8 @@
# Example using a Gem::Package
#
# Builds a .gem file given a Gem::Specification. A .gem file is a tarball
-# which contains a data.tar.gz and metadata.gz, and possibly signatures.
+# which contains a data.tar.gz, metadata.gz, checksums.yaml.gz and possibly
+# signatures.
#
# require 'rubygems'
# require 'rubygems/package'
@@ -41,19 +41,16 @@
# #files are the files in the .gem tar file, not the Ruby files in the gem
# #extract_files and #contents automatically call #verify
-require 'rubygems/security'
-require 'rubygems/specification'
-require 'rubygems/user_interaction'
-require 'zlib'
+require_relative "../rubygems"
+require_relative 'security'
+require_relative 'user_interaction'
class Gem::Package
-
include Gem::UserInteraction
class Error < Gem::Exception; end
class FormatError < Error
-
attr_reader :path
def initialize(message, source = nil)
@@ -65,16 +62,20 @@ class Gem::Package
super message
end
-
end
class PathError < Error
-
def initialize(destination, destination_dir)
super "installing into parent path %s of %s is not allowed" %
[destination, destination_dir]
end
+ end
+ class SymlinkError < Error
+ def initialize(name, destination, destination_dir)
+ super "installing symlink '%s' pointing to parent path %s of %s is not allowed" %
+ [name, destination, destination_dir]
+ end
end
class NonSeekableIO < Error; end
@@ -191,12 +192,14 @@ class Gem::Package
# Creates a new package that will read or write to the file +gem+.
def initialize(gem, security_policy) # :notnew:
+ require 'zlib'
+
@gem = gem
@build_time = Gem.source_date_epoch
@checksums = {}
@contents = nil
- @digests = Hash.new { |h, algorithm| h[algorithm] = {} }
+ @digests = Hash.new {|h, algorithm| h[algorithm] = {} }
@files = nil
@security_policy = security_policy
@signatures = {}
@@ -217,7 +220,7 @@ class Gem::Package
def add_checksums(tar)
Gem.load_yaml
- checksums_by_algorithm = Hash.new { |h, algorithm| h[algorithm] = {} }
+ checksums_by_algorithm = Hash.new {|h, algorithm| h[algorithm] = {} }
@checksums.each do |name, digests|
digests.each do |algorithm, digest|
@@ -256,14 +259,7 @@ class Gem::Package
stat = File.lstat file
if stat.symlink?
- target_path = File.readlink(file)
-
- unless target_path.start_with? '.'
- relative_dir = File.dirname(file).sub("#{Dir.pwd}/", '')
- target_path = File.join(relative_dir, target_path)
- end
-
- tar.add_symlink file, target_path, stat.mode
+ tar.add_symlink file, File.readlink(file), stat.mode
end
next unless stat.file?
@@ -302,7 +298,7 @@ class Gem::Package
setup_signer(
signer_options: {
- expiration_length_days: Gem.configuration.cert_expiration_length_days
+ expiration_length_days: Gem.configuration.cert_expiration_length_days,
}
)
@@ -363,12 +359,7 @@ EOM
end
algorithms.each do |algorithm|
- digester =
- if defined?(OpenSSL::Digest)
- OpenSSL::Digest.new algorithm
- else
- Digest.const_get(algorithm).new
- end
+ digester = Gem::Security.create_digest(algorithm)
digester << entry.read(16384) until entry.eof?
@@ -416,13 +407,21 @@ EOM
# extracted.
def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc:
- directories = [] if dir_mode
+ directories = []
open_tar_gz io do |tar|
tar.each do |entry|
next unless File.fnmatch pattern, entry.full_name, File::FNM_DOTMATCH
destination = install_location entry.full_name, destination_dir
+ if entry.symlink?
+ link_target = entry.header.linkname
+ real_destination = link_target.start_with?("/") ? link_target : File.expand_path(link_target, File.dirname(destination))
+
+ raise Gem::Package::SymlinkError.new(entry.full_name, real_destination, destination_dir) unless
+ normalize_path(real_destination).start_with? normalize_path(destination_dir + '/')
+ end
+
FileUtils.rm_rf destination
mkdir_options = {}
@@ -433,9 +432,11 @@ EOM
else
File.dirname destination
end
- directories << mkdir if directories
- mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name
+ unless directories.include?(mkdir)
+ FileUtils.mkdir_p mkdir, **mkdir_options
+ directories << mkdir
+ end
File.open destination, 'wb' do |out|
out.write entry.read
@@ -448,8 +449,7 @@ EOM
end
end
- if directories
- directories.uniq!
+ if dir_mode
File.chmod(dir_mode, *directories)
end
end
@@ -482,21 +482,11 @@ EOM
raise Gem::Package::PathError.new(filename, destination_dir) if
filename.start_with? '/'
- destination_dir = File.expand_path(File.realpath(destination_dir))
- destination = File.expand_path(File.join(destination_dir, filename))
+ destination_dir = File.realpath(destination_dir)
+ destination = File.expand_path(filename, destination_dir)
raise Gem::Package::PathError.new(destination, destination_dir) unless
- destination.start_with? destination_dir + '/'
-
- begin
- real_destination = File.expand_path(File.realpath(destination))
- rescue
- # it's fine if the destination doesn't exist, because rm -rf'ing it can't cause any damage
- nil
- else
- raise Gem::Package::PathError.new(real_destination, destination_dir) unless
- real_destination.start_with? destination_dir + '/'
- end
+ normalize_path(destination).start_with? normalize_path(destination_dir + '/')
destination.tap(&Gem::UNTAINT)
destination
@@ -510,22 +500,6 @@ EOM
end
end
- def mkdir_p_safe(mkdir, mkdir_options, destination_dir, file_name)
- destination_dir = File.realpath(File.expand_path(destination_dir))
- parts = mkdir.split(File::SEPARATOR)
- parts.reduce do |path, basename|
- path = File.realpath(path) unless path == ""
- path = File.expand_path(path + File::SEPARATOR + basename)
- lstat = File.lstat path rescue nil
- if !lstat || !lstat.directory?
- unless normalize_path(path).start_with? normalize_path(destination_dir) and (FileUtils.mkdir path, **mkdir_options rescue false)
- raise Gem::Package::PathError.new(file_name, destination_dir)
- end
- end
- path
- end
- end
-
##
# Loads a Gem::Specification from the TarEntry +entry+
@@ -580,10 +554,10 @@ EOM
)
@spec.signing_key = nil
- @spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_s }
+ @spec.cert_chain = @signer.cert_chain.map {|cert| cert.to_s }
else
@signer = Gem::Security::Signer.new nil, nil, passphrase
- @spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_pem } if
+ @spec.cert_chain = @signer.cert_chain.map {|cert| cert.to_pem } if
@signer.cert_chain
end
end
@@ -679,10 +653,9 @@ EOM
when 'data.tar.gz' then
verify_gz entry
end
- rescue => e
- message = "package is corrupt, exception while verifying: " +
- "#{e.message} (#{e.class})"
- raise Gem::Package::FormatError.new message, @gem
+ rescue
+ warn "Exception while verifying #{@gem.path}"
+ raise
end
##
@@ -717,15 +690,14 @@ EOM
rescue Zlib::GzipFile::Error => e
raise Gem::Package::FormatError.new(e.message, entry.full_name)
end
-
end
-require 'rubygems/package/digest_io'
-require 'rubygems/package/source'
-require 'rubygems/package/file_source'
-require 'rubygems/package/io_source'
-require 'rubygems/package/old'
-require 'rubygems/package/tar_header'
-require 'rubygems/package/tar_reader'
-require 'rubygems/package/tar_reader/entry'
-require 'rubygems/package/tar_writer'
+require_relative 'package/digest_io'
+require_relative 'package/source'
+require_relative 'package/file_source'
+require_relative 'package/io_source'
+require_relative 'package/old'
+require_relative 'package/tar_header'
+require_relative 'package/tar_reader'
+require_relative 'package/tar_reader/entry'
+require_relative 'package/tar_writer'
diff --git a/lib/rubygems/package/digest_io.rb b/lib/rubygems/package/digest_io.rb
index d9e6c3c021..4736f76d93 100644
--- a/lib/rubygems/package/digest_io.rb
+++ b/lib/rubygems/package/digest_io.rb
@@ -3,7 +3,6 @@
# IO wrapper that creates digests of contents written to the IO it wraps.
class Gem::Package::DigestIO
-
##
# Collected digests for wrapped writes.
#
@@ -60,5 +59,4 @@ class Gem::Package::DigestIO
result
end
-
end
diff --git a/lib/rubygems/package/file_source.rb b/lib/rubygems/package/file_source.rb
index 8a4f9da6f2..114a950c77 100644
--- a/lib/rubygems/package/file_source.rb
+++ b/lib/rubygems/package/file_source.rb
@@ -7,7 +7,6 @@
# object to `Gem::Package.new`.
class Gem::Package::FileSource < Gem::Package::Source # :nodoc: all
-
attr_reader :path
def initialize(path)
@@ -29,5 +28,4 @@ class Gem::Package::FileSource < Gem::Package::Source # :nodoc: all
def with_read_io(&block)
File.open path, 'rb', &block
end
-
end
diff --git a/lib/rubygems/package/io_source.rb b/lib/rubygems/package/io_source.rb
index 669a859d0a..03d7714524 100644
--- a/lib/rubygems/package/io_source.rb
+++ b/lib/rubygems/package/io_source.rb
@@ -8,7 +8,6 @@
# object to `Gem::Package.new`.
class Gem::Package::IOSource < Gem::Package::Source # :nodoc: all
-
attr_reader :io
def initialize(io)
@@ -33,13 +32,16 @@ class Gem::Package::IOSource < Gem::Package::Source # :nodoc: all
def with_read_io
yield io
+ ensure
+ io.rewind
end
def with_write_io
yield io
+ ensure
+ io.rewind
end
def path
end
-
end
diff --git a/lib/rubygems/package/old.rb b/lib/rubygems/package/old.rb
index f574b989aa..25317ef23f 100644
--- a/lib/rubygems/package/old.rb
+++ b/lib/rubygems/package/old.rb
@@ -12,7 +12,6 @@
# Please pretend this doesn't exist.
class Gem::Package::Old < Gem::Package
-
undef_method :spec=
##
@@ -42,7 +41,7 @@ class Gem::Package::Old < Gem::Package
read_until_dashes io # spec
header = file_list io
- @contents = header.map { |file| file['path'] }
+ @contents = header.map {|file| file['path'] }
end
end
@@ -166,5 +165,4 @@ class Gem::Package::Old < Gem::Package
true
end
-
end
diff --git a/lib/rubygems/package/tar_header.rb b/lib/rubygems/package/tar_header.rb
index c37612772a..ce9b49e3eb 100644
--- a/lib/rubygems/package/tar_header.rb
+++ b/lib/rubygems/package/tar_header.rb
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# frozen_string_literal: true
#--
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
@@ -29,7 +28,6 @@
# A header for a tar file
class Gem::Package::TarHeader
-
##
# Fields in the tar header
@@ -126,7 +124,8 @@ class Gem::Package::TarHeader
end
def self.strict_oct(str)
- return str.oct if str =~ /\A[0-7]*\z/
+ return str.strip.oct if str.strip =~ /\A[0-7]*\z/
+
raise ArgumentError, "#{str.inspect} is not an octal string"
end
@@ -209,7 +208,7 @@ class Gem::Package::TarHeader
private
def calculate_checksum(header)
- header.unpack("C*").inject { |a, b| a + b }
+ header.unpack("C*").inject {|a, b| a + b }
end
def header(checksum = @checksum)
@@ -230,7 +229,7 @@ class Gem::Package::TarHeader
gname,
oct(devmajor, 7),
oct(devminor, 7),
- prefix
+ prefix,
]
header = header.pack PACK_FORMAT
@@ -241,5 +240,4 @@ class Gem::Package::TarHeader
def oct(num, len)
"%0#{len}o" % num
end
-
end
diff --git a/lib/rubygems/package/tar_reader.rb b/lib/rubygems/package/tar_reader.rb
index aa31ea27d4..41121f3bfb 100644
--- a/lib/rubygems/package/tar_reader.rb
+++ b/lib/rubygems/package/tar_reader.rb
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# frozen_string_literal: true
#--
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
@@ -9,7 +8,6 @@
# TarReader reads tar files and allows iteration over their items
class Gem::Package::TarReader
-
include Enumerable
##
@@ -121,7 +119,6 @@ class Gem::Package::TarReader
ensure
rewind
end
-
end
-require 'rubygems/package/tar_reader/entry'
+require_relative 'tar_reader/entry'
diff --git a/lib/rubygems/package/tar_reader/entry.rb b/lib/rubygems/package/tar_reader/entry.rb
index 19054c1635..5865599d3a 100644
--- a/lib/rubygems/package/tar_reader/entry.rb
+++ b/lib/rubygems/package/tar_reader/entry.rb
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# frozen_string_literal: true
#++
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
@@ -9,7 +8,6 @@
# Class for reading entries out of a tar file
class Gem::Package::TarReader::Entry
-
##
# Header for this tar entry
@@ -166,5 +164,4 @@ class Gem::Package::TarReader::Entry
@io.pos = @orig_pos
@read = 0
end
-
end
diff --git a/lib/rubygems/package/tar_test_case.rb b/lib/rubygems/package/tar_test_case.rb
deleted file mode 100644
index 75978c8ed0..0000000000
--- a/lib/rubygems/package/tar_test_case.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-# frozen_string_literal: true
-require 'rubygems/test_case'
-require 'rubygems/package'
-
-##
-# A test case for Gem::Package::Tar* classes
-
-class Gem::Package::TarTestCase < Gem::TestCase
-
- def ASCIIZ(str, length)
- str + "\0" * (length - str.length)
- end
-
- def SP(s)
- s + " "
- end
-
- def SP_Z(s)
- s + " \0"
- end
-
- def Z(s)
- s + "\0"
- end
-
- def assert_headers_equal(expected, actual)
- expected = expected.to_s unless String === expected
- actual = actual.to_s unless String === actual
-
- fields = %w[
- name 100
- mode 8
- uid 8
- gid 8
- size 12
- mtime 12
- checksum 8
- typeflag 1
- linkname 100
- magic 6
- version 2
- uname 32
- gname 32
- devmajor 8
- devminor 8
- prefix 155
- ]
-
- offset = 0
-
- until fields.empty? do
- name = fields.shift
- length = fields.shift.to_i
-
- if name == "checksum"
- chksum_off = offset
- offset += length
- next
- end
-
- assert_equal expected[offset, length], actual[offset, length],
- "Field #{name} of the tar header differs."
-
- offset += length
- end
-
- assert_equal expected[chksum_off, 8], actual[chksum_off, 8]
- end
-
- def calc_checksum(header)
- sum = header.unpack("C*").inject{|s,a| s + a}
- SP(Z(to_oct(sum, 6)))
- end
-
- def header(type, fname, dname, length, mode, mtime, checksum = nil, linkname = "")
- checksum ||= " " * 8
-
- arr = [ # struct tarfile_entry_posix
- ASCIIZ(fname, 100), # char name[100]; ASCII + (Z unless filled)
- Z(to_oct(mode, 7)), # char mode[8]; 0 padded, octal null
- Z(to_oct(0, 7)), # char uid[8]; ditto
- Z(to_oct(0, 7)), # char gid[8]; ditto
- Z(to_oct(length, 11)), # char size[12]; 0 padded, octal, null
- Z(to_oct(mtime, 11)), # char mtime[12]; 0 padded, octal, null
- checksum, # char checksum[8]; 0 padded, octal, null, space
- type, # char typeflag[1]; file: "0" dir: "5"
- ASCIIZ(linkname, 100), # char linkname[100]; ASCII + (Z unless filled)
- "ustar\0", # char magic[6]; "ustar\0"
- "00", # char version[2]; "00"
- ASCIIZ("wheel", 32), # char uname[32]; ASCIIZ
- ASCIIZ("wheel", 32), # char gname[32]; ASCIIZ
- Z(to_oct(0, 7)), # char devmajor[8]; 0 padded, octal, null
- Z(to_oct(0, 7)), # char devminor[8]; 0 padded, octal, null
- ASCIIZ(dname, 155) # char prefix[155]; ASCII + (Z unless filled)
- ]
-
- h = arr.join
- ret = h + "\0" * (512 - h.size)
- assert_equal(512, ret.size)
- ret
- end
-
- def tar_dir_header(name, prefix, mode, mtime)
- h = header("5", name, prefix, 0, mode, mtime)
- checksum = calc_checksum(h)
- header("5", name, prefix, 0, mode, mtime, checksum)
- end
-
- def tar_file_header(fname, dname, mode, length, mtime)
- h = header("0", fname, dname, length, mode, mtime)
- checksum = calc_checksum(h)
- header("0", fname, dname, length, mode, mtime, checksum)
- end
-
- def tar_symlink_header(fname, prefix, mode, mtime, linkname)
- h = header("2", fname, prefix, 0, mode, mtime, nil, linkname)
- checksum = calc_checksum(h)
- header("2", fname, prefix, 0, mode, mtime, checksum, linkname)
- end
-
- def to_oct(n, pad_size)
- "%0#{pad_size}o" % n
- end
-
- def util_entry(tar)
- io = TempIO.new tar
-
- header = Gem::Package::TarHeader.from io
-
- Gem::Package::TarReader::Entry.new header, io
- end
-
- def util_dir_entry
- util_entry tar_dir_header("foo", "bar", 0, Time.now)
- end
-
- def util_symlink_entry
- util_entry tar_symlink_header("foo", "bar", 0, Time.now, "link")
- end
-
-end
diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb
index 96d8184e8e..877cc167c9 100644
--- a/lib/rubygems/package/tar_writer.rb
+++ b/lib/rubygems/package/tar_writer.rb
@@ -1,24 +1,19 @@
-# -*- coding: utf-8 -*-
# frozen_string_literal: true
#--
# Copyright (C) 2004 Mauricio Julio Fernández Pradier
# See LICENSE.txt for additional licensing information.
#++
-require 'digest'
-
##
# Allows writing of tar files
class Gem::Package::TarWriter
-
class FileOverflow < StandardError; end
##
# IO wrapper that allows writing a limited amount of data
class BoundedStream
-
##
# Maximum number of bytes that can be written
@@ -50,14 +45,12 @@ class Gem::Package::TarWriter
@written += data.bytesize
data.bytesize
end
-
end
##
# IO wrapper that provides only #write
class RestrictedStream
-
##
# Creates a new RestrictedStream wrapping +io+
@@ -71,7 +64,6 @@ class Gem::Package::TarWriter
def write(data)
@io.write data
end
-
end
##
@@ -146,8 +138,7 @@ class Gem::Package::TarWriter
if digest.respond_to? :name
digest.name
else
- /::([^:]+)$/ =~ digest_algorithm.name
- $1
+ digest_algorithm.class.name[/::([^:]+)\z/, 1]
end
[digest_name, digest]
@@ -175,7 +166,7 @@ class Gem::Package::TarWriter
def add_file_signed(name, mode, signer)
digest_algorithms = [
signer.digest_algorithm,
- Digest::SHA512,
+ Gem::Security.create_digest('SHA512'),
].compact.uniq
digests = add_file_digest name, mode, digest_algorithms do |io|
@@ -334,5 +325,4 @@ class Gem::Package::TarWriter
return name, prefix
end
-
end
diff --git a/lib/rubygems/package_task.rb b/lib/rubygems/package_task.rb
index a11d09fb21..bb48616b0e 100644
--- a/lib/rubygems/package_task.rb
+++ b/lib/rubygems/package_task.rb
@@ -20,13 +20,8 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-require 'rubygems'
-require 'rubygems/package'
-begin
- gem 'rake'
-rescue Gem::LoadError
-end
-
+require_relative '../rubygems'
+require_relative 'package'
require 'rake/packagetask'
##
@@ -62,7 +57,6 @@ require 'rake/packagetask'
# end
class Gem::PackageTask < Rake::PackageTask
-
##
# Ruby Gem::Specification containing the metadata for this package. The
# name, version and package_files are automatically determined from the
@@ -88,6 +82,7 @@ class Gem::PackageTask < Rake::PackageTask
super gem.full_name, :noversion
@gem_spec = gem
@package_files += gem_spec.files if gem_spec.files
+ @fileutils_output = $stdout
end
##
@@ -124,5 +119,4 @@ class Gem::PackageTask < Rake::PackageTask
end
end
end
-
end
diff --git a/lib/rubygems/path_support.rb b/lib/rubygems/path_support.rb
index 6a5d180a02..8103caf324 100644
--- a/lib/rubygems/path_support.rb
+++ b/lib/rubygems/path_support.rb
@@ -5,7 +5,6 @@
# to the rest of RubyGems.
#
class Gem::PathSupport
-
##
# The default system path for managing Gems.
attr_reader :home
@@ -68,7 +67,7 @@ class Gem::PathSupport
gem_path = default_path
end
- gem_path.map { |path| expand(path) }.uniq
+ gem_path.map {|path| expand(path) }.uniq
end
# Return the default Gem path
@@ -88,5 +87,4 @@ class Gem::PathSupport
path
end
end
-
end
diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb
index 521c552bea..efb046c7aa 100644
--- a/lib/rubygems/platform.rb
+++ b/lib/rubygems/platform.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require "rubygems/deprecate"
+require_relative "deprecate"
##
# Available list of platforms for targeting Gem installations.
@@ -7,14 +7,9 @@ require "rubygems/deprecate"
# See `gem help platform` for information on platform matching.
class Gem::Platform
-
@local = nil
- attr_accessor :cpu
-
- attr_accessor :os
-
- attr_accessor :version
+ attr_accessor :cpu, :os, :version
def self.local
arch = RbConfig::CONFIG['arch']
@@ -23,18 +18,33 @@ class Gem::Platform
end
def self.match(platform)
- Gem.platforms.any? do |local_platform|
+ match_platforms?(platform, Gem.platforms)
+ end
+
+ def self.match_platforms?(platform, platforms)
+ platforms.any? do |local_platform|
platform.nil? or
local_platform == platform or
(local_platform != Gem::Platform::RUBY and local_platform =~ platform)
end
end
+ private_class_method :match_platforms?
+
+ def self.match_spec?(spec)
+ match_gem?(spec.platform, spec.name)
+ end
+
+ def self.match_gem?(platform, gem_name)
+ # Note: this method might be redefined by Ruby implementations to
+ # customize behavior per RUBY_ENGINE, gem_name or other criteria.
+ match_platforms?(platform, Gem.platforms)
+ end
def self.installable?(spec)
if spec.respond_to? :installable_platform?
spec.installable_platform?
else
- match spec.platform
+ match_spec? spec
end
end
@@ -56,7 +66,7 @@ class Gem::Platform
when String then
arch = arch.split '-'
- if arch.length > 2 and arch.last !~ /\d/ # reassemble x86-linux-gnu
+ if arch.length > 2 and arch.last !~ /\d/ # reassemble x86-linux-gnu
extra = arch.pop
arch.last << "-#{extra}"
end
@@ -68,7 +78,7 @@ class Gem::Platform
else cpu
end
- if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ # for command-line
+ if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ # for command-line
@os, @version = arch
return
end
@@ -90,6 +100,7 @@ class Gem::Platform
when /^dotnet([\d.]*)/ then [ 'dotnet', $1 ]
when /linux-?((?!gnu)\w+)?/ then [ 'linux', $1 ]
when /mingw32/ then [ 'mingw32', nil ]
+ when /mingw-?(\w+)?/ then [ 'mingw', $1 ]
when /(mswin\d+)(\_(\d+))?/ then
os, version = $1, $3
@cpu = 'x86' if @cpu.nil? and os =~ /32$/
@@ -111,10 +122,6 @@ class Gem::Platform
end
end
- def inspect
- "%s @cpu=%p, @os=%p, @version=%p>" % [super[0..-2], *to_a]
- end
-
def to_a
[@cpu, @os, @version]
end
@@ -150,7 +157,7 @@ class Gem::Platform
# cpu
([nil,'universal'].include?(@cpu) or [nil, 'universal'].include?(other.cpu) or @cpu == other.cpu or
- (@cpu == 'arm' and other.cpu =~ /\Aarm/)) and
+ (@cpu == 'arm' and other.cpu.start_with?("arm"))) and
# os
@os == other.os and
@@ -202,5 +209,4 @@ class Gem::Platform
# This will be replaced with Gem::Platform::local.
CURRENT = 'current'.freeze
-
end
diff --git a/lib/rubygems/psych_tree.rb b/lib/rubygems/psych_tree.rb
index b4eebf1dcc..6f399a289e 100644
--- a/lib/rubygems/psych_tree.rb
+++ b/lib/rubygems/psych_tree.rb
@@ -2,7 +2,6 @@
module Gem
if defined? ::Psych::Visitors
class NoAliasYAMLTree < Psych::Visitors::YAMLTree
-
def self.create
new({})
end unless respond_to? :create
@@ -28,7 +27,6 @@ module Gem
end
private :format_time
-
end
end
end
diff --git a/lib/rubygems/query_utils.rb b/lib/rubygems/query_utils.rb
new file mode 100644
index 0000000000..0acd5bf9c8
--- /dev/null
+++ b/lib/rubygems/query_utils.rb
@@ -0,0 +1,353 @@
+# frozen_string_literal: true
+
+require_relative 'local_remote_options'
+require_relative 'spec_fetcher'
+require_relative 'version_option'
+require_relative 'text'
+
+module Gem::QueryUtils
+
+ include Gem::Text
+ include Gem::LocalRemoteOptions
+ include Gem::VersionOption
+
+ def add_query_options
+ add_option('-i', '--[no-]installed',
+ 'Check for installed gem') do |value, options|
+ options[:installed] = value
+ end
+
+ add_option('-I', 'Equivalent to --no-installed') do |value, options|
+ options[:installed] = false
+ end
+
+ add_version_option command, "for use with --installed"
+
+ add_option('-d', '--[no-]details',
+ 'Display detailed information of gem(s)') do |value, options|
+ options[:details] = value
+ end
+
+ add_option('--[no-]versions',
+ 'Display only gem names') do |value, options|
+ options[:versions] = value
+ options[:details] = false unless value
+ end
+
+ add_option('-a', '--all',
+ 'Display all gem versions') do |value, options|
+ options[:all] = value
+ end
+
+ add_option('-e', '--exact',
+ 'Name of gem(s) to query on matches the',
+ 'provided STRING') do |value, options|
+ options[:exact] = value
+ end
+
+ add_option('--[no-]prerelease',
+ 'Display prerelease versions') do |value, options|
+ options[:prerelease] = value
+ end
+
+ add_local_remote_options
+ end
+
+ def defaults_str # :nodoc:
+ "--local --name-matches // --no-details --versions --no-installed"
+ end
+
+ def execute
+ gem_names = Array(options[:name])
+
+ if !args.empty?
+ gem_names = options[:exact] ? args.map{|arg| /\A#{Regexp.escape(arg)}\Z/ } : args.map{|arg| /#{arg}/i }
+ end
+
+ terminate_interaction(check_installed_gems(gem_names)) if check_installed_gems?
+
+ gem_names.each {|n| show_gems(n) }
+ end
+
+ private
+
+ def check_installed_gems(gem_names)
+ exit_code = 0
+
+ if args.empty? && !gem_name?
+ alert_error "You must specify a gem name"
+ exit_code = 4
+ elsif gem_names.count > 1
+ alert_error "You must specify only ONE gem!"
+ exit_code = 4
+ else
+ installed = installed?(gem_names.first, options[:version])
+ installed = !installed unless options[:installed]
+
+ say(installed)
+ exit_code = 1 if !installed
+ end
+
+ exit_code
+ end
+
+ def check_installed_gems?
+ !options[:installed].nil?
+ end
+
+ def gem_name?
+ !options[:name].source.empty?
+ end
+
+ def prerelease
+ options[:prerelease]
+ end
+
+ def show_prereleases?
+ prerelease.nil? || prerelease
+ end
+
+ def args
+ options[:args].to_a
+ end
+
+ def display_header(type)
+ if (ui.outs.tty? and Gem.configuration.verbose) or both?
+ say
+ say "*** #{type} GEMS ***"
+ say
+ end
+ end
+
+ #Guts of original execute
+ def show_gems(name)
+ show_local_gems(name) if local?
+ show_remote_gems(name) if remote?
+ end
+
+ def show_local_gems(name, req = Gem::Requirement.default)
+ display_header("LOCAL")
+
+ specs = Gem::Specification.find_all do |s|
+ s.name =~ name and req =~ s.version
+ end
+
+ dep = Gem::Deprecate.skip_during { Gem::Dependency.new name, req }
+ specs.select! do |s|
+ dep.match?(s.name, s.version, show_prereleases?)
+ end
+
+ spec_tuples = specs.map do |spec|
+ [spec.name_tuple, spec]
+ end
+
+ output_query_results(spec_tuples)
+ end
+
+ def show_remote_gems(name)
+ display_header("REMOTE")
+
+ fetcher = Gem::SpecFetcher.fetcher
+
+ spec_tuples = if name.respond_to?(:source) && name.source.empty?
+ fetcher.detect(specs_type) { true }
+ else
+ fetcher.detect(specs_type) do |name_tuple|
+ name === name_tuple.name
+ end
+ end
+
+ output_query_results(spec_tuples)
+ end
+
+ def specs_type
+ if options[:all]
+ if options[:prerelease]
+ :complete
+ else
+ :released
+ end
+ elsif options[:prerelease]
+ :prerelease
+ else
+ :latest
+ end
+ end
+
+ ##
+ # Check if gem +name+ version +version+ is installed.
+
+ def installed?(name, req = Gem::Requirement.default)
+ Gem::Specification.any? {|s| s.name =~ name and req =~ s.version }
+ end
+
+ def output_query_results(spec_tuples)
+ output = []
+ versions = Hash.new {|h,name| h[name] = [] }
+
+ spec_tuples.each do |spec_tuple, source|
+ versions[spec_tuple.name] << [spec_tuple, source]
+ end
+
+ versions = versions.sort_by do |(n,_),_|
+ n.downcase
+ end
+
+ output_versions output, versions
+
+ say output.join(options[:details] ? "\n\n" : "\n")
+ end
+
+ def output_versions(output, versions)
+ versions.each do |gem_name, matching_tuples|
+ matching_tuples = matching_tuples.sort_by {|n,_| n.version }.reverse
+
+ platforms = Hash.new {|h,version| h[version] = [] }
+
+ matching_tuples.each do |n, _|
+ platforms[n.version] << n.platform if n.platform
+ end
+
+ seen = {}
+
+ matching_tuples.delete_if do |n,_|
+ if seen[n.version]
+ true
+ else
+ seen[n.version] = true
+ false
+ end
+ end
+
+ output << clean_text(make_entry(matching_tuples, platforms))
+ end
+ end
+
+ def entry_details(entry, detail_tuple, specs, platforms)
+ return unless options[:details]
+
+ name_tuple, spec = detail_tuple
+
+ spec = spec.fetch_spec(name_tuple)if spec.respond_to?(:fetch_spec)
+
+ entry << "\n"
+
+ spec_platforms entry, platforms
+ spec_authors entry, spec
+ spec_homepage entry, spec
+ spec_license entry, spec
+ spec_loaded_from entry, spec, specs
+ spec_summary entry, spec
+ end
+
+ def entry_versions(entry, name_tuples, platforms, specs)
+ return unless options[:versions]
+
+ list =
+ if platforms.empty? or options[:details]
+ name_tuples.map {|n| n.version }.uniq
+ else
+ platforms.sort.reverse.map do |version, pls|
+ out = version.to_s
+
+ if options[:domain] == :local
+ default = specs.any? do |s|
+ !s.is_a?(Gem::Source) && s.version == version && s.default_gem?
+ end
+ out = "default: #{out}" if default
+ end
+
+ if pls != [Gem::Platform::RUBY]
+ platform_list = [pls.delete(Gem::Platform::RUBY), *pls.sort].compact
+ out = platform_list.unshift(out).join(' ')
+ end
+
+ out
+ end
+ end
+
+ entry << " (#{list.join ', '})"
+ end
+
+ def make_entry(entry_tuples, platforms)
+ detail_tuple = entry_tuples.first
+
+ name_tuples, specs = entry_tuples.flatten.partition do |item|
+ Gem::NameTuple === item
+ end
+
+ entry = [name_tuples.first.name]
+
+ entry_versions(entry, name_tuples, platforms, specs)
+ entry_details(entry, detail_tuple, specs, platforms)
+
+ entry.join
+ end
+
+ def spec_authors(entry, spec)
+ authors = "Author#{spec.authors.length > 1 ? 's' : ''}: ".dup
+ authors << spec.authors.join(', ')
+ entry << format_text(authors, 68, 4)
+ end
+
+ def spec_homepage(entry, spec)
+ return if spec.homepage.nil? or spec.homepage.empty?
+
+ entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4)
+ end
+
+ def spec_license(entry, spec)
+ return if spec.license.nil? or spec.license.empty?
+
+ licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: ".dup
+ licenses << spec.licenses.join(', ')
+ entry << "\n" << format_text(licenses, 68, 4)
+ end
+
+ def spec_loaded_from(entry, spec, specs)
+ return unless spec.loaded_from
+
+ if specs.length == 1
+ default = spec.default_gem? ? ' (default)' : nil
+ entry << "\n" << " Installed at#{default}: #{spec.base_dir}"
+ else
+ label = 'Installed at'
+ specs.each do |s|
+ version = s.version.to_s
+ version << ', default' if s.default_gem?
+ entry << "\n" << " #{label} (#{version}): #{s.base_dir}"
+ label = ' ' * label.length
+ end
+ end
+ end
+
+ def spec_platforms(entry, platforms)
+ non_ruby = platforms.any? do |_, pls|
+ pls.any? {|pl| pl != Gem::Platform::RUBY }
+ end
+
+ return unless non_ruby
+
+ if platforms.length == 1
+ title = platforms.values.length == 1 ? 'Platform' : 'Platforms'
+ entry << " #{title}: #{platforms.values.sort.join(', ')}\n"
+ else
+ entry << " Platforms:\n"
+
+ sorted_platforms = platforms.sort_by {|version,| version }
+
+ sorted_platforms.each do |version, pls|
+ label = " #{version}: "
+ data = format_text pls.sort.join(', '), 68, label.length
+ data[0, label.length] = label
+ entry << data << "\n"
+ end
+ end
+ end
+
+ def spec_summary(entry, spec)
+ summary = truncate_text(spec.summary, "the summary for #{spec.full_name}")
+ entry << "\n\n" << format_text(summary, 68, 4)
+ end
+
+end
diff --git a/lib/rubygems/rdoc.rb b/lib/rubygems/rdoc.rb
index 4e16fbb86f..ac5e8f0822 100644
--- a/lib/rubygems/rdoc.rb
+++ b/lib/rubygems/rdoc.rb
@@ -1,17 +1,5 @@
# frozen_string_literal: true
-require 'rubygems'
-
-begin
- gem 'rdoc'
-rescue Gem::LoadError
- # swallow
-else
- # This will force any deps that 'rdoc' might have
- # (such as json) that are ambiguous to be activated, which
- # is important because we end up using Specification.reset
- # and we don't want the warning it pops out.
- Gem.finish_resolve
-end
+require_relative '../rubygems'
begin
require 'rdoc/rubygems_hook'
diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index 2ed619f1bc..de6f88f39a 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -1,52 +1,41 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/request'
-require 'rubygems/request/connection_pools'
-require 'rubygems/s3_uri_signer'
-require 'rubygems/uri_formatter'
-require 'rubygems/uri_parsing'
-require 'rubygems/user_interaction'
-require 'resolv'
-require 'rubygems/deprecate'
+require_relative '../rubygems'
+require_relative 'request'
+require_relative 'request/connection_pools'
+require_relative 's3_uri_signer'
+require_relative 'uri_formatter'
+require_relative 'uri'
+require_relative 'user_interaction'
##
# RemoteFetcher handles the details of fetching gems and gem information from
# a remote source.
class Gem::RemoteFetcher
-
include Gem::UserInteraction
- extend Gem::Deprecate
-
- include Gem::UriParsing
##
# A FetchError exception wraps up the various possible IO and HTTP failures
# that could happen while downloading from the internet.
class FetchError < Gem::Exception
-
- include Gem::UriParsing
-
##
# The URI which was being accessed when the exception happened.
- attr_accessor :uri
+ attr_accessor :uri, :original_uri
def initialize(message, uri)
- super message
+ uri = Gem::Uri.new(uri)
- uri = parse_uri(uri)
+ super uri.redact_credentials_from(message)
- uri.password = 'REDACTED' if uri.respond_to?(:password) && uri.password
-
- @uri = uri.to_s
+ @original_uri = uri.to_s
+ @uri = uri.redacted.to_s
end
def to_s # :nodoc:
"#{super} (#{uri})"
end
-
end
##
@@ -55,6 +44,7 @@ class Gem::RemoteFetcher
class UnknownHostError < FetchError
end
+ deprecate_constant(:UnknownHostError)
@fetcher = nil
@@ -82,16 +72,16 @@ class Gem::RemoteFetcher
# fetching the gem.
def initialize(proxy=nil, dns=nil, headers={})
+ require_relative 'core_ext/tcpsocket_init' if Gem.configuration.ipv4_fallback_enabled
require 'net/http'
require 'stringio'
- require 'time'
require 'uri'
Socket.do_not_reverse_lookup = true
@proxy = proxy
@pools = {}
- @pool_lock = Mutex.new
+ @pool_lock = Thread::Mutex.new
@cert_files = Gem::Request.get_cert_files
@headers = headers
@@ -109,7 +99,7 @@ class Gem::RemoteFetcher
return if found.empty?
- spec, source = found.max_by { |(s,_)| s.version }
+ spec, source = found.max_by {|(s,_)| s.version }
download spec, source.uri
end
@@ -120,11 +110,12 @@ class Gem::RemoteFetcher
# always replaced.
def download(spec, source_uri, install_dir = Gem.dir)
+ install_cache_dir = File.join install_dir, "cache"
cache_dir =
- if Dir.pwd == install_dir # see fetch_command
+ if Dir.pwd == install_dir # see fetch_command
install_dir
- elsif File.writable? install_dir
- File.join install_dir, "cache"
+ elsif File.writable?(install_cache_dir) || (File.writable?(install_dir) && (not File.exist?(install_cache_dir)))
+ install_cache_dir
else
File.join Gem.user_dir, "cache"
end
@@ -132,9 +123,10 @@ class Gem::RemoteFetcher
gem_file_name = File.basename spec.cache_file
local_gem_path = File.join cache_dir, gem_file_name
+ require "fileutils"
FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
- source_uri = parse_uri(source_uri)
+ source_uri = Gem::Uri.new(source_uri)
scheme = source_uri.scheme
@@ -215,12 +207,12 @@ class Gem::RemoteFetcher
def fetch_http(uri, last_modified = nil, head = false, depth = 0)
fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get
response = request uri, fetch_type, last_modified do |req|
- headers.each { |k,v| req.add_field(k,v) }
+ headers.each {|k,v| req.add_field(k,v) }
end
case response
when Net::HTTPOK, Net::HTTPNotModified then
- response.uri = uri if response.respond_to? :uri
+ response.uri = uri
head ? response : response.body
when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther,
Net::HTTPTemporaryRedirect then
@@ -229,7 +221,7 @@ class Gem::RemoteFetcher
unless location = response['Location']
raise FetchError.new("redirecting but no redirect location was given", uri)
end
- location = parse_uri location
+ location = Gem::Uri.new location
if https?(uri) && !https?(location)
raise FetchError.new("redirecting to non-https resource: #{location}", uri)
@@ -247,7 +239,7 @@ class Gem::RemoteFetcher
# Downloads +uri+ and returns it as a String.
def fetch_path(uri, mtime = nil, head = false)
- uri = parse_uri uri
+ uri = Gem::Uri.new uri
unless uri.scheme
raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}"
@@ -255,7 +247,7 @@ class Gem::RemoteFetcher
data = send "fetch_#{uri.scheme}", uri, mtime, head
- if data and !head and uri.to_s =~ /\.gz$/
+ if data and !head and uri.to_s.end_with?(".gz")
begin
data = Gem::Util.gunzip data
rescue Zlib::GzipFile::Error
@@ -264,15 +256,9 @@ class Gem::RemoteFetcher
end
data
- rescue Timeout::Error
- raise UnknownHostError.new('timed out', uri)
- rescue IOError, SocketError, SystemCallError,
- *(OpenSSL::SSL::SSLError if defined?(OpenSSL)) => e
- if e.message =~ /getaddrinfo/
- raise UnknownHostError.new('no such name', uri)
- else
- raise FetchError.new("#{e.class}: #{e}", uri)
- end
+ rescue Timeout::Error, IOError, SocketError, SystemCallError,
+ *(OpenSSL::SSL::SSLError if Gem::HAVE_OPENSSL) => e
+ raise FetchError.new("#{e.class}: #{e}", uri)
end
def fetch_s3(uri, mtime = nil, head = false)
@@ -310,17 +296,6 @@ class Gem::RemoteFetcher
end
##
- # Returns the size of +uri+ in bytes.
-
- def fetch_size(uri)
- response = fetch_path(uri, nil, true)
-
- response['content-length'].to_i
- end
-
- deprecate :fetch_size, :none, 2019, 12
-
- ##
# Performs a Net::HTTP request of type +request_class+ on +uri+ returning
# a Net::HTTP response object. request maintains a table of persistent
# connections to reduce connect overhead.
@@ -341,7 +316,7 @@ class Gem::RemoteFetcher
end
def close_all
- @pools.each_value {|pool| pool.close_all}
+ @pools.each_value {|pool| pool.close_all }
end
private
@@ -355,5 +330,4 @@ class Gem::RemoteFetcher
@pools[proxy] ||= Gem::Request::ConnectionPools.new proxy, @cert_files
end
end
-
end
diff --git a/lib/rubygems/request.rb b/lib/rubygems/request.rb
index b5a14ec34d..d6100c914b 100644
--- a/lib/rubygems/request.rb
+++ b/lib/rubygems/request.rb
@@ -1,10 +1,8 @@
# frozen_string_literal: true
require 'net/http'
-require 'time'
-require 'rubygems/user_interaction'
+require_relative 'user_interaction'
class Gem::Request
-
extend Gem::UserInteraction
include Gem::UserInteraction
@@ -46,7 +44,8 @@ class Gem::Request
end
def self.configure_connection_for_https(connection, cert_files)
- require 'net/https'
+ raise Gem::Exception.new('OpenSSL is not available. Install OpenSSL and rebuild Ruby (preferred) or use non-HTTPS sources') unless Gem::HAVE_OPENSSL
+
connection.use_ssl = true
connection.verify_mode =
Gem.configuration.ssl_verify_mode || OpenSSL::SSL::VERIFY_PEER
@@ -78,12 +77,6 @@ class Gem::Request
end
connection
- rescue LoadError => e
- raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
- e.message =~ / -- openssl$/
-
- raise Gem::Exception.new(
- 'Unable to require openssl, install OpenSSL and rebuild Ruby (preferred) or use non-HTTPS sources')
end
def self.verify_certificate(store_context)
@@ -103,8 +96,10 @@ class Gem::Request
return unless cert
case error_number
when OpenSSL::X509::V_ERR_CERT_HAS_EXPIRED then
+ require 'time'
"Certificate #{cert.subject} expired at #{cert.not_after.iso8601}"
when OpenSSL::X509::V_ERR_CERT_NOT_YET_VALID then
+ require 'time'
"Certificate #{cert.subject} not valid until #{cert.not_before.iso8601}"
when OpenSSL::X509::V_ERR_CERT_REJECTED then
"Certificate #{cert.subject} is rejected"
@@ -132,7 +127,7 @@ class Gem::Request
def connection_for(uri)
@connection_pool.checkout
- rescue defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : Errno::EHOSTDOWN,
+ rescue Gem::HAVE_OPENSSL ? OpenSSL::SSL::SSLError : Errno::EHOSTDOWN,
Errno::EHOSTDOWN => e
raise Gem::RemoteFetcher::FetchError.new(e.message, uri)
end
@@ -150,6 +145,7 @@ class Gem::Request
request.add_field 'Keep-Alive', '30'
if @last_modified
+ require 'time'
request.add_field 'If-Modified-Since', @last_modified.httpdate
end
@@ -197,7 +193,7 @@ class Gem::Request
begin
@requests[connection.object_id] += 1
- verbose "#{request.method} #{@uri}"
+ verbose "#{request.method} #{Gem::Uri.new(@uri).redacted}"
file_name = File.basename(@uri.path)
# perform download progress reporter only for gems
@@ -291,9 +287,8 @@ class Gem::Request
ua
end
-
end
-require 'rubygems/request/http_pool'
-require 'rubygems/request/https_pool'
-require 'rubygems/request/connection_pools'
+require_relative 'request/http_pool'
+require_relative 'request/https_pool'
+require_relative 'request/connection_pools'
diff --git a/lib/rubygems/request/connection_pools.rb b/lib/rubygems/request/connection_pools.rb
index 9444239b2c..a4c2929b38 100644
--- a/lib/rubygems/request/connection_pools.rb
+++ b/lib/rubygems/request/connection_pools.rb
@@ -1,20 +1,17 @@
# frozen_string_literal: true
class Gem::Request::ConnectionPools # :nodoc:
-
@client = Net::HTTP
class << self
-
attr_accessor :client
-
end
def initialize(proxy_uri, cert_files)
@proxy_uri = proxy_uri
@cert_files = cert_files
@pools = {}
- @pool_mutex = Mutex.new
+ @pool_mutex = Thread::Mutex.new
end
def pool_for(uri)
@@ -31,7 +28,7 @@ class Gem::Request::ConnectionPools # :nodoc:
end
def close_all
- @pools.each_value {|pool| pool.close_all}
+ @pools.each_value {|pool| pool.close_all }
end
private
@@ -95,5 +92,4 @@ class Gem::Request::ConnectionPools # :nodoc:
net_http_args
end
end
-
end
diff --git a/lib/rubygems/request/http_pool.rb b/lib/rubygems/request/http_pool.rb
index 058094a209..f028516db8 100644
--- a/lib/rubygems/request/http_pool.rb
+++ b/lib/rubygems/request/http_pool.rb
@@ -6,14 +6,13 @@
# use it.
class Gem::Request::HTTPPool # :nodoc:
-
attr_reader :cert_files, :proxy_uri
def initialize(http_args, cert_files, proxy_uri)
@http_args = http_args
@cert_files = cert_files
@proxy_uri = proxy_uri
- @queue = SizedQueue.new 1
+ @queue = Thread::SizedQueue.new 1
@queue << nil
end
@@ -44,5 +43,4 @@ class Gem::Request::HTTPPool # :nodoc:
connection.start
connection
end
-
end
diff --git a/lib/rubygems/request/https_pool.rb b/lib/rubygems/request/https_pool.rb
index 1236079b7d..50f42d9e0d 100644
--- a/lib/rubygems/request/https_pool.rb
+++ b/lib/rubygems/request/https_pool.rb
@@ -1,11 +1,9 @@
# frozen_string_literal: true
class Gem::Request::HTTPSPool < Gem::Request::HTTPPool # :nodoc:
-
private
def setup_connection(connection)
Gem::Request.configure_connection_for_https(connection, @cert_files)
super
end
-
end
diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb
index d6fb41f514..01b01599a8 100644
--- a/lib/rubygems/request_set.rb
+++ b/lib/rubygems/request_set.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'tsort'
+require_relative 'tsort'
##
# A RequestSet groups a request to activate a set of dependencies.
@@ -15,8 +15,7 @@ require 'tsort'
# #=> ["nokogiri-1.6.0", "mini_portile-0.5.1", "pg-0.17.0"]
class Gem::RequestSet
-
- include TSort
+ include Gem::TSort
##
# Array of gems to install even if already installed
@@ -152,7 +151,7 @@ class Gem::RequestSet
@prerelease = options[:prerelease]
requests = []
- download_queue = Queue.new
+ download_queue = Thread::Queue.new
# Create a thread-safe list of gems to download
sorted_requests.each do |req|
@@ -184,7 +183,7 @@ class Gem::RequestSet
if req.installed?
req.spec.spec.build_extensions
- if @always_install.none? { |spec| spec == req.spec.spec }
+ if @always_install.none? {|spec| spec == req.spec.spec }
yield req, nil if block_given?
next
end
@@ -196,19 +195,8 @@ class Gem::RequestSet
yield req, installer if block_given?
end
rescue Gem::RuntimeRequirementNotMetError => e
- recent_match = req.spec.set.find_all(req.request).sort_by(&:version).reverse_each.find do |s|
- s = s.spec
- s.required_ruby_version.satisfied_by?(Gem.ruby_version) &&
- s.required_rubygems_version.satisfied_by?(Gem.rubygems_version) &&
- Gem::Platform.installable?(s)
- end
- if recent_match
- suggestion = "The last version of #{req.request} to support your Ruby & RubyGems was #{recent_match.version}. Try installing it with `gem install #{recent_match.name} -v #{recent_match.version}`"
- suggestion += " and then running the current command again" unless @always_install.include?(req.spec.spec)
- else
- suggestion = "There are no versions of #{req.request} compatible with your Ruby & RubyGems"
- suggestion += ". Maybe try installing an older version of the gem you're looking for?" unless @always_install.include?(req.spec.spec)
- end
+ suggestion = "There are no versions of #{req.request} compatible with your Ruby & RubyGems"
+ suggestion += ". Maybe try installing an older version of the gem you're looking for?" unless @always_install.include?(req.spec.spec)
e.suggestion = suggestion
raise
end
@@ -269,7 +257,7 @@ class Gem::RequestSet
gem_home, ENV['GEM_HOME'] = ENV['GEM_HOME'], dir
existing = force ? [] : specs_in(dir)
- existing.delete_if { |s| @always_install.include? s }
+ existing.delete_if {|s| @always_install.include? s }
dir = File.expand_path dir
@@ -283,7 +271,7 @@ class Gem::RequestSet
sorted_requests.each do |request|
spec = request.spec
- if existing.find { |s| s.full_name == spec.full_name }
+ if existing.find {|s| s.full_name == spec.full_name }
yield request, nil if block_given?
next
end
@@ -315,7 +303,7 @@ class Gem::RequestSet
end
end
- require "rubygems/dependency_installer"
+ require_relative "dependency_installer"
inst = Gem::DependencyInstaller.new options
inst.installed_gems.replace specs
@@ -386,7 +374,7 @@ class Gem::RequestSet
q.text 'sets:'
q.breakable
- q.pp @sets.map { |set| set.class }
+ q.pp @sets.map {|set| set.class }
end
end
@@ -440,7 +428,7 @@ class Gem::RequestSet
end
def specs
- @specs ||= @requests.map { |r| r.full_spec }
+ @specs ||= @requests.map {|r| r.full_spec }
end
def specs_in(dir)
@@ -471,9 +459,8 @@ class Gem::RequestSet
yield match
end
end
-
end
-require 'rubygems/request_set/gem_dependency_api'
-require 'rubygems/request_set/lockfile'
-require 'rubygems/request_set/lockfile/tokenizer'
+require_relative 'request_set/gem_dependency_api'
+require_relative 'request_set/lockfile'
+require_relative 'request_set/lockfile/tokenizer'
diff --git a/lib/rubygems/request_set/gem_dependency_api.rb b/lib/rubygems/request_set/gem_dependency_api.rb
index ef3f302ea8..7188b07346 100644
--- a/lib/rubygems/request_set/gem_dependency_api.rb
+++ b/lib/rubygems/request_set/gem_dependency_api.rb
@@ -31,7 +31,6 @@
# See `gem help install` and `gem help gem_dependencies` for further details.
class Gem::RequestSet::GemDependencyAPI
-
ENGINE_MAP = { # :nodoc:
:jruby => %w[jruby],
:jruby_18 => %w[jruby],
@@ -89,7 +88,7 @@ class Gem::RequestSet::GemDependencyAPI
:truffleruby => Gem::Platform::RUBY,
:x64_mingw => x64_mingw,
:x64_mingw_20 => x64_mingw,
- :x64_mingw_21 => x64_mingw
+ :x64_mingw_21 => x64_mingw,
}.freeze
gt_eq_0 = Gem::Requirement.new '>= 0'
@@ -206,7 +205,7 @@ class Gem::RequestSet::GemDependencyAPI
@git_set = @set.git_set
@git_sources = {}
@installing = false
- @requires = Hash.new { |h, name| h[name] = [] }
+ @requires = Hash.new {|h, name| h[name] = [] }
@vendor_set = @set.vendor_set
@source_set = @set.source_set
@gem_sources = {}
@@ -380,7 +379,7 @@ class Gem::RequestSet::GemDependencyAPI
Gem::Requirement.create requirements
end
- return unless gem_platforms options
+ return unless gem_platforms name, options
groups = gem_group name, options
@@ -533,7 +532,7 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
# Handles the platforms: option from +options+. Returns true if the
# platform matches the current platform.
- def gem_platforms(options) # :nodoc:
+ def gem_platforms(name, options) # :nodoc:
platform_names = Array(options.delete :platform)
platform_names.concat Array(options.delete :platforms)
platform_names.concat @current_platforms if @current_platforms
@@ -544,7 +543,7 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
raise ArgumentError, "unknown platform #{platform_name.inspect}" unless
platform = PLATFORM_MAP[platform_name]
- next false unless Gem::Platform.match platform
+ next false unless Gem::Platform.match_gem? platform, name
if engines = ENGINE_MAP[platform_name]
next false unless engines.include? Gem.ruby_engine
@@ -842,5 +841,4 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
Gem.sources << url
end
-
end
diff --git a/lib/rubygems/request_set/lockfile.rb b/lib/rubygems/request_set/lockfile.rb
index 5423f2c14f..bec29ef1b9 100644
--- a/lib/rubygems/request_set/lockfile.rb
+++ b/lib/rubygems/request_set/lockfile.rb
@@ -5,12 +5,10 @@
# constructed.
class Gem::RequestSet::Lockfile
-
##
# Raised when a lockfile cannot be parsed
class ParseError < Gem::Exception
-
##
# The column where the error was encountered
@@ -36,7 +34,6 @@ class Gem::RequestSet::Lockfile
@path = path
super "#{message} (at line #{line} column #{column})"
end
-
end
##
@@ -89,7 +86,7 @@ class Gem::RequestSet::Lockfile
def add_DEPENDENCIES(out) # :nodoc:
out << "DEPENDENCIES"
- out.concat @dependencies.sort_by { |name,| name }.map { |name, requirement|
+ out.concat @dependencies.sort_by {|name,| name }.map {|name, requirement|
" #{name}#{requirement.for_lockfile}"
}
@@ -103,12 +100,12 @@ class Gem::RequestSet::Lockfile
request.spec.source.uri
end
- source_groups.sort_by { |group,| group.to_s }.map do |group, requests|
+ source_groups.sort_by {|group,| group.to_s }.map do |group, requests|
out << "GEM"
out << " remote: #{group}"
out << " specs:"
- requests.sort_by { |request| request.name }.each do |request|
+ requests.sort_by {|request| request.name }.each do |request|
next if request.spec.name == 'bundler'
platform = "-#{request.spec.platform}" unless
Gem::Platform::RUBY == request.spec.platform
@@ -140,10 +137,10 @@ class Gem::RequestSet::Lockfile
out << " revision: #{revision}"
out << " specs:"
- requests.sort_by { |request| request.name }.each do |request|
+ requests.sort_by {|request| request.name }.each do |request|
out << " #{request.name} (#{request.version})"
- dependencies = request.spec.dependencies.sort_by { |dep| dep.name }
+ dependencies = request.spec.dependencies.sort_by {|dep| dep.name }
dependencies.each do |dep|
out << " #{dep.name}#{dep.requirement.for_lockfile}"
end
@@ -185,9 +182,9 @@ class Gem::RequestSet::Lockfile
def add_PLATFORMS(out) # :nodoc:
out << "PLATFORMS"
- platforms = requests.map { |request| request.spec.platform }.uniq
+ platforms = requests.map {|request| request.spec.platform }.uniq
- platforms = platforms.sort_by { |platform| platform.to_s }
+ platforms = platforms.sort_by {|platform| platform.to_s }
platforms.each do |platform|
out << " #{platform}"
@@ -197,7 +194,7 @@ class Gem::RequestSet::Lockfile
end
def spec_groups
- requests.group_by { |request| request.spec.class }
+ requests.group_by {|request| request.spec.class }
end
##
@@ -237,7 +234,6 @@ class Gem::RequestSet::Lockfile
def requests
@set.sorted_requests
end
-
end
-require 'rubygems/request_set/lockfile/tokenizer'
+require_relative 'lockfile/tokenizer'
diff --git a/lib/rubygems/request_set/lockfile/parser.rb b/lib/rubygems/request_set/lockfile/parser.rb
index 1e9d2b12de..8c12b435af 100644
--- a/lib/rubygems/request_set/lockfile/parser.rb
+++ b/lib/rubygems/request_set/lockfile/parser.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
class Gem::RequestSet::Lockfile::Parser
-
###
# Parses lockfiles
@@ -341,5 +340,4 @@ class Gem::RequestSet::Lockfile::Parser
def unget(token) # :nodoc:
@tokens.unshift token
end
-
end
diff --git a/lib/rubygems/request_set/lockfile/tokenizer.rb b/lib/rubygems/request_set/lockfile/tokenizer.rb
index 97396ec199..cb8030c143 100644
--- a/lib/rubygems/request_set/lockfile/tokenizer.rb
+++ b/lib/rubygems/request_set/lockfile/tokenizer.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/request_set/lockfile/parser'
+require_relative 'parser'
class Gem::RequestSet::Lockfile::Tokenizer
-
Token = Struct.new :type, :value, :column, :line
EOF = Token.new :EOF
@@ -23,7 +22,7 @@ class Gem::RequestSet::Lockfile::Tokenizer
end
def to_a
- @tokens.map { |token| [token.type, token.value, token.column, token.line] }
+ @tokens.map {|token| [token.type, token.value, token.column, token.line] }
end
def skip(type)
@@ -110,5 +109,4 @@ class Gem::RequestSet::Lockfile::Tokenizer
@tokens
end
-
end
diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb
index 1e17fc2dc2..d2e28fab5b 100644
--- a/lib/rubygems/requirement.rb
+++ b/lib/rubygems/requirement.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require "rubygems/version"
-require "rubygems/deprecate"
+require_relative "deprecate"
##
# A Requirement is a set of one or more version restrictions. It supports a
@@ -10,20 +9,19 @@ require "rubygems/deprecate"
# together in RubyGems.
class Gem::Requirement
-
OPS = { #:nodoc:
- "=" => lambda { |v, r| v == r },
- "!=" => lambda { |v, r| v != r },
- ">" => lambda { |v, r| v > r },
- "<" => lambda { |v, r| v < r },
- ">=" => lambda { |v, r| v >= r },
- "<=" => lambda { |v, r| v <= r },
- "~>" => lambda { |v, r| v >= r && v.release < r.bump }
+ "=" => lambda {|v, r| v == r },
+ "!=" => lambda {|v, r| v != r },
+ ">" => lambda {|v, r| v > r },
+ "<" => lambda {|v, r| v < r },
+ ">=" => lambda {|v, r| v >= r },
+ "<=" => lambda {|v, r| v <= r },
+ "~>" => lambda {|v, r| v >= r && v.release < r.bump },
}.freeze
SOURCE_SET_REQUIREMENT = Struct.new(:for_lockfile).new "!" # :nodoc:
- quoted = OPS.keys.map { |k| Regexp.quote k }.join "|"
+ quoted = OPS.keys.map {|k| Regexp.quote k }.join "|"
PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*".freeze # :nodoc:
##
@@ -113,7 +111,7 @@ class Gem::Requirement
elsif $1 == ">=" && $2 == "0.a"
DefaultPrereleaseRequirement
else
- [$1 || "=", Gem::Version.new($2)]
+ [-($1 || "="), Gem::Version.new($2)]
end
end
@@ -137,7 +135,7 @@ class Gem::Requirement
if requirements.empty?
@requirements = [DefaultRequirement]
else
- @requirements = requirements.map! { |r| self.class.parse r }
+ @requirements = requirements.map! {|r| self.class.parse r }
end
end
@@ -148,7 +146,7 @@ class Gem::Requirement
new = new.flatten
new.compact!
new.uniq!
- new = new.map { |r| self.class.parse r }
+ new = new.map {|r| self.class.parse r }
@requirements.concat new
end
@@ -188,32 +186,27 @@ class Gem::Requirement
end
def as_list # :nodoc:
- requirements.map { |op, version| "#{op} #{version}" }
+ requirements.map {|op, version| "#{op} #{version}" }
end
def hash # :nodoc:
- requirements.sort.hash
+ requirements.map {|r| r.first == "~>" ? [r[0], r[1].to_s] : r }.sort.hash
end
def marshal_dump # :nodoc:
- fix_syck_default_key_in_requirements
-
[@requirements]
end
def marshal_load(array) # :nodoc:
@requirements = array[0]
- fix_syck_default_key_in_requirements
+ raise TypeError, "wrong @requirements" unless Array === @requirements
end
def yaml_initialize(tag, vals) # :nodoc:
vals.each do |ivar, val|
instance_variable_set "@#{ivar}", val
end
-
- Gem.load_yaml
- fix_syck_default_key_in_requirements
end
def init_with(coder) # :nodoc:
@@ -233,7 +226,7 @@ class Gem::Requirement
# are prereleases
def prerelease?
- requirements.any? { |r| r.last.prerelease? }
+ requirements.any? {|r| r.last.prerelease? }
end
def pretty_print(q) # :nodoc:
@@ -248,8 +241,7 @@ class Gem::Requirement
def satisfied_by?(version)
raise ArgumentError, "Need a Gem::Version: #{version.inspect}" unless
Gem::Version === version
- # #28965: syck has a bug with unquoted '=' YAML.loading as YAML::DefaultKey
- requirements.all? { |op, rv| (OPS[op] || OPS["="]).call version, rv }
+ requirements.all? {|op, rv| OPS[op].call version, rv }
end
alias :=== :satisfied_by?
@@ -272,7 +264,7 @@ class Gem::Requirement
return unless Gem::Requirement === other
# An == check is always necessary
- return false unless requirements == other.requirements
+ return false unless _sorted_requirements == other._sorted_requirements
# An == check is sufficient unless any requirements use ~>
return true unless _tilde_requirements.any?
@@ -284,30 +276,18 @@ class Gem::Requirement
protected
- def _tilde_requirements
- requirements.select { |r| r.first == "~>" }
+ def _sorted_requirements
+ @_sorted_requirements ||= requirements.sort_by(&:to_s)
end
- private
-
- def fix_syck_default_key_in_requirements # :nodoc:
- Gem.load_yaml
-
- # Fixup the Syck DefaultKey bug
- @requirements.each do |r|
- if r[0].kind_of? Gem::SyckDefaultKey
- r[0] = "="
- end
- end
+ def _tilde_requirements
+ @_tilde_requirements ||= _sorted_requirements.select {|r| r.first == "~>" }
end
-
end
class Gem::Version
-
# This is needed for compatibility with older yaml
# gemspecs.
Requirement = Gem::Requirement # :nodoc:
-
end
diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb
index ea9687bdbf..51a11fed47 100644
--- a/lib/rubygems/resolver.rb
+++ b/lib/rubygems/resolver.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/dependency'
-require 'rubygems/exceptions'
-require 'rubygems/util'
-require 'rubygems/util/list'
+require_relative 'dependency'
+require_relative 'exceptions'
+require_relative 'util/list'
##
# Given a set of Gem::Dependency objects as +needed+ and a way to query the
@@ -11,8 +10,7 @@ require 'rubygems/util/list'
# all the requirements.
class Gem::Resolver
-
- require 'rubygems/resolver/molinillo'
+ require_relative 'resolver/molinillo'
##
# If the DEBUG_RESOLVER environment variable is set then debugging mode is
@@ -116,7 +114,7 @@ class Gem::Resolver
def explain(stage, *data) # :nodoc:
return unless DEBUG_RESOLVER
- d = data.map { |x| x.pretty_inspect }.join(", ")
+ d = data.map {|x| x.pretty_inspect }.join(", ")
$stderr.printf "%10s %s\n", stage.to_s.upcase, d
end
@@ -189,7 +187,7 @@ class Gem::Resolver
def resolve
locking_dg = Molinillo::DependencyGraph.new
- Molinillo::Resolver.new(self, self).resolve(@needed.map { |d| DependencyRequest.new d, nil }, locking_dg).tsort.map(&:payload).compact
+ Molinillo::Resolver.new(self, self).resolve(@needed.map {|d| DependencyRequest.new d, nil }, locking_dg).tsort.map(&:payload).compact
rescue Molinillo::VersionConflict => e
conflict = e.conflicts.values.first
raise Gem::DependencyResolutionError, Conflict.new(conflict.requirement_trees.first.first, conflict.existing, conflict.requirement)
@@ -206,7 +204,7 @@ class Gem::Resolver
if (skip_dep_gems = skip_gems[dependency.name]) && !skip_dep_gems.empty?
matching = all.select do |api_spec|
- skip_dep_gems.any? { |s| api_spec.version == s.version }
+ skip_dep_gems.any? {|s| api_spec.version == s.version }
end
all = matching unless matching.empty?
@@ -235,7 +233,7 @@ class Gem::Resolver
raise exc
end
- groups = Hash.new { |hash, key| hash[key] = [] }
+ groups = Hash.new {|hash, key| hash[key] = [] }
# create groups & sources in the same loop
sources = possibles.map do |spec|
@@ -248,9 +246,9 @@ class Gem::Resolver
sources.each do |source|
groups[source].
- sort_by { |spec| [spec.version, Gem::Platform.local =~ spec.platform ? 1 : 0] }.
- map { |spec| ActivationRequest.new spec, dependency }.
- each { |activation_request| activation_requests << activation_request }
+ sort_by {|spec| [spec.version, Gem::Platform.local =~ spec.platform ? 1 : 0] }.
+ map {|spec| ActivationRequest.new spec, dependency }.
+ each {|activation_request| activation_requests << activation_request }
end
activation_requests
@@ -263,7 +261,12 @@ class Gem::Resolver
end
def requirement_satisfied_by?(requirement, activated, spec)
- requirement.matches_spec? spec
+ matches_spec = requirement.matches_spec? spec
+ return matches_spec if @soft_missing
+
+ matches_spec &&
+ spec.spec.required_ruby_version.satisfied_by?(Gem.ruby_version) &&
+ spec.spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version)
end
def name_for(dependency)
@@ -283,7 +286,7 @@ class Gem::Resolver
amount_constrained(dependency),
conflicts[name] ? 0 : 1,
activated.vertex_named(name).payload ? 0 : search_for(dependency).count,
- i # for stable sort
+ i, # for stable sort
]
end
end
@@ -313,33 +316,32 @@ class Gem::Resolver
end
end
private :amount_constrained
-
end
-require 'rubygems/resolver/activation_request'
-require 'rubygems/resolver/conflict'
-require 'rubygems/resolver/dependency_request'
-require 'rubygems/resolver/requirement_list'
-require 'rubygems/resolver/stats'
-
-require 'rubygems/resolver/set'
-require 'rubygems/resolver/api_set'
-require 'rubygems/resolver/composed_set'
-require 'rubygems/resolver/best_set'
-require 'rubygems/resolver/current_set'
-require 'rubygems/resolver/git_set'
-require 'rubygems/resolver/index_set'
-require 'rubygems/resolver/installer_set'
-require 'rubygems/resolver/lock_set'
-require 'rubygems/resolver/vendor_set'
-require 'rubygems/resolver/source_set'
-
-require 'rubygems/resolver/specification'
-require 'rubygems/resolver/spec_specification'
-require 'rubygems/resolver/api_specification'
-require 'rubygems/resolver/git_specification'
-require 'rubygems/resolver/index_specification'
-require 'rubygems/resolver/installed_specification'
-require 'rubygems/resolver/local_specification'
-require 'rubygems/resolver/lock_specification'
-require 'rubygems/resolver/vendor_specification'
+require_relative 'resolver/activation_request'
+require_relative 'resolver/conflict'
+require_relative 'resolver/dependency_request'
+require_relative 'resolver/requirement_list'
+require_relative 'resolver/stats'
+
+require_relative 'resolver/set'
+require_relative 'resolver/api_set'
+require_relative 'resolver/composed_set'
+require_relative 'resolver/best_set'
+require_relative 'resolver/current_set'
+require_relative 'resolver/git_set'
+require_relative 'resolver/index_set'
+require_relative 'resolver/installer_set'
+require_relative 'resolver/lock_set'
+require_relative 'resolver/vendor_set'
+require_relative 'resolver/source_set'
+
+require_relative 'resolver/specification'
+require_relative 'resolver/spec_specification'
+require_relative 'resolver/api_specification'
+require_relative 'resolver/git_specification'
+require_relative 'resolver/index_specification'
+require_relative 'resolver/installed_specification'
+require_relative 'resolver/local_specification'
+require_relative 'resolver/lock_specification'
+require_relative 'resolver/vendor_specification'
diff --git a/lib/rubygems/resolver/activation_request.rb b/lib/rubygems/resolver/activation_request.rb
index 2a8d6032f8..ae35681db9 100644
--- a/lib/rubygems/resolver/activation_request.rb
+++ b/lib/rubygems/resolver/activation_request.rb
@@ -4,7 +4,6 @@
# dependency that was used to introduce this activation.
class Gem::Resolver::ActivationRequest
-
##
# The parent request for this activation request.
@@ -29,12 +28,20 @@ class Gem::Resolver::ActivationRequest
when Gem::Specification
@spec == other
when Gem::Resolver::ActivationRequest
- @spec == other.spec && @request == other.request
+ @spec == other.spec
else
false
end
end
+ def eql?(other)
+ self == other
+ end
+
+ def hash
+ @spec.hash
+ end
+
##
# Is this activation request for a development dependency?
@@ -152,5 +159,4 @@ class Gem::Resolver::ActivationRequest
def name_tuple
@name_tuple ||= Gem::NameTuple.new(name, version, platform)
end
-
end
diff --git a/lib/rubygems/resolver/api_set.rb b/lib/rubygems/resolver/api_set.rb
index 135f1b08aa..21c9b8920c 100644
--- a/lib/rubygems/resolver/api_set.rb
+++ b/lib/rubygems/resolver/api_set.rb
@@ -4,6 +4,7 @@
# Returns instances of APISpecification.
class Gem::Resolver::APISet < Gem::Resolver::Set
+ autoload :GemParser, File.expand_path("api_set/gem_parser", __dir__)
##
# The URI for the dependency API this APISet uses.
@@ -25,15 +26,15 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
# API URL +dep_uri+ which is described at
# https://guides.rubygems.org/rubygems-org-api
- def initialize(dep_uri = 'https://rubygems.org/api/v1/dependencies')
+ def initialize(dep_uri = 'https://index.rubygems.org/info/')
super()
- dep_uri = URI dep_uri unless URI === dep_uri # for ruby 1.8
+ dep_uri = URI dep_uri unless URI === dep_uri
@dep_uri = dep_uri
- @uri = dep_uri + '../..'
+ @uri = dep_uri + '..'
- @data = Hash.new { |h,k| h[k] = [] }
+ @data = Hash.new {|h,k| h[k] = [] }
@source = Gem::Source.new @uri
@to_fetch = []
@@ -53,7 +54,7 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
end
versions(req.name).each do |ver|
- if req.dependency.match? req.name, ver[:number]
+ if req.dependency.match? req.name, ver[:number], @prerelease
res << Gem::Resolver::APISpecification.new(self, ver)
end
end
@@ -67,7 +68,7 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
def prefetch(reqs)
return unless @remote
- names = reqs.map { |r| r.dependency.name }
+ names = reqs.map {|r| r.dependency.name }
needed = names - @data.keys - @to_fetch
@to_fetch += needed
@@ -76,20 +77,8 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
def prefetch_now # :nodoc:
needed, @to_fetch = @to_fetch, []
- uri = @dep_uri + "?gems=#{needed.sort.join ','}"
- str = Gem::RemoteFetcher.fetcher.fetch_path uri
-
- loaded = []
-
- Marshal.load(str).each do |ver|
- name = ver[:name]
-
- @data[name] << ver
- loaded << name
- end
-
- (needed - loaded).each do |missing|
- @data[missing] = []
+ needed.sort.each do |name|
+ versions(name)
end
end
@@ -112,14 +101,32 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
return @data[name]
end
- uri = @dep_uri + "?gems=#{name}"
+ uri = @dep_uri + name
str = Gem::RemoteFetcher.fetcher.fetch_path uri
- Marshal.load(str).each do |ver|
- @data[ver[:name]] << ver
+ lines(str).each do |ver|
+ number, platform, dependencies, requirements = parse_gem(ver)
+
+ platform ||= "ruby"
+ dependencies = dependencies.map {|dep_name, reqs| [dep_name, reqs.join(", ")] }
+ requirements = requirements.map {|req_name, reqs| [req_name.to_sym, reqs] }.to_h
+
+ @data[name] << { name: name, number: number, platform: platform, dependencies: dependencies, requirements: requirements }
end
@data[name]
end
+ private
+
+ def lines(str)
+ lines = str.split("\n")
+ header = lines.index("---")
+ header ? lines[header + 1..-1] : lines
+ end
+
+ def parse_gem(string)
+ @gem_parser ||= GemParser.new
+ @gem_parser.parse(string)
+ end
end
diff --git a/lib/rubygems/resolver/api_set/gem_parser.rb b/lib/rubygems/resolver/api_set/gem_parser.rb
new file mode 100644
index 0000000000..685c39558d
--- /dev/null
+++ b/lib/rubygems/resolver/api_set/gem_parser.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class Gem::Resolver::APISet::GemParser
+ def parse(line)
+ version_and_platform, rest = line.split(" ", 2)
+ version, platform = version_and_platform.split("-", 2)
+ dependencies, requirements = rest.split("|", 2).map {|s| s.split(",") } if rest
+ dependencies = dependencies ? dependencies.map {|d| parse_dependency(d) } : []
+ requirements = requirements ? requirements.map {|d| parse_dependency(d) } : []
+ [version, platform, dependencies, requirements]
+ end
+
+ private
+
+ def parse_dependency(string)
+ dependency = string.split(":")
+ dependency[-1] = dependency[-1].split("&") if dependency.size > 1
+ dependency
+ end
+end
diff --git a/lib/rubygems/resolver/api_specification.rb b/lib/rubygems/resolver/api_specification.rb
index 4052846e99..b5aa0b71d4 100644
--- a/lib/rubygems/resolver/api_specification.rb
+++ b/lib/rubygems/resolver/api_specification.rb
@@ -6,6 +6,16 @@
# is the name, version, and dependencies.
class Gem::Resolver::APISpecification < Gem::Resolver::Specification
+ ##
+ # We assume that all instances of this class are immutable;
+ # so avoid duplicated generation for performance.
+ @@cache = {}
+ def self.new(set, api_data)
+ cache_key = [set, api_data]
+ cache = @@cache[cache_key]
+ return cache if cache
+ @@cache[cache_key] = super
+ end
##
# Creates an APISpecification for the given +set+ from the rubygems.org
@@ -19,12 +29,14 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
@set = set
@name = api_data[:name]
- @version = Gem::Version.new api_data[:number]
- @platform = Gem::Platform.new api_data[:platform]
- @original_platform = api_data[:platform]
+ @version = Gem::Version.new(api_data[:number]).freeze
+ @platform = Gem::Platform.new(api_data[:platform]).freeze
+ @original_platform = api_data[:platform].freeze
@dependencies = api_data[:dependencies].map do |name, ver|
- Gem::Dependency.new name, ver.split(/\s*,\s*/)
- end
+ Gem::Dependency.new(name, ver.split(/\s*,\s*/)).freeze
+ end.freeze
+ @required_ruby_version = Gem::Requirement.new(api_data.dig(:requirements, :ruby)).freeze
+ @required_rubygems_version = Gem::Requirement.new(api_data.dig(:requirements, :rubygems)).freeze
end
def ==(other) # :nodoc:
@@ -32,8 +44,11 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
@set == other.set and
@name == other.name and
@version == other.version and
- @platform == other.platform and
- @dependencies == other.dependencies
+ @platform == other.platform
+ end
+
+ def hash
+ @set.hash ^ @name.hash ^ @version.hash ^ @platform.hash
end
def fetch_development_dependencies # :nodoc:
@@ -43,7 +58,7 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
end
def installable_platform? # :nodoc:
- Gem::Platform.match @platform
+ Gem::Platform.match_gem? @platform, @name
end
def pretty_print(q) # :nodoc:
@@ -86,5 +101,4 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
def source # :nodoc:
@set.source
end
-
end
diff --git a/lib/rubygems/resolver/best_set.rb b/lib/rubygems/resolver/best_set.rb
index 8a8c15d9a4..300ea8015c 100644
--- a/lib/rubygems/resolver/best_set.rb
+++ b/lib/rubygems/resolver/best_set.rb
@@ -5,7 +5,6 @@
# It combines IndexSet and APISet
class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
-
##
# Creates a BestSet for the given +sources+ or Gem::sources if none are
# specified. +sources+ must be a Gem::SourceList.
@@ -59,9 +58,9 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
# The calling method must retry the exception to repeat the lookup.
def replace_failed_api_set(error) # :nodoc:
- uri = error.uri
+ uri = error.original_uri
uri = URI uri unless URI === uri
- uri.query = nil
+ uri = uri + "."
raise error unless api_set = @sets.find do |set|
Gem::Resolver::APISet === set and set.dep_uri == uri
@@ -74,5 +73,4 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
index_set
end
end
-
end
diff --git a/lib/rubygems/resolver/composed_set.rb b/lib/rubygems/resolver/composed_set.rb
index 4baac9c75b..226da1e1e0 100644
--- a/lib/rubygems/resolver/composed_set.rb
+++ b/lib/rubygems/resolver/composed_set.rb
@@ -9,7 +9,6 @@
# This method will eliminate nesting of composed sets.
class Gem::Resolver::ComposedSet < Gem::Resolver::Set
-
attr_reader :sets # :nodoc:
##
@@ -40,11 +39,11 @@ class Gem::Resolver::ComposedSet < Gem::Resolver::Set
def remote=(remote)
super
- @sets.each { |set| set.remote = remote }
+ @sets.each {|set| set.remote = remote }
end
def errors
- @errors + @sets.map { |set| set.errors }.flatten
+ @errors + @sets.map {|set| set.errors }.flatten
end
##
@@ -60,7 +59,6 @@ class Gem::Resolver::ComposedSet < Gem::Resolver::Set
# Prefetches +reqs+ in all sets.
def prefetch(reqs)
- @sets.each { |s| s.prefetch(reqs) }
+ @sets.each {|s| s.prefetch(reqs) }
end
-
end
diff --git a/lib/rubygems/resolver/conflict.rb b/lib/rubygems/resolver/conflict.rb
index 2b337db339..4c4588d7e8 100644
--- a/lib/rubygems/resolver/conflict.rb
+++ b/lib/rubygems/resolver/conflict.rb
@@ -4,7 +4,6 @@
# with a spec that would be activated.
class Gem::Resolver::Conflict
-
##
# The specification that was activated prior to the conflict
@@ -55,7 +54,7 @@ class Gem::Resolver::Conflict
activated = @activated.spec.full_name
dependency = @failed_dep.dependency
requirement = dependency.requirement
- alternates = dependency.matching_specs.map { |spec| spec.full_name }
+ alternates = dependency.matching_specs.map {|spec| spec.full_name }
unless alternates.empty?
matching = <<-MATCHING.chomp
@@ -86,7 +85,7 @@ class Gem::Resolver::Conflict
activated, requirement,
request_path(@activated).reverse.join(", depends on\n "),
request_path(@failed_dep).reverse.join(", depends on\n "),
- matching,
+ matching
]
end
@@ -151,5 +150,4 @@ class Gem::Resolver::Conflict
def requester
@failed_dep.requester
end
-
end
diff --git a/lib/rubygems/resolver/current_set.rb b/lib/rubygems/resolver/current_set.rb
index d60e46389d..c3aa3a2c37 100644
--- a/lib/rubygems/resolver/current_set.rb
+++ b/lib/rubygems/resolver/current_set.rb
@@ -5,9 +5,7 @@
# for installed gems.
class Gem::Resolver::CurrentSet < Gem::Resolver::Set
-
def find_all(req)
req.dependency.matching_specs
end
-
end
diff --git a/lib/rubygems/resolver/dependency_request.rb b/lib/rubygems/resolver/dependency_request.rb
index 1984aa9ddc..356aadb3b2 100644
--- a/lib/rubygems/resolver/dependency_request.rb
+++ b/lib/rubygems/resolver/dependency_request.rb
@@ -4,7 +4,6 @@
# contained the Dependency.
class Gem::Resolver::DependencyRequest
-
##
# The wrapped Gem::Dependency
@@ -29,7 +28,7 @@ class Gem::Resolver::DependencyRequest
when Gem::Dependency
@dependency == other
when Gem::Resolver::DependencyRequest
- @dependency == other.dependency && @requester == other.requester
+ @dependency == other.dependency
else
false
end
@@ -116,5 +115,4 @@ class Gem::Resolver::DependencyRequest
def to_s # :nodoc:
@dependency.to_s
end
-
end
diff --git a/lib/rubygems/resolver/git_set.rb b/lib/rubygems/resolver/git_set.rb
index 6340b92fae..eac51f15ad 100644
--- a/lib/rubygems/resolver/git_set.rb
+++ b/lib/rubygems/resolver/git_set.rb
@@ -10,7 +10,6 @@
# set.add_git_gem 'rake', 'git://example/rake.git', tag: 'rake-10.1.0'
class Gem::Resolver::GitSet < Gem::Resolver::Set
-
##
# The root directory for git gems in this set. This is usually Gem.dir, the
# installation directory for regular gems.
@@ -118,5 +117,4 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set
end
end
end
-
end
diff --git a/lib/rubygems/resolver/git_specification.rb b/lib/rubygems/resolver/git_specification.rb
index f43cfba853..ee47080ab4 100644
--- a/lib/rubygems/resolver/git_specification.rb
+++ b/lib/rubygems/resolver/git_specification.rb
@@ -5,7 +5,6 @@
# option.
class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
-
def ==(other) # :nodoc:
self.class === other and
@set == other.set and
@@ -22,7 +21,7 @@ class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
# the executables.
def install(options = {})
- require 'rubygems/installer'
+ require_relative '../installer'
installer = Gem::Installer.for_spec spec, options
@@ -54,5 +53,4 @@ class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
q.pp @source
end
end
-
end
diff --git a/lib/rubygems/resolver/index_set.rb b/lib/rubygems/resolver/index_set.rb
index e32e1fa5ba..9390e34255 100644
--- a/lib/rubygems/resolver/index_set.rb
+++ b/lib/rubygems/resolver/index_set.rb
@@ -4,7 +4,6 @@
# source index.
class Gem::Resolver::IndexSet < Gem::Resolver::Set
-
def initialize(source = nil) # :nodoc:
super()
@@ -17,7 +16,7 @@ class Gem::Resolver::IndexSet < Gem::Resolver::Set
Gem::SpecFetcher.fetcher
end
- @all = Hash.new { |h,k| h[k] = [] }
+ @all = Hash.new {|h,k| h[k] = [] }
list, errors = @f.available_specs :complete
@@ -76,5 +75,4 @@ class Gem::Resolver::IndexSet < Gem::Resolver::Set
end
end
end
-
end
diff --git a/lib/rubygems/resolver/index_specification.rb b/lib/rubygems/resolver/index_specification.rb
index ed9423791c..9ea76f40ba 100644
--- a/lib/rubygems/resolver/index_specification.rb
+++ b/lib/rubygems/resolver/index_specification.rb
@@ -5,7 +5,6 @@
# and +version+ are needed.
class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification
-
##
# An IndexSpecification is created from the index format described in `gem
# help generate_index`.
@@ -34,6 +33,38 @@ class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification
spec.dependencies
end
+ ##
+ # The required_ruby_version constraint for this specification
+ #
+ # A fallback is included because when generated, some marshalled specs have it
+ # set to +nil+.
+
+ def required_ruby_version
+ spec.required_ruby_version || Gem::Requirement.default
+ end
+
+ ##
+ # The required_rubygems_version constraint for this specification
+ #
+ # A fallback is included because the original version of the specification
+ # API didn't include that field, so some marshalled specs in the index have it
+ # set to +nil+.
+
+ def required_rubygems_version
+ spec.required_rubygems_version || Gem::Requirement.default
+ end
+
+ def ==(other)
+ self.class === other &&
+ @name == other.name &&
+ @version == other.version &&
+ @platform == other.platform
+ end
+
+ def hash
+ @name.hash ^ @version.hash ^ @platform.hash
+ end
+
def inspect # :nodoc:
'#<%s %s source %s>' % [self.class, full_name, @source]
end
@@ -65,5 +96,4 @@ class Gem::Resolver::IndexSpecification < Gem::Resolver::Specification
@source.fetch_spec tuple
end
end
-
end
diff --git a/lib/rubygems/resolver/installed_specification.rb b/lib/rubygems/resolver/installed_specification.rb
index 9d996fc1da..167ba1439e 100644
--- a/lib/rubygems/resolver/installed_specification.rb
+++ b/lib/rubygems/resolver/installed_specification.rb
@@ -4,7 +4,6 @@
# locally.
class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification
-
def ==(other) # :nodoc:
self.class === other and
@set == other.set and
@@ -54,5 +53,4 @@ class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification
def source
@source ||= Gem::Source::Installed.new
end
-
end
diff --git a/lib/rubygems/resolver/installer_set.rb b/lib/rubygems/resolver/installer_set.rb
index ba14ee945d..f4fee351a5 100644
--- a/lib/rubygems/resolver/installer_set.rb
+++ b/lib/rubygems/resolver/installer_set.rb
@@ -4,7 +4,6 @@
# files
class Gem::Resolver::InstallerSet < Gem::Resolver::Set
-
##
# List of Gem::Specification objects that must always be installed.
@@ -27,13 +26,18 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
attr_reader :remote_set # :nodoc:
##
+ # Ignore ruby & rubygems specification constraints.
+ #
+
+ attr_accessor :force # :nodoc:
+
+ ##
# Creates a new InstallerSet that will look for gems in +domain+.
def initialize(domain)
super()
@domain = domain
- @remote = consider_remote?
@f = Gem::SpecFetcher.fetcher
@@ -43,6 +47,7 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
@local = {}
@local_source = Gem::Source::Local.new
@remote_set = Gem::Resolver::BestSet.new
+ @force = false
@specs = {}
end
@@ -65,15 +70,30 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
Gem::Platform.local === s.platform
end
- if found.empty?
- exc = Gem::UnsatisfiableDependencyError.new request
- exc.errors = errors
-
- raise exc
+ found = found.sort_by do |s|
+ [s.version, s.platform == Gem::Platform::RUBY ? -1 : 1]
end
- newest = found.max_by do |s|
- [s.version, s.platform == Gem::Platform::RUBY ? -1 : 1]
+ newest = found.last
+
+ unless @force
+ found_matching_metadata = found.reverse.find do |spec|
+ metadata_satisfied?(spec)
+ end
+
+ if found_matching_metadata.nil?
+ if newest
+ ensure_required_ruby_version_met(newest.spec)
+ ensure_required_rubygems_version_met(newest.spec)
+ else
+ exc = Gem::UnsatisfiableDependencyError.new request
+ exc.errors = errors
+
+ raise exc
+ end
+ else
+ newest = found_matching_metadata
+ end
end
@always_install << newest.spec
@@ -118,12 +138,12 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
dep = req.dependency
return res if @ignore_dependencies and
- @always_install.none? { |spec| dep.match? spec }
+ @always_install.none? {|spec| dep.match? spec }
name = dep.name
dep.matching_specs.each do |gemspec|
- next if @always_install.any? { |spec| spec.name == gemspec.name }
+ next if @always_install.any? {|spec| spec.name == gemspec.name }
res << Gem::Resolver::InstalledSpecification.new(self, gemspec)
end unless @ignore_installed
@@ -168,10 +188,10 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
end
def inspect # :nodoc:
- always_install = @always_install.map { |s| s.full_name }
+ always_install = @always_install.map {|s| s.full_name }
'#<%s domain: %s specs: %p always install: %p>' % [
- self.class, @domain, @specs.keys, always_install,
+ self.class, @domain, @specs.keys, always_install
]
end
@@ -224,4 +244,31 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
end
end
+ private
+
+ def metadata_satisfied?(spec)
+ spec.required_ruby_version.satisfied_by?(Gem.ruby_version) &&
+ spec.required_rubygems_version.satisfied_by?(Gem.rubygems_version)
+ end
+
+ def ensure_required_ruby_version_met(spec) # :nodoc:
+ if rrv = spec.required_ruby_version
+ ruby_version = Gem.ruby_version
+ unless rrv.satisfied_by? ruby_version
+ raise Gem::RuntimeRequirementNotMetError,
+ "#{spec.full_name} requires Ruby version #{rrv}. The current ruby version is #{ruby_version}."
+ end
+ end
+ end
+
+ def ensure_required_rubygems_version_met(spec) # :nodoc:
+ if rrgv = spec.required_rubygems_version
+ unless rrgv.satisfied_by? Gem.rubygems_version
+ rg_version = Gem::VERSION
+ raise Gem::RuntimeRequirementNotMetError,
+ "#{spec.full_name} requires RubyGems version #{rrgv}. The current RubyGems version is #{rg_version}. " +
+ "Try 'gem update --system' to update RubyGems itself."
+ end
+ end
+ end
end
diff --git a/lib/rubygems/resolver/local_specification.rb b/lib/rubygems/resolver/local_specification.rb
index 7418cfcc86..9c69c4ab74 100644
--- a/lib/rubygems/resolver/local_specification.rb
+++ b/lib/rubygems/resolver/local_specification.rb
@@ -3,7 +3,6 @@
# A LocalSpecification comes from a .gem file on the local filesystem.
class Gem::Resolver::LocalSpecification < Gem::Resolver::SpecSpecification
-
##
# Returns +true+ if this gem is installable for the current platform.
@@ -37,5 +36,4 @@ class Gem::Resolver::LocalSpecification < Gem::Resolver::SpecSpecification
q.text "source: #{@source.path}"
end
end
-
end
diff --git a/lib/rubygems/resolver/lock_set.rb b/lib/rubygems/resolver/lock_set.rb
index 4134b4dcaf..eabf217aba 100644
--- a/lib/rubygems/resolver/lock_set.rb
+++ b/lib/rubygems/resolver/lock_set.rb
@@ -3,7 +3,6 @@
# A set of gems from a gem dependencies lockfile.
class Gem::Resolver::LockSet < Gem::Resolver::Set
-
attr_reader :specs # :nodoc:
##
@@ -29,7 +28,7 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set
def add(name, version, platform) # :nodoc:
version = Gem::Version.new version
specs = [
- Gem::Resolver::LockSpecification.new(self, name, version, @sources, platform)
+ Gem::Resolver::LockSpecification.new(self, name, version, @sources, platform),
]
@specs.concat specs
@@ -75,8 +74,7 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set
q.text 'specs:'
q.breakable
- q.pp @specs.map { |spec| spec.full_name }
+ q.pp @specs.map {|spec| spec.full_name }
end
end
-
end
diff --git a/lib/rubygems/resolver/lock_specification.rb b/lib/rubygems/resolver/lock_specification.rb
index 5954507dba..cdb8e4e425 100644
--- a/lib/rubygems/resolver/lock_specification.rb
+++ b/lib/rubygems/resolver/lock_specification.rb
@@ -6,7 +6,6 @@
# lockfile.
class Gem::Resolver::LockSpecification < Gem::Resolver::Specification
-
attr_reader :sources
def initialize(set, name, version, sources, platform)
@@ -83,5 +82,4 @@ class Gem::Resolver::LockSpecification < Gem::Resolver::Specification
s.dependencies.concat @dependencies
end
end
-
end
diff --git a/lib/rubygems/resolver/molinillo.rb b/lib/rubygems/resolver/molinillo.rb
index 2357f41bee..12ca740e5a 100644
--- a/lib/rubygems/resolver/molinillo.rb
+++ b/lib/rubygems/resolver/molinillo.rb
@@ -1,2 +1,2 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo'
+require_relative 'molinillo/lib/molinillo'
diff --git a/lib/rubygems/resolver/molinillo/LICENSE b/lib/rubygems/resolver/molinillo/LICENSE
new file mode 100644
index 0000000000..01feffa088
--- /dev/null
+++ b/lib/rubygems/resolver/molinillo/LICENSE
@@ -0,0 +1,9 @@
+This project is licensed under the MIT license.
+
+Copyright (c) 2014 Samuel E. Giddins segiddins@segiddins.me
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo.rb b/lib/rubygems/resolver/molinillo/lib/molinillo.rb
index 0ae4b6a912..f67badbde7 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo/gem_metadata'
-require 'rubygems/resolver/molinillo/lib/molinillo/errors'
-require 'rubygems/resolver/molinillo/lib/molinillo/resolver'
-require 'rubygems/resolver/molinillo/lib/molinillo/modules/ui'
-require 'rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider'
+
+require_relative 'molinillo/gem_metadata'
+require_relative 'molinillo/errors'
+require_relative 'molinillo/resolver'
+require_relative 'molinillo/modules/ui'
+require_relative 'molinillo/modules/specification_provider'
# Gem::Resolver::Molinillo is a generic dependency resolution algorithm.
module Gem::Resolver::Molinillo
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb
index 1bbc72c1f6..d540d3baff 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
# @!visibility private
module Delegates
@@ -45,6 +46,12 @@ module Gem::Resolver::Molinillo
current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty
current_state.conflicts
end
+
+ # (see Gem::Resolver::Molinillo::ResolutionState#unused_unwind_options)
+ def unused_unwind_options
+ current_state = state || Gem::Resolver::Molinillo::ResolutionState.empty
+ current_state.unused_unwind_options
+ end
end
end
end
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb
index 71903c7e86..b765226fb0 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
module Delegates
# Delegates all {Gem::Resolver::Molinillo::SpecificationProvider} methods to a
@@ -25,6 +26,13 @@ module Gem::Resolver::Molinillo
end
end
+ # (see Gem::Resolver::Molinillo::SpecificationProvider#dependencies_equal?)
+ def dependencies_equal?(dependencies, other_dependencies)
+ with_no_such_dependency_error_handling do
+ specification_provider.dependencies_equal?(dependencies, other_dependencies)
+ end
+ end
+
# (see Gem::Resolver::Molinillo::SpecificationProvider#name_for)
def name_for(dependency)
with_no_such_dependency_error_handling do
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
index b413e3ab6a..95f8416b96 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-require 'set'
-require 'tsort'
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log'
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex'
+require_relative '../../../../tsort'
+
+require_relative 'dependency_graph/log'
+require_relative 'dependency_graph/vertex'
module Gem::Resolver::Molinillo
# A directed acyclic graph that is tuned to hold named dependencies
@@ -17,7 +17,7 @@ module Gem::Resolver::Molinillo
vertices.values.each { |v| yield v }
end
- include TSort
+ include Gem::TSort
# @!visibility private
alias tsort_each_node each
@@ -123,6 +123,7 @@ module Gem::Resolver::Molinillo
dot.join("\n")
end
+ # @param [DependencyGraph] other
# @return [Boolean] whether the two dependency graphs are equal, determined
# by a recursive traversal of each {#root_vertices} and its
# {Vertex#successors}
@@ -147,8 +148,8 @@ module Gem::Resolver::Molinillo
vertex = add_vertex(name, payload, root)
vertex.explicit_requirements << requirement if root
parent_names.each do |parent_name|
- parent_node = vertex_named(parent_name)
- add_edge(parent_node, vertex, requirement)
+ parent_vertex = vertex_named(parent_name)
+ add_edge(parent_vertex, vertex, requirement)
end
vertex
end
@@ -189,7 +190,7 @@ module Gem::Resolver::Molinillo
# @return [Edge] the added edge
def add_edge(origin, destination, requirement)
if destination.path_to?(origin)
- raise CircularDependencyError.new([origin, destination])
+ raise CircularDependencyError.new(path(destination, origin))
end
add_edge_no_circular(origin, destination, requirement)
end
@@ -218,5 +219,37 @@ module Gem::Resolver::Molinillo
def add_edge_no_circular(origin, destination, requirement)
log.add_edge_no_circular(self, origin.name, destination.name, requirement)
end
+
+ # Returns the path between two vertices
+ # @raise [ArgumentError] if there is no path between the vertices
+ # @param [Vertex] from
+ # @param [Vertex] to
+ # @return [Array<Vertex>] the shortest path from `from` to `to`
+ def path(from, to)
+ distances = Hash.new(vertices.size + 1)
+ distances[from.name] = 0
+ predecessors = {}
+ each do |vertex|
+ vertex.successors.each do |successor|
+ if distances[successor.name] > distances[vertex.name] + 1
+ distances[successor.name] = distances[vertex.name] + 1
+ predecessors[successor] = vertex
+ end
+ end
+ end
+
+ path = [to]
+ while before = predecessors[to]
+ path << before
+ to = before
+ break if to == from
+ end
+
+ unless path.last.equal?(from)
+ raise ArgumentError, "There is no path from #{from.name} to #{to.name}"
+ end
+
+ path.reverse
+ end
end
end
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb
index eeedabb069..cc140031b3 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
class DependencyGraph
# An action that modifies a {DependencyGraph} that is reversible.
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
index e994e59d05..5570483253 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action'
+
+require_relative 'action'
module Gem::Resolver::Molinillo
class DependencyGraph
# @!visibility private
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb
index 6cde933080..f1411d5efa 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action'
+
+require_relative 'action'
module Gem::Resolver::Molinillo
class DependencyGraph
# @!visibility private
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb
index d44aaf1f06..3b48d77a50 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action'
+
+require_relative 'action'
module Gem::Resolver::Molinillo
class DependencyGraph
# @!visibility private
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb
index fa03e2d365..92f60d5be8 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action'
+
+require_relative 'action'
module Gem::Resolver::Molinillo
class DependencyGraph
# @!visibility private
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb
index 5cdd84b5c1..7aeb8847ec 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb
@@ -1,10 +1,11 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular'
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex'
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge'
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named'
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload'
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag'
+
+require_relative 'add_edge_no_circular'
+require_relative 'add_vertex'
+require_relative 'delete_edge'
+require_relative 'detach_vertex_named'
+require_relative 'set_payload'
+require_relative 'tag'
module Gem::Resolver::Molinillo
class DependencyGraph
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb
index 02cfba64a7..726292a2c3 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action'
+
+require_relative 'action'
module Gem::Resolver::Molinillo
class DependencyGraph
# @!visibility private
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb
index 0cb08075ca..bfe6fd31f8 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action'
+
+require_relative 'action'
module Gem::Resolver::Molinillo
class DependencyGraph
# @!visibility private
@@ -13,11 +14,11 @@ module Gem::Resolver::Molinillo
end
# (see Action#up)
- def up(_graph)
+ def up(graph)
end
# (see Action#down)
- def down(_graph)
+ def down(graph)
end
# @!group Tag
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb
index cebd9cafdd..77114951b2 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
class DependencyGraph
# A vertex in a {DependencyGraph} that encapsulates a {#name} and a
@@ -32,7 +33,7 @@ module Gem::Resolver::Molinillo
# @return [Array<Object>] all of the requirements that required
# this vertex
def requirements
- incoming_edges.map(&:requirement) + explicit_requirements
+ (incoming_edges.map(&:requirement) + explicit_requirements).uniq
end
# @return [Array<Edge>] the edges of {#graph} that have `self` as their
@@ -49,14 +50,25 @@ module Gem::Resolver::Molinillo
incoming_edges.map(&:origin)
end
- # @return [Array<Vertex>] the vertices of {#graph} where `self` is a
+ # @return [Set<Vertex>] the vertices of {#graph} where `self` is a
# {#descendent?}
def recursive_predecessors
- vertices = predecessors
- vertices += vertices.map(&:recursive_predecessors).flatten(1)
- vertices.uniq!
+ _recursive_predecessors
+ end
+
+ # @param [Set<Vertex>] vertices the set to add the predecessors to
+ # @return [Set<Vertex>] the vertices of {#graph} where `self` is a
+ # {#descendent?}
+ def _recursive_predecessors(vertices = new_vertex_set)
+ incoming_edges.each do |edge|
+ vertex = edge.origin
+ next unless vertices.add?(vertex)
+ vertex._recursive_predecessors(vertices)
+ end
+
vertices
end
+ protected :_recursive_predecessors
# @return [Array<Vertex>] the vertices of {#graph} that have an edge with
# `self` as their {Edge#origin}
@@ -64,14 +76,25 @@ module Gem::Resolver::Molinillo
outgoing_edges.map(&:destination)
end
- # @return [Array<Vertex>] the vertices of {#graph} where `self` is an
+ # @return [Set<Vertex>] the vertices of {#graph} where `self` is an
# {#ancestor?}
def recursive_successors
- vertices = successors
- vertices += vertices.map(&:recursive_successors).flatten(1)
- vertices.uniq!
+ _recursive_successors
+ end
+
+ # @param [Set<Vertex>] vertices the set to add the successors to
+ # @return [Set<Vertex>] the vertices of {#graph} where `self` is an
+ # {#ancestor?}
+ def _recursive_successors(vertices = new_vertex_set)
+ outgoing_edges.each do |edge|
+ vertex = edge.destination
+ next unless vertices.add?(vertex)
+ vertex._recursive_successors(vertices)
+ end
+
vertices
end
+ protected :_recursive_successors
# @return [String] a string suitable for debugging
def inspect
@@ -105,21 +128,37 @@ module Gem::Resolver::Molinillo
# Is there a path from `self` to `other` following edges in the
# dependency graph?
- # @return true iff there is a path following edges within this {#graph}
+ # @return whether there is a path following edges within this {#graph}
def path_to?(other)
- equal?(other) || successors.any? { |v| v.path_to?(other) }
+ _path_to?(other)
end
alias descendent? path_to?
+ # @param [Vertex] other the vertex to check if there's a path to
+ # @param [Set<Vertex>] visited the vertices of {#graph} that have been visited
+ # @return [Boolean] whether there is a path to `other` from `self`
+ def _path_to?(other, visited = new_vertex_set)
+ return false unless visited.add?(self)
+ return true if equal?(other)
+ successors.any? { |v| v._path_to?(other, visited) }
+ end
+ protected :_path_to?
+
# Is there a path from `other` to `self` following edges in the
# dependency graph?
- # @return true iff there is a path following edges within this {#graph}
+ # @return whether there is a path following edges within this {#graph}
def ancestor?(other)
other.path_to?(self)
end
alias is_reachable_from? ancestor?
+
+ def new_vertex_set
+ require 'set'
+ Set.new
+ end
+ private :new_vertex_set
end
end
end
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb
index 129246bf4a..ada03a901c 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/errors.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
# An error that occurred during the resolution process
class ResolverError < StandardError; end
@@ -17,7 +18,7 @@ module Gem::Resolver::Molinillo
# @param [Array<Object>] required_by @see {#required_by}
def initialize(dependency, required_by = [])
@dependency = dependency
- @required_by = required_by
+ @required_by = required_by.uniq
super()
end
@@ -33,7 +34,7 @@ module Gem::Resolver::Molinillo
# An error caused by attempting to fulfil a dependency that was circular
#
- # @note This exception will be thrown iff a {Vertex} is added to a
+ # @note This exception will be thrown if and only if a {Vertex} is added to a
# {DependencyGraph} that has a {DependencyGraph::Vertex#path_to?} an
# existing {DependencyGraph::Vertex}
class CircularDependencyError < ResolverError
@@ -41,11 +42,11 @@ module Gem::Resolver::Molinillo
attr_reader :dependencies
# Initializes a new error with the given circular vertices.
- # @param [Array<DependencyGraph::Vertex>] nodes the nodes in the dependency
+ # @param [Array<DependencyGraph::Vertex>] vertices the vertices in the dependency
# that caused the error
- def initialize(nodes)
- super "There is a circular dependency between #{nodes.map(&:name).join(' and ')}"
- @dependencies = nodes.map(&:payload).to_set
+ def initialize(vertices)
+ super "There is a circular dependency between #{vertices.map(&:name).join(' and ')}"
+ @dependencies = vertices.map { |vertex| vertex.payload.possibilities.last }.to_set
end
end
@@ -55,11 +56,16 @@ module Gem::Resolver::Molinillo
# resolution to fail
attr_reader :conflicts
+ # @return [SpecificationProvider] the specification provider used during
+ # resolution
+ attr_reader :specification_provider
+
# Initializes a new error with the given version conflicts.
# @param [{String => Resolution::Conflict}] conflicts see {#conflicts}
- def initialize(conflicts)
+ # @param [SpecificationProvider] specification_provider see {#specification_provider}
+ def initialize(conflicts, specification_provider)
pairs = []
- conflicts.values.flatten.map(&:requirements).flatten.each do |conflicting|
+ conflicts.values.flat_map(&:requirements).each do |conflicting|
conflicting.each do |source, conflict_requirements|
conflict_requirements.each do |c|
pairs << [c, source]
@@ -69,7 +75,69 @@ module Gem::Resolver::Molinillo
super "Unable to satisfy the following requirements:\n\n" \
"#{pairs.map { |r, d| "- `#{r}` required by `#{d}`" }.join("\n")}"
+
@conflicts = conflicts
+ @specification_provider = specification_provider
+ end
+
+ require_relative 'delegates/specification_provider'
+ include Delegates::SpecificationProvider
+
+ # @return [String] An error message that includes requirement trees,
+ # which is much more detailed & customizable than the default message
+ # @param [Hash] opts the options to create a message with.
+ # @option opts [String] :solver_name The user-facing name of the solver
+ # @option opts [String] :possibility_type The generic name of a possibility
+ # @option opts [Proc] :reduce_trees A proc that reduced the list of requirement trees
+ # @option opts [Proc] :printable_requirement A proc that pretty-prints requirements
+ # @option opts [Proc] :additional_message_for_conflict A proc that appends additional
+ # messages for each conflict
+ # @option opts [Proc] :version_for_spec A proc that returns the version number for a
+ # possibility
+ def message_with_trees(opts = {})
+ solver_name = opts.delete(:solver_name) { self.class.name.split('::').first }
+ possibility_type = opts.delete(:possibility_type) { 'possibility named' }
+ reduce_trees = opts.delete(:reduce_trees) { proc { |trees| trees.uniq.sort_by(&:to_s) } }
+ printable_requirement = opts.delete(:printable_requirement) { proc { |req| req.to_s } }
+ additional_message_for_conflict = opts.delete(:additional_message_for_conflict) { proc {} }
+ version_for_spec = opts.delete(:version_for_spec) { proc(&:to_s) }
+ incompatible_version_message_for_conflict = opts.delete(:incompatible_version_message_for_conflict) do
+ proc do |name, _conflict|
+ %(#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":)
+ end
+ end
+
+ conflicts.sort.reduce(''.dup) do |o, (name, conflict)|
+ o << "\n" << incompatible_version_message_for_conflict.call(name, conflict) << "\n"
+ if conflict.locked_requirement
+ o << %( In snapshot (#{name_for_locking_dependency_source}):\n)
+ o << %( #{printable_requirement.call(conflict.locked_requirement)}\n)
+ o << %(\n)
+ end
+ o << %( In #{name_for_explicit_dependency_source}:\n)
+ trees = reduce_trees.call(conflict.requirement_trees)
+
+ o << trees.map do |tree|
+ t = ''.dup
+ depth = 2
+ tree.each do |req|
+ t << ' ' * depth << printable_requirement.call(req)
+ unless tree.last == req
+ if spec = conflict.activated_by_name[name_for(req)]
+ t << %( was resolved to #{version_for_spec.call(spec)}, which)
+ end
+ t << %( depends on)
+ end
+ t << %(\n)
+ depth += 1
+ end
+ t
+ end.join("\n")
+
+ additional_message_for_conflict.call(o, name, conflict)
+
+ o
+ end.strip
end
end
end
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb
index c5b5bd729f..6b5ada7ade 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
# The version of Gem::Resolver::Molinillo.
- VERSION = '0.5.7'.freeze
+ VERSION = '0.7.0'.freeze
end
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb
index 916345b12a..1067bf7439 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
- # Provides information about specifcations and dependencies to the resolver,
+ # Provides information about specifications and dependencies to the resolver,
# allowing the {Resolver} class to remain generic while still providing power
# and flexibility.
#
@@ -44,6 +45,17 @@ module Gem::Resolver::Molinillo
true
end
+ # Determines whether two arrays of dependencies are equal, and thus can be
+ # grouped.
+ #
+ # @param [Array<Object>] dependencies
+ # @param [Array<Object>] other_dependencies
+ # @return [Boolean] whether `dependencies` and `other_dependencies` should
+ # be considered equal.
+ def dependencies_equal?(dependencies, other_dependencies)
+ dependencies == other_dependencies
+ end
+
# Returns the name for the given `dependency`.
# @note This method should be 'pure', i.e. the return value should depend
# only on the `dependency` parameter.
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb
index dbc4e000e4..a810fd519c 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
# Conveys information about the resolution process to a user.
module UI
@@ -48,7 +49,8 @@ module Gem::Resolver::Molinillo
if debug?
debug_info = yield
debug_info = debug_info.inspect unless debug_info.is_a?(String)
- output.puts debug_info.split("\n").map { |s| ' ' * depth + s }
+ debug_info = debug_info.split("\n").map { |s| ":#{depth.to_s.rjust 4}: #{s}" }
+ output.puts debug_info
end
end
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
index 73a4242157..8b40e59e42 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
class Resolver
# A specific resolution from a given {Resolver}
@@ -8,22 +9,125 @@ module Gem::Resolver::Molinillo
# @attr [{String,Nil=>[Object]}] requirements the requirements that caused the conflict
# @attr [Object, nil] existing the existing spec that was in conflict with
# the {#possibility}
- # @attr [Object] possibility the spec that was unable to be activated due
- # to a conflict
+ # @attr [Object] possibility_set the set of specs that was unable to be
+ # activated due to a conflict.
# @attr [Object] locked_requirement the relevant locking requirement.
# @attr [Array<Array<Object>>] requirement_trees the different requirement
# trees that led to every requirement for the conflicting name.
# @attr [{String=>Object}] activated_by_name the already-activated specs.
+ # @attr [Object] underlying_error an error that has occurred during resolution, and
+ # will be raised at the end of it if no resolution is found.
Conflict = Struct.new(
:requirement,
:requirements,
:existing,
- :possibility,
+ :possibility_set,
:locked_requirement,
:requirement_trees,
- :activated_by_name
+ :activated_by_name,
+ :underlying_error
)
+ class Conflict
+ # @return [Object] a spec that was unable to be activated due to a conflict
+ def possibility
+ possibility_set && possibility_set.latest_version
+ end
+ end
+
+ # A collection of possibility states that share the same dependencies
+ # @attr [Array] dependencies the dependencies for this set of possibilities
+ # @attr [Array] possibilities the possibilities
+ PossibilitySet = Struct.new(:dependencies, :possibilities)
+
+ class PossibilitySet
+ # String representation of the possibility set, for debugging
+ def to_s
+ "[#{possibilities.join(', ')}]"
+ end
+
+ # @return [Object] most up-to-date dependency in the possibility set
+ def latest_version
+ possibilities.last
+ end
+ end
+
+ # Details of the state to unwind to when a conflict occurs, and the cause of the unwind
+ # @attr [Integer] state_index the index of the state to unwind to
+ # @attr [Object] state_requirement the requirement of the state we're unwinding to
+ # @attr [Array] requirement_tree for the requirement we're relaxing
+ # @attr [Array] conflicting_requirements the requirements that combined to cause the conflict
+ # @attr [Array] requirement_trees for the conflict
+ # @attr [Array] requirements_unwound_to_instead array of unwind requirements that were chosen over this unwind
+ UnwindDetails = Struct.new(
+ :state_index,
+ :state_requirement,
+ :requirement_tree,
+ :conflicting_requirements,
+ :requirement_trees,
+ :requirements_unwound_to_instead
+ )
+
+ class UnwindDetails
+ include Comparable
+
+ # We compare UnwindDetails when choosing which state to unwind to. If
+ # two options have the same state_index we prefer the one most
+ # removed from a requirement that caused the conflict. Both options
+ # would unwind to the same state, but a `grandparent` option will
+ # filter out fewer of its possibilities after doing so - where a state
+ # is both a `parent` and a `grandparent` to requirements that have
+ # caused a conflict this is the correct behaviour.
+ # @param [UnwindDetail] other UnwindDetail to be compared
+ # @return [Integer] integer specifying ordering
+ def <=>(other)
+ if state_index > other.state_index
+ 1
+ elsif state_index == other.state_index
+ reversed_requirement_tree_index <=> other.reversed_requirement_tree_index
+ else
+ -1
+ end
+ end
+
+ # @return [Integer] index of state requirement in reversed requirement tree
+ # (the conflicting requirement itself will be at position 0)
+ def reversed_requirement_tree_index
+ @reversed_requirement_tree_index ||=
+ if state_requirement
+ requirement_tree.reverse.index(state_requirement)
+ else
+ 999_999
+ end
+ end
+
+ # @return [Boolean] where the requirement of the state we're unwinding
+ # to directly caused the conflict. Note: in this case, it is
+ # impossible for the state we're unwinding to to be a parent of
+ # any of the other conflicting requirements (or we would have
+ # circularity)
+ def unwinding_to_primary_requirement?
+ requirement_tree.last == state_requirement
+ end
+
+ # @return [Array] array of sub-dependencies to avoid when choosing a
+ # new possibility for the state we've unwound to. Only relevant for
+ # non-primary unwinds
+ def sub_dependencies_to_avoid
+ @requirements_to_avoid ||=
+ requirement_trees.map do |tree|
+ index = tree.index(state_requirement)
+ tree[index + 1] if index
+ end.compact
+ end
+
+ # @return [Array] array of all the requirements that led to the need for
+ # this unwind
+ def all_requirements
+ @all_requirements ||= requirement_trees.flatten(1)
+ end
+ end
+
# @return [SpecificationProvider] the provider that knows about
# dependencies, requirements, specifications, versions, etc.
attr_reader :specification_provider
@@ -64,7 +168,7 @@ module Gem::Resolver::Molinillo
start_resolution
while state
- break unless state.requirements.any? || state.requirement
+ break if !state.requirement && state.requirements.empty?
indicate_progress
if state.respond_to?(:pop_possibility_state) # DependencyState
debug(depth) { "Creating possibility state for #{requirement} (#{possibilities.count} remaining)" }
@@ -78,7 +182,7 @@ module Gem::Resolver::Molinillo
process_topmost_state
end
- activated.freeze
+ resolve_activated_specs
ensure
end_resolution
end
@@ -103,12 +207,25 @@ module Gem::Resolver::Molinillo
def start_resolution
@started_at = Time.now
- handle_missing_or_push_dependency_state(initial_state)
+ push_initial_state
debug { "Starting resolution (#{@started_at})\nUser-requested dependencies: #{original_requested}" }
resolver_ui.before_resolution
end
+ def resolve_activated_specs
+ activated.vertices.each do |_, vertex|
+ next unless vertex.payload
+
+ latest_version = vertex.payload.possibilities.reverse_each.find do |possibility|
+ vertex.requirements.all? { |req| requirement_satisfied_by?(req, activated, possibility) }
+ end
+
+ activated.set_payload(vertex.name, latest_version)
+ end
+ activated.freeze
+ end
+
# Ends the resolution process
# @return [void]
def end_resolution
@@ -121,11 +238,11 @@ module Gem::Resolver::Molinillo
debug { 'Activated: ' + Hash[activated.vertices.select { |_n, v| v.payload }].keys.join(', ') } if state
end
- require 'rubygems/resolver/molinillo/lib/molinillo/state'
- require 'rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider'
+ require_relative 'state'
+ require_relative 'modules/specification_provider'
- require 'rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state'
- require 'rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider'
+ require_relative 'delegates/resolution_state'
+ require_relative 'delegates/specification_provider'
include Gem::Resolver::Molinillo::Delegates::ResolutionState
include Gem::Resolver::Molinillo::Delegates::SpecificationProvider
@@ -136,9 +253,12 @@ module Gem::Resolver::Molinillo
if possibility
attempt_to_activate
else
- create_conflict if state.is_a? PossibilityState
- unwind_for_conflict until possibility && state.is_a?(DependencyState)
+ create_conflict
+ unwind_for_conflict
end
+ rescue CircularDependencyError => underlying_error
+ create_conflict(underlying_error)
+ unwind_for_conflict
end
# @return [Object] the current possibility that the resolution is trying
@@ -153,63 +273,296 @@ module Gem::Resolver::Molinillo
states.last
end
- # Creates the initial state for the resolution, based upon the
+ # Creates and pushes the initial state for the resolution, based upon the
# {#requested} dependencies
- # @return [DependencyState] the initial state for the resolution
- def initial_state
+ # @return [void]
+ def push_initial_state
graph = DependencyGraph.new.tap do |dg|
- original_requested.each { |r| dg.add_vertex(name_for(r), nil, true).tap { |v| v.explicit_requirements << r } }
+ original_requested.each do |requested|
+ vertex = dg.add_vertex(name_for(requested), nil, true)
+ vertex.explicit_requirements << requested
+ end
dg.tag(:initial_state)
end
- requirements = sort_dependencies(original_requested, graph, {})
- initial_requirement = requirements.shift
- DependencyState.new(
- initial_requirement && name_for(initial_requirement),
- requirements,
- graph,
- initial_requirement,
- initial_requirement && search_for(initial_requirement),
- 0,
- {}
- )
+ push_state_for_requirements(original_requested, true, graph)
end
# Unwinds the states stack because a conflict has been encountered
# @return [void]
def unwind_for_conflict
- debug(depth) { "Unwinding for conflict: #{requirement} to #{state_index_for_unwind / 2}" }
+ details_for_unwind = build_details_for_unwind
+ unwind_options = unused_unwind_options
+ debug(depth) { "Unwinding for conflict: #{requirement} to #{details_for_unwind.state_index / 2}" }
conflicts.tap do |c|
- sliced_states = states.slice!((state_index_for_unwind + 1)..-1)
- raise VersionConflict.new(c) unless state
+ sliced_states = states.slice!((details_for_unwind.state_index + 1)..-1)
+ raise_error_unless_state(c)
activated.rewind_to(sliced_states.first || :initial_state) if sliced_states
state.conflicts = c
+ state.unused_unwind_options = unwind_options
+ filter_possibilities_after_unwind(details_for_unwind)
index = states.size - 1
@parents_of.each { |_, a| a.reject! { |i| i >= index } }
+ state.unused_unwind_options.reject! { |uw| uw.state_index >= index }
+ end
+ end
+
+ # Raises a VersionConflict error, or any underlying error, if there is no
+ # current state
+ # @return [void]
+ def raise_error_unless_state(conflicts)
+ return if state
+
+ error = conflicts.values.map(&:underlying_error).compact.first
+ raise error || VersionConflict.new(conflicts, specification_provider)
+ end
+
+ # @return [UnwindDetails] Details of the nearest index to which we could unwind
+ def build_details_for_unwind
+ # Get the possible unwinds for the current conflict
+ current_conflict = conflicts[name]
+ binding_requirements = binding_requirements_for_conflict(current_conflict)
+ unwind_details = unwind_options_for_requirements(binding_requirements)
+
+ last_detail_for_current_unwind = unwind_details.sort.last
+ current_detail = last_detail_for_current_unwind
+
+ # Look for past conflicts that could be unwound to affect the
+ # requirement tree for the current conflict
+ all_reqs = last_detail_for_current_unwind.all_requirements
+ all_reqs_size = all_reqs.size
+ relevant_unused_unwinds = unused_unwind_options.select do |alternative|
+ diff_reqs = all_reqs - alternative.requirements_unwound_to_instead
+ next if diff_reqs.size == all_reqs_size
+ # Find the highest index unwind whilst looping through
+ current_detail = alternative if alternative > current_detail
+ alternative
+ end
+
+ # Add the current unwind options to the `unused_unwind_options` array.
+ # The "used" option will be filtered out during `unwind_for_conflict`.
+ state.unused_unwind_options += unwind_details.reject { |detail| detail.state_index == -1 }
+
+ # Update the requirements_unwound_to_instead on any relevant unused unwinds
+ relevant_unused_unwinds.each do |d|
+ (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
+ end
+ unwind_details.each do |d|
+ (d.requirements_unwound_to_instead << current_detail.state_requirement).uniq!
+ end
+
+ current_detail
+ end
+
+ # @param [Array<Object>] binding_requirements array of requirements that combine to create a conflict
+ # @return [Array<UnwindDetails>] array of UnwindDetails that have a chance
+ # of resolving the passed requirements
+ def unwind_options_for_requirements(binding_requirements)
+ unwind_details = []
+
+ trees = []
+ binding_requirements.reverse_each do |r|
+ partial_tree = [r]
+ trees << partial_tree
+ unwind_details << UnwindDetails.new(-1, nil, partial_tree, binding_requirements, trees, [])
+
+ # If this requirement has alternative possibilities, check if any would
+ # satisfy the other requirements that created this conflict
+ requirement_state = find_state_for(r)
+ if conflict_fixing_possibilities?(requirement_state, binding_requirements)
+ unwind_details << UnwindDetails.new(
+ states.index(requirement_state),
+ r,
+ partial_tree,
+ binding_requirements,
+ trees,
+ []
+ )
+ end
+
+ # Next, look at the parent of this requirement, and check if the requirement
+ # could have been avoided if an alternative PossibilitySet had been chosen
+ parent_r = parent_of(r)
+ next if parent_r.nil?
+ partial_tree.unshift(parent_r)
+ requirement_state = find_state_for(parent_r)
+ if requirement_state.possibilities.any? { |set| !set.dependencies.include?(r) }
+ unwind_details << UnwindDetails.new(
+ states.index(requirement_state),
+ parent_r,
+ partial_tree,
+ binding_requirements,
+ trees,
+ []
+ )
+ end
+
+ # Finally, look at the grandparent and up of this requirement, looking
+ # for any possibilities that wouldn't create their parent requirement
+ grandparent_r = parent_of(parent_r)
+ until grandparent_r.nil?
+ partial_tree.unshift(grandparent_r)
+ requirement_state = find_state_for(grandparent_r)
+ if requirement_state.possibilities.any? { |set| !set.dependencies.include?(parent_r) }
+ unwind_details << UnwindDetails.new(
+ states.index(requirement_state),
+ grandparent_r,
+ partial_tree,
+ binding_requirements,
+ trees,
+ []
+ )
+ end
+ parent_r = grandparent_r
+ grandparent_r = parent_of(parent_r)
+ end
+ end
+
+ unwind_details
+ end
+
+ # @param [DependencyState] state
+ # @param [Array] binding_requirements array of requirements
+ # @return [Boolean] whether or not the given state has any possibilities
+ # that could satisfy the given requirements
+ def conflict_fixing_possibilities?(state, binding_requirements)
+ return false unless state
+
+ state.possibilities.any? do |possibility_set|
+ possibility_set.possibilities.any? do |poss|
+ possibility_satisfies_requirements?(poss, binding_requirements)
+ end
+ end
+ end
+
+ # Filter's a state's possibilities to remove any that would not fix the
+ # conflict we've just rewound from
+ # @param [UnwindDetails] unwind_details details of the conflict just
+ # unwound from
+ # @return [void]
+ def filter_possibilities_after_unwind(unwind_details)
+ return unless state && !state.possibilities.empty?
+
+ if unwind_details.unwinding_to_primary_requirement?
+ filter_possibilities_for_primary_unwind(unwind_details)
+ else
+ filter_possibilities_for_parent_unwind(unwind_details)
end
end
- # @return [Integer] The index to which the resolution should unwind in the
- # case of conflict.
- def state_index_for_unwind
- current_requirement = requirement
- existing_requirement = requirement_for_existing_name(name)
- index = -1
- [current_requirement, existing_requirement].each do |r|
- until r.nil?
- current_state = find_state_for(r)
- if state_any?(current_state)
- current_index = states.index(current_state)
- index = current_index if current_index > index
- break
+ # Filter's a state's possibilities to remove any that would not satisfy
+ # the requirements in the conflict we've just rewound from
+ # @param [UnwindDetails] unwind_details details of the conflict just unwound from
+ # @return [void]
+ def filter_possibilities_for_primary_unwind(unwind_details)
+ unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
+ unwinds_to_state << unwind_details
+ unwind_requirement_sets = unwinds_to_state.map(&:conflicting_requirements)
+
+ state.possibilities.reject! do |possibility_set|
+ possibility_set.possibilities.none? do |poss|
+ unwind_requirement_sets.any? do |requirements|
+ possibility_satisfies_requirements?(poss, requirements)
end
- r = parent_of(r)
end
end
+ end
+
+ # @param [Object] possibility a single possibility
+ # @param [Array] requirements an array of requirements
+ # @return [Boolean] whether the possibility satisfies all of the
+ # given requirements
+ def possibility_satisfies_requirements?(possibility, requirements)
+ name = name_for(possibility)
+
+ activated.tag(:swap)
+ activated.set_payload(name, possibility) if activated.vertex_named(name)
+ satisfied = requirements.all? { |r| requirement_satisfied_by?(r, activated, possibility) }
+ activated.rewind_to(:swap)
+
+ satisfied
+ end
+
+ # Filter's a state's possibilities to remove any that would (eventually)
+ # create a requirement in the conflict we've just rewound from
+ # @param [UnwindDetails] unwind_details details of the conflict just unwound from
+ # @return [void]
+ def filter_possibilities_for_parent_unwind(unwind_details)
+ unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
+ unwinds_to_state << unwind_details
+
+ primary_unwinds = unwinds_to_state.select(&:unwinding_to_primary_requirement?).uniq
+ parent_unwinds = unwinds_to_state.uniq - primary_unwinds
+
+ allowed_possibility_sets = primary_unwinds.flat_map do |unwind|
+ states[unwind.state_index].possibilities.select do |possibility_set|
+ possibility_set.possibilities.any? do |poss|
+ possibility_satisfies_requirements?(poss, unwind.conflicting_requirements)
+ end
+ end
+ end
+
+ requirements_to_avoid = parent_unwinds.flat_map(&:sub_dependencies_to_avoid)
+
+ state.possibilities.reject! do |possibility_set|
+ !allowed_possibility_sets.include?(possibility_set) &&
+ (requirements_to_avoid - possibility_set.dependencies).empty?
+ end
+ end
+
+ # @param [Conflict] conflict
+ # @return [Array] minimal array of requirements that would cause the passed
+ # conflict to occur.
+ def binding_requirements_for_conflict(conflict)
+ return [conflict.requirement] if conflict.possibility.nil?
+
+ possible_binding_requirements = conflict.requirements.values.flatten(1).uniq
+
+ # When there's a `CircularDependency` error the conflicting requirement
+ # (the one causing the circular) won't be `conflict.requirement`
+ # (which won't be for the right state, because we won't have created it,
+ # because it's circular).
+ # We need to make sure we have that requirement in the conflict's list,
+ # otherwise we won't be able to unwind properly, so we just return all
+ # the requirements for the conflict.
+ return possible_binding_requirements if conflict.underlying_error
+
+ possibilities = search_for(conflict.requirement)
+
+ # If all the requirements together don't filter out all possibilities,
+ # then the only two requirements we need to consider are the initial one
+ # (where the dependency's version was first chosen) and the last
+ if binding_requirement_in_set?(nil, possible_binding_requirements, possibilities)
+ return [conflict.requirement, requirement_for_existing_name(name_for(conflict.requirement))].compact
+ end
+
+ # Loop through the possible binding requirements, removing each one
+ # that doesn't bind. Use a `reverse_each` as we want the earliest set of
+ # binding requirements, and don't use `reject!` as we wish to refine the
+ # array *on each iteration*.
+ binding_requirements = possible_binding_requirements.dup
+ possible_binding_requirements.reverse_each do |req|
+ next if req == conflict.requirement
+ unless binding_requirement_in_set?(req, binding_requirements, possibilities)
+ binding_requirements -= [req]
+ end
+ end
+
+ binding_requirements
+ end
- index
+ # @param [Object] requirement we wish to check
+ # @param [Array] possible_binding_requirements array of requirements
+ # @param [Array] possibilities array of possibilities the requirements will be used to filter
+ # @return [Boolean] whether or not the given requirement is required to filter
+ # out all elements of the array of possibilities.
+ def binding_requirement_in_set?(requirement, possible_binding_requirements, possibilities)
+ possibilities.any? do |poss|
+ possibility_satisfies_requirements?(poss, possible_binding_requirements - [requirement])
+ end
end
+ # @param [Object] requirement
# @return [Object] the requirement that led to `requirement` being added
# to the list of requirements.
def parent_of(requirement)
@@ -219,29 +572,27 @@ module Gem::Resolver::Molinillo
parent_state.requirement
end
+ # @param [String] name
# @return [Object] the requirement that led to a version of a possibility
# with the given name being activated.
def requirement_for_existing_name(name)
- return nil unless activated.vertex_named(name).payload
+ return nil unless vertex = activated.vertex_named(name)
+ return nil unless vertex.payload
states.find { |s| s.name == name }.requirement
end
+ # @param [Object] requirement
# @return [ResolutionState] the state whose `requirement` is the given
# `requirement`.
def find_state_for(requirement)
return nil unless requirement
- states.reverse_each.find { |i| requirement == i.requirement && i.is_a?(DependencyState) }
- end
-
- # @return [Boolean] whether or not the given state has any possibilities
- # left.
- def state_any?(state)
- state && state.possibilities.any?
+ states.find { |i| requirement == i.requirement }
end
+ # @param [Object] underlying_error
# @return [Conflict] a {Conflict} that reflects the failure to activate
# the {#possibility} in conjunction with the current {#state}
- def create_conflict
+ def create_conflict(underlying_error = nil)
vertex = activated.vertex_named(name)
locked_requirement = locked_requirement_named(name)
@@ -250,18 +601,21 @@ module Gem::Resolver::Molinillo
requirements[name_for_explicit_dependency_source] = vertex.explicit_requirements
end
requirements[name_for_locking_dependency_source] = [locked_requirement] if locked_requirement
- vertex.incoming_edges.each { |edge| (requirements[edge.origin.payload] ||= []).unshift(edge.requirement) }
+ vertex.incoming_edges.each do |edge|
+ (requirements[edge.origin.payload.latest_version] ||= []).unshift(edge.requirement)
+ end
activated_by_name = {}
- activated.each { |v| activated_by_name[v.name] = v.payload if v.payload }
+ activated.each { |v| activated_by_name[v.name] = v.payload.latest_version if v.payload }
conflicts[name] = Conflict.new(
requirement,
requirements,
- vertex.payload,
+ vertex.payload && vertex.payload.latest_version,
possibility,
locked_requirement,
requirement_trees,
- activated_by_name
+ activated_by_name,
+ underlying_error
)
end
@@ -272,6 +626,7 @@ module Gem::Resolver::Molinillo
vertex.requirements.map { |r| requirement_tree_for(r) }
end
+ # @param [Object] requirement
# @return [Array<Object>] the list of requirements that led to
# `requirement` being required.
def requirement_tree_for(requirement)
@@ -311,116 +666,47 @@ module Gem::Resolver::Molinillo
# @return [void]
def attempt_to_activate
debug(depth) { 'Attempting to activate ' + possibility.to_s }
- existing_node = activated.vertex_named(name)
- if existing_node.payload
- debug(depth) { "Found existing spec (#{existing_node.payload})" }
- attempt_to_activate_existing_spec(existing_node)
+ existing_vertex = activated.vertex_named(name)
+ if existing_vertex.payload
+ debug(depth) { "Found existing spec (#{existing_vertex.payload})" }
+ attempt_to_filter_existing_spec(existing_vertex)
else
- attempt_to_activate_new_spec
- end
- end
-
- # Attempts to activate the current {#possibility} (given that it has
- # already been activated)
- # @return [void]
- def attempt_to_activate_existing_spec(existing_node)
- existing_spec = existing_node.payload
- if requirement_satisfied_by?(requirement, activated, existing_spec)
- new_requirements = requirements.dup
- push_state_for_requirements(new_requirements, false)
- else
- return if attempt_to_swap_possibility
- create_conflict
- debug(depth) { "Unsatisfied by existing spec (#{existing_node.payload})" }
- unwind_for_conflict
- end
- end
-
- # Attempts to swp the current {#possibility} with the already-activated
- # spec with the given name
- # @return [Boolean] Whether the possibility was swapped into {#activated}
- def attempt_to_swap_possibility
- activated.tag(:swap)
- vertex = activated.vertex_named(name)
- activated.set_payload(name, possibility)
- if !vertex.requirements.
- all? { |r| requirement_satisfied_by?(r, activated, possibility) } ||
- !new_spec_satisfied?
- activated.rewind_to(:swap)
- return
- end
- fixup_swapped_children(vertex)
- activate_spec
- end
-
- # Ensures there are no orphaned successors to the given {vertex}.
- # @param [DependencyGraph::Vertex] vertex the vertex to fix up.
- # @return [void]
- def fixup_swapped_children(vertex) # rubocop:disable Metrics/CyclomaticComplexity
- payload = vertex.payload
- deps = dependencies_for(payload).group_by(&method(:name_for))
- vertex.outgoing_edges.each do |outgoing_edge|
- requirement = outgoing_edge.requirement
- parent_index = @parents_of[requirement].last
- succ = outgoing_edge.destination
- matching_deps = Array(deps[succ.name])
- dep_matched = matching_deps.include?(requirement)
-
- # only push the current index when it was originally required by the
- # same named spec
- if parent_index && states[parent_index].name == name
- @parents_of[requirement].push(states.size - 1)
+ latest = possibility.latest_version
+ possibility.possibilities.select! do |possibility|
+ requirement_satisfied_by?(requirement, activated, possibility)
end
-
- if matching_deps.empty? && !succ.root? && succ.predecessors.to_a == [vertex]
- debug(depth) { "Removing orphaned spec #{succ.name} after swapping #{name}" }
- succ.requirements.each { |r| @parents_of.delete(r) }
-
- removed_names = activated.detach_vertex_named(succ.name).map(&:name)
- requirements.delete_if do |r|
- # the only removed vertices are those with no other requirements,
- # so it's safe to delete only based upon name here
- removed_names.include?(name_for(r))
- end
- elsif !dep_matched
- debug(depth) { "Removing orphaned dependency #{requirement} after swapping #{name}" }
- # also reset if we're removing the edge, but only if its parent has
- # already been fixed up
- @parents_of[requirement].push(states.size - 1) if @parents_of[requirement].empty?
-
- activated.delete_edge(outgoing_edge)
- requirements.delete(requirement)
+ if possibility.latest_version.nil?
+ # ensure there's a possibility for better error messages
+ possibility.possibilities << latest if latest
+ create_conflict
+ unwind_for_conflict
+ else
+ activate_new_spec
end
end
end
- # Attempts to activate the current {#possibility} (given that it hasn't
- # already been activated)
+ # Attempts to update the existing vertex's `PossibilitySet` with a filtered version
# @return [void]
- def attempt_to_activate_new_spec
- if new_spec_satisfied?
- activate_spec
+ def attempt_to_filter_existing_spec(vertex)
+ filtered_set = filtered_possibility_set(vertex)
+ if !filtered_set.possibilities.empty?
+ activated.set_payload(name, filtered_set)
+ new_requirements = requirements.dup
+ push_state_for_requirements(new_requirements, false)
else
create_conflict
+ debug(depth) { "Unsatisfied by existing spec (#{vertex.payload})" }
unwind_for_conflict
end
end
- # @return [Boolean] whether the current spec is satisfied as a new
- # possibility.
- def new_spec_satisfied?
- unless requirement_satisfied_by?(requirement, activated, possibility)
- debug(depth) { 'Unsatisfied by requested spec' }
- return false
- end
-
- locked_requirement = locked_requirement_named(name)
-
- locked_spec_satisfied = !locked_requirement ||
- requirement_satisfied_by?(locked_requirement, activated, possibility)
- debug(depth) { 'Unsatisfied by locked spec' } unless locked_spec_satisfied
-
- locked_spec_satisfied
+ # Generates a filtered version of the existing vertex's `PossibilitySet` using the
+ # current state's `requirement`
+ # @param [Object] vertex existing vertex
+ # @return [PossibilitySet] filtered possibility set
+ def filtered_possibility_set(vertex)
+ PossibilitySet.new(vertex.payload.dependencies, vertex.payload.possibilities & possibility.possibilities)
end
# @param [String] requirement_name the spec name to search for
@@ -434,7 +720,7 @@ module Gem::Resolver::Molinillo
# Add the current {#possibility} to the dependency graph of the current
# {#state}
# @return [void]
- def activate_spec
+ def activate_new_spec
conflicts.delete(name)
debug(depth) { "Activated #{name} at #{possibility}" }
activated.set_payload(name, possibility)
@@ -442,14 +728,14 @@ module Gem::Resolver::Molinillo
end
# Requires the dependencies that the recently activated spec has
- # @param [Object] activated_spec the specification that has just been
+ # @param [Object] possibility_set the PossibilitySet that has just been
# activated
# @return [void]
- def require_nested_dependencies_for(activated_spec)
- nested_dependencies = dependencies_for(activated_spec)
+ def require_nested_dependencies_for(possibility_set)
+ nested_dependencies = dependencies_for(possibility_set.latest_version)
debug(depth) { "Requiring nested dependencies (#{nested_dependencies.join(', ')})" }
nested_dependencies.each do |d|
- activated.add_child_vertex(name_for(d), nil, [name_for(activated_spec)], d)
+ activated.add_child_vertex(name_for(d), nil, [name_for(possibility_set.latest_version)], d)
parent_index = states.size - 1
parents = @parents_of[d]
parents << parent_index if parents.empty?
@@ -461,23 +747,82 @@ module Gem::Resolver::Molinillo
# Pushes a new {DependencyState} that encapsulates both existing and new
# requirements
# @param [Array] new_requirements
+ # @param [Boolean] requires_sort
+ # @param [Object] new_activated
# @return [void]
def push_state_for_requirements(new_requirements, requires_sort = true, new_activated = activated)
new_requirements = sort_dependencies(new_requirements.uniq, new_activated, conflicts) if requires_sort
- new_requirement = new_requirements.shift
+ new_requirement = nil
+ loop do
+ new_requirement = new_requirements.shift
+ break if new_requirement.nil? || states.none? { |s| s.requirement == new_requirement }
+ end
new_name = new_requirement ? name_for(new_requirement) : ''.freeze
- possibilities = new_requirement ? search_for(new_requirement) : []
+ possibilities = possibilities_for_requirement(new_requirement)
handle_missing_or_push_dependency_state DependencyState.new(
new_name, new_requirements, new_activated,
- new_requirement, possibilities, depth, conflicts.dup
+ new_requirement, possibilities, depth, conflicts.dup, unused_unwind_options.dup
)
end
+ # Checks a proposed requirement with any existing locked requirement
+ # before generating an array of possibilities for it.
+ # @param [Object] requirement the proposed requirement
+ # @param [Object] activated
+ # @return [Array] possibilities
+ def possibilities_for_requirement(requirement, activated = self.activated)
+ return [] unless requirement
+ if locked_requirement_named(name_for(requirement))
+ return locked_requirement_possibility_set(requirement, activated)
+ end
+
+ group_possibilities(search_for(requirement))
+ end
+
+ # @param [Object] requirement the proposed requirement
+ # @param [Object] activated
+ # @return [Array] possibility set containing only the locked requirement, if any
+ def locked_requirement_possibility_set(requirement, activated = self.activated)
+ all_possibilities = search_for(requirement)
+ locked_requirement = locked_requirement_named(name_for(requirement))
+
+ # Longwinded way to build a possibilities array with either the locked
+ # requirement or nothing in it. Required, since the API for
+ # locked_requirement isn't guaranteed.
+ locked_possibilities = all_possibilities.select do |possibility|
+ requirement_satisfied_by?(locked_requirement, activated, possibility)
+ end
+
+ group_possibilities(locked_possibilities)
+ end
+
+ # Build an array of PossibilitySets, with each element representing a group of
+ # dependency versions that all have the same sub-dependency version constraints
+ # and are contiguous.
+ # @param [Array] possibilities an array of possibilities
+ # @return [Array<PossibilitySet>] an array of possibility sets
+ def group_possibilities(possibilities)
+ possibility_sets = []
+ current_possibility_set = nil
+
+ possibilities.reverse_each do |possibility|
+ dependencies = dependencies_for(possibility)
+ if current_possibility_set && dependencies_equal?(current_possibility_set.dependencies, dependencies)
+ current_possibility_set.possibilities.unshift(possibility)
+ else
+ possibility_sets.unshift(PossibilitySet.new(dependencies, [possibility]))
+ current_possibility_set = possibility_sets.first
+ end
+ end
+
+ possibility_sets
+ end
+
# Pushes a new {DependencyState}.
# If the {#specification_provider} says to
# {SpecificationProvider#allow_missing?} that particular requirement, and
# there are no possibilities for that requirement, then `state` is not
- # pushed, and the node in {#activated} is removed, and we continue
+ # pushed, and the vertex in {#activated} is removed, and we continue
# resolving the remaining requirements.
# @param [DependencyState] state
# @return [void]
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb
index 5c59a45c3d..d43121f8ca 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/resolver.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/resolver/molinillo/lib/molinillo/dependency_graph'
+
+require_relative 'dependency_graph'
module Gem::Resolver::Molinillo
# This class encapsulates a dependency resolver.
@@ -8,7 +9,7 @@ module Gem::Resolver::Molinillo
#
#
class Resolver
- require 'rubygems/resolver/molinillo/lib/molinillo/resolution'
+ require_relative 'resolution'
# @return [SpecificationProvider] the specification provider used
# in the resolution process
diff --git a/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb b/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb
index c20de98854..6e7c715fce 100644
--- a/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb
+++ b/lib/rubygems/resolver/molinillo/lib/molinillo/state.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
module Gem::Resolver::Molinillo
# A state that a {Resolution} can be in
# @attr [String] name the name of the current requirement
@@ -7,7 +8,8 @@ module Gem::Resolver::Molinillo
# @attr [Object] requirement the current requirement
# @attr [Object] possibilities the possibilities to satisfy the current requirement
# @attr [Integer] depth the depth of the resolution
- # @attr [Set<Object>] conflicts unresolved conflicts
+ # @attr [Hash] conflicts unresolved conflicts, indexed by dependency name
+ # @attr [Array<UnwindDetails>] unused_unwind_options unwinds for previous conflicts that weren't explored
ResolutionState = Struct.new(
:name,
:requirements,
@@ -15,14 +17,15 @@ module Gem::Resolver::Molinillo
:requirement,
:possibilities,
:depth,
- :conflicts
+ :conflicts,
+ :unused_unwind_options
)
class ResolutionState
# Returns an empty resolution state
# @return [ResolutionState] an empty state
def self.empty
- new(nil, [], DependencyGraph.new, nil, nil, 0, Set.new)
+ new(nil, [], DependencyGraph.new, nil, nil, 0, {}, [])
end
end
@@ -40,7 +43,8 @@ module Gem::Resolver::Molinillo
requirement,
[possibilities.pop],
depth + 1,
- conflicts.dup
+ conflicts.dup,
+ unused_unwind_options.dup
).tap do |state|
state.activated.tag(state)
end
diff --git a/lib/rubygems/resolver/requirement_list.rb b/lib/rubygems/resolver/requirement_list.rb
index cf0014b0bb..5b51493c9a 100644
--- a/lib/rubygems/resolver/requirement_list.rb
+++ b/lib/rubygems/resolver/requirement_list.rb
@@ -7,7 +7,6 @@
# first.
class Gem::Resolver::RequirementList
-
include Enumerable
##
@@ -79,5 +78,4 @@ class Gem::Resolver::RequirementList
x = @exact[0,5]
x + @list[0,5 - x.size]
end
-
end
diff --git a/lib/rubygems/resolver/set.rb b/lib/rubygems/resolver/set.rb
index 242f9cd3dc..5d8dd51eaa 100644
--- a/lib/rubygems/resolver/set.rb
+++ b/lib/rubygems/resolver/set.rb
@@ -4,7 +4,6 @@
# dependencies) used in resolution. This set is abstract.
class Gem::Resolver::Set
-
##
# Set to true to disable network access for this set
@@ -21,7 +20,6 @@ class Gem::Resolver::Set
attr_accessor :prerelease
def initialize # :nodoc:
- require 'uri'
@prerelease = false
@remote = true
@errors = []
@@ -53,5 +51,4 @@ class Gem::Resolver::Set
def remote? # :nodoc:
@remote
end
-
end
diff --git a/lib/rubygems/resolver/source_set.rb b/lib/rubygems/resolver/source_set.rb
index 8e799514fd..bf8c23184e 100644
--- a/lib/rubygems/resolver/source_set.rb
+++ b/lib/rubygems/resolver/source_set.rb
@@ -4,7 +4,6 @@
# Kind off like BestSet but filters the sources for gems
class Gem::Resolver::SourceSet < Gem::Resolver::Set
-
##
# Creates a SourceSet for the given +sources+ or Gem::sources if none are
# specified. +sources+ must be a Gem::SourceList.
@@ -43,5 +42,4 @@ class Gem::Resolver::SourceSet < Gem::Resolver::Set
link = @links[name]
@sets[link] ||= Gem::Source.new(link).dependency_resolver_set if link
end
-
end
diff --git a/lib/rubygems/resolver/spec_specification.rb b/lib/rubygems/resolver/spec_specification.rb
index d0e744f3a7..7b665fe876 100644
--- a/lib/rubygems/resolver/spec_specification.rb
+++ b/lib/rubygems/resolver/spec_specification.rb
@@ -4,7 +4,6 @@
# Resolver specifications that are backed by a Gem::Specification.
class Gem::Resolver::SpecSpecification < Gem::Resolver::Specification
-
##
# A SpecSpecification is created for a +set+ for a Gem::Specification in
# +spec+. The +source+ is either where the +spec+ came from, or should be
@@ -24,6 +23,20 @@ class Gem::Resolver::SpecSpecification < Gem::Resolver::Specification
end
##
+ # The required_ruby_version constraint for this specification
+
+ def required_ruby_version
+ spec.required_ruby_version
+ end
+
+ ##
+ # The required_rubygems_version constraint for this specification
+
+ def required_rubygems_version
+ spec.required_rubygems_version
+ end
+
+ ##
# The name and version of the specification.
#
# Unlike Gem::Specification#full_name, the platform is not included.
@@ -52,5 +65,4 @@ class Gem::Resolver::SpecSpecification < Gem::Resolver::Specification
def version
spec.version
end
-
end
diff --git a/lib/rubygems/resolver/specification.rb b/lib/rubygems/resolver/specification.rb
index e859d6659a..dfcb7eb057 100644
--- a/lib/rubygems/resolver/specification.rb
+++ b/lib/rubygems/resolver/specification.rb
@@ -5,7 +5,6 @@
# dependency resolution in the resolver is included.
class Gem::Resolver::Specification
-
##
# The dependencies of the gem for this specification
@@ -45,6 +44,16 @@ class Gem::Resolver::Specification
attr_reader :version
##
+ # The required_ruby_version constraint for this specification.
+
+ attr_reader :required_ruby_version
+
+ ##
+ # The required_ruby_version constraint for this specification.
+
+ attr_reader :required_rubygems_version
+
+ ##
# Sets default instance variables for the specification.
def initialize
@@ -54,6 +63,8 @@ class Gem::Resolver::Specification
@set = nil
@source = nil
@version = nil
+ @required_ruby_version = Gem::Requirement.default
+ @required_rubygems_version = Gem::Requirement.default
end
##
@@ -82,7 +93,7 @@ class Gem::Resolver::Specification
# specification.
def install(options = {})
- require 'rubygems/installer'
+ require_relative '../installer'
gem = download options
@@ -105,11 +116,10 @@ class Gem::Resolver::Specification
# Returns true if this specification is installable on this platform.
def installable_platform?
- Gem::Platform.match spec.platform
+ Gem::Platform.match_spec? spec
end
def local? # :nodoc:
false
end
-
end
diff --git a/lib/rubygems/resolver/stats.rb b/lib/rubygems/resolver/stats.rb
index 5f41940b1e..64b458f504 100644
--- a/lib/rubygems/resolver/stats.rb
+++ b/lib/rubygems/resolver/stats.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
class Gem::Resolver::Stats
-
def initialize
@max_depth = 0
@max_requirements = 0
@@ -43,5 +42,4 @@ class Gem::Resolver::Stats
$stdout.printf PATTERN, "Backtracking #", @backtracking
$stdout.printf PATTERN, "Iteration #", @iterations
end
-
end
diff --git a/lib/rubygems/resolver/vendor_set.rb b/lib/rubygems/resolver/vendor_set.rb
index 7e2e917d5c..48c640d8c9 100644
--- a/lib/rubygems/resolver/vendor_set.rb
+++ b/lib/rubygems/resolver/vendor_set.rb
@@ -15,7 +15,6 @@
# rake.gemspec (watching the given name).
class Gem::Resolver::VendorSet < Gem::Resolver::Set
-
##
# The specifications for this set.
@@ -83,5 +82,4 @@ class Gem::Resolver::VendorSet < Gem::Resolver::Set
end
end
end
-
end
diff --git a/lib/rubygems/resolver/vendor_specification.rb b/lib/rubygems/resolver/vendor_specification.rb
index 56f2e6eb2c..8dfe5940f2 100644
--- a/lib/rubygems/resolver/vendor_specification.rb
+++ b/lib/rubygems/resolver/vendor_specification.rb
@@ -5,7 +5,6 @@
# option.
class Gem::Resolver::VendorSpecification < Gem::Resolver::SpecSpecification
-
def ==(other) # :nodoc:
self.class === other and
@set == other.set and
@@ -20,5 +19,4 @@ class Gem::Resolver::VendorSpecification < Gem::Resolver::SpecSpecification
def install(options = {})
yield nil
end
-
end
diff --git a/lib/rubygems/s3_uri_signer.rb b/lib/rubygems/s3_uri_signer.rb
index 534b8676a0..4d1deee997 100644
--- a/lib/rubygems/s3_uri_signer.rb
+++ b/lib/rubygems/s3_uri_signer.rb
@@ -1,14 +1,10 @@
-require 'base64'
-require 'digest'
-require 'openssl'
+require_relative 'openssl'
##
# S3URISigner implements AWS SigV4 for S3 Source to avoid a dependency on the aws-sdk-* gems
# More on AWS SigV4: https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html
class Gem::S3URISigner
-
class ConfigurationError < Gem::Exception
-
def initialize(message)
super message
end
@@ -16,11 +12,9 @@ class Gem::S3URISigner
def to_s # :nodoc:
"#{super}"
end
-
end
class InstanceProfileError < Gem::Exception
-
def initialize(message)
super message
end
@@ -28,7 +22,6 @@ class Gem::S3URISigner
def to_s # :nodoc:
"#{super}"
end
-
end
attr_accessor :uri
@@ -93,7 +86,7 @@ class Gem::S3URISigner
"AWS4-HMAC-SHA256",
date_time,
credential_info,
- Digest::SHA256.hexdigest(canonical_request)
+ OpenSSL::Digest::SHA256.hexdigest(canonical_request),
].join("\n")
end
@@ -146,8 +139,8 @@ class Gem::S3URISigner
def ec2_metadata_credentials_json
require 'net/http'
- require 'rubygems/request'
- require 'rubygems/request/connection_pools'
+ require_relative 'request'
+ require_relative 'request/connection_pools'
require 'json'
iam_info = ec2_metadata_request(EC2_IAM_INFO)
@@ -179,5 +172,4 @@ class Gem::S3URISigner
BASE64_URI_TRANSLATE = { "+" => "%2B", "/" => "%2F", "=" => "%3D", "\n" => "" }.freeze
EC2_IAM_INFO = "http://169.254.169.254/latest/meta-data/iam/info".freeze
EC2_IAM_SECURITY_CREDENTIALS = "http://169.254.169.254/latest/meta-data/iam/security-credentials/".freeze
-
end
diff --git a/lib/rubygems/safe_yaml.rb b/lib/rubygems/safe_yaml.rb
index 3540fd74dd..e905052e1c 100644
--- a/lib/rubygems/safe_yaml.rb
+++ b/lib/rubygems/safe_yaml.rb
@@ -7,7 +7,7 @@ module Gem
# Psych.safe_load
module SafeYAML
- PERMITTED_CLASSES = %w(
+ PERMITTED_CLASSES = %w[
Symbol
Time
Date
@@ -17,14 +17,12 @@ module Gem
Gem::Specification
Gem::Version
Gem::Version::Requirement
- YAML::Syck::DefaultKey
- Syck::DefaultKey
- ).freeze
+ ].freeze
- PERMITTED_SYMBOLS = %w(
+ PERMITTED_SYMBOLS = %w[
development
runtime
- ).freeze
+ ].freeze
if ::YAML.respond_to? :safe_load
def self.safe_load(input)
diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
index 7b0a0b3c6a..8240a1a059 100644
--- a/lib/rubygems/security.rb
+++ b/lib/rubygems/security.rb
@@ -5,15 +5,8 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/exceptions'
-require 'fileutils'
-
-begin
- require 'openssl'
-rescue LoadError => e
- raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
- e.message =~ / -- openssl$/
-end
+require_relative 'exceptions'
+require_relative 'openssl'
##
# = Signing gems
@@ -62,11 +55,11 @@ end
#
# $ tar tf your-gem-1.0.gem
# metadata.gz
-# metadata.gz.sum
# metadata.gz.sig # metadata signature
# data.tar.gz
-# data.tar.gz.sum
# data.tar.gz.sig # data signature
+# checksums.yaml.gz
+# checksums.yaml.gz.sig # checksums signature
#
# === Manually signing gems
#
@@ -159,8 +152,11 @@ end
# certificate for EMAIL_ADDR
# -C, --certificate CERT Signing certificate for --sign
# -K, --private-key KEY Key for --sign or --build
+# -A, --key-algorithm ALGORITHM Select key algorithm for --build from RSA, DSA, or EC. Defaults to RSA.
# -s, --sign CERT Signs CERT with the key from -K
# and the certificate from -C
+# -d, --days NUMBER_OF_DAYS Days before the certificate expires
+# -R, --re-sign Re-signs the certificate from -C with the key from -K
#
# We've already covered the <code>--build</code> option, and the
# <code>--add</code>, <code>--list</code>, and <code>--remove</code> commands
@@ -265,7 +261,7 @@ end
# 2. Grab the public key from the gemspec
#
# gem spec some_signed_gem-1.0.gem cert_chain | \
-# ruby -ryaml -e 'puts YAML.load_documents($stdin)' > public_key.crt
+# ruby -ryaml -e 'puts YAML.load($stdin)' > public_key.crt
#
# 3. Generate a SHA1 hash of the data.tar.gz
#
@@ -322,7 +318,6 @@ end
# * Honor extension restrictions
# * Might be better to store the certificate chain as a PKCS#7 or PKCS#12
# file, instead of an array embedded in the metadata.
-# * Flexible signature and key algorithms, not hard-coded to RSA and SHA1.
#
# == Original author
#
@@ -337,40 +332,24 @@ module Gem::Security
class Exception < Gem::Exception; end
##
- # Digest algorithm used to sign gems
-
- DIGEST_ALGORITHM =
- if defined?(OpenSSL::Digest::SHA256)
- OpenSSL::Digest::SHA256
- elsif defined?(OpenSSL::Digest::SHA1)
- OpenSSL::Digest::SHA1
- else
- require 'digest'
- Digest::SHA512
- end
+ # Used internally to select the signing digest from all computed digests
+
+ DIGEST_NAME = 'SHA256' # :nodoc:
##
- # Used internally to select the signing digest from all computed digests
+ # Length of keys created by RSA and DSA keys
- DIGEST_NAME = # :nodoc:
- if DIGEST_ALGORITHM.method_defined? :name
- DIGEST_ALGORITHM.new.name
- else
- DIGEST_ALGORITHM.name[/::([^:]+)\z/, 1]
- end
+ RSA_DSA_KEY_LENGTH = 3072
##
- # Algorithm for creating the key pair used to sign gems
+ # Default algorithm to use when building a key pair
- KEY_ALGORITHM =
- if defined?(OpenSSL::PKey::RSA)
- OpenSSL::PKey::RSA
- end
+ DEFAULT_KEY_ALGORITHM = 'RSA'
##
- # Length of keys created by KEY_ALGORITHM
+ # Named curve used for Elliptic Curve
- KEY_LENGTH = 3072
+ EC_NAME = 'secp384r1'
##
# Cipher used to encrypt the key pair used to sign gems.
@@ -423,7 +402,7 @@ module Gem::Security
serial = 1)
cert = OpenSSL::X509::Certificate.new
- cert.public_key = key.public_key
+ cert.public_key = get_public_key(key)
cert.version = 2
cert.serial = serial
@@ -442,6 +421,24 @@ module Gem::Security
end
##
+ # Gets the right public key from a PKey instance
+
+ def self.get_public_key(key)
+ return key.public_key unless key.is_a?(OpenSSL::PKey::EC)
+
+ ec_key = OpenSSL::PKey::EC.new(key.group.curve_name)
+ ec_key.public_key = key.public_key
+ ec_key
+ end
+
+ ##
+ # In Ruby 2.3 EC doesn't implement the private_key? but not the private? method
+
+ if defined?(OpenSSL::PKey::EC) && Gem::Version.new(String.new(RUBY_VERSION)) < Gem::Version.new("2.4.0")
+ OpenSSL::PKey::EC.send(:alias_method, :private?, :private_key?)
+ end
+
+ ##
# Creates a self-signed certificate with an issuer and subject from +email+,
# a subject alternative name of +email+ and the given +extensions+ for the
# +key+.
@@ -466,11 +463,41 @@ module Gem::Security
end
##
- # Creates a new key pair of the specified +length+ and +algorithm+. The
- # default is a 3072 bit RSA key.
+ # Creates a new digest instance using the specified +algorithm+. The default
+ # is SHA256.
+
+ if defined?(OpenSSL::Digest)
+ def self.create_digest(algorithm = DIGEST_NAME)
+ OpenSSL::Digest.new(algorithm)
+ end
+ else
+ require 'digest'
+
+ def self.create_digest(algorithm = DIGEST_NAME)
+ Digest.const_get(algorithm).new
+ end
+ end
- def self.create_key(length = KEY_LENGTH, algorithm = KEY_ALGORITHM)
- algorithm.new length
+ ##
+ # Creates a new key pair of the specified +algorithm+. RSA, DSA, and EC
+ # are supported.
+
+ def self.create_key(algorithm)
+ if defined?(OpenSSL::PKey)
+ case algorithm.downcase
+ when 'dsa'
+ OpenSSL::PKey::DSA.new(RSA_DSA_KEY_LENGTH)
+ when 'rsa'
+ OpenSSL::PKey::RSA.new(RSA_DSA_KEY_LENGTH)
+ when 'ec'
+ domain_key = OpenSSL::PKey::EC.new(EC_NAME)
+ domain_key.generate_key
+ domain_key
+ else
+ raise Gem::Security::Exception,
+ "#{algorithm} algorithm not found. RSA, DSA, and EC algorithms are supported."
+ end
+ end
end
##
@@ -483,7 +510,7 @@ module Gem::Security
dcs = dcs.split '.'
- name = "CN=#{cn}/#{dcs.map { |dc| "DC=#{dc}" }.join '/'}"
+ name = "CN=#{cn}/#{dcs.map {|dc| "DC=#{dc}" }.join '/'}"
OpenSSL::X509::Name.parse name
end
@@ -499,7 +526,7 @@ module Gem::Security
raise Gem::Security::Exception,
"incorrect signing key for re-signing " +
"#{expired_certificate.subject}" unless
- expired_certificate.public_key.to_pem == private_key.public_key.to_pem
+ expired_certificate.public_key.to_pem == get_public_key(private_key).to_pem
unless expired_certificate.subject.to_s ==
expired_certificate.issuer.to_s
@@ -526,7 +553,7 @@ module Gem::Security
##
# Sign the public key from +certificate+ with the +signing_key+ and
- # +signing_cert+, using the Gem::Security::DIGEST_ALGORITHM. Uses the
+ # +signing_cert+, using the Gem::Security::DIGEST_NAME. Uses the
# default certificate validity range and extensions.
#
# Returns the newly signed certificate.
@@ -553,7 +580,7 @@ module Gem::Security
signed = create_cert signee_subject, signee_key, age, extensions, serial
signed.issuer = signing_cert.subject
- signed.sign signing_key, Gem::Security::DIGEST_ALGORITHM.new
+ signed.sign signing_key, Gem::Security::DIGEST_NAME
end
##
@@ -598,10 +625,10 @@ module Gem::Security
end
-if defined?(OpenSSL::SSL)
- require 'rubygems/security/policy'
- require 'rubygems/security/policies'
- require 'rubygems/security/trust_dir'
+if Gem::HAVE_OPENSSL
+ require_relative 'security/policy'
+ require_relative 'security/policies'
+ require_relative 'security/trust_dir'
end
-require 'rubygems/security/signer'
+require_relative 'security/signer'
diff --git a/lib/rubygems/security/policy.rb b/lib/rubygems/security/policy.rb
index 1aa6eab18c..3c3cb647ee 100644
--- a/lib/rubygems/security/policy.rb
+++ b/lib/rubygems/security/policy.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/user_interaction'
+require_relative '../user_interaction'
##
# A Gem::Security::Policy object encapsulates the settings for verifying
@@ -8,7 +8,6 @@ require 'rubygems/user_interaction'
# Gem::Security::Policies.
class Gem::Security::Policy
-
include Gem::UserInteraction
attr_reader :name
@@ -25,8 +24,6 @@ class Gem::Security::Policy
# options.
def initialize(name, policy = {}, opt = {})
- require 'openssl'
-
@name = name
@opt = opt
@@ -76,7 +73,7 @@ class Gem::Security::Policy
def check_data(public_key, digest, signature, data)
raise Gem::Security::Exception, "invalid signature" unless
- public_key.verify digest.new, signature, data.digest
+ public_key.verify digest, signature, data.digest
true
end
@@ -118,9 +115,11 @@ class Gem::Security::Policy
raise Gem::Security::Exception, 'missing key or signature'
end
+ public_key = Gem::Security.get_public_key(key)
+
raise Gem::Security::Exception,
"certificate #{signer.subject} does not match the signing key" unless
- signer.public_key.to_pem == key.public_key.to_pem
+ signer.public_key.to_pem == public_key.to_pem
true
end
@@ -139,7 +138,7 @@ class Gem::Security::Policy
raise Gem::Security::Exception,
"root certificate #{root.subject} is not self-signed " +
"(issuer #{root.issuer})" if
- root.issuer.to_s != root.subject.to_s # HACK to_s is for ruby 1.8
+ root.issuer != root.subject
check_cert root, root, time
end
@@ -167,9 +166,9 @@ class Gem::Security::Policy
end
save_cert = OpenSSL::X509::Certificate.new File.read path
- save_dgst = digester.digest save_cert.public_key.to_s
+ save_dgst = digester.digest save_cert.public_key.to_pem
- pkey_str = root.public_key.to_s
+ pkey_str = root.public_key.to_pem
cert_dgst = digester.digest pkey_str
raise Gem::Security::Exception,
@@ -197,7 +196,7 @@ class Gem::Security::Policy
("[Policy: %s - data: %p signer: %p chain: %p root: %p " +
"signed-only: %p trusted-only: %p]") % [
@name, @verify_chain, @verify_data, @verify_root, @verify_signer,
- @only_signed, @only_trusted,
+ @only_signed, @only_trusted
]
end
@@ -224,7 +223,7 @@ class Gem::Security::Policy
end
opt = @opt
- digester = Gem::Security::DIGEST_ALGORITHM
+ digester = Gem::Security.create_digest
trust_dir = opt[:trust_dir]
time = Time.now
@@ -291,5 +290,4 @@ class Gem::Security::Policy
end
alias to_s name # :nodoc:
-
end
diff --git a/lib/rubygems/security/signer.rb b/lib/rubygems/security/signer.rb
index 5e4ba6ebba..968cf88973 100644
--- a/lib/rubygems/security/signer.rb
+++ b/lib/rubygems/security/signer.rb
@@ -2,10 +2,9 @@
##
# Basic OpenSSL-based package signing class.
-require "rubygems/user_interaction"
+require_relative "../user_interaction"
class Gem::Security::Signer
-
include Gem::UserInteraction
##
@@ -35,11 +34,11 @@ class Gem::Security::Signer
attr_reader :options
DEFAULT_OPTIONS = {
- expiration_length_days: 365
+ expiration_length_days: 365,
}.freeze
##
- # Attemps to re-sign an expired cert with a given private key
+ # Attempts to re-sign an expired cert with a given private key
def self.re_sign_cert(expired_cert, expired_cert_path, private_key)
return unless expired_cert.not_after < Time.now
@@ -81,11 +80,11 @@ class Gem::Security::Signer
@cert_chain = [default_cert] if File.exist? default_cert
end
- @digest_algorithm = Gem::Security::DIGEST_ALGORITHM
@digest_name = Gem::Security::DIGEST_NAME
+ @digest_algorithm = Gem::Security.create_digest(@digest_name)
- if @key && !@key.is_a?(OpenSSL::PKey::RSA)
- @key = OpenSSL::PKey::RSA.new(File.read(@key), @passphrase)
+ if @key && !@key.is_a?(OpenSSL::PKey::PKey)
+ @key = OpenSSL::PKey.read(File.read(@key), @passphrase)
end
if @cert_chain
@@ -106,10 +105,10 @@ class Gem::Security::Signer
# this value is preferred, otherwise the subject is used.
def extract_name(cert) # :nodoc:
- subject_alt_name = cert.extensions.find { |e| 'subjectAltName' == e.oid }
+ subject_alt_name = cert.extensions.find {|e| 'subjectAltName' == e.oid }
if subject_alt_name
- /\Aemail:/ =~ subject_alt_name.value
+ /\Aemail:/ =~ subject_alt_name.value # rubocop:disable Performance/StartWith
$' || subject_alt_name.value
else
@@ -178,8 +177,7 @@ class Gem::Security::Signer
disk_cert = File.read(disk_cert_path) rescue nil
disk_key_path = File.join(Gem.default_key_path)
- disk_key =
- OpenSSL::PKey::RSA.new(File.read(disk_key_path), @passphrase) rescue nil
+ disk_key = OpenSSL::PKey.read(File.read(disk_key_path), @passphrase) rescue nil
return unless disk_key
@@ -202,5 +200,4 @@ class Gem::Security::Signer
end
end
end
-
end
diff --git a/lib/rubygems/security/trust_dir.rb b/lib/rubygems/security/trust_dir.rb
index 98031ea22b..456947274c 100644
--- a/lib/rubygems/security/trust_dir.rb
+++ b/lib/rubygems/security/trust_dir.rb
@@ -4,7 +4,6 @@
# verification.
class Gem::Security::TrustDir
-
##
# Default permissions for the trust directory and its contents
@@ -26,7 +25,7 @@ class Gem::Security::TrustDir
@dir = dir
@permissions = permissions
- @digester = Gem::Security::DIGEST_ALGORITHM
+ @digester = Gem::Security.create_digest
end
##
@@ -105,6 +104,7 @@ class Gem::Security::TrustDir
# permissions.
def verify
+ require 'fileutils'
if File.exist? @dir
raise Gem::Security::Exception,
"trust directory #{@dir} is not a directory" unless
@@ -115,5 +115,4 @@ class Gem::Security::TrustDir
FileUtils.mkdir_p @dir, :mode => @permissions[:trust_dir]
end
end
-
end
diff --git a/lib/rubygems/security_option.rb b/lib/rubygems/security_option.rb
index 3403aaaf05..a4c570ded5 100644
--- a/lib/rubygems/security_option.rb
+++ b/lib/rubygems/security_option.rb
@@ -5,7 +5,7 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
+require_relative '../rubygems'
# forward-declare
@@ -19,16 +19,16 @@ end
module Gem::SecurityOption
def add_security_option
- OptionParser.accept Gem::Security::Policy do |value|
- require 'rubygems/security'
+ Gem::OptionParser.accept Gem::Security::Policy do |value|
+ require_relative 'security'
- raise OptionParser::InvalidArgument, 'OpenSSL not installed' unless
+ raise Gem::OptionParser::InvalidArgument, 'OpenSSL not installed' unless
defined?(Gem::Security::HighSecurity)
policy = Gem::Security::Policies[value]
unless policy
valid = Gem::Security::Policies.keys.sort
- raise OptionParser::InvalidArgument, "#{value} (#{valid.join ', '} are valid)"
+ raise Gem::OptionParser::InvalidArgument, "#{value} (#{valid.join ', '} are valid)"
end
policy
end
diff --git a/lib/rubygems/server.rb b/lib/rubygems/server.rb
index 83d7cf5abc..45be05bcda 100644
--- a/lib/rubygems/server.rb
+++ b/lib/rubygems/server.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'webrick'
require 'zlib'
require 'erb'
require 'uri'
-require 'rubygems'
-require 'rubygems/rdoc'
+require_relative '../rubygems'
+require_relative 'rdoc'
##
# Gem::Server and allows users to serve gems for consumption by
@@ -29,7 +28,6 @@ require 'rubygems/rdoc'
# TODO Refactor into a real WEBrick servlet to remove code duplication.
class Gem::Server
-
attr_reader :spec_dirs
include ERB::Util
@@ -430,6 +428,12 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
end
def initialize(gem_dirs, port, daemon, launch = nil, addresses = nil)
+ begin
+ require 'webrick'
+ rescue LoadError
+ abort "webrick is not found. You may need to `gem install webrick` to install webrick."
+ end
+
Gem::RDoc.load_rdoc
Socket.do_not_reverse_lookup = true
@@ -442,8 +446,8 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
logger = WEBrick::Log.new nil, WEBrick::BasicLog::FATAL
@server = WEBrick::HTTPServer.new :DoNotListen => true, :Logger => logger
- @spec_dirs = @gem_dirs.map { |gem_dir| File.join gem_dir, 'specifications' }
- @spec_dirs.reject! { |spec_dir| !File.directory? spec_dir }
+ @spec_dirs = @gem_dirs.map {|gem_dir| File.join gem_dir, 'specifications' }
+ @spec_dirs.reject! {|spec_dir| !File.directory? spec_dir }
reset_gems
@@ -458,7 +462,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
def uri_encode(str)
str.gsub(URI::UNSAFE) do |match|
- match.each_byte.map { |c| sprintf('%%%02X', c.ord) }.join
+ match.each_byte.map {|c| sprintf('%%%02X', c.ord) }.join
end
end
@@ -573,7 +577,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
add_date res
case req.request_uri.path
- when %r|^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)\.gemspec\.rz$| then
+ when %r{^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)\.gemspec\.rz$} then
marshal_format, full_name = $1, $2
specs = Gem::Specification.find_all_by_full_name(full_name)
@@ -615,11 +619,11 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
}
end
- deps = deps.sort_by { |dep| [dep["name"].downcase, dep["version"]] }
+ deps = deps.sort_by {|dep| [dep["name"].downcase, dep["version"]] }
deps.last["is_last"] = true unless deps.empty?
# executables
- executables = spec.executables.sort.collect { |exec| {"executable" => exec} }
+ executables = spec.executables.sort.collect {|exec| {"executable" => exec} }
executables = nil if executables.empty?
executables.last["is_last"] = true if executables
@@ -668,7 +672,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
"version" => Gem::VERSION,
}
- specs = specs.sort_by { |spec| [spec["name"].downcase, spec["version"]] }
+ specs = specs.sort_by {|spec| [spec["name"].downcase, spec["version"]] }
specs.last["is_last"] = true
# tag all specs with first_name_entry
@@ -772,7 +776,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
doc_items << {
:name => base_name,
:url => doc_root(new_path),
- :summary => ''
+ :summary => '',
}
end
@@ -869,11 +873,10 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
listeners = @server.listeners.map{|l| l.addr[2] }
# TODO: 0.0.0.0 == any, not localhost.
- host = listeners.any?{|l| l == '0.0.0.0'} ? 'localhost' : listeners.first
+ host = listeners.any?{|l| l == '0.0.0.0' } ? 'localhost' : listeners.first
say "Launching browser to http://#{host}:#{@port}"
system("#{@launch} http://#{host}:#{@port}")
end
-
end
diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb
index 8572cb1806..b5bd6b80e6 100644
--- a/lib/rubygems/source.rb
+++ b/lib/rubygems/source.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
-autoload :FileUtils, 'fileutils'
-require "rubygems/text"
+require_relative "text"
##
# A Source knows how to list and fetch gems from a RubyGems marshal index.
#
@@ -9,7 +8,6 @@ require "rubygems/text"
# bundler dependency API and so-forth.
class Gem::Source
-
include Comparable
include Gem::Text
@@ -81,7 +79,15 @@ class Gem::Source
def dependency_resolver_set # :nodoc:
return Gem::Resolver::IndexSet.new self if 'file' == uri.scheme
- bundler_api_uri = uri + './api/v1/dependencies'
+ fetch_uri = if uri.host == "rubygems.org"
+ index_uri = uri.dup
+ index_uri.host = "index.rubygems.org"
+ index_uri
+ else
+ uri
+ end
+
+ bundler_api_uri = enforce_trailing_slash(fetch_uri)
begin
fetcher = Gem::RemoteFetcher.fetcher
@@ -89,11 +95,7 @@ class Gem::Source
rescue Gem::RemoteFetcher::FetchError
Gem::Resolver::IndexSet.new self
else
- if response.respond_to? :uri
- Gem::Resolver::APISet.new response.uri
- else
- Gem::Resolver::APISet.new bundler_api_uri
- end
+ Gem::Resolver::APISet.new response.uri + "./info/"
end
end
@@ -132,7 +134,7 @@ class Gem::Source
spec_file_name = name_tuple.spec_name
- source_uri = uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}"
+ source_uri = enforce_trailing_slash(uri) + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}"
cache_dir = cache_dir source_uri
@@ -150,6 +152,7 @@ class Gem::Source
spec = Gem::Util.inflate spec
if update_cache?
+ require "fileutils"
FileUtils.mkdir_p cache_dir
File.open local_spec, 'wb' do |io|
@@ -176,12 +179,15 @@ class Gem::Source
file = FILES[type]
fetcher = Gem::RemoteFetcher.fetcher
file_name = "#{file}.#{Gem.marshal_version}"
- spec_path = uri + "#{file_name}.gz"
+ spec_path = enforce_trailing_slash(uri) + "#{file_name}.gz"
cache_dir = cache_dir spec_path
local_file = File.join(cache_dir, file_name)
retried = false
- FileUtils.mkdir_p cache_dir if update_cache?
+ if update_cache?
+ require "fileutils"
+ FileUtils.mkdir_p cache_dir
+ end
spec_dump = fetcher.cache_update_path spec_path, local_file, update_cache?
@@ -222,14 +228,19 @@ class Gem::Source
def typo_squatting?(host, distance_threshold=4)
return if @uri.host.nil?
- levenshtein_distance(@uri.host, host) <= distance_threshold
+ levenshtein_distance(@uri.host, host).between? 1, distance_threshold
end
+ private
+
+ def enforce_trailing_slash(uri)
+ uri.merge(uri.path.gsub(/\/+$/, '') + '/')
+ end
end
-require 'rubygems/source/git'
-require 'rubygems/source/installed'
-require 'rubygems/source/specific_file'
-require 'rubygems/source/local'
-require 'rubygems/source/lock'
-require 'rubygems/source/vendor'
+require_relative 'source/git'
+require_relative 'source/installed'
+require_relative 'source/specific_file'
+require_relative 'source/local'
+require_relative 'source/lock'
+require_relative 'source/vendor'
diff --git a/lib/rubygems/source/git.rb b/lib/rubygems/source/git.rb
index 0b8a4339cc..cda5aa8073 100644
--- a/lib/rubygems/source/git.rb
+++ b/lib/rubygems/source/git.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-require 'rubygems/util'
##
# A git gem for use in a gem dependencies file.
@@ -12,7 +11,6 @@ require 'rubygems/util'
# source.specs
class Gem::Source::Git < Gem::Source
-
##
# The name of the gem created by this git gem.
@@ -103,9 +101,11 @@ class Gem::Source::Git < Gem::Source
success = system @git, 'reset', '--quiet', '--hard', rev_parse
- success &&=
- Gem::Util.silent_system @git, 'submodule', 'update',
- '--quiet', '--init', '--recursive' if @need_submodules
+ if @need_submodules
+ _, status = Open3.capture2e(@git, 'submodule', 'update', '--quiet', '--init', '--recursive')
+
+ success &&= status.success?
+ end
success
end
@@ -225,17 +225,16 @@ class Gem::Source::Git < Gem::Source
# A hash for the git gem based on the git repository URI.
def uri_hash # :nodoc:
- require 'digest' # required here to avoid deadlocking in Gem.activate_bin_path (because digest is a gem on 2.5+)
+ require_relative '../openssl'
normalized =
- if @repository =~ %r%^\w+://(\w+@)?%
- uri = URI(@repository).normalize.to_s.sub %r%/$%,''
+ if @repository =~ %r{^\w+://(\w+@)?}
+ uri = URI(@repository).normalize.to_s.sub %r{/$},''
uri.sub(/\A(\w+)/) { $1.downcase }
else
@repository
end
- Digest::SHA1.hexdigest normalized
+ OpenSSL::Digest::SHA1.hexdigest normalized
end
-
end
diff --git a/lib/rubygems/source/installed.rb b/lib/rubygems/source/installed.rb
index 8e20cbd76d..7e1dd7af5a 100644
--- a/lib/rubygems/source/installed.rb
+++ b/lib/rubygems/source/installed.rb
@@ -3,7 +3,6 @@
# Represents an installed gem. This is used for dependency resolution.
class Gem::Source::Installed < Gem::Source
-
def initialize # :nodoc:
@uri = nil
end
@@ -36,5 +35,4 @@ class Gem::Source::Installed < Gem::Source
def pretty_print(q) # :nodoc:
q.text '[Installed]'
end
-
end
diff --git a/lib/rubygems/source/local.rb b/lib/rubygems/source/local.rb
index 875e992d85..078b06203f 100644
--- a/lib/rubygems/source/local.rb
+++ b/lib/rubygems/source/local.rb
@@ -4,7 +4,6 @@
# dependencies.
class Gem::Source::Local < Gem::Source
-
def initialize # :nodoc:
@specs = nil
@api_uri = nil
@@ -61,7 +60,7 @@ class Gem::Source::Local < Gem::Source
when :latest
tup = pkg.spec.name_tuple
- cur = names.find { |x| x.name == tup.name }
+ cur = names.find {|x| x.name == tup.name }
if !cur
names << tup
elsif cur.version < tup.version
@@ -98,7 +97,7 @@ class Gem::Source::Local < Gem::Source
end
end
- found.max_by { |s| s.version }
+ found.max_by {|s| s.version }
end
def fetch_spec(name) # :nodoc:
@@ -129,5 +128,4 @@ class Gem::Source::Local < Gem::Source
end
end
end
-
end
diff --git a/lib/rubygems/source/lock.rb b/lib/rubygems/source/lock.rb
index 3b3f491750..49f097467b 100644
--- a/lib/rubygems/source/lock.rb
+++ b/lib/rubygems/source/lock.rb
@@ -5,7 +5,6 @@
# dependency lock files.
class Gem::Source::Lock < Gem::Source
-
##
# The wrapped Gem::Source
@@ -48,5 +47,4 @@ class Gem::Source::Lock < Gem::Source
def uri # :nodoc:
@wrapped.uri
end
-
end
diff --git a/lib/rubygems/source/specific_file.rb b/lib/rubygems/source/specific_file.rb
index a22772b9c0..24db1440dd 100644
--- a/lib/rubygems/source/specific_file.rb
+++ b/lib/rubygems/source/specific_file.rb
@@ -4,7 +4,6 @@
# local gems.
class Gem::Source::SpecificFile < Gem::Source
-
##
# The path to the gem for this specific file.
@@ -69,5 +68,4 @@ class Gem::Source::SpecificFile < Gem::Source
super
end
end
-
end
diff --git a/lib/rubygems/source/vendor.rb b/lib/rubygems/source/vendor.rb
index a87fa63331..543acf1388 100644
--- a/lib/rubygems/source/vendor.rb
+++ b/lib/rubygems/source/vendor.rb
@@ -3,7 +3,6 @@
# This represents a vendored source that is similar to an installed gem.
class Gem::Source::Vendor < Gem::Source::Installed
-
##
# Creates a new Vendor source for a gem that was unpacked at +path+.
@@ -23,5 +22,4 @@ class Gem::Source::Vendor < Gem::Source::Installed
nil
end
end
-
end
diff --git a/lib/rubygems/source_list.rb b/lib/rubygems/source_list.rb
index b1d1f2c362..13b25b63dc 100644
--- a/lib/rubygems/source_list.rb
+++ b/lib/rubygems/source_list.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-require 'rubygems/source'
##
# The SourceList represents the sources rubygems has been configured to use.
@@ -15,7 +14,6 @@ require 'rubygems/source'
# The most common way to get a SourceList is Gem.sources.
class Gem::SourceList
-
include Enumerable
##
@@ -90,7 +88,7 @@ class Gem::SourceList
# Yields each source URI in the list.
def each
- @sources.each { |s| yield s.uri.to_s }
+ @sources.each {|s| yield s.uri.to_s }
end
##
@@ -115,7 +113,7 @@ class Gem::SourceList
# Returns an Array of source URI Strings.
def to_a
- @sources.map { |x| x.uri.to_s }
+ @sources.map {|x| x.uri.to_s }
end
alias_method :to_ary, :to_a
@@ -135,7 +133,7 @@ class Gem::SourceList
if other.kind_of? Gem::Source
@sources.include? other
else
- @sources.find { |x| x.uri.to_s == other.to_s }
+ @sources.find {|x| x.uri.to_s == other.to_s }
end
end
@@ -146,8 +144,7 @@ class Gem::SourceList
if source.kind_of? Gem::Source
@sources.delete source
else
- @sources.delete_if { |x| x.uri.to_s == source.to_s }
+ @sources.delete_if {|x| x.uri.to_s == source.to_s }
end
end
-
end
diff --git a/lib/rubygems/source_local.rb b/lib/rubygems/source_local.rb
deleted file mode 100644
index 5107069fd0..0000000000
--- a/lib/rubygems/source_local.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# frozen_string_literal: true
-require 'rubygems/source'
-require 'rubygems/source_local'
-
-unless Gem::Deprecate.skip
- Kernel.warn "#{Gem.location_of_caller(3).join(':')}: Warning: Requiring rubygems/source_local is deprecated; please use rubygems/source/local instead."
-end
diff --git a/lib/rubygems/source_specific_file.rb b/lib/rubygems/source_specific_file.rb
deleted file mode 100644
index b676b1d3a2..0000000000
--- a/lib/rubygems/source_specific_file.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-require 'rubygems/source/specific_file'
-
-unless Gem::Deprecate.skip
- Kernel.warn "#{Gem.location_of_caller(3).join(':')}: Warning: Requiring rubygems/source_specific_file is deprecated; please use rubygems/source/specific_file instead."
-end
diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb
index cf86b72188..68ff605a83 100644
--- a/lib/rubygems/spec_fetcher.rb
+++ b/lib/rubygems/spec_fetcher.rb
@@ -1,15 +1,14 @@
# frozen_string_literal: true
-require 'rubygems/remote_fetcher'
-require 'rubygems/user_interaction'
-require 'rubygems/errors'
-require 'rubygems/text'
-require 'rubygems/name_tuple'
+require_relative 'remote_fetcher'
+require_relative 'user_interaction'
+require_relative 'errors'
+require_relative 'text'
+require_relative 'name_tuple'
##
# SpecFetcher handles metadata updates from remote gem repositories.
class Gem::SpecFetcher
-
include Gem::UserInteraction
include Gem::Text
@@ -92,14 +91,14 @@ class Gem::SpecFetcher
list.each do |source, specs|
if dependency.name.is_a?(String) && specs.respond_to?(:bsearch)
- start_index = (0 ... specs.length).bsearch{ |i| specs[i].name >= dependency.name }
- end_index = (0 ... specs.length).bsearch{ |i| specs[i].name > dependency.name }
+ start_index = (0 ... specs.length).bsearch{|i| specs[i].name >= dependency.name }
+ end_index = (0 ... specs.length).bsearch{|i| specs[i].name > dependency.name }
specs = specs[start_index ... end_index] if start_index && end_index
end
found[source] = specs.select do |tup|
if dependency.match?(tup)
- if matching_platform and !Gem::Platform.match(tup.platform)
+ if matching_platform and !Gem::Platform.match_gem?(tup.platform, tup.name)
pm = (
rejected_specs[dependency] ||= \
Gem::PlatformMismatch.new(tup.name, tup.version))
@@ -122,7 +121,7 @@ class Gem::SpecFetcher
end
end
- tuples = tuples.sort_by { |x| x[0] }
+ tuples = tuples.sort_by {|x| x[0] }
return [tuples, errors]
end
@@ -171,30 +170,33 @@ class Gem::SpecFetcher
# Suggests gems based on the supplied +gem_name+. Returns an array of
# alternative gem names.
- def suggest_gems_from_name(gem_name, type = :latest)
+ def suggest_gems_from_name(gem_name, type = :latest, num_results = 5)
gem_name = gem_name.downcase.tr('_-', '')
max = gem_name.size / 2
names = available_specs(type).first.values.flatten(1)
matches = names.map do |n|
next unless n.match_platform?
-
- distance = levenshtein_distance gem_name, n.name.downcase.tr('_-', '')
-
- next if distance >= max
-
- return [n.name] if distance == 0
-
- [n.name, distance]
+ [n.name, 0] if n.name.downcase.tr('_-', '').include?(gem_name)
end.compact
+ if matches.length < num_results
+ matches += names.map do |n|
+ next unless n.match_platform?
+ distance = levenshtein_distance gem_name, n.name.downcase.tr('_-', '')
+ next if distance >= max
+ return [n.name] if distance == 0
+ [n.name, distance]
+ end.compact
+ end
+
matches = if matches.empty? && type != :prerelease
suggest_gems_from_name gem_name, :prerelease
else
- matches.uniq.sort_by { |name, dist| dist }
+ matches.uniq.sort_by {|name, dist| dist }
end
- matches.first(5).map { |name, dist| name }
+ matches.map {|name, dist| name }.uniq.first(num_results)
end
##
@@ -251,10 +253,9 @@ class Gem::SpecFetcher
def tuples_for(source, type, gracefully_ignore=false) # :nodoc:
@caches[type][source.uri] ||=
- source.load_specs(type).sort_by { |tup| tup.name }
+ source.load_specs(type).sort_by {|tup| tup.name }
rescue Gem::RemoteFetcher::FetchError
raise unless gracefully_ignore
[]
end
-
end
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index f925480f88..b493a47ef0 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -6,14 +6,11 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/version'
-require 'rubygems/requirement'
-require 'rubygems/platform'
-require 'rubygems/deprecate'
-require 'rubygems/basic_specification'
-require 'rubygems/stub_specification'
-require 'rubygems/specification_policy'
-require 'rubygems/util/list'
+require_relative 'deprecate'
+require_relative 'basic_specification'
+require_relative 'stub_specification'
+require_relative 'specification_policy'
+require_relative 'util/list'
##
# The Specification class contains the information for a gem. Typically
@@ -37,7 +34,6 @@ require 'rubygems/util/list'
# items you may add to a specification.
class Gem::Specification < Gem::BasicSpecification
-
extend Gem::Deprecate
# REFACTOR: Consider breaking out this version stuff into a separate
@@ -81,18 +77,18 @@ class Gem::Specification < Gem::BasicSpecification
-1 => ['(RubyGems versions up to and including 0.7 did not have versioned specifications)'],
1 => [
'Deprecated "test_suite_file" in favor of the new, but equivalent, "test_files"',
- '"test_file=x" is a shortcut for "test_files=[x]"'
+ '"test_file=x" is a shortcut for "test_files=[x]"',
],
2 => [
'Added "required_rubygems_version"',
'Now forward-compatible with future versions',
],
3 => [
- 'Added Fixnum validation to the specification_version'
+ 'Added Fixnum validation to the specification_version',
],
4 => [
- 'Added sandboxed freeform metadata to the specification version.'
- ]
+ 'Added sandboxed freeform metadata to the specification version.',
+ ],
}.freeze
MARSHAL_FIELDS = { # :nodoc:
@@ -106,12 +102,8 @@ class Gem::Specification < Gem::BasicSpecification
today = Time.now.utc
TODAY = Time.utc(today.year, today.month, today.day) # :nodoc:
- # rubocop:disable Style/MutableConstant
- LOAD_CACHE = {} # :nodoc:
- # rubocop:enable Style/MutableConstant
- LOAD_CACHE_MUTEX = Mutex.new
-
- private_constant :LOAD_CACHE if defined? private_constant
+ @load_cache = {} # :nodoc:
+ @load_cache_mutex = Thread::Mutex.new
VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/.freeze # :nodoc:
@@ -180,18 +172,29 @@ class Gem::Specification < Gem::BasicSpecification
end
end
- @@attributes = @@default_value.keys.sort_by { |s| s.to_s }
- @@array_attributes = @@default_value.reject { |k,v| v != [] }.keys
+ @@attributes = @@default_value.keys.sort_by {|s| s.to_s }
+ @@array_attributes = @@default_value.reject {|k,v| v != [] }.keys
@@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition do |k|
@@default_value[k].nil?
end
- @@stubs_by_name = {}
+ def self.clear_specs # :nodoc:
+ @@all_specs_mutex.synchronize do
+ @@all = nil
+ @@stubs = nil
+ @@stubs_by_name = {}
+ @@spec_with_requirable_file = {}
+ @@active_stub_with_requirable_file = {}
+ end
+ end
+ private_class_method :clear_specs
+
+ @@all_specs_mutex = Thread::Mutex.new
+
+ clear_specs
# Sentinel object to represent "not found" stubs
NOT_FOUND = Struct.new(:to_spec, :this).new # :nodoc:
- @@spec_with_requirable_file = {}
- @@active_stub_with_requirable_file = {}
# Tracking removed method calls to warn users during build time.
REMOVED_METHODS = [:rubyforge_project=].freeze # :nodoc:
@@ -249,12 +252,11 @@ class Gem::Specification < Gem::BasicSpecification
# require 'rake'
# spec.files = FileList['lib/**/*.rb',
# 'bin/*',
- # '[A-Z]*',
- # 'test/**/*'].to_a
+ # '[A-Z]*'].to_a
#
# # or without Rake...
# spec.files = Dir['lib/**/*.rb'] + Dir['bin/*']
- # spec.files += Dir['[A-Z]*'] + Dir['test/**/*']
+ # spec.files += Dir['[A-Z]*']
# spec.files.reject! { |fn| fn.include? "CVS" }
def files
@@ -286,6 +288,15 @@ class Gem::Specification < Gem::BasicSpecification
# :section: Recommended gemspec attributes
##
+ # The version of Ruby required by this gem
+ #
+ # Usage:
+ #
+ # spec.required_ruby_version = '>= 2.7.0'
+
+ attr_reader :required_ruby_version
+
+ ##
# A long description of this gem
#
# The description should be more detailed than the summary but not
@@ -328,17 +339,21 @@ class Gem::Specification < Gem::BasicSpecification
# This should just be the name of your license. The full text of the license
# should be inside of the gem (at the top level) when you build it.
#
- # The simplest way, is to specify the standard SPDX ID
+ # The simplest way is to specify the standard SPDX ID
# https://spdx.org/licenses/ for the license.
- # Ideally you should pick one that is OSI (Open Source Initiative)
+ # Ideally, you should pick one that is OSI (Open Source Initiative)
# http://opensource.org/licenses/alphabetical approved.
#
- # The most commonly used OSI approved licenses are MIT and Apache-2.0.
+ # The most commonly used OSI-approved licenses are MIT and Apache-2.0.
# GitHub also provides a license picker at http://choosealicense.com/.
#
+ # You can also use a custom license file along with your gemspec and specify
+ # a LicenseRef-<idstring>, where idstring is the name of the file containing
+ # the license text.
+ #
# You should specify a license for your gem so that people know how they are
- # permitted to use it, and any restrictions you're placing on it. Not
- # specifying a license means all rights are reserved; others have no rights
+ # permitted to use it and any restrictions you're placing on it. Not
+ # specifying a license means all rights are reserved; others have no right
# to use the code for any purpose.
#
# You can set multiple licenses with #licenses=
@@ -390,6 +405,7 @@ class Gem::Specification < Gem::BasicSpecification
# "mailing_list_uri" => "https://groups.example.com/bestgemever",
# "source_code_uri" => "https://example.com/user/bestgemever",
# "wiki_uri" => "https://example.com/user/bestgemever/wiki"
+ # "funding_uri" => "https://example.com/donate"
# }
#
# These links will be used on your gem's page on rubygems.org and must pass
@@ -516,11 +532,6 @@ class Gem::Specification < Gem::BasicSpecification
end
##
- # The version of Ruby required by this gem
-
- attr_reader :required_ruby_version
-
- ##
# The RubyGems version required by this gem
attr_reader :required_rubygems_version
@@ -560,6 +571,10 @@ class Gem::Specification < Gem::BasicSpecification
# spec.add_runtime_dependency 'example', '~> 1.1', '>= 1.1.4'
def add_runtime_dependency(gem, *requirements)
+ if requirements.uniq.size != requirements.size
+ warn "WARNING: duplicated #{gem} dependency #{requirements}"
+ end
+
add_dependency_with_type(gem, :runtime, requirements)
end
@@ -665,6 +680,9 @@ class Gem::Specification < Gem::BasicSpecification
#
# # Only prereleases or final releases after 2.6.0.preview2
# spec.required_ruby_version = '> 2.6.0.preview2'
+ #
+ # # This gem will work with 2.3.0 or greater, including major version 3, but lesser than 4.0.0
+ # spec.required_ruby_version = '>= 2.3', '< 4'
def required_ruby_version=(req)
@required_ruby_version = Gem::Requirement.create req
@@ -725,7 +743,7 @@ class Gem::Specification < Gem::BasicSpecification
# Deprecated: You must now specify the executable name to Gem.bin_path.
attr_writer :default_executable
- deprecate :default_executable=, :none, 2018, 12
+ rubygems_deprecate :default_executable=
##
# Allows deinstallation of gems with legacy platforms.
@@ -740,23 +758,15 @@ class Gem::Specification < Gem::BasicSpecification
attr_accessor :specification_version
def self._all # :nodoc:
- unless defined?(@@all) && @@all
- @@all = stubs.map(&:to_spec)
-
- # After a reset, make sure already loaded specs
- # are still marked as activated.
- specs = {}
- Gem.loaded_specs.each_value{|s| specs[s] = true}
- @@all.each{|s| s.activated = true if specs[s]}
- end
- @@all
+ @@all_specs_mutex.synchronize { @@all ||= Gem.loaded_specs.values | stubs.map(&:to_spec) }
end
- def self._clear_load_cache # :nodoc:
- LOAD_CACHE_MUTEX.synchronize do
- LOAD_CACHE.clear
+ def self.clear_load_cache # :nodoc:
+ @load_cache_mutex.synchronize do
+ @load_cache.clear
end
end
+ private_class_method :clear_load_cache
def self.each_gemspec(dirs) # :nodoc:
dirs.each do |dir|
@@ -767,7 +777,7 @@ class Gem::Specification < Gem::BasicSpecification
end
def self.gemspec_stubs_in(dir, pattern)
- Gem::Util.glob_files_in_dir(pattern, dir).map { |path| yield path }.select(&:valid?)
+ Gem::Util.glob_files_in_dir(pattern, dir).map {|path| yield path }.select(&:valid?)
end
private_class_method :gemspec_stubs_in
@@ -782,21 +792,11 @@ class Gem::Specification < Gem::BasicSpecification
dirs.flat_map do |dir|
base_dir = File.dirname dir
gems_dir = File.join base_dir, "gems"
- gemspec_stubs_in(dir, pattern) { |path| yield path, base_dir, gems_dir }
+ gemspec_stubs_in(dir, pattern) {|path| yield path, base_dir, gems_dir }
end
end
private_class_method :map_stubs
- def self.uniq_by(list, &block) # :nodoc:
- list.uniq(&block)
- end
- private_class_method :uniq_by
-
- def self.sort_by!(list, &block)
- list.sort_by!(&block)
- end
- private_class_method :sort_by!
-
def self.each_spec(dirs) # :nodoc:
each_gemspec(dirs) do |path|
spec = self.load path
@@ -810,11 +810,9 @@ class Gem::Specification < Gem::BasicSpecification
def self.stubs
@@stubs ||= begin
pattern = "*.gemspec"
- stubs = Gem.loaded_specs.values + installed_stubs(dirs, pattern) + default_stubs(pattern)
- stubs = uniq_by(stubs) { |stub| stub.full_name }
+ stubs = stubs_for_pattern(pattern, false)
- _resort!(stubs)
- @@stubs_by_name = stubs.select { |s| Gem::Platform.match s.platform }.group_by(&:name)
+ @@stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name)
stubs
end
end
@@ -830,8 +828,6 @@ class Gem::Specification < Gem::BasicSpecification
end
end
- EMPTY = [].freeze # :nodoc:
-
##
# Returns a Gem::StubSpecification for installed gem named +name+
# only returns stubs that match Gem.platforms
@@ -840,23 +836,32 @@ class Gem::Specification < Gem::BasicSpecification
if @@stubs
@@stubs_by_name[name] || []
else
- pattern = "#{name}-*.gemspec"
- stubs = Gem.loaded_specs.values +
- installed_stubs(dirs, pattern).select { |s| Gem::Platform.match s.platform } +
- default_stubs(pattern)
- stubs = uniq_by(stubs) { |stub| stub.full_name }.group_by(&:name)
- stubs.each_value { |v| _resort!(v) }
-
- @@stubs_by_name.merge! stubs
- @@stubs_by_name[name] ||= EMPTY
+ @@stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s|
+ s.name == name
+ end
end
end
+ ##
+ # Finds stub specifications matching a pattern from the standard locations,
+ # optionally filtering out specs not matching the current platform
+ #
+ def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc:
+ installed_stubs = installed_stubs(Gem::Specification.dirs, pattern)
+ installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform
+ stubs = installed_stubs + default_stubs(pattern)
+ stubs = stubs.uniq {|stub| stub.full_name }
+ _resort!(stubs)
+ stubs
+ end
+
def self._resort!(specs) # :nodoc:
specs.sort! do |a, b|
names = a.name <=> b.name
next names if names.nonzero?
- b.version <=> a.version
+ versions = b.version <=> a.version
+ next versions if versions.nonzero?
+ b.platform == Gem::Platform::RUBY ? -1 : 1
end
end
@@ -939,7 +944,7 @@ class Gem::Specification < Gem::BasicSpecification
def self.dirs=(dirs)
self.reset
- @@dirs = Array(dirs).map { |dir| File.join dir, "specifications" }
+ @@dirs = Array(dirs).map {|dir| File.join dir, "specifications" }
end
extend Enumerable
@@ -1022,10 +1027,7 @@ class Gem::Specification < Gem::BasicSpecification
# Return currently unresolved specs that contain the file matching +path+.
def self.find_in_unresolved(path)
- # TODO: do we need these?? Kill it
- specs = unresolved_deps.values.map { |dep| dep.to_specs }.flatten
-
- specs.find_all { |spec| spec.contains_requirable_file? path }
+ unresolved_specs.find_all {|spec| spec.contains_requirable_file? path }
end
##
@@ -1033,9 +1035,7 @@ class Gem::Specification < Gem::BasicSpecification
# specs that contain the file matching +path+.
def self.find_in_unresolved_tree(path)
- specs = unresolved_deps.values.map { |dep| dep.to_specs }.flatten
-
- specs.each do |spec|
+ unresolved_specs.each do |spec|
spec.traverse do |from_spec, dep, to_spec, trail|
if to_spec.has_conflicts? || to_spec.conficts_when_loaded_with?(trail)
:next
@@ -1048,6 +1048,11 @@ class Gem::Specification < Gem::BasicSpecification
[]
end
+ def self.unresolved_specs
+ unresolved_deps.values.map {|dep| dep.to_specs }.flatten
+ end
+ private_class_method :unresolved_specs
+
##
# Special loader for YAML files. When a Specification object is loaded
# from a YAML file, it bypasses the normal Ruby object initialization
@@ -1084,21 +1089,23 @@ class Gem::Specification < Gem::BasicSpecification
_latest_specs Gem::Specification._all, prerelease
end
+ ##
+ # Return the latest installed spec for gem +name+.
+
+ def self.latest_spec_for(name)
+ latest_specs(true).find {|installed_spec| installed_spec.name == name }
+ end
+
def self._latest_specs(specs, prerelease = false) # :nodoc:
- result = Hash.new { |h,k| h[k] = {} }
- native = {}
+ result = {}
specs.reverse_each do |spec|
next if spec.version.prerelease? unless prerelease
- native[spec.name] = spec.version if spec.platform == Gem::Platform::RUBY
- result[spec.name][spec.platform] = spec
+ result[spec.name] = spec
end
- result.map(&:last).map(&:values).flatten.reject do |spec|
- minimum = native[spec.name]
- minimum && spec.version < minimum
- end.sort_by{ |tup| tup.name }
+ result.map(&:last).flatten.sort_by{|tup| tup.name }
end
##
@@ -1107,7 +1114,7 @@ class Gem::Specification < Gem::BasicSpecification
def self.load(file)
return unless file
- _spec = LOAD_CACHE_MUTEX.synchronize { LOAD_CACHE[file] }
+ _spec = @load_cache_mutex.synchronize { @load_cache[file] }
return _spec if _spec
file = file.dup.tap(&Gem::UNTAINT)
@@ -1122,12 +1129,12 @@ class Gem::Specification < Gem::BasicSpecification
if Gem::Specification === _spec
_spec.loaded_from = File.expand_path file.to_s
- LOAD_CACHE_MUTEX.synchronize do
- prev = LOAD_CACHE[file]
+ @load_cache_mutex.synchronize do
+ prev = @load_cache[file]
if prev
_spec = prev
else
- LOAD_CACHE[file] = _spec
+ @load_cache[file] = _spec
end
end
return _spec
@@ -1155,7 +1162,7 @@ class Gem::Specification < Gem::BasicSpecification
def self.normalize_yaml_input(input)
result = input.respond_to?(:read) ? input.read : input
- result = "--- " + result unless result =~ /\A--- /
+ result = "--- " + result unless result.start_with?("--- ")
result = result.dup
result.gsub!(/ !!null \n/, " \n")
# date: 2011-04-26 00:00:00.000000000Z
@@ -1172,7 +1179,7 @@ class Gem::Specification < Gem::BasicSpecification
# version as well.
def self.outdated
- outdated_and_latest_version.map { |local, _| local.name }
+ outdated_and_latest_version.map {|local, _| local.name }
end
##
@@ -1193,7 +1200,7 @@ class Gem::Specification < Gem::BasicSpecification
Gem::Dependency.new local_spec.name, ">= #{local_spec.version}"
remotes, = fetcher.search_for_dependency dependency
- remotes = remotes.map { |n, _| n.version }
+ remotes = remotes.map {|n, _| n.version }
latest_remote = remotes.sort.last
@@ -1224,13 +1231,9 @@ class Gem::Specification < Gem::BasicSpecification
def self.reset
@@dirs = nil
- Gem.pre_reset_hooks.each { |hook| hook.call }
- @@all = nil
- @@stubs = nil
- @@stubs_by_name = {}
- @@spec_with_requirable_file = {}
- @@active_stub_with_requirable_file = {}
- _clear_load_cache
+ Gem.pre_reset_hooks.each {|hook| hook.call }
+ clear_specs
+ clear_load_cache
unresolved = unresolved_deps
unless unresolved.empty?
w = "W" + "ARN"
@@ -1241,19 +1244,19 @@ class Gem::Specification < Gem::BasicSpecification
versions = find_all_by_name(dep.name)
unless versions.empty?
warn " Available/installed versions of this gem:"
- versions.each { |s| warn " - #{s.version}" }
+ versions.each {|s| warn " - #{s.version}" }
end
end
warn "#{w}: Clearing out unresolved specs. Try 'gem cleanup <gem>'"
warn "Please report a bug if this causes problems."
unresolved.clear
end
- Gem.post_reset_hooks.each { |hook| hook.call }
+ Gem.post_reset_hooks.each {|hook| hook.call }
end
# DOC: This method needs documented or nodoc'd
def self.unresolved_deps
- @unresolved_deps ||= Hash.new { |h, n| h[n] = Gem::Dependency.new n }
+ @unresolved_deps ||= Hash.new {|h, n| h[n] = Gem::Dependency.new n }
end
##
@@ -1284,7 +1287,7 @@ class Gem::Specification < Gem::BasicSpecification
# Cleanup any YAML::PrivateType. They only show up for an old bug
# where nil => null, so just convert them to nil based on the type.
- array.map! { |e| e.kind_of?(YAML::PrivateType) ? nil : e }
+ array.map! {|e| e.kind_of?(YAML::PrivateType) ? nil : e }
spec.instance_variable_set :@rubygems_version, array[0]
# spec version
@@ -1349,7 +1352,7 @@ class Gem::Specification < Gem::BasicSpecification
true, # has_rdoc
@new_platform,
@licenses,
- @metadata
+ @metadata,
]
end
@@ -1397,7 +1400,11 @@ class Gem::Specification < Gem::BasicSpecification
raise e
end
- specs = spec_dep.to_specs
+ begin
+ specs = spec_dep.to_specs
+ rescue Gem::MissingSpecError => e
+ raise Gem::MissingSpecError.new(e.name, e.requirement, "at: #{self.spec_file}")
+ end
if specs.size == 1
specs.first.activate
@@ -1433,7 +1440,7 @@ class Gem::Specification < Gem::BasicSpecification
self.summary = sanitize_string(summary)
self.description = sanitize_string(description)
self.post_install_message = sanitize_string(post_install_message)
- self.authors = authors.collect { |a| sanitize_string(a) }
+ self.authors = authors.collect {|a| sanitize_string(a) }
end
##
@@ -1445,13 +1452,7 @@ class Gem::Specification < Gem::BasicSpecification
# HACK the #to_s is in here because RSpec has an Array of Arrays of
# Strings for authors. Need a way to disallow bad values on gemspec
# generation. (Probably won't happen.)
- string = string.to_s
-
- begin
- Builder::XChar.encode string
- rescue NameError, NoMethodError
- string.to_xs
- end
+ string.to_s
end
##
@@ -1462,7 +1463,7 @@ class Gem::Specification < Gem::BasicSpecification
return nil if executables.nil?
if @bindir
- Array(executables).map { |e| File.join(@bindir, e) }
+ Array(executables).map {|e| File.join(@bindir, e) }
else
executables
end
@@ -1544,7 +1545,7 @@ class Gem::Specification < Gem::BasicSpecification
def build_args
if File.exist? build_info_file
build_info = File.readlines build_info_file
- build_info = build_info.map { |x| x.strip }
+ build_info = build_info.map {|x| x.strip }
build_info.delete ""
build_info
else
@@ -1557,9 +1558,8 @@ class Gem::Specification < Gem::BasicSpecification
# the gem.build_complete file is missing.
def build_extensions # :nodoc:
- return if default_gem?
return if extensions.empty?
- return if installed_by_version < Gem::Version.new('2.2.0.preview.2')
+ return if default_gem?
return if File.exist? gem_build_complete_path
return if !File.writable?(base_dir)
return if !File.exist?(File.join(base_dir, 'extensions'))
@@ -1570,9 +1570,9 @@ class Gem::Specification < Gem::BasicSpecification
unresolved_deps = Gem::Specification.unresolved_deps.dup
Gem::Specification.unresolved_deps.clear
- require 'rubygems/config_file'
- require 'rubygems/ext'
- require 'rubygems/user_interaction'
+ require_relative 'config_file'
+ require_relative 'ext'
+ require_relative 'user_interaction'
ui = Gem::SilentUI.new
Gem::DefaultUserInteraction.use_ui ui do
@@ -1636,7 +1636,7 @@ class Gem::Specification < Gem::BasicSpecification
def conficts_when_loaded_with?(list_of_specs) # :nodoc:
result = list_of_specs.any? do |spec|
- spec.dependencies.any? { |dep| dep.runtime? && (dep.name == name) && !satisfies_requirement?(dep) }
+ spec.dependencies.any? {|dep| dep.runtime? && (dep.name == name) && !satisfies_requirement?(dep) }
end
result
end
@@ -1692,12 +1692,6 @@ class Gem::Specification < Gem::BasicSpecification
when String then
if DateTimeFormat =~ date
Time.utc($1.to_i, $2.to_i, $3.to_i)
-
- # Workaround for where the date format output from psych isn't
- # parsed as a Time object by syck and thus comes through as a
- # string.
- elsif /\A(\d{4})-(\d{2})-(\d{2}) \d{2}:\d{2}:\d{2}\.\d+?Z\z/ =~ date
- Time.utc($1.to_i, $2.to_i, $3.to_i)
else
raise(Gem::InvalidSpecificationException,
"invalid date format in specification: #{date.inspect}")
@@ -1725,7 +1719,7 @@ class Gem::Specification < Gem::BasicSpecification
end
result
end
- deprecate :default_executable, :none, 2018, 12
+ rubygems_deprecate :default_executable
##
# The default value for specification attribute +name+
@@ -1750,10 +1744,11 @@ class Gem::Specification < Gem::BasicSpecification
#
# [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]
- def dependent_gems
+ def dependent_gems(check_dev=true)
out = []
Gem::Specification.each do |spec|
- spec.dependencies.each do |dep|
+ deps = check_dev ? spec.dependencies : spec.runtime_dependencies
+ deps.each do |dep|
if self.satisfies_requirement?(dep)
sats = []
find_all_satisfiers(dep) do |sat|
@@ -1770,7 +1765,7 @@ class Gem::Specification < Gem::BasicSpecification
# Returns all specs that matches this spec's runtime dependencies.
def dependent_specs
- runtime_dependencies.map { |dep| dep.to_specs }.flatten
+ runtime_dependencies.map {|dep| dep.to_specs }.flatten
end
##
@@ -1784,7 +1779,7 @@ class Gem::Specification < Gem::BasicSpecification
# List of dependencies that are used for development
def development_dependencies
- dependencies.select { |d| d.type == :development }
+ dependencies.select {|d| d.type == :development }
end
##
@@ -1845,29 +1840,23 @@ class Gem::Specification < Gem::BasicSpecification
end
##
- # Sets executables to +value+, ensuring it is an array. Don't
- # use this, push onto the array instead.
+ # Sets executables to +value+, ensuring it is an array.
def executables=(value)
- # TODO: warn about setting instead of pushing
@executables = Array(value)
end
##
- # Sets extensions to +extensions+, ensuring it is an array. Don't
- # use this, push onto the array instead.
+ # Sets extensions to +extensions+, ensuring it is an array.
def extensions=(extensions)
- # TODO: warn about setting instead of pushing
@extensions = Array extensions
end
##
- # Sets extra_rdoc_files to +files+, ensuring it is an array. Don't
- # use this, push onto the array instead.
+ # Sets extra_rdoc_files to +files+, ensuring it is an array.
def extra_rdoc_files=(files)
- # TODO: warn about setting instead of pushing
@extra_rdoc_files = Array files
end
@@ -1933,7 +1922,7 @@ class Gem::Specification < Gem::BasicSpecification
def has_rdoc # :nodoc:
true
end
- deprecate :has_rdoc, :none, 2018, 12
+ rubygems_deprecate :has_rdoc
##
# Deprecated and ignored.
@@ -1943,10 +1932,10 @@ class Gem::Specification < Gem::BasicSpecification
def has_rdoc=(ignored) # :nodoc:
@has_rdoc = true
end
- deprecate :has_rdoc=, :none, 2018, 12
+ rubygems_deprecate :has_rdoc=
alias :has_rdoc? :has_rdoc # :nodoc:
- deprecate :has_rdoc?, :none, 2018, 12
+ rubygems_deprecate :has_rdoc?
##
# True if this gem has files in test_files
@@ -1968,7 +1957,9 @@ class Gem::Specification < Gem::BasicSpecification
yaml_initialize coder.tag, coder.map
end
- eval <<-RB, binding, __FILE__, __LINE__ + 1
+ eval <<-RUBY, binding, __FILE__, __LINE__ + 1
+ # frozen_string_literal: true
+
def set_nil_attributes_to_nil
#{@@nil_attributes.map {|key| "@#{key} = nil" }.join "; "}
end
@@ -1978,7 +1969,7 @@ class Gem::Specification < Gem::BasicSpecification
#{@@non_nil_attributes.map {|key| "@#{key} = #{INITIALIZE_CODE_FOR_DEFAULTS[key]}" }.join ";"}
end
private :set_not_nil_attributes_to_default_values
- RB
+ RUBY
##
# Specification constructor. Assigns the default values to the attributes
@@ -2003,6 +1994,10 @@ class Gem::Specification < Gem::BasicSpecification
self.name = name if name
self.version = version if version
+ if platform = Gem.platforms.last and platform != Gem::Platform::RUBY and platform != Gem::Platform.local
+ self.platform = platform
+ end
+
yield self if block_given?
end
@@ -2115,7 +2110,7 @@ class Gem::Specification < Gem::BasicSpecification
end
if @specification_version > CURRENT_SPECIFICATION_VERSION and
- sym.to_s =~ /=$/
+ sym.to_s.end_with?("=")
warn "ignoring #{sym} loading #{full_name}" if $DEBUG
else
super
@@ -2127,9 +2122,8 @@ class Gem::Specification < Gem::BasicSpecification
# probably want to build_extensions
def missing_extensions?
- return false if default_gem?
return false if extensions.empty?
- return false if installed_by_version < Gem::Version.new('2.2.0.preview.2')
+ return false if default_gem?
return false if File.exist? gem_build_complete_path
true
@@ -2199,7 +2193,7 @@ class Gem::Specification < Gem::BasicSpecification
attributes.each do |attr_name|
current_value = self.send attr_name
- current_value = current_value.sort if %i(files test_files).include? attr_name
+ current_value = current_value.sort if %i[files test_files].include? attr_name
if current_value != default_value(attr_name) or
self.class.required_attribute? attr_name
@@ -2249,11 +2243,9 @@ class Gem::Specification < Gem::BasicSpecification
end
##
- # Sets rdoc_options to +value+, ensuring it is an array. Don't
- # use this, push onto the array instead.
+ # Sets rdoc_options to +value+, ensuring it is an array.
def rdoc_options=(options)
- # TODO: warn about setting instead of pushing
@rdoc_options = Array options
end
@@ -2272,11 +2264,9 @@ class Gem::Specification < Gem::BasicSpecification
end
##
- # Set requirements to +req+, ensuring it is an array. Don't
- # use this, push onto the array instead.
+ # Set requirements to +req+, ensuring it is an array.
def requirements=(req)
- # TODO: warn about setting instead of pushing
@requirements = Array req
end
@@ -2298,9 +2288,9 @@ class Gem::Specification < Gem::BasicSpecification
def ruby_code(obj)
case obj
when String then obj.dump + ".freeze"
- when Array then '[' + obj.map { |x| ruby_code x }.join(", ") + ']'
+ when Array then '[' + obj.map {|x| ruby_code x }.join(", ") + ']'
when Hash then
- seg = obj.keys.sort.map { |k| "#{k.to_s.dump} => #{obj[k].to_s.dump}" }
+ seg = obj.keys.sort.map {|k| "#{k.to_s.dump} => #{obj[k].to_s.dump}" }
"{ #{seg.join(', ')} }"
when Gem::Version then obj.to_s.dump
when DateLike then obj.strftime('%Y-%m-%d').dump
@@ -2328,7 +2318,7 @@ class Gem::Specification < Gem::BasicSpecification
# True if this gem has the same attributes as +other+.
def same_attributes?(spec)
- @@attributes.all? { |name, default| self.send(name) == spec.send(name) }
+ @@attributes.all? {|name, default| self.send(name) == spec.send(name) }
end
private :same_attributes?
@@ -2427,7 +2417,6 @@ class Gem::Specification < Gem::BasicSpecification
# still have their default values are omitted.
def to_ruby
- require 'openssl'
mark_version
result = []
result << "# -*- encoding: utf-8 -*-"
@@ -2460,17 +2449,22 @@ class Gem::Specification < Gem::BasicSpecification
:version,
:has_rdoc,
:default_executable,
- :metadata
+ :metadata,
+ :signing_key,
]
@@attributes.each do |attr_name|
next if handled.include? attr_name
current_value = self.send(attr_name)
if current_value != default_value(attr_name) || self.class.required_attribute?(attr_name)
- result << " s.#{attr_name} = #{ruby_code current_value}" unless current_value.is_a?(OpenSSL::PKey::RSA)
+ result << " s.#{attr_name} = #{ruby_code current_value}"
end
end
+ if String === signing_key
+ result << " s.signing_key = #{signing_key.dump}.freeze"
+ end
+
if @installed_by_version
result << nil
result << " s.installed_by_version = \"#{Gem::VERSION}\" if s.respond_to? :installed_by_version"
@@ -2533,7 +2527,7 @@ class Gem::Specification < Gem::BasicSpecification
# back, we have to check again here to make sure that our
# psych code was properly loaded, and load it if not.
unless Gem.const_defined?(:NoAliasYAMLTree)
- require 'rubygems/psych_tree'
+ require_relative 'psych_tree'
end
builder = Gem::NoAliasYAMLTree.create
@@ -2558,7 +2552,7 @@ class Gem::Specification < Gem::BasicSpecification
begin
dependencies.each do |dep|
next unless dep.runtime?
- dep.to_specs.each do |dep_spec|
+ dep.matching_specs(true).each do |dep_spec|
next if visited.has_key?(dep_spec)
visited[dep_spec] = true
trail.push(dep_spec)
@@ -2570,7 +2564,7 @@ class Gem::Specification < Gem::BasicSpecification
unless result == :next
spec_name = dep_spec.name
dep_spec.traverse(trail, visited, &block) unless
- trail.any? { |s| s.name == spec_name }
+ trail.any? {|s| s.name == spec_name }
end
end
end
@@ -2595,30 +2589,27 @@ class Gem::Specification < Gem::BasicSpecification
end
def keep_only_files_and_directories
- @executables.delete_if { |x| File.directory?(File.join(@bindir, x)) }
- @extensions.delete_if { |x| File.directory?(x) && !File.symlink?(x) }
- @extra_rdoc_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) }
- @files.delete_if { |x| File.directory?(x) && !File.symlink?(x) }
- @test_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) }
+ @executables.delete_if {|x| File.directory?(File.join(@bindir, x)) }
+ @extensions.delete_if {|x| File.directory?(x) && !File.symlink?(x) }
+ @extra_rdoc_files.delete_if {|x| File.directory?(x) && !File.symlink?(x) }
+ @files.delete_if {|x| File.directory?(x) && !File.symlink?(x) }
+ @test_files.delete_if {|x| File.directory?(x) && !File.symlink?(x) }
end
def validate_metadata
Gem::SpecificationPolicy.new(self).validate_metadata
end
+ rubygems_deprecate :validate_metadata
- ##
- # Checks that dependencies use requirements as we recommend. Warnings are
- # issued when dependencies are open-ended or overly strict for semantic
- # versioning.
def validate_dependencies
Gem::SpecificationPolicy.new(self).validate_dependencies
end
+ rubygems_deprecate :validate_dependencies
- ##
- # Checks to see if the files to be packaged are world-readable.
def validate_permissions
Gem::SpecificationPolicy.new(self).validate_permissions
end
+ rubygems_deprecate :validate_permissions
##
# Set the version to +version+, potentially also setting
@@ -2681,8 +2672,4 @@ class Gem::Specification < Gem::BasicSpecification
def raw_require_paths # :nodoc:
@require_paths
end
-
end
-
-# DOC: What is this and why is it here, randomly, at the end of this file?
-Gem.clear_paths
diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb
index b7fb2cfa1a..73bd31970c 100644
--- a/lib/rubygems/specification_policy.rb
+++ b/lib/rubygems/specification_policy.rb
@@ -1,14 +1,13 @@
-require 'rubygems/user_interaction'
+require_relative 'user_interaction'
class Gem::SpecificationPolicy
-
include Gem::UserInteraction
VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/.freeze # :nodoc:
SPECIAL_CHARACTERS = /\A[#{Regexp.escape('.-_')}]+/.freeze # :nodoc:
- VALID_URI_PATTERN = %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z}.freeze # :nodoc:
+ VALID_URI_PATTERN = %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z}.freeze # :nodoc:
METADATA_LINK_KEYS = %w[
bug_tracker_uri
@@ -18,6 +17,7 @@ class Gem::SpecificationPolicy
mailing_list_uri
source_code_uri
wiki_uri
+ funding_uri
].freeze # :nodoc:
def initialize(specification)
@@ -32,13 +32,32 @@ class Gem::SpecificationPolicy
attr_accessor :packaging
##
- # Checks that the specification contains all required fields, and does a
- # very basic sanity check.
+ # Does a sanity check on the specification.
#
# Raises InvalidSpecificationException if the spec does not pass the
# checks.
+ #
+ # It also performs some validations that do not raise but print warning
+ # messages instead.
def validate(strict = false)
+ validate_required!
+
+ validate_optional(strict) if packaging || strict
+
+ true
+ end
+
+ ##
+ # Does a sanity check on the specification.
+ #
+ # Raises InvalidSpecificationException if the spec does not pass the
+ # checks.
+ #
+ # Only runs checks that are considered necessary for the specification to be
+ # functional.
+
+ def validate_required!
validate_nil_attributes
validate_rubygems_version
@@ -65,16 +84,24 @@ class Gem::SpecificationPolicy
validate_metadata
+ validate_licenses_length
+
+ validate_lazy_metadata
+
+ validate_duplicate_dependencies
+ end
+
+ def validate_optional(strict)
validate_licenses
validate_permissions
- validate_lazy_metadata
-
validate_values
validate_dependencies
+ validate_extensions
+
validate_removed_attributes
if @warnings > 0
@@ -84,8 +111,6 @@ class Gem::SpecificationPolicy
alert_warning help_text
end
end
-
- true
end
##
@@ -99,39 +124,39 @@ class Gem::SpecificationPolicy
end
metadata.each do |key, value|
+ entry = "metadata['#{key}']"
if !key.kind_of?(String)
error "metadata keys must be a String"
end
if key.size > 128
- error "metadata key too large (#{key.size} > 128)"
+ error "metadata key is too large (#{key.size} > 128)"
end
if !value.kind_of?(String)
- error "metadata values must be a String"
+ error "#{entry} value must be a String"
end
if value.size > 1024
- error "metadata value too large (#{value.size} > 1024)"
+ error "#{entry} value is too large (#{value.size} > 1024)"
end
if METADATA_LINK_KEYS.include? key
if value !~ VALID_URI_PATTERN
- error "metadata['#{key}'] has invalid link: #{value.inspect}"
+ error "#{entry} has invalid link: #{value.inspect}"
end
end
end
end
##
- # Implementation for Specification#validate_dependencies
+ # Checks that no duplicate dependencies are specified.
- def validate_dependencies # :nodoc:
+ def validate_duplicate_dependencies # :nodoc:
# NOTE: see REFACTOR note in Gem::Dependency about types - this might be brittle
- seen = Gem::Dependency::TYPES.inject({}) { |types, type| types.merge({ type => {}}) }
+ seen = Gem::Dependency::TYPES.inject({}) {|types, type| types.merge({ type => {}}) }
error_messages = []
- warning_messages = []
@specification.dependencies.each do |dep|
if prev = seen[dep.type][dep.name]
error_messages << <<-MESSAGE
@@ -141,7 +166,20 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
end
seen[dep.type][dep.name] = dep
+ end
+ if error_messages.any?
+ error error_messages.join
+ end
+ end
+
+ ##
+ # Checks that dependencies use requirements as we recommend. Warnings are
+ # issued when dependencies are open-ended or overly strict for semantic
+ # versioning.
+ def validate_dependencies # :nodoc:
+ warning_messages = []
+ @specification.dependencies.each do |dep|
prerelease_dep = dep.requirements_list.any? do |req|
Gem::Requirement.new(req).prerelease?
end
@@ -176,11 +214,8 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
warning_messages << ["open-ended dependency on #{dep} is not recommended", recommendation].join("\n") + "\n"
end
end
- if error_messages.any?
- error error_messages.join
- end
if warning_messages.any?
- warning_messages.each { |warning_message| warning warning_message }
+ warning_messages.each {|warning_message| warning warning_message }
end
end
@@ -257,7 +292,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
def validate_non_files
return unless packaging
- non_files = @specification.files.reject {|x| File.file?(x) || File.symlink?(x)}
+ non_files = @specification.files.reject {|x| File.file?(x) || File.symlink?(x) }
unless non_files.empty?
error "[\"#{non_files.join "\", \""}\"] are not files"
@@ -282,7 +317,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
platform = @specification.platform
case platform
- when Gem::Platform, Gem::Platform::RUBY # ok
+ when Gem::Platform, Gem::Platform::RUBY # ok
else
error "invalid platform #{platform.inspect}, see Gem::Platform"
end
@@ -303,9 +338,8 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
String
end
- unless Array === val and val.all? {|x| x.kind_of?(klass)}
- raise(Gem::InvalidSpecificationException,
- "#{field} must be an Array of #{klass}")
+ unless Array === val and val.all? {|x| x.kind_of?(klass) }
+ error "#{field} must be an Array of #{klass}"
end
end
@@ -315,33 +349,39 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
error "authors may not be empty"
end
- def validate_licenses
+ def validate_licenses_length
licenses = @specification.licenses
licenses.each do |license|
if license.length > 64
error "each license must be 64 characters or less"
end
+ end
+ end
+
+ def validate_licenses
+ licenses = @specification.licenses
+ licenses.each do |license|
if !Gem::Licenses.match?(license)
suggestions = Gem::Licenses.suggestions(license)
- message = <<-warning
+ message = <<-WARNING
license value '#{license}' is invalid. Use a license identifier from
http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license.
- warning
- message += "Did you mean #{suggestions.map { |s| "'#{s}'"}.join(', ')}?\n" unless suggestions.nil?
+ WARNING
+ message += "Did you mean #{suggestions.map {|s| "'#{s}'" }.join(', ')}?\n" unless suggestions.nil?
warning(message)
end
end
- warning <<-warning if licenses.empty?
+ warning <<-WARNING if licenses.empty?
licenses is empty, but is recommended. Use a license identifier from
http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license.
- warning
+ WARNING
end
LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '')
- LAZY_PATTERN = /FI XME|TO DO/x.freeze
+ LAZY_PATTERN = /\AFI XME|\ATO DO/x.freeze
HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i.freeze
def validate_lazy_metadata
@@ -393,7 +433,7 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
validate_shebang_line_in(executable)
end
- @specification.files.select { |f| File.symlink?(f) }.each do |file|
+ @specification.files.select {|f| File.symlink?(f) }.each do |file|
warning "#{file} is a symlink, which is not supported on all platforms"
end
end
@@ -416,6 +456,18 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
end
end
+ def validate_extensions # :nodoc:
+ require_relative 'ext'
+ builder = Gem::Ext::Builder.new(@specification)
+
+ rake_extension = @specification.extensions.any? {|s| builder.builder_for(s) == Gem::Ext::RakeBuilder }
+ rake_dependency = @specification.dependencies.any? {|d| d.name == 'rake' }
+
+ warning <<-WARNING if rake_extension && !rake_dependency
+You have specified rake based extension, but rake is not added as dependency. It is recommended to add rake as a dependency in gemspec since there's no guarantee rake will be already installed.
+ WARNING
+ end
+
def warning(statement) # :nodoc:
@warnings += 1
@@ -431,5 +483,4 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
def help_text # :nodoc:
"See https://guides.rubygems.org/specification-reference/ for help"
end
-
end
diff --git a/lib/rubygems/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem b/lib/rubygems/ssl_certs/index.rubygems.org/GlobalSignRootCA.pem
deleted file mode 100644
index f4ce4ca43d..0000000000
--- a/lib/rubygems/ssl_certs/index.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/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem b/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem
deleted file mode 100644
index 9e6810ab70..0000000000
--- a/lib/rubygems/ssl_certs/rubygems.global.ssl.fastly.net/DigiCertHighAssuranceEVRootCA.pem
+++ /dev/null
@@ -1,23 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
-ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
-MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
-LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
-RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
-+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
-PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
-xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
-Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
-hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
-EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
-MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
-FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
-nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
-eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
-hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
-Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
-vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
-+OkuE6N36B9K
------END CERTIFICATE-----
diff --git a/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem b/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem
deleted file mode 100644
index 20585f1c01..0000000000
--- a/lib/rubygems/ssl_certs/rubygems.org/AddTrustExternalCARoot.pem
+++ /dev/null
@@ -1,25 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
-IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
-MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
-FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
-bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
-dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
-H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
-uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
-mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
-a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
-E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
-WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
-VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
-Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
-cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
-IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
-AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
-YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
-6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
-Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
-c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
-mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
------END CERTIFICATE-----
diff --git a/lib/rubygems/stub_specification.rb b/lib/rubygems/stub_specification.rb
index 959030fd54..4246f9de86 100644
--- a/lib/rubygems/stub_specification.rb
+++ b/lib/rubygems/stub_specification.rb
@@ -5,7 +5,6 @@
# information.
class Gem::StubSpecification < Gem::BasicSpecification
-
# :nodoc:
PREFIX = "# stub: ".freeze
@@ -13,7 +12,6 @@ class Gem::StubSpecification < Gem::BasicSpecification
OPEN_MODE = 'r:UTF-8:-'.freeze
class StubLine # :nodoc: all
-
attr_reader :name, :version, :platform, :require_paths, :extensions,
:full_name
@@ -31,7 +29,7 @@ class Gem::StubSpecification < Gem::BasicSpecification
# in their require paths, so lets take advantage of that by pre-allocating
# a require path list for that case.
REQUIRE_PATH_LIST = { # :nodoc:
- 'lib' => ['lib'].freeze
+ 'lib' => ['lib'].freeze,
}.freeze
def initialize(data, extensions)
@@ -56,7 +54,6 @@ class Gem::StubSpecification < Gem::BasicSpecification
REQUIRE_PATHS[x] || x
end
end
-
end
def self.default_gemspec_stub(filename, base_dir, gems_dir)
@@ -212,5 +209,4 @@ class Gem::StubSpecification < Gem::BasicSpecification
def stubbed?
data.is_a? StubLine
end
-
end
diff --git a/lib/rubygems/syck_hack.rb b/lib/rubygems/syck_hack.rb
deleted file mode 100644
index 0d87c71df4..0000000000
--- a/lib/rubygems/syck_hack.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-# :stopdoc:
-
-# Hack to handle syck's DefaultKey bug
-#
-# This file is always loaded AFTER either syck or psych are already
-# loaded. It then looks at what constants are available and creates
-# a consistent view on all rubys.
-#
-# All this is so that there is always a YAML::Syck::DefaultKey
-# class no matter if the full yaml library has loaded or not.
-#
-
-module YAML # :nodoc:
- # In newer 1.9.2, there is a Syck toplevel constant instead of it
- # being underneath YAML. If so, reference it back under YAML as
- # well.
- if defined? ::Syck
- # for tests that change YAML::ENGINE
- # 1.8 does not support the second argument to const_defined?
- remove_const :Syck rescue nil
-
- Syck = ::Syck
-
- # JRuby's "Syck" is called "Yecht"
- elsif defined? YAML::Yecht
- Syck = YAML::Yecht
-
- # Otherwise, if there is no YAML::Syck, then we've got just psych
- # loaded, so lets define a stub for DefaultKey.
- elsif !defined? YAML::Syck
- module Syck
- class DefaultKey # :nodoc:
- end
- end
- end
-
- # Now that we've got something that is always here, define #to_s
- # so when code tries to use this, it at least just shows up like it
- # should.
- module Syck
- class DefaultKey
-
- remove_method :to_s rescue nil
-
- def to_s
- '='
- end
-
- end
- end
-
- SyntaxError = Error unless defined? SyntaxError
-end
-
-# Sometime in the 1.9 dev cycle, the Syck constant was moved from under YAML
-# to be a toplevel constant. So gemspecs created under these versions of Syck
-# will have references to Syck::DefaultKey.
-#
-# So we need to be sure that we reference Syck at the toplevel too so that
-# we can always load these kind of gemspecs.
-#
-if !defined?(Syck)
- Syck = YAML::Syck
-end
-
-# Now that we've got Syck setup in all the right places, store
-# a reference to the DefaultKey class inside Gem. We do this so that
-# if later on YAML, etc are redefined, we've still got a consistent
-# place to find the DefaultKey class for comparison.
-
-module Gem
- # for tests that change YAML::ENGINE
- remove_const :SyckDefaultKey if const_defined? :SyckDefaultKey
-
- SyckDefaultKey = YAML::Syck::DefaultKey
-end
-
-# :startdoc:
diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb
deleted file mode 100644
index c6f5f29d4e..0000000000
--- a/lib/rubygems/test_case.rb
+++ /dev/null
@@ -1,1554 +0,0 @@
-# frozen_string_literal: true
-
-require 'rubygems'
-
-# If bundler gemspec exists, add to stubs
-bundler_gemspec = File.expand_path("../../../bundler/bundler.gemspec", __FILE__)
-if File.exist?(bundler_gemspec)
- Gem::Specification.dirs.unshift File.dirname(bundler_gemspec)
- Gem::Specification.class_variable_set :@@stubs, nil
- Gem::Specification.stubs
- Gem::Specification.dirs.shift
-end
-
-begin
- gem 'minitest', '~> 5.0'
-rescue Gem::LoadError
-end
-
-begin
- require 'simplecov'
- SimpleCov.start do
- add_filter "/test/"
- add_filter "/bundler/"
- add_filter "/lib/rubygems/resolver/molinillo"
- end
-rescue LoadError
-end
-
-require 'bundler'
-
-require 'minitest/autorun'
-
-require 'rubygems/deprecate'
-
-require 'fileutils'
-require 'pathname'
-require 'pp'
-require 'rubygems/package'
-require 'shellwords'
-require 'tmpdir'
-require 'uri'
-require 'zlib'
-require 'benchmark' # stdlib
-require 'rubygems/mock_gem_ui'
-
-module Gem
-
- ##
- # Allows setting the gem path searcher. This method is available when
- # requiring 'rubygems/test_case'
-
- def self.searcher=(searcher)
- @searcher = searcher
- end
-
- ##
- # Allows toggling Windows behavior. This method is available when requiring
- # 'rubygems/test_case'
-
- def self.win_platform=(val)
- @@win_platform = val
- end
-
- ##
- # Allows setting path to Ruby. This method is available when requiring
- # 'rubygems/test_case'
-
- def self.ruby=(ruby)
- @ruby = ruby
- end
-
- ##
- # When rubygems/test_case is required the default user interaction is a
- # MockGemUi.
-
- module DefaultUserInteraction
- @ui = Gem::MockGemUi.new
- end
-end
-
-##
-# RubyGemTestCase provides a variety of methods for testing rubygems and
-# gem-related behavior in a sandbox. Through RubyGemTestCase you can install
-# and uninstall gems, fetch remote gems through a stub fetcher and be assured
-# your normal set of gems is not affected.
-
-class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Unit::TestCase)
-
- extend Gem::Deprecate
-
- attr_accessor :fetcher # :nodoc:
-
- attr_accessor :gem_repo # :nodoc:
-
- attr_accessor :uri # :nodoc:
-
- TEST_PATH = ENV.fetch('RUBYGEMS_TEST_PATH', File.expand_path('../../../test/rubygems', __FILE__))
-
- SPECIFICATIONS = File.expand_path(File.join(TEST_PATH, "specifications"), __FILE__)
-
- def assert_activate(expected, *specs)
- specs.each do |spec|
- case spec
- when String then
- Gem::Specification.find_by_name(spec).activate
- when Gem::Specification then
- spec.activate
- else
- flunk spec.inspect
- end
- end
-
- loaded = Gem.loaded_specs.values.map(&:full_name)
-
- assert_equal expected.sort, loaded.sort if expected
- end
-
- # TODO: move to minitest
- def assert_path_exists(path, msg = nil)
- msg = message(msg) { "Expected path '#{path}' to exist" }
- assert File.exist?(path), msg
- end
-
- def assert_directory_exists(path, msg = nil)
- msg = message(msg) { "Expected path '#{path}' to be a directory" }
- assert_path_exists path
- assert File.directory?(path), msg
- end
-
- ##
- # Sets the ENABLE_SHARED entry in RbConfig::CONFIG to +value+ and restores
- # the original value when the block ends
-
- def enable_shared(value)
- enable_shared = RbConfig::CONFIG['ENABLE_SHARED']
- RbConfig::CONFIG['ENABLE_SHARED'] = value
-
- yield
- ensure
- if enable_shared
- RbConfig::CONFIG['enable_shared'] = enable_shared
- else
- RbConfig::CONFIG.delete 'enable_shared'
- end
- end
-
- ##
- # Sets the vendordir entry in RbConfig::CONFIG to +value+ and restores the
- # original value when the block ends
- #
- def vendordir(value)
- vendordir = RbConfig::CONFIG['vendordir']
-
- if value
- RbConfig::CONFIG['vendordir'] = value
- else
- RbConfig::CONFIG.delete 'vendordir'
- end
-
- yield
- ensure
- if vendordir
- RbConfig::CONFIG['vendordir'] = vendordir
- else
- RbConfig::CONFIG.delete 'vendordir'
- end
- end
-
- ##
- # Sets the bindir entry in RbConfig::CONFIG to +value+ and restores the
- # original value when the block ends
- #
- def bindir(value)
- with_clean_path_to_ruby do
- bindir = RbConfig::CONFIG['bindir']
-
- if value
- RbConfig::CONFIG['bindir'] = value
- else
- RbConfig::CONFIG.delete 'bindir'
- end
-
- begin
- yield
- ensure
- if bindir
- RbConfig::CONFIG['bindir'] = bindir
- else
- RbConfig::CONFIG.delete 'bindir'
- end
- end
- end
- end
-
- ##
- # Sets the EXEEXT entry in RbConfig::CONFIG to +value+ and restores the
- # original value when the block ends
- #
- def exeext(value)
- exeext = RbConfig::CONFIG['EXEEXT']
-
- if value
- RbConfig::CONFIG['EXEEXT'] = value
- else
- RbConfig::CONFIG.delete 'EXEEXT'
- end
-
- yield
- ensure
- if exeext
- RbConfig::CONFIG['EXEEXT'] = exeext
- else
- RbConfig::CONFIG.delete 'EXEEXT'
- end
- end
-
- # TODO: move to minitest
- def refute_path_exists(path, msg = nil)
- msg = message(msg) { "Expected path '#{path}' to not exist" }
- refute File.exist?(path), msg
- end
-
- def scan_make_command_lines(output)
- output.scan(/^#{Regexp.escape make_command}(?:[[:blank:]].*)?$/)
- end
-
- def parse_make_command_line(line)
- command, *args = line.shellsplit
-
- targets = []
- macros = {}
-
- args.each do |arg|
- case arg
- when /\A(\w+)=/
- macros[$1] = $'
- else
- targets << arg
- end
- end
-
- targets << '' if targets.empty?
-
- {
- :command => command,
- :targets => targets,
- :macros => macros,
- }
- end
-
- def assert_contains_make_command(target, output, msg = nil)
- if output.match(/\n/)
- msg = message(msg) do
- 'Expected output containing make command "%s": %s' % [
- ('%s %s' % [make_command, target]).rstrip,
- output.inspect
- ]
- end
- else
- msg = message(msg) do
- 'Expected make command "%s": %s' % [
- ('%s %s' % [make_command, target]).rstrip,
- output.inspect
- ]
- end
- end
-
- assert scan_make_command_lines(output).any? { |line|
- make = parse_make_command_line(line)
-
- if make[:targets].include?(target)
- yield make, line if block_given?
- true
- else
- false
- end
- }, msg
- end
-
- include Gem::DefaultUserInteraction
-
- undef_method :default_test if instance_methods.include? 'default_test' or
- instance_methods.include? :default_test
-
- ##
- # #setup prepares a sandboxed location to install gems. All installs are
- # directed to a temporary directory. All install plugins are removed.
- #
- # If the +RUBY+ environment variable is set the given path is used for
- # Gem::ruby. The local platform is set to <tt>i386-mswin32</tt> for Windows
- # or <tt>i686-darwin8.10.1</tt> otherwise.
-
- def setup
- super
-
- @orig_env = ENV.to_hash
-
- ENV['GEM_VENDOR'] = nil
- ENV['GEMRC'] = nil
- ENV['SOURCE_DATE_EPOCH'] = nil
-
- @current_dir = Dir.pwd
- @fetcher = nil
-
- @back_ui = Gem::DefaultUserInteraction.ui
- @ui = Gem::MockGemUi.new
- # This needs to be a new instance since we call use_ui(@ui) when we want to
- # capture output
- Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new
-
- tmpdir = File.realpath Dir.tmpdir
- tmpdir.tap(&Gem::UNTAINT)
-
- @tempdir = File.join(tmpdir, "test_rubygems_#{$$}")
- @tempdir.tap(&Gem::UNTAINT)
-
- FileUtils.mkdir_p @tempdir
-
- # This makes the tempdir consistent on Windows.
- # Dir.tmpdir may return short path name, but Dir[Dir.tmpdir] returns long
- # path name. https://bugs.ruby-lang.org/issues/10819
- # File.expand_path or File.realpath doesn't convert path name to long path
- # name. Only Dir[] (= Dir.glob) works.
- # Short and long path name is specific to Windows filesystem.
- if win_platform?
- @tempdir = Dir[@tempdir][0]
- @tempdir.tap(&Gem::UNTAINT)
- end
-
- @gemhome = File.join @tempdir, 'gemhome'
- @userhome = File.join @tempdir, 'userhome'
- ENV["GEM_SPEC_CACHE"] = File.join @tempdir, 'spec_cache'
-
- @orig_ruby = if ENV['RUBY']
- ruby = Gem.ruby
- Gem.ruby = ENV['RUBY']
- ruby
- end
-
- @git = ENV['GIT'] || 'git'
-
- Gem.ensure_gem_subdirectories @gemhome
-
- @orig_LOAD_PATH = $LOAD_PATH.dup
- $LOAD_PATH.map! do |s|
- expand_path = File.realpath(s) rescue File.expand_path(s)
- if expand_path != s
- expand_path.tap(&Gem::UNTAINT)
- if s.instance_variable_defined?(:@gem_prelude_index)
- expand_path.instance_variable_set(:@gem_prelude_index, expand_path)
- end
- expand_path.freeze if s.frozen?
- s = expand_path
- end
- s
- end
-
- Dir.chdir @tempdir
-
- ENV['HOME'] = @userhome
- Gem.instance_variable_set :@user_home, nil
- Gem.instance_variable_set :@gemdeps, nil
- Gem.instance_variable_set :@env_requirements_by_name, nil
- Gem.send :remove_instance_variable, :@ruby_version if
- Gem.instance_variables.include? :@ruby_version
-
- FileUtils.mkdir_p @gemhome
- FileUtils.mkdir_p @userhome
-
- ENV['GEM_PRIVATE_KEY_PASSPHRASE'] = PRIVATE_KEY_PASSPHRASE
-
- @default_dir = File.join @tempdir, 'default'
- @default_spec_dir = File.join @default_dir, "specifications", "default"
- if Gem.java_platform?
- @orig_default_gem_home = RbConfig::CONFIG['default_gem_home']
- RbConfig::CONFIG['default_gem_home'] = @default_dir
- else
- Gem.instance_variable_set(:@default_dir, @default_dir)
- end
- FileUtils.mkdir_p @default_spec_dir
-
- Gem::Specification.unresolved_deps.clear
- Gem.use_paths(@gemhome)
-
- Gem::Security.reset
-
- Gem.loaded_specs.clear
- Gem.instance_variable_set(:@activated_gem_paths, 0)
- Gem.clear_default_specs
- Bundler.reset!
-
- Gem.configuration.verbose = true
- Gem.configuration.update_sources = true
-
- Gem::RemoteFetcher.fetcher = Gem::FakeFetcher.new
-
- @gem_repo = "http://gems.example.com/"
- @uri = URI.parse @gem_repo
- Gem.sources.replace [@gem_repo]
-
- Gem.searcher = nil
- Gem::SpecFetcher.fetcher = nil
-
- @orig_arch = RbConfig::CONFIG['arch']
-
- if win_platform?
- util_set_arch 'i386-mswin32'
- else
- util_set_arch 'i686-darwin8.10.1'
- end
-
- @orig_hooks = {}
- %w[post_install_hooks done_installing_hooks post_uninstall_hooks pre_uninstall_hooks pre_install_hooks pre_reset_hooks post_reset_hooks post_build_hooks].each do |name|
- @orig_hooks[name] = Gem.send(name).dup
- end
-
- @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
- @orig_LOADED_FEATURES = $LOADED_FEATURES.dup
- end
-
- ##
- # #teardown restores the process to its original state and removes the
- # tempdir
-
- def teardown
- $LOAD_PATH.replace @orig_LOAD_PATH if @orig_LOAD_PATH
- if @orig_LOADED_FEATURES
- if @orig_LOAD_PATH
- paths = @orig_LOAD_PATH.map {|path| File.join(File.expand_path(path), "/")}
- ($LOADED_FEATURES - @orig_LOADED_FEATURES).each do |feat|
- unless paths.any? {|path| feat.start_with?(path)}
- $LOADED_FEATURES.delete(feat)
- end
- end
- else
- $LOADED_FEATURES.replace @orig_LOADED_FEATURES
- end
- end
-
- RbConfig::CONFIG['arch'] = @orig_arch
-
- if defined? Gem::RemoteFetcher
- Gem::RemoteFetcher.fetcher = nil
- end
-
- Dir.chdir @current_dir
-
- FileUtils.rm_rf @tempdir
-
- ENV.replace(@orig_env)
-
- Gem.ruby = @orig_ruby if @orig_ruby
-
- if Gem.java_platform?
- RbConfig::CONFIG['default_gem_home'] = @orig_default_gem_home
- else
- Gem.instance_variable_set :@default_dir, nil
- end
-
- Gem::Specification._clear_load_cache
- Gem::Specification.unresolved_deps.clear
- Gem::refresh
-
- @orig_hooks.each do |name, hooks|
- Gem.send(name).replace hooks
- end
-
- @back_ui.close
- end
-
- def common_installer_setup
- common_installer_teardown
-
- Gem.post_build do |installer|
- @post_build_hook_arg = installer
- true
- end
-
- Gem.post_install do |installer|
- @post_install_hook_arg = installer
- end
-
- Gem.post_uninstall do |uninstaller|
- @post_uninstall_hook_arg = uninstaller
- end
-
- Gem.pre_install do |installer|
- @pre_install_hook_arg = installer
- true
- end
-
- Gem.pre_uninstall do |uninstaller|
- @pre_uninstall_hook_arg = uninstaller
- end
- end
-
- def common_installer_teardown
- Gem.post_build_hooks.clear
- Gem.post_install_hooks.clear
- Gem.done_installing_hooks.clear
- Gem.post_reset_hooks.clear
- Gem.post_uninstall_hooks.clear
- Gem.pre_install_hooks.clear
- Gem.pre_reset_hooks.clear
- Gem.pre_uninstall_hooks.clear
- end
-
- ##
- # A git_gem is used with a gem dependencies file. The gem created here
- # has no files, just a gem specification for the given +name+ and +version+.
- #
- # Yields the +specification+ to the block, if given
-
- def git_gem(name = 'a', version = 1)
- have_git?
-
- directory = File.join 'git', name
- directory = File.expand_path directory
-
- git_spec = Gem::Specification.new name, version do |specification|
- yield specification if block_given?
- end
-
- FileUtils.mkdir_p directory
-
- gemspec = "#{name}.gemspec"
-
- File.open File.join(directory, gemspec), 'w' do |io|
- io.write git_spec.to_ruby
- end
-
- head = nil
-
- Dir.chdir directory do
- unless File.exist? '.git'
- system @git, 'init', '--quiet'
- system @git, 'config', 'user.name', 'RubyGems Tests'
- system @git, 'config', 'user.email', 'rubygems@example'
- end
-
- system @git, 'add', gemspec
- system @git, 'commit', '-a', '-m', 'a non-empty commit message', '--quiet'
- head = Gem::Util.popen(@git, 'rev-parse', 'master').strip
- end
-
- return name, git_spec.version, directory, head
- end
-
- ##
- # Skips this test unless you have a git executable
-
- def have_git?
- return if in_path? @git
-
- skip 'cannot find git executable, use GIT environment variable to set'
- end
-
- def in_path?(executable) # :nodoc:
- return true if %r%\A([A-Z]:|/)% =~ executable and File.exist? executable
-
- ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory|
- File.exist? File.join directory, executable
- end
- end
-
- ##
- # Builds and installs the Gem::Specification +spec+
-
- def install_gem(spec, options = {})
- require 'rubygems/installer'
-
- gem = File.join @tempdir, "gems", "#{spec.full_name}.gem"
-
- unless File.exist? gem
- use_ui Gem::MockGemUi.new do
- Dir.chdir @tempdir do
- Gem::Package.build spec
- end
- end
-
- gem = File.join(@tempdir, File.basename(spec.cache_file)).tap(&Gem::UNTAINT)
- end
-
- Gem::Installer.at(gem, options.merge({:wrappers => true})).install
- end
-
- ##
- # Builds and installs the Gem::Specification +spec+ into the user dir
-
- def install_gem_user(spec)
- install_gem spec, :user_install => true
- end
-
- ##
- # Uninstalls the Gem::Specification +spec+
- def uninstall_gem(spec)
- require 'rubygems/uninstaller'
-
- Class.new(Gem::Uninstaller) do
- def ask_if_ok(spec)
- true
- end
- end.new(spec.name, :executables => true, :user_install => true).uninstall
- end
-
- ##
- # Enables pretty-print for all tests
-
- def mu_pp(obj)
- s = String.new
- s = PP.pp obj, s
- s = s.force_encoding(Encoding.default_external)
- s.chomp
- end
-
- ##
- # Reads a Marshal file at +path+
-
- def read_cache(path)
- File.open path.dup.tap(&Gem::UNTAINT), 'rb' do |io|
- Marshal.load io.read
- end
- end
-
- ##
- # Reads a binary file at +path+
-
- def read_binary(path)
- Gem.read_binary path
- end
-
- ##
- # Writes a binary file to +path+ which is relative to +@gemhome+
-
- def write_file(path)
- path = File.join @gemhome, path unless Pathname.new(path).absolute?
- dir = File.dirname path
- FileUtils.mkdir_p dir unless File.directory? dir
-
- File.open path, 'wb' do |io|
- yield io if block_given?
- end
-
- path
- end
-
- def all_spec_names
- Gem::Specification.map(&:full_name)
- end
-
- ##
- # Creates a Gem::Specification with a minimum of extra work. +name+ and
- # +version+ are the gem's name and version, platform, author, email,
- # homepage, summary and description are defaulted. The specification is
- # yielded for customization.
- #
- # The gem is added to the installed gems in +@gemhome+ and the runtime.
- #
- # Use this with #write_file to build an installed gem.
-
- def quick_gem(name, version='2')
- require 'rubygems/specification'
-
- spec = Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = name
- s.version = version
- s.author = 'A User'
- s.email = 'example@example.com'
- s.homepage = 'http://example.com'
- s.summary = "this is a summary"
- s.description = "This is a test description"
-
- yield(s) if block_given?
- end
-
- Gem::Specification.map # HACK: force specs to (re-)load before we write
-
- written_path = write_file spec.spec_file do |io|
- io.write spec.to_ruby_for_cache
- end
-
- spec.loaded_from = written_path
-
- Gem::Specification.reset
-
- return spec
- end
-
- ##
- # Builds a gem from +spec+ and places it in <tt>File.join @gemhome,
- # 'cache'</tt>. Automatically creates files based on +spec.files+
-
- def util_build_gem(spec)
- dir = spec.gem_dir
- FileUtils.mkdir_p dir
-
- Dir.chdir dir do
- spec.files.each do |file|
- next if File.exist? file
- FileUtils.mkdir_p File.dirname(file)
-
- File.open file, 'w' do |fp|
- fp.puts "# #{file}"
- end
- end
-
- use_ui Gem::MockGemUi.new do
- Gem::Package.build spec
- end
-
- cache = spec.cache_file
- FileUtils.mv File.basename(cache), cache
- end
- end
-
- def util_remove_gem(spec)
- FileUtils.rm_rf spec.cache_file
- FileUtils.rm_rf spec.spec_file
- end
-
- ##
- # Removes all installed gems from +@gemhome+.
-
- def util_clear_gems
- FileUtils.rm_rf File.join(@gemhome, "gems")
- FileUtils.mkdir File.join(@gemhome, "gems")
- FileUtils.rm_rf File.join(@gemhome, "specifications")
- FileUtils.mkdir File.join(@gemhome, "specifications")
- Gem::Specification.reset
- end
-
- ##
- # Install the provided specs
-
- def install_specs(*specs)
- specs.each do |spec|
- Gem::Installer.for_spec(spec).install
- end
-
- Gem.searcher = nil
- end
-
- ##
- # Installs the provided default specs including writing the spec file
-
- def install_default_gems(*specs)
- install_default_specs(*specs)
-
- specs.each do |spec|
- File.open spec.loaded_from, 'w' do |io|
- io.write spec.to_ruby_for_cache
- end
- end
- end
-
- ##
- # Install the provided default specs
-
- def install_default_specs(*specs)
- specs.each do |spec|
- installer = Gem::Installer.for_spec(spec, :install_as_default => true)
- installer.install
- Gem.register_default_spec(spec)
- end
- end
-
- def loaded_spec_names
- Gem.loaded_specs.values.map(&:full_name).sort
- end
-
- def unresolved_names
- Gem::Specification.unresolved_deps.values.map(&:to_s).sort
- end
-
- def save_loaded_features
- old_loaded_features = $LOADED_FEATURES.dup
- yield
- ensure
- prefix = File.dirname(__FILE__) + "/"
- new_features = ($LOADED_FEATURES - old_loaded_features)
- old_loaded_features.concat(new_features.select {|f| f.rindex(prefix, 0)})
- $LOADED_FEATURES.replace old_loaded_features
- end
-
- def new_default_spec(name, version, deps = nil, *files)
- spec = util_spec name, version, deps
-
- spec.loaded_from = File.join(@default_spec_dir, spec.spec_name)
- spec.files = files
-
- lib_dir = File.join(@tempdir, "default_gems", "lib")
- lib_dir.instance_variable_set(:@gem_prelude_index, lib_dir)
- $LOAD_PATH.unshift(lib_dir)
- files.each do |file|
- rb_path = File.join(lib_dir, file)
- FileUtils.mkdir_p(File.dirname(rb_path))
- File.open(rb_path, "w") do |rb|
- rb << "# #{file}"
- end
- end
-
- spec
- end
-
- ##
- # Creates a spec with +name+, +version+. +deps+ can specify the dependency
- # or a +block+ can be given for full customization of the specification.
-
- def util_spec(name, version = 2, deps = nil, *files) # :yields: specification
- raise "deps or block, not both" if deps and block_given?
-
- spec = Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = name
- s.version = version
- s.author = 'A User'
- s.email = 'example@example.com'
- s.homepage = 'http://example.com'
- s.summary = "this is a summary"
- s.description = "This is a test description"
-
- s.files.push(*files) unless files.empty?
-
- yield s if block_given?
- end
-
- if deps
- # Since Hash#each is unordered in 1.8, sort the keys and iterate that
- # way so the tests are deterministic on all implementations.
- deps.keys.sort.each do |n|
- spec.add_dependency n, (deps[n] || '>= 0')
- end
- end
-
- unless files.empty?
- write_file spec.spec_file do |io|
- io.write spec.to_ruby_for_cache
- end
-
- util_build_gem spec
-
- cache_file = File.join @tempdir, 'gems', "#{spec.full_name}.gem"
- FileUtils.mkdir_p File.dirname cache_file
- FileUtils.mv spec.cache_file, cache_file
- FileUtils.rm spec.spec_file
- end
-
- return spec
- end
-
- ##
- # Creates a gem with +name+, +version+ and +deps+. The specification will
- # be yielded before gem creation for customization. The gem will be placed
- # in <tt>File.join @tempdir, 'gems'</tt>. The specification and .gem file
- # location are returned.
-
- def util_gem(name, version, deps = nil, &block)
- if deps
- block = proc do |s|
- # Since Hash#each is unordered in 1.8, sort
- # the keys and iterate that way so the tests are
- # deterministic on all implementations.
- deps.keys.sort.each do |n|
- s.add_dependency n, (deps[n] || '>= 0')
- end
- end
- end
-
- spec = quick_gem(name, version, &block)
-
- util_build_gem spec
-
- cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
- FileUtils.mkdir_p File.dirname cache_file
- FileUtils.mv spec.cache_file, cache_file
- FileUtils.rm spec.spec_file
-
- spec.loaded_from = nil
-
- [spec, cache_file]
- end
-
- ##
- # Gzips +data+.
-
- def util_gzip(data)
- out = StringIO.new
-
- Zlib::GzipWriter.wrap out do |io|
- io.write data
- end
-
- out.string
- end
-
- ##
- # Creates several default gems which all have a lib/code.rb file. The gems
- # are not installed but are available in the cache dir.
- #
- # +@a1+:: gem a version 1, this is the best-described gem.
- # +@a2+:: gem a version 2
- # +@a3a:: gem a version 3.a
- # +@a_evil9+:: gem a_evil version 9, use this to ensure similarly-named gems
- # don't collide with a.
- # +@b2+:: gem b version 2
- # +@c1_2+:: gem c version 1.2
- # +@pl1+:: gem pl version 1, this gem has a legacy platform of i386-linux.
- #
- # Additional +prerelease+ gems may also be created:
- #
- # +@a2_pre+:: gem a version 2.a
- # TODO: nuke this and fix tests. this should speed up a lot
-
- def util_make_gems(prerelease = false)
- @a1 = quick_gem 'a', '1' do |s|
- s.files = %w[lib/code.rb]
- s.require_paths = %w[lib]
- s.date = Gem::Specification::TODAY - 86400
- s.homepage = 'http://a.example.com'
- s.email = %w[example@example.com example2@example.com]
- s.authors = %w[Example Example2]
- s.description = <<-DESC
-This line is really, really long. So long, in fact, that it is more than eighty characters long! The purpose of this line is for testing wrapping behavior because sometimes people don't wrap their text to eighty characters. Without the wrapping, the text might not look good in the RSS feed.
-
-Also, a list:
- * An entry that\'s actually kind of sort
- * an entry that\'s really long, which will probably get wrapped funny. That's ok, somebody wasn't thinking straight when they made it more than eighty characters.
- DESC
- end
-
- init = proc do |s|
- s.files = %w[lib/code.rb]
- s.require_paths = %w[lib]
- end
-
- @a2 = quick_gem('a', '2', &init)
- @a3a = quick_gem('a', '3.a', &init)
- @a_evil9 = quick_gem('a_evil', '9', &init)
- @b2 = quick_gem('b', '2', &init)
- @c1_2 = quick_gem('c', '1.2', &init)
- @x = quick_gem('x', '1', &init)
- @dep_x = quick_gem('dep_x', '1') do |s|
- s.files = %w[lib/code.rb]
- s.require_paths = %w[lib]
- s.add_dependency 'x', '>= 1'
- end
-
- @pl1 = quick_gem 'pl', '1' do |s| # l for legacy
- s.files = %w[lib/code.rb]
- s.require_paths = %w[lib]
- s.platform = Gem::Platform.new 'i386-linux'
- s.instance_variable_set :@original_platform, 'i386-linux'
- end
-
- if prerelease
- @a2_pre = quick_gem('a', '2.a', &init)
- write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb])
- util_build_gem @a2_pre
- end
-
- write_file File.join(*%W[gems #{@a1.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@a2.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@a_evil9.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@b2.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@x.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb])
-
- [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1, @x, @dep_x].each do |spec|
- util_build_gem spec
- end
-
- FileUtils.rm_r File.join(@gemhome, "gems", @pl1.original_name)
- end
-
- ##
- # Set the platform to +arch+
-
- def util_set_arch(arch)
- RbConfig::CONFIG['arch'] = arch
- platform = Gem::Platform.new arch
-
- Gem.instance_variable_set :@platforms, nil
- Gem::Platform.instance_variable_set :@local, nil
-
- yield if block_given?
-
- platform
- end
-
- ##
- # Add +spec+ to +@fetcher+ serving the data in the file +path+.
- # +repo+ indicates which repo to make +spec+ appear to be in.
-
- def add_to_fetcher(spec, path=nil, repo=@gem_repo)
- path ||= spec.cache_file
- @fetcher.data["#{@gem_repo}gems/#{spec.file_name}"] = read_binary(path)
- end
-
- ##
- # Sets up Gem::SpecFetcher to return information from the gems in +specs+.
-
- def util_setup_spec_fetcher(*specs)
- all_specs = Gem::Specification.to_a + specs
- Gem::Specification._resort! all_specs
-
- spec_fetcher = Gem::SpecFetcher.fetcher
-
- prerelease, all = all_specs.partition { |spec| spec.version.prerelease? }
- latest = Gem::Specification._latest_specs all_specs
-
- spec_fetcher.specs[@uri] = []
- all.each do |spec|
- spec_fetcher.specs[@uri] << spec.name_tuple
- end
-
- spec_fetcher.latest_specs[@uri] = []
- latest.each do |spec|
- spec_fetcher.latest_specs[@uri] << spec.name_tuple
- end
-
- spec_fetcher.prerelease_specs[@uri] = []
- prerelease.each do |spec|
- spec_fetcher.prerelease_specs[@uri] << spec.name_tuple
- end
-
- # HACK for test_download_to_cache
- unless Gem::RemoteFetcher === @fetcher
- v = Gem.marshal_version
-
- specs = all.map { |spec| spec.name_tuple }
- s_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic specs
-
- latest_specs = latest.map do |spec|
- spec.name_tuple
- end
-
- l_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic latest_specs
-
- prerelease_specs = prerelease.map { |spec| spec.name_tuple }
- p_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic prerelease_specs
-
- @fetcher.data["#{@gem_repo}specs.#{v}.gz"] = s_zip
- @fetcher.data["#{@gem_repo}latest_specs.#{v}.gz"] = l_zip
- @fetcher.data["#{@gem_repo}prerelease_specs.#{v}.gz"] = p_zip
-
- v = Gem.marshal_version
-
- all_specs.each do |spec|
- path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz"
- data = Marshal.dump spec
- data_deflate = Zlib::Deflate.deflate data
- @fetcher.data[path] = data_deflate
- end
- end
-
- nil # force errors
- end
-
- ##
- # Deflates +data+
-
- def util_zip(data)
- Zlib::Deflate.deflate data
- end
-
- def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil, description = nil, engine = "ruby", engine_version = nil)
- if Gem.instance_variables.include? :@ruby_version
- Gem.send :remove_instance_variable, :@ruby_version
- end
-
- @RUBY_VERSION = RUBY_VERSION
- @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
- @RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION)
- @RUBY_DESCRIPTION = RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION)
- @RUBY_ENGINE = RUBY_ENGINE
- @RUBY_ENGINE_VERSION = RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION)
-
- util_clear_RUBY_VERSION
-
- Object.const_set :RUBY_VERSION, version
- Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel
- Object.const_set :RUBY_REVISION, revision if revision
- Object.const_set :RUBY_DESCRIPTION, description if description
- Object.const_set :RUBY_ENGINE, engine
- Object.const_set :RUBY_ENGINE_VERSION, engine_version if engine_version
- end
-
- def util_restore_RUBY_VERSION
- util_clear_RUBY_VERSION
-
- Object.const_set :RUBY_VERSION, @RUBY_VERSION
- Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if
- defined?(@RUBY_PATCHLEVEL)
- Object.const_set :RUBY_REVISION, @RUBY_REVISION if
- defined?(@RUBY_REVISION)
- Object.const_set :RUBY_DESCRIPTION, @RUBY_DESCRIPTION if
- defined?(@RUBY_DESCRIPTION)
- Object.const_set :RUBY_ENGINE, @RUBY_ENGINE
- Object.const_set :RUBY_ENGINE_VERSION, @RUBY_ENGINE_VERSION if
- defined?(@RUBY_ENGINE_VERSION)
- end
-
- def util_clear_RUBY_VERSION
- Object.send :remove_const, :RUBY_VERSION
- Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
- Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION)
- Object.send :remove_const, :RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION)
- Object.send :remove_const, :RUBY_ENGINE
- Object.send :remove_const, :RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION)
- end
-
- ##
- # Is this test being run on a Windows platform?
-
- def self.win_platform?
- Gem.win_platform?
- end
-
- ##
- # Is this test being run on a Windows platform?
-
- def win_platform?
- Gem.win_platform?
- end
-
- ##
- # Is this test being run on a Java platform?
-
- def self.java_platform?
- Gem.java_platform?
- end
-
- ##
- # Is this test being run on a Java platform?
-
- def java_platform?
- Gem.java_platform?
- end
-
- ##
- # Returns whether or not we're on a version of Ruby built with VC++ (or
- # Borland) versus Cygwin, Mingw, etc.
-
- def self.vc_windows?
- RUBY_PLATFORM.match('mswin')
- end
-
- ##
- # Returns whether or not we're on a version of Ruby built with VC++ (or
- # Borland) versus Cygwin, Mingw, etc.
-
- def vc_windows?
- RUBY_PLATFORM.match('mswin')
- end
-
- ##
- # Returns the make command for the current platform. For versions of Ruby
- # built on MS Windows with VC++ or Borland it will return 'nmake'. On all
- # other platforms, including Cygwin, it will return 'make'.
-
- def self.make_command
- ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make')
- end
-
- ##
- # Returns the make command for the current platform. For versions of Ruby
- # built on MS Windows with VC++ or Borland it will return 'nmake'. On all
- # other platforms, including Cygwin, it will return 'make'.
-
- def make_command
- ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make')
- end
-
- ##
- # Returns whether or not the nmake command could be found.
-
- def nmake_found?
- system('nmake /? 1>NUL 2>&1')
- end
-
- # In case we're building docs in a background process, this method waits for
- # that process to exit (or if it's already been reaped, or never happened,
- # swallows the Errno::ECHILD error).
- def wait_for_child_process_to_exit
- Process.wait if Process.respond_to?(:fork)
- rescue Errno::ECHILD
- end
-
- ##
- # Allows tests to use a random (but controlled) port number instead of
- # a hardcoded one. This helps CI tools when running parallels builds on
- # the same builder slave.
-
- def self.process_based_port
- @@process_based_port ||= 8000 + $$ % 1000
- end
-
- ##
- # See ::process_based_port
-
- def process_based_port
- self.class.process_based_port
- end
-
- ##
- # Allows the proper version of +rake+ to be used for the test.
-
- def build_rake_in(good=true)
- gem_ruby = Gem.ruby
- Gem.ruby = @@ruby
- env_rake = ENV["rake"]
- rake = (good ? @@good_rake : @@bad_rake)
- ENV["rake"] = rake
- yield rake
- ensure
- Gem.ruby = gem_ruby
- if env_rake
- ENV["rake"] = env_rake
- else
- ENV.delete("rake")
- end
- end
-
- ##
- # Finds the path to the Ruby executable
-
- def self.rubybin
- ruby = ENV["RUBY"]
- return ruby if ruby
- ruby = "ruby"
- rubyexe = "#{ruby}.exe"
-
- 3.times do
- if File.exist? ruby and File.executable? ruby and !File.directory? ruby
- return File.expand_path(ruby)
- end
- if File.exist? rubyexe and File.executable? rubyexe
- return File.expand_path(rubyexe)
- end
- ruby = File.join("..", ruby)
- end
-
- begin
- require "rbconfig"
- File.join(RbConfig::CONFIG["bindir"],
- RbConfig::CONFIG["ruby_install_name"] +
- RbConfig::CONFIG["EXEEXT"])
- rescue LoadError
- "ruby"
- end
- end
-
- def with_clean_path_to_ruby
- orig_ruby = Gem.ruby
-
- Gem.instance_variable_set :@ruby, nil
-
- yield
- ensure
- Gem.instance_variable_set :@ruby, orig_ruby
- end
-
- class << self
-
- # :nodoc:
- ##
- # Return the join path, with escaping backticks, dollars, and
- # double-quotes. Unlike `shellescape`, equal-sign is not escaped.
- private
-
- def escape_path(*path)
- path = File.join(*path)
- if %r'\A[-+:/=@,.\w]+\z' =~ path
- path
- else
- "\"#{path.gsub(/[`$"]/, '\\&')}\""
- end
- end
-
- end
-
- @@ruby = rubybin
- @@good_rake = "#{rubybin} #{escape_path(TEST_PATH, 'good_rake.rb')}"
- @@bad_rake = "#{rubybin} #{escape_path(TEST_PATH, 'bad_rake.rb')}"
-
- ##
- # Construct a new Gem::Dependency.
-
- def dep(name, *requirements)
- Gem::Dependency.new name, *requirements
- end
-
- ##
- # Constructs a Gem::Resolver::DependencyRequest from a
- # Gem::Dependency +dep+, a +from_name+ and +from_version+ requesting the
- # dependency and a +parent+ DependencyRequest
-
- def dependency_request(dep, from_name, from_version, parent = nil)
- remote = Gem::Source.new @uri
-
- unless parent
- parent_dep = dep from_name, from_version
- parent = Gem::Resolver::DependencyRequest.new parent_dep, nil
- end
-
- spec = Gem::Resolver::IndexSpecification.new \
- nil, from_name, from_version, remote, Gem::Platform::RUBY
- activation = Gem::Resolver::ActivationRequest.new spec, parent
-
- Gem::Resolver::DependencyRequest.new dep, activation
- end
-
- ##
- # Constructs a new Gem::Requirement.
-
- def req(*requirements)
- return requirements.first if Gem::Requirement === requirements.first
- Gem::Requirement.create requirements
- end
-
- ##
- # Constructs a new Gem::Specification.
-
- def spec(name, version, &block)
- Gem::Specification.new name, v(version), &block
- end
-
- ##
- # Creates a SpecFetcher pre-filled with the gems or specs defined in the
- # block.
- #
- # Yields a +fetcher+ object that responds to +spec+ and +gem+. +spec+ adds
- # a specification to the SpecFetcher while +gem+ adds both a specification
- # and the gem data to the RemoteFetcher so the built gem can be downloaded.
- #
- # If only the a-3 gem is supposed to be downloaded you can save setup
- # time by creating only specs for the other versions:
- #
- # spec_fetcher do |fetcher|
- # fetcher.spec 'a', 1
- # fetcher.spec 'a', 2, 'b' => 3 # dependency on b = 3
- # fetcher.gem 'a', 3 do |spec|
- # # spec is a Gem::Specification
- # # ...
- # end
- # end
-
- def spec_fetcher(repository = @gem_repo)
- Gem::TestCase::SpecFetcherSetup.declare self, repository do |spec_fetcher_setup|
- yield spec_fetcher_setup if block_given?
- end
- end
-
- ##
- # Construct a new Gem::Version.
-
- def v(string)
- Gem::Version.create string
- end
-
- ##
- # A vendor_gem is used with a gem dependencies file. The gem created here
- # has no files, just a gem specification for the given +name+ and +version+.
- #
- # Yields the +specification+ to the block, if given
-
- def vendor_gem(name = 'a', version = 1)
- directory = File.join 'vendor', name
-
- FileUtils.mkdir_p directory
-
- save_gemspec name, version, directory
- end
-
- ##
- # create_gemspec creates gem specification in given +directory+ or '.'
- # for the given +name+ and +version+.
- #
- # Yields the +specification+ to the block, if given
-
- def save_gemspec(name = 'a', version = 1, directory = '.')
- vendor_spec = Gem::Specification.new name, version do |specification|
- yield specification if block_given?
- end
-
- File.open File.join(directory, "#{name}.gemspec"), 'w' do |io|
- io.write vendor_spec.to_ruby
- end
-
- return name, vendor_spec.version, directory
- end
-
- ##
- # The StaticSet is a static set of gem specifications used for testing only.
- # It is available by requiring Gem::TestCase.
-
- class StaticSet < Gem::Resolver::Set
-
- ##
- # A StaticSet ignores remote because it has a fixed set of gems.
-
- attr_accessor :remote
-
- ##
- # Creates a new StaticSet for the given +specs+
-
- def initialize(specs)
- super()
-
- @specs = specs
-
- @remote = true
- end
-
- ##
- # Adds +spec+ to this set.
-
- def add(spec)
- @specs << spec
- end
-
- ##
- # Finds +dep+ in this set.
-
- def find_spec(dep)
- @specs.reverse_each do |s|
- return s if dep.matches_spec? s
- end
- end
-
- ##
- # Finds all gems matching +dep+ in this set.
-
- def find_all(dep)
- @specs.find_all { |s| dep.match? s, @prerelease }
- end
-
- ##
- # Loads a Gem::Specification from this set which has the given +name+,
- # version +ver+, +platform+. The +source+ is ignored.
-
- def load_spec(name, ver, platform, source)
- dep = Gem::Dependency.new name, ver
- spec = find_spec dep
-
- Gem::Specification.new spec.name, spec.version do |s|
- s.platform = spec.platform
- end
- end
-
- def prefetch(reqs) # :nodoc:
- end
-
- end
-
- ##
- # Loads certificate named +cert_name+ from <tt>test/rubygems/</tt>.
-
- def self.load_cert(cert_name)
- cert_file = cert_path cert_name
-
- cert = File.read cert_file
-
- OpenSSL::X509::Certificate.new cert
- end
-
- ##
- # Returns the path to the certificate named +cert_name+ from
- # <tt>test/rubygems/</tt>.
-
- def self.cert_path(cert_name)
- if 32 == (Time.at(2**32) rescue 32)
- cert_file = "#{TEST_PATH}/#{cert_name}_cert_32.pem"
-
- return cert_file if File.exist? cert_file
- end
-
- "#{TEST_PATH}/#{cert_name}_cert.pem"
- end
-
- ##
- # Loads an RSA private key named +key_name+ with +passphrase+ in <tt>test/rubygems/</tt>
-
- def self.load_key(key_name, passphrase = nil)
- key_file = key_path key_name
-
- key = File.read key_file
-
- OpenSSL::PKey::RSA.new key, passphrase
- end
-
- ##
- # Returns the path to the key named +key_name+ from <tt>test/rubygems</tt>
-
- def self.key_path(key_name)
- "#{TEST_PATH}/#{key_name}_key.pem"
- end
-
- # :stopdoc:
- # only available in RubyGems tests
-
- PRIVATE_KEY_PASSPHRASE = 'Foo bar'.freeze
-
- begin
- PRIVATE_KEY = load_key 'private'
- PRIVATE_KEY_PATH = key_path 'private'
-
- # ENCRYPTED_PRIVATE_KEY is PRIVATE_KEY encrypted with PRIVATE_KEY_PASSPHRASE
- ENCRYPTED_PRIVATE_KEY = load_key 'encrypted_private', PRIVATE_KEY_PASSPHRASE
- ENCRYPTED_PRIVATE_KEY_PATH = key_path 'encrypted_private'
-
- PUBLIC_KEY = PRIVATE_KEY.public_key
-
- PUBLIC_CERT = load_cert 'public'
- PUBLIC_CERT_PATH = cert_path 'public'
- rescue Errno::ENOENT
- PRIVATE_KEY = nil
- PUBLIC_KEY = nil
- PUBLIC_CERT = nil
- end if defined?(OpenSSL::SSL)
-
-end
-
-# require dependencies that are not discoverable once GEM_HOME and GEM_PATH
-# are wiped
-begin
- gem 'rake'
-rescue Gem::LoadError
-end
-
-begin
- require 'rake/packagetask'
-rescue LoadError
-end
-
-begin
- gem 'rdoc'
- require 'rdoc'
-
- require 'rubygems/rdoc'
-rescue LoadError, Gem::LoadError
-end
-
-begin
- gem 'builder'
- require 'builder/xchar'
-rescue LoadError, Gem::LoadError
-end
-
-require 'rubygems/test_utilities'
diff --git a/lib/rubygems/test_utilities.rb b/lib/rubygems/test_utilities.rb
deleted file mode 100644
index 69ff05370e..0000000000
--- a/lib/rubygems/test_utilities.rb
+++ /dev/null
@@ -1,380 +0,0 @@
-# frozen_string_literal: true
-require 'tempfile'
-require 'rubygems'
-require 'rubygems/remote_fetcher'
-
-##
-# A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP
-# requests when testing code that uses RubyGems.
-#
-# Example:
-#
-# @fetcher = Gem::FakeFetcher.new
-# @fetcher.data['http://gems.example.com/yaml'] = source_index.to_yaml
-# Gem::RemoteFetcher.fetcher = @fetcher
-#
-# use nested array if multiple response is needed
-#
-# @fetcher.data['http://gems.example.com/sequence'] = [['Success', 200, 'OK'], ['Failed', 401, 'Unauthorized']]
-#
-# @fetcher.fetch_path('http://gems.example.com/sequence') # => ['Success', 200, 'OK']
-# @fetcher.fetch_path('http://gems.example.com/sequence') # => ['Failed', 401, 'Unauthorized']
-#
-# # invoke RubyGems code
-#
-# paths = @fetcher.paths
-# assert_equal 'http://gems.example.com/yaml', paths.shift
-# assert paths.empty?, paths.join(', ')
-#
-# See RubyGems' tests for more examples of FakeFetcher.
-
-class Gem::FakeFetcher
-
- attr_reader :data
- attr_reader :last_request
- attr_accessor :paths
-
- def initialize
- @data = {}
- @paths = []
- end
-
- def find_data(path, nargs = 3)
- return File.read path.path if URI === path and 'file' == path.scheme
-
- if URI === path and "URI::#{path.scheme.upcase}" != path.class.name
- raise ArgumentError,
- "mismatch for scheme #{path.scheme} and class #{path.class}"
- end
-
- path = path.to_s
- @paths << path
- raise ArgumentError, 'need full URI' unless path =~ %r'^https?://'
-
- unless @data.key? path
- raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
- end
-
- data = @data[path]
-
- data.flatten! and return data.shift(nargs) if data.respond_to?(:flatten!)
- data
- end
-
- def fetch_path(path, mtime = nil, head = false)
- data = find_data(path)
-
- if data.respond_to?(:call)
- data.call
- else
- if path.to_s =~ /gz$/ and not data.nil? and not data.empty?
- data = Gem::Util.gunzip data
- end
- data
- end
- end
-
- def cache_update_path(uri, path = nil, update = true)
- if data = fetch_path(uri)
- open(path, 'wb') { |io| io.write data } if path and update
- data
- else
- Gem.read_binary(path) if path
- end
- end
-
- # Thanks, FakeWeb!
- def open_uri_or_path(path)
- data = find_data(path)
- body, code, msg = data
-
- response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
- response.instance_variable_set(:@body, body)
- response.instance_variable_set(:@read, true)
- response
- end
-
- def request(uri, request_class, last_modified = nil)
- data = find_data(uri)
- body, code, msg = (data.respond_to?(:call) ? data.call : data)
-
- @last_request = request_class.new uri.request_uri
- yield @last_request if block_given?
-
- response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
- response.instance_variable_set(:@body, body)
- response.instance_variable_set(:@read, true)
- response
- end
-
- def pretty_print(q) # :nodoc:
- q.group 2, '[FakeFetcher', ']' do
- q.breakable
- q.text 'URIs:'
-
- q.breakable
- q.pp @data.keys
- end
- end
-
- def fetch_size(path)
- path = path.to_s
- @paths << path
-
- raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
-
- unless @data.key? path
- raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
- end
-
- data = @data[path]
-
- data.respond_to?(:call) ? data.call : data.length
- end
-
- def download(spec, source_uri, install_dir = Gem.dir)
- name = File.basename spec.cache_file
- path = if Dir.pwd == install_dir # see fetch_command
- install_dir
- else
- File.join install_dir, "cache"
- end
-
- path = File.join path, name
-
- if source_uri =~ /^http/
- File.open(path, "wb") do |f|
- f.write fetch_path(File.join(source_uri, "gems", name))
- end
- else
- FileUtils.cp source_uri, path
- end
-
- path
- end
-
- def download_to_cache(dependency)
- found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dependency
-
- return if found.empty?
-
- spec, source = found.first
-
- download spec, source.uri.to_s
- end
-
-end
-
-# :stopdoc:
-class Gem::RemoteFetcher
-
- def self.fetcher=(fetcher)
- @fetcher = fetcher
- end
-
-end
-# :startdoc:
-
-##
-# The SpecFetcherSetup allows easy setup of a remote source in RubyGems tests:
-#
-# spec_fetcher do |f|
-# f.gem 'a', 1
-# f.spec 'a', 2
-# f.gem 'b', 1' 'a' => '~> 1.0'
-# end
-#
-# The above declaration creates two gems, a-1 and b-1, with a dependency from
-# b to a. The declaration creates an additional spec a-2, but no gem for it
-# (so it cannot be installed).
-#
-# After the gems are created they are removed from Gem.dir.
-
-class Gem::TestCase::SpecFetcherSetup
-
- ##
- # Executes a SpecFetcher setup block. Yields an instance then creates the
- # gems and specifications defined in the instance.
-
- def self.declare(test, repository)
- setup = new test, repository
-
- yield setup
-
- setup.execute
- end
-
- def initialize(test, repository) # :nodoc:
- @test = test
- @repository = repository
-
- @gems = {}
- @downloaded = []
- @installed = []
- @operations = []
- end
-
- ##
- # Returns a Hash of created Specification full names and the corresponding
- # Specification.
-
- def created_specs
- created = {}
-
- @gems.keys.each do |spec|
- created[spec.full_name] = spec
- end
-
- created
- end
-
- ##
- # Creates any defined gems or specifications
-
- def execute # :nodoc:
- execute_operations
-
- setup_fetcher
-
- created_specs
- end
-
- def execute_operations # :nodoc:
- @operations.each do |operation, *arguments|
- block = arguments.pop
- case operation
- when :gem then
- spec, gem = @test.util_gem(*arguments, &block)
-
- write_spec spec
-
- @gems[spec] = gem
- @installed << spec
- when :download then
- spec, gem = @test.util_gem(*arguments, &block)
-
- @gems[spec] = gem
- @downloaded << spec
- when :spec then
- spec = @test.util_spec(*arguments, &block)
-
- write_spec spec
-
- @gems[spec] = nil
- @installed << spec
- end
- end
- end
-
- ##
- # Creates a gem with +name+, +version+ and +deps+. The created gem can be
- # downloaded and installed.
- #
- # The specification will be yielded before gem creation for customization,
- # but only the block or the dependencies may be set, not both.
-
- def gem(name, version, dependencies = nil, &block)
- @operations << [:gem, name, version, dependencies, block]
- end
-
- ##
- # Creates a gem with +name+, +version+ and +deps+. The created gem is
- # downloaded in to the cache directory but is not installed
- #
- # The specification will be yielded before gem creation for customization,
- # but only the block or the dependencies may be set, not both.
-
- def download(name, version, dependencies = nil, &block)
- @operations << [:download, name, version, dependencies, block]
- end
-
- ##
- # Creates a legacy platform spec with the name 'pl' and version 1
-
- def legacy_platform
- spec 'pl', 1 do |s|
- s.platform = Gem::Platform.new 'i386-linux'
- s.instance_variable_set :@original_platform, 'i386-linux'
- end
- end
-
- def setup_fetcher # :nodoc:
- require 'zlib'
- require 'socket'
- require 'rubygems/remote_fetcher'
-
- unless @test.fetcher
- @test.fetcher = Gem::FakeFetcher.new
- Gem::RemoteFetcher.fetcher = @test.fetcher
- end
-
- Gem::Specification.reset
-
- begin
- gem_repo, @test.gem_repo = @test.gem_repo, @repository
- @test.uri = URI @repository
-
- @test.util_setup_spec_fetcher(*@downloaded)
- ensure
- @test.gem_repo = gem_repo
- @test.uri = URI gem_repo
- end
-
- @gems.each do |spec, gem|
- next unless gem
-
- @test.fetcher.data["#{@repository}gems/#{spec.file_name}"] =
- Gem.read_binary(gem)
-
- FileUtils.cp gem, spec.cache_file
- end
- end
-
- ##
- # Creates a spec with +name+, +version+ and +deps+. The created gem can be
- # downloaded and installed.
- #
- # The specification will be yielded before creation for customization,
- # but only the block or the dependencies may be set, not both.
-
- def spec(name, version, dependencies = nil, &block)
- @operations << [:spec, name, version, dependencies, block]
- end
-
- def write_spec(spec) # :nodoc:
- File.open spec.spec_file, 'w' do |io|
- io.write spec.to_ruby_for_cache
- end
- end
-
-end
-
-##
-# A StringIO duck-typed class that uses Tempfile instead of String as the
-# backing store.
-#
-# This is available when rubygems/test_utilities is required.
-#--
-# This class was added to flush out problems in Rubinius' IO implementation.
-
-class TempIO < Tempfile
-
- ##
- # Creates a new TempIO that will be initialized to contain +string+.
-
- def initialize(string = '')
- super "TempIO"
- binmode
- write string
- rewind
- end
-
- ##
- # The content of the TempIO as a String.
-
- def string
- flush
- Gem.read_binary path
- end
-
-end
diff --git a/lib/rubygems/tsort.rb b/lib/rubygems/tsort.rb
new file mode 100644
index 0000000000..ebe7c3364b
--- /dev/null
+++ b/lib/rubygems/tsort.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require_relative 'tsort/lib/tsort'
diff --git a/lib/rubygems/tsort/.document b/lib/rubygems/tsort/.document
new file mode 100644
index 0000000000..0c43bbd6b3
--- /dev/null
+++ b/lib/rubygems/tsort/.document
@@ -0,0 +1 @@
+# Vendored files do not need to be documented
diff --git a/lib/rubygems/tsort/LICENSE.txt b/lib/rubygems/tsort/LICENSE.txt
new file mode 100644
index 0000000000..a009caefea
--- /dev/null
+++ b/lib/rubygems/tsort/LICENSE.txt
@@ -0,0 +1,22 @@
+Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/lib/rubygems/tsort/lib/tsort.rb b/lib/rubygems/tsort/lib/tsort.rb
new file mode 100644
index 0000000000..f68c5947d3
--- /dev/null
+++ b/lib/rubygems/tsort/lib/tsort.rb
@@ -0,0 +1,454 @@
+# frozen_string_literal: true
+
+#--
+# tsort.rb - provides a module for topological sorting and strongly connected components.
+#++
+#
+
+#
+# Gem::TSort implements topological sorting using Tarjan's algorithm for
+# strongly connected components.
+#
+# Gem::TSort is designed to be able to be used with any object which can be
+# interpreted as a directed graph.
+#
+# Gem::TSort requires two methods to interpret an object as a graph,
+# tsort_each_node and tsort_each_child.
+#
+# * tsort_each_node is used to iterate for all nodes over a graph.
+# * tsort_each_child is used to iterate for child nodes of a given node.
+#
+# The equality of nodes are defined by eql? and hash since
+# Gem::TSort uses Hash internally.
+#
+# == A Simple Example
+#
+# The following example demonstrates how to mix the Gem::TSort module into an
+# existing class (in this case, Hash). Here, we're treating each key in
+# the hash as a node in the graph, and so we simply alias the required
+# #tsort_each_node method to Hash's #each_key method. For each key in the
+# hash, the associated value is an array of the node's child nodes. This
+# choice in turn leads to our implementation of the required #tsort_each_child
+# method, which fetches the array of child nodes and then iterates over that
+# array using the user-supplied block.
+#
+# require 'rubygems/tsort/lib/tsort'
+#
+# class Hash
+# include Gem::TSort
+# alias tsort_each_node each_key
+# def tsort_each_child(node, &block)
+# fetch(node).each(&block)
+# end
+# end
+#
+# {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort
+# #=> [3, 2, 1, 4]
+#
+# {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components
+# #=> [[4], [2, 3], [1]]
+#
+# == A More Realistic Example
+#
+# A very simple `make' like tool can be implemented as follows:
+#
+# require 'rubygems/tsort/lib/tsort'
+#
+# class Make
+# def initialize
+# @dep = {}
+# @dep.default = []
+# end
+#
+# def rule(outputs, inputs=[], &block)
+# triple = [outputs, inputs, block]
+# outputs.each {|f| @dep[f] = [triple]}
+# @dep[triple] = inputs
+# end
+#
+# def build(target)
+# each_strongly_connected_component_from(target) {|ns|
+# if ns.length != 1
+# fs = ns.delete_if {|n| Array === n}
+# raise Gem::TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}")
+# end
+# n = ns.first
+# if Array === n
+# outputs, inputs, block = n
+# inputs_time = inputs.map {|f| File.mtime f}.max
+# begin
+# outputs_time = outputs.map {|f| File.mtime f}.min
+# rescue Errno::ENOENT
+# outputs_time = nil
+# end
+# if outputs_time == nil ||
+# inputs_time != nil && outputs_time <= inputs_time
+# sleep 1 if inputs_time != nil && inputs_time.to_i == Time.now.to_i
+# block.call
+# end
+# end
+# }
+# end
+#
+# def tsort_each_child(node, &block)
+# @dep[node].each(&block)
+# end
+# include Gem::TSort
+# end
+#
+# def command(arg)
+# print arg, "\n"
+# system arg
+# end
+#
+# m = Make.new
+# m.rule(%w[t1]) { command 'date > t1' }
+# m.rule(%w[t2]) { command 'date > t2' }
+# m.rule(%w[t3]) { command 'date > t3' }
+# m.rule(%w[t4], %w[t1 t3]) { command 'cat t1 t3 > t4' }
+# m.rule(%w[t5], %w[t4 t2]) { command 'cat t4 t2 > t5' }
+# m.build('t5')
+#
+# == Bugs
+#
+# * 'tsort.rb' is wrong name because this library uses
+# Tarjan's algorithm for strongly connected components.
+# Although 'strongly_connected_components.rb' is correct but too long.
+#
+# == References
+#
+# R. E. Tarjan, "Depth First Search and Linear Graph Algorithms",
+# <em>SIAM Journal on Computing</em>, Vol. 1, No. 2, pp. 146-160, June 1972.
+#
+
+module Gem
+ module TSort
+ class Cyclic < StandardError
+ end
+
+ # Returns a topologically sorted array of nodes.
+ # The array is sorted from children to parents, i.e.
+ # the first element has no child and the last node has no parent.
+ #
+ # If there is a cycle, Gem::TSort::Cyclic is raised.
+ #
+ # class G
+ # include Gem::TSort
+ # def initialize(g)
+ # @g = g
+ # end
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
+ # def tsort_each_node(&b) @g.each_key(&b) end
+ # end
+ #
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
+ # p graph.tsort #=> [4, 2, 3, 1]
+ #
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
+ # p graph.tsort # raises Gem::TSort::Cyclic
+ #
+ def tsort
+ each_node = method(:tsort_each_node)
+ each_child = method(:tsort_each_child)
+ Gem::TSort.tsort(each_node, each_child)
+ end
+
+ # Returns a topologically sorted array of nodes.
+ # The array is sorted from children to parents, i.e.
+ # the first element has no child and the last node has no parent.
+ #
+ # The graph is represented by _each_node_ and _each_child_.
+ # _each_node_ should have +call+ method which yields for each node in the graph.
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
+ #
+ # If there is a cycle, Gem::TSort::Cyclic is raised.
+ #
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # p Gem::TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1]
+ #
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # p Gem::TSort.tsort(each_node, each_child) # raises Gem::TSort::Cyclic
+ #
+ def TSort.tsort(each_node, each_child)
+ Gem::TSort.tsort_each(each_node, each_child).to_a
+ end
+
+ # The iterator version of the #tsort method.
+ # <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, Gem::TSort::Cyclic is raised.
+ #
+ # class G
+ # include Gem::TSort
+ # def initialize(g)
+ # @g = g
+ # end
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
+ # def tsort_each_node(&b) @g.each_key(&b) end
+ # end
+ #
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
+ # graph.tsort_each {|n| p n }
+ # #=> 4
+ # # 2
+ # # 3
+ # # 1
+ #
+ def tsort_each(&block) # :yields: node
+ each_node = method(:tsort_each_node)
+ each_child = method(:tsort_each_child)
+ Gem::TSort.tsort_each(each_node, each_child, &block)
+ end
+
+ # The iterator version of the Gem::TSort.tsort method.
+ #
+ # The graph is represented by _each_node_ and _each_child_.
+ # _each_node_ should have +call+ method which yields for each node in the graph.
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
+ #
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # Gem::TSort.tsort_each(each_node, each_child) {|n| p n }
+ # #=> 4
+ # # 2
+ # # 3
+ # # 1
+ #
+ def TSort.tsort_each(each_node, each_child) # :yields: node
+ return to_enum(__method__, each_node, each_child) unless block_given?
+
+ Gem::TSort.each_strongly_connected_component(each_node, each_child) {|component|
+ if component.size == 1
+ yield component.first
+ else
+ raise Cyclic.new("topological sort failed: #{component.inspect}")
+ end
+ }
+ end
+
+ # Returns strongly connected components as an array of arrays of nodes.
+ # The array is sorted from children to parents.
+ # Each elements of the array represents a strongly connected component.
+ #
+ # class G
+ # include Gem::TSort
+ # def initialize(g)
+ # @g = g
+ # end
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
+ # def tsort_each_node(&b) @g.each_key(&b) end
+ # end
+ #
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
+ # p graph.strongly_connected_components #=> [[4], [2], [3], [1]]
+ #
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
+ # p graph.strongly_connected_components #=> [[4], [2, 3], [1]]
+ #
+ def strongly_connected_components
+ each_node = method(:tsort_each_node)
+ each_child = method(:tsort_each_child)
+ Gem::TSort.strongly_connected_components(each_node, each_child)
+ end
+
+ # Returns strongly connected components as an array of arrays of nodes.
+ # The array is sorted from children to parents.
+ # Each elements of the array represents a strongly connected component.
+ #
+ # The graph is represented by _each_node_ and _each_child_.
+ # _each_node_ should have +call+ method which yields for each node in the graph.
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
+ #
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # p Gem::TSort.strongly_connected_components(each_node, each_child)
+ # #=> [[4], [2], [3], [1]]
+ #
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # p Gem::TSort.strongly_connected_components(each_node, each_child)
+ # #=> [[4], [2, 3], [1]]
+ #
+ def TSort.strongly_connected_components(each_node, each_child)
+ Gem::TSort.each_strongly_connected_component(each_node, each_child).to_a
+ end
+
+ # The iterator version of the #strongly_connected_components method.
+ # <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 Gem::TSort
+ # def initialize(g)
+ # @g = g
+ # end
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
+ # def tsort_each_node(&b) @g.each_key(&b) end
+ # end
+ #
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
+ # graph.each_strongly_connected_component {|scc| p scc }
+ # #=> [4]
+ # # [2]
+ # # [3]
+ # # [1]
+ #
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
+ # graph.each_strongly_connected_component {|scc| p scc }
+ # #=> [4]
+ # # [2, 3]
+ # # [1]
+ #
+ def each_strongly_connected_component(&block) # :yields: nodes
+ each_node = method(:tsort_each_node)
+ each_child = method(:tsort_each_child)
+ Gem::TSort.each_strongly_connected_component(each_node, each_child, &block)
+ end
+
+ # The iterator version of the Gem::TSort.strongly_connected_components method.
+ #
+ # The graph is represented by _each_node_ and _each_child_.
+ # _each_node_ should have +call+ method which yields for each node in the graph.
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
+ #
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # Gem::TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
+ # #=> [4]
+ # # [2]
+ # # [3]
+ # # [1]
+ #
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
+ # each_node = lambda {|&b| g.each_key(&b) }
+ # each_child = lambda {|n, &b| g[n].each(&b) }
+ # Gem::TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
+ # #=> [4]
+ # # [2, 3]
+ # # [1]
+ #
+ def TSort.each_strongly_connected_component(each_node, each_child) # :yields: nodes
+ return to_enum(__method__, each_node, each_child) unless block_given?
+
+ id_map = {}
+ stack = []
+ each_node.call {|node|
+ unless id_map.include? node
+ Gem::TSort.each_strongly_connected_component_from(node, each_child, id_map, stack) {|c|
+ yield c
+ }
+ end
+ }
+ nil
+ end
+
+ # Iterates over strongly connected component in the subgraph reachable from
+ # _node_.
+ #
+ # Return value is unspecified.
+ #
+ # #each_strongly_connected_component_from doesn't call #tsort_each_node.
+ #
+ # class G
+ # include Gem::TSort
+ # def initialize(g)
+ # @g = g
+ # end
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
+ # def tsort_each_node(&b) @g.each_key(&b) end
+ # end
+ #
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
+ # #=> [4]
+ # # [2]
+ #
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
+ # #=> [4]
+ # # [2, 3]
+ #
+ def each_strongly_connected_component_from(node, id_map={}, stack=[], &block) # :yields: nodes
+ Gem::TSort.each_strongly_connected_component_from(node, method(:tsort_each_child), id_map, stack, &block)
+ end
+
+ # Iterates over strongly connected components in a graph.
+ # The graph is represented by _node_ and _each_child_.
+ #
+ # _node_ is the first node.
+ # _each_child_ should have +call+ method which takes a node argument
+ # and yields for each child node.
+ #
+ # Return value is unspecified.
+ #
+ # #Gem::TSort.each_strongly_connected_component_from is a class method and
+ # it doesn't need a class to represent a graph which includes Gem::TSort.
+ #
+ # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
+ # each_child = lambda {|n, &b| graph[n].each(&b) }
+ # Gem::TSort.each_strongly_connected_component_from(1, each_child) {|scc|
+ # p scc
+ # }
+ # #=> [4]
+ # # [2, 3]
+ # # [1]
+ #
+ def TSort.each_strongly_connected_component_from(node, each_child, id_map={}, stack=[]) # :yields: nodes
+ return to_enum(__method__, node, each_child, id_map, stack) unless block_given?
+
+ minimum_id = node_id = id_map[node] = id_map.size
+ stack_length = stack.length
+ stack << node
+
+ each_child.call(node) {|child|
+ if id_map.include? child
+ child_id = id_map[child]
+ minimum_id = child_id if child_id && child_id < minimum_id
+ else
+ sub_minimum_id =
+ Gem::TSort.each_strongly_connected_component_from(child, each_child, id_map, stack) {|c|
+ yield c
+ }
+ minimum_id = sub_minimum_id if sub_minimum_id < minimum_id
+ end
+ }
+
+ if node_id == minimum_id
+ component = stack.slice!(stack_length .. -1)
+ component.each {|n| id_map[n] = nil}
+ yield component
+ end
+
+ minimum_id
+ end
+
+ # Should be implemented by a extended class.
+ #
+ # #tsort_each_node is used to iterate for all nodes over a graph.
+ #
+ def tsort_each_node # :yields: node
+ raise NotImplementedError.new
+ end
+
+ # Should be implemented by a extended class.
+ #
+ # #tsort_each_child is used to iterate for child nodes of _node_.
+ #
+ def tsort_each_child(node) # :yields: child
+ raise NotImplementedError.new
+ end
+ end
+end
diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb
index 20b437d472..1c3bf260c2 100644
--- a/lib/rubygems/uninstaller.rb
+++ b/lib/rubygems/uninstaller.rb
@@ -6,10 +6,11 @@
#++
require 'fileutils'
-require 'rubygems'
-require 'rubygems/dependency_list'
-require 'rubygems/rdoc'
-require 'rubygems/user_interaction'
+require_relative '../rubygems'
+require_relative 'installer_uninstaller_utils'
+require_relative 'dependency_list'
+require_relative 'rdoc'
+require_relative 'user_interaction'
##
# An Uninstaller.
@@ -20,9 +21,10 @@ require 'rubygems/user_interaction'
# file. See Gem.pre_uninstall and Gem.post_uninstall for details.
class Gem::Uninstaller
-
include Gem::UserInteraction
+ include Gem::InstallerUninstallerUtils
+
##
# The directory a gem's executables will be installed into
@@ -47,6 +49,7 @@ class Gem::Uninstaller
@gem = gem
@version = options[:version] || Gem::Requirement.default
@gem_home = File.realpath(options[:install_dir] || Gem.dir)
+ @plugins_dir = Gem.plugindir(@gem_home)
@force_executables = options[:executables]
@force_all = options[:all]
@force_ignore = options[:ignore]
@@ -67,6 +70,9 @@ class Gem::Uninstaller
# only add user directory if install_dir is not set
@user_install = false
@user_install = options[:user_install] unless options[:install_dir]
+
+ # Optimization: populated during #uninstall
+ @default_specs_matching_uninstall_params = []
end
##
@@ -95,10 +101,8 @@ class Gem::Uninstaller
default_specs, list = list.partition do |spec|
spec.default_gem?
end
-
- default_specs.each do |default_spec|
- say "Gem #{default_spec.full_name} cannot be uninstalled because it is a default gem"
- end
+ warn_cannot_uninstall_default_gems(default_specs - list)
+ @default_specs_matching_uninstall_params = default_specs
list, other_repo_specs = list.partition do |spec|
@gem_home == spec.base_dir or
@@ -110,10 +114,10 @@ class Gem::Uninstaller
if list.empty?
return unless other_repo_specs.any?
- other_repos = other_repo_specs.map { |spec| spec.base_dir }.uniq
+ other_repos = other_repo_specs.map {|spec| spec.base_dir }.uniq
message = ["#{@gem} is not installed in GEM_HOME, try:"]
- message.concat other_repos.map { |repo|
+ message.concat other_repos.map {|repo|
"\tgem uninstall -i #{repo} #{@gem}"
}
@@ -122,7 +126,7 @@ class Gem::Uninstaller
remove_all list
elsif list.size > 1
- gem_names = list.map { |gem| gem.full_name }
+ gem_names = list.map {|gem| gem.full_name }
gem_names << "All versions"
say
@@ -158,8 +162,11 @@ class Gem::Uninstaller
end
remove_executables @spec
+ remove_plugins @spec
remove @spec
+ regenerate_plugins
+
Gem.post_uninstall_hooks.each do |hook|
hook.call self
end
@@ -168,11 +175,10 @@ class Gem::Uninstaller
end
##
- # Removes installed executables and batch files (windows only) for
- # +gemspec+.
+ # Removes installed executables and batch files (windows only) for +spec+.
def remove_executables(spec)
- return if spec.nil? or spec.executables.empty?
+ return if spec.executables.empty?
executables = spec.executables.clone
@@ -191,7 +197,7 @@ class Gem::Uninstaller
return if executables.empty?
- executables = executables.map { |exec| formatted_program_filename exec }
+ executables = executables.map {|exec| formatted_program_filename exec }
remove = if @force_executables.nil?
ask_yes_no("Remove executables:\n" +
@@ -226,15 +232,11 @@ class Gem::Uninstaller
# NOTE: removes uninstalled gems from +list+.
def remove_all(list)
- list.each { |spec| uninstall_gem spec }
+ list.each {|spec| uninstall_gem spec }
end
##
# spec:: the spec of the gem to be uninstalled
- # list:: the list of all such gems
- #
- # Warning: this method modifies the +list+ parameter. Once it has
- # uninstalled a gem, it is removed from that list.
def remove(spec)
unless path_ok?(@gem_home, spec) or
@@ -269,12 +271,31 @@ class Gem::Uninstaller
end
safe_delete { FileUtils.rm_r gemspec }
- say "Successfully uninstalled #{spec.full_name}"
+ announce_deletion_of(spec)
Gem::Specification.reset
end
##
+ # Remove any plugin wrappers for +spec+.
+
+ def remove_plugins(spec) # :nodoc:
+ return if spec.plugins.empty?
+
+ remove_plugins_for(spec, @plugins_dir)
+ end
+
+ ##
+ # Regenerates plugin wrappers after removal.
+
+ def regenerate_plugins
+ latest = Gem::Specification.latest_spec_for(@spec.name)
+ return if latest.nil?
+
+ regenerate_plugins_for(latest, @plugins_dir)
+ end
+
+ ##
# Is +spec+ in +gem_dir+?
def path_ok?(gem_dir, spec)
@@ -317,8 +338,8 @@ class Gem::Uninstaller
s.name == spec.name && s.full_name != spec.full_name
end
- spec.dependent_gems.each do |dep_spec, dep, satlist|
- unless siblings.any? { |s| s.satisfies_requirement? dep }
+ spec.dependent_gems(@check_dev).each do |dep_spec, dep, satlist|
+ unless siblings.any? {|s| s.satisfies_requirement? dep }
msg << "#{dep_spec.name}-#{dep_spec.version} depends on #{dep}"
end
end
@@ -336,7 +357,7 @@ class Gem::Uninstaller
# of what it did for us to find rather than trying to recreate
# it again.
if @format_executable
- require 'rubygems/installer'
+ require_relative 'installer'
Gem::Installer.exec_format % File.basename(filename)
else
filename
@@ -354,4 +375,33 @@ class Gem::Uninstaller
raise e
end
+ private
+
+ def announce_deletion_of(spec)
+ name = spec.full_name
+ say "Successfully uninstalled #{name}"
+ if default_spec_matches?(spec)
+ say(
+ "There was both a regular copy and a default copy of #{name}. The " \
+ "regular copy was successfully uninstalled, but the default copy " \
+ "was left around because default gems can't be removed."
+ )
+ end
+ end
+
+ # @return true if the specs of any default gems are `==` to the given `spec`.
+ def default_spec_matches?(spec)
+ !default_specs_that_match(spec).empty?
+ end
+
+ # @return [Array] specs of default gems that are `==` to the given `spec`.
+ def default_specs_that_match(spec)
+ @default_specs_matching_uninstall_params.select {|default_spec| spec == default_spec }
+ end
+
+ def warn_cannot_uninstall_default_gems(specs)
+ specs.each do |spec|
+ say "Gem #{spec.full_name} cannot be uninstalled because it is a default gem"
+ end
+ end
end
diff --git a/lib/rubygems/uri.rb b/lib/rubygems/uri.rb
new file mode 100644
index 0000000000..ba30fac2f5
--- /dev/null
+++ b/lib/rubygems/uri.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+##
+# The Uri handles rubygems source URIs.
+#
+
+class Gem::Uri
+ def initialize(source_uri)
+ @parsed_uri = parse(source_uri)
+ end
+
+ def redacted
+ return self unless valid_uri?
+
+ if token? || oauth_basic?
+ with_redacted_user
+ elsif password?
+ with_redacted_password
+ else
+ self
+ end
+ end
+
+ def to_s
+ @parsed_uri.to_s
+ end
+
+ def redact_credentials_from(text)
+ return text unless valid_uri? && password?
+
+ text.sub(password, 'REDACTED')
+ end
+
+ def method_missing(method_name, *args, &blk)
+ if @parsed_uri.respond_to?(method_name)
+ @parsed_uri.send(method_name, *args, &blk)
+ else
+ super
+ end
+ end
+
+ def respond_to_missing?(method_name, include_private = false)
+ @parsed_uri.respond_to?(method_name, include_private) || super
+ end
+
+ protected
+
+ # Add a protected reader for the cloned instance to access the original object's parsed uri
+ attr_reader :parsed_uri
+
+ private
+
+ ##
+ # Parses the #uri, raising if it's invalid
+
+ def parse!(uri)
+ require "uri"
+
+ raise URI::InvalidURIError unless uri
+
+ # Always escape URI's to deal with potential spaces and such
+ # It should also be considered that source_uri may already be
+ # a valid URI with escaped characters. e.g. "{DESede}" is encoded
+ # as "%7BDESede%7D". If this is escaped again the percentage
+ # symbols will be escaped.
+ begin
+ URI.parse(uri)
+ rescue URI::InvalidURIError
+ URI.parse(URI::DEFAULT_PARSER.escape(uri))
+ end
+ end
+
+ ##
+ # Parses the #uri, returning the original uri if it's invalid
+
+ def parse(uri)
+ return uri unless uri.is_a?(String)
+
+ parse!(uri)
+ rescue URI::InvalidURIError
+ uri
+ end
+
+ def with_redacted_user
+ clone.tap {|uri| uri.user = 'REDACTED' }
+ end
+
+ def with_redacted_password
+ clone.tap {|uri| uri.password = 'REDACTED' }
+ end
+
+ def valid_uri?
+ !@parsed_uri.is_a?(String)
+ end
+
+ def password?
+ !!password
+ end
+
+ def oauth_basic?
+ password == 'x-oauth-basic'
+ end
+
+ def token?
+ !user.nil? && password.nil?
+ end
+
+ def initialize_copy(original)
+ @parsed_uri = original.parsed_uri.clone
+ end
+end
diff --git a/lib/rubygems/uri_formatter.rb b/lib/rubygems/uri_formatter.rb
index f3d510470b..3bda896875 100644
--- a/lib/rubygems/uri_formatter.rb
+++ b/lib/rubygems/uri_formatter.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-require 'cgi'
##
# The UriFormatter handles URIs from user-input and escaping.
@@ -9,7 +8,6 @@ require 'cgi'
# p uf.normalize #=> 'http://example.com'
class Gem::UriFormatter
-
##
# The URI to be formatted.
@@ -19,6 +17,8 @@ class Gem::UriFormatter
# Creates a new URI formatter for +uri+.
def initialize(uri)
+ require 'cgi'
+
@uri = uri
end
@@ -44,5 +44,4 @@ class Gem::UriFormatter
return unless @uri
CGI.unescape @uri
end
-
end
diff --git a/lib/rubygems/uri_parser.rb b/lib/rubygems/uri_parser.rb
deleted file mode 100644
index 5c7cabc436..0000000000
--- a/lib/rubygems/uri_parser.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-##
-# The UriParser handles parsing URIs.
-#
-
-class Gem::UriParser
-
- ##
- # Parses the #uri, raising if it's invalid
-
- def parse!(uri)
- raise URI::InvalidURIError unless uri
-
- # Always escape URI's to deal with potential spaces and such
- # It should also be considered that source_uri may already be
- # a valid URI with escaped characters. e.g. "{DESede}" is encoded
- # as "%7BDESede%7D". If this is escaped again the percentage
- # symbols will be escaped.
- begin
- URI.parse(uri)
- rescue URI::InvalidURIError
- URI.parse(URI::DEFAULT_PARSER.escape(uri))
- end
- end
-
- ##
- # Parses the #uri, returning the original uri if it's invalid
-
- def parse(uri)
- parse!(uri)
- rescue URI::InvalidURIError
- uri
- end
-
-end
diff --git a/lib/rubygems/uri_parsing.rb b/lib/rubygems/uri_parsing.rb
deleted file mode 100644
index 941d7e023a..0000000000
--- a/lib/rubygems/uri_parsing.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require "rubygems/uri_parser"
-
-module Gem::UriParsing
-
- def parse_uri(source_uri)
- return source_uri unless source_uri.is_a?(String)
-
- uri_parser.parse(source_uri)
- end
-
- private :parse_uri
-
- def uri_parser
- require "uri"
-
- Gem::UriParser.new
- end
-
- private :uri_parser
-
-end
diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb
index 93f528a763..0ab44fbf6c 100644
--- a/lib/rubygems/user_interaction.rb
+++ b/lib/rubygems/user_interaction.rb
@@ -5,9 +5,8 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/util'
-require 'rubygems/deprecate'
-require 'rubygems/text'
+require_relative 'deprecate'
+require_relative 'text'
##
# Module that defines the default UserInteraction. Any class including this
@@ -173,7 +172,6 @@ end
# Gem::StreamUI implements a simple stream based user interface.
class Gem::StreamUI
-
extend Gem::Deprecate
##
@@ -323,7 +321,7 @@ class Gem::StreamUI
def _gets_noecho
require_io_console
- @ins.noecho {@ins.gets}
+ @ins.noecho { @ins.gets }
end
##
@@ -359,14 +357,6 @@ class Gem::StreamUI
end
##
- # Display a debug message on the same location as error messages.
-
- def debug(statement)
- @errs.puts statement
- end
- deprecate :debug, :none, 2018, 12
-
- ##
# Terminate the application with exit code +status+, running any exit
# handlers that might have been defined.
@@ -396,7 +386,6 @@ class Gem::StreamUI
# An absolutely silent progress reporter.
class SilentProgressReporter
-
##
# The count of items is never updated for the silent progress reporter.
@@ -421,14 +410,12 @@ class Gem::StreamUI
def done
end
-
end
##
# A basic dotted progress reporter.
class SimpleProgressReporter
-
include Gem::DefaultUserInteraction
##
@@ -466,14 +453,12 @@ class Gem::StreamUI
def done
@out.puts "\n#{@terminal_message}"
end
-
end
##
# A progress reporter that prints out messages about the current progress.
class VerboseProgressReporter
-
include Gem::DefaultUserInteraction
##
@@ -510,7 +495,6 @@ class Gem::StreamUI
def done
@out.puts @terminal_message
end
-
end
##
@@ -528,7 +512,6 @@ class Gem::StreamUI
# An absolutely silent download reporter.
class SilentDownloadReporter
-
##
# The silent download reporter ignores all arguments
@@ -554,15 +537,13 @@ class Gem::StreamUI
def done
end
-
end
##
# A progress reporter that behaves nicely with threaded downloading.
class ThreadedDownloadReporter
-
- MUTEX = Mutex.new
+ MUTEX = Thread::Mutex.new
##
# The current file name being displayed
@@ -610,9 +591,7 @@ class Gem::StreamUI
@out.puts message
end
end
-
end
-
end
##
@@ -620,7 +599,6 @@ end
# STDOUT, and STDERR.
class Gem::ConsoleUI < Gem::StreamUI
-
##
# The Console UI has no arguments as it defaults to reading input from
# stdin, output to stdout and warnings or errors to stderr.
@@ -628,14 +606,12 @@ class Gem::ConsoleUI < Gem::StreamUI
def initialize
super STDIN, STDOUT, STDERR, true
end
-
end
##
# SilentUI is a UI choice that is absolutely silent.
class Gem::SilentUI < Gem::StreamUI
-
##
# The SilentUI has no arguments as it does not use any stream.
@@ -661,5 +637,4 @@ class Gem::SilentUI < Gem::StreamUI
def progress_reporter(*args) # :nodoc:
SilentProgressReporter.new(@outs, *args)
end
-
end
diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb
index 7fc239af9a..4363c5adce 100644
--- a/lib/rubygems/util.rb
+++ b/lib/rubygems/util.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
+require_relative 'deprecate'
+
##
# This module contains various utility methods as module methods.
module Gem::Util
- @silent_mutex = nil
-
##
# Zlib::GzipReader wrapper that unzips +data+.
@@ -70,6 +70,12 @@ module Gem::Util
system(*(cmds << opt))
end
+ class << self
+ extend Gem::Deprecate
+
+ rubygems_deprecate :silent_system
+ end
+
##
# Enumerates the parents of +directory+.
diff --git a/lib/rubygems/util/licenses.rb b/lib/rubygems/util/licenses.rb
index f23be157b9..3f4178c6e0 100644
--- a/lib/rubygems/util/licenses.rb
+++ b/lib/rubygems/util/licenses.rb
@@ -1,15 +1,15 @@
# frozen_string_literal: true
-require 'rubygems/text'
+require_relative '../text'
class Gem::Licenses
-
extend Gem::Text
NONSTANDARD = 'Nonstandard'.freeze
+ LICENSE_REF = 'LicenseRef-.+'.freeze
# Software Package Data Exchange (SPDX) standard open-source software
# license identifiers
- LICENSE_IDENTIFIERS = %w(
+ LICENSE_IDENTIFIERS = %w[
0BSD
AAL
ADSL
@@ -19,6 +19,8 @@ class Gem::Licenses
AFL-2.1
AFL-3.0
AGPL-1.0
+ AGPL-1.0-only
+ AGPL-1.0-or-later
AGPL-3.0
AGPL-3.0-only
AGPL-3.0-or-later
@@ -26,6 +28,7 @@ class Gem::Licenses
AML
AMPAS
ANTLR-PD
+ ANTLR-PD-fallback
APAFML
APL-1.0
APSL-1.0
@@ -49,29 +52,41 @@ class Gem::Licenses
BSD-2-Clause-FreeBSD
BSD-2-Clause-NetBSD
BSD-2-Clause-Patent
+ BSD-2-Clause-Views
BSD-3-Clause
BSD-3-Clause-Attribution
BSD-3-Clause-Clear
BSD-3-Clause-LBNL
+ BSD-3-Clause-Modification
+ BSD-3-Clause-No-Military-License
BSD-3-Clause-No-Nuclear-License
BSD-3-Clause-No-Nuclear-License-2014
BSD-3-Clause-No-Nuclear-Warranty
+ BSD-3-Clause-Open-MPI
BSD-4-Clause
+ BSD-4-Clause-Shortened
BSD-4-Clause-UC
BSD-Protection
BSD-Source-Code
BSL-1.0
+ BUSL-1.1
Bahyph
Barr
Beerware
BitTorrent-1.0
BitTorrent-1.1
+ BlueOak-1.0.0
Borceux
+ C-UDA-1.0
+ CAL-1.0
+ CAL-1.0-Combined-Work-Exception
CATOSL-1.1
CC-BY-1.0
CC-BY-2.0
CC-BY-2.5
CC-BY-3.0
+ CC-BY-3.0-AT
+ CC-BY-3.0-US
CC-BY-4.0
CC-BY-NC-1.0
CC-BY-NC-2.0
@@ -82,6 +97,7 @@ class Gem::Licenses
CC-BY-NC-ND-2.0
CC-BY-NC-ND-2.5
CC-BY-NC-ND-3.0
+ CC-BY-NC-ND-3.0-IGO
CC-BY-NC-ND-4.0
CC-BY-NC-SA-1.0
CC-BY-NC-SA-2.0
@@ -95,12 +111,17 @@ class Gem::Licenses
CC-BY-ND-4.0
CC-BY-SA-1.0
CC-BY-SA-2.0
+ CC-BY-SA-2.0-UK
+ CC-BY-SA-2.1-JP
CC-BY-SA-2.5
CC-BY-SA-3.0
+ CC-BY-SA-3.0-AT
CC-BY-SA-4.0
+ CC-PDDC
CC0-1.0
CDDL-1.0
CDDL-1.1
+ CDL-1.0
CDLA-Permissive-1.0
CDLA-Sharing-1.0
CECILL-1.0
@@ -109,6 +130,11 @@ class Gem::Licenses
CECILL-2.1
CECILL-B
CECILL-C
+ CERN-OHL-1.1
+ CERN-OHL-1.2
+ CERN-OHL-P-2.0
+ CERN-OHL-S-2.0
+ CERN-OHL-W-2.0
CNRI-Jython
CNRI-Python
CNRI-Python-GPL-Compatible
@@ -124,12 +150,14 @@ class Gem::Licenses
Cube
D-FSL-1.0
DOC
+ DRL-1.0
DSDP
Dotseqn
ECL-1.0
ECL-2.0
EFL-1.0
EFL-2.0
+ EPICS
EPL-1.0
EPL-2.0
EUDatagrid
@@ -145,17 +173,32 @@ class Gem::Licenses
FTL
Fair
Frameworx-1.0
+ FreeBSD-DOC
FreeImage
+ GD
GFDL-1.1
+ GFDL-1.1-invariants-only
+ GFDL-1.1-invariants-or-later
+ GFDL-1.1-no-invariants-only
+ GFDL-1.1-no-invariants-or-later
GFDL-1.1-only
GFDL-1.1-or-later
GFDL-1.2
+ GFDL-1.2-invariants-only
+ GFDL-1.2-invariants-or-later
+ GFDL-1.2-no-invariants-only
+ GFDL-1.2-no-invariants-or-later
GFDL-1.2-only
GFDL-1.2-or-later
GFDL-1.3
+ GFDL-1.3-invariants-only
+ GFDL-1.3-invariants-or-later
+ GFDL-1.3-no-invariants-only
+ GFDL-1.3-no-invariants-or-later
GFDL-1.3-only
GFDL-1.3-or-later
GL2PS
+ GLWTPL
GPL-1.0
GPL-1.0+
GPL-1.0-only
@@ -179,7 +222,10 @@ class Gem::Licenses
Glide
Glulxe
HPND
+ HPND-sell-variant
+ HTMLTIDY
HaskellReport
+ Hippocratic-2.1
IBM-pibs
ICU
IJG
@@ -192,6 +238,7 @@ class Gem::Licenses
Intel
Intel-ACPI
Interbase-1.0
+ JPNIC
JSON
JasPer-2.0
LAL-1.2
@@ -222,11 +269,15 @@ class Gem::Licenses
LiLiQ-R-1.1
LiLiQ-Rplus-1.1
Libpng
+ Linux-OpenIB
MIT
+ MIT-0
MIT-CMU
+ MIT-Modern-Variant
MIT-advertising
MIT-enna
MIT-feh
+ MIT-open-group
MITNFA
MPL-1.0
MPL-1.1
@@ -238,12 +289,18 @@ class Gem::Licenses
MakeIndex
MirOS
Motosoto
+ MulanPSL-1.0
+ MulanPSL-2.0
Multics
Mup
+ NAIST-2003
NASA-1.3
NBPL-1.0
+ NCGL-UK-2.0
NCSA
NGPL
+ NIST-PD
+ NIST-PD-fallback
NLOD-1.0
NLPL
NOSL
@@ -252,6 +309,7 @@ class Gem::Licenses
NPOSL-3.0
NRL
NTP
+ NTP-0
Naumen
Net-SNMP
NetCDF
@@ -259,11 +317,23 @@ class Gem::Licenses
Nokia
Noweb
Nunit
+ O-UDA-1.0
OCCT-PL
OCLC-2.0
+ ODC-By-1.0
ODbL-1.0
OFL-1.0
+ OFL-1.0-RFN
+ OFL-1.0-no-RFN
OFL-1.1
+ OFL-1.1-RFN
+ OFL-1.1-no-RFN
+ OGC-1.0
+ OGDL-Taiwan-1.0
+ OGL-Canada-2.0
+ OGL-UK-1.0
+ OGL-UK-2.0
+ OGL-UK-3.0
OGTSL
OLDAP-1.1
OLDAP-1.2
@@ -293,7 +363,12 @@ class Gem::Licenses
PDDL-1.0
PHP-3.0
PHP-3.01
+ PSF-2.0
+ Parity-6.0.0
+ Parity-7.0.0
Plexus
+ PolyForm-Noncommercial-1.0.0
+ PolyForm-Small-Business-1.0.0
PostgreSQL
Python-2.0
QPL-1.0
@@ -311,15 +386,21 @@ class Gem::Licenses
SGI-B-1.0
SGI-B-1.1
SGI-B-2.0
+ SHL-0.5
+ SHL-0.51
SISSL
SISSL-1.2
SMLNJ
SMPPL
SNIA
SPL-1.0
+ SSH-OpenSSH
+ SSH-short
+ SSPL-1.0
SWL
Saxpath
Sendmail
+ Sendmail-8.23
SimPL-2.0
Sleepycat
Spencer-86
@@ -327,11 +408,15 @@ class Gem::Licenses
Spencer-99
StandardML-NJ
SugarCRM-1.1.3
+ TAPR-OHL-1.0
TCL
TCP-wrappers
TMate
TORQUE-1.1
TOSL
+ TU-Berlin-1.0
+ TU-Berlin-2.0
+ UCL-1.0
UPL-1.0
Unicode-DFS-2015
Unicode-DFS-2016
@@ -361,16 +446,22 @@ class Gem::Licenses
Zimbra-1.3
Zimbra-1.4
Zlib
+ blessing
bzip2-1.0.5
bzip2-1.0.6
+ copyleft-next-0.3.0
+ copyleft-next-0.3.1
curl
diffmark
dvipdfm
eCos-2.0
eGenix
+ etalab-2.0
gSOAP-1.3b
gnuplot
iMatix
+ libpng-2.0
+ libselinux-1.0
libtiff
mpich2
psfrag
@@ -379,10 +470,10 @@ class Gem::Licenses
xinetd
xpp
zlib-acknowledgement
- ).freeze
+ ].freeze
# exception identifiers
- EXCEPTION_IDENTIFIERS = %w(
+ EXCEPTION_IDENTIFIERS = %w[
389-exception
Autoconf-exception-2.0
Autoconf-exception-3.0
@@ -396,12 +487,26 @@ class Gem::Licenses
Font-exception-2.0
GCC-exception-2.0
GCC-exception-3.1
+ GPL-3.0-linking-exception
+ GPL-3.0-linking-source-exception
+ GPL-CC-1.0
+ LGPL-3.0-linking-exception
+ LLVM-exception
LZMA-exception
Libtool-exception
Linux-syscall-note
Nokia-Qt-exception-1.1
OCCT-exception-1.0
+ OCaml-LGPL-linking-exception
+ OpenJDK-assembly-exception-1.0
+ PS-or-PDF-font-exception-20170817
+ Qt-GPL-exception-1.0
+ Qt-LGPL-exception-1.1
Qwt-exception-1.0
+ SHL-2.0
+ SHL-2.1
+ Swift-exception
+ Universal-FOSS-exception-1.0
WxWindows-exception-3.1
eCos-exception-2.0
freertos-exception-2.0
@@ -410,15 +515,16 @@ class Gem::Licenses
mif-exception
openvpn-openssl-exception
u-boot-exception-2.0
- ).freeze
+ ].freeze
REGEXP = %r{
\A
- (
+ (?:
#{Regexp.union(LICENSE_IDENTIFIERS)}
\+?
- (\s WITH \s #{Regexp.union(EXCEPTION_IDENTIFIERS)})?
+ (?:\s WITH \s #{Regexp.union(EXCEPTION_IDENTIFIERS)})?
| #{NONSTANDARD}
+ | #{LICENSE_REF}
)
\Z
}ox.freeze
@@ -435,5 +541,4 @@ class Gem::Licenses
return unless lowest < license.size
by_distance[lowest]
end
-
end
diff --git a/lib/rubygems/util/list.rb b/lib/rubygems/util/list.rb
index 7e4d6b5de6..33c40af4bb 100644
--- a/lib/rubygems/util/list.rb
+++ b/lib/rubygems/util/list.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
module Gem
class List
-
include Enumerable
attr_accessor :value, :tail
@@ -34,6 +33,5 @@ module Gem
return List.new(value) unless list
List.new value, list
end
-
end
end
diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb
index 7ed0a1f80f..728595e778 100644
--- a/lib/rubygems/validator.rb
+++ b/lib/rubygems/validator.rb
@@ -5,14 +5,13 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems/package'
-require 'rubygems/installer'
+require_relative 'package'
+require_relative 'installer'
##
# Validator performs various gem file and gem database validation
class Gem::Validator
-
include Gem::UserInteraction
def initialize # :nodoc:
@@ -60,7 +59,7 @@ class Gem::Validator
# TODO needs further cleanup
def alien(gems=[])
- errors = Hash.new { |h,k| h[k] = {} }
+ errors = Hash.new {|h,k| h[k] = {} }
Gem::Specification.each do |spec|
next unless gems.include? spec.name unless gems.empty?
@@ -141,5 +140,4 @@ class Gem::Validator
errors
end
-
end
diff --git a/lib/rubygems/version.rb b/lib/rubygems/version.rb
index b1faedcda2..20bbff4fdd 100644
--- a/lib/rubygems/version.rb
+++ b/lib/rubygems/version.rb
@@ -150,7 +150,6 @@
# a zero to give a sensible result.
class Gem::Version
-
autoload :Requirement, File.expand_path('requirement', __dir__)
include Comparable
@@ -187,7 +186,7 @@ class Gem::Version
# ver3 = Version.create(nil) # -> nil
def self.create(input)
- if self === input # check yourself before you wreck yourself
+ if self === input # check yourself before you wreck yourself
input
elsif input.nil?
nil
@@ -231,7 +230,7 @@ class Gem::Version
def bump
@@bump[self] ||= begin
segments = self.segments
- segments.pop while segments.any? { |s| String === s }
+ segments.pop while segments.any? {|s| String === s }
segments.pop if segments.size > 1
segments[-1] = segments[-1].succ
@@ -310,7 +309,7 @@ class Gem::Version
def release
@@release[self] ||= if prerelease?
segments = self.segments
- segments.pop while segments.any? { |s| String === s }
+ segments.pop while segments.any? {|s| String === s }
self.class.new segments.join('.')
else
self
@@ -327,7 +326,7 @@ class Gem::Version
def approximate_recommendation
segments = self.segments
- segments.pop while segments.any? { |s| String === s }
+ segments.pop while segments.any? {|s| String === s }
segments.pop while segments.size > 2
segments.push 0 while segments.size < 2
@@ -404,5 +403,4 @@ class Gem::Version
numeric_segments = string_segments.slice!(0, string_start || string_segments.size)
return numeric_segments, string_segments
end
-
end
diff --git a/lib/rubygems/version_option.rb b/lib/rubygems/version_option.rb
index 458a7a6601..1db382fa7f 100644
--- a/lib/rubygems/version_option.rb
+++ b/lib/rubygems/version_option.rb
@@ -5,7 +5,7 @@
# See LICENSE.txt for permissions.
#++
-require 'rubygems'
+require_relative '../rubygems'
##
# Mixin methods for --version and --platform Gem::Command options.
@@ -16,7 +16,7 @@ module Gem::VersionOption
# Add the --platform option to the option parser.
def add_platform_option(task = command, *wrap)
- OptionParser.accept Gem::Platform do |value|
+ Gem::OptionParser.accept Gem::Platform do |value|
if value == Gem::Platform::RUBY
value
else
@@ -51,7 +51,7 @@ module Gem::VersionOption
# Add the --version option to the option parser.
def add_version_option(task = command, *wrap)
- OptionParser.accept Gem::Requirement do |value|
+ Gem::OptionParser.accept Gem::Requirement do |value|
Gem::Requirement.new(*value.split(/\s*,\s*/))
end
@@ -73,4 +73,10 @@ module Gem::VersionOption
end
end
+ ##
+ # Extract platform given on the command line
+
+ def get_platform_from_requirements(requirements)
+ Gem.platforms[1].to_s if requirements.key? :added_platform
+ end
end
diff --git a/lib/securerandom.gemspec b/lib/securerandom.gemspec
new file mode 100644
index 0000000000..358dc58056
--- /dev/null
+++ b/lib/securerandom.gemspec
@@ -0,0 +1,22 @@
+Gem::Specification.new do |spec|
+ spec.name = "securerandom"
+ spec.version = "0.1.0"
+ spec.authors = ["Tanaka Akira"]
+ spec.email = ["akr@fsij.org"]
+
+ spec.summary = %q{Interface for secure random number generator.}
+ spec.description = %q{Interface for secure random number generator.}
+ spec.homepage = "https://github.com/ruby/securerandom"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.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/securerandom.rb b/lib/securerandom.rb
index 205cb70be5..241fde98ce 100644
--- a/lib/securerandom.rb
+++ b/lib/securerandom.rb
@@ -66,42 +66,11 @@
#
module SecureRandom
- @rng_chooser = Mutex.new # :nodoc:
-
class << self
def bytes(n)
return gen_random(n)
end
- def gen_random(n)
- ret = Random.urandom(1)
- if ret.nil?
- begin
- require 'openssl'
- rescue NoMethodError
- raise NotImplementedError, "No random device"
- else
- @rng_chooser.synchronize do
- class << self
- remove_method :gen_random
- alias gen_random gen_random_openssl
- public :gen_random
- end
- end
- return gen_random(n)
- end
- else
- @rng_chooser.synchronize do
- class << self
- remove_method :gen_random
- alias gen_random gen_random_urandom
- public :gen_random
- end
- end
- return gen_random(n)
- end
- end
-
private
def gen_random_openssl(n)
@@ -129,6 +98,21 @@ module SecureRandom
end
ret
end
+
+ ret = Random.urandom(1)
+ if ret.nil?
+ begin
+ require 'openssl'
+ rescue NoMethodError
+ raise NotImplementedError, "No random device"
+ else
+ alias gen_random gen_random_openssl
+ end
+ else
+ alias gen_random gen_random_urandom
+ end
+
+ public :gen_random
end
end
diff --git a/lib/set.rb b/lib/set.rb
index 1b0e3ae6fc..09c5595727 100644
--- a/lib/set.rb
+++ b/lib/set.rb
@@ -1,38 +1,31 @@
-#--
# frozen_string_literal: true
+# :markup: markdown
#
# set.rb - defines the Set class
-#++
-# Copyright (c) 2002-2016 Akinori MUSHA <knu@iDaemons.org>
+#
+# Copyright (c) 2002-2020 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.
-#
-# $Id$
-#
-# == Overview
-#
+
+
+##
# This library provides the Set class, which deals with a collection
# of unordered values with no duplicates. It is a hybrid of Array's
-# intuitive inter-operation facilities and Hash's fast lookup. If you
-# need to keep values sorted in some order, use the SortedSet class.
+# intuitive inter-operation facilities and Hash's fast lookup.
#
-# The method +to_set+ is added to Enumerable for convenience.
-#
-# See the Set and SortedSet documentation for examples of usage.
-
-
+# The method `to_set` is added to Enumerable for convenience.
#
# Set implements a collection of unordered values with no duplicates.
# This is a hybrid of Array's intuitive inter-operation facilities and
# Hash's fast lookup.
#
-# Set is easy to use with Enumerable objects (implementing +each+).
+# Set is easy to use with Enumerable objects (implementing `each`).
# Most of the initializer methods and binary operators accept generic
# Enumerable objects besides sets and arrays. An Enumerable object
-# can be converted to Set using the +to_set+ method.
+# can be converted to Set using the `to_set` method.
#
# Set uses Hash as storage, so you must note the following points:
#
@@ -45,27 +38,29 @@
# * When a string is to be stored, a frozen copy of the string is
# stored instead unless the original string is already frozen.
#
-# == Comparison
+# ## Comparison
#
-# The comparison operators <, >, <=, and >= are implemented as
-# shorthand for the {proper_,}{subset?,superset?} methods. However,
-# the <=> operator is intentionally left out because not every pair of
-# sets is comparable ({x, y} vs. {x, z} for example).
+# 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
+# ## Example
#
-# 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
+# ```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
+# ## Contact
#
-# - Akinori MUSHA <knu@iDaemons.org> (current maintainer)
+# - Akinori MUSHA <<knu@iDaemons.org>> (current maintainer)
#
class Set
include Enumerable
@@ -136,10 +131,18 @@ class Set
@hash = orig.instance_variable_get(:@hash).dup
end
- # Clone internal hash.
- def initialize_clone(orig)
- super
- @hash = orig.instance_variable_get(:@hash).clone
+ if Kernel.instance_method(:initialize_clone).arity != 1
+ # Clone internal hash.
+ def initialize_clone(orig, **options)
+ super
+ @hash = orig.instance_variable_get(:@hash).clone(**options)
+ end
+ else
+ # Clone internal hash.
+ def initialize_clone(orig)
+ super
+ @hash = orig.instance_variable_get(:@hash).clone
+ end
end
def freeze # :nodoc:
@@ -194,9 +197,9 @@ class Set
end
# Returns self if no arguments are given. Otherwise, converts the
- # set to another with klass.new(self, *args, &block).
+ # set to another with `klass.new(self, *args, &block)`.
#
- # In subclasses, returns klass.new(self, *args, &block) unless
+ # In subclasses, returns `klass.new(self, *args, &block)` unless
# overridden.
def to_set(klass = Set, *args, &block)
return self if instance_of?(Set) && klass == Set && block.nil? && args.empty?
@@ -297,11 +300,24 @@ class Set
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 set have at least one
# element in common.
#
- # Set[1, 2, 3].intersect? Set[4, 5] #=> false
- # Set[1, 2, 3].intersect? Set[3, 4] #=> true
+ # Set[1, 2, 3].intersect? Set[4, 5] #=> false
+ # Set[1, 2, 3].intersect? Set[3, 4] #=> true
def intersect?(set)
set.is_a?(Set) or raise ArgumentError, "value must be a set"
if size < set.size
@@ -312,10 +328,10 @@ class Set
end
# Returns true if the set and the given set have no element in
- # common. This method is the opposite of +intersect?+.
+ # common. This method is the opposite of `intersect?`.
#
- # Set[1, 2, 3].disjoint? Set[3, 4] #=> false
- # Set[1, 2, 3].disjoint? Set[4, 5] #=> true
+ # Set[1, 2, 3].disjoint? Set[3, 4] #=> false
+ # Set[1, 2, 3].disjoint? Set[4, 5] #=> true
def disjoint?(set)
!intersect?(set)
end
@@ -329,7 +345,7 @@ class Set
self
end
- # Adds the given object to the set and returns self. Use +merge+ to
+ # Adds the given object to the set and returns self. Use `merge` to
# add many elements at once.
#
# Set[1, 2].add(3) #=> #<Set: {1, 2, 3}>
@@ -351,8 +367,8 @@ class Set
add(o) unless include?(o)
end
- # Deletes the given object from the set and returns self. Use +subtract+ to
- # delete many items at once.
+ # Deletes the given object from the set and returns self. Use
+ # `subtract` to delete many items at once.
def delete(o)
@hash.delete(o)
self
@@ -386,7 +402,7 @@ class Set
self
end
- # Replaces the elements with ones returned by collect().
+ # Replaces the elements with ones returned by `collect()`.
# Returns an enumerator if no block is given.
def collect!
block_given? or return enum_for(__method__) { size }
@@ -464,14 +480,22 @@ class Set
# Set['a', 'b', 'z'] & ['a', 'b', 'c'] #=> #<Set: {"a", "b"}>
def &(enum)
n = self.class.new
- do_with_enum(enum) { |o| n.add(o) if include?(o) }
+ if enum.is_a?(Set)
+ if enum.size > size
+ each { |o| n.add(o) if enum.include?(o) }
+ else
+ enum.each { |o| n.add(o) if include?(o) }
+ end
+ else
+ do_with_enum(enum) { |o| n.add(o) if include?(o) }
+ end
n
end
alias intersection &
# Returns a new set containing elements exclusive between the set
- # and the given enumerable object. (set ^ enum) is equivalent to
- # ((set | enum) - (set & enum)).
+ # and the given enumerable object. `(set ^ enum)` is equivalent to
+ # `((set | enum) - (set & enum))`.
#
# Set[1, 2] ^ Set[2, 3] #=> #<Set: {3, 1}>
# Set[1, 'b', 'c'] ^ ['b', 'd'] #=> #<Set: {"d", 1, "c"}>
@@ -527,20 +551,20 @@ class Set
#
# Used in case statements:
#
- # require 'set'
+ # require 'set'
#
- # case :apple
- # when Set[:potato, :carrot]
- # "vegetable"
- # when Set[:apple, :banana]
- # "fruit"
- # end
- # # => "fruit"
+ # case :apple
+ # when Set[:potato, :carrot]
+ # "vegetable"
+ # when Set[:apple, :banana]
+ # "fruit"
+ # end
+ # # => "fruit"
#
# Or by itself:
#
- # Set[1, 2, 3] === 2 #=> true
- # Set[1, 2, 3] === 4 #=> false
+ # Set[1, 2, 3] === 2 #=> true
+ # Set[1, 2, 3] === 4 #=> false
#
alias === include?
@@ -549,12 +573,12 @@ class Set
# 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"}>}
+ # 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
@@ -576,13 +600,13 @@ class Set
# 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}>}>
+ # 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)
@@ -615,6 +639,12 @@ class Set
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
@@ -651,259 +681,12 @@ class Set
end
end
-#
-# SortedSet implements a Set that guarantees that its elements are
-# yielded in sorted order (according to the return values of their
-# #<=> methods) when iterating over them.
-#
-# All elements that are added to a SortedSet must respond to the <=>
-# method for comparison.
-#
-# Also, all elements must be <em>mutually comparable</em>: <tt>el1 <=>
-# el2</tt> must not return <tt>nil</tt> for any elements <tt>el1</tt>
-# and <tt>el2</tt>, else an ArgumentError will be raised when
-# iterating over the SortedSet.
-#
-# == Example
-#
-# require "set"
-#
-# set = SortedSet.new([2, 1, 5, 6, 4, 5, 3, 3, 3])
-# ary = []
-#
-# set.each do |obj|
-# ary << obj
-# end
-#
-# p ary # => [1, 2, 3, 4, 5, 6]
-#
-# set2 = SortedSet.new([1, 2, "3"])
-# set2.each { |obj| } # => raises ArgumentError: comparison of Fixnum with String failed
-#
-class SortedSet < Set
- @@setup = false
- @@mutex = Mutex.new
-
- class << self
- def [](*ary) # :nodoc:
- new(ary)
- end
-
- def setup # :nodoc:
- @@setup and return
- ret = nil
-
- @@mutex.synchronize do
- # a hack to shut up warning
- alias_method :old_init, :initialize
-
- begin
- require 'rbtree'
- ret = :rbtree
-
- module_eval <<-END, __FILE__, __LINE__+1
- def initialize(*args)
- @hash = RBTree.new
- super
- end
-
- def add(o)
- o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>"
- super
- end
- alias << add
- END
- rescue LoadError
- ret = true
- module_eval <<-END, __FILE__, __LINE__+1
- def initialize(*args)
- @keys = nil
- super
- end
-
- def clear
- @keys = nil
- super
- end
-
- def replace(enum)
- @keys = nil
- super
- end
-
- def add(o)
- o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>"
- @keys = nil
- super
- end
- alias << add
-
- def delete(o)
- @keys = nil
- @hash.delete(o)
- self
- end
-
- def delete_if
- block_given? or return enum_for(__method__) { size }
- n = @hash.size
- super
- @keys = nil if @hash.size != n
- self
- end
-
- def keep_if
- block_given? or return enum_for(__method__) { size }
- n = @hash.size
- super
- @keys = nil if @hash.size != n
- self
- end
-
- def merge(enum)
- @keys = nil
- super
- end
-
- def each(&block)
- block or return enum_for(__method__) { size }
- to_a.each(&block)
- self
- end
-
- def to_a
- (@keys = @hash.keys).sort! unless @keys
- @keys
- end
-
- def freeze
- to_a
- super
- end
-
- def rehash
- @keys = nil
- super
- end
- END
- end
- # a hack to shut up warning
- remove_method :old_init
-
- @@setup = true
- ret
- end
- end
- end
-
- def initialize(*args, &block) # :nodoc:
- if SortedSet.setup == :rbtree
- @hash = RBTree.new
- else
- @keys = nil
- end
- super
- end
-end
-
module Enumerable
# Makes a set from the enumerable object with given arguments.
- # Needs to +require "set"+ to use this method.
+ # Needs to `require "set"` to use this method.
def to_set(klass = Set, *args, &block)
klass.new(self, *args, &block)
end
end
-# =begin
-# == RestricedSet class
-# RestricedSet implements a set with restrictions defined by a given
-# block.
-#
-# === Super class
-# Set
-#
-# === Class Methods
-# --- RestricedSet::new(enum = nil) { |o| ... }
-# --- RestricedSet::new(enum = nil) { |rset, o| ... }
-# Creates a new restricted set containing the elements of the given
-# enumerable object. Restrictions are defined by the given block.
-#
-# If the block's arity is 2, it is called with the RestrictedSet
-# itself and an object to see if the object is allowed to be put in
-# the set.
-#
-# Otherwise, the block is called with an object to see if the object
-# is allowed to be put in the set.
-#
-# === Instance Methods
-# --- restriction_proc
-# Returns the restriction procedure of the set.
-#
-# =end
-#
-# class RestricedSet < Set
-# def initialize(*args, &block)
-# @proc = block or raise ArgumentError, "missing a block"
-#
-# if @proc.arity == 2
-# instance_eval %{
-# def add(o)
-# @hash[o] = true if @proc.call(self, o)
-# self
-# end
-# alias << add
-#
-# def add?(o)
-# if include?(o) || !@proc.call(self, o)
-# nil
-# else
-# @hash[o] = true
-# self
-# end
-# end
-#
-# def replace(enum)
-# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
-# clear
-# enum.each_entry { |o| add(o) }
-#
-# self
-# end
-#
-# def merge(enum)
-# enum.respond_to?(:each) or raise ArgumentError, "value must be enumerable"
-# enum.each_entry { |o| add(o) }
-#
-# self
-# end
-# }
-# else
-# instance_eval %{
-# def add(o)
-# if @proc.call(o)
-# @hash[o] = true
-# end
-# self
-# end
-# alias << add
-#
-# def add?(o)
-# if include?(o) || !@proc.call(o)
-# nil
-# else
-# @hash[o] = true
-# self
-# end
-# end
-# }
-# end
-#
-# super(*args)
-# end
-#
-# def restriction_proc
-# @proc
-# end
-# end
-
-# Tests have been moved to test/test_set.rb.
+autoload :SortedSet, "#{__dir__}/set/sorted_set"
diff --git a/lib/set/set.gemspec b/lib/set/set.gemspec
new file mode 100644
index 0000000000..53b614ba22
--- /dev/null
+++ b/lib/set/set.gemspec
@@ -0,0 +1,25 @@
+Gem::Specification.new do |spec|
+ spec.name = "set"
+ spec.version = "1.0.1"
+ 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.license = "BSD-2-Clause"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+ spec.metadata["changelog_uri"] = "https://github.com/ruby/set/blob/v#{spec.version}/CHANGELOG.md"
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/set/sorted_set.rb b/lib/set/sorted_set.rb
new file mode 100644
index 0000000000..e4e01ba4a8
--- /dev/null
+++ b/lib/set/sorted_set.rb
@@ -0,0 +1,6 @@
+begin
+ require 'sorted_set'
+rescue ::LoadError
+ raise "The `SortedSet` class has been extracted from the `set` library." \
+ "You must use the `sorted_set` gem or other alternatives."
+end
diff --git a/lib/shellwords.gemspec b/lib/shellwords.gemspec
new file mode 100644
index 0000000000..8ae87b230e
--- /dev/null
+++ b/lib/shellwords.gemspec
@@ -0,0 +1,22 @@
+Gem::Specification.new do |spec|
+ spec.name = "shellwords"
+ spec.version = "0.1.0"
+ spec.authors = ["Akinori MUSHA"]
+ spec.email = ["knu@idaemons.org"]
+
+ spec.summary = %q{Manipulates strings with word parsing rules of UNIX Bourne shell.}
+ spec.description = %q{Manipulates strings with word parsing rules of UNIX Bourne shell.}
+ spec.homepage = "https://github.com/ruby/shellwords"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/shellwords.rb b/lib/shellwords.rb
index 1eaddce7ba..4368a53ea8 100644
--- a/lib/shellwords.rb
+++ b/lib/shellwords.rb
@@ -24,28 +24,37 @@
# argv = "see how they run".shellsplit
# argv #=> ["see", "how", "they", "run"]
#
-# Be careful you don't leave a quote unmatched.
+# They treat quotes as special characters, so an unmatched quote will
+# cause an ArgumentError.
#
# argv = "they all ran after the farmer's wife".shellsplit
-# #=> ArgumentError: Unmatched double quote: ...
+# #=> ArgumentError: Unmatched quote: ...
#
-# In this case, you might want to use Shellwords.escape, or its alias
-# String#shellescape.
+# Shellwords also provides methods that do the opposite.
+# Shellwords.escape, or its alias, String#shellescape, escapes
+# shell metacharacters in a string for use in a command line.
#
-# This method will escape the String for you to safely use with a Bourne shell.
+# filename = "special's.txt"
#
-# argv = Shellwords.escape("special's.txt")
-# argv #=> "special\\'s.txt"
-# system("cat " + argv)
+# system("cat -- #{filename.shellescape}")
+# # runs "cat -- special\\'s.txt"
+#
+# Note the '--'. Without it, cat(1) will treat the following argument
+# as a command line option if it starts with '-'. It is guaranteed
+# that Shellwords.escape converts a string to a form that a Bourne
+# shell will parse back to the original string, but it is the
+# programmer's responsibility to make sure that passing an arbitrary
+# argument to a command does no harm.
#
# Shellwords also comes with a core extension for Array, Array#shelljoin.
#
-# argv = %w{ls -lta lib}
-# system(argv.shelljoin)
+# dir = "Funny GIFs"
+# argv = %W[ls -lta -- #{dir}]
+# system(argv.shelljoin + " | less")
+# # runs "ls -lta -- Funny\\ GIFs | less"
#
-# You can use this method to create an escaped string out of an array of tokens
-# separated by a space. In this example we used the literal shortcut for
-# Array.new.
+# You can use this method to build a complete command line out of an
+# array of arguments.
#
# === Authors
# * Wakou Aoyama
@@ -81,7 +90,7 @@ module Shellwords
field = String.new
line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do
|word, sq, dq, esc, garbage, sep|
- raise ArgumentError, "Unmatched double quote: #{line.inspect}" if garbage
+ raise ArgumentError, "Unmatched quote: #{line.inspect}" if garbage
# 2.2.3 Double-Quotes:
#
# The <backslash> shall retain its special meaning as an
@@ -123,7 +132,7 @@ module Shellwords
#
# # Search files in lib for method definitions
# pattern = "^[ \t]*def "
- # open("| grep -Ern #{pattern.shellescape} lib") { |grep|
+ # open("| grep -Ern -e #{pattern.shellescape} lib") { |grep|
# grep.each_line { |line|
# file, lineno, matched_line = line.split(':', 3)
# # ...
diff --git a/lib/singleton.rb b/lib/singleton.rb
index 8e8a779a2e..07420d2ea2 100644
--- a/lib/singleton.rb
+++ b/lib/singleton.rb
@@ -13,7 +13,7 @@
#
# This ensures that only one instance of Klass can be created.
#
-# a,b = Klass.instance, Klass.instance
+# a,b = Klass.instance, Klass.instance
#
# a == b
# # => true
@@ -92,6 +92,8 @@
# p a.strip # => nil
#
module Singleton
+ VERSION = "0.1.1"
+
# Raises a TypeError to prevent cloning.
def clone
raise TypeError, "can't clone instance of singleton #{self.class}"
diff --git a/lib/singleton/singleton.gemspec b/lib/singleton/singleton.gemspec
index c6a273a839..88d3111b65 100644
--- a/lib/singleton/singleton.gemspec
+++ b/lib/singleton/singleton.gemspec
@@ -1,19 +1,22 @@
-begin
- require_relative "lib/singleton/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "singleton"
- spec.version = Singleton::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
spec.summary = %q{The Singleton module implements the Singleton pattern.}
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/singleton"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/lib/singleton/version.rb b/lib/singleton/version.rb
deleted file mode 100644
index 01ab1eb5fa..0000000000
--- a/lib/singleton/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module Singleton
- VERSION = "0.1.0"
-end
diff --git a/lib/tempfile.gemspec b/lib/tempfile.gemspec
new file mode 100644
index 0000000000..4917b997e7
--- /dev/null
+++ b/lib/tempfile.gemspec
@@ -0,0 +1,24 @@
+Gem::Specification.new do |spec|
+ spec.name = "tempfile"
+ spec.version = "0.1.1"
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{A utility class for managing temporary files.}
+ spec.description = %q{A utility class for managing temporary files.}
+ spec.homepage = "https://github.com/ruby/tempfile"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/tempfile.rb b/lib/tempfile.rb
index efb0b1bcd6..1577e45bec 100644
--- a/lib/tempfile.rb
+++ b/lib/tempfile.rb
@@ -53,6 +53,14 @@ require 'tmpdir'
# file.unlink # deletes the temp file
# end
#
+# Tempfile.create { ... } exists for this purpose and is more convenient to use.
+# Note that Tempfile.create returns a File instance instead of a Tempfile, which
+# also avoids the overhead and complications of delegation.
+#
+# Tempfile.open('foo') do |file|
+# # ...do something with file...
+# end
+#
# === Unlink after creation
#
# On POSIX systems, it's possible to unlink a file right after creating it,
@@ -82,6 +90,10 @@ class Tempfile < DelegateClass(File)
# Creates a temporary file with permissions 0600 (= only readable and
# writable by the owner) and opens it with mode "w+".
#
+ # It is recommended to use Tempfile.create { ... } instead when possible,
+ # because that method avoids the cost of delegation and does not rely on a
+ # finalizer to close and unlink the file, which is unreliable.
+ #
# The +basename+ parameter is used to determine the name of the
# temporary file. You can either pass a String or an Array with
# 2 String elements. In the former form, the temporary file's base
@@ -263,11 +275,25 @@ class Tempfile < DelegateClass(File)
# Creates a new Tempfile.
#
+ # This method is not recommended and exists mostly for backward compatibility.
+ # Please use Tempfile.create instead, which avoids the cost of delegation,
+ # does not rely on a finalizer, and also unlinks the file when given a block.
+ #
+ # Tempfile.open is still appropriate if you need the Tempfile to be unlinked
+ # by a finalizer and you cannot explicitly know where in the program the
+ # Tempfile can be unlinked safely.
+ #
# If no block is given, this is a synonym for Tempfile.new.
#
# If a block is given, then a Tempfile object will be constructed,
- # and the block is run with said object as argument. The Tempfile
+ # and the block is run with the Tempfile object as argument. The Tempfile
# object will be automatically closed after the block terminates.
+ # However, the file will *not* be unlinked and needs to be manually unlinked
+ # with Tempfile#close! or Tempfile#unlink. The finalizer will try to unlink
+ # but should not be relied upon as it can keep the file on the disk much
+ # longer than intended. For instance, on CRuby, finalizers can be delayed
+ # due to conservative stack scanning and references left in unused memory.
+ #
# The call returns the value of the block.
#
# In any case, all arguments (<code>*args</code>) will be passed to Tempfile.new.
@@ -299,22 +325,22 @@ class Tempfile < DelegateClass(File)
end
end
-# Creates a temporary file as usual File object (not Tempfile).
-# It doesn't use finalizer and delegation.
+# Creates a temporary file as a usual File object (not a Tempfile).
+# It does not use finalizer and delegation, which makes it more efficient and reliable.
#
# If no block is given, this is similar to Tempfile.new except
-# creating File instead of Tempfile.
-# The created file is not removed automatically.
-# You should use File.unlink to remove it.
+# creating File instead of Tempfile. In that case, the created file is
+# not removed automatically. You should use File.unlink to remove it.
#
# If a block is given, then a File object will be constructed,
# and the block is invoked with the object as the argument.
# The File object will be automatically closed and
-# the temporary file is removed after the block terminates.
+# the temporary file is removed after the block terminates,
+# releasing all resources that the block created.
# The call returns the value of the block.
#
# In any case, all arguments (+basename+, +tmpdir+, +mode+, and
-# <code>**options</code>) will be treated as Tempfile.new.
+# <code>**options</code>) will be treated the same as for Tempfile.new.
#
# Tempfile.create('foo', '/home/temp') do |f|
# # ... do something with f ...
diff --git a/lib/time.gemspec b/lib/time.gemspec
new file mode 100644
index 0000000000..040b9f34cf
--- /dev/null
+++ b/lib/time.gemspec
@@ -0,0 +1,24 @@
+Gem::Specification.new do |spec|
+ spec.name = "time"
+ spec.version = "0.1.0"
+ spec.authors = ["Tanaka Akira"]
+ spec.email = ["akr@fsij.org"]
+
+ spec.summary = %q{Extends the Time class with methods for parsing and conversion.}
+ spec.description = %q{Extends the Time class with methods for parsing and conversion.}
+ spec.homepage = "https://github.com/ruby/time"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "date"
+end
diff --git a/lib/time.rb b/lib/time.rb
index f27bacde65..625c2c87bb 100644
--- a/lib/time.rb
+++ b/lib/time.rb
@@ -272,6 +272,11 @@ class Time
# Takes a string representation of a Time and attempts to parse it
# using a heuristic.
#
+ # This method **does not** function as a validator. If the input
+ # string does not match valid formats strictly, you may get a
+ # cryptic result. Should consider to use `Time.strptime` instead
+ # of this method as possible.
+ #
# require 'time'
#
# Time.parse("2010-10-31") #=> 2010-10-31 00:00:00 -0500
@@ -590,12 +595,12 @@ class Time
end
#
- # Parses +date+ as a dateTime defined by the XML Schema and converts it to
+ # Parses +time+ as a dateTime defined by the XML Schema and converts it to
# a Time object. The format is a restricted version of the format defined
# by ISO 8601.
#
- # ArgumentError is raised if +date+ is not compliant with the format or if
- # the Time class cannot represent specified date.
+ # ArgumentError is raised if +time+ is not compliant with the format or if
+ # the Time class cannot represent the specified time.
#
# See #xmlschema for more information on this format.
#
@@ -606,14 +611,14 @@ class Time
#
# You must require 'time' to use this method.
#
- def xmlschema(date)
+ def xmlschema(time)
if /\A\s*
(-?\d+)-(\d\d)-(\d\d)
T
(\d\d):(\d\d):(\d\d)
(\.\d+)?
(Z|[+-]\d\d(?::?\d\d)?)?
- \s*\z/ix =~ date
+ \s*\z/ix =~ time
year = $1.to_i
mon = $2.to_i
day = $3.to_i
@@ -636,7 +641,7 @@ class Time
self.local(year, mon, day, hour, min, sec, usec)
end
else
- raise ArgumentError.new("invalid date: #{date.inspect}")
+ raise ArgumentError.new("invalid xmlschema format: #{time.inspect}")
end
end
alias iso8601 xmlschema
diff --git a/lib/timeout.rb b/lib/timeout.rb
index 62a35169a4..0dc84b08b1 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -23,6 +23,8 @@
# Copyright:: (C) 2000 Information-technology Promotion Agency, Japan
module Timeout
+ VERSION = "0.1.1"
+
# Raised by Timeout.timeout when the block times out.
class Error < RuntimeError
attr_reader :thread
diff --git a/lib/timeout/timeout.gemspec b/lib/timeout/timeout.gemspec
index 7b650bdc31..3dc37f8768 100644
--- a/lib/timeout/timeout.gemspec
+++ b/lib/timeout/timeout.gemspec
@@ -1,19 +1,22 @@
-begin
- require_relative "lib/timeout/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "timeout"
- spec.version = Timeout::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
spec.summary = %q{Auto-terminate potentially long-running operations in Ruby.}
spec.description = %q{Auto-terminate potentially long-running operations in Ruby.}
spec.homepage = "https://github.com/ruby/timeout"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/lib/timeout/version.rb b/lib/timeout/version.rb
deleted file mode 100644
index 39fc6eec5f..0000000000
--- a/lib/timeout/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module Timeout
- VERSION = "0.1.0"
-end
diff --git a/lib/tmpdir.gemspec b/lib/tmpdir.gemspec
new file mode 100644
index 0000000000..7b76403002
--- /dev/null
+++ b/lib/tmpdir.gemspec
@@ -0,0 +1,26 @@
+Gem::Specification.new do |spec|
+ spec.name = "tmpdir"
+ spec.version = "0.1.2"
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{Extends the Dir class to manage the OS temporary file path.}
+ spec.description = %q{Extends the Dir class to manage the OS temporary file path.}
+ spec.homepage = "https://github.com/ruby/tmpdir"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "fileutils"
+end
diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb
index 5e42e8e302..bf7db5282a 100644
--- a/lib/tmpdir.rb
+++ b/lib/tmpdir.rb
@@ -20,14 +20,21 @@ class Dir
def self.tmpdir
tmp = nil
- [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp', '.'].each do |dir|
+ ['TMPDIR', 'TMP', 'TEMP', ['system temporary path', @@systmpdir], ['/tmp']*2, ['.']*2].each do |name, dir = ENV[name]|
next if !dir
dir = File.expand_path(dir)
- if stat = File.stat(dir) and stat.directory? and stat.writable? and
- (!stat.world_writable? or stat.sticky?)
+ stat = File.stat(dir) rescue next
+ case
+ when !stat.directory?
+ warn "#{name} is not a directory: #{dir}"
+ when !stat.writable?
+ warn "#{name} is not writable: #{dir}"
+ when stat.world_writable? && !stat.sticky?
+ warn "#{name} is world-writable: #{dir}"
+ else
tmp = dir
break
- end rescue nil
+ end
end
raise ArgumentError, "could not find a temporary directory" unless tmp
tmp
@@ -110,6 +117,14 @@ class Dir
UNUSABLE_CHARS = "^,-.0-9A-Z_a-z~"
+ class << (RANDOM = Random.new)
+ MAX = 36**6 # < 0x100000000
+ def next
+ rand(MAX).to_s(36)
+ end
+ end
+ private_constant :RANDOM
+
def create(basename, tmpdir=nil, max_try: nil, **opts)
origdir = tmpdir
tmpdir ||= tmpdir()
@@ -123,7 +138,7 @@ class Dir
suffix &&= suffix.delete(UNUSABLE_CHARS)
begin
t = Time.now.strftime("%Y%m%d")
- path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"\
+ path = "#{prefix}#{t}-#{$$}-#{RANDOM.next}"\
"#{n ? %[-#{n}] : ''}#{suffix||''}"
path = File.join(tmpdir, path)
yield(path, n, opts, origdir)
diff --git a/lib/tracer.rb b/lib/tracer.rb
index c1540b8d23..9014d80da5 100644
--- a/lib/tracer.rb
+++ b/lib/tracer.rb
@@ -60,6 +60,7 @@
# by Keiju ISHITSUKA(keiju@ishitsuka.com)
#
class Tracer
+ VERSION = "0.1.1"
class << self
# display additional debug information (defaults to false)
diff --git a/lib/tracer/tracer.gemspec b/lib/tracer/tracer.gemspec
index 9eab333f79..de9401da2c 100644
--- a/lib/tracer/tracer.gemspec
+++ b/lib/tracer/tracer.gemspec
@@ -1,22 +1,24 @@
-begin
- require_relative "lib/tracer/version"
-rescue LoadError
- # for Ruby core repository
- require_relative "version"
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
end
Gem::Specification.new do |spec|
- spec.name = "tracer"
- spec.version = Tracer::VERSION
+ spec.name = name
+ spec.version = version
spec.authors = ["Keiju ISHITSUKA"]
spec.email = ["keiju@ruby-lang.org"]
spec.summary = %q{Outputs a source level execution trace of a Ruby program.}
spec.description = %q{Outputs a source level execution trace of a Ruby program.}
spec.homepage = "https://github.com/ruby/tracer"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/tracer.rb", "lib/tracer/version.rb", "tracer.gemspec"]
+ spec.files = ["Gemfile", "LICENSE.txt", "README.md", "Rakefile", "lib/tracer.rb", "tracer.gemspec"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
diff --git a/lib/tracer/version.rb b/lib/tracer/version.rb
deleted file mode 100644
index f1b6dcd094..0000000000
--- a/lib/tracer/version.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class Tracer
- VERSION = "0.1.0"
-end
diff --git a/lib/tsort.gemspec b/lib/tsort.gemspec
new file mode 100644
index 0000000000..4656d0b845
--- /dev/null
+++ b/lib/tsort.gemspec
@@ -0,0 +1,22 @@
+Gem::Specification.new do |spec|
+ spec.name = "tsort"
+ spec.version = "0.1.0"
+ spec.authors = ["Tanaka Akira"]
+ spec.email = ["akr@fsij.org"]
+
+ spec.summary = %q{Topological sorting using Tarjan's algorithm}
+ spec.description = %q{Topological sorting using Tarjan's algorithm}
+ spec.homepage = "https://github.com/ruby/tsort"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/un.gemspec b/lib/un.gemspec
new file mode 100644
index 0000000000..1b89ffa2fb
--- /dev/null
+++ b/lib/un.gemspec
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+Gem::Specification.new do |spec|
+ spec.name = "un"
+ spec.version = "0.1.0"
+ spec.authors = ["WATANABE Hirofumi"]
+ spec.email = ["eban@ruby-lang.org"]
+
+ spec.summary = "Utilities to replace common UNIX commands"
+ spec.description = spec.summary
+ spec.homepage = "https://github.com/ruby/un"
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = spec.homepage
+
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+end
diff --git a/lib/un.rb b/lib/un.rb
index 4a15a37394..3f59e3ff8b 100644
--- a/lib/un.rb
+++ b/lib/un.rb
@@ -22,7 +22,7 @@
# ruby -run -e touch -- [OPTION] FILE
# ruby -run -e wait_writable -- [OPTION] FILE
# ruby -run -e mkmf -- [OPTION] EXTNAME [OPTION]
-# ruby -run -e httpd -- [OPTION] DocumentRoot
+# ruby -run -e httpd -- [OPTION] [DocumentRoot]
# ruby -run -e help [COMMAND]
require "fileutils"
@@ -88,7 +88,7 @@ def cp
options[:preserve] = true if options.delete :p
dest = argv.pop
argv = argv[0] if argv.size == 1
- FileUtils.send cmd, argv, dest, **options
+ FileUtils.__send__ cmd, argv, dest, **options
end
end
@@ -109,7 +109,7 @@ def ln
options[:force] = true if options.delete :f
dest = argv.pop
argv = argv[0] if argv.size == 1
- FileUtils.send cmd, argv, dest, **options
+ FileUtils.__send__ cmd, argv, dest, **options
end
end
@@ -144,7 +144,7 @@ def rm
cmd = "rm"
cmd += "_r" if options.delete :r
options[:force] = true if options.delete :f
- FileUtils.send cmd, argv, **options
+ FileUtils.__send__ cmd, argv, **options
end
end
@@ -161,7 +161,7 @@ def mkdir
setup("p") do |argv, options|
cmd = "mkdir"
cmd += "_p" if options.delete :p
- FileUtils.send cmd, argv, **options
+ FileUtils.__send__ cmd, argv, **options
end
end
@@ -304,7 +304,7 @@ end
##
# Run WEBrick HTTP server.
#
-# ruby -run -e httpd -- [OPTION] DocumentRoot
+# ruby -run -e httpd -- [OPTION] [DocumentRoot]
#
# --bind-address=ADDR address to bind
# --port=NUM listening port number
@@ -326,7 +326,11 @@ def httpd
"ServerName=NAME", "ServerSoftware=NAME",
"SSLCertificate=CERT", "SSLPrivateKey=KEY") do
|argv, options|
- require 'webrick'
+ begin
+ require 'webrick'
+ rescue LoadError
+ abort "webrick is not found. You may need to `gem install webrick` to install webrick."
+ end
opt = options[:RequestTimeout] and options[:RequestTimeout] = opt.to_i
[:Port, :MaxClients].each do |name|
opt = options[name] and (options[name] = Integer(opt)) rescue nil
diff --git a/lib/uri.rb b/lib/uri.rb
index ea8ea3e18c..b544a5ee65 100644
--- a/lib/uri.rb
+++ b/lib/uri.rb
@@ -86,19 +86,18 @@
# License::
# Copyright (c) 2001 akira yamada <akira@ruby-lang.org>
# You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
module URI
end
-require 'uri/version'
-require 'uri/common'
-require 'uri/generic'
-require 'uri/file'
-require 'uri/ftp'
-require 'uri/http'
-require 'uri/https'
-require 'uri/ldap'
-require 'uri/ldaps'
-require 'uri/mailto'
+require_relative 'uri/version'
+require_relative 'uri/common'
+require_relative 'uri/generic'
+require_relative 'uri/file'
+require_relative 'uri/ftp'
+require_relative 'uri/http'
+require_relative 'uri/https'
+require_relative 'uri/ldap'
+require_relative 'uri/ldaps'
+require_relative 'uri/mailto'
diff --git a/lib/uri/common.rb b/lib/uri/common.rb
index b886923c9e..d818592b74 100644
--- a/lib/uri/common.rb
+++ b/lib/uri/common.rb
@@ -3,7 +3,6 @@
# = uri/common.rb
#
# Author:: Akira Yamada <akira@ruby-lang.org>
-# Revision:: $Id$
# License::
# You can redistribute it and/or modify it under the same term as Ruby.
#
@@ -61,82 +60,6 @@ module URI
module_function :make_components_hash
end
- # Module for escaping unsafe characters with codes.
- module Escape
- #
- # == Synopsis
- #
- # URI.escape(str [, unsafe])
- #
- # == Args
- #
- # +str+::
- # String to replaces in.
- # +unsafe+::
- # Regexp that matches all symbols that must be replaced with codes.
- # By default uses <tt>UNSAFE</tt>.
- # When this argument is a String, it represents a character set.
- #
- # == Description
- #
- # Escapes the string, replacing all unsafe characters with codes.
- #
- # This method is obsolete and should not be used. Instead, use
- # CGI.escape, URI.encode_www_form or URI.encode_www_form_component
- # depending on your specific use case.
- #
- # == Usage
- #
- # require 'uri'
- #
- # enc_uri = URI.escape("http://example.com/?a=\11\15")
- # # => "http://example.com/?a=%09%0D"
- #
- # URI.unescape(enc_uri)
- # # => "http://example.com/?a=\t\r"
- #
- # URI.escape("@?@!", "!?")
- # # => "@%3F@%21"
- #
- def escape(*arg)
- warn "URI.escape is obsolete", uplevel: 1
- DEFAULT_PARSER.escape(*arg)
- end
- alias encode escape
- #
- # == Synopsis
- #
- # URI.unescape(str)
- #
- # == Args
- #
- # +str+::
- # String to unescape.
- #
- # == Description
- #
- # This method is obsolete and should not be used. Instead, use
- # CGI.unescape, URI.decode_www_form or URI.decode_www_form_component
- # depending on your specific use case.
- #
- # == Usage
- #
- # require 'uri'
- #
- # enc_uri = URI.escape("http://example.com/?a=\11\15")
- # # => "http://example.com/?a=%09%0D"
- #
- # URI.unescape(enc_uri)
- # # => "http://example.com/?a=\t\r"
- #
- def unescape(*arg)
- warn "URI.unescape is obsolete", uplevel: 1
- DEFAULT_PARSER.unescape(*arg)
- end
- alias decode unescape
- end # module Escape
-
- extend Escape
include REGEXP
@@schemes = {}
@@ -146,6 +69,20 @@ module URI
end
#
+ # Construct a URI instance, using the scheme to detect the appropriate class
+ # from +URI.scheme_list+.
+ #
+ def self.for(scheme, *arguments, default: Generic)
+ if scheme
+ uri_class = @@schemes[scheme.upcase] || default
+ else
+ uri_class = default
+ end
+
+ return uri_class.new(scheme, *arguments)
+ end
+
+ #
# Base class for all URI exceptions.
#
class Error < StandardError; end
@@ -315,7 +252,7 @@ module URI
#
# Returns a Regexp object which matches to URI-like strings.
# The Regexp object returned by this method includes arbitrary
- # number of capture group (parentheses). Never rely on it's number.
+ # number of capture group (parentheses). Never rely on its number.
#
# == Usage
#
@@ -362,7 +299,7 @@ module URI
# If +enc+ is given, convert +str+ to the encoding before percent encoding.
#
# This is an implementation of
- # http://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
+ # https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
#
# See URI.decode_www_form_component, URI.encode_www_form.
def self.encode_www_form_component(str, enc=nil)
@@ -403,7 +340,7 @@ module URI
# This method doesn't handle files. When you send a file, use
# multipart/form-data.
#
- # This refers http://url.spec.whatwg.org/#concept-urlencoded-serializer
+ # This refers https://url.spec.whatwg.org/#concept-urlencoded-serializer
#
# URI.encode_www_form([["q", "ruby"], ["lang", "en"]])
# #=> "q=ruby&lang=en"
diff --git a/lib/uri/ftp.rb b/lib/uri/ftp.rb
index f57b4b7df9..fb38481193 100644
--- a/lib/uri/ftp.rb
+++ b/lib/uri/ftp.rb
@@ -3,7 +3,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See URI for general documentation
#
diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb
index c672d15eb2..a4192c6557 100644
--- a/lib/uri/generic.rb
+++ b/lib/uri/generic.rb
@@ -4,7 +4,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See URI for general documentation
#
@@ -1098,7 +1097,7 @@ module URI
# # => "http://my.example.com/main.rbx?page=1"
#
def merge(oth)
- rel = parser.send(:convert_to_uri, oth)
+ rel = parser.__send__(:convert_to_uri, oth)
if rel.absolute?
#raise BadURIError, "both URI are absolute" if absolute?
@@ -1183,7 +1182,7 @@ module URI
# :stopdoc:
def route_from0(oth)
- oth = parser.send(:convert_to_uri, oth)
+ oth = parser.__send__(:convert_to_uri, oth)
if self.relative?
raise BadURIError,
"relative URI: #{self}"
@@ -1291,7 +1290,7 @@ module URI
# #=> #<URI::Generic /main.rbx?page=1>
#
def route_to(oth)
- parser.send(:convert_to_uri, oth).route_from(self)
+ parser.__send__(:convert_to_uri, oth).route_from(self)
end
#
@@ -1405,7 +1404,7 @@ module URI
# Returns an Array of the components defined from the COMPONENT Array.
def component_ary
component.collect do |x|
- self.send(x)
+ self.__send__(x)
end
end
protected :component_ary
@@ -1430,7 +1429,7 @@ module URI
def select(*components)
components.collect do |c|
if component.include?(c)
- self.send(c)
+ self.__send__(c)
else
raise ArgumentError,
"expected of components of #{self.class} (#{self.class.component.join(', ')})"
diff --git a/lib/uri/http.rb b/lib/uri/http.rb
index 2e2ebcc1d3..70cfb2a1bf 100644
--- a/lib/uri/http.rb
+++ b/lib/uri/http.rb
@@ -3,7 +3,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See URI for general documentation
#
diff --git a/lib/uri/https.rb b/lib/uri/https.rb
index 4780ee0a44..c481b1fe6d 100644
--- a/lib/uri/https.rb
+++ b/lib/uri/https.rb
@@ -3,7 +3,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See URI for general documentation
#
diff --git a/lib/uri/ldap.rb b/lib/uri/ldap.rb
index 61ec3d3f12..14e6163292 100644
--- a/lib/uri/ldap.rb
+++ b/lib/uri/ldap.rb
@@ -7,7 +7,6 @@
# License::
# URI::LDAP is copyrighted free software by Takaaki Tateishi and Akira Yamada.
# You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See URI for general documentation
#
diff --git a/lib/uri/mailto.rb b/lib/uri/mailto.rb
index 9c06871c7a..d08c2ae9da 100644
--- a/lib/uri/mailto.rb
+++ b/lib/uri/mailto.rb
@@ -3,7 +3,6 @@
#
# Author:: Akira Yamada <akira@ruby-lang.org>
# License:: You can redistribute it and/or modify it under the same term as Ruby.
-# Revision:: $Id$
#
# See URI for general documentation
#
diff --git a/lib/uri/rfc2396_parser.rb b/lib/uri/rfc2396_parser.rb
index 556da20aa2..c719aa0726 100644
--- a/lib/uri/rfc2396_parser.rb
+++ b/lib/uri/rfc2396_parser.rb
@@ -3,7 +3,6 @@
# = uri/common.rb
#
# Author:: Akira Yamada <akira@ruby-lang.org>
-# Revision:: $Id$
# License::
# You can redistribute it and/or modify it under the same term as Ruby.
#
@@ -208,21 +207,9 @@ module URI
# #=> #<URI::LDAP ldap://ldap.example.com/dc=example?user=john>
#
def parse(uri)
- scheme, userinfo, host, port,
- registry, path, opaque, query, fragment = self.split(uri)
-
- if scheme && URI.scheme_list.include?(scheme.upcase)
- URI.scheme_list[scheme.upcase].new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment, self)
- else
- Generic.new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment, self)
- end
+ URI.for(*self.split(uri), self)
end
-
#
# == Args
#
diff --git a/lib/uri/rfc3986_parser.rb b/lib/uri/rfc3986_parser.rb
index 08539f069a..49a594c17d 100644
--- a/lib/uri/rfc3986_parser.rb
+++ b/lib/uri/rfc3986_parser.rb
@@ -69,18 +69,7 @@ module URI
end
def parse(uri) # :nodoc:
- scheme, userinfo, host, port,
- registry, path, opaque, query, fragment = self.split(uri)
- scheme_list = URI.scheme_list
- if scheme && scheme_list.include?(uc = scheme.upcase)
- scheme_list[uc].new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment, self)
- else
- Generic.new(scheme, userinfo, host, port,
- registry, path, opaque, query,
- fragment, self)
- end
+ URI.for(*self.split(uri), self)
end
diff --git a/lib/uri/uri.gemspec b/lib/uri/uri.gemspec
index 95cb8e2d42..c4a16f47eb 100644
--- a/lib/uri/uri.gemspec
+++ b/lib/uri/uri.gemspec
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
spec.summary = %q{URI is a module providing classes to handle Uniform Resource Identifiers}
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/uri"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/lib/uri/version.rb b/lib/uri/version.rb
index 4f54113393..41da51d844 100644
--- a/lib/uri/version.rb
+++ b/lib/uri/version.rb
@@ -1,6 +1,6 @@
module URI
# :stopdoc:
- VERSION_CODE = '001000'.freeze
+ VERSION_CODE = '001001'.freeze
VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
# :startdoc:
end
diff --git a/lib/uri/ws.rb b/lib/uri/ws.rb
new file mode 100644
index 0000000000..2bfee59003
--- /dev/null
+++ b/lib/uri/ws.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: false
+# = uri/ws.rb
+#
+# Author:: Matt Muller <mamuller@amazon.com>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+#
+# See URI for general documentation
+#
+
+require_relative 'generic'
+
+module URI
+
+ #
+ # The syntax of WS URIs is defined in RFC6455 section 3.
+ #
+ # Note that the Ruby URI library allows WS URLs containing usernames and
+ # passwords. This is not legal as per the RFC, but used to be
+ # supported in Internet Explorer 5 and 6, before the MS04-004 security
+ # update. See <URL:http://support.microsoft.com/kb/834489>.
+ #
+ class WS < Generic
+ # A Default port of 80 for URI::WS.
+ DEFAULT_PORT = 80
+
+ # An Array of the available components for URI::WS.
+ COMPONENT = %i[
+ scheme
+ userinfo host port
+ path
+ query
+ ].freeze
+
+ #
+ # == Description
+ #
+ # Creates a new URI::WS object from components, with syntax checking.
+ #
+ # The components accepted are userinfo, host, port, path, and query.
+ #
+ # The components should be provided either as an Array, or as a Hash
+ # with keys formed by preceding the component names with a colon.
+ #
+ # If an Array is used, the components must be passed in the
+ # order <code>[userinfo, host, port, path, query]</code>.
+ #
+ # Example:
+ #
+ # uri = URI::WS.build(host: 'www.example.com', path: '/foo/bar')
+ #
+ # uri = URI::WS.build([nil, "www.example.com", nil, "/path", "query"])
+ #
+ # Currently, if passed userinfo components this method generates
+ # invalid WS URIs as per RFC 1738.
+ #
+ def self.build(args)
+ tmp = Util.make_components_hash(self, args)
+ super(tmp)
+ end
+
+ #
+ # == Description
+ #
+ # Returns the full path for a WS URI, as required by Net::HTTP::Get.
+ #
+ # If the URI contains a query, the full path is URI#path + '?' + URI#query.
+ # Otherwise, the path is simply URI#path.
+ #
+ # Example:
+ #
+ # uri = URI::WS.build(path: '/foo/bar', query: 'test=true')
+ # uri.request_uri # => "/foo/bar?test=true"
+ #
+ def request_uri
+ return unless @path
+
+ url = @query ? "#@path?#@query" : @path.dup
+ url.start_with?(?/.freeze) ? url : ?/ + url
+ end
+ end
+
+ @@schemes['WS'] = WS
+
+end
diff --git a/lib/uri/wss.rb b/lib/uri/wss.rb
new file mode 100644
index 0000000000..1cfa133389
--- /dev/null
+++ b/lib/uri/wss.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: false
+# = uri/wss.rb
+#
+# Author:: Matt Muller <mamuller@amazon.com>
+# License:: You can redistribute it and/or modify it under the same term as Ruby.
+#
+# See URI for general documentation
+#
+
+require_relative 'ws'
+
+module URI
+
+ # The default port for WSS URIs is 443, and the scheme is 'wss:' rather
+ # than 'ws:'. Other than that, WSS URIs are identical to WS URIs;
+ # see URI::WS.
+ class WSS < WS
+ # A Default port of 443 for URI::WSS
+ DEFAULT_PORT = 443
+ end
+ @@schemes['WSS'] = WSS
+end
diff --git a/lib/weakref.rb b/lib/weakref.rb
index 824d4016e1..fbd5d8fa82 100644
--- a/lib/weakref.rb
+++ b/lib/weakref.rb
@@ -17,6 +17,7 @@ require "delegate"
#
class WeakRef < Delegator
+ VERSION = "0.1.1"
##
# RefError is raised when a referenced object has been recycled by the
diff --git a/lib/weakref/weakref.gemspec b/lib/weakref/weakref.gemspec
new file mode 100644
index 0000000000..96a9765079
--- /dev/null
+++ b/lib/weakref/weakref.gemspec
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+name = File.basename(__FILE__, ".gemspec")
+version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
+ end rescue nil
+end
+
+Gem::Specification.new do |spec|
+ spec.name = name
+ spec.version = version
+ spec.authors = ["Yukihiro Matsumoto"]
+ spec.email = ["matz@ruby-lang.org"]
+
+ spec.summary = %q{Allows a referenced object to be garbage-collected.}
+ spec.description = %q{Allows a referenced object to be garbage-collected.}
+ spec.homepage = "https://github.com/ruby/weakref"
+
+ spec.metadata["homepage_uri"] = spec.homepage
+ spec.metadata["source_code_uri"] = "https://github.com/ruby/weakref"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
+
+ # Specify which files should be added to the gem when it is released.
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
+ `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ end
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "delegate"
+end
diff --git a/lib/webrick.rb b/lib/webrick.rb
deleted file mode 100644
index 1c0eb81dbd..0000000000
--- a/lib/webrick.rb
+++ /dev/null
@@ -1,227 +0,0 @@
-# frozen_string_literal: false
-##
-# = WEB server toolkit.
-#
-# WEBrick is an HTTP server toolkit that can be configured as an HTTPS server,
-# a proxy server, and a virtual-host server. WEBrick features complete
-# logging of both server operations and HTTP access. WEBrick supports both
-# basic and digest authentication in addition to algorithms not in RFC 2617.
-#
-# A WEBrick server can be composed of multiple WEBrick servers or servlets to
-# provide differing behavior on a per-host or per-path basis. WEBrick
-# includes servlets for handling CGI scripts, ERB pages, Ruby blocks and
-# directory listings.
-#
-# WEBrick also includes tools for daemonizing a process and starting a process
-# at a higher privilege level and dropping permissions.
-#
-# == Starting an HTTP server
-#
-# To create a new WEBrick::HTTPServer that will listen to connections on port
-# 8000 and serve documents from the current user's public_html folder:
-#
-# require 'webrick'
-#
-# root = File.expand_path '~/public_html'
-# server = WEBrick::HTTPServer.new :Port => 8000, :DocumentRoot => root
-#
-# To run the server you will need to provide a suitable shutdown hook as
-# starting the server blocks the current thread:
-#
-# trap 'INT' do server.shutdown end
-#
-# server.start
-#
-# == Custom Behavior
-#
-# The easiest way to have a server perform custom operations is through
-# WEBrick::HTTPServer#mount_proc. The block given will be called with a
-# WEBrick::HTTPRequest with request info and a WEBrick::HTTPResponse which
-# must be filled in appropriately:
-#
-# server.mount_proc '/' do |req, res|
-# res.body = 'Hello, world!'
-# end
-#
-# Remember that +server.mount_proc+ must precede +server.start+.
-#
-# == Servlets
-#
-# Advanced custom behavior can be obtained through mounting a subclass of
-# WEBrick::HTTPServlet::AbstractServlet. Servlets provide more modularity
-# when writing an HTTP server than mount_proc allows. Here is a simple
-# servlet:
-#
-# class Simple < WEBrick::HTTPServlet::AbstractServlet
-# def do_GET request, response
-# status, content_type, body = do_stuff_with request
-#
-# response.status = 200
-# response['Content-Type'] = 'text/plain'
-# response.body = 'Hello, World!'
-# end
-# end
-#
-# To initialize the servlet you mount it on the server:
-#
-# server.mount '/simple', Simple
-#
-# See WEBrick::HTTPServlet::AbstractServlet for more details.
-#
-# == Virtual Hosts
-#
-# A server can act as a virtual host for multiple host names. After creating
-# the listening host, additional hosts that do not listen can be created and
-# attached as virtual hosts:
-#
-# server = WEBrick::HTTPServer.new # ...
-#
-# vhost = WEBrick::HTTPServer.new :ServerName => 'vhost.example',
-# :DoNotListen => true, # ...
-# vhost.mount '/', ...
-#
-# server.virtual_host vhost
-#
-# If no +:DocumentRoot+ is provided and no servlets or procs are mounted on the
-# main server it will return 404 for all URLs.
-#
-# == HTTPS
-#
-# To create an HTTPS server you only need to enable SSL and provide an SSL
-# certificate name:
-#
-# require 'webrick'
-# require 'webrick/https'
-#
-# cert_name = [
-# %w[CN localhost],
-# ]
-#
-# server = WEBrick::HTTPServer.new(:Port => 8000,
-# :SSLEnable => true,
-# :SSLCertName => cert_name)
-#
-# This will start the server with a self-generated self-signed certificate.
-# The certificate will be changed every time the server is restarted.
-#
-# To create a server with a pre-determined key and certificate you can provide
-# them:
-#
-# require 'webrick'
-# require 'webrick/https'
-# require 'openssl'
-#
-# cert = OpenSSL::X509::Certificate.new File.read '/path/to/cert.pem'
-# pkey = OpenSSL::PKey::RSA.new File.read '/path/to/pkey.pem'
-#
-# server = WEBrick::HTTPServer.new(:Port => 8000,
-# :SSLEnable => true,
-# :SSLCertificate => cert,
-# :SSLPrivateKey => pkey)
-#
-# == Proxy Server
-#
-# WEBrick can act as a proxy server:
-#
-# require 'webrick'
-# require 'webrick/httpproxy'
-#
-# proxy = WEBrick::HTTPProxyServer.new :Port => 8000
-#
-# trap 'INT' do proxy.shutdown end
-#
-# See WEBrick::HTTPProxy for further details including modifying proxied
-# responses.
-#
-# == Basic and Digest authentication
-#
-# WEBrick provides both Basic and Digest authentication for regular and proxy
-# servers. See WEBrick::HTTPAuth, WEBrick::HTTPAuth::BasicAuth and
-# WEBrick::HTTPAuth::DigestAuth.
-#
-# == WEBrick as a Production Web Server
-#
-# WEBrick can be run as a production server for small loads.
-#
-# === Daemonizing
-#
-# To start a WEBrick server as a daemon simple run WEBrick::Daemon.start
-# before starting the server.
-#
-# === Dropping Permissions
-#
-# WEBrick can be started as one user to gain permission to bind to port 80 or
-# 443 for serving HTTP or HTTPS traffic then can drop these permissions for
-# regular operation. To listen on all interfaces for HTTP traffic:
-#
-# sockets = WEBrick::Utils.create_listeners nil, 80
-#
-# Then drop privileges:
-#
-# WEBrick::Utils.su 'www'
-#
-# Then create a server that does not listen by default:
-#
-# server = WEBrick::HTTPServer.new :DoNotListen => true, # ...
-#
-# Then overwrite the listening sockets with the port 80 sockets:
-#
-# server.listeners.replace sockets
-#
-# === Logging
-#
-# WEBrick can separately log server operations and end-user access. For
-# server operations:
-#
-# log_file = File.open '/var/log/webrick.log', 'a+'
-# log = WEBrick::Log.new log_file
-#
-# For user access logging:
-#
-# access_log = [
-# [log_file, WEBrick::AccessLog::COMBINED_LOG_FORMAT],
-# ]
-#
-# server = WEBrick::HTTPServer.new :Logger => log, :AccessLog => access_log
-#
-# See WEBrick::AccessLog for further log formats.
-#
-# === Log Rotation
-#
-# To rotate logs in WEBrick on a HUP signal (like syslogd can send), open the
-# log file in 'a+' mode (as above) and trap 'HUP' to reopen the log file:
-#
-# trap 'HUP' do log_file.reopen '/path/to/webrick.log', 'a+'
-#
-# == Copyright
-#
-# Author: IPR -- Internet Programming with Ruby -- writers
-#
-# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU
-# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
-# reserved.
-#--
-# $IPR: webrick.rb,v 1.12 2002/10/01 17:16:31 gotoyuzo Exp $
-
-module WEBrick
-end
-
-require 'webrick/compat.rb'
-
-require 'webrick/version.rb'
-require 'webrick/config.rb'
-require 'webrick/log.rb'
-require 'webrick/server.rb'
-require_relative 'webrick/utils.rb'
-require 'webrick/accesslog'
-
-require 'webrick/htmlutils.rb'
-require 'webrick/httputils.rb'
-require 'webrick/cookie.rb'
-require 'webrick/httpversion.rb'
-require 'webrick/httpstatus.rb'
-require 'webrick/httprequest.rb'
-require 'webrick/httpresponse.rb'
-require 'webrick/httpserver.rb'
-require 'webrick/httpservlet.rb'
-require 'webrick/httpauth.rb'
diff --git a/lib/webrick/httpauth/authenticator.rb b/lib/webrick/httpauth/authenticator.rb
deleted file mode 100644
index 8655118a04..0000000000
--- a/lib/webrick/httpauth/authenticator.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-# frozen_string_literal: false
-#--
-# httpauth/authenticator.rb -- Authenticator mix-in module.
-#
-# Author: IPR -- Internet Programming with Ruby -- writers
-# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
-# reserved.
-#
-# $IPR: authenticator.rb,v 1.3 2003/02/20 07:15:47 gotoyuzo Exp $
-
-module WEBrick
- module HTTPAuth
-
- ##
- # Module providing generic support for both Digest and Basic
- # authentication schemes.
-
- module Authenticator
-
- RequestField = "Authorization" # :nodoc:
- ResponseField = "WWW-Authenticate" # :nodoc:
- ResponseInfoField = "Authentication-Info" # :nodoc:
- AuthException = HTTPStatus::Unauthorized # :nodoc:
-
- ##
- # Method of authentication, must be overridden by the including class
-
- AuthScheme = nil
-
- ##
- # The realm this authenticator covers
-
- attr_reader :realm
-
- ##
- # The user database for this authenticator
-
- attr_reader :userdb
-
- ##
- # The logger for this authenticator
-
- attr_reader :logger
-
- private
-
- # :stopdoc:
-
- ##
- # Initializes the authenticator from +config+
-
- def check_init(config)
- [:UserDB, :Realm].each{|sym|
- unless config[sym]
- raise ArgumentError, "Argument #{sym.inspect} missing."
- end
- }
- @realm = config[:Realm]
- @userdb = config[:UserDB]
- @logger = config[:Logger] || Log::new($stderr)
- @reload_db = config[:AutoReloadUserDB]
- @request_field = self::class::RequestField
- @response_field = self::class::ResponseField
- @resp_info_field = self::class::ResponseInfoField
- @auth_exception = self::class::AuthException
- @auth_scheme = self::class::AuthScheme
- end
-
- ##
- # Ensures +req+ has credentials that can be authenticated.
-
- def check_scheme(req)
- unless credentials = req[@request_field]
- error("no credentials in the request.")
- return nil
- end
- unless match = /^#{@auth_scheme}\s+/i.match(credentials)
- error("invalid scheme in %s.", credentials)
- info("%s: %s", @request_field, credentials) if $DEBUG
- return nil
- end
- return match.post_match
- end
-
- def log(meth, fmt, *args)
- msg = format("%s %s: ", @auth_scheme, @realm)
- msg << fmt % args
- @logger.send(meth, msg)
- end
-
- def error(fmt, *args)
- if @logger.error?
- log(:error, fmt, *args)
- end
- end
-
- def info(fmt, *args)
- if @logger.info?
- log(:info, fmt, *args)
- end
- end
-
- # :startdoc:
- end
-
- ##
- # Module providing generic support for both Digest and Basic
- # authentication schemes for proxies.
-
- module ProxyAuthenticator
- RequestField = "Proxy-Authorization" # :nodoc:
- ResponseField = "Proxy-Authenticate" # :nodoc:
- InfoField = "Proxy-Authentication-Info" # :nodoc:
- AuthException = HTTPStatus::ProxyAuthenticationRequired # :nodoc:
- end
- end
-end
diff --git a/lib/webrick/httpproxy.rb b/lib/webrick/httpproxy.rb
deleted file mode 100644
index d05d59514c..0000000000
--- a/lib/webrick/httpproxy.rb
+++ /dev/null
@@ -1,350 +0,0 @@
-# frozen_string_literal: false
-#
-# httpproxy.rb -- HTTPProxy Class
-#
-# Author: IPR -- Internet Programming with Ruby -- writers
-# Copyright (c) 2002 GOTO Kentaro
-# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
-# reserved.
-#
-# $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $
-# $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $
-
-require_relative "httpserver"
-require "net/http"
-
-module WEBrick
-
- NullReader = Object.new # :nodoc:
- class << NullReader # :nodoc:
- def read(*args)
- nil
- end
- alias gets read
- end
-
- FakeProxyURI = Object.new # :nodoc:
- class << FakeProxyURI # :nodoc:
- def method_missing(meth, *args)
- if %w(scheme host port path query userinfo).member?(meth.to_s)
- return nil
- end
- super
- end
- end
-
- # :startdoc:
-
- ##
- # An HTTP Proxy server which proxies GET, HEAD and POST requests.
- #
- # To create a simple proxy server:
- #
- # require 'webrick'
- # require 'webrick/httpproxy'
- #
- # proxy = WEBrick::HTTPProxyServer.new Port: 8000
- #
- # trap 'INT' do proxy.shutdown end
- # trap 'TERM' do proxy.shutdown end
- #
- # proxy.start
- #
- # See ::new for proxy-specific configuration items.
- #
- # == Modifying proxied responses
- #
- # To modify content the proxy server returns use the +:ProxyContentHandler+
- # option:
- #
- # handler = proc do |req, res|
- # if res['content-type'] == 'text/plain' then
- # res.body << "\nThis content was proxied!\n"
- # end
- # end
- #
- # proxy =
- # WEBrick::HTTPProxyServer.new Port: 8000, ProxyContentHandler: handler
-
- class HTTPProxyServer < HTTPServer
-
- ##
- # Proxy server configurations. The proxy server handles the following
- # configuration items in addition to those supported by HTTPServer:
- #
- # :ProxyAuthProc:: Called with a request and response to authorize a
- # request
- # :ProxyVia:: Appended to the via header
- # :ProxyURI:: The proxy server's URI
- # :ProxyContentHandler:: Called with a request and response and allows
- # modification of the response
- # :ProxyTimeout:: Sets the proxy timeouts to 30 seconds for open and 60
- # seconds for read operations
-
- def initialize(config={}, default=Config::HTTP)
- super(config, default)
- c = @config
- @via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}"
- end
-
- # :stopdoc:
- def service(req, res)
- if req.request_method == "CONNECT"
- do_CONNECT(req, res)
- elsif req.unparsed_uri =~ %r!^http://!
- proxy_service(req, res)
- else
- super(req, res)
- end
- end
-
- def proxy_auth(req, res)
- if proc = @config[:ProxyAuthProc]
- proc.call(req, res)
- end
- req.header.delete("proxy-authorization")
- end
-
- def proxy_uri(req, res)
- # should return upstream proxy server's URI
- return @config[:ProxyURI]
- end
-
- def proxy_service(req, res)
- # Proxy Authentication
- proxy_auth(req, res)
-
- begin
- self.send("do_#{req.request_method}", req, res)
- rescue NoMethodError
- raise HTTPStatus::MethodNotAllowed,
- "unsupported method `#{req.request_method}'."
- rescue => err
- logger.debug("#{err.class}: #{err.message}")
- raise HTTPStatus::ServiceUnavailable, err.message
- end
-
- # Process contents
- if handler = @config[:ProxyContentHandler]
- handler.call(req, res)
- end
- end
-
- def do_CONNECT(req, res)
- # Proxy Authentication
- proxy_auth(req, res)
-
- ua = Thread.current[:WEBrickSocket] # User-Agent
- raise HTTPStatus::InternalServerError,
- "[BUG] cannot get socket" unless ua
-
- host, port = req.unparsed_uri.split(":", 2)
- # Proxy authentication for upstream proxy server
- if proxy = proxy_uri(req, res)
- proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0"
- if proxy.userinfo
- credentials = "Basic " + [proxy.userinfo].pack("m0")
- end
- host, port = proxy.host, proxy.port
- end
-
- begin
- @logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.")
- os = TCPSocket.new(host, port) # origin server
-
- if proxy
- @logger.debug("CONNECT: sending a Request-Line")
- os << proxy_request_line << CRLF
- @logger.debug("CONNECT: > #{proxy_request_line}")
- if credentials
- @logger.debug("CONNECT: sending credentials")
- os << "Proxy-Authorization: " << credentials << CRLF
- end
- os << CRLF
- proxy_status_line = os.gets(LF)
- @logger.debug("CONNECT: read Status-Line from the upstream server")
- @logger.debug("CONNECT: < #{proxy_status_line}")
- if %r{^HTTP/\d+\.\d+\s+200\s*} =~ proxy_status_line
- while line = os.gets(LF)
- break if /\A(#{CRLF}|#{LF})\z/om =~ line
- end
- else
- raise HTTPStatus::BadGateway
- end
- end
- @logger.debug("CONNECT #{host}:#{port}: succeeded")
- res.status = HTTPStatus::RC_OK
- rescue => ex
- @logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'")
- res.set_error(ex)
- raise HTTPStatus::EOFError
- ensure
- if handler = @config[:ProxyContentHandler]
- handler.call(req, res)
- end
- res.send_response(ua)
- access_log(@config, req, res)
-
- # Should clear request-line not to send the response twice.
- # see: HTTPServer#run
- req.parse(NullReader) rescue nil
- end
-
- begin
- while fds = IO::select([ua, os])
- if fds[0].member?(ua)
- buf = ua.readpartial(1024);
- @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent")
- os.write(buf)
- elsif fds[0].member?(os)
- buf = os.readpartial(1024);
- @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}")
- ua.write(buf)
- end
- end
- rescue
- os.close
- @logger.debug("CONNECT #{host}:#{port}: closed")
- end
-
- raise HTTPStatus::EOFError
- end
-
- def do_GET(req, res)
- perform_proxy_request(req, res, Net::HTTP::Get)
- end
-
- def do_HEAD(req, res)
- perform_proxy_request(req, res, Net::HTTP::Head)
- end
-
- def do_POST(req, res)
- perform_proxy_request(req, res, Net::HTTP::Post, req.body_reader)
- end
-
- def do_OPTIONS(req, res)
- res['allow'] = "GET,HEAD,POST,OPTIONS,CONNECT"
- end
-
- private
-
- # Some header fields should not be transferred.
- HopByHop = %w( connection keep-alive proxy-authenticate upgrade
- proxy-authorization te trailers transfer-encoding )
- ShouldNotTransfer = %w( set-cookie proxy-connection )
- def split_field(f) f ? f.split(/,\s+/).collect{|i| i.downcase } : [] end
-
- def choose_header(src, dst)
- connections = split_field(src['connection'])
- src.each{|key, value|
- key = key.downcase
- if HopByHop.member?(key) || # RFC2616: 13.5.1
- connections.member?(key) || # RFC2616: 14.10
- ShouldNotTransfer.member?(key) # pragmatics
- @logger.debug("choose_header: `#{key}: #{value}'")
- next
- end
- dst[key] = value
- }
- end
-
- # Net::HTTP is stupid about the multiple header fields.
- # Here is workaround:
- def set_cookie(src, dst)
- if str = src['set-cookie']
- cookies = []
- str.split(/,\s*/).each{|token|
- if /^[^=]+;/o =~ token
- cookies[-1] << ", " << token
- elsif /=/o =~ token
- cookies << token
- else
- cookies[-1] << ", " << token
- end
- }
- dst.cookies.replace(cookies)
- end
- end
-
- def set_via(h)
- if @config[:ProxyVia]
- if h['via']
- h['via'] << ", " << @via
- else
- h['via'] = @via
- end
- end
- end
-
- def setup_proxy_header(req, res)
- # Choose header fields to transfer
- header = Hash.new
- choose_header(req, header)
- set_via(header)
- return header
- end
-
- def setup_upstream_proxy_authentication(req, res, header)
- if upstream = proxy_uri(req, res)
- if upstream.userinfo
- header['proxy-authorization'] =
- "Basic " + [upstream.userinfo].pack("m0")
- end
- return upstream
- end
- return FakeProxyURI
- end
-
- def perform_proxy_request(req, res, req_class, body_stream = nil)
- uri = req.request_uri
- path = uri.path.dup
- path << "?" << uri.query if uri.query
- header = setup_proxy_header(req, res)
- upstream = setup_upstream_proxy_authentication(req, res, header)
-
- body_tmp = []
- http = Net::HTTP.new(uri.host, uri.port, upstream.host, upstream.port)
- req_fib = Fiber.new do
- http.start do
- if @config[:ProxyTimeout]
- ################################## these issues are
- http.open_timeout = 30 # secs # necessary (maybe because
- http.read_timeout = 60 # secs # Ruby's bug, but why?)
- ##################################
- end
- if body_stream && req['transfer-encoding'] =~ /\bchunked\b/i
- header['Transfer-Encoding'] = 'chunked'
- end
- http_req = req_class.new(path, header)
- http_req.body_stream = body_stream if body_stream
- http.request(http_req) do |response|
- # Persistent connection requirements are mysterious for me.
- # So I will close the connection in every response.
- res['proxy-connection'] = "close"
- res['connection'] = "close"
-
- # stream Net::HTTP::HTTPResponse to WEBrick::HTTPResponse
- res.status = response.code.to_i
- res.chunked = response.chunked?
- choose_header(response, res)
- set_cookie(response, res)
- set_via(res)
- response.read_body do |buf|
- body_tmp << buf
- Fiber.yield # wait for res.body Proc#call
- end
- end # http.request
- end
- end
- req_fib.resume # read HTTP response headers and first chunk of the body
- res.body = ->(socket) do
- while buf = body_tmp.shift
- socket.write(buf)
- buf.clear
- req_fib.resume # continue response.read_body
- end
- end
- end
- # :stopdoc:
- end
-end
diff --git a/lib/webrick/httprequest.rb b/lib/webrick/httprequest.rb
deleted file mode 100644
index 6af0cee97d..0000000000
--- a/lib/webrick/httprequest.rb
+++ /dev/null
@@ -1,631 +0,0 @@
-# frozen_string_literal: false
-#
-# httprequest.rb -- HTTPRequest Class
-#
-# Author: IPR -- Internet Programming with Ruby -- writers
-# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
-# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
-# reserved.
-#
-# $IPR: httprequest.rb,v 1.64 2003/07/13 17:18:22 gotoyuzo Exp $
-
-require 'uri'
-require_relative 'httpversion'
-require_relative 'httpstatus'
-require_relative 'httputils'
-require_relative 'cookie'
-
-module WEBrick
-
- ##
- # An HTTP request. This is consumed by service and do_* methods in
- # WEBrick servlets
-
- class HTTPRequest
-
- BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ] # :nodoc:
-
- # :section: Request line
-
- ##
- # The complete request line such as:
- #
- # GET / HTTP/1.1
-
- attr_reader :request_line
-
- ##
- # The request method, GET, POST, PUT, etc.
-
- attr_reader :request_method
-
- ##
- # The unparsed URI of the request
-
- attr_reader :unparsed_uri
-
- ##
- # The HTTP version of the request
-
- attr_reader :http_version
-
- # :section: Request-URI
-
- ##
- # The parsed URI of the request
-
- attr_reader :request_uri
-
- ##
- # The request path
-
- attr_reader :path
-
- ##
- # The script name (CGI variable)
-
- attr_accessor :script_name
-
- ##
- # The path info (CGI variable)
-
- attr_accessor :path_info
-
- ##
- # The query from the URI of the request
-
- attr_accessor :query_string
-
- # :section: Header and entity body
-
- ##
- # The raw header of the request
-
- attr_reader :raw_header
-
- ##
- # The parsed header of the request
-
- attr_reader :header
-
- ##
- # The parsed request cookies
-
- attr_reader :cookies
-
- ##
- # The Accept header value
-
- attr_reader :accept
-
- ##
- # The Accept-Charset header value
-
- attr_reader :accept_charset
-
- ##
- # The Accept-Encoding header value
-
- attr_reader :accept_encoding
-
- ##
- # The Accept-Language header value
-
- attr_reader :accept_language
-
- # :section:
-
- ##
- # The remote user (CGI variable)
-
- attr_accessor :user
-
- ##
- # The socket address of the server
-
- attr_reader :addr
-
- ##
- # The socket address of the client
-
- attr_reader :peeraddr
-
- ##
- # Hash of request attributes
-
- attr_reader :attributes
-
- ##
- # Is this a keep-alive connection?
-
- attr_reader :keep_alive
-
- ##
- # The local time this request was received
-
- attr_reader :request_time
-
- ##
- # Creates a new HTTP request. WEBrick::Config::HTTP is the default
- # configuration.
-
- def initialize(config)
- @config = config
- @buffer_size = @config[:InputBufferSize]
- @logger = config[:Logger]
-
- @request_line = @request_method =
- @unparsed_uri = @http_version = nil
-
- @request_uri = @host = @port = @path = nil
- @script_name = @path_info = nil
- @query_string = nil
- @query = nil
- @form_data = nil
-
- @raw_header = Array.new
- @header = nil
- @cookies = []
- @accept = []
- @accept_charset = []
- @accept_encoding = []
- @accept_language = []
- @body = ""
-
- @addr = @peeraddr = nil
- @attributes = {}
- @user = nil
- @keep_alive = false
- @request_time = nil
-
- @remaining_size = nil
- @socket = nil
-
- @forwarded_proto = @forwarded_host = @forwarded_port =
- @forwarded_server = @forwarded_for = nil
- end
-
- ##
- # Parses a request from +socket+. This is called internally by
- # WEBrick::HTTPServer.
-
- def parse(socket=nil)
- @socket = socket
- begin
- @peeraddr = socket.respond_to?(:peeraddr) ? socket.peeraddr : []
- @addr = socket.respond_to?(:addr) ? socket.addr : []
- rescue Errno::ENOTCONN
- raise HTTPStatus::EOFError
- end
-
- read_request_line(socket)
- if @http_version.major > 0
- read_header(socket)
- @header['cookie'].each{|cookie|
- @cookies += Cookie::parse(cookie)
- }
- @accept = HTTPUtils.parse_qvalues(self['accept'])
- @accept_charset = HTTPUtils.parse_qvalues(self['accept-charset'])
- @accept_encoding = HTTPUtils.parse_qvalues(self['accept-encoding'])
- @accept_language = HTTPUtils.parse_qvalues(self['accept-language'])
- end
- return if @request_method == "CONNECT"
- return if @unparsed_uri == "*"
-
- begin
- setup_forwarded_info
- @request_uri = parse_uri(@unparsed_uri)
- @path = HTTPUtils::unescape(@request_uri.path)
- @path = HTTPUtils::normalize_path(@path)
- @host = @request_uri.host
- @port = @request_uri.port
- @query_string = @request_uri.query
- @script_name = ""
- @path_info = @path.dup
- rescue
- raise HTTPStatus::BadRequest, "bad URI `#{@unparsed_uri}'."
- end
-
- if /\Aclose\z/io =~ self["connection"]
- @keep_alive = false
- elsif /\Akeep-alive\z/io =~ self["connection"]
- @keep_alive = true
- elsif @http_version < "1.1"
- @keep_alive = false
- else
- @keep_alive = true
- end
- end
-
- ##
- # Generate HTTP/1.1 100 continue response if the client expects it,
- # otherwise does nothing.
-
- def continue # :nodoc:
- if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
- @socket << "HTTP/#{@config[:HTTPVersion]} 100 continue#{CRLF}#{CRLF}"
- @header.delete('expect')
- end
- end
-
- ##
- # Returns the request body.
-
- def body(&block) # :yields: body_chunk
- block ||= Proc.new{|chunk| @body << chunk }
- read_body(@socket, block)
- @body.empty? ? nil : @body
- end
-
- ##
- # Prepares the HTTPRequest object for use as the
- # source for IO.copy_stream
-
- def body_reader
- @body_tmp = []
- @body_rd = Fiber.new do
- body do |buf|
- @body_tmp << buf
- Fiber.yield
- end
- end
- @body_rd.resume # grab the first chunk and yield
- self
- end
-
- # for IO.copy_stream. Note: we may return a larger string than +size+
- # here; but IO.copy_stream does not care.
- def readpartial(size, buf = ''.b) # :nodoc
- res = @body_tmp.shift or raise EOFError, 'end of file reached'
- buf.replace(res)
- res.clear
- @body_rd.resume # get more chunks
- buf
- end
-
- ##
- # Request query as a Hash
-
- def query
- unless @query
- parse_query()
- end
- @query
- end
-
- ##
- # The content-length header
-
- def content_length
- return Integer(self['content-length'])
- end
-
- ##
- # The content-type header
-
- def content_type
- return self['content-type']
- end
-
- ##
- # Retrieves +header_name+
-
- def [](header_name)
- if @header
- value = @header[header_name.downcase]
- value.empty? ? nil : value.join(", ")
- end
- end
-
- ##
- # Iterates over the request headers
-
- def each
- if @header
- @header.each{|k, v|
- value = @header[k]
- yield(k, value.empty? ? nil : value.join(", "))
- }
- end
- end
-
- ##
- # The host this request is for
-
- def host
- return @forwarded_host || @host
- end
-
- ##
- # The port this request is for
-
- def port
- return @forwarded_port || @port
- end
-
- ##
- # The server name this request is for
-
- def server_name
- return @forwarded_server || @config[:ServerName]
- end
-
- ##
- # The client's IP address
-
- def remote_ip
- return self["client-ip"] || @forwarded_for || @peeraddr[3]
- end
-
- ##
- # Is this an SSL request?
-
- def ssl?
- return @request_uri.scheme == "https"
- end
-
- ##
- # Should the connection this request was made on be kept alive?
-
- def keep_alive?
- @keep_alive
- end
-
- def to_s # :nodoc:
- ret = @request_line.dup
- @raw_header.each{|line| ret << line }
- ret << CRLF
- ret << body if body
- ret
- end
-
- ##
- # Consumes any remaining body and updates keep-alive status
-
- def fixup() # :nodoc:
- begin
- body{|chunk| } # read remaining body
- rescue HTTPStatus::Error => ex
- @logger.error("HTTPRequest#fixup: #{ex.class} occurred.")
- @keep_alive = false
- rescue => ex
- @logger.error(ex)
- @keep_alive = false
- end
- end
-
- # This method provides the metavariables defined by the revision 3
- # of "The WWW Common Gateway Interface Version 1.1"
- # To browse the current document of CGI Version 1.1, see below:
- # http://tools.ietf.org/html/rfc3875
-
- def meta_vars
- meta = Hash.new
-
- cl = self["Content-Length"]
- ct = self["Content-Type"]
- meta["CONTENT_LENGTH"] = cl if cl.to_i > 0
- meta["CONTENT_TYPE"] = ct.dup if ct
- meta["GATEWAY_INTERFACE"] = "CGI/1.1"
- meta["PATH_INFO"] = @path_info ? @path_info.dup : ""
- #meta["PATH_TRANSLATED"] = nil # no plan to be provided
- meta["QUERY_STRING"] = @query_string ? @query_string.dup : ""
- meta["REMOTE_ADDR"] = @peeraddr[3]
- meta["REMOTE_HOST"] = @peeraddr[2]
- #meta["REMOTE_IDENT"] = nil # no plan to be provided
- meta["REMOTE_USER"] = @user
- meta["REQUEST_METHOD"] = @request_method.dup
- meta["REQUEST_URI"] = @request_uri.to_s
- meta["SCRIPT_NAME"] = @script_name.dup
- meta["SERVER_NAME"] = @host
- meta["SERVER_PORT"] = @port.to_s
- meta["SERVER_PROTOCOL"] = "HTTP/" + @config[:HTTPVersion].to_s
- meta["SERVER_SOFTWARE"] = @config[:ServerSoftware].dup
-
- self.each{|key, val|
- next if /^content-type$/i =~ key
- next if /^content-length$/i =~ key
- name = "HTTP_" + key
- name.gsub!(/-/o, "_")
- name.upcase!
- meta[name] = val
- }
-
- meta
- end
-
- private
-
- # :stopdoc:
-
- MAX_URI_LENGTH = 2083 # :nodoc:
-
- # same as Mongrel, Thin and Puma
- MAX_HEADER_LENGTH = (112 * 1024) # :nodoc:
-
- def read_request_line(socket)
- @request_line = read_line(socket, MAX_URI_LENGTH) if socket
- raise HTTPStatus::EOFError unless @request_line
-
- @request_bytes = @request_line.bytesize
- if @request_bytes >= MAX_URI_LENGTH and @request_line[-1, 1] != LF
- raise HTTPStatus::RequestURITooLarge
- end
-
- @request_time = Time.now
- if /^(\S+)\s+(\S++)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
- @request_method = $1
- @unparsed_uri = $2
- @http_version = HTTPVersion.new($3 ? $3 : "0.9")
- else
- rl = @request_line.sub(/\x0d?\x0a\z/o, '')
- raise HTTPStatus::BadRequest, "bad Request-Line `#{rl}'."
- end
- end
-
- def read_header(socket)
- if socket
- while line = read_line(socket)
- break if /\A(#{CRLF}|#{LF})\z/om =~ line
- if (@request_bytes += line.bytesize) > MAX_HEADER_LENGTH
- raise HTTPStatus::RequestEntityTooLarge, 'headers too large'
- end
- @raw_header << line
- end
- end
- @header = HTTPUtils::parse_header(@raw_header.join)
- end
-
- def parse_uri(str, scheme="http")
- if @config[:Escape8bitURI]
- str = HTTPUtils::escape8bit(str)
- end
- str.sub!(%r{\A/+}o, '/')
- uri = URI::parse(str)
- return uri if uri.absolute?
- if @forwarded_host
- host, port = @forwarded_host, @forwarded_port
- elsif self["host"]
- pattern = /\A(#{URI::REGEXP::PATTERN::HOST})(?::(\d+))?\z/n
- host, port = *self['host'].scan(pattern)[0]
- elsif @addr.size > 0
- host, port = @addr[2], @addr[1]
- else
- host, port = @config[:ServerName], @config[:Port]
- end
- uri.scheme = @forwarded_proto || scheme
- uri.host = host
- uri.port = port ? port.to_i : nil
- return URI::parse(uri.to_s)
- end
-
- def read_body(socket, block)
- return unless socket
- if tc = self['transfer-encoding']
- case tc
- when /\Achunked\z/io then read_chunked(socket, block)
- else raise HTTPStatus::NotImplemented, "Transfer-Encoding: #{tc}."
- end
- elsif self['content-length'] || @remaining_size
- @remaining_size ||= self['content-length'].to_i
- while @remaining_size > 0
- sz = [@buffer_size, @remaining_size].min
- break unless buf = read_data(socket, sz)
- @remaining_size -= buf.bytesize
- block.call(buf)
- end
- if @remaining_size > 0 && @socket.eof?
- raise HTTPStatus::BadRequest, "invalid body size."
- end
- elsif BODY_CONTAINABLE_METHODS.member?(@request_method)
- raise HTTPStatus::LengthRequired
- end
- return @body
- end
-
- def read_chunk_size(socket)
- line = read_line(socket)
- if /^([0-9a-fA-F]+)(?:;(\S+))?/ =~ line
- chunk_size = $1.hex
- chunk_ext = $2
- [ chunk_size, chunk_ext ]
- else
- raise HTTPStatus::BadRequest, "bad chunk `#{line}'."
- end
- end
-
- def read_chunked(socket, block)
- chunk_size, = read_chunk_size(socket)
- while chunk_size > 0
- begin
- sz = [ chunk_size, @buffer_size ].min
- data = read_data(socket, sz) # read chunk-data
- if data.nil? || data.bytesize != sz
- raise HTTPStatus::BadRequest, "bad chunk data size."
- end
- block.call(data)
- end while (chunk_size -= sz) > 0
-
- read_line(socket) # skip CRLF
- chunk_size, = read_chunk_size(socket)
- end
- read_header(socket) # trailer + CRLF
- @header.delete("transfer-encoding")
- @remaining_size = 0
- end
-
- def _read_data(io, method, *arg)
- begin
- WEBrick::Utils.timeout(@config[:RequestTimeout]){
- return io.__send__(method, *arg)
- }
- rescue Errno::ECONNRESET
- return nil
- rescue Timeout::Error
- raise HTTPStatus::RequestTimeout
- end
- end
-
- def read_line(io, size=4096)
- _read_data(io, :gets, LF, size)
- end
-
- def read_data(io, size)
- _read_data(io, :read, size)
- end
-
- def parse_query()
- begin
- if @request_method == "GET" || @request_method == "HEAD"
- @query = HTTPUtils::parse_query(@query_string)
- elsif self['content-type'] =~ /^application\/x-www-form-urlencoded/
- @query = HTTPUtils::parse_query(body)
- elsif self['content-type'] =~ /^multipart\/form-data; boundary=(.+)/
- boundary = HTTPUtils::dequote($1)
- @query = HTTPUtils::parse_form_data(body, boundary)
- else
- @query = Hash.new
- end
- rescue => ex
- raise HTTPStatus::BadRequest, ex.message
- end
- end
-
- PrivateNetworkRegexp = /
- ^unknown$|
- ^((::ffff:)?127.0.0.1|::1)$|
- ^(::ffff:)?(10|172\.(1[6-9]|2[0-9]|3[01])|192\.168)\.
- /ixo
-
- # It's said that all X-Forwarded-* headers will contain more than one
- # (comma-separated) value if the original request already contained one of
- # these headers. Since we could use these values as Host header, we choose
- # the initial(first) value. (apr_table_mergen() adds new value after the
- # existing value with ", " prefix)
- def setup_forwarded_info
- if @forwarded_server = self["x-forwarded-server"]
- @forwarded_server = @forwarded_server.split(",", 2).first
- end
- if @forwarded_proto = self["x-forwarded-proto"]
- @forwarded_proto = @forwarded_proto.split(",", 2).first
- end
- if host_port = self["x-forwarded-host"]
- host_port = host_port.split(",", 2).first
- if host_port =~ /\A(\[[0-9a-fA-F:]+\])(?::(\d+))?\z/
- @forwarded_host = $1
- tmp = $2
- else
- @forwarded_host, tmp = host_port.split(":", 2)
- end
- @forwarded_port = (tmp || (@forwarded_proto == "https" ? 443 : 80)).to_i
- end
- if addrs = self["x-forwarded-for"]
- addrs = addrs.split(",").collect(&:strip)
- addrs.reject!{|ip| PrivateNetworkRegexp =~ ip }
- @forwarded_for = addrs.first
- end
- end
-
- # :startdoc:
- end
-end
diff --git a/lib/webrick/httpservlet/filehandler.rb b/lib/webrick/httpservlet/filehandler.rb
deleted file mode 100644
index 601882ef4c..0000000000
--- a/lib/webrick/httpservlet/filehandler.rb
+++ /dev/null
@@ -1,541 +0,0 @@
-# frozen_string_literal: false
-#
-# filehandler.rb -- FileHandler Module
-#
-# Author: IPR -- Internet Programming with Ruby -- writers
-# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
-# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
-# reserved.
-#
-# $IPR: filehandler.rb,v 1.44 2003/06/07 01:34:51 gotoyuzo Exp $
-
-require 'time'
-
-require_relative '../htmlutils'
-require_relative '../httputils'
-require_relative '../httpstatus'
-
-module WEBrick
- module HTTPServlet
-
- ##
- # Servlet for serving a single file. You probably want to use the
- # FileHandler servlet instead as it handles directories and fancy indexes.
- #
- # Example:
- #
- # server.mount('/my_page.txt', WEBrick::HTTPServlet::DefaultFileHandler,
- # '/path/to/my_page.txt')
- #
- # This servlet handles If-Modified-Since and Range requests.
-
- class DefaultFileHandler < AbstractServlet
-
- ##
- # Creates a DefaultFileHandler instance for the file at +local_path+.
-
- def initialize(server, local_path)
- super(server, local_path)
- @local_path = local_path
- end
-
- # :stopdoc:
-
- def do_GET(req, res)
- st = File::stat(@local_path)
- mtime = st.mtime
- res['etag'] = sprintf("%x-%x-%x", st.ino, st.size, st.mtime.to_i)
-
- if not_modified?(req, res, mtime, res['etag'])
- res.body = ''
- raise HTTPStatus::NotModified
- elsif req['range']
- make_partial_content(req, res, @local_path, st.size)
- raise HTTPStatus::PartialContent
- else
- mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes])
- res['content-type'] = mtype
- res['content-length'] = st.size.to_s
- res['last-modified'] = mtime.httpdate
- res.body = File.open(@local_path, "rb")
- end
- end
-
- def not_modified?(req, res, mtime, etag)
- if ir = req['if-range']
- begin
- if Time.httpdate(ir) >= mtime
- return true
- end
- rescue
- if HTTPUtils::split_header_value(ir).member?(res['etag'])
- return true
- end
- end
- end
-
- if (ims = req['if-modified-since']) && Time.parse(ims) >= mtime
- return true
- end
-
- if (inm = req['if-none-match']) &&
- HTTPUtils::split_header_value(inm).member?(res['etag'])
- return true
- end
-
- return false
- end
-
- # returns a lambda for webrick/httpresponse.rb send_body_proc
- def multipart_body(body, parts, boundary, mtype, filesize)
- lambda do |socket|
- begin
- begin
- first = parts.shift
- last = parts.shift
- socket.write(
- "--#{boundary}#{CRLF}" \
- "Content-Type: #{mtype}#{CRLF}" \
- "Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \
- "#{CRLF}"
- )
-
- begin
- IO.copy_stream(body, socket, last - first + 1, first)
- rescue NotImplementedError
- body.seek(first, IO::SEEK_SET)
- IO.copy_stream(body, socket, last - first + 1)
- end
- socket.write(CRLF)
- end while parts[0]
- socket.write("--#{boundary}--#{CRLF}")
- ensure
- body.close
- end
- end
- end
-
- def make_partial_content(req, res, filename, filesize)
- mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes])
- unless ranges = HTTPUtils::parse_range_header(req['range'])
- raise HTTPStatus::BadRequest,
- "Unrecognized range-spec: \"#{req['range']}\""
- end
- File.open(filename, "rb"){|io|
- if ranges.size > 1
- time = Time.now
- boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
- parts = []
- ranges.each {|range|
- prange = prepare_range(range, filesize)
- next if prange[0] < 0
- parts.concat(prange)
- }
- raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty?
- res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
- if req.http_version < '1.1'
- res['connection'] = 'close'
- else
- res.chunked = true
- end
- res.body = multipart_body(io.dup, parts, boundary, mtype, filesize)
- elsif range = ranges[0]
- first, last = prepare_range(range, filesize)
- raise HTTPStatus::RequestRangeNotSatisfiable if first < 0
- res['content-type'] = mtype
- res['content-range'] = "bytes #{first}-#{last}/#{filesize}"
- res['content-length'] = (last - first + 1).to_s
- res.body = io.dup
- else
- raise HTTPStatus::BadRequest
- end
- }
- end
-
- def prepare_range(range, filesize)
- first = range.first < 0 ? filesize + range.first : range.first
- return -1, -1 if first < 0 || first >= filesize
- last = range.last < 0 ? filesize + range.last : range.last
- last = filesize - 1 if last >= filesize
- return first, last
- end
-
- # :startdoc:
- end
-
- ##
- # Serves a directory including fancy indexing and a variety of other
- # options.
- #
- # Example:
- #
- # server.mount('/assets', WEBrick::HTTPServlet::FileHandler,
- # '/path/to/assets')
-
- class FileHandler < AbstractServlet
- HandlerTable = Hash.new # :nodoc:
-
- ##
- # Allow custom handling of requests for files with +suffix+ by class
- # +handler+
-
- def self.add_handler(suffix, handler)
- HandlerTable[suffix] = handler
- end
-
- ##
- # Remove custom handling of requests for files with +suffix+
-
- def self.remove_handler(suffix)
- HandlerTable.delete(suffix)
- end
-
- ##
- # Creates a FileHandler servlet on +server+ that serves files starting
- # at directory +root+
- #
- # +options+ may be a Hash containing keys from
- # WEBrick::Config::FileHandler or +true+ or +false+.
- #
- # If +options+ is true or false then +:FancyIndexing+ is enabled or
- # disabled respectively.
-
- def initialize(server, root, options={}, default=Config::FileHandler)
- @config = server.config
- @logger = @config[:Logger]
- @root = File.expand_path(root)
- if options == true || options == false
- options = { :FancyIndexing => options }
- end
- @options = default.dup.update(options)
- end
-
- # :stopdoc:
-
- def service(req, res)
- # if this class is mounted on "/" and /~username is requested.
- # we're going to override path informations before invoking service.
- if defined?(Etc) && @options[:UserDir] && req.script_name.empty?
- if %r|^(/~([^/]+))| =~ req.path_info
- script_name, user = $1, $2
- path_info = $'
- begin
- passwd = Etc::getpwnam(user)
- @root = File::join(passwd.dir, @options[:UserDir])
- req.script_name = script_name
- req.path_info = path_info
- rescue
- @logger.debug "#{self.class}#do_GET: getpwnam(#{user}) failed"
- end
- end
- end
- prevent_directory_traversal(req, res)
- super(req, res)
- end
-
- def do_GET(req, res)
- unless exec_handler(req, res)
- set_dir_list(req, res)
- end
- end
-
- def do_POST(req, res)
- unless exec_handler(req, res)
- raise HTTPStatus::NotFound, "`#{req.path}' not found."
- end
- end
-
- def do_OPTIONS(req, res)
- unless exec_handler(req, res)
- super(req, res)
- end
- end
-
- # ToDo
- # RFC2518: HTTP Extensions for Distributed Authoring -- WEBDAV
- #
- # PROPFIND PROPPATCH MKCOL DELETE PUT COPY MOVE
- # LOCK UNLOCK
-
- # RFC3253: Versioning Extensions to WebDAV
- # (Web Distributed Authoring and Versioning)
- #
- # VERSION-CONTROL REPORT CHECKOUT CHECK_IN UNCHECKOUT
- # MKWORKSPACE UPDATE LABEL MERGE ACTIVITY
-
- private
-
- def trailing_pathsep?(path)
- # check for trailing path separator:
- # File.dirname("/aaaa/bbbb/") #=> "/aaaa")
- # File.dirname("/aaaa/bbbb/x") #=> "/aaaa/bbbb")
- # File.dirname("/aaaa/bbbb") #=> "/aaaa")
- # File.dirname("/aaaa/bbbbx") #=> "/aaaa")
- return File.dirname(path) != File.dirname(path+"x")
- end
-
- def prevent_directory_traversal(req, res)
- # Preventing directory traversal on Windows platforms;
- # Backslashes (0x5c) in path_info are not interpreted as special
- # character in URI notation. So the value of path_info should be
- # normalize before accessing to the filesystem.
-
- # dirty hack for filesystem encoding; in nature, File.expand_path
- # should not be used for path normalization. [Bug #3345]
- path = req.path_info.dup.force_encoding(Encoding.find("filesystem"))
- if trailing_pathsep?(req.path_info)
- # File.expand_path removes the trailing path separator.
- # Adding a character is a workaround to save it.
- # File.expand_path("/aaa/") #=> "/aaa"
- # File.expand_path("/aaa/" + "x") #=> "/aaa/x"
- expanded = File.expand_path(path + "x")
- expanded.chop! # remove trailing "x"
- else
- expanded = File.expand_path(path)
- end
- expanded.force_encoding(req.path_info.encoding)
- req.path_info = expanded
- end
-
- def exec_handler(req, res)
- raise HTTPStatus::NotFound, "`#{req.path}' not found" unless @root
- if set_filename(req, res)
- handler = get_handler(req, res)
- call_callback(:HandlerCallback, req, res)
- h = handler.get_instance(@config, res.filename)
- h.service(req, res)
- return true
- end
- call_callback(:HandlerCallback, req, res)
- return false
- end
-
- def get_handler(req, res)
- suffix1 = (/\.(\w+)\z/ =~ res.filename) && $1.downcase
- if /\.(\w+)\.([\w\-]+)\z/ =~ res.filename
- if @options[:AcceptableLanguages].include?($2.downcase)
- suffix2 = $1.downcase
- end
- end
- handler_table = @options[:HandlerTable]
- return handler_table[suffix1] || handler_table[suffix2] ||
- HandlerTable[suffix1] || HandlerTable[suffix2] ||
- DefaultFileHandler
- end
-
- def set_filename(req, res)
- res.filename = @root.dup
- path_info = req.path_info.scan(%r|/[^/]*|)
-
- path_info.unshift("") # dummy for checking @root dir
- while base = path_info.first
- break if base == "/"
- break unless File.directory?(File.expand_path(res.filename + base))
- shift_path_info(req, res, path_info)
- call_callback(:DirectoryCallback, req, res)
- end
-
- if base = path_info.first
- if base == "/"
- if file = search_index_file(req, res)
- shift_path_info(req, res, path_info, file)
- call_callback(:FileCallback, req, res)
- return true
- end
- shift_path_info(req, res, path_info)
- elsif file = search_file(req, res, base)
- shift_path_info(req, res, path_info, file)
- call_callback(:FileCallback, req, res)
- return true
- else
- raise HTTPStatus::NotFound, "`#{req.path}' not found."
- end
- end
-
- return false
- end
-
- def check_filename(req, res, name)
- if nondisclosure_name?(name) || windows_ambiguous_name?(name)
- @logger.warn("the request refers nondisclosure name `#{name}'.")
- raise HTTPStatus::NotFound, "`#{req.path}' not found."
- end
- end
-
- def shift_path_info(req, res, path_info, base=nil)
- tmp = path_info.shift
- base = base || tmp
- req.path_info = path_info.join
- req.script_name << base
- res.filename = File.expand_path(res.filename + base)
- check_filename(req, res, File.basename(res.filename))
- end
-
- def search_index_file(req, res)
- @config[:DirectoryIndex].each{|index|
- if file = search_file(req, res, "/"+index)
- return file
- end
- }
- return nil
- end
-
- def search_file(req, res, basename)
- langs = @options[:AcceptableLanguages]
- path = res.filename + basename
- if File.file?(path)
- return basename
- elsif langs.size > 0
- req.accept_language.each{|lang|
- path_with_lang = path + ".#{lang}"
- if langs.member?(lang) && File.file?(path_with_lang)
- return basename + ".#{lang}"
- end
- }
- (langs - req.accept_language).each{|lang|
- path_with_lang = path + ".#{lang}"
- if File.file?(path_with_lang)
- return basename + ".#{lang}"
- end
- }
- end
- return nil
- end
-
- def call_callback(callback_name, req, res)
- if cb = @options[callback_name]
- cb.call(req, res)
- end
- end
-
- def windows_ambiguous_name?(name)
- return true if /[. ]+\z/ =~ name
- return true if /::\$DATA\z/ =~ name
- return false
- end
-
- def nondisclosure_name?(name)
- @options[:NondisclosureName].each{|pattern|
- if File.fnmatch(pattern, name, File::FNM_CASEFOLD)
- return true
- end
- }
- return false
- end
-
- def set_dir_list(req, res)
- redirect_to_directory_uri(req, res)
- unless @options[:FancyIndexing]
- raise HTTPStatus::Forbidden, "no access permission to `#{req.path}'"
- end
- local_path = res.filename
- list = Dir::entries(local_path).collect{|name|
- next if name == "." || name == ".."
- next if nondisclosure_name?(name)
- next if windows_ambiguous_name?(name)
- st = (File::stat(File.join(local_path, name)) rescue nil)
- if st.nil?
- [ name, nil, -1 ]
- elsif st.directory?
- [ name + "/", st.mtime, -1 ]
- else
- [ name, st.mtime, st.size ]
- end
- }
- list.compact!
-
- query = req.query
-
- d0 = nil
- idx = nil
- %w[N M S].each_with_index do |q, i|
- if d = query.delete(q)
- idx ||= i
- d0 ||= d
- end
- end
- d0 ||= "A"
- idx ||= 0
- d1 = (d0 == "A") ? "D" : "A"
-
- if d0 == "A"
- list.sort!{|a,b| a[idx] <=> b[idx] }
- else
- list.sort!{|a,b| b[idx] <=> a[idx] }
- end
-
- namewidth = query["NameWidth"]
- if namewidth == "*"
- namewidth = nil
- elsif !namewidth or (namewidth = namewidth.to_i) < 2
- namewidth = 25
- end
- query = query.inject('') {|s, (k, v)| s << '&' << HTMLUtils::escape("#{k}=#{v}")}
-
- type = "text/html"
- case enc = Encoding.find('filesystem')
- when Encoding::US_ASCII, Encoding::ASCII_8BIT
- else
- type << "; charset=\"#{enc.name}\""
- end
- res['content-type'] = type
-
- title = "Index of #{HTMLUtils::escape(req.path)}"
- res.body = <<-_end_of_html_
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
-<HTML>
- <HEAD>
- <TITLE>#{title}</TITLE>
- <style type="text/css">
- <!--
- .name, .mtime { text-align: left; }
- .size { text-align: right; }
- td { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
- table { border-collapse: collapse; }
- tr th { border-bottom: 2px groove; }
- //-->
- </style>
- </HEAD>
- <BODY>
- <H1>#{title}</H1>
- _end_of_html_
-
- res.body << "<TABLE width=\"100%\"><THEAD><TR>\n"
- res.body << "<TH class=\"name\"><A HREF=\"?N=#{d1}#{query}\">Name</A></TH>"
- res.body << "<TH class=\"mtime\"><A HREF=\"?M=#{d1}#{query}\">Last modified</A></TH>"
- res.body << "<TH class=\"size\"><A HREF=\"?S=#{d1}#{query}\">Size</A></TH>\n"
- res.body << "</TR></THEAD>\n"
- res.body << "<TBODY>\n"
-
- query.sub!(/\A&/, '?')
- list.unshift [ "..", File::mtime(local_path+"/.."), -1 ]
- list.each{ |name, time, size|
- if name == ".."
- dname = "Parent Directory"
- elsif namewidth and name.size > namewidth
- dname = name[0...(namewidth - 2)] << '..'
- else
- dname = name
- end
- s = "<TR><TD class=\"name\"><A HREF=\"#{HTTPUtils::escape(name)}#{query if name.end_with?('/')}\">#{HTMLUtils::escape(dname)}</A></TD>"
- s << "<TD class=\"mtime\">" << (time ? time.strftime("%Y/%m/%d %H:%M") : "") << "</TD>"
- s << "<TD class=\"size\">" << (size >= 0 ? size.to_s : "-") << "</TD></TR>\n"
- res.body << s
- }
- res.body << "</TBODY></TABLE>"
- res.body << "<HR>"
-
- res.body << <<-_end_of_html_
- <ADDRESS>
- #{HTMLUtils::escape(@config[:ServerSoftware])}<BR>
- at #{req.host}:#{req.port}
- </ADDRESS>
- </BODY>
-</HTML>
- _end_of_html_
- end
-
- # :startdoc:
- end
- end
-end
diff --git a/lib/webrick/httputils.rb b/lib/webrick/httputils.rb
deleted file mode 100644
index 76d4bd0dc7..0000000000
--- a/lib/webrick/httputils.rb
+++ /dev/null
@@ -1,511 +0,0 @@
-# frozen_string_literal: false
-#
-# httputils.rb -- HTTPUtils Module
-#
-# Author: IPR -- Internet Programming with Ruby -- writers
-# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
-# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
-# reserved.
-#
-# $IPR: httputils.rb,v 1.34 2003/06/05 21:34:08 gotoyuzo Exp $
-
-require 'socket'
-require 'tempfile'
-
-module WEBrick
- CR = "\x0d" # :nodoc:
- LF = "\x0a" # :nodoc:
- CRLF = "\x0d\x0a" # :nodoc:
-
- ##
- # HTTPUtils provides utility methods for working with the HTTP protocol.
- #
- # This module is generally used internally by WEBrick
-
- module HTTPUtils
-
- ##
- # Normalizes a request path. Raises an exception if the path cannot be
- # normalized.
-
- def normalize_path(path)
- raise "abnormal path `#{path}'" if path[0] != ?/
- ret = path.dup
-
- ret.gsub!(%r{/+}o, '/') # // => /
- while ret.sub!(%r'/\.(?:/|\Z)', '/'); end # /. => /
- while ret.sub!(%r'/(?!\.\./)[^/]+/\.\.(?:/|\Z)', '/'); end # /foo/.. => /foo
-
- raise "abnormal path `#{path}'" if %r{/\.\.(/|\Z)} =~ ret
- ret
- end
- module_function :normalize_path
-
- ##
- # Default mime types
-
- DefaultMimeTypes = {
- "ai" => "application/postscript",
- "asc" => "text/plain",
- "avi" => "video/x-msvideo",
- "bin" => "application/octet-stream",
- "bmp" => "image/bmp",
- "class" => "application/octet-stream",
- "cer" => "application/pkix-cert",
- "crl" => "application/pkix-crl",
- "crt" => "application/x-x509-ca-cert",
- #"crl" => "application/x-pkcs7-crl",
- "css" => "text/css",
- "dms" => "application/octet-stream",
- "doc" => "application/msword",
- "dvi" => "application/x-dvi",
- "eps" => "application/postscript",
- "etx" => "text/x-setext",
- "exe" => "application/octet-stream",
- "gif" => "image/gif",
- "htm" => "text/html",
- "html" => "text/html",
- "jpe" => "image/jpeg",
- "jpeg" => "image/jpeg",
- "jpg" => "image/jpeg",
- "js" => "application/javascript",
- "json" => "application/json",
- "lha" => "application/octet-stream",
- "lzh" => "application/octet-stream",
- "mov" => "video/quicktime",
- "mpe" => "video/mpeg",
- "mpeg" => "video/mpeg",
- "mpg" => "video/mpeg",
- "pbm" => "image/x-portable-bitmap",
- "pdf" => "application/pdf",
- "pgm" => "image/x-portable-graymap",
- "png" => "image/png",
- "pnm" => "image/x-portable-anymap",
- "ppm" => "image/x-portable-pixmap",
- "ppt" => "application/vnd.ms-powerpoint",
- "ps" => "application/postscript",
- "qt" => "video/quicktime",
- "ras" => "image/x-cmu-raster",
- "rb" => "text/plain",
- "rd" => "text/plain",
- "rtf" => "application/rtf",
- "sgm" => "text/sgml",
- "sgml" => "text/sgml",
- "svg" => "image/svg+xml",
- "tif" => "image/tiff",
- "tiff" => "image/tiff",
- "txt" => "text/plain",
- "wasm" => "application/wasm",
- "xbm" => "image/x-xbitmap",
- "xhtml" => "text/html",
- "xls" => "application/vnd.ms-excel",
- "xml" => "text/xml",
- "xpm" => "image/x-xpixmap",
- "xwd" => "image/x-xwindowdump",
- "zip" => "application/zip",
- }
-
- ##
- # Loads Apache-compatible mime.types in +file+.
-
- def load_mime_types(file)
- # note: +file+ may be a "| command" for now; some people may
- # rely on this, but currently we do not use this method by default.
- open(file){ |io|
- hash = Hash.new
- io.each{ |line|
- next if /^#/ =~ line
- line.chomp!
- mimetype, ext0 = line.split(/\s+/, 2)
- next unless ext0
- next if ext0.empty?
- ext0.split(/\s+/).each{ |ext| hash[ext] = mimetype }
- }
- hash
- }
- end
- module_function :load_mime_types
-
- ##
- # Returns the mime type of +filename+ from the list in +mime_tab+. If no
- # mime type was found application/octet-stream is returned.
-
- def mime_type(filename, mime_tab)
- suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
- suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
- mime_tab[suffix1] || mime_tab[suffix2] || "application/octet-stream"
- end
- module_function :mime_type
-
- ##
- # Parses an HTTP header +raw+ into a hash of header fields with an Array
- # of values.
-
- def parse_header(raw)
- header = Hash.new([].freeze)
- field = nil
- raw.each_line{|line|
- case line
- when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):\s*(.*?)\s*\z/om
- field, value = $1, $2
- field.downcase!
- header[field] = [] unless header.has_key?(field)
- header[field] << value
- when /^\s+(.*?)\s*\z/om
- value = $1
- unless field
- raise HTTPStatus::BadRequest, "bad header '#{line}'."
- end
- header[field][-1] << " " << value
- else
- raise HTTPStatus::BadRequest, "bad header '#{line}'."
- end
- }
- header.each{|key, values|
- values.each(&:strip!)
- }
- header
- end
- module_function :parse_header
-
- ##
- # Splits a header value +str+ according to HTTP specification.
-
- def split_header_value(str)
- str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+)
- (?:,\s*|\Z)'xn).flatten
- end
- module_function :split_header_value
-
- ##
- # Parses a Range header value +ranges_specifier+
-
- def parse_range_header(ranges_specifier)
- if /^bytes=(.*)/ =~ ranges_specifier
- byte_range_set = split_header_value($1)
- byte_range_set.collect{|range_spec|
- case range_spec
- when /^(\d+)-(\d+)/ then $1.to_i .. $2.to_i
- when /^(\d+)-/ then $1.to_i .. -1
- when /^-(\d+)/ then -($1.to_i) .. -1
- else return nil
- end
- }
- end
- end
- module_function :parse_range_header
-
- ##
- # Parses q values in +value+ as used in Accept headers.
-
- def parse_qvalues(value)
- tmp = []
- if value
- parts = value.split(/,\s*/)
- parts.each {|part|
- if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
- val = m[1]
- q = (m[2] or 1).to_f
- tmp.push([val, q])
- end
- }
- tmp = tmp.sort_by{|val, q| -q}
- tmp.collect!{|val, q| val}
- end
- return tmp
- end
- module_function :parse_qvalues
-
- ##
- # Removes quotes and escapes from +str+
-
- def dequote(str)
- ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
- ret.gsub!(/\\(.)/, "\\1")
- ret
- end
- module_function :dequote
-
- ##
- # Quotes and escapes quotes in +str+
-
- def quote(str)
- '"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
- end
- module_function :quote
-
- ##
- # Stores multipart form data. FormData objects are created when
- # WEBrick::HTTPUtils.parse_form_data is called.
-
- class FormData < String
- EmptyRawHeader = [].freeze # :nodoc:
- EmptyHeader = {}.freeze # :nodoc:
-
- ##
- # The name of the form data part
-
- attr_accessor :name
-
- ##
- # The filename of the form data part
-
- attr_accessor :filename
-
- attr_accessor :next_data # :nodoc:
- protected :next_data
-
- ##
- # Creates a new FormData object.
- #
- # +args+ is an Array of form data entries. One FormData will be created
- # for each entry.
- #
- # This is called by WEBrick::HTTPUtils.parse_form_data for you
-
- def initialize(*args)
- @name = @filename = @next_data = nil
- if args.empty?
- @raw_header = []
- @header = nil
- super("")
- else
- @raw_header = EmptyRawHeader
- @header = EmptyHeader
- super(args.shift)
- unless args.empty?
- @next_data = self.class.new(*args)
- end
- end
- end
-
- ##
- # Retrieves the header at the first entry in +key+
-
- def [](*key)
- begin
- @header[key[0].downcase].join(", ")
- rescue StandardError, NameError
- super
- end
- end
-
- ##
- # Adds +str+ to this FormData which may be the body, a header or a
- # header entry.
- #
- # This is called by WEBrick::HTTPUtils.parse_form_data for you
-
- def <<(str)
- if @header
- super
- elsif str == CRLF
- @header = HTTPUtils::parse_header(@raw_header.join)
- if cd = self['content-disposition']
- if /\s+name="(.*?)"/ =~ cd then @name = $1 end
- if /\s+filename="(.*?)"/ =~ cd then @filename = $1 end
- end
- else
- @raw_header << str
- end
- self
- end
-
- ##
- # Adds +data+ at the end of the chain of entries
- #
- # This is called by WEBrick::HTTPUtils.parse_form_data for you.
-
- def append_data(data)
- tmp = self
- while tmp
- unless tmp.next_data
- tmp.next_data = data
- break
- end
- tmp = tmp.next_data
- end
- self
- end
-
- ##
- # Yields each entry in this FormData
-
- def each_data
- tmp = self
- while tmp
- next_data = tmp.next_data
- yield(tmp)
- tmp = next_data
- end
- end
-
- ##
- # Returns all the FormData as an Array
-
- def list
- ret = []
- each_data{|data|
- ret << data.to_s
- }
- ret
- end
-
- ##
- # A FormData will behave like an Array
-
- alias :to_ary :list
-
- ##
- # This FormData's body
-
- def to_s
- String.new(self)
- end
- end
-
- ##
- # Parses the query component of a URI in +str+
-
- def parse_query(str)
- query = Hash.new
- if str
- str.split(/[&;]/).each{|x|
- next if x.empty?
- key, val = x.split(/=/,2)
- key = unescape_form(key)
- val = unescape_form(val.to_s)
- val = FormData.new(val)
- val.name = key
- if query.has_key?(key)
- query[key].append_data(val)
- next
- end
- query[key] = val
- }
- end
- query
- end
- module_function :parse_query
-
- ##
- # Parses form data in +io+ with the given +boundary+
-
- def parse_form_data(io, boundary)
- boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/
- form_data = Hash.new
- return form_data unless io
- data = nil
- io.each_line{|line|
- if boundary_regexp =~ line
- if data
- data.chop!
- key = data.name
- if form_data.has_key?(key)
- form_data[key].append_data(data)
- else
- form_data[key] = data
- end
- end
- data = FormData.new
- next
- else
- if data
- data << line
- end
- end
- }
- return form_data
- end
- module_function :parse_form_data
-
- #####
-
- reserved = ';/?:@&=+$,'
- num = '0123456789'
- lowalpha = 'abcdefghijklmnopqrstuvwxyz'
- upalpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
- mark = '-_.!~*\'()'
- unreserved = num + lowalpha + upalpha + mark
- control = (0x0..0x1f).collect{|c| c.chr }.join + "\x7f"
- space = " "
- delims = '<>#%"'
- unwise = '{}|\\^[]`'
- nonascii = (0x80..0xff).collect{|c| c.chr }.join
-
- module_function
-
- # :stopdoc:
-
- def _make_regex(str) /([#{Regexp.escape(str)}])/n end
- def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end
- def _escape(str, regex)
- str = str.b
- str.gsub!(regex) {"%%%02X" % $1.ord}
- # %-escaped string should contain US-ASCII only
- str.force_encoding(Encoding::US_ASCII)
- end
- def _unescape(str, regex)
- str = str.b
- str.gsub!(regex) {$1.hex.chr}
- # encoding of %-unescaped string is unknown
- str
- end
-
- UNESCAPED = _make_regex(control+space+delims+unwise+nonascii)
- UNESCAPED_FORM = _make_regex(reserved+control+delims+unwise+nonascii)
- NONASCII = _make_regex(nonascii)
- ESCAPED = /%([0-9a-fA-F]{2})/
- UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,")
-
- # :startdoc:
-
- ##
- # Escapes HTTP reserved and unwise characters in +str+
-
- def escape(str)
- _escape(str, UNESCAPED)
- end
-
- ##
- # Unescapes HTTP reserved and unwise characters in +str+
-
- def unescape(str)
- _unescape(str, ESCAPED)
- end
-
- ##
- # Escapes form reserved characters in +str+
-
- def escape_form(str)
- ret = _escape(str, UNESCAPED_FORM)
- ret.gsub!(/ /, "+")
- ret
- end
-
- ##
- # Unescapes form reserved characters in +str+
-
- def unescape_form(str)
- _unescape(str.gsub(/\+/, " "), ESCAPED)
- end
-
- ##
- # Escapes path +str+
-
- def escape_path(str)
- result = ""
- str.scan(%r{/([^/]*)}).each{|i|
- result << "/" << _escape(i[0], UNESCAPED_PCHAR)
- }
- return result
- end
-
- ##
- # Escapes 8 bit characters in +str+
-
- def escape8bit(str)
- _escape(str, NONASCII)
- end
- end
-end
diff --git a/lib/webrick/server.rb b/lib/webrick/server.rb
deleted file mode 100644
index 4a6e74c4f9..0000000000
--- a/lib/webrick/server.rb
+++ /dev/null
@@ -1,378 +0,0 @@
-# frozen_string_literal: false
-#
-# server.rb -- GenericServer Class
-#
-# Author: IPR -- Internet Programming with Ruby -- writers
-# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
-# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
-# reserved.
-#
-# $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $
-
-require 'socket'
-require_relative 'config'
-require_relative 'log'
-
-module WEBrick
-
- ##
- # Server error exception
-
- class ServerError < StandardError; end
-
- ##
- # Base server class
-
- class SimpleServer
-
- ##
- # A SimpleServer only yields when you start it
-
- def SimpleServer.start
- yield
- end
- end
-
- ##
- # A generic module for daemonizing a process
-
- class Daemon
-
- ##
- # Performs the standard operations for daemonizing a process. Runs a
- # block, if given.
-
- def Daemon.start
- Process.daemon
- File.umask(0)
- yield if block_given?
- end
- end
-
- ##
- # Base TCP server class. You must subclass GenericServer and provide a #run
- # method.
-
- class GenericServer
-
- ##
- # The server status. One of :Stop, :Running or :Shutdown
-
- attr_reader :status
-
- ##
- # The server configuration
-
- attr_reader :config
-
- ##
- # The server logger. This is independent from the HTTP access log.
-
- attr_reader :logger
-
- ##
- # Tokens control the number of outstanding clients. The
- # <code>:MaxClients</code> configuration sets this.
-
- attr_reader :tokens
-
- ##
- # Sockets listening for connections.
-
- attr_reader :listeners
-
- ##
- # Creates a new generic server from +config+. The default configuration
- # comes from +default+.
-
- def initialize(config={}, default=Config::General)
- @config = default.dup.update(config)
- @status = :Stop
- @config[:Logger] ||= Log::new
- @logger = @config[:Logger]
-
- @tokens = Thread::SizedQueue.new(@config[:MaxClients])
- @config[:MaxClients].times{ @tokens.push(nil) }
-
- webrickv = WEBrick::VERSION
- rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
- @logger.info("WEBrick #{webrickv}")
- @logger.info("ruby #{rubyv}")
-
- @listeners = []
- @shutdown_pipe = nil
- unless @config[:DoNotListen]
- if @config[:Listen]
- warn(":Listen option is deprecated; use GenericServer#listen", uplevel: 1)
- end
- listen(@config[:BindAddress], @config[:Port])
- if @config[:Port] == 0
- @config[:Port] = @listeners[0].addr[1]
- end
- end
- end
-
- ##
- # Retrieves +key+ from the configuration
-
- def [](key)
- @config[key]
- end
-
- ##
- # Adds listeners from +address+ and +port+ to the server. See
- # WEBrick::Utils::create_listeners for details.
-
- def listen(address, port)
- @listeners += Utils::create_listeners(address, port)
- end
-
- ##
- # Starts the server and runs the +block+ for each connection. This method
- # does not return until the server is stopped from a signal handler or
- # another thread using #stop or #shutdown.
- #
- # If the block raises a subclass of StandardError the exception is logged
- # and ignored. If an IOError or Errno::EBADF exception is raised the
- # exception is ignored. If an Exception subclass is raised the exception
- # is logged and re-raised which stops the server.
- #
- # To completely shut down a server call #shutdown from ensure:
- #
- # server = WEBrick::GenericServer.new
- # # or WEBrick::HTTPServer.new
- #
- # begin
- # server.start
- # ensure
- # server.shutdown
- # end
-
- def start(&block)
- raise ServerError, "already started." if @status != :Stop
- server_type = @config[:ServerType] || SimpleServer
-
- setup_shutdown_pipe
-
- server_type.start{
- @logger.info \
- "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
- @status = :Running
- call_callback(:StartCallback)
-
- shutdown_pipe = @shutdown_pipe
-
- thgroup = ThreadGroup.new
- begin
- while @status == :Running
- begin
- sp = shutdown_pipe[0]
- if svrs = IO.select([sp, *@listeners])
- if svrs[0].include? sp
- # swallow shutdown pipe
- buf = String.new
- nil while String ===
- sp.read_nonblock([sp.nread, 8].max, buf, exception: false)
- break
- end
- svrs[0].each{|svr|
- @tokens.pop # blocks while no token is there.
- if sock = accept_client(svr)
- unless config[:DoNotReverseLookup].nil?
- sock.do_not_reverse_lookup = !!config[:DoNotReverseLookup]
- end
- th = start_thread(sock, &block)
- th[:WEBrickThread] = true
- thgroup.add(th)
- else
- @tokens.push(nil)
- end
- }
- end
- rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex
- # if the listening socket was closed in GenericServer#shutdown,
- # IO::select raise it.
- rescue StandardError => ex
- msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
- @logger.error msg
- rescue Exception => ex
- @logger.fatal ex
- raise
- end
- end
- ensure
- cleanup_shutdown_pipe(shutdown_pipe)
- cleanup_listener
- @status = :Shutdown
- @logger.info "going to shutdown ..."
- thgroup.list.each{|th| th.join if th[:WEBrickThread] }
- call_callback(:StopCallback)
- @logger.info "#{self.class}#start done."
- @status = :Stop
- end
- }
- end
-
- ##
- # Stops the server from accepting new connections.
-
- def stop
- if @status == :Running
- @status = :Shutdown
- end
-
- alarm_shutdown_pipe {|f| f.write_nonblock("\0")}
- end
-
- ##
- # Shuts down the server and all listening sockets. New listeners must be
- # provided to restart the server.
-
- def shutdown
- stop
-
- alarm_shutdown_pipe(&:close)
- end
-
- ##
- # You must subclass GenericServer and implement \#run which accepts a TCP
- # client socket
-
- def run(sock)
- @logger.fatal "run() must be provided by user."
- end
-
- private
-
- # :stopdoc:
-
- ##
- # Accepts a TCP client socket from the TCP server socket +svr+ and returns
- # the client socket.
-
- def accept_client(svr)
- case sock = svr.to_io.accept_nonblock(exception: false)
- when :wait_readable
- nil
- else
- if svr.respond_to?(:start_immediately)
- sock = OpenSSL::SSL::SSLSocket.new(sock, ssl_context)
- sock.sync_close = true
- # we cannot do OpenSSL::SSL::SSLSocket#accept here because
- # a slow client can prevent us from accepting connections
- # from other clients
- end
- sock
- end
- rescue Errno::ECONNRESET, Errno::ECONNABORTED,
- Errno::EPROTO, Errno::EINVAL
- nil
- rescue StandardError => ex
- msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
- @logger.error msg
- nil
- end
-
- ##
- # Starts a server thread for the client socket +sock+ that runs the given
- # +block+.
- #
- # Sets the socket to the <code>:WEBrickSocket</code> thread local variable
- # in the thread.
- #
- # If any errors occur in the block they are logged and handled.
-
- def start_thread(sock, &block)
- Thread.start{
- begin
- Thread.current[:WEBrickSocket] = sock
- begin
- addr = sock.peeraddr
- @logger.debug "accept: #{addr[3]}:#{addr[1]}"
- rescue SocketError
- @logger.debug "accept: <address unknown>"
- raise
- end
- if sock.respond_to?(:sync_close=) && @config[:SSLStartImmediately]
- WEBrick::Utils.timeout(@config[:RequestTimeout]) do
- begin
- sock.accept # OpenSSL::SSL::SSLSocket#accept
- rescue Errno::ECONNRESET, Errno::ECONNABORTED,
- Errno::EPROTO, Errno::EINVAL
- Thread.exit
- end
- end
- end
- call_callback(:AcceptCallback, sock)
- block ? block.call(sock) : run(sock)
- rescue Errno::ENOTCONN
- @logger.debug "Errno::ENOTCONN raised"
- rescue ServerError => ex
- msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
- @logger.error msg
- rescue Exception => ex
- @logger.error ex
- ensure
- @tokens.push(nil)
- Thread.current[:WEBrickSocket] = nil
- if addr
- @logger.debug "close: #{addr[3]}:#{addr[1]}"
- else
- @logger.debug "close: <address unknown>"
- end
- sock.close
- end
- }
- end
-
- ##
- # Calls the callback +callback_name+ from the configuration with +args+
-
- def call_callback(callback_name, *args)
- @config[callback_name]&.call(*args)
- end
-
- def setup_shutdown_pipe
- return @shutdown_pipe ||= IO.pipe
- end
-
- def cleanup_shutdown_pipe(shutdown_pipe)
- @shutdown_pipe = nil
- shutdown_pipe&.each(&:close)
- end
-
- def alarm_shutdown_pipe
- _, pipe = @shutdown_pipe # another thread may modify @shutdown_pipe.
- if pipe
- if !pipe.closed?
- begin
- yield pipe
- rescue IOError # closed by another thread.
- end
- end
- end
- end
-
- def cleanup_listener
- @listeners.each{|s|
- if @logger.debug?
- addr = s.addr
- @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
- end
- begin
- s.shutdown
- rescue Errno::ENOTCONN
- # when `Errno::ENOTCONN: Socket is not connected' on some platforms,
- # call #close instead of #shutdown.
- # (ignore @config[:ShutdownSocketWithoutClose])
- s.close
- else
- unless @config[:ShutdownSocketWithoutClose]
- s.close
- end
- end
- }
- @listeners.clear
- end
- end # end of GenericServer
-end
diff --git a/lib/webrick/ssl.rb b/lib/webrick/ssl.rb
deleted file mode 100644
index d125083528..0000000000
--- a/lib/webrick/ssl.rb
+++ /dev/null
@@ -1,215 +0,0 @@
-# frozen_string_literal: false
-#
-# ssl.rb -- SSL/TLS enhancement for GenericServer
-#
-# Copyright (c) 2003 GOTOU Yuuzou All rights reserved.
-#
-# $Id$
-
-require 'webrick'
-require 'openssl'
-
-module WEBrick
- module Config
- svrsoft = General[:ServerSoftware]
- osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
-
- ##
- # Default SSL server configuration.
- #
- # WEBrick can automatically create a self-signed certificate if
- # <code>:SSLCertName</code> is set. For more information on the various
- # SSL options see OpenSSL::SSL::SSLContext.
- #
- # :ServerSoftware ::
- # The server software name used in the Server: header.
- # :SSLEnable :: false,
- # Enable SSL for this server. Defaults to false.
- # :SSLCertificate ::
- # The SSL certificate for the server.
- # :SSLPrivateKey ::
- # The SSL private key for the server certificate.
- # :SSLClientCA :: nil,
- # Array of certificates that will be sent to the client.
- # :SSLExtraChainCert :: nil,
- # Array of certificates that will be added to the certificate chain
- # :SSLCACertificateFile :: nil,
- # Path to a CA certificate file
- # :SSLCACertificatePath :: nil,
- # Path to a directory containing CA certificates
- # :SSLCertificateStore :: nil,
- # OpenSSL::X509::Store used for certificate validation of the client
- # :SSLTmpDhCallback :: nil,
- # Callback invoked when DH parameters are required.
- # :SSLVerifyClient ::
- # Sets whether the client is verified. This defaults to VERIFY_NONE
- # which is typical for an HTTPS server.
- # :SSLVerifyDepth ::
- # Number of CA certificates to walk when verifying a certificate chain
- # :SSLVerifyCallback ::
- # Custom certificate verification callback
- # :SSLServerNameCallback::
- # Custom servername indication callback
- # :SSLTimeout ::
- # Maximum session lifetime
- # :SSLOptions ::
- # Various SSL options
- # :SSLCiphers ::
- # Ciphers to be used
- # :SSLStartImmediately ::
- # Immediately start SSL upon connection? Defaults to true
- # :SSLCertName ::
- # SSL certificate name. Must be set to enable automatic certificate
- # creation.
- # :SSLCertComment ::
- # Comment used during automatic certificate creation.
-
- SSL = {
- :ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}",
- :SSLEnable => false,
- :SSLCertificate => nil,
- :SSLPrivateKey => nil,
- :SSLClientCA => nil,
- :SSLExtraChainCert => nil,
- :SSLCACertificateFile => nil,
- :SSLCACertificatePath => nil,
- :SSLCertificateStore => nil,
- :SSLTmpDhCallback => nil,
- :SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
- :SSLVerifyDepth => nil,
- :SSLVerifyCallback => nil, # custom verification
- :SSLTimeout => nil,
- :SSLOptions => nil,
- :SSLCiphers => nil,
- :SSLStartImmediately => true,
- # Must specify if you use auto generated certificate.
- :SSLCertName => nil,
- :SSLCertComment => "Generated by Ruby/OpenSSL"
- }
- General.update(SSL)
- end
-
- module Utils
- ##
- # Creates a self-signed certificate with the given number of +bits+,
- # the issuer +cn+ and a +comment+ to be stored in the certificate.
-
- def create_self_signed_cert(bits, cn, comment)
- rsa = OpenSSL::PKey::RSA.new(bits){|p, n|
- case p
- when 0; $stderr.putc "." # BN_generate_prime
- when 1; $stderr.putc "+" # BN_generate_prime
- when 2; $stderr.putc "*" # searching good prime,
- # n = #of try,
- # but also data from BN_generate_prime
- when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
- # but also data from BN_generate_prime
- else; $stderr.putc "*" # BN_generate_prime
- end
- }
- cert = OpenSSL::X509::Certificate.new
- cert.version = 2
- cert.serial = 1
- name = (cn.kind_of? String) ? OpenSSL::X509::Name.parse(cn)
- : OpenSSL::X509::Name.new(cn)
- cert.subject = name
- cert.issuer = name
- cert.not_before = Time.now
- cert.not_after = Time.now + (365*24*60*60)
- cert.public_key = rsa.public_key
-
- ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
- ef.issuer_certificate = cert
- cert.extensions = [
- ef.create_extension("basicConstraints","CA:FALSE"),
- ef.create_extension("keyUsage", "keyEncipherment"),
- ef.create_extension("subjectKeyIdentifier", "hash"),
- ef.create_extension("extendedKeyUsage", "serverAuth"),
- ef.create_extension("nsComment", comment),
- ]
- aki = ef.create_extension("authorityKeyIdentifier",
- "keyid:always,issuer:always")
- cert.add_extension(aki)
- cert.sign(rsa, OpenSSL::Digest::SHA256.new)
-
- return [ cert, rsa ]
- end
- module_function :create_self_signed_cert
- end
-
- ##
- #--
- # Updates WEBrick::GenericServer with SSL functionality
-
- class GenericServer
-
- ##
- # SSL context for the server when run in SSL mode
-
- def ssl_context # :nodoc:
- @ssl_context ||= begin
- if @config[:SSLEnable]
- ssl_context = setup_ssl_context(@config)
- @logger.info("\n" + @config[:SSLCertificate].to_text)
- ssl_context
- end
- end
- end
-
- undef listen
-
- ##
- # Updates +listen+ to enable SSL when the SSL configuration is active.
-
- def listen(address, port) # :nodoc:
- listeners = Utils::create_listeners(address, port)
- if @config[:SSLEnable]
- listeners.collect!{|svr|
- ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context)
- ssvr.start_immediately = @config[:SSLStartImmediately]
- ssvr
- }
- end
- @listeners += listeners
- setup_shutdown_pipe
- end
-
- ##
- # Sets up an SSL context for +config+
-
- def setup_ssl_context(config) # :nodoc:
- unless config[:SSLCertificate]
- cn = config[:SSLCertName]
- comment = config[:SSLCertComment]
- cert, key = Utils::create_self_signed_cert(2048, cn, comment)
- config[:SSLCertificate] = cert
- config[:SSLPrivateKey] = key
- end
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.key = config[:SSLPrivateKey]
- ctx.cert = config[:SSLCertificate]
- ctx.client_ca = config[:SSLClientCA]
- ctx.extra_chain_cert = config[:SSLExtraChainCert]
- ctx.ca_file = config[:SSLCACertificateFile]
- ctx.ca_path = config[:SSLCACertificatePath]
- ctx.cert_store = config[:SSLCertificateStore]
- ctx.tmp_dh_callback = config[:SSLTmpDhCallback]
- ctx.verify_mode = config[:SSLVerifyClient]
- ctx.verify_depth = config[:SSLVerifyDepth]
- ctx.verify_callback = config[:SSLVerifyCallback]
- ctx.servername_cb = config[:SSLServerNameCallback] || proc { |args| ssl_servername_callback(*args) }
- ctx.timeout = config[:SSLTimeout]
- ctx.options = config[:SSLOptions]
- ctx.ciphers = config[:SSLCiphers]
- ctx
- end
-
- ##
- # ServerNameIndication callback
-
- def ssl_servername_callback(sslsocket, hostname = nil)
- # default
- end
-
- end
-end
diff --git a/lib/webrick/utils.rb b/lib/webrick/utils.rb
deleted file mode 100644
index 07044876b9..0000000000
--- a/lib/webrick/utils.rb
+++ /dev/null
@@ -1,270 +0,0 @@
-# frozen_string_literal: false
-#
-# utils.rb -- Miscellaneous utilities
-#
-# Author: IPR -- Internet Programming with Ruby -- writers
-# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
-# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
-# reserved.
-#
-# $IPR: utils.rb,v 1.10 2003/02/16 22:22:54 gotoyuzo Exp $
-
-require 'socket'
-require 'io/nonblock'
-require 'etc'
-
-module WEBrick
- module Utils
- ##
- # Sets IO operations on +io+ to be non-blocking
- def set_non_blocking(io)
- io.nonblock = true if io.respond_to?(:nonblock=)
- end
- module_function :set_non_blocking
-
- ##
- # Sets the close on exec flag for +io+
- def set_close_on_exec(io)
- io.close_on_exec = true if io.respond_to?(:close_on_exec=)
- end
- module_function :set_close_on_exec
-
- ##
- # Changes the process's uid and gid to the ones of +user+
- def su(user)
- if pw = Etc.getpwnam(user)
- Process::initgroups(user, pw.gid)
- Process::Sys::setgid(pw.gid)
- Process::Sys::setuid(pw.uid)
- else
- warn("WEBrick::Utils::su doesn't work on this platform", uplevel: 1)
- end
- end
- module_function :su
-
- ##
- # The server hostname
- def getservername
- host = Socket::gethostname
- begin
- Socket::gethostbyname(host)[0]
- rescue
- host
- end
- end
- module_function :getservername
-
- ##
- # Creates TCP server sockets bound to +address+:+port+ and returns them.
- #
- # It will create IPV4 and IPV6 sockets on all interfaces.
- def create_listeners(address, port)
- unless port
- raise ArgumentError, "must specify port"
- end
- sockets = Socket.tcp_server_sockets(address, port)
- sockets = sockets.map {|s|
- s.autoclose = false
- ts = TCPServer.for_fd(s.fileno)
- s.close
- ts
- }
- return sockets
- end
- module_function :create_listeners
-
- ##
- # Characters used to generate random strings
- RAND_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
- "0123456789" +
- "abcdefghijklmnopqrstuvwxyz"
-
- ##
- # Generates a random string of length +len+
- def random_string(len)
- rand_max = RAND_CHARS.bytesize
- ret = ""
- len.times{ ret << RAND_CHARS[rand(rand_max)] }
- ret
- end
- module_function :random_string
-
- ###########
-
- require "timeout"
- require "singleton"
-
- ##
- # Class used to manage timeout handlers across multiple threads.
- #
- # Timeout handlers should be managed by using the class methods which are
- # synchronized.
- #
- # id = TimeoutHandler.register(10, Timeout::Error)
- # begin
- # sleep 20
- # puts 'foo'
- # ensure
- # TimeoutHandler.cancel(id)
- # end
- #
- # will raise Timeout::Error
- #
- # id = TimeoutHandler.register(10, Timeout::Error)
- # begin
- # sleep 5
- # puts 'foo'
- # ensure
- # TimeoutHandler.cancel(id)
- # end
- #
- # will print 'foo'
- #
- class TimeoutHandler
- include Singleton
-
- ##
- # Mutex used to synchronize access across threads
- TimeoutMutex = Thread::Mutex.new # :nodoc:
-
- ##
- # Registers a new timeout handler
- #
- # +time+:: Timeout in seconds
- # +exception+:: Exception to raise when timeout elapsed
- def TimeoutHandler.register(seconds, exception)
- at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + seconds
- instance.register(Thread.current, at, exception)
- end
-
- ##
- # Cancels the timeout handler +id+
- def TimeoutHandler.cancel(id)
- instance.cancel(Thread.current, id)
- end
-
- def self.terminate
- instance.terminate
- end
-
- ##
- # Creates a new TimeoutHandler. You should use ::register and ::cancel
- # instead of creating the timeout handler directly.
- def initialize
- TimeoutMutex.synchronize{
- @timeout_info = Hash.new
- }
- @queue = Thread::Queue.new
- @watcher = nil
- end
-
- # :nodoc:
- private \
- def watch
- to_interrupt = []
- while true
- now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- wakeup = nil
- to_interrupt.clear
- TimeoutMutex.synchronize{
- @timeout_info.each {|thread, ary|
- next unless ary
- ary.each{|info|
- time, exception = *info
- if time < now
- to_interrupt.push [thread, info.object_id, exception]
- elsif !wakeup || time < wakeup
- wakeup = time
- end
- }
- }
- }
- to_interrupt.each {|arg| interrupt(*arg)}
- if !wakeup
- @queue.pop
- elsif (wakeup -= now) > 0
- begin
- (th = Thread.start {@queue.pop}).join(wakeup)
- ensure
- th&.kill&.join
- end
- end
- @queue.clear
- end
- end
-
- # :nodoc:
- private \
- def watcher
- (w = @watcher)&.alive? and return w # usual case
- TimeoutMutex.synchronize{
- (w = @watcher)&.alive? and next w # pathological check
- @watcher = Thread.start(&method(:watch))
- }
- end
-
- ##
- # Interrupts the timeout handler +id+ and raises +exception+
- def interrupt(thread, id, exception)
- if cancel(thread, id) && thread.alive?
- thread.raise(exception, "execution timeout")
- end
- end
-
- ##
- # Registers a new timeout handler
- #
- # +time+:: Timeout in seconds
- # +exception+:: Exception to raise when timeout elapsed
- def register(thread, time, exception)
- info = nil
- TimeoutMutex.synchronize{
- (@timeout_info[thread] ||= []) << (info = [time, exception])
- }
- @queue.push nil
- watcher
- return info.object_id
- end
-
- ##
- # Cancels the timeout handler +id+
- def cancel(thread, id)
- TimeoutMutex.synchronize{
- if ary = @timeout_info[thread]
- ary.delete_if{|info| info.object_id == id }
- if ary.empty?
- @timeout_info.delete(thread)
- end
- return true
- end
- return false
- }
- end
-
- ##
- def terminate
- TimeoutMutex.synchronize{
- @timeout_info.clear
- @watcher&.kill&.join
- }
- end
- end
-
- ##
- # Executes the passed block and raises +exception+ if execution takes more
- # than +seconds+.
- #
- # If +seconds+ is zero or nil, simply executes the block
- def timeout(seconds, exception=Timeout::Error)
- return yield if seconds.nil? or seconds.zero?
- # raise ThreadError, "timeout within critical session" if Thread.critical
- id = TimeoutHandler.register(seconds, exception)
- begin
- yield(seconds)
- ensure
- TimeoutHandler.cancel(id)
- end
- end
- module_function :timeout
- end
-end
diff --git a/lib/webrick/version.rb b/lib/webrick/version.rb
deleted file mode 100644
index 7bcdd5b943..0000000000
--- a/lib/webrick/version.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: false
-#--
-# version.rb -- version and release date
-#
-# Author: IPR -- Internet Programming with Ruby -- writers
-# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU
-# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
-# reserved.
-#
-# $IPR: version.rb,v 1.74 2003/07/22 19:20:43 gotoyuzo Exp $
-
-module WEBrick
-
- ##
- # The WEBrick version
-
- VERSION = "1.6.1"
-end
diff --git a/lib/webrick/webrick.gemspec b/lib/webrick/webrick.gemspec
deleted file mode 100644
index 5490502539..0000000000
--- a/lib/webrick/webrick.gemspec
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-begin
- require_relative 'lib/webrick/version'
-rescue LoadError
- # for Ruby core repository
- require_relative 'version'
-end
-
-Gem::Specification.new do |s|
- s.name = "webrick"
- s.version = WEBrick::VERSION
- s.summary = "HTTP server toolkit"
- s.description = "WEBrick is an HTTP server toolkit that can be configured as an HTTPS server, a proxy server, and a virtual-host server."
-
- s.require_path = %w{lib}
- s.files = [
- "Gemfile",
- "LICENSE.txt",
- "README.md",
- "Rakefile",
- "bin/console",
- "bin/setup",
- "lib/webrick.rb",
- "lib/webrick/accesslog.rb",
- "lib/webrick/cgi.rb",
- "lib/webrick/compat.rb",
- "lib/webrick/config.rb",
- "lib/webrick/cookie.rb",
- "lib/webrick/htmlutils.rb",
- "lib/webrick/httpauth.rb",
- "lib/webrick/httpauth/authenticator.rb",
- "lib/webrick/httpauth/basicauth.rb",
- "lib/webrick/httpauth/digestauth.rb",
- "lib/webrick/httpauth/htdigest.rb",
- "lib/webrick/httpauth/htgroup.rb",
- "lib/webrick/httpauth/htpasswd.rb",
- "lib/webrick/httpauth/userdb.rb",
- "lib/webrick/httpproxy.rb",
- "lib/webrick/httprequest.rb",
- "lib/webrick/httpresponse.rb",
- "lib/webrick/https.rb",
- "lib/webrick/httpserver.rb",
- "lib/webrick/httpservlet.rb",
- "lib/webrick/httpservlet/abstract.rb",
- "lib/webrick/httpservlet/cgi_runner.rb",
- "lib/webrick/httpservlet/cgihandler.rb",
- "lib/webrick/httpservlet/erbhandler.rb",
- "lib/webrick/httpservlet/filehandler.rb",
- "lib/webrick/httpservlet/prochandler.rb",
- "lib/webrick/httpstatus.rb",
- "lib/webrick/httputils.rb",
- "lib/webrick/httpversion.rb",
- "lib/webrick/log.rb",
- "lib/webrick/server.rb",
- "lib/webrick/ssl.rb",
- "lib/webrick/utils.rb",
- "lib/webrick/version.rb",
- "webrick.gemspec",
- ]
- s.required_ruby_version = ">= 2.3.0"
-
- s.authors = ["TAKAHASHI Masayoshi", "GOTOU YUUZOU", "Eric Wong"]
- s.email = [nil, nil, 'normal@ruby-lang.org']
- s.homepage = "https://www.ruby-lang.org"
- s.license = "BSD-2-Clause"
-
- if s.respond_to?(:metadata=)
- s.metadata = {
- "bug_tracker_uri" => "https://bugs.ruby-lang.org/projects/ruby-trunk/issues",
- "homepage_uri" => "https://www.ruby-lang.org",
- "source_code_uri" => "https://git.ruby-lang.org/ruby.git/"
- }
- end
-
- s.add_development_dependency "rake"
-end
diff --git a/lib/yaml.rb b/lib/yaml.rb
index cec7808f05..17b27e802f 100644
--- a/lib/yaml.rb
+++ b/lib/yaml.rb
@@ -40,7 +40,7 @@ YAML = Psych # :nodoc:
#
# == History
#
-# Syck was the original for YAML implementation in Ruby's standard library
+# Syck was the original YAML implementation in Ruby's standard library
# developed by why the lucky stiff.
#
# You can still use Syck, if you prefer, for parsing and emitting YAML, but you
diff --git a/lib/yaml/yaml.gemspec b/lib/yaml/yaml.gemspec
index ba5027a9b6..cf19b0e0da 100644
--- a/lib/yaml/yaml.gemspec
+++ b/lib/yaml/yaml.gemspec
@@ -1,13 +1,13 @@
Gem::Specification.new do |spec|
spec.name = "yaml"
- spec.version = "0.1.0"
+ spec.version = "0.1.1"
spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"]
spec.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org"]
spec.summary = "YAML Ain't Markup Language"
spec.description = spec.summary
spec.homepage = "https://github.com/ruby/yaml"
- spec.license = "BSD-2-Clause"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/libexec/bundle b/libexec/bundle
index b3b1b691d8..1168e5a361 100755
--- a/libexec/bundle
+++ b/libexec/bundle
@@ -15,6 +15,9 @@ else
require "bundler"
end
+# Workaround for non-activated bundler spec due to missing https://github.com/rubygems/rubygems/commit/4e306d7bcdee924b8d80ca9db6125aa59ee4e5a3
+gem "bundler", Bundler::VERSION if Gem.rubygems_version < Gem::Version.new("2.6.2")
+
# Check if an older version of bundler is installed
$LOAD_PATH.each do |path|
next unless path =~ %r{/bundler-0\.(\d+)} && $1.to_i < 9
diff --git a/libexec/erb b/libexec/erb
new file mode 100755
index 0000000000..ded76991dc
--- /dev/null
+++ b/libexec/erb
@@ -0,0 +1,174 @@
+#!/usr/bin/env ruby
+# Tiny eRuby --- ERB2
+# Copyright (c) 1999-2000,2002 Masatoshi SEKI
+# You can redistribute it and/or modify it under the same terms as Ruby.
+
+require 'erb'
+
+class ERB
+ module Main
+ def ARGV.switch
+ return nil if self.empty?
+ arg = self.shift
+ return nil if arg == '--'
+ case arg
+ when /\A-(.)(.*)/
+ if $1 == '-'
+ arg, @maybe_arg = arg.split(/=/, 2)
+ return arg
+ end
+ raise 'unknown switch "-"' if $2[0] == ?- and $1 != 'T'
+ if $2.size > 0
+ self.unshift "-#{$2}"
+ @maybe_arg = $2
+ else
+ @maybe_arg = nil
+ end
+ "-#{$1}"
+ when /\A(\w+)=/
+ arg
+ else
+ self.unshift arg
+ nil
+ end
+ end
+
+ def ARGV.req_arg
+ (@maybe_arg || self.shift || raise('missing argument')).tap {
+ @maybe_arg = nil
+ }
+ end
+
+ def trim_mode_opt(trim_mode, disable_percent)
+ return trim_mode if disable_percent
+ case trim_mode
+ when 0
+ return '%'
+ when 1
+ return '%>'
+ when 2
+ return '%<>'
+ when '-'
+ return '%-'
+ end
+ end
+ module_function :trim_mode_opt
+
+ def run(factory=ERB)
+ trim_mode = 0
+ disable_percent = false
+ variables = {}
+ begin
+ while switch = ARGV.switch
+ case switch
+ when '-x' # ruby source
+ output = true
+ when '-n' # line number
+ number = true
+ when '-v' # verbose
+ $VERBOSE = true
+ when '--version' # version
+ STDERR.puts factory.version
+ exit
+ when '-d', '--debug' # debug
+ $DEBUG = true
+ when '-r' # require
+ require ARGV.req_arg
+ when '-S' # security level
+ warn 'warning: -S option of erb command is deprecated. Please do not use this.'
+ arg = ARGV.req_arg
+ raise "invalid safe_level #{arg.dump}" unless arg =~ /\A[0-1]\z/
+ safe_level = arg.to_i
+ when '-T' # trim mode
+ arg = ARGV.req_arg
+ if arg == '-'
+ trim_mode = arg
+ next
+ end
+ raise "invalid trim mode #{arg.dump}" unless arg =~ /\A[0-2]\z/
+ trim_mode = arg.to_i
+ when '-E', '--encoding'
+ arg = ARGV.req_arg
+ set_encoding(*arg.split(/:/, 2))
+ when '-U'
+ set_encoding(Encoding::UTF_8, Encoding::UTF_8)
+ when '-P'
+ disable_percent = true
+ when '--help'
+ raise "print this help"
+ when /\A-/
+ 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]"
+ 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
+EOU
+ exit 1
+ end
+
+ $<.set_encoding(Encoding::UTF_8, nil)
+ src = $<.read
+ filename = $FILENAME
+ exit 2 unless src
+ trim = trim_mode_opt(trim_mode, disable_percent)
+ if safe_level.nil?
+ erb = factory.new(src, trim_mode: trim)
+ else
+ # [deprecated] This will be removed at Ruby 2.7.
+ erb = factory.new(src, safe_level, trim_mode: trim)
+ end
+ erb.filename = filename
+ if output
+ if number
+ erb.src.each_line.with_index do |line, l|
+ puts "%3d %s"%[l+1, line]
+ end
+ else
+ puts erb.src
+ end
+ else
+ bind = TOPLEVEL_BINDING
+ if variables
+ enc = erb.encoding
+ for var, val in variables do
+ val = val.encode(enc) if val
+ bind.local_variable_set(var, val)
+ end
+ end
+ erb.run(bind)
+ end
+ end
+ module_function :run
+
+ def set_encoding(extern, intern = nil)
+ verbose, $VERBOSE = $VERBOSE, nil
+ Encoding.default_external = extern unless extern.nil? || extern == ""
+ Encoding.default_internal = intern unless intern.nil? || intern == ""
+ [$stdin, $stdout, $stderr].each do |io|
+ io.set_encoding(extern, intern)
+ end
+ ensure
+ $VERBOSE = verbose
+ end
+ module_function :set_encoding
+ class << self; private :set_encoding; end
+ end
+end
+
+ERB::Main.run
diff --git a/libexec/racc b/libexec/racc
index 5656b25e42..4507d04962 100755
--- a/libexec/racc
+++ b/libexec/racc
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby
#
-# $Id$
+#
#
# Copyright (c) 1999-2006 Minero Aoki
#
@@ -51,7 +51,7 @@ def main
logfilename = path
}
parser.on('-e', '--executable [RUBYPATH]', 'Makes executable parser.') {|path|
- executable = true
+ make_executable = true
rubypath = (path == 'ruby' ? nil : path)
}
parser.on('-E', '--embedded', "Embeds Racc runtime in output.") {
@@ -71,10 +71,6 @@ def main
'Uses CLASSNAME instead of Racc::Parser.') {|name|
superclass = name
}
- parser.on('--runtime=FEATURE',
- "Uses FEATURE instead of 'racc/parser'") {|feat|
- runtime = feature
- }
parser.on('-C', '--check-only', 'Checks syntax and quit immediately.') {|fl|
check_only = fl
}
@@ -88,24 +84,21 @@ def main
debug_flags = Racc::DebugFlags.parse_option_string(flags)
}
#parser.on('--no-extensions', 'Run Racc without any Ruby extension.') {
- # Racc.const_set :Racc_No_Extentions, true
+ # Racc.const_set :Racc_No_Extensions, true
#}
parser.on('--version', 'Prints version and quit.') {
puts "racc version #{Racc::Version}"
exit 0
}
parser.on('--runtime-version', 'Prints runtime version and quit.') {
- printf "racc runtime version %s (rev. %s); %s\n",
+ printf "racc runtime version %s; %s\n",
Racc::Parser::Racc_Runtime_Version,
- Racc::Parser::Racc_Runtime_Revision,
if Racc::Parser.racc_runtime_type == 'ruby'
- sprintf('ruby core version %s (rev. %s)',
- Racc::Parser::Racc_Runtime_Core_Version_R,
- Racc::Parser::Racc_Runtime_Core_Revision_R)
+ sprintf('ruby core version %s',
+ Racc::Parser::Racc_Runtime_Core_Version_R)
else
- sprintf('c core version %s (rev. %s)',
- Racc::Parser::Racc_Runtime_Core_Version_C,
- Racc::Parser::Racc_Runtime_Core_Revision_C)
+ sprintf('c core version %s',
+ Racc::Parser::Racc_Runtime_Core_Version_C)
end
exit 0
}
@@ -187,8 +180,12 @@ def main
log_useless states.grammar
log_conflict states
else
- report_useless states.grammar
- report_conflict states
+ has_useless = report_useless states.grammar
+ has_conflicts = report_conflict states
+ if has_useless || has_conflicts
+ preamble = make_logfile ? 'C' : 'Turn on logging with "-v" and c'
+ $stderr.puts %Q{#{preamble}heck ".output" file for details}
+ end
end
profiler.report
@@ -204,13 +201,29 @@ def make_filename(path, suffix)
path.sub(/(?:\..*?)?\z/, suffix)
end
+LIST_LIMIT = 10
+def report_list(enum, label)
+ c = enum.count
+ if c > 0
+ $stderr.puts "#{c} #{label}:"
+ enum.first(LIST_LIMIT).each do |item|
+ $stderr.puts " #{yield item}"
+ end
+ $stderr.puts " ..." if c > LIST_LIMIT
+ end
+end
+
+# @return [Boolean] if anything was reported
def report_conflict(states)
if states.should_report_srconflict?
+ reported = true
$stderr.puts "#{states.n_srconflicts} shift/reduce conflicts"
end
if states.rrconflict_exist?
+ reported = true
$stderr.puts "#{states.n_rrconflicts} reduce/reduce conflicts"
end
+ reported
end
def log_conflict(states)
@@ -225,16 +238,17 @@ def log_conflict(states)
}
end
+# @return [Boolean] if anything was reported
def report_useless(grammar)
- if grammar.useless_nonterminal_exist?
- $stderr.puts "#{grammar.n_useless_nonterminals} useless nonterminals"
- end
- if grammar.useless_rule_exist?
- $stderr.puts "#{grammar.n_useless_rules} useless rules"
- end
+ reported = report_list(grammar.each_useless_nonterminal, 'useless nonterminals', &:to_s)
+
+ reported ||= report_list(grammar.each_useless_rule, 'useless rules') { |r| "##{r.ident} (#{r.target})" }
+
if grammar.start.useless?
$stderr.puts 'fatal: start symbol does not derive any sentence'
+ reported = true
end
+ reported
end
def log_useless(grammar)
diff --git a/libexec/racc2y b/libexec/racc2y
deleted file mode 100755
index f88d73ed2c..0000000000
--- a/libexec/racc2y
+++ /dev/null
@@ -1,195 +0,0 @@
-#!/usr/local/bin/ruby
-#
-# $Id$
-#
-# Copyright (c) 1999-2006 Minero Aoki
-#
-# This program is feee software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-# For details of the LGPL, see the file "COPYING".
-#
-
-require 'racc/grammarfileparser'
-require 'racc/info'
-require 'optparse'
-
-def main
- @with_action = true
- with_header = false
- with_inner = false
- with_footer = false
- output = nil
- parser = OptionParser.new
- parser.banner = "Usage: #{File.basename($0)} [-AHIF] [-oFILENAME] GRAMMARFILE"
- parser.on('-o', '--output=FILENAME', 'output file name [<input>.yacc]') {|name|
- output = name
- }
- parser.on('-A', '--without-action', 'Does not include actions.') {
- @with_action = false
- }
- parser.on('-H', '--with-header', 'Includes header part.') {
- with_header = true
- }
- parser.on('-I', '--with-inner', 'Includes inner part.') {
- with_inner = true
- }
- parser.on('-F', '--with-footer', 'Includes footer part.') {
- with_footer = true
- }
- parser.on('--version', 'Prints version and quit.') {
- puts "racc2y version #{Racc::Version}"
- exit 0
- }
- parser.on('--copyright', 'Prints copyright and quit.') {
- puts Racc::Copyright
- exit 0
- }
- parser.on('--help', 'Prints this message and quit.') {
- puts parser.help
- exit 1
- }
- begin
- parser.parse!
- rescue OptionParser::ParseError => err
- $stderr.puts err.message
- $stderr.puts parser.help
- exit 1
- end
- if ARGV.empty?
- $stderr.puts "no input file"
- exit 1
- end
- unless ARGV.size == 1
- $stderr.puts "too many inputs"
- exit 1
- end
- input = ARGV[0]
-
- begin
- result = Racc::GrammarFileParser.parse_file(input)
- result.grammar.init
- File.open(output || "#{input}.yacc", 'w') {|f|
- f.puts "/* generated from #{input} */"
- if with_header
- f.puts
- f.puts '%{'
- print_user_codes f, result.params.header
- f.puts '%}'
- end
- f.puts
- print_terminals f, result.grammar
- f.puts
- print_precedence_table f, precedence_table(result.grammar)
- f.puts
- f.puts '%%'
- print_grammar f, result.grammar
- f.puts '%%'
- if with_inner
- f.puts '/*---- inner ----*/'
- print_user_codes f, result.params.inner
- end
- if with_footer
- f.puts '/*---- footer ----*/'
- print_user_codes f, result.params.footer
- end
- }
- rescue SystemCallError => err
- $stderr.puts err.message
- exit 1
- end
-end
-
-def print_terminals(f, grammar)
- init_indent = '%token'.size
- f.print '%token'
- columns = init_indent
- grammar.symboltable.each_terminal do |t|
- next unless t.terminal?
- next if t.dummy?
- next if t == grammar.symboltable.anchor
- next if t == grammar.symboltable.error
- unless t.value.kind_of?(String)
- if columns > 60
- f.puts
- f.print ' ' * init_indent
- columns = init_indent
- end
- columns += f.write(" #{yacc_symbol(t)}")
- end
- end
- f.puts
-end
-
-def precedence_table(grammar)
- table = []
- grammar.symboltable.select {|sym| sym.precedence }.each do |sym|
- (table[sym.prec] ||= [sym.assoc]).push sym
- end
- table.compact
-end
-
-def print_precedence_table(f, table)
- return if table.empty?
- f.puts '/* precedance table */'
- table.each do |syms|
- assoc = syms.shift
- f.printf '%%%-8s ', assoc.to_s.downcase
- f.puts syms.map {|s| yacc_symbol(s) }.join(' ')
- end
- f.puts
-end
-
-def print_grammar(f, grammar)
- prev_target = nil
- indent = 10
- embactions = []
- grammar.each do |rule|
- if rule.target.dummy?
- embactions.push rule.action unless rule.action.empty?
- next
- end
- if rule.target == prev_target
- f.print ' ' * indent, '|'
- else
- prev_target = rule.target
- f.printf "\n%-10s:", yacc_symbol(prev_target)
- end
- rule.symbols.each do |s|
- if s.dummy? # target of dummy rule for embedded action
- f.puts
- print_action f, embactions.shift, indent
- f.print ' ' * (indent + 1)
- else
- f.print ' ', yacc_symbol(s)
- end
- end
- if rule.specified_prec
- f.print ' %prec ', yacc_symbol(rule.specified_prec)
- end
- f.puts
- unless rule.action.empty?
- print_action f, rule.action, indent
- end
- end
-end
-
-def print_action(f, action, indent)
- return unless @with_action
- f.print ' ' * (indent + 4), "{\n"
- f.print ' ' * (indent + 6), action.source.text.strip, "\n"
- f.print ' ' * (indent + 4) , "}\n"
-end
-
-def print_user_codes(f, srcs)
- return if srcs.empty?
- srcs.each do |src|
- f.puts src.text
- end
-end
-
-def yacc_symbol(s)
- s.to_s.gsub('"', "'")
-end
-
-main
diff --git a/libexec/y2racc b/libexec/y2racc
deleted file mode 100755
index 7933f94153..0000000000
--- a/libexec/y2racc
+++ /dev/null
@@ -1,339 +0,0 @@
-#!/usr/local/bin/ruby
-#
-# $Id$
-#
-# Copyright (c) 1999-2006 Minero Aoki
-#
-# This program is free software.
-# You can distribute/modify this program under the terms of
-# the GNU LGPL, Lesser General Public License version 2.1.
-# For details of the GNU LGPL, see the file "COPYING".
-#
-
-require 'racc/info'
-require 'strscan'
-require 'forwardable'
-require 'optparse'
-
-def main
- @with_action = true
- @with_header = false
- @with_usercode = false
- cname = 'MyParser'
- input = nil
- output = nil
- parser = OptionParser.new
- parser.banner = "Usage: #{File.basename($0)} [-Ahu] [-c <classname>] [-o <filename>] <input>"
- parser.on('-o', '--output=FILENAME', 'output file name [<input>.racc]') {|name|
- output = name
- }
- parser.on('-c', '--classname=NAME', "Name of the parser class. [#{cname}]") {|name|
- cname = name
- }
- parser.on('-A', '--without-action', 'Does not include actions.') {
- @with_action = false
- }
- parser.on('-h', '--with-header', 'Includes header (%{...%}).') {
- @with_header = true
- }
- parser.on('-u', '--with-user-code', 'Includes user code.') {
- @with_usercode = true
- }
- parser.on('--version', 'Prints version and quit.') {
- puts "y2racc version #{Racc::Version}"
- exit 0
- }
- parser.on('--copyright', 'Prints copyright and quit.') {
- puts Racc::Copyright
- exit 0
- }
- parser.on('--help', 'Prints this message and quit.') {
- puts parser.help
- exit 1
- }
- begin
- parser.parse!
- rescue OptionParser::ParseError => err
- $stderr.puts err.message
- $stderr.puts parser.help
- exit 1
- end
- if ARGV.empty?
- $stderr.puts 'no input'
- exit 1
- end
- if ARGV.size > 1
- $stderr.puts 'too many input'
- exit 1
- end
- input = ARGV[0]
-
- begin
- result = YaccFileParser.parse_file(input)
- File.open(output || "#{input}.racc", 'w') {|f|
- convert cname, result, f
- }
- rescue SystemCallError => err
- $stderr.puts err.message
- exit 1
- end
-end
-
-def convert(classname, result, f)
- init_indent = 'token'.size
- f.puts %<# Converted from "#{result.filename}" by y2racc version #{Racc::Version}>
- f.puts
- f.puts "class #{classname}"
- unless result.terminals.empty?
- f.puts
- f.print 'token'
- columns = init_indent
- result.terminals.each do |t|
- if columns > 60
- f.puts
- f.print ' ' * init_indent
- columns = init_indent
- end
- columns += f.write(" #{t}")
- end
- f.puts
- end
- unless result.precedence_table.empty?
- f.puts
- f.puts 'preclow'
- result.precedence_table.each do |assoc, toks|
- f.printf " %-8s %s\n", assoc, toks.join(' ') unless toks.empty?
- end
- f.puts 'prechigh'
- end
- if result.start
- f.puts
- f.puts "start #{@start}"
- end
-
- f.puts
- f.puts 'rule'
- texts = @with_action ? result.grammar : result.grammar_without_actions
- texts.each do |text|
- f.print text
- end
-
- if @with_header and result.header
- f.puts
- f.puts '---- header'
- f.puts result.header
- end
- if @with_usercode and result.usercode
- f.puts
- f.puts '---- footer'
- f.puts result.usercode
- end
-end
-
-class ParseError < StandardError; end
-
-class StringScanner_withlineno
- def initialize(src)
- @s = StringScanner.new(src)
- @lineno = 1
- end
-
- extend Forwardable
- def_delegator "@s", :eos?
- def_delegator "@s", :rest
-
- attr_reader :lineno
-
- def scan(re)
- advance_lineno(@s.scan(re))
- end
-
- def scan_until(re)
- advance_lineno(@s.scan_until(re))
- end
-
- def skip(re)
- str = advance_lineno(@s.scan(re))
- str ? str.size : nil
- end
-
- def getch
- advance_lineno(@s.getch)
- end
-
- private
-
- def advance_lineno(str)
- @lineno += str.count("\n") if str
- str
- end
-end
-
-class YaccFileParser
-
- Result = Struct.new(:terminals, :precedence_table, :start,
- :header, :grammar, :usercode, :filename)
- class Result # reopen
- def initialize
- super
- self.terminals = []
- self.precedence_table = []
- self.start = nil
- self.grammar = []
- self.header = nil
- self.usercode = nil
- self.filename = nil
- end
-
- def grammar_without_actions
- grammar().map {|text| text[0,1] == '{' ? '{}' : text }
- end
- end
-
- def YaccFileParser.parse_file(filename)
- new().parse(File.read(filename), filename)
- end
-
- def parse(src, filename = '-')
- @result = Result.new
- @filename = filename
- @result.filename = filename
- s = StringScanner_withlineno.new(src)
- parse_header s
- parse_grammar s
- @result
- end
-
- private
-
- COMMENT = %r</\*[^*]*\*+(?:[^/*][^*]*\*+)*/>
- CHAR = /'((?:[^'\\]+|\\.)*)'/
- STRING = /"((?:[^"\\]+|\\.)*)"/
-
- def parse_header(s)
- skip_until_percent s
- until s.eos?
- case
- when t = s.scan(/left/)
- @result.precedence_table.push ['left', scan_symbols(s)]
- when t = s.scan(/right/)
- @result.precedence_table.push ['right', scan_symbols(s)]
- when t = s.scan(/nonassoc/)
- @result.precedence_table.push ['nonassoc', scan_symbols(s)]
- when t = s.scan(/token/)
- list = scan_symbols(s)
- list.shift if /\A<(.*)>\z/ =~ list[0]
- @result.terminals.concat list
- when t = s.scan(/start/)
- @result.start = scan_symbols(s)[0]
- when s.skip(%r<(?:
- type | union | expect | thong | binary |
- semantic_parser | pure_parser | no_lines |
- raw | token_table
- )\b>x)
- skip_until_percent s
- when s.skip(/\{/) # header (%{...%})
- str = s.scan_until(/\%\}/)
- str.chop!
- str.chop!
- @result.header = str
- skip_until_percent s
- when s.skip(/\%/) # grammar (%%...)
- return
- else
- raise ParseError, "#{@filename}:#{s.lineno}: scan error"
- end
- end
- end
-
- def skip_until_percent(s)
- until s.eos?
- s.skip /[^\%\/]+/
- next if s.skip(COMMENT)
- return if s.getch == '%'
- end
- end
-
- def scan_symbols(s)
- list = []
- until s.eos?
- s.skip /\s+/
- if s.skip(COMMENT)
- ;
- elsif t = s.scan(CHAR)
- list.push t
- elsif t = s.scan(STRING)
- list.push t
- elsif s.skip(/\%/)
- break
- elsif t = s.scan(/\S+/)
- list.push t
- else
- raise ParseError, "#{@filename}:#{@lineno}: scan error"
- end
- end
- list
- end
-
- def parse_grammar(s)
- buf = []
- until s.eos?
- if t = s.scan(/[^%'"{\/]+/)
- buf.push t
- break if s.eos?
- end
- if s.skip(/\{/)
- buf.push scan_action(s)
- elsif t = s.scan(/'(?:[^'\\]+|\\.)*'/) then buf.push t
- elsif t = s.scan(/"(?:[^"\\]+|\\.)*"/) then buf.push t
- elsif t = s.scan(COMMENT) then buf.push t
- elsif s.skip(/%prec\b/) then buf.push '='
- elsif s.skip(/%%/)
- @result.usercode = s.rest
- break
- else
- buf.push s.getch
- end
- end
- @result.grammar = buf
- end
-
- def scan_action(s)
- buf = '{'
- nest = 1
- until s.eos?
- if t = s.scan(%r<[^/{}'"]+>)
- buf << t
- break if s.eos?
- elsif t = s.scan(COMMENT)
- buf << t
- elsif t = s.scan(CHAR)
- buf << t
- elsif t = s.scan(STRING)
- buf << t
- else
- c = s.getch
- buf << c
- case c
- when '{'
- nest += 1
- when '}'
- nest -= 1
- return buf if nest == 0
- end
- end
- end
- $stderr.puts "warning: unterminated action in #{@filename}"
- buf
- end
-
-end
-
-unless Object.method_defined?(:funcall)
- class Object
- alias funcall __send__
- end
-end
-
-
-main
diff --git a/load.c b/load.c
index 51c21ee4f2..3dcc40bbe9 100644
--- a/load.c
+++ b/load.c
@@ -2,13 +2,20 @@
* load methods from eval.c
*/
-#include "ruby/encoding.h"
-#include "ruby/util.h"
-#include "internal.h"
#include "dln.h"
#include "eval_intern.h"
-#include "probes.h"
+#include "internal.h"
+#include "internal/dir.h"
+#include "internal/error.h"
+#include "internal/file.h"
+#include "internal/load.h"
+#include "internal/parse.h"
+#include "internal/thread.h"
+#include "internal/variable.h"
#include "iseq.h"
+#include "probes.h"
+#include "ruby/encoding.h"
+#include "ruby/util.h"
static VALUE ruby_dln_librefs;
@@ -516,9 +523,7 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
}
if (st_get_key(loading_tbl, (st_data_t)feature, &data)) {
if (fn) *fn = (const char*)data;
- loading:
- if (!ext) return 'u';
- return !IS_RBEXT(ext) ? 's' : 'r';
+ goto loading;
}
else {
VALUE bufstr;
@@ -550,6 +555,10 @@ rb_feature_p(const char *feature, const char *ext, int rb, int expanded, const c
rb_str_resize(bufstr, 0);
}
return 0;
+
+ loading:
+ if (!ext) return 'u';
+ return !IS_RBEXT(ext) ? 's' : 'r';
}
int
@@ -715,14 +724,30 @@ rb_load_protect(VALUE fname, int wrap, int *pstate)
* call-seq:
* load(filename, wrap=false) -> true
*
- * Loads and executes the Ruby
- * program in the file _filename_. If the filename does not
- * resolve to an absolute path, the file is searched for in the library
- * directories listed in <code>$:</code>. If the optional _wrap_
- * parameter is +true+, the loaded script will be executed
- * under an anonymous module, protecting the calling program's global
- * namespace. In no circumstance will any local variables in the loaded
- * file be propagated to the loading environment.
+ * Loads and executes the Ruby program in the file _filename_.
+ *
+ * If the filename is an absolute path (e.g. starts with '/'), the file
+ * will be loaded directly using the absolute path.
+ *
+ * If the filename is an explicit relative path (e.g. starts with './' or
+ * '../'), the file will be loaded using the relative path from the current
+ * directory.
+ *
+ * Otherwise, the file will be searched for in the library
+ * directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
+ * If the file is found in a directory, it will attempt to load the file
+ * relative to that directory. If the file is not found in any of the
+ * directories in <code>$LOAD_PATH</code>, the file will be loaded using
+ * the relative path from the current directory.
+ *
+ * If the file doesn't exist when there is an attempt to load it, a
+ * LoadError will be raised.
+ *
+ * If the optional _wrap_ parameter is +true+, the loaded script will
+ * be executed under an anonymous module, protecting the calling
+ * program's global namespace. In no circumstance will any local
+ * variables in the loaded file be propagated to the loading
+ * environment.
*/
static VALUE
@@ -820,8 +845,10 @@ load_unlock(const char *ftptr, int done)
* Loads the given +name+, returning +true+ if successful and +false+ if the
* feature is already loaded.
*
- * If the filename does not resolve to an absolute path, it will be searched
- * for in the directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
+ * If the filename neither resolves to an absolute path nor starts with
+ * './' or '../', the file will be searched for in the library
+ * directories listed in <code>$LOAD_PATH</code> (<code>$:</code>).
+ * If the filename starts with './' or '../', resolution is based on Dir.pwd.
*
* If the filename has the extension ".rb", it is loaded as a source file; if
* the extension is ".so", ".o", or ".dll", or the default shared library
@@ -953,9 +980,7 @@ search_required(VALUE fname, volatile VALUE *path, feature_func rb_feature_p)
default:
if (ft) {
- statically_linked:
- if (loading) *path = rb_filesystem_str_new_cstr(loading);
- return ft;
+ goto statically_linked;
}
/* fall through */
case 1:
@@ -965,6 +990,10 @@ search_required(VALUE fname, volatile VALUE *path, feature_func rb_feature_p)
*path = tmp;
}
return type ? 's' : 'r';
+
+ statically_linked:
+ if (loading) *path = rb_filesystem_str_new_cstr(loading);
+ return ft;
}
static void
@@ -1012,6 +1041,25 @@ rb_resolve_feature_path(VALUE klass, VALUE fname)
return rb_ary_new_from_args(2, sym, path);
}
+static void
+ext_config_push(rb_thread_t *th, struct rb_ext_config *prev)
+{
+ *prev = th->ext_config;
+ th->ext_config = (struct rb_ext_config){0};
+}
+
+static void
+ext_config_pop(rb_thread_t *th, struct rb_ext_config *prev)
+{
+ th->ext_config = *prev;
+}
+
+void
+rb_ext_ractor_safe(bool flag)
+{
+ GET_THREAD()->ext_config.ractor_safe = flag;
+}
+
/*
* returns
* 0: if already loaded (false)
@@ -1030,6 +1078,8 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
enum ruby_tag_type state;
char *volatile ftptr = 0;
VALUE path;
+ volatile bool reset_ext_config = false;
+ struct rb_ext_config prev_ext_config;
fname = rb_get_path(fname);
path = rb_str_encode_ospath(fname);
@@ -1060,6 +1110,8 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
break;
case 's':
+ reset_ext_config = true;
+ ext_config_push(th, &prev_ext_config);
handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
path, VM_BLOCK_HANDLER_NONE, path);
rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
@@ -1070,9 +1122,12 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
}
}
EC_POP_TAG();
- th = rb_ec_thread_ptr(ec);
- th->top_self = self;
- th->top_wrapper = wrapper;
+
+ rb_thread_t *th2 = rb_ec_thread_ptr(ec);
+ th2->top_self = self;
+ th2->top_wrapper = wrapper;
+ if (reset_ext_config) ext_config_pop(th2, &prev_ext_config);
+
if (ftptr) load_unlock(RSTRING_PTR(path), !state);
if (state) {
@@ -1125,23 +1180,6 @@ ruby_require_internal(const char *fname, unsigned int len)
}
VALUE
-rb_require_safe(VALUE fname, int safe)
-{
- rb_warn("rb_require_safe will be removed in Ruby 3.0");
- rb_execution_context_t *ec = GET_EC();
- int result = require_internal(ec, fname, 1);
-
- if (result > TAG_RETURN) {
- EC_JUMP_TAG(ec, result);
- }
- if (result < 0) {
- load_failed(fname);
- }
-
- return result ? Qtrue : Qfalse;
-}
-
-VALUE
rb_require_string(VALUE fname)
{
rb_execution_context_t *ec = GET_EC();
@@ -1266,7 +1304,7 @@ static VALUE
rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
{
VALUE klass = rb_class_real(rb_vm_cbase());
- if (NIL_P(klass)) {
+ if (!klass) {
rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
}
return rb_mod_autoload(klass, sym, file);
@@ -1297,15 +1335,13 @@ rb_f_autoload_p(int argc, VALUE *argv, VALUE obj)
void
Init_load(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern2((str), strlen(str))
rb_vm_t *vm = GET_VM();
static const char var_load_path[] = "$:";
ID id_load_path = rb_intern2(var_load_path, sizeof(var_load_path)-1);
rb_define_hooked_variable(var_load_path, (VALUE*)vm, load_path_getter, rb_gvar_readonly_setter);
- rb_alias_variable(rb_intern("$-I"), id_load_path);
- rb_alias_variable(rb_intern("$LOAD_PATH"), id_load_path);
+ rb_alias_variable(rb_intern_const("$-I"), id_load_path);
+ rb_alias_variable(rb_intern_const("$LOAD_PATH"), id_load_path);
vm->load_path = rb_ary_new();
vm->expanded_load_path = rb_ary_tmp_new(0);
vm->load_path_snapshot = rb_ary_tmp_new(0);
diff --git a/localeinit.c b/localeinit.c
index bec29a6d46..bbcbac832e 100644
--- a/localeinit.c
+++ b/localeinit.c
@@ -123,8 +123,9 @@ Init_enc_set_filesystem_encoding(void)
idx = ENCINDEX_US_ASCII;
#elif defined _WIN32
char cp[SIZEOF_CP_NAME];
- const UINT codepage = ruby_w32_codepage[1] ? ruby_w32_codepage[1] :
- AreFileApisANSI() ? GetACP() : GetOEMCP();
+ const UINT codepage = ruby_w32_codepage[1];
+ if (!codepage) return ENCINDEX_UTF_8;
+ /* for debugging */
CP_FORMAT(cp, codepage);
idx = rb_enc_find_index(cp);
if (idx < 0) idx = ENCINDEX_ASCII;
diff --git a/man/bundle-add.1 b/man/bundle-add.1
deleted file mode 100644
index 8b75859104..0000000000
--- a/man/bundle-add.1
+++ /dev/null
@@ -1,66 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-ADD" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install
-.
-.SH "SYNOPSIS"
-\fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-git=GIT] [\-\-branch=BRANCH] [\-\-skip\-install] [\-\-strict] [\-\-optimistic]
-.
-.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"
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-version\fR, \fB\-v\fR
-Specify version requirements(s) for the added gem\.
-.
-.TP
-\fB\-\-group\fR, \fB\-g\fR
-Specify the group(s) for the added gem\. Multiple groups should be separated by commas\.
-.
-.TP
-\fB\-\-source\fR, , \fB\-s\fR
-Specify the source for the added gem\.
-.
-.TP
-\fB\-\-git\fR
-Specify the git source for the added gem\.
-.
-.TP
-\fB\-\-branch\fR
-Specify the git branch for the added gem\.
-.
-.TP
-\fB\-\-skip\-install\fR
-Adds the gem to the Gemfile but does not install it\.
-.
-.TP
-\fB\-\-optimistic\fR
-Adds optimistic declaration of version
-.
-.TP
-\fB\-\-strict\fR
-Adds strict declaration of version
-
diff --git a/man/bundle-add.1.txt b/man/bundle-add.1.txt
deleted file mode 100644
index dcd76df4ae..0000000000
--- a/man/bundle-add.1.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-BUNDLE-ADD(1) BUNDLE-ADD(1)
-
-
-
-NAME
- bundle-add - Add gem to the Gemfile and run bundle install
-
-SYNOPSIS
- bundle add GEM_NAME [--group=GROUP] [--version=VERSION]
- [--source=SOURCE] [--git=GIT] [--branch=BRANCH] [--skip-install]
- [--strict] [--optimistic]
-
-DESCRIPTION
- Adds the named gem to the Gemfile and run bundle install. bundle
- install can be avoided by using the flag --skip-install.
-
- Example:
-
- bundle add rails
-
- bundle add rails --version "< 3.0, > 1.1"
-
- bundle add rails --version "~> 5.0.0" --source "https://gems.exam-
- ple.com" --group "development"
-
- bundle add rails --skip-install
-
- bundle add rails --group "development, test"
-
-OPTIONS
- --version, -v
- Specify version requirements(s) for the added gem.
-
- --group, -g
- Specify the group(s) for the added gem. Multiple groups should
- be separated by commas.
-
- --source, , -s
- Specify the source for the added gem.
-
- --git Specify the git source for the added gem.
-
- --branch
- Specify the git branch for the added gem.
-
- --skip-install
- Adds the gem to the Gemfile but does not install it.
-
- --optimistic
- Adds optimistic declaration of version
-
- --strict
- Adds strict declaration of version
-
-
-
-
- January 2020 BUNDLE-ADD(1)
diff --git a/man/bundle-binstubs.1 b/man/bundle-binstubs.1
deleted file mode 100644
index 4f9e5c0e31..0000000000
--- a/man/bundle-binstubs.1
+++ /dev/null
@@ -1,40 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-BINSTUBS" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
-.
-.SH "SYNOPSIS"
-\fBbundle binstubs\fR \fIGEM_NAME\fR [\-\-force] [\-\-path PATH] [\-\-standalone]
-.
-.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\.
-.
-.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
-Specify a different shebang executable name than the default (default \'ruby\')
-.
-.SH "BUNDLE INSTALL \-\-BINSTUBS"
-To create binstubs for all the gems in the bundle you can use the \fB\-\-binstubs\fR flag in bundle install(1) \fIbundle\-install\.1\.html\fR\.
diff --git a/man/bundle-binstubs.1.txt b/man/bundle-binstubs.1.txt
deleted file mode 100644
index cbd2b12da0..0000000000
--- a/man/bundle-binstubs.1.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-BUNDLE-BINSTUBS(1) BUNDLE-BINSTUBS(1)
-
-
-
-NAME
- bundle-binstubs - Install the binstubs of the listed gems
-
-SYNOPSIS
- bundle binstubs GEM_NAME [--force] [--path PATH] [--standalone]
-
-DESCRIPTION
- Binstubs are scripts that wrap around executables. Bundler creates a
- small Ruby file (a binstub) that loads Bundler, runs the command, and
- puts it into bin/. Binstubs are a shortcut-or alternative- to always
- using bundle exec. This gives you a file that can be run directly, and
- one that will always run the correct gem version used by the applica-
- tion.
-
- For example, if you run bundle binstubs rspec-core, Bundler will create
- the file bin/rspec. That file will contain enough code to load Bundler,
- tell it to load the bundled gems, and then run rspec.
-
- This command generates binstubs for executables in GEM_NAME. Binstubs
- are put into bin, or the --path directory if one has been set. Calling
- binstubs with [GEM [GEM]] will create binstubs for all given gems.
-
-OPTIONS
- --force
- Overwrite existing binstubs if they exist.
-
- --path The location to install the specified binstubs to. This defaults
- to bin.
-
- --standalone
- Makes binstubs that can work without depending on Rubygems or
- Bundler at runtime.
-
- --shebang
- Specify a different shebang executable name than the default
- (default 'ruby')
-
-BUNDLE INSTALL --BINSTUBS
- To create binstubs for all the gems in the bundle you can use the
- --binstubs flag in bundle install(1) bundle-install.1.html.
-
-
-
- January 2020 BUNDLE-BINSTUBS(1)
diff --git a/man/bundle-binstubs.ronn b/man/bundle-binstubs.ronn
deleted file mode 100644
index 8909fdc3da..0000000000
--- a/man/bundle-binstubs.ronn
+++ /dev/null
@@ -1,43 +0,0 @@
-bundle-binstubs(1) -- Install the binstubs of the listed gems
-=============================================================
-
-## SYNOPSIS
-
-`bundle binstubs` <GEM_NAME> [--force] [--path PATH] [--standalone]
-
-## DESCRIPTION
-
-Binstubs are scripts that wrap around executables. Bundler creates a
-small Ruby file (a binstub) that loads Bundler, runs the command,
-and puts it into `bin/`. Binstubs are a shortcut-or alternative-
-to always using `bundle exec`. This gives you a file that can be run
-directly, and one that will always run the correct gem version
-used by the application.
-
-For example, if you run `bundle binstubs rspec-core`, Bundler will create
-the file `bin/rspec`. That file will contain enough code to load Bundler,
-tell it to load the bundled gems, and then run rspec.
-
-This command generates binstubs for executables in `GEM_NAME`.
-Binstubs are put into `bin`, or the `--path` directory if one has been set.
-Calling binstubs with [GEM [GEM]] will create binstubs for all given gems.
-
-## OPTIONS
-
-* `--force`:
- Overwrite existing binstubs if they exist.
-
-* `--path`:
- The location to install the specified binstubs to. This defaults to `bin`.
-
-* `--standalone`:
- Makes binstubs that can work without depending on Rubygems or Bundler at
- runtime.
-
-* `--shebang`:
- Specify a different shebang executable name than the default (default 'ruby')
-
-## BUNDLE INSTALL --BINSTUBS
-
-To create binstubs for all the gems in the bundle you can use the `--binstubs`
-flag in [bundle install(1)](bundle-install.1.html).
diff --git a/man/bundle-cache.1 b/man/bundle-cache.1
deleted file mode 100644
index cb376777ff..0000000000
--- a/man/bundle-cache.1
+++ /dev/null
@@ -1,55 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-CACHE" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
-.
-.SH "SYNOPSIS"
-\fBbundle cache\fR
-.
-.SH "DESCRIPTION"
-Copy all of the \fB\.gem\fR files needed to run the application into the \fBvendor/cache\fR directory\. In the future, when running [bundle install(1)][bundle\-install], use the gems in the cache in preference to the ones on \fBrubygems\.org\fR\.
-.
-.SH "GIT AND PATH GEMS"
-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\.
-.
-.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"
-By default, if you run \fBbundle install(1)\fR](bundle\-install\.1\.html) after running bundle cache(1) \fIbundle\-cache\.1\.html\fR, bundler will still connect to \fBrubygems\.org\fR to check whether a platform\-specific gem exists for any of the gems in \fBvendor/cache\fR\.
-.
-.P
-For instance, consider this Gemfile(5):
-.
-.IP "" 4
-.
-.nf
-
-source "https://rubygems\.org"
-
-gem "nokogiri"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-If you run \fBbundle cache\fR under C Ruby, bundler will retrieve the version of \fBnokogiri\fR for the \fB"ruby"\fR platform\. If you deploy to JRuby and run \fBbundle install\fR, bundler is forced to check to see whether a \fB"java"\fR platformed \fBnokogiri\fR exists\.
-.
-.P
-Even though the \fBnokogiri\fR gem for the Ruby platform is \fItechnically\fR acceptable on JRuby, it has a C extension that does not run on JRuby\. As a result, bundler will, by default, still connect to \fBrubygems\.org\fR to check whether it has a version of one of your gems more specific to your platform\.
-.
-.P
-This problem is also not limited to the \fB"java"\fR platform\. A similar (common) problem can happen when developing on Windows and deploying to Linux, or even when developing on OSX and deploying to Linux\.
-.
-.P
-If you know for sure that the gems packaged in \fBvendor/cache\fR are appropriate for the platform you are on, you can run \fBbundle install \-\-local\fR to skip checking for more appropriate gems, and use the ones in \fBvendor/cache\fR\.
-.
-.P
-One way to be sure that you have the right platformed versions of all your gems is to run \fBbundle cache\fR on an identical machine and check in the gems\. For instance, you can run \fBbundle cache\fR on an identical staging box during your staging process, and check in the \fBvendor/cache\fR before deploying to production\.
-.
-.P
-By default, bundle cache(1) \fIbundle\-cache\.1\.html\fR fetches and also installs the gems to the default location\. To package the dependencies to \fBvendor/cache\fR without installing them to the local install location, you can run \fBbundle cache \-\-no\-install\fR\.
diff --git a/man/bundle-cache.1.txt b/man/bundle-cache.1.txt
deleted file mode 100644
index c0b8b5bf07..0000000000
--- a/man/bundle-cache.1.txt
+++ /dev/null
@@ -1,78 +0,0 @@
-BUNDLE-CACHE(1) BUNDLE-CACHE(1)
-
-
-
-NAME
- bundle-cache - Package your needed .gem files into your application
-
-SYNOPSIS
- bundle cache
-
-DESCRIPTION
- Copy all of the .gem files needed to run the application into the ven-
- dor/cache directory. In the future, when running [bundle
- install(1)][bundle-install], use the gems in the cache in preference to
- the ones on rubygems.org.
-
-GIT AND PATH GEMS
- The bundle cache command can also package :git and :path dependencies
- besides .gem files. This needs to be explicitly enabled via the --all
- option. Once used, the --all option will be remembered.
-
-SUPPORT FOR MULTIPLE PLATFORMS
- When using gems that have different packages for different platforms,
- Bundler supports caching of gems for other platforms where the Gemfile
- has been resolved (i.e. present in the lockfile) in vendor/cache. This
- needs to be enabled via the --all-platforms option. This setting will
- be remembered in your local bundler configuration.
-
-REMOTE FETCHING
- By default, if you run bundle install(1)](bundle-install.1.html) after
- running bundle cache(1) bundle-cache.1.html, bundler will still connect
- to rubygems.org to check whether a platform-specific gem exists for any
- of the gems in vendor/cache.
-
- For instance, consider this Gemfile(5):
-
-
-
- source "https://rubygems.org"
-
- gem "nokogiri"
-
-
-
- If you run bundle cache under C Ruby, bundler will retrieve the version
- of nokogiri for the "ruby" platform. If you deploy to JRuby and run
- bundle install, bundler is forced to check to see whether a "java"
- platformed nokogiri exists.
-
- Even though the nokogiri gem for the Ruby platform is technically
- acceptable on JRuby, it has a C extension that does not run on JRuby.
- As a result, bundler will, by default, still connect to rubygems.org to
- check whether it has a version of one of your gems more specific to
- your platform.
-
- This problem is also not limited to the "java" platform. A similar
- (common) problem can happen when developing on Windows and deploying to
- Linux, or even when developing on OSX and deploying to Linux.
-
- If you know for sure that the gems packaged in vendor/cache are appro-
- priate for the platform you are on, you can run bundle install --local
- to skip checking for more appropriate gems, and use the ones in ven-
- dor/cache.
-
- One way to be sure that you have the right platformed versions of all
- your gems is to run bundle cache on an identical machine and check in
- the gems. For instance, you can run bundle cache on an identical stag-
- ing box during your staging process, and check in the vendor/cache
- before deploying to production.
-
- By default, bundle cache(1) bundle-cache.1.html fetches and also
- installs the gems to the default location. To package the dependencies
- to vendor/cache without installing them to the local install location,
- you can run bundle cache --no-install.
-
-
-
- January 2020 BUNDLE-CACHE(1)
diff --git a/man/bundle-check.1 b/man/bundle-check.1
deleted file mode 100644
index aba5b66348..0000000000
--- a/man/bundle-check.1
+++ /dev/null
@@ -1,31 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-CHECK" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
-.
-.SH "SYNOPSIS"
-\fBbundle check\fR [\-\-dry\-run] [\-\-gemfile=FILE] [\-\-path=PATH]
-.
-.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
-If not, the first missing gem is listed and Bundler exits status 1\.
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-dry\-run\fR
-Locks the [\fBGemfile(5)\fR][Gemfile(5)] before running the command\.
-.
-.TP
-\fB\-\-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/man/bundle-check.1.txt b/man/bundle-check.1.txt
deleted file mode 100644
index cca5fae9e1..0000000000
--- a/man/bundle-check.1.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-BUNDLE-CHECK(1) BUNDLE-CHECK(1)
-
-
-
-NAME
- bundle-check - Verifies if dependencies are satisfied by installed gems
-
-SYNOPSIS
- bundle check [--dry-run] [--gemfile=FILE] [--path=PATH]
-
-DESCRIPTION
- check searches the local machine for each of the gems requested in the
- Gemfile. If all gems are found, Bundler prints a success message and
- exits with a status of 0.
-
- If not, the first missing gem is listed and Bundler exits status 1.
-
-OPTIONS
- --dry-run
- Locks the [Gemfile(5)][Gemfile(5)] before running the command.
-
- --gemfile
- Use the specified gemfile instead of the [Gemfile(5)][Gem-
- file(5)].
-
- --path Specify a different path than the system default ($BUNDLE_PATH
- or $GEM_HOME). Bundler will remember this value for future
- installs on this machine.
-
-
-
-
- January 2020 BUNDLE-CHECK(1)
diff --git a/man/bundle-clean.1 b/man/bundle-clean.1
deleted file mode 100644
index cc5c8e86d7..0000000000
--- a/man/bundle-clean.1
+++ /dev/null
@@ -1,24 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-CLEAN" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
-.
-.SH "SYNOPSIS"
-\fBbundle clean\fR [\-\-dry\-run] [\-\-force]
-.
-.SH "DESCRIPTION"
-This command will remove all unused gems in your bundler directory\. This is useful when you have made many changes to your gem dependencies\.
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-dry\-run\fR
-Print the changes, but do not clean the unused gems\.
-.
-.TP
-\fB\-\-force\fR
-Force a clean even if \fB\-\-path\fR is not set\.
-
diff --git a/man/bundle-clean.1.txt b/man/bundle-clean.1.txt
deleted file mode 100644
index 300d0c0b51..0000000000
--- a/man/bundle-clean.1.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-BUNDLE-CLEAN(1) BUNDLE-CLEAN(1)
-
-
-
-NAME
- bundle-clean - Cleans up unused gems in your bundler directory
-
-SYNOPSIS
- bundle clean [--dry-run] [--force]
-
-DESCRIPTION
- This command will remove all unused gems in your bundler directory.
- This is useful when you have made many changes to your gem dependen-
- cies.
-
-OPTIONS
- --dry-run
- Print the changes, but do not clean the unused gems.
-
- --force
- Force a clean even if --path is not set.
-
-
-
-
- January 2020 BUNDLE-CLEAN(1)
diff --git a/man/bundle-config.1 b/man/bundle-config.1
deleted file mode 100644
index c3464fb2ec..0000000000
--- a/man/bundle-config.1
+++ /dev/null
@@ -1,497 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-CONFIG" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-config\fR \- Set bundler configuration options
-.
-.SH "SYNOPSIS"
-\fBbundle config\fR [list|get|set|unset] [\fIname\fR [\fIvalue\fR]]
-.
-.SH "DESCRIPTION"
-This command allows you to interact with Bundler\'s configuration system\.
-.
-.P
-Bundler loads configuration settings in this order:
-.
-.IP "1." 4
-Local config (\fBapp/\.bundle/config\fR)
-.
-.IP "2." 4
-Environmental variables (\fBENV\fR)
-.
-.IP "3." 4
-Global config (\fB~/\.bundle/config\fR)
-.
-.IP "4." 4
-Bundler default config
-.
-.IP "" 0
-.
-.P
-Executing \fBbundle config list\fR with will print a list of all bundler configuration for the current bundle, and where that configuration 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 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
-Executing \fBbundle config set \-\-global <name> <value>\fR works the same as above\.
-.
-.P
-Executing \fBbundle config set \-\-local <name> <value>\fR will set that configuration to the local application\. The configuration will be stored in \fBapp/\.bundle/config\fR\.
-.
-.P
-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
-Executing \fBbundle config unset \-\-local <name> <value>\fR will delete the configuration only from the local application\.
-.
-.P
-Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
-.
-.P
-Executing \fBbundle config set disable_multisource true\fR upgrades the warning about the Gemfile containing multiple primary sources to an error\. Executing \fBbundle config unset disable_multisource\fR downgrades this error to a warning\.
-.
-.SH "REMEMBERING OPTIONS"
-Flags passed to \fBbundle install\fR or the Bundler runtime, such as \fB\-\-path foo\fR or \fB\-\-without production\fR, are remembered between commands and saved to your local application\'s configuration (normally, \fB\./\.bundle/config\fR)\.
-.
-.P
-However, this will be changed in bundler 3, so it\'s better not to rely on this behavior\. If these options must be remembered, it\'s better to set them using \fBbundle config\fR (e\.g\., \fBbundle config set path foo\fR)\.
-.
-.P
-The options that can be configured are:
-.
-.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\.
-.
-.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\.
-.
-.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\.
-.
-.TP
-\fBwithout\fR
-A space\-separated list of groups referencing gems to skip during installation\.
-.
-.TP
-\fBwith\fR
-A space\-separated list of groups referencing gems to include during installation\.
-.
-.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
-A very common example, the \fBmysql\fR gem, requires Snow Leopard users to pass configuration flags to \fBgem install\fR to specify where to find the \fBmysql_config\fR executable\.
-.
-.IP "" 4
-.
-.nf
-
-gem install mysql \-\- \-\-with\-mysql\-config=/usr/local/mysql/bin/mysql_config
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Since the specific location of that executable can change from machine to machine, you can specify these flags on a per\-machine basis\.
-.
-.IP "" 4
-.
-.nf
-
-bundle config set build\.mysql \-\-with\-mysql\-config=/usr/local/mysql/bin/mysql_config
-.
-.fi
-.
-.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_bundler_dependency_conflicts\fR (\fBBUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS\fR): Allow resolving to specifications that have dependencies on \fBbundler\fR that are incompatible with the running Bundler version\.
-.
-.IP "\(bu" 4
-\fBallow_deployment_source_credential_changes\fR (\fBBUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES\fR): When in deployment mode, allow changing the credentials to a gem\'s source\. Ex: \fBhttps://some\.host\.com/gems/path/\fR \-> \fBhttps://user_name:password@some\.host\.com/gems/path\fR
-.
-.IP "\(bu" 4
-\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\.
-.
-.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_multisource\fR (\fBBUNDLE_DISABLE_MULTISOURCE\fR): When set, Gemfiles containing multiple sources will produce errors instead of warnings\. Use \fBbundle config unset disable_multisource\fR to unset\.
-.
-.IP "\(bu" 4
-\fBdisable_platform_warnings\fR (\fBBUNDLE_DISABLE_PLATFORM_WARNINGS\fR): Disable warnings during bundle install when a dependency is unused on the current platform\.
-.
-.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\.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_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 1\.
-.
-.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_update_to_newer_versions\fR (\fBBUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS\fR): During \fBbundle update\fR, only resolve to newer versions of the gems in the lockfile\.
-.
-.IP "\(bu" 4
-\fBpath\fR (\fBBUNDLE_PATH\fR): The location on disk where all gems in your bundle will be located regardless of \fB$GEM_HOME\fR or \fB$GEM_PATH\fR values\. Bundle gems not found in this location will be installed by \fBbundle install\fR\. Defaults to \fBGem\.dir\fR\. When \-\-deployment is used, defaults to vendor/bundle\.
-.
-.IP "\(bu" 4
-\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
-\fBskip_default_git_sources\fR (\fBBUNDLE_SKIP_DEFAULT_GIT_SOURCES\fR): Whether Bundler should skip adding default git source shortcuts to the Gemfile DSL\.
-.
-.IP "\(bu" 4
-\fBspecific_platform\fR (\fBBUNDLE_SPECIFIC_PLATFORM\fR): Allow bundler to resolve for the specific running platform and store it in the lockfile, instead of only using a generic platform\. A specific platform is the exact platform triple reported by \fBGem::Platform\.local\fR, such as \fBx86_64\-darwin\-16\fR or \fBuniversal\-java\-1\.8\fR\. On the other hand, generic platforms are those such as \fBruby\fR, \fBmswin\fR, or \fBjava\fR\. In this example, \fBx86_64\-darwin\-16\fR would map to \fBruby\fR and \fBuniversal\-java\-1\.8\fR to \fBjava\fR\.
-.
-.IP "\(bu" 4
-\fBssl_ca_cert\fR (\fBBUNDLE_SSL_CA_CERT\fR): Path to a designated CA certificate file or folder containing multiple certificates for trusted CAs in PEM format\.
-.
-.IP "\(bu" 4
-\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
-\fBsuppress_install_using_messages\fR (\fBBUNDLE_SUPPRESS_INSTALL_USING_MESSAGES\fR): Avoid printing \fBUsing \.\.\.\fR messages during installation when the version of a gem has not changed\.
-.
-.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
-\fBunlock_source_unlocks_spec\fR (\fBBUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC\fR): Whether running \fBbundle update \-\-source NAME\fR unlocks a gem with the given name\. Defaults to \fBtrue\fR\.
-.
-.IP "\(bu" 4
-\fBupdate_requires_all_flag\fR (\fBBUNDLE_UPDATE_REQUIRES_ALL_FLAG\fR) Require passing \fB\-\-all\fR to \fBbundle update\fR when everything should be updated, and disallow passing no options to \fBbundle update\fR\.
-.
-.IP "\(bu" 4
-\fBuser_agent\fR (\fBBUNDLE_USER_AGENT\fR): The custom user agent fragment Bundler includes in API requests\.
-.
-.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 package(1) \fIbundle\-package\.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
-.
-.nf
-
-bundle config set local\.GEM_NAME /path/to/local/git/repository
-.
-.fi
-.
-.IP "" 0
-.
-.P
-For example, in order to use a local Rack repository, a developer could call:
-.
-.IP "" 4
-.
-.nf
-
-bundle config set local\.rack ~/Work/git/rack
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Now instead of checking out the remote git repository, the local override will be used\. Similar to a path source, every time the local git repository change, changes will be automatically picked up by Bundler\. This means a commit in the local git repo will update the revision in the \fBGemfile\.lock\fR to the local git repo revision\. This requires the same attention as git submodules\. Before pushing to the remote, you need to ensure the local override was pushed, otherwise you may point to a commit that only exists in your local machine\. You\'ll also need to CGI escape your usernames and passwords as well\.
-.
-.P
-Bundler does many checks to ensure a developer won\'t work with invalid references\. Particularly, we force a developer to specify a branch in the \fBGemfile\fR in order to use this feature\. If the branch specified in the \fBGemfile\fR and the current branch in the local git repository do not match, Bundler will abort\. This ensures that a developer is always working against the correct branches, and prevents accidental locking to a different branch\.
-.
-.P
-Finally, Bundler also ensures that the current revision in the \fBGemfile\.lock\fR exists in the local git repository\. By doing this, Bundler forces you to fetch the latest changes in the remotes\.
-.
-.SH "MIRRORS OF GEM SOURCES"
-Bundler supports overriding gem sources with mirrors\. This allows you to configure rubygems\.org as the gem source in your Gemfile while still using your mirror to fetch gems\.
-.
-.IP "" 4
-.
-.nf
-
-bundle config set mirror\.SOURCE_URL MIRROR_URL
-.
-.fi
-.
-.IP "" 0
-.
-.P
-For example, to use a mirror of rubygems\.org hosted at rubygems\-mirror\.org:
-.
-.IP "" 4
-.
-.nf
-
-bundle config set mirror\.http://rubygems\.org http://rubygems\-mirror\.org
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Each mirror also provides a fallback timeout setting\. If the mirror does not respond within the fallback timeout, Bundler will try to use the original server instead of the mirror\.
-.
-.IP "" 4
-.
-.nf
-
-bundle config set mirror\.SOURCE_URL\.fallback_timeout TIMEOUT
-.
-.fi
-.
-.IP "" 0
-.
-.P
-For example, to fall back to rubygems\.org after 3 seconds:
-.
-.IP "" 4
-.
-.nf
-
-bundle config set mirror\.https://rubygems\.org\.fallback_timeout 3
-.
-.fi
-.
-.IP "" 0
-.
-.P
-The default fallback timeout is 0\.1 seconds, but the setting can currently only accept whole seconds (for example, 1, 15, or 30)\.
-.
-.SH "CREDENTIALS FOR GEM SOURCES"
-Bundler allows you to configure credentials for any gem source, which allows you to avoid putting secrets into your Gemfile\.
-.
-.IP "" 4
-.
-.nf
-
-bundle config set SOURCE_HOSTNAME USERNAME:PASSWORD
-.
-.fi
-.
-.IP "" 0
-.
-.P
-For example, to save the credentials of user \fBclaudette\fR for the gem source at \fBgems\.longerous\.com\fR, you would run:
-.
-.IP "" 4
-.
-.nf
-
-bundle config set gems\.longerous\.com claudette:s00pers3krit
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Or you can set the credentials as an environment variable like this:
-.
-.IP "" 4
-.
-.nf
-
-export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-For gems with a git source with HTTP(S) URL you can specify credentials like so:
-.
-.IP "" 4
-.
-.nf
-
-bundle config set https://github\.com/bundler/bundler\.git username:password
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Or you can set the credentials as an environment variable like so:
-.
-.IP "" 4
-.
-.nf
-
-export BUNDLE_GITHUB__COM=username:password
-.
-.fi
-.
-.IP "" 0
-.
-.P
-This is especially useful for private repositories on hosts such as Github, where you can use personal OAuth tokens:
-.
-.IP "" 4
-.
-.nf
-
-export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x\-oauth\-basic
-.
-.fi
-.
-.IP "" 0
-.
-.SH "CONFIGURE BUNDLER DIRECTORIES"
-Bundler\'s home, config, cache and plugin directories are able to be configured through environment variables\. The default location for Bundler\'s home directory is \fB~/\.bundle\fR, which all directories inherit from by default\. The following outlines the available environment variables and their default values
-.
-.IP "" 4
-.
-.nf
-
-BUNDLE_USER_HOME : $HOME/\.bundle
-BUNDLE_USER_CACHE : $BUNDLE_USER_HOME/cache
-BUNDLE_USER_CONFIG : $BUNDLE_USER_HOME/config
-BUNDLE_USER_PLUGIN : $BUNDLE_USER_HOME/plugin
-.
-.fi
-.
-.IP "" 0
-
diff --git a/man/bundle-config.1.txt b/man/bundle-config.1.txt
deleted file mode 100644
index f5fc0ce12a..0000000000
--- a/man/bundle-config.1.txt
+++ /dev/null
@@ -1,528 +0,0 @@
-BUNDLE-CONFIG(1) BUNDLE-CONFIG(1)
-
-
-
-NAME
- bundle-config - Set bundler configuration options
-
-SYNOPSIS
- bundle config [list|get|set|unset] [name [value]]
-
-DESCRIPTION
- This command allows you to interact with Bundler's configuration sys-
- tem.
-
- Bundler loads configuration settings in this order:
-
- 1. Local config (app/.bundle/config)
-
- 2. Environmental variables (ENV)
-
- 3. Global config (~/.bundle/config)
-
- 4. Bundler default config
-
-
-
- Executing bundle config list with will print a list of all bundler con-
- figuration for the current bundle, and where that configuration was
- set.
-
- Executing bundle config get <name> will print the value of that config-
- uration setting, and where it was set.
-
- Executing bundle config set <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 set --global <name> <value> works the same as
- above.
-
- Executing bundle config set --local <name> <value> will set that con-
- figuration to the local application. The configuration will be stored
- in app/.bundle/config.
-
- Executing bundle config unset <name> will delete the configuration in
- both local and global sources.
-
- Executing bundle config unset --global <name> will delete the configu-
- ration only from the user configuration.
-
- Executing bundle config unset --local <name> <value> will delete the
- configuration only from the local application.
-
- Executing bundle with the BUNDLE_IGNORE_CONFIG environment variable set
- will cause it to ignore all configuration.
-
- Executing bundle config set disable_multisource true upgrades the warn-
- ing about the Gemfile containing multiple primary sources to an error.
- Executing bundle config unset disable_multisource downgrades this error
- to a warning.
-
-REMEMBERING OPTIONS
- Flags passed to bundle install or the Bundler runtime, such as --path
- foo or --without production, are remembered between commands and saved
- to your local application's configuration (normally, ./.bundle/config).
-
- However, this will be changed in bundler 3, so it's better not to rely
- on this behavior. If these options must be remembered, it's better to
- set them using bundle config (e.g., bundle config set path foo).
-
- The options that can be configured are:
-
- bin Creates a directory (defaults to ~/bin) and place any executa-
- bles from the gem there. These executables run in Bundler's con-
- text. If used, you might add this directory to your environ-
- ment's PATH variable. For instance, if the rails gem comes with
- a rails executable, this flag will create a bin/rails executable
- that ensures that all referred dependencies will be resolved
- using the bundled gems.
-
- deployment
- In deployment mode, Bundler will 'roll-out' the bundle for pro-
- duction use. Please check carefully if you want to have this
- option enabled in development or test environments.
-
- path The location to install the specified gems to. This defaults to
- Rubygems' setting. Bundler shares this location with Rubygems,
- gem install ... will have gem installed there, too. Therefore,
- gems installed without a --path ... setting will show up by
- calling gem list. Accordingly, gems installed to other locations
- will not get listed.
-
- without
- A space-separated list of groups referencing gems to skip during
- installation.
-
- with A space-separated list of groups referencing gems to include
- during installation.
-
-BUILD OPTIONS
- You can use bundle config to give Bundler the flags to pass to the gem
- installer every time bundler tries to install a particular gem.
-
- A very common example, the mysql gem, requires Snow Leopard users to
- pass configuration flags to gem install to specify where to find the
- mysql_config executable.
-
-
-
- gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
-
-
-
- Since the specific location of that executable can change from machine
- to machine, you can specify these flags on a per-machine basis.
-
-
-
- bundle config set build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config
-
-
-
- After running this command, every time bundler needs to install the
- mysql gem, it will pass along the flags you specified.
-
-CONFIGURATION KEYS
- Configuration keys in bundler have two forms: the canonical form and
- the environment variable form.
-
- For instance, passing the --without flag to bundle install(1) bun-
- dle-install.1.html prevents Bundler from installing certain groups
- specified in the Gemfile(5). Bundler persists this value in app/.bun-
- dle/config so that calls to Bundler.setup do not try to find gems from
- the Gemfile that you didn't install. Additionally, subsequent calls to
- bundle install(1) bundle-install.1.html remember this setting and skip
- those groups.
-
- The canonical form of this configuration is "without". To convert the
- canonical form to the environment variable form, capitalize it, and
- prepend BUNDLE_. The environment variable form of "without" is BUN-
- DLE_WITHOUT.
-
- Any periods in the configuration keys must be replaced with two under-
- scores when setting it via environment variables. The configuration key
- local.rack becomes the environment variable BUNDLE_LOCAL__RACK.
-
-LIST OF AVAILABLE KEYS
- The following is a list of all configuration keys and their purpose.
- You can learn more about their operation in bundle install(1) bun-
- dle-install.1.html.
-
- o allow_bundler_dependency_conflicts (BUNDLE_ALLOW_BUNDLER_DEPEN-
- DENCY_CONFLICTS): Allow resolving to specifications that have
- dependencies on bundler that are incompatible with the running
- Bundler version.
-
- o allow_deployment_source_credential_changes (BUNDLE_ALLOW_DEPLOY-
- MENT_SOURCE_CREDENTIAL_CHANGES): When in deployment mode, allow
- changing the credentials to a gem's source. Ex:
- https://some.host.com/gems/path/ -> https://user_name:pass-
- word@some.host.com/gems/path
-
- o allow_offline_install (BUNDLE_ALLOW_OFFLINE_INSTALL): Allow Bundler
- to use cached data when installing without network access.
-
- o auto_clean_without_path (BUNDLE_AUTO_CLEAN_WITHOUT_PATH): Automati-
- cally run bundle clean after installing when an explicit path has
- not been set and Bundler is not installing into the system gems.
-
- o auto_install (BUNDLE_AUTO_INSTALL): Automatically run bundle
- install when gems are missing.
-
- o bin (BUNDLE_BIN): Install executables from gems in the bundle to
- the specified directory. Defaults to false.
-
- o cache_all (BUNDLE_CACHE_ALL): Cache all gems, including path and
- git gems.
-
- o cache_all_platforms (BUNDLE_CACHE_ALL_PLATFORMS): Cache gems for
- all platforms.
-
- o cache_path (BUNDLE_CACHE_PATH): The directory that bundler will
- place cached gems in when running bundle package, and that bundler
- will look in when installing gems. Defaults to vendor/cache.
-
- o clean (BUNDLE_CLEAN): Whether Bundler should run bundle clean auto-
- matically after bundle install.
-
- o console (BUNDLE_CONSOLE): The console that bundle console starts.
- Defaults to irb.
-
- o default_install_uses_path (BUNDLE_DEFAULT_INSTALL_USES_PATH):
- Whether a bundle install without an explicit --path argument
- defaults to installing gems in .bundle.
-
- o deployment (BUNDLE_DEPLOYMENT): Disallow changes to the Gemfile.
- When the Gemfile is changed and the lockfile has not been updated,
- running Bundler commands will be blocked.
-
- o disable_checksum_validation (BUNDLE_DISABLE_CHECKSUM_VALIDATION):
- Allow installing gems even if they do not match the checksum pro-
- vided by RubyGems.
-
- o disable_exec_load (BUNDLE_DISABLE_EXEC_LOAD): Stop Bundler from
- using load to launch an executable in-process in bundle exec.
-
- o disable_local_branch_check (BUNDLE_DISABLE_LOCAL_BRANCH_CHECK):
- Allow Bundler to use a local git override without a branch speci-
- fied in the Gemfile.
-
- o disable_multisource (BUNDLE_DISABLE_MULTISOURCE): When set, Gem-
- files containing multiple sources will produce errors instead of
- warnings. Use bundle config unset disable_multisource to unset.
-
- o disable_platform_warnings (BUNDLE_DISABLE_PLATFORM_WARNINGS): Dis-
- able warnings during bundle install when a dependency is unused on
- the current platform.
-
- o disable_shared_gems (BUNDLE_DISABLE_SHARED_GEMS): Stop Bundler from
- accessing gems installed to RubyGems' normal location.
-
- o disable_version_check (BUNDLE_DISABLE_VERSION_CHECK): Stop Bundler
- from checking if a newer Bundler version is available on
- rubygems.org.
-
- o force_ruby_platform (BUNDLE_FORCE_RUBY_PLATFORM): Ignore the cur-
- rent machine's platform and install only ruby platform gems. As a
- result, gems with native extensions will be compiled from source.
-
- o frozen (BUNDLE_FROZEN): Disallow changes to the Gemfile. When the
- Gemfile is changed and the lockfile has not been updated, running
- Bundler commands will be blocked. Defaults to true when --deploy-
- ment is used.
-
- o gem.push_key (BUNDLE_GEM__PUSH_KEY): Sets the --key parameter for
- gem push when using the rake release command with a private gem-
- stash server.
-
- o gemfile (BUNDLE_GEMFILE): The name of the file that bundler should
- use as the Gemfile. This location of this file also sets the root
- of the project, which is used to resolve relative paths in the Gem-
- file, among other things. By default, bundler will search up from
- the current working directory until it finds a Gemfile.
-
- o global_gem_cache (BUNDLE_GLOBAL_GEM_CACHE): Whether Bundler should
- cache all gems globally, rather than locally to the installing Ruby
- installation.
-
- o ignore_messages (BUNDLE_IGNORE_MESSAGES): When set, no post install
- messages will be printed. To silence a single gem, use dot notation
- like ignore_messages.httparty true.
-
- o init_gems_rb (BUNDLE_INIT_GEMS_RB) Generate a gems.rb instead of a
- Gemfile when running bundle init.
-
- o jobs (BUNDLE_JOBS): The number of gems Bundler can install in par-
- allel. Defaults to 1.
-
- o no_install (BUNDLE_NO_INSTALL): Whether bundle package should skip
- installing gems.
-
- o no_prune (BUNDLE_NO_PRUNE): Whether Bundler should leave outdated
- gems unpruned when caching.
-
- o only_update_to_newer_versions (BUNDLE_ONLY_UPDATE_TO_NEWER_VER-
- SIONS): During bundle update, only resolve to newer versions of the
- gems in the lockfile.
-
- o path (BUNDLE_PATH): The location on disk where all gems in your
- bundle will be located regardless of $GEM_HOME or $GEM_PATH values.
- Bundle gems not found in this location will be installed by bundle
- install. Defaults to Gem.dir. When --deployment is used, defaults
- to vendor/bundle.
-
- o path.system (BUNDLE_PATH__SYSTEM): Whether Bundler will install
- gems into the default system path (Gem.dir).
-
- o path_relative_to_cwd (BUNDLE_PATH_RELATIVE_TO_CWD) Makes --path
- relative to the CWD instead of the Gemfile.
-
- o plugins (BUNDLE_PLUGINS): Enable Bundler's experimental plugin sys-
- tem.
-
- o prefer_patch (BUNDLE_PREFER_PATCH): Prefer updating only to next
- patch version during updates. Makes bundle update calls equivalent
- to bundler update --patch.
-
- o print_only_version_number (BUNDLE_PRINT_ONLY_VERSION_NUMBER) Print
- only version number from bundler --version.
-
- o redirect (BUNDLE_REDIRECT): The number of redirects allowed for
- network requests. Defaults to 5.
-
- o retry (BUNDLE_RETRY): The number of times to retry failed network
- requests. Defaults to 3.
-
- o setup_makes_kernel_gem_public (BUNDLE_SETUP_MAKES_KERNEL_GEM_PUB-
- LIC): Have Bundler.setup make the Kernel#gem method public, even
- though RubyGems declares it as private.
-
- o shebang (BUNDLE_SHEBANG): The program name that should be invoked
- for generated binstubs. Defaults to the ruby install name used to
- generate the binstub.
-
- o silence_deprecations (BUNDLE_SILENCE_DEPRECATIONS): Whether Bundler
- should silence deprecation warnings for behavior that will be
- changed in the next major version.
-
- o silence_root_warning (BUNDLE_SILENCE_ROOT_WARNING): Silence the
- warning Bundler prints when installing gems as root.
-
- o skip_default_git_sources (BUNDLE_SKIP_DEFAULT_GIT_SOURCES): Whether
- Bundler should skip adding default git source shortcuts to the Gem-
- file DSL.
-
- o specific_platform (BUNDLE_SPECIFIC_PLATFORM): Allow bundler to
- resolve for the specific running platform and store it in the lock-
- file, instead of only using a generic platform. A specific platform
- is the exact platform triple reported by Gem::Platform.local, such
- as x86_64-darwin-16 or universal-java-1.8. On the other hand,
- generic platforms are those such as ruby, mswin, or java. In this
- example, x86_64-darwin-16 would map to ruby and universal-java-1.8
- to java.
-
- o ssl_ca_cert (BUNDLE_SSL_CA_CERT): Path to a designated CA certifi-
- cate file or folder containing multiple certificates for trusted
- CAs in PEM format.
-
- o ssl_client_cert (BUNDLE_SSL_CLIENT_CERT): Path to a designated file
- containing a X.509 client certificate and key in PEM format.
-
- o ssl_verify_mode (BUNDLE_SSL_VERIFY_MODE): The SSL verification mode
- Bundler uses when making HTTPS requests. Defaults to verify peer.
-
- o suppress_install_using_messages (BUNDLE_SUPPRESS_INSTALL_USING_MES-
- SAGES): Avoid printing Using ... messages during installation when
- the version of a gem has not changed.
-
- o system_bindir (BUNDLE_SYSTEM_BINDIR): The location where RubyGems
- installs binstubs. Defaults to Gem.bindir.
-
- o timeout (BUNDLE_TIMEOUT): The seconds allowed before timing out for
- network requests. Defaults to 10.
-
- o unlock_source_unlocks_spec (BUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC):
- Whether running bundle update --source NAME unlocks a gem with the
- given name. Defaults to true.
-
- o update_requires_all_flag (BUNDLE_UPDATE_REQUIRES_ALL_FLAG) Require
- passing --all to bundle update when everything should be updated,
- and disallow passing no options to bundle update.
-
- o user_agent (BUNDLE_USER_AGENT): The custom user agent fragment
- Bundler includes in API requests.
-
- o with (BUNDLE_WITH): A :-separated list of groups whose gems bundler
- should install.
-
- o without (BUNDLE_WITHOUT): A :-separated list of groups whose gems
- bundler should not install.
-
-
-
- In general, you should set these settings per-application by using the
- applicable flag to the bundle install(1) bundle-install.1.html or bun-
- dle package(1) bundle-package.1.html command.
-
- You can set them globally either via environment variables or bundle
- config, whichever is preferable for your setup. If you use both, envi-
- ronment variables will take preference over global settings.
-
-LOCAL GIT REPOS
- Bundler also allows you to work against a git repository locally
- instead of using the remote version. This can be achieved by setting up
- a local override:
-
-
-
- bundle config set local.GEM_NAME /path/to/local/git/repository
-
-
-
- For example, in order to use a local Rack repository, a developer could
- call:
-
-
-
- bundle config set local.rack ~/Work/git/rack
-
-
-
- Now instead of checking out the remote git repository, the local over-
- ride will be used. Similar to a path source, every time the local git
- repository change, changes will be automatically picked up by Bundler.
- This means a commit in the local git repo will update the revision in
- the Gemfile.lock to the local git repo revision. This requires the same
- attention as git submodules. Before pushing to the remote, you need to
- ensure the local override was pushed, otherwise you may point to a com-
- mit that only exists in your local machine. You'll also need to CGI
- escape your usernames and passwords as well.
-
- Bundler does many checks to ensure a developer won't work with invalid
- references. Particularly, we force a developer to specify a branch in
- the Gemfile in order to use this feature. If the branch specified in
- the Gemfile and the current branch in the local git repository do not
- match, Bundler will abort. This ensures that a developer is always
- working against the correct branches, and prevents accidental locking
- to a different branch.
-
- Finally, Bundler also ensures that the current revision in the Gem-
- file.lock exists in the local git repository. By doing this, Bundler
- forces you to fetch the latest changes in the remotes.
-
-MIRRORS OF GEM SOURCES
- Bundler supports overriding gem sources with mirrors. This allows you
- to configure rubygems.org as the gem source in your Gemfile while still
- using your mirror to fetch gems.
-
-
-
- bundle config set mirror.SOURCE_URL MIRROR_URL
-
-
-
- For example, to use a mirror of rubygems.org hosted at rubygems-mir-
- ror.org:
-
-
-
- bundle config set mirror.http://rubygems.org http://rubygems-mirror.org
-
-
-
- Each mirror also provides a fallback timeout setting. If the mirror
- does not respond within the fallback timeout, Bundler will try to use
- the original server instead of the mirror.
-
-
-
- bundle config set mirror.SOURCE_URL.fallback_timeout TIMEOUT
-
-
-
- For example, to fall back to rubygems.org after 3 seconds:
-
-
-
- bundle config set mirror.https://rubygems.org.fallback_timeout 3
-
-
-
- The default fallback timeout is 0.1 seconds, but the setting can cur-
- rently only accept whole seconds (for example, 1, 15, or 30).
-
-CREDENTIALS FOR GEM SOURCES
- Bundler allows you to configure credentials for any gem source, which
- allows you to avoid putting secrets into your Gemfile.
-
-
-
- bundle config set SOURCE_HOSTNAME USERNAME:PASSWORD
-
-
-
- For example, to save the credentials of user claudette for the gem
- source at gems.longerous.com, you would run:
-
-
-
- bundle config set gems.longerous.com claudette:s00pers3krit
-
-
-
- Or you can set the credentials as an environment variable like this:
-
-
-
- export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit"
-
-
-
- For gems with a git source with HTTP(S) URL you can specify credentials
- like so:
-
-
-
- bundle config set https://github.com/bundler/bundler.git username:password
-
-
-
- Or you can set the credentials as an environment variable like so:
-
-
-
- export BUNDLE_GITHUB__COM=username:password
-
-
-
- This is especially useful for private repositories on hosts such as
- Github, where you can use personal OAuth tokens:
-
-
-
- export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x-oauth-basic
-
-
-
-CONFIGURE BUNDLER DIRECTORIES
- Bundler's home, config, cache and plugin directories are able to be
- configured through environment variables. The default location for
- Bundler's home directory is ~/.bundle, which all directories inherit
- from by default. The following outlines the available environment vari-
- ables and their default values
-
-
-
- BUNDLE_USER_HOME : $HOME/.bundle
- BUNDLE_USER_CACHE : $BUNDLE_USER_HOME/cache
- BUNDLE_USER_CONFIG : $BUNDLE_USER_HOME/config
- BUNDLE_USER_PLUGIN : $BUNDLE_USER_HOME/plugin
-
-
-
-
-
-
- January 2020 BUNDLE-CONFIG(1)
diff --git a/man/bundle-config.ronn b/man/bundle-config.ronn
deleted file mode 100644
index 75b389e7e3..0000000000
--- a/man/bundle-config.ronn
+++ /dev/null
@@ -1,399 +0,0 @@
-bundle-config(1) -- Set bundler configuration options
-=====================================================
-
-## SYNOPSIS
-
-`bundle config` [list|get|set|unset] [<name> [<value>]]
-
-## DESCRIPTION
-
-This command allows you to interact with Bundler's configuration system.
-
-Bundler loads configuration settings in this order:
-
-1. Local config (`app/.bundle/config`)
-2. Environmental variables (`ENV`)
-3. Global config (`~/.bundle/config`)
-4. Bundler default config
-
-Executing `bundle config list` with will print a list of all bundler
-configuration for the current bundle, and where that configuration
-was set.
-
-Executing `bundle config get <name>` will print the value of that configuration
-setting, and where it was set.
-
-Executing `bundle config set <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 set --global <name> <value>` works the same as above.
-
-Executing `bundle config set --local <name> <value>` will set that configuration to
-the local application. The configuration will be stored in `app/.bundle/config`.
-
-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> <value>` will delete the
-configuration only from the local application.
-
-Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
-cause it to ignore all configuration.
-
-Executing `bundle config set disable_multisource true` upgrades the warning about
-the Gemfile containing multiple primary sources to an error. Executing `bundle
-config unset disable_multisource` downgrades this error to a warning.
-
-## REMEMBERING OPTIONS
-
-Flags passed to `bundle install` or the Bundler runtime, such as `--path foo` or
-`--without production`, are remembered between commands and saved to your local
-application's configuration (normally, `./.bundle/config`).
-
-However, this will be changed in bundler 3, so it's better not to rely on this
-behavior. If these options must be remembered, it's better to set them using
-`bundle config` (e.g., `bundle config set path foo`).
-
-The options that can be configured are:
-
-* `bin`:
- Creates a directory (defaults to `~/bin`) and place any executables from the
- gem there. These executables run in Bundler's context. If used, you might add
- this directory to your environment's `PATH` variable. For instance, if the
- `rails` gem comes with a `rails` executable, this flag will create a
- `bin/rails` executable that ensures that all referred dependencies will be
- resolved using the bundled gems.
-
-* `deployment`:
- In deployment mode, Bundler will 'roll-out' the bundle for
- `production` use. Please check carefully if you want to have this option
- enabled in `development` or `test` environments.
-
-* `path`:
- The location to install the specified gems to. This defaults to Rubygems'
- setting. Bundler shares this location with Rubygems, `gem install ...` will
- have gem installed there, too. Therefore, gems installed without a
- `--path ...` setting will show up by calling `gem list`. Accordingly, gems
- installed to other locations will not get listed.
-
-* `without`:
- A space-separated list of groups referencing gems to skip during installation.
-
-* `with`:
- A space-separated list of groups referencing gems to include during installation.
-
-## BUILD OPTIONS
-
-You can use `bundle config` to give Bundler the flags to pass to the gem
-installer every time bundler tries to install a particular gem.
-
-A very common example, the `mysql` gem, requires Snow Leopard users to
-pass configuration flags to `gem install` to specify where to find the
-`mysql_config` executable.
-
- gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
-
-Since the specific location of that executable can change from machine
-to machine, you can specify these flags on a per-machine basis.
-
- bundle config set build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config
-
-After running this command, every time bundler needs to install the
-`mysql` gem, it will pass along the flags you specified.
-
-## CONFIGURATION KEYS
-
-Configuration keys in bundler have two forms: the canonical form and the
-environment variable form.
-
-For instance, passing the `--without` flag to [bundle install(1)](bundle-install.1.html)
-prevents Bundler from installing certain groups specified in the Gemfile(5). Bundler
-persists this value in `app/.bundle/config` so that calls to `Bundler.setup`
-do not try to find gems from the `Gemfile` that you didn't install. Additionally,
-subsequent calls to [bundle install(1)](bundle-install.1.html) remember this setting
-and skip those groups.
-
-The canonical form of this configuration is `"without"`. To convert the canonical
-form to the environment variable form, capitalize it, and prepend `BUNDLE_`. The
-environment variable form of `"without"` is `BUNDLE_WITHOUT`.
-
-Any periods in the configuration keys must be replaced with two underscores when
-setting it via environment variables. The configuration key `local.rack` becomes
-the environment variable `BUNDLE_LOCAL__RACK`.
-
-## LIST OF AVAILABLE KEYS
-
-The following is a list of all configuration keys and their purpose. You can
-learn more about their operation in [bundle install(1)](bundle-install.1.html).
-
-* `allow_bundler_dependency_conflicts` (`BUNDLE_ALLOW_BUNDLER_DEPENDENCY_CONFLICTS`):
- Allow resolving to specifications that have dependencies on `bundler` that
- are incompatible with the running Bundler version.
-* `allow_deployment_source_credential_changes` (`BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES`):
- When in deployment mode, allow changing the credentials to a gem's source.
- Ex: `https://some.host.com/gems/path/` -> `https://user_name:password@some.host.com/gems/path`
-* `allow_offline_install` (`BUNDLE_ALLOW_OFFLINE_INSTALL`):
- Allow Bundler to use cached data when installing without network access.
-* `auto_clean_without_path` (`BUNDLE_AUTO_CLEAN_WITHOUT_PATH`):
- Automatically run `bundle clean` after installing when an explicit `path`
- has not been set and Bundler is not installing into the system gems.
-* `auto_install` (`BUNDLE_AUTO_INSTALL`):
- Automatically run `bundle install` when gems are missing.
-* `bin` (`BUNDLE_BIN`):
- Install executables from gems in the bundle to the specified directory.
- Defaults to `false`.
-* `cache_all` (`BUNDLE_CACHE_ALL`):
- Cache all gems, including path and git gems.
-* `cache_all_platforms` (`BUNDLE_CACHE_ALL_PLATFORMS`):
- Cache gems for all platforms.
-* `cache_path` (`BUNDLE_CACHE_PATH`):
- The directory that bundler will place cached gems in when running
- <code>bundle package</code>, and that bundler will look in when installing gems.
- Defaults to `vendor/cache`.
-* `clean` (`BUNDLE_CLEAN`):
- Whether Bundler should run `bundle clean` automatically after
- `bundle install`.
-* `console` (`BUNDLE_CONSOLE`):
- The console that `bundle console` starts. Defaults to `irb`.
-* `default_install_uses_path` (`BUNDLE_DEFAULT_INSTALL_USES_PATH`):
- Whether a `bundle install` without an explicit `--path` argument defaults
- to installing gems in `.bundle`.
-* `deployment` (`BUNDLE_DEPLOYMENT`):
- Disallow changes to the `Gemfile`. When the `Gemfile` is changed and the
- lockfile has not been updated, running Bundler commands will be blocked.
-* `disable_checksum_validation` (`BUNDLE_DISABLE_CHECKSUM_VALIDATION`):
- Allow installing gems even if they do not match the checksum provided by
- RubyGems.
-* `disable_exec_load` (`BUNDLE_DISABLE_EXEC_LOAD`):
- Stop Bundler from using `load` to launch an executable in-process in
- `bundle exec`.
-* `disable_local_branch_check` (`BUNDLE_DISABLE_LOCAL_BRANCH_CHECK`):
- Allow Bundler to use a local git override without a branch specified in the
- Gemfile.
-* `disable_multisource` (`BUNDLE_DISABLE_MULTISOURCE`):
- When set, Gemfiles containing multiple sources will produce errors
- instead of warnings.
- Use `bundle config unset disable_multisource` to unset.
-* `disable_platform_warnings` (`BUNDLE_DISABLE_PLATFORM_WARNINGS`):
- Disable warnings during bundle install when a dependency is unused on the current platform.
-* `disable_shared_gems` (`BUNDLE_DISABLE_SHARED_GEMS`):
- Stop Bundler from accessing gems installed to RubyGems' normal location.
-* `disable_version_check` (`BUNDLE_DISABLE_VERSION_CHECK`):
- Stop Bundler from checking if a newer Bundler version is available on
- rubygems.org.
-* `force_ruby_platform` (`BUNDLE_FORCE_RUBY_PLATFORM`):
- Ignore the current machine's platform and install only `ruby` platform gems.
- As a result, gems with native extensions will be compiled from source.
-* `frozen` (`BUNDLE_FROZEN`):
- Disallow changes to the `Gemfile`. When the `Gemfile` is changed and the
- lockfile has not been updated, running Bundler commands will be blocked.
- Defaults to `true` when `--deployment` is used.
-* `gem.push_key` (`BUNDLE_GEM__PUSH_KEY`):
- Sets the `--key` parameter for `gem push` when using the `rake release`
- command with a private gemstash server.
-* `gemfile` (`BUNDLE_GEMFILE`):
- The name of the file that bundler should use as the `Gemfile`. This location
- of this file also sets the root of the project, which is used to resolve
- relative paths in the `Gemfile`, among other things. By default, bundler
- will search up from the current working directory until it finds a
- `Gemfile`.
-* `global_gem_cache` (`BUNDLE_GLOBAL_GEM_CACHE`):
- Whether Bundler should cache all gems globally, rather than locally to the
- installing Ruby installation.
-* `ignore_messages` (`BUNDLE_IGNORE_MESSAGES`): When set, no post install
- messages will be printed. To silence a single gem, use dot notation like
- `ignore_messages.httparty true`.
-* `init_gems_rb` (`BUNDLE_INIT_GEMS_RB`)
- Generate a `gems.rb` instead of a `Gemfile` when running `bundle init`.
-* `jobs` (`BUNDLE_JOBS`):
- The number of gems Bundler can install in parallel. Defaults to 1.
-* `no_install` (`BUNDLE_NO_INSTALL`):
- Whether `bundle package` should skip installing gems.
-* `no_prune` (`BUNDLE_NO_PRUNE`):
- Whether Bundler should leave outdated gems unpruned when caching.
-* `only_update_to_newer_versions` (`BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS`):
- During `bundle update`, only resolve to newer versions of the gems in the
- lockfile.
-* `path` (`BUNDLE_PATH`):
- The location on disk where all gems in your bundle will be located regardless
- of `$GEM_HOME` or `$GEM_PATH` values. Bundle gems not found in this location
- will be installed by `bundle install`. Defaults to `Gem.dir`. When --deployment
- is used, defaults to vendor/bundle.
-* `path.system` (`BUNDLE_PATH__SYSTEM`):
- Whether Bundler will install gems into the default system path (`Gem.dir`).
-* `path_relative_to_cwd` (`BUNDLE_PATH_RELATIVE_TO_CWD`)
- Makes `--path` relative to the CWD instead of the `Gemfile`.
-* `plugins` (`BUNDLE_PLUGINS`):
- Enable Bundler's experimental plugin system.
-* `prefer_patch` (BUNDLE_PREFER_PATCH):
- Prefer updating only to next patch version during updates. Makes `bundle update` calls equivalent to `bundler update --patch`.
-* `print_only_version_number` (`BUNDLE_PRINT_ONLY_VERSION_NUMBER`)
- Print only version number from `bundler --version`.
-* `redirect` (`BUNDLE_REDIRECT`):
- The number of redirects allowed for network requests. Defaults to `5`.
-* `retry` (`BUNDLE_RETRY`):
- The number of times to retry failed network requests. Defaults to `3`.
-* `setup_makes_kernel_gem_public` (`BUNDLE_SETUP_MAKES_KERNEL_GEM_PUBLIC`):
- Have `Bundler.setup` make the `Kernel#gem` method public, even though
- RubyGems declares it as private.
-* `shebang` (`BUNDLE_SHEBANG`):
- The program name that should be invoked for generated binstubs. Defaults to
- the ruby install name used to generate the binstub.
-* `silence_deprecations` (`BUNDLE_SILENCE_DEPRECATIONS`):
- Whether Bundler should silence deprecation warnings for behavior that will
- be changed in the next major version.
-* `silence_root_warning` (`BUNDLE_SILENCE_ROOT_WARNING`):
- Silence the warning Bundler prints when installing gems as root.
-* `skip_default_git_sources` (`BUNDLE_SKIP_DEFAULT_GIT_SOURCES`):
- Whether Bundler should skip adding default git source shortcuts to the
- Gemfile DSL.
-* `specific_platform` (`BUNDLE_SPECIFIC_PLATFORM`):
- Allow bundler to resolve for the specific running platform and store it in
- the lockfile, instead of only using a generic platform.
- A specific platform is the exact platform triple reported by
- `Gem::Platform.local`, such as `x86_64-darwin-16` or `universal-java-1.8`.
- On the other hand, generic platforms are those such as `ruby`, `mswin`, or
- `java`. In this example, `x86_64-darwin-16` would map to `ruby` and
- `universal-java-1.8` to `java`.
-* `ssl_ca_cert` (`BUNDLE_SSL_CA_CERT`):
- Path to a designated CA certificate file or folder containing multiple
- certificates for trusted CAs in PEM format.
-* `ssl_client_cert` (`BUNDLE_SSL_CLIENT_CERT`):
- Path to a designated file containing a X.509 client certificate
- and key in PEM format.
-* `ssl_verify_mode` (`BUNDLE_SSL_VERIFY_MODE`):
- The SSL verification mode Bundler uses when making HTTPS requests.
- Defaults to verify peer.
-* `suppress_install_using_messages` (`BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES`):
- Avoid printing `Using ...` messages during installation when the version of
- a gem has not changed.
-* `system_bindir` (`BUNDLE_SYSTEM_BINDIR`):
- The location where RubyGems installs binstubs. Defaults to `Gem.bindir`.
-* `timeout` (`BUNDLE_TIMEOUT`):
- The seconds allowed before timing out for network requests. Defaults to `10`.
-* `unlock_source_unlocks_spec` (`BUNDLE_UNLOCK_SOURCE_UNLOCKS_SPEC`):
- Whether running `bundle update --source NAME` unlocks a gem with the given
- name. Defaults to `true`.
-* `update_requires_all_flag` (`BUNDLE_UPDATE_REQUIRES_ALL_FLAG`)
- Require passing `--all` to `bundle update` when everything should be updated,
- and disallow passing no options to `bundle update`.
-* `user_agent` (`BUNDLE_USER_AGENT`):
- The custom user agent fragment Bundler includes in API requests.
-* `with` (`BUNDLE_WITH`):
- A `:`-separated list of groups whose gems bundler should install.
-* `without` (`BUNDLE_WITHOUT`):
- A `:`-separated list of groups whose gems bundler should not install.
-
-In general, you should set these settings per-application by using the applicable
-flag to the [bundle install(1)](bundle-install.1.html) or [bundle package(1)](bundle-package.1.html) command.
-
-You can set them globally either via environment variables or `bundle config`,
-whichever is preferable for your setup. If you use both, environment variables
-will take preference over global settings.
-
-## LOCAL GIT REPOS
-
-Bundler also allows you to work against a git repository locally
-instead of using the remote version. This can be achieved by setting
-up a local override:
-
- bundle config set local.GEM_NAME /path/to/local/git/repository
-
-For example, in order to use a local Rack repository, a developer could call:
-
- bundle config set local.rack ~/Work/git/rack
-
-Now instead of checking out the remote git repository, the local
-override will be used. Similar to a path source, every time the local
-git repository change, changes will be automatically picked up by
-Bundler. This means a commit in the local git repo will update the
-revision in the `Gemfile.lock` to the local git repo revision. This
-requires the same attention as git submodules. Before pushing to
-the remote, you need to ensure the local override was pushed, otherwise
-you may point to a commit that only exists in your local machine.
-You'll also need to CGI escape your usernames and passwords as well.
-
-Bundler does many checks to ensure a developer won't work with
-invalid references. Particularly, we force a developer to specify
-a branch in the `Gemfile` in order to use this feature. If the branch
-specified in the `Gemfile` and the current branch in the local git
-repository do not match, Bundler will abort. This ensures that
-a developer is always working against the correct branches, and prevents
-accidental locking to a different branch.
-
-Finally, Bundler also ensures that the current revision in the
-`Gemfile.lock` exists in the local git repository. By doing this, Bundler
-forces you to fetch the latest changes in the remotes.
-
-## MIRRORS OF GEM SOURCES
-
-Bundler supports overriding gem sources with mirrors. This allows you to
-configure rubygems.org as the gem source in your Gemfile while still using your
-mirror to fetch gems.
-
- bundle config set mirror.SOURCE_URL MIRROR_URL
-
-For example, to use a mirror of rubygems.org hosted at rubygems-mirror.org:
-
- bundle config set mirror.http://rubygems.org http://rubygems-mirror.org
-
-Each mirror also provides a fallback timeout setting. If the mirror does not
-respond within the fallback timeout, Bundler will try to use the original
-server instead of the mirror.
-
- bundle config set mirror.SOURCE_URL.fallback_timeout TIMEOUT
-
-For example, to fall back to rubygems.org after 3 seconds:
-
- bundle config set mirror.https://rubygems.org.fallback_timeout 3
-
-The default fallback timeout is 0.1 seconds, but the setting can currently
-only accept whole seconds (for example, 1, 15, or 30).
-
-## CREDENTIALS FOR GEM SOURCES
-
-Bundler allows you to configure credentials for any gem source, which allows
-you to avoid putting secrets into your Gemfile.
-
- bundle config set SOURCE_HOSTNAME USERNAME:PASSWORD
-
-For example, to save the credentials of user `claudette` for the gem source at
-`gems.longerous.com`, you would run:
-
- bundle config set gems.longerous.com claudette:s00pers3krit
-
-Or you can set the credentials as an environment variable like this:
-
- export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit"
-
-For gems with a git source with HTTP(S) URL you can specify credentials like so:
-
- bundle config set https://github.com/bundler/bundler.git username:password
-
-Or you can set the credentials as an environment variable like so:
-
- export BUNDLE_GITHUB__COM=username:password
-
-This is especially useful for private repositories on hosts such as Github,
-where you can use personal OAuth tokens:
-
- export BUNDLE_GITHUB__COM=abcd0123generatedtoken:x-oauth-basic
-
-
-## CONFIGURE BUNDLER DIRECTORIES
-
-Bundler's home, config, cache and plugin directories are able to be configured
-through environment variables. The default location for Bundler's home directory is
-`~/.bundle`, which all directories inherit from by default. The following
-outlines the available environment variables and their default values
-
- BUNDLE_USER_HOME : $HOME/.bundle
- BUNDLE_USER_CACHE : $BUNDLE_USER_HOME/cache
- BUNDLE_USER_CONFIG : $BUNDLE_USER_HOME/config
- BUNDLE_USER_PLUGIN : $BUNDLE_USER_HOME/plugin
-
diff --git a/man/bundle-doctor.1 b/man/bundle-doctor.1
deleted file mode 100644
index 344c40066b..0000000000
--- a/man/bundle-doctor.1
+++ /dev/null
@@ -1,44 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-DOCTOR" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-doctor\fR \- Checks the bundle for common problems
-.
-.SH "SYNOPSIS"
-\fBbundle doctor\fR [\-\-quiet] [\-\-gemfile=GEMFILE]
-.
-.SH "DESCRIPTION"
-Checks your Gemfile and gem environment for common problems\. If issues are detected, Bundler prints them and exits status 1\. Otherwise, Bundler prints a success message and exits status 0\.
-.
-.P
-Examples of common problems caught by bundle\-doctor include:
-.
-.IP "\(bu" 4
-Invalid Bundler settings
-.
-.IP "\(bu" 4
-Mismatched Ruby versions
-.
-.IP "\(bu" 4
-Mismatched platforms
-.
-.IP "\(bu" 4
-Uninstalled gems
-.
-.IP "\(bu" 4
-Missing dependencies
-.
-.IP "" 0
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-quiet\fR
-Only output warnings and errors\.
-.
-.TP
-\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\.
-
diff --git a/man/bundle-doctor.1.txt b/man/bundle-doctor.1.txt
deleted file mode 100644
index 595ba99633..0000000000
--- a/man/bundle-doctor.1.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-BUNDLE-DOCTOR(1) BUNDLE-DOCTOR(1)
-
-
-
-NAME
- bundle-doctor - Checks the bundle for common problems
-
-SYNOPSIS
- bundle doctor [--quiet] [--gemfile=GEMFILE]
-
-DESCRIPTION
- Checks your Gemfile and gem environment for common problems. If issues
- are detected, Bundler prints them and exits status 1. Otherwise,
- Bundler prints a success message and exits status 0.
-
- Examples of common problems caught by bundle-doctor include:
-
- o Invalid Bundler settings
-
- o Mismatched Ruby versions
-
- o Mismatched platforms
-
- o Uninstalled gems
-
- o Missing dependencies
-
-
-
-OPTIONS
- --quiet
- Only output warnings and errors.
-
- --gemfile=<gemfile>
- The location of the Gemfile(5) which Bundler should use. This
- defaults to a Gemfile(5) in the current working directory. In
- general, Bundler will assume that the location of the Gemfile(5)
- is also the project's root and will try to find Gemfile.lock and
- vendor/cache relative to this location.
-
-
-
-
- January 2020 BUNDLE-DOCTOR(1)
diff --git a/man/bundle-exec.1 b/man/bundle-exec.1
deleted file mode 100644
index 555819a5b4..0000000000
--- a/man/bundle-exec.1
+++ /dev/null
@@ -1,165 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-EXEC" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-exec\fR \- Execute a command in the context of the bundle
-.
-.SH "SYNOPSIS"
-\fBbundle exec\fR [\-\-keep\-file\-descriptors] \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
-Essentially, if you would normally have run something like \fBrspec spec/my_spec\.rb\fR, and you want to use the gems specified in the [\fBGemfile(5)\fR][Gemfile(5)] and installed via bundle install(1) \fIbundle\-install\.1\.html\fR, you should run \fBbundle exec rspec spec/my_spec\.rb\fR\.
-.
-.P
-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
-Exec in Ruby 2\.0 began discarding non\-standard file descriptors\. When this flag is passed, exec will revert to the 1\.9 behaviour of passing all file descriptors to the new process\.
-.
-.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
-After using \fB\-\-binstubs\fR, \fBbin/rspec spec/my_spec\.rb\fR is identical to \fBbundle exec rspec spec/my_spec\.rb\fR\.
-.
-.SH "ENVIRONMENT MODIFICATIONS"
-\fBbundle exec\fR makes a number of changes to the shell environment, then executes the command you specify in full\.
-.
-.IP "\(bu" 4
-make sure that it\'s still possible to shell out to \fBbundle\fR from inside a command invoked by \fBbundle exec\fR (using \fB$BUNDLE_BIN_PATH\fR)
-.
-.IP "\(bu" 4
-put the directory containing executables (like \fBrails\fR, \fBrspec\fR, \fBrackup\fR) for your bundle on \fB$PATH\fR
-.
-.IP "\(bu" 4
-make sure that if bundler is invoked in the subshell, it uses the same \fBGemfile\fR (by setting \fBBUNDLE_GEMFILE\fR)
-.
-.IP "\(bu" 4
-add \fB\-rbundler/setup\fR to \fB$RUBYOPT\fR, which makes sure that Ruby programs invoked in the subshell can see the gems in the bundle
-.
-.IP "" 0
-.
-.P
-It also modifies Rubygems:
-.
-.IP "\(bu" 4
-disallow loading additional gems not in the bundle
-.
-.IP "\(bu" 4
-modify the \fBgem\fR method to be a no\-op if a gem matching the requirements is in the bundle, and to raise a \fBGem::LoadError\fR if it\'s not
-.
-.IP "\(bu" 4
-Define \fBGem\.refresh\fR to be a no\-op, since the source index is always frozen when using bundler, and to prevent gems from the system leaking into the environment
-.
-.IP "\(bu" 4
-Override \fBGem\.bin_path\fR to use the gems in the bundle, making system executables work
-.
-.IP "\(bu" 4
-Add all gems in the bundle into Gem\.loaded_specs
-.
-.IP "" 0
-.
-.P
-Finally, \fBbundle exec\fR also implicitly modifies \fBGemfile\.lock\fR if the lockfile and the Gemfile do not match\. Bundler needs the Gemfile to determine things such as a gem\'s groups, \fBautorequire\fR, and platforms, etc\., and that information isn\'t stored in the lockfile\. The Gemfile and lockfile must be synced in order to \fBbundle exec\fR successfully, so \fBbundle exec\fR updates the lockfile beforehand\.
-.
-.SS "Loading"
-By default, when attempting to \fBbundle exec\fR to a file with a ruby shebang, Bundler will \fBKernel\.load\fR that file instead of using \fBKernel\.exec\fR\. For the vast majority of cases, this is a performance improvement\. In a rare few cases, this could cause some subtle side\-effects (such as dependence on the exact contents of \fB$0\fR or \fB__FILE__\fR) and the optimization can be disabled by enabling the \fBdisable_exec_load\fR setting\.
-.
-.SS "Shelling out"
-Any Ruby code that opens a subshell (like \fBsystem\fR, backticks, or \fB%x{}\fR) will automatically use the current Bundler environment\. If you need to shell out to a Ruby command that is not part of your current bundle, use the \fBwith_clean_env\fR method with a block\. Any subshells created inside the block will be given the environment present before Bundler was activated\. For example, Homebrew commands run Ruby, but don\'t work inside a bundle:
-.
-.IP "" 4
-.
-.nf
-
-Bundler\.with_clean_env do
- `brew install wget`
-end
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Using \fBwith_clean_env\fR is also necessary if you are shelling out to a different bundle\. Any Bundler commands run in a subshell will inherit the current Gemfile, so commands that need to run in the context of a different bundle also need to use \fBwith_clean_env\fR\.
-.
-.IP "" 4
-.
-.nf
-
-Bundler\.with_clean_env do
- Dir\.chdir "/other/bundler/project" do
- `bundle exec \./script`
- end
-end
-.
-.fi
-.
-.IP "" 0
-.
-.P
-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\')
-.
-.fi
-.
-.IP "" 0
-.
-.SH "RUBYGEMS PLUGINS"
-At present, the Rubygems plugin system requires all files named \fBrubygems_plugin\.rb\fR on the load path of \fIany\fR installed gem when any Ruby code requires \fBrubygems\.rb\fR\. This includes executables installed into the system, like \fBrails\fR, \fBrackup\fR, and \fBrspec\fR\.
-.
-.P
-Since Rubygems plugins can contain arbitrary Ruby code, they commonly end up activating themselves or their dependencies\.
-.
-.P
-For instance, the \fBgemcutter 0\.5\fR gem depended on \fBjson_pure\fR\. If you had that version of gemcutter installed (even if you \fIalso\fR had a newer version without this problem), Rubygems would activate \fBgemcutter 0\.5\fR and \fBjson_pure <latest>\fR\.
-.
-.P
-If your Gemfile(5) also contained \fBjson_pure\fR (or a gem with a dependency on \fBjson_pure\fR), the latest version on your system might conflict with the version in your Gemfile(5), or the snapshot version in your \fBGemfile\.lock\fR\.
-.
-.P
-If this happens, bundler will say:
-.
-.IP "" 4
-.
-.nf
-
-You have already activated json_pure 1\.4\.6 but your Gemfile
-requires json_pure 1\.4\.3\. Consider using bundle exec\.
-.
-.fi
-.
-.IP "" 0
-.
-.P
-In this situation, you almost certainly want to remove the underlying gem with the problematic gem plugin\. In general, the authors of these plugins (in this case, the \fBgemcutter\fR gem) have released newer versions that are more careful in their plugins\.
-.
-.P
-You can find a list of all the gems containing gem plugins by running
-.
-.IP "" 4
-.
-.nf
-
-ruby \-rrubygems \-e "puts Gem\.find_files(\'rubygems_plugin\.rb\')"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-At the very least, you should remove all but the newest version of each gem plugin, and also remove all gem plugins that you aren\'t using (\fBgem uninstall gem_name\fR)\.
diff --git a/man/bundle-exec.1.txt b/man/bundle-exec.1.txt
deleted file mode 100644
index ebdc2fda71..0000000000
--- a/man/bundle-exec.1.txt
+++ /dev/null
@@ -1,178 +0,0 @@
-BUNDLE-EXEC(1) BUNDLE-EXEC(1)
-
-
-
-NAME
- bundle-exec - Execute a command in the context of the bundle
-
-SYNOPSIS
- bundle exec [--keep-file-descriptors] command
-
-DESCRIPTION
- This command executes the command, making all gems specified in the
- [Gemfile(5)][Gemfile(5)] available to require in Ruby programs.
-
- Essentially, if you would normally have run something like rspec
- spec/my_spec.rb, and you want to use the gems specified in the [Gem-
- file(5)][Gemfile(5)] and installed via bundle install(1) bun-
- dle-install.1.html, you should run bundle exec rspec spec/my_spec.rb.
-
- Note that bundle exec does not require that an executable is available
- on your shell's $PATH.
-
-OPTIONS
- --keep-file-descriptors
- Exec in Ruby 2.0 began discarding non-standard file descriptors.
- When this flag is passed, exec will revert to the 1.9 behaviour
- of passing all file descriptors to the new process.
-
-BUNDLE INSTALL --BINSTUBS
- If you use the --binstubs flag in bundle install(1) bun-
- dle-install.1.html, Bundler will automatically create a directory
- (which defaults to app_root/bin) containing all of the executables
- available from gems in the bundle.
-
- After using --binstubs, bin/rspec spec/my_spec.rb is identical to bun-
- dle exec rspec spec/my_spec.rb.
-
-ENVIRONMENT MODIFICATIONS
- bundle exec makes a number of changes to the shell environment, then
- executes the command you specify in full.
-
- o make sure that it's still possible to shell out to bundle from
- inside a command invoked by bundle exec (using $BUNDLE_BIN_PATH)
-
- o put the directory containing executables (like rails, rspec,
- rackup) for your bundle on $PATH
-
- o make sure that if bundler is invoked in the subshell, it uses the
- same Gemfile (by setting BUNDLE_GEMFILE)
-
- o add -rbundler/setup to $RUBYOPT, which makes sure that Ruby pro-
- grams invoked in the subshell can see the gems in the bundle
-
-
-
- It also modifies Rubygems:
-
- o disallow loading additional gems not in the bundle
-
- o modify the gem method to be a no-op if a gem matching the require-
- ments is in the bundle, and to raise a Gem::LoadError if it's not
-
- o Define Gem.refresh to be a no-op, since the source index is always
- frozen when using bundler, and to prevent gems from the system
- leaking into the environment
-
- o Override Gem.bin_path to use the gems in the bundle, making system
- executables work
-
- o Add all gems in the bundle into Gem.loaded_specs
-
-
-
- Finally, bundle exec also implicitly modifies Gemfile.lock if the lock-
- file and the Gemfile do not match. Bundler needs the Gemfile to deter-
- mine things such as a gem's groups, autorequire, and platforms, etc.,
- and that information isn't stored in the lockfile. The Gemfile and
- lockfile must be synced in order to bundle exec successfully, so bundle
- exec updates the lockfile beforehand.
-
- Loading
- By default, when attempting to bundle exec to a file with a ruby she-
- bang, Bundler will Kernel.load that file instead of using Kernel.exec.
- For the vast majority of cases, this is a performance improvement. In a
- rare few cases, this could cause some subtle side-effects (such as
- dependence on the exact contents of $0 or __FILE__) and the optimiza-
- tion can be disabled by enabling the disable_exec_load setting.
-
- Shelling out
- Any Ruby code that opens a subshell (like system, backticks, or %x{})
- will automatically use the current Bundler environment. If you need to
- shell out to a Ruby command that is not part of your current bundle,
- use the with_clean_env method with a block. Any subshells created
- inside the block will be given the environment present before Bundler
- was activated. For example, Homebrew commands run Ruby, but don't work
- inside a bundle:
-
-
-
- Bundler.with_clean_env do
- `brew install wget`
- end
-
-
-
- Using with_clean_env is also necessary if you are shelling out to a
- different bundle. Any Bundler commands run in a subshell will inherit
- the current Gemfile, so commands that need to run in the context of a
- different bundle also need to use with_clean_env.
-
-
-
- Bundler.with_clean_env do
- Dir.chdir "/other/bundler/project" do
- `bundle exec ./script`
- end
- end
-
-
-
- Bundler provides convenience helpers that wrap system and exec, and
- they can be used like this:
-
-
-
- Bundler.clean_system('brew install wget')
- Bundler.clean_exec('brew install wget')
-
-
-
-RUBYGEMS PLUGINS
- At present, the Rubygems plugin system requires all files named
- rubygems_plugin.rb on the load path of any installed gem when any Ruby
- code requires rubygems.rb. This includes executables installed into the
- system, like rails, rackup, and rspec.
-
- Since Rubygems plugins can contain arbitrary Ruby code, they commonly
- end up activating themselves or their dependencies.
-
- For instance, the gemcutter 0.5 gem depended on json_pure. If you had
- that version of gemcutter installed (even if you also had a newer ver-
- sion without this problem), Rubygems would activate gemcutter 0.5 and
- json_pure <latest>.
-
- If your Gemfile(5) also contained json_pure (or a gem with a dependency
- on json_pure), the latest version on your system might conflict with
- the version in your Gemfile(5), or the snapshot version in your Gem-
- file.lock.
-
- If this happens, bundler will say:
-
-
-
- You have already activated json_pure 1.4.6 but your Gemfile
- requires json_pure 1.4.3. Consider using bundle exec.
-
-
-
- In this situation, you almost certainly want to remove the underlying
- gem with the problematic gem plugin. In general, the authors of these
- plugins (in this case, the gemcutter gem) have released newer versions
- that are more careful in their plugins.
-
- You can find a list of all the gems containing gem plugins by running
-
-
-
- ruby -rrubygems -e "puts Gem.find_files('rubygems_plugin.rb')"
-
-
-
- At the very least, you should remove all but the newest version of each
- gem plugin, and also remove all gem plugins that you aren't using (gem
- uninstall gem_name).
-
-
-
- January 2020 BUNDLE-EXEC(1)
diff --git a/man/bundle-gem.1 b/man/bundle-gem.1
deleted file mode 100644
index baed185e70..0000000000
--- a/man/bundle-gem.1
+++ /dev/null
@@ -1,80 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-GEM" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
-.
-.SH "SYNOPSIS"
-\fBbundle gem\fR \fIGEM_NAME\fR \fIOPTIONS\fR
-.
-.SH "DESCRIPTION"
-Generates a directory named \fBGEM_NAME\fR with a \fBRakefile\fR, \fBGEM_NAME\.gemspec\fR, and other supporting files and directories that can be used to develop a rubygem with that name\.
-.
-.P
-Run \fBrake \-T\fR in the resulting project for a list of Rake tasks that can be used to test and publish the gem to rubygems\.org\.
-.
-.P
-The generated project skeleton can be customized with OPTIONS, as explained below\. Note that these options can also be specified via Bundler\'s global configuration file using the following names:
-.
-.IP "\(bu" 4
-\fBgem\.coc\fR
-.
-.IP "\(bu" 4
-\fBgem\.mit\fR
-.
-.IP "\(bu" 4
-\fBgem\.test\fR
-.
-.IP "" 0
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-exe\fR or \fB\-b\fR or \fB\-\-bin\fR
-Specify that Bundler should create a binary executable (as \fBexe/GEM_NAME\fR) in the generated rubygem project\. This binary will also be added to the \fBGEM_NAME\.gemspec\fR manifest\. This behavior is disabled by default\.
-.
-.TP
-\fB\-\-no\-exe\fR
-Do not create a binary (overrides \fB\-\-exe\fR specified in the global config)\.
-.
-.TP
-\fB\-\-coc\fR
-Add a \fBCODE_OF_CONDUCT\.md\fR file to the root of the generated project\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
-.
-.TP
-\fB\-\-no\-coc\fR
-Do not create a \fBCODE_OF_CONDUCT\.md\fR (overrides \fB\-\-coc\fR specified in the global config)\.
-.
-.TP
-\fB\-\-ext\fR
-Add boilerplate for C extension code to the generated project\. This behavior is disabled by default\.
-.
-.TP
-\fB\-\-no\-ext\fR
-Do not add C extension code (overrides \fB\-\-ext\fR specified in the global config)\.
-.
-.TP
-\fB\-\-mit\fR
-Add an MIT license to a \fBLICENSE\.txt\fR file in the root of the generated project\. Your name from the global git config is used for the copyright statement\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\.
-.
-.TP
-\fB\-\-no\-mit\fR
-Do not create a \fBLICENSE\.txt\fR (overrides \fB\-\-mit\fR specified in the global config)\.
-.
-.TP
-\fB\-t\fR, \fB\-\-test=minitest\fR, \fB\-\-test=rspec\fR
-Specify the test framework that Bundler should use when generating the project\. Acceptable values are \fBminitest\fR and \fBrspec\fR\. The \fBGEM_NAME\.gemspec\fR will be configured and a skeleton test/spec directory will be created based on this option\. If this option is unspecified, an interactive prompt will be displayed and the answer will be saved in Bundler\'s global config for future \fBbundle gem\fR use\. If no option is specified, the default testing framework is RSpec\.
-.
-.TP
-\fB\-e\fR, \fB\-\-edit[=EDITOR]\fR
-Open the resulting GEM_NAME\.gemspec in EDITOR, or the default editor if not specified\. The default is \fB$BUNDLER_EDITOR\fR, \fB$VISUAL\fR, or \fB$EDITOR\fR\.
-.
-.SH "SEE ALSO"
-.
-.IP "\(bu" 4
-bundle config(1) \fIbundle\-config\.1\.html\fR
-.
-.IP "" 0
-
diff --git a/man/bundle-gem.1.txt b/man/bundle-gem.1.txt
deleted file mode 100644
index 554bb1a41b..0000000000
--- a/man/bundle-gem.1.txt
+++ /dev/null
@@ -1,91 +0,0 @@
-BUNDLE-GEM(1) BUNDLE-GEM(1)
-
-
-
-NAME
- bundle-gem - Generate a project skeleton for creating a rubygem
-
-SYNOPSIS
- bundle gem GEM_NAME OPTIONS
-
-DESCRIPTION
- Generates a directory named GEM_NAME with a Rakefile, GEM_NAME.gemspec,
- and other supporting files and directories that can be used to develop
- a rubygem with that name.
-
- Run rake -T in the resulting project for a list of Rake tasks that can
- be used to test and publish the gem to rubygems.org.
-
- The generated project skeleton can be customized with OPTIONS, as
- explained below. Note that these options can also be specified via
- Bundler's global configuration file using the following names:
-
- o gem.coc
-
- o gem.mit
-
- o gem.test
-
-
-
-OPTIONS
- --exe or -b or --bin
- Specify that Bundler should create a binary executable (as
- exe/GEM_NAME) in the generated rubygem project. This binary will
- also be added to the GEM_NAME.gemspec manifest. This behavior is
- disabled by default.
-
- --no-exe
- Do not create a binary (overrides --exe specified in the global
- config).
-
- --coc Add a CODE_OF_CONDUCT.md file to the root of the generated
- project. If this option is unspecified, an interactive prompt
- will be displayed and the answer will be saved in Bundler's
- global config for future bundle gem use.
-
- --no-coc
- Do not create a CODE_OF_CONDUCT.md (overrides --coc specified in
- the global config).
-
- --ext Add boilerplate for C extension code to the generated project.
- This behavior is disabled by default.
-
- --no-ext
- Do not add C extension code (overrides --ext specified in the
- global config).
-
- --mit Add an MIT license to a LICENSE.txt file in the root of the gen-
- erated project. Your name from the global git config is used for
- the copyright statement. If this option is unspecified, an
- interactive prompt will be displayed and the answer will be
- saved in Bundler's global config for future bundle gem use.
-
- --no-mit
- Do not create a LICENSE.txt (overrides --mit specified in the
- global config).
-
- -t, --test=minitest, --test=rspec
- Specify the test framework that Bundler should use when generat-
- ing the project. Acceptable values are minitest and rspec. The
- GEM_NAME.gemspec will be configured and a skeleton test/spec
- directory will be created based on this option. If this option
- is unspecified, an interactive prompt will be displayed and the
- answer will be saved in Bundler's global config for future bun-
- dle gem use. If no option is specified, the default testing
- framework is RSpec.
-
- -e, --edit[=EDITOR]
- Open the resulting GEM_NAME.gemspec in EDITOR, or the default
- editor if not specified. The default is $BUNDLER_EDITOR, $VIS-
- UAL, or $EDITOR.
-
-SEE ALSO
- o bundle config(1) bundle-config.1.html
-
-
-
-
-
-
- January 2020 BUNDLE-GEM(1)
diff --git a/man/bundle-gem.ronn b/man/bundle-gem.ronn
deleted file mode 100644
index cf3d037df2..0000000000
--- a/man/bundle-gem.ronn
+++ /dev/null
@@ -1,78 +0,0 @@
-bundle-gem(1) -- Generate a project skeleton for creating a rubygem
-====================================================================
-
-## SYNOPSIS
-
-`bundle gem` <GEM_NAME> [OPTIONS]
-
-## DESCRIPTION
-
-Generates a directory named `GEM_NAME` with a `Rakefile`, `GEM_NAME.gemspec`,
-and other supporting files and directories that can be used to develop a
-rubygem with that name.
-
-Run `rake -T` in the resulting project for a list of Rake tasks that can be used
-to test and publish the gem to rubygems.org.
-
-The generated project skeleton can be customized with OPTIONS, as explained
-below. Note that these options can also be specified via Bundler's global
-configuration file using the following names:
-
-* `gem.coc`
-* `gem.mit`
-* `gem.test`
-
-## OPTIONS
-
-* `--exe` or `-b` or `--bin`:
- Specify that Bundler should create a binary executable (as `exe/GEM_NAME`)
- in the generated rubygem project. This binary will also be added to the
- `GEM_NAME.gemspec` manifest. This behavior is disabled by default.
-
-* `--no-exe`:
- Do not create a binary (overrides `--exe` specified in the global config).
-
-* `--coc`:
- Add a `CODE_OF_CONDUCT.md` file to the root of the generated project. If
- this option is unspecified, an interactive prompt will be displayed and the
- answer will be saved in Bundler's global config for future `bundle gem` use.
-
-* `--no-coc`:
- Do not create a `CODE_OF_CONDUCT.md` (overrides `--coc` specified in the
- global config).
-
-* `--ext`:
- Add boilerplate for C extension code to the generated project. This behavior
- is disabled by default.
-
-* `--no-ext`:
- Do not add C extension code (overrides `--ext` specified in the global
- config).
-
-* `--mit`:
- Add an MIT license to a `LICENSE.txt` file in the root of the generated
- project. Your name from the global git config is used for the copyright
- statement. If this option is unspecified, an interactive prompt will be
- displayed and the answer will be saved in Bundler's global config for future
- `bundle gem` use.
-
-* `--no-mit`:
- Do not create a `LICENSE.txt` (overrides `--mit` specified in the global
- config).
-
-* `-t`, `--test=minitest`, `--test=rspec`:
- Specify the test framework that Bundler should use when generating the
- project. Acceptable values are `minitest` and `rspec`. The `GEM_NAME.gemspec`
- will be configured and a skeleton test/spec directory will be created based
- on this option. If this option is unspecified, an interactive prompt will be
- displayed and the answer will be saved in Bundler's global config for future
- `bundle gem` use.
- If no option is specified, the default testing framework is RSpec.
-
-* `-e`, `--edit[=EDITOR]`:
- Open the resulting GEM_NAME.gemspec in EDITOR, or the default editor if not
- specified. The default is `$BUNDLER_EDITOR`, `$VISUAL`, or `$EDITOR`.
-
-## SEE ALSO
-
-* [bundle config(1)](bundle-config.1.html)
diff --git a/man/bundle-info.1 b/man/bundle-info.1
deleted file mode 100644
index d7c73e9bb7..0000000000
--- a/man/bundle-info.1
+++ /dev/null
@@ -1,20 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-INFO" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-info\fR \- Show information for the given gem in your bundle
-.
-.SH "SYNOPSIS"
-\fBbundle info\fR [GEM] [\-\-path]
-.
-.SH "DESCRIPTION"
-Print the basic information about the provided GEM such as homepage, version, path and summary\.
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-path\fR
-Print the path of the given gem
-
diff --git a/man/bundle-info.1.txt b/man/bundle-info.1.txt
deleted file mode 100644
index 67563aa191..0000000000
--- a/man/bundle-info.1.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-BUNDLE-INFO(1) BUNDLE-INFO(1)
-
-
-
-NAME
- bundle-info - Show information for the given gem in your bundle
-
-SYNOPSIS
- bundle info [GEM] [--path]
-
-DESCRIPTION
- Print the basic information about the provided GEM such as homepage,
- version, path and summary.
-
-OPTIONS
- --path Print the path of the given gem
-
-
-
-
- January 2020 BUNDLE-INFO(1)
diff --git a/man/bundle-init.1 b/man/bundle-init.1
deleted file mode 100644
index 803d4b9be8..0000000000
--- a/man/bundle-init.1
+++ /dev/null
@@ -1,25 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-INIT" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
-.
-.SH "SYNOPSIS"
-\fBbundle init\fR [\-\-gemspec=FILE]
-.
-.SH "DESCRIPTION"
-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
-Use the specified \.gemspec to create the [\fBGemfile(5)\fR][Gemfile(5)]
-.
-.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\.
-.
-.SH "SEE ALSO"
-Gemfile(5) \fIhttps://bundler\.io/man/gemfile\.5\.html\fR
diff --git a/man/bundle-init.1.txt b/man/bundle-init.1.txt
deleted file mode 100644
index 2565edbece..0000000000
--- a/man/bundle-init.1.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-BUNDLE-INIT(1) BUNDLE-INIT(1)
-
-
-
-NAME
- bundle-init - Generates a Gemfile into the current working directory
-
-SYNOPSIS
- bundle init [--gemspec=FILE]
-
-DESCRIPTION
- Init generates a default [Gemfile(5)][Gemfile(5)] in the current work-
- ing directory. When adding a [Gemfile(5)][Gemfile(5)] to a gem with a
- gemspec, the --gemspec option will automatically add each dependency
- listed in the gemspec file to the newly created [Gemfile(5)][Gem-
- file(5)].
-
-OPTIONS
- --gemspec
- Use the specified .gemspec to create the [Gemfile(5)][Gem-
- file(5)]
-
-FILES
- Included in the default [Gemfile(5)][Gemfile(5)] generated is the line
- # frozen_string_literal: true. This is a magic comment supported for
- the first time in Ruby 2.3. The presence of this line results in all
- string literals in the file being implicitly frozen.
-
-SEE ALSO
- Gemfile(5) https://bundler.io/man/gemfile.5.html
-
-
-
- January 2020 BUNDLE-INIT(1)
diff --git a/man/bundle-inject.1 b/man/bundle-inject.1
deleted file mode 100644
index 3370a91573..0000000000
--- a/man/bundle-inject.1
+++ /dev/null
@@ -1,33 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-INJECT" "1" "January 2020" "" ""
-.
-.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
diff --git a/man/bundle-inject.1.txt b/man/bundle-inject.1.txt
deleted file mode 100644
index 4707b99e5f..0000000000
--- a/man/bundle-inject.1.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-BUNDLE-INJECT(1) BUNDLE-INJECT(1)
-
-
-
-NAME
- bundle-inject - Add named gem(s) with version requirements to Gemfile
-
-SYNOPSIS
- bundle inject [GEM] [VERSION]
-
-DESCRIPTION
- Adds the named gem(s) with their version requirements to the resolved
- [Gemfile(5)][Gemfile(5)].
-
- This command will add the gem to both your [Gemfile(5)][Gemfile(5)] and
- Gemfile.lock if it isn't listed yet.
-
- Example:
-
-
-
- bundle install
- bundle inject 'rack' '> 0'
-
-
-
- This will inject the 'rack' gem with a version greater than 0 in your
- [Gemfile(5)][Gemfile(5)] and Gemfile.lock
-
-
-
- January 2020 BUNDLE-INJECT(1)
diff --git a/man/bundle-install.1 b/man/bundle-install.1
deleted file mode 100644
index 4a289f5c2e..0000000000
--- a/man/bundle-install.1
+++ /dev/null
@@ -1,311 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-INSTALL" "1" "January 2020" "" ""
-.
-.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] [\-\-quiet] [\-\-redownload] [\-\-retry=NUMBER] [\-\-shebang] [\-\-standalone[=GROUP[ GROUP\.\.\.]]] [\-\-system] [\-\-trust\-policy=POLICY] [\-\-with=GROUP[ GROUP\.\.\.]] [\-\-without=GROUP[ GROUP\.\.\.]]
-.
-.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
-If a \fBGemfile\.lock\fR does exist, and you have not updated your Gemfile(5), Bundler will fetch all remote sources, but use the dependencies specified in the \fBGemfile\.lock\fR instead of resolving dependencies\.
-.
-.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"
-To apply any of \fB\-\-binstubs\fR, \fB\-\-deployment\fR, \fB\-\-path\fR, or \fB\-\-without\fR every time \fBbundle install\fR is run, use \fBbundle config\fR (see bundle\-config(1))\.
-.
-.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\.
-.
-.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\.
-.
-.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\.
-.
-.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
-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
-The maximum number of parallel download and install jobs\. The default is \fB1\fR\.
-.
-.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\-\-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\.
-.
-.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\.
-.
-.TP
-\fB\-\-quiet\fR
-Do not print progress information to the standard output\. Instead, Bundler will exit using a status code (\fB$?\fR)\.
-.
-.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\.
-.
-.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]\.
-.
-.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\.
-.
-.TP
-\fB\-\-trust\-policy=[<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\.
-.
-.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\.
-.
-.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\.
-.
-.IP "1." 4
-A \fBGemfile\.lock\fR is required\.
-.
-.IP
-To ensure that the same versions of the gems you developed with and tested with are also used in deployments, a \fBGemfile\.lock\fR is required\.
-.
-.IP
-This is mainly to ensure that you remember to check your \fBGemfile\.lock\fR into version control\.
-.
-.IP "2." 4
-The \fBGemfile\.lock\fR must be up to date
-.
-.IP
-In development, you can modify your Gemfile(5) and re\-run \fBbundle install\fR to \fIconservatively update\fR your \fBGemfile\.lock\fR snapshot\.
-.
-.IP
-In deployment, your \fBGemfile\.lock\fR should be up\-to\-date with changes made in your Gemfile(5)\.
-.
-.IP "3." 4
-Gems are installed to \fBvendor/bundle\fR not your default system location
-.
-.IP
-In development, it\'s convenient to share the gems used in your application with other applications and other scripts that run on the system\.
-.
-.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\.
-.
-.IP "" 0
-.
-.SH "SUDO USAGE"
-By default, Bundler installs gems to the same location as \fBgem install\fR\.
-.
-.P
-In some cases, that location may not be writable by your Unix user\. In that case, Bundler will stage everything in a temporary directory, then ask you for your \fBsudo\fR password in order to copy the gems into their system location\.
-.
-.P
-From your perspective, this is identical to installing the gems directly into the system\.
-.
-.P
-You should never use \fBsudo bundle install\fR\. This is because several other steps in \fBbundle install\fR must be performed as the current user:
-.
-.IP "\(bu" 4
-Updating your \fBGemfile\.lock\fR
-.
-.IP "\(bu" 4
-Updating your \fBvendor/cache\fR, if necessary
-.
-.IP "\(bu" 4
-Checking out private git repositories using your user\'s SSH keys
-.
-.IP "" 0
-.
-.P
-Of these three, the first two could theoretically be performed by \fBchown\fRing the resulting files to \fB$SUDO_USER\fR\. The third, however, can only be performed by invoking the \fBgit\fR command as the current user\. Therefore, git gems are downloaded and installed into \fB~/\.bundle\fR rather than $GEM_HOME or $BUNDLE_PATH\.
-.
-.P
-As a result, you should run \fBbundle install\fR as the current user, and Bundler will ask for your password if it is needed to put the gems into their final location\.
-.
-.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\.
-.
-.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)\.
-.
-.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
-\fBBundler offers a rock\-solid guarantee that the third\-party code you are running in development and testing is also the third\-party code you are running in production\. You can choose to exclude some of that code in different environments, but you will never be caught flat\-footed by different versions of third\-party code being used in different environments\.\fR
-.
-.P
-For a simple illustration, consider the following Gemfile(5):
-.
-.IP "" 4
-.
-.nf
-
-source \'https://rubygems\.org\'
-
-gem \'sinatra\'
-
-group :production do
- gem \'rack\-perftools\-profiler\'
-end
-.
-.fi
-.
-.IP "" 0
-.
-.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\.
-.
-.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
-This also means that you cannot include different versions of the same gem in different groups, because doing so would result in different sets of dependencies used in development and production\. Because of the vagaries of the dependency resolution process, this usually affects more than the gems you list in your Gemfile(5), and can (surprisingly) radically change the gems you are using\.
-.
-.SH "THE GEMFILE\.LOCK"
-When you run \fBbundle install\fR, Bundler will persist the full names and versions of all gems that you used (including dependencies of the gems specified in the Gemfile(5)) into a file called \fBGemfile\.lock\fR\.
-.
-.P
-Bundler uses this file in all subsequent calls to \fBbundle install\fR, which guarantees that you always use the same exact code, even as your application moves across machines\.
-.
-.P
-Because of the way dependency resolution works, even a seemingly small change (for instance, an update to a point\-release of a dependency of a gem in your Gemfile(5)) can result in radically different gems being needed to satisfy all dependencies\.
-.
-.P
-As a result, you \fBSHOULD\fR check your \fBGemfile\.lock\fR into version control, in both applications and gems\. If you do not, every machine that checks out your repository (including your production server) will resolve all dependencies again, which will result in different versions of third\-party code being used if \fBany\fR of the gems in the Gemfile(5) or any of their dependencies have been updated\.
-.
-.P
-When Bundler first shipped, the \fBGemfile\.lock\fR was included in the \fB\.gitignore\fR file included with generated gems\. Over time, however, it became clear that this practice forces the pain of broken dependencies onto new contributors, while leaving existing contributors potentially unaware of the problem\. Since \fBbundle install\fR is usually the first step towards a contribution, the pain of broken dependencies would discourage new contributors from contributing\. As a result, we have revised our guidance for gem authors to now recommend checking in the lock for gems\.
-.
-.SH "CONSERVATIVE UPDATING"
-When you make a change to the Gemfile(5) and then run \fBbundle install\fR, Bundler will update only the gems that you modified\.
-.
-.P
-In other words, if a gem that you \fBdid not modify\fR worked before you called \fBbundle install\fR, it will continue to use the exact same versions of all dependencies as it used before the update\.
-.
-.P
-Let\'s take a look at an example\. Here\'s your original Gemfile(5):
-.
-.IP "" 4
-.
-.nf
-
-source \'https://rubygems\.org\'
-
-gem \'actionpack\', \'2\.3\.8\'
-gem \'activemerchant\'
-.
-.fi
-.
-.IP "" 0
-.
-.P
-In this case, both \fBactionpack\fR and \fBactivemerchant\fR depend on \fBactivesupport\fR\. The \fBactionpack\fR gem depends on \fBactivesupport 2\.3\.8\fR and \fBrack ~> 1\.1\.0\fR, while the \fBactivemerchant\fR gem depends on \fBactivesupport >= 2\.3\.2\fR, \fBbraintree >= 2\.0\.0\fR, and \fBbuilder >= 2\.0\.0\fR\.
-.
-.P
-When the dependencies are first resolved, Bundler will select \fBactivesupport 2\.3\.8\fR, which satisfies the requirements of both gems in your Gemfile(5)\.
-.
-.P
-Next, you modify your Gemfile(5) to:
-.
-.IP "" 4
-.
-.nf
-
-source \'https://rubygems\.org\'
-
-gem \'actionpack\', \'3\.0\.0\.rc\'
-gem \'activemerchant\'
-.
-.fi
-.
-.IP "" 0
-.
-.P
-The \fBactionpack 3\.0\.0\.rc\fR gem has a number of new dependencies, and updates the \fBactivesupport\fR dependency to \fB= 3\.0\.0\.rc\fR and the \fBrack\fR dependency to \fB~> 1\.2\.1\fR\.
-.
-.P
-When you run \fBbundle install\fR, Bundler notices that you changed the \fBactionpack\fR gem, but not the \fBactivemerchant\fR gem\. It evaluates the gems currently being used to satisfy its requirements:
-.
-.TP
-\fBactivesupport 2\.3\.8\fR
-also used to satisfy a dependency in \fBactivemerchant\fR, which is not being updated
-.
-.TP
-\fBrack ~> 1\.1\.0\fR
-not currently being used to satisfy another dependency
-.
-.P
-Because you did not explicitly ask to update \fBactivemerchant\fR, you would not expect it to suddenly stop working after updating \fBactionpack\fR\. However, satisfying the new \fBactivesupport 3\.0\.0\.rc\fR dependency of actionpack requires updating one of its dependencies\.
-.
-.P
-Even though \fBactivemerchant\fR declares a very loose dependency that theoretically matches \fBactivesupport 3\.0\.0\.rc\fR, Bundler treats gems in your Gemfile(5) that have not changed as an atomic unit together with their dependencies\. In this case, the \fBactivemerchant\fR dependency is treated as \fBactivemerchant 1\.7\.1 + activesupport 2\.3\.8\fR, so \fBbundle install\fR will report that it cannot update \fBactionpack\fR\.
-.
-.P
-To explicitly update \fBactionpack\fR, including its dependencies which other gems in the Gemfile(5) still depend on, run \fBbundle update actionpack\fR (see \fBbundle update(1)\fR)\.
-.
-.P
-\fBSummary\fR: In general, after making a change to the Gemfile(5) , you should first try to run \fBbundle install\fR, which will guarantee that no other gem in the Gemfile(5) is impacted by the change\. If that does not work, run bundle update(1) \fIbundle\-update\.1\.html\fR\.
-.
-.SH "SEE ALSO"
-.
-.IP "\(bu" 4
-Gem install docs \fIhttp://guides\.rubygems\.org/rubygems\-basics/#installing\-gems\fR
-.
-.IP "\(bu" 4
-Rubygems signing docs \fIhttp://guides\.rubygems\.org/security/\fR
-.
-.IP "" 0
-
diff --git a/man/bundle-install.1.txt b/man/bundle-install.1.txt
deleted file mode 100644
index b1a9ad1eb3..0000000000
--- a/man/bundle-install.1.txt
+++ /dev/null
@@ -1,401 +0,0 @@
-BUNDLE-INSTALL(1) BUNDLE-INSTALL(1)
-
-
-
-NAME
- bundle-install - Install the dependencies specified in your Gemfile
-
-SYNOPSIS
- bundle install [--binstubs[=DIRECTORY]] [--clean] [--deployment]
- [--frozen] [--full-index] [--gemfile=GEMFILE] [--jobs=NUMBER] [--local]
- [--no-cache] [--no-prune] [--path PATH] [--quiet] [--redownload]
- [--retry=NUMBER] [--shebang] [--standalone[=GROUP[ GROUP...]]] [--sys-
- tem] [--trust-policy=POLICY] [--with=GROUP[ GROUP...]] [--with-
- out=GROUP[ GROUP...]]
-
-DESCRIPTION
- Install the gems specified in your Gemfile(5). If this is the first
- time you run bundle install (and a Gemfile.lock does not exist),
- Bundler will fetch all remote sources, resolve dependencies and install
- all needed gems.
-
- If a Gemfile.lock does exist, and you have not updated your Gemfile(5),
- Bundler will fetch all remote sources, but use the dependencies speci-
- fied in the Gemfile.lock instead of resolving dependencies.
-
- If a Gemfile.lock does exist, and you have updated your Gemfile(5),
- Bundler will use the dependencies in the Gemfile.lock for all gems that
- you did not update, but will re-resolve the dependencies of gems that
- you did update. You can find more information about this update process
- below under CONSERVATIVE UPDATING.
-
-OPTIONS
- To apply any of --binstubs, --deployment, --path, or --without every
- time bundle install is run, use bundle config (see bundle-config(1)).
-
- --binstubs[=<directory>]
- Binstubs are scripts that wrap around executables. Bundler cre-
- ates a small Ruby file (a binstub) that loads Bundler, runs the
- command, and puts it in bin/. This lets you link the binstub
- inside of an application to the exact gem version the applica-
- tion needs.
-
- Creates a directory (defaults to ~/bin) and places any executa-
- bles from the gem there. These executables run in Bundler's con-
- text. If used, you might add this directory to your environ-
- ment's PATH variable. For instance, if the rails gem comes with
- a rails executable, this flag will create a bin/rails executable
- that ensures that all referred dependencies will be resolved
- using the bundled gems.
-
- --clean
- On finishing the installation Bundler is going to remove any
- gems not present in the current Gemfile(5). Don't worry, gems
- currently in use will not be removed.
-
- --deployment
- In deployment mode, Bundler will 'roll-out' the bundle for pro-
- duction or CI use. Please check carefully if you want to have
- this option enabled in your development environment.
-
- --redownload
- Force download every gem, even if the required versions are
- already available locally.
-
- --frozen
- Do not allow the Gemfile.lock to be updated after this install.
- Exits non-zero if there are going to be changes to the Gem-
- file.lock.
-
- --full-index
- Bundler will not call Rubygems' API endpoint (default) but down-
- load and cache a (currently big) index file of all gems. Perfor-
- mance can be improved for large bundles that seldom change by
- enabling this option.
-
- --gemfile=<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>]
- The maximum number of parallel download and install jobs. The
- default is 1.
-
- --local
- Do not attempt to connect to rubygems.org. Instead, Bundler will
- use the gems already present in Rubygems' cache or in ven-
- dor/cache. Note that if a appropriate platform-specific gem
- exists on rubygems.org it will not be found.
-
- --no-cache
- Do not update the cache in vendor/cache with the newly bundled
- gems. This does not remove any gems in the cache but keeps the
- newly bundled gems from being cached during the install.
-
- --no-prune
- Don't remove stale gems from the cache when the installation
- finishes.
-
- --path=<path>
- The location to install the specified gems to. This defaults to
- Rubygems' setting. Bundler shares this location with Rubygems,
- gem install ... will have gem installed there, too. Therefore,
- gems installed without a --path ... setting will show up by
- calling gem list. Accordingly, gems installed to other locations
- will not get listed.
-
- --quiet
- Do not print progress information to the standard output.
- Instead, Bundler will exit using a status code ($?).
-
- --retry=[<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 --bin-
- stubs together with --shebang jruby these executables will be
- changed to execute jruby instead.
-
- --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. Bundler creates a directory named bundle
- and installs the bundle there. It also generates a bun-
- dle/bundler/setup.rb file to replace Bundler's own setup in the
- manner required. Using this option implicitly sets path, which
- is a [remembered option][REMEMBERED OPTIONS].
-
- --system
- Installs the gems specified in the bundle to the system's
- Rubygems location. This overrides any previous configuration of
- --path.
-
- --trust-policy=[<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.
-
- --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.
-
-DEPLOYMENT MODE
- Bundler's defaults are optimized for development. To switch to defaults
- optimized for deployment and for CI, use the --deployment flag. Do not
- activate deployment mode on development machines, as it will cause an
- error when the Gemfile(5) is modified.
-
- 1. A Gemfile.lock is required.
-
- To ensure that the same versions of the gems you developed with and
- tested with are also used in deployments, a Gemfile.lock is
- required.
-
- This is mainly to ensure that you remember to check your Gem-
- file.lock into version control.
-
- 2. The Gemfile.lock must be up to date
-
- In development, you can modify your Gemfile(5) and re-run bundle
- install to conservatively update your Gemfile.lock snapshot.
-
- In deployment, your Gemfile.lock should be up-to-date with changes
- made in your Gemfile(5).
-
- 3. Gems are installed to vendor/bundle not your default system loca-
- tion
-
- In development, it's convenient to share the gems used in your
- application with other applications and other scripts that run on
- the system.
-
- In deployment, isolation is a more important default. In addition,
- the user deploying the application may not have permission to
- install gems to the system, or the web server may not have permis-
- sion to read them.
-
- As a result, bundle install --deployment installs gems to the ven-
- dor/bundle directory in the application. This may be overridden
- using the --path option.
-
-
-
-SUDO USAGE
- By default, Bundler installs gems to the same location as gem install.
-
- In some cases, that location may not be writable by your Unix user. In
- that case, Bundler will stage everything in a temporary directory, then
- ask you for your sudo password in order to copy the gems into their
- system location.
-
- From your perspective, this is identical to installing the gems
- directly into the system.
-
- You should never use sudo bundle install. This is because several other
- steps in bundle install must be performed as the current user:
-
- o Updating your Gemfile.lock
-
- o Updating your vendor/cache, if necessary
-
- o Checking out private git repositories using your user's SSH keys
-
-
-
- Of these three, the first two could theoretically be performed by
- chowning the resulting files to $SUDO_USER. The third, however, can
- only be performed by invoking the git command as the current user.
- Therefore, git gems are downloaded and installed into ~/.bundle rather
- than $GEM_HOME or $BUNDLE_PATH.
-
- As a result, you should run bundle install as the current user, and
- Bundler will ask for your password if it is needed to put the gems into
- their final location.
-
-INSTALLING GROUPS
- By default, bundle install will install all gems in all groups in your
- Gemfile(5), except those declared for a different platform.
-
- However, you can explicitly tell Bundler to skip installing certain
- groups with the --without option. This option takes a space-separated
- list of groups.
-
- While the --without option will skip installing the gems in the speci-
- fied groups, it will still download those gems and use them to resolve
- the dependencies of every gem in your Gemfile(5).
-
- This is so that installing a different set of groups on another machine
- (such as a production server) will not change the gems and versions
- that you have already developed and tested against.
-
- Bundler offers a rock-solid guarantee that the third-party code you are
- running in development and testing is also the third-party code you are
- running in production. You can choose to exclude some of that code in
- different environments, but you will never be caught flat-footed by
- different versions of third-party code being used in different environ-
- ments.
-
- For a simple illustration, consider the following Gemfile(5):
-
-
-
- source 'https://rubygems.org'
-
- gem 'sinatra'
-
- group :production do
- gem 'rack-perftools-profiler'
- end
-
-
-
- In this case, sinatra depends on any version of Rack (>= 1.0), while
- rack-perftools-profiler depends on 1.x (~> 1.0).
-
- When you run bundle install --without production in development, we
- look at the dependencies of rack-perftools-profiler as well. That way,
- you do not spend all your time developing against Rack 2.0, using new
- APIs unavailable in Rack 1.x, only to have Bundler switch to Rack 1.2
- when the production group is used.
-
- This should not cause any problems in practice, because we do not
- attempt to install the gems in the excluded groups, and only evaluate
- as part of the dependency resolution process.
-
- This also means that you cannot include different versions of the same
- gem in different groups, because doing so would result in different
- sets of dependencies used in development and production. Because of the
- vagaries of the dependency resolution process, this usually affects
- more than the gems you list in your Gemfile(5), and can (surprisingly)
- radically change the gems you are using.
-
-THE GEMFILE.LOCK
- When you run bundle install, Bundler will persist the full names and
- versions of all gems that you used (including dependencies of the gems
- specified in the Gemfile(5)) into a file called Gemfile.lock.
-
- Bundler uses this file in all subsequent calls to bundle install, which
- guarantees that you always use the same exact code, even as your appli-
- cation moves across machines.
-
- Because of the way dependency resolution works, even a seemingly small
- change (for instance, an update to a point-release of a dependency of a
- gem in your Gemfile(5)) can result in radically different gems being
- needed to satisfy all dependencies.
-
- As a result, you SHOULD check your Gemfile.lock into version control,
- in both applications and gems. If you do not, every machine that checks
- out your repository (including your production server) will resolve all
- dependencies again, which will result in different versions of
- third-party code being used if any of the gems in the Gemfile(5) or any
- of their dependencies have been updated.
-
- When Bundler first shipped, the Gemfile.lock was included in the .git-
- ignore file included with generated gems. Over time, however, it became
- clear that this practice forces the pain of broken dependencies onto
- new contributors, while leaving existing contributors potentially
- unaware of the problem. Since bundle install is usually the first step
- towards a contribution, the pain of broken dependencies would discour-
- age new contributors from contributing. As a result, we have revised
- our guidance for gem authors to now recommend checking in the lock for
- gems.
-
-CONSERVATIVE UPDATING
- When you make a change to the Gemfile(5) and then run bundle install,
- Bundler will update only the gems that you modified.
-
- In other words, if a gem that you did not modify worked before you
- called bundle install, it will continue to use the exact same versions
- of all dependencies as it used before the update.
-
- Let's take a look at an example. Here's your original Gemfile(5):
-
-
-
- source 'https://rubygems.org'
-
- gem 'actionpack', '2.3.8'
- gem 'activemerchant'
-
-
-
- In this case, both actionpack and activemerchant depend on activesup-
- port. The actionpack gem depends on activesupport 2.3.8 and rack ~>
- 1.1.0, while the activemerchant gem depends on activesupport >= 2.3.2,
- braintree >= 2.0.0, and builder >= 2.0.0.
-
- When the dependencies are first resolved, Bundler will select
- activesupport 2.3.8, which satisfies the requirements of both gems in
- your Gemfile(5).
-
- Next, you modify your Gemfile(5) to:
-
-
-
- source 'https://rubygems.org'
-
- gem 'actionpack', '3.0.0.rc'
- gem 'activemerchant'
-
-
-
- The actionpack 3.0.0.rc gem has a number of new dependencies, and
- updates the activesupport dependency to = 3.0.0.rc and the rack depen-
- dency to ~> 1.2.1.
-
- When you run bundle install, Bundler notices that you changed the
- actionpack gem, but not the activemerchant gem. It evaluates the gems
- currently being used to satisfy its requirements:
-
- activesupport 2.3.8
- also used to satisfy a dependency in activemerchant, which is
- not being updated
-
- rack ~> 1.1.0
- not currently being used to satisfy another dependency
-
- Because you did not explicitly ask to update activemerchant, you would
- not expect it to suddenly stop working after updating actionpack. How-
- ever, satisfying the new activesupport 3.0.0.rc dependency of action-
- pack requires updating one of its dependencies.
-
- Even though activemerchant declares a very loose dependency that theo-
- retically matches activesupport 3.0.0.rc, Bundler treats gems in your
- Gemfile(5) that have not changed as an atomic unit together with their
- dependencies. In this case, the activemerchant dependency is treated as
- activemerchant 1.7.1 + activesupport 2.3.8, so bundle install will
- report that it cannot update actionpack.
-
- To explicitly update actionpack, including its dependencies which other
- gems in the Gemfile(5) still depend on, run bundle update actionpack
- (see bundle update(1)).
-
- Summary: In general, after making a change to the Gemfile(5) , you
- should first try to run bundle install, which will guarantee that no
- other gem in the Gemfile(5) is impacted by the change. If that does not
- work, run bundle update(1) bundle-update.1.html.
-
-SEE ALSO
- o Gem install docs
- http://guides.rubygems.org/rubygems-basics/#installing-gems
-
- o Rubygems signing docs http://guides.rubygems.org/security/
-
-
-
-
-
-
- January 2020 BUNDLE-INSTALL(1)
diff --git a/man/bundle-install.ronn b/man/bundle-install.ronn
deleted file mode 100644
index 2ba82f27a5..0000000000
--- a/man/bundle-install.ronn
+++ /dev/null
@@ -1,383 +0,0 @@
-bundle-install(1) -- Install the dependencies specified in your Gemfile
-=======================================================================
-
-## SYNOPSIS
-
-`bundle install` [--binstubs[=DIRECTORY]]
- [--clean]
- [--deployment]
- [--frozen]
- [--full-index]
- [--gemfile=GEMFILE]
- [--jobs=NUMBER]
- [--local]
- [--no-cache]
- [--no-prune]
- [--path PATH]
- [--quiet]
- [--redownload]
- [--retry=NUMBER]
- [--shebang]
- [--standalone[=GROUP[ GROUP...]]]
- [--system]
- [--trust-policy=POLICY]
- [--with=GROUP[ GROUP...]]
- [--without=GROUP[ GROUP...]]
-
-## DESCRIPTION
-
-Install the gems specified in your Gemfile(5). If this is the first
-time you run bundle install (and a `Gemfile.lock` does not exist),
-Bundler will fetch all remote sources, resolve dependencies and
-install all needed gems.
-
-If a `Gemfile.lock` does exist, and you have not updated your Gemfile(5),
-Bundler will fetch all remote sources, but use the dependencies
-specified in the `Gemfile.lock` instead of resolving dependencies.
-
-If a `Gemfile.lock` does exist, and you have updated your Gemfile(5),
-Bundler will use the dependencies in the `Gemfile.lock` for all gems
-that you did not update, but will re-resolve the dependencies of
-gems that you did update. You can find more information about this
-update process below under [CONSERVATIVE UPDATING][].
-
-## OPTIONS
-
-To apply any of `--binstubs`, `--deployment`, `--path`, or `--without` every
-time `bundle install` is run, use `bundle config` (see bundle-config(1)).
-
-* `--binstubs[=<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.
-
-* `--deployment`:
- In [deployment mode][DEPLOYMENT MODE], Bundler will 'roll-out' the bundle for
- production or CI use. Please check carefully if you want to have this option
- enabled in your development environment.
-
-* `--redownload`:
- Force download every gem, even if the required versions are already available
- locally.
-
-* `--frozen`:
- Do not allow the Gemfile.lock to be updated after this install. Exits
- non-zero if there are going to be changes to the Gemfile.lock.
-
-* `--full-index`:
- Bundler will not call Rubygems' API endpoint (default) but download and cache
- a (currently big) index file of all gems. Performance can be improved for
- large bundles that seldom change by enabling this option.
-
-* `--gemfile=<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>]`:
- The maximum number of parallel download and install jobs. The default
- is `1`.
-
-* `--local`:
- Do not attempt to connect to `rubygems.org`. Instead, Bundler will use the
- gems already present in Rubygems' cache or in `vendor/cache`. Note that if a
- appropriate platform-specific gem exists on `rubygems.org` it will not be
- found.
-
-* `--no-cache`:
- Do not update the cache in `vendor/cache` with the newly bundled gems. This
- does not remove any gems in the cache but keeps the newly bundled gems from
- being cached during the install.
-
-* `--no-prune`:
- Don't remove stale gems from the cache when the installation finishes.
-
-* `--path=<path>`:
- The location to install the specified gems to. This defaults to Rubygems'
- setting. Bundler shares this location with Rubygems, `gem install ...` will
- have gem installed there, too. Therefore, gems installed without a
- `--path ...` setting will show up by calling `gem list`. Accordingly, gems
- installed to other locations will not get listed.
-
-* `--quiet`:
- Do not print progress information to the standard output. Instead, Bundler
- will exit using a status code (`$?`).
-
-* `--retry=[<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.
-
-* `--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.
- Bundler creates a directory named `bundle` and installs the bundle there. It
- also generates a `bundle/bundler/setup.rb` file to replace Bundler's own setup
- in the manner required. Using this option implicitly sets `path`, which is a
- [remembered option][REMEMBERED OPTIONS].
-
-* `--system`:
- Installs the gems specified in the bundle to the system's Rubygems location.
- This overrides any previous configuration of `--path`.
-
-* `--trust-policy=[<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.
-
-* `--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.
-
-## DEPLOYMENT MODE
-
-Bundler's defaults are optimized for development. To switch to
-defaults optimized for deployment and for CI, use the `--deployment`
-flag. Do not activate deployment mode on development machines, as it
-will cause an error when the Gemfile(5) is modified.
-
-1. A `Gemfile.lock` is required.
-
- To ensure that the same versions of the gems you developed with
- and tested with are also used in deployments, a `Gemfile.lock`
- is required.
-
- This is mainly to ensure that you remember to check your
- `Gemfile.lock` into version control.
-
-2. The `Gemfile.lock` must be up to date
-
- In development, you can modify your Gemfile(5) and re-run
- `bundle install` to [conservatively update][CONSERVATIVE UPDATING]
- your `Gemfile.lock` snapshot.
-
- In deployment, your `Gemfile.lock` should be up-to-date with
- changes made in your Gemfile(5).
-
-3. Gems are installed to `vendor/bundle` not your default system location
-
- In development, it's convenient to share the gems used in your
- application with other applications and other scripts that run on
- the system.
-
- In deployment, isolation is a more important default. In addition,
- the user deploying the application may not have permission to install
- gems to the system, or the web server may not have permission to
- read them.
-
- As a result, `bundle install --deployment` installs gems to
- the `vendor/bundle` directory in the application. This may be
- overridden using the `--path` option.
-
-## SUDO USAGE
-
-By default, Bundler installs gems to the same location as `gem install`.
-
-In some cases, that location may not be writable by your Unix user. In
-that case, Bundler will stage everything in a temporary directory,
-then ask you for your `sudo` password in order to copy the gems into
-their system location.
-
-From your perspective, this is identical to installing the gems
-directly into the system.
-
-You should never use `sudo bundle install`. This is because several
-other steps in `bundle install` must be performed as the current user:
-
-* Updating your `Gemfile.lock`
-* Updating your `vendor/cache`, if necessary
-* Checking out private git repositories using your user's SSH keys
-
-Of these three, the first two could theoretically be performed by
-`chown`ing the resulting files to `$SUDO_USER`. The third, however,
-can only be performed by invoking the `git` command as
-the current user. Therefore, git gems are downloaded and installed
-into `~/.bundle` rather than $GEM_HOME or $BUNDLE_PATH.
-
-As a result, you should run `bundle install` as the current user,
-and Bundler will ask for your password if it is needed to put the
-gems into their final location.
-
-## INSTALLING GROUPS
-
-By default, `bundle install` will install all gems in all groups
-in your Gemfile(5), except those declared for a different platform.
-
-However, you can explicitly tell Bundler to skip installing
-certain groups with the `--without` option. This option takes
-a space-separated list of groups.
-
-While the `--without` option will skip _installing_ the gems in the
-specified groups, it will still _download_ those gems and use them to
-resolve the dependencies of every gem in your Gemfile(5).
-
-This is so that installing a different set of groups on another
- machine (such as a production server) will not change the
-gems and versions that you have already developed and tested against.
-
-`Bundler offers a rock-solid guarantee that the third-party
-code you are running in development and testing is also the
-third-party code you are running in production. You can choose
-to exclude some of that code in different environments, but you
-will never be caught flat-footed by different versions of
-third-party code being used in different environments.`
-
-For a simple illustration, consider the following Gemfile(5):
-
- source 'https://rubygems.org'
-
- gem 'sinatra'
-
- group :production do
- gem 'rack-perftools-profiler'
- end
-
-In this case, `sinatra` depends on any version of Rack (`>= 1.0`), while
-`rack-perftools-profiler` depends on 1.x (`~> 1.0`).
-
-When you run `bundle install --without production` in development, we
-look at the dependencies of `rack-perftools-profiler` as well. That way,
-you do not spend all your time developing against Rack 2.0, using new
-APIs unavailable in Rack 1.x, only to have Bundler switch to Rack 1.2
-when the `production` group _is_ used.
-
-This should not cause any problems in practice, because we do not
-attempt to `install` the gems in the excluded groups, and only evaluate
-as part of the dependency resolution process.
-
-This also means that you cannot include different versions of the same
-gem in different groups, because doing so would result in different
-sets of dependencies used in development and production. Because of
-the vagaries of the dependency resolution process, this usually
-affects more than the gems you list in your Gemfile(5), and can
-(surprisingly) radically change the gems you are using.
-
-## THE GEMFILE.LOCK
-
-When you run `bundle install`, Bundler will persist the full names
-and versions of all gems that you used (including dependencies of
-the gems specified in the Gemfile(5)) into a file called `Gemfile.lock`.
-
-Bundler uses this file in all subsequent calls to `bundle install`,
-which guarantees that you always use the same exact code, even
-as your application moves across machines.
-
-Because of the way dependency resolution works, even a
-seemingly small change (for instance, an update to a point-release
-of a dependency of a gem in your Gemfile(5)) can result in radically
-different gems being needed to satisfy all dependencies.
-
-As a result, you `SHOULD` check your `Gemfile.lock` into version
-control, in both applications and gems. If you do not, every machine that
-checks out your repository (including your production server) will resolve all
-dependencies again, which will result in different versions of
-third-party code being used if `any` of the gems in the Gemfile(5)
-or any of their dependencies have been updated.
-
-When Bundler first shipped, the `Gemfile.lock` was included in the `.gitignore`
-file included with generated gems. Over time, however, it became clear that
-this practice forces the pain of broken dependencies onto new contributors,
-while leaving existing contributors potentially unaware of the problem. Since
-`bundle install` is usually the first step towards a contribution, the pain of
-broken dependencies would discourage new contributors from contributing. As a
-result, we have revised our guidance for gem authors to now recommend checking
-in the lock for gems.
-
-## CONSERVATIVE UPDATING
-
-When you make a change to the Gemfile(5) and then run `bundle install`,
-Bundler will update only the gems that you modified.
-
-In other words, if a gem that you `did not modify` worked before
-you called `bundle install`, it will continue to use the exact
-same versions of all dependencies as it used before the update.
-
-Let's take a look at an example. Here's your original Gemfile(5):
-
- source 'https://rubygems.org'
-
- gem 'actionpack', '2.3.8'
- gem 'activemerchant'
-
-In this case, both `actionpack` and `activemerchant` depend on
-`activesupport`. The `actionpack` gem depends on `activesupport 2.3.8`
-and `rack ~> 1.1.0`, while the `activemerchant` gem depends on
-`activesupport >= 2.3.2`, `braintree >= 2.0.0`, and `builder >= 2.0.0`.
-
-When the dependencies are first resolved, Bundler will select
-`activesupport 2.3.8`, which satisfies the requirements of both
-gems in your Gemfile(5).
-
-Next, you modify your Gemfile(5) to:
-
- source 'https://rubygems.org'
-
- gem 'actionpack', '3.0.0.rc'
- gem 'activemerchant'
-
-The `actionpack 3.0.0.rc` gem has a number of new dependencies,
-and updates the `activesupport` dependency to `= 3.0.0.rc` and
-the `rack` dependency to `~> 1.2.1`.
-
-When you run `bundle install`, Bundler notices that you changed
-the `actionpack` gem, but not the `activemerchant` gem. It
-evaluates the gems currently being used to satisfy its requirements:
-
- * `activesupport 2.3.8`:
- also used to satisfy a dependency in `activemerchant`,
- which is not being updated
- * `rack ~> 1.1.0`:
- not currently being used to satisfy another dependency
-
-Because you did not explicitly ask to update `activemerchant`,
-you would not expect it to suddenly stop working after updating
-`actionpack`. However, satisfying the new `activesupport 3.0.0.rc`
-dependency of actionpack requires updating one of its dependencies.
-
-Even though `activemerchant` declares a very loose dependency
-that theoretically matches `activesupport 3.0.0.rc`, Bundler treats
-gems in your Gemfile(5) that have not changed as an atomic unit
-together with their dependencies. In this case, the `activemerchant`
-dependency is treated as `activemerchant 1.7.1 + activesupport 2.3.8`,
-so `bundle install` will report that it cannot update `actionpack`.
-
-To explicitly update `actionpack`, including its dependencies
-which other gems in the Gemfile(5) still depend on, run
-`bundle update actionpack` (see `bundle update(1)`).
-
-`Summary`: In general, after making a change to the Gemfile(5) , you
-should first try to run `bundle install`, which will guarantee that no
-other gem in the Gemfile(5) is impacted by the change. If that
-does not work, run [bundle update(1)](bundle-update.1.html).
-
-## SEE ALSO
-
-* [Gem install docs](http://guides.rubygems.org/rubygems-basics/#installing-gems)
-* [Rubygems signing docs](http://guides.rubygems.org/security/)
diff --git a/man/bundle-list.1 b/man/bundle-list.1
deleted file mode 100644
index 72bc391ac2..0000000000
--- a/man/bundle-list.1
+++ /dev/null
@@ -1,50 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-LIST" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-list\fR \- List all the gems in the bundle
-.
-.SH "SYNOPSIS"
-\fBbundle list\fR [\-\-name\-only] [\-\-paths] [\-\-without\-group=GROUP] [\-\-only\-group=GROUP]
-.
-.SH "DESCRIPTION"
-Prints a list of all the gems in the bundle including their version\.
-.
-.P
-Example:
-.
-.P
-bundle list \-\-name\-only
-.
-.P
-bundle list \-\-paths
-.
-.P
-bundle list \-\-without\-group test
-.
-.P
-bundle list \-\-only\-group dev
-.
-.P
-bundle list \-\-only\-group dev \-\-paths
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-name\-only\fR
-Print only the name of each gem\.
-.
-.TP
-\fB\-\-paths\fR
-Print the path to each gem in the bundle\.
-.
-.TP
-\fB\-\-without\-group\fR
-Print all gems expect from a group\.
-.
-.TP
-\fB\-\-only\-group\fR
-Print gems from a particular group\.
-
diff --git a/man/bundle-list.1.txt b/man/bundle-list.1.txt
deleted file mode 100644
index 645e62e452..0000000000
--- a/man/bundle-list.1.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-BUNDLE-LIST(1) BUNDLE-LIST(1)
-
-
-
-NAME
- bundle-list - List all the gems in the bundle
-
-SYNOPSIS
- bundle list [--name-only] [--paths] [--without-group=GROUP]
- [--only-group=GROUP]
-
-DESCRIPTION
- Prints a list of all the gems in the bundle including their version.
-
- Example:
-
- bundle list --name-only
-
- bundle list --paths
-
- bundle list --without-group test
-
- bundle list --only-group dev
-
- bundle list --only-group dev --paths
-
-OPTIONS
- --name-only
- Print only the name of each gem.
-
- --paths
- Print the path to each gem in the bundle.
-
- --without-group
- Print all gems expect from a group.
-
- --only-group
- Print gems from a particular group.
-
-
-
-
- January 2020 BUNDLE-LIST(1)
diff --git a/man/bundle-list.ronn b/man/bundle-list.ronn
deleted file mode 100644
index 120cf5e307..0000000000
--- a/man/bundle-list.ronn
+++ /dev/null
@@ -1,33 +0,0 @@
-bundle-list(1) -- List all the gems in the bundle
-=========================================================================
-
-## SYNOPSIS
-
-`bundle list` [--name-only] [--paths] [--without-group=GROUP] [--only-group=GROUP]
-
-## DESCRIPTION
-
-Prints a list of all the gems in the bundle including their version.
-
-Example:
-
-bundle list --name-only
-
-bundle list --paths
-
-bundle list --without-group test
-
-bundle list --only-group dev
-
-bundle list --only-group dev --paths
-
-## OPTIONS
-
-* `--name-only`:
- Print only the name of each gem.
-* `--paths`:
- Print the path to each gem in the bundle.
-* `--without-group`:
- Print all gems expect from a group.
-* `--only-group`:
- Print gems from a particular group.
diff --git a/man/bundle-lock.1 b/man/bundle-lock.1
deleted file mode 100644
index 89f6e35179..0000000000
--- a/man/bundle-lock.1
+++ /dev/null
@@ -1,84 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-LOCK" "1" "January 2020" "" ""
-.
-.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]
-.
-.SH "DESCRIPTION"
-Lock the gems specified in Gemfile\.
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-update=<*gems>\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\-\-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
-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
-Add a new platform to the lockfile, re\-resolving for the addition of that platform\.
-.
-.TP
-\fB\-\-remove\-platform\fR
-Remove a platform from the lockfile\.
-.
-.TP
-\fB\-\-patch\fR
-If updating, prefer updating only to next patch version\.
-.
-.TP
-\fB\-\-minor\fR
-If updating, prefer updating only to next minor version\.
-.
-.TP
-\fB\-\-major\fR
-If updating, prefer updating to next major version (default)\.
-.
-.TP
-\fB\-\-strict\fR
-If updating, do not allow any gem to be updated past latest \-\-patch | \-\-minor | \-\-major\.
-.
-.TP
-\fB\-\-conservative\fR
-If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated\.
-.
-.SH "UPDATING ALL GEMS"
-If you run \fBbundle lock\fR with \fB\-\-update\fR option without list of gems, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\.
-.
-.SH "UPDATING A LIST OF GEMS"
-Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the gems that you specified locked to the versions in the \fBGemfile\.lock\fR\.
-.
-.P
-For instance, you only want to update \fBnokogiri\fR, run \fBbundle lock \-\-update nokogiri\fR\.
-.
-.P
-Bundler will update \fBnokogiri\fR and any of its dependencies, but leave the rest of the gems that you specified locked to the versions in the \fBGemfile\.lock\fR\.
-.
-.SH "SUPPORTING OTHER PLATFORMS"
-If you want your bundle to support platforms other than the one you\'re running locally, you can run \fBbundle lock \-\-add\-platform PLATFORM\fR to add PLATFORM to the lockfile, force bundler to re\-resolve and consider the new platform when picking gems, all without needing to have a machine that matches PLATFORM handy to install those platform\-specific gems on\.
-.
-.P
-For a full explanation of gem platforms, see \fBgem help platform\fR\.
-.
-.SH "PATCH LEVEL OPTIONS"
-See bundle update(1) \fIbundle\-update\.1\.html\fR for details\.
diff --git a/man/bundle-lock.1.txt b/man/bundle-lock.1.txt
deleted file mode 100644
index 80dcada5b3..0000000000
--- a/man/bundle-lock.1.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-BUNDLE-LOCK(1) BUNDLE-LOCK(1)
-
-
-
-NAME
- bundle-lock - Creates / Updates a lockfile without installing
-
-SYNOPSIS
- bundle lock [--update] [--local] [--print] [--lockfile=PATH]
- [--full-index] [--add-platform] [--remove-platform] [--patch] [--minor]
- [--major] [--strict] [--conservative]
-
-DESCRIPTION
- Lock the gems specified in Gemfile.
-
-OPTIONS
- --update=<*gems>
- Ignores the existing lockfile. Resolve then updates lockfile.
- Taking a list of gems or updating all gems if no list is given.
-
- --local
- Do not attempt to connect to rubygems.org. Instead, Bundler will
- use the gems already present in Rubygems' cache or in ven-
- dor/cache. Note that if a appropriate platform-specific gem
- exists on rubygems.org it will not be found.
-
- --print
- Prints the lockfile to STDOUT instead of writing to the file
- system.
-
- --lockfile=<path>
- The path where the lockfile should be written to.
-
- --full-index
- Fall back to using the single-file index of all gems.
-
- --add-platform
- Add a new platform to the lockfile, re-resolving for the addi-
- tion of that platform.
-
- --remove-platform
- Remove a platform from the lockfile.
-
- --patch
- If updating, prefer updating only to next patch version.
-
- --minor
- If updating, prefer updating only to next minor version.
-
- --major
- If updating, prefer updating to next major version (default).
-
- --strict
- If updating, do not allow any gem to be updated past latest
- --patch | --minor | --major.
-
- --conservative
- If updating, use bundle install conservative update behavior and
- do not allow shared dependencies to be updated.
-
-UPDATING ALL GEMS
- If you run bundle lock with --update option without list of gems,
- bundler will ignore any previously installed gems and resolve all
- dependencies again based on the latest versions of all gems available
- in the sources.
-
-UPDATING A LIST OF GEMS
- Sometimes, you want to update a single gem in the Gemfile(5), and leave
- the rest of the gems that you specified locked to the versions in the
- Gemfile.lock.
-
- For instance, you only want to update nokogiri, run bundle lock
- --update nokogiri.
-
- Bundler will update nokogiri and any of its dependencies, but leave the
- rest of the gems that you specified locked to the versions in the Gem-
- file.lock.
-
-SUPPORTING OTHER PLATFORMS
- If you want your bundle to support platforms other than the one you're
- running locally, you can run bundle lock --add-platform PLATFORM to add
- PLATFORM to the lockfile, force bundler to re-resolve and consider the
- new platform when picking gems, all without needing to have a machine
- that matches PLATFORM handy to install those platform-specific gems on.
-
- For a full explanation of gem platforms, see gem help platform.
-
-PATCH LEVEL OPTIONS
- See bundle update(1) bundle-update.1.html for details.
-
-
-
- January 2020 BUNDLE-LOCK(1)
diff --git a/man/bundle-open.1 b/man/bundle-open.1
deleted file mode 100644
index 5a11eeeb64..0000000000
--- a/man/bundle-open.1
+++ /dev/null
@@ -1,32 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-OPEN" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
-.
-.SH "SYNOPSIS"
-\fBbundle open\fR [GEM]
-.
-.SH "DESCRIPTION"
-Opens the source directory of the provided GEM in your editor\.
-.
-.P
-For this to work the \fBEDITOR\fR or \fBBUNDLER_EDITOR\fR environment variable has to be set\.
-.
-.P
-Example:
-.
-.IP "" 4
-.
-.nf
-
-bundle open \'rack\'
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Will open the source directory for the \'rack\' gem in your bundle\.
diff --git a/man/bundle-open.1.txt b/man/bundle-open.1.txt
deleted file mode 100644
index 288bbce0e3..0000000000
--- a/man/bundle-open.1.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-BUNDLE-OPEN(1) BUNDLE-OPEN(1)
-
-
-
-NAME
- bundle-open - Opens the source directory for a gem in your bundle
-
-SYNOPSIS
- bundle open [GEM]
-
-DESCRIPTION
- Opens the source directory of the provided GEM in your editor.
-
- For this to work the EDITOR or BUNDLER_EDITOR environment variable has
- to be set.
-
- Example:
-
-
-
- bundle open 'rack'
-
-
-
- Will open the source directory for the 'rack' gem in your bundle.
-
-
-
- January 2020 BUNDLE-OPEN(1)
diff --git a/man/bundle-outdated.1 b/man/bundle-outdated.1
deleted file mode 100644
index 408e568034..0000000000
--- a/man/bundle-outdated.1
+++ /dev/null
@@ -1,155 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-OUTDATED" "1" "January 2020" "" ""
-.
-.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] [\-\-update\-strict] [\-\-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"
-.
-.TP
-\fB\-\-local\fR
-Do not attempt to fetch gems remotely and use the gem cache instead\.
-.
-.TP
-\fB\-\-pre\fR
-Check for newer pre\-release gems\.
-.
-.TP
-\fB\-\-source\fR
-Check against a specific source\.
-.
-.TP
-\fB\-\-strict\fR
-Only list newer versions allowed by your Gemfile requirements\.
-.
-.TP
-\fB\-\-parseable\fR, \fB\-\-porcelain\fR
-Use minimal formatting for more parseable output\.
-.
-.TP
-\fB\-\-group\fR
-List gems from a specific group\.
-.
-.TP
-\fB\-\-groups\fR
-List gems organized by groups\.
-.
-.TP
-\fB\-\-update\-strict\fR
-Strict conservative resolution, do not allow any gem to be updated past latest \-\-patch | \-\-minor| \-\-major\.
-.
-.TP
-\fB\-\-minor\fR
-Prefer updating only to next minor version\.
-.
-.TP
-\fB\-\-major\fR
-Prefer updating to next major version (default)\.
-.
-.TP
-\fB\-\-patch\fR
-Prefer updating only to next patch version\.
-.
-.TP
-\fB\-\-filter\-major\fR
-Only list major newer versions\.
-.
-.TP
-\fB\-\-filter\-minor\fR
-Only list minor newer versions\.
-.
-.TP
-\fB\-\-filter\-patch\fR
-Only list patch newer versions\.
-.
-.TP
-\fB\-\-only\-explicit\fR
-Only list gems specified in your Gemfile, not their dependencies\.
-.
-.SH "PATCH LEVEL OPTIONS"
-See bundle update(1) \fIbundle\-update\.1\.html\fR for details\.
-.
-.P
-One difference between the patch level options in \fBbundle update\fR and here is the \fB\-\-strict\fR option\. \fB\-\-strict\fR was already an option on outdated before the patch level options were added\. \fB\-\-strict\fR wasn\'t altered, and the \fB\-\-update\-strict\fR option on \fBoutdated\fR reflects what \fB\-\-strict\fR does on \fBbundle update\fR\.
-.
-.SH "FILTERING OUTPUT"
-The 3 filtering options do not affect the resolution of versions, merely what versions are shown in the output\.
-.
-.P
-If the regular output shows the following:
-.
-.IP "" 4
-.
-.nf
-
-* faker (newest 1\.6\.6, installed 1\.6\.5, requested ~> 1\.4) in groups "development, test"
-* hashie (newest 3\.4\.6, installed 1\.2\.0, requested = 1\.2\.0) in groups "default"
-* headless (newest 2\.3\.1, installed 2\.2\.3) in groups "test"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-\fB\-\-filter\-major\fR would only show:
-.
-.IP "" 4
-.
-.nf
-
-* hashie (newest 3\.4\.6, installed 1\.2\.0, requested = 1\.2\.0) in groups "default"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-\fB\-\-filter\-minor\fR would only show:
-.
-.IP "" 4
-.
-.nf
-
-* headless (newest 2\.3\.1, installed 2\.2\.3) in groups "test"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-\fB\-\-filter\-patch\fR would only show:
-.
-.IP "" 4
-.
-.nf
-
-* faker (newest 1\.6\.6, installed 1\.6\.5, requested ~> 1\.4) in groups "development, test"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Filter options can be combined\. \fB\-\-filter\-minor\fR and \fB\-\-filter\-patch\fR would show:
-.
-.IP "" 4
-.
-.nf
-
-* faker (newest 1\.6\.6, installed 1\.6\.5, requested ~> 1\.4) in groups "development, test"
-* headless (newest 2\.3\.1, installed 2\.2\.3) in groups "test"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Combining all three \fBfilter\fR options would be the same result as providing none of them\.
diff --git a/man/bundle-outdated.1.txt b/man/bundle-outdated.1.txt
deleted file mode 100644
index c938e0a4ab..0000000000
--- a/man/bundle-outdated.1.txt
+++ /dev/null
@@ -1,131 +0,0 @@
-BUNDLE-OUTDATED(1) BUNDLE-OUTDATED(1)
-
-
-
-NAME
- bundle-outdated - List installed gems with newer versions available
-
-SYNOPSIS
- bundle outdated [GEM] [--local] [--pre] [--source] [--strict]
- [--parseable | --porcelain] [--group=GROUP] [--groups]
- [--update-strict] [--patch|--minor|--major] [--filter-major] [--fil-
- ter-minor] [--filter-patch] [--only-explicit]
-
-DESCRIPTION
- Outdated lists the names and versions of gems that have a newer version
- available in the given source. Calling outdated with [GEM [GEM]] will
- only check for newer versions of the given gems. Prerelease gems are
- ignored by default. If your gems are up to date, Bundler will exit with
- a status of 0. Otherwise, it will exit 1.
-
-OPTIONS
- --local
- Do not attempt to fetch gems remotely and use the gem cache
- instead.
-
- --pre Check for newer pre-release gems.
-
- --source
- Check against a specific source.
-
- --strict
- Only list newer versions allowed by your Gemfile requirements.
-
- --parseable, --porcelain
- Use minimal formatting for more parseable output.
-
- --group
- List gems from a specific group.
-
- --groups
- List gems organized by groups.
-
- --update-strict
- Strict conservative resolution, do not allow any gem to be
- updated past latest --patch | --minor| --major.
-
- --minor
- Prefer updating only to next minor version.
-
- --major
- Prefer updating to next major version (default).
-
- --patch
- Prefer updating only to next patch version.
-
- --filter-major
- Only list major newer versions.
-
- --filter-minor
- Only list minor newer versions.
-
- --filter-patch
- Only list patch newer versions.
-
- --only-explicit
- Only list gems specified in your Gemfile, not their dependen-
- cies.
-
-PATCH LEVEL OPTIONS
- See bundle update(1) bundle-update.1.html for details.
-
- One difference between the patch level options in bundle update and
- here is the --strict option. --strict was already an option on outdated
- before the patch level options were added. --strict wasn't altered, and
- the --update-strict option on outdated reflects what --strict does on
- bundle update.
-
-FILTERING OUTPUT
- The 3 filtering options do not affect the resolution of versions,
- merely what versions are shown in the output.
-
- If the regular output shows the following:
-
-
-
- * faker (newest 1.6.6, installed 1.6.5, requested ~> 1.4) in groups "development, test"
- * hashie (newest 3.4.6, installed 1.2.0, requested = 1.2.0) in groups "default"
- * headless (newest 2.3.1, installed 2.2.3) in groups "test"
-
-
-
- --filter-major would only show:
-
-
-
- * hashie (newest 3.4.6, installed 1.2.0, requested = 1.2.0) in groups "default"
-
-
-
- --filter-minor would only show:
-
-
-
- * headless (newest 2.3.1, installed 2.2.3) in groups "test"
-
-
-
- --filter-patch would only show:
-
-
-
- * faker (newest 1.6.6, installed 1.6.5, requested ~> 1.4) in groups "development, test"
-
-
-
- Filter options can be combined. --filter-minor and --filter-patch would
- show:
-
-
-
- * faker (newest 1.6.6, installed 1.6.5, requested ~> 1.4) in groups "development, test"
- * headless (newest 2.3.1, installed 2.2.3) in groups "test"
-
-
-
- Combining all three filter options would be the same result as provid-
- ing none of them.
-
-
-
- January 2020 BUNDLE-OUTDATED(1)
diff --git a/man/bundle-package.1 b/man/bundle-package.1
deleted file mode 100644
index 142f298cf4..0000000000
--- a/man/bundle-package.1
+++ /dev/null
@@ -1,55 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-PACKAGE" "1" "September 2019" "" ""
-.
-.SH "NAME"
-\fBbundle\-package\fR \- Package your needed \fB\.gem\fR files into your application
-.
-.SH "SYNOPSIS"
-\fBbundle package\fR
-.
-.SH "DESCRIPTION"
-Copy all of the \fB\.gem\fR files needed to run the application into the \fBvendor/cache\fR directory\. In the future, when running [bundle install(1)][bundle\-install], use the gems in the cache in preference to the ones on \fBrubygems\.org\fR\.
-.
-.SH "GIT AND PATH GEMS"
-Since Bundler 1\.2, the \fBbundle package\fR command can also package \fB:git\fR and \fB:path\fR dependencies besides \.gem files\. This needs to be explicitly enabled via the \fB\-\-all\fR option\. Once used, the \fB\-\-all\fR option will be remembered\.
-.
-.SH "SUPPORT FOR MULTIPLE PLATFORMS"
-When using gems that have different packages for different platforms, Bundler 1\.8 and newer support caching of gems for other platforms where the Gemfile has been resolved (i\.e\. present in the lockfile) in \fBvendor/cache\fR\. This needs to be enabled via the \fB\-\-all\-platforms\fR option\. This setting will be remembered in your local bundler configuration\.
-.
-.SH "REMOTE FETCHING"
-By default, if you run \fBbundle install(1)\fR](bundle\-install\.1\.html) after running bundle package(1) \fIbundle\-package\.1\.html\fR, bundler will still connect to \fBrubygems\.org\fR to check whether a platform\-specific gem exists for any of the gems in \fBvendor/cache\fR\.
-.
-.P
-For instance, consider this Gemfile(5):
-.
-.IP "" 4
-.
-.nf
-
-source "https://rubygems\.org"
-
-gem "nokogiri"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-If you run \fBbundle package\fR under C Ruby, bundler will retrieve the version of \fBnokogiri\fR for the \fB"ruby"\fR platform\. If you deploy to JRuby and run \fBbundle install\fR, bundler is forced to check to see whether a \fB"java"\fR platformed \fBnokogiri\fR exists\.
-.
-.P
-Even though the \fBnokogiri\fR gem for the Ruby platform is \fItechnically\fR acceptable on JRuby, it has a C extension that does not run on JRuby\. As a result, bundler will, by default, still connect to \fBrubygems\.org\fR to check whether it has a version of one of your gems more specific to your platform\.
-.
-.P
-This problem is also not limited to the \fB"java"\fR platform\. A similar (common) problem can happen when developing on Windows and deploying to Linux, or even when developing on OSX and deploying to Linux\.
-.
-.P
-If you know for sure that the gems packaged in \fBvendor/cache\fR are appropriate for the platform you are on, you can run \fBbundle install \-\-local\fR to skip checking for more appropriate gems, and use the ones in \fBvendor/cache\fR\.
-.
-.P
-One way to be sure that you have the right platformed versions of all your gems is to run \fBbundle package\fR on an identical machine and check in the gems\. For instance, you can run \fBbundle package\fR on an identical staging box during your staging process, and check in the \fBvendor/cache\fR before deploying to production\.
-.
-.P
-By default, bundle package(1) \fIbundle\-package\.1\.html\fR fetches and also installs the gems to the default location\. To package the dependencies to \fBvendor/cache\fR without installing them to the local install location, you can run \fBbundle package \-\-no\-install\fR\.
diff --git a/man/bundle-package.1.txt b/man/bundle-package.1.txt
deleted file mode 100644
index ff4068b3bd..0000000000
--- a/man/bundle-package.1.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-BUNDLE-PACKAGE(1) BUNDLE-PACKAGE(1)
-
-
-
-NAME
- bundle-package - Package your needed .gem files into your application
-
-SYNOPSIS
- bundle package
-
-DESCRIPTION
- Copy all of the .gem files needed to run the application into the ven-
- dor/cache directory. In the future, when running [bundle
- install(1)][bundle-install], use the gems in the cache in preference to
- the ones on rubygems.org.
-
-GIT AND PATH GEMS
- Since Bundler 1.2, the bundle package command can also package :git and
- :path dependencies besides .gem files. This needs to be explicitly
- enabled via the --all option. Once used, the --all option will be
- remembered.
-
-SUPPORT FOR MULTIPLE PLATFORMS
- When using gems that have different packages for different platforms,
- Bundler 1.8 and newer support caching of gems for other platforms where
- the Gemfile has been resolved (i.e. present in the lockfile) in ven-
- dor/cache. This needs to be enabled via the --all-platforms option.
- This setting will be remembered in your local bundler configuration.
-
-REMOTE FETCHING
- By default, if you run bundle install(1)](bundle-install.1.html) after
- running bundle package(1) bundle-package.1.html, bundler will still
- connect to rubygems.org to check whether a platform-specific gem exists
- for any of the gems in vendor/cache.
-
- For instance, consider this Gemfile(5):
-
-
-
- source "https://rubygems.org"
-
- gem "nokogiri"
-
-
-
- If you run bundle package under C Ruby, bundler will retrieve the ver-
- sion of nokogiri for the "ruby" platform. If you deploy to JRuby and
- run bundle install, bundler is forced to check to see whether a "java"
- platformed nokogiri exists.
-
- Even though the nokogiri gem for the Ruby platform is technically
- acceptable on JRuby, it has a C extension that does not run on JRuby.
- As a result, bundler will, by default, still connect to rubygems.org to
- check whether it has a version of one of your gems more specific to
- your platform.
-
- This problem is also not limited to the "java" platform. A similar
- (common) problem can happen when developing on Windows and deploying to
- Linux, or even when developing on OSX and deploying to Linux.
-
- If you know for sure that the gems packaged in vendor/cache are appro-
- priate for the platform you are on, you can run bundle install --local
- to skip checking for more appropriate gems, and use the ones in ven-
- dor/cache.
-
- One way to be sure that you have the right platformed versions of all
- your gems is to run bundle package on an identical machine and check in
- the gems. For instance, you can run bundle package on an identical
- staging box during your staging process, and check in the vendor/cache
- before deploying to production.
-
- By default, bundle package(1) bundle-package.1.html fetches and also
- installs the gems to the default location. To package the dependencies
- to vendor/cache without installing them to the local install location,
- you can run bundle package --no-install.
-
-
-
- September 2019 BUNDLE-PACKAGE(1)
diff --git a/man/bundle-package.ronn b/man/bundle-package.ronn
deleted file mode 100644
index bc137374da..0000000000
--- a/man/bundle-package.ronn
+++ /dev/null
@@ -1,72 +0,0 @@
-bundle-package(1) -- Package your needed `.gem` files into your application
-===========================================================================
-
-## SYNOPSIS
-
-`bundle package`
-
-## DESCRIPTION
-
-Copy all of the `.gem` files needed to run the application into the
-`vendor/cache` directory. In the future, when running [bundle install(1)][bundle-install],
-use the gems in the cache in preference to the ones on `rubygems.org`.
-
-## GIT AND PATH GEMS
-
-Since Bundler 1.2, the `bundle package` command can also package `:git` and
-`:path` dependencies besides .gem files. This needs to be explicitly enabled
-via the `--all` option. Once used, the `--all` option will be remembered.
-
-## SUPPORT FOR MULTIPLE PLATFORMS
-
-When using gems that have different packages for different platforms, Bundler
-1.8 and newer support caching of gems for other platforms where the Gemfile
-has been resolved (i.e. present in the lockfile) in `vendor/cache`. This needs
-to be enabled via the `--all-platforms` option. This setting will be remembered
-in your local bundler configuration.
-
-## REMOTE FETCHING
-
-By default, if you run `bundle install(1)`](bundle-install.1.html) after running
-[bundle package(1)](bundle-package.1.html), bundler will still connect to `rubygems.org`
-to check whether a platform-specific gem exists for any of the gems
-in `vendor/cache`.
-
-For instance, consider this Gemfile(5):
-
- source "https://rubygems.org"
-
- gem "nokogiri"
-
-If you run `bundle package` under C Ruby, bundler will retrieve
-the version of `nokogiri` for the `"ruby"` platform. If you deploy
-to JRuby and run `bundle install`, bundler is forced to check to
-see whether a `"java"` platformed `nokogiri` exists.
-
-Even though the `nokogiri` gem for the Ruby platform is
-_technically_ acceptable on JRuby, it has a C extension
-that does not run on JRuby. As a result, bundler will, by default,
-still connect to `rubygems.org` to check whether it has a version
-of one of your gems more specific to your platform.
-
-This problem is also not limited to the `"java"` platform.
-A similar (common) problem can happen when developing on Windows
-and deploying to Linux, or even when developing on OSX and
-deploying to Linux.
-
-If you know for sure that the gems packaged in `vendor/cache`
-are appropriate for the platform you are on, you can run
-`bundle install --local` to skip checking for more appropriate
-gems, and use the ones in `vendor/cache`.
-
-One way to be sure that you have the right platformed versions
-of all your gems is to run `bundle package` on an identical
-machine and check in the gems. For instance, you can run
-`bundle package` on an identical staging box during your
-staging process, and check in the `vendor/cache` before
-deploying to production.
-
-By default, [bundle package(1)](bundle-package.1.html) fetches and also
-installs the gems to the default location. To package the
-dependencies to `vendor/cache` without installing them to the
-local install location, you can run `bundle package --no-install`.
diff --git a/man/bundle-platform.1 b/man/bundle-platform.1
deleted file mode 100644
index c83aa3c5d4..0000000000
--- a/man/bundle-platform.1
+++ /dev/null
@@ -1,61 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-PLATFORM" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-platform\fR \- Displays platform compatibility information
-.
-.SH "SYNOPSIS"
-\fBbundle platform\fR [\-\-ruby]
-.
-.SH "DESCRIPTION"
-\fBplatform\fR will display information from your Gemfile, Gemfile\.lock, and Ruby VM about your platform\.
-.
-.P
-For instance, using this Gemfile(5):
-.
-.IP "" 4
-.
-.nf
-
-source "https://rubygems\.org"
-
-ruby "1\.9\.3"
-
-gem "rack"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-If you run \fBbundle platform\fR on Ruby 1\.9\.3, it will display the following output:
-.
-.IP "" 4
-.
-.nf
-
-Your platform is: x86_64\-linux
-
-Your app has gems that work on these platforms:
-* ruby
-
-Your Gemfile specifies a Ruby version requirement:
-* ruby 1\.9\.3
-
-Your current platform satisfies the Ruby version requirement\.
-.
-.fi
-.
-.IP "" 0
-.
-.P
-\fBplatform\fR will list all the platforms in your \fBGemfile\.lock\fR as well as the \fBruby\fR directive if applicable from your Gemfile(5)\. It will also let you know if the \fBruby\fR directive requirement has been met\. If \fBruby\fR directive doesn\'t match the running Ruby VM, it will tell you what part does not\.
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-ruby\fR
-It will display the ruby directive information, so you don\'t have to parse it from the Gemfile(5)\.
-
diff --git a/man/bundle-platform.1.txt b/man/bundle-platform.1.txt
deleted file mode 100644
index f9dc8ccc1f..0000000000
--- a/man/bundle-platform.1.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-BUNDLE-PLATFORM(1) BUNDLE-PLATFORM(1)
-
-
-
-NAME
- bundle-platform - Displays platform compatibility information
-
-SYNOPSIS
- bundle platform [--ruby]
-
-DESCRIPTION
- platform will display information from your Gemfile, Gemfile.lock, and
- Ruby VM about your platform.
-
- For instance, using this Gemfile(5):
-
-
-
- source "https://rubygems.org"
-
- ruby "1.9.3"
-
- gem "rack"
-
-
-
- If you run bundle platform on Ruby 1.9.3, it will display the following
- output:
-
-
-
- Your platform is: x86_64-linux
-
- Your app has gems that work on these platforms:
- * ruby
-
- Your Gemfile specifies a Ruby version requirement:
- * ruby 1.9.3
-
- Your current platform satisfies the Ruby version requirement.
-
-
-
- platform will list all the platforms in your Gemfile.lock as well as
- the ruby directive if applicable from your Gemfile(5). It will also let
- you know if the ruby directive requirement has been met. If ruby direc-
- tive doesn't match the running Ruby VM, it will tell you what part does
- not.
-
-OPTIONS
- --ruby It will display the ruby directive information, so you don't
- have to parse it from the Gemfile(5).
-
-
-
-
- January 2020 BUNDLE-PLATFORM(1)
diff --git a/man/bundle-pristine.1 b/man/bundle-pristine.1
deleted file mode 100644
index 460e3d4e5a..0000000000
--- a/man/bundle-pristine.1
+++ /dev/null
@@ -1,34 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-PRISTINE" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
-.
-.SH "SYNOPSIS"
-\fBbundle pristine\fR
-.
-.SH "DESCRIPTION"
-\fBpristine\fR restores the installed gems in the bundle to their pristine condition using the local gem cache from RubyGems\. For git gems, a forced checkout will be performed\.
-.
-.P
-For further explanation, \fBbundle pristine\fR ignores unpacked files on disk\. In other words, this command utilizes the local \fB\.gem\fR cache or the gem\'s git repository as if one were installing from scratch\.
-.
-.P
-Note: the Bundler gem cannot be restored to its original state with \fBpristine\fR\. One also cannot use \fBbundle pristine\fR on gems with a \'path\' option in the Gemfile, because bundler has no original copy it can restore from\.
-.
-.P
-When is it practical to use \fBbundle pristine\fR?
-.
-.P
-It comes in handy when a developer is debugging a gem\. \fBbundle pristine\fR is a great way to get rid of experimental changes to a gem that one may not want\.
-.
-.P
-Why use \fBbundle pristine\fR over \fBgem pristine \-\-all\fR?
-.
-.P
-Both commands are very similar\. For context: \fBbundle pristine\fR, without arguments, cleans all gems from the lockfile\. Meanwhile, \fBgem pristine \-\-all\fR cleans all installed gems for that Ruby version\.
-.
-.P
-If a developer forgets which gems in their project they might have been debugging, the Rubygems \fBgem pristine [GEMNAME]\fR command may be inconvenient\. One can avoid waiting for \fBgem pristine \-\-all\fR, and instead run \fBbundle pristine\fR\.
diff --git a/man/bundle-pristine.1.txt b/man/bundle-pristine.1.txt
deleted file mode 100644
index 8d474fe497..0000000000
--- a/man/bundle-pristine.1.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-BUNDLE-PRISTINE(1) BUNDLE-PRISTINE(1)
-
-
-
-NAME
- bundle-pristine - Restores installed gems to their pristine condition
-
-SYNOPSIS
- bundle pristine
-
-DESCRIPTION
- pristine restores the installed gems in the bundle to their pristine
- condition using the local gem cache from RubyGems. For git gems, a
- forced checkout will be performed.
-
- For further explanation, bundle pristine ignores unpacked files on
- disk. In other words, this command utilizes the local .gem cache or the
- gem's git repository as if one were installing from scratch.
-
- Note: the Bundler gem cannot be restored to its original state with
- pristine. One also cannot use bundle pristine on gems with a 'path'
- option in the Gemfile, because bundler has no original copy it can
- restore from.
-
- When is it practical to use bundle pristine?
-
- It comes in handy when a developer is debugging a gem. bundle pristine
- is a great way to get rid of experimental changes to a gem that one may
- not want.
-
- Why use bundle pristine over gem pristine --all?
-
- Both commands are very similar. For context: bundle pristine, without
- arguments, cleans all gems from the lockfile. Meanwhile, gem pristine
- --all cleans all installed gems for that Ruby version.
-
- If a developer forgets which gems in their project they might have been
- debugging, the Rubygems gem pristine [GEMNAME] command may be inconve-
- nient. One can avoid waiting for gem pristine --all, and instead run
- bundle pristine.
-
-
-
- January 2020 BUNDLE-PRISTINE(1)
diff --git a/man/bundle-remove.1 b/man/bundle-remove.1
deleted file mode 100644
index cb4ad8d384..0000000000
--- a/man/bundle-remove.1
+++ /dev/null
@@ -1,31 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-REMOVE" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-remove\fR \- Removes gems from the Gemfile
-.
-.SH "SYNOPSIS"
-\fBbundle remove [GEM [GEM \.\.\.]] [\-\-install]\fR
-.
-.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/man/bundle-remove.1.txt b/man/bundle-remove.1.txt
deleted file mode 100644
index 7203422f39..0000000000
--- a/man/bundle-remove.1.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-BUNDLE-REMOVE(1) BUNDLE-REMOVE(1)
-
-
-
-NAME
- bundle-remove - Removes gems from the Gemfile
-
-SYNOPSIS
- bundle remove [GEM [GEM ...]] [--install]
-
-DESCRIPTION
- Removes the given gems from the Gemfile while ensuring that the result-
- ing Gemfile is still valid. If a gem cannot be removed, a warning is
- printed. If a gem is already absent from the Gemfile, and error is
- raised.
-
-OPTIONS
- --install
- Runs bundle install after the given gems have been removed from
- the Gemfile, which ensures that both the lockfile and the
- installed gems on disk are also updated to remove the given
- gem(s).
-
- Example:
-
- bundle remove rails
-
- bundle remove rails rack
-
- bundle remove rails rack --install
-
-
-
- January 2020 BUNDLE-REMOVE(1)
diff --git a/man/bundle-show.1 b/man/bundle-show.1
deleted file mode 100644
index 2922a33467..0000000000
--- a/man/bundle-show.1
+++ /dev/null
@@ -1,23 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-SHOW" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
-.
-.SH "SYNOPSIS"
-\fBbundle show\fR [GEM] [\-\-paths]
-.
-.SH "DESCRIPTION"
-Without the [GEM] option, \fBshow\fR will print a list of the names and versions of all gems that are required by your [\fBGemfile(5)\fR][Gemfile(5)], sorted by name\.
-.
-.P
-Calling show with [GEM] will list the exact location of that gem on your machine\.
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-paths\fR
-List the paths of all gems that are required by your [\fBGemfile(5)\fR][Gemfile(5)], sorted by gem name\.
-
diff --git a/man/bundle-show.1.txt b/man/bundle-show.1.txt
deleted file mode 100644
index 58f1620168..0000000000
--- a/man/bundle-show.1.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-BUNDLE-SHOW(1) BUNDLE-SHOW(1)
-
-
-
-NAME
- bundle-show - Shows all the gems in your bundle, or the path to a gem
-
-SYNOPSIS
- bundle show [GEM] [--paths]
-
-DESCRIPTION
- Without the [GEM] option, show will print a list of the names and ver-
- sions of all gems that are required by your [Gemfile(5)][Gemfile(5)],
- sorted by name.
-
- Calling show with [GEM] will list the exact location of that gem on
- your machine.
-
-OPTIONS
- --paths
- List the paths of all gems that are required by your [Gem-
- file(5)][Gemfile(5)], sorted by gem name.
-
-
-
-
- January 2020 BUNDLE-SHOW(1)
diff --git a/man/bundle-update.1 b/man/bundle-update.1
deleted file mode 100644
index f315532bb9..0000000000
--- a/man/bundle-update.1
+++ /dev/null
@@ -1,394 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-UPDATE" "1" "January 2020" "" ""
-.
-.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]
-.
-.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
-You would use \fBbundle update\fR to explicitly update the version of a gem\.
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-all\fR
-Update all gems specified in Gemfile\.
-.
-.TP
-\fB\-\-group=<name>\fR, \fB\-g=[<name>]\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
-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
-Do not attempt to fetch gems remotely and use the gem cache instead\.
-.
-.TP
-\fB\-\-ruby\fR
-Update the locked version of Ruby to the current version of Ruby\.
-.
-.TP
-\fB\-\-bundler\fR
-Update the locked version of bundler to the invoked bundler version\.
-.
-.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
-Specify the number of jobs to run in parallel\. The default is \fB1\fR\.
-.
-.TP
-\fB\-\-retry=[<number>]\fR
-Retry failed network or git requests for \fInumber\fR times\.
-.
-.TP
-\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
-\fB\-\-minor\fR
-Prefer updating only to next minor version\.
-.
-.TP
-\fB\-\-major\fR
-Prefer updating to next major version (default)\.
-.
-.TP
-\fB\-\-strict\fR
-Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR | \fB\-\-major\fR\.
-.
-.TP
-\fB\-\-conservative\fR
-Use bundle install conservative update behavior and do not allow shared dependencies to be updated\.
-.
-.SH "UPDATING ALL GEMS"
-If you run \fBbundle update \-\-all\fR, bundler will ignore any previously installed gems and resolve all dependencies again based on the latest versions of all gems available in the sources\.
-.
-.P
-Consider the following Gemfile(5):
-.
-.IP "" 4
-.
-.nf
-
-source "https://rubygems\.org"
-
-gem "rails", "3\.0\.0\.rc"
-gem "nokogiri"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-When you run bundle install(1) \fIbundle\-install\.1\.html\fR the first time, bundler will resolve all of the dependencies, all the way down, and install what you need:
-.
-.IP "" 4
-.
-.nf
-
-Fetching gem metadata from https://rubygems\.org/\.\.\.\.\.\.\.\.\.
-Resolving dependencies\.\.\.
-Installing builder 2\.1\.2
-Installing abstract 1\.0\.0
-Installing rack 1\.2\.8
-Using bundler 1\.7\.6
-Installing rake 10\.4\.0
-Installing polyglot 0\.3\.5
-Installing mime\-types 1\.25\.1
-Installing i18n 0\.4\.2
-Installing mini_portile 0\.6\.1
-Installing tzinfo 0\.3\.42
-Installing rack\-mount 0\.6\.14
-Installing rack\-test 0\.5\.7
-Installing treetop 1\.4\.15
-Installing thor 0\.14\.6
-Installing activesupport 3\.0\.0\.rc
-Installing erubis 2\.6\.6
-Installing activemodel 3\.0\.0\.rc
-Installing arel 0\.4\.0
-Installing mail 2\.2\.20
-Installing activeresource 3\.0\.0\.rc
-Installing actionpack 3\.0\.0\.rc
-Installing activerecord 3\.0\.0\.rc
-Installing actionmailer 3\.0\.0\.rc
-Installing railties 3\.0\.0\.rc
-Installing rails 3\.0\.0\.rc
-Installing nokogiri 1\.6\.5
-
-Bundle complete! 2 Gemfile dependencies, 26 gems total\.
-Use `bundle show [gemname]` to see where a bundled gem is installed\.
-.
-.fi
-.
-.IP "" 0
-.
-.P
-As you can see, even though you have two gems in the Gemfile(5), your application needs 26 different gems in order to run\. Bundler remembers the exact versions it installed in \fBGemfile\.lock\fR\. The next time you run bundle install(1) \fIbundle\-install\.1\.html\fR, bundler skips the dependency resolution and installs the same gems as it installed last time\.
-.
-.P
-After checking in the \fBGemfile\.lock\fR into version control and cloning it on another machine, running bundle install(1) \fIbundle\-install\.1\.html\fR will \fIstill\fR install the gems that you installed last time\. You don\'t need to worry that a new release of \fBerubis\fR or \fBmail\fR changes the gems you use\.
-.
-.P
-However, from time to time, you might want to update the gems you are using to the newest versions that still match the gems in your Gemfile(5)\.
-.
-.P
-To do this, run \fBbundle update \-\-all\fR, which will ignore the \fBGemfile\.lock\fR, and resolve all the dependencies again\. Keep in mind that this process can result in a significantly different set of the 25 gems, based on the requirements of new gems that the gem authors released since the last time you ran \fBbundle update \-\-all\fR\.
-.
-.SH "UPDATING A LIST OF GEMS"
-Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the gems that you specified locked to the versions in the \fBGemfile\.lock\fR\.
-.
-.P
-For instance, in the scenario above, imagine that \fBnokogiri\fR releases version \fB1\.4\.4\fR, and you want to update it \fIwithout\fR updating Rails and all of its dependencies\. To do this, run \fBbundle update nokogiri\fR\.
-.
-.P
-Bundler will update \fBnokogiri\fR and any of its dependencies, but leave alone Rails and its dependencies\.
-.
-.SH "OVERLAPPING DEPENDENCIES"
-Sometimes, multiple gems declared in your Gemfile(5) are satisfied by the same second\-level dependency\. For instance, consider the case of \fBthin\fR and \fBrack\-perftools\-profiler\fR\.
-.
-.IP "" 4
-.
-.nf
-
-source "https://rubygems\.org"
-
-gem "thin"
-gem "rack\-perftools\-profiler"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-The \fBthin\fR gem depends on \fBrack >= 1\.0\fR, while \fBrack\-perftools\-profiler\fR depends on \fBrack ~> 1\.0\fR\. If you run bundle install, you get:
-.
-.IP "" 4
-.
-.nf
-
-Fetching source index for https://rubygems\.org/
-Installing daemons (1\.1\.0)
-Installing eventmachine (0\.12\.10) with native extensions
-Installing open4 (1\.0\.1)
-Installing perftools\.rb (0\.4\.7) with native extensions
-Installing rack (1\.2\.1)
-Installing rack\-perftools_profiler (0\.0\.2)
-Installing thin (1\.2\.7) with native extensions
-Using bundler (1\.0\.0\.rc\.3)
-.
-.fi
-.
-.IP "" 0
-.
-.P
-In this case, the two gems have their own set of dependencies, but they share \fBrack\fR in common\. If you run \fBbundle update thin\fR, bundler will update \fBdaemons\fR, \fBeventmachine\fR and \fBrack\fR, which are dependencies of \fBthin\fR, but not \fBopen4\fR or \fBperftools\.rb\fR, which are dependencies of \fBrack\-perftools_profiler\fR\. Note that \fBbundle update thin\fR will update \fBrack\fR even though it\'s \fIalso\fR a dependency of \fBrack\-perftools_profiler\fR\.
-.
-.P
-In short, by default, when you update a gem using \fBbundle update\fR, bundler will update all dependencies of that gem, including those that are also dependencies of another gem\.
-.
-.P
-To prevent updating shared dependencies, prior to version 1\.14 the only option was the \fBCONSERVATIVE UPDATING\fR behavior in bundle install(1) \fIbundle\-install\.1\.html\fR:
-.
-.P
-In this scenario, updating the \fBthin\fR version manually in the Gemfile(5), and then running bundle install(1) \fIbundle\-install\.1\.html\fR will only update \fBdaemons\fR and \fBeventmachine\fR, but not \fBrack\fR\. For more information, see the \fBCONSERVATIVE UPDATING\fR section of bundle install(1) \fIbundle\-install\.1\.html\fR\.
-.
-.P
-Starting with 1\.14, specifying the \fB\-\-conservative\fR option will also prevent shared dependencies from being updated\.
-.
-.SH "PATCH LEVEL OPTIONS"
-Version 1\.14 introduced 4 patch\-level options that will influence how gem versions are resolved\. One of the following options can be used: \fB\-\-patch\fR, \fB\-\-minor\fR or \fB\-\-major\fR\. \fB\-\-strict\fR can be added to further influence resolution\.
-.
-.TP
-\fB\-\-patch\fR
-Prefer updating only to next patch version\.
-.
-.TP
-\fB\-\-minor\fR
-Prefer updating only to next minor version\.
-.
-.TP
-\fB\-\-major\fR
-Prefer updating to next major version (default)\.
-.
-.TP
-\fB\-\-strict\fR
-Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR | \fB\-\-major\fR\.
-.
-.P
-When Bundler is resolving what versions to use to satisfy declared requirements in the Gemfile or in parent gems, it looks up all available versions, filters out any versions that don\'t satisfy the requirement, and then, by default, sorts them from newest to oldest, considering them in that order\.
-.
-.P
-Providing one of the patch level options (e\.g\. \fB\-\-patch\fR) changes the sort order of the satisfying versions, causing Bundler to consider the latest \fB\-\-patch\fR or \fB\-\-minor\fR version available before other versions\. Note that versions outside the stated patch level could still be resolved to if necessary to find a suitable dependency graph\.
-.
-.P
-For example, if gem \'foo\' is locked at 1\.0\.2, with no gem requirement defined in the Gemfile, and versions 1\.0\.3, 1\.0\.4, 1\.1\.0, 1\.1\.1, 2\.0\.0 all exist, the default order of preference by default (\fB\-\-major\fR) will be "2\.0\.0, 1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2"\.
-.
-.P
-If the \fB\-\-patch\fR option is used, the order of preference will change to "1\.0\.4, 1\.0\.3, 1\.0\.2, 1\.1\.1, 1\.1\.0, 2\.0\.0"\.
-.
-.P
-If the \fB\-\-minor\fR option is used, the order of preference will change to "1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2, 2\.0\.0"\.
-.
-.P
-Combining the \fB\-\-strict\fR option with any of the patch level options will remove any versions beyond the scope of the patch level option, to ensure that no gem is updated that far\.
-.
-.P
-To continue the previous example, if both \fB\-\-patch\fR and \fB\-\-strict\fR options are used, the available versions for resolution would be "1\.0\.4, 1\.0\.3, 1\.0\.2"\. If \fB\-\-minor\fR and \fB\-\-strict\fR are used, it would be "1\.1\.1, 1\.1\.0, 1\.0\.4, 1\.0\.3, 1\.0\.2"\.
-.
-.P
-Gem requirements as defined in the Gemfile will still be the first determining factor for what versions are available\. If the gem requirement for \fBfoo\fR in the Gemfile is \'~> 1\.0\', that will accomplish the same thing as providing the \fB\-\-minor\fR and \fB\-\-strict\fR options\.
-.
-.SH "PATCH LEVEL EXAMPLES"
-Given the following gem specifications:
-.
-.IP "" 4
-.
-.nf
-
-foo 1\.4\.3, requires: ~> bar 2\.0
-foo 1\.4\.4, requires: ~> bar 2\.0
-foo 1\.4\.5, requires: ~> bar 2\.1
-foo 1\.5\.0, requires: ~> bar 2\.1
-foo 1\.5\.1, requires: ~> bar 3\.0
-bar with versions 2\.0\.3, 2\.0\.4, 2\.1\.0, 2\.1\.1, 3\.0\.0
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Gemfile:
-.
-.IP "" 4
-.
-.nf
-
-gem \'foo\'
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Gemfile\.lock:
-.
-.IP "" 4
-.
-.nf
-
-foo (1\.4\.3)
- bar (~> 2\.0)
-bar (2\.0\.3)
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Cases:
-.
-.IP "" 4
-.
-.nf
-
-# Command Line Result
-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
-1 bundle update \-\-patch \'foo 1\.4\.5\', \'bar 2\.1\.1\'
-2 bundle update \-\-patch foo \'foo 1\.4\.5\', \'bar 2\.1\.1\'
-3 bundle update \-\-minor \'foo 1\.5\.1\', \'bar 3\.0\.0\'
-4 bundle update \-\-minor \-\-strict \'foo 1\.5\.0\', \'bar 2\.1\.1\'
-5 bundle update \-\-patch \-\-strict \'foo 1\.4\.4\', \'bar 2\.0\.4\'
-.
-.fi
-.
-.IP "" 0
-.
-.P
-In case 1, bar is upgraded to 2\.1\.1, a minor version increase, because the dependency from foo 1\.4\.5 required it\.
-.
-.P
-In case 2, only foo is requested to be unlocked, but bar is also allowed to move because it\'s not a declared dependency in the Gemfile\.
-.
-.P
-In case 3, bar goes up a whole major release, because a minor increase is preferred now for foo, and when it goes to 1\.5\.1, it requires 3\.0\.0 of bar\.
-.
-.P
-In case 4, foo is preferred up to a minor version, but 1\.5\.1 won\'t work because the \-\-strict flag removes bar 3\.0\.0 from consideration since it\'s a major increment\.
-.
-.P
-In case 5, both foo and bar have any minor or major increments removed from consideration because of the \-\-strict flag, so the most they can move is up to 1\.4\.4 and 2\.0\.4\.
-.
-.SH "RECOMMENDED WORKFLOW"
-In general, when working with an application managed with bundler, you should use the following workflow:
-.
-.IP "\(bu" 4
-After you create your Gemfile(5) for the first time, run
-.
-.IP
-$ bundle install
-.
-.IP "\(bu" 4
-Check the resulting \fBGemfile\.lock\fR into version control
-.
-.IP
-$ git add Gemfile\.lock
-.
-.IP "\(bu" 4
-When checking out this repository on another development machine, run
-.
-.IP
-$ bundle install
-.
-.IP "\(bu" 4
-When checking out this repository on a deployment machine, run
-.
-.IP
-$ bundle install \-\-deployment
-.
-.IP "\(bu" 4
-After changing the Gemfile(5) to reflect a new or update dependency, run
-.
-.IP
-$ bundle install
-.
-.IP "\(bu" 4
-Make sure to check the updated \fBGemfile\.lock\fR into version control
-.
-.IP
-$ git add Gemfile\.lock
-.
-.IP "\(bu" 4
-If bundle install(1) \fIbundle\-install\.1\.html\fR reports a conflict, manually update the specific gems that you changed in the Gemfile(5)
-.
-.IP
-$ bundle update rails thin
-.
-.IP "\(bu" 4
-If you want to update all the gems to the latest possible versions that still match the gems listed in the Gemfile(5), run
-.
-.IP
-$ bundle update \-\-all
-.
-.IP "" 0
-
diff --git a/man/bundle-update.1.txt b/man/bundle-update.1.txt
deleted file mode 100644
index b8208c75d3..0000000000
--- a/man/bundle-update.1.txt
+++ /dev/null
@@ -1,390 +0,0 @@
-BUNDLE-UPDATE(1) BUNDLE-UPDATE(1)
-
-
-
-NAME
- bundle-update - Update your gems to the latest available versions
-
-SYNOPSIS
- bundle update *gems [--all] [--group=NAME] [--source=NAME] [--local]
- [--ruby] [--bundler[=VERSION]] [--full-index] [--jobs=JOBS] [--quiet]
- [--patch|--minor|--major] [--redownload] [--strict] [--conservative]
-
-DESCRIPTION
- Update the gems specified (all gems, if --all flag is used), ignoring
- the previously installed gems specified in the Gemfile.lock. In gen-
- eral, you should use bundle install(1) bundle-install.1.html to install
- the same exact gems and versions across machines.
-
- You would use bundle update to explicitly update the version of a gem.
-
-OPTIONS
- --all Update all gems specified in Gemfile.
-
- --group=<name>, -g=[<name>]
- 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>
- The name of a :git or :path source used in the Gemfile(5). For
- instance, with a :git source of
- http://github.com/rails/rails.git, you would call bundle update
- --source rails
-
- --local
- Do not attempt to fetch gems remotely and use the gem cache
- instead.
-
- --ruby Update the locked version of Ruby to the current version of
- Ruby.
-
- --bundler
- Update the locked version of bundler to the invoked bundler ver-
- sion.
-
- --full-index
- Fall back to using the single-file index of all gems.
-
- --jobs=[<number>], -j[<number>]
- Specify the number of jobs to run in parallel. The default is 1.
-
- --retry=[<number>]
- Retry failed network or git requests for number times.
-
- --quiet
- Only output warnings and errors.
-
- --redownload
- Force downloading every gem.
-
- --patch
- Prefer updating only to next patch version.
-
- --minor
- Prefer updating only to next minor version.
-
- --major
- Prefer updating to next major version (default).
-
- --strict
- Do not allow any gem to be updated past latest --patch | --minor
- | --major.
-
- --conservative
- Use bundle install conservative update behavior and do not allow
- shared dependencies to be updated.
-
-UPDATING ALL GEMS
- If you run bundle update --all, bundler will ignore any previously
- installed gems and resolve all dependencies again based on the latest
- versions of all gems available in the sources.
-
- Consider the following Gemfile(5):
-
-
-
- source "https://rubygems.org"
-
- gem "rails", "3.0.0.rc"
- gem "nokogiri"
-
-
-
- When you run bundle install(1) bundle-install.1.html the first time,
- bundler will resolve all of the dependencies, all the way down, and
- install what you need:
-
-
-
- Fetching gem metadata from https://rubygems.org/.........
- Resolving dependencies...
- Installing builder 2.1.2
- Installing abstract 1.0.0
- Installing rack 1.2.8
- Using bundler 1.7.6
- Installing rake 10.4.0
- Installing polyglot 0.3.5
- Installing mime-types 1.25.1
- Installing i18n 0.4.2
- Installing mini_portile 0.6.1
- Installing tzinfo 0.3.42
- Installing rack-mount 0.6.14
- Installing rack-test 0.5.7
- Installing treetop 1.4.15
- Installing thor 0.14.6
- Installing activesupport 3.0.0.rc
- Installing erubis 2.6.6
- Installing activemodel 3.0.0.rc
- Installing arel 0.4.0
- Installing mail 2.2.20
- Installing activeresource 3.0.0.rc
- Installing actionpack 3.0.0.rc
- Installing activerecord 3.0.0.rc
- Installing actionmailer 3.0.0.rc
- Installing railties 3.0.0.rc
- Installing rails 3.0.0.rc
- Installing nokogiri 1.6.5
-
- Bundle complete! 2 Gemfile dependencies, 26 gems total.
- Use `bundle show [gemname]` to see where a bundled gem is installed.
-
-
-
- As you can see, even though you have two gems in the Gemfile(5), your
- application needs 26 different gems in order to run. Bundler remembers
- the exact versions it installed in Gemfile.lock. The next time you run
- bundle install(1) bundle-install.1.html, bundler skips the dependency
- resolution and installs the same gems as it installed last time.
-
- After checking in the Gemfile.lock into version control and cloning it
- on another machine, running bundle install(1) bundle-install.1.html
- will still install the gems that you installed last time. You don't
- need to worry that a new release of erubis or mail changes the gems you
- use.
-
- However, from time to time, you might want to update the gems you are
- using to the newest versions that still match the gems in your Gem-
- file(5).
-
- To do this, run bundle update --all, which will ignore the Gem-
- file.lock, and resolve all the dependencies again. Keep in mind that
- this process can result in a significantly different set of the 25
- gems, based on the requirements of new gems that the gem authors
- released since the last time you ran bundle update --all.
-
-UPDATING A LIST OF GEMS
- Sometimes, you want to update a single gem in the Gemfile(5), and leave
- the rest of the gems that you specified locked to the versions in the
- Gemfile.lock.
-
- For instance, in the scenario above, imagine that nokogiri releases
- version 1.4.4, and you want to update it without updating Rails and all
- of its dependencies. To do this, run bundle update nokogiri.
-
- Bundler will update nokogiri and any of its dependencies, but leave
- alone Rails and its dependencies.
-
-OVERLAPPING DEPENDENCIES
- Sometimes, multiple gems declared in your Gemfile(5) are satisfied by
- the same second-level dependency. For instance, consider the case of
- thin and rack-perftools-profiler.
-
-
-
- source "https://rubygems.org"
-
- gem "thin"
- gem "rack-perftools-profiler"
-
-
-
- The thin gem depends on rack >= 1.0, while rack-perftools-profiler
- depends on rack ~> 1.0. If you run bundle install, you get:
-
-
-
- Fetching source index for https://rubygems.org/
- Installing daemons (1.1.0)
- Installing eventmachine (0.12.10) with native extensions
- Installing open4 (1.0.1)
- Installing perftools.rb (0.4.7) with native extensions
- Installing rack (1.2.1)
- Installing rack-perftools_profiler (0.0.2)
- Installing thin (1.2.7) with native extensions
- Using bundler (1.0.0.rc.3)
-
-
-
- In this case, the two gems have their own set of dependencies, but they
- share rack in common. If you run bundle update thin, bundler will
- update daemons, eventmachine and rack, which are dependencies of thin,
- but not open4 or perftools.rb, which are dependencies of
- rack-perftools_profiler. Note that bundle update thin will update rack
- even though it's also a dependency of rack-perftools_profiler.
-
- In short, by default, when you update a gem using bundle update,
- bundler will update all dependencies of that gem, including those that
- are also dependencies of another gem.
-
- To prevent updating shared dependencies, prior to version 1.14 the only
- option was the CONSERVATIVE UPDATING behavior in bundle install(1) bun-
- dle-install.1.html:
-
- In this scenario, updating the thin version manually in the Gemfile(5),
- and then running bundle install(1) bundle-install.1.html will only
- update daemons and eventmachine, but not rack. For more information,
- see the CONSERVATIVE UPDATING section of bundle install(1) bun-
- dle-install.1.html.
-
- Starting with 1.14, specifying the --conservative option will also pre-
- vent shared dependencies from being updated.
-
-PATCH LEVEL OPTIONS
- Version 1.14 introduced 4 patch-level options that will influence how
- gem versions are resolved. One of the following options can be used:
- --patch, --minor or --major. --strict can be added to further influence
- resolution.
-
- --patch
- Prefer updating only to next patch version.
-
- --minor
- Prefer updating only to next minor version.
-
- --major
- Prefer updating to next major version (default).
-
- --strict
- Do not allow any gem to be updated past latest --patch | --minor
- | --major.
-
- When Bundler is resolving what versions to use to satisfy declared
- requirements in the Gemfile or in parent gems, it looks up all avail-
- able versions, filters out any versions that don't satisfy the require-
- ment, and then, by default, sorts them from newest to oldest, consider-
- ing them in that order.
-
- Providing one of the patch level options (e.g. --patch) changes the
- sort order of the satisfying versions, causing Bundler to consider the
- latest --patch or --minor version available before other versions. Note
- that versions outside the stated patch level could still be resolved to
- if necessary to find a suitable dependency graph.
-
- For example, if gem 'foo' is locked at 1.0.2, with no gem requirement
- defined in the Gemfile, and versions 1.0.3, 1.0.4, 1.1.0, 1.1.1, 2.0.0
- all exist, the default order of preference by default (--major) will be
- "2.0.0, 1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2".
-
- If the --patch option is used, the order of preference will change to
- "1.0.4, 1.0.3, 1.0.2, 1.1.1, 1.1.0, 2.0.0".
-
- If the --minor option is used, the order of preference will change to
- "1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2, 2.0.0".
-
- Combining the --strict option with any of the patch level options will
- remove any versions beyond the scope of the patch level option, to
- ensure that no gem is updated that far.
-
- To continue the previous example, if both --patch and --strict options
- are used, the available versions for resolution would be "1.0.4, 1.0.3,
- 1.0.2". If --minor and --strict are used, it would be "1.1.1, 1.1.0,
- 1.0.4, 1.0.3, 1.0.2".
-
- Gem requirements as defined in the Gemfile will still be the first
- determining factor for what versions are available. If the gem require-
- ment for foo in the Gemfile is '~> 1.0', that will accomplish the same
- thing as providing the --minor and --strict options.
-
-PATCH LEVEL EXAMPLES
- Given the following gem specifications:
-
-
-
- foo 1.4.3, requires: ~> bar 2.0
- foo 1.4.4, requires: ~> bar 2.0
- foo 1.4.5, requires: ~> bar 2.1
- foo 1.5.0, requires: ~> bar 2.1
- foo 1.5.1, requires: ~> bar 3.0
- bar with versions 2.0.3, 2.0.4, 2.1.0, 2.1.1, 3.0.0
-
-
-
- Gemfile:
-
-
-
- gem 'foo'
-
-
-
- Gemfile.lock:
-
-
-
- foo (1.4.3)
- bar (~> 2.0)
- bar (2.0.3)
-
-
-
- Cases:
-
-
-
- # Command Line Result
- ------------------------------------------------------------
- 1 bundle update --patch 'foo 1.4.5', 'bar 2.1.1'
- 2 bundle update --patch foo 'foo 1.4.5', 'bar 2.1.1'
- 3 bundle update --minor 'foo 1.5.1', 'bar 3.0.0'
- 4 bundle update --minor --strict 'foo 1.5.0', 'bar 2.1.1'
- 5 bundle update --patch --strict 'foo 1.4.4', 'bar 2.0.4'
-
-
-
- In case 1, bar is upgraded to 2.1.1, a minor version increase, because
- the dependency from foo 1.4.5 required it.
-
- In case 2, only foo is requested to be unlocked, but bar is also
- allowed to move because it's not a declared dependency in the Gemfile.
-
- In case 3, bar goes up a whole major release, because a minor increase
- is preferred now for foo, and when it goes to 1.5.1, it requires 3.0.0
- of bar.
-
- In case 4, foo is preferred up to a minor version, but 1.5.1 won't work
- because the --strict flag removes bar 3.0.0 from consideration since
- it's a major increment.
-
- In case 5, both foo and bar have any minor or major increments removed
- from consideration because of the --strict flag, so the most they can
- move is up to 1.4.4 and 2.0.4.
-
-RECOMMENDED WORKFLOW
- In general, when working with an application managed with bundler, you
- should use the following workflow:
-
- o After you create your Gemfile(5) for the first time, run
-
- $ bundle install
-
- o Check the resulting Gemfile.lock into version control
-
- $ git add Gemfile.lock
-
- o When checking out this repository on another development machine,
- run
-
- $ bundle install
-
- o When checking out this repository on a deployment machine, run
-
- $ bundle install --deployment
-
- o After changing the Gemfile(5) to reflect a new or update depen-
- dency, run
-
- $ bundle install
-
- o Make sure to check the updated Gemfile.lock into version control
-
- $ git add Gemfile.lock
-
- o If bundle install(1) bundle-install.1.html reports a conflict, man-
- ually update the specific gems that you changed in the Gemfile(5)
-
- $ bundle update rails thin
-
- o If you want to update all the gems to the latest possible versions
- that still match the gems listed in the Gemfile(5), run
-
- $ bundle update --all
-
-
-
-
-
-
- January 2020 BUNDLE-UPDATE(1)
diff --git a/man/bundle-update.ronn b/man/bundle-update.ronn
deleted file mode 100644
index 397fecadcb..0000000000
--- a/man/bundle-update.ronn
+++ /dev/null
@@ -1,350 +0,0 @@
-bundle-update(1) -- Update your gems to the latest available versions
-=====================================================================
-
-## SYNOPSIS
-
-`bundle update` <*gems> [--all]
- [--group=NAME]
- [--source=NAME]
- [--local]
- [--ruby]
- [--bundler[=VERSION]]
- [--full-index]
- [--jobs=JOBS]
- [--quiet]
- [--patch|--minor|--major]
- [--redownload]
- [--strict]
- [--conservative]
-
-## DESCRIPTION
-
-Update the gems specified (all gems, if `--all` flag is used), ignoring
-the previously installed gems specified in the `Gemfile.lock`. In
-general, you should use [bundle install(1)](bundle-install.1.html) to install the same exact
-gems and versions across machines.
-
-You would use `bundle update` to explicitly update the version of a
-gem.
-
-## OPTIONS
-
-* `--all`:
- Update all gems specified in Gemfile.
-
-* `--group=<name>`, `-g=[<name>]`:
- 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>`:
- The name of a `:git` or `:path` source used in the Gemfile(5). For
- instance, with a `:git` source of `http://github.com/rails/rails.git`,
- you would call `bundle update --source rails`
-
-* `--local`:
- Do not attempt to fetch gems remotely and use the gem cache instead.
-
-* `--ruby`:
- Update the locked version of Ruby to the current version of Ruby.
-
-* `--bundler`:
- Update the locked version of bundler to the invoked bundler version.
-
-* `--full-index`:
- Fall back to using the single-file index of all gems.
-
-* `--jobs=[<number>]`, `-j[<number>]`:
- Specify the number of jobs to run in parallel. The default is `1`.
-
-* `--retry=[<number>]`:
- Retry failed network or git requests for <number> times.
-
-* `--quiet`:
- Only output warnings and errors.
-
-* `--redownload`:
- Force downloading every gem.
-
-* `--patch`:
- Prefer updating only to next patch version.
-
-* `--minor`:
- Prefer updating only to next minor version.
-
-* `--major`:
- Prefer updating to next major version (default).
-
-* `--strict`:
- Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`.
-
-* `--conservative`:
- Use bundle install conservative update behavior and do not allow shared dependencies to be updated.
-
-## UPDATING ALL GEMS
-
-If you run `bundle update --all`, bundler will ignore
-any previously installed gems and resolve all dependencies again
-based on the latest versions of all gems available in the sources.
-
-Consider the following Gemfile(5):
-
- source "https://rubygems.org"
-
- gem "rails", "3.0.0.rc"
- gem "nokogiri"
-
-When you run [bundle install(1)](bundle-install.1.html) the first time, bundler will resolve
-all of the dependencies, all the way down, and install what you need:
-
- Fetching gem metadata from https://rubygems.org/.........
- Resolving dependencies...
- Installing builder 2.1.2
- Installing abstract 1.0.0
- Installing rack 1.2.8
- Using bundler 1.7.6
- Installing rake 10.4.0
- Installing polyglot 0.3.5
- Installing mime-types 1.25.1
- Installing i18n 0.4.2
- Installing mini_portile 0.6.1
- Installing tzinfo 0.3.42
- Installing rack-mount 0.6.14
- Installing rack-test 0.5.7
- Installing treetop 1.4.15
- Installing thor 0.14.6
- Installing activesupport 3.0.0.rc
- Installing erubis 2.6.6
- Installing activemodel 3.0.0.rc
- Installing arel 0.4.0
- Installing mail 2.2.20
- Installing activeresource 3.0.0.rc
- Installing actionpack 3.0.0.rc
- Installing activerecord 3.0.0.rc
- Installing actionmailer 3.0.0.rc
- Installing railties 3.0.0.rc
- Installing rails 3.0.0.rc
- Installing nokogiri 1.6.5
-
- Bundle complete! 2 Gemfile dependencies, 26 gems total.
- Use `bundle show [gemname]` to see where a bundled gem is installed.
-
-As you can see, even though you have two gems in the Gemfile(5), your application
-needs 26 different gems in order to run. Bundler remembers the exact versions
-it installed in `Gemfile.lock`. The next time you run [bundle install(1)](bundle-install.1.html), bundler skips
-the dependency resolution and installs the same gems as it installed last time.
-
-After checking in the `Gemfile.lock` into version control and cloning it on another
-machine, running [bundle install(1)](bundle-install.1.html) will _still_ install the gems that you installed
-last time. You don't need to worry that a new release of `erubis` or `mail` changes
-the gems you use.
-
-However, from time to time, you might want to update the gems you are using to the
-newest versions that still match the gems in your Gemfile(5).
-
-To do this, run `bundle update --all`, which will ignore the `Gemfile.lock`, and resolve
-all the dependencies again. Keep in mind that this process can result in a significantly
-different set of the 25 gems, based on the requirements of new gems that the gem
-authors released since the last time you ran `bundle update --all`.
-
-## UPDATING A LIST OF GEMS
-
-Sometimes, you want to update a single gem in the Gemfile(5), and leave the rest of the
-gems that you specified locked to the versions in the `Gemfile.lock`.
-
-For instance, in the scenario above, imagine that `nokogiri` releases version `1.4.4`, and
-you want to update it _without_ updating Rails and all of its dependencies. To do this,
-run `bundle update nokogiri`.
-
-Bundler will update `nokogiri` and any of its dependencies, but leave alone Rails and
-its dependencies.
-
-## OVERLAPPING DEPENDENCIES
-
-Sometimes, multiple gems declared in your Gemfile(5) are satisfied by the same
-second-level dependency. For instance, consider the case of `thin` and
-`rack-perftools-profiler`.
-
- source "https://rubygems.org"
-
- gem "thin"
- gem "rack-perftools-profiler"
-
-The `thin` gem depends on `rack >= 1.0`, while `rack-perftools-profiler` depends
-on `rack ~> 1.0`. If you run bundle install, you get:
-
- Fetching source index for https://rubygems.org/
- Installing daemons (1.1.0)
- Installing eventmachine (0.12.10) with native extensions
- Installing open4 (1.0.1)
- Installing perftools.rb (0.4.7) with native extensions
- Installing rack (1.2.1)
- Installing rack-perftools_profiler (0.0.2)
- Installing thin (1.2.7) with native extensions
- Using bundler (1.0.0.rc.3)
-
-In this case, the two gems have their own set of dependencies, but they share
-`rack` in common. If you run `bundle update thin`, bundler will update `daemons`,
-`eventmachine` and `rack`, which are dependencies of `thin`, but not `open4` or
-`perftools.rb`, which are dependencies of `rack-perftools_profiler`. Note that
-`bundle update thin` will update `rack` even though it's _also_ a dependency of
-`rack-perftools_profiler`.
-
-In short, by default, when you update a gem using `bundle update`, bundler will
-update all dependencies of that gem, including those that are also dependencies
-of another gem.
-
-To prevent updating shared dependencies, prior to version 1.14 the only option
-was the `CONSERVATIVE UPDATING` behavior in [bundle install(1)](bundle-install.1.html):
-
-In this scenario, updating the `thin` version manually in the Gemfile(5),
-and then running [bundle install(1)](bundle-install.1.html) will only update `daemons` and `eventmachine`,
-but not `rack`. For more information, see the `CONSERVATIVE UPDATING` section
-of [bundle install(1)](bundle-install.1.html).
-
-Starting with 1.14, specifying the `--conservative` option will also prevent shared
-dependencies from being updated.
-
-## PATCH LEVEL OPTIONS
-
-Version 1.14 introduced 4 patch-level options that will influence how gem
-versions are resolved. One of the following options can be used: `--patch`,
-`--minor` or `--major`. `--strict` can be added to further influence resolution.
-
-* `--patch`:
- Prefer updating only to next patch version.
-
-* `--minor`:
- Prefer updating only to next minor version.
-
-* `--major`:
- Prefer updating to next major version (default).
-
-* `--strict`:
- Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`.
-
-When Bundler is resolving what versions to use to satisfy declared
-requirements in the Gemfile or in parent gems, it looks up all
-available versions, filters out any versions that don't satisfy
-the requirement, and then, by default, sorts them from newest to
-oldest, considering them in that order.
-
-Providing one of the patch level options (e.g. `--patch`) changes the
-sort order of the satisfying versions, causing Bundler to consider the
-latest `--patch` or `--minor` version available before other versions.
-Note that versions outside the stated patch level could still be
-resolved to if necessary to find a suitable dependency graph.
-
-For example, if gem 'foo' is locked at 1.0.2, with no gem requirement
-defined in the Gemfile, and versions 1.0.3, 1.0.4, 1.1.0, 1.1.1, 2.0.0
-all exist, the default order of preference by default (`--major`) will
-be "2.0.0, 1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2".
-
-If the `--patch` option is used, the order of preference will change to
-"1.0.4, 1.0.3, 1.0.2, 1.1.1, 1.1.0, 2.0.0".
-
-If the `--minor` option is used, the order of preference will change to
-"1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2, 2.0.0".
-
-Combining the `--strict` option with any of the patch level options
-will remove any versions beyond the scope of the patch level option,
-to ensure that no gem is updated that far.
-
-To continue the previous example, if both `--patch` and `--strict`
-options are used, the available versions for resolution would be
-"1.0.4, 1.0.3, 1.0.2". If `--minor` and `--strict` are used, it would
-be "1.1.1, 1.1.0, 1.0.4, 1.0.3, 1.0.2".
-
-Gem requirements as defined in the Gemfile will still be the first
-determining factor for what versions are available. If the gem
-requirement for `foo` in the Gemfile is '~> 1.0', that will accomplish
-the same thing as providing the `--minor` and `--strict` options.
-
-## PATCH LEVEL EXAMPLES
-
-Given the following gem specifications:
-
- foo 1.4.3, requires: ~> bar 2.0
- foo 1.4.4, requires: ~> bar 2.0
- foo 1.4.5, requires: ~> bar 2.1
- foo 1.5.0, requires: ~> bar 2.1
- foo 1.5.1, requires: ~> bar 3.0
- bar with versions 2.0.3, 2.0.4, 2.1.0, 2.1.1, 3.0.0
-
-Gemfile:
-
- gem 'foo'
-
-Gemfile.lock:
-
- foo (1.4.3)
- bar (~> 2.0)
- bar (2.0.3)
-
-Cases:
-
- # Command Line Result
- ------------------------------------------------------------
- 1 bundle update --patch 'foo 1.4.5', 'bar 2.1.1'
- 2 bundle update --patch foo 'foo 1.4.5', 'bar 2.1.1'
- 3 bundle update --minor 'foo 1.5.1', 'bar 3.0.0'
- 4 bundle update --minor --strict 'foo 1.5.0', 'bar 2.1.1'
- 5 bundle update --patch --strict 'foo 1.4.4', 'bar 2.0.4'
-
-In case 1, bar is upgraded to 2.1.1, a minor version increase, because
-the dependency from foo 1.4.5 required it.
-
-In case 2, only foo is requested to be unlocked, but bar is also
-allowed to move because it's not a declared dependency in the Gemfile.
-
-In case 3, bar goes up a whole major release, because a minor increase
-is preferred now for foo, and when it goes to 1.5.1, it requires 3.0.0
-of bar.
-
-In case 4, foo is preferred up to a minor version, but 1.5.1 won't work
-because the --strict flag removes bar 3.0.0 from consideration since
-it's a major increment.
-
-In case 5, both foo and bar have any minor or major increments removed
-from consideration because of the --strict flag, so the most they can
-move is up to 1.4.4 and 2.0.4.
-
-## RECOMMENDED WORKFLOW
-
-In general, when working with an application managed with bundler, you should
-use the following workflow:
-
-* After you create your Gemfile(5) for the first time, run
-
- $ bundle install
-
-* Check the resulting `Gemfile.lock` into version control
-
- $ git add Gemfile.lock
-
-* When checking out this repository on another development machine, run
-
- $ bundle install
-
-* When checking out this repository on a deployment machine, run
-
- $ bundle install --deployment
-
-* After changing the Gemfile(5) to reflect a new or update dependency, run
-
- $ bundle install
-
-* Make sure to check the updated `Gemfile.lock` into version control
-
- $ git add Gemfile.lock
-
-* If [bundle install(1)](bundle-install.1.html) reports a conflict, manually update the specific
- gems that you changed in the Gemfile(5)
-
- $ bundle update rails thin
-
-* If you want to update all the gems to the latest possible versions that
- still match the gems listed in the Gemfile(5), run
-
- $ bundle update --all
diff --git a/man/bundle-viz.1 b/man/bundle-viz.1
deleted file mode 100644
index a2153da28d..0000000000
--- a/man/bundle-viz.1
+++ /dev/null
@@ -1,39 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE\-VIZ" "1" "January 2020" "" ""
-.
-.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\.
-.
-.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/man/bundle-viz.1.txt b/man/bundle-viz.1.txt
deleted file mode 100644
index c934b4cf5b..0000000000
--- a/man/bundle-viz.1.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-BUNDLE-VIZ(1) BUNDLE-VIZ(1)
-
-
-
-NAME
- bundle-viz - Generates a visual dependency graph for your Gemfile
-
-SYNOPSIS
- bundle viz [--file=FILE] [--format=FORMAT] [--requirements] [--version]
- [--without=GROUP GROUP]
-
-DESCRIPTION
- viz generates a PNG file of the current Gemfile(5) as a dependency
- graph. viz requires the ruby-graphviz gem (and its dependencies).
-
- The associated gems must also be installed via bundle install(1) bun-
- dle-install.1.html.
-
-OPTIONS
- --file, -f
- The name to use for the generated file. See --format option
-
- --format, -F
- This is output format option. Supported format is png, jpg, svg,
- dot ...
-
- --requirements, -R
- Set to show the version of each required dependency.
-
- --version, -v
- Set to show each gem version.
-
- --without, -W
- Exclude gems that are part of the specified named group.
-
-
-
-
- January 2020 BUNDLE-VIZ(1)
diff --git a/man/bundle.1 b/man/bundle.1
deleted file mode 100644
index 4a9a9bec4d..0000000000
--- a/man/bundle.1
+++ /dev/null
@@ -1,136 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "BUNDLE" "1" "January 2020" "" ""
-.
-.SH "NAME"
-\fBbundle\fR \- Ruby Dependency Management
-.
-.SH "SYNOPSIS"
-\fBbundle\fR COMMAND [\-\-no\-color] [\-\-verbose] [ARGS]
-.
-.SH "DESCRIPTION"
-Bundler manages an \fBapplication\'s dependencies\fR through its entire life across many machines systematically and repeatably\.
-.
-.P
-See the bundler website \fIhttps://bundler\.io\fR for information on getting started, and Gemfile(5) for more information on the \fBGemfile\fR format\.
-.
-.SH "OPTIONS"
-.
-.TP
-\fB\-\-no\-color\fR
-Print all output without color
-.
-.TP
-\fB\-\-retry\fR, \fB\-r\fR
-Specify the number of times you wish to attempt network commands
-.
-.TP
-\fB\-\-verbose\fR, \fB\-V\fR
-Print out additional logging information
-.
-.SH "BUNDLE COMMANDS"
-We divide \fBbundle\fR subcommands into primary commands and utilities:
-.
-.SH "PRIMARY COMMANDS"
-.
-.TP
-\fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR
-Install the gems specified by the \fBGemfile\fR or \fBGemfile\.lock\fR
-.
-.TP
-\fBbundle update(1)\fR \fIbundle\-update\.1\.html\fR
-Update dependencies to their latest versions
-.
-.TP
-\fBbundle package(1)\fR \fIbundle\-package\.1\.html\fR
-Package the \.gem files required by your application into the \fBvendor/cache\fR directory
-.
-.TP
-\fBbundle exec(1)\fR \fIbundle\-exec\.1\.html\fR
-Execute a script in the current bundle
-.
-.TP
-\fBbundle config(1)\fR \fIbundle\-config\.1\.html\fR
-Specify and read configuration options for Bundler
-.
-.TP
-\fBbundle help(1)\fR
-Display detailed help for each subcommand
-.
-.SH "UTILITIES"
-.
-.TP
-\fBbundle add(1)\fR \fIbundle\-add\.1\.html\fR
-Add the named gem to the Gemfile and run \fBbundle install\fR
-.
-.TP
-\fBbundle binstubs(1)\fR \fIbundle\-binstubs\.1\.html\fR
-Generate binstubs for executables in a gem
-.
-.TP
-\fBbundle check(1)\fR \fIbundle\-check\.1\.html\fR
-Determine whether the requirements for your application are installed and available to Bundler
-.
-.TP
-\fBbundle show(1)\fR \fIbundle\-show\.1\.html\fR
-Show the source location of a particular gem in the bundle
-.
-.TP
-\fBbundle outdated(1)\fR \fIbundle\-outdated\.1\.html\fR
-Show all of the outdated gems in the current bundle
-.
-.TP
-\fBbundle console(1)\fR
-Start an IRB session in the current bundle
-.
-.TP
-\fBbundle open(1)\fR \fIbundle\-open\.1\.html\fR
-Open an installed gem in the editor
-.
-.TP
-\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
-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
-\fBbundle gem(1)\fR \fIbundle\-gem\.1\.html\fR
-Create a simple gem, suitable for development with Bundler
-.
-.TP
-\fBbundle platform(1)\fR \fIbundle\-platform\.1\.html\fR
-Display platform compatibility information
-.
-.TP
-\fBbundle clean(1)\fR \fIbundle\-clean\.1\.html\fR
-Clean up unused gems in your Bundler directory
-.
-.TP
-\fBbundle doctor(1)\fR \fIbundle\-doctor\.1\.html\fR
-Display warnings about common problems
-.
-.TP
-\fBbundle remove(1)\fR \fIbundle\-remove\.1\.html\fR
-Removes gems from the Gemfile
-.
-.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 cache(1)\fR
-.
-.IP "\(bu" 4
-\fBbundle show(1)\fR
-.
-.IP "" 0
-
diff --git a/man/bundle.1.txt b/man/bundle.1.txt
deleted file mode 100644
index e7eb35aa14..0000000000
--- a/man/bundle.1.txt
+++ /dev/null
@@ -1,116 +0,0 @@
-BUNDLE(1) BUNDLE(1)
-
-
-
-NAME
- bundle - Ruby Dependency Management
-
-SYNOPSIS
- bundle COMMAND [--no-color] [--verbose] [ARGS]
-
-DESCRIPTION
- Bundler manages an application's dependencies through its entire life
- across many machines systematically and repeatably.
-
- See the bundler website https://bundler.io for information on getting
- started, and Gemfile(5) for more information on the Gemfile format.
-
-OPTIONS
- --no-color
- Print all output without color
-
- --retry, -r
- Specify the number of times you wish to attempt network commands
-
- --verbose, -V
- Print out additional logging information
-
-BUNDLE COMMANDS
- We divide bundle subcommands into primary commands and utilities:
-
-PRIMARY COMMANDS
- bundle install(1) bundle-install.1.html
- Install the gems specified by the Gemfile or Gemfile.lock
-
- bundle update(1) bundle-update.1.html
- Update dependencies to their latest versions
-
- bundle package(1) bundle-package.1.html
- Package the .gem files required by your application into the
- vendor/cache directory
-
- bundle exec(1) bundle-exec.1.html
- Execute a script in the current bundle
-
- bundle config(1) bundle-config.1.html
- Specify and read configuration options for Bundler
-
- bundle help(1)
- Display detailed help for each subcommand
-
-UTILITIES
- bundle add(1) bundle-add.1.html
- Add the named gem to the Gemfile and run bundle install
-
- bundle binstubs(1) bundle-binstubs.1.html
- Generate binstubs for executables in a gem
-
- bundle check(1) bundle-check.1.html
- Determine whether the requirements for your application are
- installed and available to Bundler
-
- bundle show(1) bundle-show.1.html
- Show the source location of a particular gem in the bundle
-
- bundle outdated(1) bundle-outdated.1.html
- Show all of the outdated gems in the current bundle
-
- bundle console(1)
- Start an IRB session in the current bundle
-
- bundle open(1) bundle-open.1.html
- Open an installed gem in the editor
-
- bundle lock(1) bundle-lock.1.html
- Generate a lockfile for your dependencies
-
- bundle viz(1) bundle-viz.1.html
- Generate a visual representation of your dependencies
-
- bundle init(1) bundle-init.1.html
- Generate a simple Gemfile, placed in the current directory
-
- bundle gem(1) bundle-gem.1.html
- Create a simple gem, suitable for development with Bundler
-
- bundle platform(1) bundle-platform.1.html
- Display platform compatibility information
-
- bundle clean(1) bundle-clean.1.html
- Clean up unused gems in your Bundler directory
-
- bundle doctor(1) bundle-doctor.1.html
- Display warnings about common problems
-
- bundle remove(1) bundle-remove.1.html
- Removes gems from the Gemfile
-
-PLUGINS
- When running a command that isn't listed in PRIMARY COMMANDS or UTILI-
- TIES, Bundler will try to find an executable on your path named
- bundler-<command> and execute it, passing down any extra arguments to
- it.
-
-OBSOLETE
- These commands are obsolete and should no longer be used:
-
- o bundle cache(1)
-
- o bundle show(1)
-
-
-
-
-
-
- January 2020 BUNDLE(1)
diff --git a/man/gemfile.5 b/man/gemfile.5
deleted file mode 100644
index a9d2cee7c7..0000000000
--- a/man/gemfile.5
+++ /dev/null
@@ -1,686 +0,0 @@
-.\" generated with Ronn/v0.7.3
-.\" http://github.com/rtomayko/ronn/tree/0.7.3
-.
-.TH "GEMFILE" "5" "January 2020" "" ""
-.
-.SH "NAME"
-\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
-.
-.SH "SYNOPSIS"
-A \fBGemfile\fR describes the gem dependencies required to execute associated Ruby code\.
-.
-.P
-Place the \fBGemfile\fR in the root of the directory containing the associated code\. For instance, in a Rails application, place the \fBGemfile\fR in the same directory as the \fBRakefile\fR\.
-.
-.SH "SYNTAX"
-A \fBGemfile\fR is evaluated as Ruby code, in a context which makes available a number of methods used to describe the gem requirements\.
-.
-.SH "GLOBAL SOURCES"
-At the top of the \fBGemfile\fR, add a line for the \fBRubygems\fR source that contains the gems listed in the \fBGemfile\fR\.
-.
-.IP "" 4
-.
-.nf
-
-source "https://rubygems\.org"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-It is possible, but not recommended as of Bundler 1\.7, to add multiple global \fBsource\fR lines\. Each of these \fBsource\fRs \fBMUST\fR be a valid Rubygems repository\.
-.
-.P
-Sources are checked for gems following the heuristics described in \fISOURCE PRIORITY\fR\. If a gem is found in more than one global source, Bundler will print a warning after installing the gem indicating which source was used, and listing the other sources where the gem is available\. A specific source can be selected for gems that need to use a non\-standard repository, suppressing this warning, by using the \fI\fB:source\fR option\fR or a \fI\fBsource\fR block\fR\.
-.
-.SS "CREDENTIALS"
-Some gem sources require a username and password\. Use bundle config(1) \fIbundle\-config\.1\.html\fR to set the username and password for any of the sources that need it\. The command must be run once on each computer that will install the Gemfile, but this keeps the credentials from being stored in plain text in version control\.
-.
-.IP "" 4
-.
-.nf
-
-bundle config gems\.example\.com user:password
-.
-.fi
-.
-.IP "" 0
-.
-.P
-For some sources, like a company Gemfury account, it may be easier to include the credentials in the Gemfile as part of the source URL\.
-.
-.IP "" 4
-.
-.nf
-
-source "https://user:password@gems\.example\.com"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Credentials in the source URL will take precedence over credentials set using \fBconfig\fR\.
-.
-.SH "RUBY"
-If your application requires a specific Ruby version or engine, specify your requirements using the \fBruby\fR method, with the following arguments\. All parameters are \fBOPTIONAL\fR unless otherwise specified\.
-.
-.SS "VERSION (required)"
-The version of Ruby that your application requires\. If your application requires an alternate Ruby engine, such as JRuby, Rubinius or TruffleRuby, this should be the Ruby version that the engine is compatible with\.
-.
-.IP "" 4
-.
-.nf
-
-ruby "1\.9\.3"
-.
-.fi
-.
-.IP "" 0
-.
-.SS "ENGINE"
-Each application \fImay\fR specify a Ruby engine\. If an engine is specified, an engine version \fImust\fR also be specified\.
-.
-.P
-What exactly is an Engine? \- A Ruby engine is an implementation of the Ruby language\.
-.
-.IP "\(bu" 4
-For background: the reference or original implementation of the Ruby programming language is called Matz\'s Ruby Interpreter \fIhttps://en\.wikipedia\.org/wiki/Ruby_MRI\fR, or MRI for short\. This is named after Ruby creator Yukihiro Matsumoto, also known as Matz\. MRI is also known as CRuby, because it is written in C\. MRI is the most widely used Ruby engine\.
-.
-.IP "\(bu" 4
-Other implementations \fIhttps://www\.ruby\-lang\.org/en/about/\fR of Ruby exist\. Some of the more well\-known implementations include Rubinius \fIhttps://rubinius\.com/\fR, and JRuby \fIhttp://jruby\.org/\fR\. Rubinius is an alternative implementation of Ruby written in Ruby\. JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine\.
-.
-.IP "" 0
-.
-.SS "ENGINE VERSION"
-Each application \fImay\fR specify a Ruby engine version\. If an engine version is specified, an engine \fImust\fR also be specified\. If the engine is "ruby" the engine version specified \fImust\fR match the Ruby version\.
-.
-.IP "" 4
-.
-.nf
-
-ruby "1\.8\.7", :engine => "jruby", :engine_version => "1\.6\.7"
-.
-.fi
-.
-.IP "" 0
-.
-.SS "PATCHLEVEL"
-Each application \fImay\fR specify a Ruby patchlevel\.
-.
-.IP "" 4
-.
-.nf
-
-ruby "2\.0\.0", :patchlevel => "247"
-.
-.fi
-.
-.IP "" 0
-.
-.SH "GEMS"
-Specify gem requirements using the \fBgem\fR method, with the following arguments\. All parameters are \fBOPTIONAL\fR unless otherwise specified\.
-.
-.SS "NAME (required)"
-For each gem requirement, list a single \fIgem\fR line\.
-.
-.IP "" 4
-.
-.nf
-
-gem "nokogiri"
-.
-.fi
-.
-.IP "" 0
-.
-.SS "VERSION"
-Each \fIgem\fR \fBMAY\fR have one or more version specifiers\.
-.
-.IP "" 4
-.
-.nf
-
-gem "nokogiri", ">= 1\.4\.2"
-gem "RedCloth", ">= 4\.1\.0", "< 4\.2\.0"
-.
-.fi
-.
-.IP "" 0
-.
-.SS "REQUIRE AS"
-Each \fIgem\fR \fBMAY\fR specify files that should be used when autorequiring via \fBBundler\.require\fR\. You may pass an array with multiple files or \fBtrue\fR if file you want \fBrequired\fR has same name as \fIgem\fR or \fBfalse\fR to prevent any file from being autorequired\.
-.
-.IP "" 4
-.
-.nf
-
-gem "redis", :require => ["redis/connection/hiredis", "redis"]
-gem "webmock", :require => false
-gem "byebug", :require => true
-.
-.fi
-.
-.IP "" 0
-.
-.P
-The argument defaults to the name of the gem\. For example, these are identical:
-.
-.IP "" 4
-.
-.nf
-
-gem "nokogiri"
-gem "nokogiri", :require => "nokogiri"
-gem "nokogiri", :require => true
-.
-.fi
-.
-.IP "" 0
-.
-.SS "GROUPS"
-Each \fIgem\fR \fBMAY\fR specify membership in one or more groups\. Any \fIgem\fR that does not specify membership in any group is placed in the \fBdefault\fR group\.
-.
-.IP "" 4
-.
-.nf
-
-gem "rspec", :group => :test
-gem "wirble", :groups => [:development, :test]
-.
-.fi
-.
-.IP "" 0
-.
-.P
-The Bundler runtime allows its two main methods, \fBBundler\.setup\fR and \fBBundler\.require\fR, to limit their impact to particular groups\.
-.
-.IP "" 4
-.
-.nf
-
-# setup adds gems to Ruby\'s load path
-Bundler\.setup # defaults to all groups
-require "bundler/setup" # same as Bundler\.setup
-Bundler\.setup(:default) # only set up the _default_ group
-Bundler\.setup(:test) # only set up the _test_ group (but `not` _default_)
-Bundler\.setup(:default, :test) # set up the _default_ and _test_ groups, but no others
-
-# require requires all of the gems in the specified groups
-Bundler\.require # defaults to the _default_ group
-Bundler\.require(:default) # identical
-Bundler\.require(:default, :test) # requires the _default_ and _test_ groups
-Bundler\.require(:test) # requires the _test_ group
-.
-.fi
-.
-.IP "" 0
-.
-.P
-The Bundler CLI allows you to specify a list of groups whose gems \fBbundle install\fR should not install with the \fBwithout\fR configuration\.
-.
-.P
-To specify multiple groups to ignore, specify a list of groups separated by spaces\.
-.
-.IP "" 4
-.
-.nf
-
-bundle config set without test
-bundle config set without development test
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Also, calling \fBBundler\.setup\fR with no parameters, or calling \fBrequire "bundler/setup"\fR will setup all groups except for the ones you excluded via \fB\-\-without\fR (since they are not available)\.
-.
-.P
-Note that on \fBbundle install\fR, bundler downloads and evaluates all gems, in order to create a single canonical list of all of the required gems and their dependencies\. This means that you cannot list different versions of the same gems in different groups\. For more details, see Understanding Bundler \fIhttps://bundler\.io/rationale\.html\fR\.
-.
-.SS "PLATFORMS"
-If a gem should only be used in a particular platform or set of platforms, you can specify them\. Platforms are essentially identical to groups, except that you do not need to use the \fB\-\-without\fR install\-time flag to exclude groups of gems for other platforms\.
-.
-.P
-There are a number of \fBGemfile\fR platforms:
-.
-.TP
-\fBruby\fR
-C Ruby (MRI), Rubinius or TruffleRuby, but \fBNOT\fR Windows
-.
-.TP
-\fBmri\fR
-Same as \fIruby\fR, but only C Ruby (MRI)
-.
-.TP
-\fBmingw\fR
-Windows 32 bit \'mingw32\' platform (aka RubyInstaller)
-.
-.TP
-\fBx64_mingw\fR
-Windows 64 bit \'mingw32\' platform (aka RubyInstaller x64)
-.
-.TP
-\fBrbx\fR
-Rubinius
-.
-.TP
-\fBjruby\fR
-JRuby
-.
-.TP
-\fBtruffleruby\fR
-TruffleRuby
-.
-.TP
-\fBmswin\fR
-Windows
-.
-.P
-You can restrict further by platform and version for all platforms \fIexcept\fR for \fBrbx\fR, \fBjruby\fR, \fBtruffleruby\fR and \fBmswin\fR\.
-.
-.P
-To specify a version in addition to a platform, append the version number without the delimiter to the platform\. For example, to specify that a gem should only be used on platforms with Ruby 2\.3, use:
-.
-.IP "" 4
-.
-.nf
-
-ruby_23
-.
-.fi
-.
-.IP "" 0
-.
-.P
-The full list of platforms and supported versions includes:
-.
-.TP
-\fBruby\fR
-1\.8, 1\.9, 2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
-.
-.TP
-\fBmri\fR
-1\.8, 1\.9, 2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
-.
-.TP
-\fBmingw\fR
-1\.8, 1\.9, 2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
-.
-.TP
-\fBx64_mingw\fR
-2\.0, 2\.1, 2\.2, 2\.3, 2\.4, 2\.5, 2\.6
-.
-.P
-As with groups, you can specify one or more platforms:
-.
-.IP "" 4
-.
-.nf
-
-gem "weakling", :platforms => :jruby
-gem "ruby\-debug", :platforms => :mri_18
-gem "nokogiri", :platforms => [:mri_18, :jruby]
-.
-.fi
-.
-.IP "" 0
-.
-.P
-All operations involving groups (\fBbundle install\fR \fIbundle\-install\.1\.html\fR, \fBBundler\.setup\fR, \fBBundler\.require\fR) behave exactly the same as if any groups not matching the current platform were explicitly excluded\.
-.
-.SS "SOURCE"
-You can select an alternate Rubygems repository for a gem using the \':source\' option\.
-.
-.IP "" 4
-.
-.nf
-
-gem "some_internal_gem", :source => "https://gems\.example\.com"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-This forces the gem to be loaded from this source and ignores any global sources declared at the top level of the file\. If the gem does not exist in this source, it will not be installed\.
-.
-.P
-Bundler will search for child dependencies of this gem by first looking in the source selected for the parent, but if they are not found there, it will fall back on global sources using the ordering described in \fISOURCE PRIORITY\fR\.
-.
-.P
-Selecting a specific source repository this way also suppresses the ambiguous gem warning described above in \fIGLOBAL SOURCES (#source)\fR\.
-.
-.P
-Using the \fB:source\fR option for an individual gem will also make that source available as a possible global source for any other gems which do not specify explicit sources\. Thus, when adding gems with explicit sources, it is recommended that you also ensure all other gems in the Gemfile are using explicit sources\.
-.
-.SS "GIT"
-If necessary, you can specify that a gem is located at a particular git repository using the \fB:git\fR parameter\. The repository can be accessed via several protocols:
-.
-.TP
-\fBHTTP(S)\fR
-gem "rails", :git => "https://github\.com/rails/rails\.git"
-.
-.TP
-\fBSSH\fR
-gem "rails", :git => "git@github\.com:rails/rails\.git"
-.
-.TP
-\fBgit\fR
-gem "rails", :git => "git://github\.com/rails/rails\.git"
-.
-.P
-If using SSH, the user that you use to run \fBbundle install\fR \fBMUST\fR have the appropriate keys available in their \fB$HOME/\.ssh\fR\.
-.
-.P
-\fBNOTE\fR: \fBhttp://\fR and \fBgit://\fR URLs should be avoided if at all possible\. These protocols are unauthenticated, so a man\-in\-the\-middle attacker can deliver malicious code and compromise your system\. HTTPS and SSH are strongly preferred\.
-.
-.P
-The \fBgroup\fR, \fBplatforms\fR, and \fBrequire\fR options are available and behave exactly the same as they would for a normal gem\.
-.
-.P
-A git repository \fBSHOULD\fR have at least one file, at the root of the directory containing the gem, with the extension \fB\.gemspec\fR\. This file \fBMUST\fR contain a valid gem specification, as expected by the \fBgem build\fR command\.
-.
-.P
-If a git repository does not have a \fB\.gemspec\fR, bundler will attempt to create one, but it will not contain any dependencies, executables, or C extension compilation instructions\. As a result, it may fail to properly integrate into your application\.
-.
-.P
-If a git repository does have a \fB\.gemspec\fR for the gem you attached it to, a version specifier, if provided, means that the git repository is only valid if the \fB\.gemspec\fR specifies a version matching the version specifier\. If not, bundler will print a warning\.
-.
-.IP "" 4
-.
-.nf
-
-gem "rails", "2\.3\.8", :git => "https://github\.com/rails/rails\.git"
-# bundle install will fail, because the \.gemspec in the rails
-# repository\'s master branch specifies version 3\.0\.0
-.
-.fi
-.
-.IP "" 0
-.
-.P
-If a git repository does \fBnot\fR have a \fB\.gemspec\fR for the gem you attached it to, a version specifier \fBMUST\fR be provided\. Bundler will use this version in the simple \fB\.gemspec\fR it creates\.
-.
-.P
-Git repositories support a number of additional options\.
-.
-.TP
-\fBbranch\fR, \fBtag\fR, and \fBref\fR
-You \fBMUST\fR only specify at most one of these options\. The default is \fB:branch => "master"\fR\. For example:
-.
-.IP
-gem "rails", :git => "https://github\.com/rails/rails\.git", :branch => "5\-0\-stable"
-.
-.IP
-gem "rails", :git => "https://github\.com/rails/rails\.git", :tag => "v5\.0\.0"
-.
-.IP
-gem "rails", :git => "https://github\.com/rails/rails\.git", :ref => "4aded"
-.
-.TP
-\fBsubmodules\fR
-For reference, a git submodule \fIhttps://git\-scm\.com/book/en/v2/Git\-Tools\-Submodules\fR lets you have another git repository within a subfolder of your repository\. Specify \fB:submodules => true\fR to cause bundler to expand any submodules included in the git repository
-.
-.P
-If a git repository contains multiple \fB\.gemspecs\fR, each \fB\.gemspec\fR represents a gem located at the same place in the file system as the \fB\.gemspec\fR\.
-.
-.IP "" 4
-.
-.nf
-
-|~rails [git root]
-| |\-rails\.gemspec [rails gem located here]
-|~actionpack
-| |\-actionpack\.gemspec [actionpack gem located here]
-|~activesupport
-| |\-activesupport\.gemspec [activesupport gem located here]
-|\.\.\.
-.
-.fi
-.
-.IP "" 0
-.
-.P
-To install a gem located in a git repository, bundler changes to the directory containing the gemspec, runs \fBgem build name\.gemspec\fR and then installs the resulting gem\. The \fBgem build\fR command, which comes standard with Rubygems, evaluates the \fB\.gemspec\fR in the context of the directory in which it is located\.
-.
-.SS "GIT SOURCE"
-A custom git source can be defined via the \fBgit_source\fR method\. Provide the source\'s name as an argument, and a block which receives a single argument and interpolates it into a string to return the full repo address:
-.
-.IP "" 4
-.
-.nf
-
-git_source(:stash){ |repo_name| "https://stash\.corp\.acme\.pl/#{repo_name}\.git" }
-gem \'rails\', :stash => \'forks/rails\'
-.
-.fi
-.
-.IP "" 0
-.
-.P
-In addition, if you wish to choose a specific branch:
-.
-.IP "" 4
-.
-.nf
-
-gem "rails", :stash => "forks/rails", :branch => "branch_name"
-.
-.fi
-.
-.IP "" 0
-.
-.SS "GITHUB"
-\fBNOTE\fR: This shorthand should be avoided until Bundler 2\.0, since it currently expands to an insecure \fBgit://\fR URL\. This allows a man\-in\-the\-middle attacker to compromise your system\.
-.
-.P
-If the git repository you want to use is hosted on GitHub and is public, you can use the :github shorthand to specify the github username and repository name (without the trailing "\.git"), separated by a slash\. If both the username and repository name are the same, you can omit one\.
-.
-.IP "" 4
-.
-.nf
-
-gem "rails", :github => "rails/rails"
-gem "rails", :github => "rails"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Are both equivalent to
-.
-.IP "" 4
-.
-.nf
-
-gem "rails", :git => "git://github\.com/rails/rails\.git"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Since the \fBgithub\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
-.
-.SS "GIST"
-If the git repository you want to use is hosted as a Github Gist and is public, you can use the :gist shorthand to specify the gist identifier (without the trailing "\.git")\.
-.
-.IP "" 4
-.
-.nf
-
-gem "the_hatch", :gist => "4815162342"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Is equivalent to:
-.
-.IP "" 4
-.
-.nf
-
-gem "the_hatch", :git => "https://gist\.github\.com/4815162342\.git"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Since the \fBgist\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
-.
-.SS "BITBUCKET"
-If the git repository you want to use is hosted on Bitbucket and is public, you can use the :bitbucket shorthand to specify the bitbucket username and repository name (without the trailing "\.git"), separated by a slash\. If both the username and repository name are the same, you can omit one\.
-.
-.IP "" 4
-.
-.nf
-
-gem "rails", :bitbucket => "rails/rails"
-gem "rails", :bitbucket => "rails"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Are both equivalent to
-.
-.IP "" 4
-.
-.nf
-
-gem "rails", :git => "https://rails@bitbucket\.org/rails/rails\.git"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-Since the \fBbitbucket\fR method is a specialization of \fBgit_source\fR, it accepts a \fB:branch\fR named argument\.
-.
-.SS "PATH"
-You can specify that a gem is located in a particular location on the file system\. Relative paths are resolved relative to the directory containing the \fBGemfile\fR\.
-.
-.P
-Similar to the semantics of the \fB:git\fR option, the \fB:path\fR option requires that the directory in question either contains a \fB\.gemspec\fR for the gem, or that you specify an explicit version that bundler should use\.
-.
-.P
-Unlike \fB:git\fR, bundler does not compile C extensions for gems specified as paths\.
-.
-.IP "" 4
-.
-.nf
-
-gem "rails", :path => "vendor/rails"
-.
-.fi
-.
-.IP "" 0
-.
-.P
-If you would like to use multiple local gems directly from the filesystem, you can set a global \fBpath\fR option to the path containing the gem\'s files\. This will automatically load gemspec files from subdirectories\.
-.
-.IP "" 4
-.
-.nf
-
-path \'components\' do
- gem \'admin_ui\'
- gem \'public_ui\'
-end
-.
-.fi
-.
-.IP "" 0
-.
-.SH "BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS"
-The \fB:source\fR, \fB:git\fR, \fB:path\fR, \fB:group\fR, and \fB:platforms\fR options may be applied to a group of gems by using block form\.
-.
-.IP "" 4
-.
-.nf
-
-source "https://gems\.example\.com" do
- gem "some_internal_gem"
- gem "another_internal_gem"
-end
-
-git "https://github\.com/rails/rails\.git" do
- gem "activesupport"
- gem "actionpack"
-end
-
-platforms :ruby do
- gem "ruby\-debug"
- gem "sqlite3"
-end
-
-group :development, :optional => true do
- gem "wirble"
- gem "faker"
-end
-.
-.fi
-.
-.IP "" 0
-.
-.P
-In the case of the group block form the :optional option can be given to prevent a group from being installed unless listed in the \fB\-\-with\fR option given to the \fBbundle install\fR command\.
-.
-.P
-In the case of the \fBgit\fR block form, the \fB:ref\fR, \fB:branch\fR, \fB:tag\fR, and \fB:submodules\fR options may be passed to the \fBgit\fR method, and all gems in the block will inherit those options\.
-.
-.P
-The presence of a \fBsource\fR block in a Gemfile also makes that source available as a possible global source for any other gems which do not specify explicit sources\. Thus, when defining source blocks, it is recommended that you also ensure all other gems in the Gemfile are using explicit sources, either via source blocks or \fB:source\fR directives on individual gems\.
-.
-.SH "INSTALL_IF"
-The \fBinstall_if\fR method allows gems to be installed based on a proc or lambda\. This is especially useful for optional gems that can only be used if certain software is installed or some other conditions are met\.
-.
-.IP "" 4
-.
-.nf
-
-install_if \-> { RUBY_PLATFORM =~ /darwin/ } do
- gem "pasteboard"
-end
-.
-.fi
-.
-.IP "" 0
-.
-.SH "GEMSPEC"
-The \fB\.gemspec\fR \fIhttp://guides\.rubygems\.org/specification\-reference/\fR file is where you provide metadata about your gem to Rubygems\. Some required Gemspec attributes include the name, description, and homepage of your gem\. This is also where you specify the dependencies your gem needs to run\.
-.
-.P
-If you wish to use Bundler to help install dependencies for a gem while it is being developed, use the \fBgemspec\fR method to pull in the dependencies listed in the \fB\.gemspec\fR file\.
-.
-.P
-The \fBgemspec\fR method adds any runtime dependencies as gem requirements in the default group\. It also adds development dependencies as gem requirements in the \fBdevelopment\fR group\. Finally, it adds a gem requirement on your project (\fB:path => \'\.\'\fR)\. In conjunction with \fBBundler\.setup\fR, this allows you to require project files in your test code as you would if the project were installed as a gem; you need not manipulate the load path manually or require project files via relative paths\.
-.
-.P
-The \fBgemspec\fR method supports optional \fB:path\fR, \fB:glob\fR, \fB:name\fR, and \fB:development_group\fR options, which control where bundler looks for the \fB\.gemspec\fR, the glob it uses to look for the gemspec (defaults to: "{,\fI,\fR/*}\.gemspec"), what named \fB\.gemspec\fR it uses (if more than one is present), and which group development dependencies are included in\.
-.
-.P
-When a \fBgemspec\fR dependency encounters version conflicts during resolution, the local version under development will always be selected \-\- even if there are remote versions that better match other requirements for the \fBgemspec\fR gem\.
-.
-.SH "SOURCE PRIORITY"
-When attempting to locate a gem to satisfy a gem requirement, bundler uses the following priority order:
-.
-.IP "1." 4
-The source explicitly attached to the gem (using \fB:source\fR, \fB:path\fR, or \fB:git\fR)
-.
-.IP "2." 4
-For implicit gems (dependencies of explicit gems), any source, git, or path repository declared on the parent\. This results in bundler prioritizing the ActiveSupport gem from the Rails git repository over ones from \fBrubygems\.org\fR
-.
-.IP "3." 4
-The sources specified via global \fBsource\fR lines, searching each source in your \fBGemfile\fR from last added to first added\.
-.
-.IP "" 0
-
diff --git a/man/gemfile.5.ronn b/man/gemfile.5.ronn
deleted file mode 100644
index 832577130c..0000000000
--- a/man/gemfile.5.ronn
+++ /dev/null
@@ -1,517 +0,0 @@
-Gemfile(5) -- A format for describing gem dependencies for Ruby programs
-========================================================================
-
-## SYNOPSIS
-
-A `Gemfile` describes the gem dependencies required to execute associated
-Ruby code.
-
-Place the `Gemfile` in the root of the directory containing the associated
-code. For instance, in a Rails application, place the `Gemfile` in the same
-directory as the `Rakefile`.
-
-## SYNTAX
-
-A `Gemfile` is evaluated as Ruby code, in a context which makes available
-a number of methods used to describe the gem requirements.
-
-## GLOBAL SOURCES
-
-At the top of the `Gemfile`, add a line for the `Rubygems` source that contains
-the gems listed in the `Gemfile`.
-
- source "https://rubygems.org"
-
-It is possible, but not recommended as of Bundler 1.7, to add multiple global
-`source` lines. Each of these `source`s `MUST` be a valid Rubygems repository.
-
-Sources are checked for gems following the heuristics described in
-[SOURCE PRIORITY][]. If a gem is found in more than one global source, Bundler
-will print a warning after installing the gem indicating which source was used,
-and listing the other sources where the gem is available. A specific source can
-be selected for gems that need to use a non-standard repository, suppressing
-this warning, by using the [`:source` option](#SOURCE) or a
-[`source` block](#BLOCK-FORM-OF-SOURCE-GIT-PATH-GROUP-and-PLATFORMS).
-
-### CREDENTIALS
-
-Some gem sources require a username and password. Use [bundle config(1)](bundle-config.1.html) to set
-the username and password for any of the sources that need it. The command must
-be run once on each computer that will install the Gemfile, but this keeps the
-credentials from being stored in plain text in version control.
-
- bundle config gems.example.com user:password
-
-For some sources, like a company Gemfury account, it may be easier to
-include the credentials in the Gemfile as part of the source URL.
-
- source "https://user:password@gems.example.com"
-
-Credentials in the source URL will take precedence over credentials set using
-`config`.
-
-## RUBY
-
-If your application requires a specific Ruby version or engine, specify your
-requirements using the `ruby` method, with the following arguments.
-All parameters are `OPTIONAL` unless otherwise specified.
-
-### VERSION (required)
-
-The version of Ruby that your application requires. If your application
-requires an alternate Ruby engine, such as JRuby, Rubinius or TruffleRuby, this
-should be the Ruby version that the engine is compatible with.
-
- ruby "1.9.3"
-
-### ENGINE
-
-Each application _may_ specify a Ruby engine. If an engine is specified, an
-engine version _must_ also be specified.
-
-What exactly is an Engine?
- - A Ruby engine is an implementation of the Ruby language.
-
- - For background: the reference or original implementation of the Ruby
- programming language is called
- [Matz's Ruby Interpreter](https://en.wikipedia.org/wiki/Ruby_MRI), or MRI
- for short. This is named after Ruby creator Yukihiro Matsumoto,
- also known as Matz. MRI is also known as CRuby, because it is written in C.
- MRI is the most widely used Ruby engine.
-
- - [Other implementations](https://www.ruby-lang.org/en/about/) of Ruby exist.
- Some of the more well-known implementations include
- [Rubinius](https://rubinius.com/), and [JRuby](http://jruby.org/).
- Rubinius is an alternative implementation of Ruby written in Ruby.
- JRuby is an implementation of Ruby on the JVM, short for Java Virtual Machine.
-
-### ENGINE VERSION
-
-Each application _may_ specify a Ruby engine version. If an engine version is
-specified, an engine _must_ also be specified. If the engine is "ruby" the
-engine version specified _must_ match the Ruby version.
-
- ruby "1.8.7", :engine => "jruby", :engine_version => "1.6.7"
-
-### PATCHLEVEL
-
-Each application _may_ specify a Ruby patchlevel.
-
- ruby "2.0.0", :patchlevel => "247"
-
-## GEMS
-
-Specify gem requirements using the `gem` method, with the following arguments.
-All parameters are `OPTIONAL` unless otherwise specified.
-
-### NAME (required)
-
-For each gem requirement, list a single _gem_ line.
-
- gem "nokogiri"
-
-### VERSION
-
-Each _gem_ `MAY` have one or more version specifiers.
-
- gem "nokogiri", ">= 1.4.2"
- gem "RedCloth", ">= 4.1.0", "< 4.2.0"
-
-### REQUIRE AS
-
-Each _gem_ `MAY` specify files that should be used when autorequiring via
-`Bundler.require`. You may pass an array with multiple files or `true` if file
-you want `required` has same name as _gem_ or `false` to
-prevent any file from being autorequired.
-
- gem "redis", :require => ["redis/connection/hiredis", "redis"]
- gem "webmock", :require => false
- gem "byebug", :require => true
-
-The argument defaults to the name of the gem. For example, these are identical:
-
- gem "nokogiri"
- gem "nokogiri", :require => "nokogiri"
- gem "nokogiri", :require => true
-
-### GROUPS
-
-Each _gem_ `MAY` specify membership in one or more groups. Any _gem_ that does
-not specify membership in any group is placed in the `default` group.
-
- gem "rspec", :group => :test
- gem "wirble", :groups => [:development, :test]
-
-The Bundler runtime allows its two main methods, `Bundler.setup` and
-`Bundler.require`, to limit their impact to particular groups.
-
- # setup adds gems to Ruby's load path
- Bundler.setup # defaults to all groups
- require "bundler/setup" # same as Bundler.setup
- Bundler.setup(:default) # only set up the _default_ group
- Bundler.setup(:test) # only set up the _test_ group (but `not` _default_)
- Bundler.setup(:default, :test) # set up the _default_ and _test_ groups, but no others
-
- # require requires all of the gems in the specified groups
- Bundler.require # defaults to the _default_ group
- Bundler.require(:default) # identical
- Bundler.require(:default, :test) # requires the _default_ and _test_ groups
- Bundler.require(:test) # requires the _test_ group
-
-The Bundler CLI allows you to specify a list of groups whose gems `bundle install` should
-not install with the `without` configuration.
-
-To specify multiple groups to ignore, specify a list of groups separated by spaces.
-
- bundle config set without test
- bundle config set without development test
-
-Also, calling `Bundler.setup` with no parameters, or calling `require "bundler/setup"`
-will setup all groups except for the ones you excluded via `--without` (since they
-are not available).
-
-Note that on `bundle install`, bundler downloads and evaluates all gems, in order to
-create a single canonical list of all of the required gems and their dependencies.
-This means that you cannot list different versions of the same gems in different
-groups. For more details, see [Understanding Bundler](https://bundler.io/rationale.html).
-
-### PLATFORMS
-
-If a gem should only be used in a particular platform or set of platforms, you can
-specify them. Platforms are essentially identical to groups, except that you do not
-need to use the `--without` install-time flag to exclude groups of gems for other
-platforms.
-
-There are a number of `Gemfile` platforms:
-
- * `ruby`:
- C Ruby (MRI), Rubinius or TruffleRuby, but `NOT` Windows
- * `mri`:
- Same as _ruby_, but only C Ruby (MRI)
- * `mingw`:
- Windows 32 bit 'mingw32' platform (aka RubyInstaller)
- * `x64_mingw`:
- Windows 64 bit 'mingw32' platform (aka RubyInstaller x64)
- * `rbx`:
- Rubinius
- * `jruby`:
- JRuby
- * `truffleruby`:
- TruffleRuby
- * `mswin`:
- Windows
-
-You can restrict further by platform and version for all platforms *except* for
-`rbx`, `jruby`, `truffleruby` and `mswin`.
-
-To specify a version in addition to a platform, append the version number without
-the delimiter to the platform. For example, to specify that a gem should only be
-used on platforms with Ruby 2.3, use:
-
- ruby_23
-
-The full list of platforms and supported versions includes:
-
- * `ruby`:
- 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
- * `mri`:
- 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
- * `mingw`:
- 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
- * `x64_mingw`:
- 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
-
-As with groups, you can specify one or more platforms:
-
- gem "weakling", :platforms => :jruby
- gem "ruby-debug", :platforms => :mri_18
- gem "nokogiri", :platforms => [:mri_18, :jruby]
-
-All operations involving groups ([`bundle install`](bundle-install.1.html), `Bundler.setup`,
-`Bundler.require`) behave exactly the same as if any groups not
-matching the current platform were explicitly excluded.
-
-### SOURCE
-
-You can select an alternate Rubygems repository for a gem using the ':source'
-option.
-
- gem "some_internal_gem", :source => "https://gems.example.com"
-
-This forces the gem to be loaded from this source and ignores any global sources
-declared at the top level of the file. If the gem does not exist in this source,
-it will not be installed.
-
-Bundler will search for child dependencies of this gem by first looking in the
-source selected for the parent, but if they are not found there, it will fall
-back on global sources using the ordering described in [SOURCE PRIORITY][].
-
-Selecting a specific source repository this way also suppresses the ambiguous
-gem warning described above in
-[GLOBAL SOURCES (#source)](#GLOBAL-SOURCES).
-
-Using the `:source` option for an individual gem will also make that source
-available as a possible global source for any other gems which do not specify
-explicit sources. Thus, when adding gems with explicit sources, it is
-recommended that you also ensure all other gems in the Gemfile are using
-explicit sources.
-
-### GIT
-
-If necessary, you can specify that a gem is located at a particular
-git repository using the `:git` parameter. The repository can be accessed via
-several protocols:
-
- * `HTTP(S)`:
- gem "rails", :git => "https://github.com/rails/rails.git"
- * `SSH`:
- gem "rails", :git => "git@github.com:rails/rails.git"
- * `git`:
- gem "rails", :git => "git://github.com/rails/rails.git"
-
-If using SSH, the user that you use to run `bundle install` `MUST` have the
-appropriate keys available in their `$HOME/.ssh`.
-
-`NOTE`: `http://` and `git://` URLs should be avoided if at all possible. These
-protocols are unauthenticated, so a man-in-the-middle attacker can deliver
-malicious code and compromise your system. HTTPS and SSH are strongly
-preferred.
-
-The `group`, `platforms`, and `require` options are available and behave
-exactly the same as they would for a normal gem.
-
-A git repository `SHOULD` have at least one file, at the root of the
-directory containing the gem, with the extension `.gemspec`. This file
-`MUST` contain a valid gem specification, as expected by the `gem build`
-command.
-
-If a git repository does not have a `.gemspec`, bundler will attempt to
-create one, but it will not contain any dependencies, executables, or
-C extension compilation instructions. As a result, it may fail to properly
-integrate into your application.
-
-If a git repository does have a `.gemspec` for the gem you attached it
-to, a version specifier, if provided, means that the git repository is
-only valid if the `.gemspec` specifies a version matching the version
-specifier. If not, bundler will print a warning.
-
- gem "rails", "2.3.8", :git => "https://github.com/rails/rails.git"
- # bundle install will fail, because the .gemspec in the rails
- # repository's master branch specifies version 3.0.0
-
-If a git repository does `not` have a `.gemspec` for the gem you attached
-it to, a version specifier `MUST` be provided. Bundler will use this
-version in the simple `.gemspec` it creates.
-
-Git repositories support a number of additional options.
-
- * `branch`, `tag`, and `ref`:
- You `MUST` only specify at most one of these options. The default
- is `:branch => "master"`. For example:
-
- gem "rails", :git => "https://github.com/rails/rails.git", :branch => "5-0-stable"
-
- gem "rails", :git => "https://github.com/rails/rails.git", :tag => "v5.0.0"
-
- gem "rails", :git => "https://github.com/rails/rails.git", :ref => "4aded"
-
- * `submodules`:
- For reference, a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules)
- lets you have another git repository within a subfolder of your repository.
- Specify `:submodules => true` to cause bundler to expand any
- submodules included in the git repository
-
-If a git repository contains multiple `.gemspecs`, each `.gemspec`
-represents a gem located at the same place in the file system as
-the `.gemspec`.
-
- |~rails [git root]
- | |-rails.gemspec [rails gem located here]
- |~actionpack
- | |-actionpack.gemspec [actionpack gem located here]
- |~activesupport
- | |-activesupport.gemspec [activesupport gem located here]
- |...
-
-To install a gem located in a git repository, bundler changes to
-the directory containing the gemspec, runs `gem build name.gemspec`
-and then installs the resulting gem. The `gem build` command,
-which comes standard with Rubygems, evaluates the `.gemspec` in
-the context of the directory in which it is located.
-
-### GIT SOURCE
-
-A custom git source can be defined via the `git_source` method. Provide the source's name
-as an argument, and a block which receives a single argument and interpolates it into a
-string to return the full repo address:
-
- git_source(:stash){ |repo_name| "https://stash.corp.acme.pl/#{repo_name}.git" }
- gem 'rails', :stash => 'forks/rails'
-
-In addition, if you wish to choose a specific branch:
-
- gem "rails", :stash => "forks/rails", :branch => "branch_name"
-
-### GITHUB
-
-`NOTE`: This shorthand should be avoided until Bundler 2.0, since it
-currently expands to an insecure `git://` URL. This allows a
-man-in-the-middle attacker to compromise your system.
-
-If the git repository you want to use is hosted on GitHub and is public, you can use the
-:github shorthand to specify the github username and repository name (without the
-trailing ".git"), separated by a slash. If both the username and repository name are the
-same, you can omit one.
-
- gem "rails", :github => "rails/rails"
- gem "rails", :github => "rails"
-
-Are both equivalent to
-
- gem "rails", :git => "git://github.com/rails/rails.git"
-
-Since the `github` method is a specialization of `git_source`, it accepts a `:branch` named argument.
-
-### GIST
-
-If the git repository you want to use is hosted as a Github Gist and is public, you can use
-the :gist shorthand to specify the gist identifier (without the trailing ".git").
-
- gem "the_hatch", :gist => "4815162342"
-
-Is equivalent to:
-
- gem "the_hatch", :git => "https://gist.github.com/4815162342.git"
-
-Since the `gist` method is a specialization of `git_source`, it accepts a `:branch` named argument.
-
-### BITBUCKET
-
-If the git repository you want to use is hosted on Bitbucket and is public, you can use the
-:bitbucket shorthand to specify the bitbucket username and repository name (without the
-trailing ".git"), separated by a slash. If both the username and repository name are the
-same, you can omit one.
-
- gem "rails", :bitbucket => "rails/rails"
- gem "rails", :bitbucket => "rails"
-
-Are both equivalent to
-
- gem "rails", :git => "https://rails@bitbucket.org/rails/rails.git"
-
-Since the `bitbucket` method is a specialization of `git_source`, it accepts a `:branch` named argument.
-
-### PATH
-
-You can specify that a gem is located in a particular location
-on the file system. Relative paths are resolved relative to the
-directory containing the `Gemfile`.
-
-Similar to the semantics of the `:git` option, the `:path`
-option requires that the directory in question either contains
-a `.gemspec` for the gem, or that you specify an explicit
-version that bundler should use.
-
-Unlike `:git`, bundler does not compile C extensions for
-gems specified as paths.
-
- gem "rails", :path => "vendor/rails"
-
-If you would like to use multiple local gems directly from the filesystem, you can set a global `path` option to the path containing the gem's files. This will automatically load gemspec files from subdirectories.
-
- path 'components' do
- gem 'admin_ui'
- gem 'public_ui'
- end
-
-## BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS
-
-The `:source`, `:git`, `:path`, `:group`, and `:platforms` options may be
-applied to a group of gems by using block form.
-
- source "https://gems.example.com" do
- gem "some_internal_gem"
- gem "another_internal_gem"
- end
-
- git "https://github.com/rails/rails.git" do
- gem "activesupport"
- gem "actionpack"
- end
-
- platforms :ruby do
- gem "ruby-debug"
- gem "sqlite3"
- end
-
- group :development, :optional => true do
- gem "wirble"
- gem "faker"
- end
-
-In the case of the group block form the :optional option can be given
-to prevent a group from being installed unless listed in the `--with`
-option given to the `bundle install` command.
-
-In the case of the `git` block form, the `:ref`, `:branch`, `:tag`,
-and `:submodules` options may be passed to the `git` method, and
-all gems in the block will inherit those options.
-
-The presence of a `source` block in a Gemfile also makes that source
-available as a possible global source for any other gems which do not specify
-explicit sources. Thus, when defining source blocks, it is
-recommended that you also ensure all other gems in the Gemfile are using
-explicit sources, either via source blocks or `:source` directives on
-individual gems.
-
-## INSTALL_IF
-
-The `install_if` method allows gems to be installed based on a proc or lambda.
-This is especially useful for optional gems that can only be used if certain
-software is installed or some other conditions are met.
-
- install_if -> { RUBY_PLATFORM =~ /darwin/ } do
- gem "pasteboard"
- end
-
-## GEMSPEC
-
-The [`.gemspec`](http://guides.rubygems.org/specification-reference/) file is where
- you provide metadata about your gem to Rubygems. Some required Gemspec
- attributes include the name, description, and homepage of your gem. This is
- also where you specify the dependencies your gem needs to run.
-
-If you wish to use Bundler to help install dependencies for a gem while it is
-being developed, use the `gemspec` method to pull in the dependencies listed in
-the `.gemspec` file.
-
-The `gemspec` method adds any runtime dependencies as gem requirements in the
-default group. It also adds development dependencies as gem requirements in the
-`development` group. Finally, it adds a gem requirement on your project (`:path
-=> '.'`). In conjunction with `Bundler.setup`, this allows you to require project
-files in your test code as you would if the project were installed as a gem; you
-need not manipulate the load path manually or require project files via relative
-paths.
-
-The `gemspec` method supports optional `:path`, `:glob`, `:name`, and `:development_group`
-options, which control where bundler looks for the `.gemspec`, the glob it uses to look
-for the gemspec (defaults to: "{,*,*/*}.gemspec"), what named `.gemspec` it uses
-(if more than one is present), and which group development dependencies are included in.
-
-When a `gemspec` dependency encounters version conflicts during resolution, the
-local version under development will always be selected -- even if there are
-remote versions that better match other requirements for the `gemspec` gem.
-
-## SOURCE PRIORITY
-
-When attempting to locate a gem to satisfy a gem requirement,
-bundler uses the following priority order:
-
- 1. The source explicitly attached to the gem (using `:source`, `:path`, or
- `:git`)
- 2. For implicit gems (dependencies of explicit gems), any source, git, or path
- repository declared on the parent. This results in bundler prioritizing the
- ActiveSupport gem from the Rails git repository over ones from
- `rubygems.org`
- 3. The sources specified via global `source` lines, searching each source in
- your `Gemfile` from last added to first added.
diff --git a/man/gemfile.5.txt b/man/gemfile.5.txt
deleted file mode 100644
index 71d2513271..0000000000
--- a/man/gemfile.5.txt
+++ /dev/null
@@ -1,649 +0,0 @@
-GEMFILE(5) GEMFILE(5)
-
-
-
-NAME
- Gemfile - A format for describing gem dependencies for Ruby programs
-
-SYNOPSIS
- A Gemfile describes the gem dependencies required to execute associated
- Ruby code.
-
- Place the Gemfile in the root of the directory containing the associ-
- ated code. For instance, in a Rails application, place the Gemfile in
- the same directory as the Rakefile.
-
-SYNTAX
- A Gemfile is evaluated as Ruby code, in a context which makes available
- a number of methods used to describe the gem requirements.
-
-GLOBAL SOURCES
- At the top of the Gemfile, add a line for the Rubygems source that con-
- tains the gems listed in the Gemfile.
-
-
-
- source "https://rubygems.org"
-
-
-
- It is possible, but not recommended as of Bundler 1.7, to add multiple
- global source lines. Each of these sources MUST be a valid Rubygems
- repository.
-
- Sources are checked for gems following the heuristics described in
- SOURCE PRIORITY. If a gem is found in more than one global source,
- Bundler will print a warning after installing the gem indicating which
- source was used, and listing the other sources where the gem is avail-
- able. A specific source can be selected for gems that need to use a
- non-standard repository, suppressing this warning, by using the :source
- option or a source block.
-
- CREDENTIALS
- Some gem sources require a username and password. Use bundle config(1)
- bundle-config.1.html to set the username and password for any of the
- sources that need it. The command must be run once on each computer
- that will install the Gemfile, but this keeps the credentials from
- being stored in plain text in version control.
-
-
-
- bundle config gems.example.com user:password
-
-
-
- For some sources, like a company Gemfury account, it may be easier to
- include the credentials in the Gemfile as part of the source URL.
-
-
-
- source "https://user:password@gems.example.com"
-
-
-
- Credentials in the source URL will take precedence over credentials set
- using config.
-
-RUBY
- If your application requires a specific Ruby version or engine, specify
- your requirements using the ruby method, with the following arguments.
- All parameters are OPTIONAL unless otherwise specified.
-
- VERSION (required)
- The version of Ruby that your application requires. If your application
- requires an alternate Ruby engine, such as JRuby, Rubinius or Truf-
- fleRuby, this should be the Ruby version that the engine is compatible
- with.
-
-
-
- ruby "1.9.3"
-
-
-
- ENGINE
- Each application may specify a Ruby engine. If an engine is specified,
- an engine version must also be specified.
-
- What exactly is an Engine? - A Ruby engine is an implementation of the
- Ruby language.
-
- o For background: the reference or original implementation of the
- Ruby programming language is called Matz's Ruby Interpreter
- https://en.wikipedia.org/wiki/Ruby_MRI, or MRI for short. This is
- named after Ruby creator Yukihiro Matsumoto, also known as Matz.
- MRI is also known as CRuby, because it is written in C. MRI is the
- most widely used Ruby engine.
-
- o Other implementations https://www.ruby-lang.org/en/about/ of Ruby
- exist. Some of the more well-known implementations include Rubinius
- https://rubinius.com/, and JRuby http://jruby.org/. Rubinius is an
- alternative implementation of Ruby written in Ruby. JRuby is an
- implementation of Ruby on the JVM, short for Java Virtual Machine.
-
-
-
- ENGINE VERSION
- Each application may specify a Ruby engine version. If an engine ver-
- sion is specified, an engine must also be specified. If the engine is
- "ruby" the engine version specified must match the Ruby version.
-
-
-
- ruby "1.8.7", :engine => "jruby", :engine_version => "1.6.7"
-
-
-
- PATCHLEVEL
- Each application may specify a Ruby patchlevel.
-
-
-
- ruby "2.0.0", :patchlevel => "247"
-
-
-
-GEMS
- Specify gem requirements using the gem method, with the following argu-
- ments. All parameters are OPTIONAL unless otherwise specified.
-
- NAME (required)
- For each gem requirement, list a single gem line.
-
-
-
- gem "nokogiri"
-
-
-
- VERSION
- Each gem MAY have one or more version specifiers.
-
-
-
- gem "nokogiri", ">= 1.4.2"
- gem "RedCloth", ">= 4.1.0", "< 4.2.0"
-
-
-
- REQUIRE AS
- Each gem MAY specify files that should be used when autorequiring via
- Bundler.require. You may pass an array with multiple files or true if
- file you want required has same name as gem or false to prevent any
- file from being autorequired.
-
-
-
- gem "redis", :require => ["redis/connection/hiredis", "redis"]
- gem "webmock", :require => false
- gem "byebug", :require => true
-
-
-
- The argument defaults to the name of the gem. For example, these are
- identical:
-
-
-
- gem "nokogiri"
- gem "nokogiri", :require => "nokogiri"
- gem "nokogiri", :require => true
-
-
-
- GROUPS
- Each gem MAY specify membership in one or more groups. Any gem that
- does not specify membership in any group is placed in the default
- group.
-
-
-
- gem "rspec", :group => :test
- gem "wirble", :groups => [:development, :test]
-
-
-
- The Bundler runtime allows its two main methods, Bundler.setup and
- Bundler.require, to limit their impact to particular groups.
-
-
-
- # setup adds gems to Ruby's load path
- Bundler.setup # defaults to all groups
- require "bundler/setup" # same as Bundler.setup
- Bundler.setup(:default) # only set up the _default_ group
- Bundler.setup(:test) # only set up the _test_ group (but `not` _default_)
- Bundler.setup(:default, :test) # set up the _default_ and _test_ groups, but no others
-
- # require requires all of the gems in the specified groups
- Bundler.require # defaults to the _default_ group
- Bundler.require(:default) # identical
- Bundler.require(:default, :test) # requires the _default_ and _test_ groups
- Bundler.require(:test) # requires the _test_ group
-
-
-
- The Bundler CLI allows you to specify a list of groups whose gems bun-
- dle install should not install with the without configuration.
-
- To specify multiple groups to ignore, specify a list of groups sepa-
- rated by spaces.
-
-
-
- bundle config set without test
- bundle config set without development test
-
-
-
- Also, calling Bundler.setup with no parameters, or calling require
- "bundler/setup" will setup all groups except for the ones you excluded
- via --without (since they are not available).
-
- Note that on bundle install, bundler downloads and evaluates all gems,
- in order to create a single canonical list of all of the required gems
- and their dependencies. This means that you cannot list different ver-
- sions of the same gems in different groups. For more details, see
- Understanding Bundler https://bundler.io/rationale.html.
-
- PLATFORMS
- If a gem should only be used in a particular platform or set of plat-
- forms, you can specify them. Platforms are essentially identical to
- groups, except that you do not need to use the --without install-time
- flag to exclude groups of gems for other platforms.
-
- There are a number of Gemfile platforms:
-
- ruby C Ruby (MRI), Rubinius or TruffleRuby, but NOT Windows
-
- mri Same as ruby, but only C Ruby (MRI)
-
- mingw Windows 32 bit 'mingw32' platform (aka RubyInstaller)
-
- x64_mingw
- Windows 64 bit 'mingw32' platform (aka RubyInstaller x64)
-
- rbx Rubinius
-
- jruby JRuby
-
- truffleruby
- TruffleRuby
-
- mswin Windows
-
- You can restrict further by platform and version for all platforms
- except for rbx, jruby, truffleruby and mswin.
-
- To specify a version in addition to a platform, append the version num-
- ber without the delimiter to the platform. For example, to specify that
- a gem should only be used on platforms with Ruby 2.3, use:
-
-
-
- ruby_23
-
-
-
- The full list of platforms and supported versions includes:
-
- ruby 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
-
- mri 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
-
- mingw 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
-
- x64_mingw
- 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
-
- As with groups, you can specify one or more platforms:
-
-
-
- gem "weakling", :platforms => :jruby
- gem "ruby-debug", :platforms => :mri_18
- gem "nokogiri", :platforms => [:mri_18, :jruby]
-
-
-
- All operations involving groups (bundle install bundle-install.1.html,
- Bundler.setup, Bundler.require) behave exactly the same as if any
- groups not matching the current platform were explicitly excluded.
-
- SOURCE
- You can select an alternate Rubygems repository for a gem using the
- ':source' option.
-
-
-
- gem "some_internal_gem", :source => "https://gems.example.com"
-
-
-
- This forces the gem to be loaded from this source and ignores any
- global sources declared at the top level of the file. If the gem does
- not exist in this source, it will not be installed.
-
- Bundler will search for child dependencies of this gem by first looking
- in the source selected for the parent, but if they are not found there,
- it will fall back on global sources using the ordering described in
- SOURCE PRIORITY.
-
- Selecting a specific source repository this way also suppresses the
- ambiguous gem warning described above in GLOBAL SOURCES (#source).
-
- Using the :source option for an individual gem will also make that
- source available as a possible global source for any other gems which
- do not specify explicit sources. Thus, when adding gems with explicit
- sources, it is recommended that you also ensure all other gems in the
- Gemfile are using explicit sources.
-
- GIT
- If necessary, you can specify that a gem is located at a particular git
- repository using the :git parameter. The repository can be accessed via
- several protocols:
-
- HTTP(S)
- gem "rails", :git => "https://github.com/rails/rails.git"
-
- SSH gem "rails", :git => "git@github.com:rails/rails.git"
-
- git gem "rails", :git => "git://github.com/rails/rails.git"
-
- If using SSH, the user that you use to run bundle install MUST have the
- appropriate keys available in their $HOME/.ssh.
-
- NOTE: http:// and git:// URLs should be avoided if at all possible.
- These protocols are unauthenticated, so a man-in-the-middle attacker
- can deliver malicious code and compromise your system. HTTPS and SSH
- are strongly preferred.
-
- The group, platforms, and require options are available and behave
- exactly the same as they would for a normal gem.
-
- A git repository SHOULD have at least one file, at the root of the
- directory containing the gem, with the extension .gemspec. This file
- MUST contain a valid gem specification, as expected by the gem build
- command.
-
- If a git repository does not have a .gemspec, bundler will attempt to
- create one, but it will not contain any dependencies, executables, or C
- extension compilation instructions. As a result, it may fail to prop-
- erly integrate into your application.
-
- If a git repository does have a .gemspec for the gem you attached it
- to, a version specifier, if provided, means that the git repository is
- only valid if the .gemspec specifies a version matching the version
- specifier. If not, bundler will print a warning.
-
-
-
- gem "rails", "2.3.8", :git => "https://github.com/rails/rails.git"
- # bundle install will fail, because the .gemspec in the rails
- # repository's master branch specifies version 3.0.0
-
-
-
- If a git repository does not have a .gemspec for the gem you attached
- it to, a version specifier MUST be provided. Bundler will use this ver-
- sion in the simple .gemspec it creates.
-
- Git repositories support a number of additional options.
-
- branch, tag, and ref
- You MUST only specify at most one of these options. The default
- is :branch => "master". For example:
-
- gem "rails", :git => "https://github.com/rails/rails.git",
- :branch => "5-0-stable"
-
- gem "rails", :git => "https://github.com/rails/rails.git", :tag
- => "v5.0.0"
-
- gem "rails", :git => "https://github.com/rails/rails.git", :ref
- => "4aded"
-
- submodules
- For reference, a git submodule
- https://git-scm.com/book/en/v2/Git-Tools-Submodules lets you
- have another git repository within a subfolder of your reposi-
- tory. Specify :submodules => true to cause bundler to expand any
- submodules included in the git repository
-
- If a git repository contains multiple .gemspecs, each .gemspec repre-
- sents a gem located at the same place in the file system as the .gem-
- spec.
-
-
-
- |~rails [git root]
- | |-rails.gemspec [rails gem located here]
- |~actionpack
- | |-actionpack.gemspec [actionpack gem located here]
- |~activesupport
- | |-activesupport.gemspec [activesupport gem located here]
- |...
-
-
-
- To install a gem located in a git repository, bundler changes to the
- directory containing the gemspec, runs gem build name.gemspec and then
- installs the resulting gem. The gem build command, which comes standard
- with Rubygems, evaluates the .gemspec in the context of the directory
- in which it is located.
-
- GIT SOURCE
- A custom git source can be defined via the git_source method. Provide
- the source's name as an argument, and a block which receives a single
- argument and interpolates it into a string to return the full repo
- address:
-
-
-
- git_source(:stash){ |repo_name| "https://stash.corp.acme.pl/#{repo_name}.git" }
- gem 'rails', :stash => 'forks/rails'
-
-
-
- In addition, if you wish to choose a specific branch:
-
-
-
- gem "rails", :stash => "forks/rails", :branch => "branch_name"
-
-
-
- GITHUB
- NOTE: This shorthand should be avoided until Bundler 2.0, since it cur-
- rently expands to an insecure git:// URL. This allows a man-in-the-mid-
- dle attacker to compromise your system.
-
- If the git repository you want to use is hosted on GitHub and is pub-
- lic, you can use the :github shorthand to specify the github username
- and repository name (without the trailing ".git"), separated by a
- slash. If both the username and repository name are the same, you can
- omit one.
-
-
-
- gem "rails", :github => "rails/rails"
- gem "rails", :github => "rails"
-
-
-
- Are both equivalent to
-
-
-
- gem "rails", :git => "git://github.com/rails/rails.git"
-
-
-
- Since the github method is a specialization of git_source, it accepts a
- :branch named argument.
-
- GIST
- If the git repository you want to use is hosted as a Github Gist and is
- public, you can use the :gist shorthand to specify the gist identifier
- (without the trailing ".git").
-
-
-
- gem "the_hatch", :gist => "4815162342"
-
-
-
- Is equivalent to:
-
-
-
- gem "the_hatch", :git => "https://gist.github.com/4815162342.git"
-
-
-
- Since the gist method is a specialization of git_source, it accepts a
- :branch named argument.
-
- BITBUCKET
- If the git repository you want to use is hosted on Bitbucket and is
- public, you can use the :bitbucket shorthand to specify the bitbucket
- username and repository name (without the trailing ".git"), separated
- by a slash. If both the username and repository name are the same, you
- can omit one.
-
-
-
- gem "rails", :bitbucket => "rails/rails"
- gem "rails", :bitbucket => "rails"
-
-
-
- Are both equivalent to
-
-
-
- gem "rails", :git => "https://rails@bitbucket.org/rails/rails.git"
-
-
-
- Since the bitbucket method is a specialization of git_source, it
- accepts a :branch named argument.
-
- PATH
- You can specify that a gem is located in a particular location on the
- file system. Relative paths are resolved relative to the directory con-
- taining the Gemfile.
-
- Similar to the semantics of the :git option, the :path option requires
- that the directory in question either contains a .gemspec for the gem,
- or that you specify an explicit version that bundler should use.
-
- Unlike :git, bundler does not compile C extensions for gems specified
- as paths.
-
-
-
- gem "rails", :path => "vendor/rails"
-
-
-
- If you would like to use multiple local gems directly from the filesys-
- tem, you can set a global path option to the path containing the gem's
- files. This will automatically load gemspec files from subdirectories.
-
-
-
- path 'components' do
- gem 'admin_ui'
- gem 'public_ui'
- end
-
-
-
-BLOCK FORM OF SOURCE, GIT, PATH, GROUP and PLATFORMS
- The :source, :git, :path, :group, and :platforms options may be applied
- to a group of gems by using block form.
-
-
-
- source "https://gems.example.com" do
- gem "some_internal_gem"
- gem "another_internal_gem"
- end
-
- git "https://github.com/rails/rails.git" do
- gem "activesupport"
- gem "actionpack"
- end
-
- platforms :ruby do
- gem "ruby-debug"
- gem "sqlite3"
- end
-
- group :development, :optional => true do
- gem "wirble"
- gem "faker"
- end
-
-
-
- In the case of the group block form the :optional option can be given
- to prevent a group from being installed unless listed in the --with
- option given to the bundle install command.
-
- In the case of the git block form, the :ref, :branch, :tag, and :sub-
- modules options may be passed to the git method, and all gems in the
- block will inherit those options.
-
- The presence of a source block in a Gemfile also makes that source
- available as a possible global source for any other gems which do not
- specify explicit sources. Thus, when defining source blocks, it is rec-
- ommended that you also ensure all other gems in the Gemfile are using
- explicit sources, either via source blocks or :source directives on
- individual gems.
-
-INSTALL_IF
- The install_if method allows gems to be installed based on a proc or
- lambda. This is especially useful for optional gems that can only be
- used if certain software is installed or some other conditions are met.
-
-
-
- install_if -> { RUBY_PLATFORM =~ /darwin/ } do
- gem "pasteboard"
- end
-
-
-
-GEMSPEC
- The .gemspec http://guides.rubygems.org/specification-reference/ file
- is where you provide metadata about your gem to Rubygems. Some required
- Gemspec attributes include the name, description, and homepage of your
- gem. This is also where you specify the dependencies your gem needs to
- run.
-
- If you wish to use Bundler to help install dependencies for a gem while
- it is being developed, use the gemspec method to pull in the dependen-
- cies listed in the .gemspec file.
-
- The gemspec method adds any runtime dependencies as gem requirements in
- the default group. It also adds development dependencies as gem
- requirements in the development group. Finally, it adds a gem require-
- ment on your project (:path => '.'). In conjunction with Bundler.setup,
- this allows you to require project files in your test code as you would
- if the project were installed as a gem; you need not manipulate the
- load path manually or require project files via relative paths.
-
- The gemspec method supports optional :path, :glob, :name, and :develop-
- ment_group options, which control where bundler looks for the .gemspec,
- the glob it uses to look for the gemspec (defaults to: "{,,/*}.gem-
- spec"), what named .gemspec it uses (if more than one is present), and
- which group development dependencies are included in.
-
- When a gemspec dependency encounters version conflicts during resolu-
- tion, the local version under development will always be selected --
- even if there are remote versions that better match other requirements
- for the gemspec gem.
-
-SOURCE PRIORITY
- When attempting to locate a gem to satisfy a gem requirement, bundler
- uses the following priority order:
-
- 1. The source explicitly attached to the gem (using :source, :path, or
- :git)
-
- 2. For implicit gems (dependencies of explicit gems), any source, git,
- or path repository declared on the parent. This results in bundler
- prioritizing the ActiveSupport gem from the Rails git repository
- over ones from rubygems.org
-
- 3. The sources specified via global source lines, searching each
- source in your Gemfile from last added to first added.
-
-
-
-
-
-
- January 2020 GEMFILE(5)
diff --git a/man/ruby.1 b/man/ruby.1
index 1888312d26..9f0ae05ee9 100644
--- a/man/ruby.1
+++ b/man/ruby.1
@@ -313,7 +313,7 @@ Enables automatic line-ending processing, which means to firstly set
to the value of
.Li "$/" ,
and secondly chops every line read using
-.Li chop! .
+.Li chomp! .
.Pp
.It Fl n
Causes Ruby to assume the following loop around your script, which
diff --git a/marshal.c b/marshal.c
index d05b4b9336..ed096f52fe 100644
--- a/marshal.c
+++ b/marshal.c
@@ -9,13 +9,7 @@
**********************************************************************/
-#include "ruby/ruby.h"
-#include "ruby/io.h"
-#include "internal.h"
-#include "ruby/st.h"
-#include "ruby/util.h"
-#include "encindex.h"
-#include "id_table.h"
+#include "ruby/internal/config.h"
#include <math.h>
#ifdef HAVE_FLOAT_H
@@ -25,6 +19,24 @@
#include <ieeefp.h>
#endif
+#include "encindex.h"
+#include "id_table.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/bignum.h"
+#include "internal/class.h"
+#include "internal/encoding.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/object.h"
+#include "internal/struct.h"
+#include "internal/util.h"
+#include "internal/vm.h"
+#include "ruby/io.h"
+#include "ruby/ruby.h"
+#include "ruby/st.h"
+#include "ruby/util.h"
+
#define BITSPERSHORT (2*CHAR_BIT)
#define SHORTMASK ((1<<BITSPERSHORT)-1)
#define SHORTDN(x) RSHIFT((x),BITSPERSHORT)
@@ -520,10 +532,13 @@ w_extended(VALUE klass, struct dump_arg *arg, int check)
klass = RCLASS_SUPER(klass);
}
while (BUILTIN_TYPE(klass) == T_ICLASS) {
- VALUE path = rb_class_name(RBASIC(klass)->klass);
- w_byte(TYPE_EXTENDED, arg);
- w_unique(path, arg);
- klass = RCLASS_SUPER(klass);
+ if (!FL_TEST(klass, RICLASS_IS_ORIGIN) ||
+ BUILTIN_TYPE(RBASIC(klass)->klass) != T_MODULE) {
+ VALUE path = rb_class_name(RBASIC(klass)->klass);
+ w_byte(TYPE_EXTENDED, arg);
+ w_unique(path, arg);
+ }
+ klass = RCLASS_SUPER(klass);
}
}
@@ -1122,6 +1137,7 @@ struct load_arg {
long offset;
st_table *symbols;
st_table *data;
+ st_table *partial_objects;
VALUE proc;
st_table *compat_tbl;
};
@@ -1148,6 +1164,7 @@ mark_load_arg(void *ptr)
return;
rb_mark_tbl(p->symbols);
rb_mark_tbl(p->data);
+ rb_mark_tbl(p->partial_objects);
rb_mark_hash(p->compat_tbl);
}
@@ -1409,9 +1426,10 @@ ruby2_keywords_flag_check(VALUE sym)
{
const char *p;
long l;
+ if (rb_enc_get_index(sym) != ENCINDEX_US_ASCII) return 0;
RSTRING_GETMEM(sym, p, l);
if (l <= 0) return 0;
- if (name_equal(name_s_ruby2_keywords_flag, rb_strlen_lit(name_s_ruby2_keywords_flag), p, 1)) {
+ if (name_equal(name_s_ruby2_keywords_flag, rb_strlen_lit(name_s_ruby2_keywords_flag), p, l)) {
return 1;
}
return 0;
@@ -1446,7 +1464,13 @@ r_symreal(struct load_arg *arg, int ivar)
idx = sym2encidx(sym, r_object(arg));
}
}
- if (idx > 0) rb_enc_associate_index(s, idx);
+ if (idx > 0) {
+ rb_enc_associate_index(s, idx);
+ if (rb_enc_str_coderange(s) == ENC_CODERANGE_BROKEN) {
+ rb_raise(rb_eArgError, "invalid byte sequence in %s: %+"PRIsVALUE,
+ rb_enc_name(rb_enc_from_index(idx)), s);
+ }
+ }
return s;
}
@@ -1488,13 +1512,13 @@ r_string(struct load_arg *arg)
static VALUE
r_entry0(VALUE v, st_index_t num, struct load_arg *arg)
{
- st_data_t real_obj = (VALUE)Qundef;
- if (arg->compat_tbl && st_lookup(arg->compat_tbl, v, &real_obj)) {
- st_insert(arg->data, num, (st_data_t)real_obj);
- }
- else {
- st_insert(arg->data, num, (st_data_t)v);
+ st_data_t real_obj = (st_data_t)v;
+ if (arg->compat_tbl) {
+ /* real_obj is kept if not found */
+ st_lookup(arg->compat_tbl, v, &real_obj);
}
+ st_insert(arg->data, num, real_obj);
+ st_insert(arg->partial_objects, (st_data_t)real_obj, Qtrue);
return v;
}
@@ -1525,10 +1549,15 @@ r_post_proc(VALUE v, struct load_arg *arg)
}
static VALUE
-r_leave(VALUE v, struct load_arg *arg)
+r_leave(VALUE v, struct load_arg *arg, bool partial)
{
v = r_fixup_compat(v, arg);
- v = r_post_proc(v, arg);
+ if (!partial) {
+ st_data_t data;
+ st_data_t key = (st_data_t)v;
+ st_delete(arg->partial_objects, &key, &data);
+ v = r_post_proc(v, arg);
+ }
return v;
}
@@ -1655,7 +1684,7 @@ append_extmod(VALUE obj, VALUE extmod)
} while (0)
static VALUE
-r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
+r_object0(struct load_arg *arg, bool partial, int *ivp, VALUE extmod)
{
VALUE v = Qnil;
int type = r_byte(arg);
@@ -1669,18 +1698,18 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
rb_raise(rb_eArgError, "dump format error (unlinked)");
}
v = (VALUE)link;
- v = r_post_proc(v, arg);
+ if (!st_lookup(arg->partial_objects, (st_data_t)v, &link)) {
+ v = r_post_proc(v, arg);
+ }
break;
case TYPE_IVAR:
{
int ivar = TRUE;
- v = r_object0(arg, &ivar, extmod);
+ v = r_object0(arg, true, &ivar, extmod);
if (ivar) r_ivar(v, NULL, arg);
- if (RB_TYPE_P(v, T_STRING)) {
- v = r_leave(v, arg);
- }
+ v = r_leave(v, arg, partial);
}
break;
@@ -1693,7 +1722,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
if (RB_TYPE_P(m, T_CLASS)) { /* prepended */
VALUE c;
- v = r_object0(arg, 0, Qnil);
+ v = r_object0(arg, true, 0, Qnil);
c = CLASS_OF(v);
if (c != m || FL_TEST(c, FL_SINGLETON)) {
rb_raise(rb_eArgError,
@@ -1710,7 +1739,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
must_be_module(m, path);
rb_ary_push(extmod, m);
- v = r_object0(arg, 0, extmod);
+ v = r_object0(arg, true, 0, extmod);
while (RARRAY_LEN(extmod) > 0) {
m = rb_ary_pop(extmod);
rb_extend_object(v, m);
@@ -1726,10 +1755,9 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
if (FL_TEST(c, FL_SINGLETON)) {
rb_raise(rb_eTypeError, "singleton can't be loaded");
}
- v = r_object0(arg, 0, extmod);
+ v = r_object0(arg, partial, 0, extmod);
if (rb_special_const_p(v) || RB_TYPE_P(v, T_OBJECT) || RB_TYPE_P(v, T_CLASS)) {
- format_error:
- rb_raise(rb_eArgError, "dump format error (user class)");
+ goto format_error;
}
if (RB_TYPE_P(v, T_MODULE) || !RTEST(rb_class_inherited_p(c, RBASIC(v)->klass))) {
VALUE tmp = rb_obj_alloc(c);
@@ -1740,19 +1768,22 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
}
break;
+ format_error:
+ rb_raise(rb_eArgError, "dump format error (user class)");
+
case TYPE_NIL:
v = Qnil;
- v = r_leave(v, arg);
+ v = r_leave(v, arg, false);
break;
case TYPE_TRUE:
v = Qtrue;
- v = r_leave(v, arg);
+ v = r_leave(v, arg, false);
break;
case TYPE_FALSE:
v = Qfalse;
- v = r_leave(v, arg);
+ v = r_leave(v, arg, false);
break;
case TYPE_FIXNUM:
@@ -1760,7 +1791,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
long i = r_long(arg);
v = LONG2FIX(i);
}
- v = r_leave(v, arg);
+ v = r_leave(v, arg, false);
break;
case TYPE_FLOAT:
@@ -1785,7 +1816,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
}
v = DBL2NUM(d);
v = r_entry(v, arg);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, false);
}
break;
@@ -1802,15 +1833,13 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
INTEGER_PACK_LITTLE_ENDIAN | (sign == '-' ? INTEGER_PACK_NEGATIVE : 0));
rb_str_resize(data, 0L);
v = r_entry(v, arg);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, false);
}
break;
case TYPE_STRING:
v = r_entry(r_string(arg), arg);
- if (!ivp) {
- v = r_leave(v, arg);
- }
+ v = r_leave(v, arg, partial);
break;
case TYPE_REGEXP:
@@ -1845,7 +1874,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
rb_str_set_len(str, dst - ptr);
}
v = r_entry0(rb_reg_new_str(str, options), idx, arg);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
}
break;
@@ -1860,7 +1889,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
rb_ary_push(v, r_object(arg));
arg->readable--;
}
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
arg->readable++;
}
break;
@@ -1883,7 +1912,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
if (type == TYPE_HASH_DEF) {
RHASH_SET_IFNONE(v, r_object(arg));
}
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
}
break;
@@ -1935,7 +1964,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
}
}
rb_struct_initialize(v, values);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
arg->readable += 2;
}
break;
@@ -1962,7 +1991,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
marshal_compat_t *compat = (marshal_compat_t*)d;
v = compat->loader(klass, v);
}
- v = r_post_proc(v, arg);
+ if (!partial) v = r_post_proc(v, arg);
}
break;
@@ -2004,7 +2033,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
}
v = r_entry0(v, idx, arg);
r_ivar(v, NULL, arg);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
}
break;
@@ -2025,9 +2054,9 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
"class %"PRIsVALUE" needs to have instance method `_load_data'",
name);
}
- r = r_object0(arg, 0, extmod);
+ r = r_object0(arg, partial, 0, extmod);
load_funcall(arg, v, s_load_data, 1, &r);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
}
break;
@@ -2038,7 +2067,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
v = rb_path_to_class(str);
prohibit_ivar("class/module", str);
v = r_entry(v, arg);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
}
break;
@@ -2049,7 +2078,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
v = path2class(str);
prohibit_ivar("class", str);
v = r_entry(v, arg);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
}
break;
@@ -2060,7 +2089,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
v = path2module(str);
prohibit_ivar("module", str);
v = r_entry(v, arg);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
}
break;
@@ -2073,7 +2102,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
v = r_symreal(arg, 0);
}
v = rb_str_intern(v);
- v = r_leave(v, arg);
+ v = r_leave(v, arg, partial);
break;
case TYPE_SYMLINK:
@@ -2095,7 +2124,7 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
static VALUE
r_object(struct load_arg *arg)
{
- return r_object0(arg, 0, Qnil);
+ return r_object0(arg, false, 0, Qnil);
}
static void
@@ -2113,6 +2142,8 @@ clear_load_arg(struct load_arg *arg)
arg->symbols = 0;
st_free_table(arg->data);
arg->data = 0;
+ st_free_table(arg->partial_objects);
+ arg->partial_objects = 0;
if (arg->compat_tbl) {
st_free_table(arg->compat_tbl);
arg->compat_tbl = 0;
@@ -2167,6 +2198,7 @@ rb_marshal_load_with_proc(VALUE port, VALUE proc)
arg->offset = 0;
arg->symbols = st_init_numtable();
arg->data = rb_init_identtable();
+ arg->partial_objects = rb_init_identtable();
arg->compat_tbl = 0;
arg->proc = 0;
arg->readable = 0;
@@ -2312,9 +2344,6 @@ rb_marshal_load_with_proc(VALUE port, VALUE proc)
void
Init_marshal(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
VALUE rb_mMarshal = rb_define_module("Marshal");
#define set_id(sym) sym = rb_intern_const(name_##sym)
set_id(s_dump);
diff --git a/math.c b/math.c
index d98467ca0a..f64ad93c06 100644
--- a/math.c
+++ b/math.c
@@ -9,13 +9,22 @@
**********************************************************************/
+#include "ruby/internal/config.h"
+
#ifdef _MSC_VER
# define _USE_MATH_DEFINES 1
#endif
-#include "internal.h"
+
+#include <errno.h>
#include <float.h>
#include <math.h>
-#include <errno.h>
+
+#include "internal.h"
+#include "internal/bignum.h"
+#include "internal/complex.h"
+#include "internal/math.h"
+#include "internal/object.h"
+#include "internal/vm.h"
#if defined(HAVE_SIGNBIT) && defined(__GNUC__) && defined(__sun) && \
!defined(signbit)
diff --git a/memory_view.c b/memory_view.c
new file mode 100644
index 0000000000..a1ab240656
--- /dev/null
+++ b/memory_view.c
@@ -0,0 +1,869 @@
+/**********************************************************************
+
+ memory_view.c - Memory View
+
+ Copyright (C) 2020 Kenta Murata <mrkn@mrkn.jp>
+
+**********************************************************************/
+
+#include "internal.h"
+#include "internal/hash.h"
+#include "internal/variable.h"
+#include "internal/util.h"
+#include "ruby/memory_view.h"
+#include "vm_sync.h"
+
+#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
+# define INTPTR2NUM LL2NUM
+# define UINTPTR2NUM ULL2NUM
+#elif SIZEOF_INTPTR_T == SIZEOF_LONG
+# define INTPTR2NUM LONG2NUM
+# define UINTPTR2NUM ULONG2NUM
+#else
+# define INTPTR2NUM INT2NUM
+# define UINTPTR2NUM UINT2NUM
+#endif
+
+
+#define STRUCT_ALIGNOF(T, result) do { \
+ (result) = RUBY_ALIGNOF(T); \
+} while(0)
+
+// Exported Object Registry
+
+static st_table *exported_object_table = NULL;
+VALUE rb_memory_view_exported_object_registry = Qundef;
+
+static int
+exported_object_registry_mark_key_i(st_data_t key, st_data_t value, st_data_t data)
+{
+ rb_gc_mark(key);
+ return ST_CONTINUE;
+}
+
+static void
+exported_object_registry_mark(void *ptr)
+{
+ // Don't use RB_VM_LOCK_ENTER here. It is unnecessary during GC.
+ st_foreach(exported_object_table, exported_object_registry_mark_key_i, 0);
+}
+
+static void
+exported_object_registry_free(void *ptr)
+{
+ RB_VM_LOCK_ENTER();
+ st_clear(exported_object_table);
+ st_free_table(exported_object_table);
+ exported_object_table = NULL;
+ RB_VM_LOCK_LEAVE();
+}
+
+const rb_data_type_t rb_memory_view_exported_object_registry_data_type = {
+ "memory_view/exported_object_registry",
+ {
+ exported_object_registry_mark,
+ exported_object_registry_free,
+ 0,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static int
+exported_object_add_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
+{
+ ASSERT_vm_locking();
+
+ if (existing) {
+ *val += 1;
+ }
+ else {
+ *val = 1;
+ }
+ return ST_CONTINUE;
+}
+
+static int
+exported_object_dec_ref(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
+{
+ ASSERT_vm_locking();
+
+ if (existing) {
+ *val -= 1;
+ if (*val == 0) {
+ return ST_DELETE;
+ }
+ }
+ return ST_CONTINUE;
+}
+
+static void
+register_exported_object(VALUE obj)
+{
+ RB_VM_LOCK_ENTER();
+ st_update(exported_object_table, (st_data_t)obj, exported_object_add_ref, 0);
+ RB_VM_LOCK_LEAVE();
+}
+
+static void
+unregister_exported_object(VALUE obj)
+{
+ RB_VM_LOCK_ENTER();
+ st_update(exported_object_table, (st_data_t)obj, exported_object_dec_ref, 0);
+ RB_VM_LOCK_LEAVE();
+}
+
+// MemoryView
+
+static ID id_memory_view;
+
+static const rb_data_type_t memory_view_entry_data_type = {
+ "memory_view/entry",
+ {
+ 0,
+ 0,
+ 0,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+/* Register memory view functions for the given class */
+bool
+rb_memory_view_register(VALUE klass, const rb_memory_view_entry_t *entry) {
+ Check_Type(klass, T_CLASS);
+ VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil);
+ if (! NIL_P(entry_obj)) {
+ rb_warning("Duplicated registration of memory view to %"PRIsVALUE, klass);
+ return false;
+ }
+ else {
+ entry_obj = TypedData_Wrap_Struct(0, &memory_view_entry_data_type, (void *)entry);
+ rb_ivar_set(klass, id_memory_view, entry_obj);
+ return true;
+ }
+}
+
+/* Examine whether the given memory view has row-major order strides. */
+bool
+rb_memory_view_is_row_major_contiguous(const rb_memory_view_t *view)
+{
+ const ssize_t ndim = view->ndim;
+ const ssize_t *shape = view->shape;
+ const ssize_t *strides = view->strides;
+ ssize_t n = view->item_size;
+ ssize_t i;
+ for (i = ndim - 1; i >= 0; --i) {
+ if (strides[i] != n) return false;
+ n *= shape[i];
+ }
+ return true;
+}
+
+/* Examine whether the given memory view has column-major order strides. */
+bool
+rb_memory_view_is_column_major_contiguous(const rb_memory_view_t *view)
+{
+ const ssize_t ndim = view->ndim;
+ const ssize_t *shape = view->shape;
+ const ssize_t *strides = view->strides;
+ ssize_t n = view->item_size;
+ ssize_t i;
+ for (i = 0; i < ndim; ++i) {
+ if (strides[i] != n) return false;
+ n *= shape[i];
+ }
+ return true;
+}
+
+/* Initialize strides array to represent the specified contiguous array. */
+void
+rb_memory_view_fill_contiguous_strides(const ssize_t ndim, const ssize_t item_size, const ssize_t *const shape, const bool row_major_p, ssize_t *const strides)
+{
+ ssize_t i, n = item_size;
+ if (row_major_p) {
+ for (i = ndim - 1; i >= 0; --i) {
+ strides[i] = n;
+ n *= shape[i];
+ }
+ }
+ else { // column-major
+ for (i = 0; i < ndim; ++i) {
+ strides[i] = n;
+ n *= shape[i];
+ }
+ }
+}
+
+/* Initialize view to expose a simple byte array */
+bool
+rb_memory_view_init_as_byte_array(rb_memory_view_t *view, VALUE obj, void *data, const ssize_t len, const bool readonly)
+{
+ view->obj = obj;
+ view->data = data;
+ view->byte_size = len;
+ view->readonly = readonly;
+ view->format = NULL;
+ view->item_size = 1;
+ view->item_desc.components = NULL;
+ view->item_desc.length = 0;
+ view->ndim = 1;
+ view->shape = NULL;
+ view->strides = NULL;
+ view->sub_offsets = NULL;
+ *((void **)&view->private) = NULL;
+
+ return true;
+}
+
+#ifdef HAVE_TRUE_LONG_LONG
+static const char native_types[] = "sSiIlLqQjJ";
+#else
+static const char native_types[] = "sSiIlLjJ";
+#endif
+static const char endianness_types[] = "sSiIlLqQjJ";
+
+typedef enum {
+ ENDIANNESS_NATIVE,
+ ENDIANNESS_LITTLE,
+ ENDIANNESS_BIG
+} endianness_t;
+
+static ssize_t
+get_format_size(const char *format, bool *native_p, ssize_t *alignment, endianness_t *endianness, ssize_t *count, const char **next_format, VALUE *error)
+{
+ RUBY_ASSERT(format != NULL);
+ RUBY_ASSERT(native_p != NULL);
+ RUBY_ASSERT(endianness != NULL);
+ RUBY_ASSERT(count != NULL);
+ RUBY_ASSERT(next_format != NULL);
+
+ *native_p = false;
+ *endianness = ENDIANNESS_NATIVE;
+ *count = 1;
+
+ const int type_char = *format;
+
+ int i = 1;
+ while (format[i]) {
+ switch (format[i]) {
+ case '!':
+ case '_':
+ if (strchr(native_types, type_char)) {
+ *native_p = true;
+ ++i;
+ }
+ else {
+ if (error) {
+ *error = rb_exc_new_str(rb_eArgError,
+ rb_sprintf("Unable to specify native size for '%c'", type_char));
+ }
+ return -1;
+ }
+ continue;
+
+ case '<':
+ case '>':
+ if (!strchr(endianness_types, type_char)) {
+ if (error) {
+ *error = rb_exc_new_str(rb_eArgError,
+ rb_sprintf("Unable to specify endianness for '%c'", type_char));
+ }
+ return -1;
+ }
+ if (*endianness != ENDIANNESS_NATIVE) {
+ *error = rb_exc_new_cstr(rb_eArgError, "Unable to use both '<' and '>' multiple times");
+ return -1;
+ }
+ *endianness = (format[i] == '<') ? ENDIANNESS_LITTLE : ENDIANNESS_BIG;
+ ++i;
+ continue;
+
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ // parse count
+ int ch = format[i];
+ if ('0' <= ch && ch <= '9') {
+ ssize_t n = 0;
+ while ('0' <= (ch = format[i]) && ch <= '9') {
+ n = 10*n + ruby_digit36_to_number_table[ch];
+ ++i;
+ }
+ *count = n;
+ }
+
+ *next_format = &format[i];
+
+ switch (type_char) {
+ case 'x': // padding
+ return 1;
+
+ case 'c': // signed char
+ case 'C': // unsigned char
+ return sizeof(char);
+
+ case 's': // s for int16_t, s! for signed short
+ case 'S': // S for uint16_t, S! for unsigned short
+ if (*native_p) {
+ STRUCT_ALIGNOF(short, *alignment);
+ return sizeof(short);
+ }
+ // fall through
+
+ case 'n': // n for big-endian 16bit unsigned integer
+ case 'v': // v for little-endian 16bit unsigned integer
+ STRUCT_ALIGNOF(int16_t, *alignment);
+ return 2;
+
+ case 'i': // i and i! for signed int
+ case 'I': // I and I! for unsigned int
+ STRUCT_ALIGNOF(int, *alignment);
+ return sizeof(int);
+
+ case 'l': // l for int32_t, l! for signed long
+ case 'L': // L for uint32_t, L! for unsigned long
+ if (*native_p) {
+ STRUCT_ALIGNOF(long, *alignment);
+ return sizeof(long);
+ }
+ // fall through
+
+ case 'N': // N for big-endian 32bit unsigned integer
+ case 'V': // V for little-endian 32bit unsigned integer
+ STRUCT_ALIGNOF(int32_t, *alignment);
+ return 4;
+
+ case 'f': // f for native float
+ case 'e': // e for little-endian float
+ case 'g': // g for big-endian float
+ STRUCT_ALIGNOF(float, *alignment);
+ return sizeof(float);
+
+ case 'q': // q for int64_t, q! for signed long long
+ case 'Q': // Q for uint64_t, Q! for unsigned long long
+ if (*native_p) {
+ STRUCT_ALIGNOF(LONG_LONG, *alignment);
+ return sizeof(LONG_LONG);
+ }
+ STRUCT_ALIGNOF(int64_t, *alignment);
+ return 8;
+
+ case 'd': // d for native double
+ case 'E': // E for little-endian double
+ case 'G': // G for big-endian double
+ STRUCT_ALIGNOF(double, *alignment);
+ return sizeof(double);
+
+ case 'j': // j for intptr_t
+ case 'J': // J for uintptr_t
+ STRUCT_ALIGNOF(intptr_t, *alignment);
+ return sizeof(intptr_t);
+
+ default:
+ *alignment = -1;
+ if (error) {
+ *error = rb_exc_new_str(rb_eArgError, rb_sprintf("Invalid type character '%c'", type_char));
+ }
+ return -1;
+ }
+}
+
+static inline ssize_t
+calculate_padding(ssize_t total, ssize_t alignment_size) {
+ if (alignment_size > 1) {
+ ssize_t res = total % alignment_size;
+ if (res > 0) {
+ return alignment_size - res;
+ }
+ }
+ return 0;
+}
+
+ssize_t
+rb_memory_view_parse_item_format(const char *format,
+ rb_memory_view_item_component_t **members,
+ size_t *n_members, const char **err)
+{
+ if (format == NULL) return 1;
+
+ VALUE error = Qnil;
+ ssize_t total = 0;
+ size_t len = 0;
+ bool alignment = false;
+ ssize_t max_alignment_size = 0;
+
+ const char *p = format;
+ if (*p == '|') { // alginment specifier
+ alignment = true;
+ ++format;
+ ++p;
+ }
+ while (*p) {
+ const char *q = p;
+
+ // ignore spaces
+ if (ISSPACE(*p)) {
+ while (ISSPACE(*p)) ++p;
+ continue;
+ }
+
+ bool native_size_p = false;
+ ssize_t alignment_size = 0;
+ endianness_t endianness = ENDIANNESS_NATIVE;
+ ssize_t count = 0;
+ const ssize_t size = get_format_size(p, &native_size_p, &alignment_size, &endianness, &count, &p, &error);
+ if (size < 0) {
+ if (err) *err = q;
+ return -1;
+ }
+ if (max_alignment_size < alignment_size) {
+ max_alignment_size = alignment_size;
+ }
+
+ const ssize_t padding = alignment ? calculate_padding(total, alignment_size) : 0;
+ total += padding + size * count;
+
+ if (*q != 'x') {
+ ++len;
+ }
+ }
+
+ // adjust total size with the alignment size of the largest element
+ if (alignment && max_alignment_size > 0) {
+ const ssize_t padding = calculate_padding(total, max_alignment_size);
+ total += padding;
+ }
+
+ if (members && n_members) {
+ rb_memory_view_item_component_t *buf = ALLOC_N(rb_memory_view_item_component_t, len);
+
+ ssize_t i = 0, offset = 0;
+ const char *p = format;
+ while (*p) {
+ const int type_char = *p;
+
+ bool native_size_p;
+ ssize_t alignment_size = 0;
+ endianness_t endianness = ENDIANNESS_NATIVE;
+ ssize_t count = 0;
+ const ssize_t size = get_format_size(p, &native_size_p, &alignment_size, &endianness, &count, &p, NULL);
+
+ const ssize_t padding = alignment ? calculate_padding(offset, alignment_size) : 0;
+ offset += padding;
+
+ if (type_char != 'x') {
+#ifdef WORDS_BIGENDIAN
+ bool little_endian_p = (endianness == ENDIANNESS_LITTLE);
+#else
+ bool little_endian_p = (endianness != ENDIANNESS_BIG);
+#endif
+
+ switch (type_char) {
+ case 'e':
+ case 'E':
+ case 'v':
+ case 'V':
+ little_endian_p = true;
+ break;
+ case 'g':
+ case 'G':
+ case 'n':
+ case 'N':
+ little_endian_p = false;
+ break;
+ default:
+ break;
+ }
+
+ buf[i++] = (rb_memory_view_item_component_t){
+ .format = type_char,
+ .native_size_p = native_size_p,
+ .little_endian_p = little_endian_p,
+ .offset = offset,
+ .size = size,
+ .repeat = count
+ };
+ }
+
+ offset += size * count;
+ }
+
+ *members = buf;
+ *n_members = len;
+ }
+
+ return total;
+}
+
+/* Return the item size. */
+ssize_t
+rb_memory_view_item_size_from_format(const char *format, const char **err)
+{
+ return rb_memory_view_parse_item_format(format, NULL, NULL, err);
+}
+
+/* Return the pointer to the item located by the given indices. */
+void *
+rb_memory_view_get_item_pointer(rb_memory_view_t *view, const ssize_t *indices)
+{
+ uint8_t *ptr = view->data;
+
+ if (view->ndim == 1) {
+ ssize_t stride = view->strides != NULL ? view->strides[0] : view->item_size;
+ return ptr + indices[0] * stride;
+ }
+
+ assert(view->shape != NULL);
+
+ ssize_t i;
+ if (view->strides == NULL) {
+ // row-major contiguous array
+ ssize_t stride = view->item_size;
+ for (i = 0; i < view->ndim; ++i) {
+ stride *= view->shape[i];
+ }
+ for (i = 0; i < view->ndim; ++i) {
+ stride /= view->shape[i];
+ ptr += indices[i] * stride;
+ }
+ }
+ else if (view->sub_offsets == NULL) {
+ // flat strided array
+ for (i = 0; i < view->ndim; ++i) {
+ ptr += indices[i] * view->strides[i];
+ }
+ }
+ else {
+ // indirect strided array
+ for (i = 0; i < view->ndim; ++i) {
+ ptr += indices[i] * view->strides[i];
+ if (view->sub_offsets[i] >= 0) {
+ ptr = *(uint8_t **)ptr + view->sub_offsets[i];
+ }
+ }
+ }
+
+ return ptr;
+}
+
+static void
+switch_endianness(uint8_t *buf, ssize_t len)
+{
+ RUBY_ASSERT(buf != NULL);
+ RUBY_ASSERT(len >= 0);
+
+ uint8_t *p = buf;
+ uint8_t *q = buf + len - 1;
+
+ while (q - p > 0) {
+ uint8_t t = *p;
+ *p = *q;
+ *q = t;
+ ++p;
+ --q;
+ }
+}
+
+static inline VALUE
+extract_item_member(const uint8_t *ptr, const rb_memory_view_item_component_t *member, const size_t i)
+{
+ RUBY_ASSERT(ptr != NULL);
+ RUBY_ASSERT(member != NULL);
+ RUBY_ASSERT(i < member->repeat);
+
+#ifdef WORDS_BIGENDIAN
+ const bool native_endian_p = !member->little_endian_p;
+#else
+ const bool native_endian_p = member->little_endian_p;
+#endif
+
+ const uint8_t *p = ptr + member->offset + i * member->size;
+
+ if (member->format == 'c') {
+ return INT2FIX(*(char *)p);
+ }
+ else if (member->format == 'C') {
+ return INT2FIX(*(unsigned char *)p);
+ }
+
+ union {
+ short s;
+ unsigned short us;
+ int i;
+ unsigned int ui;
+ long l;
+ unsigned long ul;
+ LONG_LONG ll;
+ unsigned LONG_LONG ull;
+ int16_t i16;
+ uint16_t u16;
+ int32_t i32;
+ uint32_t u32;
+ int64_t i64;
+ uint64_t u64;
+ intptr_t iptr;
+ uintptr_t uptr;
+ float f;
+ double d;
+ } val;
+
+ if (!native_endian_p) {
+ MEMCPY(&val, p, uint8_t, member->size);
+ switch_endianness((uint8_t *)&val, member->size);
+ }
+ else {
+ MEMCPY(&val, p, uint8_t, member->size);
+ }
+
+ switch (member->format) {
+ case 's':
+ if (member->native_size_p) {
+ return INT2FIX(val.s);
+ }
+ else {
+ return INT2FIX(val.i16);
+ }
+
+ case 'S':
+ case 'n':
+ case 'v':
+ if (member->native_size_p) {
+ return UINT2NUM(val.us);
+ }
+ else {
+ return INT2FIX(val.u16);
+ }
+
+ case 'i':
+ return INT2NUM(val.i);
+
+ case 'I':
+ return UINT2NUM(val.ui);
+
+ case 'l':
+ if (member->native_size_p) {
+ return LONG2NUM(val.l);
+ }
+ else {
+ return LONG2NUM(val.i32);
+ }
+
+ case 'L':
+ case 'N':
+ case 'V':
+ if (member->native_size_p) {
+ return ULONG2NUM(val.ul);
+ }
+ else {
+ return ULONG2NUM(val.u32);
+ }
+
+ case 'f':
+ case 'e':
+ case 'g':
+ return DBL2NUM(val.f);
+
+ case 'q':
+ if (member->native_size_p) {
+ return LL2NUM(val.ll);
+ }
+ else {
+#if SIZEOF_INT64_t == SIZEOF_LONG
+ return LONG2NUM(val.i64);
+#else
+ return LL2NUM(val.i64);
+#endif
+ }
+
+ case 'Q':
+ if (member->native_size_p) {
+ return ULL2NUM(val.ull);
+ }
+ else {
+#if SIZEOF_UINT64_t == SIZEOF_LONG
+ return ULONG2NUM(val.u64);
+#else
+ return ULL2NUM(val.u64);
+#endif
+ }
+
+ case 'd':
+ case 'E':
+ case 'G':
+ return DBL2NUM(val.d);
+
+ case 'j':
+ return INTPTR2NUM(val.iptr);
+
+ case 'J':
+ return UINTPTR2NUM(val.uptr);
+
+ default:
+ UNREACHABLE_RETURN(Qnil);
+ }
+}
+
+/* Return a value of the extracted member. */
+VALUE
+rb_memory_view_extract_item_member(const void *ptr, const rb_memory_view_item_component_t *member, const size_t i)
+{
+ if (ptr == NULL) return Qnil;
+ if (member == NULL) return Qnil;
+ if (i >= member->repeat) return Qnil;
+
+ return extract_item_member(ptr, member, i);
+}
+
+/* Return a value that consists of item members.
+ * When an item is a single member, the return value is a single value.
+ * When an item consists of multiple members, an array will be returned. */
+VALUE
+rb_memory_view_extract_item_members(const void *ptr, const rb_memory_view_item_component_t *members, const size_t n_members)
+{
+ if (ptr == NULL) return Qnil;
+ if (members == NULL) return Qnil;
+ if (n_members == 0) return Qnil;
+
+ if (n_members == 1 && members[0].repeat == 1) {
+ return rb_memory_view_extract_item_member(ptr, members, 0);
+ }
+
+ size_t i, j;
+ VALUE item = rb_ary_new();
+ for (i = 0; i < n_members; ++i) {
+ for (j = 0; j < members[i].repeat; ++j) {
+ VALUE v = extract_item_member(ptr, &members[i], j);
+ rb_ary_push(item, v);
+ }
+ }
+
+ return item;
+}
+
+void
+rb_memory_view_prepare_item_desc(rb_memory_view_t *view)
+{
+ if (view->item_desc.components == NULL) {
+ const char *err;
+ rb_memory_view_item_component_t **p_components =
+ (rb_memory_view_item_component_t **)&view->item_desc.components;
+ ssize_t n = rb_memory_view_parse_item_format(view->format, p_components, &view->item_desc.length, &err);
+ if (n < 0) {
+ rb_raise(rb_eRuntimeError,
+ "Unable to parse item format at %"PRIdSIZE" in \"%s\"",
+ (err - view->format), view->format);
+ }
+ }
+}
+
+/* Return a value that consists of item members in the given memory view. */
+VALUE
+rb_memory_view_get_item(rb_memory_view_t *view, const ssize_t *indices)
+{
+ void *ptr = rb_memory_view_get_item_pointer(view, indices);
+
+ if (view->format == NULL) {
+ return INT2FIX(*(uint8_t *)ptr);
+ }
+
+ if (view->item_desc.components == NULL) {
+ rb_memory_view_prepare_item_desc(view);
+ }
+
+ return rb_memory_view_extract_item_members(ptr, view->item_desc.components, view->item_desc.length);
+}
+
+static const rb_memory_view_entry_t *
+lookup_memory_view_entry(VALUE klass)
+{
+ VALUE entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil);
+ while (NIL_P(entry_obj)) {
+ klass = rb_class_get_superclass(klass);
+
+ if (klass == rb_cBasicObject || klass == rb_cObject)
+ return NULL;
+
+ entry_obj = rb_ivar_lookup(klass, id_memory_view, Qnil);
+ }
+
+ if (! rb_typeddata_is_kind_of(entry_obj, &memory_view_entry_data_type))
+ return NULL;
+
+ return (const rb_memory_view_entry_t *)RTYPEDDATA_DATA(entry_obj);
+}
+
+/* Examine whether the given object supports memory view. */
+bool
+rb_memory_view_available_p(VALUE obj)
+{
+ VALUE klass = CLASS_OF(obj);
+ const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass);
+ if (entry)
+ return (* entry->available_p_func)(obj);
+ else
+ return false;
+}
+
+/* Obtain a memory view from obj, and substitute the information to view. */
+bool
+rb_memory_view_get(VALUE obj, rb_memory_view_t* view, int flags)
+{
+ VALUE klass = CLASS_OF(obj);
+ const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass);
+ if (entry) {
+ if (!(*entry->available_p_func)(obj)) {
+ return false;
+ }
+
+ bool rv = (*entry->get_func)(obj, view, flags);
+ if (rv) {
+ register_exported_object(view->obj);
+ }
+ return rv;
+ }
+ else
+ return false;
+}
+
+/* Release the memory view obtained from obj. */
+bool
+rb_memory_view_release(rb_memory_view_t* view)
+{
+ VALUE klass = CLASS_OF(view->obj);
+ const rb_memory_view_entry_t *entry = lookup_memory_view_entry(klass);
+ if (entry) {
+ bool rv = true;
+ if (entry->release_func) {
+ rv = (*entry->release_func)(view->obj, view);
+ }
+ if (rv) {
+ unregister_exported_object(view->obj);
+ view->obj = Qnil;
+ if (view->item_desc.components) {
+ xfree((void *)view->item_desc.components);
+ }
+ }
+ return rv;
+ }
+ else
+ return false;
+}
+
+void
+Init_MemoryView(void)
+{
+ exported_object_table = rb_init_identtable();
+
+ // exported_object_table is referred through rb_memory_view_exported_object_registry
+ // in -test-/memory_view extension.
+ VALUE obj = TypedData_Wrap_Struct(
+ 0, &rb_memory_view_exported_object_registry_data_type,
+ exported_object_table);
+ rb_gc_register_mark_object(obj);
+ rb_memory_view_exported_object_registry = obj;
+
+ id_memory_view = rb_intern_const("__memory_view__");
+}
diff --git a/method.h b/method.h
index 18deea7b03..16a48ccf88 100644
--- a/method.h
+++ b/method.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_METHOD_H
+#define RUBY_METHOD_H 1
/**********************************************************************
method.h -
@@ -8,10 +10,11 @@
Copyright (C) 2009 Koichi Sasada
**********************************************************************/
-#ifndef RUBY_METHOD_H
-#define RUBY_METHOD_H 1
#include "internal.h"
+#include "internal/imemo.h"
+#include "internal/compilers.h"
+#include "internal/static_assert.h"
#ifndef END_OF_ENUMERATION
# if defined(__GNUC__) &&! defined(__STRICT_ANSI__)
@@ -66,8 +69,13 @@ typedef struct rb_callable_method_entry_struct { /* same fields with rb_method_e
#define METHOD_ENTRY_VISI(me) (rb_method_visibility_t)(((me)->flags & (IMEMO_FL_USER0 | IMEMO_FL_USER1)) >> (IMEMO_FL_USHIFT+0))
#define METHOD_ENTRY_BASIC(me) (int) (((me)->flags & (IMEMO_FL_USER2 )) >> (IMEMO_FL_USHIFT+2))
-#define METHOD_ENTRY_COMPLEMENTED(me) ((me)->flags & IMEMO_FL_USER3)
-#define METHOD_ENTRY_COMPLEMENTED_SET(me) ((me)->flags = (me)->flags | IMEMO_FL_USER3)
+#define METHOD_ENTRY_COMPLEMENTED(me) ((me)->flags & IMEMO_FL_USER3)
+#define METHOD_ENTRY_COMPLEMENTED_SET(me) ((me)->flags |= IMEMO_FL_USER3)
+#define METHOD_ENTRY_CACHED(me) ((me)->flags & IMEMO_FL_USER4)
+#define METHOD_ENTRY_CACHED_SET(me) ((me)->flags |= IMEMO_FL_USER4)
+#define METHOD_ENTRY_INVALIDATED(me) ((me)->flags & IMEMO_FL_USER5)
+#define METHOD_ENTRY_INVALIDATED_SET(me) ((me)->flags |= IMEMO_FL_USER5)
+#define METHOD_ENTRY_CACHEABLE(me) !(METHOD_ENTRY_VISI(me) == METHOD_VISI_PROTECTED)
static inline void
METHOD_ENTRY_VISI_SET(rb_method_entry_t *me, rb_method_visibility_t visi)
@@ -151,6 +159,7 @@ typedef struct rb_method_refined_struct {
typedef struct rb_method_bmethod_struct {
VALUE proc; /* should be marked */
struct rb_hook_list_struct *hooks;
+ VALUE defined_ractor;
} rb_method_bmethod_t;
enum method_optimized_type {
@@ -181,6 +190,8 @@ struct rb_method_definition_struct {
uintptr_t method_serial;
};
+struct rb_id_table;
+
typedef struct rb_method_definition_struct rb_method_definition_t;
STATIC_ASSERT(sizeof_method_def, offsetof(rb_method_definition_t, body)==8);
@@ -223,8 +234,13 @@ const rb_method_entry_t *rb_method_entry_clone(const rb_method_entry_t *me);
const rb_callable_method_entry_t *rb_method_entry_complement_defined_class(const rb_method_entry_t *src_me, ID called_id, VALUE defined_class);
void rb_method_entry_copy(rb_method_entry_t *dst, const rb_method_entry_t *src);
+void rb_method_table_insert(VALUE klass, struct rb_id_table *table, ID method_id, const rb_method_entry_t *me);
+
void rb_scope_visibility_set(rb_method_visibility_t);
VALUE rb_unnamed_parameters(int arity);
+void rb_clear_method_cache(VALUE klass_or_module, ID mid);
+void rb_clear_method_cache_all(void);
+
#endif /* RUBY_METHOD_H */
diff --git a/mini_builtin.c b/mini_builtin.c
index ad289bf896..86803e1656 100644
--- a/mini_builtin.c
+++ b/mini_builtin.c
@@ -1,6 +1,7 @@
#include "internal.h"
-#include "vm_core.h"
+#include "internal/array.h"
#include "iseq.h"
+#include "vm_core.h"
#include "builtin.h"
#include "miniprelude.c"
diff --git a/misc/expand_tabs.rb b/misc/expand_tabs.rb
index 7b3bff78ff..b748ab4a61 100755
--- a/misc/expand_tabs.rb
+++ b/misc/expand_tabs.rb
@@ -81,7 +81,6 @@ DEFAULT_GEM_LIBS = %w[
sync
thwait
tracer
- webrick
]
DEFAULT_GEM_EXTS = %w[
@@ -96,7 +95,6 @@ DEFAULT_GEM_EXTS = %w[
json
openssl
psych
- sdbm
stringio
strscan
zlib
diff --git a/misc/lldb_cruby.py b/misc/lldb_cruby.py
index a582b7dde0..075612735c 100755
--- a/misc/lldb_cruby.py
+++ b/misc/lldb_cruby.py
@@ -11,6 +11,152 @@ import lldb
import os
import shlex
+HEAP_PAGE_ALIGN_LOG = 14
+HEAP_PAGE_ALIGN_MASK = (~(~0 << HEAP_PAGE_ALIGN_LOG))
+
+class BackTrace:
+ VM_FRAME_MAGIC_METHOD = 0x11110001
+ VM_FRAME_MAGIC_BLOCK = 0x22220001
+ VM_FRAME_MAGIC_CLASS = 0x33330001
+ VM_FRAME_MAGIC_TOP = 0x44440001
+ VM_FRAME_MAGIC_CFUNC = 0x55550001
+ VM_FRAME_MAGIC_IFUNC = 0x66660001
+ VM_FRAME_MAGIC_EVAL = 0x77770001
+ VM_FRAME_MAGIC_RESCUE = 0x78880001
+ VM_FRAME_MAGIC_DUMMY = 0x79990001
+
+ VM_FRAME_MAGIC_MASK = 0x7fff0001
+
+ VM_FRAME_MAGIC_NAME = {
+ VM_FRAME_MAGIC_TOP: "TOP",
+ VM_FRAME_MAGIC_METHOD: "METHOD",
+ VM_FRAME_MAGIC_CLASS: "CLASS",
+ VM_FRAME_MAGIC_BLOCK: "BLOCK",
+ VM_FRAME_MAGIC_CFUNC: "CFUNC",
+ VM_FRAME_MAGIC_IFUNC: "IFUNC",
+ VM_FRAME_MAGIC_EVAL: "EVAL",
+ VM_FRAME_MAGIC_RESCUE: "RESCUE",
+ 0: "-----"
+ }
+
+ def __init__(self, debugger, command, result, internal_dict):
+ self.debugger = debugger
+ self.command = command
+ self.result = result
+
+ self.target = debugger.GetSelectedTarget()
+ self.process = self.target.GetProcess()
+ self.thread = self.process.GetSelectedThread()
+ self.frame = self.thread.GetSelectedFrame()
+ self.tRString = self.target.FindFirstType("struct RString").GetPointerType()
+ self.tRArray = self.target.FindFirstType("struct RArray").GetPointerType()
+
+ rb_cft_len = len("rb_control_frame_t")
+ method_type_length = sorted(map(len, self.VM_FRAME_MAGIC_NAME.values()), reverse=True)[0]
+ # cfp address, method type, function name
+ self.fmt = "%%-%ds %%-%ds %%s" % (rb_cft_len, method_type_length)
+
+ def vm_frame_magic(self, cfp):
+ ep = cfp.GetValueForExpressionPath("->ep")
+ frame_type = ep.GetChildAtIndex(0).GetValueAsUnsigned() & self.VM_FRAME_MAGIC_MASK
+ return self.VM_FRAME_MAGIC_NAME.get(frame_type, "(none)")
+
+ def rb_iseq_path_str(self, iseq):
+ tRBasic = self.target.FindFirstType("struct RBasic").GetPointerType()
+
+ pathobj = iseq.GetValueForExpressionPath("->body->location.pathobj")
+ pathobj = pathobj.Cast(tRBasic)
+ flags = pathobj.GetValueForExpressionPath("->flags").GetValueAsUnsigned()
+ flType = flags & RUBY_T_MASK
+
+ if flType == RUBY_T_ARRAY:
+ pathobj = pathobj.Cast(self.tRArray)
+
+ if flags & RUBY_FL_USER1:
+ len = ((flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3))
+ ptr = pathobj.GetValueForExpressionPath("->as.ary")
+ else:
+ len = pathobj.GetValueForExpressionPath("->as.heap.len").GetValueAsSigned()
+ ptr = pathobj.GetValueForExpressionPath("->as.heap.ptr")
+
+ pathobj = ptr.GetChildAtIndex(0)
+
+ pathobj = pathobj.Cast(self.tRString)
+ ptr, len = string2cstr(pathobj)
+ err = lldb.SBError()
+ path = self.target.process.ReadMemory(ptr, len, err)
+ if err.Success():
+ return path.decode("utf-8")
+ else:
+ return "unknown"
+
+ def dump_iseq_frame(self, cfp, iseq):
+ m = self.vm_frame_magic(cfp)
+
+ if iseq.GetValueAsUnsigned():
+ iseq_label = iseq.GetValueForExpressionPath("->body->location.label")
+ path = self.rb_iseq_path_str(iseq)
+ ptr, len = string2cstr(iseq_label.Cast(self.tRString))
+
+ err = lldb.SBError()
+ iseq_name = self.target.process.ReadMemory(ptr, len, err)
+ if err.Success():
+ iseq_name = iseq_name.decode("utf-8")
+ else:
+ iseq_name = "error!!"
+
+ else:
+ print("No iseq", file=self.result)
+
+ print(self.fmt % (("%0#12x" % cfp.GetAddress().GetLoadAddress(self.target)), m, "%s %s" % (path, iseq_name)), file=self.result)
+
+ def dump_cfunc_frame(self, cfp):
+ print(self.fmt % ("%0#12x" % (cfp.GetAddress().GetLoadAddress(self.target)), "CFUNC", ""), file=self.result)
+
+ def print_bt(self, ec):
+ tRbExecutionContext_t = self.target.FindFirstType("rb_execution_context_t")
+ ec = ec.Cast(tRbExecutionContext_t.GetPointerType())
+ vm_stack = ec.GetValueForExpressionPath("->vm_stack")
+ vm_stack_size = ec.GetValueForExpressionPath("->vm_stack_size")
+
+ last_cfp_frame = ec.GetValueForExpressionPath("->cfp")
+ cfp_type_p = last_cfp_frame.GetType()
+
+ stack_top = vm_stack.GetValueAsUnsigned() + (
+ vm_stack_size.GetValueAsUnsigned() * vm_stack.GetType().GetByteSize())
+
+ cfp_frame_size = cfp_type_p.GetPointeeType().GetByteSize()
+
+ start_cfp = stack_top
+ # Skip dummy frames
+ start_cfp -= cfp_frame_size
+ start_cfp -= cfp_frame_size
+
+ last_cfp = last_cfp_frame.GetValueAsUnsigned()
+
+ size = ((start_cfp - last_cfp) / cfp_frame_size) + 1
+
+ print(self.fmt % ("rb_control_frame_t", "TYPE", ""), file=self.result)
+
+ curr_addr = start_cfp
+
+ while curr_addr >= last_cfp:
+ cfp = self.target.CreateValueFromAddress("cfp", lldb.SBAddress(curr_addr, self.target), cfp_type_p.GetPointeeType())
+ ep = cfp.GetValueForExpressionPath("->ep")
+ iseq = cfp.GetValueForExpressionPath("->iseq")
+
+ frame_type = ep.GetChildAtIndex(0).GetValueAsUnsigned() & self.VM_FRAME_MAGIC_MASK
+
+ if iseq.GetValueAsUnsigned():
+ pc = cfp.GetValueForExpressionPath("->pc")
+ if pc.GetValueAsUnsigned():
+ self.dump_iseq_frame(cfp, iseq)
+ else:
+ if frame_type == self.VM_FRAME_MAGIC_CFUNC:
+ self.dump_cfunc_frame(cfp)
+
+ curr_addr -= cfp_frame_size
+
def lldb_init(debugger):
target = debugger.GetSelectedTarget()
global SIZEOF_VALUE
@@ -110,9 +256,31 @@ def lldb_inspect(debugger, target, result, val):
print('immediate(%x)' % num, file=result)
else:
tRBasic = target.FindFirstType("struct RBasic").GetPointerType()
+ tRValue = target.FindFirstType("struct RVALUE")
+ tUintPtr = target.FindFirstType("uintptr_t") # bits_t
+
val = val.Cast(tRBasic)
flags = val.GetValueForExpressionPath("->flags").GetValueAsUnsigned()
flaginfo = ""
+
+ num_in_page = (val.GetValueAsUnsigned() & HEAP_PAGE_ALIGN_MASK) // tRValue.GetByteSize();
+ bits_bitlength = tUintPtr.GetByteSize() * 8
+ bitmap_index = num_in_page // bits_bitlength
+ bitmap_offset = num_in_page & (bits_bitlength - 1)
+ bitmap_bit = 1 << bitmap_offset
+
+ page = get_page(lldb, target, val)
+ page_type = target.FindFirstType("struct heap_page").GetPointerType()
+ page.Cast(page_type)
+
+ print("bits [%s%s%s%s%s]" % (
+ check_bits(page, "uncollectible_bits", bitmap_index, bitmap_bit, "L"),
+ check_bits(page, "mark_bits", bitmap_index, bitmap_bit, "M"),
+ check_bits(page, "pinned_bits", bitmap_index, bitmap_bit, "P"),
+ check_bits(page, "marking_bits", bitmap_index, bitmap_bit, "R"),
+ check_bits(page, "wb_unprotected_bits", bitmap_index, bitmap_bit, "U"),
+ ), file=result)
+
if (flags & RUBY_FL_PROMOTED) == RUBY_FL_PROMOTED:
flaginfo += "[PROMOTED] "
if (flags & RUBY_FL_FREEZE) == RUBY_FL_FREEZE:
@@ -132,7 +300,10 @@ def lldb_inspect(debugger, target, result, val):
result.write('T_STRING: %s' % flaginfo)
tRString = target.FindFirstType("struct RString").GetPointerType()
ptr, len = string2cstr(val.Cast(tRString))
- append_command_output(debugger, "print *(const char (*)[%d])%0#x" % (len, ptr), result)
+ if len == 0:
+ result.write("(empty)\n")
+ else:
+ append_command_output(debugger, "print *(const char (*)[%d])%0#x" % (len, ptr), result)
elif flType == RUBY_T_SYMBOL:
result.write('T_SYMBOL: %s' % flaginfo)
tRSymbol = target.FindFirstType("struct RSymbol").GetPointerType()
@@ -173,13 +344,14 @@ def lldb_inspect(debugger, target, result, val):
elif flType == RUBY_T_BIGNUM:
tRBignum = target.FindFirstType("struct RBignum").GetPointerType()
val = val.Cast(tRBignum)
+ sign = '+' if (flags & RUBY_FL_USER1) != 0 else '-'
if flags & RUBY_FL_USER2:
len = ((flags & (RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5)) >> (RUBY_FL_USHIFT+3))
- print("T_BIGNUM: len=%d (embed)" % len, file=result)
+ print("T_BIGNUM: sign=%s len=%d (embed)" % (sign, len), file=result)
append_command_output(debugger, "print ((struct RBignum *) %0#x)->as.ary" % val.GetValueAsUnsigned(), result)
else:
len = val.GetValueForExpressionPath("->as.heap.len").GetValueAsSigned()
- print("T_BIGNUM: len=%d" % len, file=result)
+ print("T_BIGNUM: sign=%s len=%d" % (sign, len), file=result)
print(val.Dereference(), file=result)
append_command_output(debugger, "expression -Z %x -fx -- (const BDIGIT*)((struct RBignum*)%d)->as.heap.digits" % (len, val.GetValueAsUnsigned()), result)
# append_command_output(debugger, "x ((struct RBignum *) %0#x)->as.heap.digits / %d" % (val.GetValueAsUnsigned(), len), result)
@@ -229,6 +401,24 @@ def lldb_inspect(debugger, target, result, val):
append_command_output(debugger, "p (node_type) %d" % nd_type, result)
val = val.Cast(tRTypedData)
append_command_output(debugger, "p *(struct RNode *) %0#x" % val.GetValueAsUnsigned(), result)
+ elif flType == RUBY_T_MOVED:
+ tRTypedData = target.FindFirstType("struct RMoved").GetPointerType()
+ val = val.Cast(tRTypedData)
+ append_command_output(debugger, "p *(struct RMoved *) %0#x" % val.GetValueAsUnsigned(), result)
+ elif flType == RUBY_T_MATCH:
+ tRTypedData = target.FindFirstType("struct RMatch").GetPointerType()
+ val = val.Cast(tRTypedData)
+ append_command_output(debugger, "p *(struct RMatch *) %0#x" % val.GetValueAsUnsigned(), result)
+ elif flType == RUBY_T_IMEMO:
+ # I'm not sure how to get IMEMO_MASK out of lldb. It's not in globals()
+ imemo_type = (flags >> RUBY_FL_USHIFT) & 0x0F # IMEMO_MASK
+ print("T_IMEMO: ", file=result)
+ append_command_output(debugger, "p (enum imemo_type) %d" % imemo_type, result)
+ append_command_output(debugger, "p *(struct MEMO *) %0#x" % val.GetValueAsUnsigned(), result)
+ elif flType == RUBY_T_ZOMBIE:
+ tRZombie = target.FindFirstType("struct RZombie").GetPointerType()
+ val = val.Cast(tRZombie)
+ append_command_output(debugger, "p *(struct RZombie *) %0#x" % val.GetValueAsUnsigned(), result)
else:
print("Not-handled type %0#x" % flType, file=result)
print(val, file=result)
@@ -261,6 +451,49 @@ def count_objects(debugger, command, ctx, result, internal_dict):
def stack_dump_raw(debugger, command, ctx, result, internal_dict):
ctx.frame.EvaluateExpression("rb_vmdebug_stack_dump_raw_current()")
+def check_bits(page, bitmap_name, bitmap_index, bitmap_bit, v):
+ bits = page.GetChildMemberWithName(bitmap_name)
+ plane = bits.GetChildAtIndex(bitmap_index).GetValueAsUnsigned()
+ if (plane & bitmap_bit) != 0:
+ return v
+ else:
+ return ' '
+
+def heap_page(debugger, command, ctx, result, internal_dict):
+ target = debugger.GetSelectedTarget()
+ process = target.GetProcess()
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ val = frame.EvaluateExpression(command)
+ page = get_page(lldb, target, val)
+ page_type = target.FindFirstType("struct heap_page").GetPointerType()
+ page.Cast(page_type)
+ append_command_output(debugger, "p (struct heap_page *) %0#x" % page.GetValueAsUnsigned(), result)
+ append_command_output(debugger, "p *(struct heap_page *) %0#x" % page.GetValueAsUnsigned(), result)
+
+def heap_page_body(debugger, command, ctx, result, internal_dict):
+ target = debugger.GetSelectedTarget()
+ process = target.GetProcess()
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ val = frame.EvaluateExpression(command)
+ page = get_page_body(lldb, target, val)
+ print("Page body address: ", page.GetAddress(), file=result)
+ print(page, file=result)
+
+def get_page_body(lldb, target, val):
+ tHeapPageBody = target.FindFirstType("struct heap_page_body")
+ addr = val.GetValueAsUnsigned()
+ page_addr = addr & ~(HEAP_PAGE_ALIGN_MASK)
+ address = lldb.SBAddress(page_addr, target)
+ return target.CreateValueFromAddress("page", address, tHeapPageBody)
+
+def get_page(lldb, target, val):
+ body = get_page_body(lldb, target, val)
+ return body.GetValueForExpressionPath("->header.page")
+
def dump_node(debugger, command, ctx, result, internal_dict):
args = shlex.split(command)
if not args:
@@ -270,10 +503,32 @@ def dump_node(debugger, command, ctx, result, internal_dict):
dump = ctx.frame.EvaluateExpression("(struct RString*)rb_parser_dump_tree((NODE*)(%s), 0)" % node)
output_string(ctx, result, dump)
+def rb_backtrace(debugger, command, result, internal_dict):
+ bt = BackTrace(debugger, command, result, internal_dict)
+ frame = bt.frame
+
+ if command:
+ if frame.IsValid():
+ val = frame.EvaluateExpression(command)
+ else:
+ val = target.EvaluateExpression(command)
+
+ error = val.GetError()
+ if error.Fail():
+ print >> result, error
+ return
+ else:
+ print("Need an EC for now")
+
+ bt.print_bt(val)
+
def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand("command script add -f lldb_cruby.lldb_rp rp")
debugger.HandleCommand("command script add -f lldb_cruby.count_objects rb_count_objects")
debugger.HandleCommand("command script add -f lldb_cruby.stack_dump_raw SDR")
debugger.HandleCommand("command script add -f lldb_cruby.dump_node dump_node")
+ debugger.HandleCommand("command script add -f lldb_cruby.heap_page heap_page")
+ debugger.HandleCommand("command script add -f lldb_cruby.heap_page_body heap_page_body")
+ debugger.HandleCommand("command script add -f lldb_cruby.rb_backtrace rbbt")
lldb_init(debugger)
print("lldb scripts for ruby has been installed.")
diff --git a/misc/lldb_disasm.py b/misc/lldb_disasm.py
new file mode 100644
index 0000000000..b46d097910
--- /dev/null
+++ b/misc/lldb_disasm.py
@@ -0,0 +1,239 @@
+#!/usr/bin/env python
+#coding: utf-8
+#
+# Usage: run `command script import -r misc/lldb_disasm.py` on LLDB
+#
+#
+# (lldb) p iseq
+# (rb_iseq_t *) $147 = 0x0000000101068400
+# (lldb) rbdisasm iseq
+# 0000 putspecialobject( 3 )
+# 0002 putnil
+# 0003 defineclass( ID: 0x560b, (rb_iseq_t *)0x1010681d0, 2 )
+# 0007 pop
+# 0008 putspecialobject( 3 )
+# 0010 putnil
+# 0011 defineclass( ID: 0x56eb, (rb_iseq_t *)0x101063b58, 2 )
+# 0015 leave
+
+
+import lldb
+import os
+import shlex
+
+class IseqDissassembler:
+ TS_VARIABLE = b'.'[0]
+ TS_CALLDATA = b'C'[0]
+ TS_CDHASH = b'H'[0]
+ TS_IC = b'K'[0]
+ TS_IVC = b'A'[0]
+ TS_ID = b'I'[0]
+ TS_ISE = b'T'[0]
+ TS_ISEQ = b'S'[0]
+ TS_OFFSET = b'O'[0]
+ TS_VALUE = b'V'[0]
+ TS_LINDEX = b'L'[0]
+ TS_FUNCPTR = b'F'[0]
+ TS_NUM = b'N'[0]
+ TS_BUILTIN = b'R'[0]
+
+ ISEQ_OPT_DISPATCH = {
+ TS_BUILTIN: "(rb_builtin_function *)%0#x",
+ TS_NUM: "%d",
+ TS_FUNCPTR: "(rb_insn_func_t) %0#x",
+ TS_LINDEX: "%d",
+ TS_VALUE: "(VALUE)%0#x",
+ TS_OFFSET: "%d",
+ TS_ISEQ: "(rb_iseq_t *)%0#x",
+ TS_ISE: "(iseq_inline_storage_entry *)%0#x",
+ TS_ID: "ID: %0#x",
+ TS_IVC: "(struct iseq_inline_iv_cache_entry *)%0#x",
+ TS_IC: "(struct iseq_inline_cache_entry *)%0#x",
+ TS_CDHASH: "CDHASH (VALUE)%0#x",
+ TS_CALLDATA: "(struct rb_call_data *)%0#x",
+ TS_VARIABLE: "VARIABLE %0#x",
+ }
+
+ def __init__(self, debugger, command, result, internal_dict):
+ self.debugger = debugger
+ self.command = command
+ self.result = result
+ self.internal_dict = internal_dict
+
+ self.target = debugger.GetSelectedTarget()
+ self.process = self.target.GetProcess()
+ self.thread = self.process.GetSelectedThread()
+ self.frame = self.thread.GetSelectedFrame()
+ self.addr2insn = self.build_addr2insn(self.target)
+ self.tChar = self.target.FindFirstType("char")
+
+ def disasm(self, val):
+ tRbISeq = self.target.FindFirstType("struct rb_iseq_struct").GetPointerType()
+ val = val.Cast(tRbISeq)
+ iseq_size = val.GetValueForExpressionPath("->body->iseq_size").GetValueAsUnsigned()
+ iseqs = val.GetValueForExpressionPath("->body->iseq_encoded")
+ idx = 0
+ print("PC IDX insn_name(operands) ", file=self.result)
+ while idx < iseq_size:
+ m = self.iseq_extract_values(self.debugger, self.target, self.process, self.result, iseqs, idx)
+ if m < 1:
+ print("Error decoding", file=self.result)
+ return
+ else:
+ idx += m
+
+ def build_addr2insn(self, target):
+ tIntPtr = target.FindFirstType("intptr_t")
+ size = target.EvaluateExpression('ruby_vminsn_type::VM_INSTRUCTION_SIZE').unsigned
+ sizeOfIntPtr = tIntPtr.GetByteSize()
+ addr_of_table = target.FindSymbols("vm_exec_core.insns_address_table")[0].GetSymbol().GetStartAddress().GetLoadAddress(target)
+
+ my_dict = {}
+
+ for insn in range(size):
+ addr_in_table = addr_of_table + (insn * sizeOfIntPtr)
+ addr = lldb.SBAddress(addr_in_table, target)
+ machine_insn = target.CreateValueFromAddress("insn", addr, tIntPtr).GetValueAsUnsigned()
+ my_dict[machine_insn] = insn
+
+ return my_dict
+
+ def rb_vm_insn_addr2insn2(self, target, result, wanted_addr):
+ return self.addr2insn.get(wanted_addr)
+
+ def iseq_extract_values(self, debugger, target, process, result, iseqs, n):
+ tValueP = target.FindFirstType("VALUE")
+ sizeofValueP = tValueP.GetByteSize()
+ pc = iseqs.unsigned + (n * sizeofValueP)
+ insn = target.CreateValueFromAddress("i", lldb.SBAddress(pc, target), tValueP)
+ addr = insn.GetValueAsUnsigned()
+ orig_insn = self.rb_vm_insn_addr2insn2(target, result, addr)
+
+ name = self.insn_name(target, process, result, orig_insn)
+ length = self.insn_len(target, orig_insn)
+ op_str = self.insn_op_types(target, process, result, orig_insn)
+ op_types = bytes(op_str, 'utf-8')
+
+ if length != (len(op_types) + 1):
+ print("error decoding iseqs", file=result)
+ return -1
+
+ print("%0#14x %04d %s" % (pc, n, name), file=result, end="")
+
+ if length == 1:
+ print("", file=result)
+ return length
+
+ print("(", end="", file=result)
+ for idx, op_type in enumerate(op_types):
+ if idx == 0:
+ print(" ", end="", file=result)
+ else:
+ print(", ", end="", file=result)
+
+ opAddr = lldb.SBAddress(iseqs.unsigned + ((n + idx + 1) * sizeofValueP), target)
+ opValue = target.CreateValueFromAddress("op", opAddr, tValueP)
+ op = opValue.GetValueAsUnsigned()
+ print(self.ISEQ_OPT_DISPATCH.get(op_type) % op, end="", file=result)
+
+ print(" )", file=result)
+ return length
+
+ def insn_len(self, target, offset):
+ size_of_char = self.tChar.GetByteSize()
+
+ symbol = target.FindSymbols("insn_len.t")[0].GetSymbol()
+ section = symbol.GetStartAddress().GetSection()
+ addr_of_table = symbol.GetStartAddress().GetOffset()
+
+ error = lldb.SBError()
+ length = section.GetSectionData().GetUnsignedInt8(error, addr_of_table + (offset * size_of_char))
+
+ if error.Success():
+ return length
+ else:
+ print("error getting length: ", error)
+
+ def insn_op_types(self, target, process, result, insn):
+ tUShort = target.FindFirstType("unsigned short")
+
+ size_of_short = tUShort.GetByteSize()
+ size_of_char = self.tChar.GetByteSize()
+
+ symbol = target.FindSymbols("insn_op_types.y")[0].GetSymbol()
+ section = symbol.GetStartAddress().GetSection()
+ addr_of_table = symbol.GetStartAddress().GetOffset()
+
+ addr_in_table = addr_of_table + (insn * size_of_short)
+
+ error = lldb.SBError()
+ offset = section.GetSectionData().GetUnsignedInt16(error, addr_in_table)
+
+ if not error.Success():
+ print("error getting op type offset: ", error)
+
+ symbol = target.FindSymbols("insn_op_types.x")[0].GetSymbol()
+ section = symbol.GetStartAddress().GetSection()
+ addr_of_table = symbol.GetStartAddress().GetOffset()
+ addr_in_name_table = addr_of_table + (offset * size_of_char)
+
+ error = lldb.SBError()
+ types = section.GetSectionData().GetString(error, addr_in_name_table)
+ if error.Success():
+ return types
+ else:
+ print("error getting op types: ", error)
+
+ def insn_name_table_offset(self, target, offset):
+ tUShort = target.FindFirstType("unsigned short")
+ size_of_short = tUShort.GetByteSize()
+
+ symbol = target.FindSymbols("insn_name.y")[0].GetSymbol()
+ section = symbol.GetStartAddress().GetSection()
+ table_offset = symbol.GetStartAddress().GetOffset()
+
+ table_offset = table_offset + (offset * size_of_short)
+
+ error = lldb.SBError()
+ offset = section.GetSectionData().GetUnsignedInt16(error, table_offset)
+
+ if error.Success():
+ return offset
+ else:
+ print("error getting insn name table offset: ", error)
+
+ def insn_name(self, target, process, result, offset):
+ symbol = target.FindSymbols("insn_name.x")[0].GetSymbol()
+ section = symbol.GetStartAddress().GetSection()
+ addr_of_table = symbol.GetStartAddress().GetOffset()
+
+ name_table_offset = self.insn_name_table_offset(target, offset)
+ addr_in_name_table = addr_of_table + name_table_offset
+
+ error = lldb.SBError()
+ name = section.GetSectionData().GetString(error, addr_in_name_table)
+
+ if error.Success():
+ return name
+ else:
+ print('error getting insn name', error)
+
+def disasm(debugger, command, result, internal_dict):
+ disassembler = IseqDissassembler(debugger, command, result, internal_dict)
+ frame = disassembler.frame
+
+ if frame.IsValid():
+ val = frame.EvaluateExpression(command)
+ else:
+ val = target.EvaluateExpression(command)
+ error = val.GetError()
+ if error.Fail():
+ print >> result, error
+ return
+
+ disassembler.disasm(val);
+
+
+def __lldb_init_module(debugger, internal_dict):
+ debugger.HandleCommand("command script add -f lldb_disasm.disasm rbdisasm")
+ print("lldb Ruby disasm installed.")
diff --git a/missing/alloca.c b/missing/alloca.c
index 96121f7647..d039dfc2cc 100644
--- a/missing/alloca.c
+++ b/missing/alloca.c
@@ -29,7 +29,7 @@
static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
#endif
-#include "ruby/config.h"
+#include "ruby/internal/config.h"
#define X3J11 1 /* config.h should contain void if needed */
#ifdef C_ALLOCA
diff --git a/missing/crypt.h b/missing/crypt.h
index 7c2642f593..ff135eee93 100644
--- a/missing/crypt.h
+++ b/missing/crypt.h
@@ -1,3 +1,5 @@
+#ifndef CRYPT_H
+#define CRYPT_H 1
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -30,9 +32,6 @@
* SUCH DAMAGE.
*/
-#ifndef CRYPT_H
-#define CRYPT_H 1
-
/* ===== Configuration ==================== */
#ifdef CHAR_BITS
diff --git a/missing/dtoa.c b/missing/dtoa.c
index e82b60c2ce..b7a8302875 100644
--- a/missing/dtoa.c
+++ b/missing/dtoa.c
@@ -183,12 +183,16 @@
#undef Long
#undef ULong
-#if SIZEOF_INT == 4
+#include <limits.h>
+
+#if (INT_MAX >> 30) && !(INT_MAX >> 31)
#define Long int
#define ULong unsigned int
-#elif SIZEOF_LONG == 4
+#elif (LONG_MAX >> 30) && !(LONG_MAX >> 31)
#define Long long int
#define ULong unsigned long int
+#else
+#error No 32bit integer
#endif
#if HAVE_LONG_LONG
@@ -202,6 +206,11 @@
#define Bug(x) {fprintf(stderr, "%s\n", (x)); exit(EXIT_FAILURE);}
#endif
+#ifndef ISDIGIT
+#include <ctype.h>
+#define ISDIGIT(c) isdigit(c)
+#endif
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -219,6 +228,9 @@ extern void FREE(void*);
#else
#define FREE xfree
#endif
+#ifndef NO_SANITIZE
+#define NO_SANITIZE(x, y) y
+#endif
#ifndef Omit_Private_Memory
#ifndef PRIVATE_MEM
@@ -280,7 +292,7 @@ extern "C" {
#endif
#ifndef hexdigit
-static const char hexdigits[] = "0123456789abcdef0123456789ABCDEF";
+static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
#endif
#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + defined(IBM) != 1
@@ -489,6 +501,19 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
#define FREE_DTOA_LOCK(n) /*unused right now*/
#endif
+#ifndef ATOMIC_PTR_CAS
+#define ATOMIC_PTR_CAS(var, old, new) ((var) = (new), (old))
+#endif
+#ifndef LIKELY
+#define LIKELY(x) (x)
+#endif
+#ifndef UNLIKELY
+#define UNLIKELY(x) (x)
+#endif
+#ifndef ASSUME
+#define ASSUME(x) (void)(x)
+#endif
+
#define Kmax 15
struct Bigint {
@@ -501,6 +526,8 @@ typedef struct Bigint Bigint;
static Bigint *freelist[Kmax+1];
+#define BLOCKING_BIGINT ((Bigint *)(-1))
+
static Bigint *
Balloc(int k)
{
@@ -510,22 +537,41 @@ Balloc(int k)
size_t len;
#endif
+ rv = 0;
ACQUIRE_DTOA_LOCK(0);
- if (k <= Kmax && (rv = freelist[k]) != 0) {
- freelist[k] = rv->next;
+ if (k <= Kmax) {
+ rv = freelist[k];
+ while (rv) {
+ Bigint *rvn = rv;
+ rv = ATOMIC_PTR_CAS(freelist[k], rv, BLOCKING_BIGINT);
+ if (LIKELY(rv != BLOCKING_BIGINT && rvn == rv)) {
+ rvn = ATOMIC_PTR_CAS(freelist[k], BLOCKING_BIGINT, rv->next);
+ assert(rvn == BLOCKING_BIGINT);
+ ASSUME(rv);
+ break;
+ }
+ }
}
- else {
+ if (!rv) {
x = 1 << k;
#ifdef Omit_Private_Memory
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
#else
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
/sizeof(double);
- if (k <= Kmax && pmem_next - private_mem + len <= PRIVATE_mem) {
- rv = (Bigint*)pmem_next;
- pmem_next += len;
+ if (k <= Kmax) {
+ double *pnext = pmem_next;
+ while (pnext - private_mem + len <= PRIVATE_mem) {
+ double *p = pnext;
+ pnext = ATOMIC_PTR_CAS(pmem_next, pnext, pnext + len);
+ if (LIKELY(p == pnext)) {
+ rv = (Bigint*)pnext;
+ ASSUME(rv);
+ break;
+ }
+ }
}
- else
+ if (!rv)
rv = (Bigint*)MALLOC(len*sizeof(double));
#endif
rv->k = k;
@@ -539,14 +585,19 @@ Balloc(int k)
static void
Bfree(Bigint *v)
{
+ Bigint *vn;
if (v) {
if (v->k > Kmax) {
FREE(v);
return;
}
ACQUIRE_DTOA_LOCK(0);
- v->next = freelist[v->k];
- freelist[v->k] = v;
+ do {
+ do {
+ vn = ATOMIC_PTR_CAS(freelist[v->k], 0, 0);
+ } while (UNLIKELY(vn == BLOCKING_BIGINT));
+ v->next = vn;
+ } while (UNLIKELY(ATOMIC_PTR_CAS(freelist[v->k], vn, v) != vn));
FREE_DTOA_LOCK(0);
}
}
@@ -829,8 +880,9 @@ static Bigint *
pow5mult(Bigint *b, int k)
{
Bigint *b1, *p5, *p51;
+ Bigint *p5tmp;
int i;
- static int p05[3] = { 5, 25, 125 };
+ static const int p05[3] = { 5, 25, 125 };
if ((i = k & 3) != 0)
b = multadd(b, p05[i-1], 0);
@@ -839,17 +891,17 @@ pow5mult(Bigint *b, int k)
return b;
if (!(p5 = p5s)) {
/* first time */
-#ifdef MULTIPLE_THREADS
ACQUIRE_DTOA_LOCK(1);
if (!(p5 = p5s)) {
- p5 = p5s = i2b(625);
+ p5 = i2b(625);
p5->next = 0;
+ p5tmp = ATOMIC_PTR_CAS(p5s, NULL, p5);
+ if (UNLIKELY(p5tmp)) {
+ Bfree(p5);
+ p5 = p5tmp;
+ }
}
FREE_DTOA_LOCK(1);
-#else
- p5 = p5s = i2b(625);
- p5->next = 0;
-#endif
}
for (;;) {
if (k & 1) {
@@ -860,17 +912,17 @@ pow5mult(Bigint *b, int k)
if (!(k >>= 1))
break;
if (!(p51 = p5->next)) {
-#ifdef MULTIPLE_THREADS
ACQUIRE_DTOA_LOCK(1);
if (!(p51 = p5->next)) {
- p51 = p5->next = mult(p5,p5);
+ p51 = mult(p5,p5);
p51->next = 0;
+ p5tmp = ATOMIC_PTR_CAS(p5->next, NULL, p51);
+ if (UNLIKELY(p5tmp)) {
+ Bfree(p51);
+ p51 = p5tmp;
+ }
}
FREE_DTOA_LOCK(1);
-#else
- p51 = p5->next = mult(p5,p5);
- p51->next = 0;
-#endif
}
p5 = p51;
}
@@ -2521,10 +2573,10 @@ static char *dtoa_result;
static char *
rv_alloc(int i)
{
- return dtoa_result = xmalloc(i);
+ return dtoa_result = MALLOC(i);
}
#else
-#define rv_alloc(i) xmalloc(i)
+#define rv_alloc(i) MALLOC(i)
#endif
static char *
@@ -2551,7 +2603,7 @@ nrv_alloc(const char *s, char **rve, size_t n)
static void
freedtoa(char *s)
{
- xfree(s);
+ FREE(s);
}
#endif
diff --git a/missing/dup2.c b/missing/dup2.c
index 7554084c5d..7f2b78c10f 100644
--- a/missing/dup2.c
+++ b/missing/dup2.c
@@ -11,7 +11,7 @@
* Return fd2 if all went well; return BADEXIT otherwise.
*/
-#include "ruby/config.h"
+#include "ruby/internal/config.h"
#if defined(HAVE_FCNTL)
# include <fcntl.h>
diff --git a/missing/explicit_bzero.c b/missing/explicit_bzero.c
index 1804cdd42e..1220e5f9ad 100644
--- a/missing/explicit_bzero.c
+++ b/missing/explicit_bzero.c
@@ -17,9 +17,9 @@
/* OS support note:
* BSDs have explicit_bzero().
- * OS-X has memset_s().
+ * macOS has memset_s().
* Windows has SecureZeroMemory() since XP.
- * Linux has none. *Sigh*
+ * Linux has explicit_bzero() since glibc 2.25, musl libc 1.1.20.
*/
/*
diff --git a/missing/file.h b/missing/file.h
index 241d716563..5e25c4761c 100644
--- a/missing/file.h
+++ b/missing/file.h
@@ -1,7 +1,6 @@
-/* This is file FILE.H */
-
#ifndef _FILE_H_
#define _FILE_H_
+/* This is file FILE.H */
#include <fcntl.h>
diff --git a/missing/flock.c b/missing/flock.c
index 71c5e74210..c0b3f80601 100644
--- a/missing/flock.c
+++ b/missing/flock.c
@@ -1,4 +1,4 @@
-#include "ruby/config.h"
+#include "ruby/internal/config.h"
#include "ruby/ruby.h"
#if defined _WIN32
diff --git a/missing/isinf.c b/missing/isinf.c
index 55187adc63..ba24b7768b 100644
--- a/missing/isinf.c
+++ b/missing/isinf.c
@@ -18,7 +18,7 @@ isinf(double n)
#else
-#include "ruby/config.h"
+#include "ruby/internal/config.h"
#if defined(HAVE_FINITE) && defined(HAVE_ISNAN)
diff --git a/missing/stdbool.h b/missing/stdbool.h
deleted file mode 100644
index f370e01e92..0000000000
--- a/missing/stdbool.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * missing/stdbool.h: Quick alternative of C99 stdbool.h
- */
-
-#ifndef _MISSING_STDBOOL_H_
-#define _MISSING_STDBOOL_H_
-
-#ifndef __bool_true_false_are_defined
-# ifndef __cplusplus
-# undef bool
-# undef false
-# undef true
-# define bool signed char
-# define false 0
-# define true 1
-# define __bool_true_false_are_defined 1
-# endif
-#endif
-
-#endif /* _MISSING_STDBOOL_H_ */
diff --git a/missing/tgamma.c b/missing/tgamma.c
index 6260e4f519..c8638eab2b 100644
--- a/missing/tgamma.c
+++ b/missing/tgamma.c
@@ -9,7 +9,7 @@ reference - Haruhiko Okumura: C-gengo niyoru saishin algorithm jiten
/***********************************************************
gamma.c -- Gamma function
***********************************************************/
-#include "ruby/config.h"
+#include "ruby/internal/config.h"
#include "ruby/missing.h"
#include <math.h>
#include <errno.h>
diff --git a/mjit.c b/mjit.c
index 4dc6ad80b4..db0efb76a3 100644
--- a/mjit.c
+++ b/mjit.c
@@ -11,60 +11,20 @@
// To share variables privately, include mjit_worker.c instead of linking.
-#include "internal.h"
+#include "ruby/internal/config.h" // defines USE_MJIT
#if USE_MJIT
-#include "mjit_worker.c"
-
#include "constant.h"
#include "id_table.h"
+#include "internal.h"
+#include "internal/class.h"
+#include "internal/cont.h"
+#include "internal/file.h"
+#include "internal/hash.h"
+#include "internal/warnings.h"
-// Copy ISeq's states so that race condition does not happen on compilation.
-static void
-mjit_copy_job_handler(void *data)
-{
- mjit_copy_job_t *job = data;
- if (stop_worker_p) { // check if mutex is still alive, before calling CRITICAL_SECTION_START.
- return;
- }
-
- CRITICAL_SECTION_START(3, "in mjit_copy_job_handler");
- // Make sure that this job is never executed when:
- // 1. job is being modified
- // 2. alloca memory inside job is expired
- // 3. ISeq is GC-ed
- if (job->finish_p) {
- CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
- return;
- }
- else if (job->iseq == NULL) { // ISeq GC notified in mjit_mark_iseq
- job->finish_p = true;
- CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
- return;
- }
-
- const struct rb_iseq_constant_body *body = job->iseq->body;
- if (job->cc_entries) {
- unsigned int i;
- struct rb_call_cache *sink = job->cc_entries;
- const struct rb_call_data *calls = body->call_data;
- const struct rb_kwarg_call_data *kw_calls = (struct rb_kwarg_call_data *)&body->call_data[body->ci_size];
- for (i = 0; i < body->ci_size; i++) {
- *sink++ = calls[i].cc;
- }
- for (i = 0; i < body->ci_kw_size; i++) {
- *sink++ = kw_calls[i].cc;
- }
- }
- if (job->is_entries) {
- memcpy(job->is_entries, body->is_entries, sizeof(union iseq_inline_storage_entry) * body->is_size);
- }
-
- job->finish_p = true;
- rb_native_cond_broadcast(&mjit_worker_wakeup);
- CRITICAL_SECTION_FINISH(3, "in mjit_copy_job_handler");
-}
+#include "mjit_worker.c"
extern int rb_thread_create_mjit_thread(void (*worker_func)(void));
@@ -101,7 +61,7 @@ mjit_gc_start_hook(void)
rb_native_cond_wait(&mjit_client_wakeup, &mjit_engine_mutex);
verbose(4, "Getting wakeup from a worker for GC");
}
- in_gc = true;
+ in_gc++;
CRITICAL_SECTION_FINISH(4, "mjit_gc_start_hook");
}
@@ -113,9 +73,12 @@ mjit_gc_exit_hook(void)
if (!mjit_enabled)
return;
CRITICAL_SECTION_START(4, "mjit_gc_exit_hook");
- in_gc = false;
- verbose(4, "Sending wakeup signal to workers after GC");
- rb_native_cond_broadcast(&mjit_gc_wakeup);
+ in_gc--;
+ RUBY_ASSERT_ALWAYS(in_gc >= 0);
+ if (!in_gc) {
+ verbose(4, "Sending wakeup signal to workers after GC");
+ rb_native_cond_broadcast(&mjit_gc_wakeup);
+ }
CRITICAL_SECTION_FINISH(4, "mjit_gc_exit_hook");
}
@@ -156,9 +119,8 @@ mjit_free_iseq(const rb_iseq_t *iseq)
return;
CRITICAL_SECTION_START(4, "mjit_free_iseq");
- if (mjit_copy_job.iseq == iseq) {
- mjit_copy_job.iseq = NULL;
- }
+ RUBY_ASSERT_ALWAYS(in_gc);
+ RUBY_ASSERT_ALWAYS(!in_jit);
if (iseq->body->jit_unit) {
// jit_unit is not freed here because it may be referred by multiple
// lists of units. `get_from_list` and `mjit_finish` do the job.
@@ -196,7 +158,7 @@ free_list(struct rb_mjit_unit_list *list, bool close_handle_p)
if (unit->handle && dlclose(unit->handle)) {
mjit_warning("failed to close handle for u%d: %s", unit->id, dlerror());
}
- clean_object_files(unit);
+ clean_temp_files(unit);
free(unit);
}
else {
@@ -206,16 +168,6 @@ free_list(struct rb_mjit_unit_list *list, bool close_handle_p)
list->length = 0;
}
-// MJIT info related to an existing continutaion.
-struct mjit_cont {
- rb_execution_context_t *ec; // continuation ec
- struct mjit_cont *prev, *next; // used to form lists
-};
-
-// Double linked list of registered continuations. This is used to detect
-// units which are in use in unload_units.
-static struct mjit_cont *first_cont;
-
// Register a new continuation with execution context `ec`. Return MJIT info about
// the continuation.
struct mjit_cont *
@@ -223,7 +175,12 @@ mjit_cont_new(rb_execution_context_t *ec)
{
struct mjit_cont *cont;
- cont = ZALLOC(struct mjit_cont);
+ // We need to use calloc instead of something like ZALLOC to avoid triggering GC here.
+ // When this function is called from rb_thread_alloc through rb_threadptr_root_fiber_setup,
+ // the thread is still being prepared and marking it causes SEGV.
+ cont = calloc(1, sizeof(struct mjit_cont));
+ if (cont == NULL)
+ rb_memerror();
cont->ec = ec;
CRITICAL_SECTION_START(3, "in mjit_cont_new");
@@ -258,7 +215,7 @@ mjit_cont_free(struct mjit_cont *cont)
}
CRITICAL_SECTION_FINISH(3, "in mjit_cont_new");
- xfree(cont);
+ free(cont);
}
// Finish work with continuation info.
@@ -273,13 +230,13 @@ finish_conts(void)
}
}
-// Create unit for `iseq`.
+// Create unit for `iseq`. This function may be called from an MJIT worker.
static void
create_unit(const rb_iseq_t *iseq)
{
struct rb_mjit_unit *unit;
- unit = ZALLOC(struct rb_mjit_unit);
+ unit = calloc(1, sizeof(struct rb_mjit_unit));
if (unit == NULL)
return;
@@ -288,100 +245,14 @@ create_unit(const rb_iseq_t *iseq)
iseq->body->jit_unit = unit;
}
-// Set up field `used_code_p` for unit iseqs whose iseq on the stack of ec.
-static void
-mark_ec_units(rb_execution_context_t *ec)
-{
- const rb_control_frame_t *cfp;
-
- if (ec->vm_stack == NULL)
- return;
- for (cfp = RUBY_VM_END_CONTROL_FRAME(ec) - 1; ; cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
- const rb_iseq_t *iseq;
- if (cfp->pc && (iseq = cfp->iseq) != NULL
- && imemo_type((VALUE) iseq) == imemo_iseq
- && (iseq->body->jit_unit) != NULL) {
- iseq->body->jit_unit->used_code_p = TRUE;
- }
-
- if (cfp == ec->cfp)
- break; // reached the most recent cfp
- }
-}
-
-// Unload JIT code of some units to satisfy the maximum permitted
-// number of units with a loaded code.
+// This is called from an MJIT worker when worker_p is true.
static void
-unload_units(void)
-{
- rb_vm_t *vm = GET_THREAD()->vm;
- rb_thread_t *th = NULL;
- struct rb_mjit_unit *unit = 0, *next, *worst;
- struct mjit_cont *cont;
- int delete_num, units_num = active_units.length;
-
- // For now, we don't unload units when ISeq is GCed. We should
- // unload such ISeqs first here.
- list_for_each_safe(&active_units.head, unit, next, unode) {
- if (unit->iseq == NULL) { // ISeq is GCed.
- remove_from_list(unit, &active_units);
- free_unit(unit);
- }
- }
-
- // Detect units which are in use and can't be unloaded.
- list_for_each(&active_units.head, unit, unode) {
- assert(unit->iseq != NULL && unit->handle != NULL);
- unit->used_code_p = FALSE;
- }
- list_for_each(&vm->living_threads, th, vmlt_node) {
- mark_ec_units(th->ec);
- }
- for (cont = first_cont; cont != NULL; cont = cont->next) {
- mark_ec_units(cont->ec);
- }
- // TODO: check slale_units and unload unused ones! (note that the unit is not associated to ISeq anymore)
-
- // Remove 1/10 units more to decrease unloading calls.
- // TODO: Calculate max total_calls in unit_queue and don't unload units
- // whose total_calls are larger than the max.
- delete_num = active_units.length / 10;
- for (; active_units.length > mjit_opts.max_cache_size - delete_num;) {
- // Find one unit that has the minimum total_calls.
- worst = NULL;
- list_for_each(&active_units.head, unit, unode) {
- if (unit->used_code_p) // We can't unload code on stack.
- continue;
-
- if (worst == NULL || worst->iseq->body->total_calls > unit->iseq->body->total_calls) {
- worst = unit;
- }
- }
- if (worst == NULL)
- break;
-
- // Unload the worst node.
- verbose(2, "Unloading unit %d (calls=%lu)", worst->id, worst->iseq->body->total_calls);
- assert(worst->handle != NULL);
- remove_from_list(worst, &active_units);
- free_unit(worst);
- }
-
- if (units_num == active_units.length && mjit_opts.wait) {
- mjit_opts.max_cache_size++; // avoid infinite loop on `rb_mjit_wait_call`. Note that --jit-wait is just for testing.
- verbose(1, "No units can be unloaded -- incremented max-cache-size to %d for --jit-wait", mjit_opts.max_cache_size);
- }
- else {
- verbose(1, "Too many JIT code -- %d units unloaded", units_num - active_units.length);
- }
-}
-
-static void
-mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info)
+mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info, bool worker_p)
{
if (!mjit_enabled || pch_status == PCH_FAILED)
return;
+ RB_DEBUG_COUNTER_INC(mjit_add_iseq_to_process);
iseq->body->jit_func = (mjit_func_t)NOT_READY_JIT_ISEQ_FUNC;
create_unit(iseq);
if (iseq->body->jit_unit == NULL)
@@ -390,14 +261,18 @@ mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_inf
if (compile_info != NULL)
iseq->body->jit_unit->compile_info = *compile_info;
- CRITICAL_SECTION_START(3, "in add_iseq_to_process");
+ if (!worker_p) {
+ CRITICAL_SECTION_START(3, "in add_iseq_to_process");
+ }
add_to_list(iseq->body->jit_unit, &unit_queue);
if (active_units.length >= mjit_opts.max_cache_size) {
- unload_units();
+ unload_requests++;
+ }
+ if (!worker_p) {
+ verbose(3, "Sending wakeup signal to workers in mjit_add_iseq_to_process");
+ rb_native_cond_broadcast(&mjit_worker_wakeup);
+ CRITICAL_SECTION_FINISH(3, "in add_iseq_to_process");
}
- verbose(3, "Sending wakeup signal to workers in mjit_add_iseq_to_process");
- rb_native_cond_broadcast(&mjit_worker_wakeup);
- CRITICAL_SECTION_FINISH(3, "in add_iseq_to_process");
}
// Add ISEQ to be JITed in parallel with the current thread.
@@ -405,7 +280,7 @@ mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_inf
void
rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq)
{
- mjit_add_iseq_to_process(iseq, NULL);
+ mjit_add_iseq_to_process(iseq, NULL, false);
}
// For this timeout seconds, --jit-wait will wait for JIT compilation finish.
@@ -454,25 +329,72 @@ rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body)
return &body->jit_unit->compile_info;
}
-void
-rb_mjit_recompile_iseq(const rb_iseq_t *iseq)
+static void
+mjit_recompile(const rb_iseq_t *iseq)
{
if ((uintptr_t)iseq->body->jit_func <= (uintptr_t)LAST_JIT_ISEQ_FUNC)
return;
verbose(1, "JIT recompile: %s@%s:%d", RSTRING_PTR(iseq->body->location.label),
RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno));
+ assert(iseq->body->jit_unit != NULL);
- CRITICAL_SECTION_START(3, "in rb_mjit_recompile_iseq");
- remove_from_list(iseq->body->jit_unit, &active_units);
- iseq->body->jit_func = (void *)NOT_ADDED_JIT_ISEQ_FUNC;
- add_to_list(iseq->body->jit_unit, &stale_units);
- CRITICAL_SECTION_FINISH(3, "in rb_mjit_recompile_iseq");
-
- mjit_add_iseq_to_process(iseq, &iseq->body->jit_unit->compile_info);
if (UNLIKELY(mjit_opts.wait)) {
+ remove_from_list(iseq->body->jit_unit, &active_units);
+ add_to_list(iseq->body->jit_unit, &stale_units);
+ mjit_add_iseq_to_process(iseq, &iseq->body->jit_unit->compile_info, false);
mjit_wait(iseq->body);
}
+ else {
+ // Lazily move active_units to stale_units to avoid race conditions around active_units with compaction.
+ // Also, it's lazily moved to unit_queue as well because otherwise it won't be added to stale_units properly.
+ // It's good to avoid a race condition between mjit_add_iseq_to_process and mjit_compile around jit_unit as well.
+ CRITICAL_SECTION_START(3, "in rb_mjit_recompile_iseq");
+ iseq->body->jit_unit->stale_p = true;
+ iseq->body->jit_func = (mjit_func_t)NOT_ADDED_JIT_ISEQ_FUNC;
+ pending_stale_p = true;
+ CRITICAL_SECTION_FINISH(3, "in rb_mjit_recompile_iseq");
+ }
+}
+
+// Recompile iseq, disabling send optimization
+void
+rb_mjit_recompile_send(const rb_iseq_t *iseq)
+{
+ rb_mjit_iseq_compile_info(iseq->body)->disable_send_cache = true;
+ mjit_recompile(iseq);
+}
+
+// Recompile iseq, disabling ivar optimization
+void
+rb_mjit_recompile_ivar(const rb_iseq_t *iseq)
+{
+ rb_mjit_iseq_compile_info(iseq->body)->disable_ivar_cache = true;
+ mjit_recompile(iseq);
+}
+
+// Recompile iseq, disabling exivar optimization
+void
+rb_mjit_recompile_exivar(const rb_iseq_t *iseq)
+{
+ rb_mjit_iseq_compile_info(iseq->body)->disable_exivar_cache = true;
+ mjit_recompile(iseq);
+}
+
+// Recompile iseq, disabling method inlining
+void
+rb_mjit_recompile_inlining(const rb_iseq_t *iseq)
+{
+ rb_mjit_iseq_compile_info(iseq->body)->disable_inlining = true;
+ mjit_recompile(iseq);
+}
+
+// Recompile iseq, disabling getconstant inlining
+void
+rb_mjit_recompile_const(const rb_iseq_t *iseq)
+{
+ rb_mjit_iseq_compile_info(iseq->body)->disable_const_cache = true;
+ mjit_recompile(iseq);
}
extern VALUE ruby_archlibdir_path, ruby_prefix_path;
@@ -801,7 +723,11 @@ mjit_init(const struct mjit_options *opts)
rb_native_cond_initialize(&mjit_worker_wakeup);
rb_native_cond_initialize(&mjit_gc_wakeup);
- // Make sure root_fiber's saved_ec is scanned by mark_ec_units
+ // Make sure the saved_ec of the initial thread's root_fiber is scanned by mark_ec_units.
+ //
+ // rb_threadptr_root_fiber_setup for the initial thread is called before mjit_init,
+ // meaning mjit_cont_new is skipped for the root_fiber. Therefore we need to call
+ // rb_fiber_init_mjit_cont again with mjit_enabled=true to set the root_fiber's mjit_cont.
rb_fiber_init_mjit_cont(GET_EC()->fiber_ptr);
// Initialize class_serials cache for compilation
@@ -879,7 +805,7 @@ mjit_resume(void)
return Qtrue;
}
-// Skip calling `clean_object_files` for units which currently exist in the list.
+// Skip calling `clean_temp_files` for units which currently exist in the list.
static void
skip_cleaning_object_files(struct rb_mjit_unit_list *list)
{
@@ -887,10 +813,6 @@ skip_cleaning_object_files(struct rb_mjit_unit_list *list)
// No mutex for list, assuming MJIT worker does not exist yet since it's immediately after fork.
list_for_each_safe(&list->head, unit, next, unode) {
-#ifndef _MSC_VER // Actually mswin does not reach here since it doesn't have fork
- if (unit->o_file) unit->o_file_inherited_p = true;
-#endif
-
#if defined(_WIN32) // mswin doesn't reach here either. This is for MinGW.
if (unit->so_file) unit->so_file = NULL;
#endif
@@ -926,6 +848,22 @@ mjit_child_after_fork(void)
start_worker();
}
+// Edit 0 to 1 to enable this feature for investigating hot methods
+#define MJIT_COUNTER 0
+#if MJIT_COUNTER
+static void
+mjit_dump_total_calls(void)
+{
+ struct rb_mjit_unit *unit;
+ fprintf(stderr, "[MJIT_COUNTER] total_calls of active_units:\n");
+ list_for_each(&active_units.head, unit, unode) {
+ const rb_iseq_t *iseq = unit->iseq;
+ fprintf(stderr, "%8ld: %s@%s:%d\n", iseq->body->total_calls, RSTRING_PTR(iseq->body->location.label),
+ RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno));
+ }
+}
+#endif
+
// Finish the threads processing units and creating PCH, finalize
// and free MJIT data. It should be called last during MJIT
// life.
@@ -961,6 +899,10 @@ mjit_finish(bool close_handle_p)
rb_native_cond_destroy(&mjit_worker_wakeup);
rb_native_cond_destroy(&mjit_gc_wakeup);
+#if MJIT_COUNTER
+ mjit_dump_total_calls();
+#endif
+
#ifndef _MSC_VER // mswin has prebuilt precompiled header
if (!mjit_opts.save_temps && getpid() == pch_owner_pid)
remove_file(pch_file);
@@ -985,6 +927,13 @@ mjit_finish(bool close_handle_p)
verbose(1, "Successful MJIT finish");
}
+// Called by rb_vm_mark().
+//
+// Mark an ISeq being compiled to prevent its CCs from being GC-ed, which
+// an MJIT worker may concurrently see.
+//
+// Also mark active_units so that we do not GC ISeq which may still be
+// referred to by mjit_recompile() or compact_all_jit_code().
void
mjit_mark(void)
{
@@ -992,33 +941,61 @@ mjit_mark(void)
return;
RUBY_MARK_ENTER("mjit");
+ // We need to release a lock when calling rb_gc_mark to avoid doubly acquiring
+ // a lock by by mjit_gc_start_hook inside rb_gc_mark.
+ //
+ // Because an MJIT worker may modify active_units anytime, we need to convert
+ // the linked list to an array to safely loop its ISeqs without keeping a lock.
CRITICAL_SECTION_START(4, "mjit_mark");
- VALUE iseq = (VALUE)mjit_copy_job.iseq;
- CRITICAL_SECTION_FINISH(4, "mjit_mark");
-
- // Don't wrap critical section with this. This may trigger GC,
- // and in that case mjit_gc_start_hook causes deadlock.
- if (iseq) rb_gc_mark(iseq);
+ int length = 0;
+ if (compiling_iseqs != NULL) {
+ while (compiling_iseqs[length]) length++;
+ }
+ length += active_units.length;
+ const rb_iseq_t **iseqs = ALLOCA_N(const rb_iseq_t *, length);
struct rb_mjit_unit *unit = NULL;
- CRITICAL_SECTION_START(4, "mjit_mark");
- list_for_each(&unit_queue.head, unit, unode) {
- if (unit->iseq) { // ISeq is still not GCed
- iseq = (VALUE)unit->iseq;
- CRITICAL_SECTION_FINISH(4, "mjit_mark rb_gc_mark");
-
- // Don't wrap critical section with this. This may trigger GC,
- // and in that case mjit_gc_start_hook causes deadlock.
- rb_gc_mark(iseq);
-
- CRITICAL_SECTION_START(4, "mjit_mark rb_gc_mark");
+ int i = 0;
+ if (compiling_iseqs != NULL) {
+ while (compiling_iseqs[i]) {
+ iseqs[i] = compiling_iseqs[i];
+ i++;
}
}
+ list_for_each(&active_units.head, unit, unode) {
+ iseqs[i] = unit->iseq;
+ i++;
+ }
+ assert(i == length);
CRITICAL_SECTION_FINISH(4, "mjit_mark");
+ for (i = 0; i < length; i++) {
+ if (iseqs[i] == NULL) // ISeq is GC-ed
+ continue;
+ rb_gc_mark((VALUE)iseqs[i]);
+ }
+
RUBY_MARK_LEAVE("mjit");
}
+// Called by rb_iseq_mark() to mark cc_entries captured for MJIT
+void
+mjit_mark_cc_entries(const struct rb_iseq_constant_body *const body)
+{
+ const struct rb_callcache **cc_entries;
+ if (body->jit_unit && (cc_entries = body->jit_unit->cc_entries) != NULL) {
+ // It must be `body->jit_unit->cc_entries_size` instead of `body->ci_size` to mark children's cc_entries
+ for (unsigned int i = 0; i < body->jit_unit->cc_entries_size; i++) {
+ const struct rb_callcache *cc = cc_entries[i];
+ if (cc != NULL && vm_cc_markable(cc)) {
+ // Pin `cc` and `cc->cme` against GC.compact as their addresses may be written in JIT-ed code.
+ rb_gc_mark((VALUE)cc);
+ rb_gc_mark((VALUE)vm_cc_cme(cc));
+ }
+ }
+ }
+}
+
// A hook to update valid_class_serials.
void
mjit_add_class_serial(rb_serial_t class_serial)
diff --git a/mjit.h b/mjit.h
index 256bf65a29..34c47d79a5 100644
--- a/mjit.h
+++ b/mjit.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_MJIT_H
+#define RUBY_MJIT_H 1
/**********************************************************************
mjit.h - Interface to MRI method JIT compiler for Ruby's main thread
@@ -6,13 +8,14 @@
**********************************************************************/
-#ifndef RUBY_MJIT_H
-#define RUBY_MJIT_H 1
+#include "ruby/internal/config.h" // defines USE_MJIT
+#include "ruby/internal/stdbool.h"
+#include "vm_core.h"
-#include "ruby.h"
-#include "debug_counter.h"
+# if USE_MJIT
-#if USE_MJIT
+#include "debug_counter.h"
+#include "ruby.h"
// Special address values of a function generated from the
// corresponding iseq by MJIT:
@@ -59,12 +62,16 @@ struct mjit_options {
// State of optimization switches
struct rb_mjit_compile_info {
- // Disable getinstancevariable/setinstancevariable optimizations based on inline cache
+ // Disable getinstancevariable/setinstancevariable optimizations based on inline cache (T_OBJECT)
bool disable_ivar_cache;
+ // Disable getinstancevariable/setinstancevariable optimizations based on inline cache (FL_EXIVAR)
+ bool disable_exivar_cache;
// Disable send/opt_send_without_block optimizations based on inline cache
bool disable_send_cache;
// Disable method inlining
bool disable_inlining;
+ // Disable opt_getinlinecache inlining
+ bool disable_const_cache;
};
typedef VALUE (*mjit_func_t)(rb_execution_context_t *, rb_control_frame_t *);
@@ -76,10 +83,14 @@ RUBY_EXTERN bool mjit_call_p;
extern void rb_mjit_add_iseq_to_process(const rb_iseq_t *iseq);
extern VALUE rb_mjit_wait_call(rb_execution_context_t *ec, struct rb_iseq_constant_body *body);
extern struct rb_mjit_compile_info* rb_mjit_iseq_compile_info(const struct rb_iseq_constant_body *body);
-extern void rb_mjit_recompile_iseq(const rb_iseq_t *iseq);
+extern void rb_mjit_recompile_send(const rb_iseq_t *iseq);
+extern void rb_mjit_recompile_ivar(const rb_iseq_t *iseq);
+extern void rb_mjit_recompile_exivar(const rb_iseq_t *iseq);
+extern void rb_mjit_recompile_inlining(const rb_iseq_t *iseq);
+extern void rb_mjit_recompile_const(const rb_iseq_t *iseq);
RUBY_SYMBOL_EXPORT_END
-extern bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname);
+extern bool mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname, int id);
extern void mjit_init(const struct mjit_options *opts);
extern void mjit_gc_start_hook(void);
extern void mjit_gc_exit_hook(void);
@@ -90,6 +101,7 @@ extern struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec);
extern void mjit_cont_free(struct mjit_cont *cont);
extern void mjit_add_class_serial(rb_serial_t class_serial);
extern void mjit_remove_class_serial(rb_serial_t class_serial);
+extern void mjit_mark_cc_entries(const struct rb_iseq_constant_body *const body);
// A threshold used to reject long iseqs from JITting as such iseqs
// takes too much time to be compiled.
@@ -100,9 +112,42 @@ static inline int
mjit_target_iseq_p(struct rb_iseq_constant_body *body)
{
return (body->type == ISEQ_TYPE_METHOD || body->type == ISEQ_TYPE_BLOCK)
+ && !body->builtin_inline_p
&& body->iseq_size < JIT_ISEQ_SIZE_THRESHOLD;
}
+# ifdef MJIT_HEADER
+NOINLINE(static COLDFUNC VALUE mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body));
+# else
+static inline VALUE mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body);
+# endif
+static VALUE
+mjit_exec_slowpath(rb_execution_context_t *ec, const rb_iseq_t *iseq, struct rb_iseq_constant_body *body)
+{
+ uintptr_t func_i = (uintptr_t)(body->jit_func);
+ ASSUME(func_i <= LAST_JIT_ISEQ_FUNC);
+ switch ((enum rb_mjit_iseq_func)func_i) {
+ case NOT_ADDED_JIT_ISEQ_FUNC:
+ RB_DEBUG_COUNTER_INC(mjit_exec_not_added);
+ if (body->total_calls == mjit_opts.min_calls && mjit_target_iseq_p(body)) {
+ rb_mjit_add_iseq_to_process(iseq);
+ if (UNLIKELY(mjit_opts.wait)) {
+ return rb_mjit_wait_call(ec, body);
+ }
+ }
+ break;
+ case NOT_READY_JIT_ISEQ_FUNC:
+ RB_DEBUG_COUNTER_INC(mjit_exec_not_ready);
+ break;
+ case NOT_COMPILED_JIT_ISEQ_FUNC:
+ RB_DEBUG_COUNTER_INC(mjit_exec_not_compiled);
+ break;
+ default: // to avoid warning with LAST_JIT_ISEQ_FUNC
+ break;
+ }
+ return Qundef;
+}
+
// Try to execute the current iseq in ec. Use JIT code if it is ready.
// If it is not, add ISEQ to the compilation queue and return Qundef.
static inline VALUE
@@ -110,8 +155,6 @@ mjit_exec(rb_execution_context_t *ec)
{
const rb_iseq_t *iseq;
struct rb_iseq_constant_body *body;
- long unsigned total_calls;
- mjit_func_t func;
if (!mjit_call_p)
return Qundef;
@@ -119,49 +162,40 @@ mjit_exec(rb_execution_context_t *ec)
iseq = ec->cfp->iseq;
body = iseq->body;
- total_calls = ++body->total_calls;
+ body->total_calls++;
- func = body->jit_func;
- if (UNLIKELY((uintptr_t)func <= (uintptr_t)LAST_JIT_ISEQ_FUNC)) {
-# ifdef MJIT_HEADER
+ mjit_func_t func = body->jit_func;
+ if (UNLIKELY((uintptr_t)func <= LAST_JIT_ISEQ_FUNC)) {
+# ifdef MJIT_HEADER
RB_DEBUG_COUNTER_INC(mjit_frame_JT2VM);
-# else
+# else
RB_DEBUG_COUNTER_INC(mjit_frame_VM2VM);
-# endif
- switch ((enum rb_mjit_iseq_func)func) {
- case NOT_ADDED_JIT_ISEQ_FUNC:
- RB_DEBUG_COUNTER_INC(mjit_exec_not_added);
- if (total_calls == mjit_opts.min_calls && mjit_target_iseq_p(body)) {
- RB_DEBUG_COUNTER_INC(mjit_exec_not_added_add_iseq);
- rb_mjit_add_iseq_to_process(iseq);
- if (UNLIKELY(mjit_opts.wait)) {
- return rb_mjit_wait_call(ec, body);
- }
- }
- return Qundef;
- case NOT_READY_JIT_ISEQ_FUNC:
- RB_DEBUG_COUNTER_INC(mjit_exec_not_ready);
- return Qundef;
- case NOT_COMPILED_JIT_ISEQ_FUNC:
- RB_DEBUG_COUNTER_INC(mjit_exec_not_compiled);
- return Qundef;
- default: // to avoid warning with LAST_JIT_ISEQ_FUNC
- break;
- }
+# endif
+ return mjit_exec_slowpath(ec, iseq, body);
}
-# ifdef MJIT_HEADER
- RB_DEBUG_COUNTER_INC(mjit_frame_JT2JT);
-# else
- RB_DEBUG_COUNTER_INC(mjit_frame_VM2JT);
-# endif
+# ifdef MJIT_HEADER
+ RB_DEBUG_COUNTER_INC(mjit_frame_JT2JT);
+# else
+ RB_DEBUG_COUNTER_INC(mjit_frame_VM2JT);
+# endif
RB_DEBUG_COUNTER_INC(mjit_exec_call_func);
return func(ec, ec->cfp);
}
void mjit_child_after_fork(void);
-#else // USE_MJIT
+# ifdef MJIT_HEADER
+#define mjit_enabled true
+# else // MJIT_HEADER
+extern bool mjit_enabled;
+# endif // MJIT_HEADER
+VALUE mjit_pause(bool wait_p);
+VALUE mjit_resume(void);
+void mjit_finish(bool close_handle_p);
+
+# else // USE_MJIT
+
static inline struct mjit_cont *mjit_cont_new(rb_execution_context_t *ec){return NULL;}
static inline void mjit_cont_free(struct mjit_cont *cont){}
static inline void mjit_gc_start_hook(void){}
@@ -173,5 +207,10 @@ static inline void mjit_remove_class_serial(rb_serial_t class_serial){}
static inline VALUE mjit_exec(rb_execution_context_t *ec) { return Qundef; /* unreachable */ }
static inline void mjit_child_after_fork(void){}
-#endif // USE_MJIT
+#define mjit_enabled false
+static inline VALUE mjit_pause(bool wait_p){ return Qnil; } // unreachable
+static inline VALUE mjit_resume(void){ return Qnil; } // unreachable
+static inline void mjit_finish(bool close_handle_p){}
+
+# endif // USE_MJIT
#endif // RUBY_MJIT_H
diff --git a/mjit_compile.c b/mjit_compile.c
index f379a896a8..c857153e35 100644
--- a/mjit_compile.c
+++ b/mjit_compile.c
@@ -10,43 +10,35 @@
// call Ruby methods (C functions that may call rb_funcall) or trigger
// GC (using ZALLOC, xmalloc, xfree, etc.) in this file.
-#include "internal.h"
+#include "ruby/internal/config.h" // defines USE_MJIT
#if USE_MJIT
+#include "internal.h"
+#include "internal/compile.h"
+#include "internal/hash.h"
+#include "internal/object.h"
+#include "internal/variable.h"
+#include "mjit.h"
#include "vm_core.h"
+#include "vm_callinfo.h"
#include "vm_exec.h"
-#include "mjit.h"
+#include "vm_insnhelper.h"
+
#include "builtin.h"
#include "insns.inc"
#include "insns_info.inc"
-#include "vm_insnhelper.h"
// Macros to check if a position is already compiled using compile_status.stack_size_for_pos
#define NOT_COMPILED_STACK_SIZE -1
#define ALREADY_COMPILED_P(status, pos) (status->stack_size_for_pos[pos] != NOT_COMPILED_STACK_SIZE)
-static size_t
-call_data_index(CALL_DATA cd, const struct rb_iseq_constant_body *body)
-{
- const struct rb_kwarg_call_data *kw_calls = (const struct rb_kwarg_call_data *)&body->call_data[body->ci_size];
- const struct rb_kwarg_call_data *kw_cd = (const struct rb_kwarg_call_data *)cd;
-
- VM_ASSERT(cd >= body->call_data && kw_cd < (kw_calls + body->ci_kw_size));
- if (kw_cd < kw_calls) {
- return cd - body->call_data;
- }
- else {
- return kw_cd - kw_calls + body->ci_size;
- }
-}
-
// For propagating information needed for lazily pushing a frame.
struct inlined_call_context {
int orig_argc; // ci->orig_argc
- VALUE me; // cc->me
- int param_size; // def_iseq_ptr(cc->me->def)->body->param.size
- int local_size; // def_iseq_ptr(cc->me->def)->body->local_table_size
+ VALUE me; // vm_cc_cme(cc)
+ int param_size; // def_iseq_ptr(vm_cc_cme(cc)->def)->body->param.size
+ int local_size; // def_iseq_ptr(vm_cc_cme(cc)->def)->body->local_table_size
};
// Storage to keep compiler's status. This should have information
@@ -58,11 +50,18 @@ struct compile_status {
// If true, JIT-ed code will use local variables to store pushed values instead of
// using VM's stack and moving stack pointer.
bool local_stack_p;
- // Safely-accessible cache entries copied from main thread.
+ // Safely-accessible ivar cache entries copied from main thread.
union iseq_inline_storage_entry *is_entries;
- struct rb_call_cache *cc_entries;
+ // Index of call cache entries captured to compiled_iseq to be marked on GC
+ int cc_entries_index;
+ // A pointer to root (i.e. not inlined) iseq being compiled.
+ const struct rb_iseq_constant_body *compiled_iseq;
+ int compiled_id; // Just a copy of compiled_iseq->jit_unit->id
// Mutated optimization levels
struct rb_mjit_compile_info *compile_info;
+ bool merge_ivar_guards_p; // If true, merge guards of ivar accesses
+ rb_serial_t ivar_serial; // ic_serial of IVC in is_entries (used only when merge_ivar_guards_p)
+ size_t max_ivar_index; // Max IVC index in is_entries (used only when merge_ivar_guards_p)
// If `inlined_iseqs[pos]` is not NULL, `mjit_compile_body` tries to inline ISeq there.
const struct rb_iseq_constant_body **inlined_iseqs;
struct inlined_call_context inline_context;
@@ -82,13 +81,38 @@ struct case_dispatch_var {
VALUE last_value;
};
-// Returns true if call cache is still not obsoleted and cc->me->def->type is available.
+static size_t
+call_data_index(CALL_DATA cd, const struct rb_iseq_constant_body *body)
+{
+ return cd - body->call_data;
+}
+
+const struct rb_callcache ** mjit_iseq_cc_entries(const struct rb_iseq_constant_body *const body);
+
+// Using this function to refer to cc_entries allocated by `mjit_capture_cc_entries`
+// instead of storing cc_entries in status directly so that we always refer to a new address
+// returned by `realloc` inside it.
+static const struct rb_callcache **
+captured_cc_entries(const struct compile_status *status)
+{
+ VM_ASSERT(status->cc_entries_index != -1);
+ return mjit_iseq_cc_entries(status->compiled_iseq) + status->cc_entries_index;
+}
+
+// Returns true if call cache is still not obsoleted and vm_cc_cme(cc)->def->type is available.
static bool
has_valid_method_type(CALL_CACHE cc)
{
- extern bool mjit_valid_class_serial_p(rb_serial_t class_serial);
- return GET_GLOBAL_METHOD_STATE() == cc->method_state
- && mjit_valid_class_serial_p(cc->class_serial[0]) && cc->me;
+ return vm_cc_cme(cc) != NULL;
+}
+
+// Returns true if MJIT thinks this cc's opt_* insn may fallback to opt_send_without_block.
+static bool
+has_cache_for_send(CALL_CACHE cc, int insn)
+{
+ extern bool rb_vm_opt_cfunc_p(CALL_CACHE cc, int insn);
+ return has_valid_method_type(cc) &&
+ !(vm_cc_cme(cc)->def->type == VM_METHOD_TYPE_CFUNC && rb_vm_opt_cfunc_p(cc, insn));
}
// Returns true if iseq can use fastpath for setup, otherwise NULL. This becomes true in the same condition
@@ -98,11 +122,23 @@ fastpath_applied_iseq_p(const CALL_INFO ci, const CALL_CACHE cc, const rb_iseq_t
{
extern bool rb_simple_iseq_p(const rb_iseq_t *iseq);
return iseq != NULL
- && !(ci->flag & VM_CALL_KW_SPLAT) && rb_simple_iseq_p(iseq) // Top of vm_callee_setup_arg. In this case, opt_pc is 0.
- && ci->orig_argc == iseq->body->param.lead_num // exclude argument_arity_error (assumption: `calling->argc == ci->orig_argc` in send insns)
+ && !(vm_ci_flag(ci) & VM_CALL_KW_SPLAT) && rb_simple_iseq_p(iseq) // Top of vm_callee_setup_arg. In this case, opt_pc is 0.
+ && vm_ci_argc(ci) == (unsigned int)iseq->body->param.lead_num // exclude argument_arity_error (assumption: `calling->argc == ci->orig_argc` in send insns)
&& vm_call_iseq_optimizable_p(ci, cc); // CC_SET_FASTPATH condition
}
+// Return true if an object of the klass may be a special const. See: rb_class_of
+static bool
+maybe_special_const_class_p(const VALUE klass)
+{
+ return klass == rb_cFalseClass
+ || klass == rb_cNilClass
+ || klass == rb_cTrueClass
+ || klass == rb_cInteger
+ || klass == rb_cSymbol
+ || klass == rb_cFloat;
+}
+
static int
compile_case_dispatch_each(VALUE key, VALUE value, VALUE arg)
{
@@ -218,12 +254,11 @@ compile_inlined_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body
{
fprintf(f, "\ncancel:\n");
fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel);\n");
- fprintf(f, " rb_mjit_iseq_compile_info(original_iseq->body)->disable_inlining = true;\n");
- fprintf(f, " rb_mjit_recompile_iseq(original_iseq);\n");
+ fprintf(f, " rb_mjit_recompile_inlining(original_iseq);\n");
// Swap pc/sp set on cancel with original pc/sp.
- fprintf(f, " const VALUE current_pc = reg_cfp->pc;\n");
- fprintf(f, " const VALUE current_sp = reg_cfp->sp;\n");
+ fprintf(f, " const VALUE *current_pc = reg_cfp->pc;\n");
+ fprintf(f, " VALUE *current_sp = reg_cfp->sp;\n");
fprintf(f, " reg_cfp->pc = orig_pc;\n");
fprintf(f, " reg_cfp->sp = orig_sp;\n\n");
@@ -245,7 +280,7 @@ compile_inlined_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body
}
// We're not just returning Qundef here so that caller's normal cancel handler can
// push back `stack` to `cfp->sp`.
- fprintf(f, " return vm_exec(ec, ec->cfp);\n");
+ fprintf(f, " return vm_exec(ec, false);\n");
}
// Print the block to cancel JIT execution.
@@ -259,14 +294,21 @@ compile_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body, struct
fprintf(f, "\nsend_cancel:\n");
fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_send_inline);\n");
- fprintf(f, " rb_mjit_iseq_compile_info(original_iseq->body)->disable_send_cache = true;\n");
- fprintf(f, " rb_mjit_recompile_iseq(original_iseq);\n");
+ fprintf(f, " rb_mjit_recompile_send(original_iseq);\n");
fprintf(f, " goto cancel;\n");
fprintf(f, "\nivar_cancel:\n");
fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_ivar_inline);\n");
- fprintf(f, " rb_mjit_iseq_compile_info(original_iseq->body)->disable_ivar_cache = true;\n");
- fprintf(f, " rb_mjit_recompile_iseq(original_iseq);\n");
+ fprintf(f, " rb_mjit_recompile_ivar(original_iseq);\n");
+ fprintf(f, " goto cancel;\n");
+
+ fprintf(f, "\nexivar_cancel:\n");
+ fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_exivar_inline);\n");
+ fprintf(f, " rb_mjit_recompile_exivar(original_iseq);\n");
+ fprintf(f, " goto cancel;\n");
+
+ fprintf(f, "\nconst_cancel:\n");
+ fprintf(f, " rb_mjit_recompile_const(original_iseq);\n");
fprintf(f, " goto cancel;\n");
fprintf(f, "\ncancel:\n");
@@ -279,7 +321,19 @@ compile_cancel_handler(FILE *f, const struct rb_iseq_constant_body *body, struct
fprintf(f, " return Qundef;\n");
}
-extern bool mjit_copy_cache_from_main_thread(const rb_iseq_t *iseq, struct rb_call_cache *cc_entries, union iseq_inline_storage_entry *is_entries);
+extern int
+mjit_capture_cc_entries(const struct rb_iseq_constant_body *compiled_iseq, const struct rb_iseq_constant_body *captured_iseq);
+
+// Copy current is_entries and use it throughout the current compilation consistently.
+// While ic->entry has been immutable since https://github.com/ruby/ruby/pull/3662,
+// we still need this to avoid a race condition between entries and ivar_serial/max_ivar_index.
+static void
+mjit_capture_is_entries(const struct rb_iseq_constant_body *body, union iseq_inline_storage_entry *is_entries)
+{
+ if (is_entries == NULL)
+ return;
+ memcpy(is_entries, body->is_entries, sizeof(union iseq_inline_storage_entry) * body->is_size);
+}
static bool
mjit_compile_body(FILE *f, const rb_iseq_t *iseq, struct compile_status *status)
@@ -298,6 +352,22 @@ mjit_compile_body(FILE *f, const rb_iseq_t *iseq, struct compile_status *status)
fprintf(f, " static const rb_iseq_t *original_iseq = (const rb_iseq_t *)0x%"PRIxVALUE";\n", (VALUE)iseq);
fprintf(f, " static const VALUE *const original_body_iseq = (VALUE *)0x%"PRIxVALUE";\n",
(VALUE)body->iseq_encoded);
+ fprintf(f, " VALUE cfp_self = reg_cfp->self;\n"); // cache self across the method
+ fprintf(f, "#define GET_SELF() cfp_self\n");
+
+ // Generate merged ivar guards first if needed
+ if (!status->compile_info->disable_ivar_cache && status->merge_ivar_guards_p) {
+ fprintf(f, " if (UNLIKELY(!(RB_TYPE_P(GET_SELF(), T_OBJECT) && (rb_serial_t)%"PRI_SERIALT_PREFIX"u == RCLASS_SERIAL(RBASIC(GET_SELF())->klass) &&", status->ivar_serial);
+ if (status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX) {
+ fprintf(f, "%"PRIuSIZE" < ROBJECT_NUMIV(GET_SELF())", status->max_ivar_index); // index < ROBJECT_NUMIV(obj) && !RB_FL_ANY_RAW(obj, ROBJECT_EMBED)
+ }
+ else {
+ fprintf(f, "ROBJECT_EMBED_LEN_MAX == ROBJECT_NUMIV(GET_SELF())"); // index < ROBJECT_NUMIV(obj) && RB_FL_ANY_RAW(obj, ROBJECT_EMBED)
+ }
+ fprintf(f, "))) {\n");
+ fprintf(f, " goto ivar_cancel;\n");
+ fprintf(f, " }\n");
+ }
// Simulate `opt_pc` in setup_parameters_complex. Other PCs which may be passed by catch tables
// are not considered since vm_exec doesn't call mjit_exec for catch tables.
@@ -315,6 +385,7 @@ mjit_compile_body(FILE *f, const rb_iseq_t *iseq, struct compile_status *status)
compile_insns(f, body, 0, 0, status);
compile_cancel_handler(f, body, status);
+ fprintf(f, "#undef GET_SELF");
return status->success;
}
@@ -345,7 +416,12 @@ inlinable_iseq_p(const struct rb_iseq_constant_body *body)
// * Do not require `cfp->sp` motion
// * Do not move `cfp->pc`
// * Do not read any `cfp->pc`
- if (insn != BIN(leave) && insn_may_depend_on_sp_or_pc(insn, body->iseq_encoded + (pos + 1)))
+ if (insn == BIN(invokebuiltin) || insn == BIN(opt_invokebuiltin_delegate) || insn == BIN(opt_invokebuiltin_delegate_leave)) {
+ // builtin insn's inlinability is handled by `Primitive.attr! 'inline'` per iseq
+ if (!body->builtin_inline_p)
+ return false;
+ }
+ else if (insn != BIN(leave) && insn_may_depend_on_sp_or_pc(insn, body->iseq_encoded + (pos + 1)))
return false;
// At this moment, `cfp->ep` in an inlined method is not working.
switch (insn) {
@@ -365,16 +441,75 @@ inlinable_iseq_p(const struct rb_iseq_constant_body *body)
return true;
}
+// Return an iseq pointer if cc has inlinable iseq.
+const rb_iseq_t *
+rb_mjit_inlinable_iseq(const struct rb_callinfo *ci, const struct rb_callcache *cc)
+{
+ const rb_iseq_t *iseq;
+ if (has_valid_method_type(cc) &&
+ !(vm_ci_flag(ci) & VM_CALL_TAILCALL) && // inlining only non-tailcall path
+ vm_cc_cme(cc)->def->type == VM_METHOD_TYPE_ISEQ &&
+ fastpath_applied_iseq_p(ci, cc, iseq = def_iseq_ptr(vm_cc_cme(cc)->def)) &&
+ // CC_SET_FASTPATH in vm_callee_setup_arg
+ inlinable_iseq_p(iseq->body)) {
+ return iseq;
+ }
+ return NULL;
+}
+
+static void
+init_ivar_compile_status(const struct rb_iseq_constant_body *body, struct compile_status *status)
+{
+ mjit_capture_is_entries(body, status->is_entries);
+
+ int num_ivars = 0;
+ unsigned int pos = 0;
+ status->max_ivar_index = 0;
+ status->ivar_serial = 0;
+
+ while (pos < body->iseq_size) {
+#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
+ int insn = rb_vm_insn_addr2insn((void *)body->iseq_encoded[pos]);
+#else
+ int insn = (int)body->iseq_encoded[pos];
+#endif
+ if (insn == BIN(getinstancevariable) || insn == BIN(setinstancevariable)) {
+ IVC ic = (IVC)body->iseq_encoded[pos+2];
+ IVC ic_copy = &(status->is_entries + ((union iseq_inline_storage_entry *)ic - body->is_entries))->iv_cache;
+ if (ic_copy->entry) { // Only initialized (ic_serial > 0) IVCs are optimized
+ num_ivars++;
+
+ if (status->max_ivar_index < ic_copy->entry->index) {
+ status->max_ivar_index = ic_copy->entry->index;
+ }
+
+ if (status->ivar_serial == 0) {
+ status->ivar_serial = ic_copy->entry->class_serial;
+ }
+ else if (status->ivar_serial != ic_copy->entry->class_serial) {
+ // Multiple classes have used this ISeq. Give up assuming one serial.
+ status->merge_ivar_guards_p = false;
+ return;
+ }
+ }
+ }
+ pos += insn_len(insn);
+ }
+ status->merge_ivar_guards_p = status->ivar_serial > 0 && num_ivars >= 2;
+}
+
// This needs to be macro instead of a function because it's using `alloca`.
#define INIT_COMPILE_STATUS(status, body, compile_root_p) do { \
status = (struct compile_status){ \
.stack_size_for_pos = (int *)alloca(sizeof(int) * body->iseq_size), \
.inlined_iseqs = compile_root_p ? \
alloca(sizeof(const struct rb_iseq_constant_body *) * body->iseq_size) : NULL, \
- .cc_entries = (body->ci_size + body->ci_kw_size) > 0 ? \
- alloca(sizeof(struct rb_call_cache) * (body->ci_size + body->ci_kw_size)) : NULL, \
.is_entries = (body->is_size > 0) ? \
alloca(sizeof(union iseq_inline_storage_entry) * body->is_size) : NULL, \
+ .cc_entries_index = (body->ci_size > 0) ? \
+ mjit_capture_cc_entries(status.compiled_iseq, body) : -1, \
+ .compiled_id = status.compiled_id, \
+ .compiled_iseq = status.compiled_iseq, \
.compile_info = compile_root_p ? \
rb_mjit_iseq_compile_info(body) : alloca(sizeof(struct rb_mjit_compile_info)) \
}; \
@@ -397,44 +532,42 @@ precompile_inlinable_iseqs(FILE *f, const rb_iseq_t *iseq, struct compile_status
#else
int insn = (int)body->iseq_encoded[pos];
#endif
-
if (insn == BIN(opt_send_without_block)) { // `compile_inlined_cancel_handler` supports only `opt_send_without_block`
CALL_DATA cd = (CALL_DATA)body->iseq_encoded[pos + 1];
- CALL_INFO ci = &cd->ci;
- CALL_CACHE cc_copy = status->cc_entries + call_data_index(cd, body); // use copy to avoid race condition
+ const struct rb_callinfo *ci = cd->ci;
+ const struct rb_callcache *cc = captured_cc_entries(status)[call_data_index(cd, body)]; // use copy to avoid race condition
+ extern bool rb_mjit_compiling_iseq_p(const rb_iseq_t *iseq);
const rb_iseq_t *child_iseq;
- if (has_valid_method_type(cc_copy) &&
- !(ci->flag & VM_CALL_TAILCALL) && // inlining only non-tailcall path
- cc_copy->me->def->type == VM_METHOD_TYPE_ISEQ && fastpath_applied_iseq_p(ci, cc_copy, child_iseq = def_iseq_ptr(cc_copy->me->def)) && // CC_SET_FASTPATH in vm_callee_setup_arg
- inlinable_iseq_p(child_iseq->body)) {
+ if ((child_iseq = rb_mjit_inlinable_iseq(ci, cc)) != NULL && rb_mjit_compiling_iseq_p(child_iseq)) {
status->inlined_iseqs[pos] = child_iseq->body;
if (mjit_opts.verbose >= 1) // print beforehand because ISeq may be GCed during copy job.
fprintf(stderr, "JIT inline: %s@%s:%d => %s@%s:%d\n",
- RSTRING_PTR(iseq->body->location.label),
- RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno),
RSTRING_PTR(child_iseq->body->location.label),
- RSTRING_PTR(rb_iseq_path(child_iseq)), FIX2INT(child_iseq->body->location.first_lineno));
+ RSTRING_PTR(rb_iseq_path(child_iseq)), FIX2INT(child_iseq->body->location.first_lineno),
+ RSTRING_PTR(iseq->body->location.label),
+ RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno));
- struct compile_status child_status;
+ struct compile_status child_status = { .compiled_iseq = status->compiled_iseq, .compiled_id = status->compiled_id };
INIT_COMPILE_STATUS(child_status, child_iseq->body, false);
child_status.inline_context = (struct inlined_call_context){
- .orig_argc = ci->orig_argc,
- .me = (VALUE)cc_copy->me,
+ .orig_argc = vm_ci_argc(ci),
+ .me = (VALUE)vm_cc_cme(cc),
.param_size = child_iseq->body->param.size,
.local_size = child_iseq->body->local_table_size
};
- if ((child_status.cc_entries != NULL || child_status.is_entries != NULL)
- && !mjit_copy_cache_from_main_thread(child_iseq, child_status.cc_entries, child_status.is_entries))
+ if (child_iseq->body->ci_size > 0 && child_status.cc_entries_index == -1) {
return false;
+ }
+ init_ivar_compile_status(child_iseq->body, &child_status);
- fprintf(f, "ALWAYS_INLINE(static VALUE _mjit_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq));\n", pos);
- fprintf(f, "static inline VALUE\n_mjit_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq)\n{\n", pos);
+ fprintf(f, "ALWAYS_INLINE(static VALUE _mjit%d_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq));\n", status->compiled_id, pos);
+ fprintf(f, "static inline VALUE\n_mjit%d_inlined_%d(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, const VALUE orig_self, const rb_iseq_t *original_iseq)\n{\n", status->compiled_id, pos);
fprintf(f, " const VALUE *orig_pc = reg_cfp->pc;\n");
- fprintf(f, " const VALUE *orig_sp = reg_cfp->sp;\n");
+ fprintf(f, " VALUE *orig_sp = reg_cfp->sp;\n");
bool success = mjit_compile_body(f, child_iseq, &child_status);
- fprintf(f, "\n} /* end of _mjit_inlined_%d */\n\n", pos);
+ fprintf(f, "\n} /* end of _mjit%d_inlined_%d */\n\n", status->compiled_id, pos);
if (!success)
return false;
@@ -447,19 +580,14 @@ precompile_inlinable_iseqs(FILE *f, const rb_iseq_t *iseq, struct compile_status
// Compile ISeq to C code in `f`. It returns true if it succeeds to compile.
bool
-mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname)
+mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname, int id)
{
- // For performance, we verify stack size only on compilation time (mjit_compile.inc.erb) without --jit-debug
- if (!mjit_opts.debug) {
- fprintf(f, "#undef OPT_CHECKED_RUN\n");
- fprintf(f, "#define OPT_CHECKED_RUN 0\n\n");
- }
-
- struct compile_status status;
+ struct compile_status status = { .compiled_iseq = iseq->body, .compiled_id = id };
INIT_COMPILE_STATUS(status, iseq->body, true);
- if ((status.cc_entries != NULL || status.is_entries != NULL)
- && !mjit_copy_cache_from_main_thread(iseq, status.cc_entries, status.is_entries))
+ if (iseq->body->ci_size > 0 && status.cc_entries_index == -1) {
return false;
+ }
+ init_ivar_compile_status(iseq->body, &status);
if (!status.compile_info->disable_send_cache && !status.compile_info->disable_inlining) {
if (!precompile_inlinable_iseqs(f, iseq, &status))
diff --git a/mjit_worker.c b/mjit_worker.c
index f0b73be2d0..d3e333da31 100644
--- a/mjit_worker.c
+++ b/mjit_worker.c
@@ -10,6 +10,19 @@
// call Ruby methods (C functions that may call rb_funcall) or trigger
// GC (using ZALLOC, xmalloc, xfree, etc.) in this file.
+/* However, note that calling `free` for resources `xmalloc`-ed in mjit.c,
+ which is currently done in some places, is sometimes problematic in the
+ following situations:
+
+ * malloc library could be different between interpreter and extensions
+ on Windows (perhaps not applicable to MJIT because CC is the same)
+ * xmalloc -> free leaks extra space used for USE_GC_MALLOC_OBJ_INFO_DETAILS
+ (not enabled by default)
+
+ ...in short, it's usually not a problem in MJIT. But maybe it's worth
+ fixing for consistency or for USE_GC_MALLOC_OBJ_INFO_DETAILS support.
+*/
+
/* We utilize widely used C compilers (GCC and LLVM Clang) to
implement MJIT. We feed them a C code generated from ISEQ. The
industrial C compilers are slower than regular JIT engines.
@@ -73,11 +86,17 @@
#endif
#include "vm_core.h"
+#include "vm_callinfo.h"
#include "mjit.h"
#include "gc.h"
#include "ruby_assert.h"
#include "ruby/debug.h"
#include "ruby/thread.h"
+#include "ruby/version.h"
+#include "builtin.h"
+#include "insns.inc"
+#include "insns_info.inc"
+#include "internal/compile.h"
#ifdef _WIN32
#include <winsock2.h>
@@ -122,30 +141,36 @@ typedef intptr_t pid_t;
#define MJIT_TMP_PREFIX "_ruby_mjit_"
+// JIT compaction requires the header transformation because linking multiple .o files
+// doesn't work without having `static` in the same function definitions. We currently
+// don't support transforming the MJIT header on Windows.
+#ifdef _WIN32
+# define USE_JIT_COMPACTION 0
+#else
+# define USE_JIT_COMPACTION 1
+#endif
+
// The unit structure that holds metadata of ISeq for MJIT.
struct rb_mjit_unit {
+ struct list_node unode;
// Unique order number of unit.
int id;
// Dlopen handle of the loaded object file.
void *handle;
rb_iseq_t *iseq;
-#ifndef _MSC_VER
- // This value is always set for `compact_all_jit_code`. Also used for lazy deletion.
- char *o_file;
- // true if it's inherited from parent Ruby process and lazy deletion should be skipped.
- // `o_file = NULL` can't be used to skip lazy deletion because `o_file` could be used
- // by child for `compact_all_jit_code`.
- bool o_file_inherited_p;
-#endif
#if defined(_WIN32)
// DLL cannot be removed while loaded on Windows. If this is set, it'll be lazily deleted.
char *so_file;
#endif
// Only used by unload_units. Flag to check this unit is currently on stack or not.
- char used_code_p;
- struct list_node unode;
+ bool used_code_p;
+ // True if this is still in active_units but it's to be lazily removed
+ bool stale_p;
// mjit_compile's optimization switches
struct rb_mjit_compile_info compile_info;
+ // captured CC values, they should be marked with iseq.
+ const struct rb_callcache **cc_entries;
+ unsigned int cc_entries_size; // iseq->body->ci_size + ones of inlined iseqs
};
// Linked list of struct rb_mjit_unit.
@@ -202,10 +227,16 @@ static rb_nativethread_cond_t mjit_client_wakeup;
static rb_nativethread_cond_t mjit_worker_wakeup;
// A thread conditional to wake up workers if at the end of GC.
static rb_nativethread_cond_t mjit_gc_wakeup;
-// True when GC is working.
-static bool in_gc;
+// Greater than 0 when GC is working.
+static int in_gc = 0;
// True when JIT is working.
-static bool in_jit;
+static bool in_jit = false;
+// True when active_units has at least one stale_p=true unit.
+static bool pending_stale_p = false;
+// The times when unload_units is requested. unload_units is called after some requests.
+static int unload_requests = 0;
+// The total number of unloaded units.
+static int total_unloads = 0;
// Set to true to stop worker.
static bool stop_worker_p;
// Set to true if worker is stopped.
@@ -368,23 +399,10 @@ remove_file(const char *filename)
}
}
-// Lazily delete .o and/or .so files.
+// Lazily delete .so files.
static void
-clean_object_files(struct rb_mjit_unit *unit)
+clean_temp_files(struct rb_mjit_unit *unit)
{
-#ifndef _MSC_VER
- if (unit->o_file) {
- char *o_file = unit->o_file;
-
- unit->o_file = NULL;
- // For compaction, unit->o_file is always set when compilation succeeds.
- // So save_temps needs to be checked here.
- if (!mjit_opts.save_temps && !unit->o_file_inherited_p)
- remove_file(o_file);
- free(o_file);
- }
-#endif
-
#if defined(_WIN32)
if (unit->so_file) {
char *so_file = unit->so_file;
@@ -412,10 +430,14 @@ free_unit(struct rb_mjit_unit *unit)
unit->iseq->body->jit_func = (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
unit->iseq->body->jit_unit = NULL;
}
+ if (unit->cc_entries) {
+ void *entries = (void *)unit->cc_entries;
+ free(entries);
+ }
if (unit->handle && dlclose(unit->handle)) { // handle is NULL if it's in queue
mjit_warning("failed to close handle for u%d: %s", unit->id, dlerror());
}
- clean_object_files(unit);
+ clean_temp_files(unit);
free(unit);
}
@@ -486,9 +508,14 @@ mjit_valid_class_serial_p(rb_serial_t class_serial)
static struct rb_mjit_unit *
get_from_list(struct rb_mjit_unit_list *list)
{
- struct rb_mjit_unit *unit = NULL, *next, *best = NULL;
+ while (in_gc) {
+ verbose(3, "Waiting wakeup from GC");
+ rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex);
+ }
+ in_jit = true; // Lock GC
// Find iseq with max total_calls
+ struct rb_mjit_unit *unit = NULL, *next, *best = NULL;
list_for_each_safe(&list->head, unit, next, unode) {
if (unit->iseq == NULL) { // ISeq is GCed.
remove_from_list(unit, list);
@@ -500,6 +527,11 @@ get_from_list(struct rb_mjit_unit_list *list)
best = unit;
}
}
+
+ in_jit = false; // Unlock GC
+ verbose(3, "Sending wakeup signal to client in a mjit-worker for GC");
+ rb_native_cond_signal(&mjit_client_wakeup);
+
if (best) {
remove_from_list(best, list);
}
@@ -546,7 +578,7 @@ form_args(int num, ...)
}
COMPILER_WARNING_PUSH
-#ifdef __GNUC__
+#if __has_warning("-Wdeprecated-declarations") || RBIMPL_COMPILER_IS(GCC)
COMPILER_WARNING_IGNORED(-Wdeprecated-declarations)
#endif
// Start an OS process of absolute executable path with arguments `argv`.
@@ -659,7 +691,7 @@ remove_so_file(const char *so_file, struct rb_mjit_unit *unit)
{
#if defined(_WIN32)
// Windows can't remove files while it's used.
- unit->so_file = strdup(so_file); // lazily delete on `clean_object_files()`
+ unit->so_file = strdup(so_file); // lazily delete on `clean_temp_files()`
if (unit->so_file == NULL)
mjit_warning("failed to allocate memory to lazily remove '%s': %s", so_file, strerror(errno));
#else
@@ -667,6 +699,91 @@ remove_so_file(const char *so_file, struct rb_mjit_unit *unit)
#endif
}
+// Print _mjitX, but make a human-readable funcname when --jit-debug is used
+static void
+sprint_funcname(char *funcname, const struct rb_mjit_unit *unit)
+{
+ const rb_iseq_t *iseq = unit->iseq;
+ if (iseq == NULL || (!mjit_opts.debug && !mjit_opts.debug_flags)) {
+ sprintf(funcname, "_mjit%d", unit->id);
+ return;
+ }
+
+ // Generate a short path
+ const char *path = RSTRING_PTR(rb_iseq_path(iseq));
+ const char *lib = "/lib/";
+ const char *version = "/" STRINGIZE(RUBY_API_VERSION_MAJOR) "." STRINGIZE(RUBY_API_VERSION_MINOR) "." STRINGIZE(RUBY_API_VERSION_TEENY) "/";
+ while (strstr(path, lib)) // skip "/lib/"
+ path = strstr(path, lib) + strlen(lib);
+ while (strstr(path, version)) // skip "/x.y.z/"
+ path = strstr(path, version) + strlen(version);
+
+ // Annotate all-normalized method names
+ const char *method = RSTRING_PTR(iseq->body->location.label);
+ if (!strcmp(method, "[]")) method = "AREF";
+ if (!strcmp(method, "[]=")) method = "ASET";
+
+ // Print and normalize
+ sprintf(funcname, "_mjit%d_%s_%s", unit->id, path, method);
+ for (size_t i = 0; i < strlen(funcname); i++) {
+ char c = funcname[i];
+ if (!(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '_')) {
+ funcname[i] = '_';
+ }
+ }
+}
+
+static const rb_iseq_t **compiling_iseqs = NULL;
+
+static bool
+set_compiling_iseqs(const rb_iseq_t *iseq)
+{
+ compiling_iseqs = calloc(iseq->body->iseq_size + 2, sizeof(rb_iseq_t *)); // 2: 1 (unit->iseq) + 1 (NULL end)
+ if (compiling_iseqs == NULL)
+ return false;
+
+ compiling_iseqs[0] = iseq;
+ int i = 1;
+
+ unsigned int pos = 0;
+ while (pos < iseq->body->iseq_size) {
+#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
+ int insn = rb_vm_insn_addr2insn((void *)iseq->body->iseq_encoded[pos]);
+#else
+ int insn = (int)iseq->body->iseq_encoded[pos];
+#endif
+ if (insn == BIN(opt_send_without_block)) {
+ CALL_DATA cd = (CALL_DATA)iseq->body->iseq_encoded[pos + 1];
+ extern const rb_iseq_t *rb_mjit_inlinable_iseq(const struct rb_callinfo *ci, const struct rb_callcache *cc);
+ const rb_iseq_t *iseq = rb_mjit_inlinable_iseq(cd->ci, cd->cc);
+ if (iseq != NULL) {
+ compiling_iseqs[i] = iseq;
+ i++;
+ }
+ }
+ pos += insn_len(insn);
+ }
+ return true;
+}
+
+bool
+rb_mjit_compiling_iseq_p(const rb_iseq_t *iseq)
+{
+ assert(compiling_iseqs != NULL);
+ int i = 0;
+ while (compiling_iseqs[i]) {
+ if (compiling_iseqs[i] == iseq) return true;
+ i++;
+ }
+ return false;
+}
+
+static const int c_file_access_mode =
+#ifdef O_BINARY
+ O_BINARY|
+#endif
+ O_WRONLY|O_EXCL|O_CREAT;
+
#define append_str2(p, str, len) ((char *)memcpy((p), str, (len))+(len))
#define append_str(p, str) append_str2(p, str, sizeof(str)-1)
#define append_lit(p, str) append_str2(p, str, rb_strlen_lit(str))
@@ -787,99 +904,164 @@ make_pch(void)
CRITICAL_SECTION_FINISH(3, "in make_pch");
}
-// Compile .c file to .o file. It returns true if it succeeds. (non-mswin)
+// Compile .c file to .so file. It returns true if it succeeds. (non-mswin)
+// Not compiling .c to .so directly because it fails on MinGW, and this helps
+// to generate no .dSYM on macOS.
static bool
-compile_c_to_o(const char *c_file, const char *o_file)
+compile_c_to_so(const char *c_file, const char *so_file)
{
- const char *files[] = {
+ char* o_file = alloca(strlen(c_file) + 1);
+ strcpy(o_file, c_file);
+ o_file[strlen(c_file) - 1] = 'o';
+
+ const char *o_args[] = {
"-o", o_file, c_file,
# ifdef __clang__
"-include-pch", pch_file,
# endif
"-c", NULL
};
-
- char **args = form_args(5, cc_common_args, CC_CODEFLAG_ARGS, cc_added_args, files, CC_LINKER_ARGS);
- if (args == NULL)
- return false;
-
+ char **args = form_args(5, cc_common_args, CC_CODEFLAG_ARGS, cc_added_args, o_args, CC_LINKER_ARGS);
+ if (args == NULL) return false;
int exit_code = exec_process(cc_path, args);
free(args);
+ if (exit_code != 0) {
+ verbose(2, "compile_c_to_so: failed to compile .c to .o: %d", exit_code);
+ return false;
+ }
- if (exit_code != 0)
- verbose(2, "compile_c_to_o: compile error: %d", exit_code);
- return exit_code == 0;
-}
-
-// Link .o files to .so file. It returns true if it succeeds. (non-mswin)
-static bool
-link_o_to_so(const char **o_files, const char *so_file)
-{
- const char *options[] = {
+ const char *so_args[] = {
"-o", so_file,
# ifdef _WIN32
libruby_pathflag,
# endif
- NULL
+ o_file, NULL
};
+ args = form_args(6, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS, so_args, CC_LIBS, CC_DLDFLAGS_ARGS, CC_LINKER_ARGS);
+ if (args == NULL) return false;
+ exit_code = exec_process(cc_path, args);
+ free(args);
+ if (!mjit_opts.save_temps) remove_file(o_file);
+ if (exit_code != 0) {
+ verbose(2, "compile_c_to_so: failed to link .o to .so: %d", exit_code);
+ }
+ return exit_code == 0;
+}
+#endif // _MSC_VER
-# if defined(__MACH__)
- extern VALUE rb_libruby_selfpath;
- const char *loader_args[] = {"-bundle_loader", StringValuePtr(rb_libruby_selfpath), NULL};
-# else
- const char *loader_args[] = {NULL};
-# endif
+#if USE_JIT_COMPACTION
+static void compile_prelude(FILE *f);
- char **args = form_args(8, CC_LDSHARED_ARGS, CC_CODEFLAG_ARGS,
- options, o_files, loader_args, CC_LIBS, CC_DLDFLAGS_ARGS, CC_LINKER_ARGS);
- if (args == NULL)
+static bool
+compile_compact_jit_code(char* c_file)
+{
+ FILE *f;
+ int fd = rb_cloexec_open(c_file, c_file_access_mode, 0600);
+ if (fd < 0 || (f = fdopen(fd, "w")) == NULL) {
+ int e = errno;
+ if (fd >= 0) (void)close(fd);
+ verbose(1, "Failed to fopen '%s', giving up JIT for it (%s)", c_file, strerror(e));
return false;
+ }
- int exit_code = exec_process(cc_path, args);
- free(args);
+ compile_prelude(f);
- if (exit_code != 0)
- verbose(2, "link_o_to_so: link error: %d", exit_code);
- return exit_code == 0;
+ // wait until mjit_gc_exit_hook is called
+ CRITICAL_SECTION_START(3, "before mjit_compile to wait GC finish");
+ while (in_gc) {
+ verbose(3, "Waiting wakeup from GC");
+ rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex);
+ }
+ // We need to check again here because we could've waited on GC above
+ bool iseq_gced = false;
+ struct rb_mjit_unit *child_unit = 0, *next;
+ list_for_each_safe(&active_units.head, child_unit, next, unode) {
+ if (child_unit->iseq == NULL) { // ISeq is GC-ed
+ iseq_gced = true;
+ verbose(1, "JIT compaction: A method for JIT code u%d is obsoleted. Compaction will be skipped.", child_unit->id);
+ remove_from_list(child_unit, &active_units);
+ free_unit(child_unit); // unload it without waiting for throttled unload_units to retry compaction quickly
+ }
+ }
+ in_jit = !iseq_gced;
+ CRITICAL_SECTION_FINISH(3, "before mjit_compile to wait GC finish");
+ if (!in_jit) {
+ fclose(f);
+ if (!mjit_opts.save_temps)
+ remove_file(c_file);
+ return false;
+ }
+
+ // This entire loop lock GC so that we do not need to consider a case that
+ // ISeq is GC-ed in a middle of re-compilation. It takes 3~4ms with 100 methods
+ // on my machine. It's not too bad compared to compilation time of C (7200~8000ms),
+ // but it might be larger if we use a larger --jit-max-cache.
+ //
+ // TODO: Consider using a more granular lock after we implement inlining across
+ // compacted functions (not done yet).
+ bool success = true;
+ list_for_each(&active_units.head, child_unit, unode) {
+ CRITICAL_SECTION_START(3, "before set_compiling_iseqs");
+ success &= set_compiling_iseqs(child_unit->iseq);
+ CRITICAL_SECTION_FINISH(3, "after set_compiling_iseqs");
+ if (!success) continue;
+
+ char funcname[MAXPATHLEN];
+ sprint_funcname(funcname, child_unit);
+
+ long iseq_lineno = 0;
+ if (FIXNUM_P(child_unit->iseq->body->location.first_lineno))
+ // FIX2INT may fallback to rb_num2long(), which is a method call and dangerous in MJIT worker. So using only FIX2LONG.
+ iseq_lineno = FIX2LONG(child_unit->iseq->body->location.first_lineno);
+ const char *sep = "@";
+ const char *iseq_label = RSTRING_PTR(child_unit->iseq->body->location.label);
+ const char *iseq_path = RSTRING_PTR(rb_iseq_path(child_unit->iseq));
+ if (!iseq_label) iseq_label = sep = "";
+ fprintf(f, "\n/* %s%s%s:%ld */\n", iseq_label, sep, iseq_path, iseq_lineno);
+ success &= mjit_compile(f, child_unit->iseq, funcname, child_unit->id);
+
+ CRITICAL_SECTION_START(3, "before compiling_iseqs free");
+ free(compiling_iseqs);
+ compiling_iseqs = NULL;
+ CRITICAL_SECTION_FINISH(3, "after compiling_iseqs free");
+ }
+
+ // release blocking mjit_gc_start_hook
+ CRITICAL_SECTION_START(3, "after mjit_compile to wakeup client for GC");
+ in_jit = false;
+ verbose(3, "Sending wakeup signal to client in a mjit-worker for GC");
+ rb_native_cond_signal(&mjit_client_wakeup);
+ CRITICAL_SECTION_FINISH(3, "in worker to wakeup client for GC");
+
+ fclose(f);
+ return success;
}
-// Link all cached .o files and build a .so file. Reload all JIT func from it. This
-// allows to avoid JIT code fragmentation and improve performance to call JIT-ed code.
+// Compile all cached .c files and build a single .so file. Reload all JIT func from it.
+// This improves the code locality for better performance in terms of iTLB and iCache.
static void
compact_all_jit_code(void)
{
-# ifndef _WIN32 // This requires header transformation but we don't transform header on Windows for now
struct rb_mjit_unit *unit, *cur = 0;
- double start_time, end_time;
+ static const char c_ext[] = ".c";
static const char so_ext[] = DLEXT;
- char so_file[MAXPATHLEN];
- const char **o_files;
- int i = 0;
+ char c_file[MAXPATHLEN], so_file[MAXPATHLEN];
// Abnormal use case of rb_mjit_unit that doesn't have ISeq
unit = calloc(1, sizeof(struct rb_mjit_unit)); // To prevent GC, don't use ZALLOC
if (unit == NULL) return;
unit->id = current_unit_num++;
+ sprint_uniq_filename(c_file, (int)sizeof(c_file), unit->id, MJIT_TMP_PREFIX, c_ext);
sprint_uniq_filename(so_file, (int)sizeof(so_file), unit->id, MJIT_TMP_PREFIX, so_ext);
- // NULL-ending for form_args
- o_files = alloca(sizeof(char *) * (active_units.length + 1));
- o_files[active_units.length] = NULL;
- CRITICAL_SECTION_START(3, "in compact_all_jit_code to keep .o files");
- list_for_each(&active_units.head, cur, unode) {
- o_files[i] = cur->o_file;
- i++;
+ bool success = compile_compact_jit_code(c_file);
+ double start_time = real_ms_time();
+ if (success) {
+ success = compile_c_to_so(c_file, so_file);
+ if (!mjit_opts.save_temps)
+ remove_file(c_file);
}
-
- start_time = real_ms_time();
- bool success = link_o_to_so(o_files, so_file);
- end_time = real_ms_time();
-
- // TODO: Shrink this big critical section. For now, this is needed to prevent failure by missing .o files.
- // This assumes that o -> so link doesn't take long time because the bottleneck, which is compiler optimization,
- // is already done. But actually it takes about 500ms for 5,000 methods on my Linux machine, so it's better to
- // finish this critical section before link_o_to_so by disabling unload_units.
- CRITICAL_SECTION_FINISH(3, "in compact_all_jit_code to keep .o files");
+ double end_time = real_ms_time();
if (success) {
void *handle = dlopen(so_file, RTLD_NOW);
@@ -899,8 +1081,8 @@ compact_all_jit_code(void)
CRITICAL_SECTION_START(3, "in compact_all_jit_code to read list");
list_for_each(&active_units.head, cur, unode) {
void *func;
- char funcname[35]; // TODO: reconsider `35`
- sprintf(funcname, "_mjit%d", cur->id);
+ char funcname[MAXPATHLEN];
+ sprint_funcname(funcname, cur);
if ((func = dlsym(handle, funcname)) == NULL) {
mjit_warning("skipping to reload '%s' from '%s': %s", funcname, so_file, dlerror());
@@ -913,16 +1095,14 @@ compact_all_jit_code(void)
}
}
CRITICAL_SECTION_FINISH(3, "in compact_all_jit_code to read list");
- verbose(1, "JIT compaction (%.1fms): Compacted %d methods -> %s", end_time - start_time, active_units.length, so_file);
+ verbose(1, "JIT compaction (%.1fms): Compacted %d methods %s -> %s", end_time - start_time, active_units.length, c_file, so_file);
}
else {
free(unit);
verbose(1, "JIT compaction failure (%.1fms): Failed to compact methods", end_time - start_time);
}
-# endif // _WIN32
}
-
-#endif // _MSC_VER
+#endif // USE_JIT_COMPACTION
static void *
load_func_from_so(const char *so_file, const char *funcname, struct rb_mjit_unit *unit)
@@ -988,44 +1168,16 @@ compile_prelude(FILE *f)
static mjit_func_t
convert_unit_to_func(struct rb_mjit_unit *unit)
{
- char c_file_buff[MAXPATHLEN], *c_file = c_file_buff, *so_file, funcname[35]; // TODO: reconsider `35`
- int fd;
- FILE *f;
- void *func;
- double start_time, end_time;
- int c_file_len = (int)sizeof(c_file_buff);
static const char c_ext[] = ".c";
static const char so_ext[] = DLEXT;
- const int access_mode =
-#ifdef O_BINARY
- O_BINARY|
-#endif
- O_WRONLY|O_EXCL|O_CREAT;
-#ifndef _MSC_VER
- static const char o_ext[] = ".o";
- char *o_file;
-#endif
-
- c_file_len = sprint_uniq_filename(c_file_buff, c_file_len, unit->id, MJIT_TMP_PREFIX, c_ext);
- if (c_file_len >= (int)sizeof(c_file_buff)) {
- ++c_file_len;
- c_file = alloca(c_file_len);
- c_file_len = sprint_uniq_filename(c_file, c_file_len, unit->id, MJIT_TMP_PREFIX, c_ext);
- }
- ++c_file_len;
+ char c_file[MAXPATHLEN], so_file[MAXPATHLEN], funcname[MAXPATHLEN];
-#ifndef _MSC_VER
- o_file = alloca(c_file_len - sizeof(c_ext) + sizeof(o_ext));
- memcpy(o_file, c_file, c_file_len - sizeof(c_ext));
- memcpy(&o_file[c_file_len - sizeof(c_ext)], o_ext, sizeof(o_ext));
-#endif
- so_file = alloca(c_file_len - sizeof(c_ext) + sizeof(so_ext));
- memcpy(so_file, c_file, c_file_len - sizeof(c_ext));
- memcpy(&so_file[c_file_len - sizeof(c_ext)], so_ext, sizeof(so_ext));
-
- sprintf(funcname, "_mjit%d", unit->id);
+ sprint_uniq_filename(c_file, (int)sizeof(c_file), unit->id, MJIT_TMP_PREFIX, c_ext);
+ sprint_uniq_filename(so_file, (int)sizeof(so_file), unit->id, MJIT_TMP_PREFIX, so_ext);
+ sprint_funcname(funcname, unit);
- fd = rb_cloexec_open(c_file, access_mode, 0600);
+ FILE *f;
+ int fd = rb_cloexec_open(c_file, c_file_access_mode, 0600);
if (fd < 0 || (f = fdopen(fd, "w")) == NULL) {
int e = errno;
if (fd >= 0) (void)close(fd);
@@ -1042,19 +1194,15 @@ convert_unit_to_func(struct rb_mjit_unit *unit)
verbose(3, "Waiting wakeup from GC");
rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex);
}
-
// We need to check again here because we could've waited on GC above
- if (unit->iseq == NULL) {
+ in_jit = (unit->iseq != NULL);
+ if (in_jit)
+ in_jit &= set_compiling_iseqs(unit->iseq);
+ CRITICAL_SECTION_FINISH(3, "before mjit_compile to wait GC finish");
+ if (!in_jit) {
fclose(f);
if (!mjit_opts.save_temps)
remove_file(c_file);
- in_jit = false; // just being explicit for return
- }
- else {
- in_jit = true;
- }
- CRITICAL_SECTION_FINISH(3, "before mjit_compile to wait GC finish");
- if (!in_jit) {
return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
}
@@ -1070,10 +1218,12 @@ convert_unit_to_func(struct rb_mjit_unit *unit)
verbose(2, "start compilation: %s@%s:%ld -> %s", iseq_label, iseq_path, iseq_lineno, c_file);
fprintf(f, "/* %s@%s:%ld */\n\n", iseq_label, iseq_path, iseq_lineno);
- bool success = mjit_compile(f, unit->iseq, funcname);
+ bool success = mjit_compile(f, unit->iseq, funcname, unit->id);
// release blocking mjit_gc_start_hook
CRITICAL_SECTION_START(3, "after mjit_compile to wakeup client for GC");
+ free(compiling_iseqs);
+ compiling_iseqs = NULL;
in_jit = false;
verbose(3, "Sending wakeup signal to client in a mjit-worker for GC");
rb_native_cond_signal(&mjit_client_wakeup);
@@ -1087,32 +1237,18 @@ convert_unit_to_func(struct rb_mjit_unit *unit)
return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
}
- start_time = real_ms_time();
-#ifdef _MSC_VER
+ double start_time = real_ms_time();
success = compile_c_to_so(c_file, so_file);
-#else
- // splitting .c -> .o step and .o -> .so step, to cache .o files in the future
- if ((success = compile_c_to_o(c_file, o_file)) != false) {
- success = link_o_to_so((const char *[]){ o_file, NULL }, so_file);
-
- // Always set o_file for compaction. The value is also used for lazy deletion.
- unit->o_file = strdup(o_file);
- if (unit->o_file == NULL) {
- mjit_warning("failed to allocate memory to remember '%s' (%s), removing it...", o_file, strerror(errno));
- remove_file(o_file);
- }
- }
-#endif
- end_time = real_ms_time();
-
if (!mjit_opts.save_temps)
remove_file(c_file);
+ double end_time = real_ms_time();
+
if (!success) {
verbose(2, "Failed to generate so: %s", so_file);
return (mjit_func_t)NOT_COMPILED_JIT_ISEQ_FUNC;
}
- func = load_func_from_so(so_file, funcname, unit);
+ void *func = load_func_from_so(so_file, funcname, unit);
if (!mjit_opts.save_temps)
remove_so_file(so_file, unit);
@@ -1123,84 +1259,167 @@ convert_unit_to_func(struct rb_mjit_unit *unit)
return (mjit_func_t)func;
}
-typedef struct {
- const rb_iseq_t *iseq;
- struct rb_call_cache *cc_entries;
- union iseq_inline_storage_entry *is_entries;
- bool finish_p;
-} mjit_copy_job_t;
+// To see cc_entries using index returned by `mjit_capture_cc_entries` in mjit_compile.c
+const struct rb_callcache **
+mjit_iseq_cc_entries(const struct rb_iseq_constant_body *const body)
+{
+ return body->jit_unit->cc_entries;
+}
-// Singleton MJIT copy job. This is made global since it needs to be durable even when MJIT worker thread is stopped.
-// (ex: register job -> MJIT pause -> MJIT resume -> dispatch job. Actually this should be just cancelled by finish_p check)
-static mjit_copy_job_t mjit_copy_job = { .iseq = NULL, .finish_p = true };
+// Capture cc entries of `captured_iseq` and append them to `compiled_iseq->jit_unit->cc_entries`.
+// This is needed when `captured_iseq` is inlined by `compiled_iseq` and GC needs to mark inlined cc.
+//
+// Index to refer to `compiled_iseq->jit_unit->cc_entries` is returned instead of the address
+// because old addresses may be invalidated by `realloc` later. -1 is returned on failure.
+//
+// This assumes that it's safe to reference cc without acquiring GVL.
+int
+mjit_capture_cc_entries(const struct rb_iseq_constant_body *compiled_iseq, const struct rb_iseq_constant_body *captured_iseq)
+{
+ struct rb_mjit_unit *unit = compiled_iseq->jit_unit;
+ unsigned int new_entries_size = unit->cc_entries_size + captured_iseq->ci_size;
+ VM_ASSERT(captured_iseq->ci_size > 0);
+
+ // Allocate new cc_entries and append them to unit->cc_entries
+ const struct rb_callcache **cc_entries;
+ int cc_entries_index = unit->cc_entries_size;
+ if (unit->cc_entries_size == 0) {
+ VM_ASSERT(unit->cc_entries == NULL);
+ unit->cc_entries = cc_entries = malloc(sizeof(struct rb_callcache *) * new_entries_size);
+ if (cc_entries == NULL) return -1;
+ }
+ else {
+ void *cc_ptr = (void *)unit->cc_entries; // get rid of bogus warning by VC
+ cc_entries = realloc(cc_ptr, sizeof(struct rb_callcache *) * new_entries_size);
+ if (cc_entries == NULL) return -1;
+ unit->cc_entries = cc_entries;
+ cc_entries += cc_entries_index;
+ }
+ unit->cc_entries_size = new_entries_size;
-static void mjit_copy_job_handler(void *data);
+ // Capture cc to cc_enties
+ for (unsigned int i = 0; i < captured_iseq->ci_size; i++) {
+ cc_entries[i] = captured_iseq->call_data[i].cc;
+ }
-// vm_trace.c
-int rb_workqueue_register(unsigned flags, rb_postponed_job_func_t , void *);
+ return cc_entries_index;
+}
-// Copy inline cache values of `iseq` to `cc_entries` and `is_entries`.
-// These buffers should be pre-allocated properly prior to calling this function.
-// Return true if copy succeeds or is not needed.
-//
-// We're lazily copying cache values from main thread because these cache values
-// could be different between ones on enqueue timing and ones on dequeue timing.
-bool
-mjit_copy_cache_from_main_thread(const rb_iseq_t *iseq, struct rb_call_cache *cc_entries, union iseq_inline_storage_entry *is_entries)
+// Set up field `used_code_p` for unit iseqs whose iseq on the stack of ec.
+static void
+mark_ec_units(rb_execution_context_t *ec)
{
- mjit_copy_job_t *job = &mjit_copy_job; // just a short hand
+ const rb_control_frame_t *cfp;
- CRITICAL_SECTION_START(3, "in mjit_copy_cache_from_main_thread");
- job->finish_p = true; // disable dispatching this job in mjit_copy_job_handler while it's being modified
- CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread");
+ if (ec->vm_stack == NULL)
+ return;
+ for (cfp = RUBY_VM_END_CONTROL_FRAME(ec) - 1; ; cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
+ const rb_iseq_t *iseq;
+ if (cfp->pc && (iseq = cfp->iseq) != NULL
+ && imemo_type((VALUE) iseq) == imemo_iseq
+ && (iseq->body->jit_unit) != NULL) {
+ iseq->body->jit_unit->used_code_p = true;
+ }
- job->cc_entries = cc_entries;
- job->is_entries = is_entries;
+ if (cfp == ec->cfp)
+ break; // reached the most recent cfp
+ }
+}
- CRITICAL_SECTION_START(3, "in mjit_copy_cache_from_main_thread");
- job->iseq = iseq; // Prevernt GC of this ISeq from here
- VM_ASSERT(in_jit);
- in_jit = false; // To avoid deadlock, allow running GC while waiting for copy job
- rb_native_cond_signal(&mjit_client_wakeup); // Unblock main thread waiting in `mjit_gc_start_hook`
+// MJIT info related to an existing continutaion.
+struct mjit_cont {
+ rb_execution_context_t *ec; // continuation ec
+ struct mjit_cont *prev, *next; // used to form lists
+};
- job->finish_p = false; // allow dispatching this job in mjit_copy_job_handler
- CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread");
+// Double linked list of registered continuations. This is used to detect
+// units which are in use in unload_units.
+static struct mjit_cont *first_cont;
- if (UNLIKELY(mjit_opts.wait)) {
- mjit_copy_job_handler((void *)job);
+// Unload JIT code of some units to satisfy the maximum permitted
+// number of units with a loaded code.
+static void
+unload_units(void)
+{
+ struct rb_mjit_unit *unit = 0, *next;
+ struct mjit_cont *cont;
+ int units_num = active_units.length;
+
+ // For now, we don't unload units when ISeq is GCed. We should
+ // unload such ISeqs first here.
+ list_for_each_safe(&active_units.head, unit, next, unode) {
+ if (unit->iseq == NULL) { // ISeq is GCed.
+ remove_from_list(unit, &active_units);
+ free_unit(unit);
+ }
}
- else if (rb_workqueue_register(0, mjit_copy_job_handler, (void *)job)) {
- CRITICAL_SECTION_START(3, "in MJIT copy job wait");
- // checking `stop_worker_p` too because `RUBY_VM_CHECK_INTS(ec)` may not
- // lush mjit_copy_job_handler when EC_EXEC_TAG() is not TAG_NONE, and then
- // `stop_worker()` could dead lock with this function.
- while (!job->finish_p && !stop_worker_p) {
- rb_native_cond_wait(&mjit_worker_wakeup, &mjit_engine_mutex);
- verbose(3, "Getting wakeup from client");
+
+ // Detect units which are in use and can't be unloaded.
+ list_for_each(&active_units.head, unit, unode) {
+ assert(unit->iseq != NULL && unit->handle != NULL);
+ unit->used_code_p = false;
+ }
+ // All threads have a root_fiber which has a mjit_cont. Other normal fibers also
+ // have a mjit_cont. Thus we can check ISeqs in use by scanning ec of mjit_conts.
+ for (cont = first_cont; cont != NULL; cont = cont->next) {
+ mark_ec_units(cont->ec);
+ }
+ // TODO: check stale_units and unload unused ones! (note that the unit is not associated to ISeq anymore)
+
+ // Unload units whose total_calls is smaller than any total_calls in unit_queue.
+ // TODO: make the algorithm more efficient
+ long unsigned prev_queue_calls = -1;
+ while (true) {
+ // Calculate the next max total_calls in unit_queue
+ long unsigned max_queue_calls = 0;
+ list_for_each(&unit_queue.head, unit, unode) {
+ if (unit->iseq != NULL && max_queue_calls < unit->iseq->body->total_calls
+ && unit->iseq->body->total_calls < prev_queue_calls) {
+ max_queue_calls = unit->iseq->body->total_calls;
+ }
}
- CRITICAL_SECTION_FINISH(3, "in MJIT copy job wait");
+ prev_queue_calls = max_queue_calls;
+
+ bool unloaded_p = false;
+ list_for_each_safe(&active_units.head, unit, next, unode) {
+ if (unit->used_code_p) // We can't unload code on stack.
+ continue;
+
+ if (max_queue_calls > unit->iseq->body->total_calls) {
+ verbose(2, "Unloading unit %d (calls=%lu, threshold=%lu)",
+ unit->id, unit->iseq->body->total_calls, max_queue_calls);
+ assert(unit->handle != NULL);
+ remove_from_list(unit, &active_units);
+ free_unit(unit);
+ unloaded_p = true;
+ }
+ }
+ if (!unloaded_p) break;
}
- CRITICAL_SECTION_START(3, "in mjit_copy_cache_from_main_thread");
- bool success_p = job->finish_p;
- // Disable dispatching this job in mjit_copy_job_handler while memory allocated by alloca
- // could be expired after finishing this function.
- job->finish_p = true;
-
- in_jit = true; // Prohibit GC during JIT compilation
- if (job->iseq == NULL) // ISeq GC is notified in mjit_mark_iseq
- success_p = false;
- job->iseq = NULL; // Allow future GC of this ISeq from here
- CRITICAL_SECTION_FINISH(3, "in mjit_copy_cache_from_main_thread");
- return success_p;
+ if (units_num > active_units.length) {
+ verbose(1, "Too many JIT code -- %d units unloaded", units_num - active_units.length);
+ total_unloads += units_num - active_units.length;
+ }
}
+static void mjit_add_iseq_to_process(const rb_iseq_t *iseq, const struct rb_mjit_compile_info *compile_info, bool worker_p);
+
// The function implementing a worker. It is executed in a separate
// thread by rb_thread_create_mjit_thread. It compiles precompiled header
// and then compiles requested ISeqs.
void
mjit_worker(void)
{
+ // Allow only `max_cache_size / 10` times (default: 10) of compaction.
+ // Note: GC of compacted code has not been implemented yet.
+ int max_compact_size = mjit_opts.max_cache_size / 10;
+ if (max_compact_size < 10) max_compact_size = 10;
+
+ // Run unload_units after it's requested `max_cache_size / 10` (default: 10) times.
+ // This throttles the call to mitigate locking in unload_units. It also throttles JIT compaction.
+ int throttle_threshold = mjit_opts.max_cache_size / 10;
+
#ifndef _MSC_VER
if (pch_status == PCH_NOT_READY) {
make_pch();
@@ -1220,11 +1439,47 @@ mjit_worker(void)
while (!stop_worker_p) {
struct rb_mjit_unit *unit;
- // wait until unit is available
+ // Wait until a unit becomes available
CRITICAL_SECTION_START(3, "in worker dequeue");
while ((list_empty(&unit_queue.head) || active_units.length >= mjit_opts.max_cache_size) && !stop_worker_p) {
rb_native_cond_wait(&mjit_worker_wakeup, &mjit_engine_mutex);
verbose(3, "Getting wakeup from client");
+
+ // Lazily move active_units to stale_units to avoid race conditions around active_units with compaction
+ if (pending_stale_p) {
+ pending_stale_p = false;
+ struct rb_mjit_unit *next;
+ list_for_each_safe(&active_units.head, unit, next, unode) {
+ if (unit->stale_p) {
+ unit->stale_p = false;
+ remove_from_list(unit, &active_units);
+ add_to_list(unit, &stale_units);
+ // Lazily put it to unit_queue as well to avoid race conditions on jit_unit with mjit_compile.
+ mjit_add_iseq_to_process(unit->iseq, &unit->iseq->body->jit_unit->compile_info, true);
+ }
+ }
+ }
+
+ // Unload some units as needed
+ if (unload_requests >= throttle_threshold) {
+ while (in_gc) {
+ verbose(3, "Waiting wakeup from GC");
+ rb_native_cond_wait(&mjit_gc_wakeup, &mjit_engine_mutex);
+ }
+ in_jit = true; // Lock GC
+
+ RB_DEBUG_COUNTER_INC(mjit_unload_units);
+ unload_units();
+ unload_requests = 0;
+
+ in_jit = false; // Unlock GC
+ verbose(3, "Sending wakeup signal to client in a mjit-worker for GC");
+ rb_native_cond_signal(&mjit_client_wakeup);
+ }
+ if (active_units.length == mjit_opts.max_cache_size && mjit_opts.wait) { // Sometimes all methods may be in use
+ mjit_opts.max_cache_size++; // avoid infinite loop on `rb_mjit_wait_call`. Note that --jit-wait is just for testing.
+ verbose(1, "No units can be unloaded -- incremented max-cache-size to %d for --jit-wait", mjit_opts.max_cache_size);
+ }
}
unit = get_from_list(&unit_queue);
CRITICAL_SECTION_FINISH(3, "in worker dequeue");
@@ -1251,10 +1506,11 @@ mjit_worker(void)
}
CRITICAL_SECTION_FINISH(3, "in jit func replace");
-#ifndef _MSC_VER
- // Combine .o files to one .so and reload all jit_func to improve memory locality
- if ((!mjit_opts.wait && unit_queue.length == 0 && active_units.length > 1)
- || active_units.length == mjit_opts.max_cache_size) {
+#if USE_JIT_COMPACTION
+ // Combine .o files to one .so and reload all jit_func to improve memory locality.
+ if (compact_units.length < max_compact_size
+ && ((!mjit_opts.wait && unit_queue.length == 0 && active_units.length > 1)
+ || (active_units.length == mjit_opts.max_cache_size && compact_units.length * throttle_threshold <= total_unloads))) { // throttle compaction by total_unloads
compact_all_jit_code();
}
#endif
diff --git a/node.c b/node.c
index 2cdf4c9dda..bef9d7bcbd 100644
--- a/node.c
+++ b/node.c
@@ -9,6 +9,9 @@
**********************************************************************/
+#include "internal.h"
+#include "internal/hash.h"
+#include "internal/variable.h"
#include "ruby/ruby.h"
#include "vm_core.h"
@@ -23,7 +26,7 @@
#define A_ID(id) add_id(buf, (id))
#define A_INT(val) rb_str_catf(buf, "%d", (val))
#define A_LONG(val) rb_str_catf(buf, "%ld", (val))
-#define A_LIT(lit) AR(rb_inspect(lit))
+#define A_LIT(lit) AR(rb_dump_literal(lit))
#define A_NODE_HEADER(node, term) \
rb_str_catf(buf, "@ %s (line: %d, location: (%d,%d)-(%d,%d))%s"term, \
ruby_node_name(nd_type(node)), nd_line(node), \
@@ -60,7 +63,7 @@
#define SIMPLE_FIELD1(name, ann) SIMPLE_FIELD(FIELD_NAME_LEN(name, ann), FIELD_NAME_DESC(name, ann))
#define F_CUSTOM1(name, ann) SIMPLE_FIELD1(#name, ann)
#define F_ID(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name)
-#define F_GENTRY(name, ann) SIMPLE_FIELD1(#name, ann) A_ID((node->name)->id)
+#define F_GENTRY(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name)
#define F_INT(name, ann) SIMPLE_FIELD1(#name, ann) A_INT(node->name)
#define F_LONG(name, ann) SIMPLE_FIELD1(#name, ann) A_LONG(node->name)
#define F_LIT(name, ann) SIMPLE_FIELD1(#name, ann) A_LIT(node->name)
@@ -76,6 +79,25 @@
#define LAST_NODE (next_indent = " ")
+VALUE
+rb_dump_literal(VALUE lit)
+{
+ if (!RB_SPECIAL_CONST_P(lit)) {
+ VALUE str;
+ switch (RB_BUILTIN_TYPE(lit)) {
+ case T_CLASS: case T_MODULE: case T_ICLASS:
+ str = rb_class_path(lit);
+ if (FL_TEST(lit, FL_SINGLETON)) {
+ str = rb_sprintf("<%"PRIsVALUE">", str);
+ }
+ return str;
+ default:
+ break;
+ }
+ }
+ return rb_inspect(lit);
+}
+
static void
add_indent(VALUE buf, VALUE indent)
{
@@ -738,6 +760,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("example: :\"foo#{ bar }baz\"");
dlit:
F_LIT(nd_lit, "preceding string");
+ if (!node->nd_next) return;
F_NODE(nd_next->nd_head, "interpolation");
LAST_NODE;
F_NODE(nd_next->nd_next, "tailing strings");
@@ -1050,6 +1073,27 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
F_NODE(nd_apinfo->post_args, "post arguments");
return;
+ case NODE_FNDPTN:
+ ANN("find pattern");
+ ANN("format: [nd_pconst](*[pre_rest_arg], args, ..., *[post_rest_arg])");
+ F_NODE(nd_pconst, "constant");
+ if (NODE_NAMED_REST_P(node->nd_fpinfo->pre_rest_arg)) {
+ F_NODE(nd_fpinfo->pre_rest_arg, "pre rest argument");
+ }
+ else {
+ F_MSG(nd_fpinfo->pre_rest_arg, "pre rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
+ }
+ F_NODE(nd_fpinfo->args, "arguments");
+
+ LAST_NODE;
+ if (NODE_NAMED_REST_P(node->nd_fpinfo->post_rest_arg)) {
+ F_NODE(nd_fpinfo->post_rest_arg, "post rest argument");
+ }
+ else {
+ F_MSG(nd_fpinfo->post_rest_arg, "post rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
+ }
+ return;
+
case NODE_HSHPTN:
ANN("hash pattern");
ANN("format: [nd_pconst]([nd_pkwargs], ..., **[nd_pkwrestarg])");
@@ -1095,7 +1139,7 @@ void
rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
n->flags = T_NODE;
- nd_set_type(n, type);
+ nd_init_type(n, type);
n->u1.value = a0;
n->u2.value = a1;
n->u3.value = a2;
@@ -1194,10 +1238,10 @@ ast_newnode_in_bucket(node_buffer_list_t *nb)
return &nb->head->buf[nb->idx++];
}
-NODE *
-rb_ast_newnode(rb_ast_t *ast, enum node_type type)
+RBIMPL_ATTR_PURE()
+static bool
+nodetype_markable_p(enum node_type type)
{
- node_buffer_t *nb = ast->node_buffer;
switch (type) {
case NODE_MATCH:
case NODE_LIT:
@@ -1209,9 +1253,29 @@ rb_ast_newnode(rb_ast_t *ast, enum node_type type)
case NODE_DSYM:
case NODE_ARGS:
case NODE_ARYPTN:
- return ast_newnode_in_bucket(&nb->markable);
+ case NODE_FNDPTN:
+ return true;
default:
- return ast_newnode_in_bucket(&nb->unmarkable);
+ return false;
+ }
+}
+
+NODE *
+rb_ast_newnode(rb_ast_t *ast, enum node_type type)
+{
+ node_buffer_t *nb = ast->node_buffer;
+ node_buffer_list_t *bucket =
+ (nodetype_markable_p(type) ? &nb->markable : &nb->unmarkable);
+ return ast_newnode_in_bucket(bucket);
+}
+
+void
+rb_ast_node_type_change(NODE *n, enum node_type type)
+{
+ enum node_type old_type = nd_type(n);
+ if (nodetype_markable_p(old_type) != nodetype_markable_p(type)) {
+ rb_bug("node type changed: %s -> %s",
+ ruby_node_name(old_type), ruby_node_name(type));
}
}
@@ -1269,12 +1333,6 @@ static void
mark_ast_value(void *ctx, NODE * node)
{
switch (nd_type(node)) {
- case NODE_ARYPTN:
- {
- struct rb_ary_pattern_info *apinfo = node->nd_apinfo;
- rb_gc_mark_movable(apinfo->imemo);
- break;
- }
case NODE_ARGS:
{
struct rb_args_info *args = node->nd_ainfo;
@@ -1291,6 +1349,10 @@ mark_ast_value(void *ctx, NODE * node)
case NODE_DSYM:
rb_gc_mark_movable(node->nd_lit);
break;
+ case NODE_ARYPTN:
+ case NODE_FNDPTN:
+ rb_gc_mark_movable(node->nd_rval);
+ break;
default:
rb_bug("unreachable node %s", ruby_node_name(nd_type(node)));
}
@@ -1300,18 +1362,13 @@ static void
update_ast_value(void *ctx, NODE * node)
{
switch (nd_type(node)) {
- case NODE_ARYPTN:
- {
- struct rb_ary_pattern_info *apinfo = node->nd_apinfo;
- apinfo->imemo = rb_gc_location(apinfo->imemo);
- break;
- }
case NODE_ARGS:
{
struct rb_args_info *args = node->nd_ainfo;
args->imemo = rb_gc_location(args->imemo);
break;
}
+ case NODE_MATCH:
case NODE_LIT:
case NODE_STR:
case NODE_XSTR:
@@ -1321,6 +1378,10 @@ update_ast_value(void *ctx, NODE * node)
case NODE_DSYM:
node->nd_lit = rb_gc_location(node->nd_lit);
break;
+ case NODE_ARYPTN:
+ case NODE_FNDPTN:
+ node->nd_rval = rb_gc_location(node->nd_rval);
+ break;
default:
rb_bug("unreachable");
}
diff --git a/node.h b/node.h
index f688f238de..192e121fd7 100644
--- a/node.h
+++ b/node.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_NODE_H
+#define RUBY_NODE_H 1
/**********************************************************************
node.h -
@@ -9,9 +11,6 @@
**********************************************************************/
-#ifndef RUBY_NODE_H
-#define RUBY_NODE_H 1
-
#if defined(__cplusplus)
extern "C" {
#if 0
@@ -124,6 +123,7 @@ enum node_type {
NODE_LAMBDA,
NODE_ARYPTN,
NODE_HSHPTN,
+ NODE_FNDPTN,
NODE_LAST
};
@@ -138,7 +138,7 @@ typedef struct rb_code_location_struct {
} rb_code_location_t;
static inline rb_code_location_t
-code_loc_gen(rb_code_location_t *loc1, rb_code_location_t *loc2)
+code_loc_gen(const rb_code_location_t *loc1, const rb_code_location_t *loc2)
{
rb_code_location_t loc;
loc.beg_pos = loc1->beg_pos;
@@ -164,16 +164,16 @@ typedef struct RNode {
struct RNode *node;
ID id;
long state;
- struct rb_global_entry *entry;
struct rb_args_info *args;
- struct rb_ary_pattern_info *apinfo;
+ struct rb_ary_pattern_info *apinfo;
+ struct rb_fnd_pattern_info *fpinfo;
VALUE value;
} u3;
rb_code_location_t nd_loc;
int node_id;
} NODE;
-#define RNODE(obj) (R_CAST(RNode)(obj))
+#define RNODE(obj) ((struct RNode *)(obj))
/* FL : 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: FINALIZE, 8: UNUSED, 9: UNUSED, 10: EXIVAR, 11: FREEZE */
/* NODE_FL: 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: NODE_FL_NEWLINE,
@@ -187,6 +187,8 @@ typedef struct RNode {
#define nd_type(n) ((int) (((n)->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
#define nd_set_type(n,t) \
+ rb_node_set_type(n, t)
+#define nd_init_type(n,t) \
(n)->flags=(((n)->flags&~NODE_TYPEMASK)|((((unsigned long)(t))<<NODE_TYPESHIFT)&NODE_TYPEMASK))
#define NODE_LSHIFT (NODE_TYPESHIFT+7)
@@ -227,7 +229,7 @@ typedef struct RNode {
#define nd_stts u1.node
-#define nd_entry u3.entry
+#define nd_entry u3.id
#define nd_vid u1.id
#define nd_cflag u2.id
#define nd_cval u3.value
@@ -279,6 +281,8 @@ typedef struct RNode {
#define nd_apinfo u3.apinfo
+#define nd_fpinfo u3.fpinfo
+
#define NEW_NODE(t,a0,a1,a2,loc) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2),loc)
#define NEW_NODE_WITH_LOCALS(t,a1,a2,loc) node_newnode_with_locals(p, (t),(VALUE)(a1),(VALUE)(a2),loc)
@@ -313,7 +317,7 @@ typedef struct RNode {
#define NEW_ZLIST(loc) NEW_NODE(NODE_ZLIST,0,0,0,loc)
#define NEW_HASH(a,loc) NEW_NODE(NODE_HASH,a,0,0,loc)
#define NEW_MASGN(l,r,loc) NEW_NODE(NODE_MASGN,l,0,r,loc)
-#define NEW_GASGN(v,val,loc) NEW_NODE(NODE_GASGN,v,val,rb_global_entry(v),loc)
+#define NEW_GASGN(v,val,loc) NEW_NODE(NODE_GASGN,v,val,v,loc)
#define NEW_LASGN(v,val,loc) NEW_NODE(NODE_LASGN,v,val,0,loc)
#define NEW_DASGN(v,val,loc) NEW_NODE(NODE_DASGN,v,val,0,loc)
#define NEW_DASGN_CURR(v,val,loc) NEW_NODE(NODE_DASGN_CURR,v,val,0,loc)
@@ -326,7 +330,7 @@ typedef struct RNode {
#define NEW_OP_ASGN_OR(i,val,loc) NEW_NODE(NODE_OP_ASGN_OR,i,val,0,loc)
#define NEW_OP_ASGN_AND(i,val,loc) NEW_NODE(NODE_OP_ASGN_AND,i,val,0,loc)
#define NEW_OP_CDECL(v,op,val,loc) NEW_NODE(NODE_OP_CDECL,v,val,op,loc)
-#define NEW_GVAR(v,loc) NEW_NODE(NODE_GVAR,v,0,rb_global_entry(v),loc)
+#define NEW_GVAR(v,loc) NEW_NODE(NODE_GVAR,v,0,v,loc)
#define NEW_LVAR(v,loc) NEW_NODE(NODE_LVAR,v,0,0,loc)
#define NEW_DVAR(v,loc) NEW_NODE(NODE_DVAR,v,0,0,loc)
#define NEW_IVAR(v,loc) NEW_NODE(NODE_IVAR,v,0,0,loc)
@@ -455,7 +459,12 @@ struct rb_ary_pattern_info {
NODE *pre_args;
NODE *rest_arg;
NODE *post_args;
- VALUE imemo;
+};
+
+struct rb_fnd_pattern_info {
+ NODE *pre_rest_arg;
+ NODE *args;
+ NODE *post_rest_arg;
};
struct parser_params;
@@ -464,9 +473,19 @@ void *rb_parser_realloc(struct parser_params *, void *, size_t);
void *rb_parser_calloc(struct parser_params *, size_t, size_t);
void rb_parser_free(struct parser_params *, void *);
PRINTF_ARGS(void rb_parser_printf(struct parser_params *parser, const char *fmt, ...), 2, 3);
+void rb_ast_node_type_change(NODE *n, enum node_type type);
RUBY_SYMBOL_EXPORT_END
+static inline VALUE
+rb_node_set_type(NODE *n, enum node_type t)
+{
+#if RUBY_DEBUG
+ rb_ast_node_type_change(n, t);
+#endif
+ return nd_init_type(n, t);
+}
+
#if defined(__cplusplus)
#if 0
{ /* satisfy cc-mode */
diff --git a/numeric.c b/numeric.c
index ea15625697..691ab77042 100644
--- a/numeric.c
+++ b/numeric.c
@@ -9,10 +9,8 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/util.h"
-#include "internal.h"
-#include "id.h"
+#include "ruby/internal/config.h"
+
#include <assert.h>
#include <ctype.h>
#include <math.h>
@@ -26,13 +24,27 @@
#include <ieeefp.h>
#endif
+#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/compilers.h"
+#include "internal/complex.h"
+#include "internal/enumerator.h"
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/rational.h"
+#include "internal/util.h"
+#include "internal/variable.h"
+#include "ruby/encoding.h"
+#include "ruby/util.h"
+#include "builtin.h"
+
/* use IEEE 64bit values if not defined */
#ifndef FLT_RADIX
#define FLT_RADIX 2
#endif
-#ifndef FLT_ROUNDS
-#define FLT_ROUNDS 1
-#endif
#ifndef DBL_MIN
#define DBL_MIN 2.2250738585072014e-308
#endif
@@ -158,15 +170,11 @@ round_half_even(double x, double s)
return x;
}
-static VALUE fix_uminus(VALUE num);
-static VALUE fix_mul(VALUE x, VALUE y);
static VALUE fix_lshift(long, unsigned long);
static VALUE fix_rshift(long, unsigned long);
static VALUE int_pow(long x, unsigned long y);
-static VALUE int_even_p(VALUE x);
-static int int_round_zero_p(VALUE num, int ndigits);
-VALUE rb_int_floor(VALUE num, int ndigits);
-VALUE rb_int_ceil(VALUE num, int ndigits);
+static VALUE rb_int_floor(VALUE num, int ndigits);
+static VALUE rb_int_ceil(VALUE num, int ndigits);
static VALUE flo_to_i(VALUE num);
static int float_round_overflow(int ndigits, int binexp);
static int float_round_underflow(int ndigits, int binexp);
@@ -181,9 +189,6 @@ static ID id_coerce;
VALUE rb_cNumeric;
VALUE rb_cFloat;
VALUE rb_cInteger;
-#ifndef RUBY_INTEGER_UNIFICATION
-VALUE rb_cFixnum;
-#endif
VALUE rb_eZeroDivError;
VALUE rb_eFloatDomainError;
@@ -219,6 +224,7 @@ rb_num_get_rounding_option(VALUE opts)
str = rb_check_string_type(rounding);
if (NIL_P(str)) goto invalid;
}
+ rb_must_asciicompat(str);
s = RSTRING_PTR(str);
switch (RSTRING_LEN(str)) {
case 2:
@@ -457,19 +463,27 @@ rb_num_coerce_cmp(VALUE x, VALUE y, ID func)
return Qnil;
}
+static VALUE
+ensure_cmp(VALUE c, VALUE x, VALUE y)
+{
+ if (NIL_P(c)) rb_cmperr(x, y);
+ return c;
+}
+
VALUE
rb_num_coerce_relop(VALUE x, VALUE y, ID func)
{
- VALUE c, x0 = x, y0 = y;
+ VALUE x0 = x, y0 = y;
- if (!do_coerce(&x, &y, FALSE) ||
- NIL_P(c = rb_funcall(x, func, 1, y))) {
+ if (!do_coerce(&x, &y, FALSE)) {
rb_cmperr(x0, y0);
- return Qnil; /* not reached */
+ UNREACHABLE_RETURN(Qnil);
}
- return c;
+ return ensure_cmp(rb_funcall(x, func, 1, y), x0, y0);
}
+NORETURN(static VALUE num_sadded(VALUE x, VALUE name));
+
/*
* :nodoc:
*
@@ -758,23 +772,36 @@ num_abs(VALUE num)
static VALUE
num_zero_p(VALUE num)
{
+ if (rb_equal(num, INT2FIX(0))) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
+int_zero_p(VALUE num)
+{
if (FIXNUM_P(num)) {
if (FIXNUM_ZERO_P(num)) {
return Qtrue;
}
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
+ else {
+ assert(RB_TYPE_P(num, T_BIGNUM));
if (rb_bigzero_p(num)) {
/* this should not happen usually */
return Qtrue;
}
}
- else if (rb_equal(num, INT2FIX(0))) {
- return Qtrue;
- }
return Qfalse;
}
+VALUE
+rb_int_zero_p(VALUE num)
+{
+ return int_zero_p(num);
+}
+
/*
* call-seq:
* num.nonzero? -> self or nil
@@ -886,9 +913,9 @@ num_negative_p(VALUE num)
* Floating point has a different arithmetic and is an inexact number.
* So you should know its esoteric system. See following:
*
- * - http://docs.sun.com/source/806-3568/ncg_goldberg.html
+ * - https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
* - https://github.com/rdp/ruby_tutorials_core/wiki/Ruby-Talk-FAQ#floats_imprecise
- * - http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
+ * - https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
*/
VALUE
@@ -897,7 +924,7 @@ rb_float_new_in_heap(double d)
NEWOBJ_OF(flt, struct RFloat, rb_cFloat, T_FLOAT | (RGENGC_WB_PROTECTED_FLOAT ? FL_WB_PROTECTED : 0));
flt->float_value = d;
- OBJ_FREEZE(flt);
+ OBJ_FREEZE((VALUE)flt);
return (VALUE)flt;
}
@@ -966,18 +993,21 @@ flo_to_s(VALUE flt)
memcpy(ptr -= decpt, buf, digs);
}
else {
- exp:
- if (digs > 1) {
- memmove(buf + 2, buf + 1, digs - 1);
- }
- else {
- buf[2] = '0';
- digs++;
- }
- buf[1] = '.';
- rb_str_cat(s, buf, digs + 1);
- rb_str_catf(s, "e%+03d", decpt - 1);
+ goto exp;
+ }
+ return s;
+
+ exp:
+ if (digs > 1) {
+ memmove(buf + 2, buf + 1, digs - 1);
+ }
+ else {
+ buf[2] = '0';
+ digs++;
}
+ buf[1] = '.';
+ rb_str_cat(s, buf, digs + 1);
+ rb_str_catf(s, "e%+03d", decpt - 1);
return s;
}
@@ -1298,7 +1328,11 @@ VALUE
rb_float_pow(VALUE x, VALUE y)
{
double dx, dy;
- if (RB_TYPE_P(y, T_FIXNUM)) {
+ if (y == INT2FIX(2)) {
+ dx = RFLOAT_VALUE(x);
+ return DBL2NUM(dx * dx);
+ }
+ else if (RB_TYPE_P(y, T_FIXNUM)) {
dx = RFLOAT_VALUE(x);
dy = (double)FIX2LONG(y);
}
@@ -1389,7 +1423,7 @@ rb_float_equal(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
@@ -1397,7 +1431,7 @@ rb_float_equal(VALUE x, VALUE y)
return num_equal(x, y);
}
a = RFLOAT_VALUE(x);
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a == b)?Qtrue:Qfalse;
@@ -1424,7 +1458,7 @@ flo_hash(VALUE num)
static VALUE
rb_dbl_hash(double d)
{
- return LONG2FIX(rb_dbl_long_hash(d));
+ return ST2FIX(rb_dbl_long_hash(d));
}
VALUE
@@ -1486,7 +1520,7 @@ flo_cmp(VALUE x, VALUE y)
MJIT_FUNC_EXPORTED int
rb_float_cmp(VALUE x, VALUE y)
{
- return NUM2INT(flo_cmp(x, y));
+ return NUM2INT(ensure_cmp(flo_cmp(x, y), x, y));
}
/*
@@ -1513,14 +1547,14 @@ rb_float_gt(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
else {
return rb_num_coerce_relop(x, y, '>');
}
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a > b)?Qtrue:Qfalse;
@@ -1550,14 +1584,14 @@ flo_ge(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
else {
return rb_num_coerce_relop(x, y, idGE);
}
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a >= b)?Qtrue:Qfalse;
@@ -1587,14 +1621,14 @@ flo_lt(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
else {
return rb_num_coerce_relop(x, y, '<');
}
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a < b)?Qtrue:Qfalse;
@@ -1624,14 +1658,14 @@ flo_le(VALUE x, VALUE y)
}
else if (RB_TYPE_P(y, T_FLOAT)) {
b = RFLOAT_VALUE(y);
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(b)) return Qfalse;
#endif
}
else {
return rb_num_coerce_relop(x, y, idLE);
}
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(a)) return Qfalse;
#endif
return (a <= b)?Qtrue:Qfalse;
@@ -1656,7 +1690,7 @@ rb_float_eql(VALUE x, VALUE y)
if (RB_TYPE_P(y, T_FLOAT)) {
double a = RFLOAT_VALUE(x);
double b = RFLOAT_VALUE(y);
-#if defined(_MSC_VER) && _MSC_VER < 1300
+#if MSC_VERSION_BEFORE(1300)
if (isnan(a) || isnan(b)) return Qfalse;
#endif
if (a == b)
@@ -1782,6 +1816,15 @@ rb_flo_is_finite_p(VALUE num)
return Qtrue;
}
+static VALUE
+flo_nextafter(VALUE flo, double value)
+{
+ double x, y;
+ x = NUM2DBL(flo);
+ y = nextafter(x, value);
+ return DBL2NUM(y);
+}
+
/*
* call-seq:
* float.next_float -> float
@@ -1837,10 +1880,7 @@ rb_flo_is_finite_p(VALUE num)
static VALUE
flo_next_float(VALUE vx)
{
- double x, y;
- x = NUM2DBL(vx);
- y = nextafter(x, HUGE_VAL);
- return DBL2NUM(y);
+ return flo_nextafter(vx, HUGE_VAL);
}
/*
@@ -1888,10 +1928,7 @@ flo_next_float(VALUE vx)
static VALUE
flo_prev_float(VALUE vx)
{
- double x, y;
- x = NUM2DBL(vx);
- y = nextafter(x, -HUGE_VAL);
- return DBL2NUM(y);
+ return flo_nextafter(vx, -HUGE_VAL);
}
VALUE
@@ -2138,7 +2175,7 @@ rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode)
return n;
}
-VALUE
+static VALUE
rb_int_floor(VALUE num, int ndigits)
{
VALUE f;
@@ -2161,7 +2198,7 @@ rb_int_floor(VALUE num, int ndigits)
return rb_int_minus(num, rb_int_modulo(num, f));
}
-VALUE
+static VALUE
rb_int_ceil(VALUE num, int ndigits)
{
VALUE f;
@@ -2583,7 +2620,7 @@ ruby_num_interval_step_size(VALUE from, VALUE to, VALUE step, int excl)
double n = ruby_float_step_size(NUM2DBL(from), NUM2DBL(to), NUM2DBL(step), excl);
if (isinf(n)) return DBL2NUM(n);
- if (POSFIXABLE(n)) return LONG2FIX(n);
+ if (POSFIXABLE(n)) return LONG2FIX((long)n);
return rb_dbl2big(n);
}
else {
@@ -2662,9 +2699,9 @@ num_step_check_fix_args(int argc, VALUE *to, VALUE *step, VALUE by, int fix_nil,
if (argc > 1 && NIL_P(*step)) {
rb_raise(rb_eTypeError, "step must be numeric");
}
- if (!allow_zero_step && rb_equal(*step, INT2FIX(0))) {
- rb_raise(rb_eArgError, "step can't be 0");
- }
+ }
+ if (!allow_zero_step && rb_equal(*step, INT2FIX(0))) {
+ rb_raise(rb_eArgError, "step can't be 0");
}
if (NIL_P(*step)) {
*step = INT2FIX(1);
@@ -2768,6 +2805,9 @@ num_step(int argc, VALUE *argv, VALUE from)
if (NIL_P(step)) {
step = INT2FIX(1);
}
+ else if (rb_equal(step, INT2FIX(0))) {
+ rb_raise(rb_eArgError, "step can't be 0");
+ }
if ((NIL_P(to) || rb_obj_is_kind_of(to, rb_cNumeric)) &&
rb_obj_is_kind_of(step, rb_cNumeric)) {
return rb_arith_seq_new(from, ID2SYM(rb_frame_this_func()), argc, argv,
@@ -2925,7 +2965,6 @@ rb_num2ulong(VALUE val)
return rb_num2ulong_internal(val, NULL);
}
-#if SIZEOF_INT < SIZEOF_LONG
void
rb_out_of_int(SIGNED_VALUE num)
{
@@ -2933,6 +2972,7 @@ rb_out_of_int(SIGNED_VALUE num)
num, num < 0 ? "small" : "big");
}
+#if SIZEOF_INT < SIZEOF_LONG
static void
check_int(long num)
{
@@ -3009,6 +3049,18 @@ rb_fix2int(VALUE val)
{
return FIX2INT(val);
}
+
+unsigned long
+rb_num2uint(VALUE val)
+{
+ return rb_num2ulong(val);
+}
+
+unsigned long
+rb_fix2uint(VALUE val)
+{
+ return RB_FIX2ULONG(val);
+}
#endif
NORETURN(static void rb_out_of_short(SIGNED_VALUE num));
@@ -3187,42 +3239,6 @@ rb_num2ull(VALUE val)
*
*/
-/*
- * call-seq:
- * int.to_i -> integer
- * int.to_int -> integer
- *
- * Since +int+ is already an Integer, returns +self+.
- *
- * #to_int is an alias for #to_i.
- */
-
-static VALUE
-int_to_i(VALUE num)
-{
- return num;
-}
-
-/*
- * call-seq:
- * int.integer? -> true
- *
- * Since +int+ is already an Integer, this always returns +true+.
- */
-
-static VALUE
-int_int_p(VALUE num)
-{
- return Qtrue;
-}
-
-/*
- * call-seq:
- * int.odd? -> true or false
- *
- * Returns +true+ if +int+ is an odd number.
- */
-
VALUE
rb_int_odd_p(VALUE num)
{
@@ -3230,23 +3246,14 @@ rb_int_odd_p(VALUE num)
if (num & 2) {
return Qtrue;
}
+ return Qfalse;
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
+ else {
+ assert(RB_TYPE_P(num, T_BIGNUM));
return rb_big_odd_p(num);
}
- else if (rb_funcall(num, '%', 1, INT2FIX(2)) != INT2FIX(0)) {
- return Qtrue;
- }
- return Qfalse;
}
-/*
- * call-seq:
- * int.even? -> true or false
- *
- * Returns +true+ if +int+ is an even number.
- */
-
static VALUE
int_even_p(VALUE num)
{
@@ -3254,14 +3261,18 @@ int_even_p(VALUE num)
if ((num & 2) == 0) {
return Qtrue;
}
+ return Qfalse;
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
+ else {
+ assert(RB_TYPE_P(num, T_BIGNUM));
return rb_big_even_p(num);
}
- else if (rb_funcall(num, '%', 1, INT2FIX(2)) == INT2FIX(0)) {
- return Qtrue;
- }
- return Qfalse;
+}
+
+VALUE
+rb_int_even_p(VALUE num)
+{
+ return int_even_p(num);
}
/*
@@ -3289,7 +3300,7 @@ static VALUE
int_anybits_p(VALUE num, VALUE mask)
{
mask = rb_to_int(mask);
- return num_zero_p(rb_int_and(num, mask)) ? Qfalse : Qtrue;
+ return int_zero_p(rb_int_and(num, mask)) ? Qfalse : Qtrue;
}
/*
@@ -3303,7 +3314,7 @@ static VALUE
int_nobits_p(VALUE num, VALUE mask)
{
mask = rb_to_int(mask);
- return num_zero_p(rb_int_and(num, mask));
+ return int_zero_p(rb_int_and(num, mask));
}
/*
@@ -3419,7 +3430,7 @@ int_chr(int argc, VALUE *argv, VALUE num)
if (0xff < i) {
enc = rb_default_internal_encoding();
if (!enc) {
- rb_raise(rb_eRangeError, "%d out of char range", i);
+ rb_raise(rb_eRangeError, "%u out of char range", i);
}
goto decode;
}
@@ -3442,38 +3453,9 @@ int_chr(int argc, VALUE *argv, VALUE num)
}
/*
- * call-seq:
- * int.ord -> self
- *
- * Returns the +int+ itself.
- *
- * 97.ord #=> 97
- *
- * This method is intended for compatibility to character literals
- * in Ruby 1.9.
- *
- * For example, <code>?a.ord</code> returns 97 both in 1.8 and 1.9.
- */
-
-static VALUE
-int_ord(VALUE num)
-{
- return num;
-}
-
-/*
* Fixnum
*/
-
-/*
- * Document-method: Integer#-@
- * call-seq:
- * -int -> integer
- *
- * Returns +int+, negated.
- */
-
static VALUE
fix_uminus(VALUE num)
{
@@ -3486,10 +3468,10 @@ rb_int_uminus(VALUE num)
if (FIXNUM_P(num)) {
return fix_uminus(num);
}
- else if (RB_TYPE_P(num, T_BIGNUM)) {
+ else {
+ assert(RB_TYPE_P(num, T_BIGNUM));
return rb_big_uminus(num);
}
- return num_funcall0(num, idUMinus);
}
/*
@@ -4012,13 +3994,7 @@ int_pow(long x, unsigned long y)
do {
while (y % 2 == 0) {
if (!FIT_SQRT_LONG(x)) {
- VALUE v;
- bignum:
- v = rb_big_pow(rb_int2big(x), LONG2NUM(y));
- if (RB_FLOAT_TYPE_P(v)) /* infinity due to overflow */
- return v;
- if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v);
- return v;
+ goto bignum;
}
x = x * x;
y >>= 1;
@@ -4032,6 +4008,14 @@ int_pow(long x, unsigned long y)
} while (--y);
if (neg) z = -z;
return LONG2NUM(z);
+
+ VALUE v;
+ bignum:
+ v = rb_big_pow(rb_int2big(x), LONG2NUM(y));
+ if (RB_FLOAT_TYPE_P(v)) /* infinity due to overflow */
+ return v;
+ if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v);
+ return v;
}
VALUE
@@ -4041,6 +4025,26 @@ rb_int_positive_pow(long x, unsigned long y)
}
static VALUE
+fix_pow_inverted(VALUE x, VALUE minusb)
+{
+ if (x == INT2FIX(0)) {
+ rb_num_zerodiv();
+ UNREACHABLE_RETURN(Qundef);
+ }
+ else {
+ VALUE y = rb_int_pow(x, minusb);
+
+ if (RB_FLOAT_TYPE_P(y)) {
+ double d = pow((double)FIX2LONG(x), RFLOAT_VALUE(y));
+ return DBL2NUM(1.0 / d);
+ }
+ else {
+ return rb_rational_raw(INT2FIX(1), y);
+ }
+ }
+}
+
+static VALUE
fix_pow(VALUE x, VALUE y)
{
long a = FIX2LONG(x);
@@ -4049,42 +4053,17 @@ fix_pow(VALUE x, VALUE y)
long b = FIX2LONG(y);
if (a == 1) return INT2FIX(1);
- if (a == -1) {
- if (b % 2 == 0)
- return INT2FIX(1);
- else
- return INT2FIX(-1);
- }
- if (b < 0) {
- if (a == 0) rb_num_zerodiv();
- y = rb_int_pow(x, LONG2NUM(-b));
- goto inverted;
- }
-
+ if (a == -1) return INT2FIX(b % 2 ? -1 : 1);
+ if (b < 0) return fix_pow_inverted(x, fix_uminus(y));
if (b == 0) return INT2FIX(1);
if (b == 1) return x;
- if (a == 0) {
- if (b > 0) return INT2FIX(0);
- return DBL2NUM(HUGE_VAL);
- }
+ if (a == 0) return INT2FIX(0);
return int_pow(a, b);
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
if (a == 1) return INT2FIX(1);
- if (a == -1) {
- if (int_even_p(y)) return INT2FIX(1);
- else return INT2FIX(-1);
- }
- if (BIGNUM_NEGATIVE_P(y)) {
- if (a == 0) rb_num_zerodiv();
- y = rb_int_pow(x, rb_big_uminus(y));
- inverted:
- if (RB_FLOAT_TYPE_P(y)) {
- double d = pow((double)a, RFLOAT_VALUE(y));
- return DBL2NUM(1.0 / d);
- }
- return rb_rational_raw(INT2FIX(1), y);
- }
+ if (a == -1) return INT2FIX(int_even_p(y) ? 1 : -1);
+ if (BIGNUM_NEGATIVE_P(y)) return fix_pow_inverted(x, rb_big_uminus(y));
if (a == 0) return INT2FIX(0);
x = rb_int2big(FIX2LONG(x));
return rb_big_pow(x, y);
@@ -4096,11 +4075,9 @@ fix_pow(VALUE x, VALUE y)
return DBL2NUM(dy < 0 ? HUGE_VAL : 0.0);
}
if (a == 1) return DBL2NUM(1.0);
- {
- if (a < 0 && dy != round(dy))
- return rb_dbl_complex_new_polar_pi(pow(-(double)a, dy), dy);
- return DBL2NUM(pow((double)a, dy));
- }
+ if (a < 0 && dy != round(dy))
+ return rb_dbl_complex_new_polar_pi(pow(-(double)a, dy), dy);
+ return DBL2NUM(pow((double)a, dy));
}
else {
return rb_num_coerce_bin(x, y, idPow);
@@ -4131,6 +4108,8 @@ rb_num_pow(VALUE x, VALUE y)
return rb_complex_pow(x, y);
case T_RATIONAL:
return rb_rational_pow(x, y);
+ default:
+ break;
}
return Qnil;
}
@@ -4383,29 +4362,14 @@ int_le(VALUE x, VALUE y)
return Qnil;
}
-/*
- * Document-method: Integer#~
- * call-seq:
- * ~int -> integer
- *
- * One's complement: returns a number where each bit is flipped.
- *
- * Inverts the bits in an Integer. As integers are conceptually of
- * infinite length, the result acts as if it had an infinite number of
- * one bits to the left. In hex representations, this is displayed
- * as two periods to the left of the digits.
- *
- * sprintf("%X", ~0x1122334455) #=> "..FEEDDCCBBAA"
- */
-
static VALUE
fix_comp(VALUE num)
{
return ~num | FIXNUM_FLAG;
}
-static VALUE
-int_comp(VALUE num)
+VALUE
+rb_int_comp(VALUE num)
{
if (FIXNUM_P(num)) {
return fix_comp(num);
@@ -4707,7 +4671,7 @@ int_aref1(VALUE num, VALUE arg)
if (!RTEST(num_negative_p(end))) {
if (!excl) end = rb_int_plus(end, INT2FIX(1));
VALUE mask = generate_mask(end);
- if (RTEST(num_zero_p(rb_int_and(num, mask)))) {
+ if (RTEST(int_zero_p(rb_int_and(num, mask)))) {
return INT2FIX(0);
}
else {
@@ -4904,51 +4868,6 @@ int_size(VALUE num)
return Qnil;
}
-/*
- * Document-method: Integer#bit_length
- * call-seq:
- * int.bit_length -> integer
- *
- * Returns the number of bits of the value of +int+.
- *
- * "Number of bits" means the bit position of the highest bit
- * which is different from the sign bit
- * (where the least significant bit has bit position 1).
- * If there is no such bit (zero or minus one), zero is returned.
- *
- * I.e. this method returns <i>ceil(log2(int < 0 ? -int : int+1))</i>.
- *
- * (-2**1000-1).bit_length #=> 1001
- * (-2**1000).bit_length #=> 1000
- * (-2**1000+1).bit_length #=> 1000
- * (-2**12-1).bit_length #=> 13
- * (-2**12).bit_length #=> 12
- * (-2**12+1).bit_length #=> 12
- * -0x101.bit_length #=> 9
- * -0x100.bit_length #=> 8
- * -0xff.bit_length #=> 8
- * -2.bit_length #=> 1
- * -1.bit_length #=> 0
- * 0.bit_length #=> 0
- * 1.bit_length #=> 1
- * 0xff.bit_length #=> 8
- * 0x100.bit_length #=> 9
- * (2**12-1).bit_length #=> 12
- * (2**12).bit_length #=> 13
- * (2**12+1).bit_length #=> 13
- * (2**1000-1).bit_length #=> 1000
- * (2**1000).bit_length #=> 1001
- * (2**1000+1).bit_length #=> 1001
- *
- * This method can be used to detect overflow in Array#pack as follows:
- *
- * if n.bit_length < 32
- * [n].pack("l") # no overflow
- * else
- * raise "overflow"
- * end
- */
-
static VALUE
rb_fix_bit_length(VALUE fix)
{
@@ -4958,7 +4877,7 @@ rb_fix_bit_length(VALUE fix)
return LONG2FIX(bit_length(v));
}
-static VALUE
+VALUE
rb_int_bit_length(VALUE num)
{
if (FIXNUM_P(num)) {
@@ -5118,7 +5037,7 @@ int_upto(VALUE from, VALUE to)
rb_yield(i);
i = rb_funcall(i, '+', 1, INT2FIX(1));
}
- if (NIL_P(c)) rb_cmperr(i, to);
+ ensure_cmp(c, i, to);
}
return from;
}
@@ -5563,16 +5482,13 @@ rb_int_s_isqrt(VALUE self, VALUE num)
void
Init_Numeric(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
#ifdef _UNICOSMP
/* Turn off floating point exceptions for divide by zero, etc. */
_set_Creg(0, 0);
#endif
- id_coerce = rb_intern("coerce");
- id_to = rb_intern("to");
- id_by = rb_intern("by");
+ id_coerce = rb_intern_const("coerce");
+ id_to = rb_intern_const("to");
+ id_by = rb_intern_const("by");
rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
@@ -5621,9 +5537,6 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "to_s", int_to_s, -1);
rb_define_alias(rb_cInteger, "inspect", "to_s");
- rb_define_method(rb_cInteger, "integer?", int_int_p, 0);
- rb_define_method(rb_cInteger, "odd?", rb_int_odd_p, 0);
- rb_define_method(rb_cInteger, "even?", int_even_p, 0);
rb_define_method(rb_cInteger, "allbits?", int_allbits_p, 1);
rb_define_method(rb_cInteger, "anybits?", int_anybits_p, 1);
rb_define_method(rb_cInteger, "nobits?", int_nobits_p, 1);
@@ -5634,9 +5547,6 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "next", int_succ, 0);
rb_define_method(rb_cInteger, "pred", int_pred, 0);
rb_define_method(rb_cInteger, "chr", int_chr, -1);
- rb_define_method(rb_cInteger, "ord", int_ord, 0);
- rb_define_method(rb_cInteger, "to_i", int_to_i, 0);
- rb_define_method(rb_cInteger, "to_int", int_to_i, 0);
rb_define_method(rb_cInteger, "to_f", int_to_f, 0);
rb_define_method(rb_cInteger, "floor", int_floor, -1);
rb_define_method(rb_cInteger, "ceil", int_ceil, -1);
@@ -5644,7 +5554,6 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "round", int_round, -1);
rb_define_method(rb_cInteger, "<=>", rb_int_cmp, 1);
- rb_define_method(rb_cInteger, "-@", rb_int_uminus, 0);
rb_define_method(rb_cInteger, "+", rb_int_plus, 1);
rb_define_method(rb_cInteger, "-", rb_int_minus, 1);
rb_define_method(rb_cInteger, "*", rb_int_mul, 1);
@@ -5659,9 +5568,6 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "pow", rb_int_powm, -1); /* in bignum.c */
- rb_define_method(rb_cInteger, "abs", rb_int_abs, 0);
- rb_define_method(rb_cInteger, "magnitude", rb_int_abs, 0);
-
rb_define_method(rb_cInteger, "===", rb_int_equal, 1);
rb_define_method(rb_cInteger, "==", rb_int_equal, 1);
rb_define_method(rb_cInteger, ">", rb_int_gt, 1);
@@ -5669,7 +5575,6 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, "<", int_lt, 1);
rb_define_method(rb_cInteger, "<=", int_le, 1);
- rb_define_method(rb_cInteger, "~", int_comp, 0);
rb_define_method(rb_cInteger, "&", rb_int_and, 1);
rb_define_method(rb_cInteger, "|", int_or, 1);
rb_define_method(rb_cInteger, "^", int_xor, 1);
@@ -5679,12 +5584,8 @@ Init_Numeric(void)
rb_define_method(rb_cInteger, ">>", rb_int_rshift, 1);
rb_define_method(rb_cInteger, "size", int_size, 0);
- rb_define_method(rb_cInteger, "bit_length", rb_int_bit_length, 0);
rb_define_method(rb_cInteger, "digits", rb_int_digits, -1);
-#ifndef RUBY_INTEGER_UNIFICATION
- rb_cFixnum = rb_cInteger;
-#endif
/* An obsolete class, use Integer */
rb_define_const(rb_cObject, "Fixnum", rb_cInteger);
rb_deprecate_constant(rb_cObject, "Fixnum");
@@ -5695,23 +5596,6 @@ Init_Numeric(void)
rb_undef_method(CLASS_OF(rb_cFloat), "new");
/*
- * Deprecated, do not use.
- *
- * Represents the rounding mode for floating point addition at the start time.
- *
- * Usually defaults to 1, rounding to the nearest number.
- *
- * Other modes include:
- *
- * -1:: Indeterminable
- * 0:: Rounding towards zero
- * 1:: Rounding to the nearest number
- * 2:: Rounding towards positive infinity
- * 3:: Rounding towards negative infinity
- */
- rb_define_const(rb_cFloat, "ROUNDS", INT2FIX(FLT_ROUNDS));
- rb_deprecate_constant(rb_cFloat, "ROUNDS");
- /*
* The base of the floating point, or number of unique digits used to
* represent the number.
*
@@ -5849,3 +5733,5 @@ rb_float_new(double d)
{
return rb_float_new_inline(d);
}
+
+#include "integer.rbinc"
diff --git a/object.c b/object.c
index 61be0d3862..64cf88ae9f 100644
--- a/object.c
+++ b/object.c
@@ -11,18 +11,33 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/st.h"
-#include "ruby/util.h"
-#include "internal.h"
-#include <stdio.h>
-#include <errno.h>
+#include "ruby/internal/config.h"
+
#include <ctype.h>
-#include <math.h>
+#include <errno.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
+
#include "constant.h"
#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/class.h"
+#include "internal/error.h"
+#include "internal/eval.h"
+#include "internal/inits.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/struct.h"
+#include "internal/symbol.h"
+#include "internal/variable.h"
#include "probes.h"
+#include "ruby/encoding.h"
+#include "ruby/st.h"
+#include "ruby/util.h"
+#include "ruby/assert.h"
+#include "builtin.h"
/*!
* \defgroup object Core objects and their operations
@@ -34,7 +49,6 @@ VALUE rb_mKernel; /*!< Kernel module */
VALUE rb_cObject; /*!< Object class */
VALUE rb_cModule; /*!< Module class */
VALUE rb_cClass; /*!< Class class */
-VALUE rb_cData; /*!< Data class */
VALUE rb_cNilClass; /*!< NilClass class */
VALUE rb_cTrueClass; /*!< TrueClass class */
@@ -123,11 +137,22 @@ rb_obj_setup(VALUE obj, VALUE klass, VALUE type)
* Case Equality -- For class Object, effectively the same as calling
* <code>#==</code>, but typically overridden by descendants to provide
* meaningful semantics in +case+ statements.
- *--
- * Same as \c Object#===, case equality.
- *++
*/
+#define case_equal rb_equal
+ /* The default implementation of #=== is
+ * to call #== with the rb_equal() optimization. */
+/*!
+ * This function is an optimized version of calling #==.
+ * It checks equality between two objects by first doing a fast
+ * identity check using using C's == (same as BasicObject#equal?).
+ * If that check fails, it calls #== dynamically.
+ * This optimization actually affects semantics,
+ * because when #== returns false for the same object obj,
+ * rb_equal(obj, obj) would still return true.
+ * This happens for Float::NAN, where Float::NAN == Float::NAN
+ * is false, but rb_equal(Float::NAN, Float::NAN) is true.
+ */
VALUE
rb_equal(VALUE obj1, VALUE obj2)
{
@@ -254,7 +279,7 @@ rb_obj_not_equal(VALUE obj1, VALUE obj2)
* It returns the \a cl itself if it is neither a singleton class or a module.
*
* \param[in] cl a Class object.
- * \return the ancestor class found, or a falsey value if nothing found.
+ * \return the ancestor class found, or Qfalse if nothing found.
*/
VALUE
rb_class_real(VALUE cl)
@@ -266,22 +291,6 @@ rb_class_real(VALUE cl)
return cl;
}
-/**
- * call-seq:
- * obj.class -> class
- *
- * Returns the class of <i>obj</i>. This method must always be called
- * with an explicit receiver, as #class is also a reserved word in
- * Ruby.
- *
- * 1.class #=> Integer
- * self.class #=> Object
- *--
- * Equivalent to \c Object\#class in Ruby.
- *
- * Returns the class of \c obj, skipping singleton classes or module inclusions.
- *++
- */
VALUE
rb_obj_class(VALUE obj)
{
@@ -315,12 +324,8 @@ rb_obj_singleton_class(VALUE obj)
MJIT_FUNC_EXPORTED void
rb_obj_copy_ivar(VALUE dest, VALUE obj)
{
- if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_IVPTR(dest)) {
- xfree(ROBJECT_IVPTR(dest));
- ROBJECT(dest)->as.heap.ivptr = 0;
- ROBJECT(dest)->as.heap.numiv = 0;
- ROBJECT(dest)->as.heap.iv_index_tbl = 0;
- }
+ RUBY_ASSERT(RBASIC(dest)->flags & ROBJECT_EMBED);
+
if (RBASIC(obj)->flags & ROBJECT_EMBED) {
MEMCPY(ROBJECT(dest)->as.ary, ROBJECT(obj)->as.ary, VALUE, ROBJECT_EMBED_LEN_MAX);
RBASIC(dest)->flags |= ROBJECT_EMBED;
@@ -355,9 +360,9 @@ init_copy(VALUE dest, VALUE obj)
}
}
-static int freeze_opt(int argc, VALUE *argv);
-static VALUE immutable_obj_clone(VALUE obj, int kwfreeze);
-static VALUE mutable_obj_clone(VALUE obj, int kwfreeze);
+static VALUE freeze_opt(int argc, VALUE *argv);
+static VALUE immutable_obj_clone(VALUE obj, VALUE kwfreeze);
+static VALUE mutable_obj_clone(VALUE obj, VALUE kwfreeze);
PUREFUNC(static inline int special_object_p(VALUE obj)); /*!< \private */
static inline int
special_object_p(VALUE obj)
@@ -376,35 +381,25 @@ special_object_p(VALUE obj)
}
}
-/*
- * call-seq:
- * obj.clone(freeze: true) -> an_object
- *
- * Produces a shallow copy of <i>obj</i>---the instance variables of
- * <i>obj</i> are copied, but not the objects they reference.
- * #clone copies the frozen (unless +:freeze+ keyword argument is
- * given with a false value) state of <i>obj</i>. See
- * also the discussion under Object#dup.
- *
- * class Klass
- * attr_accessor :str
- * end
- * s1 = Klass.new #=> #<Klass:0x401b3a38>
- * s1.str = "Hello" #=> "Hello"
- * s2 = s1.clone #=> #<Klass:0x401b3998 @str="Hello">
- * s2.str[1,4] = "i" #=> "i"
- * s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
- * s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
- *
- * This method may have class-specific behavior. If so, that
- * behavior will be documented under the #+initialize_copy+ method of
- * the class.
- */
+static VALUE
+obj_freeze_opt(VALUE freeze)
+{
+ switch(freeze) {
+ case Qfalse:
+ case Qtrue:
+ case Qnil:
+ break;
+ default:
+ rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE, rb_obj_class(freeze));
+ }
+
+ return freeze;
+}
static VALUE
-rb_obj_clone2(int argc, VALUE *argv, VALUE obj)
+rb_obj_clone2(rb_execution_context_t *ec, VALUE obj, VALUE freeze)
{
- int kwfreeze = freeze_opt(argc, argv);
+ VALUE kwfreeze = obj_freeze_opt(freeze);
if (!special_object_p(obj))
return mutable_obj_clone(obj, kwfreeze);
return immutable_obj_clone(obj, kwfreeze);
@@ -414,16 +409,16 @@ rb_obj_clone2(int argc, VALUE *argv, VALUE obj)
VALUE
rb_immutable_obj_clone(int argc, VALUE *argv, VALUE obj)
{
- int kwfreeze = freeze_opt(argc, argv);
+ VALUE kwfreeze = freeze_opt(argc, argv);
return immutable_obj_clone(obj, kwfreeze);
}
-static int
+static VALUE
freeze_opt(int argc, VALUE *argv)
{
static ID keyword_ids[1];
VALUE opt;
- VALUE kwfreeze;
+ VALUE kwfreeze = Qnil;
if (!keyword_ids[0]) {
CONST_ID(keyword_ids[0], "freeze");
@@ -431,28 +426,26 @@ freeze_opt(int argc, VALUE *argv)
rb_scan_args(argc, argv, "0:", &opt);
if (!NIL_P(opt)) {
rb_get_kwargs(opt, keyword_ids, 0, 1, &kwfreeze);
- if (kwfreeze == Qfalse) return FALSE;
- if (kwfreeze != Qundef && kwfreeze != Qtrue) {
- rb_raise(rb_eArgError, "unexpected value for freeze: %"PRIsVALUE,
- rb_obj_class(kwfreeze));
- }
+ if (kwfreeze != Qundef)
+ kwfreeze = obj_freeze_opt(kwfreeze);
}
- return TRUE;
+ return kwfreeze;
}
static VALUE
-immutable_obj_clone(VALUE obj, int kwfreeze)
+immutable_obj_clone(VALUE obj, VALUE kwfreeze)
{
- if (!kwfreeze)
+ if (kwfreeze == Qfalse)
rb_raise(rb_eArgError, "can't unfreeze %"PRIsVALUE,
rb_obj_class(obj));
return obj;
}
static VALUE
-mutable_obj_clone(VALUE obj, int kwfreeze)
+mutable_obj_clone(VALUE obj, VALUE kwfreeze)
{
VALUE clone, singleton;
+ VALUE argv[2];
clone = rb_obj_alloc(rb_obj_class(obj));
@@ -463,10 +456,45 @@ mutable_obj_clone(VALUE obj, int kwfreeze)
}
init_copy(clone, obj);
- rb_funcall(clone, id_init_clone, 1, obj);
- if (kwfreeze) {
+ switch (kwfreeze) {
+ case Qnil:
+ rb_funcall(clone, id_init_clone, 1, obj);
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
+ break;
+ case Qtrue:
+ {
+ static VALUE freeze_true_hash;
+ if (!freeze_true_hash) {
+ freeze_true_hash = rb_hash_new();
+ rb_gc_register_mark_object(freeze_true_hash);
+ rb_hash_aset(freeze_true_hash, ID2SYM(rb_intern("freeze")), Qtrue);
+ rb_obj_freeze(freeze_true_hash);
+ }
+
+ argv[0] = obj;
+ argv[1] = freeze_true_hash;
+ rb_funcallv_kw(clone, id_init_clone, 2, argv, RB_PASS_KEYWORDS);
+ RBASIC(clone)->flags |= FL_FREEZE;
+ break;
+ }
+ case Qfalse:
+ {
+ static VALUE freeze_false_hash;
+ if (!freeze_false_hash) {
+ freeze_false_hash = rb_hash_new();
+ rb_gc_register_mark_object(freeze_false_hash);
+ rb_hash_aset(freeze_false_hash, ID2SYM(rb_intern("freeze")), Qfalse);
+ rb_obj_freeze(freeze_false_hash);
+ }
+
+ argv[0] = obj;
+ argv[1] = freeze_false_hash;
+ rb_funcallv_kw(clone, id_init_clone, 2, argv, RB_PASS_KEYWORDS);
+ break;
+ }
+ default:
+ rb_bug("invalid kwfreeze passed to mutable_obj_clone");
}
return clone;
@@ -482,7 +510,7 @@ VALUE
rb_obj_clone(VALUE obj)
{
if (special_object_p(obj)) return obj;
- return mutable_obj_clone(obj, Qtrue);
+ return mutable_obj_clone(obj, Qnil);
}
/**
@@ -518,11 +546,11 @@ rb_obj_clone(VALUE obj)
* s1.extend(Foo) #=> #<Klass:0x401b3a38>
* s1.foo #=> "foo"
*
- * s2 = s1.clone #=> #<Klass:0x401b3a38>
+ * s2 = s1.clone #=> #<Klass:0x401be280>
* s2.foo #=> "foo"
*
- * s3 = s1.dup #=> #<Klass:0x401b3a38>
- * s3.foo #=> NoMethodError: undefined method `foo' for #<Klass:0x401b3a38>
+ * s3 = s1.dup #=> #<Klass:0x401c1084>
+ * s3.foo #=> NoMethodError: undefined method `foo' for #<Klass:0x401c1084>
*--
* Equivalent to \c Object\#dup in Ruby
*++
@@ -559,47 +587,16 @@ rb_obj_itself(VALUE obj)
return obj;
}
-static VALUE
+VALUE
rb_obj_size(VALUE self, VALUE args, VALUE obj)
{
return LONG2FIX(1);
}
-/*
- * call-seq:
- * obj.then {|x| block } -> an_object
- * obj.yield_self {|x| block } -> an_object
- *
- * Yields self to the block and returns the result of the block.
- *
- * 3.next.then {|x| x**x }.to_s #=> "256"
- * "my string".yield_self {|s| s.upcase } #=> "MY STRING"
- *
- * Good usage for +then+ is value piping in method chains:
- *
- * require 'open-uri'
- * require 'json'
- *
- * construct_url(arguments).
- * then {|url| open(url).read }.
- * then {|response| JSON.parse(response) }
- *
- * When called without block, the method returns +Enumerator+,
- * which can be used, for example, for conditional
- * circuit-breaking:
- *
- * # meets condition, no-op
- * 1.then.detect(&:odd?) # => 1
- * # does not meet condition, drop value
- * 2.then.detect(&:odd?) # => nil
- *
- */
-
static VALUE
-rb_obj_yield_self(VALUE obj)
+block_given_p(rb_execution_context_t *ec, VALUE self)
{
- RETURN_SIZED_ENUMERATOR(obj, 0, 0, rb_obj_size);
- return rb_yield_values2(1, &obj);
+ return rb_block_given_p() ? Qtrue : Qfalse;
}
/**
@@ -624,10 +621,10 @@ rb_obj_init_copy(VALUE obj, VALUE orig)
/*!
* :nodoc:
*--
- * Default implementation of \c #initialize_dup and \c #initialize_clone
+ * Default implementation of \c #initialize_dup
*
* \param[in,out] obj the receiver being initialized
- * \param[in] orig the object to be dup or cloned from.
+ * \param[in] orig the object to be dup from.
*++
**/
VALUE
@@ -637,6 +634,27 @@ rb_obj_init_dup_clone(VALUE obj, VALUE orig)
return obj;
}
+/*!
+ * :nodoc:
+ *--
+ * Default implementation of \c #initialize_clone
+ *
+ * \param[in] The number of arguments
+ * \param[in] The array of arguments
+ * \param[in] obj the receiver being initialized
+ *++
+ **/
+static VALUE
+rb_obj_init_clone(int argc, VALUE *argv, VALUE obj)
+{
+ VALUE orig, opts;
+ rb_scan_args(argc, argv, "1:", &orig, &opts);
+ /* Ignore a freeze keyword */
+ if (argc == 2) (void)freeze_opt(1, &opts);
+ rb_funcall(obj, id_init_copy, 1, orig);
+ return obj;
+}
+
/**
* call-seq:
* obj.to_s -> string
@@ -735,7 +753,7 @@ inspect_obj(VALUE obj, VALUE str, int recur)
*
* Returns a string containing a human-readable representation of <i>obj</i>.
* The default #inspect shows the object's class name, an encoding of
- * the object id, and a list of the instance variables and their
+ * its memory address, and a list of the instance variables and their
* values (by calling #inspect on each of them). User defined classes
* should override this method to provide a better representation of
* <i>obj</i>. When overriding this method, it should return a string
@@ -774,15 +792,13 @@ rb_obj_inspect(VALUE obj)
static VALUE
class_or_module_required(VALUE c)
{
- if (SPECIAL_CONST_P(c)) goto not_class;
- switch (BUILTIN_TYPE(c)) {
+ switch (OBJ_BUILTIN_TYPE(c)) {
case T_MODULE:
case T_CLASS:
case T_ICLASS:
break;
default:
- not_class:
rb_raise(rb_eTypeError, "class or module required");
}
return c;
@@ -887,31 +903,6 @@ rb_class_search_ancestor(VALUE cl, VALUE c)
return class_search_ancestor(cl, RCLASS_ORIGIN(c));
}
-/**
- * call-seq:
- * obj.tap {|x| block } -> obj
- *
- * Yields self to the block, and then returns self.
- * The primary purpose of this method is to "tap into" a method chain,
- * in order to perform operations on intermediate results within the chain.
- *
- * (1..10) .tap {|x| puts "original: #{x}" }
- * .to_a .tap {|x| puts "array: #{x}" }
- * .select {|x| x.even? } .tap {|x| puts "evens: #{x}" }
- * .map {|x| x*x } .tap {|x| puts "squares: #{x}" }
- *
- *--
- * \private
- *++
- */
-
-VALUE
-rb_obj_tap(VALUE obj)
-{
- rb_yield(obj);
- return obj;
-}
-
/*
* Document-method: inherited
@@ -1141,7 +1132,7 @@ rb_obj_tap(VALUE obj)
*/
static VALUE
-rb_obj_dummy()
+rb_obj_dummy(void)
{
return Qnil;
}
@@ -1168,7 +1159,7 @@ rb_obj_dummy1(VALUE _x, VALUE _y)
VALUE
rb_obj_tainted(VALUE obj)
{
- rb_warning("Object#tainted? is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("Object#tainted?", "3.2");
return Qfalse;
}
@@ -1182,7 +1173,7 @@ rb_obj_tainted(VALUE obj)
VALUE
rb_obj_taint(VALUE obj)
{
- rb_warning("Object#taint is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("Object#taint", "3.2");
return obj;
}
@@ -1197,7 +1188,7 @@ rb_obj_taint(VALUE obj)
VALUE
rb_obj_untaint(VALUE obj)
{
- rb_warning("Object#untaint is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("Object#untaint", "3.2");
return obj;
}
@@ -1211,7 +1202,7 @@ rb_obj_untaint(VALUE obj)
VALUE
rb_obj_untrusted(VALUE obj)
{
- rb_warning("Object#untrusted? is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("Object#untrusted?", "3.2");
return Qfalse;
}
@@ -1225,7 +1216,7 @@ rb_obj_untrusted(VALUE obj)
VALUE
rb_obj_untrust(VALUE obj)
{
- rb_warning("Object#untrust is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("Object#untrust", "3.2");
return obj;
}
@@ -1240,7 +1231,7 @@ rb_obj_untrust(VALUE obj)
VALUE
rb_obj_trust(VALUE obj)
{
- rb_warning("Object#trust is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("Object#trust", "3.2");
return obj;
}
@@ -1251,7 +1242,7 @@ rb_obj_trust(VALUE obj)
void
rb_obj_infect(VALUE victim, VALUE carrier)
{
- rb_warning("rb_obj_infect is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("rb_obj_infect", "3.2");
}
/**
@@ -1295,23 +1286,6 @@ rb_obj_freeze(VALUE obj)
return obj;
}
-/**
- * call-seq:
- * obj.frozen? -> true or false
- *
- * Returns the freeze status of <i>obj</i>.
- *
- * a = [ "a", "b", "c" ]
- * a.freeze #=> ["a", "b", "c"]
- * a.frozen? #=> true
- *--
- * Determines if the object is frozen. Equivalent to \c Object\#frozen? in Ruby.
- * \param[in] obj the object to be determines
- * \retval Qtrue if frozen
- * \retval Qfalse if not frozen
- *++
- */
-
VALUE
rb_obj_frozen_p(VALUE obj)
{
@@ -1555,13 +1529,7 @@ false_and(VALUE obj, VALUE obj2)
* <code>nil</code> or <code>false</code>; <code>true</code> otherwise.
*/
-static VALUE
-false_or(VALUE obj, VALUE obj2)
-{
- return RTEST(obj2)?Qtrue:Qfalse;
-}
-
-
+#define false_or true_and
/*
* call-seq:
@@ -1574,11 +1542,7 @@ false_or(VALUE obj, VALUE obj2)
*
*/
-static VALUE
-false_xor(VALUE obj, VALUE obj2)
-{
- return RTEST(obj2)?Qtrue:Qfalse;
-}
+#define false_xor true_and
/*
* call-seq:
@@ -1617,15 +1581,15 @@ rb_false(VALUE obj)
*
* This method is deprecated.
*
- * This is not only unuseful but also troublesome because it
- * may hide a type error.
+ * This is not only useless but also troublesome because it may hide a
+ * type error.
*/
static VALUE
rb_obj_match(VALUE obj1, VALUE obj2)
{
if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) {
- rb_warn("deprecated Object#=~ is called on %"PRIsVALUE
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "deprecated Object#=~ is called on %"PRIsVALUE
"; it always returns nil", rb_obj_class(obj1));
}
return Qnil;
@@ -1668,7 +1632,7 @@ rb_obj_not_match(VALUE obj1, VALUE obj2)
static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
{
- if (obj1 == obj2 || rb_equal(obj1, obj2))
+ if (rb_equal(obj1, obj2))
return INT2FIX(0);
return Qnil;
}
@@ -1955,10 +1919,11 @@ rb_mod_initialize(VALUE module)
/* :nodoc: */
static VALUE
-rb_mod_initialize_clone(VALUE clone, VALUE orig)
+rb_mod_initialize_clone(int argc, VALUE* argv, VALUE clone)
{
- VALUE ret;
- ret = rb_obj_init_dup_clone(clone, orig);
+ VALUE ret, orig, opts;
+ rb_scan_args(argc, argv, "1:", &orig, &opts);
+ ret = rb_obj_init_clone(argc, argv, clone);
if (OBJ_FROZEN(orig))
rb_class_name(clone);
return ret;
@@ -2125,13 +2090,6 @@ rb_obj_alloc(VALUE klass)
return rb_class_alloc(klass);
}
-static VALUE
-rb_class_allocate_instance(VALUE klass)
-{
- NEWOBJ_OF(obj, struct RObject, klass, T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 0));
- return (VALUE)obj;
-}
-
/*
* call-seq:
* class.new(args, ...) -> obj
@@ -2143,8 +2101,8 @@ rb_class_allocate_instance(VALUE klass)
*
*/
-static VALUE
-rb_class_s_new(int argc, const VALUE *argv, VALUE klass)
+VALUE
+rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass)
{
VALUE obj;
@@ -2296,37 +2254,42 @@ id_for_attr(VALUE obj, VALUE name)
/*
* call-seq:
- * attr_reader(symbol, ...) -> nil
- * attr(symbol, ...) -> nil
- * attr_reader(string, ...) -> nil
- * attr(string, ...) -> nil
+ * attr_reader(symbol, ...) -> array
+ * attr(symbol, ...) -> array
+ * attr_reader(string, ...) -> array
+ * attr(string, ...) -> array
*
* Creates instance variables and corresponding methods that return the
* value of each instance variable. Equivalent to calling
* ``<code>attr</code><i>:name</i>'' on each name in turn.
* String arguments are converted to symbols.
+ * Returns an array of defined method names as symbols.
*/
static VALUE
rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass)
{
int i;
+ VALUE names = rb_ary_new2(argc);
for (i=0; i<argc; i++) {
- rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, FALSE, TRUE);
+ ID id = id_for_attr(klass, argv[i]);
+ rb_attr(klass, id, TRUE, FALSE, TRUE);
+ rb_ary_push(names, ID2SYM(id));
}
- return Qnil;
+ return names;
}
/**
* call-seq:
- * attr(name, ...) -> nil
- * attr(name, true) -> nil
- * attr(name, false) -> nil
+ * attr(name, ...) -> array
+ * attr(name, true) -> array
+ * attr(name, false) -> array
*
* The first form is equivalent to #attr_reader.
* The second form is equivalent to <code>attr_accessor(name)</code> but deprecated.
* The last form is equivalent to <code>attr_reader(name)</code> but deprecated.
+ * Returns an array of defined method names as symbols.
*--
* \private
* \todo can be static?
@@ -2336,47 +2299,57 @@ VALUE
rb_mod_attr(int argc, VALUE *argv, VALUE klass)
{
if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) {
- rb_warning("optional boolean argument is obsoleted");
- rb_attr(klass, id_for_attr(klass, argv[0]), 1, RTEST(argv[1]), TRUE);
- return Qnil;
+ ID id = id_for_attr(klass, argv[0]);
+ VALUE names = rb_ary_new();
+
+ rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, "optional boolean argument is obsoleted");
+ rb_attr(klass, id, 1, RTEST(argv[1]), TRUE);
+ rb_ary_push(names, ID2SYM(id));
+ if (argv[1] == Qtrue) rb_ary_push(names, ID2SYM(rb_id_attrset(id)));
+ return names;
}
return rb_mod_attr_reader(argc, argv, klass);
}
/*
* call-seq:
- * attr_writer(symbol, ...) -> nil
- * attr_writer(string, ...) -> nil
+ * attr_writer(symbol, ...) -> array
+ * attr_writer(string, ...) -> array
*
* Creates an accessor method to allow assignment to the attribute
* <i>symbol</i><code>.id2name</code>.
* String arguments are converted to symbols.
+ * Returns an array of defined method names as symbols.
*/
static VALUE
rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass)
{
int i;
+ VALUE names = rb_ary_new2(argc);
for (i=0; i<argc; i++) {
- rb_attr(klass, id_for_attr(klass, argv[i]), FALSE, TRUE, TRUE);
+ ID id = id_for_attr(klass, argv[i]);
+ rb_attr(klass, id, FALSE, TRUE, TRUE);
+ rb_ary_push(names, ID2SYM(rb_id_attrset(id)));
}
- return Qnil;
+ return names;
}
/*
* call-seq:
- * attr_accessor(symbol, ...) -> nil
- * attr_accessor(string, ...) -> nil
+ * attr_accessor(symbol, ...) -> array
+ * attr_accessor(string, ...) -> array
*
* Defines a named attribute for this module, where the name is
* <i>symbol.</i><code>id2name</code>, creating an instance variable
* (<code>@name</code>) and a corresponding access method to read it.
* Also creates a method called <code>name=</code> to set the attribute.
* String arguments are converted to symbols.
+ * Returns an array of defined method names as symbols.
*
* module Mod
- * attr_accessor(:one, :two)
+ * attr_accessor(:one, :two) #=> [:one, :one=, :two, :two=]
* end
* Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]
*/
@@ -2385,11 +2358,16 @@ static VALUE
rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass)
{
int i;
+ VALUE names = rb_ary_new2(argc * 2);
for (i=0; i<argc; i++) {
- rb_attr(klass, id_for_attr(klass, argv[i]), TRUE, TRUE, TRUE);
+ ID id = id_for_attr(klass, argv[i]);
+
+ rb_attr(klass, id, TRUE, TRUE, TRUE);
+ rb_ary_push(names, ID2SYM(id));
+ rb_ary_push(names, ID2SYM(rb_id_attrset(id)));
}
- return Qnil;
+ return names;
}
/*
@@ -2462,8 +2440,7 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod)
pend = path + RSTRING_LEN(name);
if (p >= pend || !*p) {
- wrong_name:
- rb_name_err_raise(wrong_constant_name, mod, name);
+ goto wrong_name;
}
if (p + 2 < pend && p[0] == ':' && p[1] == ':') {
@@ -2530,6 +2507,10 @@ rb_mod_const_get(int argc, VALUE *argv, VALUE mod)
}
return mod;
+
+ wrong_name:
+ rb_name_err_raise(wrong_constant_name, mod, name);
+ UNREACHABLE_RETURN(Qundef);
}
/*
@@ -2632,8 +2613,7 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
pend = path + RSTRING_LEN(name);
if (p >= pend || !*p) {
- wrong_name:
- rb_name_err_raise(wrong_constant_name, mod, name);
+ goto wrong_name;
}
if (p + 2 < pend && p[0] == ':' && p[1] == ':') {
@@ -2706,6 +2686,10 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
}
return Qtrue;
+
+ wrong_name:
+ rb_name_err_raise(wrong_constant_name, mod, name);
+ UNREACHABLE_RETURN(Qundef);
}
/*
@@ -2713,8 +2697,8 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
* mod.const_source_location(sym, inherit=true) -> [String, Integer]
* mod.const_source_location(str, inherit=true) -> [String, Integer]
*
- * Returns the Ruby source filename and line number containing first definition
- * of constant specified. If the named constant is not found, +nil+ is returned.
+ * Returns the Ruby source filename and line number containing the definition
+ * of the constant specified. If the named constant is not found, +nil+ is returned.
* If the constant is found, but its source location can not be extracted
* (constant is defined in C code), empty array is returned.
*
@@ -2722,30 +2706,34 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
* by default).
*
* # test.rb:
- * class A
+ * class A # line 1
* C1 = 1
+ * C2 = 2
* end
*
- * module M
- * C2 = 2
+ * module M # line 6
+ * C3 = 3
* end
*
- * class B < A
+ * class B < A # line 10
* include M
- * C3 = 3
+ * C4 = 4
* end
*
* class A # continuation of A definition
+ * C2 = 8 # constant redefinition; warned yet allowed
* end
*
- * p B.const_source_location('C3') # => ["test.rb", 11]
- * p B.const_source_location('C2') # => ["test.rb", 6]
+ * p B.const_source_location('C4') # => ["test.rb", 12]
+ * p B.const_source_location('C3') # => ["test.rb", 7]
* p B.const_source_location('C1') # => ["test.rb", 2]
*
- * p B.const_source_location('C2', false) # => nil -- don't lookup in ancestors
+ * p B.const_source_location('C3', false) # => nil -- don't lookup in ancestors
+ *
+ * p A.const_source_location('C2') # => ["test.rb", 16] -- actual (last) definition place
*
- * p Object.const_source_location('B') # => ["test.rb", 9]
- * p Object.const_source_location('A') # => ["test.rb", 1] -- note it is first entry, not "continuation"
+ * p Object.const_source_location('B') # => ["test.rb", 10] -- top-level constant could be looked through Object
+ * p Object.const_source_location('A') # => ["test.rb", 1] -- class reopening is NOT considered new definition
*
* p B.const_source_location('A') # => ["test.rb", 1] -- because Object is in ancestors
* p M.const_source_location('A') # => ["test.rb", 1] -- Object is not ancestor, but additionally checked for modules
@@ -2785,8 +2773,7 @@ rb_mod_const_source_location(int argc, VALUE *argv, VALUE mod)
pend = path + RSTRING_LEN(name);
if (p >= pend || !*p) {
- wrong_name:
- rb_name_err_raise(wrong_constant_name, mod, name);
+ goto wrong_name;
}
if (p + 2 < pend && p[0] == ':' && p[1] == ':') {
@@ -2852,6 +2839,10 @@ rb_mod_const_source_location(int argc, VALUE *argv, VALUE mod)
}
return loc;
+
+ wrong_name:
+ rb_name_err_raise(wrong_constant_name, mod, name);
+ UNREACHABLE_RETURN(Qundef);
}
/*
@@ -2893,9 +2884,9 @@ rb_obj_ivar_get(VALUE obj, VALUE iv)
* obj.instance_variable_set(string, obj) -> obj
*
* Sets the instance variable named by <i>symbol</i> to the given
- * object, thereby frustrating the efforts of the class's
- * author to attempt to provide proper encapsulation. The variable
- * does not have to exist prior to this call.
+ * object. This may circumvent the encapsulation intended by
+ * the author of the class, so it should be used with care.
+ * The variable does not have to exist prior to this call.
* If the instance variable name is passed as a string, that string
* is converted to a symbol.
*
@@ -3310,33 +3301,35 @@ rb_convert_to_integer(VALUE val, int base, int raise_exception)
{
VALUE tmp;
+ if (base) {
+ tmp = rb_check_string_type(val);
+
+ if (! NIL_P(tmp)) {
+ val = tmp;
+ }
+ else if (! raise_exception) {
+ return Qnil;
+ }
+ else {
+ rb_raise(rb_eArgError, "base specified for non string value");
+ }
+ }
if (RB_FLOAT_TYPE_P(val)) {
- double f;
- if (base != 0) goto arg_error;
- f = RFLOAT_VALUE(val);
+ double f = RFLOAT_VALUE(val);
if (!raise_exception && !isfinite(f)) return Qnil;
if (FIXABLE(f)) return LONG2FIX((long)f);
return rb_dbl2big(f);
}
else if (RB_INTEGER_TYPE_P(val)) {
- if (base != 0) goto arg_error;
return val;
}
else if (RB_TYPE_P(val, T_STRING)) {
return rb_str_convert_to_inum(val, base, TRUE, raise_exception);
}
else if (NIL_P(val)) {
- if (base != 0) goto arg_error;
if (!raise_exception) return Qnil;
rb_raise(rb_eTypeError, "can't convert nil into Integer");
}
- if (base != 0) {
- tmp = rb_check_string_type(val);
- if (!NIL_P(tmp)) return rb_str_convert_to_inum(tmp, base, TRUE, raise_exception);
- arg_error:
- if (!raise_exception) return Qnil;
- rb_raise(rb_eArgError, "base specified for non string value");
- }
tmp = rb_protect(rb_check_to_int, val, NULL);
if (RB_INTEGER_TYPE_P(tmp)) return tmp;
@@ -3398,8 +3391,9 @@ rb_opts_exception_p(VALUE opts, int default_value)
* integer string representation. If <i>arg</i> is a String,
* when <i>base</i> is omitted or equals zero, radix indicators
* (<code>0</code>, <code>0b</code>, and <code>0x</code>) are honored.
- * In any case, strings should be strictly conformed to numeric
- * representation. This behavior is different from that of
+ * In any case, strings should consist only of one or more digits, except
+ * for that a sign, one underscore between two digits, and leading/trailing
+ * spaces are optional. This behavior is different from that of
* String#to_i. Non string values will be converted by first
* trying <code>to_int</code>, then <code>to_i</code>.
*
@@ -3413,6 +3407,7 @@ rb_opts_exception_p(VALUE opts, int default_value)
* Integer(Time.new) #=> 1204973019
* Integer("0930", 10) #=> 930
* Integer("111", 2) #=> 7
+ * Integer(" +1_0 ") #=> 10
* Integer(nil) #=> TypeError: can't convert nil into Integer
* Integer("x") #=> ArgumentError: invalid value for Integer(): "x"
*
@@ -3476,13 +3471,7 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
}
if (p == end) {
if (badcheck) {
- bad:
- if (raise)
- rb_invalid_str(q, "Float()");
- else {
- if (error) *error = 1;
- return 0.0;
- }
+ goto bad;
}
return d;
}
@@ -3557,6 +3546,16 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
rb_raise(rb_eArgError, "Float %.*s%s out of range", w, q, ellipsis);
}
return d;
+
+ bad:
+ if (raise) {
+ rb_invalid_str(q, "Float()");
+ UNREACHABLE_RETURN(nan(""));
+ }
+ else {
+ if (error) *error = 1;
+ return 0.0;
+ }
}
/*!
@@ -3750,32 +3749,11 @@ rb_Float(VALUE val)
return rb_convert_to_float(val, TRUE);
}
-/*
- * call-seq:
- * Float(arg, exception: true) -> float or nil
- *
- * 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
- * suppressed by passing <code>exception: false</code>.
- *
- * Float(1) #=> 1.0
- * Float("123.456") #=> 123.456
- * Float("123.0_badstring") #=> ArgumentError: invalid value for Float(): "123.0_badstring"
- * Float(nil) #=> TypeError: can't convert nil into Float
- * Float("123.0_badstring", exception: false) #=> nil
- */
-
static VALUE
-rb_f_float(int argc, VALUE *argv, VALUE obj)
+rb_f_float(rb_execution_context_t *ec, VALUE obj, VALUE arg, VALUE opts)
{
- VALUE arg = Qnil, opts = Qnil;
-
- rb_scan_args(argc, argv, "1:", &arg, &opts);
- return rb_convert_to_float(arg, opts_exception_p(opts));
+ int exception = rb_bool_expected(opts, "exception");
+ return rb_convert_to_float(arg, exception);
}
static VALUE
@@ -3854,6 +3832,8 @@ rb_num_to_dbl(VALUE val)
if (basic_to_f_p(rb_cRational))
return rat2dbl_without_to_f(val);
break;
+ default:
+ break;
}
}
val = numeric_to_float(val);
@@ -3891,6 +3871,8 @@ rb_num2dbl(VALUE val)
return rat2dbl_without_to_f(val);
case T_STRING:
rb_raise(rb_eTypeError, "no implicit conversion to float from string");
+ default:
+ break;
}
}
val = rb_convert_type_with_id(val, T_FLOAT, "Float", id_to_f);
@@ -4069,13 +4051,13 @@ rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound)
continue;
}
break;
+ default:
+ break;
}
}
return rb_check_funcall_with_hook_kw(obj, id_dig, argc, argv,
no_dig_method, obj,
- rb_empty_keyword_given_p() ?
- RB_PASS_EMPTY_KEYWORDS :
- RB_NO_KEYWORDS);
+ RB_NO_KEYWORDS);
}
return obj;
}
@@ -4515,9 +4497,6 @@ InitVM_Object(void)
rb_cClass = rb_define_class("Class", rb_cModule);
#endif
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy0, 0);
rb_define_alloc_func(rb_cBasicObject, rb_class_allocate_instance);
rb_define_method(rb_cBasicObject, "==", rb_obj_equal, 1);
@@ -4552,23 +4531,19 @@ InitVM_Object(void)
rb_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy1, 1);
rb_define_method(rb_mKernel, "nil?", rb_false, 0);
- rb_define_method(rb_mKernel, "===", rb_equal, 1);
+ rb_define_method(rb_mKernel, "===", case_equal, 1);
rb_define_method(rb_mKernel, "=~", rb_obj_match, 1);
rb_define_method(rb_mKernel, "!~", rb_obj_not_match, 1);
rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
rb_define_method(rb_mKernel, "hash", rb_obj_hash, 0); /* in hash.c */
rb_define_method(rb_mKernel, "<=>", rb_obj_cmp, 1);
- rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
rb_define_method(rb_mKernel, "singleton_class", rb_obj_singleton_class, 0);
- rb_define_method(rb_mKernel, "clone", rb_obj_clone2, -1);
rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
rb_define_method(rb_mKernel, "itself", rb_obj_itself, 0);
- rb_define_method(rb_mKernel, "yield_self", rb_obj_yield_self, 0);
- rb_define_method(rb_mKernel, "then", rb_obj_yield_self, 0);
rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
rb_define_method(rb_mKernel, "initialize_dup", rb_obj_init_dup_clone, 1);
- rb_define_method(rb_mKernel, "initialize_clone", rb_obj_init_dup_clone, 1);
+ rb_define_method(rb_mKernel, "initialize_clone", rb_obj_init_clone, -1);
rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
@@ -4577,7 +4552,6 @@ InitVM_Object(void)
rb_define_method(rb_mKernel, "untrusted?", rb_obj_untrusted, 0);
rb_define_method(rb_mKernel, "trust", rb_obj_trust, 0);
rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0);
- rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0);
rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);
rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
@@ -4596,13 +4570,11 @@ InitVM_Object(void)
rb_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of, 1);
rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
- rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0);
rb_define_global_function("sprintf", f_sprintf, -1);
rb_define_global_function("format", f_sprintf, -1);
rb_define_global_function("Integer", rb_f_integer, -1);
- rb_define_global_function("Float", rb_f_float, -1);
rb_define_global_function("String", rb_f_string, 1);
rb_define_global_function("Array", rb_f_array, 1);
@@ -4621,16 +4593,11 @@ InitVM_Object(void)
rb_define_method(rb_cNilClass, "&", false_and, 1);
rb_define_method(rb_cNilClass, "|", false_or, 1);
rb_define_method(rb_cNilClass, "^", false_xor, 1);
- rb_define_method(rb_cNilClass, "===", rb_equal, 1);
+ rb_define_method(rb_cNilClass, "===", case_equal, 1);
rb_define_method(rb_cNilClass, "nil?", rb_true, 0);
rb_undef_alloc_func(rb_cNilClass);
rb_undef_method(CLASS_OF(rb_cNilClass), "new");
- /*
- * An obsolete alias of +nil+
- */
- rb_define_global_const("NIL", Qnil);
- rb_deprecate_constant(rb_cObject, "NIL");
rb_define_method(rb_cModule, "freeze", rb_mod_freeze, 0);
rb_define_method(rb_cModule, "===", rb_mod_eqq, 1);
@@ -4655,7 +4622,7 @@ InitVM_Object(void)
rb_define_alloc_func(rb_cModule, rb_module_s_alloc);
rb_define_method(rb_cModule, "initialize", rb_mod_initialize, 0);
- rb_define_method(rb_cModule, "initialize_clone", rb_mod_initialize_clone, 1);
+ rb_define_method(rb_cModule, "initialize_clone", rb_mod_initialize_clone, -1);
rb_define_method(rb_cModule, "instance_methods", rb_class_instance_methods, -1); /* in class.c */
rb_define_method(rb_cModule, "public_instance_methods",
rb_class_public_instance_methods, -1); /* in class.c */
@@ -4686,7 +4653,7 @@ InitVM_Object(void)
rb_define_method(rb_cModule, "singleton_class?", rb_mod_singleton_p, 0);
rb_define_method(rb_cClass, "allocate", rb_class_alloc_m, 0);
- rb_define_method(rb_cClass, "new", rb_class_s_new, -1);
+ rb_define_method(rb_cClass, "new", rb_class_new_instance_pass_kw, -1);
rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1);
rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
rb_define_alloc_func(rb_cClass, rb_class_s_alloc);
@@ -4694,16 +4661,6 @@ InitVM_Object(void)
rb_undef_method(rb_cClass, "append_features");
rb_undef_method(rb_cClass, "prepend_features");
- /*
- * Document-class: Data
- *
- * This is a deprecated class, base class for C extensions using
- * Data_Make_Struct or Data_Wrap_Struct.
- */
- rb_cData = rb_define_class("Data", rb_cObject);
- rb_undef_alloc_func(rb_cData);
- rb_deprecate_constant(rb_cObject, "Data");
-
rb_cTrueClass = rb_define_class("TrueClass", rb_cObject);
rb_cTrueClass_to_s = rb_fstring_enc_lit("true", rb_usascii_encoding());
rb_gc_register_mark_object(rb_cTrueClass_to_s);
@@ -4712,14 +4669,9 @@ InitVM_Object(void)
rb_define_method(rb_cTrueClass, "&", true_and, 1);
rb_define_method(rb_cTrueClass, "|", true_or, 1);
rb_define_method(rb_cTrueClass, "^", true_xor, 1);
- rb_define_method(rb_cTrueClass, "===", rb_equal, 1);
+ rb_define_method(rb_cTrueClass, "===", case_equal, 1);
rb_undef_alloc_func(rb_cTrueClass);
rb_undef_method(CLASS_OF(rb_cTrueClass), "new");
- /*
- * An obsolete alias of +true+
- */
- rb_define_global_const("TRUE", Qtrue);
- rb_deprecate_constant(rb_cObject, "TRUE");
rb_cFalseClass = rb_define_class("FalseClass", rb_cObject);
rb_cFalseClass_to_s = rb_fstring_enc_lit("false", rb_usascii_encoding());
@@ -4729,16 +4681,13 @@ InitVM_Object(void)
rb_define_method(rb_cFalseClass, "&", false_and, 1);
rb_define_method(rb_cFalseClass, "|", false_or, 1);
rb_define_method(rb_cFalseClass, "^", false_xor, 1);
- rb_define_method(rb_cFalseClass, "===", rb_equal, 1);
+ rb_define_method(rb_cFalseClass, "===", case_equal, 1);
rb_undef_alloc_func(rb_cFalseClass);
rb_undef_method(CLASS_OF(rb_cFalseClass), "new");
- /*
- * An obsolete alias of +false+
- */
- rb_define_global_const("FALSE", Qfalse);
- rb_deprecate_constant(rb_cObject, "FALSE");
}
+#include "kernel.rbinc"
+
void
Init_Object(void)
{
diff --git a/pack.c b/pack.c
index ae5a9a18e2..9fecc31a34 100644
--- a/pack.c
+++ b/pack.c
@@ -9,12 +9,21 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "internal.h"
-#include <sys/types.h>
+#include "ruby/internal/config.h"
+
#include <ctype.h>
#include <errno.h>
#include <float.h>
+#include <sys/types.h>
+
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/bits.h"
+#include "internal/string.h"
+#include "internal/symbol.h"
+#include "internal/util.h"
+#include "internal/variable.h"
+
#include "builtin.h"
/*
@@ -1759,7 +1768,5 @@ utf8_to_uv(const char *p, long *lenp)
void
Init_pack(void)
{
- load_pack();
-
id_associated = rb_make_internal_id();
}
diff --git a/pack.rb b/pack.rb
index 3f921a93dd..a4723861d5 100644
--- a/pack.rb
+++ b/pack.rb
@@ -131,7 +131,7 @@ class Array
# X | --- | back up a byte
# x | --- | null byte
def pack(fmt, buffer: nil)
- __builtin_pack_pack(fmt, buffer)
+ Primitive.pack_pack(fmt, buffer)
end
end
@@ -212,7 +212,7 @@ class String
# V | Integer | 32-bit unsigned, VAX (little-endian) byte order
# | |
# U | Integer | UTF-8 character
- # w | Integer | BER-compressed integer (see Array.pack)
+ # w | Integer | BER-compressed integer (see Array#pack)
#
# Float | |
# Directive | Returns | Meaning
@@ -254,7 +254,7 @@ class String
# * Q_, Q!, q_, and q! are available since Ruby 2.1.
# * I!<, i!<, I!>, and i!> are available since Ruby 1.9.3.
def unpack(fmt)
- __builtin_pack_unpack(fmt)
+ Primitive.pack_unpack(fmt)
end
# call-seq:
@@ -278,6 +278,6 @@ class String
# Thus unpack1 is convenient, makes clear the intention and signals
# the expected return value to those reading the code.
def unpack1(fmt)
- __builtin_pack_unpack1(fmt)
+ Primitive.pack_unpack1(fmt)
end
end
diff --git a/parse.y b/parse.y
index 2bf825a052..3bc3748dd5 100644
--- a/parse.y
+++ b/parse.y
@@ -20,18 +20,61 @@
#define YYLTYPE rb_code_location_t
#define YYLTYPE_IS_DECLARED 1
-#include "ruby/ruby.h"
-#include "ruby/st.h"
-#include "ruby/encoding.h"
+#include "ruby/internal/config.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+
+struct lex_context;
+
#include "internal.h"
+#include "internal/compile.h"
+#include "internal/compilers.h"
+#include "internal/complex.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/imemo.h"
+#include "internal/io.h"
+#include "internal/numeric.h"
+#include "internal/parse.h"
+#include "internal/rational.h"
+#include "internal/re.h"
+#include "internal/symbol.h"
+#include "internal/thread.h"
+#include "internal/util.h"
+#include "internal/variable.h"
#include "node.h"
-#include "parse.h"
-#include "symbol.h"
-#include "regenc.h"
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
#include "probes.h"
+#include "regenc.h"
+#include "ruby/encoding.h"
+#include "ruby/regex.h"
+#include "ruby/ruby.h"
+#include "ruby/st.h"
+#include "ruby/util.h"
+#include "ruby/ractor.h"
+#include "symbol.h"
+
+enum shareability {
+ shareable_none,
+ shareable_literal,
+ shareable_copy,
+ shareable_everything,
+};
+
+struct lex_context {
+ unsigned int in_defined: 1;
+ unsigned int in_kwarg: 1;
+ unsigned int in_def: 1;
+ unsigned int in_class: 1;
+ BITFIELD(enum shareability, shareable_constant_value, 2);
+};
+
+#include "parse.h"
+
+#define NO_LEX_CTXT (struct lex_context){0}
+
+#define AREF(ary, i) RARRAY_AREF(ary, i)
#ifndef WARN_PAST_SCOPE
# define WARN_PAST_SCOPE 0
@@ -46,7 +89,6 @@
#define YYCALLOC(nelem, size) rb_parser_calloc(p, (nelem), (size))
#define YYFREE(ptr) rb_parser_free(p, (ptr))
#define YYFPRINTF rb_parser_printf
-#define YYPRINT(out, tok, val) parser_token_value_print(p, (tok), &(val))
#define YY_LOCATION_PRINT(File, loc) \
rb_parser_printf(p, "%d.%d-%d.%d", \
(loc).beg_pos.lineno, (loc).beg_pos.column,\
@@ -272,15 +314,13 @@ struct parser_params {
int max_numparam;
+ struct lex_context ctxt;
+
unsigned int command_start:1;
unsigned int eofp: 1;
unsigned int ruby__end__seen: 1;
unsigned int debug: 1;
unsigned int has_shebang: 1;
- unsigned int in_defined: 1;
- unsigned int in_kwarg: 1;
- unsigned int in_def: 1;
- unsigned int in_class: 1;
unsigned int token_seen: 1;
unsigned int token_info_enabled: 1;
# if WARN_PAST_SCOPE
@@ -296,7 +336,6 @@ struct parser_params {
unsigned int do_loop: 1;
unsigned int do_chomp: 1;
unsigned int do_split: 1;
- unsigned int warn_location: 1;
NODE *eval_tree_begin;
NODE *eval_tree;
@@ -362,6 +401,12 @@ static int parser_yyerror(struct parser_params*, const YYLTYPE *yylloc, const ch
#define yyerror(yylloc, p, msg) parser_yyerror(p, yylloc, msg)
#define token_flush(ptr) ((ptr)->lex.ptok = (ptr)->lex.pcur)
+static void token_info_setup(token_info *ptinfo, const char *ptr, const rb_code_location_t *loc);
+static void token_info_push(struct parser_params*, const char *token, const rb_code_location_t *loc);
+static void token_info_pop(struct parser_params*, const char *token, const rb_code_location_t *loc);
+static void token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, int same, const rb_code_location_t *loc);
+static void token_info_drop(struct parser_params *p, const char *token, rb_code_position_t beg_pos);
+
#ifdef RIPPER
#define compile_for_eval (0)
#else
@@ -431,6 +476,7 @@ set_line_body(NODE *body, int line)
static NODE* cond(struct parser_params *p, NODE *node, const YYLTYPE *loc);
static NODE* method_cond(struct parser_params *p, NODE *node, const YYLTYPE *loc);
#define new_nil(loc) NEW_NIL(loc)
+static NODE *new_nil_at(struct parser_params *p, const rb_code_position_t *pos);
static NODE *new_if(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*);
static NODE *new_unless(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*);
static NODE *logop(struct parser_params*,ID,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*);
@@ -442,7 +488,7 @@ static int value_expr_gen(struct parser_params*,NODE*);
static void void_expr(struct parser_params*,NODE*);
static NODE *remove_begin(NODE*);
static NODE *remove_begin_all(NODE*);
-#define value_expr(node) value_expr_gen(p, (node) = remove_begin(node))
+#define value_expr(node) value_expr_gen(p, (node))
static NODE *void_stmts(struct parser_params*,NODE*);
static void reduce_nodes(struct parser_params*,NODE**);
static void block_dup_check(struct parser_params*,NODE*,NODE*);
@@ -455,6 +501,7 @@ static NODE *last_arg_append(struct parser_params *p, NODE *args, NODE *last_arg
static NODE *rest_arg_append(struct parser_params *p, NODE *args, NODE *rest_arg, const YYLTYPE *loc);
static NODE *literal_concat(struct parser_params*,NODE*,NODE*,const YYLTYPE*);
static NODE *new_evstr(struct parser_params*,NODE*,const YYLTYPE*);
+static NODE *new_dstr(struct parser_params*,NODE*,const YYLTYPE*);
static NODE *evstr2dstr(struct parser_params*,NODE*);
static NODE *splat_array(NODE*);
static void mark_lvar_used(struct parser_params *p, NODE *rhs);
@@ -470,9 +517,11 @@ static NODE *new_args(struct parser_params*,NODE*,NODE*,ID,NODE*,NODE*,const YYL
static NODE *new_args_tail(struct parser_params*,NODE*,ID,ID,const YYLTYPE*);
static NODE *new_array_pattern(struct parser_params *p, NODE *constant, NODE *pre_arg, NODE *aryptn, const YYLTYPE *loc);
static NODE *new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID rest_arg, NODE *post_args, const YYLTYPE *loc);
+static NODE *new_find_pattern(struct parser_params *p, NODE *constant, NODE *fndptn, const YYLTYPE *loc);
+static NODE *new_find_pattern_tail(struct parser_params *p, ID pre_rest_arg, NODE *args, ID post_rest_arg, const YYLTYPE *loc);
static NODE *new_hash_pattern(struct parser_params *p, NODE *constant, NODE *hshptn, const YYLTYPE *loc);
static NODE *new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, const YYLTYPE *loc);
-static NODE *new_case3(struct parser_params *p, NODE *val, NODE *pat, const YYLTYPE *loc);
+static void warn_one_line_pattern_matching(struct parser_params *p, NODE *node, NODE *pattern, bool right_assign);
static NODE *new_kw_arg(struct parser_params *p, NODE *k, const YYLTYPE *loc);
static NODE *args_with_numbered(struct parser_params*,NODE*,int);
@@ -490,12 +539,12 @@ static NODE *aryset(struct parser_params*,NODE*,NODE*,const YYLTYPE*);
static NODE *attrset(struct parser_params*,NODE*,ID,ID,const YYLTYPE*);
static void rb_backref_error(struct parser_params*,NODE*);
-static NODE *node_assign(struct parser_params*,NODE*,NODE*,const YYLTYPE*);
+static NODE *node_assign(struct parser_params*,NODE*,NODE*,struct lex_context,const YYLTYPE*);
-static NODE *new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYPE *loc);
+static NODE *new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context, const YYLTYPE *loc);
static NODE *new_ary_op_assign(struct parser_params *p, NODE *ary, NODE *args, ID op, NODE *rhs, const YYLTYPE *args_loc, const YYLTYPE *loc);
static NODE *new_attr_op_assign(struct parser_params *p, NODE *lhs, ID atype, ID attr, ID op, NODE *rhs, const YYLTYPE *loc);
-static NODE *new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYPE *loc);
+static NODE *new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context, const YYLTYPE *loc);
static NODE *new_bodystmt(struct parser_params *p, NODE *head, NODE *rescue, NODE *rescue_else, NODE *ensure, const YYLTYPE *loc);
static NODE *const_decl(struct parser_params *p, NODE* path, const YYLTYPE *loc);
@@ -535,6 +584,7 @@ static void check_literal_when(struct parser_params *p, NODE *args, const YYLTYP
#define get_num(num) (num)
#else /* RIPPER */
#define NODE_RIPPER NODE_CDECL
+#define NEW_RIPPER(a,b,c,loc) (VALUE)NEW_CDECL(a,b,c,loc)
static inline int ripper_is_node_yylval(VALUE n);
@@ -544,7 +594,7 @@ ripper_new_yylval(struct parser_params *p, ID a, VALUE b, VALUE c)
if (ripper_is_node_yylval(c)) c = RNODE(c)->nd_cval;
add_mark_object(p, b);
add_mark_object(p, c);
- return (VALUE)NEW_CDECL(a, b, c, &NULL_LOC);
+ return NEW_RIPPER(a, b, c, &NULL_LOC);
}
static inline int
@@ -579,10 +629,11 @@ static VALUE new_regexp(struct parser_params *, VALUE, VALUE, const YYLTYPE *);
static VALUE const_decl(struct parser_params *p, VALUE path);
static VALUE var_field(struct parser_params *p, VALUE a);
-static VALUE assign_error(struct parser_params *p, VALUE a);
+static VALUE assign_error(struct parser_params *p, const char *mesg, VALUE a);
static VALUE parser_reg_compile(struct parser_params*, VALUE, int, VALUE *);
+static VALUE backref_error(struct parser_params*, NODE *, VALUE);
#endif /* !RIPPER */
/* forward declaration */
@@ -602,8 +653,11 @@ RUBY_SYMBOL_EXPORT_END
static void error_duplicate_pattern_variable(struct parser_params *p, ID id, const YYLTYPE *loc);
static void error_duplicate_pattern_key(struct parser_params *p, ID id, const YYLTYPE *loc);
-static void parser_token_value_print(struct parser_params *p, enum yytokentype type, const YYSTYPE *valp);
+#ifndef RIPPER
static ID formal_argument(struct parser_params*, ID);
+#else
+static ID formal_argument(struct parser_params*, VALUE);
+#endif
static ID shadowing_lvar(struct parser_params*,ID);
static void new_bv(struct parser_params*,ID);
@@ -615,7 +669,11 @@ static int local_id(struct parser_params *p, ID id);
static int local_id_ref(struct parser_params*, ID, ID **);
#ifndef RIPPER
static ID internal_id(struct parser_params*);
+static NODE *new_args_forward_call(struct parser_params*, NODE*, const YYLTYPE*, const YYLTYPE*);
+static NODE *new_args_forward_def(struct parser_params*, NODE*, const YYLTYPE*);
#endif
+static int check_forwarding_args(struct parser_params*);
+static void add_forwarding_args(struct parser_params *p);
static const struct vtable *dyna_push(struct parser_params *);
static void dyna_pop(struct parser_params*, const struct vtable *);
@@ -796,14 +854,7 @@ static VALUE
new_array_pattern(struct parser_params *p, VALUE constant, VALUE pre_arg, VALUE aryptn, const YYLTYPE *loc)
{
NODE *t = (NODE *)aryptn;
- struct rb_ary_pattern_info *apinfo = t->nd_apinfo;
- VALUE pre_args = Qnil, rest_arg = Qnil, post_args = Qnil;
-
- if (apinfo) {
- pre_args = rb_ary_entry(apinfo->imemo, 0);
- rest_arg = rb_ary_entry(apinfo->imemo, 1);
- post_args = rb_ary_entry(apinfo->imemo, 2);
- }
+ VALUE pre_args = t->u1.value, rest_arg = t->u2.value, post_args = t->u3.value;
if (!NIL_P(pre_arg)) {
if (!NIL_P(pre_args)) {
@@ -820,7 +871,6 @@ static VALUE
new_array_pattern_tail(struct parser_params *p, VALUE pre_args, VALUE has_rest, VALUE rest_arg, VALUE post_args, const YYLTYPE *loc)
{
NODE *t;
- struct rb_ary_pattern_info *apinfo;
if (has_rest) {
rest_arg = dispatch1(var_field, rest_arg ? rest_arg : Qnil);
@@ -829,14 +879,34 @@ new_array_pattern_tail(struct parser_params *p, VALUE pre_args, VALUE has_rest,
rest_arg = Qnil;
}
- VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer();
- apinfo = ZALLOC(struct rb_ary_pattern_info);
- rb_imemo_tmpbuf_set_ptr(tmpbuf, apinfo);
- apinfo->imemo = rb_ary_new_from_args(4, pre_args, rest_arg, post_args, tmpbuf);
+ t = rb_node_newnode(NODE_ARYPTN, pre_args, rest_arg, post_args, &NULL_LOC);
+ add_mark_object(p, pre_args);
+ add_mark_object(p, rest_arg);
+ add_mark_object(p, post_args);
+ return (VALUE)t;
+}
- t = rb_node_newnode(NODE_ARYPTN, Qnil, Qnil, (VALUE)apinfo, &NULL_LOC);
- RB_OBJ_WRITTEN(p->ast, Qnil, apinfo->imemo);
+static VALUE
+new_find_pattern(struct parser_params *p, VALUE constant, VALUE fndptn, const YYLTYPE *loc)
+{
+ NODE *t = (NODE *)fndptn;
+ VALUE pre_rest_arg = t->u1.value, args = t->u2.value, post_rest_arg = t->u3.value;
+
+ return dispatch4(fndptn, constant, pre_rest_arg, args, post_rest_arg);
+}
+static VALUE
+new_find_pattern_tail(struct parser_params *p, VALUE pre_rest_arg, VALUE args, VALUE post_rest_arg, const YYLTYPE *loc)
+{
+ NODE *t;
+
+ pre_rest_arg = dispatch1(var_field, pre_rest_arg ? pre_rest_arg : Qnil);
+ post_rest_arg = dispatch1(var_field, post_rest_arg ? post_rest_arg : Qnil);
+
+ t = rb_node_newnode(NODE_FNDPTN, pre_rest_arg, args, post_rest_arg, &NULL_LOC);
+ add_mark_object(p, pre_rest_arg);
+ add_mark_object(p, args);
+ add_mark_object(p, post_rest_arg);
return (VALUE)t;
}
@@ -881,8 +951,53 @@ static VALUE heredoc_dedent(struct parser_params*,VALUE);
#define ID2VAL(id) (id)
#define TOKEN2VAL(t) ID2VAL(t)
#define KWD2EID(t, v) keyword_##t
+
+static NODE *
+set_defun_body(struct parser_params *p, NODE *n, NODE *args, NODE *body, const YYLTYPE *loc)
+{
+ body = remove_begin(body);
+ reduce_nodes(p, &body);
+ n->nd_defn = NEW_SCOPE(args, body, loc);
+ n->nd_loc = *loc;
+ nd_set_line(n->nd_defn, loc->end_pos.lineno);
+ set_line_body(body, loc->beg_pos.lineno);
+ return n;
+}
+
+static NODE *
+rescued_expr(struct parser_params *p, NODE *arg, NODE *rescue,
+ const YYLTYPE *arg_loc, const YYLTYPE *mod_loc, const YYLTYPE *res_loc)
+{
+ YYLTYPE loc = code_loc_gen(mod_loc, res_loc);
+ rescue = NEW_RESBODY(0, remove_begin(rescue), 0, &loc);
+ loc.beg_pos = arg_loc->beg_pos;
+ return NEW_RESCUE(arg, rescue, 0, &loc);
+}
+
#endif /* RIPPER */
+static void
+restore_defun(struct parser_params *p, NODE *name)
+{
+ YYSTYPE c = {.val = name->nd_cval};
+ p->cur_arg = name->nd_vid;
+ p->ctxt.in_def = c.ctxt.in_def;
+ p->ctxt.shareable_constant_value = c.ctxt.shareable_constant_value;
+}
+
+static void
+endless_method_name(struct parser_params *p, NODE *defn, const YYLTYPE *loc)
+{
+#ifdef RIPPER
+ defn = defn->nd_defn;
+#endif
+ ID mid = defn->nd_mid;
+ if (is_attrset_id(mid)) {
+ yyerror1(loc, "setter method cannot be defined in an endless method definition");
+ }
+ token_info_drop(p, "def", loc->beg_pos);
+}
+
#ifndef RIPPER
# define Qnone 0
# define Qnull 0
@@ -915,12 +1030,14 @@ static VALUE heredoc_dedent(struct parser_params*,VALUE);
# define rb_warning4L(l,fmt,a,b,c,d) WARNING_CALL(WARNING_ARGS_L(l, fmt, 5), (a), (b), (c), (d))
#ifdef RIPPER
static ID id_warn, id_warning, id_gets, id_assoc;
+# define ERR_MESG() STR_NEW2(mesg) /* to bypass Ripper DSL */
# define WARN_S_L(s,l) STR_NEW(s,l)
# define WARN_S(s) STR_NEW2(s)
# define WARN_I(i) INT2NUM(i)
# define WARN_ID(i) rb_id2str(i)
# define WARN_IVAL(i) i
# define PRIsWARN "s"
+# define rb_warn0L_experimental(l,fmt) WARN_CALL(WARN_ARGS_L(l, fmt, 1))
# define WARN_ARGS(fmt,n) p->value, id_warn, n, rb_usascii_str_new_lit(fmt)
# define WARN_ARGS_L(l,fmt,n) WARN_ARGS(fmt,n)
# ifdef HAVE_VA_ARGS_MACRO
@@ -947,6 +1064,7 @@ PRINTF_ARGS(static void ripper_compile_error(struct parser_params*, const char *
# define WARN_ARGS(fmt,n) WARN_ARGS_L(p->ruby_sourceline,fmt,n)
# define WARN_ARGS_L(l,fmt,n) p->ruby_sourcefile, (l), (fmt)
# define WARN_CALL rb_compile_warn
+# define rb_warn0L_experimental(l,fmt) rb_category_compile_warn(RB_WARN_CATEGORY_EXPERIMENTAL, WARN_ARGS_L(l, fmt, 1))
# define WARNING_ARGS(fmt,n) WARN_ARGS(fmt,n)
# define WARNING_ARGS_L(l,fmt,n) WARN_ARGS_L(l,fmt,n)
# define WARNING_CALL rb_compile_warning
@@ -954,11 +1072,6 @@ PRINTF_ARGS(static void parser_compile_error(struct parser_params*, const char *
# define compile_error parser_compile_error
#endif
-static void token_info_setup(token_info *ptinfo, const char *ptr, const rb_code_location_t *loc);
-static void token_info_push(struct parser_params*, const char *token, const rb_code_location_t *loc);
-static void token_info_pop(struct parser_params*, const char *token, const rb_code_location_t *loc);
-static void token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, int same, const rb_code_location_t *loc);
-
#define WARN_EOL(tok) \
(looking_at_eol_p(p) ? \
(void)rb_warning0("`" tok "' at the end of line without an expression") : \
@@ -969,6 +1082,35 @@ static int looking_at_eol_p(struct parser_params *p);
%expect 0
%define api.pure
%define parse.error verbose
+%printer {
+#ifndef RIPPER
+ rb_parser_printf(p, "%"PRIsVALUE, rb_id2str($$));
+#else
+ rb_parser_printf(p, "%"PRIsVALUE, RNODE($$)->nd_rval);
+#endif
+} tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL tOP_ASGN
+%printer {
+#ifndef RIPPER
+ rb_parser_printf(p, "%+"PRIsVALUE, $$->nd_lit);
+#else
+ rb_parser_printf(p, "%+"PRIsVALUE, get_value($$));
+#endif
+} tINTEGER tFLOAT tRATIONAL tIMAGINARY tSTRING_CONTENT tCHAR
+%printer {
+#ifndef RIPPER
+ rb_parser_printf(p, "$%ld", $$->nd_nth);
+#else
+ rb_parser_printf(p, "%"PRIsVALUE, $$);
+#endif
+} tNTH_REF
+%printer {
+#ifndef RIPPER
+ rb_parser_printf(p, "$%c", (int)$$->nd_nth);
+#else
+ rb_parser_printf(p, "%"PRIsVALUE, $$);
+#endif
+} tBACK_REF
+
%lex-param {struct parser_params *p}
%parse-param {struct parser_params *p}
%initial-action
@@ -984,6 +1126,7 @@ static int looking_at_eol_p(struct parser_params *p);
st_table *tbl;
const struct vtable *vars;
struct rb_strterm_struct *strterm;
+ struct lex_context ctxt;
}
%token <id>
@@ -1043,7 +1186,7 @@ static int looking_at_eol_p(struct parser_params *p);
%token <id> tIVAR "instance variable"
%token <id> tCONSTANT "constant"
%token <id> tCVAR "class variable"
-%token <id> tLABEL
+%token <id> tLABEL "label"
%token <node> tINTEGER "integer literal"
%token <node> tFLOAT "float literal"
%token <node> tRATIONAL "rational literal"
@@ -1057,7 +1200,7 @@ static int looking_at_eol_p(struct parser_params *p);
%type <node> singleton 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> literal numeric simple_numeric ssym dsym symbol cpath def_name defn_head defs_head
%type <node> top_compstmt top_stmts top_stmt begin_block
%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
%type <node> expr_value expr_value_do arg_value primary_value fcall rel_expr
@@ -1068,7 +1211,8 @@ static int looking_at_eol_p(struct parser_params *p);
%type <node> command_rhs arg_rhs
%type <node> command_asgn mrhs mrhs_arg superclass block_call block_command
%type <node> f_block_optarg f_block_opt
-%type <node> f_arglist f_args f_arg f_arg_item f_optarg f_marg f_marg_list f_margs f_rest_marg
+%type <node> f_arglist f_opt_paren_args f_paren_args f_args f_arg f_arg_item
+%type <node> f_optarg f_marg f_marg_list f_margs f_rest_marg
%type <node> assoc_list assocs assoc undef_list backref string_dvar for_var
%type <node> block_param opt_block_param block_param_def f_opt
%type <node> f_kwarg f_kw f_block_kwarg f_block_kw
@@ -1077,15 +1221,16 @@ static int looking_at_eol_p(struct parser_params *p);
%type <node> brace_block cmd_brace_block do_block lhs none fitem
%type <node> mlhs mlhs_head mlhs_basic mlhs_item mlhs_node mlhs_post 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
+%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
%type <node> p_value p_primitive p_variable p_var_ref p_const
%type <node> p_kwargs p_kwarg p_kw
%type <id> keyword_variable user_variable sym operation 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_kw_label
-%type <id> f_no_kwarg args_forward
+%type <id> p_rest p_kwrest p_kwnorest p_any_kwrest p_kw_label
+%type <id> f_no_kwarg f_any_kwrest args_forward excessed_comma
+ %type <ctxt> lex_ctxt /* keep <ctxt> in ripper */
%token END_OF_INPUT 0 "end-of-input"
%token <id> '.'
/* escaped chars, should be ignored otherwise */
@@ -1346,11 +1491,12 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
}
| keyword_alias tGVAR tNTH_REF
{
+ static const char mesg[] = "can't make alias for the number variables";
/*%%%*/
- yyerror1(&@3, "can't make alias for the number variables");
+ yyerror1(&@3, mesg);
$$ = NEW_BEGIN(0, &@$);
/*% %*/
- /*% ripper[error]: alias_error!(var_alias!($2, $3)) %*/
+ /*% ripper[error]: alias_error!(ERR_MESG(), $3) %*/
}
| keyword_undef undef_list
{
@@ -1411,7 +1557,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
}
| keyword_END '{' compstmt '}'
{
- if (p->in_def) {
+ if (p->ctxt.in_def) {
rb_warn0("END in method; use at_exit");
}
/*%%%*/
@@ -1424,99 +1570,99 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
/*% ripper: END!($3) %*/
}
| command_asgn
- | mlhs '=' command_call
+ | mlhs '=' lex_ctxt command_call
{
/*%%%*/
- value_expr($3);
- $$ = node_assign(p, $1, $3, &@$);
+ value_expr($4);
+ $$ = node_assign(p, $1, $4, $3, &@$);
/*% %*/
- /*% ripper: massign!($1, $3) %*/
+ /*% ripper: massign!($1, $4) %*/
}
- | lhs '=' mrhs
+ | lhs '=' lex_ctxt mrhs
{
/*%%%*/
- value_expr($3);
- $$ = node_assign(p, $1, $3, &@$);
+ value_expr($4);
+ $$ = node_assign(p, $1, $4, $3, &@$);
/*% %*/
- /*% ripper: assign!($1, $3) %*/
+ /*% ripper: assign!($1, $4) %*/
}
- | mlhs '=' mrhs_arg modifier_rescue stmt
+ | mlhs '=' lex_ctxt mrhs_arg modifier_rescue stmt
{
/*%%%*/
- YYLTYPE loc = code_loc_gen(&@4, &@5);
- value_expr($3);
- $$ = node_assign(p, $1, NEW_RESCUE($3, NEW_RESBODY(0, remove_begin($5), 0, &loc), 0, &@$), &@$);
+ YYLTYPE loc = code_loc_gen(&@5, &@6);
+ value_expr($4);
+ $$ = node_assign(p, $1, NEW_RESCUE($4, NEW_RESBODY(0, remove_begin($6), 0, &loc), 0, &@$), $3, &@$);
/*% %*/
- /*% ripper: massign!($1, rescue_mod!($3, $5)) %*/
+ /*% ripper: massign!($1, rescue_mod!($4, $6)) %*/
}
- | mlhs '=' mrhs_arg
+ | mlhs '=' lex_ctxt mrhs_arg
{
/*%%%*/
- $$ = node_assign(p, $1, $3, &@$);
+ $$ = node_assign(p, $1, $4, $3, &@$);
/*% %*/
- /*% ripper: massign!($1, $3) %*/
+ /*% ripper: massign!($1, $4) %*/
}
| expr
;
-command_asgn : lhs '=' command_rhs
+command_asgn : lhs '=' lex_ctxt command_rhs
{
/*%%%*/
- $$ = node_assign(p, $1, $3, &@$);
+ $$ = node_assign(p, $1, $4, $3, &@$);
/*% %*/
- /*% ripper: assign!($1, $3) %*/
+ /*% ripper: assign!($1, $4) %*/
}
- | var_lhs tOP_ASGN command_rhs
+ | var_lhs tOP_ASGN lex_ctxt command_rhs
{
/*%%%*/
- $$ = new_op_assign(p, $1, $2, $3, &@$);
+ $$ = new_op_assign(p, $1, $2, $4, $3, &@$);
/*% %*/
- /*% ripper: opassign!($1, $2, $3) %*/
+ /*% ripper: opassign!($1, $2, $4) %*/
}
- | primary_value '[' opt_call_args rbracket tOP_ASGN command_rhs
+ | primary_value '[' opt_call_args rbracket tOP_ASGN lex_ctxt command_rhs
{
/*%%%*/
- $$ = new_ary_op_assign(p, $1, $3, $5, $6, &@3, &@$);
+ $$ = new_ary_op_assign(p, $1, $3, $5, $7, &@3, &@$);
/*% %*/
- /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $6) %*/
+ /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $7) %*/
}
- | primary_value call_op tIDENTIFIER tOP_ASGN command_rhs
+ | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt command_rhs
{
/*%%%*/
- $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$);
+ $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$);
/*% %*/
- /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/
+ /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/
}
- | primary_value call_op tCONSTANT tOP_ASGN command_rhs
+ | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt command_rhs
{
/*%%%*/
- $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$);
+ $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$);
/*% %*/
- /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/
+ /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/
}
- | primary_value tCOLON2 tCONSTANT tOP_ASGN command_rhs
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt command_rhs
{
/*%%%*/
YYLTYPE loc = code_loc_gen(&@1, &@3);
- $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $5, &@$);
+ $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $6, $5, &@$);
/*% %*/
- /*% ripper: opassign!(const_path_field!($1, $3), $4, $5) %*/
+ /*% ripper: opassign!(const_path_field!($1, $3), $4, $6) %*/
}
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_rhs
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN lex_ctxt command_rhs
{
/*%%%*/
- $$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $5, &@$);
+ $$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $6, &@$);
/*% %*/
- /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $5) %*/
+ /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $6) %*/
}
- | backref tOP_ASGN command_rhs
+ | backref tOP_ASGN lex_ctxt command_rhs
{
/*%%%*/
rb_backref_error(p, $1);
$$ = NEW_BEGIN(0, &@$);
/*% %*/
- /*% ripper[error]: assign_error!(assign!(var_field(p, $1), $3)) %*/
+ /*% ripper[error]: backref_error(p, RNODE($1), assign!(var_field(p, $1), $4)) %*/
}
;
@@ -1554,27 +1700,87 @@ expr : command_call
{
$$ = call_uni_op(p, method_cond(p, $2, &@2), '!', &@1, &@$);
}
+ | arg tASSOC
+ {
+ value_expr($1);
+ SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
+ p->command_start = FALSE;
+ $<ctxt>$ = p->ctxt;
+ p->ctxt.in_kwarg = 1;
+ }
+ {$<tbl>$ = push_pvtbl(p);}
+ p_expr
+ {pop_pvtbl(p, $<tbl>4);}
+ {
+ p->ctxt.in_kwarg = $<ctxt>3.in_kwarg;
+ /*%%%*/
+ $$ = NEW_CASE3($1, NEW_IN($5, 0, 0, &@5), &@$);
+ warn_one_line_pattern_matching(p, $$, $5, true);
+ /*% %*/
+ /*% ripper: case!($1, in!($5, Qnil, Qnil)) %*/
+ }
| arg keyword_in
{
value_expr($1);
SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
p->command_start = FALSE;
- $<num>$ = p->in_kwarg;
- p->in_kwarg = 1;
+ $<ctxt>$ = p->ctxt;
+ p->ctxt.in_kwarg = 1;
}
{$<tbl>$ = push_pvtbl(p);}
p_expr
{pop_pvtbl(p, $<tbl>4);}
{
- p->in_kwarg = !!$<num>3;
+ p->ctxt.in_kwarg = $<ctxt>3.in_kwarg;
/*%%%*/
- $$ = new_case3(p, $1, NEW_IN($5, 0, 0, &@5), &@$);
+ $$ = NEW_CASE3($1, NEW_IN($5, NEW_TRUE(&@5), NEW_FALSE(&@5), &@5), &@$);
+ warn_one_line_pattern_matching(p, $$, $5, false);
/*% %*/
/*% ripper: case!($1, in!($5, Qnil, Qnil)) %*/
}
| arg %prec tLBRACE_ARG
;
+def_name : fname
+ {
+ ID fname = get_id($1);
+ ID cur_arg = p->cur_arg;
+ YYSTYPE c = {.ctxt = p->ctxt};
+ numparam_name(p, fname);
+ local_push(p, 0);
+ p->cur_arg = 0;
+ p->ctxt.in_def = 1;
+ $<node>$ = NEW_NODE(NODE_SELF, /*vid*/cur_arg, /*mid*/fname, /*cval*/c.val, &@$);
+ /*%%%*/
+ /*%
+ $$ = NEW_RIPPER(fname, get_value($1), $$, &NULL_LOC);
+ %*/
+ }
+ ;
+
+defn_head : k_def def_name
+ {
+ $$ = $2;
+ /*%%%*/
+ $$ = NEW_NODE(NODE_DEFN, 0, $$->nd_mid, $$, &@$);
+ /*% %*/
+ }
+ ;
+
+defs_head : k_def singleton dot_or_colon {SET_LEX_STATE(EXPR_FNAME);} def_name
+ {
+ SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */
+ $$ = $5;
+ /*%%%*/
+ $$ = NEW_NODE(NODE_DEFS, $2, $$->nd_mid, $$, &@$);
+ /*%
+ VALUE ary = rb_ary_new_from_args(3, $2, $3, get_value($$));
+ add_mark_object(p, ary);
+ $<node>$->nd_rval = ary;
+ %*/
+ }
+ ;
+
expr_value : expr
{
value_expr($1);
@@ -1911,7 +2117,7 @@ mlhs_node : user_variable
rb_backref_error(p, $1);
$$ = NEW_BEGIN(0, &@$);
/*% %*/
- /*% ripper[error]: assign_error!(var_field(p, $1)) %*/
+ /*% ripper[error]: backref_error(p, RNODE($1), var_field(p, $1)) %*/
}
;
@@ -1977,16 +2183,17 @@ lhs : user_variable
rb_backref_error(p, $1);
$$ = NEW_BEGIN(0, &@$);
/*% %*/
- /*% ripper[error]: assign_error!(var_field(p, $1)) %*/
+ /*% ripper[error]: backref_error(p, RNODE($1), var_field(p, $1)) %*/
}
;
cname : tIDENTIFIER
{
+ static const char mesg[] = "class/module name must be CONSTANT";
/*%%%*/
- yyerror1(&@1, "class/module name must be CONSTANT");
+ yyerror1(&@1, mesg);
/*% %*/
- /*% ripper[error]: class_name_error!($1) %*/
+ /*% ripper[error]: class_name_error!(ERR_MESG(), $1) %*/
}
| tCONSTANT
;
@@ -2098,74 +2305,70 @@ reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
| keyword_while | keyword_until
;
-arg : lhs '=' arg_rhs
+arg : lhs '=' lex_ctxt arg_rhs
{
/*%%%*/
- $$ = node_assign(p, $1, $3, &@$);
+ $$ = node_assign(p, $1, $4, $3, &@$);
/*% %*/
- /*% ripper: assign!($1, $3) %*/
+ /*% ripper: assign!($1, $4) %*/
}
- | var_lhs tOP_ASGN arg_rhs
+ | var_lhs tOP_ASGN lex_ctxt arg_rhs
{
/*%%%*/
- $$ = new_op_assign(p, $1, $2, $3, &@$);
+ $$ = new_op_assign(p, $1, $2, $4, $3, &@$);
/*% %*/
- /*% ripper: opassign!($1, $2, $3) %*/
+ /*% ripper: opassign!($1, $2, $4) %*/
}
- | primary_value '[' opt_call_args rbracket tOP_ASGN arg_rhs
+ | primary_value '[' opt_call_args rbracket tOP_ASGN lex_ctxt arg_rhs
{
/*%%%*/
- value_expr($6);
- $$ = new_ary_op_assign(p, $1, $3, $5, $6, &@3, &@$);
+ $$ = new_ary_op_assign(p, $1, $3, $5, $7, &@3, &@$);
/*% %*/
- /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $6) %*/
+ /*% ripper: opassign!(aref_field!($1, escape_Qundef($3)), $5, $7) %*/
}
- | primary_value call_op tIDENTIFIER tOP_ASGN arg_rhs
+ | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt arg_rhs
{
/*%%%*/
- value_expr($5);
- $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$);
+ $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$);
/*% %*/
- /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/
+ /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/
}
- | primary_value call_op tCONSTANT tOP_ASGN arg_rhs
+ | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt arg_rhs
{
/*%%%*/
- value_expr($5);
- $$ = new_attr_op_assign(p, $1, $2, $3, $4, $5, &@$);
+ $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$);
/*% %*/
- /*% ripper: opassign!(field!($1, $2, $3), $4, $5) %*/
+ /*% ripper: opassign!(field!($1, $2, $3), $4, $6) %*/
}
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg_rhs
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN lex_ctxt arg_rhs
{
/*%%%*/
- value_expr($5);
- $$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $5, &@$);
+ $$ = new_attr_op_assign(p, $1, ID2VAL(idCOLON2), $3, $4, $6, &@$);
/*% %*/
- /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $5) %*/
+ /*% ripper: opassign!(field!($1, ID2VAL(idCOLON2), $3), $4, $6) %*/
}
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg_rhs
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt arg_rhs
{
/*%%%*/
YYLTYPE loc = code_loc_gen(&@1, &@3);
- $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $5, &@$);
+ $$ = new_const_op_assign(p, NEW_COLON2($1, $3, &loc), $4, $6, $5, &@$);
/*% %*/
- /*% ripper: opassign!(const_path_field!($1, $3), $4, $5) %*/
+ /*% ripper: opassign!(const_path_field!($1, $3), $4, $6) %*/
}
- | tCOLON3 tCONSTANT tOP_ASGN arg_rhs
+ | tCOLON3 tCONSTANT tOP_ASGN lex_ctxt arg_rhs
{
/*%%%*/
- $$ = new_const_op_assign(p, NEW_COLON3($2, &@$), $3, $4, &@$);
+ $$ = new_const_op_assign(p, NEW_COLON3($2, &@$), $3, $5, $4, &@$);
/*% %*/
- /*% ripper: opassign!(top_const_field!($2), $3, $4) %*/
+ /*% ripper: opassign!(top_const_field!($2), $3, $5) %*/
}
- | backref tOP_ASGN arg_rhs
+ | backref tOP_ASGN lex_ctxt arg_rhs
{
/*%%%*/
rb_backref_error(p, $1);
$$ = NEW_BEGIN(0, &@$);
/*% %*/
- /*% ripper[error]: assign_error!(opassign!(var_field(p, $1), $2, $3)) %*/
+ /*% ripper[error]: backref_error(p, RNODE($1), opassign!(var_field(p, $1), $2, $4)) %*/
}
| arg tDOT2 arg
{
@@ -2188,48 +2391,32 @@ arg : lhs '=' arg_rhs
| arg tDOT2
{
/*%%%*/
- YYLTYPE loc;
- loc.beg_pos = @2.end_pos;
- loc.end_pos = @2.end_pos;
-
value_expr($1);
- $$ = NEW_DOT2($1, new_nil(&loc), &@$);
+ $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$);
/*% %*/
/*% ripper: dot2!($1, Qnil) %*/
}
| arg tDOT3
{
/*%%%*/
- YYLTYPE loc;
- loc.beg_pos = @2.end_pos;
- loc.end_pos = @2.end_pos;
-
value_expr($1);
- $$ = NEW_DOT3($1, new_nil(&loc), &@$);
+ $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$);
/*% %*/
/*% ripper: dot3!($1, Qnil) %*/
}
| tBDOT2 arg
{
/*%%%*/
- YYLTYPE loc;
- loc.beg_pos = @1.beg_pos;
- loc.end_pos = @1.beg_pos;
-
value_expr($2);
- $$ = NEW_DOT2(new_nil(&loc), $2, &@$);
+ $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$);
/*% %*/
/*% ripper: dot2!(Qnil, $2) %*/
}
| tBDOT3 arg
{
/*%%%*/
- YYLTYPE loc;
- loc.beg_pos = @1.beg_pos;
- loc.end_pos = @1.beg_pos;
-
value_expr($2);
- $$ = NEW_DOT3(new_nil(&loc), $2, &@$);
+ $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$);
/*% %*/
/*% ripper: dot3!(Qnil, $2) %*/
}
@@ -2330,9 +2517,9 @@ arg : lhs '=' arg_rhs
{
$$ = logop(p, idOROP, $1, $3, &@2, &@$);
}
- | keyword_defined opt_nl {p->in_defined = 1;} arg
+ | keyword_defined opt_nl {p->ctxt.in_defined = 1;} arg
{
- p->in_defined = 0;
+ p->ctxt.in_defined = 0;
$$ = new_defined(p, $4, &@$);
}
| arg '?' arg opt_nl ':' arg
@@ -2344,6 +2531,52 @@ arg : lhs '=' arg_rhs
/*% %*/
/*% ripper: ifop!($1, $3, $6) %*/
}
+ | defn_head f_opt_paren_args '=' arg
+ {
+ endless_method_name(p, $<node>1, &@1);
+ restore_defun(p, $<node>1->nd_defn);
+ /*%%%*/
+ $$ = set_defun_body(p, $1, $2, $4, &@$);
+ /*% %*/
+ /*% ripper: def!(get_value($1), $2, $4) %*/
+ local_pop(p);
+ }
+ | defn_head f_opt_paren_args '=' arg modifier_rescue arg
+ {
+ endless_method_name(p, $<node>1, &@1);
+ restore_defun(p, $<node>1->nd_defn);
+ /*%%%*/
+ $4 = rescued_expr(p, $4, $6, &@4, &@5, &@6);
+ $$ = set_defun_body(p, $1, $2, $4, &@$);
+ /*% %*/
+ /*% ripper: def!(get_value($1), $2, rescue_mod!($4, $6)) %*/
+ local_pop(p);
+ }
+ | defs_head f_opt_paren_args '=' arg
+ {
+ endless_method_name(p, $<node>1, &@1);
+ restore_defun(p, $<node>1->nd_defn);
+ /*%%%*/
+ $$ = set_defun_body(p, $1, $2, $4, &@$);
+ /*%
+ $1 = get_value($1);
+ %*/
+ /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $4) %*/
+ local_pop(p);
+ }
+ | defs_head f_opt_paren_args '=' arg modifier_rescue arg
+ {
+ endless_method_name(p, $<node>1, &@1);
+ restore_defun(p, $<node>1->nd_defn);
+ /*%%%*/
+ $4 = rescued_expr(p, $4, $6, &@4, &@5, &@6);
+ $$ = set_defun_body(p, $1, $2, $4, &@$);
+ /*%
+ $1 = get_value($1);
+ %*/
+ /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, rescue_mod!($4, $6)) %*/
+ local_pop(p);
+ }
| primary
{
$$ = $1;
@@ -2367,6 +2600,16 @@ rel_expr : arg relop arg %prec '>'
}
;
+lex_ctxt : tSP
+ {
+ $$ = p->ctxt;
+ }
+ | none
+ {
+ $$ = p->ctxt;
+ }
+ ;
+
arg_value : arg
{
value_expr($1);
@@ -2403,9 +2646,8 @@ arg_rhs : arg %prec tOP_ASGN
| arg modifier_rescue arg
{
/*%%%*/
- YYLTYPE loc = code_loc_gen(&@2, &@3);
value_expr($1);
- $$ = NEW_RESCUE($1, NEW_RESBODY(0, remove_begin($3), 0, &loc), 0, &@$);
+ $$ = rescued_expr(p, $1, $3, &@1, &@2, &@3);
/*% %*/
/*% ripper: rescue_mod!($1, $3) %*/
}
@@ -2420,53 +2662,24 @@ paren_args : '(' opt_call_args rparen
}
| '(' args ',' args_forward rparen
{
- if (!local_id(p, idFWD_REST) ||
-#if idFWD_KWREST
- !local_id(p, idFWD_KWREST) ||
-#endif
- !local_id(p, idFWD_BLOCK)) {
- compile_error(p, "unexpected ...");
+ if (!check_forwarding_args(p)) {
$$ = Qnone;
}
else {
/*%%%*/
- NODE *splat = NEW_SPLAT(NEW_LVAR(idFWD_REST, &@4), &@4);
-#if idFWD_KWREST
- NODE *kwrest = list_append(p, NEW_LIST(0, &@4), NEW_LVAR(idFWD_KWREST, &@4));
-#endif
- NODE *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@4), &@4);
- $$ = rest_arg_append(p, $2, splat, &@$);
-#if idFWD_KWREST
- $$ = arg_append(p, $$, new_hash(p, kwrest, &@4), &@4);
-#endif
- $$ = arg_blk_pass($$, block);
+ $$ = new_args_forward_call(p, $2, &@4, &@$);
/*% %*/
/*% ripper: arg_paren!(args_add!($2, $4)) %*/
}
}
| '(' args_forward rparen
{
- if (!local_id(p, idFWD_REST) ||
-#if idFWD_KWREST
- !local_id(p, idFWD_KWREST) ||
-#endif
- !local_id(p, idFWD_BLOCK)) {
- compile_error(p, "unexpected ...");
+ if (!check_forwarding_args(p)) {
$$ = Qnone;
}
else {
/*%%%*/
- NODE *splat = NEW_SPLAT(NEW_LVAR(idFWD_REST, &@2), &@2);
-#if idFWD_KWREST
- NODE *kwrest = list_append(p, NEW_LIST(0, &@2), NEW_LVAR(idFWD_KWREST, &@2));
-#endif
- NODE *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@2), &@2);
-#if idFWD_KWREST
- $$ = arg_append(p, splat, new_hash(p, kwrest, &@2), &@2);
-#else
- $$ = splat;
-#endif
- $$ = arg_blk_pass($$, block);
+ $$ = new_args_forward_call(p, 0, &@2, &@$);
/*% %*/
/*% ripper: arg_paren!($2) %*/
}
@@ -2759,9 +2972,9 @@ primary : literal
/*% %*/
/*% ripper: yield0! %*/
}
- | keyword_defined opt_nl '(' {p->in_defined = 1;} expr rparen
+ | keyword_defined opt_nl '(' {p->ctxt.in_defined = 1;} expr rparen
{
- p->in_defined = 0;
+ p->ctxt.in_defined = 0;
$$ = new_defined(p, $5, &@$);
}
| keyword_not '(' expr rparen
@@ -2788,17 +3001,7 @@ primary : literal
/*% %*/
/*% ripper: method_add_block!($1, $2) %*/
}
- | tLAMBDA
- {
- token_info_push(p, "->", &@1);
- }
- lambda
- {
- $$ = $3;
- /*%%%*/
- nd_set_first_loc($$, @1.beg_pos);
- /*% %*/
- }
+ | lambda
| k_if expr_value then
compstmt
if_tail
@@ -2877,7 +3080,7 @@ primary : literal
k_end
{
/*%%%*/
- $$ = new_case3(p, $2, $4, &@$);
+ $$ = NEW_CASE3($2, $4, &@$);
/*% %*/
/*% ripper: case!($2, $4) %*/
}
@@ -2912,10 +3115,10 @@ primary : literal
m->nd_next = $2;
break;
case NODE_MASGN: /* e.each {|*internal_var| a, b, c = (internal_var.length == 1 && Array === (tmp = internal_var[0]) ? tmp : internal_var); ... } */
- m->nd_next = node_assign(p, $2, NEW_FOR_MASGN(internal_var, &@2), &@2);
+ m->nd_next = node_assign(p, $2, NEW_FOR_MASGN(internal_var, &@2), NO_LEX_CTXT, &@2);
break;
default: /* e.each {|*internal_var| @a, B, c[1], d.attr = internal_val; ... } */
- m->nd_next = node_assign(p, NEW_MASGN(NEW_LIST($2, &@2), 0, &@2), internal_var, &@2);
+ m->nd_next = node_assign(p, NEW_MASGN(NEW_LIST($2, &@2), 0, &@2), internal_var, NO_LEX_CTXT, &@2);
}
/* {|*internal_id| <m> = internal_id; ... } */
args = new_args(p, m, 0, id, 0, new_args_tail(p, 0, 0, 0, &@2), &@2);
@@ -2927,12 +3130,11 @@ primary : literal
}
| k_class cpath superclass
{
- if (p->in_def) {
+ if (p->ctxt.in_def) {
YYLTYPE loc = code_loc_gen(&@1, &@2);
yyerror1(&loc, "class definition in method body");
}
- $<num>1 = p->in_class;
- p->in_class = 1;
+ p->ctxt.in_class = 1;
local_push(p, 0);
}
bodystmt
@@ -2946,13 +3148,13 @@ primary : literal
/*% %*/
/*% ripper: class!($2, $3, $5) %*/
local_pop(p);
- p->in_class = $<num>1 & 1;
+ p->ctxt.in_class = $<ctxt>1.in_class;
+ p->ctxt.shareable_constant_value = $<ctxt>1.shareable_constant_value;
}
| k_class tLSHFT expr
{
- $<num>$ = (p->in_class << 1) | p->in_def;
- p->in_def = 0;
- p->in_class = 0;
+ p->ctxt.in_def = 0;
+ p->ctxt.in_class = 0;
local_push(p, 0);
}
term
@@ -2967,17 +3169,17 @@ primary : literal
/*% %*/
/*% ripper: sclass!($3, $6) %*/
local_pop(p);
- p->in_def = $<num>4 & 1;
- p->in_class = ($<num>4 >> 1) & 1;
+ p->ctxt.in_def = $<ctxt>1.in_def;
+ p->ctxt.in_class = $<ctxt>1.in_class;
+ p->ctxt.shareable_constant_value = $<ctxt>1.shareable_constant_value;
}
| k_module cpath
{
- if (p->in_def) {
+ if (p->ctxt.in_def) {
YYLTYPE loc = code_loc_gen(&@1, &@2);
yyerror1(&loc, "module definition in method body");
}
- $<num>1 = p->in_class;
- p->in_class = 1;
+ p->ctxt.in_class = 1;
local_push(p, 0);
}
bodystmt
@@ -2991,60 +3193,34 @@ primary : literal
/*% %*/
/*% ripper: module!($2, $4) %*/
local_pop(p);
- p->in_class = $<num>1 & 1;
- }
- | k_def fname
- {
- numparam_name(p, get_id($2));
- local_push(p, 0);
- $<id>$ = p->cur_arg;
- p->cur_arg = 0;
- }
- {
- $<num>$ = p->in_def;
- p->in_def = 1;
+ p->ctxt.in_class = $<ctxt>1.in_class;
+ p->ctxt.shareable_constant_value = $<ctxt>1.shareable_constant_value;
}
+ | defn_head
f_arglist
bodystmt
k_end
{
+ restore_defun(p, $<node>1->nd_defn);
/*%%%*/
- NODE *body = remove_begin($6);
- reduce_nodes(p, &body);
- $$ = NEW_DEFN($2, $5, body, &@$);
- nd_set_line($$->nd_defn, @7.end_pos.lineno);
- set_line_body(body, @1.beg_pos.lineno);
+ $$ = set_defun_body(p, $1, $2, $3, &@$);
/*% %*/
- /*% ripper: def!($2, $5, $6) %*/
+ /*% ripper: def!(get_value($1), $2, $3) %*/
local_pop(p);
- p->in_def = $<num>4 & 1;
- p->cur_arg = $<id>3;
- }
- | k_def singleton dot_or_colon {SET_LEX_STATE(EXPR_FNAME);} fname
- {
- numparam_name(p, get_id($5));
- $<num>4 = p->in_def;
- p->in_def = 1;
- SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */
- local_push(p, 0);
- $<id>$ = p->cur_arg;
- p->cur_arg = 0;
}
+ | defs_head
f_arglist
bodystmt
k_end
{
+ restore_defun(p, $<node>1->nd_defn);
/*%%%*/
- NODE *body = remove_begin($8);
- reduce_nodes(p, &body);
- $$ = NEW_DEFS($2, $5, $7, body, &@$);
- nd_set_line($$->nd_defn, @9.end_pos.lineno);
- set_line_body(body, @1.beg_pos.lineno);
- /*% %*/
- /*% ripper: defs!($2, $3, $5, $7, $8) %*/
+ $$ = set_defun_body(p, $1, $2, $3, &@$);
+ /*%
+ $1 = get_value($1);
+ %*/
+ /*% ripper: defs!(AREF($1, 0), AREF($1, 1), AREF($1, 2), $2, $3) %*/
local_pop(p);
- p->in_def = $<num>4 & 1;
- p->cur_arg = $<id>6;
}
| keyword_break
{
@@ -3139,12 +3315,14 @@ k_for : keyword_for
k_class : keyword_class
{
token_info_push(p, "class", &@$);
+ $<ctxt>$ = p->ctxt;
}
;
k_module : keyword_module
{
token_info_push(p, "module", &@$);
+ $<ctxt>$ = p->ctxt;
}
;
@@ -3214,7 +3392,7 @@ k_end : keyword_end
k_return : keyword_return
{
- if (p->in_class && !p->in_def && !dyna_in_block(p))
+ if (p->ctxt.in_class && !p->ctxt.in_def && !dyna_in_block(p))
yyerror1(&@1, "Invalid return in class/module body");
}
;
@@ -3342,6 +3520,10 @@ f_rest_marg : tSTAR f_norm_arg
}
;
+f_any_kwrest : f_kwrest
+ | f_no_kwarg {$$ = ID2VAL(idNil);}
+ ;
+
block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, $1, $3, $4, &@3);
@@ -3350,14 +3532,10 @@ block_args_tail : f_block_kwarg ',' f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, $1, Qnone, $2, &@1);
}
- | f_kwrest opt_f_block_arg
+ | f_any_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, Qnone, $1, $2, &@1);
}
- | f_no_kwarg opt_f_block_arg
- {
- $$ = new_args_tail(p, Qnone, ID2VAL(idNil), $2, &@1);
- }
| f_block_arg
{
$$ = new_args_tail(p, Qnone, Qnone, $1, &@1);
@@ -3374,6 +3552,16 @@ opt_block_args_tail : ',' block_args_tail
}
;
+excessed_comma : ','
+ {
+ /* magic number for rest_id in iseq_set_arguments() */
+ /*%%%*/
+ $$ = NODE_SPECIAL_EXCESSIVE_COMMA;
+ /*% %*/
+ /*% ripper: excessed_comma! %*/
+ }
+ ;
+
block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, $1, $3, $5, Qnone, $6, &@$);
@@ -3394,13 +3582,10 @@ block_param : f_arg ',' f_block_optarg ',' f_rest_arg opt_block_args_tail
{
$$ = new_args(p, $1, Qnone, $3, Qnone, $4, &@$);
}
- | f_arg ','
+ | f_arg excessed_comma
{
- /*%%%*/
- /* magic number for rest_id in iseq_set_arguments() */
- $$ = new_args(p, $1, Qnone, NODE_SPECIAL_EXCESSIVE_COMMA, Qnone, new_args_tail(p, Qnone, Qnone, Qnone, &@1), &@$);
- /*% %*/
- /*% ripper: new_args(p, $1, Qnone, excessed_comma!, Qnone, new_args_tail(p, Qnone, Qnone, Qnone, NULL), NULL) %*/
+ $$ = new_args_tail(p, Qnone, Qnone, Qnone, &@2);
+ $$ = new_args(p, $1, Qnone, $2, Qnone, $$, &@$);
}
| f_arg ',' f_rest_arg ',' f_arg opt_block_args_tail
{
@@ -3498,10 +3683,10 @@ bvar : tIDENTIFIER
}
;
-lambda : {
- $<vars>$ = dyna_push(p);
- }
+lambda : tLAMBDA
{
+ token_info_push(p, "->", &@1);
+ $<vars>1 = dyna_push(p);
$<num>$ = p->lex.lpar_beg;
p->lex.lpar_beg = p->lex.paren_nest;
}
@@ -3529,6 +3714,7 @@ lambda : {
$$ = NEW_LAMBDA($5, $7, &loc);
nd_set_line($$->nd_body, @7.end_pos.lineno);
nd_set_line($$, @5.end_pos.lineno);
+ nd_set_first_loc($$, @1.beg_pos);
}
/*% %*/
/*% ripper: lambda!($5, $7) %*/
@@ -3804,24 +3990,26 @@ p_case_body : keyword_in
{
SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
p->command_start = FALSE;
- $<num>$ = p->in_kwarg;
- p->in_kwarg = 1;
+ $<ctxt>1 = p->ctxt;
+ p->ctxt.in_kwarg = 1;
+ $<tbl>$ = push_pvtbl(p);
+ }
+ {
+ $<tbl>$ = push_pktbl(p);
}
- {$<tbl>$ = push_pvtbl(p);}
- {$<tbl>$ = push_pktbl(p);}
p_top_expr then
- {pop_pktbl(p, $<tbl>4);}
- {pop_pvtbl(p, $<tbl>3);}
{
- p->in_kwarg = !!$<num>2;
+ pop_pktbl(p, $<tbl>3);
+ pop_pvtbl(p, $<tbl>2);
+ p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;
}
compstmt
p_cases
{
/*%%%*/
- $$ = NEW_IN($5, $10, $11, &@$);
+ $$ = NEW_IN($4, $7, $8, &@$);
/*% %*/
- /*% ripper: in!($5, $10, escape_Qundef($11)) %*/
+ /*% ripper: in!($4, $7, escape_Qundef($8)) %*/
}
;
@@ -3862,6 +4050,10 @@ p_top_expr_body : p_expr
/*%
%*/
}
+ | p_find
+ {
+ $$ = new_find_pattern(p, Qnone, $1, &@$);
+ }
| p_args_tail
{
$$ = new_array_pattern(p, Qnone, Qnone, $1, &@$);
@@ -3910,6 +4102,15 @@ p_expr_basic : p_value
/*%
%*/
}
+ | p_const p_lparen p_find rparen
+ {
+ pop_pktbl(p, $<tbl>2);
+ $$ = new_find_pattern(p, $1, $3, &@$);
+ /*%%%*/
+ nd_set_first_loc($$, @1.beg_pos);
+ /*%
+ %*/
+ }
| p_const p_lparen p_kwargs rparen
{
pop_pktbl(p, $<tbl>2);
@@ -3933,6 +4134,15 @@ p_expr_basic : p_value
/*%
%*/
}
+ | p_const p_lbracket p_find rbracket
+ {
+ pop_pktbl(p, $<tbl>2);
+ $$ = new_find_pattern(p, $1, $3, &@$);
+ /*%%%*/
+ nd_set_first_loc($$, @1.beg_pos);
+ /*%
+ %*/
+ }
| p_const p_lbracket p_kwargs rbracket
{
pop_pktbl(p, $<tbl>2);
@@ -3947,10 +4157,13 @@ p_expr_basic : p_value
$$ = new_array_pattern_tail(p, Qnone, 0, 0, Qnone, &@$);
$$ = new_array_pattern(p, $1, Qnone, $$, &@$);
}
- | tLBRACK {$<tbl>$ = push_pktbl(p);} p_args rbracket
+ | tLBRACK p_args rbracket
{
- pop_pktbl(p, $<tbl>2);
- $$ = new_array_pattern(p, Qnone, Qnone, $3, &@$);
+ $$ = new_array_pattern(p, Qnone, Qnone, $2, &@$);
+ }
+ | tLBRACK p_find rbracket
+ {
+ $$ = new_find_pattern(p, Qnone, $2, &@$);
}
| tLBRACK rbracket
{
@@ -3960,13 +4173,13 @@ p_expr_basic : p_value
| tLBRACE
{
$<tbl>$ = push_pktbl(p);
- $<num>1 = p->in_kwarg;
- p->in_kwarg = 0;
+ $<ctxt>1 = p->ctxt;
+ p->ctxt.in_kwarg = 0;
}
p_kwargs rbrace
{
pop_pktbl(p, $<tbl>2);
- p->in_kwarg = $<num>1;
+ p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;
$$ = new_hash_pattern(p, Qnone, $3, &@$);
}
| tLBRACE rbrace
@@ -4035,21 +4248,33 @@ p_args_head : p_arg ','
}
;
-p_args_tail : tSTAR tIDENTIFIER
+p_args_tail : p_rest
{
- $$ = new_array_pattern_tail(p, Qnone, 1, $2, Qnone, &@$);
+ $$ = new_array_pattern_tail(p, Qnone, 1, $1, Qnone, &@$);
}
- | tSTAR tIDENTIFIER ',' p_args_post
+ | p_rest ',' p_args_post
{
- $$ = new_array_pattern_tail(p, Qnone, 1, $2, $4, &@$);
+ $$ = new_array_pattern_tail(p, Qnone, 1, $1, $3, &@$);
}
- | tSTAR
+ ;
+
+p_find : p_rest ',' p_args_post ',' p_rest
{
- $$ = new_array_pattern_tail(p, Qnone, 1, 0, Qnone, &@$);
+ $$ = new_find_pattern_tail(p, $1, $3, $5, &@$);
+
+ if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL))
+ rb_warn0L_experimental(nd_line($$), "Find pattern is experimental, and the behavior may change in future versions of Ruby!");
+ }
+ ;
+
+
+p_rest : tSTAR tIDENTIFIER
+ {
+ $$ = $2;
}
- | tSTAR ',' p_args_post
+ | tSTAR
{
- $$ = new_array_pattern_tail(p, Qnone, 1, 0, $3, &@$);
+ $$ = 0;
}
;
@@ -4072,7 +4297,7 @@ p_arg : p_expr
}
;
-p_kwargs : p_kwarg ',' p_kwrest
+p_kwargs : p_kwarg ',' p_any_kwrest
{
$$ = new_hash_pattern_tail(p, new_unique_key_hash(p, $1, &@$), $3, &@$);
}
@@ -4084,18 +4309,10 @@ p_kwargs : p_kwarg ',' p_kwrest
{
$$ = new_hash_pattern_tail(p, new_unique_key_hash(p, $1, &@$), 0, &@$);
}
- | p_kwrest
+ | p_any_kwrest
{
$$ = new_hash_pattern_tail(p, new_hash(p, Qnone, &@$), $1, &@$);
}
- | p_kwarg ',' p_kwnorest
- {
- $$ = new_hash_pattern_tail(p, new_unique_key_hash(p, $1, &@$), ID2VAL(idNil), &@$);
- }
- | p_kwnorest
- {
- $$ = new_hash_pattern_tail(p, new_hash(p, Qnone, &@$), ID2VAL(idNil), &@$);
- }
;
p_kwarg : p_kw
@@ -4171,6 +4388,10 @@ p_kwnorest : kwrest_mark keyword_nil
}
;
+p_any_kwrest : p_kwrest
+ | p_kwnorest {$$ = ID2VAL(idNil);}
+ ;
+
p_value : p_primitive
| p_primitive tDOT2 p_primitive
{
@@ -4192,25 +4413,17 @@ p_value : p_primitive
}
| p_primitive tDOT2
{
- /*%%%*/
- YYLTYPE loc;
- loc.beg_pos = @2.end_pos;
- loc.end_pos = @2.end_pos;
-
+ /*%%%*/
value_expr($1);
- $$ = NEW_DOT2($1, new_nil(&loc), &@$);
+ $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$);
/*% %*/
/*% ripper: dot2!($1, Qnil) %*/
}
| p_primitive tDOT3
{
/*%%%*/
- YYLTYPE loc;
- loc.beg_pos = @2.end_pos;
- loc.end_pos = @2.end_pos;
-
value_expr($1);
- $$ = NEW_DOT3($1, new_nil(&loc), &@$);
+ $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$);
/*% %*/
/*% ripper: dot3!($1, Qnil) %*/
}
@@ -4220,24 +4433,16 @@ p_value : p_primitive
| tBDOT2 p_primitive
{
/*%%%*/
- YYLTYPE loc;
- loc.beg_pos = @1.beg_pos;
- loc.end_pos = @1.beg_pos;
-
value_expr($2);
- $$ = NEW_DOT2(new_nil(&loc), $2, &@$);
+ $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$);
/*% %*/
/*% ripper: dot2!(Qnil, $2) %*/
}
| tBDOT3 p_primitive
{
/*%%%*/
- YYLTYPE loc;
- loc.beg_pos = @1.beg_pos;
- loc.end_pos = @1.beg_pos;
-
value_expr($2);
- $$ = NEW_DOT3(new_nil(&loc), $2, &@$);
+ $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$);
/*% %*/
/*% ripper: dot3!(Qnil, $2) %*/
}
@@ -4258,17 +4463,7 @@ p_primitive : literal
/*% %*/
/*% ripper: var_ref!($1) %*/
}
- | tLAMBDA
- {
- token_info_push(p, "->", &@1);
- }
- lambda
- {
- $$ = $3;
- /*%%%*/
- nd_set_first_loc($$, @1.beg_pos);
- /*% %*/
- }
+ | lambda
;
p_variable : tIDENTIFIER
@@ -4323,7 +4518,7 @@ opt_rescue : k_rescue exc_list exc_var then
{
/*%%%*/
$$ = NEW_RESBODY($2,
- $3 ? block_append(p, node_assign(p, $3, NEW_ERRINFO(&@3), &@3), $5) : $5,
+ $3 ? block_append(p, node_assign(p, $3, NEW_ERRINFO(&@3), NO_LEX_CTXT, &@3), $5) : $5,
$6, &@$);
fixpos($$, $2?$2:$5);
/*% %*/
@@ -4835,7 +5030,9 @@ superclass : '<'
}
;
-f_arglist : '(' f_args rparen
+f_opt_paren_args: f_paren_args | none;
+
+f_paren_args : '(' f_args rparen
{
/*%%%*/
$$ = $2;
@@ -4846,42 +5043,35 @@ f_arglist : '(' f_args rparen
}
| '(' f_arg ',' args_forward rparen
{
- arg_var(p, idFWD_REST);
-#if idFWD_KWREST
- arg_var(p, idFWD_KWREST);
-#endif
- arg_var(p, idFWD_BLOCK);
+ add_forwarding_args(p);
/*%%%*/
- $$ = new_args_tail(p, Qnone, idFWD_KWREST, idFWD_BLOCK, &@4);
- $$ = new_args(p, $2, Qnone, idFWD_REST, Qnone, $$, &@4);
+ $$ = new_args_forward_def(p, $2, &@$);
/*% %*/
- /*% ripper: paren!(params_new($2, Qnone, $4, Qnone, Qnone, Qnone, Qnone)) %*/
+ /*% ripper: paren!(params!($2, Qnone, $4, Qnone, Qnone, Qnone, Qnone)) %*/
SET_LEX_STATE(EXPR_BEG);
p->command_start = TRUE;
}
| '(' args_forward rparen
{
- arg_var(p, idFWD_REST);
-#if idFWD_KWREST
- arg_var(p, idFWD_KWREST);
-#endif
- arg_var(p, idFWD_BLOCK);
+ add_forwarding_args(p);
/*%%%*/
- $$ = new_args_tail(p, Qnone, idFWD_KWREST, idFWD_BLOCK, &@2);
- $$ = new_args(p, Qnone, Qnone, idFWD_REST, Qnone, $$, &@2);
+ $$ = new_args_forward_def(p, 0, &@$);
/*% %*/
- /*% ripper: paren!(params_new(Qnone, Qnone, $2, Qnone, Qnone, Qnone, Qnone)) %*/
+ /*% ripper: paren!(params!(Qnone, Qnone, $2, Qnone, Qnone, Qnone, Qnone)) %*/
SET_LEX_STATE(EXPR_BEG);
p->command_start = TRUE;
}
+ ;
+
+f_arglist : f_paren_args
| {
- $<num>$ = p->in_kwarg;
- p->in_kwarg = 1;
+ $<ctxt>$ = p->ctxt;
+ p->ctxt.in_kwarg = 1;
SET_LEX_STATE(p->lex.state|EXPR_LABEL); /* force for args */
}
- f_args term
+ f_args term
{
- p->in_kwarg = !!$<num>1;
+ p->ctxt.in_kwarg = $<ctxt>1.in_kwarg;
$$ = $2;
SET_LEX_STATE(EXPR_BEG);
p->command_start = TRUE;
@@ -4896,14 +5086,10 @@ args_tail : f_kwarg ',' f_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, $1, Qnone, $2, &@1);
}
- | f_kwrest opt_f_block_arg
+ | f_any_kwrest opt_f_block_arg
{
$$ = new_args_tail(p, Qnone, $1, $2, &@1);
}
- | f_no_kwarg opt_f_block_arg
- {
- $$ = new_args_tail(p, Qnone, ID2VAL(idNil), $2, &@1);
- }
| f_block_arg
{
$$ = new_args_tail(p, Qnone, Qnone, $1, &@1);
@@ -4994,42 +5180,46 @@ args_forward : tBDOT3
f_bad_arg : tCONSTANT
{
+ static const char mesg[] = "formal argument cannot be a constant";
/*%%%*/
- yyerror1(&@1, "formal argument cannot be a constant");
+ yyerror1(&@1, mesg);
$$ = 0;
/*% %*/
- /*% ripper[error]: param_error!($1) %*/
+ /*% ripper[error]: param_error!(ERR_MESG(), $1) %*/
}
| tIVAR
{
+ static const char mesg[] = "formal argument cannot be an instance variable";
/*%%%*/
- yyerror1(&@1, "formal argument cannot be an instance variable");
+ yyerror1(&@1, mesg);
$$ = 0;
/*% %*/
- /*% ripper[error]: param_error!($1) %*/
+ /*% ripper[error]: param_error!(ERR_MESG(), $1) %*/
}
| tGVAR
{
+ static const char mesg[] = "formal argument cannot be a global variable";
/*%%%*/
- yyerror1(&@1, "formal argument cannot be a global variable");
+ yyerror1(&@1, mesg);
$$ = 0;
/*% %*/
- /*% ripper[error]: param_error!($1) %*/
+ /*% ripper[error]: param_error!(ERR_MESG(), $1) %*/
}
| tCVAR
{
+ static const char mesg[] = "formal argument cannot be a class variable";
/*%%%*/
- yyerror1(&@1, "formal argument cannot be a class variable");
+ yyerror1(&@1, mesg);
$$ = 0;
/*% %*/
- /*% ripper[error]: param_error!($1) %*/
+ /*% ripper[error]: param_error!(ERR_MESG(), $1) %*/
}
;
f_norm_arg : f_bad_arg
| tIDENTIFIER
{
- formal_argument(p, get_id($1));
+ formal_argument(p, $1);
p->max_numparam = ORDINAL_PARAM;
$$ = $1;
}
@@ -5090,9 +5280,8 @@ f_arg : f_arg_item
f_label : tLABEL
{
- ID id = get_id($1);
- arg_var(p, formal_argument(p, id));
- p->cur_arg = id;
+ arg_var(p, formal_argument(p, $1));
+ p->cur_arg = get_id($1);
p->max_numparam = ORDINAL_PARAM;
$$ = $1;
}
@@ -5508,7 +5697,7 @@ ripper_yylval_id(struct parser_params *p, ID x)
# define set_yylval_id(x) (void)(x)
# define set_yylval_name(x) (void)(yylval.val = ripper_yylval_id(p, x))
# define set_yylval_literal(x) add_mark_object(p, (x))
-# define set_yylval_node(x) (void)(x)
+# define set_yylval_node(x) (yylval.val = ripper_new_yylval(p, 0, 0, STR_NEW(p->lex.ptok, p->lex.pcur-p->lex.ptok)))
# define yylval_id() yylval.id
# define _cur_loc NULL_LOC /* dummy */
#endif
@@ -5574,9 +5763,6 @@ ripper_dispatch_delayed_token(struct parser_params *p, enum yytokentype t)
#define has_delayed_token(p) (!NIL_P(p->delayed.token))
#endif /* RIPPER */
-#include "ruby/regex.h"
-#include "ruby/util.h"
-
static inline int
is_identchar(const char *ptr, const char *MAYBE_UNUSED(ptr_end), rb_encoding *enc)
{
@@ -5642,6 +5828,26 @@ token_info_pop(struct parser_params *p, const char *token, const rb_code_locatio
}
static void
+token_info_drop(struct parser_params *p, const char *token, rb_code_position_t beg_pos)
+{
+ token_info *ptinfo_beg = p->token_info;
+
+ if (!ptinfo_beg) return;
+ p->token_info = ptinfo_beg->next;
+
+ if (ptinfo_beg->beg.lineno != beg_pos.lineno ||
+ ptinfo_beg->beg.column != beg_pos.column ||
+ strcmp(ptinfo_beg->token, token)) {
+ compile_error(p, "token position mismatch: %d:%d:%s expected but %d:%d:%s",
+ beg_pos.lineno, beg_pos.column, token,
+ ptinfo_beg->beg.lineno, ptinfo_beg->beg.column,
+ ptinfo_beg->token);
+ }
+
+ ruby_sized_xfree(ptinfo_beg, sizeof(*ptinfo_beg));
+}
+
+static void
token_info_warn(struct parser_params *p, const char *token, token_info *ptinfo_beg, int same, const rb_code_location_t *loc)
{
token_info ptinfo_end_body, *ptinfo_end = &ptinfo_end_body;
@@ -5882,7 +6088,7 @@ vtable_free_gen(struct parser_params *p, int line, const char *name,
if (tbl->tbl) {
ruby_sized_xfree(tbl->tbl, tbl->capa * sizeof(ID));
}
- ruby_sized_xfree(tbl, sizeof(tbl));
+ ruby_sized_xfree(tbl, sizeof(*tbl));
}
}
#define vtable_free(tbl) vtable_free_gen(p, __LINE__, #tbl, tbl)
@@ -5980,7 +6186,7 @@ yycompile0(VALUE arg)
if (!compile_for_eval && !NIL_P(p->ruby_sourcefile_string)) {
p->debug_lines = debug_lines(p->ruby_sourcefile_string);
if (p->debug_lines && p->ruby_sourceline > 0) {
- VALUE str = STR_NEW0();
+ VALUE str = rb_default_rs;
n = p->ruby_sourceline;
do {
rb_ary_push(p->debug_lines, str);
@@ -6288,11 +6494,6 @@ parser_cr(struct parser_params *p, int c)
p->lex.pcur++;
c = '\n';
}
- else if (!p->cr_seen) {
- p->cr_seen = TRUE;
- /* carried over with p->lex.nextline for nextc() */
- rb_warn0("encountered \\r in middle of line, treated as a mere space");
- }
return c;
}
@@ -6589,7 +6790,11 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp)
goto eof;
}
if ((c = nextc(p)) == '\\') {
- if (peek(p, 'u')) goto eof;
+ switch (peekc(p)) {
+ case 'u': case 'U':
+ nextc(p);
+ goto eof;
+ }
return read_escape(p, flags|ESCAPE_META, encp) | 0x80;
}
else if (c == -1 || !ISASCII(c)) goto eof;
@@ -6614,7 +6819,11 @@ read_escape(struct parser_params *p, int flags, rb_encoding **encp)
case 'c':
if (flags & ESCAPE_CONTROL) goto eof;
if ((c = nextc(p))== '\\') {
- if (peek(p, 'u')) goto eof;
+ switch (peekc(p)) {
+ case 'u': case 'U':
+ nextc(p);
+ goto eof;
+ }
c = read_escape(p, flags|ESCAPE_CONTROL, encp);
}
else if (c == '?')
@@ -7672,7 +7881,12 @@ static int
arg_ambiguous(struct parser_params *p, char c)
{
#ifndef RIPPER
- rb_warning1("ambiguous first argument; put parentheses or a space even after `%c' operator", WARN_I(c));
+ if (c == '/') {
+ rb_warning1("ambiguity between regexp and two divisions: wrap regexp in parentheses or add a space after `%c' operator", WARN_I(c));
+ }
+ else {
+ rb_warning1("ambiguous first argument; put parentheses or a space even after `%c' operator", WARN_I(c));
+ }
#else
dispatch1(arg_ambiguous, rb_usascii_str_new(&c, 1));
#endif
@@ -7680,33 +7894,36 @@ arg_ambiguous(struct parser_params *p, char c)
}
static ID
+#ifndef RIPPER
formal_argument(struct parser_params *p, ID lhs)
+#else
+formal_argument(struct parser_params *p, VALUE lhs)
+#endif
{
- switch (id_type(lhs)) {
+ switch (id_type(get_id(lhs))) {
case ID_LOCAL:
break;
#ifndef RIPPER
+# define ERR(mesg) yyerror0(mesg)
+#else
+# define ERR(mesg) (dispatch2(param_error, WARN_S(mesg), lhs), ripper_error(p))
+#endif
case ID_CONST:
- yyerror0("formal argument cannot be a constant");
+ ERR("formal argument cannot be a constant");
return 0;
case ID_INSTANCE:
- yyerror0("formal argument cannot be an instance variable");
+ ERR("formal argument cannot be an instance variable");
return 0;
case ID_GLOBAL:
- yyerror0("formal argument cannot be a global variable");
+ ERR("formal argument cannot be a global variable");
return 0;
case ID_CLASS:
- yyerror0("formal argument cannot be a class variable");
+ ERR("formal argument cannot be a class variable");
return 0;
default:
- yyerror0("formal argument must be local variable");
+ ERR("formal argument must be local variable");
return 0;
-#else
- default:
- lhs = dispatch1(param_error, lhs);
- ripper_error(p);
- return 0;
-#endif
+#undef ERR
}
shadowing_lvar(p, lhs);
return lhs;
@@ -7786,6 +8003,8 @@ comment_at_top(struct parser_params *p)
typedef long (*rb_magic_comment_length_t)(struct parser_params *p, const char *name, long len);
typedef void (*rb_magic_comment_setter_t)(struct parser_params *p, const char *name, const char *val);
+static int parser_invalid_pragma_value(struct parser_params *p, const char *name, const char *val);
+
static void
magic_comment_encoding(struct parser_params *p, const char *name, const char *val)
{
@@ -7800,17 +8019,23 @@ parser_get_bool(struct parser_params *p, const char *name, const char *val)
{
switch (*val) {
case 't': case 'T':
- if (strcasecmp(val, "true") == 0) {
+ if (STRCASECMP(val, "true") == 0) {
return TRUE;
}
break;
case 'f': case 'F':
- if (strcasecmp(val, "false") == 0) {
+ if (STRCASECMP(val, "false") == 0) {
return FALSE;
}
break;
}
- rb_compile_warning(p->ruby_sourcefile, p->ruby_sourceline, "invalid value for %s: %s", name, val);
+ return parser_invalid_pragma_value(p, name, val);
+}
+
+static int
+parser_invalid_pragma_value(struct parser_params *p, const char *name, const char *val)
+{
+ rb_warning2("invalid value for %s: %s", WARN_S(name), WARN_S(val));
return -1;
}
@@ -7840,6 +8065,43 @@ parser_set_compile_option_flag(struct parser_params *p, const char *name, const
(b ? Qtrue : Qfalse));
}
+static void
+parser_set_shareable_constant_value(struct parser_params *p, const char *name, const char *val)
+{
+ for (const char *s = p->lex.pbeg, *e = p->lex.pcur; s < e; ++s) {
+ if (*s == ' ' || *s == '\t') continue;
+ if (*s == '#') break;
+ rb_warning1("`%s' is ignored unless in comment-only line", WARN_S(name));
+ return;
+ }
+
+ switch (*val) {
+ case 'n': case 'N':
+ if (STRCASECMP(val, "none") == 0) {
+ p->ctxt.shareable_constant_value = shareable_none;
+ return;
+ }
+ break;
+ case 'l': case 'L':
+ if (STRCASECMP(val, "literal") == 0) {
+ p->ctxt.shareable_constant_value = shareable_literal;
+ return;
+ }
+ break;
+ case 'e': case 'E':
+ if (STRCASECMP(val, "experimental_copy") == 0) {
+ p->ctxt.shareable_constant_value = shareable_copy;
+ return;
+ }
+ if (STRCASECMP(val, "experimental_everything") == 0) {
+ p->ctxt.shareable_constant_value = shareable_everything;
+ return;
+ }
+ break;
+ }
+ parser_invalid_pragma_value(p, name, val);
+}
+
# if WARN_PAST_SCOPE
static void
parser_set_past_scope(struct parser_params *p, const char *name, const char *val)
@@ -7859,6 +8121,7 @@ static const struct magic_comment magic_comments[] = {
{"coding", magic_comment_encoding, parser_encode_length},
{"encoding", magic_comment_encoding, parser_encode_length},
{"frozen_string_literal", parser_set_compile_option_flag},
+ {"shareable_constant_value", parser_set_shareable_constant_value},
{"warn_indent", parser_set_token_info},
# if WARN_PAST_SCOPE
{"warn_past_scope", parser_set_past_scope},
@@ -8427,16 +8690,22 @@ parse_percent(struct parser_params *p, const int space_seen, const enum lex_stat
quotation:
if (c == -1 || !ISALNUM(c)) {
term = c;
+ if (!ISASCII(c)) goto unknown;
c = 'Q';
}
else {
term = nextc(p);
if (rb_enc_isalnum(term, p->enc) || !parser_isascii(p)) {
+ unknown:
+ pushback(p, term);
+ c = parser_precise_mbclen(p, p->lex.pcur);
+ if (c < 0) return 0;
+ p->lex.pcur += c;
yyerror0("unknown type of %string");
return 0;
}
}
- if (c == -1 || term == -1) {
+ if (term == -1) {
compile_error(p, "unterminated quoted string meets end of file");
return 0;
}
@@ -8626,7 +8895,8 @@ parse_gvar(struct parser_params *p, const enum lex_state_e last_state)
pushback(p, c);
if (IS_lex_state_for(last_state, EXPR_FNAME)) goto gvar;
tokfix(p);
- set_yylval_node(NEW_NTH_REF(parse_numvar(p), &_cur_loc));
+ c = parse_numvar(p);
+ set_yylval_node(NEW_NTH_REF(c, &_cur_loc));
return tNTH_REF;
default:
@@ -8862,7 +9132,14 @@ parser_yylex(struct parser_params *p)
return 0;
/* white spaces */
- case ' ': case '\t': case '\f': case '\r':
+ case '\r':
+ if (!p->cr_seen) {
+ p->cr_seen = TRUE;
+ /* carried over with p->lex.nextline for nextc() */
+ rb_warn0("encountered \\r in middle of line, treated as a mere space");
+ }
+ /* fall through */
+ case ' ': case '\t': case '\f':
case '\13': /* '\v' */
space_seen = 1;
#ifdef RIPPER
@@ -8902,7 +9179,7 @@ parser_yylex(struct parser_params *p)
dispatch_scan_event(p, tIGNORED_NL);
}
fallthru = FALSE;
- if (!c && p->in_kwarg) {
+ if (!c && p->ctxt.in_kwarg) {
goto normal_newline;
}
goto retry;
@@ -9271,6 +9548,10 @@ parser_yylex(struct parser_params *p)
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);
@@ -9427,6 +9708,7 @@ parser_yylex(struct parser_params *p)
p->lex.paren_nest++;
if (IS_AFTER_OPERATOR()) {
if ((c = nextc(p)) == ']') {
+ p->lex.paren_nest--;
SET_LEX_STATE(EXPR_ARG);
if ((c = nextc(p)) == '=') {
return tASET;
@@ -9729,12 +10011,24 @@ literal_concat0(struct parser_params *p, VALUE head, VALUE tail)
return 1;
}
+static VALUE
+string_literal_head(enum node_type htype, NODE *head)
+{
+ if (htype != NODE_DSTR) return Qfalse;
+ if (head->nd_next) {
+ head = head->nd_next->nd_end->nd_head;
+ if (!head || nd_type(head) != NODE_STR) return Qfalse;
+ }
+ const VALUE lit = head->nd_lit;
+ ASSUME(lit != Qfalse);
+ return lit;
+}
+
/* concat two string literals */
static NODE *
literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *loc)
{
enum node_type htype;
- NODE *headlast;
VALUE lit;
if (!head) return tail;
@@ -9742,9 +10036,7 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l
htype = nd_type(head);
if (htype == NODE_EVSTR) {
- NODE *node = NEW_DSTR(STR_NEW0(), loc);
- RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit);
- head = list_append(p, node, head);
+ head = new_dstr(p, head, loc);
htype = NODE_DSTR;
}
if (p->heredoc_indent > 0) {
@@ -9759,10 +10051,8 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l
}
switch (nd_type(tail)) {
case NODE_STR:
- if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) &&
- nd_type(headlast) == NODE_STR) {
+ if ((lit = string_literal_head(htype, head)) != Qfalse) {
htype = NODE_STR;
- lit = headlast->nd_lit;
}
else {
lit = head->nd_lit;
@@ -9792,13 +10082,16 @@ literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *l
else if (NIL_P(tail->nd_lit)) {
append:
head->nd_alen += tail->nd_alen - 1;
- head->nd_next->nd_end->nd_next = tail->nd_next;
- head->nd_next->nd_end = tail->nd_next->nd_end;
+ if (!head->nd_next) {
+ head->nd_next = tail->nd_next;
+ }
+ else if (tail->nd_next) {
+ head->nd_next->nd_end->nd_next = tail->nd_next;
+ head->nd_next->nd_end = tail->nd_next->nd_end;
+ }
rb_discard_node(p, tail);
}
- else if (htype == NODE_DSTR && (headlast = head->nd_next->nd_end->nd_head) &&
- nd_type(headlast) == NODE_STR) {
- lit = headlast->nd_lit;
+ else if ((lit = string_literal_head(htype, head)) != Qfalse) {
if (!literal_concat0(p, lit, tail->nd_lit))
goto error;
tail->nd_lit = Qnil;
@@ -9824,9 +10117,7 @@ static NODE *
evstr2dstr(struct parser_params *p, NODE *node)
{
if (nd_type(node) == NODE_EVSTR) {
- NODE * dstr = NEW_DSTR(STR_NEW0(), &node->nd_loc);
- RB_OBJ_WRITTEN(p->ast, Qnil, dstr->nd_lit);
- node = list_append(p, dstr, node);
+ node = new_dstr(p, node, &node->nd_loc);
}
return node;
}
@@ -9838,7 +10129,9 @@ new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc)
if (node) {
switch (nd_type(node)) {
- case NODE_STR: case NODE_DSTR: case NODE_EVSTR:
+ case NODE_STR:
+ nd_set_type(node, NODE_DSTR);
+ case NODE_DSTR: case NODE_EVSTR:
return node;
}
}
@@ -9846,6 +10139,15 @@ new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc)
}
static NODE *
+new_dstr(struct parser_params *p, NODE *node, const YYLTYPE *loc)
+{
+ VALUE lit = STR_NEW0();
+ NODE *dstr = NEW_DSTR(lit, loc);
+ RB_OBJ_WRITTEN(p->ast, Qnil, lit);
+ return list_append(p, dstr, node);
+}
+
+static NODE *
call_bin_op(struct parser_params *p, NODE *recv, ID id, NODE *arg1,
const YYLTYPE *op_loc, const YYLTYPE *loc)
{
@@ -9946,19 +10248,6 @@ past_dvar_p(struct parser_params *p, ID id)
}
# endif
-/* As Ripper#warn does not have arguments for the location, so the
- * following messages cannot be separated */
-#define WARN_LOCATION(type) do { \
- if (p->warn_location) { \
- int line; \
- VALUE file = rb_source_location(&line); \
- rb_warn3(type" in eval may not return location in binding;" \
- " use Binding#source_location instead\n" \
- "%"PRIsWARN":%d: warning: in `%"PRIsWARN"'", \
- file, WARN_I(line), rb_id2str(rb_frame_this_func())); \
- } \
-} while (0)
-
static int
numparam_nested_p(struct parser_params *p)
{
@@ -9992,7 +10281,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc)
case keyword_false:
return NEW_FALSE(loc);
case keyword__FILE__:
- WARN_LOCATION("__FILE__");
{
VALUE file = p->ruby_sourcefile_string;
if (NIL_P(file))
@@ -10004,7 +10292,6 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc)
}
return node;
case keyword__LINE__:
- WARN_LOCATION("__LINE__");
return NEW_LIT(INT2FIX(p->tokline), loc);
case keyword__ENCODING__:
node = NEW_LIT(rb_enc_from_encoding(p->enc), loc);
@@ -10042,7 +10329,7 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc)
return node;
}
# if WARN_PAST_SCOPE
- if (!p->in_defined && RTEST(ruby_verbose) && past_dvar_p(p, id)) {
+ if (!p->ctxt.in_defined && RTEST(ruby_verbose) && past_dvar_p(p, id)) {
rb_warning1("possible reference to past scope - %"PRIsWARN, rb_id2str(id));
}
# endif
@@ -10100,12 +10387,17 @@ new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc)
static NODE*
symbol_append(struct parser_params *p, NODE *symbols, NODE *symbol)
{
- if (nd_type(symbol) == NODE_DSTR) {
+ enum node_type type = nd_type(symbol);
+ switch (type) {
+ case NODE_DSTR:
nd_set_type(symbol, NODE_DSYM);
- }
- else {
+ break;
+ case NODE_STR:
nd_set_type(symbol, NODE_LIT);
RB_OBJ_WRITTEN(p->ast, Qnil, symbol->nd_lit = rb_str_intern(symbol->nd_lit));
+ break;
+ default:
+ compile_error(p, "unexpected node as symbol: %s", ruby_node_name(type));
}
return list_append(p, symbols, symbol);
}
@@ -10141,8 +10433,10 @@ new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc)
node->nd_cflag = options & RE_OPTION_MASK;
if (!NIL_P(node->nd_lit)) reg_fragment_check(p, node->nd_lit, options);
for (list = (prev = node)->nd_next; list; list = list->nd_next) {
- if (nd_type(list->nd_head) == NODE_STR) {
- VALUE tail = list->nd_head->nd_lit;
+ NODE *frag = list->nd_head;
+ enum node_type type = nd_type(frag);
+ if (type == NODE_STR || (type == NODE_DSTR && !frag->nd_next)) {
+ VALUE tail = frag->nd_lit;
if (reg_fragment_check(p, tail, options) && prev && !NIL_P(prev->nd_lit)) {
VALUE lit = prev == node ? prev->nd_lit : prev->nd_head->nd_lit;
if (!literal_concat0(p, lit, tail)) {
@@ -10383,8 +10677,8 @@ rb_parser_fatal(struct parser_params *p, const char *fmt, ...)
rb_str_resize(mesg, 0);
append_bitstack_value(p->cmdarg_stack, mesg);
compile_error(p, "cmdarg_stack: %"PRIsVALUE, mesg);
- if (p->debug_output == rb_stdout)
- p->debug_output = rb_stderr;
+ if (p->debug_output == rb_ractor_stdout())
+ p->debug_output = rb_ractor_stderr();
p->debug = TRUE;
}
@@ -10516,7 +10810,7 @@ assignable0(struct parser_params *p, ID id, const char **err)
case ID_GLOBAL: return NODE_GASGN;
case ID_INSTANCE: return NODE_IASGN;
case ID_CONST:
- if (!p->in_def) return NODE_CDECL;
+ if (!p->ctxt.in_def) return NODE_CDECL;
*err = "dynamic constant assignment";
return -1;
case ID_CLASS: return NODE_CVASGN;
@@ -10550,7 +10844,7 @@ assignable(struct parser_params *p, VALUE lhs)
{
const char *err = 0;
assignable0(p, get_id(lhs), &err);
- if (err) lhs = assign_error(p, lhs);
+ if (err) lhs = assign_error(p, err, lhs);
return lhs;
}
#endif
@@ -10644,7 +10938,17 @@ rb_backref_error(struct parser_params *p, NODE *node)
break;
}
}
+#else
+static VALUE
+backref_error(struct parser_params *p, NODE *ref, VALUE expr)
+{
+ VALUE mesg = rb_str_new_cstr("Can't set variable ");
+ rb_str_append(mesg, ref->nd_cval);
+ return dispatch2(assign_error, mesg, expr);
+}
+#endif
+#ifndef RIPPER
static NODE *
arg_append(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc)
{
@@ -10751,18 +11055,263 @@ mark_lvar_used(struct parser_params *p, NODE *rhs)
}
static NODE *
-node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, const YYLTYPE *loc)
+const_decl_path(struct parser_params *p, NODE **dest)
+{
+ NODE *n = *dest;
+ if (nd_type(n) != NODE_CALL) {
+ const YYLTYPE *loc = &n->nd_loc;
+ VALUE path;
+ if (n->nd_vid) {
+ path = rb_id2str(n->nd_vid);
+ }
+ else {
+ n = n->nd_else;
+ path = rb_ary_new();
+ for (; n && nd_type(n) == NODE_COLON2; n = n->nd_head) {
+ rb_ary_push(path, rb_id2str(n->nd_mid));
+ }
+ if (n && nd_type(n) == NODE_CONST) {
+ // Const::Name
+ rb_ary_push(path, rb_id2str(n->nd_vid));
+ }
+ else if (n && nd_type(n) == NODE_COLON3) {
+ // ::Const::Name
+ rb_ary_push(path, rb_str_new(0, 0));
+ }
+ else {
+ // expression::Name
+ rb_ary_push(path, rb_str_new_cstr("..."));
+ }
+ path = rb_ary_join(rb_ary_reverse(path), rb_str_new_cstr("::"));
+ path = rb_fstring(path);
+ }
+ *dest = n = NEW_LIT(path, loc);
+ }
+ return n;
+}
+
+extern VALUE rb_mRubyVMFrozenCore;
+
+static NODE *
+make_shareable_node(struct parser_params *p, NODE *value, bool copy, const YYLTYPE *loc)
+{
+ NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc);
+
+ if (copy) {
+ return NEW_CALL(fcore, rb_intern("make_shareable_copy"),
+ NEW_LIST(value, loc), loc);
+ }
+ else {
+ return NEW_CALL(fcore, rb_intern("make_shareable"),
+ NEW_LIST(value, loc), loc);
+ }
+}
+
+static NODE *
+ensure_shareable_node(struct parser_params *p, NODE **dest, NODE *value, const YYLTYPE *loc)
+{
+ NODE *fcore = NEW_LIT(rb_mRubyVMFrozenCore, loc);
+ NODE *args = NEW_LIST(value, loc);
+ args = list_append(p, args, const_decl_path(p, dest));
+ return NEW_CALL(fcore, rb_intern("ensure_shareable"), args, loc);
+}
+
+static int is_static_content(NODE *node);
+
+static VALUE
+shareable_literal_value(NODE *node)
+{
+ if (!node) return Qnil;
+ enum node_type type = nd_type(node);
+ switch (type) {
+ case NODE_TRUE:
+ return Qtrue;
+ case NODE_FALSE:
+ return Qfalse;
+ case NODE_NIL:
+ return Qnil;
+ case NODE_LIT:
+ return node->nd_lit;
+ default:
+ return Qundef;
+ }
+}
+
+#ifndef SHAREABLE_BARE_EXPRESSION
+#define SHAREABLE_BARE_EXPRESSION 1
+#endif
+
+static NODE *
+shareable_literal_constant(struct parser_params *p, enum shareability shareable,
+ NODE **dest, NODE *value, const YYLTYPE *loc, size_t level)
+{
+# define shareable_literal_constant_next(n) \
+ shareable_literal_constant(p, shareable, dest, (n), &(n)->nd_loc, level+1)
+ VALUE lit = Qnil;
+
+ if (!value) return 0;
+ enum node_type type = nd_type(value);
+ switch (type) {
+ case NODE_TRUE:
+ case NODE_FALSE:
+ case NODE_NIL:
+ case NODE_LIT:
+ return value;
+
+ case NODE_DSTR:
+ if (shareable == shareable_literal) {
+ value = NEW_CALL(value, idUMinus, 0, loc);
+ }
+ return value;
+
+ case NODE_STR:
+ lit = rb_fstring(value->nd_lit);
+ nd_set_type(value, NODE_LIT);
+ RB_OBJ_WRITE(p->ast, &value->nd_lit, lit);
+ return value;
+
+ case NODE_ZLIST:
+ lit = rb_ary_new();
+ OBJ_FREEZE_RAW(lit);
+ return NEW_LIT(lit, loc);
+
+ case NODE_LIST:
+ lit = rb_ary_new();
+ for (NODE *n = value; n; n = n->nd_next) {
+ NODE *elt = n->nd_head;
+ if (elt) {
+ elt = shareable_literal_constant_next(elt);
+ if (elt) {
+ n->nd_head = elt;
+ }
+ else if (RTEST(lit)) {
+ rb_ary_clear(lit);
+ lit = Qfalse;
+ }
+ }
+ if (RTEST(lit)) {
+ VALUE e = shareable_literal_value(elt);
+ if (e != Qundef) {
+ rb_ary_push(lit, e);
+ }
+ else {
+ rb_ary_clear(lit);
+ lit = Qnil; /* make shareable at runtime */
+ }
+ }
+ }
+ break;
+
+ case NODE_HASH:
+ if (!value->nd_brace) return 0;
+ lit = rb_hash_new();
+ for (NODE *n = value->nd_head; n; n = n->nd_next->nd_next) {
+ NODE *key = n->nd_head;
+ NODE *val = n->nd_next->nd_head;
+ if (key) {
+ key = shareable_literal_constant_next(key);
+ if (key) {
+ n->nd_head = key;
+ }
+ else if (RTEST(lit)) {
+ rb_hash_clear(lit);
+ lit = Qfalse;
+ }
+ }
+ if (val) {
+ val = shareable_literal_constant_next(val);
+ if (val) {
+ n->nd_next->nd_head = val;
+ }
+ else if (RTEST(lit)) {
+ rb_hash_clear(lit);
+ lit = Qfalse;
+ }
+ }
+ if (RTEST(lit)) {
+ VALUE k = shareable_literal_value(key);
+ VALUE v = shareable_literal_value(val);
+ if (k != Qundef && v != Qundef) {
+ rb_hash_aset(lit, k, v);
+ }
+ else {
+ rb_hash_clear(lit);
+ lit = Qnil; /* make shareable at runtime */
+ }
+ }
+ }
+ break;
+
+ default:
+ if (shareable == shareable_literal &&
+ (SHAREABLE_BARE_EXPRESSION || level > 0)) {
+ return ensure_shareable_node(p, dest, value, loc);
+ }
+ return 0;
+ }
+
+ /* Array or Hash */
+ if (!lit) return 0;
+ if (NIL_P(lit)) {
+ // if shareable_literal, all elements should have been ensured
+ // as shareable
+ value = make_shareable_node(p, value, false, loc);
+ }
+ else {
+ value = NEW_LIT(rb_ractor_make_shareable(lit), loc);
+ }
+
+ return value;
+# undef shareable_literal_constant_next
+}
+
+static NODE *
+shareable_constant_value(struct parser_params *p, enum shareability shareable,
+ NODE *lhs, NODE *value, const YYLTYPE *loc)
+{
+ if (!value) return 0;
+ switch (shareable) {
+ case shareable_none:
+ return value;
+
+ case shareable_literal:
+ {
+ NODE *lit = shareable_literal_constant(p, shareable, &lhs, value, loc, 0);
+ if (lit) return lit;
+ return value;
+ }
+ break;
+
+ case shareable_copy:
+ case shareable_everything:
+ {
+ NODE *lit = shareable_literal_constant(p, shareable, &lhs, value, loc, 0);
+ if (lit) return lit;
+ return make_shareable_node(p, value, shareable == shareable_copy, loc);
+ }
+ break;
+
+ default:
+ UNREACHABLE_RETURN(0);
+ }
+}
+
+static NODE *
+node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc)
{
if (!lhs) return 0;
switch (nd_type(lhs)) {
+ case NODE_CDECL:
+ rhs = shareable_constant_value(p, ctxt.shareable_constant_value, lhs, rhs, loc);
+ /* fallthru */
+
case NODE_GASGN:
case NODE_IASGN:
case NODE_LASGN:
case NODE_DASGN:
case NODE_DASGN_CURR:
case NODE_MASGN:
- case NODE_CDECL:
case NODE_CVASGN:
lhs->nd_value = rhs;
nd_set_loc(lhs, loc);
@@ -11120,7 +11669,8 @@ range_op(struct parser_params *p, NODE *node, const YYLTYPE *loc)
value_expr(node);
if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
if (!e_option_supplied(p)) parser_warn(p, node, "integer literal in flip-flop");
- return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(rb_intern("$."), loc), loc), loc);
+ ID lineno = rb_intern("$.");
+ return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(lineno, loc), loc), loc);
}
return cond0(p, node, COND_IN_FF, loc);
}
@@ -11195,6 +11745,13 @@ method_cond(struct parser_params *p, NODE *node, const YYLTYPE *loc)
}
static NODE*
+new_nil_at(struct parser_params *p, const rb_code_position_t *pos)
+{
+ YYLTYPE loc = {*pos, *pos};
+ return NEW_NIL(&loc);
+}
+
+static NODE*
new_if(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc)
{
if (!cc) return right;
@@ -11285,7 +11842,7 @@ negate_lit(struct parser_params *p, VALUE lit)
lit = rb_big_norm(lit);
break;
case T_RATIONAL:
- RRATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num));
+ RATIONAL_SET_NUM(lit, negate_lit(p, RRATIONAL(lit)->num));
break;
case T_COMPLEX:
RCOMPLEX_SET_REAL(lit, negate_lit(p, RCOMPLEX(lit)->real));
@@ -11355,7 +11912,7 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N
}
static NODE*
-new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block, const YYLTYPE *loc)
+new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block, const YYLTYPE *kw_rest_loc)
{
int saved_line = p->ruby_sourceline;
NODE *node;
@@ -11404,14 +11961,14 @@ new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block,
if (kw_rest_arg) arg_var(p, kw_rest_arg);
if (block) arg_var(p, block);
- args->kw_rest_arg = NEW_DVAR(kw_rest_arg, loc);
+ args->kw_rest_arg = NEW_DVAR(kw_rest_arg, kw_rest_loc);
args->kw_rest_arg->nd_cflag = kw_bits;
}
else if (kw_rest_arg == idNil) {
args->no_kwarg = 1;
}
else if (kw_rest_arg) {
- args->kw_rest_arg = NEW_DVAR(kw_rest_arg, loc);
+ args->kw_rest_arg = NEW_DVAR(kw_rest_arg, kw_rest_loc);
}
p->ruby_sourceline = saved_line;
@@ -11459,8 +12016,7 @@ new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID
VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer();
struct rb_ary_pattern_info *apinfo = ZALLOC(struct rb_ary_pattern_info);
rb_imemo_tmpbuf_set_ptr(tmpbuf, apinfo);
- node = NEW_NODE(NODE_ARYPTN, 0, 0, apinfo, loc);
- apinfo->imemo = tmpbuf;
+ node = NEW_NODE(NODE_ARYPTN, 0, tmpbuf, apinfo, loc);
RB_OBJ_WRITTEN(p->ast, Qnil, tmpbuf);
apinfo->pre_args = pre_args;
@@ -11484,6 +12040,33 @@ new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, ID
}
static NODE*
+new_find_pattern(struct parser_params *p, NODE *constant, NODE *fndptn, const YYLTYPE *loc)
+{
+ fndptn->nd_pconst = constant;
+
+ return fndptn;
+}
+
+static NODE*
+new_find_pattern_tail(struct parser_params *p, ID pre_rest_arg, NODE *args, ID post_rest_arg, const YYLTYPE *loc)
+{
+ int saved_line = p->ruby_sourceline;
+ NODE *node;
+ VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer();
+ struct rb_fnd_pattern_info *fpinfo = ZALLOC(struct rb_fnd_pattern_info);
+ rb_imemo_tmpbuf_set_ptr(tmpbuf, fpinfo);
+ node = NEW_NODE(NODE_FNDPTN, 0, tmpbuf, fpinfo, loc);
+ RB_OBJ_WRITTEN(p->ast, Qnil, tmpbuf);
+
+ fpinfo->pre_rest_arg = pre_rest_arg ? assignable(p, pre_rest_arg, 0, loc) : NODE_SPECIAL_NO_NAME_REST;
+ fpinfo->args = args;
+ fpinfo->post_rest_arg = post_rest_arg ? assignable(p, post_rest_arg, 0, loc) : NODE_SPECIAL_NO_NAME_REST;
+
+ p->ruby_sourceline = saved_line;
+ return node;
+}
+
+static NODE*
new_hash_pattern(struct parser_params *p, NODE *constant, NODE *hshptn, const YYLTYPE *loc)
{
hshptn->nd_pconst = constant;
@@ -11512,14 +12095,15 @@ new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, co
return node;
}
-static NODE *
-new_case3(struct parser_params *p, NODE *val, NODE *pat, const YYLTYPE *loc)
+static void
+warn_one_line_pattern_matching(struct parser_params *p, NODE *node, NODE *pattern, bool right_assign)
{
- NODE *node = NEW_CASE3(val, pat, loc);
+ enum node_type type;
+ type = nd_type(pattern);
- if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL))
- rb_warn0L(nd_line(node), "Pattern matching is experimental, and the behavior may change in future versions of Ruby!");
- return node;
+ if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL) &&
+ !(right_assign && (type == NODE_LASGN || type == NODE_DASGN || type == NODE_DASGN_CURR)))
+ rb_warn0L_experimental(nd_line(node), "One-line pattern matching is experimental, and the behavior may change in future versions of Ruby!");
}
static NODE*
@@ -11644,14 +12228,27 @@ new_unique_key_hash(struct parser_params *p, NODE *hash, const YYLTYPE *loc)
#ifndef RIPPER
static NODE *
-new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYPE *loc)
+new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc)
{
NODE *asgn;
if (lhs) {
ID vid = lhs->nd_vid;
YYLTYPE lhs_loc = lhs->nd_loc;
+ int shareable = ctxt.shareable_constant_value;
+ if (shareable) {
+ switch (nd_type(lhs)) {
+ case NODE_CDECL:
+ case NODE_COLON2:
+ case NODE_COLON3:
+ break;
+ default:
+ shareable = 0;
+ break;
+ }
+ }
if (op == tOROP) {
+ rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
lhs->nd_value = rhs;
nd_set_loc(lhs, loc);
asgn = NEW_OP_ASGN_OR(gettable(p, vid, &lhs_loc), lhs, loc);
@@ -11665,13 +12262,20 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYP
}
}
else if (op == tANDOP) {
+ if (shareable) {
+ rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
+ }
lhs->nd_value = rhs;
nd_set_loc(lhs, loc);
asgn = NEW_OP_ASGN_AND(gettable(p, vid, &lhs_loc), lhs, loc);
}
else {
asgn = lhs;
- asgn->nd_value = NEW_CALL(gettable(p, vid, &lhs_loc), op, NEW_LIST(rhs, &rhs->nd_loc), loc);
+ rhs = NEW_CALL(gettable(p, vid, &lhs_loc), op, NEW_LIST(rhs, &rhs->nd_loc), loc);
+ if (shareable) {
+ rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
+ }
+ asgn->nd_value = rhs;
nd_set_loc(asgn, loc);
}
}
@@ -11711,11 +12315,12 @@ new_attr_op_assign(struct parser_params *p, NODE *lhs,
}
static NODE *
-new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const YYLTYPE *loc)
+new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_context ctxt, const YYLTYPE *loc)
{
NODE *asgn;
if (lhs) {
+ rhs = shareable_constant_value(p, ctxt.shareable_constant_value, lhs, rhs, loc);
asgn = NEW_OP_CDECL(lhs, op, rhs, loc);
}
else {
@@ -11728,7 +12333,7 @@ new_const_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, const
static NODE *
const_decl(struct parser_params *p, NODE *path, const YYLTYPE *loc)
{
- if (p->in_def) {
+ if (p->ctxt.in_def) {
yyerror1(loc, "dynamic constant assignment");
}
return NEW_CDECL(0, 0, (path), loc);
@@ -11737,17 +12342,16 @@ const_decl(struct parser_params *p, NODE *path, const YYLTYPE *loc)
static VALUE
const_decl(struct parser_params *p, VALUE path)
{
- if (p->in_def) {
- path = dispatch1(assign_error, path);
- ripper_error(p);
+ if (p->ctxt.in_def) {
+ path = assign_error(p, "dynamic constant assignment", path);
}
return path;
}
static VALUE
-assign_error(struct parser_params *p, VALUE a)
+assign_error(struct parser_params *p, const char *mesg, VALUE a)
{
- a = dispatch1(assign_error, a);
+ a = dispatch2(assign_error, ERR_MESG(), a);
ripper_error(p);
return a;
}
@@ -11900,8 +12504,8 @@ static void
numparam_name(struct parser_params *p, ID id)
{
if (!NUMPARAM_ID_P(id)) return;
- rb_warn1("`_%d' is reserved for numbered parameter; consider another name",
- WARN_I(NUMPARAM_ID_TO_IDX(id)));
+ compile_error(p, "_%d is reserved for numbered parameter",
+ NUMPARAM_ID_TO_IDX(id));
}
static void
@@ -11955,6 +12559,52 @@ local_id(struct parser_params *p, ID id)
return local_id_ref(p, id, NULL);
}
+static int
+check_forwarding_args(struct parser_params *p)
+{
+ if (local_id(p, idFWD_REST) &&
+#if idFWD_KWREST
+ local_id(p, idFWD_KWREST) &&
+#endif
+ local_id(p, idFWD_BLOCK)) return TRUE;
+ compile_error(p, "unexpected ...");
+ return FALSE;
+}
+
+static void
+add_forwarding_args(struct parser_params *p)
+{
+ arg_var(p, idFWD_REST);
+#if idFWD_KWREST
+ arg_var(p, idFWD_KWREST);
+#endif
+ arg_var(p, idFWD_BLOCK);
+}
+
+#ifndef RIPPER
+static NODE *
+new_args_forward_call(struct parser_params *p, NODE *leading, const YYLTYPE *loc, const YYLTYPE *argsloc)
+{
+ NODE *splat = NEW_SPLAT(NEW_LVAR(idFWD_REST, loc), loc);
+#if idFWD_KWREST
+ NODE *kwrest = list_append(p, NEW_LIST(0, loc), NEW_LVAR(idFWD_KWREST, loc));
+#endif
+ NODE *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, loc), loc);
+ NODE *args = leading ? rest_arg_append(p, leading, splat, argsloc) : splat;
+#if idFWD_KWREST
+ args = arg_append(p, splat, new_hash(p, kwrest, loc), loc);
+#endif
+ return arg_blk_pass(args, block);
+}
+
+static NODE *
+new_args_forward_def(struct parser_params *p, NODE *leading, const YYLTYPE *loc)
+{
+ NODE *n = new_args_tail(p, Qnone, idFWD_KWREST, idFWD_BLOCK, loc);
+ return new_args(p, leading, Qnone, idFWD_REST, Qnone, n, loc);
+}
+#endif
+
static NODE *
numparam_push(struct parser_params *p)
{
@@ -12081,7 +12731,7 @@ dvar_defined_ref(struct parser_params *p, ID id, ID **vidrefp)
if (used) used = used->prev;
}
- if (vars == DVARS_INHERIT) {
+ if (vars == DVARS_INHERIT && !NUMPARAM_ID_P(id)) {
return rb_dvar_defined(id, p->parent_iseq);
}
@@ -12193,9 +12843,9 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
var = intern_cstr(s, len, enc);
if (len < MAX_WORD_LENGTH && rb_reserved_word(s, (int)len)) {
- if (!lvar_defined(p, var)) return ST_CONTINUE;
+ if (!lvar_defined(p, var)) return ST_CONTINUE;
}
- node = node_assign(p, assignable(p, var, 0, arg->loc), NEW_LIT(ID2SYM(var), arg->loc), arg->loc);
+ node = node_assign(p, assignable(p, var, 0, arg->loc), NEW_LIT(ID2SYM(var), arg->loc), NO_LEX_CTXT, arg->loc);
succ = arg->succ_block;
if (!succ) succ = NEW_BEGIN(0, arg->loc);
succ = block_append(p, succ, node);
@@ -12277,14 +12927,6 @@ rb_parser_set_options(VALUE vparser, int print, int loop, int chomp, int split)
p->do_split = split;
}
-void
-rb_parser_warn_location(VALUE vparser, int warn)
-{
- struct parser_params *p;
- TypedData_Get_Struct(vparser, struct parser_params, &parser_data_type, p);
- p->warn_location = warn;
-}
-
static NODE *
parser_append_options(struct parser_params *p, NODE *node)
{
@@ -12300,8 +12942,10 @@ parser_append_options(struct parser_params *p, NODE *node)
if (p->do_loop) {
if (p->do_split) {
- NODE *args = NEW_LIST(NEW_GVAR(rb_intern("$;"), LOC), LOC);
- NODE *split = NEW_GASGN(rb_intern("$F"),
+ ID ifs = rb_intern("$;");
+ ID fields = rb_intern("$F");
+ NODE *args = NEW_LIST(NEW_GVAR(ifs, LOC), LOC);
+ NODE *split = NEW_GASGN(fields,
NEW_CALL(NEW_GVAR(idLASTLINE, LOC),
rb_intern("split"), args, LOC),
LOC);
@@ -12353,7 +12997,7 @@ parser_initialize(struct parser_params *p)
p->error_buffer = Qfalse;
#endif
p->debug_buffer = Qnil;
- p->debug_output = rb_stdout;
+ p->debug_output = rb_ractor_stdout();
p->enc = rb_utf8_encoding();
}
diff --git a/prelude.rb b/prelude.rb
index be249af751..b1e477a3ea 100644
--- a/prelude.rb
+++ b/prelude.rb
@@ -1,18 +1,3 @@
-class << Thread
- # call-seq:
- # Thread.exclusive { block } -> obj
- #
- # Wraps the block in a single, VM-global Mutex.synchronize, returning the
- # value of the block. A thread executing inside the exclusive section will
- # only block other threads which also use the Thread.exclusive mechanism.
- def exclusive(&block) end if false
- mutex = Mutex.new # :nodoc:
- define_method(:exclusive) do |&block|
- warn "Thread.exclusive is deprecated, use Thread::Mutex", uplevel: 1
- mutex.synchronize(&block)
- end
-end
-
class Binding
# :nodoc:
def irb
diff --git a/probes.d b/probes.d
index 57a3d762bd..0762a2d25f 100644
--- a/probes.d
+++ b/probes.d
@@ -214,17 +214,6 @@ provider ruby {
Fired at the end of a sweep phase.
*/
probe gc__sweep__end();
-
- /*
- ruby:::method-cache-clear(class, filename, lineno);
-
- This probe is fired when the method cache is cleared.
-
- * `class` the name of the class or "global" (a string)
- * `filename` the file name where the cache is _being cleared_ (a string)
- * `lineno` the line number where the cache is _being cleared_ (an int)
- */
- probe method__cache__clear(const char *class, const char *filename, int lineno);
};
#pragma D attributes Stable/Evolving/Common provider ruby provider
diff --git a/probes_helper.h b/probes_helper.h
index 115c78d467..d2d0ebb6e2 100644
--- a/probes_helper.h
+++ b/probes_helper.h
@@ -12,7 +12,9 @@ struct ruby_dtrace_method_hook_args {
volatile VALUE name;
};
+MJIT_SYMBOL_EXPORT_BEGIN
NOINLINE(int rb_dtrace_setup(rb_execution_context_t *, VALUE, ID, struct ruby_dtrace_method_hook_args *));
+MJIT_SYMBOL_EXPORT_END
#define RUBY_DTRACE_METHOD_HOOK(name, ec, klazz, id) \
do { \
diff --git a/proc.c b/proc.c
index 0c8889f04b..a933fde3a8 100644
--- a/proc.c
+++ b/proc.c
@@ -10,14 +10,16 @@
**********************************************************************/
#include "eval_intern.h"
-#include "internal.h"
#include "gc.h"
-#include "vm_core.h"
+#include "internal.h"
+#include "internal/class.h"
+#include "internal/error.h"
+#include "internal/eval.h"
+#include "internal/object.h"
+#include "internal/proc.h"
+#include "internal/symbol.h"
#include "iseq.h"
-
-/* Proc.new with no block will raise an exception in the future
- * versions */
-#define PROC_NEW_REQUIRES_BLOCK 0
+#include "vm_core.h"
#if !defined(__GNUC__) || __GNUC__ < 5 || defined(__MINGW32__)
# define NO_CLOBBERED(v) (*(volatile VALUE *)&(v))
@@ -46,6 +48,7 @@ VALUE rb_cProc;
static rb_block_call_func bmcall;
static int method_arity(VALUE);
static int method_min_max_arity(VALUE, int *max);
+static VALUE proc_binding(VALUE self);
#define attached id__attached__
@@ -61,18 +64,18 @@ block_mark(const struct rb_block *block)
case block_type_ifunc:
{
const struct rb_captured_block *captured = &block->as.captured;
- RUBY_MARK_NO_PIN_UNLESS_NULL(captured->self);
- RUBY_MARK_NO_PIN_UNLESS_NULL((VALUE)captured->code.val);
+ RUBY_MARK_MOVABLE_UNLESS_NULL(captured->self);
+ RUBY_MARK_MOVABLE_UNLESS_NULL((VALUE)captured->code.val);
if (captured->ep && captured->ep[VM_ENV_DATA_INDEX_ENV] != Qundef /* cfunc_proc_t */) {
- RUBY_MARK_NO_PIN_UNLESS_NULL(VM_ENV_ENVVAL(captured->ep));
+ rb_gc_mark(VM_ENV_ENVVAL(captured->ep));
}
}
break;
case block_type_symbol:
- RUBY_MARK_NO_PIN_UNLESS_NULL(block->as.symbol);
+ RUBY_MARK_MOVABLE_UNLESS_NULL(block->as.symbol);
break;
case block_type_proc:
- RUBY_MARK_NO_PIN_UNLESS_NULL(block->as.proc);
+ RUBY_MARK_MOVABLE_UNLESS_NULL(block->as.proc);
break;
}
}
@@ -87,9 +90,6 @@ block_compact(struct rb_block *block)
struct rb_captured_block *captured = &block->as.captured;
captured->self = rb_gc_location(captured->self);
captured->code.val = rb_gc_location(captured->code.val);
- if (captured->ep && captured->ep[VM_ENV_DATA_INDEX_ENV] != Qundef /* cfunc_proc_t */) {
- UPDATE_REFERENCE(captured->ep[VM_ENV_DATA_INDEX_ENV]);
- }
}
break;
case block_type_symbol:
@@ -421,7 +421,11 @@ get_local_variable_ptr(const rb_env_t **envp, ID lid)
const rb_env_t *env = *envp;
do {
if (!VM_ENV_FLAGS(env->ep, VM_FRAME_FLAG_CFRAME)) {
- const rb_iseq_t *iseq = env->iseq;
+ if (VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_ISOLATED)) {
+ return NULL;
+ }
+
+ const rb_iseq_t *iseq = env->iseq;
unsigned int i;
VM_ASSERT(rb_obj_is_iseq((VALUE)iseq));
@@ -539,14 +543,15 @@ bind_local_variable_get(VALUE bindval, VALUE sym)
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
- if ((ptr = get_local_variable_ptr(&env, lid)) == NULL) {
- sym = ID2SYM(lid);
- undefined:
- rb_name_err_raise("local variable `%1$s' is not defined for %2$s",
- bindval, sym);
+ if ((ptr = get_local_variable_ptr(&env, lid)) != NULL) {
+ return *ptr;
}
- return *ptr;
+ sym = ID2SYM(lid);
+ undefined:
+ rb_name_err_raise("local variable `%1$s' is not defined for %2$s",
+ bindval, sym);
+ UNREACHABLE_RETURN(Qundef);
}
/*
@@ -661,7 +666,7 @@ bind_location(VALUE bindval)
}
static VALUE
-cfunc_proc_new(VALUE klass, VALUE ifunc, int8_t is_lambda)
+cfunc_proc_new(VALUE klass, VALUE ifunc)
{
rb_proc_t *proc;
cfunc_proc_t *sproc;
@@ -679,7 +684,7 @@ cfunc_proc_new(VALUE klass, VALUE ifunc, int8_t is_lambda)
/* self? */
RB_OBJ_WRITE(procval, &proc->block.as.captured.code.ifunc, ifunc);
- proc->is_lambda = is_lambda;
+ proc->is_lambda = TRUE;
return procval;
}
@@ -691,6 +696,7 @@ sym_proc_new(VALUE klass, VALUE sym)
GetProcPtr(procval, proc);
vm_block_type_set(&proc->block, block_type_symbol);
+ proc->is_lambda = TRUE;
RB_OBJ_WRITE(procval, &proc->block.as.symbol, sym);
return procval;
}
@@ -721,21 +727,22 @@ rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int m
}
arity.argc.min = min_argc;
arity.argc.max = max_argc;
- return IFUNC_NEW(func, data, arity.packed);
+ VALUE ret = rb_imemo_new(imemo_ifunc, (VALUE)func, (VALUE)data, arity.packed, 0);
+ return (struct vm_ifunc *)ret;
}
MJIT_FUNC_EXPORTED VALUE
rb_func_proc_new(rb_block_call_func_t func, VALUE val)
{
struct vm_ifunc *ifunc = rb_vm_ifunc_proc_new(func, (void *)val);
- return cfunc_proc_new(rb_cProc, (VALUE)ifunc, 0);
+ return cfunc_proc_new(rb_cProc, (VALUE)ifunc);
}
-VALUE
+MJIT_FUNC_EXPORTED VALUE
rb_func_lambda_new(rb_block_call_func_t func, VALUE val, int min_argc, int max_argc)
{
struct vm_ifunc *ifunc = rb_vm_ifunc_new(func, (void *)val, min_argc, max_argc);
- return cfunc_proc_new(rb_cProc, (VALUE)ifunc, 1);
+ return cfunc_proc_new(rb_cProc, (VALUE)ifunc);
}
static const char proc_without_block[] = "tried to create Proc object without a block";
@@ -749,25 +756,7 @@ proc_new(VALUE klass, int8_t is_lambda, int8_t kernel)
VALUE block_handler;
if ((block_handler = rb_vm_frame_block_handler(cfp)) == VM_BLOCK_HANDLER_NONE) {
-#if !PROC_NEW_REQUIRES_BLOCK
- cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
-
- if ((block_handler = rb_vm_frame_block_handler(cfp)) != VM_BLOCK_HANDLER_NONE) {
- if (is_lambda) {
- rb_raise(rb_eArgError, proc_without_block);
- }
- else {
- const char *name = kernel ? "Kernel#proc" : "Proc.new";
- rb_warn_deprecated("Capturing the given block using %s",
- "`&block`", name);
- }
- }
-#else
- if (0);
-#endif
- else {
- rb_raise(rb_eArgError, proc_without_block);
- }
+ rb_raise(rb_eArgError, proc_without_block);
}
/* block is in cf */
@@ -858,6 +847,34 @@ rb_block_lambda(void)
return proc_new(rb_cProc, TRUE, FALSE);
}
+static void
+f_lambda_warn(void)
+{
+ rb_control_frame_t *cfp = GET_EC()->cfp;
+ VALUE block_handler = rb_vm_frame_block_handler(cfp);
+
+ if (block_handler != VM_BLOCK_HANDLER_NONE) {
+ switch (vm_block_handler_type(block_handler)) {
+ case block_handler_type_iseq:
+ if (RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)->ep == VM_BH_TO_ISEQ_BLOCK(block_handler)->ep) {
+ return;
+ }
+ break;
+ case block_handler_type_symbol:
+ return;
+ case block_handler_type_proc:
+ if (rb_proc_lambda_p(VM_BH_TO_PROC(block_handler))) {
+ return;
+ }
+ break;
+ case block_handler_type_ifunc:
+ break;
+ }
+ }
+
+ rb_warn_deprecated("lambda without a literal block", "the proc without lambda");
+}
+
/*
* call-seq:
* lambda { |...| block } -> a_proc
@@ -869,6 +886,7 @@ rb_block_lambda(void)
static VALUE
f_lambda(VALUE _)
{
+ f_lambda_warn();
return rb_block_lambda();
}
@@ -949,14 +967,11 @@ rb_proc_call_kw(VALUE self, VALUE args, int kw_splat)
{
VALUE vret;
rb_proc_t *proc;
- VALUE v;
int argc = check_argc(RARRAY_LEN(args));
const VALUE *argv = RARRAY_CONST_PTR(args);
GetProcPtr(self, proc);
- v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
vret = rb_vm_invoke_proc(GET_EC(), proc, argc, argv,
kw_splat, VM_BLOCK_HANDLER_NONE);
- rb_free_tmp_buffer(&v);
RB_GC_GUARD(self);
RB_GC_GUARD(args);
return vret;
@@ -988,10 +1003,8 @@ rb_proc_call_with_block_kw(VALUE self, int argc, const VALUE *argv, VALUE passed
rb_execution_context_t *ec = GET_EC();
VALUE vret;
rb_proc_t *proc;
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
GetProcPtr(self, proc);
vret = rb_vm_invoke_proc(ec, proc, argc, argv, kw_splat, proc_to_block_handler(passed_procval));
- rb_free_tmp_buffer(&v);
RB_GC_GUARD(self);
return vret;
}
@@ -1088,7 +1101,8 @@ rb_vm_block_min_max_arity(const struct rb_block *block, int *max)
return ifunc->argc.min;
}
case block_type_symbol:
- break;
+ *max = UNLIMITED_ARGUMENTS;
+ return 1;
}
*max = UNLIMITED_ARGUMENTS;
return 0;
@@ -1141,6 +1155,41 @@ block_setup(struct rb_block *block, VALUE block_handler)
}
int
+rb_block_pair_yield_optimizable(void)
+{
+ int min, max;
+ const rb_execution_context_t *ec = GET_EC();
+ rb_control_frame_t *cfp = ec->cfp;
+ VALUE block_handler = rb_vm_frame_block_handler(cfp);
+ struct rb_block block;
+
+ if (block_handler == VM_BLOCK_HANDLER_NONE) {
+ rb_raise(rb_eArgError, "no block given");
+ }
+
+ block_setup(&block, block_handler);
+ min = rb_vm_block_min_max_arity(&block, &max);
+
+ switch (vm_block_type(&block)) {
+ case block_handler_type_symbol:
+ return 0;
+
+ case block_handler_type_proc:
+ {
+ VALUE procval = block_handler;
+ rb_proc_t *proc;
+ GetProcPtr(procval, proc);
+ if (proc->is_lambda) return 0;
+ if (min != max) return 0;
+ return min > 1;
+ }
+
+ default:
+ return min > 1;
+ }
+}
+
+int
rb_block_arity(void)
{
int min, max;
@@ -1166,7 +1215,6 @@ rb_block_arity(void)
rb_proc_t *proc;
GetProcPtr(procval, proc);
return (proc->is_lambda ? min == max : max != UNLIMITED_ARGUMENTS) ? min : -min-1;
- /* fall through */
}
default:
@@ -1225,6 +1273,89 @@ rb_proc_get_iseq(VALUE self, int *is_proc)
return NULL;
}
+/* call-seq:
+ * prc == other -> true or false
+ * prc.eql?(other) -> true or false
+ *
+ * Two proc are the same if, and only if, they were created from the same code block.
+ *
+ * def return_block(&block)
+ * block
+ * end
+ *
+ * def pass_block_twice(&block)
+ * [return_block(&block), return_block(&block)]
+ * end
+ *
+ * block1, block2 = pass_block_twice { puts 'test' }
+ * # Blocks might be instantiated into Proc's lazily, so they may, or may not,
+ * # be the same object.
+ * # But they are produced from the same code block, so they are equal
+ * block1 == block2
+ * #=> true
+ *
+ * # Another Proc will never be equal, even if the code is the "same"
+ * block1 == proc { puts 'test' }
+ * #=> false
+ *
+ */
+static VALUE
+proc_eq(VALUE self, VALUE other)
+{
+ const rb_proc_t *self_proc, *other_proc;
+ const struct rb_block *self_block, *other_block;
+
+ if (rb_obj_class(self) != rb_obj_class(other)) {
+ return Qfalse;
+ }
+
+ GetProcPtr(self, self_proc);
+ GetProcPtr(other, other_proc);
+
+ if (self_proc->is_from_method != other_proc->is_from_method ||
+ self_proc->is_lambda != other_proc->is_lambda) {
+ return Qfalse;
+ }
+
+ self_block = &self_proc->block;
+ other_block = &other_proc->block;
+
+ if (vm_block_type(self_block) != vm_block_type(other_block)) {
+ return Qfalse;
+ }
+
+ switch (vm_block_type(self_block)) {
+ case block_type_iseq:
+ if (self_block->as.captured.ep != \
+ other_block->as.captured.ep ||
+ self_block->as.captured.code.iseq != \
+ other_block->as.captured.code.iseq) {
+ return Qfalse;
+ }
+ break;
+ case block_type_ifunc:
+ if (self_block->as.captured.ep != \
+ other_block->as.captured.ep ||
+ self_block->as.captured.code.ifunc != \
+ other_block->as.captured.code.ifunc) {
+ return Qfalse;
+ }
+ break;
+ case block_type_proc:
+ if (self_block->as.proc != other_block->as.proc) {
+ return Qfalse;
+ }
+ break;
+ case block_type_symbol:
+ if (self_block->as.symbol != other_block->as.symbol) {
+ return Qfalse;
+ }
+ break;
+ }
+
+ return Qtrue;
+}
+
static VALUE
iseq_location(const rb_iseq_t *iseq)
{
@@ -1534,12 +1665,12 @@ mnew_internal(const rb_method_entry_t *me, VALUE klass, VALUE iclass,
}
if (me->def->type == VM_METHOD_TYPE_ZSUPER) {
if (me->defined_class) {
- VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->defined_class));
+ VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->defined_class));
id = me->def->original_id;
me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(klass, id, &iclass);
}
else {
- VALUE klass = RCLASS_SUPER(me->owner);
+ VALUE klass = RCLASS_SUPER(RCLASS_ORIGIN(me->owner));
id = me->def->original_id;
me = rb_method_entry_without_refinements(klass, id, &iclass);
}
@@ -1619,8 +1750,8 @@ method_entry_defined_class(const rb_method_entry_t *me)
* meth == other_meth -> true or false
*
* Two method objects are equal if they are bound to the same
- * object and refer to the same method definition and their owners are the
- * same class or module.
+ * object and refer to the same method definition and the classes
+ * defining the methods are the same class or module.
*/
static VALUE
@@ -1779,7 +1910,7 @@ rb_method_name_error(VALUE klass, VALUE str)
{
#define MSG(s) rb_fstring_lit("undefined method `%1$s' for"s" `%2$s'")
VALUE c = klass;
- VALUE s;
+ VALUE s = Qundef;
if (FL_TEST(c, FL_SINGLETON)) {
VALUE obj = rb_ivar_get(klass, attached);
@@ -1788,15 +1919,15 @@ rb_method_name_error(VALUE klass, VALUE str)
case T_MODULE:
case T_CLASS:
c = obj;
- s = MSG("");
+ break;
+ default:
+ break;
}
- goto normal_class;
}
else if (RB_TYPE_P(c, T_MODULE)) {
s = MSG(" module");
}
- else {
- normal_class:
+ if (s == Qundef) {
s = MSG(" class");
}
rb_name_err_raise_str(s, c, str);
@@ -1903,27 +2034,39 @@ rb_obj_public_method(VALUE obj, VALUE vid)
VALUE
rb_obj_singleton_method(VALUE obj, VALUE vid)
{
- const rb_method_entry_t *me;
VALUE klass = rb_singleton_class_get(obj);
ID id = rb_check_id(&vid);
- if (NIL_P(klass) || NIL_P(klass = RCLASS_ORIGIN(klass))) {
- undef:
- rb_name_err_raise("undefined singleton method `%1$s' for `%2$s'",
- obj, vid);
+ if (NIL_P(klass)) {
+ /* goto undef; */
}
- if (!id) {
+ else if (NIL_P(klass = RCLASS_ORIGIN(klass))) {
+ /* goto undef; */
+ }
+ else if (! id) {
VALUE m = mnew_missing_by_name(klass, obj, &vid, FALSE, rb_cMethod);
if (m) return m;
- goto undef;
+ /* else goto undef; */
}
- me = rb_method_entry_at(klass, id);
- if (UNDEFINED_METHOD_ENTRY_P(me) ||
- UNDEFINED_REFINED_METHOD_P(me->def)) {
- vid = ID2SYM(id);
- goto undef;
+ else {
+ const rb_method_entry_t *me = rb_method_entry_at(klass, id);
+ vid = ID2SYM(id);
+
+ if (UNDEFINED_METHOD_ENTRY_P(me)) {
+ /* goto undef; */
+ }
+ else if (UNDEFINED_REFINED_METHOD_P(me->def)) {
+ /* goto undef; */
+ }
+ else {
+ return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE);
+ }
}
- return mnew_from_me(me, klass, klass, obj, id, rb_cMethod, FALSE);
+
+ /* undef: */
+ rb_name_err_raise("undefined singleton method `%1$s' for `%2$s'",
+ obj, vid);
+ UNREACHABLE_RETURN(Qundef);
}
/*
@@ -2043,25 +2186,7 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
name = argv[0];
id = rb_check_id(&name);
if (argc == 1) {
-#if PROC_NEW_REQUIRES_BLOCK
body = rb_block_lambda();
-#else
- const rb_execution_context_t *ec = GET_EC();
- VALUE block_handler = rb_vm_frame_block_handler(ec->cfp);
- if (block_handler == VM_BLOCK_HANDLER_NONE) rb_raise(rb_eArgError, proc_without_block);
-
- switch (vm_block_handler_type(block_handler)) {
- case block_handler_type_proc:
- body = VM_BH_TO_PROC(block_handler);
- break;
- case block_handler_type_symbol:
- body = rb_sym_to_proc(VM_BH_TO_SYMBOL(block_handler));
- break;
- case block_handler_type_iseq:
- case block_handler_type_ifunc:
- body = rb_vm_make_lambda(ec, VM_BH_TO_CAPT_BLOCK(block_handler), rb_cProc);
- }
-#endif
}
else {
body = argv[1];
@@ -2377,6 +2502,10 @@ convert_umethod_to_method_components(VALUE method, VALUE recv, VALUE *methclass_
VALUE iclass = data->me->defined_class;
VALUE klass = CLASS_OF(recv);
+ if (RB_TYPE_P(methclass, T_MODULE)) {
+ VALUE refined_class = rb_refinement_module_get_refined_class(methclass);
+ if (!NIL_P(refined_class)) methclass = refined_class;
+ }
if (!RB_TYPE_P(methclass, T_MODULE) &&
methclass != CLASS_OF(recv) && !rb_obj_is_kind_of(recv, methclass)) {
if (FL_TEST(methclass, FL_SINGLETON)) {
@@ -2654,6 +2783,21 @@ rb_obj_method_arity(VALUE obj, ID id)
return rb_mod_method_arity(CLASS_OF(obj), id);
}
+VALUE
+rb_callable_receiver(VALUE callable)
+{
+ if (rb_obj_is_proc(callable)) {
+ VALUE binding = proc_binding(callable);
+ return rb_funcall(binding, rb_intern("receiver"), 0);
+ }
+ else if (rb_obj_is_method(callable)) {
+ return method_receiver(callable);
+ }
+ else {
+ return Qundef;
+ }
+}
+
const rb_method_definition_t *
rb_method_def(VALUE method)
{
@@ -2816,7 +2960,8 @@ method_inspect(VALUE method)
TypedData_Get_Struct(method, struct METHOD, &method_data_type, data);
str = rb_sprintf("#<% "PRIsVALUE": ", rb_obj_class(method));
- mklass = data->klass;
+ mklass = data->iclass;
+ if (!mklass) mklass = data->klass;
if (RB_TYPE_P(mklass, T_ICLASS)) {
/* TODO: I'm not sure why mklass is T_ICLASS.
@@ -2856,6 +3001,15 @@ method_inspect(VALUE method)
}
}
else {
+ mklass = data->klass;
+ if (FL_TEST(mklass, FL_SINGLETON)) {
+ VALUE v = rb_ivar_get(mklass, attached);
+ if (!(RB_TYPE_P(v, T_CLASS) || RB_TYPE_P(v, T_MODULE))) {
+ do {
+ mklass = RCLASS_SUPER(mklass);
+ } while (RB_TYPE_P(mklass, T_ICLASS));
+ }
+ }
rb_str_buf_append(str, rb_inspect(mklass));
if (defined_class != mklass) {
rb_str_catf(str, "(% "PRIsVALUE")", defined_class);
@@ -3137,6 +3291,8 @@ proc_binding(VALUE self)
GetProcPtr(self, proc);
block = &proc->block;
+ if (proc->is_isolated) rb_raise(rb_eArgError, "Can't create Binding from isolated Proc");
+
again:
switch (vm_block_type(block)) {
case block_type_iseq:
@@ -3148,8 +3304,6 @@ proc_binding(VALUE self)
GetProcPtr(block->as.proc, proc);
block = &proc->block;
goto again;
- case block_type_symbol:
- goto error;
case block_type_ifunc:
{
const struct vm_ifunc *ifunc = block->as.captured.code.ifunc;
@@ -3166,12 +3320,11 @@ proc_binding(VALUE self)
RB_OBJ_WRITE(env, &env->iseq, empty);
break;
}
- else {
- error:
- rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
- return Qnil;
- }
}
+ /* FALLTHROUGH */
+ case block_type_symbol:
+ rb_raise(rb_eArgError, "Can't create Binding from C level Proc");
+ UNREACHABLE_RETURN(Qnil);
}
bindval = rb_binding_alloc(rb_cBinding);
@@ -3401,8 +3554,14 @@ rb_proc_compose_to_left(VALUE self, VALUE g)
procs[1] = g;
args = rb_ary_tmp_new_from_values(0, 2, procs);
- GetProcPtr(self, procp);
- is_lambda = procp->is_lambda;
+ if (rb_obj_is_proc(g)) {
+ GetProcPtr(g, procp);
+ is_lambda = procp->is_lambda;
+ }
+ else {
+ VM_ASSERT(rb_obj_is_method(g) || rb_obj_respond_to(g, idCall, TRUE));
+ is_lambda = 1;
+ }
proc = rb_proc_new(compose, args);
GetProcPtr(proc, procp);
@@ -3773,7 +3932,7 @@ proc_ruby2_keywords(VALUE procval)
*
* p = proc {|x, y| x }
* l = lambda {|x, y| x }
- * [[1, 2], [3, 4]].map(&p) #=> [1, 2]
+ * [[1, 2], [3, 4]].map(&p) #=> [1, 3]
* [[1, 2], [3, 4]].map(&l) # ArgumentError: wrong number of arguments (given 1, expected 2)
*
* The only exception is dynamic method definition: even if defined by
@@ -3805,7 +3964,7 @@ proc_ruby2_keywords(VALUE procval)
* == Conversion of other objects to procs
*
* Any object that implements the +to_proc+ method can be converted into
- * a proc by the <code>&</code> operator, and therefore con be
+ * a proc by the <code>&</code> operator, and therefore can be
* consumed by iterators.
*
@@ -3949,9 +4108,12 @@ Init_Proc(void)
rb_define_method(rb_cProc, "curry", proc_curry, -1);
rb_define_method(rb_cProc, "<<", proc_compose_to_left, 1);
rb_define_method(rb_cProc, ">>", proc_compose_to_right, 1);
+ rb_define_method(rb_cProc, "==", proc_eq, 1);
+ rb_define_method(rb_cProc, "eql?", proc_eq, 1);
rb_define_method(rb_cProc, "source_location", rb_proc_location, 0);
rb_define_method(rb_cProc, "parameters", rb_proc_parameters, 0);
rb_define_method(rb_cProc, "ruby2_keywords", proc_ruby2_keywords, 0);
+ // rb_define_method(rb_cProc, "isolate", rb_proc_isolate, 0); is not accepted.
/* Exceptions */
rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError);
diff --git a/process.c b/process.c
index 475b27545f..674f05dd6c 100644
--- a/process.c
+++ b/process.c
@@ -11,83 +11,112 @@
**********************************************************************/
-#include "ruby/config.h"
-#include "ruby/io.h"
-#include "internal.h"
-#include "ruby/thread.h"
-#include "ruby/util.h"
-#include "vm_core.h"
-#include "hrtime.h"
+#include "ruby/internal/config.h"
-#include <stdio.h>
+#include "internal/scheduler.h"
+#include "coroutine/Stack.h"
+
+#include <ctype.h>
#include <errno.h>
#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <time.h>
+
#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
+# include <stdlib.h>
#endif
+
#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+# include <unistd.h>
#endif
+
#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
+# include <fcntl.h>
#endif
+
#ifdef HAVE_PROCESS_H
-#include <process.h>
+# include <process.h>
#endif
-#include <time.h>
-#include <ctype.h>
-
#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
+# define EXIT_SUCCESS 0
#endif
+
#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
+# define EXIT_FAILURE 1
#endif
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
+
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
#endif
+
#ifdef HAVE_VFORK_H
# include <vfork.h>
#endif
+
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
+
#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif
-#include "ruby/st.h"
#include <sys/stat.h>
#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
+# include <sys/time.h>
#endif
+
#ifdef HAVE_SYS_TIMES_H
-#include <sys/times.h>
+# include <sys/times.h>
#endif
#ifdef HAVE_PWD_H
-#include <pwd.h>
+# include <pwd.h>
#endif
+
#ifdef HAVE_GRP_H
-#include <grp.h>
+# include <grp.h>
# ifdef __CYGWIN__
int initgroups(const char *, rb_gid_t);
# endif
#endif
+
#ifdef HAVE_SYS_ID_H
-#include <sys/id.h>
+# include <sys/id.h>
#endif
#ifdef __APPLE__
# include <mach/mach_time.h>
#endif
+#include "dln.h"
+#include "hrtime.h"
+#include "internal.h"
+#include "internal/bits.h"
+#include "internal/dir.h"
+#include "internal/error.h"
+#include "internal/eval.h"
+#include "internal/hash.h"
+#include "internal/object.h"
+#include "internal/process.h"
+#include "internal/thread.h"
+#include "internal/variable.h"
+#include "internal/warnings.h"
+#include "mjit.h"
+#include "ruby/io.h"
+#include "ruby/st.h"
+#include "ruby/thread.h"
+#include "ruby/util.h"
+#include "vm_core.h"
+#include "ruby/ractor.h"
+
/* define system APIs */
#ifdef _WIN32
#undef open
@@ -345,8 +374,6 @@ close_unless_reserved(int fd)
/*#define DEBUG_REDIRECT*/
#if defined(DEBUG_REDIRECT)
-#include <stdarg.h>
-
static void
ttyprintf(const char *fmt, ...)
{
@@ -542,6 +569,29 @@ proc_get_ppid(VALUE _)
static VALUE rb_cProcessStatus;
+struct rb_process_status {
+ rb_pid_t pid;
+ int status;
+ int error;
+};
+
+static const rb_data_type_t rb_process_status_type = {
+ .wrap_struct_name = "Process::Status",
+ .function = {
+ .dfree = RUBY_DEFAULT_FREE,
+ },
+ .data = NULL,
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static VALUE
+rb_process_status_allocate(VALUE klass)
+{
+ struct rb_process_status *data = NULL;
+
+ return TypedData_Make_Struct(klass, struct rb_process_status, &rb_process_status_type, data);
+}
+
VALUE
rb_last_status_get(void)
{
@@ -569,13 +619,47 @@ proc_s_last_status(VALUE mod)
return rb_last_status_get();
}
+VALUE
+rb_process_status_new(rb_pid_t pid, int status, int error)
+{
+ VALUE last_status = rb_process_status_allocate(rb_cProcessStatus);
+
+ struct rb_process_status *data = RTYPEDDATA_DATA(last_status);
+ data->pid = pid;
+ data->status = status;
+ data->error = error;
+
+ rb_obj_freeze(last_status);
+ return last_status;
+}
+
+static VALUE
+process_status_dump(VALUE status)
+{
+ VALUE dump = rb_class_new_instance(0, 0, rb_cObject);
+ struct rb_process_status *data = RTYPEDDATA_DATA(status);
+ if (data->pid) {
+ rb_ivar_set(dump, id_status, INT2NUM(data->status));
+ rb_ivar_set(dump, id_pid, PIDT2NUM(data->pid));
+ }
+ return dump;
+}
+
+static VALUE
+process_status_load(VALUE real_obj, VALUE load_obj)
+{
+ struct rb_process_status *data = rb_check_typeddata(real_obj, &rb_process_status_type);
+ VALUE status = rb_attr_get(load_obj, id_status);
+ VALUE pid = rb_attr_get(load_obj, id_pid);
+ data->pid = NIL_P(pid) ? 0 : NUM2PIDT(pid);
+ data->status = NIL_P(status) ? 0 : NUM2INT(status);
+ return real_obj;
+}
+
void
rb_last_status_set(int status, rb_pid_t pid)
{
- rb_thread_t *th = GET_THREAD();
- th->last_status = rb_obj_alloc(rb_cProcessStatus);
- rb_ivar_set(th->last_status, id_status, INT2FIX(status));
- rb_ivar_set(th->last_status, id_pid, PIDT2NUM(pid));
+ GET_THREAD()->last_status = rb_process_status_new(pid, status, 0);
}
void
@@ -584,11 +668,25 @@ rb_last_status_clear(void)
GET_THREAD()->last_status = Qnil;
}
+static rb_pid_t
+pst_pid(VALUE pst)
+{
+ struct rb_process_status *data = RTYPEDDATA_DATA(pst);
+ return data->pid;
+}
+
+static int
+pst_status(VALUE pst)
+{
+ struct rb_process_status *data = RTYPEDDATA_DATA(pst);
+ return data->status;
+}
+
/*
* call-seq:
* stat.to_i -> integer
*
- * Returns the bits in _stat_ as a Integer. Poking
+ * Returns the bits in _stat_ as an Integer. Poking
* around in these bits is platform dependent.
*
* fork { exit 0xab } #=> 26566
@@ -597,12 +695,13 @@ rb_last_status_clear(void)
*/
static VALUE
-pst_to_i(VALUE st)
+pst_to_i(VALUE self)
{
- return rb_ivar_get(st, id_status);
+ int status = pst_status(self);
+ return RB_INT2NUM(status);
}
-#define PST2INT(st) NUM2INT(pst_to_i(st))
+#define PST2INT(st) pst_status(st)
/*
* call-seq:
@@ -616,9 +715,10 @@ pst_to_i(VALUE st)
*/
static VALUE
-pst_pid(VALUE st)
+pst_pid_m(VALUE self)
{
- return rb_attr_get(st, id_pid);
+ rb_pid_t pid = pst_pid(self);
+ return PIDT2NUM(pid);
}
static VALUE pst_message_status(VALUE str, int status);
@@ -683,7 +783,7 @@ pst_to_s(VALUE st)
int status;
VALUE str;
- pid = NUM2PIDT(pst_pid(st));
+ pid = pst_pid(st);
status = PST2INT(st);
str = rb_str_buf_new(0);
@@ -708,13 +808,12 @@ pst_inspect(VALUE st)
{
rb_pid_t pid;
int status;
- VALUE vpid, str;
+ VALUE str;
- vpid = pst_pid(st);
- if (NIL_P(vpid)) {
+ pid = pst_pid(st);
+ if (!pid) {
return rb_sprintf("#<%s: uninitialized>", rb_class2name(CLASS_OF(st)));
}
- pid = NUM2PIDT(vpid);
status = PST2INT(st);
str = rb_sprintf("#<%s: ", rb_class2name(CLASS_OF(st)));
@@ -1077,6 +1176,8 @@ waitpid_state_init(struct waitpid_state *w, rb_pid_t pid, int options)
w->ret = 0;
w->pid = pid;
w->options = options;
+ w->errnum = 0;
+ w->status = 0;
}
static const rb_hrtime_t *
@@ -1187,8 +1288,10 @@ waitpid_wait(struct waitpid_state *w)
*/
rb_native_mutex_lock(&vm->waitpid_lock);
- if (w->pid > 0 || list_empty(&vm->waiting_pids))
+ if (w->pid > 0 || list_empty(&vm->waiting_pids)) {
w->ret = do_waitpid(w->pid, &w->status, w->options | WNOHANG);
+ }
+
if (w->ret) {
if (w->ret == -1) w->errnum = errno;
}
@@ -1237,35 +1340,124 @@ waitpid_no_SIGCHLD(struct waitpid_state *w)
w->errnum = errno;
}
-rb_pid_t
-rb_waitpid(rb_pid_t pid, int *st, int flags)
+VALUE
+rb_process_status_wait(rb_pid_t pid, int flags)
{
- struct waitpid_state w;
+ // We only enter the scheduler if we are "blocking":
+ if (!(flags & WNOHANG)) {
+ VALUE scheduler = rb_scheduler_current();
+ if (rb_scheduler_supports_process_wait(scheduler)) {
+ return rb_scheduler_process_wait(scheduler, pid, flags);
+ }
+ }
+
+ COROUTINE_STACK_LOCAL(struct waitpid_state, w);
- waitpid_state_init(&w, pid, flags);
- w.ec = GET_EC();
+ waitpid_state_init(w, pid, flags);
+ w->ec = GET_EC();
if (WAITPID_USE_SIGCHLD) {
- waitpid_wait(&w);
+ waitpid_wait(w);
}
else {
- waitpid_no_SIGCHLD(&w);
+ waitpid_no_SIGCHLD(w);
}
- if (st) *st = w.status;
- if (w.ret == -1) {
- errno = w.errnum;
+ rb_pid_t ret = w->ret;
+ int s = w->status, e = w->errnum;
+ COROUTINE_STACK_FREE(w);
+
+ if (ret == 0) return Qnil;
+ if (ret > 0 && ruby_nocldwait) {
+ ret = -1;
+ e = ECHILD;
}
- else if (w.ret > 0) {
- if (ruby_nocldwait) {
- w.ret = -1;
- errno = ECHILD;
- }
- else {
- rb_last_status_set(w.status, w.ret);
- }
+
+ return rb_process_status_new(ret, s, e);
+}
+
+/*
+ * call-seq:
+ * Process::Status.wait(pid=-1, flags=0) -> Process::Status
+ *
+ * Waits for a child process to exit and returns a Process::Status object
+ * containing information on that process. Which child it waits on
+ * depends on the value of _pid_:
+ *
+ * > 0:: Waits for the child whose process ID equals _pid_.
+ *
+ * 0:: Waits for any child whose process group ID equals that of the
+ * calling process.
+ *
+ * -1:: Waits for any child process (the default if no _pid_ is
+ * given).
+ *
+ * < -1:: Waits for any child whose process group ID equals the absolute
+ * value of _pid_.
+ *
+ * The _flags_ argument may be a logical or of the flag values
+ * Process::WNOHANG (do not block if no child available)
+ * or Process::WUNTRACED (return stopped children that
+ * haven't been reported). Not all flags are available on all
+ * platforms, but a flag value of zero will work on all platforms.
+ *
+ * Returns +nil+ if there are no child processes.
+ * Not available on all platforms.
+ *
+ * May invoke the scheduler hook _process_wait_.
+ *
+ * fork { exit 99 } #=> 27429
+ * Process::Status.wait #=> pid 27429 exit 99
+ * $? #=> nil
+ *
+ * pid = fork { sleep 3 } #=> 27440
+ * Time.now #=> 2008-03-08 19:56:16 +0900
+ * Process::Status.wait(pid, Process::WNOHANG) #=> nil
+ * Time.now #=> 2008-03-08 19:56:16 +0900
+ * Process::Status.wait(pid, 0) #=> pid 27440 exit 99
+ * Time.now #=> 2008-03-08 19:56:19 +0900
+ *
+ * This is an EXPERIMENTAL FEATURE.
+ */
+
+VALUE
+rb_process_status_waitv(int argc, VALUE *argv, VALUE _)
+{
+ rb_check_arity(argc, 0, 2);
+
+ rb_pid_t pid = -1;
+ int flags = 0;
+
+ if (argc >= 1) {
+ pid = NUM2PIDT(argv[0]);
}
- return w.ret;
+
+ if (argc >= 2) {
+ flags = RB_NUM2INT(argv[1]);
+ }
+
+ return rb_process_status_wait(pid, flags);
+}
+
+rb_pid_t
+rb_waitpid(rb_pid_t pid, int *st, int flags)
+{
+ VALUE status = rb_process_status_wait(pid, flags);
+ if (NIL_P(status)) return 0;
+
+ struct rb_process_status *data = RTYPEDDATA_DATA(status);
+ pid = data->pid;
+
+ if (st) *st = data->status;
+
+ if (pid == -1) {
+ errno = data->error;
+ }
+ else {
+ GET_THREAD()->last_status = status;
+ }
+
+ return pid;
}
static VALUE
@@ -1285,12 +1477,15 @@ proc_wait(int argc, VALUE *argv)
flags = NUM2UINT(vflags);
}
}
+
if ((pid = rb_waitpid(pid, &status, flags)) < 0)
rb_sys_fail(0);
+
if (pid == 0) {
rb_last_status_clear();
return Qnil;
}
+
return PIDT2NUM(pid);
}
@@ -1591,7 +1786,12 @@ after_exec(void)
}
#if defined HAVE_WORKING_FORK || defined HAVE_DAEMON
-#define before_fork_ruby() before_exec()
+static void
+before_fork_ruby(void)
+{
+ before_exec();
+}
+
static void
after_fork_ruby(void)
{
@@ -1600,8 +1800,6 @@ after_fork_ruby(void)
}
#endif
-#include "dln.h"
-
#if defined(HAVE_WORKING_FORK)
/* try_with_sh and exec_with_sh should be async-signal-safe. Actually it is.*/
@@ -1865,8 +2063,7 @@ check_exec_redirect_fd(VALUE v, int iskey)
fd = fptr->fd;
}
else {
- wrong:
- rb_raise(rb_eArgError, "wrong exec redirect");
+ goto wrong;
}
if (fd < 0) {
rb_raise(rb_eArgError, "negative file descriptor");
@@ -1877,6 +2074,10 @@ check_exec_redirect_fd(VALUE v, int iskey)
}
#endif
return INT2FIX(fd);
+
+ wrong:
+ rb_raise(rb_eArgError, "wrong exec redirect");
+ UNREACHABLE_RETURN(Qundef);
}
static VALUE
@@ -1890,12 +2091,11 @@ check_exec_redirect1(VALUE ary, VALUE key, VALUE param)
rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
}
else {
- int i, n=0;
+ int i;
for (i = 0 ; i < RARRAY_LEN(key); i++) {
VALUE v = RARRAY_AREF(key, i);
VALUE fd = check_exec_redirect_fd(v, !NIL_P(param));
rb_ary_push(ary, hide_obj(rb_assoc_new(fd, param)));
- n++;
}
}
return ary;
@@ -1911,7 +2111,7 @@ check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp)
switch (TYPE(val)) {
case T_SYMBOL:
- if (!(id = rb_check_id(&val))) goto wrong_symbol;
+ id = rb_check_id(&val);
if (id == id_close) {
param = Qnil;
eargp->fd_close = check_exec_redirect1(eargp->fd_close, key, param);
@@ -1929,7 +2129,6 @@ check_exec_redirect(VALUE key, VALUE val, struct rb_execarg *eargp)
eargp->fd_dup2 = check_exec_redirect1(eargp->fd_dup2, key, param);
}
else {
- wrong_symbol:
rb_raise(rb_eArgError, "wrong exec redirect symbol: %"PRIsVALUE,
val);
}
@@ -2332,7 +2531,7 @@ check_exec_env_i(st_data_t st_key, st_data_t st_val, st_data_t arg)
k = StringValueCStr(key);
if (strchr(k, '='))
- rb_raise(rb_eArgError, "environment name contains a equal : %s", k);
+ rb_raise(rb_eArgError, "environment name contains a equal : %"PRIsVALUE, key);
if (!NIL_P(val))
StringValueCStr(val);
@@ -2397,6 +2596,8 @@ check_hash(VALUE obj)
case T_STRING:
case T_ARRAY:
return Qnil;
+ default:
+ break;
}
return rb_check_hash_type(obj);
}
@@ -2744,8 +2945,6 @@ rb_execarg_parent_start1(VALUE execarg_obj)
int fd2;
if (NIL_P(fd2v)) {
struct open_struct open_data;
- FilePathValue(vpath);
- vpath = rb_str_encode_ospath(vpath);
again:
open_data.fname = vpath;
open_data.oflags = flags;
@@ -2938,6 +3137,8 @@ rb_f_exec(int argc, const VALUE *argv)
UNREACHABLE_RETURN(Qnil);
}
+NORETURN(static VALUE f_exec(int c, const VALUE *a, VALUE _));
+
/*
* call-seq:
* exec([env,] command... [,options])
@@ -3014,7 +3215,8 @@ rb_f_exec(int argc, const VALUE *argv)
static VALUE
f_exec(int c, const VALUE *a, VALUE _)
{
- return rb_f_exec(c, a);
+ rb_f_exec(c, a);
+ UNREACHABLE_RETURN(Qnil);
}
#define ERRMSG(str) do { if (errmsg && 0 < errmsg_buflen) strlcpy(errmsg, (str), errmsg_buflen); } while (0)
@@ -3503,10 +3705,8 @@ rb_execarg_run_options(const struct rb_execarg *eargp, struct rb_execarg *sargp,
if (eargp->chdir_given) {
if (sargp) {
- char *cwd = ruby_getcwd();
sargp->chdir_given = 1;
- sargp->chdir_dir = hide_obj(rb_str_new2(cwd));
- xfree(cwd);
+ sargp->chdir_dir = hide_obj(rb_dir_getwd_ospath());
}
if (chdir(RSTRING_PTR(eargp->chdir_dir)) == -1) { /* async-signal-safe */
ERRMSG("chdir");
@@ -3966,10 +4166,6 @@ disable_child_handler_fork_child(struct child_handler_disabler_state *old, char
return 0;
}
-COMPILER_WARNING_PUSH
-#ifdef __GNUC__
-COMPILER_WARNING_IGNORED(-Wdeprecated-declarations)
-#endif
static rb_pid_t
retry_fork_async_signal_safe(int *status, int *ep,
int (*chfunc)(void*, char *, size_t), void *charg,
@@ -3994,9 +4190,9 @@ retry_fork_async_signal_safe(int *status, int *ep,
if (!has_privilege())
pid = vfork();
else
- pid = fork();
+ pid = rb_fork();
#else
- pid = fork();
+ pid = rb_fork();
#endif
if (pid == 0) {/* fork succeed, child process */
int ret;
@@ -4030,7 +4226,6 @@ retry_fork_async_signal_safe(int *status, int *ep,
return -1;
}
}
-COMPILER_WARNING_POP
static rb_pid_t
fork_check_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg,
@@ -4060,7 +4255,7 @@ fork_check_err(int *status, int (*chfunc)(void*, char *, size_t), void *charg,
"only used by extensions");
rb_protect(proc_syswait, (VALUE)pid, status);
}
- else if (!w) {
+ else if (!w || w == WAITPID_LOCK_ONLY) {
rb_syswait(pid);
}
errno = err;
@@ -4084,10 +4279,6 @@ rb_fork_async_signal_safe(int *status,
return fork_check_err(status, chfunc, charg, fds, errmsg, errmsg_buflen, 0);
}
-COMPILER_WARNING_PUSH
-#ifdef __GNUC__
-COMPILER_WARNING_IGNORED(-Wdeprecated-declarations)
-#endif
rb_pid_t
rb_fork_ruby(int *status)
{
@@ -4102,7 +4293,7 @@ rb_fork_ruby(int *status)
if (mjit_enabled) mjit_pause(false); // Don't leave locked mutex to child. Note: child_handler must be enabled to pause MJIT.
disable_child_handler_before_fork(&old);
before_fork_ruby();
- pid = fork();
+ pid = rb_fork();
err = errno;
after_fork_ruby();
disable_child_handler_fork_parent(&old); /* yes, bad name */
@@ -4114,7 +4305,6 @@ rb_fork_ruby(int *status)
return -1;
}
}
-COMPILER_WARNING_POP
#endif
@@ -4194,6 +4384,7 @@ exit_status_code(VALUE status)
return istatus;
}
+NORETURN(static VALUE rb_f_exit_bang(int argc, VALUE *argv, VALUE obj));
/*
* call-seq:
* Process.exit!(status=false)
@@ -4250,6 +4441,7 @@ rb_f_exit(int argc, const VALUE *argv)
UNREACHABLE_RETURN(Qnil);
}
+NORETURN(static VALUE f_exit(int c, const VALUE *a, VALUE _));
/*
* call-seq:
* exit(status=true)
@@ -4294,20 +4486,10 @@ rb_f_exit(int argc, const VALUE *argv)
static VALUE
f_exit(int c, const VALUE *a, VALUE _)
{
- return rb_f_exit(c, a);
+ rb_f_exit(c, a);
+ UNREACHABLE_RETURN(Qnil);
}
-/*
- * call-seq:
- * abort
- * Kernel::abort([msg])
- * Process.abort([msg])
- *
- * Terminate execution immediately, effectively by calling
- * <code>Kernel.exit(false)</code>. If _msg_ is given, it is written
- * to STDERR prior to terminating.
- */
-
VALUE
rb_f_abort(int argc, const VALUE *argv)
{
@@ -4325,7 +4507,7 @@ rb_f_abort(int argc, const VALUE *argv)
args[1] = args[0] = argv[0];
StringValue(args[0]);
- rb_io_puts(1, args, rb_stderr);
+ rb_io_puts(1, args, rb_ractor_stderr());
args[0] = INT2NUM(EXIT_FAILURE);
rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit));
}
@@ -4333,10 +4515,24 @@ rb_f_abort(int argc, const VALUE *argv)
UNREACHABLE_RETURN(Qnil);
}
+NORETURN(static VALUE f_abort(int c, const VALUE *a, VALUE _));
+
+/*
+ * call-seq:
+ * abort
+ * Kernel::abort([msg])
+ * Process.abort([msg])
+ *
+ * Terminate execution immediately, effectively by calling
+ * <code>Kernel.exit(false)</code>. If _msg_ is given, it is written
+ * to STDERR prior to terminating.
+ */
+
static VALUE
f_abort(int c, const VALUE *a, VALUE _)
{
- return rb_f_abort(c, a);
+ rb_f_abort(c, a);
+ UNREACHABLE_RETURN(Qnil);
}
void
@@ -4383,8 +4579,7 @@ rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
#endif
#if defined HAVE_WORKING_FORK && !USE_SPAWNV
- pid = fork_check_err(0, rb_exec_atfork, eargp, eargp->redirect_fds,
- errmsg, errmsg_buflen, eargp);
+ pid = fork_check_err(0, rb_exec_atfork, eargp, eargp->redirect_fds, errmsg, errmsg_buflen, eargp);
#else
prog = eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name;
@@ -4398,32 +4593,37 @@ rb_spawn_process(struct rb_execarg *eargp, char *errmsg, size_t errmsg_buflen)
}
# if defined HAVE_SPAWNV
if (eargp->use_shell) {
- pid = proc_spawn_sh(RSTRING_PTR(prog));
+ pid = proc_spawn_sh(RSTRING_PTR(prog));
}
else {
char **argv = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
- pid = proc_spawn_cmd(argv, prog, eargp);
+ pid = proc_spawn_cmd(argv, prog, eargp);
+ }
+
+ if (pid == -1) {
+ rb_last_status_set(0x7f << 8, pid);
}
- if (pid == -1)
- rb_last_status_set(0x7f << 8, 0);
# else
status = system(rb_execarg_commandline(eargp, &prog));
- rb_last_status_set((status & 0xff) << 8, 0);
pid = 1; /* dummy */
+ rb_last_status_set((status & 0xff) << 8, pid);
# endif
+
if (eargp->waitpid_state && eargp->waitpid_state != WAITPID_LOCK_ONLY) {
eargp->waitpid_state->pid = pid;
}
+
rb_execarg_run_options(&sarg, NULL, errmsg, errmsg_buflen);
#endif
+
return pid;
}
struct spawn_args {
VALUE execarg;
struct {
- char *ptr;
- size_t buflen;
+ char *ptr;
+ size_t buflen;
} errmsg;
};
@@ -4903,20 +5103,25 @@ rb_f_spawn(int argc, VALUE *argv, VALUE _)
static VALUE
rb_f_sleep(int argc, VALUE *argv, VALUE _)
{
- time_t beg, end;
+ time_t beg = time(0);
+ VALUE scheduler = rb_scheduler_current();
- beg = time(0);
- if (argc == 0) {
- rb_thread_sleep_forever();
+ if (scheduler != Qnil) {
+ rb_scheduler_kernel_sleepv(scheduler, argc, argv);
}
else {
- rb_check_arity(argc, 0, 1);
- rb_thread_wait_for(rb_time_interval(argv[0]));
+ if (argc == 0) {
+ rb_thread_sleep_forever();
+ }
+ else {
+ rb_check_arity(argc, 0, 1);
+ rb_thread_wait_for(rb_time_interval(argv[0]));
+ }
}
- end = time(0) - beg;
+ time_t end = time(0) - beg;
- return INT2FIX(end);
+ return TIMET2NUM(end);
}
@@ -5553,6 +5758,12 @@ rb_getlogin(void)
# ifdef USE_GETLOGIN_R
+#if defined(__FreeBSD__)
+ typedef int getlogin_r_size_t;
+#else
+ typedef size_t getlogin_r_size_t;
+#endif
+
long loginsize = GETLOGIN_R_SIZE_INIT; /* maybe -1 */
if (loginsize < 0)
@@ -5566,7 +5777,7 @@ rb_getlogin(void)
int gle;
errno = 0;
- while ((gle = getlogin_r(login, loginsize)) != 0) {
+ while ((gle = getlogin_r(login, (getlogin_r_size_t)loginsize)) != 0) {
if (gle == ENOTTY || gle == ENXIO || gle == ENOENT) {
rb_str_resize(maybe_result, 0);
@@ -5828,7 +6039,7 @@ obj2uid(VALUE id
#ifndef USE_GETPWNAM_R
endpwent();
#endif
- rb_raise(rb_eArgError, "can't find user for %s", usrname);
+ rb_raise(rb_eArgError, "can't find user for %"PRIsVALUE, id);
}
uid = pwptr->pw_uid;
#ifndef USE_GETPWNAM_R
@@ -5907,7 +6118,7 @@ obj2gid(VALUE id
#if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
endgrent();
#endif
- rb_raise(rb_eArgError, "can't find group for %s", grpname);
+ rb_raise(rb_eArgError, "can't find group for %"PRIsVALUE, id);
}
gid = grptr->gr_gid;
#if !defined(USE_GETGRNAM_R) && defined(HAVE_ENDGRENT)
@@ -8198,29 +8409,33 @@ rb_clock_gettime(int argc, VALUE *argv, VALUE _)
* call-seq:
* Process.clock_getres(clock_id [, unit]) -> number
*
- * Returns the time resolution returned by POSIX clock_getres() function.
+ * Returns an estimate of the resolution of a +clock_id+ using the POSIX
+ * <code>clock_getres()</code> function.
+ *
+ * Note the reported resolution is often inaccurate on most platforms due to
+ * underlying bugs for this function and therefore the reported resolution
+ * often differs from the actual resolution of the clock in practice.
+ * Inaccurate reported resolutions have been observed for various clocks including
+ * CLOCK_MONOTONIC and CLOCK_MONOTONIC_RAW when using Linux, macOS, BSD or AIX
+ * platforms, when using ARM processors, or when using virtualization.
*
* +clock_id+ specifies a kind of clock.
* See the document of +Process.clock_gettime+ for details.
- *
- * +clock_id+ can be a symbol as +Process.clock_gettime+.
- * However the result may not be accurate.
- * For example, <code>Process.clock_getres(:GETTIMEOFDAY_BASED_CLOCK_REALTIME)</code>
- * returns 1.0e-06 which means 1 microsecond, but actual resolution can be more coarse.
+ * +clock_id+ can be a symbol as for +Process.clock_gettime+.
*
* If the given +clock_id+ is not supported, Errno::EINVAL is raised.
*
- * +unit+ specifies a type of the return value.
+ * +unit+ specifies the type of the return value.
* +Process.clock_getres+ accepts +unit+ as +Process.clock_gettime+.
- * The default value, +:float_second+, is also same as
+ * The default value, +:float_second+, is also the same as
* +Process.clock_gettime+.
*
* +Process.clock_getres+ also accepts +:hertz+ as +unit+.
- * +:hertz+ means a the reciprocal of +:float_second+.
+ * +:hertz+ means the reciprocal of +:float_second+.
*
* +:hertz+ can be used to obtain the exact value of
- * the clock ticks per second for times() function and
- * CLOCKS_PER_SEC for clock() function.
+ * the clock ticks per second for the times() function and
+ * CLOCKS_PER_SEC for the clock() function.
*
* <code>Process.clock_getres(:TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID, :hertz)</code>
* returns the clock ticks per second.
@@ -8404,10 +8619,12 @@ static VALUE rb_mProcID_Syscall;
void
InitVM_process(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
rb_define_virtual_variable("$?", get_CHILD_STATUS, 0);
rb_define_virtual_variable("$$", get_PROCESS_ID, 0);
+
+ rb_gvar_ractor_local("$$");
+ rb_gvar_ractor_local("$?");
+
rb_define_global_function("exec", f_exec, -1);
rb_define_global_function("fork", rb_f_fork, 0);
rb_define_global_function("exit!", rb_f_exit_bang, -1);
@@ -8457,7 +8674,12 @@ InitVM_process(void)
rb_define_method(rb_cWaiter, "pid", detach_process_pid, 0);
rb_cProcessStatus = rb_define_class_under(rb_mProcess, "Status", rb_cObject);
+ rb_define_alloc_func(rb_cProcessStatus, rb_process_status_allocate);
rb_undef_method(CLASS_OF(rb_cProcessStatus), "new");
+ rb_marshal_define_compat(rb_cProcessStatus, rb_cObject,
+ process_status_dump, process_status_load);
+
+ rb_define_singleton_method(rb_cProcessStatus, "wait", rb_process_status_waitv, -1);
rb_define_method(rb_cProcessStatus, "==", pst_equal, 1);
rb_define_method(rb_cProcessStatus, "&", pst_bitand, 1);
@@ -8466,7 +8688,7 @@ InitVM_process(void)
rb_define_method(rb_cProcessStatus, "to_s", pst_to_s, 0);
rb_define_method(rb_cProcessStatus, "inspect", pst_inspect, 0);
- rb_define_method(rb_cProcessStatus, "pid", pst_pid, 0);
+ rb_define_method(rb_cProcessStatus, "pid", pst_pid_m, 0);
rb_define_method(rb_cProcessStatus, "stopped?", pst_wifstopped, 0);
rb_define_method(rb_cProcessStatus, "stopsig", pst_wstopsig, 0);
@@ -8768,9 +8990,6 @@ InitVM_process(void)
#if defined(HAVE_TIMES) || defined(_WIN32)
/* Placeholder for rusage */
rb_cProcessTms = rb_struct_define_under(rb_mProcess, "Tms", "utime", "stime", "cutime", "cstime", NULL);
- /* An obsolete name of Process::Tms for backward compatibility */
- rb_define_const(rb_cStruct, "Tms", rb_cProcessTms);
- rb_deprecate_constant(rb_cStruct, "Tms");
#endif
SAVED_USER_ID = geteuid();
@@ -8831,46 +9050,46 @@ InitVM_process(void)
void
Init_process(void)
{
- id_in = rb_intern("in");
- id_out = rb_intern("out");
- id_err = rb_intern("err");
- id_pid = rb_intern("pid");
- id_uid = rb_intern("uid");
- id_gid = rb_intern("gid");
- id_close = rb_intern("close");
- id_child = rb_intern("child");
+ id_in = rb_intern_const("in");
+ id_out = rb_intern_const("out");
+ id_err = rb_intern_const("err");
+ id_pid = rb_intern_const("pid");
+ id_uid = rb_intern_const("uid");
+ id_gid = rb_intern_const("gid");
+ id_close = rb_intern_const("close");
+ id_child = rb_intern_const("child");
#ifdef HAVE_SETPGID
- id_pgroup = rb_intern("pgroup");
+ id_pgroup = rb_intern_const("pgroup");
#endif
#ifdef _WIN32
- id_new_pgroup = rb_intern("new_pgroup");
-#endif
- id_unsetenv_others = rb_intern("unsetenv_others");
- id_chdir = rb_intern("chdir");
- id_umask = rb_intern("umask");
- id_close_others = rb_intern("close_others");
- id_ENV = rb_intern("ENV");
- id_nanosecond = rb_intern("nanosecond");
- id_microsecond = rb_intern("microsecond");
- id_millisecond = rb_intern("millisecond");
- id_second = rb_intern("second");
- id_float_microsecond = rb_intern("float_microsecond");
- id_float_millisecond = rb_intern("float_millisecond");
- id_float_second = rb_intern("float_second");
- id_GETTIMEOFDAY_BASED_CLOCK_REALTIME = rb_intern("GETTIMEOFDAY_BASED_CLOCK_REALTIME");
- id_TIME_BASED_CLOCK_REALTIME = rb_intern("TIME_BASED_CLOCK_REALTIME");
+ id_new_pgroup = rb_intern_const("new_pgroup");
+#endif
+ id_unsetenv_others = rb_intern_const("unsetenv_others");
+ id_chdir = rb_intern_const("chdir");
+ id_umask = rb_intern_const("umask");
+ id_close_others = rb_intern_const("close_others");
+ id_ENV = rb_intern_const("ENV");
+ id_nanosecond = rb_intern_const("nanosecond");
+ id_microsecond = rb_intern_const("microsecond");
+ id_millisecond = rb_intern_const("millisecond");
+ id_second = rb_intern_const("second");
+ id_float_microsecond = rb_intern_const("float_microsecond");
+ id_float_millisecond = rb_intern_const("float_millisecond");
+ id_float_second = rb_intern_const("float_second");
+ id_GETTIMEOFDAY_BASED_CLOCK_REALTIME = rb_intern_const("GETTIMEOFDAY_BASED_CLOCK_REALTIME");
+ id_TIME_BASED_CLOCK_REALTIME = rb_intern_const("TIME_BASED_CLOCK_REALTIME");
#ifdef HAVE_TIMES
- id_TIMES_BASED_CLOCK_MONOTONIC = rb_intern("TIMES_BASED_CLOCK_MONOTONIC");
- id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID");
+ id_TIMES_BASED_CLOCK_MONOTONIC = rb_intern_const("TIMES_BASED_CLOCK_MONOTONIC");
+ id_TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("TIMES_BASED_CLOCK_PROCESS_CPUTIME_ID");
#endif
#ifdef RUSAGE_SELF
- id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID");
+ id_GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID");
#endif
- id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern("CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID");
+ id_CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID = rb_intern_const("CLOCK_BASED_CLOCK_PROCESS_CPUTIME_ID");
#ifdef __APPLE__
- id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC = rb_intern("MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC");
+ id_MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC = rb_intern_const("MACH_ABSOLUTE_TIME_BASED_CLOCK_MONOTONIC");
#endif
- id_hertz = rb_intern("hertz");
+ id_hertz = rb_intern_const("hertz");
InitVM(process);
}
diff --git a/ractor.c b/ractor.c
new file mode 100644
index 0000000000..bf31b545cf
--- /dev/null
+++ b/ractor.c
@@ -0,0 +1,3257 @@
+// Ractor implementation
+
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+#include "ruby/ractor.h"
+#include "ruby/thread_native.h"
+#include "vm_core.h"
+#include "vm_sync.h"
+#include "ractor_core.h"
+#include "internal/complex.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/rational.h"
+#include "internal/struct.h"
+#include "internal/thread.h"
+#include "variable.h"
+#include "gc.h"
+#include "transient_heap.h"
+
+VALUE rb_cRactor;
+
+VALUE rb_eRactorUnsafeError;
+VALUE rb_eRactorIsolationError;
+static VALUE rb_eRactorError;
+static VALUE rb_eRactorRemoteError;
+static VALUE rb_eRactorMovedError;
+static VALUE rb_eRactorClosedError;
+static VALUE rb_cRactorMovedObject;
+
+static void vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *r, const char *file, int line);
+
+static void
+ASSERT_ractor_unlocking(rb_ractor_t *r)
+{
+#if RACTOR_CHECK_MODE > 0
+ // GET_EC is NULL in an MJIT worker
+ if (rb_current_execution_context(false) != NULL && r->sync.locked_by == rb_ractor_self(GET_RACTOR())) {
+ rb_bug("recursive ractor locking");
+ }
+#endif
+}
+
+static void
+ASSERT_ractor_locking(rb_ractor_t *r)
+{
+#if RACTOR_CHECK_MODE > 0
+ // GET_EC is NULL in an MJIT worker
+ if (rb_current_execution_context(false) != NULL && r->sync.locked_by != rb_ractor_self(GET_RACTOR())) {
+ rp(r->sync.locked_by);
+ rb_bug("ractor lock is not acquired.");
+ }
+#endif
+}
+
+static void
+ractor_lock(rb_ractor_t *r, const char *file, int line)
+{
+ RUBY_DEBUG_LOG2(file, line, "locking r:%u%s", r->pub.id, GET_RACTOR() == r ? " (self)" : "");
+
+ ASSERT_ractor_unlocking(r);
+ rb_native_mutex_lock(&r->sync.lock);
+
+#if RACTOR_CHECK_MODE > 0
+ if (rb_current_execution_context(false) != NULL) { // GET_EC is NULL in an MJIT worker
+ r->sync.locked_by = rb_ractor_self(GET_RACTOR());
+ }
+#endif
+
+ RUBY_DEBUG_LOG2(file, line, "locked r:%u%s", r->pub.id, GET_RACTOR() == r ? " (self)" : "");
+}
+
+static void
+ractor_lock_self(rb_ractor_t *cr, const char *file, int line)
+{
+ VM_ASSERT(cr == GET_RACTOR());
+ VM_ASSERT(cr->sync.locked_by != cr->pub.self);
+ ractor_lock(cr, file, line);
+}
+
+static void
+ractor_unlock(rb_ractor_t *r, const char *file, int line)
+{
+ ASSERT_ractor_locking(r);
+#if RACTOR_CHECK_MODE > 0
+ r->sync.locked_by = Qnil;
+#endif
+ rb_native_mutex_unlock(&r->sync.lock);
+
+ RUBY_DEBUG_LOG2(file, line, "r:%u%s", r->pub.id, GET_RACTOR() == r ? " (self)" : "");
+}
+
+static void
+ractor_unlock_self(rb_ractor_t *cr, const char *file, int line)
+{
+ VM_ASSERT(cr == GET_RACTOR());
+ VM_ASSERT(cr->sync.locked_by == cr->pub.self);
+ ractor_unlock(cr, file, line);
+}
+
+#define RACTOR_LOCK(r) ractor_lock(r, __FILE__, __LINE__)
+#define RACTOR_UNLOCK(r) ractor_unlock(r, __FILE__, __LINE__)
+#define RACTOR_LOCK_SELF(r) ractor_lock_self(r, __FILE__, __LINE__)
+#define RACTOR_UNLOCK_SELF(r) ractor_unlock_self(r, __FILE__, __LINE__)
+
+static void
+ractor_cond_wait(rb_ractor_t *r)
+{
+#if RACTOR_CHECK_MODE > 0
+ VALUE locked_by = r->sync.locked_by;
+ r->sync.locked_by = Qnil;
+#endif
+ rb_native_cond_wait(&r->sync.cond, &r->sync.lock);
+
+#if RACTOR_CHECK_MODE > 0
+ r->sync.locked_by = locked_by;
+#endif
+}
+
+static const char *
+ractor_status_str(enum ractor_status status)
+{
+ switch (status) {
+ case ractor_created: return "created";
+ case ractor_running: return "running";
+ case ractor_blocking: return "blocking";
+ case ractor_terminated: return "terminated";
+ }
+ rb_bug("unreachable");
+}
+
+static void
+ractor_status_set(rb_ractor_t *r, enum ractor_status status)
+{
+ RUBY_DEBUG_LOG("r:%u [%s]->[%s]", r->pub.id, ractor_status_str(r->status_), ractor_status_str(status));
+
+ // check 1
+ if (r->status_ != ractor_created) {
+ VM_ASSERT(r == GET_RACTOR()); // only self-modification is allowed.
+ ASSERT_vm_locking();
+ }
+
+ // check2: transition check. assume it will be vanished on non-debug build.
+ switch (r->status_) {
+ case ractor_created:
+ VM_ASSERT(status == ractor_blocking);
+ break;
+ case ractor_running:
+ VM_ASSERT(status == ractor_blocking||
+ status == ractor_terminated);
+ break;
+ case ractor_blocking:
+ VM_ASSERT(status == ractor_running);
+ break;
+ case ractor_terminated:
+ VM_ASSERT(0); // unreachable
+ break;
+ }
+
+ r->status_ = status;
+}
+
+static bool
+ractor_status_p(rb_ractor_t *r, enum ractor_status status)
+{
+ return rb_ractor_status_p(r, status);
+}
+
+static struct rb_ractor_basket *ractor_queue_at(struct rb_ractor_queue *rq, int i);
+
+static void
+ractor_queue_mark(struct rb_ractor_queue *rq)
+{
+ for (int i=0; i<rq->cnt; i++) {
+ struct rb_ractor_basket *b = ractor_queue_at(rq, i);
+ rb_gc_mark(b->v);
+ rb_gc_mark(b->sender);
+ }
+}
+
+static void ractor_local_storage_mark(rb_ractor_t *r);
+static void ractor_local_storage_free(rb_ractor_t *r);
+
+static void
+ractor_mark(void *ptr)
+{
+ rb_ractor_t *r = (rb_ractor_t *)ptr;
+
+ ractor_queue_mark(&r->sync.incoming_queue);
+ rb_gc_mark(r->sync.wait.taken_basket.v);
+ rb_gc_mark(r->sync.wait.taken_basket.sender);
+ rb_gc_mark(r->sync.wait.yielded_basket.v);
+ rb_gc_mark(r->sync.wait.yielded_basket.sender);
+ rb_gc_mark(r->receiving_mutex);
+
+ rb_gc_mark(r->loc);
+ rb_gc_mark(r->name);
+ rb_gc_mark(r->r_stdin);
+ rb_gc_mark(r->r_stdout);
+ rb_gc_mark(r->r_stderr);
+ rb_hook_list_mark(&r->pub.hooks);
+
+ if (r->threads.cnt > 0) {
+ rb_thread_t *th = 0;
+ list_for_each(&r->threads.set, th, lt_node) {
+ VM_ASSERT(th != NULL);
+ rb_gc_mark(th->self);
+ }
+ }
+
+ ractor_local_storage_mark(r);
+}
+
+static void
+ractor_queue_free(struct rb_ractor_queue *rq)
+{
+ free(rq->baskets);
+}
+
+static void
+ractor_waiting_list_free(struct rb_ractor_waiting_list *wl)
+{
+ free(wl->ractors);
+}
+
+static void
+ractor_free(void *ptr)
+{
+ rb_ractor_t *r = (rb_ractor_t *)ptr;
+ rb_native_mutex_destroy(&r->sync.lock);
+ rb_native_cond_destroy(&r->sync.cond);
+ ractor_queue_free(&r->sync.incoming_queue);
+ ractor_waiting_list_free(&r->sync.taking_ractors);
+ ractor_local_storage_free(r);
+ rb_hook_list_free(&r->pub.hooks);
+ ruby_xfree(r);
+}
+
+static size_t
+ractor_queue_memsize(const struct rb_ractor_queue *rq)
+{
+ return sizeof(struct rb_ractor_basket) * rq->size;
+}
+
+static size_t
+ractor_waiting_list_memsize(const struct rb_ractor_waiting_list *wl)
+{
+ return sizeof(rb_ractor_t *) * wl->size;
+}
+
+static size_t
+ractor_memsize(const void *ptr)
+{
+ rb_ractor_t *r = (rb_ractor_t *)ptr;
+
+ // TODO
+ return sizeof(rb_ractor_t) +
+ ractor_queue_memsize(&r->sync.incoming_queue) +
+ ractor_waiting_list_memsize(&r->sync.taking_ractors);
+}
+
+static const rb_data_type_t ractor_data_type = {
+ "ractor",
+ {
+ ractor_mark,
+ ractor_free,
+ ractor_memsize,
+ NULL, // update
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY /* | RUBY_TYPED_WB_PROTECTED */
+};
+
+bool
+rb_ractor_p(VALUE gv)
+{
+ if (rb_typeddata_is_kind_of(gv, &ractor_data_type)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static inline rb_ractor_t *
+RACTOR_PTR(VALUE self)
+{
+ VM_ASSERT(rb_ractor_p(self));
+
+ rb_ractor_t *r = DATA_PTR(self);
+ // TODO: check
+ return r;
+}
+
+static uint32_t ractor_last_id;
+
+#if RACTOR_CHECK_MODE > 0
+MJIT_FUNC_EXPORTED uint32_t
+rb_ractor_current_id(void)
+{
+ if (GET_THREAD()->ractor == NULL) {
+ return 1; // main ractor
+ }
+ else {
+ return rb_ractor_id(GET_RACTOR());
+ }
+}
+#endif
+
+static void
+ractor_queue_setup(struct rb_ractor_queue *rq)
+{
+ rq->size = 2;
+ rq->cnt = 0;
+ rq->start = 0;
+ rq->baskets = malloc(sizeof(struct rb_ractor_basket) * rq->size);
+}
+
+static struct rb_ractor_basket *
+ractor_queue_at(struct rb_ractor_queue *rq, int i)
+{
+ return &rq->baskets[(rq->start + i) % rq->size];
+}
+
+static void
+ractor_queue_advance(struct rb_ractor_queue *rq)
+{
+ ASSERT_ractor_locking(GET_RACTOR());
+
+ if (rq->reserved_cnt == 0) {
+ rq->cnt--;
+ rq->start = (rq->start + 1) % rq->size;
+ rq->serial++;
+ }
+ else {
+ ractor_queue_at(rq, 0)->type = basket_type_deleted;
+ }
+}
+
+static bool
+ractor_queue_skip_p(struct rb_ractor_queue *rq, int i)
+{
+ struct rb_ractor_basket *b = ractor_queue_at(rq, i);
+ return b->type == basket_type_deleted ||
+ b->type == basket_type_reserved;
+}
+
+static void
+ractor_queue_compact(rb_ractor_t *r, struct rb_ractor_queue *rq)
+{
+ ASSERT_ractor_locking(r);
+
+ while (rq->cnt > 0 && ractor_queue_at(rq, 0)->type == basket_type_deleted) {
+ ractor_queue_advance(rq);
+ }
+}
+
+static bool
+ractor_queue_empty_p(rb_ractor_t *r, struct rb_ractor_queue *rq)
+{
+ ASSERT_ractor_locking(r);
+
+ if (rq->cnt == 0) {
+ return true;
+ }
+
+ ractor_queue_compact(r, rq);
+
+ for (int i=0; i<rq->cnt; i++) {
+ if (!ractor_queue_skip_p(rq, i)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool
+ractor_queue_deq(rb_ractor_t *r, struct rb_ractor_queue *rq, struct rb_ractor_basket *basket)
+{
+ bool found = false;
+
+ RACTOR_LOCK(r);
+ {
+ if (!ractor_queue_empty_p(r, rq)) {
+ for (int i=0; i<rq->cnt; i++) {
+ if (!ractor_queue_skip_p(rq, i)) {
+ struct rb_ractor_basket *b = ractor_queue_at(rq, i);
+ *basket = *b;
+
+ // remove from queue
+ b->type = basket_type_deleted;
+ ractor_queue_compact(r, rq);
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ RACTOR_UNLOCK(r);
+
+ return found;
+}
+
+static void
+ractor_queue_enq(rb_ractor_t *r, struct rb_ractor_queue *rq, struct rb_ractor_basket *basket)
+{
+ ASSERT_ractor_locking(r);
+
+ if (rq->size <= rq->cnt) {
+ rq->baskets = realloc(rq->baskets, sizeof(struct rb_ractor_basket) * rq->size * 2);
+ for (int i=rq->size - rq->start; 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", __func__, rq, rq->cnt);
+}
+
+static void
+ractor_basket_clear(struct rb_ractor_basket *b)
+{
+ b->type = basket_type_none;
+ b->v = Qfalse;
+ b->sender = Qfalse;
+}
+
+static VALUE ractor_reset_belonging(VALUE obj); // in this file
+
+static VALUE
+ractor_basket_value(struct rb_ractor_basket *b)
+{
+ switch (b->type) {
+ case basket_type_ref:
+ break;
+ case basket_type_copy:
+ case basket_type_move:
+ case basket_type_will:
+ b->type = basket_type_ref;
+ b->v = ractor_reset_belonging(b->v);
+ break;
+ default:
+ rb_bug("unreachable");
+ }
+
+ return b->v;
+}
+
+static VALUE
+ractor_basket_accept(struct rb_ractor_basket *b)
+{
+ VALUE v = ractor_basket_value(b);
+
+ if (b->exception) {
+ VALUE cause = v;
+ VALUE err = rb_exc_new_cstr(rb_eRactorRemoteError, "thrown by remote Ractor.");
+ rb_ivar_set(err, rb_intern("@ractor"), b->sender);
+ ractor_basket_clear(b);
+ rb_ec_setup_exception(NULL, err, cause);
+ rb_exc_raise(err);
+ }
+
+ ractor_basket_clear(b);
+ return v;
+}
+
+static void
+ractor_recursive_receive_if(rb_ractor_t *r)
+{
+ if (r->receiving_mutex && rb_mutex_owned_p(r->receiving_mutex)) {
+ rb_raise(rb_eRactorError, "can not call receive/receive_if recursively");
+ }
+}
+
+static VALUE
+ractor_try_receive(rb_execution_context_t *ec, rb_ractor_t *r)
+{
+ struct rb_ractor_queue *rq = &r->sync.incoming_queue;
+ struct rb_ractor_basket basket;
+
+ ractor_recursive_receive_if(r);
+
+ if (ractor_queue_deq(r, rq, &basket) == false) {
+ if (r->sync.incoming_port_closed) {
+ rb_raise(rb_eRactorClosedError, "The incoming port is already closed");
+ }
+ else {
+ return Qundef;
+ }
+ }
+
+ return ractor_basket_accept(&basket);
+}
+
+static void *
+ractor_sleep_wo_gvl(void *ptr)
+{
+ rb_ractor_t *cr = ptr;
+ RACTOR_LOCK_SELF(cr);
+ {
+ VM_ASSERT(cr->sync.wait.status != wait_none);
+ if (cr->sync.wait.wakeup_status == wakeup_none) {
+ ractor_cond_wait(cr);
+ }
+ cr->sync.wait.status = wait_none;
+ }
+ RACTOR_UNLOCK_SELF(cr);
+ return NULL;
+}
+
+static void
+ractor_sleep_interrupt(void *ptr)
+{
+ rb_ractor_t *r = ptr;
+
+ RACTOR_LOCK(r);
+ if (r->sync.wait.wakeup_status == wakeup_none) {
+ r->sync.wait.wakeup_status = wakeup_by_interrupt;
+ rb_native_cond_signal(&r->sync.cond);
+ }
+ RACTOR_UNLOCK(r);
+}
+
+#if USE_RUBY_DEBUG_LOG
+static const char *
+wait_status_str(enum ractor_wait_status wait_status)
+{
+ switch ((int)wait_status) {
+ case wait_none: return "none";
+ case wait_receiving: return "receiving";
+ case wait_taking: return "taking";
+ case wait_yielding: return "yielding";
+ case wait_receiving|wait_taking: return "receiving|taking";
+ case wait_receiving|wait_yielding: return "receiving|yielding";
+ case wait_taking|wait_yielding: return "taking|yielding";
+ case wait_receiving|wait_taking|wait_yielding: return "receiving|taking|yielding";
+ }
+ rb_bug("unrechable");
+}
+
+static const char *
+wakeup_status_str(enum ractor_wakeup_status wakeup_status)
+{
+ switch (wakeup_status) {
+ case wakeup_none: return "none";
+ case wakeup_by_send: return "by_send";
+ case wakeup_by_yield: return "by_yield";
+ case wakeup_by_take: return "by_take";
+ case wakeup_by_close: return "by_close";
+ case wakeup_by_interrupt: return "by_interrupt";
+ case wakeup_by_retry: return "by_retry";
+ }
+ rb_bug("unrechable");
+}
+#endif // USE_RUBY_DEBUG_LOG
+
+static void
+ractor_sleep(rb_execution_context_t *ec, rb_ractor_t *cr)
+{
+ VM_ASSERT(GET_RACTOR() == cr);
+ VM_ASSERT(cr->sync.wait.status != wait_none);
+ // fprintf(stderr, "%s r:%p status:%s, wakeup_status:%s\n", __func__, cr,
+ // wait_status_str(cr->sync.wait.status), wakeup_status_str(cr->sync.wait.wakeup_status));
+
+ RACTOR_UNLOCK(cr);
+ {
+ rb_nogvl(ractor_sleep_wo_gvl, cr,
+ ractor_sleep_interrupt, cr,
+ RB_NOGVL_UBF_ASYNC_SAFE | RB_NOGVL_INTR_FAIL);
+ }
+ RACTOR_LOCK(cr);
+
+ // rb_nogvl() can be canceled by interrupts
+ if (cr->sync.wait.status != wait_none) {
+ cr->sync.wait.status = wait_none;
+ cr->sync.wait.wakeup_status = wakeup_by_interrupt;
+
+ RACTOR_UNLOCK(cr);
+ rb_thread_check_ints();
+ RACTOR_LOCK(cr); // reachable?
+ }
+}
+
+static bool
+ractor_sleeping_by(const rb_ractor_t *r, enum ractor_wait_status wait_status)
+{
+ return (r->sync.wait.status & wait_status) && r->sync.wait.wakeup_status == wakeup_none;
+}
+
+static bool
+ractor_wakeup(rb_ractor_t *r, enum ractor_wait_status wait_status, enum ractor_wakeup_status wakeup_status)
+{
+ ASSERT_ractor_locking(r);
+
+ // fprintf(stderr, "%s r:%p status:%s/%s wakeup_status:%s/%s\n", __func__, r,
+ // wait_status_str(r->sync.wait.status), wait_status_str(wait_status),
+ // wakeup_status_str(r->sync.wait.wakeup_status), wakeup_status_str(wakeup_status));
+
+ if (ractor_sleeping_by(r, wait_status)) {
+ r->sync.wait.wakeup_status = wakeup_status;
+ rb_native_cond_signal(&r->sync.cond);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static void
+ractor_register_taking(rb_ractor_t *r, rb_ractor_t *cr)
+{
+ VM_ASSERT(cr == GET_RACTOR());
+ bool retry_try = false;
+
+ RACTOR_LOCK(r);
+ {
+ if (ractor_sleeping_by(r, wait_yielding)) {
+ // already waiting for yielding. retry try_take.
+ retry_try = true;
+ }
+ else {
+ // insert cr into taking list
+ struct rb_ractor_waiting_list *wl = &r->sync.taking_ractors;
+
+ for (int i=0; i<wl->cnt; i++) {
+ if (wl->ractors[i] == cr) {
+ // TODO: make it clean code.
+ rb_native_mutex_unlock(&r->sync.lock);
+ rb_raise(rb_eRuntimeError, "Already another thread of same ractor is waiting.");
+ }
+ }
+
+ if (wl->size == 0) {
+ wl->size = 1;
+ wl->ractors = malloc(sizeof(rb_ractor_t *) * wl->size);
+ if (wl->ractors == NULL) rb_bug("can't allocate buffer");
+ }
+ else if (wl->size <= wl->cnt + 1) {
+ wl->size *= 2;
+ wl->ractors = realloc(wl->ractors, sizeof(rb_ractor_t *) * wl->size);
+ if (wl->ractors == NULL) rb_bug("can't re-allocate buffer");
+ }
+ wl->ractors[wl->cnt++] = cr;
+ }
+ }
+ RACTOR_UNLOCK(r);
+
+ if (retry_try) {
+ RACTOR_LOCK(cr);
+ {
+ if (cr->sync.wait.wakeup_status == wakeup_none) {
+ VM_ASSERT(cr->sync.wait.status != wait_none);
+
+ cr->sync.wait.wakeup_status = wakeup_by_retry;
+ cr->sync.wait.status = wait_none;
+ }
+ }
+ RACTOR_UNLOCK(cr);
+ }
+}
+
+static void
+ractor_waiting_list_del(rb_ractor_t *r, struct rb_ractor_waiting_list *wl, rb_ractor_t *wr)
+{
+ RACTOR_LOCK(r);
+ {
+ int pos = -1;
+ for (int i=0; i<wl->cnt; i++) {
+ if (wl->ractors[i] == wr) {
+ pos = i;
+ break;
+ }
+ }
+ if (pos >= 0) { // found
+ wl->cnt--;
+ for (int i=pos; i<wl->cnt; i++) {
+ wl->ractors[i] = wl->ractors[i+1];
+ }
+ }
+ }
+ RACTOR_UNLOCK(r);
+}
+
+static rb_ractor_t *
+ractor_waiting_list_shift(rb_ractor_t *r, struct rb_ractor_waiting_list *wl)
+{
+ ASSERT_ractor_locking(r);
+ VM_ASSERT(&r->sync.taking_ractors == wl);
+
+ if (wl->cnt > 0) {
+ rb_ractor_t *tr = wl->ractors[0];
+ for (int i=1; i<wl->cnt; i++) {
+ wl->ractors[i-1] = wl->ractors[i];
+ }
+ wl->cnt--;
+ return tr;
+ }
+ else {
+ return NULL;
+ }
+}
+
+static void
+ractor_receive_wait(rb_execution_context_t *ec, rb_ractor_t *cr)
+{
+ VM_ASSERT(cr == rb_ec_ractor_ptr(ec));
+ ractor_recursive_receive_if(cr);
+
+ RACTOR_LOCK(cr);
+ {
+ if (ractor_queue_empty_p(cr, &cr->sync.incoming_queue)) {
+ VM_ASSERT(cr->sync.wait.status == wait_none);
+ cr->sync.wait.status = wait_receiving;
+ cr->sync.wait.wakeup_status = wakeup_none;
+ ractor_sleep(ec, cr);
+ cr->sync.wait.wakeup_status = wakeup_none;
+ }
+ }
+ RACTOR_UNLOCK(cr);
+}
+
+static VALUE
+ractor_receive(rb_execution_context_t *ec, rb_ractor_t *cr)
+{
+ VM_ASSERT(cr == rb_ec_ractor_ptr(ec));
+ VALUE v;
+
+ while ((v = ractor_try_receive(ec, cr)) == Qundef) {
+ ractor_receive_wait(ec, cr);
+ }
+
+ return v;
+}
+
+#if 0
+// for debug
+static const char *
+basket_type_name(enum rb_ractor_basket_type type)
+{
+ switch (type) {
+#define T(t) case basket_type_##t: return #t
+ T(none);
+ T(ref);
+ T(copy);
+ T(move);
+ T(will);
+ T(deleted);
+ T(reserved);
+ default: rb_bug("unreachable");
+ }
+}
+
+static void
+rq_dump(struct rb_ractor_queue *rq)
+{
+ bool bug = false;
+ for (int i=0; i<rq->cnt; i++) {
+ struct rb_ractor_basket *b = ractor_queue_at(rq, i);
+ fprintf(stderr, "%d (start:%d) type:%s %p %s\n", i, rq->start, basket_type_name(b->type), b, RSTRING_PTR(RARRAY_AREF(b->v, 1)));
+ if (b->type == basket_type_reserved) bug = true;
+ }
+ if (bug) rb_bug("!!");
+}
+#endif
+
+struct receive_block_data {
+ rb_ractor_t *cr;
+ struct rb_ractor_queue *rq;
+ VALUE v;
+ int index;
+ bool success;
+};
+
+static void
+ractor_receive_if_lock(rb_ractor_t *cr)
+{
+ VALUE m = cr->receiving_mutex;
+ if (m == Qfalse) {
+ m = cr->receiving_mutex = rb_mutex_new();
+ }
+ rb_mutex_lock(m);
+}
+
+static VALUE
+receive_if_body(VALUE ptr)
+{
+ struct receive_block_data *data = (struct receive_block_data *)ptr;
+
+ ractor_receive_if_lock(data->cr);
+ VALUE block_result = rb_yield(data->v);
+
+ RACTOR_LOCK_SELF(data->cr);
+ {
+ struct rb_ractor_basket *b = ractor_queue_at(data->rq, data->index);
+ VM_ASSERT(b->type == basket_type_reserved);
+ data->rq->reserved_cnt--;
+
+ if (RTEST(block_result)) {
+ b->type = basket_type_deleted;
+ ractor_queue_compact(data->cr, data->rq);
+ }
+ else {
+ b->type = basket_type_ref;
+ }
+ }
+ RACTOR_UNLOCK_SELF(data->cr);
+
+ data->success = true;
+
+ if (RTEST(block_result)) {
+ return data->v;
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+receive_if_ensure(VALUE v)
+{
+ struct receive_block_data *data = (struct receive_block_data *)v;
+
+ if (!data->success) {
+ RACTOR_LOCK_SELF(data->cr);
+ {
+ struct rb_ractor_basket *b = ractor_queue_at(data->rq, data->index);
+ VM_ASSERT(b->type == basket_type_reserved);
+ b->type = basket_type_deleted;
+ data->rq->reserved_cnt--;
+ }
+ RACTOR_UNLOCK_SELF(data->cr);
+ }
+
+ rb_mutex_unlock(data->cr->receiving_mutex);
+ return Qnil;
+}
+
+static VALUE
+ractor_receive_if(rb_execution_context_t *ec, VALUE crv, VALUE b)
+{
+ if (!RTEST(b)) rb_raise(rb_eArgError, "no block given");
+
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ unsigned int serial = (unsigned int)-1;
+ int index = 0;
+ struct rb_ractor_queue *rq = &cr->sync.incoming_queue;
+
+ while (1) {
+ VALUE v = Qundef;
+
+ ractor_receive_wait(ec, cr);
+
+ RACTOR_LOCK_SELF(cr);
+ {
+ if (serial != rq->serial) {
+ serial = rq->serial;
+ index = 0;
+ }
+
+ // check newer version
+ for (int i=index; i<rq->cnt; i++) {
+ if (!ractor_queue_skip_p(rq, i)) {
+ struct rb_ractor_basket *b = ractor_queue_at(rq, i);
+ v = ractor_basket_value(b);
+ b->type = basket_type_reserved;
+ rq->reserved_cnt++;
+ index = i;
+ break;
+ }
+ }
+ }
+ RACTOR_UNLOCK_SELF(cr);
+
+ if (v != Qundef) {
+ struct receive_block_data data = {
+ .cr = cr,
+ .rq = rq,
+ .v = v,
+ .index = index,
+ .success = false,
+ };
+
+ VALUE result = rb_ensure(receive_if_body, (VALUE)&data,
+ receive_if_ensure, (VALUE)&data);
+
+ if (result != Qundef) return result;
+ index++;
+ }
+ }
+}
+
+static void
+ractor_send_basket(rb_execution_context_t *ec, rb_ractor_t *r, struct rb_ractor_basket *b)
+{
+ bool closed = false;
+ struct rb_ractor_queue *rq = &r->sync.incoming_queue;
+
+ RACTOR_LOCK(r);
+ {
+ if (r->sync.incoming_port_closed) {
+ closed = true;
+ }
+ else {
+ ractor_queue_enq(r, rq, b);
+ if (ractor_wakeup(r, wait_receiving, wakeup_by_send)) {
+ RUBY_DEBUG_LOG("wakeup", 0);
+ }
+ }
+ }
+ RACTOR_UNLOCK(r);
+
+ if (closed) {
+ rb_raise(rb_eRactorClosedError, "The incoming-port is already closed");
+ }
+}
+
+static VALUE ractor_move(VALUE obj); // in this file
+static VALUE ractor_copy(VALUE obj); // in this file
+
+static void
+ractor_basket_setup(rb_execution_context_t *ec, struct rb_ractor_basket *basket, VALUE obj, VALUE move, bool exc, bool is_will, bool is_yield)
+{
+ basket->sender = rb_ec_ractor_ptr(ec)->pub.self;
+ basket->exception = exc;
+
+ if (is_will) {
+ basket->type = basket_type_will;
+ basket->v = obj;
+ }
+ else if (rb_ractor_shareable_p(obj)) {
+ basket->type = basket_type_ref;
+ basket->v = obj;
+ }
+ else if (!RTEST(move)) {
+ basket->v = ractor_copy(obj);
+ basket->type = basket_type_copy;
+ }
+ else {
+ basket->type = basket_type_move;
+
+ if (is_yield) {
+ basket->v = obj; // call ractor_move() when yielding timing.
+ }
+ else {
+ basket->v = ractor_move(obj);
+ }
+ }
+}
+
+static VALUE
+ractor_send(rb_execution_context_t *ec, rb_ractor_t *r, VALUE obj, VALUE move)
+{
+ struct rb_ractor_basket basket;
+ ractor_basket_setup(ec, &basket, obj, move, false, false, false);
+ ractor_send_basket(ec, r, &basket);
+ return r->pub.self;
+}
+
+static VALUE
+ractor_try_take(rb_execution_context_t *ec, rb_ractor_t *r)
+{
+ struct rb_ractor_basket basket = {
+ .type = basket_type_none,
+ };
+ bool closed = false;
+
+ RACTOR_LOCK(r);
+ {
+ if (ractor_sleeping_by(r, wait_yielding)) {
+ MAYBE_UNUSED(bool) wakeup_result;
+ VM_ASSERT(r->sync.wait.yielded_basket.type != basket_type_none);
+
+ if (r->sync.wait.yielded_basket.type == basket_type_move) {
+ wakeup_result = ractor_wakeup(r, wait_yielding, wakeup_by_retry);
+ }
+ else {
+ wakeup_result = ractor_wakeup(r, wait_yielding, wakeup_by_take);
+ basket = r->sync.wait.yielded_basket;
+ ractor_basket_clear(&r->sync.wait.yielded_basket);
+ }
+ VM_ASSERT(wakeup_result);
+ }
+ else if (r->sync.outgoing_port_closed) {
+ closed = true;
+ }
+ }
+ RACTOR_UNLOCK(r);
+
+ if (basket.type == basket_type_none) {
+ if (closed) {
+ rb_raise(rb_eRactorClosedError, "The outgoing-port is already closed");
+ }
+ else {
+ return Qundef;
+ }
+ }
+ else {
+ return ractor_basket_accept(&basket);
+ }
+}
+
+static VALUE
+ractor_yield_move_body(VALUE v)
+{
+ return ractor_move(v);
+}
+
+static bool
+ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_basket *basket)
+{
+ ASSERT_ractor_unlocking(cr);
+ VM_ASSERT(basket->type != basket_type_none);
+
+ if (cr->sync.outgoing_port_closed) {
+ rb_raise(rb_eRactorClosedError, "The outgoing-port is already closed");
+ }
+
+ rb_ractor_t *r;
+
+ retry_shift:
+ RACTOR_LOCK(cr);
+ {
+ r = ractor_waiting_list_shift(cr, &cr->sync.taking_ractors);
+ }
+ RACTOR_UNLOCK(cr);
+
+ if (r) {
+ bool retry_shift = false;
+
+ RACTOR_LOCK(r);
+ {
+ if (ractor_sleeping_by(r, wait_taking)) {
+ VM_ASSERT(r->sync.wait.taken_basket.type == basket_type_none);
+
+ if (basket->type == basket_type_move) {
+ enum ractor_wait_status prev_wait_status = r->sync.wait.status;
+ r->sync.wait.status = wait_moving;
+
+ RACTOR_UNLOCK(r);
+ {
+ int state;
+ VALUE moved_value = rb_protect(ractor_yield_move_body, basket->v, &state);
+ if (state) {
+ r->sync.wait.status = prev_wait_status;
+ rb_jump_tag(state);
+ }
+ else {
+ basket->v = moved_value;
+ }
+ }
+ RACTOR_LOCK(r);
+
+ if (!ractor_wakeup(r, wait_moving, wakeup_by_yield)) {
+ // terminating?
+ }
+ }
+ else {
+ ractor_wakeup(r, wait_taking, wakeup_by_yield);
+ }
+ r->sync.wait.taken_basket = *basket;
+ }
+ else {
+ retry_shift = true;
+ }
+ }
+ RACTOR_UNLOCK(r);
+
+ if (retry_shift) {
+ // get candidate take-waiting ractor, but already woke up by another reason.
+ // retry to check another ractor.
+ goto retry_shift;
+ }
+ else {
+ return true;
+ }
+ }
+ else {
+ return false;
+ }
+}
+
+// select(r1, r2, r3, receive: true, yield: obj)
+static VALUE
+ractor_select(rb_execution_context_t *ec, const VALUE *rs, const int rs_len, VALUE yielded_value, bool move, VALUE *ret_r)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ VALUE crv = cr->pub.self;
+ VALUE ret = Qundef;
+ int i;
+ bool interrupted = false;
+ enum ractor_wait_status wait_status = 0;
+ bool yield_p = (yielded_value != Qundef) ? true : false;
+ const int alen = rs_len + (yield_p ? 1 : 0);
+
+ struct ractor_select_action {
+ enum ractor_select_action_type {
+ ractor_select_action_take,
+ ractor_select_action_receive,
+ ractor_select_action_yield,
+ } type;
+ VALUE v;
+ } *actions = ALLOCA_N(struct ractor_select_action, alen);
+
+ VM_ASSERT(cr->sync.wait.status == wait_none);
+ VM_ASSERT(cr->sync.wait.wakeup_status == wakeup_none);
+ VM_ASSERT(cr->sync.wait.taken_basket.type == basket_type_none);
+ VM_ASSERT(cr->sync.wait.yielded_basket.type == basket_type_none);
+
+ // setup actions
+ for (i=0; i<rs_len; i++) {
+ VALUE v = rs[i];
+
+ if (v == crv) {
+ actions[i].type = ractor_select_action_receive;
+ actions[i].v = Qnil;
+ wait_status |= wait_receiving;
+ }
+ else if (rb_ractor_p(v)) {
+ actions[i].type = ractor_select_action_take;
+ actions[i].v = v;
+ wait_status |= wait_taking;
+ }
+ else {
+ rb_raise(rb_eArgError, "should be a ractor object, but %"PRIsVALUE, v);
+ }
+ }
+ rs = NULL;
+
+ restart:
+
+ if (yield_p) {
+ actions[rs_len].type = ractor_select_action_yield;
+ actions[rs_len].v = Qundef;
+ wait_status |= wait_yielding;
+ ractor_basket_setup(ec, &cr->sync.wait.yielded_basket, yielded_value, move, false, false, true);
+ }
+
+ // TODO: shuffle actions
+
+ while (1) {
+ RUBY_DEBUG_LOG("try actions (%s)", wait_status_str(wait_status));
+
+ for (i=0; i<alen; i++) {
+ VALUE v, rv;
+ switch (actions[i].type) {
+ case ractor_select_action_take:
+ rv = actions[i].v;
+ v = ractor_try_take(ec, RACTOR_PTR(rv));
+ if (v != Qundef) {
+ *ret_r = rv;
+ ret = v;
+ goto cleanup;
+ }
+ break;
+ case ractor_select_action_receive:
+ v = ractor_try_receive(ec, cr);
+ if (v != Qundef) {
+ *ret_r = ID2SYM(rb_intern("receive"));
+ ret = v;
+ goto cleanup;
+ }
+ break;
+ case ractor_select_action_yield:
+ {
+ if (ractor_try_yield(ec, cr, &cr->sync.wait.yielded_basket)) {
+ *ret_r = ID2SYM(rb_intern("yield"));
+ ret = Qnil;
+ goto cleanup;
+ }
+ }
+ break;
+ }
+ }
+
+ RUBY_DEBUG_LOG("wait actions (%s)", wait_status_str(wait_status));
+
+ RACTOR_LOCK(cr);
+ {
+ VM_ASSERT(cr->sync.wait.status == wait_none);
+ cr->sync.wait.status = wait_status;
+ cr->sync.wait.wakeup_status = wakeup_none;
+ }
+ RACTOR_UNLOCK(cr);
+
+ // prepare waiting
+ for (i=0; i<alen; i++) {
+ rb_ractor_t *r;
+ switch (actions[i].type) {
+ case ractor_select_action_take:
+ r = RACTOR_PTR(actions[i].v);
+ ractor_register_taking(r, cr);
+ break;
+ case ractor_select_action_yield:
+ case ractor_select_action_receive:
+ break;
+ }
+ }
+
+ // wait
+ RACTOR_LOCK(cr);
+ {
+ if (cr->sync.wait.wakeup_status == wakeup_none) {
+ for (i=0; i<alen; i++) {
+ rb_ractor_t *r;
+
+ switch (actions[i].type) {
+ case ractor_select_action_take:
+ r = RACTOR_PTR(actions[i].v);
+ if (ractor_sleeping_by(r, wait_yielding)) {
+ RUBY_DEBUG_LOG("wakeup_none, but r:%u is waiting for yielding", r->pub.id);
+ cr->sync.wait.wakeup_status = wakeup_by_retry;
+ goto skip_sleep;
+ }
+ break;
+ case ractor_select_action_receive:
+ if (cr->sync.incoming_queue.cnt > 0) {
+ RUBY_DEBUG_LOG("wakeup_none, but incoming_queue has %u messages", cr->sync.incoming_queue.cnt);
+ cr->sync.wait.wakeup_status = wakeup_by_retry;
+ goto skip_sleep;
+ }
+ break;
+ case ractor_select_action_yield:
+ if (cr->sync.taking_ractors.cnt > 0) {
+ RUBY_DEBUG_LOG("wakeup_none, but %u taking_ractors are waiting", cr->sync.taking_ractors.cnt);
+ cr->sync.wait.wakeup_status = wakeup_by_retry;
+ goto skip_sleep;
+ }
+ else if (cr->sync.outgoing_port_closed) {
+ cr->sync.wait.wakeup_status = wakeup_by_close;
+ goto skip_sleep;
+ }
+ break;
+ }
+ }
+
+ RUBY_DEBUG_LOG("sleep %s", wait_status_str(cr->sync.wait.status));
+ ractor_sleep(ec, cr);
+ RUBY_DEBUG_LOG("awaken %s", wakeup_status_str(cr->sync.wait.wakeup_status));
+ }
+ else {
+ skip_sleep:
+ RUBY_DEBUG_LOG("no need to sleep %s->%s",
+ wait_status_str(cr->sync.wait.status),
+ wakeup_status_str(cr->sync.wait.wakeup_status));
+ cr->sync.wait.status = wait_none;
+ }
+ }
+ RACTOR_UNLOCK(cr);
+
+ // cleanup waiting
+ for (i=0; i<alen; i++) {
+ rb_ractor_t *r;
+ switch (actions[i].type) {
+ case ractor_select_action_take:
+ r = RACTOR_PTR(actions[i].v);
+ ractor_waiting_list_del(r, &r->sync.taking_ractors, cr);
+ break;
+ case ractor_select_action_receive:
+ case ractor_select_action_yield:
+ break;
+ }
+ }
+
+ // check results
+ enum ractor_wakeup_status wakeup_status = cr->sync.wait.wakeup_status;
+ cr->sync.wait.wakeup_status = wakeup_none;
+
+ switch (wakeup_status) {
+ case wakeup_none:
+ // OK. something happens.
+ // retry loop.
+ break;
+ case wakeup_by_retry:
+ // Retry request.
+ break;
+ case wakeup_by_send:
+ // OK.
+ // retry loop and try_receive will succss.
+ break;
+ case wakeup_by_yield:
+ // take was succeeded!
+ // cr.wait.taken_basket contains passed block
+ VM_ASSERT(cr->sync.wait.taken_basket.type != basket_type_none);
+ *ret_r = cr->sync.wait.taken_basket.sender;
+ VM_ASSERT(rb_ractor_p(*ret_r));
+ ret = ractor_basket_accept(&cr->sync.wait.taken_basket);
+ goto cleanup;
+ case wakeup_by_take:
+ *ret_r = ID2SYM(rb_intern("yield"));
+ ret = Qnil;
+ goto cleanup;
+ case wakeup_by_close:
+ // OK.
+ // retry loop and will get CloseError.
+ break;
+ case wakeup_by_interrupt:
+ ret = Qundef;
+ interrupted = true;
+ goto cleanup;
+ }
+ }
+
+ cleanup:
+ RUBY_DEBUG_LOG("cleanup actions (%s)", wait_status_str(wait_status));
+
+ if (cr->sync.wait.yielded_basket.type != basket_type_none) {
+ ractor_basket_clear(&cr->sync.wait.yielded_basket);
+ }
+
+ VM_ASSERT(cr->sync.wait.status == wait_none);
+ VM_ASSERT(cr->sync.wait.wakeup_status == wakeup_none);
+ VM_ASSERT(cr->sync.wait.taken_basket.type == basket_type_none);
+ VM_ASSERT(cr->sync.wait.yielded_basket.type == basket_type_none);
+
+ if (interrupted) {
+ rb_vm_check_ints_blocking(ec);
+ interrupted = false;
+ goto restart;
+ }
+
+ VM_ASSERT(ret != Qundef);
+ return ret;
+}
+
+static VALUE
+ractor_yield(rb_execution_context_t *ec, rb_ractor_t *r, VALUE obj, VALUE move)
+{
+ VALUE ret_r;
+ ractor_select(ec, NULL, 0, obj, RTEST(move) ? true : false, &ret_r);
+ return Qnil;
+}
+
+static VALUE
+ractor_take(rb_execution_context_t *ec, rb_ractor_t *r)
+{
+ VALUE ret_r;
+ VALUE v = ractor_select(ec, &r->pub.self, 1, Qundef, false, &ret_r);
+ return v;
+}
+
+static VALUE
+ractor_close_incoming(rb_execution_context_t *ec, rb_ractor_t *r)
+{
+ VALUE prev;
+
+ RACTOR_LOCK(r);
+ {
+ if (!r->sync.incoming_port_closed) {
+ prev = Qfalse;
+ r->sync.incoming_port_closed = true;
+ if (ractor_wakeup(r, wait_receiving, wakeup_by_close)) {
+ VM_ASSERT(r->sync.incoming_queue.cnt == 0);
+ RUBY_DEBUG_LOG("cancel receiving", 0);
+ }
+ }
+ else {
+ prev = Qtrue;
+ }
+ }
+ RACTOR_UNLOCK(r);
+ return prev;
+}
+
+static VALUE
+ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *r)
+{
+ VALUE prev;
+
+ RACTOR_LOCK(r);
+ {
+ if (!r->sync.outgoing_port_closed) {
+ prev = Qfalse;
+ r->sync.outgoing_port_closed = true;
+ }
+ else {
+ prev = Qtrue;
+ }
+
+ // wakeup all taking ractors
+ rb_ractor_t *taking_ractor;
+ while ((taking_ractor = ractor_waiting_list_shift(r, &r->sync.taking_ractors)) != NULL) {
+ RACTOR_LOCK(taking_ractor);
+ ractor_wakeup(taking_ractor, wait_taking, wakeup_by_close);
+ RACTOR_UNLOCK(taking_ractor);
+ }
+
+ // raising yielding Ractor
+ if (!r->yield_atexit &&
+ ractor_wakeup(r, wait_yielding, wakeup_by_close)) {
+ RUBY_DEBUG_LOG("cancel yielding", 0);
+ }
+ }
+ RACTOR_UNLOCK(r);
+ return prev;
+}
+
+// creation/termination
+
+static uint32_t
+ractor_next_id(void)
+{
+ uint32_t id;
+
+ RB_VM_LOCK();
+ {
+ id = ++ractor_last_id;
+ }
+ RB_VM_UNLOCK();
+
+ return id;
+}
+
+static void
+vm_insert_ractor0(rb_vm_t *vm, rb_ractor_t *r, bool single_ractor_mode)
+{
+ RUBY_DEBUG_LOG("r:%u ractor.cnt:%u++", r->pub.id, vm->ractor.cnt);
+ VM_ASSERT(single_ractor_mode || RB_VM_LOCKED_P());
+
+ list_add_tail(&vm->ractor.set, &r->vmlr_node);
+ vm->ractor.cnt++;
+}
+
+static void
+cancel_single_ractor_mode(void)
+{
+ // enable multi-ractor mode
+ RUBY_DEBUG_LOG("enable multi-ractor mode", 0);
+
+ rb_gc_start();
+ rb_transient_heap_evacuate();
+
+ ruby_single_main_ractor = NULL;
+
+ if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
+ rb_category_warn(RB_WARN_CATEGORY_EXPERIMENTAL,
+ "Ractor is experimental, and the behavior may change in future versions of Ruby! "
+ "Also there are many implementation issues.");
+ }
+}
+
+static void
+vm_insert_ractor(rb_vm_t *vm, rb_ractor_t *r)
+{
+ VM_ASSERT(ractor_status_p(r, ractor_created));
+
+ if (rb_multi_ractor_p()) {
+ RB_VM_LOCK();
+ {
+ vm_insert_ractor0(vm, r, false);
+ vm_ractor_blocking_cnt_inc(vm, r, __FILE__, __LINE__);
+ }
+ RB_VM_UNLOCK();
+ }
+ else {
+ if (vm->ractor.cnt == 0) {
+ // main ractor
+ vm_insert_ractor0(vm, r, true);
+ ractor_status_set(r, ractor_blocking);
+ ractor_status_set(r, ractor_running);
+ }
+ else {
+ cancel_single_ractor_mode();
+ vm_insert_ractor0(vm, r, true);
+ vm_ractor_blocking_cnt_inc(vm, r, __FILE__, __LINE__);
+ }
+ }
+}
+
+static void
+vm_remove_ractor(rb_vm_t *vm, rb_ractor_t *cr)
+{
+ VM_ASSERT(ractor_status_p(cr, ractor_running));
+ VM_ASSERT(vm->ractor.cnt > 1);
+ VM_ASSERT(cr->threads.cnt == 1);
+
+ RB_VM_LOCK();
+ {
+ RUBY_DEBUG_LOG("ractor.cnt:%u-- terminate_waiting:%d",
+ vm->ractor.cnt, vm->ractor.sync.terminate_waiting);
+
+ VM_ASSERT(vm->ractor.cnt > 0);
+ list_del(&cr->vmlr_node);
+
+ if (vm->ractor.cnt <= 2 && vm->ractor.sync.terminate_waiting) {
+ rb_native_cond_signal(&vm->ractor.sync.terminate_cond);
+ }
+ vm->ractor.cnt--;
+
+ /* Clear the cached freelist to prevent a memory leak. */
+ rb_gc_ractor_newobj_cache_clear(&cr->newobj_cache);
+
+ ractor_status_set(cr, ractor_terminated);
+ }
+ RB_VM_UNLOCK();
+}
+
+static VALUE
+ractor_alloc(VALUE klass)
+{
+ rb_ractor_t *r;
+ VALUE rv = TypedData_Make_Struct(klass, rb_ractor_t, &ractor_data_type, r);
+ FL_SET_RAW(rv, RUBY_FL_SHAREABLE);
+ r->pub.self = rv;
+ VM_ASSERT(ractor_status_p(r, ractor_created));
+ return rv;
+}
+
+rb_ractor_t *
+rb_ractor_main_alloc(void)
+{
+ rb_ractor_t *r = ruby_mimmalloc(sizeof(rb_ractor_t));
+ if (r == NULL) {
+ fprintf(stderr, "[FATAL] failed to allocate memory for main ractor\n");
+ exit(EXIT_FAILURE);
+ }
+ MEMZERO(r, rb_ractor_t, 1);
+ r->pub.id = ++ractor_last_id;
+ r->loc = Qnil;
+ r->name = Qnil;
+ r->pub.self = Qnil;
+ ruby_single_main_ractor = r;
+
+ return r;
+}
+
+#if defined(HAVE_WORKING_FORK)
+void
+rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th)
+{
+ // initialize as a main ractor
+ vm->ractor.cnt = 0;
+ vm->ractor.blocking_cnt = 0;
+ ruby_single_main_ractor = th->ractor;
+ th->ractor->status_ = ractor_created;
+
+ rb_ractor_living_threads_init(th->ractor);
+ rb_ractor_living_threads_insert(th->ractor, th);
+
+ VM_ASSERT(vm->ractor.blocking_cnt == 0);
+ VM_ASSERT(vm->ractor.cnt == 1);
+}
+#endif
+
+void rb_gvl_init(rb_global_vm_lock_t *gvl);
+
+void
+rb_ractor_living_threads_init(rb_ractor_t *r)
+{
+ list_head_init(&r->threads.set);
+ r->threads.cnt = 0;
+ r->threads.blocking_cnt = 0;
+}
+
+static void
+ractor_init(rb_ractor_t *r, VALUE name, VALUE loc)
+{
+ ractor_queue_setup(&r->sync.incoming_queue);
+ rb_native_mutex_initialize(&r->sync.lock);
+ rb_native_cond_initialize(&r->sync.cond);
+ rb_native_cond_initialize(&r->barrier_wait_cond);
+
+ // thread management
+ rb_gvl_init(&r->threads.gvl);
+ rb_ractor_living_threads_init(r);
+
+ // naming
+ if (!NIL_P(name)) {
+ rb_encoding *enc;
+ StringValueCStr(name);
+ enc = rb_enc_get(name);
+ if (!rb_enc_asciicompat(enc)) {
+ rb_raise(rb_eArgError, "ASCII incompatible encoding (%s)",
+ rb_enc_name(enc));
+ }
+ name = rb_str_new_frozen(name);
+ }
+ r->name = name;
+ r->loc = loc;
+}
+
+void
+rb_ractor_main_setup(rb_vm_t *vm, rb_ractor_t *r, rb_thread_t *th)
+{
+ r->pub.self = TypedData_Wrap_Struct(rb_cRactor, &ractor_data_type, r);
+ FL_SET_RAW(r->pub.self, RUBY_FL_SHAREABLE);
+ ractor_init(r, Qnil, Qnil);
+ r->threads.main = th;
+ rb_ractor_living_threads_insert(r, th);
+}
+
+static VALUE
+ractor_create(rb_execution_context_t *ec, VALUE self, VALUE loc, VALUE name, VALUE args, VALUE block)
+{
+ VALUE rv = ractor_alloc(self);
+ rb_ractor_t *r = RACTOR_PTR(rv);
+ ractor_init(r, name, loc);
+
+ // can block here
+ r->pub.id = ractor_next_id();
+ RUBY_DEBUG_LOG("r:%u", r->pub.id);
+
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ r->verbose = cr->verbose;
+ r->debug = cr->debug;
+
+ rb_thread_create_ractor(r, args, block);
+
+ RB_GC_GUARD(rv);
+ return rv;
+}
+
+static void
+ractor_yield_atexit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE v, bool exc)
+{
+ if (cr->sync.outgoing_port_closed) {
+ return;
+ }
+
+ ASSERT_ractor_unlocking(cr);
+
+ struct rb_ractor_basket basket;
+ ractor_basket_setup(ec, &basket, v, Qfalse, exc, true, true /* this flag is ignored because move is Qfalse */);
+
+ retry:
+ if (ractor_try_yield(ec, cr, &basket)) {
+ // OK.
+ }
+ else {
+ bool retry = false;
+ RACTOR_LOCK(cr);
+ {
+ if (cr->sync.taking_ractors.cnt == 0) {
+ cr->sync.wait.yielded_basket = basket;
+
+ VM_ASSERT(cr->sync.wait.status == wait_none);
+ cr->sync.wait.status = wait_yielding;
+ cr->sync.wait.wakeup_status = wakeup_none;
+
+ VM_ASSERT(cr->yield_atexit == false);
+ cr->yield_atexit = true;
+ }
+ else {
+ retry = true; // another ractor is waiting for the yield.
+ }
+ }
+ RACTOR_UNLOCK(cr);
+
+ if (retry) goto retry;
+ }
+}
+
+void
+rb_ractor_teardown(rb_execution_context_t *ec)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ ractor_close_incoming(ec, cr);
+ ractor_close_outgoing(ec, cr);
+
+ // sync with rb_ractor_terminate_interrupt_main_thread()
+ RB_VM_LOCK_ENTER();
+ {
+ VM_ASSERT(cr->threads.main != NULL);
+ cr->threads.main = NULL;
+ }
+ RB_VM_LOCK_LEAVE();
+}
+
+void
+rb_ractor_atexit(rb_execution_context_t *ec, VALUE result)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ ractor_yield_atexit(ec, cr, result, false);
+}
+
+void
+rb_ractor_atexit_exception(rb_execution_context_t *ec)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ ractor_yield_atexit(ec, cr, ec->errinfo, true);
+}
+
+void
+rb_ractor_receive_parameters(rb_execution_context_t *ec, rb_ractor_t *r, int len, VALUE *ptr)
+{
+ for (int i=0; i<len; i++) {
+ ptr[i] = ractor_receive(ec, r);
+ }
+}
+
+void
+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);
+ }
+}
+
+MJIT_FUNC_EXPORTED bool
+rb_ractor_main_p_(void)
+{
+ VM_ASSERT(rb_multi_ractor_p());
+ rb_execution_context_t *ec = GET_EC();
+ 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;
+}
+
+rb_global_vm_lock_t *
+rb_ractor_gvl(rb_ractor_t *r)
+{
+ return &r->threads.gvl;
+}
+
+int
+rb_ractor_living_thread_num(const rb_ractor_t *r)
+{
+ return r->threads.cnt;
+}
+
+VALUE
+rb_ractor_thread_list(rb_ractor_t *r)
+{
+ rb_thread_t *th = 0;
+ VALUE *ts;
+ int ts_cnt;
+
+ RACTOR_LOCK(r);
+ {
+ ts = ALLOCA_N(VALUE, r->threads.cnt);
+ ts_cnt = 0;
+
+ list_for_each(&r->threads.set, th, lt_node) {
+ switch (th->status) {
+ case THREAD_RUNNABLE:
+ case THREAD_STOPPED:
+ case THREAD_STOPPED_FOREVER:
+ ts[ts_cnt++] = th->self;
+ default:
+ break;
+ }
+ }
+ }
+ RACTOR_UNLOCK(r);
+
+ VALUE ary = rb_ary_new();
+ for (int i=0; i<ts_cnt; i++) {
+ rb_ary_push(ary, ts[i]);
+ }
+
+ return ary;
+}
+
+void
+rb_ractor_living_threads_insert(rb_ractor_t *r, rb_thread_t *th)
+{
+ VM_ASSERT(th != NULL);
+
+ RACTOR_LOCK(r);
+ {
+ RUBY_DEBUG_LOG("r(%d)->threads.cnt:%d++", r->pub.id, r->threads.cnt);
+ list_add_tail(&r->threads.set, &th->lt_node);
+ r->threads.cnt++;
+ }
+ RACTOR_UNLOCK(r);
+
+ // first thread for a ractor
+ if (r->threads.cnt == 1) {
+ VM_ASSERT(ractor_status_p(r, ractor_created));
+ vm_insert_ractor(th->vm, r);
+ }
+}
+
+static void
+vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *r, const char *file, int line)
+{
+ ractor_status_set(r, ractor_blocking);
+
+ RUBY_DEBUG_LOG2(file, line, "vm->ractor.blocking_cnt:%d++", vm->ractor.blocking_cnt);
+ vm->ractor.blocking_cnt++;
+ VM_ASSERT(vm->ractor.blocking_cnt <= vm->ractor.cnt);
+}
+
+void
+rb_vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line)
+{
+ ASSERT_vm_locking();
+ VM_ASSERT(GET_RACTOR() == cr);
+ vm_ractor_blocking_cnt_inc(vm, cr, file, line);
+}
+
+void
+rb_vm_ractor_blocking_cnt_dec(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line)
+{
+ ASSERT_vm_locking();
+ VM_ASSERT(GET_RACTOR() == cr);
+
+ RUBY_DEBUG_LOG2(file, line, "vm->ractor.blocking_cnt:%d--", vm->ractor.blocking_cnt);
+ VM_ASSERT(vm->ractor.blocking_cnt > 0);
+ vm->ractor.blocking_cnt--;
+
+ ractor_status_set(cr, ractor_running);
+}
+
+static void
+ractor_check_blocking(rb_ractor_t *cr, unsigned int remained_thread_cnt, const char *file, int line)
+{
+ VM_ASSERT(cr == GET_RACTOR());
+
+ RUBY_DEBUG_LOG2(file, line,
+ "cr->threads.cnt:%u cr->threads.blocking_cnt:%u vm->ractor.cnt:%u vm->ractor.blocking_cnt:%u",
+ cr->threads.cnt, cr->threads.blocking_cnt,
+ GET_VM()->ractor.cnt, GET_VM()->ractor.blocking_cnt);
+
+ VM_ASSERT(cr->threads.cnt >= cr->threads.blocking_cnt + 1);
+
+ if (remained_thread_cnt > 0 &&
+ // will be block
+ cr->threads.cnt == cr->threads.blocking_cnt + 1) {
+ // change ractor status: running -> blocking
+ rb_vm_t *vm = GET_VM();
+ ASSERT_vm_unlocking();
+
+ RB_VM_LOCK();
+ {
+ rb_vm_ractor_blocking_cnt_inc(vm, cr, file, line);
+ }
+ RB_VM_UNLOCK();
+ }
+}
+
+void
+rb_ractor_living_threads_remove(rb_ractor_t *cr, rb_thread_t *th)
+{
+ VM_ASSERT(cr == GET_RACTOR());
+ RUBY_DEBUG_LOG("r->threads.cnt:%d--", cr->threads.cnt);
+ ractor_check_blocking(cr, cr->threads.cnt - 1, __FILE__, __LINE__);
+
+ if (cr->threads.cnt == 1) {
+ vm_remove_ractor(th->vm, cr);
+ }
+ else {
+ RACTOR_LOCK(cr);
+ {
+ list_del(&th->lt_node);
+ cr->threads.cnt--;
+ }
+ RACTOR_UNLOCK(cr);
+ }
+}
+
+void
+rb_ractor_blocking_threads_inc(rb_ractor_t *cr, const char *file, int line)
+{
+ RUBY_DEBUG_LOG2(file, line, "cr->threads.blocking_cnt:%d++", cr->threads.blocking_cnt);
+
+ VM_ASSERT(cr->threads.cnt > 0);
+ VM_ASSERT(cr == GET_RACTOR());
+
+ ractor_check_blocking(cr, cr->threads.cnt, __FILE__, __LINE__);
+ cr->threads.blocking_cnt++;
+}
+
+void
+rb_ractor_blocking_threads_dec(rb_ractor_t *cr, const char *file, int line)
+{
+ RUBY_DEBUG_LOG2(file, line,
+ "r->threads.blocking_cnt:%d--, r->threads.cnt:%u",
+ cr->threads.blocking_cnt, cr->threads.cnt);
+
+ VM_ASSERT(cr == GET_RACTOR());
+
+ if (cr->threads.cnt == cr->threads.blocking_cnt) {
+ rb_vm_t *vm = GET_VM();
+
+ RB_VM_LOCK_ENTER();
+ {
+ rb_vm_ractor_blocking_cnt_dec(vm, cr, __FILE__, __LINE__);
+ }
+ RB_VM_LOCK_LEAVE();
+ }
+
+ cr->threads.blocking_cnt--;
+}
+
+void
+rb_ractor_vm_barrier_interrupt_running_thread(rb_ractor_t *r)
+{
+ VM_ASSERT(r != GET_RACTOR());
+ ASSERT_ractor_unlocking(r);
+ ASSERT_vm_locking();
+
+ RACTOR_LOCK(r);
+ {
+ if (ractor_status_p(r, ractor_running)) {
+ rb_execution_context_t *ec = r->threads.running_ec;
+ if (ec) {
+ RUBY_VM_SET_VM_BARRIER_INTERRUPT(ec);
+ }
+ }
+ }
+ RACTOR_UNLOCK(r);
+}
+
+void
+rb_ractor_terminate_interrupt_main_thread(rb_ractor_t *r)
+{
+ VM_ASSERT(r != GET_RACTOR());
+ ASSERT_ractor_unlocking(r);
+ ASSERT_vm_locking();
+
+ rb_thread_t *main_th = r->threads.main;
+ if (main_th) {
+ if (main_th->status != THREAD_KILLED) {
+ RUBY_VM_SET_TERMINATE_INTERRUPT(main_th->ec);
+ rb_threadptr_interrupt(main_th);
+ }
+ else {
+ RUBY_DEBUG_LOG("killed (%p)", main_th);
+ }
+ }
+}
+
+void rb_thread_terminate_all(rb_thread_t *th); // thread.c
+
+static void
+ractor_terminal_interrupt_all(rb_vm_t *vm)
+{
+ if (vm->ractor.cnt > 1) {
+ // send terminate notification to all ractors
+ rb_ractor_t *r = 0;
+ list_for_each(&vm->ractor.set, r, vmlr_node) {
+ if (r != vm->ractor.main_ractor) {
+ rb_ractor_terminate_interrupt_main_thread(r);
+ }
+ }
+ }
+}
+
+void
+rb_ractor_terminate_all(void)
+{
+ rb_vm_t *vm = GET_VM();
+ rb_ractor_t *cr = vm->ractor.main_ractor;
+
+ VM_ASSERT(cr == GET_RACTOR()); // only main-ractor's main-thread should kick it.
+
+ if (vm->ractor.cnt > 1) {
+ RB_VM_LOCK();
+ ractor_terminal_interrupt_all(vm); // kill all ractors
+ RB_VM_UNLOCK();
+ }
+ rb_thread_terminate_all(GET_THREAD()); // kill other threads in main-ractor and wait
+
+ RB_VM_LOCK();
+ {
+ while (vm->ractor.cnt > 1) {
+ RUBY_DEBUG_LOG("terminate_waiting:%d", vm->ractor.sync.terminate_waiting);
+ vm->ractor.sync.terminate_waiting = true;
+
+ // wait for 1sec
+ rb_vm_ractor_blocking_cnt_inc(vm, cr, __FILE__, __LINE__);
+ rb_vm_cond_timedwait(vm, &vm->ractor.sync.terminate_cond, 1000 /* ms */);
+ rb_vm_ractor_blocking_cnt_dec(vm, cr, __FILE__, __LINE__);
+
+ ractor_terminal_interrupt_all(vm);
+ }
+ }
+ RB_VM_UNLOCK();
+}
+
+rb_execution_context_t *
+rb_vm_main_ractor_ec(rb_vm_t *vm)
+{
+ return vm->ractor.main_ractor->threads.running_ec;
+}
+
+static VALUE
+ractor_moved_missing(int argc, VALUE *argv, VALUE self)
+{
+ rb_raise(rb_eRactorMovedError, "can not send any methods to a moved object");
+}
+
+/*
+ * Document-class: Ractor::ClosedError
+ *
+ * Raised when an attempt is made to send a message to a closed port,
+ * or to retrieve a message from a closed and empty port.
+ * Ports may be closed explicitly with Ractor#close_outgoing/close_incoming
+ * and are closed implicitly when a Ractor terminates.
+ *
+ * r = Ractor.new { sleep(500) }
+ * r.close_outgoing
+ * r.take # Ractor::ClosedError
+ *
+ * ClosedError is a descendant of StopIteration, so the closing of the ractor will break
+ * the loops without propagating the error:
+ *
+ * r = Ractor.new do
+ * loop do
+ * msg = receive # raises ClosedError and loop traps it
+ * puts "Received: #{msg}"
+ * end
+ * puts "loop exited"
+ * end
+ *
+ * 3.times{|i| r << i}
+ * r.close_incoming
+ * r.take
+ * puts "Continue successfully"
+ *
+ * This will print:
+ *
+ * Received: 0
+ * Received: 1
+ * Received: 2
+ * loop exited
+ * Continue successfully
+ */
+
+/*
+ * Document-class: Ractor::RemoteError
+ *
+ * Raised on attempt to Ractor#take if there was an uncaught exception in the Ractor.
+ * Its +cause+ will contain the original exception, and +ractor+ is the original ractor
+ * it was raised in.
+ *
+ * r = Ractor.new { raise "Something weird happened" }
+ *
+ * begin
+ * r.take
+ * rescue => e
+ * p e # => #<Ractor::RemoteError: thrown by remote Ractor.>
+ * p e.ractor == r # => true
+ * p e.cause # => #<RuntimeError: Something weird happened>
+ * end
+ *
+ */
+
+/*
+ * Document-class: Ractor::MovedError
+ *
+ * Raised on an attempt to access an object which was moved in Ractor#send or Ractor.yield.
+ *
+ * r = Ractor.new { sleep }
+ *
+ * ary = [1, 2, 3]
+ * r.send(ary, move: true)
+ * ary.inspect
+ * # Ractor::MovedError (can not send any methods to a moved object)
+ *
+ */
+
+/*
+ * Document-class: Ractor::MovedObject
+ *
+ * A special object which replaces any value that was moved to another ractor in Ractor#send
+ * or Ractor.yield. Any attempt to access the object results in Ractor::MovedError.
+ *
+ * r = Ractor.new { receive }
+ *
+ * ary = [1, 2, 3]
+ * r.send(ary, move: true)
+ * p Ractor::MovedObject === ary
+ * # => true
+ * ary.inspect
+ * # Ractor::MovedError (can not send any methods to a moved object)
+ */
+
+// Main docs are in ractor.rb, but without this clause there are weird artifacts
+// in their rendering.
+/*
+ * Document-class: Ractor
+ *
+ */
+
+void
+Init_Ractor(void)
+{
+ rb_cRactor = rb_define_class("Ractor", rb_cObject);
+ rb_undef_alloc_func(rb_cRactor);
+
+ rb_eRactorError = rb_define_class_under(rb_cRactor, "Error", rb_eRuntimeError);
+ rb_eRactorIsolationError = rb_define_class_under(rb_cRactor, "IsolationError", rb_eRactorError);
+ rb_eRactorRemoteError = rb_define_class_under(rb_cRactor, "RemoteError", rb_eRactorError);
+ rb_eRactorMovedError = rb_define_class_under(rb_cRactor, "MovedError", rb_eRactorError);
+ rb_eRactorClosedError = rb_define_class_under(rb_cRactor, "ClosedError", rb_eStopIteration);
+ rb_eRactorUnsafeError = rb_define_class_under(rb_cRactor, "UnsafeError", rb_eRactorError);
+
+ rb_cRactorMovedObject = rb_define_class_under(rb_cRactor, "MovedObject", rb_cBasicObject);
+ rb_undef_alloc_func(rb_cRactorMovedObject);
+ rb_define_method(rb_cRactorMovedObject, "method_missing", ractor_moved_missing, -1);
+
+ // override methods defined in BasicObject
+ rb_define_method(rb_cRactorMovedObject, "__send__", ractor_moved_missing, -1);
+ rb_define_method(rb_cRactorMovedObject, "!", ractor_moved_missing, -1);
+ rb_define_method(rb_cRactorMovedObject, "==", ractor_moved_missing, -1);
+ rb_define_method(rb_cRactorMovedObject, "!=", ractor_moved_missing, -1);
+ rb_define_method(rb_cRactorMovedObject, "__id__", ractor_moved_missing, -1);
+ rb_define_method(rb_cRactorMovedObject, "equal?", ractor_moved_missing, -1);
+ rb_define_method(rb_cRactorMovedObject, "instance_eval", ractor_moved_missing, -1);
+ rb_define_method(rb_cRactorMovedObject, "instance_exec", ractor_moved_missing, -1);
+}
+
+void
+rb_ractor_dump(void)
+{
+ rb_vm_t *vm = GET_VM();
+ rb_ractor_t *r = 0;
+
+ list_for_each(&vm->ractor.set, r, vmlr_node) {
+ if (r != vm->ractor.main_ractor) {
+ fprintf(stderr, "r:%u (%s)\n", r->pub.id, ractor_status_str(r->status_));
+ }
+ }
+}
+
+VALUE
+rb_ractor_stdin(void)
+{
+ if (rb_ractor_main_p()) {
+ return rb_stdin;
+ }
+ else {
+ rb_ractor_t *cr = GET_RACTOR();
+ return cr->r_stdin;
+ }
+}
+
+VALUE
+rb_ractor_stdout(void)
+{
+ if (rb_ractor_main_p()) {
+ return rb_stdout;
+ }
+ else {
+ rb_ractor_t *cr = GET_RACTOR();
+ return cr->r_stdout;
+ }
+}
+
+VALUE
+rb_ractor_stderr(void)
+{
+ if (rb_ractor_main_p()) {
+ return rb_stderr;
+ }
+ else {
+ rb_ractor_t *cr = GET_RACTOR();
+ return cr->r_stderr;
+ }
+}
+
+void
+rb_ractor_stdin_set(VALUE in)
+{
+ if (rb_ractor_main_p()) {
+ rb_stdin = in;
+ }
+ else {
+ rb_ractor_t *cr = GET_RACTOR();
+ RB_OBJ_WRITE(cr->pub.self, &cr->r_stdin, in);
+ }
+}
+
+void
+rb_ractor_stdout_set(VALUE out)
+{
+ if (rb_ractor_main_p()) {
+ rb_stdout = out;
+ }
+ else {
+ rb_ractor_t *cr = GET_RACTOR();
+ RB_OBJ_WRITE(cr->pub.self, &cr->r_stdout, out);
+ }
+}
+
+void
+rb_ractor_stderr_set(VALUE err)
+{
+ if (rb_ractor_main_p()) {
+ rb_stderr = err;
+ }
+ else {
+ rb_ractor_t *cr = GET_RACTOR();
+ RB_OBJ_WRITE(cr->pub.self, &cr->r_stderr, err);
+ }
+}
+
+rb_hook_list_t *
+rb_ractor_hooks(rb_ractor_t *cr)
+{
+ return &cr->pub.hooks;
+}
+
+/// traverse function
+
+// 2: stop search
+// 1: skip child
+// 0: continue
+
+enum obj_traverse_iterator_result {
+ traverse_cont,
+ traverse_skip,
+ traverse_stop,
+};
+
+typedef enum obj_traverse_iterator_result (*rb_obj_traverse_enter_func)(VALUE obj);
+typedef enum obj_traverse_iterator_result (*rb_obj_traverse_leave_func)(VALUE obj);
+typedef enum obj_traverse_iterator_result (*rb_obj_traverse_final_func)(VALUE obj);
+
+static enum obj_traverse_iterator_result null_leave(VALUE obj);
+
+struct obj_traverse_data {
+ rb_obj_traverse_enter_func enter_func;
+ rb_obj_traverse_leave_func leave_func;
+
+ st_table *rec;
+ VALUE rec_hash;
+};
+
+
+struct obj_traverse_callback_data {
+ bool stop;
+ struct obj_traverse_data *data;
+};
+
+static int obj_traverse_i(VALUE obj, struct obj_traverse_data *data);
+
+static int
+obj_hash_traverse_i(VALUE key, VALUE val, VALUE ptr)
+{
+ struct obj_traverse_callback_data *d = (struct obj_traverse_callback_data *)ptr;
+
+ if (obj_traverse_i(key, d->data)) {
+ d->stop = true;
+ return ST_STOP;
+ }
+
+ if (obj_traverse_i(val, d->data)) {
+ d->stop = true;
+ return ST_STOP;
+ }
+
+ return ST_CONTINUE;
+}
+
+static void
+obj_traverse_reachable_i(VALUE obj, void *ptr)
+{
+ struct obj_traverse_callback_data *d = (struct obj_traverse_callback_data *)ptr;
+
+ if (obj_traverse_i(obj, d->data)) {
+ d->stop = true;
+ }
+}
+
+static struct st_table *
+obj_traverse_rec(struct obj_traverse_data *data)
+{
+ if (UNLIKELY(!data->rec)) {
+ data->rec_hash = rb_ident_hash_new();
+ data->rec = rb_hash_st_table(data->rec_hash);
+ }
+ return data->rec;
+}
+
+static int
+obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
+{
+ if (RB_SPECIAL_CONST_P(obj)) return 0;
+
+ switch (data->enter_func(obj)) {
+ case traverse_cont: break;
+ case traverse_skip: return 0; // skip children
+ case traverse_stop: return 1; // stop search
+ }
+
+ if (UNLIKELY(st_insert(obj_traverse_rec(data), obj, 1))) {
+ // already traversed
+ return 0;
+ }
+
+ if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
+ struct gen_ivtbl *ivtbl;
+ rb_ivar_generic_ivtbl_lookup(obj, &ivtbl);
+ for (uint32_t i = 0; i < ivtbl->numiv; i++) {
+ VALUE val = ivtbl->ivptr[i];
+ if (val != Qundef && obj_traverse_i(val, data)) return 1;
+ }
+ }
+
+ switch (BUILTIN_TYPE(obj)) {
+ // no child node
+ case T_STRING:
+ case T_FLOAT:
+ case T_BIGNUM:
+ case T_REGEXP:
+ case T_FILE:
+ case T_SYMBOL:
+ case T_MATCH:
+ break;
+
+ case T_OBJECT:
+ {
+ uint32_t len = ROBJECT_NUMIV(obj);
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+
+ for (uint32_t i=0; i<len; i++) {
+ VALUE val = ptr[i];
+ if (val != Qundef && obj_traverse_i(val, data)) return 1;
+ }
+ }
+ break;
+
+ case T_ARRAY:
+ {
+ for (int i = 0; i < RARRAY_LENINT(obj); i++) {
+ VALUE e = rb_ary_entry(obj, i);
+ if (obj_traverse_i(e, data)) return 1;
+ }
+ }
+ break;
+
+ case T_HASH:
+ {
+ if (obj_traverse_i(RHASH_IFNONE(obj), data)) return 1;
+
+ struct obj_traverse_callback_data d = {
+ .stop = false,
+ .data = data,
+ };
+ rb_hash_foreach(obj, obj_hash_traverse_i, (VALUE)&d);
+ if (d.stop) return 1;
+ }
+ break;
+
+ case T_STRUCT:
+ {
+ long len = RSTRUCT_LEN(obj);
+ const VALUE *ptr = RSTRUCT_CONST_PTR(obj);
+
+ for (long i=0; i<len; i++) {
+ if (obj_traverse_i(ptr[i], 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;
+ break;
+ case T_COMPLEX:
+ if (obj_traverse_i(RCOMPLEX(obj)->real, data)) return 1;
+ if (obj_traverse_i(RCOMPLEX(obj)->imag, data)) return 1;
+ break;
+
+ case T_DATA:
+ case T_IMEMO:
+ {
+ struct obj_traverse_callback_data d = {
+ .stop = false,
+ .data = data,
+ };
+ RB_VM_LOCK_ENTER_NO_BARRIER();
+ {
+ rb_objspace_reachable_objects_from(obj, obj_traverse_reachable_i, &d);
+ }
+ RB_VM_LOCK_LEAVE_NO_BARRIER();
+ if (d.stop) return 1;
+ }
+ break;
+
+ // unreachable
+ case T_CLASS:
+ case T_MODULE:
+ case T_ICLASS:
+ default:
+ rp(obj);
+ rb_bug("unreachable");
+ }
+
+ if (data->leave_func(obj) == traverse_stop) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+struct rb_obj_traverse_final_data {
+ rb_obj_traverse_final_func final_func;
+ int stopped;
+};
+
+static int
+obj_traverse_final_i(st_data_t key, st_data_t val, st_data_t arg)
+{
+ struct rb_obj_traverse_final_data *data = (void *)arg;
+ if (data->final_func(key)) {
+ data->stopped = 1;
+ return ST_STOP;
+ }
+ return ST_CONTINUE;
+}
+
+// 0: traverse all
+// 1: stopped
+static int
+rb_obj_traverse(VALUE obj,
+ rb_obj_traverse_enter_func enter_func,
+ rb_obj_traverse_leave_func leave_func,
+ rb_obj_traverse_final_func final_func)
+{
+ struct obj_traverse_data data = {
+ .enter_func = enter_func,
+ .leave_func = leave_func,
+ .rec = NULL,
+ };
+
+ if (obj_traverse_i(obj, &data)) return 1;
+ if (final_func && data.rec) {
+ struct rb_obj_traverse_final_data f = {final_func, 0};
+ st_foreach(data.rec, obj_traverse_final_i, (st_data_t)&f);
+ return f.stopped;
+ }
+ return 0;
+}
+
+static int
+frozen_shareable_p(VALUE obj, bool *made_shareable)
+{
+ if (!RB_TYPE_P(obj, T_DATA)) {
+ return true;
+ }
+ else if (RTYPEDDATA_P(obj)) {
+ const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
+ if (type->flags & RUBY_TYPED_FROZEN_SHAREABLE) {
+ return true;
+ }
+ else if (made_shareable && rb_obj_is_proc(obj)) {
+ // special path to make shareable Proc.
+ rb_proc_ractor_make_shareable(obj);
+ *made_shareable = true;
+ VM_ASSERT(RB_OBJ_SHAREABLE_P(obj));
+ return false;
+ }
+ }
+
+ return false;
+}
+
+static enum obj_traverse_iterator_result
+make_shareable_check_shareable(VALUE obj)
+{
+ VM_ASSERT(!SPECIAL_CONST_P(obj));
+ bool made_shareable = false;
+
+ if (rb_ractor_shareable_p(obj)) {
+ return traverse_skip;
+ }
+ else if (!frozen_shareable_p(obj, &made_shareable)) {
+ if (made_shareable) {
+ return traverse_skip;
+ }
+ else {
+ rb_raise(rb_eRactorError, "can not make shareable object for %"PRIsVALUE, obj);
+ }
+ }
+
+ if (!RB_OBJ_FROZEN_RAW(obj)) {
+ rb_funcall(obj, idFreeze, 0);
+
+ if (UNLIKELY(!RB_OBJ_FROZEN_RAW(obj))) {
+ rb_raise(rb_eRactorError, "#freeze does not freeze object correctly");
+ }
+
+ if (RB_OBJ_SHAREABLE_P(obj)) {
+ return traverse_skip;
+ }
+ }
+
+ return traverse_cont;
+}
+
+static enum obj_traverse_iterator_result
+mark_shareable(VALUE obj)
+{
+ FL_SET_RAW(obj, RUBY_FL_SHAREABLE);
+ return traverse_cont;
+}
+
+VALUE
+rb_ractor_make_shareable(VALUE obj)
+{
+ rb_obj_traverse(obj,
+ make_shareable_check_shareable,
+ null_leave, mark_shareable);
+ return obj;
+}
+
+VALUE
+rb_ractor_make_shareable_copy(VALUE obj)
+{
+ VALUE copy = ractor_copy(obj);
+ rb_obj_traverse(copy,
+ make_shareable_check_shareable,
+ null_leave, mark_shareable);
+ return copy;
+}
+
+VALUE
+rb_ractor_ensure_shareable(VALUE obj, VALUE name)
+{
+ if (!rb_ractor_shareable_p(obj)) {
+ VALUE message = rb_sprintf("cannot assign unshareable object to %"PRIsVALUE,
+ name);
+ rb_exc_raise(rb_exc_new_str(rb_eRactorIsolationError, message));
+ }
+ return obj;
+}
+
+static enum obj_traverse_iterator_result
+shareable_p_enter(VALUE obj)
+{
+ if (RB_OBJ_SHAREABLE_P(obj)) {
+ return traverse_skip;
+ }
+ else if (RB_TYPE_P(obj, T_CLASS) ||
+ RB_TYPE_P(obj, T_MODULE) ||
+ RB_TYPE_P(obj, T_ICLASS)) {
+ // TODO: remove it
+ mark_shareable(obj);
+ return traverse_skip;
+ }
+ else if (RB_OBJ_FROZEN_RAW(obj) &&
+ frozen_shareable_p(obj, NULL)) {
+ return traverse_cont;
+ }
+
+ return traverse_stop; // fail
+}
+
+MJIT_FUNC_EXPORTED bool
+rb_ractor_shareable_p_continue(VALUE obj)
+{
+ if (rb_obj_traverse(obj,
+ shareable_p_enter, null_leave,
+ mark_shareable)) {
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+#if RACTOR_CHECK_MODE > 0
+static enum obj_traverse_iterator_result
+reset_belonging_enter(VALUE obj)
+{
+ if (rb_ractor_shareable_p(obj)) {
+ return traverse_skip;
+ }
+ else {
+ rb_ractor_setup_belonging(obj);
+ return traverse_cont;
+ }
+}
+#endif
+
+static enum obj_traverse_iterator_result
+null_leave(VALUE obj)
+{
+ return traverse_cont;
+}
+
+static VALUE
+ractor_reset_belonging(VALUE obj)
+{
+#if RACTOR_CHECK_MODE > 0
+ rb_obj_traverse(obj, reset_belonging_enter, null_leave, NULL);
+#endif
+ return obj;
+}
+
+
+/// traverse and replace function
+
+// 2: stop search
+// 1: skip child
+// 0: continue
+
+struct obj_traverse_replace_data;
+static int obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data);
+typedef enum obj_traverse_iterator_result (*rb_obj_traverse_replace_enter_func)(VALUE obj, struct obj_traverse_replace_data *data);
+typedef enum obj_traverse_iterator_result (*rb_obj_traverse_replace_leave_func)(VALUE obj, struct obj_traverse_replace_data *data);
+
+struct obj_traverse_replace_data {
+ rb_obj_traverse_replace_enter_func enter_func;
+ rb_obj_traverse_replace_leave_func leave_func;
+
+ st_table *rec;
+ VALUE rec_hash;
+
+ VALUE replacement;
+ bool move;
+};
+
+struct obj_traverse_replace_callback_data {
+ bool stop;
+ VALUE src;
+ struct obj_traverse_replace_data *data;
+};
+
+static int
+obj_hash_traverse_replace_foreach_i(st_data_t key, st_data_t value, st_data_t argp, int error)
+{
+ return ST_REPLACE;
+}
+
+static int
+obj_hash_traverse_replace_i(st_data_t *key, st_data_t *val, st_data_t ptr, int exists)
+{
+ struct obj_traverse_replace_callback_data *d = (struct obj_traverse_replace_callback_data *)ptr;
+ struct obj_traverse_replace_data *data = d->data;
+
+ if (obj_traverse_replace_i(*key, data)) {
+ d->stop = true;
+ return ST_STOP;
+ }
+ else if (*key != data->replacement) {
+ VALUE v = *key = data->replacement;
+ RB_OBJ_WRITTEN(d->src, Qundef, v);
+ }
+
+ if (obj_traverse_replace_i(*val, data)) {
+ d->stop = true;
+ return ST_STOP;
+ }
+ else if (*val != data->replacement) {
+ VALUE v = *val = data->replacement;
+ RB_OBJ_WRITTEN(d->src, Qundef, v);
+ }
+
+ return ST_CONTINUE;
+}
+
+static struct st_table *
+obj_traverse_replace_rec(struct obj_traverse_replace_data *data)
+{
+ if (UNLIKELY(!data->rec)) {
+ data->rec_hash = rb_ident_hash_new();
+ data->rec = rb_hash_st_table(data->rec_hash);
+ }
+ return data->rec;
+}
+
+#if USE_TRANSIENT_HEAP
+void rb_ary_transient_heap_evacuate(VALUE ary, int promote);
+void rb_obj_transient_heap_evacuate(VALUE obj, int promote);
+void rb_hash_transient_heap_evacuate(VALUE hash, int promote);
+void rb_struct_transient_heap_evacuate(VALUE st, int promote);
+#endif
+
+static void
+obj_refer_only_shareables_p_i(VALUE obj, void *ptr)
+{
+ int *pcnt = (int *)ptr;
+
+ if (!rb_ractor_shareable_p(obj)) {
+ pcnt++;
+ }
+}
+
+static int
+obj_refer_only_shareables_p(VALUE obj)
+{
+ int cnt = 0;
+ RB_VM_LOCK_ENTER_NO_BARRIER();
+ {
+ rb_objspace_reachable_objects_from(obj, obj_refer_only_shareables_p_i, &cnt);
+ }
+ RB_VM_LOCK_LEAVE_NO_BARRIER();
+ return cnt == 0;
+}
+
+static int
+obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
+{
+ VALUE replacement;
+
+ if (RB_SPECIAL_CONST_P(obj)) {
+ data->replacement = obj;
+ return 0;
+ }
+
+ switch (data->enter_func(obj, data)) {
+ case traverse_cont: break;
+ case traverse_skip: return 0; // skip children
+ case traverse_stop: return 1; // stop search
+ }
+
+ replacement = data->replacement;
+
+ if (UNLIKELY(st_lookup(obj_traverse_replace_rec(data), (st_data_t)obj, (st_data_t *)&replacement))) {
+ data->replacement = replacement;
+ return 0;
+ }
+ else {
+ st_insert(obj_traverse_replace_rec(data), (st_data_t)obj, (st_data_t)replacement);
+ }
+
+ if (!data->move) {
+ obj = replacement;
+ }
+
+#define CHECK_AND_REPLACE(v) do { \
+ VALUE _val = (v); \
+ if (obj_traverse_replace_i(_val, data)) { return 1; } \
+ else if (data->replacement != _val) { RB_OBJ_WRITE(obj, &v, data->replacement); } \
+} while (0)
+
+ if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
+ struct gen_ivtbl *ivtbl;
+ rb_ivar_generic_ivtbl_lookup(obj, &ivtbl);
+ for (uint32_t i = 0; i < ivtbl->numiv; i++) {
+ if (ivtbl->ivptr[i] != Qundef) {
+ CHECK_AND_REPLACE(ivtbl->ivptr[i]);
+ }
+ }
+ }
+
+ switch (BUILTIN_TYPE(obj)) {
+ // no child node
+ case T_FLOAT:
+ case T_BIGNUM:
+ case T_REGEXP:
+ case T_FILE:
+ case T_SYMBOL:
+ case T_MATCH:
+ break;
+ case T_STRING:
+ rb_str_make_independent(obj);
+ break;
+
+ case T_OBJECT:
+ {
+#if USE_TRANSIENT_HEAP
+ if (data->move) rb_obj_transient_heap_evacuate(obj, TRUE);
+#endif
+
+ uint32_t len = ROBJECT_NUMIV(obj);
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+
+ for (uint32_t i=0; i<len; i++) {
+ if (ptr[i] != Qundef) {
+ CHECK_AND_REPLACE(ptr[i]);
+ }
+ }
+ }
+ break;
+
+ case T_ARRAY:
+ {
+ rb_ary_cancel_sharing(obj);
+#if USE_TRANSIENT_HEAP
+ if (data->move) rb_ary_transient_heap_evacuate(obj, TRUE);
+#endif
+
+ for (int i = 0; i < RARRAY_LENINT(obj); i++) {
+ VALUE e = rb_ary_entry(obj, i);
+
+ if (obj_traverse_replace_i(e, data)) {
+ return 1;
+ }
+ else if (e != data->replacement) {
+ RARRAY_ASET(obj, i, data->replacement);
+ }
+ }
+ RB_GC_GUARD(obj);
+ }
+ break;
+
+ case T_HASH:
+ {
+#if USE_TRANSIENT_HEAP
+ if (data->move) rb_hash_transient_heap_evacuate(obj, TRUE);
+#endif
+ struct obj_traverse_replace_callback_data d = {
+ .stop = false,
+ .data = data,
+ .src = obj,
+ };
+ rb_hash_stlike_foreach_with_replace(obj,
+ obj_hash_traverse_replace_foreach_i,
+ obj_hash_traverse_replace_i,
+ (VALUE)&d);
+ if (d.stop) return 1;
+ // TODO: rehash here?
+
+ VALUE ifnone = RHASH_IFNONE(obj);
+ if (obj_traverse_replace_i(ifnone, data)) {
+ return 1;
+ }
+ else if (ifnone != data->replacement) {
+ RHASH_SET_IFNONE(obj, data->replacement);
+ }
+ }
+ break;
+
+ case T_STRUCT:
+ {
+#if USE_TRANSIENT_HEAP
+ if (data->move) rb_struct_transient_heap_evacuate(obj, TRUE);
+#endif
+ long len = RSTRUCT_LEN(obj);
+ const VALUE *ptr = RSTRUCT_CONST_PTR(obj);
+
+ for (long i=0; i<len; i++) {
+ CHECK_AND_REPLACE(ptr[i]);
+ }
+ }
+ break;
+
+ case T_RATIONAL:
+ CHECK_AND_REPLACE(RRATIONAL(obj)->num);
+ CHECK_AND_REPLACE(RRATIONAL(obj)->den);
+ break;
+ case T_COMPLEX:
+ CHECK_AND_REPLACE(RCOMPLEX(obj)->real);
+ CHECK_AND_REPLACE(RCOMPLEX(obj)->imag);
+ break;
+
+ case T_DATA:
+ if (!data->move && obj_refer_only_shareables_p(obj)) {
+ break;
+ }
+ else {
+ rb_raise(rb_eRactorError, "can not %s %"PRIsVALUE" object.",
+ data->move ? "move" : "copy", rb_class_of(obj));
+ }
+
+ case T_IMEMO:
+ // not supported yet
+ return 1;
+
+ // unreachable
+ case T_CLASS:
+ case T_MODULE:
+ case T_ICLASS:
+ default:
+ rp(obj);
+ rb_bug("unreachable");
+ }
+
+ data->replacement = replacement;
+
+ if (data->leave_func(obj, data) == traverse_stop) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+// 0: traverse all
+// 1: stopped
+static VALUE
+rb_obj_traverse_replace(VALUE obj,
+ rb_obj_traverse_replace_enter_func enter_func,
+ rb_obj_traverse_replace_leave_func leave_func,
+ bool move)
+{
+ struct obj_traverse_replace_data data = {
+ .enter_func = enter_func,
+ .leave_func = leave_func,
+ .rec = NULL,
+ .replacement = Qundef,
+ .move = move,
+ };
+
+ if (obj_traverse_replace_i(obj, &data)) {
+ return Qundef;
+ }
+ else {
+ return data.replacement;
+ }
+}
+
+struct RVALUE {
+ VALUE flags;
+ VALUE klass;
+ VALUE v1;
+ VALUE v2;
+ VALUE v3;
+};
+
+static const VALUE fl_users = FL_USER1 | FL_USER2 | FL_USER3 |
+ FL_USER4 | FL_USER5 | FL_USER6 | FL_USER7 |
+ FL_USER8 | FL_USER9 | FL_USER10 | FL_USER11 |
+ FL_USER12 | FL_USER13 | FL_USER14 | FL_USER15 |
+ FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19;
+
+static void
+ractor_moved_bang(VALUE obj)
+{
+ // invalidate src object
+ struct RVALUE *rv = (void *)obj;
+
+ rv->klass = rb_cRactorMovedObject;
+ rv->v1 = 0;
+ rv->v2 = 0;
+ rv->v3 = 0;
+ rv->flags = rv->flags & ~fl_users;
+
+ // TODO: record moved location
+}
+
+static enum obj_traverse_iterator_result
+move_enter(VALUE obj, struct obj_traverse_replace_data *data)
+{
+ if (rb_ractor_shareable_p(obj)) {
+ data->replacement = obj;
+ return traverse_skip;
+ }
+ else {
+ data->replacement = rb_obj_alloc(RBASIC_CLASS(obj));
+ return traverse_cont;
+ }
+}
+
+void rb_replace_generic_ivar(VALUE clone, VALUE obj); // variable.c
+
+static enum obj_traverse_iterator_result
+move_leave(VALUE obj, struct obj_traverse_replace_data *data)
+{
+ VALUE v = data->replacement;
+ struct RVALUE *dst = (struct RVALUE *)v;
+ struct RVALUE *src = (struct RVALUE *)obj;
+
+ dst->flags = (dst->flags & ~fl_users) | (src->flags & fl_users);
+
+ dst->v1 = src->v1;
+ dst->v2 = src->v2;
+ dst->v3 = src->v3;
+
+ if (UNLIKELY(FL_TEST_RAW(obj, FL_EXIVAR))) {
+ rb_replace_generic_ivar(v, obj);
+ }
+
+ // TODO: generic_ivar
+
+ ractor_moved_bang(obj);
+ return traverse_cont;
+}
+
+static VALUE
+ractor_move(VALUE obj)
+{
+ VALUE val = rb_obj_traverse_replace(obj, move_enter, move_leave, true);
+ if (val != Qundef) {
+ return val;
+ }
+ else {
+ rb_raise(rb_eRactorError, "can not move the object");
+ }
+}
+
+static enum obj_traverse_iterator_result
+copy_enter(VALUE obj, struct obj_traverse_replace_data *data)
+{
+ if (rb_ractor_shareable_p(obj)) {
+ data->replacement = obj;
+ return traverse_skip;
+ }
+ else {
+ data->replacement = rb_obj_clone(obj);
+ return traverse_cont;
+ }
+}
+
+static enum obj_traverse_iterator_result
+copy_leave(VALUE obj, struct obj_traverse_replace_data *data)
+{
+ return traverse_cont;
+}
+
+static VALUE
+ractor_copy(VALUE obj)
+{
+ VALUE val = rb_obj_traverse_replace(obj, copy_enter, copy_leave, false);
+ if (val != Qundef) {
+ return val;
+ }
+ else {
+ rb_raise(rb_eRactorError, "can not copy the object");
+ }
+}
+
+// Ractor local storage
+
+struct rb_ractor_local_key_struct {
+ const struct rb_ractor_local_storage_type *type;
+ void *main_cache;
+};
+
+static struct freed_ractor_local_keys_struct {
+ int cnt;
+ int capa;
+ rb_ractor_local_key_t *keys;
+} freed_ractor_local_keys;
+
+static int
+ractor_local_storage_mark_i(st_data_t key, st_data_t val, st_data_t dmy)
+{
+ struct rb_ractor_local_key_struct *k = (struct rb_ractor_local_key_struct *)key;
+ if (k->type->mark) (*k->type->mark)((void *)val);
+ return ST_CONTINUE;
+}
+
+static enum rb_id_table_iterator_result
+idkey_local_storage_mark_i(ID id, VALUE val, void *dmy)
+{
+ rb_gc_mark(val);
+ return ID_TABLE_CONTINUE;
+}
+
+static void
+ractor_local_storage_mark(rb_ractor_t *r)
+{
+ if (r->local_storage) {
+ st_foreach(r->local_storage, ractor_local_storage_mark_i, 0);
+
+ for (int i=0; i<freed_ractor_local_keys.cnt; i++) {
+ rb_ractor_local_key_t key = freed_ractor_local_keys.keys[i];
+ st_data_t val;
+ if (st_delete(r->local_storage, (st_data_t *)&key, &val) &&
+ key->type->free) {
+ (*key->type->free)((void *)val);
+ }
+ }
+ }
+
+ if (r->idkey_local_storage) {
+ rb_id_table_foreach(r->idkey_local_storage, idkey_local_storage_mark_i, NULL);
+ }
+}
+
+static int
+ractor_local_storage_free_i(st_data_t key, st_data_t val, st_data_t dmy)
+{
+ struct rb_ractor_local_key_struct *k = (struct rb_ractor_local_key_struct *)key;
+ if (k->type->free) (*k->type->free)((void *)val);
+ return ST_CONTINUE;
+}
+
+static void
+ractor_local_storage_free(rb_ractor_t *r)
+{
+ if (r->local_storage) {
+ st_foreach(r->local_storage, ractor_local_storage_free_i, 0);
+ st_free_table(r->local_storage);
+ }
+
+ if (r->idkey_local_storage) {
+ rb_id_table_free(r->idkey_local_storage);
+ }
+}
+
+static void
+rb_ractor_local_storage_value_mark(void *ptr)
+{
+ rb_gc_mark((VALUE)ptr);
+}
+
+static const struct rb_ractor_local_storage_type ractor_local_storage_type_null = {
+ NULL,
+ NULL,
+};
+
+const struct rb_ractor_local_storage_type rb_ractor_local_storage_type_free = {
+ NULL,
+ ruby_xfree,
+};
+
+static const struct rb_ractor_local_storage_type ractor_local_storage_type_value = {
+ rb_ractor_local_storage_value_mark,
+ NULL,
+};
+
+rb_ractor_local_key_t
+rb_ractor_local_storage_ptr_newkey(const struct rb_ractor_local_storage_type *type)
+{
+ rb_ractor_local_key_t key = ALLOC(struct rb_ractor_local_key_struct);
+ key->type = type ? type : &ractor_local_storage_type_null;
+ key->main_cache = (void *)Qundef;
+ return key;
+}
+
+rb_ractor_local_key_t
+rb_ractor_local_storage_value_newkey(void)
+{
+ return rb_ractor_local_storage_ptr_newkey(&ractor_local_storage_type_value);
+}
+
+void
+rb_ractor_local_storage_delkey(rb_ractor_local_key_t key)
+{
+ RB_VM_LOCK_ENTER();
+ {
+ if (freed_ractor_local_keys.cnt == freed_ractor_local_keys.capa) {
+ freed_ractor_local_keys.capa = freed_ractor_local_keys.capa ? freed_ractor_local_keys.capa * 2 : 4;
+ REALLOC_N(freed_ractor_local_keys.keys, rb_ractor_local_key_t, freed_ractor_local_keys.capa);
+ }
+ freed_ractor_local_keys.keys[freed_ractor_local_keys.cnt++] = key;
+ }
+ RB_VM_LOCK_LEAVE();
+}
+
+static bool
+ractor_local_ref(rb_ractor_local_key_t key, void **pret)
+{
+ if (rb_ractor_main_p()) {
+ if ((VALUE)key->main_cache != Qundef) {
+ *pret = key->main_cache;
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ rb_ractor_t *cr = GET_RACTOR();
+
+ if (cr->local_storage && st_lookup(cr->local_storage, (st_data_t)key, (st_data_t *)pret)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+}
+
+static void
+ractor_local_set(rb_ractor_local_key_t key, void *ptr)
+{
+ rb_ractor_t *cr = GET_RACTOR();
+
+ if (cr->local_storage == NULL) {
+ cr->local_storage = st_init_numtable();
+ }
+
+ st_insert(cr->local_storage, (st_data_t)key, (st_data_t)ptr);
+
+ if (rb_ractor_main_p()) {
+ key->main_cache = ptr;
+ }
+}
+
+VALUE
+rb_ractor_local_storage_value(rb_ractor_local_key_t key)
+{
+ VALUE val;
+ if (ractor_local_ref(key, (void **)&val)) {
+ return val;
+ }
+ else {
+ return Qnil;
+ }
+}
+
+bool
+rb_ractor_local_storage_value_lookup(rb_ractor_local_key_t key, VALUE *val)
+{
+ if (ractor_local_ref(key, (void **)val)) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+void
+rb_ractor_local_storage_value_set(rb_ractor_local_key_t key, VALUE val)
+{
+ ractor_local_set(key, (void *)val);
+}
+
+void *
+rb_ractor_local_storage_ptr(rb_ractor_local_key_t key)
+{
+ void *ret;
+ if (ractor_local_ref(key, &ret)) {
+ return ret;
+ }
+ else {
+ return NULL;
+ }
+}
+
+void
+rb_ractor_local_storage_ptr_set(rb_ractor_local_key_t key, void *ptr)
+{
+ ractor_local_set(key, ptr);
+}
+
+#define DEFAULT_KEYS_CAPA 0x10
+
+void
+rb_ractor_finish_marking(void)
+{
+ for (int i=0; i<freed_ractor_local_keys.cnt; i++) {
+ ruby_xfree(freed_ractor_local_keys.keys[i]);
+ }
+ freed_ractor_local_keys.cnt = 0;
+ if (freed_ractor_local_keys.capa > DEFAULT_KEYS_CAPA) {
+ freed_ractor_local_keys.capa = DEFAULT_KEYS_CAPA;
+ REALLOC_N(freed_ractor_local_keys.keys, rb_ractor_local_key_t, DEFAULT_KEYS_CAPA);
+ }
+}
+
+static VALUE
+ractor_local_value(rb_execution_context_t *ec, VALUE self, VALUE sym)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ ID id = rb_check_id(&sym);
+ struct rb_id_table *tbl = cr->idkey_local_storage;
+ VALUE val;
+
+ if (id && tbl && rb_id_table_lookup(tbl, id, &val)) {
+ return val;
+ }
+ else {
+ return Qnil;
+ }
+}
+
+static VALUE
+ractor_local_value_set(rb_execution_context_t *ec, VALUE self, VALUE sym, VALUE val)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ ID id = SYM2ID(rb_to_symbol(sym));
+ struct rb_id_table *tbl = cr->idkey_local_storage;
+
+ if (tbl == NULL) {
+ tbl = cr->idkey_local_storage = rb_id_table_create(2);
+ }
+ rb_id_table_insert(tbl, id, val);
+ return val;
+}
+
+#include "ractor.rbinc"
diff --git a/ractor.rb b/ractor.rb
new file mode 100644
index 0000000000..e6d5847237
--- /dev/null
+++ b/ractor.rb
@@ -0,0 +1,838 @@
+# Ractor is a Actor-model abstraction for Ruby that provides thread-safe parallel execution.
+#
+# Ractor.new can make new Ractor and it will run in parallel.
+#
+# # The simplest ractor
+# r = Ractor.new {puts "I am in Ractor!"}
+# r.take # wait it to finish
+# # here "I am in Ractor!" would be printed
+#
+# Ractors do not share usual objects, so the some kind of thread-safety concerns such as data-race,
+# race-conditions are not available on multi-ractor programming.
+#
+# To achieve this, ractors severely limit object sharing between different ractors.
+# For example, unlike threads, ractors can't access each other's objects, nor any objects through
+# variables of the outer scope.
+#
+# a = 1
+# r = Ractor.new {puts "I am in Ractor! a=#{a}"}
+# # fails immediately with
+# # ArgumentError (can not isolate a Proc because it accesses outer variables (a).)
+#
+# On CRuby (the default implementation), Global Virtual Machine Lock (GVL) is held per ractor, so
+# ractors are performed in parallel without locking each other.
+#
+# Instead of accessing the shared state, the objects should be passed to and from ractors via
+# sending and receiving objects as messages.
+#
+# a = 1
+# r = Ractor.new do
+# a_in_ractor = receive # receive blocks till somebody will pass message
+# puts "I am in Ractor! a=#{a_in_ractor}"
+# end
+# r.send(a) # pass it
+# r.take
+# # here "I am in Ractor! a=1" would be printed
+#
+# There are two pairs of methods for sending/receiving messages:
+#
+# * Ractor#send and Ractor.receive for when the _sender_ knows the receiver (push);
+# * Ractor.yield and Ractor#take for when the _receiver_ knows the sender (pull);
+#
+# In addition to that, an argument to Ractor.new would be passed to block and available there
+# as if received by Ractor.receive, and the last block value would be sent outside of the
+# ractor as if sent by Ractor.yield.
+#
+# A little demonstration on a classic ping-pong:
+#
+# server = Ractor.new do
+# puts "Server starts: #{self.inspect}"
+# puts "Server sends: ping"
+# Ractor.yield 'ping' # The server doesn't know the receiver and sends to whoever interested
+# received = Ractor.receive # The server doesn't know the sender and receives from whoever sent
+# puts "Server received: #{received}"
+# end
+#
+# client = Ractor.new(server) do |srv| # The server is sent inside client, and available as srv
+# puts "Client starts: #{self.inspect}"
+# received = srv.take # The Client takes a message specifically from the server
+# puts "Client received from " \
+# "#{srv.inspect}: #{received}"
+# puts "Client sends to " \
+# "#{srv.inspect}: pong"
+# srv.send 'pong' # The client sends a message specifically to the server
+# end
+#
+# [client, server].each(&:take) # Wait till they both finish
+#
+# This will output:
+#
+# Server starts: #<Ractor:#2 test.rb:1 running>
+# Server sends: ping
+# Client starts: #<Ractor:#3 test.rb:8 running>
+# Client received from #<Ractor:#2 rac.rb:1 blocking>: ping
+# Client sends to #<Ractor:#2 rac.rb:1 blocking>: pong
+# Server received: pong
+#
+# It is said that Ractor receives messages via the <em>incoming port</em>, and sends them
+# to the <em>outgoing port</em>. Either one can be disabled with Ractor#close_incoming and
+# Ractor#close_outgoing respectively. If a ractor terminated, its ports will be closed
+# automatically.
+#
+# == Shareable and unshareable objects
+#
+# When the object is sent to and from the ractor, it is important to understand whether the
+# object is shareable or unshareable. Most of objects are unshareable objects.
+#
+# Shareable objects are basically those which can be used by several threads without compromising
+# thread-safety; e.g. immutable ones. Ractor.shareable? allows to check this, and Ractor.make_shareable
+# tries to make object shareable if it is not.
+#
+# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are
+# Ractor.shareable?('foo') #=> false, unless the string is frozen due to # freeze_string_literals: true
+# Ractor.shareable?('foo'.freeze) #=> true
+#
+# ary = ['hello', 'world']
+# ary.frozen? #=> false
+# ary[0].frozen? #=> false
+# Ractor.make_shareable(ary)
+# ary.frozen? #=> true
+# ary[0].frozen? #=> true
+# ary[1].frozen? #=> true
+#
+# When a shareable object is sent (via #send or Ractor.yield), no additional processing happens,
+# and it just becomes usable by both ractors. When an unshareable object is sent, it can be
+# either _copied_ or _moved_. The first is the default, and it makes the object's full copy by
+# deep cloning of non-shareable parts of its structure.
+#
+# data = ['foo', 'bar'.freeze]
+# r = Ractor.new do
+# data2 = Ractor.receive
+# puts "In ractor: #{data2.object_id}, #{data2[0].object_id}, #{data2[1].object_id}"
+# end
+# r.send(data)
+# r.take
+# puts "Outside : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}"
+#
+# This will output:
+#
+# In ractor: 340, 360, 320
+# Outside : 380, 400, 320
+#
+# (Note that object id of both array and non-frozen string inside array have changed inside
+# the ractor, showing it is different objects. But the second array's element, which is a
+# shareable frozen string, has the same object_id.)
+#
+# Deep cloning of the objects may be slow, and sometimes impossible. Alternatively,
+# <tt>move: true</tt> may be used on sending. This will <em>move</em> the object to the
+# receiving ractor, making it inaccessible for a sending ractor.
+#
+# data = ['foo', 'bar']
+# r = Ractor.new do
+# data_in_ractor = Ractor.receive
+# puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}"
+# end
+# r.send(data, move: true)
+# r.take
+# puts "Outside: moved? #{Ractor::MovedObject === data}"
+# puts "Outside: #{data.inspect}"
+#
+# This will output:
+#
+# In ractor: 100, 120
+# Outside: moved? true
+# test.rb:9:in `method_missing': can not send any methods to a moved object (Ractor::MovedError)
+#
+# Notice that even +inspect+ (and more basic methods like <tt>__id__</tt>) is inaccessible
+# on a moved object.
+#
+# Besides frozen objects, there are shareable objects. Class and Module objects are shareable so
+# the Class/Module definitons are shared between ractors. Ractor objects are also shareable objects.
+# All operations for the shareable mutable objects are thread-safe, so the thread-safety property
+# will be kept. We can not define mutable shareable objects in Ruby, but C extensions can introduce them.
+#
+# It is prohibited to access instance variables of mutable shareable objects (especially Modules and classes)
+# from ractors other than main:
+#
+# class C
+# class << self
+# attr_accessor :tricky
+# end
+# end
+#
+# C.tricky = 'test'
+#
+# r = Ractor.new(C) do |cls|
+# puts "I see #{cls}"
+# puts "I can't see #{cls.tricky}"
+# end
+# r.take
+# # I see C
+# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
+#
+# Ractors can access constants if they are shareable. The main Ractor is the only one that can
+# access non-shareable constants.
+#
+# GOOD = 'good'.freeze
+# BAD = 'bad'
+#
+# r = Ractor.new do
+# puts "GOOD=#{GOOD}"
+# puts "BAD=#{BAD}"
+# end
+# r.take
+# # GOOD=good
+# # can not access non-shareable objects in constant Object::BAD by non-main Ractor. (NameError)
+#
+# # Consider the same C class from above
+#
+# r = Ractor.new do
+# puts "I see #{C}"
+# puts "I can't see #{C.tricky}"
+# end
+# r.take
+# # I see C
+# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
+#
+# See also the description of <tt># shareable_constant_value</tt> pragma in
+# {Comments syntax}[rdoc-ref:doc/syntax/comments.rdoc] explanation.
+#
+# == Ractors vs threads
+#
+# Each ractor creates its own thread. New threads can be created from inside ractor
+# (and, on CRuby, sharing GVL with other threads of this ractor).
+#
+# r = Ractor.new do
+# a = 1
+# Thread.new {puts "Thread in ractor: a=#{a}"}.join
+# end
+# r.take
+# # Here "Thread in ractor: a=1" will be printed
+#
+# == Note on code examples
+#
+# In examples below, sometimes we use the following method to wait till ractors that
+# are not currently blocked will finish (or process till next blocking) method.
+#
+# def wait
+# sleep(0.1)
+# end
+#
+# It is **only for demonstration purposes** and shouldn't be used in a real code.
+# Most of the times, just #take is used to wait till ractor will finish.
+#
+# == Reference
+#
+# See {Ractor desgin doc}[rdoc-ref:doc/ractor.md] for more details.
+#
+class Ractor
+ #
+ # call-seq:
+ # Ractor.new(*args, name: nil) {|*args| block } -> ractor
+ #
+ # Create a new Ractor with args and a block.
+ #
+ # A block (Proc) will be isolated (can't access to outer variables). +self+
+ # inside the block will refer to the current Ractor.
+ #
+ # r = Ractor.new { puts "Hi, I am #{self.inspect}" }
+ # r.take
+ # # Prints "Hi, I am #<Ractor:#2 test.rb:1 running>"
+ #
+ # +args+ passed to the method would be propagated to block args by the same rules as
+ # objects passed through #send/Ractor.receive: if +args+ are not shareable, they
+ # will be copied (via deep cloning, which might be inefficient).
+ #
+ # arg = [1, 2, 3]
+ # puts "Passing: #{arg} (##{arg.object_id})"
+ # r = Ractor.new(arg) {|received_arg|
+ # puts "Received: #{received_arg} (##{received_arg.object_id})"
+ # }
+ # r.take
+ # # Prints:
+ # # Passing: [1, 2, 3] (#280)
+ # # Received: [1, 2, 3] (#300)
+ #
+ # Ractor's +name+ can be set for debugging purposes:
+ #
+ # r = Ractor.new(name: 'my ractor') {}
+ # p r
+ # #=> #<Ractor:#3 my ractor test.rb:1 terminated>
+ #
+ def self.new(*args, name: nil, &block)
+ b = block # TODO: builtin bug
+ raise ArgumentError, "must be called with a block" unless block
+ loc = caller_locations(1, 1).first
+ loc = "#{loc.path}:#{loc.lineno}"
+ __builtin_ractor_create(loc, name, args, b)
+ end
+
+ # Returns the currently executing Ractor.
+ #
+ # Ractor.current #=> #<Ractor:#1 running>
+ def self.current
+ __builtin_cexpr! %q{
+ rb_ractor_self(rb_ec_ractor_ptr(ec));
+ }
+ end
+
+ # Returns total count of Ractors currently running.
+ #
+ # Ractor.count #=> 1
+ # r = Ractor.new(name: 'example') { Ractor.yield(1) }
+ # Ractor.count #=> 2 (main + example ractor)
+ # r.take # wait for Ractor.yield(1)
+ # r.take # wait till r will finish
+ # Ractor.count #=> 1
+ def self.count
+ __builtin_cexpr! %q{
+ ULONG2NUM(GET_VM()->ractor.cnt);
+ }
+ end
+
+ #
+ # call-seq:
+ # Ractor.select(*ractors, [yield_value:, move: false]) -> [ractor or symbol, obj]
+ #
+ # Waits for the first ractor to have something in its outgoing port, reads from this ractor, and
+ # returns that ractor and the object received.
+ #
+ # r1 = Ractor.new {Ractor.yield 'from 1'}
+ # r2 = Ractor.new {Ractor.yield 'from 2'}
+ #
+ # r, obj = Ractor.select(r1, r2)
+ #
+ # puts "received #{obj.inspect} from #{r.inspect}"
+ # # Prints: received "from 1" from #<Ractor:#2 test.rb:1 running>
+ #
+ # If one of the given ractors is the current ractor, and it would be selected, +r+ will contain
+ # +:receive+ symbol instead of the ractor object.
+ #
+ # r1 = Ractor.new(Ractor.current) do |main|
+ # main.send 'to main'
+ # Ractor.yield 'from 1'
+ # end
+ # r2 = Ractor.new do
+ # Ractor.yield 'from 2'
+ # end
+ #
+ # r, obj = Ractor.select(r1, r2, Ractor.current)
+ # puts "received #{obj.inspect} from #{r.inspect}"
+ # # Prints: received "to main" from :receive
+ #
+ # If +yield_value+ is provided, that value may be yielded if another Ractor is calling #take.
+ # In this case, the pair <tt>[:yield, nil]</tt> would be returned:
+ #
+ # r1 = Ractor.new(Ractor.current) do |main|
+ # puts "Received from main: #{main.take}"
+ # end
+ #
+ # puts "Trying to select"
+ # r, obj = Ractor.select(r1, Ractor.current, yield_value: 123)
+ # wait
+ # puts "Received #{obj.inspect} from #{r.inspect}"
+ #
+ # This will print:
+ #
+ # Trying to select
+ # Received from main: 123
+ # Received nil from :yield
+ #
+ # +move+ boolean flag defines whether yielded value should be copied (default) or moved.
+ def self.select(*ractors, yield_value: yield_unspecified = true, move: false)
+ raise ArgumentError, 'specify at least one ractor or `yield_value`' if yield_unspecified && ractors.empty?
+
+ __builtin_cstmt! %q{
+ const VALUE *rs = RARRAY_CONST_PTR_TRANSIENT(ractors);
+ VALUE rv;
+ VALUE v = ractor_select(ec, rs, RARRAY_LENINT(ractors),
+ yield_unspecified == Qtrue ? Qundef : yield_value,
+ (bool)RTEST(move) ? true : false, &rv);
+ return rb_ary_new_from_args(2, rv, v);
+ }
+ end
+
+ #
+ # call-seq:
+ # Ractor.receive -> msg
+ #
+ # Receive an incoming message from the current Ractor's incoming port's queue, which was
+ # sent there by #send.
+ #
+ # r = Ractor.new do
+ # v1 = Ractor.receive
+ # puts "Received: #{v1}"
+ # end
+ # r.send('message1')
+ # r.take
+ # # Here will be printed: "Received: message1"
+ #
+ # Alternatively, private instance method +receive+ may be used:
+ #
+ # r = Ractor.new do
+ # v1 = receive
+ # puts "Received: #{v1}"
+ # end
+ # r.send('message1')
+ # r.take
+ # # Here will be printed: "Received: message1"
+ #
+ # The method blocks if the queue is empty.
+ #
+ # r = Ractor.new do
+ # puts "Before first receive"
+ # v1 = Ractor.receive
+ # puts "Received: #{v1}"
+ # v2 = Ractor.receive
+ # puts "Received: #{v2}"
+ # end
+ # wait
+ # puts "Still not received"
+ # r.send('message1')
+ # wait
+ # puts "Still received only one"
+ # r.send('message2')
+ # r.take
+ #
+ # Output:
+ #
+ # Before first receive
+ # Still not received
+ # Received: message1
+ # Still received only one
+ # Received: message2
+ #
+ # If close_incoming was called on the ractor, the method raises Ractor::ClosedError
+ # if there are no more messages in incoming queue:
+ #
+ # Ractor.new do
+ # close_incoming
+ # receive
+ # end
+ # wait
+ # # in `receive': The incoming port is already closed => #<Ractor:#2 test.rb:1 running> (Ractor::ClosedError)
+ #
+ def self.receive
+ __builtin_cexpr! %q{
+ ractor_receive(ec, rb_ec_ractor_ptr(ec))
+ }
+ end
+
+ class << self
+ alias recv receive
+ end
+
+ # same as Ractor.receive
+ private def receive
+ __builtin_cexpr! %q{
+ ractor_receive(ec, rb_ec_ractor_ptr(ec))
+ }
+ end
+ alias recv receive
+
+ #
+ # call-seq:
+ # Ractor.receive_if {|msg| block } -> msg
+ #
+ # Receive only a specific message.
+ #
+ # Instead of Ractor.receive, Ractor.receive_if can provide a pattern
+ # by a block and you can choose the receiving message.
+ #
+ # r = Ractor.new do
+ # p Ractor.receive_if{|msg| msg.match?(/foo/)} #=> "foo3"
+ # p Ractor.receive_if{|msg| msg.match?(/bar/)} #=> "bar1"
+ # p Ractor.receive_if{|msg| msg.match?(/baz/)} #=> "baz2"
+ # end
+ # r << "bar1"
+ # r << "baz2"
+ # r << "foo3"
+ # r.take
+ #
+ # This will output:
+ #
+ # foo3
+ # bar1
+ # baz2
+ #
+ # If the block returns a truthy value, the message will be removed from the incoming queue
+ # and returned.
+ # Otherwise, the messsage remains in the incoming queue and the following received
+ # messages are checked by the given block.
+ #
+ # If there are no messages left in the incoming queue, the method will
+ # block until new messages arrive.
+ #
+ # If the block is escaped by break/return/exception/throw, the message is removed from
+ # the incoming queue as if a truthy value had been returned.
+ #
+ # r = Ractor.new do
+ # val = Ractor.receive_if{|msg| msg.is_a?(Array)}
+ # puts "Received successfully: #{val}"
+ # end
+ #
+ # r.send(1)
+ # r.send('test')
+ # wait
+ # puts "2 non-matching sent, nothing received"
+ # r.send([1, 2, 3])
+ # wait
+ #
+ # Prints:
+ #
+ # 2 non-matching sent, nothing received
+ # Received successfully: [1, 2, 3]
+ #
+ # Note that you can not call receive/receive_if in the given block recursively.
+ # It means that you should not do any tasks in the block.
+ #
+ # Ractor.current << true
+ # Ractor.receive_if{|msg| Ractor.receive}
+ # #=> `receive': can not call receive/receive_if recursively (Ractor::Error)
+ #
+ def self.receive_if &b
+ Primitive.ractor_receive_if b
+ end
+
+ private def receive_if &b
+ Primitive.ractor_receive_if b
+ end
+
+ #
+ # call-seq:
+ # ractor.send(msg, move: false) -> self
+ #
+ # Send a message to a Ractor's incoming queue to be consumed by Ractor.receive.
+ #
+ # r = Ractor.new do
+ # value = Ractor.receive
+ # puts "Received #{value}"
+ # end
+ # r.send 'message'
+ # # Prints: "Received: message"
+ #
+ # The method is non-blocking (will return immediately even if the ractor is not ready
+ # to receive anything):
+ #
+ # r = Ractor.new {sleep(5)}
+ # r.send('test')
+ # puts "Sent successfully"
+ # # Prints: "Sent successfully" immediately
+ #
+ # Attempt to send to ractor which already finished its execution will raise Ractor::ClosedError.
+ #
+ # r = Ractor.new {}
+ # r.take
+ # p r
+ # # "#<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 would be raised immediately, not when ractor will try to receive
+ #
+ # If the +obj+ is unshareable, by default it would be copied into ractor by deep cloning.
+ # If the <tt>move: true</tt> is passed, object is _moved_ into ractor and becomes
+ # inaccessible to sender.
+ #
+ # r = Ractor.new {puts "Received: #{receive}"}
+ # msg = 'message'
+ # r.send(msg, move: true)
+ # r.take
+ # p msg
+ #
+ # This prints:
+ #
+ # Received: message
+ # in `p': undefined method `inspect' for #<Ractor::MovedObject:0x000055c99b9b69b8>
+ #
+ # All references to the object and its parts will become invalid in sender.
+ #
+ # r = Ractor.new {puts "Received: #{receive}"}
+ # s = 'message'
+ # ary = [s]
+ # copy = ary.dup
+ # r.send(ary, move: true)
+ #
+ # s.inspect
+ # # Ractor::MovedError (can not send any methods to a moved object)
+ # ary.class
+ # # Ractor::MovedError (can not send any methods to a moved object)
+ # copy.class
+ # # => Array, it is different object
+ # copy[0].inspect
+ # # Ractor::MovedError (can not send any methods to a moved object)
+ # # ...but its item was still a reference to `s`, which was moved
+ #
+ # If the object was shareable, <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)
+ }
+ end
+ alias << send
+
+ #
+ # call-seq:
+ # Ractor.yield(msg, move: false) -> nil
+ #
+ # Send a message to the current ractor's outgoing port to be consumed by #take.
+ #
+ # r = Ractor.new {Ractor.yield 'Hello from ractor'}
+ # puts r.take
+ # # Prints: "Hello from ractor"
+ #
+ # The method is blocking, and will return only when somebody consumes the
+ # sent message.
+ #
+ # r = Ractor.new do
+ # Ractor.yield 'Hello from ractor'
+ # puts "Ractor: after yield"
+ # end
+ # wait
+ # puts "Still not taken"
+ # puts r.take
+ #
+ # This will print:
+ #
+ # Still not taken
+ # Hello from ractor
+ # Ractor: after yield
+ #
+ # If the outgoing port was closed with #close_outgoing, the method will raise:
+ #
+ # r = Ractor.new do
+ # close_outgoing
+ # Ractor.yield 'Hello from ractor'
+ # end
+ # wait
+ # # `yield': The outgoing-port is already closed (Ractor::ClosedError)
+ #
+ # The meaning of +move+ argument is the same as for #send.
+ def self.yield(obj, move: false)
+ __builtin_cexpr! %q{
+ ractor_yield(ec, rb_ec_ractor_ptr(ec), obj, move)
+ }
+ end
+
+ #
+ # call-seq:
+ # ractor.take -> msg
+ #
+ # Take a message from ractor's outgoing port, which was put there by Ractor.yield or at ractor's
+ # finalization.
+ #
+ # r = Ractor.new do
+ # Ractor.yield 'explicit yield'
+ # 'last value'
+ # end
+ # puts r.take #=> 'explicit yield'
+ # puts r.take #=> 'last value'
+ # puts r.take # Ractor::ClosedError (The outgoing-port is already closed)
+ #
+ # The fact that the last value is also put to outgoing port means that +take+ can be used
+ # as some analog of Thread#join ("just wait till ractor finishes"), but don't forget it
+ # will raise if somebody had already consumed everything ractor have produced.
+ #
+ # If the outgoing port was closed with #close_outgoing, the method will raise Ractor::ClosedError.
+ #
+ # r = Ractor.new do
+ # sleep(500)
+ # Ractor.yield 'Hello from ractor'
+ # end
+ # r.close_outgoing
+ # r.take
+ # # Ractor::ClosedError (The outgoing-port is already closed)
+ # # The error would be raised immediately, not when ractor will try to receive
+ #
+ # If an uncaught exception is raised in the Ractor, it is propagated on take as a
+ # Ractor::RemoteError.
+ #
+ # r = Ractor.new {raise "Something weird happened"}
+ #
+ # begin
+ # r.take
+ # rescue => e
+ # p e # => #<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 closing of the ractor will break
+ # the loops without propagating the error:
+ #
+ # r = Ractor.new do
+ # 3.times {|i| Ractor.yield "message #{i}"}
+ # "finishing"
+ # end
+ #
+ # loop {puts "Received: " + r.take}
+ # puts "Continue successfully"
+ #
+ # This will print:
+ #
+ # Received: message 0
+ # Received: message 1
+ # Received: message 2
+ # Received: finishing
+ # Continue successfully
+ def take
+ __builtin_cexpr! %q{
+ ractor_take(ec, RACTOR_PTR(self))
+ }
+ end
+
+ def inspect
+ loc = __builtin_cexpr! %q{ RACTOR_PTR(self)->loc }
+ name = __builtin_cexpr! %q{ RACTOR_PTR(self)->name }
+ id = __builtin_cexpr! %q{ INT2FIX(rb_ractor_id(RACTOR_PTR(self))) }
+ status = __builtin_cexpr! %q{
+ rb_str_new2(ractor_status_str(RACTOR_PTR(self)->status_))
+ }
+ "#<Ractor:##{id}#{name ? ' '+name : ''}#{loc ? " " + loc : ''} #{status}>"
+ end
+
+ alias to_s inspect
+
+ # The name set in Ractor.new, or +nil+.
+ def name
+ __builtin_cexpr! %q{RACTOR_PTR(self)->name}
+ end
+
+ class RemoteError
+ attr_reader :ractor
+ end
+
+ #
+ # call-seq:
+ # ractor.close_incoming -> true | false
+ #
+ # Closes the incoming port and returns its previous state.
+ # All further attempts to Ractor.receive in the ractor, and #send to the ractor
+ # will fail with Ractor::ClosedError.
+ #
+ # r = Ractor.new {sleep(500)}
+ # r.close_incoming #=> false
+ # r.close_incoming #=> true
+ # r.send('test')
+ # # Ractor::ClosedError (The incoming-port is already closed)
+ def close_incoming
+ __builtin_cexpr! %q{
+ ractor_close_incoming(ec, RACTOR_PTR(self));
+ }
+ end
+
+ #
+ # call-seq:
+ # ractor.close_outgoing -> true | false
+ #
+ # Closes the outgoing port and returns its previous state.
+ # All further attempts to Ractor.yield in the ractor, and #take from the ractor
+ # will fail with Ractor::ClosedError.
+ #
+ # r = Ractor.new {sleep(500)}
+ # r.close_outgoing #=> false
+ # r.close_outgoing #=> true
+ # r.take
+ # # Ractor::ClosedError (The outgoing-port is already closed)
+ def close_outgoing
+ __builtin_cexpr! %q{
+ ractor_close_outgoing(ec, RACTOR_PTR(self));
+ }
+ end
+
+ #
+ # call-seq:
+ # Ractor.shareable?(obj) -> true | false
+ #
+ # Checks if the object is shareable by ractors.
+ #
+ # Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are frozen
+ # Ractor.shareable?('foo') #=> false, unless the string is frozen due to # freeze_string_literals: true
+ # Ractor.shareable?('foo'.freeze) #=> true
+ #
+ # See also the "Shareable and unshareable objects" section in the Ractor class docs.
+ def self.shareable? obj
+ __builtin_cexpr! %q{
+ rb_ractor_shareable_p(obj) ? Qtrue : Qfalse;
+ }
+ end
+
+ #
+ # call-seq:
+ # Ractor.make_shareable(obj, copy: false) -> shareable_obj
+ #
+ # Make +obj+ shareable between ractors.
+ #
+ # +obj+ and all the objects it refers to will be frozen, unless they are
+ # already shareable.
+ #
+ # If +copy+ keyword is +true+, the method will copy objects before freezing them
+ # This is safer option but it can take be slower.
+ #
+ # Note that the specification and implementation of this method are not
+ # mature and may be changed in the future.
+ #
+ # obj = ['test']
+ # Ractor.shareable?(obj) #=> false
+ # Ractor.make_shareable(obj) #=> ["test"]
+ # Ractor.shareable?(obj) #=> true
+ # obj.frozen? #=> true
+ # obj[0].frozen? #=> true
+ #
+ # # Copy vs non-copy versions:
+ # obj1 = ['test']
+ # obj1s = Ractor.make_shareable(obj1)
+ # obj1.frozen? #=> true
+ # obj1s.object_id == obj1.object_id #=> true
+ # obj2 = ['test']
+ # obj2s = Ractor.make_shareable(obj2, copy: true)
+ # obj2.frozen? #=> false
+ # obj2s.frozen? #=> true
+ # obj2s.object_id == obj2.object_id #=> false
+ # obj2s[0].object_id == obj2[0].object_id #=> false
+ #
+ # See also the "Shareable and unshareable objects" section in the Ractor class docs.
+ def self.make_shareable obj, copy: false
+ if copy
+ __builtin_cexpr! %q{
+ rb_ractor_make_shareable_copy(obj);
+ }
+ else
+ __builtin_cexpr! %q{
+ rb_ractor_make_shareable(obj);
+ }
+ end
+ end
+
+ # get a value from ractor-local storage
+ def [](sym)
+ Primitive.ractor_local_value(sym)
+ end
+
+ # set a value in ractor-local storage
+ def []=(sym, val)
+ Primitive.ractor_local_value_set(sym, val)
+ end
+
+ # returns main ractor
+ def self.main
+ __builtin_cexpr! %q{
+ rb_ractor_self(GET_VM()->ractor.main_ractor);
+ }
+ end
+end
diff --git a/ractor_core.h b/ractor_core.h
new file mode 100644
index 0000000000..800e7ce409
--- /dev/null
+++ b/ractor_core.h
@@ -0,0 +1,341 @@
+#include "ruby/ruby.h"
+#include "ruby/ractor.h"
+#include "vm_core.h"
+#include "id_table.h"
+#include "vm_debug.h"
+
+#ifndef RACTOR_CHECK_MODE
+#define RACTOR_CHECK_MODE (0 || VM_CHECK_MODE || RUBY_DEBUG)
+#endif
+
+enum rb_ractor_basket_type {
+ basket_type_none,
+ basket_type_ref,
+ basket_type_copy,
+ basket_type_move,
+ basket_type_will,
+ basket_type_deleted,
+ basket_type_reserved,
+};
+
+struct rb_ractor_basket {
+ bool exception;
+ enum rb_ractor_basket_type type;
+ VALUE v;
+ VALUE sender;
+};
+
+struct rb_ractor_queue {
+ struct rb_ractor_basket *baskets;
+ int start;
+ int cnt;
+ int size;
+ unsigned int serial;
+ unsigned int reserved_cnt;
+};
+
+struct rb_ractor_waiting_list {
+ int cnt;
+ int size;
+ rb_ractor_t **ractors;
+};
+
+struct rb_ractor_sync {
+ // ractor lock
+ rb_nativethread_lock_t lock;
+#if RACTOR_CHECK_MODE > 0
+ VALUE locked_by;
+#endif
+ rb_nativethread_cond_t cond;
+
+ // communication
+ struct rb_ractor_queue incoming_queue;
+ struct rb_ractor_waiting_list taking_ractors;
+
+ bool incoming_port_closed;
+ bool outgoing_port_closed;
+
+ struct ractor_wait {
+ enum ractor_wait_status {
+ wait_none = 0x00,
+ wait_receiving = 0x01,
+ wait_taking = 0x02,
+ wait_yielding = 0x04,
+ wait_moving = 0x08,
+ } status;
+
+ enum ractor_wakeup_status {
+ wakeup_none,
+ wakeup_by_send,
+ wakeup_by_yield,
+ wakeup_by_take,
+ wakeup_by_close,
+ wakeup_by_interrupt,
+ wakeup_by_retry,
+ } wakeup_status;
+
+ struct rb_ractor_basket yielded_basket;
+ struct rb_ractor_basket taken_basket;
+ } wait;
+};
+
+struct rb_ractor_struct {
+ struct rb_ractor_pub pub;
+
+ struct rb_ractor_sync sync;
+ VALUE receiving_mutex;
+ bool yield_atexit;
+
+ // vm wide barrier synchronization
+ rb_nativethread_cond_t barrier_wait_cond;
+
+ // thread management
+ struct {
+ struct list_head set;
+ unsigned int cnt;
+ unsigned int blocking_cnt;
+ unsigned int sleeper;
+ rb_global_vm_lock_t gvl;
+ rb_execution_context_t *running_ec;
+ rb_thread_t *main;
+ } threads;
+ VALUE thgroup_default;
+
+ VALUE name;
+ VALUE loc;
+
+ // created
+ // | ready to run
+ // ====================== inserted to vm->ractor
+ // v
+ // blocking <---+ all threads are blocking
+ // | |
+ // v |
+ // running -----+
+ // | all threads are terminated.
+ // ====================== removed from vm->ractor
+ // v
+ // terminated
+ //
+ // status is protected by VM lock (global state)
+
+ enum ractor_status {
+ ractor_created,
+ ractor_running,
+ ractor_blocking,
+ ractor_terminated,
+ } status_;
+
+ struct list_node vmlr_node;
+
+ // ractor local data
+
+ st_table *local_storage;
+ struct rb_id_table *idkey_local_storage;
+
+ VALUE r_stdin;
+ VALUE r_stdout;
+ VALUE r_stderr;
+ VALUE verbose;
+ VALUE debug;
+
+ rb_ractor_newobj_cache_t newobj_cache;
+
+ // gc.c rb_objspace_reachable_objects_from
+ struct gc_mark_func_data_struct {
+ void *data;
+ void (*mark_func)(VALUE v, void *data);
+ } *mfd;
+}; // rb_ractor_t is defined in vm_core.h
+
+
+static inline VALUE
+rb_ractor_self(const rb_ractor_t *r)
+{
+ return r->pub.self;
+}
+
+rb_ractor_t *rb_ractor_main_alloc(void);
+void rb_ractor_main_setup(rb_vm_t *vm, rb_ractor_t *main_ractor, rb_thread_t *main_thread);
+void rb_ractor_atexit(rb_execution_context_t *ec, VALUE result);
+void rb_ractor_atexit_exception(rb_execution_context_t *ec);
+void rb_ractor_teardown(rb_execution_context_t *ec);
+void rb_ractor_receive_parameters(rb_execution_context_t *ec, rb_ractor_t *g, int len, VALUE *ptr);
+void rb_ractor_send_parameters(rb_execution_context_t *ec, rb_ractor_t *g, VALUE args);
+
+VALUE rb_thread_create_ractor(rb_ractor_t *g, VALUE args, VALUE proc); // defined in thread.c
+
+rb_global_vm_lock_t *rb_ractor_gvl(rb_ractor_t *);
+int rb_ractor_living_thread_num(const rb_ractor_t *);
+VALUE rb_ractor_thread_list(rb_ractor_t *r);
+
+void rb_ractor_living_threads_init(rb_ractor_t *r);
+void rb_ractor_living_threads_insert(rb_ractor_t *r, rb_thread_t *th);
+void rb_ractor_living_threads_remove(rb_ractor_t *r, rb_thread_t *th);
+void rb_ractor_blocking_threads_inc(rb_ractor_t *r, const char *file, int line); // TODO: file, line only for RUBY_DEBUG_LOG
+void rb_ractor_blocking_threads_dec(rb_ractor_t *r, const char *file, int line); // TODO: file, line only for RUBY_DEBUG_LOG
+
+void rb_ractor_vm_barrier_interrupt_running_thread(rb_ractor_t *r);
+void rb_ractor_terminate_interrupt_main_thread(rb_ractor_t *r);
+void rb_ractor_terminate_all(void);
+bool rb_ractor_main_p_(void);
+void rb_ractor_finish_marking(void);
+void rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th);
+
+VALUE rb_ractor_ensure_shareable(VALUE obj, VALUE name);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+bool rb_ractor_shareable_p_continue(VALUE obj);
+
+// THIS FUNCTION SHOULD NOT CALL WHILE INCREMENTAL MARKING!!
+// This function is for T_DATA::free_func
+void rb_ractor_local_storage_delkey(rb_ractor_local_key_t key);
+
+RUBY_SYMBOL_EXPORT_END
+
+static inline bool
+rb_ractor_main_p(void)
+{
+ if (ruby_single_main_ractor) {
+ return true;
+ }
+ else {
+ return rb_ractor_main_p_();
+ }
+}
+
+static inline bool
+rb_ractor_status_p(rb_ractor_t *r, enum ractor_status status)
+{
+ return r->status_ == status;
+}
+
+static inline void
+rb_ractor_sleeper_threads_inc(rb_ractor_t *r)
+{
+ r->threads.sleeper++;
+}
+
+static inline void
+rb_ractor_sleeper_threads_dec(rb_ractor_t *r)
+{
+ r->threads.sleeper--;
+}
+
+static inline void
+rb_ractor_sleeper_threads_clear(rb_ractor_t *r)
+{
+ r->threads.sleeper = 0;
+}
+
+static inline int
+rb_ractor_sleeper_thread_num(rb_ractor_t *r)
+{
+ return r->threads.sleeper;
+}
+
+static inline void
+rb_ractor_thread_switch(rb_ractor_t *cr, rb_thread_t *th)
+{
+ if (cr->threads.running_ec != th->ec) {
+ if (0) fprintf(stderr, "rb_ractor_thread_switch ec:%p->%p\n",
+ (void *)cr->threads.running_ec, (void *)th->ec);
+ }
+ else {
+ return;
+ }
+
+ if (cr->threads.running_ec != th->ec) {
+ th->running_time_us = 0;
+ }
+
+ cr->threads.running_ec = th->ec;
+
+ VM_ASSERT(cr == GET_RACTOR());
+}
+
+static inline void
+rb_ractor_set_current_ec(rb_ractor_t *cr, rb_execution_context_t *ec)
+{
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+ #if __APPLE__
+ rb_current_ec_set(ec);
+ #else
+ ruby_current_ec = ec;
+ #endif
+#else
+ native_tls_set(ruby_current_ec_key, ec);
+#endif
+
+ if (cr->threads.running_ec != ec) {
+ if (0) fprintf(stderr, "rb_ractor_set_current_ec ec:%p->%p\n",
+ (void *)cr->threads.running_ec, (void *)ec);
+ }
+ else {
+ VM_ASSERT(0); // should be different
+ }
+
+ cr->threads.running_ec = ec;
+}
+
+void rb_vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line);
+void rb_vm_ractor_blocking_cnt_dec(rb_vm_t *vm, rb_ractor_t *cr, const char *file, int line);
+
+static inline uint32_t
+rb_ractor_id(const rb_ractor_t *r)
+{
+ return r->pub.id;
+}
+
+#if RACTOR_CHECK_MODE > 0
+uint32_t rb_ractor_current_id(void);
+
+static inline void
+rb_ractor_setup_belonging_to(VALUE obj, uint32_t rid)
+{
+ VALUE flags = RBASIC(obj)->flags & 0xffffffff; // 4B
+ RBASIC(obj)->flags = flags | ((VALUE)rid << 32);
+}
+
+static inline void
+rb_ractor_setup_belonging(VALUE obj)
+{
+ rb_ractor_setup_belonging_to(obj, rb_ractor_current_id());
+}
+
+static inline uint32_t
+rb_ractor_belonging(VALUE obj)
+{
+ if (SPECIAL_CONST_P(obj) || RB_OBJ_SHAREABLE_P(obj)) {
+ return 0;
+ }
+ else {
+ return RBASIC(obj)->flags >> 32;
+ }
+}
+
+static inline VALUE
+rb_ractor_confirm_belonging(VALUE obj)
+{
+ uint32_t id = rb_ractor_belonging(obj);
+
+ if (id == 0) {
+ if (UNLIKELY(!rb_ractor_shareable_p(obj))) {
+ rp(obj);
+ rb_bug("id == 0 but not shareable");
+ }
+ }
+ else if (UNLIKELY(id != rb_ractor_current_id())) {
+ if (rb_ractor_shareable_p(obj)) {
+ // ok
+ }
+ else {
+ rp(obj);
+ rb_bug("rb_ractor_confirm_belonging object-ractor id:%u, current-ractor id:%u", id, rb_ractor_current_id());
+ }
+ }
+ return obj;
+}
+#else
+#define rb_ractor_confirm_belonging(obj) obj
+#endif
diff --git a/random.c b/random.c
index f2e57909a3..4d70c17116 100644
--- a/random.c
+++ b/random.c
@@ -9,45 +9,67 @@
**********************************************************************/
-#if defined __APPLE__
-# include <AvailabilityMacros.h>
-#endif
-
-#include "internal.h"
+#include "ruby/internal/config.h"
+#include <errno.h>
#include <limits.h>
+#include <math.h>
+#include <float.h>
+#include <time.h>
+
#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+# include <unistd.h>
#endif
-#include <time.h>
+
#include <sys/types.h>
#include <sys/stat.h>
+
#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
+# include <fcntl.h>
#endif
-#include <math.h>
-#include <errno.h>
+
#if defined(HAVE_SYS_TIME_H)
-#include <sys/time.h>
+# include <sys/time.h>
#endif
#ifdef HAVE_SYSCALL_H
-#include <syscall.h>
+# include <syscall.h>
#elif defined HAVE_SYS_SYSCALL_H
-#include <sys/syscall.h>
+# include <sys/syscall.h>
#endif
#ifdef _WIN32
-#include <windows.h>
-#include <wincrypt.h>
+# include <winsock2.h>
+# include <windows.h>
+# include <wincrypt.h>
#endif
-#include "ruby_atomic.h"
#ifdef __OpenBSD__
/* to define OpenBSD for version check */
-#include <sys/param.h>
+# include <sys/param.h>
+#endif
+
+#if defined HAVE_GETRANDOM
+# include <sys/random.h>
+#elif defined __linux__ && defined __NR_getrandom
+# include <linux/random.h>
+#endif
+
+#if defined __APPLE__
+# include <AvailabilityMacros.h>
#endif
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/compilers.h"
+#include "internal/numeric.h"
+#include "internal/random.h"
+#include "internal/sanitizers.h"
+#include "internal/variable.h"
+#include "ruby_atomic.h"
+#include "ruby/random.h"
+#include "ruby/ractor.h"
+
typedef int int_must_be_32bit_at_least[sizeof(int) * CHAR_BIT < 32 ? -1 : 1];
#include "missing/mt19937.c"
@@ -62,12 +84,22 @@ genrand_real(struct MT *mt)
return int_pair_to_real_exclusive(a, b);
}
+static const double dbl_reduce_scale = /* 2**(-DBL_MANT_DIG) */
+ (1.0
+ / (double)(DBL_MANT_DIG > 2*31 ? (1ul<<31) : 1.0)
+ / (double)(DBL_MANT_DIG > 1*31 ? (1ul<<31) : 1.0)
+ / (double)(1ul<<(DBL_MANT_DIG%31)));
+
static double
int_pair_to_real_exclusive(uint32_t a, uint32_t b)
{
- a >>= 5;
- b >>= 6;
- return(a*67108864.0+b)*(1.0/9007199254740992.0);
+ static const int a_shift = DBL_MANT_DIG < 64 ?
+ (64-DBL_MANT_DIG)/2 : 0;
+ static const int b_shift = DBL_MANT_DIG < 64 ?
+ (65-DBL_MANT_DIG)/2 : 0;
+ a >>= a_shift;
+ b >>= b_shift;
+ return (a*(double)(1ul<<(32-b_shift))+b)*dbl_reduce_scale;
}
/* generates a random number on [0,1] with 53-bit resolution*/
@@ -88,44 +120,82 @@ genrand_real2(struct MT *mt)
#undef M
typedef struct {
- VALUE seed;
+ rb_random_t base;
struct MT mt;
-} rb_random_t;
+} rb_random_mt_t;
#define DEFAULT_SEED_CNT 4
-static rb_random_t default_rand;
-
-static VALUE rand_init(struct MT *mt, VALUE vseed);
+static VALUE rand_init(const rb_random_interface_t *, rb_random_t *, VALUE);
static VALUE random_seed(VALUE);
+static void fill_random_seed(uint32_t *seed, size_t cnt);
+static VALUE make_seed_value(uint32_t *ptr, size_t len);
-static rb_random_t *
-rand_start(rb_random_t *r)
+RB_RANDOM_INTERFACE_DECLARE(rand_mt);
+static const rb_random_interface_t random_mt_if = {
+ DEFAULT_SEED_CNT * 32,
+ RB_RANDOM_INTERFACE_DEFINE(rand_mt)
+};
+
+static rb_random_mt_t *
+rand_mt_start(rb_random_mt_t *r)
{
- struct MT *mt = &r->mt;
- if (!genrand_initialized(mt)) {
- r->seed = rand_init(mt, random_seed(Qundef));
+ if (!genrand_initialized(&r->mt)) {
+ r->base.seed = rand_init(&random_mt_if, &r->base, random_seed(Qundef));
}
return r;
}
-static struct MT *
+static rb_random_t *
+rand_start(rb_random_mt_t *r)
+{
+ return &rand_mt_start(r)->base;
+}
+
+static rb_ractor_local_key_t default_rand_key;
+
+static void
+default_rand_mark(void *ptr)
+{
+ rb_random_mt_t *rnd = (rb_random_mt_t *)ptr;
+ rb_gc_mark(rnd->base.seed);
+}
+
+static const struct rb_ractor_local_storage_type default_rand_key_storage_type = {
+ default_rand_mark,
+ ruby_xfree,
+};
+
+static rb_random_mt_t *
+default_rand(void)
+{
+ rb_random_mt_t *rnd;
+
+ if ((rnd = rb_ractor_local_storage_ptr(default_rand_key)) == NULL) {
+ rnd = ZALLOC(rb_random_mt_t);
+ rb_ractor_local_storage_ptr_set(default_rand_key, rnd);
+ }
+
+ return rnd;
+}
+
+static rb_random_mt_t *
default_mt(void)
{
- return &rand_start(&default_rand)->mt;
+ return rand_mt_start(default_rand());
}
unsigned int
rb_genrand_int32(void)
{
- struct MT *mt = default_mt();
+ struct MT *mt = &default_mt()->mt;
return genrand_int32(mt);
}
double
rb_genrand_real(void)
{
- struct MT *mt = default_mt();
+ struct MT *mt = &default_mt()->mt;
return genrand_real(mt);
}
@@ -135,13 +205,13 @@ static double
int_pair_to_real_inclusive(uint32_t a, uint32_t b)
{
double r;
- enum {dig = 53};
+ enum {dig = DBL_MANT_DIG};
enum {dig_u = dig-32, dig_r64 = 64-dig, bmask = ~(~0u<<(dig_r64))};
#if defined HAVE_UINT128_T
const uint128_t m = ((uint128_t)1 << dig) | 1;
uint128_t x = ((uint128_t)a << 32) | b;
r = (double)(uint64_t)((x * m) >> 64);
-#elif defined HAVE_UINT64_T && !(defined _MSC_VER && _MSC_VER <= 1200)
+#elif defined HAVE_UINT64_T && !MSC_VERSION_BEFORE(1300)
uint64_t x = ((uint64_t)a << dig_u) +
(((uint64_t)b + (a >> dig_u)) >> dig_r64);
r = (double)x;
@@ -150,7 +220,7 @@ int_pair_to_real_inclusive(uint32_t a, uint32_t b)
b = (b >> dig_r64) + (((a >> dig_u) + (b & bmask)) >> dig_r64);
r = (double)a * (1 << dig_u) + b;
#endif
- return ldexp(r, -dig);
+ return r * dbl_reduce_scale;
}
VALUE rb_cRandom;
@@ -160,18 +230,15 @@ static ID id_rand, id_bytes;
NORETURN(static void domain_error(void));
/* :nodoc: */
-static void
+#define random_mark rb_random_mark
+
+void
random_mark(void *ptr)
{
rb_gc_mark(((rb_random_t *)ptr)->seed);
}
-static void
-random_free(void *ptr)
-{
- if (ptr != &default_rand)
- xfree(ptr);
-}
+#define random_free RUBY_TYPED_DEFAULT_FREE
static size_t
random_memsize(const void *ptr)
@@ -179,8 +246,8 @@ random_memsize(const void *ptr)
return sizeof(rb_random_t);
}
-static const rb_data_type_t random_mt_type = {
- "random/MT",
+const rb_data_type_t rb_random_data_type = {
+ "random",
{
random_mark,
random_free,
@@ -189,62 +256,132 @@ static const rb_data_type_t random_mt_type = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
+#define random_mt_mark rb_random_mark
+
+static void
+random_mt_free(void *ptr)
+{
+ rb_random_mt_t *rnd = rb_ractor_local_storage_ptr(default_rand_key);
+ if (ptr != rnd)
+ xfree(ptr);
+}
+
+static size_t
+random_mt_memsize(const void *ptr)
+{
+ return sizeof(rb_random_mt_t);
+}
+
+static const rb_data_type_t random_mt_type = {
+ "random/MT",
+ {
+ random_mt_mark,
+ random_mt_free,
+ random_mt_memsize,
+ },
+ &rb_random_data_type,
+ (void *)&random_mt_if,
+ RUBY_TYPED_FREE_IMMEDIATELY
+};
+
static rb_random_t *
get_rnd(VALUE obj)
{
rb_random_t *ptr;
- TypedData_Get_Struct(obj, rb_random_t, &random_mt_type, ptr);
- return rand_start(ptr);
+ TypedData_Get_Struct(obj, rb_random_t, &rb_random_data_type, ptr);
+ if (RTYPEDDATA_TYPE(obj) == &random_mt_type)
+ return rand_start((rb_random_mt_t *)ptr);
+ return ptr;
+}
+
+static rb_random_mt_t *
+get_rnd_mt(VALUE obj)
+{
+ rb_random_mt_t *ptr;
+ TypedData_Get_Struct(obj, rb_random_mt_t, &random_mt_type, ptr);
+ return ptr;
}
static rb_random_t *
try_get_rnd(VALUE obj)
{
if (obj == rb_cRandom) {
- return rand_start(&default_rand);
+ return rand_start(default_rand());
}
- if (!rb_typeddata_is_kind_of(obj, &random_mt_type)) return NULL;
- return rand_start(DATA_PTR(obj));
+ if (!rb_typeddata_is_kind_of(obj, &rb_random_data_type)) return NULL;
+ if (RTYPEDDATA_TYPE(obj) == &random_mt_type)
+ return rand_start(DATA_PTR(obj));
+ rb_random_t *rnd = DATA_PTR(obj);
+ if (!rnd) {
+ rb_raise(rb_eArgError, "uninitialized random: %s",
+ RTYPEDDATA_TYPE(obj)->wrap_struct_name);
+ }
+ return rnd;
+}
+
+static const rb_random_interface_t *
+try_rand_if(VALUE obj, rb_random_t *rnd)
+{
+ if (rnd == &default_rand()->base) {
+ return &random_mt_if;
+ }
+ return rb_rand_if(obj);
+}
+
+/* :nodoc: */
+void
+rb_random_base_init(rb_random_t *rnd)
+{
+ rnd->seed = INT2FIX(0);
}
/* :nodoc: */
static VALUE
random_alloc(VALUE klass)
{
- rb_random_t *rnd;
- VALUE obj = TypedData_Make_Struct(klass, rb_random_t, &random_mt_type, rnd);
- rnd->seed = INT2FIX(0);
+ rb_random_mt_t *rnd;
+ VALUE obj = TypedData_Make_Struct(klass, rb_random_mt_t, &random_mt_type, rnd);
+ rb_random_base_init(&rnd->base);
return obj;
}
static VALUE
-rand_init(struct MT *mt, VALUE seed)
+rand_init_default(const rb_random_interface_t *rng, rb_random_t *rnd)
+{
+ VALUE seed, buf0 = 0;
+ size_t len = roomof(rng->default_seed_bits, 32);
+ uint32_t *buf = ALLOCV_N(uint32_t, buf0, len+1);
+
+ fill_random_seed(buf, len);
+ rng->init(rnd, buf, len);
+ seed = make_seed_value(buf, len);
+ explicit_bzero(buf, len * sizeof(*buf));
+ ALLOCV_END(buf0);
+ return seed;
+}
+
+static VALUE
+rand_init(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE seed)
{
- uint32_t buf0[SIZEOF_LONG / SIZEOF_INT32 * 4], *buf = buf0;
+ uint32_t *buf;
+ VALUE buf0 = 0;
size_t len;
int sign;
len = rb_absint_numwords(seed, 32, NULL);
- if (len > numberof(buf0))
- buf = ALLOC_N(uint32_t, len);
+ if (len == 0) len = 1;
+ buf = ALLOCV_N(uint32_t, buf0, len);
sign = rb_integer_pack(seed, buf, len, sizeof(uint32_t), 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
if (sign < 0)
sign = -sign;
- if (len == 0) {
- buf[0] = 0;
- len = 1;
- }
- if (len <= 1) {
- init_genrand(mt, buf[0]);
- }
- else {
+ if (len > 1) {
if (sign != 2 && buf[len-1] == 1) /* remove leading-zero-guard */
len--;
- init_by_array(mt, buf, (int)len);
}
+ rng->init(rnd, buf, len);
explicit_bzero(buf, len * sizeof(*buf));
- if (buf != buf0) xfree(buf);
+ ALLOCV_END(buf0);
return seed;
}
@@ -260,19 +397,21 @@ rand_init(struct MT *mt, VALUE seed)
static VALUE
random_init(int argc, VALUE *argv, VALUE obj)
{
- VALUE vseed;
- rb_random_t *rnd = get_rnd(obj);
+ rb_random_t *rnd = try_get_rnd(obj);
+ const rb_random_interface_t *rng = rb_rand_if(obj);
- if (rb_check_arity(argc, 0, 1) == 0) {
- rb_check_frozen(obj);
- vseed = random_seed(obj);
+ if (!rng) {
+ rb_raise(rb_eTypeError, "undefined random interface: %s",
+ RTYPEDDATA_TYPE(obj)->wrap_struct_name);
+ }
+ argc = rb_check_arity(argc, 0, 1);
+ rb_check_frozen(obj);
+ if (argc == 0) {
+ rnd->seed = rand_init_default(rng, rnd);
}
else {
- vseed = argv[0];
- rb_check_copyable(obj, vseed);
- vseed = rb_to_int(vseed);
+ rnd->seed = rand_init(rng, rnd, rb_to_int(argv[0]));
}
- rnd->seed = rand_init(&rnd->mt, vseed);
return obj;
}
@@ -324,11 +463,7 @@ fill_random_bytes_urandom(void *seed, size_t size)
# define fill_random_bytes_urandom(seed, size) -1
#endif
-#if defined HAVE_GETRANDOM
-# include <sys/random.h>
-#elif defined __linux__ && defined __NR_getrandom
-# include <linux/random.h>
-
+#if ! defined HAVE_GETRANDOM && defined __linux__ && defined __NR_getrandom
# ifndef GRND_NONBLOCK
# define GRND_NONBLOCK 0x0001 /* not defined in musl libc */
# endif
@@ -393,6 +528,8 @@ fill_random_bytes_syscall(void *seed, size_t size, int unused)
old_prov = (HCRYPTPROV)ATOMIC_PTR_CAS(perm_prov, 0, prov);
if (LIKELY(!old_prov)) { /* no other threads acquired */
if (prov != (HCRYPTPROV)INVALID_HANDLE_VALUE) {
+#undef RUBY_UNTYPED_DATA_WARNING
+#define RUBY_UNTYPED_DATA_WARNING 0
rb_gc_register_mark_object(Data_Wrap_Struct(0, 0, release_crypt, &perm_prov));
}
}
@@ -444,6 +581,7 @@ ruby_fill_random_bytes(void *seed, size_t size, int need_secure)
#define fill_random_bytes ruby_fill_random_bytes
+/* cnt must be 4 or more */
static void
fill_random_seed(uint32_t *seed, size_t cnt)
{
@@ -493,6 +631,10 @@ make_seed_value(uint32_t *ptr, size_t len)
return seed;
}
+#define with_random_seed(size, add) \
+ for (uint32_t seedbuf[(size)+(add)], loop = (fill_random_seed(seedbuf, (size)), 1); \
+ loop; explicit_bzero(seedbuf, (size)*sizeof(seedbuf[0])), loop = 0)
+
/*
* call-seq: Random.new_seed -> integer
*
@@ -505,10 +647,9 @@ static VALUE
random_seed(VALUE _)
{
VALUE v;
- uint32_t buf[DEFAULT_SEED_CNT+1];
- fill_random_seed(buf, DEFAULT_SEED_CNT);
- v = make_seed_value(buf, DEFAULT_SEED_CNT);
- explicit_bzero(buf, DEFAULT_SEED_LEN);
+ with_random_seed(DEFAULT_SEED_CNT, 1) {
+ v = make_seed_value(seedbuf, DEFAULT_SEED_CNT);
+ }
return v;
}
@@ -561,15 +702,15 @@ random_get_seed(VALUE obj)
/* :nodoc: */
static VALUE
-random_copy(VALUE obj, VALUE orig)
+rand_mt_copy(VALUE obj, VALUE orig)
{
- rb_random_t *rnd1, *rnd2;
+ rb_random_mt_t *rnd1, *rnd2;
struct MT *mt;
if (!OBJ_INIT_COPY(obj, orig)) return obj;
- rnd1 = get_rnd(obj);
- rnd2 = get_rnd(orig);
+ rnd1 = get_rnd_mt(obj);
+ rnd2 = get_rnd_mt(orig);
mt = &rnd1->mt;
*rnd1 = *rnd2;
@@ -587,9 +728,9 @@ mt_state(const struct MT *mt)
/* :nodoc: */
static VALUE
-random_state(VALUE obj)
+rand_mt_state(VALUE obj)
{
- rb_random_t *rnd = get_rnd(obj);
+ rb_random_mt_t *rnd = get_rnd_mt(obj);
return mt_state(&rnd->mt);
}
@@ -597,14 +738,14 @@ random_state(VALUE obj)
static VALUE
random_s_state(VALUE klass)
{
- return mt_state(&default_rand.mt);
+ return mt_state(&default_rand()->mt);
}
/* :nodoc: */
static VALUE
-random_left(VALUE obj)
+rand_mt_left(VALUE obj)
{
- rb_random_t *rnd = get_rnd(obj);
+ rb_random_mt_t *rnd = get_rnd_mt(obj);
return INT2FIX(rnd->mt.left);
}
@@ -612,28 +753,28 @@ random_left(VALUE obj)
static VALUE
random_s_left(VALUE klass)
{
- return INT2FIX(default_rand.mt.left);
+ return INT2FIX(default_rand()->mt.left);
}
/* :nodoc: */
static VALUE
-random_dump(VALUE obj)
+rand_mt_dump(VALUE obj)
{
- rb_random_t *rnd = get_rnd(obj);
+ rb_random_mt_t *rnd = rb_check_typeddata(obj, &random_mt_type);
VALUE dump = rb_ary_new2(3);
rb_ary_push(dump, mt_state(&rnd->mt));
rb_ary_push(dump, INT2FIX(rnd->mt.left));
- rb_ary_push(dump, rnd->seed);
+ rb_ary_push(dump, rnd->base.seed);
return dump;
}
/* :nodoc: */
static VALUE
-random_load(VALUE obj, VALUE dump)
+rand_mt_load(VALUE obj, VALUE dump)
{
- rb_random_t *rnd = get_rnd(obj);
+ rb_random_mt_t *rnd = rb_check_typeddata(obj, &random_mt_type);
struct MT *mt = &rnd->mt;
VALUE state, left = INT2FIX(1), seed = INT2FIX(0);
unsigned long x;
@@ -660,17 +801,42 @@ random_load(VALUE obj, VALUE dump)
}
mt->left = (unsigned int)x;
mt->next = mt->state + numberof(mt->state) - x + 1;
- rnd->seed = rb_to_int(seed);
+ rnd->base.seed = rb_to_int(seed);
return obj;
}
+static void
+rand_mt_init(rb_random_t *rnd, const uint32_t *buf, size_t len)
+{
+ struct MT *mt = &((rb_random_mt_t *)rnd)->mt;
+ if (len <= 1) {
+ init_genrand(mt, len ? buf[0] : 0);
+ }
+ else {
+ init_by_array(mt, buf, (int)len);
+ }
+}
+
+static unsigned int
+rand_mt_get_int32(rb_random_t *rnd)
+{
+ struct MT *mt = &((rb_random_mt_t *)rnd)->mt;
+ return genrand_int32(mt);
+}
+
+static void
+rand_mt_get_bytes(rb_random_t *rnd, void *ptr, size_t n)
+{
+ rb_rand_bytes_int32(rand_mt_get_int32, rnd, ptr, n);
+}
+
/*
* call-seq:
* srand(number = Random.new_seed) -> old_seed
*
- * Seeds the system pseudo-random number generator, Random::DEFAULT, with
- * +number+. The previous seed value is returned.
+ * Seeds the system pseudo-random number generator, with +number+.
+ * The previous seed value is returned.
*
* If +number+ is omitted, seeds the generator using a source of entropy
* provided by the operating system, if available (/dev/urandom on Unix systems
@@ -692,7 +858,7 @@ static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
VALUE seed, old;
- rb_random_t *r = &default_rand;
+ rb_random_mt_t *r = rand_mt_start(default_rand());
if (rb_check_arity(argc, 0, 1) == 0) {
seed = random_seed(obj);
@@ -700,8 +866,9 @@ rb_f_srand(int argc, VALUE *argv, VALUE obj)
else {
seed = rb_to_int(argv[0]);
}
- old = r->seed;
- r->seed = rand_init(&r->mt, seed);
+ old = r->base.seed;
+ rand_init(&random_mt_if, &r->base, seed);
+ r->base.seed = seed;
return old;
}
@@ -721,7 +888,7 @@ make_mask(unsigned long x)
}
static unsigned long
-limited_rand(struct MT *mt, unsigned long limit)
+limited_rand(const rb_random_interface_t *rng, rb_random_t *rnd, unsigned long limit)
{
/* mt must be initialized */
unsigned long val, mask;
@@ -736,7 +903,7 @@ limited_rand(struct MT *mt, unsigned long limit)
val = 0;
for (i = SIZEOF_LONG/SIZEOF_INT32-1; 0 <= i; i--) {
if ((mask >> (i * 32)) & 0xffffffff) {
- val |= (unsigned long)genrand_int32(mt) << (i * 32);
+ val |= (unsigned long)rng->get_int32(rnd) << (i * 32);
val &= mask;
if (limit < val)
goto retry;
@@ -747,13 +914,13 @@ limited_rand(struct MT *mt, unsigned long limit)
#endif
do {
- val = genrand_int32(mt) & mask;
+ val = rng->get_int32(rnd) & mask;
} while (limit < val);
return val;
}
static VALUE
-limited_big_rand(struct MT *mt, VALUE limit)
+limited_big_rand(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE limit)
{
/* mt must be initialized */
@@ -777,22 +944,19 @@ limited_big_rand(struct MT *mt, VALUE limit)
mask = 0;
boundary = 1;
for (i = len-1; 0 <= i; i--) {
- uint32_t rnd;
+ uint32_t r = 0;
uint32_t lim = lim_array[i];
mask = mask ? 0xffffffff : (uint32_t)make_mask(lim);
if (mask) {
- rnd = genrand_int32(mt) & mask;
+ r = rng->get_int32(rnd) & mask;
if (boundary) {
- if (lim < rnd)
+ if (lim < r)
goto retry;
- if (rnd < lim)
+ if (r < lim)
boundary = 0;
}
}
- else {
- rnd = 0;
- }
- rnd_array[i] = rnd;
+ rnd_array[i] = r;
}
val = rb_integer_unpack(rnd_array, len, sizeof(uint32_t), 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
@@ -810,7 +974,8 @@ limited_big_rand(struct MT *mt, VALUE limit)
unsigned long
rb_genrand_ulong_limited(unsigned long limit)
{
- return limited_rand(default_mt(), limit);
+ rb_random_mt_t *mt = default_mt();
+ return limited_rand(&random_mt_if, &mt->base, limit);
}
static VALUE
@@ -830,9 +995,9 @@ obj_random_bytes(VALUE obj, void *p, long n)
}
static unsigned int
-random_int32(rb_random_t *rnd)
+random_int32(const rb_random_interface_t *rng, rb_random_t *rnd)
{
- return genrand_int32(&rnd->mt);
+ return rng->get_int32(rnd);
}
unsigned int
@@ -844,7 +1009,7 @@ rb_random_int32(VALUE obj)
obj_random_bytes(obj, &x, sizeof(x));
return (unsigned int)x;
}
- return random_int32(rnd);
+ return random_int32(try_rand_if(obj, rnd), rnd);
}
static double
@@ -859,9 +1024,17 @@ random_real(VALUE obj, rb_random_t *rnd, int excl)
b = x[1];
}
else {
- a = random_int32(rnd);
- b = random_int32(rnd);
+ const rb_random_interface_t *rng = try_rand_if(obj, rnd);
+ if (rng->get_real) return rng->get_real(rnd, excl);
+ a = random_int32(rng, rnd);
+ b = random_int32(rng, rnd);
}
+ return rb_int_pair_to_real(a, b, excl);
+}
+
+double
+rb_int_pair_to_real(uint32_t a, uint32_t b, int excl)
+{
if (excl) {
return int_pair_to_real_exclusive(a, b);
}
@@ -885,7 +1058,7 @@ rb_random_real(VALUE obj)
}
return d;
}
- return genrand_real(&rnd->mt);
+ return random_real(obj, rnd, TRUE);
}
static inline VALUE
@@ -927,7 +1100,7 @@ random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit)
} while (limit < val);
return val;
}
- return limited_rand(&rnd->mt, limit);
+ return limited_rand(try_rand_if(obj, rnd), rnd, limit);
}
unsigned long
@@ -946,7 +1119,7 @@ rb_random_ulong_limited(VALUE obj, unsigned long limit)
}
return r;
}
- return limited_rand(&rnd->mt, limit);
+ return limited_rand(try_rand_if(obj, rnd), rnd, limit);
}
static VALUE
@@ -975,10 +1148,20 @@ random_ulong_limited_big(VALUE obj, rb_random_t *rnd, VALUE vmax)
ALLOCV_END(vtmp);
return v;
}
- return limited_big_rand(&rnd->mt, vmax);
+ return limited_big_rand(try_rand_if(obj, rnd), rnd, vmax);
}
-static VALUE genrand_bytes(rb_random_t *rnd, long n);
+static VALUE
+rand_bytes(const rb_random_interface_t *rng, rb_random_t *rnd, long n)
+{
+ VALUE bytes;
+ char *ptr;
+
+ bytes = rb_str_new(0, n);
+ ptr = RSTRING_PTR(bytes);
+ rb_rand_bytes_int32(rng->get_int32, rnd, ptr, n);
+ return bytes;
+}
/*
* call-seq: prng.bytes(size) -> string
@@ -991,20 +1174,18 @@ static VALUE genrand_bytes(rb_random_t *rnd, long n);
static VALUE
random_bytes(VALUE obj, VALUE len)
{
- return genrand_bytes(get_rnd(obj), NUM2LONG(rb_to_int(len)));
+ rb_random_t *rnd = try_get_rnd(obj);
+ return rand_bytes(rb_rand_if(obj), rnd, NUM2LONG(rb_to_int(len)));
}
-static VALUE
-genrand_bytes(rb_random_t *rnd, long n)
+void
+rb_rand_bytes_int32(rb_random_get_int32_func *get_int32,
+ rb_random_t *rnd, void *p, size_t n)
{
- VALUE bytes;
- char *ptr;
+ char *ptr = p;
unsigned int r, i;
-
- bytes = rb_str_new(0, n);
- ptr = RSTRING_PTR(bytes);
for (; n >= SIZEOF_INT32; n -= SIZEOF_INT32) {
- r = genrand_int32(&rnd->mt);
+ r = get_int32(rnd);
i = SIZEOF_INT32;
do {
*ptr++ = (char)r;
@@ -1012,13 +1193,12 @@ genrand_bytes(rb_random_t *rnd, long n)
} while (--i);
}
if (n > 0) {
- r = genrand_int32(&rnd->mt);
+ r = get_int32(rnd);
do {
*ptr++ = (char)r;
r >>= CHAR_BIT;
} while (--n);
}
- return bytes;
}
VALUE
@@ -1028,7 +1208,7 @@ rb_random_bytes(VALUE obj, long n)
if (!rnd) {
return obj_random_bytes(obj, NULL, n);
}
- return genrand_bytes(rnd, n);
+ return rand_bytes(try_rand_if(obj, rnd), rnd, n);
}
/*
@@ -1040,8 +1220,15 @@ rb_random_bytes(VALUE obj, long n)
static VALUE
random_s_bytes(VALUE obj, VALUE len)
{
- rb_random_t *rnd = rand_start(&default_rand);
- return genrand_bytes(rnd, NUM2LONG(rb_to_int(len)));
+ rb_random_t *rnd = rand_start(default_rand());
+ return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len)));
+}
+
+static VALUE
+random_s_seed(VALUE obj)
+{
+ rb_random_mt_t *rnd = rand_mt_start(default_rand());
+ return rnd->base.seed;
}
static VALUE
@@ -1143,8 +1330,8 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
long max;
vmax = v;
v = Qnil;
+ fixnum:
if (FIXNUM_P(vmax)) {
- fixnum:
if ((max = FIX2LONG(vmax) - excl) >= 0) {
unsigned long r = random_ulong_limited(obj, rnd, (unsigned long)max);
v = ULONG2NUM(r);
@@ -1241,7 +1428,7 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd);
static VALUE
random_rand(int argc, VALUE *argv, VALUE obj)
{
- VALUE v = rand_random(argc, argv, obj, get_rnd(obj));
+ VALUE v = rand_random(argc, argv, obj, try_get_rnd(obj));
check_random_number(v, argv);
return v;
}
@@ -1320,16 +1507,16 @@ rand_random_number(int argc, VALUE *argv, VALUE obj)
* prng1 == prng2 # => true
*/
static VALUE
-random_equal(VALUE self, VALUE other)
+rand_mt_equal(VALUE self, VALUE other)
{
- rb_random_t *r1, *r2;
+ rb_random_mt_t *r1, *r2;
if (rb_obj_class(self) != rb_obj_class(other)) return Qfalse;
- r1 = get_rnd(self);
- r2 = get_rnd(other);
+ r1 = get_rnd_mt(self);
+ r2 = get_rnd_mt(other);
if (memcmp(r1->mt.state, r2->mt.state, sizeof(r1->mt.state))) return Qfalse;
if ((r1->mt.next - r1->mt.state) != (r2->mt.next - r2->mt.state)) return Qfalse;
if (r1->mt.left != r2->mt.left) return Qfalse;
- return rb_equal(r1->seed, r2->seed);
+ return rb_equal(r1->base.seed, r2->base.seed);
}
/*
@@ -1367,32 +1554,30 @@ static VALUE
rb_f_rand(int argc, VALUE *argv, VALUE obj)
{
VALUE vmax;
- rb_random_t *rnd = rand_start(&default_rand);
+ rb_random_t *rnd = rand_start(default_rand());
if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) {
- VALUE v = rand_range(Qnil, rnd, vmax);
+ VALUE v = rand_range(obj, rnd, vmax);
if (v != Qfalse) return v;
vmax = rb_to_int(vmax);
if (vmax != INT2FIX(0)) {
- v = rand_int(Qnil, rnd, vmax, 0);
+ v = rand_int(obj, rnd, vmax, 0);
if (!NIL_P(v)) return v;
}
}
- return DBL2NUM(genrand_real(&rnd->mt));
+ return DBL2NUM(random_real(obj, rnd, TRUE));
}
/*
* call-seq:
* Random.rand -> float
* Random.rand(max) -> number
- *
- * Alias of Random::DEFAULT.rand.
*/
static VALUE
random_s_rand(int argc, VALUE *argv, VALUE obj)
{
- VALUE v = rand_random(argc, argv, Qnil, rand_start(&default_rand));
+ VALUE v = rand_random(argc, argv, Qnil, rand_start(default_rand()));
check_random_number(v, argv);
return v;
}
@@ -1417,33 +1602,33 @@ random_s_rand(int argc, VALUE *argv, VALUE obj)
typedef struct {
st_index_t hash;
uint8_t sip[16];
-} seed_keys_t;
+} hash_salt_t;
static union {
- seed_keys_t key;
- uint32_t u32[type_roomof(seed_keys_t, uint32_t)];
-} seed;
+ hash_salt_t key;
+ uint32_t u32[type_roomof(hash_salt_t, uint32_t)];
+} hash_salt;
static void
-init_seed(struct MT *mt)
+init_hash_salt(struct MT *mt)
{
int i;
- for (i = 0; i < numberof(seed.u32); ++i)
- seed.u32[i] = genrand_int32(mt);
+ for (i = 0; i < numberof(hash_salt.u32); ++i)
+ hash_salt.u32[i] = genrand_int32(mt);
}
NO_SANITIZE("unsigned-integer-overflow", extern st_index_t rb_hash_start(st_index_t h));
st_index_t
rb_hash_start(st_index_t h)
{
- return st_hash_start(seed.key.hash + h);
+ return st_hash_start(hash_salt.key.hash + h);
}
st_index_t
rb_memhash(const void *ptr, long len)
{
- sip_uint64_t h = sip_hash13(seed.key.sip, ptr, len);
+ sip_uint64_t h = sip_hash13(hash_salt.key.sip, ptr, len);
#ifdef HAVE_UINT64_T
return (st_index_t)h;
#else
@@ -1456,54 +1641,31 @@ rb_memhash(const void *ptr, long len)
void
Init_RandomSeedCore(void)
{
+ if (!fill_random_bytes(&hash_salt, sizeof(hash_salt), FALSE)) return;
+
/*
- Don't reuse this MT for Random::DEFAULT. Random::DEFAULT::seed shouldn't
+ If failed to fill siphash's salt with random data, expand less random
+ data with MT.
+
+ Don't reuse this MT for default_rand(). default_rand()::seed shouldn't
provide a hint that an attacker guess siphash's seed.
*/
struct MT mt;
- uint32_t initial_seed[DEFAULT_SEED_CNT];
-
- fill_random_seed(initial_seed, DEFAULT_SEED_CNT);
- init_by_array(&mt, initial_seed, DEFAULT_SEED_CNT);
-
- init_seed(&mt);
-
- explicit_bzero(initial_seed, DEFAULT_SEED_LEN);
-}
-static VALUE
-init_randomseed(struct MT *mt)
-{
- uint32_t initial[DEFAULT_SEED_CNT+1];
- VALUE seed;
-
- fill_random_seed(initial, DEFAULT_SEED_CNT);
- init_by_array(mt, initial, DEFAULT_SEED_CNT);
- seed = make_seed_value(initial, DEFAULT_SEED_CNT);
- explicit_bzero(initial, DEFAULT_SEED_LEN);
- return seed;
-}
-
-/* construct Random::DEFAULT bits */
-static VALUE
-Init_Random_default(VALUE klass)
-{
- rb_random_t *r = &default_rand;
- struct MT *mt = &r->mt;
- VALUE v = TypedData_Wrap_Struct(klass, &random_mt_type, r);
-
- rb_gc_register_mark_object(v);
- r->seed = init_randomseed(mt);
+ with_random_seed(DEFAULT_SEED_CNT, 0) {
+ init_by_array(&mt, seedbuf, DEFAULT_SEED_CNT);
+ }
- return v;
+ init_hash_salt(&mt);
+ explicit_bzero(&mt, sizeof(mt));
}
void
rb_reset_random_seed(void)
{
- rb_random_t *r = &default_rand;
+ rb_random_mt_t *r = default_rand();
uninit_genrand(&r->mt);
- r->seed = INT2FIX(0);
+ r->base.seed = INT2FIX(0);
}
/*
@@ -1519,47 +1681,57 @@ rb_reset_random_seed(void)
*
* The class method Random.rand provides the base functionality of Kernel.rand
* along with better handling of floating point values. These are both
- * interfaces to Random::DEFAULT, the Ruby system PRNG.
+ * interfaces to the Ruby system PRNG.
*
- * Random.new will create a new PRNG with a state independent of
- * Random::DEFAULT, allowing multiple generators with different seed values or
+ * Random.new will create a new PRNG with a state independent of the Ruby
+ * system PRNG, allowing multiple generators with different seed values or
* sequence positions to exist simultaneously. Random objects can be
* marshaled, allowing sequences to be saved and resumed.
*
* PRNGs are currently implemented as a modified Mersenne Twister with a period
- * of 2**19937-1.
+ * of 2**19937-1. As this algorithm is _not_ for cryptographical use, you must
+ * use SecureRandom for security purpose, instead of this PRNG.
*/
void
InitVM_Random(void)
{
+ VALUE base;
+ ID id_base = rb_intern_const("Base");
+
rb_define_global_function("srand", rb_f_srand, -1);
rb_define_global_function("rand", rb_f_rand, -1);
- rb_cRandom = rb_define_class("Random", rb_cObject);
+ base = rb_define_class_id(id_base, rb_cObject);
+ rb_undef_alloc_func(base);
+ rb_cRandom = rb_define_class("Random", base);
+ rb_const_set(rb_cRandom, id_base, base);
rb_define_alloc_func(rb_cRandom, random_alloc);
+ rb_define_method(base, "initialize", random_init, -1);
+ rb_define_method(base, "rand", random_rand, -1);
+ rb_define_method(base, "bytes", random_bytes, 1);
+ rb_define_method(base, "seed", random_get_seed, 0);
+ rb_define_method(rb_cRandom, "initialize_copy", rand_mt_copy, 1);
+ rb_define_private_method(rb_cRandom, "marshal_dump", rand_mt_dump, 0);
+ rb_define_private_method(rb_cRandom, "marshal_load", rand_mt_load, 1);
+ rb_define_private_method(rb_cRandom, "state", rand_mt_state, 0);
+ rb_define_private_method(rb_cRandom, "left", rand_mt_left, 0);
+ rb_define_method(rb_cRandom, "==", rand_mt_equal, 1);
+
+#if 0 /* for RDoc: it can't handle unnamed base class */
rb_define_method(rb_cRandom, "initialize", random_init, -1);
rb_define_method(rb_cRandom, "rand", random_rand, -1);
rb_define_method(rb_cRandom, "bytes", random_bytes, 1);
rb_define_method(rb_cRandom, "seed", random_get_seed, 0);
- rb_define_method(rb_cRandom, "initialize_copy", random_copy, 1);
- rb_define_private_method(rb_cRandom, "marshal_dump", random_dump, 0);
- rb_define_private_method(rb_cRandom, "marshal_load", random_load, 1);
- rb_define_private_method(rb_cRandom, "state", random_state, 0);
- rb_define_private_method(rb_cRandom, "left", random_left, 0);
- rb_define_method(rb_cRandom, "==", random_equal, 1);
+#endif
- {
- /* Direct access to Ruby's Pseudorandom number generator (PRNG). */
- VALUE rand_default = Init_Random_default(rb_cRandom);
- /* The default Pseudorandom number generator. Used by class
- * methods of Random. */
- rb_define_const(rb_cRandom, "DEFAULT", rand_default);
- }
+ rb_define_const(rb_cRandom, "DEFAULT", rb_cRandom);
+ rb_deprecate_constant(rb_cRandom, "DEFAULT");
rb_define_singleton_method(rb_cRandom, "srand", rb_f_srand, -1);
rb_define_singleton_method(rb_cRandom, "rand", random_s_rand, -1);
rb_define_singleton_method(rb_cRandom, "bytes", random_s_bytes, 1);
+ rb_define_singleton_method(rb_cRandom, "seed", random_s_seed, 0);
rb_define_singleton_method(rb_cRandom, "new_seed", random_seed, 0);
rb_define_singleton_method(rb_cRandom, "urandom", random_raw_seed, 1);
rb_define_private_method(CLASS_OF(rb_cRandom), "state", random_s_state, 0);
@@ -1568,11 +1740,13 @@ InitVM_Random(void)
{
/* Format raw random number as Random does */
VALUE m = rb_define_module_under(rb_cRandom, "Formatter");
- rb_include_module(rb_cRandom, m);
- rb_extend_object(rb_cRandom, m);
+ rb_include_module(base, m);
+ rb_extend_object(base, m);
rb_define_method(m, "random_number", rand_random_number, -1);
rb_define_method(m, "rand", rand_random_number, -1);
}
+
+ default_rand_key = rb_ractor_local_storage_ptr_newkey(&default_rand_key_storage_type);
}
#undef rb_intern
diff --git a/range.c b/range.c
index 2deb495712..2939ef3798 100644
--- a/range.c
+++ b/range.c
@@ -9,14 +9,24 @@
**********************************************************************/
-#include "internal.h"
-#include "id.h"
+#include "ruby/internal/config.h"
+
#include <assert.h>
+#include <math.h>
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
-#include <math.h>
+
+#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/compar.h"
+#include "internal/enum.h"
+#include "internal/enumerator.h"
+#include "internal/error.h"
+#include "internal/numeric.h"
+#include "internal/range.h"
VALUE rb_cRange;
static ID id_beg, id_end, id_excl;
@@ -48,6 +58,10 @@ range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end)
RANGE_SET_EXCL(range, exclude_end);
RANGE_SET_BEG(range, beg);
RANGE_SET_END(range, end);
+
+ if (CLASS_OF(range) == rb_cRange) {
+ rb_obj_freeze(range);
+ }
}
VALUE
@@ -310,6 +324,8 @@ linear_object_p(VALUE obj)
case T_FLOAT:
case T_BIGNUM:
return TRUE;
+ default:
+ break;
}
if (rb_obj_is_kind_of(obj, rb_cNumeric)) return TRUE;
if (rb_obj_is_kind_of(obj, rb_cTime)) return TRUE;
@@ -399,6 +415,13 @@ range_step(int argc, VALUE *argv, VALUE range)
step = (!rb_check_arity(argc, 0, 1) ? INT2FIX(1) : argv[0]);
if (!rb_block_given_p()) {
+ if (!rb_obj_is_kind_of(step, rb_cNumeric)) {
+ step = rb_to_int(step);
+ }
+ if (rb_equal(step, INT2FIX(0))) {
+ rb_raise(rb_eArgError, "step can't be 0");
+ }
+
const VALUE b_num_p = rb_obj_is_kind_of(b, rb_cNumeric);
const VALUE e_num_p = rb_obj_is_kind_of(e, rb_cNumeric);
if ((b_num_p && (NIL_P(e) || e_num_p)) || (NIL_P(b) && e_num_p)) {
@@ -819,6 +842,38 @@ range_enum_size(VALUE range, VALUE args, VALUE eobj)
return range_size(range);
}
+RBIMPL_ATTR_NORETURN()
+static void
+range_each_bignum_endless(VALUE beg)
+{
+ for (;; beg = rb_big_plus(beg, INT2FIX(1))) {
+ rb_yield(beg);
+ }
+ UNREACHABLE;
+}
+
+RBIMPL_ATTR_NORETURN()
+static void
+range_each_fixnum_endless(VALUE beg)
+{
+ for (long i = FIX2LONG(beg); FIXABLE(i); i++) {
+ rb_yield(LONG2FIX(i));
+ }
+
+ range_each_bignum_endless(LONG2NUM(RUBY_FIXNUM_MAX + 1));
+ UNREACHABLE;
+}
+
+static VALUE
+range_each_fixnum_loop(VALUE beg, VALUE end, VALUE range)
+{
+ long lim = FIX2LONG(end) + !EXCL(range);
+ for (long i = FIX2LONG(beg); i < lim; i++) {
+ rb_yield(LONG2FIX(i));
+ }
+ return range;
+}
+
/*
* call-seq:
* rng.each {| i | block } -> rng
@@ -844,7 +899,7 @@ static VALUE
range_each(VALUE range)
{
VALUE beg, end;
- long i, lim;
+ long i;
RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size);
@@ -852,24 +907,10 @@ range_each(VALUE range)
end = RANGE_END(range);
if (FIXNUM_P(beg) && NIL_P(end)) {
- fixnum_endless:
- i = FIX2LONG(beg);
- while (FIXABLE(i)) {
- rb_yield(LONG2FIX(i++));
- }
- beg = LONG2NUM(i);
- bignum_endless:
- for (;; beg = rb_big_plus(beg, INT2FIX(1)))
- rb_yield(beg);
+ range_each_fixnum_endless(beg);
}
else if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */
- fixnum_loop:
- lim = FIX2LONG(end);
- if (!EXCL(range))
- lim += 1;
- for (i = FIX2LONG(beg); i < lim; i++) {
- rb_yield(LONG2FIX(i));
- }
+ return range_each_fixnum_loop(beg, end, range);
}
else if (RB_INTEGER_TYPE_P(beg) && (NIL_P(end) || RB_INTEGER_TYPE_P(end))) {
if (SPECIAL_CONST_P(end) || RBIGNUM_POSITIVE_P(end)) { /* end >= FIXNUM_MIN */
@@ -878,11 +919,11 @@ range_each(VALUE range)
do {
rb_yield(beg);
} while (!FIXNUM_P(beg = rb_big_plus(beg, INT2FIX(1))));
- if (NIL_P(end)) goto fixnum_endless;
- if (FIXNUM_P(end)) goto fixnum_loop;
+ if (NIL_P(end)) range_each_fixnum_endless(beg);
+ if (FIXNUM_P(end)) return range_each_fixnum_loop(beg, end, range);
}
else {
- if (NIL_P(end)) goto bignum_endless;
+ if (NIL_P(end)) range_each_bignum_endless(beg);
if (FIXNUM_P(end)) return range;
}
}
@@ -993,7 +1034,7 @@ first_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, cbarg))
}
rb_ary_push(ary[1], i);
n--;
- ary[0] = INT2NUM(n);
+ ary[0] = LONG2NUM(n);
return Qnil;
}
@@ -1170,14 +1211,34 @@ range_min(int argc, VALUE *argv, VALUE range)
* rng.max(n) -> obj
* rng.max(n) {| a,b | block } -> obj
*
- * Returns the maximum value in the range. Returns +nil+ if the begin
- * value of the range larger than the end value. Returns +nil+ if
- * the begin value of an exclusive range is equal to the end value.
- *
- * Can be given an optional block to override the default comparison
- * method <code>a <=> b</code>.
- *
- * (10..20).max #=> 20
+ * Returns the maximum value in the range, or an array of maximum
+ * values in the range if given an \Integer argument.
+ *
+ * For inclusive ranges with an end, the maximum value of the range
+ * is the same as the end of the range.
+ *
+ * If an argument or block is given, or +self+ is an exclusive,
+ * non-numeric range, calls Enumerable#max (via +super+) with the
+ * argument and/or block to get the maximum values, unless +self+ is
+ * a beginless range, in which case it raises a RangeError.
+ *
+ * If +self+ is an exclusive, integer range (both start and end of the
+ * range are integers), and no arguments or block are provided, returns
+ * last value in the range (1 before the end). Otherwise, if +self+ is
+ * an exclusive, numeric range, raises a TypeError.
+ *
+ * Returns +nil+ if the begin value of the range larger than the
+ * end value. Returns +nil+ if the begin value of an exclusive
+ * range is equal to the end value. Raises a RangeError if called on
+ * an endless range.
+ *
+ * Examples:
+ * (10..20).max #=> 20
+ * (10..20).max(2) #=> [20, 19]
+ * (10...20).max #=> 19
+ * (10...20).max(2) #=> [19, 18]
+ * (10...20).max{|x, y| -x <=> -y } #=> 10
+ * (10...20).max(2){|x, y| -x <=> -y } #=> [10, 11]
*/
static VALUE
@@ -1190,16 +1251,17 @@ range_max(int argc, VALUE *argv, VALUE range)
rb_raise(rb_eRangeError, "cannot get the maximum of endless range");
}
+ VALUE b = RANGE_BEG(range);
+
if (rb_block_given_p() || (EXCL(range) && !nm) || argc) {
- if (NIL_P(RANGE_BEG(range))) {
+ if (NIL_P(b)) {
rb_raise(rb_eRangeError, "cannot get the maximum of beginless range with custom comparison method");
}
return rb_call_super(argc, argv);
}
else {
struct cmp_opt_data cmp_opt = { 0, 0 };
- VALUE b = RANGE_BEG(range);
- int c = OPTIMIZED_CMP(b, e, cmp_opt);
+ int c = NIL_P(b) ? -1 : OPTIMIZED_CMP(b, e, cmp_opt);
if (c > 0)
return Qnil;
@@ -1274,51 +1336,81 @@ rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
return (int)Qtrue;
}
+/* Extract the components of a Range.
+ *
+ * You can use +err+ to control the behavior of out-of-range and exception.
+ *
+ * When +err+ is 0 or 2, if the begin offset is greater than +len+,
+ * it is out-of-range. The +RangeError+ is raised only if +err+ is 2,
+ * in this case. If +err+ is 0, +Qnil+ will be returned.
+ *
+ * When +err+ is 1, the begin and end offsets won't be adjusted even if they
+ * are greater than +len+. It allows +rb_ary_aset+ extends arrays.
+ *
+ * If the begin component of the given range is negative and is too-large
+ * abstract value, the +RangeError+ is raised only +err+ is 1 or 2.
+ *
+ * The case of <code>err = 0</code> is used in item accessing methods such as
+ * +rb_ary_aref+, +rb_ary_slice_bang+, and +rb_str_aref+.
+ *
+ * The case of <code>err = 1</code> is used in Array's methods such as
+ * +rb_ary_aset+ and +rb_ary_fill+.
+ *
+ * The case of <code>err = 2</code> is used in +rb_str_aset+.
+ */
VALUE
-rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
+rb_range_component_beg_len(VALUE b, VALUE e, int excl,
+ long *begp, long *lenp, long len, int err)
{
- long beg, end, origbeg, origend;
- VALUE b, e;
- int excl;
+ long beg, end;
- if (!rb_range_values(range, &b, &e, &excl))
- return Qfalse;
beg = NIL_P(b) ? 0 : NUM2LONG(b);
end = NIL_P(e) ? -1 : NUM2LONG(e);
if (NIL_P(e)) excl = 0;
- origbeg = beg;
- origend = end;
if (beg < 0) {
- beg += len;
- if (beg < 0)
- goto out_of_range;
+ beg += len;
+ if (beg < 0)
+ goto out_of_range;
}
if (end < 0)
- end += len;
+ end += len;
if (!excl)
- end++; /* include end point */
+ end++; /* include end point */
if (err == 0 || err == 2) {
- if (beg > len)
- goto out_of_range;
- if (end > len)
- end = len;
+ if (beg > len)
+ goto out_of_range;
+ if (end > len)
+ end = len;
}
len = end - beg;
if (len < 0)
- len = 0;
+ len = 0;
*begp = beg;
*lenp = len;
return Qtrue;
out_of_range:
- if (err) {
- rb_raise(rb_eRangeError, "%ld..%s%ld out of range",
- origbeg, excl ? "." : "", origend);
- }
return Qnil;
}
+VALUE
+rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
+{
+ VALUE b, e;
+ int excl;
+
+ if (!rb_range_values(range, &b, &e, &excl))
+ return Qfalse;
+
+ VALUE res = rb_range_component_beg_len(b, e, excl, begp, lenp, len, err);
+ if (NIL_P(res) && err) {
+ rb_raise(rb_eRangeError, "%+"PRIsVALUE" out of range", range);
+ }
+
+ return res;
+}
+
/*
* call-seq:
* rng.to_s -> string
@@ -1549,7 +1641,7 @@ r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val)
if (!NIL_P(end) && NIL_P(val_end)) return FALSE;
if (!NIL_P(beg) && NIL_P(val_beg)) return FALSE;
- if (!NIL_P(val_beg) && !NIL_P(val_end) && r_less(val_beg, val_end) > -EXCL(val)) return FALSE;
+ if (!NIL_P(val_beg) && !NIL_P(val_end) && r_less(val_beg, val_end) > (EXCL(val) ? -1 : 0)) return FALSE;
if (!NIL_P(val_beg) && !r_cover_p(range, beg, end, val_beg)) return FALSE;
cmp_end = r_less(end, val_end);
@@ -1564,7 +1656,7 @@ r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val)
return TRUE;
}
- val_max = rb_rescue2(r_call_max, val, NULL, Qnil, rb_eTypeError, (VALUE)0);
+ val_max = rb_rescue2(r_call_max, val, 0, Qnil, rb_eTypeError, (VALUE)0);
if (val_max == Qnil) return FALSE;
return r_less(end, val_max) >= 0;
@@ -1584,10 +1676,7 @@ r_cover_p(VALUE range, VALUE beg, VALUE end, VALUE val)
static VALUE
range_dumper(VALUE range)
{
- VALUE v;
- NEWOBJ_OF(m, struct RObject, rb_cObject, T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 1));
-
- v = (VALUE)m;
+ VALUE v = rb_obj_alloc(rb_cObject);
rb_ivar_set(v, id_excl, RANGE_EXCL(range));
rb_ivar_set(v, id_beg, RANGE_BEG(range));
@@ -1754,12 +1843,9 @@ range_count(int argc, VALUE *argv, VALUE range)
void
Init_Range(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
- id_beg = rb_intern("begin");
- id_end = rb_intern("end");
- id_excl = rb_intern("excl");
+ id_beg = rb_intern_const("begin");
+ id_end = rb_intern_const("end");
+ id_excl = rb_intern_const("excl");
rb_cRange = rb_struct_define_without_accessor(
"Range", rb_cObject, range_alloc,
diff --git a/rational.c b/rational.c
index 9f6964f0aa..d621773838 100644
--- a/rational.c
+++ b/rational.c
@@ -5,30 +5,39 @@
which is written in ruby.
*/
-#include "internal.h"
-#include "id.h"
-#include <math.h>
+#include "ruby/internal/config.h"
+
+#include <ctype.h>
#include <float.h>
+#include <math.h>
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
-#define NDEBUG
-#include "ruby_assert.h"
-
#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
#define USE_GMP
#include <gmp.h>
#endif
+#undef NDEBUG
+#define NDEBUG
+#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/complex.h"
+#include "internal/gc.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/rational.h"
+#include "ruby_assert.h"
+
#define ZERO INT2FIX(0)
#define ONE INT2FIX(1)
#define TWO INT2FIX(2)
#define GMP_GCD_DIGITS 1
-#define INT_POSITIVE_P(x) (FIXNUM_P(x) ? FIXNUM_POSITIVE_P(x) : BIGNUM_POSITIVE_P(x))
#define INT_ZERO_P(x) (FIXNUM_P(x) ? FIXNUM_ZERO_P(x) : rb_bigzero_p(x))
VALUE rb_cRational;
@@ -44,6 +53,7 @@ static ID id_abs, id_integer_p,
#define f_to_s rb_obj_as_string
static VALUE nurat_to_f(VALUE self);
+static VALUE float_to_r(VALUE self);
inline static VALUE
f_add(VALUE x, VALUE y)
@@ -52,6 +62,8 @@ f_add(VALUE x, VALUE y)
return x;
if (FIXNUM_ZERO_P(x))
return y;
+ if (RB_INTEGER_TYPE_P(x))
+ return rb_int_plus(x, y);
return rb_funcall(x, '+', 1, y);
}
@@ -70,6 +82,10 @@ f_lt_p(VALUE x, VALUE y)
{
if (FIXNUM_P(x) && FIXNUM_P(y))
return (SIGNED_VALUE)x < (SIGNED_VALUE)y;
+ if (RB_INTEGER_TYPE_P(x)) {
+ VALUE r = rb_int_cmp(x, y);
+ if (!NIL_P(r)) return rb_int_negative_p(r);
+ }
return RTEST(rb_funcall(x, '<', 1, y));
}
@@ -129,11 +145,13 @@ f_to_i(VALUE x)
return rb_funcall(x, id_to_i, 0);
}
-inline static VALUE
+inline static int
f_eqeq_p(VALUE x, VALUE y)
{
if (FIXNUM_P(x) && FIXNUM_P(y))
return x == y;
+ if (RB_INTEGER_TYPE_P(x))
+ return RTEST(rb_int_equal(x, y));
return (int)rb_equal(x, y);
}
@@ -394,9 +412,9 @@ nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
{
NEWOBJ_OF(obj, struct RRational, klass, T_RATIONAL | (RGENGC_WB_PROTECTED_RATIONAL ? FL_WB_PROTECTED : 0));
- RRATIONAL_SET_NUM(obj, num);
- RRATIONAL_SET_DEN(obj, den);
- OBJ_FREEZE_RAW(obj);
+ RATIONAL_SET_NUM((VALUE)obj, num);
+ RATIONAL_SET_DEN((VALUE)obj, den);
+ OBJ_FREEZE_RAW((VALUE)obj);
return (VALUE)obj;
}
@@ -413,18 +431,6 @@ f_rational_new_bang1(VALUE klass, VALUE x)
return nurat_s_new_internal(klass, x, ONE);
}
-#ifdef CANONICALIZATION_FOR_MATHN
-static int canonicalization = 0;
-
-RUBY_FUNC_EXPORTED void
-nurat_canonicalization(int f)
-{
- canonicalization = f;
-}
-#else
-# define canonicalization 0
-#endif
-
inline static void
nurat_int_check(VALUE num)
{
@@ -473,8 +479,6 @@ nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den)
nurat_canonicalize(&num, &den);
nurat_reduce(&num, &den);
- if (canonicalization && f_one_p(den))
- return num;
return nurat_s_new_internal(klass, num, den);
}
@@ -483,30 +487,9 @@ nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den)
{
nurat_canonicalize(&num, &den);
- if (canonicalization && f_one_p(den))
- return num;
return nurat_s_new_internal(klass, num, den);
}
-static VALUE
-nurat_s_new(int argc, VALUE *argv, VALUE klass)
-{
- VALUE num, den;
-
- switch (rb_scan_args(argc, argv, "11", &num, &den)) {
- case 1:
- num = nurat_int_value(num);
- den = ONE;
- break;
- default:
- num = nurat_int_value(num);
- den = nurat_int_value(den);
- break;
- }
-
- return nurat_s_canonicalize_internal(klass, num, den);
-}
-
inline static VALUE
f_rational_new2(VALUE klass, VALUE x, VALUE y)
{
@@ -976,15 +959,6 @@ nurat_fdiv(VALUE self, VALUE other)
return rb_funcall(div, idTo_f, 0);
}
-inline static VALUE
-f_odd_p(VALUE integer)
-{
- if (rb_funcall(integer, '%', 1, INT2FIX(2)) != INT2FIX(0)) {
- return Qtrue;
- }
- return Qfalse;
-}
-
/*
* call-seq:
* rat ** numeric -> numeric
@@ -1019,7 +993,7 @@ rb_rational_pow(VALUE self, VALUE other)
return f_rational_new_bang1(CLASS_OF(self), ONE);
}
else if (f_minus_one_p(dat->num) && RB_INTEGER_TYPE_P(other)) {
- return f_rational_new_bang1(CLASS_OF(self), INT2FIX(f_odd_p(other) ? -1 : 1));
+ return f_rational_new_bang1(CLASS_OF(self), INT2FIX(rb_int_odd_p(other) ? -1 : 1));
}
else if (INT_ZERO_P(dat->num)) {
if (rb_num_negative_p(other)) {
@@ -1096,21 +1070,19 @@ rb_rational_pow(VALUE self, VALUE other)
VALUE
rb_rational_cmp(VALUE self, VALUE other)
{
- if (RB_INTEGER_TYPE_P(other)) {
+ switch (TYPE(other)) {
+ case T_FIXNUM:
+ case T_BIGNUM:
{
get_dat1(self);
if (dat->den == LONG2FIX(1))
return rb_int_cmp(dat->num, other); /* c14n */
other = f_rational_new_bang1(CLASS_OF(self), other);
- goto other_is_rational;
+ /* FALLTHROUGH */
}
- }
- else if (RB_FLOAT_TYPE_P(other)) {
- return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other));
- }
- else if (RB_TYPE_P(other, T_RATIONAL)) {
- other_is_rational:
+
+ case T_RATIONAL:
{
VALUE num1, num2;
@@ -1127,8 +1099,11 @@ rb_rational_cmp(VALUE self, VALUE other)
}
return rb_int_cmp(rb_int_minus(num1, num2), ZERO);
}
- }
- else {
+
+ case T_FLOAT:
+ return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other));
+
+ default:
return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
}
}
@@ -1200,11 +1175,17 @@ nurat_coerce(VALUE self, VALUE other)
return rb_assoc_new(other, self);
}
else if (RB_TYPE_P(other, T_COMPLEX)) {
- if (k_exact_zero_p(RCOMPLEX(other)->imag))
- return rb_assoc_new(f_rational_new_bang1
- (CLASS_OF(self), RCOMPLEX(other)->real), self);
- else
+ if (!k_exact_zero_p(RCOMPLEX(other)->imag))
return rb_assoc_new(other, rb_Complex(self, INT2FIX(0)));
+ other = RCOMPLEX(other)->real;
+ if (RB_FLOAT_TYPE_P(other)) {
+ other = float_to_r(other);
+ RBASIC_SET_CLASS(other, CLASS_OF(self));
+ }
+ else {
+ other = f_rational_new_bang1(CLASS_OF(self), other);
+ }
+ return rb_assoc_new(other, self);
}
rb_raise(rb_eTypeError, "%s can't be coerced into %s",
@@ -1735,27 +1716,36 @@ static VALUE
nurat_rationalize(int argc, VALUE *argv, VALUE self)
{
VALUE e, a, b, p, q;
+ VALUE rat = self;
+ get_dat1(self);
if (rb_check_arity(argc, 0, 1) == 0)
return self;
- if (nurat_negative_p(self))
- return rb_rational_uminus(nurat_rationalize(argc, argv, rb_rational_uminus(self)));
-
e = f_abs(argv[0]);
- a = f_sub(self, e);
- b = f_add(self, e);
+
+ if (INT_NEGATIVE_P(dat->num)) {
+ rat = f_rational_new2(RBASIC_CLASS(self), rb_int_uminus(dat->num), dat->den);
+ }
+
+ a = FIXNUM_ZERO_P(e) ? rat : rb_rational_minus(rat, e);
+ b = FIXNUM_ZERO_P(e) ? rat : rb_rational_plus(rat, e);
if (f_eqeq_p(a, b))
return self;
nurat_rationalize_internal(a, b, &p, &q);
+ if (rat != self) {
+ RATIONAL_SET_NUM(rat, rb_int_uminus(p));
+ RATIONAL_SET_DEN(rat, q);
+ return rat;
+ }
return f_rational_new2(CLASS_OF(self), p, q);
}
/* :nodoc: */
-static VALUE
-nurat_hash(VALUE self)
+st_index_t
+rb_rational_hash(VALUE self)
{
st_index_t v, h[2];
VALUE n;
@@ -1766,9 +1756,16 @@ nurat_hash(VALUE self)
n = rb_hash(dat->den);
h[1] = NUM2LONG(n);
v = rb_memhash(h, sizeof(h));
- return ST2FIX(v);
+ return v;
+}
+
+static VALUE
+nurat_hash(VALUE self)
+{
+ return ST2FIX(rb_rational_hash(self));
}
+
static VALUE
f_format(VALUE self, VALUE (*func)(VALUE))
{
@@ -1839,8 +1836,8 @@ nurat_loader(VALUE self, VALUE a)
nurat_int_check(num);
nurat_int_check(den);
nurat_canonicalize(&num, &den);
- RRATIONAL_SET_NUM(dat, num);
- RRATIONAL_SET_DEN(dat, den);
+ RATIONAL_SET_NUM((VALUE)dat, num);
+ RATIONAL_SET_DEN((VALUE)dat, den);
OBJ_FREEZE_RAW(self);
return self;
@@ -1950,6 +1947,14 @@ rb_gcdlcm(VALUE self, VALUE other)
VALUE
rb_rational_raw(VALUE x, VALUE y)
{
+ if (! RB_INTEGER_TYPE_P(x))
+ x = rb_to_int(x);
+ if (! RB_INTEGER_TYPE_P(y))
+ y = rb_to_int(y);
+ if (INT_NEGATIVE_P(y)) {
+ x = rb_int_uminus(x);
+ y = rb_int_uminus(y);
+ }
return nurat_s_new_internal(rb_cRational, x, y);
}
@@ -2033,12 +2038,7 @@ rb_numeric_quo(VALUE x, VALUE y)
return rb_funcallv(x, idFdiv, 1, &y);
}
- if (canonicalization) {
- x = rb_rational_raw1(x);
- }
- else {
- x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
- }
+ x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
return rb_rational_div(x, y);
}
@@ -2076,7 +2076,6 @@ integer_denominator(VALUE self)
return INT2FIX(1);
}
-static VALUE float_to_r(VALUE self);
/*
* call-seq:
* flo.numerator -> integer
@@ -2097,9 +2096,6 @@ rb_float_numerator(VALUE self)
if (isinf(d) || isnan(d))
return self;
r = float_to_r(self);
- if (canonicalization && k_integer_p(r)) {
- return r;
- }
return nurat_numerator(r);
}
@@ -2120,9 +2116,6 @@ rb_float_denominator(VALUE self)
if (isinf(d) || isnan(d))
return INT2FIX(1);
r = float_to_r(self);
- if (canonicalization && k_integer_p(r)) {
- return ONE;
- }
return nurat_denominator(r);
}
@@ -2253,7 +2246,7 @@ rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
VALUE
rb_flt_rationalize(VALUE flt)
{
- VALUE a, b, f, p, q;
+ VALUE a, b, f, p, q, den;
int n;
float_decode_internal(flt, &f, &n);
@@ -2261,7 +2254,7 @@ rb_flt_rationalize(VALUE flt)
return rb_rational_new1(rb_int_lshift(f, INT2FIX(n)));
{
- VALUE radix_times_f, den;
+ VALUE radix_times_f;
radix_times_f = rb_int_mul(INT2FIX(FLT_RADIX), f);
#if FLT_RADIX == 2 && 0
@@ -2270,13 +2263,15 @@ rb_flt_rationalize(VALUE flt)
den = rb_int_positive_pow(FLT_RADIX, 1-n);
#endif
- a = rb_rational_new2(rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
- b = rb_rational_new2(rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
+ a = rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1));
+ b = rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1));
}
- if (nurat_eqeq_p(a, b))
+ if (f_eqeq_p(a, b))
return float_to_r(flt);
+ a = rb_rational_new2(a, den);
+ b = rb_rational_new2(b, den);
nurat_rationalize_internal(a, b, &p, &q);
return rb_rational_new2(p, q);
}
@@ -2299,20 +2294,20 @@ static VALUE
float_rationalize(int argc, VALUE *argv, VALUE self)
{
double d = RFLOAT_VALUE(self);
-
- if (d < 0.0)
- return rb_rational_uminus(float_rationalize(argc, argv, DBL2NUM(-d)));
+ VALUE rat;
+ int neg = d < 0.0;
+ if (neg) self = DBL2NUM(-d);
if (rb_check_arity(argc, 0, 1)) {
- return rb_flt_rationalize_with_prec(self, argv[0]);
+ rat = rb_flt_rationalize_with_prec(self, argv[0]);
}
else {
- return rb_flt_rationalize(self);
+ rat = rb_flt_rationalize(self);
}
+ if (neg) RATIONAL_SET_NUM(rat, rb_int_uminus(RRATIONAL(rat)->num));
+ return rat;
}
-#include <ctype.h>
-
inline static int
issign(int c)
{
@@ -2428,7 +2423,7 @@ parse_rat(const char *s, const char *const e, int strict, int raise)
if (!read_num(&s, e, &num, &nexp)) {
if (strict) return Qnil;
- return canonicalization ? ZERO : nurat_s_alloc(rb_cRational);
+ return nurat_s_alloc(rb_cRational);
}
den = ONE;
if (s < e && *s == '/') {
@@ -2456,24 +2451,27 @@ parse_rat(const char *s, const char *const e, int strict, int raise)
if (nexp != ZERO) {
if (INT_NEGATIVE_P(nexp)) {
VALUE mul;
- if (!FIXNUM_P(nexp)) {
- overflow:
- return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
+ if (FIXNUM_P(nexp)) {
+ mul = f_expt10(LONG2NUM(-FIX2LONG(nexp)));
+ if (! RB_FLOAT_TYPE_P(mul)) {
+ num = rb_int_mul(num, mul);
+ goto reduce;
+ }
}
- mul = f_expt10(LONG2NUM(-FIX2LONG(nexp)));
- if (RB_FLOAT_TYPE_P(mul)) goto overflow;
- num = rb_int_mul(num, mul);
+ return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
}
else {
VALUE div;
- if (!FIXNUM_P(nexp)) {
- underflow:
- return sign == '-' ? DBL2NUM(-0.0) : DBL2NUM(+0.0);
+ if (FIXNUM_P(nexp)) {
+ div = f_expt10(nexp);
+ if (! RB_FLOAT_TYPE_P(div)) {
+ den = rb_int_mul(den, div);
+ goto reduce;
+ }
}
- div = f_expt10(nexp);
- if (RB_FLOAT_TYPE_P(div)) goto underflow;
- den = rb_int_mul(den, div);
+ return sign == '-' ? DBL2NUM(-0.0) : DBL2NUM(+0.0);
}
+ reduce:
nurat_reduce(&num, &den);
}
@@ -2481,9 +2479,7 @@ parse_rat(const char *s, const char *const e, int strict, int raise)
num = negate_num(num);
}
- if (!canonicalization || den != ONE)
- num = rb_rational_raw(num, den);
- return num;
+ return rb_rational_raw(num, den);
}
static VALUE
@@ -2573,6 +2569,8 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
VALUE a1 = numv, a2 = denv;
int state;
+ assert(a1 != Qundef);
+
if (NIL_P(a1) || NIL_P(a2)) {
if (!raise) return Qnil;
rb_raise(rb_eTypeError, "can't convert nil into Rational");
@@ -2588,21 +2586,47 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
a2 = RCOMPLEX(a2)->real;
}
- if (RB_FLOAT_TYPE_P(a1)) {
+ if (RB_INTEGER_TYPE_P(a1)) {
+ // nothing to do
+ }
+ else if (RB_FLOAT_TYPE_P(a1)) {
a1 = float_to_r(a1);
}
+ else if (RB_TYPE_P(a1, T_RATIONAL)) {
+ // nothing to do
+ }
else if (RB_TYPE_P(a1, T_STRING)) {
a1 = string_to_r_strict(a1, raise);
if (!raise && NIL_P(a1)) return Qnil;
}
+ else if (!rb_respond_to(a1, idTo_r)) {
+ VALUE tmp = rb_protect(rb_check_to_int, a1, NULL);
+ rb_set_errinfo(Qnil);
+ if (!NIL_P(tmp)) {
+ a1 = tmp;
+ }
+ }
- if (RB_FLOAT_TYPE_P(a2)) {
+ if (RB_INTEGER_TYPE_P(a2)) {
+ // nothing to do
+ }
+ else if (RB_FLOAT_TYPE_P(a2)) {
a2 = float_to_r(a2);
}
+ else if (RB_TYPE_P(a2, T_RATIONAL)) {
+ // nothing to do
+ }
else if (RB_TYPE_P(a2, T_STRING)) {
a2 = string_to_r_strict(a2, raise);
if (!raise && NIL_P(a2)) return Qnil;
}
+ else if (a2 != Qundef && !rb_respond_to(a2, idTo_r)) {
+ VALUE tmp = rb_protect(rb_check_to_int, a2, NULL);
+ rb_set_errinfo(Qnil);
+ if (!NIL_P(tmp)) {
+ a2 = tmp;
+ }
+ }
if (RB_TYPE_P(a1, T_RATIONAL)) {
if (a2 == Qundef || (k_exact_one_p(a2)))
@@ -2610,7 +2634,7 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
}
if (a2 == Qundef) {
- if (!k_integer_p(a1)) {
+ if (!RB_INTEGER_TYPE_P(a1)) {
if (!raise) {
VALUE result = rb_protect(to_rational, a1, NULL);
rb_set_errinfo(Qnil);
@@ -2645,25 +2669,32 @@ nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
}
}
if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
- (!f_integer_p(a1) || !f_integer_p(a2)))
+ (!f_integer_p(a1) || !f_integer_p(a2))) {
+ VALUE tmp = rb_protect(to_rational, a1, &state);
+ if (!state) {
+ a1 = tmp;
+ }
+ else {
+ rb_set_errinfo(Qnil);
+ }
return f_div(a1, a2);
+ }
}
- {
- int argc;
- VALUE argv2[2];
- argv2[0] = a1;
- if (a2 == Qundef) {
- argv2[1] = Qnil;
- argc = 1;
- }
- else {
- if (!k_integer_p(a2) && !raise) return Qnil;
- argv2[1] = a2;
- argc = 2;
- }
- return nurat_s_new(argc, argv2, klass);
+ a1 = nurat_int_value(a1);
+
+ if (a2 == Qundef) {
+ a2 = ONE;
}
+ else if (!k_integer_p(a2) && !raise) {
+ return Qnil;
+ }
+ else {
+ a2 = nurat_int_value(a2);
+ }
+
+
+ return nurat_s_canonicalize_internal(klass, a1, a2);
}
static VALUE
@@ -2724,13 +2755,10 @@ void
Init_Rational(void)
{
VALUE compat;
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
- id_abs = rb_intern("abs");
- id_integer_p = rb_intern("integer?");
- id_i_num = rb_intern("@numerator");
- id_i_den = rb_intern("@denominator");
+ id_abs = rb_intern_const("abs");
+ id_integer_p = rb_intern_const("integer?");
+ id_i_num = rb_intern_const("@numerator");
+ id_i_den = rb_intern_const("@denominator");
rb_cRational = rb_define_class("Rational", rb_cNumeric);
diff --git a/re.c b/re.c
index 718a66b031..5b6f129963 100644
--- a/re.c
+++ b/re.c
@@ -9,13 +9,21 @@
**********************************************************************/
+#include "ruby/internal/config.h"
+
+#include <ctype.h>
+
+#include "encindex.h"
+#include "internal.h"
+#include "internal/hash.h"
+#include "internal/imemo.h"
+#include "internal/re.h"
+#include "internal/string.h"
+#include "internal/variable.h"
+#include "regint.h"
#include "ruby/encoding.h"
#include "ruby/re.h"
#include "ruby/util.h"
-#include "internal.h"
-#include "regint.h"
-#include "encindex.h"
-#include <ctype.h>
VALUE rb_eRegexpError;
@@ -304,8 +312,10 @@ char_to_option(int c)
return val;
}
+enum { OPTBUF_SIZE = 4 };
+
static char *
-option_to_str(char str[4], int options)
+option_to_str(char str[OPTBUF_SIZE], int options)
{
char *p = str;
if (options & ONIG_OPTION_MULTILINE) *p++ = 'm';
@@ -455,7 +465,7 @@ rb_reg_desc(const char *s, long len, VALUE re)
rb_reg_expr_str(str, s, len, enc, resenc, '/');
rb_str_buf_cat2(str, "/");
if (re) {
- char opts[4];
+ char opts[OPTBUF_SIZE];
rb_reg_check(re);
if (*option_to_str(opts, RREGEXP_PTR(re)->options))
rb_str_buf_cat2(str, opts);
@@ -547,7 +557,7 @@ rb_reg_str_with_term(VALUE re, int term)
long len;
const UChar* ptr;
VALUE str = rb_str_buf_new2("(?");
- char optbuf[5];
+ char optbuf[OPTBUF_SIZE + 1]; /* for '-' */
rb_encoding *enc = rb_enc_get(re);
rb_reg_check(re);
@@ -661,7 +671,7 @@ rb_reg_raise(const char *s, long len, const char *err, VALUE re)
static VALUE
rb_enc_reg_error_desc(const char *s, long len, rb_encoding *enc, int options, const char *err)
{
- char opts[6];
+ char opts[OPTBUF_SIZE + 1]; /* for '/' */
VALUE desc = rb_str_buf_new2(err);
rb_encoding *resenc = rb_default_internal_encoding();
if (resenc == NULL) resenc = rb_default_external_encoding();
@@ -917,12 +927,12 @@ make_regexp(const char *s, long len, rb_encoding *enc, int flags, onig_errmsg_bu
* aliased as global variables:
*
* * <code>$~</code> is Regexp.last_match;
- * * <code>$&</code> is Regexp.last_match<code>[0]</code>;
+ * * <code>$&</code> is Regexp.last_match<code>[ 0 ]</code>;
* * <code>$1</code>, <code>$2</code>, and so on are
- * Regexp.last_match<code>[i]</code> (captures by number);
+ * Regexp.last_match<code>[ i ]</code> (captures by number);
* * <code>$`</code> is Regexp.last_match<code>.pre_match</code>;
* * <code>$'</code> is Regexp.last_match<code>.post_match</code>;
- * * <code>$+</code> is Regexp.last_match<code>[-1]</code> (the last capture).
+ * * <code>$+</code> is Regexp.last_match<code>[ -1 ]</code> (the last capture).
*
* See also "Special global variables" section in Regexp documentation.
*/
@@ -1482,8 +1492,10 @@ rb_reg_prepare_re0(VALUE re, VALUE str, onig_errmsg_buffer err)
rb_raise(rb_eArgError, "regexp preprocess failed: %s", err);
}
- r = onig_new(&reg, (UChar* )RSTRING_PTR(unescaped),
- (UChar* )(RSTRING_PTR(unescaped) + RSTRING_LEN(unescaped)),
+ const char *ptr;
+ long len;
+ RSTRING_GETMEM(unescaped, ptr, len);
+ r = onig_new(&reg, (UChar *)ptr, (UChar *)(ptr + len),
reg->options, enc,
OnigDefaultSyntax, &einfo);
if (r) {
@@ -1534,18 +1546,21 @@ rb_reg_adjust_startpos(VALUE re, VALUE str, long pos, int reverse)
}
/* returns byte offset */
-long
-rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str)
+static long
+rb_reg_search_set_match(VALUE re, VALUE str, long pos, int reverse, int set_backref_str, VALUE *set_match)
{
long result;
VALUE match;
struct re_registers regi, *regs = &regi;
- char *range = RSTRING_PTR(str);
+ char *start, *range;
+ long len;
regex_t *reg;
int tmpreg;
onig_errmsg_buffer err = "";
- if (pos > RSTRING_LEN(str) || pos < 0) {
+ RSTRING_GETMEM(str, start, len);
+ range = start;
+ if (pos > len || pos < 0) {
rb_backref_set(Qnil);
return -1;
}
@@ -1554,25 +1569,14 @@ rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str)
tmpreg = reg != RREGEXP_PTR(re);
if (!tmpreg) RREGEXP(re)->usecnt++;
- match = rb_backref_get();
- if (!NIL_P(match)) {
- if (FL_TEST(match, MATCH_BUSY)) {
- match = Qnil;
- }
- else {
- regs = RMATCH_REGS(match);
- }
- }
- if (NIL_P(match)) {
- MEMZERO(regs, struct re_registers, 1);
- }
+ MEMZERO(regs, struct re_registers, 1);
if (!reverse) {
- range += RSTRING_LEN(str);
+ range += len;
}
result = onig_search(reg,
- (UChar*)(RSTRING_PTR(str)),
- ((UChar*)(RSTRING_PTR(str)) + RSTRING_LEN(str)),
- ((UChar*)(RSTRING_PTR(str)) + pos),
+ (UChar*)start,
+ ((UChar*)(start + len)),
+ ((UChar*)(start + pos)),
((UChar*)range),
regs, ONIG_OPTION_NONE);
if (!tmpreg) RREGEXP(re)->usecnt--;
@@ -1598,13 +1602,10 @@ rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str)
}
}
- if (NIL_P(match)) {
- int err;
- match = match_alloc(rb_cMatch);
- err = rb_reg_region_copy(RMATCH_REGS(match), regs);
- onig_region_free(regs, 0);
- if (err) rb_memerror();
- }
+ match = match_alloc(rb_cMatch);
+ int copy_err = rb_reg_region_copy(RMATCH_REGS(match), regs);
+ onig_region_free(regs, 0);
+ if (copy_err) rb_memerror();
if (set_backref_str) {
RMATCH(match)->str = rb_str_new4(str);
@@ -1612,11 +1613,18 @@ rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str)
RMATCH(match)->regexp = re;
rb_backref_set(match);
+ if (set_match) *set_match = match;
return result;
}
long
+rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str)
+{
+ return rb_reg_search_set_match(re, str, pos, reverse, set_backref_str, NULL);
+}
+
+long
rb_reg_search(VALUE re, VALUE str, long pos, int reverse)
{
return rb_reg_search0(re, str, pos, reverse, 1);
@@ -1648,10 +1656,13 @@ rb_reg_start_with_p(VALUE re, VALUE str)
if (NIL_P(match)) {
MEMZERO(regs, struct re_registers, 1);
}
+ const char *ptr;
+ long len;
+ RSTRING_GETMEM(str, ptr, len);
result = onig_match(reg,
- (UChar*)(RSTRING_PTR(str)),
- ((UChar*)(RSTRING_PTR(str)) + RSTRING_LEN(str)),
- (UChar*)(RSTRING_PTR(str)),
+ (UChar*)(ptr),
+ ((UChar*)(ptr + len)),
+ (UChar*)(ptr),
regs, ONIG_OPTION_NONE);
if (!tmpreg) RREGEXP(re)->usecnt--;
if (tmpreg) {
@@ -2926,7 +2937,9 @@ rb_reg_init_str_enc(VALUE re, VALUE s, rb_encoding *enc, int options)
MJIT_FUNC_EXPORTED VALUE
rb_reg_new_ary(VALUE ary, int opt)
{
- return rb_reg_new_str(rb_reg_preprocess_dregexp(ary, opt), opt);
+ VALUE re = rb_reg_new_str(rb_reg_preprocess_dregexp(ary, opt), opt);
+ rb_obj_freeze(re);
+ return re;
}
VALUE
@@ -2961,6 +2974,7 @@ rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline)
return Qnil;
}
FL_SET(re, REG_LITERAL);
+ rb_obj_freeze(re);
return re;
}
@@ -3106,7 +3120,7 @@ reg_operand(VALUE s, int check)
}
static long
-reg_match_pos(VALUE re, VALUE *strp, long pos)
+reg_match_pos(VALUE re, VALUE *strp, long pos, VALUE* set_match)
{
VALUE str = *strp;
@@ -3125,7 +3139,7 @@ reg_match_pos(VALUE re, VALUE *strp, long pos)
}
pos = rb_str_offset(str, pos);
}
- return rb_reg_search(re, str, pos, 0);
+ return rb_reg_search_set_match(re, str, pos, 0, 1, set_match);
}
/*
@@ -3179,7 +3193,7 @@ reg_match_pos(VALUE re, VALUE *strp, long pos)
VALUE
rb_reg_match(VALUE re, VALUE str)
{
- long pos = reg_match_pos(re, &str, 0);
+ long pos = reg_match_pos(re, &str, 0, NULL);
if (pos < 0) return Qnil;
pos = rb_str_sublen(str, pos);
return LONG2FIX(pos);
@@ -3257,8 +3271,8 @@ rb_reg_match2(VALUE re)
/*
* call-seq:
- * rxp.match(str) -> matchdata or nil
- * rxp.match(str,pos) -> matchdata or nil
+ * rxp.match(str, pos=0) -> matchdata or nil
+ * rxp.match(str, pos=0) {|match| block } -> obj
*
* Returns a MatchData object describing the match, or
* <code>nil</code> if there was no match. This is equivalent to
@@ -3290,7 +3304,7 @@ rb_reg_match2(VALUE re)
static VALUE
rb_reg_match_m(int argc, VALUE *argv, VALUE re)
{
- VALUE result, str, initpos;
+ VALUE result = Qnil, str, initpos;
long pos;
if (rb_scan_args(argc, argv, "11", &str, &initpos) == 2) {
@@ -3300,12 +3314,11 @@ rb_reg_match_m(int argc, VALUE *argv, VALUE re)
pos = 0;
}
- pos = reg_match_pos(re, &str, pos);
+ pos = reg_match_pos(re, &str, pos, &result);
if (pos < 0) {
rb_backref_set(Qnil);
return Qnil;
}
- result = rb_backref_get();
rb_match_busy(result);
if (!NIL_P(result) && rb_block_given_p()) {
return rb_yield(result);
@@ -3446,7 +3459,7 @@ rb_reg_initialize_m(int argc, VALUE *argv, VALUE self)
flags |= ARG_ENCODING_NONE;
}
else {
- rb_warn("encoding option is ignored - %s", kcode);
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "encoding option is ignored - %s", kcode);
}
}
str = StringValue(argv[0]);
@@ -3502,8 +3515,9 @@ rb_reg_quote(VALUE str)
}
t = RSTRING_PTR(tmp);
/* copy upto metacharacter */
- memcpy(t, RSTRING_PTR(str), s - RSTRING_PTR(str));
- t += s - RSTRING_PTR(str);
+ const char *p = RSTRING_PTR(str);
+ memcpy(t, p, s - p);
+ t += s - p;
while (s < send) {
c = rb_enc_ascget(s, send, &clen, enc);
@@ -3781,10 +3795,12 @@ rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp)
rb_encoding *str_enc = rb_enc_get(str);
rb_encoding *src_enc = rb_enc_get(src);
int acompat = rb_enc_asciicompat(str_enc);
+ long n;
#define ASCGET(s,e,cl) (acompat ? (*(cl)=1,ISASCII((s)[0])?(s)[0]:-1) : rb_enc_ascget((s), (e), (cl), str_enc))
- p = s = RSTRING_PTR(str);
- e = s + RSTRING_LEN(str);
+ RSTRING_GETMEM(str, s, n);
+ p = s;
+ e = s + n;
while (s < e) {
int c = ASCGET(s, e, &clen);
@@ -3896,29 +3912,16 @@ rb_reg_regsub(VALUE str, VALUE src, struct re_registers *regs, VALUE regexp)
}
static VALUE
-kcode_getter(ID _x, VALUE *_y)
-{
- rb_warn("variable $KCODE is no longer effective");
- return Qnil;
-}
-
-static void
-kcode_setter(VALUE val, ID id, VALUE *_)
-{
- rb_warn("variable $KCODE is no longer effective; ignored");
-}
-
-static VALUE
ignorecase_getter(ID _x, VALUE *_y)
{
- rb_warn("variable $= is no longer effective");
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "variable $= is no longer effective");
return Qfalse;
}
static void
ignorecase_setter(VALUE val, ID id, VALUE *_)
{
- rb_warn("variable $= is no longer effective; ignored");
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "variable $= is no longer effective; ignored");
}
static VALUE
@@ -4031,9 +4034,13 @@ Init_Regexp(void)
rb_define_virtual_variable("$'", postmatch_getter, 0);
rb_define_virtual_variable("$+", last_paren_match_getter, 0);
+ rb_gvar_ractor_local("$~");
+ rb_gvar_ractor_local("$&");
+ rb_gvar_ractor_local("$`");
+ rb_gvar_ractor_local("$'");
+ rb_gvar_ractor_local("$+");
+
rb_define_virtual_variable("$=", ignorecase_getter, ignorecase_setter);
- rb_define_virtual_variable("$KCODE", kcode_getter, kcode_setter);
- rb_define_virtual_variable("$-K", kcode_getter, kcode_setter);
rb_cRegexp = rb_define_class("Regexp", rb_cObject);
rb_define_alloc_func(rb_cRegexp, rb_reg_s_alloc);
diff --git a/regcomp.c b/regcomp.c
index 00d3746348..bd38313875 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -138,6 +138,27 @@ bitset_on_num(BitSetRef bs)
}
#endif
+// Attempt to right size allocated buffers for a regex post compile
+static void
+onig_reg_resize(regex_t *reg)
+{
+ do {
+ if (!reg->used) {
+ xfree(reg->p);
+ reg->alloc = 0;
+ reg->p = 0;
+ }
+ else if (reg->alloc > reg->used) {
+ unsigned char *new_ptr = xrealloc(reg->p, reg->used);
+ // Skip the right size optimization if memory allocation fails
+ if (new_ptr) {
+ reg->alloc = reg->used;
+ reg->p = new_ptr;
+ }
+ }
+ } while ((reg = reg->chain) != 0);
+}
+
extern int
onig_bbuf_init(BBuf* buf, OnigDistance size)
{
@@ -5889,6 +5910,7 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
#endif
end:
+ onig_reg_resize(reg);
return r;
err_unset:
diff --git a/regparse.c b/regparse.c
index a96c8c2fa7..24ff5b9a18 100644
--- a/regparse.c
+++ b/regparse.c
@@ -2187,7 +2187,6 @@ enum ReduceType {
RQ_AQ, /* to '*?' */
RQ_QQ, /* to '??' */
RQ_P_QQ, /* to '+)??' */
- RQ_PQ_Q /* to '+?)?' */
};
static enum ReduceType const ReduceTypeTable[6][6] = {
@@ -2197,7 +2196,7 @@ static enum ReduceType const ReduceTypeTable[6][6] = {
{RQ_A, RQ_A, RQ_DEL, RQ_ASIS, RQ_P_QQ, RQ_DEL}, /* '+' */
{RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL, RQ_AQ, RQ_AQ}, /* '??' */
{RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL, RQ_DEL}, /* '*?' */
- {RQ_ASIS, RQ_PQ_Q, RQ_DEL, RQ_AQ, RQ_AQ, RQ_DEL} /* '+?' */
+ {RQ_ASIS, RQ_ASIS, RQ_ASIS, RQ_AQ, RQ_AQ, RQ_DEL} /* '+?' */
};
extern void
@@ -2234,12 +2233,6 @@ onig_reduce_nested_quantifier(Node* pnode, Node* cnode)
c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 1;
return ;
break;
- case RQ_PQ_Q:
- p->target = cnode;
- p->lower = 0; p->upper = 1; p->greedy = 1;
- c->lower = 1; c->upper = REPEAT_INFINITE; c->greedy = 0;
- return ;
- break;
case RQ_ASIS:
p->target = cnode;
return ;
@@ -4348,7 +4341,7 @@ fetch_char_property_to_ctype(UChar** src, UChar* end, ScanEnv* env)
OnigEncoding enc = env->enc;
UChar *prev, *start, *p = *src;
- r = 0;
+ r = ONIGERR_INVALID_CHAR_PROPERTY_NAME;
start = prev = p;
while (!PEND) {
@@ -4362,7 +4355,6 @@ fetch_char_property_to_ctype(UChar** src, UChar* end, ScanEnv* env)
return r;
}
else if (c == '(' || c == ')' || c == '{' || c == '|') {
- r = ONIGERR_INVALID_CHAR_PROPERTY_NAME;
break;
}
}
diff --git a/ruby-runner.c b/ruby-runner.c
index d41ba274c3..b756c219fa 100644
--- a/ruby-runner.c
+++ b/ruby-runner.c
@@ -1,5 +1,5 @@
#define _POSIX_C_SOURCE 200809L
-#include "ruby/config.h"
+#include "ruby/internal/config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/ruby.c b/ruby.c
index bcdfb321a3..2251fde4e2 100644
--- a/ruby.c
+++ b/ruby.c
@@ -11,38 +11,60 @@
**********************************************************************/
-#ifdef __CYGWIN__
-#include <windows.h>
-#include <sys/cygwin.h>
-#endif
-#include "ruby/encoding.h"
-#include "ruby/thread.h"
-#include "ruby/version.h"
-#include "internal.h"
-#include "eval_intern.h"
-#include "dln.h"
+#include "ruby/internal/config.h"
+
+#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
-#include <ctype.h>
+
+#ifdef __CYGWIN__
+# include <windows.h>
+# include <sys/cygwin.h>
+#endif
#ifdef __hpux
-#include <sys/pstat.h>
+# include <sys/pstat.h>
#endif
-#if (defined(LOAD_RELATIVE) || defined(__MACH__)) && defined(HAVE_DLADDR)
-#include <dlfcn.h>
+
+#if defined(LOAD_RELATIVE) && defined(HAVE_DLADDR)
+# include <dlfcn.h>
#endif
#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+# include <unistd.h>
#endif
+
#if defined(HAVE_FCNTL_H)
-#include <fcntl.h>
+# include <fcntl.h>
#elif defined(HAVE_SYS_FCNTL_H)
-#include <sys/fcntl.h>
+# include <sys/fcntl.h>
#endif
+
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
+
+#include "dln.h"
+#include "eval_intern.h"
+#include "internal.h"
+#include "internal/error.h"
+#include "internal/file.h"
+#include "internal/inits.h"
+#include "internal/io.h"
+#include "internal/load.h"
+#include "internal/loadpath.h"
+#include "internal/missing.h"
+#include "internal/object.h"
+#include "internal/parse.h"
+#include "internal/process.h"
+#include "internal/variable.h"
+#include "mjit.h"
+#include "ruby/encoding.h"
+#include "ruby/thread.h"
+#include "ruby/util.h"
+#include "ruby/version.h"
+#include "ruby/internal/error.h"
+
#ifndef MAXPATHLEN
# define MAXPATHLEN 1024
#endif
@@ -50,10 +72,6 @@
# define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
#endif
-#include "ruby/util.h"
-
-#include "mjit.h"
-
void Init_ruby_description(void);
#ifndef HAVE_STDLIB_H
@@ -223,20 +241,26 @@ static struct {
char **argv;
} origarg;
+static const char esc_standout[] = "\n\033[1;7m";
+static const char esc_bold[] = "\033[1m";
+static const char esc_reset[] = "\033[0m";
+static const char esc_none[] = "";
+
static void
-show_usage_line(const char *str, unsigned int namelen, unsigned int secondlen, int help)
+show_usage_line(const char *str, unsigned int namelen, unsigned int secondlen, int help, int highlight, unsigned int w)
{
- const unsigned int w = 16;
+ const char *sb = highlight ? esc_bold : esc_none;
+ const char *se = highlight ? esc_reset : esc_none;
const int wrap = help && namelen + secondlen - 1 > w;
- printf(" %.*s%-*.*s%-*s%s\n", namelen-1, str,
+ printf(" %s%.*s%-*.*s%s%-*s%s\n", sb, namelen-1, str,
(wrap ? 0 : w - namelen + 1),
- (help ? secondlen-1 : 0), str + namelen,
+ (help ? secondlen-1 : 0), str + namelen, se,
(wrap ? w + 3 : 0), (wrap ? "\n" : ""),
str + namelen + secondlen);
}
static void
-usage(const char *name, int help)
+usage(const char *name, int help, int highlight, int columns)
{
/* This message really ought to be max 23 lines.
* Removed -h because the user already knows that option. Others? */
@@ -286,6 +310,7 @@ usage(const char *name, int help)
M("--verbose", "", "turn on verbose mode and disable script from stdin"),
M("--version", "", "print the version number, then exit"),
M("--help", "", "show this message, -h for short message"),
+ M("--backtrace-limit=num", "", "limit the maximum length of backtrace"),
};
static const struct message dumps[] = {
M("insns", "", "instruction sequences"),
@@ -314,27 +339,32 @@ usage(const char *name, int help)
M("--jit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"),
};
int i;
+ const char *sb = highlight ? esc_standout+1 : esc_none;
+ const char *se = highlight ? esc_reset : esc_none;
const int num = numberof(usage_msg) - (help ? 1 : 0);
-#define SHOW(m) show_usage_line((m).str, (m).namelen, (m).secondlen, help)
+ unsigned int w = (columns > 80 ? (columns - 79) / 2 : 0) + 16;
+#define SHOW(m) show_usage_line((m).str, (m).namelen, (m).secondlen, help, highlight, w)
- printf("Usage: %s [switches] [--] [programfile] [arguments]\n", name);
+ printf("%sUsage:%s %s [switches] [--] [programfile] [arguments]\n", sb, se, name);
for (i = 0; i < num; ++i)
SHOW(usage_msg[i]);
if (!help) return;
+ if (highlight) sb = esc_standout;
+
for (i = 0; i < numberof(help_msg); ++i)
SHOW(help_msg[i]);
- puts("Dump List:");
+ printf("%s""Dump List:%s\n", sb, se);
for (i = 0; i < numberof(dumps); ++i)
SHOW(dumps[i]);
- puts("Features:");
+ printf("%s""Features:%s\n", sb, se);
for (i = 0; i < numberof(features); ++i)
SHOW(features[i]);
- puts("Warning categories:");
+ printf("%s""Warning categories:%s\n", sb, se);
for (i = 0; i < numberof(warn_categories); ++i)
SHOW(warn_categories[i]);
- puts("JIT options (experimental):");
+ printf("%s""JIT options (experimental):%s\n", sb, se);
for (i = 0; i < numberof(mjit_options); ++i)
SHOW(mjit_options[i]);
}
@@ -501,7 +531,7 @@ str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
void ruby_init_loadpath(void);
-#if defined(LOAD_RELATIVE) || defined(__MACH__)
+#if defined(LOAD_RELATIVE)
static VALUE
runtime_libruby_path(void)
{
@@ -577,10 +607,6 @@ runtime_libruby_path(void)
#define INITIAL_LOAD_PATH_MARK rb_intern_const("@gem_prelude_index")
VALUE ruby_archlibdir_path, ruby_prefix_path;
-#if defined(__MACH__)
-// A path to libruby.dylib itself or where it's statically linked to.
-VALUE rb_libruby_selfpath;
-#endif
void
ruby_init_loadpath(void)
@@ -588,14 +614,6 @@ ruby_init_loadpath(void)
VALUE load_path, archlibdir = 0;
ID id_initial_load_path_mark;
const char *paths = ruby_initial_load_paths;
-#if defined(LOAD_RELATIVE) || defined(__MACH__)
- VALUE libruby_path = runtime_libruby_path();
-# if defined(__MACH__)
- rb_libruby_selfpath = libruby_path;
- rb_gc_register_address(&rb_libruby_selfpath);
-# endif
-#endif
-
#if defined LOAD_RELATIVE
#if !defined ENABLE_MULTIARCH
# define RUBY_ARCH_PATH ""
@@ -609,7 +627,7 @@ ruby_init_loadpath(void)
size_t baselen;
const char *p;
- sopath = libruby_path;
+ sopath = runtime_libruby_path();
libpath = RSTRING_PTR(sopath);
p = strrchr(libpath, '/');
@@ -894,9 +912,7 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable)
if (NAME_MATCH_P(#bit, str, len)) {set |= mask = FEATURE_BIT(bit); FEATURE_FOUND;}
EACH_FEATURES(SET_FEATURE, ;);
if (NAME_MATCH_P("all", str, len)) {
- found:
- FEATURE_SET_TO(*argp, mask, (mask & enable));
- return;
+ goto found;
}
#if AMBIGUOUS_FEATURE_NAMES
if (matched == 1) goto found;
@@ -916,6 +932,11 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable)
rb_warn("unknown argument for --%s: `%.*s'",
enable ? "enable" : "disable", len, str);
rb_warn("features are [%.*s].", (int)strlen(list), list);
+ return;
+
+ found:
+ FEATURE_SET_TO(*argp, mask, (mask & enable));
+ return;
}
static void
@@ -988,34 +1009,45 @@ set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen
static void
setup_mjit_options(const char *s, struct mjit_options *mjit_opt)
{
+#define opt_match(s, l, name) \
+ ((((l) > rb_strlen_lit(name)) ? (s)[rb_strlen_lit(name)] == '=' : \
+ (l) == rb_strlen_lit(name)) && \
+ memcmp((s), name, rb_strlen_lit(name)) == 0 && \
+ (((s) += rb_strlen_lit(name)), 1))
+#define opt_match_noarg(s, l, name) \
+ opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --jit-" name " is ignored"), 1) : 1)
+#define opt_match_arg(s, l, name) \
+ opt_match(s, l, name) && (*(s) ? 1 : (rb_raise(rb_eRuntimeError, "--jit-" name " needs an argument"), 0))
+ if (*s != '-') return;
+ const size_t l = strlen(++s);
if (*s == 0) return;
- else if (strcmp(s, "-warnings") == 0) {
+ else if (opt_match_noarg(s, l, "warnings")) {
mjit_opt->warnings = 1;
}
- else if (strncmp(s, "-debug=", 7) == 0) {
- mjit_opt->debug_flags = strdup(s + 7);
- }
- else if (strcmp(s, "-debug") == 0) {
- mjit_opt->debug = 1;
+ else if (opt_match(s, l, "debug")) {
+ if (*s)
+ mjit_opt->debug_flags = strdup(s + 1);
+ else
+ mjit_opt->debug = 1;
}
- else if (strcmp(s, "-wait") == 0) {
+ else if (opt_match_noarg(s, l, "wait")) {
mjit_opt->wait = 1;
}
- else if (strcmp(s, "-save-temps") == 0) {
+ else if (opt_match_noarg(s, l, "save-temps")) {
mjit_opt->save_temps = 1;
}
- else if (strncmp(s, "-verbose=", 9) == 0) {
- mjit_opt->verbose = atoi(s + 9);
+ else if (opt_match(s, l, "verbose")) {
+ mjit_opt->verbose = *s ? atoi(s + 1) : 1;
}
- else if (strncmp(s, "-max-cache=", 11) == 0) {
- mjit_opt->max_cache_size = atoi(s + 11);
+ else if (opt_match_arg(s, l, "max-cache")) {
+ mjit_opt->max_cache_size = atoi(s + 1);
}
- else if (strncmp(s, "-min-calls=", 11) == 0) {
- mjit_opt->min_calls = atoi(s + 11);
+ else if (opt_match_arg(s, l, "min-calls")) {
+ mjit_opt->min_calls = atoi(s + 1);
}
else {
rb_raise(rb_eRuntimeError,
- "invalid MJIT option `%s' (--help will show valid MJIT options)", s + 1);
+ "invalid MJIT option `%s' (--help will show valid MJIT options)", s);
}
}
#endif
@@ -1108,7 +1140,7 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
if (*++s) {
v = scan_oct(s, 1, &numlen);
if (numlen == 0)
- v = 1;
+ v = 2;
s += numlen;
}
if (!opt->warning) {
@@ -1270,18 +1302,6 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
}
goto reswitch;
- case 'T':
- {
- size_t numlen;
-
- if (*++s) {
- scan_oct(s, 2, &numlen);
- s += numlen;
- }
- }
- rb_warn("ruby -T will be removed in Ruby 3.0");
- goto reswitch;
-
case 'I':
forbid_setid("-I");
if (*++s)
@@ -1419,6 +1439,12 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
opt->dump |= DUMP_BIT(help);
goto switch_end;
}
+ else if (is_option_with_arg("backtrace-limit", Qfalse, Qfalse)) {
+ char *e;
+ long n = strtol(s, &e, 10);
+ if (errno == ERANGE || n < 0 || *e) rb_raise(rb_eRuntimeError, "wrong limit for backtrace length");
+ rb_backtrace_length_limit = n;
+ }
else {
rb_raise(rb_eRuntimeError,
"invalid option --%s (-h will show valid options)", s);
@@ -1470,6 +1496,30 @@ ruby_init_prelude(void)
rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
}
+void rb_call_builtin_inits(void);
+
+static void
+ruby_opt_init(ruby_cmdline_options_t *opt)
+{
+ if (opt->dump & dump_exit_bits) return;
+
+ if (opt->features.set & FEATURE_BIT(gems)) {
+ rb_define_module("Gem");
+ if (opt->features.set & FEATURE_BIT(did_you_mean)) {
+ rb_define_module("DidYouMean");
+ }
+ }
+
+ rb_warning_category_update(opt->warn.mask, opt->warn.set);
+
+ Init_ext(); /* load statically linked extensions before rubygems */
+ rb_call_builtin_inits();
+ ruby_init_prelude();
+
+ ruby_set_script_name(opt->script_name);
+ require_libraries(&opt->req_list);
+}
+
static int
opt_enc_index(VALUE enc_name)
{
@@ -1593,6 +1643,40 @@ rb_f_chomp(int argc, VALUE *argv, VALUE _)
return str;
}
+static void
+setup_pager_env(void)
+{
+ if (!getenv("LESS")) ruby_setenv("LESS", "-R"); // Output "raw" control characters.
+}
+
+#ifdef _WIN32
+static int
+tty_enabled(void)
+{
+ HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
+ DWORD m;
+ if (!GetConsoleMode(h, &m)) return 0;
+# ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x4
+# endif
+ if (!(m & ENABLE_VIRTUAL_TERMINAL_PROCESSING)) return 0;
+ return 1;
+}
+#elif !defined(HAVE_WORKING_FORK)
+# define tty_enabled() 0
+#endif
+
+static VALUE
+copy_str(VALUE str, rb_encoding *enc, bool intern)
+{
+ if (!intern) {
+ if (rb_enc_str_coderange_scan(str, enc) == ENC_CODERANGE_BROKEN)
+ return 0;
+ return rb_enc_associate(rb_str_dup(str), enc);
+ }
+ return rb_enc_interned_str(RSTRING_PTR(str), RSTRING_LEN(str), enc);
+}
+
static VALUE
process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
{
@@ -1602,19 +1686,73 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
const rb_iseq_t *iseq;
rb_encoding *enc, *lenc;
#if UTF8_PATH
- rb_encoding *uenc, *ienc = 0;
+ rb_encoding *ienc = 0;
+ rb_encoding *const uenc = rb_utf8_encoding();
#endif
const char *s;
char fbuf[MAXPATHLEN];
int i = (int)proc_options(argc, argv, opt, 0);
unsigned int dump = opt->dump & dump_exit_bits;
+ rb_vm_t *vm = GET_VM();
+ const long loaded_before_enc = RARRAY_LEN(vm->loaded_features);
if (opt->dump & (DUMP_BIT(usage)|DUMP_BIT(help))) {
+ int tty = isatty(1);
const char *const progname =
(argc > 0 && argv && argv[0] ? argv[0] :
origarg.argc > 0 && origarg.argv && origarg.argv[0] ? origarg.argv[0] :
ruby_engine);
- usage(progname, (opt->dump & DUMP_BIT(help)));
+ int columns = 0;
+ if ((opt->dump & DUMP_BIT(help)) && tty) {
+ const char *pager_env = getenv("RUBY_PAGER");
+ if (!pager_env) pager_env = getenv("PAGER");
+ if (pager_env && *pager_env && isatty(0)) {
+ const char *columns_env = getenv("COLUMNS");
+ if (columns_env) columns = atoi(columns_env);
+ VALUE pager = rb_str_new_cstr(pager_env);
+#ifdef HAVE_WORKING_FORK
+ int fds[2];
+ if (rb_pipe(fds) == 0) {
+ rb_pid_t pid = rb_fork();
+ if (pid > 0) {
+ /* exec PAGER with reading from child */
+ dup2(fds[0], 0);
+ }
+ else if (pid == 0) {
+ /* send the help message to the parent PAGER */
+ dup2(fds[1], 1);
+ dup2(fds[1], 2);
+ }
+ close(fds[0]);
+ close(fds[1]);
+ if (pid > 0) {
+ setup_pager_env();
+ rb_f_exec(1, &pager);
+ kill(SIGTERM, pid);
+ rb_waitpid(pid, 0, 0);
+ }
+ }
+#else
+ setup_pager_env();
+ VALUE port = rb_io_popen(pager, rb_str_new_lit("w"), Qnil, Qnil);
+ if (!NIL_P(port)) {
+ int oldout = dup(1);
+ int olderr = dup(2);
+ int fd = RFILE(port)->fptr->fd;
+ tty = tty_enabled();
+ dup2(fd, 1);
+ dup2(fd, 2);
+ usage(progname, 1, tty, columns);
+ fflush(stdout);
+ dup2(oldout, 1);
+ dup2(olderr, 2);
+ rb_io_close(port);
+ return Qtrue;
+ }
+#endif
+ }
+ }
+ usage(progname, (opt->dump & DUMP_BIT(help)), tty, columns);
return Qtrue;
}
@@ -1641,7 +1779,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
}
if (opt->src.enc.name)
- rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
+ /* cannot set deprecated category, as enabling deprecation warnings based on flags
+ * has not happened yet.
+ */
+ rb_warning("-K is specified; it is for 1.8 compatibility and may cause odd behavior");
#if USE_MJIT
if (opt->features.set & FEATURE_BIT(jit)) {
@@ -1733,7 +1874,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
enc = rb_enc_from_index(opt->ext.enc.index);
}
else {
- enc = lenc;
+ enc = IF_UTF8_PATH(uenc, lenc);
}
rb_enc_set_default_external(rb_enc_from_encoding(enc));
if (opt->intern.enc.index >= 0) {
@@ -1745,8 +1886,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
#endif
}
script_name = opt->script_name;
- rb_enc_associate(opt->script_name,
- IF_UTF8_PATH(uenc = rb_utf8_encoding(), lenc));
+ rb_enc_associate(opt->script_name, IF_UTF8_PATH(uenc, lenc));
#if UTF8_PATH
if (uenc != lenc) {
opt->script_name = str_conv_enc(opt->script_name, uenc, lenc);
@@ -1756,7 +1896,6 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
rb_obj_freeze(opt->script_name);
if (IF_UTF8_PATH(uenc != lenc, 1)) {
long i;
- rb_vm_t *vm = GET_VM();
VALUE load_path = vm->load_path;
const ID id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK;
int modifiable = FALSE;
@@ -1770,7 +1909,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
if (newpath == path) continue;
path = newpath;
#else
- path = rb_enc_associate(rb_str_dup(path), lenc);
+ if (!(path = copy_str(path, lenc, !mark))) continue;
#endif
if (mark) rb_ivar_set(path, id_initial_load_path_mark, path);
if (!modifiable) {
@@ -1783,17 +1922,20 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
rb_ary_replace(vm->load_path_snapshot, load_path);
}
}
-
- rb_warning_category_update(opt->warn.mask, opt->warn.set);
-
- Init_ext(); /* load statically linked extensions before rubygems */
- if (opt->features.set & FEATURE_BIT(gems)) {
- rb_define_module("Gem");
- if (opt->features.set & FEATURE_BIT(did_you_mean)) {
- rb_define_module("DidYouMean");
- }
+ {
+ VALUE loaded_features = vm->loaded_features;
+ bool modified = false;
+ for (long i = loaded_before_enc; i < RARRAY_LEN(loaded_features); ++i) {
+ VALUE path = RARRAY_AREF(loaded_features, i);
+ if (!(path = copy_str(path, IF_UTF8_PATH(uenc, lenc), true))) continue;
+ modified = true;
+ RARRAY_ASET(loaded_features, i, path);
+ }
+ if (modified) {
+ rb_ary_replace(vm->loaded_features_snapshot, loaded_features);
+ }
}
- ruby_init_prelude();
+
if (opt->features.mask & COMPILATION_FEATURES) {
VALUE option = rb_hash_new();
#define SET_COMPILE_OPTION(h, o, name) \
@@ -1827,10 +1969,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
}
#endif
rb_enc_associate(opt->e_script, eenc);
- if (!(opt->dump & ~DUMP_BIT(version_v))) {
- ruby_set_script_name(opt->script_name);
- require_libraries(&opt->req_list);
- }
+ ruby_opt_init(opt);
ruby_set_script_name(progname);
rb_parser_set_options(parser, opt->do_print, opt->do_loop,
opt->do_line, opt->do_split);
@@ -1851,7 +1990,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
enc = rb_enc_from_index(opt->ext.enc.index);
}
else {
- enc = lenc;
+ enc = IF_UTF8_PATH(uenc, lenc);
}
rb_enc_set_default_external(rb_enc_from_encoding(enc));
if (opt->intern.enc.index >= 0) {
@@ -1929,6 +2068,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
rb_define_readonly_boolean("$-l", opt->do_line);
rb_define_readonly_boolean("$-a", opt->do_split);
+ rb_gvar_ractor_local("$-p");
+ rb_gvar_ractor_local("$-l");
+ rb_gvar_ractor_local("$-a");
+
if ((rb_e_script = opt->e_script) != 0) {
rb_gc_register_mark_object(opt->e_script);
}
@@ -2056,10 +2199,7 @@ load_file_internal(VALUE argp_v)
if (NIL_P(c)) {
argp->f = f = Qnil;
}
- if (!(opt->dump & ~DUMP_BIT(version_v))) {
- ruby_set_script_name(opt->script_name);
- require_libraries(&opt->req_list); /* Why here? unnatural */
- }
+ ruby_opt_init(opt);
}
if (opt->src.enc.index >= 0) {
enc = rb_enc_from_index(opt->src.enc.index);
@@ -2149,9 +2289,13 @@ open_load_file(VALUE fname_v, int *xflag)
rb_update_max_fd(fd);
#if defined HAVE_FCNTL && MODE_TO_LOAD != O_RDONLY
+# ifdef ENOTSUP
+# define IS_SUPPORTED_OP(e) ((e) != ENOTSUP)
+# else
+# define IS_SUPPORTED_OP(e) ((void)(e), 1)
+# endif
/* disabling O_NONBLOCK */
- if (fcntl(fd, F_SETFL, 0) < 0) {
- e = errno;
+ if (fcntl(fd, F_SETFL, 0) < 0 && IS_SUPPORTED_OP(e = errno)) {
(void)close(fd);
rb_load_fail(fname_v, strerror(e));
}
@@ -2340,16 +2484,24 @@ forbid_setid(const char *s, const ruby_cmdline_options_t *opt)
rb_raise(rb_eSecurityError, "no %s allowed while running setgid", s);
}
+static VALUE
+verbose_getter(ID id, VALUE *ptr)
+{
+ return *rb_ruby_verbose_ptr();
+}
+
static void
verbose_setter(VALUE val, ID id, VALUE *variable)
{
- *variable = RTEST(val) ? Qtrue : val;
+ *rb_ruby_verbose_ptr() = RTEST(val) ? Qtrue : val;
}
static VALUE
-opt_W_getter(ID id, VALUE *variable)
+opt_W_getter(ID id, VALUE *dmy)
{
- switch (*variable) {
+ VALUE v = *rb_ruby_verbose_ptr();
+
+ switch (v) {
case Qnil:
return INT2FIX(0);
case Qfalse:
@@ -2361,16 +2513,35 @@ opt_W_getter(ID id, VALUE *variable)
}
}
+static VALUE
+debug_getter(ID id, VALUE *dmy)
+{
+ return *rb_ruby_debug_ptr();
+}
+
+static void
+debug_setter(VALUE val, ID id, VALUE *dmy)
+{
+ *rb_ruby_debug_ptr() = val;
+}
+
/*! Defines built-in variables */
void
ruby_prog_init(void)
{
- rb_define_hooked_variable("$VERBOSE", &ruby_verbose, 0, verbose_setter);
- rb_define_hooked_variable("$-v", &ruby_verbose, 0, verbose_setter);
- rb_define_hooked_variable("$-w", &ruby_verbose, 0, verbose_setter);
- rb_define_hooked_variable("$-W", &ruby_verbose, opt_W_getter, rb_gvar_readonly_setter);
- rb_define_variable("$DEBUG", &ruby_debug);
- rb_define_variable("$-d", &ruby_debug);
+ rb_define_virtual_variable("$VERBOSE", verbose_getter, verbose_setter);
+ rb_define_virtual_variable("$-v", verbose_getter, verbose_setter);
+ rb_define_virtual_variable("$-w", verbose_getter, verbose_setter);
+ rb_define_virtual_variable("$-W", opt_W_getter, rb_gvar_readonly_setter);
+ rb_define_virtual_variable("$DEBUG", debug_getter, debug_setter);
+ rb_define_virtual_variable("$-d", debug_getter, debug_setter);
+
+ rb_gvar_ractor_local("$VERBOSE");
+ rb_gvar_ractor_local("$-v");
+ rb_gvar_ractor_local("$-w");
+ rb_gvar_ractor_local("$-W");
+ rb_gvar_ractor_local("$DEBUG");
+ rb_gvar_ractor_local("$-d");
rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0);
rb_define_hooked_variable("$PROGRAM_NAME", &rb_progname, 0, set_arg0);
diff --git a/ruby_assert.h b/ruby_assert.h
index fa15da1e25..ddd348c7d3 100644
--- a/ruby_assert.h
+++ b/ruby_assert.h
@@ -1,15 +1,15 @@
+#ifndef RUBY_TOPLEVEL_ASSERT_H /*-*-C-*-vi:se ft=c:*/
+#define RUBY_TOPLEVEL_ASSERT_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.
+ */
#include "ruby/assert.h"
-
-#if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
-/* C89 compilers are required to support strings of only 509 chars. */
-/* can't use RUBY_ASSERT for such compilers. */
-#include <assert.h>
-#else
#undef assert
-#define assert RUBY_ASSERT
-#endif
+#define assert RUBY_ASSERT_NDEBUG
-#ifdef NDEBUG
- #undef RUBY_NDEBUG
- #define RUBY_NDEBUG 1
-#endif
+#endif /* RUBY_TOPLEVEL_ASSERT_H */
diff --git a/ruby_atomic.h b/ruby_atomic.h
index 2516dbfb42..57d341082d 100644
--- a/ruby_atomic.h
+++ b/ruby_atomic.h
@@ -1,244 +1,23 @@
-#ifndef RUBY_ATOMIC_H
-#define RUBY_ATOMIC_H
-
-#if 0
-#elif defined HAVE_GCC_ATOMIC_BUILTINS
-typedef unsigned int rb_atomic_t;
-# define ATOMIC_SET(var, val) (void)__atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST)
-# define ATOMIC_INC(var) __atomic_fetch_add(&(var), 1, __ATOMIC_SEQ_CST)
-# define ATOMIC_DEC(var) __atomic_fetch_sub(&(var), 1, __ATOMIC_SEQ_CST)
-# define ATOMIC_OR(var, val) __atomic_fetch_or(&(var), (val), __ATOMIC_SEQ_CST)
-# define ATOMIC_EXCHANGE(var, val) __atomic_exchange_n(&(var), (val), __ATOMIC_SEQ_CST)
-# define ATOMIC_CAS(var, oldval, newval) \
-({ __typeof__(var) oldvaldup = (oldval); /* oldval should not be modified */ \
- __atomic_compare_exchange_n(&(var), &oldvaldup, (newval), 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \
- oldvaldup; })
-
-# define ATOMIC_SIZE_ADD(var, val) __atomic_fetch_add(&(var), (val), __ATOMIC_SEQ_CST)
-# define ATOMIC_SIZE_SUB(var, val) __atomic_fetch_sub(&(var), (val), __ATOMIC_SEQ_CST)
-
-# define RUBY_ATOMIC_GENERIC_MACRO 1
-
-#elif defined HAVE_GCC_SYNC_BUILTINS
-/* @shyouhei hack to support atomic operations in case of gcc. Gcc
- * has its own pseudo-insns to support them. See info, or
- * http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html */
-
-typedef unsigned int rb_atomic_t; /* Anything OK */
-# define ATOMIC_SET(var, val) (void)__sync_lock_test_and_set(&(var), (val))
-# define ATOMIC_INC(var) __sync_fetch_and_add(&(var), 1)
-# define ATOMIC_DEC(var) __sync_fetch_and_sub(&(var), 1)
-# define ATOMIC_OR(var, val) __sync_fetch_and_or(&(var), (val))
-# define ATOMIC_EXCHANGE(var, val) __sync_lock_test_and_set(&(var), (val))
-# define ATOMIC_CAS(var, oldval, newval) __sync_val_compare_and_swap(&(var), (oldval), (newval))
-
-# define ATOMIC_SIZE_ADD(var, val) __sync_fetch_and_add(&(var), (val))
-# define ATOMIC_SIZE_SUB(var, val) __sync_fetch_and_sub(&(var), (val))
-
-# define RUBY_ATOMIC_GENERIC_MACRO 1
-
-#elif defined _WIN32
-#if defined _MSC_VER && _MSC_VER > 1200
-#pragma intrinsic(_InterlockedOr)
-#endif
-typedef LONG rb_atomic_t;
-
-# define ATOMIC_SET(var, val) InterlockedExchange(&(var), (val))
-# define ATOMIC_INC(var) InterlockedIncrement(&(var))
-# define ATOMIC_DEC(var) InterlockedDecrement(&(var))
-#if defined __GNUC__
-# define ATOMIC_OR(var, val) __asm__("lock\n\t" "orl\t%1, %0" : "=m"(var) : "Ir"(val))
-#elif defined _MSC_VER && _MSC_VER <= 1200
-# define ATOMIC_OR(var, val) rb_w32_atomic_or(&(var), (val))
-static inline void
-rb_w32_atomic_or(volatile rb_atomic_t *var, rb_atomic_t val)
-{
-#ifdef _M_IX86
- __asm mov eax, var;
- __asm mov ecx, val;
- __asm lock or [eax], ecx;
-#else
-#error unsupported architecture
-#endif
-}
-#else
-# define ATOMIC_OR(var, val) _InterlockedOr(&(var), (val))
-#endif
-# define ATOMIC_EXCHANGE(var, val) InterlockedExchange(&(var), (val))
-# define ATOMIC_CAS(var, oldval, newval) InterlockedCompareExchange(&(var), (newval), (oldval))
-# if defined _MSC_VER && _MSC_VER <= 1200
-static inline rb_atomic_t
-rb_w32_atomic_cas(volatile rb_atomic_t *var, rb_atomic_t oldval, rb_atomic_t newval)
-{
- return (rb_atomic_t)InterlockedCompareExchange((PVOID *)var, (PVOID)newval, (PVOID)oldval);
-}
-# undef ATOMIC_CAS
-# define ATOMIC_CAS(var, oldval, newval) rb_w32_atomic_cas(&(var), (oldval), (newval))
-# endif
-# ifdef _M_AMD64
-# define ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd64((LONG_LONG *)&(var), (val))
-# define ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd64((LONG_LONG *)&(var), -(LONG)(val))
-# define ATOMIC_SIZE_INC(var) InterlockedIncrement64(&(var))
-# define ATOMIC_SIZE_DEC(var) InterlockedDecrement64(&(var))
-# define ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange64(&(var), (val))
-# define ATOMIC_SIZE_CAS(var, oldval, newval) InterlockedCompareExchange64(&(var), (newval), (oldval))
-# else
-# define ATOMIC_SIZE_ADD(var, val) InterlockedExchangeAdd((LONG *)&(var), (val))
-# define ATOMIC_SIZE_SUB(var, val) InterlockedExchangeAdd((LONG *)&(var), -(LONG)(val))
-# define ATOMIC_SIZE_INC(var) InterlockedIncrement((LONG *)&(var))
-# define ATOMIC_SIZE_DEC(var) InterlockedDecrement((LONG *)&(var))
-# define ATOMIC_SIZE_EXCHANGE(var, val) InterlockedExchange((LONG *)&(var), (val))
-# endif
-
-# ifdef InterlockedExchangePointer
-# define ATOMIC_PTR_EXCHANGE(var, val) InterlockedExchangePointer((PVOID volatile *)&(var), (PVOID)(val))
-# endif /* See below for definitions of other situations */
-
-#elif defined(__sun) && defined(HAVE_ATOMIC_H)
-#include <atomic.h>
-typedef unsigned int rb_atomic_t;
-
-# define ATOMIC_SET(var, val) (void)atomic_swap_uint(&(var), (val))
-# define ATOMIC_INC(var) atomic_inc_uint(&(var))
-# define ATOMIC_DEC(var) atomic_dec_uint(&(var))
-# define ATOMIC_OR(var, val) atomic_or_uint(&(var), (val))
-# define ATOMIC_EXCHANGE(var, val) atomic_swap_uint(&(var), (val))
-# define ATOMIC_CAS(var, oldval, newval) atomic_cas_uint(&(var), (oldval), (newval))
-
-# if SIZEOF_SIZE_T == SIZEOF_LONG
-# define ATOMIC_SIZE_ADD(var, val) atomic_add_long(&(var), (val))
-# define ATOMIC_SIZE_SUB(var, val) atomic_add_long(&(var), -(val))
-# define ATOMIC_SIZE_INC(var) atomic_inc_ulong(&(var))
-# define ATOMIC_SIZE_DEC(var) atomic_dec_ulong(&(var))
-# define ATOMIC_SIZE_EXCHANGE(var, val) atomic_swap_ulong(&(var), (val))
-# define ATOMIC_SIZE_CAS(var, oldval, val) atomic_cas_ulong(&(var), (oldval), (val))
-# else
-# define ATOMIC_SIZE_ADD(var, val) atomic_add_int(&(var), (val))
-# define ATOMIC_SIZE_SUB(var, val) atomic_add_int(&(var), -(val))
-# define ATOMIC_SIZE_INC(var) atomic_inc_uint(&(var))
-# define ATOMIC_SIZE_DEC(var) atomic_dec_uint(&(var))
-# define ATOMIC_SIZE_EXCHANGE(var, val) atomic_swap_uint(&(var), (val))
-# endif
-
-#else
-typedef int rb_atomic_t;
-#define NEED_RUBY_ATOMIC_OPS
-extern rb_atomic_t ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val);
-extern rb_atomic_t ruby_atomic_compare_and_swap(rb_atomic_t *ptr,
- rb_atomic_t cmp,
- rb_atomic_t newval);
-
-# define ATOMIC_SET(var, val) (void)((var) = (val))
-# define ATOMIC_INC(var) ((var)++)
-# define ATOMIC_DEC(var) ((var)--)
-# define ATOMIC_OR(var, val) ((var) |= (val))
-# define ATOMIC_EXCHANGE(var, val) ruby_atomic_exchange(&(var), (val))
-# define ATOMIC_CAS(var, oldval, newval) ruby_atomic_compare_and_swap(&(var), (oldval), (newval))
-
-# define ATOMIC_SIZE_ADD(var, val) (void)((var) += (val))
-# define ATOMIC_SIZE_SUB(var, val) (void)((var) -= (val))
-# define ATOMIC_SIZE_EXCHANGE(var, val) ruby_atomic_size_exchange(&(var), (val))
-static inline size_t
-ruby_atomic_size_exchange(size_t *ptr, size_t val)
-{
- size_t old = *ptr;
- *ptr = val;
- return old;
-}
-#endif
-
-#ifndef ATOMIC_SIZE_INC
-# define ATOMIC_SIZE_INC(var) ATOMIC_INC(var)
-#endif
-
-#ifndef ATOMIC_SIZE_DEC
-# define ATOMIC_SIZE_DEC(var) ATOMIC_DEC(var)
-#endif
-
-#ifndef ATOMIC_SIZE_EXCHANGE
-# define ATOMIC_SIZE_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val)
-#endif
-
-#ifndef ATOMIC_SIZE_CAS
-# define ATOMIC_SIZE_CAS(var, oldval, val) ATOMIC_CAS(var, oldval, val)
-#endif
-
-#if RUBY_ATOMIC_GENERIC_MACRO
-# ifndef ATOMIC_PTR_EXCHANGE
-# define ATOMIC_PTR_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val)
-# endif
-
-# ifndef ATOMIC_PTR_CAS
-# define ATOMIC_PTR_CAS(var, oldval, newval) ATOMIC_CAS(var, oldval, newval)
-# endif
-
-# ifndef ATOMIC_VALUE_EXCHANGE
-# define ATOMIC_VALUE_EXCHANGE(var, val) ATOMIC_EXCHANGE(var, val)
-# endif
-
-# ifndef ATOMIC_VALUE_CAS
-# define ATOMIC_VALUE_CAS(var, oldval, val) ATOMIC_CAS(var, oldval, val)
-# endif
-#endif
-
-#ifndef ATOMIC_PTR_EXCHANGE
-# if SIZEOF_VOIDP == SIZEOF_SIZE_T
-# define ATOMIC_PTR_EXCHANGE(var, val) (void *)ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val))
-# else
-# define ATOMIC_PTR_EXCHANGE(var, val) ruby_atomic_ptr_exchange((const void **)&(var), (val))
-static inline void *
-ruby_atomic_ptr_exchange(const void **ptr, const void *val)
-{
- const void *const old = *ptr;
- *ptr = val;
- return (void *)old;
-}
-# endif
-#endif
-
-#ifndef ATOMIC_PTR_CAS
-# if SIZEOF_VOIDP == SIZEOF_SIZE_T
-# define ATOMIC_PTR_CAS(var, oldval, val) (void *)ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val))
-# else
-# define ATOMIC_PTR_CAS(var, oldval, val) ruby_atomic_ptr_cas(&(var), (oldval), (val))
-static inline void *
-ruby_atomic_ptr_cas(const void **ptr, const void *oldval, const void *val)
-{
- const void *const old = *ptr;
- if (old == oldval) *ptr = val;
- return (void *)old;
-}
-# endif
-#endif
-
-#ifndef ATOMIC_VALUE_EXCHANGE
-# if SIZEOF_VALUE == SIZEOF_SIZE_T
-# define ATOMIC_VALUE_EXCHANGE(var, val) ATOMIC_SIZE_EXCHANGE(*(size_t *)&(var), (size_t)(val))
-# else
-# define ATOMIC_VALUE_EXCHANGE(var, val) ruby_atomic_value_exchange(&(var), (val))
-static inline VALUE
-ruby_atomic_value_exchange(VALUE *ptr, VALUE val)
-{
- const VALUE old = *ptr;
- *ptr = val;
- return old;
-}
-# endif
-#endif
-
-#ifndef ATOMIC_VALUE_CAS
-# if SIZEOF_VALUE == SIZEOF_SIZE_T
-# define ATOMIC_VALUE_CAS(var, oldval, val) ATOMIC_SIZE_CAS(*(size_t *)&(var), (size_t)(oldval), (size_t)(val))
-# else
-# define ATOMIC_VALUE_CAS(var, oldval, val) ruby_atomic_value_cas(&(var), (oldval), (val))
-static inline VALUE
-ruby_atomic_value_cas(VALUE *ptr, VALUE oldval, VALUE val)
-{
- const VALUE old = *ptr;
- if (old == oldval) *ptr = val;
- return old;
-}
-# endif
-#endif
-
-#endif /* RUBY_ATOMIC_H */
+#include "ruby/atomic.h"
+
+/* shim macros only */
+#define ATOMIC_ADD(var, val) RUBY_ATOMIC_ADD(var, val)
+#define ATOMIC_CAS(var, oldval, newval) RUBY_ATOMIC_CAS(var, oldval, newval)
+#define ATOMIC_DEC(var) RUBY_ATOMIC_DEC(var)
+#define ATOMIC_EXCHANGE(var, val) RUBY_ATOMIC_EXCHANGE(var, val)
+#define ATOMIC_FETCH_ADD(var, val) RUBY_ATOMIC_FETCH_ADD(var, val)
+#define ATOMIC_FETCH_SUB(var, val) RUBY_ATOMIC_FETCH_SUB(var, val)
+#define ATOMIC_INC(var) RUBY_ATOMIC_INC(var)
+#define ATOMIC_OR(var, val) RUBY_ATOMIC_OR(var, val)
+#define ATOMIC_PTR_CAS(var, oldval, newval) RUBY_ATOMIC_PTR_CAS(var, oldval, newval)
+#define ATOMIC_PTR_EXCHANGE(var, val) RUBY_ATOMIC_PTR_EXCHANGE(var, val)
+#define ATOMIC_SET(var, val) RUBY_ATOMIC_SET(var, val)
+#define ATOMIC_SIZE_ADD(var, val) RUBY_ATOMIC_SIZE_ADD(var, val)
+#define ATOMIC_SIZE_CAS(var, oldval, newval) RUBY_ATOMIC_SIZE_CAS(var, oldval, newval)
+#define ATOMIC_SIZE_DEC(var) RUBY_ATOMIC_SIZE_DEC(var)
+#define ATOMIC_SIZE_EXCHANGE(var, val) RUBY_ATOMIC_SIZE_EXCHANGE(var, val)
+#define ATOMIC_SIZE_INC(var) RUBY_ATOMIC_SIZE_INC(var)
+#define ATOMIC_SIZE_SUB(var, val) RUBY_ATOMIC_SIZE_SUB(var, val)
+#define ATOMIC_SUB(var, val) RUBY_ATOMIC_SUB(var, val)
+#define ATOMIC_VALUE_CAS(var, oldval, val) RUBY_ATOMIC_VALUE_CAS(var, oldval, val)
+#define ATOMIC_VALUE_EXCHANGE(var, val) RUBY_ATOMIC_VALUE_EXCHANGE(var, val)
diff --git a/safe.c b/safe.c
deleted file mode 100644
index a6b4905337..0000000000
--- a/safe.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/**********************************************************************
-
- safe.c -
-
- $Author$
- created at: Tue Sep 23 09:44:32 JST 2008
-
- Copyright (C) 2008 Yukihiro Matsumoto
-
-**********************************************************************/
-
-#define SAFE_LEVEL_MAX RUBY_SAFE_LEVEL_MAX
-
-#include "ruby/ruby.h"
-#include "vm_core.h"
-
-/* $SAFE accessor */
-
-#undef rb_secure
-#undef rb_set_safe_level
-#undef ruby_safe_level_2_warning
-
-int
-ruby_safe_level_2_warning(void)
-{
- rb_warn("rb_safe_level_2_warning will be removed in Ruby 3.0");
- return 2;
-}
-
-int
-rb_safe_level(void)
-{
- rb_warn("rb_safe_level will be removed in Ruby 3.0");
- return GET_VM()->safe_level_;
-}
-
-void
-rb_set_safe_level_force(int safe)
-{
- rb_warn("rb_set_safe_level_force will be removed in Ruby 3.0");
- GET_VM()->safe_level_ = safe;
-}
-
-void
-rb_set_safe_level(int level)
-{
- rb_vm_t *vm = GET_VM();
-
- rb_warn("rb_set_safe_level will be removed in Ruby 3.0");
- if (level > SAFE_LEVEL_MAX) {
- rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete");
- }
- else if (level < 0) {
- rb_raise(rb_eArgError, "$SAFE should be >= 0");
- }
- else {
- int line;
- const char *path = rb_source_location_cstr(&line);
-
- if (0) fprintf(stderr, "%s:%d $SAFE %d -> %d\n",
- path ? path : "-", line, vm->safe_level_, level);
-
- vm->safe_level_ = level;
- }
-}
-
-static VALUE
-safe_getter(ID _x, VALUE *_y)
-{
- rb_warn("$SAFE will become a normal global variable in Ruby 3.0");
- return INT2NUM(GET_VM()->safe_level_);
-}
-
-static void
-safe_setter(VALUE val, ID _x, VALUE *_y)
-{
- int level = NUM2INT(val);
- rb_vm_t *vm = GET_VM();
-
- rb_warn("$SAFE will become a normal global variable in Ruby 3.0");
- if (level > SAFE_LEVEL_MAX) {
- rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete");
- }
- else if (level < 0) {
- rb_raise(rb_eArgError, "$SAFE should be >= 0");
- }
- else {
- int line;
- const char *path = rb_source_location_cstr(&line);
-
- if (0) fprintf(stderr, "%s:%d $SAFE %d -> %d\n",
- path ? path : "-", line, vm->safe_level_, level);
-
- vm->safe_level_ = level;
- }
-}
-
-void
-rb_secure(int level)
-{
- rb_warn("rb_secure will be removed in Ruby 3.0");
- if (level <= GET_VM()->safe_level_) {
- ID caller_name = rb_frame_callee();
- if (caller_name) {
- rb_raise(rb_eSecurityError, "Insecure operation `%"PRIsVALUE"' at level %d",
- rb_id2str(caller_name), GET_VM()->safe_level_);
- }
- else {
- rb_raise(rb_eSecurityError, "Insecure operation at level %d",
- GET_VM()->safe_level_);
- }
- }
-}
-
-void
-rb_secure_update(VALUE obj)
-{
- rb_warn("rb_secure_update will be removed in Ruby 3.0");
-}
-
-void
-rb_insecure_operation(void)
-{
- rb_warn("rb_insecure_operation will be removed in Ruby 3.0");
- ID caller_name = rb_frame_callee();
- if (caller_name) {
- rb_raise(rb_eSecurityError, "Insecure operation - %"PRIsVALUE,
- rb_id2str(caller_name));
- }
- else {
- rb_raise(rb_eSecurityError, "Insecure operation: -r");
- }
-}
-
-void
-rb_check_safe_obj(VALUE x)
-{
- rb_warn("rb_check_safe_obj will be removed in Ruby 3.0");
-}
-
-void
-Init_safe(void)
-{
- rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
-}
diff --git a/sample/drb/name.rb b/sample/drb/name.rb
index a8ad28749d..6d88186dab 100644
--- a/sample/drb/name.rb
+++ b/sample/drb/name.rb
@@ -39,11 +39,12 @@ require 'drb/drb'
module DRbNamedObject
DRbNAMEDICT = {}
+ DRBNAMEMUTEX = Thread::Mutex.new
attr_reader(:drb_name)
def drb_name=(name)
@drb_name = name
- Thread.exclusive do
+ DRBNAMEMUTEX.synchronize do
raise(IndexError, name) if DRbNAMEDICT[name]
DRbNAMEDICT[name] = self
end
diff --git a/sample/list.rb b/sample/list.rb
index b4d1d653e4..7458ba0244 100644
--- a/sample/list.rb
+++ b/sample/list.rb
@@ -5,7 +5,6 @@ class MyElem
# @variables are instance variable, no declaration needed
@data = item
@succ = nil
- @head = nil
end
def data
@@ -23,6 +22,10 @@ class MyElem
end
class MyList
+ def initialize
+ @head = nil
+ end
+
def add_to_list(obj)
elt = MyElem.new(obj)
if @head
diff --git a/sample/openssl/c_rehash.rb b/sample/openssl/c_rehash.rb
index cd6c9d5fd4..8282816b9d 100644
--- a/sample/openssl/c_rehash.rb
+++ b/sample/openssl/c_rehash.rb
@@ -161,7 +161,7 @@ private
end
def fingerprint(der)
- Digest::MD5.hexdigest(der).upcase
+ Digest.hexdigest('MD5', der).upcase
end
end
diff --git a/sample/openssl/echo_svr.rb b/sample/openssl/echo_svr.rb
index 719de6be84..ba15394e6f 100644
--- a/sample/openssl/echo_svr.rb
+++ b/sample/openssl/echo_svr.rb
@@ -37,7 +37,7 @@ else
ef.issuer_certificate = cert
cert.add_extension ef.create_extension("authorityKeyIdentifier",
"keyid:always,issuer:always")
- cert.sign(key, OpenSSL::Digest::SHA1.new)
+ cert.sign(key, OpenSSL::Digest.new('SHA1'))
end
ctx = OpenSSL::SSL::SSLContext.new()
diff --git a/sample/openssl/gen_csr.rb b/sample/openssl/gen_csr.rb
index 4228707fdb..a061260cd7 100644
--- a/sample/openssl/gen_csr.rb
+++ b/sample/openssl/gen_csr.rb
@@ -41,7 +41,7 @@ req = X509::Request.new
req.version = 0
req.subject = name
req.public_key = keypair.public_key
-req.sign(keypair, Digest::MD5.new)
+req.sign(keypair, Digest.new('MD5'))
puts "Writing #{csrout}..."
File.open(csrout, "w") do |f|
diff --git a/sample/trick2013/mame/remarks.markdown b/sample/trick2013/mame/remarks.markdown
index 8c1988c809..488681d88d 100644
--- a/sample/trick2013/mame/remarks.markdown
+++ b/sample/trick2013/mame/remarks.markdown
@@ -27,7 +27,7 @@ In the piano roll, `#` represents a pin that hits a note, and `|` represents a s
The leftmost column corresponds 110Hz (low A).
Every column corresponds a semitone higher than the left one.
-This program uses [the frequency modulation synthesis](http://en.wikipedia.org/wiki/Frequency_modulation_synthesis) to play the sound like a music-box.
+This program uses [the frequency modulation synthesis](https://en.wikipedia.org/wiki/Frequency_modulation_synthesis) to play the sound like a music-box.
You can create a different-sounding tone by changing the parameter.
For example, the following will play the sound like a harpsichord.
@@ -44,4 +44,4 @@ You have to use sox by replacing the following part:
with:
- IO.popen("./pl","wb") \ No newline at end of file
+ IO.popen("./pl","wb")
diff --git a/sample/trick2015/kinaba/entry.rb b/sample/trick2015/kinaba/entry.rb
index 18923a6a9f..aa077dc240 100644
--- a/sample/trick2015/kinaba/entry.rb
+++ b/sample/trick2015/kinaba/entry.rb
@@ -62,7 +62,7 @@ while 0x00012345 >= $counter
TrueClass
Dir
Encoding
- Data
+ Proc
Hash
Method
Enumerator
diff --git a/sample/webrick/demo-app.rb b/sample/webrick/demo-app.rb
deleted file mode 100644
index c7a2a0a6a4..0000000000
--- a/sample/webrick/demo-app.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-require "pp"
-
-module DemoApplication
- def initialize(config, enctype)
- super
- @enctype = enctype
- end
-
- def do_GET(req, res)
- if req.path_info != "/"
- res.set_redirect(WEBrick::HTTPStatus::Found, req.script_name + "/")
- end
- res.body =<<-_end_of_html_
- <HTML>
- <FORM method="POST" enctype=#{@enctype}>
- text: <INPUT type="text" name="text"><BR>
- file: <INPUT type="file" name="file"><BR>
- check:
- <INPUT type="checkbox" name="check" value="a">a,
- <INPUT type="checkbox" name="check" value="b">b,
- <INPUT type="checkbox" name="check" value="c">c,
- <BR>
- <INPUT type="submit">
- </FORM>
- </HTML>
- _end_of_html_
- res['content-type'] = 'text/html; charset=iso-8859-1'
- end
-
- def do_POST(req, res)
- if req["content-length"].to_i > 1024*10
- raise WEBrick::HTTPStatus::Forbidden, "file size too large"
- end
- res.body =<<-_end_of_html_
- <HTML>
- <H2>Query Parameters</H2>
- #{display_query(req.query)}
- <A href="#{req.path}">return</A>
- <H2>Request</H2>
- <PRE>#{WEBrick::HTMLUtils::escape(PP::pp(req, "", 80))}</PRE>
- <H2>Response</H2>
- <PRE>#{WEBrick::HTMLUtils::escape(PP::pp(res, "", 80))}</PRE>
- </HTML>
- _end_of_html_
- res['content-type'] = 'text/html; charset=iso-8859-1'
- end
-
- private
-
- def display_query(q)
- ret = ""
- q.each{|key, val|
- ret << "<H3>#{WEBrick::HTMLUtils::escape(key)}</H3>"
- ret << "<TABLE border=1>"
- ret << make_tr("val", val.inspect)
- ret << make_tr("val.to_a", val.to_a.inspect)
- ret << make_tr("val.to_ary", val.to_ary.inspect)
- ret << "</TABLE>"
- }
- ret
- end
-
- def make_tr(arg0, arg1)
- "<TR><TD>#{arg0}</TD><TD>#{WEBrick::HTMLUtils::escape(arg1)}</TD></TR>"
- end
-end
diff --git a/sample/webrick/demo-multipart.cgi b/sample/webrick/demo-multipart.cgi
deleted file mode 100644
index 0893fadadf..0000000000
--- a/sample/webrick/demo-multipart.cgi
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env ruby
-require "webrick/cgi"
-require "webrick/https" # should load if it runs on HTTPS server
-require "./demo-app"
-
-class DemoCGI < WEBrick::CGI
- include DemoApplication
-end
-
-config = { :NPH => false }
-cgi = DemoCGI.new(config, "multipart/form-data")
-cgi.start
diff --git a/sample/webrick/demo-servlet.rb b/sample/webrick/demo-servlet.rb
deleted file mode 100644
index 9c18cc65d1..0000000000
--- a/sample/webrick/demo-servlet.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require "webrick"
-require "./demo-app"
-
-class DemoServlet < WEBrick::HTTPServlet::AbstractServlet
- include DemoApplication
-end
diff --git a/sample/webrick/demo-urlencoded.cgi b/sample/webrick/demo-urlencoded.cgi
deleted file mode 100644
index e4706f8b59..0000000000
--- a/sample/webrick/demo-urlencoded.cgi
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env ruby
-require "webrick/cgi"
-require "webrick/https" # should load if it runs on HTTPS server
-require "./demo-app"
-
-class DemoCGI < WEBrick::CGI
- include DemoApplication
-end
-
-config = { :NPH => false }
-cgi = DemoCGI.new(config, "application/x-www-form-urlencoded")
-cgi.start
diff --git a/sample/webrick/hello.cgi b/sample/webrick/hello.cgi
deleted file mode 100644
index 35d2240df0..0000000000
--- a/sample/webrick/hello.cgi
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env ruby
-require "webrick/cgi"
-
-class HelloCGI < WEBrick::CGI
- def do_GET(req, res)
- res["content-type"] = "text/plain"
- res.body = "Hello, world.\n"
- end
-end
-
-HelloCGI.new.start
diff --git a/sample/webrick/hello.rb b/sample/webrick/hello.rb
deleted file mode 100644
index 4d02676818..0000000000
--- a/sample/webrick/hello.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-require "webrick"
-
-class HelloServlet < WEBrick::HTTPServlet::AbstractServlet
- def do_GET(req, res)
- res["content-type"] = "text/plain"
- res.body = "Hello, world.\n"
- end
-end
diff --git a/sample/webrick/httpd.rb b/sample/webrick/httpd.rb
deleted file mode 100644
index b0edf47582..0000000000
--- a/sample/webrick/httpd.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require "webrick"
-
-httpd = WEBrick::HTTPServer.new(
- :DocumentRoot => File::dirname(__FILE__),
- :Port => 10080,
- :Logger => WEBrick::Log.new($stderr, WEBrick::Log::DEBUG),
- :AccessLog => [
- [ $stderr, WEBrick::AccessLog::COMMON_LOG_FORMAT ],
- [ $stderr, WEBrick::AccessLog::REFERER_LOG_FORMAT ],
- [ $stderr, WEBrick::AccessLog::AGENT_LOG_FORMAT ],
- ],
- :CGIPathEnv => ENV["PATH"] # PATH environment variable for CGI.
-)
-
-require "./hello"
-httpd.mount("/hello", HelloServlet)
-
-require "./demo-servlet"
-httpd.mount("/urlencoded", DemoServlet, "application/x-www-form-urlencoded")
-httpd.mount("/multipart", DemoServlet, "multipart/form-data")
-
-trap(:INT){ httpd.shutdown }
-httpd.start
diff --git a/sample/webrick/httpproxy.rb b/sample/webrick/httpproxy.rb
deleted file mode 100644
index c84457ece7..0000000000
--- a/sample/webrick/httpproxy.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-require "webrick"
-require "webrick/httpproxy"
-
-# The :ProxyContentHandler proc will be invoked before sending a response to
-# the User-Agent. You can inspect the pair of request and response messages
-# (or edit the response message if necessary).
-
-pch = Proc.new{|req, res|
- p [ req.request_line, res.status_line ]
-}
-
-def upstream_proxy
- if prx = ENV["http_proxy"]
- return URI.parse(prx)
- end
- return nil
-end
-
-httpd = WEBrick::HTTPProxyServer.new(
- :Port => 10080,
- :ProxyContentHandler => pch,
- :ProxyURI => upstream_proxy
-)
-Signal.trap(:INT){ httpd.shutdown }
-httpd.start
diff --git a/sample/webrick/httpsd.rb b/sample/webrick/httpsd.rb
deleted file mode 100644
index a120782c3c..0000000000
--- a/sample/webrick/httpsd.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require "webrick"
-require "webrick/https"
-
-hostname = WEBrick::Utils::getservername
-subject = [["O", "ruby-lang.org"], ["OU", "sample"], ["CN", hostname]]
-comment = "Comment for self-signed certificate"
-
-httpd = WEBrick::HTTPServer.new(
- :DocumentRoot => File::dirname(__FILE__),
- :Port => 10443,
- :SSLEnable => true,
-
- # Specify key pair and server certificate.
- # :SSLPrivateKey => OpenSSL::PKey::RSA.new(File.read("server.key")),
- # :SSLCertificate => OpenSSL::X509::Certificate.new(File.read("server.crt")),
-
- # specify the following SSL options if you want to use auto
- # generated self-signed certificate.
- :SSLCertName => subject,
- :SSLComment => comment,
-
- :CGIPathEnv => ENV["PATH"] # PATH environment variable for CGI.
-)
-
-require "./hello"
-httpd.mount("/hello", HelloServlet)
-
-require "./demo-servlet"
-httpd.mount("/urlencoded", DemoServlet, "application/x-www-form-urlencoded")
-httpd.mount("/multipart", DemoServlet, "multipart/form-data")
-
-trap(:INT){ httpd.shutdown }
-httpd.start
diff --git a/scheduler.c b/scheduler.c
new file mode 100644
index 0000000000..66cbfc6f10
--- /dev/null
+++ b/scheduler.c
@@ -0,0 +1,212 @@
+/**********************************************************************
+
+ scheduler.c
+
+ $Author$
+
+ Copyright (C) 2020 Samuel Grant Dawson Williams
+
+**********************************************************************/
+
+#include "vm_core.h"
+#include "internal/scheduler.h"
+#include "ruby/io.h"
+
+static ID id_close;
+
+static ID id_block;
+static ID id_unblock;
+
+static ID id_kernel_sleep;
+static ID id_process_wait;
+
+static ID id_io_read;
+static ID id_io_write;
+static ID id_io_wait;
+
+void
+Init_Scheduler(void)
+{
+ id_close = rb_intern_const("close");
+
+ id_block = rb_intern_const("block");
+ id_unblock = rb_intern_const("unblock");
+
+ id_kernel_sleep = rb_intern_const("kernel_sleep");
+ id_process_wait = rb_intern_const("process_wait");
+
+ id_io_read = rb_intern_const("io_read");
+ id_io_write = rb_intern_const("io_write");
+ id_io_wait = rb_intern_const("io_wait");
+}
+
+VALUE
+rb_scheduler_get(void)
+{
+ rb_thread_t *thread = GET_THREAD();
+ VM_ASSERT(thread);
+
+ return thread->scheduler;
+}
+
+static void
+verify_interface(VALUE scheduler)
+{
+ if (!rb_respond_to(scheduler, id_block)) {
+ rb_raise(rb_eArgError, "Scheduler must implement #block!");
+ }
+
+ if (!rb_respond_to(scheduler, id_unblock)) {
+ rb_raise(rb_eArgError, "Scheduler must implement #unblock!");
+ }
+
+ if (!rb_respond_to(scheduler, id_kernel_sleep)) {
+ rb_raise(rb_eArgError, "Scheduler must implement #kernel_sleep!");
+ }
+
+ if (!rb_respond_to(scheduler, id_io_wait)) {
+ rb_raise(rb_eArgError, "Scheduler must implement #io_wait!");
+ }
+}
+
+VALUE
+rb_scheduler_set(VALUE scheduler)
+{
+ rb_thread_t *thread = GET_THREAD();
+ VM_ASSERT(thread);
+
+ if (scheduler != Qnil) {
+ verify_interface(scheduler);
+ }
+
+ // We invoke Scheduler#close when setting it to something else, to ensure the previous scheduler runs to completion before changing the scheduler. That way, we do not need to consider interactions, e.g., of a Fiber from the previous scheduler with the new scheduler.
+ if (thread->scheduler != Qnil) {
+ rb_scheduler_close(thread->scheduler);
+ }
+
+ thread->scheduler = scheduler;
+
+ return thread->scheduler;
+}
+
+static VALUE
+rb_threadptr_scheduler_current(rb_thread_t *thread)
+{
+ VM_ASSERT(thread);
+
+ if (thread->blocking == 0) {
+ return thread->scheduler;
+ } else {
+ return Qnil;
+ }
+}
+
+VALUE
+rb_scheduler_current(void)
+{
+ return rb_threadptr_scheduler_current(GET_THREAD());
+}
+
+VALUE rb_thread_scheduler_current(VALUE thread)
+{
+ return rb_threadptr_scheduler_current(rb_thread_ptr(thread));
+}
+
+VALUE
+rb_scheduler_close(VALUE scheduler)
+{
+ if (rb_respond_to(scheduler, id_close)) {
+ return rb_funcall(scheduler, id_close, 0);
+ }
+
+ return Qnil;
+}
+
+VALUE
+rb_scheduler_timeout(struct timeval *timeout)
+{
+ if (timeout) {
+ return rb_float_new((double)timeout->tv_sec + (0.000001f * timeout->tv_usec));
+ }
+
+ return Qnil;
+}
+
+VALUE
+rb_scheduler_kernel_sleep(VALUE scheduler, VALUE timeout)
+{
+ return rb_funcall(scheduler, id_kernel_sleep, 1, timeout);
+}
+
+VALUE
+rb_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv)
+{
+ return rb_funcallv(scheduler, id_kernel_sleep, argc, argv);
+}
+
+int
+rb_scheduler_supports_process_wait(VALUE scheduler)
+{
+ return rb_respond_to(scheduler, id_process_wait);
+}
+
+VALUE
+rb_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags)
+{
+ return rb_funcall(scheduler, id_process_wait, 2, PIDT2NUM(pid), RB_INT2NUM(flags));
+}
+
+VALUE
+rb_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout)
+{
+ return rb_funcall(scheduler, id_block, 2, blocker, timeout);
+}
+
+VALUE
+rb_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber)
+{
+ return rb_funcall(scheduler, id_unblock, 2, blocker, fiber);
+}
+
+VALUE
+rb_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout)
+{
+ return rb_funcall(scheduler, id_io_wait, 3, io, events, timeout);
+}
+
+VALUE
+rb_scheduler_io_wait_readable(VALUE scheduler, VALUE io)
+{
+ return rb_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_READABLE), Qnil);
+}
+
+VALUE
+rb_scheduler_io_wait_writable(VALUE scheduler, VALUE io)
+{
+ return rb_scheduler_io_wait(scheduler, io, RB_UINT2NUM(RUBY_IO_WRITABLE), Qnil);
+}
+
+int
+rb_scheduler_supports_io_read(VALUE scheduler)
+{
+ return rb_respond_to(scheduler, id_io_read);
+}
+
+VALUE
+rb_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
+{
+ return rb_funcall(scheduler, id_io_read, 4, io, buffer, SIZET2NUM(offset), SIZET2NUM(length));
+}
+
+int
+rb_scheduler_supports_io_write(VALUE scheduler)
+{
+ return rb_respond_to(scheduler, id_io_write);
+}
+
+VALUE
+rb_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
+{
+ // We should ensure string has capacity to receive data, and then resize it afterwards.
+ return rb_funcall(scheduler, id_io_write, 4, io, buffer, SIZET2NUM(offset), SIZET2NUM(length));
+}
diff --git a/signal.c b/signal.c
index 68d68c54bf..c13bc19f1c 100644
--- a/signal.c
+++ b/signal.c
@@ -11,36 +11,40 @@
**********************************************************************/
-#include "internal.h"
-#include "vm_core.h"
+#include "ruby/internal/config.h"
+
+#include <errno.h>
#include <signal.h>
#include <stdio.h>
-#include <errno.h>
-#include "ruby_atomic.h"
-#include "eval_intern.h"
+
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
+
#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
+# include <sys/uio.h>
#endif
+
#ifdef HAVE_UCONTEXT_H
-#include <ucontext.h>
+# include <ucontext.h>
#endif
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-# include <valgrind/memcheck.h>
-# ifndef VALGRIND_MAKE_MEM_DEFINED
-# define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE((p), (n))
-# endif
-# ifndef VALGRIND_MAKE_MEM_UNDEFINED
-# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE((p), (n))
-# endif
-#else
-# define VALGRIND_MAKE_MEM_DEFINED(p, n) 0
-# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
+#if HAVE_PTHREAD_H
+# include <pthread.h>
#endif
+#include "debug_counter.h"
+#include "eval_intern.h"
+#include "internal.h"
+#include "internal/eval.h"
+#include "internal/sanitizers.h"
+#include "internal/signal.h"
+#include "internal/string.h"
+#include "internal/thread.h"
+#include "ruby_atomic.h"
+#include "vm_core.h"
+#include "ractor_core.h"
+
#ifdef NEED_RUBY_ATOMIC_OPS
rb_atomic_t
ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val)
@@ -240,23 +244,7 @@ signm2signo(VALUE *sig_ptr, int negative, int exit, int *prefix_ptr)
prefix += signame_prefix_len;
}
if (len <= (long)prefix) {
- unsupported:
- if (prefix == signame_prefix_len) {
- prefix = 0;
- }
- else if (prefix > signame_prefix_len) {
- prefix -= signame_prefix_len;
- len -= prefix;
- vsig = rb_str_subseq(vsig, prefix, len);
- prefix = 0;
- }
- else {
- len -= prefix;
- vsig = rb_str_subseq(vsig, prefix, len);
- prefix = signame_prefix_len;
- }
- rb_raise(rb_eArgError, "unsupported signal `%.*s%"PRIsVALUE"'",
- prefix, signame_prefix, vsig);
+ goto unsupported;
}
if (prefix_ptr) *prefix_ptr = prefix;
@@ -269,7 +257,25 @@ signm2signo(VALUE *sig_ptr, int negative, int exit, int *prefix_ptr)
return negative ? -sigs->signo : sigs->signo;
}
}
- goto unsupported;
+
+ unsupported:
+ if (prefix == signame_prefix_len) {
+ prefix = 0;
+ }
+ else if (prefix > signame_prefix_len) {
+ prefix -= signame_prefix_len;
+ len -= prefix;
+ vsig = rb_str_subseq(vsig, prefix, len);
+ prefix = 0;
+ }
+ else {
+ len -= prefix;
+ vsig = rb_str_subseq(vsig, prefix, len);
+ prefix = signame_prefix_len;
+ }
+ rb_raise(rb_eArgError, "unsupported signal `%.*s%"PRIsVALUE"'",
+ prefix, signame_prefix, vsig);
+ UNREACHABLE_RETURN(0);
}
static const char*
@@ -395,7 +401,6 @@ interrupt_init(int argc, VALUE *argv, VALUE self)
return rb_call_super(2, args);
}
-#include "debug_counter.h"
void rb_malloc_info_show_results(void); /* gc.c */
void
@@ -410,7 +415,7 @@ ruby_default_signal(int sig)
raise(sig);
}
-static RETSIGTYPE sighandler(int sig);
+static void sighandler(int sig);
static int signal_ignored(int sig);
static void signal_enque(int sig);
@@ -444,7 +449,7 @@ rb_f_kill(int argc, const VALUE *argv)
}
}
else {
- const rb_pid_t self = (GET_THREAD() == GET_VM()->main_thread) ? getpid() : -1;
+ const rb_pid_t self = (GET_THREAD() == GET_VM()->ractor.main_thread) ? getpid() : -1;
int wakeup = 0;
for (i=1; i<argc; i++) {
@@ -491,7 +496,7 @@ rb_f_kill(int argc, const VALUE *argv)
}
}
if (wakeup) {
- rb_threadptr_check_signal(GET_VM()->main_thread);
+ rb_threadptr_check_signal(GET_VM()->ractor.main_thread);
}
}
rb_thread_execute_interrupts(rb_thread_current());
@@ -514,17 +519,19 @@ typedef void ruby_sigaction_t(int, siginfo_t*, void*);
#define SIGINFO_ARG , siginfo_t *info, void *ctx
#define SIGINFO_CTX ctx
#else
-typedef RETSIGTYPE ruby_sigaction_t(int);
+typedef void ruby_sigaction_t(int);
#define SIGINFO_ARG
#define SIGINFO_CTX 0
#endif
#ifdef USE_SIGALTSTACK
+/* XXX: BSD_vfprintf() uses >1500B stack and x86-64 need >5KiB stack. */
+#define RUBY_SIGALTSTACK_SIZE (16*1024)
+
static int
rb_sigaltstack_size(void)
{
- /* XXX: BSD_vfprintf() uses >1500KiB stack and x86-64 need >5KiB stack. */
- int size = 16*1024;
+ int size = RUBY_SIGALTSTACK_SIZE;
#ifdef MINSIGSTKSZ
{
@@ -545,14 +552,28 @@ rb_sigaltstack_size(void)
return size;
}
+static int rb_sigaltstack_size_value = 0;
+
+void *
+rb_allocate_sigaltstack(void)
+{
+ void *altstack;
+ if (!rb_sigaltstack_size_value) {
+ rb_sigaltstack_size_value = rb_sigaltstack_size();
+ }
+ altstack = malloc(rb_sigaltstack_size_value);
+ if (!altstack) rb_memerror();
+ return altstack;
+}
+
/* alternate stack for SIGSEGV */
void *
-rb_register_sigaltstack(void)
+rb_register_sigaltstack(void *altstack)
{
stack_t newSS, oldSS;
- newSS.ss_size = rb_sigaltstack_size();
- newSS.ss_sp = xmalloc(newSS.ss_size);
+ newSS.ss_size = rb_sigaltstack_size_value;
+ newSS.ss_sp = altstack;
newSS.ss_flags = 0;
sigaltstack(&newSS, &oldSS); /* ignore error. */
@@ -694,7 +715,7 @@ static rb_atomic_t sigchld_hit;
# define GET_SIGCHLD_HIT() 0
#endif
-static RETSIGTYPE
+static void
sighandler(int sig)
{
int old_errnum = errno;
@@ -728,10 +749,6 @@ rb_signal_buff_size(void)
return signal_buff.size;
}
-#if HAVE_PTHREAD_H
-#include <pthread.h>
-#endif
-
static void
rb_disable_interrupt(void)
{
@@ -916,7 +933,7 @@ NOINLINE(static void check_reserved_signal_(const char *name, size_t name_len));
static sighandler_t default_sigbus_handler;
NORETURN(static ruby_sigaction_t sigbus);
-static RETSIGTYPE
+static void
sigbus(int sig SIGINFO_ARG)
{
check_reserved_signal("BUS");
@@ -938,7 +955,7 @@ sigbus(int sig SIGINFO_ARG)
static sighandler_t default_sigsegv_handler;
NORETURN(static ruby_sigaction_t sigsegv);
-static RETSIGTYPE
+static void
sigsegv(int sig SIGINFO_ARG)
{
check_reserved_signal("SEGV");
@@ -952,7 +969,7 @@ sigsegv(int sig SIGINFO_ARG)
static sighandler_t default_sigill_handler;
NORETURN(static ruby_sigaction_t sigill);
-static RETSIGTYPE
+static void
sigill(int sig SIGINFO_ARG)
{
check_reserved_signal("ILL");
@@ -1017,7 +1034,7 @@ check_reserved_signal_(const char *name, size_t name_len)
#endif
#if defined SIGPIPE || defined SIGSYS
-static RETSIGTYPE
+static void
sig_do_nothing(int sig)
{
}
@@ -1199,6 +1216,14 @@ trap_handler(VALUE *cmd, int sig)
*cmd = command;
RSTRING_GETMEM(command, cptr, len);
switch (len) {
+ sig_ign:
+ func = SIG_IGN;
+ *cmd = Qtrue;
+ break;
+ sig_dfl:
+ func = default_handler(sig);
+ *cmd = 0;
+ break;
case 0:
goto sig_ign;
break;
@@ -1213,14 +1238,10 @@ trap_handler(VALUE *cmd, int sig)
break;
case 7:
if (memcmp(cptr, "SIG_IGN", 7) == 0) {
-sig_ign:
- func = SIG_IGN;
- *cmd = Qtrue;
+ goto sig_ign;
}
else if (memcmp(cptr, "SIG_DFL", 7) == 0) {
-sig_dfl:
- func = default_handler(sig);
- *cmd = 0;
+ goto sig_dfl;
}
else if (memcmp(cptr, "DEFAULT", 7) == 0) {
goto sig_dfl;
@@ -1393,6 +1414,11 @@ sig_trap(int argc, VALUE *argv, VALUE _)
func = trap_handler(&cmd, sig);
}
+ if (rb_obj_is_proc(cmd) &&
+ !rb_ractor_main_p() && !rb_ractor_shareable_p(cmd)) {
+ cmd = rb_proc_isolate(cmd);
+ }
+
return trap(sig, func, cmd);
}
@@ -1563,7 +1589,7 @@ Init_signal(void)
force_install_sighandler(SIGILL, (sighandler_t)sigill, &default_sigill_handler);
#endif
#ifdef SIGSEGV
- RB_ALTSTACK_INIT(GET_VM()->main_altstack);
+ RB_ALTSTACK_INIT(GET_VM()->main_altstack, rb_allocate_sigaltstack());
force_install_sighandler(SIGSEGV, (sighandler_t)sigsegv, &default_sigsegv_handler);
#endif
}
diff --git a/spec/README.md b/spec/README.md
index 1b2e4d5f53..c67aedbb80 100644
--- a/spec/README.md
+++ b/spec/README.md
@@ -66,7 +66,7 @@ See `spec/ruby/CONTRIBUTING.md` for more documentation about guards.
To verify specs are compatible with older Ruby versions:
```
cd spec/ruby
-$RUBY_MANAGER use 2.4.6
+$RUBY_MANAGER use 2.4.9
../mspec/bin/mspec -j
```
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb
index 247838600b..b8191fe20f 100644
--- a/spec/bundler/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler/bundler_spec.rb
@@ -124,7 +124,15 @@ RSpec.describe Bundler do
describe "#which" do
let(:executable) { "executable" }
- let(:path) { %w[/a /b c ../d /e] }
+
+ let(:path) do
+ if Gem.win_platform?
+ %w[C:/a C:/b C:/c C:/../d C:/e]
+ else
+ %w[/a /b c ../d /e]
+ end
+ end
+
let(:expected) { "executable" }
before do
@@ -149,7 +157,13 @@ RSpec.describe Bundler do
it_behaves_like "it returns the correct executable"
context "when the executable in inside a quoted path" do
- let(:expected) { "/e/executable" }
+ let(:expected) do
+ if Gem.win_platform?
+ "C:/e/executable"
+ else
+ "/e/executable"
+ end
+ end
it_behaves_like "it returns the correct executable"
end
@@ -162,11 +176,9 @@ RSpec.describe Bundler do
describe "configuration" do
context "disable_shared_gems" do
it "should unset GEM_PATH with empty string" do
- env = {}
expect(Bundler).to receive(:use_system_gems?).and_return(false)
- Bundler.send(:configure_gem_path, env)
- expect(env.keys).to include("GEM_PATH")
- expect(env["GEM_PATH"]).to eq ""
+ Bundler.send(:configure_gem_path)
+ expect(ENV["GEM_PATH"]).to eq ""
end
end
end
@@ -196,6 +208,8 @@ EOF
gem "rack"
G
+ allow(Bundler).to receive(:root).and_return(bundled_app)
+
Bundler.mkdir_p(bundled_app.join("foo", "bar"))
expect(bundled_app.join("foo", "bar")).to exist
end
@@ -233,11 +247,8 @@ EOF
allow(Bundler.rubygems).to receive(:user_home).and_return(path)
allow(File).to receive(:directory?).with(path).and_return false
allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
- message = <<EOF
-`/home/oggy` is not a directory.
-Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
-EOF
- expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.ui).to receive(:warn).with("`/home/oggy` is not a directory.\n")
+ expect(Bundler.ui).to receive(:warn).with("Bundler will use `/tmp/trulyrandom' as your home directory temporarily.\n")
expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
end
end
@@ -252,11 +263,8 @@ EOF
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"))
- message = <<EOF
-`/home/oggy` is not writable.
-Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
-EOF
- expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.ui).to receive(:warn).with("`/home/oggy` is not writable.\n")
+ expect(Bundler.ui).to receive(:warn).with("Bundler will use `/tmp/trulyrandom' as your home directory temporarily.\n")
expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
end
@@ -277,11 +285,8 @@ EOF
it "should issue warning and return a temporary user home" do
allow(Bundler.rubygems).to receive(:user_home).and_return(nil)
allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
- message = <<EOF
-Your home directory is not set.
-Bundler will use `/tmp/trulyrandom' as your home directory temporarily.
-EOF
- expect(Bundler.ui).to receive(:warn).with(message)
+ expect(Bundler.ui).to receive(:warn).with("Your home directory is not set.\n")
+ expect(Bundler.ui).to receive(:warn).with("Bundler will use `/tmp/trulyrandom' as your home directory temporarily.\n")
expect(Bundler.user_home).to eq(Pathname("/tmp/trulyrandom"))
end
end
@@ -322,7 +327,7 @@ EOF
end
context "with unwritable files in a parent dir" do
- # Regression test for https://github.com/bundler/bundler/pull/6316
+ # Regression test for https://github.com/rubygems/bundler/pull/6316
# It doesn't matter if there are other unwritable files so long as
# bundle_path can be created
before do
diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb
index ddcd699d6c..c5de12c211 100644
--- a/spec/bundler/bundler/cli_spec.rb
+++ b/spec/bundler/bundler/cli_spec.rb
@@ -4,16 +4,18 @@ require "bundler/cli"
RSpec.describe "bundle executable" do
it "returns non-zero exit status when passed unrecognized options" do
- bundle "--invalid_argument"
- expect(exitstatus).to_not be_zero if exitstatus
+ bundle "--invalid_argument", :raise_on_error => false
+ expect(exitstatus).to_not be_zero
end
it "returns non-zero exit status when passed unrecognized task" do
- bundle "unrecognized-task"
- expect(exitstatus).to_not be_zero if exitstatus
+ bundle "unrecognized-task", :raise_on_error => false
+ expect(exitstatus).to_not be_zero
end
it "looks for a binary and executes it if it's named bundler-<task>" do
+ skip "Could not find command testtasks, probably because not a windows friendly executable" if Gem.win_platform?
+
File.open(tmp("bundler-testtasks"), "w", 0o755) do |f|
ruby = ENV["RUBY"] || "/usr/bin/env ruby"
f.puts "#!#{ruby}\nputs 'Hello, world'\n"
@@ -23,7 +25,6 @@ RSpec.describe "bundle executable" do
bundle "testtasks"
end
- expect(exitstatus).to be_zero if exitstatus
expect(out).to eq("Hello, world")
end
@@ -31,55 +32,63 @@ RSpec.describe "bundle executable" do
it "aliases e to exec" do
bundle "e --help"
- expect(out).to include("BUNDLE-EXEC")
+ expect(out_with_macos_man_workaround).to include("bundle-exec")
end
it "aliases ex to exec" do
bundle "ex --help"
- expect(out).to include("BUNDLE-EXEC")
+ expect(out_with_macos_man_workaround).to include("bundle-exec")
end
it "aliases exe to exec" do
bundle "exe --help"
- expect(out).to include("BUNDLE-EXEC")
+ expect(out_with_macos_man_workaround).to include("bundle-exec")
end
it "aliases c to check" do
bundle "c --help"
- expect(out).to include("BUNDLE-CHECK")
+ expect(out_with_macos_man_workaround).to include("bundle-check")
end
it "aliases i to install" do
bundle "i --help"
- expect(out).to include("BUNDLE-INSTALL")
+ expect(out_with_macos_man_workaround).to include("bundle-install")
end
it "aliases ls to list" do
bundle "ls --help"
- expect(out).to include("BUNDLE-LIST")
+ expect(out_with_macos_man_workaround).to include("bundle-list")
end
it "aliases package to cache" do
bundle "package --help"
- expect(out).to include("BUNDLE-CACHE")
+ expect(out_with_macos_man_workaround).to include("bundle-cache")
end
it "aliases pack to cache" do
bundle "pack --help"
- expect(out).to include("BUNDLE-CACHE")
+ expect(out_with_macos_man_workaround).to include("bundle-cache")
+ end
+
+ private
+
+ # Some `man` (e.g., on macOS) always highlights the output even to
+ # non-tty.
+ def out_with_macos_man_workaround
+ out.gsub(/.[\b]/, "")
end
end
context "with no arguments" do
it "prints a concise help message", :bundler => "3" do
- bundle! ""
+ bundle ""
expect(err).to be_empty
expect(out).to include("Bundler version #{Bundler::VERSION}").
and include("\n\nBundler commands:\n\n").
@@ -91,7 +100,7 @@ RSpec.describe "bundle executable" do
context "when ENV['BUNDLE_GEMFILE'] is set to an empty string" do
it "ignores it" do
- gemfile bundled_app("Gemfile"), <<-G
+ gemfile bundled_app_gemfile, <<-G
source "#{file_uri_for(gem_repo1)}"
gem 'rack'
G
@@ -102,54 +111,38 @@ RSpec.describe "bundle executable" do
end
end
- context "when ENV['RUBYGEMS_GEMDEPS'] is set" do
- it "displays a warning" do
- gemfile bundled_app("Gemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
- G
-
- bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "foo" }
- expect(err).to include("RUBYGEMS_GEMDEPS")
- expect(err).to include("conflict with Bundler")
-
- bundle :install, :env => { "RUBYGEMS_GEMDEPS" => "" }
- expect(err).not_to include("RUBYGEMS_GEMDEPS")
- end
- end
-
context "with --verbose" do
it "prints the running command" do
- gemfile ""
- bundle! "info bundler", :verbose => true
+ gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ bundle "info bundler", :verbose => true
expect(out).to start_with("Running `bundle info bundler --verbose` with bundler #{Bundler::VERSION}")
end
it "doesn't print defaults" do
- install_gemfile! "", :verbose => true
- expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}")
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"", :verbose => true
+ expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}")
end
it "doesn't print defaults" do
- install_gemfile! "", :verbose => true
- expect(out).to start_with("Running `bundle install --retry 0 --verbose` with bundler #{Bundler::VERSION}")
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"", :verbose => true
+ expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}")
end
end
describe "printing the outdated warning" do
shared_examples_for "no warning" do
it "prints no warning" do
- bundle "fail"
+ bundle "fail", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false
expect(last_command.stdboth).to eq("Could not find command \"fail\".")
end
end
- let(:bundler_version) { "1.1" }
+ let(:bundler_version) { "2.0" }
let(:latest_version) { nil }
before do
- bundle! "config set --global disable_version_check false"
+ bundle "config set --global disable_version_check false"
- simulate_bundler_version(bundler_version)
+ pristine_system_gems "bundler-#{bundler_version}"
if latest_version
info_path = home(".bundle/cache/compact_index/rubygems.org.443.29b0360b937aa4d161703e6160654e47/info/bundler")
info_path.parent.mkpath
@@ -174,7 +167,7 @@ RSpec.describe "bundle executable" do
context "when the latest version is greater than the current version" do
let(:latest_version) { "222.0" }
it "prints the version warning" do
- bundle "fail"
+ bundle "fail", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false
expect(err).to start_with(<<-EOS.strip)
The latest bundler is #{latest_version}, but you are currently running #{bundler_version}.
To install the latest version, run `gem install bundler`
@@ -182,16 +175,16 @@ To install the latest version, run `gem install bundler`
end
context "and disable_version_check is set" do
- before { bundle! "config set disable_version_check true" }
+ before { bundle "config set disable_version_check true", :env => { "BUNDLER_VERSION" => bundler_version } }
include_examples "no warning"
end
context "running a parseable command" do
it "prints no warning" do
- bundle! "config get --parseable foo"
+ bundle "config get --parseable foo", :env => { "BUNDLER_VERSION" => bundler_version }
expect(last_command.stdboth).to eq ""
- bundle "platform --ruby"
+ bundle "platform --ruby", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false
expect(last_command.stdboth).to eq "Could not locate Gemfile"
end
end
@@ -199,7 +192,7 @@ To install the latest version, run `gem install bundler`
context "and is a pre-release" do
let(:latest_version) { "222.0.0.pre.4" }
it "prints the version warning" do
- bundle "fail"
+ bundle "fail", :env => { "BUNDLER_VERSION" => bundler_version }, :raise_on_error => false
expect(err).to start_with(<<-EOS.strip)
The latest bundler is #{latest_version}, but you are currently running #{bundler_version}.
To install the latest version, run `gem install bundler --pre`
diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb
index fd554a7b0d..fe417e3920 100644
--- a/spec/bundler/bundler/compact_index_client/updater_spec.rb
+++ b/spec/bundler/bundler/compact_index_client/updater_spec.rb
@@ -3,28 +3,24 @@
require "net/http"
require "bundler/compact_index_client"
require "bundler/compact_index_client/updater"
+require "tmpdir"
RSpec.describe Bundler::CompactIndexClient::Updater do
let(:fetcher) { double(:fetcher) }
- let(:local_path) { Pathname("/tmp/localpath") }
+ let(:local_path) { Pathname.new Dir.mktmpdir("localpath") }
let(:remote_path) { double(:remote_path) }
- subject(:updater) { described_class.new(fetcher) }
+ let!(:updater) { described_class.new(fetcher) }
context "when the ETag header is missing" do
- # Regression test for https://github.com/bundler/bundler/issues/5463
+ # Regression test for https://github.com/rubygems/bundler/issues/5463
+ let(:response) { double(:response, :body => "abc123") }
- let(:response) { double(:response, :body => "") }
-
- it "MisMatchedChecksumError is raised" do
- # Twice: #update retries on failure
- expect(response).to receive(:[]).with("Content-Encoding").twice { "" }
- expect(response).to receive(:[]).with("ETag").twice { nil }
- expect(fetcher).to receive(:call).twice { response }
+ it "treats the response as an update" do
+ expect(response).to receive(:[]).with("ETag") { nil }
+ expect(fetcher).to receive(:call) { response }
- expect do
- updater.update(local_path, remote_path)
- end.to raise_error(Bundler::CompactIndexClient::Updater::MisMatchedChecksumError)
+ updater.update(local_path, remote_path)
end
end
@@ -32,8 +28,7 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
let(:response) { double(:response, :body => "") }
it "raises HTTPError" do
- expect(response).to receive(:[]).with("Content-Encoding") { "gzip" }
- expect(fetcher).to receive(:call) { response }
+ expect(fetcher).to receive(:call).and_raise(Zlib::GzipFile::Error)
expect do
updater.update(local_path, remote_path)
@@ -41,15 +36,24 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
end
end
- context "when bundler doesn't have permissions on Dir.tmpdir" do
- let(:response) { double(:response, :body => "") }
+ context "when receiving non UTF-8 data and default internal encoding set to ASCII" do
+ let(:response) { double(:response, :body => "\x8B".b) }
- it "Errno::EACCES is raised" do
- allow(Dir).to receive(:mktmpdir) { raise Errno::EACCES }
+ it "works just fine" do
+ old_verbose = $VERBOSE
+ previous_internal_encoding = Encoding.default_internal
+
+ begin
+ $VERBOSE = false
+ Encoding.default_internal = "ASCII"
+ expect(response).to receive(:[]).with("ETag") { nil }
+ expect(fetcher).to receive(:call) { response }
- expect do
updater.update(local_path, remote_path)
- end.to raise_error(Bundler::PermissionError)
+ ensure
+ Encoding.default_internal = previous_internal_encoding
+ $VERBOSE = old_verbose
+ end
end
end
end
diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb
index 1f4c1a0807..cd70d77cba 100644
--- a/spec/bundler/bundler/definition_spec.rb
+++ b/spec/bundler/bundler/definition_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe Bundler::Definition do
end
describe "detects changes" do
- it "for a path gem with changes", :bundler => "< 3" do
+ it "for a path gem with changes" do
build_lib "foo", "1.0", :path => lib_path("foo")
install_gemfile <<-G
@@ -49,45 +49,7 @@ RSpec.describe Bundler::Definition do
bundle :install, :env => { "DEBUG" => "1" }
expect(out).to match(/re-resolving dependencies/)
- lockfile_should_be <<-G
- PATH
- remote: #{lib_path("foo")}
- specs:
- foo (1.0)
- rack (= 1.0)
-
- GEM
- remote: #{file_uri_for(gem_repo1)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "for a path gem with changes", :bundler => "3" do
- build_lib "foo", "1.0", :path => lib_path("foo")
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :path => "#{lib_path("foo")}"
- G
-
- build_lib "foo", "1.0", :path => lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
- end
-
- bundle :install, :env => { "DEBUG" => "1" }
-
- expect(out).to match(/re-resolving dependencies/)
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo")}
specs:
@@ -124,7 +86,7 @@ RSpec.describe Bundler::Definition do
bundle :check, :env => { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo")}
specs:
@@ -157,15 +119,14 @@ RSpec.describe Bundler::Definition do
bundle :check, :env => { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
only_java (1.1-java)
PLATFORMS
- java
- #{lockfile_platforms}
+ #{lockfile_platforms_for(["java"] + local_platforms)}
DEPENDENCIES
only_java
@@ -184,7 +145,7 @@ RSpec.describe Bundler::Definition do
bundle :check, :env => { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -210,10 +171,12 @@ RSpec.describe Bundler::Definition do
source "#{file_uri_for(gem_repo1)}"
gem "foo"
G
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
it "should get a locked specs list when updating all" do
- definition = Bundler::Definition.new(bundled_app("Gemfile.lock"), [], Bundler::SourceList.new, true)
+ definition = Bundler::Definition.new(bundled_app_lock, [], Bundler::SourceList.new, true)
locked_specs = definition.gem_version_promoter.locked_specs
expect(locked_specs.to_a.map(&:name)).to eq ["foo"]
expect(definition.instance_variable_get("@locked_specs").empty?).to eq true
@@ -230,7 +193,7 @@ RSpec.describe Bundler::Definition do
context "eager unlock" do
let(:source_list) do
Bundler::SourceList.new.tap do |source_list|
- source_list.global_rubygems_source = file_uri_for(gem_repo4)
+ source_list.add_global_rubygems_remote(file_uri_for(gem_repo4))
end
end
@@ -267,6 +230,8 @@ RSpec.describe Bundler::Definition do
BUNDLED WITH
1.13.0
L
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
it "should not eagerly unlock shared dependency with bundle install conservative updating behavior" do
@@ -275,7 +240,7 @@ RSpec.describe Bundler::Definition do
Bundler::Dependency.new("shared_owner_b", ">= 0")]
unlock_hash_for_bundle_install = {}
definition = Bundler::Definition.new(
- bundled_app("Gemfile.lock"),
+ bundled_app_lock,
updated_deps_in_gemfile,
source_list,
unlock_hash_for_bundle_install
@@ -289,10 +254,10 @@ RSpec.describe Bundler::Definition do
Bundler::Dependency.new("shared_owner_a", ">= 0"),
Bundler::Dependency.new("shared_owner_b", ">= 0")]
definition = Bundler::Definition.new(
- bundled_app("Gemfile.lock"),
+ bundled_app_lock,
updated_deps_in_gemfile,
source_list,
- :gems => ["shared_owner_a"], :lock_shared_dependencies => true
+ :gems => ["shared_owner_a"], :conservative => true
)
locked = definition.send(:converge_locked_specs).map(&:name)
expect(locked).to eq %w[isolated_dep isolated_owner shared_dep shared_owner_b]
@@ -302,33 +267,6 @@ RSpec.describe Bundler::Definition do
end
end
- describe "find_resolved_spec" do
- it "with no platform set in SpecSet" do
- ss = Bundler::SpecSet.new([build_stub_spec("a", "1.0"), build_stub_spec("b", "1.0")])
- dfn = Bundler::Definition.new(nil, [], mock_source_list, true)
- dfn.instance_variable_set("@specs", ss)
- found = dfn.find_resolved_spec(build_spec("a", "0.9", "ruby").first)
- expect(found.name).to eq "a"
- expect(found.version.to_s).to eq "1.0"
- end
- end
-
- describe "find_indexed_specs" do
- it "with no platform set in indexed specs" do
- index = Bundler::Index.new
- %w[1.0.0 1.0.1 1.1.0].each {|v| index << build_stub_spec("foo", v) }
-
- dfn = Bundler::Definition.new(nil, [], mock_source_list, true)
- dfn.instance_variable_set("@index", index)
- found = dfn.find_indexed_specs(build_spec("foo", "0.9", "ruby").first)
- expect(found.length).to eq 3
- end
- end
-
- def build_stub_spec(name, version)
- Bundler::StubSpecification.new(name, version, nil, nil)
- end
-
def mock_source_list
Class.new do
def all_sources
diff --git a/spec/bundler/bundler/dep_proxy_spec.rb b/spec/bundler/bundler/dep_proxy_spec.rb
index 0f8d6b1076..8d02a33725 100644
--- a/spec/bundler/bundler/dep_proxy_spec.rb
+++ b/spec/bundler/bundler/dep_proxy_spec.rb
@@ -2,10 +2,10 @@
RSpec.describe Bundler::DepProxy do
let(:dep) { Bundler::Dependency.new("rake", ">= 0") }
- subject { described_class.new(dep, Gem::Platform::RUBY) }
+ subject { described_class.get_proxy(dep, Gem::Platform::RUBY) }
let(:same) { subject }
- let(:other) { subject.dup }
- let(:different) { described_class.new(dep, Gem::Platform::JAVA) }
+ let(:other) { described_class.get_proxy(dep, Gem::Platform::RUBY) }
+ let(:different) { described_class.get_proxy(dep, Gem::Platform::JAVA) }
describe "#eql?" do
it { expect(subject.eql?(same)).to be true }
@@ -15,8 +15,18 @@ RSpec.describe Bundler::DepProxy do
it { expect(subject.eql?("foobar")).to be false }
end
- describe "#hash" do
- it { expect(subject.hash).to eq(same.hash) }
- it { expect(subject.hash).to eq(other.hash) }
+ describe "must use factory methods" do
+ it { expect { described_class.new(dep, Gem::Platform::RUBY) }.to raise_error NoMethodError }
+ it { expect { subject.dup }.to raise_error NoMethodError }
+ it { expect { subject.clone }.to raise_error NoMethodError }
+ end
+
+ describe "frozen" do
+ if Gem.ruby_version >= Gem::Version.new("2.5.0")
+ error = Object.const_get("FrozenError")
+ else
+ error = RuntimeError
+ end
+ it { expect { subject.instance_variable_set(:@__platform, {}) }.to raise_error error }
end
end
diff --git a/spec/bundler/bundler/digest_spec.rb b/spec/bundler/bundler/digest_spec.rb
new file mode 100644
index 0000000000..d6bb043fd0
--- /dev/null
+++ b/spec/bundler/bundler/digest_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require "digest"
+require "bundler/digest"
+
+RSpec.describe Bundler::Digest do
+ context "SHA1" do
+ subject { Bundler::Digest }
+ let(:stdlib) { ::Digest::SHA1 }
+
+ it "is compatible with stdlib" do
+ ["foo", "skfjsdlkfjsdf", "3924m", "ldskfj"].each do |payload|
+ expect(subject.sha1(payload)).to be == stdlib.hexdigest(payload)
+ end
+ end
+ end
+end
diff --git a/spec/bundler/bundler/dsl_spec.rb b/spec/bundler/bundler/dsl_spec.rb
index 40739a431b..a44a12924c 100644
--- a/spec/bundler/bundler/dsl_spec.rb
+++ b/spec/bundler/bundler/dsl_spec.rb
@@ -25,7 +25,46 @@ RSpec.describe Bundler::Dsl do
expect { subject.git_source(:example) }.to raise_error(Bundler::InvalidOption)
end
- context "default hosts", :bundler => "2" do
+ it "converts :github PR to URI using https" do
+ subject.gem("sparks", :github => "https://github.com/indirect/sparks/pull/5")
+ github_uri = "https://github.com/indirect/sparks.git"
+ expect(subject.dependencies.first.source.uri).to eq(github_uri)
+ expect(subject.dependencies.first.source.branch).to eq("refs/pull/5/head")
+ end
+
+ it "rejects :github PR URI with a branch, ref or tag" do
+ expect do
+ subject.gem("sparks", :github => "https://github.com/indirect/sparks/pull/5", :branch => "foo")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :branch option can't be used with `github: "https://github.com/indirect/sparks/pull/5"`),
+ )
+
+ expect do
+ subject.gem("sparks", :github => "https://github.com/indirect/sparks/pull/5", :ref => "foo")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :ref option can't be used with `github: "https://github.com/indirect/sparks/pull/5"`),
+ )
+
+ expect do
+ subject.gem("sparks", :github => "https://github.com/indirect/sparks/pull/5", :tag => "foo")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :tag option can't be used with `github: "https://github.com/indirect/sparks/pull/5"`),
+ )
+ end
+
+ it "rejects :github with :git" do
+ expect do
+ subject.gem("sparks", :github => "indirect/sparks", :git => "https://github.com/indirect/sparks.git")
+ end.to raise_error(
+ Bundler::GemfileError,
+ %(The :git option can't be used with `github: "indirect/sparks"`),
+ )
+ end
+
+ context "default hosts", :bundler => "< 3" do
it "converts :github to URI using https" do
subject.gem("sparks", :github => "indirect/sparks")
github_uri = "https://github.com/indirect/sparks.git"
@@ -63,16 +102,16 @@ RSpec.describe Bundler::Dsl do
end
end
- context "default git sources", :bundler => "3" do
- it "has none" do
- expect(subject.instance_variable_get(:@git_sources)).to eq({})
+ context "default git sources" do
+ it "has bitbucket, gist, and github" do
+ expect(subject.instance_variable_get(:@git_sources).keys.sort).to eq(%w[bitbucket gist github])
end
end
end
describe "#method_missing" do
it "raises an error for unknown DSL methods" do
- expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).
+ expect(Bundler).to receive(:read_file).with(source_root.join("Gemfile").to_s).
and_return("unknown")
error_msg = "There was an error parsing `Gemfile`: Undefined local variable or method `unknown' for Gemfile. Bundler cannot continue."
@@ -83,13 +122,13 @@ RSpec.describe Bundler::Dsl do
describe "#eval_gemfile" do
it "handles syntax errors with a useful message" do
- expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return("}")
+ expect(Bundler).to receive(:read_file).with(source_root.join("Gemfile").to_s).and_return("}")
expect { subject.eval_gemfile("Gemfile") }.
to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: (syntax error, unexpected tSTRING_DEND|(compile error - )?syntax error, unexpected '\}'). Bundler cannot continue./)
end
it "distinguishes syntax errors from evaluation errors" do
- expect(Bundler).to receive(:read_file).with(bundled_app("Gemfile").to_s).and_return(
+ expect(Bundler).to receive(:read_file).with(source_root.join("Gemfile").to_s).and_return(
"ruby '2.1.5', :engine => 'ruby', :engine_version => '1.2.4'"
)
expect { subject.eval_gemfile("Gemfile") }.
@@ -174,40 +213,6 @@ RSpec.describe Bundler::Dsl do
end
end
- describe "#gemspec" do
- let(:spec) do
- Gem::Specification.new do |gem|
- gem.name = "example"
- gem.platform = platform
- end
- end
-
- before do
- allow(Dir).to receive(:[]).and_return(["spec_path"])
- allow(Bundler).to receive(:load_gemspec).with("spec_path").and_return(spec)
- allow(Bundler).to receive(:default_gemfile).and_return(Pathname.new("./Gemfile"))
- end
-
- context "with a ruby platform" do
- let(:platform) { "ruby" }
-
- it "keeps track of the ruby platforms in the dependency" do
- subject.gemspec
- expect(subject.dependencies.last.platforms).to eq(Bundler::Dependency::REVERSE_PLATFORM_MAP[Gem::Platform::RUBY])
- end
- end
-
- context "with a jruby platform" do
- let(:platform) { "java" }
-
- it "keeps track of the jruby platforms in the dependency" do
- allow(Gem::Platform).to receive(:local).and_return(java)
- subject.gemspec
- expect(subject.dependencies.last.platforms).to eq(Bundler::Dependency::REVERSE_PLATFORM_MAP[Gem::Platform::JAVA])
- end
- end
- end
-
context "can bundle groups of gems with" do
# git "https://github.com/rails/rails.git" do
# gem "railties"
@@ -229,20 +234,7 @@ RSpec.describe Bundler::Dsl do
# gem 'spree_api'
# gem 'spree_backend'
# end
- describe "#github", :bundler => "< 3" do
- it "from github" do
- spree_gems = %w[spree_core spree_api spree_backend]
- subject.github "spree" do
- spree_gems.each {|spree_gem| subject.send :gem, spree_gem }
- end
-
- subject.dependencies.each do |d|
- expect(d.source.uri).to eq("https://github.com/spree/spree.git")
- end
- end
- end
-
- describe "#github", :bundler => "2" do
+ describe "#github" do
it "from github" do
spree_gems = %w[spree_core spree_api spree_backend]
subject.github "spree" do
@@ -254,23 +246,12 @@ RSpec.describe Bundler::Dsl do
end
end
end
-
- describe "#github", :bundler => "3" do
- it "from github" do
- expect do
- spree_gems = %w[spree_core spree_api spree_backend]
- subject.github "spree" do
- spree_gems.each {|spree_gem| subject.send :gem, spree_gem }
- end
- end.to raise_error(Bundler::DeprecatedError, /github method has been removed/)
- end
- end
end
describe "syntax errors" do
it "will raise a Bundler::GemfileError" do
gemfile "gem 'foo', :path => /unquoted/string/syntax/error"
- expect { Bundler::Dsl.evaluate(bundled_app("Gemfile"), nil, true) }.
+ expect { Bundler::Dsl.evaluate(bundled_app_gemfile, nil, true) }.
to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`:( compile error -)? unknown regexp options - trg.+ Bundler cannot continue./)
end
end
@@ -278,7 +259,7 @@ RSpec.describe Bundler::Dsl do
describe "Runtime errors" do
it "will raise a Bundler::GemfileError" do
gemfile "raise RuntimeError, 'foo'"
- expect { Bundler::Dsl.evaluate(bundled_app("Gemfile"), nil, true) }.
+ expect { Bundler::Dsl.evaluate(bundled_app_gemfile, nil, true) }.
to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: foo. Bundler cannot continue./i)
end
end
@@ -299,4 +280,21 @@ 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/env_spec.rb b/spec/bundler/bundler/env_spec.rb
index 7686fe386a..8cd59311b2 100644
--- a/spec/bundler/bundler/env_spec.rb
+++ b/spec/bundler/bundler/env_spec.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require "openssl"
require "bundler/settings"
RSpec.describe Bundler::Env do
@@ -34,6 +33,8 @@ RSpec.describe Bundler::Env do
end
it "prints user home" do
+ skip "needs to use a valid HOME" if Gem.win_platform? && RUBY_VERSION < "2.6.0"
+
with_clear_paths("HOME", "/a/b/c") do
out = described_class.report
expect(out).to include("User Home /a/b/c")
@@ -41,7 +42,11 @@ RSpec.describe Bundler::Env do
end
it "prints user path" do
+ skip "needs to use a valid HOME" if Gem.win_platform? && RUBY_VERSION < "2.6.0"
+
with_clear_paths("HOME", "/a/b/c") do
+ allow(File).to receive(:exist?)
+ allow(File).to receive(:exist?).with("/a/b/c/.gem").and_return(true)
out = described_class.report
expect(out).to include("User Path /a/b/c/.gem")
end
@@ -54,7 +59,7 @@ RSpec.describe Bundler::Env do
end
end
- private
+ private
def with_clear_paths(env_var, env_value)
old_env_var = ENV[env_var]
@@ -68,7 +73,7 @@ RSpec.describe Bundler::Env do
context "when there is a Gemfile and a lockfile and print_gemfile is true" do
before do
- gemfile "gem 'rack', '1.0.0'"
+ gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem 'rack', '1.0.0'"
lockfile <<-L
GEM
@@ -82,6 +87,8 @@ RSpec.describe Bundler::Env do
BUNDLED WITH
1.10.0
L
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
let(:output) { described_class.report(:print_gemfile => true) }
@@ -105,6 +112,34 @@ RSpec.describe Bundler::Env do
end
end
+ context "when there's bundler config with credentials" do
+ before do
+ bundle "config set https://localgemserver.test/ user:pass"
+ end
+
+ let(:output) { described_class.report(:print_gemfile => true) }
+
+ it "prints the config with redacted values" do
+ expect(output).to include("https://localgemserver.test")
+ expect(output).to include("user:[REDACTED]")
+ expect(output).to_not include("user:pass")
+ end
+ end
+
+ context "when there's bundler config with OAuth token credentials" do
+ before do
+ bundle "config set https://localgemserver.test/ api_token:x-oauth-basic"
+ end
+
+ let(:output) { described_class.report(:print_gemfile => true) }
+
+ it "prints the config with redacted values" do
+ expect(output).to include("https://localgemserver.test")
+ expect(output).to include("[REDACTED]:x-oauth-basic")
+ expect(output).to_not include("api_token:x-oauth-basic")
+ end
+ end
+
context "when Gemfile contains a gemspec and print_gemspecs is true" do
let(:gemspec) do
strip_whitespace(<<-GEMSPEC)
@@ -116,11 +151,13 @@ RSpec.describe Bundler::Env do
end
before do
- gemfile("gemspec")
+ gemfile("source \"#{file_uri_for(gem_repo1)}\"; gemspec")
File.open(bundled_app.join("foo.gemspec"), "wb") do |f|
f.write(gemspec)
end
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
it "prints the gemspec" do
@@ -133,13 +170,15 @@ RSpec.describe Bundler::Env do
context "when eval_gemfile is used" do
it "prints all gemfiles" do
- create_file "other/Gemfile-other", "gem 'rack'"
- create_file "other/Gemfile", "eval_gemfile 'Gemfile-other'"
- create_file "Gemfile-alt", <<-G
+ create_file bundled_app("other/Gemfile-other"), "gem 'rack'"
+ create_file bundled_app("other/Gemfile"), "eval_gemfile 'Gemfile-other'"
+ create_file bundled_app("Gemfile-alt"), <<-G
source "#{file_uri_for(gem_repo1)}"
eval_gemfile "other/Gemfile"
G
- gemfile "eval_gemfile #{File.expand_path("Gemfile-alt").dump}"
+ gemfile "eval_gemfile #{bundled_app("Gemfile-alt").to_s.dump}"
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app)
output = described_class.report(:print_gemspecs => true)
expect(output).to include(strip_whitespace(<<-ENV))
@@ -148,7 +187,7 @@ RSpec.describe Bundler::Env do
### Gemfile
```ruby
- eval_gemfile #{File.expand_path("Gemfile-alt").dump}
+ eval_gemfile #{bundled_app("Gemfile-alt").to_s.dump}
```
### Gemfile-alt
@@ -173,7 +212,7 @@ RSpec.describe Bundler::Env do
### Gemfile.lock
```
- <No #{bundled_app("Gemfile.lock")} found>
+ <No #{bundled_app_lock} found>
```
ENV
end
diff --git a/spec/bundler/bundler/fetcher/compact_index_spec.rb b/spec/bundler/bundler/fetcher/compact_index_spec.rb
index c9419d3eb1..00eb27edea 100644
--- a/spec/bundler/bundler/fetcher/compact_index_spec.rb
+++ b/spec/bundler/bundler/fetcher/compact_index_spec.rb
@@ -1,5 +1,8 @@
# frozen_string_literal: true
+# load CompactIndexClient upfront to prevent thread safety issues during parallel specs
+require "bundler/compact_index_client"
+
RSpec.describe Bundler::Fetcher::CompactIndex do
let(:downloader) { double(:downloader) }
let(:display_uri) { Bundler::URI("http://sampleuri.com") }
@@ -62,7 +65,7 @@ RSpec.describe Bundler::Fetcher::CompactIndex do
context "when FIPS-mode is active" do
before do
- allow(OpenSSL::Digest::MD5).to receive(:digest).
+ allow(OpenSSL::Digest).to receive(:digest).with("MD5", "").
and_raise(OpenSSL::Digest::DigestError)
end
diff --git a/spec/bundler/bundler/fetcher/downloader_spec.rb b/spec/bundler/bundler/fetcher/downloader_spec.rb
index ba8451d9fa..94a0993a54 100644
--- a/spec/bundler/bundler/fetcher/downloader_spec.rb
+++ b/spec/bundler/bundler/fetcher/downloader_spec.rb
@@ -83,6 +83,11 @@ 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
+ expect { subject.fetch(uri, options, counter) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
+ /`bundle config set --global www\.uri-to-fetch\.com username:password`.*`BUNDLE_WWW__URI___TO___FETCH__COM`/m)
+ end
+
context "when the there are credentials provided in the request" do
let(:uri) { Bundler::URI("http://user:password@www.uri-to-fetch.com") }
@@ -188,7 +193,7 @@ RSpec.describe Bundler::Fetcher::Downloader do
let(:message) { "undefined method 'undefined_method_call'" }
it "should raise the original NoMethodError" do
- expect { subject.request(uri, options) }.to raise_error(NoMethodError, "undefined method 'undefined_method_call'")
+ expect { subject.request(uri, options) }.to raise_error(NoMethodError, /undefined method 'undefined_method_call'/)
end
end
end
@@ -226,16 +231,7 @@ RSpec.describe Bundler::Fetcher::Downloader do
end
end
- context "when error message is about getaddrinfo issues" do
- let(:message) { "getaddrinfo: nodename nor servname provided for http://www.uri-to-fetch.com" }
-
- it "should raise a Bundler::Fetcher::NetworkDownError" do
- expect { subject.request(uri, options) }.to raise_error(Bundler::Fetcher::NetworkDownError,
- /Could not reach host www.uri-to-fetch.com/)
- end
- end
-
- context "when error message is about neither host down or getaddrinfo" do
+ context "when error message is not about host down" do
let(:message) { "other error about network" }
it "should raise a Bundler::HTTPError" do
diff --git a/spec/bundler/bundler/fetcher/index_spec.rb b/spec/bundler/bundler/fetcher/index_spec.rb
index 5ecd7d9e05..f0db07583c 100644
--- a/spec/bundler/bundler/fetcher/index_spec.rb
+++ b/spec/bundler/bundler/fetcher/index_spec.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require "rubygems/remote_fetcher"
+
RSpec.describe Bundler::Fetcher::Index do
let(:downloader) { nil }
let(:remote) { nil }
@@ -17,100 +19,81 @@ RSpec.describe Bundler::Fetcher::Index do
end
context "error handling" do
- shared_examples_for "the error is properly handled" do
- let(:remote_uri) { Bundler::URI("http://remote-uri.org") }
- before do
- allow(subject).to receive(:remote_uri).and_return(remote_uri)
- end
+ let(:remote_uri) { Bundler::URI("http://remote-uri.org") }
+ before do
+ allow(rubygems).to receive(:fetch_all_remote_specs) { raise Gem::RemoteFetcher::FetchError.new(error_message, display_uri) }
+ allow(subject).to receive(:remote_uri).and_return(remote_uri)
+ end
- context "when certificate verify failed" do
- let(:error_message) { "certificate verify failed" }
+ context "when certificate verify failed" do
+ let(:error_message) { "certificate verify failed" }
- it "should raise a Bundler::Fetcher::CertificateFailureError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::CertificateFailureError,
- %r{Could not verify the SSL certificate for http://sample_uri.com})
- end
+ it "should raise a Bundler::Fetcher::CertificateFailureError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::CertificateFailureError,
+ %r{Could not verify the SSL certificate for http://sample_uri.com})
end
+ end
- context "when a 401 response occurs" do
- let(:error_message) { "401" }
-
- before do
- allow(remote_uri).to receive(:userinfo).and_return(userinfo)
- end
-
- context "and there was userinfo" do
- let(:userinfo) { double(:userinfo) }
+ context "when a 401 response occurs" do
+ let(:error_message) { "401" }
- it "should raise a Bundler::Fetcher::BadAuthenticationError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError,
- %r{Bad username or password for http://remote-uri.org})
- end
- end
+ before do
+ allow(remote_uri).to receive(:userinfo).and_return(userinfo)
+ end
- context "and there was no userinfo" do
- let(:userinfo) { nil }
+ context "and there was userinfo" do
+ let(:userinfo) { double(:userinfo) }
- it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
- %r{Authentication is required for http://remote-uri.org})
- end
+ it "should raise a Bundler::Fetcher::BadAuthenticationError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError,
+ %r{Bad username or password for http://remote-uri.org})
end
end
- context "when a 403 response occurs" do
- let(:error_message) { "403" }
+ context "and there was no userinfo" do
+ let(:userinfo) { nil }
- before do
- allow(remote_uri).to receive(:userinfo).and_return(userinfo)
+ it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
+ %r{Authentication is required for http://remote-uri.org})
end
+ end
+ end
- context "and there was userinfo" do
- let(:userinfo) { double(:userinfo) }
+ context "when a 403 response occurs" do
+ let(:error_message) { "403" }
- it "should raise a Bundler::Fetcher::BadAuthenticationError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError,
- %r{Bad username or password for http://remote-uri.org})
- end
- end
+ before do
+ allow(remote_uri).to receive(:userinfo).and_return(userinfo)
+ end
- context "and there was no userinfo" do
- let(:userinfo) { nil }
+ context "and there was userinfo" do
+ let(:userinfo) { double(:userinfo) }
- it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
- %r{Authentication is required for http://remote-uri.org})
- end
+ it "should raise a Bundler::Fetcher::BadAuthenticationError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::BadAuthenticationError,
+ %r{Bad username or password for http://remote-uri.org})
end
end
- context "any other message is returned" do
- let(:error_message) { "You get an error, you get an error!" }
-
- before { allow(Bundler).to receive(:ui).and_return(double(:trace => nil)) }
+ context "and there was no userinfo" do
+ let(:userinfo) { nil }
- it "should raise a Bundler::HTTPError" do
- expect { subject.specs(gem_names) }.to raise_error(Bundler::HTTPError, "Could not fetch specs from http://sample_uri.com")
+ it "should raise a Bundler::Fetcher::AuthenticationRequiredError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::Fetcher::AuthenticationRequiredError,
+ %r{Authentication is required for http://remote-uri.org})
end
end
end
- context "when a Gem::RemoteFetcher::FetchError occurs" do
- before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise Gem::RemoteFetcher::FetchError.new(error_message, nil) } }
+ context "any other message is returned" do
+ let(:error_message) { "You get an error, you get an error!" }
- it_behaves_like "the error is properly handled"
- end
-
- context "when a OpenSSL::SSL::SSLError occurs" do
- before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise OpenSSL::SSL::SSLError.new(error_message) } }
-
- it_behaves_like "the error is properly handled"
- end
-
- context "when a Net::HTTPFatalError occurs" do
- before { allow(rubygems).to receive(:fetch_all_remote_specs) { raise Net::HTTPFatalError.new(error_message, 404) } }
+ before { allow(Bundler).to receive(:ui).and_return(double(:trace => nil)) }
- it_behaves_like "the error is properly handled"
+ it "should raise a Bundler::HTTPError" do
+ expect { subject.specs(gem_names) }.to raise_error(Bundler::HTTPError, "Could not fetch specs from http://sample_uri.com due to underlying error <You get an error, you get an error! (http://sample_uri.com)>")
+ end
end
end
end
diff --git a/spec/bundler/bundler/fetcher_spec.rb b/spec/bundler/bundler/fetcher_spec.rb
index 539179db43..256d342775 100644
--- a/spec/bundler/bundler/fetcher_spec.rb
+++ b/spec/bundler/bundler/fetcher_spec.rb
@@ -150,9 +150,10 @@ RSpec.describe Bundler::Fetcher do
end
it "from many CI" do
- with_env_vars("TRAVIS" => "foo", "CI_NAME" => "my_ci") do
+ with_env_vars("TRAVIS" => "foo", "GITLAB_CI" => "gitlab", "CI_NAME" => "my_ci") do
ci_part = fetcher.user_agent.split(" ").find {|x| x.start_with?("ci/") }
expect(ci_part).to match("travis")
+ expect(ci_part).to match("gitlab")
expect(ci_part).to match("my_ci")
end
end
diff --git a/spec/bundler/bundler/friendly_errors_spec.rb b/spec/bundler/bundler/friendly_errors_spec.rb
index e9189b0514..496191f891 100644
--- a/spec/bundler/bundler/friendly_errors_spec.rb
+++ b/spec/bundler/bundler/friendly_errors_spec.rb
@@ -7,13 +7,13 @@ require "cgi"
RSpec.describe Bundler, "friendly errors" do
context "with invalid YAML in .gemrc" do
before do
- File.open(Gem.configuration.config_file_name, "w") do |f|
+ File.open(home(".gemrc"), "w") do |f|
f.write "invalid: yaml: hah"
end
end
after do
- FileUtils.rm(Gem.configuration.config_file_name)
+ FileUtils.rm(home(".gemrc"))
end
it "reports a relevant friendly error message" do
@@ -25,7 +25,6 @@ RSpec.describe Bundler, "friendly errors" do
bundle :install, :env => { "DEBUG" => "true" }
expect(err).to include("Failed to load #{home(".gemrc")}")
- expect(exitstatus).to eq(0) if exitstatus
end
end
@@ -115,18 +114,12 @@ RSpec.describe Bundler, "friendly errors" do
context "LoadError" do
let(:error) { LoadError.new("cannot load such file -- openssl") }
- it "Bundler.ui receive error" do
- expect(Bundler.ui).to receive(:error).with("\nCould not load OpenSSL.")
- Bundler::FriendlyErrors.log_error(error)
- end
-
- it "Bundler.ui receive warn" do
- expect(Bundler.ui).to receive(:warn).with(any_args, :wrap => true)
- Bundler::FriendlyErrors.log_error(error)
+ before do
+ allow(error).to receive(:backtrace).and_return(["backtrace"])
end
- it "Bundler.ui receive trace" do
- expect(Bundler.ui).to receive(:trace).with(error)
+ it "Bundler.ui receive error" do
+ expect(Bundler.ui).to receive(:error).with("\nCould not load OpenSSL. LoadError: cannot load such file -- openssl\nbacktrace")
Bundler::FriendlyErrors.log_error(error)
end
end
@@ -200,9 +193,9 @@ RSpec.describe Bundler, "friendly errors" do
describe "#request_issue_report_for" do
it "calls relevant methods for Bundler.ui" do
- expect(Bundler.ui).to receive(:info)
- expect(Bundler.ui).to receive(:error)
- expect(Bundler.ui).to receive(:warn)
+ expect(Bundler.ui).not_to receive(:info)
+ expect(Bundler.ui).to receive(:error).exactly(3).times
+ expect(Bundler.ui).not_to receive(:warn)
Bundler::FriendlyErrors.request_issue_report_for(StandardError.new)
end
@@ -221,7 +214,7 @@ 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/bundler/bundler/search?q=Exception+message&type=Issues")
+ expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/rubygems/rubygems/search?q=Exception+message&type=Issues")
end
it "generates a search URL for only the first line of a multi-line exception message" do
@@ -230,7 +223,7 @@ First line of the exception message
Second line of the exception message
END
- expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/bundler/bundler/search?q=First+line+of+the+exception+message&type=Issues")
+ expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/rubygems/rubygems/search?q=First+line+of+the+exception+message&type=Issues")
end
it "generates the url without colons" do
@@ -239,7 +232,7 @@ 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/bundler/bundler/search?q=#{CGI.escape("Exception with colons ")}&type=Issues")
+ expect(issues_url).to eq("https://github.com/rubygems/rubygems/search?q=#{CGI.escape("Exception with colons ")}&type=Issues")
end
it "removes information after - for Errono::EACCES" do
@@ -249,7 +242,7 @@ END
allow(exception).to receive(:is_a?).with(Errno).and_return(true)
issues_url = Bundler::FriendlyErrors.issues_url(exception)
expect(issues_url).not_to include("/Users/foo/bar")
- expect(issues_url).to eq("https://github.com/bundler/bundler/search?q=#{CGI.escape("Errno EACCES Permission denied @ dir_s_mkdir ")}&type=Issues")
+ expect(issues_url).to eq("https://github.com/rubygems/rubygems/search?q=#{CGI.escape("Errno EACCES Permission denied @ dir_s_mkdir ")}&type=Issues")
end
end
end
diff --git a/spec/bundler/bundler/gem_helper_spec.rb b/spec/bundler/bundler/gem_helper_spec.rb
index 29e10d64f8..2c43719aa1 100644
--- a/spec/bundler/bundler/gem_helper_spec.rb
+++ b/spec/bundler/bundler/gem_helper_spec.rb
@@ -9,7 +9,8 @@ RSpec.describe Bundler::GemHelper do
let(:app_gemspec_path) { app_path.join("#{app_name}.gemspec") }
before(:each) do
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
+ global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__LINTER" => "false",
+ "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
bundle "gem #{app_name}"
prepare_gemspec(app_gemspec_path)
end
@@ -60,10 +61,16 @@ RSpec.describe Bundler::GemHelper do
mock_confirm_message message
end
+ def mock_checksum_message(name, version)
+ message = "#{name} #{version} checksum written to checksums/#{name}-#{version}.gem.sha512."
+ mock_confirm_message message
+ end
+
subject! { Bundler::GemHelper.new(app_path) }
let(:app_version) { "0.1.0" }
let(:app_gem_dir) { app_path.join("pkg") }
let(:app_gem_path) { app_gem_dir.join("#{app_name}-#{app_version}.gem") }
+ let(:app_sha_path) { app_path.join("checksums", "#{app_name}-#{app_version}.gem.sha512") }
let(:app_gemspec_content) { File.read(app_gemspec_path) }
before(:each) do
@@ -97,6 +104,7 @@ RSpec.describe Bundler::GemHelper do
context "before installation" do
it "raises an error with appropriate message" do
task_names.each do |name|
+ skip "Rake::FileTask '#{name}' exists" if File.exist?(name)
expect { Rake.application[name] }.
to raise_error(/^Don't know how to build task '#{name}'/)
end
@@ -138,6 +146,57 @@ RSpec.describe Bundler::GemHelper do
expect(app_gem_path).to exist
end
end
+
+ context "when building in the current working directory" do
+ it "creates .gem file" do
+ mock_build_message app_name, app_version
+ Dir.chdir app_path do
+ Bundler::GemHelper.new.build_gem
+ end
+ expect(app_gem_path).to exist
+ end
+ end
+
+ context "when building in a location relative to the current working directory" do
+ it "creates .gem file" do
+ mock_build_message app_name, app_version
+ Dir.chdir File.dirname(app_path) do
+ Bundler::GemHelper.new(File.basename(app_path)).build_gem
+ end
+ expect(app_gem_path).to exist
+ end
+ end
+ end
+
+ describe "#build_checksum" do
+ context "when build was successful" do
+ it "creates .sha512 file" do
+ mock_build_message app_name, app_version
+ mock_checksum_message app_name, app_version
+ subject.build_checksum
+ expect(app_sha_path).to exist
+ end
+ end
+ context "when building in the current working directory" do
+ it "creates a .sha512 file" do
+ mock_build_message app_name, app_version
+ mock_checksum_message app_name, app_version
+ Dir.chdir app_path do
+ Bundler::GemHelper.new.build_checksum
+ end
+ expect(app_sha_path).to exist
+ end
+ end
+ context "when building in a location relative to the current working directory" do
+ it "creates a .sha512 file" do
+ mock_build_message app_name, app_version
+ mock_checksum_message app_name, app_version
+ Dir.chdir File.dirname(app_path) do
+ Bundler::GemHelper.new(File.basename(app_path)).build_checksum
+ end
+ expect(app_sha_path).to exist
+ end
+ end
end
describe "#install_gem" do
@@ -147,7 +206,7 @@ RSpec.describe Bundler::GemHelper do
mock_confirm_message "#{app_name} (#{app_version}) installed."
subject.install_gem(nil, :local)
expect(app_gem_path).to exist
- gem_command! :list
+ gem_command :list
expect(out).to include("#{app_name} (#{app_version})")
end
end
@@ -160,7 +219,7 @@ RSpec.describe Bundler::GemHelper do
FileUtils.touch app_gem_path
app_gem_path
end
- expect { subject.install_gem }.to raise_error(/Couldn't install gem/)
+ expect { subject.install_gem }.to raise_error(/Running `#{gem_bin} install #{app_gem_path}` failed/)
end
end
end
@@ -178,13 +237,11 @@ RSpec.describe Bundler::GemHelper do
end
before do
- Dir.chdir(app_path) do
- `git init`
- `git config user.email "you@example.com"`
- `git config user.name "name"`
- `git config commit.gpgsign false`
- `git config push.default simple`
- end
+ sys_exec("git init", :dir => app_path)
+ sys_exec("git config user.email \"you@example.com\"", :dir => app_path)
+ sys_exec("git config user.name \"name\"", :dir => app_path)
+ sys_exec("git config commit.gpgsign false", :dir => app_path)
+ sys_exec("git config push.default simple", :dir => app_path)
# silence messages
allow(Bundler.ui).to receive(:confirm)
@@ -198,13 +255,13 @@ RSpec.describe Bundler::GemHelper do
end
it "when there are uncommitted files" do
- Dir.chdir(app_path) { `git add .` }
+ sys_exec("git add .", :dir => app_path)
expect { Rake.application["release"].invoke }.
to raise_error("There are files that need to be committed first.")
end
it "when there is no git remote" do
- Dir.chdir(app_path) { `git commit -a -m "initial commit"` }
+ sys_exec("git commit -a -m \"initial commit\"", :dir => app_path)
expect { Rake.application["release"].invoke }.to raise_error(RuntimeError)
end
end
@@ -213,19 +270,17 @@ RSpec.describe Bundler::GemHelper do
let(:repo) { build_git("foo", :bare => true) }
before do
- Dir.chdir(app_path) do
- sys_exec("git remote add origin #{file_uri_for(repo.path)}")
- sys_exec('git commit -a -m "initial commit"')
- end
+ sys_exec("git remote add origin #{file_uri_for(repo.path)}", :dir => app_path)
+ sys_exec('git commit -a -m "initial commit"', :dir => app_path)
end
context "on releasing" do
before do
mock_build_message app_name, app_version
mock_confirm_message "Tagged v#{app_version}."
- mock_confirm_message "Pushed git commits and tags."
+ mock_confirm_message "Pushed git commits and release tag."
- Dir.chdir(app_path) { sys_exec("git push -u origin master") }
+ sys_exec("git push -u origin master", :dir => app_path)
end
it "calls rubygem_push with proper arguments" do
@@ -235,7 +290,43 @@ RSpec.describe Bundler::GemHelper do
end
it "uses Kernel.system" do
- expect(Kernel).to receive(:system).with(gem_bin, "push", app_gem_path.to_s, "--host", "http://example.org").and_return(true)
+ cmd = gem_bin.shellsplit
+ expect(Kernel).to receive(:system).with(*cmd, "push", app_gem_path.to_s, "--host", "http://example.org").and_return(true)
+
+ Rake.application["release"].invoke
+ end
+
+ it "also works when releasing from an ambiguous reference" do
+ # Create a branch with the same name as the tag
+ sys_exec("git checkout -b v#{app_version}", :dir => app_path)
+ sys_exec("git push -u origin v#{app_version}", :dir => app_path)
+
+ expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
+
+ Rake.application["release"].invoke
+ end
+
+ it "also works with releasing from a branch not yet pushed" do
+ sys_exec("git checkout -b module_function", :dir => app_path)
+
+ expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
+
+ Rake.application["release"].invoke
+ end
+ end
+
+ context "on releasing with a custom tag prefix" do
+ before do
+ Bundler::GemHelper.tag_prefix = "foo-"
+ mock_build_message app_name, app_version
+ mock_confirm_message "Pushed git commits and release tag."
+
+ sys_exec("git push -u origin master", :dir => app_path)
+ expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
+ end
+
+ it "prepends the custom prefix to the tag" do
+ mock_confirm_message "Tagged foo-v#{app_version}."
Rake.application["release"].invoke
end
@@ -246,9 +337,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)
- Dir.chdir(app_path) do
- `git tag -a -m \"Version #{app_version}\" v#{app_version}`
- end
+ sys_exec("git tag -a -m \"Version #{app_version}\" v#{app_version}", :dir => app_path)
Rake.application["release"].invoke
end
@@ -269,12 +358,10 @@ RSpec.describe Bundler::GemHelper do
end
before do
- Dir.chdir(app_path) do
- `git init`
- `git config user.email "you@example.com"`
- `git config user.name "name"`
- `git config push.default simple`
- end
+ sys_exec("git init", :dir => app_path)
+ sys_exec("git config user.email \"you@example.com\"", :dir => app_path)
+ sys_exec("git config user.name \"name\"", :dir => app_path)
+ sys_exec("git config push.gpgsign simple", :dir => app_path)
# silence messages
allow(Bundler.ui).to receive(:confirm)
diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb
index 01e0232fba..43a3630bbb 100644
--- a/spec/bundler/bundler/gem_version_promoter_spec.rb
+++ b/spec/bundler/bundler/gem_version_promoter_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Bundler::GemVersionPromoter do
def build_spec_groups(name, versions)
versions.map do |v|
- Bundler::Resolver::SpecGroup.new(build_spec(name, v))
+ Bundler::Resolver::SpecGroup.create_for({ Gem::Platform::RUBY => build_spec(name, v) }, [Gem::Platform::RUBY], Gem::Platform::RUBY)
end
end
@@ -170,7 +170,7 @@ RSpec.describe Bundler::GemVersionPromoter do
context "debug output" do
it "should not kerblooie on its own debug output" do
gvp = unlocking(:level => :patch)
- dep = Bundler::DepProxy.new(dep("foo", "1.2.0").first, "ruby")
+ dep = Bundler::DepProxy.get_proxy(dep("foo", "1.2.0").first, "ruby")
result = gvp.send(:debug_format_result, dep, build_spec_groups("foo", %w[1.2.0 1.3.0]))
expect(result.class).to eq Array
end
diff --git a/spec/bundler/bundler/installer/parallel_installer_spec.rb b/spec/bundler/bundler/installer/parallel_installer_spec.rb
index ace5c1a23a..e680633862 100644
--- a/spec/bundler/bundler/installer/parallel_installer_spec.rb
+++ b/spec/bundler/bundler/installer/parallel_installer_spec.rb
@@ -44,4 +44,37 @@ The missing gems are:
end
end
end
+
+ context "when the spec set is not a valid resolution" do
+ let(:all_specs) do
+ [
+ build_spec("cucumber", "4.1.0") {|s| s.runtime "diff-lcs", "< 1.4" },
+ build_spec("diff-lcs", "1.4.4"),
+ ].flatten
+ end
+
+ it "prints a warning" do
+ expect(Bundler.ui).to receive(:warn).with(<<-W.strip)
+Your lockfile doesn't include a valid resolution.
+You can fix this by regenerating your lockfile or trying to manually editing the bad locked gems to a version that satisfies all dependencies.
+The unmet dependencies are:
+* diff-lcs (< 1.4), depended upon cucumber-4.1.0, unsatisfied by diff-lcs-1.4.4
+ W
+ subject.check_for_unmet_dependencies
+ end
+ end
+
+ context "when the spec set is a valid resolution" do
+ let(:all_specs) do
+ [
+ build_spec("cucumber", "4.1.0") {|s| s.runtime "diff-lcs", "< 1.4" },
+ build_spec("diff-lcs", "1.3"),
+ ].flatten
+ end
+
+ it "doesn't print a warning" do
+ expect(Bundler.ui).not_to receive(:warn)
+ subject.check_for_unmet_dependencies
+ end
+ end
end
diff --git a/spec/bundler/bundler/installer/spec_installation_spec.rb b/spec/bundler/bundler/installer/spec_installation_spec.rb
index a9cf09a372..e63ef26cb3 100644
--- a/spec/bundler/bundler/installer/spec_installation_spec.rb
+++ b/spec/bundler/bundler/installer/spec_installation_spec.rb
@@ -8,6 +8,10 @@ RSpec.describe Bundler::ParallelInstaller::SpecInstallation do
def a_spec.name
"I like tests"
end
+
+ def a_spec.full_name
+ "I really like tests"
+ end
a_spec
end
diff --git a/spec/bundler/bundler/mirror_spec.rb b/spec/bundler/bundler/mirror_spec.rb
index 4a8a0c7c48..1eaf1e9a8e 100644
--- a/spec/bundler/bundler/mirror_spec.rb
+++ b/spec/bundler/bundler/mirror_spec.rb
@@ -305,6 +305,8 @@ RSpec.describe Bundler::Settings::TCPSocketProbe do
end
it "probes the server correctly" do
+ skip "obscure error" if Gem.win_platform?
+
with_server_and_mirror do |server, mirror|
expect(server.closed?).to be_falsey
expect(probe.replies?(mirror)).to be_truthy
diff --git a/spec/bundler/bundler/plugin/api/source_spec.rb b/spec/bundler/bundler/plugin/api/source_spec.rb
index 2c50ff56a4..428ceb220a 100644
--- a/spec/bundler/bundler/plugin/api/source_spec.rb
+++ b/spec/bundler/bundler/plugin/api/source_spec.rb
@@ -79,4 +79,10 @@ RSpec.describe Bundler::Plugin::API::Source do
end
end
end
+
+ describe "to_s" do
+ it "returns the string with type and uri" do
+ expect(source.to_s).to eq("plugin source for spec_type with uri uri://to/test")
+ end
+ end
end
diff --git a/spec/bundler/bundler/plugin/dsl_spec.rb b/spec/bundler/bundler/plugin/dsl_spec.rb
index be23db3bba..00e39dca69 100644
--- a/spec/bundler/bundler/plugin/dsl_spec.rb
+++ b/spec/bundler/bundler/plugin/dsl_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Bundler::Plugin::DSL do
expect(dsl.inferred_plugins).to eq(["bundler-source-news"])
end
- it "registers a source type plugin only once for multiple declataions" do
+ it "registers a source type plugin only once for multiple declarations" do
expect(dsl).to receive(:plugin).with("bundler-source-news").and_call_original.once
dsl.source("some_random_url", :type => "news") {}
diff --git a/spec/bundler/bundler/plugin/index_spec.rb b/spec/bundler/bundler/plugin/index_spec.rb
index e18e960fb8..d34b0de342 100644
--- a/spec/bundler/bundler/plugin/index_spec.rb
+++ b/spec/bundler/bundler/plugin/index_spec.rb
@@ -4,7 +4,8 @@ RSpec.describe Bundler::Plugin::Index do
Index = Bundler::Plugin::Index
before do
- gemfile ""
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ gemfile "source \"#{file_uri_for(gem_repo1)}\""
path = lib_path(plugin_name)
index.register_plugin("new-plugin", path.to_s, [path.join("lib").to_s], commands, sources, hooks)
end
@@ -21,7 +22,7 @@ RSpec.describe Bundler::Plugin::Index do
expect(index.plugin_path(plugin_name)).to eq(lib_path(plugin_name))
end
- it "load_paths is available for retrival" do
+ it "load_paths is available for retrieval" do
expect(index.load_paths(plugin_name)).to eq([lib_path(plugin_name).join("lib").to_s])
end
@@ -97,7 +98,13 @@ RSpec.describe Bundler::Plugin::Index do
expect(index.hook_plugins("after-bar")).to eq([plugin_name])
end
- context "that are not registered", :focused do
+ it "is gone after unregistration" do
+ expect(index.index_file.read).to include("after-bar:\n - \"new-plugin\"\n")
+ index.unregister_plugin(plugin_name)
+ expect(index.index_file.read).to_not include("after-bar:\n - \n")
+ end
+
+ context "that are not registered" do
let(:file) { double("index-file") }
before do
@@ -117,11 +124,11 @@ RSpec.describe Bundler::Plugin::Index do
describe "global index" do
before do
- Dir.chdir(tmp) do
- Bundler::Plugin.reset!
- path = lib_path("gplugin")
- index.register_plugin("gplugin", path.to_s, [path.join("lib").to_s], [], ["glb_source"], [])
- end
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(nil)
+
+ Bundler::Plugin.reset!
+ path = lib_path("gplugin")
+ index.register_plugin("gplugin", path.to_s, [path.join("lib").to_s], [], ["glb_source"], [])
end
it "skips sources" do
diff --git a/spec/bundler/bundler/plugin_spec.rb b/spec/bundler/bundler/plugin_spec.rb
index e0e2e9afdf..25cae014dd 100644
--- a/spec/bundler/bundler/plugin_spec.rb
+++ b/spec/bundler/bundler/plugin_spec.rb
@@ -67,6 +67,8 @@ RSpec.describe Bundler::Plugin do
end
it "passes the name and options to installer" do
+ allow(index).to receive(:installed?).
+ with("new-plugin")
allow(installer).to receive(:install).with(["new-plugin"], opts) do
{ "new-plugin" => spec }
end.once
@@ -75,6 +77,8 @@ RSpec.describe Bundler::Plugin do
end
it "validates the installed plugin" do
+ allow(index).to receive(:installed?).
+ with("new-plugin")
allow(subject).
to receive(:validate_plugin!).with(lib_path("new-plugin")).once
@@ -82,6 +86,8 @@ RSpec.describe Bundler::Plugin do
end
it "registers the plugin with index" do
+ allow(index).to receive(:installed?).
+ with("new-plugin")
allow(index).to receive(:register_plugin).
with("new-plugin", lib_path("new-plugin").to_s, [lib_path("new-plugin").join("lib").to_s], []).once
subject.install ["new-plugin"], opts
@@ -98,6 +104,7 @@ RSpec.describe Bundler::Plugin do
end.once
allow(subject).to receive(:validate_plugin!).twice
+ allow(index).to receive(:installed?).twice
allow(index).to receive(:register_plugin).twice
subject.install ["new-plugin", "another-plugin"], opts
end
@@ -107,11 +114,12 @@ RSpec.describe Bundler::Plugin do
describe "evaluate gemfile for plugins" do
let(:definition) { double("definition") }
let(:builder) { double("builder") }
- let(:gemfile) { bundled_app("Gemfile") }
+ let(:gemfile) { bundled_app_gemfile }
before do
allow(Plugin::DSL).to receive(:new) { builder }
allow(builder).to receive(:eval_gemfile).with(gemfile)
+ allow(builder).to receive(:check_primary_source_safety)
allow(builder).to receive(:to_definition) { definition }
allow(builder).to receive(:inferred_plugins) { [] }
end
@@ -237,7 +245,7 @@ RSpec.describe Bundler::Plugin do
describe "#root" do
context "in app dir" do
before do
- gemfile ""
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
it "returns plugin dir in app .bundle path" do
@@ -246,8 +254,11 @@ RSpec.describe Bundler::Plugin do
end
context "outside app dir" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(nil)
+ end
+
it "returns plugin dir in global bundle path" do
- Dir.chdir tmp
expect(subject.root).to eq(home.join(".bundle/plugin"))
end
end
@@ -275,7 +286,7 @@ RSpec.describe Bundler::Plugin do
Bundler::Plugin::Events.send(:define, :EVENT_2, "event-2")
allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_1).
- and_return(["foo-plugin"])
+ and_return(["foo-plugin", "", nil])
allow(index).to receive(:hook_plugins).with(Bundler::Plugin::Events::EVENT_2).
and_return(["foo-plugin"])
allow(index).to receive(:plugin_path).with("foo-plugin").and_return(path)
diff --git a/spec/bundler/bundler/rubygems_integration_spec.rb b/spec/bundler/bundler/rubygems_integration_spec.rb
index 11fa2f4e0d..7557c806fe 100644
--- a/spec/bundler/bundler/rubygems_integration_spec.rb
+++ b/spec/bundler/bundler/rubygems_integration_spec.rb
@@ -43,12 +43,10 @@ RSpec.describe Bundler::RubygemsIntegration do
describe "#download_gem" do
let(:bundler_retry) { double(Bundler::Retry) }
- let(:retry) { double("Bundler::Retry") }
- let(:uri) { Bundler::URI.parse("https://foo.bar") }
- let(:path) { Gem.path.first }
+ let(:uri) { Bundler::URI.parse("https://foo.bar") }
+ let(:cache_dir) { "#{Gem.path.first}/cache" }
let(:spec) do
- spec = Bundler::RemoteSpecification.new("Foo", Gem::Version.new("2.5.2"),
- Gem::Platform::RUBY, nil)
+ spec = Gem::Specification.new("Foo", Gem::Version.new("2.5.2"))
spec.remote = Bundler::Source::Rubygems::Remote.new(uri.to_s)
spec
end
@@ -56,13 +54,13 @@ RSpec.describe Bundler::RubygemsIntegration do
it "successfully downloads gem with retries" do
expect(Bundler.rubygems).to receive(:gem_remote_fetcher).and_return(fetcher)
- expect(fetcher).to receive(:headers=).with("X-Gemfile-Source" => "https://foo.bar")
+ expect(fetcher).to receive(:headers=).with({ "X-Gemfile-Source" => "https://foo.bar" })
expect(Bundler::Retry).to receive(:new).with("download gem from #{uri}/").
and_return(bundler_retry)
expect(bundler_retry).to receive(:attempts).and_yield
- expect(fetcher).to receive(:download).with(spec, uri, path)
+ expect(fetcher).to receive(:cache_update_path)
- Bundler.rubygems.download_gem(spec, uri, path)
+ Bundler.rubygems.download_gem(spec, uri, cache_dir)
end
end
@@ -78,7 +76,7 @@ RSpec.describe Bundler::RubygemsIntegration do
it "sets the 'X-Gemfile-Source' header containing the original source" do
expect(Bundler.rubygems).to receive(:gem_remote_fetcher).twice.and_return(fetcher)
- expect(fetcher).to receive(:headers=).with("X-Gemfile-Source" => "http://zombo.com").twice
+ expect(fetcher).to receive(:headers=).with({ "X-Gemfile-Source" => "http://zombo.com" }).twice
expect(fetcher).to receive(:fetch_path).with(uri + "specs.4.8.gz").and_return(specs_response)
expect(fetcher).to receive(:fetch_path).with(uri + "prerelease_specs.4.8.gz").and_return(prerelease_specs_response)
result = Bundler.rubygems.fetch_all_remote_specs(remote_with_mirror)
diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb
index b83d768477..24e3de7ba8 100644
--- a/spec/bundler/bundler/settings_spec.rb
+++ b/spec/bundler/bundler/settings_spec.rb
@@ -64,13 +64,10 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
describe "#global_config_file" do
context "when $HOME is not accessible" do
- context "when $TMPDIR is not writable" do
- it "does not raise" do
- expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil)
- expect(Bundler).to receive(:tmp).twice.and_raise(Errno::EROFS, "Read-only file system @ dir_s_mkdir - /tmp/bundler")
+ it "does not raise" do
+ expect(Bundler.rubygems).to receive(:user_home).twice.and_return(nil)
- expect(subject.send(:global_config_file)).to be_nil
- end
+ expect(subject.send(:global_config_file)).to be_nil
end
end
end
@@ -130,6 +127,8 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
describe "#temporary" do
it "reset after used" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+
Bundler.settings.set_command_option :no_install, true
Bundler.settings.temporary(:no_install => false) do
@@ -310,16 +309,26 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
describe "BUNDLE_ keys format" do
let(:settings) { described_class.new(bundled_app(".bundle")) }
- it "converts older keys without double dashes" do
+ it "converts older keys without double underscore" do
config("BUNDLE_MY__PERSONAL.RACK" => "~/Work/git/rack")
expect(settings["my.personal.rack"]).to eq("~/Work/git/rack")
end
- it "converts older keys without trailing slashes and double dashes" do
+ it "converts older keys without trailing slashes and double underscore" do
config("BUNDLE_MIRROR__HTTPS://RUBYGEMS.ORG" => "http://rubygems-mirror.org")
expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org")
end
+ it "converts older keys with dashes" do
+ config("BUNDLE_MY-PERSONAL-SERVER__ORG" => "my-personal-server.org")
+ expect(Bundler.ui).to receive(:warn).with(
+ "Your #{bundled_app(".bundle/config")} config includes `BUNDLE_MY-PERSONAL-SERVER__ORG`, which contains the dash character (`-`).\n" \
+ "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \
+ "Please edit #{bundled_app(".bundle/config")} and replace any dashes in configuration keys with a triple underscore (`___`)."
+ )
+ expect(settings["my-personal-server.org"]).to eq("my-personal-server.org")
+ end
+
it "reads newer keys format properly" do
config("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://rubygems-mirror.org")
expect(settings["mirror.https://rubygems.org/"]).to eq("http://rubygems-mirror.org")
diff --git a/spec/bundler/bundler/shared_helpers_spec.rb b/spec/bundler/bundler/shared_helpers_spec.rb
index 4530a9a5cd..97647dc6eb 100644
--- a/spec/bundler/bundler/shared_helpers_spec.rb
+++ b/spec/bundler/bundler/shared_helpers_spec.rb
@@ -4,10 +4,13 @@ RSpec.describe Bundler::SharedHelpers do
let(:ext_lock_double) { double(:ext_lock) }
before do
+ pwd_stub
allow(Bundler.rubygems).to receive(:ext_lock).and_return(ext_lock_double)
allow(ext_lock_double).to receive(:synchronize) {|&block| block.call }
end
+ let(:pwd_stub) { allow(subject).to receive(:pwd).and_return(bundled_app) }
+
subject { Bundler::SharedHelpers }
describe "#default_gemfile" do
@@ -77,7 +80,7 @@ RSpec.describe Bundler::SharedHelpers do
let(:global_rubygems_dir) { Pathname.new(bundled_app) }
before do
- Dir.mkdir ".bundle"
+ Dir.mkdir bundled_app(".bundle")
allow(Bundler.rubygems).to receive(:user_home).and_return(global_rubygems_dir)
end
@@ -91,7 +94,7 @@ RSpec.describe Bundler::SharedHelpers do
let(:expected_bundle_dir_path) { Pathname.new("#{bundled_app}/.bundle") }
before do
- Dir.mkdir ".bundle"
+ Dir.mkdir bundled_app(".bundle")
allow(Bundler.rubygems).to receive(:user_home).and_return(global_rubygems_dir)
end
@@ -109,7 +112,8 @@ RSpec.describe Bundler::SharedHelpers do
shared_examples_for "correctly determines whether to return a Gemfile path" do
context "currently in directory with a Gemfile" do
- before { File.new("Gemfile", "w") }
+ before { FileUtils.touch(bundled_app_gemfile) }
+ after { FileUtils.rm(bundled_app_gemfile) }
it "returns path of the bundle Gemfile" do
expect(subject.in_bundle?).to eq("#{bundled_app}/Gemfile")
@@ -147,22 +151,24 @@ RSpec.describe Bundler::SharedHelpers do
describe "#chdir" do
let(:op_block) { proc { Dir.mkdir "nested_dir" } }
- before { Dir.mkdir "chdir_test_dir" }
+ before { Dir.mkdir bundled_app("chdir_test_dir") }
it "executes the passed block while in the specified directory" do
- subject.chdir("chdir_test_dir", &op_block)
- expect(Pathname.new("chdir_test_dir/nested_dir")).to exist
+ subject.chdir(bundled_app("chdir_test_dir"), &op_block)
+ expect(bundled_app("chdir_test_dir/nested_dir")).to exist
end
end
describe "#pwd" do
+ let(:pwd_stub) { nil }
+
it "returns the current absolute path" do
- expect(subject.pwd).to eq(bundled_app)
+ expect(subject.pwd).to eq(source_root)
end
end
describe "#with_clean_git_env" do
- let(:with_clean_git_env_block) { proc { Dir.mkdir "with_clean_git_env_test_dir" } }
+ let(:with_clean_git_env_block) { proc { Dir.mkdir bundled_app("with_clean_git_env_test_dir") } }
before do
ENV["GIT_DIR"] = "ORIGINAL_ENV_GIT_DIR"
@@ -171,20 +177,20 @@ RSpec.describe Bundler::SharedHelpers do
it "executes the passed block" do
subject.with_clean_git_env(&with_clean_git_env_block)
- expect(Pathname.new("with_clean_git_env_test_dir")).to exist
+ expect(bundled_app("with_clean_git_env_test_dir")).to exist
end
context "when a block is passed" do
let(:with_clean_git_env_block) do
proc do
- Dir.mkdir "git_dir_test_dir" unless ENV["GIT_DIR"].nil?
- Dir.mkdir "git_work_tree_test_dir" unless ENV["GIT_WORK_TREE"].nil?
+ Dir.mkdir bundled_app("git_dir_test_dir") unless ENV["GIT_DIR"].nil?
+ Dir.mkdir bundled_app("git_work_tree_test_dir") unless ENV["GIT_WORK_TREE"].nil?
end end
it "uses a fresh git env for execution" do
subject.with_clean_git_env(&with_clean_git_env_block)
- expect(Pathname.new("git_dir_test_dir")).to_not exist
- expect(Pathname.new("git_work_tree_test_dir")).to_not exist
+ expect(bundled_app("git_dir_test_dir")).to_not exist
+ expect(bundled_app("git_work_tree_test_dir")).to_not exist
end
end
@@ -224,7 +230,7 @@ RSpec.describe Bundler::SharedHelpers do
end
shared_examples_for "ENV['PATH'] gets set correctly" do
- before { Dir.mkdir ".bundle" }
+ before { Dir.mkdir bundled_app(".bundle") }
it "ensures bundle bin path is in ENV['PATH']" do
subject.set_bundle_environment
@@ -236,7 +242,7 @@ RSpec.describe Bundler::SharedHelpers do
shared_examples_for "ENV['RUBYOPT'] gets set correctly" do
it "ensures -rbundler/setup is at the beginning of ENV['RUBYOPT']" do
subject.set_bundle_environment
- expect(ENV["RUBYOPT"].split(" ")).to start_with("-r#{lib_dir}/bundler/setup")
+ expect(ENV["RUBYOPT"].split(" ")).to start_with("-r#{source_lib_dir}/bundler/setup")
end
end
@@ -244,7 +250,7 @@ RSpec.describe Bundler::SharedHelpers do
let(:ruby_lib_path) { "stubbed_ruby_lib_dir" }
before do
- allow(Bundler::SharedHelpers).to receive(:bundler_ruby_lib).and_return(ruby_lib_path)
+ allow(subject).to receive(:bundler_ruby_lib).and_return(ruby_lib_path)
end
it "ensures bundler's ruby version lib path is in ENV['RUBYLIB']" do
@@ -263,7 +269,7 @@ RSpec.describe Bundler::SharedHelpers do
end
it "ignores if bundler_ruby_lib is same as rubylibdir" do
- allow(Bundler::SharedHelpers).to receive(:bundler_ruby_lib).and_return(RbConfig::CONFIG["rubylibdir"])
+ allow(subject).to receive(:bundler_ruby_lib).and_return(RbConfig::CONFIG["rubylibdir"])
subject.set_bundle_environment
@@ -422,8 +428,8 @@ RSpec.describe Bundler::SharedHelpers do
let(:file_op_block) { proc {|path| FileUtils.mkdir_p(path) } }
it "performs the operation in the passed block" do
- subject.filesystem_access("./test_dir", &file_op_block)
- expect(Pathname.new("test_dir")).to exist
+ subject.filesystem_access(bundled_app("test_dir"), &file_op_block)
+ expect(bundled_app("test_dir")).to exist
end
end
diff --git a/spec/bundler/bundler/source/git/git_proxy_spec.rb b/spec/bundler/bundler/source/git/git_proxy_spec.rb
index c18490233d..cffd72cc3f 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/bundler/bundler.git" }
+ let(:uri) { "https://github.com/rubygems/rubygems.git" }
let(:ref) { "HEAD" }
let(:revision) { nil }
let(:git_source) { nil }
@@ -11,30 +11,30 @@ RSpec.describe Bundler::Source::Git::GitProxy do
context "with configured credentials" do
it "adds username and password to URI" do
Bundler.settings.temporary(uri => "u:p") do
- expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git"))
+ expect(subject).to receive(:git_retry).with("clone", "--bare", "--no-hardlinks", "--quiet", "--", "https://u:p@github.com/rubygems/rubygems.git", path.to_s)
subject.checkout
end
end
it "adds username and password to URI for host" do
Bundler.settings.temporary("github.com" => "u:p") do
- expect(subject).to receive(:git_retry).with(match("https://u:p@github.com/bundler/bundler.git"))
+ expect(subject).to receive(:git_retry).with("clone", "--bare", "--no-hardlinks", "--quiet", "--", "https://u:p@github.com/rubygems/rubygems.git", path.to_s)
subject.checkout
end
end
it "does not add username and password to mismatched URI" do
- Bundler.settings.temporary("https://u:p@github.com/bundler/bundler-mismatch.git" => "u:p") do
- expect(subject).to receive(:git_retry).with(match(uri))
+ Bundler.settings.temporary("https://u:p@github.com/rubygems/rubygems-mismatch.git" => "u:p") do
+ expect(subject).to receive(:git_retry).with("clone", "--bare", "--no-hardlinks", "--quiet", "--", uri, path.to_s)
subject.checkout
end
end
it "keeps original userinfo" do
Bundler.settings.temporary("github.com" => "u:p") do
- original = "https://orig:info@github.com/bundler/bundler.git"
+ original = "https://orig:info@github.com/rubygems/rubygems.git"
subject = described_class.new(Pathname("path"), original, "HEAD")
- expect(subject).to receive(:git_retry).with(match(original))
+ expect(subject).to receive(:git_retry).with("clone", "--bare", "--no-hardlinks", "--quiet", "--", original, path.to_s)
subject.checkout
end
end
@@ -123,26 +123,49 @@ RSpec.describe Bundler::Source::Git::GitProxy do
end
describe "#copy_to" do
+ let(:cache) { tmpdir("cache_path") }
let(:destination) { tmpdir("copy_to_path") }
let(:submodules) { false }
context "when given a SHA as a revision" do
let(:revision) { "abcd" * 10 }
- let(:command) { "reset --hard #{revision}" }
+ let(:command) { ["reset", "--hard", revision] }
+ let(:command_for_display) { "git #{command.shelljoin}" }
it "fails gracefully when resetting to the revision fails" do
- expect(subject).to receive(:git_retry).with(start_with("clone ")) { destination.mkpath }
- expect(subject).to receive(:git_retry).with(start_with("fetch "))
- expect(subject).to receive(:git).with(command).and_raise(Bundler::Source::Git::GitCommandError, command)
+ expect(subject).to receive(:git_retry).with("clone", any_args) { destination.mkpath }
+ expect(subject).to receive(:git_retry).with("fetch", any_args, :dir => destination)
+ expect(subject).to receive(:git).with(*command, :dir => destination).and_raise(Bundler::Source::Git::GitCommandError.new(command_for_display, destination))
expect(subject).not_to receive(:git)
expect { subject.copy_to(destination, submodules) }.
to raise_error(
Bundler::Source::Git::MissingGitRevisionError,
- "Git error: command `git #{command}` in directory #{destination} has failed.\n" \
- "Revision #{revision} does not exist in the repository #{uri}. Maybe you misspelled it?" \
+ "Git error: command `#{command_for_display}` in directory #{destination} has failed.\n" \
+ "Revision #{revision} does not exist in the repository #{uri}. Maybe you misspelled it?\n" \
+ "If this error persists you could try removing the cache directory '#{destination}'"
)
end
end
end
+
+ it "doesn't allow arbitrary code execution through Gemfile uris with a leading dash" do
+ gemfile <<~G
+ gem "poc", git: "-u./pay:load.sh"
+ G
+
+ file = bundled_app("pay:load.sh")
+
+ create_file file, <<~RUBY
+ #!/bin/sh
+
+ touch #{bundled_app("canary")}
+ RUBY
+
+ FileUtils.chmod("+x", file)
+
+ bundle :lock, :raise_on_error => false
+
+ expect(Pathname.new(bundled_app("canary"))).not_to exist
+ end
end
diff --git a/spec/bundler/bundler/source/git_spec.rb b/spec/bundler/bundler/source/git_spec.rb
index f7475a35aa..ed6dc3cd29 100644
--- a/spec/bundler/bundler/source/git_spec.rb
+++ b/spec/bundler/bundler/source/git_spec.rb
@@ -14,14 +14,59 @@ RSpec.describe Bundler::Source::Git do
describe "#to_s" do
it "returns a description" do
- expect(subject.to_s).to eq "https://github.com/foo/bar.git (at master)"
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git"
end
context "when the URI contains credentials" do
let(:uri) { "https://my-secret-token:x-oauth-basic@github.com/foo/bar.git" }
it "filters credentials" do
- expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git (at master)"
+ expect(subject.to_s).to eq "https://x-oauth-basic@github.com/foo/bar.git"
+ end
+ end
+
+ context "when the source has a glob specifier" do
+ let(:glob) { "bar/baz/*.gemspec" }
+ let(:options) do
+ { "uri" => uri, "glob" => glob }
+ end
+
+ it "includes it" do
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git (glob: bar/baz/*.gemspec)"
+ end
+ end
+
+ context "when the source has a reference" do
+ let(:git_proxy_stub) do
+ instance_double(Bundler::Source::Git::GitProxy, :revision => "123abc", :branch => "v1.0.0")
+ end
+ let(:options) do
+ { "uri" => uri, "ref" => "v1.0.0" }
+ end
+
+ before do
+ allow(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub)
+ end
+
+ it "includes it" do
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git (at v1.0.0@123abc)"
+ end
+ end
+
+ context "when the source has both reference and glob specifiers" do
+ let(:git_proxy_stub) do
+ instance_double(Bundler::Source::Git::GitProxy, :revision => "123abc", :branch => "v1.0.0")
+ end
+ let(:options) do
+ { "uri" => uri, "ref" => "v1.0.0", "glob" => "gems/foo/*.gemspec" }
+ end
+
+ before do
+ allow(Bundler::Source::Git::GitProxy).to receive(:new).and_return(git_proxy_stub)
+ end
+
+ it "includes both" do
+ expect(subject.to_s).to eq "https://github.com/foo/bar.git (at v1.0.0@123abc, glob: gems/foo/*.gemspec)"
end
end
end
diff --git a/spec/bundler/bundler/source/rubygems_spec.rb b/spec/bundler/bundler/source/rubygems_spec.rb
index 7c457a7265..884fa81046 100644
--- a/spec/bundler/bundler/source/rubygems_spec.rb
+++ b/spec/bundler/bundler/source/rubygems_spec.rb
@@ -30,4 +30,18 @@ RSpec.describe Bundler::Source::Rubygems do
end
end
end
+
+ describe "#no_remotes?" do
+ context "when no remote provided" do
+ it "returns a truthy value" do
+ expect(described_class.new("remotes" => []).no_remotes?).to be_truthy
+ end
+ end
+
+ context "when a remote provided" do
+ it "returns a falsey value" do
+ expect(described_class.new("remotes" => ["https://rubygems.org"]).no_remotes?).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/source_list_spec.rb b/spec/bundler/bundler/source_list_spec.rb
index 93159998c6..f860e9ff58 100644
--- a/spec/bundler/bundler/source_list_spec.rb
+++ b/spec/bundler/bundler/source_list_spec.rb
@@ -75,7 +75,7 @@ RSpec.describe Bundler::SourceList do
let(:msg) do
"The git source `git://existing-git.org/path.git` " \
"uses the `git` protocol, which transmits data without encryption. " \
- "Disable this warning with `bundle config set git.allow_insecure true`, " \
+ "Disable this warning with `bundle config set --local git.allow_insecure true`, " \
"or switch to the `https` protocol to keep your data secure."
end
@@ -115,15 +115,15 @@ RSpec.describe Bundler::SourceList do
end
end
- describe "#add_rubygems_remote", :bundler => "< 3" do
- let!(:returned_source) { source_list.add_rubygems_remote("https://rubygems.org/") }
+ describe "#add_global_rubygems_remote" do
+ let!(:returned_source) { source_list.add_global_rubygems_remote("https://rubygems.org/") }
it "returns the aggregate rubygems source" do
expect(returned_source).to be_instance_of(Bundler::Source::Rubygems)
end
it "adds the provided remote to the beginning of the aggregate source" do
- source_list.add_rubygems_remote("https://othersource.org")
+ source_list.add_global_rubygems_remote("https://othersource.org")
expect(returned_source.remotes).to eq [
Bundler::URI("https://othersource.org/"),
Bundler::URI("https://rubygems.org/"),
@@ -212,22 +212,22 @@ RSpec.describe Bundler::SourceList do
describe "#path_sources" do
it "returns an empty array when no path sources have been added" do
- source_list.add_rubygems_remote("https://rubygems.org")
+ source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_git_source("uri" => "git://host/path.git")
expect(source_list.path_sources).to be_empty
end
it "returns path sources in the reverse order that they were added" do
source_list.add_git_source("uri" => "git://third-git.org/path.git")
- source_list.add_rubygems_remote("https://fifth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fifth-rubygems.org")
source_list.add_path_source("path" => "/third/path/to/gem")
- source_list.add_rubygems_remote("https://fourth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem")
- source_list.add_rubygems_remote("https://third-rubygems.org")
+ source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_git_source("uri" => "git://second-git.org/path.git")
- source_list.add_rubygems_remote("https://second-rubygems.org")
+ source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem")
- source_list.add_rubygems_remote("https://first-rubygems.org")
+ source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_git_source("uri" => "git://first-git.org/path.git")
expect(source_list.path_sources).to eq [
@@ -240,7 +240,7 @@ RSpec.describe Bundler::SourceList do
describe "#git_sources" do
it "returns an empty array when no git sources have been added" do
- source_list.add_rubygems_remote("https://rubygems.org")
+ source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_path_source("path" => "/path/to/gem")
expect(source_list.git_sources).to be_empty
@@ -248,15 +248,15 @@ RSpec.describe Bundler::SourceList do
it "returns git sources in the reverse order that they were added" do
source_list.add_git_source("uri" => "git://third-git.org/path.git")
- source_list.add_rubygems_remote("https://fifth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fifth-rubygems.org")
source_list.add_path_source("path" => "/third/path/to/gem")
- source_list.add_rubygems_remote("https://fourth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem")
- source_list.add_rubygems_remote("https://third-rubygems.org")
+ source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_git_source("uri" => "git://second-git.org/path.git")
- source_list.add_rubygems_remote("https://second-rubygems.org")
+ source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem")
- source_list.add_rubygems_remote("https://first-rubygems.org")
+ source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_git_source("uri" => "git://first-git.org/path.git")
expect(source_list.git_sources).to eq [
@@ -269,7 +269,7 @@ RSpec.describe Bundler::SourceList do
describe "#plugin_sources" do
it "returns an empty array when no plugin sources have been added" do
- source_list.add_rubygems_remote("https://rubygems.org")
+ source_list.add_global_rubygems_remote("https://rubygems.org")
source_list.add_path_source("path" => "/path/to/gem")
expect(source_list.plugin_sources).to be_empty
@@ -279,13 +279,13 @@ RSpec.describe Bundler::SourceList do
source_list.add_plugin_source("new_source", "uri" => "https://third-git.org/path.git")
source_list.add_git_source("https://new-git.org")
source_list.add_path_source("path" => "/third/path/to/gem")
- source_list.add_rubygems_remote("https://fourth-rubygems.org")
+ source_list.add_global_rubygems_remote("https://fourth-rubygems.org")
source_list.add_path_source("path" => "/second/path/to/gem")
- source_list.add_rubygems_remote("https://third-rubygems.org")
+ source_list.add_global_rubygems_remote("https://third-rubygems.org")
source_list.add_plugin_source("new_source", "uri" => "git://second-git.org/path.git")
- source_list.add_rubygems_remote("https://second-rubygems.org")
+ source_list.add_global_rubygems_remote("https://second-rubygems.org")
source_list.add_path_source("path" => "/first/path/to/gem")
- source_list.add_rubygems_remote("https://first-rubygems.org")
+ source_list.add_global_rubygems_remote("https://first-rubygems.org")
source_list.add_plugin_source("new_source", "uri" => "git://first-git.org/path.git")
expect(source_list.plugin_sources).to eq [
@@ -339,7 +339,7 @@ RSpec.describe Bundler::SourceList do
describe "#get" do
context "when it includes an equal source" do
let(:rubygems_source) { Bundler::Source::Rubygems.new("remotes" => ["https://rubygems.org"]) }
- before { @equal_source = source_list.add_rubygems_remote("https://rubygems.org") }
+ before { @equal_source = source_list.add_global_rubygems_remote("https://rubygems.org") }
it "returns the equal source" do
expect(source_list.get(rubygems_source)).to be @equal_source
@@ -372,26 +372,7 @@ RSpec.describe Bundler::SourceList do
source_list.add_git_source("uri" => "git://first-git.org/path.git")
end
- it "combines the rubygems sources into a single instance, removing duplicate remotes from the end", :bundler => "< 3" do
- expect(source_list.lock_sources).to eq [
- Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"),
- Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"),
- Bundler::Source::Git.new("uri" => "git://third-git.org/path.git"),
- ASourcePlugin.new("uri" => "https://second-plugin.org/random"),
- ASourcePlugin.new("uri" => "https://third-bar.org/foo"),
- Bundler::Source::Path.new("path" => "/first/path/to/gem"),
- Bundler::Source::Path.new("path" => "/second/path/to/gem"),
- Bundler::Source::Path.new("path" => "/third/path/to/gem"),
- Bundler::Source::Rubygems.new("remotes" => [
- "https://duplicate-rubygems.org",
- "https://first-rubygems.org",
- "https://second-rubygems.org",
- "https://third-rubygems.org",
- ]),
- ]
- end
-
- it "returns all sources, without combining rubygems sources", :bundler => "3" do
+ it "returns all sources, without combining rubygems sources" do
expect(source_list.lock_sources).to eq [
Bundler::Source::Git.new("uri" => "git://first-git.org/path.git"),
Bundler::Source::Git.new("uri" => "git://second-git.org/path.git"),
@@ -460,4 +441,19 @@ RSpec.describe Bundler::SourceList do
source_list.remote!
end
end
+
+ describe "implicit_global_source?" do
+ context "when a global rubygem source provided" do
+ it "returns a falsy value" do
+ source_list.add_global_rubygems_remote("https://rubygems.org")
+
+ expect(source_list.implicit_global_source?).to be_falsey
+ end
+ end
+ context "when no global rubygem source provided" do
+ it "returns a truthy value" do
+ expect(source_list.implicit_global_source?).to be_truthy
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/source_spec.rb b/spec/bundler/bundler/source_spec.rb
index 0c35c27fdf..af370bb45c 100644
--- a/spec/bundler/bundler/source_spec.rb
+++ b/spec/bundler/bundler/source_spec.rb
@@ -188,7 +188,7 @@ RSpec.describe Bundler::Source do
end
end
-private
+ private
def with_ui(ui)
old_ui = Bundler.ui
diff --git a/spec/bundler/bundler/stub_specification_spec.rb b/spec/bundler/bundler/stub_specification_spec.rb
index 7495b5d661..fb612813c2 100644
--- a/spec/bundler/bundler/stub_specification_spec.rb
+++ b/spec/bundler/bundler/stub_specification_spec.rb
@@ -1,15 +1,14 @@
# frozen_string_literal: true
RSpec.describe Bundler::StubSpecification do
- let(:gemspec) do
- Gem::Specification.new do |s|
+ let(:with_bundler_stub_spec) do
+ gemspec = Gem::Specification.new do |s|
s.name = "gemname"
s.version = "1.0.0"
s.loaded_from = __FILE__
+ s.extensions = "ext/gemname"
end
- end
- let(:with_bundler_stub_spec) do
described_class.from_stub(gemspec)
end
@@ -19,4 +18,30 @@ RSpec.describe Bundler::StubSpecification do
expect(stub).to be(with_bundler_stub_spec)
end
end
+
+ describe "#manually_installed?" do
+ it "returns true if installed_by_version is nil or 0" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ expect(stub.manually_installed?).to be true
+ end
+
+ it "returns false if installed_by_version is greater than 0" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ stub.installed_by_version = Gem::Version.new(1)
+ expect(stub.manually_installed?).to be false
+ end
+ end
+
+ describe "#missing_extensions?" do
+ it "returns false if manually_installed?" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ expect(stub.missing_extensions?).to be false
+ end
+
+ it "returns true if not manually_installed?" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+ stub.installed_by_version = Gem::Version.new(1)
+ expect(stub.missing_extensions?).to be true
+ end
+ end
end
diff --git a/spec/bundler/bundler/worker_spec.rb b/spec/bundler/bundler/worker_spec.rb
index 2e5642709d..e4ebbd2932 100644
--- a/spec/bundler/bundler/worker_spec.rb
+++ b/spec/bundler/bundler/worker_spec.rb
@@ -19,4 +19,51 @@ RSpec.describe Bundler::Worker do
end
end
end
+
+ describe "handling interrupts" do
+ let(:status) do
+ pid = Process.fork do
+ $stderr.reopen File.new("/dev/null", "w")
+ Signal.trap "INT", previous_interrupt_handler
+ subject.enq "a"
+ subject.stop unless interrupt_before_stopping
+ Process.kill "INT", Process.pid
+ end
+
+ Process.wait2(pid).last
+ end
+
+ before do
+ skip "requires Process.fork" unless Process.respond_to?(:fork)
+ end
+
+ context "when interrupted before stopping" do
+ let(:interrupt_before_stopping) { true }
+ let(:previous_interrupt_handler) { ->(*) { exit 0 } }
+
+ it "aborts" do
+ expect(status.exitstatus).to eq(1)
+ end
+ end
+
+ context "when interrupted after stopping" do
+ let(:interrupt_before_stopping) { false }
+
+ context "when the previous interrupt handler was the default" do
+ let(:previous_interrupt_handler) { "DEFAULT" }
+
+ it "uses the default interrupt handler" do
+ expect(status).to be_signaled
+ end
+ end
+
+ context "when the previous interrupt handler was customized" do
+ let(:previous_interrupt_handler) { ->(*) { exit 42 } }
+
+ it "restores the custom interrupt handler after stopping" do
+ expect(status.exitstatus).to eq(42)
+ end
+ end
+ end
+ end
end
diff --git a/spec/bundler/cache/gems_spec.rb b/spec/bundler/cache/gems_spec.rb
index 89d6d41570..a8382a5d8c 100644
--- a/spec/bundler/cache/gems_spec.rb
+++ b/spec/bundler/cache/gems_spec.rb
@@ -4,11 +4,12 @@ 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'
G
- system_gems "rack-1.0.0", :path => :bundle_path
- bundle! :cache
+ system_gems "rack-1.0.0", :path => path
+ bundle :cache
end
it "copies the .gem file to vendor/cache" do
@@ -27,7 +28,7 @@ RSpec.describe "bundle cache" do
end
it "uses the cache as a source when installing gems with --local" do
- system_gems [], :path => :bundle_path
+ system_gems [], :path => default_bundle_path
bundle "install --local"
expect(the_bundle).to include_gems("rack 1.0.0")
@@ -39,6 +40,7 @@ RSpec.describe "bundle cache" do
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -46,9 +48,10 @@ RSpec.describe "bundle cache" do
end
it "does not reinstall gems from the cache if they exist in the bundle" do
- system_gems "rack-1.0.0", :path => :bundle_path
+ system_gems "rack-1.0.0", :path => default_bundle_path
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -56,7 +59,7 @@ RSpec.describe "bundle cache" do
s.write "lib/rack.rb", "RACK = 'FAIL'"
end
- bundle! :install, :local => true
+ bundle :install, :local => true
expect(the_bundle).to include_gems("rack 1.0.0")
end
@@ -64,54 +67,55 @@ RSpec.describe "bundle cache" do
cache_gems "rack-1.0.0"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
bundle "cache"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
end
context "using system gems" do
- before { bundle! "config set path.system true" }
+ before { bundle "config set path.system true" }
+ let(:path) { system_gem_path }
it_behaves_like "when there are only gemsources"
end
context "installing into a local path" do
- before { bundle! "config set path ./.bundle" }
+ before { bundle "config set path ./.bundle" }
+ let(:path) { local_gem_path }
it_behaves_like "when there are only gemsources"
end
- describe "when there is a built-in gem" do
+ describe "when there is a built-in gem", :ruby_repo do
+ let(:default_json_version) { ruby "gem 'json'; require 'json'; puts JSON::VERSION" }
+
before :each do
build_repo2 do
- build_gem "builtin_gem", "1.0.2"
+ build_gem "json", default_json_version
end
- build_gem "builtin_gem", "1.0.2", :to_system => true do |s|
- s.summary = "This builtin_gem is bundled with Ruby"
- end
-
- FileUtils.rm("#{system_gem_path}/cache/builtin_gem-1.0.2.gem")
+ build_gem "json", default_json_version, :to_system => true, :default => true
end
it "uses builtin gems when installing to system gems" do
- bundle! "config set path.system true"
- install_gemfile %(gem 'builtin_gem', '1.0.2')
- expect(the_bundle).to include_gems("builtin_gem 1.0.2")
+ bundle "config set path.system true"
+ install_gemfile %(source "#{file_uri_for(gem_repo1)}"; gem 'json', '#{default_json_version}'), :verbose => true
+ expect(out).to include("Using json #{default_json_version}")
end
it "caches remote and builtin gems" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
- gem 'builtin_gem', '1.0.2'
+ gem 'json', '#{default_json_version}'
gem 'rack', '1.0.0'
G
bundle :cache
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- expect(bundled_app("vendor/cache/builtin_gem-1.0.2.gem")).to exist
+ expect(bundled_app("vendor/cache/json-#{default_json_version}.gem")).to exist
end
it "doesn't make remote request after caching the gem" do
@@ -129,15 +133,16 @@ RSpec.describe "bundle cache" do
end
it "errors if the builtin gem isn't available to cache" do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
install_gemfile <<-G
- gem 'builtin_gem', '1.0.2'
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'json', '#{default_json_version}'
G
- bundle :cache
- expect(exitstatus).to_not eq(0) if exitstatus
- expect(err).to include("builtin_gem-1.0.2 is built in to Ruby, and can't be cached")
+ bundle :cache, :raise_on_error => false
+ expect(exitstatus).to_not eq(0)
+ expect(err).to include("json-#{default_json_version} is built in to Ruby, and can't be cached")
end
end
@@ -165,11 +170,11 @@ RSpec.describe "bundle cache" do
end
it "should not explode if the lockfile is not present" do
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
bundle :cache
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
end
@@ -195,7 +200,12 @@ RSpec.describe "bundle cache" do
end
it "adds and removes when gems are updated" do
- update_repo2
+ update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+ end
+
bundle "update", :all => true
expect(cached_gem("rack-1.2")).to exist
expect(cached_gem("rack-1.0.0")).not_to exist
@@ -295,6 +305,7 @@ RSpec.describe "bundle cache" do
:path => bundled_app("vendor/cache")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo-bundler"
G
diff --git a/spec/bundler/cache/git_spec.rb b/spec/bundler/cache/git_spec.rb
index 8123c514b6..b88993e9b1 100644
--- a/spec/bundler/cache/git_spec.rb
+++ b/spec/bundler/cache/git_spec.rb
@@ -18,6 +18,7 @@ RSpec.describe "bundle cache with git" do
ref = git.ref_for("master", 11)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
@@ -31,15 +32,17 @@ RSpec.describe "bundle cache with git" do
expect(the_bundle).to include_gems "foo 1.0"
end
- it "copies repository to vendor cache and uses it even when installed with bundle --path" do
+ it "copies repository to vendor cache and uses it even when configured with `path`" do
git = build_git "foo"
ref = git.ref_for("master", 11)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
- bundle "install --path vendor/bundle"
+ bundle "config set --local path vendor/bundle"
+ bundle "install"
bundle "config set cache_all true"
bundle :cache
@@ -53,13 +56,14 @@ RSpec.describe "bundle cache with git" do
it "runs twice without exploding" do
build_git "foo"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
bundle "config set cache_all true"
- bundle! :cache
- bundle! :cache
+ bundle :cache
+ bundle :cache
expect(out).to include "Updating files in vendor/cache"
FileUtils.rm_rf lib_path("foo-1.0")
@@ -71,6 +75,7 @@ RSpec.describe "bundle cache with git" do
old_ref = git.ref_for("master", 11)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
@@ -84,15 +89,15 @@ RSpec.describe "bundle cache with git" do
ref = git.ref_for("master", 11)
expect(ref).not_to eq(old_ref)
- bundle! "update", :all => true
+ bundle "update", :all => true
bundle "config set cache_all true"
- bundle! :cache
+ bundle :cache
expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
expect(bundled_app("vendor/cache/foo-1.0-#{old_ref}")).not_to exist
FileUtils.rm_rf lib_path("foo-1.0")
- run! "require 'foo'"
+ run "require 'foo'"
expect(out).to eq("CACHE")
end
@@ -101,11 +106,12 @@ RSpec.describe "bundle cache with git" do
old_ref = git.ref_for("master", 11)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
bundle "config set cache_all true"
- bundle! :cache
+ bundle :cache
update_git "foo" do |s|
s.write "lib/foo.rb", "puts :CACHE"
@@ -129,6 +135,7 @@ RSpec.describe "bundle cache with git" do
ref = git.ref_for("master", 11)
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :master
G
@@ -149,21 +156,17 @@ RSpec.describe "bundle cache with git" do
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])
-
build_git "submodule", "1.0"
git = build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
end
- Dir.chdir(lib_path("has_submodule-1.0")) do
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0"
- `git commit -m "submodulator"`
- end
+ sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0")
+ sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
@@ -178,32 +181,6 @@ RSpec.describe "bundle cache with git" do
expect(the_bundle).to include_gems "has_submodule 1.0"
end
- it "displays warning message when detecting git repo in Gemfile", :bundler => "< 3" do
- build_git "foo"
-
- install_gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
-
- bundle :cache
-
- expect(err).to include("Your Gemfile contains path and git dependencies.")
- end
-
- it "does not display warning message if cache_all is set in bundle config" do
- build_git "foo"
-
- install_gemfile <<-G
- gem "foo", :git => '#{lib_path("foo-1.0")}'
- G
-
- bundle "config set cache_all true"
- bundle :cache
- bundle :cache
-
- expect(err).not_to include("Your Gemfile contains path and git dependencies.")
- end
-
it "caches pre-evaluated gemspecs" do
git = build_git "foo"
@@ -213,6 +190,7 @@ 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)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
bundle "config set cache_all true"
@@ -227,15 +205,16 @@ RSpec.describe "bundle cache with git" do
build_git "foo"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
- bundle! "config set cache_all true"
- bundle! :cache, "all-platforms" => true, :install => false, :path => "./vendor/cache"
+ bundle "config set cache_all true"
+ bundle :cache, "all-platforms" => true, :install => false
simulate_new_machine
with_path_as "" do
- bundle! "config set deployment true"
- bundle! :install, :local => true
+ bundle "config set deployment true"
+ bundle :install, :local => true
expect(the_bundle).to include_gem "foo 1.0"
end
end
diff --git a/spec/bundler/cache/path_spec.rb b/spec/bundler/cache/path_spec.rb
index 79e8b4a82b..2ad136a008 100644
--- a/spec/bundler/cache/path_spec.rb
+++ b/spec/bundler/cache/path_spec.rb
@@ -5,6 +5,7 @@ RSpec.describe "bundle cache with path" do
build_lib "foo", :path => bundled_app("lib/foo")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{bundled_app("lib/foo")}'
G
@@ -18,6 +19,7 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -26,17 +28,17 @@ RSpec.describe "bundle cache with path" do
expect(bundled_app("vendor/cache/foo-1.0")).to exist
expect(bundled_app("vendor/cache/foo-1.0/.bundlecache")).to be_file
- FileUtils.rm_rf lib_path("foo-1.0")
expect(the_bundle).to include_gems "foo 1.0"
end
it "copies when the path is outside the bundle and the paths intersect" do
- libname = File.basename(Dir.pwd) + "_gem"
- libpath = File.join(File.dirname(Dir.pwd), libname)
+ libname = File.basename(bundled_app) + "_gem"
+ libpath = File.join(File.dirname(bundled_app), libname)
build_lib libname, :path => libpath
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "#{libname}", :path => '#{libpath}'
G
@@ -45,7 +47,6 @@ RSpec.describe "bundle cache with path" do
expect(bundled_app("vendor/cache/#{libname}")).to exist
expect(bundled_app("vendor/cache/#{libname}/.bundlecache")).to be_file
- FileUtils.rm_rf libpath
expect(the_bundle).to include_gems "#{libname} 1.0"
end
@@ -53,6 +54,7 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -66,7 +68,6 @@ RSpec.describe "bundle cache with path" do
bundle :cache
expect(bundled_app("vendor/cache/foo-1.0")).to exist
- FileUtils.rm_rf lib_path("foo-1.0")
run "require 'foo'"
expect(out).to eq("CACHE")
@@ -76,36 +77,57 @@ RSpec.describe "bundle cache with path" 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
+ expect(bundled_app("vendor/cache/foo-1.0")).to exist
+
+ build_lib "bar"
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "bar", :path => '#{lib_path("bar-1.0")}'
G
bundle :cache
- expect(bundled_app("vendor/cache/bar-1.0")).not_to exist
+ expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
end
- it "raises a warning without --all", :bundler => "< 3" do
+ it "does not cache path gems by default", :bundler => "< 3" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
bundle :cache
- expect(err).to match(/please pass the \-\-all flag/)
+ expect(err).to be_empty
expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
end
+ it "caches path gems by default", :bundler => "3" do
+ build_lib "foo"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :path => '#{lib_path("foo-1.0")}'
+ G
+
+ bundle :cache
+ expect(err).to be_empty
+ expect(bundled_app("vendor/cache/foo-1.0")).to exist
+ end
+
it "stores the given flag" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -114,6 +136,7 @@ RSpec.describe "bundle cache with path" do
build_lib "bar"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
gem "bar", :path => '#{lib_path("bar-1.0")}'
G
@@ -126,6 +149,7 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -134,11 +158,12 @@ RSpec.describe "bundle cache with path" do
build_lib "baz"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => '#{lib_path("foo-1.0")}'
gem "baz", :path => '#{lib_path("baz-1.0")}'
G
- bundle "cache --no-all"
+ bundle "cache --no-all", :raise_on_error => false
expect(bundled_app("vendor/cache/baz-1.0")).not_to exist
end
end
diff --git a/spec/bundler/cache/platform_spec.rb b/spec/bundler/cache/platform_spec.rb
index b65bb06ae6..128278956c 100644
--- a/spec/bundler/cache/platform_spec.rb
+++ b/spec/bundler/cache/platform_spec.rb
@@ -34,14 +34,14 @@ RSpec.describe "bundle cache with multiple platforms" do
end
it "ensures that a successful bundle install does not delete gems for other platforms" do
- bundle! "install"
+ bundle "install"
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist
end
it "ensures that a successful bundle update does not delete gems for other platforms" do
- bundle! "update", :all => true
+ bundle "update", :all => true
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist
diff --git a/spec/bundler/commands/add_spec.rb b/spec/bundler/commands/add_spec.rb
index 35fd43d3d2..4c533652ca 100644
--- a/spec/bundler/commands/add_spec.rb
+++ b/spec/bundler/commands/add_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe "bundle add" do
build_git "foo", "2.0"
- install_gemfile <<-G
+ gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "weakling", "~> 0.0.1"
G
@@ -21,7 +21,7 @@ RSpec.describe "bundle add" do
context "when no gems are specified" do
it "shows error" do
- bundle "add"
+ bundle "add", :raise_on_error => false
expect(err).to include("Please specify gems to add")
end
@@ -30,25 +30,25 @@ RSpec.describe "bundle add" do
describe "without version specified" do
it "version requirement becomes ~> major.minor.patch when resolved version is < 1.0" do
bundle "add 'bar'"
- expect(bundled_app("Gemfile").read).to match(/gem "bar", "~> 0.12.3"/)
+ expect(bundled_app_gemfile.read).to match(/gem "bar", "~> 0.12.3"/)
expect(the_bundle).to include_gems "bar 0.12.3"
end
it "version requirement becomes ~> major.minor when resolved version is > 1.0" do
bundle "add 'baz'"
- expect(bundled_app("Gemfile").read).to match(/gem "baz", "~> 1.2"/)
+ expect(bundled_app_gemfile.read).to match(/gem "baz", "~> 1.2"/)
expect(the_bundle).to include_gems "baz 1.2.3"
end
it "version requirement becomes ~> major.minor.patch.pre when resolved version is < 1.0" do
bundle "add 'cat'"
- expect(bundled_app("Gemfile").read).to match(/gem "cat", "~> 0.12.3.pre"/)
+ expect(bundled_app_gemfile.read).to match(/gem "cat", "~> 0.12.3.pre"/)
expect(the_bundle).to include_gems "cat 0.12.3.pre"
end
it "version requirement becomes ~> major.minor.pre when resolved version is > 1.0.pre" do
bundle "add 'dog'"
- expect(bundled_app("Gemfile").read).to match(/gem "dog", "~> 1.1.pre"/)
+ expect(bundled_app_gemfile.read).to match(/gem "dog", "~> 1.1.pre"/)
expect(the_bundle).to include_gems "dog 1.1.3.pre"
end
end
@@ -56,14 +56,14 @@ RSpec.describe "bundle add" do
describe "with --version" do
it "adds dependency of specified version and runs install" do
bundle "add 'foo' --version='~> 1.0'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 1.0"/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 1.0"/)
expect(the_bundle).to include_gems "foo 1.1"
end
it "adds multiple version constraints when specified" do
requirements = ["< 3.0", "> 1.0"]
bundle "add 'foo' --version='#{requirements.join(", ")}'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", #{Gem::Requirement.new(requirements).as_list.map(&:dump).join(', ')}/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", #{Gem::Requirement.new(requirements).as_list.map(&:dump).join(', ')}/)
expect(the_bundle).to include_gems "foo 2.0"
end
end
@@ -71,13 +71,13 @@ RSpec.describe "bundle add" do
describe "with --group" do
it "adds dependency for the specified group" do
bundle "add 'foo' --group='development'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :group => :development/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :group => :development/)
expect(the_bundle).to include_gems "foo 2.0"
end
it "adds dependency to more than one group" do
bundle "add 'foo' --group='development, test'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :groups => \[:development, :test\]/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :groups => \[:development, :test\]/)
expect(the_bundle).to include_gems "foo 2.0"
end
end
@@ -86,7 +86,7 @@ RSpec.describe "bundle add" do
it "adds dependency with specified source" do
bundle "add 'foo' --source='#{file_uri_for(gem_repo2)}'"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "~> 2.0", :source => "#{file_uri_for(gem_repo2)}"/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :source => "#{file_uri_for(gem_repo2)}"/)
expect(the_bundle).to include_gems "foo 2.0"
end
end
@@ -95,7 +95,7 @@ RSpec.describe "bundle add" do
it "adds dependency with specified github 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
@@ -108,7 +108,7 @@ RSpec.describe "bundle add" do
it "adds dependency with specified github 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
@@ -117,66 +117,66 @@ RSpec.describe "bundle add" do
it "adds gem to Gemfile but is not installed" do
bundle "add foo --skip-install --version=2.0"
- expect(bundled_app("Gemfile").read).to match(/gem "foo", "= 2.0"/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "= 2.0"/)
expect(the_bundle).to_not include_gems "foo 2.0"
end
end
it "using combination of short form options works like long form" do
bundle "add 'foo' -s='#{file_uri_for(gem_repo2)}' -g='development' -v='~>1.0'"
- expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 1.0", :group => :development, :source => "#{file_uri_for(gem_repo2)}")
+ expect(bundled_app_gemfile.read).to include %(gem "foo", "~> 1.0", :group => :development, :source => "#{file_uri_for(gem_repo2)}")
expect(the_bundle).to include_gems "foo 1.1"
end
it "shows error message when version is not formatted correctly" do
- bundle "add 'foo' -v='~>1 . 0'"
+ bundle "add 'foo' -v='~>1 . 0'", :raise_on_error => false
expect(err).to match("Invalid gem requirement pattern '~>1 . 0'")
end
it "shows error message when gem cannot be found" do
bundle "config set force_ruby_platform true"
- bundle "add 'werk_it'"
+ bundle "add 'werk_it'", :raise_on_error => false
expect(err).to match("Could not find gem 'werk_it' in")
- bundle "add 'werk_it' -s='#{file_uri_for(gem_repo2)}'"
+ bundle "add 'werk_it' -s='#{file_uri_for(gem_repo2)}'", :raise_on_error => false
expect(err).to match("Could not find gem 'werk_it' in rubygems repository")
end
it "shows error message when source cannot be reached" do
- bundle "add 'baz' --source='http://badhostasdf'"
+ bundle "add 'baz' --source='http://badhostasdf'", :raise_on_error => false
expect(err).to include("Could not reach host badhostasdf. Check your network connection and try again.")
- bundle "add 'baz' --source='file://does/not/exist'"
+ bundle "add 'baz' --source='file://does/not/exist'", :raise_on_error => false
expect(err).to include("Could not fetch specs from file://does/not/exist/")
end
describe "with --optimistic" do
it "adds optimistic version" do
- bundle! "add 'foo' --optimistic"
- expect(bundled_app("Gemfile").read).to include %(gem "foo", ">= 2.0")
+ bundle "add 'foo' --optimistic"
+ expect(bundled_app_gemfile.read).to include %(gem "foo", ">= 2.0")
expect(the_bundle).to include_gems "foo 2.0"
end
end
describe "with --strict option" do
it "adds strict version" do
- bundle! "add 'foo' --strict"
- expect(bundled_app("Gemfile").read).to include %(gem "foo", "= 2.0")
+ bundle "add 'foo' --strict"
+ expect(bundled_app_gemfile.read).to include %(gem "foo", "= 2.0")
expect(the_bundle).to include_gems "foo 2.0"
end
end
describe "with no option" do
it "adds pessimistic version" do
- bundle! "add 'foo'"
- expect(bundled_app("Gemfile").read).to include %(gem "foo", "~> 2.0")
+ bundle "add 'foo'"
+ expect(bundled_app_gemfile.read).to include %(gem "foo", "~> 2.0")
expect(the_bundle).to include_gems "foo 2.0"
end
end
describe "with --optimistic and --strict" do
it "throws error" do
- bundle "add 'foo' --strict --optimistic"
+ bundle "add 'foo' --strict --optimistic", :raise_on_error => false
expect(err).to include("You can not specify `--strict` and `--optimistic` at the same time")
end
@@ -184,14 +184,14 @@ RSpec.describe "bundle add" do
context "multiple gems" do
it "adds multiple gems to gemfile" do
- bundle! "add bar baz"
+ bundle "add bar baz"
- expect(bundled_app("Gemfile").read).to match(/gem "bar", "~> 0.12.3"/)
- expect(bundled_app("Gemfile").read).to match(/gem "baz", "~> 1.2"/)
+ expect(bundled_app_gemfile.read).to match(/gem "bar", "~> 0.12.3"/)
+ expect(bundled_app_gemfile.read).to match(/gem "baz", "~> 1.2"/)
end
it "throws error if any of the specified gems are present in the gemfile with different version" do
- bundle "add weakling bar"
+ bundle "add weakling bar", :raise_on_error => false
expect(err).to include("You cannot specify the same gem twice with different version requirements")
expect(err).to include("You specified: weakling (~> 0.0.1) and weakling (>= 0).")
@@ -205,7 +205,7 @@ RSpec.describe "bundle add" do
gem "rack", "1.0"
G
- bundle "add 'rack' --version=1.1"
+ bundle "add 'rack' --version=1.1", :raise_on_error => false
expect(err).to include("You cannot specify the same gem twice with different version requirements")
expect(err).to include("If you want to update the gem version, run `bundle update rack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
@@ -217,7 +217,7 @@ RSpec.describe "bundle add" do
gem "rack", "1.0"
G
- bundle "add 'rack'"
+ bundle "add 'rack'", :raise_on_error => false
expect(err).to include("Gem already added.")
expect(err).to include("You cannot specify the same gem twice with different version requirements")
@@ -232,7 +232,7 @@ RSpec.describe "bundle add" do
gem "rack"
G
- bundle "add 'rack' --version=1.1"
+ bundle "add 'rack' --version=1.1", :raise_on_error => false
expect(err).to include("You cannot specify the same gem twice with different version requirements")
expect(err).to include("If you want to update the gem version, run `bundle update rack`.")
@@ -242,7 +242,7 @@ RSpec.describe "bundle add" do
describe "when a gem is added and cache exists" do
it "caches all new dependencies added for the specified gem" do
- bundle! :cache
+ bundle :cache
bundle "add 'rack' --version=1.0.0"
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
diff --git a/spec/bundler/commands/binstubs_spec.rb b/spec/bundler/commands/binstubs_spec.rb
index 7c04e8ddbd..1cd0e16d95 100644
--- a/spec/bundler/commands/binstubs_spec.rb
+++ b/spec/bundler/commands/binstubs_spec.rb
@@ -40,25 +40,37 @@ RSpec.describe "bundle binstubs <gem>" do
end
it "allows installing all binstubs" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
G
- bundle! :binstubs, :all => true
+ bundle :binstubs, :all => true
expect(bundled_app("bin/rails")).to exist
expect(bundled_app("bin/rake")).to exist
end
+ it "allows installing binstubs for all platforms" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ bundle "binstubs rack --all-platforms"
+
+ expect(bundled_app("bin/rackup")).to exist
+ expect(bundled_app("bin/rackup.cmd")).to exist
+ end
+
it "displays an error when used without any gem" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- bundle "binstubs"
- expect(exitstatus).to eq(1) if exitstatus
+ bundle "binstubs", :raise_on_error => false
+ expect(exitstatus).to eq(1)
expect(err).to include("`bundle binstubs` needs at least one gem to run.")
end
@@ -68,7 +80,7 @@ RSpec.describe "bundle binstubs <gem>" do
gem "rack"
G
- bundle "binstubs rack", :all => true
+ bundle "binstubs rack", :all => true, :raise_on_error => false
expect(last_command).to be_failure
expect(err).to include("Cannot specify --all with specific gems")
end
@@ -82,11 +94,11 @@ RSpec.describe "bundle binstubs <gem>" do
bundle "binstubs rack"
- File.open("bin/bundle", "wb") do |file|
+ File.open(bundled_app("bin/bundle"), "wb") do |file|
file.print "OMG"
end
- sys_exec "bin/rackup"
+ sys_exec "bin/rackup", :raise_on_error => false
expect(err).to include("was not generated by Bundler")
end
@@ -94,49 +106,49 @@ RSpec.describe "bundle binstubs <gem>" do
context "the bundle binstub" do
before do
- if system_bundler_version == :bundler
- system_gems :bundler
- elsif system_bundler_version
- build_repo4 do
- build_gem "bundler", system_bundler_version do |s|
- s.executables = "bundle"
- s.bindir = "exe"
- s.write "exe/bundle", "puts %(system bundler #{system_bundler_version}\\n\#{ARGV.inspect})"
- end
- end
- system_gems "bundler-#{system_bundler_version}", :gem_repo => gem_repo4
- end
+ pristine_system_gems "bundler-#{system_bundler_version}"
build_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "prints_loaded_gems", "1.0" do |s|
s.executables = "print_loaded_gems"
s.bindir = "exe"
s.write "exe/print_loaded_gems", <<-R
- specs = Gem.loaded_specs.values.reject {|s| Bundler.rubygems.spec_default_gem?(s) }
+ specs = Gem.loaded_specs.values.reject {|s| s.default_gem? }
puts specs.map(&:full_name).sort.inspect
R
end
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rack"
gem "prints_loaded_gems"
G
- bundle! "binstubs bundler rack prints_loaded_gems"
+ bundle "binstubs bundler rack prints_loaded_gems"
end
let(:system_bundler_version) { Bundler::VERSION }
it "runs bundler" do
- sys_exec! "#{bundled_app("bin/bundle")} install"
- expect(out).to eq %(system bundler #{system_bundler_version}\n["install"])
+ sys_exec "bin/bundle install", :env => { "DEBUG" => "1" }
+ expect(out).to include %(Using bundler #{system_bundler_version}\n)
end
context "when BUNDLER_VERSION is set" do
it "runs the correct version of bundler" do
- sys_exec "#{bundled_app("bin/bundle")} install", "BUNDLER_VERSION" => "999.999.999"
- expect(exitstatus).to eq(42) if exitstatus
- expect(err).to include("Activating bundler (~> 999.999) failed:").
- and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 999.999'`")
+ sys_exec "bin/bundle install", :env => { "BUNDLER_VERSION" => "999.999.999" }, :raise_on_error => false
+ expect(exitstatus).to eq(42)
+ expect(err).to include("Activating bundler (999.999.999) failed:").
+ and include("To install the version of bundler this project requires, run `gem install bundler -v '999.999.999'`")
+ end
+
+ it "runs the correct version of bundler even if a higher version is installed" do
+ system_gems "bundler-999.999.998", "bundler-999.999.999"
+
+ sys_exec "bin/bundle install", :env => { "BUNDLER_VERSION" => "999.999.998", "DEBUG" => "1" }, :raise_on_error => false
+ expect(out).to include %(Using bundler 999.999.998\n)
end
end
@@ -147,8 +159,8 @@ RSpec.describe "bundle binstubs <gem>" do
end
it "runs the correct version of bundler" do
- sys_exec "#{bundled_app("bin/bundle")} install"
- expect(exitstatus).to eq(42) if exitstatus
+ sys_exec "bin/bundle install", :raise_on_error => false
+ expect(exitstatus).to eq(42)
expect(err).to include("Activating bundler (~> 999.999) failed:").
and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 999.999'`")
end
@@ -162,8 +174,8 @@ RSpec.describe "bundle binstubs <gem>" do
end
it "runs the correct version of bundler" do
- sys_exec "#{bundled_app("bin/bundle")} install"
- expect(exitstatus).to eq(42) if exitstatus
+ sys_exec "bin/bundle install", :raise_on_error => false
+ expect(exitstatus).to eq(42)
expect(err).to include("Activating bundler (~> 44.0) failed:").
and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 44.0'`")
end
@@ -177,8 +189,8 @@ RSpec.describe "bundle binstubs <gem>" do
end
it "runs the available version of bundler when the version is older and the same major" do
- sys_exec "#{bundled_app("bin/bundle")} install"
- expect(exitstatus).not_to eq(42) if exitstatus
+ sys_exec "bin/bundle install"
+ expect(exitstatus).not_to eq(42)
expect(err).not_to include("Activating bundler (~> 55.0) failed:")
end
end
@@ -191,8 +203,8 @@ RSpec.describe "bundle binstubs <gem>" do
end
it "runs the correct version of bundler when the version is a pre-release" do
- sys_exec "#{bundled_app("bin/bundle")} install"
- expect(exitstatus).to eq(42) if exitstatus
+ sys_exec "bin/bundle install", :raise_on_error => false
+ expect(exitstatus).to eq(42)
expect(err).to include("Activating bundler (~> 2.12.a) failed:").
and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 2.12.a'`")
end
@@ -203,30 +215,29 @@ RSpec.describe "bundle binstubs <gem>" do
before { lockfile.gsub(system_bundler_version, "1.1.1") }
it "calls through to the latest bundler version" do
- sys_exec! "#{bundled_app("bin/bundle")} update --bundler"
- expect(out).to eq %(system bundler #{system_bundler_version}\n["update", "--bundler"])
+ sys_exec "bin/bundle update --bundler", :env => { "DEBUG" => "1" }
+ expect(out).to include %(Using bundler #{system_bundler_version}\n)
end
it "calls through to the explicit bundler version" do
- sys_exec "#{bundled_app("bin/bundle")} update --bundler=999.999.999"
- expect(exitstatus).to eq(42) if exitstatus
- expect(err).to include("Activating bundler (~> 999.999) failed:").
- and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 999.999'`")
+ sys_exec "bin/bundle update --bundler=999.999.999", :raise_on_error => false
+ expect(exitstatus).to eq(42)
+ expect(err).to include("Activating bundler (999.999.999) failed:").
+ and include("To install the version of bundler this project requires, run `gem install bundler -v '999.999.999'`")
end
end
context "without a lockfile" do
it "falls back to the latest installed bundler" do
- FileUtils.rm bundled_app("Gemfile.lock")
- sys_exec! bundled_app("bin/bundle").to_s
- expect(out).to eq "system bundler #{system_bundler_version}\n[]"
+ FileUtils.rm bundled_app_lock
+ sys_exec "bin/bundle install", :env => { "DEBUG" => "1" }
+ expect(out).to include "Using bundler #{system_bundler_version}\n"
end
end
context "using another binstub" do
- let(:system_bundler_version) { :bundler }
it "loads all gems" do
- sys_exec! bundled_app("bin/print_loaded_gems").to_s
+ sys_exec bundled_app("bin/print_loaded_gems").to_s
expect(out).to eq %(["bundler-#{Bundler::VERSION}", "prints_loaded_gems-1.0", "rack-1.2"])
end
@@ -234,8 +245,8 @@ RSpec.describe "bundle binstubs <gem>" 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
- expect(exitstatus).to eq(42) if exitstatus
+ sys_exec bundled_app("bin/rackup").to_s, :raise_on_error => false
+ expect(exitstatus).to eq(42)
expect(err).to include("Activating bundler (~> 999.999) failed:").
and include("To install the version of bundler this project requires, run `gem install bundler -v '~> 999.999'`")
end
@@ -250,6 +261,7 @@ RSpec.describe "bundle binstubs <gem>" do
s.executables = %w[foo]
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo")}"
G
@@ -265,6 +277,7 @@ RSpec.describe "bundle binstubs <gem>" do
s.executables = %w[foo]
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo")}"
G
@@ -282,7 +295,7 @@ RSpec.describe "bundle binstubs <gem>" do
bundle "binstubs rack"
binary = bundled_app("bin/rackup")
- expect(File.stat(binary).mode.to_s(8)).to eq("100775")
+ expect(File.stat(binary).mode.to_s(8)).to eq(Gem.win_platform? ? "100644" : "100775")
end
end
@@ -294,8 +307,7 @@ RSpec.describe "bundle binstubs <gem>" do
G
bundle "binstubs rack --shebang jruby"
-
- expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env jruby\n")
+ expect(File.readlines(bundled_app("bin/rackup")).first).to eq("#!/usr/bin/env jruby\n")
end
end
end
@@ -306,9 +318,9 @@ RSpec.describe "bundle binstubs <gem>" do
source "#{file_uri_for(gem_repo1)}"
G
- bundle "binstubs doesnt_exist"
+ bundle "binstubs doesnt_exist", :raise_on_error => false
- expect(exitstatus).to eq(7) if exitstatus
+ expect(exitstatus).to eq(7)
expect(err).to include("Could not find gem 'doesnt_exist'.")
end
end
@@ -332,8 +344,8 @@ RSpec.describe "bundle binstubs <gem>" do
gem "rails"
G
- bundle! "binstubs rack", :path => "exec"
- bundle! :install
+ bundle "binstubs rack", :path => "exec"
+ bundle :install
expect(bundled_app("exec/rails")).to exist
end
@@ -348,21 +360,29 @@ RSpec.describe "bundle binstubs <gem>" do
end
it "generates a standalone binstub" do
- bundle! "binstubs rack --standalone"
+ bundle "binstubs rack --standalone"
expect(bundled_app("bin/rackup")).to exist
end
it "generates a binstub that does not depend on rubygems or bundler" do
- bundle! "binstubs rack --standalone"
+ bundle "binstubs rack --standalone"
expect(File.read(bundled_app("bin/rackup"))).to_not include("Gem.bin_path")
end
context "when specified --path option" do
it "generates a standalone binstub at the given path" do
- bundle! "binstubs rack --standalone --path foo"
+ bundle "binstubs rack --standalone --path foo"
expect(bundled_app("foo/rackup")).to exist
end
end
+
+ context "when specified --all-platforms option" do
+ it "generates standalone binstubs for all platforms" do
+ bundle "binstubs rack --standalone --all-platforms"
+ expect(bundled_app("bin/rackup")).to exist
+ expect(bundled_app("bin/rackup.cmd")).to exist
+ end
+ end
end
context "when the bin already exists" do
@@ -428,8 +448,14 @@ RSpec.describe "bundle binstubs <gem>" do
end
it "works if the gem has development dependencies" do
+ build_repo2 do
+ build_gem "with_development_dependency" do |s|
+ s.add_development_dependency "activesupport", "= 2.3.5"
+ end
+ end
+
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "with_development_dependency"
G
diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb
index 07ec186c2f..9bb85c6587 100644
--- a/spec/bundler/commands/cache_spec.rb
+++ b/spec/bundler/commands/cache_spec.rb
@@ -1,6 +1,19 @@
# frozen_string_literal: true
RSpec.describe "bundle cache" do
+ it "doesn't update the cache multiple times, even if it already exists" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ bundle :cache
+ expect(out).to include("Updating files in vendor/cache").once
+
+ bundle :cache
+ expect(out).to include("Updating files in vendor/cache").once
+ end
+
context "with --gemfile" do
it "finds the gemfile" do
gemfile bundled_app("NotGemfile"), <<-G
@@ -56,7 +69,7 @@ RSpec.describe "bundle cache" do
D
bundle "config set cache_all true"
- bundle! :cache
+ bundle :cache
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
@@ -88,7 +101,7 @@ RSpec.describe "bundle cache" do
D
bundle "config set cache_all true"
- bundle! :cache
+ bundle :cache
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
@@ -133,7 +146,7 @@ RSpec.describe "bundle cache" do
D
bundle "config set cache_all true"
- bundle! :cache
+ bundle :cache
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
@@ -152,7 +165,7 @@ RSpec.describe "bundle cache" do
gem 'rack'
D
- bundle! :cache, forgotten_command_line_options(:path => bundled_app("test"))
+ bundle "cache --path #{bundled_app("test")}"
expect(the_bundle).to include_gems "rack 1.0.0"
expect(bundled_app("test/vendor/cache/")).to exist
@@ -166,7 +179,7 @@ RSpec.describe "bundle cache" do
gem 'rack'
D
- bundle! "cache --no-install"
+ bundle "cache --no-install"
expect(the_bundle).not_to include_gems "rack 1.0.0"
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
@@ -178,8 +191,8 @@ RSpec.describe "bundle cache" do
gem 'rack'
D
- bundle! "cache --no-install"
- bundle! "install"
+ bundle "cache --no-install"
+ bundle "install"
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -190,14 +203,18 @@ RSpec.describe "bundle cache" do
gem "rack", "1.0.0"
D
- bundle! "cache --no-install"
- bundle! "update --all"
+ bundle "cache --no-install"
+ bundle "update --all"
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
context "with --all-platforms" do
+ before do
+ skip "doesn't put gems where it should" if Gem.win_platform?
+ end
+
it "puts the gems in vendor/cache even for other rubies" do
gemfile <<-D
source "#{file_uri_for(gem_repo1)}"
@@ -217,7 +234,8 @@ RSpec.describe "bundle cache" do
end
end
- install_gemfile! <<-G, forgotten_command_line_options(:without => "wo")
+ bundle "config set --local without wo"
+ install_gemfile <<-G
source "file:#{gem_repo1}"
gem "rack"
group :wo do
@@ -226,19 +244,35 @@ RSpec.describe "bundle cache" do
end
G
- bundle! :cache, "all-platforms" => true
+ bundle :cache, "all-platforms" => true
expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist
expect(bundled_app("vendor/cache/uninstallable-2.0.gem")).to exist
expect(the_bundle).to include_gem "rack 1.0"
expect(the_bundle).not_to include_gems "weakling", "uninstallable"
- bundle! :install, forgotten_command_line_options(:without => "wo")
+ bundle "config set --local without wo"
+ bundle :install
expect(the_bundle).to include_gem "rack 1.0"
expect(the_bundle).not_to include_gems "weakling", "uninstallable"
end
+
+ it "does not fail to cache gems in excluded groups when there's a lockfile but gems not previously installed" do
+ bundle "config set --local without wo"
+ gemfile <<-G
+ source "https://my.gem.repo.1"
+ gem "rack"
+ group :wo do
+ gem "weakling"
+ end
+ G
+
+ bundle :lock, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ bundle :cache, "all-platforms" => true, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist
+ end
end
- context "with --frozen" do
+ context "with frozen configured" do
before do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -247,17 +281,20 @@ RSpec.describe "bundle cache" do
bundle "install"
end
- subject { bundle :cache, forgotten_command_line_options(:frozen => true) }
+ subject do
+ bundle "config set --local frozen true"
+ bundle :cache, :raise_on_error => false
+ end
it "tries to install with frozen" do
- bundle! "config set deployment true"
+ bundle "config set deployment true"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
gem "rack-obama"
G
subject
- expect(exitstatus).to eq(16) if exitstatus
+ expect(exitstatus).to eq(16)
expect(err).to include("deployment mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
@@ -265,6 +302,30 @@ RSpec.describe "bundle cache" do
expect(out).to include("frozen").or include("deployment")
end
end
+
+ context "with gems with extensions" do
+ before do
+ build_repo2 do
+ build_gem "racc", "2.0" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", "task(:default) { puts 'INSTALLING rack' }"
+ end
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "racc"
+ G
+ end
+
+ it "installs them properly from cache to a different path" do
+ bundle "cache"
+ bundle "config set --local path vendor/bundle"
+ bundle "install --local"
+ end
+ end
end
RSpec.describe "bundle install with gem sources" do
@@ -284,18 +345,38 @@ RSpec.describe "bundle install with gem sources" do
expect(the_bundle).to include_gems "rack 1.0.0"
end
- it "does not hit the remote at all" do
+ it "does not hit the remote at all in frozen mode" do
build_repo2
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
- bundle! :cache
+ bundle :cache
simulate_new_machine
FileUtils.rm_rf gem_repo2
- bundle! :install, forgotten_command_line_options(:deployment => true, :path => "vendor/bundle")
+ bundle "config set --local deployment true"
+ bundle "config set --local path vendor/bundle"
+ bundle :install
+ expect(the_bundle).to include_gems "rack 1.0.0"
+ end
+
+ it "does not hit the remote at all when cache_all_platforms configured" do
+ build_repo2
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack"
+ G
+
+ bundle :cache
+ simulate_new_machine
+ FileUtils.rm_rf 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"
end
diff --git a/spec/bundler/commands/check_spec.rb b/spec/bundler/commands/check_spec.rb
index c755ef2804..1fa35136eb 100644
--- a/spec/bundler/commands/check_spec.rb
+++ b/spec/bundler/commands/check_spec.rb
@@ -8,7 +8,6 @@ RSpec.describe "bundle check" do
G
bundle :check
- expect(exitstatus).to eq(0) if exitstatus
expect(out).to include("The Gemfile's dependencies are satisfied")
end
@@ -18,8 +17,7 @@ RSpec.describe "bundle check" do
gem "rails"
G
- Dir.chdir tmp
- bundle "check --gemfile bundled_app/Gemfile"
+ bundle "check --gemfile bundled_app/Gemfile", :dir => tmp
expect(out).to include("The Gemfile's dependencies are satisfied")
end
@@ -29,11 +27,11 @@ RSpec.describe "bundle check" do
gem "rails"
G
- FileUtils.rm("Gemfile.lock")
+ FileUtils.rm(bundled_app_lock)
bundle "check"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
it "does not create a Gemfile.lock if --dry-run was passed" do
@@ -42,11 +40,11 @@ RSpec.describe "bundle check" do
gem "rails"
G
- FileUtils.rm("Gemfile.lock")
+ FileUtils.rm(bundled_app_lock)
bundle "check --dry-run"
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
end
it "prints a generic error if the missing gems are unresolvable" do
@@ -57,7 +55,7 @@ RSpec.describe "bundle check" do
gem "rails"
G
- bundle :check
+ bundle :check, :raise_on_error => false
expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
end
@@ -67,28 +65,30 @@ RSpec.describe "bundle check" do
gem "rails"
G
- bundle :check
- expect(exitstatus).to be > 0 if exitstatus
+ bundle :check, :raise_on_error => false
+ expect(exitstatus).to be > 0
expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
end
it "prints a generic message if you changed your lockfile" do
+ build_repo2 do
+ build_gem "rails_pinned_to_old_activesupport" do |s|
+ s.add_dependency "activesupport", "= 1.2.3"
+ end
+ end
+
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem 'rails'
G
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rails_fail'
- G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rails"
- gem "rails_fail"
+ gem "rails_pinned_to_old_activesupport"
G
- bundle :check
+ bundle :check, :raise_on_error => false
expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
end
@@ -100,21 +100,21 @@ RSpec.describe "bundle check" do
end
G
- bundle! "install --without foo"
- bundle! "check"
+ bundle "install --without foo"
+ bundle "check"
expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "uses the without setting" do
- bundle! "config set without foo"
- install_gemfile! <<-G
+ bundle "config set without foo"
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
group :foo do
gem "rack"
end
G
- bundle! "check"
+ bundle "check"
expect(out).to include("The Gemfile's dependencies are satisfied")
end
@@ -124,16 +124,33 @@ RSpec.describe "bundle check" do
gem "rack", :group => :foo
G
- bundle :install, forgotten_command_line_options(:without => "foo")
+ bundle "config set --local without foo"
+ bundle :install
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- bundle "check"
+ bundle "check", :raise_on_error => false
+ expect(err).to include("* rack (1.0.0)")
+ expect(exitstatus).to eq(1)
+ end
+
+ it "ensures that gems are actually installed and not just cached in applications' cache" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ bundle "config set --local path vendor/bundle"
+ bundle :cache
+
+ gem_command "uninstall rack", :env => { "GEM_HOME" => vendored_gems.to_s }
+
+ bundle "check", :raise_on_error => false
expect(err).to include("* rack (1.0.0)")
- expect(exitstatus).to eq(1) if exitstatus
+ expect(exitstatus).to eq(1)
end
it "ignores missing gems restricted to other platforms" do
@@ -145,7 +162,7 @@ RSpec.describe "bundle check" do
end
G
- system_gems "rack-1.0.0", :path => :bundle_path
+ system_gems "rack-1.0.0", :path => default_bundle_path
lockfile <<-G
GEM
@@ -176,7 +193,7 @@ RSpec.describe "bundle check" do
end
G
- system_gems "rack-1.0.0", :path => :bundle_path
+ system_gems "rack-1.0.0", :path => default_bundle_path
lockfile <<-G
GEM
@@ -199,42 +216,28 @@ RSpec.describe "bundle check" do
end
it "outputs an error when the default Gemfile is not found" do
- bundle :check
- expect(exitstatus).to eq(10) if exitstatus
+ bundle :check, :raise_on_error => false
+ expect(exitstatus).to eq(10)
expect(err).to include("Could not locate Gemfile")
end
it "does not output fatal error message" do
- bundle :check
- expect(exitstatus).to eq(10) if exitstatus
+ bundle :check, :raise_on_error => false
+ expect(exitstatus).to eq(10)
expect(err).not_to include("Unfortunately, a fatal error has occurred. ")
end
- it "should not crash when called multiple times on a new machine" do
- gemfile <<-G
- gem 'rails', '3.0.0.beta3'
- gem 'paperclip', :git => 'git://github.com/thoughtbot/paperclip.git'
- G
-
- simulate_new_machine
- bundle "check"
- last_out = out
- 3.times do
- bundle :check
- expect(out).to eq(last_out)
- end
- end
-
it "fails when there's no lock file and frozen is set" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "foo"
G
- bundle! "install", forgotten_command_line_options(:deployment => true)
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ bundle "config set --local deployment true"
+ bundle "install"
+ FileUtils.rm(bundled_app_lock)
- bundle :check
+ bundle :check, :raise_on_error => false
expect(last_command).to be_failure
end
@@ -251,13 +254,13 @@ RSpec.describe "bundle check" do
end
it "returns success" do
- bundle! "check --path vendor/bundle"
+ bundle "check --path vendor/bundle"
expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "should write to .bundle/config" do
bundle "check --path vendor/bundle"
- bundle! "check"
+ bundle "check"
end
end
@@ -268,11 +271,11 @@ RSpec.describe "bundle check" do
gem "rails"
G
- bundle "check --path vendor/bundle"
+ bundle "check --path vendor/bundle", :raise_on_error => false
end
it "returns false" do
- expect(exitstatus).to eq(1) if exitstatus
+ expect(exitstatus).to eq(1)
expect(err).to match(/The following gems are missing/)
end
end
@@ -290,21 +293,147 @@ RSpec.describe "bundle check" do
it "returns success when the Gemfile is satisfied" do
bundle :install
bundle :check
- expect(exitstatus).to eq(0) if exitstatus
expect(out).to include("The Gemfile's dependencies are satisfied")
end
it "shows what is missing with the current Gemfile if it is not satisfied" do
simulate_new_machine
- bundle :check
+ bundle :check, :raise_on_error => false
expect(err).to match(/The following gems are missing/)
expect(err).to include("* rack (1.0")
end
end
+ describe "when locked with multiple dependents with different requirements" do
+ before :each do
+ build_repo4 do
+ build_gem "depends_on_rack" do |s|
+ s.add_dependency "rack", ">= 1.0"
+ end
+ build_gem "also_depends_on_rack" do |s|
+ s.add_dependency "rack", "~> 1.0"
+ end
+ build_gem "rack"
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "depends_on_rack"
+ gem "also_depends_on_rack"
+ G
+
+ bundle "lock"
+ end
+
+ it "shows what is missing with the current Gemfile without duplications" do
+ bundle :check, :raise_on_error => false
+ expect(err).to match(/The following gems are missing/)
+ expect(err).to include("* rack (1.0").once
+ end
+ end
+
+ describe "when locked under multiple platforms" do
+ before :each do
+ build_repo4 do
+ build_gem "rack"
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "rack"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ rack (1.0)
+
+ PLATFORMS
+ ruby
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "shows what is missing with the current Gemfile without duplications" do
+ bundle :check, :raise_on_error => false
+ expect(err).to match(/The following gems are missing/)
+ expect(err).to include("* rack (1.0").once
+ end
+ end
+
+ describe "when using only scoped rubygems sources" do
+ before do
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo2)}"
+ source "#{file_uri_for(gem_repo1)}" do
+ gem "rack"
+ end
+ G
+ end
+
+ it "returns success when the Gemfile is satisfied" do
+ system_gems "rack-1.0.0", :path => default_bundle_path
+ bundle :check
+ expect(out).to include("The Gemfile's dependencies are satisfied")
+ end
+ end
+
+ describe "when using only scoped rubygems sources with indirect dependencies" do
+ before do
+ build_repo4 do
+ build_gem "depends_on_rack" do |s|
+ s.add_dependency "rack"
+ end
+
+ build_gem "rack"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo4)}" do
+ gem "depends_on_rack"
+ end
+ G
+ end
+
+ it "returns success when the Gemfile is satisfied and generates a correct lockfile" do
+ system_gems "depends_on_rack-1.0", "rack-1.0", :gem_repo => gem_repo4, :path => default_bundle_path
+ bundle :check
+ expect(out).to include("The Gemfile's dependencies are satisfied")
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ depends_on_rack (1.0)
+ rack
+ rack (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ depends_on_rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
describe "BUNDLED WITH" do
def lock_with(bundler_version = nil)
- lock = <<-L
+ lock = <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -318,13 +447,15 @@ RSpec.describe "bundle check" do
L
if bundler_version
- lock += "\n BUNDLED WITH\n #{bundler_version}\n"
+ lock += "\nBUNDLED WITH\n #{bundler_version}\n"
end
lock
end
before do
+ bundle "config set --local path vendor/bundle"
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -335,24 +466,25 @@ RSpec.describe "bundle check" do
it "does not change the lock" do
lockfile lock_with(nil)
bundle :check
- lockfile_should_be lock_with(nil)
+ expect(lockfile).to eq lock_with(nil)
end
end
context "is newer" do
it "does not change the lock but warns" do
lockfile lock_with(Bundler::VERSION.succ)
- bundle! :check
+ bundle :check
expect(err).to include("the running version of Bundler (#{Bundler::VERSION}) is older than the version that created the lockfile (#{Bundler::VERSION.succ})")
- lockfile_should_be lock_with(Bundler::VERSION.succ)
+ expect(lockfile).to eq lock_with(Bundler::VERSION.succ)
end
end
context "is older" do
it "does not change the lock" do
- lockfile lock_with("1.10.1")
+ system_gems "bundler-1.18.0"
+ lockfile lock_with("1.18.0")
bundle :check
- lockfile_should_be lock_with("1.10.1")
+ expect(lockfile).to eq lock_with("1.18.0")
end
end
end
diff --git a/spec/bundler/commands/clean_spec.rb b/spec/bundler/commands/clean_spec.rb
index 5cc97de912..9cce998416 100644
--- a/spec/bundler/commands/clean_spec.rb
+++ b/spec/bundler/commands/clean_spec.rb
@@ -27,16 +27,16 @@ RSpec.describe "bundle clean" do
bundle "config set path vendor/bundle"
bundle "config set clean false"
- bundle! "install"
+ bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
G
- bundle! "install"
+ bundle "install"
- bundle! :clean
+ bundle :clean
expect(out).to include("Removing foo (1.0)")
@@ -86,7 +86,7 @@ RSpec.describe "bundle clean" do
bundle "config set path vendor/bundle"
bundle "config set clean false"
- bundle! "install"
+ bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -94,9 +94,9 @@ RSpec.describe "bundle clean" do
gem "rack", "0.9.1"
gem "foo"
G
- bundle! "update rack"
+ bundle "update rack"
- bundle! :clean
+ bundle :clean
expect(out).to include("Removing rack (1.0.0)")
@@ -234,13 +234,13 @@ RSpec.describe "bundle clean" do
G
bundle "config set path vendor/bundle"
- bundle! "install"
+ bundle "install"
- update_git "foo", :path => lib_path("foo-bar")
+ update_git "foo-bar", :path => lib_path("foo-bar")
revision2 = revision_for(lib_path("foo-bar"))
- bundle! "update", :all => true
- bundle! :clean
+ bundle "update", :all => true
+ bundle :clean
expect(out).to include("Removing foo-bar (#{revision[0..11]})")
@@ -261,6 +261,7 @@ RSpec.describe "bundle clean" do
revision = revision_for(lib_path("rails"))
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "activesupport", :git => "#{lib_path("rails")}", :ref => '#{revision}'
G
@@ -315,20 +316,19 @@ RSpec.describe "bundle clean" do
bundle "install"
bundle :clean
- expect(exitstatus).to eq(0) if exitstatus
end
it "displays an error when used without --path" do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
G
- bundle :clean
+ bundle :clean, :raise_on_error => false
- expect(exitstatus).to eq(15) if exitstatus
+ expect(exitstatus).to eq(15)
expect(err).to include("--force")
end
@@ -364,22 +364,22 @@ RSpec.describe "bundle clean" do
end
it "does not call clean automatically when using system gems" do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "thin"
gem "rack"
G
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- gem_command! :list
+ gem_command :list
expect(out).to include("rack (1.0.0)").and include("thin (1.0)")
end
@@ -421,7 +421,7 @@ RSpec.describe "bundle clean" do
build_gem "foo", "1.0.1"
end
- bundle! "update", :all => true
+ bundle "update", :all => true
should_have_gems "foo-1.0.1"
should_not_have_gems "foo-1.0"
@@ -430,7 +430,7 @@ RSpec.describe "bundle clean" do
it "automatically cleans when path has not been set", :bundler => "3" do
build_repo2
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "foo"
@@ -440,7 +440,7 @@ RSpec.describe "bundle clean" do
build_gem "foo", "1.0.1"
end
- bundle! "update", :all => true
+ bundle "update", :all => true
files = Pathname.glob(bundled_app(".bundle", Bundler.ruby_scope, "*", "*"))
files.map! {|f| f.to_s.sub(bundled_app(".bundle", Bundler.ruby_scope).to_s, "") }
@@ -480,18 +480,18 @@ RSpec.describe "bundle clean" do
gem "foo"
G
bundle "config set path vendor/bundle"
- bundle! "install"
+ bundle "install"
update_repo2 do
build_gem "foo", "1.0.1"
end
- bundle! :update, :all => true
+ bundle :update, :all => true
should_have_gems "foo-1.0", "foo-1.0.1"
end
it "does not clean on bundle update when using --system" do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
build_repo2
@@ -500,19 +500,19 @@ RSpec.describe "bundle clean" do
gem "foo"
G
- bundle! "install"
+ bundle "install"
update_repo2 do
build_gem "foo", "1.0.1"
end
- bundle! :update, :all => true
+ bundle :update, :all => true
- gem_command! :list
+ gem_command :list
expect(out).to include("foo (1.0.1, 1.0)")
end
it "cleans system gems when --force is used" do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -531,12 +531,12 @@ RSpec.describe "bundle clean" do
bundle "clean --force"
expect(out).to include("Removing foo (1.0)")
- gem_command! :list
+ gem_command :list
expect(out).not_to include("foo (1.0)")
expect(out).to include("rack (1.0.0)")
end
- describe "when missing permissions" do
+ describe "when missing permissions", :permissions do
before { ENV["BUNDLE_PATH__SYSTEM"] = "true" }
let(:system_cache_path) { system_gem_path("cache") }
after do
@@ -560,12 +560,12 @@ RSpec.describe "bundle clean" do
FileUtils.chmod(0o500, system_cache_path)
- bundle :clean, :force => true
+ bundle :clean, :force => true, :raise_on_error => false
expect(err).to include(system_gem_path.to_s)
expect(err).to include("grant write permissions")
- gem_command! :list
+ gem_command :list
expect(out).to include("foo (1.0)")
expect(out).to include("rack (1.0.0)")
end
@@ -585,11 +585,11 @@ RSpec.describe "bundle clean" do
bundle "install"
# mimic 7 length git revisions in Gemfile.lock
- gemfile_lock = File.read(bundled_app("Gemfile.lock")).split("\n")
+ gemfile_lock = File.read(bundled_app_lock).split("\n")
gemfile_lock.each_with_index do |line, index|
gemfile_lock[index] = line[0..(11 + 7)] if line.include?(" revision:")
end
- lockfile(bundled_app("Gemfile.lock"), gemfile_lock.join("\n"))
+ lockfile(bundled_app_lock, gemfile_lock.join("\n"))
bundle "config set path vendor/bundle"
bundle "install"
@@ -602,10 +602,9 @@ RSpec.describe "bundle clean" do
end
it "when using --force on system gems, it doesn't remove binaries" do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
- build_repo2
- update_repo2 do
+ build_repo2 do
build_gem "bindir" do |s|
s.bindir = "exe"
s.executables = "foo"
@@ -623,10 +622,33 @@ RSpec.describe "bundle clean" do
sys_exec "foo"
- expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("1.0")
end
+ it "when using --force, it doesn't remove default gem binaries" do
+ skip "does not work on old rubies because the realworld gems that need to be installed don't support them" if RUBY_VERSION < "2.7.0"
+
+ skip "does not work on rubygems versions where `--install_dir` doesn't respect --default" unless Gem::Installer.for_spec(loaded_gemspec, :install_dir => "/foo").default_spec_file == "/foo/specifications/default/bundler-#{Bundler::VERSION}.gemspec" # Since rubygems 3.2.0.rc.2
+
+ default_irb_version = ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", :raise_on_error => false
+ skip "irb isn't a default gem" if default_irb_version.empty?
+
+ # simulate executable for default gem
+ build_gem "irb", default_irb_version, :to_system => true, :default => true do |s|
+ s.executables = "irb"
+ end
+
+ realworld_system_gems "fiddle --version 1.0.6", "tsort --version 0.1.0", "pathname --version 0.1.0", "set --version 1.0.1"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ G
+
+ bundle "clean --force", :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+
+ expect(out).not_to include("Removing irb")
+ end
+
it "doesn't blow up on path gems without a .gemspec" do
relative_path = "vendor/private_gems/bar-1.0"
absolute_path = bundled_app(relative_path)
@@ -644,7 +666,7 @@ RSpec.describe "bundle clean" do
bundle "config set path vendor/bundle"
bundle "install"
- bundle! :clean
+ bundle :clean
end
it "doesn't remove gems in dry-run mode with path set" do
@@ -749,7 +771,7 @@ RSpec.describe "bundle clean" do
bundle "config set path vendor/bundle"
bundle "config set clean false"
- bundle! "install"
+ bundle "install"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -758,8 +780,8 @@ RSpec.describe "bundle clean" do
gem "weakling"
G
- bundle! "config set auto_install 1"
- bundle! :clean
+ bundle "config set auto_install 1"
+ bundle :clean
expect(out).to include("Installing weakling 0.0.3")
should_have_gems "thin-1.0", "rack-1.0.0", "weakling-0.0.3"
should_not_have_gems "foo-1.0"
@@ -777,11 +799,11 @@ RSpec.describe "bundle clean" do
G
bundle "config set path vendor/bundle"
- bundle! "install"
+ bundle "install"
expect(vendored_gems("bundler/gems/extensions")).to exist
expect(vendored_gems("bundler/gems/very_simple_git_binary-1.0-#{revision[0..11]}")).to exist
- bundle! :clean
+ bundle :clean
expect(out).to be_empty
expect(vendored_gems("bundler/gems/extensions")).to exist
@@ -798,7 +820,7 @@ RSpec.describe "bundle clean" do
G
bundle "config set path vendor/bundle"
- bundle! "install"
+ bundle "install"
very_simple_binary_extensions_dir =
Pathname.glob("#{vendored_gems}/extensions/*/*/very_simple_binary-1.0").first
@@ -816,8 +838,8 @@ RSpec.describe "bundle clean" do
gem "simple_binary"
G
- bundle! "install"
- bundle! :clean
+ bundle "install"
+ bundle :clean
expect(out).to eq("Removing very_simple_binary (1.0)")
expect(very_simple_binary_extensions_dir).not_to exist
@@ -838,7 +860,7 @@ RSpec.describe "bundle clean" do
G
bundle "config set path vendor/bundle"
- bundle! "install"
+ bundle "install"
very_simple_binary_extensions_dir =
Pathname.glob("#{vendored_gems}/bundler/gems/extensions/*/*/very_simple_git_binary-1.0-#{short_revision}").first
@@ -846,25 +868,27 @@ RSpec.describe "bundle clean" do
expect(very_simple_binary_extensions_dir).to exist
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
G
- bundle! "install"
- bundle! :clean
+ bundle "install"
+ bundle :clean
expect(out).to include("Removing thin (1.0)")
expect(very_simple_binary_extensions_dir).to exist
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
G
- bundle! "install"
- bundle! :clean
+ bundle "install"
+ bundle :clean
expect(out).to eq("Removing very_simple_git_binary-1.0 (#{short_revision})")
expect(very_simple_binary_extensions_dir).not_to exist
end
- it "keeps git extension directories when excluded by group", :ruby_repo do
+ it "keeps git extension directories when excluded by group" do
build_git "very_simple_git_binary", &:add_c_extension
revision = revision_for(lib_path("very_simple_git_binary-1.0"))
@@ -881,8 +905,8 @@ RSpec.describe "bundle clean" do
bundle :lock
bundle "config set without development"
bundle "config set path vendor/bundle"
- bundle! "install"
- bundle! :clean
+ bundle "install"
+ bundle :clean
very_simple_binary_extensions_dir =
Pathname.glob("#{vendored_gems}/bundler/gems/extensions/*/*/very_simple_git_binary-1.0-#{short_revision}").first
diff --git a/spec/bundler/commands/config_spec.rb b/spec/bundler/commands/config_spec.rb
index ef580463e5..2d0a7dc989 100644
--- a/spec/bundler/commands/config_spec.rb
+++ b/spec/bundler/commands/config_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe ".bundle/config" do
end
end
- describe "location" do
+ describe "location with a gemfile" do
before :each do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -45,7 +45,8 @@ RSpec.describe ".bundle/config" do
it "can be moved with an environment variable" do
ENV["BUNDLE_APP_CONFIG"] = tmp("foo/bar").to_s
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle "install"
expect(bundled_app(".bundle")).not_to exist
expect(tmp("foo/bar/config")).to exist
@@ -54,14 +55,48 @@ RSpec.describe ".bundle/config" do
it "can provide a relative path with the environment variable" do
FileUtils.mkdir_p bundled_app("omg")
- Dir.chdir bundled_app("omg")
ENV["BUNDLE_APP_CONFIG"] = "../foo"
- bundle "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle "install", :dir => bundled_app("omg")
expect(bundled_app(".bundle")).not_to exist
expect(bundled_app("../foo/config")).to exist
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "rack 1.0.0", :dir => bundled_app("omg")
+ end
+ end
+
+ describe "location without a gemfile" do
+ it "works with an absolute path" do
+ ENV["BUNDLE_APP_CONFIG"] = tmp("foo/bar").to_s
+ bundle "config set --local path vendor/bundle"
+
+ expect(bundled_app(".bundle")).not_to exist
+ expect(tmp("foo/bar/config")).to exist
+ end
+ end
+
+ describe "config location" do
+ let(:bundle_user_config) { File.join(Dir.home, ".config/bundler") }
+
+ before do
+ Dir.mkdir File.dirname(bundle_user_config)
+ end
+
+ it "can be configured through BUNDLE_USER_CONFIG" do
+ bundle "config set path vendor", :env => { "BUNDLE_USER_CONFIG" => bundle_user_config }
+ bundle "config get path", :env => { "BUNDLE_USER_CONFIG" => bundle_user_config }
+ expect(out).to include("Set for the current user (#{bundle_user_config}): \"vendor\"")
+ end
+
+ context "when not explicitly configured, but BUNDLE_USER_HOME set" do
+ let(:bundle_user_home) { bundled_app(".bundle").to_s }
+
+ it "uses the right location" do
+ bundle "config set path vendor", :env => { "BUNDLE_USER_HOME" => bundle_user_home }
+ bundle "config get path", :env => { "BUNDLE_USER_HOME" => bundle_user_home }
+ expect(out).to include("Set for the current user (#{bundle_user_home}/config): \"vendor\"")
+ end
end
end
@@ -80,8 +115,8 @@ RSpec.describe ".bundle/config" do
end
it "can also be set explicitly" do
- bundle! "config set --global foo global"
- run! "puts Bundler.settings[:foo]"
+ bundle "config set --global foo global"
+ run "puts Bundler.settings[:foo]"
expect(out).to eq("global")
end
@@ -138,7 +173,7 @@ RSpec.describe ".bundle/config" do
it "expands the path at time of setting" do
bundle "config set --global local.foo .."
run "puts Bundler.settings['local.foo']"
- expect(out).to eq(File.expand_path(Dir.pwd + "/.."))
+ expect(out).to eq(File.expand_path(bundled_app.to_s + "/.."))
end
it "saves with parseable option" do
@@ -205,7 +240,7 @@ RSpec.describe ".bundle/config" do
it "expands the path at time of setting" do
bundle "config set --local local.foo .."
run "puts Bundler.settings['local.foo']"
- expect(out).to eq(File.expand_path(Dir.pwd + "/.."))
+ expect(out).to eq(File.expand_path(bundled_app.to_s + "/.."))
end
it "can be deleted with parseable option" do
@@ -310,7 +345,7 @@ E
end
describe "quoting" do
- before(:each) { gemfile "# no gems" }
+ before(:each) { gemfile "source \"#{file_uri_for(gem_repo1)}\"" }
let(:long_string) do
"--with-xml2-include=/usr/pkg/include/libxml2 --with-xml2-lib=/usr/pkg/lib " \
"--with-xslt-dir=/usr/pkg"
@@ -390,85 +425,101 @@ E
describe "subcommands" do
it "list" do
- bundle! "config list"
+ bundle "config list"
expect(out).to eq "Settings are listed in order of priority. The top value will be used.\nspec_run\nSet via BUNDLE_SPEC_RUN: \"true\""
- bundle! "config list", :parseable => true
+ bundle "config list", :parseable => true
expect(out).to eq "spec_run=true"
end
+ it "list with credentials" do
+ bundle "config list", :env => { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
+ expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"user:[REDACTED]\"\n\nspec_run\nSet via BUNDLE_SPEC_RUN: \"true\""
+
+ bundle "config list", :parseable => true, :env => { "BUNDLE_GEMS__MYSERVER__COM" => "user:password" }
+ expect(out).to eq "gems.myserver.com=user:password\nspec_run=true"
+ end
+
+ it "list with API token credentials" do
+ bundle "config list", :env => { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
+ expect(out).to eq "Settings are listed in order of priority. The top value will be used.\ngems.myserver.com\nSet via BUNDLE_GEMS__MYSERVER__COM: \"[REDACTED]:x-oauth-basic\"\n\nspec_run\nSet via BUNDLE_SPEC_RUN: \"true\""
+
+ bundle "config list", :parseable => true, :env => { "BUNDLE_GEMS__MYSERVER__COM" => "api_token:x-oauth-basic" }
+ expect(out).to eq "gems.myserver.com=api_token:x-oauth-basic\nspec_run=true"
+ end
+
it "get" do
ENV["BUNDLE_BAR"] = "bar_val"
- bundle! "config get foo"
+ bundle "config get foo"
expect(out).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
ENV["BUNDLE_FOO"] = "foo_val"
- bundle! "config get foo --parseable"
+ bundle "config get foo --parseable"
expect(out).to eq "foo=foo_val"
- bundle! "config get foo"
+ bundle "config get foo"
expect(out).to eq "Settings for `foo` in order of priority. The top value will be used\nSet via BUNDLE_FOO: \"foo_val\""
end
it "set" do
- bundle! "config set foo 1"
+ bundle "config set foo 1"
expect(out).to eq ""
- bundle! "config set --local foo 2"
+ bundle "config set --local foo 2"
expect(out).to eq ""
- bundle! "config set --global foo 3"
+ bundle "config set --global foo 3"
expect(out).to eq "Your application has set foo to \"2\". This will override the global value you are currently setting"
- bundle! "config set --parseable --local foo 4"
+ bundle "config set --parseable --local foo 4"
expect(out).to eq "foo=4"
- bundle! "config set --local foo 4.1"
+ bundle "config set --local foo 4.1"
expect(out).to eq "You are replacing the current local value of foo, which is currently \"4\""
- bundle "config set --global --local foo 5"
+ bundle "config set --global --local foo 5", :raise_on_error => false
expect(last_command).to be_failure
expect(err).to eq "The options global and local were specified. Please only use one of the switches at a time."
end
it "unset" do
- bundle! "config unset foo"
+ bundle "config unset foo"
expect(out).to eq ""
- bundle! "config set foo 1"
- bundle! "config unset foo --parseable"
+ bundle "config set foo 1"
+ bundle "config unset foo --parseable"
expect(out).to eq ""
- bundle! "config set --local foo 1"
- bundle! "config set --global foo 2"
+ bundle "config set --local foo 1"
+ bundle "config set --global foo 2"
- bundle! "config unset foo"
+ bundle "config unset foo"
expect(out).to eq ""
- expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
+ expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
- bundle! "config set --local foo 1"
- bundle! "config set --global foo 2"
+ bundle "config set --local foo 1"
+ bundle "config set --global foo 2"
- bundle! "config unset foo --local"
+ bundle "config unset foo --local"
expect(out).to eq ""
- expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for the current user (#{home(".bundle/config")}): \"2\""
- bundle! "config unset foo --global"
+ expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for the current user (#{home(".bundle/config")}): \"2\""
+ bundle "config unset foo --global"
expect(out).to eq ""
- expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
+ expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
- bundle! "config set --local foo 1"
- bundle! "config set --global foo 2"
+ bundle "config set --local foo 1"
+ bundle "config set --global foo 2"
- bundle! "config unset foo --global"
+ bundle "config unset foo --global"
expect(out).to eq ""
- expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for your local app (#{bundled_app(".bundle/config")}): \"1\""
- bundle! "config unset foo --local"
+ expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nSet for your local app (#{bundled_app(".bundle/config")}): \"1\""
+ bundle "config unset foo --local"
expect(out).to eq ""
- expect(bundle!("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
+ expect(bundle("config get foo")).to eq "Settings for `foo` in order of priority. The top value will be used\nYou have not configured a value for `foo`"
- bundle "config unset foo --local --global"
+ bundle "config unset foo --local --global", :raise_on_error => false
expect(last_command).to be_failure
expect(err).to eq "The options global and local were specified. Please only use one of the switches at a time."
end
@@ -484,7 +535,7 @@ RSpec.describe "setting gemfile via config" do
G
bundle "config set --local gemfile #{bundled_app("NotGemfile")}"
- expect(File.exist?(".bundle/config")).to eq(true)
+ expect(File.exist?(bundled_app(".bundle/config"))).to eq(true)
bundle "config list"
expect(out).to include("NotGemfile")
diff --git a/spec/bundler/commands/console_spec.rb b/spec/bundler/commands/console_spec.rb
index a0b71ff016..aa76096e3d 100644
--- a/spec/bundler/commands/console_spec.rb
+++ b/spec/bundler/commands/console_spec.rb
@@ -1,9 +1,44 @@
# frozen_string_literal: true
-RSpec.describe "bundle console", :bundler => "< 3" do
+RSpec.describe "bundle console", :bundler => "< 3", :readline => true do
before :each do
+ build_repo2 do
+ # A minimal fake pry console
+ build_gem "pry" do |s|
+ s.write "lib/pry.rb", <<-RUBY
+ class Pry
+ class << self
+ def toplevel_binding
+ unless defined?(@toplevel_binding) && @toplevel_binding
+ TOPLEVEL_BINDING.eval %{
+ def self.__pry__; binding; end
+ Pry.instance_variable_set(:@toplevel_binding, __pry__)
+ class << self; undef __pry__; end
+ }
+ end
+ @toplevel_binding.eval('private')
+ @toplevel_binding
+ end
+
+ def __pry__
+ while line = gets
+ begin
+ puts eval(line, toplevel_binding).inspect.sub(/^"(.*)"$/, '=> \\1')
+ rescue Exception => e
+ puts "\#{e.class}: \#{e.message}"
+ puts e.backtrace.first
+ end
+ end
+ end
+ alias start __pry__
+ end
+ end
+ RUBY
+ end
+ end
+
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rack"
gem "activesupport", :group => :test
gem "rack_middleware", :group => :development
@@ -20,15 +55,15 @@ RSpec.describe "bundle console", :bundler => "< 3" do
it "uses IRB as default console" do
bundle "console" do |input, _, _|
- input.puts("__method__")
+ input.puts("__FILE__")
input.puts("exit")
end
- expect(out).to include(":irb_binding")
+ expect(out).to include("(irb)")
end
it "starts another REPL if configured as such" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "pry"
G
bundle "config set console pry"
@@ -45,10 +80,10 @@ RSpec.describe "bundle console", :bundler => "< 3" do
# make sure pry isn't there
bundle "console" do |input, _, _|
- input.puts("__method__")
+ input.puts("__FILE__")
input.puts("exit")
end
- expect(out).to include(":irb_binding")
+ expect(out).to include("(irb)")
end
it "doesn't load any other groups" do
@@ -87,7 +122,7 @@ RSpec.describe "bundle console", :bundler => "< 3" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rack"
gem "activesupport", :group => :test
gem "rack_middleware", :group => :development
diff --git a/spec/bundler/commands/doctor_spec.rb b/spec/bundler/commands/doctor_spec.rb
index d829f00092..860b638f06 100644
--- a/spec/bundler/commands/doctor_spec.rb
+++ b/spec/bundler/commands/doctor_spec.rb
@@ -7,7 +7,7 @@ require "bundler/cli/doctor"
RSpec.describe "bundle doctor" do
before(:each) do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -24,15 +24,16 @@ RSpec.describe "bundle doctor" do
it "succeeds on a sane installation" do
bundle :doctor
-
- expect(exitstatus).to eq(0)
end
context "when all files in home are readable/writable" do
before(:each) do
stat = double("stat")
unwritable_file = double("file")
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [unwritable_file] }
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:exist?).with(unwritable_file).and_return(true)
allow(File).to receive(:stat).with(unwritable_file) { stat }
allow(stat).to receive(:uid) { Process.uid }
allow(File).to receive(:writable?).with(unwritable_file) { true }
@@ -48,7 +49,6 @@ RSpec.describe "bundle doctor" do
doctor = Bundler::CLI::Doctor.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"]
- allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with("/usr/lib/libSystem.dylib").and_return(true)
expect { doctor.run }.not_to(raise_error, @stdout.string)
expect(@stdout.string).to be_empty
@@ -58,7 +58,6 @@ RSpec.describe "bundle doctor" do
doctor = Bundler::CLI::Doctor.new({})
expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"]
- allow(File).to receive(:exist?).and_call_original
allow(File).to receive(:exist?).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(false)
expect { doctor.run }.to raise_error(Bundler::ProductionError, strip_whitespace(<<-E).strip), @stdout.string
The following gems are missing OS dependencies:
@@ -68,11 +67,32 @@ RSpec.describe "bundle doctor" do
end
end
+ context "when home contains broken symlinks" do
+ before(:each) do
+ @broken_symlink = double("file")
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@broken_symlink] }
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:exist?).with(@broken_symlink) { false }
+ end
+
+ it "exits with an error if home contains files that are not readable/writable" do
+ expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
+ expect(@stdout.string).to include(
+ "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{@broken_symlink}"
+ )
+ expect(@stdout.string).not_to include("No issues")
+ end
+ end
+
context "when home contains files that are not readable/writable" do
before(:each) do
@stat = double("stat")
@unwritable_file = double("file")
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
allow(Find).to receive(:find).with(Bundler.bundle_path.to_s) { [@unwritable_file] }
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:exist?).with(@unwritable_file) { true }
allow(File).to receive(:stat).with(@unwritable_file) { @stat }
end
@@ -87,7 +107,7 @@ RSpec.describe "bundle doctor" do
expect(@stdout.string).not_to include("No issues")
end
- context "when home contains files that are not owned by the current process" do
+ context "when home contains files that are not owned by the current process", :permissions do
before(:each) do
allow(@stat).to receive(:uid) { 0o0000 }
end
@@ -113,4 +133,14 @@ RSpec.describe "bundle doctor" do
end
end
end
+
+ context "when home contains filesname with special characters" do
+ it "escape filename before command execute" do
+ doctor = Bundler::CLI::Doctor.new({})
+ expect(doctor).to receive(:`).with("/usr/bin/otool -L \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string")
+ doctor.dylibs_darwin('$(date) "\'\.bundle')
+ expect(doctor).to receive(:`).with("/usr/bin/ldd \\$\\(date\\)\\ \\\"\\'\\\\.bundle").and_return("dummy string")
+ doctor.dylibs_ldd('$(date) "\'\.bundle')
+ end
+ end
end
diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb
index 42f760ab12..e67e5b96ef 100644
--- a/spec/bundler/commands/exec_spec.rb
+++ b/spec/bundler/commands/exec_spec.rb
@@ -3,11 +3,12 @@
RSpec.describe "bundle exec" do
let(:system_gems_to_install) { %w[rack-1.0.0 rack-0.9.1] }
before :each do
- system_gems(system_gems_to_install, :path => :bundle_path)
+ system_gems(system_gems_to_install, :path => default_bundle_path)
end
it "works with --gemfile flag" do
create_file "CustomGemfile", <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack", "1.0.0"
G
@@ -17,6 +18,7 @@ RSpec.describe "bundle exec" do
it "activates the correct gem" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
G
@@ -24,8 +26,20 @@ RSpec.describe "bundle exec" do
expect(out).to eq("0.9.1")
end
+ it "works and prints no warnings when HOME is not writable" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack", "0.9.1"
+ G
+
+ bundle "exec rackup", :env => { "HOME" => "/" }
+ expect(out).to eq("0.9.1")
+ expect(err).to be_empty
+ end
+
it "works when the bins are in ~/.bundle" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -35,6 +49,7 @@ RSpec.describe "bundle exec" do
it "works when running from a random directory" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -44,53 +59,85 @@ RSpec.describe "bundle exec" do
end
it "works when exec'ing something else" do
- install_gemfile 'gem "rack"'
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
bundle "exec echo exec"
expect(out).to eq("exec")
end
it "works when exec'ing to ruby" do
- install_gemfile 'gem "rack"'
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
bundle "exec ruby -e 'puts %{hi}'"
expect(out).to eq("hi")
end
it "works when exec'ing to rubygems" do
- install_gemfile 'gem "rack"'
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
bundle "exec #{gem_cmd} --version"
expect(out).to eq(Gem::VERSION)
end
it "works when exec'ing to rubygems through sh -c" do
- install_gemfile 'gem "rack"'
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
bundle "exec sh -c '#{gem_cmd} --version'"
expect(out).to eq(Gem::VERSION)
end
+ it "works when exec'ing back to bundler with a lockfile that doesn't include the current platform" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack", "0.9.1"
+ G
+
+ # simulate lockfile generated with old version not including specific platform
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ rack (0.9.1)
+
+ PLATFORMS
+ RUBY
+
+ DEPENDENCIES
+ rack (= 0.9.1)
+
+ BUNDLED WITH
+ 2.1.4
+ L
+
+ bundle "exec bundle cache", :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+
+ expect(out).to include("Updating files in vendor/cache")
+ end
+
it "respects custom process title when loading through ruby" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
script_that_changes_its_own_title_and_checks_if_picked_up_by_ps_unix_utility = <<~'RUBY'
- Process.setproctitle("1-2-3-4-5-6-7-8-9-10-11-12-13-14-15")
+ Process.setproctitle("1-2-3-4-5-6-7")
puts `ps -ocommand= -p#{$$}`
RUBY
- create_file "Gemfile"
+ create_file "Gemfile", "source \"#{file_uri_for(gem_repo1)}\""
create_file "a.rb", script_that_changes_its_own_title_and_checks_if_picked_up_by_ps_unix_utility
bundle "exec ruby a.rb"
- expect(out).to eq("1-2-3-4-5-6-7-8-9-10-11-12-13-14-15")
+ expect(out).to eq("1-2-3-4-5-6-7")
end
it "accepts --verbose" do
- install_gemfile 'gem "rack"'
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
bundle "exec --verbose echo foobar"
expect(out).to eq("foobar")
end
it "passes --verbose to command if it is given after the command" do
- install_gemfile 'gem "rack"'
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
bundle "exec echo --verbose"
expect(out).to eq("--verbose")
end
it "handles --keep-file-descriptors" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
require "tempfile"
command = Tempfile.new("io-test")
@@ -107,7 +154,7 @@ RSpec.describe "bundle exec" do
end
G
- install_gemfile ""
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
sys_exec "#{Gem.ruby} #{command.path}"
expect(out).to be_empty
@@ -115,19 +162,21 @@ RSpec.describe "bundle exec" do
end
it "accepts --keep-file-descriptors" do
- install_gemfile ""
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
bundle "exec --keep-file-descriptors echo foobar"
expect(err).to be_empty
end
it "can run a command named --verbose" do
- install_gemfile 'gem "rack"'
- File.open("--verbose", "w") do |f|
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
+ File.open(bundled_app("--verbose"), "w") do |f|
f.puts "#!/bin/sh"
f.puts "echo foobar"
end
- File.chmod(0o744, "--verbose")
+ File.chmod(0o744, bundled_app("--verbose"))
with_path_as(".") do
bundle "exec -- --verbose"
end
@@ -146,40 +195,35 @@ RSpec.describe "bundle exec" do
gem "rack", "0.9.1"
G
- Dir.chdir bundled_app2 do
- install_gemfile bundled_app2("Gemfile"), <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack_two", "1.0.0"
- G
- end
+ install_gemfile bundled_app2("Gemfile"), <<-G, :dir => bundled_app2
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack_two", "1.0.0"
+ G
- bundle! "exec rackup"
+ bundle "exec rackup"
expect(out).to eq("0.9.1")
- Dir.chdir bundled_app2 do
- bundle! "exec rackup"
- expect(out).to eq("1.0.0")
- end
+ bundle "exec rackup", :dir => bundled_app2
+ expect(out).to eq("1.0.0")
end
context "with default gems" do
let(:system_gems_to_install) { [] }
- let(:default_irb_version) { ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION" }
+ let(:default_irb_version) { ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", :raise_on_error => false }
context "when not specified in Gemfile" do
before do
skip "irb isn't a default gem" if default_irb_version.empty?
- install_gemfile ""
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
end
it "uses version provided by ruby" do
- bundle! "exec irb --version"
+ bundle "exec irb --version"
expect(out).to include(default_irb_version)
- expect(err).to be_empty
end
end
@@ -202,7 +246,7 @@ RSpec.describe "bundle exec" do
end
it "uses version specified" do
- bundle! "exec irb --version"
+ bundle "exec irb --version"
expect(out).to eq(specified_irb_version)
expect(err).to be_empty
@@ -230,7 +274,7 @@ RSpec.describe "bundle exec" do
gem "gem_depending_on_old_irb"
G
- bundle! "exec irb --version"
+ bundle "exec irb --version"
end
it "uses resolved version" do
@@ -254,14 +298,12 @@ RSpec.describe "bundle exec" do
gem "rack", "0.9.1"
G
- Dir.chdir bundled_app2 do
- install_gemfile bundled_app2("Gemfile"), <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack_two", "1.0.0"
- G
- end
+ install_gemfile bundled_app2("Gemfile"), <<-G, :dir => bundled_app2
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack_two", "1.0.0"
+ G
- bundle! "exec rackup"
+ bundle "exec rackup"
expect(last_command.stderr).to eq(
"Bundler is using a binstub that was created for a different gem (rack).\n" \
@@ -270,7 +312,8 @@ RSpec.describe "bundle exec" do
end
it "handles gems installed with --without" do
- install_gemfile <<-G, forgotten_command_line_options(:without => "middleware")
+ bundle "config set --local without middleware"
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack" # rack 0.9.1 and 1.0 exist
@@ -286,22 +329,29 @@ RSpec.describe "bundle exec" do
end
it "does not duplicate already exec'ed RUBYOPT" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- rubyopt = ENV["RUBYOPT"]
- rubyopt = "-r#{lib_dir}/bundler/setup #{rubyopt}"
+ bundler_setup_opt = "-r#{lib_dir}/bundler/setup"
+
+ rubyopt = opt_add(bundler_setup_opt, ENV["RUBYOPT"])
bundle "exec 'echo $RUBYOPT'"
- expect(out).to have_rubyopts(rubyopt)
+ expect(out.split(" ").count(bundler_setup_opt)).to eq(1)
bundle "exec 'echo $RUBYOPT'", :env => { "RUBYOPT" => rubyopt }
- expect(out).to have_rubyopts(rubyopt)
+ expect(out.split(" ").count(bundler_setup_opt)).to eq(1)
end
it "does not duplicate already exec'ed RUBYLIB" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -318,45 +368,48 @@ RSpec.describe "bundle exec" do
it "errors nicely when the argument doesn't exist" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- bundle "exec foobarbaz"
- expect(exitstatus).to eq(127) if exitstatus
+ bundle "exec foobarbaz", :raise_on_error => false
+ expect(exitstatus).to eq(127)
expect(err).to include("bundler: command not found: foobarbaz")
expect(err).to include("Install missing gem executables with `bundle install`")
end
it "errors nicely when the argument is not executable" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
bundle "exec touch foo"
- bundle "exec ./foo"
- expect(exitstatus).to eq(126) if exitstatus
+ bundle "exec ./foo", :raise_on_error => false
+ expect(exitstatus).to eq(126)
expect(err).to include("bundler: not executable: ./foo")
end
it "errors nicely when no arguments are passed" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- bundle "exec"
- expect(exitstatus).to eq(128) if exitstatus
+ bundle "exec", :raise_on_error => false
+ expect(exitstatus).to eq(128)
expect(err).to include("bundler: exec needs a command to run")
end
it "raises a helpful error when exec'ing to something outside of the bundle" do
- bundle! "config set clean false" # want to keep the rackup binstub
- install_gemfile! <<-G
+ bundle "config set clean false" # want to keep the rackup binstub
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "with_license"
+ gem "foo"
G
[true, false].each do |l|
- bundle! "config set disable_exec_load #{l}"
- bundle "exec rackup"
+ bundle "config set disable_exec_load #{l}"
+ bundle "exec rackup", :raise_on_error => false
expect(err).to include "can't find executable rackup for gem rack. rack is not currently included in the bundle, perhaps you meant to add it to your Gemfile?"
end
end
@@ -368,7 +421,10 @@ 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"
G
@@ -415,44 +471,45 @@ RSpec.describe "bundle exec" do
with_fake_man do
bundle "#{exec} --help cat"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
it "shows bundle-exec's man page when --help is before exec" do
with_fake_man do
bundle "--help #{exec}"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
it "shows bundle-exec's man page when -h is before exec" do
with_fake_man do
bundle "-h #{exec}"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
it "shows bundle-exec's man page when --help is after exec" do
with_fake_man do
bundle "#{exec} --help"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
it "shows bundle-exec's man page when -h is after exec" do
with_fake_man do
bundle "#{exec} -h"
end
- expect(out).to include(%(["#{root}/man/bundle-exec.1"]))
+ expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
end
end
end
describe "with gem executables" do
- describe "run from a random directory", :ruby_repo do
+ describe "run from a random directory" do
before(:each) do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
end
@@ -476,6 +533,7 @@ RSpec.describe "bundle exec" do
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "fizz", :path => "#{File.expand_path(home("fizz"))}"
G
end
@@ -500,6 +558,7 @@ RSpec.describe "bundle exec" do
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "fizz_git", :git => "#{lib_path("fizz_git-1.0")}"
G
end
@@ -523,6 +582,7 @@ RSpec.describe "bundle exec" do
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "fizz_no_gemspec", "1.0", :git => "#{lib_path("fizz_no_gemspec-1.0")}"
G
end
@@ -552,6 +612,36 @@ RSpec.describe "bundle exec" do
expect(out).to include("Installing foo 1.0")
end
+ it "loads the correct optparse when `auto_install` is set, and optparse is a dependency" do
+ if Gem.ruby_version >= Gem::Version.new("3.0.0") && Gem.rubygems_version < Gem::Version.new("3.3.0.a")
+ skip "optparse is a default gem, and rubygems loads it during install"
+ end
+
+ build_repo4 do
+ build_gem "fastlane", "2.192.0" do |s|
+ s.executables = "fastlane"
+ s.add_dependency "optparse", "~> 999.999.999"
+ end
+
+ build_gem "optparse", "999.999.998"
+ build_gem "optparse", "999.999.999"
+ end
+
+ system_gems "optparse-999.999.998", :gem_repo => gem_repo4
+
+ bundle "config set auto_install 1"
+ bundle "config set --local path vendor/bundle"
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "fastlane"
+ G
+
+ bundle "exec fastlane"
+ expect(out).to include("Installing optparse 999.999.999")
+ expect(out).to include("2.192.0")
+ end
+
describe "with gems bundled via :path with invalid gemspecs" do
it "outputs the gemspec validation errors" do
build_lib "foo"
@@ -568,11 +658,12 @@ RSpec.describe "bundle exec" do
G
end
- install_gemfile <<-G
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
- bundle "exec irb"
+ bundle "exec irb", :raise_on_error => false
expect(err).to match("The gemspec at #{lib_path("foo-1.0").join("foo.gemspec")} is not valid")
expect(err).to match('"TODO" is not a summary')
@@ -581,7 +672,11 @@ RSpec.describe "bundle exec" do
describe "with gems bundled for deployment" do
it "works when calling bundler from another script" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
module Monkey
def bin_path(a,b,c)
raise Gem::GemNotFoundException.new('Fail')
@@ -589,8 +684,9 @@ RSpec.describe "bundle exec" do
end
Bundler.rubygems.extend(Monkey)
G
- bundle "install --deployment"
- bundle "exec ruby -e '`#{bindir.join("bundler")} -v`; puts $?.success?'"
+ bundle "config set path.system true"
+ bundle "install"
+ bundle "exec ruby -e '`bundle -v`; puts $?.success?'", :env => { "BUNDLER_VERSION" => Bundler::VERSION }
expect(out).to match("true")
end
end
@@ -610,10 +706,11 @@ RSpec.describe "bundle exec" do
RUBY
before do
- path.open("w") {|f| f << executable }
- path.chmod(0o755)
+ bundled_app(path).open("w") {|f| f << executable }
+ bundled_app(path).chmod(0o755)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
end
@@ -630,29 +727,42 @@ RSpec.describe "bundle exec" do
let(:expected) { [exec, args, rack, process].join("\n") }
let(:expected_err) { "" }
- subject { bundle "exec #{path} arg1 arg2" }
+ subject { bundle "exec #{path} arg1 arg2", :raise_on_error => false }
- shared_examples_for "it runs" do
- it "like a normally executed executable" do
- subject
- expect(exitstatus).to eq(exit_code) if exitstatus
- expect(err).to eq(expected_err)
- expect(out).to eq(expected)
- end
- end
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
- it_behaves_like "it runs"
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
context "the executable exits explicitly" do
let(:executable) { super() << "\nexit #{exit_code}\nputs 'POST_EXIT'\n" }
context "with exit 0" do
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "with exit 99" do
let(:exit_code) { 99 }
- it_behaves_like "it runs"
+
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
end
@@ -669,7 +779,15 @@ RSpec.describe "bundle exec" do
# this is specified by C99
128 + 15
end
- it_behaves_like "it runs"
+
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "the executable is empty" do
@@ -678,7 +796,15 @@ RSpec.describe "bundle exec" do
let(:exit_code) { 0 }
let(:expected_err) { "#{path} is empty" }
let(:expected) { "" }
- it_behaves_like "it runs"
+
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "the executable raises" do
@@ -686,28 +812,52 @@ RSpec.describe "bundle exec" do
let(:exit_code) { 1 }
let(:expected_err) do
"bundler: failed to load command: #{path} (#{path})" \
- "\nRuntimeError: ERROR\n #{path}:10:in `<top (required)>'"
+ "\n#{path}:10: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 start_with(expected_err)
+ expect(out).to eq(expected)
end
- it_behaves_like "it runs"
end
context "the executable raises an error without a backtrace" do
let(:executable) { super() << "\nclass Err < Exception\ndef backtrace; end;\nend\nraise Err" }
let(:exit_code) { 1 }
- let(:expected_err) { "bundler: failed to load command: #{path} (#{path})\nErr: Err" }
+ let(:expected_err) { "bundler: failed to load command: #{path} (#{path})\n#{system_gem_path("bin/bundle")}: Err (Err)" }
let(:expected) { super() }
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when the file uses the current ruby shebang" do
let(:shebang) { "#!#{Gem.ruby}" }
- it_behaves_like "it runs"
+
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when Bundler.setup fails", :bundler => "< 3" do
before do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack', '2'
G
ENV["BUNDLER_FORCE_TTY"] = "true"
@@ -716,16 +866,25 @@ RSpec.describe "bundle exec" do
let(:exit_code) { Bundler::GemNotFound.new.status_code }
let(:expected) { "" }
let(:expected_err) { <<-EOS.strip }
-\e[31mCould not find gem 'rack (= 2)' in any of the gem sources listed in your Gemfile.\e[0m
-\e[33mRun `bundle install` to install missing gems.\e[0m
+Could not find gem 'rack (= 2)' in locally installed gems.
+The source contains the following versions of 'rack': 0.9.1, 1.0.0
+Run `bundle install` to install missing gems.
EOS
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when Bundler.setup fails", :bundler => "3" do
before do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack', '2'
G
ENV["BUNDLER_FORCE_TTY"] = "true"
@@ -734,19 +893,33 @@ RSpec.describe "bundle exec" do
let(:exit_code) { Bundler::GemNotFound.new.status_code }
let(:expected) { "" }
let(:expected_err) { <<-EOS.strip }
-\e[31mCould not find gem 'rack (= 2)' in locally installed gems.
-The source contains 'rack' at: 1.0.0\e[0m
-\e[33mRun `bundle install` to install missing gems.\e[0m
+Could not find gem 'rack (= 2)' in locally installed gems.
+The source contains the following versions of 'rack': 1.0.0
+Run `bundle install` to install missing gems.
EOS
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when the executable exits non-zero via at_exit" do
let(:executable) { super() + "\n\nat_exit { $! ? raise($!) : exit(1) }" }
let(:exit_code) { 1 }
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when disable_exec_load is set" do
@@ -757,7 +930,14 @@ The source contains 'rack' at: 1.0.0\e[0m
bundle "config set disable_exec_load true"
end
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "regarding $0 and __FILE__" do
@@ -773,16 +953,30 @@ $0: #{path.to_s.inspect}
__FILE__: #{path.to_s.inspect}
EOS
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
context "when the path is relative" do
let(:path) { super().relative_path_from(bundled_app) }
- it_behaves_like "it runs"
+ it "runs" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
context "when the path is relative with a leading ./" do
- let(:path) { Pathname.new("./#{super().relative_path_from(Pathname.pwd)}") }
+ let(:path) { Pathname.new("./#{super().relative_path_from(bundled_app)}") }
pending "relative paths with ./ have absolute __FILE__"
end
@@ -813,7 +1007,9 @@ __FILE__: #{path.to_s.inspect}
RUBY
it "receives the signal" do
- bundle!("exec #{path}") do |_, o, thr|
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ bundle("exec #{path}") do |_, o, thr|
o.gets # Consumes 'Started' and ensures that thread has started
Process.kill("INT", thr.pid)
end
@@ -834,11 +1030,13 @@ __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?
+
test_signals.each do |n|
Signal.trap(n, "IGNORE")
end
- bundle!("exec #{path}")
+ bundle("exec #{path}")
expect(out).to eq(test_signals.count.to_s)
end
@@ -849,65 +1047,176 @@ __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?
+
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
bundle "config set path vendor/bundler"
- bundle! :install
+ bundle :install
end
- it "correctly shells out", :ruby_repo do
+ it "correctly shells out" do
file = bundled_app("file_that_bundle_execs.rb")
- create_file(file, <<-RB)
+ create_file(file, <<-RUBY)
#!#{Gem.ruby}
puts `bundle exec echo foo`
- RB
+ RUBY
file.chmod(0o777)
- bundle! "exec #{file}"
+ bundle "exec #{file}", :env => { "PATH" => path }
expect(out).to eq("foo")
end
end
+ context "when Kernel.require uses extra monkeypatches" do
+ before do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ end
+
+ it "does not undo the monkeypatches" do
+ karafka = bundled_app("bin/karafka")
+ create_file(karafka, <<~RUBY)
+ #!#{Gem.ruby}
+
+ module Kernel
+ module_function
+
+ alias_method :require_before_extra_monkeypatches, :require
+
+ def require(path)
+ puts "requiring \#{path} used the monkeypatch"
+
+ require_before_extra_monkeypatches(path)
+ end
+ end
+
+ Bundler.setup(:default)
+
+ require "foo"
+ RUBY
+ karafka.chmod(0o777)
+
+ foreman = bundled_app("bin/foreman")
+ create_file(foreman, <<~RUBY)
+ #!#{Gem.ruby}
+
+ puts `bundle exec bin/karafka`
+ RUBY
+ foreman.chmod(0o777)
+
+ bundle "exec #{foreman}"
+ expect(out).to eq("requiring foo used the monkeypatch")
+ end
+ end
+
+ context "when gemfile and path are configured", :ruby_repo do
+ before do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+
+ build_repo2 do
+ build_gem "rails", "6.1.0" do |s|
+ s.executables = "rails"
+ end
+ end
+
+ bundle "config set path vendor/bundle"
+ bundle "config set gemfile gemfiles/rack_6_1.gemfile"
+
+ create_file(bundled_app("gemfiles/rack_6_1.gemfile"), <<~RUBY)
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "rails", "6.1.0"
+ RUBY
+
+ # A Gemfile needs to be in the root to trick bundler's root resolution
+ create_file(bundled_app("Gemfile"), "source \"#{file_uri_for(gem_repo1)}\"")
+
+ bundle "install"
+ end
+
+ it "can still find gems after a nested subprocess" do
+ script = bundled_app("bin/myscript")
+
+ create_file(script, <<~RUBY)
+ #!#{Gem.ruby}
+
+ puts `bundle exec rails`
+ RUBY
+
+ script.chmod(0o777)
+
+ bundle "exec #{script}"
+
+ expect(err).to be_empty
+ expect(out).to eq("6.1.0")
+ end
+ end
+
context "with a system gem that shadows a default gem" do
let(:openssl_version) { "99.9.9" }
- let(:expected) { ruby "gem 'openssl', '< 999999'; require 'openssl'; puts OpenSSL::VERSION", :artifice => nil }
+ let(:expected) { ruby "gem 'openssl', '< 999999'; require 'openssl'; puts OpenSSL::VERSION", :artifice => nil, :raise_on_error => false }
it "only leaves the default gem in the stdlib available" do
+ skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
skip "openssl isn't a default gem" if expected.empty?
- install_gemfile! "" # must happen before installing the broken system gem
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" # must happen before installing the broken system gem
build_repo4 do
build_gem "openssl", openssl_version do |s|
- s.write("lib/openssl.rb", <<-RB)
+ s.write("lib/openssl.rb", <<-RUBY)
raise "custom openssl should not be loaded, it's not in the gemfile!"
- RB
+ RUBY
end
end
- system_gems(:bundler, "openssl-#{openssl_version}", :gem_repo => gem_repo4)
+ system_gems("openssl-#{openssl_version}", :gem_repo => gem_repo4)
file = bundled_app("require_openssl.rb")
- create_file(file, <<-RB)
+ create_file(file, <<-RUBY)
#!/usr/bin/env ruby
require "openssl"
puts OpenSSL::VERSION
warn Gem.loaded_specs.values.map(&:full_name)
- RB
+ RUBY
file.chmod(0o777)
+ env = { "PATH" => path }
aggregate_failures do
- expect(bundle!("exec #{file}", :artifice => nil)).to eq(expected)
- expect(bundle!("exec bundle exec #{file}", :artifice => nil)).to eq(expected)
- expect(bundle!("exec ruby #{file}", :artifice => nil)).to eq(expected)
- expect(run!(file.read, :artifice => nil)).to eq(expected)
+ expect(bundle("exec #{file}", :artifice => nil, :env => env)).to eq(expected)
+ expect(bundle("exec bundle exec #{file}", :artifice => nil, :env => env)).to eq(expected)
+ expect(bundle("exec ruby #{file}", :artifice => nil, :env => env)).to eq(expected)
+ expect(run(file.read, :artifice => nil, :env => env)).to eq(expected)
end
+ skip "ruby_core has openssl and rubygems in the same folder, and this test needs rubygems require but default openssl not in a directly added entry in $LOAD_PATH" if ruby_core?
# sanity check that we get the newer, custom version without bundler
- sys_exec("#{Gem.ruby} #{file}")
+ sys_exec "#{Gem.ruby} #{file}", :env => env, :raise_on_error => false
expect(err).to include("custom openssl should not be loaded")
end
end
+
+ context "with a git gem that includes extensions", :ruby_repo do
+ before do
+ build_git "simple_git_binary", &:add_c_extension
+ bundle "config set --local path .bundle"
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "simple_git_binary", :git => '#{lib_path("simple_git_binary-1.0")}'
+ G
+ end
+
+ it "allows calling bundle install" do
+ bundle "exec bundle install"
+ end
+
+ it "allows calling bundle install after removing gem.build_complete" do
+ FileUtils.rm_rf Dir[bundled_app(".bundle/**/gem.build_complete")]
+ bundle "exec #{Gem.ruby} -S bundle install"
+ end
+ end
end
end
diff --git a/spec/bundler/commands/fund_spec.rb b/spec/bundler/commands/fund_spec.rb
new file mode 100644
index 0000000000..5a0c5411da
--- /dev/null
+++ b/spec/bundler/commands/fund_spec.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle fund" do
+ before do
+ build_repo2 do
+ build_gem "has_funding_and_other_metadata" do |s|
+ s.metadata = {
+ "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
+ "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
+ "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
+ "homepage_uri" => "https://bestgemever.example.io",
+ "mailing_list_uri" => "https://groups.example.com/bestgemever",
+ "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding",
+ "source_code_uri" => "https://example.com/user/bestgemever",
+ "wiki_uri" => "https://example.com/user/bestgemever/wiki",
+ }
+ end
+
+ build_gem "has_funding", "1.2.3" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/has_funding/funding",
+ }
+ end
+
+ build_gem "gem_with_dependent_funding", "1.0" do |s|
+ s.add_dependency "has_funding"
+ end
+ end
+ end
+
+ it "prints fund information for all gems in the bundle" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding'
+ gem 'rack-obama'
+ G
+
+ bundle "fund"
+
+ expect(out).to include("* has_funding_and_other_metadata (1.0)\n Funding: https://example.com/has_funding_and_other_metadata/funding")
+ expect(out).to include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding")
+ expect(out).to_not include("rack-obama")
+ end
+
+ it "does not consider fund information for gem dependencies" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'gem_with_dependent_funding'
+ G
+
+ bundle "fund"
+
+ expect(out).to_not include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding")
+ expect(out).to_not include("gem_with_dependent_funding")
+ end
+
+ it "prints message if none of the gems have fund information" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'rack-obama'
+ G
+
+ bundle "fund"
+
+ expect(out).to include("None of the installed gems you directly depend on are looking for funding.")
+ end
+
+ describe "with --group option" do
+ it "prints fund message for only specified group gems" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'has_funding_and_other_metadata', :group => :development
+ gem 'has_funding'
+ G
+
+ bundle "fund --group development"
+ expect(out).to include("* has_funding_and_other_metadata (1.0)\n Funding: https://example.com/has_funding_and_other_metadata/funding")
+ expect(out).to_not include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding")
+ end
+ end
+end
diff --git a/spec/bundler/commands/help_spec.rb b/spec/bundler/commands/help_spec.rb
index f4f90b9347..f72763900e 100644
--- a/spec/bundler/commands/help_spec.rb
+++ b/spec/bundler/commands/help_spec.rb
@@ -1,25 +1,25 @@
# frozen_string_literal: true
RSpec.describe "bundle help" do
- it "uses mann when available" do
+ it "uses man when available" do
with_fake_man do
bundle "help gemfile"
end
- expect(out).to eq(%(["#{root}/man/gemfile.5"]))
+ expect(out).to eq(%(["#{man_dir}/gemfile.5"]))
end
- it "prefixes bundle commands with bundle- when finding the groff files" do
+ it "prefixes bundle commands with bundle- when finding the man files" do
with_fake_man do
bundle "help install"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
- it "simply outputs the txt file when there is no man on the path" do
+ it "simply outputs the human readable file when there is no man on the path" do
with_path_as("") do
bundle "help install"
end
- expect(out).to match(/BUNDLE-INSTALL/)
+ expect(out).to match(/bundle-install/)
end
it "still outputs the old help for commands that do not have man pages yet" do
@@ -28,6 +28,8 @@ RSpec.describe "bundle help" do
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?
+
File.open(tmp("bundler-testtasks"), "w", 0o755) do |f|
f.puts "#!/usr/bin/env ruby\nputs ARGV.join(' ')\n"
end
@@ -36,7 +38,6 @@ RSpec.describe "bundle help" do
bundle "help testtasks"
end
- expect(exitstatus).to be_zero if exitstatus
expect(out).to eq("--help")
end
@@ -44,33 +45,33 @@ RSpec.describe "bundle help" do
with_fake_man do
bundle "install --help"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
it "is called when the --help flag is used before the command" do
with_fake_man do
bundle "--help install"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
it "is called when the -h flag is used before the command" do
with_fake_man do
bundle "-h install"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
it "is called when the -h flag is used after the command" do
with_fake_man do
bundle "install -h"
end
- expect(out).to eq(%(["#{root}/man/bundle-install.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle-install.1"]))
end
it "has helpful output when using --help flag for a non-existent command" do
with_fake_man do
- bundle "instill -h"
+ bundle "instill -h", :raise_on_error => false
end
expect(err).to include('Could not find command "instill".')
end
@@ -79,11 +80,11 @@ RSpec.describe "bundle help" do
with_fake_man do
bundle "--help"
end
- expect(out).to eq(%(["#{root}/man/bundle.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle.1"]))
with_fake_man do
bundle "-h"
end
- expect(out).to eq(%(["#{root}/man/bundle.1"]))
+ expect(out).to eq(%(["#{man_dir}/bundle.1"]))
end
end
diff --git a/spec/bundler/commands/info_spec.rb b/spec/bundler/commands/info_spec.rb
index 4572823498..7f618b5f6c 100644
--- a/spec/bundler/commands/info_spec.rb
+++ b/spec/bundler/commands/info_spec.rb
@@ -3,18 +3,33 @@
RSpec.describe "bundle info" do
context "with a standard Gemfile" do
before do
+ build_repo2 do
+ build_gem "has_metadata" do |s|
+ s.metadata = {
+ "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
+ "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
+ "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
+ "homepage_uri" => "https://bestgemever.example.io",
+ "mailing_list_uri" => "https://groups.example.com/bestgemever",
+ "source_code_uri" => "https://example.com/user/bestgemever",
+ "wiki_uri" => "https://example.com/user/bestgemever/wiki",
+ }
+ end
+ end
+
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rails"
+ gem "has_metadata"
G
end
it "creates a Gemfile.lock when invoked with a gem name" do
- FileUtils.rm("Gemfile.lock")
+ FileUtils.rm(bundled_app_lock)
bundle "info rails"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
it "prints information if gem exists in bundle" do
@@ -35,11 +50,41 @@ RSpec.describe "bundle info" do
expect(out).to eq(root.to_s)
end
+ it "prints gem version if exists in bundle" do
+ bundle "info rails --version"
+ expect(out).to eq("2.3.2")
+ end
+
+ it "doesn't claim that bundler has been deleted, even if using a custom path without bundler there" do
+ bundle "config set --local path vendor/bundle"
+ bundle "install"
+ bundle "info bundler"
+ expect(out).to include("\tPath: #{root}")
+ expect(err).not_to match(/The gem bundler has been deleted/i)
+ end
+
it "complains if gem not in bundle" do
- bundle "info missing"
+ bundle "info missing", :raise_on_error => false
expect(err).to eq("Could not find gem 'missing'.")
end
+ it "warns if path no longer exists on disk" do
+ FileUtils.rm_rf(default_bundle_path("gems", "rails-2.3.2"))
+
+ bundle "info rails --path"
+
+ expect(err).to match(/The gem rails has been deleted/i)
+ expect(err).to match(default_bundle_path("gems", "rails-2.3.2").to_s)
+
+ bundle "info rail --path"
+ expect(err).to match(/The gem rails has been deleted/i)
+ expect(err).to match(default_bundle_path("gems", "rails-2.3.2").to_s)
+
+ bundle "info rails"
+ expect(err).to match(/The gem rails has been deleted/i)
+ expect(err).to match(default_bundle_path("gems", "rails-2.3.2").to_s)
+ end
+
context "given a default gem shippped in ruby", :ruby_repo do
it "prints information about the default gem" do
bundle "info rdoc"
@@ -48,6 +93,22 @@ RSpec.describe "bundle info" do
end
end
+ context "given a gem with metadata" do
+ it "prints the gem metadata" do
+ bundle "info has_metadata"
+ expect(out).to include "* has_metadata (1.0)
+\tSummary: This is just a fake gem for testing
+\tHomepage: http://example.com
+\tDocumentation: https://www.example.info/gems/bestgemever/0.0.1
+\tSource Code: https://example.com/user/bestgemever
+\tWiki: https://example.com/user/bestgemever/wiki
+\tChangelog: https://example.com/user/bestgemever/CHANGELOG.md
+\tBug Tracker: https://example.com/user/bestgemever/issues
+\tMailing List: https://groups.example.com/bestgemever
+\tPath: #{default_bundle_path("gems", "has_metadata-1.0")}"
+ end
+ end
+
context "when gem does not have homepage" do
before do
build_repo2 do
@@ -71,6 +132,7 @@ RSpec.describe "bundle info" do
it "prints out git info" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
expect(the_bundle).to include_gems "foo 1.0"
@@ -86,6 +148,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)}"
gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg"
G
expect(the_bundle).to include_gems "foo 1.0.omg"
@@ -97,6 +160,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)}"
gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{sha}"
G
@@ -107,17 +171,18 @@ 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)}"
gem "foo", "1.0.0-beta.1", :git => "#{lib_path("foo")}"
G
expect(the_bundle).to include_gems "foo 1.0.0.pre.beta.1"
- bundle! "info foo"
+ bundle "info foo"
expect(out).to include("foo (1.0.0.pre.beta.1")
end
end
context "with a valid regexp for gem name" do
- it "presents alternatives" do
+ it "presents alternatives", :readline do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -125,7 +190,7 @@ RSpec.describe "bundle info" do
G
bundle "info rac"
- expect(out).to eq "1 : rack\n2 : rack-obama\n0 : - exit -\n>"
+ expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>)?\z/)
end
end
@@ -138,8 +203,22 @@ RSpec.describe "bundle info" do
invalid_regexp = "[]"
- bundle "info #{invalid_regexp}"
+ bundle "info #{invalid_regexp}", :raise_on_error => false
expect(err).to include("Could not find gem '#{invalid_regexp}'.")
end
end
+
+ context "with without configured" do
+ it "does not find the gem, but gives a helpful error" do
+ bundle "config without test"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rails", group: :test
+ G
+
+ bundle "info rails", :raise_on_error => false
+ expect(err).to include("Could not find gem 'rails', because it's in the group 'test', configured to be ignored.")
+ end
+ end
end
diff --git a/spec/bundler/commands/init_spec.rb b/spec/bundler/commands/init_spec.rb
index 7960ce85bd..683a453c7d 100644
--- a/spec/bundler/commands/init_spec.rb
+++ b/spec/bundler/commands/init_spec.rb
@@ -2,9 +2,9 @@
RSpec.describe "bundle init" do
it "generates a Gemfile" do
- bundle! :init
+ bundle :init
expect(out).to include("Writing new Gemfile")
- expect(bundled_app("Gemfile")).to be_file
+ expect(bundled_app_gemfile).to be_file
end
context "when a Gemfile already exists" do
@@ -15,11 +15,11 @@ RSpec.describe "bundle init" do
end
it "does not change existing Gemfiles" do
- expect { bundle :init }.not_to change { File.read(bundled_app("Gemfile")) }
+ expect { bundle :init, :raise_on_error => false }.not_to change { File.read(bundled_app_gemfile) }
end
it "notifies the user that an existing Gemfile already exists" do
- bundle :init
+ bundle :init, :raise_on_error => false
expect(err).to include("Gemfile already exists")
end
end
@@ -28,13 +28,11 @@ RSpec.describe "bundle init" do
let(:subdir) { "child_dir" }
it "lets users generate a Gemfile in a child directory" do
- bundle! :init
+ bundle :init
FileUtils.mkdir bundled_app(subdir)
- Dir.chdir bundled_app(subdir) do
- bundle! :init
- end
+ bundle :init, :dir => bundled_app(subdir)
expect(out).to include("Writing new Gemfile")
expect(bundled_app("#{subdir}/Gemfile")).to be_file
@@ -50,9 +48,7 @@ RSpec.describe "bundle init" do
mode = File.stat(bundled_app(subdir)).mode ^ 0o222
FileUtils.chmod mode, bundled_app(subdir)
- Dir.chdir bundled_app(subdir) do
- bundle :init
- end
+ bundle :init, :dir => bundled_app(subdir), :raise_on_error => false
expect(err).to include("directory is not writable")
expect(Dir[bundled_app("#{subdir}/*")]).to be_empty
@@ -75,7 +71,7 @@ RSpec.describe "bundle init" do
bundle :init, :gemspec => spec_file
- gemfile = bundled_app("Gemfile").read
+ gemfile = bundled_app_gemfile.read
expect(gemfile).to match(%r{source 'https://rubygems.org'})
expect(gemfile.scan(/gem "rack", "= 1.0.1"/).size).to eq(1)
expect(gemfile.scan(/gem "rspec", "= 1.2"/).size).to eq(1)
@@ -93,7 +89,7 @@ RSpec.describe "bundle init" do
S
end
- bundle :init, :gemspec => spec_file
+ bundle :init, :gemspec => spec_file, :raise_on_error => false
expect(err).to include("There was an error while loading `test.gemspec`")
end
end
@@ -103,7 +99,7 @@ RSpec.describe "bundle init" do
before { bundle "config set init_gems_rb true" }
it "generates a gems.rb" do
- bundle! :init
+ bundle :init
expect(out).to include("Writing new gems.rb")
expect(bundled_app("gems.rb")).to be_file
end
@@ -116,11 +112,11 @@ RSpec.describe "bundle init" do
end
it "does not change existing Gemfiles" do
- expect { bundle :init }.not_to change { File.read(bundled_app("gems.rb")) }
+ expect { bundle :init, :raise_on_error => false }.not_to change { File.read(bundled_app("gems.rb")) }
end
it "notifies the user that an existing gems.rb already exists" do
- bundle :init
+ bundle :init, :raise_on_error => false
expect(err).to include("gems.rb already exists")
end
end
@@ -129,13 +125,11 @@ RSpec.describe "bundle init" do
let(:subdir) { "child_dir" }
it "lets users generate a Gemfile in a child directory" do
- bundle! :init
+ bundle :init
FileUtils.mkdir bundled_app(subdir)
- Dir.chdir bundled_app(subdir) do
- bundle! :init
- end
+ bundle :init, :dir => bundled_app(subdir)
expect(out).to include("Writing new gems.rb")
expect(bundled_app("#{subdir}/gems.rb")).to be_file
diff --git a/spec/bundler/commands/inject_spec.rb b/spec/bundler/commands/inject_spec.rb
index 01c1f91877..2d97bf6ff0 100644
--- a/spec/bundler/commands/inject_spec.rb
+++ b/spec/bundler/commands/inject_spec.rb
@@ -10,9 +10,9 @@ RSpec.describe "bundle inject", :bundler => "< 3" do
context "without a lockfile" do
it "locks with the injected gems" do
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/)
+ expect(bundled_app_lock.read).to match(/rack-obama/)
end
end
@@ -22,28 +22,28 @@ RSpec.describe "bundle inject", :bundler => "< 3" do
end
it "adds the injected gems to the Gemfile" do
- expect(bundled_app("Gemfile").read).not_to match(/rack-obama/)
+ expect(bundled_app_gemfile.read).not_to match(/rack-obama/)
bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile").read).to match(/rack-obama/)
+ expect(bundled_app_gemfile.read).to match(/rack-obama/)
end
it "locks with the injected gems" do
- expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/)
+ expect(bundled_app_lock.read).not_to match(/rack-obama/)
bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/)
+ expect(bundled_app_lock.read).to match(/rack-obama/)
end
end
context "with injected gems already in the Gemfile" do
it "doesn't add existing gems" do
- bundle "inject 'rack' '> 0'"
+ bundle "inject 'rack' '> 0'", :raise_on_error => false
expect(err).to match(/cannot specify the same gem twice/i)
end
end
context "incorrect arguments" do
it "fails when more than 2 arguments are passed" do
- bundle "inject gem_name 1 v"
+ bundle "inject gem_name 1 v", :raise_on_error => false
expect(err).to eq(<<-E.strip)
ERROR: "bundle inject" was called with arguments ["gem_name", "1", "v"]
Usage: "bundle inject GEM VERSION"
@@ -54,7 +54,7 @@ Usage: "bundle inject GEM VERSION"
context "with source option" do
it "add gem with source option in gemfile" do
bundle "inject 'foo' '>0' --source #{file_uri_for(gem_repo1)}"
- gemfile = bundled_app("Gemfile").read
+ gemfile = bundled_app_gemfile.read
str = "gem \"foo\", \"> 0\", :source => \"#{file_uri_for(gem_repo1)}\""
expect(gemfile).to include str
end
@@ -63,14 +63,14 @@ Usage: "bundle inject GEM VERSION"
context "with group option" do
it "add gem with group option in gemfile" do
bundle "inject 'rack-obama' '>0' --group=development"
- gemfile = bundled_app("Gemfile").read
+ gemfile = bundled_app_gemfile.read
str = "gem \"rack-obama\", \"> 0\", :group => :development"
expect(gemfile).to include str
end
it "add gem with multiple groups in gemfile" do
bundle "inject 'rack-obama' '>0' --group=development,test"
- gemfile = bundled_app("Gemfile").read
+ gemfile = bundled_app_gemfile.read
str = "gem \"rack-obama\", \"> 0\", :groups => [:development, :test]"
expect(gemfile).to include str
end
@@ -80,21 +80,21 @@ Usage: "bundle inject GEM VERSION"
before do
bundle "install"
if Bundler.feature_flag.bundler_3_mode?
- bundle! "config set --local deployment true"
+ bundle "config set --local deployment true"
else
- bundle! "config set --local frozen true"
+ bundle "config set --local frozen true"
end
end
it "injects anyway" do
bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile").read).to match(/rack-obama/)
+ expect(bundled_app_gemfile.read).to match(/rack-obama/)
end
it "locks with the injected gems" do
- expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/)
+ expect(bundled_app_lock.read).not_to match(/rack-obama/)
bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app("Gemfile.lock").read).to match(/rack-obama/)
+ expect(bundled_app_lock.read).to match(/rack-obama/)
end
it "restores frozen afterwards" do
@@ -108,10 +108,10 @@ Usage: "bundle inject GEM VERSION"
source "#{file_uri_for(gem_repo1)}"
gem "rack-obama"
G
- bundle "inject 'rack' '> 0'"
+ bundle "inject 'rack' '> 0'", :raise_on_error => false
expect(err).to match(/trying to install in deployment mode after changing/)
- expect(bundled_app("Gemfile.lock").read).not_to match(/rack-obama/)
+ expect(bundled_app_lock.read).not_to match(/rack-obama/)
end
end
end
diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb
index b57d81b10a..e00caa5315 100644
--- a/spec/bundler/commands/install_spec.rb
+++ b/spec/bundler/commands/install_spec.rb
@@ -12,12 +12,12 @@ RSpec.describe "bundle install with gem sources" do
end
it "does not make a lockfile if the install fails" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
raise StandardError, "FAIL"
G
expect(err).to include('StandardError, "FAIL"')
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
end
it "creates a Gemfile.lock" do
@@ -26,7 +26,7 @@ RSpec.describe "bundle install with gem sources" do
gem "rack"
G
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
it "does not create ./.bundle by default", :bundler => "< 3" do
@@ -35,7 +35,7 @@ RSpec.describe "bundle install with gem sources" do
gem "rack"
G
- bundle! :install # can't use install_gemfile since it sets retry
+ bundle :install # can't use install_gemfile since it sets retry
expect(bundled_app(".bundle")).not_to exist
end
@@ -45,7 +45,7 @@ RSpec.describe "bundle install with gem sources" do
gem "rack"
G
- bundle! :install, :env => { "BUNDLE_PATH__SYSTEM" => "true" } # can't use install_gemfile since it sets retry
+ bundle :install, :env => { "BUNDLE_PATH__SYSTEM" => "true" } # can't use install_gemfile since it sets retry
expect(bundled_app(".bundle")).not_to exist
end
@@ -66,13 +66,13 @@ RSpec.describe "bundle install with gem sources" do
gem 'rack'
G
- lockfile = File.read(bundled_app("Gemfile.lock"))
+ lockfile = File.read(bundled_app_lock)
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
raise StandardError, "FAIL"
G
- expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile)
+ expect(File.read(bundled_app_lock)).to eq(lockfile)
end
it "does not touch the lockfile if nothing changed" do
@@ -81,7 +81,7 @@ RSpec.describe "bundle install with gem sources" do
gem "rack"
G
- expect { run "1" }.not_to change { File.mtime(bundled_app("Gemfile.lock")) }
+ expect { run "1" }.not_to change { File.mtime(bundled_app_lock) }
end
it "fetches gems" do
@@ -94,6 +94,21 @@ RSpec.describe "bundle install with gem sources" do
expect(the_bundle).to include_gems("rack 1.0.0")
end
+ it "auto-heals missing gems" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'rack'
+ G
+
+ FileUtils.rm_rf(default_bundle_path("gems/rack-1.0.0"))
+
+ bundle "install --verbose"
+
+ expect(out).to include("Installing rack 1.0.0")
+ expect(default_bundle_path("gems/rack-1.0.0")).to exist
+ expect(the_bundle).to include_gems("rack 1.0.0")
+ end
+
it "fetches gems when multiple versions are specified" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -115,11 +130,11 @@ RSpec.describe "bundle install with gem sources" do
end
it "raises an appropriate error when gems are specified using symbols" do
- install_gemfile(<<-G)
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem :rack
G
- expect(exitstatus).to eq(4) if exitstatus
+ expect(exitstatus).to eq(4)
end
it "pulls in dependencies" do
@@ -141,8 +156,14 @@ RSpec.describe "bundle install with gem sources" do
end
it "does not install the development dependency" do
+ build_repo2 do
+ build_gem "with_development_dependency" do |s|
+ s.add_development_dependency "activesupport", "= 2.3.5"
+ end
+ end
+
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "with_development_dependency"
G
@@ -176,7 +197,7 @@ RSpec.describe "bundle install with gem sources" do
end
it "does not reinstall any gem that is already available locally" do
- system_gems "activesupport-2.3.2", :path => :bundle_path
+ system_gems "activesupport-2.3.2", :path => default_bundle_path
build_repo2 do
build_gem "activesupport", "2.3.2" do |s|
@@ -216,8 +237,22 @@ RSpec.describe "bundle install with gem sources" do
expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
end
+ it "loads env plugins" do
+ plugin_msg = "hello from an env plugin!"
+ create_file "plugins/rubygems_plugin.rb", "puts '#{plugin_msg}'"
+ rubylib = ENV["RUBYLIB"].to_s.split(File::PATH_SEPARATOR).unshift(bundled_app("plugins").to_s).join(File::PATH_SEPARATOR)
+ install_gemfile <<-G, :env => { "RUBYLIB" => rubylib }
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ expect(last_command.stdboth).to include(plugin_msg)
+ end
+
describe "with a gem that installs multiple platforms" do
it "installs gems for the local platform as first choice" do
+ skip "version is 1.0, not 1.0.0" if Gem.win_platform?
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "platform_specific"
@@ -271,28 +306,32 @@ RSpec.describe "bundle install with gem sources" do
end
it "works" do
- bundle "install", forgotten_command_line_options(:path => "vendor")
+ bundle "config set --local path vendor"
+ bundle "install"
expect(the_bundle).to include_gems "rack 1.0"
end
it "allows running bundle install --system without deleting foo", :bundler => "< 3" do
- bundle "install", forgotten_command_line_options(:path => "vendor")
- bundle "install", forgotten_command_line_options(:system => true)
+ bundle "install --path vendor"
+ bundle "install --system"
FileUtils.rm_rf(bundled_app("vendor"))
expect(the_bundle).to include_gems "rack 1.0"
end
it "allows running bundle install --system after deleting foo", :bundler => "< 3" do
- bundle "install", forgotten_command_line_options(:path => "vendor")
+ bundle "install --path vendor"
FileUtils.rm_rf(bundled_app("vendor"))
- bundle "install", forgotten_command_line_options(:system => true)
+ bundle "install --system"
expect(the_bundle).to include_gems "rack 1.0"
end
end
it "finds gems in multiple sources", :bundler => "< 3" do
- build_repo2
- update_repo2
+ build_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+ end
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -306,80 +345,103 @@ RSpec.describe "bundle install with gem sources" do
end
it "gives a useful error if no sources are set" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
gem "rack"
G
- bundle :install
- expect(err).to include("Your Gemfile has no gem server sources")
+ expect(err).to include("This Gemfile does not include an explicit global source. " \
+ "Not using an explicit global source may result in a different lockfile being generated depending on " \
+ "the gems you have installed locally before bundler is run. " \
+ "Instead, define a global source in your Gemfile like this: source \"https://rubygems.org\".")
end
it "creates a Gemfile.lock on a blank Gemfile" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
G
- expect(File.exist?(bundled_app("Gemfile.lock"))).to eq(true)
+ expect(File.exist?(bundled_app_lock)).to eq(true)
end
- context "throws a warning if a gem is added twice in Gemfile" do
- it "without version requirements" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- gem "rack"
- G
+ it "throws a warning if a gem is added twice in Gemfile without version requirements" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack"
+ gem "rack"
+ G
- expect(err).to include("Your Gemfile lists the gem rack (>= 0) more than once.")
- expect(err).to include("Remove any duplicate entries and specify the gem only once.")
- expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
- end
+ expect(err).to include("Your Gemfile lists the gem rack (>= 0) more than once.")
+ expect(err).to include("Remove any duplicate entries and specify the gem only once.")
+ expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
+ end
- it "with same versions" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", "1.0"
- gem "rack", "1.0"
- G
+ it "throws a warning if a gem is added twice in Gemfile with same versions" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack", "1.0"
+ gem "rack", "1.0"
+ G
- expect(err).to include("Your Gemfile lists the gem rack (= 1.0) more than once.")
- expect(err).to include("Remove any duplicate entries and specify the gem only once.")
- expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
- end
+ expect(err).to include("Your Gemfile lists the gem rack (= 1.0) more than once.")
+ expect(err).to include("Remove any duplicate entries and specify the gem only once.")
+ expect(err).to include("While it's not a problem now, it could cause errors if you change the version of one of them later.")
end
- context "throws an error if a gem is added twice in Gemfile" do
- it "when version of one dependency is not specified" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- gem "rack", "1.0"
- G
+ it "does not throw a warning if a gem is added once in Gemfile and also inside a gemspec as a development dependency" do
+ build_lib "my-gem", :path => bundled_app do |s|
+ s.add_development_dependency "my-private-gem"
+ end
- expect(err).to include("You cannot specify the same gem twice with different version requirements")
- expect(err).to include("You specified: rack (>= 0) and rack (= 1.0).")
+ build_repo2 do
+ build_gem "my-private-gem"
end
- it "when different versions of both dependencies are specified" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", "1.0"
- gem "rack", "1.1"
- G
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo2)}"
- expect(err).to include("You cannot specify the same gem twice with different version requirements")
- expect(err).to include("You specified: rack (= 1.0) and rack (= 1.1).")
- end
+ gemspec
+
+ gem "my-private-gem", :group => :development
+ G
+
+ bundle :install
+
+ expect(err).to be_empty
+ expect(the_bundle).to include_gems("my-private-gem 1.0")
+ end
+
+ it "throws an error if a gem is added twice in Gemfile when version of one dependency is not specified" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack"
+ gem "rack", "1.0"
+ G
+
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).to include("You specified: rack (>= 0) and rack (= 1.0).")
+ end
+
+ it "throws an error if a gem is added twice in Gemfile when different versions of both dependencies are specified" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack", "1.0"
+ gem "rack", "1.1"
+ G
+
+ expect(err).to include("You cannot specify the same gem twice with different version requirements")
+ expect(err).to include("You specified: rack (= 1.0) and rack (= 1.1).")
end
it "gracefully handles error when rubygems server is unavailable" do
- install_gemfile <<-G, :artifice => nil
+ skip "networking issue" if Gem.win_platform?
+
+ install_gemfile <<-G, :artifice => nil, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
source "http://0.0.0.0:9384" do
gem 'foo'
end
G
- bundle :install, :artifice => nil
expect(err).to include("Could not fetch specs from http://0.0.0.0:9384/")
expect(err).not_to include("file://")
end
@@ -397,7 +459,7 @@ RSpec.describe "bundle install with gem sources" do
build_gem "ruby-ajp", "1.0.0"
end
- install_gemfile <<-G, :full_index => true
+ install_gemfile <<-G, :full_index => true, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
gem "ajp-rails", "0.0.0"
@@ -405,7 +467,7 @@ RSpec.describe "bundle install with gem sources" do
expect(last_command.stdboth).not_to match(/Error Report/i)
expect(err).to include("An error occurred while installing ajp-rails (0.0.0), and Bundler cannot continue.").
- and include("Make sure that `gem install ajp-rails -v '0.0.0' --source '#{file_uri_for(gem_repo2)}/'` succeeds before bundling.")
+ and include("Bundler::APIResponseInvalidDependenciesError")
end
it "doesn't blow up when the local .bundle/config is empty" do
@@ -417,7 +479,6 @@ RSpec.describe "bundle install with gem sources" do
gem 'foo'
G
- expect(exitstatus).to eq(0) if exitstatus
end
it "doesn't blow up when the global .bundle/config is empty" do
@@ -429,7 +490,6 @@ RSpec.describe "bundle install with gem sources" do
gem 'foo'
G
- expect(exitstatus).to eq(0) if exitstatus
end
end
@@ -438,9 +498,10 @@ RSpec.describe "bundle install with gem sources" do
context "and using an unsupported Ruby version" do
it "prints an error" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
::RUBY_VERSION = '2.0.1'
ruby '~> 2.2'
+ source "#{file_uri_for(gem_repo1)}"
G
expect(err).to include("Your Ruby version is 2.0.1, but your Gemfile specified ~> 2.2")
end
@@ -452,12 +513,14 @@ RSpec.describe "bundle install with gem sources" do
::RUBY_VERSION = '2.1.3'
::RUBY_PATCHLEVEL = 100
ruby '~> 2.1.0'
+ source "#{file_uri_for(gem_repo1)}"
G
end
it "writes current Ruby version to Gemfile.lock" do
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -478,10 +541,12 @@ RSpec.describe "bundle install with gem sources" do
::RUBY_VERSION = '2.2.3'
::RUBY_PATCHLEVEL = 100
ruby '~> 2.2.0'
+ source "#{file_uri_for(gem_repo1)}"
G
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -496,49 +561,199 @@ RSpec.describe "bundle install with gem sources" do
#{Bundler::VERSION}
L
end
+
+ it "does not crash when unlocking" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ ruby '>= 2.1.0'
+ G
+
+ bundle "update"
+
+ expect(err).not_to include("Could not find gem 'Ruby")
+ end
end
end
describe "when Bundler root contains regex chars" do
- before do
+ it "doesn't blow up when using the `gem` DSL" do
root_dir = tmp("foo[]bar")
FileUtils.mkdir_p(root_dir)
- in_app_root_custom(root_dir)
- end
- it "doesn't blow up" do
build_lib "foo"
gemfile = <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', :path => "#{lib_path("foo-1.0")}"
G
- File.open("Gemfile", "w") do |file|
+ File.open("#{root_dir}/Gemfile", "w") do |file|
file.puts gemfile
end
- bundle :install
+ bundle :install, :dir => root_dir
+ end
+
+ it "doesn't blow up when using the `gemspec` DSL" do
+ root_dir = tmp("foo[]bar")
+
+ FileUtils.mkdir_p(root_dir)
+
+ build_lib "foo", :path => root_dir
+ gemfile = <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gemspec
+ G
+ File.open("#{root_dir}/Gemfile", "w") do |file|
+ file.puts gemfile
+ end
- expect(exitstatus).to eq(0) if exitstatus
+ bundle :install, :dir => root_dir
end
end
describe "when requesting a quiet install via --quiet" do
- it "should be quiet" do
+ it "should be quiet if there are no warnings" do
bundle "config set force_ruby_platform true"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack'
G
bundle :install, :quiet => true
- expect(err).to include("Could not find gem 'rack'")
- expect(err).to_not include("Your Gemfile has no gem server sources")
+ expect(out).to be_empty
+ expect(err).to be_empty
+ end
+
+ it "should still display warnings and errors" do
+ bundle "config set force_ruby_platform true"
+
+ create_file("install_with_warning.rb", <<~RUBY)
+ require "#{lib_dir}/bundler"
+ require "#{lib_dir}/bundler/cli"
+ require "#{lib_dir}/bundler/cli/install"
+
+ module RunWithWarning
+ def run
+ super
+ rescue
+ Bundler.ui.warn "BOOOOO"
+ raise
+ end
+ end
+
+ Bundler::CLI::Install.prepend(RunWithWarning)
+ RUBY
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'non-existing-gem'
+ G
+
+ bundle :install, :quiet => true, :raise_on_error => false, :env => { "RUBYOPT" => "-r#{bundled_app("install_with_warning.rb")}" }
+ expect(out).to be_empty
+ expect(err).to include("Could not find gem 'non-existing-gem'")
+ expect(err).to include("BOOOOO")
+ end
+ end
+
+ describe "when bundle path does not have write access", :permissions do
+ let(:bundle_path) { bundled_app("vendor") }
+
+ before do
+ FileUtils.mkdir_p(bundle_path)
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'rack'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod(0o500, bundle_path)
+
+ bundle "config set --local path vendor"
+ bundle :install, :raise_on_error => false
+ expect(err).to include(bundle_path.to_s)
+ expect(err).to include("grant write permissions")
+ end
+ end
+
+ describe "when bundle gems path does not have write access", :permissions do
+ let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
+
+ before do
+ FileUtils.mkdir_p(gems_path)
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'rack'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod("-x", gems_path)
+ bundle "config set --local path vendor"
+
+ begin
+ bundle :install, :raise_on_error => false
+ ensure
+ FileUtils.chmod("+x", gems_path)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to create `#{gems_path.join("rack-1.0.0")}`. " \
+ "It is likely that you need to grant executable permissions for all parent directories and write permissions for `#{gems_path}`."
+ )
+ end
+ end
+
+ describe "when the path of a specific gem is not writable", :permissions do
+ let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
+ let(:foo_path) { gems_path.join("foo-1.0.0") }
+
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.write "CHANGELOG.md", "foo"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'foo'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ bundle "config set --local path vendor"
+ bundle :install
+ expect(out).to include("Bundle complete!")
+ expect(err).to be_empty
+
+ FileUtils.chmod("-x", foo_path)
+
+ begin
+ bundle "install --redownload", :raise_on_error => false
+ ensure
+ FileUtils.chmod("+x", foo_path)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to delete `#{foo_path}`. " \
+ "It is likely that you need to grant executable permissions for all parent directories " \
+ "and write permissions for `#{gems_path}`, and the same thing for all subdirectories inside #{foo_path}."
+ )
end
end
- describe "when bundle path does not have write access" do
+ describe "when bundle cache path does not have write access", :permissions do
+ let(:cache_path) { bundled_app("vendor/#{Bundler.ruby_scope}/cache") }
+
before do
- FileUtils.mkdir_p(bundled_app("vendor"))
+ FileUtils.mkdir_p(cache_path)
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem 'rack'
@@ -546,26 +761,27 @@ RSpec.describe "bundle install with gem sources" do
end
it "should display a proper message to explain the problem" do
- FileUtils.chmod(0o500, bundled_app("vendor"))
+ FileUtils.chmod(0o500, cache_path)
- bundle :install, forgotten_command_line_options(:path => "vendor")
- expect(err).to include(bundled_app("vendor").to_s)
+ bundle "config set --local path vendor"
+ bundle :install, :raise_on_error => false
+ expect(err).to include(cache_path.to_s)
expect(err).to include("grant write permissions")
end
end
context "after installing with --standalone" do
before do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- forgotten_command_line_options(:path => "bundle")
- bundle! "install", :standalone => true
+ bundle "config set --local path bundle"
+ bundle "install", :standalone => true
end
it "includes the standalone path" do
- bundle! "binstubs rack", :standalone => true
+ bundle "binstubs rack", :standalone => true
standalone_line = File.read(bundled_app("bin/rackup")).each_line.find {|line| line.include? "$:.unshift" }.strip
expect(standalone_line).to eq %($:.unshift File.expand_path "../../bundle", path.realpath)
end
@@ -580,10 +796,166 @@ RSpec.describe "bundle install with gem sources" do
end
it "should display a helpful message explaining how to fix it" do
- bundle :install, :env => { "BUNDLE_RUBYGEMS__ORG" => "user:pass{word" }
- expect(exitstatus).to eq(17) if exitstatus
+ bundle :install, :env => { "BUNDLE_RUBYGEMS__ORG" => "user:pass{word" }, :raise_on_error => false
+ expect(exitstatus).to eq(17)
expect(err).to eq("Please CGI escape your usernames and passwords before " \
"setting them for authentication.")
end
end
+
+ context "in a frozen bundle" do
+ before do
+ build_repo4 do
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-19"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "libv8"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ libv8 (8.4.255.0-x86_64-darwin-19)
+
+ PLATFORMS
+ x86_64-darwin-19
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "config set --local deployment true"
+ end
+
+ it "should fail loudly if the lockfile platforms don't include the current platform" do
+ simulate_platform(Gem::Platform.new("x86_64-linux")) { bundle "install", :raise_on_error => false }
+
+ expect(err).to eq(
+ "Your bundle only supports platforms [\"x86_64-darwin-19\"] but your local platform is x86_64-linux. " \
+ "Add the current platform to the lockfile with `bundle lock --add-platform x86_64-linux` and try again."
+ )
+ end
+ end
+
+ context "with missing platform specific gems in lockfile" do
+ before do
+ build_repo4 do
+ build_gem "racc", "1.5.2"
+
+ build_gem "nokogiri", "1.12.4" do |s|
+ s.platform = "x86_64-darwin"
+ s.add_runtime_dependency "racc", "~> 1.4"
+ end
+
+ build_gem "nokogiri", "1.12.4" do |s|
+ s.platform = "x86_64-linux"
+ s.add_runtime_dependency "racc", "~> 1.4"
+ end
+
+ build_gem "crass", "1.0.6"
+
+ build_gem "loofah", "2.12.0" do |s|
+ s.add_runtime_dependency "crass", "~> 1.0.2"
+ s.add_runtime_dependency "nokogiri", ">= 1.5.9"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ ruby "#{RUBY_VERSION}"
+
+ gem "loofah", "~> 2.12.0"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ crass (1.0.6)
+ loofah (2.12.0)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.5.9)
+ nokogiri (1.12.4-x86_64-darwin)
+ racc (~> 1.4)
+ racc (1.5.2)
+
+ PLATFORMS
+ x86_64-darwin-20
+ x86_64-linux
+
+ DEPENDENCIES
+ loofah (~> 2.12.0)
+
+ RUBY VERSION
+ #{Bundler::RubyVersion.system}
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile" do
+ bundle "config set --local path vendor/bundle"
+
+ simulate_platform "x86_64-linux" do
+ bundle "install", :artifice => "compact_index"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ crass (1.0.6)
+ loofah (2.12.0)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.5.9)
+ nokogiri (1.12.4-x86_64-darwin)
+ racc (~> 1.4)
+ nokogiri (1.12.4-x86_64-linux)
+ racc (~> 1.4)
+ racc (1.5.2)
+
+ PLATFORMS
+ x86_64-darwin-20
+ x86_64-linux
+
+ DEPENDENCIES
+ loofah (~> 2.12.0)
+
+ RUBY VERSION
+ #{Bundler::RubyVersion.system}
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "with --local flag" do
+ before do
+ system_gems "rack-1.0.0", :path => default_bundle_path
+ end
+
+ it "respects installed gems without fetching any remote sources" do
+ install_gemfile <<-G, :local => true
+ source "#{file_uri_for(gem_repo1)}"
+
+ source "https://not-existing-source" do
+ gem "rack"
+ end
+ G
+
+ expect(last_command).to be_success
+ end
+ end
end
diff --git a/spec/bundler/commands/licenses_spec.rb b/spec/bundler/commands/licenses_spec.rb
index d4fa02d0a7..a203984890 100644
--- a/spec/bundler/commands/licenses_spec.rb
+++ b/spec/bundler/commands/licenses_spec.rb
@@ -2,8 +2,14 @@
RSpec.describe "bundle licenses" do
before :each do
+ build_repo2 do
+ build_gem "with_license" do |s|
+ s.license = "MIT"
+ end
+ end
+
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rails"
gem "with_license"
G
@@ -18,7 +24,7 @@ RSpec.describe "bundle licenses" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rails"
gem "with_license"
gem "foo"
diff --git a/spec/bundler/commands/list_spec.rb b/spec/bundler/commands/list_spec.rb
index 71d2136d38..66930ded75 100644
--- a/spec/bundler/commands/list_spec.rb
+++ b/spec/bundler/commands/list_spec.rb
@@ -3,7 +3,7 @@
RSpec.describe "bundle list" do
context "with name-only and paths option" do
it "raises an error" do
- bundle "list --name-only --paths"
+ bundle "list --name-only --paths", :raise_on_error => false
expect(err).to eq "The `--name-only` and `--paths` options cannot be used together"
end
@@ -11,7 +11,7 @@ RSpec.describe "bundle list" do
context "with without-group and only-group option" do
it "raises an error" do
- bundle "list --without-group dev --only-group test"
+ bundle "list --without-group dev --only-group test", :raise_on_error => false
expect(err).to eq "The `--only-group` and `--without-group` options cannot be used together"
end
@@ -24,25 +24,37 @@ RSpec.describe "bundle list" do
gem "rack"
gem "rspec", :group => [:test]
+ gem "rails", :group => [:production]
G
end
context "when group is present" do
it "prints the gems not in the specified group" do
- bundle! "list --without-group test"
+ bundle "list --without-group test"
expect(out).to include(" * rack (1.0.0)")
+ expect(out).to include(" * rails (2.3.2)")
expect(out).not_to include(" * rspec (1.2.7)")
end
end
context "when group is not found" do
it "raises an error" do
- bundle "list --without-group random"
+ bundle "list --without-group random", :raise_on_error => false
expect(err).to eq "`random` group could not be found."
end
end
+
+ context "when multiple groups" do
+ it "prints the gems not in the specified groups" do
+ bundle "list --without-group test production"
+
+ expect(out).to include(" * rack (1.0.0)")
+ expect(out).not_to include(" * rails (2.3.2)")
+ expect(out).not_to include(" * rspec (1.2.7)")
+ end
+ end
end
describe "with only-group option" do
@@ -52,12 +64,13 @@ RSpec.describe "bundle list" do
gem "rack"
gem "rspec", :group => [:test]
+ gem "rails", :group => [:production]
G
end
context "when group is present" do
it "prints the gems in the specified group" do
- bundle! "list --only-group default"
+ bundle "list --only-group default"
expect(out).to include(" * rack (1.0.0)")
expect(out).not_to include(" * rspec (1.2.7)")
@@ -66,11 +79,21 @@ RSpec.describe "bundle list" do
context "when group is not found" do
it "raises an error" do
- bundle "list --only-group random"
+ bundle "list --only-group random", :raise_on_error => false
expect(err).to eq "`random` group could not be found."
end
end
+
+ context "when multiple groups" do
+ it "prints the gems in the specified groups" do
+ bundle "list --only-group default production"
+
+ expect(out).to include(" * rack (1.0.0)")
+ expect(out).to include(" * rails (2.3.2)")
+ expect(out).not_to include(" * rspec (1.2.7)")
+ end
+ end
end
context "with name-only option" do
@@ -94,6 +117,10 @@ RSpec.describe "bundle list" do
context "with paths option" do
before do
build_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "bar"
end
diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb
index 1d9813a835..22709f4528 100644
--- a/spec/bundler/commands/lock_spec.rb
+++ b/spec/bundler/commands/lock_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe "bundle lock" do
gemfile <<-G
source "#{file_uri_for(repo)}"
gem "rails"
- gem "with_license"
+ gem "weakling"
gem "foo"
G
@@ -38,9 +38,9 @@ RSpec.describe "bundle lock" do
actionpack (= 2.3.2)
activerecord (= 2.3.2)
activeresource (= 2.3.2)
- rake (= 12.3.2)
- rake (12.3.2)
- with_license (1.0)
+ rake (= 13.0.1)
+ rake (13.0.1)
+ weakling (0.0.3)
PLATFORMS
#{lockfile_platforms}
@@ -48,7 +48,7 @@ RSpec.describe "bundle lock" do
DEPENDENCIES
foo
rails
- with_license
+ weakling
BUNDLED WITH
#{Bundler::VERSION}
@@ -78,15 +78,15 @@ RSpec.describe "bundle lock" do
it "writes a lockfile when there is an outdated lockfile using --update" do
lockfile @lockfile.gsub("2.3.2", "2.3.1")
- bundle! "lock --update"
+ bundle "lock --update"
expect(read_lockfile).to eq(@lockfile)
end
it "does not fetch remote specs when using the --local option" do
- bundle "lock --update --local"
+ bundle "lock --update --local", :raise_on_error => false
- expect(err).to match(/sources listed in your Gemfile|installed locally/)
+ expect(err).to match(/locally installed gems/)
end
it "works with --gemfile flag" do
@@ -133,7 +133,7 @@ RSpec.describe "bundle lock" do
end
it "update specific gems using --update" do
- lockfile @lockfile.gsub("2.3.2", "2.3.1").gsub("12.3.2", "10.0.1")
+ lockfile @lockfile.gsub("2.3.2", "2.3.1").gsub("13.0.1", "10.0.1")
bundle "lock --update rails rake"
@@ -143,7 +143,7 @@ RSpec.describe "bundle lock" do
it "errors when updating a missing specific gems using --update" do
lockfile @lockfile
- bundle "lock --update blahblah"
+ bundle "lock --update blahblah", :raise_on_error => false
expect(err).to eq("Could not find gem 'blahblah'.")
expect(read_lockfile).to eq(@lockfile)
@@ -156,9 +156,9 @@ RSpec.describe "bundle lock" do
gem "thin"
gem "rack_middleware", :group => "test"
G
- bundle! "config set without test"
- bundle! "config set path .bundle"
- bundle! "lock"
+ bundle "config set without test"
+ bundle "config set path .bundle"
+ bundle "lock"
expect(bundled_app(".bundle")).not_to exist
end
@@ -195,6 +195,8 @@ RSpec.describe "bundle lock" do
gem 'foo'
gem 'qux'
G
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
it "single gem updates dependent gem to minor" do
@@ -211,14 +213,41 @@ RSpec.describe "bundle lock" do
end
it "supports adding new platforms" do
- bundle! "lock --add-platform java x86-mingw32"
+ bundle "lock --add-platform java x86-mingw32"
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
lockfile = Bundler::LockfileParser.new(read_lockfile)
expect(lockfile.platforms).to match_array(local_platforms.unshift(java, mingw).uniq)
end
+ it "supports adding new platforms with force_ruby_platform = true" do
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ platform_specific (1.0)
+ platform_specific (1.0-x86-linux)
+
+ PLATFORMS
+ ruby
+ x86-linux
+
+ DEPENDENCIES
+ platform_specific
+ L
+
+ bundle "config set force_ruby_platform true"
+ bundle "lock --add-platform java x86-mingw32"
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ lockfile = Bundler::LockfileParser.new(read_lockfile)
+ expect(lockfile.platforms).to contain_exactly(rb, linux, java, mingw)
+ end
+
it "supports adding the `ruby` platform" do
- bundle! "lock --add-platform ruby"
+ bundle "lock --add-platform ruby"
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
lockfile = Bundler::LockfileParser.new(read_lockfile)
expect(lockfile.platforms).to match_array(local_platforms.unshift("ruby").uniq)
end
@@ -229,23 +258,24 @@ RSpec.describe "bundle lock" do
end
it "allows removing platforms" do
- bundle! "lock --add-platform java x86-mingw32"
+ bundle "lock --add-platform java x86-mingw32"
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
lockfile = Bundler::LockfileParser.new(read_lockfile)
expect(lockfile.platforms).to match_array(local_platforms.unshift(java, mingw).uniq)
- bundle! "lock --remove-platform java"
+ bundle "lock --remove-platform java"
lockfile = Bundler::LockfileParser.new(read_lockfile)
expect(lockfile.platforms).to match_array(local_platforms.unshift(mingw).uniq)
end
it "errors when removing all platforms" do
- bundle "lock --remove-platform #{local_platforms.join(" ")}"
+ bundle "lock --remove-platform #{local_platforms.join(" ")}", :raise_on_error => false
expect(err).to include("Removing all platforms from the bundle is not allowed")
end
- # from https://github.com/bundler/bundler/issues/4896
+ # from https://github.com/rubygems/bundler/issues/4896
it "properly adds platforms when platform requirements come from different dependencies" do
build_repo4 do
build_gem "ffi", "1.9.14"
@@ -282,9 +312,9 @@ RSpec.describe "bundle lock" do
gem "gssapi"
G
- simulate_platform(mingw) { bundle! :lock }
+ simulate_platform(mingw) { bundle :lock }
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -307,9 +337,9 @@ RSpec.describe "bundle lock" do
#{Bundler::VERSION}
G
- simulate_platform(rb) { bundle! :lock }
+ simulate_platform(rb) { bundle :lock }
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -336,6 +366,176 @@ RSpec.describe "bundle lock" do
G
end
+ it "doesn't crash when an update candidate doesn't have any matching platform" do
+ build_repo4 do
+ build_gem "libv8", "8.4.255.0"
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-19"
+ end
+
+ build_gem "libv8", "15.0.71.48.1beta2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "libv8"
+ G
+
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ libv8 (8.4.255.0)
+ libv8 (8.4.255.0-x86_64-darwin-19)
+
+ PLATFORMS
+ ruby
+ x86_64-darwin-19
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ simulate_platform(Gem::Platform.new("x86_64-darwin-19")) { bundle "lock --update" }
+
+ expect(out).to match(/Writing lockfile to.+Gemfile\.lock/)
+ end
+
+ it "adds all more specific candidates when they all have the same dependencies" do
+ build_repo4 do
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-19"
+ end
+
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-20"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "libv8"
+ G
+
+ simulate_platform(Gem::Platform.new("x86_64-darwin")) { bundle "lock" }
+
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ libv8 (8.4.255.0-x86_64-darwin-19)
+ libv8 (8.4.255.0-x86_64-darwin-20)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
+ it "respects the previous lockfile if it had a matching less specific platform already locked, and installs the best variant for each platform" do
+ build_repo4 do
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-19"
+ end
+
+ build_gem "libv8", "8.4.255.0" do |s|
+ s.platform = "x86_64-darwin-20"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "libv8"
+ G
+
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ libv8 (8.4.255.0-x86_64-darwin-19)
+ libv8 (8.4.255.0-x86_64-darwin-20)
+
+ PLATFORMS
+ x86_64-darwin
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ previous_lockfile = lockfile
+
+ %w[x86_64-darwin-19 x86_64-darwin-20].each do |platform|
+ simulate_platform(Gem::Platform.new(platform)) do
+ bundle "lock"
+ expect(lockfile).to eq(previous_lockfile)
+
+ bundle "install"
+ expect(the_bundle).to include_gem("libv8 8.4.255.0 #{platform}")
+ end
+ end
+ end
+
+ it "does not conflict on ruby requirements when adding new platforms" do
+ next_minor = Gem.ruby_version.segments[0..1].map.with_index {|s, i| i == 1 ? s + 1 : s }.join(".")
+
+ build_repo4 do
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{next_minor}.dev"
+ end
+
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "universal-darwin"
+ s.required_ruby_version = "< #{next_minor}.dev"
+ end
+
+ build_gem "raygun-apm", "1.0.78" do |s|
+ s.platform = "x64-mingw32"
+ s.required_ruby_version = "< #{next_minor}.dev"
+ end
+ end
+
+ gemfile <<-G
+ source "https://localgemserver.test"
+
+ gem "raygun-apm"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ raygun-apm (1.0.78-universal-darwin)
+
+ PLATFORMS
+ x86_64-darwin-19
+
+ DEPENDENCIES
+ raygun-apm
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --add-platform x86_64-linux", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ end
+
context "when an update is available" do
let(:repo) { gem_repo2 }
@@ -347,14 +547,14 @@ RSpec.describe "bundle lock" do
end
it "does not implicitly update" do
- bundle! "lock"
+ bundle "lock"
expect(read_lockfile).to eq(@lockfile)
end
it "accounts for changes in the gemfile" do
gemfile gemfile.gsub('"foo"', '"foo", "2.0"')
- bundle! "lock"
+ bundle "lock"
expect(read_lockfile).to eq(@lockfile.sub("foo (1.0)", "foo (2.0)").sub(/foo$/, "foo (= 2.0)"))
end
diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb
index 708b41f623..db5228ebc2 100644
--- a/spec/bundler/commands/newgem_spec.rb
+++ b/spec/bundler/commands/newgem_spec.rb
@@ -10,6 +10,18 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb")).to exist
end
+ def bundle_exec_rubocop
+ prepare_gemspec(bundled_app(gem_name, "#{gem_name}.gemspec"))
+ bundle "config set path #{rubocop_gems}", :dir => bundled_app(gem_name)
+ bundle "exec rubocop --debug --config .rubocop.yml", :dir => bundled_app(gem_name)
+ end
+
+ def bundle_exec_standardrb
+ prepare_gemspec(bundled_app(gem_name, "#{gem_name}.gemspec"))
+ bundle "config set path #{standard_gems}", :dir => bundled_app(gem_name)
+ bundle "exec standardrb --debug", :dir => bundled_app(gem_name)
+ end
+
let(:generated_gemspec) { Bundler.load_gemspec_uncached(bundled_app(gem_name).join("#{gem_name}.gemspec")) }
let(:gem_name) { "mygem" }
@@ -17,85 +29,45 @@ RSpec.describe "bundle gem" do
let(:require_path) { "mygem" }
before do
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
- git_config_content = <<-EOF
- [user]
- name = "Bundler User"
- email = user@example.com
- [github]
- user = bundleuser
- EOF
- @git_config_location = ENV["GIT_CONFIG"]
- path = "#{tmp}/test_git_config.txt"
- File.open(path, "w") {|f| f.write(git_config_content) }
- ENV["GIT_CONFIG"] = path
- end
-
- after do
- FileUtils.rm(ENV["GIT_CONFIG"]) if File.exist?(ENV["GIT_CONFIG"])
- ENV["GIT_CONFIG"] = @git_config_location
- end
-
- shared_examples_for "git config is present" do
- context "git config user.{name,email} present" do
- it "sets gemspec author to git user.name if available" do
- expect(generated_gemspec.authors.first).to eq("Bundler User")
- end
-
- it "sets gemspec email to git user.email if available" do
- expect(generated_gemspec.email.first).to eq("user@example.com")
- end
- end
- end
-
- shared_examples_for "git config is absent" do
- it "sets gemspec author to default message if git user.name is not set or empty" do
- expect(generated_gemspec.authors.first).to eq("TODO: Write your name")
- end
-
- 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
+ sys_exec("git config --global user.name 'Bundler User'")
+ sys_exec("git config --global user.email user@example.com")
+ sys_exec("git config --global github.user bundleuser")
end
describe "git repo initialization" do
- shared_examples_for "a gem with an initial git repo" do
- before do
- bundle! "gem #{gem_name} #{flags}"
- end
-
- it "generates a gem skeleton with a .git folder" do
- gem_skeleton_assertions
- expect(bundled_app("#{gem_name}/.git")).to exist
- end
+ it "generates a gem skeleton with a .git folder", :readline do
+ bundle "gem #{gem_name}"
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/.git")).to exist
end
- context "when using the default" do
- it_behaves_like "a gem with an initial git repo" do
- let(:flags) { "" }
- end
+ it "generates a gem skeleton with a .git folder when passing --git", :readline do
+ bundle "gem #{gem_name} --git"
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/.git")).to exist
end
- context "when explicitly passing --git" do
- it_behaves_like "a gem with an initial git repo" do
- let(:flags) { "--git" }
- end
+ it "generates a gem skeleton without a .git folder when passing --no-git", :readline do
+ bundle "gem #{gem_name} --no-git"
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/.git")).not_to exist
end
- context "when passing --no-git" do
+ context "on a path with spaces" do
before do
- bundle! "gem #{gem_name} --no-git"
+ Dir.mkdir(bundled_app("path with spaces"))
end
- it "generates a gem skeleton without a .git folder" do
- gem_skeleton_assertions
- expect(bundled_app("#{gem_name}/.git")).not_to exist
+
+ it "properly initializes git repo", :readline do
+ bundle "gem #{gem_name}", :dir => bundled_app("path with spaces")
+ expect(bundled_app("path with spaces/#{gem_name}/.git")).to exist
end
end
end
shared_examples_for "--mit flag" do
before do
- bundle! "gem #{gem_name} --mit"
+ bundle "gem #{gem_name} --mit"
end
it "generates a gem skeleton with MIT license" do
gem_skeleton_assertions
@@ -106,7 +78,7 @@ RSpec.describe "bundle gem" do
shared_examples_for "--no-mit flag" do
before do
- bundle! "gem #{gem_name} --no-mit"
+ bundle "gem #{gem_name} --no-mit"
end
it "generates a gem skeleton without MIT license" do
gem_skeleton_assertions
@@ -115,43 +87,283 @@ RSpec.describe "bundle gem" do
end
shared_examples_for "--coc flag" do
- before do
- bundle! "gem #{gem_name} --coc"
- end
it "generates a gem skeleton with MIT license" do
+ bundle "gem #{gem_name} --coc"
gem_skeleton_assertions
expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to exist
end
- describe "README additions" do
- it "generates the README with a section for the Code of Conduct" do
- expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct")
- expect(bundled_app("#{gem_name}/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md")
- end
+ it "generates the README with a section for the Code of Conduct" do
+ bundle "gem #{gem_name} --coc"
+ expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct")
+ expect(bundled_app("#{gem_name}/README.md").read).to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md})
+ end
+
+ it "generates the README with a section for the Code of Conduct, respecting the configured git default branch", :git => ">= 2.28.0" do
+ sys_exec("git config --global init.defaultBranch main")
+ bundle "gem #{gem_name} --coc"
+
+ expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct")
+ expect(bundled_app("#{gem_name}/README.md").read).to include("https://github.com/bundleuser/#{gem_name}/blob/main/CODE_OF_CONDUCT.md")
end
end
shared_examples_for "--no-coc flag" do
before do
- bundle! "gem #{gem_name} --no-coc"
+ bundle "gem #{gem_name} --no-coc"
end
it "generates a gem skeleton without Code of Conduct" do
gem_skeleton_assertions
expect(bundled_app("#{gem_name}/CODE_OF_CONDUCT.md")).to_not exist
end
- describe "README additions" do
- it "generates the README without a section for the Code of Conduct" do
- expect(bundled_app("#{gem_name}/README.md").read).not_to include("## Code of Conduct")
- expect(bundled_app("#{gem_name}/README.md").read).not_to include("https://github.com/bundleuser/#{gem_name}/blob/master/CODE_OF_CONDUCT.md")
+ it "generates the README without a section for the Code of Conduct" do
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("## Code of Conduct")
+ expect(bundled_app("#{gem_name}/README.md").read).not_to match(%r{https://github\.com/bundleuser/#{gem_name}/blob/.*/CODE_OF_CONDUCT.md})
+ end
+ end
+
+ shared_examples_for "--changelog flag" do
+ before do
+ bundle "gem #{gem_name} --changelog"
+ end
+ it "generates a gem skeleton with a CHANGELOG", :readline do
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/CHANGELOG.md")).to exist
+ end
+ end
+
+ shared_examples_for "--no-changelog flag" do
+ before do
+ bundle "gem #{gem_name} --no-changelog"
+ end
+ it "generates a gem skeleton without a CHANGELOG", :readline do
+ gem_skeleton_assertions
+ expect(bundled_app("#{gem_name}/CHANGELOG.md")).to_not exist
+ end
+ end
+
+ shared_examples_for "--rubocop flag" do
+ context "is deprecated", :bundler => "< 3" do
+ before do
+ bundle "gem #{gem_name} --rubocop"
+ end
+
+ it "generates a gem skeleton with rubocop" do
+ gem_skeleton_assertions
+ expect(bundled_app("test-gem/Rakefile")).to read_as(
+ include("# frozen_string_literal: true").
+ and(include('require "rubocop/rake_task"').
+ and(include("RuboCop::RakeTask.new").
+ and(match(/default:.+:rubocop/))))
+ )
+ end
+
+ it "includes rubocop in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" }
+ expect(rubocop_dep).not_to be_nil
+ end
+
+ it "generates a default .rubocop.yml" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ end
+ end
+ end
+
+ shared_examples_for "--no-rubocop flag" do
+ context "is deprecated", :bundler => "< 3" do
+ define_negated_matcher :exclude, :include
+
+ before do
+ bundle "gem #{gem_name} --no-rubocop"
+ end
+
+ it "generates a gem skeleton without rubocop" do
+ gem_skeleton_assertions
+ expect(bundled_app("test-gem/Rakefile")).to read_as(exclude("rubocop"))
+ expect(bundled_app("test-gem/#{gem_name}.gemspec")).to read_as(exclude("rubocop"))
end
+
+ it "does not include rubocop in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" }
+ expect(rubocop_dep).to be_nil
+ end
+
+ it "doesn't generate a default .rubocop.yml" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ end
+ end
+ end
+
+ shared_examples_for "--linter=rubocop flag" do
+ before do
+ bundle "gem #{gem_name} --linter=rubocop"
+ end
+
+ it "generates a gem skeleton with rubocop" do
+ gem_skeleton_assertions
+ expect(bundled_app("test-gem/Rakefile")).to read_as(
+ include("# frozen_string_literal: true").
+ and(include('require "rubocop/rake_task"').
+ and(include("RuboCop::RakeTask.new").
+ and(match(/default:.+:rubocop/))))
+ )
+ end
+
+ it "includes rubocop in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" }
+ expect(rubocop_dep).not_to be_nil
+ end
+
+ it "generates a default .rubocop.yml" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ end
+ end
+
+ shared_examples_for "--linter=standard flag" do
+ before do
+ bundle "gem #{gem_name} --linter=standard"
+ end
+
+ it "generates a gem skeleton with standard" do
+ gem_skeleton_assertions
+ expect(bundled_app("test-gem/Rakefile")).to read_as(
+ include('require "standard/rake"').
+ and(match(/default:.+:standard/))
+ )
+ end
+
+ it "includes standard in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ standard_dep = builder.dependencies.find {|d| d.name == "standard" }
+ expect(standard_dep).not_to be_nil
+ end
+
+ it "generates a default .standard.yml" do
+ expect(bundled_app("#{gem_name}/.standard.yml")).to exist
+ end
+ end
+
+ shared_examples_for "--linter=none flag" do
+ define_negated_matcher :exclude, :include
+
+ before do
+ bundle "gem #{gem_name} --linter=none"
+ end
+
+ it "generates a gem skeleton without rubocop" do
+ gem_skeleton_assertions
+ expect(bundled_app("test-gem/Rakefile")).to read_as(exclude("rubocop"))
+ expect(bundled_app("test-gem/#{gem_name}.gemspec")).to read_as(exclude("rubocop"))
+ end
+
+ it "does not include rubocop in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ rubocop_dep = builder.dependencies.find {|d| d.name == "rubocop" }
+ expect(rubocop_dep).to be_nil
+ end
+
+ it "does not include standard in generated Gemfile" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ standard_dep = builder.dependencies.find {|d| d.name == "standard" }
+ expect(standard_dep).to be_nil
+ end
+
+ it "doesn't generate a default .rubocop.yml" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ end
+
+ it "doesn't generate a default .standard.yml" do
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
+ end
+
+ it "has no rubocop offenses when using --linter=rubocop flag", :readline do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext and --linter=rubocop flag", :readline do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --ext --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext, --test=minitest, and --linter=rubocop flag", :readline do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --ext --test=minitest --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext, --test=rspec, and --linter=rubocop flag", :readline do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --ext --test=rspec --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no rubocop offenses when using --ext, --ext=test-unit, and --linter=rubocop flag", :readline do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --ext --test=test-unit --linter=rubocop"
+ bundle_exec_rubocop
+ expect(last_command).to be_success
+ end
+
+ it "has no standard offenses when using --linter=standard flag", :readline do
+ skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
+ bundle "gem #{gem_name} --linter=standard"
+ bundle_exec_standardrb
+ expect(err).to be_empty
+ end
+
+ shared_examples_for "CI config is absent" do
+ it "does not create any CI files" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
end
end
- context "README.md" do
+ shared_examples_for "test framework is absent" do
+ it "does not create any test framework files" do
+ expect(bundled_app("#{gem_name}/.rspec")).to_not exist
+ expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb")).to_not exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to_not exist
+ expect(bundled_app("#{gem_name}/test/#{require_path}.rb")).to_not exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to_not exist
+ end
+ end
+
+ context "README.md", :readline do
context "git config github.user present" do
before do
- bundle! "gem #{gem_name}"
+ bundle "gem #{gem_name}"
end
it "contribute URL set to git username" do
@@ -162,7 +374,7 @@ RSpec.describe "bundle gem" do
context "git config github.user is absent" do
before do
- sys_exec("git config --unset github.user")
+ sys_exec("git config --global --unset github.user")
bundle "gem #{gem_name}"
end
@@ -173,18 +385,18 @@ RSpec.describe "bundle gem" do
end
end
- it "creates a new git repository" do
+ it "creates a new git repository", :readline do
bundle "gem #{gem_name}"
expect(bundled_app("#{gem_name}/.git")).to exist
end
- context "when git is not available" do
+ context "when git is not available", :readline do
# This spec cannot have `git` available in the test env
before do
load_paths = [lib_dir, spec_dir]
load_path_str = "-I#{load_paths.join(File::PATH_SEPARATOR)}"
- sys_exec "#{Gem.ruby} #{load_path_str} #{bindir.join("bundle")} gem #{gem_name}", "PATH" => ""
+ sys_exec "#{Gem.ruby} #{load_path_str} #{bindir.join("bundle")} gem #{gem_name}", :env => { "PATH" => "" }
end
it "creates the gem without the need for git" do
@@ -200,25 +412,24 @@ RSpec.describe "bundle gem" do
end
end
- it "generates a valid gemspec" do
- bundle! "gem newgem --bin"
+ it "generates a valid gemspec", :readline, :ruby_repo do
+ bundle "gem newgem --bin"
prepare_gemspec(bundled_app("newgem", "newgem.gemspec"))
- Dir.chdir(bundled_app("newgem")) do
- gems = ["rake-12.3.2"]
- system_gems gems, :path => :bundle_path
- bundle! "exec rake build"
- end
+ gems = ["rake-13.0.1"]
+ path = Bundler.feature_flag.default_install_uses_path? ? local_gem_path(:base => bundled_app("newgem")) : system_gem_path
+ system_gems gems, :path => path
+ bundle "exec rake build", :dir => bundled_app("newgem")
expect(last_command.stdboth).not_to include("ERROR")
end
- context "gem naming with relative paths" do
+ context "gem naming with relative paths", :readline do
it "resolves ." do
create_temporary_dir("tmp")
- bundle "gem ."
+ bundle "gem .", :dir => bundled_app("tmp")
expect(bundled_app("tmp/lib/tmp.rb")).to exist
end
@@ -226,7 +437,7 @@ RSpec.describe "bundle gem" do
it "resolves .." do
create_temporary_dir("temp/empty_dir")
- bundle "gem .."
+ bundle "gem ..", :dir => bundled_app("temp/empty_dir")
expect(bundled_app("temp/lib/temp.rb")).to exist
end
@@ -234,89 +445,164 @@ RSpec.describe "bundle gem" do
it "resolves relative directory" do
create_temporary_dir("tmp/empty/tmp")
- bundle "gem ../../empty"
+ bundle "gem ../../empty", :dir => bundled_app("tmp/empty/tmp")
expect(bundled_app("tmp/empty/lib/empty.rb")).to exist
end
def create_temporary_dir(dir)
- FileUtils.mkdir_p(dir)
- Dir.chdir(dir)
+ FileUtils.mkdir_p(bundled_app(dir))
+ end
+ end
+
+ shared_examples_for "--github-username option" do |github_username|
+ before do
+ bundle "gem #{gem_name} --github-username=#{github_username}"
+ end
+
+ it "generates a gem skeleton" do
+ gem_skeleton_assertions
+ end
+
+ it "contribute URL set to given github username" do
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("[USERNAME]")
+ expect(bundled_app("#{gem_name}/README.md").read).to include("github.com/#{github_username}")
+ end
+ end
+
+ shared_examples_for "github_username configuration" do
+ context "with github_username setting set to some value" do
+ before do
+ global_config "BUNDLE_GEM__GITHUB_USERNAME" => "different_username"
+ bundle "gem #{gem_name}"
+ end
+
+ it "generates a gem skeleton" do
+ gem_skeleton_assertions
+ end
+
+ it "contribute URL set to bundle config setting" do
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("[USERNAME]")
+ expect(bundled_app("#{gem_name}/README.md").read).to include("github.com/different_username")
+ end
+ end
+
+ context "with github_username setting set to false" do
+ before do
+ global_config "BUNDLE_GEM__GITHUB_USERNAME" => "false"
+ bundle "gem #{gem_name}"
+ end
+
+ it "generates a gem skeleton" do
+ gem_skeleton_assertions
+ end
+
+ it "contribute URL set to [USERNAME]" do
+ expect(bundled_app("#{gem_name}/README.md").read).to include("[USERNAME]")
+ expect(bundled_app("#{gem_name}/README.md").read).not_to include("github.com/bundleuser")
+ end
end
end
shared_examples_for "generating a gem" do
it "generates a gem skeleton" do
- bundle! "gem #{gem_name}"
+ bundle "gem #{gem_name}"
expect(bundled_app("#{gem_name}/#{gem_name}.gemspec")).to exist
expect(bundled_app("#{gem_name}/Gemfile")).to exist
expect(bundled_app("#{gem_name}/Rakefile")).to exist
expect(bundled_app("#{gem_name}/lib/#{require_path}.rb")).to exist
expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb")).to exist
+ expect(bundled_app("#{gem_name}/sig/#{require_path}.rbs")).to exist
expect(bundled_app("#{gem_name}/.gitignore")).to exist
expect(bundled_app("#{gem_name}/bin/setup")).to exist
expect(bundled_app("#{gem_name}/bin/console")).to exist
expect(bundled_app("#{gem_name}/bin/setup")).to be_executable
expect(bundled_app("#{gem_name}/bin/console")).to be_executable
+ expect(bundled_app("#{gem_name}/bin/setup").read).to start_with("#!")
+ expect(bundled_app("#{gem_name}/bin/console").read).to start_with("#!")
end
it "starts with version 0.1.0" do
- bundle! "gem #{gem_name}"
+ bundle "gem #{gem_name}"
expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/VERSION = "0.1.0"/)
end
+ it "declare String type for VERSION constant" do
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/sig/#{require_path}.rbs").read).to match(/VERSION: String/)
+ end
+
context "git config user.{name,email} is set" do
before do
- bundle! "gem #{gem_name}"
+ bundle "gem #{gem_name}"
+ end
+
+ it "sets gemspec author to git user.name if available" do
+ expect(generated_gemspec.authors.first).to eq("Bundler User")
end
- it_should_behave_like "git config is present"
+ it "sets gemspec email to git user.email if available" do
+ expect(generated_gemspec.email.first).to eq("user@example.com")
+ end
end
context "git config user.{name,email} is not set" do
before do
- `git config --unset user.name`
- `git config --unset user.email`
+ sys_exec("git config --global --unset user.name")
+ sys_exec("git config --global --unset user.email")
bundle "gem #{gem_name}"
end
- it_should_behave_like "git config is absent"
+ it "sets gemspec author to default message if git user.name is not set or empty" do
+ expect(generated_gemspec.authors.first).to eq("TODO: Write your name")
+ end
+
+ it "sets gemspec email to default message if git user.email is not set or empty" do
+ expect(generated_gemspec.email.first).to eq("TODO: Write your email address")
+ end
end
it "sets gemspec metadata['allowed_push_host']" do
- bundle! "gem #{gem_name}"
+ bundle "gem #{gem_name}"
expect(generated_gemspec.metadata["allowed_push_host"]).
- to match(/mygemserver\.com/)
+ to match(/example\.com/)
end
it "sets a minimum ruby version" do
- bundle! "gem #{gem_name}"
-
- bundler_gemspec = Bundler::GemHelper.new(gemspec_dir).gemspec
+ bundle "gem #{gem_name}"
- expect(bundler_gemspec.required_ruby_version).to eq(generated_gemspec.required_ruby_version)
+ expect(generated_gemspec.required_ruby_version.to_s).to start_with(">=")
end
it "requires the version file" do
- bundle! "gem #{gem_name}"
+ bundle "gem #{gem_name}"
- expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(%r{require "#{require_path}/version"})
+ expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(%r{require_relative "#{require_relative_path}/version"})
end
it "creates a base error class" do
- bundle! "gem #{gem_name}"
+ bundle "gem #{gem_name}"
expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/class Error < StandardError; end$/)
end
+ it "does not include the gemspec file in files" do
+ bundle "gem #{gem_name}"
+
+ bundler_gemspec = Bundler::GemHelper.new(gemspec_dir).gemspec
+
+ expect(bundler_gemspec.files).not_to include("#{gem_name}.gemspec")
+ end
+
it "runs rake without problems" do
- bundle! "gem #{gem_name}"
+ bundle "gem #{gem_name}"
- system_gems ["rake-12.3.2"]
+ system_gems ["rake-13.0.1"]
rakefile = strip_whitespace <<-RAKEFILE
task :default do
@@ -327,10 +613,8 @@ RSpec.describe "bundle gem" do
file.puts rakefile
end
- Dir.chdir(bundled_app(gem_name)) do
- sys_exec(rake)
- expect(out).to include("SUCCESS")
- end
+ sys_exec(rake, :dir => bundled_app(gem_name))
+ expect(out).to include("SUCCESS")
end
context "--exe parameter set" do
@@ -366,13 +650,7 @@ RSpec.describe "bundle gem" do
bundle "gem #{gem_name}"
end
- it "doesn't create any spec/test file" do
- expect(bundled_app("#{gem_name}/.rspec")).to_not exist
- expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb")).to_not exist
- expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to_not exist
- expect(bundled_app("#{gem_name}/test/#{require_path}.rb")).to_not exist
- expect(bundled_app("#{gem_name}/test/minitest_helper.rb")).to_not exist
- end
+ it_behaves_like "test framework is absent"
end
context "--test parameter set to rspec" do
@@ -387,13 +665,12 @@ RSpec.describe "bundle gem" do
end
it "depends on a specific version of rspec in generated Gemfile" do
- Dir.chdir(bundled_app(gem_name)) do
- builder = Bundler::Dsl.new
- builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
- builder.dependencies
- rspec_dep = builder.dependencies.find {|d| d.name == "rspec" }
- expect(rspec_dep).to be_specific
- end
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ rspec_dep = builder.dependencies.find {|d| d.name == "rspec" }
+ expect(rspec_dep).to be_specific
end
it "requires the main file" do
@@ -436,13 +713,12 @@ RSpec.describe "bundle gem" do
end
it "depends on a specific version of minitest" do
- Dir.chdir(bundled_app(gem_name)) do
- builder = Bundler::Dsl.new
- builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
- builder.dependencies
- minitest_dep = builder.dependencies.find {|d| d.name == "minitest" }
- expect(minitest_dep).to be_specific
- end
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ minitest_dep = builder.dependencies.find {|d| d.name == "minitest" }
+ expect(minitest_dep).to be_specific
end
it "builds spec skeleton" do
@@ -454,7 +730,7 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}"))
end
- it "requires 'minitest_helper'" do
+ it "requires 'test_helper'" do
expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include(%(require "test_helper"))
end
@@ -471,6 +747,8 @@ RSpec.describe "bundle gem" do
it "creates a default rake task to run the test suite" do
rakefile = strip_whitespace <<-RAKEFILE
+ # frozen_string_literal: true
+
require "bundler/gem_tasks"
require "rake/testtask"
@@ -480,81 +758,552 @@ RSpec.describe "bundle gem" do
t.test_files = FileList["test/**/*_test.rb"]
end
- task :default => :test
+ task default: :test
RAKEFILE
expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
end
end
- context "--test with no arguments" do
+ context "--test parameter set to test-unit" do
before do
+ bundle "gem #{gem_name} --test=test-unit"
+ end
+
+ it "depends on a specific version of test-unit" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ builder = Bundler::Dsl.new
+ builder.eval_gemfile(bundled_app("#{gem_name}/Gemfile"))
+ builder.dependencies
+ test_unit_dep = builder.dependencies.find {|d| d.name == "test-unit" }
+ expect(test_unit_dep).to be_specific
+ end
+
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ end
+
+ it "requires the main file" do
+ expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}"))
+ end
+
+ it "requires 'test_helper'" do
+ expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include(%(require "test_helper"))
+ end
+
+ it "creates a default test which fails" do
+ expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include("assert_equal(\"expected\", \"actual\")")
+ end
+ end
+
+ context "gem.test setting set to test-unit" do
+ before do
+ bundle "config set gem.test test-unit"
+ bundle "gem #{gem_name}"
+ end
+
+ it "creates a default rake task to run the test suite" do
+ rakefile = strip_whitespace <<-RAKEFILE
+ # frozen_string_literal: true
+
+ require "bundler/gem_tasks"
+ require "rake/testtask"
+
+ Rake::TestTask.new(:test) do |t|
+ t.libs << "test"
+ t.libs << "lib"
+ t.test_files = FileList["test/**/*_test.rb"]
+ end
+
+ task default: :test
+ RAKEFILE
+
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
+ end
+ end
+
+ context "gem.test set to rspec and --test with no arguments", :hint_text do
+ before do
+ bundle "config set gem.test rspec"
bundle "gem #{gem_name} --test"
end
- it "defaults to rspec" do
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/.rspec")).to exist
+ expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb")).to exist
expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist
- expect(bundled_app("#{gem_name}/test/minitest_helper.rb")).to_not exist
end
- it "creates a .travis.yml file to test the library against the current Ruby version on Travis CI" do
- expect(bundled_app("#{gem_name}/.travis.yml").read).to match(/- #{RUBY_VERSION}/)
+ it "hints that --test is already configured" do
+ expect(out).to match("rspec is already configured, ignoring --test flag.")
+ end
+ end
+
+ context "gem.test setting set to false and --test with no arguments", :hint_text do
+ before do
+ bundle "config set gem.test false"
+ bundle "gem #{gem_name} --test"
+ end
+
+ it "asks to generate test files" do
+ expect(out).to match("Do you want to generate tests with your gem?")
+ end
+
+ it "hints that the choice will only be applied to the current gem" do
+ expect(out).to match("Your choice will only be applied to this gem.")
+ end
+
+ it_behaves_like "test framework is absent"
+ end
+
+ context "gem.test setting not set and --test with no arguments", :hint_text do
+ before do
+ bundle "gem #{gem_name} --test"
+ end
+
+ it "asks to generate test files" do
+ expect(out).to match("Do you want to generate tests with your gem?")
+ end
+
+ it "hints that the choice will be applied to future bundle gem calls" do
+ hint = "Future `bundle gem` calls will use your choice. " \
+ "This setting can be changed anytime with `bundle config gem.test`."
+ expect(out).to match(hint)
+ end
+
+ it_behaves_like "test framework is absent"
+ end
+
+ context "--ci with no argument" do
+ it "does not generate any CI config" do
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
+ end
+ end
+
+ context "--ci set to github" do
+ it "generates a GitHub Actions config file" do
+ bundle "gem #{gem_name} --ci=github"
+
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ end
+ end
+
+ context "--ci set to gitlab" do
+ it "generates a GitLab CI config file" do
+ bundle "gem #{gem_name} --ci=gitlab"
+
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
+ end
+ end
+
+ context "--ci set to circle" do
+ it "generates a CircleCI config file" do
+ bundle "gem #{gem_name} --ci=circle"
+
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
+ end
+ end
+
+ context "--ci set to travis" do
+ it "generates a Travis CI config file" do
+ bundle "gem #{gem_name} --ci=travis"
+
+ expect(bundled_app("#{gem_name}/.travis.yml")).to exist
+ end
+ end
+
+ context "gem.ci setting set to none" do
+ it "doesn't generate any CI config" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.travis.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
+ end
+ end
+
+ context "gem.ci setting set to github" do
+ it "generates a GitHub Actions config file" do
+ bundle "config set gem.ci github"
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ end
+ end
+
+ context "gem.ci setting set to travis" do
+ it "generates a Travis CI config file" do
+ bundle "config set gem.ci travis"
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.travis.yml")).to exist
+ end
+ end
+
+ context "gem.ci setting set to gitlab" do
+ it "generates a GitLab CI config file" do
+ bundle "config set gem.ci gitlab"
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
+ end
+ end
+
+ context "gem.ci setting set to circle" do
+ it "generates a CircleCI config file" do
+ bundle "config set gem.ci circle"
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
+ end
+ end
+
+ context "gem.ci set to github and --ci with no arguments", :hint_text do
+ before do
+ bundle "config set gem.ci github"
+ bundle "gem #{gem_name} --ci"
+ end
+
+ it "generates a GitHub Actions config file" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ end
+
+ it "hints that --ci is already configured" do
+ expect(out).to match("github is already configured, ignoring --ci flag.")
+ end
+ end
+
+ context "gem.ci setting set to false and --ci with no arguments", :hint_text do
+ before do
+ bundle "config set gem.ci false"
+ bundle "gem #{gem_name} --ci"
+ end
+
+ it "asks to setup CI" do
+ expect(out).to match("Do you want to set up continuous integration for your gem?")
+ end
+
+ it "hints that the choice will only be applied to the current gem" do
+ expect(out).to match("Your choice will only be applied to this gem.")
+ end
+ end
+
+ context "gem.ci setting not set and --ci with no arguments", :hint_text do
+ before do
+ bundle "gem #{gem_name} --ci"
+ end
+
+ it "asks to setup CI" do
+ expect(out).to match("Do you want to set up continuous integration for your gem?")
+ end
+
+ it "hints that the choice will be applied to future bundle gem calls" do
+ hint = "Future `bundle gem` calls will use your choice. " \
+ "This setting can be changed anytime with `bundle config gem.ci`."
+ expect(out).to match(hint)
+ end
+ end
+
+ context "--linter with no argument" do
+ it "does not generate any linter config" do
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
+ end
+
+ context "--linter set to rubocop" do
+ it "generates a RuboCop config" do
+ bundle "gem #{gem_name} --linter=rubocop"
+
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
+ end
+
+ context "--linter set to standard" do
+ it "generates a Standard config" do
+ bundle "gem #{gem_name} --linter=standard"
+
+ expect(bundled_app("#{gem_name}/.standard.yml")).to exist
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ end
+ end
+
+ context "gem.linter setting set to none" do
+ it "doesn't generate any linter config" do
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
+ end
+
+ context "gem.linter setting set to rubocop" do
+ it "generates a RuboCop config file" do
+ bundle "config set gem.linter rubocop"
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ end
+ end
+
+ context "gem.linter setting set to standard" do
+ it "generates a Standard config file" do
+ bundle "config set gem.linter standard"
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/.standard.yml")).to exist
+ end
+ end
+
+ context "gem.rubocop setting set to true", :bundler => "< 3" do
+ before do
+ bundle "config set gem.rubocop true"
+ bundle "gem #{gem_name}"
+ end
+
+ it "generates rubocop config" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ end
+
+ it "unsets gem.rubocop" do
+ bundle "config gem.rubocop"
+ expect(out).to include("You have not configured a value for `gem.rubocop`")
+ end
+
+ it "sets gem.linter=rubocop instead" do
+ bundle "config gem.linter"
+ expect(out).to match(/Set for the current user .*: "rubocop"/)
+ end
+ end
+
+ context "gem.linter set to rubocop and --linter with no arguments", :hint_text do
+ before do
+ bundle "config set gem.linter rubocop"
+ bundle "gem #{gem_name} --linter"
+ end
+
+ it "generates a RuboCop config file" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ end
+
+ it "hints that --linter is already configured" do
+ expect(out).to match("rubocop is already configured, ignoring --linter flag.")
+ end
+ end
+
+ context "gem.linter setting set to false and --linter with no arguments", :hint_text do
+ before do
+ bundle "config set gem.linter false"
+ bundle "gem #{gem_name} --linter"
+ end
+
+ it "asks to setup a linter" do
+ expect(out).to match("Do you want to add a code linter and formatter to your gem?")
+ end
+
+ it "hints that the choice will only be applied to the current gem" do
+ expect(out).to match("Your choice will only be applied to this gem.")
+ end
+ end
+
+ context "gem.linter setting not set and --linter with no arguments", :hint_text do
+ before do
+ bundle "gem #{gem_name} --linter"
+ end
+
+ it "asks to setup a linter" do
+ expect(out).to match("Do you want to add a code linter and formatter to your gem?")
+ end
+
+ it "hints that the choice will be applied to future bundle gem calls" do
+ hint = "Future `bundle gem` calls will use your choice. " \
+ "This setting can be changed anytime with `bundle config gem.linter`."
+ expect(out).to match(hint)
end
end
context "--edit option" do
it "opens the generated gemspec in the user's text editor" do
output = bundle "gem #{gem_name} --edit=echo"
- gemspec_path = File.join(Dir.pwd, gem_name, "#{gem_name}.gemspec")
+ gemspec_path = File.join(bundled_app, gem_name, "#{gem_name}.gemspec")
expect(output).to include("echo \"#{gemspec_path}\"")
end
end
end
- context "testing --mit and --coc options against bundle config settings" do
+ context "testing --mit and --coc options against bundle config settings", :readline do
let(:gem_name) { "test-gem" }
let(:require_path) { "test/gem" }
context "with mit option in bundle config settings set to true" do
before do
- global_config "BUNDLE_GEM__MIT" => "true", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
+ global_config "BUNDLE_GEM__MIT" => "true"
end
it_behaves_like "--mit flag"
it_behaves_like "--no-mit flag"
end
context "with mit option in bundle config settings set to false" do
+ before do
+ global_config "BUNDLE_GEM__MIT" => "false"
+ end
it_behaves_like "--mit flag"
it_behaves_like "--no-mit flag"
end
context "with coc option in bundle config settings set to true" do
before do
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "true"
+ global_config "BUNDLE_GEM__COC" => "true"
end
it_behaves_like "--coc flag"
it_behaves_like "--no-coc flag"
end
context "with coc option in bundle config settings set to false" do
+ before do
+ global_config "BUNDLE_GEM__COC" => "false"
+ end
it_behaves_like "--coc flag"
it_behaves_like "--no-coc flag"
end
+
+ context "with rubocop option in bundle config settings set to true" do
+ before do
+ global_config "BUNDLE_GEM__RUBOCOP" => "true"
+ end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--linter=none flag"
+ it_behaves_like "--rubocop flag"
+ it_behaves_like "--no-rubocop flag"
+ end
+
+ context "with rubocop option in bundle config settings set to false" do
+ before do
+ global_config "BUNDLE_GEM__RUBOCOP" => "false"
+ end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--linter=none flag"
+ it_behaves_like "--rubocop flag"
+ it_behaves_like "--no-rubocop flag"
+ end
+
+ context "with linter option in bundle config settings set to rubocop" do
+ before do
+ global_config "BUNDLE_GEM__LINTER" => "rubocop"
+ end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--linter=none flag"
+ end
+
+ context "with linter option in bundle config settings set to standard" do
+ before do
+ global_config "BUNDLE_GEM__LINTER" => "standard"
+ end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--linter=none flag"
+ end
+
+ context "with linter option in bundle config settings set to false" do
+ before do
+ global_config "BUNDLE_GEM__LINTER" => "false"
+ end
+ it_behaves_like "--linter=rubocop flag"
+ it_behaves_like "--linter=standard flag"
+ it_behaves_like "--linter=none flag"
+ end
+
+ context "with changelog option in bundle config settings set to true" do
+ before do
+ global_config "BUNDLE_GEM__CHANGELOG" => "true"
+ end
+ it_behaves_like "--changelog flag"
+ it_behaves_like "--no-changelog flag"
+ end
+
+ context "with changelog option in bundle config settings set to false" do
+ before do
+ global_config "BUNDLE_GEM__CHANGELOG" => "false"
+ end
+ it_behaves_like "--changelog flag"
+ it_behaves_like "--no-changelog flag"
+ end
+ end
+
+ context "testing --github-username option against git and bundle config settings", :readline do
+ context "without git config set" do
+ before do
+ sys_exec("git config --global --unset github.user")
+ end
+ context "with github-username option in bundle config settings set to some value" do
+ before do
+ global_config "BUNDLE_GEM__GITHUB_USERNAME" => "different_username"
+ end
+ it_behaves_like "--github-username option", "gh_user"
+ end
+
+ context "with github-username option in bundle config settings set to false" do
+ before do
+ global_config "BUNDLE_GEM__GITHUB_USERNAME" => "false"
+ end
+ it_behaves_like "--github-username option", "gh_user"
+ end
+ end
+
+ context "with git config set" do
+ context "with github-username option in bundle config settings set to some value" do
+ before do
+ global_config "BUNDLE_GEM__GITHUB_USERNAME" => "different_username"
+ end
+ it_behaves_like "--github-username option", "gh_user"
+ end
+
+ context "with github-username option in bundle config settings set to false" do
+ before do
+ global_config "BUNDLE_GEM__GITHUB_USERNAME" => "false"
+ end
+ it_behaves_like "--github-username option", "gh_user"
+ end
+ end
+ end
+
+ context "testing github_username bundle config against git config settings", :readline do
+ context "without git config set" do
+ before do
+ sys_exec("git config --global --unset github.user")
+ end
+
+ it_behaves_like "github_username configuration"
+ end
+
+ context "with git config set" do
+ it_behaves_like "github_username configuration"
+ end
end
- context "gem naming with underscore" do
+ context "gem naming with underscore", :readline do
let(:gem_name) { "test_gem" }
let(:require_path) { "test_gem" }
- let(:flags) { nil }
+ let(:require_relative_path) { "test_gem" }
- before do
- bundle! ["gem", gem_name, flags].compact.join(" ")
- end
+ let(:flags) { nil }
it "does not nest constants" do
+ bundle ["gem", gem_name, flags].compact.join(" ")
expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/module TestGem/)
expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/module TestGem/)
end
@@ -564,6 +1313,10 @@ RSpec.describe "bundle gem" do
context "--ext parameter set" do
let(:flags) { "--ext" }
+ before do
+ bundle ["gem", gem_name, flags].compact.join(" ")
+ end
+
it "builds ext skeleton" do
expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb")).to exist
expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.h")).to exist
@@ -576,16 +1329,18 @@ RSpec.describe "bundle gem" do
it "depends on compile task for build" do
rakefile = strip_whitespace <<-RAKEFILE
+ # frozen_string_literal: true
+
require "bundler/gem_tasks"
require "rake/extensiontask"
- task :build => :compile
+ task build: :compile
Rake::ExtensionTask.new("#{gem_name}") do |ext|
ext.lib_dir = "lib/#{gem_name}"
end
- task :default => [:clobber, :compile, :spec]
+ task default: %i[clobber compile]
RAKEFILE
expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
@@ -593,16 +1348,15 @@ RSpec.describe "bundle gem" do
end
end
- context "gem naming with dashed" do
+ context "gem naming with dashed", :readline do
let(:gem_name) { "test-gem" }
let(:require_path) { "test/gem" }
- before do
- bundle! "gem #{gem_name}"
- end
+ let(:require_relative_path) { "gem" }
it "nests constants so they work" do
+ bundle "gem #{gem_name}"
expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/module Test\n module Gem/)
expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/module Test\n module Gem/)
end
@@ -611,29 +1365,29 @@ RSpec.describe "bundle gem" do
end
describe "uncommon gem names" do
- it "can deal with two dashes" do
- bundle! "gem a--a"
+ it "can deal with two dashes", :readline do
+ bundle "gem a--a"
expect(bundled_app("a--a/a--a.gemspec")).to exist
end
it "fails gracefully with a ." do
- bundle "gem foo.gemspec"
+ bundle "gem foo.gemspec", :raise_on_error => false
expect(err).to end_with("Invalid gem name foo.gemspec -- `Foo.gemspec` is an invalid constant name")
end
it "fails gracefully with a ^" do
- bundle "gem ^"
+ bundle "gem ^", :raise_on_error => false
expect(err).to end_with("Invalid gem name ^ -- `^` is an invalid constant name")
end
it "fails gracefully with a space" do
- bundle "gem 'foo bar'"
+ bundle "gem 'foo bar'", :raise_on_error => false
expect(err).to end_with("Invalid gem name foo bar -- `Foo bar` is an invalid constant name")
end
it "fails gracefully when multiple names are passed" do
- bundle "gem foo bar baz"
+ bundle "gem foo bar baz", :raise_on_error => false
expect(err).to eq(<<-E.strip)
ERROR: "bundle gem" was called with arguments ["foo", "bar", "baz"]
Usage: "bundle gem NAME [OPTIONS]"
@@ -641,9 +1395,9 @@ Usage: "bundle gem NAME [OPTIONS]"
end
end
- describe "#ensure_safe_gem_name" do
+ describe "#ensure_safe_gem_name", :readline do
before do
- bundle "gem #{subject}"
+ bundle "gem #{subject}", :raise_on_error => false
end
context "with an existing const name" do
@@ -667,7 +1421,7 @@ Usage: "bundle gem NAME [OPTIONS]"
end
end
- context "on first run" do
+ context "on first run", :readline do
it "asks about test framework" do
global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__COC" => "false"
@@ -677,20 +1431,32 @@ Usage: "bundle gem NAME [OPTIONS]"
expect(bundled_app("foobar/spec/spec_helper.rb")).to exist
rakefile = strip_whitespace <<-RAKEFILE
+ # frozen_string_literal: true
+
require "bundler/gem_tasks"
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
- task :default => :spec
+ task default: :spec
RAKEFILE
expect(bundled_app("foobar/Rakefile").read).to eq(rakefile)
expect(bundled_app("foobar/Gemfile").read).to include('gem "rspec"')
end
+ it "asks about CI service" do
+ global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__LINTER" => "false"
+
+ bundle "gem foobar" do |input, _, _|
+ input.puts "github"
+ end
+
+ expect(bundled_app("foobar/.github/workflows/main.yml")).to exist
+ end
+
it "asks about MIT license" do
- global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false"
+ global_config "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__LINTER" => "false"
bundle "config list"
@@ -702,7 +1468,7 @@ Usage: "bundle gem NAME [OPTIONS]"
end
it "asks about CoC" do
- global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false"
+ global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__LINTER" => "false"
bundle "gem foobar" do |input, _, _|
input.puts "yes"
@@ -710,21 +1476,32 @@ Usage: "bundle gem NAME [OPTIONS]"
expect(bundled_app("foobar/CODE_OF_CONDUCT.md")).to exist
end
+
+ it "asks about CHANGELOG" do
+ global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__LINTER" => "false",
+ "BUNDLE_GEM__COC" => "false"
+
+ bundle "gem foobar" do |input, _, _|
+ input.puts "yes"
+ end
+
+ expect(bundled_app("foobar/CHANGELOG.md")).to exist
+ end
end
- context "on conflicts with a previously created file" do
+ context "on conflicts with a previously created file", :readline do
it "should fail gracefully" do
- FileUtils.touch("conflict-foobar")
- bundle "gem conflict-foobar"
- expect(err).to include("Errno::ENOTDIR")
- expect(exitstatus).to eql(32) if exitstatus
+ FileUtils.touch(bundled_app("conflict-foobar"))
+ bundle "gem conflict-foobar", :raise_on_error => false
+ expect(err).to eq("Couldn't create a new gem named `conflict-foobar` because there's an existing file named `conflict-foobar`.")
+ expect(exitstatus).to eql(32)
end
end
- context "on conflicts with a previously created directory" do
+ context "on conflicts with a previously created directory", :readline do
it "should succeed" do
- FileUtils.mkdir_p("conflict-foobar/Gemfile")
- bundle! "gem conflict-foobar"
+ FileUtils.mkdir_p(bundled_app("conflict-foobar/Gemfile"))
+ bundle "gem conflict-foobar"
expect(out).to include("file_clash conflict-foobar/Gemfile").
and include "Initializing git repo in #{bundled_app("conflict-foobar")}"
end
diff --git a/spec/bundler/commands/open_spec.rb b/spec/bundler/commands/open_spec.rb
index 8fae4af5b4..53dc35c2c7 100644
--- a/spec/bundler/commands/open_spec.rb
+++ b/spec/bundler/commands/open_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe "bundle open" do
end
it "complains if gem not in bundle" do
- bundle "open missing", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ bundle "open missing", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, :raise_on_error => false
expect(err).to match(/could not find gem 'missing'/i)
end
@@ -48,7 +48,7 @@ RSpec.describe "bundle open" do
end
it "suggests alternatives for similar-sounding gems" do
- bundle "open Rails", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ bundle "open Rails", :env => { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, :raise_on_error => false
expect(err).to match(/did you mean rails\?/i)
end
@@ -58,7 +58,7 @@ RSpec.describe "bundle open" do
expect(out).to include("bundler_editor #{default_bundle_path("gems", "activerecord-2.3.2")}")
end
- it "select the gem from many match gems" do
+ it "select the gem from many match gems", :readline do
env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
bundle "open active", :env => env do |input, _, _|
input.puts "2"
@@ -67,9 +67,9 @@ RSpec.describe "bundle open" do
expect(out).to match(/bundler_editor #{default_bundle_path('gems', 'activerecord-2.3.2')}\z/)
end
- it "allows selecting exit from many match gems" do
+ it "allows selecting exit from many match gems", :readline do
env = { "EDITOR" => "echo editor", "VISUAL" => "echo visual", "BUNDLER_EDITOR" => "echo bundler_editor" }
- bundle! "open active", :env => env do |input, _, _|
+ bundle "open active", :env => env do |input, _, _|
input.puts "0"
end
end
@@ -87,14 +87,14 @@ RSpec.describe "bundle open" do
end
it "opens the editor with a clean env" do
- bundle "open", :env => { "EDITOR" => "sh -c 'env'", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
+ bundle "open", :env => { "EDITOR" => "sh -c 'env'", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, :raise_on_error => false
expect(out).not_to include("BUNDLE_GEMFILE=")
end
end
context "when opening a default gem" do
let(:default_gems) do
- ruby!(<<-RUBY).split("\n")
+ ruby(<<-RUBY).split("\n")
if Gem::Specification.is_a?(Enumerable)
puts Gem::Specification.select(&:default_gem?).map(&:name)
end
@@ -105,6 +105,7 @@ 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)}"
gem "json"
G
end
diff --git a/spec/bundler/commands/outdated_spec.rb b/spec/bundler/commands/outdated_spec.rb
index df911eaffd..731d67af1b 100644
--- a/spec/bundler/commands/outdated_spec.rb
+++ b/spec/bundler/commands/outdated_spec.rb
@@ -1,24 +1,24 @@
# frozen_string_literal: true
RSpec.describe "bundle outdated" do
- before :each do
- build_repo2 do
- build_git "foo", :path => lib_path("foo")
- build_git "zebra", :path => lib_path("zebra")
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "zebra", :git => "#{lib_path("zebra")}"
- gem "foo", :git => "#{lib_path("foo")}"
- gem "activesupport", "2.3.5"
- gem "weakling", "~> 0.0.1"
- gem "duradura", '7.0'
- gem "terranova", '8'
- G
- end
-
describe "with no arguments" do
+ before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
it "returns a sorted list of outdated gems" do
update_repo2 do
build_gem "activesupport", "3.0"
@@ -27,15 +27,37 @@ RSpec.describe "bundle outdated" do
update_git "zebra", :path => lib_path("zebra")
end
- bundle "outdated"
+ bundle "outdated", :raise_on_error => false
+
+ expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip
+ Gem Current Latest Requested Groups
+ activesupport 2.3.5 3.0 = 2.3.5 default
+ foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ weakling 0.0.3 0.2 ~> 0.0.1 default
+ zebra 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ TABLE
+
+ expect(out).to match(Regexp.new(expected_output))
+ end
+
+ it "excludes header row from the sorting" do
+ update_repo2 do
+ build_gem "AAA", %w[1.0.0 2.0.0]
+ end
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)")
- expect(out).to include("weakling (newest 0.2, installed 0.0.3, requested ~> 0.0.1)")
- expect(out).to include("foo (newest 1.0")
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "AAA", "1.0.0"
+ G
+
+ bundle "outdated", :raise_on_error => false
+
+ expected_output = <<~TABLE
+ Gem Current Latest Requested Groups
+ AAA 1.0.0 2.0.0 = 1.0.0 default
+ TABLE
- # Gem names are one per-line, between "*" and their parenthesized version.
- gem_list = out.split("\n").map {|g| g[/\* (.*) \(/, 1] }.compact
- expect(gem_list).to eq(gem_list.sort)
+ expect(out).to include(expected_output.strip)
end
it "returns non zero exit status if outdated gems present" do
@@ -44,15 +66,13 @@ RSpec.describe "bundle outdated" do
update_git "foo", :path => lib_path("foo")
end
- bundle "outdated"
+ bundle "outdated", :raise_on_error => false
- expect(exitstatus).to_not be_zero if exitstatus
+ expect(exitstatus).to_not be_zero
end
it "returns success exit status if no outdated gems present" do
bundle "outdated"
-
- expect(exitstatus).to be_zero if exitstatus
end
it "adds gem group to dependency output when repo is updated" do
@@ -69,14 +89,141 @@ RSpec.describe "bundle outdated" do
update_repo2 { build_gem "activesupport", "3.0" }
update_repo2 { build_gem "terranova", "9" }
- bundle "outdated --verbose"
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5) in groups \"development, test\"")
- expect(out).to include("terranova (newest 9, installed 8, requested = 8) in group \"default\"")
+ bundle "outdated", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ activesupport 2.3.5 3.0 = 2.3.5 development, test
+ terranova 8 9 = 8 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+ end
+
+ describe "with --verbose option" do
+ before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
+ it "shows the location of the latest version's gemspec if installed" do
+ bundle "config set clean false"
+
+ update_repo2 { build_gem "activesupport", "3.0" }
+ update_repo2 { build_gem "terranova", "9" }
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "terranova", '9'
+ gem 'activesupport', '2.3.5'
+ G
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "terranova", '8'
+ gem 'activesupport', '2.3.5'
+ G
+
+ bundle "outdated --verbose", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups Path
+ activesupport 2.3.5 3.0 = 2.3.5 default
+ terranova 8 9 = 8 default #{default_bundle_path("specifications/terranova-9.gemspec")}
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+ end
+
+ describe "with multiple, duplicated sources, with lockfile in old format", :bundler => "< 3" do
+ before do
+ build_repo2 do
+ build_gem "dotenv", "2.7.6"
+
+ build_gem "oj", "3.11.3"
+ build_gem "oj", "3.11.5"
+
+ build_gem "vcr", "6.0.0"
+ end
+
+ build_repo gem_repo3 do
+ build_gem "pkg-gem-flowbyte-with-dep", "1.0.0" do |s|
+ s.add_dependency "oj"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "dotenv"
+
+ source "https://gem.repo3" do
+ gem 'pkg-gem-flowbyte-with-dep'
+ end
+
+ gem "vcr",source: "https://gem.repo2"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ remote: https://gem.repo3/
+ specs:
+ dotenv (2.7.6)
+ oj (3.11.3)
+ pkg-gem-flowbyte-with-dep (1.0.0)
+ oj
+ vcr (6.0.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ dotenv
+ pkg-gem-flowbyte-with-dep!
+ vcr!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "works" do
+ bundle :install, :artifice => "compact_index"
+ bundle :outdated, :artifice => "compact_index", :raise_on_error => false
+
+ expected_output = <<~TABLE
+ Gem Current Latest Requested Groups
+ oj 3.11.3 3.11.5
+ TABLE
+
+ expect(out).to include(expected_output.strip)
end
end
describe "with --group option" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -89,62 +236,100 @@ RSpec.describe "bundle outdated" do
G
end
- def test_group_option(group = nil, gems_list_size = 1)
+ def test_group_option(group)
update_repo2 do
build_gem "activesupport", "3.0"
build_gem "terranova", "9"
build_gem "duradura", "8.0"
end
- bundle "outdated --group #{group}"
-
- # Gem names are one per-line, between "*" and their parenthesized version.
- gem_list = out.split("\n").map {|g| g[/\* (.*) \(/, 1] }.compact
- expect(gem_list).to eq(gem_list.sort)
- expect(gem_list.size).to eq gems_list_size
+ bundle "outdated --group #{group}", :raise_on_error => false
end
- it "not outdated gems" do
+ it "works when the bundle is up to date" do
bundle "outdated --group"
- expect(out).to include("Bundle up to date!")
+ expect(out).to end_with("Bundle up to date!")
end
it "returns a sorted list of outdated gems from one group => 'default'" do
test_group_option("default")
- expect(out).to include("===== Group \"default\" =====")
- expect(out).to include("terranova (")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ terranova 8 9 = 8 default
+ TABLE
- expect(out).not_to include("===== Groups \"development, test\" =====")
- expect(out).not_to include("activesupport")
- expect(out).not_to include("duradura")
+ expect(out).to end_with(expected_output)
end
it "returns a sorted list of outdated gems from one group => 'development'" do
- test_group_option("development", 2)
+ test_group_option("development")
- expect(out).not_to include("===== Group \"default\" =====")
- expect(out).not_to include("terranova (")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ activesupport 2.3.5 3.0 = 2.3.5 development, test
+ duradura 7.0 8.0 = 7.0 development, test
+ TABLE
- expect(out).to include("===== Groups \"development, test\" =====")
- expect(out).to include("activesupport")
- expect(out).to include("duradura")
+ expect(out).to end_with(expected_output)
end
it "returns a sorted list of outdated gems from one group => 'test'" do
- test_group_option("test", 2)
+ test_group_option("test")
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ activesupport 2.3.5 3.0 = 2.3.5 development, test
+ duradura 7.0 8.0 = 7.0 development, test
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+ end
+
+ describe "with --groups option and outdated transitive dependencies" do
+ before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+
+ build_gem "bar", %w[2.0.0]
+
+ build_gem "bar_dependant", "7.0" do |s|
+ s.add_dependency "bar", "~> 2.0"
+ end
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "bar_dependant", '7.0'
+ G
+
+ update_repo2 do
+ build_gem "bar", %w[3.0.0]
+ end
+ end
+
+ it "returns a sorted list of outdated gems" do
+ bundle "outdated --groups", :raise_on_error => false
- expect(out).not_to include("===== Group \"default\" =====")
- expect(out).not_to include("terranova (")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ bar 2.0.0 3.0.0
+ TABLE
- expect(out).to include("===== Groups \"development, test\" =====")
- expect(out).to include("activesupport")
- expect(out).to include("duradura")
+ expect(out).to end_with(expected_output)
end
end
describe "with --groups option" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -159,7 +344,7 @@ RSpec.describe "bundle outdated" do
it "not outdated gems" do
bundle "outdated --groups"
- expect(out).to include("Bundle up to date!")
+ expect(out).to end_with("Bundle up to date!")
end
it "returns a sorted list of outdated gems by groups" do
@@ -169,35 +354,58 @@ RSpec.describe "bundle outdated" do
build_gem "duradura", "8.0"
end
- bundle "outdated --groups"
- expect(out).to include("===== Group \"default\" =====")
- expect(out).to include("terranova (newest 9, installed 8, requested = 8)")
- expect(out).to include("===== Groups \"development, test\" =====")
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)")
- expect(out).to include("duradura (newest 8.0, installed 7.0, requested = 7.0)")
+ bundle "outdated --groups", :raise_on_error => false
- expect(out).not_to include("weakling (")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ activesupport 2.3.5 3.0 = 2.3.5 development, test
+ duradura 7.0 8.0 = 7.0 development, test
+ terranova 8 9 = 8 default
+ TABLE
- # TODO: check gems order inside the group
+ expect(out).to end_with(expected_output)
end
end
describe "with --local option" do
+ before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "weakling", "~> 0.0.1"
+ gem "terranova", '8'
+ group :development, :test do
+ gem 'activesupport', '2.3.5'
+ gem "duradura", '7.0'
+ end
+ G
+ end
+
it "uses local cache to return a list of outdated gems" do
update_repo2 do
build_gem "activesupport", "2.3.4"
end
- bundle! "config set clean false"
+ bundle "config set clean false"
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport", "2.3.4"
G
- bundle "outdated --local"
+ bundle "outdated --local", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ activesupport 2.3.4 2.3.5 = 2.3.4 default
+ TABLE
- expect(out).to include("activesupport (newest 2.3.5, installed 2.3.4, requested = 2.3.4)")
+ expect(out).to end_with(expected_output)
end
it "doesn't hit repo2" do
@@ -211,10 +419,23 @@ RSpec.describe "bundle outdated" do
shared_examples_for "a minimal output is desired" do
context "and gems are outdated" do
before do
- update_repo2 do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+
build_gem "activesupport", "3.0"
build_gem "weakling", "0.2"
end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
end
it "outputs a sorted list of outdated gems with a more minimal format" do
@@ -234,31 +455,68 @@ RSpec.describe "bundle outdated" do
end
describe "with --parseable option" do
- subject { bundle "outdated --parseable" }
+ subject { bundle "outdated --parseable", :raise_on_error => false }
it_behaves_like "a minimal output is desired"
end
describe "with aliased --porcelain option" do
- subject { bundle "outdated --porcelain" }
+ subject { bundle "outdated --porcelain", :raise_on_error => false }
it_behaves_like "a minimal output is desired"
end
describe "with specified gems" do
it "returns list of outdated gems" do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "3.0"
update_git "foo", :path => lib_path("foo")
end
- bundle "outdated foo"
- expect(out).not_to include("activesupport (newest")
- expect(out).to include("foo (newest 1.0")
+ bundle "outdated foo", :raise_on_error => false
+
+ expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip
+ Gem Current Latest Requested Groups
+ foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ TABLE
+
+ expect(out).to match(Regexp.new(expected_output))
end
end
describe "pre-release gems" do
+ before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
context "without the --pre option" do
it "ignores pre-release versions" do
update_repo2 do
@@ -266,7 +524,8 @@ RSpec.describe "bundle outdated" do
end
bundle "outdated"
- expect(out).not_to include("activesupport (3.0.0.beta > 2.3.5)")
+
+ expect(out).to end_with("Bundle up to date!")
end
end
@@ -276,8 +535,14 @@ RSpec.describe "bundle outdated" do
build_gem "activesupport", "3.0.0.beta"
end
- bundle "outdated --pre"
- expect(out).to include("activesupport (newest 3.0.0.beta, installed 2.3.5, requested = 2.3.5)")
+ bundle "outdated --pre", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ activesupport 2.3.5 3.0.0.beta = 2.3.5 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
end
@@ -293,24 +558,62 @@ RSpec.describe "bundle outdated" do
gem "activesupport", "3.0.0.beta.1"
G
- bundle "outdated"
- expect(out).to include("(newest 3.0.0.beta.2, installed 3.0.0.beta.1, requested = 3.0.0.beta.1)")
+ bundle "outdated", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ activesupport 3.0.0.beta.1 3.0.0.beta.2 = 3.0.0.beta.1 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
end
end
filter_strict_option = Bundler.feature_flag.bundler_2_mode? ? :"filter-strict" : :strict
describe "with --#{filter_strict_option} option" do
+ before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
it "only reports gems that have a newer version that matches the specified dependency version requirements" do
update_repo2 do
build_gem "activesupport", "3.0"
build_gem "weakling", "0.0.5"
end
+ bundle :outdated, filter_strict_option => true, :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ weakling 0.0.3 0.0.5 ~> 0.0.1 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+
+ it "doesn't crash when some deps unused on the current platform" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport", platforms: [:ruby_22]
+ G
+
bundle :outdated, filter_strict_option => true
- expect(out).to_not include("activesupport (newest")
- expect(out).to include("(newest 0.0.5, installed 0.0.3, requested ~> 0.0.1)")
+ expect(out).to end_with("Bundle up to date!")
end
it "only reports gem dependencies when they can actually be updated" do
@@ -321,7 +624,7 @@ RSpec.describe "bundle outdated" do
bundle :outdated, filter_strict_option => true
- expect(out).to_not include("rack (1.2")
+ expect(out).to end_with("Bundle up to date!")
end
describe "and filter options" do
@@ -337,10 +640,14 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "0.0.5"
end
- bundle :outdated, filter_strict_option => true, "filter-patch" => true
+ bundle :outdated, filter_strict_option => true, "filter-patch" => true, :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ weakling 0.0.3 0.0.5 >= 0.0.1 default
+ TABLE
- expect(out).to_not include("activesupport (newest")
- expect(out).to include("(newest 0.0.5, installed 0.0.3")
+ expect(out).to end_with(expected_output)
end
it "only reports gems that match requirement and minor filter level" do
@@ -355,10 +662,14 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "0.1.5"
end
- bundle :outdated, filter_strict_option => true, "filter-minor" => true
+ bundle :outdated, filter_strict_option => true, "filter-minor" => true, :raise_on_error => false
- expect(out).to_not include("activesupport (newest")
- expect(out).to include("(newest 0.1.5, installed 0.0.3")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ weakling 0.0.3 0.1.5 >= 0.0.1 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
it "only reports gems that match requirement and major filter level" do
@@ -373,23 +684,44 @@ RSpec.describe "bundle outdated" do
build_gem "weakling", "1.1.5"
end
- bundle :outdated, filter_strict_option => true, "filter-major" => true
+ bundle :outdated, filter_strict_option => true, "filter-major" => true, :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ weakling 0.0.3 1.1.5 >= 0.0.1 default
+ TABLE
- expect(out).to_not include("activesupport (newest")
- expect(out).to include("(newest 1.1.5, installed 0.0.3")
+ expect(out).to end_with(expected_output)
end
end
end
describe "with invalid gem name" do
+ before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+ end
+
it "returns could not find gem name" do
- bundle "outdated invalid_gem_name"
+ bundle "outdated invalid_gem_name", :raise_on_error => false
expect(err).to include("Could not find gem 'invalid_gem_name'.")
end
it "returns non-zero exit code" do
- bundle "outdated invalid_gem_name"
- expect(exitstatus).to_not be_zero if exitstatus
+ bundle "outdated invalid_gem_name", :raise_on_error => false
+ expect(exitstatus).to_not be_zero
end
end
@@ -401,24 +733,28 @@ RSpec.describe "bundle outdated" do
G
bundle "config set auto_install 1"
- bundle :outdated
+ bundle :outdated, :raise_on_error => false
expect(out).to include("Installing foo 1.0")
end
context "after bundle install --deployment", :bundler => "< 3" do
before do
- install_gemfile <<-G, forgotten_command_line_options(:deployment => true)
+ build_repo2
+
+ gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rack"
gem "foo"
G
+ bundle :lock
+ bundle :install, :deployment => true
end
it "outputs a helpful message about being in deployment mode" do
update_repo2 { build_gem "activesupport", "3.0" }
- bundle "outdated"
+ bundle "outdated", :raise_on_error => false
expect(last_command).to be_failure
expect(err).to include("You are trying to check outdated gems in deployment mode.")
expect(err).to include("Run `bundle outdated` elsewhere.")
@@ -427,21 +763,26 @@ RSpec.describe "bundle outdated" do
end
end
- context "after bundle config set deployment true" do
+ context "after bundle config set --local deployment true" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rack"
gem "foo"
G
- bundle! "config set deployment true"
+ bundle "config set --local deployment true"
end
it "outputs a helpful message about being in deployment mode" do
update_repo2 { build_gem "activesupport", "3.0" }
- bundle "outdated"
+ bundle "outdated", :raise_on_error => false
expect(last_command).to be_failure
expect(err).to include("You are trying to check outdated gems in deployment mode.")
expect(err).to include("Run `bundle outdated` elsewhere.")
@@ -452,6 +793,8 @@ RSpec.describe "bundle outdated" do
context "update available for a gem on a different platform" do
before do
+ build_repo2
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "laduradura", '= 5.15.2'
@@ -460,11 +803,15 @@ RSpec.describe "bundle outdated" do
it "reports that no updates are available" do
bundle "outdated"
- expect(out).to include("Bundle up to date!")
+ expect(out).to end_with("Bundle up to date!")
end
end
context "update available for a gem on the same platform while multiple platforms used for gem" do
+ before do
+ build_repo2
+ end
+
it "reports that updates are available if the Ruby platform is used" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -472,36 +819,53 @@ RSpec.describe "bundle outdated" do
G
bundle "outdated"
- expect(out).to include("Bundle up to date!")
+ expect(out).to end_with("Bundle up to date!")
end
- it "reports that updates are available if the JRuby platform is used" do
- simulate_ruby_engine "jruby", "1.6.7" do
- simulate_platform "jruby" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby]
- G
+ it "reports that updates are available if the JRuby platform is used", :jruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby]
+ G
- bundle "outdated"
- expect(out).to include("Outdated gems included in the bundle:")
- expect(out).to include("laduradura (newest 5.15.3, installed 5.15.2, requested = 5.15.2)")
- end
- end
+ bundle "outdated", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ laduradura 5.15.2 5.15.3 = 5.15.2 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
end
shared_examples_for "version update is detected" do
it "reports that a gem has a newer version" do
subject
- expect(out).to include("Outdated gems included in the bundle:")
- expect(out).to include("activesupport (newest")
- expect(out).to_not include("ERROR REPORT TEMPLATE")
+
+ outdated_gems = out.split("\n").drop_while {|l| !l.start_with?("Gem") }[1..-1]
+
+ expect(outdated_gems.size).to be > 0
end
end
shared_examples_for "major version updates are detected" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "3.3.5"
build_gem "weakling", "0.8.0"
@@ -513,6 +877,21 @@ RSpec.describe "bundle outdated" do
context "when on a new machine" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
simulate_new_machine
update_git "foo", :path => lib_path("foo")
@@ -522,12 +901,27 @@ RSpec.describe "bundle outdated" do
end
end
- subject { bundle "outdated" }
+ subject { bundle "outdated", :raise_on_error => false }
it_behaves_like "version update is detected"
end
shared_examples_for "minor version updates are detected" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "2.7.5"
build_gem "weakling", "2.0.1"
@@ -539,6 +933,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "patch version updates are detected" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "2.3.7"
build_gem "weakling", "0.3.1"
@@ -551,15 +960,27 @@ RSpec.describe "bundle outdated" do
shared_examples_for "no version updates are detected" do
it "does not detect any version updates" do
subject
- expect(out).to include("updates to display.")
- expect(out).to_not include("ERROR REPORT TEMPLATE")
- expect(out).to_not include("activesupport (newest")
- expect(out).to_not include("weakling (newest")
+ expect(out).to end_with("updates to display.")
end
end
shared_examples_for "major version is ignored" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "3.3.5"
build_gem "weakling", "1.0.1"
@@ -571,6 +992,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "minor version is ignored" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "2.4.5"
build_gem "weakling", "0.3.1"
@@ -582,6 +1018,21 @@ RSpec.describe "bundle outdated" do
shared_examples_for "patch version is ignored" do
before do
+ build_repo2 do
+ build_git "foo", :path => lib_path("foo")
+ build_git "zebra", :path => lib_path("zebra")
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "zebra", :git => "#{lib_path("zebra")}"
+ gem "foo", :git => "#{lib_path("foo")}"
+ gem "activesupport", "2.3.5"
+ gem "weakling", "~> 0.0.1"
+ gem "duradura", '7.0'
+ gem "terranova", '8'
+ G
+
update_repo2 do
build_gem "activesupport", "2.3.6"
build_gem "weakling", "0.0.4"
@@ -592,7 +1043,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-major option" do
- subject { bundle "outdated --filter-major" }
+ subject { bundle "outdated --filter-major", :raise_on_error => false }
it_behaves_like "major version updates are detected"
it_behaves_like "minor version is ignored"
@@ -600,7 +1051,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-minor option" do
- subject { bundle "outdated --filter-minor" }
+ subject { bundle "outdated --filter-minor", :raise_on_error => false }
it_behaves_like "minor version updates are detected"
it_behaves_like "major version is ignored"
@@ -608,7 +1059,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-patch option" do
- subject { bundle "outdated --filter-patch" }
+ subject { bundle "outdated --filter-patch", :raise_on_error => false }
it_behaves_like "patch version updates are detected"
it_behaves_like "major version is ignored"
@@ -616,7 +1067,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-minor --filter-patch options" do
- subject { bundle "outdated --filter-minor --filter-patch" }
+ subject { bundle "outdated --filter-minor --filter-patch", :raise_on_error => false }
it_behaves_like "minor version updates are detected"
it_behaves_like "patch version updates are detected"
@@ -624,7 +1075,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-major --filter-minor options" do
- subject { bundle "outdated --filter-major --filter-minor" }
+ subject { bundle "outdated --filter-major --filter-minor", :raise_on_error => false }
it_behaves_like "major version updates are detected"
it_behaves_like "minor version updates are detected"
@@ -632,7 +1083,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-major --filter-patch options" do
- subject { bundle "outdated --filter-major --filter-patch" }
+ subject { bundle "outdated --filter-major --filter-patch", :raise_on_error => false }
it_behaves_like "major version updates are detected"
it_behaves_like "patch version updates are detected"
@@ -640,7 +1091,7 @@ RSpec.describe "bundle outdated" do
end
describe "with --filter-major --filter-minor --filter-patch options" do
- subject { bundle "outdated --filter-major --filter-minor --filter-patch" }
+ subject { bundle "outdated --filter-major --filter-minor --filter-patch", :raise_on_error => false }
it_behaves_like "major version updates are detected"
it_behaves_like "minor version updates are detected"
@@ -658,49 +1109,55 @@ RSpec.describe "bundle outdated" do
# establish a lockfile set to 1.0.0
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem 'patch', '1.0.0'
- gem 'minor', '1.0.0'
- gem 'major', '1.0.0'
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'patch', '1.0.0'
+ gem 'minor', '1.0.0'
+ gem 'major', '1.0.0'
G
# remove 1.4.3 requirement and bar altogether
# to setup update specs below
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem 'patch'
- gem 'minor'
- gem 'major'
+ source "#{file_uri_for(gem_repo4)}"
+ gem 'patch'
+ gem 'minor'
+ gem 'major'
G
end
it "shows nothing when patching and filtering to minor" do
bundle "outdated --patch --filter-minor"
- expect(out).to include("No minor updates to display.")
- expect(out).not_to include("patch (newest")
- expect(out).not_to include("minor (newest")
- expect(out).not_to include("major (newest")
+ expect(out).to end_with("No minor updates to display.")
end
it "shows all gems when patching and filtering to patch" do
- bundle "outdated --patch --filter-patch"
+ bundle "outdated --patch --filter-patch", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ major 1.0.0 1.0.1 >= 0 default
+ minor 1.0.0 1.0.1 >= 0 default
+ patch 1.0.0 1.0.1 >= 0 default
+ TABLE
- expect(out).to include("patch (newest 1.0.1")
- expect(out).to include("minor (newest 1.0.1")
- expect(out).to include("major (newest 1.0.1")
+ expect(out).to end_with(expected_output)
end
it "shows minor and major when updating to minor and filtering to patch and minor" do
- bundle "outdated --minor --filter-minor"
+ bundle "outdated --minor --filter-minor", :raise_on_error => false
- expect(out).not_to include("patch (newest")
- expect(out).to include("minor (newest 1.1.0")
- expect(out).to include("major (newest 1.1.0")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ major 1.0.0 1.1.0 >= 0 default
+ minor 1.0.0 1.1.0 >= 0 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
it "shows minor when updating to major and filtering to minor with parseable" do
- bundle "outdated --major --filter-minor --parseable"
+ bundle "outdated --major --filter-minor --parseable", :raise_on_error => false
expect(out).not_to include("patch (newest")
expect(out).to include("minor (newest")
@@ -742,11 +1199,15 @@ RSpec.describe "bundle outdated" do
end
it "shows gems with update-strict updating to patch and filtering to patch" do
- bundle "outdated --patch --update-strict --filter-patch"
+ bundle "outdated --patch --update-strict --filter-patch", :raise_on_error => false
- expect(out).to include("foo (newest 1.4.4")
- expect(out).to include("bar (newest 2.0.5")
- expect(out).not_to include("qux (newest")
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ bar 2.0.3 2.0.5
+ foo 1.4.3 1.4.4 >= 0 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
end
end
end
@@ -771,10 +1232,113 @@ RSpec.describe "bundle outdated" do
gem 'weakling'
G
- bundle "outdated --only-explicit"
+ bundle "outdated --only-explicit", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ weakling 0.2 0.3 >= 0 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+ end
+
+ describe "with a multiplatform lockfile" do
+ before do
+ build_repo4 do
+ build_gem "nokogiri", "1.11.1"
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.platform = Bundler.local_platform
+ end
+
+ build_gem "nokogiri", "1.11.2"
+ build_gem "nokogiri", "1.11.2" do |s|
+ s.platform = Bundler.local_platform
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ nokogiri (1.11.1)
+ nokogiri (1.11.1-#{Bundler.local_platform})
+
+ PLATFORMS
+ ruby
+ #{Bundler.local_platform}
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "nokogiri"
+ G
+ end
+
+ it "reports a single entry per gem" do
+ bundle "outdated", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ nokogiri 1.11.1 1.11.2 >= 0 default
+ TABLE
+
+ expect(out).to end_with(expected_output)
+ end
+ end
+
+ context "when a gem is no longer a dependency after a full update" do
+ before do
+ build_repo4 do
+ build_gem "mini_portile2", "2.5.2" do |s|
+ s.add_dependency "net-ftp", "~> 0.1"
+ end
+
+ build_gem "mini_portile2", "2.5.3"
+
+ build_gem "net-ftp", "0.1.2"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "mini_portile2"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ mini_portile2 (2.5.2)
+ net-ftp (~> 0.1)
+ net-ftp (0.1.2)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ mini_portile2
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "works" do
+ bundle "outdated", :raise_on_error => false
+
+ expected_output = <<~TABLE.strip
+ Gem Current Latest Requested Groups
+ mini_portile2 2.5.2 2.5.3 >= 0 default
+ TABLE
- expect(out).to include("weakling (newest 0.3")
- expect(out).not_to include("bar (newest 2.2")
+ expect(out).to end_with(expected_output)
end
end
end
diff --git a/spec/bundler/commands/post_bundle_message_spec.rb b/spec/bundler/commands/post_bundle_message_spec.rb
index 6fd4fb7089..3050b87754 100644
--- a/spec/bundler/commands/post_bundle_message_spec.rb
+++ b/spec/bundler/commands/post_bundle_message_spec.rb
@@ -22,78 +22,86 @@ RSpec.describe "post bundle message" do
let(:bundle_show_message) { Bundler::VERSION.split(".").first.to_i < 3 ? bundle_show_system_message : bundle_show_path_message }
describe "for fresh bundle install" do
- it "without any options" do
+ it "shows proper messages according to the configured groups" do
bundle :install
expect(out).to include(bundle_show_message)
expect(out).not_to include("Gems in the group")
expect(out).to include(bundle_complete_message)
expect(out).to include(installed_gems_stats)
- end
- it "with --without one group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
+ bundle "config set --local without emo"
+ bundle :install
expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the group emo were not installed")
+ expect(out).to include("Gems in the group 'emo' were not installed")
expect(out).to include(bundle_complete_message)
expect(out).to include(installed_gems_stats)
- end
- it "with --without two groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo test")
+ bundle "config set --local without emo test"
+ bundle :install
expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the groups emo and test were not installed")
+ expect(out).to include("Gems in the groups 'emo' and 'test' were not installed")
expect(out).to include(bundle_complete_message)
expect(out).to include("4 Gemfile dependencies, 3 gems now installed.")
- end
- it "with --without more groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo obama test")
+ bundle "config set --local without emo obama test"
+ bundle :install
expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the groups emo, obama and test were not installed")
+ expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not installed")
expect(out).to include(bundle_complete_message)
expect(out).to include("4 Gemfile dependencies, 2 gems now installed.")
end
- describe "with --path and" do
+ describe "with `path` configured" do
let(:bundle_path) { "./vendor" }
- it "without any options" do
- bundle! :install, forgotten_command_line_options(:path => "vendor")
+ it "shows proper messages according to the configured groups" do
+ bundle "config set --local path vendor"
+ bundle :install
expect(out).to include(bundle_show_path_message)
expect(out).to_not include("Gems in the group")
expect(out).to include(bundle_complete_message)
- end
- it "with --without one group" do
- bundle! :install, forgotten_command_line_options(:without => "emo", :path => "vendor")
+ bundle "config set --local path vendor"
+ bundle "config set --local without emo"
+ bundle :install
expect(out).to include(bundle_show_path_message)
- expect(out).to include("Gems in the group emo were not installed")
+ expect(out).to include("Gems in the group 'emo' were not installed")
expect(out).to include(bundle_complete_message)
- end
- it "with --without two groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo test", :path => "vendor")
+ bundle "config set --local path vendor"
+ bundle "config set --local without emo test"
+ bundle :install
expect(out).to include(bundle_show_path_message)
- expect(out).to include("Gems in the groups emo and test were not installed")
+ expect(out).to include("Gems in the groups 'emo' and 'test' were not installed")
expect(out).to include(bundle_complete_message)
- end
- it "with --without more groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo obama test", :path => "vendor")
+ bundle "config set --local path vendor"
+ bundle "config set --local without emo obama test"
+ bundle :install
expect(out).to include(bundle_show_path_message)
- expect(out).to include("Gems in the groups emo, obama and test were not installed")
+ expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not installed")
expect(out).to include(bundle_complete_message)
end
+ end
+
+ describe "with an absolute `path` inside the cwd configured" do
+ let(:bundle_path) { bundled_app("cache") }
- it "with an absolute --path inside the cwd" do
- bundle! :install, forgotten_command_line_options(:path => bundled_app("cache"))
+ it "shows proper messages according to the configured groups" do
+ bundle "config set --local path #{bundle_path}"
+ bundle :install
expect(out).to include("Bundled gems are installed into `./cache`")
expect(out).to_not include("Gems in the group")
expect(out).to include(bundle_complete_message)
end
+ end
+
+ describe "with `path` configured to an absolute path outside the cwd" do
+ let(:bundle_path) { tmp("not_bundled_app") }
- it "with an absolute --path outside the cwd" do
- bundle! :install, forgotten_command_line_options(:path => tmp("not_bundled_app"))
+ it "shows proper messages according to the configured groups" do
+ bundle "config set --local path #{bundle_path}"
+ bundle :install
expect(out).to include("Bundled gems are installed into `#{tmp("not_bundled_app")}`")
expect(out).to_not include("Gems in the group")
expect(out).to include(bundle_complete_message)
@@ -105,24 +113,14 @@ RSpec.describe "post bundle message" do
bundle "config set force_ruby_platform true"
end
- it "should report a helpful error message", :bundler => "< 3" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "not-a-gem", :group => :development
- G
- expect(err).to include("Could not find gem 'not-a-gem' in any of the gem sources listed in your Gemfile.")
- end
-
- it "should report a helpful error message", :bundler => "3" do
- install_gemfile <<-G
+ it "should report a helpful error message" do
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "rack"
gem "not-a-gem", :group => :development
G
expect(err).to include <<-EOS.strip
Could not find gem 'not-a-gem' in rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally.
-The source does not contain any versions of 'not-a-gem'
EOS
end
@@ -133,7 +131,7 @@ The source does not contain any versions of 'not-a-gem'
G
bundle :cache
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "rack"
gem "not-a-gem", :group => :development
@@ -144,7 +142,7 @@ The source does not contain any versions of 'not-a-gem'
end
end
- describe "for second bundle install run" do
+ describe "for second bundle install run", :bundler => "< 3" do
it "without any options" do
2.times { bundle :install }
expect(out).to include(bundle_show_message)
@@ -154,56 +152,53 @@ The source does not contain any versions of 'not-a-gem'
end
it "with --without one group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
- bundle! :install
+ bundle "install --without emo"
+ bundle :install
expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the group emo were not installed")
+ expect(out).to include("Gems in the group 'emo' were not installed")
expect(out).to include(bundle_complete_message)
expect(out).to include(installed_gems_stats)
end
it "with --without two groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo test")
- bundle! :install
+ bundle "install --without emo test"
+ bundle :install
expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the groups emo and test were not installed")
+ expect(out).to include("Gems in the groups 'emo' and 'test' were not installed")
expect(out).to include(bundle_complete_message)
end
it "with --without more groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo obama test")
+ bundle "install --without emo obama test"
bundle :install
expect(out).to include(bundle_show_message)
- expect(out).to include("Gems in the groups emo, obama and test were not installed")
+ expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not installed")
expect(out).to include(bundle_complete_message)
end
end
describe "for bundle update" do
- it "without any options" do
- bundle! :update, :all => true
+ it "shows proper messages according to the configured groups" do
+ bundle :update, :all => true
expect(out).not_to include("Gems in the groups")
expect(out).to include(bundle_updated_message)
- end
- it "with --without one group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
- bundle! :update, :all => true
- expect(out).to include("Gems in the group emo were not updated")
+ bundle "config set --local without emo"
+ bundle :install
+ bundle :update, :all => true
+ expect(out).to include("Gems in the group 'emo' were not updated")
expect(out).to include(bundle_updated_message)
- end
- it "with --without two groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo test")
- bundle! :update, :all => true
- expect(out).to include("Gems in the groups emo and test were not updated")
+ bundle "config set --local without emo test"
+ bundle :install
+ bundle :update, :all => true
+ expect(out).to include("Gems in the groups 'emo' and 'test' were not updated")
expect(out).to include(bundle_updated_message)
- end
- it "with --without more groups" do
- bundle! :install, forgotten_command_line_options(:without => "emo obama test")
- bundle! :update, :all => true
- expect(out).to include("Gems in the groups emo, obama and test were not updated")
+ bundle "config set --local without emo obama test"
+ bundle :install
+ bundle :update, :all => true
+ expect(out).to include("Gems in the groups 'emo', 'obama' and 'test' were not updated")
expect(out).to include(bundle_updated_message)
end
end
diff --git a/spec/bundler/commands/pristine_spec.rb b/spec/bundler/commands/pristine_spec.rb
index cc7f760d74..2f730bd4e2 100644
--- a/spec/bundler/commands/pristine_spec.rb
+++ b/spec/bundler/commands/pristine_spec.rb
@@ -18,21 +18,23 @@ RSpec.describe "bundle pristine", :ruby_repo do
build_lib "bar", :path => lib_path("bar")
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "weakling"
gem "very_simple_binary"
- gem "foo", :git => "#{lib_path("foo")}"
+ gem "foo", :git => "#{lib_path("foo")}", :branch => "master"
gem "git_with_ext", :git => "#{lib_path("git_with_ext")}"
gem "bar", :path => "#{lib_path("bar")}"
gemspec
G
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
end
context "when sourced from RubyGems" do
it "reverts using cached .gem file" do
- spec = Bundler.definition.specs["weakling"].first
+ spec = find_spec("weakling")
changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt")
FileUtils.touch(changes_txt)
@@ -43,10 +45,9 @@ RSpec.describe "bundle pristine", :ruby_repo do
end
it "does not delete the bundler gem" do
- system_gems :bundler
- bundle! "install"
- bundle! "pristine", :system_bundler => true
- bundle! "-v", :system_bundler => true
+ bundle "install"
+ bundle "pristine"
+ bundle "-v"
expected = if Bundler::VERSION < "3.0"
"Bundler version"
@@ -60,32 +61,45 @@ RSpec.describe "bundle pristine", :ruby_repo do
context "when sourced from git repo" do
it "reverts by resetting to current revision`" do
- spec = Bundler.definition.specs["foo"].first
+ spec = find_spec("foo")
changed_file = Pathname.new(spec.full_gem_path).join("lib/foo.rb")
diff = "#Pristine spec changes"
File.open(changed_file, "a") {|f| f.puts diff }
expect(File.read(changed_file)).to include(diff)
- bundle! "pristine"
+ bundle "pristine"
expect(File.read(changed_file)).to_not include(diff)
end
it "removes added files" do
- spec = Bundler.definition.specs["foo"].first
+ spec = find_spec("foo")
changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt")
FileUtils.touch(changes_txt)
expect(changes_txt).to be_file
- bundle! "pristine"
+ bundle "pristine"
expect(changes_txt).not_to be_file
end
+
+ it "displays warning and ignores changes when a local config exists" do
+ spec = find_spec("foo")
+ bundle "config set local.#{spec.name} #{lib_path(spec.name)}"
+
+ changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt")
+ FileUtils.touch(changes_txt)
+ expect(changes_txt).to be_file
+
+ bundle "pristine"
+ expect(changes_txt).to be_file
+ expect(err).to include("Cannot pristine #{spec.name} (#{spec.version}#{spec.git_version}). Gem is locally overridden.")
+ end
end
context "when sourced from gemspec" do
it "displays warning and ignores changes when sourced from gemspec" do
- spec = Bundler.definition.specs["baz"].first
+ spec = find_spec("baz")
changed_file = Pathname.new(spec.full_gem_path).join("lib/baz.rb")
diff = "#Pristine spec changes"
@@ -98,7 +112,7 @@ RSpec.describe "bundle pristine", :ruby_repo do
end
it "reinstall gemspec dependency" do
- spec = Bundler.definition.specs["baz-dev"].first
+ spec = find_spec("baz-dev")
changed_file = Pathname.new(spec.full_gem_path).join("lib/baz/dev.rb")
diff = "#Pristine spec changes"
@@ -112,7 +126,7 @@ RSpec.describe "bundle pristine", :ruby_repo do
context "when sourced from path" do
it "displays warning and ignores changes when sourced from local path" do
- spec = Bundler.definition.specs["bar"].first
+ spec = find_spec("bar")
changes_txt = Pathname.new(spec.full_gem_path).join("lib/changes.txt")
FileUtils.touch(changes_txt)
expect(changes_txt).to be_file
@@ -124,22 +138,22 @@ RSpec.describe "bundle pristine", :ruby_repo do
context "when passing a list of gems to pristine" do
it "resets them" do
- foo = Bundler.definition.specs["foo"].first
+ foo = find_spec("foo")
foo_changes_txt = Pathname.new(foo.full_gem_path).join("lib/changes.txt")
FileUtils.touch(foo_changes_txt)
expect(foo_changes_txt).to be_file
- bar = Bundler.definition.specs["bar"].first
+ bar = find_spec("bar")
bar_changes_txt = Pathname.new(bar.full_gem_path).join("lib/changes.txt")
FileUtils.touch(bar_changes_txt)
expect(bar_changes_txt).to be_file
- weakling = Bundler.definition.specs["weakling"].first
+ weakling = find_spec("weakling")
weakling_changes_txt = Pathname.new(weakling.full_gem_path).join("lib/changes.txt")
FileUtils.touch(weakling_changes_txt)
expect(weakling_changes_txt).to be_file
- bundle! "pristine foo bar weakling"
+ bundle "pristine foo bar weakling"
expect(err).to include("Cannot pristine bar (1.0). Gem is sourced from local path.")
expect(out).to include("Installing weakling 1.0")
@@ -150,13 +164,13 @@ RSpec.describe "bundle pristine", :ruby_repo do
end
it "raises when one of them is not in the lockfile" do
- bundle "pristine abcabcabc"
+ bundle "pristine abcabcabc", :raise_on_error => false
expect(err).to include("Could not find gem 'abcabcabc'.")
end
end
context "when a build config exists for one of the gems" do
- let(:very_simple_binary) { Bundler.definition.specs["very_simple_binary"].first }
+ let(:very_simple_binary) { find_spec("very_simple_binary") }
let(:c_ext_dir) { Pathname.new(very_simple_binary.full_gem_path).join("ext") }
let(:build_opt) { "--with-ext-lib=#{c_ext_dir}" }
before { bundle "config set build.very_simple_binary -- #{build_opt}" }
@@ -164,7 +178,7 @@ RSpec.describe "bundle pristine", :ruby_repo do
# This just verifies that the generated Makefile from the c_ext gem makes
# use of the build_args from the bundle config
it "applies the config when installing the gem" do
- bundle! "pristine"
+ bundle "pristine"
makefile_contents = File.read(c_ext_dir.join("Makefile").to_s)
expect(makefile_contents).to match(/libpath =.*#{c_ext_dir}/)
@@ -173,7 +187,7 @@ RSpec.describe "bundle pristine", :ruby_repo do
end
context "when a build config exists for a git sourced gem" do
- let(:git_with_ext) { Bundler.definition.specs["git_with_ext"].first }
+ let(:git_with_ext) { find_spec("git_with_ext") }
let(:c_ext_dir) { Pathname.new(git_with_ext.full_gem_path).join("ext") }
let(:build_opt) { "--with-ext-lib=#{c_ext_dir}" }
before { bundle "config set build.git_with_ext -- #{build_opt}" }
@@ -181,11 +195,27 @@ RSpec.describe "bundle pristine", :ruby_repo do
# This just verifies that the generated Makefile from the c_ext gem makes
# use of the build_args from the bundle config
it "applies the config when installing the gem" do
- bundle! "pristine"
+ bundle "pristine"
makefile_contents = File.read(c_ext_dir.join("Makefile").to_s)
expect(makefile_contents).to match(/libpath =.*#{c_ext_dir}/)
expect(makefile_contents).to match(/LIBPATH =.*-L#{c_ext_dir}/)
end
end
+
+ context "when BUNDLE_GEMFILE doesn't exist" do
+ before do
+ bundle "pristine", :env => { "BUNDLE_GEMFILE" => "does/not/exist" }, :raise_on_error => false
+ end
+
+ it "shows a meaningful error" do
+ expect(err).to eq("#{bundled_app("does/not/exist")} not found")
+ end
+ end
+
+ def find_spec(name)
+ without_env_side_effects do
+ Bundler.definition.specs[name].first
+ end
+ end
end
diff --git a/spec/bundler/commands/remove_spec.rb b/spec/bundler/commands/remove_spec.rb
index 402faaf1f3..95d6e75e9f 100644
--- a/spec/bundler/commands/remove_spec.rb
+++ b/spec/bundler/commands/remove_spec.rb
@@ -7,13 +7,13 @@ RSpec.describe "bundle remove" do
source "#{file_uri_for(gem_repo1)}"
G
- bundle "remove"
+ bundle "remove", :raise_on_error => false
expect(err).to include("Please specify gems to remove.")
end
end
- context "when --install flag is specified" do
+ context "when --install flag is specified", :bundler => "< 3" do
it "removes gems from .bundle" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -21,7 +21,7 @@ RSpec.describe "bundle remove" do
gem "rack"
G
- bundle! "remove rack --install"
+ bundle "remove rack --install"
expect(out).to include("rack was removed.")
expect(the_bundle).to_not include_gems "rack"
@@ -37,13 +37,40 @@ RSpec.describe "bundle remove" do
gem "rack"
G
- bundle! "remove rack"
+ bundle "remove rack"
expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
+ expect(the_bundle).to_not include_gems "rack"
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
+
+ context "when gem is specified in multiple lines" do
+ it "shows success for removed gem" do
+ build_git "rack"
+
+ gemfile <<-G
+ source '#{file_uri_for(gem_repo1)}'
+
+ gem 'git'
+ gem 'rack',
+ git: "#{lib_path("rack-1.0")}",
+ branch: 'master'
+ gem 'nokogiri'
+ G
+
+ bundle "remove rack"
+
+ expect(out).to include("rack was removed.")
+ expect(gemfile).to eq <<~G
+ source '#{file_uri_for(gem_repo1)}'
+
+ gem 'git'
+ gem 'nokogiri'
+ G
+ end
+ end
end
context "when gem is not present in gemfile" do
@@ -52,14 +79,14 @@ RSpec.describe "bundle remove" do
source "#{file_uri_for(gem_repo1)}"
G
- bundle "remove rack"
+ bundle "remove rack", :raise_on_error => false
- expect(err).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.")
+ expect(err).to include("`rack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
end
end
end
- describe "remove mutiple gems from gemfile" do
+ describe "remove multiple gems from gemfile" do
context "when all gems are present in gemfile" do
it "shows success fir all removed gems" do
gemfile <<-G
@@ -69,11 +96,11 @@ RSpec.describe "bundle remove" do
gem "rails"
G
- bundle! "remove rack rails"
+ bundle "remove rack rails"
expect(out).to include("rack was removed.")
expect(out).to include("rails was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
@@ -89,10 +116,10 @@ RSpec.describe "bundle remove" do
gem "rspec"
G
- bundle "remove rails rack minitest"
+ bundle "remove rails rack minitest", :raise_on_error => false
- expect(err).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.")
- gemfile_should_be <<-G
+ expect(err).to include("`rack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
@@ -111,10 +138,10 @@ RSpec.describe "bundle remove" do
gem "rack", :group => [:dev]
G
- bundle! "remove rack"
+ bundle "remove rack"
expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
@@ -131,10 +158,10 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
@@ -151,10 +178,10 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rack"
+ bundle "remove rack"
expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
group :test do
@@ -177,16 +204,16 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
end
- context "when the gem belongs to mutiple groups" do
+ context "when the gem belongs to multiple groups" do
it "removes the groups" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -196,16 +223,16 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
end
- context "when the gem is present in mutiple groups" do
+ context "when the gem is present in multiple groups" do
it "removes all empty blocks" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -219,10 +246,10 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
@@ -242,10 +269,10 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
@@ -265,10 +292,10 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
group :test do
@@ -292,10 +319,10 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
group :test do
@@ -309,17 +336,17 @@ RSpec.describe "bundle remove" do
end
describe "arbitrary gemfile" do
- context "when mutiple gems are present in same line" do
+ context "when multiple gems are present in same line" do
it "shows warning for gems not removed" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"; gem "rails"
G
- bundle "remove rails"
+ bundle "remove rails", :raise_on_error => false
expect(err).to include("Gems could not be removed. rack (>= 0) would also have been removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
gem "rack"; gem "rails"
G
@@ -328,7 +355,7 @@ 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
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem"rack"
gem"rspec"
@@ -336,12 +363,12 @@ RSpec.describe "bundle remove" do
gem "minitest"
G
- bundle! "remove rails rack rspec minitest"
+ bundle "remove rails rack rspec minitest"
expect(out).to include("rails was removed.")
expect(out).to include("minitest was removed.")
expect(out).to include("rack, rspec could not be removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
gem"rack"
gem"rspec"
@@ -368,12 +395,12 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "install"
+ bundle "install"
- bundle! "remove rspec"
+ bundle "remove rspec"
expect(out).to include("rspec was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -396,7 +423,7 @@ RSpec.describe "bundle remove" do
gem "rack"
G
- bundle! "remove rack"
+ bundle "remove rack"
expect(out).to include("rack was removed.")
end
@@ -414,7 +441,7 @@ RSpec.describe "bundle remove" do
eval_gemfile "Gemfile-other"
G
- bundle! "remove rack"
+ bundle "remove rack"
expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"")
expect(out).to include("rack was removed.")
@@ -434,9 +461,9 @@ RSpec.describe "bundle remove" do
eval_gemfile "Gemfile-other"
G
- bundle "remove rack"
+ bundle "remove rack", :raise_on_error => false
- expect(err).to include("`rack` is not specified in #{bundled_app("Gemfile")} so it could not be removed.")
+ expect(err).to include("`rack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
end
end
@@ -453,11 +480,11 @@ RSpec.describe "bundle remove" do
gem "rack"
G
- bundle "remove rack"
+ bundle "remove rack", :raise_on_error => false
expect(out).to include("rack was removed.")
expect(err).to include("`rack` is not specified in #{bundled_app("Gemfile-other")} so it could not be removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
eval_gemfile "Gemfile-other"
@@ -478,11 +505,11 @@ RSpec.describe "bundle remove" do
gem "rack"
G
- bundle "remove rack"
+ bundle "remove rack", :raise_on_error => false
expect(out).to include("rack was removed.")
expect(err).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
eval_gemfile "Gemfile-other"
@@ -503,11 +530,11 @@ RSpec.describe "bundle remove" do
gem "rails"; gem "rack"
G
- bundle "remove rack"
+ bundle "remove rack", :raise_on_error => false
expect(err).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
expect(bundled_app("Gemfile-other").read).to include("gem \"rack\"")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
eval_gemfile "Gemfile-other"
@@ -529,7 +556,7 @@ RSpec.describe "bundle remove" do
gem"rack"
G
- bundle! "remove rack"
+ bundle "remove rack"
expect(out).to include("rack was removed.")
expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"")
@@ -547,10 +574,10 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rack"
+ bundle "remove rack"
expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
@@ -566,10 +593,10 @@ RSpec.describe "bundle remove" do
end
G
- bundle! "remove rack"
+ bundle "remove rack"
expect(out).to include("rack was removed.")
- gemfile_should_be <<-G
+ expect(gemfile).to eq <<~G
source "#{file_uri_for(gem_repo1)}"
G
end
@@ -587,9 +614,89 @@ RSpec.describe "bundle remove" do
gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
G
- bundle! "remove foo"
+ bundle "remove foo"
expect(out).to include("foo could not be removed.")
end
end
+
+ describe "with comments that mention gems" do
+ context "when comment is a separate line comment" do
+ it "does not remove the line comment" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
+ # gem "rack" might be used in the future
+ gem "rack"
+ G
+
+ bundle "remove rack"
+
+ expect(out).to include("rack was removed.")
+ expect(gemfile).to eq <<~G
+ source "#{file_uri_for(gem_repo1)}"
+
+ # gem "rack" might be used in the future
+ G
+ end
+ end
+
+ context "when gem specified for removal has an inline comment" do
+ it "removes the inline comment" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
+ gem "rack" # this can be removed
+ G
+
+ bundle "remove rack"
+
+ expect(out).to include("rack was removed.")
+ expect(gemfile).to eq <<~G
+ source "#{file_uri_for(gem_repo1)}"
+ G
+ end
+ end
+
+ context "when gem specified for removal is mentioned in other gem's comment" do
+ it "does not remove other gem" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "puma" # implements interface provided by gem "rack"
+
+ gem "rack"
+ G
+
+ bundle "remove rack"
+
+ expect(out).to_not include("puma was removed.")
+ expect(out).to include("rack was removed.")
+ expect(gemfile).to eq <<~G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "puma" # implements interface provided by gem "rack"
+ G
+ end
+ end
+
+ context "when gem specified for removal has a comment that mentions other gem" do
+ it "does not remove other gem" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "puma" # implements interface provided by gem "rack"
+
+ gem "rack"
+ G
+
+ bundle "remove puma"
+
+ expect(out).to include("puma was removed.")
+ expect(out).to_not include("rack was removed.")
+ expect(gemfile).to eq <<~G
+ source "#{file_uri_for(gem_repo1)}"
+
+ gem "rack"
+ G
+ end
+ end
+ end
end
diff --git a/spec/bundler/commands/show_spec.rb b/spec/bundler/commands/show_spec.rb
index 61b8f73e7f..2adb121616 100644
--- a/spec/bundler/commands/show_spec.rb
+++ b/spec/bundler/commands/show_spec.rb
@@ -10,19 +10,19 @@ RSpec.describe "bundle show", :bundler => "< 3" do
end
it "creates a Gemfile.lock if one did not exist" do
- FileUtils.rm("Gemfile.lock")
+ FileUtils.rm(bundled_app_lock)
bundle "show"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
it "creates a Gemfile.lock when invoked with a gem name" do
- FileUtils.rm("Gemfile.lock")
+ FileUtils.rm(bundled_app_lock)
bundle "show rails"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
it "prints path if gem exists in bundle" do
@@ -50,14 +50,14 @@ RSpec.describe "bundle show", :bundler => "< 3" do
end
it "complains if gem not in bundle" do
- bundle "show missing"
+ bundle "show missing", :raise_on_error => false
expect(err).to match(/could not find gem 'missing'/i)
end
it "prints path of all gems in bundle sorted by name" do
bundle "show --paths"
- expect(out).to include(default_bundle_path("gems", "rake-12.3.2").to_s)
+ expect(out).to include(default_bundle_path("gems", "rake-13.0.1").to_s)
expect(out).to include(default_bundle_path("gems", "rails-2.3.2").to_s)
# Gem names are the last component of their path.
@@ -135,7 +135,7 @@ RSpec.describe "bundle show", :bundler => "< 3" do
G
expect(the_bundle).to include_gems "foo 1.0.0.pre.beta.1"
- bundle! :show
+ bundle :show
expect(out).to include("foo (1.0.0.pre.beta.1")
end
end
@@ -143,13 +143,12 @@ RSpec.describe "bundle show", :bundler => "< 3" do
context "in a fresh gem in a blank git repo" do
before :each do
build_git "foo", :path => lib_path("foo")
- in_app_root_custom lib_path("foo")
- File.open("Gemfile", "w") {|f| f.puts "gemspec" }
- sys_exec "rm -rf .git && git init"
+ File.open(lib_path("foo/Gemfile"), "w") {|f| f.puts "gemspec" }
+ sys_exec "rm -rf .git && git init", :dir => lib_path("foo")
end
it "does not output git errors" do
- bundle :show
+ bundle :show, :dir => lib_path("foo")
expect(err_without_deprecations).to be_empty
end
end
@@ -166,7 +165,7 @@ RSpec.describe "bundle show", :bundler => "< 3" do
end
context "with a valid regexp for gem name" do
- it "presents alternatives" do
+ it "presents alternatives", :readline do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -174,7 +173,7 @@ RSpec.describe "bundle show", :bundler => "< 3" do
G
bundle "show rac"
- expect(out).to eq "1 : rack\n2 : rack-obama\n0 : - exit -\n>"
+ expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>)?\z/)
end
end
@@ -187,19 +186,19 @@ RSpec.describe "bundle show", :bundler => "< 3" do
invalid_regexp = "[]"
- bundle "show #{invalid_regexp}"
+ bundle "show #{invalid_regexp}", :raise_on_error => false
expect(err).to include("Could not find gem '#{invalid_regexp}'.")
end
end
context "--outdated option" do
- # Regression test for https://github.com/bundler/bundler/issues/5375
+ # Regression test for https://github.com/rubygems/bundler/issues/5375
before do
build_repo2
end
it "doesn't update gems to newer versions" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rails"
G
@@ -212,9 +211,9 @@ RSpec.describe "bundle show", :bundler => "< 3" do
end
end
- bundle! "show --outdated"
+ bundle "show --outdated"
- bundle! "install"
+ bundle "install"
expect(the_bundle).to include_gem("rails 2.3.2")
end
end
diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb
index e4449312eb..403a48a508 100644
--- a/spec/bundler/commands/update_spec.rb
+++ b/spec/bundler/commands/update_spec.rb
@@ -1,20 +1,24 @@
# frozen_string_literal: true
RSpec.describe "bundle update" do
- before :each do
- build_repo2
+ describe "with no arguments" do
+ before do
+ build_repo2
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport"
- gem "rack-obama"
- gem "platform_specific"
- G
- end
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
+ gem "platform_specific"
+ G
+ end
- describe "with no arguments", :bundler => "< 3" do
it "updates the entire bundle" do
update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "activesupport", "3.0"
end
@@ -30,31 +34,48 @@ RSpec.describe "bundle update" do
gem "rack-obama"
exit!
G
- bundle "update"
- expect(bundled_app("Gemfile.lock")).to exist
+ bundle "update", :raise_on_error => false
+ expect(bundled_app_lock).to exist
end
end
- describe "with --all", :bundler => "3" do
+ describe "with --all" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "updates the entire bundle" do
update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "activesupport", "3.0"
end
- bundle! "update", :all => true
+ bundle "update", :all => true
expect(out).to include("Bundle updated!")
expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
end
it "doesn't delete the Gemfile.lock file if something goes wrong" do
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
gem "rack-obama"
exit!
G
- bundle "update", :all => true
- expect(bundled_app("Gemfile.lock")).to exist
+ bundle "update", :all => true, :raise_on_error => false
+ expect(bundled_app_lock).to exist
end
end
@@ -65,35 +86,46 @@ RSpec.describe "bundle update" do
gem "rack", "1.0"
G
- bundle! "update --gemfile OmgFile", :all => true
+ bundle "update --gemfile OmgFile", :all => true
expect(bundled_app("OmgFile.lock")).to exist
end
end
context "when update_requires_all_flag is set" do
- before { bundle! "config set update_requires_all_flag true" }
+ before { bundle "config set update_requires_all_flag true" }
it "errors when passed nothing" do
- install_gemfile! ""
- bundle :update
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ bundle :update, :raise_on_error => false
expect(err).to eq("To update everything, pass the `--all` flag.")
end
it "errors when passed --all and another option" do
- install_gemfile! ""
- bundle "update --all foo"
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ bundle "update --all foo", :raise_on_error => false
expect(err).to eq("Cannot specify --all along with specific options.")
end
it "updates everything when passed --all" do
- install_gemfile! ""
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
bundle "update --all"
expect(out).to include("Bundle updated!")
end
end
describe "--quiet argument" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "hides UI messages" do
bundle "update --quiet"
expect(out).not_to include("Bundle updated!")
@@ -101,8 +133,23 @@ RSpec.describe "bundle update" do
end
describe "with a top level dependency" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "unlocks all child dependencies that are unrelated to other locked dependencies" do
update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "activesupport", "3.0"
end
@@ -112,95 +159,276 @@ RSpec.describe "bundle update" do
end
describe "with an unknown dependency" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "should inform the user" do
- bundle "update halting-problem-solver"
+ bundle "update halting-problem-solver", :raise_on_error => false
expect(err).to include "Could not find gem 'halting-problem-solver'"
end
it "should suggest alternatives" do
- bundle "update platformspecific"
+ bundle "update platformspecific", :raise_on_error => false
expect(err).to include "Did you mean platform_specific?"
end
end
describe "with a child dependency" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "should update the child dependency" do
- update_repo2
+ update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+ end
+
bundle "update rack"
expect(the_bundle).to include_gems "rack 1.2"
end
end
describe "when a possible resolve requires an older version of a locked gem" do
- context "and only_update_to_newer_versions is set" do
- before do
- bundle! "config set only_update_to_newer_versions true"
+ it "does not go to an older version" do
+ build_repo4 do
+ build_gem "tilt", "2.0.8"
+ build_gem "slim", "3.0.9" do |s|
+ s.add_dependency "tilt", [">= 1.3.3", "< 2.1"]
+ end
+ build_gem "slim_lint", "0.16.1" do |s|
+ s.add_dependency "slim", [">= 3.0", "< 5.0"]
+ end
+ build_gem "slim-rails", "0.2.1" do |s|
+ s.add_dependency "slim", ">= 0.9.2"
+ end
+ build_gem "slim-rails", "3.1.3" do |s|
+ s.add_dependency "slim", "~> 3.0"
+ end
end
- it "does not go to an older version" do
- build_repo4 do
- build_gem "tilt", "2.0.8"
- build_gem "slim", "3.0.9" do |s|
- s.add_dependency "tilt", [">= 1.3.3", "< 2.1"]
- end
- build_gem "slim_lint", "0.16.1" do |s|
- s.add_dependency "slim", [">= 3.0", "< 5.0"]
- end
- build_gem "slim-rails", "0.2.1" do |s|
- s.add_dependency "slim", ">= 0.9.2"
- end
- build_gem "slim-rails", "3.1.3" do |s|
- s.add_dependency "slim", "~> 3.0"
- end
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "slim-rails"
+ gem "slim_lint"
+ G
+
+ expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
+
+ update_repo4 do
+ build_gem "slim", "4.0.0" do |s|
+ s.add_dependency "tilt", [">= 2.0.6", "< 2.1"]
end
+ end
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "slim-rails"
- gem "slim_lint"
- G
+ bundle "update", :all => true
- expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
+ expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
+ end
- update_repo4 do
- build_gem "slim", "4.0.0" do |s|
- s.add_dependency "tilt", [">= 2.0.6", "< 2.1"]
- end
+ it "does not go to an older version, even if the version upgrade that could cause another gem to downgrade is activated first" do
+ build_repo4 do
+ # countries is processed before country_select by the resolver due to having less spec groups (groups of versions with the same dependencies) (2 vs 3)
+
+ build_gem "countries", "2.1.4"
+ build_gem "countries", "3.1.0"
+
+ build_gem "countries", "4.0.0" do |s|
+ s.add_dependency "sixarm_ruby_unaccent", "~> 1.1"
+ end
+
+ build_gem "country_select", "1.2.0"
+
+ build_gem "country_select", "2.1.4" do |s|
+ s.add_dependency "countries", "~> 2.0"
+ end
+ build_gem "country_select", "3.1.1" do |s|
+ s.add_dependency "countries", "~> 2.0"
end
- bundle! "update", :all => true
+ build_gem "country_select", "5.1.0" do |s|
+ s.add_dependency "countries", "~> 3.0"
+ end
+
+ build_gem "sixarm_ruby_unaccent", "1.1.0"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "country_select"
+ gem "countries"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ countries (3.1.0)
+ country_select (5.1.0)
+ countries (~> 3.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ countries
+ country_select
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- expect(the_bundle).to include_gems("slim 3.0.9", "slim-rails 3.1.3", "slim_lint 0.16.1")
+ previous_lockfile = lockfile
+
+ bundle "lock --update"
+
+ expect(lockfile).to eq(previous_lockfile)
+ end
+
+ it "does not downgrade indirect dependencies unnecessarily" do
+ build_repo4 do
+ build_gem "a" do |s|
+ s.add_dependency "b"
+ s.add_dependency "c"
+ end
+ build_gem "b"
+ build_gem "c"
+ build_gem "c", "2.0"
end
- it "should still downgrade if forced by the Gemfile" do
- build_repo4 do
- build_gem "a"
- build_gem "b", "1.0"
- build_gem "b", "2.0"
+ install_gemfile <<-G, :verbose => true
+ source "#{file_uri_for(gem_repo4)}"
+ gem "a"
+ G
+
+ expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0")
+
+ update_repo4 do
+ build_gem "b", "2.0" do |s|
+ s.add_dependency "c", "< 2"
end
+ end
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "a"
- gem "b"
- G
+ bundle "update", :all => true, :verbose => true
+ expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0")
+ end
+
+ it "should still downgrade if forced by the Gemfile" do
+ build_repo4 do
+ build_gem "a"
+ build_gem "b", "1.0"
+ build_gem "b", "2.0"
+ end
- expect(the_bundle).to include_gems("a 1.0", "b 2.0")
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "a"
+ gem "b"
+ G
- gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "a"
- gem "b", "1.0"
- G
+ expect(the_bundle).to include_gems("a 1.0", "b 2.0")
- bundle! "update b"
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "a"
+ gem "b", "1.0"
+ G
+
+ bundle "update b"
+
+ expect(the_bundle).to include_gems("a 1.0", "b 1.0")
+ end
- expect(the_bundle).to include_gems("a 1.0", "b 1.0")
+ it "should still downgrade if forced by the Gemfile, when transitive dependencies also need downgrade" do
+ build_repo4 do
+ build_gem "activesupport", "6.1.4.1" do |s|
+ s.add_dependency "tzinfo", "~> 2.0"
+ end
+
+ build_gem "activesupport", "6.0.4.1" do |s|
+ s.add_dependency "tzinfo", "~> 1.1"
+ end
+
+ build_gem "tzinfo", "2.0.4"
+ build_gem "tzinfo", "1.2.9"
end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "activesupport", "~> 6.1.0"
+ G
+
+ expect(the_bundle).to include_gems("activesupport 6.1.4.1", "tzinfo 2.0.4")
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "activesupport", "~> 6.0.0"
+ G
+
+ original_lockfile = lockfile
+
+ expected_lockfile = <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ activesupport (6.0.4.1)
+ tzinfo (~> 1.1)
+ tzinfo (1.2.9)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activesupport (~> 6.0.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "update activesupport"
+ expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
+ expect(lockfile).to eq(expected_lockfile)
+
+ lockfile original_lockfile
+ bundle "update"
+ expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
+ expect(lockfile).to eq(expected_lockfile)
+
+ lockfile original_lockfile
+ bundle "lock --update"
+ expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
+ expect(lockfile).to eq(expected_lockfile)
end
end
describe "with --local option" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "doesn't hit repo2" do
FileUtils.rm_rf(gem_repo2)
@@ -210,6 +438,10 @@ RSpec.describe "bundle update" do
end
describe "with --group option" do
+ before do
+ build_repo2
+ end
+
it "should update only specified group gems" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -217,6 +449,10 @@ RSpec.describe "bundle update" do
gem "rack"
G
update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "activesupport", "3.0"
end
bundle "update --group development"
@@ -242,7 +478,7 @@ RSpec.describe "bundle update" do
end
context "when there is a source with the same name as a gem in a group" do
- before :each do
+ before do
build_git "foo", :path => lib_path("activesupport")
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -269,6 +505,10 @@ RSpec.describe "bundle update" do
gem "rack"
G
update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "activesupport", "3.0"
end
bundle "update --group development"
@@ -280,9 +520,20 @@ RSpec.describe "bundle update" do
end
describe "in a frozen bundle" do
+ before do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
+ gem "platform_specific"
+ G
+ end
+
it "should fail loudly", :bundler => "< 3" do
- bundle! "install --deployment"
- bundle "update", :all => true
+ bundle "install --deployment"
+ bundle "update", :all => true, :raise_on_error => false
expect(last_command).to be_failure
expect(err).to match(/You are trying to install in deployment mode after changing.your Gemfile/m)
@@ -290,56 +541,45 @@ RSpec.describe "bundle update" do
end
it "should suggest different command when frozen is set globally", :bundler => "< 3" do
- bundle! "config set --global frozen 1"
- bundle "update", :all => true
+ bundle "config set --global frozen 1"
+ bundle "update", :all => true, :raise_on_error => false
expect(err).to match(/You are trying to install in deployment mode after changing.your Gemfile/m).
and match(/freeze \nby running `bundle config unset frozen`./m)
end
it "should suggest different command when frozen is set globally", :bundler => "3" do
- bundle! "config set --global deployment true"
- bundle "update", :all => true
+ bundle "config set --global deployment true"
+ bundle "update", :all => true, :raise_on_error => false
expect(err).to match(/You are trying to install in deployment mode after changing.your Gemfile/m).
and match(/freeze \nby running `bundle config unset deployment`./m)
end
end
describe "with --source option" do
- it "should not update gems not included in the source that happen to have the same name", :bundler => "< 3" do
- install_gemfile! <<-G
+ before do
+ build_repo2
+ end
+
+ it "should not update gems not included in the source that happen to have the same name" do
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
G
update_repo2 { build_gem "activesupport", "3.0" }
- bundle! "update --source activesupport"
- expect(the_bundle).to include_gem "activesupport 3.0"
+ bundle "update --source activesupport"
+ expect(the_bundle).not_to include_gem "activesupport 3.0"
end
- it "should not update gems not included in the source that happen to have the same name", :bundler => "3" do
- install_gemfile! <<-G
+ it "should not update gems not included in the source that happen to have the same name" do
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
G
update_repo2 { build_gem "activesupport", "3.0" }
- bundle! "update --source activesupport"
- expect(the_bundle).not_to include_gem "activesupport 3.0"
- end
-
- context "with unlock_source_unlocks_spec set to false" do
- before { bundle! "config set unlock_source_unlocks_spec false" }
-
- it "should not update gems not included in the source that happen to have the same name" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport"
- G
- update_repo2 { build_gem "activesupport", "3.0" }
-
- bundle "update --source activesupport"
- expect(the_bundle).not_to include_gems "activesupport 3.0"
- end
+ bundle "update --source activesupport"
+ expect(the_bundle).not_to include_gems "activesupport 3.0"
end
end
@@ -359,20 +599,7 @@ RSpec.describe "bundle update" do
G
end
- it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do
- update_repo2 do
- build_gem "fred", "2.0"
- build_gem "harry", "2.0" do |s|
- s.add_dependency "fred"
- end
- end
-
- bundle "update --source harry"
- expect(the_bundle).to include_gems "harry 2.0"
- expect(the_bundle).to include_gems "fred 1.0"
- end
-
- it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do
+ it "should not update the child dependencies of a gem that has the same name as the source" do
update_repo2 do
build_gem "fred", "2.0"
build_gem "harry", "2.0" do |s|
@@ -404,7 +631,7 @@ RSpec.describe "bundle update" do
G
end
- it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "< 3" do
+ it "should not update the child dependencies of a gem that has the same name as the source" do
update_repo2 do
build_gem "george", "2.0"
build_gem "harry", "2.0" do |s|
@@ -413,27 +640,133 @@ RSpec.describe "bundle update" do
end
bundle "update --source harry"
- expect(the_bundle).to include_gems "harry 2.0"
- expect(the_bundle).to include_gems "fred 1.0"
- expect(the_bundle).to include_gems "george 1.0"
+ expect(the_bundle).to include_gems "harry 1.0", "fred 1.0", "george 1.0"
end
+ end
- it "should not update the child dependencies of a gem that has the same name as the source", :bundler => "3" do
- update_repo2 do
- build_gem "george", "2.0"
- build_gem "harry", "2.0" do |s|
- s.add_dependency "george"
+ it "shows the previous version of the gem when updated from rubygems source", :bundler => "< 3" do
+ build_repo2
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ G
+
+ bundle "update", :all => true
+ expect(out).to include("Using activesupport 2.3.5")
+
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ end
+
+ bundle "update", :all => true
+ expect(out).to include("Installing activesupport 3.0 (was 2.3.5)")
+ end
+
+ context "with suppress_install_using_messages set" do
+ before { bundle "config set suppress_install_using_messages true" }
+
+ it "only prints `Using` for versions that have changed" do
+ build_repo4 do
+ build_gem "bar"
+ build_gem "foo"
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "bar"
+ gem "foo"
+ G
+
+ bundle "update", :all => true
+ expect(out).to match(/Resolving dependencies\.\.\.\.*\nBundle updated!/)
+
+ update_repo4 do
+ build_gem "foo", "2.0"
+ end
+
+ bundle "update", :all => true
+ out.sub!("Removing foo (1.0)\n", "")
+ expect(out).to match(/Resolving dependencies\.\.\.\.*\nFetching foo 2\.0 \(was 1\.0\)\nInstalling foo 2\.0 \(was 1\.0\)\nBundle updated/)
+ end
+ end
+
+ it "shows error message when Gemfile.lock is not preset and gem is specified" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ G
+
+ bundle "update nonexisting", :raise_on_error => false
+ expect(err).to include("This Bundle hasn't been installed yet. Run `bundle install` to update and install the bundled gems.")
+ expect(exitstatus).to eq(22)
+ end
+
+ context "with multiple, duplicated sources, with lockfile in old format", :bundler => "< 3" do
+ before do
+ build_repo2 do
+ build_gem "dotenv", "2.7.6"
+
+ build_gem "oj", "3.11.3"
+ build_gem "oj", "3.11.5"
+
+ build_gem "vcr", "6.0.0"
+ end
+
+ build_repo gem_repo3 do
+ build_gem "pkg-gem-flowbyte-with-dep", "1.0.0" do |s|
+ s.add_dependency "oj"
end
end
- bundle "update --source harry"
- expect(the_bundle).to include_gems "harry 1.0", "fred 1.0", "george 1.0"
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "dotenv"
+
+ source "https://gem.repo3" do
+ gem 'pkg-gem-flowbyte-with-dep'
+ end
+
+ gem "vcr",source: "https://gem.repo2"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ remote: https://gem.repo3/
+ specs:
+ dotenv (2.7.6)
+ oj (3.11.3)
+ pkg-gem-flowbyte-with-dep (1.0.0)
+ oj
+ vcr (6.0.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ dotenv
+ pkg-gem-flowbyte-with-dep!
+ vcr!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "works" do
+ bundle :install, :artifice => "compact_index"
+ bundle "update oj", :artifice => "compact_index"
+
+ expect(out).to include("Bundle updated!")
+ expect(the_bundle).to include_gems "oj 3.11.5"
end
end
end
RSpec.describe "bundle update in more complicated situations" do
- before :each do
+ before do
build_repo2
end
@@ -446,6 +779,10 @@ RSpec.describe "bundle update in more complicated situations" do
G
update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "thin", "2.0" do |s|
s.add_dependency "rack"
end
@@ -456,7 +793,7 @@ RSpec.describe "bundle update in more complicated situations" do
end
it "will warn when some explicitly updated gems are not updated" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "thin"
@@ -468,7 +805,7 @@ RSpec.describe "bundle update in more complicated situations" do
build_gem "rack", "10.0"
end
- bundle! "update thin rack-obama"
+ bundle "update thin rack-obama"
expect(last_command.stdboth).to include "Bundler attempted to update rack-obama but its version stayed the same"
expect(the_bundle).to include_gems "thin 2.0", "rack 10.0", "rack-obama 1.0"
end
@@ -476,7 +813,8 @@ RSpec.describe "bundle update in more complicated situations" do
it "will not warn when an explicitly updated git gem changes sha but not version" do
build_git "foo"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
@@ -484,7 +822,7 @@ RSpec.describe "bundle update in more complicated situations" do
s.write "lib/foo2.rb", "puts :foo2"
end
- bundle! "update foo"
+ bundle "update foo"
expect(last_command.stdboth).not_to include "attempted to update"
end
@@ -492,7 +830,8 @@ RSpec.describe "bundle update in more complicated situations" do
it "will not warn when changing gem sources but not versions" do
build_git "rack"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
gem "rack", :git => '#{lib_path("rack-1.0")}'
G
@@ -501,7 +840,7 @@ RSpec.describe "bundle update in more complicated situations" do
gem "rack"
G
- bundle! "update rack"
+ bundle "update rack"
expect(last_command.stdboth).not_to include "attempted to update"
end
@@ -554,12 +893,12 @@ RSpec.describe "bundle update in more complicated situations" do
end
it "allows updating" do
- bundle! :update, :all => true
+ bundle :update, :all => true
expect(the_bundle).to include_gem "a 1.1"
end
it "allows updating a specific gem" do
- bundle! "update a"
+ bundle "update a"
expect(the_bundle).to include_gem "a 1.1"
end
end
@@ -593,7 +932,7 @@ RSpec.describe "bundle update in more complicated situations" do
end
it "is not updated because it is not actually included in the bundle" do
- bundle! "update a"
+ bundle "update a"
expect(last_command.stdboth).to include "Bundler attempted to update a but it was not considered because it is for a different platform from the current one"
expect(the_bundle).to_not include_gem "a"
end
@@ -617,11 +956,13 @@ RSpec.describe "bundle update without a Gemfile.lock" do
end
RSpec.describe "bundle update when a gem depends on a newer version of bundler" do
- before(:each) do
+ before do
build_repo2 do
build_gem "rails", "3.0.1" do |s|
s.add_dependency "bundler", Bundler::VERSION.succ
end
+
+ build_gem "bundler", Bundler::VERSION.succ
end
gemfile <<-G
@@ -630,85 +971,11 @@ RSpec.describe "bundle update when a gem depends on a newer version of bundler"
G
end
- it "should explain that bundler conflicted", :bundler => "< 3" do
- bundle "update", :all => true
+ it "should explain that bundler conflicted and how to resolve the conflict" do
+ bundle "update", :all => true, :raise_on_error => false
expect(last_command.stdboth).not_to match(/in snapshot/i)
expect(err).to match(/current Bundler version/i).
- and match(/perhaps you need to update bundler/i)
- end
-
- it "should warn that the newer version of Bundler would conflict", :bundler => "3" do
- bundle! "update", :all => true
- expect(err).to include("rails (3.0.1) has dependency bundler").
- and include("so the dependency is being ignored")
- expect(the_bundle).to include_gem "rails 3.0.1"
- end
-end
-
-RSpec.describe "bundle update" do
- it "shows the previous version of the gem when updated from rubygems source", :bundler => "< 3" do
- build_repo2
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport"
- G
-
- bundle "update", :all => true
- expect(out).to include("Using activesupport 2.3.5")
-
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
-
- bundle "update", :all => true
- expect(out).to include("Installing activesupport 3.0 (was 2.3.5)")
- end
-
- context "with suppress_install_using_messages set" do
- before { bundle! "config set suppress_install_using_messages true" }
-
- it "only prints `Using` for versions that have changed" do
- build_repo4 do
- build_gem "bar"
- build_gem "foo"
- end
-
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "bar"
- gem "foo"
- G
-
- bundle! "update", :all => true
- out.gsub!(/RubyGems [\d\.]+ is not threadsafe.*\n?/, "")
- expect(out).to include "Resolving dependencies...\nBundle updated!"
-
- update_repo4 do
- build_gem "foo", "2.0"
- end
-
- bundle! "update", :all => true
- out.sub!("Removing foo (1.0)\n", "")
- out.gsub!(/RubyGems [\d\.]+ is not threadsafe.*\n?/, "")
- expect(out).to include strip_whitespace(<<-EOS).strip
- Resolving dependencies...
- Fetching foo 2.0 (was 1.0)
- Installing foo 2.0 (was 1.0)
- Bundle updated
- EOS
- end
- end
-
- it "shows error message when Gemfile.lock is not preset and gem is specified" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport"
- G
-
- bundle "update nonexisting"
- expect(err).to include("This Bundle hasn't been installed yet. Run `bundle install` to update and install the bundled gems.")
- expect(exitstatus).to eq(22) if exitstatus
+ and match(/Install the necessary version with `gem install bundler:#{Bundler::VERSION.succ}`/i)
end
end
@@ -718,22 +985,24 @@ RSpec.describe "bundle update --ruby" do
::RUBY_VERSION = '2.1.3'
::RUBY_PATCHLEVEL = 100
ruby '~> 2.1.0'
+ source "#{file_uri_for(gem_repo1)}"
G
- bundle "update --ruby"
end
context "when the Gemfile removes the ruby" do
before do
- install_gemfile <<-G
+ gemfile <<-G
::RUBY_VERSION = '2.1.4'
::RUBY_PATCHLEVEL = 222
+ source "#{file_uri_for(gem_repo1)}"
G
end
it "removes the Ruby from the Gemfile.lock" do
bundle "update --ruby"
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -749,17 +1018,19 @@ RSpec.describe "bundle update --ruby" do
context "when the Gemfile specified an updated Ruby version" do
before do
- install_gemfile <<-G
+ gemfile <<-G
::RUBY_VERSION = '2.1.4'
::RUBY_PATCHLEVEL = 222
ruby '~> 2.1.0'
+ source "#{file_uri_for(gem_repo1)}"
G
end
it "updates the Gemfile.lock with the latest version" do
bundle "update --ruby"
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -778,14 +1049,15 @@ RSpec.describe "bundle update --ruby" do
context "when a different Ruby is being used than has been versioned" do
before do
- install_gemfile <<-G
+ gemfile <<-G
::RUBY_VERSION = '2.2.2'
::RUBY_PATCHLEVEL = 505
ruby '~> 2.1.0'
+ source "#{file_uri_for(gem_repo1)}"
G
end
it "shows a helpful error message" do
- bundle "update --ruby"
+ bundle "update --ruby", :raise_on_error => false
expect(err).to include("Your Ruby version is 2.2.2, but your Gemfile specified ~> 2.1.0")
end
@@ -793,17 +1065,19 @@ RSpec.describe "bundle update --ruby" do
context "when updating Ruby version and Gemfile `ruby`" do
before do
- install_gemfile <<-G
+ gemfile <<-G
::RUBY_VERSION = '1.8.3'
::RUBY_PATCHLEVEL = 55
ruby '~> 1.8.0'
+ source "#{file_uri_for(gem_repo1)}"
G
end
it "updates the Gemfile.lock with the latest version" do
bundle "update --ruby"
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -827,15 +1101,16 @@ RSpec.describe "bundle update --bundler" do
build_gem "rack", "1.0"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gem "rack"
G
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, '\11.0.0\2')
FileUtils.rm_r gem_repo4
- bundle! :update, :bundler => true, :verbose => true
+ bundle :update, :bundler => true, :verbose => true
expect(the_bundle).to include_gem "rack 1.0"
expect(the_bundle.locked_gems.bundler_version).to eq v(Bundler::VERSION)
@@ -879,8 +1154,8 @@ RSpec.describe "bundle update conservative" do
context "with patch set as default update level in config" do
it "should do a patch level update" do
- bundle! "config set --local prefer_patch true"
- bundle! "update foo"
+ bundle "config set --local prefer_patch true"
+ bundle "update foo"
expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.1", "qux 1.0.0"
end
@@ -888,13 +1163,13 @@ RSpec.describe "bundle update conservative" do
context "patch preferred" do
it "single gem updates dependent gem to minor" do
- bundle! "update --patch foo"
+ bundle "update --patch foo"
expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.1", "qux 1.0.0"
end
it "update all" do
- bundle! "update --patch", :all => true
+ bundle "update --patch", :all => true
expect(the_bundle).to include_gems "foo 1.4.5", "bar 2.1.1", "qux 1.0.1"
end
@@ -902,7 +1177,7 @@ RSpec.describe "bundle update conservative" do
context "minor preferred" do
it "single gem updates dependent gem to major" do
- bundle! "update --minor foo"
+ bundle "update --minor foo"
expect(the_bundle).to include_gems "foo 1.5.1", "bar 3.0.0", "qux 1.0.0"
end
@@ -910,13 +1185,13 @@ RSpec.describe "bundle update conservative" do
context "strict" do
it "patch preferred" do
- bundle! "update --patch foo bar --strict"
+ bundle "update --patch foo bar --strict"
expect(the_bundle).to include_gems "foo 1.4.4", "bar 2.0.5", "qux 1.0.0"
end
it "minor preferred" do
- bundle! "update --minor --strict", :all => true
+ bundle "update --minor --strict", :all => true
expect(the_bundle).to include_gems "foo 1.5.0", "bar 2.1.1", "qux 1.1.0"
end
@@ -948,9 +1223,9 @@ RSpec.describe "bundle update conservative" do
gem 'shared_owner_b'
G
- lockfile <<-L
+ lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: #{file_uri_for(gem_repo4)}/
specs:
isolated_dep (2.0.1)
isolated_owner (1.0.1)
@@ -962,15 +1237,15 @@ RSpec.describe "bundle update conservative" do
shared_dep (~> 5.0)
PLATFORMS
- ruby
+ #{specific_local_platform}
DEPENDENCIES
+ isolated_owner
shared_owner_a
shared_owner_b
- isolated_owner
BUNDLED WITH
- 1.13.0
+ #{Bundler::VERSION}
L
end
@@ -989,7 +1264,42 @@ RSpec.describe "bundle update conservative" do
it "should not eagerly unlock with --conservative" do
bundle "update --conservative shared_owner_a isolated_owner"
- expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.2", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1"
+ expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.1"
+ end
+
+ it "should only update direct dependencies when fully updating with --conservative" do
+ bundle "update --conservative"
+
+ expect(the_bundle).to include_gems "isolated_owner 1.0.2", "isolated_dep 2.0.1", "shared_dep 5.0.1", "shared_owner_a 3.0.2", "shared_owner_b 4.0.2"
+ end
+
+ it "should only change direct dependencies when updating the lockfile with --conservative" do
+ bundle "lock --update --conservative"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ isolated_dep (2.0.1)
+ isolated_owner (1.0.2)
+ isolated_dep (~> 2.0)
+ shared_dep (5.0.1)
+ shared_owner_a (3.0.2)
+ shared_dep (~> 5.0)
+ shared_owner_b (4.0.2)
+ shared_dep (~> 5.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ isolated_owner
+ shared_owner_a
+ shared_owner_b
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
it "should match bundle install conservative update behavior when not eagerly unlocking" do
@@ -1009,11 +1319,11 @@ RSpec.describe "bundle update conservative" do
context "error handling" do
before do
- gemfile ""
+ gemfile "source \"#{file_uri_for(gem_repo1)}\""
end
it "raises if too many flags are provided" do
- bundle "update --patch --minor", :all => true
+ bundle "update --patch --minor", :all => true, :raise_on_error => false
expect(err).to eq "Provide only one of the following options: minor, patch"
end
diff --git a/spec/bundler/commands/version_spec.rb b/spec/bundler/commands/version_spec.rb
index 8eecd9c53e..53d545f5fa 100644
--- a/spec/bundler/commands/version_spec.rb
+++ b/spec/bundler/commands/version_spec.rb
@@ -11,36 +11,36 @@ RSpec.describe "bundle version" do
context "with -v" do
it "outputs the version", :bundler => "< 3" do
- bundle! "-v"
+ bundle "-v"
expect(out).to eq("Bundler version #{Bundler::VERSION}")
end
it "outputs the version", :bundler => "3" do
- bundle! "-v"
+ bundle "-v"
expect(out).to eq(Bundler::VERSION)
end
end
context "with --version" do
it "outputs the version", :bundler => "< 3" do
- bundle! "--version"
+ bundle "--version"
expect(out).to eq("Bundler version #{Bundler::VERSION}")
end
it "outputs the version", :bundler => "3" do
- bundle! "--version"
+ bundle "--version"
expect(out).to eq(Bundler::VERSION)
end
end
context "with version" do
it "outputs the version with build metadata", :bundler => "< 3" do
- bundle! "version"
+ bundle "version"
expect(out).to match(/\ABundler version #{Regexp.escape(Bundler::VERSION)} \(\d{4}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/)
end
it "outputs the version with build metadata", :bundler => "3" do
- bundle! "version"
+ bundle "version"
expect(out).to match(/\A#{Regexp.escape(Bundler::VERSION)} \(\d{4}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/)
end
end
diff --git a/spec/bundler/commands/viz_spec.rb b/spec/bundler/commands/viz_spec.rb
index 029c3aca24..0efb24b504 100644
--- a/spec/bundler/commands/viz_spec.rb
+++ b/spec/bundler/commands/viz_spec.rb
@@ -1,13 +1,10 @@
# frozen_string_literal: true
RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot") do
- let(:ruby_graphviz) do
- graphviz_glob = base_system_gems.join("cache/ruby-graphviz*")
- Pathname.glob(graphviz_glob).first
- end
-
before do
- system_gems ruby_graphviz
+ graphviz_version = RUBY_VERSION >= "2.4" ? "1.2.5" : "1.2.4"
+
+ realworld_system_gems "ruby-graphviz --version #{graphviz_version}"
end
it "graphs gems from the Gemfile" do
@@ -17,10 +14,10 @@ RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot") do
gem "rack-obama"
G
- bundle! "viz"
+ bundle "viz"
expect(out).to include("gem_graph.png")
- bundle! "viz", :format => "debug"
+ bundle "viz", :format => "debug"
expect(out).to eq(strip_whitespace(<<-DOT).strip)
digraph Gemfile {
concentrate = "true";
@@ -51,10 +48,10 @@ RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot") do
gem "rack-obama"
G
- bundle! "viz"
+ bundle "viz"
expect(out).to include("gem_graph.png")
- bundle! "viz", :format => :debug, :version => true
+ bundle "viz", :format => :debug, :version => true
expect(out).to eq(strip_whitespace(<<-EOS).strip)
digraph Gemfile {
concentrate = "true";
@@ -82,7 +79,7 @@ RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot") do
end
end
- system_gems ruby_graphviz, "graphviz-999", :gem_repo => gem_repo4
+ system_gems "graphviz-999", :gem_repo => gem_repo4
end
it "loads the correct ruby-graphviz gem" do
@@ -92,7 +89,7 @@ RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot") do
gem "rack-obama"
G
- bundle! "viz", :format => "debug"
+ bundle "viz", :format => "debug"
expect(out).to eq(strip_whitespace(<<-DOT).strip)
digraph Gemfile {
concentrate = "true";
@@ -124,7 +121,7 @@ RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot") do
end
G
- bundle! "viz --without=rails"
+ bundle "viz --without=rails"
expect(out).to include("gem_graph.png")
end
@@ -142,7 +139,7 @@ RSpec.describe "bundle viz", :bundler => "< 3", :if => Bundler.which("dot") do
end
G
- bundle! "viz --without=rails:rack"
+ bundle "viz --without=rails:rack"
expect(out).to include("gem_graph.png")
end
end
diff --git a/spec/bundler/install/allow_offline_install_spec.rb b/spec/bundler/install/allow_offline_install_spec.rb
index 8af88b7efe..524363fde5 100644
--- a/spec/bundler/install/allow_offline_install_spec.rb
+++ b/spec/bundler/install/allow_offline_install_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "bundle install with :allow_offline_install" do
context "with no cached data locally" do
it "still installs" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, :artifice => "compact_index"
source "http://testgemserver.local"
gem "rack-obama"
G
@@ -15,7 +15,7 @@ RSpec.describe "bundle install with :allow_offline_install" do
end
it "still fails when the network is down" do
- install_gemfile <<-G, :artifice => "fail"
+ install_gemfile <<-G, :artifice => "fail", :raise_on_error => false
source "http://testgemserver.local"
gem "rack-obama"
G
@@ -26,10 +26,10 @@ 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 => :bundle_path
+ system_gems ["rack-1.0.0"], :path => default_bundle_path
- bundle! "config set clean false"
- install_gemfile! <<-G, :artifice => "compact_index"
+ bundle "config set clean false"
+ install_gemfile <<-G, :artifice => "compact_index"
source "http://testgemserver.local"
gem "rack-obama"
gem "rack", "< 1.0"
@@ -42,7 +42,7 @@ RSpec.describe "bundle install with :allow_offline_install" do
gem "rack-obama"
G
- bundle! :update, :artifice => "fail", :all => true
+ bundle :update, :artifice => "fail", :all => true
expect(last_command.stdboth).to include "Using the cached data for the new index because of a network error"
expect(the_bundle).to include_gems("rack-obama 1.0", "rack 1.0.0")
@@ -70,18 +70,22 @@ RSpec.describe "bundle install with :allow_offline_install" do
end
it "will install from a cached git repo" do
+ skip "doesn't print errors" if Gem.win_platform?
+
git = build_git "a", "1.0.0", :path => lib_path("a")
update_git("a", :path => git.path, :branch => "new_branch")
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "a", :git => #{git.path.to_s.dump}
G
- break_git_remote_ops! { bundle! :update, :all => true }
+ break_git_remote_ops! { bundle :update, :all => true }
expect(err).to include("Using cached git data because of network errors")
expect(the_bundle).to be_locked
break_git_remote_ops! do
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "a", :git => #{git.path.to_s.dump}, :branch => "new_branch"
G
end
diff --git a/spec/bundler/install/binstubs_spec.rb b/spec/bundler/install/binstubs_spec.rb
index 78ee893b81..6961171f4f 100644
--- a/spec/bundler/install/binstubs_spec.rb
+++ b/spec/bundler/install/binstubs_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe "bundle install" do
end
it "warns about the situation" do
- bundle! "exec rackup"
+ bundle "exec rackup"
expect(last_command.stderr).to include(
"The `rackup` executable in the `fake` gem is being loaded, but it's also present in other gems (rack).\n" \
diff --git a/spec/bundler/install/bundler_spec.rb b/spec/bundler/install/bundler_spec.rb
index 6ea15d13b5..963ce82db8 100644
--- a/spec/bundler/install/bundler_spec.rb
+++ b/spec/bundler/install/bundler_spec.rb
@@ -21,18 +21,58 @@ RSpec.describe "bundle install" do
expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}"
end
- it "are not added if not already present" do
+ it "are forced to the current bundler version even if not already present" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- expect(the_bundle).not_to include_gems "bundler #{Bundler::VERSION}"
+ expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}"
end
- it "causes a conflict if explicitly requesting a different version" do
- bundle "config set force_ruby_platform true"
+ it "causes a conflict if explicitly requesting a different version of bundler" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rails", "3.0"
+ gem "bundler", "0.9.1"
+ G
- install_gemfile <<-G
+ nice_error = <<-E.strip.gsub(/^ {8}/, "")
+ Bundler could not find compatible versions for gem "bundler":
+ In Gemfile:
+ bundler (= 0.9.1)
+
+ Current Bundler version:
+ bundler (#{Bundler::VERSION})
+
+ Your bundle requires a different version of Bundler than the one you're running.
+ Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install`
+ E
+ expect(err).to include(nice_error)
+ end
+
+ it "causes a conflict if explicitly requesting a non matching requirement on bundler" do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rails", "3.0"
+ gem "bundler", "~> 0.8"
+ G
+
+ nice_error = <<-E.strip.gsub(/^ {8}/, "")
+ Bundler could not find compatible versions for gem "bundler":
+ In Gemfile:
+ bundler (~> 0.8)
+
+ Current Bundler version:
+ bundler (#{Bundler::VERSION})
+
+ Your bundle requires a different version of Bundler than the one you're running.
+ Install the necessary version with `gem install bundler:0.9.1` and rerun bundler using `bundle _0.9.1_ install`
+ E
+ expect(err).to include(nice_error)
+ end
+
+ it "causes a conflict if explicitly requesting a version of bundler that doesn't exist" do
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
gem "rails", "3.0"
gem "bundler", "0.9.2"
@@ -45,15 +85,19 @@ RSpec.describe "bundle install" do
Current Bundler version:
bundler (#{Bundler::VERSION})
- This Gemfile requires a different version of Bundler.
- Perhaps you need to update Bundler by running `gem install bundler`?
- Could not find gem 'bundler (= 0.9.2)' in any
+ Your bundle requires a different version of Bundler than the one you're running, and that version could not be found.
E
expect(err).to include(nice_error)
end
it "works for gems with multiple versions in its dependencies" do
+ build_repo2 do
+ build_gem "multiple_versioned_deps" do |s|
+ s.add_dependency "weakling", ">= 0.0.1", "< 0.1"
+ end
+ end
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
@@ -93,10 +137,16 @@ RSpec.describe "bundle install" do
it "causes a conflict if child dependencies conflict" do
bundle "config set force_ruby_platform true"
- install_gemfile <<-G
+ update_repo2 do
+ build_gem "rails_pinned_to_old_activesupport" do |s|
+ s.add_dependency "activesupport", "= 1.2.3"
+ end
+ end
+
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
gem "activemerchant"
- gem "rails_fail"
+ gem "rails_pinned_to_old_activesupport"
G
nice_error = <<-E.strip.gsub(/^ {8}/, "")
@@ -105,7 +155,7 @@ RSpec.describe "bundle install" do
activemerchant was resolved to 1.0, which depends on
activesupport (>= 2.0.0)
- rails_fail was resolved to 1.0, which depends on
+ rails_pinned_to_old_activesupport was resolved to 1.0, which depends on
activesupport (= 1.2.3)
E
expect(err).to include(nice_error)
@@ -114,9 +164,15 @@ RSpec.describe "bundle install" do
it "causes a conflict if a child dependency conflicts with the Gemfile" do
bundle "config set force_ruby_platform true"
- install_gemfile <<-G
+ update_repo2 do
+ build_gem "rails_pinned_to_old_activesupport" do |s|
+ s.add_dependency "activesupport", "= 1.2.3"
+ end
+ end
+
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
- gem "rails_fail"
+ gem "rails_pinned_to_old_activesupport"
gem "activesupport", "2.3.5"
G
@@ -125,58 +181,59 @@ RSpec.describe "bundle install" do
In Gemfile:
activesupport (= 2.3.5)
- rails_fail was resolved to 1.0, which depends on
+ rails_pinned_to_old_activesupport was resolved to 1.0, which depends on
activesupport (= 1.2.3)
E
expect(err).to include(nice_error)
end
- it "can install dependencies with newer bundler version with system gems" do
- bundle! "config set path.system true"
- install_gemfile! <<-G
+ it "does not cause a conflict if new dependencies in the Gemfile require older dependencies than the lockfile" do
+ update_repo2 do
+ build_gem "rails_pinned_to_old_activesupport" do |s|
+ s.add_dependency "activesupport", "= 1.2.3"
+ end
+ end
+
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
- gem "rails", "3.0"
+ gem 'rails', "2.3.2"
G
- simulate_bundler_version "99999999.99.1"
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rails_pinned_to_old_activesupport"
+ G
- bundle! "check"
- expect(out).to include("The Gemfile's dependencies are satisfied")
+ expect(out).to include("Installing activesupport 1.2.3 (was 2.3.2)")
+ expect(err).to be_empty
end
- it "can install dependencies with newer bundler version with a local path" do
- bundle! "config set path .bundle"
- install_gemfile! <<-G
+ it "can install dependencies with newer bundler version with system gems" do
+ bundle "config set path.system true"
+
+ system_gems "bundler-99999999.99.1"
+
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "rails", "3.0"
G
- simulate_bundler_version "99999999.99.1"
-
- bundle! "check"
+ bundle "check"
expect(out).to include("The Gemfile's dependencies are satisfied")
end
- context "with allow_bundler_dependency_conflicts set" do
- before { bundle! "config set allow_bundler_dependency_conflicts true" }
-
- it "are forced to the current bundler version with warnings when no compatible version is found" do
- build_repo4 do
- build_gem "requires_nonexistant_bundler" do |s|
- s.add_runtime_dependency "bundler", "99.99.99.99"
- end
- end
+ it "can install dependencies with newer bundler version with a local path" do
+ bundle "config set path .bundle"
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "requires_nonexistant_bundler"
- G
+ system_gems "bundler-99999999.99.1"
- expect(err).to include "requires_nonexistant_bundler (1.0) has dependency bundler (= 99.99.99.99), " \
- "which is unsatisfied by the current bundler version #{Bundler::VERSION}, so the dependency is being ignored"
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rails", "3.0"
+ G
- expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}", "requires_nonexistant_bundler 1.0"
- end
+ bundle "check"
+ expect(out).to include("The Gemfile's dependencies are satisfied")
end
end
end
diff --git a/spec/bundler/install/deploy_spec.rb b/spec/bundler/install/deploy_spec.rb
index f92a531bf5..54fc6371cb 100644
--- a/spec/bundler/install/deploy_spec.rb
+++ b/spec/bundler/install/deploy_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "install with --deployment or --frozen" do
+RSpec.describe "install in deployment or frozen mode" do
before do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -10,76 +10,94 @@ RSpec.describe "install with --deployment or --frozen" do
context "with CLI flags", :bundler => "< 3" do
it "fails without a lockfile and says that --deployment requires a lock" do
- bundle "install --deployment"
+ bundle "install --deployment", :raise_on_error => false
expect(err).to include("The --deployment flag requires a Gemfile.lock")
end
it "fails without a lockfile and says that --frozen requires a lock" do
- bundle "install --frozen"
+ bundle "install --frozen", :raise_on_error => false
expect(err).to include("The --frozen flag requires a Gemfile.lock")
end
it "disallows --deployment --system" do
- bundle "install --deployment --system"
+ bundle "install --deployment --system", :raise_on_error => false
expect(err).to include("You have specified both --deployment")
expect(err).to include("Please choose only one option")
- expect(exitstatus).to eq(15) if exitstatus
+ expect(exitstatus).to eq(15)
end
it "disallows --deployment --path --system" do
- bundle "install --deployment --path . --system"
+ bundle "install --deployment --path . --system", :raise_on_error => false
expect(err).to include("You have specified both --path")
expect(err).to include("as well as --system")
expect(err).to include("Please choose only one option")
- expect(exitstatus).to eq(15) if exitstatus
+ expect(exitstatus).to eq(15)
end
it "doesn't mess up a subsequent `bundle install` after you try to deploy without a lock" do
- bundle "install --deployment"
- bundle! :install
+ bundle "install --deployment", :raise_on_error => false
+ bundle :install
expect(the_bundle).to include_gems "rack 1.0"
end
end
it "still works if you are not in the app directory and specify --gemfile" do
- bundle! "install"
- Dir.chdir tmp do
- simulate_new_machine
- bundle! :install,
- forgotten_command_line_options(:gemfile => "#{tmp}/bundled_app/Gemfile",
- :deployment => true,
- :path => "vendor/bundle")
- end
+ bundle "install"
+ simulate_new_machine
+ bundle "config set --local deployment true"
+ bundle "config set --local path vendor/bundle"
+ bundle "install --gemfile #{tmp}/bundled_app/Gemfile", :dir => tmp
expect(the_bundle).to include_gems "rack 1.0"
end
it "works if you exclude a group with a git gem" do
build_git "foo"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
group :test do
gem "foo", :git => "#{lib_path("foo-1.0")}"
end
G
- bundle! :install
- bundle! :install, forgotten_command_line_options(:deployment => true, :without => "test")
+ bundle :install
+ bundle "config set --local deployment true"
+ bundle "config set --local without test"
+ bundle :install
end
it "works when you bundle exec bundle" do
- bundle! :install
- bundle "install --deployment"
- bundle! "exec bundle check"
+ skip "doesn't find bundle" if Gem.win_platform?
+
+ bundle :install
+ bundle "config set --local deployment true"
+ bundle :install
+ bundle "exec bundle check", :env => { "PATH" => path }
end
it "works when using path gems from the same path and the version is specified" do
build_lib "foo", :path => lib_path("nested/foo")
build_lib "bar", :path => lib_path("nested/bar")
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", "1.0", :path => "#{lib_path("nested")}"
gem "bar", :path => "#{lib_path("nested")}"
G
- bundle! :install
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ bundle :install
+ bundle "config set --local deployment true"
+ bundle :install
+ end
+
+ it "works when path gems are specified twice" do
+ build_lib "foo", :path => lib_path("nested/foo")
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :path => "#{lib_path("nested/foo")}"
+ gem "foo", :path => "#{lib_path("nested/foo")}"
+ G
+
+ bundle :install
+ bundle "config set --local deployment true"
+ bundle :install
end
it "works when there are credentials in the source URL" do
@@ -89,66 +107,70 @@ RSpec.describe "install with --deployment or --frozen" do
gem "rack-obama", ">= 1.0"
G
- bundle! :install, forgotten_command_line_options(:deployment => true).merge(:artifice => "endpoint_strict_basic_authentication")
+ bundle "config set --local deployment true"
+ bundle :install, :artifice => "endpoint_strict_basic_authentication"
end
it "works with sources given by a block" do
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
source "#{file_uri_for(gem_repo1)}" do
gem "rack"
end
G
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ bundle :install
expect(the_bundle).to include_gems "rack 1.0"
end
context "when replacing a host with the same host with credentials" do
before do
- bundle! "install", forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle "install"
gemfile <<-G
- source "http://user_name:password@localgemserver.test/"
- gem "rack"
+ source "http://user_name:password@localgemserver.test/"
+ gem "rack"
G
lockfile <<-G
- GEM
- remote: http://localgemserver.test/
- specs:
- rack (1.0.0)
+ GEM
+ remote: http://localgemserver.test/
+ specs:
+ rack (1.0.0)
- PLATFORMS
- #{local}
+ PLATFORMS
+ #{local}
- DEPENDENCIES
- rack
+ DEPENDENCIES
+ rack
G
- bundle! "config set --local deployment true"
+ bundle "config set --local deployment true"
end
it "prevents the replace by default" do
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/The list of sources changed/)
end
context "when allow_deployment_source_credential_changes is true" do
- before { bundle! "config set allow_deployment_source_credential_changes true" }
+ before { bundle "config set allow_deployment_source_credential_changes true" }
it "allows the replace" do
- bundle! :install
+ bundle :install
expect(out).to match(/Bundle complete!/)
end
end
context "when allow_deployment_source_credential_changes is false" do
- before { bundle! "config set allow_deployment_source_credential_changes false" }
+ before { bundle "config set allow_deployment_source_credential_changes false" }
it "prevents the replace" do
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/The list of sources changed/)
end
@@ -168,7 +190,7 @@ RSpec.describe "install with --deployment or --frozen" do
before { ENV["BUNDLE_ALLOW_DEPLOYMENT_SOURCE_CREDENTIAL_CHANGES"] = "false" }
it "prevents the replace" do
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/The list of sources changed/)
end
@@ -177,29 +199,29 @@ RSpec.describe "install with --deployment or --frozen" do
describe "with an existing lockfile" do
before do
- bundle! "install"
+ bundle "install"
end
it "installs gems by default to vendor/bundle", :bundler => "< 3" do
- bundle! "install --deployment"
+ bundle "install --deployment"
expect(out).to include("vendor/bundle")
end
it "installs gems to custom path if specified", :bundler => "< 3" do
- bundle! "install --path vendor/bundle2 --deployment"
+ bundle "install --path vendor/bundle2 --deployment"
expect(out).to include("vendor/bundle2")
end
it "works with the --deployment flag if you didn't change anything", :bundler => "< 3" do
- bundle! "install --deployment"
+ bundle "install --deployment"
end
it "works with the --frozen flag if you didn't change anything", :bundler => "< 3" do
- bundle! "install --frozen"
+ bundle "install --frozen"
end
it "works with BUNDLE_FROZEN if you didn't change anything" do
- bundle! :install, :env => { "BUNDLE_FROZEN" => "true" }
+ bundle :install, :env => { "BUNDLE_FROZEN" => "true" }
end
it "explodes with the --deployment flag if you make a change and don't check in the lockfile" do
@@ -209,7 +231,8 @@ RSpec.describe "install with --deployment or --frozen" do
gem "rack-obama"
G
- bundle :install, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ bundle :install, :raise_on_error => false
expect(err).to include("deployment mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
@@ -219,7 +242,7 @@ RSpec.describe "install with --deployment or --frozen" do
it "works if a path gem is missing but is in a without group" do
build_lib "path_gem"
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rake"
gem "path_gem", :path => "#{lib_path("path_gem-1.0")}", :group => :development
@@ -227,14 +250,17 @@ RSpec.describe "install with --deployment or --frozen" do
expect(the_bundle).to include_gems "path_gem 1.0"
FileUtils.rm_r lib_path("path_gem-1.0")
- bundle! :install, forgotten_command_line_options(:path => ".bundle", :without => "development", :deployment => true).merge(:env => { "DEBUG" => "1" })
- run! "puts :WIN"
+ bundle "config set --local path .bundle"
+ bundle "config set --local without development"
+ bundle "config set --local deployment true"
+ bundle :install, :env => { "DEBUG" => "1" }
+ run "puts :WIN"
expect(out).to eq("WIN")
end
it "explodes if a path gem is missing" do
build_lib "path_gem"
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rake"
gem "path_gem", :path => "#{lib_path("path_gem-1.0")}", :group => :development
@@ -242,7 +268,9 @@ RSpec.describe "install with --deployment or --frozen" do
expect(the_bundle).to include_gems "path_gem 1.0"
FileUtils.rm_r lib_path("path_gem-1.0")
- bundle :install, forgotten_command_line_options(:path => ".bundle", :deployment => true)
+ bundle "config set --local path .bundle"
+ bundle "config set --local deployment true"
+ bundle :install, :raise_on_error => false
expect(err).to include("The path `#{lib_path("path_gem-1.0")}` does not exist.")
end
@@ -254,7 +282,7 @@ RSpec.describe "install with --deployment or --frozen" do
G
ENV["BUNDLE_FROZEN"] = "1"
- bundle "install"
+ bundle "install", :raise_on_error => false
expect(err).to include("deployment mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
@@ -270,7 +298,7 @@ RSpec.describe "install with --deployment or --frozen" do
G
ENV["BUNDLE_DEPLOYMENT"] = "true"
- bundle "install"
+ bundle "install", :raise_on_error => false
expect(err).to include("deployment mode")
expect(err).to include("You have added to the Gemfile")
expect(err).to include("* rack-obama")
@@ -278,7 +306,7 @@ RSpec.describe "install with --deployment or --frozen" do
expect(err).not_to include("You have changed in the Gemfile")
end
- it "installs gems by default to vendor/bundle when `--deployment` is set via an environment variable", :bundler => "< 3" do
+ it "installs gems by default to vendor/bundle when deployment mode is set via an environment variable", :bundler => "< 3" do
ENV["BUNDLE_DEPLOYMENT"] = "true"
bundle "install"
expect(out).to include("vendor/bundle")
@@ -312,7 +340,8 @@ RSpec.describe "install with --deployment or --frozen" do
gem "activesupport"
G
- bundle :install, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ bundle :install, :raise_on_error => false
expect(err).to include("deployment mode")
expect(err).to include("You have added to the Gemfile:\n* activesupport\n\n")
expect(err).to include("You have deleted from the Gemfile:\n* rack")
@@ -325,13 +354,14 @@ RSpec.describe "install with --deployment or --frozen" do
gem "rack", :git => "git://hubz.com"
G
- bundle :install, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ bundle :install, :raise_on_error => false
expect(err).to include("deployment mode")
- expect(err).to include("You have added to the Gemfile:\n* source: git://hubz.com (at master)")
- expect(err).not_to include("You have changed in the Gemfile")
+ expect(err).not_to include("You have added to the Gemfile")
+ expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `git://hubz.com`")
end
- it "explodes if you unpin a source" do
+ it "explodes if you change a source" do
build_git "rack"
install_gemfile <<-G
@@ -344,14 +374,15 @@ RSpec.describe "install with --deployment or --frozen" do
gem "rack"
G
- bundle :install, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ bundle :install, :raise_on_error => false
expect(err).to include("deployment mode")
- expect(err).to include("You have deleted from the Gemfile:\n* source: #{lib_path("rack-1.0")} (at master@#{revision_for(lib_path("rack-1.0"))[0..6]}")
+ expect(err).not_to include("You have deleted from the Gemfile")
expect(err).not_to include("You have added to the Gemfile")
- expect(err).not_to include("You have changed in the Gemfile")
+ expect(err).to include("You have changed in the Gemfile:\n* rack from `#{lib_path("rack-1.0")}` to `no specified source`")
end
- it "explodes if you unpin a source, leaving it pinned somewhere else" do
+ it "explodes if you change a source" do
build_lib "foo", :path => lib_path("rack/foo")
build_git "rack", :path => lib_path("rack")
@@ -367,17 +398,18 @@ RSpec.describe "install with --deployment or --frozen" do
gem "foo", :git => "#{lib_path("rack")}"
G
- bundle :install, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ bundle :install, :raise_on_error => false
expect(err).to include("deployment mode")
- expect(err).to include("You have changed in the Gemfile:\n* rack from `no specified source` to `#{lib_path("rack")} (at master@#{revision_for(lib_path("rack"))[0..6]})`")
+ expect(err).to include("You have changed in the Gemfile:\n* rack from `#{lib_path("rack")}` to `no specified source`")
expect(err).not_to include("You have added to the Gemfile")
expect(err).not_to include("You have deleted from the Gemfile")
end
it "remembers that the bundle is frozen at runtime" do
- bundle! :lock
+ bundle :lock
- bundle! "config set --local deployment true"
+ bundle "config set --local deployment true"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -385,7 +417,7 @@ RSpec.describe "install with --deployment or --frozen" do
gem "rack-obama"
G
- expect(the_bundle).not_to include_gems "rack 1.0.0"
+ run "require 'rack'", :raise_on_error => false
expect(err).to include strip_whitespace(<<-E).strip
The dependencies in your gemfile changed
@@ -402,23 +434,24 @@ You have deleted from the Gemfile:
context "with path in Gemfile and packed" do
it "works fine after bundle package and bundle install --local" do
build_lib "foo", :path => lib_path("foo")
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo")}"
G
- bundle! :install
+ bundle :install
expect(the_bundle).to include_gems "foo 1.0"
bundle "config set cache_all true"
- bundle! :cache
+ bundle :cache
expect(bundled_app("vendor/cache/foo")).to be_directory
- bundle! "install --local"
+ bundle "install --local"
expect(out).to include("Updating files in vendor/cache")
simulate_new_machine
- bundle! "config set --local deployment true"
- bundle! "install --verbose"
+ bundle "config set --local deployment true"
+ bundle "install --verbose"
expect(out).not_to include("You are trying to install in deployment mode after changing your Gemfile")
expect(out).not_to include("You have added to the Gemfile")
expect(out).not_to include("You have deleted from the Gemfile")
diff --git a/spec/bundler/install/failure_spec.rb b/spec/bundler/install/failure_spec.rb
index 57ffafd588..4a9c33754f 100644
--- a/spec/bundler/install/failure_spec.rb
+++ b/spec/bundler/install/failure_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe "bundle install" do
context "installing a gem fails" do
- it "prints out why that gem was being installed" do
+ it "prints out why that gem was being installed and the underlying error" do
build_repo2 do
build_gem "activesupport", "2.3.2" do |s|
s.extensions << "Rakefile"
@@ -14,106 +14,13 @@ RSpec.describe "bundle install" do
end
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
gem "rails"
G
+ expect(err).to start_with("Gem::Ext::BuildError: ERROR: Failed to build gem native extension.")
expect(err).to end_with(<<-M.strip)
An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
-Make sure that `gem install activesupport -v '2.3.2' --source '#{file_uri_for(gem_repo2)}/'` succeeds before bundling.
-
-In Gemfile:
- rails was resolved to 2.3.2, which depends on
- actionmailer was resolved to 2.3.2, which depends on
- activesupport
- M
- end
-
- context "when installing a git gem" do
- it "does not tell the user to run 'gem install'" do
- build_git "activesupport", "2.3.2", :path => lib_path("activesupport") do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- abort "make installing activesupport-2.3.2 fail"
- end
- RUBY
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rails"
- gem "activesupport", :git => "#{lib_path("activesupport")}"
- G
-
- expect(err).to end_with(<<-M.strip)
-An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
-
-In Gemfile:
- rails was resolved to 2.3.2, which depends on
- actionmailer was resolved to 2.3.2, which depends on
- activesupport
- M
- end
- end
-
- context "when installing a gem using a git block" do
- it "does not tell the user to run 'gem install'" do
- build_git "activesupport", "2.3.2", :path => lib_path("activesupport") do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- abort "make installing activesupport-2.3.2 fail"
- end
- RUBY
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rails"
-
- git "#{lib_path("activesupport")}" do
- gem "activesupport"
- end
- G
-
- expect(err).to end_with(<<-M.strip)
-An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
-
-
-In Gemfile:
- rails was resolved to 2.3.2, which depends on
- actionmailer was resolved to 2.3.2, which depends on
- activesupport
- M
- end
- end
-
- it "prints out the hint for the remote source when available" do
- build_repo2 do
- build_gem "activesupport", "2.3.2" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- abort "make installing activesupport-2.3.2 fail"
- end
- RUBY
- end
- end
-
- build_repo4 do
- build_gem "a"
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- source "#{file_uri_for(gem_repo2)}" do
- gem "rails"
- end
- G
- expect(err).to end_with(<<-M.strip)
-An error occurred while installing activesupport (2.3.2), and Bundler cannot continue.
-Make sure that `gem install activesupport -v '2.3.2' --source '#{file_uri_for(gem_repo2)}/'` succeeds before bundling.
In Gemfile:
rails was resolved to 2.3.2, which depends on
@@ -132,7 +39,7 @@ In Gemfile:
end
it "removes the downloaded .gem" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo4)}"
gem "a"
G
diff --git a/spec/bundler/install/gemfile/eval_gemfile_spec.rb b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
index 7df94aaff5..02283291b4 100644
--- a/spec/bundler/install/gemfile/eval_gemfile_spec.rb
+++ b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
@@ -11,12 +11,14 @@ 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)}"
gemspec :path => 'gems/gunks'
G
end
it "installs the gemspec specified gem" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
eval_gemfile 'Gemfile-other'
G
expect(out).to include("Resolving dependencies")
@@ -26,28 +28,65 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
end
end
+ context "eval-ed Gemfile points to an internal gemspec and uses a scoped source that duplicates the main Gemfile global source" do
+ before do
+ build_repo2 do
+ build_gem "rails", "6.1.3.2"
+
+ build_gem "zip-zip", "0.3"
+ end
+
+ create_file bundled_app("gems/Gemfile"), <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gemspec :path => "\#{__dir__}/gunks"
+
+ source "#{file_uri_for(gem_repo2)}" do
+ gem "zip-zip"
+ end
+ G
+ end
+
+ it "installs and finds gems correctly" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "rails"
+
+ eval_gemfile File.join(__dir__, "gems/Gemfile")
+ G
+ expect(out).to include("Resolving dependencies")
+ expect(out).to include("Bundle complete")
+
+ expect(the_bundle).to include_gem "rails 6.1.3.2"
+ end
+ end
+
context "eval-ed Gemfile has relative-path gems" do
before do
- build_lib("a", :path => "gems/a")
- create_file "nested/Gemfile-nested", <<-G
+ build_lib("a", :path => bundled_app("gems/a"))
+ create_file bundled_app("nested/Gemfile-nested"), <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "a", :path => "../gems/a"
G
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
eval_gemfile "nested/Gemfile-nested"
G
end
it "installs the path gem" do
- bundle! :install
+ bundle :install
expect(the_bundle).to include_gem("a 1.0")
end
# Make sure that we are properly comparing path based gems between the
# parsed lockfile and the evaluated gemfile.
- it "bundles with --deployment" do
- bundle! :install
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ it "bundles with deployment mode configured" do
+ bundle :install
+ bundle "config set --local deployment true"
+ bundle :install
end
end
@@ -56,6 +95,7 @@ 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)}"
eval_gemfile 'other/Gemfile-other'
gemspec :path => 'gems/gunks'
G
@@ -74,7 +114,7 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
source "#{file_uri_for(gem_repo1)}"
eval_gemfile "other/Gemfile"
G
- install_gemfile! "eval_gemfile File.expand_path('Gemfile-alt')"
+ install_gemfile "eval_gemfile File.expand_path('Gemfile-alt')"
expect(the_bundle).to include_gem "rack 1.0.0"
end
diff --git a/spec/bundler/install/gemfile/gemspec_spec.rb b/spec/bundler/install/gemfile/gemspec_spec.rb
index 26a6235166..6d9cd2daff 100644
--- a/spec/bundler/install/gemfile/gemspec_spec.rb
+++ b/spec/bundler/install/gemfile/gemspec_spec.rb
@@ -61,7 +61,7 @@ RSpec.describe "bundle install from an existing gemspec" do
it "should raise if there are no gemspecs available" do
build_lib("foo", :path => tmp.join("foo"), :gemspec => false)
- install_gemfile(<<-G)
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
gemspec :path => '#{tmp.join("foo")}'
G
@@ -73,7 +73,7 @@ RSpec.describe "bundle install from an existing gemspec" do
s.write("foo2.gemspec", build_spec("foo", "4.0").first.to_ruby)
end
- install_gemfile(<<-G)
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
gemspec :path => '#{tmp.join("foo")}'
G
@@ -117,21 +117,20 @@ RSpec.describe "bundle install from an existing gemspec" do
build_lib("foo", :path => tmp.join("foo")) do |s|
s.write("Gemfile", "source '#{file_uri_for(gem_repo1)}'\ngemspec")
s.add_dependency "actionpack", "=2.3.2"
- s.add_development_dependency "rake", "=12.3.2"
+ s.add_development_dependency "rake", "=13.0.1"
end
- Dir.chdir(tmp.join("foo")) do
- bundle "install"
- # This should really be able to rely on $stderr, but, it's not written
- # right, so we can't. In fact, this is a bug negation test, and so it'll
- # ghost pass in future, and will only catch a regression if the message
- # doesn't change. Exit codes should be used correctly (they can be more
- # than just 0 and 1).
- output = bundle("install --deployment")
- expect(output).not_to match(/You have added to the Gemfile/)
- expect(output).not_to match(/You have deleted from the Gemfile/)
- expect(output).not_to match(/install in deployment mode after changing/)
- end
+ bundle "install", :dir => tmp.join("foo")
+ # This should really be able to rely on $stderr, but, it's not written
+ # right, so we can't. In fact, this is a bug negation test, and so it'll
+ # ghost pass in future, and will only catch a regression if the message
+ # doesn't change. Exit codes should be used correctly (they can be more
+ # than just 0 and 1).
+ bundle "config set --local deployment true"
+ output = bundle("install", :dir => tmp.join("foo"))
+ expect(output).not_to match(/You have added to the Gemfile/)
+ expect(output).not_to match(/You have deleted from the Gemfile/)
+ expect(output).not_to match(/install in deployment mode after changing/)
end
it "should match a lockfile without needing to re-resolve" do
@@ -139,12 +138,12 @@ RSpec.describe "bundle install from an existing gemspec" do
s.add_dependency "rack"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gemspec :path => '#{tmp.join("foo")}'
G
- bundle! "install", :verbose => true
+ bundle "install", :verbose => true
message = "Found no changes, using resolution from the lockfile"
expect(out.scan(message).size).to eq(1)
@@ -158,32 +157,29 @@ RSpec.describe "bundle install from an existing gemspec" do
s.add_development_dependency "thin"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gemspec :path => '#{tmp.join("foo")}'
G
- bundle! "install", :verbose => true
+ bundle "install", :verbose => true
message = "Found no changes, using resolution from the lockfile"
expect(out.scan(message).size).to eq(1)
end
- it "should match a lockfile on non-ruby platforms with a transitive platform dependency" do
- simulate_platform java
- simulate_ruby_engine "jruby"
-
+ it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby do
build_lib("foo", :path => tmp.join("foo")) do |s|
s.add_dependency "platform_specific"
end
- system_gems "platform_specific-1.0-java", :path => :bundle_path, :keep_path => true
+ system_gems "platform_specific-1.0-java", :path => default_bundle_path
- install_gemfile! <<-G
+ install_gemfile <<-G
gemspec :path => '#{tmp.join("foo")}'
G
- bundle! "update --bundler", :verbose => true
+ bundle "update --bundler", :verbose => true
expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 JAVA"
end
@@ -193,7 +189,7 @@ RSpec.describe "bundle install from an existing gemspec" do
s.write "raise 'ahh' unless Dir.pwd == '#{tmp.join("foo")}'"
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
gemspec :path => '#{tmp.join("foo")}'
G
expect(last_command.stdboth).not_to include("ahh")
@@ -201,7 +197,7 @@ RSpec.describe "bundle install from an existing gemspec" do
it "allows the gemspec to activate other gems" do
ENV["BUNDLE_PATH__SYSTEM"] = "true"
- # see https://github.com/bundler/bundler/issues/5409
+ # see https://github.com/rubygems/bundler/issues/5409
#
# issue was caused by rubygems having an unresolved gem during a require,
# so emulate that
@@ -213,7 +209,8 @@ RSpec.describe "bundle install from an existing gemspec" do
f.write "#{gemspec.strip}.tap { gem 'rack-obama'; require 'rack/obama' }"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gemspec
G
@@ -251,7 +248,7 @@ RSpec.describe "bundle install from an existing gemspec" do
build_gem "foo", "0.0.1"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "deps"
gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
@@ -259,20 +256,21 @@ RSpec.describe "bundle install from an existing gemspec" do
expect(the_bundle).to include_gems "foo 1.0.0"
- run! "Gem.finish_resolve; puts 'WIN'"
+ run "Gem.finish_resolve; puts 'WIN'"
expect(out).to eq("WIN")
end
- it "works with only_update_to_newer_versions" do
+ it "handles downgrades" do
build_lib "omg", "2.0", :path => lib_path("omg")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gemspec :path => "#{lib_path("omg")}"
G
build_lib "omg", "1.0", :path => lib_path("omg")
- bundle! :install, :env => { "BUNDLE_BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS" => "true" }
+ bundle :install
expect(the_bundle).to include_gems "omg 1.0"
end
@@ -284,7 +282,7 @@ RSpec.describe "bundle install from an existing gemspec" do
s.add_dependency "activesupport", ">= 1"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gemspec
G
@@ -295,7 +293,8 @@ RSpec.describe "bundle install from an existing gemspec" do
s.add_dependency "activesupport", ">= 1.0.1"
end
- bundle :install, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ bundle :install, :raise_on_error => false
expect(err).to include("changed")
end
@@ -333,6 +332,8 @@ RSpec.describe "bundle install from an existing gemspec" do
let(:platform) { "ruby" }
before do
+ skip "not installing for some reason" if Gem.win_platform?
+
build_lib("foo", :path => tmp.join("foo")) do |s|
s.add_dependency "rack", "=1.0.0"
end
@@ -365,13 +366,11 @@ RSpec.describe "bundle install from an existing gemspec" do
L
end
- context "using JRuby with explicit platform" do
- let(:platform) { "java" }
-
+ context "using JRuby with explicit platform", :jruby do
before do
create_file(
- tmp.join("foo", "foo-#{platform}.gemspec"),
- build_spec("foo", "1.0", platform) do
+ tmp.join("foo", "foo-java.gemspec"),
+ build_spec("foo", "1.0", "java") do
dep "rack", "=1.0.0"
@spec.authors = "authors"
@spec.summary = "summary"
@@ -380,27 +379,17 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "should install" do
- simulate_ruby_engine "jruby" do
- simulate_platform "java" do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
+ results = bundle "install", :artifice => "endpoint"
+ expect(results).to include("Installing rack 1.0.0")
+ expect(the_bundle).to include_gems "rack 1.0.0"
end
end
- context "using JRuby" do
- let(:platform) { "java" }
-
+ context "using JRuby", :jruby do
it "should install" do
- simulate_ruby_engine "jruby" do
- simulate_platform "java" do
- results = bundle "install", :artifice => "endpoint"
- expect(results).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
+ results = bundle "install", :artifice => "endpoint"
+ expect(results).to include("Installing rack 1.0.0")
+ expect(the_bundle).to include_gems "rack 1.0.0"
end
end
@@ -425,7 +414,7 @@ RSpec.describe "bundle install from an existing gemspec" do
end
end
- build_lib "foo", :path => "." do |s|
+ build_lib "foo", :path => bundled_app do |s|
if platform_specific_type == :runtime
s.add_runtime_dependency dependency
elsif platform_specific_type == :development
@@ -435,14 +424,13 @@ RSpec.describe "bundle install from an existing gemspec" do
end
end
- %w[ruby jruby].each do |platform|
- simulate_platform(platform) do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gemspec
- G
- end
- end
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gemspec
+ G
+
+ simulate_platform("ruby") { bundle "install" }
+ simulate_platform("jruby") { bundle "install" }
end
context "on ruby" do
@@ -560,7 +548,7 @@ RSpec.describe "bundle install from an existing gemspec" do
it "installs the ruby platform gemspec" do
simulate_platform "ruby"
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
G
@@ -568,10 +556,11 @@ RSpec.describe "bundle install from an existing gemspec" do
expect(the_bundle).to include_gems "foo 1.0.0", "rack 1.0.0"
end
- it "installs the ruby platform gemspec and skips dev deps with --without development" do
+ it "installs the ruby platform gemspec and skips dev deps with `without development` configured" do
simulate_platform "ruby"
- install_gemfile! <<-G, forgotten_command_line_options(:without => "development")
+ bundle "config set --local without development"
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
G
@@ -580,4 +569,57 @@ RSpec.describe "bundle install from an existing gemspec" do
expect(the_bundle).not_to include_gem "rack"
end
end
+
+ context "with multiple platforms and resolving for more specific platforms" do
+ before do
+ build_lib("chef", :path => tmp.join("chef")) do |s|
+ s.version = "17.1.17"
+ s.write "chef-universal-mingw32.gemspec", build_spec("chef", "17.1.17", "universal-mingw32") {|sw| sw.runtime "win32-api", "~> 1.5.3" }.first.to_ruby
+ end
+ end
+
+ it "does not remove the platform specific specs from the lockfile when updating" do
+ build_repo4 do
+ build_gem "win32-api", "1.5.3" do |s|
+ s.platform = "universal-mingw32"
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gemspec :path => "../chef"
+ G
+
+ initial_lockfile = <<~L
+ PATH
+ remote: ../chef
+ specs:
+ chef (17.1.17)
+ chef (17.1.17-universal-mingw32)
+ win32-api (~> 1.5.3)
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ win32-api (1.5.3-universal-mingw32)
+
+ PLATFORMS
+ ruby
+ x64-mingw32
+ x86-mingw32
+
+ DEPENDENCIES
+ chef!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile initial_lockfile
+
+ bundle "update"
+
+ expect(lockfile).to eq initial_lockfile
+ end
+ end
end
diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb
index c5ea2c202d..150fcf2c42 100644
--- a/spec/bundler/install/gemfile/git_spec.rb
+++ b/spec/bundler/install/gemfile/git_spec.rb
@@ -30,11 +30,15 @@ RSpec.describe "bundle install with git sources" do
expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes :size => 1
end
- it "caches the git repo globally" do
+ it "caches the git repo globally and properly uses the cached repo on the next invocation" do
simulate_new_machine
- bundle! "config set global_gem_cache true"
- bundle! :install
+ bundle "config set global_gem_cache true"
+ bundle :install
expect(Dir["#{home}/.bundle/cache/git/foo-1.0-*"]).to have_attributes :size => 1
+
+ bundle "install --verbose"
+ expect(err).to be_empty
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")}")
end
it "caches the evaluated gemspec" do
@@ -57,22 +61,19 @@ RSpec.describe "bundle install with git sources" do
it "does not update the git source implicitly" do
update_git "foo"
- in_app_root2 do
- install_gemfile bundled_app2("Gemfile"), <<-G
- git "#{lib_path("foo-1.0")}" do
- gem 'foo'
- end
- G
- end
+ install_gemfile bundled_app2("Gemfile"), <<-G, :dir => bundled_app2
+ source "#{file_uri_for(gem_repo1)}"
+ git "#{lib_path("foo-1.0")}" do
+ gem 'foo'
+ end
+ G
- in_app_root do
- run <<-RUBY
- require 'foo'
- puts "fail" if defined?(FOO_PREV_REF)
- RUBY
+ run <<-RUBY
+ require 'foo'
+ puts "fail" if defined?(FOO_PREV_REF)
+ RUBY
- expect(out).to be_empty
- end
+ expect(out).to be_empty
end
it "sets up git gem executables on the path" do
@@ -83,11 +84,12 @@ RSpec.describe "bundle install with git sources" do
it "complains if pinned specs don't exist in the git repo" do
build_git "foo"
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", "1.1", :git => "#{lib_path("foo-1.0")}"
G
- expect(err).to include("The source contains 'foo' at: 1.0")
+ expect(err).to include("The source contains the following versions of 'foo': 1.0")
end
it "complains with version and platform if pinned specs don't exist in the git repo" do
@@ -97,13 +99,14 @@ RSpec.describe "bundle install with git sources" do
s.platform = "java"
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
platforms :jruby do
gem "only_java", "1.2", :git => "#{lib_path("only_java-1.0-java")}"
end
G
- expect(err).to include("The source contains 'only_java' at: 1.0 java")
+ expect(err).to include("The source contains the following versions of 'only_java': 1.0 java")
end
it "complains with multiple versions and platforms if pinned specs don't exist in the git repo" do
@@ -118,30 +121,33 @@ RSpec.describe "bundle install with git sources" do
s.write "only_java1-0.gemspec", File.read("#{lib_path("only_java-1.0-java")}/only_java.gemspec")
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
platforms :jruby do
gem "only_java", "1.2", :git => "#{lib_path("only_java-1.1-java")}"
end
G
- expect(err).to include("The source contains 'only_java' at: 1.0 java, 1.1 java")
+ expect(err).to include("The source contains the following versions of 'only_java': 1.0 java, 1.1 java")
end
it "still works after moving the application directory" do
- bundle "install --path vendor/bundle"
+ bundle "config set --local path vendor/bundle"
+ bundle "install"
+
FileUtils.mv bundled_app, tmp("bundled_app.bck")
- Dir.chdir tmp("bundled_app.bck")
- expect(the_bundle).to include_gems "foo 1.0"
+ expect(the_bundle).to include_gems "foo 1.0", :dir => tmp("bundled_app.bck")
end
it "can still install after moving the application directory" do
- bundle "install --path vendor/bundle"
+ bundle "config set --local path vendor/bundle"
+ bundle "install"
+
FileUtils.mv bundled_app, tmp("bundled_app.bck")
update_git "foo", "1.1", :path => lib_path("foo-1.0")
- Dir.chdir tmp("bundled_app.bck")
gemfile tmp("bundled_app.bck/Gemfile"), <<-G
source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}" do
@@ -151,9 +157,9 @@ RSpec.describe "bundle install with git sources" do
gem "rack", "1.0"
G
- bundle "update foo"
+ bundle "update foo", :dir => tmp("bundled_app.bck")
- expect(the_bundle).to include_gems "foo 1.1", "rack 1.0"
+ expect(the_bundle).to include_gems "foo 1.1", "rack 1.0", :dir => tmp("bundled_app.bck")
end
end
@@ -185,6 +191,7 @@ RSpec.describe "bundle install with git sources" do
it "works" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}", :ref => "#{@revision}" do
gem "foo"
end
@@ -200,6 +207,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)}"
git "#{lib_path("foo-1.0")}", :ref => #{@revision.to_sym.inspect} do
gem "foo"
end
@@ -220,23 +228,22 @@ RSpec.describe "bundle install with git sources" do
s.write("lib/foo.rb", "raise 'FAIL'")
end
- Dir.chdir(lib_path("foo-1.0")) do
- `git update-ref -m "Bundler Spec!" refs/bundler/1 master~1`
- end
+ sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0"))
# want to ensure we don't fallback to HEAD
update_git "foo", :path => lib_path("foo-1.0"), :branch => "rando" do |s|
- s.write("lib/foo.rb", "raise 'FAIL'")
+ s.write("lib/foo.rb", "raise 'FAIL_FROM_RANDO'")
end
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}", :ref => "refs/bundler/1" do
gem "foo"
end
G
expect(err).to be_empty
- run! <<-RUBY
+ run <<-RUBY
require 'foo'
puts "WIN" if defined?(FOO)
RUBY
@@ -245,7 +252,8 @@ RSpec.describe "bundle install with git sources" do
end
it "works when the revision is a non-head ref and it was previously downloaded" do
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
@@ -256,23 +264,22 @@ RSpec.describe "bundle install with git sources" do
s.write("lib/foo.rb", "raise 'FAIL'")
end
- Dir.chdir(lib_path("foo-1.0")) do
- `git update-ref -m "Bundler Spec!" refs/bundler/1 master~1`
- end
+ sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0"))
# want to ensure we don't fallback to HEAD
update_git "foo", :path => lib_path("foo-1.0"), :branch => "rando" do |s|
- s.write("lib/foo.rb", "raise 'FAIL'")
+ s.write("lib/foo.rb", "raise 'FAIL_FROM_RANDO'")
end
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}", :ref => "refs/bundler/1" do
gem "foo"
end
G
expect(err).to be_empty
- run! <<-RUBY
+ run <<-RUBY
require 'foo'
puts "WIN" if defined?(FOO)
RUBY
@@ -281,24 +288,21 @@ RSpec.describe "bundle install with git sources" do
end
it "does not download random non-head refs" do
- Dir.chdir(lib_path("foo-1.0")) do
- sys_exec!('git update-ref -m "Bundler Spec!" refs/bundler/1 master~1')
- end
+ sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 master~1", :dir => lib_path("foo-1.0"))
- bundle! "config set global_gem_cache true"
+ bundle "config set global_gem_cache true"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
G
# ensure we also git fetch after cloning
- bundle! :update, :all => true
+ bundle :update, :all => true
- Dir.chdir(Dir[home(".bundle/cache/git/foo-*")].first) do
- sys_exec("git ls-remote .")
- end
+ sys_exec("git ls-remote .", :dir => Dir[home(".bundle/cache/git/foo-*")].first)
expect(out).not_to include("refs/bundler/1")
end
@@ -307,12 +311,12 @@ RSpec.describe "bundle install with git sources" do
describe "when specifying a branch" do
let(:branch) { "branch" }
let(:repo) { build_git("foo").path }
- before(:each) do
- update_git("foo", :path => repo, :branch => branch)
- end
it "works" do
+ update_git("foo", :path => repo, :branch => branch)
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{repo}", :branch => #{branch.dump} do
gem "foo"
end
@@ -324,7 +328,12 @@ RSpec.describe "bundle install with git sources" do
context "when the branch starts with a `#`" do
let(:branch) { "#149/redirect-url-fragment" }
it "works" do
+ skip "git does not accept this" if Gem.win_platform?
+
+ update_git("foo", :path => repo, :branch => branch)
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{repo}", :branch => #{branch.dump} do
gem "foo"
end
@@ -337,7 +346,12 @@ RSpec.describe "bundle install with git sources" do
context "when the branch includes quotes" do
let(:branch) { %('") }
it "works" do
+ skip "git does not accept this" if Gem.win_platform?
+
+ update_git("foo", :path => repo, :branch => branch)
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{repo}", :branch => #{branch.dump} do
gem "foo"
end
@@ -351,12 +365,12 @@ RSpec.describe "bundle install with git sources" do
describe "when specifying a tag" do
let(:tag) { "tag" }
let(:repo) { build_git("foo").path }
- before(:each) do
- update_git("foo", :path => repo, :tag => tag)
- end
it "works" do
+ update_git("foo", :path => repo, :tag => tag)
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -368,7 +382,12 @@ RSpec.describe "bundle install with git sources" do
context "when the tag starts with a `#`" do
let(:tag) { "#149/redirect-url-fragment" }
it "works" do
+ skip "git does not accept this" if Gem.win_platform?
+
+ update_git("foo", :path => repo, :tag => tag)
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -381,7 +400,12 @@ RSpec.describe "bundle install with git sources" do
context "when the tag includes quotes" do
let(:tag) { %('") }
it "works" do
+ skip "git does not accept this" if Gem.win_platform?
+
+ update_git("foo", :path => repo, :tag => tag)
+
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -406,8 +430,8 @@ RSpec.describe "bundle install with git sources" do
gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
G
- bundle! %(config set local.rack #{lib_path("local-rack")})
- bundle! :install
+ bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle :install
run "require 'rack'"
expect(out).to eq("LOCAL")
@@ -442,14 +466,14 @@ RSpec.describe "bundle install with git sources" do
s.write "lib/rack.rb", "puts :LOCAL"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
G
- bundle! %(config set local.rack #{lib_path("local-rack")})
- bundle! :install
- run! "require 'rack'"
+ bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle :install
+ run "require 'rack'"
expect(out).to eq("LOCAL")
end
@@ -463,7 +487,7 @@ RSpec.describe "bundle install with git sources" do
gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
G
- lockfile0 = File.read(bundled_app("Gemfile.lock"))
+ lockfile0 = File.read(bundled_app_lock)
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
update_git "rack", "0.8", :path => lib_path("local-rack") do |s|
@@ -473,7 +497,7 @@ RSpec.describe "bundle install with git sources" do
bundle %(config set local.rack #{lib_path("local-rack")})
run "require 'rack'"
- lockfile1 = File.read(bundled_app("Gemfile.lock"))
+ lockfile1 = File.read(bundled_app_lock)
expect(lockfile1).not_to eq(lockfile0)
end
@@ -485,7 +509,7 @@ RSpec.describe "bundle install with git sources" do
gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
G
- lockfile0 = File.read(bundled_app("Gemfile.lock"))
+ lockfile0 = File.read(bundled_app_lock)
FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
update_git "rack", "0.8", :path => lib_path("local-rack")
@@ -493,7 +517,7 @@ RSpec.describe "bundle install with git sources" do
bundle %(config set local.rack #{lib_path("local-rack")})
bundle :install
- lockfile1 = File.read(bundled_app("Gemfile.lock"))
+ lockfile1 = File.read(bundled_app_lock)
expect(lockfile1).not_to eq(lockfile0)
end
@@ -506,7 +530,7 @@ RSpec.describe "bundle install with git sources" do
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/)
solution = "config unset local.rack"
@@ -528,7 +552,7 @@ RSpec.describe "bundle install with git sources" do
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/Cannot use local override for rack-0.8 at #{Regexp.escape(lib_path('local-rack').to_s)} because :branch is not specified in Gemfile/)
solution = "config unset local.rack"
@@ -570,7 +594,7 @@ RSpec.describe "bundle install with git sources" do
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/is using branch another but Gemfile specifies master/)
end
@@ -587,9 +611,27 @@ RSpec.describe "bundle install with git sources" do
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/The Gemfile lock is pointing to revision \w+/)
end
+
+ it "does not explode on invalid revision on install" do
+ build_git "rack", "0.8"
+
+ build_git "rack", "0.8", :path => lib_path("local-rack") do |s|
+ s.write "lib/rack.rb", "puts :LOCAL"
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ G
+
+ bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set disable_local_revision_check true)
+ bundle :install
+ expect(out).to match(/Bundle complete!/)
+ end
end
describe "specified inline" do
@@ -679,6 +721,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)}"
path "#{lib_path("hi2u")}" do
gem "omg"
gem "hi2u"
@@ -695,6 +738,7 @@ RSpec.describe "bundle install with git sources" do
update_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{@revision}"
G
@@ -759,6 +803,7 @@ RSpec.describe "bundle install with git sources" do
build_git "foo", "1.0"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", "1.0", :git => "#{lib_path("foo-1.0")}"
G
@@ -780,10 +825,11 @@ 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)}"
gem "foo", "1.0", :git => "omgomg"
G
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to include("Git error:")
expect(err).to include("fatal")
@@ -794,6 +840,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)}"
gem "foo", :git => "#{lib_path("foo space-1.0")}"
G
@@ -804,6 +851,7 @@ RSpec.describe "bundle install with git sources" do
build_git "forced", "1.0"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("forced-1.0")}" do
gem 'forced'
end
@@ -817,28 +865,22 @@ RSpec.describe "bundle install with git sources" do
bundle "update", :all => true
expect(the_bundle).to include_gems "forced 1.1"
- Dir.chdir(lib_path("forced-1.0")) do
- `git reset --hard HEAD^`
- end
+ sys_exec("git reset --hard HEAD^", :dir => lib_path("forced-1.0"))
bundle "update", :all => true
expect(the_bundle).to include_gems "forced 1.0"
end
it "ignores submodules if :submodule is not passed" do
- # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
- system(*%W[git config --global protocol.file.allow always])
-
build_git "submodule", "1.0"
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
end
- Dir.chdir(lib_path("has_submodule-1.0")) do
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0"
- `git commit -m "submodulator"`
- end
+ sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0")
+ sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0")
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
@@ -849,19 +891,15 @@ RSpec.describe "bundle install with git sources" do
end
it "handles repos with submodules" do
- # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
- system(*%W[git config --global protocol.file.allow always])
-
build_git "submodule", "1.0"
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
end
- Dir.chdir(lib_path("has_submodule-1.0")) do
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0"
- `git commit -m "submodulator"`
- end
+ sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0")
+ sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
@@ -870,10 +908,30 @@ RSpec.describe "bundle install with git sources" do
expect(the_bundle).to include_gems "has_submodule 1.0"
end
+ it "does not warn when deiniting submodules" do
+ build_git "submodule", "1.0"
+ build_git "has_submodule", "1.0"
+
+ sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0")
+ sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0")
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ git "#{lib_path("has_submodule-1.0")}" do
+ gem "has_submodule"
+ end
+ G
+ expect(err).to be_empty
+
+ expect(the_bundle).to include_gems "has_submodule 1.0"
+ expect(the_bundle).to_not include_gems "submodule 1.0"
+ end
+
it "handles implicit updates when modifying the source info" do
git = build_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
@@ -883,6 +941,7 @@ RSpec.describe "bundle install with git sources" do
update_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}", :ref => "#{git.ref_for("HEAD^")}" do
gem "foo"
end
@@ -900,6 +959,7 @@ RSpec.describe "bundle install with git sources" do
build_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -913,12 +973,12 @@ RSpec.describe "bundle install with git sources" do
build_git "foo"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
bundle "install"
bundle "install"
- expect(exitstatus).to eq(0) if exitstatus
end
it "prints a friendly error if a file blocks the git repo" do
@@ -927,11 +987,12 @@ RSpec.describe "bundle install with git sources" do
FileUtils.mkdir_p(default_bundle_path)
FileUtils.touch(default_bundle_path("bundler"))
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- expect(exitstatus).to_not eq(0) if exitstatus
+ expect(exitstatus).to_not eq(0)
expect(err).to include("Bundler could not install a gem because it " \
"needs to create a directory, but a file exists " \
"- #{default_bundle_path("bundler")}")
@@ -945,11 +1006,12 @@ RSpec.describe "bundle install with git sources" do
build_git "bar", :path => lib_path("nested")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("nested")}"
gem "bar", :git => "#{lib_path("nested")}"
G
- expect(File.read(bundled_app("Gemfile.lock")).scan("GIT").size).to eq(1)
+ expect(File.read(bundled_app_lock).scan("GIT").size).to eq(1)
end
describe "switching sources" do
@@ -1002,6 +1064,7 @@ 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"))}"
G
@@ -1009,8 +1072,8 @@ RSpec.describe "bundle install with git sources" do
update_git "valim"
new_revision = revision_for(lib_path("valim-1.0"))
- old_lockfile = File.read(bundled_app("Gemfile.lock"))
- lockfile(bundled_app("Gemfile.lock"), old_lockfile.gsub(/revision: #{old_revision}/, "revision: #{new_revision}"))
+ old_lockfile = File.read(bundled_app_lock)
+ lockfile(bundled_app_lock, old_lockfile.gsub(/revision: #{old_revision}/, "revision: #{new_revision}"))
bundle "install"
@@ -1027,18 +1090,20 @@ 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}"
G
expect(out).to_not match(/Revision.*does not exist/)
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :ref => "deadbeef"
G
expect(err).to include("Revision deadbeef does not exist in the repository")
end
end
- describe "bundle install --deployment with git sources" do
+ describe "bundle install with deployment mode configured and git sources" do
it "works" do
build_git "valim", :path => lib_path("valim")
@@ -1049,7 +1114,8 @@ RSpec.describe "bundle install with git sources" do
simulate_new_machine
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ bundle :install
end
end
@@ -1057,6 +1123,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)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1076,6 +1143,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)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1095,6 +1163,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)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1106,8 +1175,7 @@ RSpec.describe "bundle install with git sources" do
H
end
- bundle :install,
- :requires => [lib_path("install_hooks.rb")]
+ bundle :install, :requires => [lib_path("install_hooks.rb")], :raise_on_error => false
expect(err).to include("failed for foo-1.0")
end
end
@@ -1139,7 +1207,7 @@ RSpec.describe "bundle install with git sources" do
R
expect(out).to eq("YES")
- run! <<-R
+ run <<-R
puts $:.grep(/ext/)
R
expect(out).to include(Pathname.glob(default_bundle_path("bundler/gems/extensions/**/foo-1.0-*")).first.to_s)
@@ -1156,16 +1224,15 @@ RSpec.describe "bundle install with git sources" do
end
2.times do |i|
- Dir.chdir(git_reader.path) do
- File.open("ext/foo.c", "w") do |file|
- file.write <<-C
- #include "ruby.h"
- VALUE foo() { return INT2FIX(#{i}); }
- void Init_foo() { rb_define_global_function("foo", &foo, 0); }
- C
- end
- `git commit -m "commit for iteration #{i}" ext/foo.c`
+ File.open(git_reader.path.join("ext/foo.c"), "w") do |file|
+ file.write <<-C
+ #include "ruby.h"
+ VALUE foo() { return INT2FIX(#{i}); }
+ void Init_foo() { rb_define_global_function("foo", &foo, 0); }
+ C
end
+ sys_exec("git commit -m \"commit for iteration #{i}\" ext/foo.c", :dir => git_reader.path)
+
git_commit_sha = git_reader.ref_for("HEAD")
install_gemfile <<-G
@@ -1193,7 +1260,7 @@ RSpec.describe "bundle install with git sources" do
RUBY
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1228,7 +1295,7 @@ In Gemfile:
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- run! <<-R
+ run <<-R
require 'foo'
puts FOO
R
@@ -1241,7 +1308,7 @@ In Gemfile:
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- run! <<-R
+ run <<-R
require 'foo'
puts FOO
R
@@ -1270,7 +1337,7 @@ In Gemfile:
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- run! <<-R
+ run <<-R
require 'foo'
puts FOO
R
@@ -1284,7 +1351,7 @@ In Gemfile:
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- run! <<-R
+ run <<-R
require 'foo'
puts FOO
R
@@ -1312,14 +1379,15 @@ In Gemfile:
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- run! <<-R
+ run <<-R
require 'foo'
puts FOO
R
+ installed_time = out
+
update_git("foo", :branch => "branch2")
- installed_time = out
expect(installed_time).to match(/\A\d+\.\d+\z/)
install_gemfile <<-G
@@ -1327,7 +1395,7 @@ In Gemfile:
gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "branch2"
G
- run! <<-R
+ run <<-R
require 'foo'
puts FOO
R
@@ -1336,9 +1404,9 @@ In Gemfile:
installed_time = out
update_git("foo")
- bundle! "update foo"
+ bundle "update foo"
- run! <<-R
+ run <<-R
require 'foo'
puts FOO
R
@@ -1362,24 +1430,61 @@ In Gemfile:
end
G
- expect(exitstatus).to eq(0) if exitstatus
expect(ENV["GIT_DIR"]).to eq("bar")
expect(ENV["GIT_WORK_TREE"]).to eq("bar")
end
end
describe "without git installed" do
- it "prints a better error message" do
+ it "prints a better error message when installing" do
+ build_git "foo"
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
+ gem "rake", git: "https://github.com/ruby/rake"
+ G
+
+ lockfile <<-L
+ GIT
+ remote: https://github.com/ruby/rake
+ revision: 5c60da8644a9e4f655e819252e3b6ca77f42b7af
+ specs:
+ rake (13.0.6)
+
+ GEM
+ remote: https://rubygems.org/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rake!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ with_path_as("") do
+ bundle "install", :raise_on_error => false
+ end
+ expect(err).
+ to include("You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git")
+ end
+
+ it "prints a better error message when updating" do
build_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
with_path_as("") do
- bundle "update", :all => true
+ bundle "update", :all => true, :raise_on_error => false
end
expect(err).
to include("You need to install git to be able to use gems from git repositories. For help installing git, please refer to GitHub's tutorial at https://help.github.com/articles/set-up-git")
@@ -1389,6 +1494,7 @@ In Gemfile:
build_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
@@ -1397,14 +1503,14 @@ In Gemfile:
bundle :cache
simulate_new_machine
- bundle! "install", :env => { "PATH" => "" }
+ bundle "install", :env => { "PATH" => "" }
expect(out).to_not include("You need to install git to be able to use gems from git repositories.")
end
end
describe "when the git source is overridden with a local git repo" do
before do
- bundle! "config set --global local.foo #{lib_path("foo")}"
+ bundle "config set --global local.foo #{lib_path("foo")}"
end
describe "and git output is colorized" do
@@ -1418,6 +1524,7 @@ In Gemfile:
build_git "foo", "1.0", :path => lib_path("foo")
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo")}", :branch => "master"
G
@@ -1432,7 +1539,8 @@ In Gemfile:
let(:credentials) { "user1:password1" }
it "does not display the password" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
git "https://#{credentials}@github.com/company/private-repo" do
gem "foo"
end
@@ -1447,7 +1555,8 @@ In Gemfile:
let(:credentials) { "oauth_token" }
it "displays the oauth scheme but not the oauth token" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
git "https://#{credentials}:x-oauth-basic@github.com/company/private-repo" do
gem "foo"
end
diff --git a/spec/bundler/install/gemfile/groups_spec.rb b/spec/bundler/install/gemfile/groups_spec.rb
index 63be1a4e43..c92b5dcc57 100644
--- a/spec/bundler/install/gemfile/groups_spec.rb
+++ b/spec/bundler/install/gemfile/groups_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe "bundle install with groups" do
end
end
- describe "installing --without" do
+ describe "without option" do
describe "with gems assigned to a single group" do
before :each do
gemfile <<-G
@@ -86,30 +86,59 @@ RSpec.describe "bundle install with groups" do
end
it "installs gems in the default group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
+ bundle "config set --local without emo"
+ bundle :install
+ expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
+ end
+
+ it "respects global `without` configuration, and saves it locally", :bundler => "< 3" do
+ bundle "config set without emo"
+ bundle :install
expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
+ bundle "config list"
+ expect(out).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 "respects global `without` configuration, but does not save it locally", :bundler => "3" do
+ bundle "config set without emo"
+ bundle :install
+ expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
+ bundle "config list"
+ expect(out).not_to include("Set for your local app (#{bundled_app(".bundle/config")}): [:emo]")
+ expect(out).to include("Set for the current user (#{home(".bundle/config")}): [:emo]")
+ end
+
+ it "allows running application where groups where configured by a different user", :bundler => "< 3" do
+ bundle "config set without emo"
+ bundle :install
+ bundle "exec ruby -e 'puts 42'", :env => { "BUNDLE_USER_HOME" => tmp("new_home").to_s }
+ expect(out).to include("42")
end
it "does not install gems from the excluded group" do
- bundle :install, :without => "emo"
+ bundle "config set --local without emo"
+ bundle :install
expect(the_bundle).not_to include_gems "activesupport 2.3.5", :groups => [:default]
end
- it "does not install gems from the previously excluded group" do
- bundle :install, forgotten_command_line_options(:without => "emo")
+ it "remembers previous exclusion with `--without`", :bundler => "< 3" do
+ bundle "install --without emo"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
bundle :install
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
end
it "does not say it installed gems from the excluded group" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
+ bundle "config set --local without emo"
+ bundle :install
expect(out).not_to include("activesupport")
end
it "allows Bundler.setup for specific groups" do
- bundle :install, forgotten_command_line_options(:without => "emo")
- run!("require 'rack'; puts RACK", :default)
+ bundle "config set --local without emo"
+ bundle :install
+ run("require 'rack'; puts RACK", :default)
expect(out).to eq("1.0.0")
end
@@ -122,20 +151,11 @@ RSpec.describe "bundle install with groups" do
end
G
- bundle :install, forgotten_command_line_options(:without => "emo")
+ bundle "config set --local without emo"
+ bundle :install
expect(the_bundle).to include_gems "activesupport 2.3.2", :groups => [:default]
end
- it "still works on a different machine and excludes gems" do
- bundle :install, forgotten_command_line_options(:without => "emo")
-
- simulate_new_machine
- bundle :install, forgotten_command_line_options(:without => "emo")
-
- expect(the_bundle).to include_gems "rack 1.0.0", :groups => [:default]
- expect(the_bundle).not_to include_gems "activesupport 2.3.5", :groups => [:default]
- end
-
it "still works when BUNDLE_WITHOUT is set" do
ENV["BUNDLE_WITHOUT"] = "emo"
@@ -148,15 +168,15 @@ RSpec.describe "bundle install with groups" do
ENV["BUNDLE_WITHOUT"] = nil
end
- it "clears without when passed an empty list" do
- bundle :install, forgotten_command_line_options(:without => "emo")
+ it "clears --without when passed an empty list", :bundler => "< 3" do
+ bundle "install --without emo"
- bundle :install, forgotten_command_line_options(:without => "")
+ bundle "install --without ''"
expect(the_bundle).to include_gems "activesupport 2.3.5"
end
- it "doesn't clear without when nothing is passed" do
- bundle :install, forgotten_command_line_options(:without => "emo")
+ it "doesn't clear without when nothing is passed", :bundler => "< 3" do
+ bundle "install --without emo"
bundle :install
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
@@ -167,45 +187,46 @@ RSpec.describe "bundle install with groups" do
expect(the_bundle).not_to include_gems "thin 1.0"
end
- it "does install gems from the optional group when requested" do
- bundle :install, forgotten_command_line_options(:with => "debugging")
+ it "installs gems from the optional group when requested" do
+ bundle "config set --local with debugging"
+ bundle :install
expect(the_bundle).to include_gems "thin 1.0"
end
- it "does install gems from the previously requested group" do
- bundle :install, forgotten_command_line_options(:with => "debugging")
+ it "installs gems from the previously requested group", :bundler => "< 3" do
+ bundle "install --with debugging"
expect(the_bundle).to include_gems "thin 1.0"
bundle :install
expect(the_bundle).to include_gems "thin 1.0"
end
- it "does install gems from the optional groups requested with BUNDLE_WITH" do
+ it "installs gems from the optional groups requested with BUNDLE_WITH" do
ENV["BUNDLE_WITH"] = "debugging"
bundle :install
expect(the_bundle).to include_gems "thin 1.0"
ENV["BUNDLE_WITH"] = nil
end
- it "clears with when passed an empty list" do
- bundle :install, forgotten_command_line_options(:with => "debugging")
- bundle :install, forgotten_command_line_options(:with => "")
+ it "clears --with when passed an empty list", :bundler => "< 3" do
+ bundle "install --with debugging"
+ bundle "install --with ''"
expect(the_bundle).not_to include_gems "thin 1.0"
end
- it "does remove groups from without when passed at --with", :bundler => "< 3" do
- bundle :install, forgotten_command_line_options(:without => "emo")
- bundle :install, forgotten_command_line_options(:with => "emo")
+ it "removes groups from without when passed at --with", :bundler => "< 3" do
+ bundle "config set --local without emo"
+ bundle "install --with emo"
expect(the_bundle).to include_gems "activesupport 2.3.5"
end
- it "does remove groups from with when passed at --without", :bundler => "< 3" do
- bundle :install, forgotten_command_line_options(:with => "debugging")
- bundle :install, forgotten_command_line_options(:without => "debugging")
+ it "removes groups from with when passed at --without", :bundler => "< 3" do
+ bundle "config set --local with debugging"
+ bundle "install --without debugging", :raise_on_error => false
expect(the_bundle).not_to include_gem "thin 1.0"
end
it "errors out when passing a group to with and without via CLI flags", :bundler => "< 3" do
- bundle :install, forgotten_command_line_options(:with => "emo debugging", :without => "emo")
+ bundle "install --with emo debugging --without emo", :raise_on_error => false
expect(last_command).to be_failure
expect(err).to include("The offending groups are: emo")
end
@@ -213,29 +234,31 @@ RSpec.describe "bundle install with groups" do
it "allows the BUNDLE_WITH setting to override BUNDLE_WITHOUT" do
ENV["BUNDLE_WITH"] = "debugging"
- bundle! :install
+ bundle :install
expect(the_bundle).to include_gem "thin 1.0"
ENV["BUNDLE_WITHOUT"] = "debugging"
expect(the_bundle).to include_gem "thin 1.0"
- bundle! :install
+ bundle :install
expect(the_bundle).to include_gem "thin 1.0"
end
- it "can add and remove a group at the same time" do
- bundle :install, forgotten_command_line_options(:with => "debugging", :without => "emo")
+ it "can add and remove a group at the same time", :bundler => "< 3" do
+ bundle "install --with debugging --without emo"
expect(the_bundle).to include_gems "thin 1.0"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
end
- it "does have no effect when listing a not optional group in with" do
- bundle :install, forgotten_command_line_options(:with => "emo")
+ it "has no effect when listing a not optional group in with" do
+ bundle "config set --local with emo"
+ bundle :install
expect(the_bundle).to include_gems "activesupport 2.3.5"
end
- it "does have no effect when listing an optional group in without" do
- bundle :install, forgotten_command_line_options(:without => "debugging")
+ it "has no effect when listing an optional group in without" do
+ bundle "config set --local without debugging"
+ bundle :install
expect(the_bundle).not_to include_gems "thin 1.0"
end
end
@@ -252,12 +275,14 @@ RSpec.describe "bundle install with groups" do
end
it "installs gems in the default group" do
- bundle! :install, forgotten_command_line_options(:without => "emo lolercoaster")
+ bundle "config set --local without emo lolercoaster"
+ bundle :install
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "installs the gem if any of its groups are installed" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
+ bundle "config set --local without emo"
+ bundle :install
expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
end
@@ -277,23 +302,21 @@ RSpec.describe "bundle install with groups" do
G
end
- it "installs the gem w/ option --without emo" do
- bundle :install, forgotten_command_line_options(:without => "emo")
+ it "installs the gem unless all groups are excluded" do
+ bundle "config set --local without emo"
+ bundle :install
expect(the_bundle).to include_gems "activesupport 2.3.5"
- end
- it "installs the gem w/ option --without lolercoaster" do
- bundle :install, forgotten_command_line_options(:without => "lolercoaster")
+ bundle "config set --local without lolercoaster"
+ bundle :install
expect(the_bundle).to include_gems "activesupport 2.3.5"
- end
- it "does not install the gem w/ option --without emo lolercoaster" do
- bundle :install, forgotten_command_line_options(:without => "emo lolercoaster")
+ bundle "config set --local without emo lolercoaster"
+ bundle :install
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- end
- it "does not install the gem w/ option --without 'emo lolercoaster'" do
- bundle :install, forgotten_command_line_options(:without => "'emo lolercoaster'")
+ bundle "config set --local without 'emo lolercoaster'"
+ bundle :install
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
end
end
@@ -313,12 +336,14 @@ RSpec.describe "bundle install with groups" do
end
it "installs gems in the default group" do
- bundle! :install, forgotten_command_line_options(:without => "emo lolercoaster")
+ bundle "config set --local without emo lolercoaster"
+ bundle :install
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "installs the gem if any of its groups are installed" do
- bundle! :install, forgotten_command_line_options(:without => "emo")
+ bundle "config set --local without emo"
+ bundle :install
expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
end
end
@@ -333,7 +358,7 @@ RSpec.describe "bundle install with groups" do
G
ruby <<-R
- require "#{lib_dir}/bundler"
+ require "#{entrypoint}"
Bundler.setup :default
Bundler.require :default
puts RACK
@@ -349,19 +374,21 @@ RSpec.describe "bundle install with groups" do
end
end
- describe "when locked and installed with --without" do
+ describe "when locked and installed with `without` option" do
before(:each) do
build_repo2
- system_gems "rack-0.9.1" do
- install_gemfile <<-G, forgotten_command_line_options(:without => "rack")
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- group :rack do
- gem "rack_middleware"
- end
- G
- end
+ system_gems "rack-0.9.1"
+
+ bundle "config set --local without rack"
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "rack"
+
+ group :rack do
+ gem "rack_middleware"
+ end
+ G
end
it "uses the correct versions even if --without was used on the original" do
@@ -377,7 +404,8 @@ RSpec.describe "bundle install with groups" do
it "does not hit the remote a second time" do
FileUtils.rm_rf gem_repo2
- bundle! :install, forgotten_command_line_options(:without => "rack").merge(:verbose => true)
+ bundle "config set --local without rack"
+ bundle :install, :verbose => true
expect(last_command.stdboth).not_to match(/fetching/i)
end
end
diff --git a/spec/bundler/install/gemfile/install_if.rb b/spec/bundler/install/gemfile/install_if.rb
deleted file mode 100644
index bfdd8fbae8..0000000000
--- a/spec/bundler/install/gemfile/install_if.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-describe "bundle install with install_if conditionals" do
- it "follows the install_if DSL" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- install_if(lambda { true }) do
- gem "activesupport", "2.3.5"
- end
- gem "thin", :install_if => false
- install_if(lambda { false }) do
- gem "foo"
- end
- gem "rack"
- G
-
- expect(the_bundle).to include_gems("rack 1.0", "activesupport 2.3.5")
- expect(the_bundle).not_to include_gems("thin")
- expect(the_bundle).not_to include_gems("foo")
-
- lockfile_should_be <<-L
- GEM
- remote: #{file_uri_for(gem_repo1)}/
- specs:
- activesupport (2.3.5)
- foo (1.0)
- rack (1.0.0)
- thin (1.0)
- rack
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- activesupport (= 2.3.5)
- foo
- rack
- thin
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
-end
diff --git a/spec/bundler/install/gemfile/install_if_spec.rb b/spec/bundler/install/gemfile/install_if_spec.rb
new file mode 100644
index 0000000000..3d2d15a698
--- /dev/null
+++ b/spec/bundler/install/gemfile/install_if_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install with install_if conditionals" do
+ it "follows the install_if DSL" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ install_if(lambda { true }) do
+ gem "activesupport", "2.3.5"
+ end
+ gem "thin", :install_if => false
+ install_if(lambda { false }) do
+ gem "foo"
+ end
+ gem "rack"
+ G
+
+ expect(the_bundle).to include_gems("rack 1.0", "activesupport 2.3.5")
+ expect(the_bundle).not_to include_gems("thin")
+ expect(the_bundle).not_to include_gems("foo")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ activesupport (2.3.5)
+ foo (1.0)
+ rack (1.0.0)
+ thin (1.0)
+ rack
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activesupport (= 2.3.5)
+ foo
+ rack
+ thin
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+end
diff --git a/spec/bundler/install/gemfile/lockfile_spec.rb b/spec/bundler/install/gemfile/lockfile_spec.rb
index b9545b91c2..313e99d0b8 100644
--- a/spec/bundler/install/gemfile/lockfile_spec.rb
+++ b/spec/bundler/install/gemfile/lockfile_spec.rb
@@ -16,12 +16,12 @@ RSpec.describe "bundle install with a lockfile present" do
context "with plugins disabled" do
before do
- bundle! "config set plugins false"
+ bundle "config set plugins false"
subject
end
it "does not evaluate the gemfile twice" do
- bundle! :install
+ bundle :install
with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "rack 1.0.0" }
@@ -31,10 +31,10 @@ RSpec.describe "bundle install with a lockfile present" do
end
context "when the gem is not installed" do
- before { FileUtils.rm_rf ".bundle" }
+ before { FileUtils.rm_rf bundled_app(".bundle") }
it "does not evaluate the gemfile twice" do
- bundle! :install
+ bundle :install
with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "rack 1.0.0" }
diff --git a/spec/bundler/install/gemfile/path_spec.rb b/spec/bundler/install/gemfile/path_spec.rb
index e53636da09..bea7c11dec 100644
--- a/spec/bundler/install/gemfile/path_spec.rb
+++ b/spec/bundler/install/gemfile/path_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path("foo-1.0")}" do
gem 'foo'
end
@@ -28,6 +29,7 @@ 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
@@ -37,9 +39,10 @@ RSpec.describe "bundle install with explicit source paths" do
it "supports relative paths" do
build_lib "foo"
- relative_path = lib_path("foo-1.0").relative_path_from(Pathname.new(Dir.pwd))
+ relative_path = lib_path("foo-1.0").relative_path_from(bundled_app)
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', :path => "#{relative_path}"
G
@@ -52,6 +55,7 @@ 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
@@ -59,11 +63,14 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "expands paths raise error with not existing user's home dir" do
+ skip "problems with ~ expansion" if Gem.win_platform?
+
build_lib "foo"
username = "some_unexisting_user"
relative_path = lib_path("foo-1.0").relative_path_from(Pathname.new("/home/#{username}").expand_path)
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', :path => "~#{username}/#{relative_path}"
G
expect(err).to match("There was an error while trying to use the path `~#{username}/#{relative_path}`.")
@@ -74,13 +81,11 @@ 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
- bundled_app("subdir").mkpath
- Dir.chdir(bundled_app("subdir")) do
- expect(the_bundle).to include_gems("foo 1.0")
- end
+ expect(the_bundle).to include_gems("foo 1.0", :dir => bundled_app("subdir").mkpath)
end
it "sorts paths consistently on install and update when they start with ./" do
@@ -88,6 +93,7 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "aaa", :path => lib_path("demo/aaa")
gemfile = <<-G
+ source "#{file_uri_for(gem_repo1)}"
gemspec
gem "aaa", :path => "./aaa"
G
@@ -106,6 +112,7 @@ RSpec.describe "bundle install with explicit source paths" do
aaa (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -119,23 +126,22 @@ RSpec.describe "bundle install with explicit source paths" do
#{Bundler::VERSION}
L
- Dir.chdir(lib_path("demo")) do
- bundle :install
- expect(lib_path("demo/Gemfile.lock")).to have_lockfile(lockfile)
- bundle :update, :all => true
- expect(lib_path("demo/Gemfile.lock")).to have_lockfile(lockfile)
- end
+ bundle :install, :dir => lib_path("demo")
+ expect(lib_path("demo/Gemfile.lock")).to read_as(lockfile)
+ bundle :update, :all => true, :dir => lib_path("demo")
+ expect(lib_path("demo/Gemfile.lock")).to read_as(lockfile)
end
it "expands paths when comparing locked paths to Gemfile paths" do
build_lib "foo", :path => bundled_app("foo-1.0")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', :path => File.expand_path("../foo-1.0", __FILE__)
G
- bundle! :install, forgotten_command_line_options(:frozen => true)
- expect(exitstatus).to eq(0) if exitstatus
+ bundle "config set --local frozen true"
+ bundle :install
end
it "installs dependencies from the path even if a newer gem is available elsewhere" do
@@ -170,22 +176,90 @@ 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
expect(the_bundle).to include_gems "foo 1.0"
end
- it "works with only_update_to_newer_versions" do
+ it "works when using prereleases of 0.0.0" do
+ build_lib "foo", "0.0.0.dev", :path => lib_path("foo")
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :path => "#{lib_path("foo")}"
+ G
+
+ lockfile <<~L
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (0.0.0.dev)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+
+ expect(the_bundle).to include_gems "foo 0.0.0.dev"
+ end
+
+ it "works when using uppercase prereleases of 0.0.0" do
+ build_lib "foo", "0.0.0.SNAPSHOT", :path => lib_path("foo")
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :path => "#{lib_path("foo")}"
+ G
+
+ lockfile <<~L
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (0.0.0.SNAPSHOT)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle :install
+
+ expect(the_bundle).to include_gems "foo 0.0.0.SNAPSHOT"
+ end
+
+ it "handles downgrades" do
build_lib "omg", "2.0", :path => lib_path("omg")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "omg", :path => "#{lib_path("omg")}"
G
build_lib "omg", "1.0", :path => lib_path("omg")
- bundle! :install, :env => { "BUNDLE_BUNDLE_ONLY_UPDATE_TO_NEWER_VERSIONS" => "true" }
+ bundle :install
expect(the_bundle).to include_gems "omg 1.0"
end
@@ -203,6 +277,7 @@ 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
@@ -223,11 +298,11 @@ RSpec.describe "bundle install with explicit source paths" do
G
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
- expect(err).to_not include("ERROR REPORT")
expect(err).to_not include("Your Gemfile has no gem server sources.")
expect(err).to match(/is not valid. Please fix this gemspec./)
expect(err).to match(/The validation error was 'missing value for attribute version'/)
@@ -246,11 +321,9 @@ RSpec.describe "bundle install with explicit source paths" do
File.open(lib_path("foo/Gemfile"), "w") {|f| f.puts gemfile }
- Dir.chdir(lib_path("foo")) do
- bundle "install"
- expect(the_bundle).to include_gems "foo 1.0"
- expect(the_bundle).to include_gems "rack 1.0"
- end
+ bundle "install", :dir => lib_path("foo")
+ expect(the_bundle).to include_gems "foo 1.0", :dir => lib_path("foo")
+ expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("foo")
end
it "supports gemspec syntax with an alternative path" do
@@ -272,19 +345,17 @@ RSpec.describe "bundle install with explicit source paths" do
s.add_dependency "rack", ">= 1.0"
end
- Dir.chdir lib_path("foo")
-
- install_gemfile lib_path("foo/Gemfile"), <<-G
+ install_gemfile lib_path("foo/Gemfile"), <<-G, :dir => lib_path("foo")
source "#{file_uri_for(gem_repo1)}"
gemspec
G
build_gem "rack", "1.0.1", :to_system => true
- bundle "install"
+ bundle "install", :dir => lib_path("foo")
- expect(the_bundle).to include_gems "foo 1.0"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "foo 1.0", :dir => lib_path("foo")
+ expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("foo")
end
it "doesn't automatically unlock dependencies when using the gemspec syntax and the gem has development dependencies" do
@@ -293,19 +364,17 @@ RSpec.describe "bundle install with explicit source paths" do
s.add_development_dependency "activesupport"
end
- Dir.chdir lib_path("foo")
-
- install_gemfile lib_path("foo/Gemfile"), <<-G
+ install_gemfile lib_path("foo/Gemfile"), <<-G, :dir => lib_path("foo")
source "#{file_uri_for(gem_repo1)}"
gemspec
G
build_gem "rack", "1.0.1", :to_system => true
- bundle "install"
+ bundle "install", :dir => lib_path("foo")
- expect(the_bundle).to include_gems "foo 1.0"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "foo 1.0", :dir => lib_path("foo")
+ expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("foo")
end
it "raises if there are multiple gemspecs" do
@@ -313,11 +382,12 @@ RSpec.describe "bundle install with explicit source paths" do
s.write "bar.gemspec", build_spec("bar", "1.0").first.to_ruby
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
gemspec :path => "#{lib_path("foo")}"
G
- expect(exitstatus).to eq(15) if exitstatus
+ expect(exitstatus).to eq(15)
expect(err).to match(/There are multiple gemspecs/)
end
@@ -327,6 +397,7 @@ 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
@@ -338,11 +409,13 @@ RSpec.describe "bundle install with explicit source paths" do
s.executables = "foobar"
end
- install_gemfile <<-G
+ install_gemfile <<-G, :verbose => true
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
+ expect(out).to include("Using foo 1.0 from source at `#{lib_path("foo-1.0")}` and installing its executables")
expect(the_bundle).to include_gems "foo 1.0"
bundle "exec foobar"
@@ -355,6 +428,7 @@ RSpec.describe "bundle install with explicit source paths" do
lib_path("foo-1.0").join("bin/performance").mkpath
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', '1.0', :path => "#{lib_path("foo-1.0")}"
G
expect(err).to be_empty
@@ -364,6 +438,7 @@ 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
@@ -376,6 +451,7 @@ 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"
@@ -394,6 +470,7 @@ 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
@@ -405,6 +482,7 @@ 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
@@ -420,15 +498,15 @@ RSpec.describe "bundle install with explicit source paths" do
specs:
GEM
- remote: http://rubygems.org
+ remote: http://rubygems.org/
L
- in_app_root { FileUtils.mkdir_p("vendor/bar") }
+ FileUtils.mkdir_p(bundled_app("vendor/bar"))
install_gemfile <<-G
+ source "http://rubygems.org"
gem "bar", "1.0.0", path: "vendor/bar", require: "bar/nyard"
G
- expect(exitstatus).to eq(0) if exitstatus
end
context "existing lockfile" do
@@ -471,6 +549,7 @@ 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
@@ -486,6 +565,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)}"
gem "foo", :path => "#{lib_path("foo")}"
G
end
@@ -538,7 +618,7 @@ RSpec.describe "bundle install with explicit source paths" do
expect(the_bundle).to include_gems "rack 0.9.1"
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo")}
specs:
@@ -566,7 +646,7 @@ RSpec.describe "bundle install with explicit source paths" do
bundle "install"
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo")}
specs:
@@ -590,6 +670,71 @@ RSpec.describe "bundle install with explicit source paths" do
expect(the_bundle).to include_gems "rack 0.9.1"
end
+
+ it "keeps using the same version even when another dependency is added" do
+ build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ s.add_dependency "rack", "0.9.1"
+ end
+
+ bundle "install"
+
+ expect(the_bundle).to include_gems "rack 0.9.1"
+
+ expect(lockfile).to eq <<~G
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+ rack (= 0.9.1)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ rack (0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ build_lib "foo", "1.0", :path => lib_path("foo") do |s|
+ s.add_dependency "rack"
+ s.add_dependency "rake", "13.0.1"
+ end
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~G
+ PATH
+ remote: #{lib_path("foo")}
+ specs:
+ foo (1.0)
+ rack
+ rake (= 13.0.1)
+
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ rack (0.9.1)
+ rake (13.0.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+
+ expect(the_bundle).to include_gems "rack 0.9.1"
+ end
end
describe "switching sources" do
@@ -617,7 +762,7 @@ RSpec.describe "bundle install with explicit source paths" do
it "switches the source when the gem existed in rubygems and the path was already being used for another gem" do
build_lib "foo", "1.0", :path => lib_path("foo")
- build_gem "bar", "1.0", :to_system => true do |s|
+ build_gem "bar", "1.0", :to_bundle => true do |s|
s.write "lib/bar.rb", "raise 'fail'"
end
@@ -653,13 +798,11 @@ RSpec.describe "bundle install with explicit source paths" do
G
File.open(lib_path("private_lib/Gemfile"), "w") {|f| f.puts gemfile }
- Dir.chdir(lib_path("private_lib")) do
- bundle :install, :env => { "DEBUG" => "1" }, :artifice => "endpoint"
- expect(out).to match(%r{^HTTP GET http://localgemserver\.test/api/v1/dependencies\?gems=rack$})
- expect(out).not_to match(/^HTTP GET.*private_lib/)
- expect(the_bundle).to include_gems "private_lib 2.2"
- expect(the_bundle).to include_gems "rack 1.0"
- end
+ bundle :install, :env => { "DEBUG" => "1" }, :artifice => "endpoint", :dir => lib_path("private_lib")
+ expect(out).to match(%r{^HTTP GET http://localgemserver\.test/api/v1/dependencies\?gems=rack$})
+ expect(out).not_to match(/^HTTP GET.*private_lib/)
+ expect(the_bundle).to include_gems "private_lib 2.2", :dir => lib_path("private_lib")
+ expect(the_bundle).to include_gems "rack 1.0", :dir => lib_path("private_lib")
end
end
@@ -667,6 +810,7 @@ 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
@@ -686,6 +830,7 @@ 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
@@ -705,6 +850,7 @@ 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
@@ -716,8 +862,7 @@ RSpec.describe "bundle install with explicit source paths" do
H
end
- bundle :install,
- :requires => [lib_path("install_hooks.rb")]
+ bundle :install, :requires => [lib_path("install_hooks.rb")], :raise_on_error => false
expect(err).to include("failed for foo-1.0")
end
@@ -728,14 +873,15 @@ RSpec.describe "bundle install with explicit source paths" do
expect(bar_file).not_to be_file
build_lib "foo" do |s|
- s.write("lib/rubygems_plugin.rb", "FileUtils.touch('#{foo_file}')")
+ s.write("lib/rubygems_plugin.rb", "require 'fileutils'; FileUtils.touch('#{foo_file}')")
end
build_git "bar" do |s|
- s.write("lib/rubygems_plugin.rb", "FileUtils.touch('#{bar_file}')")
+ s.write("lib/rubygems_plugin.rb", "require 'fileutils'; FileUtils.touch('#{bar_file}')")
end
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo-1.0")}"
gem "bar", :path => "#{lib_path("bar-1.0")}"
G
diff --git a/spec/bundler/install/gemfile/platform_spec.rb b/spec/bundler/install/gemfile/platform_spec.rb
index c096531398..35a3872c03 100644
--- a/spec/bundler/install/gemfile/platform_spec.rb
+++ b/spec/bundler/install/gemfile/platform_spec.rb
@@ -50,6 +50,31 @@ RSpec.describe "bundle install across platforms" do
expect(the_bundle).to include_gems "platform_specific 1.0 JAVA"
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 do
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo1)}
+ specs:
+ platform_specific (1.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ platform_specific
+ G
+
+ bundle "config set --local frozen true"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ end
+
it "works with gems that have different dependencies" do
simulate_platform "java"
install_gemfile <<-G
@@ -63,14 +88,15 @@ RSpec.describe "bundle install across platforms" do
simulate_new_machine
simulate_platform "ruby"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
-
- gem "nokogiri"
- G
+ bundle "install"
expect(the_bundle).to include_gems "nokogiri 1.4.2"
expect(the_bundle).not_to include_gems "weakling"
+
+ simulate_platform "java"
+ bundle "install"
+
+ expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
end
it "does not keep unneeded platforms for gems that are used" do
@@ -95,14 +121,14 @@ RSpec.describe "bundle install across platforms" do
simulate_platform java
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gem "empyrean", "0.1.0"
gem "pry"
G
- lockfile_should_be <<-L
+ expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -128,9 +154,9 @@ RSpec.describe "bundle install across platforms" do
#{Bundler::VERSION}
L
- bundle! "lock --add-platform ruby"
+ bundle "lock --add-platform ruby"
- good_lockfile = strip_whitespace(<<-L)
+ good_lockfile = <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -160,9 +186,9 @@ RSpec.describe "bundle install across platforms" do
#{Bundler::VERSION}
L
- lockfile_should_be good_lockfile
+ expect(lockfile).to eq good_lockfile
- bad_lockfile = strip_whitespace <<-L
+ bad_lockfile = <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
@@ -195,65 +221,54 @@ RSpec.describe "bundle install across platforms" do
aggregate_failures do
lockfile bad_lockfile
- bundle! :install
- lockfile_should_be good_lockfile
+ bundle :install
+ expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle! :update, :all => true
- lockfile_should_be good_lockfile
+ bundle :update, :all => true
+ expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle! "update ffi"
- lockfile_should_be good_lockfile
+ bundle "update ffi"
+ expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle! "update empyrean"
- lockfile_should_be good_lockfile
+ bundle "update empyrean"
+ expect(lockfile).to eq good_lockfile
lockfile bad_lockfile
- bundle! :lock
- lockfile_should_be good_lockfile
+ bundle :lock
+ expect(lockfile).to eq good_lockfile
end
end
- it "works the other way with gems that have different dependencies" do
- simulate_platform "ruby"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
-
- gem "nokogiri"
- G
-
- simulate_platform "java"
- bundle "install"
-
- expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
- end
-
- it "works with gems that have extra platform-specific runtime dependencies", :bundler => "< 3" do
+ it "works with gems with platform-specific dependency having different requirements order" do
simulate_platform x64_mac
update_repo2 do
- build_gem "facter", "2.4.6"
- build_gem "facter", "2.4.6" do |s|
+ build_gem "fspath", "3"
+ build_gem "image_optim_pack", "1.2.3" do |s|
+ s.add_runtime_dependency "fspath", ">= 2.1", "< 4"
+ end
+ build_gem "image_optim_pack", "1.2.3" do |s|
s.platform = "universal-darwin"
- s.add_runtime_dependency "CFPropertyList"
+ s.add_runtime_dependency "fspath", "< 4", ">= 2.1"
end
- build_gem "CFPropertyList"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ G
+
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
- gem "facter"
+ gem "image_optim_pack"
G
- expect(err).to include "Unable to use the platform-specific (universal-darwin) version of facter (2.4.6) " \
- "because it has different dependencies from the ruby version. " \
- "To use the platform-specific version of the gem, run `bundle config set specific_platform true` and install again."
+ expect(err).not_to include "Unable to use the platform-specific"
- expect(the_bundle).to include_gem "facter 2.4.6"
- expect(the_bundle).not_to include_gem "CFPropertyList"
+ expect(the_bundle).to include_gem "image_optim_pack 1.2.3 universal-darwin"
end
it "fetches gems again after changing the version of Ruby" do
@@ -263,17 +278,62 @@ RSpec.describe "bundle install across platforms" do
gem "rack", "1.0.0"
G
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle :install
FileUtils.mv(vendored_gems, bundled_app("vendor/bundle", Gem.ruby_engine, "1.8"))
- bundle! :install
+ bundle :install
expect(vendored_gems("gems/rack-1.0.0")).to exist
end
+
+ it "keeps existing platforms when installing with force_ruby_platform" do
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ platform_specific (1.0-java)
+
+ PLATFORMS
+ java
+
+ DEPENDENCIES
+ platform_specific
+ G
+
+ bundle "config set --local force_ruby_platform true"
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gem "platform_specific 1.0 RUBY"
+
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ platform_specific (1.0)
+ platform_specific (1.0-java)
+
+ PLATFORMS
+ java
+ ruby
+
+ DEPENDENCIES
+ platform_specific
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
end
RSpec.describe "bundle install with platform conditionals" do
it "installs gems tagged w/ the current platforms" do
+ skip "platform issues" if Gem.win_platform?
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -298,7 +358,52 @@ RSpec.describe "bundle install with platform conditionals" do
expect(the_bundle).not_to include_gems "nokogiri 1.4.2"
end
+ it "installs gems tagged w/ another platform but also dependent on the current one transitively" do
+ build_repo4 do
+ build_gem "activesupport", "6.1.4.1" do |s|
+ s.add_dependency "tzinfo", "~> 2.0"
+ end
+
+ build_gem "tzinfo", "2.0.4"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+
+ gem "activesupport"
+
+ platforms :#{not_local_tag} do
+ gem "tzinfo", "~> 1.2"
+ end
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ activesupport (6.1.4.1)
+ tzinfo (~> 2.0)
+ tzinfo (2.0.4)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ activesupport
+ tzinfo (~> 1.2)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose"
+
+ expect(the_bundle).to include_gems "tzinfo 2.0.4"
+ end
+
it "installs gems tagged w/ the current platforms inline" do
+ skip "platform issues" if Gem.win_platform?
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri", :platforms => :#{local_tag}
@@ -317,6 +422,8 @@ RSpec.describe "bundle install with platform conditionals" do
end
it "installs gems tagged w/ the current platform inline" do
+ skip "platform issues" if Gem.win_platform?
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri", :platform => :#{local_tag}
@@ -336,18 +443,17 @@ RSpec.describe "bundle install with platform conditionals" do
build_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
platform :#{not_local_tag} do
gem "foo", :git => "#{lib_path("foo-1.0")}"
end
G
bundle :list
- expect(exitstatus).to eq(0) if exitstatus
end
it "does not attempt to install gems from :rbx when using --local" do
simulate_platform "ruby"
- simulate_ruby_engine "ruby"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -360,7 +466,6 @@ RSpec.describe "bundle install with platform conditionals" do
it "does not attempt to install gems from other rubies when using --local" do
simulate_platform "ruby"
- simulate_ruby_engine "ruby"
other_ruby_version_tag = RUBY_VERSION =~ /^1\.8/ ? :ruby_19 : :ruby_18
gemfile <<-G
@@ -372,9 +477,8 @@ RSpec.describe "bundle install with platform conditionals" do
expect(out).not_to match(/Could not find gem 'some_gem/)
end
- it "prints a helpful warning when a dependency is unused on any platform" do
+ it "does not print a warning when a dependency is unused on a platform different from the current one" do
simulate_platform "ruby"
- simulate_ruby_engine "ruby"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -382,30 +486,24 @@ RSpec.describe "bundle install with platform conditionals" do
gem "rack", :platform => [:mingw, :mswin, :x64_mingw, :jruby]
G
- bundle! "install"
-
- expect(err).to include <<-O.strip
-The dependency #{Gem::Dependency.new("rack", ">= 0")} will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
- O
- end
-
- context "when disable_platform_warnings is true" do
- before { bundle! "config set disable_platform_warnings true" }
+ bundle "install"
- it "does not print the warning when a dependency is unused on any platform" do
- simulate_platform "ruby"
- simulate_ruby_engine "ruby"
+ expect(err).to be_empty
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
- gem "rack", :platform => [:mingw, :mswin, :x64_mingw, :jruby]
- G
+ PLATFORMS
+ ruby
- bundle! "install"
+ DEPENDENCIES
+ rack
- expect(out).not_to match(/The dependency (.*) will be unused/)
- end
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
end
@@ -413,13 +511,21 @@ RSpec.describe "when a gem has no architecture" do
it "still installs correctly" do
simulate_platform mswin
+ build_repo2 do
+ # The rcov gem is platform mswin32, but has no arch
+ build_gem "rcov" do |s|
+ s.platform = Gem::Platform.new([nil, "mswin32", nil])
+ s.write "lib/rcov.rb", "RCOV = '1.0.0'"
+ end
+ end
+
gemfile <<-G
# Try to install gem with nil arch
source "http://localgemserver.test/"
gem "rcov"
G
- bundle :install, :artifice => "windows"
+ bundle :install, :artifice => "windows", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(the_bundle).to include_gems "rcov 1.0.0"
end
end
diff --git a/spec/bundler/install/gemfile/ruby_spec.rb b/spec/bundler/install/gemfile/ruby_spec.rb
index d1e9fc7e05..fd4300c042 100644
--- a/spec/bundler/install/gemfile/ruby_spec.rb
+++ b/spec/bundler/install/gemfile/ruby_spec.rb
@@ -2,10 +2,10 @@
RSpec.describe "ruby requirement" do
def locked_ruby_version
- Bundler::RubyVersion.from_string(Bundler::LockfileParser.new(lockfile).ruby_version)
+ Bundler::RubyVersion.from_string(Bundler::LockfileParser.new(File.read(bundled_app_lock)).ruby_version)
end
- # As discovered by https://github.com/bundler/bundler/issues/4147, there is
+ # As discovered by https://github.com/rubygems/bundler/issues/4147, there is
# no test coverage to ensure that adding a gem is possible with a ruby
# requirement. This test verifies the fix, committed in bfbad5c5.
it "allows adding gems" do
@@ -22,7 +22,6 @@ RSpec.describe "ruby requirement" do
gem "rack-obama"
G
- expect(exitstatus).to eq(0) if exitstatus
expect(the_bundle).to include_gems "rack-obama 1.0"
end
@@ -51,6 +50,7 @@ RSpec.describe "ruby requirement" do
gem "rack"
G
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
simulate_ruby_version "5100"
@@ -72,6 +72,7 @@ RSpec.describe "ruby requirement" do
gem "rack"
G
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
simulate_ruby_version "5100"
@@ -87,7 +88,7 @@ RSpec.describe "ruby requirement" do
end
it "allows requirements with trailing whitespace" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
ruby "#{RUBY_VERSION}\\n \t\\n"
gem "rack"
@@ -97,7 +98,7 @@ RSpec.describe "ruby requirement" do
end
it "fails gracefully with malformed requirements" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
ruby ">= 0", "-.\\0"
gem "rack"
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index 61943ef2e5..5456e95f33 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -15,56 +15,56 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
- context "with multiple toplevel sources", :bundler => "< 3" do
+ context "with multiple toplevel sources" do
let(:repo3_rack_version) { "1.0.0" }
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo3)}"
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo3"
+ source "https://gem.repo1"
gem "rack-obama"
gem "rack"
G
end
- it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "2" do
- bundle :install
+ it "warns about ambiguous gems, but installs anyway, prioritizing sources last to first", :bundler => "< 3" do
+ bundle :install, :artifice => "compact_index"
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).to include("Installed from: #{file_uri_for(gem_repo1)}")
+ expect(err).to include("Installed from: https://gem.repo1")
expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
end
it "fails", :bundler => "3" do
- bundle :install
+ bundle :instal, :artifice => "compact_index", :raise_on_error => false
expect(err).to include("Each source after the first must include a block")
- expect(exitstatus).to eq(4) if exitstatus
+ expect(exitstatus).to eq(4)
end
end
- context "when different versions of the same gem are in multiple sources", :bundler => "< 3" do
+ context "when different versions of the same gem are in multiple sources" do
let(:repo3_rack_version) { "1.2" }
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo3)}"
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo3"
+ source "https://gem.repo1"
gem "rack-obama"
gem "rack", "1.0.0" # force it to install the working version in repo1
G
-
- bundle :install
end
- it "warns about ambiguous gems, but installs anyway", :bundler => "2" do
+ it "warns about ambiguous gems, but installs anyway", :bundler => "< 3" do
+ bundle :install, :artifice => "compact_index"
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).to include("Installed from: #{file_uri_for(gem_repo1)}")
+ expect(err).to include("Installed from: https://gem.repo1")
expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", :source => "remote1")
end
it "fails", :bundler => "3" do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
expect(err).to include("Each source after the first must include a block")
- expect(exitstatus).to eq(4) if exitstatus
+ expect(exitstatus).to eq(4)
end
end
end
@@ -85,29 +85,30 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo3)}"
- source "#{file_uri_for(gem_repo1)}" do
+ source "https://gem.repo3"
+ source "https://gem.repo1" do
gem "thin" # comes first to test name sorting
gem "rack"
end
- gem "rack-obama" # shoud come from repo3!
+ gem "rack-obama" # should come from repo3!
G
end
it "installs the gems without any warning" do
- bundle! :install
- expect(out).not_to include("Warning")
+ bundle :install, :artifice => "compact_index"
+ expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("rack-obama 1.0.0")
expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote1")
end
it "can cache and deploy" do
- bundle! :cache
+ bundle :cache, :artifice => "compact_index"
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/rack-obama-1.0.gem")).to exist
- bundle! :install, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ bundle :install, :artifice => "compact_index"
expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0")
end
@@ -127,258 +128,813 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
- gemfile <<-G
- source "#{file_uri_for(gem_repo3)}"
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo3"
gem "rack-obama" # should come from repo3!
- gem "rack", :source => "#{file_uri_for(gem_repo1)}"
+ gem "rack", :source => "https://gem.repo1"
G
end
it "installs the gems without any warning" do
- bundle :install
- expect(out).not_to include("Warning")
+ expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0")
end
end
- context "when a pinned gem has an indirect dependency" do
+ context "when a pinned gem has an indirect dependency in the pinned source" do
before do
build_repo gem_repo3 do
build_gem "depends_on_rack", "1.0.1" do |s|
s.add_dependency "rack"
end
end
+
+ # we need a working rack gem in repo3
+ update_repo gem_repo3 do
+ build_gem "rack", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ source "https://gem.repo3" do
+ gem "depends_on_rack"
+ end
+ G
end
- context "when the indirect dependency is in the pinned source" do
+ context "and not in any other sources" do
before do
- # we need a working rack gem in repo3
- update_repo gem_repo3 do
- build_gem "rack", "1.0.0"
+ build_repo(gem_repo2) {}
+ end
+
+ it "installs from the same source without any warning" do
+ bundle :install, :artifice => "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+ end
+ end
+
+ context "and in another source" do
+ before do
+ # need this to be broken to check for correct source ordering
+ build_repo gem_repo2 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
+ end
end
+ end
+
+ it "installs from the same source without any warning" do
+ bundle :install, :artifice => "compact_index"
+ expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+
+ # In https://github.com/bundler/bundler/issues/3585 this failed
+ # when there is already a lock file, and the gems are missing, so try again
+ system_gems []
+ bundle :install, :artifice => "compact_index"
+
+ expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+ end
+ end
+ end
+
+ context "when a pinned gem has an indirect dependency in a different source" do
+ before do
+ # In these tests, we need a working rack gem in repo2 and not repo3
+
+ build_repo gem_repo3 do
+ build_gem "depends_on_rack", "1.0.1" do |s|
+ s.add_dependency "rack"
+ end
+ end
+
+ build_repo gem_repo2 do
+ build_gem "rack", "1.0.0"
+ end
+ end
+
+ context "and not in any other sources" do
+ before do
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo2"
+ source "https://gem.repo3" do
+ gem "depends_on_rack"
+ end
+ G
+ end
+
+ it "installs from the other source without any warning" do
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ end
+ end
+
+ context "and in yet another source" do
+ before do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- source "#{file_uri_for(gem_repo3)}" do
+ source "https://gem.repo1"
+ source "https://gem.repo2"
+ source "https://gem.repo3" do
gem "depends_on_rack"
end
G
end
- context "and not in any other sources" do
- before do
- build_repo(gem_repo2) {}
- end
+ it "installs from the other source and warns about ambiguous gems", :bundler => "< 3" do
+ bundle :install, :artifice => "compact_index"
+ expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(err).to include("Installed from: https://gem.repo2")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ remote: https://gem.repo2/
+ specs:
+ rack (1.0.0)
+
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ depends_on_rack (1.0.1)
+ rack
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ depends_on_rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ previous_lockfile = lockfile
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ expect(lockfile).to eq(previous_lockfile)
+ end
- it "installs from the same source without any warning" do
- bundle :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
- end
+ it "fails", :bundler => "3" do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
+ expect(err).to include("Each source after the first must include a block")
+ expect(exitstatus).to eq(4)
end
+ end
- context "and in another source" do
- before do
- # need this to be broken to check for correct source ordering
- build_repo gem_repo2 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
+ context "and only the dependency is pinned" do
+ before do
+ # need this to be broken to check for correct source ordering
+ build_repo gem_repo2 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
end
end
- context "when disable_multisource is set" do
- before do
- bundle! "config set disable_multisource true"
- end
+ gemfile <<-G
+ source "https://gem.repo3" # contains depends_on_rack
+ source "https://gem.repo2" # contains broken rack
- it "installs from the same source without any warning" do
- bundle! :install
+ gem "depends_on_rack" # installed from gem_repo3
+ gem "rack", :source => "https://gem.repo1"
+ G
+ end
- expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ it "installs the dependency from the pinned source without warning", :bundler => "< 3" do
+ bundle :install, :artifice => "compact_index"
- # when there is already a lock file, and the gems are missing, so try again
- system_gems []
- bundle! :install
+ expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
- expect(out).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
- end
- end
+ # In https://github.com/rubygems/bundler/issues/3585 this failed
+ # when there is already a lock file, and the gems are missing, so try again
+ system_gems []
+ bundle :install, :artifice => "compact_index"
+
+ expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ end
+
+ it "fails", :bundler => "3" do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
+ expect(err).to include("Each source after the first must include a block")
+ expect(exitstatus).to eq(4)
end
end
+ end
- context "when the indirect dependency is in a different source" do
- before do
- # In these tests, we need a working rack gem in repo2 and not repo3
- build_repo gem_repo2 do
- build_gem "rack", "1.0.0"
- end
+ context "when a top-level gem can only be found in an scoped source" do
+ before do
+ build_repo2
+
+ build_repo gem_repo3 do
+ build_gem "private_gem_1", "1.0.0"
+ build_gem "private_gem_2", "1.0.0"
end
- context "and not in any other sources" do
- before do
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- source "#{file_uri_for(gem_repo3)}" do
- gem "depends_on_rack"
- end
- G
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "private_gem_1"
+
+ source "https://gem.repo3" do
+ gem "private_gem_2"
end
+ G
+ end
- it "installs from the other source without any warning" do
- bundle :install
- expect(out).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ it "fails" do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
+ expect(err).to include("Could not find gem 'private_gem_1' in rubygems repository https://gem.repo2/ or installed locally.")
+ end
+ end
+
+ context "when an indirect dependency can't be found in the aggregate rubygems source", :bundler => "< 3" do
+ before do
+ build_repo2
+
+ build_repo gem_repo3 do
+ build_gem "depends_on_missing", "1.0.1" do |s|
+ s.add_dependency "missing"
end
end
- context "and in yet another source", :bundler => "< 3" do
- before do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo2)}"
- source "#{file_uri_for(gem_repo3)}" do
- gem "depends_on_rack"
- end
- G
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ source "https://gem.repo3"
+
+ gem "depends_on_missing"
+ G
+ end
+
+ it "fails" do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
+ expect(err).to include("Could not find gem 'missing', which is required by gem 'depends_on_missing', in any of the sources.")
+ end
+ end
- bundle :install
+ context "when a top-level gem has an indirect dependency" do
+ before do
+ build_repo gem_repo2 do
+ build_gem "depends_on_rack", "1.0.1" do |s|
+ s.add_dependency "rack"
end
+ end
- it "installs from the other source and warns about ambiguous gems", :bundler => "2" do
- expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).to include("Installed from: #{file_uri_for(gem_repo2)}")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ build_repo gem_repo3 do
+ build_gem "unrelated_gem", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ gem "depends_on_rack"
+
+ source "https://gem.repo3" do
+ gem "unrelated_gem"
end
+ G
+ end
- it "fails", :bundler => "3" do
- expect(err).to include("Each source after the first must include a block")
- expect(exitstatus).to eq(4) if exitstatus
+ context "and the dependency is only in the top-level source" do
+ before do
+ update_repo gem_repo2 do
+ build_gem "rack", "1.0.0"
end
end
- context "and only the dependency is pinned", :bundler => "< 3" do
- before do
- # need this to be broken to check for correct source ordering
- build_repo gem_repo2 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
+ it "installs the dependency from the top-level source without warning" do
+ bundle :install, :artifice => "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote2")
+ expect(the_bundle).to include_gems("unrelated_gem 1.0.0", :source => "remote3")
+ end
+ end
+
+ context "and the dependency is only in a pinned source" do
+ before do
+ update_repo gem_repo3 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
end
+ end
+ end
- gemfile <<-G
- source "#{file_uri_for(gem_repo3)}" # contains depends_on_rack
- source "#{file_uri_for(gem_repo2)}" # contains broken rack
+ it "does not find the dependency" do
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
+ expect(err).to include(
+ "Could not find gem 'rack', which is required by gem 'depends_on_rack', in rubygems repository https://gem.repo2/ or installed locally."
+ )
+ end
+ end
- gem "depends_on_rack" # installed from gem_repo3
- gem "rack", :source => "#{file_uri_for(gem_repo1)}"
- G
+ context "and the dependency is in both the top-level and a pinned source" do
+ before do
+ update_repo gem_repo2 do
+ build_gem "rack", "1.0.0"
end
- it "installs the dependency from the pinned source without warning", :bundler => "2" do
- bundle :install
+ update_repo gem_repo3 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
+ end
+ end
+ end
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ it "installs the dependency from the top-level source without warning" do
+ bundle :install, :artifice => "compact_index"
+ expect(err).not_to include("Warning")
+ expect(run("require 'rack'; puts RACK")).to eq("1.0.0")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0")
+ expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote2")
+ expect(the_bundle).to include_gems("unrelated_gem 1.0.0", :source => "remote3")
+ end
+ end
+ end
- # In https://github.com/bundler/bundler/issues/3585 this failed
- # when there is already a lock file, and the gems are missing, so try again
- system_gems []
- bundle :install
+ context "when a scoped gem has a deeply nested indirect dependency" do
+ before do
+ build_repo gem_repo3 do
+ build_gem "depends_on_depends_on_rack", "1.0.1" do |s|
+ s.add_dependency "depends_on_rack"
+ end
- expect(err).not_to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0")
+ build_gem "depends_on_rack", "1.0.1" do |s|
+ s.add_dependency "rack"
end
+ end
- it "fails", :bundler => "3" do
- bundle :install
- expect(err).to include("Each source after the first must include a block")
- expect(exitstatus).to eq(4) if exitstatus
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ source "https://gem.repo3" do
+ gem "depends_on_depends_on_rack"
end
+ G
+ end
+
+ context "and the dependency is only in the top-level source" do
+ before do
+ update_repo gem_repo2 do
+ build_gem "rack", "1.0.0"
+ end
+ end
+
+ it "installs the dependency from the top-level source" do
+ bundle :install, :artifice => "compact_index"
+ expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0")
+ expect(the_bundle).to include_gems("rack 1.0.0", :source => "remote2")
+ expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", :source => "remote3")
end
end
- end
- context "when a top-level gem has an indirect dependency" do
- context "when disable_multisource is set" do
+ context "and the dependency is only in a pinned source" do
before do
- bundle! "config set disable_multisource true"
+ build_repo2
+
+ update_repo gem_repo3 do
+ build_gem "rack", "1.0.0"
+ end
end
+ it "installs the dependency from the pinned source" do
+ bundle :install, :artifice => "compact_index"
+ expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+ end
+ end
+
+ context "and the dependency is in both the top-level and a pinned source" do
before do
- build_repo gem_repo2 do
- build_gem "depends_on_rack", "1.0.1" do |s|
- s.add_dependency "rack"
+ update_repo gem_repo2 do
+ build_gem "rack", "1.0.0" do |s|
+ s.write "lib/rack.rb", "RACK = 'FAIL'"
end
end
- build_repo gem_repo3 do
- build_gem "unrelated_gem", "1.0.0"
+ update_repo gem_repo3 do
+ build_gem "rack", "1.0.0"
end
+ end
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ it "installs the dependency from the pinned source without warning" do
+ bundle :install, :artifice => "compact_index"
+ expect(the_bundle).to include_gems("depends_on_depends_on_rack 1.0.1", "depends_on_rack 1.0.1", "rack 1.0.0", :source => "remote3")
+ end
+ end
+ end
- gem "depends_on_rack"
+ context "when the lockfile has aggregated rubygems sources and newer versions of dependencies are available" do
+ before do
+ build_repo gem_repo2 do
+ build_gem "activesupport", "6.0.3.4" do |s|
+ s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2"
+ s.add_dependency "i18n", ">= 0.7", "< 2"
+ s.add_dependency "minitest", "~> 5.1"
+ s.add_dependency "tzinfo", "~> 1.1"
+ s.add_dependency "zeitwerk", "~> 2.2", ">= 2.2.2"
+ end
- source "#{file_uri_for(gem_repo3)}" do
- gem "unrelated_gem"
- end
- G
- end
+ build_gem "activesupport", "6.1.2.1" do |s|
+ s.add_dependency "concurrent-ruby", "~> 1.0", ">= 1.0.2"
+ s.add_dependency "i18n", ">= 1.6", "< 2"
+ s.add_dependency "minitest", ">= 5.1"
+ s.add_dependency "tzinfo", "~> 2.0"
+ s.add_dependency "zeitwerk", "~> 2.3"
+ end
- context "and the dependency is only in the top-level source" do
- before do
- update_repo gem_repo2 do
- build_gem "rack", "1.0.0"
- end
+ build_gem "concurrent-ruby", "1.1.8"
+ build_gem "concurrent-ruby", "1.1.9"
+ build_gem "connection_pool", "2.2.3"
+
+ build_gem "i18n", "1.8.9" do |s|
+ s.add_dependency "concurrent-ruby", "~> 1.0"
+ end
+
+ build_gem "minitest", "5.14.3"
+ build_gem "rack", "2.2.3"
+ build_gem "redis", "4.2.5"
+
+ build_gem "sidekiq", "6.1.3" do |s|
+ s.add_dependency "connection_pool", ">= 2.2.2"
+ s.add_dependency "rack", "~> 2.0"
+ s.add_dependency "redis", ">= 4.2.0"
end
- it "installs all gems without warning" do
- bundle :install
- expect(err).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0")
+ build_gem "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
- context "and the dependency is only in a pinned source" do
- before do
- update_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
- end
+ build_repo gem_repo3 do
+ build_gem "sidekiq-pro", "5.2.1" do |s|
+ s.add_dependency "connection_pool", ">= 2.2.3"
+ s.add_dependency "sidekiq", ">= 6.1.0"
+ end
+ end
+
+ gemfile <<-G
+ # frozen_string_literal: true
+
+ source "https://gem.repo2"
+
+ gem "activesupport"
+
+ source "https://gem.repo3" do
+ gem "sidekiq-pro"
end
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ remote: https://gem.repo3/
+ specs:
+ activesupport (6.0.3.4)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 0.7, < 2)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ zeitwerk (~> 2.2, >= 2.2.2)
+ concurrent-ruby (1.1.8)
+ connection_pool (2.2.3)
+ i18n (1.8.9)
+ concurrent-ruby (~> 1.0)
+ minitest (5.14.3)
+ rack (2.2.3)
+ redis (4.2.5)
+ sidekiq (6.1.3)
+ connection_pool (>= 2.2.2)
+ rack (~> 2.0)
+ redis (>= 4.2.0)
+ sidekiq-pro (5.2.1)
+ connection_pool (>= 2.2.3)
+ sidekiq (>= 6.1.0)
+ thread_safe (0.3.6)
+ tzinfo (1.2.9)
+ thread_safe (~> 0.1)
+ zeitwerk (2.4.2)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ activesupport
+ sidekiq-pro!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "does not install newer versions but updates the lockfile format when running bundle install in non frozen mode, and doesn't warn" do
+ bundle :install, :artifice => "compact_index"
+ expect(err).to be_empty
+
+ expect(the_bundle).to include_gems("activesupport 6.0.3.4")
+ expect(the_bundle).not_to include_gems("activesupport 6.1.2.1")
+ expect(the_bundle).to include_gems("tzinfo 1.2.9")
+ expect(the_bundle).not_to include_gems("tzinfo 2.0.4")
+ expect(the_bundle).to include_gems("concurrent-ruby 1.1.8")
+ expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.9")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ activesupport (6.0.3.4)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 0.7, < 2)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ zeitwerk (~> 2.2, >= 2.2.2)
+ concurrent-ruby (1.1.8)
+ connection_pool (2.2.3)
+ i18n (1.8.9)
+ concurrent-ruby (~> 1.0)
+ minitest (5.14.3)
+ rack (2.2.3)
+ redis (4.2.5)
+ sidekiq (6.1.3)
+ connection_pool (>= 2.2.2)
+ rack (~> 2.0)
+ redis (>= 4.2.0)
+ thread_safe (0.3.6)
+ tzinfo (1.2.9)
+ thread_safe (~> 0.1)
+ zeitwerk (2.4.2)
+
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ sidekiq-pro (5.2.1)
+ connection_pool (>= 2.2.3)
+ sidekiq (>= 6.1.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ activesupport
+ sidekiq-pro!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
- it "does not find the dependency" do
- bundle :install
- expect(err).to include("Could not find gem 'rack', which is required by gem 'depends_on_rack', in any of the relevant sources")
+ it "does not install newer versions or generate lockfile changes when running bundle install in frozen mode, and warns", :bundler => "< 3" do
+ initial_lockfile = lockfile
+
+ bundle "config set --local frozen true"
+ bundle :install, :artifice => "compact_index"
+
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+
+ expect(the_bundle).to include_gems("activesupport 6.0.3.4")
+ expect(the_bundle).not_to include_gems("activesupport 6.1.2.1")
+ expect(the_bundle).to include_gems("tzinfo 1.2.9")
+ expect(the_bundle).not_to include_gems("tzinfo 2.0.4")
+ expect(the_bundle).to include_gems("concurrent-ruby 1.1.8")
+ expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.9")
+
+ expect(lockfile).to eq(initial_lockfile)
+ end
+
+ it "fails when running bundle install in frozen mode", :bundler => "3" do
+ initial_lockfile = lockfile
+
+ bundle "config set --local frozen true"
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
+
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+
+ expect(lockfile).to eq(initial_lockfile)
+ end
+
+ it "splits sections and upgrades gems when running bundle update, and doesn't warn" do
+ bundle "update --all", :artifice => "compact_index"
+ expect(err).to be_empty
+
+ expect(the_bundle).not_to include_gems("activesupport 6.0.3.4")
+ expect(the_bundle).to include_gems("activesupport 6.1.2.1")
+ expect(the_bundle).not_to include_gems("tzinfo 1.2.9")
+ expect(the_bundle).to include_gems("tzinfo 2.0.4")
+ expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8")
+ expect(the_bundle).to include_gems("concurrent-ruby 1.1.9")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ activesupport (6.1.2.1)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 1.6, < 2)
+ minitest (>= 5.1)
+ tzinfo (~> 2.0)
+ zeitwerk (~> 2.3)
+ concurrent-ruby (1.1.9)
+ connection_pool (2.2.3)
+ i18n (1.8.9)
+ concurrent-ruby (~> 1.0)
+ minitest (5.14.3)
+ rack (2.2.3)
+ redis (4.2.5)
+ sidekiq (6.1.3)
+ connection_pool (>= 2.2.2)
+ rack (~> 2.0)
+ redis (>= 4.2.0)
+ tzinfo (2.0.4)
+ concurrent-ruby (~> 1.0)
+ zeitwerk (2.4.2)
+
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ sidekiq-pro (5.2.1)
+ connection_pool (>= 2.2.3)
+ sidekiq (>= 6.1.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ activesupport
+ sidekiq-pro!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "upgrades the lockfile format and upgrades the requested gem when running bundle update with an argument" do
+ bundle "update concurrent-ruby", :artifice => "compact_index"
+ expect(err).to be_empty
+
+ expect(the_bundle).to include_gems("activesupport 6.0.3.4")
+ expect(the_bundle).not_to include_gems("activesupport 6.1.2.1")
+ expect(the_bundle).to include_gems("tzinfo 1.2.9")
+ expect(the_bundle).not_to include_gems("tzinfo 2.0.4")
+ expect(the_bundle).to include_gems("concurrent-ruby 1.1.9")
+ expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ activesupport (6.0.3.4)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 0.7, < 2)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ zeitwerk (~> 2.2, >= 2.2.2)
+ concurrent-ruby (1.1.9)
+ connection_pool (2.2.3)
+ i18n (1.8.9)
+ concurrent-ruby (~> 1.0)
+ minitest (5.14.3)
+ rack (2.2.3)
+ redis (4.2.5)
+ sidekiq (6.1.3)
+ connection_pool (>= 2.2.2)
+ rack (~> 2.0)
+ redis (>= 4.2.0)
+ thread_safe (0.3.6)
+ tzinfo (1.2.9)
+ thread_safe (~> 0.1)
+ zeitwerk (2.4.2)
+
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ sidekiq-pro (5.2.1)
+ connection_pool (>= 2.2.3)
+ sidekiq (>= 6.1.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ activesupport
+ sidekiq-pro!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when a top-level gem has an indirect dependency present in the default source, but with a different version from the one resolved" do
+ before do
+ build_lib "activesupport", "7.0.0.alpha", :path => lib_path("rails/activesupport")
+ build_lib "rails", "7.0.0.alpha", :path => lib_path("rails") do |s|
+ s.add_dependency "activesupport", "= 7.0.0.alpha"
+ end
+
+ build_repo gem_repo2 do
+ build_gem "activesupport", "6.1.2"
+
+ build_gem "webpacker", "5.2.1" do |s|
+ s.add_dependency "activesupport", ">= 5.2"
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"
- end
+ gemfile <<-G
+ source "https://gem.repo2"
- update_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
- end
+ gemspec :path => "#{lib_path("rails")}"
+
+ gem "webpacker", "~> 5.0"
+ G
+ end
+
+ it "installs all gems without warning" do
+ bundle :install, :artifice => "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", "rails 7.0.0.alpha")
+ expect(the_bundle).to include_gems("activesupport 7.0.0.alpha", :source => "path@#{lib_path("rails/activesupport")}")
+ expect(the_bundle).to include_gems("rails 7.0.0.alpha", :source => "path@#{lib_path("rails")}")
+ end
+ end
+
+ context "when a pinned gem has an indirect dependency with more than one level of indirection in the default source " do
+ before do
+ build_repo gem_repo3 do
+ build_gem "handsoap", "0.2.5.5" do |s|
+ s.add_dependency "nokogiri", ">= 1.2.3"
end
+ end
- it "installs the dependency from the top-level source without warning" do
- bundle :install
- expect(err).not_to include("Warning")
- expect(the_bundle).to include_gems("depends_on_rack 1.0.1", "rack 1.0.0", "unrelated_gem 1.0.0")
+ update_repo gem_repo2 do
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.add_dependency "racca", "~> 1.4"
end
+
+ build_gem "racca", "1.5.2"
end
+
+ gemfile <<-G
+ source "https://gem.repo2"
+
+ source "https://gem.repo3" do
+ gem "handsoap"
+ end
+
+ gem "nokogiri"
+ G
+ end
+
+ it "installs from the default source without any warnings or errors and generates a proper lockfile" do
+ expected_lockfile = <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ nokogiri (1.11.1)
+ racca (~> 1.4)
+ racca (1.5.2)
+
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ handsoap (0.2.5.5)
+ nokogiri (>= 1.2.3)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ handsoap!
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose", :artifice => "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2")
+ expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3")
+ expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2")
+ expect(lockfile).to eq(expected_lockfile)
+
+ # Even if the gems are already installed
+ FileUtils.rm bundled_app_lock
+ bundle "install --verbose", :artifice => "compact_index"
+ expect(err).not_to include("Warning")
+ expect(the_bundle).to include_gems("handsoap 0.2.5.5", "nokogiri 1.11.1", "racca 1.5.2")
+ expect(the_bundle).to include_gems("handsoap 0.2.5.5", :source => "remote3")
+ expect(the_bundle).to include_gems("nokogiri 1.11.1", "racca 1.5.2", :source => "remote2")
+ expect(lockfile).to eq(expected_lockfile)
end
end
@@ -388,64 +944,145 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "not_in_repo1", "1.0.0"
end
- gemfile <<-G
- source "#{file_uri_for(gem_repo3)}"
- gem "not_in_repo1", :source => "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false
+ source "https://gem.repo3"
+ gem "not_in_repo1", :source => "https://gem.repo1"
G
end
it "does not install the gem" do
- bundle :install
expect(err).to include("Could not find gem 'not_in_repo1'")
end
end
context "with an existing lockfile" do
before do
- system_gems "rack-0.9.1", "rack-1.0.0", :path => :bundle_path
+ system_gems "rack-0.9.1", "rack-1.0.0", :path => default_bundle_path
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}
- remote: #{file_uri_for(gem_repo3)}
+ remote: https://gem.repo1
+ specs:
+
+ GEM
+ remote: https://gem.repo3
specs:
rack (0.9.1)
PLATFORMS
- ruby
+ #{specific_local_platform}
DEPENDENCIES
rack!
L
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo3)}" do
+ source "https://gem.repo1"
+ source "https://gem.repo3" do
gem 'rack'
end
G
end
- # Reproduction of https://github.com/bundler/bundler/issues/3298
+ # Reproduction of https://github.com/rubygems/bundler/issues/3298
it "does not unlock the installed gem on exec" do
expect(the_bundle).to include_gems("rack 0.9.1")
end
end
+ context "with a lockfile with aggregated rubygems sources" do
+ let(:aggregate_gem_section_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo1/
+ remote: https://gem.repo3/
+ specs:
+ rack (0.9.1)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ let(:split_gem_section_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ GEM
+ remote: https://gem.repo3/
+ specs:
+ rack (0.9.1)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo gem_repo3 do
+ build_gem "rack", "0.9.1"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ source "https://gem.repo3" do
+ gem 'rack'
+ end
+ G
+
+ lockfile aggregate_gem_section_lockfile
+ end
+
+ it "installs the existing lockfile but prints a warning", :bundler => "< 3" do
+ bundle "config set --local deployment true"
+
+ bundle "install", :artifice => "compact_index"
+
+ expect(lockfile).to eq(aggregate_gem_section_lockfile)
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+ expect(the_bundle).to include_gems("rack 0.9.1", :source => "remote3")
+ end
+
+ it "refuses to install the existing lockfile and prints an error", :bundler => "3" do
+ bundle "config set --local deployment true"
+
+ bundle "install", :artifice => "compact_index", :raise_on_error =>false
+
+ expect(lockfile).to eq(aggregate_gem_section_lockfile)
+ expect(err).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure.")
+ expect(out).to be_empty
+ end
+ end
+
context "with a path gem in the same Gemfile" do
before do
build_lib "foo"
gemfile <<-G
- gem "rack", :source => "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack", :source => "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
end
it "does not unlock the non-path gem after install" do
- bundle! :install
+ bundle :install, :artifice => "compact_index"
- bundle! %(exec ruby -e 'puts "OK"')
+ bundle %(exec ruby -e 'puts "OK"')
expect(out).to include("OK")
end
@@ -456,14 +1093,13 @@ RSpec.describe "bundle install with gems on multiple sources" do
before do
system_gems "rack-0.9.1"
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack" # shoud come from repo1!
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo1"
+ gem "rack" # should come from repo1!
G
end
it "installs the gems without any warning" do
- bundle :install
expect(err).not_to include("Warning")
expect(the_bundle).to include_gems("rack 1.0.0")
end
@@ -479,13 +1115,14 @@ RSpec.describe "bundle install with gems on multiple sources" do
# Installing this gemfile...
gemfile <<-G
- source '#{file_uri_for(gem_repo1)}'
+ source 'https://gem.repo1'
gem 'rack'
- gem 'foo', '~> 0.1', :source => '#{file_uri_for(gem_repo4)}'
- gem 'bar', '~> 0.1', :source => '#{file_uri_for(gem_repo4)}'
+ gem 'foo', '~> 0.1', :source => 'https://gem.repo4'
+ gem 'bar', '~> 0.1', :source => 'https://gem.repo4'
G
- bundle! :install, forgotten_command_line_options(:path => "../gems/system")
+ bundle "config set --local path ../gems/system"
+ bundle :install, :artifice => "compact_index"
# And then we add some new versions...
update_repo4 do
@@ -496,11 +1133,11 @@ RSpec.describe "bundle install with gems on multiple sources" do
it "allows them to be unlocked separately" do
# And install this gemfile, updating only foo.
- install_gemfile <<-G
- source '#{file_uri_for(gem_repo1)}'
+ install_gemfile <<-G, :artifice => "compact_index"
+ source 'https://gem.repo1'
gem 'rack'
- gem 'foo', '~> 0.2', :source => '#{file_uri_for(gem_repo4)}'
- gem 'bar', '~> 0.1', :source => '#{file_uri_for(gem_repo4)}'
+ gem 'foo', '~> 0.2', :source => 'https://gem.repo4'
+ gem 'bar', '~> 0.1', :source => 'https://gem.repo4'
G
# It should update foo to 0.2, but not the (locked) bar 0.1
@@ -511,17 +1148,20 @@ 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_repo3
+ build_repo gem_repo3 do
+ build_gem "rack"
+ end
+
build_lib "path1"
build_lib "path2"
build_git "git1"
build_git "git2"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo1"
gem "rails"
- source "#{file_uri_for(gem_repo3)}" do
+ source "https://gem.repo3" do
gem "rack"
end
@@ -533,7 +1173,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "does not re-resolve" do
- bundle! :install, :verbose => true
+ bundle :install, :artifice => "compact_index", :verbose => true
expect(out).to include("using resolution from the lockfile")
expect(out).not_to include("re-resolving dependencies")
end
@@ -542,27 +1182,24 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "when a gem is installed to system gems" do
before do
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo1"
gem "rack"
G
end
context "and the gemfile changes" do
it "is still able to find that gem from remote sources" do
- source_uri = file_uri_for(gem_repo1)
- second_uri = file_uri_for(gem_repo4)
-
build_repo4 do
build_gem "rack", "2.0.1.1.forked"
build_gem "thor", "0.19.1.1.forked"
end
# When this gemfile is installed...
- install_gemfile <<-G
- source "#{source_uri}"
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo1"
- source "#{second_uri}" do
+ source "https://gem.repo4" do
gem "rack", "2.0.1.1.forked"
gem "thor"
end
@@ -571,9 +1208,9 @@ RSpec.describe "bundle install with gems on multiple sources" do
# Then we change the Gemfile by adding a version to thor
gemfile <<-G
- source "#{source_uri}"
+ source "https://gem.repo1"
- source "#{second_uri}" do
+ source "https://gem.repo4" do
gem "rack", "2.0.1.1.forked"
gem "thor", "0.19.1.1.forked"
end
@@ -581,20 +1218,24 @@ RSpec.describe "bundle install with gems on multiple sources" do
G
# But we should still be able to find rack 2.0.1.1.forked and install it
- bundle! :install
+ bundle :install, :artifice => "compact_index"
end
end
end
describe "source changed to one containing a higher version of a dependency" do
before do
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo1"
gem "rack"
G
build_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "bar"
end
@@ -602,23 +1243,109 @@ RSpec.describe "bundle install with gems on multiple sources" do
s.add_dependency "bar", "=1.0.0"
end
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo2"
gem "rack"
gemspec :path => "#{tmp.join("gemspec_test")}"
G
end
- it "keeps the old version", :bundler => "2" do
+ it "conservatively installs the existing locked version" do
expect(the_bundle).to include_gems("rack 1.0.0")
end
+ end
+
+ it "doesn't update version when a gem uses a source block but a higher version from another source is already installed locally" do
+ build_repo2 do
+ build_gem "example", "0.1.0"
+ end
- it "installs the higher version in the new repo", :bundler => "3" do
- expect(the_bundle).to include_gems("rack 1.2")
+ build_repo4 do
+ build_gem "example", "1.0.2"
end
+
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "https://gem.repo4"
+
+ gem "example", :source => "https://gem.repo2"
+ G
+
+ bundle "info example"
+ expect(out).to include("example (0.1.0)")
+
+ system_gems "example-1.0.2", :path => default_bundle_path, :gem_repo => gem_repo4
+
+ bundle "update example --verbose", :artifice => "compact_index"
+ expect(out).not_to include("Using example 1.0.2")
+ expect(out).to include("Using example 0.1.0")
end
- context "when a gem is available from multiple ambiguous sources", :bundler => "3" do
+ it "fails inmmediately with a helpful error when a rubygems source does not exist and bundler/setup is required" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ source "https://gem.repo4" do
+ gem "example"
+ end
+ G
+
+ simulate_bundler_version_when_missing_prerelease_default_gem_activation do
+ ruby <<~R, :raise_on_error => false
+ require 'bundler/setup'
+ R
+ end
+
+ expect(last_command).to be_failure
+ expect(err).to include("Could not find gem 'example' in locally installed gems.")
+ end
+
+ it "fails inmmediately with a helpful error when a non retriable network error happens while resolving sources" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ source "https://gem.repo4" do
+ gem "example"
+ end
+ G
+
+ bundle "install", :artifice => nil, :raise_on_error => false
+
+ expect(last_command).to be_failure
+ expect(err).to include("Could not reach host gem.repo4. Check your network connection and try again.")
+ end
+
+ context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "< 3" do
+ it "succeeds but warns, suggesting a source block" do
+ build_repo4 do
+ build_gem "depends_on_rack" do |s|
+ s.add_dependency "rack"
+ end
+ build_gem "rack"
+ end
+
+ install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
+
+ source "https://gem.repo4" do
+ gem "depends_on_rack"
+ end
+
+ source "https://gem.repo1" do
+ gem "thin"
+ end
+ G
+ expect(err).to eq strip_whitespace(<<-EOS).strip
+ Warning: The gem 'rack' was found in multiple relevant sources.
+ * rubygems repository https://gem.repo1/
+ * rubygems repository https://gem.repo4/
+ You should add this gem to the source block for the source you wish it to be installed from.
+ EOS
+ expect(last_command).to be_success
+ expect(the_bundle).to be_locked
+ end
+ end
+
+ context "when an indirect dependency is available from multiple ambiguous sources", :bundler => "3" do
it "raises, suggesting a source block" do
build_repo4 do
build_gem "depends_on_rack" do |s|
@@ -627,21 +1354,93 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "rack"
end
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- source "#{file_uri_for(gem_repo1)}" do
+ install_gemfile <<-G, :artifice => "compact_index", :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo4" do
+ gem "depends_on_rack"
+ end
+ source "https://gem.repo1" do
gem "thin"
end
- gem "depends_on_rack"
G
expect(last_command).to be_failure
expect(err).to eq strip_whitespace(<<-EOS).strip
The gem 'rack' was found in multiple relevant sources.
- * rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally
- * rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally
+ * rubygems repository https://gem.repo1/
+ * rubygems repository https://gem.repo4/
You must add this gem to the source block for the source you wish it to be installed from.
EOS
expect(the_bundle).not_to be_locked
end
end
+
+ context "when upgrading a lockfile suffering from dependency confusion" do
+ before do
+ build_repo4 do
+ build_gem "mime-types", "3.0.0"
+ end
+
+ build_repo2 do
+ build_gem "capybara", "2.5.0" do |s|
+ s.add_dependency "mime-types", ">= 1.16"
+ end
+
+ build_gem "mime-types", "3.3.1"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
+
+ gem "capybara", "~> 2.5.0"
+
+ source "https://gem.repo4" do
+ gem "mime-types", "~> 3.0"
+ end
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ remote: https://gem.repo4/
+ specs:
+ capybara (2.5.0)
+ mime-types (>= 1.16)
+ mime-types (3.3.1)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ capybara (~> 2.5.0)
+ mime-types (~> 3.0)!
+ L
+ end
+
+ it "upgrades the lockfile correctly" do
+ bundle "lock --update", :artifice => "compact_index"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ capybara (2.5.0)
+ mime-types (>= 1.16)
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ mime-types (3.0.0)
+
+ PLATFORMS
+ #{specific_local_platform}
+
+ DEPENDENCIES
+ capybara (~> 2.5.0)
+ mime-types (~> 3.0)!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
end
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index 24b602589f..ce2823ce9a 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -1,53 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "bundle install with specific_platform enabled" do
- before do
- bundle "config set specific_platform true"
-
- build_repo2 do
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1")
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "universal-darwin" }
-
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.5")
-
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "universal-darwin" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.4")
-
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3")
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86_64-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x86-linux" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "x64-mingw32" }
- build_gem("google-protobuf", "3.0.0.alpha.5.0.3") {|s| s.platform = "universal-darwin" }
-
- build_gem("google-protobuf", "3.0.0.alpha.4.0")
- build_gem("google-protobuf", "3.0.0.alpha.3.1.pre")
- build_gem("google-protobuf", "3.0.0.alpha.3")
- build_gem("google-protobuf", "3.0.0.alpha.2.0")
- build_gem("google-protobuf", "3.0.0.alpha.1.1")
- build_gem("google-protobuf", "3.0.0.alpha.1.0")
-
- build_gem("facter", "2.4.6")
- build_gem("facter", "2.4.6") do |s|
- s.platform = "universal-darwin"
- s.add_runtime_dependency "CFPropertyList"
- end
- build_gem("CFPropertyList")
- end
- end
-
+RSpec.describe "bundle install with specific platforms" do
let(:google_protobuf) { <<-G }
source "#{file_uri_for(gem_repo2)}"
gem "google-protobuf"
@@ -56,54 +9,239 @@ RSpec.describe "bundle install with specific_platform enabled" do
context "when on a darwin machine" do
before { simulate_platform "x86_64-darwin-15" }
- it "locks to both the specific darwin platform and ruby" do
- install_gemfile!(google_protobuf)
- expect(the_bundle.locked_gems.platforms).to eq([pl("ruby"), pl("x86_64-darwin-15")])
+ it "locks to the specific darwin platform" do
+ setup_multiplatform_gem
+ install_gemfile(google_protobuf)
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")])
expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[
- google-protobuf-3.0.0.alpha.5.0.5.1
google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
])
end
- it "caches both the universal-darwin and ruby gems when --all-platforms is passed" do
+ it "understands that a non-platform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do
+ setup_multiplatform_gem
+
+ system_gems "bundler-2.1.4"
+
+ # Consistent location to install and look for gems
+ bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" }
+
+ install_gemfile(google_protobuf, :env => { "BUNDLER_VERSION" => "2.1.4" })
+
+ # simulate lockfile created with old bundler, which only locks for ruby platform
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ google-protobuf (3.0.0.alpha.5.0.5.1)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ google-protobuf
+
+ BUNDLED WITH
+ 2.1.4
+ L
+
+ # force strict usage of the lock file by setting frozen mode
+ bundle "config set --local frozen true", :env => { "BUNDLER_VERSION" => "2.1.4" }
+
+ # make sure the platform that got actually installed with the old bundler is used
+ expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
+ end
+
+ it "understands that a non-platform specific gem in a new lockfile locked only to RUBY doesn't necessarily mean installing the non-specific variant" do
+ setup_multiplatform_gem
+
+ system_gems "bundler-2.1.4"
+
+ # Consistent location to install and look for gems
+ bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" }
+
+ gemfile google_protobuf
+
+ # simulate lockfile created with old bundler, which only locks for ruby platform
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ google-protobuf (3.0.0.alpha.4.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ google-protobuf
+
+ BUNDLED WITH
+ 2.1.4
+ L
+
+ bundle "update", :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+
+ # make sure the platform that the platform specific dependency is used, since we're only locked to ruby
+ expect(the_bundle).to include_gem("google-protobuf 3.0.0.alpha.5.0.5.1 universal-darwin")
+
+ # make sure we're still only locked to ruby
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ google-protobuf (3.0.0.alpha.5.0.5.1)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ google-protobuf
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "doesn't discard previously installed platform specific gem and fall back to ruby on subsequent bundles" do
+ build_repo2 do
+ build_gem("libv8", "8.4.255.0")
+ build_gem("libv8", "8.4.255.0") {|s| s.platform = "universal-darwin" }
+
+ build_gem("mini_racer", "1.0.0") do |s|
+ s.add_runtime_dependency "libv8"
+ end
+ end
+
+ system_gems "bundler-2.1.4"
+
+ # Consistent location to install and look for gems
+ bundle "config set --local path vendor/bundle", :env => { "BUNDLER_VERSION" => "2.1.4" }
+
+ gemfile <<-G
+ source "https://localgemserver.test"
+ gem "libv8"
+ G
+
+ # simulate lockfile created with old bundler, which only locks for ruby platform
+ lockfile <<-L
+ GEM
+ remote: https://localgemserver.test/
+ specs:
+ libv8 (8.4.255.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ 2.1.4
+ L
+
+ bundle "install --verbose", :artifice => "compact_index", :env => { "BUNDLER_VERSION" => "2.1.4", "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ expect(out).to include("Installing libv8 8.4.255.0 (universal-darwin)")
+
+ bundle "add mini_racer --verbose", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ expect(out).to include("Using libv8 8.4.255.0 (universal-darwin)")
+ end
+
+ it "caches the universal-darwin gem when --all-platforms is passed and properly picks it up on further bundler invocations" do
+ setup_multiplatform_gem
+ gemfile(google_protobuf)
+ bundle "cache --all-platforms"
+ expect(cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")).to exist
+
+ bundle "install --verbose"
+ expect(err).to be_empty
+ end
+
+ it "caches the universal-darwin gem when cache_all_platforms is configured and properly picks it up on further bundler invocations" do
+ setup_multiplatform_gem
gemfile(google_protobuf)
- bundle! "package --all-platforms"
- expect([cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1"), cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")]).
- to all(exist)
+ bundle "config set --local cache_all_platforms true"
+ bundle "cache"
+ expect(cached_gem("google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin")).to exist
+
+ bundle "install --verbose"
+ expect(err).to be_empty
+ end
+
+ it "caches multiplatform git gems with a single gemspec when --all-platforms is passed" do
+ git = build_git "pg_array_parser", "1.0"
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "pg_array_parser", :git => "#{lib_path("pg_array_parser-1.0")}"
+ G
+
+ lockfile <<-L
+ GIT
+ remote: #{lib_path("pg_array_parser-1.0")}
+ revision: #{git.ref_for("master")}
+ specs:
+ pg_array_parser (1.0-java)
+ pg_array_parser (1.0)
+
+ GEM
+ specs:
+
+ PLATFORMS
+ java
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ pg_array_parser!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "config set --local cache_all true"
+ bundle "cache --all-platforms"
+
+ expect(err).to be_empty
end
it "uses the platform-specific gem with extra dependencies" do
- install_gemfile! <<-G
+ setup_multiplatform_gem_with_different_dependencies_per_platform
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "facter"
G
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
- expect(the_bundle.locked_gems.platforms).to eq([pl("ruby"), pl("x86_64-darwin-15")])
+ expect(the_bundle.locked_gems.platforms).to eq([pl("x86_64-darwin-15")])
expect(the_bundle).to include_gems("facter 2.4.6 universal-darwin", "CFPropertyList 1.0")
expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(["CFPropertyList-1.0",
- "facter-2.4.6",
"facter-2.4.6-universal-darwin"])
end
context "when adding a platform via lock --add_platform" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ end
+
it "adds the foreign platform" do
- install_gemfile!(google_protobuf)
- bundle! "lock --add-platform=#{x64_mingw}"
+ setup_multiplatform_gem
+ install_gemfile(google_protobuf)
+ bundle "lock --add-platform=#{x64_mingw}"
- expect(the_bundle.locked_gems.platforms).to eq([rb, x64_mingw, pl("x86_64-darwin-15")])
+ expect(the_bundle.locked_gems.platforms).to eq([x64_mingw, pl("x86_64-darwin-15")])
expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[
- google-protobuf-3.0.0.alpha.5.0.5.1
google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32
])
end
it "falls back on plain ruby when that version doesnt have a platform-specific gem" do
- install_gemfile!(google_protobuf)
- bundle! "lock --add-platform=#{java}"
+ setup_multiplatform_gem
+ install_gemfile(google_protobuf)
+ bundle "lock --add-platform=#{java}"
- expect(the_bundle.locked_gems.platforms).to eq([java, rb, pl("x86_64-darwin-15")])
+ expect(the_bundle.locked_gems.platforms).to eq([java, pl("x86_64-darwin-15")])
expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[
google-protobuf-3.0.0.alpha.5.0.5.1
google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
@@ -111,4 +249,67 @@ RSpec.describe "bundle install with specific_platform enabled" do
end
end
end
+
+ it "installs sorbet-static, which does not provide a pure ruby variant, just fine on truffleruby", :truffleruby do
+ build_repo2 do
+ build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "x86_64-linux" }
+ build_gem("sorbet-static", "0.5.6403") {|s| s.platform = "universal-darwin-20" }
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "sorbet-static", "0.5.6403"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ sorbet-static (0.5.6403-universal-darwin-20)
+ sorbet-static (0.5.6403-x86_64-linux)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ sorbet-static (= 0.5.6403)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose"
+ end
+
+ private
+
+ def setup_multiplatform_gem
+ build_repo2 do
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1")
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x86_64-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "x64-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5.1") {|s| s.platform = "universal-darwin" }
+
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x86_64-linux" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5") {|s| s.platform = "x64-mingw32" }
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.5")
+
+ build_gem("google-protobuf", "3.0.0.alpha.5.0.4") {|s| s.platform = "universal-darwin" }
+
+ build_gem("google-protobuf", "3.0.0.alpha.4.0")
+ build_gem("google-protobuf", "3.0.0.alpha.3.1.pre")
+ end
+ end
+
+ def setup_multiplatform_gem_with_different_dependencies_per_platform
+ build_repo2 do
+ build_gem("facter", "2.4.6")
+ build_gem("facter", "2.4.6") do |s|
+ s.platform = "universal-darwin"
+ s.add_runtime_dependency "CFPropertyList"
+ end
+ build_gem("CFPropertyList")
+ end
+ end
end
diff --git a/spec/bundler/install/gemfile_spec.rb b/spec/bundler/install/gemfile_spec.rb
index dd08939cb0..0f8f1ecfa8 100644
--- a/spec/bundler/install/gemfile_spec.rb
+++ b/spec/bundler/install/gemfile_spec.rb
@@ -3,7 +3,9 @@
RSpec.describe "bundle install" do
context "with duplicated gems" do
it "will display a warning" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
+
gem 'rails', '~> 4.0.0'
gem 'rails', '~> 4.0.0'
G
@@ -44,62 +46,52 @@ RSpec.describe "bundle install" do
end
it "uses the gemfile while in a subdirectory" do
bundled_app("subdir").mkpath
- Dir.chdir(bundled_app("subdir")) do
- bundle "install"
- bundle "list"
+ bundle "install", :dir => bundled_app("subdir")
+ bundle "list", :dir => bundled_app("subdir")
- expect(out).to include("rack (1.0.0)")
- end
+ expect(out).to include("rack (1.0.0)")
end
end
context "with deprecated features" do
- before :each do
- in_app_root
- end
-
it "reports that lib is an invalid option" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
gem "rack", :lib => "rack"
G
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/You passed :lib as an option for gem 'rack', but it is invalid/)
end
end
- context "with engine specified in symbol" do
+ context "with engine specified in symbol", :jruby do
it "does not raise any error parsing Gemfile" do
- simulate_ruby_version "2.3.0" do
- simulate_ruby_engine "jruby", "9.1.2.0" do
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo1)}"
- ruby "2.3.0", :engine => :jruby, :engine_version => "9.1.2.0"
- G
-
- expect(out).to match(/Bundle complete!/)
- end
- end
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ ruby "#{RUBY_VERSION}", :engine => :jruby, :engine_version => "#{RUBY_ENGINE_VERSION}"
+ G
+
+ expect(out).to match(/Bundle complete!/)
end
it "installation succeeds" do
- simulate_ruby_version "2.3.0" do
- simulate_ruby_engine "jruby", "9.1.2.0" do
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo1)}"
- ruby "2.3.0", :engine => :jruby, :engine_version => "9.1.2.0"
- gem "rack"
- G
-
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ ruby "#{RUBY_VERSION}", :engine => :jruby, :engine_version => "#{RUBY_ENGINE_VERSION}"
+ gem "rack"
+ G
+
+ expect(the_bundle).to include_gems "rack 1.0.0"
end
end
context "with a Gemfile containing non-US-ASCII characters" do
it "reads the Gemfile with the UTF-8 encoding by default" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
str = "Il était une fois ..."
puts "The source encoding is: " + str.encoding.name
G
@@ -113,6 +105,8 @@ 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)}"
+
str = "Il #{"\xE9".dup.force_encoding("binary")}tait une fois ..."
puts "The source encoding is: " + str.encoding.name
G
diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb
index a294b83d1c..0cee69f702 100644
--- a/spec/bundler/install/gems/compact_index_spec.rb
+++ b/spec/bundler/install/gems/compact_index_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "compact index api" do
gem "rack"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -21,7 +21,7 @@ RSpec.describe "compact index api" do
gem " sinatra"
G
- bundle :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index", :raise_on_error => false
expect(err).to include("' sinatra' is not a valid gem name because it contains whitespace.")
end
@@ -31,7 +31,7 @@ RSpec.describe "compact index api" do
gem "rails"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems(
"rails 2.3.2",
@@ -51,7 +51,7 @@ RSpec.describe "compact index api" do
build_gem "Rack", "0.1"
end
- install_gemfile! <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
gem "rack", "1.0"
gem "Rack", "0.1"
@@ -59,7 +59,7 @@ RSpec.describe "compact index api" do
# can't use `include_gems` here since the `require` will conflict on a
# case-insensitive FS
- run! "Bundler.require; puts Gem.loaded_specs.values_at('rack', 'Rack').map(&:full_name)"
+ run "Bundler.require; puts Gem.loaded_specs.values_at('rack', 'Rack').map(&:full_name)"
expect(out).to eq("rack-1.0\nRack-0.1")
end
@@ -69,18 +69,20 @@ RSpec.describe "compact index api" do
gem "net-sftp"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
expect(the_bundle).to include_gems "net-sftp 1.1.1"
end
- it "should use the endpoint when using --deployment" do
+ it "should use the endpoint when using deployment mode" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
- bundle! :install, forgotten_command_line_options(:deployment => true, :path => "vendor/bundle").merge(:artifice => "compact_index")
+ bundle "config set --local deployment true"
+ bundle "config set --local path vendor/bundle"
+ bundle :install, :artifice => "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -98,12 +100,12 @@ RSpec.describe "compact index api" do
end
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
expect(the_bundle).to include_gems("rails 2.3.2")
end
- it "handles git dependencies that are in rubygems using --deployment" do
+ it "handles git dependencies that are in rubygems using deployment mode" do
build_git "foo" do |s|
s.executables = "foobar"
s.add_dependency "rails", "2.3.2"
@@ -114,14 +116,15 @@ RSpec.describe "compact index api" do
gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
- bundle "install --deployment", :artifice => "compact_index"
+ bundle "config set --local deployment true"
+ bundle :install, :artifice => "compact_index"
expect(the_bundle).to include_gems("rails 2.3.2")
end
- it "doesn't fail if you only have a git gem with no deps when using --deployment" do
+ it "doesn't fail if you only have a git gem with no deps when using deployment mode" do
build_git "foo"
gemfile <<-G
source "#{source_uri}"
@@ -129,31 +132,19 @@ RSpec.describe "compact index api" do
G
bundle "install", :artifice => "compact_index"
- bundle! :install, forgotten_command_line_options(:deployment => true).merge(:artifice => "compact_index")
+ bundle "config set --local deployment true"
+ bundle :install, :artifice => "compact_index"
expect(the_bundle).to include_gems("foo 1.0")
end
- it "falls back when the API errors out" do
- simulate_platform mswin
-
- gemfile <<-G
- source "#{source_uri}"
- gem "rcov"
- G
-
- bundle! :install, :artifice => "windows"
- expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rcov 1.0.0"
- end
-
it "falls back when the API URL returns 403 Forbidden" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
- bundle! :install, :verbose => true, :artifice => "compact_index_forbidden"
+ bundle :install, :verbose => true, :artifice => "compact_index_forbidden"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -164,7 +155,7 @@ RSpec.describe "compact index api" do
gem "rack"
G
- bundle! :install, :verbose => true, :artifice => "compact_index_checksum_mismatch"
+ bundle :install, :verbose => true, :artifice => "compact_index_checksum_mismatch"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(out).to include <<-'WARN'
The checksum of /versions does not match the checksum provided by the server! Something is wrong (local checksum is "\"d41d8cd98f00b204e9800998ecf8427e\"", was expecting "\"123\"").
@@ -180,7 +171,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -191,7 +182,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle! :install, :artifice => "compact_index_host_redirect"
+ bundle :install, :artifice => "compact_index_host_redirect"
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -214,7 +205,7 @@ The checksum of /versions does not match the checksum provided by the server! So
H
end
- bundle! :install, :artifice => "compact_index_host_redirect", :requires => [lib_path("disable_net_http_persistent.rb")]
+ bundle :install, :artifice => "compact_index_host_redirect", :requires => [lib_path("disable_net_http_persistent.rb")]
expect(out).to_not match(/Too many redirects/)
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -225,7 +216,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :artifice => "compact_index_redirects"
+ bundle :install, :artifice => "compact_index_redirects", :raise_on_error => false
expect(err).to match(/Too many redirects/)
end
@@ -247,21 +238,44 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle! "update --full-index", :artifice => "compact_index", :all => true
+ bundle "update --full-index", :artifice => "compact_index", :all => true
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
it "does not double check for gems that are only installed locally" do
- system_gems %w[rack-1.0.0 thin-1.0 net_a-1.0]
- bundle! "config set --local path.system true"
+ build_repo2 do
+ build_gem "net_a" do |s|
+ s.add_dependency "net_b"
+ s.add_dependency "net_build_extensions"
+ end
+
+ build_gem "net_b"
+
+ build_gem "net_build_extensions" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/net_build_extensions.rb", "w") do |f|
+ f.puts "NET_BUILD_EXTENSIONS = 'YES'"
+ end
+ end
+ RUBY
+ end
+ end
+
+ system_gems %w[rack-1.0.0 thin-1.0 net_a-1.0], :gem_repo => gem_repo2
+ bundle "config set --local path.system true"
ENV["BUNDLER_SPEC_ALL_REQUESTS"] = strip_whitespace(<<-EOS).strip
#{source_uri}/versions
#{source_uri}/info/rack
EOS
- install_gemfile! <<-G, :artifice => "compact_index", :verbose => true
+ install_gemfile <<-G, :artifice => "compact_index", :verbose => true, :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
source "#{source_uri}"
gem "rack"
G
@@ -283,7 +297,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "back_deps"
G
- bundle! :install, :artifice => "compact_index_extra"
+ bundle :install, :artifice => "compact_index_extra"
expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0"
end
@@ -295,7 +309,7 @@ The checksum of /versions does not match the checksum provided by the server! So
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- install_gemfile! <<-G, :artifice => "compact_index_extra", :verbose => true
+ install_gemfile <<-G, :artifice => "compact_index_extra", :verbose => true
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -310,7 +324,7 @@ The checksum of /versions does not match the checksum provided by the server! So
source "#{source_uri}"
gem "rack", "1.0.0"
G
- bundle! :install, :artifice => "compact_index_extra_api"
+ bundle :install, :artifice => "compact_index_extra_api"
expect(the_bundle).to include_gems "rack 1.0.0"
build_repo4 do
@@ -324,7 +338,7 @@ The checksum of /versions does not match the checksum provided by the server! So
source "#{source_uri}/extra"
gem "rack", "1.2"
G
- bundle! :install, :artifice => "compact_index_extra_api"
+ bundle :install, :artifice => "compact_index_extra_api"
expect(the_bundle).to include_gems "rack 1.2"
end
@@ -346,32 +360,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'somegem', '1.0.0'
G
- bundle! :install, :artifice => "compact_index_extra_api"
-
- expect(the_bundle).to include_gems "somegem 1.0.0"
- expect(the_bundle).to include_gems "activesupport 1.2.3"
- end
-
- it "considers all possible versions of dependencies from all api gem sources when using blocks", :bundler => "< 3" do
- # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that
- # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0
- # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other
- # repo and installs it.
- build_repo4 do
- build_gem "activesupport", "1.2.0"
- build_gem "somegem", "1.0.0" do |s|
- s.add_dependency "activesupport", "1.2.3" # This version exists only in repo1
- end
- end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra" do
- gem 'somegem', '1.0.0'
- end
- G
-
- bundle! :install, :artifice => "compact_index_extra_api"
+ bundle :install, :artifice => "compact_index_extra_api"
expect(the_bundle).to include_gems "somegem 1.0.0"
expect(the_bundle).to include_gems "activesupport 1.2.3"
@@ -392,7 +381,7 @@ The checksum of /versions does not match the checksum provided by the server! So
end
G
- bundle! :install, :artifice => "compact_index_extra"
+ bundle :install, :artifice => "compact_index_extra"
expect(out).to include("Fetching gem metadata from http://localgemserver.test/")
expect(out).to include("Fetching source index from http://localgemserver.test/extra")
@@ -404,22 +393,19 @@ The checksum of /versions does not match the checksum provided by the server! So
s.add_dependency "foo"
end
build_gem "missing"
- # need to hit the limit
- 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i|
- build_gem "gem#{i}"
- end
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- gemfile <<-G
+ api_request_limit = low_api_request_limit_for(gem_repo2)
+
+ install_gemfile <<-G, :artifice => "compact_index_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
end
G
- bundle! :install, :artifice => "compact_index_extra_missing"
expect(the_bundle).to include_gems "back_deps 1.0"
end
@@ -429,15 +415,13 @@ The checksum of /versions does not match the checksum provided by the server! So
s.add_dependency "foo"
end
build_gem "missing"
- # need to hit the limit
- 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i|
- build_gem "gem#{i}"
- end
FileUtils.rm_rf Dir[gem_repo4("gems/foo-*.gem")]
end
- install_gemfile! <<-G, :artifice => "compact_index_extra_api_missing"
+ api_request_limit = low_api_request_limit_for(gem_repo4)
+
+ install_gemfile <<-G, :artifice => "compact_index_extra_api_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
@@ -454,11 +438,11 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'foo'
G
- bundle! :install, :artifice => "compact_index_api_missing"
+ bundle :install, :artifice => "compact_index_api_missing"
expect(the_bundle).to include_gems "foo 1.0"
end
- it "fetches again when more dependencies are found in subsequent sources using --deployment", :bundler => "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode", :bundler => "< 3" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -472,13 +456,13 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "back_deps"
G
- bundle! :install, :artifice => "compact_index_extra"
-
- bundle "install --deployment", :artifice => "compact_index_extra"
+ bundle :install, :artifice => "compact_index_extra"
+ bundle "config --set local deployment true"
+ bundle :install, :artifice => "compact_index_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "fetches again when more dependencies are found in subsequent sources using --deployment with blocks" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode with blocks" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -493,20 +477,26 @@ The checksum of /versions does not match the checksum provided by the server! So
end
G
- bundle! :install, :artifice => "compact_index_extra"
-
- bundle "install --deployment", :artifice => "compact_index_extra"
+ bundle :install, :artifice => "compact_index_extra"
+ bundle "config set --local deployment true"
+ bundle :install, :artifice => "compact_index_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
it "does not refetch if the only unmet dependency is bundler" do
+ build_repo2 do
+ build_gem "bundler_dep" do |s|
+ s.add_dependency "bundler"
+ end
+ end
+
gemfile <<-G
source "#{source_uri}"
gem "bundler_dep"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
@@ -518,7 +508,7 @@ The checksum of /versions does not match the checksum provided by the server! So
source "#{source_uri}"
gem "rails"
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
expect(the_bundle).to include_gems "rails 2.3.2"
end
@@ -562,7 +552,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'rack-obama'
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
expect(out).to include("Post-install message from rack:")
end
@@ -572,7 +562,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem 'rack_middleware'
G
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
expect(out).to include("Post-install message from rack:")
expect(out).to include("Rack's post install message")
end
@@ -581,7 +571,7 @@ The checksum of /versions does not match the checksum provided by the server! So
let(:user) { "user" }
let(:password) { "pass" }
let(:basic_auth_source_uri) do
- uri = URI.parse(source_uri)
+ uri = Bundler::URI.parse(source_uri)
uri.user = user
uri.password = password
@@ -594,32 +584,22 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle! :install, :artifice => "compact_index_basic_authentication"
+ bundle :install, :artifice => "compact_index_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
- it "strips http basic authentication creds for modern index" do
+ it "passes basic authentication details and strips out creds also in verbose mode" do
gemfile <<-G
source "#{basic_auth_source_uri}"
gem "rack"
G
- bundle! :install, :artifice => "endopint_marshal_fail_basic_authentication"
+ bundle :install, :verbose => true, :artifice => "compact_index_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
- it "strips http basic auth creds when it can't reach the server" do
- gemfile <<-G
- source "#{basic_auth_source_uri}"
- gem "rack"
- G
-
- bundle :install, :artifice => "endpoint_500"
- expect(out).not_to include("#{user}:#{password}")
- end
-
it "strips http basic auth creds when warning about ambiguous sources", :bundler => "< 3" do
gemfile <<-G
source "#{basic_auth_source_uri}"
@@ -627,7 +607,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle! :install, :artifice => "compact_index_basic_authentication"
+ bundle :install, :artifice => "compact_index_basic_authentication"
expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
expect(err).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -639,7 +619,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle! :install, :artifice => "compact_index_creds_diff_host"
+ bundle :install, :artifice => "compact_index_creds_diff_host"
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -654,7 +634,7 @@ The checksum of /versions does not match the checksum provided by the server! So
it "reads authentication details by host name from bundle config" do
bundle "config set #{source_hostname} #{user}:#{password}"
- bundle! :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, :artifice => "compact_index_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -664,7 +644,7 @@ The checksum of /versions does not match the checksum provided by the server! So
# The trailing slash is necessary here; Fetcher canonicalizes the URI.
bundle "config set #{source_uri}/ #{user}:#{password}"
- bundle! :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, :artifice => "compact_index_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -672,7 +652,7 @@ The checksum of /versions does not match the checksum provided by the server! So
it "should use the API" do
bundle "config set #{source_hostname} #{user}:#{password}"
- bundle! :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, :artifice => "compact_index_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -685,19 +665,19 @@ The checksum of /versions does not match the checksum provided by the server! So
bundle "config set #{source_hostname} otheruser:wrong"
- bundle! :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, :artifice => "compact_index_strict_basic_authentication"
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "shows instructions if auth is not provided for the source" do
- bundle :install, :artifice => "compact_index_strict_basic_authentication"
- expect(err).to include("bundle config set #{source_hostname} username:password")
+ bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false
+ expect(err).to include("bundle config set --global #{source_hostname} username:password")
end
it "fails if authentication has already been provided, but failed" do
bundle "config set #{source_hostname} #{user}:wrong"
- bundle :install, :artifice => "compact_index_strict_basic_authentication"
+ bundle :install, :artifice => "compact_index_strict_basic_authentication", :raise_on_error => false
expect(err).to include("Bad username or password")
end
end
@@ -711,7 +691,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle! :install, :artifice => "compact_index_basic_authentication"
+ bundle :install, :artifice => "compact_index_basic_authentication"
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
@@ -736,7 +716,7 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install, :env => { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" }
+ bundle :install, :env => { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, :raise_on_error => false
expect(err).to include("OpenSSL")
end
end
@@ -756,40 +736,40 @@ The checksum of /versions does not match the checksum provided by the server! So
gem "rack"
G
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/could not verify the SSL certificate/i)
end
end
context ".gemrc with sources is present" do
- before do
+ it "uses other sources declared in the Gemfile" do
File.open(home(".gemrc"), "w") do |file|
file.puts({ :sources => ["https://rubygems.org"] }.to_yaml)
end
- end
- after do
- home(".gemrc").rmtree
- end
-
- it "uses other sources declared in the Gemfile" do
- gemfile <<-G
- source "#{source_uri}"
- gem 'rack'
- G
+ begin
+ gemfile <<-G
+ source "#{source_uri}"
+ gem 'rack'
+ G
- bundle! :install, :artifice => "compact_index_forbidden"
+ bundle :install, :artifice => "compact_index_forbidden"
+ ensure
+ home(".gemrc").rmtree
+ end
end
end
it "performs partial update with a non-empty range" do
+ skip "HTTP_RANGE not set" if Gem.win_platform?
+
gemfile <<-G
source "#{source_uri}"
gem 'rack', '0.9.1'
G
# Initial install creates the cached versions file
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
# Update the Gemfile so we can check subsequent install was successful
gemfile <<-G
@@ -798,7 +778,7 @@ The checksum of /versions does not match the checksum provided by the server! So
G
# Second install should make only a partial request to /versions
- bundle! :install, :artifice => "compact_index_partial_update"
+ bundle :install, :artifice => "compact_index_partial_update"
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -815,12 +795,34 @@ The checksum of /versions does not match the checksum provided by the server! So
FileUtils.mkdir_p(File.dirname(versions))
FileUtils.touch(versions)
- bundle! :install, :artifice => "compact_index_concurrent_download"
+ bundle :install, :artifice => "compact_index_concurrent_download"
expect(File.read(versions)).to start_with("created_at")
expect(the_bundle).to include_gems "rack 1.0.0"
end
+ it "performs full update if server endpoints serve partial content responses but don't have incremental content and provide no Etag" do
+ build_repo4 do
+ build_gem "rack", "0.9.1"
+ end
+
+ install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'rack', '0.9.1'
+ G
+
+ update_repo4 do
+ build_gem "rack", "1.0.0"
+ end
+
+ install_gemfile <<-G, :artifice => "compact_index_partial_update_no_etag_not_incremental", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ source "#{source_uri}"
+ gem 'rack', '1.0.0'
+ G
+
+ expect(the_bundle).to include_gems "rack 1.0.0"
+ end
+
it "performs full update of compact index info cache if range is not satisfiable" do
gemfile <<-G
source "#{source_uri}"
@@ -830,7 +832,7 @@ The checksum of /versions does not match the checksum provided by the server! So
rake_info_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info", "rack")
- bundle! :install, :artifice => "compact_index"
+ bundle :install, :artifice => "compact_index"
expected_rack_info_content = File.read(rake_info_path)
@@ -845,7 +847,7 @@ The checksum of /versions does not match the checksum provided by the server! So
# The cache files now being longer means the requested range is going to be not satisfiable
# Bundler must end up requesting the whole file to fix things up.
- bundle! :install, :artifice => "compact_index_range_not_satisfiable"
+ bundle :install, :artifice => "compact_index_range_not_satisfiable"
resulting_rack_info_content = File.read(rake_info_path)
@@ -853,11 +855,11 @@ The checksum of /versions does not match the checksum provided by the server! So
end
it "fails gracefully when the source URI has an invalid scheme" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "htps://rubygems.org"
gem "rack"
G
- expect(exitstatus).to eq(15) if exitstatus
+ expect(exitstatus).to eq(15)
expect(err).to end_with(<<-E.strip)
The request uri `htps://index.rubygems.org/versions` has an invalid scheme (`htps`). Did you mean `http` or `https`?
E
@@ -865,12 +867,12 @@ The checksum of /versions does not match the checksum provided by the server! So
describe "checksum validation" do
it "raises when the checksum does not match" do
- install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum"
+ install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum", :raise_on_error => false
source "#{source_uri}"
gem "rack"
G
- expect(exitstatus).to eq(19) if exitstatus
+ expect(exitstatus).to eq(19)
expect(err).
to include("Bundler cannot continue installing rack (1.0.0).").
and include("The checksum for the downloaded `rack-1.0.0.gem` does not match the checksum given by the server.").
@@ -879,23 +881,23 @@ The checksum of /versions does not match the checksum provided by the server! So
and include("1. delete the downloaded gem located at: `#{default_bundle_path}/gems/rack-1.0.0/rack-1.0.0.gem`").
and include("2. run `bundle install`").
and include("If you wish to continue installing the downloaded gem, and are certain it does not pose a security issue despite the mismatching checksum, do the following:").
- and include("1. run `bundle config set disable_checksum_validation true` to turn off checksum verification").
+ and include("1. run `bundle config set --local disable_checksum_validation true` to turn off checksum verification").
and include("2. run `bundle install`").
and match(/\(More info: The expected SHA256 checksum was "#{"ab" * 22}", but the checksum for the downloaded gem was ".+?"\.\)/)
end
it "raises when the checksum is the wrong length" do
- install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum", :env => { "BUNDLER_SPEC_RACK_CHECKSUM" => "checksum!" }
+ install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum", :env => { "BUNDLER_SPEC_RACK_CHECKSUM" => "checksum!", "DEBUG" => "1" }, :verbose => true, :raise_on_error => false
source "#{source_uri}"
gem "rack"
G
- expect(exitstatus).to eq(5) if exitstatus
+ expect(exitstatus).to eq(5)
expect(err).to include("The given checksum for rack-1.0.0 (\"checksum!\") is not a valid SHA256 hexdigest nor base64digest")
end
it "does not raise when disable_checksum_validation is set" do
- bundle! "config set disable_checksum_validation true"
- install_gemfile! <<-G, :artifice => "compact_index_wrong_gem_checksum"
+ bundle "config set disable_checksum_validation true"
+ install_gemfile <<-G, :artifice => "compact_index_wrong_gem_checksum"
source "#{source_uri}"
gem "rack"
G
@@ -903,7 +905,7 @@ The checksum of /versions does not match the checksum provided by the server! So
end
it "works when cache dir is world-writable" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, :artifice => "compact_index"
File.umask(0000)
source "#{source_uri}"
gem "rack"
@@ -911,11 +913,11 @@ The checksum of /versions does not match the checksum provided by the server! So
end
it "doesn't explode when the API dependencies are wrong" do
- install_gemfile <<-G, :artifice => "compact_index_wrong_dependencies", :env => { "DEBUG" => "true" }
+ install_gemfile <<-G, :artifice => "compact_index_wrong_dependencies", :env => { "DEBUG" => "true" }, :raise_on_error => false
source "#{source_uri}"
gem "rails"
G
- deps = [Gem::Dependency.new("rake", "= 12.3.2"),
+ deps = [Gem::Dependency.new("rake", "= 13.0.1"),
Gem::Dependency.new("actionpack", "= 2.3.2"),
Gem::Dependency.new("activerecord", "= 2.3.2"),
Gem::Dependency.new("actionmailer", "= 2.3.2"),
@@ -927,14 +929,15 @@ Either installing with `--full-index` or running `bundle update rails` should fi
end
it "does not duplicate specs in the lockfile when updating and a dependency is not installed" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, :artifice => "compact_index"
+ source "#{file_uri_for(gem_repo1)}"
source "#{source_uri}" do
gem "rails"
gem "activemerchant"
end
G
- gem_command! :uninstall, "activemerchant"
- bundle! "update rails", :artifice => "compact_index"
+ gem_command "uninstall activemerchant"
+ bundle "update rails", :artifice => "compact_index"
expect(lockfile.scan(/activemerchant \(/).size).to eq(1)
end
end
diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb
index a8713eb445..9738a75474 100644
--- a/spec/bundler/install/gems/dependency_api_spec.rb
+++ b/spec/bundler/install/gems/dependency_api_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe "gemcutter's dependency API" do
gem " sinatra"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, :artifice => "endpoint", :raise_on_error => false
expect(err).to include("' sinatra' is not a valid gem name because it contains whitespace.")
end
@@ -53,14 +53,16 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "net-sftp 1.1.1"
end
- it "should use the endpoint when using --deployment" do
+ it "should use the endpoint when using deployment mode" do
gemfile <<-G
source "#{source_uri}"
gem "rack"
G
bundle :install, :artifice => "endpoint"
- bundle! :install, forgotten_command_line_options(:deployment => true, :path => "vendor/bundle").merge(:artifice => "endpoint")
+ bundle "config set --local deployment true"
+ bundle "config set --local path vendor/bundle"
+ bundle :install, :artifice => "endpoint"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -83,7 +85,7 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems("rails 2.3.2")
end
- it "handles git dependencies that are in rubygems using --deployment" do
+ it "handles git dependencies that are in rubygems using deployment mode" do
build_git "foo" do |s|
s.executables = "foobar"
s.add_dependency "rails", "2.3.2"
@@ -96,12 +98,13 @@ RSpec.describe "gemcutter's dependency API" do
bundle :install, :artifice => "endpoint"
- bundle "install --deployment", :artifice => "endpoint"
+ bundle "config set --local deployment true"
+ bundle :install, :artifice => "endpoint"
expect(the_bundle).to include_gems("rails 2.3.2")
end
- it "doesn't fail if you only have a git gem with no deps when using --deployment" do
+ it "doesn't fail if you only have a git gem with no deps when using deployment mode" do
build_git "foo"
gemfile <<-G
source "#{source_uri}"
@@ -109,7 +112,8 @@ RSpec.describe "gemcutter's dependency API" do
G
bundle "install", :artifice => "endpoint"
- bundle! :install, forgotten_command_line_options(:deployment => true).merge(:artifice => "endpoint")
+ bundle "config set --local deployment true"
+ bundle :install, :artifice => "endpoint"
expect(the_bundle).to include_gems("foo 1.0")
end
@@ -117,12 +121,20 @@ RSpec.describe "gemcutter's dependency API" do
it "falls back when the API errors out" do
simulate_platform mswin
+ build_repo2 do
+ # The rcov gem is platform mswin32, but has no arch
+ build_gem "rcov" do |s|
+ s.platform = Gem::Platform.new([nil, "mswin32", nil])
+ s.write "lib/rcov.rb", "RCOV = '1.0.0'"
+ end
+ end
+
gemfile <<-G
source "#{source_uri}"
gem "rcov"
G
- bundle :install, :artifice => "windows"
+ bundle :install, :artifice => "windows", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems "rcov 1.0.0"
end
@@ -215,7 +227,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint_redirect"
+ bundle :install, :artifice => "endpoint_redirect", :raise_on_error => false
expect(err).to match(/Too many redirects/)
end
@@ -237,7 +249,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle! "update --full-index", :artifice => "endpoint", :all => true
+ bundle "update --full-index", :artifice => "endpoint", :all => true
expect(out).to include("Fetching source index from #{source_uri}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -320,31 +332,6 @@ RSpec.describe "gemcutter's dependency API" do
gem 'somegem', '1.0.0'
G
- bundle! :install, :artifice => "endpoint_extra_api"
-
- expect(the_bundle).to include_gems "somegem 1.0.0"
- expect(the_bundle).to include_gems "activesupport 1.2.3"
- end
-
- it "considers all possible versions of dependencies from all api gem sources using blocks" do
- # In this scenario, the gem "somegem" only exists in repo4. It depends on specific version of activesupport that
- # exists only in repo1. There happens also be a version of activesupport in repo4, but not the one that version 1.0.0
- # of somegem wants. This test makes sure that bundler actually finds version 1.2.3 of active support in the other
- # repo and installs it.
- build_repo4 do
- build_gem "activesupport", "1.2.0"
- build_gem "somegem", "1.0.0" do |s|
- s.add_dependency "activesupport", "1.2.3" # This version exists only in repo1
- end
- end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra" do
- gem 'somegem', '1.0.0'
- end
- G
-
bundle :install, :artifice => "endpoint_extra_api"
expect(the_bundle).to include_gems "somegem 1.0.0"
@@ -378,21 +365,18 @@ RSpec.describe "gemcutter's dependency API" do
s.add_dependency "foo"
end
build_gem "missing"
- # need to hit the limit
- 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i|
- build_gem "gem#{i}"
- end
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- gemfile <<-G
+ api_request_limit = low_api_request_limit_for(gem_repo2)
+
+ install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}"
source "#{source_uri}/extra"
gem "back_deps"
G
- bundle :install, :artifice => "endpoint_extra_missing"
expect(the_bundle).to include_gems "back_deps 1.0"
end
@@ -402,22 +386,19 @@ RSpec.describe "gemcutter's dependency API" do
s.add_dependency "foo"
end
build_gem "missing"
- # need to hit the limit
- 1.upto(Bundler::Source::Rubygems::API_REQUEST_LIMIT) do |i|
- build_gem "gem#{i}"
- end
FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
end
- gemfile <<-G
+ api_request_limit = low_api_request_limit_for(gem_repo2)
+
+ install_gemfile <<-G, :artifice => "endpoint_extra_missing", :requires => [api_request_limit_hack_file], :env => { "BUNDLER_SPEC_API_REQUEST_LIMIT" => api_request_limit.to_s }.merge(env_for_missing_prerelease_default_gem_activation)
source "#{source_uri}"
source "#{source_uri}/extra" do
gem "back_deps"
end
G
- bundle :install, :artifice => "endpoint_extra_missing"
expect(the_bundle).to include_gems "back_deps 1.0"
end
@@ -432,7 +413,7 @@ RSpec.describe "gemcutter's dependency 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", :bundler => "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode", :bundler => "< 3" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -447,12 +428,12 @@ RSpec.describe "gemcutter's dependency API" do
G
bundle :install, :artifice => "endpoint_extra"
-
- bundle "install --deployment", :artifice => "endpoint_extra"
+ bundle "config set --local deployment true"
+ bundle :install, :artifice => "endpoint_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "fetches again when more dependencies are found in subsequent sources using --deployment with blocks" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode with blocks" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
@@ -468,19 +449,25 @@ RSpec.describe "gemcutter's dependency API" do
G
bundle :install, :artifice => "endpoint_extra"
-
- bundle "install --deployment", :artifice => "endpoint_extra"
+ bundle "config set --local deployment true"
+ bundle "install", :artifice => "endpoint_extra"
expect(the_bundle).to include_gems "back_deps 1.0"
end
it "does not refetch if the only unmet dependency is bundler" do
+ build_repo2 do
+ build_gem "bundler_dep" do |s|
+ s.add_dependency "bundler"
+ end
+ end
+
gemfile <<-G
source "#{source_uri}"
gem "bundler_dep"
G
- bundle :install, :artifice => "endpoint"
+ bundle :install, :artifice => "endpoint", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
@@ -555,7 +542,7 @@ RSpec.describe "gemcutter's dependency API" do
let(:user) { "user" }
let(:password) { "pass" }
let(:basic_auth_source_uri) do
- uri = URI.parse(source_uri)
+ uri = Bundler::URI.parse(source_uri)
uri.user = user
uri.password = password
@@ -573,13 +560,24 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "rack 1.0.0"
end
+ it "passes basic authentication details and strips out creds also in verbose mode" do
+ gemfile <<-G
+ source "#{basic_auth_source_uri}"
+ gem "rack"
+ G
+
+ bundle :install, :verbose => true, :artifice => "endpoint_basic_authentication"
+ expect(out).not_to include("#{user}:#{password}")
+ expect(the_bundle).to include_gems "rack 1.0.0"
+ end
+
it "strips http basic authentication creds for modern index" do
gemfile <<-G
source "#{basic_auth_source_uri}"
gem "rack"
G
- bundle :install, :artifice => "endopint_marshal_fail_basic_authentication"
+ bundle :install, :artifice => "endpoint_marshal_fail_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -590,7 +588,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :artifice => "endpoint_500"
+ bundle :install, :artifice => "endpoint_500", :raise_on_error => false
expect(out).not_to include("#{user}:#{password}")
end
@@ -617,6 +615,22 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "rack 1.0.0"
end
+ describe "with host including dashes" do
+ before do
+ gemfile <<-G
+ source "http://local-gemserver.test"
+ gem "rack"
+ G
+ end
+
+ it "reads authentication details from a valid ENV variable" do
+ bundle :install, :artifice => "endpoint_strict_basic_authentication", :env => { "BUNDLE_LOCAL___GEMSERVER__TEST" => "#{user}:#{password}" }
+
+ expect(out).to include("Fetching gem metadata from http://local-gemserver.test")
+ expect(the_bundle).to include_gems "rack 1.0.0"
+ end
+ end
+
describe "with authentication details in bundle config" do
before do
gemfile <<-G
@@ -664,14 +678,14 @@ RSpec.describe "gemcutter's dependency API" do
end
it "shows instructions if auth is not provided for the source" do
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
- expect(err).to include("bundle config set #{source_hostname} username:password")
+ bundle :install, :artifice => "endpoint_strict_basic_authentication", :raise_on_error => false
+ expect(err).to include("bundle config set --global #{source_hostname} username:password")
end
it "fails if authentication has already been provided, but failed" do
bundle "config set #{source_hostname} #{user}:wrong"
- bundle :install, :artifice => "endpoint_strict_basic_authentication"
+ bundle :install, :artifice => "endpoint_strict_basic_authentication", :raise_on_error => false
expect(err).to include("Bad username or password")
end
end
@@ -710,7 +724,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install, :env => { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" }
+ bundle :install, :env => { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, :raise_on_error => false
expect(err).to include("OpenSSL")
end
end
@@ -730,31 +744,27 @@ RSpec.describe "gemcutter's dependency API" do
gem "rack"
G
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err).to match(/could not verify the SSL certificate/i)
end
end
context ".gemrc with sources is present" do
- before do
+ it "uses other sources declared in the Gemfile" do
File.open(home(".gemrc"), "w") do |file|
file.puts({ :sources => ["https://rubygems.org"] }.to_yaml)
end
- end
-
- after do
- home(".gemrc").rmtree
- end
-
- it "uses other sources declared in the Gemfile" do
- gemfile <<-G
- source "#{source_uri}"
- gem 'rack'
- G
- bundle "install", :artifice => "endpoint_marshal_fail"
+ begin
+ gemfile <<-G
+ source "#{source_uri}"
+ gem 'rack'
+ G
- expect(exitstatus).to eq(0) if exitstatus
+ bundle "install", :artifice => "endpoint_marshal_fail"
+ ensure
+ home(".gemrc").rmtree
+ end
end
end
end
diff --git a/spec/bundler/install/gems/flex_spec.rb b/spec/bundler/install/gems/flex_spec.rb
index 865bc7b72a..f9b374cf01 100644
--- a/spec/bundler/install/gems/flex_spec.rb
+++ b/spec/bundler/install/gems/flex_spec.rb
@@ -166,8 +166,7 @@ RSpec.describe "bundle flex_install" do
expect(the_bundle).to include_gems "rack_middleware 1.0", "rack 0.9.1"
- build_repo2
- update_repo2 do
+ build_repo2 do
build_gem "rack-obama", "2.0" do |s|
s.add_dependency "rack", "=1.2"
end
@@ -184,8 +183,8 @@ RSpec.describe "bundle flex_install" do
end
it "does not install gems whose dependencies are not met" do
- bundle :install
- ruby <<-RUBY
+ bundle :install, :raise_on_error => false
+ ruby <<-RUBY, :raise_on_error => false
require 'bundler/setup'
RUBY
expect(err).to match(/could not find gem 'rack-obama/i)
@@ -210,7 +209,7 @@ RSpec.describe "bundle flex_install" do
the gems in your Gemfile, which may resolve the conflict.
E
- bundle :install, :retry => 0
+ bundle :install, :retry => 0, :raise_on_error => false
expect(err).to end_with(nice_error)
end
end
@@ -230,14 +229,27 @@ RSpec.describe "bundle flex_install" do
G
end
- it "does something" do
- expect do
- bundle "install"
- end.not_to change { File.read(bundled_app("Gemfile.lock")) }
+ it "should work when you install" do
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ rack (0.9.1)
+ rack-obama (1.0)
+ rack
- expect(err).to include("rack = 0.9.1")
- expect(err).to include("locked at 1.0.0")
- expect(err).to include("bundle update rack")
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack (= 0.9.1)
+ rack-obama
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
it "should work when you update" do
@@ -246,68 +258,38 @@ RSpec.describe "bundle flex_install" do
end
describe "when adding a new source" do
- it "updates the lockfile", :bundler => "< 3" do
- build_repo2
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- G
-
- lockfile_should_be <<-L
- GEM
- remote: #{file_uri_for(gem_repo1)}/
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
-
- it "updates the lockfile", :bundler => "3" do
+ it "updates the lockfile" do
build_repo2
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
source "#{file_uri_for(gem_repo2)}" do
end
gem "rack"
G
- lockfile_should_be <<-L
- GEM
- remote: #{file_uri_for(gem_repo1)}/
- specs:
- rack (1.0.0)
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ rack (1.0.0)
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
- PLATFORMS
- #{lockfile_platforms}
+ PLATFORMS
+ #{lockfile_platforms}
- DEPENDENCIES
- rack
+ DEPENDENCIES
+ rack
- BUNDLED WITH
- #{Bundler::VERSION}
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
end
@@ -341,7 +323,7 @@ RSpec.describe "bundle flex_install" do
G
# upgrade Rails to 3.0.0 and then install again
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
gem "rails", "3.0.0"
gem "capybara", "0.3.9"
diff --git a/spec/bundler/install/gems/fund_spec.rb b/spec/bundler/install/gems/fund_spec.rb
new file mode 100644
index 0000000000..f521b0296f
--- /dev/null
+++ b/spec/bundler/install/gems/fund_spec.rb
@@ -0,0 +1,137 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install" do
+ context "with gem sources" do
+ before do
+ build_repo2 do
+ build_gem "has_funding_and_other_metadata" do |s|
+ s.metadata = {
+ "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
+ "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
+ "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
+ "homepage_uri" => "https://bestgemever.example.io",
+ "mailing_list_uri" => "https://groups.example.com/bestgemever",
+ "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding",
+ "source_code_uri" => "https://example.com/user/bestgemever",
+ "wiki_uri" => "https://example.com/user/bestgemever/wiki",
+ }
+ end
+
+ build_gem "has_funding", "1.2.3" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/has_funding/funding",
+ }
+ end
+
+ build_gem "gem_with_dependent_funding", "1.0" do |s|
+ s.add_dependency "has_funding"
+ end
+ end
+ end
+
+ context "when gems include a fund URI" do
+ it "displays the plural fund message after installing" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding'
+ gem 'rack-obama'
+ G
+
+ expect(out).to include("2 installed gems you directly depend on are looking for funding.")
+ end
+
+ it "displays the singular fund message after installing" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'has_funding'
+ gem 'rack-obama'
+ G
+
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+ end
+ end
+
+ context "when gems do not include fund messages" do
+ it "does not display any fund messages" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ G
+
+ expect(out).not_to include("gem you depend on")
+ end
+ end
+
+ context "when a dependency includes a fund message" do
+ it "does not display the fund message" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'gem_with_dependent_funding'
+ G
+
+ expect(out).not_to include("gem you depend on")
+ end
+ end
+ end
+
+ context "with git sources" do
+ context "when gems include fund URI" do
+ it "displays the fund message after installing" do
+ build_git "also_has_funding" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/also_has_funding/funding",
+ }
+ end
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}'
+ G
+
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+ end
+
+ it "displays the fund message if repo is updated" do
+ build_git "also_has_funding" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/also_has_funding/funding",
+ }
+ end
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}'
+ G
+
+ build_git "also_has_funding", "1.1" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/also_has_funding/funding",
+ }
+ end
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.1")}'
+ G
+
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+ end
+
+ it "displays the fund message if repo is not updated" do
+ build_git "also_has_funding" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/also_has_funding/funding",
+ }
+ end
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}'
+ G
+
+ bundle :install
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+
+ bundle :install
+ expect(out).to include("1 installed gem you directly depend on is looking for funding.")
+ end
+ end
+ end
+end
diff --git a/spec/bundler/install/gems/native_extensions_spec.rb b/spec/bundler/install/gems/native_extensions_spec.rb
index 3e59a3cebd..d5cafcfc2c 100644
--- a/spec/bundler/install/gems/native_extensions_spec.rb
+++ b/spec/bundler/install/gems/native_extensions_spec.rb
@@ -40,7 +40,6 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
bundle "config set build.c_extension --with-c_extension=hello"
bundle "install"
- expect(out).not_to include("extconf.rb failed")
expect(out).to include("Installing c_extension 1.0 with native extensions")
run "Bundler.require; puts CExtension.new.its_true"
@@ -76,18 +75,73 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
C
end
- bundle! "config set build.c_extension --with-c_extension=hello"
+ bundle "config set build.c_extension --with-c_extension=hello"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump}
G
- expect(out).not_to include("extconf.rb failed")
+ expect(err).to_not include("warning: conflicting chdir during another chdir block")
- run! "Bundler.require; puts CExtension.new.its_true"
+ run "Bundler.require; puts CExtension.new.its_true"
expect(out).to eq("true")
end
+ it "installs correctly from git when multiple gems with extensions share one repository" do
+ build_repo2 do
+ ["one", "two"].each do |n|
+ build_lib "c_extension_#{n}", "1.0", :path => lib_path("gems/c_extension_#{n}") do |s|
+ s.extensions = ["ext/extconf.rb"]
+ s.write "ext/extconf.rb", <<-E
+ require "mkmf"
+ name = "c_extension_bundle_#{n}"
+ dir_config(name)
+ raise "OMG" unless with_config("c_extension_#{n}") == "#{n}"
+ create_makefile(name)
+ E
+
+ s.write "ext/c_extension_#{n}.c", <<-C
+ #include "ruby.h"
+
+ VALUE c_extension_#{n}_value(VALUE self) {
+ return rb_str_new_cstr("#{n}");
+ }
+
+ void Init_c_extension_bundle_#{n}() {
+ VALUE c_Extension = rb_define_class("CExtension_#{n}", rb_cObject);
+ rb_define_method(c_Extension, "value", c_extension_#{n}_value, 0);
+ }
+ C
+
+ s.write "lib/c_extension_#{n}.rb", <<-C
+ require "c_extension_bundle_#{n}"
+ C
+ end
+ end
+ build_git "gems", :path => lib_path("gems"), :gemspec => false
+ end
+
+ bundle "config set build.c_extension_one --with-c_extension_one=one"
+ bundle "config set build.c_extension_two --with-c_extension_two=two"
+
+ # 1st time, require only one gem -- only one of the extensions gets built.
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "c_extension_one", :git => #{lib_path("gems").to_s.dump}
+ G
+
+ # 2nd time, require both gems -- we need both extensions to be built now.
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "c_extension_one", :git => #{lib_path("gems").to_s.dump}
+ gem "c_extension_two", :git => #{lib_path("gems").to_s.dump}
+ G
+
+ run "Bundler.require; puts CExtension_one.new.value; puts CExtension_two.new.value"
+ expect(out).to eq("one\ntwo")
+ end
+
it "install with multiple build flags" do
build_git "c_extension" do |s|
s.extensions = ["ext/extconf.rb"]
@@ -117,15 +171,14 @@ RSpec.describe "installing a gem with native extensions", :ruby_repo do
C
end
- bundle! "config set build.c_extension --with-c_extension=hello --with-c_extension_bundle-dir=hola"
+ bundle "config set build.c_extension --with-c_extension=hello --with-c_extension_bundle-dir=hola"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump}
G
- expect(out).not_to include("extconf.rb failed")
-
- run! "Bundler.require; puts CExtension.new.its_true"
+ run "Bundler.require; puts CExtension.new.its_true"
expect(out).to eq("true")
end
end
diff --git a/spec/bundler/install/gems/post_install_spec.rb b/spec/bundler/install/gems/post_install_spec.rb
index 3f6d7ce42c..7426f54877 100644
--- a/spec/bundler/install/gems/post_install_spec.rb
+++ b/spec/bundler/install/gems/post_install_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe "bundle install" do
end
end
- context "when a dependecy includes a post install message" do
+ context "when a dependency includes a post install message" do
it "should display the post install message" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb
index 52511ff67f..94fac0052c 100644
--- a/spec/bundler/install/gems/resolving_spec.rb
+++ b/spec/bundler/install/gems/resolving_spec.rb
@@ -1,9 +1,72 @@
# frozen_string_literal: true
RSpec.describe "bundle install with install-time dependencies" do
+ before do
+ build_repo2 do
+ build_gem "with_implicit_rake_dep" do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/implicit_rake_dep.rb", "w") do |f|
+ f.puts "IMPLICIT_RAKE_DEP = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ build_gem "another_implicit_rake_dep" do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
+ f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ # Test complicated gem dependencies for install
+ build_gem "net_a" do |s|
+ s.add_dependency "net_b"
+ s.add_dependency "net_build_extensions"
+ end
+
+ build_gem "net_b"
+
+ build_gem "net_build_extensions" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/net_build_extensions.rb", "w") do |f|
+ f.puts "NET_BUILD_EXTENSIONS = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ build_gem "net_c" do |s|
+ s.add_dependency "net_a"
+ s.add_dependency "net_d"
+ end
+
+ build_gem "net_d"
+
+ build_gem "net_e" do |s|
+ s.add_dependency "net_d"
+ end
+ end
+ end
+
it "installs gems with implicit rake dependencies" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "with_implicit_rake_dep"
gem "another_implicit_rake_dep"
gem "rake"
@@ -18,7 +81,28 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(out).to eq("YES\nYES")
end
+ it "installs gems with implicit rake dependencies without rake previously installed" do
+ with_path_as("") do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "with_implicit_rake_dep"
+ gem "another_implicit_rake_dep"
+ gem "rake"
+ G
+ end
+
+ run <<-R
+ require 'implicit_rake_dep'
+ require 'another_implicit_rake_dep'
+ puts IMPLICIT_RAKE_DEP
+ puts ANOTHER_IMPLICIT_RAKE_DEP
+ R
+ expect(out).to eq("YES\nYES")
+ end
+
it "installs gems with a dependency with no type" do
+ skip "incorrect data check error" if Gem.win_platform?
+
build_repo2
path = "#{gem_repo2}/#{Gem::MARSHAL_SPEC_DIR}/actionpack-2.3.2.gemspec.rz"
@@ -41,7 +125,7 @@ RSpec.describe "bundle install with install-time dependencies" do
describe "with crazy rubygem plugin stuff" do
it "installs plugins" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "net_b"
G
@@ -49,8 +133,8 @@ RSpec.describe "bundle install with install-time dependencies" do
end
it "installs plugins depended on by other plugins" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, :env => { "DEBUG" => "1" }
+ source "#{file_uri_for(gem_repo2)}"
gem "net_a"
G
@@ -58,8 +142,8 @@ RSpec.describe "bundle install with install-time dependencies" do
end
it "installs multiple levels of dependencies" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, :env => { "DEBUG" => "1" }
+ source "#{file_uri_for(gem_repo2)}"
gem "net_c"
gem "net_e"
G
@@ -67,34 +151,54 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(the_bundle).to include_gems "net_a 1.0", "net_b 1.0", "net_c 1.0", "net_d 1.0", "net_e 1.0"
end
+ context "with ENV['BUNDLER_DEBUG_RESOLVER'] set" do
+ it "produces debug output" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "net_c"
+ gem "net_e"
+ G
+
+ bundle :install, :env => { "BUNDLER_DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
+
+ expect(out).to include("BUNDLER: Starting resolution")
+ end
+ end
+
context "with ENV['DEBUG_RESOLVER'] set" do
it "produces debug output" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "net_c"
gem "net_e"
G
- bundle :install, :env => { "DEBUG_RESOLVER" => "1" }
+ bundle :install, :env => { "DEBUG_RESOLVER" => "1", "DEBUG" => "1" }
- expect(err).to include("Creating possibility state for net_c")
+ expect(out).to include("BUNDLER: Starting resolution")
end
end
context "with ENV['DEBUG_RESOLVER_TREE'] set" do
it "produces debug output" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "net_c"
gem "net_e"
G
- bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1" }
+ bundle :install, :env => { "DEBUG_RESOLVER_TREE" => "1", "DEBUG" => "1" }
- expect(err).to include(" net_b").
- and include("Starting resolution").
- and include("Finished resolution").
- and include("Attempting to activate")
+ activated_groups = if local_platforms.any?
+ "net_b (1.0) (ruby), net_b (1.0) (#{local_platforms.join(", ")})"
+ else
+ "net_b (1.0) (ruby)"
+ end
+
+ expect(out).to include(" net_b").
+ and include("BUNDLER: Starting resolution").
+ and include("BUNDLER: Finished resolution").
+ and include("Attempting to activate [#{activated_groups}]")
end
end
end
@@ -103,6 +207,10 @@ 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"
+ end
+
build_gem "rack", "9001.0.0" do |s|
s.required_ruby_version = "> 9000"
end
@@ -137,6 +245,31 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000")
expect(the_bundle).to include_gems("rack 1.2")
end
+
+ it "installs the older not platform specific version" do
+ build_repo4 do
+ build_gem "rack", "9001.0.0" do |s|
+ s.required_ruby_version = "> 9000"
+ end
+ build_gem "rack", "1.2" do |s|
+ s.platform = mingw
+ s.required_ruby_version = "> 9000"
+ end
+ build_gem "rack", "1.2"
+ end
+
+ simulate_platform mingw do
+ install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ ruby "#{RUBY_VERSION}"
+ source "http://localgemserver.test/"
+ gem 'rack'
+ G
+ end
+
+ expect(out).to_not include("rack-9001.0.0 requires ruby version > 9000")
+ expect(out).to_not include("rack-1.2-#{Bundler.local_platform} requires ruby version > 9000")
+ expect(the_bundle).to include_gems("rack 1.2")
+ end
end
context "allows no gems" do
@@ -153,7 +286,9 @@ 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 }
+ skip "ruby requirement includes platform and it shouldn't" if Gem.win_platform?
+
+ install_gemfile <<-G, :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, :raise_on_error => false
source "http://localgemserver.test/"
ruby #{ruby_requirement}
gem 'require_ruby'
@@ -202,7 +337,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo2)}"
gem 'require_rubygems'
G
diff --git a/spec/bundler/install/gems/standalone_spec.rb b/spec/bundler/install/gems/standalone_spec.rb
index f1d5c8b505..db16a1b0e1 100644
--- a/spec/bundler/install/gems/standalone_spec.rb
+++ b/spec/bundler/install/gems/standalone_spec.rb
@@ -7,6 +7,12 @@ RSpec.shared_examples "bundle install --standalone" do
expect(the_bundle).to include_gems(*args)
end
+ it "still makes system gems unavailable to normal bundler" do
+ system_gems "rack-1.0.0"
+
+ expect(the_bundle).to_not include_gems("rack")
+ end
+
it "generates a bundle/bundler/setup.rb" do
expect(bundled_app("bundle/bundler/setup.rb")).to exist
end
@@ -21,15 +27,51 @@ RSpec.shared_examples "bundle install --standalone" do
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
- Dir.chdir(bundled_app) do
- ruby testrb, :no_lib => true
+ ruby testrb
+
+ expect(out).to eq(expected_gems.values.join("\n"))
+ end
+
+ it "makes the gems available without bundler via Kernel.require" do
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ RUBY
+ expected_gems.each do |k, _|
+ testrb << "\nKernel.require \"#{k}\""
+ testrb << "\nputs #{k.upcase}"
end
+ ruby testrb
expect(out).to eq(expected_gems.values.join("\n"))
end
+ it "makes system gems unavailable without bundler" do
+ system_gems "rack-1.0.0"
+
+ testrb = String.new <<-RUBY
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
+
+ begin
+ require "rack"
+ rescue LoadError
+ puts "LoadError"
+ end
+ RUBY
+ ruby testrb
+
+ expect(out).to eq("LoadError")
+ end
+
it "works on a different system" do
- FileUtils.mv(bundled_app, "#{bundled_app}2")
+ begin
+ FileUtils.mv(bundled_app, "#{bundled_app}2")
+ rescue Errno::ENOTEMPTY
+ puts "Couldn't rename test app since the target folder has these files: #{Dir.glob("#{bundled_app}2/*")}"
+ raise
+ end
testrb = String.new <<-RUBY
$:.unshift File.expand_path("bundle")
@@ -40,9 +82,7 @@ RSpec.shared_examples "bundle install --standalone" do
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
- Dir.chdir("#{bundled_app}2") do
- ruby testrb, :no_lib => true
- end
+ ruby testrb, :dir => "#{bundled_app}2"
expect(out).to eq(expected_gems.values.join("\n"))
end
@@ -54,7 +94,8 @@ RSpec.shared_examples "bundle install --standalone" do
source "#{file_uri_for(gem_repo1)}"
gem "rails"
G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle :install, :standalone => true, :dir => cwd
end
let(:expected_gems) do
@@ -67,9 +108,79 @@ RSpec.shared_examples "bundle install --standalone" do
include_examples "common functionality"
end
+ describe "with default gems and a lockfile", :ruby_repo do
+ before do
+ skip "does not work on rubygems versions where `--install_dir` doesn't respect --default" unless Gem::Installer.for_spec(loaded_gemspec, :install_dir => "/foo").default_spec_file == "/foo/specifications/default/bundler-#{Bundler::VERSION}.gemspec" # Since rubygems 3.2.0.rc.2
+ skip "does not work on old rubies because the realworld gems that need to be installed don't support them" if RUBY_VERSION < "2.7.0"
+
+ realworld_system_gems "fiddle --version 1.0.6", "tsort --version 0.1.0"
+
+ necessary_system_gems = ["optparse --version 0.1.1", "psych --version 3.3.2", "yaml --version 0.1.1", "logger --version 1.4.3", "etc --version 1.2.0", "stringio --version 3.0.0"]
+ necessary_system_gems += ["shellwords --version 0.1.0", "base64 --version 0.1.0", "resolv --version 0.2.1"] if Gem.rubygems_version < Gem::Version.new("3.3.3.a")
+ realworld_system_gems(*necessary_system_gems, :path => scoped_gem_path(bundled_app("bundle")))
+
+ build_gem "foo", "1.0.0", :to_system => true, :default => true do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "bar", "1.0.0", :to_system => true, :default => true
+
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "bar", "1.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "foo"
+ G
+
+ bundle "lock", :dir => cwd, :artifice => "compact_index"
+ end
+
+ it "works" do
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle :install, :standalone => true, :dir => cwd, :artifice => "compact_index", :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+ end
+ end
+
+ describe "with Gemfiles using path sources and resulting bundle moved to a folder hierarchy with different nesting" do
+ before do
+ build_lib "minitest", "1.0.0", :path => lib_path("minitest")
+
+ Dir.mkdir bundled_app("app")
+
+ gemfile bundled_app("app/Gemfile"), <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "minitest", :path => "#{lib_path("minitest")}"
+ G
+
+ bundle "install", :standalone => true, :dir => bundled_app("app")
+
+ Dir.mkdir tmp("one_more_level")
+ FileUtils.mv bundled_app, tmp("one_more_level")
+ end
+
+ it "also works" do
+ ruby <<-RUBY, :dir => tmp("one_more_level/bundled_app/app")
+ require "./bundle/bundler/setup"
+
+ require "minitest"
+ puts MINITEST
+ RUBY
+
+ expect(out).to eq("1.0.0")
+ expect(err).to be_empty
+ end
+ end
+
describe "with gems with native extension", :ruby_repo do
before do
- install_gemfile <<-G, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ bundle "config set --local path #{bundled_app("bundle")}"
+ install_gemfile <<-G, :standalone => true, :dir => cwd
source "#{file_uri_for(gem_repo1)}"
gem "very_simple_binary"
G
@@ -78,8 +189,8 @@ RSpec.shared_examples "bundle install --standalone" do
it "generates a bundle/bundler/setup.rb with the proper paths" do
expected_path = bundled_app("bundle/bundler/setup.rb")
extension_line = File.read(expected_path).each_line.find {|line| line.include? "/extensions/" }.strip
- expect(extension_line).to start_with '$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/extensions/'
- expect(extension_line).to end_with '/very_simple_binary-1.0"'
+ expect(extension_line).to start_with '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{RbConfig::CONFIG["ruby_version"]}/extensions/'
+ expect(extension_line).to end_with '/very_simple_binary-1.0")'
end
end
@@ -102,7 +213,9 @@ RSpec.shared_examples "bundle install --standalone" do
end
G
end
- install_gemfile <<-G, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ bundle "config set --local path #{bundled_app("bundle")}"
+ install_gemfile <<-G, :standalone => true, :dir => cwd, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
end
@@ -122,7 +235,8 @@ RSpec.shared_examples "bundle install --standalone" do
gem "rails"
gem "devise", :git => "#{lib_path("devise-1.0")}"
G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle :install, :standalone => true, :dir => cwd
end
let(:expected_gems) do
@@ -149,7 +263,8 @@ RSpec.shared_examples "bundle install --standalone" do
gem "rack-test"
end
G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle :install, :standalone => true, :dir => cwd
end
let(:expected_gems) do
@@ -162,88 +277,69 @@ RSpec.shared_examples "bundle install --standalone" do
include_examples "common functionality"
it "allows creating a standalone file with limited groups" do
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => "default")
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle :install, :standalone => "default", :dir => cwd
- Dir.chdir(bundled_app) do
- load_error_ruby <<-RUBY, "spec", :no_lib => true
- $:.unshift File.expand_path("bundle")
- require "bundler/setup"
+ load_error_ruby <<-RUBY, "spec"
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
- require "actionpack"
- puts ACTIONPACK
- require "spec"
- RUBY
- end
+ require "actionpack"
+ puts ACTIONPACK
+ require "spec"
+ RUBY
expect(out).to eq("2.3.2")
expect(err).to eq("ZOMG LOAD ERROR")
end
- it "allows --without to limit the groups used in a standalone" do
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle"), :without => "test").merge(:standalone => true)
+ it "allows `without` configuration to limit the groups used in a standalone" do
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle "config set --local without test"
+ bundle :install, :standalone => true, :dir => cwd
- Dir.chdir(bundled_app) do
- load_error_ruby <<-RUBY, "spec", :no_lib => true
- $:.unshift File.expand_path("bundle")
- require "bundler/setup"
+ load_error_ruby <<-RUBY, "spec"
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
- require "actionpack"
- puts ACTIONPACK
- require "spec"
- RUBY
- end
+ require "actionpack"
+ puts ACTIONPACK
+ require "spec"
+ RUBY
expect(out).to eq("2.3.2")
expect(err).to eq("ZOMG LOAD ERROR")
end
- it "allows --path to change the location of the standalone bundle", :bundler => "< 3" do
- bundle! "install", forgotten_command_line_options(:path => "path/to/bundle").merge(:standalone => true)
-
- Dir.chdir(bundled_app) do
- ruby <<-RUBY, :no_lib => true
- $:.unshift File.expand_path("path/to/bundle")
- require "bundler/setup"
-
- require "actionpack"
- puts ACTIONPACK
- RUBY
- end
+ it "allows `path` configuration to change the location of the standalone bundle" do
+ bundle "config set --local path path/to/bundle"
+ bundle "install", :standalone => true, :dir => cwd
- expect(out).to eq("2.3.2")
- end
-
- it "allows --path to change the location of the standalone bundle", :bundler => "3" do
- bundle! "install", forgotten_command_line_options(:path => "path/to/bundle").merge(:standalone => true)
- path = File.expand_path("path/to/bundle")
-
- Dir.chdir(bundled_app) do
- ruby <<-RUBY, :no_lib => true
- $:.unshift File.expand_path(#{path.dump})
- require "bundler/setup"
+ ruby <<-RUBY
+ $:.unshift File.expand_path("path/to/bundle")
+ require "bundler/setup"
- require "actionpack"
- puts ACTIONPACK
- RUBY
- end
+ require "actionpack"
+ puts ACTIONPACK
+ RUBY
expect(out).to eq("2.3.2")
end
- it "allows remembered --without to limit the groups used in a standalone" do
- bundle! :install, forgotten_command_line_options(:without => "test")
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true)
+ it "allows `without` to limit the groups used in a standalone" do
+ bundle "config set --local without test"
+ bundle :install, :dir => cwd
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle :install, :standalone => true, :dir => cwd
- Dir.chdir(bundled_app) do
- load_error_ruby <<-RUBY, "spec", :no_lib => true
- $:.unshift File.expand_path("bundle")
- require "bundler/setup"
+ load_error_ruby <<-RUBY, "spec"
+ $:.unshift File.expand_path("bundle")
+ require "bundler/setup"
- require "actionpack"
- puts ACTIONPACK
- require "spec"
- RUBY
- end
+ require "actionpack"
+ puts ACTIONPACK
+ require "spec"
+ RUBY
expect(out).to eq("2.3.2")
expect(err).to eq("ZOMG LOAD ERROR")
@@ -259,7 +355,8 @@ RSpec.shared_examples "bundle install --standalone" do
source "#{source_uri}"
gem "rails"
G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true, :artifice => "endpoint")
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle :install, :standalone => true, :artifice => "endpoint", :dir => cwd
end
let(:expected_gems) do
@@ -279,7 +376,8 @@ RSpec.shared_examples "bundle install --standalone" do
source "#{file_uri_for(gem_repo1)}"
gem "rails"
G
- bundle! :install, forgotten_command_line_options(:path => bundled_app("bundle")).merge(:standalone => true, :binstubs => true)
+ bundle "config set --local path #{bundled_app("bundle")}"
+ bundle :install, :standalone => true, :binstubs => true, :dir => cwd
end
let(:expected_gems) do
@@ -292,28 +390,24 @@ RSpec.shared_examples "bundle install --standalone" do
include_examples "common functionality"
it "creates stubs that use the standalone load path" do
- Dir.chdir(bundled_app) do
- expect(`bin/rails -v`.chomp).to eql "2.3.2"
- end
+ expect(sys_exec("bin/rails -v").chomp).to eql "2.3.2"
end
it "creates stubs that can be executed from anywhere" do
require "tmpdir"
- Dir.chdir(Dir.tmpdir) do
- sys_exec!(%(#{bundled_app("bin/rails")} -v))
- expect(out).to eq("2.3.2")
- end
+ sys_exec(%(#{bundled_app("bin/rails")} -v), :dir => Dir.tmpdir)
+ expect(out).to eq("2.3.2")
end
it "creates stubs that can be symlinked" do
- pending "File.symlink is unsupported on Windows" if Bundler::WINDOWS
+ skip "symlinks unsupported" if Gem.win_platform?
symlink_dir = tmp("symlink")
FileUtils.mkdir_p(symlink_dir)
symlink = File.join(symlink_dir, "rails")
File.symlink(bundled_app("bin/rails"), symlink)
- sys_exec!("#{symlink} -v")
+ sys_exec("#{symlink} -v")
expect(out).to eq("2.3.2")
end
@@ -325,13 +419,13 @@ RSpec.shared_examples "bundle install --standalone" do
end
RSpec.describe "bundle install --standalone" do
+ let(:cwd) { bundled_app }
+
include_examples("bundle install --standalone")
end
RSpec.describe "bundle install --standalone run in a subdirectory" do
- before do
- Dir.chdir(bundled_app("bob").tap(&:mkpath))
- end
+ let(:cwd) { bundled_app("bob").tap(&:mkpath) }
include_examples("bundle install --standalone")
end
diff --git a/spec/bundler/install/gems/sudo_spec.rb b/spec/bundler/install/gems/sudo_spec.rb
index 170ffaca03..3e5d38ea4c 100644
--- a/spec/bundler/install/gems/sudo_spec.rb
+++ b/spec/bundler/install/gems/sudo_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe "when using sudo", :sudo => true do
end
before do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
subdir.mkpath
sudo "chmod u-w #{subdir}"
end
@@ -32,7 +32,7 @@ RSpec.describe "when using sudo", :sudo => true do
describe "and GEM_HOME is owned by root" do
before :each do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
chown_system_gems_to_root
end
@@ -49,8 +49,23 @@ RSpec.describe "when using sudo", :sudo => true do
end
it "installs rake and a gem dependent on rake in the same session" do
+ build_repo2 do
+ build_gem "another_implicit_rake_dep" do |s|
+ s.extensions << "Rakefile"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
+ f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
+ end
+ end
+ RUBY
+ end
+ end
+
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rake"
gem "another_implicit_rake_dep"
G
@@ -105,11 +120,12 @@ RSpec.describe "when using sudo", :sudo => true do
describe "and BUNDLE_PATH is not writable" do
before do
- sudo "chmod ugo-w #{default_bundle_path}"
+ bundle "config set --local path .bundle"
+ sudo "chmod ugo-w .bundle"
end
after do
- sudo "chmod ugo+w #{default_bundle_path}"
+ sudo "chmod ugo+w .bundle"
end
it "installs" do
@@ -118,7 +134,7 @@ RSpec.describe "when using sudo", :sudo => true do
gem "rack", '1.0'
G
- expect(default_bundle_path("gems/rack-1.0.0")).to exist
+ expect(local_gem_path("gems/rack-1.0.0")).to exist
expect(the_bundle).to include_gems "rack 1.0"
end
@@ -140,11 +156,13 @@ RSpec.describe "when using sudo", :sudo => true do
describe "and GEM_HOME is not writable" do
it "installs" do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
gem_home = tmp("sudo_gem_home")
sudo "mkdir -p #{gem_home}"
sudo "chmod ugo-w #{gem_home}"
+ system_gems :bundler, :path => gem_home
+
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", '1.0'
@@ -166,7 +184,7 @@ RSpec.describe "when using sudo", :sudo => true do
end
it "warns against that" do
- bundle :install, :sudo => true
+ bundle :install, :sudo => :preserve_env
expect(err).to include(warning)
end
@@ -179,7 +197,7 @@ RSpec.describe "when using sudo", :sudo => true do
context "when silence_root_warning = false" do
it "warns against that" do
- bundle :install, :sudo => true, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "false" }
+ bundle :install, :sudo => :preserve_env, :env => { "BUNDLE_SILENCE_ROOT_WARNING" => "false" }
expect(err).to include(warning)
end
end
diff --git a/spec/bundler/install/gems/win32_spec.rb b/spec/bundler/install/gems/win32_spec.rb
index 01edcca803..419b14ff0f 100644
--- a/spec/bundler/install/gems/win32_spec.rb
+++ b/spec/bundler/install/gems/win32_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe "bundle install with win32-generated lockfile" do
it "should read lockfile" do
- File.open(bundled_app("Gemfile.lock"), "wb") do |f|
+ File.open(bundled_app_lock, "wb") do |f|
f << "GEM\r\n"
f << " remote: #{file_uri_for(gem_repo1)}/\r\n"
f << " specs:\r\n"
@@ -21,6 +21,5 @@ RSpec.describe "bundle install with win32-generated lockfile" do
gem "rack"
G
- expect(exitstatus).to eq(0) if exitstatus
end
end
diff --git a/spec/bundler/install/gemspecs_spec.rb b/spec/bundler/install/gemspecs_spec.rb
index 4c00caa60c..3684d8749d 100644
--- a/spec/bundler/install/gemspecs_spec.rb
+++ b/spec/bundler/install/gemspecs_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe "bundle install" do
build_lib "yaml_spec", :gemspec => :yaml
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'yaml_spec', :path => "#{lib_path("yaml_spec-1.0")}"
G
expect(err).to be_empty
@@ -33,6 +34,8 @@ RSpec.describe "bundle install" do
gem 'rack'
G
+ system_gems "rack-1.0.0", :path => default_bundle_path
+
FileUtils.mkdir_p "#{default_bundle_path}/specifications"
File.open("#{default_bundle_path}/specifications/rack-1.0.0.gemspec", "w+") do |f|
spec = Gem::Specification.new do |s|
@@ -43,7 +46,7 @@ RSpec.describe "bundle install" do
f.write spec.to_ruby
end
bundle :install, :artifice => "endpoint_marshal_fail" # force gemspec load
- expect(the_bundle).to include_gems "activesupport 2.3.2"
+ expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.2"
end
it "does not hang when gemspec has incompatible encoding" do
@@ -57,6 +60,7 @@ RSpec.describe "bundle install" do
G
install_gemfile <<-G, :env => { "LANG" => "C" }
+ source "#{file_uri_for(gem_repo1)}"
gemspec
G
@@ -82,6 +86,7 @@ RSpec.describe "bundle install" do
G
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gemspec
G
@@ -96,6 +101,7 @@ RSpec.describe "bundle install" do
install_gemfile <<-G
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby'
+ source "#{file_uri_for(gem_repo1)}"
gemspec
G
expect(the_bundle).to include_gems "foo 1.0"
@@ -107,8 +113,9 @@ RSpec.describe "bundle install" do
s.required_ruby_version = "#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}"
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby', :patchlevel => '#{RUBY_PATCHLEVEL}'
+ source "#{file_uri_for(gem_repo1)}"
gemspec
G
expect(the_bundle).to include_gems "foo 1.0"
@@ -121,14 +128,15 @@ RSpec.describe "bundle install" do
s.required_ruby_version = "#{RUBY_VERSION}.#{patchlevel}"
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby', :patchlevel => '#{patchlevel}'
+ source "#{file_uri_for(gem_repo1)}"
gemspec
G
expect(err).to include("Ruby patchlevel")
expect(err).to include("but your Gemfile specified")
- expect(exitstatus).to eq(18) if exitstatus
+ expect(exitstatus).to eq(18)
end
it "fails and complains about version on version mismatch" do
@@ -138,14 +146,15 @@ RSpec.describe "bundle install" do
s.required_ruby_version = version
end
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
ruby '#{version}', :engine_version => '#{version}', :engine => 'ruby'
+ source "#{file_uri_for(gem_repo1)}"
gemspec
G
expect(err).to include("Ruby version")
expect(err).to include("but your Gemfile specified")
- expect(exitstatus).to eq(18) if exitstatus
+ expect(exitstatus).to eq(18)
end
end
end
diff --git a/spec/bundler/install/git_spec.rb b/spec/bundler/install/git_spec.rb
index cc8bf70b03..d43aacee7e 100644
--- a/spec/bundler/install/git_spec.rb
+++ b/spec/bundler/install/git_spec.rb
@@ -2,37 +2,51 @@
RSpec.describe "bundle install" do
context "git sources" do
- it "displays the revision hash of the gem repository", :bundler => "< 3" do
+ it "displays the revision hash of the gem repository" do
build_git "foo", "1.0", :path => lib_path("foo")
- install_gemfile <<-G
- gem "foo", :git => "#{lib_path("foo")}"
+ install_gemfile <<-G, :verbose => true
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo"))}"
+ G
+
+ expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at master@#{revision_for(lib_path("foo"))[0..6]})")
+ expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
+ end
+
+ it "displays the correct default branch", :git => ">= 2.28.0" do
+ build_git "foo", "1.0", :path => lib_path("foo"), :default_branch => "main"
+
+ install_gemfile <<-G, :verbose => true
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo"))}"
G
- bundle! :install
- expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at master@#{revision_for(lib_path("foo"))[0..6]})")
+ expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main@#{revision_for(lib_path("foo"))[0..6]})")
expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
end
- it "displays the ref of the gem repository when using branch~num as a ref", :bundler => "< 3" do
+ it "displays the ref of the gem repository when using branch~num as a ref" do
+ skip "maybe branch~num notation doesn't work on Windows' git" if Gem.win_platform?
+
build_git "foo", "1.0", :path => lib_path("foo")
rev = revision_for(lib_path("foo"))[0..6]
update_git "foo", "2.0", :path => lib_path("foo"), :gemspec => true
rev2 = revision_for(lib_path("foo"))[0..6]
update_git "foo", "3.0", :path => lib_path("foo"), :gemspec => true
- install_gemfile! <<-G
- gem "foo", :git => "#{lib_path("foo")}", :ref => "master~2"
+ install_gemfile <<-G, :verbose => true
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo"))}", :ref => "master~2"
G
- bundle! :install
- expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at master~2@#{rev})")
+ expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at master~2@#{rev})")
expect(the_bundle).to include_gems "foo 1.0", :source => "git@#{lib_path("foo")}"
update_git "foo", "4.0", :path => lib_path("foo"), :gemspec => true
- bundle! :update, :all => true
- expect(out).to include("Using foo 2.0 (was 1.0) from #{lib_path("foo")} (at master~2@#{rev2})")
+ bundle :update, :all => true, :verbose => true
+ expect(out).to include("Using foo 2.0 (was 1.0) from #{file_uri_for(lib_path("foo"))} (at master~2@#{rev2})")
expect(the_bundle).to include_gems "foo 2.0", :source => "git@#{lib_path("foo")}"
end
@@ -40,6 +54,7 @@ RSpec.describe "bundle install" 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
G
@@ -57,7 +72,9 @@ RSpec.describe "bundle install" do
foo!
L
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle", :without => "development")
+ bundle "config set --local path vendor/bundle"
+ bundle "config set --local without development"
+ bundle :install
expect(out).to include("Bundle complete!")
end
@@ -71,8 +88,8 @@ RSpec.describe "bundle install" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
- gem "foo", :git => "#{lib_path("gems")}", :glob => "foo/*.gemspec"
- gem "zebra", :git => "#{lib_path("gems")}", :glob => "zebra/*.gemspec"
+ gem "foo", :git => "#{file_uri_for(lib_path("gems"))}", :glob => "foo/*.gemspec"
+ gem "zebra", :git => "#{file_uri_for(lib_path("gems"))}", :glob => "zebra/*.gemspec"
G
bundle "info foo"
diff --git a/spec/bundler/install/global_cache_spec.rb b/spec/bundler/install/global_cache_spec.rb
index 023e52b060..afa0ff76c1 100644
--- a/spec/bundler/install/global_cache_spec.rb
+++ b/spec/bundler/install/global_cache_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.describe "global gem caching" do
- before { bundle! "config set global_gem_cache true" }
+ before { bundle "config set global_gem_cache true" }
describe "using the cross-application user cache" do
let(:source) { "http://localgemserver.test" }
@@ -16,7 +16,7 @@ RSpec.describe "global gem caching" do
end
it "caches gems into the global cache on download" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, :artifice => "compact_index"
source "#{source}"
gem "rack"
G
@@ -29,7 +29,7 @@ RSpec.describe "global gem caching" do
source_global_cache.mkpath
FileUtils.cp(gem_repo1("gems/rack-1.0.0.gem"), source_global_cache("rack-1.0.0.gem"))
- install_gemfile! <<-G, :artifice => "compact_index_no_gem"
+ install_gemfile <<-G, :artifice => "compact_index_no_gem"
source "#{source}"
gem "rack"
G
@@ -37,24 +37,36 @@ RSpec.describe "global gem caching" do
expect(the_bundle).to include_gems "rack 1.0.0"
end
+ it "shows a proper error message if a cached gem is corrupted" do
+ source_global_cache.mkpath
+ FileUtils.touch(source_global_cache("rack-1.0.0.gem"))
+
+ install_gemfile <<-G, :artifice => "compact_index_no_gem", :raise_on_error => false
+ source "#{source}"
+ gem "rack"
+ G
+
+ expect(err).to include("Gem::Package::FormatError: package metadata is missing in #{source_global_cache("rack-1.0.0.gem")}")
+ end
+
describe "when the same gem from different sources is installed" do
it "should use the appropriate one from the global cache" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, :artifice => "compact_index"
source "#{source}"
gem "rack"
G
- FileUtils.rm_r(default_bundle_path)
+ simulate_new_machine
expect(the_bundle).not_to include_gems "rack 1.0.0"
expect(source_global_cache("rack-1.0.0.gem")).to exist
# rack 1.0.0 is not installed and it is in the global cache
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, :artifice => "compact_index"
source "#{source2}"
gem "rack", "0.9.1"
G
- FileUtils.rm_r(default_bundle_path)
+ simulate_new_machine
expect(the_bundle).not_to include_gems "rack 0.9.1"
expect(source2_global_cache("rack-0.9.1.gem")).to exist
# rack 0.9.1 is not installed and it is in the global cache
@@ -64,18 +76,18 @@ RSpec.describe "global gem caching" do
gem "rack", "1.0.0"
G
- bundle! :install, :artifice => "compact_index_no_gem"
+ bundle :install, :artifice => "compact_index_no_gem"
# rack 1.0.0 is installed and rack 0.9.1 is not
expect(the_bundle).to include_gems "rack 1.0.0"
expect(the_bundle).not_to include_gems "rack 0.9.1"
- FileUtils.rm_r(default_bundle_path)
+ simulate_new_machine
gemfile <<-G
source "#{source2}"
gem "rack", "0.9.1"
G
- bundle! :install, :artifice => "compact_index_no_gem"
+ bundle :install, :artifice => "compact_index_no_gem"
# rack 0.9.1 is installed and rack 1.0.0 is not
expect(the_bundle).to include_gems "rack 0.9.1"
expect(the_bundle).not_to include_gems "rack 1.0.0"
@@ -87,8 +99,8 @@ RSpec.describe "global gem caching" do
gem "rack"
G
- bundle! :install, :artifice => "compact_index"
- FileUtils.rm_r(default_bundle_path)
+ bundle :install, :artifice => "compact_index"
+ simulate_new_machine
expect(the_bundle).not_to include_gems "rack 1.0.0"
expect(source_global_cache("rack-1.0.0.gem")).to exist
# rack 1.0.0 is not installed and it is in the global cache
@@ -98,8 +110,8 @@ RSpec.describe "global gem caching" do
gem "rack", "0.9.1"
G
- bundle! :install, :artifice => "compact_index"
- FileUtils.rm_r(default_bundle_path)
+ bundle :install, :artifice => "compact_index"
+ simulate_new_machine
expect(the_bundle).not_to include_gems "rack 0.9.1"
expect(source2_global_cache("rack-0.9.1.gem")).to exist
# rack 0.9.1 is not installed and it is in the global cache
@@ -111,8 +123,10 @@ RSpec.describe "global gem caching" do
expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source2_global_cache("rack-0.9.1.gem")).to exist
- bundle :install, :artifice => "compact_index_no_gem"
+ bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false
expect(err).to include("Internal Server Error 500")
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
# rack 1.0.0 is not installed and rack 0.9.1 is not
expect(the_bundle).not_to include_gems "rack 1.0.0"
expect(the_bundle).not_to include_gems "rack 0.9.1"
@@ -124,8 +138,10 @@ RSpec.describe "global gem caching" do
expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source2_global_cache("rack-0.9.1.gem")).to exist
- bundle :install, :artifice => "compact_index_no_gem"
+ bundle :install, :artifice => "compact_index_no_gem", :raise_on_error => false
expect(err).to include("Internal Server Error 500")
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
# rack 0.9.1 is not installed and rack 1.0.0 is not
expect(the_bundle).not_to include_gems "rack 0.9.1"
expect(the_bundle).not_to include_gems "rack 1.0.0"
@@ -134,7 +150,7 @@ RSpec.describe "global gem caching" do
describe "when installing gems from a different directory" do
it "uses the global cache as a source" do
- install_gemfile! <<-G, :artifice => "compact_index"
+ install_gemfile <<-G, :artifice => "compact_index"
source "#{source}"
gem "rack"
gem "activesupport"
@@ -145,12 +161,12 @@ RSpec.describe "global gem caching" do
expect(the_bundle).to include_gems "activesupport 2.3.5"
expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
- FileUtils.rm_r(default_bundle_path)
+ simulate_new_machine
# Both gems are now only in the global cache
expect(the_bundle).not_to include_gems "rack 1.0.0"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- install_gemfile! <<-G, :artifice => "compact_index_no_gem"
+ install_gemfile <<-G, :artifice => "compact_index_no_gem"
source "#{source}"
gem "rack"
G
@@ -161,39 +177,42 @@ RSpec.describe "global gem caching" do
expect(source_global_cache("rack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
- Dir.chdir bundled_app2 do
- create_file bundled_app2("gems.rb"), <<-G
- source "#{source}"
- gem "activesupport"
- G
-
- # Neither gem is installed and both are in the global cache
- expect(the_bundle).not_to include_gems "rack 1.0.0"
- expect(the_bundle).not_to include_gems "activesupport 2.3.5"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- expect(source_global_cache("activesupport-2.3.5.gem")).to exist
-
- # Install using the global cache instead of by downloading the .gem
- # from the server
- bundle! :install, :artifice => "compact_index_no_gem"
-
- # activesupport is installed and both are in the global cache
- expect(the_bundle).not_to include_gems "rack 1.0.0"
- expect(the_bundle).to include_gems "activesupport 2.3.5"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- expect(source_global_cache("activesupport-2.3.5.gem")).to exist
+ create_file bundled_app2("gems.rb"), <<-G
+ source "#{source}"
+ gem "activesupport"
+ G
+
+ # Neither gem is installed and both are in the global cache
+ expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2
+ expect(the_bundle).not_to include_gems "activesupport 2.3.5", :dir => bundled_app2
+ expect(source_global_cache("rack-1.0.0.gem")).to exist
+ expect(source_global_cache("activesupport-2.3.5.gem")).to exist
+
+ # Install using the global cache instead of by downloading the .gem
+ # from the server
+ bundle :install, :artifice => "compact_index_no_gem", :dir => bundled_app2
+
+ # activesupport is installed and both are in the global cache
+ simulate_bundler_version_when_missing_prerelease_default_gem_activation do
+ expect(the_bundle).not_to include_gems "rack 1.0.0", :dir => bundled_app2
+ expect(the_bundle).to include_gems "activesupport 2.3.5", :dir => bundled_app2
end
+
+ expect(source_global_cache("rack-1.0.0.gem")).to exist
+ expect(source_global_cache("activesupport-2.3.5.gem")).to exist
end
end
end
- describe "extension caching", :ruby_repo do
- it "works" do
+ describe "extension caching" do
+ it "works", :ruby_repo do
+ skip "gets incorrect ref in path" if Gem.win_platform?
+
build_git "very_simple_git_binary", &:add_c_extension
build_lib "very_simple_path_binary", &:add_c_extension
revision = revision_for(lib_path("very_simple_git_binary-1.0"))[0, 12]
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "very_simple_binary"
@@ -209,7 +228,7 @@ RSpec.describe "global gem caching" do
cached_extensions = Pathname.glob(home(".bundle", "cache", "extensions", "*", "*", "*", "*", "*")).sort
expect(cached_extensions).to eq [gem_binary_cache, git_binary_cache].sort
- run! <<-R
+ run <<-R
require 'very_simple_binary_c'; puts ::VERY_SIMPLE_BINARY_IN_C
require 'very_simple_git_binary_c'; puts ::VERY_SIMPLE_GIT_BINARY_IN_C
R
@@ -220,12 +239,12 @@ RSpec.describe "global gem caching" do
gem_binary_cache.join("very_simple_binary_c.rb").open("w") {|f| f << "puts File.basename(__FILE__)" }
git_binary_cache.join("very_simple_git_binary_c.rb").open("w") {|f| f << "puts File.basename(__FILE__)" }
- bundle! "config set --local path different_path"
- bundle! :install
+ bundle "config set --local path different_path"
+ bundle :install
expect(Dir[home(".bundle", "cache", "extensions", "**", "*binary_c*")]).to all(end_with(".rb"))
- run! <<-R
+ run <<-R
require 'very_simple_binary_c'
require 'very_simple_git_binary_c'
R
diff --git a/spec/bundler/install/path_spec.rb b/spec/bundler/install/path_spec.rb
index 5240c5820c..b0392c4ed2 100644
--- a/spec/bundler/install/path_spec.rb
+++ b/spec/bundler/install/path_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.describe "bundle install" do
- describe "with --path" do
+ describe "with path configured" do
before :each do
build_gem "rack", "1.0.0", :to_system => true do |s|
s.write "lib/rack.rb", "puts 'FAIL'"
@@ -13,32 +13,41 @@ RSpec.describe "bundle install" do
G
end
- it "does not use available system gems with bundle --path vendor/bundle", :bundler => "< 3" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ it "does not use available system gems with `vendor/bundle" do
+ bundle "config set --local path vendor/bundle"
+ bundle :install
expect(the_bundle).to include_gems "rack 1.0.0"
end
+ it "uses system gems with `path.system` configured with more priority than `path`" do
+ bundle "config set --local path.system true"
+ bundle "config set --global path vendor/bundle"
+ bundle :install
+ run "require 'rack'", :raise_on_error => false
+ expect(out).to include("FAIL")
+ end
+
it "handles paths with regex characters in them" do
dir = bundled_app("bun++dle")
dir.mkpath
- Dir.chdir(dir) do
- bundle! :install, forgotten_command_line_options(:path => dir.join("vendor/bundle"))
- expect(out).to include("installed into `./vendor/bundle`")
- end
+ bundle "config set --local path #{dir.join("vendor/bundle")}"
+ bundle :install, :dir => dir
+ expect(out).to include("installed into `./vendor/bundle`")
dir.rmtree
end
- it "prints a warning to let the user know what has happened with bundle --path vendor/bundle" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ it "prints a message to let the user know where gems where installed" do
+ bundle "config set --local path vendor/bundle"
+ bundle :install
expect(out).to include("gems are installed into `./vendor/bundle`")
end
it "disallows --path vendor/bundle --system", :bundler => "< 3" do
- bundle "install --path vendor/bundle --system"
+ bundle "install --path vendor/bundle --system", :raise_on_error => false
expect(err).to include("Please choose only one option.")
- expect(exitstatus).to eq(15) if exitstatus
+ expect(exitstatus).to eq(15)
end
it "remembers to disable system gems after the first time with bundle --path vendor/bundle", :bundler => "< 3" do
@@ -51,33 +60,27 @@ RSpec.describe "bundle install" do
end
context "with path_relative_to_cwd set to true" do
- before { bundle! "config set path_relative_to_cwd true" }
+ before { bundle "config set path_relative_to_cwd true" }
it "installs the bundle relatively to current working directory", :bundler => "< 3" do
- Dir.chdir(bundled_app.parent) do
- bundle! "install --gemfile='#{bundled_app}/Gemfile' --path vendor/bundle"
- expect(out).to include("installed into `./vendor/bundle`")
- expect(bundled_app("../vendor/bundle")).to be_directory
- end
+ bundle "install --gemfile='#{bundled_app}/Gemfile' --path vendor/bundle", :dir => bundled_app.parent
+ expect(out).to include("installed into `./vendor/bundle`")
+ expect(bundled_app("../vendor/bundle")).to be_directory
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "installs the standalone bundle relative to the cwd" do
- Dir.chdir(bundled_app.parent) do
- bundle! :install, :gemfile => bundled_app("Gemfile"), :standalone => true
- expect(out).to include("installed into `./bundled_app/bundle`")
- expect(bundled_app("bundle")).to be_directory
- expect(bundled_app("bundle/ruby")).to be_directory
- end
+ bundle :install, :gemfile => bundled_app_gemfile, :standalone => true, :dir => bundled_app.parent
+ expect(out).to include("installed into `./bundled_app/bundle`")
+ expect(bundled_app("bundle")).to be_directory
+ expect(bundled_app("bundle/ruby")).to be_directory
- bundle! "config unset path"
+ bundle "config unset path"
- Dir.chdir(bundled_app("subdir").tap(&:mkpath)) do
- bundle! :install, :gemfile => bundled_app("Gemfile"), :standalone => true
- expect(out).to include("installed into `../bundle`")
- expect(bundled_app("bundle")).to be_directory
- expect(bundled_app("bundle/ruby")).to be_directory
- end
+ bundle :install, :gemfile => bundled_app_gemfile, :standalone => true, :dir => bundled_app("subdir").tap(&:mkpath)
+ expect(out).to include("installed into `../bundle`")
+ expect(bundled_app("bundle")).to be_directory
+ expect(bundled_app("bundle/ruby")).to be_directory
end
end
end
@@ -98,7 +101,7 @@ RSpec.describe "bundle install" do
if type == :env
ENV["BUNDLE_PATH"] = location
elsif type == :global
- bundle! "config set path #{location}", "no-color" => nil
+ bundle "config set path #{location}", "no-color" => nil
end
end
@@ -106,7 +109,8 @@ RSpec.describe "bundle install" do
context "when set via #{type}" do
it "installs gems to a path if one is specified" do
set_bundle_path(type, bundled_app("vendor2").to_s)
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle :install
expect(vendored_gems("gems/rack-1.0.0")).to be_directory
expect(bundled_app("vendor2")).not_to be_directory
@@ -115,9 +119,9 @@ RSpec.describe "bundle install" do
it "installs gems to ." do
set_bundle_path(type, ".")
- bundle! "config set --global disable_shared_gems true"
+ bundle "config set --global disable_shared_gems true"
- bundle! :install
+ bundle :install
paths_to_exist = %w[cache/rack-1.0.0.gem gems/rack-1.0.0 specifications/rack-1.0.0.gemspec].map {|path| bundled_app(Bundler.ruby_scope, path) }
expect(paths_to_exist).to all exist
@@ -127,7 +131,7 @@ RSpec.describe "bundle install" do
it "installs gems to the path" do
set_bundle_path(type, bundled_app("vendor").to_s)
- bundle! :install
+ bundle :install
expect(bundled_app("vendor", Bundler.ruby_scope, "gems/rack-1.0.0")).to be_directory
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -137,9 +141,7 @@ RSpec.describe "bundle install" do
set_bundle_path(type, "vendor")
FileUtils.mkdir_p bundled_app("lol")
- Dir.chdir(bundled_app("lol")) do
- bundle! :install
- end
+ bundle :install, :dir => bundled_app("lol")
expect(bundled_app("vendor", Bundler.ruby_scope, "gems/rack-1.0.0")).to be_directory
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -157,7 +159,8 @@ RSpec.describe "bundle install" do
end
it "sets BUNDLE_PATH as the first argument to bundle install" do
- bundle! :install, forgotten_command_line_options(:path => "./vendor/bundle")
+ bundle "config set --local path ./vendor/bundle"
+ bundle :install
expect(vendored_gems("gems/rack-1.0.0")).to be_directory
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -166,7 +169,8 @@ RSpec.describe "bundle install" do
it "disables system gems when passing a path to install" do
# This is so that vendored gems can be distributed to others
build_gem "rack", "1.1.0", :to_system => true
- bundle! :install, forgotten_command_line_options(:path => "./vendor/bundle")
+ bundle "config set --local path ./vendor/bundle"
+ bundle :install
expect(vendored_gems("gems/rack-1.0.0")).to be_directory
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -182,7 +186,8 @@ RSpec.describe "bundle install" do
gem "very_simple_binary"
G
- bundle! :install, forgotten_command_line_options(:path => "./vendor/bundle")
+ bundle "config set --local path ./vendor/bundle"
+ bundle :install
expect(vendored_gems("gems/very_simple_binary-1.0")).to be_directory
expect(vendored_gems("extensions")).to be_directory
@@ -190,10 +195,11 @@ RSpec.describe "bundle install" do
vendored_gems("extensions").rmtree
- run "require 'very_simple_binary_c'"
+ run "require 'very_simple_binary_c'", :raise_on_error => false
expect(err).to include("Bundler::GemNotFound")
- bundle :install, forgotten_command_line_options(:path => "./vendor/bundle")
+ bundle "config set --local path ./vendor/bundle"
+ bundle :install
expect(vendored_gems("gems/very_simple_binary-1.0")).to be_directory
expect(vendored_gems("extensions")).to be_directory
@@ -203,9 +209,7 @@ RSpec.describe "bundle install" do
describe "to a file" do
before do
- in_app_root do
- FileUtils.touch "bundle"
- end
+ FileUtils.touch bundled_app("bundle")
end
it "reports the file exists" do
@@ -214,7 +218,8 @@ RSpec.describe "bundle install" do
gem "rack"
G
- bundle :install, forgotten_command_line_options(:path => "bundle")
+ bundle "config set --local path bundle"
+ bundle :install, :raise_on_error => false
expect(err).to include("file already exists")
end
end
diff --git a/spec/bundler/install/prereleases_spec.rb b/spec/bundler/install/prereleases_spec.rb
index fb01220ed7..629eb89dac 100644
--- a/spec/bundler/install/prereleases_spec.rb
+++ b/spec/bundler/install/prereleases_spec.rb
@@ -1,10 +1,19 @@
# frozen_string_literal: true
RSpec.describe "bundle install" do
+ before do
+ build_repo2 do
+ build_gem "not_released", "1.0.pre"
+
+ build_gem "has_prerelease", "1.0"
+ build_gem "has_prerelease", "1.1.pre"
+ end
+ end
+
describe "when prerelease gems are available" do
it "finds prereleases" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "not_released"
G
expect(the_bundle).to include_gems "not_released 1.0.pre"
@@ -12,7 +21,7 @@ RSpec.describe "bundle install" do
it "uses regular releases if available" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "has_prerelease"
G
expect(the_bundle).to include_gems "has_prerelease 1.0"
@@ -20,7 +29,7 @@ RSpec.describe "bundle install" do
it "uses prereleases if requested" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "has_prerelease", "1.1.pre"
G
expect(the_bundle).to include_gems "has_prerelease 1.1.pre"
@@ -29,7 +38,11 @@ RSpec.describe "bundle install" do
describe "when prerelease gems are not available" do
it "still works" do
- build_repo3
+ build_repo gem_repo3 do
+ build_gem "rack"
+ end
+ FileUtils.rm_rf Dir[gem_repo3("prerelease*")]
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo3)}"
gem "rack"
diff --git a/spec/bundler/install/process_lock_spec.rb b/spec/bundler/install/process_lock_spec.rb
index cab4ba0819..dac0d34bc4 100644
--- a/spec/bundler/install/process_lock_spec.rb
+++ b/spec/bundler/install/process_lock_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe "process lock spec" do
end
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
diff --git a/spec/bundler/install/redownload_spec.rb b/spec/bundler/install/redownload_spec.rb
index 818c33bd61..a936b2b536 100644
--- a/spec/bundler/install/redownload_spec.rb
+++ b/spec/bundler/install/redownload_spec.rb
@@ -12,9 +12,9 @@ RSpec.describe "bundle install" do
it "re-installs installed gems" do
rack_lib = default_bundle_path("gems/rack-1.0.0/lib/rack.rb")
- bundle! :install
+ bundle :install
rack_lib.open("w") {|f| f.write("blah blah blah") }
- bundle! :install, flag => true
+ bundle :install, flag => true
expect(out).to include "Installing rack 1.0.0"
expect(rack_lib.open(&:read)).to eq("RACK = '1.0.0'\n")
@@ -22,7 +22,7 @@ RSpec.describe "bundle install" do
end
it "works on first bundle install" do
- bundle! :install, flag => true
+ bundle :install, flag => true
expect(out).to include "Installing rack 1.0.0"
expect(the_bundle).to include_gems "rack 1.0.0"
@@ -33,6 +33,7 @@ RSpec.describe "bundle install" do
before do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
end
@@ -40,16 +41,16 @@ RSpec.describe "bundle install" do
it "re-installs installed gems" do
foo_lib = default_bundle_path("bundler/gems/foo-1.0-#{ref}/lib/foo.rb")
- bundle! :install
+ bundle :install
foo_lib.open("w") {|f| f.write("blah blah blah") }
- bundle! :install, flag => true
+ bundle :install, flag => true
expect(foo_lib.open(&:read)).to eq("FOO = '1.0'\n")
expect(the_bundle).to include_gems "foo 1.0"
end
it "works on first bundle install" do
- bundle! :install, flag => true
+ bundle :install, flag => true
expect(the_bundle).to include_gems "foo 1.0"
end
@@ -62,12 +63,12 @@ RSpec.describe "bundle install" do
end
it "shows a deprecation when single flag passed" do
- bundle! "install --force"
+ bundle "install --force"
expect(err).to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
end
it "shows a deprecation when multiple flags passed" do
- bundle! "install --no-color --force"
+ bundle "install --no-color --force"
expect(err).to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
end
end
@@ -78,12 +79,12 @@ RSpec.describe "bundle install" do
end
it "does not show a deprecation when single flag passed" do
- bundle! "install --redownload"
+ bundle "install --redownload"
expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
end
it "does not show a deprecation when single multiple flags passed" do
- bundle! "install --no-color --redownload"
+ bundle "install --no-color --redownload"
expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
end
end
diff --git a/spec/bundler/install/security_policy_spec.rb b/spec/bundler/install/security_policy_spec.rb
index 28c34d9ce7..43c3069c4e 100644
--- a/spec/bundler/install/security_policy_spec.rb
+++ b/spec/bundler/install/security_policy_spec.rb
@@ -16,30 +16,28 @@ RSpec.describe "policies with unsigned gems" do
end
it "will work after you try to deploy without a lock" do
- bundle "install --deployment"
+ bundle "install --deployment", :raise_on_error => false
bundle :install
- expect(exitstatus).to eq(0) if exitstatus
expect(the_bundle).to include_gems "rack 1.0", "signed_gem 1.0"
end
it "will fail when given invalid security policy" do
- bundle "install --trust-policy=InvalidPolicyName"
+ bundle "install --trust-policy=InvalidPolicyName", :raise_on_error => false
expect(err).to include("RubyGems doesn't know about trust policy")
end
it "will fail with High Security setting due to presence of unsigned gem" do
- bundle "install --trust-policy=HighSecurity"
+ bundle "install --trust-policy=HighSecurity", :raise_on_error => false
expect(err).to include("security policy didn't allow")
end
it "will fail with Medium Security setting due to presence of unsigned gem" do
- bundle "install --trust-policy=MediumSecurity"
+ bundle "install --trust-policy=MediumSecurity", :raise_on_error => false
expect(err).to include("security policy didn't allow")
end
it "will succeed with no policy" do
bundle "install"
- expect(exitstatus).to eq(0) if exitstatus
end
end
@@ -53,24 +51,22 @@ RSpec.describe "policies with signed gems and no CA" do
end
it "will fail with High Security setting, gem is self-signed" do
- bundle "install --trust-policy=HighSecurity"
+ bundle "install --trust-policy=HighSecurity", :raise_on_error => false
expect(err).to include("security policy didn't allow")
end
it "will fail with Medium Security setting, gem is self-signed" do
- bundle "install --trust-policy=MediumSecurity"
+ bundle "install --trust-policy=MediumSecurity", :raise_on_error => false
expect(err).to include("security policy didn't allow")
end
it "will succeed with Low Security setting, low security accepts self signed gem" do
bundle "install --trust-policy=LowSecurity"
- expect(exitstatus).to eq(0) if exitstatus
expect(the_bundle).to include_gems "signed_gem 1.0"
end
it "will succeed with no policy" do
bundle "install"
- expect(exitstatus).to eq(0) if exitstatus
expect(the_bundle).to include_gems "signed_gem 1.0"
end
end
diff --git a/spec/bundler/install/yanked_spec.rb b/spec/bundler/install/yanked_spec.rb
index 80729b3f5b..c5f3d788ba 100644
--- a/spec/bundler/install/yanked_spec.rb
+++ b/spec/bundler/install/yanked_spec.rb
@@ -22,7 +22,7 @@ RSpec.context "when installing a bundle that includes yanked gems" do
L
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo4)}"
gem "foo", "10.0.0"
G
@@ -33,7 +33,7 @@ RSpec.context "when installing a bundle that includes yanked gems" do
it "throws the original error when only the Gemfile specifies a gem version that doesn't exist" do
bundle "config set force_ruby_platform true"
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo4)}"
gem "foo", "10.0.0"
G
@@ -63,11 +63,42 @@ RSpec.context "when using gem before installing" do
rack (= 0.9.1)
L
- bundle :list
+ bundle :list, :raise_on_error => false
expect(err).to include("Could not find rack-0.9.1 in any of the sources")
expect(err).to_not include("Your bundle is locked to rack (0.9.1), but that version could not be found in any of the sources listed in your Gemfile.")
expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.")
expect(err).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.")
end
+
+ it "does not suggest the author has yanked the gem when using more than one gem, but shows all gems that couldn't be found in the source" do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack", "0.9.1"
+ gem "rack_middleware", "1.0"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}
+ specs:
+ rack (0.9.1)
+ rack_middleware (1.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ rack (= 0.9.1)
+ rack_middleware (1.0)
+ L
+
+ bundle :list, :raise_on_error => false
+
+ expect(err).to include("Could not find rack-0.9.1, rack_middleware-1.0 in any of the sources")
+ expect(err).to include("Install missing gems with `bundle install`.")
+ expect(err).to_not include("Your bundle is locked to rack (0.9.1), but that version could not be found in any of the sources listed in your Gemfile.")
+ expect(err).to_not include("If you haven't changed sources, that means the author of rack (0.9.1) has removed it.")
+ expect(err).to_not include("You'll need to update your bundle to a different version of rack (0.9.1) that hasn't been removed in order to install.")
+ end
end
diff --git a/spec/bundler/lock/git_spec.rb b/spec/bundler/lock/git_spec.rb
index 14b80483ee..56db5d8305 100644
--- a/spec/bundler/lock/git_spec.rb
+++ b/spec/bundler/lock/git_spec.rb
@@ -5,6 +5,7 @@ RSpec.describe "bundle lock with git gems" do
build_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
end
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index ddab4831a5..8befb0d400 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -3,16 +3,28 @@
RSpec.describe "the lockfile format" do
include Bundler::GemHelpers
+ before do
+ build_repo2 do
+ # Capistrano did this (at least until version 2.5.10)
+ # RubyGems 2.2 doesn't allow the specifying of a dependency twice
+ # See https://github.com/rubygems/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f
+ build_gem "double_deps", "1.0", :skip_validation => true do |s|
+ s.add_dependency "net-ssh", ">= 1.0.0"
+ s.add_dependency "net-ssh"
+ end
+ end
+ end
+
it "generates a simple lockfile for a single source, gem" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -28,6 +40,8 @@ RSpec.describe "the lockfile format" do
end
it "updates the lockfile's bundler version if current ver. is newer" do
+ system_gems "bundler-1.8.2"
+
lockfile <<-L
GIT
remote: git://github.com/nex3/haml.git
@@ -35,7 +49,7 @@ RSpec.describe "the lockfile format" do
specs:
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -50,15 +64,15 @@ RSpec.describe "the lockfile format" do
1.8.2
L
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -78,7 +92,7 @@ RSpec.describe "the lockfile format" do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -93,14 +107,14 @@ RSpec.describe "the lockfile format" do
L
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -118,7 +132,7 @@ RSpec.describe "the lockfile format" do
it "updates the lockfile's bundler version if not present" do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -130,14 +144,14 @@ RSpec.describe "the lockfile format" do
L
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo2)}"
gem "rack", "> 0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -152,13 +166,14 @@ RSpec.describe "the lockfile format" do
G
end
- it "warns if the current is older than lockfile's bundler version" do
- current_version = Bundler::VERSION
- newer_minor = bump_minor(current_version)
+ it "warns if the current version is older than lockfile's bundler version, and locked version is a final release" do
+ current_version = "999.998.999"
+ system_gems "bundler-#{current_version}"
+ newer_minor = "999.999.0"
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -172,22 +187,117 @@ RSpec.describe "the lockfile format" do
#{newer_minor}
L
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, :env => { "BUNDLER_VERSION" => current_version }
+ source "#{file_uri_for(gem_repo2)}"
gem "rack"
G
- pre_flag = prerelease?(newer_minor) ? " --pre" : ""
warning_message = "the running version of Bundler (#{current_version}) is older " \
"than the version that created the lockfile (#{newer_minor}). " \
"We suggest you to upgrade to the version that created the " \
- "lockfile by running `gem install bundler:#{newer_minor}#{pre_flag}`."
+ "lockfile by running `gem install bundler:#{newer_minor}`."
expect(err).to include warning_message
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{newer_minor}
+ G
+ end
+
+ it "warns if the current version is older than lockfile's bundler version, and locked version is a prerelease" do
+ current_version = "999.998.999"
+ system_gems "bundler-#{current_version}"
+ newer_minor = "999.999.0.pre1"
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{newer_minor}
+ L
+
+ install_gemfile <<-G, :env => { "BUNDLER_VERSION" => current_version }
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "rack"
+ G
+
+ warning_message = "the running version of Bundler (#{current_version}) is older " \
+ "than the version that created the lockfile (#{newer_minor}). " \
+ "We suggest you to upgrade to the version that created the " \
+ "lockfile by running `gem install bundler:#{newer_minor} --pre`."
+ expect(err).to include warning_message
+
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{newer_minor}
+ G
+ end
+
+ it "doesn't warn if the current version is older than lockfile's bundler version, and locked version is a dev version" do
+ current_version = "999.998.999"
+ system_gems "bundler-#{current_version}"
+ newer_minor = "999.999.0.dev"
+
+ lockfile <<-L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack
+
+ BUNDLED WITH
+ #{newer_minor}
+ L
+
+ install_gemfile <<-G, :env => { "BUNDLER_VERSION" => current_version }
+ source "#{file_uri_for(gem_repo2)}"
+
+ gem "rack"
+ G
+
+ expect(err).to be_empty
+
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -206,9 +316,11 @@ RSpec.describe "the lockfile format" do
current_version = Bundler::VERSION
older_major = previous_major(current_version)
+ system_gems "bundler-#{older_major}"
+
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -222,8 +334,8 @@ RSpec.describe "the lockfile format" do
#{older_major}
L
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ install_gemfile <<-G, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack"
G
@@ -233,9 +345,9 @@ RSpec.describe "the lockfile format" do
"#{current_version.split(".").first}, after which you will be unable to return to Bundler #{older_major.split(".").first}."
)
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -252,14 +364,14 @@ RSpec.describe "the lockfile format" do
it "generates a simple lockfile for a single source, gem with dependencies" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack-obama"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
rack-obama (1.0)
@@ -278,14 +390,14 @@ RSpec.describe "the lockfile format" do
it "generates a simple lockfile for a single source, gem with a version requirement" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack-obama", ">= 1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
rack-obama (1.0)
@@ -302,43 +414,12 @@ RSpec.describe "the lockfile format" do
G
end
- it "generates a lockfile without credentials for a configured source", :bundler => "< 3" do
+ it "generates a lockfile without credentials for a configured source" do
bundle "config set http://localgemserver.test/ user:pass"
install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
- source "http://localgemserver.test/" do
-
- end
-
- source "http://user:pass@othergemserver.test/" do
- gem "rack-obama", ">= 1.0"
- end
- G
-
- lockfile_should_be <<-G
- GEM
- remote: http://localgemserver.test/
- remote: http://user:pass@othergemserver.test/
- specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- rack-obama (>= 1.0)!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "generates a lockfile without credentials for a configured source", :bundler => "3" do
- bundle "config set http://localgemserver.test/ user:pass"
+ source "#{file_uri_for(gem_repo1)}"
- install_gemfile(<<-G, :artifice => "endpoint_strict_basic_authentication", :quiet => true)
source "http://localgemserver.test/" do
end
@@ -348,8 +429,9 @@ RSpec.describe "the lockfile format" do
end
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
GEM
@@ -376,13 +458,13 @@ RSpec.describe "the lockfile format" do
it "generates lockfiles with multiple requirements" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "net-sftp"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
net-sftp (1.1.1)
net-ssh (>= 1.0.0, < 1.99.0)
@@ -401,42 +483,15 @@ RSpec.describe "the lockfile format" do
expect(the_bundle).to include_gems "net-sftp 1.1.1", "net-ssh 1.0.0"
end
- it "generates a simple lockfile for a single pinned source, gem with a version requirement", :bundler => "< 3" do
- git = build_git "foo"
-
- install_gemfile <<-G
- gem "foo", :git => "#{lib_path("foo-1.0")}"
- G
-
- lockfile_should_be <<-G
- GIT
- remote: #{lib_path("foo-1.0")}
- revision: #{git.ref_for("master")}
- specs:
- foo (1.0)
-
- GEM
- specs:
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- foo!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
it "generates a simple lockfile for a single pinned source, gem with a version requirement" do
git = build_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
revision: #{git.ref_for("master")}
@@ -444,6 +499,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -461,7 +517,7 @@ RSpec.describe "the lockfile format" do
build_lib "omg", :path => lib_path("omg")
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
platforms :#{not_local_tag} do
gem "omg", :path => "#{lib_path("omg")}"
@@ -477,7 +533,7 @@ RSpec.describe "the lockfile format" do
specs:
GEM
- remote: #{file_uri_for(gem_repo1)}//
+ remote: #{file_uri_for(gem_repo2)}//
specs:
rack (1.0.0)
@@ -492,7 +548,7 @@ RSpec.describe "the lockfile format" do
#{Bundler::VERSION}
L
- bundle! "install"
+ bundle "install"
expect(the_bundle).to include_gems "rack 1.0.0"
end
@@ -500,12 +556,13 @@ RSpec.describe "the lockfile format" do
git = build_git "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
revision: #{git.ref_for("master")}
@@ -513,6 +570,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -531,10 +589,11 @@ RSpec.describe "the lockfile format" do
update_git "foo", :branch => "omg"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
revision: #{git.ref_for("omg")}
@@ -543,6 +602,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -561,10 +621,11 @@ RSpec.describe "the lockfile format" do
update_git "foo", :tag => "omg"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}", :tag => "omg"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("foo-1.0")}
revision: #{git.ref_for("omg")}
@@ -573,6 +634,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -590,16 +652,18 @@ RSpec.describe "the lockfile format" do
build_lib "foo"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo-1.0")}
specs:
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -616,21 +680,23 @@ RSpec.describe "the lockfile format" do
it "serializes pinned path sources to the lockfile even when packaging" do
build_lib "foo"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
bundle "config set cache_all true"
- bundle! :cache
- bundle! :install, :local => true
+ bundle :cache
+ bundle :install, :local => true
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo-1.0")}
specs:
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -649,14 +715,14 @@ RSpec.describe "the lockfile format" do
bar = build_git "bar"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack"
gem "foo", :path => "#{lib_path("foo-1.0")}"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GIT
remote: #{lib_path("bar-1.0")}
revision: #{bar.ref_for("master")}
@@ -669,7 +735,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -686,18 +752,42 @@ RSpec.describe "the lockfile format" do
G
end
+ it "removes redundant sources" do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}/"
+
+ gem "rack", :source => "#{file_uri_for(gem_repo2)}/"
+ G
+
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ rack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
+
it "lists gems alphabetically" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "thin"
gem "actionpack"
gem "rack-obama"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
actionpack (2.3.2)
activesupport (= 2.3.2)
@@ -723,14 +813,14 @@ RSpec.describe "the lockfile format" do
it "orders dependencies' dependencies in alphabetical order" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rails"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
actionmailer (2.3.2)
activesupport (= 2.3.2)
@@ -746,8 +836,8 @@ RSpec.describe "the lockfile format" do
actionpack (= 2.3.2)
activerecord (= 2.3.2)
activeresource (= 2.3.2)
- rake (= 12.3.2)
- rake (12.3.2)
+ rake (= 13.0.1)
+ rake (13.0.1)
PLATFORMS
#{lockfile_platforms}
@@ -762,13 +852,13 @@ RSpec.describe "the lockfile format" do
it "orders dependencies by version" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem 'double_deps'
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
double_deps (1.0)
net-ssh
@@ -788,14 +878,14 @@ RSpec.describe "the lockfile format" do
it "does not add the :require option to the lockfile" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack-obama", ">= 1.0", :require => "rack/obama"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
rack-obama (1.0)
@@ -814,14 +904,14 @@ RSpec.describe "the lockfile format" do
it "does not add the :group option to the lockfile" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack-obama", ">= 1.0", :group => :test
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
rack-obama (1.0)
@@ -842,18 +932,20 @@ RSpec.describe "the lockfile format" do
build_lib "foo", :path => bundled_app("foo")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path "foo" do
gem "foo"
end
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: foo
specs:
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -871,18 +963,20 @@ RSpec.describe "the lockfile format" do
build_lib "foo", :path => bundled_app(File.join("..", "foo"))
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path "../foo" do
gem "foo"
end
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: ../foo
specs:
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -900,18 +994,20 @@ RSpec.describe "the lockfile format" do
build_lib "foo", :path => bundled_app("foo")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path File.expand_path("../foo", __FILE__) do
gem "foo"
end
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: foo
specs:
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -929,16 +1025,18 @@ RSpec.describe "the lockfile format" do
build_lib("foo", :path => tmp.join("foo"))
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gemspec :path => "../foo"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PATH
remote: ../foo
specs:
foo (1.0)
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -952,51 +1050,10 @@ RSpec.describe "the lockfile format" do
G
end
- it "keeps existing platforms in the lockfile", :bundler => "< 3" do
- lockfile <<-G
- GEM
- remote: #{file_uri_for(gem_repo1)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- java
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
-
- gem "rack"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: #{file_uri_for(gem_repo1)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- java
- #{generic_local_platform}
-
- DEPENDENCIES
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "keeps existing platforms in the lockfile", :bundler => "3" do
+ it "keeps existing platforms in the lockfile" do
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -1011,21 +1068,19 @@ RSpec.describe "the lockfile format" do
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
PLATFORMS
- java
- #{generic_local_platform}
- #{specific_local_platform}
+ #{lockfile_platforms_for(["java"] + local_platforms)}
DEPENDENCIES
rack
@@ -1035,38 +1090,7 @@ RSpec.describe "the lockfile format" do
G
end
- it "persists the spec's platform to the lockfile", :bundler => "< 3" do
- build_repo2 do
- build_gem "platform_specific", "1.0" do |s|
- s.platform = Gem::Platform.new("universal-java-16")
- end
- end
-
- simulate_platform "universal-java-16"
-
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "platform_specific"
- G
-
- lockfile_should_be <<-G
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- platform_specific (1.0-java)
-
- PLATFORMS
- java
-
- DEPENDENCIES
- platform_specific
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "persists the spec's platform and specific platform to the lockfile", :bundler => "3" do
+ it "persists the spec's specific platform to the lockfile" do
build_repo2 do
build_gem "platform_specific", "1.0" do |s|
s.platform = Gem::Platform.new("universal-java-16")
@@ -1075,20 +1099,18 @@ RSpec.describe "the lockfile format" do
simulate_platform "universal-java-16"
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "platform_specific"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
remote: #{file_uri_for(gem_repo2)}/
specs:
- platform_specific (1.0-java)
platform_specific (1.0-universal-java-16)
PLATFORMS
- java
universal-java-16
DEPENDENCIES
@@ -1101,19 +1123,19 @@ RSpec.describe "the lockfile format" do
it "does not add duplicate gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack"
gem "activesupport"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
activesupport (2.3.5)
rack (1.0.0)
@@ -1132,14 +1154,14 @@ RSpec.describe "the lockfile format" do
it "does not add duplicate dependencies" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack"
gem "rack"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -1156,14 +1178,14 @@ RSpec.describe "the lockfile format" do
it "does not add duplicate dependencies with versions" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack", "1.0"
gem "rack", "1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -1180,14 +1202,14 @@ RSpec.describe "the lockfile format" do
it "does not add duplicate dependencies in different groups" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack", "1.0", :group => :one
gem "rack", "1.0", :group => :two
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (1.0.0)
@@ -1203,36 +1225,36 @@ RSpec.describe "the lockfile format" do
end
it "raises if two different versions are used" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack", "1.0"
gem "rack", "1.1"
G
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
expect(err).to include "rack (= 1.0) and rack (= 1.1)"
end
it "raises if two different sources are used" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack"
gem "rack", :git => "git://hubz.com"
G
- expect(bundled_app("Gemfile.lock")).not_to exist
- expect(err).to include "rack (>= 0) should come from an unspecified source and git://hubz.com (at master)"
+ expect(bundled_app_lock).not_to exist
+ expect(err).to include "rack (>= 0) should come from an unspecified source and git://hubz.com"
end
it "works correctly with multiple version dependencies" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack", "> 0.9", "< 1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (0.9.1)
@@ -1249,14 +1271,14 @@ RSpec.describe "the lockfile format" do
it "captures the Ruby version in the lockfile" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
+ source "#{file_uri_for(gem_repo2)}/"
ruby '#{RUBY_VERSION}'
gem "rack", "> 0.9", "< 1.0"
G
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack (0.9.1)
@@ -1274,86 +1296,10 @@ RSpec.describe "the lockfile format" do
G
end
- # Some versions of the Bundler 1.1 RC series introduced corrupted
- # lockfiles. There were two major problems:
- #
- # * multiple copies of the same GIT section appeared in the lockfile
- # * when this happened, those sections got multiple copies of gems
- # in those sections.
- it "fixes corrupted lockfiles" do
- build_git "omg", :path => lib_path("omg")
- revision = revision_for(lib_path("omg"))
-
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}/"
- gem "omg", :git => "#{lib_path("omg")}", :branch => 'master'
- G
-
- bundle! :install, forgotten_command_line_options(:path => "vendor")
- expect(the_bundle).to include_gems "omg 1.0"
-
- # Create a Gemfile.lock that has duplicate GIT sections
- lockfile <<-L
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
- specs:
- omg (1.0)
-
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
- specs:
- omg (1.0)
-
- GEM
- remote: #{file_uri_for(gem_repo1)}/
- specs:
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- omg!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
- FileUtils.rm_rf(bundled_app("vendor"))
- bundle "install"
- expect(the_bundle).to include_gems "omg 1.0"
-
- # Confirm that duplicate specs do not appear
- lockfile_should_be(<<-L)
- GIT
- remote: #{lib_path("omg")}
- revision: #{revision}
- branch: master
- specs:
- omg (1.0)
-
- GEM
- remote: #{file_uri_for(gem_repo1)}/
- specs:
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- omg!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
-
it "raises a helpful error message when the lockfile is missing deps" do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo2)}/
specs:
rack_middleware (1.0)
@@ -1364,8 +1310,8 @@ RSpec.describe "the lockfile format" do
rack_middleware
L
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}"
gem "rack_middleware"
G
@@ -1376,7 +1322,7 @@ RSpec.describe "the lockfile format" do
describe "a line ending" do
def set_lockfile_mtime_to_known_value
time = Time.local(2000, 1, 1, 0, 0, 0)
- File.utime(time, time, bundled_app("Gemfile.lock"))
+ File.utime(time, time, bundled_app_lock)
end
before(:each) do
build_repo2
@@ -1389,28 +1335,42 @@ RSpec.describe "the lockfile format" do
end
it "generates Gemfile.lock with \\n line endings" do
- expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n")
+ expect(File.read(bundled_app_lock)).not_to match("\r\n")
expect(the_bundle).to include_gems "rack 1.0"
end
context "during updates" do
it "preserves Gemfile.lock \\n line endings" do
- update_repo2
-
- expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) }
- expect(File.read(bundled_app("Gemfile.lock"))).not_to match("\r\n")
+ update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+ end
+
+ expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) }
+ expect(File.read(bundled_app_lock)).not_to match("\r\n")
expect(the_bundle).to include_gems "rack 1.2"
end
it "preserves Gemfile.lock \\n\\r line endings" do
- update_repo2
- win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n")
- File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) }
+ skip "needs to be adapted" if Gem.win_platform?
+
+ update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+ end
+
+ win_lock = File.read(bundled_app_lock).gsub(/\n/, "\r\n")
+ File.open(bundled_app_lock, "wb") {|f| f.puts(win_lock) }
set_lockfile_mtime_to_known_value
- expect { bundle "update", :all => true }.to change { File.mtime(bundled_app("Gemfile.lock")) }
- expect(File.read(bundled_app("Gemfile.lock"))).to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.2"
+ expect { bundle "update", :all => true }.to change { File.mtime(bundled_app_lock) }
+ expect(File.read(bundled_app_lock)).to match("\r\n")
+
+ simulate_bundler_version_when_missing_prerelease_default_gem_activation do
+ expect(the_bundle).to include_gems "rack 1.2"
+ end
end
end
@@ -1421,20 +1381,20 @@ RSpec.describe "the lockfile format" do
require 'bundler'
Bundler.setup
RUBY
- end.not_to change { File.mtime(bundled_app("Gemfile.lock")) }
+ end.not_to change { File.mtime(bundled_app_lock) }
end
it "preserves Gemfile.lock \\n\\r line endings" do
- win_lock = File.read(bundled_app("Gemfile.lock")).gsub(/\n/, "\r\n")
- File.open(bundled_app("Gemfile.lock"), "wb") {|f| f.puts(win_lock) }
+ win_lock = File.read(bundled_app_lock).gsub(/\n/, "\r\n")
+ File.open(bundled_app_lock, "wb") {|f| f.puts(win_lock) }
set_lockfile_mtime_to_known_value
expect do
ruby <<-RUBY
- require 'bundler'
+ require '#{entrypoint}'
Bundler.setup
RUBY
- end.not_to change { File.mtime(bundled_app("Gemfile.lock")) }
+ end.not_to change { File.mtime(bundled_app_lock) }
end
end
end
@@ -1442,7 +1402,7 @@ 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_repo1)}//
+ remote: #{file_uri_for(gem_repo2)}//
specs:
<<<<<<<
rack (1.0.0)
@@ -1460,8 +1420,8 @@ RSpec.describe "the lockfile format" do
#{Bundler::VERSION}
L
- install_gemfile(<<-G)
- source "#{file_uri_for(gem_repo1)}/"
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo2)}/"
gem "rack"
G
@@ -1469,7 +1429,7 @@ RSpec.describe "the lockfile format" do
expect(err).to match(/git checkout HEAD -- Gemfile.lock/i)
end
-private
+ private
def prerelease?(version)
Gem::Version.new(version).prerelease?
diff --git a/spec/bundler/other/cli_dispatch_spec.rb b/spec/bundler/other/cli_dispatch_spec.rb
index 0082606d7e..2d6080296f 100644
--- a/spec/bundler/other/cli_dispatch_spec.rb
+++ b/spec/bundler/other/cli_dispatch_spec.rb
@@ -2,19 +2,19 @@
RSpec.describe "bundle command names" do
it "work when given fully" do
- bundle "install"
+ bundle "install", :raise_on_error => false
expect(err).to eq("Could not locate Gemfile")
expect(last_command.stdboth).not_to include("Ambiguous command")
end
it "work when not ambiguous" do
- bundle "ins"
+ bundle "ins", :raise_on_error => false
expect(err).to eq("Could not locate Gemfile")
expect(last_command.stdboth).not_to include("Ambiguous command")
end
it "print a friendly error when ambiguous" do
- bundle "in"
+ bundle "in", :raise_on_error => false
expect(err).to eq("Ambiguous command in matches [info, init, inject, install]")
end
end
diff --git a/spec/bundler/other/ext_spec.rb b/spec/bundler/other/ext_spec.rb
index f2a512e629..e13f62a856 100644
--- a/spec/bundler/other/ext_spec.rb
+++ b/spec/bundler/other/ext_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe "Gem::SourceIndex#refresh!" do
end
it "does not explode when called" do
- run "Gem.source_index.refresh!"
- run "Gem::SourceIndex.new([]).refresh!"
+ run "Gem.source_index.refresh!", :raise_on_error => false
+ run "Gem::SourceIndex.new([]).refresh!", :raise_on_error => false
end
end
diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb
index df2fdd263a..b228027c03 100644
--- a/spec/bundler/other/major_deprecation_spec.rb
+++ b/spec/bundler/other/major_deprecation_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe "major deprecations" do
describe "Bundler" do
before do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -17,7 +17,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .unbundled_env", :bundler => "2" do
+ it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do
expect(deprecations).to include \
"`Bundler.clean_env` has been deprecated in favor of `Bundler.unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.original_env` " \
@@ -33,7 +33,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .unbundled_env", :bundler => "2" do
+ it "is deprecated in favor of .unbundled_env", :bundler => "< 3" do
expect(deprecations).to include(
"`Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env` " \
@@ -50,7 +50,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .unbundled_system", :bundler => "2" do
+ it "is deprecated in favor of .unbundled_system", :bundler => "< 3" do
expect(deprecations).to include(
"`Bundler.clean_system` has been deprecated in favor of `Bundler.unbundled_system`. " \
"If you instead want to run the command in the environment before bundler was originally loaded, use `Bundler.original_system` " \
@@ -67,7 +67,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .unbundled_exec", :bundler => "2" do
+ it "is deprecated in favor of .unbundled_exec", :bundler => "< 3" do
expect(deprecations).to include(
"`Bundler.clean_exec` has been deprecated in favor of `Bundler.unbundled_exec`. " \
"If you instead want to exec to a command in the environment before bundler was originally loaded, use `Bundler.original_exec` " \
@@ -84,7 +84,7 @@ RSpec.describe "major deprecations" do
bundle "exec ruby -e #{source.dump}"
end
- it "is deprecated in favor of .load", :bundler => "2" do
+ it "is deprecated in favor of .load", :bundler => "< 3" do
expect(deprecations).to include "Bundler.environment has been removed in favor of Bundler.load (called at -e:1)"
end
@@ -92,9 +92,21 @@ RSpec.describe "major deprecations" do
end
end
+ describe "bundle exec --no-keep-file-descriptors" do
+ before do
+ bundle "exec --no-keep-file-descriptors -e 1", :raise_on_error => false
+ end
+
+ it "is deprecated", :bundler => "< 3" do
+ expect(deprecations).to include "The `--no-keep-file-descriptors` has been deprecated. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to"
+ end
+
+ pending "is removed and shows a helpful error message about it", :bundler => "3"
+ end
+
describe "bundle update --quiet" do
it "does not print any deprecations" do
- bundle :update, :quiet => true
+ bundle :update, :quiet => true, :raise_on_error => false
expect(deprecations).to be_empty
end
end
@@ -106,25 +118,91 @@ RSpec.describe "major deprecations" do
gem "rack"
G
- bundle "check --path vendor/bundle"
+ bundle "check --path vendor/bundle", :raise_on_error => false
end
- it "should print a deprecation warning", :bundler => "2" do
+ it "should print a deprecation warning", :bundler => "< 3" do
expect(deprecations).to include(
"The `--path` flag is deprecated because it relies on being " \
"remembered across bundler invocations, which bundler will no " \
- "longer do in future versions. Instead please use `bundle config set " \
+ "longer do in future versions. Instead please use `bundle config set --local " \
+ "path 'vendor/bundle'`, and stop using this flag"
+ )
+ end
+
+ pending "fails with a helpful error", :bundler => "3"
+ end
+
+ context "bundle check --path=" do
+ before do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ bundle "check --path=vendor/bundle", :raise_on_error => false
+ end
+
+ it "should print a deprecation warning", :bundler => "< 3" do
+ expect(deprecations).to include(
+ "The `--path` flag is deprecated because it relies on being " \
+ "remembered across bundler invocations, which bundler will no " \
+ "longer do in future versions. Instead please use `bundle config set --local " \
"path 'vendor/bundle'`, and stop using this flag"
)
end
- pending "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
+ end
+
+ context "bundle cache --all" do
+ before do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ bundle "cache --all", :raise_on_error => false
+ end
+
+ it "should print a deprecation warning", :bundler => "< 3" do
+ expect(deprecations).to include(
+ "The `--all` flag is deprecated because it relies on being " \
+ "remembered across bundler invocations, which bundler will no " \
+ "longer do in future versions. Instead please use `bundle config set " \
+ "cache_all true`, and stop using this flag"
+ )
+ end
+
+ pending "fails with a helpful error", :bundler => "3"
+ end
+
+ context "bundle cache --path" do
+ before do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
+
+ bundle "cache --path foo", :raise_on_error => false
+ end
+
+ it "should print a deprecation warning", :bundler => "< 3" do
+ expect(deprecations).to include(
+ "The `--path` flag is deprecated because its semantics are unclear. " \
+ "Use `bundle config cache_path` to configure the path of your cache of gems, " \
+ "and `bundle config path` to configure the path where your gems are installed, " \
+ "and stop using this flag"
+ )
+ end
+
+ pending "fails with a helpful error", :bundler => "3"
end
describe "bundle config" do
describe "old list interface" do
before do
- bundle! "config"
+ bundle "config"
end
it "warns", :bundler => "3" do
@@ -136,7 +214,7 @@ RSpec.describe "major deprecations" do
describe "old get interface" do
before do
- bundle! "config waka"
+ bundle "config waka"
end
it "warns", :bundler => "3" do
@@ -148,7 +226,7 @@ RSpec.describe "major deprecations" do
describe "old set interface" do
before do
- bundle! "config waka wakapun"
+ bundle "config waka wakapun"
end
it "warns", :bundler => "3" do
@@ -160,7 +238,7 @@ RSpec.describe "major deprecations" do
describe "old set interface with --local" do
before do
- bundle! "config --local waka wakapun"
+ bundle "config --local waka wakapun"
end
it "warns", :bundler => "3" do
@@ -172,7 +250,7 @@ RSpec.describe "major deprecations" do
describe "old set interface with --global" do
before do
- bundle! "config --global waka wakapun"
+ bundle "config --global waka wakapun"
end
it "warns", :bundler => "3" do
@@ -184,7 +262,7 @@ RSpec.describe "major deprecations" do
describe "old unset interface" do
before do
- bundle! "config --delete waka"
+ bundle "config --delete waka"
end
it "warns", :bundler => "3" do
@@ -196,7 +274,7 @@ RSpec.describe "major deprecations" do
describe "old unset interface with --local" do
before do
- bundle! "config --delete --local waka"
+ bundle "config --delete --local waka"
end
it "warns", :bundler => "3" do
@@ -208,7 +286,7 @@ RSpec.describe "major deprecations" do
describe "old unset interface with --global" do
before do
- bundle! "config --delete --global waka"
+ bundle "config --delete --global waka"
end
it "warns", :bundler => "3" do
@@ -228,14 +306,14 @@ RSpec.describe "major deprecations" do
end
it "warns when no options are given", :bundler => "3" do
- bundle! "update"
+ bundle "update"
expect(deprecations).to include("Pass --all to `bundle update` to update everything")
end
pending "fails with a helpful error when no options are given", :bundler => "3"
it "does not warn when --all is passed" do
- bundle! "update --all"
+ bundle "update --all"
expect(deprecations).to be_empty
end
end
@@ -248,8 +326,8 @@ RSpec.describe "major deprecations" do
G
end
- it "should output a deprecation warning", :bundler => "2" do
- expect(deprecations).to include("The --binstubs option will be removed in favor of `bundle binstubs`")
+ it "should output a deprecation warning", :bundler => "< 3" do
+ expect(deprecations).to include("The --binstubs option will be removed in favor of `bundle binstubs --all`")
end
pending "fails with a helpful error", :bundler => "3"
@@ -267,8 +345,8 @@ RSpec.describe "major deprecations" do
end
it "should print a proper warning, and use gems.rb" do
- create_file "gems.rb"
- install_gemfile! <<-G
+ create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
@@ -292,17 +370,18 @@ RSpec.describe "major deprecations" do
end
{
- :clean => true,
- :deployment => true,
- :frozen => true,
- :"no-cache" => true,
- :"no-prune" => true,
- :path => "vendor/bundle",
- :shebang => "ruby27",
- :system => true,
- :without => "development",
- :with => "development",
- }.each do |name, value|
+ "clean" => ["clean", true],
+ "deployment" => ["deployment", true],
+ "frozen" => ["frozen", true],
+ "no-deployment" => ["deployment", false],
+ "no-prune" => ["no_prune", true],
+ "path" => ["path", "vendor/bundle"],
+ "shebang" => ["shebang", "ruby27"],
+ "system" => ["system", true],
+ "without" => ["without", "development"],
+ "with" => ["with", "development"],
+ }.each do |name, expectations|
+ option_name, value = *expectations
flag_name = "--#{name}"
context "with the #{flag_name} flag" do
@@ -311,16 +390,16 @@ RSpec.describe "major deprecations" do
bundle "install #{flag_name} #{value}"
end
- it "should print a deprecation warning", :bundler => "2" do
+ it "should print a deprecation warning", :bundler => "< 3" do
expect(deprecations).to include(
"The `#{flag_name}` flag is deprecated because it relies on " \
"being remembered across bundler invocations, which bundler " \
"will no longer do in future versions. Instead please use " \
- "`bundle config set #{name} '#{value}'`, and stop using this flag"
+ "`bundle config set --local #{option_name} '#{value}'`, and stop using this flag"
)
end
- pending "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
end
end
end
@@ -333,30 +412,98 @@ RSpec.describe "major deprecations" do
G
end
- it "shows a deprecation", :bundler => "2" do
+ it "shows a deprecation", :bundler => "< 3" do
+ expect(deprecations).to include(
+ "Your Gemfile contains multiple primary sources. " \
+ "Using `source` more than once without a block is a security risk, and " \
+ "may result in installing unexpected gems. To resolve this warning, use " \
+ "a block to indicate which gems should come from the secondary source."
+ )
+ end
+
+ it "doesn't show lockfile deprecations if there's a lockfile", :bundler => "< 3" do
+ bundle "install"
+
expect(deprecations).to include(
"Your Gemfile contains multiple primary sources. " \
"Using `source` more than once without a block is a security risk, and " \
"may result in installing unexpected gems. To resolve this warning, use " \
- "a block to indicate which gems should come from the secondary source. " \
- "To upgrade this warning to an error, run `bundle config set " \
- "disable_multisource true`."
+ "a block to indicate which gems should come from the secondary source."
)
+ expect(deprecations).not_to include(
+ "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \
+ "Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure."
+ )
+ bundle "config set --local frozen true"
+ bundle "install"
+
+ expect(deprecations).to include(
+ "Your Gemfile contains multiple primary sources. " \
+ "Using `source` more than once without a block is a security risk, and " \
+ "may result in installing unexpected gems. To resolve this warning, use " \
+ "a block to indicate which gems should come from the secondary source."
+ )
+ expect(deprecations).not_to include(
+ "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. " \
+ "Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure."
+ )
+ end
+
+ pending "fails with a helpful error", :bundler => "3"
+ end
+
+ context "bundle install in frozen mode with a lockfile with a single rubygems section with multiple remotes" do
+ before do
+ build_repo gem_repo3 do
+ build_gem "rack", "0.9.1"
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ source "#{file_uri_for(gem_repo3)}" do
+ gem 'rack'
+ end
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ remote: #{file_uri_for(gem_repo3)}/
+ specs:
+ rack (0.9.1)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "config set --local frozen true"
+ end
+
+ it "shows a deprecation", :bundler => "< 3" do
+ bundle "install"
+
+ expect(deprecations).to include("Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure.")
end
- pending "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
end
context "when Bundler.setup is run in a ruby script" do
before do
- create_file "gems.rb"
- install_gemfile! <<-G
+ create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :group => :test
G
ruby <<-RUBY
- require '#{lib_dir}/bundler'
+ require '#{entrypoint}'
Bundler.setup
Bundler.setup
@@ -372,19 +519,19 @@ RSpec.describe "major deprecations" do
context "when `bundler/deployment` is required in a ruby script" do
before do
- ruby(<<-RUBY)
+ ruby(<<-RUBY, :env => env_for_missing_prerelease_default_gem_activation)
require 'bundler/deployment'
RUBY
end
- it "should print a capistrano deprecation warning", :bundler => "2" do
+ it "should print a capistrano deprecation warning", :bundler => "< 3" do
expect(deprecations).to include("Bundler no longer integrates " \
"with Capistrano, but Capistrano provides " \
"its own integration with Bundler via the " \
"capistrano-bundler gem. Use it instead.")
end
- pending "should fail with a helpful error", :bundler => "3"
+ pending "fails with a helpful error", :bundler => "3"
end
describe Bundler::Dsl do
@@ -394,25 +541,34 @@ RSpec.describe "major deprecations" do
end
context "with github gems" do
- it "warns about removal", :bundler => "2" do
+ it "does not warn about removal", :bundler => "< 3" do
+ expect(Bundler.ui).not_to receive(:warn)
+ subject.gem("sparks", :github => "indirect/sparks")
+ github_uri = "https://github.com/indirect/sparks.git"
+ expect(subject.dependencies.first.source.uri).to eq(github_uri)
+ end
+
+ it "warns about removal", :bundler => "3" do
msg = <<-EOS
The :github git source is deprecated, and will be removed in the future. Change any "reponame" :github sources to "username/reponame". Add this code to the top of your Gemfile to ensure it continues to work:
git_source(:github) {|repo_name| "https://github.com/\#{repo_name}.git" }
EOS
- expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg)
+ expect(Bundler.ui).to receive(:warn).with("[DEPRECATED] #{msg}")
subject.gem("sparks", :github => "indirect/sparks")
github_uri = "https://github.com/indirect/sparks.git"
expect(subject.dependencies.first.source.uri).to eq(github_uri)
end
-
- pending "should fail with a helpful error", :bundler => "3"
end
context "with bitbucket gems" do
- it "warns about removal", :bundler => "2" do
- allow(Bundler.ui).to receive(:deprecate)
+ it "does not warn about removal", :bundler => "< 3" do
+ expect(Bundler.ui).not_to receive(:warn)
+ subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails")
+ end
+
+ it "warns about removal", :bundler => "3" do
msg = <<-EOS
The :bitbucket git source is deprecated, and will be removed in the future. Add this code to the top of your Gemfile to ensure it continues to work:
@@ -423,105 +579,64 @@ The :bitbucket git source is deprecated, and will be removed in the future. Add
end
EOS
- expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg)
+ expect(Bundler.ui).to receive(:warn).with("[DEPRECATED] #{msg}")
subject.gem("not-really-a-gem", :bitbucket => "mcorp/flatlab-rails")
end
-
- pending "should fail with a helpful error", :bundler => "3"
end
context "with gist gems" do
- it "warns about removal", :bundler => "2" do
- allow(Bundler.ui).to receive(:deprecate)
+ it "does not warn about removal", :bundler => "< 3" do
+ expect(Bundler.ui).not_to receive(:warn)
+ subject.gem("not-really-a-gem", :gist => "1234")
+ end
+
+ it "warns about removal", :bundler => "3" do
msg = <<-EOS
The :gist git source is deprecated, and will be removed in the future. Add this code to the top of your Gemfile to ensure it continues to work:
git_source(:gist) {|repo_name| "https://gist.github.com/\#{repo_name}.git" }
EOS
- expect(Bundler::SharedHelpers).to receive(:major_deprecation).with(3, msg)
+ expect(Bundler.ui).to receive(:warn).with("[DEPRECATED] #{msg}")
subject.gem("not-really-a-gem", :gist => "1234")
end
-
- pending "should fail with a helpful error", :bundler => "3"
end
end
context "bundle show" do
before do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
end
- context "without flags" do
- before do
- bundle! :show
- end
-
- it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do
- expect(deprecations).to include("use `bundle list` instead of `bundle show`")
- end
-
- pending "fails with a helpful message", :bundler => "3"
- end
-
context "with --outdated flag" do
before do
- bundle! "show --outdated"
+ bundle "show --outdated"
end
- it "prints a deprecation warning informing about its removal", :bundler => "2" do
+ it "prints a deprecation warning informing about its removal", :bundler => "< 3" do
expect(deprecations).to include("the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement")
end
pending "fails with a helpful message", :bundler => "3"
end
+ end
- context "with --verbose flag" do
- before do
- bundle! "show --verbose"
- end
-
- it "prints a deprecation warning informing about its removal", :bundler => "2" do
- expect(deprecations).to include("the `--verbose` flag to `bundle show` was undocumented and will be removed without replacement")
- end
-
- pending "fails with a helpful message", :bundler => "3"
- end
-
- context "with a gem argument" do
- before do
- bundle! "show rack"
- end
-
- it "prints a deprecation warning recommending `bundle info`", :bundler => "2" do
- expect(deprecations).to include("use `bundle info rack` instead of `bundle show rack`")
- end
-
- pending "fails with a helpful message", :bundler => "3"
- end
-
- context "with the --paths option" do
- before do
- bundle "show --paths"
- end
-
- it "prints a deprecation warning recommending `bundle list`", :bundler => "2" do
- expect(deprecations).to include("use `bundle list` instead of `bundle show --paths`")
- end
-
- pending "fails with a helpful message", :bundler => "3"
+ context "bundle remove" do
+ before do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
end
- context "with a gem argument and the --paths option" do
- before do
- bundle "show rack --paths"
- end
+ context "with --install" do
+ it "shows a deprecation warning", :bundler => "< 3" do
+ bundle "remove rack --install"
- it "prints deprecation warning recommending `bundle info`", :bundler => "2" do
- expect(deprecations).to include("use `bundle info rack --path` instead of `bundle show rack --paths`")
+ expect(err).to include "[DEPRECATED] The `--install` flag has been deprecated. `bundle install` is triggered by default."
end
pending "fails with a helpful message", :bundler => "3"
@@ -530,10 +645,10 @@ The :gist git source is deprecated, and will be removed in the future. Add this
context "bundle console" do
before do
- bundle "console"
+ bundle "console", :raise_on_error => false
end
- it "prints a deprecation warning", :bundler => "2" do
+ 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>`"
end
@@ -542,21 +657,63 @@ The :gist git source is deprecated, and will be removed in the future. Add this
end
context "bundle viz" do
- let(:ruby_graphviz) do
- graphviz_glob = base_system_gems.join("cache/ruby-graphviz*")
- Pathname.glob(graphviz_glob).first
- end
-
before do
- system_gems ruby_graphviz
- create_file "gems.rb"
+ graphviz_version = RUBY_VERSION >= "2.4" ? "1.2.5" : "1.2.4"
+ realworld_system_gems "ruby-graphviz --version #{graphviz_version}"
+ create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\""
bundle "viz"
end
- it "prints a deprecation warning", :bundler => "2" do
- expect(deprecations).to include "The `viz` command has been moved to the `bundle-viz` gem, see https://github.com/bundler/bundler-viz"
+ it "prints a deprecation warning", :bundler => "< 3" do
+ expect(deprecations).to include "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
+
+ describe "deprecating rubocop", :readline do
+ context "bundle gem --rubocop" do
+ before 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"
+ end
+ end
+
+ context "bundle gem --no-rubocop" do
+ before 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"
+ 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
+ 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
+ end
+ end
end
diff --git a/spec/bundler/other/platform_spec.rb b/spec/bundler/other/platform_spec.rb
index 9f25637622..5693d6bce6 100644
--- a/spec/bundler/other/platform_spec.rb
+++ b/spec/bundler/other/platform_spec.rb
@@ -168,9 +168,9 @@ G
gem "foo"
G
- bundle "platform"
+ bundle "platform", :raise_on_error => false
- expect(exitstatus).not_to eq(0) if exitstatus
+ expect(exitstatus).not_to eq(0)
end
it "raises an error if engine_version is used but engine is not" do
@@ -181,9 +181,9 @@ G
gem "foo"
G
- bundle "platform"
+ bundle "platform", :raise_on_error => false
- expect(exitstatus).not_to eq(0) if exitstatus
+ expect(exitstatus).not_to eq(0)
end
it "raises an error if engine version doesn't match ruby version for MRI" do
@@ -194,9 +194,9 @@ G
gem "foo"
G
- bundle "platform"
+ bundle "platform", :raise_on_error => false
- expect(exitstatus).not_to eq(0) if exitstatus
+ expect(exitstatus).not_to eq(0)
end
it "should print if no ruby version is specified" do
@@ -213,11 +213,13 @@ G
it "handles when there is a locked requirement" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
ruby "< 1.8.7"
G
lockfile <<-L
GEM
+ remote: #{file_uri_for(gem_repo1)}/
specs:
PLATFORMS
@@ -232,25 +234,27 @@ G
#{Bundler::VERSION}
L
- bundle! "platform --ruby"
+ bundle "platform --ruby"
expect(out).to eq("ruby 1.0.0p127")
end
it "handles when there is a requirement in the gemfile" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
ruby ">= 1.8.7"
G
- bundle! "platform --ruby"
+ bundle "platform --ruby"
expect(out).to eq("ruby 1.8.7")
end
it "handles when there are multiple requirements in the gemfile" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
ruby ">= 1.8.7", "< 2.0.0"
G
- bundle! "platform --ruby"
+ bundle "platform --ruby"
expect(out).to eq("ruby 1.8.7")
end
end
@@ -265,27 +269,27 @@ G
let(:patchlevel_fixnum) { "#{ruby_version_correct}, :patchlevel => #{RUBY_PATCHLEVEL}1" }
def should_be_ruby_version_incorrect
- expect(exitstatus).to eq(18) if exitstatus
+ expect(exitstatus).to eq(18)
expect(err).to be_include("Your Ruby version is #{RUBY_VERSION}, but your Gemfile specified #{not_local_ruby_version}")
end
def should_be_engine_incorrect
- expect(exitstatus).to eq(18) if exitstatus
+ expect(exitstatus).to eq(18)
expect(err).to be_include("Your Ruby engine is #{local_ruby_engine}, but your Gemfile specified #{not_local_tag}")
end
def should_be_engine_version_incorrect
- expect(exitstatus).to eq(18) if exitstatus
+ expect(exitstatus).to eq(18)
expect(err).to be_include("Your #{local_ruby_engine} version is #{local_engine_version}, but your Gemfile specified #{local_ruby_engine} #{not_local_engine_version}")
end
def should_be_patchlevel_incorrect
- expect(exitstatus).to eq(18) if exitstatus
+ expect(exitstatus).to eq(18)
expect(err).to be_include("Your Ruby patchlevel is #{RUBY_PATCHLEVEL}, but your Gemfile specified #{not_local_patchlevel}")
end
def should_be_patchlevel_fixnum
- expect(exitstatus).to eq(18) if exitstatus
+ expect(exitstatus).to eq(18)
expect(err).to be_include("The Ruby patchlevel in your Gemfile must be a string")
end
@@ -298,20 +302,18 @@ G
#{ruby_version_correct}
G
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
- it "installs fine with any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ it "installs fine with any engine", :jruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
- #{ruby_version_correct_engineless}
- G
+ #{ruby_version_correct_engineless}
+ G
- expect(bundled_app("Gemfile.lock")).to exist
- end
+ expect(bundled_app_lock).to exist
end
it "installs fine when the patchlevel matches" do
@@ -322,56 +324,54 @@ G
#{ruby_version_correct_patchlevel}
G
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
it "doesn't install when the ruby version doesn't match" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "rack"
#{ruby_version_incorrect}
G
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
should_be_ruby_version_incorrect
end
it "doesn't install when engine doesn't match" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "rack"
#{engine_incorrect}
G
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
should_be_engine_incorrect
end
- it "doesn't install when engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ it "doesn't install when engine version doesn't match", :jruby do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
- #{engine_version_incorrect}
- G
+ #{engine_version_incorrect}
+ G
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_engine_version_incorrect
- end
+ expect(bundled_app_lock).not_to exist
+ should_be_engine_version_incorrect
end
it "doesn't install when patchlevel doesn't match" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "rack"
#{patchlevel_incorrect}
G
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
should_be_patchlevel_incorrect
end
end
@@ -391,28 +391,24 @@ G
G
bundle :check
- expect(exitstatus).to eq(0) if exitstatus
- expect(out).to eq("Resolving dependencies...\nThe Gemfile's dependencies are satisfied")
+ expect(out).to match(/\AResolving dependencies\.\.\.\.*\nThe Gemfile's dependencies are satisfied\z/)
end
- it "checks fine with any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
+ it "checks fine with any engine", :jruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
- #{ruby_version_correct_engineless}
- G
+ #{ruby_version_correct_engineless}
+ G
- bundle :check
- expect(exitstatus).to eq(0) if exitstatus
- expect(out).to eq("Resolving dependencies...\nThe Gemfile's dependencies are satisfied")
- end
+ bundle :check
+ expect(out).to match(/\AResolving dependencies\.\.\.\.*\nThe Gemfile's dependencies are satisfied\z/)
end
it "fails when ruby version doesn't match" do
@@ -428,7 +424,7 @@ G
#{ruby_version_incorrect}
G
- bundle :check
+ bundle :check, :raise_on_error => false
should_be_ruby_version_incorrect
end
@@ -445,27 +441,25 @@ G
#{engine_incorrect}
G
- bundle :check
+ bundle :check, :raise_on_error => false
should_be_engine_incorrect
end
- it "fails when engine version doesn't match" do
- simulate_ruby_engine "ruby" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
+ it "fails when engine version doesn't match", :jruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ G
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
- #{engine_version_incorrect}
- G
+ #{engine_version_incorrect}
+ G
- bundle :check
- should_be_engine_version_incorrect
- end
+ bundle :check, :raise_on_error => false
+ should_be_engine_version_incorrect
end
it "fails when patchlevel doesn't match" do
@@ -481,7 +475,7 @@ G
#{patchlevel_incorrect}
G
- bundle :check
+ bundle :check, :raise_on_error => false
should_be_patchlevel_incorrect
end
end
@@ -506,6 +500,10 @@ G
#{ruby_version_correct}
G
update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
+ end
+
build_gem "activesupport", "3.0"
end
@@ -513,22 +511,24 @@ G
expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
end
- it "updates fine with any engine" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport"
- gem "rack-obama"
+ it "updates fine with any engine", :jruby do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
- #{ruby_version_correct_engineless}
- G
- update_repo2 do
- build_gem "activesupport", "3.0"
+ #{ruby_version_correct_engineless}
+ G
+ update_repo2 do
+ build_gem "rack", "1.2" do |s|
+ s.executables = "rackup"
end
- bundle "update", :all => true
- expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
+ build_gem "activesupport", "3.0"
end
+
+ bundle "update", :all => true
+ expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
end
it "fails when ruby version doesn't match" do
@@ -543,11 +543,11 @@ G
build_gem "activesupport", "3.0"
end
- bundle :update, :all => true
+ bundle :update, :all => true, :raise_on_error => false
should_be_ruby_version_incorrect
end
- it "fails when ruby engine doesn't match" do
+ it "fails when ruby engine doesn't match", :jruby do
gemfile <<-G
source "#{file_uri_for(gem_repo2)}"
gem "activesupport"
@@ -559,26 +559,24 @@ G
build_gem "activesupport", "3.0"
end
- bundle :update, :all => true
+ bundle :update, :all => true, :raise_on_error => false
should_be_engine_incorrect
end
- it "fails when ruby engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport"
- gem "rack-obama"
-
- #{engine_version_incorrect}
- G
- update_repo2 do
- build_gem "activesupport", "3.0"
- end
+ it "fails when ruby engine version doesn't match", :jruby do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport"
+ gem "rack-obama"
- bundle :update, :all => true
- should_be_engine_version_incorrect
+ #{engine_version_incorrect}
+ G
+ update_repo2 do
+ build_gem "activesupport", "3.0"
end
+
+ bundle :update, :all => true, :raise_on_error => false
+ should_be_engine_version_incorrect
end
it "fails when patchlevel doesn't match" do
@@ -592,7 +590,7 @@ G
build_gem "activesupport", "3.0"
end
- bundle :update, :all => true
+ bundle :update, :all => true, :raise_on_error => false
should_be_patchlevel_incorrect
end
end
@@ -606,7 +604,7 @@ G
end
it "prints path if ruby version is correct" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
@@ -617,18 +615,16 @@ G
expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
end
- it "prints path if ruby version is correct for any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rails"
+ it "prints path if ruby version is correct for any engine", :jruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rails"
- #{ruby_version_correct_engineless}
- G
+ #{ruby_version_correct_engineless}
+ G
- bundle "info rails --path"
- expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
- end
+ bundle "info rails --path"
+ expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
end
it "fails if ruby version doesn't match", :bundler => "< 3" do
@@ -639,7 +635,7 @@ G
#{ruby_version_incorrect}
G
- bundle "show rails"
+ bundle "show rails", :raise_on_error => false
should_be_ruby_version_incorrect
end
@@ -651,22 +647,20 @@ G
#{engine_incorrect}
G
- bundle "show rails"
+ bundle "show rails", :raise_on_error => false
should_be_engine_incorrect
end
- it "fails if engine version doesn't match", :bundler => "< 3" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rails"
+ it "fails if engine version doesn't match", :bundler => "< 3", :jruby => true do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rails"
- #{engine_version_incorrect}
- G
+ #{engine_version_incorrect}
+ G
- bundle "show rails"
- should_be_engine_version_incorrect
- end
+ bundle "show rails", :raise_on_error => false
+ should_be_engine_version_incorrect
end
it "fails when patchlevel doesn't match", :bundler => "< 3" do
@@ -680,7 +674,7 @@ G
build_gem "activesupport", "3.0"
end
- bundle "show rails"
+ bundle "show rails", :raise_on_error => false
should_be_patchlevel_incorrect
end
end
@@ -695,6 +689,7 @@ G
it "copies the .gem file to vendor/cache when ruby version matches" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack'
#{ruby_version_correct}
@@ -704,53 +699,52 @@ G
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
end
- it "copies the .gem file to vendor/cache when ruby version matches for any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ it "copies the .gem file to vendor/cache when ruby version matches for any engine", :jruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'rack'
- #{ruby_version_correct_engineless}
- G
+ #{ruby_version_correct_engineless}
+ G
- bundle! :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- end
+ bundle :cache
+ expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
end
it "fails if the ruby version doesn't match" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack'
#{ruby_version_incorrect}
G
- bundle :cache
+ bundle :cache, :raise_on_error => false
should_be_ruby_version_incorrect
end
it "fails if the engine doesn't match" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack'
#{engine_incorrect}
G
- bundle :cache
+ bundle :cache, :raise_on_error => false
should_be_engine_incorrect
end
- it "fails if the engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- gem 'rack'
+ it "fails if the engine version doesn't match", :jruby do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'rack'
- #{engine_version_incorrect}
- G
+ #{engine_version_incorrect}
+ G
- bundle :cache
- should_be_engine_version_incorrect
- end
+ bundle :cache, :raise_on_error => false
+ should_be_engine_version_incorrect
end
it "fails when patchlevel doesn't match" do
@@ -761,14 +755,14 @@ G
#{patchlevel_incorrect}
G
- bundle :cache
+ bundle :cache, :raise_on_error => false
should_be_patchlevel_incorrect
end
end
context "bundle pack" do
before do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem 'rack'
G
@@ -776,6 +770,7 @@ G
it "copies the .gem file to vendor/cache when ruby version matches" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack'
#{ruby_version_correct}
@@ -785,53 +780,52 @@ G
expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
end
- it "copies the .gem file to vendor/cache when ruby version matches any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ it "copies the .gem file to vendor/cache when ruby version matches any engine", :jruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'rack'
- #{ruby_version_correct_engineless}
- G
+ #{ruby_version_correct_engineless}
+ G
- bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- end
+ bundle :cache
+ expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
end
it "fails if the ruby version doesn't match" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack'
#{ruby_version_incorrect}
G
- bundle :cache
+ bundle :cache, :raise_on_error => false
should_be_ruby_version_incorrect
end
it "fails if the engine doesn't match" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'rack'
#{engine_incorrect}
G
- bundle :cache
+ bundle :cache, :raise_on_error => false
should_be_engine_incorrect
end
- it "fails if the engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- gem 'rack'
+ it "fails if the engine version doesn't match", :jruby do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem 'rack'
- #{engine_version_incorrect}
- G
+ #{engine_version_incorrect}
+ G
- bundle :cache
- should_be_engine_version_incorrect
- end
+ bundle :cache, :raise_on_error => false
+ should_be_engine_version_incorrect
end
it "fails when patchlevel doesn't match" do
@@ -842,7 +836,7 @@ G
#{patchlevel_incorrect}
G
- bundle :cache
+ bundle :cache, :raise_on_error => false
should_be_patchlevel_incorrect
end
end
@@ -850,11 +844,12 @@ G
context "bundle exec" do
before do
ENV["BUNDLER_FORCE_TTY"] = "true"
- system_gems "rack-1.0.0", "rack-0.9.1", :path => :bundle_path
+ system_gems "rack-1.0.0", "rack-0.9.1", :path => default_bundle_path
end
it "activates the correct gem when ruby version matches" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
#{ruby_version_correct}
@@ -864,53 +859,52 @@ G
expect(out).to include("0.9.1")
end
- it "activates the correct gem when ruby version matches any engine" do
- simulate_ruby_engine "jruby" do
- system_gems "rack-1.0.0", "rack-0.9.1", :path => :bundle_path
- gemfile <<-G
- gem "rack", "0.9.1"
+ it "activates the correct gem when ruby version matches any engine", :jruby do
+ system_gems "rack-1.0.0", "rack-0.9.1", :path => default_bundle_path
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack", "0.9.1"
- #{ruby_version_correct_engineless}
- G
+ #{ruby_version_correct_engineless}
+ G
- bundle "exec rackup"
- expect(out).to include("0.9.1")
- end
+ bundle "exec rackup"
+ expect(out).to include("0.9.1")
end
it "fails when the ruby version doesn't match" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
#{ruby_version_incorrect}
G
- bundle "exec rackup"
+ bundle "exec rackup", :raise_on_error => false
should_be_ruby_version_incorrect
end
it "fails when the engine doesn't match" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack", "0.9.1"
#{engine_incorrect}
G
- bundle "exec rackup"
+ bundle "exec rackup", :raise_on_error => false
should_be_engine_incorrect
end
- # it "fails when the engine version doesn't match" do
- # simulate_ruby_engine "jruby" do
- # gemfile <<-G
- # gem "rack", "0.9.1"
+ # it "fails when the engine version doesn't match", :jruby do
+ # gemfile <<-G
+ # gem "rack", "0.9.1"
#
- # #{engine_version_incorrect}
- # G
+ # #{engine_version_incorrect}
+ # G
#
- # bundle "exec rackup"
- # should_be_engine_version_incorrect
- # end
+ # bundle "exec rackup"
+ # should_be_engine_version_incorrect
# end
it "fails when patchlevel doesn't match" do
@@ -921,7 +915,7 @@ G
#{patchlevel_incorrect}
G
- bundle "exec rackup"
+ bundle "exec rackup", :raise_on_error => false
should_be_patchlevel_incorrect
end
end
@@ -936,7 +930,7 @@ G
G
end
- it "starts IRB with the default group loaded when ruby version matches" do
+ it "starts IRB with the default group loaded when ruby version matches", :readline do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -953,24 +947,21 @@ G
expect(out).to include("0.9.1")
end
- it "starts IRB with the default group loaded when ruby version matches any engine" do
- skip "irb depend on JRuby.compile_ir and don't work in simulated environment." unless RUBY_ENGINE == "jruby"
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
+ it "starts IRB with the default group loaded when ruby version matches", :readline, :jruby do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ gem "activesupport", :group => :test
+ gem "rack_middleware", :group => :development
- #{ruby_version_correct_engineless}
- G
+ #{ruby_version_correct_engineless}
+ G
- bundle "console" do |input, _, _|
- input.puts("puts RACK")
- input.puts("exit")
- end
- expect(out).to include("0.9.1")
+ bundle "console" do |input, _, _|
+ input.puts("puts RACK")
+ input.puts("exit")
end
+ expect(out).to include("0.9.1")
end
it "fails when ruby version doesn't match" do
@@ -983,7 +974,7 @@ G
#{ruby_version_incorrect}
G
- bundle "console"
+ bundle "console", :raise_on_error => false
should_be_ruby_version_incorrect
end
@@ -997,24 +988,22 @@ G
#{engine_incorrect}
G
- bundle "console"
+ bundle "console", :raise_on_error => false
should_be_engine_incorrect
end
- it "fails when engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
+ it "fails when engine version doesn't match", :jruby do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ gem "activesupport", :group => :test
+ gem "rack_middleware", :group => :development
- #{engine_version_incorrect}
- G
+ #{engine_version_incorrect}
+ G
- bundle "console"
- should_be_engine_version_incorrect
- end
+ bundle "console", :raise_on_error => false
+ should_be_engine_version_incorrect
end
it "fails when patchlevel doesn't match" do
@@ -1027,7 +1016,7 @@ G
#{patchlevel_incorrect}
G
- bundle "console"
+ bundle "console", :raise_on_error => false
should_be_patchlevel_incorrect
end
end
@@ -1052,31 +1041,29 @@ G
#{ruby_version_correct}
G
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
run "1"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
- it "makes a Gemfile.lock if setup succeeds for any engine" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "yard"
- gem "rack"
+ it "makes a Gemfile.lock if setup succeeds for any engine", :jruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "yard"
+ gem "rack"
- #{ruby_version_correct_engineless}
- G
+ #{ruby_version_correct_engineless}
+ G
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
- run "1"
- expect(bundled_app("Gemfile.lock")).to exist
- end
+ run "1"
+ expect(bundled_app_lock).to exist
end
it "fails when ruby version doesn't match" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "yard"
gem "rack"
@@ -1084,18 +1071,16 @@ G
#{ruby_version_incorrect}
G
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
- ruby <<-R
- require 'bundler/setup'
- R
+ ruby "require 'bundler/setup'", :env => { "BUNDLER_VERSION" => Bundler::VERSION }, :raise_on_error => false
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
should_be_ruby_version_incorrect
end
it "fails when engine doesn't match" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "yard"
gem "rack"
@@ -1103,39 +1088,33 @@ G
#{engine_incorrect}
G
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
- ruby <<-R
- require 'bundler/setup'
- R
+ ruby "require 'bundler/setup'", :env => { "BUNDLER_VERSION" => Bundler::VERSION }, :raise_on_error => false
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
should_be_engine_incorrect
end
- it "fails when engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "yard"
- gem "rack"
+ it "fails when engine version doesn't match", :jruby do
+ install_gemfile <<-G, :raise_on_error => false
+ source "#{file_uri_for(gem_repo1)}"
+ gem "yard"
+ gem "rack"
- #{engine_version_incorrect}
- G
+ #{engine_version_incorrect}
+ G
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
- ruby <<-R
- require 'bundler/setup'
- R
+ ruby "require 'bundler/setup'", :env => { "BUNDLER_VERSION" => Bundler::VERSION }, :raise_on_error => false
- expect(bundled_app("Gemfile.lock")).not_to exist
- should_be_engine_version_incorrect
- end
+ expect(bundled_app_lock).not_to exist
+ should_be_engine_version_incorrect
end
it "fails when patchlevel doesn't match" do
- install_gemfile <<-G
+ install_gemfile <<-G, :raise_on_error => false
source "#{file_uri_for(gem_repo1)}"
gem "yard"
gem "rack"
@@ -1143,13 +1122,11 @@ G
#{patchlevel_incorrect}
G
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
- ruby <<-R
- require 'bundler/setup'
- R
+ ruby "require 'bundler/setup'", :env => { "BUNDLER_VERSION" => Bundler::VERSION }, :raise_on_error => false
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
should_be_patchlevel_incorrect
end
end
@@ -1181,31 +1158,41 @@ G
#{ruby_version_correct}
G
- bundle "outdated"
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5")
- expect(out).to include("foo (newest 1.0")
+ bundle "outdated", :raise_on_error => false
+
+ expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip
+ Gem Current Latest Requested Groups
+ activesupport 2.3.5 3.0 = 2.3.5 default
+ foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ TABLE
+
+ expect(out).to match(Regexp.new(expected_output))
end
- it "returns list of outdated gems when the ruby version matches for any engine" do
- simulate_ruby_engine "jruby" do
- bundle! :install
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
+ it "returns list of outdated gems when the ruby version matches for any engine", :jruby do
+ bundle :install
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", :path => lib_path("foo")
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
+
+ #{ruby_version_correct_engineless}
+ G
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
+ bundle "outdated", :raise_on_error => false
- #{ruby_version_correct_engineless}
- G
+ expected_output = <<~TABLE.gsub("x", "\\\h").tr(".", "\.").strip
+ Gem Current Latest Requested Groups
+ activesupport 2.3.5 3.0 = 2.3.5 default
+ foo 1.0 xxxxxxx 1.0 xxxxxxx >= 0 default
+ TABLE
- bundle "outdated"
- expect(out).to include("activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)")
- expect(out).to include("foo (newest 1.0")
- end
+ expect(out).to match(Regexp.new(expected_output))
end
it "fails when the ruby version doesn't match" do
@@ -1222,7 +1209,7 @@ G
#{ruby_version_incorrect}
G
- bundle "outdated"
+ bundle "outdated", :raise_on_error => false
should_be_ruby_version_incorrect
end
@@ -1240,68 +1227,62 @@ G
#{engine_incorrect}
G
- bundle "outdated"
+ bundle "outdated", :raise_on_error => false
should_be_engine_incorrect
end
- it "fails when the engine version doesn't match" do
- simulate_ruby_engine "jruby" do
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
+ it "fails when the engine version doesn't match", :jruby do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", :path => lib_path("foo")
+ end
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
- #{engine_version_incorrect}
- G
+ #{engine_version_incorrect}
+ G
- bundle "outdated"
- should_be_engine_version_incorrect
- end
+ bundle "outdated", :raise_on_error => false
+ should_be_engine_version_incorrect
end
- it "fails when the patchlevel doesn't match" do
- simulate_ruby_engine "jruby" do
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
+ it "fails when the patchlevel doesn't match", :jruby do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", :path => lib_path("foo")
+ end
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
- #{patchlevel_incorrect}
- G
+ #{patchlevel_incorrect}
+ G
- bundle "outdated"
- should_be_patchlevel_incorrect
- end
+ bundle "outdated", :raise_on_error => false
+ should_be_patchlevel_incorrect
end
- it "fails when the patchlevel is a fixnum" do
- simulate_ruby_engine "jruby" do
- update_repo2 do
- build_gem "activesupport", "3.0"
- update_git "foo", :path => lib_path("foo")
- end
+ it "fails when the patchlevel is a fixnum", :jruby do
+ update_repo2 do
+ build_gem "activesupport", "3.0"
+ update_git "foo", :path => lib_path("foo")
+ end
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "activesupport", "2.3.5"
- gem "foo", :git => "#{lib_path("foo")}"
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "activesupport", "2.3.5"
+ gem "foo", :git => "#{lib_path("foo")}"
- #{patchlevel_fixnum}
- G
+ #{patchlevel_fixnum}
+ G
- bundle "outdated"
- should_be_patchlevel_fixnum
- end
+ bundle "outdated", :raise_on_error => false
+ should_be_patchlevel_fixnum
end
end
end
diff --git a/spec/bundler/plugins/command_spec.rb b/spec/bundler/plugins/command_spec.rb
index 4728f66f5f..3a7adf4b48 100644
--- a/spec/bundler/plugins/command_spec.rb
+++ b/spec/bundler/plugins/command_spec.rb
@@ -69,12 +69,10 @@ RSpec.describe "command plugins" do
end
end
- bundle "plugin install copycat --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install copycat --source #{file_uri_for(gem_repo2)}", :raise_on_error => false
expect(out).not_to include("Installed plugin copycat")
- expect(err).to include("Failed to install plugin")
-
- expect(err).to include("Command(s) `mahcommand` declared by copycat are already registered.")
+ expect(err).to include("Failed to install plugin `copycat`, due to Bundler::Plugin::Index::CommandConflict (Command(s) `mahcommand` declared by copycat are already registered.)")
end
end
diff --git a/spec/bundler/plugins/install_spec.rb b/spec/bundler/plugins/install_spec.rb
index 669ed09fb5..009516260a 100644
--- a/spec/bundler/plugins/install_spec.rb
+++ b/spec/bundler/plugins/install_spec.rb
@@ -9,7 +9,7 @@ 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)}"
+ bundle "plugin install no-foo --source #{file_uri_for(gem_repo1)}", :raise_on_error => false
expect(err).to include("Could not find")
plugin_should_not_be_installed("no-foo")
@@ -22,6 +22,19 @@ RSpec.describe "bundler plugin install" do
plugin_should_be_installed("foo")
end
+ it "installs from sources configured as Gem.sources without any flags" do
+ bundle "plugin install foo", :env => { "BUNDLER_SPEC_GEM_SOURCES" => file_uri_for(gem_repo2).to_s }
+
+ expect(out).to include("Installed plugin foo")
+ plugin_should_be_installed("foo")
+ end
+
+ it "shows help when --help flag is given" do
+ bundle "plugin install --help"
+
+ expect(out).to include("bundle plugin install PLUGINS # Install the plugin from the source")
+ end
+
context "plugin is already installed" do
before do
bundle "plugin install foo --source #{file_uri_for(gem_repo2)}"
@@ -56,6 +69,21 @@ RSpec.describe "bundler plugin install" do
plugin_should_be_installed("foo", "kung-foo")
end
+ it "installs the latest version if not installed" do
+ update_repo2 do
+ build_plugin "foo", "1.1"
+ end
+
+ bundle "plugin install foo --version 1.0 --source #{file_uri_for(gem_repo2)} --verbose"
+ expect(out).to include("Installing foo 1.0")
+
+ bundle "plugin install foo --source #{file_uri_for(gem_repo2)} --verbose"
+ expect(out).to include("Installing foo 1.1")
+
+ bundle "plugin install foo --source #{file_uri_for(gem_repo2)} --verbose"
+ expect(out).to include("Using foo 1.1")
+ end
+
it "works with different load paths" do
build_repo2 do
build_plugin "testing" do |s|
@@ -96,9 +124,9 @@ RSpec.describe "bundler plugin install" do
build_gem "charlie"
end
- bundle "plugin install charlie --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install charlie --source #{file_uri_for(gem_repo2)}", :raise_on_error => false
- expect(err).to include("plugins.rb was not found")
+ expect(err).to include("Failed to install plugin `charlie`, due to Bundler::Plugin::MalformattedPlugin (plugins.rb was not found in the plugin.)")
expect(global_plugin_gem("charlie-1.0")).not_to be_directory
@@ -115,7 +143,7 @@ RSpec.describe "bundler plugin install" do
end
end
- bundle "plugin install chaplin --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install chaplin --source #{file_uri_for(gem_repo2)}", :raise_on_error => false
expect(global_plugin_gem("chaplin-1.0")).not_to be_directory
@@ -147,14 +175,18 @@ RSpec.describe "bundler plugin install" do
end
it "raises an error when both git and local git sources are specified" do
- bundle "plugin install foo --local_git /phony/path/project --git git@gitphony.com:/repo/project"
+ bundle "plugin install foo --local_git /phony/path/project --git git@gitphony.com:/repo/project", :raise_on_error => false
- expect(exitstatus).not_to eq(0) if exitstatus
+ expect(exitstatus).not_to eq(0)
expect(err).to eq("Remote and local plugin git sources can't be both specified")
end
end
context "Gemfile eval" do
+ before do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ end
+
it "installs plugins listed in gemfile" do
gemfile <<-G
source '#{file_uri_for(gem_repo2)}'
@@ -197,6 +229,7 @@ RSpec.describe "bundler plugin install" do
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
plugin 'ga-plugin', :git => "#{lib_path("ga-plugin-1.0")}"
G
@@ -204,14 +237,29 @@ RSpec.describe "bundler plugin install" do
plugin_should_be_installed("ga-plugin")
end
+ it "accepts path sources" do
+ build_lib "ga-plugin" do |s|
+ s.write "plugins.rb"
+ end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ plugin 'ga-plugin', :path => "#{lib_path("ga-plugin-1.0")}"
+ G
+
+ expect(out).to include("Installed plugin ga-plugin")
+ plugin_should_be_installed("ga-plugin")
+ end
+
context "in deployment mode" do
it "installs plugins" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source '#{file_uri_for(gem_repo2)}'
gem 'rack', "1.0.0"
G
- install_gemfile! <<-G, forgotten_command_line_options(:deployment => true)
+ bundle "config set --local deployment true"
+ install_gemfile <<-G
source '#{file_uri_for(gem_repo2)}'
plugin 'foo'
gem 'rack', "1.0.0"
@@ -238,13 +286,14 @@ RSpec.describe "bundler plugin install" do
end
RUBY
- ruby code
+ ruby code, :env => { "BUNDLER_VERSION" => Bundler::VERSION }
expect(local_plugin_gem("foo-1.0", "plugins.rb")).to exist
end
end
describe "local plugin" do
it "is installed when inside an app" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
gemfile ""
bundle "plugin install foo --source #{file_uri_for(gem_repo2)}"
@@ -287,21 +336,16 @@ RSpec.describe "bundler plugin install" do
end
# outside the app
- Dir.chdir tmp
- bundle "plugin install fubar --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install fubar --source #{file_uri_for(gem_repo2)}", :dir => tmp
end
it "inside the app takes precedence over global plugin" do
- Dir.chdir bundled_app
-
bundle "shout"
expect(out).to eq("local_one")
end
it "outside the app global plugin is used" do
- Dir.chdir tmp
-
- bundle "shout"
+ bundle "shout", :dir => tmp
expect(out).to eq("global_one")
end
end
diff --git a/spec/bundler/plugins/source/example_spec.rb b/spec/bundler/plugins/source/example_spec.rb
index f2151a5a73..7d098997ec 100644
--- a/spec/bundler/plugins/source/example_spec.rb
+++ b/spec/bundler/plugins/source/example_spec.rb
@@ -33,6 +33,7 @@ RSpec.describe "real source plugins" do
def install(spec, opts)
mkdir_p(install_path.parent)
+ require 'fileutils'
FileUtils.cp_r(path, install_path)
spec_path = install_path.join("\#{spec.full_name}.gemspec")
@@ -66,35 +67,10 @@ RSpec.describe "real source plugins" do
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
- it "writes to lock file", :bundler => "< 3" do
+ it "writes to lock file" do
bundle "install"
- lockfile_should_be <<-G
- PLUGIN SOURCE
- remote: #{lib_path("a-path-gem-1.0")}
- type: mpath
- specs:
- a-path-gem (1.0)
-
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- a-path-gem!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "writes to lock file", :bundler => "3" do
- bundle "install"
-
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PLUGIN SOURCE
remote: #{lib_path("a-path-gem-1.0")}
type: mpath
@@ -155,10 +131,11 @@ RSpec.describe "real source plugins" do
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
- it "copies repository to vendor cache and uses it even when installed with bundle --path" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ it "copies repository to vendor cache and uses it even when installed with `path` configured" do
+ bundle "config set --local path vendor/bundle"
+ bundle :install
bundle "config set cache_all true"
- bundle! :cache
+ bundle :cache
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
@@ -167,9 +144,10 @@ RSpec.describe "real source plugins" do
end
it "bundler package copies repository to vendor cache" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle :install
bundle "config set cache_all true"
- bundle! :cache
+ bundle :cache
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
@@ -203,7 +181,7 @@ RSpec.describe "real source plugins" do
end
it "installs" do
- bundle! "install"
+ bundle "install"
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
@@ -215,6 +193,8 @@ RSpec.describe "real source plugins" do
build_repo2 do
build_plugin "bundler-source-gitp" do |s|
s.write "plugins.rb", <<-RUBY
+ require "open3"
+
class SPlugin < Bundler::Plugin::API
source "gitp"
@@ -254,9 +234,7 @@ RSpec.describe "real source plugins" do
mkdir_p(install_path.dirname)
rm_rf(install_path)
`git clone --no-checkout --quiet "\#{cache_path}" "\#{install_path}"`
- Dir.chdir install_path do
- `git reset --hard \#{revision}`
- end
+ Open3.capture2e("git reset --hard \#{revision}", :chdir => install_path)
spec_path = install_path.join("\#{spec.full_name}.gemspec")
spec_path.open("wb") {|f| f.write spec.to_ruby }
@@ -310,9 +288,8 @@ RSpec.describe "real source plugins" do
cache_repo
end
- Dir.chdir cache_path do
- `git rev-parse --verify \#{@ref}`.strip
- end
+ output, _status = Open3.capture2e("git rev-parse --verify \#{@ref}", :chdir => cache_path)
+ output.strip
end
def base_name
@@ -361,38 +338,11 @@ RSpec.describe "real source plugins" do
expect(the_bundle).to include_gems("ma-gitp-gem 1.0")
end
- it "writes to lock file", :bundler => "< 3" do
- revision = revision_for(lib_path("ma-gitp-gem-1.0"))
- bundle "install"
-
- lockfile_should_be <<-G
- PLUGIN SOURCE
- remote: #{file_uri_for(lib_path("ma-gitp-gem-1.0"))}
- type: gitp
- revision: #{revision}
- specs:
- ma-gitp-gem (1.0)
-
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- ma-gitp-gem!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "writes to lock file", :bundler => "3" do
+ it "writes to lock file" do
revision = revision_for(lib_path("ma-gitp-gem-1.0"))
bundle "install"
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
PLUGIN SOURCE
remote: #{file_uri_for(lib_path("ma-gitp-gem-1.0"))}
type: gitp
diff --git a/spec/bundler/plugins/source_spec.rb b/spec/bundler/plugins/source_spec.rb
index c8deee96b1..14643e5c81 100644
--- a/spec/bundler/plugins/source_spec.rb
+++ b/spec/bundler/plugins/source_spec.rb
@@ -21,6 +21,7 @@ RSpec.describe "bundler source plugin" do
end
G
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
plugin_should_be_installed("bundler-source-psource")
end
@@ -75,6 +76,7 @@ RSpec.describe "bundler source plugin" do
end
it "installs the explicit one" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
plugin_should_be_installed("another-psource")
end
@@ -100,6 +102,7 @@ RSpec.describe "bundler source plugin" do
end
it "installs the default one" do
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
plugin_should_be_installed("bundler-source-psource")
end
end
diff --git a/spec/bundler/plugins/uninstall_spec.rb b/spec/bundler/plugins/uninstall_spec.rb
new file mode 100644
index 0000000000..8180241911
--- /dev/null
+++ b/spec/bundler/plugins/uninstall_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundler plugin uninstall" do
+ before do
+ build_repo2 do
+ build_plugin "foo"
+ build_plugin "kung-foo"
+ end
+ end
+
+ it "shows proper error message when plugins are not specified" do
+ bundle "plugin uninstall"
+ expect(err).to include("No plugins to uninstall")
+ end
+
+ it "uninstalls specified plugins" do
+ bundle "plugin install foo kung-foo --source #{file_uri_for(gem_repo2)}"
+ plugin_should_be_installed("foo")
+ plugin_should_be_installed("kung-foo")
+
+ bundle "plugin uninstall foo"
+ expect(out).to include("Uninstalled plugin foo")
+ plugin_should_not_be_installed("foo")
+ plugin_should_be_installed("kung-foo")
+ end
+
+ it "shows proper message when plugin is not installed" do
+ bundle "plugin uninstall foo"
+ expect(err).to include("Plugin foo is not installed")
+ plugin_should_not_be_installed("foo")
+ end
+
+ describe "with --all" do
+ it "uninstalls all installed plugins" do
+ bundle "plugin install foo kung-foo --source #{file_uri_for(gem_repo2)}"
+ plugin_should_be_installed("foo")
+ plugin_should_be_installed("kung-foo")
+
+ bundle "plugin uninstall --all"
+ plugin_should_not_be_installed("foo")
+ plugin_should_not_be_installed("kung-foo")
+ end
+
+ it "shows proper no plugins installed message when no plugins installed" do
+ bundle "plugin uninstall --all"
+ expect(out).to include("No plugins installed")
+ end
+ end
+end
diff --git a/spec/bundler/quality_es_spec.rb b/spec/bundler/quality_es_spec.rb
index 4238ac7452..90968e6270 100644
--- a/spec/bundler/quality_es_spec.rb
+++ b/spec/bundler/quality_es_spec.rb
@@ -40,12 +40,10 @@ RSpec.describe "La biblioteca si misma" do
it "mantiene la calidad de lenguaje de la documentación" do
included = /ronn/
error_messages = []
- Dir.chdir(root) do
- `git ls-files -z -- man`.split("\x0").each do |filename|
- next unless filename =~ included
- error_messages << check_for_expendable_words(filename)
- error_messages << check_for_specific_pronouns(filename)
- end
+ man_tracked_files.each do |filename|
+ next unless filename =~ included
+ error_messages << check_for_expendable_words(filename)
+ error_messages << check_for_specific_pronouns(filename)
end
expect(error_messages.compact).to be_well_formed
end
@@ -53,12 +51,10 @@ RSpec.describe "La biblioteca si misma" do
it "mantiene la calidad de lenguaje de oraciones usadas en el código fuente" do
error_messages = []
exempt = /vendor/
- Dir.chdir(root) do
- lib_tracked_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_expendable_words(filename)
- error_messages << check_for_specific_pronouns(filename)
- end
+ lib_tracked_files.each do |filename|
+ next if filename =~ exempt
+ error_messages << check_for_expendable_words(filename)
+ error_messages << check_for_specific_pronouns(filename)
end
expect(error_messages.compact).to be_well_formed
end
diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb
index 09e59d88ae..62f3722a39 100644
--- a/spec/bundler/quality_spec.rb
+++ b/spec/bundler/quality_spec.rb
@@ -3,25 +3,6 @@
require "set"
RSpec.describe "The library itself" do
- def check_for_debugging_mechanisms(filename)
- debugging_mechanisms_regex = /
- (binding\.pry)|
- (debugger)|
- (sleep\s*\(?\d+)|
- (fit\s*\(?("|\w))
- /x
-
- failing_lines = []
- each_line(filename) do |line, number|
- if line =~ debugging_mechanisms_regex && !line.end_with?("# ignore quality_spec\n")
- failing_lines << number + 1
- end
- end
-
- return if failing_lines.empty?
- "#{filename} has debugging mechanisms (like binding.pry, sleep, debugger, rspec focusing, etc.) on lines #{failing_lines.join(", ")}"
- end
-
def check_for_git_merge_conflicts(filename)
merge_conflicts_regex = /
<<<<<<<|
@@ -105,14 +86,12 @@ RSpec.describe "The library itself" do
end
it "has no malformed whitespace" do
- exempt = /\.gitmodules|fixtures|vendor|LICENSE|vcr_cassettes|rbreadline\.diff|\.txt$/
+ exempt = /\.gitmodules|fixtures|vendor|LICENSE|vcr_cassettes|rbreadline\.diff|index\.txt$/
error_messages = []
- Dir.chdir(root) do
- tracked_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_tab_characters(filename)
- error_messages << check_for_extra_spaces(filename)
- end
+ tracked_files.each do |filename|
+ next if filename =~ exempt
+ error_messages << check_for_tab_characters(filename)
+ error_messages << check_for_extra_spaces(filename)
end
expect(error_messages.compact).to be_well_formed
end
@@ -120,23 +99,9 @@ RSpec.describe "The library itself" do
it "has no estraneous quotes" do
exempt = /vendor|vcr_cassettes|LICENSE|rbreadline\.diff/
error_messages = []
- Dir.chdir(root) do
- tracked_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_straneous_quotes(filename)
- end
- end
- expect(error_messages.compact).to be_well_formed
- end
-
- it "does not include any leftover debugging or development mechanisms" do
- exempt = %r{quality_spec.rb|support/helpers|vcr_cassettes|\.md|\.ronn|\.txt|\.5|\.1}
- error_messages = []
- Dir.chdir(root) do
- tracked_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_debugging_mechanisms(filename)
- end
+ tracked_files.each do |filename|
+ next if filename =~ exempt
+ error_messages << check_for_straneous_quotes(filename)
end
expect(error_messages.compact).to be_well_formed
end
@@ -144,11 +109,9 @@ RSpec.describe "The library itself" do
it "does not include any unresolved merge conflicts" do
error_messages = []
exempt = %r{lock/lockfile_spec|quality_spec|vcr_cassettes|\.ronn|lockfile_parser\.rb}
- Dir.chdir(root) do
- tracked_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_git_merge_conflicts(filename)
- end
+ tracked_files.each do |filename|
+ next if filename =~ exempt
+ error_messages << check_for_git_merge_conflicts(filename)
end
expect(error_messages.compact).to be_well_formed
end
@@ -156,37 +119,38 @@ RSpec.describe "The library itself" do
it "maintains language quality of the documentation" do
included = /ronn/
error_messages = []
- Dir.chdir(root) do
- `git ls-files -z -- man`.split("\x0").each do |filename|
- next unless filename =~ included
- error_messages << check_for_expendable_words(filename)
- error_messages << check_for_specific_pronouns(filename)
- end
+ man_tracked_files.each do |filename|
+ next unless filename =~ included
+ error_messages << check_for_expendable_words(filename)
+ error_messages << check_for_specific_pronouns(filename)
end
expect(error_messages.compact).to be_well_formed
end
it "maintains language quality of sentences used in source code" do
error_messages = []
- exempt = /vendor|vcr_cassettes/
- Dir.chdir(root) do
- lib_tracked_files.split("\x0").each do |filename|
- next if filename =~ exempt
- error_messages << check_for_expendable_words(filename)
- error_messages << check_for_specific_pronouns(filename)
- end
+ exempt = /vendor|vcr_cassettes|CODE_OF_CONDUCT/
+ lib_tracked_files.each do |filename|
+ next if filename =~ exempt
+ error_messages << check_for_expendable_words(filename)
+ error_messages << check_for_specific_pronouns(filename)
end
expect(error_messages.compact).to be_well_formed
end
it "documents all used settings" do
exemptions = %w[
- auto_config_jobs
- deployment_means_frozen
forget_cli_options
+ gem.changelog
+ gem.ci
gem.coc
+ gem.linter
gem.mit
+ gem.rubocop
+ gem.test
+ git.allow_insecure
inline
+ trust-policy
use_gem_version_promoter_for_major_updates
]
@@ -196,16 +160,15 @@ RSpec.describe "The library itself" do
Bundler::Settings::BOOL_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::BOOL_KEYS" }
Bundler::Settings::NUMBER_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::NUMBER_KEYS" }
Bundler::Settings::ARRAY_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::ARRAY_KEYS" }
+ Bundler::Settings::STRING_KEYS.each {|k| all_settings[k] << "in Bundler::Settings::STRING_KEYS" }
- Dir.chdir(root) do
- key_pattern = /([a-z\._-]+)/i
- lib_tracked_files.split("\x0").each do |filename|
- each_line(filename) do |line, number|
- line.scan(/Bundler\.settings\[:#{key_pattern}\]/).flatten.each {|s| all_settings[s] << "referenced at `#{filename}:#{number.succ}`" }
- end
+ key_pattern = /([a-z\._-]+)/i
+ lib_tracked_files.each do |filename|
+ each_line(filename) do |line, number|
+ line.scan(/Bundler\.settings\[:#{key_pattern}\]/).flatten.each {|s| all_settings[s] << "referenced at `#{filename}:#{number.succ}`" }
end
- documented_settings = File.read("man/bundle-config.ronn")[/LIST OF AVAILABLE KEYS.*/m].scan(/^\* `#{key_pattern}`/).flatten
end
+ documented_settings = File.read("lib/bundler/man/bundle-config.1.ronn")[/LIST OF AVAILABLE KEYS.*/m].scan(/^\* `#{key_pattern}`/).flatten
documented_settings.each do |s|
all_settings.delete(s)
@@ -231,57 +194,52 @@ RSpec.describe "The library itself" do
end
it "ships the correct set of files" do
- Dir.chdir(root) do
- git_list = shipped_files.split("\x0")
+ git_list = git_ls_files(ruby_core? ? "lib/bundler lib/bundler.rb libexec/bundle*" : "lib exe CHANGELOG.md LICENSE.md README.md bundler.gemspec")
- gem_list = Gem::Specification.load(gemspec.to_s).files
+ gem_list = loaded_gemspec.files
- expect(git_list.to_set).to eq(gem_list.to_set)
- end
+ expect(git_list.sort).to eq(gem_list.sort)
end
it "does not contain any warnings" do
- Dir.chdir(root) do
- exclusions = %w[
- lib/bundler/capistrano.rb
- lib/bundler/deployment.rb
- lib/bundler/gem_tasks.rb
- lib/bundler/vlad.rb
- lib/bundler/templates/gems.rb
- ]
- files_to_require = lib_tracked_files.split("\x0").grep(/\.rb$/) - exclusions
- files_to_require.reject! {|f| f.start_with?("lib/bundler/vendor") }
- files_to_require.map! {|f| f.chomp(".rb") }
- sys_exec!("ruby -w -Ilib") do |input, _, _|
- files_to_require.each do |f|
- input.puts "require '#{f.sub(%r{\Alib/}, "")}'"
- end
+ exclusions = %w[
+ lib/bundler/capistrano.rb
+ lib/bundler/deployment.rb
+ lib/bundler/gem_tasks.rb
+ lib/bundler/vlad.rb
+ lib/bundler/templates/gems.rb
+ ]
+ files_to_require = lib_tracked_files.grep(/\.rb$/) - exclusions
+ files_to_require.reject! {|f| f.start_with?("lib/bundler/vendor") }
+ files_to_require.map! {|f| File.expand_path(f, source_root) }
+ files_to_require.sort!
+ sys_exec("ruby -w") do |input, _, _|
+ files_to_require.each do |f|
+ input.puts "require '#{f}'"
end
+ end
- warnings = last_command.stdboth.split("\n")
- # ignore warnings around deprecated Object#=~ method in RubyGems
- warnings.reject! {|w| w =~ %r{rubygems\/version.rb.*deprecated\ Object#=~} }
+ warnings = last_command.stdboth.split("\n")
+ # ignore warnings around deprecated Object#=~ method in RubyGems
+ warnings.reject! {|w| w =~ %r{rubygems\/version.rb.*deprecated\ Object#=~} }
- expect(warnings).to be_well_formed
- end
+ expect(warnings).to be_well_formed
end
it "does not use require internally, but require_relative" do
- Dir.chdir(root) do
- exempt = %r{templates/|vendor/}
- all_bad_requires = []
- lib_tracked_files.split("\x0").each do |filename|
- next if filename =~ exempt
- each_line(filename) do |line, number|
- line.scan(/^ *require "bundler/).each { all_bad_requires << "#{filename}:#{number.succ}" }
- end
+ exempt = %r{templates/|\.5|\.1|vendor/}
+ all_bad_requires = []
+ lib_tracked_files.each do |filename|
+ next if filename =~ exempt
+ each_line(filename) do |line, number|
+ line.scan(/^ *require "bundler/).each { all_bad_requires << "#{filename}:#{number.succ}" }
end
-
- expect(all_bad_requires).to be_empty, "#{all_bad_requires.size} internal requires that should use `require_relative`: #{all_bad_requires}"
end
+
+ expect(all_bad_requires).to be_empty, "#{all_bad_requires.size} internal requires that should use `require_relative`: #{all_bad_requires}"
end
-private
+ private
def each_line(filename, &block)
File.readlines(filename, :encoding => "UTF-8").each_with_index(&block)
diff --git a/spec/bundler/realworld/dependency_api_spec.rb b/spec/bundler/realworld/dependency_api_spec.rb
index dea8329a4d..08c6acf190 100644
--- a/spec/bundler/realworld/dependency_api_spec.rb
+++ b/spec/bundler/realworld/dependency_api_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe "gemcutter's dependency API", :realworld => true do
@t.run
wait_for_server("127.0.0.1", port)
- bundle! "config set timeout 1"
+ bundle "config set timeout 1"
end
after do
@@ -34,7 +34,7 @@ RSpec.describe "gemcutter's dependency API", :realworld => true do
end
it "times out and falls back on the modern index" do
- install_gemfile! <<-G, :artifice => nil
+ install_gemfile <<-G, :artifice => nil
source "#{@server_uri}"
gem "rack"
G
diff --git a/spec/bundler/realworld/double_check_spec.rb b/spec/bundler/realworld/double_check_spec.rb
index 90cf298b33..d7f28d10bb 100644
--- a/spec/bundler/realworld/double_check_spec.rb
+++ b/spec/bundler/realworld/double_check_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "double checking sources", :realworld => true, :sometimes => true do
+RSpec.describe "double checking sources", :realworld => true do
it "finds already-installed gems" do
create_file("rails.gemspec", <<-RUBY)
Gem::Specification.new do |s|
@@ -25,16 +25,16 @@ RSpec.describe "double checking sources", :realworld => true, :sometimes => true
RUBY
cmd = <<-RUBY
- require "#{lib_dir}/bundler"
+ require "#{entrypoint}"
require "#{spec_dir}/support/artifice/vcr"
- require "#{lib_dir}/bundler/inline"
+ require "#{entrypoint}/inline"
gemfile(true) do
source "https://rubygems.org"
gem "rails", path: "."
end
RUBY
- ruby! cmd
- ruby! cmd
+ ruby cmd
+ ruby cmd
end
end
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
index a91e6a359e..df5eeda9fe 100644
--- a/spec/bundler/realworld/edgecases_spec.rb
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
-RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
+RSpec.describe "real world edgecases", :realworld => true do
def rubygems_version(name, requirement)
- ruby! <<-RUBY
+ ruby <<-RUBY
require "#{spec_dir}/support/artifice/vcr"
- require "#{lib_dir}/bundler"
- require "#{lib_dir}/bundler/source/rubygems/remote"
- require "#{lib_dir}/bundler/fetcher"
+ require "#{entrypoint}"
+ require "#{entrypoint}/source/rubygems/remote"
+ require "#{entrypoint}/fetcher"
rubygem = Bundler.ui.silence do
source = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org"))
fetcher = Bundler::Fetcher.new(source)
@@ -29,7 +29,7 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
gem 'capybara', '~> 2.2.0'
gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9
G
- bundle! :lock
+ bundle :lock
expect(lockfile).to include(rubygems_version("rails", "~> 5.0"))
expect(lockfile).to include("capybara (2.2.1)")
end
@@ -43,7 +43,7 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
gem "gxapi_rails", "< 0.1.0" # 0.1.0 was released way after the test was written
gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9
G
- bundle! :lock
+ bundle :lock
expect(lockfile).to include("gxapi_rails (0.0.6)")
end
@@ -56,13 +56,15 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
gem "activerecord", "~> 3.0"
gem "builder", "~> 2.1.2"
G
- bundle! :lock
+ bundle :lock
expect(lockfile).to include(rubygems_version("i18n", "~> 0.6.0"))
expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0"))
end
it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do
- # from https://github.com/bundler/bundler/issues/5031
+ # from https://github.com/rubygems/bundler/issues/5031
+
+ system_gems "bundler-2.99.0"
gemfile <<-G
source "https://rubygems.org"
@@ -189,159 +191,337 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do
rails (~> 4.2.7.1)
L
- bundle! "lock --update paperclip"
+ bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "2.99.0" }
expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0"))
end
- # https://github.com/bundler/bundler/issues/1500
- it "does not fail install because of gem plugins" do
- realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2")
- gemfile <<-G
+ it "outputs a helpful error message when gems have invalid gemspecs" do
+ install_gemfile <<-G, :standalone => true, :raise_on_error => false, :env => { "BUNDLE_FORCE_RUBY_PLATFORM" => "1" }
+ source 'https://rubygems.org'
+ gem "resque-scheduler", "2.2.0"
+ gem "redis-namespace", "1.6.0" # for a consistent resolution including ruby 2.3.0
+ gem "ruby2_keywords", "0.0.5"
+ G
+ expect(err).to include("You have one or more invalid gemspecs that need to be fixed.")
+ expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec")
+ end
+
+ it "doesn't hang on big gemfile" do
+ skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/
+
+ gemfile <<~G
+ # frozen_string_literal: true
+
source "https://rubygems.org"
- gem 'rack', '1.0.1'
+ ruby "2.7.3"
+
+ gem "rails"
+ gem "pg", ">= 0.18", "< 2.0"
+ gem "goldiloader"
+ gem "awesome_nested_set"
+ gem "circuitbox"
+ gem "passenger"
+ gem "globalid"
+ gem "rack-cors"
+ gem "rails-pg-extras"
+ gem "linear_regression_trend"
+ gem "rack-protection"
+ gem "pundit"
+ gem "remote_ip_proxy_scrubber"
+ gem "bcrypt"
+ gem "searchkick"
+ gem "excon"
+ gem "faraday_middleware-aws-sigv4"
+ gem "typhoeus"
+ gem "sidekiq"
+ gem "sidekiq-undertaker"
+ gem "sidekiq-cron"
+ gem "storext"
+ gem "appsignal"
+ gem "fcm"
+ gem "business_time"
+ gem "tzinfo"
+ gem "holidays"
+ gem "bigdecimal"
+ gem "progress_bar"
+ gem "redis"
+ gem "hiredis"
+ gem "state_machines"
+ gem "state_machines-audit_trail"
+ gem "state_machines-activerecord"
+ gem "interactor"
+ gem "ar_transaction_changes"
+ gem "redis-rails"
+ gem "seed_migration"
+ gem "lograge"
+ gem "graphiql-rails", group: :development
+ gem "graphql"
+ gem "pusher"
+ gem "rbnacl"
+ gem "jwt"
+ gem "json-schema"
+ gem "discard"
+ gem "money"
+ gem "strip_attributes"
+ gem "validates_email_format_of"
+ gem "audited"
+ gem "concurrent-ruby"
+ gem "with_advisory_lock"
+
+ group :test do
+ gem "rspec-sidekiq"
+ gem "simplecov", require: false
+ end
+
+ group :development, :test do
+ gem "byebug", platform: :mri
+ gem "guard"
+ gem "guard-bundler"
+ gem "guard-rspec"
+ gem "rb-fsevent"
+ gem "rspec_junit_formatter"
+ gem "rspec-collection_matchers"
+ gem "rspec-rails"
+ gem "rspec-retry"
+ gem "state_machines-rspec"
+ gem "dotenv-rails"
+ gem "database_cleaner-active_record"
+ gem "database_cleaner-redis"
+ gem "timecop"
+ end
+
+ gem "factory_bot_rails"
+ gem "faker"
+
+ group :development do
+ gem "listen"
+ gem "sql_queries_count"
+ gem "rubocop"
+ gem "rubocop-performance"
+ gem "rubocop-rspec"
+ gem "rubocop-rails"
+ gem "brakeman"
+ gem "bundler-audit"
+ gem "solargraph"
+ gem "annotate"
+ end
G
- bundle "config set --local path vendor/bundle"
- bundle! :install
- expect(err).not_to include("Could not find rake")
- expect(err).to be_empty
+ if Bundler.feature_flag.bundler_3_mode?
+ # Conflicts on bundler version, so fails earlier
+ bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false
+ expect(out).to display_total_steps_of(435)
+ else
+ bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
+ expect(out).to display_total_steps_of(1025)
+ end
end
- it "checks out git repos when the lockfile is corrupted" do
- gemfile <<-G
- source "https://rubygems.org"
- git_source(:github) {|repo| "https://github.com/\#{repo}.git" }
+ it "doesn't hang on tricky gemfile" do
+ skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/
+
+ gemfile <<~G
+ source 'https://rubygems.org'
- gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
- gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
- gem 'actionpack', :github => 'carlhuda/rails-bundler-test', :branch => 'master'
+ group :development do
+ gem "puppet-module-posix-default-r2.7", '~> 0.3'
+ gem "puppet-module-posix-dev-r2.7", '~> 0.3'
+ gem "beaker-rspec"
+ gem "beaker-puppet"
+ gem "beaker-docker"
+ gem "beaker-puppet_install_helper"
+ gem "beaker-module_install_helper"
+ end
G
- lockfile <<-L
- GIT
- remote: https://github.com/carlhuda/rails-bundler-test.git
- revision: 369e28a87419565f1940815219ea9200474589d4
- branch: master
- specs:
- actionpack (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.1)
- rack (~> 1.4.0)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.1.2)
- activemodel (3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- activerecord (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activesupport (3.2.2)
- i18n (~> 0.6)
- multi_json (~> 1.0)
-
- GIT
- remote: https://github.com/carlhuda/rails-bundler-test.git
- revision: 369e28a87419565f1940815219ea9200474589d4
- branch: master
- specs:
- actionpack (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.1)
- rack (~> 1.4.0)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.1.2)
- activemodel (3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- activerecord (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activesupport (3.2.2)
- i18n (~> 0.6)
- multi_json (~> 1.0)
-
- GIT
- remote: https://github.com/carlhuda/rails-bundler-test.git
- revision: 369e28a87419565f1940815219ea9200474589d4
- branch: master
- specs:
- actionpack (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- erubis (~> 2.7.0)
- journey (~> 1.0.1)
- rack (~> 1.4.0)
- rack-cache (~> 1.2)
- rack-test (~> 0.6.1)
- sprockets (~> 2.1.2)
- activemodel (3.2.2)
- activesupport (= 3.2.2)
- builder (~> 3.0.0)
- activerecord (3.2.2)
- activemodel (= 3.2.2)
- activesupport (= 3.2.2)
- arel (~> 3.0.2)
- tzinfo (~> 0.3.29)
- activesupport (3.2.2)
- i18n (~> 0.6)
- multi_json (~> 1.0)
+ bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
- GEM
- remote: https://rubygems.org/
- specs:
- arel (3.0.2)
- builder (3.0.0)
- erubis (2.7.0)
- hike (1.2.1)
- i18n (0.6.0)
- journey (1.0.3)
- multi_json (1.1.0)
- rack (1.4.1)
- rack-cache (1.2)
- rack (>= 0.4)
- rack-test (0.6.1)
- rack (>= 1.0)
- sprockets (2.1.2)
- hike (~> 1.2)
- rack (~> 1.0)
- tilt (~> 1.1, != 1.3.0)
- tilt (1.3.3)
- tzinfo (0.3.32)
+ if Bundler.feature_flag.bundler_3_mode?
+ expect(out).to display_total_steps_of(890)
+ else
+ expect(out).to display_total_steps_of(891)
+ end
+ end
- PLATFORMS
- ruby
+ it "doesn't hang on nix gemfile" do
+ skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" || RUBY_PLATFORM =~ /darwin/
- DEPENDENCIES
- actionpack!
- activerecord!
- activesupport!
- L
+ gemfile <<~G
+ source "https://rubygems.org" do
+ gem "addressable"
+ gem "atk"
+ gem "awesome_print"
+ gem "bacon"
+ gem "byebug"
+ gem "cairo"
+ gem "cairo-gobject"
+ gem "camping"
+ gem "charlock_holmes"
+ gem "cld3"
+ gem "cocoapods"
+ gem "cocoapods-acknowledgements"
+ gem "cocoapods-art"
+ gem "cocoapods-bin"
+ gem "cocoapods-browser"
+ gem "cocoapods-bugsnag"
+ gem "cocoapods-check"
+ gem "cocoapods-clean"
+ gem "cocoapods-clean_build_phases_scripts"
+ gem "cocoapods-core"
+ gem "cocoapods-coverage"
+ gem "cocoapods-deintegrate"
+ gem "cocoapods-dependencies"
+ gem "cocoapods-deploy"
+ gem "cocoapods-downloader"
+ gem "cocoapods-expert-difficulty"
+ gem "cocoapods-fix-react-native"
+ gem "cocoapods-generate"
+ gem "cocoapods-git_url_rewriter"
+ gem "cocoapods-keys"
+ gem "cocoapods-no-dev-schemes"
+ gem "cocoapods-open"
+ gem "cocoapods-packager"
+ gem "cocoapods-playgrounds"
+ gem "cocoapods-plugins"
+ gem "cocoapods-prune-localizations"
+ gem "cocoapods-rome"
+ gem "cocoapods-search"
+ gem "cocoapods-sorted-search"
+ gem "cocoapods-static-swift-framework"
+ gem "cocoapods-stats"
+ gem "cocoapods-tdfire-binary"
+ gem "cocoapods-testing"
+ gem "cocoapods-trunk"
+ gem "cocoapods-try"
+ gem "cocoapods-try-release-fix"
+ gem "cocoapods-update-if-you-dare"
+ gem "cocoapods-whitelist"
+ gem "cocoapods-wholemodule"
+ gem "coderay"
+ gem "concurrent-ruby"
+ gem "curb"
+ gem "curses"
+ gem "daemons"
+ gem "dep-selector-libgecode"
+ gem "digest-sha3"
+ gem "domain_name"
+ gem "do_sqlite3"
+ gem "ethon"
+ gem "eventmachine"
+ gem "excon"
+ gem "faraday"
+ gem "ffi"
+ gem "ffi-rzmq-core"
+ gem "fog-dnsimple"
+ gem "gdk_pixbuf2"
+ gem "gio2"
+ gem "gitlab-markup"
+ gem "glib2"
+ gem "gpgme"
+ gem "gtk2"
+ gem "hashie"
+ gem "highline"
+ gem "hike"
+ gem "hitimes"
+ gem "hpricot"
+ gem "httpclient"
+ gem "http-cookie"
+ gem "iconv"
+ gem "idn-ruby"
+ gem "jbuilder"
+ gem "jekyll"
+ gem "jmespath"
+ gem "jwt"
+ gem "libv8"
+ gem "libxml-ruby"
+ gem "magic"
+ gem "markaby"
+ gem "method_source"
+ gem "mini_magick"
+ gem "msgpack"
+ gem "mysql2"
+ gem "ncursesw"
+ gem "netrc"
+ gem "net-scp"
+ gem "net-ssh"
+ gem "nokogiri"
+ gem "opus-ruby"
+ gem "ovirt-engine-sdk"
+ gem "pango"
+ gem "patron"
+ gem "pcaprub"
+ gem "pg"
+ gem "pry"
+ gem "pry-byebug"
+ gem "pry-doc"
+ gem "public_suffix"
+ gem "puma"
+ gem "rails"
+ gem "rainbow"
+ gem "rbnacl"
+ gem "rb-readline"
+ gem "re2"
+ gem "redis"
+ gem "redis-rack"
+ gem "rest-client"
+ gem "rmagick"
+ gem "rpam2"
+ gem "rspec"
+ gem "rubocop"
+ gem "rubocop-performance"
+ gem "ruby-libvirt"
+ gem "ruby-lxc"
+ gem "ruby-progressbar"
+ gem "ruby-terminfo"
+ gem "ruby-vips"
+ gem "rubyzip"
+ gem "rugged"
+ gem "sassc"
+ gem "scrypt"
+ gem "semian"
+ gem "sequel"
+ gem "sequel_pg"
+ gem "simplecov"
+ gem "sinatra"
+ gem "slop"
+ gem "snappy"
+ gem "sqlite3"
+ gem "taglib-ruby"
+ gem "thrift"
+ gem "tilt"
+ gem "tiny_tds"
+ gem "treetop"
+ gem "typhoeus"
+ gem "tzinfo"
+ gem "unf_ext"
+ gem "uuid4r"
+ gem "whois"
+ gem "zookeeper"
+ end
+ G
+
+ bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }
- bundle! :lock
- expect(err).to be_empty
+ if Bundler.feature_flag.bundler_3_mode?
+ expect(out).to display_total_steps_of(1874)
+ else
+ expect(out).to display_total_steps_of(1922)
+ end
end
- it "outputs a helpful error message when gems have invalid gemspecs" do
- install_gemfile <<-G, :standalone => true
- source 'https://rubygems.org'
- gem "resque-scheduler", "2.2.0"
- G
- expect(err).to include("You have one or more invalid gemspecs that need to be fixed.")
- expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec")
+ private
+
+ RSpec::Matchers.define :display_total_steps_of do |expected_steps|
+ match do |out|
+ out.include?("BUNDLER: Finished resolution (#{expected_steps} steps)")
+ end
+
+ failure_message do |out|
+ actual_steps = out.scan(/BUNDLER: Finished resolution \((\d+) steps\)/).first.first
+
+ "Expected resolution to finish in #{expected_steps} steps, but took #{actual_steps}"
+ end
end
end
diff --git a/spec/bundler/realworld/ffi_spec.rb b/spec/bundler/realworld/ffi_spec.rb
new file mode 100644
index 0000000000..083ea38901
--- /dev/null
+++ b/spec/bundler/realworld/ffi_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+RSpec.describe "loading dinamically linked library on a bundle exec context", :realworld => true do
+ it "passes ENV right after argv in memory" do
+ create_file "foo.rb", <<~RUBY
+ require 'ffi'
+
+ module FOO
+ extend FFI::Library
+ ffi_lib './libfoo.so'
+
+ attach_function :Hello, [], :void
+ end
+
+ FOO.Hello()
+ RUBY
+
+ create_file "libfoo.c", <<~'C'
+ #include <stdio.h>
+
+ static int foo_init(int argc, char** argv, char** envp) {
+ if (argv[argc+1] == NULL) {
+ printf("FAIL\n");
+ } else {
+ printf("OK\n");
+ }
+
+ return 0;
+ }
+
+ #if defined(__APPLE__) && defined(__MACH__)
+ __attribute__((section("__DATA,__mod_init_func"), used, aligned(sizeof(void*))))
+ #else
+ __attribute__((section(".init_array")))
+ #endif
+ static void *ctr = &foo_init;
+
+ extern char** environ;
+
+ void Hello() {
+ return;
+ }
+ C
+
+ sys_exec "gcc -g -o libfoo.so -shared -fpic libfoo.c"
+
+ install_gemfile <<-G
+ source "https://rubygems.org"
+
+ gem 'ffi'
+ G
+
+ bundle "exec ruby foo.rb"
+
+ expect(out).to eq("OK")
+ end
+end
diff --git a/spec/bundler/realworld/fixtures/warbler/.gitignore b/spec/bundler/realworld/fixtures/warbler/.gitignore
new file mode 100644
index 0000000000..d392f0e82c
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/.gitignore
@@ -0,0 +1 @@
+*.jar
diff --git a/spec/bundler/realworld/fixtures/warbler/Gemfile b/spec/bundler/realworld/fixtures/warbler/Gemfile
new file mode 100644
index 0000000000..4fbf2d05a7
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/Gemfile
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "demo", :path => "./demo"
+gem "jruby-jars", "~> 9.2"
+gem "warbler", "~> 2.0"
diff --git a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
new file mode 100644
index 0000000000..05bcb877db
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
@@ -0,0 +1,30 @@
+PATH
+ remote: demo
+ specs:
+ demo (1.0)
+
+GEM
+ remote: https://rubygems.org/
+ specs:
+ jruby-jars (9.2.16.0)
+ jruby-rack (1.1.21)
+ rake (13.0.1)
+ rubyzip (1.3.0)
+ warbler (2.0.5)
+ jruby-jars (>= 9.0.0.0)
+ jruby-rack (>= 1.1.1, < 1.3)
+ rake (>= 10.1.0)
+ rubyzip (~> 1.0, < 1.4)
+
+PLATFORMS
+ java
+ ruby
+ universal-java-11
+
+DEPENDENCIES
+ demo!
+ jruby-jars (~> 9.2)
+ warbler (~> 2.0)
+
+BUNDLED WITH
+ 2.3.0.dev
diff --git a/spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb b/spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb
new file mode 100644
index 0000000000..25f614ecc2
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/bin/warbler-example.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+puts require "bundler/setup"
diff --git a/spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec b/spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec
new file mode 100644
index 0000000000..ed5a0dc080
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/warbler/demo/demo.gemspec
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+Gem::Specification.new do |spec|
+ spec.name = "demo"
+ spec.version = "1.0"
+ spec.author = "Somebody"
+ spec.summary = "A demo gem"
+ spec.license = "MIT"
+ spec.homepage = "https://example.org"
+end
diff --git a/spec/bundler/realworld/gemfile_source_header_spec.rb b/spec/bundler/realworld/gemfile_source_header_spec.rb
index 3f507b056a..ada2fc92ee 100644
--- a/spec/bundler/realworld/gemfile_source_header_spec.rb
+++ b/spec/bundler/realworld/gemfile_source_header_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe "fetching dependencies with a mirrored source", :realworld => tru
expect(the_bundle).to include_gems "weakling 0.0.3"
end
-private
+ private
def setup_server
require_rack
diff --git a/spec/bundler/realworld/mirror_probe_spec.rb b/spec/bundler/realworld/mirror_probe_spec.rb
index 735fb2b3dd..84d6a9c782 100644
--- a/spec/bundler/realworld/mirror_probe_spec.rb
+++ b/spec/bundler/realworld/mirror_probe_spec.rb
@@ -71,13 +71,13 @@ RSpec.describe "fetching dependencies with a not available mirror", :realworld =
gem 'weakling'
G
- bundle :install, :artifice => nil
+ bundle :install, :artifice => nil, :raise_on_error => false
expect(out).to include("Fetching source index from #{mirror}")
- expect(err).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(err).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(err).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(err).to include("Could not fetch specs from #{mirror}")
+ expect(err).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2)")
+ expect(err).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2)")
+ expect(err).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2)")
+ expect(err).to include("Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2)")
end
it "prints each error and warning on a new line" do
@@ -86,15 +86,10 @@ RSpec.describe "fetching dependencies with a not available mirror", :realworld =
gem 'weakling'
G
- bundle :install, :artifice => nil
+ bundle :install, :artifice => nil, :raise_on_error => false
expect(out).to include "Fetching source index from #{mirror}/"
- expect(err).to include <<-EOS.strip
-Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}/
-Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}/
-Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}/
-Could not fetch specs from #{mirror}/
- EOS
+ expect(err.split("\n").count).to eq(4)
end
end
@@ -109,13 +104,13 @@ Could not fetch specs from #{mirror}/
gem 'weakling'
G
- bundle :install, :artifice => nil
+ bundle :install, :artifice => nil, :raise_on_error => false
expect(out).to include("Fetching source index from #{mirror}")
- expect(err).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(err).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(err).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}")
- expect(err).to include("Could not fetch specs from #{mirror}")
+ expect(err).to include("Retrying fetcher due to error (2/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2)")
+ expect(err).to include("Retrying fetcher due to error (3/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2)")
+ expect(err).to include("Retrying fetcher due to error (4/4): Bundler::HTTPError Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2)")
+ expect(err).to include("Could not fetch specs from #{mirror}/ due to underlying error <Errno::ECONNREFUSED: Failed to open TCP connection to #{host}:#{@mirror_port} (Connection refused - connect(2)")
end
end
@@ -138,7 +133,7 @@ Could not fetch specs from #{mirror}/
end
def setup_mirror
- mirror_port = find_unused_port
- @mirror_uri = "http://#{host}:#{mirror_port}"
+ @mirror_port = find_unused_port
+ @mirror_uri = "http://#{host}:#{@mirror_port}"
end
end
diff --git a/spec/bundler/realworld/parallel_spec.rb b/spec/bundler/realworld/parallel_spec.rb
index 7738b46aac..97c0e0cab4 100644
--- a/spec/bundler/realworld/parallel_spec.rb
+++ b/spec/bundler/realworld/parallel_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "parallel", :realworld => true, :sometimes => true do
+RSpec.describe "parallel", :realworld => true do
it "installs" do
gemfile <<-G
source "https://rubygems.org"
@@ -53,7 +53,7 @@ RSpec.describe "parallel", :realworld => true, :sometimes => true do
bundle :install, :standalone => true, :jobs => 4
- ruby <<-RUBY, :no_lib => true
+ ruby <<-RUBY
$:.unshift File.expand_path("bundle")
require "bundler/setup"
diff --git a/spec/bundler/realworld/slow_perf_spec.rb b/spec/bundler/realworld/slow_perf_spec.rb
new file mode 100644
index 0000000000..aced5a1641
--- /dev/null
+++ b/spec/bundler/realworld/slow_perf_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe "bundle install with complex dependencies", :realworld => true do
+ it "resolves quickly" do
+ gemfile <<-G
+ source 'https://rubygems.org'
+
+ gem "actionmailer"
+ gem "mongoid", ">= 0.10.2"
+ G
+
+ start_time = Time.now
+
+ bundle "lock"
+
+ duration = Time.now - start_time
+
+ expect(duration.to_f).to be < 12 # seconds
+ end
+end
diff --git a/spec/bundler/resolver/basic_spec.rb b/spec/bundler/resolver/basic_spec.rb
index 57897f89b4..ee62dc3577 100644
--- a/spec/bundler/resolver/basic_spec.rb
+++ b/spec/bundler/resolver/basic_spec.rb
@@ -176,7 +176,7 @@ Bundler could not find compatible versions for gem "a":
deps = []
@deps.each do |d|
- deps << Bundler::DepProxy.new(d, "ruby")
+ deps << Bundler::DepProxy.get_proxy(d, "ruby")
end
should_resolve_and_include %w[foo-1.0.0 bar-1.0.0], [[]]
diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb
index fee0cf1f1c..bc4081f8b5 100644
--- a/spec/bundler/resolver/platform_spec.rb
+++ b/spec/bundler/resolver/platform_spec.rb
@@ -28,6 +28,266 @@ RSpec.describe "Resolving platform craziness" do
end
end
+ it "resolves multiplatform gems with redundant platforms correctly" do
+ @index = build_index do
+ gem "zookeeper", "1.4.11"
+ gem "zookeeper", "1.4.11", "java" do
+ dep "slyphon-log4j", "= 1.2.15"
+ dep "slyphon-zookeeper_jar", "= 3.3.5"
+ end
+ gem "slyphon-log4j", "1.2.15"
+ gem "slyphon-zookeeper_jar", "3.3.5", "java"
+ end
+
+ dep "zookeeper"
+ platforms "java", "ruby", "universal-java-11"
+
+ should_resolve_as %w[zookeeper-1.4.11 zookeeper-1.4.11-java slyphon-log4j-1.2.15 slyphon-zookeeper_jar-3.3.5-java]
+ end
+
+ it "takes the latest ruby gem, even if an older platform specific version is available" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw32"
+ gem "foo", "1.1.0"
+ end
+ dep "foo"
+ platforms "x64-mingw32"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+
+ it "takes the ruby version if the platform version is incompatible" do
+ @index = build_index do
+ gem "bar", "1.0.0"
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw32" do
+ dep "bar", "< 1"
+ end
+ end
+ dep "foo"
+ platforms "x64-mingw32"
+
+ should_resolve_as %w[foo-1.0.0]
+ end
+
+ it "prefers the platform specific gem to the ruby version" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw32"
+ end
+ dep "foo"
+ platforms "x64-mingw32"
+
+ should_resolve_as %w[foo-1.0.0-x64-mingw32]
+ end
+
+ it "takes the latest ruby gem if the platform specific gem doesn't match the required_ruby_version" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw32"
+ gem "foo", "1.1.0"
+ gem "foo", "1.1.0", "x64-mingw32" do |s|
+ s.required_ruby_version = [">= 2.0", "< 2.4"]
+ end
+ gem "Ruby\0", "2.5.1"
+ end
+ dep "foo"
+ dep "Ruby\0", "2.5.1"
+ platforms "x64-mingw32"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+
+ it "takes the latest ruby gem with required_ruby_version if the platform specific gem doesn't match the required_ruby_version" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw32"
+ gem "foo", "1.1.0" do |s|
+ s.required_ruby_version = [">= 2.0"]
+ end
+ gem "foo", "1.1.0", "x64-mingw32" do |s|
+ s.required_ruby_version = [">= 2.0", "< 2.4"]
+ end
+ gem "Ruby\0", "2.5.1"
+ end
+ dep "foo"
+ dep "Ruby\0", "2.5.1"
+ platforms "x64-mingw32"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+
+ it "takes the latest ruby gem if the platform specific gem doesn't match the required_ruby_version with multiple platforms" do
+ @index = build_index do
+ gem "foo", "1.0.0"
+ gem "foo", "1.0.0", "x64-mingw32"
+ gem "foo", "1.1.0" do |s|
+ s.required_ruby_version = [">= 2.0"]
+ end
+ gem "foo", "1.1.0", "x64-mingw32" do |s|
+ s.required_ruby_version = [">= 2.0", "< 2.4"]
+ end
+ gem "Ruby\0", "2.5.1"
+ end
+ dep "foo"
+ dep "Ruby\0", "2.5.1"
+ platforms "x86_64-linux", "x64-mingw32"
+
+ should_resolve_as %w[foo-1.1.0]
+ end
+
+ it "doesn't include gems not needed for none of the platforms" do
+ @index = build_index do
+ gem "empyrean", "0.1.0"
+ gem "coderay", "1.1.2"
+ gem "method_source", "0.9.0"
+
+ gem "spoon", "0.0.6" do
+ dep "ffi", ">= 0"
+ end
+
+ gem "pry", "0.11.3", "java" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ dep "spoon", "~> 0.0"
+ end
+
+ gem "pry", "0.11.3" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ end
+
+ gem "ffi", "1.9.23", "java"
+ gem "ffi", "1.9.23"
+ end
+
+ dep "empyrean", "0.1.0"
+ dep "pry"
+
+ platforms "ruby", "java"
+
+ should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6]
+ end
+
+ it "includes gems needed for at least one platform" do
+ @index = build_index do
+ gem "empyrean", "0.1.0"
+ gem "coderay", "1.1.2"
+ gem "method_source", "0.9.0"
+
+ gem "spoon", "0.0.6" do
+ dep "ffi", ">= 0"
+ end
+
+ gem "pry", "0.11.3", "java" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ dep "spoon", "~> 0.0"
+ end
+
+ gem "pry", "0.11.3" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ end
+
+ gem "ffi", "1.9.23", "java"
+ gem "ffi", "1.9.23"
+
+ gem "extra", "1.0.0" do
+ dep "ffi", ">= 0"
+ end
+ end
+
+ dep "empyrean", "0.1.0"
+ dep "pry"
+ dep "extra"
+
+ platforms "ruby", "java"
+
+ should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6]
+ end
+
+ it "includes gems needed for at least one platform even when the platform specific requirement is processed earlier than the generic requirement" do
+ @index = build_index do
+ gem "empyrean", "0.1.0"
+ gem "coderay", "1.1.2"
+ gem "method_source", "0.9.0"
+
+ gem "spoon", "0.0.6" do
+ dep "ffi", ">= 0"
+ end
+
+ gem "pry", "0.11.3", "java" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ dep "spoon", "~> 0.0"
+ end
+
+ gem "pry", "0.11.3" do
+ dep "coderay", "~> 1.1.0"
+ dep "method_source", "~> 0.9.0"
+ end
+
+ gem "ffi", "1.9.23", "java"
+ gem "ffi", "1.9.23"
+
+ gem "extra", "1.0.0" do
+ dep "extra2", ">= 0"
+ end
+
+ gem "extra2", "1.0.0" do
+ dep "extra3", ">= 0"
+ end
+
+ gem "extra3", "1.0.0" do
+ dep "ffi", ">= 0"
+ end
+ end
+
+ dep "empyrean", "0.1.0"
+ dep "pry"
+ dep "extra"
+
+ platforms "ruby", "java"
+
+ should_resolve_as %w[coderay-1.1.2 empyrean-0.1.0 extra-1.0.0 extra2-1.0.0 extra3-1.0.0 ffi-1.9.23 ffi-1.9.23-java method_source-0.9.0 pry-0.11.3 pry-0.11.3-java spoon-0.0.6]
+ end
+
+ it "properly adds platforms when platform requirements come from different dependencies" do
+ @index = build_index do
+ gem "ffi", "1.9.14"
+ gem "ffi", "1.9.14", "universal-mingw32"
+
+ gem "gssapi", "0.1"
+ gem "gssapi", "0.2"
+ gem "gssapi", "0.3"
+ gem "gssapi", "1.2.0" do
+ dep "ffi", ">= 1.0.1"
+ end
+
+ gem "mixlib-shellout", "2.2.6"
+ gem "mixlib-shellout", "2.2.6", "universal-mingw32" do
+ dep "win32-process", "~> 0.8.2"
+ end
+
+ # we need all these versions to get the sorting the same as it would be
+ # pulling from rubygems.org
+ %w[0.8.3 0.8.2 0.8.1 0.8.0].each do |v|
+ gem "win32-process", v do
+ dep "ffi", ">= 1.0.0"
+ end
+ end
+ end
+
+ dep "mixlib-shellout"
+ dep "gssapi"
+
+ platforms "universal-mingw32", "ruby"
+
+ should_resolve_as %w[ffi-1.9.14 ffi-1.9.14-universal-mingw32 gssapi-1.2.0 mixlib-shellout-2.2.6 mixlib-shellout-2.2.6-universal-mingw32 win32-process-0.8.3]
+ end
+
describe "with mingw32" do
before :each do
@index = build_index do
@@ -90,11 +350,11 @@ RSpec.describe "Resolving platform craziness" do
end
end
- it "reports on the conflict" do
+ it "takes the ruby version as fallback" do
platforms "ruby", "java"
dep "foo"
- should_conflict_on "baz"
+ should_resolve_as %w[bar-1.0.0 baz-1.0.0 foo-1.0.0]
end
end
end
diff --git a/spec/bundler/runtime/executable_spec.rb b/spec/bundler/runtime/executable_spec.rb
index 003be97cd6..a11f547648 100644
--- a/spec/bundler/runtime/executable_spec.rb
+++ b/spec/bundler/runtime/executable_spec.rb
@@ -2,14 +2,14 @@
RSpec.describe "Running bin/* commands" do
before :each do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
end
it "runs the bundled command when in the bundle" do
- bundle! "binstubs rack"
+ bundle "binstubs rack"
build_gem "rack", "2.0", :to_system => true do |s|
s.executables = "rackup"
@@ -20,7 +20,7 @@ RSpec.describe "Running bin/* commands" do
end
it "allows the location of the gem stubs to be specified" do
- bundle! "binstubs rack", :path => "gbin"
+ bundle "binstubs rack", :path => "gbin"
expect(bundled_app("bin")).not_to exist
expect(bundled_app("gbin/rackup")).to exist
@@ -30,33 +30,31 @@ RSpec.describe "Running bin/* commands" do
end
it "allows absolute paths as a specification of where to install bin stubs" do
- bundle! "binstubs rack", :path => tmp("bin")
+ bundle "binstubs rack", :path => tmp("bin")
gembin tmp("bin/rackup")
expect(out).to eq("1.0.0")
end
it "uses the default ruby install name when shebang is not specified" do
- bundle! "binstubs rack"
- expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env #{RbConfig::CONFIG["ruby_install_name"]}\n")
+ bundle "binstubs rack"
+ expect(File.readlines(bundled_app("bin/rackup")).first).to eq("#!/usr/bin/env #{RbConfig::CONFIG["ruby_install_name"]}\n")
end
it "allows the name of the shebang executable to be specified" do
- bundle! "binstubs rack", :shebang => "ruby-foo"
- expect(File.open("bin/rackup").gets).to eq("#!/usr/bin/env ruby-foo\n")
+ bundle "binstubs rack", :shebang => "ruby-foo"
+ expect(File.readlines(bundled_app("bin/rackup")).first).to eq("#!/usr/bin/env ruby-foo\n")
end
it "runs the bundled command when out of the bundle" do
- bundle! "binstubs rack"
+ bundle "binstubs rack"
build_gem "rack", "2.0", :to_system => true do |s|
s.executables = "rackup"
end
- Dir.chdir(tmp) do
- gembin "rackup"
- expect(out).to eq("1.0.0")
- end
+ gembin "rackup", :dir => tmp
+ expect(out).to eq("1.0.0")
end
it "works with gems in path" do
@@ -65,10 +63,11 @@ RSpec.describe "Running bin/* commands" do
end
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack", :path => "#{lib_path("rack")}"
G
- bundle! "binstubs rack"
+ bundle "binstubs rack"
build_gem "rack", "2.0", :to_system => true do |s|
s.executables = "rackup"
@@ -79,34 +78,32 @@ RSpec.describe "Running bin/* commands" do
end
it "creates a bundle binstub" do
- build_gem "bundler", Bundler::VERSION, :to_system => true do |s|
- s.executables = "bundle"
- end
-
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "bundler"
G
- bundle! "binstubs bundler"
+ bundle "binstubs bundler"
expect(bundled_app("bin/bundle")).to exist
end
it "does not generate bin stubs if the option was not specified" do
- bundle! "install"
+ bundle "install"
expect(bundled_app("bin/rackup")).not_to exist
end
it "allows you to stop installing binstubs", :bundler => "< 3" do
- bundle! "install --binstubs bin/"
+ skip "delete permission error" if Gem.win_platform?
+
+ bundle "install --binstubs bin/"
bundled_app("bin/rackup").rmtree
- bundle! "install --binstubs \"\""
+ bundle "install --binstubs \"\""
expect(bundled_app("bin/rackup")).not_to exist
- bundle! "config bin"
+ bundle "config bin"
expect(out).to include("You have not configured a value for `bin`")
end
@@ -116,7 +113,7 @@ RSpec.describe "Running bin/* commands" do
gem "activesupport"
G
- bundle! :install, :binstubs => "bin"
+ bundle :install, :binstubs => "bin"
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -130,21 +127,21 @@ RSpec.describe "Running bin/* commands" do
end
it "rewrites bins on binstubs (to maintain backwards compatibility)" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
create_file("bin/rackup", "OMG")
- bundle! "binstubs rack"
+ bundle "binstubs rack"
expect(bundled_app("bin/rackup").read).to_not eq("OMG")
end
it "use BUNDLE_GEMFILE gemfile for binstub" do
# context with bin/bundler w/ default Gemfile
- bundle! "binstubs bundler"
+ bundle "binstubs bundler"
# generate other Gemfile with executable gem
build_repo2 do
@@ -159,7 +156,7 @@ RSpec.describe "Running bin/* commands" do
# generate binstub for executable from non default Gemfile (other then bin/bundler version)
ENV["BUNDLE_GEMFILE"] = "OtherGemfile"
bundle "install"
- bundle! "binstubs bindir"
+ bundle "binstubs bindir"
# remove user settings
ENV["BUNDLE_GEMFILE"] = nil
@@ -167,7 +164,6 @@ RSpec.describe "Running bin/* commands" do
# run binstub for non default Gemfile
gembin "foo"
- expect(exitstatus).to eq(0) if exitstatus
expect(out).to eq("1.0")
end
end
diff --git a/spec/bundler/runtime/gem_tasks_spec.rb b/spec/bundler/runtime/gem_tasks_spec.rb
index 74270a2316..b0ef0cc144 100644
--- a/spec/bundler/runtime/gem_tasks_spec.rb
+++ b/spec/bundler/runtime/gem_tasks_spec.rb
@@ -15,12 +15,11 @@ RSpec.describe "require 'bundler/gem_tasks'" do
bundled_app("Rakefile").open("w") do |f|
f.write <<-RAKEFILE
- $:.unshift("#{lib_dir}")
require "bundler/gem_tasks"
RAKEFILE
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rake"
@@ -28,8 +27,8 @@ RSpec.describe "require 'bundler/gem_tasks'" do
end
it "includes the relevant tasks" do
- with_gem_path_as(Spec::Path.base_system_gems.to_s) do
- sys_exec "#{rake} -T", "RUBYOPT" => "-I#{lib_dir}"
+ with_gem_path_as(base_system_gems.to_s) do
+ sys_exec "#{rake} -T", :env => { "GEM_HOME" => system_gem_path.to_s }
end
expect(err).to be_empty
@@ -42,38 +41,65 @@ RSpec.describe "require 'bundler/gem_tasks'" do
]
tasks = out.lines.to_a.map {|s| s.split("#").first.strip }
expect(tasks & expected_tasks).to eq(expected_tasks)
- expect(exitstatus).to eq(0) if exitstatus
end
- it "defines a working `rake install` task" do
- with_gem_path_as(Spec::Path.base_system_gems.to_s) do
- sys_exec "#{rake} install", "RUBYOPT" => "-I#{lib_dir}"
+ it "defines a working `rake install` task", :ruby_repo do
+ with_gem_path_as(base_system_gems.to_s) do
+ sys_exec "#{rake} install", :env => { "GEM_HOME" => system_gem_path.to_s }
end
expect(err).to be_empty
- bundle! "exec rake install"
+ bundle "exec rake install"
expect(err).to be_empty
end
- context "rake build when path has spaces" do
+ context "rake build when path has spaces", :ruby_repo do
before do
spaced_bundled_app = tmp.join("bundled app")
- FileUtils.mv bundled_app, spaced_bundled_app
- Dir.chdir(spaced_bundled_app)
+ FileUtils.cp_r bundled_app, spaced_bundled_app
+ bundle "exec rake build", :dir => spaced_bundled_app
end
it "still runs successfully" do
- bundle! "exec rake build"
+ expect(err).to be_empty
+ end
+ end
+
+ context "rake build when path has brackets", :ruby_repo do
+ before do
+ bracketed_bundled_app = tmp.join("bundled[app")
+ FileUtils.cp_r bundled_app, bracketed_bundled_app
+ bundle "exec rake build", :dir => bracketed_bundled_app
+ end
+
+ it "still runs successfully" do
+ expect(err).to be_empty
+ end
+ end
+
+ context "bundle path configured locally" do
+ before do
+ bundle "config set path vendor/bundle"
+ end
+
+ it "works", :ruby_repo do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
+ gem "rake"
+ G
+
+ bundle "exec rake -T"
expect(err).to be_empty
end
end
it "adds 'pkg' to rake/clean's CLOBBER" do
- with_gem_path_as(Spec::Path.base_system_gems.to_s) do
- sys_exec! %(#{rake} -e 'load "Rakefile"; puts CLOBBER.inspect')
+ with_gem_path_as(base_system_gems.to_s) do
+ sys_exec %(#{rake} -e 'load "Rakefile"; puts CLOBBER.inspect'), :env => { "GEM_HOME" => system_gem_path.to_s }
end
expect(out).to eq '["pkg"]'
end
diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb
index cd762fe636..3b5ede41ee 100644
--- a/spec/bundler/runtime/inline_spec.rb
+++ b/spec/bundler/runtime/inline_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe "bundler/inline#gemfile" do
def script(code, options = {})
- requires = ["#{lib_dir}/bundler/inline"]
+ requires = ["#{entrypoint}/inline"]
requires.unshift "#{spec_dir}/support/artifice/" + options.delete(:artifice) if options.key?(:artifice)
requires = requires.map {|r| "require '#{r}'" }.join("\n")
ruby("#{requires}\n\n" + code, options)
@@ -48,6 +48,7 @@ RSpec.describe "bundler/inline#gemfile" do
it "requires the gems" do
script <<-RUBY
gemfile do
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem "two"
end
@@ -55,10 +56,10 @@ RSpec.describe "bundler/inline#gemfile" do
RUBY
expect(out).to eq("two")
- expect(exitstatus).to be_zero if exitstatus
- script <<-RUBY
+ script <<-RUBY, :raise_on_error => false
gemfile do
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem "eleven"
end
@@ -78,7 +79,6 @@ RSpec.describe "bundler/inline#gemfile" do
RUBY
expect(out).to include("Rack's post install message")
- expect(exitstatus).to be_zero if exitstatus
script <<-RUBY, :artifice => "endpoint"
gemfile(true) do
@@ -91,12 +91,11 @@ RSpec.describe "bundler/inline#gemfile" do
err_lines = err.split("\n")
err_lines.reject!{|line| line =~ /\.rb:\d+: warning: / } unless RUBY_VERSION < "2.7"
expect(err_lines).to be_empty
- expect(exitstatus).to be_zero if exitstatus
end
it "lets me use my own ui object" do
script <<-RUBY, :artifice => "endpoint"
- require '#{lib_dir}/bundler'
+ require '#{entrypoint}'
class MyBundlerUI < Bundler::UI::Silent
def confirm(msg, newline = nil)
puts "CONFIRMED!"
@@ -109,12 +108,11 @@ RSpec.describe "bundler/inline#gemfile" do
RUBY
expect(out).to eq("CONFIRMED!\nCONFIRMED!")
- expect(exitstatus).to be_zero if exitstatus
end
it "has an option for quiet installation" do
script <<-RUBY, :artifice => "endpoint"
- require '#{lib_dir}/bundler/inline'
+ require '#{entrypoint}/inline'
gemfile(true, :quiet => true) do
source "https://notaserver.com"
@@ -126,7 +124,7 @@ RSpec.describe "bundler/inline#gemfile" do
end
it "raises an exception if passed unknown arguments" do
- script <<-RUBY
+ script <<-RUBY, :raise_on_error => false
gemfile(true, :arglebargle => true) do
path "#{lib_path}"
gem "two"
@@ -140,9 +138,10 @@ RSpec.describe "bundler/inline#gemfile" do
it "does not mutate the option argument" do
script <<-RUBY
- require '#{lib_dir}/bundler'
+ require '#{entrypoint}'
options = { :ui => Bundler::UI::Shell.new }
gemfile(false, options) do
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem "two"
end
@@ -151,7 +150,6 @@ RSpec.describe "bundler/inline#gemfile" do
RUBY
expect(out).to match("OKAY")
- expect(exitstatus).to be_zero if exitstatus
end
it "installs quietly if necessary when the install option is not set" do
@@ -166,7 +164,6 @@ RSpec.describe "bundler/inline#gemfile" do
expect(out).to eq("1.0.0")
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
end
it "installs quietly from git if necessary when the install option is not set" do
@@ -174,6 +171,7 @@ 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)}"
gem "foo", :git => #{lib_path("foo-1.0.0").to_s.dump}
gem "baz", :git => #{lib_path("baz-2.0.0").to_s.dump}, :ref => #{baz_ref.dump}
end
@@ -184,19 +182,20 @@ RSpec.describe "bundler/inline#gemfile" do
expect(out).to eq("1.0.0\n2.0.0")
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
end
it "allows calling gemfile twice" do
script <<-RUBY
gemfile do
path "#{lib_path}" do
+ source "#{file_uri_for(gem_repo1)}"
gem "two"
end
end
gemfile do
path "#{lib_path}" do
+ source "#{file_uri_for(gem_repo1)}"
gem "four"
end
end
@@ -204,7 +203,6 @@ RSpec.describe "bundler/inline#gemfile" do
expect(out).to eq("two\nfour")
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
end
it "installs inline gems when a Gemfile.lock is present" do
@@ -226,22 +224,19 @@ RSpec.describe "bundler/inline#gemfile" do
rake
BUNDLED WITH
- 1.13.6
+ #{Bundler::VERSION}
G
- in_app_root do
- script <<-RUBY
- gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- end
+ script <<-RUBY
+ gemfile do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ end
- puts RACK
- RUBY
- end
+ puts RACK
+ RUBY
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
end
it "installs inline gems when frozen is set" do
@@ -255,25 +250,34 @@ RSpec.describe "bundler/inline#gemfile" do
RUBY
expect(last_command.stderr).to be_empty
- expect(exitstatus).to be_zero if exitstatus
+ end
+
+ it "installs inline gems when deployment is set" do
+ script <<-RUBY, :env => { "BUNDLE_DEPLOYMENT" => "true" }
+ gemfile do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ end
+
+ puts RACK
+ RUBY
+
+ expect(last_command.stderr).to be_empty
end
it "installs inline gems when BUNDLE_GEMFILE is set to an empty string" do
ENV["BUNDLE_GEMFILE"] = ""
- in_app_root do
- script <<-RUBY
- gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- end
+ script <<-RUBY
+ gemfile do
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rack"
+ end
- puts RACK
- RUBY
- end
+ puts RACK
+ RUBY
expect(err).to be_empty
- expect(exitstatus).to be_zero if exitstatus
end
it "installs inline gems when BUNDLE_BIN is set" do
@@ -350,4 +354,67 @@ RSpec.describe "bundler/inline#gemfile" do
expect(last_command).to be_success
expect(out).to include("BUNDLE_GEMFILE is empty")
end
+
+ it "does not error out if library requires optional dependencies" do
+ Dir.mkdir tmp("path_without_gemfile")
+
+ foo_code = <<~RUBY
+ begin
+ gem "bar"
+ rescue LoadError
+ end
+
+ puts "WIN"
+ RUBY
+
+ build_lib "foo", "1.0.0" do |s|
+ s.write "lib/foo.rb", foo_code
+ end
+
+ script <<-RUBY, :dir => tmp("path_without_gemfile")
+ gemfile do
+ source "#{file_uri_for(gem_repo2)}"
+ path "#{lib_path}" do
+ gem "foo", require: false
+ end
+ end
+
+ require "foo"
+ RUBY
+
+ expect(out).to eq("WIN")
+ expect(err).to be_empty
+ end
+
+ it "when requiring fileutils after does not show redefinition warnings" do
+ dependency_installer_loads_fileutils = ruby "require 'rubygems/dependency_installer'; puts $LOADED_FEATURES.grep(/fileutils/)", :raise_on_error => false
+ skip "does not work if rubygems/dependency_installer loads fileutils, which happens until rubygems 3.2.0" unless dependency_installer_loads_fileutils.empty?
+
+ skip "pathname does not install cleanly on this ruby" if RUBY_VERSION < "2.7.0"
+
+ Dir.mkdir tmp("path_without_gemfile")
+
+ default_fileutils_version = ruby "gem 'fileutils', '< 999999'; require 'fileutils'; puts FileUtils::VERSION", :raise_on_error => false
+ skip "fileutils isn't a default gem" if default_fileutils_version.empty?
+
+ realworld_system_gems "fileutils --version 1.4.1"
+
+ realworld_system_gems "pathname --version 0.2.0"
+
+ realworld_system_gems "fiddle" # not sure why, but this is needed on Windows to boot rubygems successfully
+
+ realworld_system_gems "timeout uri" # this spec uses net/http which requires these default gems
+
+ script <<-RUBY, :dir => tmp("path_without_gemfile"), :env => { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+ require "bundler/inline"
+
+ gemfile(true) do
+ source "#{file_uri_for(gem_repo2)}"
+ end
+
+ require "fileutils"
+ RUBY
+
+ expect(err).to eq("The Gemfile specifies no dependencies")
+ end
end
diff --git a/spec/bundler/runtime/load_spec.rb b/spec/bundler/runtime/load_spec.rb
index 7de67e247c..96a22a46cc 100644
--- a/spec/bundler/runtime/load_spec.rb
+++ b/spec/bundler/runtime/load_spec.rb
@@ -3,10 +3,11 @@
RSpec.describe "Bundler.load" do
describe "with a gemfile" do
before(:each) do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
+ allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app)
end
it "provides a list of the env dependencies" do
@@ -31,7 +32,8 @@ RSpec.describe "Bundler.load" do
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- bundle! :install
+ bundle :install
+ allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app)
end
it "provides a list of the env dependencies" do
@@ -73,14 +75,14 @@ RSpec.describe "Bundler.load" do
describe "when called twice" do
it "doesn't try to load the runtime twice" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
gem "activesupport", :group => :test
G
- ruby! <<-RUBY
- require "#{lib_dir}/bundler"
+ ruby <<-RUBY
+ require "#{entrypoint}"
Bundler.setup :default
Bundler.require :default
puts RACK
@@ -97,11 +99,11 @@ 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
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "activerecord"
G
-
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
Bundler.load.specs.each do |spec|
expect(spec.to_yaml).not_to match(/^\s+source:/)
expect(spec.to_yaml).not_to match(/^\s+groups:/)
diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb
index f7e93eacf1..433396d106 100644
--- a/spec/bundler/runtime/platform_spec.rb
+++ b/spec/bundler/runtime/platform_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
ruby <<-R
begin
- require 'bundler'
+ require '#{entrypoint}'
Bundler.ui.silence { Bundler.setup }
rescue Bundler::GemNotFound => e
puts "WIN"
@@ -49,7 +49,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
G
simulate_platform "x86-darwin-10"
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri"
G
@@ -57,6 +57,126 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
expect(the_bundle).to include_gems "nokogiri 1.4.2"
end
+ it "will keep both platforms when both ruby and a specific ruby platform are locked and the bundle is unlocked" do
+ build_repo4 do
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.add_dependency "mini_portile2", "~> 2.5.0"
+ s.add_dependency "racc", "~> 1.5.2"
+ end
+
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.platform = Bundler.local_platform
+ s.add_dependency "racc", "~> 1.4"
+ end
+
+ build_gem "mini_portile2", "2.5.0"
+ build_gem "racc", "1.5.2"
+ end
+
+ good_lockfile = <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ mini_portile2 (2.5.0)
+ nokogiri (1.11.1)
+ mini_portile2 (~> 2.5.0)
+ racc (~> 1.5.2)
+ nokogiri (1.11.1-#{Bundler.local_platform})
+ racc (~> 1.4)
+ racc (1.5.2)
+
+ PLATFORMS
+ #{lockfile_platforms_for(["ruby"] + local_platforms)}
+
+ DEPENDENCIES
+ nokogiri (~> 1.11)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "nokogiri", "~> 1.11"
+ G
+
+ lockfile good_lockfile
+
+ bundle "update nokogiri"
+
+ expect(lockfile).to eq(good_lockfile)
+ end
+
+ it "will not try to install platform specific gems when they don't match the current ruby if locked only to ruby" do
+ build_repo4 do
+ build_gem "nokogiri", "1.11.1"
+
+ build_gem "nokogiri", "1.11.1" do |s|
+ s.platform = Bundler.local_platform
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gems.repo4"
+ gem "nokogiri"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gems.repo4/
+ specs:
+ nokogiri (1.11.1)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install", :artifice => "compact_index", :env => { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+
+ expect(out).to include("Fetching nokogiri 1.11.1")
+ expect(the_bundle).to include_gems "nokogiri 1.11.1"
+ expect(the_bundle).not_to include_gems "nokogiri 1.11.1 #{Bundler.local_platform}"
+ end
+
+ it "will use the java platform if both generic java and generic ruby platforms are locked", :jruby do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "nokogiri"
+ G
+
+ lockfile <<-G
+ GEM
+ remote: #{file_uri_for(gem_repo1)}/
+ specs:
+ nokogiri (1.4.2)
+ nokogiri (1.4.2-java)
+ weakling (>= 0.0.3)
+ weakling (0.0.3)
+
+ PLATFORMS
+ java
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ 2.1.4
+ G
+
+ bundle "install"
+
+ expect(out).to include("Fetching nokogiri 1.4.2 (java)")
+ expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA"
+ end
+
it "will add the resolve for the current platform" do
lockfile <<-G
GEM
@@ -75,7 +195,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
simulate_platform "x86-darwin-100"
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri"
gem "platform_specific"
@@ -84,40 +204,62 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100"
end
- it "allows specifying only-ruby-platform" do
- simulate_platform "java"
+ it "allows specifying only-ruby-platform on jruby", :jruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "nokogiri"
+ gem "platform_specific"
+ G
+
+ bundle "config set force_ruby_platform true"
- install_gemfile! <<-G
+ bundle "install"
+
+ expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY"
+ end
+
+ it "allows specifying only-ruby-platform" do
+ gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri"
gem "platform_specific"
G
- bundle! "config set force_ruby_platform true"
+ bundle "config set force_ruby_platform true"
- bundle! "install"
+ bundle "install"
expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY"
end
+ it "doesn't pull platform specific gems on truffleruby", :truffleruby do
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "platform_specific"
+ G
+
+ expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ end
+
it "allows specifying only-ruby-platform on windows with dependency platforms" do
simulate_windows do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "nokogiri", :platforms => [:mingw, :mswin, :x64_mingw, :jruby]
gem "platform_specific"
G
- bundle! "config set force_ruby_platform true"
+ bundle "config set force_ruby_platform true"
- bundle! "install"
+ bundle "install"
expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ expect(the_bundle).to not_include_gems "nokogiri"
end
end
it "allows specifying only-ruby-platform on windows with gemspec dependency" do
- build_lib("foo", "1.0", :path => ".") do |s|
+ build_lib("foo", "1.0", :path => bundled_app) do |s|
s.add_dependency "rack"
end
@@ -125,11 +267,11 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
source "#{file_uri_for(gem_repo1)}"
gemspec
G
- bundle! :lock
+ bundle :lock
simulate_windows do
- bundle! "config set force_ruby_platform true"
- bundle! "install"
+ bundle "config set force_ruby_platform true"
+ bundle "install"
expect(the_bundle).to include_gems "rack 1.0"
end
@@ -158,7 +300,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
requires_platform_specific
L
- install_gemfile! <<-G, :verbose => true
+ install_gemfile <<-G, :verbose => true
source "#{file_uri_for(gem_repo2)}"
gem "requires_platform_specific"
G
diff --git a/spec/bundler/runtime/require_spec.rb b/spec/bundler/runtime/require_spec.rb
index a8d7826123..d91b5f8666 100644
--- a/spec/bundler/runtime/require_spec.rb
+++ b/spec/bundler/runtime/require_spec.rb
@@ -46,6 +46,7 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem "one", :group => :bar, :require => %w[baz qux]
gem "two"
@@ -112,6 +113,7 @@ 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)}"
path "#{lib_path}" do
gem "two", :require => 'fail'
end
@@ -130,12 +132,13 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem "faulty"
end
G
- run "Bundler.require"
+ run "Bundler.require", :raise_on_error => false
expect(err).to match("error while trying to load the gem 'faulty'")
expect(err).to match("Gem Internal Error Message")
end
@@ -146,6 +149,7 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem "loadfuuu"
end
@@ -155,7 +159,7 @@ RSpec.describe "Bundler.require" do
begin
Bundler.require
rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR: \#{e.message}"
+ warn "ZOMG LOAD ERROR: \#{e.message}"
end
RUBY
run(cmd)
@@ -172,6 +176,7 @@ RSpec.describe "Bundler.require" do
it "requires gem names that are namespaced" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path '#{lib_path}' do
gem 'jquery-rails'
end
@@ -186,13 +191,15 @@ RSpec.describe "Bundler.require" do
s.write "lib/brcrypt.rb", "BCrypt = '1.0.0'"
end
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+
path "#{lib_path}" do
gem "bcrypt-ruby"
end
G
cmd = <<-RUBY
- require '#{lib_dir}/bundler'
+ require '#{entrypoint}'
Bundler.require
RUBY
ruby(cmd)
@@ -202,6 +209,7 @@ RSpec.describe "Bundler.require" do
it "does not mangle explicitly given requires" do
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem 'jquery-rails', :require => 'jquery-rails'
end
@@ -219,6 +227,7 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem "load-fuuu"
end
@@ -228,7 +237,7 @@ RSpec.describe "Bundler.require" do
begin
Bundler.require
rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR" if e.message.include?("Could not open library 'libfuuu-1.0'")
+ warn "ZOMG LOAD ERROR" if e.message.include?("Could not open library 'libfuuu-1.0'")
end
RUBY
run(cmd)
@@ -242,6 +251,7 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem "load-fuuu"
end
@@ -251,7 +261,7 @@ RSpec.describe "Bundler.require" do
begin
Bundler.require
rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR: \#{e.message}"
+ warn "ZOMG LOAD ERROR: \#{e.message}"
end
RUBY
run(cmd)
@@ -300,6 +310,7 @@ 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)}"
path "#{lib_path}" do
gem "two"
gem "one"
@@ -318,6 +329,7 @@ RSpec.describe "Bundler.require" do
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "multi_gem", :require => "one", :group => :one
gem "multi_gem", :require => "two", :group => :two
G
@@ -341,6 +353,7 @@ 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)}"
path "#{lib_path}" do
gem "one"
gem "two"
@@ -358,6 +371,7 @@ RSpec.describe "Bundler.require" do
end
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "busted_require"
G
@@ -370,12 +384,12 @@ RSpec.describe "Bundler.require" do
end
it "does not load rubygems gemspecs that are used" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- run! <<-R
+ run <<-R
path = File.join(Gem.dir, "specifications", "rack-1.0.0.gemspec")
contents = File.read(path)
contents = contents.lines.to_a.insert(-2, "\n raise 'broken gemspec'\n").join
@@ -384,7 +398,7 @@ RSpec.describe "Bundler.require" do
end
R
- run! <<-R
+ run <<-R
Bundler.require
puts "WIN"
R
@@ -395,11 +409,12 @@ RSpec.describe "Bundler.require" do
it "does not load git gemspecs that are used" do
build_git "foo"
- install_gemfile! <<-G
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- run! <<-R
+ run <<-R
path = Gem.loaded_specs["foo"].loaded_from
contents = File.read(path)
contents = contents.lines.to_a.insert(-2, "\n raise 'broken gemspec'\n").join
@@ -408,7 +423,7 @@ RSpec.describe "Bundler.require" do
end
R
- run! <<-R
+ run <<-R
Bundler.require
puts "WIN"
R
@@ -423,7 +438,7 @@ RSpec.describe "Bundler.require with platform specific dependencies" do
source "#{file_uri_for(gem_repo1)}"
platforms :#{not_local_tag} do
- gem "fail", :require => "omgomg"
+ gem "platform_specific", :require => "omgomg"
end
gem "rack", "1.0.0"
@@ -434,6 +449,8 @@ RSpec.describe "Bundler.require with platform specific dependencies" do
end
it "requires gems pinned to multiple platforms, including the current one" do
+ skip "platform issues" if Gem.win_platform?
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb
index 7f00a63078..35873dcaa9 100644
--- a/spec/bundler/runtime/setup_spec.rb
+++ b/spec/bundler/runtime/setup_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe "Bundler.setup" do
G
ruby <<-RUBY
- require '#{lib_dir}/bundler'
+ require 'bundler'
Bundler.setup
require 'rack'
@@ -34,7 +34,7 @@ RSpec.describe "Bundler.setup" do
it "doesn't make all groups available" do
ruby <<-RUBY
- require '#{lib_dir}/bundler'
+ require 'bundler'
Bundler.setup(:default)
begin
@@ -49,7 +49,7 @@ RSpec.describe "Bundler.setup" do
it "accepts string for group name" do
ruby <<-RUBY
- require '#{lib_dir}/bundler'
+ require 'bundler'
Bundler.setup(:default, 'test')
require 'rack'
@@ -61,7 +61,7 @@ RSpec.describe "Bundler.setup" do
it "leaves all groups available if they were already" do
ruby <<-RUBY
- require '#{lib_dir}/bundler'
+ require 'bundler'
Bundler.setup
Bundler.setup(:default)
@@ -74,7 +74,7 @@ RSpec.describe "Bundler.setup" do
it "leaves :default available if setup is called twice" do
ruby <<-RUBY
- require '#{lib_dir}/bundler'
+ require 'bundler'
Bundler.setup(:default)
Bundler.setup(:default, :test)
@@ -90,8 +90,8 @@ RSpec.describe "Bundler.setup" do
end
it "handles multiple non-additive invocations" do
- ruby <<-RUBY
- require '#{lib_dir}/bundler'
+ ruby <<-RUBY, :raise_on_error => false
+ require 'bundler'
Bundler.setup(:default, :test)
Bundler.setup(:default)
require 'rack'
@@ -107,9 +107,9 @@ RSpec.describe "Bundler.setup" do
context "load order" do
def clean_load_path(lp)
- without_bundler_load_path = ruby!("puts $LOAD_PATH").split("\n")
- lp -= without_bundler_load_path
- lp.map! {|p| p.sub(/^#{Regexp.union system_gem_path.to_s, default_bundle_path.to_s, lib_dir.to_s}/i, "") }
+ without_bundler_load_path = ruby("puts $LOAD_PATH").split("\n")
+ lp -= [*without_bundler_load_path, lib_dir.to_s]
+ lp.map! {|p| p.sub(system_gem_path.to_s, "") }
end
it "puts loaded gems after -I and RUBYLIB", :ruby_repo do
@@ -122,7 +122,7 @@ RSpec.describe "Bundler.setup" do
ENV["RUBYLIB"] = "rubylib_dir"
ruby <<-RUBY
- require '#{lib_dir}/bundler'
+ require 'bundler'
Bundler.setup
puts $LOAD_PATH
RUBY
@@ -136,15 +136,15 @@ RSpec.describe "Bundler.setup" do
end
it "orders the load path correctly when there are dependencies" do
- system_gems :bundler
+ bundle "config set path.system true"
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rails"
G
- ruby! <<-RUBY
- require '#{lib_dir}/bundler'
+ ruby <<-RUBY
+ require 'bundler'
Bundler.setup
puts $LOAD_PATH
RUBY
@@ -153,26 +153,27 @@ RSpec.describe "Bundler.setup" do
expect(load_path).to start_with(
"/gems/rails-2.3.2/lib",
- "/gems/bundler-#{Bundler::VERSION}/lib",
"/gems/activeresource-2.3.2/lib",
"/gems/activerecord-2.3.2/lib",
"/gems/actionpack-2.3.2/lib",
"/gems/actionmailer-2.3.2/lib",
"/gems/activesupport-2.3.2/lib",
- "/gems/rake-12.3.2/lib"
+ "/gems/rake-13.0.1/lib"
)
end
it "falls back to order the load path alphabetically for backwards compatibility" do
- install_gemfile! <<-G
+ bundle "config set path.system true"
+
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "weakling"
gem "duradura"
gem "terranova"
G
- ruby! <<-RUBY
- require '#{lib_dir}/bundler/setup'
+ ruby <<-RUBY
+ require 'bundler/setup'
puts $LOAD_PATH
RUBY
@@ -193,7 +194,7 @@ RSpec.describe "Bundler.setup" do
G
ruby <<-R
- require '#{lib_dir}/bundler'
+ require '#{entrypoint}'
begin
Bundler.setup
@@ -212,13 +213,13 @@ RSpec.describe "Bundler.setup" do
gem "rack"
G
- ruby <<-R
- require '#{lib_dir}/bundler'
+ ruby <<-R, :raise_on_error => false
+ require 'bundler'
Bundler.setup
R
- expect(bundled_app("Gemfile.lock")).not_to exist
+ expect(bundled_app_lock).not_to exist
end
it "doesn't change the Gemfile.lock if the setup fails" do
@@ -227,7 +228,7 @@ RSpec.describe "Bundler.setup" do
gem "rack"
G
- lockfile = File.read(bundled_app("Gemfile.lock"))
+ lockfile = File.read(bundled_app_lock)
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
@@ -235,13 +236,13 @@ RSpec.describe "Bundler.setup" do
gem "nosuchgem", "10.0"
G
- ruby <<-R
- require '#{lib_dir}/bundler'
+ ruby <<-R, :raise_on_error => false
+ require 'bundler'
Bundler.setup
R
- expect(File.read(bundled_app("Gemfile.lock"))).to eq(lockfile)
+ expect(File.read(bundled_app_lock)).to eq(lockfile)
end
it "makes a Gemfile.lock if setup succeeds" do
@@ -250,12 +251,12 @@ RSpec.describe "Bundler.setup" do
gem "rack"
G
- File.read(bundled_app("Gemfile.lock"))
+ File.read(bundled_app_lock)
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
run "1"
- expect(bundled_app("Gemfile.lock")).to exist
+ expect(bundled_app_lock).to exist
end
describe "$BUNDLE_GEMFILE" do
@@ -279,17 +280,17 @@ RSpec.describe "Bundler.setup" do
end
context "an absolute path is not provided" do
- it "uses BUNDLE_GEMFILE to locate the gemfile if present" do
+ it "uses BUNDLE_GEMFILE to locate the gemfile if present and doesn't fail in deployment mode" do
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
G
bundle "install"
- bundle "install --deployment"
+ bundle "config set --local deployment true"
ENV["BUNDLE_GEMFILE"] = "Gemfile"
ruby <<-R
- require '#{lib_dir}/bundler'
+ require 'bundler'
begin
Bundler.setup
@@ -429,12 +430,13 @@ RSpec.describe "Bundler.setup" do
build_git "rack", "1.0.0"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-1.0.0")}"
G
end
it "provides a useful exception when the git repo is not checked out yet" do
- run "1"
+ run "1", :raise_on_error => false
expect(err).to match(/the git source #{lib_path('rack-1.0.0')} is not yet checked out. Please run `bundle install`/i)
end
@@ -444,7 +446,7 @@ RSpec.describe "Bundler.setup" do
break_git!
ruby <<-R
- require '#{lib_dir}/bundler'
+ require 'bundler'
begin
Bundler.setup
@@ -460,12 +462,12 @@ RSpec.describe "Bundler.setup" do
it "provides a good exception if the lockfile is unavailable" do
bundle "install"
- FileUtils.rm(bundled_app("Gemfile.lock"))
+ FileUtils.rm(bundled_app_lock)
break_git!
ruby <<-R
- require "#{lib_dir}/bundler"
+ require "#{entrypoint}"
begin
Bundler.setup
@@ -475,29 +477,32 @@ RSpec.describe "Bundler.setup" do
end
R
- run "puts 'FAIL'"
+ run "puts 'FAIL'", :raise_on_error => false
expect(err).not_to include "This is not the git you are looking for"
end
it "works even when the cache directory has been deleted" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle :install
FileUtils.rm_rf vendored_gems("cache")
expect(the_bundle).to include_gems "rack 1.0.0"
end
it "does not randomly change the path when specifying --path and the bundle directory becomes read only" do
- bundle! :install, forgotten_command_line_options(:path => "vendor/bundle")
+ bundle "config set --local path vendor/bundle"
+ bundle :install
- with_read_only("**/*") do
+ with_read_only("#{bundled_app}/**/*") do
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
it "finds git gem when default bundle path becomes read only" do
+ bundle "config set --local path .bundle"
bundle "install"
- with_read_only("#{Bundler.bundle_path}/**/*") do
+ with_read_only("#{bundled_app(".bundle")}/**/*") do
expect(the_bundle).to include_gems "rack 1.0.0"
end
end
@@ -515,10 +520,10 @@ RSpec.describe "Bundler.setup" do
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle! :install
+ bundle :install
FileUtils.rm_rf(lib_path("local-rack"))
- run "require 'rack'"
+ run "require 'rack'", :raise_on_error => false
expect(err).to match(/Cannot use local override for rack-0.8 because #{Regexp.escape(lib_path('local-rack').to_s)} does not exist/)
end
@@ -533,14 +538,14 @@ RSpec.describe "Bundler.setup" do
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle! :install
+ bundle :install
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}"
G
- run "require 'rack'"
+ run "require 'rack'", :raise_on_error => false
expect(err).to match(/because :branch is not specified in Gemfile/)
end
@@ -555,14 +560,14 @@ RSpec.describe "Bundler.setup" do
G
bundle %(config set local.rack #{lib_path("local-rack")})
- bundle! :install
+ bundle :install
gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "changed"
G
- run "require 'rack'"
+ run "require 'rack'", :raise_on_error => false
expect(err).to match(/is using branch master but Gemfile specifies changed/)
end
@@ -582,14 +587,15 @@ RSpec.describe "Bundler.setup" do
G
bundle %(config set local.rack #{lib_path("local-rack")})
- run "require 'rack'"
+ run "require 'rack'", :raise_on_error => false
expect(err).to match(/is using branch master but Gemfile specifies nonexistant/)
end
end
describe "when excluding groups" do
it "doesn't change the resolve if --without is used" do
- install_gemfile <<-G, forgotten_command_line_options(:without => :rails)
+ bundle "config set --local without rails"
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
@@ -598,13 +604,14 @@ RSpec.describe "Bundler.setup" do
end
G
- install_gems "activesupport-2.3.5"
+ system_gems "activesupport-2.3.5"
expect(the_bundle).to include_gems "activesupport 2.3.2", :groups => :default
end
it "remembers --without and does not bail on bare Bundler.setup" do
- install_gemfile <<-G, forgotten_command_line_options(:without => :rails)
+ bundle "config set --local without rails"
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
@@ -613,13 +620,53 @@ RSpec.describe "Bundler.setup" do
end
G
- install_gems "activesupport-2.3.5"
+ system_gems "activesupport-2.3.5"
expect(the_bundle).to include_gems "activesupport 2.3.2"
end
+ it "remembers --without and does not bail on bare Bundler.setup, even in the case of path gems no longer available" do
+ bundle "config set --local without development"
+
+ path = bundled_app(File.join("vendor", "foo"))
+ build_lib "foo", :path => path
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "activesupport", "2.3.2"
+ gem 'foo', :path => 'vendor/foo', :group => :development
+ G
+
+ FileUtils.rm_rf(path)
+
+ ruby "require 'bundler'; Bundler.setup", :env => { "DEBUG" => "1" }
+ expect(out).to include("Assuming that source at `vendor/foo` has not changed since fetching its specs errored")
+ expect(out).to include("Found no changes, using resolution from the lockfile")
+ expect(err).to be_empty
+ end
+
+ it "doesn't re-resolve when a pre-release bundler is used and a dependency includes a dependency on bundler" do
+ system_gems "bundler-9.99.9.beta1"
+
+ build_repo4 do
+ build_gem "depends_on_bundler", "1.0" do |s|
+ s.add_dependency "bundler", ">= 1.5.0"
+ end
+ end
+
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "depends_on_bundler"
+ G
+
+ ruby "require '#{system_gem_path("gems/bundler-9.99.9.beta1/lib/bundler.rb")}'; Bundler.setup", :env => { "DEBUG" => "1" }
+ expect(out).to include("Found no changes, using resolution from the lockfile")
+ expect(err).to be_empty
+ end
+
it "remembers --without and does not include groups passed to Bundler.setup" do
- install_gemfile <<-G, forgotten_command_line_options(:without => :rails)
+ bundle "config set --local without rails"
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "activesupport"
@@ -659,12 +706,12 @@ RSpec.describe "Bundler.setup" do
end
it "does not load all gemspecs" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- run! <<-R
+ run <<-R
File.open(File.join(Gem.dir, "specifications", "broken.gemspec"), "w") do |f|
f.write <<-RUBY
# -*- encoding: utf-8 -*-
@@ -679,7 +726,7 @@ end
end
R
- run! <<-R
+ run <<-R
puts "WIN"
R
@@ -698,41 +745,68 @@ end
expect(err).to be_empty
end
- describe "$MANPATH" do
- before do
+ context "when the user has `MANPATH` set", :man do
+ before { ENV["MANPATH"] = "/foo#{File::PATH_SEPARATOR}" }
+
+ it "adds the gem's man dir to the MANPATH" do
build_repo4 do
build_gem "with_man" do |s|
s.write("man/man1/page.1", "MANPAGE")
end
end
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "with_man"
+ G
+
+ run "puts ENV['MANPATH']"
+ expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}#{File::PATH_SEPARATOR}/foo")
end
+ end
- context "when the user has one set" do
- before { ENV["MANPATH"] = "/foo:" }
+ context "when the user does not have `MANPATH` set", :man do
+ before { ENV.delete("MANPATH") }
- it "adds the gem's man dir to the MANPATH" do
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "with_man"
- G
+ it "adds the gem's man dir to the MANPATH, leaving : in the end so that system man pages still work" do
+ build_repo4 do
+ build_gem "with_man" do |s|
+ s.write("man/man1/page.1", "MANPAGE")
+ end
- run! "puts ENV['MANPATH']"
- expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}:/foo")
+ build_gem "with_man_overriding_system_man" do |s|
+ s.write("man/man1/ls.1", "LS MANPAGE")
+ end
end
- end
- context "when the user does not have one set" do
- before { ENV.delete("MANPATH") }
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "with_man"
+ G
- it "adds the gem's man dir to the MANPATH" do
- install_gemfile! <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "with_man"
- G
+ run <<~RUBY
+ puts ENV['MANPATH']
+ require "open3"
+ puts Open3.capture2e("man", "ls")[1].success?
+ RUBY
- run! "puts ENV['MANPATH']"
- expect(out).to eq(default_bundle_path("gems/with_man-1.0/man").to_s)
- end
+ expect(out).to eq("#{default_bundle_path("gems/with_man-1.0/man")}#{File::PATH_SEPARATOR}\ntrue")
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "with_man_overriding_system_man"
+ G
+
+ run <<~RUBY
+ puts ENV['MANPATH']
+ require "open3"
+ puts Open3.capture2e("man", "ls")[0]
+ RUBY
+
+ lines = out.split("\n")
+
+ expect(lines).to include("#{default_bundle_path("gems/with_man_overriding_system_man-1.0/man")}#{File::PATH_SEPARATOR}")
+ expect(lines).to include("LS MANPAGE")
end
end
@@ -759,22 +833,20 @@ end
full_gem_name = gem_name + "-1.0"
ext_dir = File.join(tmp("extensions", full_gem_name))
- install_gems full_gem_name
+ system_gems full_gem_name
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
G
ruby <<-R
- if Gem::Specification.method_defined? :extension_dir
- s = Gem::Specification.find_by_name '#{gem_name}'
- s.extension_dir = '#{ext_dir}'
+ s = Gem::Specification.find_by_name '#{gem_name}'
+ s.extension_dir = '#{ext_dir}'
- # Don't build extensions.
- s.class.send(:define_method, :build_extensions) { nil }
- end
+ # Don't build extensions.
+ s.class.send(:define_method, :build_extensions) { nil }
- require '#{lib_dir}/bundler'
+ require 'bundler'
gem '#{gem_name}'
puts $LOAD_PATH.count {|path| path =~ /#{gem_name}/} >= 2
@@ -793,13 +865,15 @@ end
let(:full_name) { "bundler-#{Bundler::VERSION}" }
before do
+ skip "symlink destination exists" if Gem.win_platform?
+
FileUtils.ln_sf(gem_home, symlinked_gem_home)
gems_dir = File.join(gem_home, "gems")
specifications_dir = File.join(gem_home, "specifications")
Dir.mkdir(gems_dir)
Dir.mkdir(specifications_dir)
- FileUtils.ln_s(root, File.join(gems_dir, full_name))
+ FileUtils.ln_s(source_root, File.join(gems_dir, full_name))
gemspec_content = File.binread(gemspec).
sub("Bundler::VERSION", %("#{Bundler::VERSION}")).
@@ -811,11 +885,11 @@ end
end
it "should not remove itself from the LOAD_PATH and require a different copy of 'bundler/setup'" do
- install_gemfile ""
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
- ruby <<-R, :env => { "GEM_PATH" => symlinked_gem_home }, :no_lib => true
+ ruby <<-R, :env => { "GEM_PATH" => symlinked_gem_home }
TracePoint.trace(:class) do |tp|
- if tp.path.include?("bundler") && !tp.path.start_with?("#{root}")
+ if tp.path.include?("bundler") && !tp.path.start_with?("#{source_root}")
puts "OMG. Defining a class from another bundler at \#{tp.path}:\#{tp.lineno}"
end
end
@@ -860,14 +934,13 @@ end
FileUtils.rm(File.join(path, "foo.gemspec"))
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', '1.2.3', :path => 'vendor/foo'
G
- Dir.chdir(bundled_app.parent) do
- run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app("Gemfile").to_s }
- require 'foo'
- R
- end
+ run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app_gemfile.to_s }, :dir => bundled_app.parent
+ require 'foo'
+ R
expect(err).to be_empty
end
@@ -882,16 +955,15 @@ end
FileUtils.rm(File.join(absolute_path, "foo.gemspec"))
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', '1.2.3', :path => '#{relative_path}'
G
bundle :install
- Dir.chdir(bundled_app.parent) do
- run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app("Gemfile").to_s }
- require 'foo'
- R
- end
+ run <<-R, :env => { "BUNDLE_GEMFILE" => bundled_app_gemfile.to_s }, :dir => bundled_app.parent
+ require 'foo'
+ R
expect(err).to be_empty
end
@@ -902,6 +974,7 @@ end
build_git "no_gemspec", :gemspec => false
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "no_gemspec", "1.0", :git => "#{lib_path("no_gemspec-1.0")}"
G
end
@@ -969,7 +1042,7 @@ end
describe "with system gems in the bundle" do
before :each do
- bundle! "config set path.system true"
+ bundle "config set path.system true"
system_gems "rack-1.0.0"
install_gemfile <<-G
@@ -1004,6 +1077,7 @@ end
end
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
end
@@ -1015,14 +1089,15 @@ end
end
it "error intelligently if the gemspec has a LoadError" do
+ skip "whitespace issue?" if Gem.win_platform?
+
ref = update_git "bar", :gemspec => false do |s|
s.write "bar.gemspec", "require 'foobarbaz'"
end.ref_for("HEAD")
- bundle :install
+ bundle :install, :raise_on_error => false
expect(err.lines.map(&:chomp)).to include(
a_string_starting_with("[!] There was an error while loading `bar.gemspec`:"),
- a_string_starting_with("Does it try to require a relative path? That's been removed in Ruby 1.9."),
" # from #{default_bundle_path "bundler", "gems", "bar-1.0-#{ref[0, 12]}", "bar.gemspec"}:1",
" > require 'foobarbaz'"
)
@@ -1032,7 +1107,7 @@ end
bundle "install"
ruby <<-RUBY
- require '#{lib_dir}/bundler'
+ require 'bundler'
bundler_module = class << Bundler; self; end
bundler_module.send(:remove_method, :require)
def Bundler.require(path)
@@ -1049,6 +1124,7 @@ end
describe "when Bundler is bundled" do
it "doesn't blow up" do
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem "bundler", :path => "#{root}"
G
@@ -1059,7 +1135,7 @@ end
describe "when BUNDLED WITH" do
def lock_with(bundler_version = nil)
- lock = <<-L
+ lock = <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -1073,13 +1149,15 @@ end
L
if bundler_version
- lock += "\n BUNDLED WITH\n #{bundler_version}\n"
+ lock += "\nBUNDLED WITH\n #{bundler_version}\n"
end
lock
end
before do
+ bundle "config set --local path.system true"
+
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
@@ -1089,26 +1167,27 @@ end
context "is not present" do
it "does not change the lock" do
lockfile lock_with(nil)
- ruby "require '#{lib_dir}/bundler/setup'"
- lockfile_should_be lock_with(nil)
+ ruby "require '#{entrypoint}/setup'"
+ expect(lockfile).to eq lock_with(nil)
end
end
context "is newer" do
it "does not change the lock or warn" do
lockfile lock_with(Bundler::VERSION.succ)
- ruby "require '#{lib_dir}/bundler/setup'"
+ ruby "require 'bundler/setup'"
expect(out).to be_empty
expect(err).to be_empty
- lockfile_should_be lock_with(Bundler::VERSION.succ)
+ expect(lockfile).to eq lock_with(Bundler::VERSION.succ)
end
end
context "is older" do
it "does not change the lock" do
+ system_gems "bundler-1.10.1"
lockfile lock_with("1.10.1")
- ruby "require '#{lib_dir}/bundler/setup'"
- lockfile_should_be lock_with("1.10.1")
+ ruby "require '#{entrypoint}/setup'"
+ expect(lockfile).to eq lock_with("1.10.1")
end
end
end
@@ -1117,7 +1196,7 @@ end
let(:ruby_version) { nil }
def lock_with(ruby_version = nil)
- lock = <<-L
+ lock = <<~L
GEM
remote: #{file_uri_for(gem_repo1)}/
specs:
@@ -1131,10 +1210,10 @@ end
L
if ruby_version
- lock += "\n RUBY VERSION\n ruby #{ruby_version}\n"
+ lock += "\nRUBY VERSION\n ruby #{ruby_version}\n"
end
- lock += <<-L
+ lock += <<~L
BUNDLED WITH
#{Bundler::VERSION}
@@ -1154,14 +1233,14 @@ end
context "is not present" do
it "does not change the lock" do
- expect { ruby! "require '#{lib_dir}/bundler/setup'" }.not_to change { lockfile }
+ expect { ruby "require 'bundler/setup'" }.not_to change { lockfile }
end
end
context "is newer" do
let(:ruby_version) { "5.5.5" }
it "does not change the lock or warn" do
- expect { ruby! "require '#{lib_dir}/bundler/setup'" }.not_to change { lockfile }
+ expect { ruby "require 'bundler/setup'" }.not_to change { lockfile }
expect(out).to be_empty
expect(err).to be_empty
end
@@ -1170,16 +1249,51 @@ end
context "is older" do
let(:ruby_version) { "1.0.0" }
it "does not change the lock" do
- expect { ruby! "require '#{lib_dir}/bundler/setup'" }.not_to change { lockfile }
+ expect { ruby "require 'bundler/setup'" }.not_to change { lockfile }
end
end
end
describe "with gemified standard libraries" do
+ it "does not load Digest", :ruby_repo do
+ skip "Only for Ruby 3.0+" unless RUBY_VERSION >= "3.0"
+
+ build_git "bar", :gemspec => false do |s|
+ s.write "lib/bar/version.rb", %(BAR_VERSION = '1.0')
+ s.write "bar.gemspec", <<-G
+ require_relative 'lib/bar/version'
+
+ Gem::Specification.new do |s|
+ s.name = 'bar'
+ s.version = BAR_VERSION
+ s.summary = 'Bar'
+ s.files = Dir["lib/**/*.rb"]
+ s.author = 'no one'
+
+ s.add_runtime_dependency 'digest'
+ end
+ G
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "bar", :git => "#{lib_path("bar-1.0")}"
+ G
+
+ bundle :install
+
+ ruby <<-RUBY
+ require '#{entrypoint}/setup'
+ puts defined?(::Digest) ? "Digest defined" : "Digest undefined"
+ require 'digest'
+ RUBY
+ expect(out).to eq("Digest undefined")
+ end
+
it "does not load Psych" do
- gemfile ""
+ gemfile "source \"#{file_uri_for(gem_repo1)}\""
ruby <<-RUBY
- require '#{lib_dir}/bundler/setup'
+ require '#{entrypoint}/setup'
puts defined?(Psych::VERSION) ? Psych::VERSION : "undefined"
require 'psych'
puts Psych::VERSION
@@ -1190,9 +1304,9 @@ end
end
it "does not load openssl" do
- install_gemfile! ""
- ruby! <<-RUBY
- require "#{lib_dir}/bundler/setup"
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ ruby <<-RUBY
+ require "bundler/setup"
puts defined?(OpenSSL) || "undefined"
require "openssl"
puts defined?(OpenSSL) || "undefined"
@@ -1202,11 +1316,19 @@ end
describe "default gem activation" do
let(:exemptions) do
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new("2.7")
+ exempts = if Gem.rubygems_version >= Gem::Version.new("2.7")
%w[did_you_mean]
else
%w[io-console openssl]
end << "bundler"
+ exempts << "fiddle" if Gem.win_platform? && Gem.rubygems_version >= Gem::Version.new("2.7")
+ exempts << "uri" if Gem.ruby_version >= Gem::Version.new("2.7")
+ exempts << "pathname" if Gem.ruby_version >= Gem::Version.new("3.0")
+ exempts << "set" unless Gem.rubygems_version >= Gem::Version.new("3.2.6")
+ exempts << "tsort" unless Gem.rubygems_version >= Gem::Version.new("3.2.31")
+ exempts << "error_highlight" # added in Ruby 3.1 as a default gem
+ exempts << "ruby2_keywords" # added in Ruby 3.1 as a default gem
+ exempts
end
let(:activation_warning_hack) { strip_whitespace(<<-RUBY) }
@@ -1243,23 +1365,25 @@ end
RUBY
it "activates no gems with -rbundler/setup" do
- install_gemfile! ""
- ruby! code, :env => { "RUBYOPT" => activation_warning_hack_rubyopt + " -r#{lib_dir}/bundler/setup" }
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ ruby code, :env => { "RUBYOPT" => activation_warning_hack_rubyopt + " -rbundler/setup" }
expect(out).to eq("{}")
end
it "activates no gems with bundle exec" do
- install_gemfile! ""
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
create_file("script.rb", code)
- bundle! "exec ruby ./script.rb", :env => { "RUBYOPT" => activation_warning_hack_rubyopt }
+ bundle "exec ruby ./script.rb", :env => { "RUBYOPT" => activation_warning_hack_rubyopt }
expect(out).to eq("{}")
end
it "activates no gems with bundle exec that is loaded" do
- install_gemfile! ""
+ skip "not executable" if Gem.win_platform?
+
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
create_file("script.rb", "#!/usr/bin/env ruby\n\n#{code}")
FileUtils.chmod(0o777, bundled_app("script.rb"))
- bundle! "exec ./script.rb", :artifice => nil, :env => { "RUBYOPT" => activation_warning_hack_rubyopt }
+ bundle "exec ./script.rb", :artifice => nil, :env => { "RUBYOPT" => activation_warning_hack_rubyopt }
expect(out).to eq("{}")
end
@@ -1268,31 +1392,31 @@ end
build_gem "net-http-pipeline", "1.0.1"
end
- system_gems "net-http-pipeline-1.0.1", :gem_repo => gem_repo4 do
- gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "net-http-pipeline", "1.0.1"
- G
+ system_gems "net-http-pipeline-1.0.1", :gem_repo => gem_repo4
- bundle "config set --local path vendor/bundle"
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "net-http-pipeline", "1.0.1"
+ G
- bundle! :install
+ bundle "config set --local path vendor/bundle"
- bundle! :check
+ bundle :install
- expect(out).to eq("The Gemfile's dependencies are satisfied")
- end
+ bundle :check
+
+ expect(out).to eq("The Gemfile's dependencies are satisfied")
end
Gem::Specification.select(&:default_gem?).map(&:name).each do |g|
- it "activates newer versions of #{g}" do
+ it "activates newer versions of #{g}", :ruby_repo do
skip if exemptions.include?(g)
build_repo4 do
build_gem g, "999999"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gem "#{g}", "999999"
G
@@ -1300,14 +1424,14 @@ end
expect(the_bundle).to include_gem("#{g} 999999", :env => { "RUBYOPT" => activation_warning_hack_rubyopt })
end
- it "activates older versions of #{g}" do
+ it "activates older versions of #{g}", :ruby_repo do
skip if exemptions.include?(g)
build_repo4 do
build_gem g, "0.0.0.a"
end
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gem "#{g}", "0.0.0.a"
G
@@ -1325,8 +1449,8 @@ end
gem "rack"
G
- ruby! <<-RUBY
- require "#{lib_dir}/bundler/setup"
+ ruby <<-RUBY
+ require "bundler/setup"
Object.new.gem "rack"
puts Gem.loaded_specs["rack"].full_name
RUBY
@@ -1335,13 +1459,13 @@ end
end
it "keeps Kernel#gem private", :bundler => "3" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- ruby <<-RUBY
- require "#{lib_dir}/bundler/setup"
+ ruby <<-RUBY, :raise_on_error => false
+ require "bundler/setup"
Object.new.gem "rack"
puts "FAIL"
RUBY
@@ -1351,13 +1475,13 @@ end
end
it "keeps Kernel#require private" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
gem "rack"
G
- ruby <<-RUBY
- require "#{lib_dir}/bundler/setup"
+ ruby <<-RUBY, :raise_on_error => false
+ require "bundler/setup"
Object.new.require "rack"
puts "FAIL"
RUBY
@@ -1367,9 +1491,48 @@ end
end
it "takes care of requiring rubygems" do
- sys_exec("#{Gem.ruby} -I#{lib_dir} -e \"puts require('bundler/setup')\"", "RUBYOPT" => "--disable=gems")
+ sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler/setup -e'puts true'", :env => { "RUBYOPT" => opt_add("--disable=gems", ENV["RUBYOPT"]) })
expect(last_command.stdboth).to eq("true")
end
+
+ it "memoizes initial set of specs when requiring bundler/setup, so that even if further code mutates dependencies, Bundler.definition.specs is not affected" do
+ install_gemfile <<~G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "yard"
+ gem "rack", :group => :test
+ G
+
+ ruby <<-RUBY, :raise_on_error => false
+ require "bundler/setup"
+ Bundler.require(:test).select! {|d| (d.groups & [:test]).any? }
+ puts Bundler.definition.specs.map(&:name).join(", ")
+ RUBY
+
+ expect(out).to include("rack, yard")
+ end
+
+ it "does not cause double loads when higher versions of default gems are activated before bundler" do
+ build_repo2 do
+ build_gem "json", "999.999.999" do |s|
+ s.write "lib/json.rb", <<~RUBY
+ module JSON
+ VERSION = "999.999.999"
+ end
+ RUBY
+ end
+ end
+
+ system_gems "json-999.999.999", :gem_repo => gem_repo2
+
+ install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ ruby <<-RUBY
+ require "json"
+ require "bundler/setup"
+ require "json"
+ RUBY
+
+ expect(err).to be_empty
+ end
end
end
diff --git a/spec/bundler/runtime/with_unbundled_env_spec.rb b/spec/bundler/runtime/with_unbundled_env_spec.rb
index 4aaf9d499c..731a9921a2 100644
--- a/spec/bundler/runtime/with_unbundled_env_spec.rb
+++ b/spec/bundler/runtime/with_unbundled_env_spec.rb
@@ -1,50 +1,58 @@
# frozen_string_literal: true
RSpec.describe "Bundler.with_env helpers" do
- def bundle_exec_ruby!(code, options = {})
+ def bundle_exec_ruby(args, options = {})
build_bundler_context options
- bundle! "exec '#{Gem.ruby}' -e #{code}", options
+ bundle "exec '#{Gem.ruby}' #{args}", options
end
def build_bundler_context(options = {})
bundle "config set path vendor/bundle"
- gemfile ""
+ gemfile "source \"#{file_uri_for(gem_repo1)}\""
bundle "install", options
end
+ def run_bundler_script(env, script)
+ system(env, "ruby", "-I#{lib_dir}", "-rbundler", script.to_s)
+ end
+
describe "Bundler.original_env" do
it "should return the PATH present before bundle was activated" do
- code = "print Bundler.original_env['PATH']"
+ create_file("source.rb", <<-RUBY)
+ print Bundler.original_env["PATH"]
+ RUBY
path = `getconf PATH`.strip + "#{File::PATH_SEPARATOR}/foo"
with_path_as(path) do
- bundle_exec_ruby!(code.dump)
+ bundle_exec_ruby(bundled_app("source.rb").to_s)
expect(last_command.stdboth).to eq(path)
end
end
it "should return the GEM_PATH present before bundle was activated" do
- code = "print Bundler.original_env['GEM_PATH']"
- gem_path = ENV["GEM_PATH"] + ":/foo"
+ create_file("source.rb", <<-RUBY)
+ print Bundler.original_env['GEM_PATH']
+ RUBY
+ gem_path = ENV["GEM_PATH"] + "#{File::PATH_SEPARATOR}/foo"
with_gem_path_as(gem_path) do
- bundle_exec_ruby!(code.dump)
+ bundle_exec_ruby(bundled_app("source.rb").to_s)
expect(last_command.stdboth).to eq(gem_path)
end
end
- it "works with nested bundle exec invocations" do
- create_file("exe.rb", <<-'RB')
+ it "works with nested bundle exec invocations", :ruby_repo do
+ create_file("exe.rb", <<-'RUBY')
count = ARGV.first.to_i
exit if count < 0
- STDERR.puts "#{count} #{ENV["PATH"].end_with?(":/foo")}"
+ STDERR.puts "#{count} #{ENV["PATH"].end_with?("#{File::PATH_SEPARATOR}/foo")}"
if count == 2
- ENV["PATH"] = "#{ENV["PATH"]}:/foo"
+ ENV["PATH"] = "#{ENV["PATH"]}#{File::PATH_SEPARATOR}/foo"
end
exec(Gem.ruby, __FILE__, (count - 1).to_s)
- RB
+ RUBY
path = `getconf PATH`.strip + File::PATH_SEPARATOR + File.dirname(Gem.ruby)
with_path_as(path) do
build_bundler_context
- bundle! "exec '#{Gem.ruby}' #{bundled_app("exe.rb")} 2"
+ bundle_exec_ruby("#{bundled_app("exe.rb")} 2")
end
expect(err).to eq <<-EOS.strip
2 false
@@ -57,41 +65,65 @@ RSpec.describe "Bundler.with_env helpers" 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")')
- code = 'puts Bundler.original_env.to_a.map {|e| e.join("=") }.sort.join("\n")'
- bundle_exec_ruby! code.dump
+ original = ruby('puts ENV.to_a.map {|e| e.join("=") }.sort.join("\n")')
+ create_file("source.rb", <<-RUBY)
+ puts Bundler.original_env.to_a.map {|e| e.join("=") }.sort.join("\n")
+ RUBY
+ bundle_exec_ruby bundled_app("source.rb")
expect(out).to eq original
end
end
shared_examples_for "an unbundling helper" do
it "should delete BUNDLE_PATH" do
- code = "print #{modified_env}.has_key?('BUNDLE_PATH')"
+ create_file("source.rb", <<-RUBY)
+ print #{modified_env}.has_key?('BUNDLE_PATH')
+ RUBY
ENV["BUNDLE_PATH"] = "./foo"
- bundle_exec_ruby! code.dump
+ bundle_exec_ruby bundled_app("source.rb")
expect(last_command.stdboth).to include "false"
end
- it "should remove '-rbundler/setup' from RUBYOPT" do
- code = "print #{modified_env}['RUBYOPT']"
- ENV["RUBYOPT"] = "-W2 -rbundler/setup #{ENV["RUBYOPT"]}"
- bundle_exec_ruby! code.dump, :env => { "BUNDLER_SPEC_DISABLE_DEFAULT_BUNDLER_GEM" => "true" }
+ it "should remove absolute path to 'bundler/setup' from RUBYOPT even if it was present in original env" do
+ create_file("source.rb", <<-RUBY)
+ print #{modified_env}['RUBYOPT']
+ RUBY
+ setup_require = "-r#{lib_dir}/bundler/setup"
+ ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 #{setup_require} #{ENV["RUBYOPT"]}"
+ simulate_bundler_version_when_missing_prerelease_default_gem_activation do
+ bundle_exec_ruby bundled_app("source.rb")
+ end
+ expect(last_command.stdboth).not_to include(setup_require)
+ end
+
+ it "should remove relative path to 'bundler/setup' from RUBYOPT even if it was present in original env" do
+ create_file("source.rb", <<-RUBY)
+ print #{modified_env}['RUBYOPT']
+ RUBY
+ ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 -rbundler/setup #{ENV["RUBYOPT"]}"
+ simulate_bundler_version_when_missing_prerelease_default_gem_activation do
+ bundle_exec_ruby bundled_app("source.rb")
+ end
expect(last_command.stdboth).not_to include("-rbundler/setup")
end
it "should restore RUBYLIB", :ruby_repo do
- code = "print #{modified_env}['RUBYLIB']"
+ create_file("source.rb", <<-RUBY)
+ print #{modified_env}['RUBYLIB']
+ RUBY
ENV["RUBYLIB"] = lib_dir.to_s + File::PATH_SEPARATOR + "/foo"
ENV["BUNDLER_ORIG_RUBYLIB"] = lib_dir.to_s + File::PATH_SEPARATOR + "/foo-original"
- bundle_exec_ruby! code.dump
+ bundle_exec_ruby bundled_app("source.rb")
expect(last_command.stdboth).to include("/foo-original")
end
it "should restore the original MANPATH" do
- code = "print #{modified_env}['MANPATH']"
+ create_file("source.rb", <<-RUBY)
+ print #{modified_env}['MANPATH']
+ RUBY
ENV["MANPATH"] = "/foo"
ENV["BUNDLER_ORIG_MANPATH"] = "/foo-original"
- bundle_exec_ruby! code.dump
+ bundle_exec_ruby bundled_app("source.rb")
expect(last_command.stdboth).to include("/foo-original")
end
end
@@ -111,7 +143,7 @@ RSpec.describe "Bundler.with_env helpers" do
describe "Bundler.with_original_env" do
it "should set ENV to original_env in the block" do
expected = Bundler.original_env
- actual = Bundler.with_original_env { ENV.to_hash }
+ actual = Bundler.with_original_env { Bundler::EnvironmentPreserver.env_to_hash(ENV) }
expect(actual).to eq(expected)
end
@@ -129,7 +161,7 @@ RSpec.describe "Bundler.with_env helpers" do
expected = Bundler.unbundled_env
actual = Bundler.ui.silence do
- Bundler.with_clean_env { ENV.to_hash }
+ Bundler.with_clean_env { Bundler::EnvironmentPreserver.env_to_hash(ENV) }
end
expect(actual).to eq(expected)
@@ -147,7 +179,7 @@ RSpec.describe "Bundler.with_env helpers" do
describe "Bundler.with_unbundled_env" do
it "should set ENV to unbundled_env in the block" do
expected = Bundler.unbundled_env
- actual = Bundler.with_unbundled_env { ENV.to_hash }
+ actual = Bundler.with_unbundled_env { Bundler::EnvironmentPreserver.env_to_hash(ENV) }
expect(actual).to eq(expected)
end
@@ -161,53 +193,53 @@ RSpec.describe "Bundler.with_env helpers" do
end
describe "Bundler.original_system" do
- let(:code) do
- <<~RUBY
- Bundler.original_system(%([ "\$BUNDLE_FOO" = "bar" ] && exit 42))
+ before do
+ create_file("source.rb", <<-'RUBY')
+ Bundler.original_system("ruby", "-e", "exit(42) if ENV['BUNDLE_FOO'] == 'bar'")
exit $?.exitstatus
RUBY
end
it "runs system inside with_original_env" do
- system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'")
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
expect($?.exitstatus).to eq(42)
end
end
describe "Bundler.clean_system", :bundler => 2 do
- let(:code) do
- <<~RUBY
- Bundler.ui.silence { Bundler.clean_system(%([ "\$BUNDLE_FOO" = "bar" ] || exit 42)) }
+ before do
+ create_file("source.rb", <<-'RUBY')
+ Bundler.ui.silence { Bundler.clean_system("ruby", "-e", "exit(42) unless ENV['BUNDLE_FOO'] == 'bar'") }
exit $?.exitstatus
RUBY
end
it "runs system inside with_clean_env" do
- system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'")
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
expect($?.exitstatus).to eq(42)
end
end
describe "Bundler.unbundled_system" do
- let(:code) do
- <<~RUBY
- Bundler.unbundled_system(%([ "\$BUNDLE_FOO" = "bar" ] || exit 42))
+ before do
+ create_file("source.rb", <<-'RUBY')
+ Bundler.unbundled_system("ruby", "-e", "exit(42) unless ENV['BUNDLE_FOO'] == 'bar'")
exit $?.exitstatus
RUBY
end
it "runs system inside with_unbundled_env" do
- system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'")
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
expect($?.exitstatus).to eq(42)
end
end
describe "Bundler.original_exec" do
- let(:code) do
- <<~RUBY
+ before do
+ create_file("source.rb", <<-'RUBY')
Process.fork do
exit Bundler.original_exec(%(test "\$BUNDLE_FOO" = "bar"))
end
@@ -221,14 +253,14 @@ RSpec.describe "Bundler.with_env helpers" do
it "runs exec inside with_original_env" do
skip "Fork not implemented" if Gem.win_platform?
- system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'")
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
expect($?.exitstatus).to eq(0)
end
end
describe "Bundler.clean_exec", :bundler => 2 do
- let(:code) do
- <<~RUBY
+ before do
+ create_file("source.rb", <<-'RUBY')
Process.fork do
exit Bundler.ui.silence { Bundler.clean_exec(%(test "\$BUNDLE_FOO" = "bar")) }
end
@@ -242,14 +274,14 @@ RSpec.describe "Bundler.with_env helpers" do
it "runs exec inside with_clean_env" do
skip "Fork not implemented" if Gem.win_platform?
- system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'")
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
expect($?.exitstatus).to eq(1)
end
end
describe "Bundler.unbundled_exec" do
- let(:code) do
- <<~RUBY
+ before do
+ create_file("source.rb", <<-'RUBY')
Process.fork do
exit Bundler.unbundled_exec(%(test "\$BUNDLE_FOO" = "bar"))
end
@@ -263,7 +295,7 @@ RSpec.describe "Bundler.with_env helpers" do
it "runs exec inside with_clean_env" do
skip "Fork not implemented" if Gem.win_platform?
- system({ "BUNDLE_FOO" => "bar" }, "ruby -I#{lib_dir} -rbundler -e '#{code}'")
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
expect($?.exitstatus).to eq(1)
end
end
diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb
index 0a49b46aaa..4d558b9907 100644
--- a/spec/bundler/spec_helper.rb
+++ b/spec/bundler/spec_helper.rb
@@ -1,10 +1,5 @@
# frozen_string_literal: true
-require_relative "support/path"
-
-$:.unshift Spec::Path.spec_dir.to_s
-$:.unshift Spec::Path.lib_dir.to_s
-
require "bundler/psyched_yaml"
require "bundler/vendored_fileutils"
require "bundler/vendored_uri"
@@ -15,17 +10,19 @@ if File.expand_path(__FILE__) =~ %r{([^\w/\.:\-])}
end
require "bundler"
-require "rspec"
+require "rspec/core"
+require "rspec/expectations"
+require "rspec/mocks"
+require "rspec/support/differ"
require_relative "support/builders"
+require_relative "support/build_metadata"
require_relative "support/filters"
require_relative "support/helpers"
require_relative "support/indexes"
require_relative "support/matchers"
-require_relative "support/parallel"
require_relative "support/permissions"
require_relative "support/platforms"
-require_relative "support/sometimes"
require_relative "support/sudo"
$debug = false
@@ -49,6 +46,8 @@ RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
config.example_status_persistence_file_path = ".rspec_status"
+ config.silence_filter_announcements = !ENV["TEST_ENV_NUMBER"].nil?
+
config.disable_monkey_patching!
# Since failures cause us to keep a bunch of long strings in memory, stop
@@ -59,9 +58,6 @@ RSpec.configure do |config|
config.bisect_runner = :shell
- original_wd = Dir.pwd
- original_env = ENV.to_hash
-
config.expect_with :rspec do |c|
c.syntax = :expect
end
@@ -70,61 +66,53 @@ RSpec.configure do |config|
mocks.allow_message_expectations_on_nil = false
end
- config.around :each do |example|
- if ENV["RUBY"]
- orig_ruby = Gem.ruby
- Gem.ruby = ENV["RUBY"]
- end
- example.run
- Gem.ruby = orig_ruby if ENV["RUBY"]
- end
-
config.before :suite do
+ Gem.ruby = ENV["RUBY"] if ENV["RUBY"]
+
require_relative "support/rubygems_ext"
- Spec::Rubygems.setup
- ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -r#{Spec::Path.spec_dir}/support/hax.rb"
+ Spec::Rubygems.test_setup
ENV["BUNDLE_SPEC_RUN"] = "true"
ENV["BUNDLE_USER_CONFIG"] = ENV["BUNDLE_USER_CACHE"] = ENV["BUNDLE_USER_PLUGIN"] = nil
+ ENV["RUBYGEMS_GEMDEPS"] = nil
+ ENV["XDG_CONFIG_HOME"] = nil
ENV["GEMRC"] = nil
# Don't wrap output in tests
ENV["THOR_COLUMNS"] = "10000"
- original_env = ENV.to_hash
-
- if ENV["RUBY"]
- FileUtils.cp_r Spec::Path.bindir, File.join(Spec::Path.root, "lib", "exe")
- end
+ extend(Spec::Helpers)
+ system_gems :bundler, :path => pristine_system_gem_path
end
config.before :all do
+ check_test_gems!
+
build_repo1
+
+ reset_paths!
end
config.around :each do |example|
- ENV.replace(original_env)
- reset!
- system_gems []
- in_app_root
- @command_executions = []
-
- Bundler.ui.silence { example.run }
-
- all_output = @command_executions.map(&:to_s_verbose).join("\n\n")
- if example.exception && !all_output.empty?
- warn all_output unless config.formatters.grep(RSpec::Core::Formatters::DocumentationFormatter).empty?
- message = example.exception.message + "\n\nCommands:\n#{all_output}"
- (class << example.exception; self; end).send(:define_method, :message) do
- message
+ begin
+ FileUtils.cp_r pristine_system_gem_path, system_gem_path
+
+ with_gem_path_as(system_gem_path) do
+ Bundler.ui.silence { example.run }
+
+ all_output = all_commands_output
+ if example.exception && !all_output.empty?
+ message = all_output + "\n" + example.exception.message
+ (class << example.exception; self; end).send(:define_method, :message) do
+ message
+ end
+ end
end
+ ensure
+ reset!
end
-
- Dir.chdir(original_wd)
end
config.after :suite do
- if ENV["RUBY"]
- FileUtils.rm_rf File.join(Spec::Path.root, "lib", "exe")
- end
+ FileUtils.rm_r Spec::Path.pristine_system_gem_path
end
end
diff --git a/spec/bundler/support/api_request_limit_hax.rb b/spec/bundler/support/api_request_limit_hax.rb
new file mode 100644
index 0000000000..37ff0203b3
--- /dev/null
+++ b/spec/bundler/support/api_request_limit_hax.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+if ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"]
+ require_relative "path"
+ require "bundler/source"
+ require "bundler/source/rubygems"
+
+ module Bundler
+ class Source
+ class Rubygems < Source
+ remove_const :API_REQUEST_LIMIT
+ API_REQUEST_LIMIT = ENV["BUNDLER_SPEC_API_REQUEST_LIMIT"].to_i
+ end
+ end
+ end
+end
diff --git a/spec/bundler/support/artifice/compact_index.rb b/spec/bundler/support/artifice/compact_index.rb
index 72abf26224..1b314e89ef 100644
--- a/spec/bundler/support/artifice/compact_index.rb
+++ b/spec/bundler/support/artifice/compact_index.rb
@@ -2,11 +2,13 @@
require_relative "endpoint"
-$LOAD_PATH.unshift Dir[base_system_gems.join("gems/compact_index*/lib")].first.to_s
+$LOAD_PATH.unshift Dir[Spec::Path.base_system_gems.join("gems/compact_index*/lib")].first.to_s
require "compact_index"
class CompactIndexAPI < Endpoint
helpers do
+ include Spec::Path
+
def load_spec(name, version, platform, gem_repo)
full_name = "#{name}-#{version}"
full_name += "-#{platform}" if platform != "ruby"
@@ -60,7 +62,7 @@ class CompactIndexAPI < Endpoint
body.byteslice(range)
end
- def gems(gem_repo = GEM_REPO)
+ def gems(gem_repo = default_gem_repo)
@gems ||= {}
@gems[gem_repo] ||= begin
specs = Bundler::Deprecate.skip_during do
@@ -78,12 +80,12 @@ class CompactIndexAPI < Endpoint
CompactIndex::Dependency.new(d.name, reqs)
end
checksum = begin
- Digest(:SHA256).file("#{GEM_REPO}/gems/#{spec.original_name}.gem").base64digest
+ Digest(:SHA256).file("#{gem_repo}/gems/#{spec.original_name}.gem").base64digest
rescue StandardError
nil
end
CompactIndex::GemVersion.new(spec.version.version, spec.platform.to_s, checksum, nil,
- deps, spec.required_ruby_version, spec.required_rubygems_version)
+ deps, spec.required_ruby_version.to_s, spec.required_rubygems_version.to_s)
end
CompactIndex::Gem.new(name, gem_versions)
end
@@ -100,7 +102,7 @@ class CompactIndexAPI < Endpoint
get "/versions" do
etag_response do
file = tmp("versions.list")
- file.delete if file.file?
+ FileUtils.rm_f(file)
file = CompactIndex::VersionsFile.new(file.to_s)
file.create(gems)
file.contents
diff --git a/spec/bundler/support/artifice/compact_index_concurrent_download.rb b/spec/bundler/support/artifice/compact_index_concurrent_download.rb
index 7f989a3f37..14c31f35a4 100644
--- a/spec/bundler/support/artifice/compact_index_concurrent_download.rb
+++ b/spec/bundler/support/artifice/compact_index_concurrent_download.rb
@@ -10,7 +10,7 @@ class CompactIndexConcurrentDownload < CompactIndexAPI
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions")
# Verify the original (empty) content hasn't been deleted, e.g. on a retry
- File.read(versions) == "" || raise("Original file should be present and empty")
+ File.binread(versions) == "" || raise("Original file should be present and empty")
# Verify this is only requested once for a partial download
env["HTTP_RANGE"] || raise("Missing Range header for expected partial download")
@@ -21,7 +21,7 @@ class CompactIndexConcurrentDownload < CompactIndexAPI
etag_response do
file = tmp("versions.list")
- file.delete if file.file?
+ FileUtils.rm_f(file)
file = CompactIndex::VersionsFile.new(file.to_s)
file.create(gems)
file.contents
diff --git a/spec/bundler/support/artifice/compact_index_creds_diff_host.rb b/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
index 6c3442e14b..cfe22c7f51 100644
--- a/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
+++ b/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
@@ -31,7 +31,7 @@ class CompactIndexCredsDiffHost < CompactIndexAPI
get "/no/creds/:id" do
if request.host.include?("diffhost") && !auth.provided?
- File.read("#{gem_repo1}/gems/#{params[:id]}")
+ File.binread("#{gem_repo1}/gems/#{params[:id]}")
end
end
end
diff --git a/spec/bundler/support/artifice/compact_index_extra.rb b/spec/bundler/support/artifice/compact_index_extra.rb
index 3a09afd06f..cec368276a 100644
--- a/spec/bundler/support/artifice/compact_index_extra.rb
+++ b/spec/bundler/support/artifice/compact_index_extra.rb
@@ -14,11 +14,11 @@ class CompactIndexExtra < CompactIndexAPI
end
get "/extra/specs.4.8.gz" do
- File.read("#{gem_repo2}/specs.4.8.gz")
+ File.binread("#{gem_repo2}/specs.4.8.gz")
end
get "/extra/prerelease_specs.4.8.gz" do
- File.read("#{gem_repo2}/prerelease_specs.4.8.gz")
+ File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
end
get "/extra/quick/Marshal.4.8/:id" do
@@ -26,11 +26,11 @@ class CompactIndexExtra < CompactIndexAPI
end
get "/extra/fetch/actual/gem/:id" do
- File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
end
get "/extra/gems/:id" do
- File.read("#{gem_repo2}/gems/#{params[:id]}")
+ File.binread("#{gem_repo2}/gems/#{params[:id]}")
end
end
diff --git a/spec/bundler/support/artifice/compact_index_extra_api.rb b/spec/bundler/support/artifice/compact_index_extra_api.rb
index 3c716763c0..5cc13421a8 100644
--- a/spec/bundler/support/artifice/compact_index_extra_api.rb
+++ b/spec/bundler/support/artifice/compact_index_extra_api.rb
@@ -14,7 +14,7 @@ class CompactIndexExtraApi < CompactIndexAPI
get "/extra/versions" do
etag_response do
file = tmp("versions.list")
- file.delete if file.file?
+ FileUtils.rm_f(file)
file = CompactIndex::VersionsFile.new(file.to_s)
file.create(gems(gem_repo4))
file.contents
@@ -29,11 +29,11 @@ class CompactIndexExtraApi < CompactIndexAPI
end
get "/extra/specs.4.8.gz" do
- File.read("#{gem_repo4}/specs.4.8.gz")
+ File.binread("#{gem_repo4}/specs.4.8.gz")
end
get "/extra/prerelease_specs.4.8.gz" do
- File.read("#{gem_repo4}/prerelease_specs.4.8.gz")
+ File.binread("#{gem_repo4}/prerelease_specs.4.8.gz")
end
get "/extra/quick/Marshal.4.8/:id" do
@@ -41,11 +41,11 @@ class CompactIndexExtraApi < CompactIndexAPI
end
get "/extra/fetch/actual/gem/:id" do
- File.read("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
end
get "/extra/gems/:id" do
- File.read("#{gem_repo4}/gems/#{params[:id]}")
+ File.binread("#{gem_repo4}/gems/#{params[:id]}")
end
end
diff --git a/spec/bundler/support/artifice/compact_index_partial_update.rb b/spec/bundler/support/artifice/compact_index_partial_update.rb
index 6e7c05d423..cb1c7b9481 100644
--- a/spec/bundler/support/artifice/compact_index_partial_update.rb
+++ b/spec/bundler/support/artifice/compact_index_partial_update.rb
@@ -18,19 +18,19 @@ class CompactIndexPartialUpdate < CompactIndexAPI
)
# Verify a cached copy of the versions file exists
- unless File.read(cached_versions_path).start_with?("created_at: ")
+ unless File.binread(cached_versions_path).start_with?("created_at: ")
raise("Cached versions file should be present and have content")
end
# Verify that a partial request is made, starting from the index of the
# final byte of the cached file.
- unless env["HTTP_RANGE"] == "bytes=#{File.read(cached_versions_path).bytesize - 1}-"
+ unless env["HTTP_RANGE"] == "bytes=#{File.binread(cached_versions_path).bytesize - 1}-"
raise("Range header should be present, and start from the index of the final byte of the cache.")
end
etag_response do
# Return the exact contents of the cache.
- File.read(cached_versions_path)
+ File.binread(cached_versions_path)
end
end
end
diff --git a/spec/bundler/support/artifice/compact_index_partial_update_no_etag_not_incremental.rb b/spec/bundler/support/artifice/compact_index_partial_update_no_etag_not_incremental.rb
new file mode 100644
index 0000000000..acf76dfbf0
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_partial_update_no_etag_not_incremental.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require_relative "compact_index"
+
+Artifice.deactivate
+
+class CompactIndexPartialUpdateNoEtagNotIncremental < CompactIndexAPI
+ def partial_update_no_etag
+ response_body = yield
+ headers "Surrogate-Control" => "max-age=2592000, stale-while-revalidate=60"
+ content_type "text/plain"
+ requested_range_for(response_body)
+ end
+
+ get "/versions" do
+ partial_update_no_etag do
+ file = tmp("versions.list")
+ FileUtils.rm_f(file)
+ file = CompactIndex::VersionsFile.new(file.to_s)
+ file.create(gems)
+ lines = file.contents([], :calculate_info_checksums => true).split("\n")
+ name, versions, checksum = lines.last.split(" ")
+
+ # shuffle versions so new versions are not appended to the end
+ [*lines[0..-2], [name, versions.split(",").reverse.join(","), checksum].join(" ")].join("\n")
+ end
+ end
+
+ get "/info/:name" do
+ partial_update_no_etag do
+ gem = gems.find {|g| g.name == params[:name] }
+ lines = CompactIndex.info(gem ? gem.versions : []).split("\n")
+
+ # shuffle versions so new versions are not appended to the end
+ [lines.first, lines.last, *lines[1..-2]].join("\n")
+ end
+ end
+end
+
+Artifice.activate_with(CompactIndexPartialUpdateNoEtagNotIncremental)
diff --git a/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb b/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb
index 788f9d6f99..bb616125bb 100644
--- a/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb
+++ b/spec/bundler/support/artifice/compact_index_range_not_satisfiable.rb
@@ -11,7 +11,7 @@ class CompactIndexRangeNotSatisfiable < CompactIndexAPI
else
etag_response do
file = tmp("versions.list")
- file.delete if file.file?
+ FileUtils.rm_f(file)
file = CompactIndex::VersionsFile.new(file.to_s)
file.create(gems)
file.contents
diff --git a/spec/bundler/support/artifice/compact_index_rate_limited.rb b/spec/bundler/support/artifice/compact_index_rate_limited.rb
index ba17476045..570105e2a0 100644
--- a/spec/bundler/support/artifice/compact_index_rate_limited.rb
+++ b/spec/bundler/support/artifice/compact_index_rate_limited.rb
@@ -7,7 +7,7 @@ Artifice.deactivate
class CompactIndexRateLimited < CompactIndexAPI
class RequestCounter
def self.queue
- @queue ||= Queue.new
+ @queue ||= Thread::Queue.new
end
def self.size
diff --git a/spec/bundler/support/artifice/endpoint.rb b/spec/bundler/support/artifice/endpoint.rb
index 7bca681e70..4a820e5a3f 100644
--- a/spec/bundler/support/artifice/endpoint.rb
+++ b/spec/bundler/support/artifice/endpoint.rb
@@ -1,16 +1,14 @@
# frozen_string_literal: true
require_relative "../path"
-require Spec::Path.lib_dir.join("bundler/deprecate")
-include Spec::Path
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra}-*/lib")].map(&:to_s))
+$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
require "artifice"
require "sinatra/base"
ALL_REQUESTS = [] # rubocop:disable Style/MutableConstant
-ALL_REQUESTS_MUTEX = Mutex.new
+ALL_REQUESTS_MUTEX = Thread::Mutex.new
at_exit do
if expected = ENV["BUNDLER_SPEC_ALL_REQUESTS"]
@@ -28,7 +26,6 @@ class Endpoint < Sinatra::Base
@all_requests ||= []
end
- GEM_REPO = Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"] || Spec::Path.gem_repo1)
set :raise_errors, true
set :show_exceptions, false
@@ -41,28 +38,46 @@ class Endpoint < Sinatra::Base
end
helpers do
- def dependencies_for(gem_names, gem_repo = GEM_REPO)
+ include Spec::Path
+
+ def default_gem_repo
+ if ENV["BUNDLER_SPEC_GEM_REPO"]
+ Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"])
+ else
+ case request.host
+ when "gem.repo1"
+ Spec::Path.gem_repo1
+ when "gem.repo2"
+ Spec::Path.gem_repo2
+ when "gem.repo3"
+ Spec::Path.gem_repo3
+ when "gem.repo4"
+ Spec::Path.gem_repo4
+ else
+ Spec::Path.gem_repo1
+ end
+ end
+ end
+
+ def dependencies_for(gem_names, gem_repo = default_gem_repo)
return [] if gem_names.nil? || gem_names.empty?
- require "#{Spec::Path.lib_dir}/bundler"
- Bundler::Deprecate.skip_during do
- all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename|
- Marshal.load(File.open(gem_repo.join(filename)).read)
- end.inject(:+)
-
- all_specs.map do |name, version, platform|
- spec = load_spec(name, version, platform, gem_repo)
- next unless gem_names.include?(spec.name)
- {
- :name => spec.name,
- :number => spec.version.version,
- :platform => spec.platform.to_s,
- :dependencies => spec.dependencies.select {|dep| dep.type == :runtime }.map do |dep|
- [dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")]
- end,
- }
- end.compact
- end
+ all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename|
+ Marshal.load(File.open(gem_repo.join(filename)).read)
+ end.inject(:+)
+
+ all_specs.map do |name, version, platform|
+ spec = load_spec(name, version, platform, gem_repo)
+ next unless gem_names.include?(spec.name)
+ {
+ :name => spec.name,
+ :number => spec.version.version,
+ :platform => spec.platform.to_s,
+ :dependencies => spec.dependencies.select {|dep| dep.type == :runtime }.map do |dep|
+ [dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")]
+ end,
+ }
+ end.compact
end
def load_spec(name, version, platform, gem_repo)
@@ -77,11 +92,11 @@ class Endpoint < Sinatra::Base
end
get "/fetch/actual/gem/:id" do
- File.read("#{GEM_REPO}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{default_gem_repo}/quick/Marshal.4.8/#{params[:id]}")
end
get "/gems/:id" do
- File.read("#{GEM_REPO}/gems/#{params[:id]}")
+ File.binread("#{default_gem_repo}/gems/#{params[:id]}")
end
get "/api/v1/dependencies" do
@@ -89,11 +104,11 @@ class Endpoint < Sinatra::Base
end
get "/specs.4.8.gz" do
- File.read("#{GEM_REPO}/specs.4.8.gz")
+ File.binread("#{default_gem_repo}/specs.4.8.gz")
end
get "/prerelease_specs.4.8.gz" do
- File.read("#{GEM_REPO}/prerelease_specs.4.8.gz")
+ File.binread("#{default_gem_repo}/prerelease_specs.4.8.gz")
end
end
diff --git a/spec/bundler/support/artifice/endpoint_500.rb b/spec/bundler/support/artifice/endpoint_500.rb
index f98e7e3bc2..0ce8dfeaad 100644
--- a/spec/bundler/support/artifice/endpoint_500.rb
+++ b/spec/bundler/support/artifice/endpoint_500.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
require_relative "../path"
-include Spec::Path
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra}-*/lib")].map(&:to_s))
+$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
require "artifice"
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 f20ef74ac6..8b8972cedd 100644
--- a/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
+++ b/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
@@ -31,7 +31,7 @@ class EndpointCredsDiffHost < Endpoint
get "/no/creds/:id" do
if request.host.include?("diffhost") && !auth.provided?
- File.read("#{gem_repo1}/gems/#{params[:id]}")
+ File.binread("#{gem_repo1}/gems/#{params[:id]}")
end
end
end
diff --git a/spec/bundler/support/artifice/endpoint_extra.rb b/spec/bundler/support/artifice/endpoint_extra.rb
index 31f6822161..942c4352b7 100644
--- a/spec/bundler/support/artifice/endpoint_extra.rb
+++ b/spec/bundler/support/artifice/endpoint_extra.rb
@@ -10,11 +10,11 @@ class EndpointExtra < Endpoint
end
get "/extra/specs.4.8.gz" do
- File.read("#{gem_repo2}/specs.4.8.gz")
+ File.binread("#{gem_repo2}/specs.4.8.gz")
end
get "/extra/prerelease_specs.4.8.gz" do
- File.read("#{gem_repo2}/prerelease_specs.4.8.gz")
+ File.binread("#{gem_repo2}/prerelease_specs.4.8.gz")
end
get "/extra/quick/Marshal.4.8/:id" do
@@ -22,11 +22,11 @@ class EndpointExtra < Endpoint
end
get "/extra/fetch/actual/gem/:id" do
- File.read("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{gem_repo2}/quick/Marshal.4.8/#{params[:id]}")
end
get "/extra/gems/:id" do
- File.read("#{gem_repo2}/gems/#{params[:id]}")
+ File.binread("#{gem_repo2}/gems/#{params[:id]}")
end
end
diff --git a/spec/bundler/support/artifice/endpoint_extra_api.rb b/spec/bundler/support/artifice/endpoint_extra_api.rb
index 213b8e5895..1cfef7a7fc 100644
--- a/spec/bundler/support/artifice/endpoint_extra_api.rb
+++ b/spec/bundler/support/artifice/endpoint_extra_api.rb
@@ -11,11 +11,11 @@ class EndpointExtraApi < Endpoint
end
get "/extra/specs.4.8.gz" do
- File.read("#{gem_repo4}/specs.4.8.gz")
+ File.binread("#{gem_repo4}/specs.4.8.gz")
end
get "/extra/prerelease_specs.4.8.gz" do
- File.read("#{gem_repo4}/prerelease_specs.4.8.gz")
+ File.binread("#{gem_repo4}/prerelease_specs.4.8.gz")
end
get "/extra/quick/Marshal.4.8/:id" do
@@ -23,11 +23,11 @@ class EndpointExtraApi < Endpoint
end
get "/extra/fetch/actual/gem/:id" do
- File.read("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
+ File.binread("#{gem_repo4}/quick/Marshal.4.8/#{params[:id]}")
end
get "/extra/gems/:id" do
- File.read("#{gem_repo4}/gems/#{params[:id]}")
+ File.binread("#{gem_repo4}/gems/#{params[:id]}")
end
end
diff --git a/spec/bundler/support/artifice/endopint_marshal_fail_basic_authentication.rb b/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb
index c341c3993f..c341c3993f 100644
--- a/spec/bundler/support/artifice/endopint_marshal_fail_basic_authentication.rb
+++ b/spec/bundler/support/artifice/endpoint_marshal_fail_basic_authentication.rb
diff --git a/spec/bundler/support/artifice/endpoint_mirror_source.rb b/spec/bundler/support/artifice/endpoint_mirror_source.rb
index 318866e420..788a9027f3 100644
--- a/spec/bundler/support/artifice/endpoint_mirror_source.rb
+++ b/spec/bundler/support/artifice/endpoint_mirror_source.rb
@@ -5,7 +5,7 @@ require_relative "endpoint"
class EndpointMirrorSource < Endpoint
get "/gems/:id" do
if request.env["HTTP_X_GEMFILE_SOURCE"] == "https://server.example.org/"
- File.read("#{gem_repo1}/gems/#{params[:id]}")
+ File.binread("#{gem_repo1}/gems/#{params[:id]}")
else
halt 500
end
diff --git a/spec/bundler/support/artifice/fail.rb b/spec/bundler/support/artifice/fail.rb
index 1059c6df4e..f69f2eccc6 100644
--- a/spec/bundler/support/artifice/fail.rb
+++ b/spec/bundler/support/artifice/fail.rb
@@ -1,11 +1,6 @@
# frozen_string_literal: true
require "net/http"
-begin
- require "net/https"
-rescue LoadError
- nil # net/https or openssl
-end
# We can't use artifice here because it uses rack
diff --git a/spec/bundler/support/artifice/vcr.rb b/spec/bundler/support/artifice/vcr.rb
index a46f8e9391..0d51201bef 100644
--- a/spec/bundler/support/artifice/vcr.rb
+++ b/spec/bundler/support/artifice/vcr.rb
@@ -31,7 +31,6 @@ class BundlerVCRHTTP < Net::HTTP
def recorded_response?
return true if ENV["BUNDLER_SPEC_PRE_RECORDED"]
- return false if ENV["BUNDLER_SPEC_FORCE_RECORD"]
request_pair_paths.all? {|f| File.exist?(f) }
end
@@ -40,7 +39,7 @@ class BundlerVCRHTTP < Net::HTTP
response_io = ::Net::BufferedIO.new(response_file)
::Net::HTTPResponse.read_new(response_io).tap do |response|
response.decode_content = request.decode_content if request.respond_to?(:decode_content)
- response.uri = request.uri if request.respond_to?(:uri)
+ response.uri = request.uri
response.reading_body(response_io, request.response_body_permitted?) do
response_block.call(response) if response_block
@@ -57,6 +56,7 @@ class BundlerVCRHTTP < Net::HTTP
response = http.request_without_vcr(request, body, &response_block)
@recording = false
unless @recording
+ require "fileutils"
FileUtils.mkdir_p(File.dirname(request_path))
binwrite(request_path, request_to_string(request))
binwrite(response_path, response_to_string(response))
@@ -79,7 +79,7 @@ class BundlerVCRHTTP < Net::HTTP
end
def read_stored_request(path)
- contents = File.read(path)
+ contents = File.binread(path)
headers = {}
method = nil
path = nil
@@ -133,6 +133,19 @@ class BundlerVCRHTTP < Net::HTTP
end
end
+ def start_with_vcr
+ if ENV["BUNDLER_SPEC_PRE_RECORDED"]
+ raise IOError, "HTTP session already opened" if @started
+ @socket = nil
+ @started = true
+ else
+ start_without_vcr
+ end
+ end
+
+ alias_method :start_without_vcr, :start
+ alias_method :start, :start_with_vcr
+
def request_with_vcr(request, *args, &block)
handler = request.instance_eval do
remove_instance_variable(:@__vcr_request_handler) if defined?(@__vcr_request_handler)
diff --git a/spec/bundler/support/artifice/windows.rb b/spec/bundler/support/artifice/windows.rb
index 21170c81d9..ddbbd62b96 100644
--- a/spec/bundler/support/artifice/windows.rb
+++ b/spec/bundler/support/artifice/windows.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
require_relative "../path"
-include Spec::Path
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra}-*/lib")].map(&:to_s))
+$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gems.join("gems/{artifice,mustermann,rack,tilt,sinatra,ruby2_keywords}-*/lib")].map(&:to_s))
require "artifice"
require "sinatra/base"
@@ -15,7 +14,7 @@ class Windows < Sinatra::Base
set :show_exceptions, false
helpers do
- def gem_repo
+ def default_gem_repo
Pathname.new(ENV["BUNDLER_SPEC_GEM_REPO"] || Spec::Path.gem_repo1)
end
end
@@ -27,7 +26,7 @@ class Windows < Sinatra::Base
files.each do |file|
get "/#{file}" do
- File.binread gem_repo.join(file)
+ File.binread default_gem_repo.join(file)
end
end
diff --git a/spec/bundler/support/build_metadata.rb b/spec/bundler/support/build_metadata.rb
new file mode 100644
index 0000000000..98d8ac23c8
--- /dev/null
+++ b/spec/bundler/support/build_metadata.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require_relative "path"
+require_relative "helpers"
+
+module Spec
+ module BuildMetadata
+ include Spec::Path
+ include Spec::Helpers
+
+ def write_build_metadata(dir: source_root)
+ build_metadata = {
+ :git_commit_sha => git_commit_sha,
+ :built_at => loaded_gemspec.date.utc.strftime("%Y-%m-%d"),
+ :release => true,
+ }
+
+ replace_build_metadata(build_metadata, dir: dir) # rubocop:disable Style/HashSyntax
+ end
+
+ def reset_build_metadata(dir: source_root)
+ build_metadata = {
+ :release => false,
+ }
+
+ replace_build_metadata(build_metadata, dir: dir) # rubocop:disable Style/HashSyntax
+ end
+
+ private
+
+ def replace_build_metadata(build_metadata, dir:)
+ build_metadata_file = File.expand_path("lib/bundler/build_metadata.rb", dir)
+
+ ivars = build_metadata.sort.map do |k, v|
+ " @#{k} = #{loaded_gemspec.send(:ruby_code, v)}"
+ end.join("\n")
+
+ contents = File.read(build_metadata_file)
+ contents.sub!(/^(\s+# begin ivars).+(^\s+# end ivars)/m, "\\1\n#{ivars}\n\\2")
+ File.open(build_metadata_file, "w") {|f| f << contents }
+ end
+
+ def git_commit_sha
+ ruby_core_tarball? ? "unknown" : sys_exec("git rev-parse --short HEAD", :dir => source_root).strip
+ end
+
+ extend self
+ end
+end
diff --git a/spec/bundler/support/builders.rb b/spec/bundler/support/builders.rb
index b3f5f9b876..90e9cbb242 100644
--- a/spec/bundler/support/builders.rb
+++ b/spec/bundler/support/builders.rb
@@ -17,8 +17,29 @@ module Spec
Gem::Platform.new(platform)
end
+ # Returns a number smaller than the size of the index. Useful for specs that
+ # need the API request limit to be reached for some reason.
+ def low_api_request_limit_for(gem_repo)
+ all_gems = Dir[gem_repo.join("gems/*.gem")]
+
+ all_gem_names = all_gems.map do |file|
+ File.basename(file, ".gem").match(/\A(?<gem_name>[^-]+)-.*\z/)[:gem_name]
+ end.uniq
+
+ (all_gem_names - ["bundler"]).size
+ end
+
def build_repo1
+ rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first
+
build_repo gem_repo1 do
+ FileUtils.cp rake_path, "#{gem_repo1}/gems/"
+
+ build_gem "coffee-script-source"
+ build_gem "git"
+ build_gem "puma"
+ build_gem "minitest"
+
build_gem "rack", %w[0.9.1 1.0.0] do |s|
s.executables = "rackup"
s.post_install_message = "Rack's post install message"
@@ -40,7 +61,7 @@ module Spec
build_gem "rails", "2.3.2" do |s|
s.executables = "rails"
- s.add_dependency "rake", "12.3.2"
+ s.add_dependency "rake", "13.0.1"
s.add_dependency "actionpack", "2.3.2"
s.add_dependency "activerecord", "2.3.2"
s.add_dependency "actionmailer", "2.3.2"
@@ -64,14 +85,6 @@ module Spec
s.add_dependency "activesupport", ">= 2.0.0"
end
- build_gem "rails_fail" do |s|
- s.add_dependency "activesupport", "= 1.2.3"
- end
-
- build_gem "missing_dep" do |s|
- s.add_dependency "not_here"
- end
-
build_gem "rspec", "1.2.7", :no_default => true do |s|
s.write "lib/spec.rb", "SPEC = '1.2.7'"
end
@@ -146,49 +159,6 @@ module Spec
build_gem "duradura", "7.0"
- build_gem "multiple_versioned_deps" do |s|
- s.add_dependency "weakling", ">= 0.0.1", "< 0.1"
- end
-
- build_gem "not_released", "1.0.pre"
-
- build_gem "has_prerelease", "1.0"
- build_gem "has_prerelease", "1.1.pre"
-
- build_gem "with_development_dependency" do |s|
- s.add_development_dependency "activesupport", "= 2.3.5"
- end
-
- build_gem "with_license" do |s|
- s.license = "MIT"
- end
-
- build_gem "with_implicit_rake_dep" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("../lib", __FILE__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/implicit_rake_dep.rb", "w") do |f|
- f.puts "IMPLICIT_RAKE_DEP = 'YES'"
- end
- end
- RUBY
- end
-
- build_gem "another_implicit_rake_dep" do |s|
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("../lib", __FILE__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/another_implicit_rake_dep.rb", "w") do |f|
- f.puts "ANOTHER_IMPLICIT_RAKE_DEP = 'YES'"
- end
- end
- RUBY
- end
-
build_gem "very_simple_binary", &:add_c_extension
build_gem "simple_binary", &:add_c_extension
@@ -203,10 +173,6 @@ module Spec
s.write "lib/rubygems_plugin.rb", "require 'bundler/omg' ; puts 'FAIL'"
end
- build_gem "bundler_dep" do |s|
- s.add_dependency "bundler"
- end
-
# The yard gem iterates over Gem.source_index looking for plugins
build_gem "yard" do |s|
s.write "lib/yard.rb", <<-Y
@@ -216,92 +182,12 @@ module Spec
Y
end
- # The rcov gem is platform mswin32, but has no arch
- build_gem "rcov" do |s|
- s.platform = Gem::Platform.new([nil, "mswin32", nil])
- s.write "lib/rcov.rb", "RCOV = '1.0.0'"
- end
-
build_gem "net-ssh"
build_gem "net-sftp", "1.1.1" do |s|
s.add_dependency "net-ssh", ">= 1.0.0", "< 1.99.0"
end
- # Test complicated gem dependencies for install
- build_gem "net_a" do |s|
- s.add_dependency "net_b"
- s.add_dependency "net_build_extensions"
- end
-
- build_gem "net_b"
-
- build_gem "net_build_extensions" do |s|
- s.add_dependency "rake"
- s.extensions << "Rakefile"
- s.write "Rakefile", <<-RUBY
- task :default do
- path = File.expand_path("../lib", __FILE__)
- FileUtils.mkdir_p(path)
- File.open("\#{path}/net_build_extensions.rb", "w") do |f|
- f.puts "NET_BUILD_EXTENSIONS = 'YES'"
- end
- end
- RUBY
- end
-
- build_gem "net_c" do |s|
- s.add_dependency "net_a"
- s.add_dependency "net_d"
- end
-
- build_gem "net_d"
-
- build_gem "net_e" do |s|
- s.add_dependency "net_d"
- end
-
- # Capistrano did this (at least until version 2.5.10)
- # RubyGems 2.2 doesn't allow the specifying of a dependency twice
- # See https://github.com/rubygems/rubygems/commit/03dbac93a3396a80db258d9bc63500333c25bd2f
- build_gem "double_deps", "1.0", :skip_validation => true do |s|
- s.add_dependency "net-ssh", ">= 1.0.0"
- s.add_dependency "net-ssh"
- end
-
build_gem "foo"
-
- # A minimal fake pry console
- build_gem "pry" do |s|
- s.write "lib/pry.rb", <<-RUBY
- class Pry
- class << self
- def toplevel_binding
- unless defined?(@toplevel_binding) && @toplevel_binding
- TOPLEVEL_BINDING.eval %{
- def self.__pry__; binding; end
- Pry.instance_variable_set(:@toplevel_binding, __pry__)
- class << self; undef __pry__; end
- }
- end
- @toplevel_binding.eval('private')
- @toplevel_binding
- end
-
- def __pry__
- while line = gets
- begin
- puts eval(line, toplevel_binding).inspect.sub(/^"(.*)"$/, '=> \\1')
- rescue Exception => e
- puts "\#{e.class}: \#{e.message}"
- puts e.backtrace.first
- end
- end
- end
- alias start __pry__
- end
- end
- RUBY
- end
end
end
@@ -311,13 +197,6 @@ module Spec
update_repo2(&blk) if block_given?
end
- def build_repo3
- build_repo gem_repo3 do
- build_gem "rack"
- end
- FileUtils.rm_rf Dir[gem_repo3("prerelease*")]
- end
-
# A repo that has no pre-installed gems included. (The caller completely
# determines the contents with the block.)
def build_repo4(&blk)
@@ -331,9 +210,6 @@ module Spec
def update_repo2
update_repo gem_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
- end
yield if block_given?
end
end
@@ -355,22 +231,24 @@ module Spec
def build_repo(path, &blk)
return if File.directory?(path)
+
+ FileUtils.mkdir_p("#{path}/gems")
+
+ update_repo(path, &blk)
+ end
+
+ def check_test_gems!
rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first
if rake_path.nil?
- Spec::Path.base_system_gems.rmtree
- Spec::Rubygems.setup
+ FileUtils.rm_rf(Path.base_system_gems)
+ Spec::Rubygems.install_test_deps
rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first
end
- if rake_path
- FileUtils.mkdir_p("#{path}/gems")
- FileUtils.cp rake_path, "#{path}/gems/"
- else
+ if rake_path.nil?
abort "Your test gems are missing! Run `rm -rf #{tmp}` and try again."
end
-
- update_repo(path, &blk)
end
def update_repo(path)
@@ -382,7 +260,7 @@ module Spec
@_build_repo = File.basename(path)
yield
with_gem_path_as Path.base_system_gems do
- Dir.chdir(path) { gem_command! :generate_index }
+ gem_command :generate_index, :dir => path
end
ensure
@_build_path = nil
@@ -424,20 +302,20 @@ module Spec
opts = args.last.is_a?(Hash) ? args.last : {}
builder = opts[:bare] ? GitBareBuilder : GitBuilder
spec = build_with(builder, name, args, &block)
- GitReader.new(opts[:path] || lib_path(spec.full_name))
+ GitReader.new(self, opts[:path] || lib_path(spec.full_name))
end
def update_git(name, *args, &block)
opts = args.last.is_a?(Hash) ? args.last : {}
spec = build_with(GitUpdater, name, args, &block)
- GitReader.new(opts[:path] || lib_path(spec.full_name))
+ GitReader.new(self, opts[:path] || lib_path(spec.full_name))
end
def build_plugin(name, *args, &blk)
build_with(PluginBuilder, name, args, &blk)
end
- private
+ private
def build_with(builder, name, args, &blk)
@_build_path ||= nil
@@ -451,7 +329,6 @@ module Spec
Array(versions).each do |version|
spec = builder.new(self, name, version)
- spec.authors = ["no one"] if !spec.authors || spec.authors.empty?
yield spec if block_given?
spec._build(options)
end
@@ -599,15 +476,6 @@ module Spec
def @spec.validate(*); end
end
- case options[:gemspec]
- when false
- # do nothing
- when :yaml
- @files["#{name}.gemspec"] = @spec.to_yaml
- else
- @files["#{name}.gemspec"] = @spec.to_ruby
- end
-
unless options[:no_default]
gem_source = options[:source] || "path@#{path}"
@files = _default_files.
@@ -616,13 +484,25 @@ module Spec
end
@spec.authors = ["no one"]
+ @spec.files = @files.keys
+
+ case options[:gemspec]
+ when false
+ # do nothing
+ when :yaml
+ @spec.files << "#{name}.gemspec"
+ @files["#{name}.gemspec"] = @spec.to_yaml
+ else
+ @spec.files << "#{name}.gemspec"
+ @files["#{name}.gemspec"] = @spec.to_ruby
+ end
@files.each do |file, source|
file = Pathname.new(path).join(file)
FileUtils.mkdir_p(file.dirname)
File.open(file, "w") {|f| f.puts source }
+ File.chmod("+x", file) if @spec.executables.map {|exe| "#{@spec.bindir}/#{exe}" }.include?(file)
end
- @spec.files = @files.keys
path
end
@@ -645,17 +525,17 @@ module Spec
class GitBuilder < LibBuilder
def _build(options)
+ default_branch = options[:default_branch] || "master"
path = options[:path] || _default_path
source = options[:source] || "git@#{path}"
super(options.merge(:path => path, :source => source))
- Dir.chdir(path) do
- `git init`
- `git add *`
- `git config user.email "lol@wut.com"`
- `git config user.name "lolwut"`
- `git config commit.gpgsign false`
- `git commit -m "OMG INITIAL COMMIT"`
- end
+ @context.git("config --global init.defaultBranch #{default_branch}", path)
+ @context.git("init", path)
+ @context.git("add *", path)
+ @context.git("config user.email lol@wut.com", path)
+ @context.git("config user.name lolwut", path)
+ @context.git("config commit.gpgsign false", path)
+ @context.git("commit -m OMG_INITIAL_COMMIT", path)
end
end
@@ -663,91 +543,71 @@ module Spec
def _build(options)
path = options[:path] || _default_path
super(options.merge(:path => path))
- Dir.chdir(path) do
- `git init --bare`
- end
+ @context.git("init --bare", path)
end
end
class GitUpdater < LibBuilder
- def silently(str)
- `#{str} 2>#{Bundler::NULL}`
- end
-
def _build(options)
libpath = options[:path] || _default_path
update_gemspec = options[:gemspec] || false
source = options[:source] || "git@#{libpath}"
- Dir.chdir(libpath) do
- silently "git checkout master"
-
- if branch = options[:branch]
- raise "You can't specify `master` as the branch" if branch == "master"
- escaped_branch = Shellwords.shellescape(branch)
-
- if `git branch | grep #{escaped_branch}`.empty?
- silently("git branch #{escaped_branch}")
- end
-
- silently("git checkout #{escaped_branch}")
- elsif tag = options[:tag]
- `git tag #{Shellwords.shellescape(tag)}`
- elsif options[:remote]
- silently("git remote add origin #{options[:remote]}")
- elsif options[:push]
- silently("git push origin #{options[:push]}")
- end
+ if branch = options[:branch]
+ @context.git("checkout -b #{Shellwords.shellescape(branch)}", libpath)
+ elsif tag = options[:tag]
+ @context.git("tag #{Shellwords.shellescape(tag)}", libpath)
+ elsif options[:remote]
+ @context.git("remote add origin #{options[:remote]}", libpath)
+ elsif options[:push]
+ @context.git("push origin #{options[:push]}", libpath)
+ end
- current_ref = `git rev-parse HEAD`.strip
- _default_files.keys.each do |path|
- _default_files[path] += "\n#{Builders.constantize(name)}_PREV_REF = '#{current_ref}'"
- end
- super(options.merge(:path => libpath, :gemspec => update_gemspec, :source => source))
- `git add *`
- `git commit -m "BUMP"`
+ current_ref = @context.git("rev-parse HEAD", libpath).strip
+ _default_files.keys.each do |path|
+ _default_files[path] += "\n#{Builders.constantize(name)}_PREV_REF = '#{current_ref}'"
end
+ super(options.merge(:path => libpath, :gemspec => update_gemspec, :source => source))
+ @context.git("commit -am BUMP", libpath)
end
end
class GitReader
- attr_reader :path
+ attr_reader :context, :path
- def initialize(path)
+ def initialize(context, path)
+ @context = context
@path = path
end
def ref_for(ref, len = nil)
- ref = git "rev-parse #{ref}"
+ ref = context.git "rev-parse #{ref}", path
ref = ref[0..len] if len
ref
end
-
- private
-
- def git(cmd)
- Bundler::SharedHelpers.with_clean_git_env do
- Dir.chdir(@path) { `git #{cmd}`.strip }
- end
- end
end
class GemBuilder < LibBuilder
def _build(opts)
lib_path = super(opts.merge(:path => @context.tmp(".tmp/#{@spec.full_name}"), :no_default => opts[:no_default]))
destination = opts[:path] || _default_path
- Dir.chdir(lib_path) do
- FileUtils.mkdir_p(destination)
-
- @spec.authors = ["that guy"] if !@spec.authors || @spec.authors.empty?
+ FileUtils.mkdir_p(lib_path.join(destination))
- Bundler.rubygems.build(@spec, opts[:skip_validation])
+ if opts[:gemspec] == :yaml || opts[:gemspec] == false
+ Dir.chdir(lib_path) do
+ Bundler.rubygems.build(@spec, opts[:skip_validation])
+ end
+ elsif opts[:skip_validation]
+ @context.gem_command "build --force #{@spec.name}", :dir => lib_path
+ else
+ @context.gem_command "build #{@spec.name}", :dir => lib_path
end
+
gem_path = File.expand_path("#{@spec.full_name}.gem", lib_path)
if opts[:to_system]
- @context.system_gems gem_path, :keep_path => true
+ @context.system_gems gem_path, :default => opts[:default]
elsif opts[:to_bundle]
- @context.system_gems gem_path, :path => :bundle_path, :keep_path => true
+ @context.system_gems gem_path, :path => @context.default_bundle_path
else
FileUtils.mv(gem_path, destination)
end
diff --git a/spec/bundler/support/bundle.rb b/spec/bundler/support/bundle.rb
new file mode 100644
index 0000000000..bb21526d35
--- /dev/null
+++ b/spec/bundler/support/bundle.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require "rubygems"
+require_relative "path"
+bundler_gemspec = Spec::Path.loaded_gemspec
+bundler_gemspec.instance_variable_set(:@full_gem_path, Spec::Path.source_root)
+bundler_gemspec.activate if bundler_gemspec.respond_to?(:activate)
+load File.expand_path("bundle", Spec::Path.bindir)
diff --git a/spec/bundler/support/command_execution.rb b/spec/bundler/support/command_execution.rb
index b3c289979f..68e5c56c75 100644
--- a/spec/bundler/support/command_execution.rb
+++ b/spec/bundler/support/command_execution.rb
@@ -3,18 +3,7 @@
module Spec
CommandExecution = Struct.new(:command, :working_directory, :exitstatus, :stdout, :stderr) do
def to_s
- c = Shellwords.shellsplit(command.strip).map {|s| s.include?("\n") ? " \\\n <<EOS\n#{s.gsub(/^/, " ").chomp}\nEOS" : Shellwords.shellescape(s) }
- c = c.reduce("") do |acc, elem|
- concat = acc + " " + elem
-
- last_line = concat.match(/.*\z/)[0]
- if last_line.size >= 100
- acc + " \\\n " + elem
- else
- concat
- end
- end
- "$ #{c.strip}"
+ "$ #{command}"
end
alias_method :inspect, :to_s
diff --git a/spec/bundler/support/filters.rb b/spec/bundler/support/filters.rb
index 4ce6648cdc..3b91897a2e 100644
--- a/spec/bundler/support/filters.rb
+++ b/spec/bundler/support/filters.rb
@@ -21,25 +21,20 @@ class RequirementChecker < Proc
end
RSpec.configure do |config|
- if ENV["BUNDLER_SUDO_TESTS"] && Spec::Sudo.present?
- config.filter_run :sudo => true
- else
- config.filter_run_excluding :sudo => true
- end
-
- if ENV["BUNDLER_REALWORLD_TESTS"]
- config.filter_run :realworld => true
- else
- config.filter_run_excluding :realworld => true
- end
+ config.filter_run_excluding :sudo => true
+ config.filter_run_excluding :realworld => true
git_version = Bundler::Source::Git::GitProxy.new(nil, nil, nil).version
- config.filter_run_excluding :rubygems => RequirementChecker.against(Gem::VERSION)
config.filter_run_excluding :git => RequirementChecker.against(git_version)
config.filter_run_excluding :bundler => RequirementChecker.against(Bundler::VERSION.split(".")[0])
config.filter_run_excluding :ruby_repo => !ENV["GEM_COMMAND"].nil?
config.filter_run_excluding :no_color_tty => Gem.win_platform? || !ENV["GITHUB_ACTION"].nil?
+ config.filter_run_excluding :permissions => Gem.win_platform?
+ config.filter_run_excluding :readline => Gem.win_platform?
+ config.filter_run_excluding :jruby => RUBY_ENGINE != "jruby"
+ config.filter_run_excluding :truffleruby => RUBY_ENGINE != "truffleruby"
+ config.filter_run_excluding :man => Gem.win_platform?
config.filter_run_when_matching :focus unless ENV["CI"]
end
diff --git a/spec/bundler/support/hax.rb b/spec/bundler/support/hax.rb
index c18470acd2..0ad5239128 100644
--- a/spec/bundler/support/hax.rb
+++ b/spec/bundler/support/hax.rb
@@ -9,60 +9,36 @@ module Gem
Gem.ruby = ENV["RUBY"]
end
- if version = ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"]
- remove_const(:VERSION) if const_defined?(:VERSION)
- VERSION = version
+ if ENV["BUNDLER_GEM_DEFAULT_DIR"]
+ @default_dir = ENV["BUNDLER_GEM_DEFAULT_DIR"]
+ @default_specifications_dir = nil
end
- class Platform
- @local = new(ENV["BUNDLER_SPEC_PLATFORM"]) if ENV["BUNDLER_SPEC_PLATFORM"]
- end
- @platforms = [Gem::Platform::RUBY, Gem::Platform.local]
-
- # We only need this hack for rubygems versions without the BundlerVersionFinder
- if Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") || ENV["BUNDLER_SPEC_DISABLE_DEFAULT_BUNDLER_GEM"]
- @path_to_default_spec_map.delete_if do |_path, spec|
- spec.name == "bundler"
+ if ENV["BUNDLER_SPEC_PLATFORM"]
+ class Platform
+ @local = new(ENV["BUNDLER_SPEC_PLATFORM"])
end
- end
-end
+ @platforms = [Gem::Platform::RUBY, Gem::Platform.local]
-if ENV["BUNDLER_SPEC_VERSION"]
- require_relative "path"
- require "#{Spec::Path.lib_dir}/bundler/version"
+ if ENV["BUNDLER_SPEC_PLATFORM"] == "ruby"
+ class << self
+ remove_method :finish_resolve
- module Bundler
- remove_const(:VERSION) if const_defined?(:VERSION)
- VERSION = ENV["BUNDLER_SPEC_VERSION"].dup
+ def finish_resolve
+ []
+ end
+ end
+ end
end
-end
-
-if ENV["BUNDLER_SPEC_WINDOWS"] == "true"
- require_relative "path"
- require "#{Spec::Path.lib_dir}/bundler/constants"
- module Bundler
- remove_const :WINDOWS if defined?(WINDOWS)
- WINDOWS = true
+ if ENV["BUNDLER_SPEC_GEM_SOURCES"]
+ @sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]]
end
-end
-class Object
- if ENV["BUNDLER_SPEC_RUBY_ENGINE"]
- if RUBY_ENGINE != "jruby" && ENV["BUNDLER_SPEC_RUBY_ENGINE"] == "jruby"
- begin
- # this has to be done up front because psych will try to load a .jar
- # if it thinks its on jruby
- require "psych"
- rescue LoadError
- nil
- end
+ # We only need this hack for rubygems versions without the BundlerVersionFinder
+ if Gem.rubygems_version < Gem::Version.new("2.7.0")
+ @path_to_default_spec_map.delete_if do |_path, spec|
+ spec.name == "bundler"
end
-
- remove_const :RUBY_ENGINE
- RUBY_ENGINE = ENV["BUNDLER_SPEC_RUBY_ENGINE"]
-
- remove_const :RUBY_ENGINE_VERSION
- RUBY_ENGINE_VERSION = ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"]
end
end
diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb
index e9c9e766cf..e44c67835f 100644
--- a/spec/bundler/support/helpers.rb
+++ b/spec/bundler/support/helpers.rb
@@ -2,39 +2,37 @@
require_relative "command_execution"
require_relative "the_bundle"
+require_relative "path"
module Spec
module Helpers
+ include Spec::Path
+
def reset!
Dir.glob("#{tmp}/{gems/*,*}", File::FNM_DOTMATCH).each do |dir|
- next if %w[base remote1 gems rubygems . ..].include?(File.basename(dir))
- if ENV["BUNDLER_SUDO_TESTS"]
- `sudo rm -rf "#{dir}"`
- else
- FileUtils.rm_rf(dir)
- end
+ next if %w[base base_system remote1 rubocop standard gems rubygems . ..].include?(File.basename(dir))
+ FileUtils.rm_rf(dir)
end
FileUtils.mkdir_p(home)
FileUtils.mkdir_p(tmpdir)
- Bundler.reset!
+ reset_paths!
end
- def self.bang(method)
- define_method("#{method}!") do |*args, &blk|
- send(method, *args, &blk).tap do
- unless last_command.success?
- raise "Invoking #{method}!(#{args.map(&:inspect).join(", ")}) failed:\n#{last_command.stdboth}"
- end
- end
- end
+ def reset_paths!
+ Bundler.reset!
+ Gem.clear_paths
end
def the_bundle(*args)
TheBundle.new(*args)
end
+ def command_executions
+ @command_executions ||= []
+ end
+
def last_command
- @command_executions.last || raise("There is no last command")
+ command_executions.last || raise("There is no last command")
end
def out
@@ -59,32 +57,19 @@ module Spec
last_command.exitstatus
end
- def in_app_root(&blk)
- Dir.chdir(bundled_app, &blk)
- end
-
- def in_app_root2(&blk)
- Dir.chdir(bundled_app2, &blk)
- end
-
- def in_app_root_custom(root, &blk)
- Dir.chdir(root, &blk)
- end
-
def run(cmd, *args)
opts = args.last.is_a?(Hash) ? args.pop : {}
groups = args.map(&:inspect).join(", ")
- setup = "require '#{lib_dir}/bundler' ; Bundler.ui.silence { Bundler.setup(#{groups}) }\n"
- ruby(setup + cmd, opts)
+ setup = "require '#{entrypoint}' ; Bundler.ui.silence { Bundler.setup(#{groups}) }"
+ ruby([setup, cmd].join(" ; "), opts)
end
- bang :run
def load_error_run(ruby, name, *args)
cmd = <<-RUBY
begin
#{ruby}
rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR" if e.message.include?("-- #{name}")
+ warn "ZOMG LOAD ERROR" if e.message.include?("-- #{name}")
end
RUBY
opts = args.last.is_a?(Hash) ? args.pop : {}
@@ -92,21 +77,16 @@ module Spec
run(cmd, *args)
end
- def bundle(cmd, options = {})
+ def bundle(cmd, options = {}, &block)
with_sudo = options.delete(:sudo)
- sudo = with_sudo == :preserve_env ? "sudo -E" : "sudo" if with_sudo
-
- bundle_bin = options.delete("bundle_bin") || bindir.join("bundle")
+ sudo = with_sudo == :preserve_env ? "sudo -E --preserve-env=RUBYOPT" : "sudo" if with_sudo
- if system_bundler = options.delete(:system_bundler)
- bundle_bin = system_gem_path.join("bin/bundler")
- end
+ bundle_bin = options.delete(:bundle_bin)
+ bundle_bin ||= installed_bindir.join("bundle")
env = options.delete(:env) || {}
- env["PATH"].gsub!("#{Path.root}/exe", "") if env["PATH"] && system_bundler
requires = options.delete(:requires) || []
- requires << "support/hax"
artifice = options.delete(:artifice) do
if RSpec.current_example.metadata[:realworld]
@@ -116,15 +96,14 @@ module Spec
end
end
if artifice
- requires << "support/artifice/#{artifice}"
+ requires << "#{Path.spec_dir}/support/artifice/#{artifice}.rb"
end
- requires_str = requires.map {|r| "-r#{r}" }.join(" ")
-
load_path = []
- load_path << lib_dir unless system_bundler
load_path << spec_dir
- load_path_str = "-I#{load_path.join(File::PATH_SEPARATOR)}"
+
+ dir = options.delete(:dir) || bundled_app
+ raise_on_error = options.delete(:raise_on_error)
args = options.map do |k, v|
case v
@@ -139,74 +118,74 @@ module Spec
end
end.join
- cmd = "#{sudo} #{Gem.ruby} #{load_path_str} #{requires_str} #{bundle_bin} #{cmd}#{args}"
- sys_exec(cmd, env) {|i, o, thr| yield i, o, thr if block_given? }
- end
- bang :bundle
-
- def forgotten_command_line_options(options)
- remembered = Bundler::VERSION.split(".", 2).first == "2"
- options = options.map do |k, v|
- v = '""' if v && v.to_s.empty?
- [k, v]
- end
- return Hash[options] if remembered
- options.each do |k, v|
- if v.nil?
- bundle! "config unset #{k}"
- else
- bundle! "config set --local #{k} #{v}"
- end
- end
- {}
+ ruby_cmd = build_ruby_cmd({ :sudo => sudo, :load_path => load_path, :requires => requires })
+ cmd = "#{ruby_cmd} #{bundle_bin} #{cmd}#{args}"
+ sys_exec(cmd, { :env => env, :dir => dir, :raise_on_error => raise_on_error }, &block)
end
def bundler(cmd, options = {})
- options["bundle_bin"] = bindir.join("bundler")
+ options[:bundle_bin] = system_gem_path.join("bin/bundler")
bundle(cmd, options)
end
def ruby(ruby, options = {})
- env = options.delete(:env) || {}
- ruby = ruby.gsub(/["`\$]/) {|m| "\\#{m}" }
- lib_option = options[:no_lib] ? "" : " -I#{lib_dir}"
- sys_exec(%(#{Gem.ruby}#{lib_option} -w -e "#{ruby}"), env)
+ ruby_cmd = build_ruby_cmd
+ escaped_ruby = ruby.shellescape
+ sys_exec(%(#{ruby_cmd} -w -e #{escaped_ruby}), options)
end
- bang :ruby
def load_error_ruby(ruby, name, opts = {})
ruby(<<-R)
begin
#{ruby}
rescue LoadError => e
- $stderr.puts "ZOMG LOAD ERROR"# if e.message.include?("-- #{name}")
+ warn "ZOMG LOAD ERROR" if e.message.include?("-- #{name}")
end
R
end
- def gembin(cmd)
- old = ENV["RUBYOPT"]
- ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -I#{lib_dir}"
+ def build_ruby_cmd(options = {})
+ sudo = options.delete(:sudo)
+
+ libs = options.delete(:load_path)
+ lib_option = libs ? "-I#{libs.join(File::PATH_SEPARATOR)}" : []
+
+ requires = options.delete(:requires) || []
+ requires << "#{Path.spec_dir}/support/hax.rb"
+ require_option = requires.map {|r| "-r#{r}" }
+
+ [sudo, Gem.ruby, *lib_option, *require_option].compact.join(" ")
+ end
+
+ def gembin(cmd, options = {})
cmd = bundled_app("bin/#{cmd}") unless cmd.to_s.include?("/")
- sys_exec(cmd.to_s)
- ensure
- ENV["RUBYOPT"] = old
+ sys_exec(cmd.to_s, options)
end
- def gem_command(command, args = "")
- sys_exec("#{Path.gem_bin} #{command} #{args}")
+ def gem_command(command, options = {})
+ env = options[:env] || {}
+ env["RUBYOPT"] = opt_add("-r#{spec_dir}/support/hax.rb", env["RUBYOPT"] || ENV["RUBYOPT"])
+ options[:env] = env
+ sys_exec("#{Path.gem_bin} #{command}", options)
end
- bang :gem_command
def rake
"#{Gem.ruby} -S #{ENV["GEM_PATH"]}/bin/rake"
end
- def sys_exec(cmd, env = {})
- command_execution = CommandExecution.new(cmd.to_s, Dir.pwd)
+ def git(cmd, path, options = {})
+ sys_exec("git #{cmd}", options.merge(:dir => path))
+ end
+
+ def sys_exec(cmd, options = {})
+ env = options[:env] || {}
+ env["RUBYOPT"] = opt_add("-r#{spec_dir}/support/switch_rubygems.rb", env["RUBYOPT"] || ENV["RUBYOPT"])
+ dir = options[:dir] || bundled_app
+ command_execution = CommandExecution.new(cmd.to_s, dir)
require "open3"
- Open3.popen3(env, cmd.to_s) do |stdin, stdout, stderr, wait_thr|
+ require "shellwords"
+ Open3.popen3(env, *cmd.shellsplit, :chdir => dir) do |stdin, stdout, stderr, wait_thr|
yield stdin, stdout, wait_thr if block_given?
stdin.close
@@ -214,14 +193,35 @@ module Spec
stderr_read_thread = Thread.new { stderr.read }
command_execution.stdout = stdout_read_thread.value.strip
command_execution.stderr = stderr_read_thread.value.strip
- command_execution.exitstatus = wait_thr && wait_thr.value.exitstatus
+
+ status = wait_thr.value
+ command_execution.exitstatus = if status.exited?
+ status.exitstatus
+ elsif status.signaled?
+ 128 + status.termsig
+ end
end
- (@command_executions ||= []) << command_execution
+ unless options[:raise_on_error] == false || command_execution.success?
+ raise <<~ERROR
+
+ Invoking `#{cmd}` failed with output:
+ ----------------------------------------------------------------------
+ #{command_execution.stdboth}
+ ----------------------------------------------------------------------
+ ERROR
+ end
+
+ command_executions << command_execution
command_execution.stdout
end
- bang :sys_exec
+
+ def all_commands_output
+ return "" if command_executions.empty?
+
+ "\n\nCommands:\n#{command_executions.map(&:to_s_verbose).join("\n\n")}"
+ end
def config(config = nil, path = bundled_app(".bundle/config"))
return YAML.load_file(path) unless config
@@ -250,7 +250,7 @@ module Spec
contents = args.shift
if contents.nil?
- File.open("Gemfile", "r", &:read)
+ File.open(bundled_app_gemfile, "r", &:read)
else
create_file("Gemfile", contents, *args)
end
@@ -260,7 +260,7 @@ module Spec
contents = args.shift
if contents.nil?
- File.open("Gemfile.lock", "r", &:read)
+ File.open(bundled_app_lock, "r", &:read)
else
create_file("Gemfile.lock", contents, *args)
end
@@ -275,77 +275,113 @@ module Spec
def install_gemfile(*args)
gemfile(*args)
opts = args.last.is_a?(Hash) ? args.last : {}
- opts[:retry] ||= 0
bundle :install, opts
end
- bang :install_gemfile
def lock_gemfile(*args)
gemfile(*args)
opts = args.last.is_a?(Hash) ? args.last : {}
- opts[:retry] ||= 0
bundle :lock, opts
end
- def install_gems(*gems)
+ def system_gems(*gems)
+ gems = gems.flatten
options = gems.last.is_a?(Hash) ? gems.pop : {}
- gem_repo = options.fetch(:gem_repo) { gem_repo1 }
- gems.each do |g|
- if g == :bundler
- with_built_bundler {|gem_path| install_gem(gem_path) }
- elsif g.to_s =~ %r{\A(?:[A-Z]:)?/.*\.gem\z}
- install_gem(g)
- else
- install_gem("#{gem_repo}/gems/#{g}.gem")
+ path = options.fetch(:path, system_gem_path)
+ default = options.fetch(:default, false)
+ with_gem_path_as(path) do
+ gem_repo = options.fetch(:gem_repo, gem_repo1)
+ gems.each do |g|
+ gem_name = g.to_s
+ if gem_name.start_with?("bundler")
+ version = gem_name.match(/\Abundler-(?<version>.*)\z/)[:version] if gem_name != "bundler"
+ with_built_bundler(version) {|gem_path| install_gem(gem_path, default) }
+ elsif gem_name =~ %r{\A(?:[a-zA-Z]:)?/.*\.gem\z}
+ install_gem(gem_name, default)
+ else
+ install_gem("#{gem_repo}/gems/#{gem_name}.gem", default)
+ end
end
end
end
- def install_gem(path)
+ def install_gem(path, default = false)
raise "OMG `#{path}` does not exist!" unless File.exist?(path)
- gem_command! :install, "--no-document --ignore-dependencies '#{path}'"
+ args = "--no-document --ignore-dependencies"
+ args += " --default --install-dir #{system_gem_path}" if default
+
+ gem_command "install #{args} '#{path}'"
end
- def with_built_bundler
- with_root_gemspec do |gemspec|
- Dir.chdir(root) { gem_command! :build, gemspec.to_s }
- end
+ def with_built_bundler(version = nil)
+ version ||= Bundler::VERSION
+ full_name = "bundler-#{version}"
+ build_path = tmp + full_name
+ bundler_path = build_path + "#{full_name}.gem"
- bundler_path = root + "bundler-#{Bundler::VERSION}.gem"
+ Dir.mkdir build_path
begin
+ shipped_files.each do |shipped_file|
+ target_shipped_file = build_path + shipped_file
+ target_shipped_dir = File.dirname(target_shipped_file)
+ FileUtils.mkdir_p target_shipped_dir unless File.directory?(target_shipped_dir)
+ FileUtils.cp shipped_file, target_shipped_file, :preserve => true
+ end
+
+ replace_version_file(version, dir: build_path) # rubocop:disable Style/HashSyntax
+
+ Spec::BuildMetadata.write_build_metadata(dir: build_path) # rubocop:disable Style/HashSyntax
+
+ gem_command "build #{relative_gemspec}", :dir => build_path
+
yield(bundler_path)
ensure
- bundler_path.rmtree
+ build_path.rmtree
end
end
def with_gem_path_as(path)
- backup = ENV.to_hash
- ENV["GEM_HOME"] = path.to_s
- ENV["GEM_PATH"] = path.to_s
- ENV["BUNDLER_ORIG_GEM_PATH"] = nil
- yield
- ensure
- ENV.replace(backup)
+ without_env_side_effects do
+ ENV["GEM_HOME"] = path.to_s
+ ENV["GEM_PATH"] = path.to_s
+ ENV["BUNDLER_ORIG_GEM_PATH"] = nil
+ yield
+ end
end
def with_path_as(path)
+ without_env_side_effects do
+ ENV["PATH"] = path.to_s
+ ENV["BUNDLER_ORIG_PATH"] = nil
+ yield
+ end
+ end
+
+ def without_env_side_effects
backup = ENV.to_hash
- ENV["PATH"] = path.to_s
- ENV["BUNDLER_ORIG_PATH"] = nil
yield
ensure
ENV.replace(backup)
end
def with_path_added(path)
- with_path_as(path.to_s + ":" + ENV["PATH"]) do
+ with_path_as([path.to_s, ENV["PATH"]].join(File::PATH_SEPARATOR)) do
yield
end
end
+ def opt_add(option, options)
+ [option.strip, options].compact.reject(&:empty?).join(" ")
+ end
+
+ def opt_remove(option, options)
+ return unless options
+
+ options.split(" ").reject {|opt| opt.strip == option.strip }.join(" ")
+ end
+
def break_git!
FileUtils.mkdir_p(tmp("broken_path"))
File.open(tmp("broken_path/git"), "w", 0o755) do |f|
@@ -356,6 +392,8 @@ 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"
@@ -363,68 +401,21 @@ module Spec
with_path_added(tmp("fake_man")) { yield }
end
- def system_gems(*gems)
- opts = gems.last.is_a?(Hash) ? gems.last : {}
- path = opts.fetch(:path, system_gem_path)
- if path == :bundle_path
- path = ruby!(<<-RUBY)
- require "bundler"
- begin
- puts Bundler.bundle_path
- rescue Bundler::GemfileNotFound
- ENV["BUNDLE_GEMFILE"] = "Gemfile"
- retry
- end
-
- RUBY
- end
- gems = gems.flatten
-
- unless opts[:keep_path]
- FileUtils.rm_rf(path)
- FileUtils.mkdir_p(path)
- end
-
- Gem.clear_paths
-
- env_backup = ENV.to_hash
- ENV["GEM_HOME"] = path.to_s
- ENV["GEM_PATH"] = path.to_s
- ENV["BUNDLER_ORIG_GEM_PATH"] = nil
+ def pristine_system_gems(*gems)
+ FileUtils.rm_rf(system_gem_path)
- install_gems(*gems)
- return unless block_given?
- begin
- yield
- ensure
- ENV.replace(env_backup)
- end
+ system_gems(*gems)
end
def realworld_system_gems(*gems)
gems = gems.flatten
+ opts = gems.last.is_a?(Hash) ? gems.pop : {}
+ path = opts.fetch(:path, system_gem_path)
- FileUtils.rm_rf(system_gem_path)
- FileUtils.mkdir_p(system_gem_path)
-
- Gem.clear_paths
-
- gem_home = ENV["GEM_HOME"]
- gem_path = ENV["GEM_PATH"]
- path = ENV["PATH"]
- ENV["GEM_HOME"] = system_gem_path.to_s
- ENV["GEM_PATH"] = system_gem_path.to_s
-
- gems.each do |gem|
- gem_command! :install, "--no-document #{gem}"
- end
- return unless block_given?
- begin
- yield
- ensure
- ENV["GEM_HOME"] = gem_home
- ENV["GEM_PATH"] = gem_path
- ENV["PATH"] = path
+ with_gem_path_as(path) do
+ gems.each do |gem|
+ gem_command "install --no-document #{gem}"
+ end
end
end
@@ -442,9 +433,8 @@ module Spec
end
def simulate_new_machine
- system_gems []
- FileUtils.rm_rf system_gem_path
FileUtils.rm_rf bundled_app(".bundle")
+ pristine_system_gems :bundler
end
def simulate_platform(platform)
@@ -464,47 +454,40 @@ module Spec
ENV["BUNDLER_SPEC_RUBY_VERSION"] = old if block_given?
end
- def simulate_ruby_engine(engine, version = "1.6.0")
- return if engine == local_ruby_engine
-
- old = ENV["BUNDLER_SPEC_RUBY_ENGINE"]
- ENV["BUNDLER_SPEC_RUBY_ENGINE"] = engine
- old_version = ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"]
- ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] = version
- yield if block_given?
- ensure
- ENV["BUNDLER_SPEC_RUBY_ENGINE"] = old if block_given?
- ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] = old_version if block_given?
+ def simulate_windows(platform = mswin)
+ simulate_platform platform do
+ simulate_bundler_version_when_missing_prerelease_default_gem_activation do
+ yield
+ end
+ end
end
- def simulate_bundler_version(version)
- old = ENV["BUNDLER_SPEC_VERSION"]
- ENV["BUNDLER_SPEC_VERSION"] = version.to_s
- yield if block_given?
- ensure
- ENV["BUNDLER_SPEC_VERSION"] = old if block_given?
- end
+ def simulate_bundler_version_when_missing_prerelease_default_gem_activation
+ return yield unless rubygems_version_failing_to_activate_bundler_prereleases
- def simulate_rubygems_version(version)
- old = ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"]
- ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"] = version.to_s
- yield if block_given?
+ old = ENV["BUNDLER_VERSION"]
+ ENV["BUNDLER_VERSION"] = Bundler::VERSION
+ yield
ensure
- ENV["BUNDLER_SPEC_RUBYGEMS_VERSION"] = old if block_given?
+ ENV["BUNDLER_VERSION"] = old
end
- def simulate_windows(platform = mswin)
- old = ENV["BUNDLER_SPEC_WINDOWS"]
- ENV["BUNDLER_SPEC_WINDOWS"] = "true"
- simulate_platform platform do
- yield
+ def env_for_missing_prerelease_default_gem_activation
+ if rubygems_version_failing_to_activate_bundler_prereleases
+ { "BUNDLER_VERSION" => Bundler::VERSION }
+ else
+ {}
end
- ensure
- ENV["BUNDLER_SPEC_WINDOWS"] = old
+ end
+
+ # versions providing a bundler version finder but not including
+ # https://github.com/rubygems/rubygems/commit/929e92d752baad3a08f3ac92eaec162cb96aedd1
+ def rubygems_version_failing_to_activate_bundler_prereleases
+ Gem.rubygems_version < Gem::Version.new("3.1.0.pre.1") && Gem.rubygems_version >= Gem::Version.new("2.7.0")
end
def revision_for(path)
- Dir.chdir(path) { `git rev-parse HEAD`.strip }
+ sys_exec("git rev-parse HEAD", :dir => path).strip
end
def with_read_only(pattern)
@@ -526,11 +509,11 @@ module Spec
process_file(pathname) do |line|
case line
when /spec\.metadata\["(?:allowed_push_host|homepage_uri|source_code_uri|changelog_uri)"\]/, /spec\.homepage/
- line.gsub(/\=.*$/, "= 'http://example.org'")
+ line.gsub(/\=.*$/, '= "http://example.org"')
when /spec\.summary/
- line.gsub(/\=.*$/, "= %q{A short summary of my new gem.}")
+ line.gsub(/\=.*$/, '= "A short summary of my new gem."')
when /spec\.description/
- line.gsub(/\=.*$/, "= %q{A longer description of my new gem.}")
+ line.gsub(/\=.*$/, '= "A longer description of my new gem."')
else
line
end
@@ -583,5 +566,11 @@ module Spec
end
port
end
+
+ private
+
+ def git_root_dir?
+ root.to_s == `git rev-parse --show-toplevel`.chomp
+ end
end
end
diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb
index dc6e0bd1e9..638f394e76 100644
--- a/spec/bundler/support/indexes.rb
+++ b/spec/bundler/support/indexes.rb
@@ -17,16 +17,19 @@ module Spec
def resolve(args = [])
@platforms ||= ["ruby"]
deps = []
- default_source = instance_double("Bundler::Source::Rubygems", :specs => @index)
+ default_source = instance_double("Bundler::Source::Rubygems", :specs => @index, :to_s => "locally install gems")
source_requirements = { :default => default_source }
@deps.each do |d|
+ source_requirements[d.name] = d.source = default_source
@platforms.each do |p|
- source_requirements[d.name] = d.source = default_source
- deps << Bundler::DepProxy.new(d, p)
+ deps << Bundler::DepProxy.get_proxy(d, p)
end
end
- source_requirements ||= {}
- Bundler::Resolver.resolve(deps, @index, source_requirements, *args)
+ args[0] ||= [] # base
+ args[1] ||= Bundler::GemVersionPromoter.new # gem_version_promoter
+ args[2] ||= [] # additional_base_requirements
+ args[3] ||= @platforms # platforms
+ Bundler::Resolver.resolve(deps, source_requirements, *args)
end
def should_resolve_as(specs)
diff --git a/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb
index df35854c2f..3c2a7f9f58 100644
--- a/spec/bundler/support/matchers.rb
+++ b/spec/bundler/support/matchers.rb
@@ -75,16 +75,6 @@ module Spec
end
end
- RSpec::Matchers.define :have_rubyopts do |*args|
- args = args.flatten
- args = args.first.split(/\s+/) if args.size == 1
-
- match do |actual|
- actual = actual.split(/\s+/) if actual.is_a?(String)
- args.all? {|arg| actual.include?(arg) } && actual.uniq.size == actual.size
- end
- end
-
RSpec::Matchers.define :be_sorted do
diffable
attr_reader :expected
@@ -124,34 +114,49 @@ module Spec
match do
opts = names.last.is_a?(Hash) ? names.pop : {}
source = opts.delete(:source)
- groups = Array(opts[:groups])
- groups << opts
- @errors = names.map do |name|
- name, version, platform = name.split(/\s+/)
- require_path = name == "bundler" ? "#{lib_dir}/bundler" : name.tr("-", "/")
+ groups = Array(opts.delete(:groups)).map(&:inspect).join(", ")
+ opts[:raise_on_error] = false
+ @errors = names.map do |full_name|
+ name, version, platform = full_name.split(/\s+/)
+ require_path = name.tr("-", "/")
version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name)
- begin
- run! "require '#{require_path}.rb'; puts #{version_const}", *groups
- rescue StandardError => e
- next "#{name} is not installed:\n#{indent(e)}"
- end
- actual_version, actual_platform = out.strip.split(/\s+/, 2)
- unless Gem::Version.new(actual_version) == Gem::Version.new(version)
+ source_const = "#{Spec::Builders.constantize(name)}_SOURCE"
+ ruby <<~R, opts
+ require 'bundler'
+ Bundler.setup(#{groups})
+
+ require '#{require_path}'
+ actual_version, actual_platform = #{version_const}.split(/\s+/, 2)
+ unless Gem::Version.new(actual_version) == Gem::Version.new('#{version}')
+ puts actual_version
+ exit 64
+ end
+ unless actual_platform.to_s == '#{platform}'
+ puts actual_platform
+ exit 65
+ end
+ require '#{require_path}/source'
+ exit 0 if #{source.nil?}
+ actual_source = #{source_const}
+ unless actual_source == '#{source}'
+ puts actual_source
+ exit 66
+ end
+ R
+ next if exitstatus == 0
+ if exitstatus == 64
+ actual_version = out.split("\n").last
next "#{name} was expected to be at version #{version} but was #{actual_version}"
end
- unless actual_platform == platform
+ if exitstatus == 65
+ actual_platform = out.split("\n").last
next "#{name} was expected to be of platform #{platform} but was #{actual_platform}"
end
- next unless source
- begin
- source_const = "#{Spec::Builders.constantize(name)}_SOURCE"
- run! "require '#{require_path}/source'; puts #{source_const}", *groups
- rescue StandardError
- next "#{name} does not have a source defined:\n#{indent(e)}"
- end
- unless out.strip == source
- next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{out}`"
+ if exitstatus == 66
+ actual_source = out.split("\n").last
+ next "Expected #{name} (#{version}) to be installed from `#{source}`, was actually from `#{actual_source}`"
end
+ next "Command to check for inclusion of gem #{full_name} failed"
end.compact
@errors.empty?
@@ -159,26 +164,34 @@ module Spec
match_when_negated do
opts = names.last.is_a?(Hash) ? names.pop : {}
- groups = Array(opts[:groups]) || []
+ groups = Array(opts.delete(:groups)).map(&:inspect).join(", ")
+ opts[:raise_on_error] = false
@errors = names.map do |name|
name, version = name.split(/\s+/, 2)
- begin
- run <<-R, *(groups + [opts])
- begin
- require '#{name}'
- puts #{Spec::Builders.constantize(name)}
- rescue LoadError, NameError
- puts "WIN"
+ ruby <<-R, opts
+ begin
+ require 'bundler'
+ Bundler.setup(#{groups})
+ rescue Bundler::GemNotFound, Bundler::GitError
+ exit 0
+ end
+
+ begin
+ require '#{name}'
+ name_constant = '#{Spec::Builders.constantize(name)}'
+ if #{version.nil?} || name_constant == '#{version}'
+ exit 64
+ else
+ exit 0
end
- R
- rescue StandardError => e
- next "checking for #{name} failed:\n#{e}\n#{e.backtrace.join("\n")}"
- end
- next if out == "WIN"
+ rescue LoadError, NameError
+ exit 0
+ end
+ R
+ next if exitstatus == 0
+ next "command to check version of #{name} installed failed" unless exitstatus == 64
next "expected #{name} to not be installed, but it was" if version.nil?
- if Gem::Version.new(out) == Gem::Version.new(version)
- next "expected #{name} (#{version}) not to be installed, but it was"
- end
+ next "expected #{name} (#{version}) not to be installed, but it was"
end.compact
@errors.empty?
@@ -195,10 +208,6 @@ module Spec
RSpec::Matchers.define_negated_matcher :not_include_gems, :include_gems
RSpec::Matchers.alias_matcher :include_gem, :include_gems
- def have_lockfile(expected)
- read_as(strip_whitespace(expected))
- end
-
def plugin_should_be_installed(*names)
names.each do |name|
expect(Bundler::Plugin).to be_installed(name)
@@ -212,13 +221,5 @@ module Spec
expect(Bundler::Plugin).not_to be_installed(name)
end
end
-
- def lockfile_should_be(expected)
- expect(bundled_app("Gemfile.lock")).to have_lockfile(expected)
- end
-
- def gemfile_should_be(expected)
- expect(bundled_app("Gemfile")).to read_as(strip_whitespace(expected))
- end
end
end
diff --git a/spec/bundler/support/parallel.rb b/spec/bundler/support/parallel.rb
deleted file mode 100644
index 8763cb9ec4..0000000000
--- a/spec/bundler/support/parallel.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.configure do |config|
- config.silence_filter_announcements = true
-end
diff --git a/spec/bundler/support/path.rb b/spec/bundler/support/path.rb
index 645da52c97..a73b3e699e 100644
--- a/spec/bundler/support/path.rb
+++ b/spec/bundler/support/path.rb
@@ -5,54 +5,98 @@ require "rbconfig"
module Spec
module Path
+ def source_root
+ @source_root ||= Pathname.new(ruby_core? ? "../../.." : "../..").expand_path(__dir__)
+ end
+
def root
- @root ||= Pathname.new(ruby_core? ? "../../../.." : "../../..").expand_path(__FILE__)
+ @root ||= system_gem_path("gems/bundler-#{Bundler::VERSION}")
end
def gemspec
- @gemspec ||= root.join(ruby_core? ? "lib/bundler/bundler.gemspec" : "bundler.gemspec")
+ @gemspec ||= source_root.join(relative_gemspec)
+ end
+
+ def relative_gemspec
+ @relative_gemspec ||= ruby_core? ? "lib/bundler/bundler.gemspec" : "bundler.gemspec"
end
def gemspec_dir
@gemspec_dir ||= gemspec.parent
end
+ def loaded_gemspec
+ @loaded_gemspec ||= Gem::Specification.load(gemspec.to_s)
+ end
+
+ def test_gemfile
+ @test_gemfile ||= source_root.join("tool/bundler/test_gems.rb")
+ end
+
+ def rubocop_gemfile
+ @rubocop_gemfile ||= source_root.join(rubocop_gemfile_basename)
+ end
+
+ def standard_gemfile
+ @standard_gemfile ||= source_root.join(standard_gemfile_basename)
+ end
+
+ def dev_gemfile
+ @dev_gemfile ||= git_root.join("dev_gems.rb")
+ end
+
def bindir
- @bindir ||= root.join(ruby_core? ? "libexec" : "exe")
+ @bindir ||= source_root.join(ruby_core? ? "libexec" : "exe")
+ end
+
+ def installed_bindir
+ @installed_bindir ||= system_gem_path("bin")
end
def gem_cmd
- @gem_cmd ||= ruby_core? ? root.join("bin/gem") : "gem"
+ @gem_cmd ||= ruby_core? ? source_root.join("bin/gem") : "gem"
end
def gem_bin
@gem_bin ||= ruby_core? ? ENV["GEM_COMMAND"] : "gem"
end
+ def path
+ env_path = ENV["PATH"]
+ env_path = env_path.split(File::PATH_SEPARATOR).reject {|path| path == bindir.to_s }.join(File::PATH_SEPARATOR) if ruby_core?
+ env_path
+ end
+
def spec_dir
- @spec_dir ||= root.join(ruby_core? ? "spec/bundler" : "spec")
+ @spec_dir ||= source_root.join(ruby_core? ? "spec/bundler" : "spec")
end
- def tracked_files
- skip "not in git working directory" unless git_root_dir?
+ def api_request_limit_hack_file
+ spec_dir.join("support/api_request_limit_hax.rb")
+ end
- @tracked_files ||= ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb spec/bundler man/bundler*` : `git ls-files -z`
+ def man_dir
+ @man_dir ||= lib_dir.join("bundler/man")
end
- def shipped_files
- skip "not in git working directory" unless git_root_dir?
+ def tracked_files
+ @tracked_files ||= git_ls_files(tracked_files_glob)
+ end
- @shipped_files ||= ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb man/bundler* libexec/bundle*` : `git ls-files -z -- lib man exe CHANGELOG.md LICENSE.md README.md bundler.gemspec`
+ def shipped_files
+ @shipped_files ||= loaded_gemspec.files
end
def lib_tracked_files
- skip "not in git working directory" unless git_root_dir?
+ @lib_tracked_files ||= git_ls_files(lib_tracked_files_glob)
+ end
- @lib_tracked_files ||= ruby_core? ? `git ls-files -z -- lib/bundler lib/bundler.rb` : `git ls-files -z -- lib`
+ def man_tracked_files
+ @man_tracked_files ||= git_ls_files(man_tracked_files_glob)
end
def tmp(*path)
- root.join("tmp", scope, *path)
+ source_root.join("tmp", scope, *path)
end
def scope
@@ -67,10 +111,10 @@ module Spec
end
def default_bundle_path(*path)
- if Bundler::VERSION.split(".").first.to_i < 3
- system_gem_path(*path)
+ if Bundler.feature_flag.default_install_uses_path?
+ local_gem_path(*path)
else
- bundled_app(*[".bundle", ENV.fetch("BUNDLER_SPEC_RUBY_ENGINE", Gem.ruby_engine), RbConfig::CONFIG["ruby_version"], *path].compact)
+ system_gem_path(*path)
end
end
@@ -80,8 +124,6 @@ module Spec
root.join(*path)
end
- alias_method :bundled_app1, :bundled_app
-
def bundled_app2(*path)
root = tmp.join("bundled_app2")
FileUtils.mkdir_p(root)
@@ -89,17 +131,33 @@ module Spec
end
def vendored_gems(path = nil)
- bundled_app(*["vendor/bundle", Gem.ruby_engine, RbConfig::CONFIG["ruby_version"], path].compact)
+ scoped_gem_path(bundled_app("vendor/bundle")).join(*[path].compact)
end
def cached_gem(path)
bundled_app("vendor/cache/#{path}.gem")
end
+ def bundled_app_gemfile
+ bundled_app("Gemfile")
+ end
+
+ def bundled_app_lock
+ bundled_app("Gemfile.lock")
+ end
+
def base_system_gems
tmp.join("gems/base")
end
+ def rubocop_gems
+ tmp.join("gems/rubocop")
+ end
+
+ def standard_gems
+ tmp.join("gems/standard")
+ end
+
def file_uri_for(path)
protocol = "file://"
root = Gem.win_platform? ? "/" : ""
@@ -135,14 +193,37 @@ module Spec
tmp("gems/system", *path)
end
+ def pristine_system_gem_path
+ tmp("gems/base_system")
+ end
+
+ def local_gem_path(*path, base: bundled_app)
+ scoped_gem_path(base.join(".bundle")).join(*path)
+ end
+
+ def scoped_gem_path(base)
+ base.join(Gem.ruby_engine, RbConfig::CONFIG["ruby_version"])
+ end
+
def lib_path(*args)
tmp("libs", *args)
end
+ def source_lib_dir
+ source_root.join("lib")
+ end
+
def lib_dir
root.join("lib")
end
+ # Sometimes rubygems version under test does not include
+ # https://github.com/rubygems/rubygems/pull/2728 and will not always end up
+ # activating the current bundler. In that case, require bundler absolutely.
+ def entrypoint
+ Gem.rubygems_version < Gem::Version.new("3.1.a") ? "#{lib_dir}/bundler" : "bundler"
+ end
+
def global_plugin_gem(*args)
home ".bundle", "plugin", "gems", *args
end
@@ -155,18 +236,11 @@ module Spec
tmp "tmpdir", *args
end
- def with_root_gemspec
- if ruby_core?
- root_gemspec = root.join("bundler.gemspec")
- # Dir.chdir(root) for Dir.glob in gemspec
- spec = Dir.chdir(root) { Gem::Specification.load(gemspec.to_s) }
- spec.bindir = "libexec"
- File.open(root_gemspec.to_s, "w") {|f| f.write spec.to_ruby }
- yield(root_gemspec)
- FileUtils.rm(root_gemspec)
- else
- yield(gemspec)
- end
+ def replace_version_file(version, dir: source_root)
+ version_file = File.expand_path("lib/bundler/version.rb", dir)
+ contents = File.read(version_file)
+ contents.sub!(/(^\s+VERSION\s*=\s*)"#{Gem::Version::VERSION_PATTERN}"/, %(\\1"#{version}"))
+ File.open(version_file, "w") {|f| f << contents }
end
def ruby_core?
@@ -180,12 +254,56 @@ module Spec
end
end
- extend self
+ private
+
+ def git_ls_files(glob)
+ skip "Not running on a git context, since running tests from a tarball" if ruby_core_tarball?
+
+ sys_exec("git ls-files -z -- #{glob}", :dir => source_root).split("\x0")
+ end
- private
+ def tracked_files_glob
+ ruby_core? ? "lib/bundler lib/bundler.rb spec/bundler man/bundle*" : ""
+ end
+
+ def lib_tracked_files_glob
+ ruby_core? ? "lib/bundler lib/bundler.rb" : "lib"
+ end
+
+ def man_tracked_files_glob
+ ruby_core? ? "man/bundle* man/gemfile*" : "lib/bundler/man/bundle*.1 lib/bundler/man/gemfile*.5"
+ end
- def git_root_dir?
- root.to_s == `git rev-parse --show-toplevel`.chomp
+ def git_root
+ ruby_core? ? source_root : source_root.parent
end
+
+ def ruby_core_tarball?
+ !git_root.join(".git").directory?
+ end
+
+ def rubocop_gemfile_basename
+ filename = if RUBY_VERSION.start_with?("2.3")
+ "rubocop23_gems"
+ elsif RUBY_VERSION.start_with?("2.4")
+ "rubocop24_gems"
+ else
+ "rubocop_gems"
+ end
+ source_root.join("tool/bundler/#{filename}.rb")
+ end
+
+ def standard_gemfile_basename
+ filename = if RUBY_VERSION.start_with?("2.3")
+ "standard23_gems"
+ elsif RUBY_VERSION.start_with?("2.4")
+ "standard24_gems"
+ else
+ "standard_gems"
+ end
+ source_root.join("tool/bundler/#{filename}.rb")
+ end
+
+ extend self
end
end
diff --git a/spec/bundler/support/platforms.rb b/spec/bundler/support/platforms.rb
index f4d63c8ded..07973fd727 100644
--- a/spec/bundler/support/platforms.rb
+++ b/spec/bundler/support/platforms.rb
@@ -65,12 +65,10 @@ module Spec
end
def local_ruby_engine
- ENV["BUNDLER_SPEC_RUBY_ENGINE"] || RUBY_ENGINE
+ RUBY_ENGINE
end
def local_engine_version
- return ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"] if ENV["BUNDLER_SPEC_RUBY_ENGINE_VERSION"]
-
RUBY_ENGINE_VERSION
end
@@ -92,15 +90,15 @@ module Spec
end
def lockfile_platforms
- local_platforms.map(&:to_s).sort.join("\n ")
+ lockfile_platforms_for(local_platforms)
+ end
+
+ def lockfile_platforms_for(platforms)
+ platforms.map(&:to_s).sort.join("\n ")
end
def local_platforms
- if Bundler.feature_flag.specific_platform?
- [local, specific_local_platform]
- else
- [local]
- end
+ [specific_local_platform]
end
end
end
diff --git a/spec/bundler/support/rubygems_ext.rb b/spec/bundler/support/rubygems_ext.rb
index ee9c750a52..f957440ab0 100644
--- a/spec/bundler/support/rubygems_ext.rb
+++ b/spec/bundler/support/rubygems_ext.rb
@@ -2,45 +2,18 @@
require_relative "path"
+$LOAD_PATH.unshift(Spec::Path.source_lib_dir.to_s)
+
module Spec
module Rubygems
- DEV_DEPS = {
- "automatiek" => "~> 0.3.0",
- "parallel_tests" => "~> 2.29",
- "rake" => "~> 12.0",
- "ronn" => "~> 0.7.3",
- "rspec" => "~> 3.8",
- "rubocop" => "= 0.77.0",
- "rubocop-performance" => "= 1.5.1",
- }.freeze
-
- DEPS = {
- "rack" => "~> 2.0",
- "rack-test" => "~> 1.1",
- "artifice" => "~> 0.6.0",
- "compact_index" => "~> 0.11.0",
- "sinatra" => "~> 2.0",
- # Rake version has to be consistent for tests to pass
- "rake" => "12.3.2",
- "builder" => "~> 3.2",
- # ruby-graphviz is used by the viz tests
- "ruby-graphviz" => ">= 0.a",
- }.freeze
-
extend self
def dev_setup
- deps = DEV_DEPS
-
- # JRuby can't build ronn, so we skip that
- deps.delete("ronn") if RUBY_ENGINE == "jruby"
-
- install_gems(deps)
+ install_gems(dev_gemfile)
end
def gem_load(gem_name, bin_container)
- require_relative "rubygems_version_manager"
- RubygemsVersionManager.new(ENV["RGV"]).switch
+ require_relative "switch_rubygems"
gem_load_and_activate(gem_name, bin_container)
end
@@ -50,25 +23,10 @@ module Spec
require gem_name
end
- def setup
- require "fileutils"
-
- Gem.clear_paths
+ def test_setup
+ setup_test_paths
- ENV["BUNDLE_PATH"] = nil
- ENV["GEM_HOME"] = ENV["GEM_PATH"] = Path.base_system_gems.to_s
- ENV["PATH"] = [Path.bindir, Path.system_gem_path.join("bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
-
- manifest = DEPS.to_a.sort_by(&:first).map {|k, v| "#{k} => #{v}\n" }
- manifest_path = Path.base_system_gems.join("manifest.txt")
- # it's OK if there are extra gems
- if !manifest_path.file? || !(manifest - manifest_path.readlines).empty?
- FileUtils.rm_rf(Path.base_system_gems)
- FileUtils.mkdir_p(Path.base_system_gems)
- puts "installing gems for the tests to use..."
- install_gems(DEPS)
- manifest_path.open("wb") {|f| f << manifest.join }
- end
+ require "fileutils"
FileUtils.mkdir_p(Path.home)
FileUtils.mkdir_p(Path.tmpdir)
@@ -80,28 +38,101 @@ module Spec
Gem::DefaultUserInteraction.ui = Gem::SilentUI.new
end
- private
+ def install_parallel_test_deps
+ Gem.clear_paths
+
+ require "parallel"
+ require "fileutils"
+
+ install_test_deps
+
+ (2..Parallel.processor_count).each do |n|
+ source = Path.source_root.join("tmp", "1")
+ destination = Path.source_root.join("tmp", n.to_s)
+
+ FileUtils.rm_rf destination
+ FileUtils.cp_r source, destination
+ end
+ end
+
+ def setup_test_paths
+ Gem.clear_paths
+
+ ENV["BUNDLE_PATH"] = nil
+ ENV["GEM_HOME"] = ENV["GEM_PATH"] = Path.base_system_gems.to_s
+ ENV["PATH"] = [Path.system_gem_path.join("bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
+ ENV["PATH"] = [Path.bindir, ENV["PATH"]].join(File::PATH_SEPARATOR) if Path.ruby_core?
+ end
+
+ def install_test_deps
+ setup_test_paths
+
+ install_gems(test_gemfile)
+ install_gems(rubocop_gemfile, Path.rubocop_gems.to_s)
+ install_gems(standard_gemfile, Path.standard_gems.to_s)
+ end
+
+ private
def gem_load_and_activate(gem_name, bin_container)
gem_activate(gem_name)
load Gem.bin_path(gem_name, bin_container)
rescue Gem::LoadError => e
- abort "We couln't activate #{gem_name} (#{e.requirement}). Run `gem install #{gem_name}:'#{e.requirement}'`"
+ abort "We couldn't activate #{gem_name} (#{e.requirement}). Run `gem install #{gem_name}:'#{e.requirement}'`"
end
def gem_activate(gem_name)
- gem_requirement = DEV_DEPS[gem_name]
+ require "bundler"
+ gem_requirement = Bundler::LockfileParser.new(File.read(dev_lockfile)).dependencies[gem_name]&.requirement
gem gem_name, gem_requirement
end
- def install_gems(gems)
- reqs, no_reqs = gems.partition {|_, req| !req.nil? && !req.split(" ").empty? }
- no_reqs.map!(&:first)
- reqs.map! {|name, req| "'#{name}:#{req}'" }
- deps = reqs.concat(no_reqs).join(" ")
- gem = ENV["GEM_COMMAND"] || "#{Gem.ruby} -S gem --backtrace"
- cmd = "#{gem} install #{deps} --no-document --conservative"
- system(cmd) || raise("Installing gems #{deps} for the tests to use failed!")
+ def install_gems(gemfile, path = nil)
+ old_gemfile = ENV["BUNDLE_GEMFILE"]
+ ENV["BUNDLE_GEMFILE"] = gemfile.to_s
+
+ if path
+ old_path = ENV["BUNDLE_PATH"]
+ ENV["BUNDLE_PATH"] = path
+ else
+ old_path__system = ENV["BUNDLE_PATH__SYSTEM"]
+ ENV["BUNDLE_PATH__SYSTEM"] = "true"
+ end
+
+ output = `#{Gem.ruby} #{File.expand_path("support/bundle.rb", Path.spec_dir)} install`
+ raise "Error when installing gems in #{gemfile}: #{output}" unless $?.success?
+ ensure
+ if path
+ ENV["BUNDLE_PATH"] = old_path
+ else
+ ENV["BUNDLE_PATH__SYSTEM"] = old_path__system
+ end
+
+ ENV["BUNDLE_GEMFILE"] = old_gemfile
+ end
+
+ def test_gemfile
+ Path.test_gemfile
+ end
+
+ def rubocop_gemfile
+ Path.rubocop_gemfile
+ end
+
+ def standard_gemfile
+ Path.standard_gemfile
+ end
+
+ def dev_gemfile
+ Path.dev_gemfile
+ end
+
+ def dev_lockfile
+ lockfile_for(dev_gemfile)
+ end
+
+ def lockfile_for(gemfile)
+ Pathname.new("#{gemfile.expand_path}.lock")
end
end
end
diff --git a/spec/bundler/support/rubygems_version_manager.rb b/spec/bundler/support/rubygems_version_manager.rb
index 854bce890d..d1b1f8dd03 100644
--- a/spec/bundler/support/rubygems_version_manager.rb
+++ b/spec/bundler/support/rubygems_version_manager.rb
@@ -15,12 +15,37 @@ class RubygemsVersionManager
def switch
return if use_system?
+ assert_system_features_not_loaded!
+
switch_local_copy_if_needed
reexec_if_needed
end
-private
+ def assert_system_features_not_loaded!
+ at_exit do
+ rubylibdir = RbConfig::CONFIG["rubylibdir"]
+
+ rubygems_path = rubylibdir + "/rubygems"
+ rubygems_default_path = rubygems_path + "/defaults"
+
+ bundler_path = rubylibdir + "/bundler"
+ bundler_exemptions = Gem.rubygems_version < Gem::Version.new("3.2.0") ? [bundler_path + "/errors.rb"] : []
+
+ bad_loaded_features = $LOADED_FEATURES.select do |loaded_feature|
+ (loaded_feature.start_with?(rubygems_path) && !loaded_feature.start_with?(rubygems_default_path)) ||
+ (loaded_feature.start_with?(bundler_path) && !bundler_exemptions.any? {|bundler_exemption| loaded_feature.start_with?(bundler_exemption) })
+ end
+
+ errors = if bad_loaded_features.any?
+ all_commands_output + "the following features were incorrectly loaded:\n#{bad_loaded_features.join("\n")}"
+ end
+
+ raise errors if errors
+ end
+ end
+
+ private
def use_system?
@source.nil?
@@ -31,12 +56,9 @@ private
require "rbconfig"
- ruby = File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"])
- ruby << RbConfig::CONFIG["EXEEXT"]
+ cmd = [RbConfig.ruby, $0, *ARGV].compact
- cmd = [ruby, $0, *ARGV].compact
-
- ENV["RUBYOPT"] = "-I#{local_copy_path.join("lib")} #{ENV["RUBYOPT"]}"
+ ENV["RUBYOPT"] = opt_add("-I#{local_copy_path.join("lib")}", opt_remove("--disable-gems", ENV["RUBYOPT"]))
exec(ENV, *cmd)
end
@@ -44,15 +66,13 @@ private
def switch_local_copy_if_needed
return unless local_copy_switch_needed?
- Dir.chdir(local_copy_path) do
- sys_exec!("git remote update")
- sys_exec!("git checkout #{target_tag} --quiet")
- end
+ sys_exec("git checkout #{target_tag}", :dir => local_copy_path)
ENV["RGV"] = local_copy_path.to_s
end
def rubygems_unrequire_needed?
+ require "rubygems"
!$LOADED_FEATURES.include?(local_copy_path.join("lib/rubygems.rb").to_s)
end
@@ -65,9 +85,7 @@ private
end
def local_copy_tag
- Dir.chdir(local_copy_path) do
- sys_exec!("git rev-parse --abbrev-ref HEAD")
- end
+ sys_exec("git rev-parse --abbrev-ref HEAD", :dir => local_copy_path)
end
def local_copy_path
@@ -77,11 +95,10 @@ private
def resolve_local_copy_path
return expanded_source if source_is_path?
- rubygems_path = root.join("tmp/rubygems")
+ rubygems_path = source_root.join("tmp/rubygems")
unless rubygems_path.directory?
- rubygems_path.parent.mkpath
- sys_exec!("git clone https://github.com/rubygems/rubygems.git #{rubygems_path}")
+ sys_exec("git clone .. #{rubygems_path}", :dir => source_root)
end
rubygems_path
@@ -92,7 +109,7 @@ private
end
def expanded_source
- @expanded_source ||= Pathname.new(@source).expand_path(root)
+ @expanded_source ||= Pathname.new(@source).expand_path(source_root)
end
def resolve_target_tag
diff --git a/spec/bundler/support/sometimes.rb b/spec/bundler/support/sometimes.rb
deleted file mode 100644
index 65a95ed59c..0000000000
--- a/spec/bundler/support/sometimes.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-module Sometimes
- def run_with_retries(example_to_run, retries)
- example = RSpec.current_example
- example.metadata[:retries] ||= retries
-
- retries.times do |t|
- example.metadata[:retried] = t + 1
- example.instance_variable_set(:@exception, nil)
- example_to_run.run
- break unless example.exception
- end
-
- if e = example.exception
- new_exception = e.exception(e.message + "[Retried #{retries} times]")
- new_exception.set_backtrace e.backtrace
- example.instance_variable_set(:@exception, new_exception)
- end
- end
-end
-
-RSpec.configure do |config|
- config.include Sometimes
- config.alias_example_to :sometimes, :sometimes => true
- config.add_setting :sometimes_retry_count, :default => 5
-
- config.around(:each, :sometimes => true) do |example|
- retries = example.metadata[:retries] || RSpec.configuration.sometimes_retry_count
- run_with_retries(example, retries)
- end
-
- config.after(:suite) do
- message = proc do |color, text|
- colored = RSpec::Core::Formatters::ConsoleCodes.wrap(text, color)
- notification = RSpec::Core::Notifications::MessageNotification.new(colored)
- formatter = RSpec.configuration.formatters.first
- formatter.message(notification) if formatter.respond_to?(:message)
- end
-
- retried_examples = RSpec.world.example_groups.map do |g|
- g.descendants.map do |d|
- d.filtered_examples.select do |e|
- e.metadata[:sometimes] && e.metadata.fetch(:retried, 1) > 1
- end
- end
- end.flatten
-
- message.call(retried_examples.empty? ? :green : :yellow, "\n\nRetried examples: #{retried_examples.count}")
-
- retried_examples.each do |e|
- message.call(:cyan, " #{e.full_description}")
- path = RSpec::Core::Metadata.relative_path(e.location)
- message.call(:cyan, " [#{e.metadata[:retried]}/#{e.metadata[:retries]}] " + path)
- end
- end
-end
diff --git a/spec/bundler/support/switch_rubygems.rb b/spec/bundler/support/switch_rubygems.rb
new file mode 100644
index 0000000000..a138d22333
--- /dev/null
+++ b/spec/bundler/support/switch_rubygems.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+require_relative "rubygems_version_manager"
+RubygemsVersionManager.new(ENV["RGV"]).switch
diff --git a/spec/bundler/update/gemfile_spec.rb b/spec/bundler/update/gemfile_spec.rb
index 8c2bd9ccbf..1c5294101e 100644
--- a/spec/bundler/update/gemfile_spec.rb
+++ b/spec/bundler/update/gemfile_spec.rb
@@ -8,8 +8,8 @@ RSpec.describe "bundle update" do
gem 'rack'
G
- bundle! :install, :gemfile => bundled_app("NotGemfile")
- bundle! :update, :gemfile => bundled_app("NotGemfile"), :all => true
+ bundle :install, :gemfile => bundled_app("NotGemfile")
+ bundle :update, :gemfile => bundled_app("NotGemfile"), :all => true
# Specify BUNDLE_GEMFILE for `the_bundle`
# to retrieve the proper Gemfile
@@ -26,11 +26,11 @@ RSpec.describe "bundle update" do
G
bundle "config set --local gemfile #{bundled_app("NotGemfile")}"
- bundle! :install
+ bundle :install
end
it "uses the gemfile to update" do
- bundle! "update", :all => true
+ bundle "update", :all => true
bundle "list"
expect(out).to include("rack (1.0.0)")
@@ -38,12 +38,10 @@ RSpec.describe "bundle update" do
it "uses the gemfile while in a subdirectory" do
bundled_app("subdir").mkpath
- Dir.chdir(bundled_app("subdir")) do
- bundle! "update", :all => true
- bundle "list"
+ bundle "update", :all => true, :dir => bundled_app("subdir")
+ bundle "list", :dir => bundled_app("subdir")
- expect(out).to include("rack (1.0.0)")
- end
+ expect(out).to include("rack (1.0.0)")
end
end
end
diff --git a/spec/bundler/update/gems/fund_spec.rb b/spec/bundler/update/gems/fund_spec.rb
new file mode 100644
index 0000000000..0dfe63d36d
--- /dev/null
+++ b/spec/bundler/update/gems/fund_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle update" do
+ before do
+ build_repo2 do
+ build_gem "has_funding_and_other_metadata" do |s|
+ s.metadata = {
+ "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
+ "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
+ "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
+ "homepage_uri" => "https://bestgemever.example.io",
+ "mailing_list_uri" => "https://groups.example.com/bestgemever",
+ "funding_uri" => "https://example.com/has_funding_and_other_metadata/funding",
+ "source_code_uri" => "https://example.com/user/bestgemever",
+ "wiki_uri" => "https://example.com/user/bestgemever/wiki",
+ }
+ end
+
+ build_gem "has_funding", "1.2.3" do |s|
+ s.metadata = {
+ "funding_uri" => "https://example.com/has_funding/funding",
+ }
+ end
+ end
+
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding', '< 2.0'
+ G
+
+ bundle :install
+ end
+
+ context "when listed gems are updated" do
+ before do
+ gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem 'has_funding_and_other_metadata'
+ gem 'has_funding'
+ G
+
+ bundle :update, :all => true
+ end
+
+ it "displays fund message" do
+ expect(out).to include("2 installed gems you directly depend on are looking for funding.")
+ end
+ end
+end
diff --git a/spec/bundler/update/gems/post_install_spec.rb b/spec/bundler/update/gems/post_install_spec.rb
index 5b061eb61b..3aaa659d57 100644
--- a/spec/bundler/update/gems/post_install_spec.rb
+++ b/spec/bundler/update/gems/post_install_spec.rb
@@ -10,9 +10,9 @@ RSpec.describe "bundle update" do
gem 'thin'
G
- bundle! "config set #{config}" if config
+ bundle "config set #{config}" if config
- bundle! :install
+ bundle :install
end
shared_examples "a config observer" do
@@ -52,7 +52,7 @@ RSpec.describe "bundle update" do
gem 'thin'
G
- bundle! :update, :all => true
+ bundle :update, :all => true
end
it_behaves_like "a post-install message outputter"
@@ -67,7 +67,7 @@ RSpec.describe "bundle update" do
gem 'thin'
G
- bundle! :update, :all => true
+ bundle :update, :all => true
end
it_behaves_like "a post-install message outputter"
diff --git a/spec/bundler/update/git_spec.rb b/spec/bundler/update/git_spec.rb
index 8a41ab86db..0787ee41a7 100644
--- a/spec/bundler/update/git_spec.rb
+++ b/spec/bundler/update/git_spec.rb
@@ -7,12 +7,13 @@ RSpec.describe "bundle update" do
update_git "foo", :branch => "omg"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo-1.0")}", :branch => "omg" do
gem 'foo'
end
G
- update_git "foo", :branch => "omg" do |s|
+ update_git "foo" do |s|
s.write "lib/foo.rb", "FOO = '1.1'"
end
@@ -27,11 +28,12 @@ RSpec.describe "bundle update" do
s.add_dependency "activesupport", "= 3.0"
end
- install_gemfile! <<-G
- gem "rails", :git => "#{lib_path("rails")}"
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rails", :git => "#{file_uri_for(lib_path("rails"))}"
G
- bundle! "update rails"
+ bundle "update rails"
expect(the_bundle).to include_gems "rails 3.0", "activesupport 3.0"
end
@@ -40,12 +42,13 @@ RSpec.describe "bundle update" do
update_git "foo", :branch => "omg", :path => lib_path("foo")
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
git "#{lib_path("foo")}", :branch => "omg" do
gem 'foo'
end
G
- update_git "foo", :branch => "omg", :path => lib_path("foo") do |s|
+ update_git "foo", :path => lib_path("foo") do |s|
s.write "lib/foo.rb", "FOO = '1.1'"
end
@@ -61,7 +64,8 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- gem "foo", :git => "#{lib_path("foo")}"
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo"))}"
gem "bar"
G
@@ -79,17 +83,19 @@ RSpec.describe "bundle update" do
build_git "foo", :path => lib_path("foo_two")
install_gemfile <<-G
- gem "foo", "1.0", :git => "#{lib_path("foo_one")}"
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", "1.0", :git => "#{file_uri_for(lib_path("foo_one"))}"
G
FileUtils.rm_rf lib_path("foo_one")
install_gemfile <<-G
- gem "foo", "1.0", :git => "#{lib_path("foo_two")}"
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", "1.0", :git => "#{file_uri_for(lib_path("foo_two"))}"
G
expect(err).to be_empty
- expect(out).to include("Fetching #{lib_path}/foo_two")
+ expect(out).to include("Fetching #{file_uri_for(lib_path)}/foo_two")
expect(out).to include("Bundle complete!")
end
@@ -100,6 +106,7 @@ RSpec.describe "bundle update" do
update_git "foo", :push => "master"
install_gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', :git => "#{@remote.path}"
G
@@ -108,18 +115,15 @@ RSpec.describe "bundle update" do
update_git "foo", :push => "fubar"
gemfile <<-G
+ source "#{file_uri_for(gem_repo1)}"
gem 'foo', :git => "#{@remote.path}", :tag => "fubar"
G
bundle "update", :all => true
- expect(exitstatus).to eq(0) if exitstatus
end
describe "with submodules" do
before :each do
- # CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
- system(*%W[git config --global protocol.file.allow always])
-
build_repo4 do
build_gem "submodule" do |s|
s.write "lib/submodule.rb", "puts 'GEM'"
@@ -134,10 +138,8 @@ RSpec.describe "bundle update" do
s.add_dependency "submodule"
end
- Dir.chdir(lib_path("has_submodule-1.0")) do
- sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0"
- `git commit -m "submodulator"`
- end
+ sys_exec "git submodule add #{lib_path("submodule-1.0")} submodule-1.0", :dir => lib_path("has_submodule-1.0")
+ sys_exec "git commit -m \"submodulator\"", :dir => lib_path("has_submodule-1.0")
end
it "it unlocks the source when submodules are added to a git source" do
@@ -163,24 +165,24 @@ RSpec.describe "bundle update" do
end
it "unlocks the source when submodules are removed from git source", :git => ">= 2.9.0" do
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
G
- run! "require 'submodule'"
+ run "require 'submodule'"
expect(out).to eq("GIT")
- install_gemfile! <<-G
+ install_gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
G
- run! "require 'submodule'"
+ run "require 'submodule'"
expect(out).to eq("GEM")
end
end
@@ -189,12 +191,13 @@ RSpec.describe "bundle update" do
build_git "foo", "1.0"
install_gemfile <<-G
- gem "foo", :git => "#{lib_path("foo-1.0")}"
+ source "#{file_uri_for(gem_repo1)}"
+ gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}"
G
lib_path("foo-1.0").join(".git").rmtree
- bundle :update, :all => true
+ bundle :update, :all => true, :raise_on_error => false
expect(err).to include(lib_path("foo-1.0").to_s).
and match(/Git error: command `git fetch.+has failed/)
end
@@ -208,7 +211,7 @@ RSpec.describe "bundle update" do
install_gemfile <<-G
source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "master"
+ gem "rack", :git => "#{file_uri_for(lib_path("rack-0.8"))}", :branch => "master"
G
bundle %(config set local.rack #{lib_path("local-rack")})
@@ -217,27 +220,17 @@ RSpec.describe "bundle update" do
end
it "shows the previous version of the gem" do
- build_git "rails", "3.0", :path => lib_path("rails")
+ build_git "rails", "2.3.2", :path => lib_path("rails")
install_gemfile <<-G
- gem "rails", :git => "#{lib_path("rails")}"
+ source "#{file_uri_for(gem_repo1)}"
+ gem "rails", :git => "#{file_uri_for(lib_path("rails"))}"
G
- lockfile <<-G
- GIT
- remote: #{lib_path("rails")}
- specs:
- rails (2.3.2)
-
- PLATFORMS
- #{generic_local_platform}
-
- DEPENDENCIES
- rails!
- G
+ update_git "rails", "3.0", :path => lib_path("rails"), :gemspec => true
bundle "update", :all => true
- expect(out).to include("Using rails 3.0 (was 2.3.2) from #{lib_path("rails")} (at master@#{revision_for(lib_path("rails"))[0..6]})")
+ expect(out).to include("Using rails 3.0 (was 2.3.2) from #{file_uri_for(lib_path("rails"))} (at master@#{revision_for(lib_path("rails"))[0..6]})")
end
end
@@ -262,14 +255,12 @@ RSpec.describe "bundle update" do
bundle "update --source foo"
- in_app_root do
- run <<-RUBY
- require 'foo'
- puts "WIN" if defined?(FOO_PREV_REF)
- RUBY
+ run <<-RUBY
+ require 'foo'
+ puts "WIN" if defined?(FOO_PREV_REF)
+ RUBY
- expect(out).to eq("WIN")
- end
+ expect(out).to eq("WIN")
end
it "unlocks gems that were originally pulled in by the source" do
@@ -302,43 +293,7 @@ RSpec.describe "bundle update" do
G
end
- it "the --source flag updates version of gems that were originally pulled in by the source", :bundler => "< 3" do
- spec_lines = lib_path("bar/foo.gemspec").read.split("\n")
- spec_lines[5] = "s.version = '2.0'"
-
- update_git "foo", "2.0", :path => @git.path do |s|
- s.write "foo.gemspec", spec_lines.join("\n")
- end
-
- ref = @git.ref_for "master"
-
- bundle "update --source bar"
-
- lockfile_should_be <<-G
- GIT
- remote: #{@git.path}
- revision: #{ref}
- specs:
- foo (2.0)
-
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{lockfile_platforms}
-
- DEPENDENCIES
- foo!
- rack
-
- BUNDLED WITH
- #{Bundler::VERSION}
- G
- end
-
- it "the --source flag updates version of gems that were originally pulled in by the source", :bundler => "3" do
+ it "the --source flag updates version of gems that were originally pulled in by the source" do
spec_lines = lib_path("bar/foo.gemspec").read.split("\n")
spec_lines[5] = "s.version = '2.0'"
@@ -350,7 +305,7 @@ RSpec.describe "bundle update" do
bundle "update --source bar"
- lockfile_should_be <<-G
+ expect(lockfile).to eq <<~G
GIT
remote: #{@git.path}
revision: #{ref}
diff --git a/spec/bundler/update/path_spec.rb b/spec/bundler/update/path_spec.rb
index 38c125e04b..756770313b 100644
--- a/spec/bundler/update/path_spec.rb
+++ b/spec/bundler/update/path_spec.rb
@@ -6,6 +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)}"
gem "activesupport", :path => "#{lib_path("rails/activesupport")}"
G
diff --git a/spec/bundler/update/redownload_spec.rb b/spec/bundler/update/redownload_spec.rb
index b34a02c78c..147be823f5 100644
--- a/spec/bundler/update/redownload_spec.rb
+++ b/spec/bundler/update/redownload_spec.rb
@@ -10,24 +10,24 @@ RSpec.describe "bundle update" do
describe "with --force" do
it "shows a deprecation when single flag passed", :bundler => 2 do
- bundle! "update rack --force"
+ bundle "update rack --force"
expect(err).to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
end
it "shows a deprecation when multiple flags passed", :bundler => 2 do
- bundle! "update rack --no-color --force"
+ bundle "update rack --no-color --force"
expect(err).to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
end
end
describe "with --redownload" do
it "does not show a deprecation when single flag passed" do
- bundle! "update rack --redownload"
+ bundle "update rack --redownload"
expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
end
it "does not show a deprecation when single multiple flags passed" do
- bundle! "update rack --no-color --redownload"
+ bundle "update rack --no-color --redownload"
expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
end
end
diff --git a/spec/mspec/Gemfile b/spec/mspec/Gemfile
index 3dc3c4145b..8e463cd71d 100644
--- a/spec/mspec/Gemfile
+++ b/spec/mspec/Gemfile
@@ -1,4 +1,4 @@
source 'https://rubygems.org'
-gem "rake", "~> 10.0"
+gem "rake", "~> 12.3"
gem "rspec", "~> 2.14.1"
diff --git a/spec/mspec/Gemfile.lock b/spec/mspec/Gemfile.lock
index ce0aa98417..74489c5aca 100644
--- a/spec/mspec/Gemfile.lock
+++ b/spec/mspec/Gemfile.lock
@@ -2,7 +2,7 @@ GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.3)
- rake (10.5.0)
+ rake (12.3.3)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
@@ -17,5 +17,5 @@ PLATFORMS
ruby
DEPENDENCIES
- rake (~> 10.0)
+ rake (~> 12.3)
rspec (~> 2.14.1)
diff --git a/spec/mspec/README.md b/spec/mspec/README.md
index e6fe44c6a2..d4054bcf0f 100644
--- a/spec/mspec/README.md
+++ b/spec/mspec/README.md
@@ -1,5 +1,3 @@
-[![Build Status](https://travis-ci.org/ruby/mspec.svg?branch=master)](https://travis-ci.org/ruby/mspec)
-
## Overview
MSpec is a specialized framework that is syntax-compatible with RSpec 2 for
@@ -38,7 +36,7 @@ specs in a manner compatible with multiple Ruby implementations.
## Requirements
-MSpec requires Ruby 2.4 or more recent.
+MSpec requires Ruby 2.5 or more recent.
## Bundler
diff --git a/spec/mspec/lib/mspec/expectations/should.rb b/spec/mspec/lib/mspec/expectations/should.rb
index 231ad15c21..ca0617484c 100644
--- a/spec/mspec/lib/mspec/expectations/should.rb
+++ b/spec/mspec/lib/mspec/expectations/should.rb
@@ -3,7 +3,10 @@ class Object
def should(matcher = NO_MATCHER_GIVEN)
MSpec.expectation
- MSpec.actions :expectation, MSpec.current.state
+ state = MSpec.current.state
+ raise "should outside example" unless state
+ MSpec.actions :expectation, state
+
if NO_MATCHER_GIVEN.equal?(matcher)
SpecPositiveOperatorMatcher.new(self)
else
@@ -16,7 +19,10 @@ class Object
def should_not(matcher = NO_MATCHER_GIVEN)
MSpec.expectation
- MSpec.actions :expectation, MSpec.current.state
+ state = MSpec.current.state
+ raise "should_not outside example" unless state
+ MSpec.actions :expectation, state
+
if NO_MATCHER_GIVEN.equal?(matcher)
SpecNegativeOperatorMatcher.new(self)
else
diff --git a/spec/mspec/lib/mspec/guards/bug.rb b/spec/mspec/lib/mspec/guards/bug.rb
index b1bfc6413e..a6af0ef964 100644
--- a/spec/mspec/lib/mspec/guards/bug.rb
+++ b/spec/mspec/lib/mspec/guards/bug.rb
@@ -1,28 +1,29 @@
require 'mspec/guards/version'
class BugGuard < VersionGuard
- def initialize(bug, version)
+ def initialize(bug, requirement)
@bug = bug
- if String === version
+ if String === requirement
MSpec.deprecate "ruby_bug with a single version", 'an exclusive range ("2.1"..."2.3")'
- @version = SpecVersion.new version, true
+ super(FULL_RUBY_VERSION, requirement)
+ @requirement = SpecVersion.new requirement, true
else
- super(version)
+ super(FULL_RUBY_VERSION, requirement)
end
- @parameters = [@bug, @version]
end
def match?
return false if MSpec.mode? :no_ruby_bug
return false unless PlatformGuard.standard?
- if Range === @version
+
+ if Range === @requirement
super
else
- FULL_RUBY_VERSION <= @version
+ FULL_RUBY_VERSION <= @requirement
end
end
end
-def ruby_bug(bug, version, &block)
- BugGuard.new(bug, version).run_unless(:ruby_bug, &block)
+def ruby_bug(bug, requirement, &block)
+ BugGuard.new(bug, requirement).run_unless(:ruby_bug, &block)
end
diff --git a/spec/mspec/lib/mspec/guards/guard.rb b/spec/mspec/lib/mspec/guards/guard.rb
index 322a08145d..3a6372a660 100644
--- a/spec/mspec/lib/mspec/guards/guard.rb
+++ b/spec/mspec/lib/mspec/guards/guard.rb
@@ -111,7 +111,7 @@ class SpecGuard
def add(example)
record example.description
- MSpec.retrieve(:formatter).tally.counter.guards!
+ MSpec.formatter.tally.counter.guards!
end
def unregister
diff --git a/spec/mspec/lib/mspec/guards/platform.rb b/spec/mspec/lib/mspec/guards/platform.rb
index 2d22d4fb59..2d5c2de6b6 100644
--- a/spec/mspec/lib/mspec/guards/platform.rb
+++ b/spec/mspec/lib/mspec/guards/platform.rb
@@ -26,8 +26,11 @@ class PlatformGuard < SpecGuard
def self.os?(*oses)
oses.any? do |os|
raise ":java is not a valid OS" if os == :java
- if os == :windows
+ case os
+ when :windows
PLATFORM =~ /(mswin|mingw)/
+ when :wsl
+ wsl?
else
PLATFORM.include?(os.to_s)
end
@@ -38,6 +41,14 @@ class PlatformGuard < SpecGuard
os?(:windows)
end
+ def self.wsl?
+ if defined?(@wsl_p)
+ @wsl_p
+ else
+ @wsl_p = `uname -r`.match?(/microsoft/i)
+ end
+ end
+
WORD_SIZE = 1.size * 8
POINTER_SIZE = begin
diff --git a/spec/mspec/lib/mspec/guards/version.rb b/spec/mspec/lib/mspec/guards/version.rb
index cb08fdac73..20f8c06d38 100644
--- a/spec/mspec/lib/mspec/guards/version.rb
+++ b/spec/mspec/lib/mspec/guards/version.rb
@@ -5,33 +5,40 @@ require 'mspec/guards/guard'
class VersionGuard < SpecGuard
FULL_RUBY_VERSION = SpecVersion.new SpecGuard.ruby_version(:full)
- def initialize(version)
- case version
+ def initialize(version, requirement)
+ version = SpecVersion.new(version) unless SpecVersion === version
+ @version = version
+
+ case requirement
when String
- @version = SpecVersion.new version
+ @requirement = SpecVersion.new requirement
when Range
- MSpec.deprecate "an empty version range end", 'a specific version' if version.end.empty?
- a = SpecVersion.new version.begin
- b = SpecVersion.new version.end
- unless version.exclude_end?
+ MSpec.deprecate "an empty version range end", 'a specific version' if requirement.end.empty?
+ a = SpecVersion.new requirement.begin
+ b = SpecVersion.new requirement.end
+ unless requirement.exclude_end?
MSpec.deprecate "ruby_version_is with an inclusive range", 'an exclusive range ("2.1"..."2.3")'
end
- @version = version.exclude_end? ? a...b : a..b
+ @requirement = requirement.exclude_end? ? a...b : a..b
else
- raise "version must be a String or Range but was a #{version.class}"
+ raise "version must be a String or Range but was a #{requirement.class}"
end
- @parameters = [version]
+ super(@version, @requirement)
end
def match?
- if Range === @version
- @version.include? FULL_RUBY_VERSION
+ if Range === @requirement
+ @requirement.include? @version
else
- FULL_RUBY_VERSION >= @version
+ @version >= @requirement
end
end
end
-def ruby_version_is(*args, &block)
- VersionGuard.new(*args).run_if(:ruby_version_is, &block)
+def version_is(base_version, requirement, &block)
+ VersionGuard.new(base_version, requirement).run_if(:version_is, &block)
+end
+
+def ruby_version_is(requirement, &block)
+ VersionGuard.new(VersionGuard::FULL_RUBY_VERSION, requirement).run_if(:ruby_version_is, &block)
end
diff --git a/spec/mspec/lib/mspec/helpers.rb b/spec/mspec/lib/mspec/helpers.rb
index b7ac9f4e85..90f9fd3fd4 100644
--- a/spec/mspec/lib/mspec/helpers.rb
+++ b/spec/mspec/lib/mspec/helpers.rb
@@ -3,7 +3,6 @@ require 'mspec/helpers/argv'
require 'mspec/helpers/datetime'
require 'mspec/helpers/fixture'
require 'mspec/helpers/flunk'
-require 'mspec/helpers/frozen_error_class'
require 'mspec/helpers/fs'
require 'mspec/helpers/io'
require 'mspec/helpers/mock_to_path'
diff --git a/spec/mspec/lib/mspec/helpers/frozen_error_class.rb b/spec/mspec/lib/mspec/helpers/frozen_error_class.rb
deleted file mode 100644
index 07cc2b4ba2..0000000000
--- a/spec/mspec/lib/mspec/helpers/frozen_error_class.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'mspec/guards/version'
-
-# This helper makes it easy to write version independent
-# specs for frozen objects.
-unless respond_to? :frozen_error_class, true
- ruby_version_is "2.5" do
- def frozen_error_class
- FrozenError
- end
- end
-
- ruby_version_is ""..."2.5" do
- def frozen_error_class
- RuntimeError
- end
- end
-end
diff --git a/spec/mspec/lib/mspec/helpers/io.rb b/spec/mspec/lib/mspec/helpers/io.rb
index 1938255d1a..29c6c37a1a 100644
--- a/spec/mspec/lib/mspec/helpers/io.rb
+++ b/spec/mspec/lib/mspec/helpers/io.rb
@@ -85,7 +85,3 @@ def new_io(name, mode = "w:utf-8")
File.new(name, mode)
end
end
-
-def find_unused_fd
- Dir.entries("/dev/fd").map(&:to_i).max + 1
-end
diff --git a/spec/mspec/lib/mspec/helpers/numeric.rb b/spec/mspec/lib/mspec/helpers/numeric.rb
index c6c2e82722..db1fde64d8 100644
--- a/spec/mspec/lib/mspec/helpers/numeric.rb
+++ b/spec/mspec/lib/mspec/helpers/numeric.rb
@@ -12,6 +12,14 @@ def bignum_value(plus = 0)
0x8000_0000_0000_0000 + plus
end
+def max_long
+ 2**(0.size * 8 - 1) - 1
+end
+
+def min_long
+ -(2**(0.size * 8 - 1))
+end
+
# This is a bit hairy, but we need to be able to write specs that cover the
# boundary between Fixnum and Bignum for operations like Fixnum#<<. Since
# this boundary is implementation-dependent, we use these helpers to write
diff --git a/spec/mspec/lib/mspec/helpers/ruby_exe.rb b/spec/mspec/lib/mspec/helpers/ruby_exe.rb
index 6d5470bbb5..075a8aaef5 100644
--- a/spec/mspec/lib/mspec/helpers/ruby_exe.rb
+++ b/spec/mspec/lib/mspec/helpers/ruby_exe.rb
@@ -153,5 +153,7 @@ def ruby_cmd(code, opts = {})
body = "-e #{code.inspect}"
end
- [RUBY_EXE, opts[:options], body, opts[:args]].compact.join(' ')
+ command = [RUBY_EXE, opts[:options], body, opts[:args]].compact.join(' ')
+ STDERR.puts "\nruby_cmd: #{command}" if ENV["DEBUG_MSPEC_RUBY_CMD"] == "true"
+ command
end
diff --git a/spec/mspec/lib/mspec/helpers/scratch.rb b/spec/mspec/lib/mspec/helpers/scratch.rb
index a6b0c02748..0da3315cd8 100644
--- a/spec/mspec/lib/mspec/helpers/scratch.rb
+++ b/spec/mspec/lib/mspec/helpers/scratch.rb
@@ -14,4 +14,8 @@ module ScratchPad
def self.recorded
@record
end
+
+ def self.inspect
+ "<ScratchPad @record=#{@record.inspect}>"
+ end
end
diff --git a/spec/mspec/lib/mspec/helpers/tmp.rb b/spec/mspec/lib/mspec/helpers/tmp.rb
index 1677fb4f14..b2a38ee983 100644
--- a/spec/mspec/lib/mspec/helpers/tmp.rb
+++ b/spec/mspec/lib/mspec/helpers/tmp.rb
@@ -3,11 +3,16 @@
# should clean up any temporary files created so that the temp
# directory is empty when the process exits.
-SPEC_TEMP_DIR = File.expand_path(ENV["SPEC_TEMP_DIR"] || "rubyspec_temp")
+SPEC_TEMP_DIR_PID = Process.pid
-SPEC_TEMP_UNIQUIFIER = "0"
+if spec_temp_dir = ENV["SPEC_TEMP_DIR"]
+ spec_temp_dir = File.realdirpath(spec_temp_dir)
+else
+ spec_temp_dir = "#{File.realpath(Dir.pwd)}/rubyspec_temp/#{SPEC_TEMP_DIR_PID}"
+end
+SPEC_TEMP_DIR = spec_temp_dir
-SPEC_TEMP_DIR_PID = Process.pid
+SPEC_TEMP_UNIQUIFIER = "0"
at_exit do
begin
@@ -31,7 +36,7 @@ all specs are cleaning up temporary files:
end
def tmp(name, uniquify = true)
- Dir.mkdir SPEC_TEMP_DIR unless Dir.exist? SPEC_TEMP_DIR
+ mkdir_p SPEC_TEMP_DIR unless Dir.exist? SPEC_TEMP_DIR
if uniquify and !name.empty?
slash = name.rindex "/"
diff --git a/spec/mspec/lib/mspec/matchers/include.rb b/spec/mspec/lib/mspec/matchers/include.rb
index 0b7eaf3ce2..3f07f35548 100644
--- a/spec/mspec/lib/mspec/matchers/include.rb
+++ b/spec/mspec/lib/mspec/matchers/include.rb
@@ -15,11 +15,11 @@ class IncludeMatcher
end
def failure_message
- ["Expected #{@actual.inspect}", "to include #{@element.inspect}"]
+ ["Expected #{MSpec.format(@actual)}", "to include #{MSpec.format(@element)}"]
end
def negative_failure_message
- ["Expected #{@actual.inspect}", "not to include #{@element.inspect}"]
+ ["Expected #{MSpec.format(@actual)}", "not to include #{MSpec.format(@element)}"]
end
end
diff --git a/spec/mspec/lib/mspec/matchers/raise_error.rb b/spec/mspec/lib/mspec/matchers/raise_error.rb
index 0e57c1b863..878428d43a 100644
--- a/spec/mspec/lib/mspec/matchers/raise_error.rb
+++ b/spec/mspec/lib/mspec/matchers/raise_error.rb
@@ -6,34 +6,43 @@ class RaiseErrorMatcher
@actual = nil
end
+ # This #matches? method is unusual because it doesn't always return a boolean but instead
+ # re-raises the original exception if proc.call raises an exception and #matching_exception? is false.
+ # The reasoning is the original exception class matters and we don't want to change it by raising another exception,
+ # so instead we attach the #failure_message and extract it in ExceptionState#message.
def matches?(proc)
@result = proc.call
return false
rescue Exception => actual
@actual = actual
+
if matching_exception?(actual)
# The block has its own expectations and will throw an exception if it fails
@block[actual] if @block
-
return true
else
+ actual.instance_variable_set(:@mspec_raise_error_message, failure_message)
raise actual
end
end
- def matching_exception?(exc)
- return false unless @exception === exc
+ def matching_class?(exc)
+ @exception === exc
+ end
- if @message then
- case @message
- when String
- return false if @message != exc.message
- when Regexp
- return false if @message !~ exc.message
- end
+ def matching_message?(exc)
+ case @message
+ when String
+ @message == exc.message
+ when Regexp
+ @message =~ exc.message
+ else
+ true
end
+ end
- return true
+ def matching_exception?(exc)
+ matching_class?(exc) and matching_message?(exc)
end
def exception_class_and_message(exception_class, message)
@@ -56,7 +65,7 @@ class RaiseErrorMatcher
message = ["Expected #{format_expected_exception}"]
if @actual
- message << "but got #{format_exception(@actual)}"
+ message << "but got: #{format_exception(@actual)}"
else
message << "but no exception was raised (#{MSpec.format(@result)} was returned)"
end
@@ -67,7 +76,7 @@ class RaiseErrorMatcher
def negative_failure_message
message = ["Expected to not get #{format_expected_exception}", ""]
unless @actual.class == @exception
- message[1] = "but got #{format_exception(@actual)}"
+ message[1] = "but got: #{format_exception(@actual)}"
end
message
end
diff --git a/spec/mspec/lib/mspec/mocks/mock.rb b/spec/mspec/lib/mspec/mocks/mock.rb
index bce41b630f..28a083cc15 100644
--- a/spec/mspec/lib/mspec/mocks/mock.rb
+++ b/spec/mspec/lib/mspec/mocks/mock.rb
@@ -180,7 +180,7 @@ module Mock
mock_respond_to? obj, *args
else
SpecExpectation.fail_with("Mock '#{name_or_inspect obj}': method #{sym}\n",
- "called with unexpected arguments #{inspect_args compare}")
+ "called with unexpected arguments #{inspect_args args}")
end
end
diff --git a/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb b/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb
index fd0a3efe14..abfb6dd0ee 100644
--- a/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb
+++ b/spec/mspec/lib/mspec/runner/actions/constants_leak_checker.rb
@@ -1,9 +1,14 @@
class ConstantsLockFile
LOCK_FILE_NAME = '.mspec.constants'
+ def self.lock_file
+ @prefix ||= File.expand_path(MSpecScript.get(:prefix) || '.')
+ "#{@prefix}/#{LOCK_FILE_NAME}"
+ end
+
def self.load
- if File.exist?(LOCK_FILE_NAME)
- File.readlines(LOCK_FILE_NAME).map(&:chomp)
+ if File.exist?(lock_file)
+ File.readlines(lock_file).map(&:chomp)
else
[]
end
@@ -11,7 +16,7 @@ class ConstantsLockFile
def self.dump(ary)
contents = ary.map(&:to_s).uniq.sort.join("\n") + "\n"
- File.write(LOCK_FILE_NAME, contents)
+ File.write(lock_file, contents)
end
end
diff --git a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
index f70799d904..596b120d9f 100644
--- a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
+++ b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
@@ -36,6 +36,7 @@ class LeakChecker
@thread_info = find_threads
@env_info = find_env
@argv_info = find_argv
+ @globals_info = find_globals
@encoding_info = find_encodings
end
@@ -48,8 +49,10 @@ class LeakChecker
check_process_leak
check_env
check_argv
+ check_globals
check_encodings
- GC.start if !@leaks.empty?
+ check_tracepoints
+ GC.start unless @leaks.empty?
@leaks.empty?
end
@@ -243,6 +246,19 @@ class LeakChecker
end
end
+ def find_globals
+ { verbose: $VERBOSE, debug: $DEBUG }
+ end
+
+ def check_globals
+ old_globals = @globals_info
+ new_globals = find_globals
+ if new_globals != old_globals
+ leak "Globals changed: #{old_globals.inspect} to #{new_globals.inspect}"
+ @globals_info = new_globals
+ end
+ end
+
def find_encodings
[Encoding.default_internal, Encoding.default_external]
end
@@ -259,6 +275,14 @@ class LeakChecker
@encoding_info = [new_internal, new_external]
end
+ def check_tracepoints
+ ObjectSpace.each_object(TracePoint) do |tp|
+ if tp.enabled?
+ leak "TracePoint is still enabled: #{tp.inspect}"
+ end
+ end
+ end
+
def leak(message)
if @leaks.empty?
$stderr.puts "\n"
diff --git a/spec/mspec/lib/mspec/runner/actions/timeout.rb b/spec/mspec/lib/mspec/runner/actions/timeout.rb
index 03fe14811f..c85bf49ad3 100644
--- a/spec/mspec/lib/mspec/runner/actions/timeout.rb
+++ b/spec/mspec/lib/mspec/runner/actions/timeout.rb
@@ -37,7 +37,7 @@ class TimeoutAction
if elapsed > @timeout
STDERR.puts "\n#{@current_state.description}"
STDERR.flush
- abort "Example took #{now - @started}s, which is longer than the timeout of #{@timeout}s"
+ abort "Example took longer than the configured timeout of #{@timeout}s"
end
end
end
diff --git a/spec/mspec/lib/mspec/runner/context.rb b/spec/mspec/lib/mspec/runner/context.rb
index 5f6c9c8ae9..62483590bb 100644
--- a/spec/mspec/lib/mspec/runner/context.rb
+++ b/spec/mspec/lib/mspec/runner/context.rb
@@ -12,15 +12,14 @@
class ContextState
attr_reader :state, :parent, :parents, :children, :examples, :to_s
- def initialize(mod, options = nil)
- @to_s = mod.to_s
- if options.is_a? Hash
- @options = options
- else
- @to_s += "#{".:#".include?(options[0,1]) ? "" : " "}#{options}" if options
- @options = { }
- end
- @options[:shared] ||= false
+ MOCK_VERIFY = -> { Mock.verify_count }
+ MOCK_CLEANUP = -> { Mock.cleanup }
+ EXPECTATION_MISSING = -> { raise SpecExpectationNotFoundError }
+
+ def initialize(description, options = nil)
+ raise "#describe options should be a Hash or nil" unless Hash === options or options.nil?
+ @to_s = description.to_s
+ @shared = options && options[:shared]
@parsed = false
@before = { :all => [], :each => [] }
@@ -28,13 +27,10 @@ class ContextState
@pre = {}
@post = {}
@examples = []
+ @state = nil
@parent = nil
@parents = [self]
@children = []
-
- @mock_verify = Proc.new { Mock.verify_count }
- @mock_cleanup = Proc.new { Mock.cleanup }
- @expectation_missing = Proc.new { raise SpecExpectationNotFoundError }
end
# Remove caching when a ContextState is dup'd for shared specs.
@@ -46,7 +42,7 @@ class ContextState
# Returns true if this is a shared +ContextState+. Essentially, when
# created with: describe "Something", :shared => true { ... }
def shared?
- return @options[:shared]
+ @shared
end
# Set the parent (enclosing) +ContextState+ for this state. Creates
@@ -127,6 +123,7 @@ class ContextState
# Creates an ExampleState instance for the block and stores it
# in a list of examples to evaluate unless the example is filtered.
def it(desc, &block)
+ raise "nested #it" if @state
example = ExampleState.new(self, desc, block)
MSpec.actions :add, example
return if MSpec.guarded?
@@ -205,7 +202,7 @@ class ContextState
if protect "before :all", pre(:all)
@examples.each do |state|
MSpec.repeat do
- @state = state
+ @state = state
example = state.example
MSpec.actions :before, state
@@ -214,20 +211,20 @@ class ContextState
if example
passed = protect nil, example
MSpec.actions :example, state, example
- protect nil, @expectation_missing if !MSpec.expectation? and passed
+ protect nil, EXPECTATION_MISSING if !MSpec.expectation? and passed
end
end
protect "after :each", post(:each)
- protect "Mock.verify_count", @mock_verify
+ protect "Mock.verify_count", MOCK_VERIFY
- protect "Mock.cleanup", @mock_cleanup
+ protect "Mock.cleanup", MOCK_CLEANUP
MSpec.actions :after, state
@state = nil
end
end
protect "after :all", post(:all)
else
- protect "Mock.cleanup", @mock_cleanup
+ protect "Mock.cleanup", MOCK_CLEANUP
end
MSpec.actions :leave
diff --git a/spec/mspec/lib/mspec/runner/example.rb b/spec/mspec/lib/mspec/runner/example.rb
index 82feba0b03..0d9f0d618c 100644
--- a/spec/mspec/lib/mspec/runner/example.rb
+++ b/spec/mspec/lib/mspec/runner/example.rb
@@ -3,12 +3,12 @@ require 'mspec/runner/mspec'
# Holds some of the state of the example (i.e. +it+ block) that is
# being evaluated. See also +ContextState+.
class ExampleState
- attr_reader :context, :it, :example
+ attr_reader :context, :it, :example
def initialize(context, it, example = nil)
- @context = context
- @it = it
- @example = example
+ @context = context
+ @it = it
+ @example = example
end
def context=(context)
@@ -25,8 +25,8 @@ class ExampleState
end
def filtered?
- incl = MSpec.retrieve(:include) || []
- excl = MSpec.retrieve(:exclude) || []
+ incl = MSpec.include
+ excl = MSpec.exclude
included = incl.empty? || incl.any? { |f| f === description }
included &&= excl.empty? || !excl.any? { |f| f === description }
!included
diff --git a/spec/mspec/lib/mspec/runner/exception.rb b/spec/mspec/lib/mspec/runner/exception.rb
index 0d9bb43105..e07f02f684 100644
--- a/spec/mspec/lib/mspec/runner/exception.rb
+++ b/spec/mspec/lib/mspec/runner/exception.rb
@@ -6,6 +6,7 @@ class ExceptionState
def initialize(state, location, exception)
@exception = exception
+ @failure = exception.class == SpecExpectationNotMetError || exception.class == SpecExpectationNotFoundError
@description = location ? "An exception occurred during: #{location}" : ""
if state
@@ -19,25 +20,35 @@ class ExceptionState
end
def failure?
- [SpecExpectationNotMetError, SpecExpectationNotFoundError].any? { |e| @exception.is_a? e }
+ @failure
end
def message
- if @exception.message.empty?
- "<No message>"
- elsif @exception.class == SpecExpectationNotMetError ||
- @exception.class == SpecExpectationNotFoundError
- @exception.message
+ message = @exception.message
+ message = "<No message>" if message.empty?
+
+ if @failure
+ message
+ elsif raise_error_message = @exception.instance_variable_get(:@mspec_raise_error_message)
+ raise_error_message.join("\n")
else
- "#{@exception.class}: #{@exception.message}"
+ "#{@exception.class}: #{message}"
end
end
def backtrace
- @backtrace_filter ||= MSpecScript.config[:backtrace_filter]
+ @backtrace_filter ||= MSpecScript.config[:backtrace_filter] || %r{(?:/bin/mspec|/lib/mspec/)}
bt = @exception.backtrace || []
-
- bt.select { |line| $MSPEC_DEBUG or @backtrace_filter !~ line }.join("\n")
+ unless $MSPEC_DEBUG
+ # Exclude <internal: entries inside MSpec code, so only after the first ignored entry
+ first_excluded_line = bt.index { |line| @backtrace_filter =~ line }
+ if first_excluded_line
+ bt = bt[0...first_excluded_line] + bt[first_excluded_line..-1].reject { |line|
+ @backtrace_filter =~ line || /^<internal:/ =~ line
+ }
+ end
+ end
+ bt.join("\n")
end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters.rb b/spec/mspec/lib/mspec/runner/formatters.rb
index d085031a12..66f515ddff 100644
--- a/spec/mspec/lib/mspec/runner/formatters.rb
+++ b/spec/mspec/lib/mspec/runner/formatters.rb
@@ -7,6 +7,7 @@ require 'mspec/runner/formatters/summary'
require 'mspec/runner/formatters/unit'
require 'mspec/runner/formatters/spinner'
require 'mspec/runner/formatters/method'
+require 'mspec/runner/formatters/stats'
require 'mspec/runner/formatters/yaml'
require 'mspec/runner/formatters/profile'
require 'mspec/runner/formatters/junit'
diff --git a/spec/mspec/lib/mspec/runner/formatters/method.rb b/spec/mspec/lib/mspec/runner/formatters/method.rb
index 8fe02575c4..925858c845 100644
--- a/spec/mspec/lib/mspec/runner/formatters/method.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/method.rb
@@ -6,13 +6,13 @@ class MethodFormatter < BaseFormatter
def initialize(out = nil)
super(out)
@methods = Hash.new do |h, k|
- hash = {}
- hash[:examples] = 0
- hash[:expectations] = 0
- hash[:failures] = 0
- hash[:errors] = 0
- hash[:exceptions] = []
- h[k] = hash
+ h[k] = {
+ examples: 0,
+ expectations: 0,
+ failures: 0,
+ errors: 0,
+ exceptions: []
+ }
end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/spinner.rb b/spec/mspec/lib/mspec/runner/formatters/spinner.rb
index 8815e1a48a..817d8c02be 100644
--- a/spec/mspec/lib/mspec/runner/formatters/spinner.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/spinner.rb
@@ -78,7 +78,7 @@ class SpinnerFormatter < BaseFormatter
# Callback for the MSpec :start event. Stores the total
# number of files that will be processed.
def start
- @total = MSpec.retrieve(:files).size
+ @total = MSpec.files_array.size
compute_progress
print progress_line
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/stats.rb b/spec/mspec/lib/mspec/runner/formatters/stats.rb
new file mode 100644
index 0000000000..8cff96d145
--- /dev/null
+++ b/spec/mspec/lib/mspec/runner/formatters/stats.rb
@@ -0,0 +1,57 @@
+require 'mspec/runner/formatters/base'
+
+class StatsPerFileFormatter < BaseFormatter
+ def initialize(out = nil)
+ super(out)
+ @data = {}
+ @root = File.expand_path(MSpecScript.get(:prefix) || '.')
+ end
+
+ def register
+ super
+ MSpec.register :load, self
+ MSpec.register :unload, self
+ end
+
+ # Resets the tallies so the counts are only for this file.
+ def load
+ tally.counter.examples = 0
+ tally.counter.errors = 0
+ tally.counter.failures = 0
+ tally.counter.tagged = 0
+ end
+
+ def unload
+ file = format_file MSpec.file
+
+ raise if @data.key?(file)
+ @data[file] = {
+ examples: tally.counter.examples,
+ errors: tally.counter.errors,
+ failures: tally.counter.failures,
+ tagged: tally.counter.tagged,
+ }
+ end
+
+ def finish
+ width = @data.keys.max_by(&:size).size
+ f = "%3d"
+ @data.each_pair do |file, data|
+ total = data[:examples]
+ passing = total - data[:errors] - data[:failures] - data[:tagged]
+ puts "#{file.ljust(width)} #{f % passing}/#{f % total}"
+ end
+
+ require 'yaml'
+ yaml = YAML.dump(@data)
+ File.write "results-#{RUBY_ENGINE}-#{RUBY_ENGINE_VERSION}.yml", yaml
+ end
+
+ private def format_file(file)
+ if file.start_with?(@root)
+ file[@root.size+1..-1]
+ else
+ raise file
+ end
+ end
+end
diff --git a/spec/mspec/lib/mspec/runner/mspec.rb b/spec/mspec/lib/mspec/runner/mspec.rb
index 5528f27cf8..8331086196 100644
--- a/spec/mspec/lib/mspec/runner/mspec.rb
+++ b/spec/mspec/lib/mspec/runner/mspec.rb
@@ -10,7 +10,6 @@ class MSpecEnv
end
module MSpec
-
@exit = nil
@abort = nil
@start = nil
@@ -20,8 +19,8 @@ module MSpec
@after = nil
@leave = nil
@finish = nil
- @exclude = nil
- @include = nil
+ @exclude = []
+ @include = []
@leave = nil
@load = nil
@unload = nil
@@ -33,13 +32,19 @@ module MSpec
@guarded = []
@features = {}
@exception = nil
- @randomize = nil
- @repeat = nil
+ @randomize = false
+ @repeat = 1
@expectation = nil
@expectations = false
- def self.describe(mod, options = nil, &block)
- state = ContextState.new mod, options
+ class << self
+ attr_reader :file, :include, :exclude
+ attr_writer :repeat, :randomize
+ attr_accessor :formatter
+ end
+
+ def self.describe(description, options = nil, &block)
+ state = ContextState.new description, options
state.parent = current
MSpec.register_current state
@@ -57,6 +62,10 @@ module MSpec
actions :finish
end
+ def self.files_array
+ @files
+ end
+
def self.each_file(&block)
if ENV["MSPEC_MULTI"]
while file = STDIN.gets
@@ -74,7 +83,7 @@ module MSpec
# The parent closed the connection without QUIT
abort "the parent did not send QUIT"
else
- return unless files = retrieve(:files)
+ return unless files = @files
shuffle files if randomize?
files.each(&block)
end
@@ -83,10 +92,11 @@ module MSpec
def self.files
each_file do |file|
setup_env
- store :file, file
+ @file = file
actions :load
protect("loading #{file}") { Kernel.load file }
actions :unload
+ raise "#{file} was executed but did not reset the current example: #{@current}" if @current
end
end
@@ -101,7 +111,7 @@ module MSpec
def self.protect(location, &block)
begin
- @env.instance_eval(&block)
+ @env.instance_exec(&block)
return true
rescue SystemExit => e
raise e
@@ -130,22 +140,24 @@ module MSpec
# Sets the toplevel ContextState to +state+.
def self.register_current(state)
- store :current, state
+ @current = state
end
# Sets the toplevel ContextState to +nil+.
def self.clear_current
- store :current, nil
+ @current = nil
end
# Returns the toplevel ContextState.
def self.current
- retrieve :current
+ @current
end
# Stores the shared ContextState keyed by description.
def self.register_shared(state)
- @shared[state.to_s] = state
+ name = state.to_s
+ raise "duplicated shared #describe: #{name}" if @shared.key?(name)
+ @shared[name] = state
end
# Returns the shared ContextState matching description.
@@ -155,17 +167,17 @@ module MSpec
# Stores the exit code used by the runner scripts.
def self.register_exit(code)
- store :exit, code
+ @exit = code
end
# Retrieves the stored exit code.
def self.exit_code
- retrieve(:exit).to_i
+ @exit.to_i
end
# Stores the list of files to be evaluated.
def self.register_files(files)
- store :files, files
+ @files = files
end
# Stores one or more substitution patterns for transforming
@@ -176,7 +188,7 @@ module MSpec
#
# See also +tags_file+.
def self.register_tags_patterns(patterns)
- store :tags_patterns, patterns
+ @tags_patterns = patterns
end
# Registers an operating mode. Modes recognized by MSpec:
@@ -187,30 +199,30 @@ module MSpec
# :report - specs that are guarded are reported
# :unguarded - all guards are forced off
def self.register_mode(mode)
- modes = retrieve :modes
+ modes = @modes
modes << mode unless modes.include? mode
end
# Clears all registered modes.
def self.clear_modes
- store :modes, []
+ @modes = []
end
# Returns +true+ if +mode+ is registered.
def self.mode?(mode)
- retrieve(:modes).include? mode
+ @modes.include? mode
end
def self.enable_feature(feature)
- retrieve(:features)[feature] = true
+ @features[feature] = true
end
def self.disable_feature(feature)
- retrieve(:features)[feature] = false
+ @features[feature] = false
end
def self.feature_enabled?(feature)
- retrieve(:features)[feature] || false
+ @features[feature] || false
end
def self.retrieve(symbol)
@@ -259,21 +271,17 @@ module MSpec
end
end
- def self.randomize(flag = true)
- @randomize = flag
- end
-
def self.randomize?
- @randomize == true
- end
-
- def self.repeat=(times)
- @repeat = times
+ @randomize
end
def self.repeat
- (@repeat || 1).times do
+ if @repeat == 1
yield
+ else
+ @repeat.times do
+ yield
+ end
end
end
@@ -289,17 +297,17 @@ module MSpec
# Records that an expectation has been encountered in an example.
def self.expectation
- store :expectations, true
+ @expectations = true
end
# Returns true if an expectation has been encountered
def self.expectation?
- retrieve :expectations
+ @expectations
end
# Resets the flag that an expectation has been encountered in an example.
def self.clear_expectations
- store :expectations, false
+ @expectations = false
end
# Transforms a spec filename into a tags filename by applying each
@@ -313,9 +321,9 @@ module MSpec
#
# See also +register_tags_patterns+.
def self.tags_file
- patterns = retrieve(:tags_patterns) ||
+ patterns = @tags_patterns ||
[[%r(spec/), 'spec/tags/'], [/_spec.rb$/, '_tags.txt']]
- patterns.inject(retrieve(:file).dup) do |file, pattern|
+ patterns.inject(@file.dup) do |file, pattern|
file.gsub(*pattern)
end
end
diff --git a/spec/mspec/lib/mspec/runner/object.rb b/spec/mspec/lib/mspec/runner/object.rb
index d5d9650795..58d98cc4df 100644
--- a/spec/mspec/lib/mspec/runner/object.rb
+++ b/spec/mspec/lib/mspec/runner/object.rb
@@ -7,8 +7,8 @@ class Object
MSpec.current.after at, &block
end
- private def describe(mod, msg = nil, options = nil, &block)
- MSpec.describe mod, msg, &block
+ private def describe(description, options = nil, &block)
+ MSpec.describe description, options, &block
end
private def it(desc, &block)
diff --git a/spec/mspec/lib/mspec/runner/parallel.rb b/spec/mspec/lib/mspec/runner/parallel.rb
index 7428b33682..6a9ecd155d 100644
--- a/spec/mspec/lib/mspec/runner/parallel.rb
+++ b/spec/mspec/lib/mspec/runner/parallel.rb
@@ -15,7 +15,7 @@ class ParallelRunner
@output_files << name
env = {
- "SPEC_TEMP_DIR" => "rubyspec_temp_#{i}",
+ "SPEC_TEMP_DIR" => "#{SPEC_TEMP_DIR}_#{i}",
"MSPEC_MULTI" => i.to_s
}
command = @argv + ["-fy", "-o", name]
diff --git a/spec/mspec/lib/mspec/utils/format.rb b/spec/mspec/lib/mspec/utils/format.rb
index bb75e131de..425dd4d11c 100644
--- a/spec/mspec/lib/mspec/utils/format.rb
+++ b/spec/mspec/lib/mspec/utils/format.rb
@@ -13,7 +13,11 @@ end
module MSpec
def self.format(obj)
- obj.pretty_inspect.chomp
+ if String === obj and obj.include?("\n")
+ "\n#{obj.inspect.gsub('\n', "\n")}"
+ else
+ obj.pretty_inspect.chomp
+ end
rescue => e
"#<#{obj.class}>(#pretty_inspect raised #{e.inspect})"
end
diff --git a/spec/mspec/lib/mspec/utils/options.rb b/spec/mspec/lib/mspec/utils/options.rb
index 3e3f708a2f..bef1dbdd2e 100644
--- a/spec/mspec/lib/mspec/utils/options.rb
+++ b/spec/mspec/lib/mspec/utils/options.rb
@@ -274,6 +274,8 @@ class MSpecOptions
config[:formatter] = SpinnerFormatter
when 't', 'method'
config[:formatter] = MethodFormatter
+ when 'e', 'stats'
+ config[:formatter] = StatsPerFileFormatter
when 'y', 'yaml'
config[:formatter] = YamlFormatter
when 'p', 'profile'
@@ -281,7 +283,7 @@ class MSpecOptions
when 'j', 'junit'
config[:formatter] = JUnitFormatter
else
- abort "Unknown format: #{o}\n#{@parser}" unless File.exist?(o)
+ abort "Unknown format: #{o}" unless File.exist?(o)
require File.expand_path(o)
if Object.const_defined?(:CUSTOM_MSPEC_FORMATTER)
config[:formatter] = CUSTOM_MSPEC_FORMATTER
@@ -300,6 +302,7 @@ class MSpecOptions
doc " m, summary SummaryFormatter"
doc " a, *, spin SpinnerFormatter"
doc " t, method MethodFormatter"
+ doc " e, stats StatsPerFileFormatter"
doc " y, yaml YamlFormatter"
doc " p, profile ProfileFormatter"
doc " j, junit JUnitFormatter\n"
@@ -377,7 +380,7 @@ class MSpecOptions
def randomize
on("-H", "--random",
"Randomize the list of spec files") do
- MSpec.randomize
+ MSpec.randomize = true
end
end
@@ -392,11 +395,11 @@ class MSpecOptions
on("-V", "--verbose", "Output the name of each file processed") do
obj = Object.new
def obj.start
- @width = MSpec.retrieve(:files).inject(0) { |max, f| f.size > max ? f.size : max }
+ @width = MSpec.files_array.inject(0) { |max, f| f.size > max ? f.size : max }
end
def obj.load
- file = MSpec.retrieve :file
- STDERR.print "\n#{file.ljust(@width)}"
+ file = MSpec.file
+ STDERR.print "\n#{file.ljust(@width)}\n"
end
MSpec.register :start, obj
MSpec.register :load, obj
@@ -467,8 +470,6 @@ class MSpecOptions
end
def all
- # Generated with:
- # puts File.read(__FILE__).scan(/def (\w+).*\n\s*on\(/)
configure {}
targets
formatters
@@ -481,6 +482,7 @@ class MSpecOptions
repeat
verbose
interrupt
+ timeout
verify
action_filters
actions
diff --git a/spec/mspec/lib/mspec/utils/script.rb b/spec/mspec/lib/mspec/utils/script.rb
index 2545a16bae..e3478ef7b0 100644
--- a/spec/mspec/lib/mspec/utils/script.rb
+++ b/spec/mspec/lib/mspec/utils/script.rb
@@ -3,7 +3,6 @@ require 'mspec/guards/version'
require 'mspec/utils/warnings'
# MSpecScript provides a skeleton for all the MSpec runner scripts.
-
class MSpecScript
# Returns the config object. Maintained at the class
# level to easily enable simple config files. See the
@@ -39,8 +38,8 @@ class MSpecScript
end
def initialize
- ruby_version_is ""..."2.4" do
- abort "MSpec needs Ruby 2.4 or more recent"
+ ruby_version_is ""..."2.5" do
+ abort "MSpec needs Ruby 2.5 or more recent"
end
config[:formatter] = nil
@@ -127,7 +126,7 @@ class MSpecScript
if formatter = config_formatter
formatter.register
- MSpec.store :formatter, formatter
+ MSpec.formatter = formatter
end
MatchFilter.new(:include, *config[:includes]).register unless config[:includes].empty?
diff --git a/spec/mspec/lib/mspec/utils/version.rb b/spec/mspec/lib/mspec/utils/version.rb
index 787a76b053..9c1c58b8df 100644
--- a/spec/mspec/lib/mspec/utils/version.rb
+++ b/spec/mspec/lib/mspec/utils/version.rb
@@ -42,7 +42,7 @@ class SpecVersion
def <=>(other)
if other.respond_to? :to_int
- other = Integer other
+ other = Integer(other.to_int)
else
other = SpecVersion.new(String(other)).to_i
end
diff --git a/spec/mspec/lib/mspec/utils/warnings.rb b/spec/mspec/lib/mspec/utils/warnings.rb
index 7c2bc6fe88..288dbe71aa 100644
--- a/spec/mspec/lib/mspec/utils/warnings.rb
+++ b/spec/mspec/lib/mspec/utils/warnings.rb
@@ -1,21 +1,17 @@
require 'mspec/guards/version'
-if RUBY_ENGINE == "ruby" and ruby_version_is("2.4")
- ruby_version_is "2.4"..."2.5" do
- # Kernel#warn does not delegate to Warning.warn in 2.4
- module Kernel
- remove_method :warn
- def warn(*messages)
- return if $VERBOSE == nil or messages.empty?
- msg = messages.join("\n")
- msg += "\n" unless msg.end_with?("\n")
- Warning.warn(msg)
- end
- private :warn
- end
- end
+# Always enable deprecation warnings when running MSpec, as ruby/spec tests for them,
+# and like in most test frameworks, all warnings should be enabled by default (same as -w).
+if Object.const_defined?(:Warning) and Warning.respond_to?(:[]=)
+ Warning[:deprecated] = true
+end
+if Object.const_defined?(:Warning) and Warning.respond_to?(:warn)
def Warning.warn(message)
+ # Suppress any warning inside the method to prevent recursion
+ verbose = $VERBOSE
+ $VERBOSE = nil
+
if Thread.current[:in_mspec_complain_matcher]
return $stderr.write(message)
end
@@ -49,12 +45,14 @@ if RUBY_ENGINE == "ruby" and ruby_version_is("2.4")
when /\/(argf|io|stringio)\/.+(ARGF|IO)#(lines|chars|bytes|codepoints) is deprecated/
when /Thread\.exclusive is deprecated.+\n.+thread\/exclusive_spec\.rb/
when /hash\/shared\/index\.rb:\d+: warning: Hash#index is deprecated; use Hash#key/
- when /env\/shared\/key\.rb:\d+: warning: ENV\.index is deprecated; use ENV\.key/
when /exponent(_spec)?\.rb:\d+: warning: in a\*\*b, b may be too big/
when /enumerator\/(new_spec|initialize_spec)\.rb:\d+: warning: Enumerator\.new without a block is deprecated/
+ when /Pattern matching is experimental, and the behavior may change in future versions of Ruby!/
else
$stderr.write message
end
+ ensure
+ $VERBOSE = verbose
end
else
$VERBOSE = nil unless ENV['OUTPUT_WARNINGS']
diff --git a/spec/mspec/spec/fixtures/config.mspec b/spec/mspec/spec/fixtures/config.mspec
index 4a069e2eb0..01654c5094 100644
--- a/spec/mspec/spec/fixtures/config.mspec
+++ b/spec/mspec/spec/fixtures/config.mspec
@@ -1,8 +1,6 @@
class MSpecScript
set :target, 'ruby'
- set :backtrace_filter, /lib\/mspec\//
-
set :tags_patterns, [
[%r(spec/fixtures/), 'spec/fixtures/tags/'],
[/_spec.rb$/, '_tags.txt']
diff --git a/spec/mspec/spec/fixtures/my_ruby b/spec/mspec/spec/fixtures/my_ruby
index 4d552f27fb..eeda3eeeec 100755
--- a/spec/mspec/spec/fixtures/my_ruby
+++ b/spec/mspec/spec/fixtures/my_ruby
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
echo $RUBY_EXE
-ruby "$@"
+exec ruby "$@"
diff --git a/spec/mspec/spec/guards/guard_spec.rb b/spec/mspec/spec/guards/guard_spec.rb
index 5c3dae4b3f..2c3317afe6 100644
--- a/spec/mspec/spec/guards/guard_spec.rb
+++ b/spec/mspec/spec/guards/guard_spec.rb
@@ -254,7 +254,7 @@ describe Object, "#guard" do
end
it "allows to combine guards" do
- guard1 = VersionGuard.new 'x.x.x'
+ guard1 = VersionGuard.new '1.2.3', 'x.x.x'
VersionGuard.stub(:new).and_return(guard1)
guard2 = PlatformGuard.new :dummy
PlatformGuard.stub(:new).and_return(guard2)
@@ -360,7 +360,7 @@ describe Object, "#guard_not" do
end
it "allows to combine guards" do
- guard1 = VersionGuard.new 'x.x.x'
+ guard1 = VersionGuard.new '1.2.3', 'x.x.x'
VersionGuard.stub(:new).and_return(guard1)
guard2 = PlatformGuard.new :dummy
PlatformGuard.stub(:new).and_return(guard2)
diff --git a/spec/mspec/spec/guards/version_spec.rb b/spec/mspec/spec/guards/version_spec.rb
index 07eb451ec9..b0025efcfb 100644
--- a/spec/mspec/spec/guards/version_spec.rb
+++ b/spec/mspec/spec/guards/version_spec.rb
@@ -14,44 +14,44 @@ require 'mspec/guards'
describe VersionGuard, "#match?" do
before :each do
hide_deprecation_warnings
- stub_const "VersionGuard::FULL_RUBY_VERSION", SpecVersion.new('1.8.6')
+ @current = '1.8.6'
end
it "returns true when the argument is equal to RUBY_VERSION" do
- VersionGuard.new('1.8.6').match?.should == true
+ VersionGuard.new(@current, '1.8.6').match?.should == true
end
it "returns true when the argument is less than RUBY_VERSION" do
- VersionGuard.new('1.8').match?.should == true
- VersionGuard.new('1.8.5').match?.should == true
+ VersionGuard.new(@current, '1.8').match?.should == true
+ VersionGuard.new(@current, '1.8.5').match?.should == true
end
it "returns false when the argument is greater than RUBY_VERSION" do
- VersionGuard.new('1.8.7').match?.should == false
- VersionGuard.new('1.9.2').match?.should == false
+ VersionGuard.new(@current, '1.8.7').match?.should == false
+ VersionGuard.new(@current, '1.9.2').match?.should == false
end
it "returns true when the argument range includes RUBY_VERSION" do
- VersionGuard.new('1.8.5'..'1.8.7').match?.should == true
- VersionGuard.new('1.8'..'1.9').match?.should == true
- VersionGuard.new('1.8'...'1.9').match?.should == true
- VersionGuard.new('1.8'..'1.8.6').match?.should == true
- VersionGuard.new('1.8.5'..'1.8.6').match?.should == true
- VersionGuard.new(''...'1.8.7').match?.should == true
+ VersionGuard.new(@current, '1.8.5'..'1.8.7').match?.should == true
+ VersionGuard.new(@current, '1.8'..'1.9').match?.should == true
+ VersionGuard.new(@current, '1.8'...'1.9').match?.should == true
+ VersionGuard.new(@current, '1.8'..'1.8.6').match?.should == true
+ VersionGuard.new(@current, '1.8.5'..'1.8.6').match?.should == true
+ VersionGuard.new(@current, ''...'1.8.7').match?.should == true
end
it "returns false when the argument range does not include RUBY_VERSION" do
- VersionGuard.new('1.8.7'..'1.8.9').match?.should == false
- VersionGuard.new('1.8.4'..'1.8.5').match?.should == false
- VersionGuard.new('1.8.4'...'1.8.6').match?.should == false
- VersionGuard.new('1.8.5'...'1.8.6').match?.should == false
- VersionGuard.new(''...'1.8.6').match?.should == false
+ VersionGuard.new(@current, '1.8.7'..'1.8.9').match?.should == false
+ VersionGuard.new(@current, '1.8.4'..'1.8.5').match?.should == false
+ VersionGuard.new(@current, '1.8.4'...'1.8.6').match?.should == false
+ VersionGuard.new(@current, '1.8.5'...'1.8.6').match?.should == false
+ VersionGuard.new(@current, ''...'1.8.6').match?.should == false
end
end
describe Object, "#ruby_version_is" do
before :each do
- @guard = VersionGuard.new 'x.x.x'
+ @guard = VersionGuard.new '1.2.3', 'x.x.x'
VersionGuard.stub(:new).and_return(@guard)
ScratchPad.clear
end
@@ -88,3 +88,25 @@ describe Object, "#ruby_version_is" do
end.should raise_error(Exception)
end
end
+
+describe Object, "#version_is" do
+ before :each do
+ hide_deprecation_warnings
+ end
+
+ it "returns the expected values" do
+ version_is('1.2.3', '1.2.2').should == true
+ version_is('1.2.3', '1.2.3').should == true
+ version_is('1.2.3', '1.2.4').should == false
+
+ version_is('1.2.3', '1').should == true
+ version_is('1.2.3', '1.0').should == true
+ version_is('1.2.3', '2').should == false
+ version_is('1.2.3', '2.0').should == false
+
+ version_is('1.2.3', '1.2.2'..'1.2.4').should == true
+ version_is('1.2.3', '1.2.2'..'1.2.3').should == true
+ version_is('1.2.3', '1.2.2'...'1.2.3').should == false
+ version_is('1.2.3', '1.2.3'..'1.2.4').should == true
+ end
+end
diff --git a/spec/mspec/spec/helpers/io_spec.rb b/spec/mspec/spec/helpers/io_spec.rb
index 19f8384912..4fa1f97d46 100644
--- a/spec/mspec/spec/helpers/io_spec.rb
+++ b/spec/mspec/spec/helpers/io_spec.rb
@@ -60,7 +60,7 @@ describe Object, "#new_fd" do
rm_r @name
end
- it "returns a Integer that can be used to create an IO instance" do
+ it "returns an Integer that can be used to create an IO instance" do
fd = new_fd @name
fd.should be_kind_of(Integer)
diff --git a/spec/mspec/spec/helpers/tmp_spec.rb b/spec/mspec/spec/helpers/tmp_spec.rb
index afadc7f51c..4dcf629d94 100644
--- a/spec/mspec/spec/helpers/tmp_spec.rb
+++ b/spec/mspec/spec/helpers/tmp_spec.rb
@@ -4,7 +4,7 @@ require 'mspec/helpers'
describe Object, "#tmp" do
before :all do
- @dir = "#{File.expand_path(Dir.pwd)}/rubyspec_temp"
+ @dir = SPEC_TEMP_DIR
end
it "returns a name relative to the current working directory" do
diff --git a/spec/mspec/spec/integration/run_spec.rb b/spec/mspec/spec/integration/run_spec.rb
index df10f77094..99a5416cb0 100644
--- a/spec/mspec/spec/integration/run_spec.rb
+++ b/spec/mspec/spec/integration/run_spec.rb
@@ -9,14 +9,12 @@ Expected 1 == 2
to be truthy but was false
CWD/spec/fixtures/a_spec.rb:8:in `block (2 levels) in <top (required)>'
CWD/spec/fixtures/a_spec.rb:2:in `<top (required)>'
-CWD/bin/mspec-run:7:in `<main>'
2)
Foo#bar fails ERROR
RuntimeError: failure
CWD/spec/fixtures/a_spec.rb:12:in `block (2 levels) in <top (required)>'
CWD/spec/fixtures/a_spec.rb:2:in `<top (required)>'
-CWD/bin/mspec-run:7:in `<main>'
Finished in D.DDDDDD seconds
EOS
diff --git a/spec/mspec/spec/integration/tag_spec.rb b/spec/mspec/spec/integration/tag_spec.rb
index 1882d71e32..f4df2f0dc4 100644
--- a/spec/mspec/spec/integration/tag_spec.rb
+++ b/spec/mspec/spec/integration/tag_spec.rb
@@ -28,7 +28,6 @@ Expected 1 == 2
to be truthy but was false
CWD/spec/fixtures/tagging_spec.rb:9:in `block (2 levels) in <top (required)>'
CWD/spec/fixtures/tagging_spec.rb:3:in `<top (required)>'
-CWD/bin/mspec-tag:7:in `<main>'
2)
Tag#me érròrs in unicode FAILED
@@ -36,7 +35,6 @@ Expected 1 == 2
to be truthy but was false
CWD/spec/fixtures/tagging_spec.rb:13:in `block (2 levels) in <top (required)>'
CWD/spec/fixtures/tagging_spec.rb:3:in `<top (required)>'
-CWD/bin/mspec-tag:7:in `<main>'
Finished in D.DDDDDD seconds
diff --git a/spec/mspec/spec/matchers/raise_error_spec.rb b/spec/mspec/spec/matchers/raise_error_spec.rb
index 1ed794e0a9..a40acc0ea0 100644
--- a/spec/mspec/spec/matchers/raise_error_spec.rb
+++ b/spec/mspec/spec/matchers/raise_error_spec.rb
@@ -12,7 +12,7 @@ describe RaiseErrorMatcher do
matcher.matches?(proc).should == true
end
- it "executes it's optional block if matched" do
+ it "executes its optional block if matched" do
run = false
proc = Proc.new { raise ExpectedException }
matcher = RaiseErrorMatcher.new(ExpectedException, nil) { |error|
@@ -62,16 +62,21 @@ describe RaiseErrorMatcher do
matcher.matches?(proc).should == false
end
- it "provides a useful failure message" do
- exc = UnexpectedException.new("unexpected")
- matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
+ it "provides a useful failure message when the exception class differs" do
+ exc = UnexpectedException.new("message")
+ matcher = RaiseErrorMatcher.new(ExpectedException, "message")
matcher.matching_exception?(exc).should == false
- lambda {
+ begin
matcher.matches?(Proc.new { raise exc })
- }.should raise_error(UnexpectedException)
- matcher.failure_message.should ==
- ["Expected ExpectedException (expected)", "but got UnexpectedException (unexpected)"]
+ rescue UnexpectedException => e
+ matcher.failure_message.should ==
+ ["Expected ExpectedException (message)", "but got: UnexpectedException (message)"]
+ ExceptionState.new(nil, nil, e).message.should ==
+ "Expected ExpectedException (message)\nbut got: UnexpectedException (message)"
+ else
+ raise "no exception"
+ end
end
it "provides a useful failure message when the proc raises the expected exception with an unexpected message" do
@@ -79,11 +84,33 @@ describe RaiseErrorMatcher do
matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
matcher.matching_exception?(exc).should == false
- lambda {
+ begin
matcher.matches?(Proc.new { raise exc })
- }.should raise_error(ExpectedException)
- matcher.failure_message.should ==
- ["Expected ExpectedException (expected)", "but got ExpectedException (unexpected)"]
+ rescue ExpectedException => e
+ matcher.failure_message.should ==
+ ["Expected ExpectedException (expected)", "but got: ExpectedException (unexpected)"]
+ ExceptionState.new(nil, nil, e).message.should ==
+ "Expected ExpectedException (expected)\nbut got: ExpectedException (unexpected)"
+ else
+ raise "no exception"
+ end
+ end
+
+ it "provides a useful failure message when both the exception class and message differ" do
+ exc = UnexpectedException.new("unexpected")
+ matcher = RaiseErrorMatcher.new(ExpectedException, "expected")
+
+ matcher.matching_exception?(exc).should == false
+ begin
+ matcher.matches?(Proc.new { raise exc })
+ rescue UnexpectedException => e
+ matcher.failure_message.should ==
+ ["Expected ExpectedException (expected)", "but got: UnexpectedException (unexpected)"]
+ ExceptionState.new(nil, nil, e).message.should ==
+ "Expected ExpectedException (expected)\nbut got: UnexpectedException (unexpected)"
+ else
+ raise "no exception"
+ end
end
it "provides a useful failure message when no exception is raised" do
@@ -127,6 +154,6 @@ describe RaiseErrorMatcher do
matcher = RaiseErrorMatcher.new(Exception, nil)
matcher.matches?(proc)
matcher.negative_failure_message.should ==
- ["Expected to not get Exception", "but got UnexpectedException (unexpected)"]
+ ["Expected to not get Exception", "but got: UnexpectedException (unexpected)"]
end
end
diff --git a/spec/mspec/spec/runner/context_spec.rb b/spec/mspec/spec/runner/context_spec.rb
index d9c20aa0cf..c5aa691323 100644
--- a/spec/mspec/spec/runner/context_spec.rb
+++ b/spec/mspec/spec/runner/context_spec.rb
@@ -55,22 +55,6 @@ describe ContextState, "#to_s" do
it "returns a description string for self when passed a String" do
ContextState.new("SomeClass").to_s.should == "SomeClass"
end
-
- it "returns a description string for self when passed a Module, String" do
- ContextState.new(Object, "when empty").to_s.should == "Object when empty"
- end
-
- it "returns a description string for self when passed a Module and String beginning with '#'" do
- ContextState.new(Object, "#to_s").to_s.should == "Object#to_s"
- end
-
- it "returns a description string for self when passed a Module and String beginning with '.'" do
- ContextState.new(Object, ".to_s").to_s.should == "Object.to_s"
- end
-
- it "returns a description string for self when passed a Module and String beginning with '::'" do
- ContextState.new(Object, "::to_s").to_s.should == "Object::to_s"
- end
end
describe ContextState, "#description" do
@@ -464,11 +448,14 @@ describe ContextState, "#process" do
end
it "shuffles the spec list if MSpec.randomize? is true" do
- MSpec.randomize
- MSpec.should_receive(:shuffle)
- @state.it("") { }
- @state.process
- MSpec.randomize false
+ MSpec.randomize = true
+ begin
+ MSpec.should_receive(:shuffle)
+ @state.it("") { }
+ @state.process
+ ensure
+ MSpec.randomize = false
+ end
end
it "sets the current MSpec ContextState" do
diff --git a/spec/mspec/spec/runner/example_spec.rb b/spec/mspec/spec/runner/example_spec.rb
index b4391f802d..7d3ad6be30 100644
--- a/spec/mspec/spec/runner/example_spec.rb
+++ b/spec/mspec/spec/runner/example_spec.rb
@@ -14,7 +14,7 @@ end
describe ExampleState, "#describe" do
before :each do
- @context = ContextState.new Object, "#to_s"
+ @context = ContextState.new "Object#to_s"
@state = ExampleState.new @context, "it"
end
@@ -64,16 +64,16 @@ end
describe ExampleState, "#filtered?" do
before :each do
- MSpec.store :include, nil
- MSpec.store :exclude, nil
+ MSpec.store :include, []
+ MSpec.store :exclude, []
@state = ExampleState.new ContextState.new("describe"), "it"
@filter = double("filter")
end
after :each do
- MSpec.store :include, nil
- MSpec.store :exclude, nil
+ MSpec.store :include, []
+ MSpec.store :exclude, []
end
it "returns false if MSpec include filters list is empty" do
diff --git a/spec/mspec/spec/runner/exception_spec.rb b/spec/mspec/spec/runner/exception_spec.rb
index 309442435c..0e0a819992 100644
--- a/spec/mspec/spec/runner/exception_spec.rb
+++ b/spec/mspec/spec/runner/exception_spec.rb
@@ -93,7 +93,7 @@ describe ExceptionState, "#message" do
it "returns <No message> if the exception message is empty" do
exc = ExceptionState.new @state, "", Exception.new("")
- exc.message.should == "<No message>"
+ exc.message.should == "Exception: <No message>"
end
it "returns the message without exception class when the exception is an SpecExpectationNotMetError" do
diff --git a/spec/mspec/spec/runner/mspec_spec.rb b/spec/mspec/spec/runner/mspec_spec.rb
index 91338c6ddb..7dad4458d3 100644
--- a/spec/mspec/spec/runner/mspec_spec.rb
+++ b/spec/mspec/spec/runner/mspec_spec.rb
@@ -1,4 +1,5 @@
require 'spec_helper'
+require 'mspec/expectations/expectations'
require 'mspec/helpers/tmp'
require 'mspec/helpers/fs'
require 'mspec/matchers/base'
@@ -8,7 +9,7 @@ require 'mspec/runner/example'
describe MSpec, ".register_files" do
it "records which spec files to run" do
MSpec.register_files [:one, :two, :three]
- MSpec.retrieve(:files).should == [:one, :two, :three]
+ MSpec.files_array.should == [:one, :two, :three]
end
end
@@ -66,9 +67,9 @@ end
describe MSpec, ".randomize" do
it "sets the flag to randomize spec execution order" do
MSpec.randomize?.should == false
- MSpec.randomize
+ MSpec.randomize = true
MSpec.randomize?.should == true
- MSpec.randomize false
+ MSpec.randomize = false
MSpec.randomize?.should == false
end
end
@@ -342,17 +343,19 @@ describe MSpec, ".files" do
end
it "shuffles the file list if .randomize? is true" do
- MSpec.randomize
+ MSpec.randomize = true
MSpec.should_receive(:shuffle)
MSpec.files
- MSpec.randomize false
+ MSpec.randomize = false
end
it "registers the current file" do
- MSpec.should_receive(:store).with(:file, :one)
- MSpec.should_receive(:store).with(:file, :two)
- MSpec.should_receive(:store).with(:file, :three)
+ load = double("load")
+ files = []
+ load.stub(:load).and_return { files << MSpec.file }
+ MSpec.register :load, load
MSpec.files
+ files.should == [:one, :two, :three]
end
end
diff --git a/spec/mspec/spec/utils/options_spec.rb b/spec/mspec/spec/utils/options_spec.rb
index face909286..f3a7046526 100644
--- a/spec/mspec/spec/utils/options_spec.rb
+++ b/spec/mspec/spec/utils/options_spec.rb
@@ -1044,7 +1044,7 @@ describe "The -H, --random option" do
end
it "registers the MSpec randomize mode" do
- MSpec.should_receive(:randomize).twice
+ MSpec.should_receive(:randomize=).twice
["-H", "--random"].each do |opt|
@options.parse opt
end
@@ -1283,3 +1283,22 @@ describe "The -d, --debug option" do
end
end
end
+
+describe "MSpecOptions#all" do
+ it "includes all options" do
+ meth = MSpecOptions.instance_method(:all)
+ file, line = meth.source_location
+ contents = File.read(file)
+ lines = contents.lines
+
+ from = line
+ to = from
+ to += 1 until /^\s*end\s*$/ =~ lines[to]
+ calls = lines[from...to].map(&:strip)
+
+ option_methods = contents.scan(/def (\w+).*\n\s*on\(/).map(&:first)
+ option_methods[0].sub!("configure", "configure {}")
+
+ calls.should == option_methods
+ end
+end
diff --git a/spec/mspec/spec/utils/script_spec.rb b/spec/mspec/spec/utils/script_spec.rb
index 3cc85fa1e2..c7fa3eb354 100644
--- a/spec/mspec/spec/utils/script_spec.rb
+++ b/spec/mspec/spec/utils/script_spec.rb
@@ -250,8 +250,8 @@ describe MSpecScript, "#register" do
it "registers :formatter with the formatter instance" do
@formatter.stub(:new).and_return(@formatter)
- MSpec.should_receive(:store).with(:formatter, @formatter)
@script.register
+ MSpec.formatter.should be(@formatter)
end
it "does not register :formatter if config[:formatter] is false" do
diff --git a/spec/mspec/tool/remove_old_guards.rb b/spec/mspec/tool/remove_old_guards.rb
index d6ed619d98..718e351e11 100644
--- a/spec/mspec/tool/remove_old_guards.rb
+++ b/spec/mspec/tool/remove_old_guards.rb
@@ -57,9 +57,10 @@ def search(regexp)
end
version = Regexp.escape(ARGV.fetch(0))
-remove_guards(/ruby_version_is ["']#{version}["'] do/, true)
-remove_guards(/ruby_version_is ["'][0-9.]*["']...["']#{version}["'] do/, false)
-remove_guards(/ruby_bug "#\d+", ["'][0-9.]*["']...["']#{version}["'] do/, true)
+version += "(?:\\.0)?" if version.count(".") < 2
+remove_guards(/ruby_version_is (["'])#{version}\1 do/, true)
+remove_guards(/ruby_version_is (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, false)
+remove_guards(/ruby_bug "#\d+", (["'])[0-9.]*\1 *... *(["'])#{version}\2 do/, true)
-search(/["']#{version}["']/)
+search(/(["'])#{version}\1/)
search(/^\s*#.+#{version}/)
diff --git a/spec/mspec/tool/sync/sync-rubyspec.rb b/spec/mspec/tool/sync/sync-rubyspec.rb
index 48047e013f..93e0f538ba 100644
--- a/spec/mspec/tool/sync/sync-rubyspec.rb
+++ b/spec/mspec/tool/sync/sync-rubyspec.rb
@@ -12,14 +12,13 @@ IMPLS = {
},
mri: {
git: "https://github.com/ruby/ruby.git",
- master: "trunk",
},
}
MSPEC = ARGV.delete('--mspec')
CHECK_LAST_MERGE = ENV['CHECK_LAST_MERGE'] != 'false'
-TEST_TRUNK = ENV['TEST_TRUNK'] != 'false'
+TEST_MASTER = ENV['TEST_MASTER'] != 'false'
MSPEC_REPO = File.expand_path("../../..", __FILE__)
raise MSPEC_REPO if !Dir.exist?(MSPEC_REPO) or !Dir.exist?("#{MSPEC_REPO}/.git")
@@ -36,6 +35,9 @@ BRIGHT_RED = "\e[31;1m"
BRIGHT_YELLOW = "\e[33;1m"
RESET = "\e[0m"
+# git filter-branch --subdirectory-filter works fine for our use case
+ENV['FILTER_BRANCH_SQUELCH_WARNING'] = '1'
+
class RubyImplementation
attr_reader :name
@@ -48,10 +50,6 @@ class RubyImplementation
@data[:git]
end
- def default_branch
- @data[:master] || "master"
- end
-
def repo_name
File.basename(git_url, ".git")
end
@@ -99,7 +97,7 @@ def update_repo(impl)
Dir.chdir(impl.repo_name) do
puts Dir.pwd
- sh "git", "checkout", impl.default_branch
+ sh "git", "checkout", "master"
sh "git", "pull"
end
end
@@ -140,7 +138,7 @@ def rebase_commits(impl)
else
last_merge = `git log --grep='^#{impl.last_merge_message}' -n 1 --format='%H %ct'`
end
- last_merge, commit_timestamp = last_merge.chomp.split(' ')
+ last_merge, commit_timestamp = last_merge.split(' ')
raise "Could not find last merge" unless last_merge
puts "Last merge is #{last_merge}"
@@ -159,10 +157,19 @@ def rebase_commits(impl)
end
end
+def new_commits?(impl)
+ Dir.chdir(SOURCE_REPO) do
+ diff = `git diff master #{impl.rebased_branch}`
+ !diff.empty?
+ end
+end
+
def test_new_specs
require "yaml"
Dir.chdir(SOURCE_REPO) do
- versions = YAML.load_file("#{MSPEC_REPO}/.travis.yml").fetch("rvm")
+ workflow = YAML.load_file(".github/workflows/ci.yml")
+ job_name = MSPEC ? "test" : "specs"
+ versions = workflow.dig("jobs", job_name, "strategy", "matrix", "ruby")
versions = versions.grep(/^\d+\./) # Test on MRI
min_version, max_version = versions.minmax
@@ -175,7 +182,7 @@ def test_new_specs
run_test[min_version]
run_test[max_version]
- run_test["trunk"] if TEST_TRUNK
+ run_test["ruby-master"] if TEST_MASTER
end
end
@@ -192,8 +199,8 @@ end
def fast_forward_master(impl)
Dir.chdir(SOURCE_REPO) do
sh "git", "checkout", "master"
- sh "git", "merge", "--ff-only", "#{impl.name}-rebased"
- sh "git", "branch", "--delete", "#{impl.name}-rebased"
+ sh "git", "merge", "--ff-only", impl.rebased_branch
+ sh "git", "branch", "--delete", impl.rebased_branch
end
end
@@ -212,10 +219,15 @@ def main(impls)
update_repo(impl)
filter_commits(impl)
rebase_commits(impl)
- test_new_specs
- verify_commits(impl)
- fast_forward_master(impl)
- check_ci
+ if new_commits?(impl)
+ test_new_specs
+ verify_commits(impl)
+ fast_forward_master(impl)
+ check_ci
+ else
+ STDERR.puts "#{BRIGHT_YELLOW}No new commits#{RESET}"
+ fast_forward_master(impl)
+ end
end
end
diff --git a/spec/mspec/tool/tag_from_output.rb b/spec/mspec/tool/tag_from_output.rb
index 43fc4808bc..fba52ec26c 100755
--- a/spec/mspec/tool/tag_from_output.rb
+++ b/spec/mspec/tool/tag_from_output.rb
@@ -26,10 +26,11 @@ output.slice_before(NUMBER).select { |number, error_line, *rest|
next
end
spec_file = spec_file[SPEC_FILE, 1]
- prefix = spec_file.index('spec/ruby')
+ prefix = spec_file.index('spec/ruby/') || spec_file.index('spec/truffle/')
spec_file = spec_file[prefix..-1]
- tags_file = spec_file.sub('spec/ruby/', "#{tags_dir}/").sub(/_spec\.rb$/, '_tags.txt')
+ tags_file = spec_file.sub('spec/ruby/', "#{tags_dir}/").sub('spec/truffle/', "#{tags_dir}/truffle/")
+ tags_file = tags_file.sub(/_spec\.rb$/, '_tags.txt')
dir = File.dirname(tags_file)
Dir.mkdir(dir) unless Dir.exist?(dir)
@@ -37,6 +38,7 @@ output.slice_before(NUMBER).select { |number, error_line, *rest|
tag_line = "fails:#{description}"
lines = File.exist?(tags_file) ? File.readlines(tags_file, chomp: true) : []
unless lines.include?(tag_line)
+ puts tags_file
File.write(tags_file, (lines + [tag_line]).join("\n") + "\n")
end
}
diff --git a/spec/mspec/tool/wrap_with_guard.rb b/spec/mspec/tool/wrap_with_guard.rb
new file mode 100755
index 0000000000..5b1bf4d7f7
--- /dev/null
+++ b/spec/mspec/tool/wrap_with_guard.rb
@@ -0,0 +1,28 @@
+#!/usr/bin/env ruby
+# Wrap the passed the files with a guard (e.g., `ruby_version_is ""..."3.0"`).
+# Notably if some methods are removed, this is a convenient way to skip such file from a given version.
+# Example usage:
+# $ spec/mspec/tool/wrap_with_guard.rb 'ruby_version_is ""..."3.0"' spec/ruby/library/set/sortedset/**/*_spec.rb
+
+guard, *files = ARGV
+abort "Usage: #{$0} GUARD FILES..." if files.empty?
+
+files.each do |file|
+ contents = File.binread(file)
+ lines = contents.lines.to_a
+
+ lines = lines.map { |line| line.chomp.empty? ? line : " #{line}" }
+
+ version_line = "#{guard} do\n"
+ if lines[0] =~ /^\s*require.+spec_helper/
+ lines[0] = lines[0].sub(/^ /, '')
+ lines.insert 1, "\n", version_line
+ else
+ warn "Could not find 'require spec_helper' line in #{file}"
+ lines.insert 0, version_line
+ end
+
+ lines << "end\n"
+
+ File.binwrite file, lines.join
+end
diff --git a/spec/ruby/.mspec.constants b/spec/ruby/.mspec.constants
index e88e58989f..6b70274c52 100644
--- a/spec/ruby/.mspec.constants
+++ b/spec/ruby/.mspec.constants
@@ -41,6 +41,7 @@ ComparisonTest
ConstantSpecsIncludedModule
ConstantVisibility
Coverage
+CoverageSpecs
CustomArgumentError
DRb
DRbIdConv
@@ -55,6 +56,7 @@ DefSpecsLambdaVisibility
DefineMethodByProcClass
DefineMethodSpecClass
DefineSingletonMethodSpecClass
+Delegator
DescArray
DescObjectTest
Digest
@@ -148,8 +150,10 @@ Readline
ReceiverClass
RegexpSpecsSubclass
RegexpSpecsSubclassTwo
+Reline
RescueInClassExample
Resolv
+Ripper
SHA1Constants
SHA256Constants
SHA384Constants
@@ -161,6 +165,7 @@ SecondClass
SecureRandom
Set
Shellwords
+SimpleDelegator
SingleForwardable
Singleton
Socket
@@ -188,6 +193,7 @@ TimeoutError
UDPSocket
UNIXServer
UNIXSocket
+URI
UnaryMinusTest
UnicodeNormalize
UnloadableDumpableDir
diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml
index 77e4e78e77..a26b525b1c 100644
--- a/spec/ruby/.rubocop.yml
+++ b/spec/ruby/.rubocop.yml
@@ -1,7 +1,7 @@
inherit_from: .rubocop_todo.yml
AllCops:
- TargetRubyVersion: 2.4
+ TargetRubyVersion: 2.5
DisplayCopNames: true
Exclude:
- command_line/fixtures/bad_syntax.rb
@@ -10,11 +10,15 @@ AllCops:
Layout/TrailingWhitespace:
Enabled: true
-Layout/TrailingBlankLines:
+Layout/TrailingEmptyLines:
Enabled: true
Exclude:
- library/coverage/fixtures/some_class.rb
+Layout/SpaceInLambdaLiteral:
+ Enabled: true
+ EnforcedStyle: require_space
+
Lint:
Enabled: true
@@ -34,10 +38,10 @@ Lint/InterpolationCheck:
Lint/LiteralAsCondition:
Enabled: false
-Lint/UnneededRequireStatement:
+Lint/RedundantRequireStatement:
Enabled: false
-Lint/UnneededSplatExpansion:
+Lint/RedundantSplatExpansion:
Enabled: false
Lint/UnifiedInteger:
@@ -88,6 +92,7 @@ Lint/UnreachableCode:
Exclude:
- 'core/enumerator/lazy/fixtures/classes.rb'
- 'core/kernel/catch_spec.rb'
+ - 'core/kernel/raise_spec.rb'
- 'core/kernel/throw_spec.rb'
- 'language/break_spec.rb'
- 'language/fixtures/break.rb'
@@ -108,12 +113,16 @@ Lint/Debugger:
Exclude:
- 'core/binding/fixtures/irb.rb'
+Lint/Loop:
+ Enabled: false
+
Style/Lambda:
Enabled: true
EnforcedStyle: literal
Exclude:
- 'language/lambda_spec.rb'
- 'language/proc_spec.rb'
+ - 'language/numbered_parameters_spec.rb'
- 'core/kernel/lambda_spec.rb'
Style/EmptyLambdaParameter:
diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml
index aac54f62ae..a469213841 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 2018-04-03 22:23:59 +0900 using RuboCop version 0.54.0.
+# on 2019-12-12 22:16:26 +0900 using RuboCop version 0.77.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@@ -20,7 +20,7 @@ Lint/DuplicateMethods:
- 'core/unboundmethod/fixtures/classes.rb'
- 'fixtures/class.rb'
-# Offense count: 5
+# Offense count: 8
Lint/EnsureReturn:
Exclude:
- 'language/fixtures/ensure.rb'
@@ -28,14 +28,16 @@ Lint/EnsureReturn:
- 'language/return_spec.rb'
# Offense count: 10
+Lint/FlipFlop:
+ Exclude:
+ - 'language/if_spec.rb'
+ - 'language/precedence_spec.rb'
+
+# Offense count: 10
Lint/FloatOutOfRange:
Exclude:
- 'core/string/modulo_spec.rb'
-# Offense count: 29
-Lint/HandleExceptions:
- Enabled: false
-
# Offense count: 2
Lint/ImplicitStringConcatenation:
Exclude:
@@ -57,28 +59,30 @@ Lint/InheritException:
- 'core/enumerator/lazy/fixtures/classes.rb'
- 'core/exception/fixtures/common.rb'
- 'core/module/fixtures/autoload_ex1.rb'
+ - 'shared/kernel/raise.rb'
-# Offense count: 5
+# Offense count: 72
# Cop supports --auto-correct.
Lint/LiteralInInterpolation:
Exclude:
- 'core/module/refine_spec.rb'
+ - 'core/regexp/shared/new.rb'
+ - 'core/string/shared/to_sym.rb'
+ - 'language/alias_spec.rb'
- 'language/defined_spec.rb'
- 'language/fixtures/squiggly_heredoc.rb'
-
-# Offense count: 16
-Lint/Loop:
- Exclude:
- - 'language/until_spec.rb'
- - 'language/while_spec.rb'
+ - 'language/string_spec.rb'
+ - 'language/symbol_spec.rb'
+ - 'language/undef_spec.rb'
+ - 'library/net/ftp/connect_spec.rb'
# Offense count: 8
# Cop supports --auto-correct.
-Lint/MultipleCompare:
+Lint/MultipleComparison:
Exclude:
- 'language/precedence_spec.rb'
-# Offense count: 12
+# Offense count: 9
Lint/ParenthesesAsGroupedExpression:
Exclude:
- 'core/string/fixtures/freeze_magic_comment.rb'
@@ -86,13 +90,19 @@ Lint/ParenthesesAsGroupedExpression:
- 'language/fixtures/send.rb'
- 'language/method_spec.rb'
+# Offense count: 2
+# Cop supports --auto-correct.
+Lint/RedundantStringCoercion:
+ Exclude:
+ - 'core/io/print_spec.rb'
+
# Offense count: 1
# Cop supports --auto-correct.
Lint/RedundantWithIndex:
Exclude:
- 'core/enumerator/with_index_spec.rb'
-# Offense count: 26
+# Offense count: 22
Lint/RescueException:
Exclude:
- 'command_line/fixtures/debug_info.rb'
@@ -100,29 +110,27 @@ Lint/RescueException:
- 'core/exception/cause_spec.rb'
- 'core/exception/no_method_error_spec.rb'
- 'core/kernel/fixtures/autoload_frozen.rb'
+ - 'core/kernel/raise_spec.rb'
- 'core/module/autoload_spec.rb'
- 'core/mutex/sleep_spec.rb'
- - 'core/process/euid_spec.rb'
- - 'core/process/setsid_spec.rb'
- - 'core/process/uid_spec.rb'
- 'core/thread/abort_on_exception_spec.rb'
- 'core/thread/shared/exit.rb'
- 'language/rescue_spec.rb'
- 'library/erb/filename_spec.rb'
-# Offense count: 2
+# Offense count: 4
# Configuration parameters: IgnoreImplicitReferences.
Lint/ShadowedArgument:
Exclude:
- 'language/fixtures/super.rb'
-# Offense count: 2
-# Cop supports --auto-correct.
-Lint/StringConversionInInterpolation:
- Exclude:
- - 'core/io/print_spec.rb'
+# Offense count: 39
+# Configuration parameters: AllowComments.
+Lint/SuppressedException:
+ Enabled: false
# Offense count: 9
+# Configuration parameters: AllowKeywordBlockArguments.
Lint/UnderscorePrefixedVariableName:
Exclude:
- 'core/io/pipe_spec.rb'
@@ -137,13 +145,4 @@ Lint/UselessAccessModifier:
- 'core/module/fixtures/classes.rb'
- 'core/module/module_function_spec.rb'
- 'core/module/private_class_method_spec.rb'
- - 'core/module/private_spec.rb'
- - 'core/module/protected_spec.rb'
- - 'core/module/public_spec.rb'
- 'language/fixtures/send.rb'
-
-# Offense count: 6186
-# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
-# URISchemes: http, https
-Metrics/LineLength:
- Max: 588
diff --git a/spec/ruby/CONTRIBUTING.md b/spec/ruby/CONTRIBUTING.md
index 1ec6f0ff4b..56e12736fc 100644
--- a/spec/ruby/CONTRIBUTING.md
+++ b/spec/ruby/CONTRIBUTING.md
@@ -8,7 +8,7 @@ Spec are grouped in 5 separate top-level groups:
* `command_line`: for the ruby executable command-line flags (`-v`, `-e`, etc)
* `language`: for the language keywords and syntax constructs (`if`, `def`, `A::B`, etc)
-* `core`: for the core methods (`Fixnum#+`, `String#upcase`, no need to require anything)
+* `core`: for the core methods (`Integer#+`, `String#upcase`, no need to require anything)
* `library`: for the standard libraries methods (`CSV.new`, `YAML.parse`, need to require the stdlib)
* `optional/capi`: for functions available to the Ruby C-extension API
@@ -53,12 +53,14 @@ which indicates the file was generated but the method unspecified.
Here is a list of frequently-used matchers, which should be enough for most specs.
There are a few extra specific matchers used in the couple specs that need it.
+#### Comparison matchers
+
```ruby
(1 + 2).should == 3 # Calls #==
(1 + 2).should_not == 5
-File.should equal(File) # Calls #equal? (tests identity)
-(1 + 2).should eql(3) # Calls #eql? (Hash equality)
+File.should.equal?(File) # Calls #equal? (tests identity)
+(1 + 2).should.eql?(3) # Calls #eql? (Hash equality)
1.should < 2
2.should <= 2
@@ -66,12 +68,19 @@ File.should equal(File) # Calls #equal? (tests identity)
4.should > 3
"Hello".should =~ /l{2}/ # Calls #=~ (Regexp match)
+```
+
+#### Predicate matchers
+
+```ruby
+[].should.empty?
+[1,2,3].should.include?(2)
-[].should be_empty # Calls #empty?
-[1,2,3].should include(2) # Calls #include?
+"hello".should.start_with?("h")
+"hello".should.end_with?("o")
(0.1 + 0.2).should be_close(0.3, TOLERANCE) # (0.2-0.1).abs < TOLERANCE
-(0.0/0.0).should be_nan # Calls Float#nan?
+(0.0/0.0).should.nan?
(1.0/0.0).should be_positive_infinity
(-1.0/0.0).should be_negative_infinity
@@ -79,11 +88,16 @@ File.should equal(File) # Calls #equal? (tests identity)
3.14.should be_kind_of(Numeric) # Calls #is_a?
Numeric.should be_ancestor_of(Float) # Float.ancestors.include?(Numeric)
-3.14.should respond_to(:to_i) # Calls #respond_to?
-Fixnum.should have_instance_method(:+)
+3.14.should.respond_to?(:to_i)
+Integer.should have_instance_method(:+)
Array.should have_method(:new)
-# Also have_constant, have_private_instance_method, have_singleton_method, etc
+```
+
+Also `have_constant`, `have_private_instance_method`, `have_singleton_method`, etc.
+
+#### Exception matchers
+```ruby
-> {
raise "oops"
}.should raise_error(RuntimeError, /oops/)
@@ -92,17 +106,26 @@ Array.should have_method(:new)
raise "oops"
}.should raise_error(RuntimeError) { |e|
# Custom checks on the Exception object
- e.message.should include("oops")
+ e.message.should.include?("oops")
e.cause.should == nil
}
+```
+
+##### should_not raise_error
+
+**To avoid!** Instead, use an expectation testing what the code in the lambda does.
+If an exception is raised, it will fail the example anyway.
-# To avoid! Instead, use an expectation testing what the code in the lambda does.
-# If an exception is raised, it will fail the example anyway.
+```ruby
-> { ... }.should_not raise_error
+```
+
+#### Warning matcher
+```ruby
-> {
- Fixnum
-}.should complain(/constant ::Fixnum is deprecated/) # Expect a warning
+ Integer
+}.should complain(/constant ::Integer is deprecated/) # Expect a warning
```
### Guards
@@ -110,15 +133,21 @@ Array.should have_method(:new)
Different guards are available as defined by mspec.
Here is a list of the most commonly-used guards:
+#### Version guards
+
```ruby
-ruby_version_is ""..."2.4" do
- # Specs for RUBY_VERSION < 2.4
+ruby_version_is ""..."2.6" do
+ # Specs for RUBY_VERSION < 2.6
end
-ruby_version_is "2.4" do
- # Specs for RUBY_VERSION >= 2.4
+ruby_version_is "2.6" do
+ # Specs for RUBY_VERSION >= 2.6
end
+```
+
+#### Platform guards
+```ruby
platform_is :windows do
# Specs only valid on Windows
end
@@ -140,27 +169,37 @@ end
big_endian do
# Big-endian platform
end
+```
+
+#### Guard for bug
+
+In case there is a bug in MRI but the expected behavior is obvious.
+First, file a bug at https://bugs.ruby-lang.org/.
+It is better to use a `ruby_version_is` guard if there was a release with the fix.
-# In case there is a bug in MRI but the expected behavior is obvious
-# First file a bug at https://bugs.ruby-lang.org/
-# It is better to use a ruby_version_is guard if there was a release with the fix
+```ruby
ruby_bug '#13669', ''...'2.5' do
it "works like this" do
# Specify the expected behavior here, not the bug
end
end
+```
+#### Combining guards
-# Combining guards
-guard -> { platform_is :windows and ruby_version_is ""..."2.5" } do
- # Windows and RUBY_VERSION < 2.5
+```ruby
+guard -> { platform_is :windows and ruby_version_is ""..."2.6" } do
+ # Windows and RUBY_VERSION < 2.6
end
-guard_not -> { platform_is :windows and ruby_version_is ""..."2.5" } do
+guard_not -> { platform_is :windows and ruby_version_is ""..."2.6" } do
# The opposite
end
+```
-# Custom guard
+#### Custom guard
+
+```ruby
max_uint = (1 << 32) - 1
guard -> { max_uint <= fixnum_max } do
end
@@ -168,6 +207,8 @@ end
Custom guards are better than a simple `if` as they allow [mspec commands](https://github.com/ruby/mspec/issues/30#issuecomment-312487779) to work properly.
+#### Implementation-specific behaviors
+
In general, the usage of guards should be minimized as possible.
There are no guards to define implementation-specific behavior because
diff --git a/spec/ruby/README.md b/spec/ruby/README.md
index c1316a9246..932cd83061 100644
--- a/spec/ruby/README.md
+++ b/spec/ruby/README.md
@@ -1,11 +1,12 @@
# The Ruby Spec Suite
-[![Actions Build Status](https://github.com/ruby/spec/workflows/CI/badge.svg?branch=master)](https://github.com/ruby/spec/actions)
-[![Windows Actions Build Status](https://github.com/ruby/spec/workflows/Windows/badge.svg?branch=master)](https://github.com/ruby/spec/actions)
+[![Actions Build Status](https://github.com/ruby/spec/workflows/CI/badge.svg)](https://github.com/ruby/spec/actions)
[![Gitter](https://badges.gitter.im/ruby/spec.svg)](https://gitter.im/ruby/spec)
The Ruby Spec Suite, abbreviated `ruby/spec`, is a test suite for the behavior of the Ruby programming language.
+### Description and Motivation
+
It is not a standardized specification like the ISO one, and does not aim to become one.
Instead, it is a practical tool to describe and test the behavior of Ruby with code.
@@ -28,16 +29,18 @@ ruby/spec is known to be tested in these implementations for every commit:
* [TruffleRuby](https://github.com/oracle/truffleruby/tree/master/spec/ruby)
* [Opal](https://github.com/opal/opal/tree/master/spec)
-ruby/spec describes the behavior of Ruby 2.4 and more recent Ruby versions.
-More precisely, every latest stable MRI release should [pass](https://travis-ci.org/ruby/spec) all specs of ruby/spec (2.4.x, 2.5.x, 2.6.x, etc), and those are tested in TravisCI.
+ruby/spec describes the behavior of Ruby 2.5 and more recent Ruby versions.
+More precisely, every latest stable MRI release should [pass](https://travis-ci.org/ruby/spec) all specs of ruby/spec (2.5.x, 2.6.x, 2.7.x, etc), and those are tested in TravisCI.
+
+### Synchronization with Ruby Implementations
The specs are synchronized both ways around once a month by @eregon between ruby/spec, MRI, JRuby and TruffleRuby.
Each of these repositories has a full copy of the specs under `spec/ruby` to ease editing specs.
Any of these repositories can be used to add or edit specs, use what is most convenient for you.
-For *testing* a Ruby implementation, one should always test against the implementation's copy of the specs under `spec/ruby`, as that's what the Ruby implementation tests against in their CI.
+For *testing* the development version of a Ruby implementation, one should always test against that implementation's copy of the specs under `spec/ruby`, as that's what the Ruby implementation tests against in their CI.
Also, this repository doesn't always contain the latest spec changes from MRI (it's synchronized monthly), and does not contain tags (specs marked as failing on that Ruby implementation).
-Running specs in a Ruby implementation can be done with:
+Running specs on a Ruby implementation can be done with:
```
$ cd ruby_implementation/spec/ruby
@@ -45,6 +48,8 @@ $ cd ruby_implementation/spec/ruby
$ ../mspec/bin/mspec
```
+### Specs for old Ruby versions
+
For older specs try these commits:
* Ruby 2.0.0-p647 - [Suite](https://github.com/ruby/spec/commit/245862558761d5abc676843ef74f86c9bcc8ea8d) using [MSpec](https://github.com/ruby/mspec/commit/f90efa068791064f955de7a843e96e2d7d3041c2) (may encounter 2 failures)
* Ruby 2.1.9 - [Suite](https://github.com/ruby/spec/commit/f029e65241374386077ac500add557ae65069b55) using [MSpec](https://github.com/ruby/mspec/commit/55568ea3918c6380e64db8c567d732fa5781efed)
@@ -121,6 +126,16 @@ MSpec can automatically add new top-level constants in this file with:
See [CONTRIBUTING.md](https://github.com/ruby/spec/blob/master/CONTRIBUTING.md) for documentation about contributing and writing specs (guards, matchers, etc).
+### Dependencies
+
+These command-line executables are needed to run the specs.
+
+* `echo`
+* `stat` for `core/file/*time_spec.rb`
+* `find` for `core/file/fixtures/file_types.rb` (package `findutils`, not needed on Windows)
+
+The file `/etc/services` is required for socket specs (package `netbase` on Debian, not needed on Windows).
+
### Socket specs from rubysl-socket
Most specs under `library/socket` were imported from [the rubysl-socket project](https://github.com/rubysl/rubysl-socket).
diff --git a/spec/ruby/command_line/dash_e_spec.rb b/spec/ruby/command_line/dash_e_spec.rb
index 9f600eb414..24ed34376d 100644
--- a/spec/ruby/command_line/dash_e_spec.rb
+++ b/spec/ruby/command_line/dash_e_spec.rb
@@ -23,7 +23,7 @@ describe "The -e command line option" do
#needs to test return => LocalJumpError
- describe "with -n and a Fixnum range" do
+ describe "with -n and an Integer range" do
before :each do
@script = "-ne 'print if %s' #{fixture(__FILE__, "conditional_range.txt")}"
end
diff --git a/spec/ruby/command_line/dash_l_spec.rb b/spec/ruby/command_line/dash_l_spec.rb
new file mode 100644
index 0000000000..5c1d3cf4cd
--- /dev/null
+++ b/spec/ruby/command_line/dash_l_spec.rb
@@ -0,0 +1,31 @@
+require_relative '../spec_helper'
+
+describe "The -l command line option" do
+ before :each do
+ @names = fixture __FILE__, "full_names.txt"
+ end
+
+ it "chomps lines with default separator" do
+ ruby_exe('puts $_.end_with?("\n")', options: "-n -l", escape: true,
+ args: " < #{@names}").should ==
+ "false\nfalse\nfalse\n"
+ end
+
+ it "chomps last line based on $/" do
+ ruby_exe('BEGIN { $/ = "ones\n" }; puts $_', options: "-W0 -n -l", escape: true,
+ args: " < #{@names}").should ==
+ "alice j\nbob field\njames grey\n"
+ end
+
+ it "sets $\\ to the value of $/" do
+ ruby_exe("puts $\\ == $/", options: "-W0 -n -l", escape: true,
+ args: " < #{@names}").should ==
+ "true\ntrue\ntrue\n"
+ end
+
+ it "sets $-l" do
+ ruby_exe("puts $-l", options: "-n -l", escape: true,
+ args: " < #{@names}").should ==
+ "true\ntrue\ntrue\n"
+ end
+end
diff --git a/spec/ruby/command_line/dash_r_spec.rb b/spec/ruby/command_line/dash_r_spec.rb
index b29895bd26..46c000b9e7 100644
--- a/spec/ruby/command_line/dash_r_spec.rb
+++ b/spec/ruby/command_line/dash_r_spec.rb
@@ -7,7 +7,22 @@ describe "The -r command line option" do
end
it "requires the specified file" do
- result = ruby_exe(@script, options: "-r #{@test_file}")
- result.should include(@test_file + ".rb")
+ out = ruby_exe(@script, options: "-r #{@test_file}")
+ out.should include("REQUIRED")
+ out.should include(@test_file + ".rb")
+ end
+
+ it "requires the file before parsing the main script" do
+ out = ruby_exe(fixture(__FILE__, "bad_syntax.rb"), options: "-r #{@test_file}", args: "2>&1")
+ $?.should_not.success?
+ out.should include("REQUIRED")
+ out.should include("syntax error")
+ end
+
+ it "does not require the file if the main script file does not exist" do
+ out = `#{ruby_exe.to_a.join(' ')} -r #{@test_file} #{fixture(__FILE__, "does_not_exist.rb")} 2>&1`
+ $?.should_not.success?
+ out.should_not.include?("REQUIRED")
+ out.should.include?("No such file or directory")
end
end
diff --git a/spec/ruby/command_line/dash_upper_k_spec.rb b/spec/ruby/command_line/dash_upper_k_spec.rb
index a060eab793..7e71532295 100644
--- a/spec/ruby/command_line/dash_upper_k_spec.rb
+++ b/spec/ruby/command_line/dash_upper_k_spec.rb
@@ -58,8 +58,8 @@ describe 'The -K command line option' do
end
it "ignores unknown codes" do
- locale = Encoding.find('locale')
+ external = Encoding.find('external')
ruby_exe(@test_string, options: '-KZ').should ==
- [Encoding::UTF_8.name, locale.name, nil].inspect
+ [Encoding::UTF_8.name, external.name, nil].inspect
end
end
diff --git a/spec/ruby/command_line/dash_upper_w_spec.rb b/spec/ruby/command_line/dash_upper_w_spec.rb
index 31bb976ad2..b705638606 100644
--- a/spec/ruby/command_line/dash_upper_w_spec.rb
+++ b/spec/ruby/command_line/dash_upper_w_spec.rb
@@ -18,3 +18,35 @@ end
describe "The -W command line option with 2" do
it_behaves_like :command_line_verbose, "-W2"
end
+
+ruby_version_is "2.7" do
+ describe "The -W command line option with :no-deprecated" do
+ it "suppresses deprecation warnings" do
+ result = ruby_exe('$; = ""', options: '-w', args: '2>&1')
+ result.should =~ /is deprecated/
+
+ result = ruby_exe('$; = ""', options: '-w -W:no-deprecated', args: '2>&1')
+ result.should == ""
+ end
+ end
+
+ describe "The -W command line option with :no-experimental" do
+ before do
+ ruby_version_is ""..."3.0" do
+ @src = 'case [0, 1]; in [a, b]; end'
+ end
+
+ ruby_version_is "3.0" do
+ @src = '[0, 1] => [a, b]'
+ end
+ end
+
+ it "suppresses experimental warnings" do
+ result = ruby_exe(@src, args: '2>&1')
+ result.should =~ /is experimental/
+
+ result = ruby_exe(@src, options: '-W:no-experimental', args: '2>&1')
+ result.should == ""
+ end
+ end
+end
diff --git a/spec/ruby/command_line/error_message_spec.rb b/spec/ruby/command_line/error_message_spec.rb
index 5fee3ead44..f3f7de4fd4 100644
--- a/spec/ruby/command_line/error_message_spec.rb
+++ b/spec/ruby/command_line/error_message_spec.rb
@@ -3,9 +3,9 @@ require_relative '../spec_helper'
describe "The error message caused by an exception" do
it "is not printed to stdout" do
out = ruby_exe("this_does_not_exist", args: "2> #{File::NULL}")
- out.chomp.empty?.should == true
+ out.chomp.should.empty?
out = ruby_exe("end #syntax error", args: "2> #{File::NULL}")
- out.chomp.empty?.should == true
+ out.chomp.should.empty?
end
end
diff --git a/spec/ruby/command_line/feature_spec.rb b/spec/ruby/command_line/feature_spec.rb
index 02571ee8c6..16e106b37d 100644
--- a/spec/ruby/command_line/feature_spec.rb
+++ b/spec/ruby/command_line/feature_spec.rb
@@ -37,11 +37,18 @@ describe "The --enable and --disable flags" do
ruby_exe("p 'foo'.frozen?", options: "--disable-frozen-string-literal").chomp.should == "false"
end
- it "can be used with all" do
+ platform_is_not :darwin do # frequently hangs for >60s on GitHub Actions macos-latest
+ it "can be used with all for enable" do
+ e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]"
+ env = {'RUBYOPT' => '-w'}
+ # Use a single variant here because it can be quite slow as it might enable jit, etc
+ ruby_exe(e, options: "--enable-all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]"
+ end
+ end
+
+ it "can be used with all for disable" do
e = "p [defined?(Gem), defined?(DidYouMean), $VERBOSE, 'foo'.frozen?]"
env = {'RUBYOPT' => '-w'}
- ruby_exe(e, options: "--enable=all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]"
- ruby_exe(e, options: "--enable-all", env: env).chomp.should == "[\"constant\", \"constant\", true, true]"
ruby_exe(e, options: "--disable=all", env: env).chomp.should == "[nil, nil, false, false]"
ruby_exe(e, options: "--disable-all", env: env).chomp.should == "[nil, nil, false, false]"
end
diff --git a/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh b/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh
index 0eede2a99f..fd3249f0e5 100644
--- a/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh
+++ b/spec/ruby/command_line/fixtures/bin/hybrid_launcher.sh
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
-exec somehow this file
+echo 'error' && exit 1
#!ruby
puts 'success'
diff --git a/spec/ruby/command_line/fixtures/test_file.rb b/spec/ruby/command_line/fixtures/test_file.rb
index 961e3c0b0c..30a832299e 100644
--- a/spec/ruby/command_line/fixtures/test_file.rb
+++ b/spec/ruby/command_line/fixtures/test_file.rb
@@ -1 +1 @@
-"test file"
+puts "REQUIRED"
diff --git a/spec/ruby/command_line/rubyopt_spec.rb b/spec/ruby/command_line/rubyopt_spec.rb
index 2db42f77ef..a739f23eb8 100644
--- a/spec/ruby/command_line/rubyopt_spec.rb
+++ b/spec/ruby/command_line/rubyopt_spec.rb
@@ -59,6 +59,26 @@ describe "Processing RUBYOPT" do
ruby_exe("p $VERBOSE", escape: true).chomp.should == "true"
end
+ ruby_version_is "2.7" do
+ it "suppresses deprecation warnings for '-W:no-deprecated'" do
+ ENV["RUBYOPT"] = '-W:no-deprecated'
+ result = ruby_exe('$; = ""', args: '2>&1')
+ result.should == ""
+ end
+
+ it "suppresses experimental warnings for '-W:no-experimental'" do
+ ENV["RUBYOPT"] = '-W:no-experimental'
+ result = ruby_exe('case 0; in a; end', args: '2>&1')
+ result.should == ""
+ end
+
+ it "suppresses deprecation and experimental warnings for '-W:no-deprecated -W:no-experimental'" do
+ ENV["RUBYOPT"] = '-W:no-deprecated -W:no-experimental'
+ result = ruby_exe('case ($; = ""); in a; end', args: '2>&1')
+ result.should == ""
+ end
+ end
+
it "requires the file for '-r'" do
f = fixture __FILE__, "rubyopt"
ENV["RUBYOPT"] = "-r#{f}"
diff --git a/spec/ruby/core/argf/binmode_spec.rb b/spec/ruby/core/argf/binmode_spec.rb
index bdcc6aa30a..e083a30a27 100644
--- a/spec/ruby/core/argf/binmode_spec.rb
+++ b/spec/ruby/core/argf/binmode_spec.rb
@@ -34,7 +34,7 @@ describe "ARGF.binmode" do
it "sets the file's encoding to BINARY" do
argf [@bin_file, @file1] do
@argf.binmode
- @argf.binmode?.should == true
+ @argf.should.binmode?
@argf.gets.encoding.should == Encoding::BINARY
@argf.skip
@argf.read.encoding.should == Encoding::BINARY
diff --git a/spec/ruby/core/argf/bytes_spec.rb b/spec/ruby/core/argf/bytes_spec.rb
index 71d07fabcb..3e11a4f5c4 100644
--- a/spec/ruby/core/argf/bytes_spec.rb
+++ b/spec/ruby/core/argf/bytes_spec.rb
@@ -1,6 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/each_byte'
-describe "ARGF.bytes" do
- it_behaves_like :argf_each_byte, :bytes
+ruby_version_is ''...'3.0' do
+ describe "ARGF.bytes" do
+ it_behaves_like :argf_each_byte, :bytes
+ end
end
diff --git a/spec/ruby/core/argf/chars_spec.rb b/spec/ruby/core/argf/chars_spec.rb
index ee79ea763b..a864ce6d52 100644
--- a/spec/ruby/core/argf/chars_spec.rb
+++ b/spec/ruby/core/argf/chars_spec.rb
@@ -1,6 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/each_char'
-describe "ARGF.chars" do
- it_behaves_like :argf_each_char, :chars
+ruby_version_is ''...'3.0' do
+ describe "ARGF.chars" do
+ it_behaves_like :argf_each_char, :chars
+ end
end
diff --git a/spec/ruby/core/argf/codepoints_spec.rb b/spec/ruby/core/argf/codepoints_spec.rb
index 7aa8a761fe..d3007c4c5b 100644
--- a/spec/ruby/core/argf/codepoints_spec.rb
+++ b/spec/ruby/core/argf/codepoints_spec.rb
@@ -1,6 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/each_codepoint'
-describe "ARGF.codepoints" do
- it_behaves_like :argf_each_codepoint, :codepoints
+ruby_version_is ''...'3.0' do
+ describe "ARGF.codepoints" do
+ it_behaves_like :argf_each_codepoint, :codepoints
+ end
end
diff --git a/spec/ruby/core/argf/lines_spec.rb b/spec/ruby/core/argf/lines_spec.rb
index 6ca6ff1256..0bf5bb0d73 100644
--- a/spec/ruby/core/argf/lines_spec.rb
+++ b/spec/ruby/core/argf/lines_spec.rb
@@ -1,6 +1,8 @@
require_relative '../../spec_helper'
require_relative 'shared/each_line'
-describe "ARGF.lines" do
- it_behaves_like :argf_each_line, :lines
+ruby_version_is ''...'3.0' do
+ describe "ARGF.lines" do
+ it_behaves_like :argf_each_line, :lines
+ end
end
diff --git a/spec/ruby/core/argf/shared/fileno.rb b/spec/ruby/core/argf/shared/fileno.rb
index 5d674048e2..4350d43747 100644
--- a/spec/ruby/core/argf/shared/fileno.rb
+++ b/spec/ruby/core/argf/shared/fileno.rb
@@ -11,7 +11,7 @@ describe :argf_fileno, shared: true do
# returns first current file even when not yet open
result << @argf.send(@method) while @argf.gets
# returns last current file even when closed
- result.map { |d| d.class }.should == [Fixnum, Fixnum, Fixnum, Fixnum]
+ result.map { |d| d.class }.should == [Integer, Integer, Integer, Integer]
end
end
diff --git a/spec/ruby/core/array/any_spec.rb b/spec/ruby/core/array/any_spec.rb
index 2fa5353e99..09d949fe6e 100644
--- a/spec/ruby/core/array/any_spec.rb
+++ b/spec/ruby/core/array/any_spec.rb
@@ -4,17 +4,17 @@ describe "Array#any?" do
describe 'with no block given (a default block of { |x| x } is implicit)' do
it "is false if the array is empty" do
empty_array = []
- empty_array.any?.should == false
+ empty_array.should_not.any?
end
it "is false if the array is not empty, but all the members of the array are falsy" do
falsy_array = [false, nil, false]
- falsy_array.any?.should == false
+ falsy_array.should_not.any?
end
it "is true if the array has any truthy members" do
not_empty_array = ['anything', nil]
- not_empty_array.any?.should == true
+ not_empty_array.should.any?
end
end
diff --git a/spec/ruby/core/array/append_spec.rb b/spec/ruby/core/array/append_spec.rb
index 302dc4a901..c12473dc07 100644
--- a/spec/ruby/core/array/append_spec.rb
+++ b/spec/ruby/core/array/append_spec.rb
@@ -30,13 +30,11 @@ describe "Array#<<" do
a.should == [:foo]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array << 5 }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array << 5 }.should raise_error(FrozenError)
end
end
-ruby_version_is "2.5" do
- describe "Array#append" do
- it_behaves_like :array_push, :append
- end
+describe "Array#append" do
+ it_behaves_like :array_push, :append
end
diff --git a/spec/ruby/core/array/bsearch_index_spec.rb b/spec/ruby/core/array/bsearch_index_spec.rb
index aafded178d..df2c7c098e 100644
--- a/spec/ruby/core/array/bsearch_index_spec.rb
+++ b/spec/ruby/core/array/bsearch_index_spec.rb
@@ -77,7 +77,7 @@ describe "Array#bsearch_index" do
@array.bsearch_index { |x| (-1) * (2**100) }.should be_nil
end
- it "handles values from Bignum#coerce" do
+ it "handles values from Integer#coerce" do
[1, 2].should include(@array.bsearch_index { |x| (2**100).coerce((1 - x / 4) * (2**100)).first })
end
end
diff --git a/spec/ruby/core/array/clear_spec.rb b/spec/ruby/core/array/clear_spec.rb
index d399d5a373..bddc672d3b 100644
--- a/spec/ruby/core/array/clear_spec.rb
+++ b/spec/ruby/core/array/clear_spec.rb
@@ -16,7 +16,7 @@ describe "Array#clear" do
it "leaves the Array empty" do
a = [1]
a.clear
- a.empty?.should == true
+ a.should.empty?
a.size.should == 0
end
@@ -44,9 +44,9 @@ describe "Array#clear" do
end
end
- it "raises a #{frozen_error_class} on a frozen array" do
+ it "raises a FrozenError on a frozen array" do
a = [1]
a.freeze
- -> { a.clear }.should raise_error(frozen_error_class)
+ -> { a.clear }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/clone_spec.rb b/spec/ruby/core/array/clone_spec.rb
index 803e746e02..e22a6c6d53 100644
--- a/spec/ruby/core/array/clone_spec.rb
+++ b/spec/ruby/core/array/clone_spec.rb
@@ -12,8 +12,8 @@ describe "Array#clone" do
aa = a.clone
bb = b.clone
- aa.frozen?.should == true
- bb.frozen?.should == false
+ aa.should.frozen?
+ bb.should_not.frozen?
end
it "copies singleton methods" do
diff --git a/spec/ruby/core/array/compact_spec.rb b/spec/ruby/core/array/compact_spec.rb
index ee3dfc0ca2..aa3c1c0446 100644
--- a/spec/ruby/core/array/compact_spec.rb
+++ b/spec/ruby/core/array/compact_spec.rb
@@ -75,7 +75,7 @@ describe "Array#compact!" do
end
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.compact! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.compact! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/concat_spec.rb b/spec/ruby/core/array/concat_spec.rb
index b297c091a3..da6763bfd6 100644
--- a/spec/ruby/core/array/concat_spec.rb
+++ b/spec/ruby/core/array/concat_spec.rb
@@ -32,13 +32,13 @@ describe "Array#concat" do
[].concat(obj).should == [5, 6, 7]
end
- it "raises a #{frozen_error_class} when Array is frozen and modification occurs" do
- -> { ArraySpecs.frozen_array.concat [1] }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when Array is frozen and modification occurs" do
+ -> { ArraySpecs.frozen_array.concat [1] }.should raise_error(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} when Array is frozen and no modification occurs" do
- -> { ArraySpecs.frozen_array.concat([]) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when Array is frozen and no modification occurs" do
+ -> { ArraySpecs.frozen_array.concat([]) }.should raise_error(FrozenError)
end
ruby_version_is ''...'2.7' do
diff --git a/spec/ruby/core/array/deconstruct_spec.rb b/spec/ruby/core/array/deconstruct_spec.rb
new file mode 100644
index 0000000000..2b07152dfc
--- /dev/null
+++ b/spec/ruby/core/array/deconstruct_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "2.7" do
+ describe "Array#deconstruct" do
+ it "returns self" do
+ array = [1]
+
+ array.deconstruct.should equal array
+ end
+ end
+end
diff --git a/spec/ruby/core/array/delete_at_spec.rb b/spec/ruby/core/array/delete_at_spec.rb
index 0ed56c18bb..fc225a03f1 100644
--- a/spec/ruby/core/array/delete_at_spec.rb
+++ b/spec/ruby/core/array/delete_at_spec.rb
@@ -35,8 +35,8 @@ describe "Array#delete_at" do
a.delete_at(-2).should == 1
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { [1,2,3].freeze.delete_at(0) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { [1,2,3].freeze.delete_at(0) }.should raise_error(FrozenError)
end
ruby_version_is ''...'2.7' do
diff --git a/spec/ruby/core/array/delete_if_spec.rb b/spec/ruby/core/array/delete_if_spec.rb
index 2312917c41..e1931220f5 100644
--- a/spec/ruby/core/array/delete_if_spec.rb
+++ b/spec/ruby/core/array/delete_if_spec.rb
@@ -39,12 +39,12 @@ describe "Array#delete_if" do
@a.freeze.delete_if.should be_an_instance_of(Enumerator)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.delete_if {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.delete_if {} }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.delete_if {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.delete_if {} }.should raise_error(FrozenError)
end
ruby_version_is ''...'2.7' do
diff --git a/spec/ruby/core/array/delete_spec.rb b/spec/ruby/core/array/delete_spec.rb
index 41e211e660..5d53c74e47 100644
--- a/spec/ruby/core/array/delete_spec.rb
+++ b/spec/ruby/core/array/delete_spec.rb
@@ -40,8 +40,8 @@ describe "Array#delete" do
[1, 2, 3].freeze.delete(0).should == nil
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { [1, 2, 3].freeze.delete(1) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { [1, 2, 3].freeze.delete(1) }.should raise_error(FrozenError)
end
ruby_version_is ''...'2.7' do
diff --git a/spec/ruby/core/array/element_set_spec.rb b/spec/ruby/core/array/element_set_spec.rb
index 9375ff9b80..2e01e838e9 100644
--- a/spec/ruby/core/array/element_set_spec.rb
+++ b/spec/ruby/core/array/element_set_spec.rb
@@ -94,8 +94,8 @@ describe "Array#[]=" do
it "checks frozen before attempting to coerce arguments" do
a = [1,2,3,4].freeze
- -> {a[:foo] = 1}.should raise_error(frozen_error_class)
- -> {a[:foo, :bar] = 1}.should raise_error(frozen_error_class)
+ -> {a[:foo] = 1}.should raise_error(FrozenError)
+ -> {a[:foo, :bar] = 1}.should raise_error(FrozenError)
end
it "sets elements in the range arguments when passed ranges" do
@@ -236,8 +236,8 @@ describe "Array#[]=" do
ary.should == [5, 6, 7]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array[0, 0] = [] }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array[0, 0] = [] }.should raise_error(FrozenError)
end
end
@@ -323,6 +323,10 @@ describe "Array#[]= with [index, count]" do
b = [1, 2, 3, 4, 5]
b[10, 0] = [1]
a.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil, 1]
+
+ c = [1, 2, 3, 4, 5]
+ c[10, 0] = []
+ c.should == [1, 2, 3, 4, 5, nil, nil, nil, nil, nil]
end
it "inserts other section in place defined by idx" do
@@ -396,6 +400,14 @@ describe "Array#[]= with [m..n]" do
a.should == [1, 2, 3, 8, 4, 5]
end
+ it "inserts at the end if m > the array size" do
+ a = [1, 2, 3]
+ a[3..3] = [4]
+ a.should == [1, 2, 3, 4]
+ a[5..7] = [6]
+ a.should == [1, 2, 3, 4, nil, 6]
+ end
+
describe "Range subclasses" do
before :each do
@range_incl = ArraySpecs::MyRange.new(1, 2)
@@ -425,6 +437,45 @@ describe "Array#[]= with [m..n]" do
end
end
+ruby_version_is "2.6" do
+ describe "Array#[]= with [m..]" do
+
+ it "just sets the section defined by range to nil even if the rhs is nil" do
+ a = [1, 2, 3, 4, 5]
+ a[eval("(2..)")] = nil
+ a.should == [1, 2, nil]
+ end
+
+ it "just sets the section defined by range to nil if m and n < 0 and the rhs is nil" do
+ a = [1, 2, 3, 4, 5]
+ a[eval("(-3..)")] = nil
+ a.should == [1, 2, nil]
+ end
+
+ it "replaces the section defined by range" do
+ a = [6, 5, 4, 3, 2, 1]
+ a[eval("(3...)")] = 9
+ a.should == [6, 5, 4, 9]
+ a[eval("(2..)")] = [7, 7, 7]
+ a.should == [6, 5, 7, 7, 7]
+ end
+
+ it "replaces the section if m and n < 0" do
+ a = [1, 2, 3, 4, 5]
+ a[eval("(-3..)")] = [7, 8, 9]
+ a.should == [1, 2, 7, 8, 9]
+ end
+
+ it "inserts at the end if m > the array size" do
+ a = [1, 2, 3]
+ a[eval("(3..)")] = [4]
+ a.should == [1, 2, 3, 4]
+ a[eval("(5..)")] = [6]
+ a.should == [1, 2, 3, 4, nil, 6]
+ end
+ end
+end
+
describe "Array#[] after a shift" do
it "works for insertion" do
a = [1,2]
diff --git a/spec/ruby/core/array/empty_spec.rb b/spec/ruby/core/array/empty_spec.rb
index b5f3e8ed48..f70b1b6ebe 100644
--- a/spec/ruby/core/array/empty_spec.rb
+++ b/spec/ruby/core/array/empty_spec.rb
@@ -3,8 +3,8 @@ require_relative 'fixtures/classes'
describe "Array#empty?" do
it "returns true if the array has no elements" do
- [].empty?.should == true
- [1].empty?.should == false
- [1, 2].empty?.should == false
+ [].should.empty?
+ [1].should_not.empty?
+ [1, 2].should_not.empty?
end
end
diff --git a/spec/ruby/core/array/fill_spec.rb b/spec/ruby/core/array/fill_spec.rb
index 1c1beef25e..6745bc8d09 100644
--- a/spec/ruby/core/array/fill_spec.rb
+++ b/spec/ruby/core/array/fill_spec.rb
@@ -43,12 +43,12 @@ describe "Array#fill" do
[nil, nil, nil, nil].fill { |i| i * 2 }.should == [0, 2, 4, 6]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.fill('x') }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.fill('x') }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.fill('x') }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.fill('x') }.should raise_error(FrozenError)
end
it "raises an ArgumentError if 4 or more arguments are passed when no block given" do
@@ -207,8 +207,9 @@ describe "Array#fill with (filler, index, length)" do
not_supported_on :opal do
it "raises an ArgumentError or RangeError for too-large sizes" do
+ error_types = [RangeError, ArgumentError]
arr = [1, 2, 3]
- -> { arr.fill(10, 1, fixnum_max) }.should raise_error(ArgumentError)
+ -> { arr.fill(10, 1, fixnum_max) }.should raise_error { |err| error_types.should include(err.class) }
-> { arr.fill(10, 1, bignum_value) }.should raise_error(RangeError)
end
end
@@ -314,4 +315,13 @@ describe "Array#fill with (filler, range)" do
def obj.<=>(rhs); rhs == self ? 0 : nil end
-> { [].fill('a', obj..obj) }.should raise_error(TypeError)
end
+
+ ruby_version_is "2.6" do
+ it "works with endless ranges" do
+ [1, 2, 3, 4].fill('x', eval("(1..)")).should == [1, 'x', 'x', 'x']
+ [1, 2, 3, 4].fill('x', eval("(3...)")).should == [1, 2, 3, 'x']
+ [1, 2, 3, 4].fill(eval("(1..)")) { |x| x + 2 }.should == [1, 3, 4, 5]
+ [1, 2, 3, 4].fill(eval("(3...)")) { |x| x + 2 }.should == [1, 2, 3, 5]
+ end
+ end
end
diff --git a/spec/ruby/core/array/first_spec.rb b/spec/ruby/core/array/first_spec.rb
index 66eeba6565..463da829a2 100644
--- a/spec/ruby/core/array/first_spec.rb
+++ b/spec/ruby/core/array/first_spec.rb
@@ -33,7 +33,7 @@ describe "Array#first" do
-> { [1, 2].first(-1) }.should raise_error(ArgumentError)
end
- it "raises a RangeError when count is a Bignum" do
+ it "raises a RangeError when count is an Integer" do
-> { [].first(bignum_value) }.should raise_error(RangeError)
end
diff --git a/spec/ruby/core/array/fixtures/classes.rb b/spec/ruby/core/array/fixtures/classes.rb
index 42071ed0cd..affb3b49e6 100644
--- a/spec/ruby/core/array/fixtures/classes.rb
+++ b/spec/ruby/core/array/fixtures/classes.rb
@@ -126,7 +126,7 @@ module ArraySpecs
attr_accessor :order
end
- class ComparableWithFixnum
+ class ComparableWithInteger
include Comparable
def initialize(num)
@num = num
@@ -144,7 +144,7 @@ module ArraySpecs
end
def self.universal_pack_object
- obj = mock("string float int")
+ obj = mock("string float int".freeze)
obj.stub!(:to_int).and_return(1)
obj.stub!(:to_str).and_return("1")
obj.stub!(:to_f).and_return(1.0)
diff --git a/spec/ruby/core/array/flatten_spec.rb b/spec/ruby/core/array/flatten_spec.rb
index 66af20ad70..2f9fb8a3ec 100644
--- a/spec/ruby/core/array/flatten_spec.rb
+++ b/spec/ruby/core/array/flatten_spec.rb
@@ -75,12 +75,24 @@ describe "Array#flatten" do
[[obj]].flatten(1)
end
- it "returns subclass instance for Array subclasses" do
- ArraySpecs::MyArray[].flatten.should be_an_instance_of(ArraySpecs::MyArray)
- ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
- ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
- ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == ArraySpecs::MyArray[1, 2, 3, 4]
- [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instance for Array subclasses" do
+ ArraySpecs::MyArray[].flatten.should be_an_instance_of(ArraySpecs::MyArray)
+ ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
+ ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(ArraySpecs::MyArray)
+ ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == ArraySpecs::MyArray[1, 2, 3, 4]
+ [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns Array instance for Array subclasses" do
+ ArraySpecs::MyArray[].flatten.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].flatten.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, [2], 3].flatten.should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, [2, 3], 4].flatten.should == [1, 2, 3, 4]
+ [ArraySpecs::MyArray[1, 2, 3]].flatten.should be_an_instance_of(Array)
+ end
end
it "is not destructive" do
@@ -109,20 +121,10 @@ describe "Array#flatten" do
-> { [@obj].flatten }.should raise_error(TypeError)
end
- ruby_version_is ""..."2.5" do
- it "calls respond_to_missing?(:to_ary, false) to try coercing" do
- def @obj.respond_to_missing?(*args) ScratchPad << args; false end
- [@obj].flatten.should == [@obj]
- ScratchPad.recorded.should == [[:to_ary, false]]
- end
- end
-
- ruby_version_is "2.5" do
- it "calls respond_to_missing?(:to_ary, true) to try coercing" do
- def @obj.respond_to_missing?(*args) ScratchPad << args; false end
- [@obj].flatten.should == [@obj]
- ScratchPad.recorded.should == [[:to_ary, true]]
- end
+ it "calls respond_to_missing?(:to_ary, true) to try coercing" do
+ def @obj.respond_to_missing?(*args) ScratchPad << args; false end
+ [@obj].flatten.should == [@obj]
+ ScratchPad.recorded.should == [[:to_ary, true]]
end
it "does not call #to_ary if not defined when #respond_to_missing? returns false" do
@@ -272,15 +274,15 @@ describe "Array#flatten!" do
ary.should == [1, 2, 3]
end
- it "raises a #{frozen_error_class} on frozen arrays when the array is modified" do
+ it "raises a FrozenError on frozen arrays when the array is modified" do
nested_ary = [1, 2, []]
nested_ary.freeze
- -> { nested_ary.flatten! }.should raise_error(frozen_error_class)
+ -> { nested_ary.flatten! }.should raise_error(FrozenError)
end
# see [ruby-core:23663]
- it "raises a #{frozen_error_class} on frozen arrays when the array would not be modified" do
- -> { ArraySpecs.frozen_array.flatten! }.should raise_error(frozen_error_class)
- -> { ArraySpecs.empty_frozen_array.flatten! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on frozen arrays when the array would not be modified" do
+ -> { ArraySpecs.frozen_array.flatten! }.should raise_error(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.flatten! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/frozen_spec.rb b/spec/ruby/core/array/frozen_spec.rb
index bb4b2b4067..3ba54be46b 100644
--- a/spec/ruby/core/array/frozen_spec.rb
+++ b/spec/ruby/core/array/frozen_spec.rb
@@ -4,13 +4,13 @@ require_relative 'fixtures/classes'
describe "Array#frozen?" do
it "returns true if array is frozen" do
a = [1, 2, 3]
- a.frozen?.should == false
+ a.should_not.frozen?
a.freeze
- a.frozen?.should == true
+ a.should.frozen?
end
it "returns false for an array being sorted by #sort" do
a = [1, 2, 3]
- a.sort { |x,y| a.frozen?.should == false; x <=> y }
+ a.sort { |x,y| a.should_not.frozen?; x <=> y }
end
end
diff --git a/spec/ruby/core/array/hash_spec.rb b/spec/ruby/core/array/hash_spec.rb
index 8392253ae4..f3bcc83fce 100644
--- a/spec/ruby/core/array/hash_spec.rb
+++ b/spec/ruby/core/array/hash_spec.rb
@@ -7,7 +7,7 @@ describe "Array#hash" do
[[], [1, 2, 3]].each do |ary|
ary.hash.should == ary.dup.hash
- ary.hash.should be_an_instance_of(Fixnum)
+ ary.hash.should be_an_instance_of(Integer)
end
end
diff --git a/spec/ruby/core/array/initialize_spec.rb b/spec/ruby/core/array/initialize_spec.rb
index dfc2ae3518..a8deed2b84 100644
--- a/spec/ruby/core/array/initialize_spec.rb
+++ b/spec/ruby/core/array/initialize_spec.rb
@@ -32,13 +32,13 @@ describe "Array#initialize" do
end.should raise_error(ArgumentError)
end
- it "raises a #{frozen_error_class} on frozen arrays" do
+ it "raises a FrozenError on frozen arrays" do
-> do
ArraySpecs.frozen_array.send :initialize
- end.should raise_error(frozen_error_class)
+ end.should raise_error(FrozenError)
-> do
ArraySpecs.frozen_array.send :initialize, ArraySpecs.frozen_array
- end.should raise_error(frozen_error_class)
+ end.should raise_error(FrozenError)
end
it "calls #to_ary to convert the value to an array, even if it's private" do
diff --git a/spec/ruby/core/array/insert_spec.rb b/spec/ruby/core/array/insert_spec.rb
index 7577a8f743..9e1757f68b 100644
--- a/spec/ruby/core/array/insert_spec.rb
+++ b/spec/ruby/core/array/insert_spec.rb
@@ -67,12 +67,12 @@ describe "Array#insert" do
-> { [].insert() }.should raise_error(ArgumentError)
end
- it "raises a #{frozen_error_class} on frozen arrays when the array is modified" do
- -> { ArraySpecs.frozen_array.insert(0, 'x') }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on frozen arrays when the array is modified" do
+ -> { ArraySpecs.frozen_array.insert(0, 'x') }.should raise_error(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on frozen arrays when the array would not be modified" do
- -> { ArraySpecs.frozen_array.insert(0) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on frozen arrays when the array would not be modified" do
+ -> { ArraySpecs.frozen_array.insert(0) }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/intersection_spec.rb b/spec/ruby/core/array/intersection_spec.rb
index 7bf2ec4dbe..27d90f1e44 100644
--- a/spec/ruby/core/array/intersection_spec.rb
+++ b/spec/ruby/core/array/intersection_spec.rb
@@ -1,87 +1,21 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'shared/intersection'
describe "Array#&" do
- it "creates an array with elements common to both arrays (intersection)" do
- ([] & []).should == []
- ([1, 2] & []).should == []
- ([] & [1, 2]).should == []
- ([ 1, 3, 5 ] & [ 1, 2, 3 ]).should == [1, 3]
- end
-
- it "creates an array with no duplicates" do
- ([ 1, 1, 3, 5 ] & [ 1, 2, 3 ]).uniq!.should == nil
- end
-
- it "creates an array with elements in order they are first encountered" do
- ([ 1, 2, 3, 2, 5 ] & [ 5, 2, 3, 4 ]).should == [2, 3, 5]
- end
-
- it "does not modify the original Array" do
- a = [1, 1, 3, 5]
- (a & [1, 2, 3]).should == [1, 3]
- a.should == [1, 1, 3, 5]
- end
-
- it "properly handles recursive arrays" do
- empty = ArraySpecs.empty_recursive_array
- (empty & empty).should == empty
-
- (ArraySpecs.recursive_array & []).should == []
- ([] & ArraySpecs.recursive_array).should == []
-
- (ArraySpecs.recursive_array & ArraySpecs.recursive_array).should == [1, 'two', 3.0, ArraySpecs.recursive_array]
- end
+ it_behaves_like :array_intersection, :&
+end
- it "tries to convert the passed argument to an Array using #to_ary" do
- obj = mock('[1,2,3]')
- obj.should_receive(:to_ary).and_return([1, 2, 3])
- ([1, 2] & obj).should == ([1, 2])
- end
+ruby_version_is "2.7" do
+ describe "Array#intersection" do
+ it_behaves_like :array_intersection, :intersection
- it "determines equivalence between elements in the sense of eql?" do
- not_supported_on :opal do
- ([5.0, 4.0] & [5, 4]).should == []
+ it "accepts multiple arguments" do
+ [1, 2, 3, 4].intersection([1, 2, 3], [2, 3, 4]).should == [2, 3]
end
- str = "x"
- ([str] & [str.dup]).should == [str]
-
- obj1 = mock('1')
- obj2 = mock('2')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.should_receive(:eql?).at_least(1).and_return(true)
- obj2.stub!(:eql?).and_return(true)
-
- ([obj1] & [obj2]).should == [obj1]
- ([obj1, obj1, obj2, obj2] & [obj2]).should == [obj1]
-
- obj1 = mock('3')
- obj2 = mock('4')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.should_receive(:eql?).at_least(1).and_return(false)
-
- ([obj1] & [obj2]).should == []
- ([obj1, obj1, obj2, obj2] & [obj2]).should == [obj2]
- end
-
- it "does return subclass instances for Array subclasses" do
- (ArraySpecs::MyArray[1, 2, 3] & []).should be_an_instance_of(Array)
- (ArraySpecs::MyArray[1, 2, 3] & ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
- ([] & ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
- end
-
- it "does not call to_ary on array subclasses" do
- ([5, 6] & ArraySpecs::ToAryArray[1, 2, 5, 6]).should == [5, 6]
- end
-
- it "properly handles an identical item even when its #eql? isn't reflexive" do
- x = mock('x')
- x.stub!(:hash).and_return(42)
- x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
-
- ([x] & [x]).should == [x]
+ it "preserves elements order from original array" do
+ [1, 2, 3, 4].intersection([3, 2, 1]).should == [1, 2, 3]
+ end
end
end
diff --git a/spec/ruby/core/array/minmax_spec.rb b/spec/ruby/core/array/minmax_spec.rb
new file mode 100644
index 0000000000..e11fe63347
--- /dev/null
+++ b/spec/ruby/core/array/minmax_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+require_relative '../../shared/enumerable/minmax'
+
+describe "Array#minmax" do
+ before :each do
+ @enum = [6, 4, 5, 10, 8]
+ @empty_enum = []
+ @incomparable_enum = [BasicObject.new, BasicObject.new]
+ @incompatible_enum = [11, "22"]
+ @strs = ["333", "2", "60", "55555", "1010", "111"]
+ end
+
+ it_behaves_like :enumerable_minmax, :minmax
+end
diff --git a/spec/ruby/core/array/multiply_spec.rb b/spec/ruby/core/array/multiply_spec.rb
index 4060666d4b..16e407348b 100644
--- a/spec/ruby/core/array/multiply_spec.rb
+++ b/spec/ruby/core/array/multiply_spec.rb
@@ -76,10 +76,20 @@ describe "Array#* with an integer" do
@array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
end
- it "returns a subclass instance" do
- (@array * 0).should be_an_instance_of(ArraySpecs::MyArray)
- (@array * 1).should be_an_instance_of(ArraySpecs::MyArray)
- (@array * 2).should be_an_instance_of(ArraySpecs::MyArray)
+ ruby_version_is ''...'3.0' do
+ it "returns a subclass instance" do
+ (@array * 0).should be_an_instance_of(ArraySpecs::MyArray)
+ (@array * 1).should be_an_instance_of(ArraySpecs::MyArray)
+ (@array * 2).should be_an_instance_of(ArraySpecs::MyArray)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns an Array instance" do
+ (@array * 0).should be_an_instance_of(Array)
+ (@array * 1).should be_an_instance_of(Array)
+ (@array * 2).should be_an_instance_of(Array)
+ end
end
it "does not call #initialize on the subclass instance" do
@@ -92,39 +102,39 @@ describe "Array#* with an integer" do
it "copies the taint status of the original array even if the passed count is 0" do
ary = [1, 2, 3]
ary.taint
- (ary * 0).tainted?.should == true
+ (ary * 0).should.tainted?
end
it "copies the taint status of the original array even if the array is empty" do
ary = []
ary.taint
- (ary * 3).tainted?.should == true
+ (ary * 3).should.tainted?
end
it "copies the taint status of the original array if the passed count is not 0" do
ary = [1, 2, 3]
ary.taint
- (ary * 1).tainted?.should == true
- (ary * 2).tainted?.should == true
+ (ary * 1).should.tainted?
+ (ary * 2).should.tainted?
end
it "copies the untrusted status of the original array even if the passed count is 0" do
ary = [1, 2, 3]
ary.untrust
- (ary * 0).untrusted?.should == true
+ (ary * 0).should.untrusted?
end
it "copies the untrusted status of the original array even if the array is empty" do
ary = []
ary.untrust
- (ary * 3).untrusted?.should == true
+ (ary * 3).should.untrusted?
end
it "copies the untrusted status of the original array if the passed count is not 0" do
ary = [1, 2, 3]
ary.untrust
- (ary * 1).untrusted?.should == true
- (ary * 2).untrusted?.should == true
+ (ary * 1).should.untrusted?
+ (ary * 2).should.untrusted?
end
end
end
diff --git a/spec/ruby/core/array/pop_spec.rb b/spec/ruby/core/array/pop_spec.rb
index 2cfecbb2b4..96ef78da32 100644
--- a/spec/ruby/core/array/pop_spec.rb
+++ b/spec/ruby/core/array/pop_spec.rb
@@ -40,12 +40,12 @@ describe "Array#pop" do
end
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.pop }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.pop }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.pop }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.pop }.should raise_error(FrozenError)
end
ruby_version_is ''...'2.7' do
@@ -158,9 +158,9 @@ describe "Array#pop" do
end
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.pop(2) }.should raise_error(frozen_error_class)
- -> { ArraySpecs.frozen_array.pop(0) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.pop(2) }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.pop(0) }.should raise_error(FrozenError)
end
ruby_version_is ''...'2.7' do
diff --git a/spec/ruby/core/array/prepend_spec.rb b/spec/ruby/core/array/prepend_spec.rb
index 22230ec300..368b8dcfcd 100644
--- a/spec/ruby/core/array/prepend_spec.rb
+++ b/spec/ruby/core/array/prepend_spec.rb
@@ -2,8 +2,6 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/unshift'
-ruby_version_is "2.5" do
- describe "Array#prepend" do
- it_behaves_like :array_unshift, :prepend
- end
+describe "Array#prepend" do
+ it_behaves_like :array_unshift, :prepend
end
diff --git a/spec/ruby/core/array/reject_spec.rb b/spec/ruby/core/array/reject_spec.rb
index 1e9c296c8d..fcf43fabde 100644
--- a/spec/ruby/core/array/reject_spec.rb
+++ b/spec/ruby/core/array/reject_spec.rb
@@ -103,12 +103,12 @@ describe "Array#reject!" do
ArraySpecs.frozen_array.reject!.should be_an_instance_of(Enumerator)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.reject! {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.reject! {} }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.reject! {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.reject! {} }.should raise_error(FrozenError)
end
it "does not truncate the array is the block raises an exception" do
diff --git a/spec/ruby/core/array/reverse_spec.rb b/spec/ruby/core/array/reverse_spec.rb
index e738be6fe7..05dbd2efcf 100644
--- a/spec/ruby/core/array/reverse_spec.rb
+++ b/spec/ruby/core/array/reverse_spec.rb
@@ -36,7 +36,7 @@ describe "Array#reverse!" do
array.reverse!.should == [array, array, array, array, array, 3.0, 'two', 1]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.reverse! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.reverse! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/rotate_spec.rb b/spec/ruby/core/array/rotate_spec.rb
index cc1aabf986..60dcc8b113 100644
--- a/spec/ruby/core/array/rotate_spec.rb
+++ b/spec/ruby/core/array/rotate_spec.rb
@@ -121,9 +121,9 @@ describe "Array#rotate!" do
a.should == []
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { [1, 2, 3].freeze.rotate!(0) }.should raise_error(frozen_error_class)
- -> { [1].freeze.rotate!(42) }.should raise_error(frozen_error_class)
- -> { [].freeze.rotate! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { [1, 2, 3].freeze.rotate!(0) }.should raise_error(FrozenError)
+ -> { [1].freeze.rotate!(42) }.should raise_error(FrozenError)
+ -> { [].freeze.rotate! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/sample_spec.rb b/spec/ruby/core/array/sample_spec.rb
index 44be91ba18..565d7ff7f9 100644
--- a/spec/ruby/core/array/sample_spec.rb
+++ b/spec/ruby/core/array/sample_spec.rb
@@ -65,28 +65,11 @@ describe "Array#sample" do
end
describe "with options" do
- it "calls #to_hash to convert the passed Object" do
- obj = mock("array_sample")
- obj.should_receive(:to_hash).and_return({})
- obj.should_not_receive(:to_int)
-
- [1, 2].sample(obj).should be_an_instance_of(Fixnum)
- end
-
- it "calls #to_int on the first argument and #to_hash on the second when passed Objects" do
- count = mock("array_sample_count")
- count.should_receive(:to_int).and_return(2)
- options = mock("array_sample_options")
- options.should_receive(:to_hash).and_return({})
-
- [1, 2].sample(count, options).size.should == 2
- end
-
it "calls #rand on the Object passed by the :random key in the arguments Hash" do
obj = mock("array_sample_random")
obj.should_receive(:rand).and_return(0.5)
- [1, 2].sample(random: obj).should be_an_instance_of(Fixnum)
+ [1, 2].sample(random: obj).should be_an_instance_of(Integer)
end
it "raises a NoMethodError if an object passed for the RNG does not define #rand" do
@@ -95,8 +78,8 @@ describe "Array#sample" do
-> { [1, 2].sample(random: obj) }.should raise_error(NoMethodError)
end
- describe "when the object returned by #rand is a Fixnum" do
- it "uses the fixnum as index" do
+ describe "when the object returned by #rand is an Integer" do
+ it "uses the integer as index" do
random = mock("array_sample_random_ret")
random.should_receive(:rand).and_return(0)
@@ -124,7 +107,7 @@ describe "Array#sample" do
end
end
- describe "when the object returned by #rand is not a Fixnum but responds to #to_int" do
+ describe "when the object returned by #rand is not an Integer but responds to #to_int" do
it "calls #to_int on the Object" do
value = mock("array_sample_random_value")
value.should_receive(:to_int).and_return(1)
diff --git a/spec/ruby/core/array/shared/clone.rb b/spec/ruby/core/array/shared/clone.rb
index f6f581b17c..3c17b1f10f 100644
--- a/spec/ruby/core/array/shared/clone.rb
+++ b/spec/ruby/core/array/shared/clone.rb
@@ -26,8 +26,8 @@ describe :array_clone, shared: true do
aa = a.send @method
bb = b.send @method
- aa.tainted?.should == true
- bb.tainted?.should == false
+ aa.should.tainted?
+ bb.should_not.tainted?
end
it "copies untrusted status from the original" do
@@ -37,8 +37,8 @@ describe :array_clone, shared: true do
aa = a.send @method
bb = b.send @method
- aa.untrusted?.should == true
- bb.untrusted?.should == false
+ aa.should.untrusted?
+ bb.should_not.untrusted?
end
end
end
diff --git a/spec/ruby/core/array/shared/collect.rb b/spec/ruby/core/array/shared/collect.rb
index cbe32d2ab4..d84432734a 100644
--- a/spec/ruby/core/array/shared/collect.rb
+++ b/spec/ruby/core/array/shared/collect.rb
@@ -114,22 +114,22 @@ describe :array_collect_b, shared: true do
end
describe "when frozen" do
- it "raises a #{frozen_error_class}" do
- -> { ArraySpecs.frozen_array.send(@method) {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError" do
+ -> { ArraySpecs.frozen_array.send(@method) {} }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} when empty" do
- -> { ArraySpecs.empty_frozen_array.send(@method) {} }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when empty" do
+ -> { ArraySpecs.empty_frozen_array.send(@method) {} }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} when calling #each on the returned Enumerator" do
+ it "raises a FrozenError when calling #each on the returned Enumerator" do
enumerator = ArraySpecs.frozen_array.send(@method)
- -> { enumerator.each {|x| x } }.should raise_error(frozen_error_class)
+ -> { enumerator.each {|x| x } }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} when calling #each on the returned Enumerator when empty" do
+ it "raises a FrozenError when calling #each on the returned Enumerator when empty" do
enumerator = ArraySpecs.empty_frozen_array.send(@method)
- -> { enumerator.each {|x| x } }.should raise_error(frozen_error_class)
+ -> { enumerator.each {|x| x } }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/shared/intersection.rb b/spec/ruby/core/array/shared/intersection.rb
new file mode 100644
index 0000000000..49849b08c2
--- /dev/null
+++ b/spec/ruby/core/array/shared/intersection.rb
@@ -0,0 +1,84 @@
+describe :array_intersection, shared: true do
+ it "creates an array with elements common to both arrays (intersection)" do
+ [].send(@method, []).should == []
+ [1, 2].send(@method, []).should == []
+ [].send(@method, [1, 2]).should == []
+ [ 1, 3, 5 ].send(@method, [ 1, 2, 3 ]).should == [1, 3]
+ end
+
+ it "creates an array with no duplicates" do
+ [ 1, 1, 3, 5 ].send(@method, [ 1, 2, 3 ]).uniq!.should == nil
+ end
+
+ it "creates an array with elements in order they are first encountered" do
+ [ 1, 2, 3, 2, 5 ].send(@method, [ 5, 2, 3, 4 ]).should == [2, 3, 5]
+ end
+
+ it "does not modify the original Array" do
+ a = [1, 1, 3, 5]
+ a.send(@method, [1, 2, 3]).should == [1, 3]
+ a.should == [1, 1, 3, 5]
+ end
+
+ it "properly handles recursive arrays" do
+ empty = ArraySpecs.empty_recursive_array
+ empty.send(@method, empty).should == empty
+
+ ArraySpecs.recursive_array.send(@method, []).should == []
+ [].send(@method, ArraySpecs.recursive_array).should == []
+
+ ArraySpecs.recursive_array.send(@method, ArraySpecs.recursive_array).should == [1, 'two', 3.0, ArraySpecs.recursive_array]
+ end
+
+ it "tries to convert the passed argument to an Array using #to_ary" do
+ obj = mock('[1,2,3]')
+ obj.should_receive(:to_ary).and_return([1, 2, 3])
+ [1, 2].send(@method, obj).should == ([1, 2])
+ end
+
+ it "determines equivalence between elements in the sense of eql?" do
+ not_supported_on :opal do
+ [5.0, 4.0].send(@method, [5, 4]).should == []
+ end
+
+ str = "x"
+ [str].send(@method, [str.dup]).should == [str]
+
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.should_receive(:eql?).at_least(1).and_return(true)
+ obj2.stub!(:eql?).and_return(true)
+
+ [obj1].send(@method, [obj2]).should == [obj1]
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj1]
+
+ obj1 = mock('3')
+ obj2 = mock('4')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.should_receive(:eql?).at_least(1).and_return(false)
+
+ [obj1].send(@method, [obj2]).should == []
+ [obj1, obj1, obj2, obj2].send(@method, [obj2]).should == [obj2]
+ end
+
+ it "does return subclass instances for Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].send(@method, []).should be_an_instance_of(Array)
+ ArraySpecs::MyArray[1, 2, 3].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
+ [].send(@method, ArraySpecs::MyArray[1, 2, 3]).should be_an_instance_of(Array)
+ end
+
+ it "does not call to_ary on array subclasses" do
+ [5, 6].send(@method, ArraySpecs::ToAryArray[1, 2, 5, 6]).should == [5, 6]
+ end
+
+ it "properly handles an identical item even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.stub!(:hash).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ [x].send(@method, [x]).should == [x]
+ end
+end
diff --git a/spec/ruby/core/array/shared/join.rb b/spec/ruby/core/array/shared/join.rb
index 5e7193de8a..c443d9a628 100644
--- a/spec/ruby/core/array/shared/join.rb
+++ b/spec/ruby/core/array/shared/join.rb
@@ -113,6 +113,20 @@ describe :array_join_with_default_separator, shared: true do
-> { ary_utf8_bad_binary.send(@method) }.should raise_error(EncodingError)
end
+
+ ruby_version_is "2.7" do
+ context "when $, is not nil" do
+ before do
+ suppress_warning do
+ $, = '*'
+ end
+ end
+
+ it "warns" do
+ -> { [].join }.should complain(/warning: \$, is set to non-nil value/)
+ end
+ end
+ end
end
describe :array_join_with_string_separator, shared: true do
diff --git a/spec/ruby/core/array/shared/keep_if.rb b/spec/ruby/core/array/shared/keep_if.rb
index 2f1299c2b3..f26aff028c 100644
--- a/spec/ruby/core/array/shared/keep_if.rb
+++ b/spec/ruby/core/array/shared/keep_if.rb
@@ -41,8 +41,8 @@ describe :keep_if, shared: true do
@frozen.should == @origin
end
- it "raises a #{frozen_error_class}" do
- -> { @frozen.send(@method) { true } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError" do
+ -> { @frozen.send(@method) { true } }.should raise_error(FrozenError)
end
end
@@ -52,8 +52,8 @@ describe :keep_if, shared: true do
@frozen.should == @origin
end
- it "raises a #{frozen_error_class}" do
- -> { @frozen.send(@method) { false } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError" do
+ -> { @frozen.send(@method) { false } }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/array/shared/push.rb b/spec/ruby/core/array/shared/push.rb
index df307073cd..ac790fb6a4 100644
--- a/spec/ruby/core/array/shared/push.rb
+++ b/spec/ruby/core/array/shared/push.rb
@@ -26,8 +26,8 @@ describe :array_push, shared: true do
array.send(@method, :last).should == [1, 'two', 3.0, array, array, array, array, array, :last]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(frozen_error_class)
- -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(FrozenError)
+ -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/shared/replace.rb b/spec/ruby/core/array/shared/replace.rb
index b3474fad09..9a6e60c1b0 100644
--- a/spec/ruby/core/array/shared/replace.rb
+++ b/spec/ruby/core/array/shared/replace.rb
@@ -52,9 +52,9 @@ describe :array_replace, shared: true do
[].send(@method, ArraySpecs::ToAryArray[5, 6, 7]).should == [5, 6, 7]
end
- it "raises a #{frozen_error_class} on a frozen array" do
+ it "raises a FrozenError on a frozen array" do
-> {
ArraySpecs.frozen_array.send(@method, ArraySpecs.frozen_array)
- }.should raise_error(frozen_error_class)
+ }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/shared/slice.rb b/spec/ruby/core/array/shared/slice.rb
index 1e7fdf934a..820047cdb2 100644
--- a/spec/ruby/core/array/shared/slice.rb
+++ b/spec/ruby/core/array/shared/slice.rb
@@ -397,28 +397,56 @@ describe :array_slice, shared: true do
@array = ArraySpecs::MyArray[1, 2, 3, 4, 5]
end
- it "returns a subclass instance with [n, m]" do
- @array.send(@method, 0, 2).should be_an_instance_of(ArraySpecs::MyArray)
+ ruby_version_is ''...'3.0' do
+ it "returns a subclass instance with [n, m]" do
+ @array.send(@method, 0, 2).should be_an_instance_of(ArraySpecs::MyArray)
+ end
+
+ it "returns a subclass instance with [-n, m]" do
+ @array.send(@method, -3, 2).should be_an_instance_of(ArraySpecs::MyArray)
+ end
+
+ it "returns a subclass instance with [n..m]" do
+ @array.send(@method, 1..3).should be_an_instance_of(ArraySpecs::MyArray)
+ end
+
+ it "returns a subclass instance with [n...m]" do
+ @array.send(@method, 1...3).should be_an_instance_of(ArraySpecs::MyArray)
+ end
+
+ it "returns a subclass instance with [-n..-m]" do
+ @array.send(@method, -3..-1).should be_an_instance_of(ArraySpecs::MyArray)
+ end
+
+ it "returns a subclass instance with [-n...-m]" do
+ @array.send(@method, -3...-1).should be_an_instance_of(ArraySpecs::MyArray)
+ end
end
- it "returns a subclass instance with [-n, m]" do
- @array.send(@method, -3, 2).should be_an_instance_of(ArraySpecs::MyArray)
- end
+ ruby_version_is '3.0' do
+ it "returns a Array instance with [n, m]" do
+ @array.send(@method, 0, 2).should be_an_instance_of(Array)
+ end
- it "returns a subclass instance with [n..m]" do
- @array.send(@method, 1..3).should be_an_instance_of(ArraySpecs::MyArray)
- end
+ it "returns a Array instance with [-n, m]" do
+ @array.send(@method, -3, 2).should be_an_instance_of(Array)
+ end
- it "returns a subclass instance with [n...m]" do
- @array.send(@method, 1...3).should be_an_instance_of(ArraySpecs::MyArray)
- end
+ it "returns a Array instance with [n..m]" do
+ @array.send(@method, 1..3).should be_an_instance_of(Array)
+ end
- it "returns a subclass instance with [-n..-m]" do
- @array.send(@method, -3..-1).should be_an_instance_of(ArraySpecs::MyArray)
- end
+ it "returns a Array instance with [n...m]" do
+ @array.send(@method, 1...3).should be_an_instance_of(Array)
+ end
+
+ it "returns a Array instance with [-n..-m]" do
+ @array.send(@method, -3..-1).should be_an_instance_of(Array)
+ end
- it "returns a subclass instance with [-n...-m]" do
- @array.send(@method, -3...-1).should be_an_instance_of(ArraySpecs::MyArray)
+ it "returns a Array instance with [-n...-m]" do
+ @array.send(@method, -3...-1).should be_an_instance_of(Array)
+ end
end
it "returns an empty array when m == n with [m...n]" do
@@ -458,23 +486,38 @@ describe :array_slice, shared: true do
end
end
- it "raises a RangeError when the start index is out of range of Fixnum" do
+ it "raises a RangeError when the start index is out of range of Integer" do
array = [1, 2, 3, 4, 5, 6]
obj = mock('large value')
- obj.should_receive(:to_int).and_return(0x8000_0000_0000_0000_0000)
+ obj.should_receive(:to_int).and_return(bignum_value)
-> { array.send(@method, obj) }.should raise_error(RangeError)
obj = 8e19
-> { array.send(@method, obj) }.should raise_error(RangeError)
+
+ # boundary value when longs are 64 bits
+ -> { array.send(@method, 2.0**63) }.should raise_error(RangeError)
+
+ # just under the boundary value when longs are 64 bits
+ array.send(@method, max_long.to_f.prev_float).should == nil
end
- it "raises a RangeError when the length is out of range of Fixnum" do
+ it "raises a RangeError when the length is out of range of Integer" do
array = [1, 2, 3, 4, 5, 6]
obj = mock('large value')
- obj.should_receive(:to_int).and_return(0x8000_0000_0000_0000_0000)
+ obj.should_receive(:to_int).and_return(bignum_value)
-> { array.send(@method, 1, obj) }.should raise_error(RangeError)
obj = 8e19
-> { array.send(@method, 1, obj) }.should raise_error(RangeError)
end
+
+ it "raises a type error if a range is passed with a length" do
+ ->{ [1, 2, 3].send(@method, 1..2, 1) }.should raise_error(TypeError)
+ end
+
+ it "raises a RangeError if passed a range with a bound that is too large" do
+ -> { "hello".send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError)
+ -> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError)
+ end
end
diff --git a/spec/ruby/core/array/shared/union.rb b/spec/ruby/core/array/shared/union.rb
index 12a98cc9fe..0b60df9ca4 100644
--- a/spec/ruby/core/array/shared/union.rb
+++ b/spec/ruby/core/array/shared/union.rb
@@ -31,7 +31,7 @@ describe :array_binary_union, shared: true do
[0].send(@method, obj).should == ([0] | [1, 2, 3])
end
- # MRI follows hashing semantics here, so doesn't actually call eql?/hash for Fixnum/Symbol
+ # MRI follows hashing semantics here, so doesn't actually call eql?/hash for Integer/Symbol
it "acts as if using an intermediate hash to collect values" do
not_supported_on :opal do
[5.0, 4.0].send(@method, [5, 4]).should == [5.0, 4.0, 5, 4]
diff --git a/spec/ruby/core/array/shared/unshift.rb b/spec/ruby/core/array/shared/unshift.rb
index be62084e95..fc82e19e2a 100644
--- a/spec/ruby/core/array/shared/unshift.rb
+++ b/spec/ruby/core/array/shared/unshift.rb
@@ -35,12 +35,12 @@ describe :array_unshift, shared: true do
array[0..5].should == [:new, 1, 'two', 3.0, array, array]
end
- it "raises a #{frozen_error_class} on a frozen array when the array is modified" do
- -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array when the array is modified" do
+ -> { ArraySpecs.frozen_array.send(@method, 1) }.should raise_error(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on a frozen array when the array would not be modified" do
- -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array when the array would not be modified" do
+ -> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/shift_spec.rb b/spec/ruby/core/array/shift_spec.rb
index 13f1abbbfe..b998e45d28 100644
--- a/spec/ruby/core/array/shift_spec.rb
+++ b/spec/ruby/core/array/shift_spec.rb
@@ -30,11 +30,11 @@ describe "Array#shift" do
array[0..2].should == ['two', 3.0, array]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.shift }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.shift }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.shift }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.shift }.should raise_error(FrozenError)
end
describe "passed a number n as an argument" do
diff --git a/spec/ruby/core/array/shuffle_spec.rb b/spec/ruby/core/array/shuffle_spec.rb
index 7a2fed7d50..b255147c75 100644
--- a/spec/ruby/core/array/shuffle_spec.rb
+++ b/spec/ruby/core/array/shuffle_spec.rb
@@ -25,12 +25,6 @@ describe "Array#shuffle" do
ArraySpecs::MyArray[1, 2, 3].shuffle.should be_an_instance_of(Array)
end
- it "attempts coercion via #to_hash" do
- obj = mock('hash')
- obj.should_receive(:to_hash).once.and_return({})
- [2, 3].shuffle(obj)
- end
-
it "calls #rand on the Object passed by the :random key in the arguments Hash" do
obj = mock("array_shuffle_random")
obj.should_receive(:rand).at_least(1).times.and_return(0.5)
@@ -95,8 +89,8 @@ describe "Array#shuffle!" do
a.should equal(original)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.shuffle! }.should raise_error(frozen_error_class)
- -> { ArraySpecs.empty_frozen_array.shuffle! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.shuffle! }.should raise_error(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.shuffle! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/array/slice_spec.rb b/spec/ruby/core/array/slice_spec.rb
index 16220bdf0d..3829794938 100644
--- a/spec/ruby/core/array/slice_spec.rb
+++ b/spec/ruby/core/array/slice_spec.rb
@@ -150,8 +150,20 @@ describe "Array#slice!" do
a.should == [1, 2]
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.slice!(0, 0) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.slice!(0, 0) }.should raise_error(FrozenError)
+ end
+
+ ruby_version_is "2.6" do
+ it "works with endless ranges" do
+ a = [1, 2, 3]
+ a.slice!(eval("(1..)")).should == [2, 3]
+ a.should == [1]
+
+ a = [1, 2, 3]
+ a.slice!(eval("(2...)")).should == [3]
+ a.should == [1, 2]
+ end
end
end
diff --git a/spec/ruby/core/array/sort_by_spec.rb b/spec/ruby/core/array/sort_by_spec.rb
index 045051d307..7cea6ec6d3 100644
--- a/spec/ruby/core/array/sort_by_spec.rb
+++ b/spec/ruby/core/array/sort_by_spec.rb
@@ -23,12 +23,12 @@ describe "Array#sort_by!" do
a.should be_an_instance_of(Array)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.sort_by! {}}.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.sort_by! {}}.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} on an empty frozen array" do
- -> { ArraySpecs.empty_frozen_array.sort_by! {}}.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty frozen array" do
+ -> { ArraySpecs.empty_frozen_array.sort_by! {}}.should raise_error(FrozenError)
end
it "returns the specified value when it would break in the given block" do
diff --git a/spec/ruby/core/array/sort_spec.rb b/spec/ruby/core/array/sort_spec.rb
index 6b84a82a48..e20b650516 100644
--- a/spec/ruby/core/array/sort_spec.rb
+++ b/spec/ruby/core/array/sort_spec.rb
@@ -58,9 +58,9 @@ describe "Array#sort" do
b = ArraySpecs::MockForCompared.new
c = ArraySpecs::MockForCompared.new
- ArraySpecs::MockForCompared.compared?.should == false
+ ArraySpecs::MockForCompared.should_not.compared?
[a, b, c].sort.should == [c, b, a]
- ArraySpecs::MockForCompared.compared?.should == true
+ ArraySpecs::MockForCompared.should.compared?
end
it "does not deal with exceptions raised by unimplemented or incorrect #<=>" do
@@ -104,17 +104,17 @@ describe "Array#sort" do
it "does not freezes self during being sorted" do
a = [1, 2, 3]
- a.sort { |x,y| a.frozen?.should == false; x <=> y }
+ a.sort { |x,y| a.should_not.frozen?; x <=> y }
end
it "returns the specified value when it would break in the given block" do
[1, 2, 3].sort{ break :a }.should == :a
end
- it "uses the sign of Bignum block results as the sort result" do
+ it "uses the sign of Integer block results as the sort result" do
a = [1, 2, 5, 10, 7, -4, 12]
begin
- class Bignum;
+ class Integer
alias old_spaceship <=>
def <=>(other)
raise
@@ -122,7 +122,7 @@ describe "Array#sort" do
end
a.sort {|n, m| (n - m) * (2 ** 200)}.should == [-4, 1, 2, 5, 7, 10, 12]
ensure
- class Bignum
+ class Integer
alias <=> old_spaceship
end
end
@@ -132,7 +132,7 @@ describe "Array#sort" do
a = [1, 2, 5, 10, 7, -4, 12]
a.sort { |n, m| n - m }.should == [-4, 1, 2, 5, 7, 10, 12]
a.sort { |n, m|
- ArraySpecs::ComparableWithFixnum.new(n-m)
+ ArraySpecs::ComparableWithInteger.new(n-m)
}.should == [-4, 1, 2, 5, 7, 10, 12]
-> {
a.sort { |n, m| (n - m).to_s }
@@ -207,9 +207,9 @@ describe "Array#sort!" do
b = ArraySpecs::MockForCompared.new
c = ArraySpecs::MockForCompared.new
- ArraySpecs::MockForCompared.compared?.should == false
+ ArraySpecs::MockForCompared.should_not.compared?
[a, b, c].sort!.should == [c, b, a]
- ArraySpecs::MockForCompared.compared?.should == true
+ ArraySpecs::MockForCompared.should.compared?
end
it "does not call #<=> on contained objects when invoked with a block" do
@@ -233,8 +233,8 @@ describe "Array#sort!" do
a.sort!{ -1 }.should be_an_instance_of(Array)
end
- it "raises a #{frozen_error_class} on a frozen array" do
- -> { ArraySpecs.frozen_array.sort! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array" do
+ -> { ArraySpecs.frozen_array.sort! }.should raise_error(FrozenError)
end
it "returns the specified value when it would break in the given block" do
diff --git a/spec/ruby/core/array/uniq_spec.rb b/spec/ruby/core/array/uniq_spec.rb
index 4b56f3c841..5911c23e6a 100644
--- a/spec/ruby/core/array/uniq_spec.rb
+++ b/spec/ruby/core/array/uniq_spec.rb
@@ -87,8 +87,8 @@ describe "Array#uniq" do
end
a.uniq.should == a
- a[0].tainted?.should == true
- a[1].tainted?.should == true
+ a[0].should.tainted?
+ a[1].should.tainted?
a = Array.new(2) do
obj = mock('0')
@@ -106,8 +106,8 @@ describe "Array#uniq" do
end
a.uniq.size.should == 1
- a[0].tainted?.should == true
- a[1].tainted?.should == true
+ a[0].should.tainted?
+ a[1].should.tainted?
end
end
@@ -128,8 +128,16 @@ describe "Array#uniq" do
[false, nil, 42].uniq { :bar }.should == [false]
end
- it "returns subclass instance on Array subclasses" do
- ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(ArraySpecs::MyArray)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instance on Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(ArraySpecs::MyArray)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns Array instance on Array subclasses" do
+ ArraySpecs::MyArray[1, 2, 3].uniq.should be_an_instance_of(Array)
+ end
end
it "properly handles an identical item even when its #eql? isn't reflexive" do
@@ -220,20 +228,20 @@ describe "Array#uniq!" do
[ "a", "b", "c" ].uniq!.should == nil
end
- it "raises a #{frozen_error_class} on a frozen array when the array is modified" do
+ it "raises a FrozenError on a frozen array when the array is modified" do
dup_ary = [1, 1, 2]
dup_ary.freeze
- -> { dup_ary.uniq! }.should raise_error(frozen_error_class)
+ -> { dup_ary.uniq! }.should raise_error(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on a frozen array when the array would not be modified" do
- -> { ArraySpecs.frozen_array.uniq!}.should raise_error(frozen_error_class)
- -> { ArraySpecs.empty_frozen_array.uniq!}.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen array when the array would not be modified" do
+ -> { ArraySpecs.frozen_array.uniq!}.should raise_error(FrozenError)
+ -> { ArraySpecs.empty_frozen_array.uniq!}.should raise_error(FrozenError)
end
it "doesn't yield to the block on a frozen array" do
- -> { ArraySpecs.frozen_array.uniq!{ raise RangeError, "shouldn't yield"}}.should raise_error(frozen_error_class)
+ -> { ArraySpecs.frozen_array.uniq!{ raise RangeError, "shouldn't yield"}}.should raise_error(FrozenError)
end
it "compares elements based on the value returned from the block" do
diff --git a/spec/ruby/core/array/values_at_spec.rb b/spec/ruby/core/array/values_at_spec.rb
index 13860150bb..f6801335f8 100644
--- a/spec/ruby/core/array/values_at_spec.rb
+++ b/spec/ruby/core/array/values_at_spec.rb
@@ -60,4 +60,11 @@ describe "Array#values_at" do
it "does not return subclass instance on Array subclasses" do
ArraySpecs::MyArray[1, 2, 3].values_at(0, 1..2, 1).should be_an_instance_of(Array)
end
+
+ ruby_version_is "2.6" do
+ it "works when given endless ranges" do
+ [1, 2, 3, 4].values_at(eval("(1..)")).should == [2, 3, 4]
+ [1, 2, 3, 4].values_at(eval("(3...)")).should == [4]
+ end
+ end
end
diff --git a/spec/ruby/core/basicobject/instance_eval_spec.rb b/spec/ruby/core/basicobject/instance_eval_spec.rb
index d3dd05b745..b6a146095d 100644
--- a/spec/ruby/core/basicobject/instance_eval_spec.rb
+++ b/spec/ruby/core/basicobject/instance_eval_spec.rb
@@ -131,14 +131,14 @@ describe "BasicObject#instance_eval" do
end
quarantine! do # Not clean, leaves cvars lying around to break other specs
- it "scopes class var accesses in the caller when called on a Fixnum" do
- # Fixnum can take instance vars
- Fixnum.class_eval "@@__tmp_instance_eval_spec = 1"
+ it "scopes class var accesses in the caller when called on an Integer" do
+ # Integer can take instance vars
+ Integer.class_eval "@@__tmp_instance_eval_spec = 1"
(defined? @@__tmp_instance_eval_spec).should be_nil
@@__tmp_instance_eval_spec = 2
1.instance_eval { @@__tmp_instance_eval_spec }.should == 2
- Fixnum.__send__(:remove_class_variable, :@@__tmp_instance_eval_spec)
+ Integer.__send__(:remove_class_variable, :@@__tmp_instance_eval_spec)
end
end
diff --git a/spec/ruby/core/basicobject/instance_exec_spec.rb b/spec/ruby/core/basicobject/instance_exec_spec.rb
index e25482d58a..289fdd889b 100644
--- a/spec/ruby/core/basicobject/instance_exec_spec.rb
+++ b/spec/ruby/core/basicobject/instance_exec_spec.rb
@@ -85,14 +85,14 @@ describe "BasicObject#instance_exec" do
end
quarantine! do # Not clean, leaves cvars lying around to break other specs
- it "scopes class var accesses in the caller when called on a Fixnum" do
- # Fixnum can take instance vars
- Fixnum.class_eval "@@__tmp_instance_exec_spec = 1"
+ it "scopes class var accesses in the caller when called on an Integer" do
+ # Integer can take instance vars
+ Integer.class_eval "@@__tmp_instance_exec_spec = 1"
(defined? @@__tmp_instance_exec_spec).should == nil
@@__tmp_instance_exec_spec = 2
1.instance_exec { @@__tmp_instance_exec_spec }.should == 2
- Fixnum.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec)
+ Integer.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec)
end
end
diff --git a/spec/ruby/core/binding/eval_spec.rb b/spec/ruby/core/binding/eval_spec.rb
index fff8c9cf44..b36bec799e 100644
--- a/spec/ruby/core/binding/eval_spec.rb
+++ b/spec/ruby/core/binding/eval_spec.rb
@@ -23,29 +23,58 @@ describe "Binding#eval" do
bind2.local_variables.should == []
end
- it "inherits __LINE__ from the enclosing scope" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- suppress_warning {bind.eval("__LINE__")}.should == obj.get_line_of_binding
- end
+ ruby_version_is ""..."3.0" do
+ it "inherits __LINE__ from the enclosing scope" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ suppress_warning {bind.eval("__LINE__")}.should == obj.get_line_of_binding
+ end
- it "preserves __LINE__ across multiple calls to eval" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- suppress_warning {bind.eval("__LINE__")}.should == obj.get_line_of_binding
- suppress_warning {bind.eval("__LINE__")}.should == obj.get_line_of_binding
- end
+ it "preserves __LINE__ across multiple calls to eval" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ suppress_warning {bind.eval("__LINE__")}.should == obj.get_line_of_binding
+ suppress_warning {bind.eval("__LINE__")}.should == obj.get_line_of_binding
+ end
- it "increments __LINE__ on each line of a multiline eval" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- suppress_warning {bind.eval("#foo\n__LINE__")}.should == obj.get_line_of_binding + 1
+ it "increments __LINE__ on each line of a multiline eval" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ suppress_warning {bind.eval("#foo\n__LINE__")}.should == obj.get_line_of_binding + 1
+ end
+
+ it "inherits __LINE__ from the enclosing scope even if the Binding is created with #send" do
+ obj = BindingSpecs::Demo.new(1)
+ bind, line = obj.get_binding_with_send_and_line
+ suppress_warning {bind.eval("__LINE__")}.should == line
+ end
end
- it "inherits __LINE__ from the enclosing scope even if the Binding is created with #send" do
- obj = BindingSpecs::Demo.new(1)
- bind, line = obj.get_binding_with_send_and_line
- suppress_warning {bind.eval("__LINE__")}.should == line
+ ruby_version_is "3.0" do
+ it "starts with line 1 if single argument is given" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("__LINE__").should == 1
+ end
+
+ it "preserves __LINE__ across multiple calls to eval" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("__LINE__").should == 1
+ bind.eval("__LINE__").should == 1
+ end
+
+ it "increments __LINE__ on each line of a multiline eval" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("#foo\n__LINE__").should == 2
+ end
+
+ it "starts with line 1 if the Binding is created with #send" do
+ obj = BindingSpecs::Demo.new(1)
+ bind, line = obj.get_binding_with_send_and_line
+ bind.eval("__LINE__").should == 1
+ end
end
it "starts with a __LINE__ of 1 if a filename is passed" do
@@ -60,10 +89,20 @@ describe "Binding#eval" do
bind.eval("#foo\n__LINE__", "(test)", 88).should == 89
end
- it "inherits __FILE__ from the enclosing scope" do
- obj = BindingSpecs::Demo.new(1)
- bind = obj.get_binding
- suppress_warning {bind.eval("__FILE__")}.should == obj.get_file_of_binding
+ ruby_version_is ""..."3.0" do
+ it "inherits __FILE__ from the enclosing scope" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ suppress_warning {bind.eval("__FILE__")}.should == obj.get_file_of_binding
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "Uses (eval) as __FILE__ if single argument given" do
+ obj = BindingSpecs::Demo.new(1)
+ bind = obj.get_binding
+ bind.eval("__FILE__").should == '(eval)'
+ end
end
it "uses the __FILE__ that is passed in" do
@@ -92,4 +131,10 @@ describe "Binding#eval" do
bind, meth = obj.get_binding_with_send_and_method
bind.eval("__method__").should == meth
end
+
+ it "reflects refinements activated in the binding scope" do
+ bind = BindingSpecs::Refined.refined_binding
+
+ bind.eval("'bar'.foo").should == "foo"
+ end
end
diff --git a/spec/ruby/core/binding/fixtures/classes.rb b/spec/ruby/core/binding/fixtures/classes.rb
index 43e32cacf6..b5f3ce9008 100644
--- a/spec/ruby/core/binding/fixtures/classes.rb
+++ b/spec/ruby/core/binding/fixtures/classes.rb
@@ -49,4 +49,18 @@ module BindingSpecs
end
end
end
+
+ module AddFooToString
+ refine(String) do
+ def foo
+ "foo"
+ end
+ end
+ end
+ class Refined
+ using AddFooToString
+ def self.refined_binding
+ binding
+ end
+ end
end
diff --git a/spec/ruby/core/binding/irb_spec.rb b/spec/ruby/core/binding/irb_spec.rb
index bd37b419f9..b3bc274f78 100644
--- a/spec/ruby/core/binding/irb_spec.rb
+++ b/spec/ruby/core/binding/irb_spec.rb
@@ -1,18 +1,16 @@
require_relative '../../spec_helper'
-ruby_version_is "2.5" do
- describe "Binding#irb" do
- it "creates an IRB session with the binding in scope" do
- irb_fixture = fixture __FILE__, "irb.rb"
- irbrc_fixture = fixture __FILE__, "irbrc"
+describe "Binding#irb" do
+ it "creates an IRB session with the binding in scope" do
+ irb_fixture = fixture __FILE__, "irb.rb"
+ irbrc_fixture = fixture __FILE__, "irbrc"
- out = IO.popen([{"IRBRC"=>irbrc_fixture}, *ruby_exe, irb_fixture], "r+") do |pipe|
- pipe.puts "a ** 2"
- pipe.puts "exit"
- pipe.readlines.map(&:chomp)
- end
-
- out[-3..-1].should == ["a ** 2", "100", "exit"]
+ out = IO.popen([{"IRBRC"=>irbrc_fixture}, *ruby_exe, irb_fixture], "r+") do |pipe|
+ pipe.puts "a ** 2"
+ pipe.puts "exit"
+ pipe.readlines.map(&:chomp)
end
+
+ out[-3..-1].should == ["a ** 2", "100", "exit"]
end
end
diff --git a/spec/ruby/core/builtin_constants/builtin_constants_spec.rb b/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
index a5141c3008..7c87a970d7 100644
--- a/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
+++ b/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
@@ -7,8 +7,8 @@ describe "RUBY_VERSION" do
end
describe "RUBY_PATCHLEVEL" do
- it "is a Fixnum" do
- RUBY_PATCHLEVEL.should be_kind_of(Fixnum)
+ it "is an Integer" do
+ RUBY_PATCHLEVEL.should be_kind_of(Integer)
end
end
@@ -34,6 +34,12 @@ describe "RUBY_PLATFORM" do
it "is a String" do
RUBY_PLATFORM.should be_kind_of(String)
end
+
+ platform_is :darwin do
+ it 'ends with the build time kernel major version on darwin' do
+ RUBY_PLATFORM.should =~ /-darwin\d+$/
+ end
+ end
end
describe "RUBY_RELEASE_DATE" do
@@ -45,7 +51,7 @@ end
describe "RUBY_REVISION" do
ruby_version_is ""..."2.7" do
it "is an Integer" do
- RUBY_REVISION.should be_kind_of(Fixnum)
+ RUBY_REVISION.should be_kind_of(Integer)
end
end
diff --git a/spec/ruby/core/class/allocate_spec.rb b/spec/ruby/core/class/allocate_spec.rb
index c426c38ff9..b39622e06a 100644
--- a/spec/ruby/core/class/allocate_spec.rb
+++ b/spec/ruby/core/class/allocate_spec.rb
@@ -30,7 +30,7 @@ describe "Class#allocate" do
end
end
- klass.allocate.initialized?.should == false
+ klass.allocate.should_not.initialized?
end
it "raises TypeError for #superclass" do
diff --git a/spec/ruby/core/class/initialize_spec.rb b/spec/ruby/core/class/initialize_spec.rb
index 9678d7b373..6348758485 100644
--- a/spec/ruby/core/class/initialize_spec.rb
+++ b/spec/ruby/core/class/initialize_spec.rb
@@ -7,7 +7,7 @@ describe "Class#initialize" do
it "raises a TypeError when called on already initialized classes" do
->{
- Fixnum.send :initialize
+ Integer.send :initialize
}.should raise_error(TypeError)
->{
diff --git a/spec/ruby/core/class/new_spec.rb b/spec/ruby/core/class/new_spec.rb
index 8191ce6a37..93152a83ee 100644
--- a/spec/ruby/core/class/new_spec.rb
+++ b/spec/ruby/core/class/new_spec.rb
@@ -95,12 +95,13 @@ describe "Class.new" do
end
it "raises a TypeError when given a non-Class" do
- error_msg = /superclass must be a Class/
- -> { Class.new("") }.should raise_error(TypeError, error_msg)
- -> { Class.new(1) }.should raise_error(TypeError, error_msg)
- -> { Class.new(:symbol) }.should raise_error(TypeError, error_msg)
- -> { Class.new(mock('o')) }.should raise_error(TypeError, error_msg)
- -> { Class.new(Module.new) }.should raise_error(TypeError, error_msg)
+ error_msg = /superclass must be a.*Class/
+ -> { Class.new("") }.should raise_error(TypeError, error_msg)
+ -> { Class.new(1) }.should raise_error(TypeError, error_msg)
+ -> { Class.new(:symbol) }.should raise_error(TypeError, error_msg)
+ -> { Class.new(mock('o')) }.should raise_error(TypeError, error_msg)
+ -> { Class.new(Module.new) }.should raise_error(TypeError, error_msg)
+ -> { Class.new(BasicObject.new) }.should raise_error(TypeError, error_msg)
end
end
@@ -126,7 +127,7 @@ describe "Class#new" do
end
end
- klass.new.initialized?.should == true
+ klass.new.should.initialized?
klass.new(1, 2, 3).args.should == [1, 2, 3]
end
diff --git a/spec/ruby/core/class/superclass_spec.rb b/spec/ruby/core/class/superclass_spec.rb
index deb5a45336..00579238a6 100644
--- a/spec/ruby/core/class/superclass_spec.rb
+++ b/spec/ruby/core/class/superclass_spec.rb
@@ -8,7 +8,7 @@ describe "Class#superclass" do
Class.superclass.should == Module
Class.new.superclass.should == Object
Class.new(String).superclass.should == String
- Class.new(Fixnum).superclass.should == Fixnum
+ Class.new(Integer).superclass.should == Integer
end
# redmine:567
diff --git a/spec/ruby/core/comparable/lt_spec.rb b/spec/ruby/core/comparable/lt_spec.rb
index 4db92719e2..bca95f8d25 100644
--- a/spec/ruby/core/comparable/lt_spec.rb
+++ b/spec/ruby/core/comparable/lt_spec.rb
@@ -40,4 +40,10 @@ describe "Comparable#<" do
a.should_receive(:<=>).any_number_of_times.and_return(nil)
-> { (a < b) }.should raise_error(ArgumentError)
end
+
+ it "raises an argument error with a message containing the value" do
+ -> { ("foo" < 7) }.should raise_error(ArgumentError) { |e|
+ e.message.should == "comparison of String with 7 failed"
+ }
+ end
end
diff --git a/spec/ruby/core/complex/coerce_spec.rb b/spec/ruby/core/complex/coerce_spec.rb
index a30a6c1d5f..9023234e73 100644
--- a/spec/ruby/core/complex/coerce_spec.rb
+++ b/spec/ruby/core/complex/coerce_spec.rb
@@ -19,7 +19,7 @@ describe "Complex#coerce" do
result.last.should be_kind_of(Complex)
end
- it "returns an array containing other and self as Complex when other is a Bignum" do
+ it "returns an array containing other and self as Complex when other is an Integer" do
result = @one.coerce(4294967296)
result.should == [4294967296, 1]
result.first.should be_kind_of(Complex)
diff --git a/spec/ruby/core/complex/comparision_spec.rb b/spec/ruby/core/complex/comparision_spec.rb
new file mode 100644
index 0000000000..2a437afb71
--- /dev/null
+++ b/spec/ruby/core/complex/comparision_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../spec_helper'
+
+describe "Complex#<=>" do
+ ruby_version_is "2.7" do
+ it "returns nil if either self or argument has imaginary part" do
+ (Complex(5, 1) <=> Complex(2)).should be_nil
+ (Complex(1) <=> Complex(2, 1)).should be_nil
+ (5 <=> Complex(2, 1)).should be_nil
+ end
+
+ it "returns nil if argument is not numeric" do
+ (Complex(5, 1) <=> "cmp").should be_nil
+ (Complex(1) <=> "cmp").should be_nil
+ (Complex(1) <=> Object.new).should be_nil
+ end
+
+ it "returns 0, 1, or -1 if self and argument do not have imaginary part" do
+ (Complex(5) <=> Complex(2)).should == 1
+ (Complex(2) <=> Complex(3)).should == -1
+ (Complex(2) <=> Complex(2)).should == 0
+
+ (Complex(5) <=> 2).should == 1
+ (Complex(2) <=> 3).should == -1
+ (Complex(2) <=> 2).should == 0
+ end
+ end
+end
diff --git a/spec/ruby/core/complex/equal_value_spec.rb b/spec/ruby/core/complex/equal_value_spec.rb
index b1e4f9cfcd..ad7236b1bd 100644
--- a/spec/ruby/core/complex/equal_value_spec.rb
+++ b/spec/ruby/core/complex/equal_value_spec.rb
@@ -53,7 +53,7 @@ describe "Complex#==" do
end
describe "with Object" do
- # Fixnum#==, Float#== and Bignum#== only return booleans - Bug?
+ # Integer#== and Float#== only return booleans - Bug?
it "calls other#== with self" do
value = Complex(3, 0)
diff --git a/spec/ruby/core/complex/exponent_spec.rb b/spec/ruby/core/complex/exponent_spec.rb
index bf07c90038..86f827aece 100644
--- a/spec/ruby/core/complex/exponent_spec.rb
+++ b/spec/ruby/core/complex/exponent_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Complex#**" do
- describe "with Fixnum 0" do
+ describe "with Integer 0" do
it "returns Complex(1)" do
(Complex(3, 4) ** 0).should eql(Complex(1))
end
diff --git a/spec/ruby/core/complex/finite_spec.rb b/spec/ruby/core/complex/finite_spec.rb
index 718848390c..7d9f82404e 100644
--- a/spec/ruby/core/complex/finite_spec.rb
+++ b/spec/ruby/core/complex/finite_spec.rb
@@ -2,31 +2,31 @@ require_relative '../../spec_helper'
describe "Complex#finite?" do
it "returns true if magnitude is finite" do
- (1+1i).finite?.should == true
+ (1+1i).should.finite?
end
it "returns false for positive infinity" do
value = Complex(Float::INFINITY, 42)
- value.finite?.should == false
+ value.should_not.finite?
end
it "returns false for positive complex with infinite imaginary" do
value = Complex(1, Float::INFINITY)
- value.finite?.should == false
+ value.should_not.finite?
end
it "returns false for negative infinity" do
value = -Complex(Float::INFINITY, 42)
- value.finite?.should == false
+ value.should_not.finite?
end
it "returns false for negative complex with infinite imaginary" do
value = -Complex(1, Float::INFINITY)
- value.finite?.should == false
+ value.should_not.finite?
end
it "returns false for NaN" do
value = Complex(Float::NAN, Float::NAN)
- value.finite?.should == false
+ value.should_not.finite?
end
end
diff --git a/spec/ruby/core/complex/shared/divide.rb b/spec/ruby/core/complex/shared/divide.rb
index a60802c74c..dc1b870cff 100644
--- a/spec/ruby/core/complex/shared/divide.rb
+++ b/spec/ruby/core/complex/shared/divide.rb
@@ -12,7 +12,7 @@ describe :complex_divide, shared: true do
end
end
- describe "with Fixnum" do
+ describe "with Integer" do
it "divides both parts of the Complex number" do
Complex(20, 40).send(@method, 2).should == Complex(10, 20)
Complex(30, 30).send(@method, 10).should == Complex(3, 3)
@@ -27,7 +27,7 @@ describe :complex_divide, shared: true do
end
end
- describe "with Bignum" do
+ describe "with Integer" do
it "divides both parts of the Complex number" do
Complex(20, 40).send(@method, 2).should == Complex(10, 20)
Complex(15, 16).send(@method, 2.0).should be_close(Complex(7.5, 8), TOLERANCE)
diff --git a/spec/ruby/core/complex/spaceship_spec.rb b/spec/ruby/core/complex/spaceship_spec.rb
deleted file mode 100644
index 7b2849a86a..0000000000
--- a/spec/ruby/core/complex/spaceship_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Complex#<=>" do
- ruby_version_is '2.7' do
- it "returns nil if either self or argument has imaginary part" do
- (Complex(5, 1) <=> Complex(2)).should be_nil
- (Complex(1) <=> Complex(2, 1)).should be_nil
- (5 <=> Complex(2, 1)).should be_nil
- end
-
- it "returns nil if argument is not numeric" do
- (Complex(5, 1) <=> "cmp").should be_nil
- (Complex(1) <=> "cmp").should be_nil
- (Complex(1) <=> Object.new).should be_nil
- end
-
- it "returns 0, 1, or -1 if self and argument do not have imaginary part" do
- (Complex(5) <=> Complex(2)).should == 1
- (Complex(2) <=> Complex(3)).should == -1
- (Complex(2) <=> Complex(2)).should == 0
-
- (Complex(5) <=> 2).should == 1
- (Complex(2) <=> 3).should == -1
- (Complex(2) <=> 2).should == 0
- end
- end
-end
diff --git a/spec/ruby/core/complex/to_c_spec.rb b/spec/ruby/core/complex/to_c_spec.rb
new file mode 100644
index 0000000000..5ce01d9d4e
--- /dev/null
+++ b/spec/ruby/core/complex/to_c_spec.rb
@@ -0,0 +1,12 @@
+require_relative '../../spec_helper'
+
+describe "Complex#to_c" do
+ it "returns self" do
+ value = Complex(1, 5)
+ value.to_c.should equal(value)
+ end
+
+ it 'returns the same value' do
+ Complex(1, 5).to_c.should == Complex(1, 5)
+ end
+end
diff --git a/spec/ruby/core/complex/to_f_spec.rb b/spec/ruby/core/complex/to_f_spec.rb
index 78e6526491..b53471c1fc 100644
--- a/spec/ruby/core/complex/to_f_spec.rb
+++ b/spec/ruby/core/complex/to_f_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Complex#to_f" do
- describe "when the imaginary part is Fixnum 0" do
+ describe "when the imaginary part is Integer 0" do
it "returns the result of sending #to_f to the real part" do
real = mock_numeric('real')
real.should_receive(:to_f).and_return(:f)
diff --git a/spec/ruby/core/complex/to_i_spec.rb b/spec/ruby/core/complex/to_i_spec.rb
index 23134705ba..1e78f5ec0e 100644
--- a/spec/ruby/core/complex/to_i_spec.rb
+++ b/spec/ruby/core/complex/to_i_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Complex#to_i" do
- describe "when the imaginary part is Fixnum 0" do
+ describe "when the imaginary part is Integer 0" do
it "returns the result of sending #to_i to the real part" do
real = mock_numeric('real')
real.should_receive(:to_i).and_return(:i)
diff --git a/spec/ruby/core/complex/to_r_spec.rb b/spec/ruby/core/complex/to_r_spec.rb
index 76a69a0b93..4559921492 100644
--- a/spec/ruby/core/complex/to_r_spec.rb
+++ b/spec/ruby/core/complex/to_r_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Complex#to_r" do
- describe "when the imaginary part is Fixnum 0" do
+ describe "when the imaginary part is Integer 0" do
it "returns the result of sending #to_r to the real part" do
real = mock_numeric('real')
real.should_receive(:to_r).and_return(:r)
diff --git a/spec/ruby/core/data/constants_spec.rb b/spec/ruby/core/data/constants_spec.rb
index 000da8fd09..a037bf6816 100644
--- a/spec/ruby/core/data/constants_spec.rb
+++ b/spec/ruby/core/data/constants_spec.rb
@@ -1,20 +1,13 @@
require_relative '../../spec_helper'
-describe "Data" do
- it "is a subclass of Object" do
- suppress_warning do
- Data.superclass.should == Object
+ruby_version_is ''...'3.0' do
+ describe "Data" do
+ it "is a subclass of Object" do
+ suppress_warning do
+ Data.superclass.should == Object
+ end
end
- end
- ruby_version_is "2.5" do
- before :each do
- @deprecated = Warning[:deprecated]
- Warning[:deprecated] = true
- end
- after :each do
- Warning[:deprecated] = @deprecated
- end
it "is deprecated" do
-> { Data }.should complain(/constant ::Data is deprecated/)
end
diff --git a/spec/ruby/core/dir/children_spec.rb b/spec/ruby/core/dir/children_spec.rb
index 8f6e62b463..e0325a24b8 100644
--- a/spec/ruby/core/dir/children_spec.rb
+++ b/spec/ruby/core/dir/children_spec.rb
@@ -3,71 +3,69 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
-ruby_version_is "2.5" do
- describe "Dir.children" do
- before :all do
- DirSpecs.create_mock_dirs
- end
+describe "Dir.children" do
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
- before :each do
- @internal = Encoding.default_internal
- end
+ before :each do
+ @internal = Encoding.default_internal
+ end
- after :all do
- DirSpecs.delete_mock_dirs
- end
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
- after :each do
- Encoding.default_internal = @internal
- end
+ after :each do
+ Encoding.default_internal = @internal
+ end
- it "returns an Array of filenames in an existing directory including dotfiles" do
- a = Dir.children(DirSpecs.mock_dir).sort
+ it "returns an Array of filenames in an existing directory including dotfiles" do
+ a = Dir.children(DirSpecs.mock_dir).sort
- a.should == DirSpecs.expected_paths - %w[. ..]
+ a.should == DirSpecs.expected_paths - %w[. ..]
- a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested").sort
- a.should == %w|.dotfile.ext directory|
- end
+ a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested").sort
+ a.should == %w|.dotfile.ext directory|
+ end
- it "calls #to_path on non-String arguments" do
- p = mock('path')
- p.should_receive(:to_path).and_return(DirSpecs.mock_dir)
- Dir.children(p)
- end
+ it "calls #to_path on non-String arguments" do
+ p = mock('path')
+ p.should_receive(:to_path).and_return(DirSpecs.mock_dir)
+ Dir.children(p)
+ end
- it "accepts an options Hash" do
- a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").sort
- a.should == %w|.dotfile.ext directory|
- end
+ it "accepts an options Hash" do
+ a = Dir.children("#{DirSpecs.mock_dir}/deeply/nested", encoding: "utf-8").sort
+ a.should == %w|.dotfile.ext directory|
+ end
- it "returns children encoded with the filesystem encoding by default" do
- # This spec depends on the locale not being US-ASCII because if it is, the
- # children that are not ascii_only? will be BINARY encoded.
- children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort
- encoding = Encoding.find("filesystem")
- encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
- platform_is_not :windows do
- children.should include("こんにちは.txt".force_encoding(encoding))
- end
- children.first.encoding.should equal(Encoding.find("filesystem"))
+ it "returns children encoded with the filesystem encoding by default" do
+ # This spec depends on the locale not being US-ASCII because if it is, the
+ # children that are not ascii_only? will be BINARY encoded.
+ children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort
+ encoding = Encoding.find("filesystem")
+ encoding = Encoding::BINARY if encoding == Encoding::US_ASCII
+ platform_is_not :windows do
+ children.should include("こんにちは.txt".force_encoding(encoding))
end
+ children.first.encoding.should equal(Encoding.find("filesystem"))
+ end
- it "returns children encoded with the specified encoding" do
- dir = File.join(DirSpecs.mock_dir, 'special')
- children = Dir.children(dir, encoding: "euc-jp").sort
- children.first.encoding.should equal(Encoding::EUC_JP)
- end
+ it "returns children encoded with the specified encoding" do
+ dir = File.join(DirSpecs.mock_dir, 'special')
+ children = Dir.children(dir, encoding: "euc-jp").sort
+ children.first.encoding.should equal(Encoding::EUC_JP)
+ end
- it "returns children transcoded to the default internal encoding" do
- Encoding.default_internal = Encoding::EUC_KR
- children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort
- children.first.encoding.should equal(Encoding::EUC_KR)
- end
+ it "returns children transcoded to the default internal encoding" do
+ Encoding.default_internal = Encoding::EUC_KR
+ children = Dir.children(File.join(DirSpecs.mock_dir, 'special')).sort
+ children.first.encoding.should equal(Encoding::EUC_KR)
+ end
- it "raises a SystemCallError if called with a nonexistent directory" do
- -> { Dir.children DirSpecs.nonexistent }.should raise_error(SystemCallError)
- end
+ it "raises a SystemCallError if called with a nonexistent directory" do
+ -> { Dir.children DirSpecs.nonexistent }.should raise_error(SystemCallError)
end
end
diff --git a/spec/ruby/core/dir/each_child_spec.rb b/spec/ruby/core/dir/each_child_spec.rb
index dcc9a456c7..93b4a1aec1 100644
--- a/spec/ruby/core/dir/each_child_spec.rb
+++ b/spec/ruby/core/dir/each_child_spec.rb
@@ -1,51 +1,49 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
-ruby_version_is "2.5" do
- describe "Dir.each_child" do
- before :all do
- DirSpecs.create_mock_dirs
- end
+describe "Dir.each_child" do
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
- after :all do
- DirSpecs.delete_mock_dirs
- end
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
- it "yields all names in an existing directory to the provided block" do
- a, b = [], []
+ it "yields all names in an existing directory to the provided block" do
+ a, b = [], []
- Dir.each_child(DirSpecs.mock_dir) {|f| a << f}
- Dir.each_child("#{DirSpecs.mock_dir}/deeply/nested") {|f| b << f}
+ Dir.each_child(DirSpecs.mock_dir) {|f| a << f}
+ Dir.each_child("#{DirSpecs.mock_dir}/deeply/nested") {|f| b << f}
- a.sort.should == DirSpecs.expected_paths - %w[. ..]
- b.sort.should == %w|.dotfile.ext directory|
- end
+ a.sort.should == DirSpecs.expected_paths - %w[. ..]
+ b.sort.should == %w|.dotfile.ext directory|
+ end
- it "returns nil when successful" do
- Dir.each_child(DirSpecs.mock_dir) {|f| f}.should == nil
- end
+ it "returns nil when successful" do
+ Dir.each_child(DirSpecs.mock_dir) {|f| f}.should == nil
+ end
- it "calls #to_path on non-String arguments" do
- p = mock('path')
- p.should_receive(:to_path).and_return(DirSpecs.mock_dir)
- Dir.each_child(p).to_a
- end
+ it "calls #to_path on non-String arguments" do
+ p = mock('path')
+ p.should_receive(:to_path).and_return(DirSpecs.mock_dir)
+ Dir.each_child(p).to_a
+ end
- it "raises a SystemCallError if passed a nonexistent directory" do
- -> { Dir.each_child(DirSpecs.nonexistent) {} }.should raise_error(SystemCallError)
- end
+ it "raises a SystemCallError if passed a nonexistent directory" do
+ -> { Dir.each_child(DirSpecs.nonexistent) {} }.should raise_error(SystemCallError)
+ end
- describe "when no block is given" do
- it "returns an Enumerator" do
- Dir.each_child(DirSpecs.mock_dir).should be_an_instance_of(Enumerator)
- Dir.each_child(DirSpecs.mock_dir).to_a.sort.should == DirSpecs.expected_paths - %w[. ..]
- end
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ Dir.each_child(DirSpecs.mock_dir).should be_an_instance_of(Enumerator)
+ Dir.each_child(DirSpecs.mock_dir).to_a.sort.should == DirSpecs.expected_paths - %w[. ..]
+ end
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- Dir.each_child(DirSpecs.mock_dir).size.should == nil
- end
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ Dir.each_child(DirSpecs.mock_dir).size.should == nil
end
end
end
diff --git a/spec/ruby/core/dir/exists_spec.rb b/spec/ruby/core/dir/exists_spec.rb
deleted file mode 100644
index 2c6f145db2..0000000000
--- a/spec/ruby/core/dir/exists_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
-require_relative 'shared/exist'
-
-describe "Dir.exists?" do
- before :all do
- DirSpecs.create_mock_dirs
- end
-
- after :all do
- DirSpecs.delete_mock_dirs
- end
-
- it_behaves_like :dir_exist, :exists?
-end
diff --git a/spec/ruby/core/dir/fileno_spec.rb b/spec/ruby/core/dir/fileno_spec.rb
index 504e36d44b..bb84ef5378 100644
--- a/spec/ruby/core/dir/fileno_spec.rb
+++ b/spec/ruby/core/dir/fileno_spec.rb
@@ -27,7 +27,7 @@ describe "Dir#fileno" do
if has_dir_fileno
it "returns the file descriptor of the dir" do
- @dir.fileno.should be_kind_of(Fixnum)
+ @dir.fileno.should be_kind_of(Integer)
end
else
it "raises an error when not implemented on the platform" do
diff --git a/spec/ruby/core/dir/fixtures/common.rb b/spec/ruby/core/dir/fixtures/common.rb
index f6708b04f7..71b1438b72 100644
--- a/spec/ruby/core/dir/fixtures/common.rb
+++ b/spec/ruby/core/dir/fixtures/common.rb
@@ -22,7 +22,7 @@ module DirSpecs
[0xe9].pack('U')
].each do |dir|
begin
- Dir.rmdir dir
+ Dir.rmdir mock_dir(dir)
rescue
end
end
@@ -36,6 +36,8 @@ module DirSpecs
.dotfile
.dotsubdir/.dotfile
.dotsubdir/nondotfile
+ nested/.dotsubir/.dotfile
+ nested/.dotsubir/nondotfile
deeply/.dotfile
deeply/nested/.dotfile.ext
@@ -160,6 +162,7 @@ module DirSpecs
dir_filename_ordering
file_one.ext
file_two.ext
+ nested
nondotfile
special
subdir_one
diff --git a/spec/ruby/core/dir/glob_spec.rb b/spec/ruby/core/dir/glob_spec.rb
index 4b437b0e24..9b6e2b2d3d 100644
--- a/spec/ruby/core/dir/glob_spec.rb
+++ b/spec/ruby/core/dir/glob_spec.rb
@@ -59,6 +59,8 @@ describe "Dir.glob" do
deeply/nested/directory/
deeply/nested/directory/structure/
dir/
+ nested/
+ nested/.dotsubir/
special/
special/test{1}/
subdir_one/
@@ -68,6 +70,18 @@ describe "Dir.glob" do
Dir.glob('**/', File::FNM_DOTMATCH).sort.should == expected
end
+ 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
+
# This is a separate case to check **/ coming after a constant
# directory as well.
it "recursively matches any subdirectories except './' or '../' with '**/' and option File::FNM_DOTMATCH" do
@@ -80,6 +94,8 @@ describe "Dir.glob" do
./deeply/nested/directory/
./deeply/nested/directory/structure/
./dir/
+ ./nested/
+ ./nested/.dotsubir/
./special/
./special/test{1}/
./subdir_one/
@@ -119,7 +135,7 @@ describe "Dir.glob" do
end
it "handles infinite directory wildcards" do
- Dir.glob('**/**/**').empty?.should == false
+ Dir.glob('**/**/**').should_not.empty?
end
it "handles simple filename patterns" do
diff --git a/spec/ruby/core/dir/home_spec.rb b/spec/ruby/core/dir/home_spec.rb
index cdfc9346dc..713ba9db9a 100644
--- a/spec/ruby/core/dir/home_spec.rb
+++ b/spec/ruby/core/dir/home_spec.rb
@@ -17,7 +17,7 @@ describe "Dir.home" do
end
it "returns a non-frozen string" do
- Dir.home.frozen?.should == false
+ Dir.home.should_not.frozen?
end
end
@@ -28,14 +28,14 @@ describe "Dir.home" do
end
end
- platform_is_not :windows, :solaris do
+ platform_is_not :windows, :solaris, :android do
it "returns the named user's home directory, from the user database" do
Dir.home(ENV['USER']).should == `echo ~#{ENV['USER']}`.chomp
end
end
it "returns a non-frozen string" do
- Dir.home(ENV['USER']).frozen?.should == false
+ Dir.home(ENV['USER']).should_not.frozen?
end
end
diff --git a/spec/ruby/core/dir/mkdir_spec.rb b/spec/ruby/core/dir/mkdir_spec.rb
index c6e2f164e2..0ed28f5a99 100644
--- a/spec/ruby/core/dir/mkdir_spec.rb
+++ b/spec/ruby/core/dir/mkdir_spec.rb
@@ -13,29 +13,33 @@ describe "Dir.mkdir" do
it "creates the named directory with the given permissions" do
DirSpecs.clear_dirs
+ nonexisting = DirSpecs.mock_dir('nonexisting')
+ default_perms = DirSpecs.mock_dir('default_perms')
+ reduced = DirSpecs.mock_dir('reduced')
begin
- File.should_not.exist?('nonexisting')
- Dir.mkdir 'nonexisting'
- File.should.exist?('nonexisting')
+ File.should_not.exist?(nonexisting)
+ Dir.mkdir nonexisting
+ File.should.exist?(nonexisting)
platform_is_not :windows do
- Dir.mkdir 'default_perms'
- a = File.stat('default_perms').mode
- Dir.mkdir 'reduced', (a - 1)
- File.stat('reduced').mode.should_not == a
+ Dir.mkdir default_perms
+ a = File.stat(default_perms).mode
+ Dir.mkdir reduced, (a - 1)
+ File.stat(reduced).mode.should_not == a
end
platform_is :windows do
- Dir.mkdir 'default_perms', 0666
- a = File.stat('default_perms').mode
- Dir.mkdir 'reduced', 0444
- File.stat('reduced').mode.should_not == a
+ Dir.mkdir default_perms, 0666
+ a = File.stat(default_perms).mode
+ Dir.mkdir reduced, 0444
+ File.stat(reduced).mode.should_not == a
end
- Dir.mkdir('always_returns_0').should == 0
+ always_returns_0 = DirSpecs.mock_dir('always_returns_0')
+ Dir.mkdir(always_returns_0).should == 0
platform_is_not(:windows) do
- File.chmod(0777, "nonexisting","default_perms","reduced","always_returns_0")
+ File.chmod(0777, nonexisting, default_perms, reduced, always_returns_0)
end
platform_is_not(:windows) do
- File.chmod(0644, "nonexisting","default_perms","reduced","always_returns_0")
+ File.chmod(0644, nonexisting, default_perms, reduced, always_returns_0)
end
ensure
DirSpecs.clear_dirs
@@ -45,7 +49,7 @@ describe "Dir.mkdir" do
it "calls #to_path on non-String arguments" do
DirSpecs.clear_dirs
p = mock('path')
- p.should_receive(:to_path).and_return('nonexisting')
+ p.should_receive(:to_path).and_return(DirSpecs.mock_dir('nonexisting'))
Dir.mkdir(p)
DirSpecs.clear_dirs
end
diff --git a/spec/ruby/core/dir/shared/glob.rb b/spec/ruby/core/dir/shared/glob.rb
index b47e23b41c..f6d41ba209 100644
--- a/spec/ruby/core/dir/shared/glob.rb
+++ b/spec/ruby/core/dir/shared/glob.rb
@@ -53,6 +53,7 @@ describe :dir_glob, shared: true do
dir_filename_ordering
file_one.ext
file_two.ext
+ nested
nondotfile
special
subdir_one
@@ -156,6 +157,7 @@ describe :dir_glob, shared: true do
dir_filename_ordering
file_one.ext
file_two.ext
+ nested
nondotfile
special
subdir_one
@@ -177,6 +179,7 @@ describe :dir_glob, shared: true do
deeply/nested/directory/
deeply/nested/directory/structure/
dir/
+ nested/
special/
special/test{1}/
subdir_one/
@@ -291,74 +294,72 @@ describe :dir_glob, shared: true do
end
end
- ruby_version_is "2.5" do
- context ":base option passed" do
- before :each do
- @mock_dir = File.expand_path tmp('dir_glob_mock')
-
- %w[
- a/b/x
- a/b/c/y
- a/b/c/d/z
- ].each do |path|
- file = File.join @mock_dir, path
- mkdir_p File.dirname(file)
- touch file
- end
- end
+ context ":base option passed" do
+ before :each do
+ @mock_dir = File.expand_path tmp('dir_glob_mock')
- after :each do
- rm_r @mock_dir
+ %w[
+ a/b/x
+ a/b/c/y
+ a/b/c/d/z
+ ].each do |path|
+ file = File.join @mock_dir, path
+ mkdir_p File.dirname(file)
+ touch file
end
+ end
- it "matches entries only from within the specified directory" do
- path = File.join(@mock_dir, "a/b/c")
- Dir.send(@method, "*", base: path).sort.should == %w( d y )
- end
+ after :each do
+ rm_r @mock_dir
+ end
- it "accepts both relative and absolute paths" do
- require 'pathname'
+ it "matches entries only from within the specified directory" do
+ path = File.join(@mock_dir, "a/b/c")
+ Dir.send(@method, "*", base: path).sort.should == %w( d y )
+ end
- path_abs = File.join(@mock_dir, "a/b/c")
- path_rel = Pathname.new(path_abs).relative_path_from(Pathname.new(Dir.pwd))
+ it "accepts both relative and absolute paths" do
+ require 'pathname'
- result_abs = Dir.send(@method, "*", base: path_abs).sort
- result_rel = Dir.send(@method, "*", base: path_rel).sort
+ path_abs = File.join(@mock_dir, "a/b/c")
+ path_rel = Pathname.new(path_abs).relative_path_from(Pathname.new(Dir.pwd))
- result_abs.should == %w( d y )
- result_rel.should == %w( d y )
- end
+ result_abs = Dir.send(@method, "*", base: path_abs).sort
+ result_rel = Dir.send(@method, "*", base: path_rel).sort
- it "returns [] if specified path does not exist" do
- path = File.join(@mock_dir, "fake-name")
- File.should_not.exist?(path)
+ result_abs.should == %w( d y )
+ result_rel.should == %w( d y )
+ end
- Dir.send(@method, "*", base: path).should == []
- end
+ it "returns [] if specified path does not exist" do
+ path = File.join(@mock_dir, "fake-name")
+ File.should_not.exist?(path)
- it "returns [] if specified path is a file" do
- path = File.join(@mock_dir, "a/b/x")
- File.should.exist?(path)
+ Dir.send(@method, "*", base: path).should == []
+ end
- Dir.send(@method, "*", base: path).should == []
- end
+ it "returns [] if specified path is a file" do
+ path = File.join(@mock_dir, "a/b/x")
+ File.should.exist?(path)
- it "raises TypeError when cannot convert value to string" do
- -> {
- Dir.send(@method, "*", base: [])
- }.should raise_error(TypeError)
- end
+ Dir.send(@method, "*", base: path).should == []
+ end
- it "handles '' as current directory path" do
- Dir.chdir @mock_dir do
- Dir.send(@method, "*", base: "").should == %w( a )
- end
+ it "raises TypeError when cannot convert value to string" do
+ -> {
+ Dir.send(@method, "*", base: [])
+ }.should raise_error(TypeError)
+ end
+
+ it "handles '' as current directory path" do
+ Dir.chdir @mock_dir do
+ Dir.send(@method, "*", base: "").should == %w( a )
end
+ end
- it "handles nil as current directory path" do
- Dir.chdir @mock_dir do
- Dir.send(@method, "*", base: nil).should == %w( a )
- end
+ it "handles nil as current directory path" do
+ Dir.chdir @mock_dir do
+ Dir.send(@method, "*", base: nil).should == %w( a )
end
end
end
diff --git a/spec/ruby/core/dir/shared/open.rb b/spec/ruby/core/dir/shared/open.rb
index 76b08dc288..920845cba1 100644
--- a/spec/ruby/core/dir/shared/open.rb
+++ b/spec/ruby/core/dir/shared/open.rb
@@ -66,7 +66,7 @@ describe :dir_open, shared: true do
Dir.send(@method, DirSpecs.mock_dir) do |dir|
io = IO.for_fd(dir.fileno)
io.autoclose = false
- io.close_on_exec?.should == true
+ io.should.close_on_exec?
end
end
end
diff --git a/spec/ruby/core/encoding/converter/constants_spec.rb b/spec/ruby/core/encoding/converter/constants_spec.rb
index 57b6a4d4e7..7d29bdb278 100644
--- a/spec/ruby/core/encoding/converter/constants_spec.rb
+++ b/spec/ruby/core/encoding/converter/constants_spec.rb
@@ -5,8 +5,8 @@ describe "Encoding::Converter::INVALID_MASK" do
Encoding::Converter.should have_constant(:INVALID_MASK)
end
- it "has a Fixnum value" do
- Encoding::Converter::INVALID_MASK.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::INVALID_MASK.should be_an_instance_of(Integer)
end
end
@@ -15,8 +15,8 @@ describe "Encoding::Converter::INVALID_REPLACE" do
Encoding::Converter.should have_constant(:INVALID_REPLACE)
end
- it "has a Fixnum value" do
- Encoding::Converter::INVALID_REPLACE.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::INVALID_REPLACE.should be_an_instance_of(Integer)
end
end
@@ -25,8 +25,8 @@ describe "Encoding::Converter::UNDEF_MASK" do
Encoding::Converter.should have_constant(:UNDEF_MASK)
end
- it "has a Fixnum value" do
- Encoding::Converter::UNDEF_MASK.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::UNDEF_MASK.should be_an_instance_of(Integer)
end
end
@@ -35,8 +35,8 @@ describe "Encoding::Converter::UNDEF_REPLACE" do
Encoding::Converter.should have_constant(:UNDEF_REPLACE)
end
- it "has a Fixnum value" do
- Encoding::Converter::UNDEF_REPLACE.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::UNDEF_REPLACE.should be_an_instance_of(Integer)
end
end
@@ -45,8 +45,8 @@ describe "Encoding::Converter::UNDEF_HEX_CHARREF" do
Encoding::Converter.should have_constant(:UNDEF_HEX_CHARREF)
end
- it "has a Fixnum value" do
- Encoding::Converter::UNDEF_HEX_CHARREF.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::UNDEF_HEX_CHARREF.should be_an_instance_of(Integer)
end
end
@@ -55,8 +55,8 @@ describe "Encoding::Converter::PARTIAL_INPUT" do
Encoding::Converter.should have_constant(:PARTIAL_INPUT)
end
- it "has a Fixnum value" do
- Encoding::Converter::PARTIAL_INPUT.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::PARTIAL_INPUT.should be_an_instance_of(Integer)
end
end
@@ -65,8 +65,8 @@ describe "Encoding::Converter::AFTER_OUTPUT" do
Encoding::Converter.should have_constant(:AFTER_OUTPUT)
end
- it "has a Fixnum value" do
- Encoding::Converter::AFTER_OUTPUT.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::AFTER_OUTPUT.should be_an_instance_of(Integer)
end
end
@@ -75,8 +75,8 @@ describe "Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR" do
Encoding::Converter.should have_constant(:UNIVERSAL_NEWLINE_DECORATOR)
end
- it "has a Fixnum value" do
- Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::UNIVERSAL_NEWLINE_DECORATOR.should be_an_instance_of(Integer)
end
end
@@ -85,8 +85,8 @@ describe "Encoding::Converter::CRLF_NEWLINE_DECORATOR" do
Encoding::Converter.should have_constant(:CRLF_NEWLINE_DECORATOR)
end
- it "has a Fixnum value" do
- Encoding::Converter::CRLF_NEWLINE_DECORATOR.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::CRLF_NEWLINE_DECORATOR.should be_an_instance_of(Integer)
end
end
@@ -95,8 +95,8 @@ describe "Encoding::Converter::CR_NEWLINE_DECORATOR" do
Encoding::Converter.should have_constant(:CR_NEWLINE_DECORATOR)
end
- it "has a Fixnum value" do
- Encoding::Converter::CR_NEWLINE_DECORATOR.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::CR_NEWLINE_DECORATOR.should be_an_instance_of(Integer)
end
end
@@ -105,8 +105,8 @@ describe "Encoding::Converter::XML_TEXT_DECORATOR" do
Encoding::Converter.should have_constant(:XML_TEXT_DECORATOR)
end
- it "has a Fixnum value" do
- Encoding::Converter::XML_TEXT_DECORATOR.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::XML_TEXT_DECORATOR.should be_an_instance_of(Integer)
end
end
@@ -115,8 +115,8 @@ describe "Encoding::Converter::XML_ATTR_CONTENT_DECORATOR" do
Encoding::Converter.should have_constant(:XML_ATTR_CONTENT_DECORATOR)
end
- it "has a Fixnum value" do
- Encoding::Converter::XML_ATTR_CONTENT_DECORATOR.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::XML_ATTR_CONTENT_DECORATOR.should be_an_instance_of(Integer)
end
end
@@ -125,7 +125,7 @@ describe "Encoding::Converter::XML_ATTR_QUOTE_DECORATOR" do
Encoding::Converter.should have_constant(:XML_ATTR_QUOTE_DECORATOR)
end
- it "has a Fixnum value" do
- Encoding::Converter::XML_ATTR_QUOTE_DECORATOR.should be_an_instance_of(Fixnum)
+ it "has an Integer value" do
+ Encoding::Converter::XML_ATTR_QUOTE_DECORATOR.should be_an_instance_of(Integer)
end
end
diff --git a/spec/ruby/core/encoding/converter/new_spec.rb b/spec/ruby/core/encoding/converter/new_spec.rb
index 9fc97263fe..1f7affc72b 100644
--- a/spec/ruby/core/encoding/converter/new_spec.rb
+++ b/spec/ruby/core/encoding/converter/new_spec.rb
@@ -47,7 +47,7 @@ describe "Encoding::Converter.new" do
conv.replacement.should == "fubar"
end
- it "calls #to_hash to convert the options argument to a Hash if not a Fixnum" do
+ it "calls #to_hash to convert the options argument to a Hash if not an Integer" do
opts = mock("encoding converter options")
opts.should_receive(:to_hash).and_return({ replace: "fubar" })
conv = Encoding::Converter.new("us-ascii", "utf-8", **opts)
@@ -82,7 +82,7 @@ describe "Encoding::Converter.new" do
end.should raise_error(TypeError)
end
- it "raises a TypeError if passed a Fixnum for the replacement object" do
+ it "raises a TypeError if passed an Integer for the replacement object" do
-> do
Encoding::Converter.new("us-ascii", "utf-8", replace: 1)
end.should raise_error(TypeError)
diff --git a/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 e3ef3e4557..94201a9b15 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
@@ -2,7 +2,6 @@
require_relative '../../../spec_helper'
describe "Encoding::InvalidByteSequenceError#incomplete_input?" do
-
it "returns nil by default" do
Encoding::InvalidByteSequenceError.new.incomplete_input?.should be_nil
end
diff --git a/spec/ruby/core/encoding/list_spec.rb b/spec/ruby/core/encoding/list_spec.rb
index 2a2078974e..8efd94ab9c 100644
--- a/spec/ruby/core/encoding/list_spec.rb
+++ b/spec/ruby/core/encoding/list_spec.rb
@@ -12,7 +12,7 @@ describe "Encoding.list" do
end
it "returns each encoding only once" do
- orig = Encoding.list.map {|e| e.name}
+ orig = Encoding.list.map { |e| e.name }
orig.should == orig.uniq
end
@@ -33,7 +33,17 @@ describe "Encoding.list" do
end
it "includes dummy encodings" do
- Encoding.list.select {|e| e.dummy?}.should_not == []
+ Encoding.list.select { |e| e.dummy? }.should_not == []
+ end
+
+ it 'includes UTF-8 encoding' do
+ Encoding.list.should.include?(Encoding::UTF_8)
+ end
+
+ ruby_version_is "2.7" do
+ it 'includes CESU-8 encoding' do
+ Encoding.list.should.include?(Encoding::CESU_8)
+ end
end
# TODO: Find example that illustrates this
diff --git a/spec/ruby/core/encoding/locale_charmap_spec.rb b/spec/ruby/core/encoding/locale_charmap_spec.rb
index 5963a8beb5..8143b9083a 100644
--- a/spec/ruby/core/encoding/locale_charmap_spec.rb
+++ b/spec/ruby/core/encoding/locale_charmap_spec.rb
@@ -7,11 +7,13 @@ describe "Encoding.locale_charmap" do
# FIXME: Get this working on Windows
platform_is :linux do
- it "returns a value based on the LC_ALL environment variable" do
- old_lc_all = ENV['LC_ALL']
- ENV['LC_ALL'] = 'C'
- ruby_exe("print Encoding.locale_charmap").should == 'ANSI_X3.4-1968'
- ENV['LC_ALL'] = old_lc_all
+ platform_is_not :android do
+ it "returns a value based on the LC_ALL environment variable" do
+ old_lc_all = ENV['LC_ALL']
+ ENV['LC_ALL'] = 'C'
+ ruby_exe("print Encoding.locale_charmap").should == 'ANSI_X3.4-1968'
+ ENV['LC_ALL'] = old_lc_all
+ end
end
end
@@ -33,6 +35,15 @@ describe "Encoding.locale_charmap" do
end
end
+ platform_is :android do
+ it "always returns UTF-8" do
+ old_lc_all = ENV['LC_ALL']
+ ENV['LC_ALL'] = 'C'
+ ruby_exe("print Encoding.locale_charmap").should == 'UTF-8'
+ ENV['LC_ALL'] = old_lc_all
+ end
+ end
+
platform_is :bsd, :darwin, :linux do
it "is unaffected by assigning to ENV['LC_ALL'] in the same process" do
old_charmap = Encoding.locale_charmap
diff --git a/spec/ruby/core/enumerable/all_spec.rb b/spec/ruby/core/enumerable/all_spec.rb
index 8af80896a9..7e9726fe87 100644
--- a/spec/ruby/core/enumerable/all_spec.rb
+++ b/spec/ruby/core/enumerable/all_spec.rb
@@ -10,13 +10,13 @@ describe "Enumerable#all?" do
end
it "always returns true on empty enumeration" do
- @empty.all?.should == true
+ @empty.should.all?
@empty.all? { nil }.should == true
- [].all?.should == true
+ [].should.all?
[].all? { false }.should == true
- {}.all?.should == true
+ {}.should.all?
{}.all? { nil }.should == true
end
@@ -26,15 +26,6 @@ describe "Enumerable#all?" do
-> { {}.all?(1, 2, 3) }.should raise_error(ArgumentError)
end
- ruby_version_is ""..."2.5" do
- it "raises an ArgumentError when any arguments provided" do
- -> { @enum.all?(Proc.new {}) }.should raise_error(ArgumentError)
- -> { @enum.all?(nil) }.should raise_error(ArgumentError)
- -> { @empty.all?(1) }.should raise_error(ArgumentError)
- -> { @enum1.all?(1) {} }.should raise_error(ArgumentError)
- end
- end
-
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.all?
@@ -47,24 +38,24 @@ describe "Enumerable#all?" do
describe "with no block" do
it "returns true if no elements are false or nil" do
- @enum.all?.should == true
- @enum1.all?.should == true
- @enum2.all?.should == false
+ @enum.should.all?
+ @enum1.should.all?
+ @enum2.should_not.all?
- EnumerableSpecs::Numerous.new('a','b','c').all?.should == true
- EnumerableSpecs::Numerous.new(0, "x", true).all?.should == true
+ EnumerableSpecs::Numerous.new('a','b','c').should.all?
+ EnumerableSpecs::Numerous.new(0, "x", true).should.all?
end
it "returns false if there are false or nil elements" do
- EnumerableSpecs::Numerous.new(false).all?.should == false
- EnumerableSpecs::Numerous.new(false, false).all?.should == false
+ EnumerableSpecs::Numerous.new(false).should_not.all?
+ EnumerableSpecs::Numerous.new(false, false).should_not.all?
- EnumerableSpecs::Numerous.new(nil).all?.should == false
- EnumerableSpecs::Numerous.new(nil, nil).all?.should == false
+ EnumerableSpecs::Numerous.new(nil).should_not.all?
+ EnumerableSpecs::Numerous.new(nil, nil).should_not.all?
- EnumerableSpecs::Numerous.new(1, nil, 2).all?.should == false
- EnumerableSpecs::Numerous.new(0, "x", false, true).all?.should == false
- @enum2.all?.should == false
+ EnumerableSpecs::Numerous.new(1, nil, 2).should_not.all?
+ EnumerableSpecs::Numerous.new(0, "x", false, true).should_not.all?
+ @enum2.should_not.all?
end
it "gathers whole arrays as elements when each yields multiple" do
@@ -133,69 +124,67 @@ describe "Enumerable#all?" do
end
end
- ruby_version_is "2.5" do
- describe 'when given a pattern argument' do
- it "calls `===` on the pattern the return value " do
- pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 }
- @enum1.all?(pattern).should == false
- pattern.yielded.should == [[0], [1], [2], [-1]]
- end
+ describe 'when given a pattern argument' do
+ it "calls `===` on the pattern the return value " do
+ pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 }
+ @enum1.all?(pattern).should == false
+ pattern.yielded.should == [[0], [1], [2], [-1]]
+ end
- # may raise an exception in future versions
- ruby_version_is ""..."2.6" do
- it "ignores block" do
- @enum2.all?(NilClass) { raise }.should == false
- [1, 2, nil].all?(NilClass) { raise }.should == false
- {a: 1}.all?(Array) { raise }.should == true
- end
+ # may raise an exception in future versions
+ ruby_version_is ""..."2.6" do
+ it "ignores block" do
+ @enum2.all?(NilClass) { raise }.should == false
+ [1, 2, nil].all?(NilClass) { raise }.should == false
+ {a: 1}.all?(Array) { raise }.should == true
end
+ end
- it "always returns true on empty enumeration" do
- @empty.all?(Integer).should == true
- [].all?(Integer).should == true
- {}.all?(NilClass).should == true
- end
+ it "always returns true on empty enumeration" do
+ @empty.all?(Integer).should == true
+ [].all?(Integer).should == true
+ {}.all?(NilClass).should == true
+ end
- it "does not hide exceptions out of #each" do
- -> {
- EnumerableSpecs::ThrowingEach.new.all?(Integer)
- }.should raise_error(RuntimeError)
- end
+ it "does not hide exceptions out of #each" do
+ -> {
+ EnumerableSpecs::ThrowingEach.new.all?(Integer)
+ }.should raise_error(RuntimeError)
+ end
- it "returns true if the pattern never returns false or nil" do
- pattern = EnumerableSpecs::Pattern.new { |x| 42 }
- @enum.all?(pattern).should == true
+ it "returns true if the pattern never returns false or nil" do
+ pattern = EnumerableSpecs::Pattern.new { |x| 42 }
+ @enum.all?(pattern).should == true
- [1, 42, 3].all?(pattern).should == true
+ [1, 42, 3].all?(pattern).should == true
- pattern = EnumerableSpecs::Pattern.new { |x| Array === x }
- {a: 1, b: 2}.all?(pattern).should == true
- end
+ pattern = EnumerableSpecs::Pattern.new { |x| Array === x }
+ {a: 1, b: 2}.all?(pattern).should == true
+ end
- it "returns false if the pattern ever returns false or nil" do
- pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 }
- @enum1.all?(pattern).should == false
- pattern.yielded.should == [[0], [1], [2], [-1]]
+ it "returns false if the pattern ever returns false or nil" do
+ pattern = EnumerableSpecs::Pattern.new { |x| x >= 0 }
+ @enum1.all?(pattern).should == false
+ pattern.yielded.should == [[0], [1], [2], [-1]]
- [1, 2, 3, -1].all?(pattern).should == false
+ [1, 2, 3, -1].all?(pattern).should == false
- pattern = EnumerableSpecs::Pattern.new { |x| x[1] >= 0 }
- {a: 1, b: -1}.all?(pattern).should == false
- end
+ pattern = EnumerableSpecs::Pattern.new { |x| x[1] >= 0 }
+ {a: 1, b: -1}.all?(pattern).should == false
+ end
- it "does not hide exceptions out of pattern#===" do
- pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
- -> {
- @enum.all?(pattern)
- }.should raise_error(RuntimeError)
- end
+ it "does not hide exceptions out of pattern#===" do
+ pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
+ -> {
+ @enum.all?(pattern)
+ }.should raise_error(RuntimeError)
+ end
- it "calls the pattern with gathered array when yielded with multiple arguments" do
- multi = EnumerableSpecs::YieldsMulti.new
- pattern = EnumerableSpecs::Pattern.new { true }
- multi.all?(pattern).should == true
- pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
- end
+ it "calls the pattern with gathered array when yielded with multiple arguments" do
+ multi = EnumerableSpecs::YieldsMulti.new
+ pattern = EnumerableSpecs::Pattern.new { true }
+ multi.all?(pattern).should == true
+ pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
end
end
end
diff --git a/spec/ruby/core/enumerable/any_spec.rb b/spec/ruby/core/enumerable/any_spec.rb
index c800fe2d4b..64e3159963 100644
--- a/spec/ruby/core/enumerable/any_spec.rb
+++ b/spec/ruby/core/enumerable/any_spec.rb
@@ -10,13 +10,13 @@ describe "Enumerable#any?" do
end
it "always returns false on empty enumeration" do
- @empty.any?.should == false
+ @empty.should_not.any?
@empty.any? { nil }.should == false
- [].any?.should == false
+ [].should_not.any?
[].any? { false }.should == false
- {}.any?.should == false
+ {}.should_not.any?
{}.any? { nil }.should == false
end
@@ -26,15 +26,6 @@ describe "Enumerable#any?" do
-> { {}.any?(1, 2, 3) }.should raise_error(ArgumentError)
end
- ruby_version_is ""..."2.5" do
- it "raises an ArgumentError when any arguments provided" do
- -> { @enum.any?(Proc.new {}) }.should raise_error(ArgumentError)
- -> { @enum.any?(nil) }.should raise_error(ArgumentError)
- -> { @empty.any?(1) }.should raise_error(ArgumentError)
- -> { @enum1.any?(1) {} }.should raise_error(ArgumentError)
- end
- end
-
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.any?
@@ -47,24 +38,24 @@ describe "Enumerable#any?" do
describe "with no block" do
it "returns true if any element is not false or nil" do
- @enum.any?.should == true
- @enum1.any?.should == true
- @enum2.any?.should == true
- EnumerableSpecs::Numerous.new(true).any?.should == true
- EnumerableSpecs::Numerous.new('a','b','c').any?.should == true
- EnumerableSpecs::Numerous.new('a','b','c', nil).any?.should == true
- EnumerableSpecs::Numerous.new(1, nil, 2).any?.should == true
- EnumerableSpecs::Numerous.new(1, false).any?.should == true
- EnumerableSpecs::Numerous.new(false, nil, 1, false).any?.should == true
- EnumerableSpecs::Numerous.new(false, 0, nil).any?.should == true
+ @enum.should.any?
+ @enum1.should.any?
+ @enum2.should.any?
+ EnumerableSpecs::Numerous.new(true).should.any?
+ EnumerableSpecs::Numerous.new('a','b','c').should.any?
+ EnumerableSpecs::Numerous.new('a','b','c', nil).should.any?
+ EnumerableSpecs::Numerous.new(1, nil, 2).should.any?
+ EnumerableSpecs::Numerous.new(1, false).should.any?
+ EnumerableSpecs::Numerous.new(false, nil, 1, false).should.any?
+ EnumerableSpecs::Numerous.new(false, 0, nil).should.any?
end
it "returns false if all elements are false or nil" do
- EnumerableSpecs::Numerous.new(false).any?.should == false
- EnumerableSpecs::Numerous.new(false, false).any?.should == false
- EnumerableSpecs::Numerous.new(nil).any?.should == false
- EnumerableSpecs::Numerous.new(nil, nil).any?.should == false
- EnumerableSpecs::Numerous.new(nil, false, nil).any?.should == false
+ EnumerableSpecs::Numerous.new(false).should_not.any?
+ EnumerableSpecs::Numerous.new(false, false).should_not.any?
+ EnumerableSpecs::Numerous.new(nil).should_not.any?
+ EnumerableSpecs::Numerous.new(nil, nil).should_not.any?
+ EnumerableSpecs::Numerous.new(nil, false, nil).should_not.any?
end
it "gathers whole arrays as elements when each yields multiple" do
@@ -147,68 +138,66 @@ describe "Enumerable#any?" do
end
end
- ruby_version_is "2.5" do
- describe 'when given a pattern argument' do
- it "calls `===` on the pattern the return value " do
- pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
- @enum1.any?(pattern).should == true
- pattern.yielded.should == [[0], [1], [2]]
- end
+ describe 'when given a pattern argument' do
+ it "calls `===` on the pattern the return value " do
+ pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
+ @enum1.any?(pattern).should == true
+ pattern.yielded.should == [[0], [1], [2]]
+ end
- # may raise an exception in future versions
- ruby_version_is ""..."2.6" do
- it "ignores block" do
- @enum2.any?(NilClass) { raise }.should == true
- [1, 2, nil].any?(NilClass) { raise }.should == true
- {a: 1}.any?(Array) { raise }.should == true
- end
+ # may raise an exception in future versions
+ ruby_version_is ""..."2.6" do
+ it "ignores block" do
+ @enum2.any?(NilClass) { raise }.should == true
+ [1, 2, nil].any?(NilClass) { raise }.should == true
+ {a: 1}.any?(Array) { raise }.should == true
end
+ end
- it "always returns false on empty enumeration" do
- @empty.any?(Integer).should == false
- [].any?(Integer).should == false
- {}.any?(NilClass).should == false
- end
+ it "always returns false on empty enumeration" do
+ @empty.any?(Integer).should == false
+ [].any?(Integer).should == false
+ {}.any?(NilClass).should == false
+ end
- it "does not hide exceptions out of #each" do
- -> {
- EnumerableSpecs::ThrowingEach.new.any?(Integer)
- }.should raise_error(RuntimeError)
- end
+ it "does not hide exceptions out of #each" do
+ -> {
+ EnumerableSpecs::ThrowingEach.new.any?(Integer)
+ }.should raise_error(RuntimeError)
+ end
- it "returns true if the pattern ever returns a truthy value" do
- @enum2.any?(NilClass).should == true
- pattern = EnumerableSpecs::Pattern.new { |x| 42 }
- @enum.any?(pattern).should == true
+ it "returns true if the pattern ever returns a truthy value" do
+ @enum2.any?(NilClass).should == true
+ pattern = EnumerableSpecs::Pattern.new { |x| 42 }
+ @enum.any?(pattern).should == true
- [1, 42, 3].any?(pattern).should == true
+ [1, 42, 3].any?(pattern).should == true
- pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] }
- {a: 1, b: 2}.any?(pattern).should == true
- end
+ pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] }
+ {a: 1, b: 2}.any?(pattern).should == true
+ end
- it "returns false if the block never returns other than false or nil" do
- pattern = EnumerableSpecs::Pattern.new { |x| nil }
- @enum1.any?(pattern).should == false
- pattern.yielded.should == [[0], [1], [2], [-1]]
+ it "returns false if the block never returns other than false or nil" do
+ pattern = EnumerableSpecs::Pattern.new { |x| nil }
+ @enum1.any?(pattern).should == false
+ pattern.yielded.should == [[0], [1], [2], [-1]]
- [1, 2, 3].any?(pattern).should == false
- {a: 1}.any?(pattern).should == false
- end
+ [1, 2, 3].any?(pattern).should == false
+ {a: 1}.any?(pattern).should == false
+ end
- it "does not hide exceptions out of pattern#===" do
- pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
- -> {
- @enum.any?(pattern)
- }.should raise_error(RuntimeError)
- end
+ it "does not hide exceptions out of pattern#===" do
+ pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
+ -> {
+ @enum.any?(pattern)
+ }.should raise_error(RuntimeError)
+ end
- it "calls the pattern with gathered array when yielded with multiple arguments" do
- multi = EnumerableSpecs::YieldsMulti.new
- pattern = EnumerableSpecs::Pattern.new { false }
- multi.any?(pattern).should == false
- pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
- end
+ it "calls the pattern with gathered array when yielded with multiple arguments" do
+ multi = EnumerableSpecs::YieldsMulti.new
+ pattern = EnumerableSpecs::Pattern.new { false }
+ multi.any?(pattern).should == false
+ pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
end
end
end
diff --git a/spec/ruby/core/enumerable/first_spec.rb b/spec/ruby/core/enumerable/first_spec.rb
index ed1ba599b4..1398807fa7 100644
--- a/spec/ruby/core/enumerable/first_spec.rb
+++ b/spec/ruby/core/enumerable/first_spec.rb
@@ -17,7 +17,7 @@ describe "Enumerable#first" do
EnumerableSpecs::YieldsMixed2.new.to_enum.first.should == nil
end
- it "raises a RangeError when passed a Bignum" do
+ it "raises a RangeError when passed an Integer" do
enum = EnumerableSpecs::Empty.new
-> { enum.first(bignum_value) }.should raise_error(RangeError)
end
diff --git a/spec/ruby/core/enumerable/fixtures/classes.rb b/spec/ruby/core/enumerable/fixtures/classes.rb
index 5051196742..fb4951c6e6 100644
--- a/spec/ruby/core/enumerable/fixtures/classes.rb
+++ b/spec/ruby/core/enumerable/fixtures/classes.rb
@@ -251,7 +251,7 @@ module EnumerableSpecs
end
end
- class ComparableWithFixnum
+ class ComparableWithInteger
include Comparable
def initialize(num)
@num = num
diff --git a/spec/ruby/core/enumerable/grep_spec.rb b/spec/ruby/core/enumerable/grep_spec.rb
index c9c0f34e27..4e66bb85ea 100644
--- a/spec/ruby/core/enumerable/grep_spec.rb
+++ b/spec/ruby/core/enumerable/grep_spec.rb
@@ -40,15 +40,25 @@ describe "Enumerable#grep" do
$~.should == nil
end
- it "sets $~ to the last match when given no block" do
- "z" =~ /z/ # Reset $~
- ["abc", "def"].grep(/b/).should == ["abc"]
+ ruby_version_is ""..."3.0.0" do
+ it "sets $~ to the last match when given no block" do
+ "z" =~ /z/ # Reset $~
+ ["abc", "def"].grep(/b/).should == ["abc"]
- # Set by the failed match of "def"
- $~.should == nil
+ # Set by the failed match of "def"
+ $~.should == nil
- ["abc", "def"].grep(/e/)
- $&.should == "e"
+ ["abc", "def"].grep(/e/)
+ $&.should == "e"
+ end
+ end
+
+ ruby_version_is "3.0.0" do
+ it "does not set $~ when given no block" do
+ "z" =~ /z/ # Reset $~
+ ["abc", "def"].grep(/b/).should == ["abc"]
+ $&.should == "z"
+ end
end
describe "with a block" do
diff --git a/spec/ruby/core/enumerable/grep_v_spec.rb b/spec/ruby/core/enumerable/grep_v_spec.rb
index 6dec487065..8cae3ac618 100644
--- a/spec/ruby/core/enumerable/grep_v_spec.rb
+++ b/spec/ruby/core/enumerable/grep_v_spec.rb
@@ -20,15 +20,25 @@ describe "Enumerable#grep_v" do
$&.should == "e"
end
- it "sets $~ to the last match when given no block" do
- "z" =~ /z/ # Reset $~
- ["abc", "def"].grep_v(/e/).should == ["abc"]
+ ruby_version_is ""..."3.0.0" do
+ it "sets $~ to the last match when given no block" do
+ "z" =~ /z/ # Reset $~
+ ["abc", "def"].grep_v(/e/).should == ["abc"]
- # Set by the match of "def"
- $&.should == "e"
+ # Set by the match of "def"
+ $&.should == "e"
- ["abc", "def"].grep_v(/b/)
- $&.should == nil
+ ["abc", "def"].grep_v(/b/)
+ $&.should == nil
+ end
+ end
+
+ ruby_version_is "3.0.0" do
+ it "does not set $~ when given no block" do
+ "z" =~ /z/ # Reset $~
+ ["abc", "def"].grep_v(/e/).should == ["abc"]
+ $&.should == "z"
+ end
end
describe "without block" do
diff --git a/spec/ruby/core/enumerable/minmax_spec.rb b/spec/ruby/core/enumerable/minmax_spec.rb
index 29f1ecf82c..f5f17ef079 100644
--- a/spec/ruby/core/enumerable/minmax_spec.rb
+++ b/spec/ruby/core/enumerable/minmax_spec.rb
@@ -1,41 +1,17 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../../shared/enumerable/minmax'
describe "Enumerable#minmax" do
before :each do
@enum = EnumerableSpecs::Numerous.new(6, 4, 5, 10, 8)
-
+ @empty_enum = EnumerableSpecs::Empty.new
+ @incomparable_enum = EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new)
+ @incompatible_enum = EnumerableSpecs::Numerous.new(11,"22")
@strs = EnumerableSpecs::Numerous.new("333", "2", "60", "55555", "1010", "111")
end
- it "min should return the minimum element" do
- @enum.minmax.should == [4, 10]
- @strs.minmax.should == ["1010", "60" ]
- end
-
- it "returns [nil, nil] for an empty Enumerable" do
- EnumerableSpecs::Empty.new.minmax.should == [nil, nil]
- end
-
- it "raises an ArgumentError when elements are incomparable" do
- -> do
- EnumerableSpecs::Numerous.new(11,"22").minmax
- end.should raise_error(ArgumentError)
- -> do
- EnumerableSpecs::Numerous.new(11,12,22,33).minmax{|a, b| nil}
- end.should raise_error(ArgumentError)
- end
-
- it "raises a NoMethodError for elements without #<=>" do
- -> do
- EnumerableSpecs::Numerous.new(BasicObject.new, BasicObject.new).minmax
- end.should raise_error(NoMethodError)
- end
-
- it "returns the minimum when using a block rule" do
- @enum.minmax {|a,b| b <=> a }.should == [10, 4]
- @strs.minmax {|a,b| a.length <=> b.length }.should == ["2", "55555"]
- end
+ it_behaves_like :enumerable_minmax, :minmax
it "gathers whole arrays as elements when each yields multiple" do
multi = EnumerableSpecs::YieldsMulti.new
diff --git a/spec/ruby/core/enumerable/none_spec.rb b/spec/ruby/core/enumerable/none_spec.rb
index 7c17e58a13..ec48eaf0a7 100644
--- a/spec/ruby/core/enumerable/none_spec.rb
+++ b/spec/ruby/core/enumerable/none_spec.rb
@@ -10,7 +10,7 @@ describe "Enumerable#none?" do
end
it "always returns true on empty enumeration" do
- @empty.none?.should == true
+ @empty.should.none?
@empty.none? { true }.should == true
end
@@ -20,15 +20,6 @@ describe "Enumerable#none?" do
-> { {}.none?(1, 2, 3) }.should raise_error(ArgumentError)
end
- ruby_version_is ""..."2.5" do
- it "raises an ArgumentError when any arguments provided" do
- -> { @enum.none?(Proc.new {}) }.should raise_error(ArgumentError)
- -> { @enum.none?(nil) }.should raise_error(ArgumentError)
- -> { @empty.none?(1) }.should raise_error(ArgumentError)
- -> { @enum.none?(1) {} }.should raise_error(ArgumentError)
- end
- end
-
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.none?
@@ -102,66 +93,64 @@ describe "Enumerable#none?" do
end
end
- ruby_version_is "2.5" do
- describe 'when given a pattern argument' do
- it "calls `===` on the pattern the return value " do
- pattern = EnumerableSpecs::Pattern.new { |x| x == 3 }
- @enum1.none?(pattern).should == true
- pattern.yielded.should == [[0], [1], [2], [-1]]
- end
+ describe 'when given a pattern argument' do
+ it "calls `===` on the pattern the return value " do
+ pattern = EnumerableSpecs::Pattern.new { |x| x == 3 }
+ @enum1.none?(pattern).should == true
+ pattern.yielded.should == [[0], [1], [2], [-1]]
+ end
- # may raise an exception in future versions
- ruby_version_is ""..."2.6" do
- it "ignores block" do
- @enum2.none?(Integer) { raise }.should == true
- [1, 2, nil].none?(TrueClass) { raise }.should == true
- {a: 1}.none?(Hash) { raise }.should == true
- end
+ # may raise an exception in future versions
+ ruby_version_is ""..."2.6" do
+ it "ignores block" do
+ @enum2.none?(Integer) { raise }.should == true
+ [1, 2, nil].none?(TrueClass) { raise }.should == true
+ {a: 1}.none?(Hash) { raise }.should == true
end
+ end
- it "always returns true on empty enumeration" do
- @empty.none?(Integer).should == true
- [].none?(Integer).should == true
- {}.none?(NilClass).should == true
- end
+ it "always returns true on empty enumeration" do
+ @empty.none?(Integer).should == true
+ [].none?(Integer).should == true
+ {}.none?(NilClass).should == true
+ end
- it "does not hide exceptions out of #each" do
- -> {
- EnumerableSpecs::ThrowingEach.new.none?(Integer)
- }.should raise_error(RuntimeError)
- end
+ it "does not hide exceptions out of #each" do
+ -> {
+ EnumerableSpecs::ThrowingEach.new.none?(Integer)
+ }.should raise_error(RuntimeError)
+ end
- it "returns true if the pattern never returns a truthy value" do
- @enum2.none?(Integer).should == true
- pattern = EnumerableSpecs::Pattern.new { |x| nil }
- @enum.none?(pattern).should == true
+ it "returns true if the pattern never returns a truthy value" do
+ @enum2.none?(Integer).should == true
+ pattern = EnumerableSpecs::Pattern.new { |x| nil }
+ @enum.none?(pattern).should == true
- [1, 42, 3].none?(pattern).should == true
- {a: 1, b: 2}.none?(pattern).should == true
- end
+ [1, 42, 3].none?(pattern).should == true
+ {a: 1, b: 2}.none?(pattern).should == true
+ end
- it "returns false if the pattern ever returns other than false or nil" do
- pattern = EnumerableSpecs::Pattern.new { |x| x < 0 }
- @enum1.none?(pattern).should == false
- pattern.yielded.should == [[0], [1], [2], [-1]]
+ it "returns false if the pattern ever returns other than false or nil" do
+ pattern = EnumerableSpecs::Pattern.new { |x| x < 0 }
+ @enum1.none?(pattern).should == false
+ pattern.yielded.should == [[0], [1], [2], [-1]]
- [1, 2, 3, -1].none?(pattern).should == false
- {a: 1}.none?(Array).should == false
- end
+ [1, 2, 3, -1].none?(pattern).should == false
+ {a: 1}.none?(Array).should == false
+ end
- it "does not hide exceptions out of pattern#===" do
- pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
- -> {
- @enum.none?(pattern)
- }.should raise_error(RuntimeError)
- end
+ it "does not hide exceptions out of pattern#===" do
+ pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
+ -> {
+ @enum.none?(pattern)
+ }.should raise_error(RuntimeError)
+ end
- it "calls the pattern with gathered array when yielded with multiple arguments" do
- multi = EnumerableSpecs::YieldsMulti.new
- pattern = EnumerableSpecs::Pattern.new { false }
- multi.none?(pattern).should == true
- pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
- end
+ it "calls the pattern with gathered array when yielded with multiple arguments" do
+ multi = EnumerableSpecs::YieldsMulti.new
+ pattern = EnumerableSpecs::Pattern.new { false }
+ multi.none?(pattern).should == true
+ pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
end
end
end
diff --git a/spec/ruby/core/enumerable/one_spec.rb b/spec/ruby/core/enumerable/one_spec.rb
index 2ae8b3efa4..6489c84742 100644
--- a/spec/ruby/core/enumerable/one_spec.rb
+++ b/spec/ruby/core/enumerable/one_spec.rb
@@ -10,7 +10,7 @@ describe "Enumerable#one?" do
end
it "always returns false on empty enumeration" do
- @empty.one?.should == false
+ @empty.should_not.one?
@empty.one? { true }.should == false
end
@@ -20,15 +20,6 @@ describe "Enumerable#one?" do
-> { {}.one?(1, 2, 3) }.should raise_error(ArgumentError)
end
- ruby_version_is ""..."2.5" do
- it "raises an ArgumentError when any arguments provided" do
- -> { @enum.one?(Proc.new {}) }.should raise_error(ArgumentError)
- -> { @enum.one?(nil) }.should raise_error(ArgumentError)
- -> { @empty.one?(1) }.should raise_error(ArgumentError)
- -> { @enum.one?(1) {} }.should raise_error(ArgumentError)
- end
- end
-
it "does not hide exceptions out of #each" do
-> {
EnumerableSpecs::ThrowingEach.new.one?
@@ -93,77 +84,75 @@ describe "Enumerable#one?" do
end
- ruby_version_is "2.5" do
- describe 'when given a pattern argument' do
- it "calls `===` on the pattern the return value " do
- pattern = EnumerableSpecs::Pattern.new { |x| x == 1 }
- @enum1.one?(pattern).should == true
- pattern.yielded.should == [[0], [1], [2], [-1]]
- end
+ describe 'when given a pattern argument' do
+ it "calls `===` on the pattern the return value " do
+ pattern = EnumerableSpecs::Pattern.new { |x| x == 1 }
+ @enum1.one?(pattern).should == true
+ pattern.yielded.should == [[0], [1], [2], [-1]]
+ end
- # may raise an exception in future versions
- ruby_version_is ""..."2.6" do
- it "ignores block" do
- @enum2.one?(NilClass) { raise }.should == true
- [1, 2, nil].one?(NilClass) { raise }.should == true
- {a: 1}.one?(Array) { raise }.should == true
- end
+ # may raise an exception in future versions
+ ruby_version_is ""..."2.6" do
+ it "ignores block" do
+ @enum2.one?(NilClass) { raise }.should == true
+ [1, 2, nil].one?(NilClass) { raise }.should == true
+ {a: 1}.one?(Array) { raise }.should == true
end
+ end
- it "always returns false on empty enumeration" do
- @empty.one?(Integer).should == false
- [].one?(Integer).should == false
- {}.one?(NilClass).should == false
- end
+ it "always returns false on empty enumeration" do
+ @empty.one?(Integer).should == false
+ [].one?(Integer).should == false
+ {}.one?(NilClass).should == false
+ end
- it "does not hide exceptions out of #each" do
- -> {
- EnumerableSpecs::ThrowingEach.new.one?(Integer)
- }.should raise_error(RuntimeError)
- end
+ it "does not hide exceptions out of #each" do
+ -> {
+ EnumerableSpecs::ThrowingEach.new.one?(Integer)
+ }.should raise_error(RuntimeError)
+ end
- it "returns true if the pattern returns a truthy value only once" do
- @enum2.one?(NilClass).should == true
- pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
- @enum1.one?(pattern).should == true
+ it "returns true if the pattern returns a truthy value only once" do
+ @enum2.one?(NilClass).should == true
+ pattern = EnumerableSpecs::Pattern.new { |x| x == 2 }
+ @enum1.one?(pattern).should == true
- [1, 2, 42, 3].one?(pattern).should == true
+ [1, 2, 42, 3].one?(pattern).should == true
- pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] }
- {a: 1, b: 2}.one?(pattern).should == true
- end
+ pattern = EnumerableSpecs::Pattern.new { |x| x == [:b, 2] }
+ {a: 1, b: 2}.one?(pattern).should == true
+ end
- it "returns false if the pattern returns a truthy value more than once" do
- pattern = EnumerableSpecs::Pattern.new { |x| !x }
- @enum2.one?(pattern).should == false
- pattern.yielded.should == [[nil], [false]]
+ it "returns false if the pattern returns a truthy value more than once" do
+ pattern = EnumerableSpecs::Pattern.new { |x| !x }
+ @enum2.one?(pattern).should == false
+ pattern.yielded.should == [[nil], [false]]
- [1, 2, 3].one?(Integer).should == false
- {a: 1, b: 2}.one?(Array).should == false
- end
+ [1, 2, 3].one?(Integer).should == false
+ {a: 1, b: 2}.one?(Array).should == false
+ end
- it "returns false if the pattern never returns a truthy value" do
- pattern = EnumerableSpecs::Pattern.new { |x| nil }
- @enum1.one?(pattern).should == false
- pattern.yielded.should == [[0], [1], [2], [-1]]
+ it "returns false if the pattern never returns a truthy value" do
+ pattern = EnumerableSpecs::Pattern.new { |x| nil }
+ @enum1.one?(pattern).should == false
+ pattern.yielded.should == [[0], [1], [2], [-1]]
- [1, 2, 3].one?(pattern).should == false
- {a: 1}.one?(pattern).should == false
- end
+ [1, 2, 3].one?(pattern).should == false
+ {a: 1}.one?(pattern).should == false
+ end
- it "does not hide exceptions out of pattern#===" do
- pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
- -> {
- @enum.one?(pattern)
- }.should raise_error(RuntimeError)
- end
+ it "does not hide exceptions out of pattern#===" do
+ pattern = EnumerableSpecs::Pattern.new { raise "from pattern" }
+ -> {
+ @enum.one?(pattern)
+ }.should raise_error(RuntimeError)
+ end
- it "calls the pattern with gathered array when yielded with multiple arguments" do
- multi = EnumerableSpecs::YieldsMulti.new
- pattern = EnumerableSpecs::Pattern.new { false }
- multi.one?(pattern).should == false
- pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
- end
+ it "calls the pattern with gathered array when yielded with multiple arguments" do
+ multi = EnumerableSpecs::YieldsMulti.new
+ pattern = EnumerableSpecs::Pattern.new { false }
+ multi.one?(pattern).should == false
+ pattern.yielded.should == [[[1, 2]], [[3, 4, 5]], [[6, 7, 8, 9]]]
end
end
end
diff --git a/spec/ruby/core/enumerable/shared/collect.rb b/spec/ruby/core/enumerable/shared/collect.rb
index 05e94777c7..71b8acd526 100644
--- a/spec/ruby/core/enumerable/shared/collect.rb
+++ b/spec/ruby/core/enumerable/shared/collect.rb
@@ -34,5 +34,35 @@ describe :enumerable_collect, shared: true do
enum.each { |i| -i }.should == [-2, -5, -3, -6, -1, -4]
end
+ it "reports the same arity as the given block" do
+ entries = [0, 1, 3, 4, 5, 6]
+ numerous = EnumerableSpecs::Numerous.new(*entries)
+
+ def numerous.each(&block)
+ ScratchPad << block.arity
+ super
+ end
+
+ numerous.send(@method) { |a, b| a % 2 }.should == [0, 1, 1, 0, 1, 0]
+ ScratchPad.recorded.should == [2]
+ ScratchPad.clear
+ ScratchPad.record []
+ numerous.send(@method) { |i| i }.should == entries
+ ScratchPad.recorded.should == [1]
+ end
+
+ it "yields 2 arguments for a Hash" do
+ c = Class.new do
+ def register(a, b)
+ ScratchPad << [a, b]
+ end
+ end
+ m = c.new.method(:register)
+
+ ScratchPad.record []
+ { 1 => 'a', 2 => 'b' }.map(&m)
+ ScratchPad.recorded.should == [[1, 'a'], [2, 'b']]
+ end
+
it_should_behave_like :enumerable_enumeratorized_with_origin_size
end
diff --git a/spec/ruby/core/enumerable/sort_spec.rb b/spec/ruby/core/enumerable/sort_spec.rb
index cff1a59986..6fc64f325e 100644
--- a/spec/ruby/core/enumerable/sort_spec.rb
+++ b/spec/ruby/core/enumerable/sort_spec.rb
@@ -31,7 +31,7 @@ describe "Enumerable#sort" do
it "compare values returned by block with 0" do
EnumerableSpecs::Numerous.new.sort { |n, m| -(n+m) * (n <=> m) }.should == [6, 5, 4, 3, 2, 1]
EnumerableSpecs::Numerous.new.sort { |n, m|
- EnumerableSpecs::ComparableWithFixnum.new(-(n+m) * (n <=> m))
+ EnumerableSpecs::ComparableWithInteger.new(-(n+m) * (n <=> m))
}.should == [6, 5, 4, 3, 2, 1]
-> {
EnumerableSpecs::Numerous.new.sort { |n, m| (n <=> m).to_s }
diff --git a/spec/ruby/core/enumerable/uniq_spec.rb b/spec/ruby/core/enumerable/uniq_spec.rb
index 82c041d4ef..e58dd36366 100644
--- a/spec/ruby/core/enumerable/uniq_spec.rb
+++ b/spec/ruby/core/enumerable/uniq_spec.rb
@@ -79,8 +79,8 @@ describe 'Enumerable#uniq' do
end
a.uniq.should == a
- a[0].tainted?.should == true
- a[1].tainted?.should == true
+ a[0].should.tainted?
+ a[1].should.tainted?
a = Array.new(2) do
obj = mock('0')
@@ -98,8 +98,8 @@ describe 'Enumerable#uniq' do
end
a.to_enum.uniq.size.should == 1
- a[0].tainted?.should == true
- a[1].tainted?.should == true
+ a[0].should.tainted?
+ a[1].should.tainted?
end
end
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb
index 8ce0ce0cd9..5be189e993 100644
--- a/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/exclude_end_spec.rb
@@ -4,15 +4,15 @@ ruby_version_is "2.6" do
describe "Enumerator::ArithmeticSequence#exclude_end?" do
context "when created using Numeric#step" do
it "always returns false" do
- 1.step(10).exclude_end?.should == false
- 10.step(1).exclude_end?.should == false
+ 1.step(10).should_not.exclude_end?
+ 10.step(1).should_not.exclude_end?
end
end
context "when created using Range#step" do
it "mirrors range.exclude_end?" do
- (1...10).step.exclude_end?.should == true
- (1..10).step.exclude_end?.should == false
+ (1...10).step.should.exclude_end?
+ (1..10).step.should_not.exclude_end?
end
end
end
diff --git a/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb b/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb
index 20a5cb6e7b..8b00fd4309 100644
--- a/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb
+++ b/spec/ruby/core/enumerator/arithmetic_sequence/step_spec.rb
@@ -5,11 +5,9 @@ ruby_version_is "2.6" do
it "returns the original value given to step method" do
(1..10).step.step.should == 1
(1..10).step(3).step.should == 3
- (1..10).step(0).step.should == 0
1.step(10).step.should == 1
1.step(10, 3).step.should == 3
- 1.step(10, 0).step.should == 0
end
end
end
diff --git a/spec/ruby/core/enumerator/each_spec.rb b/spec/ruby/core/enumerator/each_spec.rb
index d88c09cdb5..99ac3120af 100644
--- a/spec/ruby/core/enumerator/each_spec.rb
+++ b/spec/ruby/core/enumerator/each_spec.rb
@@ -40,10 +40,10 @@ describe "Enumerator#each" do
end
it "calls the method given in the constructor until it's exhausted" do
- each = mock('each')
- each.should_receive(:each).and_yield(1).and_yield(2).and_yield(3)
+ each = mock('peach')
+ each.should_receive(:peach).and_yield(1).and_yield(2).and_yield(3)
acc = []
- each.to_enum.each {|e| acc << e }
+ each.to_enum(:peach).each {|e| acc << e }
acc.should == [1,2,3]
end
diff --git a/spec/ruby/core/enumerator/initialize_spec.rb b/spec/ruby/core/enumerator/initialize_spec.rb
index 53bf5d4ef2..113bbf9957 100644
--- a/spec/ruby/core/enumerator/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/initialize_spec.rb
@@ -11,8 +11,10 @@ describe "Enumerator#initialize" do
Enumerator.should have_private_instance_method(:initialize, false)
end
- it "returns self when given an object" do
- @uninitialized.send(:initialize, Object.new).should equal(@uninitialized)
+ ruby_version_is ''...'3.0' do
+ it "returns self when given an object" do
+ @uninitialized.send(:initialize, Object.new).should equal(@uninitialized)
+ end
end
it "returns self when given a block" do
@@ -43,7 +45,7 @@ describe "Enumerator#initialize" do
@uninitialized.send(:initialize, Float::INFINITY) {}.size.should equal(Float::INFINITY)
end
- it "sets size to the given size if the given size is a Fixnum" do
+ it "sets size to the given size if the given size is an Integer" do
@uninitialized.send(:initialize, 100) {}.size.should == 100
end
diff --git a/spec/ruby/core/enumerator/lazy/eager_spec.rb b/spec/ruby/core/enumerator/lazy/eager_spec.rb
new file mode 100644
index 0000000000..30ba2dfe0e
--- /dev/null
+++ b/spec/ruby/core/enumerator/lazy/eager_spec.rb
@@ -0,0 +1,29 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "2.7" do
+ describe "Enumerator::Lazy#eager" do
+ it "returns a non-lazy Enumerator converted from the lazy enumerator" do
+ enum = [1, 2, 3].lazy
+
+ enum.class.should == Enumerator::Lazy
+ enum.eager.class.should == Enumerator
+ end
+
+ it "does not enumerate an enumerator" do
+ ScratchPad.record []
+
+ sequence = [1, 2, 3]
+ enum_lazy = Enumerator::Lazy.new(sequence) do |yielder, value|
+ yielder << value
+ ScratchPad << value
+ end
+
+ ScratchPad.recorded.should == []
+ enum = enum_lazy.eager
+ ScratchPad.recorded.should == []
+
+ enum.map { |i| i }.should == [1, 2, 3]
+ ScratchPad.recorded.should == [1, 2, 3]
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/lazy/initialize_spec.rb b/spec/ruby/core/enumerator/lazy/initialize_spec.rb
index 88c66530b9..f23018d010 100644
--- a/spec/ruby/core/enumerator/lazy/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/initialize_spec.rb
@@ -43,7 +43,7 @@ describe "Enumerator::Lazy#initialize" do
@uninitialized.send(:initialize, @receiver, Float::INFINITY) {}.size.should equal(Float::INFINITY)
end
- it "sets given size to own size if the given size is a Fixnum" do
+ it "sets given size to own size if the given size is an Integer" do
@uninitialized.send(:initialize, @receiver, 100) {}.size.should == 100
end
diff --git a/spec/ruby/core/enumerator/new_spec.rb b/spec/ruby/core/enumerator/new_spec.rb
index 170809dbc1..9aea9fdd17 100644
--- a/spec/ruby/core/enumerator/new_spec.rb
+++ b/spec/ruby/core/enumerator/new_spec.rb
@@ -1,41 +1,120 @@
require_relative '../../spec_helper'
describe "Enumerator.new" do
- it "creates a new custom enumerator with the given object, iterator and arguments" do
- enum = Enumerator.new(1, :upto, 3)
- enum.should be_an_instance_of(Enumerator)
- end
+ context "no block given" do
+ ruby_version_is '3.0' do
+ it "raises" do
+ -> { Enumerator.new(1, :upto, 3) }.should raise_error(ArgumentError)
+ end
+ end
- it "creates a new custom enumerator that responds to #each" do
- enum = Enumerator.new(1, :upto, 3)
- enum.respond_to?(:each).should == true
- end
+ ruby_version_is ''...'3.0' do
+ it "creates a new custom enumerator with the given object, iterator and arguments" do
+ enum = Enumerator.new(1, :upto, 3)
+ enum.should be_an_instance_of(Enumerator)
+ end
- it "creates a new custom enumerator that runs correctly" do
- Enumerator.new(1, :upto, 3).map{|x|x}.should == [1,2,3]
- end
+ it "creates a new custom enumerator that responds to #each" do
+ enum = Enumerator.new(1, :upto, 3)
+ enum.respond_to?(:each).should == true
+ end
- it "aliases the second argument to :each" do
- Enumerator.new(1..2).to_a.should == Enumerator.new(1..2, :each).to_a
- end
+ it "creates a new custom enumerator that runs correctly" do
+ Enumerator.new(1, :upto, 3).map{|x|x}.should == [1,2,3]
+ end
- it "doesn't check for the presence of the iterator method" do
- Enumerator.new(nil).should be_an_instance_of(Enumerator)
+ it "aliases the second argument to :each" do
+ Enumerator.new(1..2).to_a.should == Enumerator.new(1..2, :each).to_a
+ end
+
+ it "doesn't check for the presence of the iterator method" do
+ Enumerator.new(nil).should be_an_instance_of(Enumerator)
+ end
+
+ it "uses the latest define iterator method" do
+ class StrangeEach
+ def each
+ yield :foo
+ end
+ end
+ enum = Enumerator.new(StrangeEach.new)
+ enum.to_a.should == [:foo]
+ class StrangeEach
+ def each
+ yield :bar
+ end
+ end
+ enum.to_a.should == [:bar]
+ end
+ end
end
- it "uses the latest define iterator method" do
- class StrangeEach
- def each
- yield :foo
+ context "when passed a block" do
+ it "defines iteration with block, yielder argument and calling << method" do
+ enum = Enumerator.new do |yielder|
+ a = 1
+
+ loop do
+ yielder << a
+ a = a + 1
+ end
end
+
+ enum.take(3).should == [1, 2, 3]
end
- enum = Enumerator.new(StrangeEach.new)
- enum.to_a.should == [:foo]
- class StrangeEach
- def each
- yield :bar
+
+ it "defines iteration with block, yielder argument and calling yield method" do
+ enum = Enumerator.new do |yielder|
+ a = 1
+
+ loop do
+ yielder.yield(a)
+ a = a + 1
+ end
+ end
+
+ enum.take(3).should == [1, 2, 3]
+ end
+
+ ruby_version_is "2.7" do
+ it "defines iteration with block, yielder argument and treating it as a proc" do
+ enum = Enumerator.new do |yielder|
+ "a\nb\nc".each_line(&yielder)
+ end
+
+ enum.to_a.should == ["a\n", "b\n", "c"]
+ end
+ end
+
+ describe 'yielded values' do
+ it 'handles yield arguments properly' do
+ Enumerator.new { |y| y.yield(1) }.to_a.should == [1]
+ Enumerator.new { |y| y.yield(1) }.first.should == 1
+
+ Enumerator.new { |y| y.yield([1]) }.to_a.should == [[1]]
+ Enumerator.new { |y| y.yield([1]) }.first.should == [1]
+
+ Enumerator.new { |y| y.yield(1, 2) }.to_a.should == [[1, 2]]
+ Enumerator.new { |y| y.yield(1, 2) }.first.should == [1, 2]
+
+ Enumerator.new { |y| y.yield([1, 2]) }.to_a.should == [[1, 2]]
+ Enumerator.new { |y| y.yield([1, 2]) }.first.should == [1, 2]
+ end
+
+ it 'handles << arguments properly' do
+ Enumerator.new { |y| y.<<(1) }.to_a.should == [1]
+ Enumerator.new { |y| y.<<(1) }.first.should == 1
+
+ Enumerator.new { |y| y.<<([1]) }.to_a.should == [[1]]
+ Enumerator.new { |y| y.<<([1]) }.first.should == [1]
+
+ # << doesn't accept multiple arguments
+ # Enumerator.new { |y| y.<<(1, 2) }.to_a.should == [[1, 2]]
+ # Enumerator.new { |y| y.<<(1, 2) }.first.should == [1, 2]
+
+ Enumerator.new { |y| y.<<([1, 2]) }.to_a.should == [[1, 2]]
+ Enumerator.new { |y| y.<<([1, 2]) }.first.should == [1, 2]
end
end
- enum.to_a.should == [:bar]
end
end
diff --git a/spec/ruby/core/enumerator/next_spec.rb b/spec/ruby/core/enumerator/next_spec.rb
index 3e9ed8b015..a5e01a399d 100644
--- a/spec/ruby/core/enumerator/next_spec.rb
+++ b/spec/ruby/core/enumerator/next_spec.rb
@@ -24,4 +24,15 @@ describe "Enumerator#next" do
@enum.rewind
@enum.next.should == 1
end
+
+ it "restarts the enumerator if an exception terminated a previous iteration" do
+ exception = StandardError.new
+ enum = Enumerator.new do
+ raise exception
+ end
+
+ result = 2.times.map { enum.next rescue $! }
+
+ result.should == [exception, exception]
+ end
end
diff --git a/spec/ruby/core/enumerator/produce_spec.rb b/spec/ruby/core/enumerator/produce_spec.rb
new file mode 100644
index 0000000000..f6f1dcd429
--- /dev/null
+++ b/spec/ruby/core/enumerator/produce_spec.rb
@@ -0,0 +1,36 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "2.7" do
+ describe "Enumerator.produce" do
+ it "creates an infinite enumerator" do
+ enum = Enumerator.produce(0) { |prev| prev + 1 }
+ enum.take(5).should == [0, 1, 2, 3, 4]
+ end
+
+ it "terminates iteration when block raises StopIteration exception" do
+ enum = Enumerator.produce(0) do | prev|
+ raise StopIteration if prev >= 2
+ prev + 1
+ end
+
+ enum.to_a.should == [0, 1, 2]
+ end
+
+ context "when initial value skipped" do
+ it "uses nil instead" do
+ ScratchPad.record []
+ enum = Enumerator.produce { |prev| ScratchPad << prev; (prev || 0) + 1 }
+
+ enum.take(3).should == [1, 2, 3]
+ ScratchPad.recorded.should == [nil, 1, 2]
+ end
+
+ it "starts enumerable from result of first block call" do
+ array = "a\nb\nc\nd".lines
+ lines = Enumerator.produce { array.shift }.take_while { |s| s }
+
+ lines.should == ["a\n", "b\n", "c\n", "d"]
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/yielder/append_spec.rb b/spec/ruby/core/enumerator/yielder/append_spec.rb
index dac66585a5..7f7059774d 100644
--- a/spec/ruby/core/enumerator/yielder/append_spec.rb
+++ b/spec/ruby/core/enumerator/yielder/append_spec.rb
@@ -21,4 +21,27 @@ describe "Enumerator::Yielder#<<" do
y = Enumerator::Yielder.new {|x| x + 1}
(y << 1).should equal(y)
end
+
+ context "when multiple arguments passed" do
+ ruby_version_is '' ... '2.6' do
+ it "yields the arguments list to the block" do
+ ary = []
+ y = Enumerator::Yielder.new { |*x| ary << x }
+ y.<<(1, 2)
+
+ ary.should == [[1, 2]]
+ end
+ end
+
+ ruby_version_is '2.6' do
+ it "raises an ArgumentError" do
+ ary = []
+ y = Enumerator::Yielder.new { |*x| ary << x }
+
+ -> {
+ y.<<(1, 2)
+ }.should raise_error(ArgumentError, /wrong number of arguments/)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/enumerator/yielder/to_proc_spec.rb b/spec/ruby/core/enumerator/yielder/to_proc_spec.rb
new file mode 100644
index 0000000000..0ed1645853
--- /dev/null
+++ b/spec/ruby/core/enumerator/yielder/to_proc_spec.rb
@@ -0,0 +1,18 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "2.7" do
+ describe "Enumerator::Yielder#to_proc" do
+ it "returns a Proc object that takes an argument and yields it to the block" do
+ ScratchPad.record []
+ y = Enumerator::Yielder.new { |*args| ScratchPad << args; "foobar" }
+
+ callable = y.to_proc
+ callable.class.should == Proc
+
+ result = callable.call(1, 2)
+ ScratchPad.recorded.should == [[1, 2]]
+
+ result.should == "foobar"
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/yielder/yield_spec.rb b/spec/ruby/core/enumerator/yielder/yield_spec.rb
index 58fc8e007a..acfdf114b6 100644
--- a/spec/ruby/core/enumerator/yielder/yield_spec.rb
+++ b/spec/ruby/core/enumerator/yielder/yield_spec.rb
@@ -20,4 +20,14 @@ describe "Enumerator::Yielder#yield" do
y = Enumerator::Yielder.new {|x| x + 1}
y.yield(1).should == 2
end
+
+ context "when multiple arguments passed" do
+ it "yields the arguments list to the block" do
+ ary = []
+ y = Enumerator::Yielder.new { |*x| ary << x }
+ y.yield(1, 2)
+
+ ary.should == [[1, 2]]
+ end
+ end
end
diff --git a/spec/ruby/core/env/delete_spec.rb b/spec/ruby/core/env/delete_spec.rb
index f11860b21d..5e7891f74d 100644
--- a/spec/ruby/core/env/delete_spec.rb
+++ b/spec/ruby/core/env/delete_spec.rb
@@ -30,6 +30,13 @@ describe "ENV.delete" do
ScratchPad.recorded.should == "foo"
end
+ ruby_version_is "3.0" do
+ it "returns the result of given block if the named environment variable does not exist" do
+ ENV.delete("foo")
+ ENV.delete("foo") { |name| "bar" }.should == "bar"
+ end
+ end
+
it "does not evaluate the block if the environment variable exists" do
ENV["foo"] = "bar"
ENV.delete("foo") { |name| fail "Should not happen" }
diff --git a/spec/ruby/core/env/element_reference_spec.rb b/spec/ruby/core/env/element_reference_spec.rb
index 7d2a2d78e3..22633e7a08 100644
--- a/spec/ruby/core/env/element_reference_spec.rb
+++ b/spec/ruby/core/env/element_reference_spec.rb
@@ -16,7 +16,7 @@ describe "ENV.[]" do
it "returns only frozen values" do
ENV[@variable] = "a non-frozen string"
- ENV[@variable].frozen?.should == true
+ ENV[@variable].should.frozen?
end
it "coerces a non-string name with #to_str" do
@@ -59,6 +59,7 @@ describe "ENV.[]" do
Encoding.default_internal = nil
locale = Encoding.find('locale')
+ locale = Encoding::UTF_8 if platform_is :windows
locale = Encoding::BINARY if locale == Encoding::US_ASCII
ENV[@variable] = "\xC3\xB8"
ENV[@variable].encoding.should == locale
diff --git a/spec/ruby/core/env/empty_spec.rb b/spec/ruby/core/env/empty_spec.rb
index 7ef17d244f..afeb406a9e 100644
--- a/spec/ruby/core/env/empty_spec.rb
+++ b/spec/ruby/core/env/empty_spec.rb
@@ -4,12 +4,12 @@ describe "ENV.empty?" do
it "returns true if the Environment is empty" do
if ENV.keys.size > 0
- ENV.empty?.should == false
+ ENV.should_not.empty?
end
orig = ENV.to_hash
begin
ENV.clear
- ENV.empty?.should == true
+ ENV.should.empty?
ensure
ENV.replace orig
end
@@ -17,7 +17,7 @@ describe "ENV.empty?" do
it "returns false if not empty" do
if ENV.keys.size > 0
- ENV.empty?.should == false
+ ENV.should_not.empty?
end
end
end
diff --git a/spec/ruby/core/env/fetch_spec.rb b/spec/ruby/core/env/fetch_spec.rb
index ef8f0a4ed3..f3af6f3dc2 100644
--- a/spec/ruby/core/env/fetch_spec.rb
+++ b/spec/ruby/core/env/fetch_spec.rb
@@ -56,7 +56,8 @@ describe "ENV.fetch" do
end
it "uses the locale encoding" do
+ encoding = platform_is(:windows) ? Encoding::UTF_8 : Encoding.find('locale')
ENV["foo"] = "bar"
- ENV.fetch("foo").encoding.should == Encoding.find('locale')
+ ENV.fetch("foo").encoding.should == encoding
end
end
diff --git a/spec/ruby/core/env/index_spec.rb b/spec/ruby/core/env/index_spec.rb
index 2457b65cc6..301a66ab4e 100644
--- a/spec/ruby/core/env/index_spec.rb
+++ b/spec/ruby/core/env/index_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
require_relative 'shared/key'
-ruby_version_is ""..."2.7" do
+ruby_version_is ''...'3.0' do
describe "ENV.index" do
it_behaves_like :env_key, :index
diff --git a/spec/ruby/core/env/shared/key.rb b/spec/ruby/core/env/shared/key.rb
index fcb3a9b8c5..93396d2aca 100644
--- a/spec/ruby/core/env/shared/key.rb
+++ b/spec/ruby/core/env/shared/key.rb
@@ -9,15 +9,23 @@ describe :env_key, shared: true do
it "returns the index associated with the passed value" do
ENV["foo"] = "bar"
- ENV.send(@method, "bar").should == "foo"
+ suppress_warning {
+ ENV.send(@method, "bar").should == "foo"
+ }
end
it "returns nil if the passed value is not found" do
ENV.delete("foo")
- ENV.send(@method, "foo").should be_nil
+ suppress_warning {
+ ENV.send(@method, "foo").should be_nil
+ }
end
it "raises TypeError if the argument is not a String and does not respond to #to_str" do
- -> { ENV.send(@method, Object.new) }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ -> {
+ suppress_warning {
+ ENV.send(@method, Object.new)
+ }
+ }.should raise_error(TypeError, "no implicit conversion of Object into String")
end
end
diff --git a/spec/ruby/core/env/shift_spec.rb b/spec/ruby/core/env/shift_spec.rb
index c03b5d50c5..49d98c3729 100644
--- a/spec/ruby/core/env/shift_spec.rb
+++ b/spec/ruby/core/env/shift_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "ENV.shift" do
it "returns a pair and deletes it" do
- ENV.empty?.should == false
+ ENV.should_not.empty?
orig = ENV.to_hash
begin
pair = ENV.shift
@@ -42,9 +42,10 @@ describe "ENV.shift" do
it "uses the locale encoding if Encoding.default_internal is nil" do
Encoding.default_internal = nil
+ encoding = platform_is(:windows) ? Encoding::UTF_8 : Encoding.find('locale')
pair = ENV.shift
- pair.first.encoding.should equal(Encoding.find("locale"))
- pair.last.encoding.should equal(Encoding.find("locale"))
+ pair.first.encoding.should equal(encoding)
+ pair.last.encoding.should equal(encoding)
end
it "transcodes from the locale encoding to Encoding.default_internal if set" do
diff --git a/spec/ruby/core/env/values_at_spec.rb b/spec/ruby/core/env/values_at_spec.rb
index ee970e5f65..87c8c7f663 100644
--- a/spec/ruby/core/env/values_at_spec.rb
+++ b/spec/ruby/core/env/values_at_spec.rb
@@ -28,7 +28,8 @@ describe "ENV.values_at" do
end
it "uses the locale encoding" do
- ENV.values_at(ENV.keys.first).first.encoding.should == Encoding.find('locale')
+ encoding = platform_is(:windows) ? Encoding::UTF_8 : Encoding.find('locale')
+ ENV.values_at(ENV.keys.first).first.encoding.should == encoding
end
it "raises TypeError when a key is not coercible to String" do
diff --git a/spec/ruby/core/exception/backtrace_spec.rb b/spec/ruby/core/exception/backtrace_spec.rb
index 2d6825180a..3f74c4cefe 100644
--- a/spec/ruby/core/exception/backtrace_spec.rb
+++ b/spec/ruby/core/exception/backtrace_spec.rb
@@ -43,7 +43,7 @@ describe "Exception#backtrace" do
# This regexp is deliberately imprecise to account for the need to abstract out
# the paths of the included mspec files and the desire to avoid specifying in any
# detail what the in `...' portion looks like.
- line.should =~ /^[^ ]+\:\d+(:in `[^`]+')?$/
+ line.should =~ /^.+:\d+:in `[^`]+'$/
end
end
diff --git a/spec/ruby/core/exception/destination_encoding_name_spec.rb b/spec/ruby/core/exception/destination_encoding_name_spec.rb
deleted file mode 100644
index a9e6474974..0000000000
--- a/spec/ruby/core/exception/destination_encoding_name_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Encoding::UndefinedConversionError#destination_encoding_name" do
- it "returns the destination encoding name" do
- ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
- begin
- ec.convert("\xa0")
- rescue Encoding::UndefinedConversionError => e
- e.destination_encoding_name.should == "EUC-JP"
- end
- end
-end
-
-describe "Encoding::InvalidByteSequenceError#destination_encoding_name" do
- it "returns the destination encoding name" do
- ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
- begin
- ec.convert("\xa0")
- rescue Encoding::InvalidByteSequenceError => e
- e.destination_encoding_name.should == "UTF-8"
- end
- end
-end
diff --git a/spec/ruby/core/exception/destination_encoding_spec.rb b/spec/ruby/core/exception/destination_encoding_spec.rb
deleted file mode 100644
index 5709c31e55..0000000000
--- a/spec/ruby/core/exception/destination_encoding_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Encoding::UndefinedConversionError#destination_encoding" do
- it "returns the destination encoding" do
- ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
- begin
- ec.convert("\xa0")
- rescue Encoding::UndefinedConversionError => e
- e.destination_encoding.should == Encoding::EUC_JP
- end
- end
-end
-
-describe "Encoding::InvalidByteSequenceError#destination_encoding" do
- it "returns the destination encoding" do
- ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
- begin
- ec.convert("\xa0")
- rescue Encoding::InvalidByteSequenceError => e
- e.destination_encoding.should == Encoding::UTF_8
- end
- end
-end
diff --git a/spec/ruby/core/exception/errno_spec.rb b/spec/ruby/core/exception/errno_spec.rb
index 9e0bf0086a..095a926e09 100644
--- a/spec/ruby/core/exception/errno_spec.rb
+++ b/spec/ruby/core/exception/errno_spec.rb
@@ -1,10 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
-describe "SystemCallError#errno" do
- it "needs to be reviewed for spec completeness"
-end
-
describe "Errno::EINVAL.new" do
it "can be called with no arguments" do
exc = Errno::EINVAL.new
@@ -46,3 +42,17 @@ describe "Errno::EAGAIN" do
end
end
end
+
+describe "Errno::ENOTSUP" do
+ it "is defined" do
+ Errno.should have_constant(:ENOTSUP)
+ end
+
+ it "is the same class as Errno::EOPNOTSUPP if they represent the same errno value" do
+ if Errno::ENOTSUP::Errno == Errno::EOPNOTSUPP::Errno
+ Errno::ENOTSUP.should == Errno::EOPNOTSUPP
+ else
+ Errno::ENOTSUP.should_not == Errno::EOPNOTSUPP
+ end
+ end
+end
diff --git a/spec/ruby/core/exception/error_bytes_spec.rb b/spec/ruby/core/exception/error_bytes_spec.rb
deleted file mode 100644
index 66dd4b62c1..0000000000
--- a/spec/ruby/core/exception/error_bytes_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Encoding::InvalidByteSequenceError#error_bytes" do
- it "returns the error bytes" do
- ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
- begin
- ec.convert("\xa0")
- rescue Encoding::InvalidByteSequenceError => e
- e.error_bytes.should == "\xA0".force_encoding("ASCII-8BIT")
- end
- end
-end
diff --git a/spec/ruby/core/exception/error_char_spec.rb b/spec/ruby/core/exception/error_char_spec.rb
deleted file mode 100644
index f95ae2a6ce..0000000000
--- a/spec/ruby/core/exception/error_char_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Encoding::UndefinedConversionError#error_char" do
- it "returns the error char" do
- ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
- begin
- ec.convert("\xa0")
- rescue Encoding::UndefinedConversionError => e
- e.error_char.should == "\u00A0"
- end
- end
-end
diff --git a/spec/ruby/core/exception/exit_value_spec.rb b/spec/ruby/core/exception/exit_value_spec.rb
index 43de56af8b..99987dd1bc 100644
--- a/spec/ruby/core/exception/exit_value_spec.rb
+++ b/spec/ruby/core/exception/exit_value_spec.rb
@@ -1,5 +1,13 @@
require_relative '../../spec_helper'
describe "LocalJumpError#exit_value" do
- it "needs to be reviewed for spec completeness"
+ def get_me_a_return
+ Proc.new { return 42 }
+ end
+
+ it "returns the value given to return" do
+ -> { get_me_a_return.call }.should raise_error(LocalJumpError) { |e|
+ e.exit_value.should == 42
+ }
+ end
end
diff --git a/spec/ruby/core/exception/frozen_error_spec.rb b/spec/ruby/core/exception/frozen_error_spec.rb
index 1b5ea71148..f27b33295c 100644
--- a/spec/ruby/core/exception/frozen_error_spec.rb
+++ b/spec/ruby/core/exception/frozen_error_spec.rb
@@ -1,13 +1,5 @@
require_relative '../../spec_helper'
-describe "FrozenError" do
- ruby_version_is "2.5" do
- it "is a subclass of RuntimeError" do
- RuntimeError.should be_ancestor_of(FrozenError)
- end
- end
-end
-
describe "FrozenError.new" do
ruby_version_is "2.7" do
it "should take optional receiver argument" do
diff --git a/spec/ruby/core/exception/full_message_spec.rb b/spec/ruby/core/exception/full_message_spec.rb
index 3df2d47f61..9cac9fb037 100644
--- a/spec/ruby/core/exception/full_message_spec.rb
+++ b/spec/ruby/core/exception/full_message_spec.rb
@@ -1,94 +1,92 @@
require_relative '../../spec_helper'
-ruby_version_is "2.5" do
- describe "Exception#full_message" do
- it "returns formatted string of exception using the same format that is used to print an uncaught exceptions to stderr" do
- e = RuntimeError.new("Some runtime error")
- e.set_backtrace(["a.rb:1", "b.rb:2"])
+describe "Exception#full_message" do
+ it "returns formatted string of exception using the same format that is used to print an uncaught exceptions to stderr" do
+ e = RuntimeError.new("Some runtime error")
+ e.set_backtrace(["a.rb:1", "b.rb:2"])
- full_message = e.full_message
- full_message.should include "RuntimeError"
- full_message.should include "Some runtime error"
- full_message.should include "a.rb:1"
- full_message.should include "b.rb:2"
- end
+ full_message = e.full_message
+ full_message.should include "RuntimeError"
+ full_message.should include "Some runtime error"
+ full_message.should include "a.rb:1"
+ full_message.should include "b.rb:2"
+ end
- ruby_version_is "2.5.1" do
- it "supports :highlight option and adds escape sequences to highlight some strings" do
- e = RuntimeError.new("Some runtime error")
+ ruby_version_is "2.5.1" do
+ it "supports :highlight option and adds escape sequences to highlight some strings" do
+ e = RuntimeError.new("Some runtime error")
- full_message = e.full_message(highlight: true, order: :bottom)
- full_message.should include "\e[1mTraceback\e[m (most recent call last)"
- full_message.should include "\e[1mSome runtime error (\e[1;4mRuntimeError\e[m\e[1m)"
+ full_message = e.full_message(highlight: true, order: :bottom)
+ full_message.should include "\e[1mTraceback\e[m (most recent call last)"
+ full_message.should include "\e[1mSome runtime error (\e[1;4mRuntimeError\e[m\e[1m)"
- full_message = e.full_message(highlight: false, order: :bottom)
- full_message.should include "Traceback (most recent call last)"
- full_message.should include "Some runtime error (RuntimeError)"
- end
+ full_message = e.full_message(highlight: false, order: :bottom)
+ full_message.should include "Traceback (most recent call last)"
+ full_message.should include "Some runtime error (RuntimeError)"
+ end
- it "supports :order option and places the error message and the backtrace at the top or the bottom" do
- e = RuntimeError.new("Some runtime error")
- e.set_backtrace(["a.rb:1", "b.rb:2"])
+ it "supports :order option and places the error message and the backtrace at the top or the bottom" do
+ e = RuntimeError.new("Some runtime error")
+ e.set_backtrace(["a.rb:1", "b.rb:2"])
- e.full_message(order: :top, highlight: false).should =~ /a.rb:1.*b.rb:2/m
- e.full_message(order: :bottom, highlight: false).should =~ /b.rb:2.*a.rb:1/m
- end
+ e.full_message(order: :top, highlight: false).should =~ /a.rb:1.*b.rb:2/m
+ e.full_message(order: :bottom, highlight: false).should =~ /b.rb:2.*a.rb:1/m
+ end
- it "shows the caller if the exception has no backtrace" do
- e = RuntimeError.new("Some runtime error")
- e.backtrace.should == nil
- full_message = e.full_message(highlight: false, order: :top)
- full_message.should include("#{__FILE__}:#{__LINE__-1}:in `")
- full_message.should include("': Some runtime error (RuntimeError)\n")
- end
+ it "shows the caller if the exception has no backtrace" do
+ e = RuntimeError.new("Some runtime error")
+ e.backtrace.should == nil
+ full_message = e.full_message(highlight: false, order: :top)
+ full_message.should include("#{__FILE__}:#{__LINE__-1}:in `")
+ full_message.should include("': Some runtime error (RuntimeError)\n")
+ end
- it "shows the exception class at the end of the first line of the message when the message contains multiple lines" do
- begin
- line = __LINE__; raise "first line\nsecond line"
- rescue => e
- full_message = e.full_message(highlight: false, order: :top).lines
- full_message[0].should include("#{__FILE__}:#{line}:in `")
- full_message[0].should include(": first line (RuntimeError)\n")
- full_message[1].should == "second line\n"
- end
+ it "shows the exception class at the end of the first line of the message when the message contains multiple lines" do
+ begin
+ line = __LINE__; raise "first line\nsecond line"
+ rescue => e
+ full_message = e.full_message(highlight: false, order: :top).lines
+ full_message[0].should include("#{__FILE__}:#{line}:in `")
+ full_message[0].should include(": first line (RuntimeError)\n")
+ full_message[1].should == "second line\n"
end
end
+ end
- ruby_version_is "2.6" do
- it "contains cause of exception" do
+ ruby_version_is "2.6" do
+ it "contains cause of exception" do
+ begin
begin
- begin
- raise 'the cause'
- rescue
- raise 'main exception'
- end
- rescue => e
- exception = e
+ raise 'the cause'
+ rescue
+ raise 'main exception'
end
-
- exception.full_message.should include "main exception"
- exception.full_message.should include "the cause"
+ rescue => e
+ exception = e
end
- it 'contains all the chain of exceptions' do
+ exception.full_message.should include "main exception"
+ exception.full_message.should include "the cause"
+ end
+
+ it 'contains all the chain of exceptions' do
+ begin
begin
begin
- begin
- raise 'origin exception'
- rescue
- raise 'intermediate exception'
- end
+ raise 'origin exception'
rescue
- raise 'last exception'
+ raise 'intermediate exception'
end
- rescue => e
- exception = e
+ rescue
+ raise 'last exception'
end
-
- exception.full_message.should include "last exception"
- exception.full_message.should include "intermediate exception"
- exception.full_message.should include "origin exception"
+ rescue => e
+ exception = e
end
+
+ exception.full_message.should include "last exception"
+ exception.full_message.should include "intermediate exception"
+ exception.full_message.should include "origin exception"
end
end
end
diff --git a/spec/ruby/core/exception/hierarchy_spec.rb b/spec/ruby/core/exception/hierarchy_spec.rb
index e52811c761..6514eb1994 100644
--- a/spec/ruby/core/exception/hierarchy_spec.rb
+++ b/spec/ruby/core/exception/hierarchy_spec.rb
@@ -37,7 +37,9 @@ describe "Exception" do
FloatDomainError => nil,
},
RegexpError => nil,
- RuntimeError => nil,
+ RuntimeError => {
+ FrozenError => nil,
+ },
SystemCallError => nil,
ThreadError => nil,
TypeError => nil,
@@ -47,9 +49,7 @@ describe "Exception" do
SystemStackError => nil,
},
}
- ruby_version_is "2.5" do
- hierarchy[Exception][StandardError][RuntimeError] = {FrozenError => nil}
- end
+
traverse = -> parent_class, parent_subclass_hash {
parent_subclass_hash.each do |child_class, child_subclass_hash|
child_class.class.should == Class
diff --git a/spec/ruby/core/exception/incomplete_input_spec.rb b/spec/ruby/core/exception/incomplete_input_spec.rb
deleted file mode 100644
index b033b33f56..0000000000
--- a/spec/ruby/core/exception/incomplete_input_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Encoding::InvalidByteSequenceError#incomplete_input?" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/exception/initialize_spec.rb b/spec/ruby/core/exception/initialize_spec.rb
deleted file mode 100644
index e724feaa39..0000000000
--- a/spec/ruby/core/exception/initialize_spec.rb
+++ /dev/null
@@ -1 +0,0 @@
-require_relative '../../spec_helper'
diff --git a/spec/ruby/core/exception/io_error_spec.rb b/spec/ruby/core/exception/io_error_spec.rb
index 8dc10cc6ce..ab8a72518f 100644
--- a/spec/ruby/core/exception/io_error_spec.rb
+++ b/spec/ruby/core/exception/io_error_spec.rb
@@ -1,11 +1,5 @@
require_relative '../../spec_helper'
-describe "IOError" do
- it "is a superclass of EOFError" do
- IOError.should be_ancestor_of(EOFError)
- end
-end
-
describe "IO::EAGAINWaitReadable" do
it "combines Errno::EAGAIN and IO::WaitReadable" do
IO::EAGAINWaitReadable.superclass.should == Errno::EAGAIN
diff --git a/spec/ruby/core/exception/key_error_spec.rb b/spec/ruby/core/exception/key_error_spec.rb
index ad280279d8..71bf2b46ff 100644
--- a/spec/ruby/core/exception/key_error_spec.rb
+++ b/spec/ruby/core/exception/key_error_spec.rb
@@ -10,6 +10,12 @@ describe "KeyError" do
error.receiver.should == receiver
error.key.should == key
+
+ error = KeyError.new("message", receiver: receiver, key: key)
+
+ error.message.should == "message"
+ error.receiver.should == receiver
+ error.key.should == key
end
end
end
diff --git a/spec/ruby/core/exception/name_error_spec.rb b/spec/ruby/core/exception/name_error_spec.rb
index d0a810029b..e901a80c42 100644
--- a/spec/ruby/core/exception/name_error_spec.rb
+++ b/spec/ruby/core/exception/name_error_spec.rb
@@ -1,11 +1,5 @@
require_relative '../../spec_helper'
-describe "NameError" do
- it "is a superclass of NoMethodError" do
- NameError.should be_ancestor_of(NoMethodError)
- end
-end
-
describe "NameError.new" do
it "should take optional name argument" do
NameError.new("msg","name").name.should == "name"
@@ -22,3 +16,15 @@ describe "NameError.new" do
end
end
end
+
+describe "NameError#dup" do
+ it "copies the name and receiver" do
+ begin
+ foo
+ rescue NameError => ne
+ name_error_dup = ne.dup
+ name_error_dup.name.should == :foo
+ name_error_dup.receiver.should == self
+ end
+ end
+end
diff --git a/spec/ruby/core/exception/name_spec.rb b/spec/ruby/core/exception/name_spec.rb
index d1def51f24..c8a49b40e2 100644
--- a/spec/ruby/core/exception/name_spec.rb
+++ b/spec/ruby/core/exception/name_spec.rb
@@ -21,9 +21,7 @@ describe "NameError#name" do
it "returns a class variable name as a symbol" do
-> {
- -> {
- @@doesnt_exist
- }.should complain(/class variable access from toplevel/)
+ eval("class singleton_class::A; @@doesnt_exist end", binding, __FILE__, __LINE__)
}.should raise_error(NameError) { |e| e.name.should == :@@doesnt_exist }
end
diff --git a/spec/ruby/core/exception/no_method_error_spec.rb b/spec/ruby/core/exception/no_method_error_spec.rb
index 28c3549562..570ffc47b1 100644
--- a/spec/ruby/core/exception/no_method_error_spec.rb
+++ b/spec/ruby/core/exception/no_method_error_spec.rb
@@ -64,7 +64,7 @@ describe "NoMethodError#message" do
NoMethodErrorSpecs::NoMethodErrorC.new.a_private_method
rescue Exception => e
e.should be_kind_of(NoMethodError)
- e.message.match(/private method/).should_not == nil
+ e.message.lines[0].should =~ /private method `a_private_method' called for #<NoMethodErrorSpecs::NoMethodErrorC:0x[\h]+>/
end
end
@@ -103,4 +103,36 @@ describe "NoMethodError#message" do
message.should include test_class.inspect
end
end
+
+ ruby_version_is "3.0" do
+ it "uses #name to display the receiver if it is a class or a module" do
+ klass = Class.new { def self.name; "MyClass"; end }
+ begin
+ klass.foo
+ rescue NoMethodError => error
+ error.message.lines.first.should == "undefined method `foo' for MyClass:Class"
+ end
+
+ mod = Module.new { def self.name; "MyModule"; end }
+ begin
+ mod.foo
+ rescue NoMethodError => error
+ error.message.lines.first.should == "undefined method `foo' for MyModule:Module"
+ end
+ end
+ end
+end
+
+describe "NoMethodError#dup" do
+ it "copies the name, arguments and receiver" do
+ begin
+ receiver = Object.new
+ receiver.foo(:one, :two)
+ rescue NoMethodError => nme
+ no_method_error_dup = nme.dup
+ no_method_error_dup.name.should == :foo
+ no_method_error_dup.receiver.should == receiver
+ no_method_error_dup.args.should == [:one, :two]
+ end
+ end
end
diff --git a/spec/ruby/core/exception/range_error_spec.rb b/spec/ruby/core/exception/range_error_spec.rb
deleted file mode 100644
index 7cfbd0f1ec..0000000000
--- a/spec/ruby/core/exception/range_error_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "RangeError" do
- it "is a superclass of FloatDomainError" do
- RangeError.should be_ancestor_of(FloatDomainError)
- end
-end
diff --git a/spec/ruby/core/exception/readagain_bytes_spec.rb b/spec/ruby/core/exception/readagain_bytes_spec.rb
deleted file mode 100644
index 0f1e24f1cf..0000000000
--- a/spec/ruby/core/exception/readagain_bytes_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Encoding::InvalidByteSequenceError#readagain_bytes" do
- it "returns the next byte" do
- begin
- "abc\xa4def".encode("ISO-8859-1", "EUC-JP")
- rescue Encoding::InvalidByteSequenceError => e
- e.error_bytes.should == "\xA4".force_encoding("ASCII-8BIT")
- e.readagain_bytes.should == 'd'
- end
- end
-end
diff --git a/spec/ruby/core/exception/reason_spec.rb b/spec/ruby/core/exception/reason_spec.rb
index 6f18aaae13..210bbc9725 100644
--- a/spec/ruby/core/exception/reason_spec.rb
+++ b/spec/ruby/core/exception/reason_spec.rb
@@ -1,5 +1,13 @@
require_relative '../../spec_helper'
describe "LocalJumpError#reason" do
- it "needs to be reviewed for spec completeness"
+ def get_me_a_return
+ Proc.new { return 42 }
+ end
+
+ it "returns 'return' for a return" do
+ -> { get_me_a_return.call }.should raise_error(LocalJumpError) { |e|
+ e.reason.should == :return
+ }
+ end
end
diff --git a/spec/ruby/core/exception/receiver_spec.rb b/spec/ruby/core/exception/receiver_spec.rb
index 7c57d63c3e..d1c23b67be 100644
--- a/spec/ruby/core/exception/receiver_spec.rb
+++ b/spec/ruby/core/exception/receiver_spec.rb
@@ -28,10 +28,8 @@ describe "NameError#receiver" do
it "returns the Object class when an undefined class variable is called" do
-> {
- -> {
- @@doesnt_exist
- }.should complain(/class variable access from toplevel/)
- }.should raise_error(NameError) {|e| e.receiver.should equal(Object) }
+ eval("class singleton_class::A; @@doesnt_exist end", binding, __FILE__, __LINE__)
+ }.should raise_error(NameError) {|e| e.receiver.should equal(singleton_class::A) }
end
it "returns a class when an undefined class variable is called in a subclass' namespace" do
diff --git a/spec/ruby/core/exception/result_spec.rb b/spec/ruby/core/exception/result_spec.rb
index 5ba26ebab1..2f12673295 100644
--- a/spec/ruby/core/exception/result_spec.rb
+++ b/spec/ruby/core/exception/result_spec.rb
@@ -1,11 +1,5 @@
require_relative '../../spec_helper'
-describe "StopIteration" do
- it "is a subclass of IndexError" do
- StopIteration.superclass.should equal(IndexError)
- end
-end
-
describe "StopIteration#result" do
before :each do
obj = Object.new
diff --git a/spec/ruby/core/exception/signm_spec.rb b/spec/ruby/core/exception/signm_spec.rb
index 8e3adcddae..4adff3b5ee 100644
--- a/spec/ruby/core/exception/signm_spec.rb
+++ b/spec/ruby/core/exception/signm_spec.rb
@@ -1,5 +1,9 @@
require_relative '../../spec_helper'
describe "SignalException#signm" do
- it "needs to be reviewed for spec completeness"
+ it "returns the signal name" do
+ -> { Process.kill(:TERM, Process.pid) }.should raise_error(SignalException) { |e|
+ e.signm.should == 'SIGTERM'
+ }
+ end
end
diff --git a/spec/ruby/core/exception/signo_spec.rb b/spec/ruby/core/exception/signo_spec.rb
index 2d04cd7805..62fc321516 100644
--- a/spec/ruby/core/exception/signo_spec.rb
+++ b/spec/ruby/core/exception/signo_spec.rb
@@ -1,5 +1,9 @@
require_relative '../../spec_helper'
describe "SignalException#signo" do
- it "needs to be reviewed for spec completeness"
+ it "returns the signal number" do
+ -> { Process.kill(:TERM, Process.pid) }.should raise_error(SignalException) { |e|
+ e.signo.should == Signal.list['TERM']
+ }
+ end
end
diff --git a/spec/ruby/core/exception/source_encoding_name_spec.rb b/spec/ruby/core/exception/source_encoding_name_spec.rb
deleted file mode 100644
index 6f5dbd01aa..0000000000
--- a/spec/ruby/core/exception/source_encoding_name_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Encoding::UndefinedConversionError#source_encoding_name" do
- it "returns the source encoding name" do
- ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
- begin
- ec.convert("\xa0")
- rescue Encoding::UndefinedConversionError => e
- e.source_encoding_name.should == "UTF-8"
- end
- end
-end
-
-describe "Encoding::InvalidByteSequenceError#source_encoding_name" do
- it "returns the source encoding name" do
- ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
- begin
- ec.convert("\xa0")
- rescue Encoding::InvalidByteSequenceError => e
- e.source_encoding_name.should == "EUC-JP"
- end
- end
-end
diff --git a/spec/ruby/core/exception/source_encoding_spec.rb b/spec/ruby/core/exception/source_encoding_spec.rb
deleted file mode 100644
index fac38e75f4..0000000000
--- a/spec/ruby/core/exception/source_encoding_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "Encoding::UndefinedConversionError#source_encoding" do
- it "returns the source encoding" do
- ec = Encoding::Converter.new("ISO-8859-1", "EUC-JP")
- begin
- ec.convert("\xa0")
- rescue Encoding::UndefinedConversionError => e
- e.source_encoding.should == Encoding::UTF_8
- end
- end
-end
-
-describe "Encoding::InvalidByteSequenceError#source_encoding" do
- it "returns the source encoding" do
- ec = Encoding::Converter.new("EUC-JP", "ISO-8859-1")
- begin
- ec.convert("\xa0")
- rescue Encoding::InvalidByteSequenceError => e
- e.source_encoding.should == Encoding::EUC_JP
- end
- end
-end
diff --git a/spec/ruby/core/exception/status_spec.rb b/spec/ruby/core/exception/status_spec.rb
index 1609bff3a5..8ace00fe10 100644
--- a/spec/ruby/core/exception/status_spec.rb
+++ b/spec/ruby/core/exception/status_spec.rb
@@ -1,5 +1,9 @@
require_relative '../../spec_helper'
describe "SystemExit#status" do
- it "needs to be reviewed for spec completeness"
+ it "returns the exit status" do
+ -> { exit 42 }.should raise_error(SystemExit) { |e|
+ e.status.should == 42
+ }
+ end
end
diff --git a/spec/ruby/core/exception/success_spec.rb b/spec/ruby/core/exception/success_spec.rb
index 82e3df92c6..6f21743340 100644
--- a/spec/ruby/core/exception/success_spec.rb
+++ b/spec/ruby/core/exception/success_spec.rb
@@ -1,5 +1,15 @@
require_relative '../../spec_helper'
describe "SystemExit#success?" do
- it "needs to be reviewed for spec completeness"
+ it "returns true if the process exited successfully" do
+ -> { exit 0 }.should raise_error(SystemExit) { |e|
+ e.should.success?
+ }
+ end
+
+ it "returns false if the process exited unsuccessfully" do
+ -> { exit(-1) }.should raise_error(SystemExit) { |e|
+ e.should_not.success?
+ }
+ end
end
diff --git a/spec/ruby/core/exception/system_call_error_spec.rb b/spec/ruby/core/exception/system_call_error_spec.rb
index c510ae440f..73167bc288 100644
--- a/spec/ruby/core/exception/system_call_error_spec.rb
+++ b/spec/ruby/core/exception/system_call_error_spec.rb
@@ -31,7 +31,7 @@ describe "SystemCallError.new" do
-> { SystemCallError.new }.should raise_error(ArgumentError)
end
- it "accepts single Fixnum argument as errno" do
+ it "accepts single Integer argument as errno" do
SystemCallError.new(-2**24).errno.should == -2**24
SystemCallError.new(-1).errno.should == -1
SystemCallError.new(0).errno.should == 0
@@ -128,3 +128,16 @@ describe "SystemCallError#message" do
SystemCallError.new("XXX").message.should =~ /XXX/
end
end
+
+describe "SystemCallError#dup" do
+ it "copies the errno" do
+ dup_sce = SystemCallError.new("message", 42).dup
+ dup_sce.errno.should == 42
+ end
+end
+
+describe "SystemCallError#backtrace" do
+ it "is nil if not raised" do
+ SystemCallError.new("message", 42).backtrace.should == nil
+ end
+end
diff --git a/spec/ruby/core/exception/system_exit_spec.rb b/spec/ruby/core/exception/system_exit_spec.rb
new file mode 100644
index 0000000000..5c6116576b
--- /dev/null
+++ b/spec/ruby/core/exception/system_exit_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../spec_helper'
+
+describe "SystemExit" do
+ it "sets the exit status and exits silently when raised" do
+ code = 'raise SystemExit.new(7)'
+ result = ruby_exe(code, args: "2>&1")
+ result.should == ""
+ $?.exitstatus.should == 7
+ end
+
+ it "sets the exit status and exits silently when raised when subclassed" do
+ code = 'class CustomExit < SystemExit; end; raise CustomExit.new(8)'
+ result = ruby_exe(code, args: "2>&1")
+ result.should == ""
+ $?.exitstatus.should == 8
+ end
+end
diff --git a/spec/ruby/core/exception/system_stack_error_spec.rb b/spec/ruby/core/exception/system_stack_error_spec.rb
deleted file mode 100644
index 0343d2da59..0000000000
--- a/spec/ruby/core/exception/system_stack_error_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "SystemStackError" do
- it "is a subclass of Exception" do
- SystemStackError.superclass.should == Exception
- end
-end
diff --git a/spec/ruby/core/exception/top_level_spec.rb b/spec/ruby/core/exception/top_level_spec.rb
new file mode 100644
index 0000000000..501c7253c3
--- /dev/null
+++ b/spec/ruby/core/exception/top_level_spec.rb
@@ -0,0 +1,47 @@
+require_relative '../../spec_helper'
+
+describe "An Exception reaching the top level" do
+ it "is printed on STDERR" do
+ ruby_exe('raise "foo"', args: "2>&1").should.include?("in `<main>': foo (RuntimeError)")
+ end
+
+ ruby_version_is "2.6" do
+ it "the Exception#cause is printed to STDERR with backtraces" do
+ code = <<-RUBY
+ def raise_cause
+ raise "the cause"
+ end
+ def raise_wrapped
+ raise "wrapped"
+ end
+ begin
+ raise_cause
+ rescue
+ raise_wrapped
+ end
+ RUBY
+ lines = ruby_exe(code, args: "2>&1").lines
+ lines.reject! { |l| l.include?('rescue in') }
+ lines.map! { |l| l.chomp[/:(in.+)/, 1] }
+ lines.should == ["in `raise_wrapped': wrapped (RuntimeError)",
+ "in `<main>'",
+ "in `raise_cause': the cause (RuntimeError)",
+ "in `<main>'"]
+ end
+ end
+
+ describe "with a custom backtrace" do
+ it "is printed on STDERR" do
+ code = <<-RUBY
+ raise RuntimeError, "foo", [
+ "/dir/foo.rb:10:in `raising'",
+ "/dir/bar.rb:20:in `caller'",
+ ]
+ RUBY
+ ruby_exe(code, args: "2>&1").should == <<-EOS
+/dir/foo.rb:10:in `raising': foo (RuntimeError)
+\tfrom /dir/bar.rb:20:in `caller'
+ EOS
+ end
+ end
+end
diff --git a/spec/ruby/core/exception/uncaught_throw_error_spec.rb b/spec/ruby/core/exception/uncaught_throw_error_spec.rb
index 57f391d755..9267df6670 100644
--- a/spec/ruby/core/exception/uncaught_throw_error_spec.rb
+++ b/spec/ruby/core/exception/uncaught_throw_error_spec.rb
@@ -1,11 +1,5 @@
require_relative '../../spec_helper'
-describe "UncaughtThrowError" do
- it "is a subclass of ArgumentError" do
- ArgumentError.should be_ancestor_of(UncaughtThrowError)
- end
-end
-
describe "UncaughtThrowError#tag" do
it "returns the object thrown" do
begin
diff --git a/spec/ruby/core/false/to_s_spec.rb b/spec/ruby/core/false/to_s_spec.rb
index c996d87000..4cae278891 100644
--- a/spec/ruby/core/false/to_s_spec.rb
+++ b/spec/ruby/core/false/to_s_spec.rb
@@ -7,7 +7,7 @@ describe "FalseClass#to_s" do
ruby_version_is "2.7" do
it "returns a frozen string" do
- false.to_s.frozen?.should == true
+ false.to_s.should.frozen?
end
it "always returns the same string" do
diff --git a/spec/ruby/core/fiber/fixtures/classes.rb b/spec/ruby/core/fiber/fixtures/classes.rb
new file mode 100644
index 0000000000..c00facd6e1
--- /dev/null
+++ b/spec/ruby/core/fiber/fixtures/classes.rb
@@ -0,0 +1,12 @@
+module FiberSpecs
+
+ class NewFiberToRaise
+ def self.raise(*args)
+ fiber = Fiber.new { Fiber.yield }
+ fiber.resume
+ fiber.raise(*args)
+ end
+ end
+
+ class CustomError < StandardError; end
+end
diff --git a/spec/ruby/core/fiber/raise_spec.rb b/spec/ruby/core/fiber/raise_spec.rb
new file mode 100644
index 0000000000..f56219e565
--- /dev/null
+++ b/spec/ruby/core/fiber/raise_spec.rb
@@ -0,0 +1,101 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative '../../shared/kernel/raise'
+
+ruby_version_is "2.7" do
+ describe "Fiber#raise" do
+ it_behaves_like :kernel_raise, :raise, FiberSpecs::NewFiberToRaise
+ end
+
+ describe "Fiber#raise" do
+ it 'raises RuntimeError by default' do
+ -> { FiberSpecs::NewFiberToRaise.raise }.should raise_error(RuntimeError)
+ end
+
+ it "raises FiberError if Fiber is not born" do
+ fiber = Fiber.new { true }
+ -> { fiber.raise }.should raise_error(FiberError, "cannot raise exception on unborn fiber")
+ end
+
+ it "raises FiberError if Fiber is dead" do
+ fiber = Fiber.new { true }
+ fiber.resume
+ -> { fiber.raise }.should raise_error(FiberError, /dead fiber called|attempt to resume a terminated fiber/)
+ end
+
+ it 'accepts error class' do
+ -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError }.should raise_error(FiberSpecs::CustomError)
+ end
+
+ it 'accepts error message' do
+ -> { FiberSpecs::NewFiberToRaise.raise "error message" }.should raise_error(RuntimeError, "error message")
+ end
+
+ it 'does not accept array of backtrace information only' do
+ -> { FiberSpecs::NewFiberToRaise.raise ['foo'] }.should raise_error(TypeError)
+ end
+
+ it 'does not accept integer' do
+ -> { FiberSpecs::NewFiberToRaise.raise 100 }.should raise_error(TypeError)
+ end
+
+ it 'accepts error class with error message' do
+ -> { FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error' }.should raise_error(FiberSpecs::CustomError, 'test error')
+ end
+
+ it 'accepts error class with with error message and backtrace information' do
+ -> {
+ FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error', ['foo', 'boo']
+ }.should raise_error(FiberSpecs::CustomError) { |e|
+ e.message.should == 'test error'
+ e.backtrace.should == ['foo', 'boo']
+ }
+ end
+
+ it 'does not accept only error message and backtrace information' do
+ -> { FiberSpecs::NewFiberToRaise.raise 'test error', ['foo', 'boo'] }.should raise_error(TypeError)
+ end
+
+ it "raises a FiberError if invoked from a different Thread" do
+ fiber = Fiber.new { Fiber.yield }
+ fiber.resume
+ Thread.new do
+ -> {
+ fiber.raise
+ }.should raise_error(FiberError, "fiber called across threads")
+ end.join
+ end
+
+ it "kills Fiber" do
+ fiber = Fiber.new { Fiber.yield :first; :second }
+ fiber.resume
+ -> { fiber.raise }.should raise_error
+ -> { fiber.resume }.should raise_error(FiberError, /dead fiber called|attempt to resume a terminated fiber/)
+ end
+ end
+
+end
+
+ruby_version_is "2.7"..."3.0" do
+ describe "Fiber#raise" do
+ it "raises a FiberError if invoked on a transferring Fiber" do
+ require "fiber"
+ root = Fiber.current
+ fiber = Fiber.new { root.transfer }
+ fiber.transfer
+ -> { fiber.raise }.should raise_error(FiberError, "cannot resume transferred Fiber")
+ end
+ end
+end
+
+ruby_version_is "3.0" do
+ describe "Fiber#raise" do
+ it "transfers and raises on a transferring fiber" do
+ require "fiber"
+ root = Fiber.current
+ fiber = Fiber.new { root.transfer }
+ fiber.transfer
+ -> { fiber.raise "msg" }.should raise_error(RuntimeError, "msg")
+ end
+ end
+end
diff --git a/spec/ruby/core/fiber/resume_spec.rb b/spec/ruby/core/fiber/resume_spec.rb
index 97495c5059..273bc866af 100644
--- a/spec/ruby/core/fiber/resume_spec.rb
+++ b/spec/ruby/core/fiber/resume_spec.rb
@@ -6,9 +6,40 @@ describe "Fiber#resume" do
end
describe "Fiber#resume" do
- it "raises a FiberError if the Fiber tries to resume itself" do
- fiber = Fiber.new { fiber.resume }
- -> { fiber.resume }.should raise_error(FiberError, /double resume/)
+ it "runs until Fiber.yield" do
+ obj = mock('obj')
+ obj.should_not_receive(:do)
+ fiber = Fiber.new { 1 + 2; Fiber.yield; obj.do }
+ fiber.resume
+ end
+
+ it "resumes from the last call to Fiber.yield on subsequent invocations" do
+ fiber = Fiber.new { Fiber.yield :first; :second }
+ fiber.resume.should == :first
+ fiber.resume.should == :second
+ end
+
+ it "sets the block parameters to its arguments on the first invocation" do
+ first = mock('first')
+ first.should_receive(:arg).with(:first).twice
+
+ fiber = Fiber.new { |arg| first.arg arg; Fiber.yield; first.arg arg; }
+ fiber.resume :first
+ fiber.resume :second
+ end
+
+ ruby_version_is '3.0' do
+ it "raises a FiberError if the Fiber tries to resume itself" do
+ fiber = Fiber.new { fiber.resume }
+ -> { fiber.resume }.should raise_error(FiberError, /current fiber/)
+ end
+ end
+
+ ruby_version_is '' ... '3.0' do
+ it "raises a FiberError if the Fiber tries to resume itself" do
+ fiber = Fiber.new { fiber.resume }
+ -> { fiber.resume }.should raise_error(FiberError, /double resume/)
+ end
end
it "returns control to the calling Fiber if called from one" do
diff --git a/spec/ruby/core/file/absolute_path_spec.rb b/spec/ruby/core/file/absolute_path_spec.rb
index 52839cf1cc..9f39923472 100644
--- a/spec/ruby/core/file/absolute_path_spec.rb
+++ b/spec/ruby/core/file/absolute_path_spec.rb
@@ -73,6 +73,12 @@ describe "File.absolute_path" do
File.absolute_path('~').should_not == File.expand_path('~')
end
+ platform_is_not :windows do
+ it "does not expand '~' when given dir argument" do
+ File.absolute_path('~', '/').should == '/~'
+ end
+ end
+
it "does not expand '~user' to a home directory." do
path = File.dirname(@abs)
Dir.chdir(path) do
diff --git a/spec/ruby/core/file/atime_spec.rb b/spec/ruby/core/file/atime_spec.rb
index 02e8412722..5663e47266 100644
--- a/spec/ruby/core/file/atime_spec.rb
+++ b/spec/ruby/core/file/atime_spec.rb
@@ -15,7 +15,7 @@ describe "File.atime" do
File.atime(@file).should be_kind_of(Time)
end
- guard -> { platform_is :linux or (platform_is :windows and ruby_version_is '2.5') } do
+ platform_is :linux, :windows do
## NOTE also that some Linux systems disable atime (e.g. via mount params) for better filesystem speed.
it "returns the last access time for the named file with microseconds" do
supports_subseconds = Integer(`stat -c%x '#{__FILE__}'`[/\.(\d+)/, 1], 10)
diff --git a/spec/ruby/core/file/ctime_spec.rb b/spec/ruby/core/file/ctime_spec.rb
index 68a9fa43cb..b16eb13c1e 100644
--- a/spec/ruby/core/file/ctime_spec.rb
+++ b/spec/ruby/core/file/ctime_spec.rb
@@ -14,7 +14,7 @@ describe "File.ctime" do
File.ctime(@file).should be_kind_of(Time)
end
- guard -> { platform_is :linux or (platform_is :windows and ruby_version_is '2.5') } do
+ platform_is :linux, :windows do
it "returns the change time for the named file (the time at which directory information about the file was changed, not the file itself) with microseconds." do
supports_subseconds = Integer(`stat -c%z '#{__FILE__}'`[/\.(\d+)/, 1], 10)
if supports_subseconds != 0
diff --git a/spec/ruby/core/file/exists_spec.rb b/spec/ruby/core/file/exists_spec.rb
deleted file mode 100644
index 31d0e4dd1e..0000000000
--- a/spec/ruby/core/file/exists_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative '../../spec_helper'
-require_relative '../../shared/file/exist'
-
-describe "File.exists?" do
- it_behaves_like :file_exist, :exists?, File
-end
diff --git a/spec/ruby/core/file/expand_path_spec.rb b/spec/ruby/core/file/expand_path_spec.rb
index 88078645ab..c31f885b92 100644
--- a/spec/ruby/core/file/expand_path_spec.rb
+++ b/spec/ruby/core/file/expand_path_spec.rb
@@ -203,9 +203,9 @@ platform_is_not :windows do
it "does not return a frozen string" do
home = "/rubyspec_home"
- File.expand_path('~').frozen?.should == false
- File.expand_path('~', '/tmp/gumby/ddd').frozen?.should == false
- File.expand_path('~/a', '/tmp/gumby/ddd').frozen?.should == false
+ File.expand_path('~').should_not.frozen?
+ File.expand_path('~', '/tmp/gumby/ddd').should_not.frozen?
+ File.expand_path('~/a', '/tmp/gumby/ddd').should_not.frozen?
end
end
diff --git a/spec/ruby/core/file/extname_spec.rb b/spec/ruby/core/file/extname_spec.rb
index e9b53bc24d..e182ed44f2 100644
--- a/spec/ruby/core/file/extname_spec.rb
+++ b/spec/ruby/core/file/extname_spec.rb
@@ -12,6 +12,16 @@ describe "File.extname" do
File.extname(".app.conf").should == ".conf"
end
+ it "returns unfrozen strings" do
+ File.extname("foo.rb").frozen?.should == false
+ File.extname("/foo/bar.rb").frozen?.should == false
+ File.extname("/foo.rb/bar.c").frozen?.should == false
+ File.extname("bar").frozen?.should == false
+ File.extname(".bashrc").frozen?.should == false
+ File.extname("/foo.bar/baz").frozen?.should == false
+ File.extname(".app.conf").frozen?.should == false
+ end
+
it "returns the extension for edge cases" do
File.extname("").should == ""
File.extname(".").should == ""
diff --git a/spec/ruby/core/file/ftype_spec.rb b/spec/ruby/core/file/ftype_spec.rb
index 8ff70baa80..cdddc404dc 100644
--- a/spec/ruby/core/file/ftype_spec.rb
+++ b/spec/ruby/core/file/ftype_spec.rb
@@ -35,6 +35,14 @@ describe "File.ftype" do
end
end
+ it "uses to_path to convert arguments" do
+ FileSpecs.normal_file do |file|
+ obj = mock('path')
+ obj.should_receive(:to_path).and_return(file)
+ File.ftype(obj).should == 'file'
+ end
+ end
+
# Both FreeBSD and Windows does not have block devices
platform_is_not :freebsd, :windows do
with_block_device do
diff --git a/spec/ruby/core/file/join_spec.rb b/spec/ruby/core/file/join_spec.rb
index f1eab02de0..0feedbae93 100644
--- a/spec/ruby/core/file/join_spec.rb
+++ b/spec/ruby/core/file/join_spec.rb
@@ -136,4 +136,13 @@ describe "File.join" do
File.join(bin).should == "bin"
File.join("usr", bin).should == "usr/bin"
end
+
+ it "raises errors for null bytes" do
+ -> { File.join("\x00x", "metadata.gz") }.should raise_error(ArgumentError) { |e|
+ e.message.should == 'string contains null byte'
+ }
+ -> { File.join("metadata.gz", "\x00x") }.should raise_error(ArgumentError) { |e|
+ e.message.should == 'string contains null byte'
+ }
+ end
end
diff --git a/spec/ruby/core/file/lchmod_spec.rb b/spec/ruby/core/file/lchmod_spec.rb
index 6a28bdc16d..7420b95e4a 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
- guard -> { File.respond_to?(:lchmod) } do
+ platform_is_not :linux, :windows, :openbsd, :solaris, :aix do
before :each do
@fname = tmp('file_chmod_test')
@lname = @fname + '.lnk'
@@ -20,19 +20,13 @@ describe "File.lchmod" do
File.chmod(0222, @lname).should == 1
File.lchmod(0755, @lname).should == 1
- File.lstat(@lname).executable?.should == true
- File.lstat(@lname).readable?.should == true
- File.lstat(@lname).writable?.should == true
+ File.lstat(@lname).should.executable?
+ File.lstat(@lname).should.readable?
+ File.lstat(@lname).should.writable?
- File.stat(@lname).executable?.should == false
- File.stat(@lname).readable?.should == false
- File.stat(@lname).writable?.should == true
- end
- end
-
- guard_not -> { File.respond_to?(:lchmod) } do
- it "raises a NotImplementedError when called" do
- -> { File.lchmod 0, "foo" }.should raise_error(NotImplementedError)
+ File.stat(@lname).should_not.executable?
+ File.stat(@lname).should_not.readable?
+ File.stat(@lname).should.writable?
end
end
end
diff --git a/spec/ruby/core/file/link_spec.rb b/spec/ruby/core/file/link_spec.rb
index cc63c76aa3..a5d5b4815f 100644
--- a/spec/ruby/core/file/link_spec.rb
+++ b/spec/ruby/core/file/link_spec.rb
@@ -13,7 +13,7 @@ describe "File.link" do
rm_r @link, @file
end
- platform_is_not :windows do
+ platform_is_not :windows, :android do
it "link a file with another" do
File.link(@file, @link).should == 0
File.should.exist?(@link)
diff --git a/spec/ruby/core/file/lstat_spec.rb b/spec/ruby/core/file/lstat_spec.rb
index 918ed02163..a5ea9d15a5 100644
--- a/spec/ruby/core/file/lstat_spec.rb
+++ b/spec/ruby/core/file/lstat_spec.rb
@@ -22,8 +22,8 @@ describe "File.lstat" do
it "returns a File::Stat object with symlink properties for a symlink" do
st = File.lstat(@link)
- st.symlink?.should == true
- st.file?.should == false
+ st.should.symlink?
+ st.should_not.file?
end
end
end
diff --git a/spec/ruby/core/file/lutime_spec.rb b/spec/ruby/core/file/lutime_spec.rb
index 7449bc4389..1f0625f61e 100644
--- a/spec/ruby/core/file/lutime_spec.rb
+++ b/spec/ruby/core/file/lutime_spec.rb
@@ -1,40 +1,38 @@
require_relative '../../spec_helper'
-ruby_version_is "2.5" do
- describe "File.lutime" do
- platform_is_not :windows do
- before :each do
- @atime = Time.utc(2000)
- @mtime = Time.utc(2001)
- @file = tmp("specs_lutime_file")
- @symlink = tmp("specs_lutime_symlink")
- touch @file
- File.symlink(@file, @symlink)
- end
+describe "File.lutime" do
+ platform_is_not :windows do
+ before :each do
+ @atime = Time.utc(2000)
+ @mtime = Time.utc(2001)
+ @file = tmp("specs_lutime_file")
+ @symlink = tmp("specs_lutime_symlink")
+ touch @file
+ File.symlink(@file, @symlink)
+ end
- after :each do
- rm_r @file, @symlink
- end
+ after :each do
+ rm_r @file, @symlink
+ end
- it "sets the access and modification time for a regular file" do
- File.lutime(@atime, @mtime, @file)
- stat = File.stat(@file)
- stat.atime.should == @atime
- stat.mtime.should === @mtime
- end
+ it "sets the access and modification time for a regular file" do
+ File.lutime(@atime, @mtime, @file)
+ stat = File.stat(@file)
+ stat.atime.should == @atime
+ stat.mtime.should === @mtime
+ end
- it "sets the access and modification time for a symlink" do
- original = File.stat(@file)
+ it "sets the access and modification time for a symlink" do
+ original = File.stat(@file)
- File.lutime(@atime, @mtime, @symlink)
- stat = File.lstat(@symlink)
- stat.atime.should == @atime
- stat.mtime.should === @mtime
+ File.lutime(@atime, @mtime, @symlink)
+ stat = File.lstat(@symlink)
+ stat.atime.should == @atime
+ stat.mtime.should === @mtime
- file = File.stat(@file)
- file.atime.should == original.atime
- file.mtime.should == original.mtime
- end
+ file = File.stat(@file)
+ file.atime.should == original.atime
+ file.mtime.should == original.mtime
end
end
end
diff --git a/spec/ruby/core/file/mtime_spec.rb b/spec/ruby/core/file/mtime_spec.rb
index 1941e2ff85..8d47d3021a 100644
--- a/spec/ruby/core/file/mtime_spec.rb
+++ b/spec/ruby/core/file/mtime_spec.rb
@@ -15,7 +15,7 @@ describe "File.mtime" do
File.mtime(@filename).should be_close(@mtime, TIME_TOLERANCE)
end
- guard -> { platform_is :linux or (platform_is :windows and ruby_version_is '2.5') } do
+ platform_is :linux, :windows do
it "returns the modification Time of the file with microseconds" do
supports_subseconds = Integer(`stat -c%y '#{__FILE__}'`[/\.(\d+)/, 1], 10)
if supports_subseconds != 0
diff --git a/spec/ruby/core/file/open_spec.rb b/spec/ruby/core/file/open_spec.rb
index e3c5618795..8faa31173e 100644
--- a/spec/ruby/core/file/open_spec.rb
+++ b/spec/ruby/core/file/open_spec.rb
@@ -28,7 +28,7 @@ describe "File.open" do
describe "with a block" do
it "does not raise error when file is closed inside the block" do
@fh = File.open(@file) { |fh| fh.close; fh }
- @fh.closed?.should == true
+ @fh.should.closed?
end
it "invokes close on an opened file when exiting the block" do
@@ -485,7 +485,7 @@ describe "File.open" do
File.size(@file).should > 0
File.open(@file, "w+") do |f|
f.pos.should == 0
- f.eof?.should == true
+ f.should.eof?
end
File.size(@file).should == 0
end
@@ -495,7 +495,7 @@ describe "File.open" do
File.size(@file).should > 0
File.open(@file, "rb+") do |f|
f.pos.should == 0
- f.eof?.should == false
+ f.should_not.eof?
end
end
@@ -504,7 +504,7 @@ describe "File.open" do
File.size(@file).should > 0
File.open(@file, "wb+") do |f|
f.pos.should == 0
- f.eof?.should == true
+ f.should.eof?
end
File.size(@file).should == 0
end
@@ -623,12 +623,10 @@ describe "File.open" do
end
end
- ruby_version_is "2.5" do
- it "raises ArgumentError if mixing :newline and binary mode" do
- -> {
- File.open(@file, "rb", newline: :universal) {}
- }.should raise_error(ArgumentError, "newline decorator with binary mode")
- end
+ it "raises ArgumentError if mixing :newline and binary mode" do
+ -> {
+ File.open(@file, "rb", newline: :universal) {}
+ }.should raise_error(ArgumentError, "newline decorator with binary mode")
end
ruby_version_is "2.6" do
diff --git a/spec/ruby/core/file/realpath_spec.rb b/spec/ruby/core/file/realpath_spec.rb
index 0c5d19287a..bd27e09da6 100644
--- a/spec/ruby/core/file/realpath_spec.rb
+++ b/spec/ruby/core/file/realpath_spec.rb
@@ -67,6 +67,12 @@ platform_is_not :windows do
it "raises Errno::ENOENT if the symlink points to an absent file" do
-> { File.realpath(@fake_link) }.should raise_error(Errno::ENOENT)
end
+
+ it "converts the argument with #to_path" do
+ path = mock("path")
+ path.should_receive(:to_path).and_return(__FILE__)
+ File.realpath(path).should == File.realpath(__FILE__ )
+ end
end
end
diff --git a/spec/ruby/core/file/shared/path.rb b/spec/ruby/core/file/shared/path.rb
index cfd119f799..0a5abe33f0 100644
--- a/spec/ruby/core/file/shared/path.rb
+++ b/spec/ruby/core/file/shared/path.rb
@@ -15,6 +15,23 @@ describe :file_path, shared: true do
@file.send(@method).should be_an_instance_of(String)
end
+ it "returns a different String on every call" do
+ @file = File.new @path
+ path1 = @file.send(@method)
+ path2 = @file.send(@method)
+ path1.should == path2
+ path1.should_not.equal?(path2)
+ end
+
+ it "returns a mutable String" do
+ @file = File.new @path.dup.freeze
+ path = @file.send(@method)
+ path.should == @path
+ path.should_not.frozen?
+ path << "test"
+ @file.send(@method).should == @path
+ end
+
it "calls to_str on argument and returns exact value" do
path = mock('path')
path.should_receive(:to_str).and_return(@path)
@@ -50,26 +67,24 @@ describe :file_path, shared: true do
@file.send(@method).encoding.should == Encoding.find("euc-jp")
end
- ruby_version_is "2.5" do
- platform_is :linux do
- guard -> { defined?(File::TMPFILE) } do
- before :each do
- @dir = tmp("tmpfilespec")
- mkdir_p @dir
- end
+ platform_is :linux do
+ guard -> { defined?(File::TMPFILE) } do
+ before :each do
+ @dir = tmp("tmpfilespec")
+ mkdir_p @dir
+ end
- after :each do
- rm_r @dir
- end
+ after :each do
+ rm_r @dir
+ end
- it "raises IOError if file was opened with File::TMPFILE" do
- begin
- File.open(@dir, File::RDWR | File::TMPFILE) do |f|
- -> { f.send(@method) }.should raise_error(IOError)
- end
- rescue Errno::EOPNOTSUPP, Errno::EINVAL, Errno::EISDIR
- skip "no support from the filesystem"
+ it "raises IOError if file was opened with File::TMPFILE" do
+ begin
+ File.open(@dir, File::RDWR | File::TMPFILE) do |f|
+ -> { f.send(@method) }.should raise_error(IOError)
end
+ rescue Errno::EOPNOTSUPP, Errno::EINVAL, Errno::EISDIR
+ skip "no support from the filesystem"
end
end
end
diff --git a/spec/ruby/core/file/size_spec.rb b/spec/ruby/core/file/size_spec.rb
index a2bf408da1..11d20cbacb 100644
--- a/spec/ruby/core/file/size_spec.rb
+++ b/spec/ruby/core/file/size_spec.rb
@@ -59,8 +59,8 @@ describe "File#size" do
@file.respond_to?(:size).should be_true
end
- it "returns the file's size as a Fixnum" do
- @file.size.should be_an_instance_of(Fixnum)
+ it "returns the file's size as an Integer" do
+ @file.size.should be_an_instance_of(Integer)
end
it "returns the file's size in bytes" do
diff --git a/spec/ruby/core/file/stat/nlink_spec.rb b/spec/ruby/core/file/stat/nlink_spec.rb
index 2dd0bff124..7143923cfc 100644
--- a/spec/ruby/core/file/stat/nlink_spec.rb
+++ b/spec/ruby/core/file/stat/nlink_spec.rb
@@ -11,7 +11,7 @@ describe "File::Stat#nlink" do
rm_r @link, @file
end
- platform_is_not :windows do
+ platform_is_not :windows, :android do
it "returns the number of links to a file" do
File::Stat.new(@file).nlink.should == 1
File.link(@file, @link)
diff --git a/spec/ruby/core/file/stat/owned_spec.rb b/spec/ruby/core/file/stat/owned_spec.rb
index 6f0c250f88..a23ad850c5 100644
--- a/spec/ruby/core/file/stat/owned_spec.rb
+++ b/spec/ruby/core/file/stat/owned_spec.rb
@@ -18,15 +18,15 @@ describe "File::Stat#owned?" do
it "returns true if the file is owned by the user" do
st = File.stat(@file)
- st.owned?.should == true
+ st.should.owned?
end
- platform_is_not :windows do
+ platform_is_not :windows, :android do
as_user do
it "returns false if the file is not owned by the user" do
system_file = '/etc/passwd'
st = File.stat(system_file)
- st.owned?.should == false
+ st.should_not.owned?
end
end
end
diff --git a/spec/ruby/core/file/stat/pipe_spec.rb b/spec/ruby/core/file/stat/pipe_spec.rb
index 7abb6c742a..692dfbf42a 100644
--- a/spec/ruby/core/file/stat/pipe_spec.rb
+++ b/spec/ruby/core/file/stat/pipe_spec.rb
@@ -12,7 +12,7 @@ describe "File::Stat#pipe?" do
touch(filename)
st = File.stat(filename)
- st.pipe?.should == false
+ st.should_not.pipe?
rm_r filename
end
@@ -23,7 +23,7 @@ describe "File::Stat#pipe?" do
File.mkfifo(filename)
st = File.stat(filename)
- st.pipe?.should == true
+ st.should.pipe?
rm_r filename
end
diff --git a/spec/ruby/core/file/stat_spec.rb b/spec/ruby/core/file/stat_spec.rb
index 31f9dc58af..6365500057 100644
--- a/spec/ruby/core/file/stat_spec.rb
+++ b/spec/ruby/core/file/stat_spec.rb
@@ -23,8 +23,8 @@ platform_is_not :windows do
st = f.stat
- st.file?.should == true
- st.zero?.should == false
+ st.should.file?
+ st.should_not.zero?
st.size.should == 8
st.size?.should == 8
st.blksize.should >= 0
@@ -38,8 +38,18 @@ platform_is_not :windows do
File.symlink(@file, @link)
st = File.stat(@link)
- st.file?.should == true
- st.symlink?.should == false
+ st.should.file?
+ st.should_not.symlink?
+ end
+
+ it "returns an error when given missing non-ASCII path" do
+ missing_path = "/missingfilepath\xE3E4".b
+ -> {
+ File.stat(missing_path)
+ }.should raise_error(SystemCallError) { |e|
+ [Errno::ENOENT, Errno::EILSEQ].should include(e.class)
+ e.message.should include(missing_path)
+ }
end
end
end
diff --git a/spec/ruby/core/file/truncate_spec.rb b/spec/ruby/core/file/truncate_spec.rb
index 43b86b7382..b4a2e3e577 100644
--- a/spec/ruby/core/file/truncate_spec.rb
+++ b/spec/ruby/core/file/truncate_spec.rb
@@ -18,7 +18,7 @@ describe "File.truncate" do
File.open(@name, "r") do |f|
f.read(99).should == "12345"
- f.eof?.should == true
+ f.should.eof?
end
end
@@ -120,7 +120,7 @@ describe "File#truncate" do
File.size(@name).should == 5
File.open(@name, "r") do |f|
f.read(99).should == "12345"
- f.eof?.should == true
+ f.should.eof?
end
end
@@ -161,7 +161,7 @@ describe "File#truncate" do
it "raises an IOError if file is closed" do
@file.close
- @file.closed?.should == true
+ @file.should.closed?
-> { @file.truncate(42) }.should raise_error(IOError)
end
diff --git a/spec/ruby/core/file/umask_spec.rb b/spec/ruby/core/file/umask_spec.rb
index 2640e3c316..7f7e40abbc 100644
--- a/spec/ruby/core/file/umask_spec.rb
+++ b/spec/ruby/core/file/umask_spec.rb
@@ -12,8 +12,8 @@ describe "File.umask" do
File.umask(@orig_umask)
end
- it "returns a Fixnum" do
- File.umask.should be_kind_of(Fixnum)
+ it "returns an Integer" do
+ File.umask.should be_kind_of(Integer)
end
platform_is_not :windows do
diff --git a/spec/ruby/core/file/utime_spec.rb b/spec/ruby/core/file/utime_spec.rb
index 9c198af18b..19cb80d5f8 100644
--- a/spec/ruby/core/file/utime_spec.rb
+++ b/spec/ruby/core/file/utime_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "File.utime" do
before :all do
- @time_is_float = /mswin|mingw/ =~ RUBY_PLATFORM && RUBY_VERSION >= '2.5'
+ @time_is_float = platform_is :windows
end
before :each do
@@ -72,13 +72,17 @@ describe "File.utime" do
platform_is :linux do
platform_is wordsize: 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)" do
+ it "allows Time instances in the far future to set mtime and atime (but some filesystems limit it up to 2446-05-10 or 2038-01-19)" do
# https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps
# "Therefore, timestamps should not overflow until May 2446."
+ # https://lwn.net/Articles/804382/
+ # "On-disk timestamps hitting the y2038 limit..."
+ # The problem seems to be being improved, but currently it actually fails on XFS on RHEL8
+ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20201112T123004Z.fail.html.gz
time = Time.at(1<<44)
File.utime(time, time, @file1)
- [559444, 2446].should.include? File.atime(@file1).year
- [559444, 2446].should.include? File.mtime(@file1).year
+ [559444, 2446, 2038].should.include? File.atime(@file1).year
+ [559444, 2446, 2038].should.include? File.mtime(@file1).year
end
end
end
diff --git a/spec/ruby/core/filetest/exists_spec.rb b/spec/ruby/core/filetest/exists_spec.rb
deleted file mode 100644
index d090d7d740..0000000000
--- a/spec/ruby/core/filetest/exists_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative '../../spec_helper'
-require_relative '../../shared/file/exist'
-
-describe "FileTest.exists?" do
- it_behaves_like :file_exist, :exists?, FileTest
-end
diff --git a/spec/ruby/core/float/comparison_spec.rb b/spec/ruby/core/float/comparison_spec.rb
index 2dc993a176..cbab3a0fa1 100644
--- a/spec/ruby/core/float/comparison_spec.rb
+++ b/spec/ruby/core/float/comparison_spec.rb
@@ -33,24 +33,22 @@ describe "Float#<=>" do
coercible.call_count.should == 3
end
- ruby_version_is "2.5" do
- it "raises TypeError when #coerce misbehaves" do
- klass = Class.new do
- def coerce(other)
- :incorrect
- end
+ it "raises TypeError when #coerce misbehaves" do
+ klass = Class.new do
+ def coerce(other)
+ :incorrect
end
-
- bad_coercible = klass.new
- -> {
- 4.2 <=> bad_coercible
- }.should raise_error(TypeError, "coerce must return [x, y]")
end
+
+ bad_coercible = klass.new
+ -> {
+ 4.2 <=> bad_coercible
+ }.should raise_error(TypeError, "coerce must return [x, y]")
end
# The 4 tests below are taken from matz's revision 23730 for Ruby trunk
#
- it "returns 1 when self is Infinity and other is a Bignum" do
+ it "returns 1 when self is Infinity and other is an Integer" do
(infinity_value <=> Float::MAX.to_i*2).should == 1
end
diff --git a/spec/ruby/core/float/finite_spec.rb b/spec/ruby/core/float/finite_spec.rb
index c5fb3df849..d839b30e32 100644
--- a/spec/ruby/core/float/finite_spec.rb
+++ b/spec/ruby/core/float/finite_spec.rb
@@ -2,18 +2,18 @@ require_relative '../../spec_helper'
describe "Float#finite?" do
it "returns true for finite values" do
- 3.14159.finite?.should == true
+ 3.14159.should.finite?
end
it "returns false for positive infinity" do
- infinity_value.finite?.should == false
+ infinity_value.should_not.finite?
end
it "returns false for negative infinity" do
- (-infinity_value).finite?.should == false
+ (-infinity_value).should_not.finite?
end
it "returns false for NaN" do
- nan_value.finite?.should == false
+ nan_value.should_not.finite?
end
end
diff --git a/spec/ruby/core/float/inspect_spec.rb b/spec/ruby/core/float/inspect_spec.rb
new file mode 100644
index 0000000000..4be1927d84
--- /dev/null
+++ b/spec/ruby/core/float/inspect_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/to_s'
+
+describe "Float#inspect" do
+ it_behaves_like :float_to_s, :inspect
+end
diff --git a/spec/ruby/core/float/nan_spec.rb b/spec/ruby/core/float/nan_spec.rb
index d09d25153c..c1043ef21b 100644
--- a/spec/ruby/core/float/nan_spec.rb
+++ b/spec/ruby/core/float/nan_spec.rb
@@ -2,8 +2,8 @@ require_relative '../../spec_helper'
describe "Float#nan?" do
it "returns true if self is not a valid IEEE floating-point number" do
- 0.0.nan?.should == false
- -1.5.nan?.should == false
- nan_value.nan?.should == true
+ 0.0.should_not.nan?
+ -1.5.should_not.nan?
+ nan_value.should.nan?
end
end
diff --git a/spec/ruby/core/float/negative_spec.rb b/spec/ruby/core/float/negative_spec.rb
new file mode 100644
index 0000000000..511d92ade6
--- /dev/null
+++ b/spec/ruby/core/float/negative_spec.rb
@@ -0,0 +1,33 @@
+require_relative '../../spec_helper'
+
+describe "Float#negative?" do
+ describe "on positive numbers" do
+ it "returns false" do
+ 0.1.negative?.should be_false
+ end
+ end
+
+ describe "on zero" do
+ it "returns false" do
+ 0.0.negative?.should be_false
+ end
+ end
+
+ describe "on negative zero" do
+ it "returns false" do
+ -0.0.negative?.should be_false
+ end
+ end
+
+ describe "on negative numbers" do
+ it "returns true" do
+ -0.1.negative?.should be_true
+ end
+ end
+
+ describe "on NaN" do
+ it "returns false" do
+ nan_value.negative?.should be_false
+ end
+ end
+end
diff --git a/spec/ruby/core/float/next_float_spec.rb b/spec/ruby/core/float/next_float_spec.rb
index 2f0eff605a..29e2d31146 100644
--- a/spec/ruby/core/float/next_float_spec.rb
+++ b/spec/ruby/core/float/next_float_spec.rb
@@ -44,6 +44,6 @@ describe "Float#next_float" do
end
it "returns NAN if NAN was the receiver" do
- Float::NAN.next_float.nan?.should == true
+ Float::NAN.next_float.should.nan?
end
end
diff --git a/spec/ruby/core/float/positive_spec.rb b/spec/ruby/core/float/positive_spec.rb
new file mode 100644
index 0000000000..575f92a720
--- /dev/null
+++ b/spec/ruby/core/float/positive_spec.rb
@@ -0,0 +1,33 @@
+require_relative '../../spec_helper'
+
+describe "Float#positive?" do
+ describe "on positive numbers" do
+ it "returns true" do
+ 0.1.positive?.should be_true
+ end
+ end
+
+ describe "on zero" do
+ it "returns false" do
+ 0.0.positive?.should be_false
+ end
+ end
+
+ describe "on negative zero" do
+ it "returns false" do
+ -0.0.positive?.should be_false
+ end
+ end
+
+ describe "on negative numbers" do
+ it "returns false" do
+ -0.1.positive?.should be_false
+ end
+ end
+
+ describe "on NaN" do
+ it "returns false" do
+ nan_value.positive?.should be_false
+ end
+ end
+end
diff --git a/spec/ruby/core/float/prev_float_spec.rb b/spec/ruby/core/float/prev_float_spec.rb
index 40fcc25a6d..5e50269da7 100644
--- a/spec/ruby/core/float/prev_float_spec.rb
+++ b/spec/ruby/core/float/prev_float_spec.rb
@@ -44,6 +44,6 @@ describe "Float#prev_float" do
end
it "returns NAN if NAN was the receiver" do
- Float::NAN.prev_float.nan?.should == true
+ Float::NAN.prev_float.should.nan?
end
end
diff --git a/spec/ruby/core/float/round_spec.rb b/spec/ruby/core/float/round_spec.rb
index e143682362..4bd2dc460c 100644
--- a/spec/ruby/core/float/round_spec.rb
+++ b/spec/ruby/core/float/round_spec.rb
@@ -114,4 +114,17 @@ describe "Float#round" do
it "raise for a non-existent round mode" do
-> { 14.2.round(half: :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode: nonsense")
end
+
+ describe "when 0.0 is given" do
+ it "returns self for positive ndigits" do
+ (0.0).round(5).inspect.should == "0.0"
+ (-0.0).round(1).inspect.should == "-0.0"
+ end
+
+ it "returns 0 for 0 or undefined ndigits" do
+ (0.0).round.should == 0
+ (-0.0).round(0).should == 0
+ (0.0).round(half: :up) == 0
+ end
+ end
end
diff --git a/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb b/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb
index 19a02572d8..eec92d858f 100644
--- a/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb
+++ b/spec/ruby/core/float/shared/arithmetic_exception_in_coerce.rb
@@ -1,33 +1,11 @@
require_relative '../fixtures/classes'
describe :float_arithmetic_exception_in_coerce, shared: true do
- ruby_version_is ""..."2.5" do
- it "rescues exception (StandardError and subclasses) raised in other#coerce and raises TypeError" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError)
+ it "does not rescue exception raised in other#coerce" do
+ b = mock("numeric with failed #coerce")
+ b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError)
- # e.g. 1.0 > b
- -> { 1.0.send(@method, b) }.should raise_error(TypeError, /MockObject can't be coerced into Float/)
- end
-
- it "does not rescue Exception and StandardError siblings raised in other#coerce" do
- [Exception, NoMemoryError].each do |exception|
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(exception)
-
- # e.g. 1.0 > b
- -> { 1.0.send(@method, b) }.should raise_error(exception)
- end
- end
- end
-
- ruby_version_is "2.5" do
- it "does not rescue exception raised in other#coerce" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError)
-
- # e.g. 1.0 > b
- -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError)
- end
+ # e.g. 1.0 > b
+ -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError)
end
end
diff --git a/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb b/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb
index f8ded53644..3e2c1e28dd 100644
--- a/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb
+++ b/spec/ruby/core/float/shared/comparison_exception_in_coerce.rb
@@ -1,35 +1,11 @@
require_relative '../fixtures/classes'
describe :float_comparison_exception_in_coerce, shared: true do
- ruby_version_is ""..."2.5" do
- it "rescues exception (StandardError and subclasses) raised in other#coerce and raises ArgumentError" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError)
+ it "does not rescue exception raised in other#coerce" do
+ b = mock("numeric with failed #coerce")
+ b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError)
- # e.g. 1.0 > b
- -> {
- -> { 1.0.send(@method, b) }.should raise_error(ArgumentError, /comparison of Float with MockObject failed/)
- }.should complain(/Numerical comparison operators will no more rescue exceptions of #coerce/)
- end
-
- it "does not rescue Exception and StandardError siblings raised in other#coerce" do
- [Exception, NoMemoryError].each do |exception|
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(exception)
-
- # e.g. 1.0 > b
- -> { 1.0.send(@method, b) }.should raise_error(exception)
- end
- end
- end
-
- ruby_version_is "2.5" do
- it "does not rescue exception raised in other#coerce" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(FloatSpecs::CoerceError)
-
- # e.g. 1.0 > b
- -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError)
- end
+ # e.g. 1.0 > b
+ -> { 1.0.send(@method, b) }.should raise_error(FloatSpecs::CoerceError)
end
end
diff --git a/spec/ruby/core/float/shared/quo.rb b/spec/ruby/core/float/shared/quo.rb
index 3487824f70..0c90171b87 100644
--- a/spec/ruby/core/float/shared/quo.rb
+++ b/spec/ruby/core/float/shared/quo.rb
@@ -1,9 +1,9 @@
describe :float_quo, shared: true do
- it "performs floating-point division between self and a Fixnum" do
+ it "performs floating-point division between self and an Integer" do
8.9.send(@method, 7).should == 1.2714285714285716
end
- it "performs floating-point division between self and a Bignum" do
+ it "performs floating-point division between self and an Integer" do
8.9.send(@method, 9999999999999**9).should == 8.900000000008011e-117
end
diff --git a/spec/ruby/core/float/shared/to_s.rb b/spec/ruby/core/float/shared/to_s.rb
new file mode 100644
index 0000000000..0925efc0f7
--- /dev/null
+++ b/spec/ruby/core/float/shared/to_s.rb
@@ -0,0 +1,308 @@
+describe :float_to_s, shared: true do
+ it "returns 'NaN' for NaN" do
+ nan_value().send(@method).should == 'NaN'
+ end
+
+ it "returns 'Infinity' for positive infinity" do
+ infinity_value().send(@method).should == 'Infinity'
+ end
+
+ it "returns '-Infinity' for negative infinity" do
+ (-infinity_value()).send(@method).should == '-Infinity'
+ end
+
+ it "returns '0.0' for 0.0" do
+ 0.0.send(@method).should == "0.0"
+ end
+
+ platform_is_not :openbsd do
+ it "emits '-' for -0.0" do
+ -0.0.send(@method).should == "-0.0"
+ end
+ end
+
+ it "emits a '-' for negative values" do
+ -3.14.send(@method).should == "-3.14"
+ end
+
+ it "emits a trailing '.0' for a whole number" do
+ 50.0.send(@method).should == "50.0"
+ end
+
+ it "emits a trailing '.0' for the mantissa in e format" do
+ 1.0e20.send(@method).should == "1.0e+20"
+ end
+
+ it "uses non-e format for a positive value with fractional part having 5 significant figures" do
+ 0.0001.send(@method).should == "0.0001"
+ end
+
+ it "uses non-e format for a negative value with fractional part having 5 significant figures" do
+ -0.0001.send(@method).should == "-0.0001"
+ end
+
+ it "uses e format for a positive value with fractional part having 6 significant figures" do
+ 0.00001.send(@method).should == "1.0e-05"
+ end
+
+ it "uses e format for a negative value with fractional part having 6 significant figures" do
+ -0.00001.send(@method).should == "-1.0e-05"
+ end
+
+ it "uses non-e format for a positive value with whole part having 15 significant figures" do
+ 10000000000000.0.send(@method).should == "10000000000000.0"
+ end
+
+ it "uses non-e format for a negative value with whole part having 15 significant figures" do
+ -10000000000000.0.send(@method).should == "-10000000000000.0"
+ end
+
+ it "uses non-e format for a positive value with whole part having 16 significant figures" do
+ 100000000000000.0.send(@method).should == "100000000000000.0"
+ end
+
+ it "uses non-e format for a negative value with whole part having 16 significant figures" do
+ -100000000000000.0.send(@method).should == "-100000000000000.0"
+ end
+
+ it "uses e format for a positive value with whole part having 18 significant figures" do
+ 10000000000000000.0.send(@method).should == "1.0e+16"
+ end
+
+ it "uses e format for a negative value with whole part having 18 significant figures" do
+ -10000000000000000.0.send(@method).should == "-1.0e+16"
+ end
+
+ it "uses e format for a positive value with whole part having 17 significant figures" do
+ 1000000000000000.0.send(@method).should == "1.0e+15"
+ end
+
+ it "uses e format for a negative value with whole part having 17 significant figures" do
+ -1000000000000000.0.send(@method).should == "-1.0e+15"
+ end
+
+ # #3273
+ it "outputs the minimal, unique form necessary to recreate the value" do
+ value = 0.21611564636388508
+ string = "0.21611564636388508"
+
+ value.send(@method).should == string
+ string.to_f.should == value
+ end
+
+ it "outputs the minimal, unique form to represent the value" do
+ 0.56.send(@method).should == "0.56"
+ end
+
+ describe "matches" do
+ it "random examples in all ranges" do
+ # 50.times do
+ # bytes = (0...8).map { rand(256) }
+ # string = bytes.pack('C8')
+ # float = string.unpack('D').first
+ # puts "#{'%.20g' % float}.send(@method).should == #{float.send(@method).inspect}"
+ # end
+
+ 2.5540217314354050325e+163.send(@method).should == "2.554021731435405e+163"
+ 2.5492588360356597544e-172.send(@method).should == "2.5492588360356598e-172"
+ 1.742770260934704852e-82.send(@method).should == "1.7427702609347049e-82"
+ 6.2108093676180883209e-104.send(@method).should == "6.210809367618088e-104"
+ -3.3448803488331067402e-143.send(@method).should == "-3.3448803488331067e-143"
+ -2.2740074343500832557e-168.send(@method).should == "-2.2740074343500833e-168"
+ 7.0587971678048535732e+191.send(@method).should == "7.058797167804854e+191"
+ -284438.88327586348169.send(@method).should == "-284438.8832758635"
+ 3.953272468476091301e+105.send(@method).should == "3.9532724684760913e+105"
+ -3.6361359552959847853e+100.send(@method).should == "-3.636135955295985e+100"
+ -1.3222325865575206185e-31.send(@method).should == "-1.3222325865575206e-31"
+ 1.1440138916932761366e+130.send(@method).should == "1.1440138916932761e+130"
+ 4.8750891560387561157e-286.send(@method).should == "4.875089156038756e-286"
+ 5.6101113356591453525e-257.send(@method).should == "5.610111335659145e-257"
+ -3.829644279545809575e-100.send(@method).should == "-3.8296442795458096e-100"
+ 1.5342839401396406117e-194.send(@method).should == "1.5342839401396406e-194"
+ 2.2284972755169921402e-144.send(@method).should == "2.228497275516992e-144"
+ 2.1825655917065601737e-61.send(@method).should == "2.1825655917065602e-61"
+ -2.6672271363524338322e-62.send(@method).should == "-2.667227136352434e-62"
+ -1.9257995160119059415e+21.send(@method).should == "-1.925799516011906e+21"
+ -8.9096732962887121718e-198.send(@method).should == "-8.909673296288712e-198"
+ 2.0202075376548644959e-90.send(@method).should == "2.0202075376548645e-90"
+ -7.7341602581786258961e-266.send(@method).should == "-7.734160258178626e-266"
+ 3.5134482598733635046e+98.send(@method).should == "3.5134482598733635e+98"
+ -2.124411722371029134e+154.send(@method).should == "-2.124411722371029e+154"
+ -4.573908787355718687e+110.send(@method).should == "-4.573908787355719e+110"
+ -1.9344425934170969879e-232.send(@method).should == "-1.934442593417097e-232"
+ -1.3274227399979271095e+171.send(@method).should == "-1.3274227399979271e+171"
+ 9.3495270482104442383e-283.send(@method).should == "9.349527048210444e-283"
+ -4.2046059371986483233e+307.send(@method).should == "-4.2046059371986483e+307"
+ 3.6133547278583543004e-117.send(@method).should == "3.613354727858354e-117"
+ 4.9247416523566613499e-08.send(@method).should == "4.9247416523566613e-08"
+ 1.6936145488250064007e-71.send(@method).should == "1.6936145488250064e-71"
+ 2.4455483206829433098e+96.send(@method).should == "2.4455483206829433e+96"
+ 7.9797449851436455384e+124.send(@method).should == "7.979744985143646e+124"
+ -1.3873689634457876774e-129.send(@method).should == "-1.3873689634457877e-129"
+ 3.9761102037533483075e+284.send(@method).should == "3.976110203753348e+284"
+ -4.2819791952139402486e-303.send(@method).should == "-4.28197919521394e-303"
+ -5.7981017546689831298e-116.send(@method).should == "-5.798101754668983e-116"
+ -3.953266497860534199e-28.send(@method).should == "-3.953266497860534e-28"
+ -2.0659852720290440959e-243.send(@method).should == "-2.065985272029044e-243"
+ 8.9670488995878688018e-05.send(@method).should == "8.967048899587869e-05"
+ -1.2317943708113061768e-98.send(@method).should == "-1.2317943708113062e-98"
+ -3.8930768307633080463e+248.send(@method).should == "-3.893076830763308e+248"
+ 6.5854032671803925627e-239.send(@method).should == "6.5854032671803926e-239"
+ 4.6257022188980878952e+177.send(@method).should == "4.625702218898088e+177"
+ -1.9397155125507235603e-187.send(@method).should == "-1.9397155125507236e-187"
+ 8.5752156951245705056e+117.send(@method).should == "8.57521569512457e+117"
+ -2.4784875958162501671e-132.send(@method).should == "-2.4784875958162502e-132"
+ -4.4125691841230058457e-203.send(@method).should == "-4.412569184123006e-203"
+ end
+
+ it "random examples in human ranges" do
+ # 50.times do
+ # formatted = ''
+ # rand(1..3).times do
+ # formatted << rand(10).to_s
+ # end
+ # formatted << '.'
+ # rand(1..9).times do
+ # formatted << rand(10).to_s
+ # end
+ # float = formatted.to_f
+ # puts "#{'%.20f' % float}.send(@method).should == #{float.send(@method).inspect}"
+ # end
+
+ 5.17869899999999994122.send(@method).should == "5.178699"
+ 905.62695729999995819526.send(@method).should == "905.6269573"
+ 62.75999999999999801048.send(@method).should == "62.76"
+ 6.93856795800000014651.send(@method).should == "6.938567958"
+ 4.95999999999999996447.send(@method).should == "4.96"
+ 32.77993899999999882766.send(@method).should == "32.779939"
+ 544.12756779999995160324.send(@method).should == "544.1275678"
+ 66.25801119999999855281.send(@method).should == "66.2580112"
+ 7.90000000000000035527.send(@method).should == "7.9"
+ 5.93100000000000004974.send(@method).should == "5.931"
+ 5.21229313600000043749.send(@method).should == "5.212293136"
+ 503.44173809000000119340.send(@method).should == "503.44173809"
+ 79.26000000000000511591.send(@method).should == "79.26"
+ 8.51524999999999998579.send(@method).should == "8.51525"
+ 174.00000000000000000000.send(@method).should == "174.0"
+ 50.39580000000000126192.send(@method).should == "50.3958"
+ 35.28999999999999914735.send(@method).should == "35.29"
+ 5.43136675399999990788.send(@method).should == "5.431366754"
+ 654.07680000000004838512.send(@method).should == "654.0768"
+ 6.07423700000000010846.send(@method).should == "6.074237"
+ 102.25779799999999397642.send(@method).should == "102.257798"
+ 5.08129999999999970584.send(@method).should == "5.0813"
+ 6.00000000000000000000.send(@method).should == "6.0"
+ 8.30000000000000071054.send(@method).should == "8.3"
+ 32.68345999999999662577.send(@method).should == "32.68346"
+ 581.11170000000004165486.send(@method).should == "581.1117"
+ 76.31342999999999676675.send(@method).should == "76.31343"
+ 438.30826000000001840817.send(@method).should == "438.30826"
+ 482.06631994000002805478.send(@method).should == "482.06631994"
+ 55.92721026899999969828.send(@method).should == "55.927210269"
+ 4.00000000000000000000.send(@method).should == "4.0"
+ 55.86693999999999959982.send(@method).should == "55.86694"
+ 787.98299999999994724931.send(@method).should == "787.983"
+ 5.73810511000000023074.send(@method).should == "5.73810511"
+ 74.51926810000000500622.send(@method).should == "74.5192681"
+ 892.89999999999997726263.send(@method).should == "892.9"
+ 68.27299999999999613465.send(@method).should == "68.273"
+ 904.10000000000002273737.send(@method).should == "904.1"
+ 5.23200000000000020606.send(@method).should == "5.232"
+ 4.09628000000000014325.send(@method).should == "4.09628"
+ 46.05152633699999853434.send(@method).should == "46.051526337"
+ 142.12884990599999923688.send(@method).should == "142.128849906"
+ 3.83057023500000015659.send(@method).should == "3.830570235"
+ 11.81684594699999912848.send(@method).should == "11.816845947"
+ 80.50000000000000000000.send(@method).should == "80.5"
+ 382.18215010000000120272.send(@method).should == "382.1821501"
+ 55.38444606899999911320.send(@method).should == "55.384446069"
+ 5.78000000000000024869.send(@method).should == "5.78"
+ 2.88244999999999995666.send(@method).should == "2.88245"
+ 43.27709999999999723741.send(@method).should == "43.2771"
+ end
+
+ it "random values from divisions" do
+ (1.0 / 7).send(@method).should == "0.14285714285714285"
+
+ # 50.times do
+ # a = rand(10)
+ # b = rand(10)
+ # c = rand(10)
+ # d = rand(10)
+ # expression = "#{a}.#{b} / #{c}.#{d}"
+ # puts " (#{expression}).send(@method).should == #{eval(expression).send(@method).inspect}"
+ # end
+
+ (1.1 / 7.1).send(@method).should == "0.15492957746478875"
+ (6.5 / 8.8).send(@method).should == "0.7386363636363635"
+ (4.8 / 4.3).send(@method).should == "1.1162790697674418"
+ (4.0 / 1.9).send(@method).should == "2.1052631578947367"
+ (9.1 / 0.8).send(@method).should == "11.374999999999998"
+ (5.3 / 7.5).send(@method).should == "0.7066666666666667"
+ (2.8 / 1.8).send(@method).should == "1.5555555555555554"
+ (2.1 / 2.5).send(@method).should == "0.8400000000000001"
+ (3.5 / 6.0).send(@method).should == "0.5833333333333334"
+ (4.6 / 0.3).send(@method).should == "15.333333333333332"
+ (0.6 / 2.4).send(@method).should == "0.25"
+ (1.3 / 9.1).send(@method).should == "0.14285714285714288"
+ (0.3 / 5.0).send(@method).should == "0.06"
+ (5.0 / 4.2).send(@method).should == "1.1904761904761905"
+ (3.0 / 2.0).send(@method).should == "1.5"
+ (6.3 / 2.0).send(@method).should == "3.15"
+ (5.4 / 6.0).send(@method).should == "0.9"
+ (9.6 / 8.1).send(@method).should == "1.1851851851851851"
+ (8.7 / 1.6).send(@method).should == "5.437499999999999"
+ (1.9 / 7.8).send(@method).should == "0.24358974358974358"
+ (0.5 / 2.1).send(@method).should == "0.23809523809523808"
+ (9.3 / 5.8).send(@method).should == "1.6034482758620692"
+ (2.7 / 8.0).send(@method).should == "0.3375"
+ (9.7 / 7.8).send(@method).should == "1.2435897435897436"
+ (8.1 / 2.4).send(@method).should == "3.375"
+ (7.7 / 2.7).send(@method).should == "2.8518518518518516"
+ (7.9 / 1.7).send(@method).should == "4.647058823529412"
+ (6.5 / 8.2).send(@method).should == "0.7926829268292683"
+ (7.8 / 9.6).send(@method).should == "0.8125"
+ (2.2 / 4.6).send(@method).should == "0.47826086956521746"
+ (0.0 / 1.0).send(@method).should == "0.0"
+ (8.3 / 2.9).send(@method).should == "2.8620689655172415"
+ (3.1 / 6.1).send(@method).should == "0.5081967213114754"
+ (2.8 / 7.8).send(@method).should == "0.358974358974359"
+ (8.0 / 0.1).send(@method).should == "80.0"
+ (1.7 / 6.4).send(@method).should == "0.265625"
+ (1.8 / 5.4).send(@method).should == "0.3333333333333333"
+ (8.0 / 5.8).send(@method).should == "1.3793103448275863"
+ (5.2 / 4.1).send(@method).should == "1.2682926829268295"
+ (9.8 / 5.8).send(@method).should == "1.6896551724137934"
+ (5.4 / 9.5).send(@method).should == "0.5684210526315789"
+ (8.4 / 4.9).send(@method).should == "1.7142857142857142"
+ (1.7 / 3.5).send(@method).should == "0.4857142857142857"
+ (1.2 / 5.1).send(@method).should == "0.23529411764705882"
+ (1.4 / 2.0).send(@method).should == "0.7"
+ (4.8 / 8.0).send(@method).should == "0.6"
+ (9.0 / 2.5).send(@method).should == "3.6"
+ (0.2 / 0.6).send(@method).should == "0.33333333333333337"
+ (7.8 / 5.2).send(@method).should == "1.5"
+ (9.5 / 5.5).send(@method).should == "1.7272727272727273"
+ end
+ end
+
+ describe 'encoding' do
+ before :each do
+ @internal = Encoding.default_internal
+ end
+
+ after :each do
+ Encoding.default_internal = @internal
+ end
+
+ it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do
+ Encoding.default_internal = nil
+ 1.23.send(@method).encoding.should equal(Encoding::US_ASCII)
+ end
+
+ it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do
+ Encoding.default_internal = Encoding::IBM437
+ 5.47.send(@method).encoding.should equal(Encoding::US_ASCII)
+ end
+ end
+end
diff --git a/spec/ruby/core/float/to_s_spec.rb b/spec/ruby/core/float/to_s_spec.rb
index ad04bc4fb6..6727a883f8 100644
--- a/spec/ruby/core/float/to_s_spec.rb
+++ b/spec/ruby/core/float/to_s_spec.rb
@@ -1,310 +1,6 @@
require_relative '../../spec_helper'
+require_relative 'shared/to_s'
describe "Float#to_s" do
- it "returns 'NaN' for NaN" do
- nan_value().to_s.should == 'NaN'
- end
-
- it "returns 'Infinity' for positive infinity" do
- infinity_value().to_s.should == 'Infinity'
- end
-
- it "returns '-Infinity' for negative infinity" do
- (-infinity_value()).to_s.should == '-Infinity'
- end
-
- it "returns '0.0' for 0.0" do
- 0.0.to_s.should == "0.0"
- end
-
- platform_is_not :openbsd do
- it "emits '-' for -0.0" do
- -0.0.to_s.should == "-0.0"
- end
- end
-
- it "emits a '-' for negative values" do
- -3.14.to_s.should == "-3.14"
- end
-
- it "emits a trailing '.0' for a whole number" do
- 50.0.to_s.should == "50.0"
- end
-
- it "emits a trailing '.0' for the mantissa in e format" do
- 1.0e20.to_s.should == "1.0e+20"
- end
-
- it "uses non-e format for a positive value with fractional part having 5 significant figures" do
- 0.0001.to_s.should == "0.0001"
- end
-
- it "uses non-e format for a negative value with fractional part having 5 significant figures" do
- -0.0001.to_s.should == "-0.0001"
- end
-
- it "uses e format for a positive value with fractional part having 6 significant figures" do
- 0.00001.to_s.should == "1.0e-05"
- end
-
- it "uses e format for a negative value with fractional part having 6 significant figures" do
- -0.00001.to_s.should == "-1.0e-05"
- end
-
- it "uses non-e format for a positive value with whole part having 15 significant figures" do
- 10000000000000.0.to_s.should == "10000000000000.0"
- end
-
- it "uses non-e format for a negative value with whole part having 15 significant figures" do
- -10000000000000.0.to_s.should == "-10000000000000.0"
- end
-
- it "uses non-e format for a positive value with whole part having 16 significant figures" do
- 100000000000000.0.to_s.should == "100000000000000.0"
- end
-
- it "uses non-e format for a negative value with whole part having 16 significant figures" do
- -100000000000000.0.to_s.should == "-100000000000000.0"
- end
-
- it "uses e format for a positive value with whole part having 18 significant figures" do
- 10000000000000000.0.to_s.should == "1.0e+16"
- end
-
- it "uses e format for a negative value with whole part having 18 significant figures" do
- -10000000000000000.0.to_s.should == "-1.0e+16"
- end
-
- it "uses e format for a positive value with whole part having 17 significant figures" do
- 1000000000000000.0.to_s.should == "1.0e+15"
- end
-
- it "uses e format for a negative value with whole part having 17 significant figures" do
- -1000000000000000.0.to_s.should == "-1.0e+15"
- end
-
- # #3273
- it "outputs the minimal, unique form necessary to recreate the value" do
- value = 0.21611564636388508
- string = "0.21611564636388508"
-
- value.to_s.should == string
- string.to_f.should == value
- end
-
- it "outputs the minimal, unique form to represent the value" do
- 0.56.to_s.should == "0.56"
- end
-
- describe "matches" do
- it "random examples in all ranges" do
- # 50.times do
- # bytes = (0...8).map { rand(256) }
- # string = bytes.pack('C8')
- # float = string.unpack('D').first
- # puts "#{'%.20g' % float}.to_s.should == #{float.to_s.inspect}"
- # end
-
- 2.5540217314354050325e+163.to_s.should == "2.554021731435405e+163"
- 2.5492588360356597544e-172.to_s.should == "2.5492588360356598e-172"
- 1.742770260934704852e-82.to_s.should == "1.7427702609347049e-82"
- 6.2108093676180883209e-104.to_s.should == "6.210809367618088e-104"
- -3.3448803488331067402e-143.to_s.should == "-3.3448803488331067e-143"
- -2.2740074343500832557e-168.to_s.should == "-2.2740074343500833e-168"
- 7.0587971678048535732e+191.to_s.should == "7.058797167804854e+191"
- -284438.88327586348169.to_s.should == "-284438.8832758635"
- 3.953272468476091301e+105.to_s.should == "3.9532724684760913e+105"
- -3.6361359552959847853e+100.to_s.should == "-3.636135955295985e+100"
- -1.3222325865575206185e-31.to_s.should == "-1.3222325865575206e-31"
- 1.1440138916932761366e+130.to_s.should == "1.1440138916932761e+130"
- 4.8750891560387561157e-286.to_s.should == "4.875089156038756e-286"
- 5.6101113356591453525e-257.to_s.should == "5.610111335659145e-257"
- -3.829644279545809575e-100.to_s.should == "-3.8296442795458096e-100"
- 1.5342839401396406117e-194.to_s.should == "1.5342839401396406e-194"
- 2.2284972755169921402e-144.to_s.should == "2.228497275516992e-144"
- 2.1825655917065601737e-61.to_s.should == "2.1825655917065602e-61"
- -2.6672271363524338322e-62.to_s.should == "-2.667227136352434e-62"
- -1.9257995160119059415e+21.to_s.should == "-1.925799516011906e+21"
- -8.9096732962887121718e-198.to_s.should == "-8.909673296288712e-198"
- 2.0202075376548644959e-90.to_s.should == "2.0202075376548645e-90"
- -7.7341602581786258961e-266.to_s.should == "-7.734160258178626e-266"
- 3.5134482598733635046e+98.to_s.should == "3.5134482598733635e+98"
- -2.124411722371029134e+154.to_s.should == "-2.124411722371029e+154"
- -4.573908787355718687e+110.to_s.should == "-4.573908787355719e+110"
- -1.9344425934170969879e-232.to_s.should == "-1.934442593417097e-232"
- -1.3274227399979271095e+171.to_s.should == "-1.3274227399979271e+171"
- 9.3495270482104442383e-283.to_s.should == "9.349527048210444e-283"
- -4.2046059371986483233e+307.to_s.should == "-4.2046059371986483e+307"
- 3.6133547278583543004e-117.to_s.should == "3.613354727858354e-117"
- 4.9247416523566613499e-08.to_s.should == "4.9247416523566613e-08"
- 1.6936145488250064007e-71.to_s.should == "1.6936145488250064e-71"
- 2.4455483206829433098e+96.to_s.should == "2.4455483206829433e+96"
- 7.9797449851436455384e+124.to_s.should == "7.979744985143646e+124"
- -1.3873689634457876774e-129.to_s.should == "-1.3873689634457877e-129"
- 3.9761102037533483075e+284.to_s.should == "3.976110203753348e+284"
- -4.2819791952139402486e-303.to_s.should == "-4.28197919521394e-303"
- -5.7981017546689831298e-116.to_s.should == "-5.798101754668983e-116"
- -3.953266497860534199e-28.to_s.should == "-3.953266497860534e-28"
- -2.0659852720290440959e-243.to_s.should == "-2.065985272029044e-243"
- 8.9670488995878688018e-05.to_s.should == "8.967048899587869e-05"
- -1.2317943708113061768e-98.to_s.should == "-1.2317943708113062e-98"
- -3.8930768307633080463e+248.to_s.should == "-3.893076830763308e+248"
- 6.5854032671803925627e-239.to_s.should == "6.5854032671803926e-239"
- 4.6257022188980878952e+177.to_s.should == "4.625702218898088e+177"
- -1.9397155125507235603e-187.to_s.should == "-1.9397155125507236e-187"
- 8.5752156951245705056e+117.to_s.should == "8.57521569512457e+117"
- -2.4784875958162501671e-132.to_s.should == "-2.4784875958162502e-132"
- -4.4125691841230058457e-203.to_s.should == "-4.412569184123006e-203"
- end
-
- it "random examples in human ranges" do
- # 50.times do
- # formatted = ''
- # rand(1..3).times do
- # formatted << rand(10).to_s
- # end
- # formatted << '.'
- # rand(1..9).times do
- # formatted << rand(10).to_s
- # end
- # float = formatted.to_f
- # puts "#{'%.20f' % float}.to_s.should == #{float.to_s.inspect}"
- # end
-
- 5.17869899999999994122.to_s.should == "5.178699"
- 905.62695729999995819526.to_s.should == "905.6269573"
- 62.75999999999999801048.to_s.should == "62.76"
- 6.93856795800000014651.to_s.should == "6.938567958"
- 4.95999999999999996447.to_s.should == "4.96"
- 32.77993899999999882766.to_s.should == "32.779939"
- 544.12756779999995160324.to_s.should == "544.1275678"
- 66.25801119999999855281.to_s.should == "66.2580112"
- 7.90000000000000035527.to_s.should == "7.9"
- 5.93100000000000004974.to_s.should == "5.931"
- 5.21229313600000043749.to_s.should == "5.212293136"
- 503.44173809000000119340.to_s.should == "503.44173809"
- 79.26000000000000511591.to_s.should == "79.26"
- 8.51524999999999998579.to_s.should == "8.51525"
- 174.00000000000000000000.to_s.should == "174.0"
- 50.39580000000000126192.to_s.should == "50.3958"
- 35.28999999999999914735.to_s.should == "35.29"
- 5.43136675399999990788.to_s.should == "5.431366754"
- 654.07680000000004838512.to_s.should == "654.0768"
- 6.07423700000000010846.to_s.should == "6.074237"
- 102.25779799999999397642.to_s.should == "102.257798"
- 5.08129999999999970584.to_s.should == "5.0813"
- 6.00000000000000000000.to_s.should == "6.0"
- 8.30000000000000071054.to_s.should == "8.3"
- 32.68345999999999662577.to_s.should == "32.68346"
- 581.11170000000004165486.to_s.should == "581.1117"
- 76.31342999999999676675.to_s.should == "76.31343"
- 438.30826000000001840817.to_s.should == "438.30826"
- 482.06631994000002805478.to_s.should == "482.06631994"
- 55.92721026899999969828.to_s.should == "55.927210269"
- 4.00000000000000000000.to_s.should == "4.0"
- 55.86693999999999959982.to_s.should == "55.86694"
- 787.98299999999994724931.to_s.should == "787.983"
- 5.73810511000000023074.to_s.should == "5.73810511"
- 74.51926810000000500622.to_s.should == "74.5192681"
- 892.89999999999997726263.to_s.should == "892.9"
- 68.27299999999999613465.to_s.should == "68.273"
- 904.10000000000002273737.to_s.should == "904.1"
- 5.23200000000000020606.to_s.should == "5.232"
- 4.09628000000000014325.to_s.should == "4.09628"
- 46.05152633699999853434.to_s.should == "46.051526337"
- 142.12884990599999923688.to_s.should == "142.128849906"
- 3.83057023500000015659.to_s.should == "3.830570235"
- 11.81684594699999912848.to_s.should == "11.816845947"
- 80.50000000000000000000.to_s.should == "80.5"
- 382.18215010000000120272.to_s.should == "382.1821501"
- 55.38444606899999911320.to_s.should == "55.384446069"
- 5.78000000000000024869.to_s.should == "5.78"
- 2.88244999999999995666.to_s.should == "2.88245"
- 43.27709999999999723741.to_s.should == "43.2771"
- end
-
- it "random values from divisions" do
- (1.0 / 7).to_s.should == "0.14285714285714285"
-
- # 50.times do
- # a = rand(10)
- # b = rand(10)
- # c = rand(10)
- # d = rand(10)
- # expression = "#{a}.#{b} / #{c}.#{d}"
- # puts " (#{expression}).to_s.should == #{eval(expression).to_s.inspect}"
- # end
-
- (1.1 / 7.1).to_s.should == "0.15492957746478875"
- (6.5 / 8.8).to_s.should == "0.7386363636363635"
- (4.8 / 4.3).to_s.should == "1.1162790697674418"
- (4.0 / 1.9).to_s.should == "2.1052631578947367"
- (9.1 / 0.8).to_s.should == "11.374999999999998"
- (5.3 / 7.5).to_s.should == "0.7066666666666667"
- (2.8 / 1.8).to_s.should == "1.5555555555555554"
- (2.1 / 2.5).to_s.should == "0.8400000000000001"
- (3.5 / 6.0).to_s.should == "0.5833333333333334"
- (4.6 / 0.3).to_s.should == "15.333333333333332"
- (0.6 / 2.4).to_s.should == "0.25"
- (1.3 / 9.1).to_s.should == "0.14285714285714288"
- (0.3 / 5.0).to_s.should == "0.06"
- (5.0 / 4.2).to_s.should == "1.1904761904761905"
- (3.0 / 2.0).to_s.should == "1.5"
- (6.3 / 2.0).to_s.should == "3.15"
- (5.4 / 6.0).to_s.should == "0.9"
- (9.6 / 8.1).to_s.should == "1.1851851851851851"
- (8.7 / 1.6).to_s.should == "5.437499999999999"
- (1.9 / 7.8).to_s.should == "0.24358974358974358"
- (0.5 / 2.1).to_s.should == "0.23809523809523808"
- (9.3 / 5.8).to_s.should == "1.6034482758620692"
- (2.7 / 8.0).to_s.should == "0.3375"
- (9.7 / 7.8).to_s.should == "1.2435897435897436"
- (8.1 / 2.4).to_s.should == "3.375"
- (7.7 / 2.7).to_s.should == "2.8518518518518516"
- (7.9 / 1.7).to_s.should == "4.647058823529412"
- (6.5 / 8.2).to_s.should == "0.7926829268292683"
- (7.8 / 9.6).to_s.should == "0.8125"
- (2.2 / 4.6).to_s.should == "0.47826086956521746"
- (0.0 / 1.0).to_s.should == "0.0"
- (8.3 / 2.9).to_s.should == "2.8620689655172415"
- (3.1 / 6.1).to_s.should == "0.5081967213114754"
- (2.8 / 7.8).to_s.should == "0.358974358974359"
- (8.0 / 0.1).to_s.should == "80.0"
- (1.7 / 6.4).to_s.should == "0.265625"
- (1.8 / 5.4).to_s.should == "0.3333333333333333"
- (8.0 / 5.8).to_s.should == "1.3793103448275863"
- (5.2 / 4.1).to_s.should == "1.2682926829268295"
- (9.8 / 5.8).to_s.should == "1.6896551724137934"
- (5.4 / 9.5).to_s.should == "0.5684210526315789"
- (8.4 / 4.9).to_s.should == "1.7142857142857142"
- (1.7 / 3.5).to_s.should == "0.4857142857142857"
- (1.2 / 5.1).to_s.should == "0.23529411764705882"
- (1.4 / 2.0).to_s.should == "0.7"
- (4.8 / 8.0).to_s.should == "0.6"
- (9.0 / 2.5).to_s.should == "3.6"
- (0.2 / 0.6).to_s.should == "0.33333333333333337"
- (7.8 / 5.2).to_s.should == "1.5"
- (9.5 / 5.5).to_s.should == "1.7272727272727273"
- end
- end
-end
-
-describe "Float#to_s" do
- before :each do
- @internal = Encoding.default_internal
- end
-
- after :each do
- Encoding.default_internal = @internal
- end
-
- it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do
- Encoding.default_internal = nil
- 1.23.to_s.encoding.should equal(Encoding::US_ASCII)
- end
-
- it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do
- Encoding.default_internal = Encoding::IBM437
- 5.47.to_s.encoding.should equal(Encoding::US_ASCII)
- end
+ it_behaves_like :float_to_s, :to_s
end
diff --git a/spec/ruby/core/float/uminus_spec.rb b/spec/ruby/core/float/uminus_spec.rb
index e676a26ada..57bae0fb4b 100644
--- a/spec/ruby/core/float/uminus_spec.rb
+++ b/spec/ruby/core/float/uminus_spec.rb
@@ -23,6 +23,6 @@ describe "Float#-@" do
end
it "returns NaN for NaN" do
- nan_value.send(:-@).nan?.should == true
+ nan_value.send(:-@).should.nan?
end
end
diff --git a/spec/ruby/core/float/zero_spec.rb b/spec/ruby/core/float/zero_spec.rb
index e70edc422a..1f3de27793 100644
--- a/spec/ruby/core/float/zero_spec.rb
+++ b/spec/ruby/core/float/zero_spec.rb
@@ -2,8 +2,8 @@ require_relative '../../spec_helper'
describe "Float#zero?" do
it "returns true if self is 0.0" do
- 0.0.zero?.should == true
- 1.0.zero?.should == false
- -1.0.zero?.should == false
+ 0.0.should.zero?
+ 1.0.should_not.zero?
+ -1.0.should_not.zero?
end
end
diff --git a/spec/ruby/core/gc/profiler/disable_spec.rb b/spec/ruby/core/gc/profiler/disable_spec.rb
index 321a207deb..74089693eb 100644
--- a/spec/ruby/core/gc/profiler/disable_spec.rb
+++ b/spec/ruby/core/gc/profiler/disable_spec.rb
@@ -11,6 +11,6 @@ describe "GC::Profiler.disable" do
it "disables the profiler" do
GC::Profiler.disable
- GC::Profiler.enabled?.should == false
+ GC::Profiler.should_not.enabled?
end
end
diff --git a/spec/ruby/core/gc/profiler/enable_spec.rb b/spec/ruby/core/gc/profiler/enable_spec.rb
index 1594511675..313ca3d949 100644
--- a/spec/ruby/core/gc/profiler/enable_spec.rb
+++ b/spec/ruby/core/gc/profiler/enable_spec.rb
@@ -12,6 +12,6 @@ describe "GC::Profiler.enable" do
it "enables the profiler" do
GC::Profiler.enable
- GC::Profiler.enabled?.should == true
+ GC::Profiler.should.enabled?
end
end
diff --git a/spec/ruby/core/gc/start_spec.rb b/spec/ruby/core/gc/start_spec.rb
index fb6820db14..c941058969 100644
--- a/spec/ruby/core/gc/start_spec.rb
+++ b/spec/ruby/core/gc/start_spec.rb
@@ -5,4 +5,8 @@ describe "GC.start" do
GC.start.should == nil
GC.start.should == nil
end
+
+ it "accepts keyword arguments" do
+ GC.start(full_mark: true, immediate_sweep: true).should == nil
+ end
end
diff --git a/spec/ruby/core/hash/any_spec.rb b/spec/ruby/core/hash/any_spec.rb
index bd33e8cd8f..c26dfabde6 100644
--- a/spec/ruby/core/hash/any_spec.rb
+++ b/spec/ruby/core/hash/any_spec.rb
@@ -4,10 +4,10 @@ describe "Hash#any?" do
describe 'with no block given' do
it "checks if there are any members of a Hash" do
empty_hash = {}
- empty_hash.any?.should == false
+ empty_hash.should_not.any?
hash_with_members = { 'key' => 'value' }
- hash_with_members.any?.should == true
+ hash_with_members.should.any?
end
end
diff --git a/spec/ruby/core/hash/clear_spec.rb b/spec/ruby/core/hash/clear_spec.rb
index e7816acbbc..cf05e36ac9 100644
--- a/spec/ruby/core/hash/clear_spec.rb
+++ b/spec/ruby/core/hash/clear_spec.rb
@@ -25,8 +25,8 @@ describe "Hash#clear" do
h.default_proc.should_not == nil
end
- it "raises a #{frozen_error_class} if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.clear }.should raise_error(frozen_error_class)
- -> { HashSpecs.empty_frozen_hash.clear }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance" do
+ -> { HashSpecs.frozen_hash.clear }.should raise_error(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.clear }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/compact_spec.rb b/spec/ruby/core/hash/compact_spec.rb
index ec9d4b5d79..2989afc8b7 100644
--- a/spec/ruby/core/hash/compact_spec.rb
+++ b/spec/ruby/core/hash/compact_spec.rb
@@ -51,8 +51,8 @@ describe "Hash#compact!" do
@hash.freeze
end
- it "keeps pairs and raises a #{frozen_error_class}" do
- ->{ @hash.compact! }.should raise_error(frozen_error_class)
+ it "keeps pairs and raises a FrozenError" do
+ ->{ @hash.compact! }.should raise_error(FrozenError)
@hash.should == @initial_pairs
end
end
diff --git a/spec/ruby/core/hash/compare_by_identity_spec.rb b/spec/ruby/core/hash/compare_by_identity_spec.rb
index 0658b4954a..874cd46eb7 100644
--- a/spec/ruby/core/hash/compare_by_identity_spec.rb
+++ b/spec/ruby/core/hash/compare_by_identity_spec.rb
@@ -33,7 +33,7 @@ describe "Hash#compare_by_identity" do
it "has no effect on an already compare_by_identity hash" do
@idh[:foo] = :bar
@idh.compare_by_identity.should equal @idh
- @idh.compare_by_identity?.should == true
+ @idh.should.compare_by_identity?
@idh[:foo].should == :bar
end
@@ -80,9 +80,9 @@ describe "Hash#compare_by_identity" do
@h[o].should == :o
end
- it "raises a #{frozen_error_class} on frozen hashes" do
+ it "raises a FrozenError on frozen hashes" do
@h = @h.freeze
- -> { @h.compare_by_identity }.should raise_error(frozen_error_class)
+ -> { @h.compare_by_identity }.should raise_error(FrozenError)
end
# Behaviour confirmed in bug #1871
diff --git a/spec/ruby/core/hash/deconstruct_keys_spec.rb b/spec/ruby/core/hash/deconstruct_keys_spec.rb
new file mode 100644
index 0000000000..b265732616
--- /dev/null
+++ b/spec/ruby/core/hash/deconstruct_keys_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "2.7" do
+ describe "Hash#deconstruct_keys" do
+ it "returns self" do
+ hash = {a: 1, b: 2}
+
+ hash.deconstruct_keys([:a, :b]).should equal hash
+ end
+
+ it "requires one argument" do
+ -> {
+ {a: 1}.deconstruct_keys
+ }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
+ end
+
+ it "ignores argument" do
+ hash = {a: 1, b: 2}
+
+ hash.deconstruct_keys([:a]).should == {a: 1, b: 2}
+ hash.deconstruct_keys(0 ).should == {a: 1, b: 2}
+ hash.deconstruct_keys('' ).should == {a: 1, b: 2}
+ end
+ end
+end
diff --git a/spec/ruby/core/hash/default_proc_spec.rb b/spec/ruby/core/hash/default_proc_spec.rb
index 83ad98e5b6..f4e4803632 100644
--- a/spec/ruby/core/hash/default_proc_spec.rb
+++ b/spec/ruby/core/hash/default_proc_spec.rb
@@ -73,8 +73,8 @@ describe "Hash#default_proc=" do
end.should raise_error(TypeError)
end
- it "raises a #{frozen_error_class} if self is frozen" do
- -> { {}.freeze.default_proc = Proc.new {} }.should raise_error(frozen_error_class)
- -> { {}.freeze.default_proc = nil }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if self is frozen" do
+ -> { {}.freeze.default_proc = Proc.new {} }.should raise_error(FrozenError)
+ -> { {}.freeze.default_proc = nil }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/default_spec.rb b/spec/ruby/core/hash/default_spec.rb
index 6cad65bb62..d8b62ea196 100644
--- a/spec/ruby/core/hash/default_spec.rb
+++ b/spec/ruby/core/hash/default_spec.rb
@@ -39,8 +39,8 @@ describe "Hash#default=" do
end
end
- it "raises a #{frozen_error_class} if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.default = nil }.should raise_error(frozen_error_class)
- -> { HashSpecs.empty_frozen_hash.default = nil }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance" do
+ -> { HashSpecs.frozen_hash.default = nil }.should raise_error(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.default = nil }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/delete_if_spec.rb b/spec/ruby/core/hash/delete_if_spec.rb
index 345a24a726..c9e670ffc3 100644
--- a/spec/ruby/core/hash/delete_if_spec.rb
+++ b/spec/ruby/core/hash/delete_if_spec.rb
@@ -34,9 +34,9 @@ describe "Hash#delete_if" do
each_pairs.should == delete_pairs
end
- it "raises a #{frozen_error_class} if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.delete_if { false } }.should raise_error(frozen_error_class)
- -> { HashSpecs.empty_frozen_hash.delete_if { true } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance" do
+ -> { HashSpecs.frozen_hash.delete_if { false } }.should raise_error(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.delete_if { true } }.should raise_error(FrozenError)
end
it_behaves_like :hash_iteration_no_block, :delete_if
diff --git a/spec/ruby/core/hash/delete_spec.rb b/spec/ruby/core/hash/delete_spec.rb
index a69815c1d9..b262e8846b 100644
--- a/spec/ruby/core/hash/delete_spec.rb
+++ b/spec/ruby/core/hash/delete_spec.rb
@@ -37,8 +37,8 @@ describe "Hash#delete" do
{ key => 5 }.delete(key).should == 5
end
- it "raises a #{frozen_error_class} if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.delete("foo") }.should raise_error(frozen_error_class)
- -> { HashSpecs.empty_frozen_hash.delete("foo") }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance" do
+ -> { HashSpecs.frozen_hash.delete("foo") }.should raise_error(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.delete("foo") }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/element_reference_spec.rb b/spec/ruby/core/hash/element_reference_spec.rb
index 2eb65d3789..e271f37ea6 100644
--- a/spec/ruby/core/hash/element_reference_spec.rb
+++ b/spec/ruby/core/hash/element_reference_spec.rb
@@ -117,4 +117,18 @@ describe "Hash#[]" do
key = HashSpecs::KeyWithPrivateHash.new
{ key => 42 }[key].should == 42
end
+
+ it "does not dispatch to hash for Boolean, Integer, Float, String, or Symbol" do
+ code = <<-EOC
+ load '#{fixture __FILE__, "name.rb"}'
+ hash = { true => 42, false => 42, 1 => 42, 2.0 => 42, "hello" => 42, :ok => 42 }
+ [true, false, 1, 2.0, "hello", :ok].each do |value|
+ raise "incorrect value" unless hash[value] == 42
+ end
+ puts "Ok."
+ EOC
+ result = ruby_exe(code, args: "2>&1")
+ result.should == "Ok.\n"
+ end
+
end
diff --git a/spec/ruby/core/hash/empty_spec.rb b/spec/ruby/core/hash/empty_spec.rb
index e9be44bab0..881e1cc34b 100644
--- a/spec/ruby/core/hash/empty_spec.rb
+++ b/spec/ruby/core/hash/empty_spec.rb
@@ -3,13 +3,13 @@ require_relative 'fixtures/classes'
describe "Hash#empty?" do
it "returns true if the hash has no entries" do
- {}.empty?.should == true
- { 1 => 1 }.empty?.should == false
+ {}.should.empty?
+ { 1 => 1 }.should_not.empty?
end
it "returns true if the hash has no entries and has a default value" do
- Hash.new(5).empty?.should == true
- Hash.new { 5 }.empty?.should == true
- Hash.new { |hsh, k| hsh[k] = k }.empty?.should == true
+ Hash.new(5).should.empty?
+ Hash.new { 5 }.should.empty?
+ Hash.new { |hsh, k| hsh[k] = k }.should.empty?
end
end
diff --git a/spec/ruby/core/hash/except_spec.rb b/spec/ruby/core/hash/except_spec.rb
new file mode 100644
index 0000000000..82cfced72f
--- /dev/null
+++ b/spec/ruby/core/hash/except_spec.rb
@@ -0,0 +1,34 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.0" do
+ describe "Hash#except" do
+ before :each do
+ @hash = { a: 1, b: 2, c: 3 }
+ end
+
+ it "returns a new duplicate hash without arguments" do
+ ret = @hash.except
+ ret.should_not equal(@hash)
+ ret.should == @hash
+ end
+
+ it "returns a hash without the requested subset" do
+ @hash.except(:c, :a).should == { b: 2 }
+ end
+
+ it "ignores keys not present in the original hash" do
+ @hash.except(:a, :chunky_bacon).should == { b: 2, c: 3 }
+ end
+
+ it "always returns a Hash without a default" do
+ klass = Class.new(Hash)
+ h = klass.new(:default)
+ h[:bar] = 12
+ h[:foo] = 42
+ r = h.except(:foo)
+ r.should == {bar: 12}
+ r.class.should == Hash
+ r.default.should == nil
+ end
+ end
+end
diff --git a/spec/ruby/core/hash/fixtures/name.rb b/spec/ruby/core/hash/fixtures/name.rb
new file mode 100644
index 0000000000..b203bf6ae4
--- /dev/null
+++ b/spec/ruby/core/hash/fixtures/name.rb
@@ -0,0 +1,30 @@
+class TrueClass
+ def hash
+ raise "TrueClass#hash should not be called"
+ end
+end
+class FalseClass
+ def hash
+ raise "FalseClass#hash should not be called"
+ end
+end
+class Integer
+ def hash
+ raise "Integer#hash should not be called"
+ end
+end
+class Float
+ def hash
+ raise "Float#hash should not be called"
+ end
+end
+class String
+ def hash
+ raise "String#hash should not be called"
+ end
+end
+class Symbol
+ def hash
+ raise "Symbol#hash should not be called"
+ end
+end
diff --git a/spec/ruby/core/hash/index_spec.rb b/spec/ruby/core/hash/index_spec.rb
index 2b52c69949..be4e2cc6ab 100644
--- a/spec/ruby/core/hash/index_spec.rb
+++ b/spec/ruby/core/hash/index_spec.rb
@@ -2,6 +2,8 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/index'
-describe "Hash#index" do
- it_behaves_like :hash_index, :index
+ruby_version_is ''...'3.0' do
+ describe "Hash#index" do
+ it_behaves_like :hash_index, :index
+ end
end
diff --git a/spec/ruby/core/hash/initialize_spec.rb b/spec/ruby/core/hash/initialize_spec.rb
index 00e1174ec8..d13496ba3b 100644
--- a/spec/ruby/core/hash/initialize_spec.rb
+++ b/spec/ruby/core/hash/initialize_spec.rb
@@ -45,17 +45,17 @@ describe "Hash#initialize" do
h.send(:initialize).should equal(h)
end
- it "raises a #{frozen_error_class} if called on a frozen instance" do
+ it "raises a FrozenError if called on a frozen instance" do
block = -> { HashSpecs.frozen_hash.instance_eval { initialize() }}
- block.should raise_error(frozen_error_class)
+ block.should raise_error(FrozenError)
block = -> { HashSpecs.frozen_hash.instance_eval { initialize(nil) } }
- block.should raise_error(frozen_error_class)
+ block.should raise_error(FrozenError)
block = -> { HashSpecs.frozen_hash.instance_eval { initialize(5) } }
- block.should raise_error(frozen_error_class)
+ block.should raise_error(FrozenError)
block = -> { HashSpecs.frozen_hash.instance_eval { initialize { 5 } } }
- block.should raise_error(frozen_error_class)
+ block.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/keep_if_spec.rb b/spec/ruby/core/hash/keep_if_spec.rb
index 278eafc969..d50d969467 100644
--- a/spec/ruby/core/hash/keep_if_spec.rb
+++ b/spec/ruby/core/hash/keep_if_spec.rb
@@ -27,9 +27,9 @@ describe "Hash#keep_if" do
h.keep_if { true }.should equal(h)
end
- it "raises a #{frozen_error_class} if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.keep_if { true } }.should raise_error(frozen_error_class)
- -> { HashSpecs.empty_frozen_hash.keep_if { false } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance" do
+ -> { HashSpecs.frozen_hash.keep_if { true } }.should raise_error(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.keep_if { false } }.should raise_error(FrozenError)
end
it_behaves_like :hash_iteration_no_block, :keep_if
diff --git a/spec/ruby/core/hash/rehash_spec.rb b/spec/ruby/core/hash/rehash_spec.rb
index 587935fc43..ff7b644786 100644
--- a/spec/ruby/core/hash/rehash_spec.rb
+++ b/spec/ruby/core/hash/rehash_spec.rb
@@ -59,8 +59,8 @@ describe "Hash#rehash" do
h.keys.should == [a]
end
- it "raises a #{frozen_error_class} if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.rehash }.should raise_error(frozen_error_class)
- -> { HashSpecs.empty_frozen_hash.rehash }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance" do
+ -> { HashSpecs.frozen_hash.rehash }.should raise_error(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.rehash }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/reject_spec.rb b/spec/ruby/core/hash/reject_spec.rb
index 1051ebd76c..397000ab67 100644
--- a/spec/ruby/core/hash/reject_spec.rb
+++ b/spec/ruby/core/hash/reject_spec.rb
@@ -35,7 +35,7 @@ describe "Hash#reject" do
ruby_version_is ''...'2.7' do
it "does not taint the resulting hash" do
h = { a: 1 }.taint
- h.reject {false}.tainted?.should == false
+ h.reject {false}.should_not.tainted?
end
end
end
@@ -89,12 +89,12 @@ describe "Hash#reject!" do
reject_bang_pairs.should == delete_if_pairs
end
- it "raises a #{frozen_error_class} if called on a frozen instance that is modified" do
- -> { HashSpecs.empty_frozen_hash.reject! { true } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance that is modified" do
+ -> { HashSpecs.empty_frozen_hash.reject! { true } }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} if called on a frozen instance that would not be modified" do
- -> { HashSpecs.frozen_hash.reject! { false } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance that would not be modified" do
+ -> { HashSpecs.frozen_hash.reject! { false } }.should raise_error(FrozenError)
end
it_behaves_like :hash_iteration_no_block, :reject!
diff --git a/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb b/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb
new file mode 100644
index 0000000000..005886a482
--- /dev/null
+++ b/spec/ruby/core/hash/ruby2_keywords_hash_spec.rb
@@ -0,0 +1,47 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "2.7" do
+ describe "Hash.ruby2_keywords_hash?" do
+ it "returns false if the Hash is not a keywords Hash" do
+ Hash.ruby2_keywords_hash?({}).should == false
+ end
+
+ it "returns true if the Hash is a keywords Hash marked by Module#ruby2_keywords" do
+ obj = Class.new {
+ ruby2_keywords def m(*args)
+ args.last
+ end
+ }.new
+ Hash.ruby2_keywords_hash?(obj.m(a: 1)).should == true
+ end
+
+ it "raises TypeError for non-Hash" do
+ -> { Hash.ruby2_keywords_hash?(nil) }.should raise_error(TypeError)
+ end
+ end
+
+ describe "Hash.ruby2_keywords_hash" do
+ it "returns a copy of a Hash and marks the copy as a keywords Hash" do
+ h = {a: 1}.freeze
+ kw = Hash.ruby2_keywords_hash(h)
+ Hash.ruby2_keywords_hash?(h).should == false
+ Hash.ruby2_keywords_hash?(kw).should == true
+ kw.should == h
+ end
+
+ it "returns an instance of the subclass if called on an instance of a subclass of Hash" do
+ h = HashSpecs::MyHash.new
+ h[:a] = 1
+ kw = Hash.ruby2_keywords_hash(h)
+ kw.class.should == HashSpecs::MyHash
+ Hash.ruby2_keywords_hash?(h).should == false
+ Hash.ruby2_keywords_hash?(kw).should == true
+ kw.should == h
+ end
+
+ it "raises TypeError for non-Hash" do
+ -> { Hash.ruby2_keywords_hash(nil) }.should raise_error(TypeError)
+ end
+ end
+end
diff --git a/spec/ruby/core/hash/shared/each.rb b/spec/ruby/core/hash/shared/each.rb
index d1f2e5f672..04a26b5c45 100644
--- a/spec/ruby/core/hash/shared/each.rb
+++ b/spec/ruby/core/hash/shared/each.rb
@@ -21,19 +21,37 @@ describe :hash_each, shared: true do
ary.sort.should == ["a", "b", "c"]
end
- it "yields 2 values and not an Array of 2 elements when given a callable of arity 2" do
- obj = Object.new
- def obj.foo(key, value)
- ScratchPad << key << value
+ ruby_version_is ""..."3.0" do
+ it "yields 2 values and not an Array of 2 elements when given a callable of arity 2" do
+ obj = Object.new
+ def obj.foo(key, value)
+ ScratchPad << key << value
+ end
+
+ ScratchPad.record([])
+ { "a" => 1 }.send(@method, &obj.method(:foo))
+ ScratchPad.recorded.should == ["a", 1]
+
+ ScratchPad.record([])
+ { "a" => 1 }.send(@method, &-> key, value { ScratchPad << key << value })
+ ScratchPad.recorded.should == ["a", 1]
end
+ end
- ScratchPad.record([])
- { "a" => 1 }.send(@method, &obj.method(:foo))
- ScratchPad.recorded.should == ["a", 1]
+ ruby_version_is "3.0" do
+ it "always yields an Array of 2 elements, even when given a callable of arity 2" do
+ obj = Object.new
+ def obj.foo(key, value)
+ end
+
+ -> {
+ { "a" => 1 }.send(@method, &obj.method(:foo))
+ }.should raise_error(ArgumentError)
- ScratchPad.record([])
- { "a" => 1 }.send(@method, &-> key, value { ScratchPad << key << value })
- ScratchPad.recorded.should == ["a", 1]
+ -> {
+ { "a" => 1 }.send(@method, &-> key, value { })
+ }.should raise_error(ArgumentError)
+ end
end
it "uses the same order as keys() and values()" do
diff --git a/spec/ruby/core/hash/shared/replace.rb b/spec/ruby/core/hash/shared/replace.rb
index b3d098763b..bea64384bb 100644
--- a/spec/ruby/core/hash/shared/replace.rb
+++ b/spec/ruby/core/hash/shared/replace.rb
@@ -37,15 +37,15 @@ describe :hash_replace, shared: true do
hash_a.default.should == hash_b.default
end
- it "raises a #{frozen_error_class} if called on a frozen instance that would not be modified" do
+ it "raises a FrozenError if called on a frozen instance that would not be modified" do
-> do
HashSpecs.frozen_hash.send(@method, HashSpecs.frozen_hash)
- end.should raise_error(frozen_error_class)
+ end.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} if called on a frozen instance that is modified" do
+ it "raises a FrozenError if called on a frozen instance that is modified" do
-> do
HashSpecs.frozen_hash.send(@method, HashSpecs.empty_frozen_hash)
- end.should raise_error(frozen_error_class)
+ end.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/hash/shared/select.rb b/spec/ruby/core/hash/shared/select.rb
index bb781817cb..5170af50d6 100644
--- a/spec/ruby/core/hash/shared/select.rb
+++ b/spec/ruby/core/hash/shared/select.rb
@@ -74,12 +74,12 @@ describe :hash_select!, shared: true do
{ a: 1 }.send(@method) { |k,v| v <= 1 }.should == nil
end
- it "raises a #{frozen_error_class} if called on an empty frozen instance" do
- -> { HashSpecs.empty_frozen_hash.send(@method) { false } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on an empty frozen instance" do
+ -> { HashSpecs.empty_frozen_hash.send(@method) { false } }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} if called on a frozen instance that would not be modified" do
- -> { HashSpecs.frozen_hash.send(@method) { true } }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance that would not be modified" do
+ -> { HashSpecs.frozen_hash.send(@method) { true } }.should raise_error(FrozenError)
end
it_should_behave_like :hash_iteration_no_block
diff --git a/spec/ruby/core/hash/shared/store.rb b/spec/ruby/core/hash/shared/store.rb
index ff40bef3ef..b823ea45ca 100644
--- a/spec/ruby/core/hash/shared/store.rb
+++ b/spec/ruby/core/hash/shared/store.rb
@@ -36,7 +36,7 @@ describe :hash_store, shared: true do
h[key].should == "foo"
end
- it " accepts keys with a Bignum hash" do
+ it " accepts keys with an Integer hash" do
o = mock(hash: 1 << 100)
h = {}
h[o] = 1
@@ -50,7 +50,7 @@ describe :hash_store, shared: true do
key << "bar"
h.should == { "foo" => 0 }
- h.keys[0].frozen?.should == true
+ h.keys[0].should.frozen?
end
it "doesn't duplicate and freeze already frozen string keys" do
@@ -86,8 +86,8 @@ describe :hash_store, shared: true do
h.keys.last.should_not equal(key2)
end
- it "raises a #{frozen_error_class} if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.send(@method, 1, 2) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance" do
+ -> { HashSpecs.frozen_hash.send(@method, 1, 2) }.should raise_error(FrozenError)
end
it "does not raise an exception if changing the value of an existing key during iteration" do
@@ -95,4 +95,21 @@ describe :hash_store, shared: true do
hash.each { hash.send(@method, 1, :foo) }
hash.should == {1 => :foo, 3 => 4, 5 => 6}
end
+
+ it "does not dispatch to hash for Boolean, Integer, Float, String, or Symbol" do
+ code = <<-EOC
+ load '#{fixture __FILE__, "name.rb"}'
+ hash = {}
+ [true, false, 1, 2.0, "hello", :ok].each do |value|
+ hash[value] = 42
+ raise "incorrect value" unless hash[value] == 42
+ hash[value] = 43
+ raise "incorrect value" unless hash[value] == 43
+ end
+ puts "OK"
+ puts hash.size
+ EOC
+ result = ruby_exe(code, args: "2>&1")
+ result.should == "OK\n6\n"
+ end
end
diff --git a/spec/ruby/core/hash/shared/update.rb b/spec/ruby/core/hash/shared/update.rb
index 3af41c450a..4bb20e5b85 100644
--- a/spec/ruby/core/hash/shared/update.rb
+++ b/spec/ruby/core/hash/shared/update.rb
@@ -34,10 +34,10 @@ describe :hash_update, shared: true do
merge_bang_pairs.should == merge_pairs
end
- it "raises a #{frozen_error_class} on a frozen instance that is modified" do
+ it "raises a FrozenError on a frozen instance that is modified" do
-> do
HashSpecs.frozen_hash.send(@method, 1 => 2)
- end.should raise_error(frozen_error_class)
+ end.should raise_error(FrozenError)
end
it "checks frozen status before coercing an object with #to_hash" do
@@ -47,14 +47,14 @@ describe :hash_update, shared: true do
def obj.to_hash() raise Exception, "should not receive #to_hash" end
obj.freeze
- -> { HashSpecs.frozen_hash.send(@method, obj) }.should raise_error(frozen_error_class)
+ -> { HashSpecs.frozen_hash.send(@method, obj) }.should raise_error(FrozenError)
end
# see redmine #1571
- it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do
+ it "raises a FrozenError on a frozen instance that would not be modified" do
-> do
HashSpecs.frozen_hash.send(@method, HashSpecs.empty_frozen_hash)
- end.should raise_error(frozen_error_class)
+ end.should raise_error(FrozenError)
end
it "does not raise an exception if changing the value of an existing key during iteration" do
diff --git a/spec/ruby/core/hash/shift_spec.rb b/spec/ruby/core/hash/shift_spec.rb
index d9f121e38b..9d43e640f5 100644
--- a/spec/ruby/core/hash/shift_spec.rb
+++ b/spec/ruby/core/hash/shift_spec.rb
@@ -57,9 +57,9 @@ describe "Hash#shift" do
h.should == {:c => 3}
end
- it "raises a #{frozen_error_class} if called on a frozen instance" do
- -> { HashSpecs.frozen_hash.shift }.should raise_error(frozen_error_class)
- -> { HashSpecs.empty_frozen_hash.shift }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if called on a frozen instance" do
+ -> { HashSpecs.frozen_hash.shift }.should raise_error(FrozenError)
+ -> { HashSpecs.empty_frozen_hash.shift }.should raise_error(FrozenError)
end
it "works when the hash is at capacity" do
diff --git a/spec/ruby/core/hash/slice_spec.rb b/spec/ruby/core/hash/slice_spec.rb
index f7717c9404..e3046d83d7 100644
--- a/spec/ruby/core/hash/slice_spec.rb
+++ b/spec/ruby/core/hash/slice_spec.rb
@@ -1,55 +1,53 @@
require_relative '../../spec_helper'
-ruby_version_is "2.5" do
- describe "Hash#slice" do
- before :each do
- @hash = { a: 1, b: 2, c: 3 }
- end
+describe "Hash#slice" do
+ before :each do
+ @hash = { a: 1, b: 2, c: 3 }
+ end
- it "returns a new empty hash without arguments" do
- ret = @hash.slice
- ret.should_not equal(@hash)
- ret.should be_an_instance_of(Hash)
- ret.should == {}
- end
+ it "returns a new empty hash without arguments" do
+ ret = @hash.slice
+ ret.should_not equal(@hash)
+ ret.should be_an_instance_of(Hash)
+ ret.should == {}
+ end
- it "returns the requested subset" do
- @hash.slice(:c, :a).should == { c: 3, a: 1 }
- end
+ it "returns the requested subset" do
+ @hash.slice(:c, :a).should == { c: 3, a: 1 }
+ end
- it "returns a hash ordered in the order of the requested keys" do
- @hash.slice(:c, :a).keys.should == [:c, :a]
- end
+ it "returns a hash ordered in the order of the requested keys" do
+ @hash.slice(:c, :a).keys.should == [:c, :a]
+ end
- it "returns only the keys of the original hash" do
- @hash.slice(:a, :chunky_bacon).should == { a: 1 }
- end
+ it "returns only the keys of the original hash" do
+ @hash.slice(:a, :chunky_bacon).should == { a: 1 }
+ end
- it "returns a Hash instance, even on subclasses" do
- klass = Class.new(Hash)
- h = klass.new
- h[:bar] = 12
- h[:foo] = 42
- r = h.slice(:foo)
- r.should == {foo: 42}
- r.class.should == Hash
- end
+ it "returns a Hash instance, even on subclasses" do
+ klass = Class.new(Hash)
+ h = klass.new
+ h[:bar] = 12
+ h[:foo] = 42
+ r = h.slice(:foo)
+ r.should == {foo: 42}
+ r.class.should == Hash
+ end
- it "uses the regular Hash#[] method, even on subclasses that override it" do
- ScratchPad.record []
- klass = Class.new(Hash) do
- def [](value)
- ScratchPad << :used_subclassed_operator
- super
- end
+ it "uses the regular Hash#[] method, even on subclasses that override it" do
+ ScratchPad.record []
+ klass = Class.new(Hash) do
+ def [](value)
+ ScratchPad << :used_subclassed_operator
+ super
end
+ end
- h = klass.new
- h[:bar] = 12
- h[:foo] = 42
- h.slice(:foo)
+ h = klass.new
+ h[:bar] = 12
+ h[:foo] = 42
+ h.slice(:foo)
- ScratchPad.recorded.should == []
- end
+ ScratchPad.recorded.should == []
end
end
diff --git a/spec/ruby/core/hash/to_proc_spec.rb b/spec/ruby/core/hash/to_proc_spec.rb
index 3e7e57d11f..8f5d21beb5 100644
--- a/spec/ruby/core/hash/to_proc_spec.rb
+++ b/spec/ruby/core/hash/to_proc_spec.rb
@@ -19,8 +19,20 @@ describe "Hash#to_proc" do
@proc = @hash.to_proc
end
- it "is not a lambda" do
- @proc.lambda?.should == false
+ ruby_version_is ""..."3.0" do
+ it "is not a lambda" do
+ @proc.should_not.lambda?
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "is a lambda" do
+ @proc.should.lambda?
+ end
+
+ it "has an arity of 1" do
+ @proc.arity.should == 1
+ end
end
it "raises ArgumentError if not passed exactly one argument" do
diff --git a/spec/ruby/core/hash/transform_keys_spec.rb b/spec/ruby/core/hash/transform_keys_spec.rb
index 32ac89b765..a7ea80d053 100644
--- a/spec/ruby/core/hash/transform_keys_spec.rb
+++ b/spec/ruby/core/hash/transform_keys_spec.rb
@@ -1,131 +1,139 @@
require_relative '../../spec_helper'
-ruby_version_is "2.5" do
- describe "Hash#transform_keys" do
- before :each do
- @hash = { a: 1, b: 2, c: 3 }
- end
+describe "Hash#transform_keys" do
+ before :each do
+ @hash = { a: 1, b: 2, c: 3 }
+ end
- it "returns new hash" do
- ret = @hash.transform_keys(&:succ)
- ret.should_not equal(@hash)
- ret.should be_an_instance_of(Hash)
- end
+ it "returns new hash" do
+ ret = @hash.transform_keys(&:succ)
+ ret.should_not equal(@hash)
+ ret.should be_an_instance_of(Hash)
+ end
- it "sets the result as transformed keys with the given block" do
- @hash.transform_keys(&:succ).should == { b: 1, c: 2, d: 3 }
- end
+ it "sets the result as transformed keys with the given block" do
+ @hash.transform_keys(&:succ).should == { b: 1, c: 2, d: 3 }
+ end
- it "keeps last pair if new keys conflict" do
- @hash.transform_keys { |_| :a }.should == { a: 3 }
- end
+ it "keeps last pair if new keys conflict" do
+ @hash.transform_keys { |_| :a }.should == { a: 3 }
+ end
- it "makes both hashes to share values" do
- value = [1, 2, 3]
- new_hash = { a: value }.transform_keys(&:upcase)
- new_hash[:A].should equal(value)
- end
+ it "makes both hashes to share values" do
+ value = [1, 2, 3]
+ new_hash = { a: value }.transform_keys(&:upcase)
+ new_hash[:A].should equal(value)
+ end
- context "when no block is given" do
- it "returns a sized Enumerator" do
- enumerator = @hash.transform_keys
- enumerator.should be_an_instance_of(Enumerator)
- enumerator.size.should == @hash.size
- enumerator.each(&:succ).should == { b: 1, c: 2, d: 3 }
- end
+ context "when no block is given" do
+ it "returns a sized Enumerator" do
+ enumerator = @hash.transform_keys
+ enumerator.should be_an_instance_of(Enumerator)
+ enumerator.size.should == @hash.size
+ enumerator.each(&:succ).should == { b: 1, c: 2, d: 3 }
end
+ end
- it "returns a Hash instance, even on subclasses" do
- klass = Class.new(Hash)
- h = klass.new
- h[:foo] = 42
- r = h.transform_keys{|v| :"x#{v}"}
- r.keys.should == [:xfoo]
- r.class.should == Hash
- end
+ it "returns a Hash instance, even on subclasses" do
+ klass = Class.new(Hash)
+ h = klass.new
+ h[:foo] = 42
+ r = h.transform_keys{|v| :"x#{v}"}
+ r.keys.should == [:xfoo]
+ r.class.should == Hash
end
+end
- describe "Hash#transform_keys!" do
- before :each do
- @hash = { a: 1, b: 2, c: 3, d: 4 }
- @initial_pairs = @hash.dup
- end
+describe "Hash#transform_keys!" do
+ before :each do
+ @hash = { a: 1, b: 2, c: 3, d: 4 }
+ @initial_pairs = @hash.dup
+ end
- it "returns self" do
- @hash.transform_keys!(&:succ).should equal(@hash)
- end
+ it "returns self" do
+ @hash.transform_keys!(&:succ).should equal(@hash)
+ end
- it "updates self as transformed values with the given block" do
- @hash.transform_keys!(&:to_s)
- @hash.should == { 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4 }
+ it "updates self as transformed values with the given block" do
+ @hash.transform_keys!(&:to_s)
+ @hash.should == { 'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4 }
+ end
+
+ # https://bugs.ruby-lang.org/issues/14380
+ ruby_version_is ""..."2.5.1" do
+ it "does not prevent conflicts between new keys and old ones" do
+ @hash.transform_keys!(&:succ)
+ @hash.should == { e: 1 }
end
+ end
- # https://bugs.ruby-lang.org/issues/14380
- ruby_version_is ""..."2.5.1" do
- it "does not prevent conflicts between new keys and old ones" do
- @hash.transform_keys!(&:succ)
- @hash.should == { e: 1 }
- end
+ ruby_version_is "2.5.1" do
+ it "prevents conflicts between new keys and old ones" do
+ @hash.transform_keys!(&:succ)
+ @hash.should == { b: 1, c: 2, d: 3, e: 4 }
end
+ end
- ruby_version_is "2.5.1" do
- it "prevents conflicts between new keys and old ones" do
- @hash.transform_keys!(&:succ)
- @hash.should == { b: 1, c: 2, d: 3, e: 4 }
+ ruby_version_is ""..."2.5.1" do
+ it "partially modifies the contents if we broke from the block" do
+ @hash.transform_keys! do |v|
+ break if v == :c
+ v.succ
end
+ @hash.should == { c: 1, d: 4 }
end
+ end
- ruby_version_is ""..."2.5.1" do
- it "partially modifies the contents if we broke from the block" do
- @hash.transform_keys! do |v|
- break if v == :c
- v.succ
- end
- @hash.should == { c: 1, d: 4 }
+ ruby_version_is "2.5.1"..."3.0.2" do
+ it "returns the processed keys if we broke from the block" do
+ @hash.transform_keys! do |v|
+ break if v == :c
+ v.succ
end
+ @hash.should == { b: 1, c: 2 }
end
+ end
- ruby_version_is "2.5.1" do
- it "returns the processed keys if we broke from the block" do
- @hash.transform_keys! do |v|
- break if v == :c
- v.succ
- end
- @hash.should == { b: 1, c: 2 }
+ ruby_version_is "3.0.2" do
+ it "returns the processed keys and non evaluated keys if we broke from the block" do
+ @hash.transform_keys! do |v|
+ break if v == :c
+ v.succ
end
+ @hash.should == { b: 1, c: 2, d: 4 }
end
+ end
- it "keeps later pair if new keys conflict" do
- @hash.transform_keys! { |_| :a }.should == { a: 4 }
- end
+ it "keeps later pair if new keys conflict" do
+ @hash.transform_keys! { |_| :a }.should == { a: 4 }
+ end
- context "when no block is given" do
- it "returns a sized Enumerator" do
- enumerator = @hash.transform_keys!
- enumerator.should be_an_instance_of(Enumerator)
- enumerator.size.should == @hash.size
- enumerator.each(&:upcase).should == { A: 1, B: 2, C: 3, D: 4 }
- end
+ context "when no block is given" do
+ it "returns a sized Enumerator" do
+ enumerator = @hash.transform_keys!
+ enumerator.should be_an_instance_of(Enumerator)
+ enumerator.size.should == @hash.size
+ enumerator.each(&:upcase).should == { A: 1, B: 2, C: 3, D: 4 }
end
+ end
- describe "on frozen instance" do
- before :each do
- @hash.freeze
- end
+ describe "on frozen instance" do
+ before :each do
+ @hash.freeze
+ end
- it "raises a #{frozen_error_class} on an empty hash" do
- ->{ {}.freeze.transform_keys!(&:upcase) }.should raise_error(frozen_error_class)
- end
+ it "raises a FrozenError on an empty hash" do
+ ->{ {}.freeze.transform_keys!(&:upcase) }.should raise_error(FrozenError)
+ end
- it "keeps pairs and raises a #{frozen_error_class}" do
- ->{ @hash.transform_keys!(&:upcase) }.should raise_error(frozen_error_class)
- @hash.should == @initial_pairs
- end
+ it "keeps pairs and raises a FrozenError" do
+ ->{ @hash.transform_keys!(&:upcase) }.should raise_error(FrozenError)
+ @hash.should == @initial_pairs
+ end
- context "when no block is given" do
- it "does not raise an exception" do
- @hash.transform_keys!.should be_an_instance_of(Enumerator)
- end
+ context "when no block is given" do
+ it "does not raise an exception" do
+ @hash.transform_keys!.should be_an_instance_of(Enumerator)
end
end
end
diff --git a/spec/ruby/core/hash/transform_values_spec.rb b/spec/ruby/core/hash/transform_values_spec.rb
index 8b53b7a522..acb469416a 100644
--- a/spec/ruby/core/hash/transform_values_spec.rb
+++ b/spec/ruby/core/hash/transform_values_spec.rb
@@ -79,12 +79,12 @@ describe "Hash#transform_values!" do
@hash.freeze
end
- it "raises a #{frozen_error_class} on an empty hash" do
- ->{ {}.freeze.transform_values!(&:succ) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on an empty hash" do
+ ->{ {}.freeze.transform_values!(&:succ) }.should raise_error(FrozenError)
end
- it "keeps pairs and raises a #{frozen_error_class}" do
- ->{ @hash.transform_values!(&:succ) }.should raise_error(frozen_error_class)
+ it "keeps pairs and raises a FrozenError" do
+ ->{ @hash.transform_values!(&:succ) }.should raise_error(FrozenError)
@hash.should == @initial_pairs
end
diff --git a/spec/ruby/core/integer/allbits_spec.rb b/spec/ruby/core/integer/allbits_spec.rb
index f4a6fe9905..11acb52e1f 100644
--- a/spec/ruby/core/integer/allbits_spec.rb
+++ b/spec/ruby/core/integer/allbits_spec.rb
@@ -1,39 +1,37 @@
require_relative '../../spec_helper'
-ruby_version_is '2.5' do
- describe "Integer#allbits?" do
- it "returns true iff all the bits of the argument are set in the receiver" do
- 42.allbits?(42).should == true
- 0b1010_1010.allbits?(0b1000_0010).should == true
- 0b1010_1010.allbits?(0b1000_0001).should == false
- 0b1000_0010.allbits?(0b1010_1010).should == false
- (0b1010_1010 | bignum_value).allbits?(0b1000_0010 | bignum_value).should == true
- (0b1010_1010 | bignum_value).allbits?(0b1000_0001 | bignum_value).should == false
- (0b1000_0010 | bignum_value).allbits?(0b1010_1010 | bignum_value).should == false
- end
+describe "Integer#allbits?" do
+ it "returns true iff all the bits of the argument are set in the receiver" do
+ 42.allbits?(42).should == true
+ 0b1010_1010.allbits?(0b1000_0010).should == true
+ 0b1010_1010.allbits?(0b1000_0001).should == false
+ 0b1000_0010.allbits?(0b1010_1010).should == false
+ (0b1010_1010 | bignum_value).allbits?(0b1000_0010 | bignum_value).should == true
+ (0b1010_1010 | bignum_value).allbits?(0b1000_0001 | bignum_value).should == false
+ (0b1000_0010 | bignum_value).allbits?(0b1010_1010 | bignum_value).should == false
+ end
- it "handles negative values using two's complement notation" do
- (~0b1).allbits?(42).should == true
- (-42).allbits?(-42).should == true
- (~0b1010_1010).allbits?(~0b1110_1011).should == true
- (~0b1010_1010).allbits?(~0b1000_0010).should == false
- (~(0b1010_1010 | bignum_value)).allbits?(~(0b1110_1011 | bignum_value)).should == true
- (~(0b1010_1010 | bignum_value)).allbits?(~(0b1000_0010 | bignum_value)).should == false
- end
+ it "handles negative values using two's complement notation" do
+ (~0b1).allbits?(42).should == true
+ (-42).allbits?(-42).should == true
+ (~0b1010_1010).allbits?(~0b1110_1011).should == true
+ (~0b1010_1010).allbits?(~0b1000_0010).should == false
+ (~(0b1010_1010 | bignum_value)).allbits?(~(0b1110_1011 | bignum_value)).should == true
+ (~(0b1010_1010 | bignum_value)).allbits?(~(0b1000_0010 | bignum_value)).should == false
+ end
- it "coerces the rhs using to_int" do
- obj = mock("the int 0b10")
- obj.should_receive(:to_int).and_return(0b10)
- 0b110.allbits?(obj).should == true
- end
+ it "coerces the rhs using to_int" do
+ obj = mock("the int 0b10")
+ obj.should_receive(:to_int).and_return(0b10)
+ 0b110.allbits?(obj).should == true
+ end
- it "raises a TypeError when given a non-Integer" do
- -> {
- (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10])
- 13.allbits?(obj)
- }.should raise_error(TypeError)
- -> { 13.allbits?("10") }.should raise_error(TypeError)
- -> { 13.allbits?(:symbol) }.should raise_error(TypeError)
- end
+ it "raises a TypeError when given a non-Integer" do
+ -> {
+ (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10])
+ 13.allbits?(obj)
+ }.should raise_error(TypeError)
+ -> { 13.allbits?("10") }.should raise_error(TypeError)
+ -> { 13.allbits?(:symbol) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/integer/anybits_spec.rb b/spec/ruby/core/integer/anybits_spec.rb
index 91f349258a..7e510fd00b 100644
--- a/spec/ruby/core/integer/anybits_spec.rb
+++ b/spec/ruby/core/integer/anybits_spec.rb
@@ -1,38 +1,36 @@
require_relative '../../spec_helper'
-ruby_version_is '2.5' do
- describe "Integer#anybits?" do
- it "returns true iff all the bits of the argument are set in the receiver" do
- 42.anybits?(42).should == true
- 0b1010_1010.anybits?(0b1000_0010).should == true
- 0b1010_1010.anybits?(0b1000_0001).should == true
- 0b1000_0010.anybits?(0b0010_1100).should == false
- different_bignum = (2 * bignum_value) & (~bignum_value)
- (0b1010_1010 | different_bignum).anybits?(0b1000_0010 | bignum_value).should == true
- (0b1010_1010 | different_bignum).anybits?(0b0010_1100 | bignum_value).should == true
- (0b1000_0010 | different_bignum).anybits?(0b0010_1100 | bignum_value).should == false
- end
+describe "Integer#anybits?" do
+ it "returns true iff all the bits of the argument are set in the receiver" do
+ 42.anybits?(42).should == true
+ 0b1010_1010.anybits?(0b1000_0010).should == true
+ 0b1010_1010.anybits?(0b1000_0001).should == true
+ 0b1000_0010.anybits?(0b0010_1100).should == false
+ different_bignum = (2 * bignum_value) & (~bignum_value)
+ (0b1010_1010 | different_bignum).anybits?(0b1000_0010 | bignum_value).should == true
+ (0b1010_1010 | different_bignum).anybits?(0b0010_1100 | bignum_value).should == true
+ (0b1000_0010 | different_bignum).anybits?(0b0010_1100 | bignum_value).should == false
+ end
- it "handles negative values using two's complement notation" do
- (~42).anybits?(42).should == false
- (-42).anybits?(-42).should == true
- (~0b100).anybits?(~0b1).should == true
- (~(0b100 | bignum_value)).anybits?(~(0b1 | bignum_value)).should == true
- end
+ it "handles negative values using two's complement notation" do
+ (~42).anybits?(42).should == false
+ (-42).anybits?(-42).should == true
+ (~0b100).anybits?(~0b1).should == true
+ (~(0b100 | bignum_value)).anybits?(~(0b1 | bignum_value)).should == true
+ end
- it "coerces the rhs using to_int" do
- obj = mock("the int 0b10")
- obj.should_receive(:to_int).and_return(0b10)
- 0b110.anybits?(obj).should == true
- end
+ it "coerces the rhs using to_int" do
+ obj = mock("the int 0b10")
+ obj.should_receive(:to_int).and_return(0b10)
+ 0b110.anybits?(obj).should == true
+ end
- it "raises a TypeError when given a non-Integer" do
- -> {
- (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10])
- 13.anybits?(obj)
- }.should raise_error(TypeError)
- -> { 13.anybits?("10") }.should raise_error(TypeError)
- -> { 13.anybits?(:symbol) }.should raise_error(TypeError)
- end
+ it "raises a TypeError when given a non-Integer" do
+ -> {
+ (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10])
+ 13.anybits?(obj)
+ }.should raise_error(TypeError)
+ -> { 13.anybits?("10") }.should raise_error(TypeError)
+ -> { 13.anybits?(:symbol) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/integer/chr_spec.rb b/spec/ruby/core/integer/chr_spec.rb
index a8755eeb84..9f105e4241 100644
--- a/spec/ruby/core/integer/chr_spec.rb
+++ b/spec/ruby/core/integer/chr_spec.rb
@@ -240,4 +240,17 @@ describe "Integer#chr with an encoding argument" do
-> { integer.chr(encoding_name) }.should raise_error(RangeError)
end
end
+
+ ruby_version_is "2.7" do
+ it 'returns a String encoding self interpreted as a codepoint in the CESU-8 encoding' do
+ # see more details here https://en.wikipedia.org/wiki/CESU-8
+ # code points from U+0000 to U+FFFF is encoded in the same way as in UTF-8
+ 0x0045.chr(Encoding::CESU_8).bytes.should == 0x0045.chr(Encoding::UTF_8).bytes
+
+ # code points in range from U+10000 to U+10FFFF is CESU-8 data containing a 6-byte surrogate pair,
+ # which decodes to a 4-byte UTF-8 string
+ 0x10400.chr(Encoding::CESU_8).bytes.should != 0x10400.chr(Encoding::UTF_8).bytes
+ 0x10400.chr(Encoding::CESU_8).bytes.to_a.should == [0xED, 0xA0, 0x81, 0xED, 0xB0, 0x80]
+ end
+ end
end
diff --git a/spec/ruby/core/integer/coerce_spec.rb b/spec/ruby/core/integer/coerce_spec.rb
index 9a19baf2ea..4d540bfb87 100644
--- a/spec/ruby/core/integer/coerce_spec.rb
+++ b/spec/ruby/core/integer/coerce_spec.rb
@@ -4,10 +4,10 @@ require 'bigdecimal'
describe "Integer#coerce" do
context "fixnum" do
- describe "when given a Fixnum" do
- it "returns an array containing two Fixnums" do
+ describe "when given an Integer" do
+ it "returns an array containing two Integers" do
1.coerce(2).should == [2, 1]
- 1.coerce(2).map { |i| i.class }.should == [Fixnum, Fixnum]
+ 1.coerce(2).map { |i| i.class }.should == [Integer, Integer]
end
end
@@ -42,26 +42,26 @@ describe "Integer#coerce" do
end
context "bignum" do
- it "coerces other to a Bignum and returns [other, self] when passed a Fixnum" do
+ it "coerces other to an Integer and returns [other, self] when passed an Integer" do
a = bignum_value
ary = a.coerce(2)
- ary[0].should be_kind_of(Bignum)
- ary[1].should be_kind_of(Bignum)
+ ary[0].should be_kind_of(Integer)
+ ary[1].should be_kind_of(Integer)
ary.should == [2, a]
end
- it "returns [other, self] when passed a Bignum" do
+ it "returns [other, self] when passed an Integer" do
a = bignum_value
b = bignum_value
ary = a.coerce(b)
- ary[0].should be_kind_of(Bignum)
- ary[1].should be_kind_of(Bignum)
+ ary[0].should be_kind_of(Integer)
+ ary[1].should be_kind_of(Integer)
ary.should == [b, a]
end
- it "raises a TypeError when not passed a Fixnum or Bignum" do
+ it "raises a TypeError when not passed an Integer" do
a = bignum_value
-> { a.coerce(nil) }.should raise_error(TypeError)
diff --git a/spec/ruby/core/integer/comparison_spec.rb b/spec/ruby/core/integer/comparison_spec.rb
index 2ff557c7c6..a0d8d24119 100644
--- a/spec/ruby/core/integer/comparison_spec.rb
+++ b/spec/ruby/core/integer/comparison_spec.rb
@@ -27,7 +27,7 @@ describe "Integer#<=>" do
end
context "bignum" do
- describe "with a Fixnum" do
+ describe "with an Integer" do
it "returns -1 when other is larger" do
(-bignum_value <=> 2).should == -1
end
@@ -37,7 +37,7 @@ describe "Integer#<=>" do
end
end
- describe "with a Bignum" do
+ describe "with an Integer" do
describe "when other is negative" do
it "returns -1 when self is negative and other is larger" do
(-bignum_value(42) <=> -bignum_value).should == -1
@@ -116,7 +116,7 @@ describe "Integer#<=>" do
describe "with an Object" do
before :each do
@big = bignum_value
- @num = mock("value for Bignum#<=>")
+ @num = mock("value for Integer#<=>")
end
it "calls #coerce on other" do
@@ -124,23 +124,11 @@ describe "Integer#<=>" do
@big <=> @num
end
- ruby_version_is ""..."2.5" do
- it "returns nil if #coerce raises an exception" do
- @num.should_receive(:coerce).with(@big).and_raise(RuntimeError)
- -> {
- @result = (@big <=> @num)
- }.should complain(/Numerical comparison operators will no more rescue exceptions/)
- @result.should be_nil
- end
- end
-
- ruby_version_is "2.5" do
- it "lets the exception go through if #coerce raises an exception" do
- @num.should_receive(:coerce).with(@big).and_raise(RuntimeError.new("my error"))
- -> {
- @big <=> @num
- }.should raise_error(RuntimeError, "my error")
- end
+ it "lets the exception go through if #coerce raises an exception" do
+ @num.should_receive(:coerce).with(@big).and_raise(RuntimeError.new("my error"))
+ -> {
+ @big <=> @num
+ }.should raise_error(RuntimeError, "my error")
end
it "raises an exception if #coerce raises a non-StandardError exception" do
@@ -170,7 +158,7 @@ describe "Integer#<=>" do
end
# The tests below are taken from matz's revision 23730 for Ruby trunk
- it "returns 1 when self is Infinity and other is a Bignum" do
+ it "returns 1 when self is Infinity and other is an Integer" do
(infinity_value <=> Float::MAX.to_i*2).should == 1
end
diff --git a/spec/ruby/core/integer/constants_spec.rb b/spec/ruby/core/integer/constants_spec.rb
index cdb7537392..35601f82b9 100644
--- a/spec/ruby/core/integer/constants_spec.rb
+++ b/spec/ruby/core/integer/constants_spec.rb
@@ -1,6 +1,6 @@
require_relative '../../spec_helper'
-ruby_version_is ""..."2.7" do
+ruby_version_is ""..."3.0" do
describe "Fixnum" do
it "is unified into Integer" do
suppress_warning do
diff --git a/spec/ruby/core/integer/denominator_spec.rb b/spec/ruby/core/integer/denominator_spec.rb
index c1477d0757..d19b8175a3 100644
--- a/spec/ruby/core/integer/denominator_spec.rb
+++ b/spec/ruby/core/integer/denominator_spec.rb
@@ -7,7 +7,7 @@ describe "Integer#denominator" do
@numbers = [
20, # Integer
-2709, # Negative Integer
- 99999999**99, # Bignum
+ 99999999**99, # Integer
-99999**621, # Negative BigNum
0,
1
diff --git a/spec/ruby/core/integer/div_spec.rb b/spec/ruby/core/integer/div_spec.rb
index 087d012fe0..bc1c4363d4 100644
--- a/spec/ruby/core/integer/div_spec.rb
+++ b/spec/ruby/core/integer/div_spec.rb
@@ -36,7 +36,7 @@ describe "Integer#div" do
10.div(y).should == result
end
- it "coerces self and the given argument to Floats and returns self divided by other as Fixnum" do
+ it "coerces self and the given argument to Floats and returns self divided by other as Integer" do
1.div(0.2).should == 5
1.div(0.16).should == 6
1.div(0.169).should == 5
diff --git a/spec/ruby/core/integer/divide_spec.rb b/spec/ruby/core/integer/divide_spec.rb
index a32d68c229..5ac2dc538d 100644
--- a/spec/ruby/core/integer/divide_spec.rb
+++ b/spec/ruby/core/integer/divide_spec.rb
@@ -2,13 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/arithmetic_coerce'
describe "Integer#/" do
- ruby_version_is "2.4"..."2.5" do
- it_behaves_like :integer_arithmetic_coerce_rescue, :/
- end
-
- ruby_version_is "2.5" do
- it_behaves_like :integer_arithmetic_coerce_not_rescue, :/
- end
+ it_behaves_like :integer_arithmetic_coerce_not_rescue, :/
context "fixnum" do
it "returns self divided by the given argument" do
diff --git a/spec/ruby/core/integer/downto_spec.rb b/spec/ruby/core/integer/downto_spec.rb
index af7a7e36b9..987704b02e 100644
--- a/spec/ruby/core/integer/downto_spec.rb
+++ b/spec/ruby/core/integer/downto_spec.rb
@@ -1,6 +1,6 @@
require_relative '../../spec_helper'
-describe "Integer#downto [stop] when self and stop are Fixnums" do
+describe "Integer#downto [stop] when self and stop are Integers" do
it "does not yield when stop is greater than self" do
result = []
5.downto(6) { |x| result << x }
diff --git a/spec/ruby/core/integer/element_reference_spec.rb b/spec/ruby/core/integer/element_reference_spec.rb
index 99283fac34..6e65c50254 100644
--- a/spec/ruby/core/integer/element_reference_spec.rb
+++ b/spec/ruby/core/integer/element_reference_spec.rb
@@ -68,16 +68,101 @@ describe "Integer#[]" do
-> { 3[obj] }.should raise_error(TypeError)
end
- it "calls #to_int to coerce a String to a Bignum and returns 0" do
+ it "calls #to_int to coerce a String to an Integer and returns 0" do
obj = mock('bignum value')
obj.should_receive(:to_int).and_return(bignum_value)
3[obj].should == 0
end
- it "returns 0 when passed a Float in the range of a Bignum" do
+ it "returns 0 when passed a Float in the range of an Integer" do
3[bignum_value.to_f].should == 0
end
+
+ ruby_version_is "2.7" do
+ context "when index and length passed" do
+ it "returns specified number of bits from specified position" do
+ 0b101001101[2, 4].should == 0b0011
+ 0b101001101[2, 5].should == 0b10011
+ 0b101001101[2, 7].should == 0b1010011
+ end
+
+ it "ensures n[i, len] equals to (n >> i) & ((1 << len) - 1)" do
+ n = 0b101001101; i = 2; len = 4
+ n[i, len].should == (n >> i) & ((1 << len) - 1)
+ end
+
+ it "moves start position to the most significant bits when negative index passed" do
+ 0b000001[-1, 4].should == 0b10
+ 0b000001[-2, 4].should == 0b100
+ 0b000001[-3, 4].should == 0b1000
+ end
+
+ it "ignores negative length" do
+ 0b101001101[1, -1].should == 0b10100110
+ 0b101001101[2, -1].should == 0b1010011
+ 0b101001101[3, -1].should == 0b101001
+
+ 0b101001101[3, -5].should == 0b101001
+ 0b101001101[3, -15].should == 0b101001
+ 0b101001101[3, -125].should == 0b101001
+ end
+ end
+
+ context "when range passed" do
+ it "returns bits specified by range" do
+ 0b101001101[2..5].should == 0b0011
+ 0b101001101[2..6].should == 0b10011
+ 0b101001101[2..8].should == 0b1010011
+ end
+
+ it "ensures n[i..j] equals to (n >> i) & ((1 << (j - i + 1)) - 1)" do
+ n = 0b101001101; i = 2; j = 5
+ n[i..j].should == (n >> i) & ((1 << (j - i + 1)) - 1)
+ end
+
+ it "ensures n[i..] equals to (n >> i)" do
+ eval("0b101001101[3..]").should == 0b101001101 >> 3
+ end
+
+ it "moves lower boundary to the most significant bits when negative value passed" do
+ 0b000001[-1, 4].should == 0b10
+ 0b000001[-2, 4].should == 0b100
+ 0b000001[-3, 4].should == 0b1000
+ end
+
+ it "ignores negative upper boundary" do
+ 0b101001101[1..-1].should == 0b10100110
+ 0b101001101[1..-2].should == 0b10100110
+ 0b101001101[1..-3].should == 0b10100110
+ end
+
+ it "ignores upper boundary smaller than lower boundary" do
+ 0b101001101[4..1].should == 0b10100
+ 0b101001101[4..2].should == 0b10100
+ 0b101001101[4..3].should == 0b10100
+ end
+
+ it "raises FloatDomainError if any boundary is infinity" do
+ -> { 0x0001[3..Float::INFINITY] }.should raise_error(FloatDomainError, /Infinity/)
+ -> { 0x0001[-Float::INFINITY..3] }.should raise_error(FloatDomainError, /-Infinity/)
+ end
+
+ context "when passed (..i)" do
+ it "returns 0 if all i bits equal 0" do
+ eval("0b10000[..1]").should == 0
+ eval("0b10000[..2]").should == 0
+ eval("0b10000[..3]").should == 0
+ end
+
+ it "raises ArgumentError if any of i bit equals 1" do
+ -> {
+ eval("0b111110[..3]")
+ }.should raise_error(ArgumentError, /The beginless range for Integer#\[\] results in infinity/)
+ end
+ end
+ end
+ end
end
context "bignum" do
diff --git a/spec/ruby/core/integer/even_spec.rb b/spec/ruby/core/integer/even_spec.rb
index a314cc6b19..a93f54c74e 100644
--- a/spec/ruby/core/integer/even_spec.rb
+++ b/spec/ruby/core/integer/even_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Integer#even?" do
context "fixnum" do
- it "returns true for a Fixnum when it is an even number" do
+ it "returns true for an Integer when it is an even number" do
(-2).even?.should be_true
(-1).even?.should be_false
@@ -11,7 +11,7 @@ describe "Integer#even?" do
2.even?.should be_true
end
- it "returns true for a Bignum when it is an even number" do
+ it "returns true for an Integer when it is an even number" do
bignum_value(0).even?.should be_true
bignum_value(1).even?.should be_false
diff --git a/spec/ruby/core/integer/gcd_spec.rb b/spec/ruby/core/integer/gcd_spec.rb
index 8aa654a16a..82086d742a 100644
--- a/spec/ruby/core/integer/gcd_spec.rb
+++ b/spec/ruby/core/integer/gcd_spec.rb
@@ -31,15 +31,15 @@ describe "Integer#gcd" do
-100.gcd(-100).should == 100
end
- it "accepts a Bignum argument" do
+ it "accepts an Integer argument" do
bignum = 9999**99
- bignum.should be_kind_of(Bignum)
+ bignum.should be_kind_of(Integer)
99.gcd(bignum).should == 99
end
- it "works if self is a Bignum" do
+ it "works if self is an Integer" do
bignum = 9999**99
- bignum.should be_kind_of(Bignum)
+ bignum.should be_kind_of(Integer)
bignum.gcd(99).should == 99
end
diff --git a/spec/ruby/core/integer/gcdlcm_spec.rb b/spec/ruby/core/integer/gcdlcm_spec.rb
index 5b3669e62a..2915750f88 100644
--- a/spec/ruby/core/integer/gcdlcm_spec.rb
+++ b/spec/ruby/core/integer/gcdlcm_spec.rb
@@ -26,15 +26,15 @@ describe "Integer#gcdlcm" do
200.gcdlcm(20)[1].should == 200.lcm(20)
end
- it "accepts a Bignum argument" do
+ it "accepts an Integer argument" do
bignum = 91999**99
- bignum.should be_kind_of(Bignum)
+ bignum.should be_kind_of(Integer)
99.gcdlcm(bignum).should == [99.gcd(bignum), 99.lcm(bignum)]
end
- it "works if self is a Bignum" do
+ it "works if self is an Integer" do
bignum = 9999**89
- bignum.should be_kind_of(Bignum)
+ bignum.should be_kind_of(Integer)
bignum.gcdlcm(99).should == [bignum.gcd(99), bignum.lcm(99)]
end
diff --git a/spec/ruby/core/integer/gt_spec.rb b/spec/ruby/core/integer/gt_spec.rb
index 428a6f6888..f0179e566d 100644
--- a/spec/ruby/core/integer/gt_spec.rb
+++ b/spec/ruby/core/integer/gt_spec.rb
@@ -2,13 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/comparison_coerce'
describe "Integer#>" do
- ruby_version_is "2.4"..."2.5" do
- it_behaves_like :integer_comparison_coerce_rescue, :>
- end
-
- ruby_version_is "2.5" do
- it_behaves_like :integer_comparison_coerce_not_rescue, :>
- end
+ it_behaves_like :integer_comparison_coerce_not_rescue, :>
context "fixnum" do
it "returns true if self is greater than the given argument" do
diff --git a/spec/ruby/core/integer/gte_spec.rb b/spec/ruby/core/integer/gte_spec.rb
index ce1385c360..6237fc2c51 100644
--- a/spec/ruby/core/integer/gte_spec.rb
+++ b/spec/ruby/core/integer/gte_spec.rb
@@ -2,13 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/comparison_coerce'
describe "Integer#>=" do
- ruby_version_is "2.4"..."2.5" do
- it_behaves_like :integer_comparison_coerce_rescue, :>=
- end
-
- ruby_version_is "2.5" do
- it_behaves_like :integer_comparison_coerce_not_rescue, :>=
- end
+ it_behaves_like :integer_comparison_coerce_not_rescue, :>=
context "fixnum" do
it "returns true if self is greater than or equal to the given argument" do
diff --git a/spec/ruby/core/integer/integer_spec.rb b/spec/ruby/core/integer/integer_spec.rb
index f8067cda06..2d5d2e3e92 100644
--- a/spec/ruby/core/integer/integer_spec.rb
+++ b/spec/ruby/core/integer/integer_spec.rb
@@ -13,8 +13,8 @@ end
describe "Integer#integer?" do
it "returns true for Integers" do
- 0.integer?.should == true
- -1.integer?.should == true
- bignum_value.integer?.should == true
+ 0.should.integer?
+ -1.should.integer?
+ bignum_value.should.integer?
end
end
diff --git a/spec/ruby/core/integer/lcm_spec.rb b/spec/ruby/core/integer/lcm_spec.rb
index 77d3ad3488..39976ea474 100644
--- a/spec/ruby/core/integer/lcm_spec.rb
+++ b/spec/ruby/core/integer/lcm_spec.rb
@@ -31,15 +31,15 @@ describe "Integer#lcm" do
-100.lcm(-100).should == 100
end
- it "accepts a Bignum argument" do
+ it "accepts an Integer argument" do
bignum = 9999**99
- bignum.should be_kind_of(Bignum)
+ bignum.should be_kind_of(Integer)
99.lcm(bignum).should == bignum
end
- it "works if self is a Bignum" do
+ it "works if self is an Integer" do
bignum = 9999**99
- bignum.should be_kind_of(Bignum)
+ bignum.should be_kind_of(Integer)
bignum.lcm(99).should == bignum
end
diff --git a/spec/ruby/core/integer/left_shift_spec.rb b/spec/ruby/core/integer/left_shift_spec.rb
index 4b5ef9386e..d2ffe4bbeb 100644
--- a/spec/ruby/core/integer/left_shift_spec.rb
+++ b/spec/ruby/core/integer/left_shift_spec.rb
@@ -52,27 +52,30 @@ describe "Integer#<< (with n << m)" do
(-7 << -64).should == -1
end
- it "returns 0 when m < 0 and m is a Bignum" do
+ it "returns 0 when m < 0 and m is an Integer" do
(3 << -bignum_value).should == 0
end
- it "returns an Bignum == fixnum_max * 2 when fixnum_max << 1 and n > 0" do
+ it "returns an Integer == fixnum_max * 2 when fixnum_max << 1 and n > 0" do
result = fixnum_max << 1
- result.should be_an_instance_of(Bignum)
+ result.should be_an_instance_of(Integer)
result.should == fixnum_max * 2
end
- it "returns an Bignum == fixnum_min * 2 when fixnum_min << 1 and n < 0" do
+ it "returns an Integer == fixnum_min * 2 when fixnum_min << 1 and n < 0" do
result = fixnum_min << 1
- result.should be_an_instance_of(Bignum)
+ result.should be_an_instance_of(Integer)
result.should == fixnum_min * 2
end
it "calls #to_int to convert the argument to an Integer" do
obj = mock("4")
obj.should_receive(:to_int).and_return(4)
-
(3 << obj).should == 48
+
+ obj = mock("to_int_neg_bignum")
+ obj.should_receive(:to_int).and_return(-bignum_value)
+ (3 << obj).should == 0
end
it "raises a TypeError when #to_int does not return an Integer" do
@@ -124,19 +127,19 @@ describe "Integer#<< (with n << m)" do
(@bignum << -68).should == 0
end
- it "returns 0 when m < 0 and m is a Bignum" do
+ it "returns 0 when m < 0 and m is an Integer" do
(@bignum << -bignum_value).should == 0
end
- it "returns a Fixnum == fixnum_max when (fixnum_max * 2) << -1 and n > 0" do
+ it "returns an Integer == fixnum_max when (fixnum_max * 2) << -1 and n > 0" do
result = (fixnum_max * 2) << -1
- result.should be_an_instance_of(Fixnum)
+ result.should be_an_instance_of(Integer)
result.should == fixnum_max
end
- it "returns a Fixnum == fixnum_min when (fixnum_min * 2) << -1 and n < 0" do
+ it "returns an Integer == fixnum_min when (fixnum_min * 2) << -1 and n < 0" do
result = (fixnum_min * 2) << -1
- result.should be_an_instance_of(Fixnum)
+ result.should be_an_instance_of(Integer)
result.should == fixnum_min
end
diff --git a/spec/ruby/core/integer/lt_spec.rb b/spec/ruby/core/integer/lt_spec.rb
index dfe2d9e369..c182f82555 100644
--- a/spec/ruby/core/integer/lt_spec.rb
+++ b/spec/ruby/core/integer/lt_spec.rb
@@ -2,13 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/comparison_coerce'
describe "Integer#<" do
- ruby_version_is "2.4"..."2.5" do
- it_behaves_like :integer_comparison_coerce_rescue, :<
- end
-
- ruby_version_is "2.5" do
- it_behaves_like :integer_comparison_coerce_not_rescue, :<
- end
+ it_behaves_like :integer_comparison_coerce_not_rescue, :<
context "fixnum" do
it "returns true if self is less than the given argument" do
diff --git a/spec/ruby/core/integer/lte_spec.rb b/spec/ruby/core/integer/lte_spec.rb
index 3d843a5dd9..65b71d77f2 100644
--- a/spec/ruby/core/integer/lte_spec.rb
+++ b/spec/ruby/core/integer/lte_spec.rb
@@ -2,13 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/comparison_coerce'
describe "Integer#<=" do
- ruby_version_is "2.4"..."2.5" do
- it_behaves_like :integer_comparison_coerce_rescue, :<=
- end
-
- ruby_version_is "2.5" do
- it_behaves_like :integer_comparison_coerce_not_rescue, :<=
- end
+ it_behaves_like :integer_comparison_coerce_not_rescue, :<=
context "fixnum" do
it "returns true if self is less than or equal to other" do
@@ -46,6 +40,11 @@ describe "Integer#<=" do
(@bignum <= (@bignum + 0.5)).should == false
end
+ it "returns true for bignums compare to a bigger float" do
+ (18446744073709551616 <= 1.8446744073709552e+19).should == true
+ (@bignum <= (@bignum + 9999.0)).should == true
+ end
+
it "raises an ArgumentError when given a non-Integer" do
-> { @bignum <= "4" }.should raise_error(ArgumentError)
-> { @bignum <= mock('str') }.should raise_error(ArgumentError)
diff --git a/spec/ruby/core/integer/minus_spec.rb b/spec/ruby/core/integer/minus_spec.rb
index 34dd36c1a7..ce50c8752f 100644
--- a/spec/ruby/core/integer/minus_spec.rb
+++ b/spec/ruby/core/integer/minus_spec.rb
@@ -2,13 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/arithmetic_coerce'
describe "Integer#-" do
- ruby_version_is "2.4"..."2.5" do
- it_behaves_like :integer_arithmetic_coerce_rescue, :-
- end
-
- ruby_version_is "2.5" do
- it_behaves_like :integer_arithmetic_coerce_not_rescue, :-
- end
+ it_behaves_like :integer_arithmetic_coerce_not_rescue, :-
context "fixnum" do
it "returns self minus the given Integer" do
diff --git a/spec/ruby/core/integer/multiply_spec.rb b/spec/ruby/core/integer/multiply_spec.rb
index 919786cbcc..d1e9c2640d 100644
--- a/spec/ruby/core/integer/multiply_spec.rb
+++ b/spec/ruby/core/integer/multiply_spec.rb
@@ -2,13 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/arithmetic_coerce'
describe "Integer#*" do
- ruby_version_is "2.4"..."2.5" do
- it_behaves_like :integer_arithmetic_coerce_rescue, :*
- end
-
- ruby_version_is "2.5" do
- it_behaves_like :integer_arithmetic_coerce_not_rescue, :*
- end
+ it_behaves_like :integer_arithmetic_coerce_not_rescue, :*
context "fixnum" do
it "returns self multiplied by the given Integer" do
diff --git a/spec/ruby/core/integer/nobits_spec.rb b/spec/ruby/core/integer/nobits_spec.rb
index af3b9e7db0..b132a4a724 100644
--- a/spec/ruby/core/integer/nobits_spec.rb
+++ b/spec/ruby/core/integer/nobits_spec.rb
@@ -1,38 +1,36 @@
require_relative '../../spec_helper'
-ruby_version_is '2.5' do
- describe "Integer#nobits?" do
- it "returns true iff all no bits of the argument are set in the receiver" do
- 42.nobits?(42).should == false
- 0b1010_1010.nobits?(0b1000_0010).should == false
- 0b1010_1010.nobits?(0b1000_0001).should == false
- 0b0100_0101.nobits?(0b1010_1010).should == true
- different_bignum = (2 * bignum_value) & (~bignum_value)
- (0b1010_1010 | different_bignum).nobits?(0b1000_0010 | bignum_value).should == false
- (0b1010_1010 | different_bignum).nobits?(0b1000_0001 | bignum_value).should == false
- (0b0100_0101 | different_bignum).nobits?(0b1010_1010 | bignum_value).should == true
- end
+describe "Integer#nobits?" do
+ it "returns true iff all no bits of the argument are set in the receiver" do
+ 42.nobits?(42).should == false
+ 0b1010_1010.nobits?(0b1000_0010).should == false
+ 0b1010_1010.nobits?(0b1000_0001).should == false
+ 0b0100_0101.nobits?(0b1010_1010).should == true
+ different_bignum = (2 * bignum_value) & (~bignum_value)
+ (0b1010_1010 | different_bignum).nobits?(0b1000_0010 | bignum_value).should == false
+ (0b1010_1010 | different_bignum).nobits?(0b1000_0001 | bignum_value).should == false
+ (0b0100_0101 | different_bignum).nobits?(0b1010_1010 | bignum_value).should == true
+ end
- it "handles negative values using two's complement notation" do
- (~0b1101).nobits?(0b1101).should == true
- (-42).nobits?(-42).should == false
- (~0b1101).nobits?(~0b10).should == false
- (~(0b1101 | bignum_value)).nobits?(~(0b10 | bignum_value)).should == false
- end
+ it "handles negative values using two's complement notation" do
+ (~0b1101).nobits?(0b1101).should == true
+ (-42).nobits?(-42).should == false
+ (~0b1101).nobits?(~0b10).should == false
+ (~(0b1101 | bignum_value)).nobits?(~(0b10 | bignum_value)).should == false
+ end
- it "coerces the rhs using to_int" do
- obj = mock("the int 0b10")
- obj.should_receive(:to_int).and_return(0b10)
- 0b110.nobits?(obj).should == false
- end
+ it "coerces the rhs using to_int" do
+ obj = mock("the int 0b10")
+ obj.should_receive(:to_int).and_return(0b10)
+ 0b110.nobits?(obj).should == false
+ end
- it "raises a TypeError when given a non-Integer" do
- -> {
- (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10])
- 13.nobits?(obj)
- }.should raise_error(TypeError)
- -> { 13.nobits?("10") }.should raise_error(TypeError)
- -> { 13.nobits?(:symbol) }.should raise_error(TypeError)
- end
+ it "raises a TypeError when given a non-Integer" do
+ -> {
+ (obj = mock('10')).should_receive(:coerce).any_number_of_times.and_return([42,10])
+ 13.nobits?(obj)
+ }.should raise_error(TypeError)
+ -> { 13.nobits?("10") }.should raise_error(TypeError)
+ -> { 13.nobits?(:symbol) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/integer/plus_spec.rb b/spec/ruby/core/integer/plus_spec.rb
index 7e919a16db..be626c3305 100644
--- a/spec/ruby/core/integer/plus_spec.rb
+++ b/spec/ruby/core/integer/plus_spec.rb
@@ -2,13 +2,7 @@ require_relative '../../spec_helper'
require_relative 'shared/arithmetic_coerce'
describe "Integer#+" do
- ruby_version_is "2.4"..."2.5" do
- it_behaves_like :integer_arithmetic_coerce_rescue, :+
- end
-
- ruby_version_is "2.5" do
- it_behaves_like :integer_arithmetic_coerce_not_rescue, :+
- end
+ it_behaves_like :integer_arithmetic_coerce_not_rescue, :+
context "fixnum" do
it "returns self plus the given Integer" do
diff --git a/spec/ruby/core/integer/pow_spec.rb b/spec/ruby/core/integer/pow_spec.rb
index ed14c40a27..4712911095 100644
--- a/spec/ruby/core/integer/pow_spec.rb
+++ b/spec/ruby/core/integer/pow_spec.rb
@@ -2,48 +2,50 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/exponent'
-ruby_version_is "2.5" do
- describe "Integer#pow" do
- context "one argument is passed" do
- it_behaves_like :integer_exponent, :pow
+describe "Integer#pow" do
+ context "one argument is passed" do
+ it_behaves_like :integer_exponent, :pow
+ end
+
+ context "two arguments are passed" do
+ it "returns modulo of self raised to the given power" do
+ 2.pow(5, 12).should == 8
+ 2.pow(6, 13).should == 12
+ 2.pow(7, 14).should == 2
+ 2.pow(8, 15).should == 1
+ end
+
+ it "works well with bignums" do
+ 2.pow(61, 5843009213693951).should eql 3697379018277258
+ 2.pow(62, 5843009213693952).should eql 1551748822859776
+ 2.pow(63, 5843009213693953).should eql 3103497645717974
+ 2.pow(64, 5843009213693954).should eql 363986077738838
+ end
+
+ it "handles sign like #divmod does" do
+ 2.pow(5, 12).should == 8
+ 2.pow(5, -12).should == -4
+ -2.pow(5, 12).should == 4
+ -2.pow(5, -12).should == -8
+ end
+
+ it "ensures all arguments are integers" do
+ -> { 2.pow(5, 12.0) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/)
+ -> { 2.pow(5, Rational(12, 1)) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/)
+ end
+
+ it "raises TypeError for non-numeric value" do
+ -> { 2.pow(5, "12") }.should raise_error(TypeError)
+ -> { 2.pow(5, []) }.should raise_error(TypeError)
+ -> { 2.pow(5, nil) }.should raise_error(TypeError)
+ end
+
+ it "raises a ZeroDivisionError when the given argument is 0" do
+ -> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError)
end
- context "two arguments are passed" do
- it "returns modulo of self raised to the given power" do
- 2.pow(5, 12).should == 8
- 2.pow(6, 13).should == 12
- 2.pow(7, 14).should == 2
- 2.pow(8, 15).should == 1
- end
-
- it "works well with bignums" do
- 2.pow(61, 5843009213693951).should eql 3697379018277258
- 2.pow(62, 5843009213693952).should eql 1551748822859776
- 2.pow(63, 5843009213693953).should eql 3103497645717974
- 2.pow(64, 5843009213693954).should eql 363986077738838
- end
-
- it "handles sign like #divmod does" do
- 2.pow(5, 12).should == 8
- 2.pow(5, -12).should == -4
- -2.pow(5, 12).should == 4
- -2.pow(5, -12).should == -8
- end
-
- it "ensures all arguments are integers" do
- -> { 2.pow(5, 12.0) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/)
- -> { 2.pow(5, Rational(12, 1)) }.should raise_error(TypeError, /2nd argument not allowed unless all arguments are integers/)
- end
-
- it "raises TypeError for non-numeric value" do
- -> { 2.pow(5, "12") }.should raise_error(TypeError)
- -> { 2.pow(5, []) }.should raise_error(TypeError)
- -> { 2.pow(5, nil) }.should raise_error(TypeError)
- end
-
- it "raises a ZeroDivisionError when the given argument is 0" do
- -> { 2.pow(5, 0) }.should raise_error(ZeroDivisionError)
- end
+ it "raises a RangeError when the first argument is negative and the second argument is present" do
+ -> { 2.pow(-5, 1) }.should raise_error(RangeError)
end
end
end
diff --git a/spec/ruby/core/integer/right_shift_spec.rb b/spec/ruby/core/integer/right_shift_spec.rb
index 3eeaf3eb2f..62cbe862b9 100644
--- a/spec/ruby/core/integer/right_shift_spec.rb
+++ b/spec/ruby/core/integer/right_shift_spec.rb
@@ -56,23 +56,26 @@ describe "Integer#>> (with n >> m)" do
(3 >> bignum_value).should == 0
end
- it "returns an Bignum == fixnum_max * 2 when fixnum_max >> -1 and n > 0" do
+ it "returns an Integer == fixnum_max * 2 when fixnum_max >> -1 and n > 0" do
result = fixnum_max >> -1
- result.should be_an_instance_of(Bignum)
+ result.should be_an_instance_of(Integer)
result.should == fixnum_max * 2
end
- it "returns an Bignum == fixnum_min * 2 when fixnum_min >> -1 and n < 0" do
+ it "returns an Integer == fixnum_min * 2 when fixnum_min >> -1 and n < 0" do
result = fixnum_min >> -1
- result.should be_an_instance_of(Bignum)
+ result.should be_an_instance_of(Integer)
result.should == fixnum_min * 2
end
it "calls #to_int to convert the argument to an Integer" do
obj = mock("2")
obj.should_receive(:to_int).and_return(2)
-
(8 >> obj).should == 2
+
+ obj = mock("to_int_bignum")
+ obj.should_receive(:to_int).and_return(bignum_value)
+ (8 >> obj).should == 0
end
it "raises a TypeError when #to_int does not return an Integer" do
@@ -150,19 +153,19 @@ describe "Integer#>> (with n >> m)" do
(@bignum >> 68).should == 0
end
- it "returns 0 when m is a Bignum" do
+ it "returns 0 when m is an Integer" do
(@bignum >> bignum_value).should == 0
end
- it "returns a Fixnum == fixnum_max when (fixnum_max * 2) >> 1 and n > 0" do
+ it "returns an Integer == fixnum_max when (fixnum_max * 2) >> 1 and n > 0" do
result = (fixnum_max * 2) >> 1
- result.should be_an_instance_of(Fixnum)
+ result.should be_an_instance_of(Integer)
result.should == fixnum_max
end
- it "returns a Fixnum == fixnum_min when (fixnum_min * 2) >> 1 and n < 0" do
+ it "returns an Integer == fixnum_min when (fixnum_min * 2) >> 1 and n < 0" do
result = (fixnum_min * 2) >> 1
- result.should be_an_instance_of(Fixnum)
+ result.should be_an_instance_of(Integer)
result.should == fixnum_min
end
diff --git a/spec/ruby/core/integer/round_spec.rb b/spec/ruby/core/integer/round_spec.rb
index feb6d475d3..45ac126fd3 100644
--- a/spec/ruby/core/integer/round_spec.rb
+++ b/spec/ruby/core/integer/round_spec.rb
@@ -6,14 +6,6 @@ describe "Integer#round" do
it_behaves_like :integer_to_i, :round
it_behaves_like :integer_rounding_positive_precision, :round
- ruby_version_is ""..."2.5" do # Not just since 2.4
- it "rounds itself as a float if passed a positive precision" do
- [2, -4, 10**70, -10**100].each do |v|
- v.round(42).should eql(v.to_f)
- end
- end
- end
-
# redmine:5228
it "returns itself rounded if passed a negative value" do
+249.round(-2).should eql(+200)
@@ -78,20 +70,10 @@ describe "Integer#round" do
(-25).round(-1, half: nil).should eql(-30)
end
- ruby_version_is "2.4"..."2.5" do
- it "returns itself as a float if passed a positive precision and the half option" do
- 35.round(1, half: :up).should eql(35.0)
- 35.round(1, half: :down).should eql(35.0)
- 35.round(1, half: :even).should eql(35.0)
- end
- end
-
- ruby_version_is "2.5" do
- it "returns itself if passed a positive precision and the half option" do
- 35.round(1, half: :up).should eql(35)
- 35.round(1, half: :down).should eql(35)
- 35.round(1, half: :even).should eql(35)
- end
+ it "returns itself if passed a positive precision and the half option" do
+ 35.round(1, half: :up).should eql(35)
+ 35.round(1, half: :down).should eql(35)
+ 35.round(1, half: :even).should eql(35)
end
it "raises ArgumentError for an unknown rounding mode" do
diff --git a/spec/ruby/core/integer/shared/comparison_coerce.rb b/spec/ruby/core/integer/shared/comparison_coerce.rb
index 50437f77f5..af52f5e99b 100644
--- a/spec/ruby/core/integer/shared/comparison_coerce.rb
+++ b/spec/ruby/core/integer/shared/comparison_coerce.rb
@@ -1,27 +1,5 @@
require_relative '../fixtures/classes'
-describe :integer_comparison_coerce_rescue, shared: true do
- it "rescues exception (StandardError and subclasses) raised in other#coerce and raises ArgumentError" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(IntegerSpecs::CoerceError)
-
- # e.g. 1 > b
- -> {
- -> { 1.send(@method, b) }.should raise_error(ArgumentError, /comparison of Integer with MockObject failed/)
- }.should complain(/Numerical comparison operators will no more rescue exceptions of #coerce/)
- end
-
- it "does not rescue Exception and StandardError siblings raised in other#coerce" do
- [Exception, NoMemoryError].each do |exception|
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(exception)
-
- # e.g. 1 > b
- -> { 1.send(@method, b) }.should raise_error(exception)
- end
- end
-end
-
describe :integer_comparison_coerce_not_rescue, shared: true do
it "does not rescue exception raised in other#coerce" do
b = mock("numeric with failed #coerce")
diff --git a/spec/ruby/core/integer/shared/equal.rb b/spec/ruby/core/integer/shared/equal.rb
index 03416b60f5..ecee17831c 100644
--- a/spec/ruby/core/integer/shared/equal.rb
+++ b/spec/ruby/core/integer/shared/equal.rb
@@ -4,14 +4,14 @@ describe :integer_equal, shared: true do
1.send(@method, 1).should == true
9.send(@method, 5).should == false
- # Actually, these call Float#==, Bignum#== etc.
+ # Actually, these call Float#==, Integer#== etc.
9.send(@method, 9.0).should == true
9.send(@method, 9.01).should == false
10.send(@method, bignum_value).should == false
end
- it "calls 'other == self' if the given argument is not a Integer" do
+ it "calls 'other == self' if the given argument is not an Integer" do
1.send(@method, '*').should == false
obj = mock('one other')
diff --git a/spec/ruby/core/integer/shared/integer_rounding.rb b/spec/ruby/core/integer/shared/integer_rounding.rb
index 3fb6e830ef..56d1819f84 100644
--- a/spec/ruby/core/integer/shared/integer_rounding.rb
+++ b/spec/ruby/core/integer/shared/integer_rounding.rb
@@ -11,19 +11,9 @@ describe :integer_rounding_positive_precision, shared: true do
end
end
- ruby_version_is "2.4"..."2.5" do
- it "returns itself as a float if passed a positive precision" do
- [2, -4, 10**70, -10**100].each do |v|
- v.send(@method, 42).should eql(v.to_f)
- end
- end
- end
-
- ruby_version_is "2.5" do
- it "returns itself if passed a positive precision" do
- [2, -4, 10**70, -10**100].each do |v|
- v.send(@method, 42).should eql(v)
- end
+ it "returns itself if passed a positive precision" do
+ [2, -4, 10**70, -10**100].each do |v|
+ v.send(@method, 42).should eql(v)
end
end
end
diff --git a/spec/ruby/core/integer/shared/next.rb b/spec/ruby/core/integer/shared/next.rb
index 85b83d6965..fd983d53ec 100644
--- a/spec/ruby/core/integer/shared/next.rb
+++ b/spec/ruby/core/integer/shared/next.rb
@@ -1,25 +1,25 @@
describe :integer_next, shared: true do
- it "returns the next larger positive Fixnum" do
+ it "returns the next larger positive Integer" do
2.send(@method).should == 3
end
- it "returns the next larger negative Fixnum" do
+ it "returns the next larger negative Integer" do
(-2).send(@method).should == -1
end
- it "returns the next larger positive Bignum" do
+ it "returns the next larger positive Integer" do
bignum_value.send(@method).should == bignum_value(1)
end
- it "returns the next larger negative Bignum" do
+ it "returns the next larger negative Integer" do
(-bignum_value(1)).send(@method).should == -bignum_value
end
- it "overflows a Fixnum to a Bignum" do
+ it "overflows an Integer to an Integer" do
fixnum_max.send(@method).should == fixnum_max + 1
end
- it "underflows a Bignum to a Fixnum" do
+ it "underflows an Integer to an Integer" do
(fixnum_min - 1).send(@method).should == fixnum_min
end
end
diff --git a/spec/ruby/core/integer/sqrt_spec.rb b/spec/ruby/core/integer/sqrt_spec.rb
index e56da058a0..4149ca2cc9 100644
--- a/spec/ruby/core/integer/sqrt_spec.rb
+++ b/spec/ruby/core/integer/sqrt_spec.rb
@@ -1,33 +1,31 @@
require_relative '../../spec_helper'
-ruby_version_is "2.5" do
- describe "Integer.sqrt" do
- it "returns an integer" do
- Integer.sqrt(10).should be_kind_of(Integer)
- end
+describe "Integer.sqrt" do
+ it "returns an integer" do
+ Integer.sqrt(10).should be_kind_of(Integer)
+ end
- it "returns the integer square root of the argument" do
- Integer.sqrt(0).should == 0
- Integer.sqrt(1).should == 1
- Integer.sqrt(24).should == 4
- Integer.sqrt(25).should == 5
- Integer.sqrt(10**400).should == 10**200
- end
+ it "returns the integer square root of the argument" do
+ Integer.sqrt(0).should == 0
+ Integer.sqrt(1).should == 1
+ Integer.sqrt(24).should == 4
+ Integer.sqrt(25).should == 5
+ Integer.sqrt(10**400).should == 10**200
+ end
- it "raises a Math::DomainError if the argument is negative" do
- -> { Integer.sqrt(-4) }.should raise_error(Math::DomainError)
- end
+ it "raises a Math::DomainError if the argument is negative" do
+ -> { Integer.sqrt(-4) }.should raise_error(Math::DomainError)
+ end
- it "accepts any argument that can be coerced to Integer" do
- Integer.sqrt(10.0).should == 3
- end
+ it "accepts any argument that can be coerced to Integer" do
+ Integer.sqrt(10.0).should == 3
+ end
- it "converts the argument with #to_int" do
- Integer.sqrt(mock_int(10)).should == 3
- end
+ it "converts the argument with #to_int" do
+ Integer.sqrt(mock_int(10)).should == 3
+ end
- it "raises a TypeError if the argument cannot be coerced to Integer" do
- -> { Integer.sqrt("test") }.should raise_error(TypeError)
- end
+ it "raises a TypeError if the argument cannot be coerced to Integer" do
+ -> { Integer.sqrt("test") }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/integer/to_r_spec.rb b/spec/ruby/core/integer/to_r_spec.rb
index 4a40575b7f..ac998e2a30 100644
--- a/spec/ruby/core/integer/to_r_spec.rb
+++ b/spec/ruby/core/integer/to_r_spec.rb
@@ -13,9 +13,9 @@ describe "Integer#to_r" do
298.to_r.denominator.should == 1
end
- it "works even if self is a Bignum" do
+ it "works even if self is an Integer" do
bignum = 99999**999
- bignum.should be_an_instance_of(Bignum)
+ bignum.should be_an_instance_of(Integer)
bignum.to_r.should == Rational(bignum, 1)
end
diff --git a/spec/ruby/core/integer/uminus_spec.rb b/spec/ruby/core/integer/uminus_spec.rb
index b6b110dec4..efaed1d2a6 100644
--- a/spec/ruby/core/integer/uminus_spec.rb
+++ b/spec/ruby/core/integer/uminus_spec.rb
@@ -10,7 +10,7 @@ describe "Integer#-@" do
-8.send(:-@).should == 8
end
- it "negates self at Fixnum/Bignum boundaries" do
+ it "negates self at Integer/Integer boundaries" do
(-fixnum_max).should == (0 - fixnum_max)
(-fixnum_max).should < 0
(-fixnum_min).should == (0 - fixnum_min)
diff --git a/spec/ruby/core/integer/upto_spec.rb b/spec/ruby/core/integer/upto_spec.rb
index 6049eb173e..dd6995e94b 100644
--- a/spec/ruby/core/integer/upto_spec.rb
+++ b/spec/ruby/core/integer/upto_spec.rb
@@ -1,6 +1,6 @@
require_relative '../../spec_helper'
-describe "Integer#upto [stop] when self and stop are Fixnums" do
+describe "Integer#upto [stop] when self and stop are Integers" do
it "does not yield when stop is less than self" do
result = []
5.upto(4) { |x| result << x }
diff --git a/spec/ruby/core/io/bytes_spec.rb b/spec/ruby/core/io/bytes_spec.rb
index feeb493566..27a44a7c6c 100644
--- a/spec/ruby/core/io/bytes_spec.rb
+++ b/spec/ruby/core/io/bytes_spec.rb
@@ -2,42 +2,44 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-describe "IO#bytes" do
- before :each do
- @io = IOSpecs.io_fixture "lines.txt"
- end
-
- after :each do
- @io.close unless @io.closed?
- end
+ruby_version_is ''...'3.0' do
+ describe "IO#bytes" do
+ before :each do
+ @io = IOSpecs.io_fixture "lines.txt"
+ end
- it "returns an enumerator of the next bytes from the stream" do
- enum = @io.bytes
- enum.should be_an_instance_of(Enumerator)
- @io.readline.should == "Voici la ligne une.\n"
- enum.first(5).should == [81, 117, 105, 32, 195]
- end
+ after :each do
+ @io.close unless @io.closed?
+ end
- it "yields each byte" do
- count = 0
- ScratchPad.record []
- @io.each_byte do |byte|
- ScratchPad << byte
- break if 4 < count += 1
+ it "returns an enumerator of the next bytes from the stream" do
+ enum = @io.bytes
+ enum.should be_an_instance_of(Enumerator)
+ @io.readline.should == "Voici la ligne une.\n"
+ enum.first(5).should == [81, 117, 105, 32, 195]
end
- ScratchPad.recorded.should == [86, 111, 105, 99, 105]
- end
+ it "yields each byte" do
+ count = 0
+ ScratchPad.record []
+ @io.each_byte do |byte|
+ ScratchPad << byte
+ break if 4 < count += 1
+ end
- it "raises an IOError on closed stream" do
- enum = IOSpecs.closed_io.bytes
- -> { enum.first }.should raise_error(IOError)
- end
+ ScratchPad.recorded.should == [86, 111, 105, 99, 105]
+ end
- it "raises an IOError on an enumerator for a stream that has been closed" do
- enum = @io.bytes
- enum.first.should == 86
- @io.close
- -> { enum.first }.should raise_error(IOError)
+ it "raises an IOError on closed stream" do
+ enum = IOSpecs.closed_io.bytes
+ -> { enum.first }.should raise_error(IOError)
+ end
+
+ it "raises an IOError on an enumerator for a stream that has been closed" do
+ enum = @io.bytes
+ enum.first.should == 86
+ @io.close
+ -> { enum.first }.should raise_error(IOError)
+ end
end
end
diff --git a/spec/ruby/core/io/chars_spec.rb b/spec/ruby/core/io/chars_spec.rb
index cd5dbbce4f..812ddbf34f 100644
--- a/spec/ruby/core/io/chars_spec.rb
+++ b/spec/ruby/core/io/chars_spec.rb
@@ -3,10 +3,12 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/chars'
-describe "IO#chars" do
- it_behaves_like :io_chars, :chars
-end
+ruby_version_is ''...'3.0' do
+ describe "IO#chars" do
+ it_behaves_like :io_chars, :chars
+ end
-describe "IO#chars" do
- it_behaves_like :io_chars_empty, :chars
+ describe "IO#chars" do
+ it_behaves_like :io_chars_empty, :chars
+ end
end
diff --git a/spec/ruby/core/io/close_on_exec_spec.rb b/spec/ruby/core/io/close_on_exec_spec.rb
index f837bb56af..91bd3c8c40 100644
--- a/spec/ruby/core/io/close_on_exec_spec.rb
+++ b/spec/ruby/core/io/close_on_exec_spec.rb
@@ -14,24 +14,24 @@ describe "IO#close_on_exec=" do
guard -> { platform_is_not :windows } do
it "sets the close-on-exec flag if true" do
@io.close_on_exec = true
- @io.close_on_exec?.should == true
+ @io.should.close_on_exec?
end
it "sets the close-on-exec flag if non-false" do
@io.close_on_exec = :true
- @io.close_on_exec?.should == true
+ @io.should.close_on_exec?
end
it "unsets the close-on-exec flag if false" do
@io.close_on_exec = true
@io.close_on_exec = false
- @io.close_on_exec?.should == false
+ @io.should_not.close_on_exec?
end
it "unsets the close-on-exec flag if nil" do
@io.close_on_exec = true
@io.close_on_exec = nil
- @io.close_on_exec?.should == false
+ @io.should_not.close_on_exec?
end
it "ensures the IO's file descriptor is closed in exec'ed processes" do
@@ -64,12 +64,12 @@ describe "IO#close_on_exec?" do
guard -> { platform_is_not :windows } do
it "returns true by default" do
- @io.close_on_exec?.should == true
+ @io.should.close_on_exec?
end
it "returns true if set" do
@io.close_on_exec = true
- @io.close_on_exec?.should == true
+ @io.should.close_on_exec?
end
it "raises IOError if called on a closed IO" do
diff --git a/spec/ruby/core/io/close_read_spec.rb b/spec/ruby/core/io/close_read_spec.rb
index 6fa4fc8ff8..26454bfddd 100644
--- a/spec/ruby/core/io/close_read_spec.rb
+++ b/spec/ruby/core/io/close_read_spec.rb
@@ -49,7 +49,7 @@ describe "IO#close_read" do
io.close_read
- io.closed?.should == true
+ io.should.closed?
end
it "does nothing on closed stream" do
diff --git a/spec/ruby/core/io/close_spec.rb b/spec/ruby/core/io/close_spec.rb
index 21bba32cd8..dda82b34de 100644
--- a/spec/ruby/core/io/close_spec.rb
+++ b/spec/ruby/core/io/close_spec.rb
@@ -14,7 +14,7 @@ describe "IO#close" do
it "closes the stream" do
@io.close
- @io.closed?.should == true
+ @io.should.closed?
end
it "returns nil" do
@@ -44,22 +44,20 @@ describe "IO#close" do
@io.close.should be_nil
end
- ruby_version_is '2.5' do
- it 'raises an IOError with a clear message' do
- read_io, write_io = IO.pipe
- going_to_read = false
- thread = Thread.new do
- -> do
- going_to_read = true
- read_io.read
- end.should raise_error(IOError, 'stream closed in another thread')
- end
-
- Thread.pass until going_to_read && thread.stop?
- read_io.close
- thread.join
- write_io.close
+ it 'raises an IOError with a clear message' do
+ read_io, write_io = IO.pipe
+ going_to_read = false
+ thread = Thread.new do
+ -> do
+ going_to_read = true
+ read_io.read
+ end.should raise_error(IOError, 'stream closed in another thread')
end
+
+ Thread.pass until going_to_read && thread.stop?
+ read_io.close
+ thread.join
+ write_io.close
end
end
diff --git a/spec/ruby/core/io/close_write_spec.rb b/spec/ruby/core/io/close_write_spec.rb
index 75e1577654..14835e4e2c 100644
--- a/spec/ruby/core/io/close_write_spec.rb
+++ b/spec/ruby/core/io/close_write_spec.rb
@@ -45,7 +45,7 @@ describe "IO#close_write" do
io.close_write
- io.closed?.should == true
+ io.should.closed?
end
it "flushes and closes the write stream" do
diff --git a/spec/ruby/core/io/codepoints_spec.rb b/spec/ruby/core/io/codepoints_spec.rb
index 915d99c027..6b275af8d1 100644
--- a/spec/ruby/core/io/codepoints_spec.rb
+++ b/spec/ruby/core/io/codepoints_spec.rb
@@ -2,24 +2,27 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/codepoints'
-# See redmine #1667
-describe "IO#codepoints" do
- it_behaves_like :io_codepoints, :codepoints
-end
+ruby_version_is ''...'3.0' do
-describe "IO#codepoints" do
- before :each do
- @io = IOSpecs.io_fixture "lines.txt"
+ # See redmine #1667
+ describe "IO#codepoints" do
+ it_behaves_like :io_codepoints, :codepoints
end
- after :each do
- @io.close unless @io.closed?
- end
+ describe "IO#codepoints" do
+ before :each do
+ @io = IOSpecs.io_fixture "lines.txt"
+ end
+
+ after :each do
+ @io.close unless @io.closed?
+ end
- it "calls the given block" do
- r = []
- @io.codepoints { |c| r << c }
- r[24].should == 232
- r.last.should == 10
+ it "calls the given block" do
+ r = []
+ @io.codepoints { |c| r << c }
+ r[24].should == 232
+ r.last.should == 10
+ end
end
end
diff --git a/spec/ruby/core/io/copy_stream_spec.rb b/spec/ruby/core/io/copy_stream_spec.rb
index c541e96e14..df9c5c7390 100644
--- a/spec/ruby/core/io/copy_stream_spec.rb
+++ b/spec/ruby/core/io/copy_stream_spec.rb
@@ -279,4 +279,44 @@ describe "IO.copy_stream" do
end
end
+
+
+ describe "with a destination that does partial reads" do
+ before do
+ @from_out, @from_in = IO.pipe
+ @to_out, @to_in = IO.pipe
+ end
+
+ after do
+ [@from_out, @from_in, @to_out, @to_in].each {|io| io.close rescue nil}
+ end
+
+ it "calls #write repeatedly on the destination Object" do
+ @from_in.write "1234"
+ @from_in.close
+
+ th = Thread.new do
+ IO.copy_stream(@from_out, @to_in)
+ end
+
+ copied = ""
+ 4.times do
+ copied += @to_out.read(1)
+ end
+
+ th.join
+
+ copied.should == "1234"
+ end
+
+ end
+end
+
+describe "IO.copy_stream" do
+ it "does not use buffering when writing to STDOUT" do
+ IO.popen([*ruby_exe, fixture(__FILE__ , "copy_in_out.rb")], "r+") do |io|
+ io.write("bar")
+ io.read(3).should == "bar"
+ end
+ end
end
diff --git a/spec/ruby/core/io/dup_spec.rb b/spec/ruby/core/io/dup_spec.rb
index de32c5e347..8cadaee118 100644
--- a/spec/ruby/core/io/dup_spec.rb
+++ b/spec/ruby/core/io/dup_spec.rb
@@ -51,16 +51,16 @@ end
@i.close
-> { @f.gets }.should_not raise_error(Exception)
- @i.closed?.should == true
- @f.closed?.should == false
+ @i.should.closed?
+ @f.should_not.closed?
end
it "allows closing the original IO without affecting the new one" do
@f.close
-> { @i.gets }.should_not raise_error(Exception)
- @i.closed?.should == false
- @f.closed?.should == true
+ @i.should_not.closed?
+ @f.should.closed?
end
it "raises IOError on closed stream" do
@@ -71,7 +71,7 @@ end
@f.close_on_exec = true
dup = @f.dup
begin
- dup.close_on_exec?.should == true
+ dup.should.close_on_exec?
ensure
dup.close
end
@@ -79,7 +79,7 @@ end
@f.close_on_exec = false
dup = @f.dup
begin
- dup.close_on_exec?.should == true
+ dup.should.close_on_exec?
ensure
dup.close
end
diff --git a/spec/ruby/core/io/each_codepoint_spec.rb b/spec/ruby/core/io/each_codepoint_spec.rb
index cddc6b4662..07a4037c8a 100644
--- a/spec/ruby/core/io/each_codepoint_spec.rb
+++ b/spec/ruby/core/io/each_codepoint_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/codepoints'
# See redmine #1667
describe "IO#each_codepoint" do
- it_behaves_like :io_codepoints, :codepoints
+ it_behaves_like :io_codepoints, :each_codepoint
end
describe "IO#each_codepoint" do
diff --git a/spec/ruby/core/io/eof_spec.rb b/spec/ruby/core/io/eof_spec.rb
index 8fd3c37132..315345d942 100644
--- a/spec/ruby/core/io/eof_spec.rb
+++ b/spec/ruby/core/io/eof_spec.rb
@@ -12,7 +12,7 @@ describe "IO#eof?" do
end
it "returns true on an empty stream that has just been opened" do
- File.open(@name) { |empty| empty.eof?.should == true }
+ File.open(@name) { |empty| empty.should.eof? }
end
it "raises IOError on stream not opened for reading" do
@@ -34,35 +34,35 @@ describe "IO#eof?" do
it "returns false when not at end of file" do
@io.read 1
- @io.eof?.should == false
+ @io.should_not.eof?
end
it "returns true after reading with read with no parameters" do
@io.read()
- @io.eof?.should == true
+ @io.should.eof?
end
it "returns true after reading with read" do
@io.read(File.size(@name))
- @io.eof?.should == true
+ @io.should.eof?
end
it "returns true after reading with sysread" do
@io.sysread(File.size(@name))
- @io.eof?.should == true
+ @io.should.eof?
end
it "returns true after reading with readlines" do
@io.readlines
- @io.eof?.should == true
+ @io.should.eof?
end
it "returns false on just opened non-empty stream" do
- @io.eof?.should == false
+ @io.should_not.eof?
end
it "does not consume the data from the stream" do
- @io.eof?.should == false
+ @io.should_not.eof?
@io.getc.should == 'V'
end
@@ -78,7 +78,7 @@ describe "IO#eof?" do
it "returns true on one-byte stream after single-byte read" do
File.open(File.dirname(__FILE__) + '/fixtures/one_byte.txt') { |one_byte|
one_byte.read(1)
- one_byte.eof?.should == true
+ one_byte.should.eof?
}
end
end
@@ -92,16 +92,16 @@ describe "IO#eof?" do
it "returns true on receiving side of Pipe when writing side is closed" do
@r, @w = IO.pipe
@w.close
- @r.eof?.should == true
+ @r.should.eof?
end
it "returns false on receiving side of Pipe when writing side wrote some data" do
@r, @w = IO.pipe
@w.puts "hello"
- @r.eof?.should == false
+ @r.should_not.eof?
@w.close
- @r.eof?.should == false
+ @r.should_not.eof?
@r.read
- @r.eof?.should == true
+ @r.should.eof?
end
end
diff --git a/spec/ruby/core/io/fixtures/classes.rb b/spec/ruby/core/io/fixtures/classes.rb
index 460dd62387..5cc42c9b44 100644
--- a/spec/ruby/core/io/fixtures/classes.rb
+++ b/spec/ruby/core/io/fixtures/classes.rb
@@ -164,7 +164,7 @@ module IOSpecs
@io = io
end
- def read(size, buf=nil)
+ def read(size, buf)
@io.read size, buf
end
@@ -178,7 +178,7 @@ module IOSpecs
@io = io
end
- def readpartial(size, buf=nil)
+ def readpartial(size, buf)
@io.readpartial size, buf
end
diff --git a/spec/ruby/core/io/fixtures/copy_in_out.rb b/spec/ruby/core/io/fixtures/copy_in_out.rb
new file mode 100644
index 0000000000..b9d4085a47
--- /dev/null
+++ b/spec/ruby/core/io/fixtures/copy_in_out.rb
@@ -0,0 +1,2 @@
+STDOUT.sync = false
+IO.copy_stream(STDIN, STDOUT)
diff --git a/spec/ruby/core/io/gets_spec.rb b/spec/ruby/core/io/gets_spec.rb
index 39b2108476..a3cd180b66 100644
--- a/spec/ruby/core/io/gets_spec.rb
+++ b/spec/ruby/core/io/gets_spec.rb
@@ -41,7 +41,7 @@ describe "IO#gets" do
ruby_version_is ''...'2.7' do
it "returns tainted strings" do
while line = @io.gets
- line.tainted?.should == true
+ line.should.tainted?
end
end
end
@@ -67,7 +67,7 @@ describe "IO#gets" do
ruby_version_is ''...'2.7' do
it "returns tainted strings" do
while line = @io.gets(nil)
- line.tainted?.should == true
+ line.should.tainted?
end
end
end
@@ -103,7 +103,7 @@ describe "IO#gets" do
ruby_version_is ''...'2.7' do
it "returns tainted strings" do
while line = @io.gets("")
- line.tainted?.should == true
+ line.should.tainted?
end
end
end
@@ -129,7 +129,7 @@ describe "IO#gets" do
ruby_version_is ''...'2.7' do
it "returns tainted strings" do
while line = @io.gets("la")
- line.tainted?.should == true
+ line.should.tainted?
end
end
end
diff --git a/spec/ruby/core/io/initialize_spec.rb b/spec/ruby/core/io/initialize_spec.rb
index c0d84765a8..ba5bc117b7 100644
--- a/spec/ruby/core/io/initialize_spec.rb
+++ b/spec/ruby/core/io/initialize_spec.rb
@@ -13,7 +13,7 @@ describe "IO#initialize" do
rm_r @name
end
- it "reassociates the IO instance with the new descriptor when passed a Fixnum" do
+ it "reassociates the IO instance with the new descriptor when passed an Integer" do
fd = new_fd @name, "r:utf-8"
@io.send :initialize, fd, 'r'
@io.fileno.should == fd
diff --git a/spec/ruby/core/io/ioctl_spec.rb b/spec/ruby/core/io/ioctl_spec.rb
index e819a217a8..8dcd9eb2c6 100644
--- a/spec/ruby/core/io/ioctl_spec.rb
+++ b/spec/ruby/core/io/ioctl_spec.rb
@@ -20,12 +20,12 @@ describe "IO#ioctl" do
end
end
- it "raises an Errno error when ioctl fails" do
+ it "raises a system call error when ioctl fails" do
File.open(__FILE__, 'r') do |f|
-> {
# TIOCGWINSZ in /usr/include/asm-generic/ioctls.h
f.ioctl 0x5413, nil
- }.should raise_error(Errno::ENOTTY)
+ }.should raise_error(SystemCallError)
end
end
end
diff --git a/spec/ruby/core/io/lines_spec.rb b/spec/ruby/core/io/lines_spec.rb
index a8b8023a2a..947c068f42 100644
--- a/spec/ruby/core/io/lines_spec.rb
+++ b/spec/ruby/core/io/lines_spec.rb
@@ -2,41 +2,43 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-describe "IO#lines" do
- before :each do
- @io = IOSpecs.io_fixture "lines.txt"
- end
-
- after :each do
- @io.close if @io
- end
+ruby_version_is ''...'3.0' do
+ describe "IO#lines" do
+ before :each do
+ @io = IOSpecs.io_fixture "lines.txt"
+ end
- it "returns an Enumerator" do
- @io.lines.should be_an_instance_of(Enumerator)
- end
+ after :each do
+ @io.close if @io
+ end
- describe "when no block is given" do
it "returns an Enumerator" do
@io.lines.should be_an_instance_of(Enumerator)
end
- describe "returned Enumerator" do
- describe "size" do
- it "should return nil" do
- @io.lines.size.should == nil
+ describe "when no block is given" do
+ it "returns an Enumerator" do
+ @io.lines.should be_an_instance_of(Enumerator)
+ end
+
+ describe "returned Enumerator" do
+ describe "size" do
+ it "should return nil" do
+ @io.lines.size.should == nil
+ end
end
end
end
- end
- it "returns a line when accessed" do
- enum = @io.lines
- enum.first.should == IOSpecs.lines[0]
- end
+ it "returns a line when accessed" do
+ enum = @io.lines
+ enum.first.should == IOSpecs.lines[0]
+ end
- it "yields each line to the passed block" do
- ScratchPad.record []
- @io.lines { |s| ScratchPad << s }
- ScratchPad.recorded.should == IOSpecs.lines
+ it "yields each line to the passed block" do
+ ScratchPad.record []
+ @io.lines { |s| ScratchPad << s }
+ ScratchPad.recorded.should == IOSpecs.lines
+ end
end
end
diff --git a/spec/ruby/core/io/pipe_spec.rb b/spec/ruby/core/io/pipe_spec.rb
index a7dcb7fab8..2f2cf06f4d 100644
--- a/spec/ruby/core/io/pipe_spec.rb
+++ b/spec/ruby/core/io/pipe_spec.rb
@@ -44,8 +44,8 @@ describe "IO.pipe" do
r, w = IO.pipe do |_r, _w|
[_r, _w]
end
- r.closed?.should == true
- w.closed?.should == true
+ r.should.closed?
+ w.should.closed?
end
it "closes both IO objects when the block raises" do
@@ -57,8 +57,8 @@ describe "IO.pipe" do
raise RuntimeError
end
end.should raise_error(RuntimeError)
- r.closed?.should == true
- w.closed?.should == true
+ r.should.closed?
+ w.should.closed?
end
it "allows IO objects to be closed within the block" do
@@ -67,8 +67,8 @@ describe "IO.pipe" do
_w.close
[_r, _w]
end
- r.closed?.should == true
- w.closed?.should == true
+ r.should.closed?
+ w.should.closed?
end
end
end
diff --git a/spec/ruby/core/io/popen_spec.rb b/spec/ruby/core/io/popen_spec.rb
index 4f873e61cd..e9d32c5c7d 100644
--- a/spec/ruby/core/io/popen_spec.rb
+++ b/spec/ruby/core/io/popen_spec.rb
@@ -77,10 +77,10 @@ describe "IO.popen" do
Process.kill "KILL", pid
@io.close
platform_is_not :windows do
- $?.signaled?.should == true
+ $?.should.signaled?
end
platform_is :windows do
- $?.exited?.should == true
+ $?.should.exited?
end
end
diff --git a/spec/ruby/core/io/pread_spec.rb b/spec/ruby/core/io/pread_spec.rb
index bfe6472fef..43071d6a31 100644
--- a/spec/ruby/core/io/pread_spec.rb
+++ b/spec/ruby/core/io/pread_spec.rb
@@ -1,52 +1,50 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
-ruby_version_is "2.5" do
- platform_is_not :windows do
- describe "IO#pread" do
- before :each do
- @fname = tmp("io_pread.txt")
- @contents = "1234567890"
- touch(@fname) { |f| f.write @contents }
- @file = File.open(@fname, "r+")
- end
-
- after :each do
- @file.close
- rm_r @fname
- end
+platform_is_not :windows do
+ describe "IO#pread" do
+ before :each do
+ @fname = tmp("io_pread.txt")
+ @contents = "1234567890"
+ touch(@fname) { |f| f.write @contents }
+ @file = File.open(@fname, "r+")
+ end
- it "accepts a length, and an offset" do
- @file.pread(4, 0).should == "1234"
- @file.pread(3, 4).should == "567"
- end
+ after :each do
+ @file.close
+ rm_r @fname
+ end
- it "accepts a length, an offset, and an output buffer" do
- buffer = "foo"
- @file.pread(3, 4, buffer)
- buffer.should == "567"
- end
+ it "accepts a length, and an offset" do
+ @file.pread(4, 0).should == "1234"
+ @file.pread(3, 4).should == "567"
+ end
- it "does not advance the file pointer" do
- @file.pread(4, 0).should == "1234"
- @file.read.should == "1234567890"
- end
+ it "accepts a length, an offset, and an output buffer" do
+ buffer = "foo"
+ @file.pread(3, 4, buffer)
+ buffer.should == "567"
+ end
- it "raises EOFError if end-of-file is reached" do
- -> { @file.pread(1, 10) }.should raise_error(EOFError)
- end
+ it "does not advance the file pointer" do
+ @file.pread(4, 0).should == "1234"
+ @file.read.should == "1234567890"
+ end
- it "raises IOError when file is not open in read mode" do
- File.open(@fname, "w") do |file|
- -> { file.pread(1, 1) }.should raise_error(IOError)
- end
- end
+ it "raises EOFError if end-of-file is reached" do
+ -> { @file.pread(1, 10) }.should raise_error(EOFError)
+ end
- it "raises IOError when file is closed" do
- file = File.open(@fname, "r+")
- file.close
+ it "raises IOError when file is not open in read mode" do
+ File.open(@fname, "w") do |file|
-> { file.pread(1, 1) }.should raise_error(IOError)
end
end
+
+ it "raises IOError when file is closed" do
+ file = File.open(@fname, "r+")
+ file.close
+ -> { file.pread(1, 1) }.should raise_error(IOError)
+ end
end
end
diff --git a/spec/ruby/core/io/print_spec.rb b/spec/ruby/core/io/print_spec.rb
index 2021cd5420..04e971ef6d 100644
--- a/spec/ruby/core/io/print_spec.rb
+++ b/spec/ruby/core/io/print_spec.rb
@@ -1,15 +1,15 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-describe IO, "#print" do
+describe "IO#print" do
before :each do
@old_separator = $\
- $\ = '->'
+ suppress_warning {$\ = '->'}
@name = tmp("io_print")
end
after :each do
- $\ = @old_separator
+ suppress_warning {$\ = @old_separator}
rm_r @name
end
diff --git a/spec/ruby/core/io/puts_spec.rb b/spec/ruby/core/io/puts_spec.rb
index 3e4b877b7f..9a708fffef 100644
--- a/spec/ruby/core/io/puts_spec.rb
+++ b/spec/ruby/core/io/puts_spec.rb
@@ -16,7 +16,7 @@ describe "IO#puts" do
ScratchPad.clear
@io.close if @io
rm_r @name
- $/ = @before_separator
+ suppress_warning {$/ = @before_separator}
end
it "writes just a newline when given no args" do
@@ -25,7 +25,7 @@ describe "IO#puts" do
end
it "writes just a newline when given just a newline" do
- -> { $stdout.puts "\n" }.should output_to_fd("\n", STDOUT)
+ -> { $stdout.puts "\n" }.should output_to_fd("\n", $stdout)
end
it "writes empty string with a newline when given nil as an arg" do
@@ -105,7 +105,7 @@ describe "IO#puts" do
end
it "ignores the $/ separator global" do
- $/ = ":"
+ suppress_warning {$/ = ":"}
@io.puts(5).should == nil
ScratchPad.recorded.should == "5\n"
end
diff --git a/spec/ruby/core/io/pwrite_spec.rb b/spec/ruby/core/io/pwrite_spec.rb
index 929ed08698..fe29d1e1f6 100644
--- a/spec/ruby/core/io/pwrite_spec.rb
+++ b/spec/ruby/core/io/pwrite_spec.rb
@@ -1,45 +1,43 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
-ruby_version_is "2.5" do
- platform_is_not :windows do
- describe "IO#pwrite" do
- before :each do
- @fname = tmp("io_pwrite.txt")
- @file = File.open(@fname, "w+")
- end
-
- after :each do
- @file.close
- rm_r @fname
- end
+platform_is_not :windows do
+ describe "IO#pwrite" do
+ before :each do
+ @fname = tmp("io_pwrite.txt")
+ @file = File.open(@fname, "w+")
+ end
- it "returns the number of bytes written" do
- @file.pwrite("foo", 0).should == 3
- end
+ after :each do
+ @file.close
+ rm_r @fname
+ end
- it "accepts a string and an offset" do
- @file.pwrite("foo", 2)
- @file.pread(3, 2).should == "foo"
- end
+ it "returns the number of bytes written" do
+ @file.pwrite("foo", 0).should == 3
+ end
- it "does not advance the pointer in the file" do
- @file.pwrite("bar", 3)
- @file.write("foo")
- @file.pread(6, 0).should == "foobar"
- end
+ it "accepts a string and an offset" do
+ @file.pwrite("foo", 2)
+ @file.pread(3, 2).should == "foo"
+ end
- it "raises IOError when file is not open in write mode" do
- File.open(@fname, "r") do |file|
- -> { file.pwrite("foo", 1) }.should raise_error(IOError)
- end
- end
+ it "does not advance the pointer in the file" do
+ @file.pwrite("bar", 3)
+ @file.write("foo")
+ @file.pread(6, 0).should == "foobar"
+ end
- it "raises IOError when file is closed" do
- file = File.open(@fname, "w+")
- file.close
+ it "raises IOError when file is not open in write mode" do
+ File.open(@fname, "r") do |file|
-> { file.pwrite("foo", 1) }.should raise_error(IOError)
end
end
+
+ it "raises IOError when file is closed" do
+ file = File.open(@fname, "w+")
+ file.close
+ -> { file.pwrite("foo", 1) }.should raise_error(IOError)
+ end
end
end
diff --git a/spec/ruby/core/io/read_nonblock_spec.rb b/spec/ruby/core/io/read_nonblock_spec.rb
index 63ccab5a44..e50531d336 100644
--- a/spec/ruby/core/io/read_nonblock_spec.rb
+++ b/spec/ruby/core/io/read_nonblock_spec.rb
@@ -46,7 +46,7 @@ describe "IO#read_nonblock" do
require 'io/nonblock'
@write.write "abc"
@read.read_nonblock(1).should == "a"
- @read.nonblock?.should == true
+ @read.should.nonblock?
end
end
diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb
index 1e9a8d2a4f..841e693f37 100644
--- a/spec/ruby/core/io/read_spec.rb
+++ b/spec/ruby/core/io/read_spec.rb
@@ -216,7 +216,7 @@ describe "IO#read" do
it "is at end-of-file when everything has been read" do
@io.read
- @io.eof?.should == true
+ @io.should.eof?
end
it "reads the contents of a file" do
diff --git a/spec/ruby/core/io/readlines_spec.rb b/spec/ruby/core/io/readlines_spec.rb
index 0d4f002972..254f2927b5 100644
--- a/spec/ruby/core/io/readlines_spec.rb
+++ b/spec/ruby/core/io/readlines_spec.rb
@@ -22,11 +22,11 @@ describe "IO#readlines" do
describe "when passed no arguments" do
before :each do
- @sep, $/ = $/, " "
+ suppress_warning {@sep, $/ = $/, " "}
end
after :each do
- $/ = @sep
+ suppress_warning {$/ = @sep}
end
it "returns an Array containing lines based on $/" do
@@ -101,31 +101,6 @@ describe "IO#readlines" do
@io.readlines(obj).should == IOSpecs.lines_r_separator
end
end
-
- describe "when passed a string that starts with a |" do
- it "gets data from the standard out of the subprocess" do
- cmd = "|sh -c 'echo hello;echo line2'"
- platform_is :windows do
- cmd = "|cmd.exe /C echo hello&echo line2"
- end
- lines = IO.readlines(cmd)
- lines.should == ["hello\n", "line2\n"]
- end
-
- platform_is_not :windows do
- it "gets data from a fork when passed -" do
- lines = IO.readlines("|-")
-
- if lines # parent
- lines.should == ["hello\n", "from a fork\n"]
- else
- puts "hello"
- puts "from a fork"
- exit!
- end
- end
- end
- end
end
describe "IO#readlines" do
@@ -169,6 +144,31 @@ 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 = IO.readlines(cmd)
+ lines.should == ["hello\n", "line2\n"]
+ end
+
+ platform_is_not :windows do
+ it "gets data from a fork when passed -" do
+ lines = IO.readlines("|-")
+
+ if lines # parent
+ lines.should == ["hello\n", "from a fork\n"]
+ else
+ puts "hello"
+ puts "from a fork"
+ exit!
+ end
+ end
+ end
+ end
+
it_behaves_like :io_readlines, :readlines
it_behaves_like :io_readlines_options_19, :readlines
end
@@ -184,7 +184,7 @@ describe "IO.readlines" do
after :each do
Encoding.default_external = @external
Encoding.default_internal = @internal
- $/ = @dollar_slash
+ suppress_warning {$/ = @dollar_slash}
end
it "encodes lines using the default external encoding" do
@@ -196,7 +196,7 @@ describe "IO.readlines" do
it "encodes lines using the default internal encoding, when set" do
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_16
- $/ = $/.encode Encoding::UTF_16
+ suppress_warning {$/ = $/.encode Encoding::UTF_16}
lines = IO.readlines(@name)
lines.all? { |s| s.encoding == Encoding::UTF_16 }.should be_true
end
diff --git a/spec/ruby/core/io/reopen_spec.rb b/spec/ruby/core/io/reopen_spec.rb
index faef80f513..8ff0f217f4 100644
--- a/spec/ruby/core/io/reopen_spec.rb
+++ b/spec/ruby/core/io/reopen_spec.rb
@@ -150,11 +150,11 @@ describe "IO#reopen with a String" do
@io.close_on_exec = true
@io.reopen @other_name
- @io.close_on_exec?.should == true
+ @io.should.close_on_exec?
@io.close_on_exec = false
@io.reopen @other_name
- @io.close_on_exec?.should == true
+ @io.should.close_on_exec?
end
it "creates the file if it doesn't exist if the IO is opened in write mode" do
@@ -293,12 +293,12 @@ describe "IO#reopen with an IO" do
@other_io.close_on_exec = true
@io.close_on_exec = true
@io.reopen @other_io
- @io.close_on_exec?.should == true
+ @io.should.close_on_exec?
@other_io.close_on_exec = false
@io.close_on_exec = false
@io.reopen @other_io
- @io.close_on_exec?.should == true
+ @io.should.close_on_exec?
end
it "may change the class of the instance" do
diff --git a/spec/ruby/core/io/rewind_spec.rb b/spec/ruby/core/io/rewind_spec.rb
index 954d56d30c..649041afaf 100644
--- a/spec/ruby/core/io/rewind_spec.rb
+++ b/spec/ruby/core/io/rewind_spec.rb
@@ -21,7 +21,7 @@ describe "IO#rewind" do
it "positions the instance to the beginning of input and clears EOF" do
value = @io.read
@io.rewind
- @io.eof?.should == false
+ @io.should_not.eof?
value.should == @io.read
end
diff --git a/spec/ruby/core/io/seek_spec.rb b/spec/ruby/core/io/seek_spec.rb
index 7e9c308272..2fa4a73ac9 100644
--- a/spec/ruby/core/io/seek_spec.rb
+++ b/spec/ruby/core/io/seek_spec.rb
@@ -44,21 +44,21 @@ describe "IO#seek" do
it "moves the read position and clears EOF with SEEK_SET" do
value = @io.read
@io.seek(0, IO::SEEK_SET)
- @io.eof?.should == false
+ @io.should_not.eof?
value.should == @io.read
end
it "moves the read position and clears EOF with SEEK_CUR" do
value = @io.read
@io.seek(-1, IO::SEEK_CUR)
- @io.eof?.should == false
+ @io.should_not.eof?
value[-1].should == @io.read[0]
end
it "moves the read position and clears EOF with SEEK_END" do
value = @io.read
@io.seek(-1, IO::SEEK_END)
- @io.eof?.should == false
+ @io.should_not.eof?
value[-1].should == @io.read[0]
end
diff --git a/spec/ruby/core/io/set_encoding_by_bom_spec.rb b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
new file mode 100644
index 0000000000..b8e4eedcb9
--- /dev/null
+++ b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
@@ -0,0 +1,57 @@
+require_relative '../../spec_helper'
+
+describe "IO#set_encoding_by_bom" do
+ before :each do
+ @name = tmp('io_set_encoding_by_bom.txt')
+ touch(@name)
+ @io = new_io(@name, 'rb')
+ end
+
+ after :each do
+ @io.close unless @io.closed?
+ rm_r @name
+ end
+
+ ruby_version_is "2.7" do
+ it "returns the result encoding if found BOM UTF-8 sequence" do
+ File.binwrite(@name, "\u{FEFF}abc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_8
+ @io.external_encoding.should == Encoding::UTF_8
+ end
+
+ it "returns the result encoding if found BOM UTF_16LE sequence" do
+ File.binwrite(@name, "\xFF\xFEabc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ @io.external_encoding.should == Encoding::UTF_16LE
+ end
+
+ it "returns the result encoding if found BOM UTF_16BE sequence" do
+ File.binwrite(@name, "\xFE\xFFabc")
+
+ @io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ @io.external_encoding.should == Encoding::UTF_16BE
+ end
+
+ it "returns nil if found BOM sequence not provided" do
+ File.write(@name, "abc")
+
+ @io.set_encoding_by_bom.should == nil
+ end
+
+ it 'returns exception if io not in binary mode' do
+ not_binary_io = new_io(@name, 'r')
+
+ -> { not_binary_io.set_encoding_by_bom }.should raise_error(ArgumentError, 'ASCII incompatible encoding needs binmode')
+ ensure
+ not_binary_io.close
+ end
+
+ it 'returns exception if encoding already set' do
+ @io.set_encoding("utf-8")
+
+ -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding is set to UTF-8 already')
+ end
+ end
+end
diff --git a/spec/ruby/core/io/shared/each.rb b/spec/ruby/core/io/shared/each.rb
index 0b2dfa3548..91766fbe03 100644
--- a/spec/ruby/core/io/shared/each.rb
+++ b/spec/ruby/core/io/shared/each.rb
@@ -168,12 +168,12 @@ describe :io_each_default_separator, shared: true do
before :each do
@io = IOSpecs.io_fixture "lines.txt"
ScratchPad.record []
- @sep, $/ = $/, " "
+ suppress_warning {@sep, $/ = $/, " "}
end
after :each do
@io.close if @io
- $/ = @sep
+ suppress_warning {$/ = @sep}
end
it "uses $/ as the default line separator" do
diff --git a/spec/ruby/core/io/shared/new.rb b/spec/ruby/core/io/shared/new.rb
index a7b4fc1cbe..f2a0970a40 100644
--- a/spec/ruby/core/io/shared/new.rb
+++ b/spec/ruby/core/io/shared/new.rb
@@ -18,7 +18,7 @@ describe :io_new, shared: true do
rm_r @name
end
- it "creates an IO instance from a Fixnum argument" do
+ it "creates an IO instance from an Integer argument" do
@io = IO.send(@method, @fd, "w")
@io.should be_an_instance_of(IO)
end
@@ -55,7 +55,7 @@ describe :io_new, shared: true do
end
end
- it "calls #to_int on an object to convert to a Fixnum" do
+ it "calls #to_int on an object to convert to an Integer" do
obj = mock("file descriptor")
obj.should_receive(:to_int).and_return(@fd)
@io = IO.send(@method, obj, "w")
@@ -148,22 +148,22 @@ describe :io_new, shared: true do
it "sets binmode from mode string" do
@io = IO.send(@method, @fd, 'wb')
- @io.binmode?.should == true
+ @io.should.binmode?
end
it "does not set binmode without being asked" do
@io = IO.send(@method, @fd, 'w')
- @io.binmode?.should == false
+ @io.should_not.binmode?
end
it "sets binmode from :binmode option" do
@io = IO.send(@method, @fd, 'w', binmode: true)
- @io.binmode?.should == true
+ @io.should.binmode?
end
it "does not set binmode from false :binmode" do
@io = IO.send(@method, @fd, 'w', binmode: false)
- @io.binmode?.should == false
+ @io.should_not.binmode?
end
it "sets external encoding to binary with binmode in mode string" do
@@ -197,11 +197,21 @@ describe :io_new, shared: true do
@io.internal_encoding.to_s.should == 'IBM866'
end
- it "accepts nil options" do
- @io = suppress_keyword_warning do
- IO.send(@method, @fd, 'w', nil)
+ ruby_version_is ''...'3.0' do
+ it "accepts nil options" do
+ @io = suppress_keyword_warning do
+ IO.send(@method, @fd, 'w', nil)
+ end
+ @io.write("foo").should == 3
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "raises ArgumentError for nil options" do
+ -> {
+ IO.send(@method, @fd, 'w', nil)
+ }.should raise_error(ArgumentError)
end
- @io.write("foo").should == 3
end
it "coerces mode with #to_str" do
@@ -260,13 +270,13 @@ describe :io_new, shared: true do
it "accepts an :autoclose option" do
@io = IO.send(@method, @fd, 'w', autoclose: false)
- @io.autoclose?.should == false
+ @io.should_not.autoclose?
@io.autoclose = true
end
it "accepts any truthy option :autoclose" do
@io = IO.send(@method, @fd, 'w', autoclose: 42)
- @io.autoclose?.should == true
+ @io.should.autoclose?
end
end
@@ -372,11 +382,21 @@ describe :io_new_errors, shared: true do
}.should raise_error(ArgumentError)
end
- it "raises TypeError if passed a hash for mode and nil for options" do
- -> {
- suppress_keyword_warning do
+ ruby_version_is ''...'3.0' do
+ it "raises TypeError if passed a hash for mode and nil for options" do
+ -> {
+ suppress_keyword_warning do
+ @io = IO.send(@method, @fd, {mode: 'w'}, nil)
+ end
+ }.should raise_error(TypeError)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "raises ArgumentError if passed a hash for mode and nil for options" do
+ -> {
@io = IO.send(@method, @fd, {mode: 'w'}, nil)
- end
- }.should raise_error(TypeError)
+ }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/io/shared/pos.rb b/spec/ruby/core/io/shared/pos.rb
index fb6d8087bc..d83a6c6692 100644
--- a/spec/ruby/core/io/shared/pos.rb
+++ b/spec/ruby/core/io/shared/pos.rb
@@ -27,7 +27,7 @@ describe :io_pos, shared: true do
io.read 1
io.read 1
io.send(@method)
- io.eof?.should == false
+ io.should_not.eof?
end
end
end
@@ -60,7 +60,7 @@ describe :io_set_pos, shared: true do
end
end
- it "does not accept Bignums that don't fit in a C long" do
+ it "does not accept Integers that don't fit in a C long" do
File.open @fname do |io|
-> { io.send @method, 2**128 }.should raise_error(RangeError)
end
diff --git a/spec/ruby/core/io/shared/readlines.rb b/spec/ruby/core/io/shared/readlines.rb
index de803f42e5..8e4a73bb98 100644
--- a/spec/ruby/core/io/shared/readlines.rb
+++ b/spec/ruby/core/io/shared/readlines.rb
@@ -54,22 +54,22 @@ describe :io_readlines_options_19, shared: true do
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator
end
- describe "when the object is a Fixnum" do
+ describe "when the object is an Integer" do
before :each do
@sep = $/
end
after :each do
- $/ = @sep
+ suppress_warning {$/ = @sep}
end
it "defaults to $/ as the separator" do
- $/ = " "
+ suppress_warning {$/ = " "}
result = IO.send(@method, @name, 10, &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit
end
- it "uses the object as a limit if it is a Fixnum" do
+ it "uses the object as a limit if it is an Integer" do
result = IO.send(@method, @name, 10, &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_limit
end
@@ -96,7 +96,7 @@ describe :io_readlines_options_19, shared: true do
end
describe "when passed name, object, object" do
- describe "when the first object is a Fixnum" do
+ describe "when the first object is an Integer" do
it "uses the second object as an options Hash" do
-> do
IO.send(@method, @filename, 10, mode: "w", &@object)
@@ -113,7 +113,7 @@ describe :io_readlines_options_19, shared: true do
end
describe "when the first object is a String" do
- it "uses the second object as a limit if it is a Fixnum" do
+ it "uses the second object as a limit if it is an Integer" do
result = IO.send(@method, @name, " ", 10, &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit
end
@@ -140,7 +140,7 @@ describe :io_readlines_options_19, shared: true do
end
end
- describe "when the first object is not a String or Fixnum" do
+ describe "when the first object is not a String or Integer" do
it "calls #to_str to convert the object to a String" do
sep = mock("io readlines separator")
sep.should_receive(:to_str).at_least(1).and_return(" ")
@@ -148,7 +148,7 @@ describe :io_readlines_options_19, shared: true do
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit
end
- it "uses the second object as a limit if it is a Fixnum" do
+ it "uses the second object as a limit if it is an Integer" do
result = IO.send(@method, @name, " ", 10, mode: "r", &@object)
(result ? result : ScratchPad.recorded).should == IOSpecs.lines_space_separator_limit
end
diff --git a/spec/ruby/core/io/sysopen_spec.rb b/spec/ruby/core/io/sysopen_spec.rb
index 4607d13687..7ad379df3a 100644
--- a/spec/ruby/core/io/sysopen_spec.rb
+++ b/spec/ruby/core/io/sysopen_spec.rb
@@ -13,7 +13,7 @@ describe "IO.sysopen" do
it "returns the file descriptor for a given path" do
@fd = IO.sysopen(@filename, "w")
- @fd.should be_kind_of(Fixnum)
+ @fd.should be_kind_of(Integer)
@fd.should_not equal(0)
end
@@ -21,7 +21,7 @@ describe "IO.sysopen" do
platform_is_not :windows do
it "works on directories" do
@fd = IO.sysopen(tmp("")) # /tmp
- @fd.should be_kind_of(Fixnum)
+ @fd.should be_kind_of(Integer)
@fd.should_not equal(0)
end
end
diff --git a/spec/ruby/core/io/ungetbyte_spec.rb b/spec/ruby/core/io/ungetbyte_spec.rb
index 1971dee534..1e2ec77e1f 100644
--- a/spec/ruby/core/io/ungetbyte_spec.rb
+++ b/spec/ruby/core/io/ungetbyte_spec.rb
@@ -37,12 +37,12 @@ describe "IO#ungetbyte" do
end
ruby_version_is ''...'2.6' do
- it "puts back one byte for a Fixnum argument..." do
+ it "puts back one byte for an Integer argument..." do
@io.ungetbyte(4095).should be_nil
@io.getbyte.should == 255
end
- it "... but not for Bignum argument (eh?)" do
+ it "... but not for Integer argument (eh?)" do
-> {
@io.ungetbyte(0x4f7574206f6620636861722072616e6765)
}.should raise_error(TypeError)
@@ -66,6 +66,10 @@ describe "IO#ungetbyte" do
end
end
+ it "raises IOError on stream not opened for reading" do
+ -> { STDOUT.ungetbyte(42) }.should raise_error(IOError, "not opened for reading")
+ end
+
it "raises an IOError if the IO is closed" do
@io.close
-> { @io.ungetbyte(42) }.should raise_error(IOError)
diff --git a/spec/ruby/core/io/ungetc_spec.rb b/spec/ruby/core/io/ungetc_spec.rb
index 34d4caf745..a05d80ee9c 100644
--- a/spec/ruby/core/io/ungetc_spec.rb
+++ b/spec/ruby/core/io/ungetc_spec.rb
@@ -74,10 +74,10 @@ describe "IO#ungetc" do
touch(@empty)
File.open(@empty) { |empty|
- empty.eof?.should == true
+ empty.should.eof?
empty.getc.should == nil
empty.ungetc(100)
- empty.eof?.should == false
+ empty.should_not.eof?
}
end
@@ -103,10 +103,19 @@ describe "IO#ungetc" do
-> { @io.sysread(1) }.should raise_error(IOError)
end
- it "does not affect the stream and returns nil when passed nil" do
- @io.getc.should == ?V
- @io.ungetc(nil)
- @io.getc.should == ?o
+ ruby_version_is "0"..."3.0" do
+ it "does not affect the stream and returns nil when passed nil" do
+ @io.getc.should == ?V
+ @io.ungetc(nil)
+ @io.getc.should == ?o
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "raises TypeError if passed nil" do
+ @io.getc.should == ?V
+ proc{@io.ungetc(nil)}.should raise_error(TypeError)
+ end
end
it "puts one or more characters back in the stream" do
@@ -127,6 +136,10 @@ describe "IO#ungetc" do
@io.ungetc(100).should be_nil
end
+ it "raises IOError on stream not opened for reading" do
+ -> { STDOUT.ungetc(100) }.should raise_error(IOError, "not opened for reading")
+ end
+
it "raises IOError on closed stream" do
@io.getc
@io.close
diff --git a/spec/ruby/core/io/write_nonblock_spec.rb b/spec/ruby/core/io/write_nonblock_spec.rb
index 5474e5c6ce..a8b9ce0a36 100644
--- a/spec/ruby/core/io/write_nonblock_spec.rb
+++ b/spec/ruby/core/io/write_nonblock_spec.rb
@@ -79,7 +79,7 @@ describe 'IO#write_nonblock' do
it 'sets the IO in nonblock mode' do
require 'io/nonblock'
@write.write_nonblock('a')
- @write.nonblock?.should == true
+ @write.should.nonblock?
end
end
end
diff --git a/spec/ruby/core/io/write_spec.rb b/spec/ruby/core/io/write_spec.rb
index b28b582019..9c9b8b254b 100644
--- a/spec/ruby/core/io/write_spec.rb
+++ b/spec/ruby/core/io/write_spec.rb
@@ -126,14 +126,12 @@ end
describe "IO#write" do
it_behaves_like :io_write, :write
- ruby_version_is "2.5" do
- it "accepts multiple arguments" do
- IO.pipe do |r, w|
- w.write("foo", "bar")
- w.close
+ it "accepts multiple arguments" do
+ IO.pipe do |r, w|
+ w.write("foo", "bar")
+ w.close
- r.read.should == "foobar"
- end
+ r.read.should == "foobar"
end
end
end
diff --git a/spec/ruby/core/kernel/Float_spec.rb b/spec/ruby/core/kernel/Float_spec.rb
index 6580c38137..ce224cada9 100644
--- a/spec/ruby/core/kernel/Float_spec.rb
+++ b/spec/ruby/core/kernel/Float_spec.rb
@@ -9,7 +9,7 @@ describe :kernel_float, shared: true do
float2.should equal float
end
- it "returns a Float for Fixnums" do
+ it "returns a Float for Integers" do
@object.send(:Float, 1).should == 1.0
end
@@ -17,7 +17,7 @@ describe :kernel_float, shared: true do
@object.send(:Float, Complex(1)).should == 1.0
end
- it "returns a Float for Bignums" do
+ it "returns a Float for Integers" do
@object.send(:Float, 1000000000000).should == 1000000000000.0
end
@@ -54,6 +54,12 @@ describe :kernel_float, shared: true do
-> { @object.send(:Float, "float") }.should raise_error(ArgumentError)
end
+ it "raises an ArgumentError for a String with string in error message" do
+ -> { @object.send(:Float, "foo") }.should raise_error(ArgumentError) { |e|
+ e.message.should == 'invalid value for Float(): "foo"'
+ }
+ end
+
it "raises an ArgumentError if there are two decimal points in the String" do
-> { @object.send(:Float, "10.0.0") }.should raise_error(ArgumentError)
end
diff --git a/spec/ruby/core/kernel/Integer_spec.rb b/spec/ruby/core/kernel/Integer_spec.rb
index 59b41d37e6..674c7dd185 100644
--- a/spec/ruby/core/kernel/Integer_spec.rb
+++ b/spec/ruby/core/kernel/Integer_spec.rb
@@ -2,11 +2,11 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe :kernel_integer, shared: true do
- it "returns a Bignum for a Bignum" do
+ it "returns an Integer for an Integer" do
Integer(2e100).should == 2e100
end
- it "returns a Fixnum for a Fixnum" do
+ it "returns an Integer for an Integer" do
Integer(100).should == 100
end
@@ -39,9 +39,9 @@ describe :kernel_integer, shared: true do
-> { Integer(nil) }.should raise_error(TypeError)
end
- it "returns a Fixnum or Bignum object" do
- Integer(2).should be_an_instance_of(Fixnum)
- Integer(9**99).should be_an_instance_of(Bignum)
+ it "returns an Integer or Integer object" do
+ Integer(2).should be_an_instance_of(Integer)
+ Integer(9**99).should be_an_instance_of(Integer)
end
it "truncates Floats" do
@@ -54,14 +54,14 @@ describe :kernel_integer, shared: true do
Integer(3.quo(2)).should == 1
end
- it "returns the value of to_int if the result is a Fixnum" do
+ it "returns the value of to_int if the result is an Integer" do
obj = mock("object")
obj.should_receive(:to_int).and_return(1)
obj.should_not_receive(:to_i)
Integer(obj).should == 1
end
- it "returns the value of to_int if the result is a Bignum" do
+ it "returns the value of to_int if the result is an Integer" do
obj = mock("object")
obj.should_receive(:to_int).and_return(2 * 10**100)
obj.should_not_receive(:to_i)
diff --git a/spec/ruby/core/kernel/__dir___spec.rb b/spec/ruby/core/kernel/__dir___spec.rb
index 3c34277277..324792a408 100644
--- a/spec/ruby/core/kernel/__dir___spec.rb
+++ b/spec/ruby/core/kernel/__dir___spec.rb
@@ -5,6 +5,13 @@ describe "Kernel#__dir__" do
__dir__.should == File.realpath(File.dirname(__FILE__))
end
+ it "returns the expanded path of the directory when used in the main script" do
+ fixtures_dir = File.dirname(fixture(__FILE__, '__dir__.rb'))
+ Dir.chdir(fixtures_dir) do
+ ruby_exe("__dir__.rb").should == "__dir__.rb\n#{fixtures_dir}\n"
+ end
+ end
+
context "when used in eval with a given filename" do
it "returns File.dirname(filename)" do
eval("__dir__", nil, "foo.rb").should == "."
@@ -12,9 +19,19 @@ describe "Kernel#__dir__" do
end
end
- context "when used in eval with top level binding" do
- it "returns the real name of the directory containing the currently-executing file" do
- eval("__dir__", binding).should == File.realpath(File.dirname(__FILE__))
+ ruby_version_is ""..."3.0" do
+ context "when used in eval with top level binding" do
+ it "returns the real name of the directory containing the currently-executing file" do
+ eval("__dir__", binding).should == File.realpath(File.dirname(__FILE__))
+ end
+ end
+ end
+
+ ruby_version_is "3.0" do
+ context "when used in eval with top level binding" do
+ it "returns nil" do
+ eval("__dir__", binding).should == nil
+ end
end
end
end
diff --git a/spec/ruby/core/kernel/at_exit_spec.rb b/spec/ruby/core/kernel/at_exit_spec.rb
index 21149f965b..7bdb5391fe 100644
--- a/spec/ruby/core/kernel/at_exit_spec.rb
+++ b/spec/ruby/core/kernel/at_exit_spec.rb
@@ -23,7 +23,7 @@ describe "Kernel.at_exit" do
it "gives access to the last raised exception" do
code = <<-EOC
at_exit do
- puts "The exception matches: \#{$! == $exception}"
+ puts "The exception matches: \#{$! == $exception} (message=\#{$!.message})"
end
begin
@@ -33,10 +33,35 @@ describe "Kernel.at_exit" do
end
EOC
- result = ruby_exe(code, args: "2>&1", escape: true)
- result.should =~ /The exception matches: true/
+ result = ruby_exe(code, args: "2>&1")
+ result.lines.should.include?("The exception matches: true (message=foo)\n")
end
+ it "both exceptions in at_exit and in the main script are printed" do
+ result = ruby_exe('at_exit { raise "at_exit_error" }; raise "main_script_error"', args: "2>&1")
+ result.should.include?('at_exit_error (RuntimeError)')
+ result.should.include?('main_script_error (RuntimeError)')
+ end
+
+ it "decides the exit status if both at_exit and the main script raise SystemExit" do
+ ruby_exe('at_exit { exit 43 }; exit 42', args: "2>&1")
+ $?.exitstatus.should == 43
+ end
+
+ it "runs all at_exit even if some raise exceptions" do
+ code = 'at_exit { STDERR.puts "last" }; at_exit { exit 43 }; at_exit { STDERR.puts "first" }; exit 42'
+ result = ruby_exe(code, args: "2>&1")
+ result.should == "first\nlast\n"
+ $?.exitstatus.should == 43
+ end
+
+ it "runs at_exit handlers even if the main script fails to parse" do
+ script = fixture(__FILE__, "at_exit.rb")
+ result = ruby_exe('{', options: "-r#{script}", args: "2>&1")
+ $?.should_not.success?
+ result.should.include?("at_exit ran\n")
+ result.should.include?("syntax error")
+ end
end
describe "Kernel#at_exit" do
diff --git a/spec/ruby/core/kernel/autoload_spec.rb b/spec/ruby/core/kernel/autoload_spec.rb
index 68732a69ef..8d56021fa8 100644
--- a/spec/ruby/core/kernel/autoload_spec.rb
+++ b/spec/ruby/core/kernel/autoload_spec.rb
@@ -57,8 +57,8 @@ describe "Kernel#autoload" do
end
describe "when Object is frozen" do
- it "raises a #{frozen_error_class} before defining the constant" do
- ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "#{frozen_error_class} - nil"
+ it "raises a FrozenError before defining the constant" do
+ ruby_exe(fixture(__FILE__, "autoload_frozen.rb")).should == "FrozenError - nil"
end
end
diff --git a/spec/ruby/core/kernel/backtick_spec.rb b/spec/ruby/core/kernel/backtick_spec.rb
index 5ab0fb0eea..834d5636c1 100644
--- a/spec/ruby/core/kernel/backtick_spec.rb
+++ b/spec/ruby/core/kernel/backtick_spec.rb
@@ -36,20 +36,24 @@ describe "Kernel#`" do
end
platform_is_not :windows do
+ it "handles invalid UTF-8 bytes in command" do
+ `echo "testing\xC2 a non UTF-8 string"`.b.should == "testing\xC2 a non UTF-8 string\n".b
+ end
+
it "sets $? to the exit status of the executed sub-process" do
ip = 'world'
`echo disc #{ip}`
$?.should be_kind_of(Process::Status)
- $?.stopped?.should == false
- $?.exited?.should == true
+ $?.should_not.stopped?
+ $?.should.exited?
$?.exitstatus.should == 0
- $?.success?.should == true
+ $?.should.success?
`echo disc #{ip}; exit 99`
$?.should be_kind_of(Process::Status)
- $?.stopped?.should == false
- $?.exited?.should == true
+ $?.should_not.stopped?
+ $?.should.exited?
$?.exitstatus.should == 99
- $?.success?.should == false
+ $?.should_not.success?
end
end
@@ -58,16 +62,16 @@ describe "Kernel#`" do
ip = 'world'
`echo disc #{ip}`
$?.should be_kind_of(Process::Status)
- $?.stopped?.should == false
- $?.exited?.should == true
+ $?.should_not.stopped?
+ $?.should.exited?
$?.exitstatus.should == 0
- $?.success?.should == true
+ $?.should.success?
`echo disc #{ip}& exit 99`
$?.should be_kind_of(Process::Status)
- $?.stopped?.should == false
- $?.exited?.should == true
+ $?.should_not.stopped?
+ $?.should.exited?
$?.exitstatus.should == 99
- $?.success?.should == false
+ $?.should_not.success?
end
end
end
diff --git a/spec/ruby/core/kernel/caller_locations_spec.rb b/spec/ruby/core/kernel/caller_locations_spec.rb
index 4de6c2ffd6..8050b5b3ab 100644
--- a/spec/ruby/core/kernel/caller_locations_spec.rb
+++ b/spec/ruby/core/kernel/caller_locations_spec.rb
@@ -7,7 +7,7 @@ describe 'Kernel#caller_locations' do
end
it 'returns an Array of caller locations' do
- KernelSpecs::CallerLocationsTest.locations.empty?.should == false
+ KernelSpecs::CallerLocationsTest.locations.should_not.empty?
end
it 'returns an Array of caller locations using a custom offset' do
@@ -22,6 +22,38 @@ describe 'Kernel#caller_locations' do
locations.length.should == 1
end
+ it "can be called with a range" do
+ locations1 = caller_locations(0)
+ locations2 = caller_locations(2..4)
+ locations1[2..4].map(&:to_s).should == locations2.map(&:to_s)
+ end
+
+ ruby_version_is "2.6" do
+ it "works with endless ranges" do
+ locations1 = caller_locations(0)
+ locations2 = caller_locations(eval("(2..)"))
+ locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
+ end
+ end
+
+ it "can be called with a range whose end is negative" do
+ locations1 = caller_locations(0)
+ locations2 = caller_locations(2..-1)
+ locations3 = caller_locations(2..-2)
+ locations1[2..-1].map(&:to_s).should == locations2.map(&:to_s)
+ locations1[2..-2].map(&:to_s).should == locations3.map(&:to_s)
+ end
+
+ it "must return nil if omitting more locations than available" do
+ caller_locations(100).should == nil
+ caller_locations(100..-1).should == nil
+ end
+
+ it "must return [] if omitting exactly the number of locations available" do
+ omit = caller_locations(0).length
+ caller_locations(omit).should == []
+ end
+
it 'returns the locations as Thread::Backtrace::Location instances' do
locations = KernelSpecs::CallerLocationsTest.locations
@@ -29,4 +61,20 @@ describe 'Kernel#caller_locations' do
location.kind_of?(Thread::Backtrace::Location).should == true
end
end
+
+ it "must return the same locations when called with 1..-1 and when called with no arguments" do
+ caller_locations.map(&:to_s).should == caller_locations(1..-1).map(&:to_s)
+ end
+
+ guard -> { Kernel.instance_method(:tap).source_location } do
+ it "includes core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
+
+ loc = nil
+ tap { loc = caller_locations(1, 1)[0] }
+ loc.label.should == "tap"
+ loc.path.should.start_with? "<internal:"
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/caller_spec.rb b/spec/ruby/core/kernel/caller_spec.rb
index 8469319c94..06e9ea6fc8 100644
--- a/spec/ruby/core/kernel/caller_spec.rb
+++ b/spec/ruby/core/kernel/caller_spec.rb
@@ -7,7 +7,7 @@ describe 'Kernel#caller' do
end
it 'returns an Array of caller locations' do
- KernelSpecs::CallerTest.locations.empty?.should == false
+ KernelSpecs::CallerTest.locations.should_not.empty?
end
it 'returns an Array of caller locations using a custom offset' do
@@ -43,4 +43,24 @@ describe 'Kernel#caller' do
"#{path}:2:in `block in <main>'\n"
]
end
+
+ ruby_version_is "2.6" do
+ it "works with endless ranges" do
+ locations1 = KernelSpecs::CallerTest.locations(0)
+ locations2 = KernelSpecs::CallerTest.locations(eval("(2..)"))
+ locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
+ end
+ 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:')
+
+ loc = nil
+ tap { loc = caller(1, 1)[0] }
+ loc.should.end_with? "in `tap'"
+ loc.should.start_with? "<internal:"
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/class_spec.rb b/spec/ruby/core/kernel/class_spec.rb
index 4d3b4e549b..2725bde19b 100644
--- a/spec/ruby/core/kernel/class_spec.rb
+++ b/spec/ruby/core/kernel/class_spec.rb
@@ -5,7 +5,7 @@ describe "Kernel#class" do
it "returns the class of the object" do
Object.new.class.should equal(Object)
- 1.class.should equal(Fixnum)
+ 1.class.should equal(Integer)
3.14.class.should equal(Float)
:hello.class.should equal(Symbol)
"hello".class.should equal(String)
diff --git a/spec/ruby/core/kernel/clone_spec.rb b/spec/ruby/core/kernel/clone_spec.rb
index f20ea618b5..c18af4a490 100644
--- a/spec/ruby/core/kernel/clone_spec.rb
+++ b/spec/ruby/core/kernel/clone_spec.rb
@@ -33,16 +33,22 @@ describe "Kernel#clone" do
@obj.freeze
o3 = @obj.clone
- o2.frozen?.should == false
- o3.frozen?.should == true
+ o2.should_not.frozen?
+ o3.should.frozen?
end
- it 'takes an option to copy freeze state or not' do
- @obj.clone(freeze: true).frozen?.should == false
- @obj.clone(freeze: false).frozen?.should == false
+ ruby_version_is '3.0' do
+ it 'takes an freeze: true option to frozen copy' do
+ @obj.clone(freeze: true).should.frozen?
+ @obj.freeze
+ @obj.clone(freeze: true).should.frozen?
+ end
+ end
+
+ it 'takes an freeze: false option to not return frozen copy' do
+ @obj.clone(freeze: false).should_not.frozen?
@obj.freeze
- @obj.clone(freeze: true).frozen?.should == true
- @obj.clone(freeze: false).frozen?.should == false
+ @obj.clone(freeze: false).should_not.frozen?
end
it "copies instance variables" do
diff --git a/spec/ruby/core/kernel/dup_spec.rb b/spec/ruby/core/kernel/dup_spec.rb
index fe0a269d69..70198abdb7 100644
--- a/spec/ruby/core/kernel/dup_spec.rb
+++ b/spec/ruby/core/kernel/dup_spec.rb
@@ -32,7 +32,7 @@ describe "Kernel#dup" do
@obj.freeze
dup = @obj.dup
- dup.frozen?.should == false
+ dup.should_not.frozen?
end
it "copies instance variables" do
diff --git a/spec/ruby/core/kernel/eval_spec.rb b/spec/ruby/core/kernel/eval_spec.rb
index 340ba23f2a..c53e51e430 100644
--- a/spec/ruby/core/kernel/eval_spec.rb
+++ b/spec/ruby/core/kernel/eval_spec.rb
@@ -159,13 +159,27 @@ describe "Kernel#eval" do
end
end
- it "uses the filename of the binding if none is provided" do
- eval("__FILE__").should == "(eval)"
- suppress_warning {eval("__FILE__", binding)}.should == __FILE__
- eval("__FILE__", binding, "success").should == "success"
- suppress_warning {eval("eval '__FILE__', binding")}.should == "(eval)"
- suppress_warning {eval("eval '__FILE__', binding", binding)}.should == __FILE__
- suppress_warning {eval("eval '__FILE__', binding", binding, 'success')}.should == 'success'
+ ruby_version_is ""..."3.0" do
+ it "uses the filename of the binding if none is provided" do
+ eval("__FILE__").should == "(eval)"
+ suppress_warning {eval("__FILE__", binding)}.should == __FILE__
+ eval("__FILE__", binding, "success").should == "success"
+ suppress_warning {eval("eval '__FILE__', binding")}.should == "(eval)"
+ suppress_warning {eval("eval '__FILE__', binding", binding)}.should == __FILE__
+ suppress_warning {eval("eval '__FILE__', binding", binding, 'success')}.should == 'success'
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "uses (eval) filename if none is provided" do
+ eval("__FILE__").should == "(eval)"
+ eval("__FILE__", binding).should == "(eval)"
+ eval("__FILE__", binding, "success").should == "success"
+ eval("eval '__FILE__', binding").should == "(eval)"
+ eval("eval '__FILE__', binding", binding).should == "(eval)"
+ eval("eval '__FILE__', binding", binding, 'success').should == '(eval)'
+ eval("eval '__FILE__', binding, 'success'", binding).should == 'success'
+ end
end
# Found via Rubinius bug github:#149
@@ -359,4 +373,44 @@ CODE
EvalSpecs.send :remove_const, :Vπstring_not_frozen
end
end
+
+ it "activates refinements from the eval scope" do
+ refinery = Module.new do
+ refine EvalSpecs::A do
+ def foo
+ "bar"
+ end
+ end
+ end
+
+ result = nil
+
+ Module.new do
+ using refinery
+
+ result = eval "EvalSpecs::A.new.foo"
+ end
+
+ result.should == "bar"
+ end
+
+ it "activates refinements from the binding" do
+ refinery = Module.new do
+ refine EvalSpecs::A do
+ def foo
+ "bar"
+ end
+ end
+ end
+
+ b = nil
+ m = Module.new do
+ using refinery
+ b = binding
+ end
+
+ result = eval "EvalSpecs::A.new.foo", b
+
+ result.should == "bar"
+ end
end
diff --git a/spec/ruby/core/kernel/extend_spec.rb b/spec/ruby/core/kernel/extend_spec.rb
index 9f98b3681f..47b22f3a18 100644
--- a/spec/ruby/core/kernel/extend_spec.rb
+++ b/spec/ruby/core/kernel/extend_spec.rb
@@ -72,8 +72,8 @@ describe "Kernel#extend" do
-> { @frozen.extend }.should raise_error(ArgumentError)
end
- it "raises a #{frozen_error_class}" do
- -> { @frozen.extend @module }.should raise_error(frozen_error_class)
+ it "raises a FrozenError" do
+ -> { @frozen.extend @module }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/kernel/fixtures/__dir__.rb b/spec/ruby/core/kernel/fixtures/__dir__.rb
new file mode 100644
index 0000000000..bf9a15e3c8
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/__dir__.rb
@@ -0,0 +1,2 @@
+puts __FILE__
+puts __dir__
diff --git a/spec/ruby/core/kernel/fixtures/at_exit.rb b/spec/ruby/core/kernel/fixtures/at_exit.rb
new file mode 100644
index 0000000000..9c11a7ad6c
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/at_exit.rb
@@ -0,0 +1,3 @@
+at_exit do
+ STDERR.puts "at_exit ran"
+end
diff --git a/spec/ruby/core/kernel/fixtures/classes.rb b/spec/ruby/core/kernel/fixtures/classes.rb
index 2f2bbf1b23..8702c925c8 100644
--- a/spec/ruby/core/kernel/fixtures/classes.rb
+++ b/spec/ruby/core/kernel/fixtures/classes.rb
@@ -49,7 +49,7 @@ module KernelSpecs
def self.chomp(str, method, sep="\n")
code = "$_ = #{str.inspect}; $/ = #{sep.inspect}; #{method}; print $_"
- IO.popen([*ruby_exe, "-n", "-e", code], "r+") do |io|
+ IO.popen([*ruby_exe, "-W0", "-n", "-e", code], "r+") do |io|
io.puts
io.close_write
io.read
@@ -350,7 +350,7 @@ module KernelSpecs
module Ampersand
def lambda(&block)
- super(&block)
+ suppress_warning {super(&block)}
end
end
diff --git a/spec/ruby/core/kernel/fixtures/warn_core_method.rb b/spec/ruby/core/kernel/fixtures/warn_core_method.rb
new file mode 100644
index 0000000000..f5dee6b668
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/warn_core_method.rb
@@ -0,0 +1,14 @@
+raise 'should be run without RubyGems' if defined?(Gem)
+
+def deprecated(n=1)
+ # puts nil, caller(0), nil
+ warn "use X instead", uplevel: n
+end
+
+1.times do # to test with a non-empty stack above the reported locations
+ deprecated
+ tap(&:deprecated)
+ tap { deprecated(2) }
+ # eval sources with a <internal: file are also ignored
+ eval "tap(&:deprecated)", nil, "<internal:should-be-skipped-by-warn-uplevel>"
+end
diff --git a/spec/ruby/core/kernel/fixtures/warn_require.rb b/spec/ruby/core/kernel/fixtures/warn_require.rb
new file mode 100644
index 0000000000..c4b0733233
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/warn_require.rb
@@ -0,0 +1 @@
+warn 'warn-require-warning', uplevel: 1
diff --git a/spec/ruby/core/kernel/fixtures/warn_require_caller.rb b/spec/ruby/core/kernel/fixtures/warn_require_caller.rb
new file mode 100644
index 0000000000..35a0f969f9
--- /dev/null
+++ b/spec/ruby/core/kernel/fixtures/warn_require_caller.rb
@@ -0,0 +1,2 @@
+# Use a different line than just 1
+require "#{__dir__}/warn_require"
diff --git a/spec/ruby/core/kernel/freeze_spec.rb b/spec/ruby/core/kernel/freeze_spec.rb
index 214b619f9f..fa32d321cf 100644
--- a/spec/ruby/core/kernel/freeze_spec.rb
+++ b/spec/ruby/core/kernel/freeze_spec.rb
@@ -51,21 +51,19 @@ describe "Kernel#freeze" do
end
end
- ruby_version_is "2.5" do
- describe "on a Complex" do
- it "has no effect since it is already frozen" do
- c = Complex(1.3, 3.1)
- c.frozen?.should be_true
- c.freeze
- end
+ describe "on a Complex" do
+ it "has no effect since it is already frozen" do
+ c = Complex(1.3, 3.1)
+ c.frozen?.should be_true
+ c.freeze
end
+ end
- describe "on a Rational" do
- it "has no effect since it is already frozen" do
- r = Rational(1, 3)
- r.frozen?.should be_true
- r.freeze
- end
+ describe "on a Rational" do
+ it "has no effect since it is already frozen" do
+ r = Rational(1, 3)
+ r.frozen?.should be_true
+ r.freeze
end
end
@@ -82,4 +80,12 @@ describe "Kernel#freeze" do
o.freeze
-> {o.instance_variable_set(:@foo, 1)}.should raise_error(RuntimeError)
end
+
+ it "freezes an object's singleton class" do
+ o = Object.new
+ c = o.singleton_class
+ c.frozen?.should == false
+ o.freeze
+ c.frozen?.should == true
+ end
end
diff --git a/spec/ruby/core/kernel/frozen_spec.rb b/spec/ruby/core/kernel/frozen_spec.rb
index 5887ed75ba..a4cec4263d 100644
--- a/spec/ruby/core/kernel/frozen_spec.rb
+++ b/spec/ruby/core/kernel/frozen_spec.rb
@@ -6,8 +6,8 @@ describe "Kernel#frozen?" do
o = mock('o')
p = mock('p')
p.freeze
- o.frozen?.should == false
- p.frozen?.should == true
+ o.should_not.frozen?
+ p.should.frozen?
end
describe "on true, false and nil" do
@@ -50,29 +50,27 @@ describe "Kernel#frozen?" do
end
end
- ruby_version_is "2.5" do
- describe "on a Complex" do
- it "returns true" do
- c = Complex(1.3, 3.1)
- c.frozen?.should be_true
- end
+ describe "on a Complex" do
+ it "returns true" do
+ c = Complex(1.3, 3.1)
+ c.frozen?.should be_true
+ end
- it "literal returns true" do
- c = eval "1.3i"
- c.frozen?.should be_true
- end
+ it "literal returns true" do
+ c = eval "1.3i"
+ c.frozen?.should be_true
end
+ end
- describe "on a Rational" do
- it "returns true" do
- r = Rational(1, 3)
- r.frozen?.should be_true
- end
+ describe "on a Rational" do
+ it "returns true" do
+ r = Rational(1, 3)
+ r.frozen?.should be_true
+ end
- it "literal returns true" do
- r = eval "1/3r"
- r.frozen?.should be_true
- end
+ it "literal returns true" do
+ r = eval "1/3r"
+ r.frozen?.should be_true
end
end
end
diff --git a/spec/ruby/core/kernel/initialize_copy_spec.rb b/spec/ruby/core/kernel/initialize_copy_spec.rb
new file mode 100644
index 0000000000..fe08d184ad
--- /dev/null
+++ b/spec/ruby/core/kernel/initialize_copy_spec.rb
@@ -0,0 +1,29 @@
+require_relative '../../spec_helper'
+
+describe "Kernel#initialize_copy" do
+ it "does nothing if the argument is the same as the receiver" do
+ obj = Object.new
+ obj.send(:initialize_copy, obj).should.equal?(obj)
+ obj.freeze
+ obj.send(:initialize_copy, obj).should.equal?(obj)
+ 1.send(:initialize_copy, 1).should.equal?(1)
+ end
+
+ it "raises FrozenError if the receiver is frozen" do
+ -> { Object.new.freeze.send(:initialize_copy, Object.new) }.should raise_error(FrozenError)
+ -> { 1.send(:initialize_copy, Object.new) }.should raise_error(FrozenError)
+ end
+
+ it "raises TypeError if the objects are of different class" do
+ klass = Class.new
+ sub = Class.new(klass)
+ a = klass.new
+ b = sub.new
+ message = 'initialize_copy should take same class object'
+ -> { a.send(:initialize_copy, b) }.should raise_error(TypeError, message)
+ -> { b.send(:initialize_copy, a) }.should raise_error(TypeError, message)
+
+ -> { a.send(:initialize_copy, 1) }.should raise_error(TypeError, message)
+ -> { a.send(:initialize_copy, 1.0) }.should raise_error(TypeError, message)
+ end
+end
diff --git a/spec/ruby/core/kernel/instance_of_spec.rb b/spec/ruby/core/kernel/instance_of_spec.rb
index 40e856b0d9..d1170d5047 100644
--- a/spec/ruby/core/kernel/instance_of_spec.rb
+++ b/spec/ruby/core/kernel/instance_of_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-describe Kernel, "#instance_of?" do
+describe "Kernel#instance_of?" do
before :each do
@o = KernelSpecs::InstanceClass.new
end
diff --git a/spec/ruby/core/kernel/instance_variable_get_spec.rb b/spec/ruby/core/kernel/instance_variable_get_spec.rb
index 84d3188f07..bb6f03d3bf 100644
--- a/spec/ruby/core/kernel/instance_variable_get_spec.rb
+++ b/spec/ruby/core/kernel/instance_variable_get_spec.rb
@@ -92,7 +92,7 @@ describe "Kernel#instance_variable_get when passed String" do
end
end
-describe "Kernel#instance_variable_get when passed Fixnum" do
+describe "Kernel#instance_variable_get when passed Integer" do
before :each do
@obj = Object.new
@obj.instance_variable_set("@test", :test)
diff --git a/spec/ruby/core/kernel/instance_variable_set_spec.rb b/spec/ruby/core/kernel/instance_variable_set_spec.rb
index c5a4085530..7fda30f72c 100644
--- a/spec/ruby/core/kernel/instance_variable_set_spec.rb
+++ b/spec/ruby/core/kernel/instance_variable_set_spec.rb
@@ -31,7 +31,7 @@ describe "Kernel#instance_variable_set" do
-> { dog_at.new.instance_variable_set(:"@", "cat") }.should raise_error(NameError)
end
- it "raises a TypeError if the instance variable name is a Fixnum" do
+ it "raises a TypeError if the instance variable name is an Integer" do
-> { "".instance_variable_set(1, 2) }.should raise_error(TypeError)
end
@@ -82,12 +82,12 @@ describe "Kernel#instance_variable_set" do
@frozen.ivar.should equal(:origin)
end
- it "raises a #{frozen_error_class} when passed replacement is identical to stored object" do
- -> { @frozen.instance_variable_set(:@ivar, :origin) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed replacement is identical to stored object" do
+ -> { @frozen.instance_variable_set(:@ivar, :origin) }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} when passed replacement is different from stored object" do
- -> { @frozen.instance_variable_set(:@ivar, :replacement) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed replacement is different from stored object" do
+ -> { @frozen.instance_variable_set(:@ivar, :replacement) }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/kernel/instance_variables_spec.rb b/spec/ruby/core/kernel/instance_variables_spec.rb
index b6d6e27772..831f0662a2 100644
--- a/spec/ruby/core/kernel/instance_variables_spec.rb
+++ b/spec/ruby/core/kernel/instance_variables_spec.rb
@@ -4,7 +4,9 @@ require_relative 'fixtures/classes'
describe "Kernel#instance_variables" do
describe "immediate values" do
it "returns an empty array if no instance variables are defined" do
- 0.instance_variables.should == []
+ [0, 0.5, true, false, nil].each do |value|
+ value.instance_variables.should == []
+ end
end
it "returns the correct array if an instance variable is added" do
diff --git a/spec/ruby/core/kernel/iterator_spec.rb b/spec/ruby/core/kernel/iterator_spec.rb
index 7fbdade9dc..3fe8317f26 100644
--- a/spec/ruby/core/kernel/iterator_spec.rb
+++ b/spec/ruby/core/kernel/iterator_spec.rb
@@ -1,12 +1,14 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-describe "Kernel#iterator?" do
- it "is a private method" do
- Kernel.should have_private_instance_method(:iterator?)
+ruby_version_is ""..."3.0" do
+ describe "Kernel#iterator?" do
+ it "is a private method" do
+ Kernel.should have_private_instance_method(:iterator?)
+ end
end
-end
-describe "Kernel.iterator?" do
- it "needs to be reviewed for spec completeness"
+ describe "Kernel.iterator?" do
+ it "needs to be reviewed for spec completeness"
+ end
end
diff --git a/spec/ruby/core/kernel/lambda_spec.rb b/spec/ruby/core/kernel/lambda_spec.rb
index 5c30511270..4dd34c6ca9 100644
--- a/spec/ruby/core/kernel/lambda_spec.rb
+++ b/spec/ruby/core/kernel/lambda_spec.rb
@@ -27,23 +27,27 @@ describe "Kernel.lambda" do
end
it "creates a lambda-style Proc if given a literal block via Kernel.public_send" do
- l = Kernel.public_send(:lambda) { 42 }
- l.lambda?.should be_true
+ suppress_warning do
+ l = Kernel.public_send(:lambda) { 42 }
+ l.lambda?.should be_true
+ end
end
it "returns the passed Proc if given an existing Proc" do
some_proc = proc {}
- l = lambda(&some_proc)
+ l = suppress_warning {lambda(&some_proc)}
l.should equal(some_proc)
l.lambda?.should be_false
end
it "creates a lambda-style Proc when called with zsuper" do
- l = KernelSpecs::LambdaSpecs::ForwardBlockWithZSuper.new.lambda { 42 }
- l.lambda?.should be_true
- l.call.should == 42
+ suppress_warning do
+ l = KernelSpecs::LambdaSpecs::ForwardBlockWithZSuper.new.lambda { 42 }
+ l.lambda?.should be_true
+ l.call.should == 42
- lambda { l.call(:extra) }.should raise_error(ArgumentError)
+ lambda { l.call(:extra) }.should raise_error(ArgumentError)
+ end
end
it "returns the passed Proc if given an existing Proc through super" do
@@ -55,7 +59,7 @@ describe "Kernel.lambda" do
it "does not create lambda-style Procs when captured with #method" do
kernel_lambda = method(:lambda)
- l = kernel_lambda.call { 42 }
+ l = suppress_warning {kernel_lambda.call { 42 }}
l.lambda?.should be_false
l.call(:extra).should == 42
end
diff --git a/spec/ruby/core/kernel/match_spec.rb b/spec/ruby/core/kernel/match_spec.rb
index 687cd68da4..6dc1eb7de8 100644
--- a/spec/ruby/core/kernel/match_spec.rb
+++ b/spec/ruby/core/kernel/match_spec.rb
@@ -14,7 +14,7 @@ describe "Kernel#=~" do
end
end
- ruby_version_is "2.6"..."2.7" do
+ ruby_version_is "2.6" do
it "is deprecated" do
-> do
Object.new =~ /regexp/
diff --git a/spec/ruby/core/kernel/p_spec.rb b/spec/ruby/core/kernel/p_spec.rb
index 798bd47b34..1bdd1740ca 100644
--- a/spec/ruby/core/kernel/p_spec.rb
+++ b/spec/ruby/core/kernel/p_spec.rb
@@ -57,10 +57,14 @@ describe "Kernel#p" do
}
-> { p(o) }.should output_to_fd("Next time, Gadget, NEXT TIME!\n")
- $\ = " *helicopter sound*\n"
+ suppress_warning {
+ $\ = " *helicopter sound*\n"
+ }
-> { p(o) }.should output_to_fd("Next time, Gadget, NEXT TIME!\n")
- $/ = " *helicopter sound*\n"
+ suppress_warning {
+ $/ = " *helicopter sound*\n"
+ }
-> { p(o) }.should output_to_fd("Next time, Gadget, NEXT TIME!\n")
end
diff --git a/spec/ruby/core/kernel/pp_spec.rb b/spec/ruby/core/kernel/pp_spec.rb
index e19dc64caf..b5b1c98d38 100644
--- a/spec/ruby/core/kernel/pp_spec.rb
+++ b/spec/ruby/core/kernel/pp_spec.rb
@@ -1,11 +1,9 @@
require_relative '../../spec_helper'
-ruby_version_is "2.5" do
- describe "Kernel#pp" do
- it "lazily loads the 'pp' library and delegates the call to that library" do
- # Run in child process to ensure 'pp' hasn't been loaded yet.
- output = ruby_exe("pp [1, 2, 3]")
- output.should == "[1, 2, 3]\n"
- end
+describe "Kernel#pp" do
+ it "lazily loads the 'pp' library and delegates the call to that library" do
+ # Run in child process to ensure 'pp' hasn't been loaded yet.
+ output = ruby_exe("pp [1, 2, 3]")
+ output.should == "[1, 2, 3]\n"
end
end
diff --git a/spec/ruby/core/kernel/printf_spec.rb b/spec/ruby/core/kernel/printf_spec.rb
index 5d68c0a13c..d8f93ce429 100644
--- a/spec/ruby/core/kernel/printf_spec.rb
+++ b/spec/ruby/core/kernel/printf_spec.rb
@@ -1,7 +1,6 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/sprintf'
-require "stringio"
describe "Kernel#printf" do
it "is a private method" do
@@ -10,7 +9,6 @@ describe "Kernel#printf" do
end
describe "Kernel.printf" do
-
before :each do
@stdout = $stdout
@name = tmp("kernel_puts.txt")
@@ -33,12 +31,18 @@ describe "Kernel.printf" do
object.should_receive(:write).with("string")
Kernel.printf(object, "%s", "string")
end
+end
+describe "Kernel.printf" do
describe "formatting" do
+ before :each do
+ require "stringio"
+ end
+
context "io is specified" do
it_behaves_like :kernel_sprintf, -> format, *args {
- io = StringIO.new
- printf(io, format, *args)
+ io = StringIO.new(+"")
+ Kernel.printf(io, format, *args)
io.string
}
end
@@ -46,10 +50,9 @@ describe "Kernel.printf" do
context "io is not specified" do
it_behaves_like :kernel_sprintf, -> format, *args {
stdout = $stdout
-
begin
- $stdout = io = StringIO.new
- printf(format, *args)
+ $stdout = io = StringIO.new(+"")
+ Kernel.printf(format, *args)
io.string
ensure
$stdout = stdout
diff --git a/spec/ruby/core/kernel/proc_spec.rb b/spec/ruby/core/kernel/proc_spec.rb
index 7854af44d0..dfe178420b 100644
--- a/spec/ruby/core/kernel/proc_spec.rb
+++ b/spec/ruby/core/kernel/proc_spec.rb
@@ -36,35 +36,31 @@ describe "Kernel.proc" do
end
describe "Kernel#proc" do
+ def some_method
+ proc
+ end
+
ruby_version_is ""..."2.7" do
it "uses the implicit block from an enclosing method" do
- def some_method
- proc
- end
-
prc = some_method { "hello" }
prc.call.should == "hello"
end
end
- ruby_version_is "2.7" do
- before :each do
- @deprecated = Warning[:deprecated]
- Warning[:deprecated] = true
- end
- after :each do
- Warning[:deprecated] = @deprecated
- end
-
+ ruby_version_is "2.7"..."3.0" do
it "can be created when called with no block" do
- def some_method
- proc
- end
-
-> {
some_method { "hello" }
}.should complain(/Capturing the given block using Kernel#proc is deprecated/)
end
end
+
+ ruby_version_is "3.0" do
+ it "raises an ArgumentError when passed no block" do
+ -> {
+ some_method { "hello" }
+ }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/raise_spec.rb b/spec/ruby/core/kernel/raise_spec.rb
index bf26560246..591daa03cf 100644
--- a/spec/ruby/core/kernel/raise_spec.rb
+++ b/spec/ruby/core/kernel/raise_spec.rb
@@ -6,6 +6,27 @@ describe "Kernel#raise" do
it "is a private method" do
Kernel.should have_private_instance_method(:raise)
end
+
+ it "re-raises the previously rescued exception if no exception is specified" do
+ ScratchPad.record nil
+
+ -> do
+ begin
+ raise Exception, "outer"
+ ScratchPad.record :no_abort
+ rescue Exception
+ begin
+ raise StandardError, "inner"
+ rescue StandardError
+ end
+
+ raise
+ ScratchPad.record :no_reraise
+ end
+ end.should raise_error(Exception, "outer")
+
+ ScratchPad.recorded.should be_nil
+ end
end
describe "Kernel#raise" do
diff --git a/spec/ruby/core/kernel/require_relative_spec.rb b/spec/ruby/core/kernel/require_relative_spec.rb
index b292a46c63..d4146eb3c8 100644
--- a/spec/ruby/core/kernel/require_relative_spec.rb
+++ b/spec/ruby/core/kernel/require_relative_spec.rb
@@ -90,6 +90,16 @@ describe "Kernel#require_relative with a relative path" do
ScratchPad.recorded.should == []
end
+ it "raises a LoadError that includes the missing path" do
+ missing_path = "#{@dir}/nonexistent.rb"
+ expanded_missing_path = File.expand_path(missing_path, File.dirname(__FILE__))
+ -> { require_relative(missing_path) }.should raise_error(LoadError) { |e|
+ e.message.should include(expanded_missing_path)
+ e.path.should == expanded_missing_path
+ }
+ ScratchPad.recorded.should == []
+ end
+
it "raises a LoadError if basepath does not exist" do
-> { eval("require_relative('#{@dir}/nonexistent.rb')") }.should raise_error(LoadError)
end
diff --git a/spec/ruby/core/kernel/respond_to_spec.rb b/spec/ruby/core/kernel/respond_to_spec.rb
index e7efc9f275..5b3ea3f651 100644
--- a/spec/ruby/core/kernel/respond_to_spec.rb
+++ b/spec/ruby/core/kernel/respond_to_spec.rb
@@ -25,7 +25,7 @@ describe "Kernel#respond_to?" do
end
it "throws a type error if argument can't be coerced into a Symbol" do
- -> { @a.respond_to?(Object.new) }.should raise_error(TypeError)
+ -> { @a.respond_to?(Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
end
it "returns false if obj responds to the given protected method" do
@@ -69,5 +69,4 @@ describe "Kernel#respond_to?" do
KernelSpecs::Foo.new.respond_to?(:bar).should == true
KernelSpecs::Foo.new.respond_to?(:invalid_and_silly_method_name).should == false
end
-
end
diff --git a/spec/ruby/core/kernel/shared/dup_clone.rb b/spec/ruby/core/kernel/shared/dup_clone.rb
index a52ccab359..84ad49cbde 100644
--- a/spec/ruby/core/kernel/shared/dup_clone.rb
+++ b/spec/ruby/core/kernel/shared/dup_clone.rb
@@ -59,8 +59,8 @@ describe :kernel_dup_clone, shared: true do
o.taint
o3 = o.send(@method)
- o2.tainted?.should == false
- o3.tainted?.should == true
+ o2.should_not.tainted?
+ o3.should.tainted?
end
end
@@ -78,8 +78,8 @@ describe :kernel_dup_clone, shared: true do
o.untrust
o3 = o.send(@method)
- o2.untrusted?.should == false
- o3.untrusted?.should == true
+ o2.should_not.untrusted?
+ o3.should.untrusted?
end
end
@@ -103,27 +103,13 @@ describe :kernel_dup_clone, shared: true do
:my_symbol.send(@method).should == :my_symbol
end
- ruby_version_is ''...'2.5' do
- it "raises a TypeError for Complex" do
- c = Complex(1.3, 3.1)
- -> { c.send(@method) }.should raise_error(TypeError)
- end
-
- it "raises a TypeError for Rational" do
- r = Rational(1, 3)
- -> { r.send(@method) }.should raise_error(TypeError)
- end
+ it "returns self for Complex" do
+ c = Complex(1.3, 3.1)
+ c.send(@method).should equal c
end
- ruby_version_is '2.5' do
- it "returns self for Complex" do
- c = Complex(1.3, 3.1)
- c.send(@method).should equal c
- end
-
- it "returns self for Rational" do
- r = Rational(1, 3)
- r.send(@method).should equal r
- end
+ it "returns self for Rational" do
+ r = Rational(1, 3)
+ r.send(@method).should equal r
end
end
diff --git a/spec/ruby/core/kernel/shared/lambda.rb b/spec/ruby/core/kernel/shared/lambda.rb
index c7180e1442..c70640082a 100644
--- a/spec/ruby/core/kernel/shared/lambda.rb
+++ b/spec/ruby/core/kernel/shared/lambda.rb
@@ -4,6 +4,8 @@ describe :kernel_lambda, shared: true do
end
it "raises an ArgumentError when no block is given" do
- -> { send(@method) }.should raise_error(ArgumentError)
+ suppress_warning do
+ -> { send(@method) }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/kernel/shared/require.rb b/spec/ruby/core/kernel/shared/require.rb
index 52089f22fe..d656b3b2f2 100644
--- a/spec/ruby/core/kernel/shared/require.rb
+++ b/spec/ruby/core/kernel/shared/require.rb
@@ -60,7 +60,7 @@ describe :kernel_require_basic, shared: true do
-> { @object.send(@method, nil) }.should raise_error(TypeError)
end
- it "raises a TypeError if passed a Fixnum" do
+ it "raises a TypeError if passed an Integer" do
-> { @object.send(@method, 42) }.should raise_error(TypeError)
end
@@ -160,6 +160,14 @@ describe :kernel_require_basic, shared: true do
ScratchPad.recorded.should == [:loaded]
end
+ it "accepts an Object with #to_path in $LOAD_PATH" do
+ obj = mock("to_path")
+ obj.should_receive(:to_path).at_least(:once).and_return(CODE_LOADING_DIR)
+ $LOAD_PATH << obj
+ @object.send(@method, "load_fixture.rb").should be_true
+ ScratchPad.recorded.should == [:loaded]
+ end
+
it "does not require file twice after $LOAD_PATH change" do
$LOAD_PATH << CODE_LOADING_DIR
@object.require("load_fixture.rb").should be_true
@@ -242,6 +250,15 @@ describe :kernel_require, shared: true do
@object.require("load_fixture").should be_true
ScratchPad.recorded.should == [:loaded]
end
+
+ ruby_bug "#16926", "2.7"..."3.0" do
+ it "does not load a feature twice when $LOAD_PATH has been modified" do
+ $LOAD_PATH.replace [CODE_LOADING_DIR]
+ @object.require("load_fixture").should be_true
+ $LOAD_PATH.replace [File.expand_path("b", CODE_LOADING_DIR), CODE_LOADING_DIR]
+ @object.require("load_fixture").should be_false
+ end
+ end
end
describe "(file extensions)" do
@@ -335,6 +352,21 @@ describe :kernel_require, shared: true do
loaded_feature = $LOADED_FEATURES.last
ScratchPad.recorded.should == [loaded_feature]
end
+
+ it "requires only once when a new matching file added to path" do
+ @object.require('load_fixture').should be_true
+ ScratchPad.recorded.should == [:loaded]
+
+ symlink_to_code_dir_two = tmp("codesymlinktwo")
+ File.symlink("#{CODE_LOADING_DIR}/b", symlink_to_code_dir_two)
+ begin
+ $LOAD_PATH.unshift(symlink_to_code_dir_two)
+
+ @object.require('load_fixture').should be_false
+ ensure
+ rm_r symlink_to_code_dir_two
+ end
+ end
end
describe "with symlinks in the required feature and $LOAD_PATH" do
@@ -354,26 +386,13 @@ describe :kernel_require, shared: true do
rm_r @dir, @symlink_to_dir
end
- ruby_version_is ""..."2.4.4" do
- it "canonicalizes neither the entry in $LOAD_PATH nor the filename passed to #require" do
- $LOAD_PATH.unshift(@symlink_to_dir)
- @object.require("symfile").should be_true
- loaded_feature = "#{@symlink_to_dir}/symfile.rb"
- ScratchPad.recorded.should == [loaded_feature]
- $".last.should == loaded_feature
- $LOAD_PATH[0].should == @symlink_to_dir
- end
- end
-
- ruby_version_is "2.4.4" do
- it "canonicalizes the entry in $LOAD_PATH but not the filename passed to #require" do
- $LOAD_PATH.unshift(@symlink_to_dir)
- @object.require("symfile").should be_true
- loaded_feature = "#{@dir}/symfile.rb"
- ScratchPad.recorded.should == [loaded_feature]
- $".last.should == loaded_feature
- $LOAD_PATH[0].should == @symlink_to_dir
- end
+ it "canonicalizes the entry in $LOAD_PATH but not the filename passed to #require" do
+ $LOAD_PATH.unshift(@symlink_to_dir)
+ @object.require("symfile").should be_true
+ loaded_feature = "#{@dir}/symfile.rb"
+ ScratchPad.recorded.should == [loaded_feature]
+ $".last.should == loaded_feature
+ $LOAD_PATH[0].should == @symlink_to_dir
end
end
end
@@ -527,41 +546,25 @@ describe :kernel_require, shared: true do
ScratchPad.recorded.should == []
end
- ruby_version_is ""..."2.5" do
- it "complex, enumerator, rational, thread and unicode_normalize are already required" do
- provided = %w[complex enumerator rational thread unicode_normalize]
- features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
- provided.each { |feature|
- features.should =~ /\b#{feature}\.(rb|so|jar)$/
- }
+ it "complex, enumerator, rational and thread are already required" do
+ provided = %w[complex enumerator rational thread]
+ features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
+ provided.each { |feature|
+ features.should =~ /\b#{feature}\.(rb|so|jar)$/
+ }
- code = provided.map { |f| "puts require #{f.inspect}\n" }.join
- required = ruby_exe(code, options: '--disable-gems')
- required.should == "false\n" * provided.size
- end
+ code = provided.map { |f| "puts require #{f.inspect}\n" }.join
+ required = ruby_exe(code, options: '--disable-gems')
+ required.should == "false\n" * provided.size
end
- ruby_version_is "2.5" do
- it "complex, enumerator, rational and thread are already required" do
- provided = %w[complex enumerator rational thread]
- features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
- provided.each { |feature|
- features.should =~ /\b#{feature}\.(rb|so|jar)$/
- }
-
- code = provided.map { |f| "puts require #{f.inspect}\n" }.join
- required = ruby_exe(code, options: '--disable-gems')
- required.should == "false\n" * provided.size
- end
-
- it "unicode_normalize is part of core and not $LOADED_FEATURES" do
- features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
- features.lines.each { |feature|
- feature.should_not include("unicode_normalize")
- }
+ it "unicode_normalize is part of core and not $LOADED_FEATURES" do
+ features = ruby_exe("puts $LOADED_FEATURES", options: '--disable-gems')
+ features.lines.each { |feature|
+ feature.should_not include("unicode_normalize")
+ }
- -> { @object.require("unicode_normalize") }.should raise_error(LoadError)
- end
+ -> { @object.require("unicode_normalize") }.should raise_error(LoadError)
end
end
diff --git a/spec/ruby/core/kernel/shared/sprintf.rb b/spec/ruby/core/kernel/shared/sprintf.rb
index 9899684284..ca1e6bb2ed 100644
--- a/spec/ruby/core/kernel/shared/sprintf.rb
+++ b/spec/ruby/core/kernel/shared/sprintf.rb
@@ -1,10 +1,4 @@
-require_relative '../../../shared/hash/key_error'
-
describe :kernel_sprintf, shared: true do
- def format(*args)
- @method.call(*args)
- end
-
describe "integer formats" do
it "converts argument into Integer with to_int" do
obj = Object.new
@@ -12,7 +6,7 @@ describe :kernel_sprintf, shared: true do
def obj.to_int; 10; end
obj.should_receive(:to_int).and_return(10)
- format("%b", obj).should == "1010"
+ @method.call("%b", obj).should == "1010"
end
it "converts argument into Integer with to_i if to_int isn't available" do
@@ -20,35 +14,35 @@ describe :kernel_sprintf, shared: true do
def obj.to_i; 10; end
obj.should_receive(:to_i).and_return(10)
- format("%b", obj).should == "1010"
+ @method.call("%b", obj).should == "1010"
end
it "converts String argument with Kernel#Integer" do
- format("%d", "0b1010").should == "10"
- format("%d", "112").should == "112"
- format("%d", "0127").should == "87"
- format("%d", "0xc4").should == "196"
+ @method.call("%d", "0b1010").should == "10"
+ @method.call("%d", "112").should == "112"
+ @method.call("%d", "0127").should == "87"
+ @method.call("%d", "0xc4").should == "196"
end
it "raises TypeError exception if cannot convert to Integer" do
-> {
- format("%b", Object.new)
+ @method.call("%b", Object.new)
}.should raise_error(TypeError)
end
["b", "B"].each do |f|
describe f do
it "converts argument as a binary number" do
- format("%#{f}", 10).should == "1010"
+ @method.call("%#{f}", 10).should == "1010"
end
it "displays negative number as a two's complement prefixed with '..1'" do
- format("%#{f}", -10).should == "..1" + "0110"
+ @method.call("%#{f}", -10).should == "..1" + "0110"
end
it "collapse negative number representation if it equals 1" do
- format("%#{f}", -1).should_not == "..11"
- format("%#{f}", -1).should == "..1"
+ @method.call("%#{f}", -1).should_not == "..11"
+ @method.call("%#{f}", -1).should == "..1"
end
end
end
@@ -56,58 +50,58 @@ describe :kernel_sprintf, shared: true do
["d", "i", "u"].each do |f|
describe f do
it "converts argument as a decimal number" do
- format("%#{f}", 112).should == "112"
- format("%#{f}", -112).should == "-112"
+ @method.call("%#{f}", 112).should == "112"
+ @method.call("%#{f}", -112).should == "-112"
end
it "works well with large numbers" do
- format("%#{f}", 1234567890987654321).should == "1234567890987654321"
+ @method.call("%#{f}", 1234567890987654321).should == "1234567890987654321"
end
end
end
describe "o" do
it "converts argument as an octal number" do
- format("%o", 87).should == "127"
+ @method.call("%o", 87).should == "127"
end
it "displays negative number as a two's complement prefixed with '..7'" do
- format("%o", -87).should == "..7" + "651"
+ @method.call("%o", -87).should == "..7" + "651"
end
it "collapse negative number representation if it equals 7" do
- format("%o", -1).should_not == "..77"
- format("%o", -1).should == "..7"
+ @method.call("%o", -1).should_not == "..77"
+ @method.call("%o", -1).should == "..7"
end
end
describe "x" do
it "converts argument as a hexadecimal number" do
- format("%x", 196).should == "c4"
+ @method.call("%x", 196).should == "c4"
end
it "displays negative number as a two's complement prefixed with '..f'" do
- format("%x", -196).should == "..f" + "3c"
+ @method.call("%x", -196).should == "..f" + "3c"
end
it "collapse negative number representation if it equals f" do
- format("%x", -1).should_not == "..ff"
- format("%x", -1).should == "..f"
+ @method.call("%x", -1).should_not == "..ff"
+ @method.call("%x", -1).should == "..f"
end
end
describe "X" do
it "converts argument as a hexadecimal number with uppercase letters" do
- format("%X", 196).should == "C4"
+ @method.call("%X", 196).should == "C4"
end
it "displays negative number as a two's complement prefixed with '..f'" do
- format("%X", -196).should == "..F" + "3C"
+ @method.call("%X", -196).should == "..F" + "3C"
end
it "collapse negative number representation if it equals F" do
- format("%X", -1).should_not == "..FF"
- format("%X", -1).should == "..F"
+ @method.call("%X", -1).should_not == "..FF"
+ @method.call("%X", -1).should == "..F"
end
end
end
@@ -116,70 +110,70 @@ describe :kernel_sprintf, shared: true do
it "converts argument into Float" do
obj = mock("float")
obj.should_receive(:to_f).and_return(9.6)
- format("%f", obj).should == "9.600000"
+ @method.call("%f", obj).should == "9.600000"
end
it "raises TypeError exception if cannot convert to Float" do
-> {
- format("%f", Object.new)
+ @method.call("%f", Object.new)
}.should raise_error(TypeError)
end
{"e" => "e", "E" => "E"}.each_pair do |f, exp|
describe f do
it "converts argument into exponential notation [-]d.dddddde[+-]dd" do
- format("%#{f}", 109.52).should == "1.095200#{exp}+02"
- format("%#{f}", -109.52).should == "-1.095200#{exp}+02"
- format("%#{f}", 0.10952).should == "1.095200#{exp}-01"
- format("%#{f}", -0.10952).should == "-1.095200#{exp}-01"
+ @method.call("%#{f}", 109.52).should == "1.095200#{exp}+02"
+ @method.call("%#{f}", -109.52).should == "-1.095200#{exp}+02"
+ @method.call("%#{f}", 0.10952).should == "1.095200#{exp}-01"
+ @method.call("%#{f}", -0.10952).should == "-1.095200#{exp}-01"
end
it "cuts excessive digits and keeps only 6 ones" do
- format("%#{f}", 1.123456789).should == "1.123457#{exp}+00"
+ @method.call("%#{f}", 1.123456789).should == "1.123457#{exp}+00"
end
it "rounds the last significant digit to the closest one" do
- format("%#{f}", 1.555555555).should == "1.555556#{exp}+00"
- format("%#{f}", -1.555555555).should == "-1.555556#{exp}+00"
- format("%#{f}", 1.444444444).should == "1.444444#{exp}+00"
+ @method.call("%#{f}", 1.555555555).should == "1.555556#{exp}+00"
+ @method.call("%#{f}", -1.555555555).should == "-1.555556#{exp}+00"
+ @method.call("%#{f}", 1.444444444).should == "1.444444#{exp}+00"
end
it "displays Float::INFINITY as Inf" do
- format("%#{f}", Float::INFINITY).should == "Inf"
- format("%#{f}", -Float::INFINITY).should == "-Inf"
+ @method.call("%#{f}", Float::INFINITY).should == "Inf"
+ @method.call("%#{f}", -Float::INFINITY).should == "-Inf"
end
it "displays Float::NAN as NaN" do
- format("%#{f}", Float::NAN).should == "NaN"
- format("%#{f}", -Float::NAN).should == "NaN"
+ @method.call("%#{f}", Float::NAN).should == "NaN"
+ @method.call("%#{f}", -Float::NAN).should == "NaN"
end
end
end
describe "f" do
it "converts floating point argument as [-]ddd.dddddd" do
- format("%f", 10.952).should == "10.952000"
- format("%f", -10.952).should == "-10.952000"
+ @method.call("%f", 10.952).should == "10.952000"
+ @method.call("%f", -10.952).should == "-10.952000"
end
it "cuts excessive digits and keeps only 6 ones" do
- format("%f", 1.123456789).should == "1.123457"
+ @method.call("%f", 1.123456789).should == "1.123457"
end
it "rounds the last significant digit to the closest one" do
- format("%f", 1.555555555).should == "1.555556"
- format("%f", -1.555555555).should == "-1.555556"
- format("%f", 1.444444444).should == "1.444444"
+ @method.call("%f", 1.555555555).should == "1.555556"
+ @method.call("%f", -1.555555555).should == "-1.555556"
+ @method.call("%f", 1.444444444).should == "1.444444"
end
it "displays Float::INFINITY as Inf" do
- format("%f", Float::INFINITY).should == "Inf"
- format("%f", -Float::INFINITY).should == "-Inf"
+ @method.call("%f", Float::INFINITY).should == "Inf"
+ @method.call("%f", -Float::INFINITY).should == "-Inf"
end
it "displays Float::NAN as NaN" do
- format("%f", Float::NAN).should == "NaN"
- format("%f", -Float::NAN).should == "NaN"
+ @method.call("%f", Float::NAN).should == "NaN"
+ @method.call("%f", -Float::NAN).should == "NaN"
end
end
@@ -187,100 +181,100 @@ describe :kernel_sprintf, shared: true do
describe f do
context "the exponent is less than -4" do
it "converts a floating point number using exponential form" do
- format("%#{f}", 0.0000123456).should == "1.23456#{exp}-05"
- format("%#{f}", -0.0000123456).should == "-1.23456#{exp}-05"
+ @method.call("%#{f}", 0.0000123456).should == "1.23456#{exp}-05"
+ @method.call("%#{f}", -0.0000123456).should == "-1.23456#{exp}-05"
- format("%#{f}", 0.000000000123456).should == "1.23456#{exp}-10"
- format("%#{f}", -0.000000000123456).should == "-1.23456#{exp}-10"
+ @method.call("%#{f}", 0.000000000123456).should == "1.23456#{exp}-10"
+ @method.call("%#{f}", -0.000000000123456).should == "-1.23456#{exp}-10"
end
end
context "the exponent is greater than or equal to the precision (6 by default)" do
it "converts a floating point number using exponential form" do
- format("%#{f}", 1234567).should == "1.23457#{exp}+06"
- format("%#{f}", 1234567890123).should == "1.23457#{exp}+12"
- format("%#{f}", -1234567).should == "-1.23457#{exp}+06"
+ @method.call("%#{f}", 1234567).should == "1.23457#{exp}+06"
+ @method.call("%#{f}", 1234567890123).should == "1.23457#{exp}+12"
+ @method.call("%#{f}", -1234567).should == "-1.23457#{exp}+06"
end
end
context "otherwise" do
it "converts a floating point number in dd.dddd form" do
- format("%#{f}", 0.0001).should == "0.0001"
- format("%#{f}", -0.0001).should == "-0.0001"
- format("%#{f}", 123456).should == "123456"
- format("%#{f}", -123456).should == "-123456"
+ @method.call("%#{f}", 0.0001).should == "0.0001"
+ @method.call("%#{f}", -0.0001).should == "-0.0001"
+ @method.call("%#{f}", 123456).should == "123456"
+ @method.call("%#{f}", -123456).should == "-123456"
end
it "cuts excessive digits in fractional part and keeps only 4 ones" do
- format("%#{f}", 12.12341111).should == "12.1234"
- format("%#{f}", -12.12341111).should == "-12.1234"
+ @method.call("%#{f}", 12.12341111).should == "12.1234"
+ @method.call("%#{f}", -12.12341111).should == "-12.1234"
end
it "rounds the last significant digit to the closest one in fractional part" do
- format("%#{f}", 1.555555555).should == "1.55556"
- format("%#{f}", -1.555555555).should == "-1.55556"
- format("%#{f}", 1.444444444).should == "1.44444"
+ @method.call("%#{f}", 1.555555555).should == "1.55556"
+ @method.call("%#{f}", -1.555555555).should == "-1.55556"
+ @method.call("%#{f}", 1.444444444).should == "1.44444"
end
it "cuts fraction part to have only 6 digits at all" do
- format("%#{f}", 1.1234567).should == "1.12346"
- format("%#{f}", 12.1234567).should == "12.1235"
- format("%#{f}", 123.1234567).should == "123.123"
- format("%#{f}", 1234.1234567).should == "1234.12"
- format("%#{f}", 12345.1234567).should == "12345.1"
- format("%#{f}", 123456.1234567).should == "123456"
+ @method.call("%#{f}", 1.1234567).should == "1.12346"
+ @method.call("%#{f}", 12.1234567).should == "12.1235"
+ @method.call("%#{f}", 123.1234567).should == "123.123"
+ @method.call("%#{f}", 1234.1234567).should == "1234.12"
+ @method.call("%#{f}", 12345.1234567).should == "12345.1"
+ @method.call("%#{f}", 123456.1234567).should == "123456"
end
end
it "displays Float::INFINITY as Inf" do
- format("%#{f}", Float::INFINITY).should == "Inf"
- format("%#{f}", -Float::INFINITY).should == "-Inf"
+ @method.call("%#{f}", Float::INFINITY).should == "Inf"
+ @method.call("%#{f}", -Float::INFINITY).should == "-Inf"
end
it "displays Float::NAN as NaN" do
- format("%#{f}", Float::NAN).should == "NaN"
- format("%#{f}", -Float::NAN).should == "NaN"
+ @method.call("%#{f}", Float::NAN).should == "NaN"
+ @method.call("%#{f}", -Float::NAN).should == "NaN"
end
end
end
describe "a" do
it "converts floating point argument as [-]0xh.hhhhp[+-]dd" do
- format("%a", 196).should == "0x1.88p+7"
- format("%a", -196).should == "-0x1.88p+7"
- format("%a", 196.1).should == "0x1.8833333333333p+7"
- format("%a", 0.01).should == "0x1.47ae147ae147bp-7"
- format("%a", -0.01).should == "-0x1.47ae147ae147bp-7"
+ @method.call("%a", 196).should == "0x1.88p+7"
+ @method.call("%a", -196).should == "-0x1.88p+7"
+ @method.call("%a", 196.1).should == "0x1.8833333333333p+7"
+ @method.call("%a", 0.01).should == "0x1.47ae147ae147bp-7"
+ @method.call("%a", -0.01).should == "-0x1.47ae147ae147bp-7"
end
it "displays Float::INFINITY as Inf" do
- format("%a", Float::INFINITY).should == "Inf"
- format("%a", -Float::INFINITY).should == "-Inf"
+ @method.call("%a", Float::INFINITY).should == "Inf"
+ @method.call("%a", -Float::INFINITY).should == "-Inf"
end
it "displays Float::NAN as NaN" do
- format("%a", Float::NAN).should == "NaN"
- format("%a", -Float::NAN).should == "NaN"
+ @method.call("%a", Float::NAN).should == "NaN"
+ @method.call("%a", -Float::NAN).should == "NaN"
end
end
describe "A" do
it "converts floating point argument as [-]0xh.hhhhp[+-]dd and use uppercase X and P" do
- format("%A", 196).should == "0X1.88P+7"
- format("%A", -196).should == "-0X1.88P+7"
- format("%A", 196.1).should == "0X1.8833333333333P+7"
- format("%A", 0.01).should == "0X1.47AE147AE147BP-7"
- format("%A", -0.01).should == "-0X1.47AE147AE147BP-7"
+ @method.call("%A", 196).should == "0X1.88P+7"
+ @method.call("%A", -196).should == "-0X1.88P+7"
+ @method.call("%A", 196.1).should == "0X1.8833333333333P+7"
+ @method.call("%A", 0.01).should == "0X1.47AE147AE147BP-7"
+ @method.call("%A", -0.01).should == "-0X1.47AE147AE147BP-7"
end
it "displays Float::INFINITY as Inf" do
- format("%A", Float::INFINITY).should == "Inf"
- format("%A", -Float::INFINITY).should == "-Inf"
+ @method.call("%A", Float::INFINITY).should == "Inf"
+ @method.call("%A", -Float::INFINITY).should == "-Inf"
end
it "displays Float::NAN as NaN" do
- format("%A", Float::NAN).should == "NaN"
- format("%A", -Float::NAN).should == "NaN"
+ @method.call("%A", Float::NAN).should == "NaN"
+ @method.call("%A", -Float::NAN).should == "NaN"
end
end
end
@@ -288,28 +282,28 @@ describe :kernel_sprintf, shared: true do
describe "other formats" do
describe "c" do
it "displays character if argument is a numeric code of character" do
- format("%c", 97).should == "a"
+ @method.call("%c", 97).should == "a"
end
it "displays character if argument is a single character string" do
- format("%c", "a").should == "a"
+ @method.call("%c", "a").should == "a"
end
it "raises ArgumentError if argument is a string of several characters" do
-> {
- format("%c", "abc")
+ @method.call("%c", "abc")
}.should raise_error(ArgumentError)
end
it "raises ArgumentError if argument is an empty string" do
-> {
- format("%c", "")
+ @method.call("%c", "")
}.should raise_error(ArgumentError)
end
it "supports Unicode characters" do
- format("%c", 1286).should == "Ԇ"
- format("%c", "ش").should == "ش"
+ @method.call("%c", 1286).should == "Ԇ"
+ @method.call("%c", "ش").should == "ش"
end
end
@@ -317,19 +311,19 @@ describe :kernel_sprintf, shared: true do
it "displays argument.inspect value" do
obj = mock("object")
obj.should_receive(:inspect).and_return("<inspect-result>")
- format("%p", obj).should == "<inspect-result>"
+ @method.call("%p", obj).should == "<inspect-result>"
end
end
describe "s" do
it "substitute argument passes as a string" do
- format("%s", "abc").should == "abc"
+ @method.call("%s", "abc").should == "abc"
end
it "converts argument to string with to_s" do
obj = mock("string")
obj.should_receive(:to_s).and_return("abc")
- format("%s", obj).should == "abc"
+ @method.call("%s", obj).should == "abc"
end
it "does not try to convert with to_str" do
@@ -339,29 +333,27 @@ describe :kernel_sprintf, shared: true do
end
-> {
- format("%s", obj)
+ @method.call("%s", obj)
}.should raise_error(NoMethodError)
end
- end
- describe "%" do
- ruby_version_is ""..."2.5" do
- it "alone displays the percent sign" do
- format("%").should == "%"
- end
+ it "formats a partial substring without including omitted characters" do
+ long_string = "aabbccddhelloddccbbaa"
+ sub_string = long_string[8, 5]
+ sprintf("%.#{1 * 3}s", sub_string).should == "hel"
end
+ end
- ruby_version_is "2.5" do
- it "alone raises an ArgumentError" do
- -> {
- format("%")
- }.should raise_error(ArgumentError)
- end
+ describe "%" do
+ it "alone raises an ArgumentError" do
+ -> {
+ @method.call("%")
+ }.should raise_error(ArgumentError)
end
it "is escaped by %" do
- format("%%").should == "%"
- format("%%d", 10).should == "%d"
+ @method.call("%%").should == "%"
+ @method.call("%%d", 10).should == "%d"
end
end
end
@@ -370,110 +362,110 @@ describe :kernel_sprintf, shared: true do
describe "space" do
context "applies to numeric formats bBdiouxXeEfgGaA" do
it "leaves a space at the start of non-negative numbers" do
- format("% b", 10).should == " 1010"
- format("% B", 10).should == " 1010"
- format("% d", 112).should == " 112"
- format("% i", 112).should == " 112"
- format("% o", 87).should == " 127"
- format("% u", 112).should == " 112"
- format("% x", 196).should == " c4"
- format("% X", 196).should == " C4"
-
- format("% e", 109.52).should == " 1.095200e+02"
- format("% E", 109.52).should == " 1.095200E+02"
- format("% f", 10.952).should == " 10.952000"
- format("% g", 12.1234).should == " 12.1234"
- format("% G", 12.1234).should == " 12.1234"
- format("% a", 196).should == " 0x1.88p+7"
- format("% A", 196).should == " 0X1.88P+7"
+ @method.call("% b", 10).should == " 1010"
+ @method.call("% B", 10).should == " 1010"
+ @method.call("% d", 112).should == " 112"
+ @method.call("% i", 112).should == " 112"
+ @method.call("% o", 87).should == " 127"
+ @method.call("% u", 112).should == " 112"
+ @method.call("% x", 196).should == " c4"
+ @method.call("% X", 196).should == " C4"
+
+ @method.call("% e", 109.52).should == " 1.095200e+02"
+ @method.call("% E", 109.52).should == " 1.095200E+02"
+ @method.call("% f", 10.952).should == " 10.952000"
+ @method.call("% g", 12.1234).should == " 12.1234"
+ @method.call("% G", 12.1234).should == " 12.1234"
+ @method.call("% a", 196).should == " 0x1.88p+7"
+ @method.call("% A", 196).should == " 0X1.88P+7"
end
it "does not leave a space at the start of negative numbers" do
- format("% b", -10).should == "-1010"
- format("% B", -10).should == "-1010"
- format("% d", -112).should == "-112"
- format("% i", -112).should == "-112"
- format("% o", -87).should == "-127"
- format("% u", -112).should == "-112"
- format("% x", -196).should == "-c4"
- format("% X", -196).should == "-C4"
-
- format("% e", -109.52).should == "-1.095200e+02"
- format("% E", -109.52).should == "-1.095200E+02"
- format("% f", -10.952).should == "-10.952000"
- format("% g", -12.1234).should == "-12.1234"
- format("% G", -12.1234).should == "-12.1234"
- format("% a", -196).should == "-0x1.88p+7"
- format("% A", -196).should == "-0X1.88P+7"
+ @method.call("% b", -10).should == "-1010"
+ @method.call("% B", -10).should == "-1010"
+ @method.call("% d", -112).should == "-112"
+ @method.call("% i", -112).should == "-112"
+ @method.call("% o", -87).should == "-127"
+ @method.call("% u", -112).should == "-112"
+ @method.call("% x", -196).should == "-c4"
+ @method.call("% X", -196).should == "-C4"
+
+ @method.call("% e", -109.52).should == "-1.095200e+02"
+ @method.call("% E", -109.52).should == "-1.095200E+02"
+ @method.call("% f", -10.952).should == "-10.952000"
+ @method.call("% g", -12.1234).should == "-12.1234"
+ @method.call("% G", -12.1234).should == "-12.1234"
+ @method.call("% a", -196).should == "-0x1.88p+7"
+ @method.call("% A", -196).should == "-0X1.88P+7"
end
it "prevents converting negative argument to two's complement form" do
- format("% b", -10).should == "-1010"
- format("% B", -10).should == "-1010"
- format("% o", -87).should == "-127"
- format("% x", -196).should == "-c4"
- format("% X", -196).should == "-C4"
+ @method.call("% b", -10).should == "-1010"
+ @method.call("% B", -10).should == "-1010"
+ @method.call("% o", -87).should == "-127"
+ @method.call("% x", -196).should == "-c4"
+ @method.call("% X", -196).should == "-C4"
end
it "treats several white spaces as one" do
- format("% b", 10).should == " 1010"
- format("% B", 10).should == " 1010"
- format("% d", 112).should == " 112"
- format("% i", 112).should == " 112"
- format("% o", 87).should == " 127"
- format("% u", 112).should == " 112"
- format("% x", 196).should == " c4"
- format("% X", 196).should == " C4"
-
- format("% e", 109.52).should == " 1.095200e+02"
- format("% E", 109.52).should == " 1.095200E+02"
- format("% f", 10.952).should == " 10.952000"
- format("% g", 12.1234).should == " 12.1234"
- format("% G", 12.1234).should == " 12.1234"
- format("% a", 196).should == " 0x1.88p+7"
- format("% A", 196).should == " 0X1.88P+7"
+ @method.call("% b", 10).should == " 1010"
+ @method.call("% B", 10).should == " 1010"
+ @method.call("% d", 112).should == " 112"
+ @method.call("% i", 112).should == " 112"
+ @method.call("% o", 87).should == " 127"
+ @method.call("% u", 112).should == " 112"
+ @method.call("% x", 196).should == " c4"
+ @method.call("% X", 196).should == " C4"
+
+ @method.call("% e", 109.52).should == " 1.095200e+02"
+ @method.call("% E", 109.52).should == " 1.095200E+02"
+ @method.call("% f", 10.952).should == " 10.952000"
+ @method.call("% g", 12.1234).should == " 12.1234"
+ @method.call("% G", 12.1234).should == " 12.1234"
+ @method.call("% a", 196).should == " 0x1.88p+7"
+ @method.call("% A", 196).should == " 0X1.88P+7"
end
end
end
describe "(digit)$" do
it "specifies the absolute argument number for this field" do
- format("%2$b", 0, 10).should == "1010"
- format("%2$B", 0, 10).should == "1010"
- format("%2$d", 0, 112).should == "112"
- format("%2$i", 0, 112).should == "112"
- format("%2$o", 0, 87).should == "127"
- format("%2$u", 0, 112).should == "112"
- format("%2$x", 0, 196).should == "c4"
- format("%2$X", 0, 196).should == "C4"
-
- format("%2$e", 0, 109.52).should == "1.095200e+02"
- format("%2$E", 0, 109.52).should == "1.095200E+02"
- format("%2$f", 0, 10.952).should == "10.952000"
- format("%2$g", 0, 12.1234).should == "12.1234"
- format("%2$G", 0, 12.1234).should == "12.1234"
- format("%2$a", 0, 196).should == "0x1.88p+7"
- format("%2$A", 0, 196).should == "0X1.88P+7"
-
- format("%2$c", 1, 97).should == "a"
- format("%2$p", "a", []).should == "[]"
- format("%2$s", "-", "abc").should == "abc"
+ @method.call("%2$b", 0, 10).should == "1010"
+ @method.call("%2$B", 0, 10).should == "1010"
+ @method.call("%2$d", 0, 112).should == "112"
+ @method.call("%2$i", 0, 112).should == "112"
+ @method.call("%2$o", 0, 87).should == "127"
+ @method.call("%2$u", 0, 112).should == "112"
+ @method.call("%2$x", 0, 196).should == "c4"
+ @method.call("%2$X", 0, 196).should == "C4"
+
+ @method.call("%2$e", 0, 109.52).should == "1.095200e+02"
+ @method.call("%2$E", 0, 109.52).should == "1.095200E+02"
+ @method.call("%2$f", 0, 10.952).should == "10.952000"
+ @method.call("%2$g", 0, 12.1234).should == "12.1234"
+ @method.call("%2$G", 0, 12.1234).should == "12.1234"
+ @method.call("%2$a", 0, 196).should == "0x1.88p+7"
+ @method.call("%2$A", 0, 196).should == "0X1.88P+7"
+
+ @method.call("%2$c", 1, 97).should == "a"
+ @method.call("%2$p", "a", []).should == "[]"
+ @method.call("%2$s", "-", "abc").should == "abc"
end
it "raises exception if argument number is bigger than actual arguments list" do
-> {
- format("%4$d", 1, 2, 3)
+ @method.call("%4$d", 1, 2, 3)
}.should raise_error(ArgumentError)
end
it "ignores '-' sign" do
- format("%2$d", 1, 2, 3).should == "2"
- format("%-2$d", 1, 2, 3).should == "2"
+ @method.call("%2$d", 1, 2, 3).should == "2"
+ @method.call("%-2$d", 1, 2, 3).should == "2"
end
it "raises ArgumentError exception when absolute and relative argument numbers are mixed" do
-> {
- format("%1$d %d", 1, 2)
+ @method.call("%1$d %d", 1, 2)
}.should raise_error(ArgumentError)
end
end
@@ -481,62 +473,62 @@ describe :kernel_sprintf, shared: true do
describe "#" do
context "applies to format o" do
it "increases the precision until the first digit will be `0' if it is not formatted as complements" do
- format("%#o", 87).should == "0127"
+ @method.call("%#o", 87).should == "0127"
end
it "does nothing for negative argument" do
- format("%#o", -87).should == "..7651"
+ @method.call("%#o", -87).should == "..7651"
end
end
context "applies to formats bBxX" do
it "prefixes the result with 0x, 0X, 0b and 0B respectively for non-zero argument" do
- format("%#b", 10).should == "0b1010"
- format("%#b", -10).should == "0b..10110"
- format("%#B", 10).should == "0B1010"
- format("%#B", -10).should == "0B..10110"
-
- format("%#x", 196).should == "0xc4"
- format("%#x", -196).should == "0x..f3c"
- format("%#X", 196).should == "0XC4"
- format("%#X", -196).should == "0X..F3C"
+ @method.call("%#b", 10).should == "0b1010"
+ @method.call("%#b", -10).should == "0b..10110"
+ @method.call("%#B", 10).should == "0B1010"
+ @method.call("%#B", -10).should == "0B..10110"
+
+ @method.call("%#x", 196).should == "0xc4"
+ @method.call("%#x", -196).should == "0x..f3c"
+ @method.call("%#X", 196).should == "0XC4"
+ @method.call("%#X", -196).should == "0X..F3C"
end
it "does nothing for zero argument" do
- format("%#b", 0).should == "0"
- format("%#B", 0).should == "0"
+ @method.call("%#b", 0).should == "0"
+ @method.call("%#B", 0).should == "0"
- format("%#o", 0).should == "0"
+ @method.call("%#o", 0).should == "0"
- format("%#x", 0).should == "0"
- format("%#X", 0).should == "0"
+ @method.call("%#x", 0).should == "0"
+ @method.call("%#X", 0).should == "0"
end
end
context "applies to formats aAeEfgG" do
it "forces a decimal point to be added, even if no digits follow" do
- format("%#.0a", 16.25).should == "0x1.p+4"
- format("%#.0A", 16.25).should == "0X1.P+4"
+ @method.call("%#.0a", 16.25).should == "0x1.p+4"
+ @method.call("%#.0A", 16.25).should == "0X1.P+4"
- format("%#.0e", 100).should == "1.e+02"
- format("%#.0E", 100).should == "1.E+02"
+ @method.call("%#.0e", 100).should == "1.e+02"
+ @method.call("%#.0E", 100).should == "1.E+02"
- format("%#.0f", 123.4).should == "123."
+ @method.call("%#.0f", 123.4).should == "123."
- format("%#g", 123456).should == "123456."
- format("%#G", 123456).should == "123456."
+ @method.call("%#g", 123456).should == "123456."
+ @method.call("%#G", 123456).should == "123456."
end
it "changes format from dd.dddd to exponential form for gG" do
- format("%#.0g", 123.4).should_not == "123."
- format("%#.0g", 123.4).should == "1.e+02"
+ @method.call("%#.0g", 123.4).should_not == "123."
+ @method.call("%#.0g", 123.4).should == "1.e+02"
end
end
context "applies to gG" do
it "does not remove trailing zeros" do
- format("%#g", 123.4).should == "123.400"
- format("%#g", 123.4).should == "123.400"
+ @method.call("%#g", 123.4).should == "123.400"
+ @method.call("%#g", 123.4).should == "123.400"
end
end
end
@@ -544,186 +536,186 @@ describe :kernel_sprintf, shared: true do
describe "+" do
context "applies to numeric formats bBdiouxXaAeEfgG" do
it "adds a leading plus sign to non-negative numbers" do
- format("%+b", 10).should == "+1010"
- format("%+B", 10).should == "+1010"
- format("%+d", 112).should == "+112"
- format("%+i", 112).should == "+112"
- format("%+o", 87).should == "+127"
- format("%+u", 112).should == "+112"
- format("%+x", 196).should == "+c4"
- format("%+X", 196).should == "+C4"
-
- format("%+e", 109.52).should == "+1.095200e+02"
- format("%+E", 109.52).should == "+1.095200E+02"
- format("%+f", 10.952).should == "+10.952000"
- format("%+g", 12.1234).should == "+12.1234"
- format("%+G", 12.1234).should == "+12.1234"
- format("%+a", 196).should == "+0x1.88p+7"
- format("%+A", 196).should == "+0X1.88P+7"
+ @method.call("%+b", 10).should == "+1010"
+ @method.call("%+B", 10).should == "+1010"
+ @method.call("%+d", 112).should == "+112"
+ @method.call("%+i", 112).should == "+112"
+ @method.call("%+o", 87).should == "+127"
+ @method.call("%+u", 112).should == "+112"
+ @method.call("%+x", 196).should == "+c4"
+ @method.call("%+X", 196).should == "+C4"
+
+ @method.call("%+e", 109.52).should == "+1.095200e+02"
+ @method.call("%+E", 109.52).should == "+1.095200E+02"
+ @method.call("%+f", 10.952).should == "+10.952000"
+ @method.call("%+g", 12.1234).should == "+12.1234"
+ @method.call("%+G", 12.1234).should == "+12.1234"
+ @method.call("%+a", 196).should == "+0x1.88p+7"
+ @method.call("%+A", 196).should == "+0X1.88P+7"
end
it "does not use two's complement form for negative numbers for formats bBoxX" do
- format("%+b", -10).should == "-1010"
- format("%+B", -10).should == "-1010"
- format("%+o", -87).should == "-127"
- format("%+x", -196).should == "-c4"
- format("%+X", -196).should == "-C4"
+ @method.call("%+b", -10).should == "-1010"
+ @method.call("%+B", -10).should == "-1010"
+ @method.call("%+o", -87).should == "-127"
+ @method.call("%+x", -196).should == "-c4"
+ @method.call("%+X", -196).should == "-C4"
end
end
end
describe "-" do
it "left-justifies the result of conversion if width is specified" do
- format("%-10b", 10).should == "1010 "
- format("%-10B", 10).should == "1010 "
- format("%-10d", 112).should == "112 "
- format("%-10i", 112).should == "112 "
- format("%-10o", 87).should == "127 "
- format("%-10u", 112).should == "112 "
- format("%-10x", 196).should == "c4 "
- format("%-10X", 196).should == "C4 "
+ @method.call("%-10b", 10).should == "1010 "
+ @method.call("%-10B", 10).should == "1010 "
+ @method.call("%-10d", 112).should == "112 "
+ @method.call("%-10i", 112).should == "112 "
+ @method.call("%-10o", 87).should == "127 "
+ @method.call("%-10u", 112).should == "112 "
+ @method.call("%-10x", 196).should == "c4 "
+ @method.call("%-10X", 196).should == "C4 "
- format("%-20e", 109.52).should == "1.095200e+02 "
- format("%-20E", 109.52).should == "1.095200E+02 "
- format("%-20f", 10.952).should == "10.952000 "
- format("%-20g", 12.1234).should == "12.1234 "
- format("%-20G", 12.1234).should == "12.1234 "
- format("%-20a", 196).should == "0x1.88p+7 "
- format("%-20A", 196).should == "0X1.88P+7 "
+ @method.call("%-20e", 109.52).should == "1.095200e+02 "
+ @method.call("%-20E", 109.52).should == "1.095200E+02 "
+ @method.call("%-20f", 10.952).should == "10.952000 "
+ @method.call("%-20g", 12.1234).should == "12.1234 "
+ @method.call("%-20G", 12.1234).should == "12.1234 "
+ @method.call("%-20a", 196).should == "0x1.88p+7 "
+ @method.call("%-20A", 196).should == "0X1.88P+7 "
- format("%-10c", 97).should == "a "
- format("%-10p", []).should == "[] "
- format("%-10s", "abc").should == "abc "
+ @method.call("%-10c", 97).should == "a "
+ @method.call("%-10p", []).should == "[] "
+ @method.call("%-10s", "abc").should == "abc "
end
end
describe "0 (zero)" do
context "applies to numeric formats bBdiouxXaAeEfgG and width is specified" do
it "pads with zeros, not spaces" do
- format("%010b", 10).should == "0000001010"
- format("%010B", 10).should == "0000001010"
- format("%010d", 112).should == "0000000112"
- format("%010i", 112).should == "0000000112"
- format("%010o", 87).should == "0000000127"
- format("%010u", 112).should == "0000000112"
- format("%010x", 196).should == "00000000c4"
- format("%010X", 196).should == "00000000C4"
-
- format("%020e", 109.52).should == "000000001.095200e+02"
- format("%020E", 109.52).should == "000000001.095200E+02"
- format("%020f", 10.952).should == "0000000000010.952000"
- format("%020g", 12.1234).should == "000000000000012.1234"
- format("%020G", 12.1234).should == "000000000000012.1234"
- format("%020a", 196).should == "0x000000000001.88p+7"
- format("%020A", 196).should == "0X000000000001.88P+7"
+ @method.call("%010b", 10).should == "0000001010"
+ @method.call("%010B", 10).should == "0000001010"
+ @method.call("%010d", 112).should == "0000000112"
+ @method.call("%010i", 112).should == "0000000112"
+ @method.call("%010o", 87).should == "0000000127"
+ @method.call("%010u", 112).should == "0000000112"
+ @method.call("%010x", 196).should == "00000000c4"
+ @method.call("%010X", 196).should == "00000000C4"
+
+ @method.call("%020e", 109.52).should == "000000001.095200e+02"
+ @method.call("%020E", 109.52).should == "000000001.095200E+02"
+ @method.call("%020f", 10.952).should == "0000000000010.952000"
+ @method.call("%020g", 12.1234).should == "000000000000012.1234"
+ @method.call("%020G", 12.1234).should == "000000000000012.1234"
+ @method.call("%020a", 196).should == "0x000000000001.88p+7"
+ @method.call("%020A", 196).should == "0X000000000001.88P+7"
end
it "uses radix-1 when displays negative argument as a two's complement" do
- format("%010b", -10).should == "..11110110"
- format("%010B", -10).should == "..11110110"
- format("%010o", -87).should == "..77777651"
- format("%010x", -196).should == "..ffffff3c"
- format("%010X", -196).should == "..FFFFFF3C"
+ @method.call("%010b", -10).should == "..11110110"
+ @method.call("%010B", -10).should == "..11110110"
+ @method.call("%010o", -87).should == "..77777651"
+ @method.call("%010x", -196).should == "..ffffff3c"
+ @method.call("%010X", -196).should == "..FFFFFF3C"
end
end
end
describe "*" do
it "uses the previous argument as the field width" do
- format("%*b", 10, 10).should == " 1010"
- format("%*B", 10, 10).should == " 1010"
- format("%*d", 10, 112).should == " 112"
- format("%*i", 10, 112).should == " 112"
- format("%*o", 10, 87).should == " 127"
- format("%*u", 10, 112).should == " 112"
- format("%*x", 10, 196).should == " c4"
- format("%*X", 10, 196).should == " C4"
-
- format("%*e", 20, 109.52).should == " 1.095200e+02"
- format("%*E", 20, 109.52).should == " 1.095200E+02"
- format("%*f", 20, 10.952).should == " 10.952000"
- format("%*g", 20, 12.1234).should == " 12.1234"
- format("%*G", 20, 12.1234).should == " 12.1234"
- format("%*a", 20, 196).should == " 0x1.88p+7"
- format("%*A", 20, 196).should == " 0X1.88P+7"
-
- format("%*c", 10, 97).should == " a"
- format("%*p", 10, []).should == " []"
- format("%*s", 10, "abc").should == " abc"
+ @method.call("%*b", 10, 10).should == " 1010"
+ @method.call("%*B", 10, 10).should == " 1010"
+ @method.call("%*d", 10, 112).should == " 112"
+ @method.call("%*i", 10, 112).should == " 112"
+ @method.call("%*o", 10, 87).should == " 127"
+ @method.call("%*u", 10, 112).should == " 112"
+ @method.call("%*x", 10, 196).should == " c4"
+ @method.call("%*X", 10, 196).should == " C4"
+
+ @method.call("%*e", 20, 109.52).should == " 1.095200e+02"
+ @method.call("%*E", 20, 109.52).should == " 1.095200E+02"
+ @method.call("%*f", 20, 10.952).should == " 10.952000"
+ @method.call("%*g", 20, 12.1234).should == " 12.1234"
+ @method.call("%*G", 20, 12.1234).should == " 12.1234"
+ @method.call("%*a", 20, 196).should == " 0x1.88p+7"
+ @method.call("%*A", 20, 196).should == " 0X1.88P+7"
+
+ @method.call("%*c", 10, 97).should == " a"
+ @method.call("%*p", 10, []).should == " []"
+ @method.call("%*s", 10, "abc").should == " abc"
end
it "left-justifies the result if width is negative" do
- format("%*b", -10, 10).should == "1010 "
- format("%*B", -10, 10).should == "1010 "
- format("%*d", -10, 112).should == "112 "
- format("%*i", -10, 112).should == "112 "
- format("%*o", -10, 87).should == "127 "
- format("%*u", -10, 112).should == "112 "
- format("%*x", -10, 196).should == "c4 "
- format("%*X", -10, 196).should == "C4 "
-
- format("%*e", -20, 109.52).should == "1.095200e+02 "
- format("%*E", -20, 109.52).should == "1.095200E+02 "
- format("%*f", -20, 10.952).should == "10.952000 "
- format("%*g", -20, 12.1234).should == "12.1234 "
- format("%*G", -20, 12.1234).should == "12.1234 "
- format("%*a", -20, 196).should == "0x1.88p+7 "
- format("%*A", -20, 196).should == "0X1.88P+7 "
-
- format("%*c", -10, 97).should == "a "
- format("%*p", -10, []).should == "[] "
- format("%*s", -10, "abc").should == "abc "
+ @method.call("%*b", -10, 10).should == "1010 "
+ @method.call("%*B", -10, 10).should == "1010 "
+ @method.call("%*d", -10, 112).should == "112 "
+ @method.call("%*i", -10, 112).should == "112 "
+ @method.call("%*o", -10, 87).should == "127 "
+ @method.call("%*u", -10, 112).should == "112 "
+ @method.call("%*x", -10, 196).should == "c4 "
+ @method.call("%*X", -10, 196).should == "C4 "
+
+ @method.call("%*e", -20, 109.52).should == "1.095200e+02 "
+ @method.call("%*E", -20, 109.52).should == "1.095200E+02 "
+ @method.call("%*f", -20, 10.952).should == "10.952000 "
+ @method.call("%*g", -20, 12.1234).should == "12.1234 "
+ @method.call("%*G", -20, 12.1234).should == "12.1234 "
+ @method.call("%*a", -20, 196).should == "0x1.88p+7 "
+ @method.call("%*A", -20, 196).should == "0X1.88P+7 "
+
+ @method.call("%*c", -10, 97).should == "a "
+ @method.call("%*p", -10, []).should == "[] "
+ @method.call("%*s", -10, "abc").should == "abc "
end
it "uses the specified argument as the width if * is followed by a number and $" do
- format("%1$*2$b", 10, 10).should == " 1010"
- format("%1$*2$B", 10, 10).should == " 1010"
- format("%1$*2$d", 112, 10).should == " 112"
- format("%1$*2$i", 112, 10).should == " 112"
- format("%1$*2$o", 87, 10).should == " 127"
- format("%1$*2$u", 112, 10).should == " 112"
- format("%1$*2$x", 196, 10).should == " c4"
- format("%1$*2$X", 196, 10).should == " C4"
-
- format("%1$*2$e", 109.52, 20).should == " 1.095200e+02"
- format("%1$*2$E", 109.52, 20).should == " 1.095200E+02"
- format("%1$*2$f", 10.952, 20).should == " 10.952000"
- format("%1$*2$g", 12.1234, 20).should == " 12.1234"
- format("%1$*2$G", 12.1234, 20).should == " 12.1234"
- format("%1$*2$a", 196, 20).should == " 0x1.88p+7"
- format("%1$*2$A", 196, 20).should == " 0X1.88P+7"
-
- format("%1$*2$c", 97, 10).should == " a"
- format("%1$*2$p", [], 10).should == " []"
- format("%1$*2$s", "abc", 10).should == " abc"
+ @method.call("%1$*2$b", 10, 10).should == " 1010"
+ @method.call("%1$*2$B", 10, 10).should == " 1010"
+ @method.call("%1$*2$d", 112, 10).should == " 112"
+ @method.call("%1$*2$i", 112, 10).should == " 112"
+ @method.call("%1$*2$o", 87, 10).should == " 127"
+ @method.call("%1$*2$u", 112, 10).should == " 112"
+ @method.call("%1$*2$x", 196, 10).should == " c4"
+ @method.call("%1$*2$X", 196, 10).should == " C4"
+
+ @method.call("%1$*2$e", 109.52, 20).should == " 1.095200e+02"
+ @method.call("%1$*2$E", 109.52, 20).should == " 1.095200E+02"
+ @method.call("%1$*2$f", 10.952, 20).should == " 10.952000"
+ @method.call("%1$*2$g", 12.1234, 20).should == " 12.1234"
+ @method.call("%1$*2$G", 12.1234, 20).should == " 12.1234"
+ @method.call("%1$*2$a", 196, 20).should == " 0x1.88p+7"
+ @method.call("%1$*2$A", 196, 20).should == " 0X1.88P+7"
+
+ @method.call("%1$*2$c", 97, 10).should == " a"
+ @method.call("%1$*2$p", [], 10).should == " []"
+ @method.call("%1$*2$s", "abc", 10).should == " abc"
end
it "left-justifies the result if specified with $ argument is negative" do
- format("%1$*2$b", 10, -10).should == "1010 "
- format("%1$*2$B", 10, -10).should == "1010 "
- format("%1$*2$d", 112, -10).should == "112 "
- format("%1$*2$i", 112, -10).should == "112 "
- format("%1$*2$o", 87, -10).should == "127 "
- format("%1$*2$u", 112, -10).should == "112 "
- format("%1$*2$x", 196, -10).should == "c4 "
- format("%1$*2$X", 196, -10).should == "C4 "
-
- format("%1$*2$e", 109.52, -20).should == "1.095200e+02 "
- format("%1$*2$E", 109.52, -20).should == "1.095200E+02 "
- format("%1$*2$f", 10.952, -20).should == "10.952000 "
- format("%1$*2$g", 12.1234, -20).should == "12.1234 "
- format("%1$*2$G", 12.1234, -20).should == "12.1234 "
- format("%1$*2$a", 196, -20).should == "0x1.88p+7 "
- format("%1$*2$A", 196, -20).should == "0X1.88P+7 "
-
- format("%1$*2$c", 97, -10).should == "a "
- format("%1$*2$p", [], -10).should == "[] "
- format("%1$*2$s", "abc", -10).should == "abc "
+ @method.call("%1$*2$b", 10, -10).should == "1010 "
+ @method.call("%1$*2$B", 10, -10).should == "1010 "
+ @method.call("%1$*2$d", 112, -10).should == "112 "
+ @method.call("%1$*2$i", 112, -10).should == "112 "
+ @method.call("%1$*2$o", 87, -10).should == "127 "
+ @method.call("%1$*2$u", 112, -10).should == "112 "
+ @method.call("%1$*2$x", 196, -10).should == "c4 "
+ @method.call("%1$*2$X", 196, -10).should == "C4 "
+
+ @method.call("%1$*2$e", 109.52, -20).should == "1.095200e+02 "
+ @method.call("%1$*2$E", 109.52, -20).should == "1.095200E+02 "
+ @method.call("%1$*2$f", 10.952, -20).should == "10.952000 "
+ @method.call("%1$*2$g", 12.1234, -20).should == "12.1234 "
+ @method.call("%1$*2$G", 12.1234, -20).should == "12.1234 "
+ @method.call("%1$*2$a", 196, -20).should == "0x1.88p+7 "
+ @method.call("%1$*2$A", 196, -20).should == "0X1.88P+7 "
+
+ @method.call("%1$*2$c", 97, -10).should == "a "
+ @method.call("%1$*2$p", [], -10).should == "[] "
+ @method.call("%1$*2$s", "abc", -10).should == "abc "
end
it "raises ArgumentError when is mixed with width" do
-> {
- format("%*10d", 10, 112)
+ @method.call("%*10d", 10, 112)
}.should raise_error(ArgumentError)
end
end
@@ -731,74 +723,74 @@ describe :kernel_sprintf, shared: true do
describe "width" do
it "specifies the minimum number of characters that will be written to the result" do
- format("%10b", 10).should == " 1010"
- format("%10B", 10).should == " 1010"
- format("%10d", 112).should == " 112"
- format("%10i", 112).should == " 112"
- format("%10o", 87).should == " 127"
- format("%10u", 112).should == " 112"
- format("%10x", 196).should == " c4"
- format("%10X", 196).should == " C4"
-
- format("%20e", 109.52).should == " 1.095200e+02"
- format("%20E", 109.52).should == " 1.095200E+02"
- format("%20f", 10.952).should == " 10.952000"
- format("%20g", 12.1234).should == " 12.1234"
- format("%20G", 12.1234).should == " 12.1234"
- format("%20a", 196).should == " 0x1.88p+7"
- format("%20A", 196).should == " 0X1.88P+7"
-
- format("%10c", 97).should == " a"
- format("%10p", []).should == " []"
- format("%10s", "abc").should == " abc"
+ @method.call("%10b", 10).should == " 1010"
+ @method.call("%10B", 10).should == " 1010"
+ @method.call("%10d", 112).should == " 112"
+ @method.call("%10i", 112).should == " 112"
+ @method.call("%10o", 87).should == " 127"
+ @method.call("%10u", 112).should == " 112"
+ @method.call("%10x", 196).should == " c4"
+ @method.call("%10X", 196).should == " C4"
+
+ @method.call("%20e", 109.52).should == " 1.095200e+02"
+ @method.call("%20E", 109.52).should == " 1.095200E+02"
+ @method.call("%20f", 10.952).should == " 10.952000"
+ @method.call("%20g", 12.1234).should == " 12.1234"
+ @method.call("%20G", 12.1234).should == " 12.1234"
+ @method.call("%20a", 196).should == " 0x1.88p+7"
+ @method.call("%20A", 196).should == " 0X1.88P+7"
+
+ @method.call("%10c", 97).should == " a"
+ @method.call("%10p", []).should == " []"
+ @method.call("%10s", "abc").should == " abc"
end
it "is ignored if argument's actual length is greater" do
- format("%5d", 1234567890).should == "1234567890"
+ @method.call("%5d", 1234567890).should == "1234567890"
end
end
describe "precision" do
context "integer types" do
it "controls the number of decimal places displayed" do
- format("%.6b", 10).should == "001010"
- format("%.6B", 10).should == "001010"
- format("%.5d", 112).should == "00112"
- format("%.5i", 112).should == "00112"
- format("%.5o", 87).should == "00127"
- format("%.5u", 112).should == "00112"
+ @method.call("%.6b", 10).should == "001010"
+ @method.call("%.6B", 10).should == "001010"
+ @method.call("%.5d", 112).should == "00112"
+ @method.call("%.5i", 112).should == "00112"
+ @method.call("%.5o", 87).should == "00127"
+ @method.call("%.5u", 112).should == "00112"
- format("%.5x", 196).should == "000c4"
- format("%.5X", 196).should == "000C4"
+ @method.call("%.5x", 196).should == "000c4"
+ @method.call("%.5X", 196).should == "000C4"
end
end
context "float types" do
it "controls the number of decimal places displayed in fraction part" do
- format("%.10e", 109.52).should == "1.0952000000e+02"
- format("%.10E", 109.52).should == "1.0952000000E+02"
- format("%.10f", 10.952).should == "10.9520000000"
- format("%.10a", 196).should == "0x1.8800000000p+7"
- format("%.10A", 196).should == "0X1.8800000000P+7"
+ @method.call("%.10e", 109.52).should == "1.0952000000e+02"
+ @method.call("%.10E", 109.52).should == "1.0952000000E+02"
+ @method.call("%.10f", 10.952).should == "10.9520000000"
+ @method.call("%.10a", 196).should == "0x1.8800000000p+7"
+ @method.call("%.10A", 196).should == "0X1.8800000000P+7"
end
it "does not affect G format" do
- format("%.10g", 12.1234).should == "12.1234"
- format("%.10g", 123456789).should == "123456789"
+ @method.call("%.10g", 12.1234).should == "12.1234"
+ @method.call("%.10g", 123456789).should == "123456789"
end
end
context "string formats" do
it "determines the maximum number of characters to be copied from the string" do
- format("%.1p", [1]).should == "["
- format("%.2p", [1]).should == "[1"
- format("%.10p", [1]).should == "[1]"
- format("%.0p", [1]).should == ""
+ @method.call("%.1p", [1]).should == "["
+ @method.call("%.2p", [1]).should == "[1"
+ @method.call("%.10p", [1]).should == "[1]"
+ @method.call("%.0p", [1]).should == ""
- format("%.1s", "abc").should == "a"
- format("%.2s", "abc").should == "ab"
- format("%.10s", "abc").should == "abc"
- format("%.0s", "abc").should == ""
+ @method.call("%.1s", "abc").should == "a"
+ @method.call("%.2s", "abc").should == "ab"
+ @method.call("%.10s", "abc").should == "abc"
+ @method.call("%.0s", "abc").should == ""
end
end
end
@@ -806,49 +798,49 @@ describe :kernel_sprintf, shared: true do
describe "reference by name" do
describe "%<name>s style" do
it "uses value passed in a hash argument" do
- format("%<foo>d", foo: 123).should == "123"
+ @method.call("%<foo>d", foo: 123).should == "123"
end
it "supports flags, width, precision and type" do
- format("%+20.10<foo>f", foo: 10.952).should == " +10.9520000000"
+ @method.call("%+20.10<foo>f", foo: 10.952).should == " +10.9520000000"
end
it "allows to place name in any position" do
- format("%+15.5<foo>f", foo: 10.952).should == " +10.95200"
- format("%+15<foo>.5f", foo: 10.952).should == " +10.95200"
- format("%+<foo>15.5f", foo: 10.952).should == " +10.95200"
- format("%<foo>+15.5f", foo: 10.952).should == " +10.95200"
+ @method.call("%+15.5<foo>f", foo: 10.952).should == " +10.95200"
+ @method.call("%+15<foo>.5f", foo: 10.952).should == " +10.95200"
+ @method.call("%+<foo>15.5f", foo: 10.952).should == " +10.95200"
+ @method.call("%<foo>+15.5f", foo: 10.952).should == " +10.95200"
end
it "cannot be mixed with unnamed style" do
-> {
- format("%d %<foo>d", 1, foo: "123")
+ @method.call("%d %<foo>d", 1, foo: "123")
}.should raise_error(ArgumentError)
end
end
describe "%{name} style" do
it "uses value passed in a hash argument" do
- format("%{foo}", foo: 123).should == "123"
+ @method.call("%{foo}", foo: 123).should == "123"
end
it "does not support type style" do
- format("%{foo}d", foo: 123).should == "123d"
+ @method.call("%{foo}d", foo: 123).should == "123d"
end
it "supports flags, width and precision" do
- format("%-20.5{foo}", foo: "123456789").should == "12345 "
+ @method.call("%-20.5{foo}", foo: "123456789").should == "12345 "
end
it "cannot be mixed with unnamed style" do
-> {
- format("%d %{foo}", 1, foo: "123")
+ @method.call("%d %{foo}", 1, foo: "123")
}.should raise_error(ArgumentError)
end
it "raises KeyError when there is no matching key" do
-> {
- format("%{foo}", {})
+ @method.call("%{foo}", {})
}.should raise_error(KeyError)
end
@@ -860,18 +852,36 @@ describe :kernel_sprintf, shared: true do
obj.should_receive(:to_s).and_return("42")
obj.should_not_receive(:to_str)
- format("%{foo}", foo: obj).should == "42"
+ @method.call("%{foo}", foo: obj).should == "42"
end
end
end
describe "faulty key" do
- before :all do
- @base_method = @method
+ before :each do
+ @object = { foooo: 1 }
+ end
+
+ it "raises a KeyError" do
+ -> {
+ @method.call("%<foo>s", @object)
+ }.should raise_error(KeyError)
end
- it_behaves_like :key_error, -> obj, key {
- @base_method.call("%<#{key}>s", obj)
- }, { foooo: 1 }
+ it "sets the Hash as the receiver of KeyError" do
+ -> {
+ @method.call("%<foo>s", @object)
+ }.should raise_error(KeyError) { |err|
+ err.receiver.should equal(@object)
+ }
+ end
+
+ it "sets the unmatched key as the key of KeyError" do
+ -> {
+ @method.call("%<foo>s", @object)
+ }.should raise_error(KeyError) { |err|
+ err.key.to_s.should == 'foo'
+ }
+ end
end
end
diff --git a/spec/ruby/core/kernel/shared/sprintf_encoding.rb b/spec/ruby/core/kernel/shared/sprintf_encoding.rb
index c3d62bf3bb..5ca66b9083 100644
--- a/spec/ruby/core/kernel/shared/sprintf_encoding.rb
+++ b/spec/ruby/core/kernel/shared/sprintf_encoding.rb
@@ -1,11 +1,19 @@
describe :kernel_sprintf_encoding, shared: true do
- def format(*args)
- @method.call(*args)
+ it "can produce a string with valid encoding" do
+ string = @method.call("good day %{valid}", valid: "e")
+ string.encoding.should == Encoding::UTF_8
+ string.valid_encoding?.should be_true
+ end
+
+ it "can produce a string with invalid encoding" do
+ string = @method.call("good day %{invalid}", invalid: "\x80")
+ string.encoding.should == Encoding::UTF_8
+ string.valid_encoding?.should be_false
end
it "returns a String in the same encoding as the format String if compatible" do
string = "%s".force_encoding(Encoding::KOI8_U)
- result = format(string, "dogs")
+ result = @method.call(string, "dogs")
result.encoding.should equal(Encoding::KOI8_U)
end
@@ -13,7 +21,7 @@ describe :kernel_sprintf_encoding, shared: true do
string = "foo %s".force_encoding(Encoding::US_ASCII)
argument = "b\303\274r".force_encoding(Encoding::UTF_8)
- result = format(string, argument)
+ result = @method.call(string, argument)
result.encoding.should equal(Encoding::UTF_8)
end
@@ -22,7 +30,7 @@ describe :kernel_sprintf_encoding, shared: true do
argument = "Ђ".encode('windows-1251')
-> {
- format(string, argument)
+ @method.call(string, argument)
}.should raise_error(Encoding::CompatibilityError)
end
end
diff --git a/spec/ruby/core/kernel/singleton_class_spec.rb b/spec/ruby/core/kernel/singleton_class_spec.rb
index 5dbb4f8c05..a8bcd916d1 100644
--- a/spec/ruby/core/kernel/singleton_class_spec.rb
+++ b/spec/ruby/core/kernel/singleton_class_spec.rb
@@ -17,7 +17,7 @@ describe "Kernel#singleton_class" do
false.singleton_class.should == FalseClass
end
- it "raises TypeError for Fixnum" do
+ it "raises TypeError for Integer" do
-> { 123.singleton_class }.should raise_error(TypeError)
end
diff --git a/spec/ruby/core/kernel/sleep_spec.rb b/spec/ruby/core/kernel/sleep_spec.rb
index 387dc4787b..71a3f24f13 100644
--- a/spec/ruby/core/kernel/sleep_spec.rb
+++ b/spec/ruby/core/kernel/sleep_spec.rb
@@ -14,7 +14,7 @@ describe "Kernel#sleep" do
sleep(0.001).should >= 0
end
- it "accepts a Fixnum" do
+ it "accepts an Integer" do
sleep(0).should >= 0
end
diff --git a/spec/ruby/core/kernel/srand_spec.rb b/spec/ruby/core/kernel/srand_spec.rb
index 5454aae8cf..6774d19284 100644
--- a/spec/ruby/core/kernel/srand_spec.rb
+++ b/spec/ruby/core/kernel/srand_spec.rb
@@ -11,6 +11,10 @@ describe "Kernel.srand" do
srand(20).should == 10
end
+ it "returns the previous seed value on the first call" do
+ ruby_exe('p srand(10)', options: '--disable-gems').chomp.should =~ /\A\d+\z/
+ end
+
it "seeds the RNG correctly and repeatably" do
srand(10)
x = rand
@@ -33,7 +37,7 @@ describe "Kernel.srand" do
srand.should == -17
end
- it "accepts a Bignum as a seed" do
+ it "accepts an Integer as a seed" do
srand(0x12345678901234567890)
srand.should == 0x12345678901234567890
end
diff --git a/spec/ruby/core/kernel/system_spec.rb b/spec/ruby/core/kernel/system_spec.rb
index 96c0496dd6..696e6ae3d7 100644
--- a/spec/ruby/core/kernel/system_spec.rb
+++ b/spec/ruby/core/kernel/system_spec.rb
@@ -6,14 +6,14 @@ describe :kernel_system, shared: true do
-> { @object.system("echo a") }.should output_to_fd("a\n")
$?.should be_an_instance_of Process::Status
- $?.success?.should == true
+ $?.should.success?
end
it "returns true when the command exits with a zero exit status" do
@object.system(ruby_cmd('exit 0')).should == true
$?.should be_an_instance_of Process::Status
- $?.success?.should == true
+ $?.should.success?
$?.exitstatus.should == 0
end
@@ -21,7 +21,7 @@ describe :kernel_system, shared: true do
@object.system(ruby_cmd('exit 1')).should == false
$?.should be_an_instance_of Process::Status
- $?.success?.should == false
+ $?.should_not.success?
$?.exitstatus.should == 1
end
@@ -40,7 +40,7 @@ describe :kernel_system, shared: true do
$?.should be_an_instance_of Process::Status
$?.pid.should be_kind_of(Integer)
- $?.exitstatus.should == 127
+ $?.should_not.success?
end
it "does not write to stderr when command execution fails" do
diff --git a/spec/ruby/core/kernel/taint_spec.rb b/spec/ruby/core/kernel/taint_spec.rb
index 6de009a46c..8ba9869af2 100644
--- a/spec/ruby/core/kernel/taint_spec.rb
+++ b/spec/ruby/core/kernel/taint_spec.rb
@@ -11,12 +11,12 @@ describe "Kernel#taint" do
it "sets the tainted bit" do
o = Object.new
o.taint
- o.tainted?.should == true
+ o.should.tainted?
end
- it "raises #{frozen_error_class} on an untainted, frozen object" do
+ it "raises FrozenError on an untainted, frozen object" do
o = Object.new.freeze
- -> { o.taint }.should raise_error(frozen_error_class)
+ -> { o.taint }.should raise_error(FrozenError)
end
it "does not raise an error on a tainted, frozen object" do
@@ -27,21 +27,36 @@ describe "Kernel#taint" do
it "has no effect on immediate values" do
[nil, true, false].each do |v|
v.taint
- v.tainted?.should == false
+ v.should_not.tainted?
end
end
it "no raises a RuntimeError on symbols" do
v = :sym
-> { v.taint }.should_not raise_error(RuntimeError)
- v.tainted?.should == false
+ v.should_not.tainted?
end
- it "no raises error on fixnum values" do
+ it "no raises error on integer values" do
[1].each do |v|
-> { v.taint }.should_not raise_error(RuntimeError)
- v.tainted?.should == false
+ v.should_not.tainted?
end
end
end
+
+ ruby_version_is "2.7"..."3.0" do
+ it "is a no-op" do
+ o = Object.new
+ o.taint
+ o.should_not.tainted?
+ end
+
+ it "warns in verbose mode" do
+ -> {
+ obj = mock("tainted")
+ obj.taint
+ }.should complain(/Object#taint is deprecated and will be removed in Ruby 3.2/, verbose: true)
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/tainted_spec.rb b/spec/ruby/core/kernel/tainted_spec.rb
index 72ce346dda..022938bfc1 100644
--- a/spec/ruby/core/kernel/tainted_spec.rb
+++ b/spec/ruby/core/kernel/tainted_spec.rb
@@ -7,8 +7,25 @@ describe "Kernel#tainted?" do
o = mock('o')
p = mock('p')
p.taint
- o.tainted?.should == false
- p.tainted?.should == true
+ o.should_not.tainted?
+ p.should.tainted?
+ end
+ end
+
+ ruby_version_is "2.7"..."3.0" do
+ it "is a no-op" do
+ o = mock('o')
+ p = mock('p')
+ p.taint
+ o.should_not.tainted?
+ p.should_not.tainted?
+ end
+
+ it "warns in verbose mode" do
+ -> {
+ o = mock('o')
+ o.tainted?
+ }.should complain(/Object#tainted\? is deprecated and will be removed in Ruby 3.2/, verbose: true)
end
end
end
diff --git a/spec/ruby/core/kernel/trust_spec.rb b/spec/ruby/core/kernel/trust_spec.rb
index 13f085f420..399983f74d 100644
--- a/spec/ruby/core/kernel/trust_spec.rb
+++ b/spec/ruby/core/kernel/trust_spec.rb
@@ -11,12 +11,12 @@ describe "Kernel#trust" do
it "clears the untrusted bit" do
o = Object.new.untrust
o.trust
- o.untrusted?.should == false
+ o.should_not.untrusted?
end
- it "raises #{frozen_error_class} on an untrusted, frozen object" do
+ it "raises FrozenError on an untrusted, frozen object" do
o = Object.new.untrust.freeze
- -> { o.trust }.should raise_error(frozen_error_class)
+ -> { o.trust }.should raise_error(FrozenError)
end
it "does not raise an error on a trusted, frozen object" do
@@ -24,4 +24,20 @@ describe "Kernel#trust" do
o.trust.should equal(o)
end
end
+
+ ruby_version_is "2.7"..."3.0" do
+ it "is a no-op" do
+ o = Object.new.untrust
+ o.should_not.untrusted?
+ o.trust
+ o.should_not.untrusted?
+ end
+
+ it "warns in verbose mode" do
+ -> {
+ o = Object.new.untrust
+ o.trust
+ }.should complain(/Object#trust is deprecated and will be removed in Ruby 3.2/, verbose: true)
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/untaint_spec.rb b/spec/ruby/core/kernel/untaint_spec.rb
index 58485fcc58..44d87da5d5 100644
--- a/spec/ruby/core/kernel/untaint_spec.rb
+++ b/spec/ruby/core/kernel/untaint_spec.rb
@@ -11,12 +11,12 @@ describe "Kernel#untaint" do
it "clears the tainted bit" do
o = Object.new.taint
o.untaint
- o.tainted?.should == false
+ o.should_not.tainted?
end
- it "raises #{frozen_error_class} on a tainted, frozen object" do
+ it "raises FrozenError on a tainted, frozen object" do
o = Object.new.taint.freeze
- -> { o.untaint }.should raise_error(frozen_error_class)
+ -> { o.untaint }.should raise_error(FrozenError)
end
it "does not raise an error on an untainted, frozen object" do
@@ -24,4 +24,20 @@ describe "Kernel#untaint" do
o.untaint.should equal(o)
end
end
+
+ ruby_version_is "2.7"..."3.0" do
+ it "is a no-op" do
+ o = Object.new.taint
+ o.should_not.tainted?
+ o.untaint
+ o.should_not.tainted?
+ end
+
+ it "warns in verbose mode" do
+ -> {
+ o = Object.new.taint
+ o.untaint
+ }.should complain(/Object#untaint is deprecated and will be removed in Ruby 3.2/, verbose: true)
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/untrust_spec.rb b/spec/ruby/core/kernel/untrust_spec.rb
index c6eb79af1c..aff0fec57b 100644
--- a/spec/ruby/core/kernel/untrust_spec.rb
+++ b/spec/ruby/core/kernel/untrust_spec.rb
@@ -11,12 +11,12 @@ describe "Kernel#untrust" do
it "sets the untrusted bit" do
o = Object.new
o.untrust
- o.untrusted?.should == true
+ o.should.untrusted?
end
- it "raises #{frozen_error_class} on a trusted, frozen object" do
+ it "raises FrozenError on a trusted, frozen object" do
o = Object.new.freeze
- -> { o.untrust }.should raise_error(frozen_error_class)
+ -> { o.untrust }.should raise_error(FrozenError)
end
it "does not raise an error on an untrusted, frozen object" do
@@ -24,4 +24,19 @@ describe "Kernel#untrust" do
o.untrust.should equal(o)
end
end
+
+ ruby_version_is "2.7"..."3.0" do
+ it "is a no-op" do
+ o = Object.new
+ o.untrust
+ o.should_not.untrusted?
+ end
+
+ it "warns in verbose mode" do
+ -> {
+ o = Object.new
+ o.untrust
+ }.should complain(/Object#untrust is deprecated and will be removed in Ruby 3.2/, verbose: true)
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/untrusted_spec.rb b/spec/ruby/core/kernel/untrusted_spec.rb
index ccebfe38be..5347c90093 100644
--- a/spec/ruby/core/kernel/untrusted_spec.rb
+++ b/spec/ruby/core/kernel/untrusted_spec.rb
@@ -5,9 +5,9 @@ describe "Kernel#untrusted?" do
ruby_version_is ''...'2.7' do
it "returns the untrusted status of an object" do
o = mock('o')
- o.untrusted?.should == false
+ o.should_not.untrusted?
o.untrust
- o.untrusted?.should == true
+ o.should.untrusted?
end
it "has no effect on immediate values" do
@@ -17,9 +17,9 @@ describe "Kernel#untrusted?" do
a.untrust
b.untrust
c.untrust
- a.untrusted?.should == false
- b.untrusted?.should == false
- c.untrusted?.should == false
+ a.should_not.untrusted?
+ b.should_not.untrusted?
+ c.should_not.untrusted?
end
it "has effect on immediate values" do
@@ -27,4 +27,20 @@ describe "Kernel#untrusted?" do
-> { d.untrust }.should_not raise_error(RuntimeError)
end
end
+
+ ruby_version_is "2.7"..."3.0" do
+ it "is a no-op" do
+ o = mock('o')
+ o.should_not.untrusted?
+ o.untrust
+ o.should_not.untrusted?
+ end
+
+ it "warns in verbose mode" do
+ -> {
+ o = mock('o')
+ o.untrusted?
+ }.should complain(/Object#untrusted\? is deprecated and will be removed in Ruby 3.2/, verbose: true)
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/warn_spec.rb b/spec/ruby/core/kernel/warn_spec.rb
index 2a404a2a35..5953a47e81 100644
--- a/spec/ruby/core/kernel/warn_spec.rb
+++ b/spec/ruby/core/kernel/warn_spec.rb
@@ -8,15 +8,16 @@ describe "Kernel#warn" do
end
after :each do
- $VERBOSE = @before_verbose
+ $VERBOSE = nil
$/ = @before_separator
+ $VERBOSE = @before_verbose
end
it "is a private method" do
Kernel.should have_private_instance_method(:warn)
end
- it "requires multiple arguments" do
+ it "accepts multiple arguments" do
Kernel.method(:warn).arity.should < 0
end
@@ -86,71 +87,161 @@ describe "Kernel#warn" do
}.should output(nil, "to_s called\n")
end
- ruby_version_is "2.5" do
- describe ":uplevel keyword argument" do
- before :each do
- $VERBOSE = true
- end
+ describe ":uplevel keyword argument" do
+ before :each do
+ $VERBOSE = true
+ end
- it "prepends a message with specified line from the backtrace" do
- w = KernelSpecs::WarnInNestedCall.new
+ it "prepends a message with specified line from the backtrace" do
+ w = KernelSpecs::WarnInNestedCall.new
- -> { w.f4("foo", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: foo|)
- -> { w.f4("foo", 1) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f1_call_lineno}: warning: foo|)
- -> { w.f4("foo", 2) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f2_call_lineno}: warning: foo|)
- -> { w.f4("foo", 3) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f3_call_lineno}: warning: foo|)
- end
+ -> { w.f4("foo", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: foo|)
+ -> { w.f4("foo", 1) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f1_call_lineno}: warning: foo|)
+ -> { w.f4("foo", 2) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f2_call_lineno}: warning: foo|)
+ -> { w.f4("foo", 3) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f3_call_lineno}: warning: foo|)
+ end
- it "converts first arg using to_s" do
- w = KernelSpecs::WarnInNestedCall.new
+ # Test both explicitly without and with RubyGems as RubyGems overrides Kernel#warn
+ it "shows the caller of #require and not #require itself without RubyGems" do
+ file = fixture(__FILE__ , "warn_require_caller.rb")
+ ruby_exe(file, options: "--disable-gems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n"
+ end
- -> { w.f4(false, 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: false|)
- -> { w.f4(nil, 1) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f1_call_lineno}: warning: |)
- obj = mock("obj")
- obj.should_receive(:to_s).and_return("to_s called")
- -> { w.f4(obj, 2) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f2_call_lineno}: warning: to_s called|)
+ ruby_version_is "2.6" do
+ it "shows the caller of #require and not #require itself with RubyGems loaded" do
+ file = fixture(__FILE__ , "warn_require_caller.rb")
+ ruby_exe(file, options: "-rrubygems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n"
end
+ end
- it "does not prepend caller information if line number is too big" do
- w = KernelSpecs::WarnInNestedCall.new
- -> { w.f4("foo", 100) }.should output(nil, "warning: foo\n")
+ 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
+ file.should.start_with?('<internal:')
+
+ file = fixture(__FILE__ , "warn_core_method.rb")
+ n = 9
+ ruby_exe(file, options: "--disable-gems", args: "2>&1").lines.should == [
+ "#{file}:#{n+0}: warning: use X instead\n",
+ "#{file}:#{n+1}: warning: use X instead\n",
+ "#{file}:#{n+2}: warning: use X instead\n",
+ "#{file}:#{n+4}: warning: use X instead\n",
+ ]
end
+ end
- it "prepends even if a message is empty or nil" do
- w = KernelSpecs::WarnInNestedCall.new
-
- -> { w.f4("", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|)
- -> { w.f4(nil, 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|)
+ ruby_version_is "3.0" do
+ it "accepts :category keyword with a symbol" do
+ -> {
+ $VERBOSE = true
+ warn("message", category: :deprecated)
+ }.should output(nil, "message\n")
end
- it "converts value to Integer" do
- w = KernelSpecs::WarnInNestedCall.new
-
- -> { w.f4(0.1) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|)
- -> { w.f4(Rational(1, 2)) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|)
+ it "accepts :category keyword with nil" do
+ -> {
+ $VERBOSE = true
+ warn("message", category: nil)
+ }.should output(nil, "message\n")
end
- it "raises ArgumentError if passed negative value" do
- -> { warn "", uplevel: -2 }.should raise_error(ArgumentError)
- -> { warn "", uplevel: -100 }.should raise_error(ArgumentError)
+ it "accepts :category keyword with object convertible to symbol" do
+ o = Object.new
+ def o.to_sym; :deprecated; end
+ -> {
+ $VERBOSE = true
+ warn("message", category: o)
+ }.should output(nil, "message\n")
end
- it "raises ArgumentError if passed -1" do
- -> { warn "", uplevel: -1 }.should raise_error(ArgumentError)
+ it "raises if :category keyword is not nil and not convertible to symbol" do
+ -> {
+ $VERBOSE = true
+ warn("message", category: Object.new)
+ }.should raise_error(TypeError)
end
+ end
- it "raises TypeError if passed not Integer" do
- -> { warn "", uplevel: "" }.should raise_error(TypeError)
- -> { warn "", uplevel: [] }.should raise_error(TypeError)
- -> { warn "", uplevel: {} }.should raise_error(TypeError)
- -> { warn "", uplevel: Object.new }.should raise_error(TypeError)
- end
+ it "converts first arg using to_s" do
+ w = KernelSpecs::WarnInNestedCall.new
+
+ -> { w.f4(false, 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: false|)
+ -> { w.f4(nil, 1) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f1_call_lineno}: warning: |)
+ obj = mock("obj")
+ obj.should_receive(:to_s).and_return("to_s called")
+ -> { w.f4(obj, 2) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.f2_call_lineno}: warning: to_s called|)
+ end
+
+ it "does not prepend caller information if the uplevel argument is too large" do
+ w = KernelSpecs::WarnInNestedCall.new
+ -> { w.f4("foo", 100) }.should output(nil, "warning: foo\n")
+ end
+
+ it "prepends even if a message is empty or nil" do
+ w = KernelSpecs::WarnInNestedCall.new
+
+ -> { w.f4("", 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|)
+ -> { w.f4(nil, 0) }.should output(nil, %r|core/kernel/fixtures/classes.rb:#{w.warn_call_lineno}: warning: \n$|)
+ end
+
+ it "converts value to Integer" do
+ w = KernelSpecs::WarnInNestedCall.new
+
+ -> { w.f4(0.1) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|)
+ -> { w.f4(Rational(1, 2)) }.should output(nil, %r|classes.rb:#{w.warn_call_lineno}:|)
+ end
+
+ it "raises ArgumentError if passed negative value" do
+ -> { warn "", uplevel: -2 }.should raise_error(ArgumentError)
+ -> { warn "", uplevel: -100 }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if passed -1" do
+ -> { warn "", uplevel: -1 }.should raise_error(ArgumentError)
end
- it "treats empty hash as no keyword argument" do
- h = {}
- -> { warn(**h) }.should_not complain(verbose: true)
- -> { warn('foo', **h) }.should complain("foo\n")
+ it "raises TypeError if passed not Integer" do
+ -> { warn "", uplevel: "" }.should raise_error(TypeError)
+ -> { warn "", uplevel: [] }.should raise_error(TypeError)
+ -> { warn "", uplevel: {} }.should raise_error(TypeError)
+ -> { warn "", uplevel: Object.new }.should raise_error(TypeError)
+ end
+ end
+
+ it "treats empty hash as no keyword argument" do
+ h = {}
+ -> { warn(**h) }.should_not complain(verbose: true)
+ -> { warn('foo', **h) }.should complain("foo\n")
+ end
+
+ it "does not call Warning.warn if self is the Warning module" do
+ # RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here
+ code = <<-RUBY
+ def Warning.warn(*args, **kwargs)
+ raise 'should not be called'
+ end
+ Kernel.instance_method(:warn).bind(Warning).call('Kernel#warn spec edge case')
+ RUBY
+ out = ruby_exe(code, args: "2>&1", options: "--disable-gems")
+ out.should == "Kernel#warn spec edge case\n"
+ $?.should.success?
+ end
+
+ it "avoids recursion if Warning#warn is redefined and calls super" do
+ # This works because of the spec above, which is the workaround for it.
+ # Note that redefining Warning#warn is a mistake which would naturally end in infinite recursion,
+ # Warning.extend Module.new { def warn } should be used instead.
+ # RubyGems redefines Kernel#warn so we need to use a subprocess and disable RubyGems here
+ code = <<-RUBY
+ module Warning
+ def warn(*args, **kwargs)
+ super
+ end
end
+ warn "avoid infinite recursion"
+ RUBY
+ out = ruby_exe(code, args: "2>&1", options: "--disable-gems")
+ out.should == "avoid infinite recursion\n"
+ $?.should.success?
end
end
diff --git a/spec/ruby/core/kernel/yield_self_spec.rb b/spec/ruby/core/kernel/yield_self_spec.rb
index affedae144..e311dcee47 100644
--- a/spec/ruby/core/kernel/yield_self_spec.rb
+++ b/spec/ruby/core/kernel/yield_self_spec.rb
@@ -1,8 +1,6 @@
require_relative '../../spec_helper'
require_relative 'shared/then'
-ruby_version_is "2.5" do
- describe "Kernel#yield_self" do
- it_behaves_like :kernel_then, :yield_self
- end
+describe "Kernel#yield_self" do
+ it_behaves_like :kernel_then, :yield_self
end
diff --git a/spec/ruby/core/main/fixtures/classes.rb b/spec/ruby/core/main/fixtures/classes.rb
index 6aba948ce0..757cee4e4a 100644
--- a/spec/ruby/core/main/fixtures/classes.rb
+++ b/spec/ruby/core/main/fixtures/classes.rb
@@ -13,6 +13,14 @@ def main_public_method
end
public :main_public_method
+def main_public_method2
+end
+public :main_public_method2
+
def main_private_method
end
private :main_private_method
+
+def main_private_method2
+end
+private :main_private_method2
diff --git a/spec/ruby/core/main/private_spec.rb b/spec/ruby/core/main/private_spec.rb
index e34e0c7b7b..78c5d287d4 100644
--- a/spec/ruby/core/main/private_spec.rb
+++ b/spec/ruby/core/main/private_spec.rb
@@ -4,20 +4,41 @@ require_relative 'fixtures/classes'
describe "main#private" do
after :each do
Object.send(:public, :main_public_method)
+ Object.send(:public, :main_public_method2)
end
- it "sets the visibility of the given method to private" do
- eval "private :main_public_method", TOPLEVEL_BINDING
- Object.should have_private_method(:main_public_method)
+ context "when single argument is passed and it is not an array" do
+ it "sets the visibility of the given methods to private" do
+ eval "private :main_public_method", TOPLEVEL_BINDING
+ Object.should have_private_method(:main_public_method)
+ end
+ end
+
+ context "when multiple arguments are passed" do
+ it "sets the visibility of the given methods to private" do
+ eval "private :main_public_method, :main_public_method2", TOPLEVEL_BINDING
+ Object.should have_private_method(:main_public_method)
+ Object.should have_private_method(:main_public_method2)
+ end
+ end
+
+ ruby_version_is "3.0" do
+ context "when single argument is passed and is an array" do
+ it "sets the visibility of the given methods to private" do
+ eval "private [:main_public_method, :main_public_method2]", TOPLEVEL_BINDING
+ Object.should have_private_method(:main_public_method)
+ Object.should have_private_method(:main_public_method2)
+ end
+ end
end
it "returns Object" do
eval("private :main_public_method", TOPLEVEL_BINDING).should equal(Object)
end
- it "raises a NameError when given an undefined name" do
+ it "raises a NameError when at least one of given method names is undefined" do
-> do
- eval "private :main_undefined_method", TOPLEVEL_BINDING
+ eval "private :main_public_method, :main_undefined_method", TOPLEVEL_BINDING
end.should raise_error(NameError)
end
end
diff --git a/spec/ruby/core/main/public_spec.rb b/spec/ruby/core/main/public_spec.rb
index afe25c705a..bfc27a9e80 100644
--- a/spec/ruby/core/main/public_spec.rb
+++ b/spec/ruby/core/main/public_spec.rb
@@ -4,11 +4,32 @@ require_relative 'fixtures/classes'
describe "main#public" do
after :each do
Object.send(:private, :main_private_method)
+ Object.send(:private, :main_private_method2)
end
- it "sets the visibility of the given method to public" do
- eval "public :main_private_method", TOPLEVEL_BINDING
- Object.should_not have_private_method(:main_private_method)
+ context "when single argument is passed and it is not an array" do
+ it "sets the visibility of the given methods to public" do
+ eval "public :main_private_method", TOPLEVEL_BINDING
+ Object.should_not have_private_method(:main_private_method)
+ end
+ end
+
+ context "when multiple arguments are passed" do
+ it "sets the visibility of the given methods to public" do
+ eval "public :main_private_method, :main_private_method2", TOPLEVEL_BINDING
+ Object.should_not have_private_method(:main_private_method)
+ Object.should_not have_private_method(:main_private_method2)
+ end
+ end
+
+ ruby_version_is "3.0" do
+ context "when single argument is passed and is an array" do
+ it "sets the visibility of the given methods to public" do
+ eval "public [:main_private_method, :main_private_method2]", TOPLEVEL_BINDING
+ Object.should_not have_private_method(:main_private_method)
+ Object.should_not have_private_method(:main_private_method2)
+ end
+ end
end
it "returns Object" do
diff --git a/spec/ruby/core/marshal/dump_spec.rb b/spec/ruby/core/marshal/dump_spec.rb
index fc78ca4ff9..0e50df7227 100644
--- a/spec/ruby/core/marshal/dump_spec.rb
+++ b/spec/ruby/core/marshal/dump_spec.rb
@@ -15,8 +15,8 @@ describe "Marshal.dump" do
Marshal.dump(false).should == "\004\bF"
end
- describe "with a Fixnum" do
- it "dumps a Fixnum" do
+ describe "with an Integer" do
+ it "dumps an Integer" do
[ [Marshal, 0, "\004\bi\000"],
[Marshal, 5, "\004\bi\n"],
[Marshal, 8, "\004\bi\r"],
@@ -38,11 +38,11 @@ describe "Marshal.dump" do
end
platform_is wordsize: 64 do
- it "dumps a positive Fixnum > 31 bits as a Bignum" do
+ it "dumps a positive Integer > 31 bits as an Integer" do
Marshal.dump(2**31 + 1).should == "\x04\bl+\a\x01\x00\x00\x80"
end
- it "dumps a negative Fixnum > 31 bits as a Bignum" do
+ it "dumps a negative Integer > 31 bits as an Integer" do
Marshal.dump(-2**31 - 1).should == "\x04\bl-\a\x01\x00\x00\x80"
end
end
@@ -157,14 +157,14 @@ describe "Marshal.dump" do
end
end
- describe "with a Bignum" do
- it "dumps a Bignum" do
+ describe "with an Integer" do
+ it "dumps an Integer" do
[ [Marshal, -4611686018427387903, "\004\bl-\t\377\377\377\377\377\377\377?"],
[Marshal, -2361183241434822606847, "\004\bl-\n\377\377\377\377\377\377\377\377\177\000"],
].should be_computed_by(:dump)
end
- it "dumps a Bignum" do
+ it "dumps an Integer" do
[ [Marshal, 2**64, "\004\bl+\n\000\000\000\000\000\000\000\000\001\000"],
[Marshal, 2**90, "\004\bl+\v#{"\000" * 11}\004"],
[Marshal, -2**63, "\004\bl-\t\000\000\000\000\000\000\000\200"],
@@ -235,13 +235,13 @@ describe "Marshal.dump" do
end
it "dumps a Regexp with instance variables" do
- o = //
+ o = Regexp.new("")
o.instance_variable_set(:@ivar, :ivar)
Marshal.dump(o).should == "\x04\bI/\x00\x00\a:\x06EF:\n@ivar:\tivar"
end
it "dumps an extended Regexp" do
- Marshal.dump(//.extend(Meths)).should == "\x04\bIe:\nMeths/\x00\x00\x06:\x06EF"
+ Marshal.dump(Regexp.new("").extend(Meths)).should == "\x04\bIe:\nMeths/\x00\x00\x06:\x06EF"
end
it "dumps a Regexp subclass" do
@@ -411,13 +411,15 @@ describe "Marshal.dump" do
load.should == (1...2)
end
- it "dumps a Range with extra instance variables" do
- range = (1...3)
- range.instance_variable_set :@foo, 42
- dump = Marshal.dump(range)
- load = Marshal.load(dump)
- load.should == range
- load.instance_variable_get(:@foo).should == 42
+ ruby_version_is ""..."3.0" do
+ it "dumps a Range with extra instance variables" do
+ range = (1...3)
+ range.instance_variable_set :@foo, 42
+ dump = Marshal.dump(range)
+ load = Marshal.load(dump)
+ load.should == range
+ load.instance_variable_get(:@foo).should == 42
+ end
end
end
@@ -556,13 +558,10 @@ describe "Marshal.dump" do
end
describe "when passed a StringIO" do
-
it "should raise an error" do
require "stringio"
-
-> { Marshal.dump(StringIO.new) }.should raise_error(TypeError)
end
-
end
it "raises a TypeError if marshalling a Method instance" do
diff --git a/spec/ruby/core/marshal/fixtures/marshal_data.rb b/spec/ruby/core/marshal/fixtures/marshal_data.rb
index 2931278290..bf58f4888d 100644
--- a/spec/ruby/core/marshal/fixtures/marshal_data.rb
+++ b/spec/ruby/core/marshal/fixtures/marshal_data.rb
@@ -227,36 +227,36 @@ module MarshalSpec
"\004\b:\010big"],
"Symbol big" => [('big' * 100).to_sym,
"\004\b:\002,\001#{'big' * 100}"],
- "Bignum -2**64" => [-2**64,
+ "Integer -2**64" => [-2**64,
"\004\bl-\n\000\000\000\000\000\000\000\000\001\000"],
- "Bignum -2**63" => [-2**63,
+ "Integer -2**63" => [-2**63,
"\004\bl-\t\000\000\000\000\000\000\000\200"],
- "Fixnum -2**24" => [-2**24,
+ "Integer -2**24" => [-2**24,
"\004\bi\375\000\000\000"],
- "Fixnum -4516727" => [-4516727,
+ "Integer -4516727" => [-4516727,
"\004\bi\375\211\024\273"],
- "Fixnum -2**16" => [-2**16,
+ "Integer -2**16" => [-2**16,
"\004\bi\376\000\000"],
- "Fixnum -2**8" => [-2**8,
+ "Integer -2**8" => [-2**8,
"\004\bi\377\000"],
- "Fixnum -123" => [-123,
+ "Integer -123" => [-123,
"\004\bi\200"],
- "Fixnum -124" => [-124, "\004\bi\377\204"],
- "Fixnum 0" => [0,
+ "Integer -124" => [-124, "\004\bi\377\204"],
+ "Integer 0" => [0,
"\004\bi\000"],
- "Fixnum 5" => [5,
+ "Integer 5" => [5,
"\004\bi\n"],
- "Fixnum 122" => [122, "\004\bi\177"],
- "Fixnum 123" => [123, "\004\bi\001{"],
- "Fixnum 2**8" => [2**8,
+ "Integer 122" => [122, "\004\bi\177"],
+ "Integer 123" => [123, "\004\bi\001{"],
+ "Integer 2**8" => [2**8,
"\004\bi\002\000\001"],
- "Fixnum 2**16" => [2**16,
+ "Integer 2**16" => [2**16,
"\004\bi\003\000\000\001"],
- "Fixnum 2**24" => [2**24,
+ "Integer 2**24" => [2**24,
"\004\bi\004\000\000\000\001"],
- "Bignum 2**64" => [2**64,
+ "Integer 2**64" => [2**64,
"\004\bl+\n\000\000\000\000\000\000\000\000\001\000"],
- "Bignum 2**90" => [2**90,
+ "Integer 2**90" => [2**90,
"\004\bl+\v#{"\000" * 11}\004"],
"Class String" => [String,
"\004\bc\vString"],
@@ -334,31 +334,31 @@ module MarshalSpec
"\004\b:\010big"],
"Symbol big" => [('big' * 100).to_sym,
"\004\b:\002,\001#{'big' * 100}"],
- "Bignum -2**64" => [-2**64,
+ "Integer -2**64" => [-2**64,
"\004\bl-\n\000\000\000\000\000\000\000\000\001\000"],
- "Bignum -2**63" => [-2**63,
+ "Integer -2**63" => [-2**63,
"\004\bl-\t\000\000\000\000\000\000\000\200"],
- "Fixnum -2**24" => [-2**24,
+ "Integer -2**24" => [-2**24,
"\004\bi\375\000\000\000"],
- "Fixnum -2**16" => [-2**16,
+ "Integer -2**16" => [-2**16,
"\004\bi\376\000\000"],
- "Fixnum -2**8" => [-2**8,
+ "Integer -2**8" => [-2**8,
"\004\bi\377\000"],
- "Fixnum -123" => [-123,
+ "Integer -123" => [-123,
"\004\bi\200"],
- "Fixnum 0" => [0,
+ "Integer 0" => [0,
"\004\bi\000"],
- "Fixnum 5" => [5,
+ "Integer 5" => [5,
"\004\bi\n"],
- "Fixnum 2**8" => [2**8,
+ "Integer 2**8" => [2**8,
"\004\bi\002\000\001"],
- "Fixnum 2**16" => [2**16,
+ "Integer 2**16" => [2**16,
"\004\bi\003\000\000\001"],
- "Fixnum 2**24" => [2**24,
+ "Integer 2**24" => [2**24,
"\004\bi\004\000\000\000\001"],
- "Bignum 2**64" => [2**64,
+ "Integer 2**64" => [2**64,
"\004\bl+\n\000\000\000\000\000\000\000\000\001\000"],
- "Bignum 2**90" => [2**90,
+ "Integer 2**90" => [2**90,
"\004\bl+\v#{"\000" * 11}\004"],
"Class String" => [String,
"\004\bc\vString"],
diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb
index 7901c8773b..97023c1640 100644
--- a/spec/ruby/core/marshal/shared/load.rb
+++ b/spec/ruby/core/marshal/shared/load.rb
@@ -1,6 +1,5 @@
# -*- encoding: binary -*-
require_relative '../fixtures/marshal_data'
-require 'stringio'
describe :marshal_load, shared: true do
before :all do
@@ -43,18 +42,17 @@ describe :marshal_load, shared: true 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; arg })
- ret.first.should == 1
- ret[1].should == [1,a]
- ret[2].should == a
- ret.size.should == 3
- end
-
ruby_bug "#18141", ""..."3.1" do
+ it "calls the proc for recursively visited data" do
+ a = [1]
+ a << a
+ ret = []
+ Marshal.send(@method, Marshal.dump(a), proc { |arg| ret << arg.inspect; arg })
+ ret[0].should == 1.inspect
+ ret[1].should == a.inspect
+ ret.size.should == 2
+ end
+
it "loads an Array with proc" do
arr = []
s = 'hi'
@@ -68,13 +66,14 @@ 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; o}
+ 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, st, false, "none",
- :b, :c, a, 2, ["hi", 10, "hi", "hi", st, [:a, :b, :c]], false, "ant"]
-
+ 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
@@ -140,28 +139,39 @@ describe :marshal_load, shared: true do
end
end
- it "loads an array containing objects having _dump method, and with proc" do
- arr = []
- myproc = Proc.new { |o| arr << o; o }
- o1 = UserDefined.new;
- o2 = UserDefinedWithIvar.new
- obj = [o1, o2, o1, o2]
+ ruby_bug "#18141", ""..."3.1" do
+ it "loads an array containing objects having _dump method, and with proc" do
+ arr = []
+ myproc = Proc.new { |o| arr << o.dup; o }
+ o1 = UserDefined.new;
+ o2 = UserDefinedWithIvar.new
+ obj = [o1, o2, o1, o2]
- Marshal.send(@method, "\x04\b[\tu:\x10UserDefined\x18\x04\b[\aI\"\nstuff\x06:\x06EF@\x06u:\x18UserDefinedWithIvar>\x04\b[\bI\"\nstuff\a:\x06EF:\t@foo:\x18UserDefinedWithIvarI\"\tmore\x06;\x00F@\a@\x06@\a", myproc)
+ Marshal.send(@method, "\x04\b[\tu:\x10UserDefined\x18\x04\b[\aI\"\nstuff\x06:\x06EF@\x06u:\x18UserDefinedWithIvar>\x04\b[\bI\"\nstuff\a:\x06EF:\t@foo:\x18UserDefinedWithIvarI\"\tmore\x06;\x00F@\a@\x06@\a", myproc)
- arr.should == [o1, o2, o1, o2, obj]
- end
+ arr[0].should == o1
+ arr[1].should == o2
+ arr[2].should == obj
+ arr.size.should == 3
+ end
- it "loads an array containing objects having marshal_dump method, and with proc" do
- arr = []
- proc = Proc.new { |o| arr << o; o }
- o1 = UserMarshal.new
- o2 = UserMarshalWithIvar.new
- obj = [o1, o2, o1, o2]
+ 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.should == ['stuff', o1, 'my data', ['my data'], o2, o1, o2, obj]
+ 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
end
it "assigns classes to nested subclasses of Array correctly" do
@@ -232,14 +242,14 @@ describe :marshal_load, shared: true do
y.first.tainted?.should be_false
end
- it "does not taint Fixnums" do
+ it "does not taint Integers" do
x = [1]
y = Marshal.send(@method, Marshal.dump(x).taint)
y.tainted?.should be_true
y.first.tainted?.should be_false
end
- it "does not taint Bignums" do
+ it "does not taint Integers" do
x = [bignum_value]
y = Marshal.send(@method, Marshal.dump(x).taint)
y.tainted?.should be_true
@@ -430,8 +440,9 @@ describe :marshal_load, shared: true do
end
it "loads a string through StringIO stream" do
- obj = "This is a string which should be unmarshalled through StringIO stream!"
- Marshal.send(@method, StringIO.new(Marshal.dump(obj))).should == obj
+ require 'stringio'
+ obj = "This is a string which should be unmarshalled through StringIO stream!"
+ Marshal.send(@method, StringIO.new(Marshal.dump(obj))).should == obj
end
it "loads a string with an ivar" do
@@ -643,7 +654,7 @@ describe :marshal_load, shared: true do
describe "for a Regexp" do
it "loads an extended Regexp" do
- obj = /[a-z]/.extend(Meths, MethsMore)
+ obj = /[a-z]/.dup.extend(Meths, MethsMore)
new_obj = Marshal.send(@method, "\004\be:\nMethse:\016MethsMore/\n[a-z]\000")
new_obj.should == obj
@@ -687,7 +698,7 @@ describe :marshal_load, shared: true do
end
end
- describe "for a Integer" do
+ describe "for an Integer" do
it "loads 0" do
Marshal.send(@method, "\004\bi\000").should == 0
Marshal.send(@method, "\004\bi\005").should == 0
@@ -760,19 +771,19 @@ describe :marshal_load, shared: true do
end
end
- describe "for a Bignum" do
+ describe "for an Integer" do
platform_is wordsize: 64 do
- context "that is Bignum on 32-bit platforms but Fixnum on 64-bit" do
- it "dumps a Fixnum" do
+ context "that is Integer on 32-bit platforms but Integer on 64-bit" do
+ it "dumps an Integer" do
val = Marshal.send(@method, "\004\bl+\ab:wU")
val.should == 1433877090
- val.class.should == Fixnum
+ val.class.should == Integer
end
- it "dumps an array containing multiple references to the Bignum as an array of Fixnum" do
+ it "dumps an array containing multiple references to the Integer as an array of Integer" do
arr = Marshal.send(@method, "\004\b[\al+\a\223BwU@\006")
arr.should == [1433879187, 1433879187]
- arr.each { |v| v.class.should == Fixnum }
+ arr.each { |v| v.class.should == Integer }
end
end
end
diff --git a/spec/ruby/core/matchdata/string_spec.rb b/spec/ruby/core/matchdata/string_spec.rb
index db0d5dfbdc..420233e1f3 100644
--- a/spec/ruby/core/matchdata/string_spec.rb
+++ b/spec/ruby/core/matchdata/string_spec.rb
@@ -9,7 +9,7 @@ describe "MatchData#string" do
it "returns a frozen copy of the match string" do
str = /(.)(.)(\d+)(\d)/.match("THX1138.").string
str.should == "THX1138."
- str.frozen?.should == true
+ str.should.frozen?
end
it "returns the same frozen string for every call" do
@@ -20,6 +20,6 @@ describe "MatchData#string" do
it "returns a frozen copy of the matched string for gsub(String)" do
'he[[o'.gsub!('[', ']')
$~.string.should == 'he[[o'
- $~.string.frozen?.should == true
+ $~.string.should.frozen?
end
end
diff --git a/spec/ruby/core/math/tan_spec.rb b/spec/ruby/core/math/tan_spec.rb
index c7b188cd81..67307f1e6e 100644
--- a/spec/ruby/core/math/tan_spec.rb
+++ b/spec/ruby/core/math/tan_spec.rb
@@ -14,8 +14,8 @@ describe "Math.tan" do
end
it "returns NaN if called with +-Infinity" do
- Math.tan(infinity_value).nan?.should == true
- Math.tan(-infinity_value).nan?.should == true
+ Math.tan(infinity_value).should.nan?
+ Math.tan(-infinity_value).should.nan?
end
it "raises a TypeError if the argument cannot be coerced with Float()" do
diff --git a/spec/ruby/core/method/case_compare_spec.rb b/spec/ruby/core/method/case_compare_spec.rb
index 17785b5c1d..a78953e8ad 100644
--- a/spec/ruby/core/method/case_compare_spec.rb
+++ b/spec/ruby/core/method/case_compare_spec.rb
@@ -2,8 +2,6 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/call'
-ruby_version_is "2.5" do
- describe "Method#===" do
- it_behaves_like :method_call, :===
- end
+describe "Method#===" do
+ it_behaves_like :method_call, :===
end
diff --git a/spec/ruby/core/method/compose_spec.rb b/spec/ruby/core/method/compose_spec.rb
index aa0aded775..0743dd4f8d 100644
--- a/spec/ruby/core/method/compose_spec.rb
+++ b/spec/ruby/core/method/compose_spec.rb
@@ -39,7 +39,8 @@ ruby_version_is "2.6" do
double = proc { |x| x + x }
(pow_2 << double).is_a?(Proc).should == true
- (pow_2 << double).lambda?.should == true
+ ruby_version_is(''...'3.0') { (pow_2 << double).should.lambda? }
+ ruby_version_is('3.0') { (pow_2 << double).should_not.lambda? }
end
it "may accept multiple arguments" do
@@ -87,7 +88,7 @@ ruby_version_is "2.6" do
double = proc { |x| x + x }
(pow_2 >> double).is_a?(Proc).should == true
- (pow_2 >> double).lambda?.should == true
+ (pow_2 >> double).should.lambda?
end
it "may accept multiple arguments" do
diff --git a/spec/ruby/core/method/fixtures/classes.rb b/spec/ruby/core/method/fixtures/classes.rb
index f3b7ff921c..be96f65e25 100644
--- a/spec/ruby/core/method/fixtures/classes.rb
+++ b/spec/ruby/core/method/fixtures/classes.rb
@@ -50,6 +50,8 @@ module MethodSpecs
def one_req(a); end
def two_req(a, b); end
+ def one_req_named(a:); end
+
def zero_with_block(&blk); end
def one_req_with_block(a, &blk); end
def two_req_with_block(a, b, &blk); end
@@ -59,6 +61,8 @@ module MethodSpecs
def one_req_two_opt(a, b=nil, c=nil); end
def two_req_one_opt(a, b, c=nil); end
+ def one_opt_named(a: nil); end
+
def one_opt_with_block(a=nil, &blk); end
def one_req_one_opt_with_block(a, b=nil, &blk); end
def one_req_two_opt_with_block(a, b=nil, c=nil, &blk); end
@@ -71,6 +75,8 @@ module MethodSpecs
def two_req_one_opt_with_splat(a, b, c=nil, *d); end
def one_req_two_opt_with_splat(a, b=nil, c=nil, *d); end
+ def zero_with_double_splat(**a); end
+
def zero_with_splat_and_block(*a, &blk); end
def one_req_with_splat_and_block(a, *b, &blk); end
def two_req_with_splat_and_block(a, b, *c, &blk); end
diff --git a/spec/ruby/core/method/shared/to_s.rb b/spec/ruby/core/method/shared/to_s.rb
index 373398a785..8f7dd8c161 100644
--- a/spec/ruby/core/method/shared/to_s.rb
+++ b/spec/ruby/core/method/shared/to_s.rb
@@ -4,7 +4,7 @@ require_relative '../fixtures/classes'
describe :method_to_s, shared: true do
before :each do
@m = MethodSpecs::MySub.new.method :bar
- @string = @m.send(@method).sub(/0x\w+/, '0xXXXXXX')
+ @string = @m.send(@method)
end
it "returns a String" do
@@ -24,6 +24,21 @@ describe :method_to_s, shared: true do
@string.should =~ /\#bar/
end
+ ruby_version_is "2.7" do
+ it "returns a String containing method arguments" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:zero).send(@method).should.include?("()")
+ obj.method(:one_req).send(@method).should.include?("(a)")
+ obj.method(:one_req_named).send(@method).should.include?("(a:)")
+ obj.method(:zero_with_block).send(@method).should.include?("(&blk)")
+ obj.method(:one_opt).send(@method).should.include?("(a=...)")
+ obj.method(:one_opt_named).send(@method).should.include?("(a: ...)")
+ obj.method(:zero_with_splat).send(@method).should.include?("(*a)")
+ obj.method(:zero_with_double_splat).send(@method).should.include?("(**a)")
+ obj.method(:one_req_one_opt_with_splat_and_block).send(@method).should.include?("(a, b=..., *c, &blk)")
+ end
+ end
+
it "returns a String containing the Module the method is defined in" do
@string.should =~ /MethodSpecs::MyMod/
end
@@ -31,4 +46,36 @@ describe :method_to_s, shared: true do
it "returns a String containing the Module the method is referenced from" do
@string.should =~ /MethodSpecs::MySub/
end
+
+ it "returns a String including all details" do
+ @string.should.start_with? "#<Method: MethodSpecs::MySub(MethodSpecs::MyMod)#bar"
+ end
+
+ it "does not show the defining module if it is the same as the receiver class" do
+ MethodSpecs::A.new.method(:baz).send(@method).should.start_with? "#<Method: MethodSpecs::A#baz"
+ end
+
+ ruby_version_is '3.0' do
+ it "returns a String containing the Module containing the method if object has a singleton class but method is not defined in the singleton class" do
+ obj = MethodSpecs::MySub.new
+ obj.singleton_class
+ @m = obj.method(:bar)
+ @string = @m.send(@method)
+ @string.should.start_with? "#<Method: MethodSpecs::MySub(MethodSpecs::MyMod)#bar"
+
+ c = MethodSpecs::MySub.dup
+ m = Module.new{def bar; end}
+ c.extend(m)
+ @string = c.method(:bar).send(@method)
+ @string.should.start_with? "#<Method: #<Class:#{c.inspect}>(#{m.inspect})#bar"
+ end
+ end
+
+ it "returns a String containing the singleton class if method is defined in the singleton class" do
+ obj = MethodSpecs::MySub.new
+ def obj.bar; end
+ @m = obj.method(:bar)
+ @string = @m.send(@method).sub(/0x\h+/, '0xXXXXXX')
+ @string.should.start_with? "#<Method: #<MethodSpecs::MySub:0xXXXXXX>.bar"
+ end
end
diff --git a/spec/ruby/core/method/source_location_spec.rb b/spec/ruby/core/method/source_location_spec.rb
index dd81b02c77..1f476aaa9b 100644
--- a/spec/ruby/core/method/source_location_spec.rb
+++ b/spec/ruby/core/method/source_location_spec.rb
@@ -16,9 +16,9 @@ describe "Method#source_location" do
file.should == File.realpath('../fixtures/classes.rb', __FILE__)
end
- it "sets the last value to a Fixnum representing the line on which the method was defined" do
+ it "sets the last value to an Integer representing the line on which the method was defined" do
line = @method.source_location.last
- line.should be_an_instance_of(Fixnum)
+ line.should be_an_instance_of(Integer)
line.should == 5
end
@@ -86,6 +86,24 @@ describe "Method#source_location" do
method.source_location[1].should == line
end
+ it "works for core methods where it returns nil or <internal:" do
+ loc = method(:__id__).source_location
+ if loc == nil
+ loc.should == nil
+ else
+ loc[0].should.start_with?('<internal:')
+ loc[1].should be_kind_of(Integer)
+ end
+
+ loc = method(:tap).source_location
+ if loc == nil
+ loc.should == nil
+ else
+ loc[0].should.start_with?('<internal:')
+ loc[1].should be_kind_of(Integer)
+ end
+ end
+
describe "for a Method generated by respond_to_missing?" do
it "returns nil" do
m = MethodSpecs::Methods.new
diff --git a/spec/ruby/core/module/alias_method_spec.rb b/spec/ruby/core/module/alias_method_spec.rb
index 662e91011f..5d3d0c23d9 100644
--- a/spec/ruby/core/module/alias_method_spec.rb
+++ b/spec/ruby/core/module/alias_method_spec.rb
@@ -42,6 +42,18 @@ describe "Module#alias_method" do
@object.was_private_one.should == 1
end
+ it "handles aliasing a method only present in a refinement" do
+ c = @class
+ Module.new do
+ refine c do
+ def uno_refined_method
+ end
+ alias_method :double_refined_method, :uno_refined_method
+ instance_method(:uno_refined_method).should == instance_method(:double_refined_method)
+ end
+ end
+ end
+
it "fails if origin method not found" do
-> { @class.make_alias :ni, :san }.should raise_error(NameError) { |e|
# a NameError and not a NoMethodError
@@ -49,9 +61,9 @@ describe "Module#alias_method" do
}
end
- it "raises #{frozen_error_class} if frozen" do
+ it "raises FrozenError if frozen" do
@class.freeze
- -> { @class.make_alias :uno, :public_one }.should raise_error(frozen_error_class)
+ -> { @class.make_alias :uno, :public_one }.should raise_error(FrozenError)
end
it "converts the names using #to_str" do
@@ -69,19 +81,23 @@ describe "Module#alias_method" do
-> { @class.make_alias mock('x'), :public_one }.should raise_error(TypeError)
end
- ruby_version_is ''...'2.5' do
- it "is a private method" do
- -> { @class.alias_method :ichi, :public_one }.should raise_error(NoMethodError)
- end
+ it "is a public method" do
+ Module.should have_public_instance_method(:alias_method, false)
end
- ruby_version_is '2.5' do
- it "is a public method" do
- Module.should have_public_instance_method(:alias_method, false)
+
+ describe "returned value" do
+ ruby_version_is ""..."3.0" do
+ it "returns self" do
+ @class.send(:alias_method, :checking_return_value, :public_one).should equal(@class)
+ end
end
- end
- it "returns self" do
- @class.send(:alias_method, :checking_return_value, :public_one).should equal(@class)
+ ruby_version_is "3.0" do
+ it "returns symbol of the defined method name" do
+ @class.send(:alias_method, :checking_return_value, :public_one).should equal(:checking_return_value)
+ @class.send(:alias_method, 'checking_return_value', :public_one).should equal(:checking_return_value)
+ end
+ end
end
it "works in module" do
diff --git a/spec/ruby/core/module/append_features_spec.rb b/spec/ruby/core/module/append_features_spec.rb
index 8fb3febc04..d960798eef 100644
--- a/spec/ruby/core/module/append_features_spec.rb
+++ b/spec/ruby/core/module/append_features_spec.rb
@@ -67,8 +67,8 @@ describe "Module#append_features" do
@other = Module.new.freeze
end
- it "raises a #{frozen_error_class} before appending self" do
- -> { @receiver.send(:append_features, @other) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError before appending self" do
+ -> { @receiver.send(:append_features, @other) }.should raise_error(FrozenError)
@other.ancestors.should_not include(@receiver)
end
end
diff --git a/spec/ruby/core/module/attr_accessor_spec.rb b/spec/ruby/core/module/attr_accessor_spec.rb
index ce95ccd487..e6a6ac7b66 100644
--- a/spec/ruby/core/module/attr_accessor_spec.rb
+++ b/spec/ruby/core/module/attr_accessor_spec.rb
@@ -36,7 +36,7 @@ describe "Module#attr_accessor" do
-> { true.spec_attr_accessor = "a" }.should raise_error(RuntimeError)
end
- it "converts non string/symbol/fixnum names to strings using to_str" do
+ it "converts non string/symbol names to strings using to_str" do
(o = mock('test')).should_receive(:to_str).any_number_of_times.and_return("test")
c = Class.new do
attr_accessor o
@@ -63,30 +63,39 @@ describe "Module#attr_accessor" do
-> { c.new.foo=1 }.should raise_error(NoMethodError)
end
- ruby_version_is ''...'2.5' do
- it "is a private method" do
- Module.should have_private_instance_method(:attr_accessor, false)
+ it "is a public method" do
+ Module.should have_public_instance_method(:attr_accessor, false)
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "returns nil" do
+ Class.new do
+ (attr_accessor :foo, 'bar').should == nil
+ end
end
end
- ruby_version_is '2.5' do
- it "is a public method" do
- Module.should have_public_instance_method(:attr_accessor, false)
+
+ ruby_version_is "3.0" do
+ it "returns an array of defined method names as symbols" do
+ Class.new do
+ (attr_accessor :foo, 'bar').should == [:foo, :foo=, :bar, :bar=]
+ end
end
end
describe "on immediates" do
before :each do
- class Fixnum
+ class Integer
attr_accessor :foobar
end
end
after :each do
- if Fixnum.method_defined?(:foobar)
- Fixnum.send(:remove_method, :foobar)
+ if Integer.method_defined?(:foobar)
+ Integer.send(:remove_method, :foobar)
end
- if Fixnum.method_defined?(:foobar=)
- Fixnum.send(:remove_method, :foobar=)
+ if Integer.method_defined?(:foobar=)
+ Integer.send(:remove_method, :foobar=)
end
end
diff --git a/spec/ruby/core/module/attr_reader_spec.rb b/spec/ruby/core/module/attr_reader_spec.rb
index 082bc03b60..b0ae906ab5 100644
--- a/spec/ruby/core/module/attr_reader_spec.rb
+++ b/spec/ruby/core/module/attr_reader_spec.rb
@@ -32,7 +32,7 @@ describe "Module#attr_reader" do
-> { true.instance_variable_set("@spec_attr_reader", "a") }.should raise_error(RuntimeError)
end
- it "converts non string/symbol/fixnum names to strings using to_str" do
+ it "converts non string/symbol names to strings using to_str" do
(o = mock('test')).should_receive(:to_str).any_number_of_times.and_return("test")
c = Class.new do
attr_reader o
@@ -58,14 +58,23 @@ describe "Module#attr_reader" do
-> { c.new.foo }.should raise_error(NoMethodError)
end
- ruby_version_is ''...'2.5' do
- it "is a private method" do
- Module.should have_private_instance_method(:attr_reader, false)
+ it "is a public method" do
+ Module.should have_public_instance_method(:attr_reader, false)
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "returns nil" do
+ Class.new do
+ (attr_reader :foo, 'bar').should == nil
+ end
end
end
- ruby_version_is '2.5' do
- it "is a public method" do
- Module.should have_public_instance_method(:attr_reader, false)
+
+ ruby_version_is "3.0" do
+ it "returns an array of defined method names as symbols" do
+ Class.new do
+ (attr_reader :foo, 'bar').should == [:foo, :bar]
+ end
end
end
end
diff --git a/spec/ruby/core/module/attr_spec.rb b/spec/ruby/core/module/attr_spec.rb
index 20316a3d39..33e0eb8628 100644
--- a/spec/ruby/core/module/attr_spec.rb
+++ b/spec/ruby/core/module/attr_spec.rb
@@ -124,7 +124,7 @@ describe "Module#attr" do
-> { c.new.bar }.should raise_error(NoMethodError)
end
- it "converts non string/symbol/fixnum names to strings using to_str" do
+ it "converts non string/symbol names to strings using to_str" do
(o = mock('test')).should_receive(:to_str).any_number_of_times.and_return("test")
Class.new { attr o }.new.respond_to?("test").should == true
end
@@ -142,14 +142,27 @@ describe "Module#attr" do
}.should complain(/boolean argument is obsoleted/, verbose: true)
end
- ruby_version_is ''...'2.5' do
- it "is a private method" do
- Module.should have_private_instance_method(:attr, false)
+ it "is a public method" do
+ Module.should have_public_instance_method(:attr, false)
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "returns nil" do
+ Class.new do
+ (attr :foo, 'bar').should == nil
+ (attr :baz, false).should == nil
+ (attr :qux, true).should == nil
+ end
end
end
- ruby_version_is '2.5' do
- it "is a public method" do
- Module.should have_public_instance_method(:attr, false)
+
+ ruby_version_is "3.0" do
+ it "returns an array of defined method names as symbols" do
+ Class.new do
+ (attr :foo, 'bar').should == [:foo, :bar]
+ (attr :baz, false).should == [:baz]
+ (attr :qux, true).should == [:qux, :qux=]
+ end
end
end
end
diff --git a/spec/ruby/core/module/attr_writer_spec.rb b/spec/ruby/core/module/attr_writer_spec.rb
index 3b110cecf7..dbf30c8144 100644
--- a/spec/ruby/core/module/attr_writer_spec.rb
+++ b/spec/ruby/core/module/attr_writer_spec.rb
@@ -32,7 +32,7 @@ describe "Module#attr_writer" do
-> { true.spec_attr_writer = "a" }.should raise_error(RuntimeError)
end
- it "converts non string/symbol/fixnum names to strings using to_str" do
+ it "converts non string/symbol names to strings using to_str" do
(o = mock('test')).should_receive(:to_str).any_number_of_times.and_return("test")
c = Class.new do
attr_writer o
@@ -58,14 +58,23 @@ describe "Module#attr_writer" do
-> { c.new.foo=1 }.should raise_error(NoMethodError)
end
- ruby_version_is ''...'2.5' do
- it "is a private method" do
- Module.should have_private_instance_method(:attr_writer, false)
+ it "is a public method" do
+ Module.should have_public_instance_method(:attr_writer, false)
+ end
+
+ ruby_version_is ""..."3.0" do
+ it "returns nil" do
+ Class.new do
+ (attr_writer :foo, 'bar').should == nil
+ end
end
end
- ruby_version_is '2.5' do
- it "is a public method" do
- Module.should have_public_instance_method(:attr_writer, false)
+
+ ruby_version_is "3.0" do
+ it "returns an array of defined method names as symbols" do
+ Class.new do
+ (attr_writer :foo, 'bar').should == [:foo=, :bar=]
+ end
end
end
end
diff --git a/spec/ruby/core/module/autoload_spec.rb b/spec/ruby/core/module/autoload_spec.rb
index 9964602347..f17675846b 100644
--- a/spec/ruby/core/module/autoload_spec.rb
+++ b/spec/ruby/core/module/autoload_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative '../../fixtures/code_loading'
require_relative 'fixtures/classes'
require 'thread'
@@ -33,14 +34,7 @@ end
describe "Module#autoload" do
before :all do
@non_existent = fixture __FILE__, "no_autoload.rb"
-
- # Require RubyGems eagerly, to ensure #require is already the RubyGems
- # version, before starting #autoload specs which snapshot #require, and
- # could end up redefining #require as the original core Kernel#require.
- begin
- require "rubygems"
- rescue LoadError
- end
+ CodeLoadingSpecs.preload_rubygems
end
before :each do
@@ -210,6 +204,13 @@ describe "Module#autoload" do
ModuleSpecs::Autoload.use_ex1.should == :good
end
+ it "considers an autoload constant as loaded when autoload is called for/from the current file" do
+ filename = fixture(__FILE__, "autoload_during_require_current_file.rb")
+ require filename
+
+ ScratchPad.recorded.should be_nil
+ end
+
describe "interacting with defined?" do
it "does not load the file when referring to the constant in defined?" do
module ModuleSpecs::Autoload::Dog
@@ -294,6 +295,32 @@ describe "Module#autoload" do
ScratchPad.recorded.should == [nil, nil]
@check.call.should == ["constant", nil]
end
+
+ it "does not raise an error if the autoload constant was not defined" do
+ module ModuleSpecs::Autoload
+ autoload :RequiredDirectlyNoConstant, fixture(__FILE__, "autoload_required_directly_no_constant.rb")
+ end
+ @path = fixture(__FILE__, "autoload_required_directly_no_constant.rb")
+ @remove << :RequiredDirectlyNoConstant
+ @check = -> {
+ [
+ defined?(ModuleSpecs::Autoload::RequiredDirectlyNoConstant),
+ ModuleSpecs::Autoload.constants(false).include?(:RequiredDirectlyNoConstant),
+ ModuleSpecs::Autoload.const_defined?(:RequiredDirectlyNoConstant),
+ ModuleSpecs::Autoload.autoload?(:RequiredDirectlyNoConstant)
+ ]
+ }
+ ScratchPad.record @check
+ @check.call.should == ["constant", true, true, @path]
+ $:.push File.dirname(@path)
+ begin
+ require "autoload_required_directly_no_constant.rb"
+ ensure
+ $:.pop
+ end
+ ScratchPad.recorded.should == [nil, true, false, nil]
+ @check.call.should == [nil, true, false, nil]
+ end
end
describe "after the autoload is triggered by require" do
@@ -737,9 +764,9 @@ describe "Module#autoload" do
end
describe "on a frozen module" do
- it "raises a #{frozen_error_class} before setting the name" do
+ it "raises a FrozenError before setting the name" do
frozen_module = Module.new.freeze
- -> { frozen_module.autoload :Foo, @non_existent }.should raise_error(frozen_error_class)
+ -> { frozen_module.autoload :Foo, @non_existent }.should raise_error(FrozenError)
frozen_module.should_not have_constant(:Foo)
end
end
diff --git a/spec/ruby/core/module/class_variable_defined_spec.rb b/spec/ruby/core/module/class_variable_defined_spec.rb
index f867d383c3..c0f2072a37 100644
--- a/spec/ruby/core/module/class_variable_defined_spec.rb
+++ b/spec/ruby/core/module/class_variable_defined_spec.rb
@@ -51,7 +51,7 @@ describe "Module#class_variable_defined?" do
}.should raise_error(NameError)
end
- it "converts a non string/symbol/fixnum name to string using to_str" do
+ it "converts a non string/symbol name to string using to_str" do
c = Class.new { class_variable_set :@@class_var, "test" }
(o = mock('@@class_var')).should_receive(:to_str).and_return("@@class_var")
c.class_variable_defined?(o).should == true
diff --git a/spec/ruby/core/module/class_variable_get_spec.rb b/spec/ruby/core/module/class_variable_get_spec.rb
index 79d22a506b..e5d06731ec 100644
--- a/spec/ruby/core/module/class_variable_get_spec.rb
+++ b/spec/ruby/core/module/class_variable_get_spec.rb
@@ -60,7 +60,7 @@ describe "Module#class_variable_get" do
-> { c.send(:class_variable_get, "@invalid_name") }.should raise_error(NameError)
end
- it "converts a non string/symbol/fixnum name to string using to_str" do
+ it "converts a non string/symbol name to string using to_str" do
c = Class.new { class_variable_set :@@class_var, "test" }
(o = mock('@@class_var')).should_receive(:to_str).and_return("@@class_var")
c.send(:class_variable_get, o).should == "test"
diff --git a/spec/ruby/core/module/class_variable_set_spec.rb b/spec/ruby/core/module/class_variable_set_spec.rb
index 204bbaf75e..63f32f5389 100644
--- a/spec/ruby/core/module/class_variable_set_spec.rb
+++ b/spec/ruby/core/module/class_variable_set_spec.rb
@@ -25,13 +25,13 @@ describe "Module#class_variable_set" do
c.send(:class_variable_get, "@@mvar").should == :new_mvar
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
-> {
Class.new.freeze.send(:class_variable_set, :@@test, "test")
- }.should raise_error(frozen_error_class)
+ }.should raise_error(FrozenError)
-> {
Module.new.freeze.send(:class_variable_set, :@@test, "test")
- }.should raise_error(frozen_error_class)
+ }.should raise_error(FrozenError)
end
it "raises a NameError when the given name is not allowed" do
@@ -45,7 +45,7 @@ describe "Module#class_variable_set" do
}.should raise_error(NameError)
end
- it "converts a non string/symbol/fixnum name to string using to_str" do
+ it "converts a non string/symbol name to string using to_str" do
(o = mock('@@class_var')).should_receive(:to_str).and_return("@@class_var")
c = Class.new
c.send(:class_variable_set, o, "test")
diff --git a/spec/ruby/core/module/const_set_spec.rb b/spec/ruby/core/module/const_set_spec.rb
index 1b8b86dd04..b537d3f133 100644
--- a/spec/ruby/core/module/const_set_spec.rb
+++ b/spec/ruby/core/module/const_set_spec.rb
@@ -20,10 +20,20 @@ describe "Module#const_set" do
m.name.should == "ConstantSpecs::CS_CONST1000"
end
- it "does not set the name of a module scoped by an anonymous module" do
- a, b = Module.new, Module.new
- a.const_set :B, b
- b.name.should be_nil
+ ruby_version_is ""..."3.0" do
+ it "does not set the name of a module scoped by an anonymous module" do
+ a, b = Module.new, Module.new
+ a.const_set :B, b
+ b.name.should be_nil
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "sets the name of a module scoped by an anonymous module" do
+ a, b = Module.new, Module.new
+ a.const_set :B, b
+ b.name.should.end_with? '::B'
+ end
end
it "sets the name of contained modules when assigning a toplevel anonymous module" do
@@ -125,8 +135,8 @@ describe "Module#const_set" do
@name = :Foo
end
- it "raises a #{frozen_error_class} before setting the name" do
- -> { @frozen.const_set @name, nil }.should raise_error(frozen_error_class)
+ it "raises a FrozenError before setting the name" do
+ -> { @frozen.const_set @name, nil }.should raise_error(FrozenError)
@frozen.should_not have_constant(@name)
end
end
diff --git a/spec/ruby/core/module/const_source_location_spec.rb b/spec/ruby/core/module/const_source_location_spec.rb
new file mode 100644
index 0000000000..9e1f2c1c49
--- /dev/null
+++ b/spec/ruby/core/module/const_source_location_spec.rb
@@ -0,0 +1,220 @@
+require_relative '../../spec_helper'
+require_relative '../../fixtures/constants'
+
+describe "Module#const_source_location" do
+ before do
+ @constants_fixture_path = File.expand_path('../../fixtures/constants.rb', __dir__)
+ end
+
+ ruby_version_is "2.7" do
+ describe "with dynamically assigned constants" do
+ it "searches a path in the immediate class or module first" do
+ ConstantSpecs::ClassA::CSL_CONST301 = :const301_1
+ ConstantSpecs::ClassA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+
+ ConstantSpecs::ModuleA::CSL_CONST301 = :const301_2
+ ConstantSpecs::ModuleA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+
+ ConstantSpecs::ParentA::CSL_CONST301 = :const301_3
+ ConstantSpecs::ParentA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+
+ ConstantSpecs::ContainerA::ChildA::CSL_CONST301 = :const301_5
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "searches a path in a module included in the immediate class before the superclass" do
+ ConstantSpecs::ParentB::CSL_CONST302 = :const302_1
+ ConstantSpecs::ModuleF::CSL_CONST302 = :const302_2
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST302).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "searches a path in the superclass before a module included in the superclass" do
+ ConstantSpecs::ModuleE::CSL_CONST303 = :const303_1
+ ConstantSpecs::ParentB::CSL_CONST303 = :const303_2
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST303).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "searches a path in a module included in the superclass" do
+ ConstantSpecs::ModuleA::CSL_CONST304 = :const304_1
+ ConstantSpecs::ModuleE::CSL_CONST304 = :const304_2
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST304).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "searches a path in the superclass chain" do
+ ConstantSpecs::ModuleA::CSL_CONST305 = :const305
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST305).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "returns path to a toplevel constant when the receiver is a Class" do
+ Object::CSL_CONST306 = :const306
+ ConstantSpecs::ContainerB::ChildB.const_source_location(:CSL_CONST306).should == [__FILE__, __LINE__ - 1]
+ end
+
+ it "returns path to a toplevel constant when the receiver is a Module" do
+ Object::CSL_CONST308 = :const308
+ ConstantSpecs.const_source_location(:CSL_CONST308).should == [__FILE__, __LINE__ - 1]
+ ConstantSpecs::ModuleA.const_source_location(:CSL_CONST308).should == [__FILE__, __LINE__ - 2]
+ end
+
+ it "returns path to the updated value of a constant" do
+ ConstantSpecs::ClassB::CSL_CONST309 = :const309_1
+ ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 1]
+
+ -> {
+ ConstantSpecs::ClassB::CSL_CONST309 = :const309_2
+ }.should complain(/already initialized constant/)
+ ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 2]
+ end
+ end
+
+ describe "with statically assigned constants" do
+ it "searches location path the immediate class or module first" do
+ ConstantSpecs::ClassA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CONST10_LINE]
+ ConstantSpecs::ModuleA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ModuleA::CS_CONST10_LINE]
+ ConstantSpecs::ParentA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST10_LINE]
+ ConstantSpecs::ContainerA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ContainerA::CS_CONST10_LINE]
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST10).should == [@constants_fixture_path, ConstantSpecs::ContainerA::ChildA::CS_CONST10_LINE]
+ end
+
+ it "searches location path a module included in the immediate class before the superclass" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST15).should == [@constants_fixture_path, ConstantSpecs::ModuleC::CS_CONST15_LINE]
+ end
+
+ it "searches location path the superclass before a module included in the superclass" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST11).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST11_LINE]
+ end
+
+ it "searches location path a module included in the superclass" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST12).should == [@constants_fixture_path, ConstantSpecs::ModuleB::CS_CONST12_LINE]
+ end
+
+ it "searches location path the superclass chain" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST13).should == [@constants_fixture_path, ConstantSpecs::ModuleA::CS_CONST13_LINE]
+ end
+
+ it "returns location path a toplevel constant when the receiver is a Class" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE]
+ end
+
+ it "returns location path a toplevel constant when the receiver is a Module" do
+ ConstantSpecs.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE]
+ ConstantSpecs::ModuleA.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE]
+ end
+ end
+
+ it "return empty path if constant defined in C code" do
+ Object.const_source_location(:String).should == []
+ end
+
+ it "accepts a String or Symbol name" do
+ Object.const_source_location(:CS_CONST1).should == [@constants_fixture_path, CS_CONST1_LINE]
+ Object.const_source_location("CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE]
+ end
+
+ it "returns nil if no constant is defined in the search path" do
+ ConstantSpecs.const_source_location(:CS_CONSTX).should == nil
+ end
+
+ it "raises a NameError if the name does not start with a capital letter" do
+ -> { ConstantSpecs.const_source_location "name" }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if the name starts with a non-alphabetic character" do
+ -> { ConstantSpecs.const_source_location "__CONSTX__" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location "@CS_CONST1" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location "!CS_CONST1" }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if the name contains non-alphabetic characters except '_'" do
+ Object.const_source_location("CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE]
+ -> { ConstantSpecs.const_source_location "CS_CONST1=" }.should raise_error(NameError)
+ -> { ConstantSpecs.const_source_location "CS_CONST1?" }.should raise_error(NameError)
+ end
+
+ it "calls #to_str to convert the given name to a String" do
+ name = mock("ClassA")
+ name.should_receive(:to_str).and_return("ClassA")
+ ConstantSpecs.const_source_location(name).should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CLASS_A_LINE]
+ end
+
+ it "raises a TypeError if conversion to a String by calling #to_str fails" do
+ name = mock('123')
+ -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError)
+
+ name.should_receive(:to_str).and_return(123)
+ -> { ConstantSpecs.const_source_location(name) }.should raise_error(TypeError)
+ end
+
+ it "does not search the singleton class of a Class or Module" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST14).should == nil
+ ConstantSpecs.const_source_location(:CS_CONST14).should == nil
+ end
+
+ it "does not search the containing scope" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST20).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST20_LINE]
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST5) == nil
+ end
+
+ it "returns nil if the constant is defined in the receiver's superclass and the inherit flag is false" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST4, false).should == nil
+ end
+
+ it "searches into the receiver superclasses if the inherit flag is true" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST4, true).should == [@constants_fixture_path, ConstantSpecs::ParentA::CS_CONST4_LINE]
+ end
+
+ it "returns nil when the receiver is a Module, the constant is defined at toplevel and the inherit flag is false" do
+ ConstantSpecs::ModuleA.const_source_location(:CS_CONST1, false).should == nil
+ end
+
+ it "returns nil when the receiver is a Class, the constant is defined at toplevel and the inherit flag is false" do
+ ConstantSpecs::ContainerA::ChildA.const_source_location(:CS_CONST1, false).should == nil
+ end
+
+ it "accepts a toplevel scope qualifier" do
+ ConstantSpecs.const_source_location("::CS_CONST1").should == [@constants_fixture_path, CS_CONST1_LINE]
+ end
+
+ it "accepts a scoped constant name" do
+ ConstantSpecs.const_source_location("ClassA::CS_CONST10").should == [@constants_fixture_path, ConstantSpecs::ClassA::CS_CONST10_LINE]
+ end
+
+ it "raises a NameError if the name includes two successive scope separators" do
+ -> { ConstantSpecs.const_source_location("ClassA::::CS_CONST10") }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if only '::' is passed" do
+ -> { ConstantSpecs.const_source_location("::") }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if a Symbol has a toplevel scope qualifier" do
+ -> { ConstantSpecs.const_source_location(:'::CS_CONST1') }.should raise_error(NameError)
+ end
+
+ it "raises a NameError if a Symbol is a scoped constant name" do
+ -> { ConstantSpecs.const_source_location(:'ClassA::CS_CONST10') }.should raise_error(NameError)
+ end
+
+ it "does search private constants path" do
+ ConstantSpecs.const_source_location(:CS_PRIVATE).should == [@constants_fixture_path, ConstantSpecs::CS_PRIVATE_LINE]
+ end
+
+ context 'autoload' do
+ before :all do
+ ConstantSpecs.autoload :CSL_CONST1, "#{__dir__}/notexisting.rb"
+ @line = __LINE__ - 1
+ end
+
+ it 'returns the autoload location while not resolved' do
+ ConstantSpecs.const_source_location('CSL_CONST1').should == [__FILE__, @line]
+ end
+
+ it 'returns where the constant was resolved when resolved' do
+ file = fixture(__FILE__, 'autoload_location.rb')
+ ConstantSpecs.autoload :CONST_LOCATION, file
+ line = ConstantSpecs::CONST_LOCATION
+ ConstantSpecs.const_source_location('CONST_LOCATION').should == [file, line]
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/module/constants_spec.rb b/spec/ruby/core/module/constants_spec.rb
index 4538e828dd..fe95143872 100644
--- a/spec/ruby/core/module/constants_spec.rb
+++ b/spec/ruby/core/module/constants_spec.rb
@@ -13,9 +13,9 @@ describe "Module.constants" do
it "returns an array of Symbol names" do
# This in NOT an exhaustive list
- Module.constants.should include(:Array, :Bignum, :Class, :Comparable, :Dir,
+ Module.constants.should include(:Array, :Class, :Comparable, :Dir,
:Enumerable, :ENV, :Exception, :FalseClass,
- :File, :Fixnum, :Float, :Hash, :Integer, :IO,
+ :File, :Float, :Hash, :Integer, :IO,
:Kernel, :Math, :Method, :Module, :NilClass,
:Numeric, :Object, :Range, :Regexp, :String,
:Symbol, :Thread, :Time, :TrueClass)
@@ -43,31 +43,31 @@ end
describe "Module#constants" do
it "returns an array of Symbol names of all constants defined in the module and all included modules" do
ConstantSpecs::ContainerA.constants.sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
]
end
it "returns all constants including inherited when passed true" do
ConstantSpecs::ContainerA.constants(true).sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
]
end
it "returns all constants including inherited when passed some object" do
ConstantSpecs::ContainerA.constants(Object.new).sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST24, :CS_CONST5, :ChildA
]
end
it "doesn't returns inherited constants when passed false" do
ConstantSpecs::ContainerA.constants(false).sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST5, :ChildA
]
end
it "doesn't returns inherited constants when passed nil" do
ConstantSpecs::ContainerA.constants(nil).sort.should == [
- :CS_CONST10, :CS_CONST23, :CS_CONST5, :ChildA
+ :CS_CONST10, :CS_CONST10_LINE, :CS_CONST23, :CS_CONST5, :ChildA
]
end
diff --git a/spec/ruby/core/module/define_method_spec.rb b/spec/ruby/core/module/define_method_spec.rb
index 29394e5b92..49472c18e1 100644
--- a/spec/ruby/core/module/define_method_spec.rb
+++ b/spec/ruby/core/module/define_method_spec.rb
@@ -245,10 +245,10 @@ describe "Module#define_method" do
-> { obj.proc_style_test :arg }.should raise_error(ArgumentError)
end
- it "raises a #{frozen_error_class} if frozen" do
+ it "raises a FrozenError if frozen" do
-> {
Class.new { freeze; define_method(:foo) {} }
- }.should raise_error(frozen_error_class)
+ }.should raise_error(FrozenError)
end
it "accepts a Method (still bound)" do
@@ -355,15 +355,8 @@ describe "Module#define_method" do
klass.new.string_test.should == "string_test result"
end
- ruby_version_is ''...'2.5' do
- it "is a private method" do
- Module.should have_private_instance_method(:define_method)
- end
- end
- ruby_version_is '2.5' do
- it "is a public method" do
- Module.should have_public_instance_method(:define_method)
- end
+ it "is a public method" do
+ Module.should have_public_instance_method(:define_method)
end
it "returns its symbol" do
diff --git a/spec/ruby/core/module/deprecate_constant_spec.rb b/spec/ruby/core/module/deprecate_constant_spec.rb
index 6a8086bc8f..7bcced981b 100644
--- a/spec/ruby/core/module/deprecate_constant_spec.rb
+++ b/spec/ruby/core/module/deprecate_constant_spec.rb
@@ -10,16 +10,6 @@ describe "Module#deprecate_constant" do
@module.private_constant :PRIVATE
@module.deprecate_constant :PRIVATE
@pattern = /deprecated/
- if Warning.respond_to?(:[])
- @deprecated = Warning[:deprecated]
- Warning[:deprecated] = true
- end
- end
-
- after :each do
- if Warning.respond_to?(:[])
- Warning[:deprecated] = @deprecated
- end
end
describe "when accessing the deprecated module" do
diff --git a/spec/ruby/core/module/fixtures/autoload_during_require_current_file.rb b/spec/ruby/core/module/fixtures/autoload_during_require_current_file.rb
new file mode 100644
index 0000000000..5aa8595065
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_during_require_current_file.rb
@@ -0,0 +1,5 @@
+module ModuleSpecs::Autoload
+ autoload(:AutoloadCurrentFile, __FILE__)
+
+ ScratchPad.record autoload?(:AutoloadCurrentFile)
+end
diff --git a/spec/ruby/core/module/fixtures/autoload_location.rb b/spec/ruby/core/module/fixtures/autoload_location.rb
new file mode 100644
index 0000000000..318851b2df
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_location.rb
@@ -0,0 +1,3 @@
+module ConstantSpecs
+ CONST_LOCATION = __LINE__
+end
diff --git a/spec/ruby/core/module/fixtures/autoload_required_directly_no_constant.rb b/spec/ruby/core/module/fixtures/autoload_required_directly_no_constant.rb
new file mode 100644
index 0000000000..25e08c1129
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/autoload_required_directly_no_constant.rb
@@ -0,0 +1,2 @@
+block = ScratchPad.recorded
+ScratchPad.record(block.call)
diff --git a/spec/ruby/core/module/fixtures/refine.rb b/spec/ruby/core/module/fixtures/refine.rb
index 46975361dd..e8215aa640 100644
--- a/spec/ruby/core/module/fixtures/refine.rb
+++ b/spec/ruby/core/module/fixtures/refine.rb
@@ -3,6 +3,10 @@ module ModuleSpecs
def foo; "foo" end
end
+ class ClassWithSuperFoo
+ def foo; [:C] end
+ end
+
module PrependedModule
def foo; "foo from prepended module"; end
end
@@ -10,4 +14,12 @@ module ModuleSpecs
module IncludedModule
def foo; "foo from included module"; end
end
+
+ def self.build_refined_class(for_super: false)
+ if for_super
+ Class.new(ClassWithSuperFoo)
+ else
+ Class.new(ClassWithFoo)
+ end
+ end
end
diff --git a/spec/ruby/core/module/included_spec.rb b/spec/ruby/core/module/included_spec.rb
index f8dbad1d31..2fdd4325f2 100644
--- a/spec/ruby/core/module/included_spec.rb
+++ b/spec/ruby/core/module/included_spec.rb
@@ -39,6 +39,6 @@ describe "Module#included" do
it "works with super using a singleton class" do
ModuleSpecs::SingletonOnModuleCase::Bar.include ModuleSpecs::SingletonOnModuleCase::Foo
- ModuleSpecs::SingletonOnModuleCase::Bar.included_called?.should == true
+ ModuleSpecs::SingletonOnModuleCase::Bar.should.included_called?
end
end
diff --git a/spec/ruby/core/module/method_added_spec.rb b/spec/ruby/core/module/method_added_spec.rb
index e1b1eda430..b983c8da76 100644
--- a/spec/ruby/core/module/method_added_spec.rb
+++ b/spec/ruby/core/module/method_added_spec.rb
@@ -59,4 +59,25 @@ describe "Module#method_added" do
end
m.should_not have_method(:method_to_undef)
end
+
+ it "is called with a precise caller location with the line of the 'def'" do
+ ScratchPad.record []
+ line = nil
+
+ Module.new do
+ def self.method_added(name)
+ location = caller_locations(1, 1)[0]
+ ScratchPad << location.lineno
+ end
+
+ line = __LINE__
+ def first
+ end
+
+ def second
+ end
+ end
+
+ ScratchPad.recorded.should == [line + 1, line + 4]
+ end
end
diff --git a/spec/ruby/core/module/method_defined_spec.rb b/spec/ruby/core/module/method_defined_spec.rb
index c2a8702d97..dccee870b1 100644
--- a/spec/ruby/core/module/method_defined_spec.rb
+++ b/spec/ruby/core/module/method_defined_spec.rb
@@ -30,7 +30,7 @@ describe "Module#method_defined?" do
m.method_defined?(:module_specs_public_method_on_kernel).should be_false
end
- it "raises a TypeError when the given object is not a string/symbol/fixnum" do
+ it "raises a TypeError when the given object is not a string/symbol" do
c = Class.new
o = mock('123')
diff --git a/spec/ruby/core/module/name_spec.rb b/spec/ruby/core/module/name_spec.rb
index 36a91f5be5..ca9106a973 100644
--- a/spec/ruby/core/module/name_spec.rb
+++ b/spec/ruby/core/module/name_spec.rb
@@ -6,10 +6,20 @@ describe "Module#name" do
Module.new.name.should be_nil
end
- it "is nil when assigned to a constant in an anonymous module" do
- m = Module.new
- m::N = Module.new
- m::N.name.should be_nil
+ ruby_version_is ""..."3.0" do
+ it "is nil when assigned to a constant in an anonymous module" do
+ m = Module.new
+ m::N = Module.new
+ m::N.name.should be_nil
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "is not nil when assigned to a constant in an anonymous module" do
+ m = Module.new
+ m::N = Module.new
+ m::N.name.should.end_with? '::N'
+ end
end
it "is not nil for a nested module created with the module keyword" do
@@ -18,6 +28,12 @@ describe "Module#name" do
m::N.name.should =~ /\A#<Module:0x[0-9a-f]+>::N\z/
end
+ it "returns nil for a singleton class" do
+ Module.new.singleton_class.name.should be_nil
+ String.singleton_class.name.should be_nil
+ Object.new.singleton_class.name.should be_nil
+ end
+
it "changes when the module is reachable through a constant path" do
m = Module.new
module m::N; end
@@ -116,7 +132,7 @@ describe "Module#name" do
ruby_version_is "2.7" do
it "returns a frozen String" do
- ModuleSpecs.name.frozen?.should == true
+ ModuleSpecs.name.should.frozen?
end
it "always returns the same String for a given Module" do
diff --git a/spec/ruby/core/module/prepend_spec.rb b/spec/ruby/core/module/prepend_spec.rb
index e143f51673..a501b5e50c 100644
--- a/spec/ruby/core/module/prepend_spec.rb
+++ b/spec/ruby/core/module/prepend_spec.rb
@@ -128,17 +128,34 @@ describe "Module#prepend" do
c.dup.new.should be_kind_of(m)
end
- it "keeps the module in the chain when dupping an intermediate module" do
- m1 = Module.new { def calc(x) x end }
- m2 = Module.new { prepend(m1) }
- c1 = Class.new { prepend(m2) }
- m2dup = m2.dup
- m2dup.ancestors.should == [m2dup,m1,m2]
- c2 = Class.new { prepend(m2dup) }
- c1.ancestors[0,3].should == [m1,m2,c1]
- c1.new.should be_kind_of(m1)
- c2.ancestors[0,4].should == [m2dup,m1,m2,c2]
- c2.new.should be_kind_of(m1)
+ ruby_version_is '0'...'3.0' do
+ it "keeps the module in the chain when dupping an intermediate module" do
+ m1 = Module.new { def calc(x) x end }
+ m2 = Module.new { prepend(m1) }
+ c1 = Class.new { prepend(m2) }
+ m2dup = m2.dup
+ m2dup.ancestors.should == [m2dup,m1,m2]
+ c2 = Class.new { prepend(m2dup) }
+ c1.ancestors[0,3].should == [m1,m2,c1]
+ c1.new.should be_kind_of(m1)
+ c2.ancestors[0,4].should == [m2dup,m1,m2,c2]
+ c2.new.should be_kind_of(m1)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "uses only new module when dupping the module" do
+ m1 = Module.new { def calc(x) x end }
+ m2 = Module.new { prepend(m1) }
+ c1 = Class.new { prepend(m2) }
+ m2dup = m2.dup
+ m2dup.ancestors.should == [m1,m2dup]
+ c2 = Class.new { prepend(m2dup) }
+ c1.ancestors[0,3].should == [m1,m2,c1]
+ c1.new.should be_kind_of(m1)
+ c2.ancestors[0,3].should == [m1,m2dup,c2]
+ c2.new.should be_kind_of(m1)
+ end
end
it "depends on prepend_features to add the module" do
diff --git a/spec/ruby/core/module/private_method_defined_spec.rb b/spec/ruby/core/module/private_method_defined_spec.rb
index 515542d9df..951f17aaa7 100644
--- a/spec/ruby/core/module/private_method_defined_spec.rb
+++ b/spec/ruby/core/module/private_method_defined_spec.rb
@@ -31,7 +31,7 @@ describe "Module#private_method_defined?" do
ModuleSpecs::CountsMixin.private_method_defined?(:private_3).should == true
end
- it "raises a TypeError if passed a Fixnum" do
+ it "raises a TypeError if passed an Integer" do
-> do
ModuleSpecs::CountsMixin.private_method_defined?(1)
end.should raise_error(TypeError)
diff --git a/spec/ruby/core/module/protected_method_defined_spec.rb b/spec/ruby/core/module/protected_method_defined_spec.rb
index 7be7bdd3c9..e022d7c5c4 100644
--- a/spec/ruby/core/module/protected_method_defined_spec.rb
+++ b/spec/ruby/core/module/protected_method_defined_spec.rb
@@ -31,7 +31,7 @@ describe "Module#protected_method_defined?" do
ModuleSpecs::CountsMixin.protected_method_defined?(:protected_3).should == true
end
- it "raises a TypeError if passed a Fixnum" do
+ it "raises a TypeError if passed an Integer" do
-> do
ModuleSpecs::CountsMixin.protected_method_defined?(1)
end.should raise_error(TypeError)
diff --git a/spec/ruby/core/module/public_method_defined_spec.rb b/spec/ruby/core/module/public_method_defined_spec.rb
index d2fcfd1e72..5c9bdf1ccc 100644
--- a/spec/ruby/core/module/public_method_defined_spec.rb
+++ b/spec/ruby/core/module/public_method_defined_spec.rb
@@ -31,7 +31,7 @@ describe "Module#public_method_defined?" do
ModuleSpecs::CountsMixin.public_method_defined?(:public_3).should == true
end
- it "raises a TypeError if passed a Fixnum" do
+ it "raises a TypeError if passed an Integer" do
-> do
ModuleSpecs::CountsMixin.public_method_defined?(1)
end.should raise_error(TypeError)
diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb
index 66c19ddb66..54217a9326 100644
--- a/spec/ruby/core/module/refine_spec.rb
+++ b/spec/ruby/core/module/refine_spec.rb
@@ -87,6 +87,31 @@ describe "Module#refine" do
inner_self.public_instance_methods.should include(:blah)
end
+ it "applies refinements to the module" do
+ refinement = Module.new do
+ refine(Enumerable) do
+ def foo?
+ self.any? ? "yes" : "no"
+ end
+ end
+ end
+
+ foo = Class.new do
+ using refinement
+
+ def initialize(items)
+ @items = items
+ end
+
+ def result
+ @items.foo?
+ end
+ end
+
+ foo.new([]).result.should == "no"
+ foo.new([1]).result.should == "yes"
+ end
+
it "raises ArgumentError if not given a block" do
-> do
Module.new do
@@ -196,8 +221,10 @@ describe "Module#refine" do
# * The included modules of C
describe "method lookup" do
it "looks in the object singleton class first" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -206,7 +233,7 @@ describe "Module#refine" do
Module.new do
using refinement
- obj = ModuleSpecs::ClassWithFoo.new
+ obj = refined_class.new
class << obj
def foo; "foo from singleton class"; end
end
@@ -216,9 +243,66 @@ describe "Module#refine" do
result.should == "foo from singleton class"
end
+ 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
+
+ it "looks in later included modules of the refined module first" do
+ a = Module.new do
+ def foo
+ "foo from A"
+ end
+ end
+
+ include_me_later = Module.new do
+ def foo
+ "foo from IncludeMeLater"
+ end
+ end
+
+ c = Class.new do
+ include a
+ end
+
+ refinement = Module.new do
+ refine c do; end
+ end
+
+ result = nil
+ Module.new do
+ using refinement
+ c.include include_me_later
+ result = c.new.foo
+ end
+
+ result.should == "foo from IncludeMeLater"
+ end
+
it "looks in prepended modules from the refinement first" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
include ModuleSpecs::IncludedModule
prepend ModuleSpecs::PrependedModule
@@ -229,15 +313,17 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ 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(ModuleSpecs::ClassWithFoo) do
+ refine(refined_class) do
include ModuleSpecs::IncludedModule
def foo; "foo from refinement"; end
@@ -247,15 +333,17 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ 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 ModuleSpecs::ClassWithFoo do
+ refine refined_class do
include ModuleSpecs::IncludedModule
end
end
@@ -263,21 +351,23 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ result = refined_class.new.foo
end
result.should == "foo from included module"
end
it "looks in the class then" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine(ModuleSpecs::ClassWithFoo) { }
+ refine(refined_class) { }
end
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ result = refined_class.new.foo
end
result.should == "foo"
@@ -287,12 +377,14 @@ describe "Module#refine" do
# methods in a subclass have priority over refinements in a superclass
it "does not override methods in subclasses" do
- subclass = Class.new(ModuleSpecs::ClassWithFoo) do
+ refined_class = ModuleSpecs.build_refined_class
+
+ subclass = Class.new(refined_class) do
def foo; "foo from subclass"; end
end
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -308,8 +400,10 @@ describe "Module#refine" do
context "for methods accessed indirectly" do
it "is honored by Kernel#send" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -317,15 +411,17 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.send :foo
+ result = refined_class.new.send :foo
end
result.should == "foo from refinement"
end
it "is honored by BasicObject#__send__" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -333,7 +429,7 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.__send__ :foo
+ result = refined_class.new.__send__ :foo
end
result.should == "foo from refinement"
@@ -359,8 +455,10 @@ describe "Module#refine" do
ruby_version_is "" ... "2.6" do
it "is not honored by Kernel#public_send" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -368,7 +466,7 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.public_send :foo
+ result = refined_class.new.public_send :foo
end
result.should == "foo"
@@ -377,8 +475,10 @@ describe "Module#refine" do
ruby_version_is "2.6" do
it "is honored by Kernel#public_send" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo; "foo from refinement"; end
end
end
@@ -386,51 +486,29 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.public_send :foo
+ result = refined_class.new.public_send :foo
end
result.should == "foo from refinement"
end
end
- ruby_version_is "" ... "2.5" do
- it "is not honored by string interpolation" do
- refinement = Module.new do
- refine Integer do
- def to_s
- "foo"
- end
+ it "is honored by string interpolation" do
+ refinement = Module.new do
+ refine Integer do
+ def to_s
+ "foo"
end
end
-
- result = nil
- Module.new do
- using refinement
- result = "#{1}"
- end
-
- result.should == "1"
end
- end
- ruby_version_is "2.5" do
- it "is honored by string interpolation" do
- refinement = Module.new do
- refine Integer do
- def to_s
- "foo"
- end
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = "#{1}"
- end
-
- result.should == "foo"
+ result = nil
+ Module.new do
+ using refinement
+ result = "#{1}"
end
+
+ result.should == "foo"
end
it "is honored by Kernel#binding" do
@@ -612,8 +690,10 @@ describe "Module#refine" do
context "when super is called in a refinement" do
it "looks in the included to refinery module" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
include ModuleSpecs::IncludedModule
def foo
@@ -625,15 +705,17 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ result = refined_class.new.foo
end
result.should == "foo from included module"
end
it "looks in the refined class" do
+ refined_class = ModuleSpecs.build_refined_class
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo
super
end
@@ -643,28 +725,81 @@ describe "Module#refine" do
result = nil
Module.new do
using refinement
- result = ModuleSpecs::ClassWithFoo.new.foo
+ result = refined_class.new.foo
end
result.should == "foo"
end
+ 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
+
# super in a method of a refinement invokes the method in the refined
# class even if there is another refinement which has been activated
# in the same context.
- it "looks in the refined class even if there is another active refinement" do
+ it "looks in the refined class first if called from refined method" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+
refinement = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo
- "foo from refinement"
+ [:R1]
end
end
end
refinement_with_super = Module.new do
- refine ModuleSpecs::ClassWithFoo do
+ refine refined_class do
def foo
- super
+ [:R2] + super
end
end
end
@@ -673,10 +808,210 @@ describe "Module#refine" do
Module.new do
using refinement
using refinement_with_super
- result = ModuleSpecs::ClassWithFoo.new.foo
+ result = refined_class.new.foo
end
- result.should == "foo"
+ result.should == [:R2, :C]
+ end
+
+ it "looks only in the refined class even if there is another active refinement" do
+ refined_class = ModuleSpecs.build_refined_class(for_super: true)
+
+ refinement = Module.new do
+ refine refined_class do
+ def bar
+ "you cannot see me from super because I belong to another active R"
+ end
+ end
+ end
+
+ refinement_with_super = Module.new do
+ refine refined_class do
+ def bar
+ super
+ end
+ end
+ end
+
+
+ Module.new do
+ using refinement
+ using refinement_with_super
+ -> {
+ refined_class.new.bar
+ }.should raise_error(NoMethodError)
+ end
+ end
+
+ 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
@@ -704,6 +1039,17 @@ describe "Module#refine" do
-> { [1,2].orig_count }.should raise_error(NoMethodError)
end
+ it "and instance_methods returns a list of methods including those of the refined module" do
+ methods = Array.instance_methods
+ methods_2 = []
+ Module.new do
+ refine Array do
+ methods_2 = instance_methods
+ end
+ end
+ methods.should == methods_2
+ end
+
# Refinements are inherited by module inclusion.
# That is, using activates all refinements in the ancestors of the specified module.
# Refinements in a descendant have priority over refinements in an ancestor.
diff --git a/spec/ruby/core/module/remove_method_spec.rb b/spec/ruby/core/module/remove_method_spec.rb
index ba08cc9b44..b6ae02078f 100644
--- a/spec/ruby/core/module/remove_method_spec.rb
+++ b/spec/ruby/core/module/remove_method_spec.rb
@@ -20,15 +20,8 @@ describe "Module#remove_method" do
@module = Module.new { def method_to_remove; end }
end
- ruby_version_is ''...'2.5' do
- it "is a private method" do
- Module.should have_private_instance_method(:remove_method, false)
- end
- end
- ruby_version_is '2.5' do
- it "is a public method" do
- Module.should have_public_instance_method(:remove_method, false)
- end
+ it "is a public method" do
+ Module.should have_public_instance_method(:remove_method, false)
end
it "removes the method from a class" do
@@ -97,12 +90,12 @@ describe "Module#remove_method" do
@frozen = @module.dup.freeze
end
- it "raises a #{frozen_error_class} when passed a name" do
- -> { @frozen.send :remove_method, :method_to_remove }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed a name" do
+ -> { @frozen.send :remove_method, :method_to_remove }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} when passed a missing name" do
- -> { @frozen.send :remove_method, :not_exist }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed a missing name" do
+ -> { @frozen.send :remove_method, :not_exist }.should raise_error(FrozenError)
end
it "raises a TypeError when passed a not name" do
diff --git a/spec/ruby/core/module/shared/class_eval.rb b/spec/ruby/core/module/shared/class_eval.rb
index 08f8ff7597..224078ae54 100644
--- a/spec/ruby/core/module/shared/class_eval.rb
+++ b/spec/ruby/core/module/shared/class_eval.rb
@@ -112,4 +112,48 @@ describe :module_class_eval, shared: true do
a.attribute.should == "A"
b.attribute.should == "B"
end
+
+ it "activates refinements from the eval scope" do
+ refinery = Module.new do
+ refine ModuleSpecs::NamedClass do
+ def foo
+ "bar"
+ end
+ end
+ end
+
+ mid = @method
+ result = nil
+
+ Class.new do
+ using refinery
+
+ result = send(mid, "ModuleSpecs::NamedClass.new.foo")
+ end
+
+ result.should == "bar"
+ end
+
+ it "activates refinements from the eval scope with block" do
+ refinery = Module.new do
+ refine ModuleSpecs::NamedClass do
+ def foo
+ "bar"
+ end
+ end
+ end
+
+ mid = @method
+ result = nil
+
+ Class.new do
+ using refinery
+
+ result = send(mid) do
+ ModuleSpecs::NamedClass.new.foo
+ end
+ end
+
+ result.should == "bar"
+ end
end
diff --git a/spec/ruby/core/module/shared/set_visibility.rb b/spec/ruby/core/module/shared/set_visibility.rb
index a04b1a54a0..9f31e230ca 100644
--- a/spec/ruby/core/module/shared/set_visibility.rb
+++ b/spec/ruby/core/module/shared/set_visibility.rb
@@ -6,6 +6,40 @@ describe :set_visibility, shared: true do
end
describe "with argument" do
+ describe "one or more arguments" do
+ it "sets visibility of given method names" do
+ visibility = @method
+ old_visibility = [:protected, :private].find {|vis| vis != visibility }
+
+ mod = Module.new {
+ send old_visibility
+ def test1() end
+ def test2() end
+ send visibility, :test1, :test2
+ }
+ mod.should send(:"have_#{visibility}_instance_method", :test1, false)
+ mod.should send(:"have_#{visibility}_instance_method", :test2, false)
+ end
+ end
+
+ ruby_version_is "3.0" do
+ describe "array as a single argument" do
+ it "sets visibility of given method names" do
+ visibility = @method
+ old_visibility = [:protected, :private].find {|vis| vis != visibility }
+
+ mod = Module.new {
+ send old_visibility
+ def test1() end
+ def test2() end
+ send visibility, [:test1, :test2]
+ }
+ mod.should send(:"have_#{visibility}_instance_method", :test1, false)
+ mod.should send(:"have_#{visibility}_instance_method", :test2, false)
+ end
+ end
+ end
+
it "does not clone method from the ancestor when setting to the same visibility in a child" do
visibility = @method
parent = Module.new {
diff --git a/spec/ruby/core/module/singleton_class_spec.rb b/spec/ruby/core/module/singleton_class_spec.rb
index b9f78eeb21..052755b73b 100644
--- a/spec/ruby/core/module/singleton_class_spec.rb
+++ b/spec/ruby/core/module/singleton_class_spec.rb
@@ -3,25 +3,25 @@ require_relative '../../spec_helper'
describe "Module#singleton_class?" do
it "returns true for singleton classes" do
xs = self.singleton_class
- xs.singleton_class?.should == true
+ xs.should.singleton_class?
end
it "returns false for other classes" do
c = Class.new
- c.singleton_class?.should == false
+ c.should_not.singleton_class?
end
describe "with singleton values" do
it "returns false for nil's singleton class" do
- NilClass.singleton_class?.should == false
+ NilClass.should_not.singleton_class?
end
it "returns false for true's singleton class" do
- TrueClass.singleton_class?.should == false
+ TrueClass.should_not.singleton_class?
end
it "returns false for false's singleton class" do
- FalseClass.singleton_class?.should == false
+ FalseClass.should_not.singleton_class?
end
end
end
diff --git a/spec/ruby/core/module/undef_method_spec.rb b/spec/ruby/core/module/undef_method_spec.rb
index b101778962..c2ad200536 100644
--- a/spec/ruby/core/module/undef_method_spec.rb
+++ b/spec/ruby/core/module/undef_method_spec.rb
@@ -18,15 +18,8 @@ describe "Module#undef_method" do
@module = Module.new { def method_to_undef; end }
end
- ruby_version_is ''...'2.5' do
- it "is a private method" do
- Module.should have_private_instance_method(:undef_method, false)
- end
- end
- ruby_version_is '2.5' do
- it "is a public method" do
- Module.should have_public_instance_method(:undef_method, false)
- end
+ it "is a public method" do
+ Module.should have_public_instance_method(:undef_method, false)
end
it "requires multiple arguments" do
@@ -97,12 +90,12 @@ describe "Module#undef_method" do
@frozen = @module.dup.freeze
end
- it "raises a #{frozen_error_class} when passed a name" do
- -> { @frozen.send :undef_method, :method_to_undef }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed a name" do
+ -> { @frozen.send :undef_method, :method_to_undef }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} when passed a missing name" do
- -> { @frozen.send :undef_method, :not_exist }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed a missing name" do
+ -> { @frozen.send :undef_method, :not_exist }.should raise_error(FrozenError)
end
it "raises a TypeError when passed a not name" do
diff --git a/spec/ruby/core/module/using_spec.rb b/spec/ruby/core/module/using_spec.rb
index 533d87d080..4781b99bb7 100644
--- a/spec/ruby/core/module/using_spec.rb
+++ b/spec/ruby/core/module/using_spec.rb
@@ -243,6 +243,96 @@ describe "Module#using" do
mod.call_foo(c).should == "foo from refinement"
end
+ it "is active for module defined via Module.new {}" do
+ refinement = Module.new do
+ refine Integer do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+
+ Module.new do
+ using refinement
+
+ Module.new do
+ result = 1.foo
+ end
+ end
+
+ result.should == "foo from refinement"
+ end
+
+ it "is active for class defined via Class.new {}" do
+ refinement = Module.new do
+ refine Integer do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ result = nil
+
+ Module.new do
+ using refinement
+
+ Class.new do
+ result = 1.foo
+ end
+ end
+
+ result.should == "foo from refinement"
+ end
+
+ it "is active for block called via instance_exec" do
+ refinement = Module.new do
+ refine Integer do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ c = Class.new do
+ using refinement
+
+ def abc
+ block = -> {
+ 1.foo
+ }
+
+ self.instance_exec(&block)
+ end
+ end
+
+ c.new.abc.should == "foo from refinement"
+ end
+
+ it "is active for block called via instance_eval" do
+ refinement = Module.new do
+ refine String do
+ def foo; "foo from refinement"; end
+ end
+ end
+
+ c = Class.new do
+ using refinement
+
+ def initialize
+ @a = "1703"
+
+ @a.instance_eval do
+ def abc
+ "#{self}: #{self.foo}"
+ end
+ end
+ end
+
+ def abc
+ @a.abc
+ end
+ end
+
+ c.new.abc.should == "1703: foo from refinement"
+ end
+
it "is not active if `using` call is not evaluated" do
result = nil
diff --git a/spec/ruby/core/mutex/owned_spec.rb b/spec/ruby/core/mutex/owned_spec.rb
index e66062534e..1f843cd576 100644
--- a/spec/ruby/core/mutex/owned_spec.rb
+++ b/spec/ruby/core/mutex/owned_spec.rb
@@ -40,4 +40,16 @@ describe "Mutex#owned?" do
m.owned?.should be_false
end
end
+
+ ruby_version_is "3.0" do
+ it "is held per Fiber" do
+ m = Mutex.new
+ m.lock
+
+ Fiber.new do
+ m.locked?.should == true
+ m.owned?.should == false
+ end.resume
+ end
+ end
end
diff --git a/spec/ruby/core/mutex/sleep_spec.rb b/spec/ruby/core/mutex/sleep_spec.rb
index f5e0d53036..9832e3125e 100644
--- a/spec/ruby/core/mutex/sleep_spec.rb
+++ b/spec/ruby/core/mutex/sleep_spec.rb
@@ -37,7 +37,7 @@ describe "Mutex#sleep" do
locked = false
th = Thread.new { m.lock; locked = true; m.sleep }
Thread.pass until locked
- Thread.pass while th.status and th.status != "sleep"
+ Thread.pass until th.stop?
m.locked?.should be_false
th.run
th.join
@@ -63,15 +63,23 @@ describe "Mutex#sleep" do
end
end
Thread.pass until locked
- Thread.pass while th.status and th.status != "sleep"
+ Thread.pass until th.stop?
th.raise(Exception)
th.value.should be_true
end
it "returns the rounded number of seconds asleep" do
m = Mutex.new
- m.lock
- m.sleep(0.001).should be_kind_of(Integer)
+ locked = false
+ th = Thread.start do
+ m.lock
+ locked = true
+ m.sleep
+ end
+ Thread.pass until locked
+ Thread.pass until th.stop?
+ th.wakeup
+ th.value.should be_kind_of(Integer)
end
it "wakes up when requesting sleep times near or equal to zero" do
@@ -89,7 +97,7 @@ describe "Mutex#sleep" do
m.lock
times.each do |time|
# just testing that sleep completes
- m.sleep(time).should_not == nil
+ -> {m.sleep(time)}.should_not raise_error
end
end
end
diff --git a/spec/ruby/core/mutex/unlock_spec.rb b/spec/ruby/core/mutex/unlock_spec.rb
index c9c3bfe14f..d999e66842 100644
--- a/spec/ruby/core/mutex/unlock_spec.rb
+++ b/spec/ruby/core/mutex/unlock_spec.rb
@@ -17,7 +17,7 @@ describe "Mutex#unlock" do
# avoid race on mutex.lock
Thread.pass until mutex.locked?
- Thread.pass while th.status and th.status != "sleep"
+ Thread.pass until th.stop?
-> { mutex.unlock }.should raise_error(ThreadError)
diff --git a/spec/ruby/core/nil/case_compare_spec.rb b/spec/ruby/core/nil/case_compare_spec.rb
new file mode 100644
index 0000000000..142560c6f5
--- /dev/null
+++ b/spec/ruby/core/nil/case_compare_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+
+describe "NilClass#===" do
+ it "returns true for nil" do
+ (nil === nil).should == true
+ end
+
+ it "returns false for non-nil object" do
+ (nil === 1).should == false
+ (nil === "").should == false
+ (nil === Object).should == false
+ end
+end
diff --git a/spec/ruby/core/nil/match_spec.rb b/spec/ruby/core/nil/match_spec.rb
index 3f69312bfe..27646e9749 100644
--- a/spec/ruby/core/nil/match_spec.rb
+++ b/spec/ruby/core/nil/match_spec.rb
@@ -15,5 +15,9 @@ ruby_version_is "2.6" do
(o =~ true).should be_nil
end
end
+
+ it "should not warn" do
+ -> { nil =~ /a/ }.should_not complain(verbose: true)
+ end
end
end
diff --git a/spec/ruby/core/nil/nil_spec.rb b/spec/ruby/core/nil/nil_spec.rb
index 47db0c5cf0..2cf97621c6 100644
--- a/spec/ruby/core/nil/nil_spec.rb
+++ b/spec/ruby/core/nil/nil_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../spec_helper'
describe "NilClass#nil?" do
it "returns true" do
- nil.nil?.should == true
+ nil.should.nil?
end
end
diff --git a/spec/ruby/core/nil/to_i_spec.rb b/spec/ruby/core/nil/to_i_spec.rb
index 099792ef68..d3d088e999 100644
--- a/spec/ruby/core/nil/to_i_spec.rb
+++ b/spec/ruby/core/nil/to_i_spec.rb
@@ -5,7 +5,7 @@ describe "NilClass#to_i" do
nil.to_i.should == 0
end
- it "does not cause NilClass to be coerced to Fixnum" do
+ it "does not cause NilClass to be coerced to Integer" do
(0 == nil).should == false
end
end
diff --git a/spec/ruby/core/nil/to_s_spec.rb b/spec/ruby/core/nil/to_s_spec.rb
index 4b61f589f7..283d26477a 100644
--- a/spec/ruby/core/nil/to_s_spec.rb
+++ b/spec/ruby/core/nil/to_s_spec.rb
@@ -7,7 +7,7 @@ describe "NilClass#to_s" do
ruby_version_is "2.7" do
it "returns a frozen string" do
- nil.to_s.frozen?.should == true
+ nil.to_s.should.frozen?
end
it "always returns the same string" do
diff --git a/spec/ruby/core/numeric/clone_spec.rb b/spec/ruby/core/numeric/clone_spec.rb
new file mode 100644
index 0000000000..e3bf0a9e7c
--- /dev/null
+++ b/spec/ruby/core/numeric/clone_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#clone" do
+ it "returns self" do
+ value = 1
+ value.clone.should equal(value)
+
+ subclass = Class.new(Numeric)
+ value = subclass.new
+ value.clone.should equal(value)
+ end
+
+ it "does not change frozen status" do
+ 1.clone.frozen?.should == true
+ end
+
+ it "accepts optonal keyword argument :freeze" do
+ value = 1
+ value.clone(freeze: true).should equal(value)
+ end
+
+ it "raises ArgumentError if passed freeze: false" do
+ -> { 1.clone(freeze: false) }.should raise_error(ArgumentError, /can't unfreeze/)
+ end
+end
diff --git a/spec/ruby/core/numeric/denominator_spec.rb b/spec/ruby/core/numeric/denominator_spec.rb
index 34729446a2..d347b280f5 100644
--- a/spec/ruby/core/numeric/denominator_spec.rb
+++ b/spec/ruby/core/numeric/denominator_spec.rb
@@ -6,7 +6,7 @@ describe "Numeric#denominator" do
before :each do
@numbers = [
20, # Integer
- 99999999**99, # Bignum
+ 99999999**99, # Integer
]
end
diff --git a/spec/ruby/core/numeric/dup_spec.rb b/spec/ruby/core/numeric/dup_spec.rb
new file mode 100644
index 0000000000..189a7ef44d
--- /dev/null
+++ b/spec/ruby/core/numeric/dup_spec.rb
@@ -0,0 +1,16 @@
+require_relative '../../spec_helper'
+
+describe "Numeric#dup" do
+ it "returns self" do
+ value = 1
+ value.dup.should equal(value)
+
+ subclass = Class.new(Numeric)
+ value = subclass.new
+ value.dup.should equal(value)
+ end
+
+ it "does not change frozen status" do
+ 1.dup.frozen?.should == true
+ end
+end
diff --git a/spec/ruby/core/numeric/integer_spec.rb b/spec/ruby/core/numeric/integer_spec.rb
index 5d4bf00360..adbac4d7aa 100644
--- a/spec/ruby/core/numeric/integer_spec.rb
+++ b/spec/ruby/core/numeric/integer_spec.rb
@@ -3,6 +3,6 @@ require_relative 'fixtures/classes'
describe "Numeric#integer?" do
it "returns false" do
- NumericSpecs::Subclass.new.integer?.should == false
+ NumericSpecs::Subclass.new.should_not.integer?
end
end
diff --git a/spec/ruby/core/numeric/negative_spec.rb b/spec/ruby/core/numeric/negative_spec.rb
index da464a9094..9c6f95fd87 100644
--- a/spec/ruby/core/numeric/negative_spec.rb
+++ b/spec/ruby/core/numeric/negative_spec.rb
@@ -31,11 +31,11 @@ describe "Numeric#negative?" do
it "returns true if self is less than 0" do
@obj.should_receive(:<).with(0).and_return(true)
- @obj.negative?.should == true
+ @obj.should.negative?
end
it "returns false if self is greater than 0" do
@obj.should_receive(:<).with(0).and_return(false)
- @obj.negative?.should == false
+ @obj.should_not.negative?
end
end
diff --git a/spec/ruby/core/numeric/positive_spec.rb b/spec/ruby/core/numeric/positive_spec.rb
index 8f98fbfa26..3b831b4d34 100644
--- a/spec/ruby/core/numeric/positive_spec.rb
+++ b/spec/ruby/core/numeric/positive_spec.rb
@@ -31,11 +31,11 @@ describe "Numeric#positive?" do
it "returns true if self is greater than 0" do
@obj.should_receive(:>).with(0).and_return(true)
- @obj.positive?.should == true
+ @obj.should.positive?
end
it "returns false if self is less than 0" do
@obj.should_receive(:>).with(0).and_return(false)
- @obj.positive?.should == false
+ @obj.should_not.positive?
end
end
diff --git a/spec/ruby/core/numeric/quo_spec.rb b/spec/ruby/core/numeric/quo_spec.rb
index 5c952b11a9..33b68a38f0 100644
--- a/spec/ruby/core/numeric/quo_spec.rb
+++ b/spec/ruby/core/numeric/quo_spec.rb
@@ -11,7 +11,7 @@ describe "Numeric#quo" do
2.quo(2.5).should eql(0.8)
end
- it "returns the result of self divided by the given Bignum as a Float" do
+ it "returns the result of self divided by the given Integer as a Float" do
45.quo(bignum_value).should be_close(1.04773789668636e-08, TOLERANCE)
end
diff --git a/spec/ruby/core/numeric/real_spec.rb b/spec/ruby/core/numeric/real_spec.rb
index caa8dcec6d..8702dcc7c2 100644
--- a/spec/ruby/core/numeric/real_spec.rb
+++ b/spec/ruby/core/numeric/real_spec.rb
@@ -7,7 +7,7 @@ describe "Numeric#real" do
20, # Integer
398.72, # Float
Rational(3, 4), # Rational
- bignum_value, # Bignum
+ bignum_value, # Integer
infinity_value,
nan_value
].map{ |n| [n, -n] }.flatten
@@ -32,6 +32,6 @@ end
describe "Numeric#real?" do
it "returns true" do
- NumericSpecs::Subclass.new.real?.should == true
+ NumericSpecs::Subclass.new.should.real?
end
end
diff --git a/spec/ruby/core/numeric/shared/imag.rb b/spec/ruby/core/numeric/shared/imag.rb
index ac2da40a3b..0b46b0020b 100644
--- a/spec/ruby/core/numeric/shared/imag.rb
+++ b/spec/ruby/core/numeric/shared/imag.rb
@@ -6,7 +6,7 @@ describe :numeric_imag, shared: true do
20, # Integer
398.72, # Float
Rational(3, 4), # Rational
- bignum_value, # Bignum
+ bignum_value, # Integer
infinity_value,
nan_value
].map{|n| [n,-n]}.flatten
diff --git a/spec/ruby/core/numeric/shared/rect.rb b/spec/ruby/core/numeric/shared/rect.rb
index 9cde19a398..c56f3c48ae 100644
--- a/spec/ruby/core/numeric/shared/rect.rb
+++ b/spec/ruby/core/numeric/shared/rect.rb
@@ -6,7 +6,7 @@ describe :numeric_rect, shared: true do
20, # Integer
398.72, # Float
Rational(3, 4), # Rational
- 99999999**99, # Bignum
+ 99999999**99, # Integer
infinity_value,
nan_value
]
diff --git a/spec/ruby/core/numeric/shared/step.rb b/spec/ruby/core/numeric/shared/step.rb
index 364d4769ad..72f33016d4 100644
--- a/spec/ruby/core/numeric/shared/step.rb
+++ b/spec/ruby/core/numeric/shared/step.rb
@@ -24,9 +24,9 @@ describe :numeric_step, :shared => true do
1.0.step.first(5).should == [1.0, 2.0, 3.0, 4.0, 5.0]
end
- describe "when self, stop and step are Fixnums" do
- it "yields only Fixnums" do
- @step.call(1, 5, 1) { |x| x.should be_an_instance_of(Fixnum) }
+ describe "when self, stop and step are Integers" do
+ it "yields only Integers" do
+ @step.call(1, 5, 1) { |x| x.should be_an_instance_of(Integer) }
end
describe "with a positive step" do
@@ -224,33 +224,25 @@ describe :numeric_step, :shared => true do
end
describe "when step is a String" do
- error = nil
- ruby_version_is "2.4"..."2.5" do
- error = TypeError
- end
- ruby_version_is "2.5" do
- error = ArgumentError
- end
-
- describe "with self and stop as Fixnums" do
- it "raises an #{error} when step is a numeric representation" do
- -> { @step.call(1, 5, "1") {} }.should raise_error(error)
- -> { @step.call(1, 5, "0.1") {} }.should raise_error(error)
- -> { @step.call(1, 5, "1/3") {} }.should raise_error(error)
+ describe "with self and stop as Integers" do
+ it "raises an ArgumentError when step is a numeric representation" do
+ -> { @step.call(1, 5, "1") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "0.1") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "1/3") {} }.should raise_error(ArgumentError)
end
- it "raises an #{error} with step as an alphanumeric string" do
- -> { @step.call(1, 5, "foo") {} }.should raise_error(error)
+ it "raises an ArgumentError with step as an alphanumeric string" do
+ -> { @step.call(1, 5, "foo") {} }.should raise_error(ArgumentError)
end
end
describe "with self and stop as Floats" do
- it "raises an #{error} when step is a numeric representation" do
- -> { @step.call(1.1, 5.1, "1") {} }.should raise_error(error)
- -> { @step.call(1.1, 5.1, "0.1") {} }.should raise_error(error)
- -> { @step.call(1.1, 5.1, "1/3") {} }.should raise_error(error)
+ it "raises an ArgumentError when step is a numeric representation" do
+ -> { @step.call(1.1, 5.1, "1") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "0.1") {} }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "1/3") {} }.should raise_error(ArgumentError)
end
- it "raises an #{error} with step as an alphanumeric string" do
- -> { @step.call(1.1, 5.1, "foo") {} }.should raise_error(error)
+ it "raises an ArgumentError with step as an alphanumeric string" do
+ -> { @step.call(1.1, 5.1, "foo") {} }.should raise_error(ArgumentError)
end
end
end
@@ -269,8 +261,10 @@ describe :numeric_step, :shared => true do
step_enum_class = Enumerator::ArithmeticSequence
end
- it "returns an #{step_enum_class} when step is 0" do
- @step.call(1, 2, 0).should be_an_instance_of(step_enum_class)
+ ruby_version_is ""..."3.0" do
+ it "returns an #{step_enum_class} when step is 0" do
+ @step.call(1, 2, 0).should be_an_instance_of(step_enum_class)
+ end
end
it "returns an #{step_enum_class} when not passed a block and self > stop" do
@@ -286,7 +280,7 @@ describe :numeric_step, :shared => true do
end
describe "when step is a String" do
- describe "with self and stop as Fixnums" do
+ describe "with self and stop as Integers" do
it "returns an Enumerator" do
@step.call(1, 5, "foo").should be_an_instance_of(Enumerator)
end
@@ -302,38 +296,30 @@ describe :numeric_step, :shared => true do
describe "returned Enumerator" do
describe "size" do
describe "when step is a String" do
- error = nil
- ruby_version_is "2.4"..."2.5" do
- error = TypeError
- end
- ruby_version_is "2.5" do
- error = ArgumentError
- end
-
- describe "with self and stop as Fixnums" do
- it "raises an #{error} when step is a numeric representation" do
- -> { @step.call(1, 5, "1").size }.should raise_error(error)
- -> { @step.call(1, 5, "0.1").size }.should raise_error(error)
- -> { @step.call(1, 5, "1/3").size }.should raise_error(error)
+ describe "with self and stop as Integers" do
+ it "raises an ArgumentError when step is a numeric representation" do
+ -> { @step.call(1, 5, "1").size }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "0.1").size }.should raise_error(ArgumentError)
+ -> { @step.call(1, 5, "1/3").size }.should raise_error(ArgumentError)
end
- it "raises an #{error} with step as an alphanumeric string" do
- -> { @step.call(1, 5, "foo").size }.should raise_error(error)
+ it "raises an ArgumentError with step as an alphanumeric string" do
+ -> { @step.call(1, 5, "foo").size }.should raise_error(ArgumentError)
end
end
describe "with self and stop as Floats" do
- it "raises an #{error} when step is a numeric representation" do
- -> { @step.call(1.1, 5.1, "1").size }.should raise_error(error)
- -> { @step.call(1.1, 5.1, "0.1").size }.should raise_error(error)
- -> { @step.call(1.1, 5.1, "1/3").size }.should raise_error(error)
+ it "raises an ArgumentError when step is a numeric representation" do
+ -> { @step.call(1.1, 5.1, "1").size }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "0.1").size }.should raise_error(ArgumentError)
+ -> { @step.call(1.1, 5.1, "1/3").size }.should raise_error(ArgumentError)
end
- it "raises an #{error} with step as an alphanumeric string" do
- -> { @step.call(1.1, 5.1, "foo").size }.should raise_error(error)
+ it "raises an ArgumentError with step as an alphanumeric string" do
+ -> { @step.call(1.1, 5.1, "foo").size }.should raise_error(ArgumentError)
end
end
end
- describe "when self, stop and step are Fixnums and step is positive" do
+ describe "when self, stop and step are Integers and step is positive" do
it "returns the difference between self and stop divided by the number of steps" do
@step.call(5, 10, 11).size.should == 1
@step.call(5, 10, 6).size.should == 1
@@ -350,7 +336,7 @@ describe :numeric_step, :shared => true do
end
end
- describe "when self, stop and step are Fixnums and step is negative" do
+ describe "when self, stop and step are Integers and step is negative" do
it "returns the difference between self and stop divided by the number of steps" do
@step.call(10, 5, -11).size.should == 1
@step.call(10, 5, -6).size.should == 1
diff --git a/spec/ruby/core/numeric/step_spec.rb b/spec/ruby/core/numeric/step_spec.rb
index e9067864c8..2773000229 100644
--- a/spec/ruby/core/numeric/step_spec.rb
+++ b/spec/ruby/core/numeric/step_spec.rb
@@ -26,12 +26,14 @@ describe "Numeric#step" do
step_enum_class = Enumerator::ArithmeticSequence
end
- it "returns an #{step_enum_class} when step is 0" do
- 1.step(5, 0).should be_an_instance_of(step_enum_class)
- end
+ ruby_version_is ""..."3.0" do
+ it "returns an #{step_enum_class} when step is 0" do
+ 1.step(5, 0).should be_an_instance_of(step_enum_class)
+ end
- it "returns an #{step_enum_class} when step is 0.0" do
- 1.step(2, 0.0).should be_an_instance_of(step_enum_class)
+ it "returns an #{step_enum_class} when step is 0.0" do
+ 1.step(2, 0.0).should be_an_instance_of(step_enum_class)
+ end
end
describe "returned #{step_enum_class}" do
@@ -48,7 +50,7 @@ describe "Numeric#step" do
end
end
- ruby_version_is "2.6" do
+ ruby_version_is "2.6"..."3.0" do
it "is infinity when step is 0" do
enum = 1.step(5, 0)
enum.size.should == Float::INFINITY
@@ -85,18 +87,20 @@ describe "Numeric#step" do
end
describe 'with keyword arguments' do
- it "doesn't raise an error when step is 0" do
- -> { 1.step(to: 5, by: 0) { break } }.should_not raise_error
- end
+ ruby_version_is ""..."3.0" do
+ it "doesn't raise an error when step is 0" do
+ -> { 1.step(to: 5, by: 0) { break } }.should_not raise_error
+ end
- it "doesn't raise an error when step is 0.0" do
- -> { 1.step(to: 2, by: 0.0) { break } }.should_not raise_error
- end
+ it "doesn't raise an error when step is 0.0" do
+ -> { 1.step(to: 2, by: 0.0) { break } }.should_not raise_error
+ end
- it "should loop over self when step is 0 or 0.0" do
- 1.step(to: 2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0]
- 1.step(to: 2, by: 0).take(5).should eql [1, 1, 1, 1, 1]
- 1.1.step(to: 2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1]
+ it "should loop over self when step is 0 or 0.0" do
+ 1.step(to: 2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0]
+ 1.step(to: 2, by: 0).take(5).should eql [1, 1, 1, 1, 1]
+ 1.1.step(to: 2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1]
+ end
end
describe "when no block is given" do
@@ -106,12 +110,14 @@ describe "Numeric#step" do
1.step(by: 42).size.should == infinity_value
end
- it "should return infinity_value when step is 0" do
- 1.step(to: 5, by: 0).size.should == infinity_value
- end
+ ruby_version_is ""..."3.0" do
+ it "should return infinity_value when step is 0" do
+ 1.step(to: 5, by: 0).size.should == infinity_value
+ end
- it "should return infinity_value when step is 0.0" do
- 1.step(to: 2, by: 0.0).size.should == infinity_value
+ it "should return infinity_value when step is 0.0" do
+ 1.step(to: 2, by: 0.0).size.should == infinity_value
+ end
end
it "should return infinity_value when ascending towards a limit of Float::INFINITY" do
@@ -146,12 +152,24 @@ describe "Numeric#step" do
end
describe 'with mixed arguments' do
- it "doesn't raise an error when step is 0" do
- -> { 1.step(5, by: 0) { break } }.should_not raise_error
+ ruby_version_is ""..."3.0" do
+ it "doesn't raise an error when step is 0" do
+ -> { 1.step(5, by: 0) { break } }.should_not raise_error
+ end
+
+ it "doesn't raise an error when step is 0.0" do
+ -> { 1.step(2, by: 0.0) { break } }.should_not raise_error
+ end
end
- it "doesn't raise an error when step is 0.0" do
- -> { 1.step(2, by: 0.0) { break } }.should_not raise_error
+ ruby_version_is "3.0" do
+ it " raises an ArgumentError when step is 0" do
+ -> { 1.step(5, by: 0) { break } }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when step is 0.0" do
+ -> { 1.step(2, by: 0.0) { break } }.should raise_error(ArgumentError)
+ end
end
it "raises a ArgumentError when limit and to are defined" do
@@ -162,21 +180,25 @@ describe "Numeric#step" do
-> { 1.step(5, 1, by: 5) { break } }.should raise_error(ArgumentError)
end
- it "should loop over self when step is 0 or 0.0" do
- 1.step(2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0]
- 1.step(2, by: 0).take(5).should eql [1, 1, 1, 1, 1]
- 1.1.step(2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1]
+ ruby_version_is ""..."3.0" do
+ it "should loop over self when step is 0 or 0.0" do
+ 1.step(2, by: 0.0).take(5).should eql [1.0, 1.0, 1.0, 1.0, 1.0]
+ 1.step(2, by: 0).take(5).should eql [1, 1, 1, 1, 1]
+ 1.1.step(2, by: 0).take(5).should eql [1.1, 1.1, 1.1, 1.1, 1.1]
+ end
end
describe "when no block is given" do
describe "returned Enumerator" do
describe "size" do
- it "should return infinity_value when step is 0" do
- 1.step(5, by: 0).size.should == infinity_value
- end
+ ruby_version_is ""..."3.0" do
+ it "should return infinity_value when step is 0" do
+ 1.step(5, by: 0).size.should == infinity_value
+ end
- it "should return infinity_value when step is 0.0" do
- 1.step(2, by: 0.0).size.should == infinity_value
+ it "should return infinity_value when step is 0.0" do
+ 1.step(2, by: 0.0).size.should == infinity_value
+ end
end
end
end
diff --git a/spec/ruby/core/numeric/zero_spec.rb b/spec/ruby/core/numeric/zero_spec.rb
index 9de71d1dc9..0fb7619bcd 100644
--- a/spec/ruby/core/numeric/zero_spec.rb
+++ b/spec/ruby/core/numeric/zero_spec.rb
@@ -8,11 +8,11 @@ describe "Numeric#zero?" do
it "returns true if self is 0" do
@obj.should_receive(:==).with(0).and_return(true)
- @obj.zero?.should == true
+ @obj.should.zero?
end
it "returns false if self is not 0" do
@obj.should_receive(:==).with(0).and_return(false)
- @obj.zero?.should == false
+ @obj.should_not.zero?
end
end
diff --git a/spec/ruby/core/objectspace/_id2ref_spec.rb b/spec/ruby/core/objectspace/_id2ref_spec.rb
index 1d8ad02deb..6e8828348e 100644
--- a/spec/ruby/core/objectspace/_id2ref_spec.rb
+++ b/spec/ruby/core/objectspace/_id2ref_spec.rb
@@ -7,7 +7,7 @@ describe "ObjectSpace._id2ref" do
r.should == s
end
- it "retrieves a Fixnum by object_id" do
+ it "retrieves an Integer by object_id" do
f = 1
r = ObjectSpace._id2ref(f.object_id)
r.should == f
diff --git a/spec/ruby/core/objectspace/define_finalizer_spec.rb b/spec/ruby/core/objectspace/define_finalizer_spec.rb
index 3f7b1ae576..ed021b7131 100644
--- a/spec/ruby/core/objectspace/define_finalizer_spec.rb
+++ b/spec/ruby/core/objectspace/define_finalizer_spec.rb
@@ -1,24 +1,42 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-# NOTE: A call to define_finalizer does not guarantee that the
-# passed proc or callable will be called at any particular time.
+# Why do we not test that finalizers are run by the GC? The documentation
+# says that finalizers are never guaranteed to be run, so we can't
+# spec that they are. On some implementations of Ruby the finalizers may
+# run asyncronously, meaning that we can't predict when they'll run,
+# even if they were guaranteed to do so. Even on MRI finalizers can be
+# very unpredictable, due to conservative stack scanning and references
+# left in unused memory.
+
describe "ObjectSpace.define_finalizer" do
it "raises an ArgumentError if the action does not respond to call" do
-> {
- ObjectSpace.define_finalizer("", mock("ObjectSpace.define_finalizer no #call"))
+ ObjectSpace.define_finalizer(Object.new, mock("ObjectSpace.define_finalizer no #call"))
}.should raise_error(ArgumentError)
end
it "accepts an object and a proc" do
- handler = -> obj { obj }
- ObjectSpace.define_finalizer("garbage", handler).should == [0, handler]
+ handler = -> id { id }
+ ObjectSpace.define_finalizer(Object.new, handler).should == [0, handler]
+ end
+
+ it "accepts an object and a bound method" do
+ handler = mock("callable")
+ def handler.finalize(id) end
+ finalize = handler.method(:finalize)
+ ObjectSpace.define_finalizer(Object.new, finalize).should == [0, finalize]
end
it "accepts an object and a callable" do
handler = mock("callable")
- def handler.call(obj) end
- ObjectSpace.define_finalizer("garbage", handler).should == [0, handler]
+ def handler.call(id) end
+ ObjectSpace.define_finalizer(Object.new, handler).should == [0, handler]
+ end
+
+ it "accepts an object and a block" do
+ handler = -> id { id }
+ ObjectSpace.define_finalizer(Object.new, &handler).should == [0, handler]
end
it "raises ArgumentError trying to define a finalizer on a non-reference" do
@@ -31,7 +49,7 @@ describe "ObjectSpace.define_finalizer" do
it "calls finalizer on process termination" do
code = <<-RUBY
def scoped
- Proc.new { puts "finalized" }
+ Proc.new { puts "finalizer run" }
end
handler = scoped
obj = "Test"
@@ -39,18 +57,104 @@ describe "ObjectSpace.define_finalizer" do
exit 0
RUBY
- ruby_exe(code).should == "finalized\n"
+ ruby_exe(code, :args => "2>&1").should include("finalizer run\n")
end
- it "calls finalizer at exit even if it is self-referencing" do
+ ruby_version_is "3.0" do
+ it "warns if the finalizer has the object as the receiver" do
+ code = <<-RUBY
+ class CapturesSelf
+ def initialize
+ ObjectSpace.define_finalizer(self, proc {
+ puts "finalizer run"
+ })
+ end
+ end
+ CapturesSelf.new
+ exit 0
+ RUBY
+
+ ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n")
+ end
+
+ it "warns if the finalizer is a method bound to the receiver" do
+ code = <<-RUBY
+ class CapturesSelf
+ def initialize
+ ObjectSpace.define_finalizer(self, method(:finalize))
+ end
+ def finalize(id)
+ puts "finalizer run"
+ end
+ end
+ CapturesSelf.new
+ exit 0
+ RUBY
+
+ ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n")
+ end
+
+ it "warns if the finalizer was a block in the receiver" do
+ code = <<-RUBY
+ class CapturesSelf
+ def initialize
+ ObjectSpace.define_finalizer(self) do
+ puts "finalizer run"
+ end
+ end
+ end
+ CapturesSelf.new
+ exit 0
+ RUBY
+
+ ruby_exe(code, :args => "2>&1").should include("warning: finalizer references object to be finalized\n")
+ end
+ end
+
+ it "calls a finalizer at exit even if it is self-referencing" do
code = <<-RUBY
obj = "Test"
- handler = Proc.new { puts "finalized" }
+ handler = Proc.new { puts "finalizer run" }
+ ObjectSpace.define_finalizer(obj, handler)
+ exit 0
+ RUBY
+
+ ruby_exe(code).should include("finalizer run\n")
+ end
+
+ it "calls a finalizer at exit even if it is indirectly self-referencing" do
+ code = <<-RUBY
+ class CapturesSelf
+ def initialize
+ ObjectSpace.define_finalizer(self, finalizer(self))
+ end
+ def finalizer(zelf)
+ proc do
+ puts "finalizer run"
+ end
+ end
+ end
+ CapturesSelf.new
+ exit 0
+ RUBY
+
+ ruby_exe(code, :args => "2>&1").should include("finalizer run\n")
+ end
+
+ it "calls a finalizer defined in a finalizer running at exit" do
+ code = <<-RUBY
+ obj = "Test"
+ handler = Proc.new do
+ obj2 = "Test"
+ handler2 = Proc.new { puts "finalizer 2 run" }
+ ObjectSpace.define_finalizer(obj2, handler2)
+ exit 0
+ end
ObjectSpace.define_finalizer(obj, handler)
exit 0
RUBY
- ruby_exe(code).should == "finalized\n"
+ ruby_exe(code, :args => "2>&1").should include("finalizer 2 run\n")
end
it "allows multiple finalizers with different 'callables' to be defined" do
diff --git a/spec/ruby/core/objectspace/weakmap/each_key_spec.rb b/spec/ruby/core/objectspace/weakmap/each_key_spec.rb
new file mode 100644
index 0000000000..df971deeb9
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/each_key_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/members'
+require_relative 'shared/each'
+
+describe "ObjectSpace::WeakMap#each_key" do
+ it_behaves_like :weakmap_members, -> map { a = []; map.each_key{ |k| a << k }; a }, %w[A B]
+end
+
+describe "ObjectSpace::WeakMap#each_key" do
+ it_behaves_like :weakmap_each, :each_key
+end
diff --git a/spec/ruby/core/objectspace/weakmap/each_pair_spec.rb b/spec/ruby/core/objectspace/weakmap/each_pair_spec.rb
new file mode 100644
index 0000000000..ea29edbd2f
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/each_pair_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/members'
+require_relative 'shared/each'
+
+describe "ObjectSpace::WeakMap#each_pair" do
+ it_behaves_like :weakmap_members, -> map { a = []; map.each_pair{ |k,v| a << "#{k}#{v}" }; a }, %w[Ax By]
+end
+
+describe "ObjectSpace::WeakMap#each_key" do
+ it_behaves_like :weakmap_each, :each_pair
+end
diff --git a/spec/ruby/core/objectspace/weakmap/each_spec.rb b/spec/ruby/core/objectspace/weakmap/each_spec.rb
new file mode 100644
index 0000000000..46fcb66a6f
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/each_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/members'
+require_relative 'shared/each'
+
+describe "ObjectSpace::WeakMap#each" do
+ it_behaves_like :weakmap_members, -> map { a = []; map.each{ |k,v| a << "#{k}#{v}" }; a }, %w[Ax By]
+end
+
+describe "ObjectSpace::WeakMap#each_key" do
+ it_behaves_like :weakmap_each, :each
+end
diff --git a/spec/ruby/core/objectspace/weakmap/each_value_spec.rb b/spec/ruby/core/objectspace/weakmap/each_value_spec.rb
new file mode 100644
index 0000000000..65a1a7f6fe
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/each_value_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/members'
+require_relative 'shared/each'
+
+describe "ObjectSpace::WeakMap#each_value" do
+ it_behaves_like :weakmap_members, -> map { a = []; map.each_value{ |k| a << k }; a }, %w[x y]
+end
+
+describe "ObjectSpace::WeakMap#each_key" do
+ it_behaves_like :weakmap_each, :each_value
+end
diff --git a/spec/ruby/core/objectspace/weakmap/element_reference_spec.rb b/spec/ruby/core/objectspace/weakmap/element_reference_spec.rb
new file mode 100644
index 0000000000..cb3174cbfa
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/element_reference_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakMap#[]" do
+ it "is faithful to the map's content" do
+ map = ObjectSpace::WeakMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+ map[key1] = ref1
+ map[key1].should == ref1
+ map[key1] = ref1
+ map[key1].should == ref1
+ map[key2] = ref2
+ map[key1].should == ref1
+ map[key2].should == ref2
+ end
+
+ it "matches using identity semantics" do
+ map = ObjectSpace::WeakMap.new
+ key1, key2 = %w[a a].map(&:upcase)
+ ref = "x"
+ map[key1] = ref
+ map[key2].should == nil
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakmap/element_set_spec.rb b/spec/ruby/core/objectspace/weakmap/element_set_spec.rb
new file mode 100644
index 0000000000..2b53650148
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/element_set_spec.rb
@@ -0,0 +1,61 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakMap#[]=" do
+ def should_accept(map, key, value)
+ (map[key] = value).should == value
+ map.should.key?(key)
+ map[key].should == value
+ end
+
+ it "is correct" do
+ map = ObjectSpace::WeakMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+ should_accept(map, key1, ref1)
+ should_accept(map, key1, ref1)
+ should_accept(map, key2, ref2)
+ map[key1].should == ref1
+ end
+
+ ruby_version_is ""..."2.7" do
+ it "does not accept primitive or frozen keys or values" do
+ map = ObjectSpace::WeakMap.new
+ x = Object.new
+ -> { map[true] = x }.should raise_error(ArgumentError)
+ -> { map[false] = x }.should raise_error(ArgumentError)
+ -> { map[nil] = x }.should raise_error(ArgumentError)
+ -> { map[42] = x }.should raise_error(ArgumentError)
+ -> { map[:foo] = x }.should raise_error(ArgumentError)
+ -> { map[x] = true }.should raise_error(ArgumentError)
+ -> { map[x] = false }.should raise_error(ArgumentError)
+ -> { map[x] = nil }.should raise_error(ArgumentError)
+ -> { map[x] = 42 }.should raise_error(ArgumentError)
+ -> { map[x] = :foo }.should raise_error(ArgumentError)
+
+ y = Object.new.freeze
+ -> { map[x] = y}.should raise_error(FrozenError)
+ -> { map[y] = x}.should raise_error(FrozenError)
+ end
+ end
+
+ ruby_version_is "2.7" do
+ it "accepts primitive or frozen keys or values" do
+ map = ObjectSpace::WeakMap.new
+ x = Object.new
+ should_accept(map, true, x)
+ should_accept(map, false, x)
+ should_accept(map, nil, x)
+ should_accept(map, 42, x)
+ should_accept(map, :foo, x)
+
+ should_accept(map, x, true)
+ should_accept(map, x, false)
+ should_accept(map, x, 42)
+ should_accept(map, x, :foo)
+
+ y = Object.new.freeze
+ should_accept(map, x, y)
+ should_accept(map, y, x)
+ end
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakmap/include_spec.rb b/spec/ruby/core/objectspace/weakmap/include_spec.rb
new file mode 100644
index 0000000000..54ca6b3030
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/include_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/include'
+
+describe "ObjectSpace::WeakMap#include?" do
+ it_behaves_like :weakmap_include?, :include?
+end
diff --git a/spec/ruby/core/objectspace/weakmap/inspect_spec.rb b/spec/ruby/core/objectspace/weakmap/inspect_spec.rb
new file mode 100644
index 0000000000..f064f6e3ea
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/inspect_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../../spec_helper'
+
+describe "ObjectSpace::WeakMap#inspect" do
+ it "displays object pointers in output" do
+ map = ObjectSpace::WeakMap.new
+ # important to test with BasicObject (without Kernel) here to test edge cases
+ key1, key2 = [BasicObject.new, Object.new]
+ ref1, ref2 = [BasicObject.new, Object.new]
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakMap:0x\h+>\z/
+ map[key1] = ref1
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakMap:0x\h+: \#<BasicObject:0x\h+> => \#<BasicObject:0x\h+>>\z/
+ map[key1] = ref1
+ map.inspect.should =~ /\A\#<ObjectSpace::WeakMap:0x\h+: \#<BasicObject:0x\h+> => \#<BasicObject:0x\h+>>\z/
+ map[key2] = ref2
+
+ regexp1 = /\A\#<ObjectSpace::WeakMap:0x\h+: \#<BasicObject:0x\h+> => \#<BasicObject:0x\h+>, \#<Object:0x\h+> => \#<Object:0x\h+>>\z/
+ regexp2 = /\A\#<ObjectSpace::WeakMap:0x\h+: \#<Object:0x\h+> => \#<Object:0x\h+>, \#<BasicObject:0x\h+> => \#<BasicObject:0x\h+>>\z/
+ str = map.inspect
+ if str =~ regexp1
+ str.should =~ regexp1
+ else
+ str.should =~ regexp2
+ end
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakmap/key_spec.rb b/spec/ruby/core/objectspace/weakmap/key_spec.rb
new file mode 100644
index 0000000000..999685ff95
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/key_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/include'
+
+describe "ObjectSpace::WeakMap#key?" do
+ it_behaves_like :weakmap_include?, :key?
+end
diff --git a/spec/ruby/core/objectspace/weakmap/keys_spec.rb b/spec/ruby/core/objectspace/weakmap/keys_spec.rb
new file mode 100644
index 0000000000..7b1494bdd7
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/keys_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/members'
+
+describe "ObjectSpace::WeakMap#keys" do
+ it_behaves_like :weakmap_members, -> map { map.keys }, %w[A B]
+end
diff --git a/spec/ruby/core/objectspace/weakmap/length_spec.rb b/spec/ruby/core/objectspace/weakmap/length_spec.rb
new file mode 100644
index 0000000000..3a935648b1
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/length_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/size'
+
+describe "ObjectSpace::WeakMap#length" do
+ it_behaves_like :weakmap_size, :length
+end
diff --git a/spec/ruby/core/objectspace/weakmap/member_spec.rb b/spec/ruby/core/objectspace/weakmap/member_spec.rb
new file mode 100644
index 0000000000..cefb190ce7
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/member_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/include'
+
+describe "ObjectSpace::WeakMap#member?" do
+ it_behaves_like :weakmap_include?, :member?
+end
diff --git a/spec/ruby/core/objectspace/weakmap/shared/each.rb b/spec/ruby/core/objectspace/weakmap/shared/each.rb
new file mode 100644
index 0000000000..3d43a19347
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/shared/each.rb
@@ -0,0 +1,10 @@
+describe :weakmap_each, shared: true do
+ it "must take a block, except when empty" do
+ map = ObjectSpace::WeakMap.new
+ key = "a".upcase
+ ref = "x"
+ map.send(@method).should == map
+ map[key] = ref
+ -> { map.send(@method) }.should raise_error(LocalJumpError)
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakmap/shared/include.rb b/spec/ruby/core/objectspace/weakmap/shared/include.rb
new file mode 100644
index 0000000000..f9c174b6d1
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/shared/include.rb
@@ -0,0 +1,34 @@
+describe :weakmap_include?, shared: true do
+ it "recognizes keys in use" do
+ map = ObjectSpace::WeakMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+
+ map[key1] = ref1
+ map.send(@method, key1).should == true
+ map[key1] = ref1
+ map.send(@method, key1).should == true
+ map[key2] = ref2
+ map.send(@method, key2).should == true
+ end
+
+ it "matches using identity semantics" do
+ map = ObjectSpace::WeakMap.new
+ key1, key2 = %w[a a].map(&:upcase)
+ ref = "x"
+ map[key1] = ref
+ map.send(@method, key2).should == false
+ end
+
+ ruby_version_is "2.7" do
+ ruby_bug "#16826", "2.7.0"..."2.7.2" do
+ it "reports true if the pair exists and the value is nil" do
+ map = ObjectSpace::WeakMap.new
+ key = Object.new
+ map[key] = nil
+ map.size.should == 1
+ map.send(@method, key).should == true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakmap/shared/members.rb b/spec/ruby/core/objectspace/weakmap/shared/members.rb
new file mode 100644
index 0000000000..57226c8d7a
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/shared/members.rb
@@ -0,0 +1,14 @@
+describe :weakmap_members, shared: true do
+ it "is correct" do
+ map = ObjectSpace::WeakMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+ @method.call(map).should == []
+ map[key1] = ref1
+ @method.call(map).should == @object[0..0]
+ map[key1] = ref1
+ @method.call(map).should == @object[0..0]
+ map[key2] = ref2
+ @method.call(map).sort.should == @object
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakmap/shared/size.rb b/spec/ruby/core/objectspace/weakmap/shared/size.rb
new file mode 100644
index 0000000000..1064f99d1b
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/shared/size.rb
@@ -0,0 +1,14 @@
+describe :weakmap_size, shared: true do
+ it "is correct" do
+ map = ObjectSpace::WeakMap.new
+ key1, key2 = %w[a b].map(&:upcase)
+ ref1, ref2 = %w[x y]
+ map.send(@method).should == 0
+ map[key1] = ref1
+ map.send(@method).should == 1
+ map[key1] = ref1
+ map.send(@method).should == 1
+ map[key2] = ref2
+ map.send(@method).should == 2
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakmap/size_spec.rb b/spec/ruby/core/objectspace/weakmap/size_spec.rb
new file mode 100644
index 0000000000..1446abaa24
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/size_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/size'
+
+describe "ObjectSpace::WeakMap#size" do
+ it_behaves_like :weakmap_size, :size
+end
diff --git a/spec/ruby/core/objectspace/weakmap/values_spec.rb b/spec/ruby/core/objectspace/weakmap/values_spec.rb
new file mode 100644
index 0000000000..6f6f90d0ba
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap/values_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/members'
+
+describe "ObjectSpace::WeakMap#values" do
+ it_behaves_like :weakmap_members, -> map { map.values }, %w[x y]
+end
diff --git a/spec/ruby/core/objectspace/weakmap_spec.rb b/spec/ruby/core/objectspace/weakmap_spec.rb
new file mode 100644
index 0000000000..2f3f93c291
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakmap_spec.rb
@@ -0,0 +1,12 @@
+require_relative '../../spec_helper'
+
+describe "ObjectSpace::WeakMap" do
+
+ # Note that we can't really spec the most important aspect of this class: that entries get removed when the values
+ # become unreachable. This is because Ruby does not offer a way to reliable invoke GC (GC.start is not enough, neither
+ # on MRI or on alternative implementations).
+
+ it "includes Enumerable" do
+ ObjectSpace::WeakMap.include?(Enumerable).should == true
+ end
+end
diff --git a/spec/ruby/core/proc/compose_spec.rb b/spec/ruby/core/proc/compose_spec.rb
index ef9c125ae9..285e96192b 100644
--- a/spec/ruby/core/proc/compose_spec.rb
+++ b/spec/ruby/core/proc/compose_spec.rb
@@ -35,16 +35,16 @@ ruby_version_is "2.6" do
g = proc { |x| x + x }
(f << g).is_a?(Proc).should == true
- (f << g).lambda?.should == false
+ (f << g).should_not.lambda?
end
- ruby_version_is(''...'2.8') do
+ ruby_version_is(''...'3.0') do
it "is a Proc when other is lambda" do
f = proc { |x| x * x }
g = -> x { x + x }
(f << g).is_a?(Proc).should == true
- (f << g).lambda?.should == false
+ (f << g).should_not.lambda?
end
it "is a lambda when self is lambda" do
@@ -52,19 +52,19 @@ ruby_version_is "2.6" do
g = proc { |x| x + x }
(f << g).is_a?(Proc).should == true
- (f << g).lambda?.should == true
+ (f << g).should.lambda?
end
end
- ruby_version_is('2.8') do
+ ruby_version_is('3.0') do
it "is a lambda when parameter is lambda" do
f = -> x { x * x }
g = proc { |x| x + x }
lambda_proc = -> x { x }
(f << g).is_a?(Proc).should == true
- (f << g).lambda?.should == false
- (f << lambda_proc).lambda?.should == true
+ (f << g).should_not.lambda?
+ (f << lambda_proc).should.lambda?
end
end
@@ -118,7 +118,7 @@ ruby_version_is "2.6" do
g = proc { |x| x + x }
(f >> g).is_a?(Proc).should == true
- (f >> g).lambda?.should == false
+ (f >> g).should_not.lambda?
end
it "is a Proc when other is lambda" do
@@ -126,7 +126,7 @@ ruby_version_is "2.6" do
g = -> x { x + x }
(f >> g).is_a?(Proc).should == true
- (f >> g).lambda?.should == false
+ (f >> g).should_not.lambda?
end
it "is a lambda when self is lambda" do
@@ -134,7 +134,7 @@ ruby_version_is "2.6" do
g = proc { |x| x + x }
(f >> g).is_a?(Proc).should == true
- (f >> g).lambda?.should == true
+ (f >> g).should.lambda?
end
it "may accept multiple arguments" do
diff --git a/spec/ruby/core/proc/eql_spec.rb b/spec/ruby/core/proc/eql_spec.rb
index a3c5a5658d..5f38af72d9 100644
--- a/spec/ruby/core/proc/eql_spec.rb
+++ b/spec/ruby/core/proc/eql_spec.rb
@@ -2,5 +2,11 @@ require_relative '../../spec_helper'
require_relative 'shared/equal'
describe "Proc#eql?" do
- it_behaves_like :proc_equal_undefined, :eql?
+ ruby_version_is "0"..."3.0" do
+ it_behaves_like :proc_equal_undefined, :eql?
+ end
+
+ ruby_version_is "3.0" do
+ it_behaves_like :proc_equal, :eql?
+ end
end
diff --git a/spec/ruby/core/proc/equal_value_spec.rb b/spec/ruby/core/proc/equal_value_spec.rb
index 1b6ac792cf..4c336331d7 100644
--- a/spec/ruby/core/proc/equal_value_spec.rb
+++ b/spec/ruby/core/proc/equal_value_spec.rb
@@ -2,5 +2,11 @@ require_relative '../../spec_helper'
require_relative 'shared/equal'
describe "Proc#==" do
- it_behaves_like :proc_equal_undefined, :==
+ ruby_version_is "0"..."3.0" do
+ it_behaves_like :proc_equal_undefined, :==
+ end
+
+ ruby_version_is "3.0" do
+ it_behaves_like :proc_equal, :==
+ end
end
diff --git a/spec/ruby/core/proc/fixtures/source_location.rb b/spec/ruby/core/proc/fixtures/source_location.rb
index 688dac1e22..5572094630 100644
--- a/spec/ruby/core/proc/fixtures/source_location.rb
+++ b/spec/ruby/core/proc/fixtures/source_location.rb
@@ -44,7 +44,7 @@ module ProcSpecs
def self.my_detached_lambda
body = -> { true }
- lambda(&body)
+ suppress_warning {lambda(&body)}
end
def self.my_detached_proc_new
diff --git a/spec/ruby/core/proc/hash_spec.rb b/spec/ruby/core/proc/hash_spec.rb
index d780c1ceb0..ebe0fde1a0 100644
--- a/spec/ruby/core/proc/hash_spec.rb
+++ b/spec/ruby/core/proc/hash_spec.rb
@@ -7,7 +7,7 @@ describe "Proc#hash" do
end
it "returns an Integer" do
- proc { 1 + 489 }.hash.should be_kind_of(Fixnum)
+ proc { 1 + 489 }.hash.should be_kind_of(Integer)
end
it "is stable" do
diff --git a/spec/ruby/core/proc/lambda_spec.rb b/spec/ruby/core/proc/lambda_spec.rb
index fe2ceb4279..b2d3f50350 100644
--- a/spec/ruby/core/proc/lambda_spec.rb
+++ b/spec/ruby/core/proc/lambda_spec.rb
@@ -15,8 +15,8 @@ describe "Proc#lambda?" do
end
it "is preserved when passing a Proc with & to the lambda keyword" do
- lambda(&->{}).lambda?.should be_true
- lambda(&proc{}).lambda?.should be_false
+ suppress_warning {lambda(&->{})}.lambda?.should be_true
+ suppress_warning {lambda(&proc{})}.lambda?.should be_false
end
it "is preserved when passing a Proc with & to the proc keyword" do
diff --git a/spec/ruby/core/proc/new_spec.rb b/spec/ruby/core/proc/new_spec.rb
index 8faf142614..6d5eb67a4b 100644
--- a/spec/ruby/core/proc/new_spec.rb
+++ b/spec/ruby/core/proc/new_spec.rb
@@ -203,15 +203,7 @@ describe "Proc.new without a block" do
end
end
- ruby_version_is "2.7" do
- before :each do
- @deprecated = Warning[:deprecated]
- Warning[:deprecated] = true
- end
- after :each do
- Warning[:deprecated] = @deprecated
- end
-
+ ruby_version_is "2.7"..."3.0" do
it "can be created if invoked from within a method with a block" do
-> { ProcSpecs.new_proc_in_method { "hello" } }.should complain(/Capturing the given block using Proc.new is deprecated/)
end
@@ -231,4 +223,16 @@ describe "Proc.new without a block" do
}.should complain(/Capturing the given block using Proc.new is deprecated/)
end
end
+
+ ruby_version_is "3.0" do
+ it "raises an ArgumentError when passed no block" do
+ def some_method
+ Proc.new
+ end
+
+ -> { ProcSpecs.new_proc_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
+ -> { ProcSpecs.new_proc_subclass_in_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
+ -> { some_method { "hello" } }.should raise_error(ArgumentError, 'tried to create Proc object without a block')
+ end
+ end
end
diff --git a/spec/ruby/core/proc/parameters_spec.rb b/spec/ruby/core/proc/parameters_spec.rb
index 2bc5f1325c..5fb5cf418d 100644
--- a/spec/ruby/core/proc/parameters_spec.rb
+++ b/spec/ruby/core/proc/parameters_spec.rb
@@ -57,7 +57,7 @@ describe "Proc#parameters" do
end
it "sets the first element of each sub-Array to :block for parameters prefixed with ampersands" do
- ->&x { }.parameters.first.first.should == :block
+ -> &x { }.parameters.first.first.should == :block
-> x, &y { }.parameters.last.first.should == :block
proc {|&x| }.parameters.first.first.should == :block
proc {|x,&y| }.parameters.last.first.should == :block
@@ -68,7 +68,7 @@ describe "Proc#parameters" do
-> x=Math::PI { }.parameters.first.last.should == :x
-> an_argument, glark, &foo { }.parameters[1].last.should == :glark
-> *rest { }.parameters.first.last.should == :rest
- ->&block { }.parameters.first.last.should == :block
+ -> &block { }.parameters.first.last.should == :block
proc {|x| }.parameters.first.last.should == :x
proc {|x=Math::PI| }.parameters.first.last.should == :x
proc {|an_argument, glark, &foo| }.parameters[1].last.should == :glark
diff --git a/spec/ruby/core/proc/shared/call_arguments.rb b/spec/ruby/core/proc/shared/call_arguments.rb
index ef6ec04620..91ada3439e 100644
--- a/spec/ruby/core/proc/shared/call_arguments.rb
+++ b/spec/ruby/core/proc/shared/call_arguments.rb
@@ -1,7 +1,7 @@
describe :proc_call_block_args, shared: true do
it "can receive block arguments" do
Proc.new {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2
- ->&b { b.send(@method)}.send(@method) {1 + 1}.should == 2
+ -> &b { b.send(@method)}.send(@method) {1 + 1}.should == 2
proc {|&b| b.send(@method)}.send(@method) {1 + 1}.should == 2
end
diff --git a/spec/ruby/core/proc/shared/equal.rb b/spec/ruby/core/proc/shared/equal.rb
index 46a1894424..0c0020ca7f 100644
--- a/spec/ruby/core/proc/shared/equal.rb
+++ b/spec/ruby/core/proc/shared/equal.rb
@@ -36,26 +36,26 @@ describe :proc_equal, shared: true do
a.send(@method, b).should be_false
end
- it "returns true if both procs have the same body and environment" do
+ it "returns false if procs are distinct but have the same body and environment" do
p = proc { :foo }
p2 = proc { :foo }
- p.send(@method, p2).should be_true
+ p.send(@method, p2).should be_false
end
- it "returns true if both lambdas with the same body and environment" do
+ it "returns false if lambdas are distinct but have same body and environment" do
x = -> { :foo }
x2 = -> { :foo }
- x.send(@method, x2).should be_true
+ x.send(@method, x2).should be_false
end
- it "returns true if both different kinds of procs with the same body and env" do
+ it "returns false if using comparing lambda to proc, even with the same body and env" do
p = -> { :foo }
p2 = proc { :foo }
- p.send(@method, p2).should be_true
+ p.send(@method, p2).should be_false
x = proc { :bar }
x2 = -> { :bar }
- x.send(@method, x2).should be_true
+ x.send(@method, x2).should be_false
end
it "returns false if other is not a Proc" do
diff --git a/spec/ruby/core/proc/shared/to_s.rb b/spec/ruby/core/proc/shared/to_s.rb
index 8b9c83927f..7f167a3d9d 100644
--- a/spec/ruby/core/proc/shared/to_s.rb
+++ b/spec/ruby/core/proc/shared/to_s.rb
@@ -33,8 +33,13 @@ describe :proc_to_s, shared: true do
describe "for a proc created with UnboundMethod#to_proc" do
it "returns a description including '(lambda)' and optionally including file and line number" do
- def hello; end
- method("hello").to_proc.send(@method).should =~ /^#<Proc:([^ ]*?)(#{sep}#{Regexp.escape __FILE__}:#{__LINE__ })? \(lambda\)>$/
+ def hello; end
+ s = method("hello").to_proc.send(@method)
+ if s.include? __FILE__
+ s.should =~ /^#<Proc:([^ ]*?)#{sep}#{Regexp.escape __FILE__}:#{__LINE__ - 3} \(lambda\)>$/
+ else
+ s.should =~ /^#<Proc:([^ ]*?) \(lambda\)>$/
+ end
end
it "has a binary encoding" do
@@ -46,7 +51,7 @@ describe :proc_to_s, shared: true do
describe "for a proc created with Symbol#to_proc" do
it "returns a description including '(&:symbol)'" do
proc = :foobar.to_proc
- proc.send(@method).should =~ /^#<Proc:0x\h+\(&:foobar\)>$/
+ proc.send(@method).should.include?('(&:foobar)')
end
it "has a binary encoding" do
diff --git a/spec/ruby/core/proc/source_location_spec.rb b/spec/ruby/core/proc/source_location_spec.rb
index b5b8178df2..f268499b82 100644
--- a/spec/ruby/core/proc/source_location_spec.rb
+++ b/spec/ruby/core/proc/source_location_spec.rb
@@ -34,21 +34,21 @@ describe "Proc#source_location" do
file.should == File.realpath('../fixtures/source_location.rb', __FILE__)
end
- it "sets the last value to a Fixnum representing the line on which the proc was defined" do
+ it "sets the last value to an Integer representing the line on which the proc was defined" do
line = @proc.source_location.last
- line.should be_an_instance_of(Fixnum)
+ line.should be_an_instance_of(Integer)
line.should == 4
line = @proc_new.source_location.last
- line.should be_an_instance_of(Fixnum)
+ line.should be_an_instance_of(Integer)
line.should == 12
line = @lambda.source_location.last
- line.should be_an_instance_of(Fixnum)
+ line.should be_an_instance_of(Integer)
line.should == 8
line = @method.source_location.last
- line.should be_an_instance_of(Fixnum)
+ line.should be_an_instance_of(Integer)
line.should == 15
end
diff --git a/spec/ruby/core/process/euid_spec.rb b/spec/ruby/core/process/euid_spec.rb
index 7bbacfadfd..a2f1bbf42e 100644
--- a/spec/ruby/core/process/euid_spec.rb
+++ b/spec/ruby/core/process/euid_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Process.euid" do
it "returns the effective user ID for this process" do
- Process.euid.should be_kind_of(Fixnum)
+ Process.euid.should be_kind_of(Integer)
end
it "also goes by Process::UID.eid" do
diff --git a/spec/ruby/core/process/exec_spec.rb b/spec/ruby/core/process/exec_spec.rb
index 5a6e3fc1a4..deb8913b6b 100644
--- a/spec/ruby/core/process/exec_spec.rb
+++ b/spec/ruby/core/process/exec_spec.rb
@@ -29,16 +29,8 @@ describe "Process.exec" do
end
end
- platform_is_not :openbsd do
- it "raises Errno::EACCES when passed a directory" do
- -> { Process.exec File.dirname(__FILE__) }.should raise_error(Errno::EACCES)
- end
- end
-
- platform_is :openbsd do
- it "raises Errno::EISDIR when passed a directory" do
- -> { Process.exec File.dirname(__FILE__) }.should raise_error(Errno::EISDIR)
- end
+ it "raises Errno::EACCES when passed a directory" do
+ -> { Process.exec File.dirname(__FILE__) }.should raise_error(Errno::EACCES)
end
it "runs the specified command, replacing current process" do
@@ -201,9 +193,11 @@ describe "Process.exec" do
map_fd_fixture = fixture __FILE__, "map_fd.rb"
cmd = <<-EOC
f = File.open(#{@name.inspect}, "w+")
- child_fd = f.fileno + 1
- File.open(#{@child_fd_file.inspect}, "w") { |io| io.print child_fd }
- Process.exec "#{ruby_cmd(map_fd_fixture)} \#{child_fd}", { child_fd => f }
+ File.open(#{__FILE__.inspect}, "r") do |io|
+ child_fd = io.fileno
+ File.open(#{@child_fd_file.inspect}, "w") { |io| io.print child_fd }
+ Process.exec "#{ruby_cmd(map_fd_fixture)} \#{child_fd}", { child_fd => f }
+ end
EOC
ruby_exe(cmd, escape: true)
diff --git a/spec/ruby/core/process/getpriority_spec.rb b/spec/ruby/core/process/getpriority_spec.rb
index 4b66e18679..a35e5956a5 100644
--- a/spec/ruby/core/process/getpriority_spec.rb
+++ b/spec/ruby/core/process/getpriority_spec.rb
@@ -5,19 +5,19 @@ describe "Process.getpriority" do
it "coerces arguments to Integers" do
ret = Process.getpriority mock_int(Process::PRIO_PROCESS), mock_int(0)
- ret.should be_kind_of(Fixnum)
+ ret.should be_kind_of(Integer)
end
it "gets the scheduling priority for a specified process" do
- Process.getpriority(Process::PRIO_PROCESS, 0).should be_kind_of(Fixnum)
+ Process.getpriority(Process::PRIO_PROCESS, 0).should be_kind_of(Integer)
end
it "gets the scheduling priority for a specified process group" do
- Process.getpriority(Process::PRIO_PGRP, 0).should be_kind_of(Fixnum)
+ Process.getpriority(Process::PRIO_PGRP, 0).should be_kind_of(Integer)
end
it "gets the scheduling priority for a specified user" do
- Process.getpriority(Process::PRIO_USER, 0).should be_kind_of(Fixnum)
+ Process.getpriority(Process::PRIO_USER, 0).should be_kind_of(Integer)
end
end
end
diff --git a/spec/ruby/core/process/groups_spec.rb b/spec/ruby/core/process/groups_spec.rb
index cbbe4fed25..33e0f9d7b3 100644
--- a/spec/ruby/core/process/groups_spec.rb
+++ b/spec/ruby/core/process/groups_spec.rb
@@ -4,6 +4,10 @@ describe "Process.groups" do
platform_is_not :windows do
it "gets an Array of the gids of groups in the supplemental group access list" do
groups = `id -G`.scan(/\d+/).map { |i| i.to_i }
+ # Include the standard `id` command output. On macOS, GNU
+ # coreutils `id` is limited to NGROUPS_MAX groups, because of
+ # the backward compatibility of getgroups(2).
+ (groups |= `/usr/bin/id -G`.scan(/\d+/).map { |i| i.to_i }) rescue nil
gid = Process.gid
expected = (groups.sort - [gid]).uniq.sort
diff --git a/spec/ruby/core/process/kill_spec.rb b/spec/ruby/core/process/kill_spec.rb
index 4bd64a1fe8..af9c9e6deb 100644
--- a/spec/ruby/core/process/kill_spec.rb
+++ b/spec/ruby/core/process/kill_spec.rb
@@ -16,7 +16,7 @@ describe "Process.kill" do
-> { Process.kill("term", @pid) }.should raise_error(ArgumentError)
end
- it "raises an ArgumentError if signal is not a Fixnum or String" do
+ it "raises an ArgumentError if signal is not an Integer or String" do
signal = mock("process kill signal")
signal.should_not_receive(:to_int)
diff --git a/spec/ruby/core/process/last_status_spec.rb b/spec/ruby/core/process/last_status_spec.rb
index 3898dd6b95..2372f2aae3 100644
--- a/spec/ruby/core/process/last_status_spec.rb
+++ b/spec/ruby/core/process/last_status_spec.rb
@@ -1,20 +1,18 @@
require_relative '../../spec_helper'
-ruby_version_is '2.5' do
- describe 'Process#last_status' do
- it 'returns the status of the last executed child process in the current thread' do
- pid = Process.wait Process.spawn("exit 0")
- Process.last_status.pid.should == pid
- end
+describe 'Process#last_status' do
+ it 'returns the status of the last executed child process in the current thread' do
+ pid = Process.wait Process.spawn("exit 0")
+ Process.last_status.pid.should == pid
+ end
- it 'returns nil if no child process has been ever executed in the current thread' do
- Thread.new do
- Process.last_status.should == nil
- end.join
- end
+ it 'returns nil if no child process has been ever executed in the current thread' do
+ Thread.new do
+ Process.last_status.should == nil
+ end.join
+ end
- it 'raises an ArgumentError if any arguments are provided' do
- -> { Process.last_status(1) }.should raise_error(ArgumentError)
- end
+ it 'raises an ArgumentError if any arguments are provided' do
+ -> { Process.last_status(1) }.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/core/process/maxgroups_spec.rb b/spec/ruby/core/process/maxgroups_spec.rb
index 362f788ab2..2549a7a971 100644
--- a/spec/ruby/core/process/maxgroups_spec.rb
+++ b/spec/ruby/core/process/maxgroups_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
platform_is_not :windows do
describe "Process.maxgroups" do
it "returns the maximum number of gids allowed in the supplemental group access list" do
- Process.maxgroups.should be_kind_of(Fixnum)
+ Process.maxgroups.should be_kind_of(Integer)
end
it "sets the maximum number of gids allowed in the supplemental group access list" do
diff --git a/spec/ruby/core/process/pid_spec.rb b/spec/ruby/core/process/pid_spec.rb
index c5947ab50d..2d008bc4b7 100644
--- a/spec/ruby/core/process/pid_spec.rb
+++ b/spec/ruby/core/process/pid_spec.rb
@@ -3,7 +3,7 @@ require_relative '../../spec_helper'
describe "Process.pid" do
it "returns the process id of this process" do
pid = Process.pid
- pid.should be_kind_of(Fixnum)
+ pid.should be_kind_of(Integer)
Process.pid.should == pid
end
end
diff --git a/spec/ruby/core/process/spawn_spec.rb b/spec/ruby/core/process/spawn_spec.rb
index 06ad9a2518..e373d8600c 100644
--- a/spec/ruby/core/process/spawn_spec.rb
+++ b/spec/ruby/core/process/spawn_spec.rb
@@ -48,10 +48,10 @@ describe "Process.spawn" do
-> { Process.wait Process.spawn("echo spawn") }.should output_to_fd("spawn\n")
end
- it "returns the process ID of the new process as a Fixnum" do
+ it "returns the process ID of the new process as an Integer" do
pid = Process.spawn(*ruby_exe, "-e", "exit")
Process.wait pid
- pid.should be_an_instance_of(Fixnum)
+ pid.should be_an_instance_of(Integer)
end
it "returns immediately" do
@@ -207,13 +207,9 @@ describe "Process.spawn" do
it "unsets environment variables whose value is nil" do
ENV["FOO"] = "BAR"
- Process.wait Process.spawn({"FOO" => nil}, "echo #{@var}>#{@name}")
- expected = "\n"
- platform_is :windows do
- # Windows does not expand the variable if it is unset
- expected = "#{@var}\n"
- end
- File.read(@name).should == expected
+ -> do
+ Process.wait Process.spawn({"FOO" => nil}, ruby_cmd("p ENV['FOO']"))
+ end.should output_to_fd("nil\n")
end
it "calls #to_hash to convert the environment" do
@@ -419,7 +415,7 @@ describe "Process.spawn" do
it "kills extra chdir processes" do
pid = nil
- Dir.chdir("/tmp") do
+ Dir.chdir("/") do
pid = Process.spawn("sleep 10")
end
@@ -461,7 +457,7 @@ describe "Process.spawn" do
# redirection
- it "redirects STDOUT to the given file descriptor if out: Fixnum" do
+ it "redirects STDOUT to the given file descriptor if out: Integer" do
File.open(@name, 'w') do |file|
-> do
Process.wait Process.spawn("echo glark", out: file.fileno)
@@ -487,7 +483,7 @@ describe "Process.spawn" do
File.read(@name).should == "glark\n"
end
- it "redirects STDERR to the given file descriptor if err: Fixnum" do
+ it "redirects STDERR to the given file descriptor if err: Integer" do
File.open(@name, 'w') do |file|
-> do
Process.wait Process.spawn("echo glark>&2", err: file.fileno)
@@ -540,6 +536,17 @@ describe "Process.spawn" do
File.read(@name).should == "glarkbang"
end
+ platform_is_not :windows, :android do
+ it "closes STDERR in the child if :err => :close" do
+ File.open(@name, 'w') do |file|
+ -> do
+ code = "begin; STDOUT.puts 'out'; STDERR.puts 'hello'; rescue => e; puts 'rescued'; end"
+ Process.wait Process.spawn(ruby_cmd(code), :out => file, :err => :close)
+ end.should output_to_fd("out\nrescued\n", file)
+ end
+ end
+ end
+
# :close_others
platform_is_not :windows do
@@ -699,13 +706,15 @@ describe "Process.spawn" do
end
it "maps the key to a file descriptor in the child that inherits the file descriptor from the parent specified by the value" do
- child_fd = find_unused_fd
- args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s])
- pid = Process.spawn(*args, { child_fd => @io })
- Process.waitpid pid
- @io.rewind
-
- @io.read.should == "writing to fd: #{child_fd}"
+ File.open(__FILE__, "r") do |f|
+ child_fd = f.fileno
+ args = ruby_cmd(fixture(__FILE__, "map_fd.rb"), args: [child_fd.to_s])
+ pid = Process.spawn(*args, { child_fd => @io })
+ Process.waitpid pid
+ @io.rewind
+
+ @io.read.should == "writing to fd: #{child_fd}"
+ end
end
end
end
diff --git a/spec/ruby/core/process/times_spec.rb b/spec/ruby/core/process/times_spec.rb
index 35a7f5b34c..b47189a7e7 100644
--- a/spec/ruby/core/process/times_spec.rb
+++ b/spec/ruby/core/process/times_spec.rb
@@ -13,18 +13,23 @@ describe "Process.times" do
Process.times.utime.should > user
end
- ruby_version_is "2.5" do
- platform_is_not :windows do
- it "uses getrusage when available to improve precision beyond milliseconds" do
- times = 1000.times.map { Process.clock_gettime(:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID) }
- if times.count { |t| !('%.6f' % t).end_with?('000') } == 0
- skip "getrusage is not supported on this environment"
- end
+ platform_is_not :windows do
+ it "uses getrusage when available to improve precision beyond milliseconds" do
+ max = 10_000
+ has_getrusage = max.times.find do
+ time = Process.clock_gettime(:GETRUSAGE_BASED_CLOCK_PROCESS_CPUTIME_ID)
+ ('%.6f' % time).end_with?('000')
+ end
+ unless has_getrusage
+ skip "getrusage is not supported on this environment"
+ end
- times = 1000.times.map { Process.times }
- times.count { |t| !('%.6f' % t.utime).end_with?('000') }.should > 0
- times.count { |t| !('%.6f' % t.stime).end_with?('000') }.should > 0
+ found = (max * 100).times.find do
+ time = Process.times.utime
+ ('%.6f' % time).end_with?('000')
end
+
+ found.should_not == nil
end
end
end
diff --git a/spec/ruby/core/process/wait_spec.rb b/spec/ruby/core/process/wait_spec.rb
index f393a99e0f..44c95d6304 100644
--- a/spec/ruby/core/process/wait_spec.rb
+++ b/spec/ruby/core/process/wait_spec.rb
@@ -7,9 +7,8 @@ describe "Process.wait" do
before :all do
begin
leaked = Process.waitall
- puts "leaked before wait specs: #{leaked}" unless leaked.empty?
# Ruby-space should not see PIDs used by mjit
- leaked.should be_empty
+ raise "subprocesses leaked before wait specs: #{leaked}" unless leaked.empty?
rescue NotImplementedError
end
end
diff --git a/spec/ruby/core/random/default_spec.rb b/spec/ruby/core/random/default_spec.rb
index 1d8b1ce5ee..a709eddd53 100644
--- a/spec/ruby/core/random/default_spec.rb
+++ b/spec/ruby/core/random/default_spec.rb
@@ -1,7 +1,38 @@
require_relative '../../spec_helper'
describe "Random::DEFAULT" do
- it "returns a Random instance" do
- Random::DEFAULT.should be_an_instance_of(Random)
+
+ it "returns a random number generator" do
+ suppress_warning do
+ Random::DEFAULT.should respond_to(:rand)
+ end
+ end
+
+ ruby_version_is ''...'3.0' do
+ it "returns a Random instance" do
+ suppress_warning do
+ Random::DEFAULT.should be_an_instance_of(Random)
+ end
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "refers to the Random class" do
+ suppress_warning do
+ Random::DEFAULT.should.equal?(Random)
+ end
+ end
+
+ it "is deprecated" do
+ -> {
+ Random::DEFAULT.should.equal?(Random)
+ }.should complain(/constant Random::DEFAULT is deprecated/)
+ end
+ end
+
+ it "changes seed on reboot" do
+ seed1 = ruby_exe('p Random::DEFAULT.seed', options: '--disable-gems')
+ seed2 = ruby_exe('p Random::DEFAULT.seed', options: '--disable-gems')
+ seed1.should != seed2
end
end
diff --git a/spec/ruby/core/random/new_seed_spec.rb b/spec/ruby/core/random/new_seed_spec.rb
index 4b34e871a2..7a93da99aa 100644
--- a/spec/ruby/core/random/new_seed_spec.rb
+++ b/spec/ruby/core/random/new_seed_spec.rb
@@ -1,8 +1,8 @@
require_relative '../../spec_helper'
describe "Random.new_seed" do
- it "returns a Bignum" do
- Random.new_seed.should be_an_instance_of(Bignum)
+ it "returns an Integer" do
+ Random.new_seed.should be_an_instance_of(Integer)
end
it "returns an arbitrary seed value each time" do
diff --git a/spec/ruby/core/random/new_spec.rb b/spec/ruby/core/random/new_spec.rb
index 07d7b439ca..4280b5b9c3 100644
--- a/spec/ruby/core/random/new_spec.rb
+++ b/spec/ruby/core/random/new_spec.rb
@@ -4,7 +4,7 @@ describe "Random.new" do
end
it "uses a random seed value if none is supplied" do
- Random.new.seed.should be_an_instance_of(Bignum)
+ Random.new.seed.should be_an_instance_of(Integer)
end
it "returns Random instances initialized with different seeds" do
diff --git a/spec/ruby/core/random/rand_spec.rb b/spec/ruby/core/random/rand_spec.rb
index 0e423301f8..7fd60d5553 100644
--- a/spec/ruby/core/random/rand_spec.rb
+++ b/spec/ruby/core/random/rand_spec.rb
@@ -49,18 +49,18 @@ describe "Random.rand" do
end
end
-describe "Random#rand with Fixnum" do
+describe "Random#rand with Integer" do
it "returns an Integer" do
- Random.new.rand(20).should be_an_instance_of(Fixnum)
+ Random.new.rand(20).should be_an_instance_of(Integer)
end
- it "returns a Fixnum greater than or equal to 0" do
+ it "returns an Integer greater than or equal to 0" do
prng = Random.new
ints = 20.times.map { prng.rand(5) }
ints.min.should >= 0
end
- it "returns a Fixnum less than the argument" do
+ it "returns an Integer less than the argument" do
prng = Random.new
ints = 20.times.map { prng.rand(5) }
ints.max.should <= 4
@@ -92,19 +92,19 @@ describe "Random#rand with Fixnum" do
end
end
-describe "Random#rand with Bignum" do
- it "typically returns a Bignum" do
+describe "Random#rand with Integer" do
+ it "typically returns an Integer" do
rnd = Random.new(1)
- 10.times.map{ rnd.rand(bignum_value*2) }.max.should be_an_instance_of(Bignum)
+ 10.times.map{ rnd.rand(bignum_value*2) }.max.should be_an_instance_of(Integer)
end
- it "returns a Bignum greater than or equal to 0" do
+ it "returns an Integer greater than or equal to 0" do
prng = Random.new
bigs = 20.times.map { prng.rand(bignum_value) }
bigs.min.should >= 0
end
- it "returns a Bignum less than the argument" do
+ it "returns an Integer less than the argument" do
prng = Random.new
bigs = 20.times.map { prng.rand(bignum_value) }
bigs.max.should < bignum_value
@@ -159,7 +159,7 @@ end
describe "Random#rand with Range" do
it "returns an element from the Range" do
- Random.new.rand(20..43).should be_an_instance_of(Fixnum)
+ Random.new.rand(20..43).should be_an_instance_of(Integer)
end
it "supports custom object types" do
diff --git a/spec/ruby/core/random/raw_seed_spec.rb b/spec/ruby/core/random/raw_seed_spec.rb
index c1a1eb1f42..0e40ed0796 100644
--- a/spec/ruby/core/random/raw_seed_spec.rb
+++ b/spec/ruby/core/random/raw_seed_spec.rb
@@ -1,9 +1,6 @@
-# -*- encoding: binary -*-
require_relative '../../spec_helper'
require_relative 'shared/urandom'
-ruby_version_is "2.5" do
- describe "Random.urandom" do
- it_behaves_like :random_urandom, :urandom
- end
+describe "Random.urandom" do
+ it_behaves_like :random_urandom, :urandom
end
diff --git a/spec/ruby/core/random/urandom_spec.rb b/spec/ruby/core/random/urandom_spec.rb
deleted file mode 100644
index e27f83cdcd..0000000000
--- a/spec/ruby/core/random/urandom_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- encoding: binary -*-
-require_relative '../../spec_helper'
-require_relative 'shared/urandom'
-
-ruby_version_is ""..."2.5" do
- describe "Random.raw_seed" do
- it_behaves_like :random_urandom, :raw_seed
- end
-end
diff --git a/spec/ruby/core/range/bsearch_spec.rb b/spec/ruby/core/range/bsearch_spec.rb
index 009cafb00e..38ccd35170 100644
--- a/spec/ruby/core/range/bsearch_spec.rb
+++ b/spec/ruby/core/range/bsearch_spec.rb
@@ -81,6 +81,19 @@ describe "Range#bsearch" do
[1, 2].should include(result)
end
end
+
+ it "returns nil for empty ranges" do
+ (0...0).bsearch { true }.should == nil
+ (0...0).bsearch { false }.should == nil
+ (0...0).bsearch { 1 }.should == nil
+ (0...0).bsearch { 0 }.should == nil
+ (0...0).bsearch { -1 }.should == nil
+
+ (4..2).bsearch { true }.should == nil
+ (4..2).bsearch { 1 }.should == nil
+ (4..2).bsearch { 0 }.should == nil
+ (4..2).bsearch { -1 }.should == nil
+ end
end
context "with Float values" do
@@ -94,13 +107,46 @@ describe "Range#bsearch" do
end
it "returns minimum element if the block returns true for every element" do
- (-0.2..4.8).bsearch { |x| x < 4 }.should == -0.2
+ (-0.2..4.8).bsearch { |x| x < 5 }.should == -0.2
end
it "returns the smallest element for which block returns true" do
(0..4.2).bsearch { |x| x >= 2 }.should == 2
(-1.2..4.3).bsearch { |x| x >= 1 }.should == 1
end
+
+ it "returns a boundary element if appropriate" do
+ (1.0..3.0).bsearch { |x| x >= 3.0 }.should == 3.0
+ (1.0...3.0).bsearch { |x| x >= 3.0.prev_float }.should == 3.0.prev_float
+ (1.0..3.0).bsearch { |x| x >= 1.0 }.should == 1.0
+ (1.0...3.0).bsearch { |x| x >= 1.0 }.should == 1.0
+ end
+
+ it "works with infinity bounds" do
+ inf = Float::INFINITY
+ (0..inf).bsearch { |x| x == inf }.should == inf
+ (0...inf).bsearch { |x| x == inf }.should == nil
+ (-inf..0).bsearch { |x| x == -inf }.should == nil
+ (-inf...0).bsearch { |x| x == -inf }.should == nil
+ (inf..inf).bsearch { |x| true }.should == inf
+ (inf...inf).bsearch { |x| true }.should == nil
+ (-inf..-inf).bsearch { |x| true }.should == -inf
+ (-inf...-inf).bsearch { |x| true }.should == nil
+ (inf..0).bsearch { true }.should == nil
+ (inf...0).bsearch { true }.should == nil
+ (0..-inf).bsearch { true }.should == nil
+ (0...-inf).bsearch { true }.should == nil
+ (inf..-inf).bsearch { true }.should == nil
+ (inf...-inf).bsearch { true }.should == nil
+ (0..inf).bsearch { |x| x >= 3 }.should == 3.0
+ (0...inf).bsearch { |x| x >= 3 }.should == 3.0
+ (-inf..0).bsearch { |x| x >= -3 }.should == -3.0
+ (-inf...0).bsearch { |x| x >= -3 }.should == -3.0
+ (-inf..inf).bsearch { |x| x >= 3 }.should == 3.0
+ (-inf...inf).bsearch { |x| x >= 3 }.should == 3.0
+ (0..inf).bsearch { |x| x >= Float::MAX }.should == Float::MAX
+ (0...inf).bsearch { |x| x >= Float::MAX }.should == Float::MAX
+ end
end
context "with a block returning negative, zero, positive numbers" do
@@ -130,7 +176,157 @@ describe "Range#bsearch" do
it "returns an element at an index for which block returns 0" do
result = (0.1..4.9).bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
result.should >= 1
- result.should <= 2
+ result.should <= 3
+ end
+
+ it "returns an element at an index for which block returns 0 (small numbers)" do
+ result = (0.1..0.3).bsearch { |x| x < 0.1 ? 1 : x > 0.3 ? -1 : 0 }
+ result.should >= 0.1
+ result.should <= 0.3
+ end
+
+ it "returns a boundary element if appropriate" do
+ (1.0..3.0).bsearch { |x| 3.0 - x }.should == 3.0
+ (1.0...3.0).bsearch { |x| 3.0.prev_float - x }.should == 3.0.prev_float
+ (1.0..3.0).bsearch { |x| 1.0 - x }.should == 1.0
+ (1.0...3.0).bsearch { |x| 1.0 - x }.should == 1.0
+ end
+
+ it "works with infinity bounds" do
+ inf = Float::INFINITY
+ (0..inf).bsearch { |x| x == inf ? 0 : -1 }.should == nil
+ (0...inf).bsearch { |x| x == inf ? 0 : -1 }.should == nil
+ (-inf...0).bsearch { |x| x == -inf ? 0 : 1 }.should == nil
+ (-inf..0).bsearch { |x| x == -inf ? 0 : 1 }.should == nil
+ (inf..inf).bsearch { 0 }.should == inf
+ (inf...inf).bsearch { 0 }.should == nil
+ (-inf..-inf).bsearch { 0 }.should == -inf
+ (-inf...-inf).bsearch { 0 }.should == nil
+ (inf..0).bsearch { 0 }.should == nil
+ (inf...0).bsearch { 0 }.should == nil
+ (0..-inf).bsearch { 0 }.should == nil
+ (0...-inf).bsearch { 0 }.should == nil
+ (inf..-inf).bsearch { 0 }.should == nil
+ (inf...-inf).bsearch { 0 }.should == nil
+ (-inf..inf).bsearch { |x| 3 - x }.should == 3.0
+ (-inf...inf).bsearch { |x| 3 - x }.should == 3.0
+ (0...inf).bsearch { |x| x >= Float::MAX ? 0 : 1 }.should == Float::MAX
+ end
+ end
+ end
+
+ ruby_version_is "2.6" do
+ context "with endless ranges and Integer values" do
+ context "with a block returning true or false" do
+ it "returns minimum element if the block returns true for every element" do
+ eval("(-2..)").bsearch { |x| true }.should == -2
+ end
+
+ it "returns the smallest element for which block returns true" do
+ eval("(0..)").bsearch { |x| x >= 2 }.should == 2
+ eval("(-1..)").bsearch { |x| x >= 1 }.should == 1
+ end
+ end
+
+ context "with a block returning negative, zero, positive numbers" do
+ it "returns nil if the block returns less than zero for every element" do
+ eval("(0..)").bsearch { |x| -1 }.should be_nil
+ end
+
+ it "returns nil if the block never returns zero" do
+ eval("(0..)").bsearch { |x| x > 5 ? -1 : 1 }.should be_nil
+ end
+
+ it "accepts -Float::INFINITY from the block" do
+ eval("(0..)").bsearch { |x| -Float::INFINITY }.should be_nil
+ end
+
+ it "returns an element at an index for which block returns 0.0" do
+ result = eval("(0..)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
+ result.should == 2
+ end
+
+ it "returns an element at an index for which block returns 0" do
+ result = eval("(0..)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
+ [1, 2].should include(result)
+ end
+ end
+ end
+
+ context "with endless ranges and Float values" do
+ context "with a block returning true or false" do
+ it "returns nil if the block returns false for every element" do
+ eval("(0.1..)").bsearch { |x| x < 0.0 }.should be_nil
+ eval("(0.1...)").bsearch { |x| x < 0.0 }.should be_nil
+ end
+
+ it "returns nil if the block returns nil for every element" do
+ eval("(-0.0..)").bsearch { |x| nil }.should be_nil
+ eval("(-0.0...)").bsearch { |x| nil }.should be_nil
+ end
+
+ it "returns minimum element if the block returns true for every element" do
+ eval("(-0.2..)").bsearch { |x| true }.should == -0.2
+ eval("(-0.2...)").bsearch { |x| true }.should == -0.2
+ end
+
+ it "returns the smallest element for which block returns true" do
+ eval("(0..)").bsearch { |x| x >= 2 }.should == 2
+ eval("(-1.2..)").bsearch { |x| x >= 1 }.should == 1
+ end
+
+ it "works with infinity bounds" do
+ inf = Float::INFINITY
+ eval("(inf..)").bsearch { |x| true }.should == inf
+ eval("(inf...)").bsearch { |x| true }.should == nil
+ eval("(-inf..)").bsearch { |x| true }.should == -inf
+ eval("(-inf...)").bsearch { |x| true }.should == -inf
+ end
+ end
+
+ context "with a block returning negative, zero, positive numbers" do
+ it "returns nil if the block returns less than zero for every element" do
+ eval("(-2.0..)").bsearch { |x| -1 }.should be_nil
+ eval("(-2.0...)").bsearch { |x| -1 }.should be_nil
+ end
+
+ it "returns nil if the block returns greater than zero for every element" do
+ eval("(0.3..)").bsearch { |x| 1 }.should be_nil
+ eval("(0.3...)").bsearch { |x| 1 }.should be_nil
+ end
+
+ it "returns nil if the block never returns zero" do
+ eval("(0.2..)").bsearch { |x| x < 2 ? 1 : -1 }.should be_nil
+ end
+
+ it "accepts (+/-)Float::INFINITY from the block" do
+ eval("(0.1..)").bsearch { |x| Float::INFINITY }.should be_nil
+ eval("(-5.0..)").bsearch { |x| -Float::INFINITY }.should be_nil
+ end
+
+ it "returns an element at an index for which block returns 0.0" do
+ result = eval("(0.0..)").bsearch { |x| x < 2 ? 1.0 : x > 2 ? -1.0 : 0.0 }
+ result.should == 2
+ end
+
+ it "returns an element at an index for which block returns 0" do
+ result = eval("(0.1..)").bsearch { |x| x < 1 ? 1 : x > 3 ? -1 : 0 }
+ result.should >= 1
+ result.should <= 3
+ end
+
+ it "works with infinity bounds" do
+ inf = Float::INFINITY
+ eval("(inf..)").bsearch { |x| 1 }.should == nil
+ eval("(inf...)").bsearch { |x| 1 }.should == nil
+ eval("(inf..)").bsearch { |x| x == inf ? 0 : 1 }.should == inf
+ eval("(inf...)").bsearch { |x| x == inf ? 0 : 1 }.should == nil
+ eval("(-inf..)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf
+ eval("(-inf...)").bsearch { |x| x == -inf ? 0 : -1 }.should == -inf
+ eval("(-inf..)").bsearch { |x| 3 - x }.should == 3
+ eval("(-inf...)").bsearch { |x| 3 - x }.should == 3
+ eval("(0.0...)").bsearch { 0 }.should != inf
+ end
end
end
end
diff --git a/spec/ruby/core/range/case_compare_spec.rb b/spec/ruby/core/range/case_compare_spec.rb
index 0ca03f6a35..b1afa90a41 100644
--- a/spec/ruby/core/range/case_compare_spec.rb
+++ b/spec/ruby/core/range/case_compare_spec.rb
@@ -25,4 +25,9 @@ describe "Range#===" do
(range === RangeSpecs::WithoutSucc.new(2)).should == true
end
end
+
+ ruby_version_is "2.7" do
+ it_behaves_like :range_cover_and_include, :===
+ it_behaves_like :range_cover, :===
+ end
end
diff --git a/spec/ruby/core/range/cover_spec.rb b/spec/ruby/core/range/cover_spec.rb
index 29c0e0bfa8..fa881607e9 100644
--- a/spec/ruby/core/range/cover_spec.rb
+++ b/spec/ruby/core/range/cover_spec.rb
@@ -6,4 +6,5 @@ require_relative 'shared/cover'
describe "Range#cover?" do
it_behaves_like :range_cover_and_include, :cover?
it_behaves_like :range_cover, :cover?
+ it_behaves_like :range_cover_subrange, :cover?
end
diff --git a/spec/ruby/core/range/dup_spec.rb b/spec/ruby/core/range/dup_spec.rb
index d1c029c6b7..6c9d0c954a 100644
--- a/spec/ruby/core/range/dup_spec.rb
+++ b/spec/ruby/core/range/dup_spec.rb
@@ -5,11 +5,11 @@ describe "Range#dup" do
copy = (1..3).dup
copy.begin.should == 1
copy.end.should == 3
- copy.exclude_end?.should == false
+ copy.should_not.exclude_end?
copy = ("a"..."z").dup
copy.begin.should == "a"
copy.end.should == "z"
- copy.exclude_end?.should == true
+ copy.should.exclude_end?
end
end
diff --git a/spec/ruby/core/range/each_spec.rb b/spec/ruby/core/range/each_spec.rb
index 110b0602d0..8935d86829 100644
--- a/spec/ruby/core/range/each_spec.rb
+++ b/spec/ruby/core/range/each_spec.rb
@@ -32,6 +32,28 @@ describe "Range#each" do
a.should == [x, y]
end
+ ruby_version_is "2.6" do
+ it "works with endless ranges" do
+ a = []
+ eval("(-2..)").each { |x| break if x > 2; a << x }
+ a.should == [-2, -1, 0, 1, 2]
+
+ a = []
+ eval("(-2...)").each { |x| break if x > 2; a << x }
+ a.should == [-2, -1, 0, 1, 2]
+ end
+
+ it "works with String endless ranges" do
+ a = []
+ eval("('A'..)").each { |x| break if x > "D"; a << x }
+ a.should == ["A", "B", "C", "D"]
+
+ a = []
+ eval("('A'...)").each { |x| break if x > "D"; a << x }
+ a.should == ["A", "B", "C", "D"]
+ end
+ end
+
it "raises a TypeError if the first element does not respond to #succ" do
-> { (0.5..2.4).each { |i| i } }.should raise_error(TypeError)
diff --git a/spec/ruby/core/range/equal_value_spec.rb b/spec/ruby/core/range/equal_value_spec.rb
index 889557fc2a..43d5e0e38a 100644
--- a/spec/ruby/core/range/equal_value_spec.rb
+++ b/spec/ruby/core/range/equal_value_spec.rb
@@ -7,4 +7,10 @@ describe "Range#==" do
it "returns true if the endpoints are ==" do
(0..1).should == (0..1.0)
end
+
+ ruby_version_is "2.6" do
+ it "returns true if the endpoints are == for endless ranges" do
+ eval("(1.0..)").should == eval("(1.0..)")
+ end
+ end
end
diff --git a/spec/ruby/core/range/exclude_end_spec.rb b/spec/ruby/core/range/exclude_end_spec.rb
index a209603d18..c4006fea78 100644
--- a/spec/ruby/core/range/exclude_end_spec.rb
+++ b/spec/ruby/core/range/exclude_end_spec.rb
@@ -2,18 +2,18 @@ require_relative '../../spec_helper'
describe "Range#exclude_end?" do
it "returns false if the range does not exclude the end value" do
- (-2..2).exclude_end?.should == false
- ('A'..'B').exclude_end?.should == false
- (0.5..2.4).exclude_end?.should == false
- (0xfffd..0xffff).exclude_end?.should == false
- Range.new(0, 1).exclude_end?.should == false
+ (-2..2).should_not.exclude_end?
+ ('A'..'B').should_not.exclude_end?
+ (0.5..2.4).should_not.exclude_end?
+ (0xfffd..0xffff).should_not.exclude_end?
+ Range.new(0, 1).should_not.exclude_end?
end
it "returns true if the range excludes the end value" do
- (0...5).exclude_end?.should == true
- ('A'...'B').exclude_end?.should == true
- (0.5...2.4).exclude_end?.should == true
- (0xfffd...0xffff).exclude_end?.should == true
- Range.new(0, 1, true).exclude_end?.should == true
+ (0...5).should.exclude_end?
+ ('A'...'B').should.exclude_end?
+ (0.5...2.4).should.exclude_end?
+ (0xfffd...0xffff).should.exclude_end?
+ Range.new(0, 1, true).should.exclude_end?
end
end
diff --git a/spec/ruby/core/range/hash_spec.rb b/spec/ruby/core/range/hash_spec.rb
index 90aeee7890..4f2681e86e 100644
--- a/spec/ruby/core/range/hash_spec.rb
+++ b/spec/ruby/core/range/hash_spec.rb
@@ -14,11 +14,11 @@ describe "Range#hash" do
(0..10).hash.should_not == (0...10).hash
end
- it "generates a Fixnum for the hash value" do
- (0..0).hash.should be_an_instance_of(Fixnum)
- (0..1).hash.should be_an_instance_of(Fixnum)
- (0...10).hash.should be_an_instance_of(Fixnum)
- (0..10).hash.should be_an_instance_of(Fixnum)
+ it "generates an Integer for the hash value" do
+ (0..0).hash.should be_an_instance_of(Integer)
+ (0..1).hash.should be_an_instance_of(Integer)
+ (0...10).hash.should be_an_instance_of(Integer)
+ (0..10).hash.should be_an_instance_of(Integer)
end
end
diff --git a/spec/ruby/core/range/initialize_spec.rb b/spec/ruby/core/range/initialize_spec.rb
index 8caf12baa2..8a6ca65daa 100644
--- a/spec/ruby/core/range/initialize_spec.rb
+++ b/spec/ruby/core/range/initialize_spec.rb
@@ -27,9 +27,18 @@ describe "Range#initialize" do
-> { @range.send(:initialize, 1, 3, 5, 7, 9) }.should raise_error(ArgumentError)
end
- it "raises a NameError if called on an already initialized Range" do
- -> { (0..1).send(:initialize, 1, 3) }.should raise_error(NameError)
- -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(NameError)
+ ruby_version_is ""..."3.0" do
+ it "raises a NameError if called on an already initialized Range" do
+ -> { (0..1).send(:initialize, 1, 3) }.should raise_error(NameError)
+ -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(NameError)
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "raises a FrozenError if called on an already initialized Range" do
+ -> { (0..1).send(:initialize, 1, 3) }.should raise_error(FrozenError)
+ -> { (0..1).send(:initialize, 1, 3, true) }.should raise_error(FrozenError)
+ end
end
it "raises an ArgumentError if arguments don't respond to <=>" do
diff --git a/spec/ruby/core/range/inspect_spec.rb b/spec/ruby/core/range/inspect_spec.rb
index 837f7e69ab..d1072531e9 100644
--- a/spec/ruby/core/range/inspect_spec.rb
+++ b/spec/ruby/core/range/inspect_spec.rb
@@ -12,6 +12,13 @@ describe "Range#inspect" do
(0.5..2.4).inspect.should == "0.5..2.4"
end
+ ruby_version_is "2.6" do
+ it "works for endless ranges" do
+ eval("(1..)").inspect.should == "1.."
+ eval("(0.1...)").inspect.should == "0.1..."
+ end
+ end
+
ruby_version_is ''...'2.7' do
it "returns a tainted string if either end is tainted" do
(("a".taint)..."c").inspect.tainted?.should be_true
diff --git a/spec/ruby/core/range/last_spec.rb b/spec/ruby/core/range/last_spec.rb
index c7e629e62c..54884ba4d6 100644
--- a/spec/ruby/core/range/last_spec.rb
+++ b/spec/ruby/core/range/last_spec.rb
@@ -46,4 +46,10 @@ describe "Range#last" do
it "raises a TypeError when passed a String" do
-> { (2..3).last("1") }.should raise_error(TypeError)
end
+
+ ruby_version_is "2.6" do
+ it "raises a RangeError when called on an endless range" do
+ -> { eval("(1..)").last }.should raise_error(RangeError)
+ end
+ end
end
diff --git a/spec/ruby/core/range/max_spec.rb b/spec/ruby/core/range/max_spec.rb
index faac0a2032..728053cefd 100644
--- a/spec/ruby/core/range/max_spec.rb
+++ b/spec/ruby/core/range/max_spec.rb
@@ -45,6 +45,12 @@ describe "Range#max" do
time_end = Time.now + 1.0
-> { (time_start...time_end).max }.should raise_error(TypeError)
end
+
+ ruby_version_is "2.6" do
+ it "raises RangeError when called on an endless range" do
+ -> { eval("(1..)").max }.should raise_error(RangeError)
+ end
+ end
end
describe "Range#max given a block" do
diff --git a/spec/ruby/core/range/min_spec.rb b/spec/ruby/core/range/min_spec.rb
index 424bd1dc87..f1dff73e6d 100644
--- a/spec/ruby/core/range/min_spec.rb
+++ b/spec/ruby/core/range/min_spec.rb
@@ -72,4 +72,11 @@ describe "Range#min given a block" do
('z'..'l').min {|x,y| x <=> y}.should be_nil
(7...7).min {|x,y| x <=> y}.should be_nil
end
+
+ ruby_version_is "2.6" do
+ it "returns the start point for endless ranges" do
+ eval("(1..)").min.should == 1
+ eval("(1.0...)").min.should == 1.0
+ end
+ end
end
diff --git a/spec/ruby/core/range/minmax_spec.rb b/spec/ruby/core/range/minmax_spec.rb
new file mode 100644
index 0000000000..fa0637ac56
--- /dev/null
+++ b/spec/ruby/core/range/minmax_spec.rb
@@ -0,0 +1,170 @@
+require_relative '../../spec_helper'
+
+# These specs use Range.new instead of the literal notation so they parse fine on Ruby < 2.6
+describe 'Range#minmax' do
+ before(:each) do
+ @x = mock('x')
+ @y = mock('y')
+
+ @x.should_receive(:<=>).with(@y).any_number_of_times.and_return(-1) # x < y
+ @x.should_receive(:<=>).with(@x).any_number_of_times.and_return(0) # x == x
+ @y.should_receive(:<=>).with(@x).any_number_of_times.and_return(1) # y > x
+ @y.should_receive(:<=>).with(@y).any_number_of_times.and_return(0) # y == y
+ end
+
+ describe 'on an inclusive range' do
+ ruby_version_is '2.6'...'2.7' do
+ it 'should try to iterate endlessly on an endless range' do
+ @x.should_receive(:succ).once.and_return(@y)
+ range = Range.new(@x, nil)
+
+ -> { range.minmax }.should raise_error(NoMethodError, /^undefined method `succ' for/)
+ end
+ end
+
+ ruby_version_is '2.7' do
+ it 'should raise RangeError on an endless range without iterating the range' do
+ @x.should_not_receive(:succ)
+
+ range = Range.new(@x, nil)
+
+ -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range')
+ end
+
+ it 'raises RangeError or ArgumentError on a beginless range' do
+ range = Range.new(nil, @x)
+
+ -> { range.minmax }.should raise_error(StandardError) { |e|
+ if RangeError === e
+ # error from #min
+ -> { raise e }.should raise_error(RangeError, 'cannot get the minimum of beginless range')
+ else
+ # error from #max
+ -> { raise e }.should raise_error(ArgumentError, 'comparison of NilClass with MockObject failed')
+ end
+ }
+ end
+ end
+
+ it 'should return beginning of range if beginning and end are equal without iterating the range' do
+ @x.should_not_receive(:succ)
+
+ (@x..@x).minmax.should == [@x, @x]
+ end
+
+ it 'should return nil pair if beginning is greater than end without iterating the range' do
+ @y.should_not_receive(:succ)
+
+ (@y..@x).minmax.should == [nil, nil]
+ end
+
+ ruby_version_is ''...'2.7' do
+ it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do
+ @x.should_receive(:succ).once.and_return(@y)
+
+ (@x..@y).minmax.should == [@x, @y]
+ end
+ end
+
+ ruby_version_is '2.7' do
+ it 'should return the minimum and maximum values for a non-numeric range without iterating the range' do
+ @x.should_not_receive(:succ)
+
+ (@x..@y).minmax.should == [@x, @y]
+ end
+ end
+
+ it 'should return the minimum and maximum values for a numeric range' do
+ (1..3).minmax.should == [1, 3]
+ end
+
+ ruby_version_is '2.7' do
+ it 'should return the minimum and maximum values for a numeric range without iterating the range' do
+ # We cannot set expectations on integers,
+ # so we "prevent" iteration by picking a value that would iterate until the spec times out.
+ range_end = Float::INFINITY
+
+ (1..range_end).minmax.should == [1, range_end]
+ end
+ end
+
+ it 'should return the minimum and maximum values according to the provided block by iterating the range' do
+ @x.should_receive(:succ).once.and_return(@y)
+
+ (@x..@y).minmax { |x, y| - (x <=> y) }.should == [@y, @x]
+ end
+ end
+
+ describe 'on an exclusive range' do
+ ruby_version_is '2.6'...'2.7' do
+ # Endless ranges introduced in 2.6
+ it 'should try to iterate endlessly on an endless range' do
+ @x.should_receive(:succ).once.and_return(@y)
+ range = Range.new(@x, nil, true)
+
+ -> { range.minmax }.should raise_error(NoMethodError, /^undefined method `succ' for/)
+ end
+ end
+
+ ruby_version_is '2.7' do
+ it 'should raise RangeError on an endless range' do
+ @x.should_not_receive(:succ)
+ range = Range.new(@x, nil, true)
+
+ -> { range.minmax }.should raise_error(RangeError, 'cannot get the maximum of endless range')
+ end
+
+ it 'should raise RangeError on a beginless range' do
+ range = Range.new(nil, @x, true)
+
+ -> { range.minmax }.should raise_error(RangeError,
+ /cannot get the maximum of beginless range with custom comparison method|cannot get the minimum of beginless range/)
+ end
+ end
+
+ ruby_bug "#17014", "2.7.0"..."3.0" do
+ it 'should return nil pair if beginning and end are equal without iterating the range' do
+ @x.should_not_receive(:succ)
+
+ (@x...@x).minmax.should == [nil, nil]
+ end
+
+ it 'should return nil pair if beginning is greater than end without iterating the range' do
+ @y.should_not_receive(:succ)
+
+ (@y...@x).minmax.should == [nil, nil]
+ end
+
+ it 'should return the minimum and maximum values for a non-numeric range by iterating the range' do
+ @x.should_receive(:succ).once.and_return(@y)
+
+ (@x...@y).minmax.should == [@x, @x]
+ end
+ end
+
+ it 'should return the minimum and maximum values for a numeric range' do
+ (1...3).minmax.should == [1, 2]
+ end
+
+ ruby_version_is '2.7' do
+ it 'should return the minimum and maximum values for a numeric range without iterating the range' do
+ # We cannot set expectations on integers,
+ # so we "prevent" iteration by picking a value that would iterate until the spec times out.
+ range_end = bignum_value
+
+ (1...range_end).minmax.should == [1, range_end - 1]
+ end
+
+ it 'raises TypeError if the end value is not an integer' do
+ range = (0...Float::INFINITY)
+ -> { range.minmax }.should raise_error(TypeError, 'cannot exclude non Integer end value')
+ end
+ end
+
+ it 'should return the minimum and maximum values according to the provided block by iterating the range' do
+ @x.should_receive(:succ).once.and_return(@y)
+
+ (@x...@y).minmax { |x, y| - (x <=> y) }.should == [@x, @x]
+ end
+ end
+end
diff --git a/spec/ruby/core/range/new_spec.rb b/spec/ruby/core/range/new_spec.rb
index 9ed2b65d5a..be10ff244e 100644
--- a/spec/ruby/core/range/new_spec.rb
+++ b/spec/ruby/core/range/new_spec.rb
@@ -33,14 +33,12 @@ describe "Range.new" do
-> { Range.new(a, b) }.should raise_error(ArgumentError)
end
- ruby_version_is "2.5" do
- it "does not rescue exception raised in #<=> when compares the given start and end" do
- b = mock('a')
- a = mock('b')
- a.should_receive(:<=>).with(b).and_raise(RangeSpecs::ComparisonError)
+ it "does not rescue exception raised in #<=> when compares the given start and end" do
+ b = mock('a')
+ a = mock('b')
+ a.should_receive(:<=>).with(b).and_raise(RangeSpecs::ComparisonError)
- -> { Range.new(a, b) }.should raise_error(RangeSpecs::ComparisonError)
- end
+ -> { Range.new(a, b) }.should raise_error(RangeSpecs::ComparisonError)
end
describe "beginless/endless range" do
diff --git a/spec/ruby/core/range/shared/cover.rb b/spec/ruby/core/range/shared/cover.rb
index 33d416fef5..5b09cea4e0 100644
--- a/spec/ruby/core/range/shared/cover.rb
+++ b/spec/ruby/core/range/shared/cover.rb
@@ -90,7 +90,9 @@ describe :range_cover, shared: true do
end
end
end
+end
+describe :range_cover_subrange, shared: true do
ruby_version_is "2.6" do
context "range argument" do
it "accepts range argument" do
diff --git a/spec/ruby/core/range/shared/cover_and_include.rb b/spec/ruby/core/range/shared/cover_and_include.rb
index a19e2c6ead..b308524310 100644
--- a/spec/ruby/core/range/shared/cover_and_include.rb
+++ b/spec/ruby/core/range/shared/cover_and_include.rb
@@ -19,6 +19,13 @@ describe :range_cover_and_include, shared: true do
(0.5...2.4).send(@method, 2.4).should == false
end
+ ruby_version_is "2.6" do
+ it "returns true if other is an element of self for endless ranges" do
+ eval("(1..)").send(@method, 2.4).should == true
+ eval("(0.5...)").send(@method, 2.4).should == true
+ end
+ end
+
it "compares values using <=>" do
rng = (1..5)
m = mock("int")
diff --git a/spec/ruby/core/range/shared/equal_value.rb b/spec/ruby/core/range/shared/equal_value.rb
index 9d8bb13351..8872b4efc0 100644
--- a/spec/ruby/core/range/shared/equal_value.rb
+++ b/spec/ruby/core/range/shared/equal_value.rb
@@ -42,4 +42,12 @@ describe :range_eql, shared: true do
b = RangeSpecs::MyRange.new(RangeSpecs::Xs.new(3), RangeSpecs::Xs.new(5))
a.send(@method, b).should == true
end
+
+ ruby_version_is "2.6" do
+ it "works for endless Ranges" do
+ eval("(1..)").send(@method, eval("(1..)")).should == true
+ eval("(0.5...)").send(@method, eval("(0.5...)")).should == true
+ eval("(1..)").send(@method, eval("(1...)")).should == false
+ end
+ end
end
diff --git a/spec/ruby/core/range/size_spec.rb b/spec/ruby/core/range/size_spec.rb
index 09759940dd..b687342b72 100644
--- a/spec/ruby/core/range/size_spec.rb
+++ b/spec/ruby/core/range/size_spec.rb
@@ -24,6 +24,13 @@ describe "Range#size" do
(-Float::INFINITY..Float::INFINITY).size.should == Float::INFINITY
end
+ ruby_version_is "2.6" do
+ it 'returns Float::INFINITY for endless ranges' do
+ eval("(1..)").size.should == Float::INFINITY
+ eval("(0.5...)").size.should == Float::INFINITY
+ end
+ end
+
it "returns nil if first and last are not Numeric" do
(:a..:z).size.should be_nil
('a'..'z').size.should be_nil
diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb
index d564e4a5cd..e284551ab3 100644
--- a/spec/ruby/core/range/step_spec.rb
+++ b/spec/ruby/core/range/step_spec.rb
@@ -274,21 +274,138 @@ describe "Range#step" do
end
end
+ ruby_version_is "2.6" 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 }
+ ScratchPad.recorded.should eql([-2, -1, 0, 1, 2])
+
+ ScratchPad.record []
+ eval("(-2...)").step { |x| break if x > 2; ScratchPad << x }
+ ScratchPad.recorded.should eql([-2, -1, 0, 1, 2])
+ end
+
+ it "yields Integer values incremented by an Integer step" do
+ eval("(-5..)").step(2) { |x| break if x > 3; ScratchPad << x }
+ ScratchPad.recorded.should eql([-5, -3, -1, 1, 3])
+
+ ScratchPad.record []
+ eval("(-5...)").step(2) { |x| break if x > 3; ScratchPad << x }
+ ScratchPad.recorded.should eql([-5, -3, -1, 1, 3])
+ end
+
+ it "yields Float values incremented by a Float step" do
+ eval("(-2..)").step(1.5) { |x| break if x > 1.0; ScratchPad << x }
+ ScratchPad.recorded.should eql([-2.0, -0.5, 1.0])
+
+ ScratchPad.record []
+ eval("(-2..)").step(1.5) { |x| break if x > 1.0; ScratchPad << x }
+ ScratchPad.recorded.should eql([-2.0, -0.5, 1.0])
+ end
+ end
+
+ describe "and Float values" do
+ it "yields Float values incremented by 1 and less than end when not passed a step" do
+ eval("(-2.0..)").step { |x| break if x > 1.5; ScratchPad << x }
+ ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0])
+
+ ScratchPad.record []
+ eval("(-2.0...)").step { |x| break if x > 1.5; ScratchPad << x }
+ ScratchPad.recorded.should eql([-2.0, -1.0, 0.0, 1.0])
+ end
+
+ it "yields Float values incremented by an Integer step" do
+ eval("(-5.0..)").step(2) { |x| break if x > 3.5; ScratchPad << x }
+ ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0])
+
+ ScratchPad.record []
+ eval("(-5.0...)").step(2) { |x| break if x > 3.5; ScratchPad << x }
+ ScratchPad.recorded.should eql([-5.0, -3.0, -1.0, 1.0, 3.0])
+ end
+
+ it "yields Float values incremented by a Float step" do
+ eval("(-1.0..)").step(0.5) { |x| break if x > 0.6; ScratchPad << x }
+ ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5])
+
+ ScratchPad.record []
+ eval("(-1.0...)").step(0.5) { |x| break if x > 0.6; ScratchPad << x }
+ ScratchPad.recorded.should eql([-1.0, -0.5, 0.0, 0.5])
+ end
+
+ it "handles infinite values at the start" do
+ eval("(-Float::INFINITY..)").step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
+ ScratchPad.recorded.should eql([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
+
+ ScratchPad.record []
+ eval("(-Float::INFINITY...)").step(2) { |x| ScratchPad << x; break if ScratchPad.recorded.size == 3 }
+ ScratchPad.recorded.should eql([-Float::INFINITY, -Float::INFINITY, -Float::INFINITY])
+ end
+ end
+
+ describe "and String values" do
+ it "yields String values incremented by #succ and less than or equal to end when not passed a step" do
+ eval("('A'..)").step { |x| break if x > "D"; ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "B", "C", "D"]
+
+ ScratchPad.record []
+ eval("('A'...)").step { |x| break if x > "D"; ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "B", "C", "D"]
+ end
+
+ it "yields String values incremented by #succ called Integer step times" do
+ eval("('A'..)").step(2) { |x| break if x > "F"; ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "C", "E"]
+
+ ScratchPad.record []
+ eval("('A'...)").step(2) { |x| break if x > "F"; ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "C", "E"]
+ end
+
+ it "raises a TypeError when passed a Float step" do
+ -> { eval("('A'..)").step(2.0) { } }.should raise_error(TypeError)
+ -> { eval("('A'...)").step(2.0) { } }.should raise_error(TypeError)
+ end
+ end
+ end
+ end
+
describe "when no block is given" do
+ ruby_version_is "3.0" do
+ it "raises an ArgumentError if step is 0" do
+ -> { (-1..1).step(0) }.should raise_error(ArgumentError)
+ end
+ end
+
describe "returned Enumerator" do
describe "size" do
- it "raises a TypeError if step does not respond to #to_int" do
- obj = mock("Range#step non-integer")
- enum = (1..2).step(obj)
- -> { enum.size }.should raise_error(TypeError)
+ ruby_version_is ""..."3.0" do
+ it "raises a TypeError if step does not respond to #to_int" do
+ obj = mock("Range#step non-integer")
+ enum = (1..2).step(obj)
+ -> { enum.size }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if #to_int does not return an Integer" do
+ obj = mock("Range#step non-integer")
+ obj.should_receive(:to_int).and_return("1")
+ enum = (1..2).step(obj)
+
+ -> { enum.size }.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")
- enum = (1..2).step(obj)
+ ruby_version_is "3.0" do
+ it "raises a TypeError if step does not respond to #to_int" do
+ obj = mock("Range#step non-integer")
+ -> { (1..2).step(obj) }.should raise_error(TypeError)
+ end
- -> { enum.size }.should raise_error(TypeError)
+ it "raises a TypeError if #to_int does not return an Integer" do
+ obj = mock("Range#step non-integer")
+ obj.should_receive(:to_int).and_return("1")
+ -> { (1..2).step(obj) }.should raise_error(TypeError)
+ end
end
ruby_version_is ""..."2.6" do
@@ -308,7 +425,7 @@ describe "Range#step" do
end
end
- ruby_version_is "2.6" do
+ ruby_version_is "2.6"..."3.0" do
it "returns Float::INFINITY for zero step" do
(-1..1).step(0).size.should == Float::INFINITY
(-1..1).step(0.0).size.should == Float::INFINITY
diff --git a/spec/ruby/core/range/to_a_spec.rb b/spec/ruby/core/range/to_a_spec.rb
index 15f0b44a9c..b0067f0e07 100644
--- a/spec/ruby/core/range/to_a_spec.rb
+++ b/spec/ruby/core/range/to_a_spec.rb
@@ -19,4 +19,10 @@ describe "Range#to_a" do
it "works with Ranges of Symbols" do
(:A..:z).to_a.size.should == 58
end
+
+ ruby_version_is "2.6" do
+ it "throws an exception for endless ranges" do
+ -> { eval("(1..)").to_a }.should raise_error(RangeError)
+ end
+ end
end
diff --git a/spec/ruby/core/range/to_s_spec.rb b/spec/ruby/core/range/to_s_spec.rb
index 7392aa9890..ccbc5d8e7e 100644
--- a/spec/ruby/core/range/to_s_spec.rb
+++ b/spec/ruby/core/range/to_s_spec.rb
@@ -11,6 +11,13 @@ describe "Range#to_s" do
(0.5..2.4).to_s.should == "0.5..2.4"
end
+ ruby_version_is "2.6" do
+ it "can show endless ranges" do
+ eval("(1..)").to_s.should == "1.."
+ eval("(1.0...)").to_s.should == "1.0..."
+ end
+ end
+
ruby_version_is ''...'2.7' do
it "returns a tainted string if either end is tainted" do
(("a".taint)..."c").to_s.tainted?.should be_true
diff --git a/spec/ruby/core/rational/comparison_spec.rb b/spec/ruby/core/rational/comparison_spec.rb
index b2784f3e7d..9d8e7fd7ee 100644
--- a/spec/ruby/core/rational/comparison_spec.rb
+++ b/spec/ruby/core/rational/comparison_spec.rb
@@ -4,7 +4,7 @@ describe "Rational#<=> when passed a Rational object" do
it_behaves_like :rational_cmp_rat, :<=>
end
-describe "Rational#<=> when passed a Integer object" do
+describe "Rational#<=> when passed an Integer object" do
it_behaves_like :rational_cmp_int, :<=>
end
diff --git a/spec/ruby/core/regexp/casefold_spec.rb b/spec/ruby/core/regexp/casefold_spec.rb
index d84a2d63c9..d36467a989 100644
--- a/spec/ruby/core/regexp/casefold_spec.rb
+++ b/spec/ruby/core/regexp/casefold_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Regexp#casefold?" do
it "returns the value of the case-insensitive flag" do
- /abc/i.casefold?.should == true
- /xyz/.casefold?.should == false
+ /abc/i.should.casefold?
+ /xyz/.should_not.casefold?
end
end
diff --git a/spec/ruby/core/regexp/initialize_spec.rb b/spec/ruby/core/regexp/initialize_spec.rb
index 36fd5c7bf2..772a233e82 100644
--- a/spec/ruby/core/regexp/initialize_spec.rb
+++ b/spec/ruby/core/regexp/initialize_spec.rb
@@ -5,8 +5,16 @@ describe "Regexp#initialize" do
Regexp.should have_private_method(:initialize)
end
- it "raises a SecurityError on a Regexp literal" do
- -> { //.send(:initialize, "") }.should raise_error(SecurityError)
+ ruby_version_is ""..."3.0" do
+ it "raises a SecurityError on a Regexp literal" do
+ -> { //.send(:initialize, "") }.should raise_error(SecurityError)
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "raises a FrozenError on a Regexp literal" do
+ -> { //.send(:initialize, "") }.should raise_error(FrozenError)
+ end
end
it "raises a TypeError on an initialized non-literal Regexp" do
diff --git a/spec/ruby/core/regexp/last_match_spec.rb b/spec/ruby/core/regexp/last_match_spec.rb
index ed496b7941..6bd8f2cd90 100644
--- a/spec/ruby/core/regexp/last_match_spec.rb
+++ b/spec/ruby/core/regexp/last_match_spec.rb
@@ -7,7 +7,7 @@ describe "Regexp.last_match" do
Regexp.last_match.should be_kind_of(MatchData)
end
- it "returns the nth field in this MatchData when passed a Fixnum" do
+ it "returns the nth field in this MatchData when passed an Integer" do
/c(.)t/ =~ 'cat'
Regexp.last_match(1).should == 'a'
end
diff --git a/spec/ruby/core/regexp/new_spec.rb b/spec/ruby/core/regexp/new_spec.rb
index d2d867b3d3..ce662b7a4f 100644
--- a/spec/ruby/core/regexp/new_spec.rb
+++ b/spec/ruby/core/regexp/new_spec.rb
@@ -14,7 +14,7 @@ describe "Regexp.new given a Regexp" do
it_behaves_like :regexp_new_string_binary, :compile
end
-describe "Regexp.new given a Fixnum" do
+describe "Regexp.new given an Integer" do
it "raises a TypeError" do
-> { Regexp.new(1) }.should raise_error(TypeError)
end
diff --git a/spec/ruby/core/regexp/options_spec.rb b/spec/ruby/core/regexp/options_spec.rb
index fb4853a014..527b51a3b2 100644
--- a/spec/ruby/core/regexp/options_spec.rb
+++ b/spec/ruby/core/regexp/options_spec.rb
@@ -1,10 +1,10 @@
require_relative '../../spec_helper'
describe "Regexp#options" do
- it "returns a Fixnum bitvector of regexp options for the Regexp object" do
- /cat/.options.should be_kind_of(Fixnum)
+ it "returns an Integer bitvector of regexp options for the Regexp object" do
+ /cat/.options.should be_kind_of(Integer)
not_supported_on :opal do
- /cat/ix.options.should be_kind_of(Fixnum)
+ /cat/ix.options.should be_kind_of(Integer)
end
end
diff --git a/spec/ruby/core/regexp/shared/new.rb b/spec/ruby/core/regexp/shared/new.rb
index bb5df7bc2e..9cbf89cd8b 100644
--- a/spec/ruby/core/regexp/shared/new.rb
+++ b/spec/ruby/core/regexp/shared/new.rb
@@ -58,7 +58,7 @@ describe :regexp_new_string, shared: true do
end
end
- it "sets options from second argument if it is one of the Fixnum option constants" do
+ it "sets options from second argument if it is one of the Integer option constants" do
r = Regexp.send(@method, 'Hi', Regexp::IGNORECASE)
(r.options & Regexp::IGNORECASE).should_not == 0
(r.options & Regexp::MULTILINE).should == 0
@@ -81,14 +81,14 @@ describe :regexp_new_string, shared: true do
end
end
- it "accepts a Fixnum of two or more options ORed together as the second argument" do
+ it "accepts an Integer of two or more options ORed together as the second argument" do
r = Regexp.send(@method, 'Hi', Regexp::IGNORECASE | Regexp::EXTENDED)
(r.options & Regexp::IGNORECASE).should_not == 0
(r.options & Regexp::MULTILINE).should == 0
(r.options & Regexp::EXTENDED).should_not == 0
end
- it "treats any non-Fixnum, non-nil, non-false second argument as IGNORECASE" do
+ it "treats any non-Integer, non-nil, non-false second argument as IGNORECASE" do
r = Regexp.send(@method, 'Hi', Object.new)
(r.options & Regexp::IGNORECASE).should_not == 0
(r.options & Regexp::MULTILINE).should == 0
diff --git a/spec/ruby/core/regexp/union_spec.rb b/spec/ruby/core/regexp/union_spec.rb
index 81a31d89b3..8076836471 100644
--- a/spec/ruby/core/regexp/union_spec.rb
+++ b/spec/ruby/core/regexp/union_spec.rb
@@ -139,6 +139,16 @@ describe "Regexp.union" do
Regexp.union(obj, "bar").should == /foo|bar/
end
+ it "uses to_regexp to convert argument" do
+ obj = mock('pattern')
+ obj.should_receive(:to_regexp).and_return(/foo/)
+ Regexp.union(obj).should == /foo/
+ end
+
+ it "accepts a Symbol as argument" do
+ Regexp.union(:foo).should == /foo/
+ end
+
it "accepts a single array of patterns as arguments" do
Regexp.union(["skiing", "sledding"]).should == /skiing|sledding/
not_supported_on :opal do
diff --git a/spec/ruby/core/signal/trap_spec.rb b/spec/ruby/core/signal/trap_spec.rb
index 91ce1f1348..831a5ee23e 100644
--- a/spec/ruby/core/signal/trap_spec.rb
+++ b/spec/ruby/core/signal/trap_spec.rb
@@ -155,7 +155,7 @@ platform_is_not :windows do
out = ruby_exe(code)
status = $?
out.should == "nil\n"
- status.signaled?.should == true
+ status.should.signaled?
status.termsig.should be_kind_of(Integer)
Signal.signame(status.termsig).should == "PIPE"
end
diff --git a/spec/ruby/core/string/bytes_spec.rb b/spec/ruby/core/string/bytes_spec.rb
index 96f1ae9cf2..859b346550 100644
--- a/spec/ruby/core/string/bytes_spec.rb
+++ b/spec/ruby/core/string/bytes_spec.rb
@@ -22,9 +22,9 @@ describe "String#bytes" do
@utf8_ascii.bytes.to_a.size.should == @utf8_ascii.bytesize
end
- it "returns bytes as Fixnums" do
- @ascii.bytes.to_a.each {|b| b.should be_an_instance_of(Fixnum)}
- @utf8_ascii.bytes { |b| b.should be_an_instance_of(Fixnum) }
+ it "returns bytes as Integers" do
+ @ascii.bytes.to_a.each {|b| b.should be_an_instance_of(Integer)}
+ @utf8_ascii.bytes { |b| b.should be_an_instance_of(Integer) }
end
it "agrees with #unpack('C*')" do
diff --git a/spec/ruby/core/string/capitalize_spec.rb b/spec/ruby/core/string/capitalize_spec.rb
index 41dd63f63e..21df18a5ae 100644
--- a/spec/ruby/core/string/capitalize_spec.rb
+++ b/spec/ruby/core/string/capitalize_spec.rb
@@ -14,8 +14,8 @@ describe "String#capitalize" do
ruby_version_is ''...'2.7' do
it "taints resulting string when self is tainted" do
- "".taint.capitalize.tainted?.should == true
- "hello".taint.capitalize.tainted?.should == true
+ "".taint.capitalize.should.tainted?
+ "hello".taint.capitalize.should.tainted?
end
end
@@ -80,9 +80,18 @@ describe "String#capitalize" do
-> { "abc".capitalize(:invalid_option) }.should raise_error(ArgumentError)
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(String)
+ StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(String)
+ end
end
end
@@ -93,6 +102,12 @@ describe "String#capitalize!" do
a.should == "Hello"
end
+ it "modifies self in place for non-ascii-compatible encodings" do
+ a = "heLLo".encode("utf-16le")
+ a.capitalize!
+ a.should == "Hello".encode("utf-16le")
+ end
+
describe "full Unicode case mapping" do
it "modifies self in place for all of Unicode with no option" do
a = "äöÜ"
@@ -106,6 +121,12 @@ describe "String#capitalize!" do
a.should == "Ss"
end
+ it "works for non-ascii-compatible encodings" do
+ a = "äöü".encode("utf-16le")
+ a.capitalize!
+ a.should == "Äöü".encode("utf-16le")
+ end
+
it "updates string metadata" do
capitalized = "ßeT"
capitalized.capitalize!
@@ -123,6 +144,12 @@ describe "String#capitalize!" do
a.capitalize!(:ascii)
a.should == "ßet"
end
+
+ it "works for non-ascii-compatible encodings" do
+ a = "aBc".encode("utf-16le")
+ a.capitalize!(:ascii)
+ a.should == "Abc".encode("utf-16le")
+ end
end
describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do
@@ -178,10 +205,10 @@ describe "String#capitalize!" do
"H".capitalize!.should == nil
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
["", "Hello", "hello"].each do |a|
a.freeze
- -> { a.capitalize! }.should raise_error(frozen_error_class)
+ -> { a.capitalize! }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/string/casecmp_spec.rb b/spec/ruby/core/string/casecmp_spec.rb
index 01b22e8f13..986fbc8718 100644
--- a/spec/ruby/core/string/casecmp_spec.rb
+++ b/spec/ruby/core/string/casecmp_spec.rb
@@ -25,16 +25,8 @@ describe "String#casecmp independent of case" do
"abc".casecmp(other).should == 0
end
- ruby_version_is ""..."2.5" do
- it "raises a TypeError if other can't be converted to a string" do
- -> { "abc".casecmp(mock('abc')) }.should raise_error(TypeError)
- end
- end
-
- ruby_version_is "2.5" do
- it "returns nil if other can't be converted to a string" do
- "abc".casecmp(mock('abc')).should be_nil
- end
+ it "returns nil if other can't be converted to a string" do
+ "abc".casecmp(mock('abc')).should be_nil
end
it "returns nil if incompatible encodings" do
@@ -196,15 +188,7 @@ describe 'String#casecmp? independent of case' do
"ß".casecmp?("ss").should be_true
end
- ruby_version_is "2.4"..."2.5" do
- it "raises a TypeError if other can't be converted to a string" do
- -> { "abc".casecmp?(mock('abc')) }.should raise_error(TypeError)
- end
- end
-
- ruby_version_is "2.5" do
- it "returns nil if other can't be converted to a string" do
- "abc".casecmp?(mock('abc')).should be_nil
- end
+ it "returns nil if other can't be converted to a string" do
+ "abc".casecmp?(mock('abc')).should be_nil
end
end
diff --git a/spec/ruby/core/string/center_spec.rb b/spec/ruby/core/string/center_spec.rb
index 0284fc28dc..b66015172c 100644
--- a/spec/ruby/core/string/center_spec.rb
+++ b/spec/ruby/core/string/center_spec.rb
@@ -49,11 +49,11 @@ describe "String#center with length, padding" do
ruby_version_is ''...'2.7' do
it "taints result when self or padstr is tainted" do
- "x".taint.center(4).tainted?.should == true
- "x".taint.center(0).tainted?.should == true
- "".taint.center(0).tainted?.should == true
- "x".taint.center(4, "*").tainted?.should == true
- "x".center(4, "*".taint).tainted?.should == true
+ "x".taint.center(4).should.tainted?
+ "x".taint.center(0).should.tainted?
+ "".taint.center(0).should.tainted?
+ "x".taint.center(4, "*").should.tainted?
+ "x".center(4, "*".taint).should.tainted?
end
end
@@ -91,13 +91,26 @@ describe "String#center with length, padding" do
-> { "hello".center(0, "") }.should raise_error(ArgumentError)
end
- it "returns subclass instances when called on subclasses" do
- StringSpecs::MyString.new("").center(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on subclasses" do
+ StringSpecs::MyString.new("").center(10).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString)
- "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on subclasses" do
+ StringSpecs::MyString.new("").center(10).should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+
+ "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ end
end
ruby_version_is ''...'2.7' do
diff --git a/spec/ruby/core/string/chomp_spec.rb b/spec/ruby/core/string/chomp_spec.rb
index 20a0925959..3d6207f876 100644
--- a/spec/ruby/core/string/chomp_spec.rb
+++ b/spec/ruby/core/string/chomp_spec.rb
@@ -6,11 +6,13 @@ describe "String#chomp" do
describe "when passed no argument" do
before do
# Ensure that $/ is set to the default value
+ @verbose, $VERBOSE = $VERBOSE, nil
@dollar_slash, $/ = $/, "\n"
end
after do
$/ = @dollar_slash
+ $VERBOSE = @verbose
end
it "does not modify a String with no trailing carriage return or newline" do
@@ -44,15 +46,28 @@ describe "String#chomp" do
end
end
- it "returns subclass instances when called on a subclass" do
- str = StringSpecs::MyString.new("hello\n").chomp
- str.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ str = StringSpecs::MyString.new("hello\n").chomp
+ str.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ str = StringSpecs::MyString.new("hello\n").chomp
+ str.should be_an_instance_of(String)
+ end
end
it "removes trailing characters that match $/ when it has been assigned a value" do
$/ = "cdef"
"abcdef".chomp.should == "ab"
end
+
+ it "removes one trailing newline for string with invalid encoding" do
+ "\xa0\xa1\n".chomp.should == "\xa0\xa1"
+ end
end
describe "when passed nil" do
@@ -106,6 +121,10 @@ describe "String#chomp" do
it "returns an empty String when self is empty" do
"".chomp("").should == ""
end
+
+ it "removes one trailing newline for string with invalid encoding" do
+ "\xa0\xa1\n".chomp("").should == "\xa0\xa1"
+ end
end
describe "when passed '\\n'" do
@@ -179,11 +198,13 @@ describe "String#chomp!" do
describe "when passed no argument" do
before do
# Ensure that $/ is set to the default value
+ @verbose, $VERBOSE = $VERBOSE, nil
@dollar_slash, $/ = $/, "\n"
end
after do
$/ = @dollar_slash
+ $VERBOSE = @verbose
end
it "modifies self" do
@@ -332,29 +353,31 @@ describe "String#chomp!" do
end
end
- it "raises a #{frozen_error_class} on a frozen instance when it is modified" do
+ it "raises a FrozenError on a frozen instance when it is modified" do
a = "string\n\r"
a.freeze
- -> { a.chomp! }.should raise_error(frozen_error_class)
+ -> { a.chomp! }.should raise_error(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on a frozen instance when it would not be modified" do
+ it "raises a FrozenError on a frozen instance when it would not be modified" do
a = "string\n\r"
a.freeze
- -> { a.chomp!(nil) }.should raise_error(frozen_error_class)
- -> { a.chomp!("x") }.should raise_error(frozen_error_class)
+ -> { a.chomp!(nil) }.should raise_error(FrozenError)
+ -> { a.chomp!("x") }.should raise_error(FrozenError)
end
end
describe "String#chomp" do
before :each do
+ @verbose, $VERBOSE = $VERBOSE, nil
@before_separator = $/
end
after :each do
$/ = @before_separator
+ $VERBOSE = @verbose
end
it "does not modify a multi-byte character" do
@@ -379,11 +402,13 @@ end
describe "String#chomp!" do
before :each do
+ @verbose, $VERBOSE = $VERBOSE, nil
@before_separator = $/
end
after :each do
$/ = @before_separator
+ $VERBOSE = @verbose
end
it "returns nil when the String is not modified" do
diff --git a/spec/ruby/core/string/chop_spec.rb b/spec/ruby/core/string/chop_spec.rb
index 9e893c3bea..9b4e7363c6 100644
--- a/spec/ruby/core/string/chop_spec.rb
+++ b/spec/ruby/core/string/chop_spec.rb
@@ -51,18 +51,26 @@ describe "String#chop" do
ruby_version_is ''...'2.7' do
it "taints result when self is tainted" do
- "hello".taint.chop.tainted?.should == true
- "".taint.chop.tainted?.should == true
+ "hello".taint.chop.should.tainted?
+ "".taint.chop.should.tainted?
end
it "untrusts result when self is untrusted" do
- "hello".untrust.chop.untrusted?.should == true
- "".untrust.chop.untrusted?.should == true
+ "hello".untrust.chop.should.untrusted?
+ "".untrust.chop.should.untrusted?
end
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(String)
+ end
end
end
@@ -113,14 +121,14 @@ describe "String#chop!" do
"".chop!.should be_nil
end
- it "raises a #{frozen_error_class} on a frozen instance that is modified" do
- -> { "string\n\r".freeze.chop! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that is modified" do
+ -> { "string\n\r".freeze.chop! }.should raise_error(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do
+ it "raises a FrozenError on a frozen instance that would not be modified" do
a = ""
a.freeze
- -> { a.chop! }.should raise_error(frozen_error_class)
+ -> { a.chop! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/clear_spec.rb b/spec/ruby/core/string/clear_spec.rb
index 0b5b8e6998..e1d68e03bd 100644
--- a/spec/ruby/core/string/clear_spec.rb
+++ b/spec/ruby/core/string/clear_spec.rb
@@ -29,9 +29,9 @@ describe "String#clear" do
s.should == ""
end
- it "raises a #{frozen_error_class} if self is frozen" do
+ it "raises a FrozenError if self is frozen" do
@s.freeze
- -> { @s.clear }.should raise_error(frozen_error_class)
- -> { "".freeze.clear }.should raise_error(frozen_error_class)
+ -> { @s.clear }.should raise_error(FrozenError)
+ -> { "".freeze.clear }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/crypt_spec.rb b/spec/ruby/core/string/crypt_spec.rb
index 6a9a4ae235..b947702492 100644
--- a/spec/ruby/core/string/crypt_spec.rb
+++ b/spec/ruby/core/string/crypt_spec.rb
@@ -33,10 +33,10 @@ describe "String#crypt" do
tainted_salt.taint
tainted_str.taint
- "mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").tainted?.should == false
- tainted_str.crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").tainted?.should == true
- "mypassword".crypt(tainted_salt).tainted?.should == true
- tainted_str.crypt(tainted_salt).tainted?.should == true
+ "mypassword".crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should_not.tainted?
+ tainted_str.crypt("$2a$04$0WVaz0pV3jzfZ5G5tpmHWu").should.tainted?
+ "mypassword".crypt(tainted_salt).should.tainted?
+ tainted_str.crypt(tainted_salt).should.tainted?
end
end
@@ -93,10 +93,10 @@ describe "String#crypt" do
tainted_salt.taint
tainted_str.taint
- "hello".crypt("aa").tainted?.should == false
- tainted_str.crypt("aa").tainted?.should == true
- "hello".crypt(tainted_salt).tainted?.should == true
- tainted_str.crypt(tainted_salt).tainted?.should == true
+ "hello".crypt("aa").should_not.tainted?
+ tainted_str.crypt("aa").should.tainted?
+ "hello".crypt(tainted_salt).should.tainted?
+ tainted_str.crypt(tainted_salt).should.tainted?
end
end
diff --git a/spec/ruby/core/string/delete_prefix_spec.rb b/spec/ruby/core/string/delete_prefix_spec.rb
index 92c301b44a..8469791f74 100644
--- a/spec/ruby/core/string/delete_prefix_spec.rb
+++ b/spec/ruby/core/string/delete_prefix_spec.rb
@@ -2,82 +2,89 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is '2.5' do
- describe "String#delete_prefix" do
- it "returns a copy of the string, with the given prefix removed" do
- 'hello'.delete_prefix('hell').should == 'o'
- 'hello'.delete_prefix('hello').should == ''
- end
+describe "String#delete_prefix" do
+ it "returns a copy of the string, with the given prefix removed" do
+ 'hello'.delete_prefix('hell').should == 'o'
+ 'hello'.delete_prefix('hello').should == ''
+ end
- it "returns a copy of the string, when the prefix isn't found" do
- s = 'hello'
- r = s.delete_prefix('hello!')
- r.should_not equal s
- r.should == s
- r = s.delete_prefix('ell')
- r.should_not equal s
- r.should == s
- r = s.delete_prefix('')
- r.should_not equal s
- r.should == s
- end
+ it "returns a copy of the string, when the prefix isn't found" do
+ s = 'hello'
+ r = s.delete_prefix('hello!')
+ r.should_not equal s
+ r.should == s
+ r = s.delete_prefix('ell')
+ r.should_not equal s
+ r.should == s
+ r = s.delete_prefix('')
+ r.should_not equal s
+ r.should == s
+ end
- ruby_version_is ''...'2.7' do
- it "taints resulting strings when other is tainted" do
- 'hello'.taint.delete_prefix('hell').tainted?.should == true
- 'hello'.taint.delete_prefix('').tainted?.should == true
- end
+ ruby_version_is ''...'2.7' do
+ it "taints resulting strings when other is tainted" do
+ 'hello'.taint.delete_prefix('hell').should.tainted?
+ 'hello'.taint.delete_prefix('').should.tainted?
end
+ end
- it "doesn't set $~" do
- $~ = nil
+ it "doesn't set $~" do
+ $~ = nil
- 'hello'.delete_prefix('hell')
- $~.should == nil
- end
+ 'hello'.delete_prefix('hell')
+ $~.should == nil
+ end
- it "calls to_str on its argument" do
- o = mock('x')
- o.should_receive(:to_str).and_return 'hell'
- 'hello'.delete_prefix(o).should == 'o'
- end
+ it "calls to_str on its argument" do
+ o = mock('x')
+ o.should_receive(:to_str).and_return 'hell'
+ 'hello'.delete_prefix(o).should == 'o'
+ end
+ ruby_version_is ''...'3.0' do
it "returns a subclass instance when called on a subclass instance" do
s = StringSpecs::MyString.new('hello')
s.delete_prefix('hell').should be_an_instance_of(StringSpecs::MyString)
end
end
- describe "String#delete_prefix!" do
- it "removes the found prefix" do
- s = 'hello'
- s.delete_prefix!('hell').should equal(s)
- s.should == 'o'
+ ruby_version_is '3.0' do
+ it "returns a String instance when called on a subclass instance" do
+ s = StringSpecs::MyString.new('hello')
+ s.delete_prefix('hell').should be_an_instance_of(String)
end
+ end
+end
- it "returns nil if no change is made" do
- s = 'hello'
- s.delete_prefix!('ell').should == nil
- s.delete_prefix!('').should == nil
- end
+describe "String#delete_prefix!" do
+ it "removes the found prefix" do
+ s = 'hello'
+ s.delete_prefix!('hell').should equal(s)
+ s.should == 'o'
+ end
- it "doesn't set $~" do
- $~ = nil
+ it "returns nil if no change is made" do
+ s = 'hello'
+ s.delete_prefix!('ell').should == nil
+ s.delete_prefix!('').should == nil
+ end
- 'hello'.delete_prefix!('hell')
- $~.should == nil
- end
+ it "doesn't set $~" do
+ $~ = nil
- it "calls to_str on its argument" do
- o = mock('x')
- o.should_receive(:to_str).and_return 'hell'
- 'hello'.delete_prefix!(o).should == 'o'
- end
+ 'hello'.delete_prefix!('hell')
+ $~.should == nil
+ end
- it "raises a #{frozen_error_class} when self is frozen" do
- -> { 'hello'.freeze.delete_prefix!('hell') }.should raise_error(frozen_error_class)
- -> { 'hello'.freeze.delete_prefix!('') }.should raise_error(frozen_error_class)
- -> { ''.freeze.delete_prefix!('') }.should raise_error(frozen_error_class)
- end
+ it "calls to_str on its argument" do
+ o = mock('x')
+ o.should_receive(:to_str).and_return 'hell'
+ 'hello'.delete_prefix!(o).should == 'o'
+ end
+
+ it "raises a FrozenError when self is frozen" do
+ -> { 'hello'.freeze.delete_prefix!('hell') }.should raise_error(FrozenError)
+ -> { 'hello'.freeze.delete_prefix!('') }.should raise_error(FrozenError)
+ -> { ''.freeze.delete_prefix!('') }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/delete_spec.rb b/spec/ruby/core/string/delete_spec.rb
index 130228041e..ebca0b7dae 100644
--- a/spec/ruby/core/string/delete_spec.rb
+++ b/spec/ruby/core/string/delete_spec.rb
@@ -70,10 +70,10 @@ describe "String#delete" do
ruby_version_is ''...'2.7' do
it "taints result when self is tainted" do
- "hello".taint.delete("e").tainted?.should == true
- "hello".taint.delete("a-z").tainted?.should == true
+ "hello".taint.delete("e").should.tainted?
+ "hello".taint.delete("a-z").should.tainted?
- "hello".delete("e".taint).tainted?.should == false
+ "hello".delete("e".taint).should_not.tainted?
end
end
@@ -93,8 +93,16 @@ describe "String#delete" do
-> { "hello world".delete(mock('x')) }.should raise_error(TypeError)
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(String)
+ end
end
end
@@ -111,11 +119,11 @@ describe "String#delete!" do
a.should == "hello"
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
a = "hello"
a.freeze
- -> { a.delete!("") }.should raise_error(frozen_error_class)
- -> { a.delete!("aeiou", "^e") }.should raise_error(frozen_error_class)
+ -> { a.delete!("") }.should raise_error(FrozenError)
+ -> { a.delete!("aeiou", "^e") }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/delete_suffix_spec.rb b/spec/ruby/core/string/delete_suffix_spec.rb
index edc0f73158..12d0ee175e 100644
--- a/spec/ruby/core/string/delete_suffix_spec.rb
+++ b/spec/ruby/core/string/delete_suffix_spec.rb
@@ -2,82 +2,89 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is '2.5' do
- describe "String#delete_suffix" do
- it "returns a copy of the string, with the given suffix removed" do
- 'hello'.delete_suffix('ello').should == 'h'
- 'hello'.delete_suffix('hello').should == ''
- end
+describe "String#delete_suffix" do
+ it "returns a copy of the string, with the given suffix removed" do
+ 'hello'.delete_suffix('ello').should == 'h'
+ 'hello'.delete_suffix('hello').should == ''
+ end
- it "returns a copy of the string, when the suffix isn't found" do
- s = 'hello'
- r = s.delete_suffix('!hello')
- r.should_not equal s
- r.should == s
- r = s.delete_suffix('ell')
- r.should_not equal s
- r.should == s
- r = s.delete_suffix('')
- r.should_not equal s
- r.should == s
- end
+ it "returns a copy of the string, when the suffix isn't found" do
+ s = 'hello'
+ r = s.delete_suffix('!hello')
+ r.should_not equal s
+ r.should == s
+ r = s.delete_suffix('ell')
+ r.should_not equal s
+ r.should == s
+ r = s.delete_suffix('')
+ r.should_not equal s
+ r.should == s
+ end
- ruby_version_is ''...'2.7' do
- it "taints resulting strings when other is tainted" do
- 'hello'.taint.delete_suffix('ello').tainted?.should == true
- 'hello'.taint.delete_suffix('').tainted?.should == true
- end
+ ruby_version_is ''...'2.7' do
+ it "taints resulting strings when other is tainted" do
+ 'hello'.taint.delete_suffix('ello').should.tainted?
+ 'hello'.taint.delete_suffix('').should.tainted?
end
+ end
- it "doesn't set $~" do
- $~ = nil
+ it "doesn't set $~" do
+ $~ = nil
- 'hello'.delete_suffix('ello')
- $~.should == nil
- end
+ 'hello'.delete_suffix('ello')
+ $~.should == nil
+ end
- it "calls to_str on its argument" do
- o = mock('x')
- o.should_receive(:to_str).and_return 'ello'
- 'hello'.delete_suffix(o).should == 'h'
- end
+ it "calls to_str on its argument" do
+ o = mock('x')
+ o.should_receive(:to_str).and_return 'ello'
+ 'hello'.delete_suffix(o).should == 'h'
+ end
+ ruby_version_is ''...'3.0' do
it "returns a subclass instance when called on a subclass instance" do
s = StringSpecs::MyString.new('hello')
s.delete_suffix('ello').should be_an_instance_of(StringSpecs::MyString)
end
end
- describe "String#delete_suffix!" do
- it "removes the found prefix" do
- s = 'hello'
- s.delete_suffix!('ello').should equal(s)
- s.should == 'h'
+ ruby_version_is '3.0' do
+ it "returns a String instance when called on a subclass instance" do
+ s = StringSpecs::MyString.new('hello')
+ s.delete_suffix('ello').should be_an_instance_of(String)
end
+ end
+end
- it "returns nil if no change is made" do
- s = 'hello'
- s.delete_suffix!('ell').should == nil
- s.delete_suffix!('').should == nil
- end
+describe "String#delete_suffix!" do
+ it "removes the found prefix" do
+ s = 'hello'
+ s.delete_suffix!('ello').should equal(s)
+ s.should == 'h'
+ end
- it "doesn't set $~" do
- $~ = nil
+ it "returns nil if no change is made" do
+ s = 'hello'
+ s.delete_suffix!('ell').should == nil
+ s.delete_suffix!('').should == nil
+ end
- 'hello'.delete_suffix!('ello')
- $~.should == nil
- end
+ it "doesn't set $~" do
+ $~ = nil
- it "calls to_str on its argument" do
- o = mock('x')
- o.should_receive(:to_str).and_return 'ello'
- 'hello'.delete_suffix!(o).should == 'h'
- end
+ 'hello'.delete_suffix!('ello')
+ $~.should == nil
+ end
- it "raises a #{frozen_error_class} when self is frozen" do
- -> { 'hello'.freeze.delete_suffix!('ello') }.should raise_error(frozen_error_class)
- -> { 'hello'.freeze.delete_suffix!('') }.should raise_error(frozen_error_class)
- -> { ''.freeze.delete_suffix!('') }.should raise_error(frozen_error_class)
- end
+ it "calls to_str on its argument" do
+ o = mock('x')
+ o.should_receive(:to_str).and_return 'ello'
+ 'hello'.delete_suffix!(o).should == 'h'
+ end
+
+ it "raises a FrozenError when self is frozen" do
+ -> { 'hello'.freeze.delete_suffix!('ello') }.should raise_error(FrozenError)
+ -> { 'hello'.freeze.delete_suffix!('') }.should raise_error(FrozenError)
+ -> { ''.freeze.delete_suffix!('') }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/downcase_spec.rb b/spec/ruby/core/string/downcase_spec.rb
index 84e94ee104..4427c9df10 100644
--- a/spec/ruby/core/string/downcase_spec.rb
+++ b/spec/ruby/core/string/downcase_spec.rb
@@ -70,14 +70,22 @@ describe "String#downcase" do
ruby_version_is ''...'2.7' do
it "taints result when self is tainted" do
- "".taint.downcase.tainted?.should == true
- "x".taint.downcase.tainted?.should == true
- "X".taint.downcase.tainted?.should == true
+ "".taint.downcase.should.tainted?
+ "x".taint.downcase.should.tainted?
+ "X".taint.downcase.should.tainted?
end
end
- it "returns a subclass instance for subclasses" do
- StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns a subclass instance for subclasses" do
+ StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns a String instance for subclasses" do
+ StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(String)
+ end
end
end
@@ -88,6 +96,12 @@ describe "String#downcase!" do
a.should == "hello"
end
+ it "modifies self in place for non-ascii-compatible encodings" do
+ a = "HeLlO".encode("utf-16le")
+ a.downcase!
+ a.should == "hello".encode("utf-16le")
+ end
+
describe "full Unicode case mapping" do
it "modifies self in place for all of Unicode with no option" do
a = "ÄÖÜ"
@@ -112,6 +126,12 @@ describe "String#downcase!" do
a.downcase!(:ascii)
a.should == "cÅr"
end
+
+ it "works for non-ascii-compatible encodings" do
+ a = "ABC".encode("utf-16le")
+ a.downcase!(:ascii)
+ a.should == "abc".encode("utf-16le")
+ end
end
describe "full Unicode case mapping adapted for Turkic languages" do
@@ -171,9 +191,9 @@ describe "String#downcase!" do
a.should == "hello"
end
- it "raises a #{frozen_error_class} when self is frozen" do
- -> { "HeLlo".freeze.downcase! }.should raise_error(frozen_error_class)
- -> { "hello".freeze.downcase! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when self is frozen" do
+ -> { "HeLlo".freeze.downcase! }.should raise_error(FrozenError)
+ -> { "hello".freeze.downcase! }.should raise_error(FrozenError)
end
it "sets the result String encoding to the source String encoding" do
diff --git a/spec/ruby/core/string/dump_spec.rb b/spec/ruby/core/string/dump_spec.rb
index 260ee37adb..817dec6c4d 100644
--- a/spec/ruby/core/string/dump_spec.rb
+++ b/spec/ruby/core/string/dump_spec.rb
@@ -5,22 +5,30 @@ require_relative 'fixtures/classes'
describe "String#dump" do
ruby_version_is ''...'2.7' do
it "taints the result if self is tainted" do
- "foo".taint.dump.tainted?.should == true
- "foo\n".taint.dump.tainted?.should == true
+ "foo".taint.dump.should.tainted?
+ "foo\n".taint.dump.should.tainted?
end
it "untrusts the result if self is untrusted" do
- "foo".untrust.dump.untrusted?.should == true
- "foo\n".untrust.dump.untrusted?.should == true
+ "foo".untrust.dump.should.untrusted?
+ "foo\n".untrust.dump.should.untrusted?
end
end
it "does not take into account if a string is frozen" do
- "foo".freeze.dump.frozen?.should == false
+ "foo".freeze.dump.should_not.frozen?
end
- it "returns a subclass instance" do
- StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns a subclass instance" do
+ StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns a String instance" do
+ StringSpecs::MyString.new.dump.should be_an_instance_of(String)
+ end
end
it "wraps string with \"" do
diff --git a/spec/ruby/core/string/each_grapheme_cluster_spec.rb b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
index 5367f84887..632f2337f1 100644
--- a/spec/ruby/core/string/each_grapheme_cluster_spec.rb
+++ b/spec/ruby/core/string/each_grapheme_cluster_spec.rb
@@ -2,10 +2,8 @@ require_relative 'shared/chars'
require_relative 'shared/grapheme_clusters'
require_relative 'shared/each_char_without_block'
-ruby_version_is "2.5" do
- describe "String#each_grapheme_cluster" do
- it_behaves_like :string_chars, :each_grapheme_cluster
- it_behaves_like :string_grapheme_clusters, :each_grapheme_cluster
- it_behaves_like :string_each_char_without_block, :each_grapheme_cluster
- end
+describe "String#each_grapheme_cluster" do
+ it_behaves_like :string_chars, :each_grapheme_cluster
+ it_behaves_like :string_grapheme_clusters, :each_grapheme_cluster
+ it_behaves_like :string_each_char_without_block, :each_grapheme_cluster
end
diff --git a/spec/ruby/core/string/element_set_spec.rb b/spec/ruby/core/string/element_set_spec.rb
index 608efc23b3..c9e02a7381 100644
--- a/spec/ruby/core/string/element_set_spec.rb
+++ b/spec/ruby/core/string/element_set_spec.rb
@@ -5,7 +5,7 @@ require_relative 'fixtures/classes'
# TODO: Add missing String#[]= specs:
# String#[re, idx] = obj
-describe "String#[]= with Fixnum index" do
+describe "String#[]= with Integer index" do
it "replaces the char at idx with other_str" do
a = "hello"
a[0] = "bam"
@@ -18,11 +18,11 @@ describe "String#[]= with Fixnum index" do
it "taints self if other_str is tainted" do
a = "hello"
a[0] = "".taint
- a.tainted?.should == true
+ a.should.tainted?
a = "hello"
a[0] = "x".taint
- a.tainted?.should == true
+ a.should.tainted?
end
end
@@ -52,11 +52,11 @@ describe "String#[]= with Fixnum index" do
str.should == "hello"
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
a = "hello"
a.freeze
- -> { a[0] = "bam" }.should raise_error(frozen_error_class)
+ -> { a[0] = "bam" }.should raise_error(FrozenError)
end
it "calls to_int on index" do
@@ -85,7 +85,7 @@ describe "String#[]= with Fixnum index" do
-> { "test"[1] = nil }.should raise_error(TypeError)
end
- it "raises a TypeError if passed a Fixnum replacement" do
+ it "raises a TypeError if passed an Integer replacement" do
-> { "abc"[1] = 65 }.should raise_error(TypeError)
end
@@ -102,7 +102,7 @@ describe "String#[]= with Fixnum index" do
str.should == "あa"
end
- it "raises a TypeError if #to_int does not return an Fixnum" do
+ it "raises a TypeError if #to_int does not return an Integer" do
index = mock("string element set")
index.should_receive(:to_int).and_return('1')
@@ -243,7 +243,7 @@ describe "String#[]= with a Regexp index" do
str.should == "axc"
end
- it "raises a TypeError if #to_int does not return a Fixnum" do
+ it "raises a TypeError if #to_int does not return an Integer" do
ref = mock("string element set regexp ref")
ref.should_receive(:to_int).and_return(nil)
@@ -438,7 +438,7 @@ describe "String#[]= with a Range index" do
end
end
-describe "String#[]= with Fixnum index, count" do
+describe "String#[]= with Integer index, count" do
it "starts at idx and overwrites count characters before inserting the rest of other_str" do
a = "hello"
a[0, 2] = "xx"
@@ -491,11 +491,11 @@ describe "String#[]= with Fixnum index, count" do
it "taints self if other_str is tainted" do
a = "hello"
a[0, 0] = "".taint
- a.tainted?.should == true
+ a.should.tainted?
a = "hello"
a[1, 4] = "x".taint
- a.tainted?.should == true
+ a.should.tainted?
end
end
diff --git a/spec/ruby/core/string/empty_spec.rb b/spec/ruby/core/string/empty_spec.rb
index fb52070723..8e53a16afc 100644
--- a/spec/ruby/core/string/empty_spec.rb
+++ b/spec/ruby/core/string/empty_spec.rb
@@ -3,10 +3,10 @@ require_relative 'fixtures/classes'
describe "String#empty?" do
it "returns true if the string has a length of zero" do
- "hello".empty?.should == false
- " ".empty?.should == false
- "\x00".empty?.should == false
- "".empty?.should == true
- StringSpecs::MyString.new("").empty?.should == true
+ "hello".should_not.empty?
+ " ".should_not.empty?
+ "\x00".should_not.empty?
+ "".should.empty?
+ StringSpecs::MyString.new("").should.empty?
end
end
diff --git a/spec/ruby/core/string/encode_spec.rb b/spec/ruby/core/string/encode_spec.rb
index 1c0c939358..ae641b2110 100644
--- a/spec/ruby/core/string/encode_spec.rb
+++ b/spec/ruby/core/string/encode_spec.rb
@@ -19,13 +19,17 @@ describe "String#encode" do
it "returns a copy when Encoding.default_internal is nil" do
Encoding.default_internal = nil
str = "あ"
- str.encode.should_not equal(str)
+ encoded = str.encode
+ encoded.should_not equal(str)
+ encoded.should == str
end
it "returns a copy for a ASCII-only String when Encoding.default_internal is nil" do
Encoding.default_internal = nil
str = "abc"
- str.encode.should_not equal(str)
+ encoded = str.encode
+ encoded.should_not equal(str)
+ encoded.should == str
end
it "encodes an ascii substring of a binary string to UTF-8" do
@@ -39,7 +43,9 @@ describe "String#encode" do
describe "when passed to encoding" do
it "returns a copy when passed the same encoding as the String" do
str = "あ"
- str.encode(Encoding::UTF_8).should_not equal(str)
+ encoded = str.encode(Encoding::UTF_8)
+ encoded.should_not equal(str)
+ encoded.should == str
end
it "round trips a String" do
@@ -75,6 +81,7 @@ describe "String#encode" do
encoded = str.encode("utf-8", "utf-8")
encoded.should_not equal(str)
+ encoded.should == str.force_encoding("utf-8")
encoded.encoding.should == Encoding::UTF_8
end
@@ -87,14 +94,28 @@ describe "String#encode" do
describe "when passed to, options" do
it "returns a copy when the destination encoding is the same as the String encoding" do
str = "あ"
- str.encode(Encoding::UTF_8, undef: :replace).should_not equal(str)
+ encoded = str.encode(Encoding::UTF_8, undef: :replace)
+ encoded.should_not equal(str)
+ encoded.should == str
end
end
describe "when passed to, from, options" do
it "returns a copy when both encodings are the same" do
str = "あ"
- str.encode("utf-8", "utf-8", invalid: :replace).should_not equal(str)
+ encoded = str.encode("utf-8", "utf-8", invalid: :replace)
+ encoded.should_not equal(str)
+ encoded.should == str
+ end
+
+ it "returns a copy in the destination encoding when both encodings are the same" do
+ str = "あ"
+ str.force_encoding("binary")
+ encoded = str.encode("utf-8", "utf-8", invalid: :replace)
+
+ encoded.should_not equal(str)
+ encoded.should == str.force_encoding("utf-8")
+ encoded.encoding.should == Encoding::UTF_8
end
end
end
@@ -112,13 +133,13 @@ describe "String#encode!" do
it_behaves_like :string_encode, :encode!
- it "raises a #{frozen_error_class} when called on a frozen String" do
- -> { "foo".freeze.encode!("euc-jp") }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when called on a frozen String" do
+ -> { "foo".freeze.encode!("euc-jp") }.should raise_error(FrozenError)
end
# http://redmine.ruby-lang.org/issues/show/1836
- it "raises a #{frozen_error_class} when called on a frozen String when it's a no-op" do
- -> { "foo".freeze.encode!("utf-8") }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when called on a frozen String when it's a no-op" do
+ -> { "foo".freeze.encode!("utf-8") }.should raise_error(FrozenError)
end
describe "when passed no options" do
diff --git a/spec/ruby/core/string/end_with_spec.rb b/spec/ruby/core/string/end_with_spec.rb
index 9ced0ca3d2..ac4fff72ad 100644
--- a/spec/ruby/core/string/end_with_spec.rb
+++ b/spec/ruby/core/string/end_with_spec.rb
@@ -1,56 +1,8 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../../shared/string/end_with'
describe "String#end_with?" do
- it "returns true only if ends match" do
- s = "hello"
- s.should.end_with?('o')
- s.should.end_with?('llo')
- end
-
- it 'returns false if the end does not match' do
- s = 'hello'
- s.should_not.end_with?('ll')
- end
-
- it "returns true if the search string is empty" do
- "hello".should.end_with?("")
- "".should.end_with?("")
- end
-
- it "returns true only if any ending match" do
- "hello".should.end_with?('x', 'y', 'llo', 'z')
- end
-
- it "converts its argument using :to_str" do
- s = "hello"
- find = mock('o')
- find.should_receive(:to_str).and_return("o")
- s.should.end_with?(find)
- end
-
- it "ignores arguments not convertible to string" do
- "hello".should_not.end_with?()
- -> { "hello".end_with?(1) }.should raise_error(TypeError)
- -> { "hello".end_with?(["o"]) }.should raise_error(TypeError)
- -> { "hello".end_with?(1, nil, "o") }.should raise_error(TypeError)
- end
-
- it "uses only the needed arguments" do
- find = mock('h')
- find.should_not_receive(:to_str)
- "hello".should.end_with?("o",find)
- end
-
- it "works for multibyte strings" do
- "céréale".should.end_with?("réale")
- end
-
- it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
- pat = "ア".encode Encoding::EUC_JP
- -> do
- "あれ".end_with?(pat)
- end.should raise_error(Encoding::CompatibilityError)
- end
+ it_behaves_like :end_with, :to_s
end
diff --git a/spec/ruby/core/string/fixtures/classes.rb b/spec/ruby/core/string/fixtures/classes.rb
index 1cc7600abb..26fcd51b5d 100644
--- a/spec/ruby/core/string/fixtures/classes.rb
+++ b/spec/ruby/core/string/fixtures/classes.rb
@@ -46,4 +46,15 @@ module StringSpecs
self.replace(str)
end
end
+
+ class SpecialVarProcessor
+ def process(match)
+ if $~ != nil
+ str = $~[0]
+ else
+ str = "unset"
+ end
+ "<#{str}>"
+ end
+ end
end
diff --git a/spec/ruby/core/string/force_encoding_spec.rb b/spec/ruby/core/string/force_encoding_spec.rb
index 56d9b1e9bc..2fe5f79c0f 100644
--- a/spec/ruby/core/string/force_encoding_spec.rb
+++ b/spec/ruby/core/string/force_encoding_spec.rb
@@ -64,8 +64,8 @@ describe "String#force_encoding" do
str.dup.force_encoding('utf-16le').should_not == str.encode('utf-16le')
end
- it "raises a #{frozen_error_class} if self is frozen" do
+ it "raises a FrozenError if self is frozen" do
str = "abcd".freeze
- -> { str.force_encoding(str.encoding) }.should raise_error(frozen_error_class)
+ -> { str.force_encoding(str.encoding) }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/grapheme_clusters_spec.rb b/spec/ruby/core/string/grapheme_clusters_spec.rb
index 0cba0e4216..3046265a12 100644
--- a/spec/ruby/core/string/grapheme_clusters_spec.rb
+++ b/spec/ruby/core/string/grapheme_clusters_spec.rb
@@ -1,15 +1,13 @@
require_relative 'shared/chars'
require_relative 'shared/grapheme_clusters'
-ruby_version_is "2.5" do
- describe "String#grapheme_clusters" do
- it_behaves_like :string_chars, :grapheme_clusters
- it_behaves_like :string_grapheme_clusters, :grapheme_clusters
+describe "String#grapheme_clusters" do
+ it_behaves_like :string_chars, :grapheme_clusters
+ it_behaves_like :string_grapheme_clusters, :grapheme_clusters
- it "returns an array when no block given" do
- string = "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}"
- string.grapheme_clusters.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"]
+ it "returns an array when no block given" do
+ string = "ab\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}\u{1F43E}"
+ string.grapheme_clusters.should == ['a', 'b', "\u{1f3f3}\u{fe0f}\u{200d}\u{1f308}", "\u{1F43E}"]
- end
end
end
diff --git a/spec/ruby/core/string/gsub_spec.rb b/spec/ruby/core/string/gsub_spec.rb
index f1d2d5ac06..6789199ff3 100644
--- a/spec/ruby/core/string/gsub_spec.rb
+++ b/spec/ruby/core/string/gsub_spec.rb
@@ -171,14 +171,14 @@ describe "String#gsub with pattern and replacement" do
hello_t.taint; a_t.taint; empty_t.taint
- hello_t.gsub(/./, a).tainted?.should == true
- hello_t.gsub(/./, empty).tainted?.should == true
+ hello_t.gsub(/./, a).should.tainted?
+ hello_t.gsub(/./, empty).should.tainted?
- hello.gsub(/./, a_t).tainted?.should == true
- hello.gsub(/./, empty_t).tainted?.should == true
- hello.gsub(//, empty_t).tainted?.should == true
+ hello.gsub(/./, a_t).should.tainted?
+ hello.gsub(/./, empty_t).should.tainted?
+ hello.gsub(//, empty_t).should.tainted?
- hello.gsub(//.taint, "foo").tainted?.should == false
+ hello.gsub(//.taint, "foo").should_not.tainted?
end
end
@@ -199,14 +199,14 @@ describe "String#gsub with pattern and replacement" do
hello_t.untrust; a_t.untrust; empty_t.untrust
- hello_t.gsub(/./, a).untrusted?.should == true
- hello_t.gsub(/./, empty).untrusted?.should == true
+ hello_t.gsub(/./, a).should.untrusted?
+ hello_t.gsub(/./, empty).should.untrusted?
- hello.gsub(/./, a_t).untrusted?.should == true
- hello.gsub(/./, empty_t).untrusted?.should == true
- hello.gsub(//, empty_t).untrusted?.should == true
+ hello.gsub(/./, a_t).should.untrusted?
+ hello.gsub(/./, empty_t).should.untrusted?
+ hello.gsub(//, empty_t).should.untrusted?
- hello.gsub(//.untrust, "foo").untrusted?.should == false
+ hello.gsub(//.untrust, "foo").should_not.untrusted?
end
end
@@ -236,11 +236,22 @@ describe "String#gsub with pattern and replacement" do
-> { "hello".gsub(/[aeiou]/, nil) }.should raise_error(TypeError)
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(String)
+ StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(String)
+ end
end
# Note: $~ cannot be tested because mspec messes with it
@@ -464,6 +475,11 @@ describe "String#gsub with pattern and block" do
offsets.should == [[1, 2], [4, 5]]
end
+ it "does not set $~ for procs created from methods" do
+ str = "hello"
+ str.gsub("l", &StringSpecs::SpecialVarProcessor.new.method(:process)).should == "he<unset><unset>o"
+ end
+
it "restores $~ after leaving the block" do
[/./, "l"].each do |pattern|
old_md = nil
@@ -521,14 +537,14 @@ describe "String#gsub with pattern and block" do
hello_t.untrust; a_t.untrust; empty_t.untrust
- hello_t.gsub(/./) { a }.untrusted?.should == true
- hello_t.gsub(/./) { empty }.untrusted?.should == true
+ hello_t.gsub(/./) { a }.should.untrusted?
+ hello_t.gsub(/./) { empty }.should.untrusted?
- hello.gsub(/./) { a_t }.untrusted?.should == true
- hello.gsub(/./) { empty_t }.untrusted?.should == true
- hello.gsub(//) { empty_t }.untrusted?.should == true
+ hello.gsub(/./) { a_t }.should.untrusted?
+ hello.gsub(/./) { empty_t }.should.untrusted?
+ hello.gsub(//) { empty_t }.should.untrusted?
- hello.gsub(//.untrust) { "foo" }.untrusted?.should == false
+ hello.gsub(//.untrust) { "foo" }.should_not.untrusted?
end
end
@@ -594,14 +610,14 @@ describe "String#gsub! with pattern and replacement" do
ruby_version_is ''...'2.7' do
it "taints self if replacement is tainted" do
a = "hello"
- a.gsub!(/./.taint, "foo").tainted?.should == false
- a.gsub!(/./, "foo".taint).tainted?.should == true
+ a.gsub!(/./.taint, "foo").should_not.tainted?
+ a.gsub!(/./, "foo".taint).should.tainted?
end
it "untrusts self if replacement is untrusted" do
a = "hello"
- a.gsub!(/./.untrust, "foo").untrusted?.should == false
- a.gsub!(/./, "foo".untrust).untrusted?.should == true
+ a.gsub!(/./.untrust, "foo").should_not.untrusted?
+ a.gsub!(/./, "foo".untrust).should.untrusted?
end
end
@@ -613,13 +629,13 @@ describe "String#gsub! with pattern and replacement" do
end
# See [ruby-core:23666]
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
s = "hello"
s.freeze
- -> { s.gsub!(/ROAR/, "x") }.should raise_error(frozen_error_class)
- -> { s.gsub!(/e/, "e") }.should raise_error(frozen_error_class)
- -> { s.gsub!(/[aeiou]/, '*') }.should raise_error(frozen_error_class)
+ -> { s.gsub!(/ROAR/, "x") }.should raise_error(FrozenError)
+ -> { s.gsub!(/e/, "e") }.should raise_error(FrozenError)
+ -> { s.gsub!(/[aeiou]/, '*') }.should raise_error(FrozenError)
end
end
@@ -633,14 +649,14 @@ describe "String#gsub! with pattern and block" do
ruby_version_is ''...'2.7' do
it "taints self if block's result is tainted" do
a = "hello"
- a.gsub!(/./.taint) { "foo" }.tainted?.should == false
- a.gsub!(/./) { "foo".taint }.tainted?.should == true
+ a.gsub!(/./.taint) { "foo" }.should_not.tainted?
+ a.gsub!(/./) { "foo".taint }.should.tainted?
end
it "untrusts self if block's result is untrusted" do
a = "hello"
- a.gsub!(/./.untrust) { "foo" }.untrusted?.should == false
- a.gsub!(/./) { "foo".untrust }.untrusted?.should == true
+ a.gsub!(/./.untrust) { "foo" }.should_not.untrusted?
+ a.gsub!(/./) { "foo".untrust }.should.untrusted?
end
end
@@ -652,13 +668,13 @@ describe "String#gsub! with pattern and block" do
end
# See [ruby-core:23663]
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
s = "hello"
s.freeze
- -> { s.gsub!(/ROAR/) { "x" } }.should raise_error(frozen_error_class)
- -> { s.gsub!(/e/) { "e" } }.should raise_error(frozen_error_class)
- -> { s.gsub!(/[aeiou]/) { '*' } }.should raise_error(frozen_error_class)
+ -> { s.gsub!(/ROAR/) { "x" } }.should raise_error(FrozenError)
+ -> { s.gsub!(/e/) { "e" } }.should raise_error(FrozenError)
+ -> { s.gsub!(/[aeiou]/) { '*' } }.should raise_error(FrozenError)
end
it "uses the compatible encoding if they are compatible" do
diff --git a/spec/ruby/core/string/index_spec.rb b/spec/ruby/core/string/index_spec.rb
index ca62911db0..8d2c8af193 100644
--- a/spec/ruby/core/string/index_spec.rb
+++ b/spec/ruby/core/string/index_spec.rb
@@ -27,7 +27,7 @@ describe "String#index" do
"abc".index("c", offset).should == 2
end
- it "raises a TypeError if passed a Fixnum" do
+ it "raises a TypeError if passed an Integer" do
-> { "abc".index 97 }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/core/string/insert_spec.rb b/spec/ruby/core/string/insert_spec.rb
index de7c12423a..752cbb2f37 100644
--- a/spec/ruby/core/string/insert_spec.rb
+++ b/spec/ruby/core/string/insert_spec.rb
@@ -44,12 +44,12 @@ describe "String#insert with index, other" do
ruby_version_is ''...'2.7' do
it "taints self if string to insert is tainted" do
str = "abcd"
- str.insert(0, "T".taint).tainted?.should == true
+ str.insert(0, "T".taint).should.tainted?
str = "abcd"
other = mock('T')
def other.to_str() "T".taint end
- str.insert(0, other).tainted?.should == true
+ str.insert(0, other).should.tainted?
end
end
@@ -59,10 +59,10 @@ describe "String#insert with index, other" do
-> { "abcd".insert(-6, mock('x')) }.should raise_error(TypeError)
end
- it "raises a #{frozen_error_class} if self is frozen" do
+ it "raises a FrozenError if self is frozen" do
str = "abcd".freeze
- -> { str.insert(4, '') }.should raise_error(frozen_error_class)
- -> { str.insert(4, 'X') }.should raise_error(frozen_error_class)
+ -> { str.insert(4, '') }.should raise_error(FrozenError)
+ -> { str.insert(4, 'X') }.should raise_error(FrozenError)
end
it "inserts a character into a multibyte encoded string" do
diff --git a/spec/ruby/core/string/inspect_spec.rb b/spec/ruby/core/string/inspect_spec.rb
index 8ddbae132a..9818796c83 100644
--- a/spec/ruby/core/string/inspect_spec.rb
+++ b/spec/ruby/core/string/inspect_spec.rb
@@ -5,13 +5,13 @@ require_relative 'fixtures/classes'
describe "String#inspect" do
ruby_version_is ''...'2.7' do
it "taints the result if self is tainted" do
- "foo".taint.inspect.tainted?.should == true
- "foo\n".taint.inspect.tainted?.should == true
+ "foo".taint.inspect.should.tainted?
+ "foo\n".taint.inspect.should.tainted?
end
it "untrusts the result if self is untrusted" do
- "foo".untrust.inspect.untrusted?.should == true
- "foo\n".untrust.inspect.untrusted?.should == true
+ "foo".untrust.inspect.should.untrusted?
+ "foo\n".untrust.inspect.should.untrusted?
end
end
@@ -319,6 +319,10 @@ describe "String#inspect" do
0.chr.inspect.should == '"\\x00"'
end
+ it "uses \\x notation for broken UTF-8 sequences" do
+ "\xF0\x9F".inspect.should == '"\\xF0\\x9F"'
+ end
+
describe "when default external is UTF-8" do
before :each do
@extenc, Encoding.default_external = Encoding.default_external, Encoding::UTF_8
diff --git a/spec/ruby/core/string/ljust_spec.rb b/spec/ruby/core/string/ljust_spec.rb
index f377e39775..0c3b2a2f44 100644
--- a/spec/ruby/core/string/ljust_spec.rb
+++ b/spec/ruby/core/string/ljust_spec.rb
@@ -33,11 +33,11 @@ describe "String#ljust with length, padding" do
ruby_version_is ''...'2.7' do
it "taints result when self or padstr is tainted" do
- "x".taint.ljust(4).tainted?.should == true
- "x".taint.ljust(0).tainted?.should == true
- "".taint.ljust(0).tainted?.should == true
- "x".taint.ljust(4, "*").tainted?.should == true
- "x".ljust(4, "*".taint).tainted?.should == true
+ "x".taint.ljust(4).should.tainted?
+ "x".taint.ljust(0).should.tainted?
+ "".taint.ljust(0).should.tainted?
+ "x".taint.ljust(4, "*").should.tainted?
+ "x".ljust(4, "*".taint).should.tainted?
end
end
@@ -74,13 +74,26 @@ describe "String#ljust with length, padding" do
-> { "hello".ljust(10, '') }.should raise_error(ArgumentError)
end
- it "returns subclass instances when called on subclasses" do
- StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on subclasses" do
+ StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString)
- "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on subclasses" do
+ StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+
+ "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ end
end
ruby_version_is ''...'2.7' do
diff --git a/spec/ruby/core/string/lstrip_spec.rb b/spec/ruby/core/string/lstrip_spec.rb
index b1a4e8541f..6b40189500 100644
--- a/spec/ruby/core/string/lstrip_spec.rb
+++ b/spec/ruby/core/string/lstrip_spec.rb
@@ -7,18 +7,20 @@ describe "String#lstrip" do
" hello world ".lstrip.should == "hello world "
"\n\r\t\n\v\r hello world ".lstrip.should == "hello world "
"hello".lstrip.should == "hello"
- "\000 \000hello\000 \000".lstrip.should == "\000 \000hello\000 \000"
end
- it "does not strip leading \\0" do
- "\x00hello".lstrip.should == "\x00hello"
+ ruby_version_is '3.1' do
+ it "strips leading \\0" do
+ "\x00hello".lstrip.should == "hello"
+ "\000 \000hello\000 \000".lstrip.should == "hello\000 \000"
+ end
end
ruby_version_is ''...'2.7' do
it "taints the result when self is tainted" do
- "".taint.lstrip.tainted?.should == true
- "ok".taint.lstrip.tainted?.should == true
- " ok".taint.lstrip.tainted?.should == true
+ "".taint.lstrip.should.tainted?
+ "ok".taint.lstrip.should.tainted?
+ " ok".taint.lstrip.should.tainted?
end
end
end
@@ -28,10 +30,14 @@ describe "String#lstrip!" do
a = " hello "
a.lstrip!.should equal(a)
a.should == "hello "
+ end
- a = "\000 \000hello\000 \000"
- a.lstrip!
- a.should == "\000 \000hello\000 \000"
+ ruby_version_is '3.1' do
+ it "strips leading \\0" do
+ a = "\000 \000hello\000 \000"
+ a.lstrip!
+ a.should == "hello\000 \000"
+ end
end
it "returns nil if no modifications were made" do
@@ -40,13 +46,13 @@ describe "String#lstrip!" do
a.should == "hello"
end
- it "raises a #{frozen_error_class} on a frozen instance that is modified" do
- -> { " hello ".freeze.lstrip! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that is modified" do
+ -> { " hello ".freeze.lstrip! }.should raise_error(FrozenError)
end
# see [ruby-core:23657]
- it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do
- -> { "hello".freeze.lstrip! }.should raise_error(frozen_error_class)
- -> { "".freeze.lstrip! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that would not be modified" do
+ -> { "hello".freeze.lstrip! }.should raise_error(FrozenError)
+ -> { "".freeze.lstrip! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/match_spec.rb b/spec/ruby/core/string/match_spec.rb
index 78b94baa44..5e988f34ca 100644
--- a/spec/ruby/core/string/match_spec.rb
+++ b/spec/ruby/core/string/match_spec.rb
@@ -137,7 +137,7 @@ describe "String#match" do
end
it "calls match on the regular expression" do
- regexp = /./
+ regexp = /./.dup
regexp.should_receive(:match).and_return(:foo)
'hello'.match(regexp).should == :foo
end
diff --git a/spec/ruby/core/string/modulo_spec.rb b/spec/ruby/core/string/modulo_spec.rb
index a16112bf44..dc11ced4e2 100644
--- a/spec/ruby/core/string/modulo_spec.rb
+++ b/spec/ruby/core/string/modulo_spec.rb
@@ -1,8 +1,22 @@
require_relative '../../spec_helper'
+require_relative '../kernel/shared/sprintf'
+require_relative '../kernel/shared/sprintf_encoding'
require_relative 'fixtures/classes'
require_relative '../../shared/hash/key_error'
describe "String#%" do
+ it_behaves_like :kernel_sprintf, -> format, *args {
+ format % args
+ }
+
+ it_behaves_like :kernel_sprintf_encoding, -> format, *args {
+ format % args
+ }
+end
+
+# TODO: these specs are mostly redundant with kernel/shared/sprintf.rb specs.
+# These specs should be moved there and deduplicated.
+describe "String#%" do
context "when key is missing from passed-in hash" do
it_behaves_like :key_error, -> obj, key { "%{#{key}}" % obj }, { a: 5 }
end
@@ -36,18 +50,9 @@ describe "String#%" do
end
end
- ruby_version_is ""..."2.5" do
- it "formats single % character at the end as literal %" do
- ("%" % []).should == "%"
- ("foo%" % []).should == "foo%"
- end
- end
-
- ruby_version_is "2.5" do
- it "raises an error if single % appears at the end" do
- -> { ("%" % []) }.should raise_error(ArgumentError)
- -> { ("foo%" % [])}.should raise_error(ArgumentError)
- end
+ it "raises an error if single % appears at the end" do
+ -> { ("%" % []) }.should raise_error(ArgumentError)
+ -> { ("foo%" % [])}.should raise_error(ArgumentError)
end
it "formats single % character before a newline as literal %" do
@@ -314,8 +319,8 @@ describe "String#%" do
subcls_format.taint
format.taint
- (format % universal).tainted?.should == true
- (subcls_format % universal).tainted?.should == true
+ (format % universal).should.tainted?
+ (subcls_format % universal).should.tainted?
end
end
end
@@ -578,12 +583,12 @@ describe "String#%" do
obj = mock('x')
def obj.inspect() "x".taint end
- ("%p" % obj).tainted?.should == true
+ ("%p" % obj).should.tainted?
obj = mock('x'); obj.taint
def obj.inspect() "x" end
- ("%p" % obj).tainted?.should == false
+ ("%p" % obj).should_not.tainted?
end
end
@@ -617,8 +622,8 @@ describe "String#%" do
ruby_version_is ''...'2.7' do
it "taints result for %s when argument is tainted" do
- ("%s" % "x".taint).tainted?.should == true
- ("%s" % mock('x').taint).tainted?.should == true
+ ("%s" % "x".taint).should.tainted?
+ ("%s" % mock('x').taint).should.tainted?
end
end
@@ -784,7 +789,7 @@ describe "String#%" do
ruby_version_is ''...'2.7' do
it "doesn't taint the result for #{format} when argument is tainted" do
- (format % "5".taint).tainted?.should == false
+ (format % "5".taint).should_not.tainted?
end
end
end
diff --git a/spec/ruby/core/string/ord_spec.rb b/spec/ruby/core/string/ord_spec.rb
index 0f5a3f6a37..cfc630a124 100644
--- a/spec/ruby/core/string/ord_spec.rb
+++ b/spec/ruby/core/string/ord_spec.rb
@@ -1,8 +1,8 @@
require_relative '../../spec_helper'
describe "String#ord" do
- it "returns a Fixnum" do
- 'a'.ord.should be_an_instance_of(Fixnum)
+ it "returns an Integer" do
+ 'a'.ord.should be_an_instance_of(Integer)
end
it "returns the codepoint of the first character in the String" do
diff --git a/spec/ruby/core/string/percent_spec.rb b/spec/ruby/core/string/percent_spec.rb
deleted file mode 100644
index e3460522b1..0000000000
--- a/spec/ruby/core/string/percent_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require_relative '../../spec_helper'
-require_relative '../kernel/shared/sprintf'
-require_relative '../kernel/shared/sprintf_encoding'
-
-describe "String#%" do
- it_behaves_like :kernel_sprintf, -> format, *args {
- format % args
- }
-
- it_behaves_like :kernel_sprintf_encoding, -> format, *args {
- format % args
- }
-end
diff --git a/spec/ruby/core/string/prepend_spec.rb b/spec/ruby/core/string/prepend_spec.rb
index c20c5a9e59..a6074be3c6 100644
--- a/spec/ruby/core/string/prepend_spec.rb
+++ b/spec/ruby/core/string/prepend_spec.rb
@@ -20,12 +20,12 @@ describe "String#prepend" do
-> { 'hello '.prepend mock('x') }.should raise_error(TypeError)
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
a = "hello"
a.freeze
- -> { a.prepend "" }.should raise_error(frozen_error_class)
- -> { a.prepend "test" }.should raise_error(frozen_error_class)
+ -> { a.prepend "" }.should raise_error(FrozenError)
+ -> { a.prepend "test" }.should raise_error(FrozenError)
end
it "works when given a subclass instance" do
diff --git a/spec/ruby/core/string/reverse_spec.rb b/spec/ruby/core/string/reverse_spec.rb
index eef46063a5..cf4956a528 100644
--- a/spec/ruby/core/string/reverse_spec.rb
+++ b/spec/ruby/core/string/reverse_spec.rb
@@ -12,8 +12,8 @@ describe "String#reverse" do
ruby_version_is ''...'2.7' do
it "taints the result if self is tainted" do
- "".taint.reverse.tainted?.should == true
- "m".taint.reverse.tainted?.should == true
+ "".taint.reverse.should.tainted?
+ "m".taint.reverse.should.tainted?
end
end
@@ -32,14 +32,14 @@ describe "String#reverse!" do
"".reverse!.should == ""
end
- it "raises a #{frozen_error_class} on a frozen instance that is modified" do
- -> { "anna".freeze.reverse! }.should raise_error(frozen_error_class)
- -> { "hello".freeze.reverse! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that is modified" do
+ -> { "anna".freeze.reverse! }.should raise_error(FrozenError)
+ -> { "hello".freeze.reverse! }.should raise_error(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do
- -> { "".freeze.reverse! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that would not be modified" do
+ -> { "".freeze.reverse! }.should raise_error(FrozenError)
end
it "reverses a string with multi byte characters" do
diff --git a/spec/ruby/core/string/rindex_spec.rb b/spec/ruby/core/string/rindex_spec.rb
index e021486bc2..7a6af0c9d0 100644
--- a/spec/ruby/core/string/rindex_spec.rb
+++ b/spec/ruby/core/string/rindex_spec.rb
@@ -4,7 +4,7 @@ require_relative 'fixtures/classes'
require_relative 'fixtures/utf-8-encoding'
describe "String#rindex with object" do
- it "raises a TypeError if obj isn't a String, Fixnum or Regexp" do
+ it "raises a TypeError if obj isn't a String, Integer or Regexp" do
not_supported_on :opal do
-> { "hello".rindex(:sym) }.should raise_error(TypeError)
end
diff --git a/spec/ruby/core/string/rjust_spec.rb b/spec/ruby/core/string/rjust_spec.rb
index 9285ecb6a7..f51aacff44 100644
--- a/spec/ruby/core/string/rjust_spec.rb
+++ b/spec/ruby/core/string/rjust_spec.rb
@@ -33,11 +33,11 @@ describe "String#rjust with length, padding" do
ruby_version_is ''...'2.7' do
it "taints result when self or padstr is tainted" do
- "x".taint.rjust(4).tainted?.should == true
- "x".taint.rjust(0).tainted?.should == true
- "".taint.rjust(0).tainted?.should == true
- "x".taint.rjust(4, "*").tainted?.should == true
- "x".rjust(4, "*".taint).tainted?.should == true
+ "x".taint.rjust(4).should.tainted?
+ "x".taint.rjust(0).should.tainted?
+ "".taint.rjust(0).should.tainted?
+ "x".taint.rjust(4, "*").should.tainted?
+ "x".rjust(4, "*".taint).should.tainted?
end
end
@@ -74,13 +74,26 @@ describe "String#rjust with length, padding" do
-> { "hello".rjust(10, '') }.should raise_error(ArgumentError)
end
- it "returns subclass instances when called on subclasses" do
- StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on subclasses" do
+ StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString)
- "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
- "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on subclasses" do
+ StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+
+ "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String)
+ end
end
ruby_version_is ''...'2.7' do
diff --git a/spec/ruby/core/string/rstrip_spec.rb b/spec/ruby/core/string/rstrip_spec.rb
index 9482765e89..57e1867956 100644
--- a/spec/ruby/core/string/rstrip_spec.rb
+++ b/spec/ruby/core/string/rstrip_spec.rb
@@ -16,9 +16,9 @@ describe "String#rstrip" do
ruby_version_is ''...'2.7' do
it "taints the result when self is tainted" do
- "".taint.rstrip.tainted?.should == true
- "ok".taint.rstrip.tainted?.should == true
- "ok ".taint.rstrip.tainted?.should == true
+ "".taint.rstrip.should.tainted?
+ "ok".taint.rstrip.should.tainted?
+ "ok ".taint.rstrip.should.tainted?
end
end
end
@@ -42,13 +42,13 @@ describe "String#rstrip!" do
a.should == "hello"
end
- it "raises a #{frozen_error_class} on a frozen instance that is modified" do
- -> { " hello ".freeze.rstrip! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that is modified" do
+ -> { " hello ".freeze.rstrip! }.should raise_error(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do
- -> { "hello".freeze.rstrip! }.should raise_error(frozen_error_class)
- -> { "".freeze.rstrip! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that would not be modified" do
+ -> { "hello".freeze.rstrip! }.should raise_error(FrozenError)
+ -> { "".freeze.rstrip! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/setbyte_spec.rb b/spec/ruby/core/string/setbyte_spec.rb
index 6912b1b66f..03e5bad88b 100644
--- a/spec/ruby/core/string/setbyte_spec.rb
+++ b/spec/ruby/core/string/setbyte_spec.rb
@@ -75,10 +75,10 @@ describe "String#setbyte" do
str1.should_not == "ledgehog"
end
- it "raises a #{frozen_error_class} if self is frozen" do
+ it "raises a FrozenError if self is frozen" do
str = "cold".freeze
str.frozen?.should be_true
- -> { str.setbyte(3,96) }.should raise_error(frozen_error_class)
+ -> { str.setbyte(3,96) }.should raise_error(FrozenError)
end
it "raises a TypeError unless the second argument is an Integer" do
diff --git a/spec/ruby/core/string/shared/chars.rb b/spec/ruby/core/string/shared/chars.rb
index 9c7a4deb8b..1f045e4530 100644
--- a/spec/ruby/core/string/shared/chars.rb
+++ b/spec/ruby/core/string/shared/chars.rb
@@ -69,11 +69,11 @@ describe :string_chars, shared: true do
str = "hello"
str.send(@method) do |x|
- x.tainted?.should == false
+ x.should_not.tainted?
end
str.dup.taint.send(@method) do |x|
- x.tainted?.should == true
+ x.should.tainted?
end
end
end
diff --git a/spec/ruby/core/string/shared/codepoints.rb b/spec/ruby/core/string/shared/codepoints.rb
index e94a57f48e..0b2e078e0a 100644
--- a/spec/ruby/core/string/shared/codepoints.rb
+++ b/spec/ruby/core/string/shared/codepoints.rb
@@ -26,9 +26,9 @@ describe :string_codepoints, shared: true do
-> { s.send(@method) { } }.should raise_error(ArgumentError)
end
- it "yields codepoints as Fixnums" do
+ it "yields codepoints as Integers" do
"glark\u{20}".send(@method).to_a.each do |codepoint|
- codepoint.should be_an_instance_of(Fixnum)
+ codepoint.should be_an_instance_of(Integer)
end
end
diff --git a/spec/ruby/core/string/shared/concat.rb b/spec/ruby/core/string/shared/concat.rb
index 435158496e..d6ffad7d4d 100644
--- a/spec/ruby/core/string/shared/concat.rb
+++ b/spec/ruby/core/string/shared/concat.rb
@@ -17,12 +17,12 @@ describe :string_concat, shared: true do
-> { 'hello '.send(@method, mock('x')) }.should raise_error(TypeError)
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
a = "hello"
a.freeze
- -> { a.send(@method, "") }.should raise_error(frozen_error_class)
- -> { a.send(@method, "test") }.should raise_error(frozen_error_class)
+ -> { a.send(@method, "") }.should raise_error(FrozenError)
+ -> { a.send(@method, "test") }.should raise_error(FrozenError)
end
it "returns a String when given a subclass instance" do
@@ -41,13 +41,13 @@ describe :string_concat, shared: true do
ruby_version_is ''...'2.7' do
it "taints self if other is tainted" do
- "x".send(@method, "".taint).tainted?.should == true
- "x".send(@method, "y".taint).tainted?.should == true
+ "x".send(@method, "".taint).should.tainted?
+ "x".send(@method, "y".taint).should.tainted?
end
it "untrusts self if other is untrusted" do
- "x".send(@method, "".untrust).untrusted?.should == true
- "x".send(@method, "y".untrust).untrusted?.should == true
+ "x".send(@method, "".untrust).should.untrusted?
+ "x".send(@method, "y".untrust).should.untrusted?
end
end
@@ -89,12 +89,12 @@ describe :string_concat, shared: true do
-> { "".send(@method, x) }.should raise_error(TypeError)
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
a = "hello"
a.freeze
- -> { a.send(@method, 0) }.should raise_error(frozen_error_class)
- -> { a.send(@method, 33) }.should raise_error(frozen_error_class)
+ -> { a.send(@method, 0) }.should raise_error(FrozenError)
+ -> { a.send(@method, 33) }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/string/shared/each_line.rb b/spec/ruby/core/string/shared/each_line.rb
index 843b123f57..f9c910596a 100644
--- a/spec/ruby/core/string/shared/each_line.rb
+++ b/spec/ruby/core/string/shared/each_line.rb
@@ -42,9 +42,9 @@ describe :string_each_line, shared: true do
ruby_version_is ''...'2.7' do
it "taints substrings that are passed to the block if self is tainted" do
- "one\ntwo\r\nthree".taint.send(@method) { |s| s.tainted?.should == true }
+ "one\ntwo\r\nthree".taint.send(@method) { |s| s.should.tainted? }
- "x.y.".send(@method, ".".taint) { |s| s.tainted?.should == false }
+ "x.y.".send(@method, ".".taint) { |s| s.should_not.tainted? }
end
end
@@ -54,28 +54,14 @@ describe :string_each_line, shared: true do
a.should == ["one\ntwo\r\nthree"]
end
- ruby_version_is ''...'2.5' do
- it "yields paragraphs (broken by 2 or more successive newlines) when passed ''" do
- a = []
- "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s }
- a.should == ["hello\nworld\n\n\n", "and\nuniverse\n\n\n\n\n"]
-
- a = []
- "hello\nworld\n\n\nand\nuniverse\n\n\n\n\ndog".send(@method, '') { |s| a << s }
- a.should == ["hello\nworld\n\n\n", "and\nuniverse\n\n\n\n\n", "dog"]
- end
- end
-
- ruby_version_is '2.5' do
- it "yields paragraphs (broken by 2 or more successive newlines) when passed '' and replaces multiple newlines with only two ones" do
- a = []
- "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s }
- a.should == ["hello\nworld\n\n", "and\nuniverse\n\n"]
+ it "yields paragraphs (broken by 2 or more successive newlines) when passed '' and replaces multiple newlines with only two ones" do
+ a = []
+ "hello\nworld\n\n\nand\nuniverse\n\n\n\n\n".send(@method, '') { |s| a << s }
+ a.should == ["hello\nworld\n\n", "and\nuniverse\n\n"]
- a = []
- "hello\nworld\n\n\nand\nuniverse\n\n\n\n\ndog".send(@method, '') { |s| a << s }
- a.should == ["hello\nworld\n\n", "and\nuniverse\n\n", "dog"]
- end
+ a = []
+ "hello\nworld\n\n\nand\nuniverse\n\n\n\n\ndog".send(@method, '') { |s| a << s }
+ a.should == ["hello\nworld\n\n", "and\nuniverse\n\n", "dog"]
end
describe "uses $/" do
@@ -84,7 +70,7 @@ describe :string_each_line, shared: true do
end
after :each do
- $/ = @before_separator
+ suppress_warning {$/ = @before_separator}
end
it "as the separator when none is given" do
@@ -96,10 +82,10 @@ describe :string_each_line, shared: true do
expected = []
str.send(@method, sep) { |x| expected << x }
- $/ = sep
+ suppress_warning {$/ = sep}
actual = []
- str.send(@method) { |x| actual << x }
+ suppress_warning {str.send(@method) { |x| actual << x }}
actual.should == expected
end
@@ -107,10 +93,20 @@ describe :string_each_line, shared: true do
end
end
- it "yields subclass instances for subclasses" do
- a = []
- StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class }
- a.should == [StringSpecs::MyString, StringSpecs::MyString]
+ ruby_version_is ''...'3.0' do
+ it "yields subclass instances for subclasses" do
+ a = []
+ StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class }
+ a.should == [StringSpecs::MyString, StringSpecs::MyString]
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "yields String instances for subclasses" do
+ a = []
+ StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class }
+ a.should == [String, String]
+ end
end
it "returns self" do
diff --git a/spec/ruby/core/string/shared/length.rb b/spec/ruby/core/string/shared/length.rb
index f387fb251c..b9eae5170f 100644
--- a/spec/ruby/core/string/shared/length.rb
+++ b/spec/ruby/core/string/shared/length.rb
@@ -23,4 +23,17 @@ describe :string_length, shared: true do
str.force_encoding('BINARY').send(@method).should == 12
end
+
+ it "returns the correct length after force_encoding(BINARY)" do
+ utf8 = "あ"
+ ascii = "a"
+ concat = utf8 + ascii
+
+ concat.encoding.should == Encoding::UTF_8
+ concat.bytesize.should == 4
+
+ concat.size.should == 2
+ concat.force_encoding(Encoding::ASCII_8BIT)
+ concat.size.should == 4
+ end
end
diff --git a/spec/ruby/core/string/shared/replace.rb b/spec/ruby/core/string/shared/replace.rb
index 620021eb92..8dfac49f02 100644
--- a/spec/ruby/core/string/shared/replace.rb
+++ b/spec/ruby/core/string/shared/replace.rb
@@ -15,28 +15,28 @@ describe :string_replace, shared: true do
a = ""
b = "".taint
a.send(@method, b)
- a.tainted?.should == true
+ a.should.tainted?
end
it "does not untaint self if other is untainted" do
a = "".taint
b = ""
a.send(@method, b)
- a.tainted?.should == true
+ a.should.tainted?
end
it "untrusts self if other is untrusted" do
a = ""
b = "".untrust
a.send(@method, b)
- a.untrusted?.should == true
+ a.should.untrusted?
end
it "does not trust self if other is trusted" do
a = "".untrust
b = ""
a.send(@method, b)
- a.untrusted?.should == true
+ a.should.untrusted?
end
end
@@ -64,14 +64,14 @@ describe :string_replace, shared: true do
-> { "hello".send(@method, mock('x')) }.should raise_error(TypeError)
end
- it "raises a #{frozen_error_class} on a frozen instance that is modified" do
+ it "raises a FrozenError on a frozen instance that is modified" do
a = "hello".freeze
- -> { a.send(@method, "world") }.should raise_error(frozen_error_class)
+ -> { a.send(@method, "world") }.should raise_error(FrozenError)
end
# see [ruby-core:23666]
- it "raises a #{frozen_error_class} on a frozen instance when self-replacing" do
+ it "raises a FrozenError on a frozen instance when self-replacing" do
a = "hello".freeze
- -> { a.send(@method, a) }.should raise_error(frozen_error_class)
+ -> { a.send(@method, a) }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/shared/slice.rb b/spec/ruby/core/string/shared/slice.rb
index b192005369..69997b7c1d 100644
--- a/spec/ruby/core/string/shared/slice.rb
+++ b/spec/ruby/core/string/shared/slice.rb
@@ -85,9 +85,9 @@ describe :string_slice_index_length, shared: true do
str = "hello world"
str.taint
- str.send(@method, 0,0).tainted?.should == true
- str.send(@method, 0,1).tainted?.should == true
- str.send(@method, 2,1).tainted?.should == true
+ str.send(@method, 0,0).should.tainted?
+ str.send(@method, 0,1).should.tainted?
+ str.send(@method, 2,1).should.tainted?
end
end
@@ -121,6 +121,8 @@ describe :string_slice_index_length, shared: true do
"x".send(@method, -2,0).should == nil
"x".send(@method, -2,1).should == nil
+
+ "x".send(@method, fixnum_max, 1).should == nil
end
it "returns nil if the length is negative" do
@@ -161,11 +163,22 @@ describe :string_slice_index_length, shared: true do
-> { "hello".send(@method, 0, bignum_value) }.should raise_error(RangeError)
end
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, 0,0).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, 0,4).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, 1,4).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, 0,0).should be_an_instance_of(StringSpecs::MyString)
+ s.send(@method, 0,4).should be_an_instance_of(StringSpecs::MyString)
+ s.send(@method, 1,4).should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, 0,0).should be_an_instance_of(String)
+ s.send(@method, 0,4).should be_an_instance_of(String)
+ s.send(@method, 1,4).should be_an_instance_of(String)
+ end
end
it "handles repeated application" do
@@ -241,20 +254,31 @@ describe :string_slice_range, shared: true do
str = "hello world"
str.taint
- str.send(@method, 0..0).tainted?.should == true
- str.send(@method, 0...0).tainted?.should == true
- str.send(@method, 0..1).tainted?.should == true
- str.send(@method, 0...1).tainted?.should == true
- str.send(@method, 2..3).tainted?.should == true
- str.send(@method, 2..0).tainted?.should == true
+ str.send(@method, 0..0).should.tainted?
+ str.send(@method, 0...0).should.tainted?
+ str.send(@method, 0..1).should.tainted?
+ str.send(@method, 0...1).should.tainted?
+ str.send(@method, 2..3).should.tainted?
+ str.send(@method, 2..0).should.tainted?
end
end
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, 0...0).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, 0..4).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, 1..4).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, 0...0).should be_an_instance_of(StringSpecs::MyString)
+ s.send(@method, 0..4).should be_an_instance_of(StringSpecs::MyString)
+ s.send(@method, 1..4).should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, 0...0).should be_an_instance_of(String)
+ s.send(@method, 0..4).should be_an_instance_of(String)
+ s.send(@method, 1..4).should be_an_instance_of(String)
+ end
end
it "calls to_int on range arguments" do
@@ -293,6 +317,24 @@ describe :string_slice_range, shared: true do
"hello world".send(@method, 6..5).send(@method, -1..-1).should == nil
"hello world".send(@method, 6..5).send(@method, 1..1).should == nil
end
+
+ it "raises a type error if a range is passed with a length" do
+ ->{ "hello".send(@method, 1..2, 1) }.should raise_error(TypeError)
+ end
+
+ it "raises a RangeError if one of the bound is too big" do
+ -> { "hello".send(@method, bignum_value..(bignum_value + 1)) }.should raise_error(RangeError)
+ -> { "hello".send(@method, 0..bignum_value) }.should raise_error(RangeError)
+ end
+
+ ruby_version_is "2.6" do
+ it "works with endless ranges" do
+ "hello there".send(@method, eval("(2..)")).should == "llo there"
+ "hello there".send(@method, eval("(2...)")).should == "llo there"
+ "hello there".send(@method, eval("(-4..)")).should == "here"
+ "hello there".send(@method, eval("(-4...)")).should == "here"
+ end
+ end
end
describe :string_slice_regexp, shared: true do
@@ -318,7 +360,7 @@ describe :string_slice_regexp, shared: true do
tainted_re = /./
tainted_re.taint
- str.send(@method, tainted_re).tainted?.should == true
+ str.send(@method, tainted_re).should.tainted?
end
end
@@ -328,10 +370,20 @@ describe :string_slice_regexp, shared: true do
end
end
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, //).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, /../).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, //).should be_an_instance_of(StringSpecs::MyString)
+ s.send(@method, /../).should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, //).should be_an_instance_of(String)
+ s.send(@method, /../).should be_an_instance_of(String)
+ end
end
it "sets $~ to MatchData when there is a match and nil when there's none" do
@@ -375,9 +427,9 @@ describe :string_slice_regexp_index, shared: true do
tainted_re = /(.)(.)(.)/
tainted_re.taint
- str.send(@method, tainted_re, 0).tainted?.should == true
- str.send(@method, tainted_re, 1).tainted?.should == true
- str.send(@method, tainted_re, -1).tainted?.should == true
+ str.send(@method, tainted_re, 0).should.tainted?
+ str.send(@method, tainted_re, 1).should.tainted?
+ str.send(@method, tainted_re, -1).should.tainted?
end
end
@@ -416,10 +468,20 @@ describe :string_slice_regexp_index, shared: true do
-> { "hello".send(@method, /(.)(.)(.)/, nil) }.should raise_error(TypeError)
end
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, /(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString)
- s.send(@method, /(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, /(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString)
+ s.send(@method, /(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, /(.)(.)/, 0).should be_an_instance_of(String)
+ s.send(@method, /(.)(.)/, 1).should be_an_instance_of(String)
+ end
end
it "sets $~ to MatchData when there is a match and nil when there's none" do
@@ -473,11 +535,22 @@ describe :string_slice_string, shared: true do
-> { "hello".send(@method, o) }.should raise_error(TypeError)
end
- it "returns a subclass instance when given a subclass instance" do
- s = StringSpecs::MyString.new("el")
- r = "hello".send(@method, s)
- r.should == "el"
- r.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns a subclass instance when given a subclass instance" do
+ s = StringSpecs::MyString.new("el")
+ r = "hello".send(@method, s)
+ r.should == "el"
+ r.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns a String instance when given a subclass instance" do
+ s = StringSpecs::MyString.new("el")
+ r = "hello".send(@method, s)
+ r.should == "el"
+ r.should be_an_instance_of(String)
+ end
end
end
@@ -547,9 +620,18 @@ describe :string_slice_regexp_group, shared: true do
-> { "hello".send(@method, /(?<q>)/, '') }.should raise_error(IndexError)
end
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.send(@method, /(?<q>.)/, 'q').should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, /(?<q>.)/, 'q').should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.send(@method, /(?<q>.)/, 'q').should be_an_instance_of(String)
+ end
end
it "sets $~ to MatchData when there is a match and nil when there's none" do
diff --git a/spec/ruby/core/string/shared/succ.rb b/spec/ruby/core/string/shared/succ.rb
index 80e4659102..25602103b6 100644
--- a/spec/ruby/core/string/shared/succ.rb
+++ b/spec/ruby/core/string/shared/succ.rb
@@ -59,16 +59,26 @@ describe :string_succ, shared: true do
"\xFF\xFF".send(@method).should == "\x01\x00\x00"
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("").send(@method).should be_an_instance_of(String)
+ StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(String)
+ StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(String)
+ end
end
ruby_version_is ''...'2.7' do
it "taints the result if self is tainted" do
["", "a", "z", "Z", "9", "\xFF", "\xFF\xFF"].each do |s|
- s.taint.send(@method).tainted?.should == true
+ s.taint.send(@method).should.tainted?
end
end
end
@@ -83,8 +93,8 @@ describe :string_succ_bang, shared: true do
end
end
- it "raises a #{frozen_error_class} if self is frozen" do
- -> { "".freeze.send(@method) }.should raise_error(frozen_error_class)
- -> { "abcd".freeze.send(@method) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if self is frozen" do
+ -> { "".freeze.send(@method) }.should raise_error(FrozenError)
+ -> { "abcd".freeze.send(@method) }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/shared/to_s.rb b/spec/ruby/core/string/shared/to_s.rb
index 36283be4d0..b8c9b8ab44 100644
--- a/spec/ruby/core/string/shared/to_s.rb
+++ b/spec/ruby/core/string/shared/to_s.rb
@@ -13,8 +13,8 @@ describe :string_to_s, shared: true do
ruby_version_is ''...'2.7' do
it "taints the result when self is tainted" do
- "x".taint.send(@method).tainted?.should == true
- StringSpecs::MyString.new("x").taint.send(@method).tainted?.should == true
+ "x".taint.send(@method).should.tainted?
+ StringSpecs::MyString.new("x").taint.send(@method).should.tainted?
end
end
end
diff --git a/spec/ruby/core/string/shared/to_sym.rb b/spec/ruby/core/string/shared/to_sym.rb
index 1180d64712..416f302aef 100644
--- a/spec/ruby/core/string/shared/to_sym.rb
+++ b/spec/ruby/core/string/shared/to_sym.rb
@@ -55,7 +55,7 @@ describe :string_to_sym, shared: true do
it "raises an EncodingError for UTF-8 String containing invalid bytes" do
invalid_utf8 = "\xC3"
- invalid_utf8.valid_encoding?.should == false
+ invalid_utf8.should_not.valid_encoding?
-> {
invalid_utf8.send(@method)
}.should raise_error(EncodingError, /invalid/)
diff --git a/spec/ruby/core/string/slice_spec.rb b/spec/ruby/core/string/slice_spec.rb
index f9f4938af3..83b475c8b5 100644
--- a/spec/ruby/core/string/slice_spec.rb
+++ b/spec/ruby/core/string/slice_spec.rb
@@ -53,10 +53,10 @@ describe "String#slice! with index" do
a.should == "hello"
end
- it "raises a #{frozen_error_class} if self is frozen" do
- -> { "hello".freeze.slice!(1) }.should raise_error(frozen_error_class)
- -> { "hello".freeze.slice!(10) }.should raise_error(frozen_error_class)
- -> { "".freeze.slice!(0) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if self is frozen" do
+ -> { "hello".freeze.slice!(1) }.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(10) }.should raise_error(FrozenError)
+ -> { "".freeze.slice!(0) }.should raise_error(FrozenError)
end
it "calls to_int on index" do
@@ -99,8 +99,8 @@ describe "String#slice! with index, length" do
str = "hello world"
str.taint
- str.slice!(0, 0).tainted?.should == true
- str.slice!(2, 1).tainted?.should == true
+ str.slice!(0, 0).should.tainted?
+ str.slice!(2, 1).should.tainted?
end
end
@@ -119,14 +119,14 @@ describe "String#slice! with index, length" do
a.should == "hello"
end
- it "raises a #{frozen_error_class} if self is frozen" do
- -> { "hello".freeze.slice!(1, 2) }.should raise_error(frozen_error_class)
- -> { "hello".freeze.slice!(10, 3) }.should raise_error(frozen_error_class)
- -> { "hello".freeze.slice!(-10, 3)}.should raise_error(frozen_error_class)
- -> { "hello".freeze.slice!(4, -3) }.should raise_error(frozen_error_class)
- -> { "hello".freeze.slice!(10, 3) }.should raise_error(frozen_error_class)
- -> { "hello".freeze.slice!(-10, 3)}.should raise_error(frozen_error_class)
- -> { "hello".freeze.slice!(4, -3) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if self is frozen" do
+ -> { "hello".freeze.slice!(1, 2) }.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(10, 3) }.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(-10, 3)}.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(4, -3) }.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(10, 3) }.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(-10, 3)}.should raise_error(FrozenError)
+ -> { "hello".freeze.slice!(4, -3) }.should raise_error(FrozenError)
end
it "calls to_int on idx and length" do
@@ -142,12 +142,21 @@ describe "String#slice! with index, length" do
"hello".slice!(obj, obj).should == "ll"
end
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(0, 0).should be_an_instance_of(StringSpecs::MyString)
- s.slice!(0, 4).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(0, 0).should be_an_instance_of(StringSpecs::MyString)
+ s.slice!(0, 4).should be_an_instance_of(StringSpecs::MyString)
+ end
end
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(0, 0).should be_an_instance_of(String)
+ s.slice!(0, 4).should be_an_instance_of(String)
+ end
+ end
it "returns the substring given by the character offsets" do
"hellö there".slice!(1,0).should == ""
@@ -191,15 +200,25 @@ describe "String#slice! Range" do
str = "hello world"
str.taint
- str.slice!(0..0).tainted?.should == true
- str.slice!(2..3).tainted?.should == true
+ str.slice!(0..0).should.tainted?
+ str.slice!(2..3).should.tainted?
+ end
+ end
+
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(0...0).should be_an_instance_of(StringSpecs::MyString)
+ s.slice!(0..4).should be_an_instance_of(StringSpecs::MyString)
end
end
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(0...0).should be_an_instance_of(StringSpecs::MyString)
- s.slice!(0..4).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(0...0).should be_an_instance_of(String)
+ s.slice!(0..4).should be_an_instance_of(String)
+ end
end
it "calls to_int on range arguments" do
@@ -248,13 +267,13 @@ describe "String#slice! Range" do
end
- it "raises a #{frozen_error_class} on a frozen instance that is modified" do
- -> { "hello".freeze.slice!(1..3) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that is modified" do
+ -> { "hello".freeze.slice!(1..3) }.should raise_error(FrozenError)
end
# see redmine #1551
- it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do
- -> { "hello".freeze.slice!(10..20)}.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that would not be modified" do
+ -> { "hello".freeze.slice!(10..20)}.should raise_error(FrozenError)
end
end
@@ -288,21 +307,31 @@ describe "String#slice! with Regexp" do
tainted_re = /./
tainted_re.taint
- str.slice!(tainted_re).tainted?.should == true
+ str.slice!(tainted_re).should.tainted?
end
end
it "doesn't taint self when regexp is tainted" do
s = "hello"
s.slice!(/./.taint)
- s.tainted?.should == false
+ s.should_not.tainted?
end
end
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(//).should be_an_instance_of(StringSpecs::MyString)
- s.slice!(/../).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(//).should be_an_instance_of(StringSpecs::MyString)
+ s.slice!(/../).should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(//).should be_an_instance_of(String)
+ s.slice!(/../).should be_an_instance_of(String)
+ end
end
it "returns the matching portion of self with a multi byte character" do
@@ -318,12 +347,12 @@ describe "String#slice! with Regexp" do
$~.should == nil
end
- it "raises a #{frozen_error_class} on a frozen instance that is modified" do
- -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that is modified" do
+ -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do
- -> { "this is a string".freeze.slice!(/zzz/) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that would not be modified" do
+ -> { "this is a string".freeze.slice!(/zzz/) }.should raise_error(FrozenError)
end
end
@@ -349,14 +378,14 @@ describe "String#slice! with Regexp, index" do
tainted_re = /(.)(.)(.)/
tainted_re.taint
- str.slice!(tainted_re, 1).tainted?.should == true
+ str.slice!(tainted_re, 1).should.tainted?
end
end
it "doesn't taint self when regexp is tainted" do
s = "hello"
s.slice!(/(.)(.)/.taint, 1)
- s.tainted?.should == false
+ s.should_not.tainted?
end
end
@@ -383,10 +412,20 @@ describe "String#slice! with Regexp, index" do
"har".slice!(/(.)(.)(.)/, obj).should == "a"
end
- it "returns subclass instances" do
- s = StringSpecs::MyString.new("hello")
- s.slice!(/(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString)
- s.slice!(/(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(/(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString)
+ s.slice!(/(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ s = StringSpecs::MyString.new("hello")
+ s.slice!(/(.)(.)/, 0).should be_an_instance_of(String)
+ s.slice!(/(.)(.)/, 1).should be_an_instance_of(String)
+ end
end
it "returns the encoding aware capture for the given index" do
@@ -410,10 +449,10 @@ describe "String#slice! with Regexp, index" do
$~.should == nil
end
- it "raises a #{frozen_error_class} if self is frozen" do
- -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(frozen_error_class)
- -> { "this is a string".freeze.slice!(/zzz/, 0)}.should raise_error(frozen_error_class)
- -> { "this is a string".freeze.slice!(/(.)/, 2)}.should raise_error(frozen_error_class)
+ it "raises a FrozenError if self is frozen" do
+ -> { "this is a string".freeze.slice!(/s.*t/) }.should raise_error(FrozenError)
+ -> { "this is a string".freeze.slice!(/zzz/, 0)}.should raise_error(FrozenError)
+ -> { "this is a string".freeze.slice!(/(.)/, 2)}.should raise_error(FrozenError)
end
end
@@ -461,16 +500,27 @@ describe "String#slice! with String" do
-> { "hello".slice!(o) }.should raise_error(TypeError)
end
- it "returns a subclass instance when given a subclass instance" do
- s = StringSpecs::MyString.new("el")
- r = "hello".slice!(s)
- r.should == "el"
- r.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns a subclass instance when given a subclass instance" do
+ s = StringSpecs::MyString.new("el")
+ r = "hello".slice!(s)
+ r.should == "el"
+ r.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns a subclass instance when given a subclass instance" do
+ s = StringSpecs::MyString.new("el")
+ r = "hello".slice!(s)
+ r.should == "el"
+ r.should be_an_instance_of(String)
+ end
end
- it "raises a #{frozen_error_class} if self is frozen" do
- -> { "hello hello".freeze.slice!('llo') }.should raise_error(frozen_error_class)
- -> { "this is a string".freeze.slice!('zzz')}.should raise_error(frozen_error_class)
- -> { "this is a string".freeze.slice!('zzz')}.should raise_error(frozen_error_class)
+ it "raises a FrozenError if self is frozen" do
+ -> { "hello hello".freeze.slice!('llo') }.should raise_error(FrozenError)
+ -> { "this is a string".freeze.slice!('zzz')}.should raise_error(FrozenError)
+ -> { "this is a string".freeze.slice!('zzz')}.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb
index cfb030ad8d..c5441e3a49 100644
--- a/spec/ruby/core/string/split_spec.rb
+++ b/spec/ruby/core/string/split_spec.rb
@@ -84,6 +84,24 @@ describe "String#split with String" do
$; = old_fs
end
end
+
+ ruby_version_is "2.7" do
+ context "when $; is not nil" do
+ before do
+ suppress_warning do
+ @old_value, $; = $;, 'foobar'
+ end
+ end
+
+ after do
+ $; = @old_value
+ end
+
+ it "warns" do
+ -> { "".split }.should complain(/warning: \$; is set to non-nil value/)
+ end
+ end
+ end
end
it "ignores leading and continuous whitespace when string is a single space" do
@@ -141,28 +159,48 @@ describe "String#split with String" do
"foo".split("bar", 3).should == ["foo"]
end
- it "returns subclass instances based on self" do
- ["", "x.y.z.", " x y "].each do |str|
- ["", ".", " "].each do |pat|
- [-1, 0, 1, 2].each do |limit|
- StringSpecs::MyString.new(str).split(pat, limit).each do |x|
- x.should be_an_instance_of(StringSpecs::MyString)
- end
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances based on self" do
+ ["", "x.y.z.", " x y "].each do |str|
+ ["", ".", " "].each do |pat|
+ [-1, 0, 1, 2].each do |limit|
+ StringSpecs::MyString.new(str).split(pat, limit).each do |x|
+ x.should be_an_instance_of(StringSpecs::MyString)
+ end
- str.split(StringSpecs::MyString.new(pat), limit).each do |x|
- x.should be_an_instance_of(String)
+ str.split(StringSpecs::MyString.new(pat), limit).each do |x|
+ x.should be_an_instance_of(String)
+ end
end
end
end
end
+
+ it "does not call constructor on created subclass instances" do
+ # can't call should_not_receive on an object that doesn't yet exist
+ # so failure here is signalled by exception, not expectation failure
+
+ s = StringSpecs::StringWithRaisingConstructor.new('silly:string')
+ s.split(':').first.should == 'silly'
+ end
end
- it "does not call constructor on created subclass instances" do
- # can't call should_not_receive on an object that doesn't yet exist
- # so failure here is signalled by exception, not expectation failure
+ ruby_version_is '3.0' do
+ it "returns String instances based on self" do
+ ["", "x.y.z.", " x y "].each do |str|
+ ["", ".", " "].each do |pat|
+ [-1, 0, 1, 2].each do |limit|
+ StringSpecs::MyString.new(str).split(pat, limit).each do |x|
+ x.should be_an_instance_of(String)
+ end
- s = StringSpecs::StringWithRaisingConstructor.new('silly:string')
- s.split(':').first.should == 'silly'
+ str.split(StringSpecs::MyString.new(pat), limit).each do |x|
+ x.should be_an_instance_of(String)
+ end
+ end
+ end
+ end
+ end
end
ruby_version_is ''...'2.7' do
@@ -171,11 +209,11 @@ describe "String#split with String" do
["", ".", " "].each do |pat|
[-1, 0, 1, 2].each do |limit|
str.dup.taint.split(pat).each do |x|
- x.tainted?.should == true
+ x.should.tainted?
end
str.split(pat.dup.taint).each do |x|
- x.tainted?.should == false
+ x.should_not.tainted?
end
end
end
@@ -337,24 +375,40 @@ describe "String#split with Regexp" do
"foo".split(/bar/, 3).should == ["foo"]
end
- it "returns subclass instances based on self" do
- ["", "x:y:z:", " x y "].each do |str|
- [//, /:/, /\s+/].each do |pat|
- [-1, 0, 1, 2].each do |limit|
- StringSpecs::MyString.new(str).split(pat, limit).each do |x|
- x.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances based on self" do
+ ["", "x:y:z:", " x y "].each do |str|
+ [//, /:/, /\s+/].each do |pat|
+ [-1, 0, 1, 2].each do |limit|
+ StringSpecs::MyString.new(str).split(pat, limit).each do |x|
+ x.should be_an_instance_of(StringSpecs::MyString)
+ end
end
end
end
end
- end
- it "does not call constructor on created subclass instances" do
- # can't call should_not_receive on an object that doesn't yet exist
- # so failure here is signalled by exception, not expectation failure
+ it "does not call constructor on created subclass instances" do
+ # can't call should_not_receive on an object that doesn't yet exist
+ # so failure here is signalled by exception, not expectation failure
+
+ s = StringSpecs::StringWithRaisingConstructor.new('silly:string')
+ s.split(/:/).first.should == 'silly'
+ end
+ end
- s = StringSpecs::StringWithRaisingConstructor.new('silly:string')
- s.split(/:/).first.should == 'silly'
+ ruby_version_is '3.0' do
+ it "returns String instances based on self" do
+ ["", "x:y:z:", " x y "].each do |str|
+ [//, /:/, /\s+/].each do |pat|
+ [-1, 0, 1, 2].each do |limit|
+ StringSpecs::MyString.new(str).split(pat, limit).each do |x|
+ x.should be_an_instance_of(String)
+ end
+ end
+ end
+ end
+ end
end
ruby_version_is ''...'2.7' do
@@ -408,25 +462,99 @@ describe "String#split with Regexp" do
end
ruby_version_is "2.6" do
- it "yields each split substrings if a block is given" do
- a = []
- returned_object = "chunky bacon".split(" ") { |str| a << str.capitalize }
+ context "when a block is given" do
+ it "yields each split substring with default pattern" do
+ a = []
+ returned_object = "chunky bacon".split { |str| a << str.capitalize }
+
+ returned_object.should == "chunky bacon"
+ a.should == ["Chunky", "Bacon"]
+ end
+
+ it "yields the string when limit is 1" do
+ a = []
+ returned_object = "chunky bacon".split("", 1) { |str| a << str.capitalize }
+
+ returned_object.should == "chunky bacon"
+ a.should == ["Chunky bacon"]
+ end
+
+ it "yields each split letter" do
+ a = []
+ returned_object = "chunky".split("", 0) { |str| a << str.capitalize }
+
+ returned_object.should == "chunky"
+ a.should == %w(C H U N K Y)
+ end
+
+ it "yields each split substring with a pattern" do
+ a = []
+ returned_object = "chunky-bacon".split("-", 0) { |str| a << str.capitalize }
+
+ returned_object.should == "chunky-bacon"
+ a.should == ["Chunky", "Bacon"]
+ end
+
+ it "yields each split substring with empty regexp pattern" do
+ a = []
+ returned_object = "chunky".split(//) { |str| a << str.capitalize }
- returned_object.should == "chunky bacon"
- a.should == ["Chunky", "Bacon"]
+ returned_object.should == "chunky"
+ a.should == %w(C H U N K Y)
+ end
+
+ it "yields each split substring with empty regexp pattern and limit" do
+ a = []
+ returned_object = "chunky".split(//, 3) { |str| a << str.capitalize }
+
+ returned_object.should == "chunky"
+ a.should == %w(C H Unky)
+ end
+
+ it "yields each split substring with a regexp pattern" do
+ a = []
+ returned_object = "chunky:bacon".split(/:/) { |str| a << str.capitalize }
+
+ returned_object.should == "chunky:bacon"
+ a.should == ["Chunky", "Bacon"]
+ end
+
+ it "returns a string as is (and doesn't call block) if it is empty" do
+ a = []
+ returned_object = "".split { |str| a << str.capitalize }
+
+ returned_object.should == ""
+ a.should == []
+ end
end
describe "for a String subclass" do
- it "yields instances of the same subclass" do
- a = []
- StringSpecs::MyString.new("a|b").split("|") { |str| a << str }
- first, last = a
+ ruby_version_is ''...'3.0' do
+ it "yields instances of the same subclass" do
+ a = []
+ StringSpecs::MyString.new("a|b").split("|") { |str| a << str }
+ first, last = a
+
+ first.should be_an_instance_of(StringSpecs::MyString)
+ first.should == "a"
- first.should be_an_instance_of(StringSpecs::MyString)
- first.should == "a"
+ last.should be_an_instance_of(StringSpecs::MyString)
+ last.should == "b"
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "yields instances of String" do
+ a = []
+ StringSpecs::MyString.new("a|b").split("|") { |str| a << str }
+ first, last = a
- last.should be_an_instance_of(StringSpecs::MyString)
- last.should == "b"
+ first.should be_an_instance_of(String)
+ first.should == "a"
+
+ last.should be_an_instance_of(String)
+ last.should == "b"
+ end
end
end
end
diff --git a/spec/ruby/core/string/squeeze_spec.rb b/spec/ruby/core/string/squeeze_spec.rb
index 2e96684b9d..6f75402c9c 100644
--- a/spec/ruby/core/string/squeeze_spec.rb
+++ b/spec/ruby/core/string/squeeze_spec.rb
@@ -56,11 +56,11 @@ describe "String#squeeze" do
ruby_version_is ''...'2.7' do
it "taints the result when self is tainted" do
- "hello".taint.squeeze("e").tainted?.should == true
- "hello".taint.squeeze("a-z").tainted?.should == true
+ "hello".taint.squeeze("e").should.tainted?
+ "hello".taint.squeeze("a-z").should.tainted?
- "hello".squeeze("e".taint).tainted?.should == false
- "hello".squeeze("l".taint).tainted?.should == false
+ "hello".squeeze("e".taint).should_not.tainted?
+ "hello".squeeze("l".taint).should_not.tainted?
end
end
@@ -80,8 +80,16 @@ describe "String#squeeze" do
-> { "hello world".squeeze(mock('x')) }.should raise_error(TypeError)
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(String)
+ end
end
end
@@ -105,11 +113,11 @@ describe "String#squeeze!" do
-> { s.squeeze!("^e-b") }.should raise_error(ArgumentError)
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
a = "yellow moon"
a.freeze
- -> { a.squeeze!("") }.should raise_error(frozen_error_class)
- -> { a.squeeze! }.should raise_error(frozen_error_class)
+ -> { a.squeeze!("") }.should raise_error(FrozenError)
+ -> { a.squeeze! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/start_with_spec.rb b/spec/ruby/core/string/start_with_spec.rb
index 1000db180c..aaed197ff3 100644
--- a/spec/ruby/core/string/start_with_spec.rb
+++ b/spec/ruby/core/string/start_with_spec.rb
@@ -1,76 +1,8 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative '../../shared/string/start_with'
describe "String#start_with?" do
- it "returns true only if beginning match" do
- s = "hello"
- s.should.start_with?('h')
- s.should.start_with?('hel')
- s.should_not.start_with?('el')
- end
-
- it "returns true only if any beginning match" do
- "hello".should.start_with?('x', 'y', 'he', 'z')
- end
-
- it "returns true if the search string is empty" do
- "hello".should.start_with?("")
- "".should.start_with?("")
- end
-
- it "converts its argument using :to_str" do
- s = "hello"
- find = mock('h')
- find.should_receive(:to_str).and_return("h")
- s.should.start_with?(find)
- end
-
- it "ignores arguments not convertible to string" do
- "hello".should_not.start_with?()
- -> { "hello".start_with?(1) }.should raise_error(TypeError)
- -> { "hello".start_with?(["h"]) }.should raise_error(TypeError)
- -> { "hello".start_with?(1, nil, "h") }.should raise_error(TypeError)
- end
-
- it "uses only the needed arguments" do
- find = mock('h')
- find.should_not_receive(:to_str)
- "hello".should.start_with?("h",find)
- end
-
- it "works for multibyte strings" do
- "céréale".should.start_with?("cér")
- end
-
- ruby_version_is "2.5" do
- it "supports regexps" do
- regexp = /[h1]/
- "hello".should.start_with?(regexp)
- "1337".should.start_with?(regexp)
- "foxes are 1337".should_not.start_with?(regexp)
- "chunky\n12bacon".should_not.start_with?(/12/)
- end
-
- it "supports regexps with ^ and $ modifiers" do
- regexp1 = /^\d{2}/
- regexp2 = /\d{2}$/
- "12test".should.start_with?(regexp1)
- "test12".should_not.start_with?(regexp1)
- "12test".should_not.start_with?(regexp2)
- "test12".should_not.start_with?(regexp2)
- end
-
- it "sets Regexp.last_match if it returns true" do
- regexp = /test-(\d+)/
- "test-1337".start_with?(regexp).should be_true
- Regexp.last_match.should_not be_nil
- Regexp.last_match[1].should == "1337"
- $1.should == "1337"
-
- "test-asdf".start_with?(regexp).should be_false
- Regexp.last_match.should be_nil
- $1.should be_nil
- end
- end
+ it_behaves_like :start_with, :to_s
end
diff --git a/spec/ruby/core/string/strip_spec.rb b/spec/ruby/core/string/strip_spec.rb
index 728b3104fa..463a9fedf3 100644
--- a/spec/ruby/core/string/strip_spec.rb
+++ b/spec/ruby/core/string/strip_spec.rb
@@ -6,18 +6,19 @@ describe "String#strip" do
" hello ".strip.should == "hello"
" hello world ".strip.should == "hello world"
"\tgoodbye\r\v\n".strip.should == "goodbye"
- "\x00 goodbye \x00".strip.should == "\x00 goodbye"
end
- it "returns a copy of self with trailing NULL bytes and whitespace" do
- " \x00 goodbye \x00 ".strip.should == "\x00 goodbye"
+ ruby_version_is '3.1' do
+ it "returns a copy of self without leading and trailing NULL bytes and whitespace" do
+ " \x00 goodbye \x00 ".strip.should == "goodbye"
+ end
end
ruby_version_is ''...'2.7' do
it "taints the result when self is tainted" do
- "".taint.strip.tainted?.should == true
- "ok".taint.strip.tainted?.should == true
- " ok ".taint.strip.tainted?.should == true
+ "".taint.strip.should.tainted?
+ "ok".taint.strip.should.tainted?
+ " ok ".taint.strip.should.tainted?
end
end
end
@@ -31,11 +32,6 @@ describe "String#strip!" do
a = "\tgoodbye\r\v\n"
a.strip!
a.should == "goodbye"
-
- a = "\000 goodbye \000"
- a.strip!
- a.should == "\000 goodbye"
-
end
it "returns nil if no modifications where made" do
@@ -44,19 +40,21 @@ describe "String#strip!" do
a.should == "hello"
end
- it "modifies self removing trailing NULL bytes and whitespace" do
- a = " \x00 goodbye \x00 "
- a.strip!
- a.should == "\x00 goodbye"
+ ruby_version_is '3.1' do
+ it "removes leading and trailing NULL bytes and whitespace" do
+ a = "\000 goodbye \000"
+ a.strip!
+ a.should == "goodbye"
+ end
end
- it "raises a #{frozen_error_class} on a frozen instance that is modified" do
- -> { " hello ".freeze.strip! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that is modified" do
+ -> { " hello ".freeze.strip! }.should raise_error(FrozenError)
end
# see #1552
- it "raises a #{frozen_error_class} on a frozen instance that would not be modified" do
- -> {"hello".freeze.strip! }.should raise_error(frozen_error_class)
- -> {"".freeze.strip! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError on a frozen instance that would not be modified" do
+ -> {"hello".freeze.strip! }.should raise_error(FrozenError)
+ -> {"".freeze.strip! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/sub_spec.rb b/spec/ruby/core/string/sub_spec.rb
index 2a859c2fc7..5ae9a4bbf3 100644
--- a/spec/ruby/core/string/sub_spec.rb
+++ b/spec/ruby/core/string/sub_spec.rb
@@ -148,14 +148,14 @@ describe "String#sub with pattern, replacement" do
hello_t.taint; a_t.taint; empty_t.taint
- hello_t.sub(/./, a).tainted?.should == true
- hello_t.sub(/./, empty).tainted?.should == true
+ hello_t.sub(/./, a).should.tainted?
+ hello_t.sub(/./, empty).should.tainted?
- hello.sub(/./, a_t).tainted?.should == true
- hello.sub(/./, empty_t).tainted?.should == true
- hello.sub(//, empty_t).tainted?.should == true
+ hello.sub(/./, a_t).should.tainted?
+ hello.sub(/./, empty_t).should.tainted?
+ hello.sub(//, empty_t).should.tainted?
- hello.sub(//.taint, "foo").tainted?.should == false
+ hello.sub(//.taint, "foo").should_not.tainted?
end
end
@@ -192,11 +192,22 @@ describe "String#sub with pattern, replacement" do
-> { "hello".sub(/[aeiou]/, 99) }.should raise_error(TypeError)
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(String)
+ StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(String)
+ StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(String)
+ end
end
it "sets $~ to MatchData of match and nil when there's none" do
@@ -298,14 +309,14 @@ describe "String#sub with pattern and block" do
hello_t.taint; a_t.taint; empty_t.taint
- hello_t.sub(/./) { a }.tainted?.should == true
- hello_t.sub(/./) { empty }.tainted?.should == true
+ hello_t.sub(/./) { a }.should.tainted?
+ hello_t.sub(/./) { empty }.should.tainted?
- hello.sub(/./) { a_t }.tainted?.should == true
- hello.sub(/./) { empty_t }.tainted?.should == true
- hello.sub(//) { empty_t }.tainted?.should == true
+ hello.sub(/./) { a_t }.should.tainted?
+ hello.sub(/./) { empty_t }.should.tainted?
+ hello.sub(//) { empty_t }.should.tainted?
- hello.sub(//.taint) { "foo" }.tainted?.should == false
+ hello.sub(//.taint) { "foo" }.should_not.tainted?
end
end
end
@@ -320,8 +331,8 @@ describe "String#sub! with pattern, replacement" do
ruby_version_is ''...'2.7' do
it "taints self if replacement is tainted" do
a = "hello"
- a.sub!(/./.taint, "foo").tainted?.should == false
- a.sub!(/./, "foo".taint).tainted?.should == true
+ a.sub!(/./.taint, "foo").should_not.tainted?
+ a.sub!(/./, "foo".taint).should.tainted?
end
end
@@ -332,13 +343,13 @@ describe "String#sub! with pattern, replacement" do
a.should == "hello"
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
s = "hello"
s.freeze
- -> { s.sub!(/ROAR/, "x") }.should raise_error(frozen_error_class)
- -> { s.sub!(/e/, "e") }.should raise_error(frozen_error_class)
- -> { s.sub!(/[aeiou]/, '*') }.should raise_error(frozen_error_class)
+ -> { s.sub!(/ROAR/, "x") }.should raise_error(FrozenError)
+ -> { s.sub!(/e/, "e") }.should raise_error(FrozenError)
+ -> { s.sub!(/[aeiou]/, '*') }.should raise_error(FrozenError)
end
end
@@ -370,8 +381,8 @@ describe "String#sub! with pattern and block" do
ruby_version_is ''...'2.7' do
it "taints self if block's result is tainted" do
a = "hello"
- a.sub!(/./.taint) { "foo" }.tainted?.should == false
- a.sub!(/./) { "foo".taint }.tainted?.should == true
+ a.sub!(/./.taint) { "foo" }.should_not.tainted?
+ a.sub!(/./) { "foo".taint }.should.tainted?
end
end
@@ -387,13 +398,13 @@ describe "String#sub! with pattern and block" do
-> { str.sub!(//) { str << 'x' } }.should raise_error(RuntimeError)
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
s = "hello"
s.freeze
- -> { s.sub!(/ROAR/) { "x" } }.should raise_error(frozen_error_class)
- -> { s.sub!(/e/) { "e" } }.should raise_error(frozen_error_class)
- -> { s.sub!(/[aeiou]/) { '*' } }.should raise_error(frozen_error_class)
+ -> { s.sub!(/ROAR/) { "x" } }.should raise_error(FrozenError)
+ -> { s.sub!(/e/) { "e" } }.should raise_error(FrozenError)
+ -> { s.sub!(/[aeiou]/) { '*' } }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/swapcase_spec.rb b/spec/ruby/core/string/swapcase_spec.rb
index c1a1608a81..32b358607e 100644
--- a/spec/ruby/core/string/swapcase_spec.rb
+++ b/spec/ruby/core/string/swapcase_spec.rb
@@ -11,8 +11,8 @@ describe "String#swapcase" do
ruby_version_is ''...'2.7' do
it "taints resulting string when self is tainted" do
- "".taint.swapcase.tainted?.should == true
- "hello".taint.swapcase.tainted?.should == true
+ "".taint.swapcase.should.tainted?
+ "hello".taint.swapcase.should.tainted?
end
end
@@ -73,9 +73,18 @@ describe "String#swapcase" do
-> { "abc".swapcase(:invalid_option) }.should raise_error(ArgumentError)
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("").swapcase.should be_an_instance_of(StringSpecs::MyString)
- StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("").swapcase.should be_an_instance_of(StringSpecs::MyString)
+ StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("").swapcase.should be_an_instance_of(String)
+ StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(String)
+ end
end
end
@@ -86,6 +95,12 @@ describe "String#swapcase!" do
a.should == "CyBeR_pUnK11"
end
+ it "modifies self in place for non-ascii-compatible encodings" do
+ a = "cYbEr_PuNk11".encode("utf-16le")
+ a.swapcase!
+ a.should == "CyBeR_pUnK11".encode("utf-16le")
+ end
+
describe "full Unicode case mapping" do
it "modifies self in place for all of Unicode with no option" do
a = "äÖü"
@@ -93,6 +108,12 @@ describe "String#swapcase!" do
a.should == "ÄöÜ"
end
+ it "works for non-ascii-compatible encodings" do
+ a = "äÖü".encode("utf-16le")
+ a.swapcase!
+ a.should == "ÄöÜ".encode("utf-16le")
+ end
+
it "updates string metadata" do
swapcased = "Aßet"
swapcased.swapcase!
@@ -110,6 +131,12 @@ describe "String#swapcase!" do
a.swapcase!(:ascii)
a.should == "AßET"
end
+
+ it "works for non-ascii-compatible encodings" do
+ a = "aBc".encode("utf-16le")
+ a.swapcase!(:ascii)
+ a.should == "AbC".encode("utf-16le")
+ end
end
describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do
@@ -164,10 +191,10 @@ describe "String#swapcase!" do
"".swapcase!.should == nil
end
- it "raises a #{frozen_error_class} when self is frozen" do
+ it "raises a FrozenError when self is frozen" do
["", "hello"].each do |a|
a.freeze
- -> { a.swapcase! }.should raise_error(frozen_error_class)
+ -> { a.swapcase! }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/string/to_i_spec.rb b/spec/ruby/core/string/to_i_spec.rb
index a37be47778..e4fa89aab3 100644
--- a/spec/ruby/core/string/to_i_spec.rb
+++ b/spec/ruby/core/string/to_i_spec.rb
@@ -131,29 +131,29 @@ describe "String#to_i" do
-> { "".to_i(37) }.should raise_error(ArgumentError)
end
- it "returns a Fixnum for long strings with trailing spaces" do
+ it "returns an Integer for long strings with trailing spaces" do
"0 ".to_i.should == 0
- "0 ".to_i.should be_an_instance_of(Fixnum)
+ "0 ".to_i.should be_an_instance_of(Integer)
"10 ".to_i.should == 10
- "10 ".to_i.should be_an_instance_of(Fixnum)
+ "10 ".to_i.should be_an_instance_of(Integer)
"-10 ".to_i.should == -10
- "-10 ".to_i.should be_an_instance_of(Fixnum)
+ "-10 ".to_i.should be_an_instance_of(Integer)
end
- it "returns a Fixnum for long strings with leading spaces" do
+ it "returns an Integer for long strings with leading spaces" do
" 0".to_i.should == 0
- " 0".to_i.should be_an_instance_of(Fixnum)
+ " 0".to_i.should be_an_instance_of(Integer)
" 10".to_i.should == 10
- " 10".to_i.should be_an_instance_of(Fixnum)
+ " 10".to_i.should be_an_instance_of(Integer)
" -10".to_i.should == -10
- " -10".to_i.should be_an_instance_of(Fixnum)
+ " -10".to_i.should be_an_instance_of(Integer)
end
- it "returns the correct Bignum for long strings" do
+ it "returns the correct Integer for long strings" do
"245789127594125924165923648312749312749327482".to_i.should == 245789127594125924165923648312749312749327482
"-245789127594125924165923648312749312749327482".to_i.should == -245789127594125924165923648312749312749327482
end
diff --git a/spec/ruby/core/string/tr_s_spec.rb b/spec/ruby/core/string/tr_s_spec.rb
index a05e421e99..c6ad12139e 100644
--- a/spec/ruby/core/string/tr_s_spec.rb
+++ b/spec/ruby/core/string/tr_s_spec.rb
@@ -45,8 +45,16 @@ describe "String#tr_s" do
"bla".tr_s(from_str, to_str).should == "BlA"
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(String)
+ end
end
ruby_version_is ''...'2.7' do
@@ -54,10 +62,10 @@ describe "String#tr_s" do
["h", "hello"].each do |str|
tainted_str = str.dup.taint
- tainted_str.tr_s("e", "a").tainted?.should == true
+ tainted_str.tr_s("e", "a").should.tainted?
- str.tr_s("e".taint, "a").tainted?.should == false
- str.tr_s("e", "a".taint).tainted?.should == false
+ str.tr_s("e".taint, "a").should_not.tainted?
+ str.tr_s("e", "a".taint).should_not.tainted?
end
end
end
@@ -127,10 +135,10 @@ describe "String#tr_s!" do
s.should == "hello"
end
- it "raises a #{frozen_error_class} if self is frozen" do
+ it "raises a FrozenError if self is frozen" do
s = "hello".freeze
- -> { s.tr_s!("el", "ar") }.should raise_error(frozen_error_class)
- -> { s.tr_s!("l", "r") }.should raise_error(frozen_error_class)
- -> { s.tr_s!("", "") }.should raise_error(frozen_error_class)
+ -> { s.tr_s!("el", "ar") }.should raise_error(FrozenError)
+ -> { s.tr_s!("l", "r") }.should raise_error(FrozenError)
+ -> { s.tr_s!("", "") }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/tr_spec.rb b/spec/ruby/core/string/tr_spec.rb
index ae826fd79b..06be1e6641 100644
--- a/spec/ruby/core/string/tr_spec.rb
+++ b/spec/ruby/core/string/tr_spec.rb
@@ -57,8 +57,16 @@ describe "String#tr" do
"bla".tr(from_str, to_str).should == "BlA"
end
- it "returns subclass instances when called on a subclass" do
- StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances when called on a subclass" do
+ StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns Stringinstances when called on a subclass" do
+ StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(String)
+ end
end
ruby_version_is ''...'2.7' do
@@ -66,10 +74,10 @@ describe "String#tr" do
["h", "hello"].each do |str|
tainted_str = str.dup.taint
- tainted_str.tr("e", "a").tainted?.should == true
+ tainted_str.tr("e", "a").should.tainted?
- str.tr("e".taint, "a").tainted?.should == false
- str.tr("e", "a".taint).tainted?.should == false
+ str.tr("e".taint, "a").should_not.tainted?
+ str.tr("e", "a".taint).should_not.tainted?
end
end
end
@@ -122,10 +130,10 @@ describe "String#tr!" do
s.should == "hello"
end
- it "raises a #{frozen_error_class} if self is frozen" do
+ it "raises a FrozenError if self is frozen" do
s = "abcdefghijklmnopqR".freeze
- -> { s.tr!("cdefg", "12") }.should raise_error(frozen_error_class)
- -> { s.tr!("R", "S") }.should raise_error(frozen_error_class)
- -> { s.tr!("", "") }.should raise_error(frozen_error_class)
+ -> { s.tr!("cdefg", "12") }.should raise_error(FrozenError)
+ -> { s.tr!("R", "S") }.should raise_error(FrozenError)
+ -> { s.tr!("", "") }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/uminus_spec.rb b/spec/ruby/core/string/uminus_spec.rb
index dace04846c..3a81b64126 100644
--- a/spec/ruby/core/string/uminus_spec.rb
+++ b/spec/ruby/core/string/uminus_spec.rb
@@ -6,34 +6,32 @@ describe 'String#-@' do
output = -input
output.should equal(input)
- output.frozen?.should == true
+ output.should.frozen?
end
it 'returns a frozen copy if the String is not frozen' do
input = 'foo'
output = -input
- output.frozen?.should == true
+ output.should.frozen?
output.should_not equal(input)
output.should == 'foo'
end
- ruby_version_is "2.5" do
- it "returns the same object for equal unfrozen strings" do
- origin = "this is a string"
- dynamic = %w(this is a string).join(' ')
+ it "returns the same object for equal unfrozen strings" do
+ origin = "this is a string"
+ dynamic = %w(this is a string).join(' ')
- origin.should_not equal(dynamic)
- (-origin).should equal(-dynamic)
- end
+ origin.should_not equal(dynamic)
+ (-origin).should equal(-dynamic)
+ end
- it "returns the same object when it's called on the same String literal" do
- (-"unfrozen string").should equal(-"unfrozen string")
- (-"unfrozen string").should_not equal(-"another unfrozen string")
- end
+ it "returns the same object when it's called on the same String literal" do
+ (-"unfrozen string").should equal(-"unfrozen string")
+ (-"unfrozen string").should_not equal(-"another unfrozen string")
end
- ruby_version_is "2.5"..."2.6" do
+ ruby_version_is ""..."2.6" do
it "does not deduplicate already frozen strings" do
dynamic = %w(this string is frozen).join(' ').freeze
@@ -71,4 +69,11 @@ describe 'String#-@' do
(-dynamic).should equal(-"this string is frozen".freeze)
end
end
+
+ ruby_version_is "3.0" do
+ it "interns the provided string if it is frozen" do
+ dynamic = "this string is unique and frozen #{rand}".freeze
+ (-dynamic).should equal(dynamic)
+ end
+ end
end
diff --git a/spec/ruby/core/string/undump_spec.rb b/spec/ruby/core/string/undump_spec.rb
index d45c4bae1b..b990aa25ee 100644
--- a/spec/ruby/core/string/undump_spec.rb
+++ b/spec/ruby/core/string/undump_spec.rb
@@ -2,452 +2,450 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is '2.5' do
- describe "String#undump" do
- ruby_version_is ''...'2.7' do
- it "taints the result if self is tainted" do
- '"foo"'.taint.undump.tainted?.should == true
- end
-
- it "untrusts the result if self is untrusted" do
- '"foo"'.untrust.undump.untrusted?.should == true
- end
+describe "String#undump" do
+ ruby_version_is ''...'2.7' do
+ it "taints the result if self is tainted" do
+ '"foo"'.taint.undump.should.tainted?
end
- it "does not take into account if a string is frozen" do
- '"foo"'.freeze.undump.frozen?.should == false
+ it "untrusts the result if self is untrusted" do
+ '"foo"'.untrust.undump.should.untrusted?
end
+ end
- it "always returns String instance" do
- StringSpecs::MyString.new('"foo"').undump.should be_an_instance_of(String)
- end
+ it "does not take into account if a string is frozen" do
+ '"foo"'.freeze.undump.should_not.frozen?
+ end
- it "strips outer \"" do
- '"foo"'.undump.should == 'foo'
- end
+ it "always returns String instance" do
+ StringSpecs::MyString.new('"foo"').undump.should be_an_instance_of(String)
+ end
- it "returns a string with special characters in \\<char> notation replaced with the characters" do
- [ ['"\\a"', "\a"],
- ['"\\b"', "\b"],
- ['"\\t"', "\t"],
- ['"\\n"', "\n"],
- ['"\\v"', "\v"],
- ['"\\f"', "\f"],
- ['"\\r"', "\r"],
- ['"\\e"', "\e"]
- ].should be_computed_by(:undump)
- end
+ it "strips outer \"" do
+ '"foo"'.undump.should == 'foo'
+ end
- it "returns a string with unescaped sequences \" and \\" do
- [ ['"\\""' , "\""],
- ['"\\\\"', "\\"]
- ].should be_computed_by(:undump)
- end
+ it "returns a string with special characters in \\<char> notation replaced with the characters" do
+ [ ['"\\a"', "\a"],
+ ['"\\b"', "\b"],
+ ['"\\t"', "\t"],
+ ['"\\n"', "\n"],
+ ['"\\v"', "\v"],
+ ['"\\f"', "\f"],
+ ['"\\r"', "\r"],
+ ['"\\e"', "\e"]
+ ].should be_computed_by(:undump)
+ end
- it "returns a string with unescaped sequences \\#<char> when # is followed by $, @, {" do
- [ ['"\\#$PATH"', "\#$PATH"],
- ['"\\#@a"', "\#@a"],
- ['"\\#@@a"', "\#@@a"],
- ['"\\#{a}"', "\#{a}"]
- ].should be_computed_by(:undump)
- end
+ it "returns a string with unescaped sequences \" and \\" do
+ [ ['"\\""' , "\""],
+ ['"\\\\"', "\\"]
+ ].should be_computed_by(:undump)
+ end
- it "returns a string with # not escaped when followed by any other character" do
- [ ['"#"', '#'],
- ['"#1"', '#1']
- ].should be_computed_by(:undump)
- end
+ it "returns a string with unescaped sequences \\#<char> when # is followed by $, @, {" do
+ [ ['"\\#$PATH"', "\#$PATH"],
+ ['"\\#@a"', "\#@a"],
+ ['"\\#@@a"', "\#@@a"],
+ ['"\\#{a}"', "\#{a}"]
+ ].should be_computed_by(:undump)
+ end
- it "returns a string with printable non-alphanumeric characters" do
- [ ['" "', ' '],
- ['"!"', '!'],
- ['"$"', '$'],
- ['"%"', '%'],
- ['"&"', '&'],
- ['"\'"', '\''],
- ['"("', '('],
- ['")"', ')'],
- ['"*"', '*'],
- ['"+"', '+'],
- ['","', ','],
- ['"-"', '-'],
- ['"."', '.'],
- ['"/"', '/'],
- ['":"', ':'],
- ['";"', ';'],
- ['"<"', '<'],
- ['"="', '='],
- ['">"', '>'],
- ['"?"', '?'],
- ['"@"', '@'],
- ['"["', '['],
- ['"]"', ']'],
- ['"^"', '^'],
- ['"_"', '_'],
- ['"`"', '`'],
- ['"{"', '{'],
- ['"|"', '|'],
- ['"}"', '}'],
- ['"~"', '~']
- ].should be_computed_by(:undump)
- end
+ it "returns a string with # not escaped when followed by any other character" do
+ [ ['"#"', '#'],
+ ['"#1"', '#1']
+ ].should be_computed_by(:undump)
+ end
- it "returns a string with numeric characters unescaped" do
- [ ['"0"', "0"],
- ['"1"', "1"],
- ['"2"', "2"],
- ['"3"', "3"],
- ['"4"', "4"],
- ['"5"', "5"],
- ['"6"', "6"],
- ['"7"', "7"],
- ['"8"', "8"],
- ['"9"', "9"],
- ].should be_computed_by(:undump)
- end
+ it "returns a string with printable non-alphanumeric characters" do
+ [ ['" "', ' '],
+ ['"!"', '!'],
+ ['"$"', '$'],
+ ['"%"', '%'],
+ ['"&"', '&'],
+ ['"\'"', '\''],
+ ['"("', '('],
+ ['")"', ')'],
+ ['"*"', '*'],
+ ['"+"', '+'],
+ ['","', ','],
+ ['"-"', '-'],
+ ['"."', '.'],
+ ['"/"', '/'],
+ ['":"', ':'],
+ ['";"', ';'],
+ ['"<"', '<'],
+ ['"="', '='],
+ ['">"', '>'],
+ ['"?"', '?'],
+ ['"@"', '@'],
+ ['"["', '['],
+ ['"]"', ']'],
+ ['"^"', '^'],
+ ['"_"', '_'],
+ ['"`"', '`'],
+ ['"{"', '{'],
+ ['"|"', '|'],
+ ['"}"', '}'],
+ ['"~"', '~']
+ ].should be_computed_by(:undump)
+ end
- it "returns a string with upper-case alpha characters unescaped" do
- [ ['"A"', 'A'],
- ['"B"', 'B'],
- ['"C"', 'C'],
- ['"D"', 'D'],
- ['"E"', 'E'],
- ['"F"', 'F'],
- ['"G"', 'G'],
- ['"H"', 'H'],
- ['"I"', 'I'],
- ['"J"', 'J'],
- ['"K"', 'K'],
- ['"L"', 'L'],
- ['"M"', 'M'],
- ['"N"', 'N'],
- ['"O"', 'O'],
- ['"P"', 'P'],
- ['"Q"', 'Q'],
- ['"R"', 'R'],
- ['"S"', 'S'],
- ['"T"', 'T'],
- ['"U"', 'U'],
- ['"V"', 'V'],
- ['"W"', 'W'],
- ['"X"', 'X'],
- ['"Y"', 'Y'],
- ['"Z"', 'Z']
- ].should be_computed_by(:undump)
- end
+ it "returns a string with numeric characters unescaped" do
+ [ ['"0"', "0"],
+ ['"1"', "1"],
+ ['"2"', "2"],
+ ['"3"', "3"],
+ ['"4"', "4"],
+ ['"5"', "5"],
+ ['"6"', "6"],
+ ['"7"', "7"],
+ ['"8"', "8"],
+ ['"9"', "9"],
+ ].should be_computed_by(:undump)
+ end
- it "returns a string with lower-case alpha characters unescaped" do
- [ ['"a"', 'a'],
- ['"b"', 'b'],
- ['"c"', 'c'],
- ['"d"', 'd'],
- ['"e"', 'e'],
- ['"f"', 'f'],
- ['"g"', 'g'],
- ['"h"', 'h'],
- ['"i"', 'i'],
- ['"j"', 'j'],
- ['"k"', 'k'],
- ['"l"', 'l'],
- ['"m"', 'm'],
- ['"n"', 'n'],
- ['"o"', 'o'],
- ['"p"', 'p'],
- ['"q"', 'q'],
- ['"r"', 'r'],
- ['"s"', 's'],
- ['"t"', 't'],
- ['"u"', 'u'],
- ['"v"', 'v'],
- ['"w"', 'w'],
- ['"x"', 'x'],
- ['"y"', 'y'],
- ['"z"', 'z']
- ].should be_computed_by(:undump)
- end
+ it "returns a string with upper-case alpha characters unescaped" do
+ [ ['"A"', 'A'],
+ ['"B"', 'B'],
+ ['"C"', 'C'],
+ ['"D"', 'D'],
+ ['"E"', 'E'],
+ ['"F"', 'F'],
+ ['"G"', 'G'],
+ ['"H"', 'H'],
+ ['"I"', 'I'],
+ ['"J"', 'J'],
+ ['"K"', 'K'],
+ ['"L"', 'L'],
+ ['"M"', 'M'],
+ ['"N"', 'N'],
+ ['"O"', 'O'],
+ ['"P"', 'P'],
+ ['"Q"', 'Q'],
+ ['"R"', 'R'],
+ ['"S"', 'S'],
+ ['"T"', 'T'],
+ ['"U"', 'U'],
+ ['"V"', 'V'],
+ ['"W"', 'W'],
+ ['"X"', 'X'],
+ ['"Y"', 'Y'],
+ ['"Z"', 'Z']
+ ].should be_computed_by(:undump)
+ end
- it "returns a string with \\x notation replaced with non-printing ASCII character" do
- [ ['"\\x00"', 0000.chr.force_encoding('utf-8')],
- ['"\\x01"', 0001.chr.force_encoding('utf-8')],
- ['"\\x02"', 0002.chr.force_encoding('utf-8')],
- ['"\\x03"', 0003.chr.force_encoding('utf-8')],
- ['"\\x04"', 0004.chr.force_encoding('utf-8')],
- ['"\\x05"', 0005.chr.force_encoding('utf-8')],
- ['"\\x06"', 0006.chr.force_encoding('utf-8')],
- ['"\\x0E"', 0016.chr.force_encoding('utf-8')],
- ['"\\x0F"', 0017.chr.force_encoding('utf-8')],
- ['"\\x10"', 0020.chr.force_encoding('utf-8')],
- ['"\\x11"', 0021.chr.force_encoding('utf-8')],
- ['"\\x12"', 0022.chr.force_encoding('utf-8')],
- ['"\\x13"', 0023.chr.force_encoding('utf-8')],
- ['"\\x14"', 0024.chr.force_encoding('utf-8')],
- ['"\\x15"', 0025.chr.force_encoding('utf-8')],
- ['"\\x16"', 0026.chr.force_encoding('utf-8')],
- ['"\\x17"', 0027.chr.force_encoding('utf-8')],
- ['"\\x18"', 0030.chr.force_encoding('utf-8')],
- ['"\\x19"', 0031.chr.force_encoding('utf-8')],
- ['"\\x1A"', 0032.chr.force_encoding('utf-8')],
- ['"\\x1C"', 0034.chr.force_encoding('utf-8')],
- ['"\\x1D"', 0035.chr.force_encoding('utf-8')],
- ['"\\x1E"', 0036.chr.force_encoding('utf-8')],
- ['"\\x1F"', 0037.chr.force_encoding('utf-8')],
- ['"\\x7F"', 0177.chr.force_encoding('utf-8')],
- ['"\\x80"', 0200.chr.force_encoding('utf-8')],
- ['"\\x81"', 0201.chr.force_encoding('utf-8')],
- ['"\\x82"', 0202.chr.force_encoding('utf-8')],
- ['"\\x83"', 0203.chr.force_encoding('utf-8')],
- ['"\\x84"', 0204.chr.force_encoding('utf-8')],
- ['"\\x85"', 0205.chr.force_encoding('utf-8')],
- ['"\\x86"', 0206.chr.force_encoding('utf-8')],
- ['"\\x87"', 0207.chr.force_encoding('utf-8')],
- ['"\\x88"', 0210.chr.force_encoding('utf-8')],
- ['"\\x89"', 0211.chr.force_encoding('utf-8')],
- ['"\\x8A"', 0212.chr.force_encoding('utf-8')],
- ['"\\x8B"', 0213.chr.force_encoding('utf-8')],
- ['"\\x8C"', 0214.chr.force_encoding('utf-8')],
- ['"\\x8D"', 0215.chr.force_encoding('utf-8')],
- ['"\\x8E"', 0216.chr.force_encoding('utf-8')],
- ['"\\x8F"', 0217.chr.force_encoding('utf-8')],
- ['"\\x90"', 0220.chr.force_encoding('utf-8')],
- ['"\\x91"', 0221.chr.force_encoding('utf-8')],
- ['"\\x92"', 0222.chr.force_encoding('utf-8')],
- ['"\\x93"', 0223.chr.force_encoding('utf-8')],
- ['"\\x94"', 0224.chr.force_encoding('utf-8')],
- ['"\\x95"', 0225.chr.force_encoding('utf-8')],
- ['"\\x96"', 0226.chr.force_encoding('utf-8')],
- ['"\\x97"', 0227.chr.force_encoding('utf-8')],
- ['"\\x98"', 0230.chr.force_encoding('utf-8')],
- ['"\\x99"', 0231.chr.force_encoding('utf-8')],
- ['"\\x9A"', 0232.chr.force_encoding('utf-8')],
- ['"\\x9B"', 0233.chr.force_encoding('utf-8')],
- ['"\\x9C"', 0234.chr.force_encoding('utf-8')],
- ['"\\x9D"', 0235.chr.force_encoding('utf-8')],
- ['"\\x9E"', 0236.chr.force_encoding('utf-8')],
- ['"\\x9F"', 0237.chr.force_encoding('utf-8')],
- ['"\\xA0"', 0240.chr.force_encoding('utf-8')],
- ['"\\xA1"', 0241.chr.force_encoding('utf-8')],
- ['"\\xA2"', 0242.chr.force_encoding('utf-8')],
- ['"\\xA3"', 0243.chr.force_encoding('utf-8')],
- ['"\\xA4"', 0244.chr.force_encoding('utf-8')],
- ['"\\xA5"', 0245.chr.force_encoding('utf-8')],
- ['"\\xA6"', 0246.chr.force_encoding('utf-8')],
- ['"\\xA7"', 0247.chr.force_encoding('utf-8')],
- ['"\\xA8"', 0250.chr.force_encoding('utf-8')],
- ['"\\xA9"', 0251.chr.force_encoding('utf-8')],
- ['"\\xAA"', 0252.chr.force_encoding('utf-8')],
- ['"\\xAB"', 0253.chr.force_encoding('utf-8')],
- ['"\\xAC"', 0254.chr.force_encoding('utf-8')],
- ['"\\xAD"', 0255.chr.force_encoding('utf-8')],
- ['"\\xAE"', 0256.chr.force_encoding('utf-8')],
- ['"\\xAF"', 0257.chr.force_encoding('utf-8')],
- ['"\\xB0"', 0260.chr.force_encoding('utf-8')],
- ['"\\xB1"', 0261.chr.force_encoding('utf-8')],
- ['"\\xB2"', 0262.chr.force_encoding('utf-8')],
- ['"\\xB3"', 0263.chr.force_encoding('utf-8')],
- ['"\\xB4"', 0264.chr.force_encoding('utf-8')],
- ['"\\xB5"', 0265.chr.force_encoding('utf-8')],
- ['"\\xB6"', 0266.chr.force_encoding('utf-8')],
- ['"\\xB7"', 0267.chr.force_encoding('utf-8')],
- ['"\\xB8"', 0270.chr.force_encoding('utf-8')],
- ['"\\xB9"', 0271.chr.force_encoding('utf-8')],
- ['"\\xBA"', 0272.chr.force_encoding('utf-8')],
- ['"\\xBB"', 0273.chr.force_encoding('utf-8')],
- ['"\\xBC"', 0274.chr.force_encoding('utf-8')],
- ['"\\xBD"', 0275.chr.force_encoding('utf-8')],
- ['"\\xBE"', 0276.chr.force_encoding('utf-8')],
- ['"\\xBF"', 0277.chr.force_encoding('utf-8')],
- ['"\\xC0"', 0300.chr.force_encoding('utf-8')],
- ['"\\xC1"', 0301.chr.force_encoding('utf-8')],
- ['"\\xC2"', 0302.chr.force_encoding('utf-8')],
- ['"\\xC3"', 0303.chr.force_encoding('utf-8')],
- ['"\\xC4"', 0304.chr.force_encoding('utf-8')],
- ['"\\xC5"', 0305.chr.force_encoding('utf-8')],
- ['"\\xC6"', 0306.chr.force_encoding('utf-8')],
- ['"\\xC7"', 0307.chr.force_encoding('utf-8')],
- ['"\\xC8"', 0310.chr.force_encoding('utf-8')],
- ['"\\xC9"', 0311.chr.force_encoding('utf-8')],
- ['"\\xCA"', 0312.chr.force_encoding('utf-8')],
- ['"\\xCB"', 0313.chr.force_encoding('utf-8')],
- ['"\\xCC"', 0314.chr.force_encoding('utf-8')],
- ['"\\xCD"', 0315.chr.force_encoding('utf-8')],
- ['"\\xCE"', 0316.chr.force_encoding('utf-8')],
- ['"\\xCF"', 0317.chr.force_encoding('utf-8')],
- ['"\\xD0"', 0320.chr.force_encoding('utf-8')],
- ['"\\xD1"', 0321.chr.force_encoding('utf-8')],
- ['"\\xD2"', 0322.chr.force_encoding('utf-8')],
- ['"\\xD3"', 0323.chr.force_encoding('utf-8')],
- ['"\\xD4"', 0324.chr.force_encoding('utf-8')],
- ['"\\xD5"', 0325.chr.force_encoding('utf-8')],
- ['"\\xD6"', 0326.chr.force_encoding('utf-8')],
- ['"\\xD7"', 0327.chr.force_encoding('utf-8')],
- ['"\\xD8"', 0330.chr.force_encoding('utf-8')],
- ['"\\xD9"', 0331.chr.force_encoding('utf-8')],
- ['"\\xDA"', 0332.chr.force_encoding('utf-8')],
- ['"\\xDB"', 0333.chr.force_encoding('utf-8')],
- ['"\\xDC"', 0334.chr.force_encoding('utf-8')],
- ['"\\xDD"', 0335.chr.force_encoding('utf-8')],
- ['"\\xDE"', 0336.chr.force_encoding('utf-8')],
- ['"\\xDF"', 0337.chr.force_encoding('utf-8')],
- ['"\\xE0"', 0340.chr.force_encoding('utf-8')],
- ['"\\xE1"', 0341.chr.force_encoding('utf-8')],
- ['"\\xE2"', 0342.chr.force_encoding('utf-8')],
- ['"\\xE3"', 0343.chr.force_encoding('utf-8')],
- ['"\\xE4"', 0344.chr.force_encoding('utf-8')],
- ['"\\xE5"', 0345.chr.force_encoding('utf-8')],
- ['"\\xE6"', 0346.chr.force_encoding('utf-8')],
- ['"\\xE7"', 0347.chr.force_encoding('utf-8')],
- ['"\\xE8"', 0350.chr.force_encoding('utf-8')],
- ['"\\xE9"', 0351.chr.force_encoding('utf-8')],
- ['"\\xEA"', 0352.chr.force_encoding('utf-8')],
- ['"\\xEB"', 0353.chr.force_encoding('utf-8')],
- ['"\\xEC"', 0354.chr.force_encoding('utf-8')],
- ['"\\xED"', 0355.chr.force_encoding('utf-8')],
- ['"\\xEE"', 0356.chr.force_encoding('utf-8')],
- ['"\\xEF"', 0357.chr.force_encoding('utf-8')],
- ['"\\xF0"', 0360.chr.force_encoding('utf-8')],
- ['"\\xF1"', 0361.chr.force_encoding('utf-8')],
- ['"\\xF2"', 0362.chr.force_encoding('utf-8')],
- ['"\\xF3"', 0363.chr.force_encoding('utf-8')],
- ['"\\xF4"', 0364.chr.force_encoding('utf-8')],
- ['"\\xF5"', 0365.chr.force_encoding('utf-8')],
- ['"\\xF6"', 0366.chr.force_encoding('utf-8')],
- ['"\\xF7"', 0367.chr.force_encoding('utf-8')],
- ['"\\xF8"', 0370.chr.force_encoding('utf-8')],
- ['"\\xF9"', 0371.chr.force_encoding('utf-8')],
- ['"\\xFA"', 0372.chr.force_encoding('utf-8')],
- ['"\\xFB"', 0373.chr.force_encoding('utf-8')],
- ['"\\xFC"', 0374.chr.force_encoding('utf-8')],
- ['"\\xFD"', 0375.chr.force_encoding('utf-8')],
- ['"\\xFE"', 0376.chr.force_encoding('utf-8')],
- ['"\\xFF"', 0377.chr.force_encoding('utf-8')]
- ].should be_computed_by(:undump)
- end
+ it "returns a string with lower-case alpha characters unescaped" do
+ [ ['"a"', 'a'],
+ ['"b"', 'b'],
+ ['"c"', 'c'],
+ ['"d"', 'd'],
+ ['"e"', 'e'],
+ ['"f"', 'f'],
+ ['"g"', 'g'],
+ ['"h"', 'h'],
+ ['"i"', 'i'],
+ ['"j"', 'j'],
+ ['"k"', 'k'],
+ ['"l"', 'l'],
+ ['"m"', 'm'],
+ ['"n"', 'n'],
+ ['"o"', 'o'],
+ ['"p"', 'p'],
+ ['"q"', 'q'],
+ ['"r"', 'r'],
+ ['"s"', 's'],
+ ['"t"', 't'],
+ ['"u"', 'u'],
+ ['"v"', 'v'],
+ ['"w"', 'w'],
+ ['"x"', 'x'],
+ ['"y"', 'y'],
+ ['"z"', 'z']
+ ].should be_computed_by(:undump)
+ end
- it "returns a string with \\u{} notation replaced with multi-byte UTF-8 characters" do
- [ ['"\u{80}"', 0200.chr('utf-8')],
- ['"\u{81}"', 0201.chr('utf-8')],
- ['"\u{82}"', 0202.chr('utf-8')],
- ['"\u{83}"', 0203.chr('utf-8')],
- ['"\u{84}"', 0204.chr('utf-8')],
- ['"\u{86}"', 0206.chr('utf-8')],
- ['"\u{87}"', 0207.chr('utf-8')],
- ['"\u{88}"', 0210.chr('utf-8')],
- ['"\u{89}"', 0211.chr('utf-8')],
- ['"\u{8a}"', 0212.chr('utf-8')],
- ['"\u{8b}"', 0213.chr('utf-8')],
- ['"\u{8c}"', 0214.chr('utf-8')],
- ['"\u{8d}"', 0215.chr('utf-8')],
- ['"\u{8e}"', 0216.chr('utf-8')],
- ['"\u{8f}"', 0217.chr('utf-8')],
- ['"\u{90}"', 0220.chr('utf-8')],
- ['"\u{91}"', 0221.chr('utf-8')],
- ['"\u{92}"', 0222.chr('utf-8')],
- ['"\u{93}"', 0223.chr('utf-8')],
- ['"\u{94}"', 0224.chr('utf-8')],
- ['"\u{95}"', 0225.chr('utf-8')],
- ['"\u{96}"', 0226.chr('utf-8')],
- ['"\u{97}"', 0227.chr('utf-8')],
- ['"\u{98}"', 0230.chr('utf-8')],
- ['"\u{99}"', 0231.chr('utf-8')],
- ['"\u{9a}"', 0232.chr('utf-8')],
- ['"\u{9b}"', 0233.chr('utf-8')],
- ['"\u{9c}"', 0234.chr('utf-8')],
- ['"\u{9d}"', 0235.chr('utf-8')],
- ['"\u{9e}"', 0236.chr('utf-8')],
- ['"\u{9f}"', 0237.chr('utf-8')],
- ].should be_computed_by(:undump)
- end
+ it "returns a string with \\x notation replaced with non-printing ASCII character" do
+ [ ['"\\x00"', 0000.chr.force_encoding('utf-8')],
+ ['"\\x01"', 0001.chr.force_encoding('utf-8')],
+ ['"\\x02"', 0002.chr.force_encoding('utf-8')],
+ ['"\\x03"', 0003.chr.force_encoding('utf-8')],
+ ['"\\x04"', 0004.chr.force_encoding('utf-8')],
+ ['"\\x05"', 0005.chr.force_encoding('utf-8')],
+ ['"\\x06"', 0006.chr.force_encoding('utf-8')],
+ ['"\\x0E"', 0016.chr.force_encoding('utf-8')],
+ ['"\\x0F"', 0017.chr.force_encoding('utf-8')],
+ ['"\\x10"', 0020.chr.force_encoding('utf-8')],
+ ['"\\x11"', 0021.chr.force_encoding('utf-8')],
+ ['"\\x12"', 0022.chr.force_encoding('utf-8')],
+ ['"\\x13"', 0023.chr.force_encoding('utf-8')],
+ ['"\\x14"', 0024.chr.force_encoding('utf-8')],
+ ['"\\x15"', 0025.chr.force_encoding('utf-8')],
+ ['"\\x16"', 0026.chr.force_encoding('utf-8')],
+ ['"\\x17"', 0027.chr.force_encoding('utf-8')],
+ ['"\\x18"', 0030.chr.force_encoding('utf-8')],
+ ['"\\x19"', 0031.chr.force_encoding('utf-8')],
+ ['"\\x1A"', 0032.chr.force_encoding('utf-8')],
+ ['"\\x1C"', 0034.chr.force_encoding('utf-8')],
+ ['"\\x1D"', 0035.chr.force_encoding('utf-8')],
+ ['"\\x1E"', 0036.chr.force_encoding('utf-8')],
+ ['"\\x1F"', 0037.chr.force_encoding('utf-8')],
+ ['"\\x7F"', 0177.chr.force_encoding('utf-8')],
+ ['"\\x80"', 0200.chr.force_encoding('utf-8')],
+ ['"\\x81"', 0201.chr.force_encoding('utf-8')],
+ ['"\\x82"', 0202.chr.force_encoding('utf-8')],
+ ['"\\x83"', 0203.chr.force_encoding('utf-8')],
+ ['"\\x84"', 0204.chr.force_encoding('utf-8')],
+ ['"\\x85"', 0205.chr.force_encoding('utf-8')],
+ ['"\\x86"', 0206.chr.force_encoding('utf-8')],
+ ['"\\x87"', 0207.chr.force_encoding('utf-8')],
+ ['"\\x88"', 0210.chr.force_encoding('utf-8')],
+ ['"\\x89"', 0211.chr.force_encoding('utf-8')],
+ ['"\\x8A"', 0212.chr.force_encoding('utf-8')],
+ ['"\\x8B"', 0213.chr.force_encoding('utf-8')],
+ ['"\\x8C"', 0214.chr.force_encoding('utf-8')],
+ ['"\\x8D"', 0215.chr.force_encoding('utf-8')],
+ ['"\\x8E"', 0216.chr.force_encoding('utf-8')],
+ ['"\\x8F"', 0217.chr.force_encoding('utf-8')],
+ ['"\\x90"', 0220.chr.force_encoding('utf-8')],
+ ['"\\x91"', 0221.chr.force_encoding('utf-8')],
+ ['"\\x92"', 0222.chr.force_encoding('utf-8')],
+ ['"\\x93"', 0223.chr.force_encoding('utf-8')],
+ ['"\\x94"', 0224.chr.force_encoding('utf-8')],
+ ['"\\x95"', 0225.chr.force_encoding('utf-8')],
+ ['"\\x96"', 0226.chr.force_encoding('utf-8')],
+ ['"\\x97"', 0227.chr.force_encoding('utf-8')],
+ ['"\\x98"', 0230.chr.force_encoding('utf-8')],
+ ['"\\x99"', 0231.chr.force_encoding('utf-8')],
+ ['"\\x9A"', 0232.chr.force_encoding('utf-8')],
+ ['"\\x9B"', 0233.chr.force_encoding('utf-8')],
+ ['"\\x9C"', 0234.chr.force_encoding('utf-8')],
+ ['"\\x9D"', 0235.chr.force_encoding('utf-8')],
+ ['"\\x9E"', 0236.chr.force_encoding('utf-8')],
+ ['"\\x9F"', 0237.chr.force_encoding('utf-8')],
+ ['"\\xA0"', 0240.chr.force_encoding('utf-8')],
+ ['"\\xA1"', 0241.chr.force_encoding('utf-8')],
+ ['"\\xA2"', 0242.chr.force_encoding('utf-8')],
+ ['"\\xA3"', 0243.chr.force_encoding('utf-8')],
+ ['"\\xA4"', 0244.chr.force_encoding('utf-8')],
+ ['"\\xA5"', 0245.chr.force_encoding('utf-8')],
+ ['"\\xA6"', 0246.chr.force_encoding('utf-8')],
+ ['"\\xA7"', 0247.chr.force_encoding('utf-8')],
+ ['"\\xA8"', 0250.chr.force_encoding('utf-8')],
+ ['"\\xA9"', 0251.chr.force_encoding('utf-8')],
+ ['"\\xAA"', 0252.chr.force_encoding('utf-8')],
+ ['"\\xAB"', 0253.chr.force_encoding('utf-8')],
+ ['"\\xAC"', 0254.chr.force_encoding('utf-8')],
+ ['"\\xAD"', 0255.chr.force_encoding('utf-8')],
+ ['"\\xAE"', 0256.chr.force_encoding('utf-8')],
+ ['"\\xAF"', 0257.chr.force_encoding('utf-8')],
+ ['"\\xB0"', 0260.chr.force_encoding('utf-8')],
+ ['"\\xB1"', 0261.chr.force_encoding('utf-8')],
+ ['"\\xB2"', 0262.chr.force_encoding('utf-8')],
+ ['"\\xB3"', 0263.chr.force_encoding('utf-8')],
+ ['"\\xB4"', 0264.chr.force_encoding('utf-8')],
+ ['"\\xB5"', 0265.chr.force_encoding('utf-8')],
+ ['"\\xB6"', 0266.chr.force_encoding('utf-8')],
+ ['"\\xB7"', 0267.chr.force_encoding('utf-8')],
+ ['"\\xB8"', 0270.chr.force_encoding('utf-8')],
+ ['"\\xB9"', 0271.chr.force_encoding('utf-8')],
+ ['"\\xBA"', 0272.chr.force_encoding('utf-8')],
+ ['"\\xBB"', 0273.chr.force_encoding('utf-8')],
+ ['"\\xBC"', 0274.chr.force_encoding('utf-8')],
+ ['"\\xBD"', 0275.chr.force_encoding('utf-8')],
+ ['"\\xBE"', 0276.chr.force_encoding('utf-8')],
+ ['"\\xBF"', 0277.chr.force_encoding('utf-8')],
+ ['"\\xC0"', 0300.chr.force_encoding('utf-8')],
+ ['"\\xC1"', 0301.chr.force_encoding('utf-8')],
+ ['"\\xC2"', 0302.chr.force_encoding('utf-8')],
+ ['"\\xC3"', 0303.chr.force_encoding('utf-8')],
+ ['"\\xC4"', 0304.chr.force_encoding('utf-8')],
+ ['"\\xC5"', 0305.chr.force_encoding('utf-8')],
+ ['"\\xC6"', 0306.chr.force_encoding('utf-8')],
+ ['"\\xC7"', 0307.chr.force_encoding('utf-8')],
+ ['"\\xC8"', 0310.chr.force_encoding('utf-8')],
+ ['"\\xC9"', 0311.chr.force_encoding('utf-8')],
+ ['"\\xCA"', 0312.chr.force_encoding('utf-8')],
+ ['"\\xCB"', 0313.chr.force_encoding('utf-8')],
+ ['"\\xCC"', 0314.chr.force_encoding('utf-8')],
+ ['"\\xCD"', 0315.chr.force_encoding('utf-8')],
+ ['"\\xCE"', 0316.chr.force_encoding('utf-8')],
+ ['"\\xCF"', 0317.chr.force_encoding('utf-8')],
+ ['"\\xD0"', 0320.chr.force_encoding('utf-8')],
+ ['"\\xD1"', 0321.chr.force_encoding('utf-8')],
+ ['"\\xD2"', 0322.chr.force_encoding('utf-8')],
+ ['"\\xD3"', 0323.chr.force_encoding('utf-8')],
+ ['"\\xD4"', 0324.chr.force_encoding('utf-8')],
+ ['"\\xD5"', 0325.chr.force_encoding('utf-8')],
+ ['"\\xD6"', 0326.chr.force_encoding('utf-8')],
+ ['"\\xD7"', 0327.chr.force_encoding('utf-8')],
+ ['"\\xD8"', 0330.chr.force_encoding('utf-8')],
+ ['"\\xD9"', 0331.chr.force_encoding('utf-8')],
+ ['"\\xDA"', 0332.chr.force_encoding('utf-8')],
+ ['"\\xDB"', 0333.chr.force_encoding('utf-8')],
+ ['"\\xDC"', 0334.chr.force_encoding('utf-8')],
+ ['"\\xDD"', 0335.chr.force_encoding('utf-8')],
+ ['"\\xDE"', 0336.chr.force_encoding('utf-8')],
+ ['"\\xDF"', 0337.chr.force_encoding('utf-8')],
+ ['"\\xE0"', 0340.chr.force_encoding('utf-8')],
+ ['"\\xE1"', 0341.chr.force_encoding('utf-8')],
+ ['"\\xE2"', 0342.chr.force_encoding('utf-8')],
+ ['"\\xE3"', 0343.chr.force_encoding('utf-8')],
+ ['"\\xE4"', 0344.chr.force_encoding('utf-8')],
+ ['"\\xE5"', 0345.chr.force_encoding('utf-8')],
+ ['"\\xE6"', 0346.chr.force_encoding('utf-8')],
+ ['"\\xE7"', 0347.chr.force_encoding('utf-8')],
+ ['"\\xE8"', 0350.chr.force_encoding('utf-8')],
+ ['"\\xE9"', 0351.chr.force_encoding('utf-8')],
+ ['"\\xEA"', 0352.chr.force_encoding('utf-8')],
+ ['"\\xEB"', 0353.chr.force_encoding('utf-8')],
+ ['"\\xEC"', 0354.chr.force_encoding('utf-8')],
+ ['"\\xED"', 0355.chr.force_encoding('utf-8')],
+ ['"\\xEE"', 0356.chr.force_encoding('utf-8')],
+ ['"\\xEF"', 0357.chr.force_encoding('utf-8')],
+ ['"\\xF0"', 0360.chr.force_encoding('utf-8')],
+ ['"\\xF1"', 0361.chr.force_encoding('utf-8')],
+ ['"\\xF2"', 0362.chr.force_encoding('utf-8')],
+ ['"\\xF3"', 0363.chr.force_encoding('utf-8')],
+ ['"\\xF4"', 0364.chr.force_encoding('utf-8')],
+ ['"\\xF5"', 0365.chr.force_encoding('utf-8')],
+ ['"\\xF6"', 0366.chr.force_encoding('utf-8')],
+ ['"\\xF7"', 0367.chr.force_encoding('utf-8')],
+ ['"\\xF8"', 0370.chr.force_encoding('utf-8')],
+ ['"\\xF9"', 0371.chr.force_encoding('utf-8')],
+ ['"\\xFA"', 0372.chr.force_encoding('utf-8')],
+ ['"\\xFB"', 0373.chr.force_encoding('utf-8')],
+ ['"\\xFC"', 0374.chr.force_encoding('utf-8')],
+ ['"\\xFD"', 0375.chr.force_encoding('utf-8')],
+ ['"\\xFE"', 0376.chr.force_encoding('utf-8')],
+ ['"\\xFF"', 0377.chr.force_encoding('utf-8')]
+ ].should be_computed_by(:undump)
+ end
- it "returns a string with \\uXXXX notation replaced with multi-byte UTF-8 characters" do
- [ ['"\u0080"', 0200.chr('utf-8')],
- ['"\u0081"', 0201.chr('utf-8')],
- ['"\u0082"', 0202.chr('utf-8')],
- ['"\u0083"', 0203.chr('utf-8')],
- ['"\u0084"', 0204.chr('utf-8')],
- ['"\u0086"', 0206.chr('utf-8')],
- ['"\u0087"', 0207.chr('utf-8')],
- ['"\u0088"', 0210.chr('utf-8')],
- ['"\u0089"', 0211.chr('utf-8')],
- ['"\u008a"', 0212.chr('utf-8')],
- ['"\u008b"', 0213.chr('utf-8')],
- ['"\u008c"', 0214.chr('utf-8')],
- ['"\u008d"', 0215.chr('utf-8')],
- ['"\u008e"', 0216.chr('utf-8')],
- ['"\u008f"', 0217.chr('utf-8')],
- ['"\u0090"', 0220.chr('utf-8')],
- ['"\u0091"', 0221.chr('utf-8')],
- ['"\u0092"', 0222.chr('utf-8')],
- ['"\u0093"', 0223.chr('utf-8')],
- ['"\u0094"', 0224.chr('utf-8')],
- ['"\u0095"', 0225.chr('utf-8')],
- ['"\u0096"', 0226.chr('utf-8')],
- ['"\u0097"', 0227.chr('utf-8')],
- ['"\u0098"', 0230.chr('utf-8')],
- ['"\u0099"', 0231.chr('utf-8')],
- ['"\u009a"', 0232.chr('utf-8')],
- ['"\u009b"', 0233.chr('utf-8')],
- ['"\u009c"', 0234.chr('utf-8')],
- ['"\u009d"', 0235.chr('utf-8')],
- ['"\u009e"', 0236.chr('utf-8')],
- ['"\u009f"', 0237.chr('utf-8')],
- ].should be_computed_by(:undump)
- end
+ it "returns a string with \\u{} notation replaced with multi-byte UTF-8 characters" do
+ [ ['"\u{80}"', 0200.chr('utf-8')],
+ ['"\u{81}"', 0201.chr('utf-8')],
+ ['"\u{82}"', 0202.chr('utf-8')],
+ ['"\u{83}"', 0203.chr('utf-8')],
+ ['"\u{84}"', 0204.chr('utf-8')],
+ ['"\u{86}"', 0206.chr('utf-8')],
+ ['"\u{87}"', 0207.chr('utf-8')],
+ ['"\u{88}"', 0210.chr('utf-8')],
+ ['"\u{89}"', 0211.chr('utf-8')],
+ ['"\u{8a}"', 0212.chr('utf-8')],
+ ['"\u{8b}"', 0213.chr('utf-8')],
+ ['"\u{8c}"', 0214.chr('utf-8')],
+ ['"\u{8d}"', 0215.chr('utf-8')],
+ ['"\u{8e}"', 0216.chr('utf-8')],
+ ['"\u{8f}"', 0217.chr('utf-8')],
+ ['"\u{90}"', 0220.chr('utf-8')],
+ ['"\u{91}"', 0221.chr('utf-8')],
+ ['"\u{92}"', 0222.chr('utf-8')],
+ ['"\u{93}"', 0223.chr('utf-8')],
+ ['"\u{94}"', 0224.chr('utf-8')],
+ ['"\u{95}"', 0225.chr('utf-8')],
+ ['"\u{96}"', 0226.chr('utf-8')],
+ ['"\u{97}"', 0227.chr('utf-8')],
+ ['"\u{98}"', 0230.chr('utf-8')],
+ ['"\u{99}"', 0231.chr('utf-8')],
+ ['"\u{9a}"', 0232.chr('utf-8')],
+ ['"\u{9b}"', 0233.chr('utf-8')],
+ ['"\u{9c}"', 0234.chr('utf-8')],
+ ['"\u{9d}"', 0235.chr('utf-8')],
+ ['"\u{9e}"', 0236.chr('utf-8')],
+ ['"\u{9f}"', 0237.chr('utf-8')],
+ ].should be_computed_by(:undump)
+ end
- it "undumps correctly string produced from non ASCII-compatible one" do
- s = "\u{876}".encode('utf-16be')
- s.dump.undump.should == s
+ it "returns a string with \\uXXXX notation replaced with multi-byte UTF-8 characters" do
+ [ ['"\u0080"', 0200.chr('utf-8')],
+ ['"\u0081"', 0201.chr('utf-8')],
+ ['"\u0082"', 0202.chr('utf-8')],
+ ['"\u0083"', 0203.chr('utf-8')],
+ ['"\u0084"', 0204.chr('utf-8')],
+ ['"\u0086"', 0206.chr('utf-8')],
+ ['"\u0087"', 0207.chr('utf-8')],
+ ['"\u0088"', 0210.chr('utf-8')],
+ ['"\u0089"', 0211.chr('utf-8')],
+ ['"\u008a"', 0212.chr('utf-8')],
+ ['"\u008b"', 0213.chr('utf-8')],
+ ['"\u008c"', 0214.chr('utf-8')],
+ ['"\u008d"', 0215.chr('utf-8')],
+ ['"\u008e"', 0216.chr('utf-8')],
+ ['"\u008f"', 0217.chr('utf-8')],
+ ['"\u0090"', 0220.chr('utf-8')],
+ ['"\u0091"', 0221.chr('utf-8')],
+ ['"\u0092"', 0222.chr('utf-8')],
+ ['"\u0093"', 0223.chr('utf-8')],
+ ['"\u0094"', 0224.chr('utf-8')],
+ ['"\u0095"', 0225.chr('utf-8')],
+ ['"\u0096"', 0226.chr('utf-8')],
+ ['"\u0097"', 0227.chr('utf-8')],
+ ['"\u0098"', 0230.chr('utf-8')],
+ ['"\u0099"', 0231.chr('utf-8')],
+ ['"\u009a"', 0232.chr('utf-8')],
+ ['"\u009b"', 0233.chr('utf-8')],
+ ['"\u009c"', 0234.chr('utf-8')],
+ ['"\u009d"', 0235.chr('utf-8')],
+ ['"\u009e"', 0236.chr('utf-8')],
+ ['"\u009f"', 0237.chr('utf-8')],
+ ].should be_computed_by(:undump)
+ end
- '"\\bv".force_encoding("UTF-16BE")'.undump.should == "\u0876".encode('utf-16be')
- end
+ it "undumps correctly string produced from non ASCII-compatible one" do
+ s = "\u{876}".encode('utf-16be')
+ s.dump.undump.should == s
- it "keeps origin encoding" do
- '"foo"'.encode("ISO-8859-1").undump.encoding.should == Encoding::ISO_8859_1
- '"foo"'.encode('windows-1251').undump.encoding.should == Encoding::Windows_1251
- end
+ '"\\bv".force_encoding("UTF-16BE")'.undump.should == "\u0876".encode('utf-16be')
+ end
+
+ it "keeps origin encoding" do
+ '"foo"'.encode("ISO-8859-1").undump.encoding.should == Encoding::ISO_8859_1
+ '"foo"'.encode('windows-1251').undump.encoding.should == Encoding::Windows_1251
+ end
- describe "Limitations" do
- it "cannot undump non ASCII-compatible string" do
- -> { '"foo"'.encode('utf-16le').undump }.should raise_error(Encoding::CompatibilityError)
- end
+ describe "Limitations" do
+ it "cannot undump non ASCII-compatible string" do
+ -> { '"foo"'.encode('utf-16le').undump }.should raise_error(Encoding::CompatibilityError)
end
+ end
- describe "invalid dump" do
- it "raises RuntimeError exception if wrapping \" are missing" do
- -> { 'foo'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
- -> { '"foo'.undump }.should raise_error(RuntimeError, /unterminated dumped string/)
- -> { 'foo"'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
- -> { "'foo'".undump }.should raise_error(RuntimeError, /invalid dumped string/)
- end
+ describe "invalid dump" do
+ it "raises RuntimeError exception if wrapping \" are missing" do
+ -> { 'foo'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
+ -> { '"foo'.undump }.should raise_error(RuntimeError, /unterminated dumped string/)
+ -> { 'foo"'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
+ -> { "'foo'".undump }.should raise_error(RuntimeError, /invalid dumped string/)
+ end
- it "raises RuntimeError if there is incorrect \\x sequence" do
- -> { '"\x"'.undump }.should raise_error(RuntimeError, /invalid hex escape/)
- -> { '"\\x3y"'.undump }.should raise_error(RuntimeError, /invalid hex escape/)
- end
+ it "raises RuntimeError if there is incorrect \\x sequence" do
+ -> { '"\x"'.undump }.should raise_error(RuntimeError, /invalid hex escape/)
+ -> { '"\\x3y"'.undump }.should raise_error(RuntimeError, /invalid hex escape/)
+ end
- it "raises RuntimeError in there is incorrect \\u sequence" do
- -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
- -> { '"\\u{"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
- -> { '"\\u{3042"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
- -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
- end
+ it "raises RuntimeError in there is incorrect \\u sequence" do
+ -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
+ -> { '"\\u{"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
+ -> { '"\\u{3042"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
+ -> { '"\\u"'.undump }.should raise_error(RuntimeError, /invalid Unicode escape/)
+ end
- it "raises RuntimeError if there is malformed dump of non ASCII-compatible string" do
- -> { '"".force_encoding("BINARY"'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
- -> { '"".force_encoding("Unknown")'.undump }.should raise_error(RuntimeError, /dumped string has unknown encoding name/)
- -> { '"".force_encoding()'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
- end
+ it "raises RuntimeError if there is malformed dump of non ASCII-compatible string" do
+ -> { '"".force_encoding("BINARY"'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
+ -> { '"".force_encoding("Unknown")'.undump }.should raise_error(RuntimeError, /dumped string has unknown encoding name/)
+ -> { '"".force_encoding()'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
+ end
- it "raises RuntimeError if string contains \0 character" do
- -> { "\"foo\0\"".undump }.should raise_error(RuntimeError, /string contains null byte/)
- end
+ it "raises RuntimeError if string contains \0 character" do
+ -> { "\"foo\0\"".undump }.should raise_error(RuntimeError, /string contains null byte/)
+ end
- it "raises RuntimeError if string contains non ASCII character" do
- -> { "\"\u3042\"".undump }.should raise_error(RuntimeError, /non-ASCII character detected/)
- end
+ it "raises RuntimeError if string contains non ASCII character" do
+ -> { "\"\u3042\"".undump }.should raise_error(RuntimeError, /non-ASCII character detected/)
+ end
- it "raises RuntimeError if there are some excessive \"" do
- -> { '" "" "'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
- end
+ it "raises RuntimeError if there are some excessive \"" do
+ -> { '" "" "'.undump }.should raise_error(RuntimeError, /invalid dumped string/)
end
end
end
diff --git a/spec/ruby/core/string/unicode_normalized_spec.rb b/spec/ruby/core/string/unicode_normalized_spec.rb
index 25c810a98f..87f3740459 100644
--- a/spec/ruby/core/string/unicode_normalized_spec.rb
+++ b/spec/ruby/core/string/unicode_normalized_spec.rb
@@ -24,16 +24,16 @@ describe "String#unicode_normalized?" do
end
it "defaults to the nfc normalization form if no forms are specified" do
- @nfc_normalized_str.unicode_normalized?.should == true
- @nfd_normalized_str.unicode_normalized?.should == false
+ @nfc_normalized_str.should.unicode_normalized?
+ @nfd_normalized_str.should_not.unicode_normalized?
end
it "returns true if string is empty" do
- "".unicode_normalized?.should == true
+ "".should.unicode_normalized?
end
it "returns true if string does not contain any unicode codepoints" do
- "abc".unicode_normalized?.should == true
+ "abc".should.unicode_normalized?
end
it "raises an Encoding::CompatibilityError if the string is not in an unicode encoding" do
diff --git a/spec/ruby/core/string/unpack/m_spec.rb b/spec/ruby/core/string/unpack/m_spec.rb
index 96841f24cb..21134514a1 100644
--- a/spec/ruby/core/string/unpack/m_spec.rb
+++ b/spec/ruby/core/string/unpack/m_spec.rb
@@ -170,4 +170,18 @@ describe "String#unpack with format 'm'" do
"".unpack("m").first.encoding.should == Encoding::BINARY
"Ojs8PT4/QA==\n".unpack("m").first.encoding.should == Encoding::BINARY
end
+
+ it "does not raise an error for an invalid base64 character" do
+ "dGV%zdA==".unpack("m").should == ["test"]
+ end
+
+ describe "when given count 0" do
+ it "decodes base64" do
+ "dGVzdA==".unpack("m0").should == ["test"]
+ end
+
+ it "raises an ArgumentError for an invalid base64 character" do
+ -> { "dGV%zdA==".unpack("m0") }.should raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/string/unpack/w_spec.rb b/spec/ruby/core/string/unpack/w_spec.rb
index 166ae58869..011c75f5c4 100644
--- a/spec/ruby/core/string/unpack/w_spec.rb
+++ b/spec/ruby/core/string/unpack/w_spec.rb
@@ -23,3 +23,13 @@ describe "String#unpack with directive 'w'" do
"\x01\x02\x03".unpack("w w").should == [1, 2]
end
end
+
+describe "String#unpack with directive 'w*'" do
+
+ it "decodes BER-compressed integers" do
+ "\x01\x02\x03\x04".unpack("w*").should == [1, 2, 3, 4]
+ "\x00\xCE\x0F\x84\x80\x80\x80\x80\x80\x80\x80\x80\x00\x01\x00".unpack("w*").should == [0, 9999, 2**65, 1, 0]
+ "\x81\x80\x80\x80\x80\x80\x80\x80\x80\x00\x90\x80\x80\x80\x80\x80\x80\x80\x03\x01\x02".unpack("w*").should == [2**63, (2**60 + 3), 1, 2]
+ end
+
+end
diff --git a/spec/ruby/core/string/upcase_spec.rb b/spec/ruby/core/string/upcase_spec.rb
index eb7d708fe0..6cf44b4703 100644
--- a/spec/ruby/core/string/upcase_spec.rb
+++ b/spec/ruby/core/string/upcase_spec.rb
@@ -67,14 +67,22 @@ describe "String#upcase" do
ruby_version_is ''...'2.7' do
it "taints result when self is tainted" do
- "".taint.upcase.tainted?.should == true
- "X".taint.upcase.tainted?.should == true
- "x".taint.upcase.tainted?.should == true
+ "".taint.upcase.should.tainted?
+ "X".taint.upcase.should.tainted?
+ "x".taint.upcase.should.tainted?
end
end
- it "returns a subclass instance for subclasses" do
- StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(StringSpecs::MyString)
+ ruby_version_is ''...'3.0' do
+ it "returns a subclass instance for subclasses" do
+ StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(StringSpecs::MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns a String instance for subclasses" do
+ StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(String)
+ end
end
end
@@ -85,6 +93,12 @@ describe "String#upcase!" do
a.should == "HELLO"
end
+ it "modifies self in place for non-ascii-compatible encodings" do
+ a = "HeLlO".encode("utf-16le")
+ a.upcase!
+ a.should == "HELLO".encode("utf-16le")
+ end
+
describe "full Unicode case mapping" do
it "modifies self in place for all of Unicode with no option" do
a = "äöü"
@@ -92,6 +106,12 @@ describe "String#upcase!" do
a.should == "ÄÖÜ"
end
+ it "works for non-ascii-compatible encodings" do
+ a = "äöü".encode("utf-16le")
+ a.upcase!
+ a.should == "ÄÖÜ".encode("utf-16le")
+ end
+
it "updates string metadata for self" do
upcased = "aßet"
upcased.upcase!
@@ -109,6 +129,12 @@ describe "String#upcase!" do
a.upcase!(:ascii)
a.should == "AßET"
end
+
+ it "works for non-ascii-compatible encodings" do
+ a = "abc".encode("utf-16le")
+ a.upcase!(:ascii)
+ a.should == "ABC".encode("utf-16le")
+ end
end
describe "modifies self in place for full Unicode case mapping adapted for Turkic languages" do
@@ -161,8 +187,8 @@ describe "String#upcase!" do
a.should == "HELLO"
end
- it "raises a #{frozen_error_class} when self is frozen" do
- -> { "HeLlo".freeze.upcase! }.should raise_error(frozen_error_class)
- -> { "HELLO".freeze.upcase! }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when self is frozen" do
+ -> { "HeLlo".freeze.upcase! }.should raise_error(FrozenError)
+ -> { "HELLO".freeze.upcase! }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/core/string/uplus_spec.rb b/spec/ruby/core/string/uplus_spec.rb
index a7402b4549..038b283c90 100644
--- a/spec/ruby/core/string/uplus_spec.rb
+++ b/spec/ruby/core/string/uplus_spec.rb
@@ -5,7 +5,7 @@ describe 'String#+@' do
input = 'foo'.freeze
output = +input
- output.frozen?.should == false
+ output.should_not.frozen?
output.should == 'foo'
end
diff --git a/spec/ruby/core/string/valid_encoding_spec.rb b/spec/ruby/core/string/valid_encoding_spec.rb
index 09916df079..d5bf31710f 100644
--- a/spec/ruby/core/string/valid_encoding_spec.rb
+++ b/spec/ruby/core/string/valid_encoding_spec.rb
@@ -13,7 +13,7 @@ describe "String#valid_encoding?" do
end
it "returns true for all encodings self is valid in" do
- str = "\u{6754}"
+ str = "\xE6\x9D\x94"
str.force_encoding('BINARY').valid_encoding?.should be_true
str.force_encoding('UTF-8').valid_encoding?.should be_true
str.force_encoding('US-ASCII').valid_encoding?.should be_false
@@ -100,6 +100,14 @@ describe "String#valid_encoding?" do
str.force_encoding('UTF8-MAC').valid_encoding?.should be_true
end
+ ruby_version_is '3.0' do
+ it "returns true for IBM720 encoding self is valid in" do
+ str = "\xE6\x9D\x94"
+ str.force_encoding('IBM720').valid_encoding?.should be_true
+ str.force_encoding('CP720').valid_encoding?.should be_true
+ end
+ end
+
it "returns false if self is valid in one encoding, but invalid in the one it's tagged with" do
str = "\u{8765}"
str.valid_encoding?.should be_true
diff --git a/spec/ruby/core/struct/deconstruct_keys_spec.rb b/spec/ruby/core/struct/deconstruct_keys_spec.rb
new file mode 100644
index 0000000000..41b9c31e02
--- /dev/null
+++ b/spec/ruby/core/struct/deconstruct_keys_spec.rb
@@ -0,0 +1,70 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "2.7" do
+ describe "Struct#deconstruct_keys" do
+ it "returns a hash of attributes" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ end
+
+ it "requires one argument" do
+ struct = Struct.new(:x)
+ obj = struct.new(1)
+
+ -> {
+ obj.deconstruct_keys
+ }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
+ end
+
+ it "returns only specified keys" do
+ struct = Struct.new(:x, :y, :z)
+ s = struct.new(1, 2, 3)
+
+ s.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ s.deconstruct_keys([:x] ).should == {x: 1}
+ s.deconstruct_keys([] ).should == {}
+ end
+
+ it "accepts string attribute names" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2}
+ end
+
+ it "accepts argument position number as well but returns them as keys" do
+ struct = Struct.new(:x, :y, :z)
+ s = struct.new(10, 20, 30)
+
+ s.deconstruct_keys([0, 1, 2]).should == {0 => 10, 1 => 20, 2 => 30}
+ s.deconstruct_keys([0, 1] ).should == {0 => 10, 1 => 20}
+ s.deconstruct_keys([0] ).should == {0 => 10}
+ end
+
+ it "ignores not existing attribute names" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys([:a, :b, :c]).should == {}
+ end
+
+ it "accepts nil argument and return all the attributes" do
+ struct = Struct.new(:x, :y)
+ obj = struct.new(1, 2)
+
+ obj.deconstruct_keys(nil).should == {x: 1, y: 2}
+ end
+
+ it "raise TypeError if passed anything accept nil or array" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ -> { s.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/)
+ -> { s.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/)
+ end
+ end
+end
diff --git a/spec/ruby/core/struct/deconstruct_spec.rb b/spec/ruby/core/struct/deconstruct_spec.rb
new file mode 100644
index 0000000000..7518a40987
--- /dev/null
+++ b/spec/ruby/core/struct/deconstruct_spec.rb
@@ -0,0 +1,12 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "2.7" do
+ describe "Struct#deconstruct" do
+ it "returns an array of attribute values" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct.should == [1, 2]
+ end
+ end
+end
diff --git a/spec/ruby/core/struct/hash_spec.rb b/spec/ruby/core/struct/hash_spec.rb
index 71e8ccbd3a..d3c95fbe56 100644
--- a/spec/ruby/core/struct/hash_spec.rb
+++ b/spec/ruby/core/struct/hash_spec.rb
@@ -4,11 +4,11 @@ require_relative 'shared/accessor'
describe "Struct#hash" do
- it "returns the same fixnum for structs with the same content" do
+ it "returns the same integer for structs with the same content" do
[StructClasses::Ruby.new("1.8.6", "PPC"),
StructClasses::Car.new("Hugo", "Foo", "1972")].each do |stc|
stc.hash.should == stc.dup.hash
- stc.hash.should be_kind_of(Fixnum)
+ stc.hash.should be_kind_of(Integer)
end
end
@@ -19,6 +19,20 @@ describe "Struct#hash" do
car.hash.should == similar_car.hash
end
+ it "returns different hashes for structs with different values" do
+ s1 = StructClasses::Ruby.new('2.7.0', 'linux')
+ s2 = StructClasses::Ruby.new('2.7.0', 'macos')
+ s1.hash.should_not == s2.hash
+ end
+
+ it "returns different hashes for structs with different values when using keyword_init: true" do
+ key = :"1 non symbol member"
+ struct_class = Struct.new(key, keyword_init: true)
+ t1 = struct_class.new(key => 1)
+ t2 = struct_class.new(key => 2)
+ t1.hash.should_not == t2.hash
+ end
+
it "allows for overriding methods in an included module" do
mod = Module.new do
def hash
diff --git a/spec/ruby/core/struct/new_spec.rb b/spec/ruby/core/struct/new_spec.rb
index 564c49af01..bb814e7cd1 100644
--- a/spec/ruby/core/struct/new_spec.rb
+++ b/spec/ruby/core/struct/new_spec.rb
@@ -15,7 +15,7 @@ describe "Struct.new" do
second = nil
-> {
second = Struct.new('Person', :hair, :sex)
- }.should complain(/redefining constant/)
+ }.should complain(/constant/)
second.should == Struct::Person
first.members.should_not == second.members
@@ -62,16 +62,8 @@ describe "Struct.new" do
-> { Struct.new(:animal, ['chris', 'evan']) }.should raise_error(TypeError)
end
- ruby_version_is ""..."2.5" do
- it "raises a TypeError if an argument is a Hash" do
- -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError)
- end
- end
-
- ruby_version_is "2.5" do
- it "raises a ArgumentError if passed a Hash with an unknown key" do
- -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(ArgumentError)
- end
+ it "raises a ArgumentError if passed a Hash with an unknown key" do
+ -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(ArgumentError)
end
it "raises ArgumentError when there is a duplicate member" do
@@ -147,71 +139,69 @@ describe "Struct.new" do
end
end
- ruby_version_is "2.5" do
- context "keyword_init: true option" do
- before :all do
- @struct_with_kwa = Struct.new(:name, :legs, keyword_init: true)
- end
+ context "keyword_init: true option" do
+ before :all do
+ @struct_with_kwa = Struct.new(:name, :legs, keyword_init: true)
+ end
+
+ it "creates a class that accepts keyword arguments to initialize" do
+ obj = @struct_with_kwa.new(name: "elefant", legs: 4)
+ obj.name.should == "elefant"
+ obj.legs.should == 4
+ end
+
+ it "raises when there is a duplicate member" do
+ -> { Struct.new(:foo, :foo, keyword_init: true) }.should raise_error(ArgumentError, "duplicate member: foo")
+ end
- it "creates a class that accepts keyword arguments to initialize" do
- obj = @struct_with_kwa.new(name: "elefant", legs: 4)
+ describe "new class instantiation" do
+ it "accepts arguments as hash as well" do
+ obj = @struct_with_kwa.new({name: "elefant", legs: 4})
obj.name.should == "elefant"
obj.legs.should == 4
end
- it "raises when there is a duplicate member" do
- -> { Struct.new(:foo, :foo, keyword_init: true) }.should raise_error(ArgumentError, "duplicate member: foo")
+ it "allows missing arguments" do
+ obj = @struct_with_kwa.new(name: "elefant")
+ obj.name.should == "elefant"
+ obj.legs.should be_nil
end
- describe "new class instantiation" do
- it "accepts arguments as hash as well" do
- obj = @struct_with_kwa.new({name: "elefant", legs: 4})
- obj.name.should == "elefant"
- obj.legs.should == 4
- end
-
- it "allows missing arguments" do
- obj = @struct_with_kwa.new(name: "elefant")
- obj.name.should == "elefant"
- obj.legs.should be_nil
- end
-
- it "allows no arguments" do
- obj = @struct_with_kwa.new
- obj.name.should be_nil
- obj.legs.should be_nil
- end
+ it "allows no arguments" do
+ obj = @struct_with_kwa.new
+ obj.name.should be_nil
+ obj.legs.should be_nil
+ end
- it "raises ArgumentError when passed not declared keyword argument" do
- -> {
- @struct_with_kwa.new(name: "elefant", legs: 4, foo: "bar")
- }.should raise_error(ArgumentError, /unknown keywords: foo/)
- end
+ it "raises ArgumentError when passed not declared keyword argument" do
+ -> {
+ @struct_with_kwa.new(name: "elefant", legs: 4, foo: "bar")
+ }.should raise_error(ArgumentError, /unknown keywords: foo/)
+ end
- it "raises ArgumentError when passed a list of arguments" do
- -> {
- @struct_with_kwa.new("elefant", 4)
- }.should raise_error(ArgumentError, /wrong number of arguments/)
- end
+ it "raises ArgumentError when passed a list of arguments" do
+ -> {
+ @struct_with_kwa.new("elefant", 4)
+ }.should raise_error(ArgumentError, /wrong number of arguments/)
+ end
- it "raises ArgumentError when passed a single non-hash argument" do
- -> {
- @struct_with_kwa.new("elefant")
- }.should raise_error(ArgumentError, /wrong number of arguments/)
- end
+ it "raises ArgumentError when passed a single non-hash argument" do
+ -> {
+ @struct_with_kwa.new("elefant")
+ }.should raise_error(ArgumentError, /wrong number of arguments/)
end
end
+ end
- context "keyword_init: false option" do
- before :all do
- @struct_without_kwa = Struct.new(:name, :legs, keyword_init: false)
- end
+ context "keyword_init: false option" do
+ before :all do
+ @struct_without_kwa = Struct.new(:name, :legs, keyword_init: false)
+ end
- it "behaves like it does without :keyword_init option" do
- obj = @struct_without_kwa.new("elefant", 4)
- obj.name.should == "elefant"
- obj.legs.should == 4
- end
+ it "behaves like it does without :keyword_init option" do
+ obj = @struct_without_kwa.new("elefant", 4)
+ obj.name.should == "elefant"
+ obj.legs.should == 4
end
end
end
diff --git a/spec/ruby/core/symbol/all_symbols_spec.rb b/spec/ruby/core/symbol/all_symbols_spec.rb
index ef2b4f85e6..1e21809093 100644
--- a/spec/ruby/core/symbol/all_symbols_spec.rb
+++ b/spec/ruby/core/symbol/all_symbols_spec.rb
@@ -1,14 +1,19 @@
require_relative '../../spec_helper'
describe "Symbol.all_symbols" do
- it "returns an array containing all the Symbols in the symbol table" do
+ it "returns an array of Symbols" do
all_symbols = Symbol.all_symbols
all_symbols.should be_an_instance_of(Array)
- all_symbols.all? { |s| s.is_a?(Symbol) ? true : (p s; false) }.should == true
+ all_symbols.each { |s| s.should be_an_instance_of(Symbol) }
end
- it "returns an Array containing Symbols that have been created" do
+ it "includes symbols that are strongly referenced" do
symbol = "symbol_specs_#{rand(5_000_000)}".to_sym
Symbol.all_symbols.should include(symbol)
end
+
+ it "includes symbols that are referenced in source code but not yet executed" do
+ Symbol.all_symbols.any? { |s| s.to_s == 'symbol_specs_referenced_in_source_code' }.should be_true
+ :symbol_specs_referenced_in_source_code
+ end
end
diff --git a/spec/ruby/core/symbol/casecmp_spec.rb b/spec/ruby/core/symbol/casecmp_spec.rb
index b485101d63..80ea51e910 100644
--- a/spec/ruby/core/symbol/casecmp_spec.rb
+++ b/spec/ruby/core/symbol/casecmp_spec.rb
@@ -63,7 +63,7 @@ describe "Symbol#casecmp" do
:abc.casecmp("abc").should be_nil
end
- it "returns nil if other is a Fixnum" do
+ it "returns nil if other is an Integer" do
:abc.casecmp(1).should be_nil
end
diff --git a/spec/ruby/core/symbol/comparison_spec.rb b/spec/ruby/core/symbol/comparison_spec.rb
index 173a7da625..613177be05 100644
--- a/spec/ruby/core/symbol/comparison_spec.rb
+++ b/spec/ruby/core/symbol/comparison_spec.rb
@@ -40,7 +40,7 @@ describe "Symbol#<=>" do
(:abc <=> "abc").should be_nil
end
- it "returns nil if other is a Fixnum" do
+ it "returns nil if other is an Integer" do
(:abc <=> 1).should be_nil
end
diff --git a/spec/ruby/core/symbol/end_with_spec.rb b/spec/ruby/core/symbol/end_with_spec.rb
new file mode 100644
index 0000000000..77dc4caf71
--- /dev/null
+++ b/spec/ruby/core/symbol/end_with_spec.rb
@@ -0,0 +1,10 @@
+# -*- encoding: utf-8 -*-
+
+require_relative '../../spec_helper'
+require_relative '../../shared/string/end_with'
+
+ruby_version_is "2.7" do
+ describe "Symbol#end_with?" do
+ it_behaves_like :end_with, :to_sym
+ end
+end
diff --git a/spec/ruby/core/symbol/match_spec.rb b/spec/ruby/core/symbol/match_spec.rb
index d37155537b..41e058f977 100644
--- a/spec/ruby/core/symbol/match_spec.rb
+++ b/spec/ruby/core/symbol/match_spec.rb
@@ -34,6 +34,23 @@ describe "Symbol#match" do
:a.match(/(.)/)[0].should == 'a'
$1.should == "a"
end
+
+ describe "when passed a block" do
+ it "yields the MatchData" do
+ :abc.match(/./) {|m| ScratchPad.record m }
+ ScratchPad.recorded.should be_kind_of(MatchData)
+ end
+
+ it "returns the block result" do
+ :abc.match(/./) { :result }.should == :result
+ end
+
+ it "does not yield if there is no match" do
+ ScratchPad.record []
+ :b.match(/a/) {|m| ScratchPad << m }
+ ScratchPad.recorded.should == []
+ end
+ end
end
describe "Symbol#match?" do
diff --git a/spec/ruby/core/symbol/start_with_spec.rb b/spec/ruby/core/symbol/start_with_spec.rb
new file mode 100644
index 0000000000..f54b3e499e
--- /dev/null
+++ b/spec/ruby/core/symbol/start_with_spec.rb
@@ -0,0 +1,10 @@
+# -*- encoding: utf-8 -*-
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+require_relative '../../shared/string/start_with'
+
+ruby_version_is "2.7" do
+ describe "Symbol#start_with?" do
+ it_behaves_like :start_with, :to_sym
+ end
+end
diff --git a/spec/ruby/core/symbol/to_proc_spec.rb b/spec/ruby/core/symbol/to_proc_spec.rb
index 60e33d7cb8..e9261e6cdf 100644
--- a/spec/ruby/core/symbol/to_proc_spec.rb
+++ b/spec/ruby/core/symbol/to_proc_spec.rb
@@ -12,18 +12,42 @@ describe "Symbol#to_proc" do
:to_s.to_proc.call(obj).should == "Received #to_s"
end
- it "produces a proc with arity -1" do
- pr = :to_s.to_proc
- pr.arity.should == -1
+ ruby_version_is ""..."3.0" do
+ it "returns a Proc with #lambda? false" do
+ pr = :to_s.to_proc
+ pr.should_not.lambda?
+ end
+
+ it "produces a Proc with arity -1" do
+ pr = :to_s.to_proc
+ pr.arity.should == -1
+ end
+
+ it "produces a Proc that always returns [[:rest]] for #parameters" do
+ pr = :to_s.to_proc
+ pr.parameters.should == [[:rest]]
+ end
end
- it "raises an ArgumentError when calling #call on the Proc without receiver" do
- -> { :object_id.to_proc.call }.should raise_error(ArgumentError, "no receiver given")
+ ruby_version_is "3.0" do
+ it "returns a Proc with #lambda? true" do
+ pr = :to_s.to_proc
+ pr.should.lambda?
+ end
+
+ it "produces a Proc with arity -2" do
+ pr = :to_s.to_proc
+ pr.arity.should == -2
+ end
+
+ it "produces a Proc that always returns [[:req], [:rest]] for #parameters" do
+ pr = :to_s.to_proc
+ pr.parameters.should == [[:req], [:rest]]
+ end
end
- it "produces a proc that always returns [[:rest]] for #parameters" do
- pr = :to_s.to_proc
- pr.parameters.should == [[:rest]]
+ it "raises an ArgumentError when calling #call on the Proc without receiver" do
+ -> { :object_id.to_proc.call }.should raise_error(ArgumentError, "no receiver given")
end
it "passes along the block passed to Proc#call" do
@@ -38,4 +62,9 @@ describe "Symbol#to_proc" do
end
klass.new.to_proc.should == :value
end
+
+ it "produces a proc with source location nil" do
+ pr = :to_s.to_proc
+ pr.source_location.should == nil
+ end
end
diff --git a/spec/ruby/core/systemexit/success_spec.rb b/spec/ruby/core/systemexit/success_spec.rb
index 6d36509c80..ba2fd22ded 100644
--- a/spec/ruby/core/systemexit/success_spec.rb
+++ b/spec/ruby/core/systemexit/success_spec.rb
@@ -3,11 +3,11 @@ require_relative '../../spec_helper'
describe "SystemExit#success?" do
it "returns true when the status is 0" do
s = SystemExit.new 0
- s.success?.should == true
+ s.should.success?
end
it "returns false when the status is not 0" do
s = SystemExit.new 1
- s.success?.should == false
+ s.should_not.success?
end
end
diff --git a/spec/ruby/core/thread/alive_spec.rb b/spec/ruby/core/thread/alive_spec.rb
index d4ba149d87..c2f5f5371d 100644
--- a/spec/ruby/core/thread/alive_spec.rb
+++ b/spec/ruby/core/thread/alive_spec.rb
@@ -3,39 +3,39 @@ require_relative 'fixtures/classes'
describe "Thread#alive?" do
it "can check it's own status" do
- ThreadSpecs.status_of_current_thread.alive?.should == true
+ ThreadSpecs.status_of_current_thread.should.alive?
end
it "describes a running thread" do
- ThreadSpecs.status_of_running_thread.alive?.should == true
+ ThreadSpecs.status_of_running_thread.should.alive?
end
it "describes a sleeping thread" do
- ThreadSpecs.status_of_sleeping_thread.alive?.should == true
+ ThreadSpecs.status_of_sleeping_thread.should.alive?
end
it "describes a blocked thread" do
- ThreadSpecs.status_of_blocked_thread.alive?.should == true
+ ThreadSpecs.status_of_blocked_thread.should.alive?
end
it "describes a completed thread" do
- ThreadSpecs.status_of_completed_thread.alive?.should == false
+ ThreadSpecs.status_of_completed_thread.should_not.alive?
end
it "describes a killed thread" do
- ThreadSpecs.status_of_killed_thread.alive?.should == false
+ ThreadSpecs.status_of_killed_thread.should_not.alive?
end
it "describes a thread with an uncaught exception" do
- ThreadSpecs.status_of_thread_with_uncaught_exception.alive?.should == false
+ ThreadSpecs.status_of_thread_with_uncaught_exception.should_not.alive?
end
it "describes a dying running thread" do
- ThreadSpecs.status_of_dying_running_thread.alive?.should == true
+ ThreadSpecs.status_of_dying_running_thread.should.alive?
end
it "describes a dying sleeping thread" do
- ThreadSpecs.status_of_dying_sleeping_thread.alive?.should == true
+ ThreadSpecs.status_of_dying_sleeping_thread.should.alive?
end
it "returns true for a killed but still running thread" do
@@ -51,7 +51,7 @@ describe "Thread#alive?" do
ThreadSpecs.spin_until_sleeping(t)
t.kill
- t.alive?.should == true
+ t.should.alive?
exit = true
t.join
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 d38659c257..b0ae28beee 100644
--- a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
@@ -10,6 +10,13 @@ describe 'Thread::Backtrace::Location#absolute_path' do
@frame.absolute_path.should == File.realpath(__FILE__)
end
+ it 'returns an absolute path when using a relative main script path' do
+ script = fixture(__FILE__, 'absolute_path_main.rb')
+ Dir.chdir(File.dirname(script)) do
+ ruby_exe('absolute_path_main.rb').should == "absolute_path_main.rb\n#{script}\n"
+ end
+ end
+
context "when used in eval with a given filename" do
it "returns filename" do
code = "caller_locations(0)[0].absolute_path"
@@ -29,33 +36,48 @@ describe 'Thread::Backtrace::Location#absolute_path' do
end
end
- platform_is_not :windows do
- before :each do
- @file = fixture(__FILE__, "absolute_path.rb")
- @symlink = tmp("symlink.rb")
- File.symlink(@file, @symlink)
- ScratchPad.record []
+ context "when used in a core method" do
+ it "returns nil" do
+ location = nil
+ tap { location = caller_locations(1, 1)[0] }
+ location.label.should == "tap"
+ if location.path.start_with?("<internal:")
+ location.absolute_path.should == nil
+ else
+ location.absolute_path.should == File.realpath(__FILE__)
+ end
end
+ end
- after :each do
- rm_r @symlink
- end
+ context "canonicalization" do
+ platform_is_not :windows do
+ before :each do
+ @file = fixture(__FILE__, "absolute_path.rb")
+ @symlink = tmp("symlink.rb")
+ File.symlink(@file, @symlink)
+ ScratchPad.record []
+ end
- it "returns a canonical path without symlinks, even when __FILE__ does not" do
- realpath = File.realpath(@symlink)
- realpath.should_not == @symlink
+ after :each do
+ rm_r @symlink
+ end
- load @symlink
- ScratchPad.recorded.should == [@symlink, realpath]
- end
+ it "returns a canonical path without symlinks, even when __FILE__ does not" do
+ realpath = File.realpath(@symlink)
+ realpath.should_not == @symlink
+
+ load @symlink
+ ScratchPad.recorded.should == [@symlink, realpath]
+ end
- it "returns a canonical path without symlinks, even when __FILE__ is removed" do
- realpath = File.realpath(@symlink)
- realpath.should_not == @symlink
+ it "returns a canonical path without symlinks, even when __FILE__ is removed" do
+ realpath = File.realpath(@symlink)
+ realpath.should_not == @symlink
- ScratchPad << -> { rm_r(@symlink) }
- load @symlink
- ScratchPad.recorded.should == [@symlink, realpath]
+ ScratchPad << -> { rm_r(@symlink) }
+ load @symlink
+ ScratchPad.recorded.should == [@symlink, realpath]
+ end
end
end
end
diff --git a/spec/ruby/core/thread/backtrace/location/base_label_spec.rb b/spec/ruby/core/thread/backtrace/location/base_label_spec.rb
index 139a68e2c8..739f62f42f 100644
--- a/spec/ruby/core/thread/backtrace/location/base_label_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/base_label_spec.rb
@@ -19,4 +19,31 @@ describe 'Thread::Backtrace::Location#base_label' do
@frame.base_label.should == 'block_location'
end
end
+
+ it "is <module:A> for a module body" do
+ module ThreadBacktraceLocationSpecs
+ module ModuleLabel
+ ScratchPad.record caller_locations(0, 1)[0].base_label
+ end
+ end
+ ScratchPad.recorded.should == '<module:ModuleLabel>'
+ end
+
+ it "is <class:A> for a class body" do
+ module ThreadBacktraceLocationSpecs
+ class ClassLabel
+ ScratchPad.record caller_locations(0, 1)[0].base_label
+ end
+ end
+ ScratchPad.recorded.should == '<class:ClassLabel>'
+ end
+
+ it "is 'singleton class' for a singleton class body" do
+ module ThreadBacktraceLocationSpecs
+ class << Object.new
+ ScratchPad.record caller_locations(0, 1)[0].base_label
+ end
+ end
+ ScratchPad.recorded.should =~ /\A(singleton class|<singleton class>)\z/
+ end
end
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/absolute_path_main.rb b/spec/ruby/core/thread/backtrace/location/fixtures/absolute_path_main.rb
new file mode 100644
index 0000000000..d2b23393d4
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/absolute_path_main.rb
@@ -0,0 +1,2 @@
+puts __FILE__
+puts caller_locations(0)[0].absolute_path
diff --git a/spec/ruby/core/thread/backtrace/location/fixtures/path.rb b/spec/ruby/core/thread/backtrace/location/fixtures/path.rb
new file mode 100644
index 0000000000..fba34cb0bc
--- /dev/null
+++ b/spec/ruby/core/thread/backtrace/location/fixtures/path.rb
@@ -0,0 +1,2 @@
+ScratchPad << __FILE__
+ScratchPad << caller_locations(0)[0].path
diff --git a/spec/ruby/core/thread/backtrace/location/lineno_spec.rb b/spec/ruby/core/thread/backtrace/location/lineno_spec.rb
index dc93d32d75..d14cf17514 100644
--- a/spec/ruby/core/thread/backtrace/location/lineno_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/lineno_spec.rb
@@ -10,4 +10,14 @@ describe 'Thread::Backtrace::Location#lineno' do
it 'returns the absolute path of the call frame' do
@frame.lineno.should == @line
end
+
+ it 'should be the same line number as in #to_s, including for core methods' do
+ # Get the caller_locations from a call made into a core library method
+ locations = [:non_empty].map { caller_locations }[0]
+
+ locations.each do |location|
+ line_number = location.to_s[/:(\d+):/, 1]
+ location.lineno.should == Integer(line_number)
+ end
+ end
end
diff --git a/spec/ruby/core/thread/backtrace/location/path_spec.rb b/spec/ruby/core/thread/backtrace/location/path_spec.rb
index b1a3439747..7863c055d3 100644
--- a/spec/ruby/core/thread/backtrace/location/path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/path_spec.rb
@@ -86,4 +86,39 @@ describe 'Thread::Backtrace::Location#path' do
end
end
end
+
+ it 'should be the same path as in #to_s, including for core methods' do
+ # Get the caller_locations from a call made into a core library method
+ locations = [:non_empty].map { caller_locations }[0]
+
+ locations.each do |location|
+ filename = location.to_s[/^(.+):\d+:/, 1]
+ path = location.path
+
+ path.should == filename
+ end
+ end
+
+ context "canonicalization" do
+ platform_is_not :windows do
+ before :each do
+ @file = fixture(__FILE__, "path.rb")
+ @symlink = tmp("symlink.rb")
+ File.symlink(@file, @symlink)
+ ScratchPad.record []
+ end
+
+ after :each do
+ rm_r @symlink
+ end
+
+ it "returns a non-canonical path with symlinks, the same as __FILE__" do
+ realpath = File.realpath(@symlink)
+ realpath.should_not == @symlink
+
+ load @symlink
+ ScratchPad.recorded.should == [@symlink, @symlink]
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/thread/backtrace_locations_spec.rb b/spec/ruby/core/thread/backtrace_locations_spec.rb
index 66947f8ea6..ead4be2d8c 100644
--- a/spec/ruby/core/thread/backtrace_locations_spec.rb
+++ b/spec/ruby/core/thread/backtrace_locations_spec.rb
@@ -19,6 +19,48 @@ describe "Thread#backtrace_locations" do
locations.each { |loc| loc.should be_an_instance_of(Thread::Backtrace::Location) }
end
+ it "can be called with a number of locations to omit" do
+ locations1 = Thread.current.backtrace_locations
+ locations2 = Thread.current.backtrace_locations(2)
+ locations2.length.should == locations1[2..-1].length
+ locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
+ end
+
+ it "can be called with a maximum number of locations to return as second parameter" do
+ locations1 = Thread.current.backtrace_locations
+ locations2 = Thread.current.backtrace_locations(2, 3)
+ locations2.map(&:to_s).should == locations1[2..4].map(&:to_s)
+ end
+
+ it "can be called with a range" do
+ locations1 = Thread.current.backtrace_locations
+ locations2 = Thread.current.backtrace_locations(2..4)
+ locations2.map(&:to_s).should == locations1[2..4].map(&:to_s)
+ end
+
+ it "can be called with a range whose end is negative" do
+ Thread.current.backtrace_locations(2..-1).map(&:to_s).should == Thread.current.backtrace_locations[2..-1].map(&:to_s)
+ Thread.current.backtrace_locations(2..-2).map(&:to_s).should == Thread.current.backtrace_locations[2..-2].map(&:to_s)
+ end
+
+ ruby_version_is "2.6" do
+ it "can be called with an endless range" do
+ locations1 = Thread.current.backtrace_locations(0)
+ locations2 = Thread.current.backtrace_locations(eval("(2..)"))
+ locations2.map(&:to_s).should == locations1[2..-1].map(&:to_s)
+ end
+ end
+
+ it "returns nil if omitting more locations than available" do
+ Thread.current.backtrace_locations(100).should == nil
+ Thread.current.backtrace_locations(100..-1).should == nil
+ end
+
+ it "returns [] if omitting exactly the number of locations available" do
+ omit = Thread.current.backtrace_locations.length
+ Thread.current.backtrace_locations(omit).should == []
+ end
+
it "without argument is the same as showing all locations with 0..-1" do
Thread.current.backtrace_locations.map(&:to_s).should == Thread.current.backtrace_locations(0..-1).map(&:to_s)
end
diff --git a/spec/ruby/core/thread/backtrace_spec.rb b/spec/ruby/core/thread/backtrace_spec.rb
index 84ed574d5c..9001b1b7eb 100644
--- a/spec/ruby/core/thread/backtrace_spec.rb
+++ b/spec/ruby/core/thread/backtrace_spec.rb
@@ -32,4 +32,38 @@ describe "Thread#backtrace" do
t.join
backtrace.should be_kind_of(Array)
end
+
+ it "can be called with a number of locations to omit" do
+ locations1 = Thread.current.backtrace
+ locations2 = Thread.current.backtrace(2)
+ locations1[2..-1].length.should == locations2.length
+ locations1[2..-1].map(&:to_s).should == locations2.map(&:to_s)
+ end
+
+ it "can be called with a maximum number of locations to return as second parameter" do
+ locations1 = Thread.current.backtrace
+ locations2 = Thread.current.backtrace(2, 3)
+ locations1[2..4].map(&:to_s).should == locations2.map(&:to_s)
+ end
+
+ it "can be called with a range" do
+ locations1 = Thread.current.backtrace
+ locations2 = Thread.current.backtrace(2..4)
+ locations1[2..4].map(&:to_s).should == locations2.map(&:to_s)
+ end
+
+ it "can be called with a range whose end is negative" do
+ Thread.current.backtrace(2..-1).should == Thread.current.backtrace[2..-1]
+ Thread.current.backtrace(2..-2).should == Thread.current.backtrace[2..-2]
+ end
+
+ it "returns nil if omitting more locations than available" do
+ Thread.current.backtrace(100).should == nil
+ Thread.current.backtrace(100..-1).should == nil
+ end
+
+ it "returns [] if omitting exactly the number of locations available" do
+ omit = Thread.current.backtrace.length
+ Thread.current.backtrace(omit).should == []
+ end
end
diff --git a/spec/ruby/core/thread/element_set_spec.rb b/spec/ruby/core/thread/element_set_spec.rb
index d974b5e1c7..c7498f7ac9 100644
--- a/spec/ruby/core/thread/element_set_spec.rb
+++ b/spec/ruby/core/thread/element_set_spec.rb
@@ -6,13 +6,13 @@ describe "Thread#[]=" do
Thread.current[:value] = nil
end
- it "raises a #{frozen_error_class} if the thread is frozen" do
+ it "raises a FrozenError if the thread is frozen" do
Thread.new do
th = Thread.current
th.freeze
-> {
th[:foo] = "bar"
- }.should raise_error(frozen_error_class, /frozen/)
+ }.should raise_error(FrozenError, /frozen/)
end.join
end
diff --git a/spec/ruby/core/thread/exclusive_spec.rb b/spec/ruby/core/thread/exclusive_spec.rb
index ca8f105da4..37c4b19d1a 100644
--- a/spec/ruby/core/thread/exclusive_spec.rb
+++ b/spec/ruby/core/thread/exclusive_spec.rb
@@ -1,47 +1,49 @@
require_relative '../../spec_helper'
-describe "Thread.exclusive" do
- before :each do
- ScratchPad.clear
- $VERBOSE, @verbose = nil, $VERBOSE
- end
+ruby_version_is ''...'3.0' do
+ describe "Thread.exclusive" do
+ before :each do
+ ScratchPad.clear
+ $VERBOSE, @verbose = nil, $VERBOSE
+ end
- after :each do
- $VERBOSE = @verbose
- end
+ after :each do
+ $VERBOSE = @verbose
+ end
- it "yields to the block" do
- Thread.exclusive { ScratchPad.record true }
- ScratchPad.recorded.should == true
- end
+ it "yields to the block" do
+ Thread.exclusive { ScratchPad.record true }
+ ScratchPad.recorded.should == true
+ end
- it "returns the result of yielding" do
- Thread.exclusive { :result }.should == :result
- end
+ it "returns the result of yielding" do
+ Thread.exclusive { :result }.should == :result
+ end
- it "blocks the caller if another thread is also in an exclusive block" do
- m = Mutex.new
- q1 = Queue.new
- q2 = Queue.new
+ it "blocks the caller if another thread is also in an exclusive block" do
+ m = Mutex.new
+ q1 = Queue.new
+ q2 = Queue.new
- t = Thread.new {
- Thread.exclusive {
- q1.push :ready
- q2.pop
+ t = Thread.new {
+ Thread.exclusive {
+ q1.push :ready
+ q2.pop
+ }
}
- }
- q1.pop.should == :ready
+ q1.pop.should == :ready
- -> { Thread.exclusive { } }.should block_caller
+ -> { Thread.exclusive { } }.should block_caller
- q2.push :done
- t.join
- end
+ q2.push :done
+ t.join
+ end
- it "is not recursive" do
- Thread.exclusive do
- -> { Thread.exclusive { } }.should raise_error(ThreadError)
+ it "is not recursive" do
+ Thread.exclusive do
+ -> { Thread.exclusive { } }.should raise_error(ThreadError)
+ end
end
end
end
diff --git a/spec/ruby/core/thread/fetch_spec.rb b/spec/ruby/core/thread/fetch_spec.rb
index d71c938880..6b37d4cfc5 100644
--- a/spec/ruby/core/thread/fetch_spec.rb
+++ b/spec/ruby/core/thread/fetch_spec.rb
@@ -1,38 +1,36 @@
require_relative '../../spec_helper'
-ruby_version_is '2.5' do
- describe 'Thread#fetch' do
- describe 'with 2 arguments' do
- it 'returns the value of the fiber-local variable if value has been assigned' do
- th = Thread.new { Thread.current[:cat] = 'meow' }
- th.join
- th.fetch(:cat, true).should == 'meow'
- end
-
- it "returns the default value if fiber-local variable hasn't been assigned" do
- th = Thread.new {}
- th.join
- th.fetch(:cat, true).should == true
- end
+describe 'Thread#fetch' do
+ describe 'with 2 arguments' do
+ it 'returns the value of the fiber-local variable if value has been assigned' do
+ th = Thread.new { Thread.current[:cat] = 'meow' }
+ th.join
+ th.fetch(:cat, true).should == 'meow'
end
- describe 'with 1 argument' do
- it 'raises a KeyError when the Thread does not have a fiber-local variable of the same name' do
- th = Thread.new {}
- th.join
- -> { th.fetch(:cat) }.should raise_error(KeyError)
- end
+ it "returns the default value if fiber-local variable hasn't been assigned" do
+ th = Thread.new {}
+ th.join
+ th.fetch(:cat, true).should == true
+ end
+ end
- it 'returns the value of the fiber-local variable if value has been assigned' do
- th = Thread.new { Thread.current[:cat] = 'meow' }
- th.join
- th.fetch(:cat).should == 'meow'
- end
+ describe 'with 1 argument' do
+ it 'raises a KeyError when the Thread does not have a fiber-local variable of the same name' do
+ th = Thread.new {}
+ th.join
+ -> { th.fetch(:cat) }.should raise_error(KeyError)
end
- it 'raises an ArgumentError when not passed one or two arguments' do
- -> { Thread.current.fetch() }.should raise_error(ArgumentError)
- -> { Thread.current.fetch(1, 2, 3) }.should raise_error(ArgumentError)
+ it 'returns the value of the fiber-local variable if value has been assigned' do
+ th = Thread.new { Thread.current[:cat] = 'meow' }
+ th.join
+ th.fetch(:cat).should == 'meow'
end
end
+
+ it 'raises an ArgumentError when not passed one or two arguments' do
+ -> { Thread.current.fetch() }.should raise_error(ArgumentError)
+ -> { Thread.current.fetch(1, 2, 3) }.should raise_error(ArgumentError)
+ end
end
diff --git a/spec/ruby/core/thread/join_spec.rb b/spec/ruby/core/thread/join_spec.rb
index f3c5cdc1ed..213fe2e505 100644
--- a/spec/ruby/core/thread/join_spec.rb
+++ b/spec/ruby/core/thread/join_spec.rb
@@ -19,6 +19,11 @@ describe "Thread#join" do
t.join(0).should equal(t)
t.join(0.0).should equal(t)
t.join(nil).should equal(t)
+ end
+
+ it "raises TypeError if the argument is not a valid timeout" do
+ t = Thread.new { }
+ t.join
-> { t.join(:foo) }.should raise_error TypeError
-> { t.join("bar") }.should raise_error TypeError
end
diff --git a/spec/ruby/core/thread/list_spec.rb b/spec/ruby/core/thread/list_spec.rb
index a0bf831856..3c6f70c13e 100644
--- a/spec/ruby/core/thread/list_spec.rb
+++ b/spec/ruby/core/thread/list_spec.rb
@@ -43,11 +43,11 @@ describe "Thread.list" do
end
end
- while spawner.alive?
+ begin
Thread.list.each { |th|
th.should be_kind_of(Thread)
}
- end
+ end while spawner.alive?
threads = spawner.value
threads.each(&:join)
diff --git a/spec/ruby/core/thread/new_spec.rb b/spec/ruby/core/thread/new_spec.rb
index 3a57149381..47a836201c 100644
--- a/spec/ruby/core/thread/new_spec.rb
+++ b/spec/ruby/core/thread/new_spec.rb
@@ -58,13 +58,13 @@ describe "Thread.new" do
m2 = Mutex.new
t = Thread.new {
m1.lock
- m1.locked?.should == true
+ m1.should.locked?
m2.lock
- m2.locked?.should == true
+ m2.should.locked?
}
t.join
- m1.locked?.should == false
- m2.locked?.should == false
+ m1.should_not.locked?
+ m2.should_not.locked?
end
it "releases Mutexes held by the Thread when the Thread finishes, also with Mutex#synchronize" do
@@ -75,9 +75,9 @@ describe "Thread.new" do
m.lock
}
m.lock
- m.locked?.should == true
+ m.should.locked?
}
t.join
- m.locked?.should == false
+ m.should_not.locked?
end
end
diff --git a/spec/ruby/core/thread/raise_spec.rb b/spec/ruby/core/thread/raise_spec.rb
index 88a96d5f4e..27de3cc627 100644
--- a/spec/ruby/core/thread/raise_spec.rb
+++ b/spec/ruby/core/thread/raise_spec.rb
@@ -203,6 +203,6 @@ describe "Thread#raise on same thread" do
Thread.current.raise
end
end
- -> { t.value }.should raise_error(RuntimeError)
+ -> { t.value }.should raise_error(RuntimeError, '')
end
end
diff --git a/spec/ruby/core/thread/report_on_exception_spec.rb b/spec/ruby/core/thread/report_on_exception_spec.rb
index a6042ba759..bf50a167df 100644
--- a/spec/ruby/core/thread/report_on_exception_spec.rb
+++ b/spec/ruby/core/thread/report_on_exception_spec.rb
@@ -1,16 +1,8 @@
require_relative '../../spec_helper'
describe "Thread.report_on_exception" do
- ruby_version_is "2.4"..."2.5" do
- it "defaults to false" do
- ruby_exe("p Thread.report_on_exception").should == "false\n"
- end
- end
-
- ruby_version_is "2.5" do
- it "defaults to true" do
- ruby_exe("p Thread.report_on_exception").should == "true\n"
- end
+ it "defaults to true" do
+ ruby_exe("p Thread.report_on_exception").should == "true\n"
end
end
@@ -33,14 +25,12 @@ describe "Thread.report_on_exception=" do
end
describe "Thread#report_on_exception" do
- ruby_version_is "2.5" do
- it "returns true for the main Thread" do
- Thread.current.report_on_exception.should == true
- end
+ it "returns true for the main Thread" do
+ Thread.current.report_on_exception.should == true
+ end
- it "returns true for new Threads" do
- Thread.new { Thread.current.report_on_exception }.value.should == true
- end
+ it "returns true for new Threads" do
+ Thread.new { Thread.current.report_on_exception }.value.should == true
end
it "returns whether the Thread will print a backtrace if it exits with an exception" do
diff --git a/spec/ruby/core/thread/shared/to_s.rb b/spec/ruby/core/thread/shared/to_s.rb
index e47426cf3f..45c04af627 100644
--- a/spec/ruby/core/thread/shared/to_s.rb
+++ b/spec/ruby/core/thread/shared/to_s.rb
@@ -4,11 +4,13 @@ describe :thread_to_s, shared: true do
sep = ruby_version_is("2.7") ? " " : "@"
it "returns a description including file and line number" do
- Thread.new { "hello" }.send(@method).should =~ /^#<Thread:([^ ]*?)#{sep}#{Regexp.escape __FILE__}:#{__LINE__ } \w+>$/
+ thread, line = Thread.new { "hello" }, __LINE__
+ thread.join
+ thread.send(@method).should =~ /^#<Thread:([^ ]*?)#{sep}#{Regexp.escape __FILE__}:#{line} \w+>$/
end
it "has a binary encoding" do
- Thread.new { "hello" }.send(@method).encoding.should == Encoding::BINARY
+ ThreadSpecs.status_of_current_thread.send(@method).encoding.should == Encoding::BINARY
end
it "can check it's own status" do
diff --git a/spec/ruby/core/thread/stop_spec.rb b/spec/ruby/core/thread/stop_spec.rb
index 33cf8f7b5c..084ab46ef6 100644
--- a/spec/ruby/core/thread/stop_spec.rb
+++ b/spec/ruby/core/thread/stop_spec.rb
@@ -13,42 +13,42 @@ end
describe "Thread#stop?" do
it "can check it's own status" do
- ThreadSpecs.status_of_current_thread.stop?.should == false
+ ThreadSpecs.status_of_current_thread.should_not.stop?
end
it "describes a running thread" do
- ThreadSpecs.status_of_running_thread.stop?.should == false
+ ThreadSpecs.status_of_running_thread.should_not.stop?
end
it "describes a sleeping thread" do
- ThreadSpecs.status_of_sleeping_thread.stop?.should == true
+ ThreadSpecs.status_of_sleeping_thread.should.stop?
end
it "describes a blocked thread" do
- ThreadSpecs.status_of_blocked_thread.stop?.should == true
+ ThreadSpecs.status_of_blocked_thread.should.stop?
end
it "describes a completed thread" do
- ThreadSpecs.status_of_completed_thread.stop?.should == true
+ ThreadSpecs.status_of_completed_thread.should.stop?
end
it "describes a killed thread" do
- ThreadSpecs.status_of_killed_thread.stop?.should == true
+ ThreadSpecs.status_of_killed_thread.should.stop?
end
it "describes a thread with an uncaught exception" do
- ThreadSpecs.status_of_thread_with_uncaught_exception.stop?.should == true
+ ThreadSpecs.status_of_thread_with_uncaught_exception.should.stop?
end
it "describes a dying running thread" do
- ThreadSpecs.status_of_dying_running_thread.stop?.should == false
+ ThreadSpecs.status_of_dying_running_thread.should_not.stop?
end
it "describes a dying sleeping thread" do
- ThreadSpecs.status_of_dying_sleeping_thread.stop?.should == true
+ ThreadSpecs.status_of_dying_sleeping_thread.should.stop?
end
it "describes a dying thread after sleep" do
- ThreadSpecs.status_of_dying_thread_after_sleep.stop?.should == false
+ ThreadSpecs.status_of_dying_thread_after_sleep.should_not.stop?
end
end
diff --git a/spec/ruby/core/thread/to_s_spec.rb b/spec/ruby/core/thread/to_s_spec.rb
index 85976177dc..cb182a017f 100644
--- a/spec/ruby/core/thread/to_s_spec.rb
+++ b/spec/ruby/core/thread/to_s_spec.rb
@@ -1,8 +1,6 @@
require_relative '../../spec_helper'
require_relative 'shared/to_s'
-ruby_version_is "2.5" do
- describe "Thread#to_s" do
- it_behaves_like :thread_to_s, :to_s
- end
+describe "Thread#to_s" do
+ it_behaves_like :thread_to_s, :to_s
end
diff --git a/spec/ruby/core/time/_dump_spec.rb b/spec/ruby/core/time/_dump_spec.rb
index 6941a1531f..4dc1c43cd2 100644
--- a/spec/ruby/core/time/_dump_spec.rb
+++ b/spec/ruby/core/time/_dump_spec.rb
@@ -15,11 +15,11 @@ describe "Time#_dump" do
# http://redmine.ruby-lang.org/issues/show/627
it "preserves the GMT flag" do
- @t.gmt?.should == true
+ @t.should.gmt?
dump = @t.send(:_dump).unpack("VV").first
((dump >> 30) & 0x1).should == 1
- @local.gmt?.should == false
+ @local.should_not.gmt?
dump = @local.send(:_dump).unpack("VV").first
((dump >> 30) & 0x1).should == 0
end
diff --git a/spec/ruby/core/time/at_spec.rb b/spec/ruby/core/time/at_spec.rb
index 368eeb7fca..4ff38bbd21 100644
--- a/spec/ruby/core/time/at_spec.rb
+++ b/spec/ruby/core/time/at_spec.rb
@@ -14,7 +14,7 @@ describe "Time.at" do
end
it "returns a non-UTC Time" do
- Time.at(1184027924).utc?.should == false
+ Time.at(1184027924).should_not.utc?
end
it "returns a subclass instance on a Time subclass" do
@@ -54,12 +54,12 @@ describe "Time.at" do
it "returns a UTC time if the argument is UTC" do
t = Time.now.getgm
- Time.at(t).utc?.should == true
+ Time.at(t).should.utc?
end
it "returns a non-UTC time if the argument is non-UTC" do
t = Time.now
- Time.at(t).utc?.should == false
+ Time.at(t).should_not.utc?
end
it "returns a subclass instance" do
@@ -92,6 +92,12 @@ describe "Time.at" do
o.should_receive(:to_r).and_return(Rational(5, 2))
Time.at(o).should == Time.at(Rational(5, 2))
end
+
+ it "needs for the argument to respond to #to_int too" do
+ o = mock('rational-but-no-to_int')
+ o.should_receive(:to_r).and_return(Rational(5, 2))
+ -> { Time.at(o) }.should raise_error(TypeError)
+ end
end
end
@@ -144,60 +150,58 @@ describe "Time.at" do
end
end
- ruby_version_is "2.5" do
- describe "passed [Time, Numeric, format]" do
- context ":nanosecond format" do
- it "treats second argument as nanoseconds" do
- Time.at(0, 123456789, :nanosecond).nsec.should == 123456789
- end
+ describe "passed [Time, Numeric, format]" do
+ context ":nanosecond format" do
+ it "treats second argument as nanoseconds" do
+ Time.at(0, 123456789, :nanosecond).nsec.should == 123456789
end
+ end
- context ":nsec format" do
- it "treats second argument as nanoseconds" do
- Time.at(0, 123456789, :nsec).nsec.should == 123456789
- end
+ context ":nsec format" do
+ it "treats second argument as nanoseconds" do
+ Time.at(0, 123456789, :nsec).nsec.should == 123456789
end
+ end
- context ":microsecond format" do
- it "treats second argument as microseconds" do
- Time.at(0, 123456, :microsecond).nsec.should == 123456000
- end
+ context ":microsecond format" do
+ it "treats second argument as microseconds" do
+ Time.at(0, 123456, :microsecond).nsec.should == 123456000
end
+ end
- context ":usec format" do
- it "treats second argument as microseconds" do
- Time.at(0, 123456, :usec).nsec.should == 123456000
- end
+ context ":usec format" do
+ it "treats second argument as microseconds" do
+ Time.at(0, 123456, :usec).nsec.should == 123456000
end
+ end
- context ":millisecond format" do
- it "treats second argument as milliseconds" do
- Time.at(0, 123, :millisecond).nsec.should == 123000000
- end
+ context ":millisecond format" do
+ it "treats second argument as milliseconds" do
+ Time.at(0, 123, :millisecond).nsec.should == 123000000
end
+ end
- context "not supported format" do
- it "raises ArgumentError" do
- -> { Time.at(0, 123456, 2) }.should raise_error(ArgumentError)
- -> { Time.at(0, 123456, nil) }.should raise_error(ArgumentError)
- -> { Time.at(0, 123456, :invalid) }.should raise_error(ArgumentError)
- end
-
- it "does not try to convert format to Symbol with #to_sym" do
- format = "usec"
- format.should_not_receive(:to_sym)
- -> { Time.at(0, 123456, format) }.should raise_error(ArgumentError)
- end
+ context "not supported format" do
+ it "raises ArgumentError" do
+ -> { Time.at(0, 123456, 2) }.should raise_error(ArgumentError)
+ -> { Time.at(0, 123456, nil) }.should raise_error(ArgumentError)
+ -> { Time.at(0, 123456, :invalid) }.should raise_error(ArgumentError)
end
- it "supports Float second argument" do
- Time.at(0, 123456789.500, :nanosecond).nsec.should == 123456789
- Time.at(0, 123456789.500, :nsec).nsec.should == 123456789
- Time.at(0, 123456.500, :microsecond).nsec.should == 123456500
- Time.at(0, 123456.500, :usec).nsec.should == 123456500
- Time.at(0, 123.500, :millisecond).nsec.should == 123500000
+ it "does not try to convert format to Symbol with #to_sym" do
+ format = "usec"
+ format.should_not_receive(:to_sym)
+ -> { Time.at(0, 123456, format) }.should raise_error(ArgumentError)
end
end
+
+ it "supports Float second argument" do
+ Time.at(0, 123456789.500, :nanosecond).nsec.should == 123456789
+ Time.at(0, 123456789.500, :nsec).nsec.should == 123456789
+ Time.at(0, 123456.500, :microsecond).nsec.should == 123456500
+ Time.at(0, 123456.500, :usec).nsec.should == 123456500
+ Time.at(0, 123.500, :millisecond).nsec.should == 123500000
+ end
end
ruby_version_is "2.6" do
diff --git a/spec/ruby/core/time/ceil_spec.rb b/spec/ruby/core/time/ceil_spec.rb
index 29dcec5d72..86029554db 100644
--- a/spec/ruby/core/time/ceil_spec.rb
+++ b/spec/ruby/core/time/ceil_spec.rb
@@ -36,10 +36,11 @@ ruby_version_is "2.7" do
it "copies own timezone to the returning value" do
@time.zone.should == @time.ceil.zone
- with_timezone "JST-9" do
- time = Time.at 0, 1
- time.zone.should == time.ceil.zone
+ time = with_timezone "JST-9" do
+ Time.at 0, 1
end
+
+ time.zone.should == time.ceil.zone
end
end
end
diff --git a/spec/ruby/core/time/dup_spec.rb b/spec/ruby/core/time/dup_spec.rb
index ee2ff7dbba..5d6621beaa 100644
--- a/spec/ruby/core/time/dup_spec.rb
+++ b/spec/ruby/core/time/dup_spec.rb
@@ -7,7 +7,7 @@ describe "Time#dup" do
end
it "copies the gmt state flag" do
- Time.now.gmtime.dup.gmt?.should == true
+ Time.now.gmtime.dup.should.gmt?
end
it "returns an independent Time object" do
@@ -15,7 +15,7 @@ describe "Time#dup" do
t2 = t.dup
t.gmtime
- t2.gmt?.should == false
+ t2.should_not.gmt?
end
it "returns a subclass instance" do
diff --git a/spec/ruby/core/time/floor_spec.rb b/spec/ruby/core/time/floor_spec.rb
index 763ed1ba51..a19585b787 100644
--- a/spec/ruby/core/time/floor_spec.rb
+++ b/spec/ruby/core/time/floor_spec.rb
@@ -28,10 +28,11 @@ ruby_version_is "2.7" do
it "copies own timezone to the returning value" do
@time.zone.should == @time.floor.zone
- with_timezone "JST-9" do
- time = Time.at 0, 1
- time.zone.should == time.floor.zone
+ time = with_timezone "JST-9" do
+ Time.at 0, 1
end
+
+ time.zone.should == time.floor.zone
end
end
end
diff --git a/spec/ruby/core/time/friday_spec.rb b/spec/ruby/core/time/friday_spec.rb
index 27f9e1dbe5..8bee7f7558 100644
--- a/spec/ruby/core/time/friday_spec.rb
+++ b/spec/ruby/core/time/friday_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Time#friday?" do
it "returns true if time represents Friday" do
- Time.local(2000, 1, 7).friday?.should == true
+ Time.local(2000, 1, 7).should.friday?
end
it "returns false if time doesn't represent Friday" do
- Time.local(2000, 1, 1).friday?.should == false
+ Time.local(2000, 1, 1).should_not.friday?
end
end
diff --git a/spec/ruby/core/time/gmt_spec.rb b/spec/ruby/core/time/gmt_spec.rb
index 7e85749d5b..840f59e0e8 100644
--- a/spec/ruby/core/time/gmt_spec.rb
+++ b/spec/ruby/core/time/gmt_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
describe "Time#gmt?" do
it "returns true if time represents a time in UTC (GMT)" do
- Time.now.gmt?.should == false
- Time.now.gmtime.gmt?.should == true
+ Time.now.should_not.gmt?
+ Time.now.gmtime.should.gmt?
end
end
diff --git a/spec/ruby/core/time/hash_spec.rb b/spec/ruby/core/time/hash_spec.rb
index 577aaf9b0a..4f4d11a2cd 100644
--- a/spec/ruby/core/time/hash_spec.rb
+++ b/spec/ruby/core/time/hash_spec.rb
@@ -1,8 +1,8 @@
require_relative '../../spec_helper'
describe "Time#hash" do
- it "returns a Fixnum" do
- Time.at(100).hash.should be_an_instance_of(Fixnum)
+ it "returns an Integer" do
+ Time.at(100).hash.should be_an_instance_of(Integer)
end
it "is stable" do
diff --git a/spec/ruby/core/time/inspect_spec.rb b/spec/ruby/core/time/inspect_spec.rb
index 01e1dfdaa6..85133838e2 100644
--- a/spec/ruby/core/time/inspect_spec.rb
+++ b/spec/ruby/core/time/inspect_spec.rb
@@ -3,4 +3,19 @@ require_relative 'shared/inspect'
describe "Time#inspect" do
it_behaves_like :inspect, :inspect
+
+ ruby_version_is "2.7" do
+ it "preserves milliseconds" do
+ t = Time.utc(2007, 11, 1, 15, 25, 0, 123456)
+ t.inspect.should == "2007-11-01 15:25:00.123456 UTC"
+ end
+
+ it "formats nanoseconds as a Rational" do
+ t = Time.utc(2007, 11, 1, 15, 25, 0, 123456.789)
+ t.nsec.should == 123456789
+ t.strftime("%N").should == "123456789"
+
+ t.inspect.should == "2007-11-01 15:25:00 8483885939586761/68719476736000000 UTC"
+ end
+ end
end
diff --git a/spec/ruby/core/time/minus_spec.rb b/spec/ruby/core/time/minus_spec.rb
index e0fbf94cb0..995dac8462 100644
--- a/spec/ruby/core/time/minus_spec.rb
+++ b/spec/ruby/core/time/minus_spec.rb
@@ -79,11 +79,11 @@ describe "Time#-" do
end
it "returns a UTC time if self is UTC" do
- (Time.utc(2012) - 10).utc?.should == true
+ (Time.utc(2012) - 10).should.utc?
end
it "returns a non-UTC time if self is non-UTC" do
- (Time.local(2012) - 10).utc?.should == false
+ (Time.local(2012) - 10).should_not.utc?
end
it "returns a time with the same fixed offset as self" do
@@ -92,17 +92,17 @@ describe "Time#-" do
it "preserves time zone" do
time_with_zone = Time.now.utc
- time_with_zone.zone.should == (time_with_zone - 60*60).zone
+ time_with_zone.zone.should == (time_with_zone - 1).zone
time_with_zone = Time.now
- time_with_zone.zone.should == (time_with_zone - 60*60).zone
+ time_with_zone.zone.should == (time_with_zone - 1).zone
end
ruby_version_is "2.6" do
context "zone is a timezone object" do
it "preserves time zone" do
zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60))
- time = Time.new(2012, 1, 1, 12, 0, 0, zone) - 60*60
+ time = Time.new(2012, 1, 1, 12, 0, 0, zone) - 1
time.zone.should == zone
end
diff --git a/spec/ruby/core/time/monday_spec.rb b/spec/ruby/core/time/monday_spec.rb
index c5c43a5c3e..47ecaeb1db 100644
--- a/spec/ruby/core/time/monday_spec.rb
+++ b/spec/ruby/core/time/monday_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Time#monday?" do
it "returns true if time represents Monday" do
- Time.local(2000, 1, 3).monday?.should == true
+ Time.local(2000, 1, 3).should.monday?
end
it "returns false if time doesn't represent Monday" do
- Time.local(2000, 1, 1).monday?.should == false
+ Time.local(2000, 1, 1).should_not.monday?
end
end
diff --git a/spec/ruby/core/time/new_spec.rb b/spec/ruby/core/time/new_spec.rb
index 064e03f056..a4bb5b362c 100644
--- a/spec/ruby/core/time/new_spec.rb
+++ b/spec/ruby/core/time/new_spec.rb
@@ -15,7 +15,7 @@ end
describe "Time.new with a utc_offset argument" do
it "returns a non-UTC time" do
- Time.new(2000, 1, 1, 0, 0, 0, 0).utc?.should == false
+ Time.new(2000, 1, 1, 0, 0, 0, 0).should_not.utc?
end
it "returns a Time with a UTC offset of the specified number of Integer seconds" do
@@ -121,7 +121,7 @@ describe "Time.new with a utc_offset argument" do
end
end
-ruby_version_is "2.7" do
+ruby_version_is "2.6" do
describe "Time.new with a timezone argument" do
it "returns a Time in the timezone" do
zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60))
@@ -129,7 +129,7 @@ ruby_version_is "2.7" do
time.zone.should == zone
time.utc_offset.should == 5*3600+30*60
- ruby_version_is "2.7" do
+ ruby_version_is "3.0" do
time.wday.should == 6
time.yday.should == 1
end
diff --git a/spec/ruby/core/time/plus_spec.rb b/spec/ruby/core/time/plus_spec.rb
index 0a9984f180..c59d9a32bb 100644
--- a/spec/ruby/core/time/plus_spec.rb
+++ b/spec/ruby/core/time/plus_spec.rb
@@ -37,11 +37,11 @@ describe "Time#+" do
end
it "returns a UTC time if self is UTC" do
- (Time.utc(2012) + 10).utc?.should == true
+ (Time.utc(2012) + 10).should.utc?
end
it "returns a non-UTC time if self is non-UTC" do
- (Time.local(2012) + 10).utc?.should == false
+ (Time.local(2012) + 10).should_not.utc?
end
it "returns a time with the same fixed offset as self" do
@@ -50,17 +50,17 @@ describe "Time#+" do
it "preserves time zone" do
time_with_zone = Time.now.utc
- time_with_zone.zone.should == (time_with_zone + 60*60).zone
+ time_with_zone.zone.should == (time_with_zone + 1).zone
time_with_zone = Time.now
- time_with_zone.zone.should == (time_with_zone + 60*60).zone
+ time_with_zone.zone.should == (time_with_zone + 1).zone
end
ruby_version_is "2.6" do
context "zone is a timezone object" do
it "preserves time zone" do
zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60))
- time = Time.new(2012, 1, 1, 12, 0, 0, zone) + 60*60
+ time = Time.new(2012, 1, 1, 12, 0, 0, zone) + 1
time.zone.should == zone
end
diff --git a/spec/ruby/core/time/saturday_spec.rb b/spec/ruby/core/time/saturday_spec.rb
index 60ffea4198..0e51407366 100644
--- a/spec/ruby/core/time/saturday_spec.rb
+++ b/spec/ruby/core/time/saturday_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Time#saturday?" do
it "returns true if time represents Saturday" do
- Time.local(2000, 1, 1).saturday?.should == true
+ Time.local(2000, 1, 1).should.saturday?
end
it "returns false if time doesn't represent Saturday" do
- Time.local(2000, 1, 2).saturday?.should == false
+ Time.local(2000, 1, 2).should_not.saturday?
end
end
diff --git a/spec/ruby/core/time/shared/local.rb b/spec/ruby/core/time/shared/local.rb
index 997b7186f1..43f331c4c1 100644
--- a/spec/ruby/core/time/shared/local.rb
+++ b/spec/ruby/core/time/shared/local.rb
@@ -6,7 +6,6 @@ describe :time_local, shared: true do
end
end
-=begin
platform_is_not :windows do
describe "timezone changes" do
it "correctly adjusts the timezone change to 'CEST' on 'Europe/Amsterdam'" do
@@ -17,7 +16,6 @@ describe :time_local, shared: true do
end
end
end
-=end
end
describe :time_local_10_arg, shared: true do
diff --git a/spec/ruby/core/time/shared/now.rb b/spec/ruby/core/time/shared/now.rb
index d8e5ac9d50..80f66a1134 100644
--- a/spec/ruby/core/time/shared/now.rb
+++ b/spec/ruby/core/time/shared/now.rb
@@ -18,18 +18,16 @@ describe :time_now, shared: true do
end
end
- guard_not -> { platform_is :windows and ruby_version_is ""..."2.5" } do
- it "has at least microsecond precision" do
- times = []
- 10_000.times do
- times << Time.now.nsec
- end
-
- # The clock should not be less accurate than expected (times should
- # not all be a multiple of the next precision up, assuming precisions
- # are multiples of ten.)
- expected = 1_000
- times.select { |t| t % (expected * 10) == 0 }.size.should_not == times.size
+ it "has at least microsecond precision" do
+ times = []
+ 10_000.times do
+ times << Time.now.nsec
end
+
+ # The clock should not be less accurate than expected (times should
+ # not all be a multiple of the next precision up, assuming precisions
+ # are multiples of ten.)
+ expected = 1_000
+ times.select { |t| t % (expected * 10) == 0 }.size.should_not == times.size
end
end
diff --git a/spec/ruby/core/time/shared/to_i.rb b/spec/ruby/core/time/shared/to_i.rb
index 03497c700b..06c966b708 100644
--- a/spec/ruby/core/time/shared/to_i.rb
+++ b/spec/ruby/core/time/shared/to_i.rb
@@ -6,4 +6,11 @@ describe :time_to_i, shared: true do
it "doesn't return an actual number of seconds in time" do
Time.at(65.5).send(@method).should == 65
end
+
+ it "rounds fractional seconds toward zero" do
+ t = Time.utc(1960, 1, 1, 0, 0, 0, 999_999)
+
+ t.to_f.to_i.should == -315619199
+ t.to_i.should == -315619200
+ end
end
diff --git a/spec/ruby/core/time/subsec_spec.rb b/spec/ruby/core/time/subsec_spec.rb
index 583a26412b..0f2c4eb856 100644
--- a/spec/ruby/core/time/subsec_spec.rb
+++ b/spec/ruby/core/time/subsec_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Time#subsec" do
- it "returns 0 as a Fixnum for a Time with a whole number of seconds" do
+ it "returns 0 as an Integer for a Time with a whole number of seconds" do
Time.at(100).subsec.should eql(0)
end
diff --git a/spec/ruby/core/time/succ_spec.rb b/spec/ruby/core/time/succ_spec.rb
index e68e64b0cc..fa6343f8e2 100644
--- a/spec/ruby/core/time/succ_spec.rb
+++ b/spec/ruby/core/time/succ_spec.rb
@@ -1,38 +1,40 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+ruby_version_is ""..."3.0" do
+ require_relative '../../spec_helper'
+ require_relative 'fixtures/classes'
-describe "Time#succ" do
- it "returns a new time one second later than time" do
- suppress_warning {
- @result = Time.at(100).succ
- }
+ describe "Time#succ" do
+ it "returns a new time one second later than time" do
+ suppress_warning {
+ @result = Time.at(100).succ
+ }
- @result.should == Time.at(101)
- end
+ @result.should == Time.at(101)
+ end
- it "returns a new instance" do
- time = Time.at(100)
+ it "returns a new instance" do
+ time = Time.at(100)
- suppress_warning {
- @result = time.succ
- }
+ suppress_warning {
+ @result = time.succ
+ }
- @result.should_not equal time
- end
+ @result.should_not equal time
+ end
- it "is obsolete" do
- -> {
- Time.at(100).succ
- }.should complain(/Time#succ is obsolete/)
- end
+ it "is obsolete" do
+ -> {
+ Time.at(100).succ
+ }.should complain(/Time#succ is obsolete/)
+ end
- ruby_version_is "2.6" do
- context "zone is a timezone object" do
- it "preserves time zone" do
- zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60))
- time = Time.new(2012, 1, 1, 12, 0, 0, zone) - 60*60
+ ruby_version_is "2.6" do
+ context "zone is a timezone object" do
+ it "preserves time zone" do
+ zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60))
+ time = Time.new(2012, 1, 1, 12, 0, 0, zone) - 1
- time.zone.should == zone
+ time.zone.should == zone
+ end
end
end
end
diff --git a/spec/ruby/core/time/sunday_spec.rb b/spec/ruby/core/time/sunday_spec.rb
index 2285583579..0d46421132 100644
--- a/spec/ruby/core/time/sunday_spec.rb
+++ b/spec/ruby/core/time/sunday_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Time#sunday?" do
it "returns true if time represents Sunday" do
- Time.local(2000, 1, 2).sunday?.should == true
+ Time.local(2000, 1, 2).should.sunday?
end
it "returns false if time doesn't represent Sunday" do
- Time.local(2000, 1, 1).sunday?.should == false
+ Time.local(2000, 1, 1).should_not.sunday?
end
end
diff --git a/spec/ruby/core/time/thursday_spec.rb b/spec/ruby/core/time/thursday_spec.rb
index c82d517519..c11e79d2fa 100644
--- a/spec/ruby/core/time/thursday_spec.rb
+++ b/spec/ruby/core/time/thursday_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Time#thursday?" do
it "returns true if time represents Thursday" do
- Time.local(2000, 1, 6).thursday?.should == true
+ Time.local(2000, 1, 6).should.thursday?
end
it "returns false if time doesn't represent Thursday" do
- Time.local(2000, 1, 1).thursday?.should == false
+ Time.local(2000, 1, 1).should_not.thursday?
end
end
diff --git a/spec/ruby/core/time/tuesday_spec.rb b/spec/ruby/core/time/tuesday_spec.rb
index 7abbdc92c0..0e7b9e7506 100644
--- a/spec/ruby/core/time/tuesday_spec.rb
+++ b/spec/ruby/core/time/tuesday_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Time#tuesday?" do
it "returns true if time represents Tuesday" do
- Time.local(2000, 1, 4).tuesday?.should == true
+ Time.local(2000, 1, 4).should.tuesday?
end
it "returns false if time doesn't represent Tuesday" do
- Time.local(2000, 1, 1).tuesday?.should == false
+ Time.local(2000, 1, 1).should_not.tuesday?
end
end
diff --git a/spec/ruby/core/time/utc_spec.rb b/spec/ruby/core/time/utc_spec.rb
index 5074c8d54d..74c17a93d1 100644
--- a/spec/ruby/core/time/utc_spec.rb
+++ b/spec/ruby/core/time/utc_spec.rb
@@ -5,7 +5,7 @@ require_relative 'shared/time_params'
describe "Time#utc?" do
it "returns true if time represents a time in UTC (GMT)" do
- Time.now.utc?.should == false
+ Time.now.should_not.utc?
end
end
diff --git a/spec/ruby/core/time/wednesday_spec.rb b/spec/ruby/core/time/wednesday_spec.rb
index 6a52c3577b..cc686681d7 100644
--- a/spec/ruby/core/time/wednesday_spec.rb
+++ b/spec/ruby/core/time/wednesday_spec.rb
@@ -2,10 +2,10 @@ require_relative '../../spec_helper'
describe "Time#wednesday?" do
it "returns true if time represents Wednesday" do
- Time.local(2000, 1, 5).wednesday?.should == true
+ Time.local(2000, 1, 5).should.wednesday?
end
it "returns false if time doesn't represent Wednesday" do
- Time.local(2000, 1, 1).wednesday?.should == false
+ Time.local(2000, 1, 1).should_not.wednesday?
end
end
diff --git a/spec/ruby/core/tracepoint/binding_spec.rb b/spec/ruby/core/tracepoint/binding_spec.rb
index f37753602e..6a7ef5f85a 100644
--- a/spec/ruby/core/tracepoint/binding_spec.rb
+++ b/spec/ruby/core/tracepoint/binding_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint#binding' do
def test
@@ -8,6 +9,7 @@ describe 'TracePoint#binding' do
it 'return the generated binding object from event' do
bindings = []
TracePoint.new(:return) { |tp|
+ next unless TracePointSpec.target_thread?
bindings << tp.binding
}.enable {
test
diff --git a/spec/ruby/core/tracepoint/callee_id_spec.rb b/spec/ruby/core/tracepoint/callee_id_spec.rb
index d340290d8b..cc08a45504 100644
--- a/spec/ruby/core/tracepoint/callee_id_spec.rb
+++ b/spec/ruby/core/tracepoint/callee_id_spec.rb
@@ -7,6 +7,7 @@ describe "TracePoint#callee_id" do
obj = TracePointSpec::ClassWithMethodAlias.new
TracePoint.new(:call) do |tp|
+ next unless TracePointSpec.target_thread?
a << tp.callee_id
end.enable do
obj.m_alias
diff --git a/spec/ruby/core/tracepoint/defined_class_spec.rb b/spec/ruby/core/tracepoint/defined_class_spec.rb
index 72536e6a56..4593db6d1f 100644
--- a/spec/ruby/core/tracepoint/defined_class_spec.rb
+++ b/spec/ruby/core/tracepoint/defined_class_spec.rb
@@ -5,6 +5,7 @@ describe 'TracePoint#defined_class' do
it 'returns class or module of the method being called' do
last_class_name = nil
TracePoint.new(:call) do |tp|
+ next unless TracePointSpec.target_thread?
last_class_name = tp.defined_class
end.enable do
TracePointSpec::B.new.foo
diff --git a/spec/ruby/core/tracepoint/disable_spec.rb b/spec/ruby/core/tracepoint/disable_spec.rb
index 612ca3c25a..73a31b3b81 100644
--- a/spec/ruby/core/tracepoint/disable_spec.rb
+++ b/spec/ruby/core/tracepoint/disable_spec.rb
@@ -1,9 +1,11 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint#disable' do
it 'returns true if trace was enabled' do
called = false
trace = TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
called = true
end
@@ -25,6 +27,7 @@ describe 'TracePoint#disable' do
it 'returns false if trace was disabled' do
called = false
trace = TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
called = true
end
@@ -41,7 +44,7 @@ describe 'TracePoint#disable' do
begin
trace.disable { enabled = trace.enabled? }
enabled.should == false
- trace.enabled?.should == true
+ trace.should.enabled?
ensure
trace.disable
end
@@ -52,7 +55,7 @@ describe 'TracePoint#disable' do
trace.enable
begin
trace.disable { 42 }.should == 42
- trace.enabled?.should == true
+ trace.should.enabled?
ensure
trace.disable
end
@@ -65,7 +68,7 @@ describe 'TracePoint#disable' do
trace.disable do |*args|
args.should == []
end
- trace.enabled?.should == true
+ trace.should.enabled?
ensure
trace.disable
end
diff --git a/spec/ruby/core/tracepoint/enable_spec.rb b/spec/ruby/core/tracepoint/enable_spec.rb
index b0fe38c559..50fded90e4 100644
--- a/spec/ruby/core/tracepoint/enable_spec.rb
+++ b/spec/ruby/core/tracepoint/enable_spec.rb
@@ -1,20 +1,21 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint#enable' do
- # def test; end
-
describe 'without a block' do
- it 'returns true if trace was enabled' do
+ it 'returns false if trace was disabled' do
called = false
trace = TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
called = true
end
line_event = true
called.should == false
- trace.enable
+ ret = trace.enable
begin
+ ret.should == false
line_event = true
called.should == true
ensure
@@ -22,30 +23,27 @@ describe 'TracePoint#enable' do
end
end
- it 'returns false if trace was disabled' do
+ it 'returns true if trace was already enabled' do
called = false
trace = TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
called = true
end
- trace.enable.should == false
- begin
- line_event = true
- called.should == true
- ensure
- trace.disable
- end
-
- called = false
line_event = true
called.should == false
- trace.enable.should == false
+ ret = trace.enable
begin
+ ret.should == false
+
+ trace.enable.should == true
+
line_event = true
called.should == true
ensure
trace.disable
+ trace.should_not.enabled?
end
end
end
@@ -54,18 +52,43 @@ describe 'TracePoint#enable' do
it 'enables the trace object within a block' do
event_name = nil
TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
event_name = tp.event
end.enable { event_name.should equal(:line) }
end
+ it 'enables the trace object for any thread' do
+ threads = []
+ trace = TracePoint.new(:line) do |tp|
+ # Runs on purpose on any Thread
+ threads << Thread.current
+ end
+
+ thread = nil
+ trace.enable do
+ line_event = true
+ thread = Thread.new do
+ event_in_other_thread = true
+ end
+ thread.join
+ end
+
+ threads = threads.uniq
+ threads.should.include?(Thread.current)
+ threads.should.include?(thread)
+ end
+
it 'can accept arguments within a block but it should not yield arguments' do
event_name = nil
- trace = TracePoint.new(:line) { |tp| event_name = tp.event }
+ trace = TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
+ event_name = tp.event
+ end
trace.enable do |*args|
event_name.should equal(:line)
args.should == []
end
- trace.enabled?.should == false
+ trace.should_not.enabled?
end
it 'enables trace object on calling with a block if it was already enabled' do
@@ -87,12 +110,54 @@ describe 'TracePoint#enable' do
it 'disables the trace object outside the block' do
called = false
- trace = TracePoint.new(:line) { called = true }
+ trace = TracePoint.new(:line) do
+ next unless TracePointSpec.target_thread?
+ called = true
+ end
trace.enable {
line_event = true
}
called.should == true
- trace.enabled?.should == false
+ trace.should_not.enabled?
+ end
+ end
+
+ describe "when nested" do
+ before do
+ ruby_version_is ""..."3.0" do
+ @path_prefix = '@'
+ end
+
+ ruby_version_is "3.0" do
+ @path_prefix = ' '
+ end
+ end
+
+ it "enables both TracePoints but only calls the respective callbacks" do
+ called = false
+ first = TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
+ called = true
+ end
+
+ all = []
+ inspects = []
+ second = TracePoint.new(:line) { |tp|
+ next unless TracePointSpec.target_thread?
+ all << tp
+ inspects << tp.inspect
+ }
+
+ line = nil
+ first.enable do
+ second.enable do
+ line = __LINE__
+ end
+ end
+
+ all.uniq.should == [second]
+ inspects.uniq.should == ["#<TracePoint:line#{@path_prefix}#{__FILE__}:#{line}>"]
+ called.should == true
end
end
@@ -104,6 +169,7 @@ describe 'TracePoint#enable' do
it 'enables trace point for specific location' do
trace = TracePoint.new(:call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.method_id
end
@@ -121,6 +187,7 @@ describe 'TracePoint#enable' do
it 'traces all the events triggered in specified location' do
trace = TracePoint.new(:line, :call, :return, :b_call, :b_return) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.event
end
@@ -140,6 +207,7 @@ describe 'TracePoint#enable' do
it 'does not trace events in nested locations' do
trace = TracePoint.new(:call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.method_id
end
@@ -177,6 +245,7 @@ describe 'TracePoint#enable' do
end
trace = TracePoint.new(:b_call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.lineno
end
@@ -193,6 +262,7 @@ describe 'TracePoint#enable' do
describe 'option value' do
it 'accepts Method' do
trace = TracePoint.new(:call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.method_id
end
@@ -208,6 +278,7 @@ describe 'TracePoint#enable' do
it 'accepts UnboundMethod' do
trace = TracePoint.new(:call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.method_id
end
@@ -225,6 +296,7 @@ describe 'TracePoint#enable' do
it 'accepts Proc' do
trace = TracePoint.new(:b_call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.lineno
end
@@ -242,6 +314,7 @@ describe 'TracePoint#enable' do
it "raises ArgumentError if target object cannot trigger specified event" do
trace = TracePoint.new(:call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.method_id
end
@@ -255,8 +328,7 @@ describe 'TracePoint#enable' do
end
it "raises ArgumentError if passed not Method/UnboundMethod/Proc" do
- trace = TracePoint.new(:call) do |tp|
- end
+ trace = TracePoint.new(:call) {}
-> {
trace.enable(target: Object.new) do
@@ -266,8 +338,7 @@ describe 'TracePoint#enable' do
context "nested enabling and disabling" do
it "raises ArgumentError if trace point already enabled with target is re-enabled with target" do
- trace = TracePoint.new(:b_call) do
- end
+ trace = TracePoint.new(:b_call) {}
-> {
trace.enable(target: -> {}) do
@@ -278,8 +349,7 @@ describe 'TracePoint#enable' do
end
it "raises ArgumentError if trace point already enabled without target is re-enabled with target" do
- trace = TracePoint.new(:b_call) do
- end
+ trace = TracePoint.new(:b_call) {}
-> {
trace.enable do
@@ -290,8 +360,7 @@ describe 'TracePoint#enable' do
end
it "raises ArgumentError if trace point already enabled with target is re-enabled without target" do
- trace = TracePoint.new(:b_call) do
- end
+ trace = TracePoint.new(:b_call) {}
-> {
trace.enable(target: -> {}) do
@@ -302,8 +371,7 @@ describe 'TracePoint#enable' do
end
it "raises ArgumentError if trace point already enabled with target is disabled with block" do
- trace = TracePoint.new(:b_call) do
- end
+ trace = TracePoint.new(:b_call) {}
-> {
trace.enable(target: -> {}) do
@@ -315,10 +383,12 @@ describe 'TracePoint#enable' do
it "traces events when trace point with target is enabled in another trace point enabled without target" do
trace_outer = TracePoint.new(:b_call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << :outer
end
trace_inner = TracePoint.new(:b_call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << :inner
end
@@ -335,10 +405,12 @@ describe 'TracePoint#enable' do
it "traces events when trace point with target is enabled in another trace point enabled with target" do
trace_outer = TracePoint.new(:b_call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << :outer
end
trace_inner = TracePoint.new(:b_call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << :inner
end
@@ -355,10 +427,12 @@ describe 'TracePoint#enable' do
it "traces events when trace point without target is enabled in another trace point enabled with target" do
trace_outer = TracePoint.new(:b_call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << :outer
end
trace_inner = TracePoint.new(:b_call) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << :inner
end
@@ -382,6 +456,7 @@ describe 'TracePoint#enable' do
it "traces :line events only on specified line of code" do
trace = TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.lineno
end
@@ -401,8 +476,7 @@ describe 'TracePoint#enable' do
end
it "raises ArgumentError if :target option isn't specified" do
- trace = TracePoint.new(:line) do |tp|
- end
+ trace = TracePoint.new(:line) {}
-> {
trace.enable(target_line: 67) do
@@ -411,8 +485,7 @@ describe 'TracePoint#enable' do
end
it "raises ArgumentError if :line event isn't registered" do
- trace = TracePoint.new(:call) do |tp|
- end
+ trace = TracePoint.new(:call) {}
target = -> {
x = 1
@@ -429,8 +502,7 @@ describe 'TracePoint#enable' do
end
it "raises ArgumentError if :target_line value is out of target code lines range" do
- trace = TracePoint.new(:line) do |tp|
- end
+ trace = TracePoint.new(:line) {}
-> {
trace.enable(target_line: 1, target: -> { }) do
@@ -439,8 +511,7 @@ describe 'TracePoint#enable' do
end
it "raises TypeError if :target_line value couldn't be coerced to Integer" do
- trace = TracePoint.new(:line) do |tp|
- end
+ trace = TracePoint.new(:line) {}
-> {
trace.enable(target_line: Object.new, target: -> { }) do
@@ -449,8 +520,7 @@ describe 'TracePoint#enable' do
end
it "raises ArgumentError if :target_line value is negative" do
- trace = TracePoint.new(:line) do |tp|
- end
+ trace = TracePoint.new(:line) {}
-> {
trace.enable(target_line: -2, target: -> { }) do
@@ -460,6 +530,7 @@ describe 'TracePoint#enable' do
it "accepts value that could be coerced to Integer" do
trace = TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.target_thread?
ScratchPad << tp.lineno
end
diff --git a/spec/ruby/core/tracepoint/enabled_spec.rb b/spec/ruby/core/tracepoint/enabled_spec.rb
index 0167d32fb0..0e9566a02c 100644
--- a/spec/ruby/core/tracepoint/enabled_spec.rb
+++ b/spec/ruby/core/tracepoint/enabled_spec.rb
@@ -1,14 +1,15 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint#enabled?' do
it 'returns true when current status of the trace is enable' do
trace = TracePoint.new(:line) {}
trace.enable do
- trace.enabled?.should == true
+ trace.should.enabled?
end
end
it 'returns false when current status of the trace is disabled' do
- TracePoint.new(:line) {}.enabled?.should == false
+ TracePoint.new(:line) {}.should_not.enabled?
end
end
diff --git a/spec/ruby/core/tracepoint/eval_script_spec.rb b/spec/ruby/core/tracepoint/eval_script_spec.rb
index 1d8e425a9a..ccf7fb5975 100644
--- a/spec/ruby/core/tracepoint/eval_script_spec.rb
+++ b/spec/ruby/core/tracepoint/eval_script_spec.rb
@@ -13,6 +13,7 @@ ruby_version_is "2.6" do
CODE
TracePoint.new(:script_compiled) do |e|
+ next unless TracePointSpec.target_thread?
ScratchPad << e.eval_script
end.enable do
eval script
diff --git a/spec/ruby/core/tracepoint/event_spec.rb b/spec/ruby/core/tracepoint/event_spec.rb
index 019d0c3253..9dea24d125 100644
--- a/spec/ruby/core/tracepoint/event_spec.rb
+++ b/spec/ruby/core/tracepoint/event_spec.rb
@@ -5,6 +5,7 @@ describe 'TracePoint#event' do
it 'returns the type of event' do
event_name = nil
TracePoint.new(:end, :call) do |tp|
+ next unless TracePointSpec.target_thread?
event_name = tp.event
end.enable do
TracePointSpec.test
diff --git a/spec/ruby/core/tracepoint/fixtures/classes.rb b/spec/ruby/core/tracepoint/fixtures/classes.rb
index 49c70e1915..3ab1b00b16 100644
--- a/spec/ruby/core/tracepoint/fixtures/classes.rb
+++ b/spec/ruby/core/tracepoint/fixtures/classes.rb
@@ -1,4 +1,10 @@
module TracePointSpec
+ @thread = Thread.current
+
+ def self.target_thread?
+ Thread.current == @thread
+ end
+
class ClassWithMethodAlias
def m
end
diff --git a/spec/ruby/core/tracepoint/inspect_spec.rb b/spec/ruby/core/tracepoint/inspect_spec.rb
index 9ff1653ae8..06bed9c99a 100644
--- a/spec/ruby/core/tracepoint/inspect_spec.rb
+++ b/spec/ruby/core/tracepoint/inspect_spec.rb
@@ -2,27 +2,124 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe 'TracePoint#inspect' do
+ before do
+ ruby_version_is ""..."3.0" do
+ @path_prefix = '@'
+ end
+
+ ruby_version_is "3.0" do
+ @path_prefix = ' '
+ end
+ end
+
it 'returns a string containing a human-readable TracePoint status' do
- TracePoint.new(:line) {}.inspect.should ==
- '#<TracePoint:disabled>'
+ TracePoint.new(:line) {}.inspect.should == '#<TracePoint:disabled>'
end
it 'returns a String showing the event, path and line' do
inspect = nil
- line = __LINE__
- TracePoint.new(:line) { |tp| inspect = tp.inspect }.enable do
- inspect.should == "#<TracePoint:line@#{__FILE__}:#{line+2}>"
+ line = nil
+ TracePoint.new(:line) { |tp|
+ next unless TracePointSpec.target_thread?
+ inspect ||= tp.inspect
+ }.enable do
+ line = __LINE__
+ end
+
+ inspect.should == "#<TracePoint:line#{@path_prefix}#{__FILE__}:#{line}>"
+ end
+
+ it 'returns a String showing the event, method, path and line for a :call event' do
+ inspect = nil
+ line = nil
+ TracePoint.new(:call) { |tp|
+ next unless TracePointSpec.target_thread?
+ inspect ||= tp.inspect
+ }.enable do
+ line = __LINE__ + 1
+ def trace_point_spec_test_call; end
+ trace_point_spec_test_call
+ end
+
+ inspect.should == "#<TracePoint:call `trace_point_spec_test_call'#{@path_prefix}#{__FILE__}:#{line}>"
+ end
+
+ it 'returns a String showing the event, method, path and line for a :return event' do
+ inspect = nil
+ line = nil
+ TracePoint.new(:return) { |tp|
+ next unless TracePointSpec.target_thread?
+ inspect ||= tp.inspect
+ }.enable do
+ line = __LINE__ + 4
+ def trace_point_spec_test_return
+ a = 1
+ return a
+ end
+ trace_point_spec_test_return
+ end
+
+ inspect.should == "#<TracePoint:return `trace_point_spec_test_return'#{@path_prefix}#{__FILE__}:#{line}>"
+ end
+
+ it 'returns a String showing the event, method, path and line for a :c_call event' do
+ inspect = nil
+ line = nil
+ TracePoint.new(:c_call) { |tp|
+ next unless TracePointSpec.target_thread?
+ inspect ||= tp.inspect
+ }.enable do
+ line = __LINE__ + 1
+ [0, 1].max
end
+
+ inspect.should == "#<TracePoint:c_call `max'#{@path_prefix}#{__FILE__}:#{line}>"
end
it 'returns a String showing the event, path and line for a :class event' do
inspect = nil
- line = __LINE__
- TracePoint.new(:class) { |tp| inspect = tp.inspect }.enable do
+ line = nil
+ TracePoint.new(:class) { |tp|
+ next unless TracePointSpec.target_thread?
+ inspect ||= tp.inspect
+ }.enable do
+ line = __LINE__ + 1
class TracePointSpec::C
end
end
- inspect.should == "#<TracePoint:class@#{__FILE__}:#{line+2}>"
+ inspect.should == "#<TracePoint:class#{@path_prefix}#{__FILE__}:#{line}>"
+ end
+
+ it 'returns a String showing the event and thread for :thread_begin event' do
+ inspect = nil
+ thread = nil
+ thread_inspection = nil
+ TracePoint.new(:thread_begin) { |tp|
+ next unless Thread.current == thread
+ inspect ||= tp.inspect
+ }.enable do
+ thread = Thread.new {}
+ thread_inspection = thread.inspect
+ thread.join
+ end
+
+ inspect.should == "#<TracePoint:thread_begin #{thread_inspection}>"
+ end
+
+ it 'returns a String showing the event and thread for :thread_end event' do
+ inspect = nil
+ thread = nil
+ thread_inspection = nil
+ TracePoint.new(:thread_end) { |tp|
+ next unless Thread.current == thread
+ inspect ||= tp.inspect
+ }.enable do
+ thread = Thread.new {}
+ thread_inspection = thread.inspect
+ thread.join
+ end
+
+ inspect.should == "#<TracePoint:thread_end #{thread_inspection}>"
end
end
diff --git a/spec/ruby/core/tracepoint/lineno_spec.rb b/spec/ruby/core/tracepoint/lineno_spec.rb
index a4d7e77e8d..77b3ac8b54 100644
--- a/spec/ruby/core/tracepoint/lineno_spec.rb
+++ b/spec/ruby/core/tracepoint/lineno_spec.rb
@@ -1,10 +1,20 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint#lineno' do
it 'returns the line number of the event' do
lineno = nil
- TracePoint.new(:line) { |tp| lineno = tp.lineno }.enable do
- lineno.should == 7
+ TracePoint.new(:line) { |tp|
+ next unless TracePointSpec.target_thread?
+ lineno = tp.lineno
+ }.enable do
+ line_event = true
end
+ lineno.should == __LINE__ - 2
+ end
+
+ it 'raises RuntimeError if accessed from outside' do
+ tp = TracePoint.new(:line) {}
+ -> { tp.lineno }.should raise_error(RuntimeError, 'access from outside')
end
end
diff --git a/spec/ruby/core/tracepoint/method_id_spec.rb b/spec/ruby/core/tracepoint/method_id_spec.rb
index 82254d1299..43e23248b7 100644
--- a/spec/ruby/core/tracepoint/method_id_spec.rb
+++ b/spec/ruby/core/tracepoint/method_id_spec.rb
@@ -1,12 +1,14 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint#method_id' do
- def test; end
-
it 'returns the name at the definition of the method being called' do
method_name = nil
- TracePoint.new(:call) { |tp| method_name = tp.method_id}.enable do
- test
+ TracePoint.new(:call) { |tp|
+ next unless TracePointSpec.target_thread?
+ method_name = tp.method_id
+ }.enable do
+ TracePointSpec.test
method_name.should equal(:test)
end
end
diff --git a/spec/ruby/core/tracepoint/new_spec.rb b/spec/ruby/core/tracepoint/new_spec.rb
index 916d826fdf..e53c2b04a2 100644
--- a/spec/ruby/core/tracepoint/new_spec.rb
+++ b/spec/ruby/core/tracepoint/new_spec.rb
@@ -8,7 +8,10 @@ describe 'TracePoint.new' do
it 'includes :line event when event is not specified' do
event_name = nil
- TracePoint.new() { |tp| event_name = tp.event }.enable do
+ TracePoint.new { |tp|
+ next unless TracePointSpec.target_thread?
+ event_name = tp.event
+ }.enable do
event_name.should equal(:line)
event_name = nil
@@ -25,7 +28,10 @@ describe 'TracePoint.new' do
event_name = nil
(o = mock('line')).should_receive(:to_sym).and_return(:line)
- TracePoint.new(o) { |tp| event_name = tp.event }.enable do
+ TracePoint.new(o) { |tp|
+ next unless TracePointSpec.target_thread?
+ event_name = tp.event
+ }.enable do
line_event = true
event_name.should == :line
end
@@ -34,6 +40,7 @@ describe 'TracePoint.new' do
it 'includes multiple events when multiple event names are passed as params' do
event_name = nil
TracePoint.new(:end, :call) do |tp|
+ next unless TracePointSpec.target_thread?
event_name = tp.event
end.enable do
TracePointSpec.test
@@ -49,16 +56,14 @@ describe 'TracePoint.new' do
it 'raises a TypeError when the given object is not a string/symbol' do
o = mock('123')
- -> { TracePoint.new(o) {}}.should raise_error(TypeError)
+ -> { TracePoint.new(o) {} }.should raise_error(TypeError)
o.should_receive(:to_sym).and_return(123)
- -> { TracePoint.new(o) {}}.should raise_error(TypeError)
+ -> { TracePoint.new(o) {} }.should raise_error(TypeError)
end
- ruby_version_is "2.5" do
- it 'expects to be called with a block' do
- -> { TracePoint.new(:line) }.should raise_error(ArgumentError, "must be called with a block")
- end
+ it 'expects to be called with a block' do
+ -> { TracePoint.new(:line) }.should raise_error(ArgumentError, "must be called with a block")
end
it "raises a Argument error when the given argument doesn't match an event name" do
diff --git a/spec/ruby/core/tracepoint/parameters_spec.rb b/spec/ruby/core/tracepoint/parameters_spec.rb
index f901c184f4..3a2cdd7750 100644
--- a/spec/ruby/core/tracepoint/parameters_spec.rb
+++ b/spec/ruby/core/tracepoint/parameters_spec.rb
@@ -1,11 +1,15 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
ruby_version_is "2.6" do
describe 'TracePoint#parameters' do
it 'returns the parameters of block' do
f = proc {|x, y, z| }
parameters = nil
- TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
+ TracePoint.new(:b_call) { |tp|
+ next unless TracePointSpec.target_thread?
+ parameters = tp.parameters
+ }.enable do
f.call
parameters.should == [[:opt, :x], [:opt, :y], [:opt, :z]]
end
@@ -14,7 +18,10 @@ ruby_version_is "2.6" do
it 'returns the parameters of lambda block' do
f = -> x, y, z { }
parameters = nil
- TracePoint.new(:b_call) {|tp| parameters = tp.parameters }.enable do
+ TracePoint.new(:b_call) { |tp|
+ next unless TracePointSpec.target_thread?
+ parameters = tp.parameters
+ }.enable do
f.call(1, 2, 3)
parameters.should == [[:req, :x], [:req, :y], [:req, :z]]
end
diff --git a/spec/ruby/core/tracepoint/path_spec.rb b/spec/ruby/core/tracepoint/path_spec.rb
index 1e31c1bb68..5b6c6d4cfc 100644
--- a/spec/ruby/core/tracepoint/path_spec.rb
+++ b/spec/ruby/core/tracepoint/path_spec.rb
@@ -1,18 +1,26 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint#path' do
it 'returns the path of the file being run' do
path = nil
- TracePoint.new(:line) { |tp| path = tp.path }.enable do
- path.should == "#{__FILE__}"
+ TracePoint.new(:line) { |tp|
+ next unless TracePointSpec.target_thread?
+ path = tp.path
+ }.enable do
+ line_event = true
end
+ path.should == "#{__FILE__}"
end
it 'equals (eval) inside an eval for :end event' do
path = nil
- TracePoint.new(:end) { |tp| path = tp.path }.enable do
+ TracePoint.new(:end) { |tp|
+ next unless TracePointSpec.target_thread?
+ path = tp.path
+ }.enable do
eval("module TracePointSpec; end")
- path.should == '(eval)'
end
+ path.should == '(eval)'
end
end
diff --git a/spec/ruby/core/tracepoint/raised_exception_spec.rb b/spec/ruby/core/tracepoint/raised_exception_spec.rb
index 450717b958..ca2f50abb3 100644
--- a/spec/ruby/core/tracepoint/raised_exception_spec.rb
+++ b/spec/ruby/core/tracepoint/raised_exception_spec.rb
@@ -1,9 +1,13 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint#raised_exception' do
it 'returns value from exception raised on the :raise event' do
raised_exception, error_result = nil
- trace = TracePoint.new(:raise) { |tp| raised_exception = tp.raised_exception }
+ trace = TracePoint.new(:raise) { |tp|
+ next unless TracePointSpec.target_thread?
+ raised_exception = tp.raised_exception
+ }
trace.enable do
begin
raise StandardError
diff --git a/spec/ruby/core/tracepoint/return_value_spec.rb b/spec/ruby/core/tracepoint/return_value_spec.rb
index f0ed86bd00..e84c7dd762 100644
--- a/spec/ruby/core/tracepoint/return_value_spec.rb
+++ b/spec/ruby/core/tracepoint/return_value_spec.rb
@@ -1,11 +1,15 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint#return_value' do
def test; 'test' end
it 'returns value from :return event' do
trace_value = nil
- TracePoint.new(:return) { |tp| trace_value = tp.return_value}.enable do
+ TracePoint.new(:return) { |tp|
+ next unless TracePointSpec.target_thread?
+ trace_value = tp.return_value
+ }.enable do
test
trace_value.should == 'test'
end
diff --git a/spec/ruby/core/tracepoint/self_spec.rb b/spec/ruby/core/tracepoint/self_spec.rb
index 8bfd09301e..2098860e59 100644
--- a/spec/ruby/core/tracepoint/self_spec.rb
+++ b/spec/ruby/core/tracepoint/self_spec.rb
@@ -4,14 +4,20 @@ require_relative 'fixtures/classes'
describe 'TracePoint#self' do
it 'return the trace object from event' do
trace = nil
- TracePoint.new(:line) { |tp| trace = tp.self }.enable do
+ TracePoint.new(:line) { |tp|
+ next unless TracePointSpec.target_thread?
+ trace = tp.self
+ }.enable do
trace.equal?(self).should be_true
end
end
it 'return the class object from a class event' do
trace = nil
- TracePoint.new(:class) { |tp| trace = tp.self }.enable do
+ TracePoint.new(:class) { |tp|
+ next unless TracePointSpec.target_thread?
+ trace = tp.self
+ }.enable do
class TracePointSpec::C
end
end
diff --git a/spec/ruby/core/tracepoint/trace_spec.rb b/spec/ruby/core/tracepoint/trace_spec.rb
index ea6c85bcc5..167f594bb9 100644
--- a/spec/ruby/core/tracepoint/trace_spec.rb
+++ b/spec/ruby/core/tracepoint/trace_spec.rb
@@ -1,9 +1,10 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
describe 'TracePoint.trace' do
it 'activates the trace automatically' do
trace = TracePoint.trace(:line) {}
- trace.enabled?.should == true
+ trace.should.enabled?
trace.disable
end
end
diff --git a/spec/ruby/core/true/case_compare_spec.rb b/spec/ruby/core/true/case_compare_spec.rb
new file mode 100644
index 0000000000..dee6dd0227
--- /dev/null
+++ b/spec/ruby/core/true/case_compare_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+
+describe "TrueClass#===" do
+ it "returns true for true" do
+ (true === true).should == true
+ end
+
+ it "returns false for non-true object" do
+ (true === 1).should == false
+ (true === "").should == false
+ (true === Object).should == false
+ end
+end
diff --git a/spec/ruby/core/true/to_s_spec.rb b/spec/ruby/core/true/to_s_spec.rb
index 68b0052c5d..f26cd138e2 100644
--- a/spec/ruby/core/true/to_s_spec.rb
+++ b/spec/ruby/core/true/to_s_spec.rb
@@ -7,7 +7,7 @@ describe "TrueClass#to_s" do
ruby_version_is "2.7" do
it "returns a frozen string" do
- true.to_s.frozen?.should == true
+ true.to_s.should.frozen?
end
it "always returns the same string" do
diff --git a/spec/ruby/core/unboundmethod/shared/to_s.rb b/spec/ruby/core/unboundmethod/shared/to_s.rb
index 3987611d3f..38503c3c60 100644
--- a/spec/ruby/core/unboundmethod/shared/to_s.rb
+++ b/spec/ruby/core/unboundmethod/shared/to_s.rb
@@ -22,4 +22,13 @@ describe :unboundmethod_to_s, shared: true do
@from_module.send(@method).should =~ /\bUnboundMethodSpecs::Mod\b/
@from_method.send(@method).should =~ /\bUnboundMethodSpecs::Methods\b/
end
+
+ it "returns a String including all details" do
+ @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
+ @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
+ end
+
+ it "does not show the defining module if it is the same as the origin" do
+ UnboundMethodSpecs::A.instance_method(:baz).send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::A#baz"
+ end
end
diff --git a/spec/ruby/core/unboundmethod/source_location_spec.rb b/spec/ruby/core/unboundmethod/source_location_spec.rb
index b5e6413816..96933a5d40 100644
--- a/spec/ruby/core/unboundmethod/source_location_spec.rb
+++ b/spec/ruby/core/unboundmethod/source_location_spec.rb
@@ -12,9 +12,9 @@ describe "UnboundMethod#source_location" do
file.should == File.realpath('../fixtures/classes.rb', __FILE__)
end
- it "sets the last value to a Fixnum representing the line on which the method was defined" do
+ it "sets the last value to an Integer representing the line on which the method was defined" do
line = @method.source_location.last
- line.should be_an_instance_of(Fixnum)
+ line.should be_an_instance_of(Integer)
line.should == 5
end
diff --git a/spec/ruby/core/warning/element_reference_spec.rb b/spec/ruby/core/warning/element_reference_spec.rb
new file mode 100644
index 0000000000..c3bf06a95b
--- /dev/null
+++ b/spec/ruby/core/warning/element_reference_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+ruby_version_is '2.7.2' do
+ describe "Warning.[]" do
+ it "returns default values for categories :deprecated and :experimental" do
+ ruby_exe('p Warning[:deprecated]').chomp.should == "false"
+ ruby_exe('p Warning[:experimental]').chomp.should == "true"
+ end
+
+ it "raises for unknown category" do
+ -> { Warning[:noop] }.should raise_error(ArgumentError, /unknown category: noop/)
+ end
+ end
+end
diff --git a/spec/ruby/core/warning/element_set_spec.rb b/spec/ruby/core/warning/element_set_spec.rb
new file mode 100644
index 0000000000..b21436d3c7
--- /dev/null
+++ b/spec/ruby/core/warning/element_set_spec.rb
@@ -0,0 +1,31 @@
+require_relative '../../spec_helper'
+
+ruby_version_is '2.7' do
+ describe "Warning.[]=" do
+ it "emits and suppresses warnings for :deprecated" do
+ ruby_exe('Warning[:deprecated] = true; $; = ""', args: "2>&1").should =~ /is deprecated/
+ ruby_exe('Warning[:deprecated] = false; $; = ""', args: "2>&1").should == ""
+ end
+
+ describe ":experimental" do
+ before do
+ ruby_version_is ""..."3.0" do
+ @src = 'case [0, 1]; in [a, b]; end'
+ end
+
+ ruby_version_is "3.0" do
+ @src = '[0, 1] => [a, b]'
+ end
+ end
+
+ it "emits and suppresses warnings for :experimental" do
+ ruby_exe("Warning[:experimental] = true; eval('#{@src}')", args: "2>&1").should =~ /is experimental/
+ ruby_exe("Warning[:experimental] = false; eval('#{@src}')", args: "2>&1").should == ""
+ end
+ end
+
+ it "raises for unknown category" do
+ -> { Warning[:noop] = false }.should raise_error(ArgumentError, /unknown category: noop/)
+ end
+ end
+end
diff --git a/spec/ruby/core/warning/warn_spec.rb b/spec/ruby/core/warning/warn_spec.rb
index 7daf6323c3..2ded6a109d 100644
--- a/spec/ruby/core/warning/warn_spec.rb
+++ b/spec/ruby/core/warning/warn_spec.rb
@@ -51,7 +51,32 @@ describe "Warning.warn" do
end
end
- ruby_version_is "2.5" do
+
+ ruby_version_is '3.0' do
+ it "is called by Kernel.warn with nil category keyword" do
+ Warning.should_receive(:warn).with("Chunky bacon!\n", category: nil)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!")
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+
+ it "is called by Kernel.warn with given category keyword converted to a symbol" do
+ Warning.should_receive(:warn).with("Chunky bacon!\n", category: :deprecated)
+ verbose = $VERBOSE
+ $VERBOSE = false
+ begin
+ Kernel.warn("Chunky bacon!", category: 'deprecated')
+ ensure
+ $VERBOSE = verbose
+ end
+ end
+ end
+
+ ruby_version_is ''...'3.0' do
it "is called by Kernel.warn" do
Warning.should_receive(:warn).with("Chunky bacon!\n")
verbose = $VERBOSE
diff --git a/spec/ruby/default.mspec b/spec/ruby/default.mspec
index 6fd6d2bf9c..a0dc69c03d 100644
--- a/spec/ruby/default.mspec
+++ b/spec/ruby/default.mspec
@@ -45,5 +45,6 @@ class MSpecScript
set :toplevel_constants_excludes, [
/\wSpecs?$/,
/^CS_CONST/,
+ /^CSL_CONST/,
]
end
diff --git a/spec/ruby/fixtures/code_loading.rb b/spec/ruby/fixtures/code_loading.rb
index d6cf0edb47..decd56a358 100644
--- a/spec/ruby/fixtures/code_loading.rb
+++ b/spec/ruby/fixtures/code_loading.rb
@@ -12,7 +12,22 @@ module CodeLoadingSpecs
end
end
+ def self.preload_rubygems
+ # Require RubyGems eagerly, to ensure #require is already the RubyGems
+ # version and RubyGems is only loaded once, before starting #require/#autoload specs
+ # which snapshot $LOADED_FEATURES and could cause RubyGems to load twice.
+ # #require specs also snapshot #require, and could end up redefining #require as the original core Kernel#require.
+ @rubygems ||= begin
+ require "rubygems"
+ true
+ rescue LoadError
+ true
+ end
+ end
+
def self.spec_setup
+ preload_rubygems
+
@saved_loaded_features = $LOADED_FEATURES.clone
@saved_load_path = $LOAD_PATH.clone
ScratchPad.record []
diff --git a/spec/ruby/fixtures/constants.rb b/spec/ruby/fixtures/constants.rb
index e5b20596ef..37271ddcc8 100644
--- a/spec/ruby/fixtures/constants.rb
+++ b/spec/ruby/fixtures/constants.rb
@@ -1,7 +1,7 @@
# Contains all static code examples of all constants behavior in language and
# library specs. The specs include language/constants_spec.rb and the specs
-# for Module#const_defined?, Module#const_get, Module#const_set,
-# Module#remove_const, Module#const_missing and Module#constants.
+# for Module#const_defined?, Module#const_get, Module#const_set, Module#remove_const,
+# Module#const_source_location, Module#const_missing and Module#constants.
#
# Rather than defining a class structure for each example, a canonical set of
# classes is used along with numerous constants, in most cases, a unique
@@ -28,14 +28,17 @@
# for completeness. No other constant of this name should be defined in the
# specs.
CS_CONST1 = :const1 # only defined here
+CS_CONST1_LINE = __LINE__ - 1
module ConstantSpecs
# Included at toplevel
module ModuleA
CS_CONST10 = :const10_1
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST12 = :const12_2
CS_CONST13 = :const13
+ CS_CONST13_LINE = __LINE__ - 1
CS_CONST21 = :const21_2
end
@@ -44,12 +47,14 @@ module ConstantSpecs
CS_CONST10 = :const10_9
CS_CONST11 = :const11_2
CS_CONST12 = :const12_1
+ CS_CONST12_LINE = __LINE__ - 1
end
# Included in ChildA
module ModuleC
CS_CONST10 = :const10_4
CS_CONST15 = :const15_1
+ CS_CONST15_LINE = __LINE__ - 1
end
# Included in ChildA metaclass
@@ -75,7 +80,9 @@ module ConstantSpecs
# are run.
class ClassA
+ CS_CLASS_A_LINE = __LINE__ - 1
CS_CONST10 = :const10_10
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST16 = :const16
CS_CONST17 = :const17_2
CS_CONST22 = :const22_1
@@ -97,10 +104,14 @@ module ConstantSpecs
include ModuleB
CS_CONST4 = :const4
+ CS_CONST4_LINE = __LINE__ - 1
CS_CONST10 = :const10_5
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST11 = :const11_1
+ CS_CONST11_LINE = __LINE__ - 1
CS_CONST15 = :const15_2
CS_CONST20 = :const20_2
+ CS_CONST20_LINE = __LINE__ - 1
CS_CONST21 = :const21_1
CS_CONST22 = :const22_2
@@ -118,6 +129,7 @@ module ConstantSpecs
CS_CONST5 = :const5
CS_CONST10 = :const10_2
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST23 = :const23
class ChildA < ParentA
@@ -135,6 +147,7 @@ module ConstantSpecs
CS_CONST6 = :const6
CS_CONST10 = :const10_3
+ CS_CONST10_LINE = __LINE__ - 1
CS_CONST19 = :const19_2
def self.const10; CS_CONST10; end
@@ -282,6 +295,7 @@ module ConstantSpecs
end
CS_PRIVATE = :cs_private
+ CS_PRIVATE_LINE = __LINE__ - 1
private_constant :CS_PRIVATE
end
diff --git a/spec/ruby/language/BEGIN_spec.rb b/spec/ruby/language/BEGIN_spec.rb
index 58cc2bebfb..5aef5a1d7c 100644
--- a/spec/ruby/language/BEGIN_spec.rb
+++ b/spec/ruby/language/BEGIN_spec.rb
@@ -18,6 +18,11 @@ describe "The BEGIN keyword" do
-> { eval "1.times { BEGIN { 1 } }" }.should raise_error(SyntaxError)
end
+ it "uses top-level for self" do
+ eval("BEGIN { ScratchPad << self.to_s }", TOPLEVEL_BINDING)
+ ScratchPad.recorded.should == ['main']
+ end
+
it "runs first in a given code unit" do
eval "ScratchPad << 'foo'; BEGIN { ScratchPad << 'bar' }"
diff --git a/spec/ruby/language/END_spec.rb b/spec/ruby/language/END_spec.rb
new file mode 100644
index 0000000000..762a8db0c0
--- /dev/null
+++ b/spec/ruby/language/END_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../spec_helper'
+
+describe "The END keyword" do
+ it "runs only once for multiple calls" do
+ ruby_exe("10.times { END { puts 'foo' }; } ").should == "foo\n"
+ end
+
+ it "runs last in a given code unit" do
+ ruby_exe("END { puts 'bar' }; puts'foo'; ").should == "foo\nbar\n"
+ end
+
+ it "runs multiple ends in LIFO order" do
+ ruby_exe("END { puts 'foo' }; END { puts 'bar' }").should == "bar\nfoo\n"
+ end
+end
diff --git a/spec/ruby/language/README b/spec/ruby/language/README
index 74eaf58709..ae08e17fb1 100644
--- a/spec/ruby/language/README
+++ b/spec/ruby/language/README
@@ -4,7 +4,7 @@ words. These words significantly describe major elements of the language,
including flow control constructs like 'for' and 'while', conditional
execution like 'if' and 'unless', exceptional execution control like 'rescue',
etc. There are also literals for the basic "types" like String, Regexp, Array
-and Fixnum.
+and Integer.
Behavioral specifications describe the behavior of concrete entities. Rather
than using concepts of computation to organize these spec files, we use
diff --git a/spec/ruby/language/alias_spec.rb b/spec/ruby/language/alias_spec.rb
index 79348f70c3..d1d06e3fac 100644
--- a/spec/ruby/language/alias_spec.rb
+++ b/spec/ruby/language/alias_spec.rb
@@ -218,7 +218,7 @@ describe "The alias keyword" do
subclass.new.test("testing").should == 4
end
- it "is not allowed against Fixnum or String instances" do
+ it "is not allowed against Integer or String instances" do
-> do
1.instance_eval do
alias :foo :to_s
@@ -255,4 +255,9 @@ describe "The alias keyword" do
code = '$a = 1; $b = 2; alias $b $a; p [$a, $b]; $b = 3; p [$a, $b]'
ruby_exe(code).should == "[1, 1]\n[3, 3]\n"
end
+
+ it "supports aliasing twice the same global variables" do
+ code = '$a = 1; alias $b $a; alias $b $a; p [$a, $b]'
+ ruby_exe(code).should == "[1, 1]\n"
+ end
end
diff --git a/spec/ruby/language/block_spec.rb b/spec/ruby/language/block_spec.rb
index 6f92383af8..b2a3cc84c4 100644
--- a/spec/ruby/language/block_spec.rb
+++ b/spec/ruby/language/block_spec.rb
@@ -44,27 +44,51 @@ describe "A block yielded a single" do
m([1, 2]) { |a, **k| [a, k] }.should == [1, {}]
end
- it "assigns elements to mixed argument types" do
- suppress_keyword_warning do
- result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
- result.should == [1, 2, [], 3, 2, {x: 9}]
+ ruby_version_is ''..."3.0" do
+ it "assigns elements to mixed argument types" do
+ suppress_keyword_warning do
+ result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
+ result.should == [1, 2, [], 3, 2, {x: 9}]
+ end
+ end
+
+ it "assigns symbol keys from a Hash to keyword arguments" do
+ suppress_keyword_warning do
+ result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] }
+ result.should == [{"a" => 1}, a: 10]
+ end
+ end
+
+ it "assigns symbol keys from a Hash returned by #to_hash to keyword arguments" do
+ suppress_keyword_warning do
+ obj = mock("coerce block keyword arguments")
+ obj.should_receive(:to_hash).and_return({"a" => 1, b: 2})
+
+ result = m([obj]) { |a=nil, **b| [a, b] }
+ result.should == [{"a" => 1}, b: 2]
+ end
end
end
- it "assigns symbol keys from a Hash to keyword arguments" do
- suppress_keyword_warning do
+ ruby_version_is "3.0" do
+ it "assigns elements to mixed argument types" do
+ result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
+ result.should == [1, 2, [3], {x: 9}, 2, {}]
+ end
+
+ it "does not treat final Hash as keyword arguments and does not autosplat" do
result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] }
- result.should == [{"a" => 1}, a: 10]
+ result.should == [[{"a" => 1, a: 10}], {}]
end
- end
- it "assigns symbol keys from a Hash returned by #to_hash to keyword arguments" do
- suppress_keyword_warning do
- obj = mock("coerce block keyword arguments")
- obj.should_receive(:to_hash).and_return({"a" => 1, b: 2})
+ it "does not call #to_hash on final argument to get keyword arguments and does not autosplat" do
+ suppress_keyword_warning do
+ obj = mock("coerce block keyword arguments")
+ obj.should_not_receive(:to_hash)
- result = m([obj]) { |a=nil, **b| [a, b] }
- result.should == [{"a" => 1}, b: 2]
+ result = m([obj]) { |a=nil, **b| [a, b] }
+ result.should == [[obj], {}]
+ end
end
end
@@ -78,7 +102,7 @@ describe "A block yielded a single" do
end
end
- ruby_version_is "2.7" do
+ ruby_version_is "2.7"...'3.0' do
it "calls #to_hash on the argument but ignores result when optional argument and keyword argument accepted" do
obj = mock("coerce block keyword arguments")
obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})
@@ -88,65 +112,114 @@ describe "A block yielded a single" do
end
end
+ ruby_version_is "3.0" do
+ it "does not call #to_hash on the argument when optional argument and keyword argument accepted and does not autosplat" do
+ obj = mock("coerce block keyword arguments")
+ obj.should_not_receive(:to_hash)
+
+ result = m([obj]) { |a=nil, **b| [a, b] }
+ result.should == [[obj], {}]
+ end
+ end
+
describe "when non-symbol keys are in a keyword arguments Hash" do
- it "separates non-symbol keys and symbol keys" do
- suppress_keyword_warning do
- result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
- result.should == [{"a" => 10}, {b: 2}]
+ ruby_version_is ""..."3.0" do
+ it "separates non-symbol keys and symbol keys" do
+ suppress_keyword_warning do
+ result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
+ result.should == [{"a" => 10}, {b: 2}]
+ end
+ end
+ end
+ ruby_version_is "3.0" do
+ it "does not separate non-symbol keys and symbol keys and does not autosplat" do
+ suppress_keyword_warning do
+ result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
+ result.should == [[{"a" => 10, b: 2}], {}]
+ end
end
end
end
- it "does not treat hashes with string keys as keyword arguments" do
- result = m(["a" => 10]) { |a = nil, **b| [a, b] }
- result.should == [{"a" => 10}, {}]
+ ruby_version_is ""..."3.0" do
+ it "does not treat hashes with string keys as keyword arguments" do
+ result = m(["a" => 10]) { |a = nil, **b| [a, b] }
+ result.should == [{"a" => 10}, {}]
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "does not treat hashes with string keys as keyword arguments and does not autosplat" do
+ result = m(["a" => 10]) { |a = nil, **b| [a, b] }
+ result.should == [[{"a" => 10}], {}]
+ end
end
- it "calls #to_hash on the last element if keyword arguments are present" do
- suppress_keyword_warning do
+ ruby_version_is ''...'3.0' do
+ it "calls #to_hash on the last element if keyword arguments are present" do
+ suppress_keyword_warning do
+ obj = mock("destructure block keyword arguments")
+ obj.should_receive(:to_hash).and_return({x: 9})
+
+ result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
+ result.should == [1, [2], 3, {x: 9}]
+ end
+ end
+
+ it "assigns the last element to a non-keyword argument if #to_hash returns nil" do
+ suppress_keyword_warning do
+ obj = mock("destructure block keyword arguments")
+ obj.should_receive(:to_hash).and_return(nil)
+
+ result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
+ result.should == [1, [2, 3], obj, {}]
+ end
+ end
+
+ it "calls #to_hash on the last element when there are more arguments than parameters" do
+ suppress_keyword_warning do
+ x = mock("destructure matching block keyword argument")
+ x.should_receive(:to_hash).and_return({x: 9})
+
+ result = m([1, 2, 3, {y: 9}, 4, 5, x]) { |a, b=5, c, **k| [a, b, c, k] }
+ result.should == [1, 2, 3, {x: 9}]
+ end
+ end
+
+ it "raises a TypeError if #to_hash does not return a Hash" do
obj = mock("destructure block keyword arguments")
- obj.should_receive(:to_hash).and_return({x: 9})
+ obj.should_receive(:to_hash).and_return(1)
- result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
- result.should == [1, [2], 3, {x: 9}]
+ -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(TypeError)
+ end
+
+ it "raises the error raised inside #to_hash" do
+ obj = mock("destructure block keyword arguments")
+ error = RuntimeError.new("error while converting to a hash")
+ obj.should_receive(:to_hash).and_raise(error)
+
+ -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(error)
end
end
- it "assigns the last element to a non-keyword argument if #to_hash returns nil" do
- suppress_keyword_warning do
+ ruby_version_is '3.0' do
+ it "does not call #to_hash on the last element if keyword arguments are present" do
obj = mock("destructure block keyword arguments")
- obj.should_receive(:to_hash).and_return(nil)
+ obj.should_not_receive(:to_hash)
result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
result.should == [1, [2, 3], obj, {}]
end
- end
- it "calls #to_hash on the last element when there are more arguments than parameters" do
- suppress_keyword_warning do
+ it "does not call #to_hash on the last element when there are more arguments than parameters" do
x = mock("destructure matching block keyword argument")
- x.should_receive(:to_hash).and_return({x: 9})
+ x.should_not_receive(:to_hash)
result = m([1, 2, 3, {y: 9}, 4, 5, x]) { |a, b=5, c, **k| [a, b, c, k] }
- result.should == [1, 2, 3, {x: 9}]
+ result.should == [1, 2, 3, {}]
end
end
- it "raises a TypeError if #to_hash does not return a Hash" do
- obj = mock("destructure block keyword arguments")
- obj.should_receive(:to_hash).and_return(1)
-
- -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(TypeError)
- end
-
- it "raises the error raised inside #to_hash" do
- obj = mock("destructure block keyword arguments")
- error = RuntimeError.new("error while converting to a hash")
- obj.should_receive(:to_hash).and_raise(error)
-
- -> { m([1, 2, 3, obj]) { |a, *b, c, **k| } }.should raise_error(error)
- end
-
it "does not call #to_ary on the Array" do
ary = [1, 2]
ary.should_not_receive(:to_ary)
@@ -244,10 +317,8 @@ describe "A block" do
@y.s(0) { 1 }.should == 1
end
- ruby_version_is "2.5" do
- it "may include a rescue clause" do
- eval("@y.z do raise ArgumentError; rescue ArgumentError; 7; end").should == 7
- end
+ it "may include a rescue clause" do
+ eval("@y.z do raise ArgumentError; rescue ArgumentError; 7; end").should == 7
end
end
@@ -260,10 +331,8 @@ describe "A block" do
@y.s(0) { || 1 }.should == 1
end
- ruby_version_is "2.5" do
- it "may include a rescue clause" do
- eval('@y.z do || raise ArgumentError; rescue ArgumentError; 7; end').should == 7
- end
+ it "may include a rescue clause" do
+ eval('@y.z do || raise ArgumentError; rescue ArgumentError; 7; end').should == 7
end
end
@@ -291,10 +360,8 @@ describe "A block" do
@y.s([1, 2]) { |a| a }.should == [1, 2]
end
- ruby_version_is "2.5" do
- it "may include a rescue clause" do
- eval('@y.s(1) do |x| raise ArgumentError; rescue ArgumentError; 7; end').should == 7
- end
+ it "may include a rescue clause" do
+ eval('@y.s(1) do |x| raise ArgumentError; rescue ArgumentError; 7; end').should == 7
end
end
@@ -806,7 +873,7 @@ describe "Post-args" do
end.call(1, 2, 3).should == [[], 1, 2, 3]
end
- it "are required" do
+ it "are required for a lambda" do
-> {
-> *a, b do
[a, b]
@@ -814,6 +881,12 @@ describe "Post-args" do
}.should raise_error(ArgumentError)
end
+ it "are assigned to nil when not enough arguments are given to a proc" do
+ proc do |a, *b, c|
+ [a, b, c]
+ end.call.should == [nil, [], nil]
+ end
+
describe "with required args" do
it "gathers remaining args in the splat" do
diff --git a/spec/ruby/language/break_spec.rb b/spec/ruby/language/break_spec.rb
index 754d5d3c49..627cb4a071 100644
--- a/spec/ruby/language/break_spec.rb
+++ b/spec/ruby/language/break_spec.rb
@@ -362,4 +362,22 @@ describe "Executing break from within a block" do
bt2.three
ScratchPad.recorded.should == [:two_ensure, :three_post, :three_ensure]
end
+
+ it "works when passing through a super call" do
+ cls1 = Class.new { def foo; yield; end }
+ cls2 = Class.new(cls1) { def foo; super { break 1 }; end }
+
+ -> do
+ cls2.new.foo.should == 1
+ end.should_not raise_error
+ end
+
+ it "raises LocalJumpError when converted into a proc during a a super call" do
+ cls1 = Class.new { def foo(&b); b; end }
+ cls2 = Class.new(cls1) { def foo; super { break 1 }.call; end }
+
+ -> do
+ cls2.new.foo
+ end.should raise_error(LocalJumpError)
+ end
end
diff --git a/spec/ruby/language/case_spec.rb b/spec/ruby/language/case_spec.rb
index 1475e20f75..410cb9afb1 100644
--- a/spec/ruby/language/case_spec.rb
+++ b/spec/ruby/language/case_spec.rb
@@ -424,4 +424,13 @@ describe "The 'case'-construct with no target expression" do
:called
end.should == :called
end
+
+ # Homogeneous cases are often optimized to avoid === using a jump table, and should be tested separately.
+ # See https://github.com/jruby/jruby/issues/6440
+ it "handles homogeneous cases" do
+ case
+ when 1; 'foo'
+ when 2; 'bar'
+ end.should == 'foo'
+ end
end
diff --git a/spec/ruby/language/class_spec.rb b/spec/ruby/language/class_spec.rb
index 88b7a6a74f..83db164e1a 100644
--- a/spec/ruby/language/class_spec.rb
+++ b/spec/ruby/language/class_spec.rb
@@ -285,6 +285,16 @@ describe "A class definition extending an object (sclass)" do
}.should raise_error(TypeError)
end
+ it "raises a TypeError when trying to extend non-Class" do
+ error_msg = /superclass must be a.* Class/
+ -> { class TestClass < ""; end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < 1; end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < :symbol; end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < mock('o'); end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < Module.new; end }.should raise_error(TypeError, error_msg)
+ -> { class TestClass < BasicObject.new; end }.should raise_error(TypeError, error_msg)
+ end
+
ruby_version_is ""..."3.0" do
it "allows accessing the block of the original scope" do
suppress_warning do
@@ -293,6 +303,14 @@ describe "A class definition extending an object (sclass)" do
end
end
+ ruby_version_is "3.0" do
+ it "does not allow accessing the block of the original scope" do
+ -> {
+ ClassSpecs.sclass_with_block { 123 }
+ }.should raise_error(SyntaxError)
+ end
+ end
+
it "can use return to cause the enclosing method to return" do
ClassSpecs.sclass_with_return.should == :inner
end
diff --git a/spec/ruby/language/comment_spec.rb b/spec/ruby/language/comment_spec.rb
new file mode 100644
index 0000000000..690e844dc0
--- /dev/null
+++ b/spec/ruby/language/comment_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../spec_helper'
+
+describe "The comment" do
+ ruby_version_is "2.7" do
+ it "can be placed between fluent dot now" do
+ code = <<~CODE
+ 10
+ # some comment
+ .to_s
+ CODE
+
+ eval(code).should == '10'
+ end
+ end
+end
diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb
index c4cf940cba..4d46cf2f84 100644
--- a/spec/ruby/language/constants_spec.rb
+++ b/spec/ruby/language/constants_spec.rb
@@ -154,6 +154,36 @@ describe "Literal (A::X) constant resolution" do
-> { ConstantSpecs::ParentA::CS_CONSTX }.should raise_error(NameError)
end
+ ruby_version_is "3.0" do
+ it "uses the module or class #name to craft the error message" do
+ mod = Module.new do
+ def self.name
+ "ModuleName"
+ end
+
+ def self.inspect
+ "<unusable info>"
+ end
+ end
+
+ -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant ModuleName::DOES_NOT_EXIST/)
+ end
+
+ it "uses the module or class #inspect to craft the error message if they are anonymous" do
+ mod = Module.new do
+ def self.name
+ nil
+ end
+
+ def self.inspect
+ "<unusable info>"
+ end
+ end
+
+ -> { mod::DOES_NOT_EXIST }.should raise_error(NameError, /uninitialized constant <unusable info>::DOES_NOT_EXIST/)
+ end
+ end
+
it "sends #const_missing to the original class or module scope" do
ConstantSpecs::ClassA::CS_CONSTX.should == :CS_CONSTX
end
@@ -425,18 +455,8 @@ end
describe "top-level constant lookup" do
context "on a class" do
- ruby_version_is "" ... "2.5" do
- it "searches Object successfully after searching other scopes" do
- -> {
- String::Hash.should == Hash
- }.should complain(/toplevel constant Hash referenced by/)
- end
- end
-
- ruby_version_is "2.5" do
- it "does not search Object after searching other scopes" do
- -> { String::Hash }.should raise_error(NameError)
- end
+ it "does not search Object after searching other scopes" do
+ -> { String::Hash }.should raise_error(NameError)
end
end
diff --git a/spec/ruby/language/def_spec.rb b/spec/ruby/language/def_spec.rb
index fc5693a2f0..6b0be19d90 100644
--- a/spec/ruby/language/def_spec.rb
+++ b/spec/ruby/language/def_spec.rb
@@ -89,6 +89,26 @@ describe "An instance method" do
def foo(a); end
-> { foo 1, 2 }.should raise_error(ArgumentError, 'wrong number of arguments (given 2, expected 1)')
end
+
+ it "raises FrozenError with the correct class name" do
+ -> {
+ Module.new do
+ self.freeze
+ def foo; end
+ end
+ }.should raise_error(FrozenError) { |e|
+ e.message.should.start_with? "can't modify frozen module"
+ }
+
+ -> {
+ Class.new do
+ self.freeze
+ def foo; end
+ end
+ }.should raise_error(FrozenError){ |e|
+ e.message.should.start_with? "can't modify frozen class"
+ }
+ end
end
describe "An instance method definition with a splat" do
@@ -261,10 +281,29 @@ describe "A singleton method definition" do
(obj==2).should == 2
end
- it "raises #{frozen_error_class} if frozen" do
+ it "raises FrozenError if frozen" do
+ obj = Object.new
+ obj.freeze
+ -> { def obj.foo; end }.should raise_error(FrozenError)
+ end
+
+ it "raises FrozenError with the correct class name" do
obj = Object.new
obj.freeze
- -> { def obj.foo; end }.should raise_error(frozen_error_class)
+ -> { def obj.foo; end }.should raise_error(FrozenError){ |e|
+ e.message.should.start_with? "can't modify frozen object"
+ }
+
+ c = obj.singleton_class
+ -> { def c.foo; end }.should raise_error(FrozenError){ |e|
+ e.message.should.start_with? "can't modify frozen Class"
+ }
+
+ m = Module.new
+ m.freeze
+ -> { def m.foo; end }.should raise_error(FrozenError){ |e|
+ e.message.should.start_with? "can't modify frozen Module"
+ }
end
end
@@ -412,12 +451,12 @@ describe "A method definition inside a metaclass scope" do
-> { Object.new.a_singleton_method }.should raise_error(NoMethodError)
end
- it "raises #{frozen_error_class} if frozen" do
+ it "raises FrozenError if frozen" do
obj = Object.new
obj.freeze
class << obj
- -> { def foo; end }.should raise_error(frozen_error_class)
+ -> { def foo; end }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb
index 02c69d27b8..4fcf869f91 100644
--- a/spec/ruby/language/defined_spec.rb
+++ b/spec/ruby/language/defined_spec.rb
@@ -275,9 +275,7 @@ describe "The defined? keyword for an expression" do
end
it "returns nil for an expression with '!' and an unset class variable" do
- -> {
- @result = defined?(!@@defined_specs_undefined_class_variable)
- }.should complain(/class variable access from toplevel/)
+ @result = eval("class singleton_class::A; defined?(!@@doesnt_exist) end", binding, __FILE__, __LINE__)
@result.should be_nil
end
@@ -286,9 +284,7 @@ describe "The defined? keyword for an expression" do
end
it "returns nil for an expression with 'not' and an unset class variable" do
- -> {
- @result = defined?(not @@defined_specs_undefined_class_variable)
- }.should complain(/class variable access from toplevel/)
+ @result = eval("class singleton_class::A; defined?(not @@doesnt_exist) end", binding, __FILE__, __LINE__)
@result.should be_nil
end
@@ -439,11 +435,11 @@ describe "The defined? keyword for an expression" do
end
end
- it "returns 'expression' when passed a Fixnum literal" do
+ it "returns 'expression' when passed an Integer literal" do
defined?(42).should == "expression"
end
- it "returns 'expression' when passed a Bignum literal" do
+ it "returns 'expression' when passed an Integer literal" do
defined?(0xdead_beef_deed_feed).should == "expression"
end
@@ -756,16 +752,8 @@ describe "The defined? keyword for a scoped constant" do
defined?(DefinedSpecs::String).should be_nil
end
- ruby_version_is ""..."2.5" do
- it "returns 'constant' when a constant is defined on top-level but not on the class" do
- defined?(DefinedSpecs::Basic::String).should == 'constant'
- end
- end
-
- ruby_version_is "2.5" do
- it "returns nil when a constant is defined on top-level but not on the class" do
- defined?(DefinedSpecs::Basic::String).should be_nil
- end
+ it "returns nil when a constant is defined on top-level but not on the class" do
+ defined?(DefinedSpecs::Basic::String).should be_nil
end
it "returns 'constant' if the scoped-scoped constant is defined" do
@@ -905,17 +893,21 @@ describe "The defined? keyword for a variable scoped constant" do
end
it "returns nil if the class scoped constant is not defined" do
- -> {
- @@defined_specs_obj = DefinedSpecs::Basic
- defined?(@@defined_specs_obj::Undefined).should be_nil
- }.should complain(/class variable access from toplevel/)
+ eval(<<-END, binding, __FILE__, __LINE__)
+ class singleton_class::A
+ @@defined_specs_obj = DefinedSpecs::Basic
+ defined?(@@defined_specs_obj::Undefined).should be_nil
+ end
+ END
end
it "returns 'constant' if the constant is defined in the scope of the class variable" do
- -> {
- @@defined_specs_obj = DefinedSpecs::Basic
- defined?(@@defined_specs_obj::A).should == "constant"
- }.should complain(/class variable access from toplevel/)
+ eval(<<-END, binding, __FILE__, __LINE__)
+ class singleton_class::A
+ @@defined_specs_obj = DefinedSpecs::Basic
+ defined?(@@defined_specs_obj::A).should == "constant"
+ end
+ END
end
it "returns nil if the local scoped constant is not defined" do
diff --git a/spec/ruby/language/delegation_spec.rb b/spec/ruby/language/delegation_spec.rb
new file mode 100644
index 0000000000..ac7b511f65
--- /dev/null
+++ b/spec/ruby/language/delegation_spec.rb
@@ -0,0 +1,41 @@
+require_relative '../spec_helper'
+require_relative 'fixtures/delegation'
+
+ruby_version_is "2.7" do
+ describe "delegation with def(...)" do
+ it "delegates rest and kwargs" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(...)
+ target(...)
+ end
+ RUBY
+
+ a.new.delegate(1, b: 2).should == [[1], {b: 2}]
+ end
+
+ it "delegates block" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate_block(...)
+ target_block(...)
+ end
+ RUBY
+
+ a.new.delegate_block(1, b: 2) { |x| x }.should == [{b: 2}, [1]]
+ end
+
+ it "parses as open endless Range when brackets are omitted" do
+ a = Class.new(DelegationSpecs::Target)
+ suppress_warning do
+ a.class_eval(<<-RUBY)
+ def delegate(...)
+ target ...
+ end
+ RUBY
+ end
+
+ a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true)
+ end
+ end
+end
diff --git a/spec/ruby/language/ensure_spec.rb b/spec/ruby/language/ensure_spec.rb
index a930bda36b..e94c523e82 100644
--- a/spec/ruby/language/ensure_spec.rb
+++ b/spec/ruby/language/ensure_spec.rb
@@ -251,83 +251,81 @@ describe "An ensure block inside {} block" do
end
end
-ruby_version_is "2.5" do
- describe "An ensure block inside 'do end' block" do
- before :each do
- ScratchPad.record []
- end
-
- it "is executed when an exception is raised in it's corresponding begin block" do
- -> {
- eval(<<-ruby).call
- lambda do
- ScratchPad << :begin
- raise EnsureSpec::Error
- ensure
- ScratchPad << :ensure
- end
- ruby
- }.should raise_error(EnsureSpec::Error)
-
- ScratchPad.recorded.should == [:begin, :ensure]
- end
+describe "An ensure block inside 'do end' block" do
+ before :each do
+ ScratchPad.record []
+ end
- it "is executed when an exception is raised and rescued in it's corresponding begin block" do
+ it "is executed when an exception is raised in it's corresponding begin block" do
+ -> {
eval(<<-ruby).call
lambda do
ScratchPad << :begin
- raise "An exception occurred!"
- rescue
- ScratchPad << :rescue
+ raise EnsureSpec::Error
ensure
ScratchPad << :ensure
end
ruby
+ }.should raise_error(EnsureSpec::Error)
- ScratchPad.recorded.should == [:begin, :rescue, :ensure]
- end
+ ScratchPad.recorded.should == [:begin, :ensure]
+ end
- it "is executed even when a symbol is thrown in it's corresponding begin block" do
- catch(:symbol) do
- eval(<<-ruby).call
- lambda do
- ScratchPad << :begin
- throw(:symbol)
- rescue
- ScratchPad << :rescue
- ensure
- ScratchPad << :ensure
- end
- ruby
+ it "is executed when an exception is raised and rescued in it's corresponding begin block" do
+ eval(<<-ruby).call
+ lambda do
+ ScratchPad << :begin
+ raise "An exception occurred!"
+ rescue
+ ScratchPad << :rescue
+ ensure
+ ScratchPad << :ensure
end
+ ruby
- ScratchPad.recorded.should == [:begin, :ensure]
- end
+ ScratchPad.recorded.should == [:begin, :rescue, :ensure]
+ end
- it "is executed when nothing is raised or thrown in it's corresponding begin block" do
+ it "is executed even when a symbol is thrown in it's corresponding begin block" do
+ catch(:symbol) do
eval(<<-ruby).call
lambda do
ScratchPad << :begin
+ throw(:symbol)
rescue
ScratchPad << :rescue
ensure
ScratchPad << :ensure
end
ruby
-
- ScratchPad.recorded.should == [:begin, :ensure]
end
- it "has no return value" do
- result = eval(<<-ruby).call
- lambda do
- :begin
- ensure
- :ensure
- end
- ruby
+ ScratchPad.recorded.should == [:begin, :ensure]
+ end
- result.should == :begin
- end
+ it "is executed when nothing is raised or thrown in it's corresponding begin block" do
+ eval(<<-ruby).call
+ lambda do
+ ScratchPad << :begin
+ rescue
+ ScratchPad << :rescue
+ ensure
+ ScratchPad << :ensure
+ end
+ ruby
+
+ ScratchPad.recorded.should == [:begin, :ensure]
+ end
+
+ it "has no return value" do
+ result = eval(<<-ruby).call
+ lambda do
+ :begin
+ ensure
+ :ensure
+ end
+ ruby
+
+ result.should == :begin
end
end
diff --git a/spec/ruby/language/fixtures/delegation.rb b/spec/ruby/language/fixtures/delegation.rb
new file mode 100644
index 0000000000..527d928390
--- /dev/null
+++ b/spec/ruby/language/fixtures/delegation.rb
@@ -0,0 +1,11 @@
+module DelegationSpecs
+ class Target
+ def target(*args, **kwargs)
+ [args, kwargs]
+ end
+
+ def target_block(*args, **kwargs)
+ yield [kwargs, args]
+ end
+ end
+end
diff --git a/spec/ruby/language/fixtures/rescue_captures.rb b/spec/ruby/language/fixtures/rescue_captures.rb
new file mode 100644
index 0000000000..69f9b83904
--- /dev/null
+++ b/spec/ruby/language/fixtures/rescue_captures.rb
@@ -0,0 +1,107 @@
+module RescueSpecs
+ class Captor
+ attr_accessor :captured_error
+
+ def self.should_capture_exception
+ captor = new
+ captor.capture('some text').should == :caught # Ensure rescue body still runs
+ captor.captured_error.message.should == 'some text'
+ end
+ end
+
+ class ClassVariableCaptor < Captor
+ def capture(msg)
+ raise msg
+ rescue => @@captured_error
+ :caught
+ end
+
+ def captured_error
+ self.class.remove_class_variable(:@@captured_error)
+ end
+ end
+
+ class ConstantCaptor < Captor
+ # Using lambda gets around the dynamic constant assignment warning
+ CAPTURE = -> msg {
+ begin
+ raise msg
+ rescue => CapturedError
+ :caught
+ end
+ }
+
+ def capture(msg)
+ CAPTURE.call(msg)
+ end
+
+ def captured_error
+ self.class.send(:remove_const, :CapturedError)
+ end
+ end
+
+ class GlobalVariableCaptor < Captor
+ def capture(msg)
+ raise msg
+ rescue => $captured_error
+ :caught
+ end
+
+ def captured_error
+ $captured_error.tap do
+ $captured_error = nil # Can't remove globals, only nil them out
+ end
+ end
+ end
+
+ class InstanceVariableCaptor < Captor
+ def capture(msg)
+ raise msg
+ rescue => @captured_error
+ :caught
+ end
+ end
+
+ class LocalVariableCaptor < Captor
+ def capture(msg)
+ raise msg
+ rescue => captured_error
+ @captured_error = captured_error
+ :caught
+ end
+ end
+
+ class SafeNavigationSetterCaptor < Captor
+ def capture(msg)
+ raise msg
+ rescue => self&.captured_error
+ :caught
+ end
+ end
+
+ class SetterCaptor < Captor
+ def capture(msg)
+ raise msg
+ rescue => self.captured_error
+ :caught
+ end
+ end
+
+ class SquareBracketsCaptor < Captor
+ def capture(msg)
+ @hash = {}
+
+ raise msg
+ rescue => self[:error]
+ :caught
+ end
+
+ def []=(key, value)
+ @hash[key] = value
+ end
+
+ def captured_error
+ @hash[:error]
+ end
+ end
+end
diff --git a/spec/ruby/language/fixtures/squiggly_heredoc.rb b/spec/ruby/language/fixtures/squiggly_heredoc.rb
index afc87514c7..d223966b93 100644
--- a/spec/ruby/language/fixtures/squiggly_heredoc.rb
+++ b/spec/ruby/language/fixtures/squiggly_heredoc.rb
@@ -29,6 +29,14 @@ module SquigglyHeredocSpecs
HERE
end
+ def self.least_indented_on_the_first_line
+ <<~HERE
+ a
+ b
+ c
+ HERE
+ end
+
def self.least_indented_on_the_last_line
<<~HERE
a
@@ -36,4 +44,20 @@ module SquigglyHeredocSpecs
c
HERE
end
+
+ def self.least_indented_on_the_first_line_single
+ <<~'HERE'
+ a
+ b
+ c
+ HERE
+ end
+
+ def self.least_indented_on_the_last_line_single
+ <<~'HERE'
+ a
+ b
+ c
+ HERE
+ end
end
diff --git a/spec/ruby/language/fixtures/super.rb b/spec/ruby/language/fixtures/super.rb
index 6a024cae23..218f1e4970 100644
--- a/spec/ruby/language/fixtures/super.rb
+++ b/spec/ruby/language/fixtures/super.rb
@@ -455,6 +455,52 @@ module SuperSpecs
end
end
+ module ZSuperWithRestAndPost
+ class A
+ def m(*args, a, b)
+ args
+ end
+
+ def m_modified(*args, a, b)
+ args
+ end
+ end
+
+ class B < A
+ def m(*args, a, b)
+ super
+ end
+
+ def m_modified(*args, a, b)
+ args[1] = 14
+ super
+ end
+ end
+ end
+
+ module ZSuperWithRestOthersAndPost
+ class A
+ def m(a, *args, b)
+ args
+ end
+
+ def m_modified(a, *args, b)
+ args
+ end
+ end
+
+ class B < A
+ def m(a, *args, b)
+ super
+ end
+
+ def m_modified(a, *args, b)
+ args[1] = 14
+ super
+ end
+ end
+ end
+
module ZSuperWithRestReassigned
class A
def a(*args)
diff --git a/spec/ruby/language/hash_spec.rb b/spec/ruby/language/hash_spec.rb
index 6f2e8e5cf0..d6600ddb4a 100644
--- a/spec/ruby/language/hash_spec.rb
+++ b/spec/ruby/language/hash_spec.rb
@@ -38,7 +38,7 @@ describe "Hash literal" do
key.reverse!
h["foo"].should == "bar"
h.keys.first.should == "foo"
- h.keys.first.frozen?.should == true
+ h.keys.first.should.frozen?
key.should == "oof"
end
@@ -149,6 +149,12 @@ describe "Hash literal" do
-> { {**obj} }.should raise_error(TypeError)
end
+ it "raises a TypeError if the object does not respond to #to_hash" do
+ obj = 42
+ -> { {**obj} }.should raise_error(TypeError)
+ -> { {a: 1, **obj} }.should raise_error(TypeError)
+ end
+
it "does not change encoding of literal string keys during creation" do
binary_hash = HashStringsBinary.literal_hash
utf8_hash = HashStringsUTF8.literal_hash
diff --git a/spec/ruby/language/heredoc_spec.rb b/spec/ruby/language/heredoc_spec.rb
index e7655a9216..95df8457e4 100644
--- a/spec/ruby/language/heredoc_spec.rb
+++ b/spec/ruby/language/heredoc_spec.rb
@@ -59,6 +59,22 @@ HERE
s.encoding.should == Encoding::US_ASCII
end
+ ruby_version_is "2.7" do
+ it 'raises SyntaxError if quoted HEREDOC identifier is ending not on same line' do
+ -> {
+ eval %{<<"HERE\n"\nraises syntax error\nHERE}
+ }.should raise_error(SyntaxError)
+ end
+ end
+
+ ruby_version_is ""..."2.7" do
+ it 'prints a warning if quoted HEREDOC identifier is ending not on same line' do
+ -> {
+ eval %{<<"HERE\n"\nit warns\nHERE}
+ }.should complain(/here document identifier ends with a newline/)
+ end
+ end
+
it "allows HEREDOC with <<~'identifier', allowing to indent identifier and content" do
require_relative 'fixtures/squiggly_heredoc'
SquigglyHeredocSpecs.message.should == "character density, n.:\n The number of very weird people in the office.\n"
@@ -86,6 +102,13 @@ HERE
it "selects the least-indented line and removes its indentation from all the lines" do
require_relative 'fixtures/squiggly_heredoc'
+ SquigglyHeredocSpecs.least_indented_on_the_first_line.should == "a\n b\n c\n"
SquigglyHeredocSpecs.least_indented_on_the_last_line.should == " a\n b\nc\n"
end
+
+ it "selects the least-indented line and removes its indentation from all the lines for <<~'identifier'" do
+ require_relative 'fixtures/squiggly_heredoc'
+ SquigglyHeredocSpecs.least_indented_on_the_first_line_single.should == "a\n b\n c\n"
+ SquigglyHeredocSpecs.least_indented_on_the_last_line_single.should == " a\n b\nc\n"
+ end
end
diff --git a/spec/ruby/language/lambda_spec.rb b/spec/ruby/language/lambda_spec.rb
index ddd0b574b3..630817c909 100644
--- a/spec/ruby/language/lambda_spec.rb
+++ b/spec/ruby/language/lambda_spec.rb
@@ -179,17 +179,33 @@ describe "A lambda literal -> () { }" do
result.should == [1, 2, 3, [4, 5], 6, [7, 8], 9, 10, 11, 12]
end
- evaluate <<-ruby do
- @a = -> (*, **k) { k }
- ruby
+ ruby_version_is ''...'3.0' do
+ evaluate <<-ruby do
+ @a = -> (*, **k) { k }
+ ruby
+
+ @a.().should == {}
+ @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5}
+
+ suppress_keyword_warning do
+ h = mock("keyword splat")
+ h.should_receive(:to_hash).and_return({a: 1})
+ @a.(h).should == {a: 1}
+ end
+ end
+ end
- @a.().should == {}
- @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5}
+ ruby_version_is '3.0' do
+ evaluate <<-ruby do
+ @a = -> (*, **k) { k }
+ ruby
+
+ @a.().should == {}
+ @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5}
- suppress_keyword_warning do
h = mock("keyword splat")
- h.should_receive(:to_hash).and_return({a: 1})
- @a.(h).should == {a: 1}
+ h.should_not_receive(:to_hash)
+ @a.(h).should == {}
end
end
@@ -332,15 +348,14 @@ describe "A lambda expression 'lambda { ... }'" do
end
it "requires a block" do
- lambda { lambda }.should raise_error(ArgumentError)
- end
-
- ruby_version_is "2.5" do
- it "may include a rescue clause" do
- eval('lambda do raise ArgumentError; rescue ArgumentError; 7; end').should be_an_instance_of(Proc)
+ suppress_warning do
+ lambda { lambda }.should raise_error(ArgumentError)
end
end
+ it "may include a rescue clause" do
+ eval('lambda do raise ArgumentError; rescue ArgumentError; 7; end').should be_an_instance_of(Proc)
+ end
context "with an implicit block" do
before do
@@ -362,9 +377,11 @@ describe "A lambda expression 'lambda { ... }'" do
ruby_version_is "2.7" do
it "raises ArgumentError" do
implicit_lambda = nil
- -> {
- meth { 1 }
- }.should raise_error(ArgumentError, /tried to create Proc object without a block/)
+ suppress_warning do
+ -> {
+ meth { 1 }
+ }.should raise_error(ArgumentError, /tried to create Proc object without a block/)
+ end
end
end
end
@@ -533,17 +550,33 @@ describe "A lambda expression 'lambda { ... }'" do
result.should == [1, 2, 3, [4, 5], 6, [7, 8], 9, 10, 11, 12]
end
- evaluate <<-ruby do
- @a = lambda { |*, **k| k }
- ruby
+ ruby_version_is ''...'3.0' do
+ evaluate <<-ruby do
+ @a = lambda { |*, **k| k }
+ ruby
- @a.().should == {}
- @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5}
+ @a.().should == {}
+ @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5}
+
+ suppress_keyword_warning do
+ h = mock("keyword splat")
+ h.should_receive(:to_hash).and_return({a: 1})
+ @a.(h).should == {a: 1}
+ end
+ end
+ end
+
+ ruby_version_is '3.0' do
+ evaluate <<-ruby do
+ @a = lambda { |*, **k| k }
+ ruby
+
+ @a.().should == {}
+ @a.(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5}
- suppress_keyword_warning do
h = mock("keyword splat")
- h.should_receive(:to_hash).and_return({a: 1})
- @a.(h).should == {a: 1}
+ h.should_not_receive(:to_hash)
+ @a.(h).should == {}
end
end
diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb
index 0486025792..462a182b3d 100644
--- a/spec/ruby/language/method_spec.rb
+++ b/spec/ruby/language/method_spec.rb
@@ -156,6 +156,26 @@ describe "A method send" do
-> { m(1, 2, *x) }.should raise_error(TypeError)
end
end
+
+ context "with a block argument" do
+ before :all do
+ def m(x)
+ if block_given?
+ [true, yield(x + 'b')]
+ else
+ [false]
+ end
+ end
+ end
+
+ it "that refers to a proc passes the proc as the block" do
+ m('a', &-> y { y + 'c'}).should == [true, 'abc']
+ end
+
+ it "that is nil passes no block" do
+ m('a', &nil).should == [false]
+ end
+ end
end
describe "An element assignment method send" do
@@ -576,10 +596,21 @@ describe "A method" do
m(a: 1, b: 2).should == { a: 1, b: 2 }
m(*[]).should == {}
m(**{}).should == {}
- m(**{a: 1, b: 2}, **{a: 4, c: 7}).should == { a: 4, b: 2, c: 7 }
+ suppress_warning {
+ eval "m(**{a: 1, b: 2}, **{a: 4, c: 7})"
+ }.should == { a: 4, b: 2, c: 7 }
-> { m(2) }.should raise_error(ArgumentError)
end
+ ruby_version_is "2.7" do
+ evaluate <<-ruby do
+ def m(**k); k end;
+ ruby
+
+ m("a" => 1).should == { "a" => 1 }
+ end
+ end
+
evaluate <<-ruby do
def m(&b) b end
ruby
@@ -713,36 +744,67 @@ describe "A method" do
end
end
- evaluate <<-ruby do
- def m(a, b: 1) [a, b] end
- ruby
+ ruby_version_is ""..."3.0" do
+ evaluate <<-ruby do
+ def m(a, b: 1) [a, b] end
+ ruby
- m(2).should == [2, 1]
- m(1, b: 2).should == [1, 2]
- suppress_keyword_warning do
- m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, 1]
+ m(2).should == [2, 1]
+ m(1, b: 2).should == [1, 2]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, 1]
+ end
end
- end
- evaluate <<-ruby do
- def m(a, **) a end
- ruby
+ evaluate <<-ruby do
+ def m(a, **) a end
+ ruby
- m(1).should == 1
- m(1, a: 2, b: 3).should == 1
- suppress_keyword_warning do
- m("a" => 1, b: 2).should == {"a" => 1, b: 2}
+ m(1).should == 1
+ m(1, a: 2, b: 3).should == 1
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == {"a" => 1, b: 2}
+ end
+ end
+
+ evaluate <<-ruby do
+ def m(a, **k) [a, k] end
+ ruby
+
+ m(1).should == [1, {}]
+ m(1, a: 2, b: 3).should == [1, {a: 2, b: 3}]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, {}]
+ end
end
end
- evaluate <<-ruby do
- def m(a, **k) [a, k] end
- ruby
+ ruby_version_is "3.0" do
+ evaluate <<-ruby do
+ def m(a, b: 1) [a, b] end
+ ruby
- m(1).should == [1, {}]
- m(1, a: 2, b: 3).should == [1, {a: 2, b: 3}]
- suppress_keyword_warning do
- m("a" => 1, b: 2).should == [{"a" => 1, b: 2}, {}]
+ m(2).should == [2, 1]
+ m(1, b: 2).should == [1, 2]
+ -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError)
+ end
+
+ evaluate <<-ruby do
+ def m(a, **) a end
+ ruby
+
+ m(1).should == 1
+ m(1, a: 2, b: 3).should == 1
+ -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError)
+ end
+
+ evaluate <<-ruby do
+ def m(a, **k) [a, k] end
+ ruby
+
+ m(1).should == [1, {}]
+ m(1, a: 2, b: 3).should == [1, {a: 2, b: 3}]
+ -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError)
end
end
@@ -854,26 +916,49 @@ describe "A method" do
result.should == [[1, 2, 3], 4, [5, 6], 7, [], 8]
end
- evaluate <<-ruby do
- def m(a=1, b:) [a, b] end
- ruby
+ ruby_version_is ""..."3.0" do
+ evaluate <<-ruby do
+ def m(a=1, b:) [a, b] end
+ ruby
- m(b: 2).should == [1, 2]
- m(2, b: 1).should == [2, 1]
- suppress_keyword_warning do
- m("a" => 1, b: 2).should == [{"a" => 1}, 2]
+ m(b: 2).should == [1, 2]
+ m(2, b: 1).should == [2, 1]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [{"a" => 1}, 2]
+ end
+ end
+
+ evaluate <<-ruby do
+ def m(a=1, b: 2) [a, b] end
+ ruby
+
+ m().should == [1, 2]
+ m(2).should == [2, 2]
+ m(b: 3).should == [1, 3]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [{"a" => 1}, 2]
+ end
end
end
- evaluate <<-ruby do
- def m(a=1, b: 2) [a, b] end
- ruby
+ ruby_version_is "3.0" do
+ evaluate <<-ruby do
+ def m(a=1, b:) [a, b] end
+ ruby
- m().should == [1, 2]
- m(2).should == [2, 2]
- m(b: 3).should == [1, 3]
- suppress_keyword_warning do
- m("a" => 1, b: 2).should == [{"a" => 1}, 2]
+ m(b: 2).should == [1, 2]
+ m(2, b: 1).should == [2, 1]
+ -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError)
+ end
+
+ evaluate <<-ruby do
+ def m(a=1, b: 2) [a, b] end
+ ruby
+
+ m().should == [1, 2]
+ m(2).should == [2, 2]
+ m(b: 3).should == [1, 3]
+ -> { m("a" => 1, b: 2) }.should raise_error(ArgumentError)
end
end
@@ -936,77 +1021,77 @@ describe "A method" do
m(1, 2, 3).should == [[1, 2], 3]
end
- evaluate <<-ruby do
- def m(*, a:) a end
- ruby
+ ruby_version_is ""..."2.7" do
+ evaluate <<-ruby do
+ def m(*, a:) a end
+ ruby
- m(a: 1).should == 1
- m(1, 2, a: 3).should == 3
- suppress_keyword_warning do
- m("a" => 1, a: 2).should == 2
+ m(a: 1).should == 1
+ m(1, 2, a: 3).should == 3
+ suppress_keyword_warning do
+ m("a" => 1, a: 2).should == 2
+ end
end
- end
- evaluate <<-ruby do
- def m(*a, b:) [a, b] end
- ruby
+ evaluate <<-ruby do
+ def m(*a, b:) [a, b] end
+ ruby
- m(b: 1).should == [[], 1]
- m(1, 2, b: 3).should == [[1, 2], 3]
- suppress_keyword_warning do
- m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
+ m(b: 1).should == [[], 1]
+ m(1, 2, b: 3).should == [[1, 2], 3]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
+ end
end
- end
- evaluate <<-ruby do
- def m(*, a: 1) a end
- ruby
+ evaluate <<-ruby do
+ def m(*, a: 1) a end
+ ruby
- m().should == 1
- m(1, 2).should == 1
- m(a: 2).should == 2
- m(1, a: 2).should == 2
- suppress_keyword_warning do
- m("a" => 1, a: 2).should == 2
+ m().should == 1
+ m(1, 2).should == 1
+ m(a: 2).should == 2
+ m(1, a: 2).should == 2
+ suppress_keyword_warning do
+ m("a" => 1, a: 2).should == 2
+ end
end
- end
- evaluate <<-ruby do
- def m(*a, b: 1) [a, b] end
- ruby
+ evaluate <<-ruby do
+ def m(*a, b: 1) [a, b] end
+ ruby
- m().should == [[], 1]
- m(1, 2, 3, b: 4).should == [[1, 2, 3], 4]
- suppress_keyword_warning do
- m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
+ m().should == [[], 1]
+ m(1, 2, 3, b: 4).should == [[1, 2, 3], 4]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
+ end
+
+ a = mock("splat")
+ a.should_not_receive(:to_ary)
+ m(*a).should == [[a], 1]
end
- a = mock("splat")
- a.should_not_receive(:to_ary)
- m(*a).should == [[a], 1]
- end
+ evaluate <<-ruby do
+ def m(*, **) end
+ ruby
- evaluate <<-ruby do
- def m(*, **) end
- ruby
+ m().should be_nil
+ m(a: 1, b: 2).should be_nil
+ m(1, 2, 3, a: 4, b: 5).should be_nil
- m().should be_nil
- m(a: 1, b: 2).should be_nil
- m(1, 2, 3, a: 4, b: 5).should be_nil
+ h = mock("keyword splat")
+ h.should_receive(:to_hash).and_return({a: 1})
+ suppress_keyword_warning do
+ m(h).should be_nil
+ end
- h = mock("keyword splat")
- h.should_receive(:to_hash).and_return({a: 1})
- suppress_keyword_warning do
- m(h).should be_nil
+ h = mock("keyword splat")
+ error = RuntimeError.new("error while converting to a hash")
+ h.should_receive(:to_hash).and_raise(error)
+ -> { m(h) }.should raise_error(error)
end
- h = mock("keyword splat")
- error = RuntimeError.new("error while converting to a hash")
- h.should_receive(:to_hash).and_raise(error)
- -> { m(h) }.should raise_error(error)
- end
-
- ruby_version_is ""..."2.7" do
evaluate <<-ruby do
def m(*a, **) a end
ruby
@@ -1093,7 +1178,57 @@ describe "A method" do
end
end
- ruby_version_is "2.7" do
+ ruby_version_is "2.7"...'3.0' do
+ evaluate <<-ruby do
+ def m(*, a:) a end
+ ruby
+
+ m(a: 1).should == 1
+ m(1, 2, a: 3).should == 3
+ suppress_keyword_warning do
+ m("a" => 1, a: 2).should == 2
+ end
+ end
+
+ evaluate <<-ruby do
+ def m(*a, b:) [a, b] end
+ ruby
+
+ m(b: 1).should == [[], 1]
+ m(1, 2, b: 3).should == [[1, 2], 3]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
+ end
+ end
+
+ evaluate <<-ruby do
+ def m(*, a: 1) a end
+ ruby
+
+ m().should == 1
+ m(1, 2).should == 1
+ m(a: 2).should == 2
+ m(1, a: 2).should == 2
+ suppress_keyword_warning do
+ m("a" => 1, a: 2).should == 2
+ end
+ end
+
+ evaluate <<-ruby do
+ def m(*a, b: 1) [a, b] end
+ ruby
+
+ m().should == [[], 1]
+ m(1, 2, 3, b: 4).should == [[1, 2, 3], 4]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
+ end
+
+ a = mock("splat")
+ a.should_not_receive(:to_ary)
+ m(*a).should == [[a], 1]
+ end
+
evaluate <<-ruby do
def m(*a, **) a end
ruby
@@ -1184,6 +1319,149 @@ describe "A method" do
m(*bo, **bo).should == [[1, 2, 3], {:b => 2, :c => 3}]
end
+
+ evaluate <<-ruby do
+ def m(*, a:) a end
+ ruby
+
+ m(a: 1).should == 1
+ m(1, 2, a: 3).should == 3
+ suppress_keyword_warning do
+ m("a" => 1, a: 2).should == 2
+ end
+ end
+
+ evaluate <<-ruby do
+ def m(*a, b:) [a, b] end
+ ruby
+
+ m(b: 1).should == [[], 1]
+ m(1, 2, b: 3).should == [[1, 2], 3]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
+ end
+ end
+
+ evaluate <<-ruby do
+ def m(*, a: 1) a end
+ ruby
+
+ m().should == 1
+ m(1, 2).should == 1
+ m(a: 2).should == 2
+ m(1, a: 2).should == 2
+ suppress_keyword_warning do
+ m("a" => 1, a: 2).should == 2
+ end
+ end
+
+ evaluate <<-ruby do
+ def m(*a, b: 1) [a, b] end
+ ruby
+
+ m().should == [[], 1]
+ m(1, 2, 3, b: 4).should == [[1, 2, 3], 4]
+ suppress_keyword_warning do
+ m("a" => 1, b: 2).should == [[{"a" => 1}], 2]
+ end
+
+ a = mock("splat")
+ a.should_not_receive(:to_ary)
+ m(*a).should == [[a], 1]
+ end
+
+ evaluate <<-ruby do
+ def m(*a, **) a end
+ ruby
+
+ m().should == []
+ m(1, 2, 3, a: 4, b: 5).should == [1, 2, 3]
+ m("a" => 1, a: 1).should == []
+ m(1, **{a: 2}).should == [1]
+
+ h = mock("keyword splat")
+ h.should_receive(:to_hash)
+ -> { m(**h) }.should raise_error(TypeError)
+ end
+
+ evaluate <<-ruby do
+ def m(*, **k) k end
+ ruby
+
+ m().should == {}
+ m(1, 2, 3, a: 4, b: 5).should == {a: 4, b: 5}
+ m("a" => 1, a: 1).should == {"a" => 1, a: 1}
+
+ h = mock("keyword splat")
+ h.should_receive(:to_hash).and_return({a: 1})
+ suppress_keyword_warning do
+ m(h).should == {a: 1}
+ end
+ end
+
+ evaluate <<-ruby do
+ def m(a = nil, **k) [a, k] end
+ ruby
+
+ m().should == [nil, {}]
+ m("a" => 1).should == [nil, {"a" => 1}]
+ m(a: 1).should == [nil, {a: 1}]
+ m("a" => 1, a: 1).should == [nil, {"a" => 1, a: 1}]
+ m({ "a" => 1 }, a: 1).should == [{"a" => 1}, {a: 1}]
+ suppress_keyword_warning do
+ m({a: 1}, {}).should == [{a: 1}, {}]
+ end
+
+ h = {"a" => 1, b: 2}
+ suppress_keyword_warning do
+ m(h).should == [{"a" => 1}, {b: 2}]
+ end
+ h.should == {"a" => 1, b: 2}
+
+ h = {"a" => 1}
+ m(h).first.should == h
+
+ h = {}
+ suppress_keyword_warning do
+ m(h).should == [nil, {}]
+ end
+
+ hh = {}
+ h = mock("keyword splat empty hash")
+ h.should_receive(:to_hash).and_return({a: 1})
+ suppress_keyword_warning do
+ m(h).should == [nil, {a: 1}]
+ end
+
+ h = mock("keyword splat")
+ h.should_receive(:to_hash).and_return({"a" => 1})
+ m(h).should == [h, {}]
+ end
+
+ evaluate <<-ruby do
+ def m(*a, **k) [a, k] end
+ ruby
+
+ m().should == [[], {}]
+ m(1).should == [[1], {}]
+ m(a: 1, b: 2).should == [[], {a: 1, b: 2}]
+ m(1, 2, 3, a: 2).should == [[1, 2, 3], {a: 2}]
+
+ m("a" => 1).should == [[], {"a" => 1}]
+ m(a: 1).should == [[], {a: 1}]
+ m("a" => 1, a: 1).should == [[], {"a" => 1, a: 1}]
+ m({ "a" => 1 }, a: 1).should == [[{"a" => 1}], {a: 1}]
+ suppress_keyword_warning do
+ m({a: 1}, {}).should == [[{a: 1}], {}]
+ end
+ m({a: 1}, {"a" => 1}).should == [[{a: 1}, {"a" => 1}], {}]
+
+ bo = BasicObject.new
+ def bo.to_a; [1, 2, 3]; end
+ def bo.to_hash; {:b => 2, :c => 3}; end
+
+ m(*bo, **bo).should == [[1, 2, 3], {:b => 2, :c => 3}]
+ end
end
evaluate <<-ruby do
@@ -1261,9 +1539,7 @@ describe "A method" do
m(a: 1).should == [1, {}]
m(a: 1, b: 2, c: 3).should == [1, {b: 2, c: 3}]
- suppress_warning do
- m("a" => 1, a: 1, b: 2).should == [1, {"a" => 1, b: 2}]
- end
+ m("a" => 1, a: 1, b: 2).should == [1, {"a" => 1, b: 2}]
end
end
@@ -1361,37 +1637,125 @@ describe "A method" do
result.should == [1, 1, [], 2, 3, 2, 4, { h: 5, i: 6 }, l]
end
- evaluate <<-ruby do
- def m(a, b = nil, c = nil, d, e: nil, **f)
- [a, b, c, d, e, f]
+ ruby_version_is "2.7" do
+ evaluate <<-ruby do
+ def m(a, **nil); a end;
+ ruby
+
+ m({a: 1}).should == {a: 1}
+ m({"a" => 1}).should == {"a" => 1}
+
+ -> { m(a: 1) }.should raise_error(ArgumentError)
+ -> { m(**{a: 1}) }.should raise_error(ArgumentError)
+ -> { m("a" => 1) }.should raise_error(ArgumentError)
+ end
+ end
+
+ ruby_version_is ''...'3.0' do
+ evaluate <<-ruby do
+ def m(a, b = nil, c = nil, d, e: nil, **f)
+ [a, b, c, d, e, f]
+ end
+ ruby
+
+ result = m(1, 2)
+ result.should == [1, nil, nil, 2, nil, {}]
+
+ suppress_warning do
+ result = m(1, 2, {foo: :bar})
+ result.should == [1, nil, nil, 2, nil, {foo: :bar}]
end
- ruby
- result = m(1, 2)
- result.should == [1, nil, nil, 2, nil, {}]
+ result = m(1, {foo: :bar})
+ result.should == [1, nil, nil, {foo: :bar}, nil, {}]
+ end
+ end
+
+ ruby_version_is '3.0' do
+ evaluate <<-ruby do
+ def m(a, b = nil, c = nil, d, e: nil, **f)
+ [a, b, c, d, e, f]
+ end
+ ruby
+
+ result = m(1, 2)
+ result.should == [1, nil, nil, 2, nil, {}]
- suppress_warning do
result = m(1, 2, {foo: :bar})
- result.should == [1, nil, nil, 2, nil, {foo: :bar}]
+ result.should == [1, 2, nil, {foo: :bar}, nil, {}]
+
+ result = m(1, {foo: :bar})
+ result.should == [1, nil, nil, {foo: :bar}, nil, {}]
+ end
+ end
+ end
+
+ ruby_version_is '2.7' do
+ context 'when passing an empty keyword splat to a method that does not accept keywords' do
+ evaluate <<-ruby do
+ def m(*a); a; end
+ ruby
+
+ h = {}
+ m(**h).should == []
end
+ end
+ end
- result = m(1, {foo: :bar})
- result.should == [1, nil, nil, {foo: :bar}, nil, {}]
+ ruby_version_is '2.7'...'3.0' do
+ context 'when passing an empty keyword splat to a method that does not accept keywords' do
+ evaluate <<-ruby do
+ def m(a); a; end
+ ruby
+ h = {}
+
+ -> do
+ m(**h).should == {}
+ end.should complain(/warning: Passing the keyword argument as the last hash parameter is deprecated/)
+ end
end
end
- context "assigns keyword arguments from a passed Hash without modifying it" do
- evaluate <<-ruby do
- def m(a: nil); a; end
- ruby
+ ruby_version_is ''...'3.0' do
+ context "assigns keyword arguments from a passed Hash without modifying it" do
+ evaluate <<-ruby do
+ def m(a: nil); a; end
+ ruby
- options = {a: 1}.freeze
- -> do
- suppress_warning do
- m(options).should == 1
- end
- end.should_not raise_error
- options.should == {a: 1}
+ options = {a: 1}.freeze
+ -> do
+ suppress_warning do
+ m(options).should == 1
+ end
+ end.should_not raise_error
+ options.should == {a: 1}
+ end
+ end
+ end
+
+ ruby_version_is '3.0' do
+ context 'when passing an empty keyword splat to a method that does not accept keywords' do
+ evaluate <<-ruby do
+ def m(a); a; end
+ ruby
+ h = {}
+
+ -> do
+ m(**h).should == {}
+ end.should raise_error(ArgumentError)
+ end
+ end
+
+ context "raises ArgumentError if passing hash as keyword arguments" do
+ evaluate <<-ruby do
+ def m(a: nil); a; end
+ ruby
+
+ options = {a: 1}.freeze
+ -> do
+ m(options)
+ end.should raise_error(ArgumentError)
+ end
end
end
end
@@ -1485,3 +1849,16 @@ describe "An array-dereference method ([])" do
end
end
end
+
+ruby_version_is '3.0' do
+ describe "An endless method definition" do
+ evaluate <<-ruby do
+ def m(a) = a
+ ruby
+
+ a = b = m 1
+ a.should == 1
+ b.should == 1
+ end
+ end
+end
diff --git a/spec/ruby/language/module_spec.rb b/spec/ruby/language/module_spec.rb
index 1b41e184bb..1a5fcaf46f 100644
--- a/spec/ruby/language/module_spec.rb
+++ b/spec/ruby/language/module_spec.rb
@@ -43,7 +43,7 @@ describe "The module keyword" do
-> { module ModuleSpecs::Modules::A; end }.should raise_error(TypeError)
end
- it "raises a TypeError if the constant is a Fixnum" do
+ it "raises a TypeError if the constant is an Integer" do
-> { module ModuleSpecs::Modules::B; end }.should raise_error(TypeError)
end
@@ -69,10 +69,20 @@ describe "Assigning an anonymous module to a constant" do
mod.name.should == "ModuleSpecs_CS1"
end
- it "does not set the name of a module scoped by an anonymous module" do
- a, b = Module.new, Module.new
- a::B = b
- b.name.should be_nil
+ ruby_version_is ""..."3.0" do
+ it "does not set the name of a module scoped by an anonymous module" do
+ a, b = Module.new, Module.new
+ a::B = b
+ b.name.should be_nil
+ end
+ end
+
+ ruby_version_is "3.0" do
+ it "sets the name of a module scoped by an anonymous module" do
+ a, b = Module.new, Module.new
+ a::B = b
+ b.name.should.end_with? '::B'
+ end
end
it "sets the name of contained modules when assigning a toplevel anonymous module" do
diff --git a/spec/ruby/language/numbered_parameters_spec.rb b/spec/ruby/language/numbered_parameters_spec.rb
new file mode 100644
index 0000000000..b05c373a68
--- /dev/null
+++ b/spec/ruby/language/numbered_parameters_spec.rb
@@ -0,0 +1,106 @@
+require_relative '../spec_helper'
+
+ruby_version_is "2.7" do
+ describe "Numbered parameters" do
+ it "provides default parameters _1, _2, ... in a block" do
+ -> { _1 }.call("a").should == "a"
+ proc { _1 }.call("a").should == "a"
+ lambda { _1 }.call("a").should == "a"
+ ["a"].map { _1 }.should == ["a"]
+ end
+
+ it "assigns nil to not passed parameters" do
+ proc { [_1, _2] }.call("a").should == ["a", nil]
+ proc { [_1, _2] }.call("a", "b").should == ["a", "b"]
+ end
+
+ it "supports variables _1-_9 only for the first 9 passed parameters" do
+ block = proc { [_1, _2, _3, _4, _5, _6, _7, _8, _9] }
+ result = block.call(1, 2, 3, 4, 5, 6, 7, 8, 9)
+ result.should == [1, 2, 3, 4, 5, 6, 7, 8, 9]
+ end
+
+ it "does not support more than 9 parameters" do
+ -> {
+ proc { [_10] }.call(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+ }.should raise_error(NameError, /undefined local variable or method `_10'/)
+ end
+
+ it "can not be used in both outer and nested blocks at the same time" do
+ -> {
+ eval("-> { _1; -> { _2 } }")
+ }.should raise_error(SyntaxError, /numbered parameter is already used in.+ outer block here/m)
+ end
+
+ ruby_version_is '2.7'...'3.0' do
+ it "can be overwritten with local variable" do
+ suppress_warning do
+ eval <<~CODE
+ _1 = 0
+ proc { _1 }.call("a").should == 0
+ CODE
+ end
+ end
+
+ it "warns when numbered parameter is overwritten with local variable" do
+ -> {
+ eval("_1 = 0")
+ }.should complain(/warning: `_1' is reserved for numbered parameter; consider another name/)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "cannot be overwritten with local variable" do
+ -> {
+ eval <<~CODE
+ _1 = 0
+ proc { _1 }.call("a").should == 0
+ CODE
+ }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
+ end
+
+ it "errors when numbered parameter is overwritten with local variable" do
+ -> {
+ eval("_1 = 0")
+ }.should raise_error(SyntaxError, /_1 is reserved for numbered parameter/)
+ end
+ end
+
+ it "raises SyntaxError when block parameters are specified explicitly" do
+ -> { eval("-> () { _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("-> (x) { _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+
+ -> { eval("proc { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("proc { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+
+ -> { eval("lambda { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("lambda { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+
+ -> { eval("['a'].map { || _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("['a'].map { |x| _1 }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ end
+
+ it "affects block arity" do
+ -> { _1 }.arity.should == 1
+ -> { _2 }.arity.should == 2
+ -> { _3 }.arity.should == 3
+ -> { _4 }.arity.should == 4
+ -> { _5 }.arity.should == 5
+ -> { _6 }.arity.should == 6
+ -> { _7 }.arity.should == 7
+ -> { _8 }.arity.should == 8
+ -> { _9 }.arity.should == 9
+
+ -> { _9 }.arity.should == 9
+ proc { _9 }.arity.should == 9
+ lambda { _9 }.arity.should == 9
+ end
+
+ it "does not work in methods" do
+ obj = Object.new
+ def obj.foo; _1 end
+
+ -> { obj.foo("a") }.should raise_error(ArgumentError, /wrong number of arguments/)
+ end
+ end
+end
diff --git a/spec/ruby/language/numbers_spec.rb b/spec/ruby/language/numbers_spec.rb
index c82a630632..418bc60fa6 100644
--- a/spec/ruby/language/numbers_spec.rb
+++ b/spec/ruby/language/numbers_spec.rb
@@ -45,6 +45,10 @@ describe "A number literal" do
eval('-3r').should == Rational(-3, 1)
end
+ it "can be a float literal with trailing 'r' to represent a Rational" do
+ eval('0.0174532925199432957r').should == Rational(174532925199432957, 10000000000000000000)
+ end
+
it "can be an bignum literal with trailing 'r' to represent a Rational" do
eval('1111111111111111111111111111111111111111111111r').should == Rational(1111111111111111111111111111111111111111111111, 1)
eval('-1111111111111111111111111111111111111111111111r').should == Rational(-1111111111111111111111111111111111111111111111, 1)
diff --git a/spec/ruby/language/pattern_matching_spec.rb b/spec/ruby/language/pattern_matching_spec.rb
new file mode 100644
index 0000000000..edc3826448
--- /dev/null
+++ b/spec/ruby/language/pattern_matching_spec.rb
@@ -0,0 +1,1035 @@
+require_relative '../spec_helper'
+
+ruby_version_is "2.7" do
+ describe "Pattern matching" do
+ # TODO: Remove excessive eval calls when support of previous version
+ # Ruby 2.6 will be dropped
+
+ before do
+ ScratchPad.record []
+ end
+
+ ruby_version_is "3.0" do
+ it "can be standalone assoc operator that deconstructs value" do
+ suppress_warning do
+ eval(<<-RUBY).should == [0, 1]
+ [0, 1] => [a, b]
+ [a, b]
+ RUBY
+ end
+ end
+ end
+
+ it "extends case expression with case/in construction" do
+ eval(<<~RUBY).should == :bar
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ end
+ RUBY
+ end
+
+ it "allows using then operator" do
+ eval(<<~RUBY).should == :bar
+ case [0, 1]
+ in [0] then :foo
+ in [0, 1] then :bar
+ end
+ RUBY
+ end
+
+ describe "warning" do
+ before do
+ ruby_version_is ""..."3.0" do
+ @src = 'case [0, 1]; in [a, b]; end'
+ end
+
+ ruby_version_is "3.0" do
+ @src = '[0, 1] => [a, b]'
+ end
+ end
+
+ 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
+
+ it "binds variables" do
+ eval(<<~RUBY).should == 1
+ case [0, 1]
+ in [0, a]
+ a
+ end
+ RUBY
+ end
+
+ it "cannot mix in and when operators" do
+ -> {
+ eval <<~RUBY
+ case []
+ when 1 == 1
+ in []
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /syntax error, unexpected `in'/)
+
+ -> {
+ eval <<~RUBY
+ case []
+ in []
+ when 1 == 1
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /syntax error, unexpected `when'/)
+ end
+
+ it "checks patterns until the first matching" do
+ eval(<<~RUBY).should == :bar
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ in [0, 1]
+ :baz
+ end
+ RUBY
+ end
+
+ it "executes else clause if no pattern matches" do
+ eval(<<~RUBY).should == false
+ case [0, 1]
+ in [0]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "raises NoMatchingPatternError if no pattern matches and no else clause" do
+ -> {
+ eval <<~RUBY
+ case [0, 1]
+ in [0]
+ end
+ RUBY
+ }.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
+ end
+
+ it "does not allow calculation or method calls in a pattern" do
+ -> {
+ eval <<~RUBY
+ case 0
+ in 1 + 1
+ true
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /unexpected/)
+ end
+
+ describe "guards" do
+ it "supports if guard" do
+ eval(<<~RUBY).should == false
+ case 0
+ in 0 if false
+ true
+ else
+ false
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case 0
+ in 0 if true
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "supports unless guard" do
+ eval(<<~RUBY).should == false
+ case 0
+ in 0 unless true
+ true
+ else
+ false
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case 0
+ in 0 unless false
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "makes bound variables visible in guard" do
+ eval(<<~RUBY).should == true
+ case [0, 1]
+ in [a, 1] if a >= 0
+ true
+ end
+ RUBY
+ end
+
+ it "does not evaluate guard if pattern does not match" do
+ eval <<~RUBY
+ case 0
+ in 1 if (ScratchPad << :foo) || true
+ else
+ end
+ RUBY
+
+ ScratchPad.recorded.should == []
+ end
+
+ it "takes guards into account when there are several matching patterns" do
+ eval(<<~RUBY).should == :bar
+ case 0
+ in 0 if false
+ :foo
+ in 0 if true
+ :bar
+ end
+ RUBY
+ end
+
+ it "executes else clause if no guarded pattern matches" do
+ eval(<<~RUBY).should == false
+ case 0
+ in 0 if false
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "raises NoMatchingPatternError if no guarded pattern matches and no else clause" do
+ -> {
+ eval <<~RUBY
+ case [0, 1]
+ in [0, 1] if false
+ end
+ RUBY
+ }.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
+ end
+ end
+
+ describe "value pattern" do
+ it "matches an object such that pattern === object" do
+ eval(<<~RUBY).should == true
+ case 0
+ in 0
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case 0
+ in (-1..1)
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case 0
+ in Integer
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case "0"
+ in /0/
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case "0"
+ in ->(s) { s == "0" }
+ true
+ end
+ RUBY
+ end
+
+ it "allows string literal with interpolation" do
+ x = "x"
+
+ eval(<<~RUBY).should == true
+ case "x"
+ in "#{x + ""}"
+ true
+ end
+ RUBY
+ end
+ end
+
+ describe "variable pattern" do
+ it "matches a value and binds variable name to this value" do
+ eval(<<~RUBY).should == 0
+ case 0
+ in a
+ a
+ end
+ RUBY
+ end
+
+ it "makes bounded variable visible outside a case statement scope" do
+ eval(<<~RUBY).should == 0
+ case 0
+ in a
+ end
+
+ a
+ RUBY
+ end
+
+ it "create local variables even if a pattern doesn't match" do
+ eval(<<~RUBY).should == [0, nil, nil]
+ case 0
+ in a
+ in b
+ in c
+ end
+
+ [a, b, c]
+ RUBY
+ end
+
+ it "allow using _ name to drop values" do
+ eval(<<~RUBY).should == 0
+ case [0, 1]
+ in [a, _]
+ a
+ end
+ RUBY
+ end
+
+ it "supports using _ in a pattern several times" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in [0, _, _]
+ true
+ end
+ RUBY
+ end
+
+ it "supports using any name with _ at the beginning in a pattern several times" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in [0, _x, _x]
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1, c: 2}
+ in {a: 0, b: _x, c: _x}
+ true
+ end
+ RUBY
+ end
+
+ it "does not support using variable name (except _) several times" do
+ -> {
+ eval <<~RUBY
+ case [0]
+ in [a, a]
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /duplicated variable name/)
+ end
+
+ it "supports existing variables in a pattern specified with ^ operator" do
+ a = 0
+
+ eval(<<~RUBY).should == true
+ case 0
+ in ^a
+ true
+ end
+ RUBY
+ end
+
+ it "allows applying ^ operator to bound variables" do
+ eval(<<~RUBY).should == 1
+ case [1, 1]
+ in [n, ^n]
+ n
+ end
+ RUBY
+
+ eval(<<~RUBY).should == false
+ case [1, 2]
+ in [n, ^n]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "requires bound variable to be specified in a pattern before ^ operator when it relies on a bound variable" do
+ -> {
+ eval <<~RUBY
+ case [1, 2]
+ in [^n, n]
+ true
+ else
+ false
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /n: no such local variable/)
+ end
+ end
+
+ describe "alternative pattern" do
+ it "matches if any of patterns matches" do
+ eval(<<~RUBY).should == true
+ case 0
+ in 0 | 1 | 2
+ true
+ end
+ RUBY
+ end
+
+ it "does not support variable binding" do
+ -> {
+ eval <<~RUBY
+ case [0, 1]
+ in [0, 0] | [0, a]
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /illegal variable in alternative pattern/)
+ end
+
+ it "support underscore prefixed variables in alternation" do
+ eval(<<~RUBY).should == true
+ case [0, 1]
+ in [1, _]
+ false
+ in [0, 0] | [0, _a]
+ true
+ end
+ RUBY
+ end
+ end
+
+ describe "AS pattern" do
+ it "binds a variable to a value if pattern matches" do
+ eval(<<~RUBY).should == 0
+ case 0
+ in Integer => n
+ n
+ end
+ RUBY
+ end
+
+ it "can be used as a nested pattern" do
+ eval(<<~RUBY).should == [2, 3]
+ case [1, [2, 3]]
+ in [1, Array => ary]
+ ary
+ end
+ RUBY
+ end
+ end
+
+ describe "Array pattern" do
+ it "supports form Constant(pat, pat, ...)" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in Array(0, 1, 2)
+ true
+ end
+ RUBY
+ end
+
+ it "supports form Constant[pat, pat, ...]" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in Array[0, 1, 2]
+ true
+ end
+ RUBY
+ end
+
+ it "supports form [pat, pat, ...]" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in [0, 1, 2]
+ true
+ end
+ RUBY
+ end
+
+ it "supports form pat, pat, ..." do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2]
+ in 0, 1, 2
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == 1
+ case [0, 1, 2]
+ in 0, a, 2
+ a
+ end
+ RUBY
+
+ eval(<<~RUBY).should == [1, 2]
+ case [0, 1, 2]
+ in 0, *rest
+ rest
+ end
+ RUBY
+ end
+
+ it "matches an object with #deconstruct method which returns an array and each element in array matches element in pattern" do
+ obj = Object.new
+ def obj.deconstruct; [0, 1] end
+
+ eval(<<~RUBY).should == true
+ case obj
+ in [Integer, Integer]
+ true
+ end
+ RUBY
+ end
+
+ it "does not match object if Constant === object returns false" do
+ eval(<<~RUBY).should == false
+ case [0, 1, 2]
+ in String[0, 1, 2]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "does not match object without #deconstruct method" do
+ obj = Object.new
+
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "raises TypeError if #deconstruct method does not return array" do
+ obj = Object.new
+ def obj.deconstruct; "" end
+
+ -> {
+ eval <<~RUBY
+ case obj
+ in Object[]
+ else
+ end
+ RUBY
+ }.should raise_error(TypeError, /deconstruct must return Array/)
+ end
+
+ it "does not match object if elements of array returned by #deconstruct method does not match elements in pattern" do
+ obj = Object.new
+ def obj.deconstruct; [1] end
+
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[0]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "binds variables" do
+ eval(<<~RUBY).should == [0, 1, 2]
+ case [0, 1, 2]
+ in [a, b, c]
+ [a, b, c]
+ end
+ RUBY
+ end
+
+ it "supports splat operator *rest" do
+ eval(<<~RUBY).should == [1, 2]
+ case [0, 1, 2]
+ in [0, *rest]
+ rest
+ end
+ RUBY
+ end
+
+ it "does not match partially by default" do
+ eval(<<~RUBY).should == false
+ case [0, 1, 2, 3]
+ in [1, 2]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "does match partially from the array beginning if list + , syntax used" do
+ eval(<<~RUBY).should == true
+ case [0, 1, 2, 3]
+ in [0, 1,]
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == true
+ case [0, 1, 2, 3]
+ in 0, 1,;
+ true
+ end
+ RUBY
+ end
+
+ it "matches [] with []" do
+ eval(<<~RUBY).should == true
+ case []
+ in []
+ true
+ end
+ RUBY
+ end
+
+ it "matches anything with *" do
+ eval(<<~RUBY).should == true
+ case [0, 1]
+ in *;
+ true
+ end
+ RUBY
+ end
+ end
+
+ describe "Hash pattern" do
+ it "supports form Constant(id: pat, id: pat, ...)" do
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1}
+ in Hash(a: 0, b: 1)
+ true
+ end
+ RUBY
+ end
+
+ it "supports form Constant[id: pat, id: pat, ...]" do
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1}
+ in Hash[a: 0, b: 1]
+ true
+ end
+ RUBY
+ end
+
+ it "supports form {id: pat, id: pat, ...}" do
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1}
+ in {a: 0, b: 1}
+ true
+ end
+ RUBY
+ end
+
+ it "supports form id: pat, id: pat, ..." do
+ eval(<<~RUBY).should == true
+ case {a: 0, b: 1}
+ in a: 0, b: 1
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in a: a, b: b
+ [a, b]
+ end
+ RUBY
+
+ eval(<<~RUBY).should == { b: 1, c: 2 }
+ case {a: 0, b: 1, c: 2}
+ in a: 0, **rest
+ rest
+ end
+ RUBY
+ end
+
+ it "supports a: which means a: a" do
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in Hash(a:, b:)
+ [a, b]
+ end
+ RUBY
+
+ a = b = nil
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in Hash[a:, b:]
+ [a, b]
+ end
+ RUBY
+
+ a = b = nil
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in {a:, b:}
+ [a, b]
+ end
+ RUBY
+
+ a = nil
+ eval(<<~RUBY).should == [0, {b: 1, c: 2}]
+ case {a: 0, b: 1, c: 2}
+ in {a:, **rest}
+ [a, rest]
+ end
+ RUBY
+
+ a = b = nil
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in a:, b:
+ [a, b]
+ end
+ RUBY
+ end
+
+ it "can mix key (a:) and key-value (a: b) declarations" do
+ eval(<<~RUBY).should == [0, 1]
+ case {a: 0, b: 1}
+ in Hash(a:, b: x)
+ [a, x]
+ end
+ RUBY
+ end
+
+ it "supports 'string': key literal" do
+ eval(<<~RUBY).should == true
+ case {a: 0}
+ in {"a": 0}
+ true
+ end
+ RUBY
+ end
+
+ it "does not support non-symbol keys" do
+ -> {
+ eval <<~RUBY
+ case {a: 1}
+ in {"a" => 1}
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /unexpected/)
+ end
+
+ it "does not support string interpolation in keys" do
+ x = "a"
+
+ -> {
+ eval <<~'RUBY'
+ case {a: 1}
+ in {"#{x}": 1}
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /symbol literal with interpolation is not allowed/)
+ end
+
+ it "raise SyntaxError when keys duplicate in pattern" do
+ -> {
+ eval <<~RUBY
+ case {a: 1}
+ in {a: 1, b: 2, a: 3}
+ end
+ RUBY
+ }.should raise_error(SyntaxError, /duplicated key name/)
+ end
+
+ it "matches an object with #deconstruct_keys method which returns a Hash with equal keys and each value in Hash matches value in pattern" do
+ obj = Object.new
+ def obj.deconstruct_keys(*); {a: 1} end
+
+ eval(<<~RUBY).should == true
+ case obj
+ in {a: 1}
+ true
+ end
+ RUBY
+ end
+
+ it "does not match object if Constant === object returns false" do
+ eval(<<~RUBY).should == false
+ case {a: 1}
+ in String[a: 1]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "does not match object without #deconstruct_keys method" do
+ obj = Object.new
+
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "does not match object if #deconstruct_keys method does not return Hash" do
+ obj = Object.new
+ def obj.deconstruct_keys(*); "" end
+
+ -> {
+ eval <<~RUBY
+ case obj
+ in Object[a: 1]
+ end
+ RUBY
+ }.should raise_error(TypeError, /deconstruct_keys must return Hash/)
+ end
+
+ it "does not match object if #deconstruct_keys method returns Hash with non-symbol keys" do
+ obj = Object.new
+ def obj.deconstruct_keys(*); {"a" => 1} end
+
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "does not match object if elements of Hash returned by #deconstruct_keys method does not match values in pattern" do
+ obj = Object.new
+ def obj.deconstruct_keys(*); {a: 1} end
+
+ eval(<<~RUBY).should == false
+ case obj
+ in Object[a: 2]
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "passes keys specified in pattern as arguments to #deconstruct_keys method" do
+ obj = Object.new
+
+ def obj.deconstruct_keys(*args)
+ ScratchPad << args
+ {a: 1, b: 2, c: 3}
+ end
+
+ eval <<~RUBY
+ case obj
+ in Object[a: 1, b: 2, c: 3]
+ end
+ RUBY
+
+ ScratchPad.recorded.sort.should == [[[:a, :b, :c]]]
+ end
+
+ it "passes keys specified in pattern to #deconstruct_keys method if pattern contains double splat operator **" do
+ obj = Object.new
+
+ def obj.deconstruct_keys(*args)
+ ScratchPad << args
+ {a: 1, b: 2, c: 3}
+ end
+
+ eval <<~RUBY
+ case obj
+ in Object[a: 1, b: 2, **]
+ end
+ RUBY
+
+ ScratchPad.recorded.sort.should == [[[:a, :b]]]
+ end
+
+ it "passes nil to #deconstruct_keys method if pattern contains double splat operator **rest" do
+ obj = Object.new
+
+ def obj.deconstruct_keys(*args)
+ ScratchPad << args
+ {a: 1, b: 2}
+ end
+
+ eval <<~RUBY
+ case obj
+ in Object[a: 1, **rest]
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [[nil]]
+ end
+
+ it "binds variables" do
+ eval(<<~RUBY).should == [0, 1, 2]
+ case {a: 0, b: 1, c: 2}
+ in {a: x, b: y, c: z}
+ [x, y, z]
+ end
+ RUBY
+ end
+
+ it "supports double splat operator **rest" do
+ eval(<<~RUBY).should == {b: 1, c: 2}
+ case {a: 0, b: 1, c: 2}
+ in {a: 0, **rest}
+ rest
+ end
+ RUBY
+ end
+
+ it "treats **nil like there should not be any other keys in a matched Hash" do
+ eval(<<~RUBY).should == true
+ case {a: 1, b: 2}
+ in {a: 1, b: 2, **nil}
+ true
+ end
+ RUBY
+
+ eval(<<~RUBY).should == false
+ case {a: 1, b: 2}
+ in {a: 1, **nil}
+ true
+ else
+ false
+ end
+ RUBY
+ end
+
+ it "can match partially" do
+ eval(<<~RUBY).should == true
+ case {a: 1, b: 2}
+ in {a: 1}
+ true
+ end
+ RUBY
+ end
+
+ it "matches {} with {}" do
+ eval(<<~RUBY).should == true
+ case {}
+ in {}
+ true
+ end
+ RUBY
+ end
+
+ it "matches anything with **" do
+ eval(<<~RUBY).should == true
+ case {a: 1}
+ in **;
+ true
+ end
+ RUBY
+ end
+ end
+
+ describe "refinements" do
+ it "are used for #deconstruct" do
+ refinery = Module.new do
+ refine Array do
+ def deconstruct
+ [0]
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinery
+
+ result = eval(<<~RUBY)
+ case []
+ in [0]
+ true
+ end
+ RUBY
+ end
+
+ result.should == true
+ end
+
+ it "are used for #deconstruct_keys" do
+ refinery = Module.new do
+ refine Hash do
+ def deconstruct_keys(_)
+ {a: 0}
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinery
+
+ result = eval(<<~RUBY)
+ case {}
+ in a: 0
+ true
+ end
+ RUBY
+ end
+
+ result.should == true
+ end
+
+ it "are used for #=== in constant pattern" do
+ refinery = Module.new do
+ refine Array.singleton_class do
+ def ===(obj)
+ obj.is_a?(Hash)
+ end
+ end
+ end
+
+ result = nil
+ Module.new do
+ using refinery
+
+ result = eval(<<~RUBY)
+ case {}
+ in Array
+ true
+ end
+ RUBY
+ end
+
+ result.should == true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb
index cdf2c28dcb..b1f5d80ad4 100644
--- a/spec/ruby/language/predefined_spec.rb
+++ b/spec/ruby/language/predefined_spec.rb
@@ -53,10 +53,10 @@ describe "Predefined global $~" do
it "is set to nil if the last match was unsuccessful" do
/foo/ =~ 'foo'
- $~.nil?.should == false
+ $~.should_not.nil?
/foo/ =~ 'bar'
- $~.nil?.should == true
+ $~.should.nil?
end
it "is set at the method-scoped level rather than block-scoped" do
@@ -398,6 +398,22 @@ describe "Predefined global $!" do
$!.should == nil
end
+ it "should be cleared when an exception is rescued even when a non-local return from block" do
+ def foo
+ [ 1 ].each do
+ begin
+ raise StandardError.new('err')
+ rescue => e
+ $!.should == e
+ return
+ end
+ end
+ end
+
+ foo
+ $!.should == nil
+ end
+
it "should not be cleared when an exception is not rescued" do
e = StandardError.new
begin
@@ -502,7 +518,7 @@ $\ String The string appended to the output of every call
Kernel#print and IO#write. The default value is nil.
$, String The separator string output between the parameters to methods such as
Kernel#print and Array#join. Defaults to nil, which adds no text.
-$. Fixnum The number of the last line read from the current input file.
+$. Integer The number of the last line read from the current input file.
$; String The default separator pattern used by String#split. May be set from the
command line using the -F flag.
$< Object An object that provides access to the concatenation of the contents of all
@@ -528,6 +544,7 @@ $stdout IO The current standard output. Assignment to $std
describe "Predefined global $/" do
before :each do
+ @verbose, $VERBOSE = $VERBOSE, nil
@dollar_slash = $/
@dollar_dash_zero = $-0
end
@@ -535,6 +552,7 @@ describe "Predefined global $/" do
after :each do
$/ = @dollar_slash
$-0 = @dollar_dash_zero
+ $VERBOSE = @verbose
end
it "can be assigned a String" do
@@ -565,7 +583,7 @@ describe "Predefined global $/" do
-> { $/ = obj }.should raise_error(TypeError)
end
- it "raises a TypeError if assigned a Fixnum" do
+ it "raises a TypeError if assigned an Integer" do
-> { $/ = 1 }.should raise_error(TypeError)
end
@@ -576,6 +594,7 @@ end
describe "Predefined global $-0" do
before :each do
+ @verbose, $VERBOSE = $VERBOSE, nil
@dollar_slash = $/
@dollar_dash_zero = $-0
end
@@ -583,6 +602,7 @@ describe "Predefined global $-0" do
after :each do
$/ = @dollar_slash
$-0 = @dollar_dash_zero
+ $VERBOSE = @verbose
end
it "can be assigned a String" do
@@ -612,7 +632,7 @@ describe "Predefined global $-0" do
-> { $-0 = obj }.should raise_error(TypeError)
end
- it "raises a TypeError if assigned a Fixnum" do
+ it "raises a TypeError if assigned an Integer" do
-> { $-0 = 1 }.should raise_error(TypeError)
end
@@ -633,6 +653,12 @@ describe "Predefined global $," do
it "raises TypeError if assigned a non-String" do
-> { $, = Object.new }.should raise_error(TypeError)
end
+
+ ruby_version_is "2.7" do
+ it "warns if assigned non-nil" do
+ -> { $, = "_" }.should complain(/warning: `\$,' is deprecated/)
+ end
+ end
end
describe "Predefined global $." do
@@ -662,6 +688,18 @@ describe "Predefined global $." do
end
end
+describe "Predefined global $;" do
+ after :each do
+ $; = nil
+ end
+
+ ruby_version_is "2.7" do
+ it "warns if assigned non-nil" do
+ -> { $; = "_" }.should complain(/warning: `\$;' is deprecated/)
+ end
+ end
+end
+
describe "Predefined global $_" do
it "is set to the last line read by e.g. StringIO#gets" do
stdin = StringIO.new("foo\nbar\n", "r")
@@ -743,7 +781,7 @@ $* Array An array of strings containing the command-line
tion of the program. Options used by the Ruby interpreter will have been
removed. [r/o]
$" Array An array containing the filenames of modules loaded by require. [r/o]
-$$ Fixnum The process number of the program being executed. [r/o]
+$$ Integer The process number of the program being executed. [r/o]
$? Process::Status The exit status of the last child process to terminate. [r/o, thread]
$: Array An array of strings, where each string specifies a directory to be searched for
Ruby scripts and binary extensions used by the load and require methods.
@@ -895,6 +933,14 @@ describe "Global variable $-d" do
end
describe "Global variable $VERBOSE" do
+ before :each do
+ @verbose = $VERBOSE
+ end
+
+ after :each do
+ $VERBOSE = @verbose
+ end
+
it "converts truthy values to true" do
[true, 1, 0, [], ""].each do |true_value|
$VERBOSE = true_value
@@ -1053,8 +1099,6 @@ The following constants are defined by the Ruby interpreter.
DATA IO If the main program file contains the directive __END__, then
the constant DATA will be initialized so that reading from it will
return lines following __END__ from the source file.
-FALSE FalseClass Synonym for false.
-NIL NilClass Synonym for nil.
RUBY_PLATFORM String The identifier of the platform running this program. This string
is in the same form as the platform identifier used by the GNU
configure utility (which is not a coincidence).
@@ -1072,39 +1116,9 @@ SCRIPT_LINES__ Hash If a constant SCRIPT_LINES__ is defined and ref
the value.
TOPLEVEL_BINDING Binding A Binding object representing the binding at Ruby’s top level—
the level where programs are initially executed.
-TRUE TrueClass Synonym for true.
=end
describe "The predefined global constants" do
- before :each do
- @deprecated = Warning[:deprecated]
- Warning[:deprecated] = true
- end
- after :each do
- Warning[:deprecated] = @deprecated
- end
-
- it "includes TRUE" do
- Object.const_defined?(:TRUE).should == true
- -> {
- TRUE.should equal(true)
- }.should complain(/constant ::TRUE is deprecated/)
- end
-
- it "includes FALSE" do
- Object.const_defined?(:FALSE).should == true
- -> {
- FALSE.should equal(false)
- }.should complain(/constant ::FALSE is deprecated/)
- end
-
- it "includes NIL" do
- Object.const_defined?(:NIL).should == true
- -> {
- NIL.should equal(nil)
- }.should complain(/constant ::NIL is deprecated/)
- end
-
it "includes STDIN" do
Object.const_defined?(:STDIN).should == true
end
@@ -1240,3 +1254,25 @@ describe "The predefined global constant" do
end
end
end
+
+ruby_version_is "2.7" do
+ describe "$LOAD_PATH.resolve_feature_path" do
+ it "returns what will be loaded without actual loading, .rb file" do
+ extension, path = $LOAD_PATH.resolve_feature_path('set')
+ extension.should == :rb
+ path.should.end_with?('/set.rb')
+ end
+
+ it "returns what will be loaded without actual loading, .so file" do
+ require 'rbconfig'
+
+ extension, path = $LOAD_PATH.resolve_feature_path('etc')
+ extension.should == :so
+ path.should.end_with?("/etc.#{RbConfig::CONFIG['DLEXT']}")
+ end
+
+ it "raises LoadError if feature cannot be found" do
+ -> { $LOAD_PATH.resolve_feature_path('noop') }.should raise_error(LoadError)
+ end
+ end
+end
diff --git a/spec/ruby/language/range_spec.rb b/spec/ruby/language/range_spec.rb
index c720c5b98e..c0f90f84d6 100644
--- a/spec/ruby/language/range_spec.rb
+++ b/spec/ruby/language/range_spec.rb
@@ -16,4 +16,11 @@ describe "Literal Ranges" do
eval("(1...)").should == Range.new(1, nil, true)
end
end
+
+ ruby_version_is "2.7" do
+ it "creates beginless ranges" do
+ eval("(..1)").should == Range.new(nil, 1)
+ eval("(...1)").should == Range.new(nil, 1, true)
+ end
+ end
end
diff --git a/spec/ruby/language/regexp/character_classes_spec.rb b/spec/ruby/language/regexp/character_classes_spec.rb
index 5f4221e213..0cf1e9b6f4 100644
--- a/spec/ruby/language/regexp/character_classes_spec.rb
+++ b/spec/ruby/language/regexp/character_classes_spec.rb
@@ -609,6 +609,12 @@ describe "Regexp with character classes" do
"루비(Ruby)".match(/\p{Hangul}+/u).to_a.should == ["루비"]
end
+ ruby_bug "#17340", ''...'3.0' do
+ it "raises a RegexpError for an unterminated unicode property" do
+ -> { Regexp.new('\p{') }.should raise_error(RegexpError)
+ end
+ end
+
it "supports \\X (unicode 9.0 with UTR #51 workarounds)" do
# simple emoji without any fancy modifier or ZWJ
/\X/.match("\u{1F98A}").to_a.should == ["🦊"]
diff --git a/spec/ruby/language/regexp/encoding_spec.rb b/spec/ruby/language/regexp/encoding_spec.rb
index b8559c6b27..8e2a294b95 100644
--- a/spec/ruby/language/regexp/encoding_spec.rb
+++ b/spec/ruby/language/regexp/encoding_spec.rb
@@ -116,4 +116,16 @@ describe "Regexps with encoding modifiers" do
it "raises Encoding::CompatibilityError when trying =~ against different encodings" do
-> { /\A[[:space:]]*\z/ =~ " ".encode("UTF-16LE") }.should raise_error(Encoding::CompatibilityError)
end
+
+ it "computes the Regexp Encoding for each interpolated Regexp instance" do
+ make_regexp = -> str { /#{str}/ }
+
+ r = make_regexp.call("été".force_encoding(Encoding::UTF_8))
+ r.should.fixed_encoding?
+ r.encoding.should == Encoding::UTF_8
+
+ r = make_regexp.call("abc".force_encoding(Encoding::UTF_8))
+ r.should_not.fixed_encoding?
+ r.encoding.should == Encoding::US_ASCII
+ end
end
diff --git a/spec/ruby/language/regexp_spec.rb b/spec/ruby/language/regexp_spec.rb
index 67c7c034e9..def9bba5f7 100644
--- a/spec/ruby/language/regexp_spec.rb
+++ b/spec/ruby/language/regexp_spec.rb
@@ -18,6 +18,12 @@ describe "Literal Regexps" do
/Hello/.should be_kind_of(Regexp)
end
+ ruby_version_is "3.0" do
+ it "is frozen" do
+ /Hello/.should.frozen?
+ end
+ end
+
it "caches the Regexp object" do
rs = []
2.times do |i|
@@ -109,6 +115,12 @@ describe "Literal Regexps" do
/foo.(?<=\d)/.match("fooA foo1").to_a.should == ["foo1"]
end
+ # https://bugs.ruby-lang.org/issues/13671
+ it "raises a RegexpError for lookbehind with specific characters" do
+ r = Regexp.new("(?<!dss)", Regexp::IGNORECASE)
+ -> { r =~ "✨" }.should raise_error(RegexpError)
+ end
+
it "supports (?<! ) (negative lookbehind)" do
/foo.(?<!\d)/.match("foo1 fooA").to_a.should == ["fooA"]
end
diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb
index a912e17431..54cbae1440 100644
--- a/spec/ruby/language/rescue_spec.rb
+++ b/spec/ruby/language/rescue_spec.rb
@@ -23,11 +23,41 @@ describe "The rescue keyword" do
end.should == :caught
end
- it "can capture the raised exception in a local variable" do
- begin
- raise SpecificExampleException, "some text"
- rescue SpecificExampleException => e
- e.message.should == "some text"
+ describe 'can capture the raised exception' do
+ before :all do
+ require_relative 'fixtures/rescue_captures'
+ end
+
+ it 'in a local variable' do
+ RescueSpecs::LocalVariableCaptor.should_capture_exception
+ end
+
+ it 'in a class variable' do
+ RescueSpecs::ClassVariableCaptor.should_capture_exception
+ end
+
+ it 'in a constant' do
+ RescueSpecs::ConstantCaptor.should_capture_exception
+ end
+
+ it 'in a global variable' do
+ RescueSpecs::GlobalVariableCaptor.should_capture_exception
+ end
+
+ it 'in an instance variable' do
+ RescueSpecs::InstanceVariableCaptor.should_capture_exception
+ end
+
+ it 'using a safely navigated setter method' do
+ RescueSpecs::SafeNavigationSetterCaptor.should_capture_exception
+ end
+
+ it 'using a setter method' do
+ RescueSpecs::SetterCaptor.should_capture_exception
+ end
+
+ it 'using a square brackets setter' do
+ RescueSpecs::SquareBracketsCaptor.should_capture_exception
end
end
@@ -435,18 +465,16 @@ describe "The rescue keyword" do
}.should raise_error(SyntaxError)
end
- ruby_version_is "2.5" do
- it "allows rescue in 'do end' block" do
- lambda = eval <<-ruby
- lambda do
- raise SpecificExampleException
- rescue SpecificExampleException
- ScratchPad << :caught
- end.call
- ruby
+ it "allows rescue in 'do end' block" do
+ lambda = eval <<-ruby
+ lambda do
+ raise SpecificExampleException
+ rescue SpecificExampleException
+ ScratchPad << :caught
+ end.call
+ ruby
- ScratchPad.recorded.should == [:caught]
- end
+ ScratchPad.recorded.should == [:caught]
end
it "allows 'rescue' in method arguments" do
@@ -481,5 +509,15 @@ describe "The rescue keyword" do
a = raise(Exception) rescue 1
}.should raise_error(Exception)
end
+
+ ruby_version_is "2.7" do
+ it "rescues with multiple assignment" do
+
+ a, b = raise rescue [1, 2]
+
+ a.should == 1
+ b.should == 2
+ end
+ end
end
end
diff --git a/spec/ruby/language/return_spec.rb b/spec/ruby/language/return_spec.rb
index 7eef6d06ca..d8506834c8 100644
--- a/spec/ruby/language/return_spec.rb
+++ b/spec/ruby/language/return_spec.rb
@@ -250,260 +250,238 @@ describe "The return keyword" do
end
end
- ruby_version_is '2.4.2' do
- describe "at top level" do
- before :each do
- @filename = tmp("top_return.rb")
- ScratchPad.record []
- end
+ describe "at top level" do
+ before :each do
+ @filename = tmp("top_return.rb")
+ ScratchPad.record []
+ end
- after do
- rm_r @filename
- end
+ after do
+ rm_r @filename
+ end
- it "stops file execution" do
- ruby_exe(<<-END_OF_CODE).should == "before return\n"
- puts "before return"
- return
+ it "stops file execution" do
+ ruby_exe(<<-END_OF_CODE).should == "before return\n"
+ puts "before return"
+ return
- puts "after return"
- END_OF_CODE
+ puts "after return"
+ END_OF_CODE
- $?.exitstatus.should == 0
- end
+ $?.exitstatus.should == 0
+ end
- describe "within if" do
- it "is allowed" do
- File.write(@filename, <<-END_OF_CODE)
- ScratchPad << "before if"
- if true
- return
- end
+ describe "within if" do
+ it "is allowed" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before if"
+ if true
+ return
+ end
- ScratchPad << "after if"
- END_OF_CODE
+ ScratchPad << "after if"
+ END_OF_CODE
- load @filename
- ScratchPad.recorded.should == ["before if"]
- end
+ load @filename
+ ScratchPad.recorded.should == ["before if"]
end
+ end
- describe "within while loop" do
- it "is allowed" do
- File.write(@filename, <<-END_OF_CODE)
- ScratchPad << "before while"
- while true
- return
- end
+ describe "within while loop" do
+ it "is allowed" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before while"
+ while true
+ return
+ end
- ScratchPad << "after while"
- END_OF_CODE
+ ScratchPad << "after while"
+ END_OF_CODE
- load @filename
- ScratchPad.recorded.should == ["before while"]
- end
+ load @filename
+ ScratchPad.recorded.should == ["before while"]
end
+ end
- describe "within a begin" do
- it "is allowed in begin block" do
- File.write(@filename, <<-END_OF_CODE)
- ScratchPad << "before begin"
- begin
- return
- end
-
- ScratchPad << "after begin"
- END_OF_CODE
-
- load @filename
- ScratchPad.recorded.should == ["before begin"]
- end
+ describe "within a begin" do
+ it "is allowed in begin block" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before begin"
+ begin
+ return
+ end
- it "is allowed in ensure block" do
- File.write(@filename, <<-END_OF_CODE)
- ScratchPad << "before begin"
- begin
- ensure
- return
- end
+ ScratchPad << "after begin"
+ END_OF_CODE
- ScratchPad << "after begin"
- END_OF_CODE
+ load @filename
+ ScratchPad.recorded.should == ["before begin"]
+ end
- load @filename
- ScratchPad.recorded.should == ["before begin"]
- end
+ it "is allowed in ensure block" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before begin"
+ begin
+ ensure
+ return
+ end
- it "is allowed in rescue block" do
- File.write(@filename, <<-END_OF_CODE)
- ScratchPad << "before begin"
- begin
- raise
- rescue RuntimeError
- return
- end
+ ScratchPad << "after begin"
+ END_OF_CODE
- ScratchPad << "after begin"
- END_OF_CODE
+ load @filename
+ ScratchPad.recorded.should == ["before begin"]
+ end
- load @filename
- ScratchPad.recorded.should == ["before begin"]
- end
+ it "is allowed in rescue block" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before begin"
+ begin
+ raise
+ rescue RuntimeError
+ return
+ end
- it "fires ensure block before returning" do
- ruby_exe(<<-END_OF_CODE).should == "within ensure\n"
- begin
- return
- ensure
- puts "within ensure"
- end
+ ScratchPad << "after begin"
+ END_OF_CODE
- puts "after begin"
- END_OF_CODE
- end
+ load @filename
+ ScratchPad.recorded.should == ["before begin"]
+ end
- ruby_bug "#14061", "2.4"..."2.5" do
- it "fires ensure block before returning while loads file" do
- File.write(@filename, <<-END_OF_CODE)
- ScratchPad << "before begin"
- begin
- return
- ensure
- ScratchPad << "within ensure"
- end
-
- ScratchPad << "after begin"
- END_OF_CODE
-
- load @filename
- ScratchPad.recorded.should == ["before begin", "within ensure"]
+ it "fires ensure block before returning" do
+ ruby_exe(<<-END_OF_CODE).should == "within ensure\n"
+ begin
+ return
+ ensure
+ puts "within ensure"
end
- end
- it "swallows exception if returns in ensure block" do
- File.write(@filename, <<-END_OF_CODE)
- begin
- raise
- ensure
- ScratchPad << "before return"
- return
- end
- END_OF_CODE
-
- load @filename
- ScratchPad.recorded.should == ["before return"]
- end
+ puts "after begin"
+ END_OF_CODE
end
- describe "within a block" do
- it "is allowed" do
- File.write(@filename, <<-END_OF_CODE)
- ScratchPad << "before call"
- proc { return }.call
+ it "fires ensure block before returning while loads file" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before begin"
+ begin
+ return
+ ensure
+ ScratchPad << "within ensure"
+ end
- ScratchPad << "after call"
- END_OF_CODE
+ ScratchPad << "after begin"
+ END_OF_CODE
- load @filename
- ScratchPad.recorded.should == ["before call"]
- end
+ load @filename
+ ScratchPad.recorded.should == ["before begin", "within ensure"]
end
- describe "within a class" do
- ruby_version_is ""..."2.5" do
- it "is allowed" do
- File.write(@filename, <<-END_OF_CODE)
- class ReturnSpecs::A
- ScratchPad << "before return"
- return
-
- ScratchPad << "after return"
- end
- END_OF_CODE
-
- load @filename
- ScratchPad.recorded.should == ["before return"]
+ it "swallows exception if returns in ensure block" do
+ File.write(@filename, <<-END_OF_CODE)
+ begin
+ raise
+ ensure
+ ScratchPad << "before return"
+ return
end
- end
+ END_OF_CODE
- ruby_version_is "2.5" do
- it "raises a SyntaxError" do
- File.write(@filename, <<-END_OF_CODE)
- class ReturnSpecs::A
- ScratchPad << "before return"
- return
+ load @filename
+ ScratchPad.recorded.should == ["before return"]
+ end
+ end
- ScratchPad << "after return"
- end
- END_OF_CODE
+ describe "within a block" do
+ it "is allowed" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before call"
+ proc { return }.call
- -> { load @filename }.should raise_error(SyntaxError)
- end
- end
- end
+ ScratchPad << "after call"
+ END_OF_CODE
- describe "within a block within a class" do
- ruby_version_is "2.7" do
- it "is not allowed" do
- File.write(@filename, <<-END_OF_CODE)
- class ReturnSpecs::A
- ScratchPad << "before return"
- 1.times { return }
- ScratchPad << "after return"
- end
- END_OF_CODE
-
- -> { load @filename }.should raise_error(LocalJumpError)
- end
- end
+ load @filename
+ ScratchPad.recorded.should == ["before call"]
end
+ end
- describe "file loading" do
- it "stops file loading and execution" do
- File.write(@filename, <<-END_OF_CODE)
+ describe "within a class" do
+ it "raises a SyntaxError" do
+ File.write(@filename, <<-END_OF_CODE)
+ class ReturnSpecs::A
ScratchPad << "before return"
return
+
ScratchPad << "after return"
- END_OF_CODE
+ end
+ END_OF_CODE
- load @filename
- ScratchPad.recorded.should == ["before return"]
- end
+ -> { load @filename }.should raise_error(SyntaxError)
end
+ end
- describe "file requiring" do
- it "stops file loading and execution" do
+ describe "within a block within a class" do
+ ruby_version_is "2.7" do
+ it "is not allowed" do
File.write(@filename, <<-END_OF_CODE)
- ScratchPad << "before return"
- return
- ScratchPad << "after return"
+ class ReturnSpecs::A
+ ScratchPad << "before return"
+ 1.times { return }
+ ScratchPad << "after return"
+ end
END_OF_CODE
- require @filename
- ScratchPad.recorded.should == ["before return"]
+ -> { load @filename }.should raise_error(LocalJumpError)
end
end
+ end
- describe "return with argument" do
- ruby_version_is ""..."2.7" do
- it "does not affect exit status" do
- ruby_exe(<<-END_OF_CODE).should == ""
- return 10
- END_OF_CODE
+ describe "file loading" do
+ it "stops file loading and execution" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before return"
+ return
+ ScratchPad << "after return"
+ END_OF_CODE
- $?.exitstatus.should == 0
- end
+ load @filename
+ ScratchPad.recorded.should == ["before return"]
+ end
+ end
+
+ describe "file requiring" do
+ it "stops file loading and execution" do
+ File.write(@filename, <<-END_OF_CODE)
+ ScratchPad << "before return"
+ return
+ ScratchPad << "after return"
+ END_OF_CODE
+
+ require @filename
+ ScratchPad.recorded.should == ["before return"]
+ end
+ end
+
+ describe "return with argument" do
+ ruby_version_is ""..."2.7" do
+ it "does not affect exit status" do
+ ruby_exe(<<-END_OF_CODE).should == ""
+ return 10
+ END_OF_CODE
+
+ $?.exitstatus.should == 0
end
+ end
- ruby_version_is "2.7" do
- it "warns but does not affect exit status" do
- err = ruby_exe(<<-END_OF_CODE, args: "2>&1")
- return 10
- END_OF_CODE
- $?.exitstatus.should == 0
+ ruby_version_is "2.7" do
+ it "warns but does not affect exit status" do
+ err = ruby_exe(<<-END_OF_CODE, args: "2>&1")
+ return 10
+ END_OF_CODE
+ $?.exitstatus.should == 0
- err.should =~ /warning: argument of top-level return is ignored/
- end
+ err.should =~ /warning: argument of top-level return is ignored/
end
end
end
diff --git a/spec/ruby/language/safe_spec.rb b/spec/ruby/language/safe_spec.rb
index 53ab4f9561..f3a7efc953 100644
--- a/spec/ruby/language/safe_spec.rb
+++ b/spec/ruby/language/safe_spec.rb
@@ -135,4 +135,18 @@ describe "The $SAFE variable" do
}.call
end
end
+
+ ruby_version_is "2.7"..."3.0" do
+ it "warn when access" do
+ -> {
+ $SAFE
+ }.should complain(/\$SAFE will become a normal global variable in Ruby 3.0/)
+ end
+
+ it "warn when set" do
+ -> {
+ $SAFE = 1
+ }.should complain(/\$SAFE will become a normal global variable in Ruby 3.0/)
+ end
+ end
end
diff --git a/spec/ruby/language/send_spec.rb b/spec/ruby/language/send_spec.rb
index c56d5e8c26..e57e2c65dc 100644
--- a/spec/ruby/language/send_spec.rb
+++ b/spec/ruby/language/send_spec.rb
@@ -421,18 +421,36 @@ describe "Invoking a method" do
specs.rest_len(0,*a,4,*5,6,7,*c,-1).should == 11
end
- it "expands the Array elements from the splat after executing the arguments and block if no other arguments follow the splat" do
- def self.m(*args, &block)
- [args, block]
+ ruby_version_is ""..."3.0" do
+ it "expands the Array elements from the splat after executing the arguments and block if no other arguments follow the splat" do
+ def self.m(*args, &block)
+ [args, block]
+ end
+
+ args = [1, nil]
+ m(*args, &args.pop).should == [[1], nil]
+
+ args = [1, nil]
+ order = []
+ m(*(order << :args; args), &(order << :block; args.pop)).should == [[1], nil]
+ order.should == [:args, :block]
end
+ end
- args = [1, nil]
- m(*args, &args.pop).should == [[1], nil]
+ ruby_version_is "3.0" do
+ it "expands the Array elements from the splat before applying block argument operations" do
+ def self.m(*args, &block)
+ [args, block]
+ end
- args = [1, nil]
- order = []
- m(*(order << :args; args), &(order << :block; args.pop)).should == [[1], nil]
- order.should == [:args, :block]
+ args = [1, nil]
+ m(*args, &args.pop).should == [[1, nil], nil]
+
+ args = [1, nil]
+ order = []
+ m(*(order << :args; args), &(order << :block; args.pop)).should == [[1, nil], nil]
+ order.should == [:args, :block]
+ end
end
it "evaluates the splatted arguments before the block if there are other arguments after the splat" do
diff --git a/spec/ruby/language/singleton_class_spec.rb b/spec/ruby/language/singleton_class_spec.rb
index df735018af..91ce9726d5 100644
--- a/spec/ruby/language/singleton_class_spec.rb
+++ b/spec/ruby/language/singleton_class_spec.rb
@@ -14,7 +14,7 @@ describe "A singleton class" do
nil.singleton_class.should == NilClass
end
- it "raises a TypeError for Fixnum's" do
+ it "raises a TypeError for Integer's" do
-> { 1.singleton_class }.should raise_error(TypeError)
end
@@ -74,7 +74,7 @@ describe "A singleton class" do
end
it "doesn't have singleton class" do
- -> { bignum_value.singleton_class.superclass.should == Bignum }.should raise_error(TypeError)
+ -> { bignum_value.singleton_class.superclass.should == Integer }.should raise_error(TypeError)
end
end
@@ -157,6 +157,23 @@ describe "A constant on a singleton class" do
end
end
+describe "Defining yield in singleton class" do
+ ruby_version_is "2.7"..."3.0" do
+ it 'emits a deprecation warning' do
+ code = <<~RUBY
+ def m
+ class << Object.new
+ yield
+ end
+ end
+ m { :ok }
+ RUBY
+
+ -> { eval(code) }.should complain(/warning: `yield' in class syntax will not be supported from Ruby 3.0/)
+ end
+ end
+end
+
describe "Defining instance methods on a singleton class" do
before :each do
@k = ClassSpecs::K.new
diff --git a/spec/ruby/language/string_spec.rb b/spec/ruby/language/string_spec.rb
index d0f62ff3c9..0178083f58 100644
--- a/spec/ruby/language/string_spec.rb
+++ b/spec/ruby/language/string_spec.rb
@@ -32,6 +32,11 @@ describe "Ruby character strings" do
"#@my_ip".should == 'xxx'
end
+ it "does not interpolate invalid variable names" do
+ "#@".should == '#@'
+ "#$%".should == '#$%'
+ end
+
it "has characters [.(=?!# end simple # interpolation" do
"#@ip[".should == 'xxx['
"#@ip.".should == 'xxx.'
@@ -260,24 +265,24 @@ describe "Ruby String literals" do
end
describe "Ruby String interpolation" do
- it "creates a String having an Encoding compatible with all components" do
- a = "\u3042"
- b = "abc".encode("binary")
-
- str = "#{a} x #{b}"
+ it "permits an empty expression" do
+ s = "#{}" # rubocop:disable Lint/EmptyInterpolation
+ s.should.empty?
+ s.should_not.frozen?
+ end
- str.should == "\xe3\x81\x82\x20\x78\x20\x61\x62\x63".force_encoding("utf-8")
- str.encoding.should == Encoding::UTF_8
+ it "returns a string with the source encoding by default" do
+ "a#{"b"}c".encoding.should == Encoding::BINARY
+ eval('"a#{"b"}c"'.force_encoding("us-ascii")).encoding.should == Encoding::US_ASCII
+ eval("# coding: US-ASCII \n 'a#{"b"}c'").encoding.should == Encoding::US_ASCII
end
- it "creates a String having the Encoding of the components when all are the same Encoding" do
+ it "returns a string with the source encoding, even if the components have another encoding" do
a = "abc".force_encoding("euc-jp")
- b = "def".force_encoding("euc-jp")
- str = '"#{a} x #{b}"'.force_encoding("euc-jp")
+ "#{a}".encoding.should == Encoding::BINARY
- result = eval(str)
- result.should == "\x61\x62\x63\x20\x78\x20\x64\x65\x66".force_encoding("euc-jp")
- result.encoding.should == Encoding::EUC_JP
+ b = "abc".encode("utf-8")
+ "#{b}".encoding.should == Encoding::BINARY
end
it "raises an Encoding::CompatibilityError if the Encodings are not compatible" do
@@ -286,4 +291,21 @@ describe "Ruby String interpolation" do
-> { "#{a} #{b}" }.should raise_error(Encoding::CompatibilityError)
end
+
+ it "creates a non-frozen String" do
+ code = <<~'RUBY'
+ "a#{6*7}c"
+ RUBY
+ eval(code).should_not.frozen?
+ end
+
+ ruby_version_is "3.0" do
+ it "creates a non-frozen String when # frozen-string-literal: true is used" do
+ code = <<~'RUBY'
+ # frozen-string-literal: true
+ "a#{6*7}c"
+ RUBY
+ eval(code).should_not.frozen?
+ end
+ end
end
diff --git a/spec/ruby/language/super_spec.rb b/spec/ruby/language/super_spec.rb
index 66a1ec7592..1ac5c5e1be 100644
--- a/spec/ruby/language/super_spec.rb
+++ b/spec/ruby/language/super_spec.rb
@@ -102,6 +102,37 @@ describe "The super keyword" do
c2.new.m(:dump) { :value }.should == :value
end
+ it "can pass an explicit block" do
+ c1 = Class.new do
+ def m(v)
+ yield(v)
+ end
+ end
+ c2 = Class.new(c1) do
+ def m(v)
+ block = -> w { yield(w + 'b') }
+ super(v, &block)
+ end
+ end
+
+ c2.new.m('a') { |x| x + 'c' }.should == 'abc'
+ end
+
+ it "can pass no block using &nil" do
+ c1 = Class.new do
+ def m(v)
+ block_given?
+ end
+ end
+ c2 = Class.new(c1) do
+ def m(v)
+ super(v, &nil)
+ end
+ end
+
+ c2.new.m('a') { raise }.should be_false
+ end
+
it "uses block argument given to method when used in a block" do
c1 = Class.new do
def m
@@ -262,6 +293,21 @@ describe "The super keyword" do
it "without explicit arguments passes arguments and rest arguments" do
SuperSpecs::ZSuperWithRestAndOthers::B.new.m(1, 2, 3, 4, 5).should == [3, 4, 5]
+ SuperSpecs::ZSuperWithRestAndOthers::B.new.m(1, 2).should == []
+ end
+
+ it "without explicit arguments passes arguments, rest arguments, and post arguments" do
+ SuperSpecs::ZSuperWithRestAndPost::B.new.m(1, 2, 3, 4, 5).should == [1, 2, 3]
+ SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m(1, 2, 3, 4, 5).should == [2, 3, 4]
+ SuperSpecs::ZSuperWithRestAndPost::B.new.m(1, 2).should == []
+ SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m(1, 2).should == []
+ end
+
+ it "without explicit arguments passes arguments, rest arguments including modifications, and post arguments" do
+ SuperSpecs::ZSuperWithRestAndPost::B.new.m_modified(1, 2, 3, 4, 5).should == [1, 14, 3]
+ SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m_modified(1, 2, 3, 4, 5).should == [2, 14, 4]
+ SuperSpecs::ZSuperWithRestAndPost::B.new.m_modified(1, 2).should == [nil, 14]
+ SuperSpecs::ZSuperWithRestOthersAndPost::B.new.m_modified(1, 2).should == [nil, 14]
end
it "without explicit arguments passes arguments and rest arguments including any modifications" do
diff --git a/spec/ruby/language/variables_spec.rb b/spec/ruby/language/variables_spec.rb
index 868603eb88..ce072baa2c 100644
--- a/spec/ruby/language/variables_spec.rb
+++ b/spec/ruby/language/variables_spec.rb
@@ -354,6 +354,16 @@ describe "Multiple assignment" do
a.should be_an_instance_of(Array)
end
+ it "unfreezes the array returned from calling 'to_a' on the splatted value" do
+ obj = Object.new
+ def obj.to_a
+ [1,2].freeze
+ end
+ res = *obj
+ res.should == [1,2]
+ res.should_not.frozen?
+ end
+
it "consumes values for an anonymous splat" do
a = 1
(* = *a).should == [1]
@@ -786,3 +796,32 @@ describe 'Local variable shadowing' do
end
end
end
+
+describe 'Allowed characters' do
+ ruby_version_is "2.6" do
+ # new feature in 2.6 -- https://bugs.ruby-lang.org/issues/13770
+ it 'does not allow non-ASCII upcased characters at the beginning' do
+ -> do
+ eval <<-CODE
+ def test
+ ἍBB = 1
+ end
+ CODE
+ end.should raise_error(SyntaxError, /dynamic constant assignment/)
+ end
+ end
+
+ it 'allows non-ASCII lowercased characters at the beginning' do
+ result = nil
+
+ eval <<-CODE
+ def test
+ μ = 1
+ end
+
+ result = test
+ CODE
+
+ result.should == 1
+ end
+end
diff --git a/spec/ruby/library/English/English_spec.rb b/spec/ruby/library/English/English_spec.rb
index f6153ec7c9..480602d5e5 100644
--- a/spec/ruby/library/English/English_spec.rb
+++ b/spec/ruby/library/English/English_spec.rb
@@ -67,18 +67,18 @@ describe "English" do
it "aliases $ORS to $\\" do
original = $\
- $\ = "\t"
+ suppress_warning {$\ = "\t"}
$ORS.should_not be_nil
$ORS.should == $\
- $\ = original
+ suppress_warning {$\ = original}
end
it "aliases $OUTPUT_RECORD_SEPARATOR to $\\" do
original = $\
- $\ = "\t"
+ suppress_warning {$\ = "\t"}
$OUTPUT_RECORD_SEPARATOR.should_not be_nil
$OUTPUT_RECORD_SEPARATOR.should == $\
- $\ = original
+ suppress_warning {$\ = original}
end
it "aliases $INPUT_LINE_NUMBER to $." do
diff --git a/spec/ruby/library/English/alias_spec.rb b/spec/ruby/library/English/alias_spec.rb
new file mode 100644
index 0000000000..78ccfb4398
--- /dev/null
+++ b/spec/ruby/library/English/alias_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+require 'English'
+
+describe "English" do
+ it "aliases $! to $ERROR_INFO and $ERROR_INFO still returns an Exception with a backtrace" do
+ exception = (1 / 0 rescue $ERROR_INFO)
+ exception.should be_kind_of(Exception)
+ exception.backtrace.should be_kind_of(Array)
+ end
+
+ it "aliases $@ to $ERROR_POSITION and $ERROR_POSITION still returns a backtrace" do
+ (1 / 0 rescue $ERROR_POSITION).should be_kind_of(Array)
+ end
+end
diff --git a/spec/ruby/library/bigdecimal/BigDecimal_spec.rb b/spec/ruby/library/bigdecimal/BigDecimal_spec.rb
index 179bde1aed..b265e84798 100644
--- a/spec/ruby/library/bigdecimal/BigDecimal_spec.rb
+++ b/spec/ruby/library/bigdecimal/BigDecimal_spec.rb
@@ -30,22 +30,30 @@ describe "Kernel#BigDecimal" do
BigDecimal(rational, 100).to_s.should == "0.99999999999999999999e18"
end
- it "accepts significant digits >= given precision" do
- BigDecimal("3.1415923", 10).precs[1].should >= 10
- end
+ ruby_version_is ""..."3.0" do
+ it "accepts significant digits >= given precision" do
+ BigDecimal("3.1415923", 10).precs[1].should >= 10
+ end
- it "determines precision from initial value" do
- pi_string = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043"
- BigDecimal(pi_string).precs[1].should >= pi_string.size-1
+ it "determines precision from initial value" do
+ pi_string = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043"
+ BigDecimal(pi_string).precs[1].should >= pi_string.size-1
+ end
end
it "ignores leading and trailing whitespace" do
BigDecimal(" \t\n \r1234\t\r\n ").should == BigDecimal("1234")
- BigDecimal(" \t\n \rNaN \n").nan?.should == true
+ BigDecimal(" \t\n \rNaN \n").should.nan?
BigDecimal(" \t\n \rInfinity \n").infinite?.should == 1
BigDecimal(" \t\n \r-Infinity \n").infinite?.should == -1
end
+ it "coerces the value argument with #to_str" do
+ initial = mock("value")
+ initial.should_receive(:to_str).and_return("123")
+ BigDecimal(initial).should == BigDecimal("123")
+ end
+
ruby_version_is ""..."2.6" do
it "ignores trailing garbage" do
BigDecimal("123E45ruby").should == BigDecimal("123E45")
@@ -94,42 +102,53 @@ describe "Kernel#BigDecimal" do
end
it "accepts NaN and [+-]Infinity" do
- BigDecimal("NaN").nan?.should == true
+ BigDecimal("NaN").should.nan?
pos_inf = BigDecimal("Infinity")
- pos_inf.finite?.should == false
+ pos_inf.should_not.finite?
pos_inf.should > 0
pos_inf.should == BigDecimal("+Infinity")
neg_inf = BigDecimal("-Infinity")
- neg_inf.finite?.should == false
+ neg_inf.should_not.finite?
neg_inf.should < 0
end
+ ruby_version_is "2.6" do
+ describe "with exception: false" do
+ it "returns nil for invalid strings" do
+ BigDecimal("invalid", exception: false).should be_nil
+ BigDecimal("0invalid", exception: false).should be_nil
+ BigDecimal("invalid0", exception: false).should be_nil
+ BigDecimal("0.", exception: false).should be_nil
+ end
+ end
+ end
+
describe "accepts NaN and [+-]Infinity as Float values" do
it "works without an explicit precision" do
- BigDecimal(Float::NAN).nan?.should == true
+ BigDecimal(Float::NAN).should.nan?
pos_inf = BigDecimal(Float::INFINITY)
- pos_inf.finite?.should == false
+ pos_inf.should_not.finite?
pos_inf.should > 0
pos_inf.should == BigDecimal("+Infinity")
neg_inf = BigDecimal(-Float::INFINITY)
- neg_inf.finite?.should == false
+ neg_inf.should_not.finite?
neg_inf.should < 0
end
it "works with an explicit precision" do
- BigDecimal(Float::NAN, Float::DIG).nan?.should == true
+ BigDecimal(Float::NAN, Float::DIG).should.nan?
pos_inf = BigDecimal(Float::INFINITY, Float::DIG)
- pos_inf.finite?.should == false
+ pos_inf.should_not.finite?
pos_inf.should > 0
pos_inf.should == BigDecimal("+Infinity")
neg_inf = BigDecimal(-Float::INFINITY, Float::DIG)
- neg_inf.finite?.should == false
+ neg_inf.should_not.finite?
neg_inf.should < 0
end
end
@@ -169,6 +188,22 @@ describe "Kernel#BigDecimal" do
BigDecimal(3).add(1 << 50, 3).should == BigDecimal('0.113e16')
end
+ it "does not call to_s when calling inspect" do
+ value = BigDecimal('44.44')
+ value.to_s.should == '0.4444e2'
+ value.inspect.should == '0.4444e2'
+
+ ruby_exe( <<-'EOF').should == "cheese 0.4444e2"
+ require 'bigdecimal'
+ module BigDecimalOverride
+ def to_s; "cheese"; end
+ end
+ BigDecimal.prepend BigDecimalOverride
+ value = BigDecimal('44.44')
+ print "#{value.to_s} #{value.inspect}"
+ EOF
+ end
+
describe "when interacting with Rational" do
before :each do
@a = BigDecimal('166.666666666')
@@ -190,12 +225,14 @@ describe "Kernel#BigDecimal" do
Float(@b).to_s.should == "166.66666666666666"
end
- it "has the expected precision on the LHS" do
- @a.precs[0].should == 18
- end
+ ruby_version_is ""..."3.0" do
+ it "has the expected precision on the LHS" do
+ @a.precs[0].should == 18
+ end
- it "has the expected maximum precision on the LHS" do
- @a.precs[1].should == 27
+ it "has the expected maximum precision on the LHS" do
+ @a.precs[1].should == 27
+ end
end
it "produces the expected result when done via Float" do
@@ -208,32 +245,36 @@ 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, _ = b.precs
- (precs >= 9).should be_true
- (precs >= n).should be_true
- (precs % 9).should == 0
+ ruby_version_is ""..."3.0" do
+ it "BigDecimal precision is the number of digits rounded up to a multiple of nine" do
+ 1.upto(100) do |n|
+ b = BigDecimal('4' * n)
+ precs, _ = b.precs
+ (precs >= 9).should be_true
+ (precs >= n).should be_true
+ (precs % 9).should == 0
+ end
+ BigDecimal('NaN').precs[0].should == 9
end
- BigDecimal('NaN').precs[0].should == 9
- end
- it "BigDecimal maximum precision is nine more than precision except for abnormals" do
- 1.upto(100) do |n|
- b = BigDecimal('4' * n)
- precs, max = b.precs
- max.should == precs + 9
+ it "BigDecimal maximum precision is nine more than precision except for abnormals" do
+ 1.upto(100) do |n|
+ b = BigDecimal('4' * n)
+ precs, max = b.precs
+ max.should == precs + 9
+ end
+ BigDecimal('NaN').precs[1].should == 9
end
- 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, @a.precs[0]).to_s.should == "0.166666666666666667e3"
+ ruby_version_is ""..."3.0" do
+ it "BigDecimal(Rational, BigDecimal.precs[0]) produces the result we expect" do
+ BigDecimal(@b, @a.precs[0]).to_s.should == "0.166666666666666667e3"
+ end
end
# Check the top-level expression works as we expect
diff --git a/spec/ruby/library/bigdecimal/abs_spec.rb b/spec/ruby/library/bigdecimal/abs_spec.rb
index ddd2bae9a9..95dc45a905 100644
--- a/spec/ruby/library/bigdecimal/abs_spec.rb
+++ b/spec/ruby/library/bigdecimal/abs_spec.rb
@@ -38,7 +38,7 @@ describe "BigDecimal#abs" do
it "properly handles special values" do
@infinity.abs.should == @infinity
@infinity_minus.abs.should == @infinity
- @nan.abs.nan?.should == true # have to do it this way, since == doesn't work on NaN
+ @nan.abs.should.nan? # have to do it this way, since == doesn't work on NaN
@zero.abs.should == 0
@zero.abs.sign.should == BigDecimal::SIGN_POSITIVE_ZERO
@zero_pos.abs.should == 0
diff --git a/spec/ruby/library/bigdecimal/add_spec.rb b/spec/ruby/library/bigdecimal/add_spec.rb
index 5b874687fe..f844ca96fa 100644
--- a/spec/ruby/library/bigdecimal/add_spec.rb
+++ b/spec/ruby/library/bigdecimal/add_spec.rb
@@ -41,14 +41,14 @@ describe "BigDecimal#add" do
@frac_3.add(@frac_4, 6).should == BigDecimal("0.11111E16")
end
- it "returns a + [Fixnum value] with given precision" do
+ it "returns a + [Integer value] with given precision" do
(1..10).each {|precision|
@dot_ones.add(0, precision).should == BigDecimal("0." + "1" * precision)
}
BigDecimal("0.88").add(0, 1).should == BigDecimal("0.9")
end
- it "returns a + [Bignum value] with given precision" do
+ it "returns a + [Integer value] with given precision" do
bignum = 10000000000000000000
(1..20).each {|precision|
@dot_ones.add(bignum, precision).should == BigDecimal("0.1E20")
@@ -136,8 +136,8 @@ describe "BigDecimal#add" do
end
it "returns NaN if NaN is involved" do
- @one.add(@nan, 10000).nan?.should == true
- @nan.add(@one, 1).nan?.should == true
+ @one.add(@nan, 10000).should.nan?
+ @nan.add(@one, 1).should.nan?
end
it "returns Infinity or -Infinity if these are involved" do
@@ -166,8 +166,8 @@ describe "BigDecimal#add" do
end
it "returns NaN if Infinity + (- Infinity)" do
- @infinity.add(@infinity_minus, 10000).nan?.should == true
- @infinity_minus.add(@infinity, 10000).nan?.should == true
+ @infinity.add(@infinity_minus, 10000).should.nan?
+ @infinity_minus.add(@infinity, 10000).should.nan?
end
it "raises TypeError when adds nil" do
diff --git a/spec/ruby/library/bigdecimal/comparison_spec.rb b/spec/ruby/library/bigdecimal/comparison_spec.rb
index a1e09b601f..c53187b727 100644
--- a/spec/ruby/library/bigdecimal/comparison_spec.rb
+++ b/spec/ruby/library/bigdecimal/comparison_spec.rb
@@ -18,7 +18,7 @@ describe "BigDecimal#<=>" do
def coerce(other)
return [other, BigDecimal('123')]
end
- def >= (other)
+ def >=(other)
BigDecimal('123') >= other
end
end
diff --git a/spec/ruby/library/bigdecimal/constants_spec.rb b/spec/ruby/library/bigdecimal/constants_spec.rb
index 1eb24d85cb..8d879c036a 100644
--- a/spec/ruby/library/bigdecimal/constants_spec.rb
+++ b/spec/ruby/library/bigdecimal/constants_spec.rb
@@ -2,10 +2,8 @@ require_relative '../../spec_helper'
require 'bigdecimal'
describe "BigDecimal constants" do
- ruby_version_is "2.5" do
- it "defines a VERSION value" do
- BigDecimal.const_defined?(:VERSION).should be_true
- end
+ it "defines a VERSION value" do
+ BigDecimal.const_defined?(:VERSION).should be_true
end
it "has a BASE value" do
diff --git a/spec/ruby/library/bigdecimal/div_spec.rb b/spec/ruby/library/bigdecimal/div_spec.rb
index 0c9eb2ddec..53ad6d0418 100644
--- a/spec/ruby/library/bigdecimal/div_spec.rb
+++ b/spec/ruby/library/bigdecimal/div_spec.rb
@@ -80,13 +80,13 @@ describe "BigDecimal#div" do
end
it "returns NaN if zero is divided by zero" do
- @zero.div(@zero, 0).nan?.should == true
- @zero_minus.div(@zero_plus, 0).nan?.should == true
- @zero_plus.div(@zero_minus, 0).nan?.should == true
+ @zero.div(@zero, 0).should.nan?
+ @zero_minus.div(@zero_plus, 0).should.nan?
+ @zero_plus.div(@zero_minus, 0).should.nan?
- @zero.div(@zero, 10).nan?.should == true
- @zero_minus.div(@zero_plus, 10).nan?.should == true
- @zero_plus.div(@zero_minus, 10).nan?.should == true
+ @zero.div(@zero, 10).should.nan?
+ @zero_minus.div(@zero_plus, 10).should.nan?
+ @zero_plus.div(@zero_minus, 10).should.nan?
end
it "raises FloatDomainError if (+|-) Infinity divided by 1 and no precision given" do
@@ -102,8 +102,8 @@ describe "BigDecimal#div" do
end
it "returns NaN if Infinity / ((+|-) Infinity)" do
- @infinity.div(@infinity_minus, 100000).nan?.should == true
- @infinity_minus.div(@infinity, 1).nan?.should == true
+ @infinity.div(@infinity_minus, 100000).should.nan?
+ @infinity_minus.div(@infinity, 1).should.nan?
end
diff --git a/spec/ruby/library/bigdecimal/divmod_spec.rb b/spec/ruby/library/bigdecimal/divmod_spec.rb
index ae8b84983a..294f01cba0 100644
--- a/spec/ruby/library/bigdecimal/divmod_spec.rb
+++ b/spec/ruby/library/bigdecimal/divmod_spec.rb
@@ -5,8 +5,8 @@ require 'bigdecimal'
module DivmodSpecs
def self.check_both_nan(array)
array.length.should == 2
- array[0].nan?.should == true
- array[1].nan?.should == true
+ array[0].should.nan?
+ array[1].should.nan?
end
def self.check_both_bigdecimal(array)
array.length.should == 2
@@ -150,7 +150,7 @@ describe "BigDecimal#divmod" do
array = @infinity.divmod(val)
array.length.should == 2
array[0].infinite?.should == (val > 0 ? 1 : -1)
- array[1].nan?.should == true
+ array[1].should.nan?
end
end
diff --git a/spec/ruby/library/bigdecimal/exponent_spec.rb b/spec/ruby/library/bigdecimal/exponent_spec.rb
index a349ac093f..f63c4e5798 100644
--- a/spec/ruby/library/bigdecimal/exponent_spec.rb
+++ b/spec/ruby/library/bigdecimal/exponent_spec.rb
@@ -22,7 +22,7 @@ describe "BigDecimal#exponent" do
=begin
platform_is wordsize: 32 do
# TODO: write specs for both 32 and 64 bit
- it "returns 0 if exponent can't be represented as Fixnum" do
+ it "returns 0 if exponent can't be represented as Integer" do
BigDecimal("2E1000000000000000").exponent.should == 0
BigDecimal("-5E-999999999999999").exponent.should == 0
end
diff --git a/spec/ruby/library/bigdecimal/finite_spec.rb b/spec/ruby/library/bigdecimal/finite_spec.rb
index 6685d589b6..8fc06029bb 100644
--- a/spec/ruby/library/bigdecimal/finite_spec.rb
+++ b/spec/ruby/library/bigdecimal/finite_spec.rb
@@ -21,14 +21,14 @@ describe "BigDecimal#finite?" do
end
it "is false if Infinity or NaN" do
- @infinity.finite?.should == false
- @infinity_minus.finite?.should == false
- @nan.finite?.should == false
+ @infinity.should_not.finite?
+ @infinity_minus.should_not.finite?
+ @nan.should_not.finite?
end
it "returns true for finite values" do
@finite_vals.each do |val|
- val.finite?.should == true
+ val.should.finite?
end
end
end
diff --git a/spec/ruby/library/bigdecimal/fix_spec.rb b/spec/ruby/library/bigdecimal/fix_spec.rb
index 53b30cbf8b..231c9a587e 100644
--- a/spec/ruby/library/bigdecimal/fix_spec.rb
+++ b/spec/ruby/library/bigdecimal/fix_spec.rb
@@ -34,7 +34,7 @@ describe "BigDecimal#fix" do
it "correctly handles special values" do
@infinity.fix.should == @infinity
@infinity_neg.fix.should == @infinity_neg
- @nan.fix.nan?.should == true
+ @nan.fix.should.nan?
end
it "returns 0 if the absolute value is < 1" do
diff --git a/spec/ruby/library/bigdecimal/frac_spec.rb b/spec/ruby/library/bigdecimal/frac_spec.rb
index 4a023b4ff6..11ccf03c2f 100644
--- a/spec/ruby/library/bigdecimal/frac_spec.rb
+++ b/spec/ruby/library/bigdecimal/frac_spec.rb
@@ -42,7 +42,7 @@ describe "BigDecimal#frac" do
it "correctly handles special values" do
@infinity.frac.should == @infinity
@infinity_neg.frac.should == @infinity_neg
- @nan.frac.nan?.should == true
+ @nan.frac.should.nan?
end
end
diff --git a/spec/ruby/library/bigdecimal/gt_spec.rb b/spec/ruby/library/bigdecimal/gt_spec.rb
index 4717cfdd9d..78547fb85f 100644
--- a/spec/ruby/library/bigdecimal/gt_spec.rb
+++ b/spec/ruby/library/bigdecimal/gt_spec.rb
@@ -17,7 +17,7 @@ describe "BigDecimal#>" do
def coerce(other)
return [other, BigDecimal('123')]
end
- def > (other)
+ def >(other)
BigDecimal('123') > other
end
end
diff --git a/spec/ruby/library/bigdecimal/gte_spec.rb b/spec/ruby/library/bigdecimal/gte_spec.rb
index 8dc81707f0..2a5cc025ba 100644
--- a/spec/ruby/library/bigdecimal/gte_spec.rb
+++ b/spec/ruby/library/bigdecimal/gte_spec.rb
@@ -17,7 +17,7 @@ describe "BigDecimal#>=" do
def coerce(other)
return [other, BigDecimal('123')]
end
- def >= (other)
+ def >=(other)
BigDecimal('123') >= other
end
end
diff --git a/spec/ruby/library/bigdecimal/lt_spec.rb b/spec/ruby/library/bigdecimal/lt_spec.rb
index 61f4f19912..02390e76e3 100644
--- a/spec/ruby/library/bigdecimal/lt_spec.rb
+++ b/spec/ruby/library/bigdecimal/lt_spec.rb
@@ -17,7 +17,7 @@ describe "BigDecimal#<" do
def coerce(other)
return [other, BigDecimal('123')]
end
- def < (other)
+ def <(other)
BigDecimal('123') < other
end
end
diff --git a/spec/ruby/library/bigdecimal/lte_spec.rb b/spec/ruby/library/bigdecimal/lte_spec.rb
index fc632315f8..b92be04123 100644
--- a/spec/ruby/library/bigdecimal/lte_spec.rb
+++ b/spec/ruby/library/bigdecimal/lte_spec.rb
@@ -17,7 +17,7 @@ describe "BigDecimal#<=" do
def coerce(other)
return [other, BigDecimal('123')]
end
- def <= (other)
+ def <=(other)
BigDecimal('123') <= other
end
end
diff --git a/spec/ruby/library/bigdecimal/minus_spec.rb b/spec/ruby/library/bigdecimal/minus_spec.rb
index 267a0f7eab..bd3c19584b 100644
--- a/spec/ruby/library/bigdecimal/minus_spec.rb
+++ b/spec/ruby/library/bigdecimal/minus_spec.rb
@@ -26,18 +26,18 @@ describe "BigDecimal#-" do
end
it "returns NaN if NaN is involved" do
- (@one - @nan).nan?.should == true
- (@nan - @one).nan?.should == true
- (@nan - @nan).nan?.should == true
- (@nan - @infinity).nan?.should == true
- (@nan - @infinity_minus).nan?.should == true
- (@infinity - @nan).nan?.should == true
- (@infinity_minus - @nan).nan?.should == true
+ (@one - @nan).should.nan?
+ (@nan - @one).should.nan?
+ (@nan - @nan).should.nan?
+ (@nan - @infinity).should.nan?
+ (@nan - @infinity_minus).should.nan?
+ (@infinity - @nan).should.nan?
+ (@infinity_minus - @nan).should.nan?
end
it "returns NaN both operands are infinite with the same sign" do
- (@infinity - @infinity).nan?.should == true
- (@infinity_minus - @infinity_minus).nan?.should == true
+ (@infinity - @infinity).should.nan?
+ (@infinity_minus - @infinity_minus).should.nan?
end
it "returns Infinity or -Infinity if these are involved" do
diff --git a/spec/ruby/library/bigdecimal/mode_spec.rb b/spec/ruby/library/bigdecimal/mode_spec.rb
index f57028ae5d..73fa1a118e 100644
--- a/spec/ruby/library/bigdecimal/mode_spec.rb
+++ b/spec/ruby/library/bigdecimal/mode_spec.rb
@@ -12,7 +12,7 @@ describe "BigDecimal.mode" do
end
it "returns the appropriate value and continue the computation if the flag is false" do
- BigDecimal("NaN").add(BigDecimal("1"),0).nan?.should == true
+ BigDecimal("NaN").add(BigDecimal("1"),0).should.nan?
BigDecimal("0").add(BigDecimal("Infinity"),0).should == BigDecimal("Infinity")
BigDecimal("1").quo(BigDecimal("0")).should == BigDecimal("Infinity")
end
diff --git a/spec/ruby/library/bigdecimal/nan_spec.rb b/spec/ruby/library/bigdecimal/nan_spec.rb
index 705492614b..9eaf69b610 100644
--- a/spec/ruby/library/bigdecimal/nan_spec.rb
+++ b/spec/ruby/library/bigdecimal/nan_spec.rb
@@ -4,20 +4,20 @@ require 'bigdecimal'
describe "BigDecimal#nan?" do
it "returns true if self is not a number" do
- BigDecimal("NaN").nan?.should == true
+ BigDecimal("NaN").should.nan?
end
it "returns false if self is not a NaN" do
- BigDecimal("Infinity").nan?.should == false
- BigDecimal("-Infinity").nan?.should == false
- BigDecimal("0").nan?.should == false
- BigDecimal("+0").nan?.should == false
- BigDecimal("-0").nan?.should == false
- BigDecimal("2E40001").nan?.should == false
- BigDecimal("3E-20001").nan?.should == false
- BigDecimal("0E-200000000").nan?.should == false
- BigDecimal("0E200000000000").nan?.should == false
- BigDecimal("0.000000000000000000000000").nan?.should == false
+ BigDecimal("Infinity").should_not.nan?
+ BigDecimal("-Infinity").should_not.nan?
+ BigDecimal("0").should_not.nan?
+ BigDecimal("+0").should_not.nan?
+ BigDecimal("-0").should_not.nan?
+ BigDecimal("2E40001").should_not.nan?
+ BigDecimal("3E-20001").should_not.nan?
+ BigDecimal("0E-200000000").should_not.nan?
+ BigDecimal("0E200000000000").should_not.nan?
+ BigDecimal("0.000000000000000000000000").should_not.nan?
end
end
diff --git a/spec/ruby/library/bigdecimal/plus_spec.rb b/spec/ruby/library/bigdecimal/plus_spec.rb
index cefc43aeaa..d1934841c8 100644
--- a/spec/ruby/library/bigdecimal/plus_spec.rb
+++ b/spec/ruby/library/bigdecimal/plus_spec.rb
@@ -30,8 +30,8 @@ describe "BigDecimal#+" do
end
it "returns NaN if NaN is involved" do
- (@one + @nan).nan?.should == true
- (@nan + @one).nan?.should == true
+ (@one + @nan).should.nan?
+ (@nan + @one).should.nan?
end
it "returns Infinity or -Infinity if these are involved" do
@@ -41,7 +41,7 @@ describe "BigDecimal#+" do
end
it "returns NaN if Infinity + (- Infinity)" do
- (@infinity + @infinity_minus).nan?.should == true
+ (@infinity + @infinity_minus).should.nan?
end
describe "with Object" do
diff --git a/spec/ruby/library/bigdecimal/precs_spec.rb b/spec/ruby/library/bigdecimal/precs_spec.rb
index f9320f2b9e..8809d094ef 100644
--- a/spec/ruby/library/bigdecimal/precs_spec.rb
+++ b/spec/ruby/library/bigdecimal/precs_spec.rb
@@ -1,48 +1,50 @@
require_relative '../../spec_helper'
require 'bigdecimal'
-describe "BigDecimal#precs" do
+ruby_version_is ""..."3.0" do
+ describe "BigDecimal#precs" do
- before :each do
- @infinity = BigDecimal("Infinity")
- @infinity_neg = BigDecimal("-Infinity")
- @nan = BigDecimal("NaN")
- @zero = BigDecimal("0")
- @zero_neg = BigDecimal("-0")
+ 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
+ @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
- @arr.each do |x|
- x.precs.kind_of?(Array).should == true
- x.precs.size.should == 2
+ it "returns array of two values" do
+ @arr.each do |x|
+ x.precs.kind_of?(Array).should == true
+ x.precs.size.should == 2
+ end
end
- end
- it "returns Integers as array values" do
- @arr.each do |x|
- x.precs[0].kind_of?(Integer).should == true
- x.precs[1].kind_of?(Integer).should == true
+ it "returns Integers as array values" do
+ @arr.each do |x|
+ x.precs[0].kind_of?(Integer).should == true
+ x.precs[1].kind_of?(Integer).should == true
+ end
end
- end
- it "returns the current value of significant digits as the first value" do
- BigDecimal("3.14159").precs[0].should >= 6
- BigDecimal('1').precs[0].should == BigDecimal('1' + '0' * 100).precs[0]
- [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value|
- value.precs[0].should <= @precision
+ it "returns the current value of significant digits as the first value" do
+ BigDecimal("3.14159").precs[0].should >= 6
+ BigDecimal('1').precs[0].should == BigDecimal('1' + '0' * 100).precs[0]
+ [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value|
+ value.precs[0].should <= @precision
+ end
end
- end
- it "returns the maximum number of significant digits as the second value" do
- BigDecimal("3.14159").precs[1].should >= 6
- BigDecimal('1').precs[1].should >= 1
- BigDecimal('1' + '0' * 100).precs[1] >= 101
- [@infinity, @infinity_neg, @nan, @zero, @zero_neg].each do |value|
- value.precs[1].should >= 1
+ it "returns the maximum number of significant digits as the second value" do
+ BigDecimal("3.14159").precs[1].should >= 6
+ BigDecimal('1').precs[1].should >= 1
+ BigDecimal('1' + '0' * 100).precs[1].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/quo_spec.rb b/spec/ruby/library/bigdecimal/quo_spec.rb
index a5c5651778..65a4330303 100644
--- a/spec/ruby/library/bigdecimal/quo_spec.rb
+++ b/spec/ruby/library/bigdecimal/quo_spec.rb
@@ -6,7 +6,7 @@ describe "BigDecimal#quo" do
it_behaves_like :bigdecimal_quo, :quo, []
it "returns NaN if NaN is involved" do
- BigDecimal("1").quo(BigDecimal("NaN")).nan?.should == true
- BigDecimal("NaN").quo(BigDecimal("1")).nan?.should == true
+ BigDecimal("1").quo(BigDecimal("NaN")).should.nan?
+ BigDecimal("NaN").quo(BigDecimal("1")).should.nan?
end
end
diff --git a/spec/ruby/library/bigdecimal/remainder_spec.rb b/spec/ruby/library/bigdecimal/remainder_spec.rb
index 04233edece..1866f665cd 100644
--- a/spec/ruby/library/bigdecimal/remainder_spec.rb
+++ b/spec/ruby/library/bigdecimal/remainder_spec.rb
@@ -38,8 +38,8 @@ describe "BigDecimal#remainder" do
end
it "returns NaN used with zero" do
- @mixed.remainder(@zero).nan?.should == true
- @zero.remainder(@zero).nan?.should == true
+ @mixed.remainder(@zero).should.nan?
+ @zero.remainder(@zero).should.nan?
end
it "returns zero if used on zero" do
@@ -47,28 +47,28 @@ describe "BigDecimal#remainder" do
end
it "returns NaN if NaN is involved" do
- @nan.remainder(@nan).nan?.should == true
- @nan.remainder(@one).nan?.should == true
- @one.remainder(@nan).nan?.should == true
- @infinity.remainder(@nan).nan?.should == true
- @nan.remainder(@infinity).nan?.should == true
+ @nan.remainder(@nan).should.nan?
+ @nan.remainder(@one).should.nan?
+ @one.remainder(@nan).should.nan?
+ @infinity.remainder(@nan).should.nan?
+ @nan.remainder(@infinity).should.nan?
end
it "returns NaN if Infinity is involved" do
- @infinity.remainder(@infinity).nan?.should == true
- @infinity.remainder(@one).nan?.should == true
- @infinity.remainder(@mixed).nan?.should == true
- @infinity.remainder(@one_minus).nan?.should == true
- @infinity.remainder(@frac_1).nan?.should == true
- @one.remainder(@infinity).nan?.should == true
+ @infinity.remainder(@infinity).should.nan?
+ @infinity.remainder(@one).should.nan?
+ @infinity.remainder(@mixed).should.nan?
+ @infinity.remainder(@one_minus).should.nan?
+ @infinity.remainder(@frac_1).should.nan?
+ @one.remainder(@infinity).should.nan?
- @infinity_minus.remainder(@infinity_minus).nan?.should == true
- @infinity_minus.remainder(@one).nan?.should == true
- @one.remainder(@infinity_minus).nan?.should == true
- @frac_2.remainder(@infinity_minus).nan?.should == true
+ @infinity_minus.remainder(@infinity_minus).should.nan?
+ @infinity_minus.remainder(@one).should.nan?
+ @one.remainder(@infinity_minus).should.nan?
+ @frac_2.remainder(@infinity_minus).should.nan?
- @infinity.remainder(@infinity_minus).nan?.should == true
- @infinity_minus.remainder(@infinity).nan?.should == true
+ @infinity.remainder(@infinity_minus).should.nan?
+ @infinity_minus.remainder(@infinity).should.nan?
end
it "coerces arguments to BigDecimal if possible" do
diff --git a/spec/ruby/library/bigdecimal/shared/clone.rb b/spec/ruby/library/bigdecimal/shared/clone.rb
index e58df3a94b..935ef76e7e 100644
--- a/spec/ruby/library/bigdecimal/shared/clone.rb
+++ b/spec/ruby/library/bigdecimal/shared/clone.rb
@@ -5,20 +5,9 @@ describe :bigdecimal_clone, shared: true do
@obj = BigDecimal("1.2345")
end
- ruby_version_is "" ... "2.5" do
- it "copies the BigDecimal's value to a newly allocated object" do
- copy = @obj.public_send(@method)
+ it "returns self" do
+ copy = @obj.public_send(@method)
- copy.should_not equal(@obj)
- copy.should == @obj
- end
- end
-
- ruby_version_is "2.5" do
- it "returns self" do
- copy = @obj.public_send(@method)
-
- copy.should equal(@obj)
- end
+ copy.should equal(@obj)
end
end
diff --git a/spec/ruby/library/bigdecimal/shared/modulo.rb b/spec/ruby/library/bigdecimal/shared/modulo.rb
index 67c0ecf2fc..aa5c5a640b 100644
--- a/spec/ruby/library/bigdecimal/shared/modulo.rb
+++ b/spec/ruby/library/bigdecimal/shared/modulo.rb
@@ -80,25 +80,25 @@ describe :bigdecimal_modulo, shared: true do
end
it "returns NaN if NaN is involved" do
- @nan.send(@method, @nan).nan?.should == true
- @nan.send(@method, @one).nan?.should == true
- @one.send(@method, @nan).nan?.should == true
- @infinity.send(@method, @nan).nan?.should == true
- @nan.send(@method, @infinity).nan?.should == true
+ @nan.send(@method, @nan).should.nan?
+ @nan.send(@method, @one).should.nan?
+ @one.send(@method, @nan).should.nan?
+ @infinity.send(@method, @nan).should.nan?
+ @nan.send(@method, @infinity).should.nan?
end
it "returns NaN if the dividend is Infinity" do
- @infinity.send(@method, @infinity).nan?.should == true
- @infinity.send(@method, @one).nan?.should == true
- @infinity.send(@method, @mixed).nan?.should == true
- @infinity.send(@method, @one_minus).nan?.should == true
- @infinity.send(@method, @frac_1).nan?.should == true
+ @infinity.send(@method, @infinity).should.nan?
+ @infinity.send(@method, @one).should.nan?
+ @infinity.send(@method, @mixed).should.nan?
+ @infinity.send(@method, @one_minus).should.nan?
+ @infinity.send(@method, @frac_1).should.nan?
- @infinity_minus.send(@method, @infinity_minus).nan?.should == true
- @infinity_minus.send(@method, @one).nan?.should == true
+ @infinity_minus.send(@method, @infinity_minus).should.nan?
+ @infinity_minus.send(@method, @one).should.nan?
- @infinity.send(@method, @infinity_minus).nan?.should == true
- @infinity_minus.send(@method, @infinity).nan?.should == true
+ @infinity.send(@method, @infinity_minus).should.nan?
+ @infinity_minus.send(@method, @infinity).should.nan?
end
it "returns the dividend if the divisor is Infinity" do
diff --git a/spec/ruby/library/bigdecimal/shared/mult.rb b/spec/ruby/library/bigdecimal/shared/mult.rb
index b94c9385de..c613df04c4 100644
--- a/spec/ruby/library/bigdecimal/shared/mult.rb
+++ b/spec/ruby/library/bigdecimal/shared/mult.rb
@@ -51,8 +51,8 @@ describe :bigdecimal_mult, shared: true do
values = @regular_vals + @zeroes
values.each do |val|
- @nan.send(@method, val, *@object).nan?.should == true
- val.send(@method, @nan, *@object).nan?.should == true
+ @nan.send(@method, val, *@object).should.nan?
+ val.send(@method, @nan, *@object).should.nan?
end
end
@@ -62,9 +62,9 @@ describe :bigdecimal_mult, shared: true do
values.each do |val|
@zeroes.each do |zero|
zero.send(@method, val, *@object).should == 0
- zero.send(@method, val, *@object).zero?.should == true
+ zero.send(@method, val, *@object).should.zero?
val.send(@method, zero, *@object).should == 0
- val.send(@method, zero, *@object).zero?.should == true
+ val.send(@method, zero, *@object).should.zero?
end
end
end
@@ -75,8 +75,8 @@ describe :bigdecimal_mult, shared: true do
values.each do |val|
infs.each do |inf|
- inf.send(@method, val, *@object).finite?.should == false
- val.send(@method, inf, *@object).finite?.should == false
+ inf.send(@method, val, *@object).should_not.finite?
+ val.send(@method, inf, *@object).should_not.finite?
end
end
@@ -89,9 +89,9 @@ describe :bigdecimal_mult, shared: true do
end
it "returns NaN if the result is undefined" do
- @zero.send(@method, @infinity, *@object).nan?.should == true
- @zero.send(@method, @infinity_minus, *@object).nan?.should == true
- @infinity.send(@method, @zero, *@object).nan?.should == true
- @infinity_minus.send(@method, @zero, *@object).nan?.should == true
+ @zero.send(@method, @infinity, *@object).should.nan?
+ @zero.send(@method, @infinity_minus, *@object).should.nan?
+ @infinity.send(@method, @zero, *@object).should.nan?
+ @infinity_minus.send(@method, @zero, *@object).should.nan?
end
end
diff --git a/spec/ruby/library/bigdecimal/shared/power.rb b/spec/ruby/library/bigdecimal/shared/power.rb
index a4848fb2e2..568a08589b 100644
--- a/spec/ruby/library/bigdecimal/shared/power.rb
+++ b/spec/ruby/library/bigdecimal/shared/power.rb
@@ -53,8 +53,8 @@ describe :bigdecimal_power, shared: true do
end
it "returns NaN if self is NaN" do
- BigDecimal("NaN").send(@method, -5).nan?.should == true
- BigDecimal("NaN").send(@method, 5).nan?.should == true
+ BigDecimal("NaN").send(@method, -5).should.nan?
+ BigDecimal("NaN").send(@method, 5).should.nan?
end
it "returns 0.0 if self is infinite and argument is negative" do
diff --git a/spec/ruby/library/bigdecimal/shared/quo.rb b/spec/ruby/library/bigdecimal/shared/quo.rb
index 4d6d64b787..46e6d62bf4 100644
--- a/spec/ruby/library/bigdecimal/shared/quo.rb
+++ b/spec/ruby/library/bigdecimal/shared/quo.rb
@@ -49,8 +49,8 @@ describe :bigdecimal_quo, shared: true do
end
it "returns NaN if Infinity / ((+|-) Infinity)" do
- @infinity.send(@method, @infinity_minus, *@object).nan?.should == true
- @infinity_minus.send(@method, @infinity, *@object).nan?.should == true
+ @infinity.send(@method, @infinity_minus, *@object).should.nan?
+ @infinity_minus.send(@method, @infinity, *@object).should.nan?
end
it "returns (+|-) Infinity if divided by zero" do
@@ -60,8 +60,8 @@ describe :bigdecimal_quo, shared: true do
end
it "returns NaN if zero is divided by zero" do
- @zero.send(@method, @zero, *@object).nan?.should == true
- @zero_minus.send(@method, @zero_plus, *@object).nan?.should == true
- @zero_plus.send(@method, @zero_minus, *@object).nan?.should == true
+ @zero.send(@method, @zero, *@object).should.nan?
+ @zero_minus.send(@method, @zero_plus, *@object).should.nan?
+ @zero_plus.send(@method, @zero_minus, *@object).should.nan?
end
end
diff --git a/spec/ruby/library/bigdecimal/shared/to_int.rb b/spec/ruby/library/bigdecimal/shared/to_int.rb
index 02f6092f23..41dd200b9f 100644
--- a/spec/ruby/library/bigdecimal/shared/to_int.rb
+++ b/spec/ruby/library/bigdecimal/shared/to_int.rb
@@ -6,7 +6,7 @@ describe :bigdecimal_to_int , shared: true do
-> { BigDecimal("NaN").send(@method) }.should raise_error(FloatDomainError)
end
- it "returns Integer or Bignum otherwise" do
+ it "returns Integer or Integer otherwise" do
BigDecimal("3E-20001").send(@method).should == 0
BigDecimal("2E4000").send(@method).should == 2 * 10 ** 4000
BigDecimal("2").send(@method).should == 2
diff --git a/spec/ruby/library/bigdecimal/sub_spec.rb b/spec/ruby/library/bigdecimal/sub_spec.rb
index 29ec851193..bddfec2186 100644
--- a/spec/ruby/library/bigdecimal/sub_spec.rb
+++ b/spec/ruby/library/bigdecimal/sub_spec.rb
@@ -50,13 +50,13 @@ describe "BigDecimal#sub" do
end
it "returns NaN if NaN is involved" do
- @one.sub(@nan, 1).nan?.should == true
- @nan.sub(@one, 1).nan?.should == true
+ @one.sub(@nan, 1).should.nan?
+ @nan.sub(@one, 1).should.nan?
end
it "returns NaN if both values are infinite with the same signs" do
- @infinity.sub(@infinity, 1).nan?.should == true
- @infinity_minus.sub(@infinity_minus, 1).nan?.should == true
+ @infinity.sub(@infinity, 1).should.nan?
+ @infinity_minus.sub(@infinity_minus, 1).should.nan?
end
it "returns Infinity or -Infinity if these are involved" do
diff --git a/spec/ruby/library/bigdecimal/to_f_spec.rb b/spec/ruby/library/bigdecimal/to_f_spec.rb
index 1cc25d5c40..84d4d49de2 100644
--- a/spec/ruby/library/bigdecimal/to_f_spec.rb
+++ b/spec/ruby/library/bigdecimal/to_f_spec.rb
@@ -41,7 +41,7 @@ describe "BigDecimal#to_f" do
@zero.to_f.should == 0
@zero.to_f.to_s.should == "0.0"
- @nan.to_f.nan?.should == true
+ @nan.to_f.should.nan?
@infinity.to_f.infinite?.should == 1
@infinity_minus.to_f.infinite?.should == -1
diff --git a/spec/ruby/library/bigdecimal/to_s_spec.rb b/spec/ruby/library/bigdecimal/to_s_spec.rb
index b6154c680d..4f1054d38e 100644
--- a/spec/ruby/library/bigdecimal/to_s_spec.rb
+++ b/spec/ruby/library/bigdecimal/to_s_spec.rb
@@ -8,6 +8,11 @@ describe "BigDecimal#to_s" do
@bigneg_str = "-3.1415926535897932384626433832795028841971693993"
@bigdec = BigDecimal(@bigdec_str)
@bigneg = BigDecimal(@bigneg_str)
+ @internal = Encoding.default_internal
+ end
+
+ after :each do
+ Encoding.default_internal = @internal
end
it "return type is of class String" do
@@ -41,6 +46,7 @@ describe "BigDecimal#to_s" do
str1 = '-123.45678 90123 45678 9'
BigDecimal("-123.45678901234567890").to_s('5F').should == str1
+ BigDecimal('1000010').to_s('5F').should == "10000 10.0"
# trailing zeroes removed
BigDecimal("1.00000000000").to_s('1F').should == "1.0"
# 0 is treated as no spaces
@@ -77,4 +83,15 @@ describe "BigDecimal#to_s" do
end
end
+ ruby_version_is "3.0" do
+ it "returns a String in US-ASCII encoding when Encoding.default_internal is nil" do
+ Encoding.default_internal = nil
+ BigDecimal('1.23').to_s.encoding.should equal(Encoding::US_ASCII)
+ end
+
+ it "returns a String in US-ASCII encoding when Encoding.default_internal is not nil" do
+ Encoding.default_internal = Encoding::IBM437
+ BigDecimal('1.23').to_s.encoding.should equal(Encoding::US_ASCII)
+ end
+ end
end
diff --git a/spec/ruby/library/bigdecimal/truncate_spec.rb b/spec/ruby/library/bigdecimal/truncate_spec.rb
index d3a15f62c7..4ad9eb92d1 100644
--- a/spec/ruby/library/bigdecimal/truncate_spec.rb
+++ b/spec/ruby/library/bigdecimal/truncate_spec.rb
@@ -58,9 +58,9 @@ describe "BigDecimal#truncate" do
end
it "returns NaN if self is NaN" do
- @nan.truncate(-1).nan?.should == true
- @nan.truncate(+1).nan?.should == true
- @nan.truncate(0).nan?.should == true
+ @nan.truncate(-1).should.nan?
+ @nan.truncate(+1).should.nan?
+ @nan.truncate(0).should.nan?
end
it "returns Infinity if self is infinite" do
diff --git a/spec/ruby/library/bigdecimal/uminus_spec.rb b/spec/ruby/library/bigdecimal/uminus_spec.rb
index 5e2a786c4c..c780cdfac5 100644
--- a/spec/ruby/library/bigdecimal/uminus_spec.rb
+++ b/spec/ruby/library/bigdecimal/uminus_spec.rb
@@ -53,6 +53,6 @@ describe "BigDecimal#-@" do
@zero_neg.send(:-@).should == @zero
@zero_neg.send(:-@).sign.should == 1
- @nan.send(:-@).nan?.should == true
+ @nan.send(:-@).should.nan?
end
end
diff --git a/spec/ruby/library/bigdecimal/zero_spec.rb b/spec/ruby/library/bigdecimal/zero_spec.rb
index c5d3acb8c3..2563210939 100644
--- a/spec/ruby/library/bigdecimal/zero_spec.rb
+++ b/spec/ruby/library/bigdecimal/zero_spec.rb
@@ -6,22 +6,22 @@ describe "BigDecimal#zero?" do
it "returns true if self does equal zero" do
really_small_zero = BigDecimal("0E-200000000")
really_big_zero = BigDecimal("0E200000000000")
- really_small_zero.zero?.should == true
- really_big_zero.zero?.should == true
- BigDecimal("0.000000000000000000000000").zero?.should == true
- BigDecimal("0").zero?.should == true
- BigDecimal("0E0").zero?.should == true
- BigDecimal("+0").zero?.should == true
- BigDecimal("-0").zero?.should == true
+ really_small_zero.should.zero?
+ really_big_zero.should.zero?
+ BigDecimal("0.000000000000000000000000").should.zero?
+ BigDecimal("0").should.zero?
+ BigDecimal("0E0").should.zero?
+ BigDecimal("+0").should.zero?
+ BigDecimal("-0").should.zero?
end
it "returns false otherwise" do
- BigDecimal("0000000001").zero?.should == false
- BigDecimal("2E40001").zero?.should == false
- BigDecimal("3E-20001").zero?.should == false
- BigDecimal("Infinity").zero?.should == false
- BigDecimal("-Infinity").zero?.should == false
- BigDecimal("NaN").zero?.should == false
+ BigDecimal("0000000001").should_not.zero?
+ BigDecimal("2E40001").should_not.zero?
+ BigDecimal("3E-20001").should_not.zero?
+ BigDecimal("Infinity").should_not.zero?
+ BigDecimal("-Infinity").should_not.zero?
+ BigDecimal("NaN").should_not.zero?
end
end
diff --git a/spec/ruby/library/cgi/cookie/name_spec.rb b/spec/ruby/library/cgi/cookie/name_spec.rb
index 326a43ade3..14226824c8 100644
--- a/spec/ruby/library/cgi/cookie/name_spec.rb
+++ b/spec/ruby/library/cgi/cookie/name_spec.rb
@@ -6,18 +6,18 @@ describe "CGI::Cookie#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"
+ cookie = CGI::Cookie.new("name" => "another cookie")
+ cookie.name.should == "another cookie"
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"
+ 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
diff --git a/spec/ruby/library/cgi/cookie/parse_spec.rb b/spec/ruby/library/cgi/cookie/parse_spec.rb
index d484c7bad9..90d2c3d148 100644
--- a/spec/ruby/library/cgi/cookie/parse_spec.rb
+++ b/spec/ruby/library/cgi/cookie/parse_spec.rb
@@ -6,16 +6,16 @@ describe "CGI::Cookie.parse" do
expected = { "test-cookie" => ["one", "two", "three"] }
CGI::Cookie.parse("test-cookie=one&two&three").should == expected
- expected = { "second-cookie" => ["three", "four"], "first-cookie" => ["one", "two"] }
- CGI::Cookie.parse("first-cookie=one&two;second-cookie=three&four").should == expected
+ 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"]
+ "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
+ CGI::Cookie.parse("first cookie=one&two;second cookie=three&four,third_cookie=five&six").should == expected
end
it "unescapes the Cookie values" do
diff --git a/spec/ruby/library/cgi/cookie/to_s_spec.rb b/spec/ruby/library/cgi/cookie/to_s_spec.rb
index 978c2d33eb..da15e6ed2a 100644
--- a/spec/ruby/library/cgi/cookie/to_s_spec.rb
+++ b/spec/ruby/library/cgi/cookie/to_s_spec.rb
@@ -27,16 +27,7 @@ describe "CGI::Cookie#to_s" do
cookie.to_s.should == "test-cookie=+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D; path="
end
- ruby_version_is ""..."2.5" do
- it "escapes tilde" do
- cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=%7E; path="
- end
+ it "does not escape tilde" do
+ cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=~; path="
end
-
- ruby_version_is "2.5" do
- it "does not escape tilde" do
- cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=~; path="
- end
- end
-
end
diff --git a/spec/ruby/library/cgi/escapeHTML_spec.rb b/spec/ruby/library/cgi/escapeHTML_spec.rb
index dcbfebe720..421aac5d4a 100644
--- a/spec/ruby/library/cgi/escapeHTML_spec.rb
+++ b/spec/ruby/library/cgi/escapeHTML_spec.rb
@@ -6,6 +6,10 @@ describe "CGI.escapeHTML" do
CGI.escapeHTML(%[& < > " ']).should == '&amp; &lt; &gt; &quot; &#39;'
end
+ it "escapes invalid encoding" do
+ CGI.escapeHTML(%[<\xA4??>]).should == "&lt;\xA4??&gt;"
+ end
+
it "does not escape any other characters" do
chars = " !\#$%()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
CGI.escapeHTML(chars).should == chars
diff --git a/spec/ruby/library/cgi/escape_spec.rb b/spec/ruby/library/cgi/escape_spec.rb
index 351bfe1070..c599a73cf0 100644
--- a/spec/ruby/library/cgi/escape_spec.rb
+++ b/spec/ruby/library/cgi/escape_spec.rb
@@ -7,20 +7,12 @@ describe "CGI.escape" do
expected = "+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D"
CGI.escape(input).should == expected
- input = "http://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277"
- expected = 'http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF'
+ input = "https://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277"
+ expected = 'https%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF'
CGI.escape(input).should == expected
end
- ruby_version_is ""..."2.5" do
- it "escapes tilde" do
- CGI.escape("~").should == "%7E"
- end
- end
-
- ruby_version_is "2.5" do
- it "does not escape tilde" do
- CGI.escape("~").should == "~"
- end
+ it "does not escape tilde" do
+ CGI.escape("~").should == "~"
end
end
diff --git a/spec/ruby/library/cgi/unescapeHTML_spec.rb b/spec/ruby/library/cgi/unescapeHTML_spec.rb
index 46387d4f01..84b30c6aa6 100644
--- a/spec/ruby/library/cgi/unescapeHTML_spec.rb
+++ b/spec/ruby/library/cgi/unescapeHTML_spec.rb
@@ -36,4 +36,9 @@ describe "CGI.unescapeHTML" do
input = "fooooooo&#"
CGI.unescapeHTML(input).should == input
end
+
+ it "unescapes invalid encoding" do
+ input = "\xFF&"
+ CGI.unescapeHTML(input).should == input
+ end
end
diff --git a/spec/ruby/library/cgi/unescape_spec.rb b/spec/ruby/library/cgi/unescape_spec.rb
index db4834e7e8..c593e24b4a 100644
--- a/spec/ruby/library/cgi/unescape_spec.rb
+++ b/spec/ruby/library/cgi/unescape_spec.rb
@@ -8,8 +8,8 @@ describe "CGI.unescape" do
expected = " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
CGI.unescape(input).should == expected
- input = 'http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF'
- expected = "http://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277"
+ input = 'https%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF'
+ expected = "https://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277"
CGI.unescape(input).should == expected
end
end
diff --git a/spec/ruby/library/conditionvariable/broadcast_spec.rb b/spec/ruby/library/conditionvariable/broadcast_spec.rb
index a31a0443bd..d88159df23 100644
--- a/spec/ruby/library/conditionvariable/broadcast_spec.rb
+++ b/spec/ruby/library/conditionvariable/broadcast_spec.rb
@@ -2,33 +2,6 @@ require_relative '../../spec_helper'
require 'thread'
describe "ConditionVariable#broadcast" do
- it "returns self if nothing to broadcast to" do
- cv = ConditionVariable.new
- cv.broadcast.should == cv
- end
-
- it "returns self if something is waiting for a broadcast" do
- m = Mutex.new
- cv = ConditionVariable.new
- in_synchronize = false
-
- th = Thread.new do
- m.synchronize do
- in_synchronize = true
- cv.wait(m)
- end
- end
-
- # wait for m to acquire the mutex
- Thread.pass until in_synchronize
- # wait until th is sleeping (ie waiting)
- Thread.pass while th.status and th.status != "sleep"
-
- m.synchronize { cv.broadcast }.should == cv
-
- th.join
- end
-
it "releases all threads waiting in line for this resource" do
m = Mutex.new
cv = ConditionVariable.new
@@ -50,7 +23,7 @@ describe "ConditionVariable#broadcast" do
# wait for all threads to acquire the mutex the first time
Thread.pass until m.synchronize { r1.size == threads.size }
# wait until all threads are sleeping (ie waiting)
- Thread.pass until threads.all? {|th| th.status == "sleep" }
+ Thread.pass until threads.all?(&:stop?)
r2.should be_empty
m.synchronize do
diff --git a/spec/ruby/library/conditionvariable/signal_spec.rb b/spec/ruby/library/conditionvariable/signal_spec.rb
index 04b249a6c6..86383073f1 100644
--- a/spec/ruby/library/conditionvariable/signal_spec.rb
+++ b/spec/ruby/library/conditionvariable/signal_spec.rb
@@ -2,33 +2,6 @@ require_relative '../../spec_helper'
require 'thread'
describe "ConditionVariable#signal" do
- it "returns self if nothing to signal" do
- cv = ConditionVariable.new
- cv.signal.should == cv
- end
-
- it "returns self if something is waiting for a signal" do
- m = Mutex.new
- cv = ConditionVariable.new
- in_synchronize = false
-
- th = Thread.new do
- m.synchronize do
- in_synchronize = true
- cv.wait(m)
- end
- end
-
- # wait for m to acquire the mutex
- Thread.pass until in_synchronize
- # wait until th is sleeping (ie waiting)
- Thread.pass while th.status and th.status != "sleep"
-
- m.synchronize { cv.signal }.should == cv
-
- th.join
- end
-
it "releases the first thread waiting in line for this resource" do
m = Mutex.new
cv = ConditionVariable.new
@@ -50,7 +23,7 @@ describe "ConditionVariable#signal" do
# wait for all threads to acquire the mutex the first time
Thread.pass until m.synchronize { r1.size == threads.size }
# wait until all threads are sleeping (ie waiting)
- Thread.pass until threads.all? {|th| th.status == "sleep" }
+ Thread.pass until threads.all?(&:stop?)
r2.should be_empty
100.times do |i|
@@ -85,7 +58,7 @@ describe "ConditionVariable#signal" do
# Make sure t1 is waiting for a signal before launching t2.
Thread.pass until in_synchronize
- Thread.pass until t1.status == 'sleep'
+ Thread.pass until t1.stop?
t2 = Thread.new do
m.synchronize do
@@ -99,6 +72,6 @@ describe "ConditionVariable#signal" do
# Check that both threads terminated without exception
t1.join
t2.join
- m.locked?.should == false
+ m.should_not.locked?
end
end
diff --git a/spec/ruby/library/conditionvariable/wait_spec.rb b/spec/ruby/library/conditionvariable/wait_spec.rb
index f57ab4c778..9a68c2b5a1 100644
--- a/spec/ruby/library/conditionvariable/wait_spec.rb
+++ b/spec/ruby/library/conditionvariable/wait_spec.rb
@@ -11,7 +11,7 @@ describe "ConditionVariable#wait" do
cv.wait(o, 1234)
end
- it "returns self" do
+ it "can be woken up by ConditionVariable#signal" do
m = Mutex.new
cv = ConditionVariable.new
in_synchronize = false
@@ -19,17 +19,62 @@ describe "ConditionVariable#wait" do
th = Thread.new do
m.synchronize do
in_synchronize = true
- cv.wait(m).should == cv
+ cv.wait(m)
end
+ :success
end
# wait for m to acquire the mutex
Thread.pass until in_synchronize
# wait until th is sleeping (ie waiting)
- Thread.pass while th.status and th.status != "sleep"
+ Thread.pass until th.stop?
m.synchronize { cv.signal }
- th.join
+ th.value.should == :success
+ end
+
+ it "can be interrupted by Thread#run" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ in_synchronize = false
+
+ th = Thread.new do
+ m.synchronize do
+ in_synchronize = true
+ cv.wait(m)
+ end
+ :success
+ end
+
+ # wait for m to acquire the mutex
+ Thread.pass until in_synchronize
+ # wait until th is sleeping (ie waiting)
+ Thread.pass until th.stop?
+
+ th.run
+ th.value.should == :success
+ end
+
+ it "can be interrupted by Thread#wakeup" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ in_synchronize = false
+
+ th = Thread.new do
+ m.synchronize do
+ in_synchronize = true
+ cv.wait(m)
+ end
+ :success
+ end
+
+ # wait for m to acquire the mutex
+ Thread.pass until in_synchronize
+ # wait until th is sleeping (ie waiting)
+ Thread.pass until th.stop?
+
+ th.wakeup
+ th.value.should == :success
end
it "reacquires the lock even if the thread is killed" do
@@ -53,7 +98,7 @@ describe "ConditionVariable#wait" do
# wait for m to acquire the mutex
Thread.pass until in_synchronize
# wait until th is sleeping (ie waiting)
- Thread.pass while th.status and th.status != "sleep"
+ Thread.pass until th.stop?
th.kill
th.join
@@ -61,41 +106,39 @@ describe "ConditionVariable#wait" do
owned.should == true
end
- ruby_bug '#14999', ''...'2.5' do
- it "reacquires the lock even if the thread is killed after being signaled" do
- m = Mutex.new
- cv = ConditionVariable.new
- in_synchronize = false
- owned = nil
-
- th = Thread.new do
- m.synchronize do
- in_synchronize = true
- begin
- cv.wait(m)
- ensure
- owned = m.owned?
- $stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned
- end
+ it "reacquires the lock even if the thread is killed after being signaled" do
+ m = Mutex.new
+ cv = ConditionVariable.new
+ in_synchronize = false
+ owned = nil
+
+ th = Thread.new do
+ m.synchronize do
+ in_synchronize = true
+ begin
+ cv.wait(m)
+ ensure
+ owned = m.owned?
+ $stderr.puts "\nThe Thread doesn't own the Mutex!" unless owned
end
end
+ end
- # wait for m to acquire the mutex
- Thread.pass until in_synchronize
- # wait until th is sleeping (ie waiting)
- Thread.pass while th.status and th.status != "sleep"
-
- m.synchronize {
- cv.signal
- # Wait that the thread is blocked on acquiring the Mutex
- sleep 0.001
- # Kill the thread, yet the thread should first acquire the Mutex before going on
- th.kill
- }
+ # wait for m to acquire the mutex
+ Thread.pass until in_synchronize
+ # wait until th is sleeping (ie waiting)
+ Thread.pass until th.stop?
+
+ m.synchronize {
+ cv.signal
+ # Wait that the thread is blocked on acquiring the Mutex
+ sleep 0.001
+ # Kill the thread, yet the thread should first acquire the Mutex before going on
+ th.kill
+ }
- th.join
- owned.should == true
- end
+ th.join
+ owned.should == true
end
it "supports multiple Threads waiting on the same ConditionVariable and Mutex" do
@@ -114,7 +157,7 @@ describe "ConditionVariable#wait" do
}
Thread.pass until m.synchronize { events.size } == n_threads
- Thread.pass while threads.any? { |th| th.status and th.status != "sleep" }
+ Thread.pass until threads.any?(&:stop?)
m.synchronize do
threads.each { |t|
# Cause interactions with the waiting threads.
diff --git a/spec/ruby/library/coverage/fixtures/eval_code.rb b/spec/ruby/library/coverage/fixtures/eval_code.rb
new file mode 100644
index 0000000000..8ab82218f3
--- /dev/null
+++ b/spec/ruby/library/coverage/fixtures/eval_code.rb
@@ -0,0 +1,11 @@
+5 + 5
+
+module CoverageSpecs
+
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
+ attr_reader :ok
+ RUBY
+
+end
+
+4 + 4
diff --git a/spec/ruby/library/coverage/result_spec.rb b/spec/ruby/library/coverage/result_spec.rb
index 9b84530076..6cf5be1346 100644
--- a/spec/ruby/library/coverage/result_spec.rb
+++ b/spec/ruby/library/coverage/result_spec.rb
@@ -5,11 +5,13 @@ describe 'Coverage.result' do
before :all do
@class_file = fixture __FILE__, 'some_class.rb'
@config_file = fixture __FILE__, 'start_coverage.rb'
+ @eval_code_file = fixture __FILE__, 'eval_code.rb'
end
after :each do
$LOADED_FEATURES.delete(@class_file)
$LOADED_FEATURES.delete(@config_file)
+ $LOADED_FEATURES.delete(@eval_code_file)
end
it 'gives the covered files as a hash with arrays of count or nil' do
@@ -75,4 +77,16 @@ describe 'Coverage.result' do
require @config_file.chomp('.rb')
Coverage.result.should_not include(@config_file)
end
+
+ it 'returns the correct results when eval is used' do
+ Coverage.start
+ require @eval_code_file.chomp('.rb')
+ result = Coverage.result
+
+ result.should == {
+ @eval_code_file => [
+ 1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1
+ ]
+ }
+ end
end
diff --git a/spec/ruby/library/csv/liberal_parsing_spec.rb b/spec/ruby/library/csv/liberal_parsing_spec.rb
index 2929d6e2aa..9878658027 100644
--- a/spec/ruby/library/csv/liberal_parsing_spec.rb
+++ b/spec/ruby/library/csv/liberal_parsing_spec.rb
@@ -4,16 +4,16 @@ require 'csv'
describe "CSV#liberal_parsing?" do
it "returns true if illegal input is handled" do
csv = CSV.new("", liberal_parsing: true)
- csv.liberal_parsing?.should == true
+ csv.should.liberal_parsing?
end
it "returns false if illegal input is not handled" do
csv = CSV.new("", liberal_parsing: false)
- csv.liberal_parsing?.should == false
+ csv.should_not.liberal_parsing?
end
it "returns false by default" do
csv = CSV.new("")
- csv.liberal_parsing?.should == false
+ csv.should_not.liberal_parsing?
end
end
diff --git a/spec/ruby/library/date/constants_spec.rb b/spec/ruby/library/date/constants_spec.rb
index fc1dba4999..1d18dd1b0c 100644
--- a/spec/ruby/library/date/constants_spec.rb
+++ b/spec/ruby/library/date/constants_spec.rb
@@ -36,11 +36,11 @@ describe "Date constants" do
[Date::MONTHNAMES, Date::DAYNAMES, Date::ABBR_MONTHNAMES, Date::ABBR_DAYNAMES].each do |ary|
-> {
ary << "Unknown"
- }.should raise_error(frozen_error_class, /frozen/)
+ }.should raise_error(FrozenError, /frozen/)
ary.compact.each do |name|
-> {
name << "modified"
- }.should raise_error(frozen_error_class, /frozen/)
+ }.should raise_error(FrozenError, /frozen/)
end
end
end
diff --git a/spec/ruby/library/date/gregorian_spec.rb b/spec/ruby/library/date/gregorian_spec.rb
index 8b7033fe75..ea7ece2ade 100644
--- a/spec/ruby/library/date/gregorian_spec.rb
+++ b/spec/ruby/library/date/gregorian_spec.rb
@@ -9,7 +9,7 @@ describe "Date#gregorian?" do
end
it "marks a day after the calendar reform as Julian" do
- Date.civil(2007, 2, 27).gregorian?.should == true
+ Date.civil(2007, 2, 27).should.gregorian?
Date.civil(1607, 2, 27, Date.civil(1582, 1, 1).jd).gregorian?.should be_true
end
diff --git a/spec/ruby/library/date/infinity_spec.rb b/spec/ruby/library/date/infinity_spec.rb
index 81d67ae249..721fd76066 100644
--- a/spec/ruby/library/date/infinity_spec.rb
+++ b/spec/ruby/library/date/infinity_spec.rb
@@ -5,16 +5,16 @@ describe "Date::Infinity" do
it "should be able to check whether Infinity is zero" do
i = Date::Infinity.new
- i.zero?.should == false
+ i.should_not.zero?
end
it "should be able to check whether Infinity is finite" do
i1 = Date::Infinity.new
- i1.finite?.should == false
+ i1.should_not.finite?
i2 = Date::Infinity.new(-1)
- i2.finite?.should == false
+ i2.should_not.finite?
i3 = Date::Infinity.new(0)
- i3.finite?.should == false
+ i3.should_not.finite?
end
it "should be able to check whether Infinity is infinite" do
@@ -28,11 +28,11 @@ describe "Date::Infinity" do
it "should be able to check whether Infinity is not a number" do
i1 = Date::Infinity.new
- i1.nan?.should == false
+ i1.should_not.nan?
i2 = Date::Infinity.new(-1)
- i2.nan?.should == false
+ i2.should_not.nan?
i3 = Date::Infinity.new(0)
- i3.nan?.should == true
+ i3.should.nan?
end
it "should be able to compare Infinity objects" do
diff --git a/spec/ruby/library/date/julian_spec.rb b/spec/ruby/library/date/julian_spec.rb
index 637a4739e5..db2629d1e7 100644
--- a/spec/ruby/library/date/julian_spec.rb
+++ b/spec/ruby/library/date/julian_spec.rb
@@ -4,12 +4,12 @@ require_relative '../../spec_helper'
describe "Date#julian?" do
it "marks a day before the calendar reform as Julian" do
- Date.civil(1007, 2, 27).julian?.should == true
+ Date.civil(1007, 2, 27).should.julian?
Date.civil(1907, 2, 27, Date.civil(1930, 1, 1).jd).julian?.should be_true
end
it "marks a day after the calendar reform as Julian" do
- Date.civil(2007, 2, 27).julian?.should == false
+ Date.civil(2007, 2, 27).should_not.julian?
Date.civil(1607, 2, 27, Date.civil(1582, 1, 1).jd).julian?.should be_false
end
diff --git a/spec/ruby/library/date/parse_spec.rb b/spec/ruby/library/date/parse_spec.rb
index 379847a6fd..ef72ba3f4e 100644
--- a/spec/ruby/library/date/parse_spec.rb
+++ b/spec/ruby/library/date/parse_spec.rb
@@ -69,6 +69,23 @@ describe "Date#parse" do
-> { Date.parse(1) }.should raise_error(TypeError)
-> { Date.parse(:invalid) }.should raise_error(TypeError)
end
+
+ it "coerces using to_str" do
+ c = Class.new do
+ attr_accessor :string
+ def to_str
+ @string
+ end
+ end
+ o = c.new
+ o.string = "19101101"
+
+ d = Date.parse(o)
+ d.should == Date.civil(1910, 11, 1)
+
+ # parse should not modify string value
+ o.to_str.should == "19101101"
+ end
end
describe "Date#parse with '.' separator" do
diff --git a/spec/ruby/library/date/shared/civil.rb b/spec/ruby/library/date/shared/civil.rb
index 4c8ba23622..bbed4a8866 100644
--- a/spec/ruby/library/date/shared/civil.rb
+++ b/spec/ruby/library/date/shared/civil.rb
@@ -5,7 +5,7 @@ describe :date_civil, shared: true do
d.year.should == -4712
d.month.should == 1
d.day.should == 1
- d.julian?.should == true
+ d.should.julian?
d.jd.should == 0
end
@@ -14,7 +14,7 @@ describe :date_civil, shared: true do
d.year.should == 2000
d.month.should == 3
d.day.should == 5
- d.julian?.should == false
+ d.should_not.julian?
d.jd.should == 2451609
# Should also work with years far in the past and future
@@ -23,14 +23,14 @@ describe :date_civil, shared: true do
d.year.should == -9000
d.month.should == 7
d.day.should == 5
- d.julian?.should == true
+ d.should.julian?
d.jd.should == -1566006
d = Date.send(@method, 9000, 10, 14)
d.year.should == 9000
d.month.should == 10
d.day.should == 14
- d.julian?.should == false
+ d.should_not.julian?
d.jd.should == 5008529
end
diff --git a/spec/ruby/library/delegate/delegator/eql_spec.rb b/spec/ruby/library/delegate/delegator/eql_spec.rb
index 3170d5727a..34f56f44c9 100644
--- a/spec/ruby/library/delegate/delegator/eql_spec.rb
+++ b/spec/ruby/library/delegate/delegator/eql_spec.rb
@@ -2,45 +2,34 @@ require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
describe "Delegator#eql?" do
- ruby_version_is ""..."2.5" do
- it "is delegated" do
- base = mock('base')
- delegator = DelegateSpecs::Delegator.new(base)
- base.should_receive(:eql?).with(42).and_return(:foo)
- delegator.eql?(42).should == :foo
- end
- end
-
- ruby_version_is "2.5" do
- it "returns true when compared with same delegator" do
- base = mock('base')
- delegator = DelegateSpecs::Delegator.new(base)
+ it "returns true when compared with same delegator" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
- delegator.eql?(delegator).should be_true
- end
+ delegator.eql?(delegator).should be_true
+ end
- it "returns true when compared with the inner object" do
- base = mock('base')
- delegator = DelegateSpecs::Delegator.new(base)
+ it "returns true when compared with the inner object" do
+ base = mock('base')
+ delegator = DelegateSpecs::Delegator.new(base)
- delegator.eql?(base).should be_true
- end
+ delegator.eql?(base).should be_true
+ end
- it "returns false when compared with the delegator with other object" do
- base = mock('base')
- other = mock('other')
- delegator0 = DelegateSpecs::Delegator.new(base)
- delegator1 = DelegateSpecs::Delegator.new(other)
+ it "returns false when compared with the delegator with other object" do
+ base = mock('base')
+ other = mock('other')
+ delegator0 = DelegateSpecs::Delegator.new(base)
+ delegator1 = DelegateSpecs::Delegator.new(other)
- delegator0.eql?(delegator1).should be_false
- end
+ delegator0.eql?(delegator1).should be_false
+ end
- it "returns false when compared with the other object" do
- base = mock('base')
- other = mock('other')
- delegator = DelegateSpecs::Delegator.new(base)
+ it "returns false when compared with the other object" do
+ base = mock('base')
+ other = mock('other')
+ delegator = DelegateSpecs::Delegator.new(base)
- delegator.eql?(other).should be_false
- end
+ delegator.eql?(other).should be_false
end
end
diff --git a/spec/ruby/library/digest/bubblebabble_spec.rb b/spec/ruby/library/digest/bubblebabble_spec.rb
index e651671108..bbc11ceec5 100644
--- a/spec/ruby/library/digest/bubblebabble_spec.rb
+++ b/spec/ruby/library/digest/bubblebabble_spec.rb
@@ -23,7 +23,7 @@ describe "Digest.bubblebabble" do
-> { Digest.bubblebabble(nil) }.should raise_error(TypeError)
end
- it "raises a TypeError when passed a Fixnum" do
+ it "raises a TypeError when passed an Integer" do
-> { Digest.bubblebabble(9001) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/library/digest/hexencode_spec.rb b/spec/ruby/library/digest/hexencode_spec.rb
index fcbbf4846a..4b6db6eaff 100644
--- a/spec/ruby/library/digest/hexencode_spec.rb
+++ b/spec/ruby/library/digest/hexencode_spec.rb
@@ -25,7 +25,7 @@ describe "Digest.hexencode" do
-> { Digest.hexencode(nil) }.should raise_error(TypeError)
end
- it "raises a TypeError when passed a Fixnum" do
+ it "raises a TypeError when passed an Integer" do
-> { Digest.hexencode(9001) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/library/digest/instance/append_spec.rb b/spec/ruby/library/digest/instance/append_spec.rb
new file mode 100644
index 0000000000..2499579298
--- /dev/null
+++ b/spec/ruby/library/digest/instance/append_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../../../spec_helper'
+require 'digest'
+require_relative 'shared/update'
+
+describe "Digest::Instance#<<" do
+ it_behaves_like :digest_instance_update, :<<
+end
diff --git a/spec/ruby/library/digest/instance/new_spec.rb b/spec/ruby/library/digest/instance/new_spec.rb
new file mode 100644
index 0000000000..3f7939844b
--- /dev/null
+++ b/spec/ruby/library/digest/instance/new_spec.rb
@@ -0,0 +1,19 @@
+require_relative '../../../spec_helper'
+require 'digest'
+require_relative '../md5/shared/constants'
+
+describe "Digest::Instance#new" do
+ it "returns a copy of the digest instance" do
+ digest = Digest::MD5.new
+ copy = digest.new
+ copy.should_not.equal?(digest)
+ end
+
+ it "calls reset" do
+ digest = Digest::MD5.new
+ digest << "test"
+ digest.hexdigest.should != MD5Constants::BlankHexdigest
+ copy = digest.new
+ copy.hexdigest.should == MD5Constants::BlankHexdigest
+ end
+end
diff --git a/spec/ruby/library/digest/instance/shared/update.rb b/spec/ruby/library/digest/instance/shared/update.rb
new file mode 100644
index 0000000000..dccc8f80df
--- /dev/null
+++ b/spec/ruby/library/digest/instance/shared/update.rb
@@ -0,0 +1,8 @@
+describe :digest_instance_update, shared: true do
+ it "raises a RuntimeError if called" do
+ c = Class.new do
+ include Digest::Instance
+ end
+ -> { c.new.update("test") }.should raise_error(RuntimeError)
+ end
+end
diff --git a/spec/ruby/library/digest/instance/update_spec.rb b/spec/ruby/library/digest/instance/update_spec.rb
new file mode 100644
index 0000000000..3bb4dd7f1b
--- /dev/null
+++ b/spec/ruby/library/digest/instance/update_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../../../spec_helper'
+require 'digest'
+require_relative 'shared/update'
+
+describe "Digest::Instance#update" do
+ it_behaves_like :digest_instance_update, :update
+end
diff --git a/spec/ruby/library/digest/md5/shared/constants.rb b/spec/ruby/library/digest/md5/shared/constants.rb
index fdfae56d63..e807b96f9f 100644
--- a/spec/ruby/library/digest/md5/shared/constants.rb
+++ b/spec/ruby/library/digest/md5/shared/constants.rb
@@ -12,5 +12,6 @@ module MD5Constants
Digest = "\2473\267qw\276\364\343\345\320\304\350\313\314\217n"
BlankHexdigest = "d41d8cd98f00b204e9800998ecf8427e"
Hexdigest = "a733b77177bef4e3e5d0c4e8cbcc8f6e"
+ Base64digest = "pzO3cXe+9OPl0MToy8yPbg=="
end
diff --git a/spec/ruby/library/digest/sha1/shared/constants.rb b/spec/ruby/library/digest/sha1/shared/constants.rb
index add86b1dd3..169438747f 100644
--- a/spec/ruby/library/digest/sha1/shared/constants.rb
+++ b/spec/ruby/library/digest/sha1/shared/constants.rb
@@ -12,6 +12,7 @@ module SHA1Constants
BlankDigest = "\3329\243\356^kK\r2U\277\357\225`\030\220\257\330\a\t"
Digest = "X!\255b\323\035\352\314a|q\344+\376\317\361V9\324\343"
BlankHexdigest = "da39a3ee5e6b4b0d3255bfef95601890afd80709"
- Hexdigest = "e907d2ba21c6c74bc0efd76e44d11fb9bbb7a75e"
+ Hexdigest = "5821ad62d31deacc617c71e42bfecff15639d4e3"
+ Base64digest = "WCGtYtMd6sxhfHHkK/7P8VY51OM="
end
diff --git a/spec/ruby/library/digest/sha2/hexdigest_spec.rb b/spec/ruby/library/digest/sha2/hexdigest_spec.rb
new file mode 100644
index 0000000000..79beca5788
--- /dev/null
+++ b/spec/ruby/library/digest/sha2/hexdigest_spec.rb
@@ -0,0 +1,32 @@
+require_relative '../../../spec_helper'
+require_relative '../sha256/shared/constants'
+
+describe "Digest::SHA2#hexdigest" do
+
+ it "returns a SHA256 hexdigest by default" do
+ cur_digest = Digest::SHA2.new
+ cur_digest.hexdigest.should == SHA256Constants::BlankHexdigest
+
+ # add something to check that the state is reset later
+ cur_digest << "test"
+
+ cur_digest.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ cur_digest.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest
+
+ # after all is done, verify that the digest is in the original, blank state
+ cur_digest.hexdigest.should == SHA256Constants::BlankHexdigest
+ end
+
+end
+
+describe "Digest::SHA2.hexdigest" do
+
+ it "returns a SHA256 hexdigest by default" do
+ Digest::SHA2.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest
+ # second invocation is intentional, to make sure there are no side-effects
+ Digest::SHA2.hexdigest(SHA256Constants::Contents).should == SHA256Constants::Hexdigest
+ Digest::SHA2.hexdigest("").should == SHA256Constants::BlankHexdigest
+ end
+
+end
diff --git a/spec/ruby/library/digest/sha256/file_spec.rb b/spec/ruby/library/digest/sha256/file_spec.rb
index 6103971b5a..8cbc5a2755 100644
--- a/spec/ruby/library/digest/sha256/file_spec.rb
+++ b/spec/ruby/library/digest/sha256/file_spec.rb
@@ -22,6 +22,10 @@ describe "Digest::SHA256.file" do
Digest::SHA256.file(@file).digest.should == SHA256Constants::Digest
end
+ it "can be used with frozen-string-literal" do
+ ruby_exe("require 'digest'; puts Digest::SHA256.file(#{@file.inspect}).digest.inspect", options: "--enable=frozen-string-literal").chomp.should == SHA256Constants::Digest.inspect
+ end
+
it "calls #to_str on an object and returns the Digest::SHA256 with the result" do
obj = mock("to_str")
obj.should_receive(:to_str).and_return(@file)
diff --git a/spec/ruby/library/digest/sha256/shared/constants.rb b/spec/ruby/library/digest/sha256/shared/constants.rb
index dd5b48dca9..351679f344 100644
--- a/spec/ruby/library/digest/sha256/shared/constants.rb
+++ b/spec/ruby/library/digest/sha256/shared/constants.rb
@@ -13,5 +13,6 @@ module SHA256Constants
Digest = "\230b\265\344_\337\357\337\242\004\314\311A\211jb\350\373\254\370\365M\230B\002\372\020j\as\270\376"
BlankHexdigest = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
Hexdigest = "9862b5e45fdfefdfa204ccc941896a62e8fbacf8f54d984202fa106a0773b8fe"
+ Base64digest = "mGK15F/f79+iBMzJQYlqYuj7rPj1TZhCAvoQagdzuP4="
end
diff --git a/spec/ruby/library/digest/sha384/shared/constants.rb b/spec/ruby/library/digest/sha384/shared/constants.rb
index 3697384fc3..2050f03f2b 100644
--- a/spec/ruby/library/digest/sha384/shared/constants.rb
+++ b/spec/ruby/library/digest/sha384/shared/constants.rb
@@ -14,5 +14,6 @@ module SHA384Constants
Digest = "B&\266:\314\216z\361!TD\001{`\355\323\320MW%\270\272\0034n\034\026g\a\217\"\333s\202\275\002Y*\217]\207u\f\034\244\231\266f"
BlankHexdigest = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"
Hexdigest = "4226b63acc8e7af1215444017b60edd3d04d5725b8ba03346e1c1667078f22db7382bd02592a8f5d87750c1ca499b666"
+ Base64digest = "Qia2OsyOevEhVEQBe2Dt09BNVyW4ugM0bhwWZwePIttzgr0CWSqPXYd1DBykmbZm"
end
diff --git a/spec/ruby/library/digest/sha512/shared/constants.rb b/spec/ruby/library/digest/sha512/shared/constants.rb
index 80f5b7bc1d..2765a1ec16 100644
--- a/spec/ruby/library/digest/sha512/shared/constants.rb
+++ b/spec/ruby/library/digest/sha512/shared/constants.rb
@@ -13,5 +13,6 @@ module SHA512Constants
Digest = "\241\231\232\365\002z\241\331\242\310=\367F\272\004\326\331g\315n\251Q\222\250\374E\257\254=\325\225\003SM\350\244\234\220\233=\031\230A;\000\203\233\340\323t\333\271\222w\266\307\2678\344\255j\003\216\300"
BlankHexdigest = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
Hexdigest = "a1999af5027aa1d9a2c83df746ba04d6d967cd6ea95192a8fc45afac3dd59503534de8a49c909b3d1998413b00839be0d374dbb99277b6c7b738e4ad6a038ec0"
+ Base64digest = "oZma9QJ6odmiyD33RroE1tlnzW6pUZKo/EWvrD3VlQNTTeiknJCbPRmYQTsAg5vg03TbuZJ3tse3OOStagOOwA=="
end
diff --git a/spec/ruby/library/erb/util/shared/url_encode.rb b/spec/ruby/library/erb/util/shared/url_encode.rb
index 5ac6215523..34009c4903 100644
--- a/spec/ruby/library/erb/util/shared/url_encode.rb
+++ b/spec/ruby/library/erb/util/shared/url_encode.rb
@@ -6,21 +6,13 @@ describe :erb_util_url_encode, shared: true do
ERB::Util.__send__(@method, input).should == expected
end
- ruby_version_is ""..."2.5" do
- it "escapes tilde" do
- ERB::Util.__send__(@method, "~").should == "%7E"
- end
- end
-
- ruby_version_is "2.5" do
- it "does not escape tilde" do
- ERB::Util.__send__(@method, "~").should == "~"
- end
+ it "does not escape tilde" do
+ ERB::Util.__send__(@method, "~").should == "~"
end
it "encode unicode string" do
- input = "http://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277"
- expected = 'http%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF'
+ input = "https://ja.wikipedia.org/wiki/\343\203\255\343\203\240\343\202\271\343\202\253\343\203\273\343\203\221\343\203\255\343\203\273\343\202\246\343\203\253\343\203\273\343\203\251\343\203\224\343\203\245\343\202\277"
+ expected = 'https%3A%2F%2Fja.wikipedia.org%2Fwiki%2F%E3%83%AD%E3%83%A0%E3%82%B9%E3%82%AB%E3%83%BB%E3%83%91%E3%83%AD%E3%83%BB%E3%82%A6%E3%83%AB%E3%83%BB%E3%83%A9%E3%83%94%E3%83%A5%E3%82%BF'
ERB::Util.__send__(@method, input).should == expected
end
diff --git a/spec/ruby/library/etc/confstr_spec.rb b/spec/ruby/library/etc/confstr_spec.rb
index 0c922a3a77..41a970a918 100644
--- a/spec/ruby/library/etc/confstr_spec.rb
+++ b/spec/ruby/library/etc/confstr_spec.rb
@@ -1,7 +1,7 @@
require File.expand_path('../../../spec_helper', __FILE__)
require 'etc'
-platform_is_not :windows do
+platform_is_not :windows, :android do
describe "Etc.confstr" do
it "returns a String for Etc::CS_PATH" do
Etc.confstr(Etc::CS_PATH).should be_an_instance_of(String)
diff --git a/spec/ruby/library/etc/getgrgid_spec.rb b/spec/ruby/library/etc/getgrgid_spec.rb
index c7bd55b20e..14da5e041d 100644
--- a/spec/ruby/library/etc/getgrgid_spec.rb
+++ b/spec/ruby/library/etc/getgrgid_spec.rb
@@ -46,13 +46,6 @@ platform_is_not :windows do
gr.name.should == @name
end
- it "returns the Group for a given gid if it exists" do
- grp = Etc.getgrgid(@gid)
- grp.should be_kind_of(Struct::Group)
- grp.gid.should == @gid
- grp.name.should == @name
- end
-
it "raises if the group does not exist" do
-> { Etc.getgrgid(9876)}.should raise_error(ArgumentError)
end
diff --git a/spec/ruby/library/etc/getgrnam_spec.rb b/spec/ruby/library/etc/getgrnam_spec.rb
index a7c624efbf..fa49f15349 100644
--- a/spec/ruby/library/etc/getgrnam_spec.rb
+++ b/spec/ruby/library/etc/getgrnam_spec.rb
@@ -11,7 +11,7 @@ platform_is :windows do
end
end
-platform_is_not :windows do
+platform_is_not :windows, :android do
describe "Etc.getgrnam" do
it "returns a Etc::Group struct instance for the given group" do
gr_name = Etc.getgrent.name
diff --git a/spec/ruby/library/etc/group_spec.rb b/spec/ruby/library/etc/group_spec.rb
index fdd39bda16..fda808eec9 100644
--- a/spec/ruby/library/etc/group_spec.rb
+++ b/spec/ruby/library/etc/group_spec.rb
@@ -5,7 +5,7 @@ require 'etc'
describe "Etc.group" do
it_behaves_like :etc_on_windows, :group
- platform_is_not :windows do
+ platform_is_not :windows, :android do
it "returns a Etc::Group struct" do
group = Etc.group
begin
diff --git a/spec/ruby/library/etc/struct_group_spec.rb b/spec/ruby/library/etc/struct_group_spec.rb
index 0b50ff578f..b2147e306d 100644
--- a/spec/ruby/library/etc/struct_group_spec.rb
+++ b/spec/ruby/library/etc/struct_group_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
require 'etc'
-describe "Struct::Group" do
+describe "Etc::Group" do
platform_is_not :windows do
grpname = IO.popen(%w'id -gn', err: IO::NULL, &:read)
next unless $?.success?
diff --git a/spec/ruby/library/etc/struct_passwd_spec.rb b/spec/ruby/library/etc/struct_passwd_spec.rb
index 93ad9dfa2a..dc37c17e7d 100644
--- a/spec/ruby/library/etc/struct_passwd_spec.rb
+++ b/spec/ruby/library/etc/struct_passwd_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
require 'etc'
-describe "Struct::Passwd" do
+describe "Etc::Passwd" do
platform_is_not :windows do
before :all do
@pw = Etc.getpwuid(`id -u`.strip.to_i)
diff --git a/spec/ruby/library/fiber/current_spec.rb b/spec/ruby/library/fiber/current_spec.rb
index 52dff3dea1..e67d7d050a 100644
--- a/spec/ruby/library/fiber/current_spec.rb
+++ b/spec/ruby/library/fiber/current_spec.rb
@@ -42,10 +42,22 @@ describe "Fiber.current" do
fiber3 = Fiber.new do
states << :fiber3
fiber2.transfer
- flunk
+ ruby_version_is '3.0' do
+ states << :fiber3_terminated
+ end
+ ruby_version_is '' ... '3.0' do
+ flunk
+ end
end
fiber3.resume
- states.should == [:fiber3, :fiber2, :fiber]
+
+ ruby_version_is "" ... "3.0" do
+ states.should == [:fiber3, :fiber2, :fiber]
+ end
+
+ ruby_version_is "3.0" do
+ states.should == [:fiber3, :fiber2, :fiber, :fiber3_terminated]
+ end
end
end
diff --git a/spec/ruby/library/fiber/resume_spec.rb b/spec/ruby/library/fiber/resume_spec.rb
index dae717c8a1..39d14bdda0 100644
--- a/spec/ruby/library/fiber/resume_spec.rb
+++ b/spec/ruby/library/fiber/resume_spec.rb
@@ -3,10 +3,21 @@ require_relative '../../spec_helper'
require 'fiber'
describe "Fiber#resume" do
- it "raises a FiberError if the Fiber has transferred control to another Fiber" do
- fiber1 = Fiber.new { true }
- fiber2 = Fiber.new { fiber1.transfer; Fiber.yield }
- fiber2.resume
- -> { fiber2.resume }.should raise_error(FiberError)
+ ruby_version_is '' ... '3.0' do
+ it "raises a FiberError if the Fiber has transferred control to another Fiber" do
+ fiber1 = Fiber.new { true }
+ fiber2 = Fiber.new { fiber1.transfer; Fiber.yield }
+ fiber2.resume
+ -> { fiber2.resume }.should raise_error(FiberError)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "can work with Fiber#transfer" do
+ fiber1 = Fiber.new { true }
+ fiber2 = Fiber.new { fiber1.transfer; Fiber.yield 10 ; Fiber.yield 20; raise }
+ fiber2.resume.should == 10
+ fiber2.resume.should == 20
+ end
end
end
diff --git a/spec/ruby/library/fiber/transfer_spec.rb b/spec/ruby/library/fiber/transfer_spec.rb
index d13053666c..7af548da1a 100644
--- a/spec/ruby/library/fiber/transfer_spec.rb
+++ b/spec/ruby/library/fiber/transfer_spec.rb
@@ -11,7 +11,13 @@ 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 == :fiber1
+
+ ruby_version_is '' ... '3.0' do
+ fiber2.resume.should == :fiber1
+ end
+ ruby_version_is '3.0' do
+ fiber2.resume.should == :fiber2
+ end
end
it "returns to the root Fiber when finished" do
@@ -34,12 +40,24 @@ describe "Fiber#transfer" do
states.should == [:start, :end]
end
- it "can transfer control to a Fiber that has transferred to another Fiber" do
- states = []
- fiber1 = Fiber.new { states << :fiber1 }
- fiber2 = Fiber.new { states << :fiber2_start; fiber1.transfer; states << :fiber2_end}
- fiber2.resume.should == [:fiber2_start, :fiber1]
- fiber2.transfer.should == [:fiber2_start, :fiber1, :fiber2_end]
+ ruby_version_is '' ... '3.0' do
+ it "can transfer control to a Fiber that has transferred to another Fiber" do
+ states = []
+ fiber1 = Fiber.new { states << :fiber1 }
+ fiber2 = Fiber.new { states << :fiber2_start; fiber1.transfer; states << :fiber2_end}
+ fiber2.resume.should == [:fiber2_start, :fiber1]
+ fiber2.transfer.should == [:fiber2_start, :fiber1, :fiber2_end]
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "can not transfer control to a Fiber that has suspended by Fiber.yield" do
+ states = []
+ fiber1 = Fiber.new { states << :fiber1 }
+ fiber2 = Fiber.new { states << :fiber2_start; Fiber.yield fiber1.transfer; states << :fiber2_end}
+ fiber2.resume.should == [:fiber2_start, :fiber1]
+ -> { fiber2.transfer }.should raise_error(FiberError)
+ end
end
it "raises a FiberError when transferring to a Fiber which resumes itself" do
@@ -83,4 +101,28 @@ describe "Fiber#transfer" do
thread.join
states.should == [0, 1, 2, 3]
end
+
+ ruby_version_is "" ... "3.0" do
+ it "runs until Fiber.yield" do
+ obj = mock('obj')
+ obj.should_not_receive(:do)
+ fiber = Fiber.new { 1 + 2; Fiber.yield; obj.do }
+ fiber.transfer
+ end
+
+ it "resumes from the last call to Fiber.yield on subsequent invocations" do
+ fiber = Fiber.new { Fiber.yield :first; :second }
+ fiber.transfer.should == :first
+ fiber.transfer.should == :second
+ end
+
+ it "sets the block parameters to its arguments on the first invocation" do
+ first = mock('first')
+ first.should_receive(:arg).with(:first).twice
+
+ fiber = Fiber.new { |arg| first.arg arg; Fiber.yield; first.arg arg; }
+ fiber.transfer :first
+ fiber.transfer :second
+ end
+ end
end
diff --git a/spec/ruby/library/getoptlong/shared/get.rb b/spec/ruby/library/getoptlong/shared/get.rb
index 772a7f6773..f44cf583d2 100644
--- a/spec/ruby/library/getoptlong/shared/get.rb
+++ b/spec/ruby/library/getoptlong/shared/get.rb
@@ -53,12 +53,10 @@ describe :getoptlong_get, shared: true do
end
end
- ruby_version_is "2.5" do
- # https://bugs.ruby-lang.org/issues/13858
- it "returns multiline argument" do
- argv [ "--size=\n10k\n" ] do
- @opts.send(@method).should == [ "--size", "\n10k\n" ]
- end
+ # https://bugs.ruby-lang.org/issues/13858
+ it "returns multiline argument" do
+ argv [ "--size=\n10k\n" ] do
+ @opts.send(@method).should == [ "--size", "\n10k\n" ]
end
end
end
diff --git a/spec/ruby/library/getoptlong/terminated_spec.rb b/spec/ruby/library/getoptlong/terminated_spec.rb
index 01a8feddea..6108a7f6e9 100644
--- a/spec/ruby/library/getoptlong/terminated_spec.rb
+++ b/spec/ruby/library/getoptlong/terminated_spec.rb
@@ -5,13 +5,13 @@ describe "GetoptLong#terminated?" do
it "returns true if option processing has terminated" do
argv [ "--size", "10k" ] do
opts = GetoptLong.new(["--size", GetoptLong::REQUIRED_ARGUMENT])
- opts.terminated?.should == false
+ opts.should_not.terminated?
opts.get.should == ["--size", "10k"]
- opts.terminated?.should == false
+ opts.should_not.terminated?
opts.get.should == nil
- opts.terminated?.should == true
+ opts.should.terminated?
end
end
end
diff --git a/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb b/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb
index 9d45055d76..1128c16dd2 100644
--- a/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb
+++ b/spec/ruby/library/ipaddr/ipv4_conversion_spec.rb
@@ -8,11 +8,11 @@ describe "IPAddr#ipv4_compat" do
a.to_s.should == "::192.168.1.2"
a.to_string.should == "0000:0000:0000:0000:0000:0000:c0a8:0102"
a.family.should == Socket::AF_INET6
- a.ipv4_compat?.should == true
+ a.should.ipv4_compat?
b = a.native
b.to_s.should == "192.168.1.2"
b.family.should == Socket::AF_INET
- b.ipv4_compat?.should == false
+ b.should_not.ipv4_compat?
a = IPAddr.new("192.168.1.2")
b = a.ipv4_compat
@@ -29,11 +29,11 @@ describe "IPAddr#ipv4_mapped" do
a.to_s.should == "::ffff:192.168.1.2"
a.to_string.should == "0000:0000:0000:0000:0000:ffff:c0a8:0102"
a.family.should == Socket::AF_INET6
- a.ipv4_mapped?.should == true
+ a.should.ipv4_mapped?
b = a.native
b.to_s.should == "192.168.1.2"
b.family.should == Socket::AF_INET
- b.ipv4_mapped?.should == false
+ b.should_not.ipv4_mapped?
a = IPAddr.new("192.168.1.2")
b = a.ipv4_mapped
diff --git a/spec/ruby/library/ipaddr/new_spec.rb b/spec/ruby/library/ipaddr/new_spec.rb
index c8c8bc80b3..3148d6e39c 100644
--- a/spec/ruby/library/ipaddr/new_spec.rb
+++ b/spec/ruby/library/ipaddr/new_spec.rb
@@ -27,8 +27,8 @@ describe "IPAddr#new" do
a.to_s.should == "3ffe:505:2::"
a.to_string.should == "3ffe:0505:0002:0000:0000:0000:0000:0000"
a.family.should == Socket::AF_INET6
- a.ipv4?.should == false
- a.ipv6?.should == true
+ a.should_not.ipv4?
+ a.should.ipv6?
a.inspect.should == "#<IPAddr: IPv6:3ffe:0505:0002:0000:0000:0000:0000:0000/ffff:ffff:ffff:0000:0000:0000:0000:0000>"
end
@@ -51,8 +51,8 @@ describe "IPAddr#new" do
a.to_s.should == "192.168.1.2"
a.to_string.should == "192.168.1.2"
a.family.should == Socket::AF_INET
- a.ipv4?.should == true
- a.ipv6?.should == false
+ a.should.ipv4?
+ a.should_not.ipv6?
end
it "initializes IPAddr ipv4 address with / subnet notation" do
diff --git a/spec/ruby/library/logger/logger/debug_spec.rb b/spec/ruby/library/logger/logger/debug_spec.rb
index d92c339232..9375ab0cc6 100644
--- a/spec/ruby/library/logger/logger/debug_spec.rb
+++ b/spec/ruby/library/logger/logger/debug_spec.rb
@@ -16,12 +16,12 @@ describe "Logger#debug?" do
it "returns true if severity level allows debug messages" do
@logger.level = Logger::DEBUG
- @logger.debug?.should == true
+ @logger.should.debug?
end
it "returns false if severity level does not allow debug messages" do
@logger.level = Logger::WARN
- @logger.debug?.should == false
+ @logger.should_not.debug?
end
end
diff --git a/spec/ruby/library/logger/logger/error_spec.rb b/spec/ruby/library/logger/logger/error_spec.rb
index d5d0bd2d2f..42f1dbd883 100644
--- a/spec/ruby/library/logger/logger/error_spec.rb
+++ b/spec/ruby/library/logger/logger/error_spec.rb
@@ -16,12 +16,12 @@ describe "Logger#error?" do
it "returns true if severity level allows printing errors" do
@logger.level = Logger::INFO
- @logger.error?.should == true
+ @logger.should.error?
end
it "returns false if severity level does not allow errors" do
@logger.level = Logger::FATAL
- @logger.error?.should == false
+ @logger.should_not.error?
end
end
diff --git a/spec/ruby/library/logger/logger/fatal_spec.rb b/spec/ruby/library/logger/logger/fatal_spec.rb
index 42d4341319..f12fa3a89f 100644
--- a/spec/ruby/library/logger/logger/fatal_spec.rb
+++ b/spec/ruby/library/logger/logger/fatal_spec.rb
@@ -16,12 +16,12 @@ describe "Logger#fatal?" do
it "returns true if severity level allows fatal messages" do
@logger.level = Logger::FATAL
- @logger.fatal?.should == true
+ @logger.should.fatal?
end
it "returns false if severity level does not allow fatal messages" do
@logger.level = Logger::UNKNOWN
- @logger.fatal?.should == false
+ @logger.should_not.fatal?
end
end
diff --git a/spec/ruby/library/logger/logger/info_spec.rb b/spec/ruby/library/logger/logger/info_spec.rb
index 21eacbbb31..eb5dca48dd 100644
--- a/spec/ruby/library/logger/logger/info_spec.rb
+++ b/spec/ruby/library/logger/logger/info_spec.rb
@@ -16,12 +16,12 @@ describe "Logger#info?" do
it "returns true if severity level allows info messages" do
@logger.level = Logger::INFO
- @logger.info?.should == true
+ @logger.should.info?
end
it "returns false if severity level does not allow info messages" do
@logger.level = Logger::FATAL
- @logger.info?.should == false
+ @logger.should_not.info?
end
end
diff --git a/spec/ruby/library/logger/logger/warn_spec.rb b/spec/ruby/library/logger/logger/warn_spec.rb
index 6617b2b41a..0bca34824a 100644
--- a/spec/ruby/library/logger/logger/warn_spec.rb
+++ b/spec/ruby/library/logger/logger/warn_spec.rb
@@ -16,12 +16,12 @@ describe "Logger#warn?" do
it "returns true if severity level allows printing warn messages" do
@logger.level = Logger::WARN
- @logger.warn?.should == true
+ @logger.should.warn?
end
it "returns false if severity level does not allow printing warn messages" do
@logger.level = Logger::FATAL
- @logger.warn?.should == false
+ @logger.should_not.warn?
end
end
diff --git a/spec/ruby/library/mathn/bignum/exponent_spec.rb b/spec/ruby/library/mathn/bignum/exponent_spec.rb
deleted file mode 100644
index ddd19ffdb4..0000000000
--- a/spec/ruby/library/mathn/bignum/exponent_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require 'mathn'
-
- describe "Bignum#**" do
- before :each do
- @bignum = bignum_value(47)
- end
-
- it "returns self raised to other (positive) power" do
- (@bignum ** 4).should == 7237005577332262361485077344629993318496048279512298547155833600056910050625
- (@bignum ** 1.2).should be_close(57262152889751597425762.57804, TOLERANCE)
- end
-
- it "returns a complex number when negative and raised to a fractional power" do
- ((-@bignum) ** (1/3)).should be_close(Complex(1048576,1816186.907597341), TOLERANCE)
- ((-@bignum) ** (1.0/3)).should be_close(Complex(1048576,1816186.907597341), TOLERANCE)
- end
- end
-end
diff --git a/spec/ruby/library/mathn/complex/Complex_spec.rb b/spec/ruby/library/mathn/complex/Complex_spec.rb
deleted file mode 100644
index 105902ed5d..0000000000
--- a/spec/ruby/library/mathn/complex/Complex_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require 'mathn'
-
- describe "Kernel#Complex" do
- it "returns an Integer if imaginary part is 0" do
- Complex(42,0).should == 42
- Complex(42,0).should be_kind_of(Fixnum)
- Complex(bignum_value,0).should == bignum_value
- Complex(bignum_value,0).should be_kind_of(Bignum)
- end
- end
-end
diff --git a/spec/ruby/library/mathn/fixnum/exponent_spec.rb b/spec/ruby/library/mathn/fixnum/exponent_spec.rb
deleted file mode 100644
index 160bf7f115..0000000000
--- a/spec/ruby/library/mathn/fixnum/exponent_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require 'mathn'
-
- describe "Fixnum#**" do
- it "returns self raised to other (positive) power" do
- (2 ** 4).should == 16
- (2 ** 1.2).should be_close(2.2973967, TOLERANCE)
- end
-
- it "returns a complex number when negative and raised to a fractional power" do
- ((-8) ** (1/3)).should be_close(Complex(1, 1.73205), TOLERANCE)
- ((-8) ** (1.0/3)).should be_close(Complex(1, 1.73205), TOLERANCE)
- end
- end
-end
diff --git a/spec/ruby/library/mathn/float/exponent_spec.rb b/spec/ruby/library/mathn/float/exponent_spec.rb
deleted file mode 100644
index 312119db00..0000000000
--- a/spec/ruby/library/mathn/float/exponent_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require 'mathn'
-
- describe "Float#**" do
- it "returns self raised to other (positive) power" do
- (2.0 ** 4).should == 16.0
- (2.0 ** 1.2).should be_close(2.2973967, TOLERANCE)
- end
-
- it "returns a complex number when negative and raised to a fractional power" do
- ((-8.0) ** (1/3)).should be_close(Complex(1, 1.73205), TOLERANCE)
- ((-8.0) ** (1.0/3)).should be_close(Complex(1, 1.73205), TOLERANCE)
- end
- end
-end
diff --git a/spec/ruby/library/mathn/integer/from_prime_division_spec.rb b/spec/ruby/library/mathn/integer/from_prime_division_spec.rb
deleted file mode 100644
index df2db6d8c1..0000000000
--- a/spec/ruby/library/mathn/integer/from_prime_division_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require 'mathn'
-
- describe "Integer.from_prime_division" do
- it "reverses a prime factorization of an integer" do
- Integer.from_prime_division([[2, 1], [3, 2], [7, 1]]).should == 126
- end
- end
-end
diff --git a/spec/ruby/library/mathn/integer/prime_division_spec.rb b/spec/ruby/library/mathn/integer/prime_division_spec.rb
deleted file mode 100644
index fb4a1c3fea..0000000000
--- a/spec/ruby/library/mathn/integer/prime_division_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require 'mathn'
-
- describe "Integer#prime_division" do
- it "performs a prime factorization of a positive integer" do
- 100.prime_division.should == [[2, 2], [5, 2]]
- end
-
- # Proper handling of negative integers has been added to MRI trunk
- # in revision 24091. Prior to that, all versions of MRI returned nonsense.
- it "performs a prime factorization of a negative integer" do
- -26.prime_division.should == [[-1, 1], [2, 1], [13, 1]]
- end
-
- it "raises a ZeroDivisionError when is called on zero" do
- -> { 0.prime_division }.should raise_error(ZeroDivisionError)
- end
- end
-end
diff --git a/spec/ruby/library/mathn/math/fixtures/classes.rb b/spec/ruby/library/mathn/math/fixtures/classes.rb
deleted file mode 100644
index 024732fa7a..0000000000
--- a/spec/ruby/library/mathn/math/fixtures/classes.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-class IncludesMath
- include Math
-end
diff --git a/spec/ruby/library/mathn/math/rsqrt_spec.rb b/spec/ruby/library/mathn/math/rsqrt_spec.rb
deleted file mode 100644
index 6cb7595afe..0000000000
--- a/spec/ruby/library/mathn/math/rsqrt_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require_relative 'shared/rsqrt'
-
- describe "Math#rsqrt" do
- it_behaves_like :mathn_math_rsqrt, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:rsqrt)
- end
- end
-
- describe "Math.rsqrt" do
- it_behaves_like :mathn_math_rsqrt, :_, Math
- end
-end
diff --git a/spec/ruby/library/mathn/math/shared/rsqrt.rb b/spec/ruby/library/mathn/math/shared/rsqrt.rb
deleted file mode 100644
index ea3d1b0cfc..0000000000
--- a/spec/ruby/library/mathn/math/shared/rsqrt.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'mathn'
-require_relative '../fixtures/classes'
-
-describe :mathn_math_rsqrt, shared: true do
- it "returns the square root for Rational numbers" do
- @object.send(:rsqrt, Rational(9, 25)).should == Rational(3, 5)
- @object.send(:rsqrt, 16/64).should == Rational(1, 2)
- end
-
- it "returns the square root for positive numbers" do
- @object.send(:rsqrt, 1).should == 1
- @object.send(:rsqrt, 4.0).should == 2.0
- @object.send(:rsqrt, 12.34).should == Math.sqrt!(12.34)
- end
-
- it "raises an Math::DomainError if the argument is a negative number" do
- -> { @object.send(:rsqrt, -1) }.should raise_error(Math::DomainError)
- -> { @object.send(:rsqrt, -4.0) }.should raise_error(Math::DomainError)
- -> { @object.send(:rsqrt, -16/64) }.should raise_error(Math::DomainError)
- end
-end
diff --git a/spec/ruby/library/mathn/math/shared/sqrt.rb b/spec/ruby/library/mathn/math/shared/sqrt.rb
deleted file mode 100644
index 5e6dae1d4f..0000000000
--- a/spec/ruby/library/mathn/math/shared/sqrt.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-require 'mathn'
-require_relative '../fixtures/classes'
-
-describe :mathn_math_sqrt, shared: true do
- it "returns the square root for Rational numbers" do
- @object.send(:sqrt, Rational(9, 25)).should == Rational(3, 5)
- @object.send(:sqrt, 16/64).should == Rational(1, 2)
- end
-
- it "returns the square root for Complex numbers" do
- @object.send(:sqrt, Complex(1, 0)).should == 1
- end
-
- it "returns the square root for positive numbers" do
- @object.send(:sqrt, 1).should == 1
- @object.send(:sqrt, 4.0).should == 2.0
- @object.send(:sqrt, 12.34).should == Math.sqrt!(12.34)
- end
-
- it "returns the square root for negative numbers" do
- @object.send(:sqrt, -9).should == Complex(0, 3)
- @object.send(:sqrt, -5.29).should == Complex(0, 2.3)
- @object.send(:sqrt, -16/64).should == Complex(0, 1/2)
- end
-end
diff --git a/spec/ruby/library/mathn/math/sqrt_spec.rb b/spec/ruby/library/mathn/math/sqrt_spec.rb
deleted file mode 100644
index 49cfe3600e..0000000000
--- a/spec/ruby/library/mathn/math/sqrt_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require_relative 'shared/sqrt'
-
- describe "Math#rsqrt" do
- it_behaves_like :mathn_math_sqrt, :_, IncludesMath.new
-
- it "is a private instance method" do
- IncludesMath.should have_private_instance_method(:sqrt)
- end
- end
-
- describe "Math.rsqrt" do
- it_behaves_like :mathn_math_sqrt, :_, Math
- end
-end
diff --git a/spec/ruby/library/mathn/mathn_spec.rb b/spec/ruby/library/mathn/mathn_spec.rb
deleted file mode 100644
index 129c8f3288..0000000000
--- a/spec/ruby/library/mathn/mathn_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "mathn" do
- ruby_version_is "2.5" do
- it "is no longer part of the standard library" do
- -> {
- require "mathn"
- }.should raise_error(LoadError) { |e|
- e.path.should == 'mathn'
- }
- end
- end
-end
diff --git a/spec/ruby/library/mathn/rational/Rational_spec.rb b/spec/ruby/library/mathn/rational/Rational_spec.rb
deleted file mode 100644
index 9a34c99751..0000000000
--- a/spec/ruby/library/mathn/rational/Rational_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require 'mathn'
-
- describe "Kernel#Rational" do
- it "returns an Integer if denominator divides numerator evenly" do
- Rational(42,6).should == 7
- Rational(42,6).should be_kind_of(Fixnum)
- Rational(bignum_value,1).should == bignum_value
- Rational(bignum_value,1).should be_kind_of(Bignum)
- end
- end
-end
diff --git a/spec/ruby/library/mathn/rational/inspect_spec.rb b/spec/ruby/library/mathn/rational/inspect_spec.rb
deleted file mode 100644
index cbf67ec0f3..0000000000
--- a/spec/ruby/library/mathn/rational/inspect_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require_relative '../../../spec_helper'
-
-ruby_version_is ''...'2.5' do
- require 'mathn'
-
- describe "Rational#inspect" do
- it "returns a string representation of self" do
- Rational(3, 4).inspect.should == "(3/4)"
- Rational(-5, 8).inspect.should == "(-5/8)"
- Rational(-1, -2).inspect.should == "(1/2)"
- Rational(0, 2).inspect.should == "0"
- Rational(bignum_value, 1).inspect.should == "#{bignum_value}"
- end
- end
-end
diff --git a/spec/ruby/library/matrix/coerce_spec.rb b/spec/ruby/library/matrix/coerce_spec.rb
index 280243d372..4022f00236 100644
--- a/spec/ruby/library/matrix/coerce_spec.rb
+++ b/spec/ruby/library/matrix/coerce_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
require 'matrix'
describe "Matrix#coerce" do
- it "allows the division of fixnum by a Matrix " do
+ it "allows the division of integer by a Matrix " do
(1/Matrix[[0,1],[-1,0]]).should == Matrix[[0,-1],[1,0]]
end
end
diff --git a/spec/ruby/library/matrix/divide_spec.rb b/spec/ruby/library/matrix/divide_spec.rb
index 2e3bb85bf6..84cecff582 100644
--- a/spec/ruby/library/matrix/divide_spec.rb
+++ b/spec/ruby/library/matrix/divide_spec.rb
@@ -16,11 +16,11 @@ describe "Matrix#/" do
# Guard against the Mathn library
guard -> { !defined?(Math.rsqrt) } do
- it "returns the result of dividing self by a Fixnum" do
+ it "returns the result of dividing self by an Integer" do
(@a / 2).should == Matrix[ [0, 1], [1, 2] ]
end
- it "returns the result of dividing self by a Bignum" do
+ it "returns the result of dividing self by an Integer" do
(@a / bignum_value).should == Matrix[ [0, 0], [0, 0] ]
end
end
diff --git a/spec/ruby/library/matrix/hash_spec.rb b/spec/ruby/library/matrix/hash_spec.rb
index fac9a06527..7dabcd3737 100644
--- a/spec/ruby/library/matrix/hash_spec.rb
+++ b/spec/ruby/library/matrix/hash_spec.rb
@@ -3,8 +3,8 @@ require 'matrix'
describe "Matrix#hash" do
- it "returns a Fixnum" do
- Matrix[ [1,2] ].hash.should be_an_instance_of(Fixnum)
+ it "returns an Integer" do
+ Matrix[ [1,2] ].hash.should be_an_instance_of(Integer)
end
it "returns the same value for the same matrix" do
diff --git a/spec/ruby/library/matrix/multiply_spec.rb b/spec/ruby/library/matrix/multiply_spec.rb
index 585f268931..e488bb0f5d 100644
--- a/spec/ruby/library/matrix/multiply_spec.rb
+++ b/spec/ruby/library/matrix/multiply_spec.rb
@@ -16,11 +16,11 @@ describe "Matrix#*" do
(@a * Vector[1,2]).should == Vector[5, 11]
end
- it "returns the result of multiplying the elements of self and a Fixnum" do
+ it "returns the result of multiplying the elements of self and an Integer" do
(@a * 2).should == Matrix[ [2, 4], [6, 8] ]
end
- it "returns the result of multiplying the elements of self and a Bignum" do
+ it "returns the result of multiplying the elements of self and an Integer" do
(@a * bignum_value).should == Matrix[
[9223372036854775808, 18446744073709551616],
[27670116110564327424, 36893488147419103232]
diff --git a/spec/ruby/library/matrix/normal_spec.rb b/spec/ruby/library/matrix/normal_spec.rb
index ebd73aaf40..a9e6c645fa 100644
--- a/spec/ruby/library/matrix/normal_spec.rb
+++ b/spec/ruby/library/matrix/normal_spec.rb
@@ -3,12 +3,12 @@ require 'matrix'
describe "Matrix.normal?" do
# it "returns false for non normal matrices" do
- # Matrix[[0, 1], [1, 2]].normal?.should == false
+ # Matrix[[0, 1], [1, 2]].should_not.normal?
# end
it "returns true for normal matrices" do
- Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].normal?.should == true
- Matrix[[0, Complex(0, 2)], [Complex(0, -2), 0]].normal?.should == true
+ Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].should.normal?
+ Matrix[[0, Complex(0, 2)], [Complex(0, -2), 0]].should.normal?
end
it "raises an error for rectangular matrices" do
diff --git a/spec/ruby/library/matrix/orthogonal_spec.rb b/spec/ruby/library/matrix/orthogonal_spec.rb
index 07b098a58d..26afe89ff0 100644
--- a/spec/ruby/library/matrix/orthogonal_spec.rb
+++ b/spec/ruby/library/matrix/orthogonal_spec.rb
@@ -3,12 +3,12 @@ require 'matrix'
describe "Matrix.orthogonal?" do
it "returns false for non orthogonal matrices" do
- Matrix[[0, 1], [1, 2]].orthogonal?.should == false
- Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].orthogonal?.should == false
+ Matrix[[0, 1], [1, 2]].should_not.orthogonal?
+ Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].should_not.orthogonal?
end
it "returns true for orthogonal matrices" do
- Matrix[[0, 1], [1, 0]].orthogonal?.should == true
+ Matrix[[0, 1], [1, 0]].should.orthogonal?
end
it "raises an error for rectangular matrices" do
diff --git a/spec/ruby/library/matrix/unitary_spec.rb b/spec/ruby/library/matrix/unitary_spec.rb
index 9c2a106ea5..af4b2bb442 100644
--- a/spec/ruby/library/matrix/unitary_spec.rb
+++ b/spec/ruby/library/matrix/unitary_spec.rb
@@ -3,14 +3,19 @@ require 'matrix'
describe "Matrix.unitary?" do
it "returns false for non unitary matrices" do
- Matrix[[0, 1], [1, 2]].unitary?.should == false
- Matrix[[0, Complex(0, 2)], [Complex(0, 2), 0]].unitary?.should == false
- Matrix[[0, Complex(0, 1)], [Complex(0, -1), 0]].unitary?.should == false
- Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].unitary?.should == false
+ Matrix[[0, 1], [1, 2]].should_not.unitary?
+ Matrix[[0, Complex(0, 2)], [Complex(0, 2), 0]].should_not.unitary?
+ Matrix[[1, 1, 0], [0, 1, 1], [1, 0, 1]].should_not.unitary?
end
it "returns true for unitary matrices" do
- Matrix[[0, Complex(0, 1)], [Complex(0, 1), 0]].unitary?.should == true
+ Matrix[[0, Complex(0, 1)], [Complex(0, 1), 0]].should.unitary?
+ end
+
+ version_is((Matrix::const_defined?(:VERSION) ? Matrix::VERSION : "0.1.0"), "0.3.0") do
+ it "returns true for unitary matrices with a Complex and a negative #imag" do
+ Matrix[[0, Complex(0, 1)], [Complex(0, -1), 0]].should.unitary?
+ end
end
it "raises an error for rectangular matrices" do
diff --git a/spec/ruby/library/matrix/zero_spec.rb b/spec/ruby/library/matrix/zero_spec.rb
index 643c57acba..68e8567c26 100644
--- a/spec/ruby/library/matrix/zero_spec.rb
+++ b/spec/ruby/library/matrix/zero_spec.rb
@@ -37,16 +37,16 @@ end
describe "Matrix.zero?" do
it "returns true for empty matrices" do
- Matrix.empty.zero?.should == true
- Matrix.empty(3,0).zero?.should == true
- Matrix.empty(0,3).zero?.should == true
+ Matrix.empty.should.zero?
+ Matrix.empty(3,0).should.zero?
+ Matrix.empty(0,3).should.zero?
end
it "returns true for matrices with zero entries" do
- Matrix.zero(2,3).zero?.should == true
+ Matrix.zero(2,3).should.zero?
end
it "returns false for matrices with non zero entries" do
- Matrix[[1]].zero?.should == false
+ Matrix[[1]].should_not.zero?
end
end
diff --git a/spec/ruby/library/net/ftp/initialize_spec.rb b/spec/ruby/library/net/ftp/initialize_spec.rb
index 507320e494..a2f64ddb1b 100644
--- a/spec/ruby/library/net/ftp/initialize_spec.rb
+++ b/spec/ruby/library/net/ftp/initialize_spec.rb
@@ -6,9 +6,7 @@ describe "Net::FTP#initialize" do
@ftp = Net::FTP.allocate
@ftp.stub!(:connect)
@port_args = []
- ruby_version_is "2.5" do
- @port_args << 21
- end
+ @port_args << 21
end
it "is private" do
diff --git a/spec/ruby/library/net/http/HTTPServerException_spec.rb b/spec/ruby/library/net/http/HTTPServerException_spec.rb
index b8ac8cac76..87841ab499 100644
--- a/spec/ruby/library/net/http/HTTPServerException_spec.rb
+++ b/spec/ruby/library/net/http/HTTPServerException_spec.rb
@@ -13,7 +13,7 @@ ruby_version_is ""..."2.6" do
end
end
-ruby_version_is "2.6"..."2.7" do
+ruby_version_is "2.6" do
describe "Net::HTTPServerException" do
it "is a subclass of Net::ProtoServerError and is warned as deprecated" do
-> { Net::HTTPServerException.should < Net::ProtoServerError }.should complain(/warning: constant Net::HTTPServerException is deprecated/)
diff --git a/spec/ruby/library/net/http/http/fixtures/http_server.rb b/spec/ruby/library/net/http/http/fixtures/http_server.rb
index 49e8f437cc..aeb0babda1 100644
--- a/spec/ruby/library/net/http/http/fixtures/http_server.rb
+++ b/spec/ruby/library/net/http/http/fixtures/http_server.rb
@@ -53,10 +53,10 @@ module NetHTTPSpecs
end
end
- class << self
- @server = nil
- @server_thread = nil
+ @server = nil
+ @server_thread = nil
+ class << self
def port
raise "server not started" unless @server
@server.config[:Port]
@@ -89,8 +89,12 @@ module NetHTTPSpecs
if @server
begin
@server.shutdown
- rescue Errno::EPIPE
+ rescue Errno::EPIPE, Errno::EBADF
# Because WEBrick is not thread-safe and only catches IOError
+
+ # EBADF can happen because WEBrick @server_thread concurrently closes the shutdown pipe
+ # once @status = :Shutdown, while the current thread does write_nonblock("\0").
+ # On MRI this EBADF is replaced by IOError due to the GIL around both #close and #write_nonblock.
end
@server = nil
end
diff --git a/spec/ruby/library/net/http/http/get2_spec.rb b/spec/ruby/library/net/http/http/get2_spec.rb
index 71dfc3d39b..519e4c2599 100644
--- a/spec/ruby/library/net/http/http/get2_spec.rb
+++ b/spec/ruby/library/net/http/http/get2_spec.rb
@@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_get'
describe "Net::HTTP#get2" do
- it_behaves_like :net_ftp_request_get, :get2
+ it_behaves_like :net_http_request_get, :get2
end
diff --git a/spec/ruby/library/net/http/http/get_spec.rb b/spec/ruby/library/net/http/http/get_spec.rb
index e6cd50fa27..0948006fca 100644
--- a/spec/ruby/library/net/http/http/get_spec.rb
+++ b/spec/ruby/library/net/http/http/get_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../../../spec_helper'
require 'net/http'
require_relative 'fixtures/http_server'
-describe "Net::HTTP.get when passed URI" do
+describe "Net::HTTP.get" do
before :each do
NetHTTPSpecs.start_server
@port = NetHTTPSpecs.port
@@ -61,15 +61,16 @@ describe "Net::HTTP.get" do
Thread.current.report_on_exception = false
Net::HTTP.get("127.0.0.1", '/', server.connect_address.ip_port)
end
+
+ socket = server_thread.value
Thread.pass until client_thread.stop?
- [server_thread, client_thread]
+ [socket, client_thread]
end
it "propagates exceptions interrupting the thread and does not replace it with Zlib::BufError" do
my_exception = Class.new(RuntimeError)
- server_thread, client_thread = start_threads
- socket = server_thread.value
+ socket, client_thread = start_threads
begin
client_thread.raise my_exception, "my exception"
-> { client_thread.value }.should raise_error(my_exception)
@@ -78,10 +79,9 @@ describe "Net::HTTP.get" do
end
end
- ruby_version_is "2.8" do # https://bugs.ruby-lang.org/issues/13882#note-6
+ ruby_version_is "3.0" do # https://bugs.ruby-lang.org/issues/13882#note-6
it "lets the kill Thread exception goes through and does not replace it with Zlib::BufError" do
- server_thread, client_thread = start_threads
- socket = server_thread.value
+ socket, client_thread = start_threads
begin
client_thread.kill
client_thread.value.should == nil
diff --git a/spec/ruby/library/net/http/http/head2_spec.rb b/spec/ruby/library/net/http/http/head2_spec.rb
index 606798e4af..6958204ee1 100644
--- a/spec/ruby/library/net/http/http/head2_spec.rb
+++ b/spec/ruby/library/net/http/http/head2_spec.rb
@@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_head'
describe "Net::HTTP#head2" do
- it_behaves_like :net_ftp_request_head, :head2
+ it_behaves_like :net_http_request_head, :head2
end
diff --git a/spec/ruby/library/net/http/http/post2_spec.rb b/spec/ruby/library/net/http/http/post2_spec.rb
index eab9a6a1d2..ccc95068fb 100644
--- a/spec/ruby/library/net/http/http/post2_spec.rb
+++ b/spec/ruby/library/net/http/http/post2_spec.rb
@@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_post'
describe "Net::HTTP#post2" do
- it_behaves_like :net_ftp_request_post, :post2
+ it_behaves_like :net_http_request_post, :post2
end
diff --git a/spec/ruby/library/net/http/http/put2_spec.rb b/spec/ruby/library/net/http/http/put2_spec.rb
index 0ee3590639..99329a5fd9 100644
--- a/spec/ruby/library/net/http/http/put2_spec.rb
+++ b/spec/ruby/library/net/http/http/put2_spec.rb
@@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_put'
describe "Net::HTTP#put2" do
- it_behaves_like :net_ftp_request_put, :put2
+ it_behaves_like :net_http_request_put, :put2
end
diff --git a/spec/ruby/library/net/http/http/request_get_spec.rb b/spec/ruby/library/net/http/http/request_get_spec.rb
index f53a2e9d65..9932ef0beb 100644
--- a/spec/ruby/library/net/http/http/request_get_spec.rb
+++ b/spec/ruby/library/net/http/http/request_get_spec.rb
@@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_get'
describe "Net::HTTP#request_get" do
- it_behaves_like :net_ftp_request_get, :get2
+ it_behaves_like :net_http_request_get, :get2
end
diff --git a/spec/ruby/library/net/http/http/request_head_spec.rb b/spec/ruby/library/net/http/http/request_head_spec.rb
index dc47557b9d..788101c951 100644
--- a/spec/ruby/library/net/http/http/request_head_spec.rb
+++ b/spec/ruby/library/net/http/http/request_head_spec.rb
@@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_head'
describe "Net::HTTP#request_head" do
- it_behaves_like :net_ftp_request_head, :request_head
+ it_behaves_like :net_http_request_head, :request_head
end
diff --git a/spec/ruby/library/net/http/http/request_post_spec.rb b/spec/ruby/library/net/http/http/request_post_spec.rb
index 0b408fa84d..7ac67cf95d 100644
--- a/spec/ruby/library/net/http/http/request_post_spec.rb
+++ b/spec/ruby/library/net/http/http/request_post_spec.rb
@@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_post'
describe "Net::HTTP#request_post" do
- it_behaves_like :net_ftp_request_post, :request_post
+ it_behaves_like :net_http_request_post, :request_post
end
diff --git a/spec/ruby/library/net/http/http/request_put_spec.rb b/spec/ruby/library/net/http/http/request_put_spec.rb
index 987b52ceb0..110ac43ca6 100644
--- a/spec/ruby/library/net/http/http/request_put_spec.rb
+++ b/spec/ruby/library/net/http/http/request_put_spec.rb
@@ -4,5 +4,5 @@ require_relative 'fixtures/http_server'
require_relative 'shared/request_put'
describe "Net::HTTP#request_put" do
- it_behaves_like :net_ftp_request_put, :request_put
+ it_behaves_like :net_http_request_put, :request_put
end
diff --git a/spec/ruby/library/net/http/http/send_request_spec.rb b/spec/ruby/library/net/http/http/send_request_spec.rb
index 03fd32e470..47b3eef5b9 100644
--- a/spec/ruby/library/net/http/http/send_request_spec.rb
+++ b/spec/ruby/library/net/http/http/send_request_spec.rb
@@ -26,7 +26,7 @@ describe "Net::HTTP#send_request" do
response = @http.send_request("HEAD", "/request")
response.body.should be_nil
- @methods.each do |method|
+ (@methods - %w[POST PUT]).each do |method|
response = @http.send_request(method, "/request")
response.body.should == "Request type: #{method}"
end
diff --git a/spec/ruby/library/net/http/http/shared/request_get.rb b/spec/ruby/library/net/http/http/shared/request_get.rb
index b0eca665d6..d25f32049b 100644
--- a/spec/ruby/library/net/http/http/shared/request_get.rb
+++ b/spec/ruby/library/net/http/http/shared/request_get.rb
@@ -1,4 +1,4 @@
-describe :net_ftp_request_get, shared: true do
+describe :net_http_request_get, shared: true do
before :each do
NetHTTPSpecs.start_server
@http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
diff --git a/spec/ruby/library/net/http/http/shared/request_head.rb b/spec/ruby/library/net/http/http/shared/request_head.rb
index 0e669de9ac..78b555884b 100644
--- a/spec/ruby/library/net/http/http/shared/request_head.rb
+++ b/spec/ruby/library/net/http/http/shared/request_head.rb
@@ -1,4 +1,4 @@
-describe :net_ftp_request_head, shared: true do
+describe :net_http_request_head, shared: true do
before :each do
NetHTTPSpecs.start_server
@http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
diff --git a/spec/ruby/library/net/http/http/shared/request_post.rb b/spec/ruby/library/net/http/http/shared/request_post.rb
index 06c5e139f9..e832411c48 100644
--- a/spec/ruby/library/net/http/http/shared/request_post.rb
+++ b/spec/ruby/library/net/http/http/shared/request_post.rb
@@ -1,4 +1,4 @@
-describe :net_ftp_request_post, shared: true do
+describe :net_http_request_post, shared: true do
before :each do
NetHTTPSpecs.start_server
@http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
diff --git a/spec/ruby/library/net/http/http/shared/request_put.rb b/spec/ruby/library/net/http/http/shared/request_put.rb
index 6ae791d7e7..3b902f4957 100644
--- a/spec/ruby/library/net/http/http/shared/request_put.rb
+++ b/spec/ruby/library/net/http/http/shared/request_put.rb
@@ -1,4 +1,4 @@
-describe :net_ftp_request_put, shared: true do
+describe :net_http_request_put, shared: true do
before :each do
NetHTTPSpecs.start_server
@http = Net::HTTP.start("localhost", NetHTTPSpecs.port)
diff --git a/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb b/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb
index 68a0454f79..8ade46689f 100644
--- a/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb
+++ b/spec/ruby/library/net/http/httpresponse/body_permitted_spec.rb
@@ -3,11 +3,11 @@ require 'net/http'
describe "Net::HTTPResponse.body_permitted?" do
it "returns true if this response type can have a response body" do
- Net::HTTPUnknownResponse.body_permitted?.should == true
- Net::HTTPInformation.body_permitted?.should == false
- Net::HTTPSuccess.body_permitted?.should == true
- Net::HTTPRedirection.body_permitted?.should == true
- Net::HTTPClientError.body_permitted?.should == true
- Net::HTTPServerError.body_permitted?.should == true
+ Net::HTTPUnknownResponse.should.body_permitted?
+ Net::HTTPInformation.should_not.body_permitted?
+ Net::HTTPSuccess.should.body_permitted?
+ Net::HTTPRedirection.should.body_permitted?
+ Net::HTTPClientError.should.body_permitted?
+ Net::HTTPServerError.should.body_permitted?
end
end
diff --git a/spec/ruby/library/objectspace/memsize_of_spec.rb b/spec/ruby/library/objectspace/memsize_of_spec.rb
index 06a80d9f9c..36d845824d 100644
--- a/spec/ruby/library/objectspace/memsize_of_spec.rb
+++ b/spec/ruby/library/objectspace/memsize_of_spec.rb
@@ -12,6 +12,10 @@ describe "ObjectSpace.memsize_of" do
ObjectSpace.memsize_of(42).should == 0
end
+ it "returns 0 for literal Symbols" do
+ ObjectSpace.memsize_of(:abc).should == 0
+ end
+
it "returns an Integer for an Object" do
obj = Object.new
ObjectSpace.memsize_of(obj).should be_kind_of(Integer)
diff --git a/spec/ruby/library/openssl/config/freeze_spec.rb b/spec/ruby/library/openssl/config/freeze_spec.rb
index 1876095d9f..c814341b86 100644
--- a/spec/ruby/library/openssl/config/freeze_spec.rb
+++ b/spec/ruby/library/openssl/config/freeze_spec.rb
@@ -3,18 +3,20 @@ require_relative '../shared/constants'
require 'openssl'
-describe "OpenSSL::Config#freeze" do
- it "needs to be reviewed for completeness"
+version_is(OpenSSL::VERSION, ""..."2.2") do
+ describe "OpenSSL::Config#freeze" do
+ it "needs to be reviewed for completeness"
- it "freezes" do
- c = OpenSSL::Config.new
- -> {
- c['foo'] = [ ['key', 'value'] ]
- }.should_not raise_error
- c.freeze
- c.frozen?.should be_true
- -> {
- c['foo'] = [ ['key', 'value'] ]
- }.should raise_error(TypeError)
+ it "freezes" do
+ c = OpenSSL::Config.new
+ -> {
+ c['foo'] = [ ['key', 'value'] ]
+ }.should_not raise_error
+ c.freeze
+ c.frozen?.should be_true
+ -> {
+ c['foo'] = [ ['key', 'value'] ]
+ }.should raise_error(TypeError)
+ end
end
end
diff --git a/spec/ruby/library/openssl/digest_spec.rb b/spec/ruby/library/openssl/digest_spec.rb
new file mode 100644
index 0000000000..b8e82d073f
--- /dev/null
+++ b/spec/ruby/library/openssl/digest_spec.rb
@@ -0,0 +1,63 @@
+require_relative '../../spec_helper'
+require_relative '../../library/digest/sha1/shared/constants'
+require_relative '../../library/digest/sha256/shared/constants'
+require_relative '../../library/digest/sha384/shared/constants'
+require_relative '../../library/digest/sha512/shared/constants'
+require 'openssl'
+
+describe "OpenSSL::Digest" do
+
+ describe ".digest" do
+ it "returns a SHA1 digest" do
+ OpenSSL::Digest.digest('sha1', SHA1Constants::Contents).should == SHA1Constants::Digest
+ end
+
+ it "returns a SHA256 digest" do
+ OpenSSL::Digest.digest('sha256', SHA256Constants::Contents).should == SHA256Constants::Digest
+ end
+
+ it "returns a SHA384 digest" do
+ OpenSSL::Digest.digest('sha384', SHA384Constants::Contents).should == SHA384Constants::Digest
+ end
+
+ it "returns a SHA512 digest" do
+ OpenSSL::Digest.digest('sha512', SHA512Constants::Contents).should == SHA512Constants::Digest
+ end
+ end
+
+ describe ".hexdigest" do
+ it "returns a SHA1 hexdigest" do
+ OpenSSL::Digest.hexdigest('sha1', SHA1Constants::Contents).should == SHA1Constants::Hexdigest
+ end
+
+ it "returns a SHA256 hexdigest" do
+ OpenSSL::Digest.hexdigest('sha256', SHA256Constants::Contents).should == SHA256Constants::Hexdigest
+ end
+
+ it "returns a SHA384 hexdigest" do
+ OpenSSL::Digest.hexdigest('sha384', SHA384Constants::Contents).should == SHA384Constants::Hexdigest
+ end
+
+ it "returns a SHA512 hexdigest" do
+ OpenSSL::Digest.hexdigest('sha512', SHA512Constants::Contents).should == SHA512Constants::Hexdigest
+ end
+ end
+
+ describe ".base64digest" do
+ it "returns a SHA1 base64digest" do
+ OpenSSL::Digest.base64digest('sha1', SHA1Constants::Contents).should == SHA1Constants::Base64digest
+ end
+
+ it "returns a SHA256 base64digest" do
+ OpenSSL::Digest.base64digest('sha256', SHA256Constants::Contents).should == SHA256Constants::Base64digest
+ end
+
+ it "returns a SHA384 base64digest" do
+ OpenSSL::Digest.base64digest('sha384', SHA384Constants::Contents).should == SHA384Constants::Base64digest
+ end
+
+ it "returns a SHA512 base64digest" do
+ OpenSSL::Digest.base64digest('sha512', SHA512Constants::Contents).should == SHA512Constants::Base64digest
+ end
+ end
+end
diff --git a/spec/ruby/library/openssl/hmac/digest_spec.rb b/spec/ruby/library/openssl/hmac/digest_spec.rb
index 22bc7023bc..03ed136e64 100644
--- a/spec/ruby/library/openssl/hmac/digest_spec.rb
+++ b/spec/ruby/library/openssl/hmac/digest_spec.rb
@@ -4,7 +4,7 @@ require 'openssl'
describe "OpenSSL::HMAC.digest" do
it "returns an SHA1 digest" do
- cur_digest = OpenSSL::Digest::SHA1.new
+ cur_digest = OpenSSL::Digest.new("SHA1")
cur_digest.digest.should == HMACConstants::BlankSHA1Digest
digest = OpenSSL::HMAC.digest(cur_digest,
HMACConstants::Key,
diff --git a/spec/ruby/library/openssl/hmac/hexdigest_spec.rb b/spec/ruby/library/openssl/hmac/hexdigest_spec.rb
index 7f73b2db09..3508c1bbd7 100644
--- a/spec/ruby/library/openssl/hmac/hexdigest_spec.rb
+++ b/spec/ruby/library/openssl/hmac/hexdigest_spec.rb
@@ -4,7 +4,7 @@ require 'openssl'
describe "OpenSSL::HMAC.hexdigest" do
it "returns an SHA1 hex digest" do
- cur_digest = OpenSSL::Digest::SHA1.new
+ cur_digest = OpenSSL::Digest.new("SHA1")
cur_digest.hexdigest.should == HMACConstants::BlankSHA1HexDigest
hexdigest = OpenSSL::HMAC.hexdigest(cur_digest,
HMACConstants::Key,
diff --git a/spec/ruby/library/openstruct/frozen_spec.rb b/spec/ruby/library/openstruct/frozen_spec.rb
index 63767bb54d..c14a4bac55 100644
--- a/spec/ruby/library/openstruct/frozen_spec.rb
+++ b/spec/ruby/library/openstruct/frozen_spec.rb
@@ -24,6 +24,7 @@ describe "OpenStruct.new when frozen" do
it "creates a frozen clone" do
f = @os.clone
+ f.frozen?.should == true
f.age.should == 70
->{ f.age = 0 }.should raise_error( RuntimeError )
->{ f.state = :newer }.should raise_error( RuntimeError )
@@ -31,6 +32,7 @@ describe "OpenStruct.new when frozen" do
it "creates an unfrozen dup" do
d = @os.dup
+ d.frozen?.should == false
d.age.should == 70
d.age = 42
d.age.should == 42
diff --git a/spec/ruby/library/openstruct/marshal_load_spec.rb b/spec/ruby/library/openstruct/marshal_load_spec.rb
index e07c4cef05..342e5e68cd 100644
--- a/spec/ruby/library/openstruct/marshal_load_spec.rb
+++ b/spec/ruby/library/openstruct/marshal_load_spec.rb
@@ -4,7 +4,7 @@ require "ostruct"
describe "OpenStruct#marshal_load when passed [Hash]" do
it "defines methods based on the passed Hash" do
os = OpenStruct.new
- os.marshal_load(age: 20, name: "John")
+ os.send :marshal_load, age: 20, name: "John"
os.age.should eql(20)
os.name.should == "John"
diff --git a/spec/ruby/library/openstruct/method_missing_spec.rb b/spec/ruby/library/openstruct/method_missing_spec.rb
index 1992b7255c..212db015a9 100644
--- a/spec/ruby/library/openstruct/method_missing_spec.rb
+++ b/spec/ruby/library/openstruct/method_missing_spec.rb
@@ -7,43 +7,20 @@ describe "OpenStruct#method_missing when called with a method name ending in '='
end
it "raises an ArgumentError when not passed any additional arguments" do
- -> { @os.method_missing(:test=) }.should raise_error(ArgumentError)
- end
-
- it "raises a TypeError when self is frozen" do
- @os.freeze
- -> { @os.method_missing(:test=, "test") }.should raise_error(RuntimeError)
- end
-
- it "creates accessor methods" do
- @os.method_missing(:test=, "test")
- @os.respond_to?(:test=).should be_true
- @os.respond_to?(:test).should be_true
-
- @os.test.should == "test"
- @os.test = "changed"
- @os.test.should == "changed"
+ -> { @os.send(:test=) }.should raise_error(ArgumentError)
end
end
describe "OpenStruct#method_missing when passed additional arguments" do
it "raises a NoMethodError when the key does not exist" do
os = OpenStruct.new
- -> { os.method_missing(:test, 1, 2, 3) }.should raise_error(NoMethodError)
+ -> { os.test(1, 2, 3) }.should raise_error(NoMethodError)
end
ruby_version_is "2.7" do
it "raises an ArgumentError when the key exists" do
os = OpenStruct.new(test: 20)
- -> { os.method_missing(:test, 1, 2, 3) }.should raise_error(ArgumentError)
+ -> { os.test(1, 2, 3) }.should raise_error(ArgumentError)
end
end
end
-
-describe "OpenStruct#method_missing when not passed any additional arguments" do
- it "returns the value for the passed method from the method/value table" do
- os = OpenStruct.new(age: 20)
- os.method_missing(:age).should eql(20)
- os.method_missing(:name).should be_nil
- end
-end
diff --git a/spec/ruby/library/pathname/absolute_spec.rb b/spec/ruby/library/pathname/absolute_spec.rb
index dce3ae72ee..109abb8ee9 100644
--- a/spec/ruby/library/pathname/absolute_spec.rb
+++ b/spec/ruby/library/pathname/absolute_spec.rb
@@ -4,19 +4,19 @@ require 'pathname'
describe "Pathname#absolute?" do
it "returns true for the root directory" do
- Pathname.new('/').absolute?.should == true
+ Pathname.new('/').should.absolute?
end
it "returns true for a dir starting with a slash" do
- Pathname.new('/usr/local/bin').absolute?.should == true
+ Pathname.new('/usr/local/bin').should.absolute?
end
it "returns false for a dir not starting with a slash" do
- Pathname.new('fish').absolute?.should == false
+ Pathname.new('fish').should_not.absolute?
end
it "returns false for a dir not starting with a slash" do
- Pathname.new('fish/dog/cow').absolute?.should == false
+ Pathname.new('fish/dog/cow').should_not.absolute?
end
end
diff --git a/spec/ruby/library/pathname/glob_spec.rb b/spec/ruby/library/pathname/glob_spec.rb
new file mode 100644
index 0000000000..f6dfd6cd58
--- /dev/null
+++ b/spec/ruby/library/pathname/glob_spec.rb
@@ -0,0 +1,57 @@
+require_relative '../../spec_helper'
+require 'pathname'
+
+describe 'Pathname.glob' do
+ before :all do
+ @dir = tmp('pathname_glob') + '/'
+ @file_1 = @dir + 'lib/ipaddr.rb'
+ @file_2 = @dir + 'lib/irb.rb'
+ @file_3 = @dir + 'lib/.hidden.rb'
+
+ touch @file_1
+ touch @file_2
+ touch @file_3
+ end
+
+ after :all do
+ rm_r @dir[0...-1]
+ end
+
+ it 'returns [] for no match' do
+ Pathname.glob(@dir + 'lib/*.js').should == []
+ end
+
+ it 'returns matching file paths' do
+ Pathname.glob(@dir + 'lib/*i*.rb').sort.should == [Pathname.new(@file_1), Pathname.new(@file_2)].sort
+ end
+
+ it 'returns matching file paths when a flag is provided' do
+ expected = [Pathname.new(@file_1), Pathname.new(@file_2), Pathname.new(@file_3)].sort
+ Pathname.glob(@dir + 'lib/*i*.rb', File::FNM_DOTMATCH).sort.should == expected
+ end
+
+ it 'returns matching file paths when supplied :base keyword argument' do
+ Pathname.glob('*i*.rb', base: @dir + 'lib').sort.should == [Pathname.new('ipaddr.rb'), Pathname.new('irb.rb')].sort
+ end
+
+ it "raises an ArgumentError when supplied a keyword argument other than :base" do
+ -> {
+ Pathname.glob('*i*.rb', foo: @dir + 'lib')
+ }.should raise_error(ArgumentError, /unknown keyword: :?foo/)
+ end
+
+ ruby_version_is ''...'2.7' do
+ it 'raises an ArgumentError when supplied a flag and :base keyword argument' do
+ -> {
+ Pathname.glob(@dir + 'lib/*i*.rb', File::FNM_DOTMATCH, base: 'lib')
+ }.should raise_error(ArgumentError, 'wrong number of arguments (given 3, expected 1..2)')
+ end
+ end
+
+ ruby_version_is "2.7" do
+ it "does not raise an ArgumentError when supplied a flag and :base keyword argument" do
+ expected = [Pathname.new('ipaddr.rb'), Pathname.new('irb.rb'), Pathname.new('.hidden.rb')].sort
+ Pathname.glob('*i*.rb', File::FNM_DOTMATCH, base: @dir + 'lib').sort.should == expected
+ end
+ end
+end
diff --git a/spec/ruby/library/pathname/new_spec.rb b/spec/ruby/library/pathname/new_spec.rb
index dcb770149f..760fd8638f 100644
--- a/spec/ruby/library/pathname/new_spec.rb
+++ b/spec/ruby/library/pathname/new_spec.rb
@@ -13,7 +13,7 @@ describe "Pathname.new" do
ruby_version_is ''...'2.7' do
it "is tainted if path is tainted" do
path = '/usr/local/bin'.taint
- Pathname.new(path).tainted?.should == true
+ Pathname.new(path).should.tainted?
end
end
diff --git a/spec/ruby/library/pathname/pathname_spec.rb b/spec/ruby/library/pathname/pathname_spec.rb
new file mode 100644
index 0000000000..7d63fe86e3
--- /dev/null
+++ b/spec/ruby/library/pathname/pathname_spec.rb
@@ -0,0 +1,30 @@
+require_relative '../../spec_helper'
+require 'pathname'
+
+describe "Kernel#Pathname" do
+ it "is a private instance method" do
+ Kernel.should have_private_instance_method(:Pathname)
+ end
+
+ it "is also a public method" do
+ Kernel.should have_method(:Pathname)
+ end
+
+ ruby_version_is ''...'2.7' do
+ it "returns a new pathname when called with a pathname argument" do
+ path = Pathname('foo')
+ new_path = Pathname(path)
+
+ path.should_not.equal?(new_path)
+ end
+ end
+
+ ruby_version_is '2.7' do
+ it "returns same argument when called with a pathname argument" do
+ path = Pathname('foo')
+ new_path = Pathname(path)
+
+ path.should.equal?(new_path)
+ end
+ end
+end
diff --git a/spec/ruby/library/pathname/relative_spec.rb b/spec/ruby/library/pathname/relative_spec.rb
index 1a08891e6c..0fab9a7b9f 100644
--- a/spec/ruby/library/pathname/relative_spec.rb
+++ b/spec/ruby/library/pathname/relative_spec.rb
@@ -4,19 +4,19 @@ require 'pathname'
describe "Pathname#relative?" do
it "returns false for the root directory" do
- Pathname.new('/').relative?.should == false
+ Pathname.new('/').should_not.relative?
end
it "returns false for a dir starting with a slash" do
- Pathname.new('/usr/local/bin').relative?.should == false
+ Pathname.new('/usr/local/bin').should_not.relative?
end
it "returns true for a dir not starting with a slash" do
- Pathname.new('fish').relative?.should == true
+ Pathname.new('fish').should.relative?
end
it "returns true for a dir not starting with a slash" do
- Pathname.new('fish/dog/cow').relative?.should == true
+ Pathname.new('fish/dog/cow').should.relative?
end
end
diff --git a/spec/ruby/library/pathname/root_spec.rb b/spec/ruby/library/pathname/root_spec.rb
index 5fec0ee956..cd2be24516 100644
--- a/spec/ruby/library/pathname/root_spec.rb
+++ b/spec/ruby/library/pathname/root_spec.rb
@@ -4,23 +4,23 @@ require 'pathname'
describe "Pathname#root?" do
it "returns true for root directories" do
- Pathname.new('/').root?.should == true
+ Pathname.new('/').should.root?
end
it "returns false for empty string" do
- Pathname.new('').root?.should == false
+ Pathname.new('').should_not.root?
end
it "returns false for a top level directory" do
- Pathname.new('/usr').root?.should == false
+ Pathname.new('/usr').should_not.root?
end
it "returns false for a top level with .. appended directory" do
- Pathname.new('/usr/..').root?.should == false
+ Pathname.new('/usr/..').should_not.root?
end
it "returns false for a directory below top level" do
- Pathname.new('/usr/local/bin/').root?.should == false
+ Pathname.new('/usr/local/bin/').should_not.root?
end
end
diff --git a/spec/ruby/library/rbconfig/rbconfig_spec.rb b/spec/ruby/library/rbconfig/rbconfig_spec.rb
index 35b465d106..b3b8f32edb 100644
--- a/spec/ruby/library/rbconfig/rbconfig_spec.rb
+++ b/spec/ruby/library/rbconfig/rbconfig_spec.rb
@@ -35,6 +35,42 @@ describe 'RbConfig::CONFIG' do
puts 'Done'
RUBY
end
+
+ guard -> {RbConfig::TOPDIR} do
+ it "libdir/LIBRUBY_SO is the path to libruby and it exists if and only if ENABLE_SHARED" do
+ libdirname = RbConfig::CONFIG['LIBPATHENV'] == 'PATH' ? 'bindir' :
+ RbConfig::CONFIG['libdirname']
+ libdir = RbConfig::CONFIG[libdirname]
+ libruby_so = "#{libdir}/#{RbConfig::CONFIG['LIBRUBY_SO']}"
+ case RbConfig::CONFIG['ENABLE_SHARED']
+ when 'yes'
+ File.should.exist?(libruby_so)
+ when 'no'
+ File.should_not.exist?(libruby_so)
+ end
+ end
+ end
+
+ platform_is :linux do
+ it "['AR'] exists and can be executed" do
+ ar = RbConfig::CONFIG.fetch('AR')
+ out = `#{ar} --version`
+ $?.should.success?
+ out.should_not be_empty
+ end
+
+ it "['STRIP'] exists and can be executed" do
+ strip = RbConfig::CONFIG.fetch('STRIP')
+ copy = tmp("sh")
+ cp '/bin/sh', copy
+ begin
+ out = `#{strip} #{copy}`
+ $?.should.success?
+ ensure
+ rm_r copy
+ end
+ end
+ end
end
describe "RbConfig::TOPDIR" do
diff --git a/spec/ruby/library/rbconfig/sizeof/limits_spec.rb b/spec/ruby/library/rbconfig/sizeof/limits_spec.rb
index a026135eee..776099da27 100644
--- a/spec/ruby/library/rbconfig/sizeof/limits_spec.rb
+++ b/spec/ruby/library/rbconfig/sizeof/limits_spec.rb
@@ -1,42 +1,40 @@
require_relative '../../../spec_helper'
require 'rbconfig/sizeof'
-ruby_version_is "2.5" do
- describe "RbConfig::LIMITS" do
- it "is a Hash" do
- RbConfig::LIMITS.should be_kind_of(Hash)
- end
+describe "RbConfig::LIMITS" do
+ it "is a Hash" do
+ RbConfig::LIMITS.should be_kind_of(Hash)
+ end
- it "has string keys and numeric values" do
- RbConfig::LIMITS.each do |key, value|
- key.should be_kind_of String
- value.should be_kind_of Numeric
- end
+ it "has string keys and numeric values" do
+ RbConfig::LIMITS.each do |key, value|
+ key.should be_kind_of String
+ value.should be_kind_of Numeric
end
+ end
- it "contains FIXNUM_MIN and FIXNUM_MAX" do
- RbConfig::LIMITS["FIXNUM_MIN"].should < 0
- RbConfig::LIMITS["FIXNUM_MAX"].should > 0
- end
+ it "contains FIXNUM_MIN and FIXNUM_MAX" do
+ RbConfig::LIMITS["FIXNUM_MIN"].should < 0
+ RbConfig::LIMITS["FIXNUM_MAX"].should > 0
+ end
- it "contains CHAR_MIN and CHAR_MAX" do
- RbConfig::LIMITS["CHAR_MIN"].should <= 0
- RbConfig::LIMITS["CHAR_MAX"].should > 0
- end
+ it "contains CHAR_MIN and CHAR_MAX" do
+ RbConfig::LIMITS["CHAR_MIN"].should <= 0
+ RbConfig::LIMITS["CHAR_MAX"].should > 0
+ end
- it "contains SHRT_MIN and SHRT_MAX" do
- RbConfig::LIMITS["SHRT_MIN"].should == -32768
- RbConfig::LIMITS["SHRT_MAX"].should == 32767
- end
+ it "contains SHRT_MIN and SHRT_MAX" do
+ RbConfig::LIMITS["SHRT_MIN"].should == -32768
+ RbConfig::LIMITS["SHRT_MAX"].should == 32767
+ end
- it "contains INT_MIN and INT_MAX" do
- RbConfig::LIMITS["INT_MIN"].should < 0
- RbConfig::LIMITS["INT_MAX"].should > 0
- end
+ it "contains INT_MIN and INT_MAX" do
+ RbConfig::LIMITS["INT_MIN"].should < 0
+ RbConfig::LIMITS["INT_MAX"].should > 0
+ end
- it "contains LONG_MIN and LONG_MAX" do
- RbConfig::LIMITS["LONG_MIN"].should < 0
- RbConfig::LIMITS["LONG_MAX"].should > 0
- end
+ it "contains LONG_MIN and LONG_MAX" do
+ RbConfig::LIMITS["LONG_MIN"].should < 0
+ RbConfig::LIMITS["LONG_MAX"].should > 0
end
end
diff --git a/spec/ruby/library/rbconfig/unicode_version_spec.rb b/spec/ruby/library/rbconfig/unicode_version_spec.rb
index 44216700c8..65bd70c242 100644
--- a/spec/ruby/library/rbconfig/unicode_version_spec.rb
+++ b/spec/ruby/library/rbconfig/unicode_version_spec.rb
@@ -2,12 +2,6 @@ require_relative '../../spec_helper'
require 'rbconfig'
describe "RbConfig::CONFIG['UNICODE_VERSION']" do
- ruby_version_is ""..."2.5" do
- it "is 9.0.0 for Ruby 2.4" do
- RbConfig::CONFIG['UNICODE_VERSION'].should == "9.0.0"
- end
- end
-
ruby_version_is "2.5"..."2.6" do
it "is 10.0.0 for Ruby 2.5" do
RbConfig::CONFIG['UNICODE_VERSION'].should == "10.0.0"
diff --git a/spec/ruby/library/rexml/attribute/clone_spec.rb b/spec/ruby/library/rexml/attribute/clone_spec.rb
index 9a4a4079e1..5c86468d45 100644
--- a/spec/ruby/library/rexml/attribute/clone_spec.rb
+++ b/spec/ruby/library/rexml/attribute/clone_spec.rb
@@ -1,11 +1,14 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#clone" do
- it "returns a copy of this Attribute" do
- orig = REXML::Attribute.new("name", "value&&")
- orig.should == orig.clone
- orig.clone.to_s.should == orig.to_s
- orig.clone.to_string.should == orig.to_string
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Attribute#clone" do
+ it "returns a copy of this Attribute" do
+ orig = REXML::Attribute.new("name", "value&&")
+ orig.should == orig.clone
+ orig.clone.to_s.should == orig.to_s
+ orig.clone.to_string.should == orig.to_string
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/element_spec.rb b/spec/ruby/library/rexml/attribute/element_spec.rb
index 832e7e9a41..0e4ce46a4f 100644
--- a/spec/ruby/library/rexml/attribute/element_spec.rb
+++ b/spec/ruby/library/rexml/attribute/element_spec.rb
@@ -1,23 +1,26 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#element" do
- it "returns the parent element" do
- e = REXML::Element.new "root"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- REXML::Attribute.new("name", "value", e).element.should == e
- REXML::Attribute.new("name", "default_constructor").element.should == nil
+ describe "REXML::Attribute#element" do
+ it "returns the parent element" do
+ e = REXML::Element.new "root"
+
+ REXML::Attribute.new("name", "value", e).element.should == e
+ REXML::Attribute.new("name", "default_constructor").element.should == nil
+ end
end
-end
-describe "REXML::Attribute#element=" do
- it "sets the parent element" do
- e = REXML::Element.new "root"
- f = REXML::Element.new "temp"
- a = REXML::Attribute.new("name", "value", e)
- a.element.should == e
+ describe "REXML::Attribute#element=" do
+ it "sets the parent element" do
+ e = REXML::Element.new "root"
+ f = REXML::Element.new "temp"
+ a = REXML::Attribute.new("name", "value", e)
+ a.element.should == e
- a.element = f
- a.element.should == f
+ a.element = f
+ a.element.should == f
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/equal_value_spec.rb b/spec/ruby/library/rexml/attribute/equal_value_spec.rb
index 8bf2c0a3a1..1498bae624 100644
--- a/spec/ruby/library/rexml/attribute/equal_value_spec.rb
+++ b/spec/ruby/library/rexml/attribute/equal_value_spec.rb
@@ -1,18 +1,21 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#==" do
- it "returns true if other has equal name and value" do
- a1 = REXML::Attribute.new("foo", "bar")
- a1.should == a1.clone
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- a2 = REXML::Attribute.new("foo", "bar")
- a1.should == a2
+ describe "REXML::Attribute#==" do
+ it "returns true if other has equal name and value" do
+ a1 = REXML::Attribute.new("foo", "bar")
+ a1.should == a1.clone
- a3 = REXML::Attribute.new("foo", "bla")
- a1.should_not == a3
+ a2 = REXML::Attribute.new("foo", "bar")
+ a1.should == a2
- a4 = REXML::Attribute.new("baz", "bar")
- a1.should_not == a4
+ a3 = REXML::Attribute.new("foo", "bla")
+ a1.should_not == a3
+
+ a4 = REXML::Attribute.new("baz", "bar")
+ a1.should_not == a4
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/hash_spec.rb b/spec/ruby/library/rexml/attribute/hash_spec.rb
index dd71b28108..7e0cbcc1ea 100644
--- a/spec/ruby/library/rexml/attribute/hash_spec.rb
+++ b/spec/ruby/library/rexml/attribute/hash_spec.rb
@@ -1,13 +1,16 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#hash" do
- # These are not really complete, any idea on how to make them more
- # "testable" will be appreciated.
- it "returns a hashcode made of the name and value of self" do
- a = REXML::Attribute.new("name", "value")
- a.hash.should be_kind_of(Numeric)
- b = REXML::Attribute.new(a)
- a.hash.should == b.hash
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Attribute#hash" do
+ # These are not really complete, any idea on how to make them more
+ # "testable" will be appreciated.
+ it "returns a hashcode made of the name and value of self" do
+ a = REXML::Attribute.new("name", "value")
+ a.hash.should be_kind_of(Numeric)
+ b = REXML::Attribute.new(a)
+ a.hash.should == b.hash
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/initialize_spec.rb b/spec/ruby/library/rexml/attribute/initialize_spec.rb
index 9f5e30c517..35b87b0733 100644
--- a/spec/ruby/library/rexml/attribute/initialize_spec.rb
+++ b/spec/ruby/library/rexml/attribute/initialize_spec.rb
@@ -1,29 +1,32 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#initialize" do
- before :each do
- @e = REXML::Element.new "root"
- @name = REXML::Attribute.new("name", "Nicko")
- @e.add_attribute @name
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "receives two strings for name and value" do
- @e.attributes["name"].should == "Nicko"
- @e.add_attribute REXML::Attribute.new("last_name", nil)
- @e.attributes["last_name"].should == ""
- end
+ describe "REXML::Attribute#initialize" do
+ before :each do
+ @e = REXML::Element.new "root"
+ @name = REXML::Attribute.new("name", "Nicko")
+ @e.add_attribute @name
+ end
- it "receives an Attribute and clones it" do
- copy = REXML::Attribute.new(@name)
- copy.should == @name
- end
+ it "receives two strings for name and value" do
+ @e.attributes["name"].should == "Nicko"
+ @e.add_attribute REXML::Attribute.new("last_name", nil)
+ @e.attributes["last_name"].should == ""
+ end
+
+ it "receives an Attribute and clones it" do
+ copy = REXML::Attribute.new(@name)
+ copy.should == @name
+ end
- it "receives a parent node" do
- last_name = REXML::Attribute.new("last_name", "McBrain", @e)
- last_name.element.should == @e
+ it "receives a parent node" do
+ last_name = REXML::Attribute.new("last_name", "McBrain", @e)
+ last_name.element.should == @e
- last_name = REXML::Attribute.new(@name, @e)
- last_name.element.should == @e
+ last_name = REXML::Attribute.new(@name, @e)
+ last_name.element.should == @e
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/inspect_spec.rb b/spec/ruby/library/rexml/attribute/inspect_spec.rb
index 632b477cca..ee5236b98e 100644
--- a/spec/ruby/library/rexml/attribute/inspect_spec.rb
+++ b/spec/ruby/library/rexml/attribute/inspect_spec.rb
@@ -1,19 +1,22 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#inspect" do
- it "returns the name and value as a string" do
- a = REXML::Attribute.new("my_name", "my_value")
- a.inspect.should == "my_name='my_value'"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "accepts attributes with no value" do
- a = REXML::Attribute.new("my_name")
- a.inspect.should == "my_name=''"
- end
+ describe "REXML::Attribute#inspect" do
+ it "returns the name and value as a string" do
+ a = REXML::Attribute.new("my_name", "my_value")
+ a.inspect.should == "my_name='my_value'"
+ end
+
+ it "accepts attributes with no value" do
+ a = REXML::Attribute.new("my_name")
+ a.inspect.should == "my_name=''"
+ end
- it "does not escape text" do
- a = REXML::Attribute.new("name", "<>")
- a.inspect.should == "name='<>'"
+ it "does not escape text" do
+ a = REXML::Attribute.new("name", "<>")
+ a.inspect.should == "name='<>'"
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/namespace_spec.rb b/spec/ruby/library/rexml/attribute/namespace_spec.rb
index 9d50770735..645b3cd1b1 100644
--- a/spec/ruby/library/rexml/attribute/namespace_spec.rb
+++ b/spec/ruby/library/rexml/attribute/namespace_spec.rb
@@ -1,24 +1,27 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#namespace" do
- it "returns the namespace url" do
- e = REXML::Element.new("root")
- e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri")
- e.namespace("ns").should == "http://some_uri"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns nil if namespace is not defined" do
- e = REXML::Element.new("root")
- e.add_attribute REXML::Attribute.new("test", "value")
- e.namespace("test").should == nil
- e.namespace("ns").should == nil
- end
+ describe "REXML::Attribute#namespace" do
+ it "returns the namespace url" do
+ e = REXML::Element.new("root")
+ e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri")
+ e.namespace("ns").should == "http://some_uri"
+ end
+
+ it "returns nil if namespace is not defined" do
+ e = REXML::Element.new("root")
+ e.add_attribute REXML::Attribute.new("test", "value")
+ e.namespace("test").should == nil
+ e.namespace("ns").should == nil
+ end
- it "defaults arg to nil" do
- e = REXML::Element.new("root")
- e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri")
- e.namespace.should == ""
- e.namespace("ns").should == "http://some_uri"
+ it "defaults arg to nil" do
+ e = REXML::Element.new("root")
+ e.add_attribute REXML::Attribute.new("xmlns:ns", "http://some_uri")
+ e.namespace.should == ""
+ e.namespace("ns").should == "http://some_uri"
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/node_type_spec.rb b/spec/ruby/library/rexml/attribute/node_type_spec.rb
index 664d7cfa03..da055ae8f0 100644
--- a/spec/ruby/library/rexml/attribute/node_type_spec.rb
+++ b/spec/ruby/library/rexml/attribute/node_type_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#node_type" do
- it "always returns :attribute" do
- attr = REXML::Attribute.new("foo", "bar")
- attr.node_type.should == :attribute
- REXML::Attribute.new(attr).node_type.should == :attribute
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Attribute#node_type" do
+ it "always returns :attribute" do
+ attr = REXML::Attribute.new("foo", "bar")
+ attr.node_type.should == :attribute
+ REXML::Attribute.new(attr).node_type.should == :attribute
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/prefix_spec.rb b/spec/ruby/library/rexml/attribute/prefix_spec.rb
index 2a47f74ad1..87bff4822b 100644
--- a/spec/ruby/library/rexml/attribute/prefix_spec.rb
+++ b/spec/ruby/library/rexml/attribute/prefix_spec.rb
@@ -1,18 +1,21 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#prefix" do
- it "returns the namespace of the Attribute" do
- ans = REXML::Attribute.new("ns:someattr", "some_value")
- out = REXML::Attribute.new("out:something", "some_other_value")
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- ans.prefix.should == "ns"
- out.prefix.should == "out"
- end
+ describe "REXML::Attribute#prefix" do
+ it "returns the namespace of the Attribute" do
+ ans = REXML::Attribute.new("ns:someattr", "some_value")
+ out = REXML::Attribute.new("out:something", "some_other_value")
+
+ ans.prefix.should == "ns"
+ out.prefix.should == "out"
+ end
- it "returns an empty string for Attributes with no prefixes" do
- attr = REXML::Attribute.new("foo", "bar")
+ it "returns an empty string for Attributes with no prefixes" do
+ attr = REXML::Attribute.new("foo", "bar")
- attr.prefix.should == ""
+ attr.prefix.should == ""
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/remove_spec.rb b/spec/ruby/library/rexml/attribute/remove_spec.rb
index 08d22cb6ba..5f928b1286 100644
--- a/spec/ruby/library/rexml/attribute/remove_spec.rb
+++ b/spec/ruby/library/rexml/attribute/remove_spec.rb
@@ -1,20 +1,23 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#remove" do
- before :each do
- @e = REXML::Element.new "Root"
- @attr = REXML::Attribute.new("foo", "bar")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "deletes this Attribute from parent" do
- @e.add_attribute(@attr)
- @e.attributes["foo"].should_not == nil
- @attr.remove
- @e.attributes["foo"].should == nil
- end
+ describe "REXML::Attribute#remove" do
+ before :each do
+ @e = REXML::Element.new "Root"
+ @attr = REXML::Attribute.new("foo", "bar")
+ end
+
+ it "deletes this Attribute from parent" do
+ @e.add_attribute(@attr)
+ @e.attributes["foo"].should_not == nil
+ @attr.remove
+ @e.attributes["foo"].should == nil
+ end
- it "does not anything if element has no parent" do
- -> {@attr.remove}.should_not raise_error(Exception)
+ it "does not anything if element has no parent" do
+ -> {@attr.remove}.should_not raise_error(Exception)
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/to_s_spec.rb b/spec/ruby/library/rexml/attribute/to_s_spec.rb
index e1ce48ec33..e362cee8f1 100644
--- a/spec/ruby/library/rexml/attribute/to_s_spec.rb
+++ b/spec/ruby/library/rexml/attribute/to_s_spec.rb
@@ -1,14 +1,17 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#to_s" do
- it "returns the value of the Attribute" do
- REXML::Attribute.new("name", "some_value").to_s.should == "some_value"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Attribute#to_s" do
+ it "returns the value of the Attribute" do
+ REXML::Attribute.new("name", "some_value").to_s.should == "some_value"
+ end
- it "returns the escaped value if it was created from Attribute" do
- orig = REXML::Attribute.new("name", "<&>")
- copy = REXML::Attribute.new(orig)
- copy.to_s.should == "&lt;&amp;&gt;"
+ it "returns the escaped value if it was created from Attribute" do
+ orig = REXML::Attribute.new("name", "<&>")
+ copy = REXML::Attribute.new(orig)
+ copy.to_s.should == "&lt;&amp;&gt;"
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/to_string_spec.rb b/spec/ruby/library/rexml/attribute/to_string_spec.rb
index 420913afeb..a9d249f5bb 100644
--- a/spec/ruby/library/rexml/attribute/to_string_spec.rb
+++ b/spec/ruby/library/rexml/attribute/to_string_spec.rb
@@ -1,14 +1,17 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#to_string" do
- it "returns the attribute as XML" do
- attr = REXML::Attribute.new("name", "value")
- attr_empty = REXML::Attribute.new("name")
- attr_ns = REXML::Attribute.new("xmlns:ns", "http://uri")
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- attr.to_string.should == "name='value'"
- attr_empty.to_string.should == "name=''"
- attr_ns.to_string.should == "xmlns:ns='http://uri'"
+ describe "REXML::Attribute#to_string" do
+ it "returns the attribute as XML" do
+ attr = REXML::Attribute.new("name", "value")
+ attr_empty = REXML::Attribute.new("name")
+ attr_ns = REXML::Attribute.new("xmlns:ns", "http://uri")
+
+ attr.to_string.should == "name='value'"
+ attr_empty.to_string.should == "name=''"
+ attr_ns.to_string.should == "xmlns:ns='http://uri'"
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/value_spec.rb b/spec/ruby/library/rexml/attribute/value_spec.rb
index 7763976881..77071f6f70 100644
--- a/spec/ruby/library/rexml/attribute/value_spec.rb
+++ b/spec/ruby/library/rexml/attribute/value_spec.rb
@@ -1,14 +1,17 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#value" do
- it "returns the value of the Attribute unnormalized" do
- attr = REXML::Attribute.new("name", "value")
- attr_ents = REXML::Attribute.new("name", "<&>")
- attr_empty = REXML::Attribute.new("name")
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- attr.value.should == "value"
- attr_ents.value.should == "<&>"
- attr_empty.value.should == ""
+ describe "REXML::Attribute#value" do
+ it "returns the value of the Attribute unnormalized" do
+ attr = REXML::Attribute.new("name", "value")
+ attr_ents = REXML::Attribute.new("name", "<&>")
+ attr_empty = REXML::Attribute.new("name")
+
+ attr.value.should == "value"
+ attr_ents.value.should == "<&>"
+ attr_empty.value.should == ""
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/write_spec.rb b/spec/ruby/library/rexml/attribute/write_spec.rb
index 7ada7460f9..0012b3cc77 100644
--- a/spec/ruby/library/rexml/attribute/write_spec.rb
+++ b/spec/ruby/library/rexml/attribute/write_spec.rb
@@ -1,23 +1,26 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#write" do
- before :each do
- @attr = REXML::Attribute.new("name", "Charlotte")
- @s = ""
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "writes the name and value to output" do
- @attr.write(@s)
- @s.should == "name='Charlotte'"
- end
+ describe "REXML::Attribute#write" do
+ before :each do
+ @attr = REXML::Attribute.new("name", "Charlotte")
+ @s = ""
+ end
+
+ it "writes the name and value to output" do
+ @attr.write(@s)
+ @s.should == "name='Charlotte'"
+ end
- it "currently ignores the second argument" do
- @attr.write(@s, 3)
- @s.should == "name='Charlotte'"
+ it "currently ignores the second argument" do
+ @attr.write(@s, 3)
+ @s.should == "name='Charlotte'"
- @s = ""
- @attr.write(@s, "foo")
- @s.should == "name='Charlotte'"
+ @s = ""
+ @attr.write(@s, "foo")
+ @s.should == "name='Charlotte'"
+ end
end
end
diff --git a/spec/ruby/library/rexml/attribute/xpath_spec.rb b/spec/ruby/library/rexml/attribute/xpath_spec.rb
index 8335e0a8ef..0a09046b01 100644
--- a/spec/ruby/library/rexml/attribute/xpath_spec.rb
+++ b/spec/ruby/library/rexml/attribute/xpath_spec.rb
@@ -1,19 +1,22 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attribute#xpath" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- before :each do
- @e = REXML::Element.new "root"
- @attr = REXML::Attribute.new("year", "1989")
- end
+ describe "REXML::Attribute#xpath" do
- it "returns the path for Attribute" do
- @e.add_attribute @attr
- @attr.xpath.should == "root/@year"
- end
+ before :each do
+ @e = REXML::Element.new "root"
+ @attr = REXML::Attribute.new("year", "1989")
+ end
+
+ it "returns the path for Attribute" do
+ @e.add_attribute @attr
+ @attr.xpath.should == "root/@year"
+ end
- it "raises an error if attribute has no parent" do
- -> { @attr.xpath }.should raise_error(Exception)
+ it "raises an error if attribute has no parent" do
+ -> { @attr.xpath }.should raise_error(Exception)
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/add_spec.rb b/spec/ruby/library/rexml/attributes/add_spec.rb
index 32a927e10b..e24e9fabbc 100644
--- a/spec/ruby/library/rexml/attributes/add_spec.rb
+++ b/spec/ruby/library/rexml/attributes/add_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/add'
-require 'rexml/document'
-describe "REXML::Attributes#add" do
- it_behaves_like :rexml_attribute_add, :add
+ruby_version_is ''...'3.0' do
+ require_relative 'shared/add'
+ require 'rexml/document'
+
+ describe "REXML::Attributes#add" do
+ it_behaves_like :rexml_attribute_add, :add
+ end
end
diff --git a/spec/ruby/library/rexml/attributes/append_spec.rb b/spec/ruby/library/rexml/attributes/append_spec.rb
index f1b08f7d6a..f96a727f47 100644
--- a/spec/ruby/library/rexml/attributes/append_spec.rb
+++ b/spec/ruby/library/rexml/attributes/append_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/add'
-require 'rexml/document'
-describe "REXML::Attributes#<<" do
- it_behaves_like :rexml_attribute_add, :<<
+ruby_version_is ''...'3.0' do
+ require_relative 'shared/add'
+ require 'rexml/document'
+
+ describe "REXML::Attributes#<<" do
+ it_behaves_like :rexml_attribute_add, :<<
+ end
end
diff --git a/spec/ruby/library/rexml/attributes/delete_all_spec.rb b/spec/ruby/library/rexml/attributes/delete_all_spec.rb
index 9340b5693b..707baa235b 100644
--- a/spec/ruby/library/rexml/attributes/delete_all_spec.rb
+++ b/spec/ruby/library/rexml/attributes/delete_all_spec.rb
@@ -1,31 +1,34 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#delete_all" do
- before :each do
- @e = REXML::Element.new("root")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "deletes all attributes that match name" do
- uri = REXML::Attribute.new("uri", "http://something")
- @e.attributes << uri
- @e.attributes.delete_all("uri")
- @e.attributes.should be_empty
- @e.attributes["uri"].should == nil
- end
+ describe "REXML::Attributes#delete_all" do
+ before :each do
+ @e = REXML::Element.new("root")
+ end
- it "deletes all attributes that match name with a namespace" do
- ns_uri = REXML::Attribute.new("xmlns:uri", "http://something_here_too")
- @e.attributes << ns_uri
- @e.attributes.delete_all("xmlns:uri")
- @e.attributes.should be_empty
- @e.attributes["xmlns:uri"].should == nil
- end
+ it "deletes all attributes that match name" do
+ uri = REXML::Attribute.new("uri", "http://something")
+ @e.attributes << uri
+ @e.attributes.delete_all("uri")
+ @e.attributes.should be_empty
+ @e.attributes["uri"].should == nil
+ end
+
+ it "deletes all attributes that match name with a namespace" do
+ ns_uri = REXML::Attribute.new("xmlns:uri", "http://something_here_too")
+ @e.attributes << ns_uri
+ @e.attributes.delete_all("xmlns:uri")
+ @e.attributes.should be_empty
+ @e.attributes["xmlns:uri"].should == nil
+ end
- it "returns the removed attribute" do
- uri = REXML::Attribute.new("uri", "http://something_here_too")
- @e.attributes << uri
- attrs = @e.attributes.delete_all("uri")
- attrs.first.should == uri
+ it "returns the removed attribute" do
+ uri = REXML::Attribute.new("uri", "http://something_here_too")
+ @e.attributes << uri
+ attrs = @e.attributes.delete_all("uri")
+ attrs.first.should == uri
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/delete_spec.rb b/spec/ruby/library/rexml/attributes/delete_spec.rb
index 495e4085ef..723fa70751 100644
--- a/spec/ruby/library/rexml/attributes/delete_spec.rb
+++ b/spec/ruby/library/rexml/attributes/delete_spec.rb
@@ -1,27 +1,30 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#delete" do
- before :each do
- @e = REXML::Element.new("root")
- @name = REXML::Attribute.new("name", "Pepe")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "takes an attribute name and deletes the attribute" do
- @e.attributes.delete("name")
- @e.attributes["name"].should be_nil
- @e.attributes.should be_empty
- end
+ describe "REXML::Attributes#delete" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @name = REXML::Attribute.new("name", "Pepe")
+ end
- it "takes an Attribute and deletes it" do
- @e.attributes.delete(@name)
- @e.attributes["name"].should be_nil
- @e.attributes.should be_empty
- end
+ it "takes an attribute name and deletes the attribute" do
+ @e.attributes.delete("name")
+ @e.attributes["name"].should be_nil
+ @e.attributes.should be_empty
+ end
+
+ it "takes an Attribute and deletes it" do
+ @e.attributes.delete(@name)
+ @e.attributes["name"].should be_nil
+ @e.attributes.should be_empty
+ end
- it "returns the element with the attribute removed" do
- ret_val = @e.attributes.delete(@name)
- ret_val.should == @e
- ret_val.attributes.should be_empty
+ it "returns the element with the attribute removed" do
+ ret_val = @e.attributes.delete(@name)
+ ret_val.should == @e
+ ret_val.attributes.should be_empty
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/each_attribute_spec.rb b/spec/ruby/library/rexml/attributes/each_attribute_spec.rb
index e84c8dbf51..692cf4f943 100644
--- a/spec/ruby/library/rexml/attributes/each_attribute_spec.rb
+++ b/spec/ruby/library/rexml/attributes/each_attribute_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#each_attribute" do
- it "iterates over the attributes yielding actual Attribute objects" do
- e = REXML::Element.new("root")
- name = REXML::Attribute.new("name", "Joe")
- ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri")
- e.add_attribute name
- e.add_attribute ns_uri
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- attributes = []
+ describe "REXML::Attributes#each_attribute" do
+ it "iterates over the attributes yielding actual Attribute objects" do
+ e = REXML::Element.new("root")
+ name = REXML::Attribute.new("name", "Joe")
+ ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri")
+ e.add_attribute name
+ e.add_attribute ns_uri
- e.attributes.each_attribute do |attr|
- attributes << attr
- end
+ attributes = []
+
+ e.attributes.each_attribute do |attr|
+ attributes << attr
+ end
- attributes = attributes.sort_by {|a| a.name }
- attributes.first.should == name
- attributes.last.should == ns_uri
+ attributes = attributes.sort_by {|a| a.name }
+ attributes.first.should == name
+ attributes.last.should == ns_uri
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/each_spec.rb b/spec/ruby/library/rexml/attributes/each_spec.rb
index ed60634b90..49add3b77b 100644
--- a/spec/ruby/library/rexml/attributes/each_spec.rb
+++ b/spec/ruby/library/rexml/attributes/each_spec.rb
@@ -1,23 +1,26 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#each" do
- before :each do
- @e = REXML::Element.new("root")
- @name = REXML::Attribute.new("name", "Joe")
- @ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri")
- @e.add_attribute @name
- @e.add_attribute @ns_uri
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Attributes#each" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @name = REXML::Attribute.new("name", "Joe")
+ @ns_uri = REXML::Attribute.new("xmlns:ns", "http://some_uri")
+ @e.add_attribute @name
+ @e.add_attribute @ns_uri
+ end
- it "iterates over the attributes yielding expanded-name/value" do
- attributes = []
- @e.attributes.each do |attr|
- attr.should be_kind_of(Array)
- attributes << attr
+ it "iterates over the attributes yielding expanded-name/value" do
+ attributes = []
+ @e.attributes.each do |attr|
+ attr.should be_kind_of(Array)
+ attributes << attr
+ end
+ attributes = attributes.sort_by {|a| a.first }
+ attributes.first.should == ["name", "Joe"]
+ attributes.last.should == ["xmlns:ns", "http://some_uri"]
end
- attributes = attributes.sort_by {|a| a.first }
- attributes.first.should == ["name", "Joe"]
- attributes.last.should == ["xmlns:ns", "http://some_uri"]
end
end
diff --git a/spec/ruby/library/rexml/attributes/element_reference_spec.rb b/spec/ruby/library/rexml/attributes/element_reference_spec.rb
index dac7952669..0d089eaab2 100644
--- a/spec/ruby/library/rexml/attributes/element_reference_spec.rb
+++ b/spec/ruby/library/rexml/attributes/element_reference_spec.rb
@@ -1,18 +1,21 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#[]" do
- before :each do
- @e = REXML::Element.new("root")
- @lang = REXML::Attribute.new("language", "english")
- @e.attributes << @lang
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns the value of an attribute" do
- @e.attributes["language"].should == "english"
- end
+ describe "REXML::Attributes#[]" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @lang = REXML::Attribute.new("language", "english")
+ @e.attributes << @lang
+ end
+
+ it "returns the value of an attribute" do
+ @e.attributes["language"].should == "english"
+ end
- it "returns nil if the attribute does not exist" do
- @e.attributes["chunky bacon"].should == nil
+ it "returns nil if the attribute does not exist" do
+ @e.attributes["chunky bacon"].should == nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/element_set_spec.rb b/spec/ruby/library/rexml/attributes/element_set_spec.rb
index 1ed94dd2a1..834ad682a6 100644
--- a/spec/ruby/library/rexml/attributes/element_set_spec.rb
+++ b/spec/ruby/library/rexml/attributes/element_set_spec.rb
@@ -1,25 +1,28 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#[]=" do
- before :each do
- @e = REXML::Element.new("song")
- @name = REXML::Attribute.new("name", "Holy Smoke!")
- @e.attributes << @name
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "sets an attribute" do
- @e.attributes["author"] = "_why's foxes"
- @e.attributes["author"].should == "_why's foxes"
- end
+ describe "REXML::Attributes#[]=" do
+ before :each do
+ @e = REXML::Element.new("song")
+ @name = REXML::Attribute.new("name", "Holy Smoke!")
+ @e.attributes << @name
+ end
- it "overwrites an existing attribute" do
- @e.attributes["name"] = "Chunky Bacon"
- @e.attributes["name"].should == "Chunky Bacon"
- end
+ it "sets an attribute" do
+ @e.attributes["author"] = "_why's foxes"
+ @e.attributes["author"].should == "_why's foxes"
+ end
+
+ it "overwrites an existing attribute" do
+ @e.attributes["name"] = "Chunky Bacon"
+ @e.attributes["name"].should == "Chunky Bacon"
+ end
- it "deletes an attribute is value is nil" do
- @e.attributes["name"] = nil
- @e.attributes.length.should == 0
+ it "deletes an attribute is value is nil" do
+ @e.attributes["name"] = nil
+ @e.attributes.length.should == 0
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb b/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb
index 1664d6e42a..1109ff519c 100644
--- a/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb
+++ b/spec/ruby/library/rexml/attributes/get_attribute_ns_spec.rb
@@ -1,14 +1,17 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#get_attribute_ns" do
- it "returns an attribute by name and namespace" do
- e = REXML::Element.new("root")
- attr = REXML::Attribute.new("xmlns:ns", "http://some_url")
- e.attributes << attr
- attr.prefix.should == "xmlns"
- # This might be a bug in Attribute, commenting until those specs
- # are ready
- # e.attributes.get_attribute_ns(attr.prefix, "name").should == "http://some_url"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Attributes#get_attribute_ns" do
+ it "returns an attribute by name and namespace" do
+ e = REXML::Element.new("root")
+ attr = REXML::Attribute.new("xmlns:ns", "http://some_url")
+ e.attributes << attr
+ attr.prefix.should == "xmlns"
+ # This might be a bug in Attribute, commenting until those specs
+ # are ready
+ # e.attributes.get_attribute_ns(attr.prefix, "name").should == "http://some_url"
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/get_attribute_spec.rb b/spec/ruby/library/rexml/attributes/get_attribute_spec.rb
index cfe58c1b9e..cc94191729 100644
--- a/spec/ruby/library/rexml/attributes/get_attribute_spec.rb
+++ b/spec/ruby/library/rexml/attributes/get_attribute_spec.rb
@@ -1,29 +1,32 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#get_attribute" do
- before :each do
- @e = REXML::Element.new("root")
- @name = REXML::Attribute.new("name", "Dave")
- @e.attributes << @name
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "fetches an attributes" do
- @e.attributes.get_attribute("name").should == @name
- end
+ describe "REXML::Attributes#get_attribute" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @name = REXML::Attribute.new("name", "Dave")
+ @e.attributes << @name
+ end
- it "fetches an namespaced attribute" do
- ns_name = REXML::Attribute.new("im:name", "Murray")
- @e.attributes << ns_name
- @e.attributes.get_attribute("name").should == @name
- @e.attributes.get_attribute("im:name").should == ns_name
- end
+ it "fetches an attributes" do
+ @e.attributes.get_attribute("name").should == @name
+ end
- it "returns an Attribute" do
- @e.attributes.get_attribute("name").should be_kind_of(REXML::Attribute)
- end
+ it "fetches an namespaced attribute" do
+ ns_name = REXML::Attribute.new("im:name", "Murray")
+ @e.attributes << ns_name
+ @e.attributes.get_attribute("name").should == @name
+ @e.attributes.get_attribute("im:name").should == ns_name
+ end
+
+ it "returns an Attribute" do
+ @e.attributes.get_attribute("name").should be_kind_of(REXML::Attribute)
+ end
- it "returns nil if it attribute does not exist" do
- @e.attributes.get_attribute("fake").should be_nil
+ it "returns nil if it attribute does not exist" do
+ @e.attributes.get_attribute("fake").should be_nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/initialize_spec.rb b/spec/ruby/library/rexml/attributes/initialize_spec.rb
index f18bd20c69..42ec742e60 100644
--- a/spec/ruby/library/rexml/attributes/initialize_spec.rb
+++ b/spec/ruby/library/rexml/attributes/initialize_spec.rb
@@ -1,18 +1,21 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#initialize" do
- it "is auto initialized by Element" do
- e = REXML::Element.new "root"
- e.attributes.should be_kind_of(REXML::Attributes)
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- e.attributes << REXML::Attribute.new("name", "Paul")
- e.attributes["name"].should == "Paul"
- end
+ describe "REXML::Attributes#initialize" do
+ it "is auto initialized by Element" do
+ e = REXML::Element.new "root"
+ e.attributes.should be_kind_of(REXML::Attributes)
+
+ e.attributes << REXML::Attribute.new("name", "Paul")
+ e.attributes["name"].should == "Paul"
+ end
- it "receives a parent node" do
- e = REXML::Element.new "root"
- e.attributes << REXML::Attribute.new("name", "Vic")
- e.attributes["name"].should == "Vic"
+ it "receives a parent node" do
+ e = REXML::Element.new "root"
+ e.attributes << REXML::Attribute.new("name", "Vic")
+ e.attributes["name"].should == "Vic"
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/length_spec.rb b/spec/ruby/library/rexml/attributes/length_spec.rb
index 3a8361b8d7..81733b4a96 100644
--- a/spec/ruby/library/rexml/attributes/length_spec.rb
+++ b/spec/ruby/library/rexml/attributes/length_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/length'
-require 'rexml/document'
-describe "REXML::Attributes#length" do
- it_behaves_like :rexml_attribute_length, :length
+ruby_version_is ''...'3.0' do
+ require_relative 'shared/length'
+ require 'rexml/document'
+
+ describe "REXML::Attributes#length" do
+ it_behaves_like :rexml_attribute_length, :length
+ end
end
diff --git a/spec/ruby/library/rexml/attributes/namespaces_spec.rb b/spec/ruby/library/rexml/attributes/namespaces_spec.rb
index 9e329fef6f..b88346854f 100644
--- a/spec/ruby/library/rexml/attributes/namespaces_spec.rb
+++ b/spec/ruby/library/rexml/attributes/namespaces_spec.rb
@@ -1,6 +1,9 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#namespaces" do
- it "needs to be reviewed for spec completeness"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Attributes#namespaces" do
+ it "needs to be reviewed for spec completeness"
+ end
end
diff --git a/spec/ruby/library/rexml/attributes/prefixes_spec.rb b/spec/ruby/library/rexml/attributes/prefixes_spec.rb
index 4675095aad..574b7ffbaf 100644
--- a/spec/ruby/library/rexml/attributes/prefixes_spec.rb
+++ b/spec/ruby/library/rexml/attributes/prefixes_spec.rb
@@ -1,24 +1,27 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#prefixes" do
- before :each do
- @e = REXML::Element.new("root")
- a1 = REXML::Attribute.new("xmlns:a", "bar")
- a2 = REXML::Attribute.new("xmlns:b", "bla")
- a3 = REXML::Attribute.new("xmlns:c", "baz")
- @e.attributes << a1
- @e.attributes << a2
- @e.attributes << a3
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- @e.attributes << REXML::Attribute.new("xmlns", "foo")
- end
+ describe "REXML::Attributes#prefixes" do
+ before :each do
+ @e = REXML::Element.new("root")
+ a1 = REXML::Attribute.new("xmlns:a", "bar")
+ a2 = REXML::Attribute.new("xmlns:b", "bla")
+ a3 = REXML::Attribute.new("xmlns:c", "baz")
+ @e.attributes << a1
+ @e.attributes << a2
+ @e.attributes << a3
- it "returns an array with the prefixes of each attribute" do
- @e.attributes.prefixes.sort.should == ["a", "b", "c"]
- end
+ @e.attributes << REXML::Attribute.new("xmlns", "foo")
+ end
+
+ it "returns an array with the prefixes of each attribute" do
+ @e.attributes.prefixes.sort.should == ["a", "b", "c"]
+ end
- it "does not include the default namespace" do
- @e.attributes.prefixes.include?("xmlns").should == false
+ it "does not include the default namespace" do
+ @e.attributes.prefixes.include?("xmlns").should == false
+ end
end
end
diff --git a/spec/ruby/library/rexml/attributes/size_spec.rb b/spec/ruby/library/rexml/attributes/size_spec.rb
index 3b1df9510d..13ef08f644 100644
--- a/spec/ruby/library/rexml/attributes/size_spec.rb
+++ b/spec/ruby/library/rexml/attributes/size_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/length'
-require 'rexml/document'
-describe "REXML::Attributes#size" do
- it_behaves_like :rexml_attribute_length, :size
+ruby_version_is ''...'3.0' do
+ require_relative 'shared/length'
+ require 'rexml/document'
+
+ describe "REXML::Attributes#size" do
+ it_behaves_like :rexml_attribute_length, :size
+ end
end
diff --git a/spec/ruby/library/rexml/attributes/to_a_spec.rb b/spec/ruby/library/rexml/attributes/to_a_spec.rb
index 1fbf71b683..902cd86a29 100644
--- a/spec/ruby/library/rexml/attributes/to_a_spec.rb
+++ b/spec/ruby/library/rexml/attributes/to_a_spec.rb
@@ -1,19 +1,22 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Attributes#to_a" do
- it "returns an array with the attributes" do
- e = REXML::Element.new("root")
- name = REXML::Attribute.new("name", "Dave")
- last = REXML::Attribute.new("last_name", "Murray")
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- e.attributes << name
- e.attributes << last
+ describe "REXML::Attributes#to_a" do
+ it "returns an array with the attributes" do
+ e = REXML::Element.new("root")
+ name = REXML::Attribute.new("name", "Dave")
+ last = REXML::Attribute.new("last_name", "Murray")
- e.attributes.to_a.sort{|a,b|a.to_s<=>b.to_s}.should == [name, last]
- end
+ e.attributes << name
+ e.attributes << last
+
+ e.attributes.to_a.sort{|a,b|a.to_s<=>b.to_s}.should == [name, last]
+ end
- it "returns an empty array if it has no attributes" do
- REXML::Element.new("root").attributes.to_a.should == []
+ it "returns an empty array if it has no attributes" do
+ REXML::Element.new("root").attributes.to_a.should == []
+ end
end
end
diff --git a/spec/ruby/library/rexml/cdata/clone_spec.rb b/spec/ruby/library/rexml/cdata/clone_spec.rb
index 7d3cfda902..abe1a0b062 100644
--- a/spec/ruby/library/rexml/cdata/clone_spec.rb
+++ b/spec/ruby/library/rexml/cdata/clone_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::CData#clone" do
- it "makes a copy of itself" do
- c = REXML::CData.new("some text")
- c.clone.to_s.should == c.to_s
- c.clone.should == c
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::CData#clone" do
+ it "makes a copy of itself" do
+ c = REXML::CData.new("some text")
+ c.clone.to_s.should == c.to_s
+ c.clone.should == c
+ end
end
end
diff --git a/spec/ruby/library/rexml/cdata/initialize_spec.rb b/spec/ruby/library/rexml/cdata/initialize_spec.rb
index 0184440d87..1393d97f4a 100644
--- a/spec/ruby/library/rexml/cdata/initialize_spec.rb
+++ b/spec/ruby/library/rexml/cdata/initialize_spec.rb
@@ -1,24 +1,27 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::CData#initialize" do
- it "creates a new CData object" do
- c = REXML::CData.new("some text")
- c.should be_kind_of(REXML::CData)
- c.should be_kind_of(REXML::Text)
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "respects whitespace if whitespace is true" do
- c = REXML::CData.new("whitespace test", true)
- c1 = REXML::CData.new("whitespace test", false)
+ describe "REXML::CData#initialize" do
+ it "creates a new CData object" do
+ c = REXML::CData.new("some text")
+ c.should be_kind_of(REXML::CData)
+ c.should be_kind_of(REXML::Text)
+ end
- c.to_s.should == "whitespace test"
- c1.to_s.should == "whitespace test"
- end
+ it "respects whitespace if whitespace is true" do
+ c = REXML::CData.new("whitespace test", true)
+ c1 = REXML::CData.new("whitespace test", false)
+
+ c.to_s.should == "whitespace test"
+ c1.to_s.should == "whitespace test"
+ end
- it "receives parent as third argument" do
- e = REXML::Element.new("root")
- REXML::CData.new("test", true, e)
- e.to_s.should == "<root><![CDATA[test]]></root>"
+ it "receives parent as third argument" do
+ e = REXML::Element.new("root")
+ REXML::CData.new("test", true, e)
+ e.to_s.should == "<root><![CDATA[test]]></root>"
+ end
end
end
diff --git a/spec/ruby/library/rexml/cdata/to_s_spec.rb b/spec/ruby/library/rexml/cdata/to_s_spec.rb
index ff3076e55e..a5c061f116 100644
--- a/spec/ruby/library/rexml/cdata/to_s_spec.rb
+++ b/spec/ruby/library/rexml/cdata/to_s_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/to_s'
-require 'rexml/document'
-describe "REXML::CData#to_s" do
- it_behaves_like :rexml_cdata_to_s, :to_s
+ruby_version_is ''...'3.0' do
+ require_relative 'shared/to_s'
+ require 'rexml/document'
+
+ describe "REXML::CData#to_s" do
+ it_behaves_like :rexml_cdata_to_s, :to_s
+ end
end
diff --git a/spec/ruby/library/rexml/cdata/value_spec.rb b/spec/ruby/library/rexml/cdata/value_spec.rb
index 6e8f8587a1..9f36226976 100644
--- a/spec/ruby/library/rexml/cdata/value_spec.rb
+++ b/spec/ruby/library/rexml/cdata/value_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/to_s'
-require 'rexml/document'
-describe "REXML::CData#value" do
- it_behaves_like :rexml_cdata_to_s, :value
+ruby_version_is ''...'3.0' do
+ require_relative 'shared/to_s'
+ require 'rexml/document'
+
+ describe "REXML::CData#value" do
+ it_behaves_like :rexml_cdata_to_s, :value
+ end
end
diff --git a/spec/ruby/library/rexml/document/add_element_spec.rb b/spec/ruby/library/rexml/document/add_element_spec.rb
index 42981d6465..29dec0b24e 100644
--- a/spec/ruby/library/rexml/document/add_element_spec.rb
+++ b/spec/ruby/library/rexml/document/add_element_spec.rb
@@ -1,31 +1,34 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Document#add_element" do
- it "adds arg1 with attributes arg2 as root node" do
- d = REXML::Document.new
- e = REXML::Element.new("root")
- d.add_element e
- d.root.should == e
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "sets arg2 as arg1's attributes" do
- d = REXML::Document.new
- e = REXML::Element.new("root")
- attr = {"foo" => "bar"}
- d.add_element(e,attr)
- d.root.attributes["foo"].should == attr["foo"]
- end
+ describe "REXML::Document#add_element" do
+ it "adds arg1 with attributes arg2 as root node" do
+ d = REXML::Document.new
+ e = REXML::Element.new("root")
+ d.add_element e
+ d.root.should == e
+ end
- it "accepts a node name as arg1 and adds it as root" do
- d = REXML::Document.new
- d.add_element "foo"
- d.root.name.should == "foo"
- end
+ it "sets arg2 as arg1's attributes" do
+ d = REXML::Document.new
+ e = REXML::Element.new("root")
+ attr = {"foo" => "bar"}
+ d.add_element(e,attr)
+ d.root.attributes["foo"].should == attr["foo"]
+ end
+
+ it "accepts a node name as arg1 and adds it as root" do
+ d = REXML::Document.new
+ d.add_element "foo"
+ d.root.name.should == "foo"
+ end
- it "sets arg1's context to the root's context" do
- d = REXML::Document.new("", {"foo" => "bar"})
- d.add_element "foo"
- d.root.context.should == d.context
+ it "sets arg1's context to the root's context" do
+ d = REXML::Document.new("", {"foo" => "bar"})
+ d.add_element "foo"
+ d.root.context.should == d.context
+ end
end
end
diff --git a/spec/ruby/library/rexml/document/add_spec.rb b/spec/ruby/library/rexml/document/add_spec.rb
index db95114e7e..8666d3dbf9 100644
--- a/spec/ruby/library/rexml/document/add_spec.rb
+++ b/spec/ruby/library/rexml/document/add_spec.rb
@@ -1,57 +1,60 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-# This spec defines Document#add and Document#<<
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
-describe :rexml_document_add, shared: true do
- before :each do
- @doc = REXML::Document.new("<root/>")
- @decl = REXML::XMLDecl.new("1.0")
- end
+ # This spec defines Document#add and Document#<<
- it "sets document's XML declaration" do
- @doc.send(@method, @decl)
- @doc.xml_decl.should == @decl
- end
+ describe :rexml_document_add, shared: true do
+ before :each do
+ @doc = REXML::Document.new("<root/>")
+ @decl = REXML::XMLDecl.new("1.0")
+ end
- it "inserts XML declaration as first node" do
- @doc.send(@method, @decl)
- @doc.children[0].version.should == "1.0"
- end
+ it "sets document's XML declaration" do
+ @doc.send(@method, @decl)
+ @doc.xml_decl.should == @decl
+ end
- it "overwrites existing XML declaration" do
- @doc.send(@method, @decl)
- @doc.send(@method, REXML::XMLDecl.new("2.0"))
- @doc.xml_decl.version.should == "2.0"
- end
+ it "inserts XML declaration as first node" do
+ @doc.send(@method, @decl)
+ @doc.children[0].version.should == "1.0"
+ end
- it "sets document DocType" do
- @doc.send(@method, REXML::DocType.new("transitional"))
- @doc.doctype.name.should == "transitional"
- end
+ it "overwrites existing XML declaration" do
+ @doc.send(@method, @decl)
+ @doc.send(@method, REXML::XMLDecl.new("2.0"))
+ @doc.xml_decl.version.should == "2.0"
+ end
- it "overwrites existing DocType" do
- @doc.send(@method, REXML::DocType.new("transitional"))
- @doc.send(@method, REXML::DocType.new("strict"))
- @doc.doctype.name.should == "strict"
- end
+ it "sets document DocType" do
+ @doc.send(@method, REXML::DocType.new("transitional"))
+ @doc.doctype.name.should == "transitional"
+ end
- it "adds root node unless it exists" do
- d = REXML::Document.new("")
- elem = REXML::Element.new "root"
- d.send(@method, elem)
- d.root.should == elem
- end
+ it "overwrites existing DocType" do
+ @doc.send(@method, REXML::DocType.new("transitional"))
+ @doc.send(@method, REXML::DocType.new("strict"))
+ @doc.doctype.name.should == "strict"
+ end
+
+ it "adds root node unless it exists" do
+ d = REXML::Document.new("")
+ elem = REXML::Element.new "root"
+ d.send(@method, elem)
+ d.root.should == elem
+ end
- it "refuses to add second root" do
- -> { @doc.send(@method, REXML::Element.new("foo")) }.should raise_error(RuntimeError)
+ it "refuses to add second root" do
+ -> { @doc.send(@method, REXML::Element.new("foo")) }.should raise_error(RuntimeError)
+ end
end
-end
-describe "REXML::Document#add" do
- it_behaves_like :rexml_document_add, :add
-end
+ describe "REXML::Document#add" do
+ it_behaves_like :rexml_document_add, :add
+ end
-describe "REXML::Document#<<" do
- it_behaves_like :rexml_document_add, :<<
+ describe "REXML::Document#<<" do
+ it_behaves_like :rexml_document_add, :<<
+ end
end
diff --git a/spec/ruby/library/rexml/document/clone_spec.rb b/spec/ruby/library/rexml/document/clone_spec.rb
index 4aebb6f156..137fe8a073 100644
--- a/spec/ruby/library/rexml/document/clone_spec.rb
+++ b/spec/ruby/library/rexml/document/clone_spec.rb
@@ -1,20 +1,23 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-# According to the MRI documentation (http://www.ruby-doc.org/stdlib/libdoc/rexml/rdoc/index.html),
-# clone's behavior "should be obvious". Apparently "obvious" means cloning
-# only the attributes and the context of the document, not its children.
-describe "REXML::Document#clone" do
- it "clones document attributes" do
- d = REXML::Document.new("foo")
- d.attributes["foo"] = "bar"
- e = d.clone
- e.attributes.should == d.attributes
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ # According to the MRI documentation (http://www.ruby-doc.org/stdlib/libdoc/rexml/rdoc/index.html),
+ # clone's behavior "should be obvious". Apparently "obvious" means cloning
+ # only the attributes and the context of the document, not its children.
+ describe "REXML::Document#clone" do
+ it "clones document attributes" do
+ d = REXML::Document.new("foo")
+ d.attributes["foo"] = "bar"
+ e = d.clone
+ e.attributes.should == d.attributes
+ end
- it "clones document context" do
- d = REXML::Document.new("foo", {"foo" => "bar"})
- e = d.clone
- e.context.should == d.context
+ it "clones document context" do
+ d = REXML::Document.new("foo", {"foo" => "bar"})
+ e = d.clone
+ e.context.should == d.context
+ end
end
end
diff --git a/spec/ruby/library/rexml/document/doctype_spec.rb b/spec/ruby/library/rexml/document/doctype_spec.rb
index b919b071e1..e1b7ba4916 100644
--- a/spec/ruby/library/rexml/document/doctype_spec.rb
+++ b/spec/ruby/library/rexml/document/doctype_spec.rb
@@ -1,15 +1,18 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Document#doctype" do
- it "returns the doctype" do
- d = REXML::Document.new
- dt = REXML::DocType.new("foo")
- d.add dt
- d.doctype.should == dt
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Document#doctype" do
+ it "returns the doctype" do
+ d = REXML::Document.new
+ dt = REXML::DocType.new("foo")
+ d.add dt
+ d.doctype.should == dt
+ end
- it "returns nil if there's no doctype" do
- REXML::Document.new.doctype.should == nil
+ it "returns nil if there's no doctype" do
+ REXML::Document.new.doctype.should == nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/document/encoding_spec.rb b/spec/ruby/library/rexml/document/encoding_spec.rb
index 343e0ee45f..2cc947f06a 100644
--- a/spec/ruby/library/rexml/document/encoding_spec.rb
+++ b/spec/ruby/library/rexml/document/encoding_spec.rb
@@ -1,22 +1,25 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Document#encoding" do
- before :each do
- @doc = REXML::Document.new
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns encoding from XML declaration" do
- @doc.add REXML::XMLDecl.new(nil, "UTF-16", nil)
- @doc.encoding.should == "UTF-16"
- end
+ describe "REXML::Document#encoding" do
+ before :each do
+ @doc = REXML::Document.new
+ end
- it "returns encoding from XML declaration (for UTF-16 as well)" do
- @doc.add REXML::XMLDecl.new("1.0", "UTF-8", nil)
- @doc.encoding.should == "UTF-8"
- end
+ it "returns encoding from XML declaration" do
+ @doc.add REXML::XMLDecl.new(nil, "UTF-16", nil)
+ @doc.encoding.should == "UTF-16"
+ end
+
+ it "returns encoding from XML declaration (for UTF-16 as well)" do
+ @doc.add REXML::XMLDecl.new("1.0", "UTF-8", nil)
+ @doc.encoding.should == "UTF-8"
+ end
- it "uses UTF-8 as default encoding" do
- @doc.encoding.should == "UTF-8"
+ it "uses UTF-8 as default encoding" do
+ @doc.encoding.should == "UTF-8"
+ end
end
end
diff --git a/spec/ruby/library/rexml/document/expanded_name_spec.rb b/spec/ruby/library/rexml/document/expanded_name_spec.rb
index 1225d13fb0..9d1025b5e0 100644
--- a/spec/ruby/library/rexml/document/expanded_name_spec.rb
+++ b/spec/ruby/library/rexml/document/expanded_name_spec.rb
@@ -1,16 +1,19 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe :document_expanded_name, shared: true do
- it "returns an empty string for root" do # root nodes have no expanded name
- REXML::Document.new.send(@method).should == ""
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe :document_expanded_name, shared: true do
+ it "returns an empty string for root" do # root nodes have no expanded name
+ REXML::Document.new.send(@method).should == ""
+ end
end
-end
-describe "REXML::Document#expanded_name" do
- it_behaves_like :document_expanded_name, :expanded_name
-end
+ describe "REXML::Document#expanded_name" do
+ it_behaves_like :document_expanded_name, :expanded_name
+ end
-describe "REXML::Document#name" do
- it_behaves_like :document_expanded_name, :name
+ describe "REXML::Document#name" do
+ it_behaves_like :document_expanded_name, :name
+ end
end
diff --git a/spec/ruby/library/rexml/document/new_spec.rb b/spec/ruby/library/rexml/document/new_spec.rb
index 3ff5e99b25..4e24b6f5a1 100644
--- a/spec/ruby/library/rexml/document/new_spec.rb
+++ b/spec/ruby/library/rexml/document/new_spec.rb
@@ -1,36 +1,39 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Document#new" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "initializes context of {} unless specified" do
- d = REXML::Document.new("<foo />")
- d.context.should == {}
- end
+ describe "REXML::Document#new" do
- it "has empty attributes if source is nil" do
- d = REXML::Document.new(nil)
- d.elements.should be_empty
- end
+ it "initializes context of {} unless specified" do
+ d = REXML::Document.new("<foo />")
+ d.context.should == {}
+ end
- it "can use other document context" do
- s = REXML::Document.new("")
- d = REXML::Document.new(s)
- d.context.should == s.context
- end
+ it "has empty attributes if source is nil" do
+ d = REXML::Document.new(nil)
+ d.elements.should be_empty
+ end
- it "clones source attributes" do
- s = REXML::Document.new("<root />")
- s.attributes["some_attr"] = "some_val"
- d = REXML::Document.new(s)
- d.attributes.should == s.attributes
- end
+ it "can use other document context" do
+ s = REXML::Document.new("")
+ d = REXML::Document.new(s)
+ d.context.should == s.context
+ end
- it "raises an error if source is not a Document, String or IO" do
- -> {REXML::Document.new(3)}.should raise_error(RuntimeError)
- end
+ it "clones source attributes" do
+ s = REXML::Document.new("<root />")
+ s.attributes["some_attr"] = "some_val"
+ d = REXML::Document.new(s)
+ d.attributes.should == s.attributes
+ end
+
+ it "raises an error if source is not a Document, String or IO" do
+ -> {REXML::Document.new(3)}.should raise_error(RuntimeError)
+ end
- it "does not perform XML validation" do
- REXML::Document.new("Invalid document").should be_kind_of(REXML::Document)
+ it "does not perform XML validation" do
+ REXML::Document.new("Invalid document").should be_kind_of(REXML::Document)
+ end
end
end
diff --git a/spec/ruby/library/rexml/document/node_type_spec.rb b/spec/ruby/library/rexml/document/node_type_spec.rb
index 85a4d507aa..b6d7e7a7da 100644
--- a/spec/ruby/library/rexml/document/node_type_spec.rb
+++ b/spec/ruby/library/rexml/document/node_type_spec.rb
@@ -1,8 +1,11 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Document#node_type" do
- it "returns :document" do
- REXML::Document.new.node_type.should == :document
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Document#node_type" do
+ it "returns :document" do
+ REXML::Document.new.node_type.should == :document
+ end
end
end
diff --git a/spec/ruby/library/rexml/document/root_spec.rb b/spec/ruby/library/rexml/document/root_spec.rb
index 3c24e79b2d..1a584a720b 100644
--- a/spec/ruby/library/rexml/document/root_spec.rb
+++ b/spec/ruby/library/rexml/document/root_spec.rb
@@ -1,12 +1,15 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Document#root" do
- it "returns document root tag name" do
- REXML::Document.new("<foo/>").root.name.should == "foo"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Document#root" do
+ it "returns document root tag name" do
+ REXML::Document.new("<foo/>").root.name.should == "foo"
+ end
- it "returns nil if there is not root" do
- REXML::Document.new.root.should == nil
+ it "returns nil if there is not root" do
+ REXML::Document.new.root.should == nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/document/stand_alone_spec.rb b/spec/ruby/library/rexml/document/stand_alone_spec.rb
index 4ac24329d6..e1c721e782 100644
--- a/spec/ruby/library/rexml/document/stand_alone_spec.rb
+++ b/spec/ruby/library/rexml/document/stand_alone_spec.rb
@@ -1,19 +1,22 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Document#stand_alone?" do
- it "returns the XMLDecl standalone value" do
- d = REXML::Document.new
- decl = REXML::XMLDecl.new("1.0", "UTF-8", "yes")
- d.add decl
- d.stand_alone?.should == "yes"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- # According to the docs this should return the default XMLDecl but that
- # will carry some more problems when printing the document. Currently, it
- # returns nil. See http://www.ruby-forum.com/topic/146812#650061
- it "returns the default value when no XML declaration present" do
- REXML::Document.new.stand_alone?.should == nil
- end
+ describe "REXML::Document#stand_alone?" do
+ it "returns the XMLDecl standalone value" do
+ d = REXML::Document.new
+ decl = REXML::XMLDecl.new("1.0", "UTF-8", "yes")
+ d.add decl
+ d.stand_alone?.should == "yes"
+ end
+ # According to the docs this should return the default XMLDecl but that
+ # will carry some more problems when printing the document. Currently, it
+ # returns nil. See http://www.ruby-forum.com/topic/146812#650061
+ it "returns the default value when no XML declaration present" do
+ REXML::Document.new.stand_alone?.should == nil
+ end
+
+ end
end
diff --git a/spec/ruby/library/rexml/document/version_spec.rb b/spec/ruby/library/rexml/document/version_spec.rb
index 983b4b9af0..4f6b40551b 100644
--- a/spec/ruby/library/rexml/document/version_spec.rb
+++ b/spec/ruby/library/rexml/document/version_spec.rb
@@ -1,14 +1,17 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Document#version" do
- it "returns XML version from declaration" do
- d = REXML::Document.new
- d.add REXML::XMLDecl.new("1.1")
- d.version.should == "1.1"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Document#version" do
+ it "returns XML version from declaration" do
+ d = REXML::Document.new
+ d.add REXML::XMLDecl.new("1.1")
+ d.version.should == "1.1"
+ end
- it "returns the default version when declaration is not present" do
- REXML::Document.new.version.should == REXML::XMLDecl::DEFAULT_VERSION
+ it "returns the default version when declaration is not present" do
+ REXML::Document.new.version.should == REXML::XMLDecl::DEFAULT_VERSION
+ end
end
end
diff --git a/spec/ruby/library/rexml/document/write_spec.rb b/spec/ruby/library/rexml/document/write_spec.rb
index efa94b7117..00c22141b3 100644
--- a/spec/ruby/library/rexml/document/write_spec.rb
+++ b/spec/ruby/library/rexml/document/write_spec.rb
@@ -1,35 +1,38 @@
-require 'rexml/document'
-require 'rexml/formatters/transitive'
require_relative '../../../spec_helper'
-# Maybe this can be cleaned
-describe "REXML::Document#write" do
- before :each do
- @d = REXML::Document.new
- city = REXML::Element.new "Springfield"
- street = REXML::Element.new "EvergreenTerrace"
- address = REXML::Element.new "House742"
- @d << city << street << address
- @str = ""
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+ require 'rexml/formatters/transitive'
- it "returns document source as string" do
- @d.write(@str)
- @str.should == "<Springfield><EvergreenTerrace><House742/></EvergreenTerrace></Springfield>"
- end
+ # Maybe this can be cleaned
+ describe "REXML::Document#write" do
+ before :each do
+ @d = REXML::Document.new
+ city = REXML::Element.new "Springfield"
+ street = REXML::Element.new "EvergreenTerrace"
+ address = REXML::Element.new "House742"
+ @d << city << street << address
+ @str = ""
+ end
- it "returns document indented" do
- @d.write(@str, 2)
- @str.should =~ /\s*<Springfield>\s*<EvergreenTerrace>\s*<House742\/>\s*<\/EvergreenTerrace>\s*<\/Springfield>/
- end
+ it "returns document source as string" do
+ @d.write(@str)
+ @str.should == "<Springfield><EvergreenTerrace><House742/></EvergreenTerrace></Springfield>"
+ end
- it "returns document with transitive support" do
- @d.write(@str, 2, true)
- @str.should =~ /\s*<Springfield\s*><EvergreenTerrace\s*><House742\s*\/><\/EvergreenTerrace\s*><\/Springfield\s*>/
- end
+ it "returns document indented" do
+ @d.write(@str, 2)
+ @str.should =~ /\s*<Springfield>\s*<EvergreenTerrace>\s*<House742\/>\s*<\/EvergreenTerrace>\s*<\/Springfield>/
+ end
+
+ it "returns document with transitive support" do
+ @d.write(@str, 2, true)
+ @str.should =~ /\s*<Springfield\s*><EvergreenTerrace\s*><House742\s*\/><\/EvergreenTerrace\s*><\/Springfield\s*>/
+ end
- it "returns document with support for IE" do
- @d.write(@str, -1, false, true)
- @str.should == "<Springfield><EvergreenTerrace><House742 /></EvergreenTerrace></Springfield>"
+ it "returns document with support for IE" do
+ @d.write(@str, -1, false, true)
+ @str.should == "<Springfield><EvergreenTerrace><House742 /></EvergreenTerrace></Springfield>"
+ end
end
end
diff --git a/spec/ruby/library/rexml/document/xml_decl_spec.rb b/spec/ruby/library/rexml/document/xml_decl_spec.rb
index 30288a150b..8ac47510b0 100644
--- a/spec/ruby/library/rexml/document/xml_decl_spec.rb
+++ b/spec/ruby/library/rexml/document/xml_decl_spec.rb
@@ -1,15 +1,18 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Document#xml_decl" do
- it "returns XML declaration of the document" do
- d = REXML::Document.new
- decl = REXML::XMLDecl.new("1.0", "UTF-16", "yes")
- d.add decl
- d.xml_decl.should == decl
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Document#xml_decl" do
+ it "returns XML declaration of the document" do
+ d = REXML::Document.new
+ decl = REXML::XMLDecl.new("1.0", "UTF-16", "yes")
+ d.add decl
+ d.xml_decl.should == decl
+ end
- it "returns default XML declaration unless present" do
- REXML::Document.new.xml_decl.should == REXML::XMLDecl.new
+ it "returns default XML declaration unless present" do
+ REXML::Document.new.xml_decl.should == REXML::XMLDecl.new
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/add_attribute_spec.rb b/spec/ruby/library/rexml/element/add_attribute_spec.rb
index d15fb81ef1..64f2ec84a3 100644
--- a/spec/ruby/library/rexml/element/add_attribute_spec.rb
+++ b/spec/ruby/library/rexml/element/add_attribute_spec.rb
@@ -1,41 +1,44 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#add_attribute" do
- before :each do
- @person = REXML::Element.new "person"
- @person.attributes["name"] = "Bill"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "adds a new attribute" do
- @person.add_attribute("age", "17")
- @person.attributes["age"].should == "17"
- end
+ describe "REXML::Element#add_attribute" do
+ before :each do
+ @person = REXML::Element.new "person"
+ @person.attributes["name"] = "Bill"
+ end
- it "overwrites an existing attribute" do
- @person.add_attribute("name", "Bill")
- @person.attributes["name"].should == "Bill"
- end
+ it "adds a new attribute" do
+ @person.add_attribute("age", "17")
+ @person.attributes["age"].should == "17"
+ end
- it "accepts a pair of strings" do
- @person.add_attribute("male", "true")
- @person.attributes["male"].should == "true"
- end
+ it "overwrites an existing attribute" do
+ @person.add_attribute("name", "Bill")
+ @person.attributes["name"].should == "Bill"
+ end
- it "accepts an Attribute for key" do
- attr = REXML::Attribute.new("male", "true")
- @person.add_attribute attr
- @person.attributes["male"].should == "true"
- end
+ it "accepts a pair of strings" do
+ @person.add_attribute("male", "true")
+ @person.attributes["male"].should == "true"
+ end
- it "ignores value if key is an Attribute" do
- attr = REXML::Attribute.new("male", "true")
- @person.add_attribute(attr, "false")
- @person.attributes["male"].should == "true"
- end
+ it "accepts an Attribute for key" do
+ attr = REXML::Attribute.new("male", "true")
+ @person.add_attribute attr
+ @person.attributes["male"].should == "true"
+ end
+
+ it "ignores value if key is an Attribute" do
+ attr = REXML::Attribute.new("male", "true")
+ @person.add_attribute(attr, "false")
+ @person.attributes["male"].should == "true"
+ end
- it "returns the attribute added" do
- attr = REXML::Attribute.new("name", "Tony")
- @person.add_attribute(attr).should == attr
+ it "returns the attribute added" do
+ attr = REXML::Attribute.new("name", "Tony")
+ @person.add_attribute(attr).should == attr
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/add_attributes_spec.rb b/spec/ruby/library/rexml/element/add_attributes_spec.rb
index b462fdf5fe..f331803dd8 100644
--- a/spec/ruby/library/rexml/element/add_attributes_spec.rb
+++ b/spec/ruby/library/rexml/element/add_attributes_spec.rb
@@ -1,22 +1,25 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#add_attributes" do
- before :each do
- @person = REXML::Element.new "person"
- @person.attributes["name"] = "Bill"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "adds multiple attributes from a hash" do
- @person.add_attributes({"name" => "Joe", "age" => "27"})
- @person.attributes["name"].should == "Joe"
- @person.attributes["age"].should == "27"
- end
+ describe "REXML::Element#add_attributes" do
+ before :each do
+ @person = REXML::Element.new "person"
+ @person.attributes["name"] = "Bill"
+ end
+
+ it "adds multiple attributes from a hash" do
+ @person.add_attributes({"name" => "Joe", "age" => "27"})
+ @person.attributes["name"].should == "Joe"
+ @person.attributes["age"].should == "27"
+ end
- it "adds multiple attributes from an array" do
- attrs = { "name" => "Joe", "age" => "27"}
- @person.add_attributes attrs.to_a
- @person.attributes["name"].should == "Joe"
- @person.attributes["age"].should == "27"
+ it "adds multiple attributes from an array" do
+ attrs = { "name" => "Joe", "age" => "27"}
+ @person.add_attributes attrs.to_a
+ @person.attributes["name"].should == "Joe"
+ @person.attributes["age"].should == "27"
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/add_element_spec.rb b/spec/ruby/library/rexml/element/add_element_spec.rb
index 8e2ffe3148..8ba023f2c7 100644
--- a/spec/ruby/library/rexml/element/add_element_spec.rb
+++ b/spec/ruby/library/rexml/element/add_element_spec.rb
@@ -1,39 +1,41 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
-describe "REXML::Element#add_element" do
- before :each do
- @root = REXML::Element.new("root")
- end
+ describe "REXML::Element#add_element" do
+ before :each do
+ @root = REXML::Element.new("root")
+ end
- it "adds a child without attributes" do
- name = REXML::Element.new("name")
- @root.add_element name
- @root.elements["name"].name.should == name.name
- @root.elements["name"].attributes.should == name.attributes
- @root.elements["name"].context.should == name.context
- end
+ it "adds a child without attributes" do
+ name = REXML::Element.new("name")
+ @root.add_element name
+ @root.elements["name"].name.should == name.name
+ @root.elements["name"].attributes.should == name.attributes
+ @root.elements["name"].context.should == name.context
+ end
- it "adds a child with attributes" do
- person = REXML::Element.new("person")
- @root.add_element(person, {"name" => "Madonna"})
- @root.elements["person"].name.should == person.name
- @root.elements["person"].attributes.should == person.attributes
- @root.elements["person"].context.should == person.context
- end
+ it "adds a child with attributes" do
+ person = REXML::Element.new("person")
+ @root.add_element(person, {"name" => "Madonna"})
+ @root.elements["person"].name.should == person.name
+ @root.elements["person"].attributes.should == person.attributes
+ @root.elements["person"].context.should == person.context
+ end
- it "adds a child with name" do
- @root.add_element "name"
- @root.elements["name"].name.should == "name"
- @root.elements["name"].attributes.should == {}
- @root.elements["name"].context.should == nil
- end
+ it "adds a child with name" do
+ @root.add_element "name"
+ @root.elements["name"].name.should == "name"
+ @root.elements["name"].attributes.should == {}
+ @root.elements["name"].context.should == nil
+ end
- it "returns the added child" do
- name = @root.add_element "name"
- @root.elements["name"].name.should == name.name
- @root.elements["name"].attributes.should == name.attributes
- @root.elements["name"].context.should == name.context
+ it "returns the added child" do
+ name = @root.add_element "name"
+ @root.elements["name"].name.should == name.name
+ @root.elements["name"].attributes.should == name.attributes
+ @root.elements["name"].context.should == name.context
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/add_namespace_spec.rb b/spec/ruby/library/rexml/element/add_namespace_spec.rb
index 77c00eec46..44b074bac7 100644
--- a/spec/ruby/library/rexml/element/add_namespace_spec.rb
+++ b/spec/ruby/library/rexml/element/add_namespace_spec.rb
@@ -1,23 +1,26 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#add_namespace" do
- before :each do
- @elem = REXML::Element.new("person")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "adds a namespace to element" do
- @elem.add_namespace("foo", "bar")
- @elem.namespace("foo").should == "bar"
- end
+ describe "REXML::Element#add_namespace" do
+ before :each do
+ @elem = REXML::Element.new("person")
+ end
- it "accepts a prefix string as prefix" do
- @elem.add_namespace("xmlns:foo", "bar")
- @elem.namespace("foo").should == "bar"
- end
+ it "adds a namespace to element" do
+ @elem.add_namespace("foo", "bar")
+ @elem.namespace("foo").should == "bar"
+ end
+
+ it "accepts a prefix string as prefix" do
+ @elem.add_namespace("xmlns:foo", "bar")
+ @elem.namespace("foo").should == "bar"
+ end
- it "uses prefix as URI if uri is nil" do
- @elem.add_namespace("some_uri", nil)
- @elem.namespace.should == "some_uri"
+ it "uses prefix as URI if uri is nil" do
+ @elem.add_namespace("some_uri", nil)
+ @elem.namespace.should == "some_uri"
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/add_text_spec.rb b/spec/ruby/library/rexml/element/add_text_spec.rb
index 54e127bf4b..3a0531ad42 100644
--- a/spec/ruby/library/rexml/element/add_text_spec.rb
+++ b/spec/ruby/library/rexml/element/add_text_spec.rb
@@ -1,24 +1,27 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#add_text" do
- before :each do
- @name = REXML::Element.new "Name"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "adds text to an element" do
- @name.add_text "Ringo"
- @name.to_s.should == "<Name>Ringo</Name>"
- end
+ describe "REXML::Element#add_text" do
+ before :each do
+ @name = REXML::Element.new "Name"
+ end
- it "accepts a Text" do
- @name.add_text(REXML::Text.new("Ringo"))
- @name.to_s.should == "<Name>Ringo</Name>"
- end
+ it "adds text to an element" do
+ @name.add_text "Ringo"
+ @name.to_s.should == "<Name>Ringo</Name>"
+ end
+
+ it "accepts a Text" do
+ @name.add_text(REXML::Text.new("Ringo"))
+ @name.to_s.should == "<Name>Ringo</Name>"
+ end
- it "joins the new text with the old one" do
- @name.add_text "Ringo"
- @name.add_text " Starr"
- @name.to_s.should == "<Name>Ringo Starr</Name>"
+ it "joins the new text with the old one" do
+ @name.add_text "Ringo"
+ @name.add_text " Starr"
+ @name.to_s.should == "<Name>Ringo Starr</Name>"
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/attribute_spec.rb b/spec/ruby/library/rexml/element/attribute_spec.rb
index e40d612ef3..b223d3440c 100644
--- a/spec/ruby/library/rexml/element/attribute_spec.rb
+++ b/spec/ruby/library/rexml/element/attribute_spec.rb
@@ -1,17 +1,20 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#attribute" do
- it "returns an attribute by name" do
- person = REXML::Element.new "Person"
- attribute = REXML::Attribute.new("drink", "coffee")
- person.add_attribute(attribute)
- person.attribute("drink").should == attribute
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Element#attribute" do
+ it "returns an attribute by name" do
+ person = REXML::Element.new "Person"
+ attribute = REXML::Attribute.new("drink", "coffee")
+ person.add_attribute(attribute)
+ person.attribute("drink").should == attribute
+ end
- it "supports attributes inside namespaces" do
- e = REXML::Element.new("element")
- e.add_attributes({"xmlns:ns" => "http://some_uri"})
- e.attribute("ns", "ns").to_s.should == "http://some_uri"
+ it "supports attributes inside namespaces" do
+ e = REXML::Element.new("element")
+ e.add_attributes({"xmlns:ns" => "http://some_uri"})
+ e.attribute("ns", "ns").to_s.should == "http://some_uri"
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/attributes_spec.rb b/spec/ruby/library/rexml/element/attributes_spec.rb
index 8959b769a8..92bcecc40a 100644
--- a/spec/ruby/library/rexml/element/attributes_spec.rb
+++ b/spec/ruby/library/rexml/element/attributes_spec.rb
@@ -1,19 +1,22 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#attributes" do
- it "returns element's Attributes" do
- p = REXML::Element.new "Person"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- name = REXML::Attribute.new("name", "John")
- attrs = REXML::Attributes.new(p)
- attrs.add name
+ describe "REXML::Element#attributes" do
+ it "returns element's Attributes" do
+ p = REXML::Element.new "Person"
- p.add_attribute name
- p.attributes.should == attrs
- end
+ name = REXML::Attribute.new("name", "John")
+ attrs = REXML::Attributes.new(p)
+ attrs.add name
+
+ p.add_attribute name
+ p.attributes.should == attrs
+ end
- it "returns an empty hash if element has no attributes" do
- REXML::Element.new("Person").attributes.should == {}
+ it "returns an empty hash if element has no attributes" do
+ REXML::Element.new("Person").attributes.should == {}
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/cdatas_spec.rb b/spec/ruby/library/rexml/element/cdatas_spec.rb
index a371a5734b..988b2cb422 100644
--- a/spec/ruby/library/rexml/element/cdatas_spec.rb
+++ b/spec/ruby/library/rexml/element/cdatas_spec.rb
@@ -1,24 +1,27 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#cdatas" do
- before :each do
- @e = REXML::Element.new("Root")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns the array of children cdatas" do
- c = REXML::CData.new("Primary")
- d = REXML::CData.new("Secondary")
- @e << c
- @e << d
- @e.cdatas.should == [c, d]
- end
+ describe "REXML::Element#cdatas" do
+ before :each do
+ @e = REXML::Element.new("Root")
+ end
- it "freezes the returned array" do
- @e.cdatas.frozen?.should == true
- end
+ it "returns the array of children cdatas" do
+ c = REXML::CData.new("Primary")
+ d = REXML::CData.new("Secondary")
+ @e << c
+ @e << d
+ @e.cdatas.should == [c, d]
+ end
+
+ it "freezes the returned array" do
+ @e.cdatas.should.frozen?
+ end
- it "returns an empty array if element has no cdata" do
- @e.cdatas.should == []
+ it "returns an empty array if element has no cdata" do
+ @e.cdatas.should == []
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/clone_spec.rb b/spec/ruby/library/rexml/element/clone_spec.rb
index d26392db41..490e43181f 100644
--- a/spec/ruby/library/rexml/element/clone_spec.rb
+++ b/spec/ruby/library/rexml/element/clone_spec.rb
@@ -1,29 +1,32 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#clone" do
- before :each do
- @e = REXML::Element.new "a"
- end
- it "creates a copy of element" do
- @e.clone.to_s.should == @e.to_s
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "copies the attributes" do
- @e.add_attribute("foo", "bar")
- @e.clone.to_s.should == @e.to_s
- end
+ describe "REXML::Element#clone" do
+ before :each do
+ @e = REXML::Element.new "a"
+ end
+ it "creates a copy of element" do
+ @e.clone.to_s.should == @e.to_s
+ end
- it "does not copy the text" do
- @e.add_text "some text..."
- @e.clone.to_s.should_not == @e
- @e.clone.to_s.should == "<a/>"
- end
+ it "copies the attributes" do
+ @e.add_attribute("foo", "bar")
+ @e.clone.to_s.should == @e.to_s
+ end
+
+ it "does not copy the text" do
+ @e.add_text "some text..."
+ @e.clone.to_s.should_not == @e
+ @e.clone.to_s.should == "<a/>"
+ end
- it "does not copy the child elements" do
- b = REXML::Element.new "b"
- @e << b
- @e.clone.should_not == @e
- @e.clone.to_s.should == "<a/>"
+ it "does not copy the child elements" do
+ b = REXML::Element.new "b"
+ @e << b
+ @e.clone.should_not == @e
+ @e.clone.to_s.should == "<a/>"
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/comments_spec.rb b/spec/ruby/library/rexml/element/comments_spec.rb
index 9dac2cc5b8..84ab9a7469 100644
--- a/spec/ruby/library/rexml/element/comments_spec.rb
+++ b/spec/ruby/library/rexml/element/comments_spec.rb
@@ -1,20 +1,23 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#comments" do
- before :each do
- @e = REXML::Element.new "root"
- @c1 = REXML::Comment.new "this is a comment"
- @c2 = REXML::Comment.new "this is another comment"
- @e << @c1
- @e << @c2
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns the array of comments" do
- @e.comments.should == [@c1, @c2]
- end
+ describe "REXML::Element#comments" do
+ before :each do
+ @e = REXML::Element.new "root"
+ @c1 = REXML::Comment.new "this is a comment"
+ @c2 = REXML::Comment.new "this is another comment"
+ @e << @c1
+ @e << @c2
+ end
+
+ it "returns the array of comments" do
+ @e.comments.should == [@c1, @c2]
+ end
- it "returns a frozen object" do
- @e.comments.frozen?.should == true
+ it "returns a frozen object" do
+ @e.comments.should.frozen?
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/delete_attribute_spec.rb b/spec/ruby/library/rexml/element/delete_attribute_spec.rb
index 5c55c5efda..e2ba81eb0d 100644
--- a/spec/ruby/library/rexml/element/delete_attribute_spec.rb
+++ b/spec/ruby/library/rexml/element/delete_attribute_spec.rb
@@ -1,39 +1,42 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#delete_attribute" do
- before :each do
- @e = REXML::Element.new("Person")
- @attr = REXML::Attribute.new("name", "Sean")
- @e.add_attribute(@attr)
- end
-
- it "deletes an attribute from the element" do
- @e.delete_attribute("name")
- @e.attributes["name"].should be_nil
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
-# Bug was filled with a patch in Ruby's tracker #20298
- quarantine! do
- it "receives an Attribute" do
+ describe "REXML::Element#delete_attribute" do
+ before :each do
+ @e = REXML::Element.new("Person")
+ @attr = REXML::Attribute.new("name", "Sean")
@e.add_attribute(@attr)
- @e.delete_attribute(@attr)
+ end
+
+ it "deletes an attribute from the element" do
+ @e.delete_attribute("name")
@e.attributes["name"].should be_nil
end
- end
- # Docs say that it returns the removed attribute but then examples
- # show it returns the element with the attribute removed.
- # Also fixed in #20298
- it "returns the element with the attribute removed" do
- elem = @e.delete_attribute("name")
- elem.attributes.should be_empty
- elem.to_s.should eql("<Person/>")
- end
+ # Bug was filled with a patch in Ruby's tracker #20298
+ quarantine! do
+ it "receives an Attribute" do
+ @e.add_attribute(@attr)
+ @e.delete_attribute(@attr)
+ @e.attributes["name"].should be_nil
+ end
+ end
- it "returns nil if the attribute does not exist" do
- @e.delete_attribute("name")
- at = @e.delete_attribute("name")
- at.should be_nil
+ # Docs say that it returns the removed attribute but then examples
+ # show it returns the element with the attribute removed.
+ # Also fixed in #20298
+ it "returns the element with the attribute removed" do
+ elem = @e.delete_attribute("name")
+ elem.attributes.should be_empty
+ elem.to_s.should eql("<Person/>")
+ end
+
+ it "returns nil if the attribute does not exist" do
+ @e.delete_attribute("name")
+ at = @e.delete_attribute("name")
+ at.should be_nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/delete_element_spec.rb b/spec/ruby/library/rexml/element/delete_element_spec.rb
index 9417229bd4..c0b486a6f7 100644
--- a/spec/ruby/library/rexml/element/delete_element_spec.rb
+++ b/spec/ruby/library/rexml/element/delete_element_spec.rb
@@ -1,49 +1,52 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#delete_element" do
- before :each do
- @root = REXML::Element.new("root")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "deletes the child element" do
- node = REXML::Element.new("some_node")
- @root.add_element node
- @root.delete_element node
- @root.elements.size.should == 0
- end
+ describe "REXML::Element#delete_element" do
+ before :each do
+ @root = REXML::Element.new("root")
+ end
- it "deletes a child via XPath" do
- @root.add_element "some_node"
- @root.delete_element "some_node"
- @root.elements.size.should == 0
- end
+ it "deletes the child element" do
+ node = REXML::Element.new("some_node")
+ @root.add_element node
+ @root.delete_element node
+ @root.elements.size.should == 0
+ end
- it "deletes the child at index" do
- @root.add_element "some_node"
- @root.delete_element 1
- @root.elements.size.should == 0
- end
+ it "deletes a child via XPath" do
+ @root.add_element "some_node"
+ @root.delete_element "some_node"
+ @root.elements.size.should == 0
+ end
- # According to the docs this should return the deleted element
- # but it won't if it's an Element.
- it "deletes Element and returns it" do
- node = REXML::Element.new("some_node")
- @root.add_element node
- del_node = @root.delete_element node
- del_node.should == node
- end
+ it "deletes the child at index" do
+ @root.add_element "some_node"
+ @root.delete_element 1
+ @root.elements.size.should == 0
+ end
- # Note how passing the string will return the removed element
- # but passing the Element as above won't.
- it "deletes an element and returns it" do
- node = REXML::Element.new("some_node")
- @root.add_element node
- del_node = @root.delete_element "some_node"
- del_node.should == node
- end
+ # According to the docs this should return the deleted element
+ # but it won't if it's an Element.
+ it "deletes Element and returns it" do
+ node = REXML::Element.new("some_node")
+ @root.add_element node
+ del_node = @root.delete_element node
+ del_node.should == node
+ end
+
+ # Note how passing the string will return the removed element
+ # but passing the Element as above won't.
+ it "deletes an element and returns it" do
+ node = REXML::Element.new("some_node")
+ @root.add_element node
+ del_node = @root.delete_element "some_node"
+ del_node.should == node
+ end
- it "returns nil unless element exists" do
- @root.delete_element("something").should == nil
+ it "returns nil unless element exists" do
+ @root.delete_element("something").should == nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/delete_namespace_spec.rb b/spec/ruby/library/rexml/element/delete_namespace_spec.rb
index 8683a40cab..a7763d51e8 100644
--- a/spec/ruby/library/rexml/element/delete_namespace_spec.rb
+++ b/spec/ruby/library/rexml/element/delete_namespace_spec.rb
@@ -1,25 +1,28 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#delete_namespace" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- before :each do
- @doc = REXML::Document.new "<a xmlns:foo='bar' xmlns='twiddle'/>"
- end
+ describe "REXML::Element#delete_namespace" do
- it "deletes a namespace from the element" do
- @doc.root.delete_namespace 'foo'
- @doc.root.namespace("foo").should be_nil
- @doc.root.to_s.should == "<a xmlns='twiddle'/>"
- end
+ before :each do
+ @doc = REXML::Document.new "<a xmlns:foo='bar' xmlns='twiddle'/>"
+ end
- it "deletes default namespace when called with no args" do
- @doc.root.delete_namespace
- @doc.root.namespace.should be_empty
- @doc.root.to_s.should == "<a xmlns:foo='bar'/>"
- end
+ it "deletes a namespace from the element" do
+ @doc.root.delete_namespace 'foo'
+ @doc.root.namespace("foo").should be_nil
+ @doc.root.to_s.should == "<a xmlns='twiddle'/>"
+ end
+
+ it "deletes default namespace when called with no args" do
+ @doc.root.delete_namespace
+ @doc.root.namespace.should be_empty
+ @doc.root.to_s.should == "<a xmlns:foo='bar'/>"
+ end
- it "returns the element" do
- @doc.root.delete_namespace.should == @doc.root
+ it "returns the element" do
+ @doc.root.delete_namespace.should == @doc.root
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/document_spec.rb b/spec/ruby/library/rexml/element/document_spec.rb
index 24773580f2..754f27d8a0 100644
--- a/spec/ruby/library/rexml/element/document_spec.rb
+++ b/spec/ruby/library/rexml/element/document_spec.rb
@@ -1,16 +1,19 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#document" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns the element's document" do
- d = REXML::Document.new("<root><elem/></root>")
- d << REXML::XMLDecl.new
- d.root.document.should == d
- d.root.document.to_s.should == d.to_s
- end
+ describe "REXML::Element#document" do
+
+ it "returns the element's document" do
+ d = REXML::Document.new("<root><elem/></root>")
+ d << REXML::XMLDecl.new
+ d.root.document.should == d
+ d.root.document.to_s.should == d.to_s
+ end
- it "returns nil if it belongs to no document" do
- REXML::Element.new("standalone").document.should be_nil
+ it "returns nil if it belongs to no document" do
+ REXML::Element.new("standalone").document.should be_nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb b/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb
index 3c5da3f015..f2d779e577 100644
--- a/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb
+++ b/spec/ruby/library/rexml/element/each_element_with_attribute_spec.rb
@@ -1,35 +1,38 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#each_element_with_attributes" do
- before :each do
- @document = REXML::Element.new("people")
- @father = REXML::Element.new("Person")
- @father.attributes["name"] = "Joe"
- @son = REXML::Element.new("Child")
- @son.attributes["name"] = "Fred"
- @document.root << @father
- @document.root << @son
- @childs = []
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns childs with attribute" do
- @document.each_element_with_attribute("name") { |elem| @childs << elem }
- @childs[0].should == @father
- @childs[1].should == @son
- end
+ describe "REXML::Element#each_element_with_attributes" do
+ before :each do
+ @document = REXML::Element.new("people")
+ @father = REXML::Element.new("Person")
+ @father.attributes["name"] = "Joe"
+ @son = REXML::Element.new("Child")
+ @son.attributes["name"] = "Fred"
+ @document.root << @father
+ @document.root << @son
+ @childs = []
+ end
- it "takes attribute value as second argument" do
- @document.each_element_with_attribute("name", "Fred"){ |elem| elem.should == @son }
- end
+ it "returns childs with attribute" do
+ @document.each_element_with_attribute("name") { |elem| @childs << elem }
+ @childs[0].should == @father
+ @childs[1].should == @son
+ end
- it "takes max number of childs as third argument" do
- @document.each_element_with_attribute("name", nil, 1) { |elem| @childs << elem }
- @childs.size.should == 1
- @childs[0].should == @father
- end
+ it "takes attribute value as second argument" do
+ @document.each_element_with_attribute("name", "Fred"){ |elem| elem.should == @son }
+ end
+
+ it "takes max number of childs as third argument" do
+ @document.each_element_with_attribute("name", nil, 1) { |elem| @childs << elem }
+ @childs.size.should == 1
+ @childs[0].should == @father
+ end
- it "takes XPath filter as fourth argument" do
- @document.each_element_with_attribute("name", nil, 0, "Child"){ |elem| elem.should == @son}
+ it "takes XPath filter as fourth argument" do
+ @document.each_element_with_attribute("name", nil, 0, "Child"){ |elem| elem.should == @son}
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/each_element_with_text_spec.rb b/spec/ruby/library/rexml/element/each_element_with_text_spec.rb
index 5f9e5b85dc..8f9d062c99 100644
--- a/spec/ruby/library/rexml/element/each_element_with_text_spec.rb
+++ b/spec/ruby/library/rexml/element/each_element_with_text_spec.rb
@@ -1,31 +1,34 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#each_element_with_text" do
- before :each do
- @document = REXML::Element.new("people")
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- @joe = REXML::Element.new("Person")
- @joe.text = "Joe"
- @fred = REXML::Element.new("Person")
- @fred.text = "Fred"
- @another = REXML::Element.new("AnotherPerson")
- @another.text = "Fred"
- @document.root << @joe
- @document.root << @fred
- @document.root << @another
- @childs = []
- end
+ describe "REXML::Element#each_element_with_text" do
+ before :each do
+ @document = REXML::Element.new("people")
- it "returns childs with text" do
- @document.each_element_with_text("Joe"){|c| c.should == @joe}
- end
+ @joe = REXML::Element.new("Person")
+ @joe.text = "Joe"
+ @fred = REXML::Element.new("Person")
+ @fred.text = "Fred"
+ @another = REXML::Element.new("AnotherPerson")
+ @another.text = "Fred"
+ @document.root << @joe
+ @document.root << @fred
+ @document.root << @another
+ @childs = []
+ end
- it "takes max as second argument" do
- @document.each_element_with_text("Fred", 1){ |c| c.should == @fred}
- end
+ it "returns childs with text" do
+ @document.each_element_with_text("Joe"){|c| c.should == @joe}
+ end
+
+ it "takes max as second argument" do
+ @document.each_element_with_text("Fred", 1){ |c| c.should == @fred}
+ end
- it "takes XPath filter as third argument" do
- @document.each_element_with_text("Fred", 0, "Person"){ |c| c.should == @fred}
+ it "takes XPath filter as third argument" do
+ @document.each_element_with_text("Fred", 0, "Person"){ |c| c.should == @fred}
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/element_reference_spec.rb b/spec/ruby/library/rexml/element/element_reference_spec.rb
index 9660ff7507..9e5d371ce4 100644
--- a/spec/ruby/library/rexml/element/element_reference_spec.rb
+++ b/spec/ruby/library/rexml/element/element_reference_spec.rb
@@ -1,20 +1,23 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#[]" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- before :each do
- @doc = REXML::Document.new("<root foo='bar'></root>")
- @child = REXML::Element.new("child")
- @doc.root.add_element @child
- end
+ describe "REXML::Element#[]" do
- it "return attribute value if argument is string or symbol" do
- @doc.root[:foo].should == 'bar'
- @doc.root['foo'].should == 'bar'
- end
+ before :each do
+ @doc = REXML::Document.new("<root foo='bar'></root>")
+ @child = REXML::Element.new("child")
+ @doc.root.add_element @child
+ end
+
+ it "return attribute value if argument is string or symbol" do
+ @doc.root[:foo].should == 'bar'
+ @doc.root['foo'].should == 'bar'
+ end
- it "return nth element if argument is int" do
- @doc.root[0].should == @child
+ it "return nth element if argument is int" do
+ @doc.root[0].should == @child
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/get_text_spec.rb b/spec/ruby/library/rexml/element/get_text_spec.rb
index 8ee9ea0824..0fa8d7cb3f 100644
--- a/spec/ruby/library/rexml/element/get_text_spec.rb
+++ b/spec/ruby/library/rexml/element/get_text_spec.rb
@@ -1,18 +1,21 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#get_text" do
- before :each do
- @doc = REXML::Document.new "<p>some text<b>this is bold!</b> more text</p>"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns the first text child node" do
- @doc.root.get_text.value.should == "some text"
- @doc.root.get_text.should be_kind_of(REXML::Text)
- end
+ describe "REXML::Element#get_text" do
+ before :each do
+ @doc = REXML::Document.new "<p>some text<b>this is bold!</b> more text</p>"
+ end
+
+ it "returns the first text child node" do
+ @doc.root.get_text.value.should == "some text"
+ @doc.root.get_text.should be_kind_of(REXML::Text)
+ end
- it "returns text from an element matching path" do
- @doc.root.get_text("b").value.should == "this is bold!"
- @doc.root.get_text("b").should be_kind_of(REXML::Text)
+ it "returns text from an element matching path" do
+ @doc.root.get_text("b").value.should == "this is bold!"
+ @doc.root.get_text("b").should be_kind_of(REXML::Text)
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/has_attributes_spec.rb b/spec/ruby/library/rexml/element/has_attributes_spec.rb
index f89ec675f5..af3ce8ce1b 100644
--- a/spec/ruby/library/rexml/element/has_attributes_spec.rb
+++ b/spec/ruby/library/rexml/element/has_attributes_spec.rb
@@ -1,17 +1,20 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#has_attributes?" do
- before :each do
- @e = REXML::Element.new("test_elem")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns true when element has any attributes" do
- @e.add_attribute("name", "Joe")
- @e.has_attributes?.should be_true
- end
+ describe "REXML::Element#has_attributes?" do
+ before :each do
+ @e = REXML::Element.new("test_elem")
+ end
+
+ it "returns true when element has any attributes" do
+ @e.add_attribute("name", "Joe")
+ @e.has_attributes?.should be_true
+ end
- it "returns false if element has no attributes" do
- @e.has_attributes?.should be_false
+ it "returns false if element has no attributes" do
+ @e.has_attributes?.should be_false
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/has_elements_spec.rb b/spec/ruby/library/rexml/element/has_elements_spec.rb
index dc5fc9c25b..04c7fe01a5 100644
--- a/spec/ruby/library/rexml/element/has_elements_spec.rb
+++ b/spec/ruby/library/rexml/element/has_elements_spec.rb
@@ -1,18 +1,21 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#has_elements?" do
- before :each do
- @e = REXML::Element.new("root")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns true if element has child elements" do
- child = REXML::Element.new("child")
- @e << child
- @e.has_elements?.should be_true
- end
+ describe "REXML::Element#has_elements?" do
+ before :each do
+ @e = REXML::Element.new("root")
+ end
+
+ it "returns true if element has child elements" do
+ child = REXML::Element.new("child")
+ @e << child
+ @e.has_elements?.should be_true
+ end
- it "returns false if element doesn't have child elements" do
- @e.has_elements?.should be_false
+ it "returns false if element doesn't have child elements" do
+ @e.has_elements?.should be_false
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/has_text_spec.rb b/spec/ruby/library/rexml/element/has_text_spec.rb
index e9d5a176cb..de19fe0763 100644
--- a/spec/ruby/library/rexml/element/has_text_spec.rb
+++ b/spec/ruby/library/rexml/element/has_text_spec.rb
@@ -1,16 +1,19 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#has_text?" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns true if element has a Text child" do
- e = REXML::Element.new("Person")
- e.text = "My text"
- e.has_text?.should be_true
- end
+ describe "REXML::Element#has_text?" do
+
+ it "returns true if element has a Text child" do
+ e = REXML::Element.new("Person")
+ e.text = "My text"
+ e.has_text?.should be_true
+ end
- it "returns false if it has no Text childs" do
- e = REXML::Element.new("Person")
- e.has_text?.should be_false
+ it "returns false if it has no Text childs" do
+ e = REXML::Element.new("Person")
+ e.has_text?.should be_false
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/inspect_spec.rb b/spec/ruby/library/rexml/element/inspect_spec.rb
index f45edd0b1f..ec16c136ee 100644
--- a/spec/ruby/library/rexml/element/inspect_spec.rb
+++ b/spec/ruby/library/rexml/element/inspect_spec.rb
@@ -1,27 +1,30 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#inspect" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- before :each do
- @name = REXML::Element.new "name"
- end
+ describe "REXML::Element#inspect" do
- it "returns the node as a string" do
- @name.inspect.should == "<name/>"
- end
+ before :each do
+ @name = REXML::Element.new "name"
+ end
- it "inserts '...' if the node has children" do
- e = REXML::Element.new "last_name"
- @name << e
- @name.inspect.should == "<name> ... </>"
- # This might make more sense but differs from MRI's default behavior
- # @name.inspect.should == "<name> ... </name>"
- end
+ it "returns the node as a string" do
+ @name.inspect.should == "<name/>"
+ end
+
+ it "inserts '...' if the node has children" do
+ e = REXML::Element.new "last_name"
+ @name << e
+ @name.inspect.should == "<name> ... </>"
+ # This might make more sense but differs from MRI's default behavior
+ # @name.inspect.should == "<name> ... </name>"
+ end
- it "inserts the attributes in the string" do
- @name.add_attribute "language"
- @name.attributes["language"] = "english"
- @name.inspect.should == "<name language='english'/>"
+ it "inserts the attributes in the string" do
+ @name.add_attribute "language"
+ @name.attributes["language"] = "english"
+ @name.inspect.should == "<name language='english'/>"
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/instructions_spec.rb b/spec/ruby/library/rexml/element/instructions_spec.rb
index aa2d192e7c..11f1396df0 100644
--- a/spec/ruby/library/rexml/element/instructions_spec.rb
+++ b/spec/ruby/library/rexml/element/instructions_spec.rb
@@ -1,21 +1,24 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#instructions" do
- before :each do
- @elem = REXML::Element.new("root")
- end
- it "returns the Instruction children nodes" do
- inst = REXML::Instruction.new("xml-stylesheet", "href='headlines.css'")
- @elem << inst
- @elem.instructions.first.should == inst
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns an empty array if it has no Instruction children" do
- @elem.instructions.should be_empty
- end
+ describe "REXML::Element#instructions" do
+ before :each do
+ @elem = REXML::Element.new("root")
+ end
+ it "returns the Instruction children nodes" do
+ inst = REXML::Instruction.new("xml-stylesheet", "href='headlines.css'")
+ @elem << inst
+ @elem.instructions.first.should == inst
+ end
+
+ it "returns an empty array if it has no Instruction children" do
+ @elem.instructions.should be_empty
+ end
- it "freezes the returned array" do
- @elem.instructions.frozen?.should be_true
+ it "freezes the returned array" do
+ @elem.instructions.frozen?.should be_true
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/namespace_spec.rb b/spec/ruby/library/rexml/element/namespace_spec.rb
index 89662f3599..28966289c5 100644
--- a/spec/ruby/library/rexml/element/namespace_spec.rb
+++ b/spec/ruby/library/rexml/element/namespace_spec.rb
@@ -1,27 +1,30 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#namespace" do
- before :each do
- @doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
- @elem = @doc.elements["//b"]
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns the default namespace" do
- @elem.namespace.should == "1"
- end
+ describe "REXML::Element#namespace" do
+ before :each do
+ @doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
+ @elem = @doc.elements["//b"]
+ end
- it "accepts a namespace prefix" do
- @elem.namespace("y").should == "2"
- @doc.elements["//c"].namespace("z").should == "3"
- end
+ it "returns the default namespace" do
+ @elem.namespace.should == "1"
+ end
- it "returns an empty String if default namespace is not defined" do
- e = REXML::Document.new("<a/>")
- e.root.namespace.should be_empty
- end
+ it "accepts a namespace prefix" do
+ @elem.namespace("y").should == "2"
+ @doc.elements["//c"].namespace("z").should == "3"
+ end
+
+ it "returns an empty String if default namespace is not defined" do
+ e = REXML::Document.new("<a/>")
+ e.root.namespace.should be_empty
+ end
- it "returns nil if namespace is not defined" do
- @elem.namespace("z").should be_nil
+ it "returns nil if namespace is not defined" do
+ @elem.namespace("z").should be_nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/namespaces_spec.rb b/spec/ruby/library/rexml/element/namespaces_spec.rb
index a84c1d1dab..4544540173 100644
--- a/spec/ruby/library/rexml/element/namespaces_spec.rb
+++ b/spec/ruby/library/rexml/element/namespaces_spec.rb
@@ -1,32 +1,35 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#namespaces" do
- before :each do
- doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
- @elem = doc.elements["//c"]
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns a hash of the namespaces" do
- ns = {"y"=>"2", "z"=>"3", "xmlns"=>"1"}
- @elem.namespaces.keys.sort.should == ns.keys.sort
- @elem.namespaces.values.sort.should == ns.values.sort
- end
+ describe "REXML::Element#namespaces" do
+ before :each do
+ doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
+ @elem = doc.elements["//c"]
+ end
- it "returns an empty hash if no namespaces exist" do
- e = REXML::Element.new "element"
- e.namespaces.kind_of?(Hash).should == true
- e.namespaces.should be_empty
- end
+ it "returns a hash of the namespaces" do
+ ns = {"y"=>"2", "z"=>"3", "xmlns"=>"1"}
+ @elem.namespaces.keys.sort.should == ns.keys.sort
+ @elem.namespaces.values.sort.should == ns.values.sort
+ end
- it "uses namespace prefixes as keys" do
- prefixes = ["y", "z", "xmlns"]
- @elem.namespaces.keys.sort.should == prefixes.sort
- end
+ it "returns an empty hash if no namespaces exist" do
+ e = REXML::Element.new "element"
+ e.namespaces.kind_of?(Hash).should == true
+ e.namespaces.should be_empty
+ end
- it "uses namespace values as the hash values" do
- values = ["2", "3", "1"]
- @elem.namespaces.values.sort.should == values.sort
- end
+ it "uses namespace prefixes as keys" do
+ prefixes = ["y", "z", "xmlns"]
+ @elem.namespaces.keys.sort.should == prefixes.sort
+ end
+
+ it "uses namespace values as the hash values" do
+ values = ["2", "3", "1"]
+ @elem.namespaces.values.sort.should == values.sort
+ end
+ end
end
diff --git a/spec/ruby/library/rexml/element/new_spec.rb b/spec/ruby/library/rexml/element/new_spec.rb
index 4ffdf4dabe..c6ab289476 100644
--- a/spec/ruby/library/rexml/element/new_spec.rb
+++ b/spec/ruby/library/rexml/element/new_spec.rb
@@ -1,35 +1,38 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#new" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "creates element from tag name" do
- REXML::Element.new("foo").name.should == "foo"
- end
+ describe "REXML::Element#new" do
- it "creates element with default attributes" do
- e = REXML::Element.new
- e.name.should == REXML::Element::UNDEFINED
- e.context.should == nil
- e.parent.should == nil
- end
+ it "creates element from tag name" do
+ REXML::Element.new("foo").name.should == "foo"
+ end
- it "creates element from another element" do
- e = REXML::Element.new "foo"
- f = REXML::Element.new e
- e.name.should == f.name
- e.context.should == f.context
- e.parent.should == f.parent
- end
+ it "creates element with default attributes" do
+ e = REXML::Element.new
+ e.name.should == REXML::Element::UNDEFINED
+ e.context.should == nil
+ e.parent.should == nil
+ end
- it "takes parent as second argument" do
- parent = REXML::Element.new "foo"
- child = REXML::Element.new "bar", parent
- child.parent.should == parent
- end
+ it "creates element from another element" do
+ e = REXML::Element.new "foo"
+ f = REXML::Element.new e
+ e.name.should == f.name
+ e.context.should == f.context
+ e.parent.should == f.parent
+ end
+
+ it "takes parent as second argument" do
+ parent = REXML::Element.new "foo"
+ child = REXML::Element.new "bar", parent
+ child.parent.should == parent
+ end
- it "takes context as third argument" do
- context = {"some_key" => "some_value"}
- REXML::Element.new("foo", nil, context).context.should == context
+ it "takes context as third argument" do
+ context = {"some_key" => "some_value"}
+ REXML::Element.new("foo", nil, context).context.should == context
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/next_element_spec.rb b/spec/ruby/library/rexml/element/next_element_spec.rb
index 5b6d6cad9b..46d8f74760 100644
--- a/spec/ruby/library/rexml/element/next_element_spec.rb
+++ b/spec/ruby/library/rexml/element/next_element_spec.rb
@@ -1,19 +1,22 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#next_element" do
- before :each do
- @a = REXML::Element.new "a"
- @b = REXML::Element.new "b"
- @c = REXML::Element.new "c"
- @a.root << @b
- @a.root << @c
- end
- it "returns next existing element" do
- @a.elements["b"].next_element.should == @c
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Element#next_element" do
+ before :each do
+ @a = REXML::Element.new "a"
+ @b = REXML::Element.new "b"
+ @c = REXML::Element.new "c"
+ @a.root << @b
+ @a.root << @c
+ end
+ it "returns next existing element" do
+ @a.elements["b"].next_element.should == @c
+ end
- it "returns nil on last element" do
- @a.elements["c"].next_element.should == nil
+ it "returns nil on last element" do
+ @a.elements["c"].next_element.should == nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/node_type_spec.rb b/spec/ruby/library/rexml/element/node_type_spec.rb
index bcab9e126d..a39c2deca5 100644
--- a/spec/ruby/library/rexml/element/node_type_spec.rb
+++ b/spec/ruby/library/rexml/element/node_type_spec.rb
@@ -1,8 +1,11 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#node_type" do
- it "returns :element" do
- REXML::Element.new("MyElem").node_type.should == :element
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Element#node_type" do
+ it "returns :element" do
+ REXML::Element.new("MyElem").node_type.should == :element
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/prefixes_spec.rb b/spec/ruby/library/rexml/element/prefixes_spec.rb
index b6edf9a847..ea4caab4bc 100644
--- a/spec/ruby/library/rexml/element/prefixes_spec.rb
+++ b/spec/ruby/library/rexml/element/prefixes_spec.rb
@@ -1,23 +1,26 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#prefixes" do
- before :each do
- doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
- @elem = doc.elements["//c"]
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns an array of the prefixes of the namespaces" do
- @elem.prefixes.should == ["y", "z"]
- end
+ describe "REXML::Element#prefixes" do
+ before :each do
+ doc = REXML::Document.new("<a xmlns='1' xmlns:y='2'><b/><c xmlns:z='3'/></a>")
+ @elem = doc.elements["//c"]
+ end
- it "does not include the default namespace" do
- @elem.prefixes.include?("xmlns").should == false
- end
+ it "returns an array of the prefixes of the namespaces" do
+ @elem.prefixes.should == ["y", "z"]
+ end
+
+ it "does not include the default namespace" do
+ @elem.prefixes.include?("xmlns").should == false
+ end
- it "returns an empty array if no namespace was defined" do
- doc = REXML::Document.new "<root><something/></root>"
- root = doc.elements["//root"]
- root.prefixes.should == []
+ it "returns an empty array if no namespace was defined" do
+ doc = REXML::Document.new "<root><something/></root>"
+ root = doc.elements["//root"]
+ root.prefixes.should == []
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/previous_element_spec.rb b/spec/ruby/library/rexml/element/previous_element_spec.rb
index 2fe79d955f..a43b1ddd10 100644
--- a/spec/ruby/library/rexml/element/previous_element_spec.rb
+++ b/spec/ruby/library/rexml/element/previous_element_spec.rb
@@ -1,20 +1,23 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#previous_element" do
- before :each do
- @a = REXML::Element.new "a"
- @b = REXML::Element.new "b"
- @c = REXML::Element.new "c"
- @a.root << @b
- @a.root << @c
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns previous element" do
- @a.elements["c"].previous_element.should == @b
- end
+ describe "REXML::Element#previous_element" do
+ before :each do
+ @a = REXML::Element.new "a"
+ @b = REXML::Element.new "b"
+ @c = REXML::Element.new "c"
+ @a.root << @b
+ @a.root << @c
+ end
+
+ it "returns previous element" do
+ @a.elements["c"].previous_element.should == @b
+ end
- it "returns nil on first element" do
- @a.elements["b"].previous_element.should == nil
+ it "returns nil on first element" do
+ @a.elements["b"].previous_element.should == nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/raw_spec.rb b/spec/ruby/library/rexml/element/raw_spec.rb
index 404ccce5f4..200a99d194 100644
--- a/spec/ruby/library/rexml/element/raw_spec.rb
+++ b/spec/ruby/library/rexml/element/raw_spec.rb
@@ -1,24 +1,27 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#raw" do
- it "returns true if raw mode is set to all" do
- REXML::Element.new("MyElem", nil, {raw: :all}).raw.should == true
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns true if raw mode is set to expanded_name" do
- REXML::Element.new("MyElem", nil, {raw: "MyElem"}).raw.should == true
- end
+ describe "REXML::Element#raw" do
+ it "returns true if raw mode is set to all" do
+ REXML::Element.new("MyElem", nil, {raw: :all}).raw.should == true
+ end
- it "returns false if raw mode is not set" do
- REXML::Element.new("MyElem", nil, {raw: ""}).raw.should == false
- end
+ it "returns true if raw mode is set to expanded_name" do
+ REXML::Element.new("MyElem", nil, {raw: "MyElem"}).raw.should == true
+ end
- it "returns false if raw is not :all or expanded_name" do
- REXML::Element.new("MyElem", nil, {raw: "Something"}).raw.should == false
- end
+ it "returns false if raw mode is not set" do
+ REXML::Element.new("MyElem", nil, {raw: ""}).raw.should == false
+ end
+
+ it "returns false if raw is not :all or expanded_name" do
+ REXML::Element.new("MyElem", nil, {raw: "Something"}).raw.should == false
+ end
- it "returns nil if context is not set" do
- REXML::Element.new("MyElem").raw.should == nil
+ it "returns nil if context is not set" do
+ REXML::Element.new("MyElem").raw.should == nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/root_spec.rb b/spec/ruby/library/rexml/element/root_spec.rb
index 1e0669033e..52aa4571b9 100644
--- a/spec/ruby/library/rexml/element/root_spec.rb
+++ b/spec/ruby/library/rexml/element/root_spec.rb
@@ -1,28 +1,31 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Element#root" do
- before :each do
- @doc = REXML::Document.new
- @root = REXML::Element.new "root"
- @node = REXML::Element.new "node"
- @doc << @root << @node
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns first child on documents" do
- @doc.root.should == @root
- end
+ describe "REXML::Element#root" do
+ before :each do
+ @doc = REXML::Document.new
+ @root = REXML::Element.new "root"
+ @node = REXML::Element.new "node"
+ @doc << @root << @node
+ end
- it "returns self on root nodes" do
- @root.root.should == @root
- end
+ it "returns first child on documents" do
+ @doc.root.should == @root
+ end
- it "returns parent's root on child nodes" do
- @node.root.should == @root
- end
+ it "returns self on root nodes" do
+ @root.root.should == @root
+ end
+
+ it "returns parent's root on child nodes" do
+ @node.root.should == @root
+ end
- it "returns self on standalone nodes" do
- e = REXML::Element.new "Elem" # Note that it doesn't have a parent node
- e.root.should == e
+ it "returns self on standalone nodes" do
+ e = REXML::Element.new "Elem" # Note that it doesn't have a parent node
+ e.root.should == e
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/text_spec.rb b/spec/ruby/library/rexml/element/text_spec.rb
index 7c290c4cda..3234bba153 100644
--- a/spec/ruby/library/rexml/element/text_spec.rb
+++ b/spec/ruby/library/rexml/element/text_spec.rb
@@ -1,46 +1,49 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#text" do
- before :each do
- @e = REXML::Element.new "name"
- @e.text = "John"
- end
-
- it "returns the text node of element" do
- @e.text.should == "John"
- end
-
- it "returns the text node value" do
- t = REXML::Text.new "Joe"
- @e.text = t
- @e.text.should == "Joe"
- @e.text.should_not == t
- end
-
- it "returns nil if no text is attached" do
- elem = REXML::Element.new "name"
- elem.text.should == nil
- end
-end
-
-describe "REXML::Element#text=" do
- before :each do
- @e = REXML::Element.new "name"
- @e.text = "John"
- end
-
- it "sets the text node" do
- @e.to_s.should == "<name>John</name>"
- end
-
- it "replaces existing text" do
- @e.text = "Joe"
- @e.to_s.should == "<name>Joe</name>"
- end
-
- it "receives nil as an argument" do
- @e.text = nil
- @e.to_s.should == "<name/>"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Element#text" do
+ before :each do
+ @e = REXML::Element.new "name"
+ @e.text = "John"
+ end
+
+ it "returns the text node of element" do
+ @e.text.should == "John"
+ end
+
+ it "returns the text node value" do
+ t = REXML::Text.new "Joe"
+ @e.text = t
+ @e.text.should == "Joe"
+ @e.text.should_not == t
+ end
+
+ it "returns nil if no text is attached" do
+ elem = REXML::Element.new "name"
+ elem.text.should == nil
+ end
+ end
+
+ describe "REXML::Element#text=" do
+ before :each do
+ @e = REXML::Element.new "name"
+ @e.text = "John"
+ end
+
+ it "sets the text node" do
+ @e.to_s.should == "<name>John</name>"
+ end
+
+ it "replaces existing text" do
+ @e.text = "Joe"
+ @e.to_s.should == "<name>Joe</name>"
+ end
+
+ it "receives nil as an argument" do
+ @e.text = nil
+ @e.to_s.should == "<name/>"
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/texts_spec.rb b/spec/ruby/library/rexml/element/texts_spec.rb
index 7975833c89..2d374d5e66 100644
--- a/spec/ruby/library/rexml/element/texts_spec.rb
+++ b/spec/ruby/library/rexml/element/texts_spec.rb
@@ -1,16 +1,19 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#texts" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns an array of the Text children" do
- e = REXML::Element.new("root")
- e.add_text "First"
- e.add_text "Second"
- e.texts.should == ["FirstSecond"]
- end
+ describe "REXML::Element#texts" do
+
+ it "returns an array of the Text children" do
+ e = REXML::Element.new("root")
+ e.add_text "First"
+ e.add_text "Second"
+ e.texts.should == ["FirstSecond"]
+ end
- it "returns an empty array if it has no Text children" do
- REXML::Element.new("root").texts.should == []
+ it "returns an empty array if it has no Text children" do
+ REXML::Element.new("root").texts.should == []
+ end
end
end
diff --git a/spec/ruby/library/rexml/element/whitespace_spec.rb b/spec/ruby/library/rexml/element/whitespace_spec.rb
index dc785ae5ce..f455067922 100644
--- a/spec/ruby/library/rexml/element/whitespace_spec.rb
+++ b/spec/ruby/library/rexml/element/whitespace_spec.rb
@@ -1,23 +1,26 @@
-require 'rexml/document'
require_relative '../../../spec_helper'
-describe "REXML::Element#whitespace" do
- it "returns true if whitespace is respected in the element" do
- e = REXML::Element.new("root")
- e.whitespace.should be_true
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- e = REXML::Element.new("root", nil, respect_whitespace: :all)
- e.whitespace.should be_true
+ describe "REXML::Element#whitespace" do
+ it "returns true if whitespace is respected in the element" do
+ e = REXML::Element.new("root")
+ e.whitespace.should be_true
- e = REXML::Element.new("root", nil, respect_whitespace: ["root"])
- e.whitespace.should be_true
- end
+ e = REXML::Element.new("root", nil, respect_whitespace: :all)
+ e.whitespace.should be_true
+
+ e = REXML::Element.new("root", nil, respect_whitespace: ["root"])
+ e.whitespace.should be_true
+ end
- it "returns false if whitespace is ignored inside element" do
- e = REXML::Element.new("root", nil, compress_whitespace: :all)
- e.whitespace.should be_false
+ it "returns false if whitespace is ignored inside element" do
+ e = REXML::Element.new("root", nil, compress_whitespace: :all)
+ e.whitespace.should be_false
- e = REXML::Element.new("root", nil, compress_whitespace: ["root"])
- e.whitespace.should be_false
+ e = REXML::Element.new("root", nil, compress_whitespace: ["root"])
+ e.whitespace.should be_false
+ end
end
end
diff --git a/spec/ruby/library/rexml/node/each_recursive_spec.rb b/spec/ruby/library/rexml/node/each_recursive_spec.rb
index dd4aa9a2f2..da347b1389 100644
--- a/spec/ruby/library/rexml/node/each_recursive_spec.rb
+++ b/spec/ruby/library/rexml/node/each_recursive_spec.rb
@@ -1,21 +1,24 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Node#each_recursive" do
- before :each do
- @doc = REXML::Document.new
- @doc << REXML::XMLDecl.new
- @root = REXML::Element.new "root"
- @child1 = REXML::Element.new "child1"
- @child2 = REXML::Element.new "child2"
- @root << @child1
- @root << @child2
- @doc << @root
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Node#each_recursive" do
+ before :each do
+ @doc = REXML::Document.new
+ @doc << REXML::XMLDecl.new
+ @root = REXML::Element.new "root"
+ @child1 = REXML::Element.new "child1"
+ @child2 = REXML::Element.new "child2"
+ @root << @child1
+ @root << @child2
+ @doc << @root
+ end
- it "visits all subnodes of self" do
- nodes = []
- @doc.each_recursive { |node| nodes << node}
- nodes.should == [@root, @child1, @child2]
+ it "visits all subnodes of self" do
+ nodes = []
+ @doc.each_recursive { |node| nodes << node}
+ nodes.should == [@root, @child1, @child2]
+ end
end
end
diff --git a/spec/ruby/library/rexml/node/find_first_recursive_spec.rb b/spec/ruby/library/rexml/node/find_first_recursive_spec.rb
index ba46f2ca35..2a4f1097ae 100644
--- a/spec/ruby/library/rexml/node/find_first_recursive_spec.rb
+++ b/spec/ruby/library/rexml/node/find_first_recursive_spec.rb
@@ -1,25 +1,28 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Node#find_first_recursive" do
- before :each do
- @e = REXML::Element.new("root")
- @node1 = REXML::Element.new("node")
- @node2 = REXML::Element.new("another node")
- @subnode = REXML::Element.new("another node")
- @node1 << @subnode
- @e << @node1
- @e << @node2
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "finds the first element that matches block" do
- found = @e.find_first_recursive { |n| n.to_s == "<node><another node/></node>"}
- found.should == @node1
- end
+ describe "REXML::Node#find_first_recursive" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @node1 = REXML::Element.new("node")
+ @node2 = REXML::Element.new("another node")
+ @subnode = REXML::Element.new("another node")
+ @node1 << @subnode
+ @e << @node1
+ @e << @node2
+ end
+
+ it "finds the first element that matches block" do
+ found = @e.find_first_recursive { |n| n.to_s == "<node><another node/></node>"}
+ found.should == @node1
+ end
- it "visits the nodes in preorder" do
- found = @e.find_first_recursive { |n| n.to_s == "<another node/>"}
- found.should == @subnode
- found.should_not == @node2
+ it "visits the nodes in preorder" do
+ found = @e.find_first_recursive { |n| n.to_s == "<another node/>"}
+ found.should == @subnode
+ found.should_not == @node2
+ end
end
end
diff --git a/spec/ruby/library/rexml/node/index_in_parent_spec.rb b/spec/ruby/library/rexml/node/index_in_parent_spec.rb
index 092851e3e7..55909f86d6 100644
--- a/spec/ruby/library/rexml/node/index_in_parent_spec.rb
+++ b/spec/ruby/library/rexml/node/index_in_parent_spec.rb
@@ -1,15 +1,18 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Node#index_in_parent" do
- it "returns the index (starting from 1) of self in parent" do
- e = REXML::Element.new("root")
- node1 = REXML::Element.new("node")
- node2 = REXML::Element.new("another node")
- e << node1
- e << node2
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- node1.index_in_parent.should == 1
- node2.index_in_parent.should == 2
+ describe "REXML::Node#index_in_parent" do
+ it "returns the index (starting from 1) of self in parent" do
+ e = REXML::Element.new("root")
+ node1 = REXML::Element.new("node")
+ node2 = REXML::Element.new("another node")
+ e << node1
+ e << node2
+
+ node1.index_in_parent.should == 1
+ node2.index_in_parent.should == 2
+ end
end
end
diff --git a/spec/ruby/library/rexml/node/next_sibling_node_spec.rb b/spec/ruby/library/rexml/node/next_sibling_node_spec.rb
index 2e8601627d..7aae861d75 100644
--- a/spec/ruby/library/rexml/node/next_sibling_node_spec.rb
+++ b/spec/ruby/library/rexml/node/next_sibling_node_spec.rb
@@ -1,21 +1,24 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Node#next_sibling_node" do
- before :each do
- @e = REXML::Element.new("root")
- @node1 = REXML::Element.new("node")
- @node2 = REXML::Element.new("another node")
- @e << @node1
- @e << @node2
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns the next child node in parent" do
- @node1.next_sibling_node.should == @node2
- end
+ describe "REXML::Node#next_sibling_node" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @node1 = REXML::Element.new("node")
+ @node2 = REXML::Element.new("another node")
+ @e << @node1
+ @e << @node2
+ end
+
+ it "returns the next child node in parent" do
+ @node1.next_sibling_node.should == @node2
+ end
- it "returns nil if there are no more child nodes next" do
- @node2.next_sibling_node.should == nil
- @e.next_sibling_node.should == nil
+ it "returns nil if there are no more child nodes next" do
+ @node2.next_sibling_node.should == nil
+ @e.next_sibling_node.should == nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/node/parent_spec.rb b/spec/ruby/library/rexml/node/parent_spec.rb
index d88ba69657..07425e8f36 100644
--- a/spec/ruby/library/rexml/node/parent_spec.rb
+++ b/spec/ruby/library/rexml/node/parent_spec.rb
@@ -1,20 +1,23 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Node#parent?" do
- it "returns true for Elements" do
- e = REXML::Element.new("foo")
- e.parent?.should == true
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns true for Documents" do
- e = REXML::Document.new
- e.parent?.should == true
- end
+ describe "REXML::Node#parent?" do
+ it "returns true for Elements" do
+ e = REXML::Element.new("foo")
+ e.should.parent?
+ end
+
+ it "returns true for Documents" do
+ e = REXML::Document.new
+ e.should.parent?
+ end
- # This includes attributes, CDatas and declarations.
- it "returns false for Texts" do
- e = REXML::Text.new("foo")
- e.parent?.should == false
+ # This includes attributes, CDatas and declarations.
+ it "returns false for Texts" do
+ e = REXML::Text.new("foo")
+ e.should_not.parent?
+ end
end
end
diff --git a/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb b/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb
index 8b96f1565a..11263968a7 100644
--- a/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb
+++ b/spec/ruby/library/rexml/node/previous_sibling_node_spec.rb
@@ -1,21 +1,24 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Node#previous_sibling_node" do
- before :each do
- @e = REXML::Element.new("root")
- @node1 = REXML::Element.new("node")
- @node2 = REXML::Element.new("another node")
- @e << @node1
- @e << @node2
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns the previous child node in parent" do
- @node2.previous_sibling_node.should == @node1
- end
+ describe "REXML::Node#previous_sibling_node" do
+ before :each do
+ @e = REXML::Element.new("root")
+ @node1 = REXML::Element.new("node")
+ @node2 = REXML::Element.new("another node")
+ @e << @node1
+ @e << @node2
+ end
+
+ it "returns the previous child node in parent" do
+ @node2.previous_sibling_node.should == @node1
+ end
- it "returns nil if there are no more child nodes before" do
- @node1.previous_sibling_node.should == nil
- @e.previous_sibling_node.should == nil
+ it "returns nil if there are no more child nodes before" do
+ @node1.previous_sibling_node.should == nil
+ @e.previous_sibling_node.should == nil
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/append_spec.rb b/spec/ruby/library/rexml/text/append_spec.rb
index de281fb0b0..5e7a5bae7c 100644
--- a/spec/ruby/library/rexml/text/append_spec.rb
+++ b/spec/ruby/library/rexml/text/append_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#<<" do
- it "appends a string to this text node" do
- text = REXML::Text.new("foo")
- text << "bar"
- text.should == "foobar"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Text#<<" do
+ it "appends a string to this text node" do
+ text = REXML::Text.new("foo")
+ text << "bar"
+ text.should == "foobar"
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/clone_spec.rb b/spec/ruby/library/rexml/text/clone_spec.rb
index 8031e140c7..7801782ff5 100644
--- a/spec/ruby/library/rexml/text/clone_spec.rb
+++ b/spec/ruby/library/rexml/text/clone_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#clone" do
- it "creates a copy of this node" do
- text = REXML::Text.new("foo")
- text.clone.should == "foo"
- text.clone.should == text
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Text#clone" do
+ it "creates a copy of this node" do
+ text = REXML::Text.new("foo")
+ text.clone.should == "foo"
+ text.clone.should == text
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/comparison_spec.rb b/spec/ruby/library/rexml/text/comparison_spec.rb
index 8bc5d66a03..119dd050a6 100644
--- a/spec/ruby/library/rexml/text/comparison_spec.rb
+++ b/spec/ruby/library/rexml/text/comparison_spec.rb
@@ -1,25 +1,28 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#<=>" do
- before :each do
- @first = REXML::Text.new("abc")
- @last = REXML::Text.new("def")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "returns -1 if lvalue is less than rvalue" do
- val = @first <=> @last
- val.should == -1
- end
+ describe "REXML::Text#<=>" do
+ before :each do
+ @first = REXML::Text.new("abc")
+ @last = REXML::Text.new("def")
+ end
- it "returns -1 if lvalue is greater than rvalue" do
- val = @last <=> @first
- val.should == 1
- end
+ it "returns -1 if lvalue is less than rvalue" do
+ val = @first <=> @last
+ val.should == -1
+ end
+
+ it "returns -1 if lvalue is greater than rvalue" do
+ val = @last <=> @first
+ val.should == 1
+ end
- it "returns 0 if both values are equal" do
- tmp = REXML::Text.new("tmp")
- val = tmp <=> tmp
- val.should == 0
+ it "returns 0 if both values are equal" do
+ tmp = REXML::Text.new("tmp")
+ val = tmp <=> tmp
+ val.should == 0
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/empty_spec.rb b/spec/ruby/library/rexml/text/empty_spec.rb
index d0b66b7a2a..4c9c899bcb 100644
--- a/spec/ruby/library/rexml/text/empty_spec.rb
+++ b/spec/ruby/library/rexml/text/empty_spec.rb
@@ -1,12 +1,15 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#empty?" do
- it "returns true if the text is empty" do
- REXML::Text.new("").empty?.should == true
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Text#empty?" do
+ it "returns true if the text is empty" do
+ REXML::Text.new("").should.empty?
+ end
- it "returns false if the text is not empty" do
- REXML::Text.new("some_text").empty?.should == false
+ it "returns false if the text is not empty" do
+ REXML::Text.new("some_text").should_not.empty?
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/indent_text_spec.rb b/spec/ruby/library/rexml/text/indent_text_spec.rb
index 1b0ee5ab16..73065c37da 100644
--- a/spec/ruby/library/rexml/text/indent_text_spec.rb
+++ b/spec/ruby/library/rexml/text/indent_text_spec.rb
@@ -1,23 +1,26 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#indent_text" do
- before :each do
- @t = REXML::Text.new("")
- end
- it "indents a string with default parameters" do
- @t.indent_text("foo").should == "\tfoo"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "accepts a custom indentation level as second argument" do
- @t.indent_text("foo", 2, "\t", true).should == "\t\tfoo"
- end
+ describe "REXML::Text#indent_text" do
+ before :each do
+ @t = REXML::Text.new("")
+ end
+ it "indents a string with default parameters" do
+ @t.indent_text("foo").should == "\tfoo"
+ end
- it "accepts a custom separator as third argument" do
- @t.indent_text("foo", 1, "\n", true).should == "\nfoo"
- end
+ it "accepts a custom indentation level as second argument" do
+ @t.indent_text("foo", 2, "\t", true).should == "\t\tfoo"
+ end
+
+ it "accepts a custom separator as third argument" do
+ @t.indent_text("foo", 1, "\n", true).should == "\nfoo"
+ end
- it "accepts a fourth parameter to skip the first line" do
- @t.indent_text("foo", 1, "\t", false).should == "foo"
+ it "accepts a fourth parameter to skip the first line" do
+ @t.indent_text("foo", 1, "\t", false).should == "foo"
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/inspect_spec.rb b/spec/ruby/library/rexml/text/inspect_spec.rb
index 0d66088a64..af389890ee 100644
--- a/spec/ruby/library/rexml/text/inspect_spec.rb
+++ b/spec/ruby/library/rexml/text/inspect_spec.rb
@@ -1,8 +1,11 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#inspect" do
- it "inspects the string attribute as a string" do
- REXML::Text.new("a text").inspect.should == "a text".inspect
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Text#inspect" do
+ it "inspects the string attribute as a string" do
+ REXML::Text.new("a text").inspect.should == "a text".inspect
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/new_spec.rb b/spec/ruby/library/rexml/text/new_spec.rb
index 3c081dec30..8b33da9294 100644
--- a/spec/ruby/library/rexml/text/new_spec.rb
+++ b/spec/ruby/library/rexml/text/new_spec.rb
@@ -1,48 +1,51 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text.new" do
-
- it "creates a Text child node with no parent" do
- t = REXML::Text.new("test")
- t.should be_kind_of(REXML::Child)
- t.should == "test"
- t.parent.should == nil
- end
-
- it "respects whitespace if second argument is true" do
- t = REXML::Text.new("testing whitespace", true)
- t.should == "testing whitespace"
- t = REXML::Text.new(" ", true)
- t.should == " "
- end
-
- it "receives a parent as third argument" do
- e = REXML::Element.new("root")
- t = REXML::Text.new("test", false, e)
- t.parent.should == e
- e.to_s.should == "<root>test</root>"
- end
-
- it "expects escaped text if raw is true" do
- t = REXML::Text.new("&lt;&amp;&gt;", false, nil, true)
- t.should == "&lt;&amp;&gt;"
-
- ->{ REXML::Text.new("<&>", false, nil, true)}.should raise_error(Exception)
- end
-
- it "uses raw value of the parent if raw is nil" do
- e1 = REXML::Element.new("root", nil, { raw: :all})
- -> {REXML::Text.new("<&>", false, e1)}.should raise_error(Exception)
-
- e2 = REXML::Element.new("root", nil, { raw: []})
- e2.raw.should be_false
- t1 = REXML::Text.new("<&>", false, e2)
- t1.should == "&lt;&amp;&gt;"
- end
-
- it "escapes the values if raw is false" do
- t = REXML::Text.new("<&>", false, nil, false)
- t.should == "&lt;&amp;&gt;"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Text.new" do
+
+ it "creates a Text child node with no parent" do
+ t = REXML::Text.new("test")
+ t.should be_kind_of(REXML::Child)
+ t.should == "test"
+ t.parent.should == nil
+ end
+
+ it "respects whitespace if second argument is true" do
+ t = REXML::Text.new("testing whitespace", true)
+ t.should == "testing whitespace"
+ t = REXML::Text.new(" ", true)
+ t.should == " "
+ end
+
+ it "receives a parent as third argument" do
+ e = REXML::Element.new("root")
+ t = REXML::Text.new("test", false, e)
+ t.parent.should == e
+ e.to_s.should == "<root>test</root>"
+ end
+
+ it "expects escaped text if raw is true" do
+ t = REXML::Text.new("&lt;&amp;&gt;", false, nil, true)
+ t.should == "&lt;&amp;&gt;"
+
+ ->{ REXML::Text.new("<&>", false, nil, true)}.should raise_error(Exception)
+ end
+
+ it "uses raw value of the parent if raw is nil" do
+ e1 = REXML::Element.new("root", nil, { raw: :all})
+ -> {REXML::Text.new("<&>", false, e1)}.should raise_error(Exception)
+
+ e2 = REXML::Element.new("root", nil, { raw: []})
+ e2.raw.should be_false
+ t1 = REXML::Text.new("<&>", false, e2)
+ t1.should == "&lt;&amp;&gt;"
+ end
+
+ it "escapes the values if raw is false" do
+ t = REXML::Text.new("<&>", false, nil, false)
+ t.should == "&lt;&amp;&gt;"
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/node_type_spec.rb b/spec/ruby/library/rexml/text/node_type_spec.rb
index 1c25a74dad..f44a1ede3e 100644
--- a/spec/ruby/library/rexml/text/node_type_spec.rb
+++ b/spec/ruby/library/rexml/text/node_type_spec.rb
@@ -1,8 +1,11 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#node_type" do
- it "returns :text" do
- REXML::Text.new("test").node_type.should == :text
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Text#node_type" do
+ it "returns :text" do
+ REXML::Text.new("test").node_type.should == :text
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/normalize_spec.rb b/spec/ruby/library/rexml/text/normalize_spec.rb
index ce3b2b3b5f..cde11ec3c9 100644
--- a/spec/ruby/library/rexml/text/normalize_spec.rb
+++ b/spec/ruby/library/rexml/text/normalize_spec.rb
@@ -1,8 +1,11 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text.normalize" do
- it "escapes a string with <, >, &, ' and \" " do
- REXML::Text.normalize("< > & \" '").should == "&lt; &gt; &amp; &quot; &apos;"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Text.normalize" do
+ it "escapes a string with <, >, &, ' and \" " do
+ REXML::Text.normalize("< > & \" '").should == "&lt; &gt; &amp; &quot; &apos;"
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/read_with_substitution_spec.rb b/spec/ruby/library/rexml/text/read_with_substitution_spec.rb
index 83b42f6d6b..7ff26f4d53 100644
--- a/spec/ruby/library/rexml/text/read_with_substitution_spec.rb
+++ b/spec/ruby/library/rexml/text/read_with_substitution_spec.rb
@@ -1,12 +1,15 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text.read_with_substitution" do
- it "reads a text and escapes entities" do
- REXML::Text.read_with_substitution("&lt; &gt; &amp; &quot; &apos;").should == "< > & \" '"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Text.read_with_substitution" do
+ it "reads a text and escapes entities" do
+ REXML::Text.read_with_substitution("&lt; &gt; &amp; &quot; &apos;").should == "< > & \" '"
+ end
- it "accepts an regex for invalid expressions and raises an error if text matches" do
- -> {REXML::Text.read_with_substitution("this is illegal", /illegal/)}.should raise_error(Exception)
+ it "accepts an regex for invalid expressions and raises an error if text matches" do
+ -> {REXML::Text.read_with_substitution("this is illegal", /illegal/)}.should raise_error(Exception)
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/to_s_spec.rb b/spec/ruby/library/rexml/text/to_s_spec.rb
index 14d7399a60..e67632c9a1 100644
--- a/spec/ruby/library/rexml/text/to_s_spec.rb
+++ b/spec/ruby/library/rexml/text/to_s_spec.rb
@@ -1,17 +1,20 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#to_s" do
- it "returns the string of this Text node" do
- u = REXML::Text.new("sean russell", false, nil, true)
- u.to_s.should == "sean russell"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- t = REXML::Text.new("some test text")
- t.to_s.should == "some test text"
- end
+ describe "REXML::Text#to_s" do
+ it "returns the string of this Text node" do
+ u = REXML::Text.new("sean russell", false, nil, true)
+ u.to_s.should == "sean russell"
+
+ t = REXML::Text.new("some test text")
+ t.to_s.should == "some test text"
+ end
- it "escapes the text" do
- t = REXML::Text.new("& < >")
- t.to_s.should == "&amp; &lt; &gt;"
+ it "escapes the text" do
+ t = REXML::Text.new("& < >")
+ t.to_s.should == "&amp; &lt; &gt;"
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/unnormalize_spec.rb b/spec/ruby/library/rexml/text/unnormalize_spec.rb
index 3072809c13..7b507194d0 100644
--- a/spec/ruby/library/rexml/text/unnormalize_spec.rb
+++ b/spec/ruby/library/rexml/text/unnormalize_spec.rb
@@ -1,8 +1,11 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text.unnormalize" do
- it "unescapes a string with the values defined in SETUTITSBUS" do
- REXML::Text.unnormalize("&lt; &gt; &amp; &quot; &apos;").should == "< > & \" '"
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
+
+ describe "REXML::Text.unnormalize" do
+ it "unescapes a string with the values defined in SETUTITSBUS" do
+ REXML::Text.unnormalize("&lt; &gt; &amp; &quot; &apos;").should == "< > & \" '"
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/value_spec.rb b/spec/ruby/library/rexml/text/value_spec.rb
index b0545b3cbd..53d40c765f 100644
--- a/spec/ruby/library/rexml/text/value_spec.rb
+++ b/spec/ruby/library/rexml/text/value_spec.rb
@@ -1,37 +1,40 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#value" do
- it "returns the text value of this node" do
- REXML::Text.new("test").value.should == "test"
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "does not escape entities" do
- REXML::Text.new("& \"").value.should == "& \""
- end
+ describe "REXML::Text#value" do
+ it "returns the text value of this node" do
+ REXML::Text.new("test").value.should == "test"
+ end
- it "follows the respect_whitespace attribute" do
- REXML::Text.new("test bar", false).value.should == "test bar"
- REXML::Text.new("test bar", true).value.should == "test bar"
- end
+ it "does not escape entities" do
+ REXML::Text.new("& \"").value.should == "& \""
+ end
- it "ignores the raw attribute" do
- REXML::Text.new("sean russell", false, nil, true).value.should == "sean russell"
- end
-end
+ it "follows the respect_whitespace attribute" do
+ REXML::Text.new("test bar", false).value.should == "test bar"
+ REXML::Text.new("test bar", true).value.should == "test bar"
+ end
-describe "REXML::Text#value=" do
- before :each do
- @t = REXML::Text.new("new")
+ it "ignores the raw attribute" do
+ REXML::Text.new("sean russell", false, nil, true).value.should == "sean russell"
+ end
end
- it "sets the text of the node" do
- @t.value = "another text"
- @t.to_s.should == "another text"
- end
+ describe "REXML::Text#value=" do
+ before :each do
+ @t = REXML::Text.new("new")
+ end
+
+ it "sets the text of the node" do
+ @t.value = "another text"
+ @t.to_s.should == "another text"
+ end
- it "escapes entities" do
- @t.value = "<a>"
- @t.to_s.should == "&lt;a&gt;"
+ it "escapes entities" do
+ @t.value = "<a>"
+ @t.to_s.should == "&lt;a&gt;"
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/wrap_spec.rb b/spec/ruby/library/rexml/text/wrap_spec.rb
index 0b60fd4151..331a8439e2 100644
--- a/spec/ruby/library/rexml/text/wrap_spec.rb
+++ b/spec/ruby/library/rexml/text/wrap_spec.rb
@@ -1,20 +1,23 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#wrap" do
- before :each do
- @t = REXML::Text.new("abc def")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "wraps the text at width" do
- @t.wrap("abc def", 3, false).should == "abc\ndef"
- end
+ describe "REXML::Text#wrap" do
+ before :each do
+ @t = REXML::Text.new("abc def")
+ end
- it "returns the string if width is greater than the size of the string" do
- @t.wrap("abc def", 10, false).should == "abc def"
- end
+ it "wraps the text at width" do
+ @t.wrap("abc def", 3, false).should == "abc\ndef"
+ end
+
+ it "returns the string if width is greater than the size of the string" do
+ @t.wrap("abc def", 10, false).should == "abc def"
+ end
- it "takes a newline at the beginning option as the third parameter" do
- @t.wrap("abc def", 3, true).should == "\nabc\ndef"
+ it "takes a newline at the beginning option as the third parameter" do
+ @t.wrap("abc def", 3, true).should == "\nabc\ndef"
+ end
end
end
diff --git a/spec/ruby/library/rexml/text/write_with_substitution_spec.rb b/spec/ruby/library/rexml/text/write_with_substitution_spec.rb
index ee79489d86..840f141e3d 100644
--- a/spec/ruby/library/rexml/text/write_with_substitution_spec.rb
+++ b/spec/ruby/library/rexml/text/write_with_substitution_spec.rb
@@ -1,33 +1,36 @@
require_relative '../../../spec_helper'
-require 'rexml/document'
-describe "REXML::Text#write_with_substitution" do
- before :each do
- @t = REXML::Text.new("test")
- @f = tmp("rexml_spec")
- @file = File.open(@f, "w+")
- end
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- after :each do
- @file.close
- rm_r @f
- end
+ describe "REXML::Text#write_with_substitution" do
+ before :each do
+ @t = REXML::Text.new("test")
+ @f = tmp("rexml_spec")
+ @file = File.open(@f, "w+")
+ end
- it "writes out the input to a String" do
- s = ""
- @t.write_with_substitution(s, "some text")
- s.should == "some text"
- end
+ after :each do
+ @file.close
+ rm_r @f
+ end
- it "writes out the input to an IO" do
- @t.write_with_substitution(@file, "some text")
- @file.rewind
- @file.gets.should == "some text"
- end
+ it "writes out the input to a String" do
+ s = ""
+ @t.write_with_substitution(s, "some text")
+ s.should == "some text"
+ end
+
+ it "writes out the input to an IO" do
+ @t.write_with_substitution(@file, "some text")
+ @file.rewind
+ @file.gets.should == "some text"
+ end
- it "escapes characters" do
- @t.write_with_substitution(@file, "& < >")
- @file.rewind
- @file.gets.should == "&amp; &lt; &gt;"
+ it "escapes characters" do
+ @t.write_with_substitution(@file, "& < >")
+ @file.rewind
+ @file.gets.should == "&amp; &lt; &gt;"
+ end
end
end
diff --git a/spec/ruby/library/ripper/lex_spec.rb b/spec/ruby/library/ripper/lex_spec.rb
new file mode 100644
index 0000000000..97cfb06904
--- /dev/null
+++ b/spec/ruby/library/ripper/lex_spec.rb
@@ -0,0 +1,23 @@
+require_relative '../../spec_helper'
+require 'ripper'
+
+describe "Ripper.lex" do
+ it "lexes a simple method declaration" do
+ expected = [
+ [[1, 0], :on_kw, "def", 'FNAME'],
+ [[1, 3], :on_sp, " ", 'FNAME'],
+ [[1, 4], :on_ident, "m", 'ENDFN'],
+ [[1, 5], :on_lparen, "(", 'BEG|LABEL'],
+ [[1, 6], :on_ident, "a", 'ARG'],
+ [[1, 7], :on_rparen, ")", 'ENDFN'],
+ [[1, 8], :on_sp, " ", 'BEG'],
+ [[1, 9], :on_kw, "nil", 'END'],
+ [[1, 12], :on_sp, " ", 'END'],
+ [[1, 13], :on_kw, "end", 'END']
+ ]
+ lexed = Ripper.lex("def m(a) nil end")
+ lexed.map { |e|
+ e[0...-1] + [e[-1].to_s.split('|').map { |s| s.sub(/^EXPR_/, '') }.join('|')]
+ }.should == expected
+ end
+end
diff --git a/spec/ruby/library/ripper/sexp_spec.rb b/spec/ruby/library/ripper/sexp_spec.rb
new file mode 100644
index 0000000000..6c69624c65
--- /dev/null
+++ b/spec/ruby/library/ripper/sexp_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../spec_helper'
+require 'ripper'
+
+describe "Ripper.sexp" do
+ it "returns an s-expression for a method declaration" do
+ expected = [:program,
+ [[:def,
+ [:@ident, "hello", [1, 4]],
+ [:params, nil, nil, nil, nil, nil, nil, nil],
+ [:bodystmt, [[:@int, "42", [1, 11]]], nil, nil, nil]]]]
+ Ripper.sexp("def hello; 42; end").should == expected
+ end
+end
diff --git a/spec/ruby/library/securerandom/random_number_spec.rb b/spec/ruby/library/securerandom/random_number_spec.rb
index 3e1812c6e8..03781f4901 100644
--- a/spec/ruby/library/securerandom/random_number_spec.rb
+++ b/spec/ruby/library/securerandom/random_number_spec.rb
@@ -10,7 +10,7 @@ describe "SecureRandom.random_number" do
it "generates a random positive number smaller then the positive integer argument" do
(1..64).each do |idx|
num = SecureRandom.random_number(idx)
- num.should be_kind_of(Fixnum)
+ num.should be_kind_of(Integer)
(0 <= num).should == true
(num < idx).should == true
end
diff --git a/spec/ruby/library/set/case_compare_spec.rb b/spec/ruby/library/set/case_compare_spec.rb
index 193006dbda..70d392a27d 100644
--- a/spec/ruby/library/set/case_compare_spec.rb
+++ b/spec/ruby/library/set/case_compare_spec.rb
@@ -2,13 +2,11 @@ require_relative '../../spec_helper'
require_relative 'shared/include'
require 'set'
-ruby_version_is "2.5" do
- describe "Set#===" do
- it_behaves_like :set_include, :===
+describe "Set#===" do
+ it_behaves_like :set_include, :===
- it "is an alias for include?" do
- set = Set.new
- set.method(:===).should == set.method(:include?)
- end
+ it "is an alias for include?" do
+ set = Set.new
+ set.method(:===).should == set.method(:include?)
end
end
diff --git a/spec/ruby/library/set/case_equality_spec.rb b/spec/ruby/library/set/case_equality_spec.rb
index 875630612e..10cbfd380a 100644
--- a/spec/ruby/library/set/case_equality_spec.rb
+++ b/spec/ruby/library/set/case_equality_spec.rb
@@ -2,8 +2,6 @@ require_relative '../../spec_helper'
require_relative 'shared/include'
require 'set'
-ruby_version_is "2.5" do
- describe "Set#===" do
- it_behaves_like :set_include, :===
- end
+describe "Set#===" do
+ it_behaves_like :set_include, :===
end
diff --git a/spec/ruby/library/set/compare_by_identity_spec.rb b/spec/ruby/library/set/compare_by_identity_spec.rb
index a6ad794ad3..9ed1602189 100644
--- a/spec/ruby/library/set/compare_by_identity_spec.rb
+++ b/spec/ruby/library/set/compare_by_identity_spec.rb
@@ -42,7 +42,7 @@ describe "Set#compare_by_identity" do
set = Set.new.compare_by_identity
set << :foo
set.compare_by_identity.should equal(set)
- set.compare_by_identity?.should == true
+ set.should.compare_by_identity?
set.to_a.should == [:foo]
end
@@ -91,11 +91,11 @@ describe "Set#compare_by_identity" do
set.to_a.sort.should == [a1, a2].sort
end
- it "raises a #{frozen_error_class} on frozen sets" do
+ it "raises a FrozenError on frozen sets" do
set = Set.new.freeze
-> {
set.compare_by_identity
- }.should raise_error(frozen_error_class, /frozen Hash/)
+ }.should raise_error(FrozenError, /frozen Hash/)
end
it "persists over #dups" do
@@ -124,20 +124,20 @@ end
describe "Set#compare_by_identity?" do
it "returns false by default" do
- Set.new.compare_by_identity?.should == false
+ Set.new.should_not.compare_by_identity?
end
it "returns true once #compare_by_identity has been invoked on self" do
set = Set.new
set.compare_by_identity
- set.compare_by_identity?.should == true
+ set.should.compare_by_identity?
end
it "returns true when called multiple times on the same set" do
set = Set.new
set.compare_by_identity
- set.compare_by_identity?.should == true
- set.compare_by_identity?.should == true
- set.compare_by_identity?.should == true
+ set.should.compare_by_identity?
+ set.should.compare_by_identity?
+ set.should.compare_by_identity?
end
end
diff --git a/spec/ruby/library/set/enumerable/to_set_spec.rb b/spec/ruby/library/set/enumerable/to_set_spec.rb
index 0f5504fef2..3790d8deee 100644
--- a/spec/ruby/library/set/enumerable/to_set_spec.rb
+++ b/spec/ruby/library/set/enumerable/to_set_spec.rb
@@ -7,10 +7,12 @@ describe "Enumerable#to_set" do
{a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]]
end
- it "allows passing an alternate class for Set" do
- sorted_set = [1, 2, 3].to_set(SortedSet)
- sorted_set.should == SortedSet[1, 2, 3]
- sorted_set.instance_of?(SortedSet).should == true
+ ruby_version_is ''...'3.0' do
+ it "allows passing an alternate class for Set" do
+ sorted_set = [1, 2, 3].to_set(SortedSet)
+ sorted_set.should == SortedSet[1, 2, 3]
+ sorted_set.instance_of?(SortedSet).should == true
+ end
end
it "passes down passed blocks" do
diff --git a/spec/ruby/library/set/sortedset/add_spec.rb b/spec/ruby/library/set/sortedset/add_spec.rb
index 5f8bde02f5..4f3bb252e1 100644
--- a/spec/ruby/library/set/sortedset/add_spec.rb
+++ b/spec/ruby/library/set/sortedset/add_spec.rb
@@ -1,39 +1,42 @@
require_relative '../../../spec_helper'
-require 'set'
-require_relative 'shared/add'
-describe "SortedSet#add" do
- it_behaves_like :sorted_set_add, :add
+ruby_version_is ""..."3.0" do
+ require 'set'
+ require_relative 'shared/add'
- it "takes only values which responds <=>" do
- obj = mock('no_comparison_operator')
- obj.stub!(:respond_to?).with(:<=>).and_return(false)
- -> { SortedSet["hello"].add(obj) }.should raise_error(ArgumentError)
- end
+ describe "SortedSet#add" do
+ it_behaves_like :sorted_set_add, :add
- it "raises on incompatible <=> comparison" do
- # Use #to_a here as elements are sorted only when needed.
- # Therefore the <=> incompatibility is only noticed on sorting.
- -> { SortedSet['1', '2'].add(3).to_a }.should raise_error(ArgumentError)
- end
-end
+ it "takes only values which responds <=>" do
+ obj = mock('no_comparison_operator')
+ obj.stub!(:respond_to?).with(:<=>).and_return(false)
+ -> { SortedSet["hello"].add(obj) }.should raise_error(ArgumentError)
+ end
-describe "SortedSet#add?" do
- before :each do
- @set = SortedSet.new
+ it "raises on incompatible <=> comparison" do
+ # Use #to_a here as elements are sorted only when needed.
+ # Therefore the <=> incompatibility is only noticed on sorting.
+ -> { SortedSet['1', '2'].add(3).to_a }.should raise_error(ArgumentError)
+ end
end
- it "adds the passed Object to self" do
- @set.add?("cat")
- @set.should include("cat")
- end
+ describe "SortedSet#add?" do
+ before :each do
+ @set = SortedSet.new
+ end
- it "returns self when the Object has not yet been added to self" do
- @set.add?("cat").should equal(@set)
- end
+ it "adds the passed Object to self" do
+ @set.add?("cat")
+ @set.should include("cat")
+ end
+
+ it "returns self when the Object has not yet been added to self" do
+ @set.add?("cat").should equal(@set)
+ end
- it "returns nil when the Object has already been added to self" do
- @set.add?("cat")
- @set.add?("cat").should be_nil
+ it "returns nil when the Object has already been added to self" do
+ @set.add?("cat")
+ @set.add?("cat").should be_nil
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/append_spec.rb b/spec/ruby/library/set/sortedset/append_spec.rb
index ebcceba962..d72d70b21f 100644
--- a/spec/ruby/library/set/sortedset/append_spec.rb
+++ b/spec/ruby/library/set/sortedset/append_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require 'set'
-require_relative 'shared/add'
-describe "SortedSet#<<" do
- it_behaves_like :sorted_set_add, :<<
+ruby_version_is ""..."3.0" do
+ require 'set'
+ require_relative 'shared/add'
+
+ describe "SortedSet#<<" do
+ it_behaves_like :sorted_set_add, :<<
+ end
end
diff --git a/spec/ruby/library/set/sortedset/case_equality_spec.rb b/spec/ruby/library/set/sortedset/case_equality_spec.rb
index 5627917677..d7c296b626 100644
--- a/spec/ruby/library/set/sortedset/case_equality_spec.rb
+++ b/spec/ruby/library/set/sortedset/case_equality_spec.rb
@@ -1,8 +1,9 @@
require_relative '../../../spec_helper'
-require_relative 'shared/include'
-require 'set'
-ruby_version_is "2.5" do
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/include'
+ require 'set'
+
describe "SortedSet#===" do
it_behaves_like :sorted_set_include, :===
end
diff --git a/spec/ruby/library/set/sortedset/classify_spec.rb b/spec/ruby/library/set/sortedset/classify_spec.rb
index 62b26d5d28..4011e58b82 100644
--- a/spec/ruby/library/set/sortedset/classify_spec.rb
+++ b/spec/ruby/library/set/sortedset/classify_spec.rb
@@ -1,27 +1,30 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#classify" do
- before :each do
- @set = SortedSet["one", "two", "three", "four"]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "yields each Object in self in sorted order" do
- res = []
- @set.classify { |x| res << x }
- res.should == ["one", "two", "three", "four"].sort
- end
+ describe "SortedSet#classify" do
+ before :each do
+ @set = SortedSet["one", "two", "three", "four"]
+ end
- it "returns an Enumerator when passed no block" do
- enum = @set.classify
- enum.should be_an_instance_of(Enumerator)
+ it "yields each Object in self in sorted order" do
+ res = []
+ @set.classify { |x| res << x }
+ res.should == ["one", "two", "three", "four"].sort
+ end
- classified = enum.each { |x| x.length }
- classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] }
- end
+ it "returns an Enumerator when passed no block" do
+ enum = @set.classify
+ enum.should be_an_instance_of(Enumerator)
+
+ classified = enum.each { |x| x.length }
+ classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] }
+ end
- it "classifies the Objects in self based on the block's return value" do
- classified = @set.classify { |x| x.length }
- classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] }
+ it "classifies the Objects in self based on the block's return value" do
+ classified = @set.classify { |x| x.length }
+ classified.should == { 3 => SortedSet["one", "two"], 4 => SortedSet["four"], 5 => SortedSet["three"] }
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/clear_spec.rb b/spec/ruby/library/set/sortedset/clear_spec.rb
index 11b5db2095..879aa824d8 100644
--- a/spec/ruby/library/set/sortedset/clear_spec.rb
+++ b/spec/ruby/library/set/sortedset/clear_spec.rb
@@ -1,17 +1,20 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#clear" do
- before :each do
- @set = SortedSet["one", "two", "three", "four"]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "removes all elements from self" do
- @set.clear
- @set.should be_empty
- end
+ describe "SortedSet#clear" do
+ before :each do
+ @set = SortedSet["one", "two", "three", "four"]
+ end
+
+ it "removes all elements from self" do
+ @set.clear
+ @set.should be_empty
+ end
- it "returns self" do
- @set.clear.should equal(@set)
+ it "returns self" do
+ @set.clear.should equal(@set)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/collect_spec.rb b/spec/ruby/library/set/sortedset/collect_spec.rb
index 21ead4fe55..0674f0d130 100644
--- a/spec/ruby/library/set/sortedset/collect_spec.rb
+++ b/spec/ruby/library/set/sortedset/collect_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require 'set'
-require_relative 'shared/collect'
-describe "SortedSet#collect!" do
- it_behaves_like :sorted_set_collect_bang, :collect!
+ruby_version_is ""..."3.0" do
+ require 'set'
+ require_relative 'shared/collect'
+
+ describe "SortedSet#collect!" do
+ it_behaves_like :sorted_set_collect_bang, :collect!
+ end
end
diff --git a/spec/ruby/library/set/sortedset/constructor_spec.rb b/spec/ruby/library/set/sortedset/constructor_spec.rb
index 953144dbdb..31f30fd892 100644
--- a/spec/ruby/library/set/sortedset/constructor_spec.rb
+++ b/spec/ruby/library/set/sortedset/constructor_spec.rb
@@ -1,15 +1,18 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet[]" do
- it "returns a new SortedSet populated with the passed Objects" do
- set = SortedSet[1, 2, 3]
+ruby_version_is ""..."3.0" do
+ require 'set'
- set.instance_of?(SortedSet).should be_true
- set.size.should eql(3)
+ describe "SortedSet[]" do
+ it "returns a new SortedSet populated with the passed Objects" do
+ set = SortedSet[1, 2, 3]
- set.should include(1)
- set.should include(2)
- set.should include(3)
+ set.instance_of?(SortedSet).should be_true
+ set.size.should eql(3)
+
+ set.should include(1)
+ set.should include(2)
+ set.should include(3)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/delete_if_spec.rb b/spec/ruby/library/set/sortedset/delete_if_spec.rb
index 1ff689376a..787639ae12 100644
--- a/spec/ruby/library/set/sortedset/delete_if_spec.rb
+++ b/spec/ruby/library/set/sortedset/delete_if_spec.rb
@@ -1,38 +1,41 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#delete_if" do
- before :each do
- @set = SortedSet["one", "two", "three"]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "yields each Object in self in sorted order" do
- ret = []
- @set.delete_if { |x| ret << x }
- ret.should == ["one", "two", "three"].sort
- end
+ describe "SortedSet#delete_if" do
+ before :each do
+ @set = SortedSet["one", "two", "three"]
+ end
- it "deletes every element from self for which the passed block returns true" do
- @set.delete_if { |x| x.size == 3 }
- @set.size.should eql(1)
+ it "yields each Object in self in sorted order" do
+ ret = []
+ @set.delete_if { |x| ret << x }
+ ret.should == ["one", "two", "three"].sort
+ end
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
- end
+ it "deletes every element from self for which the passed block returns true" do
+ @set.delete_if { |x| x.size == 3 }
+ @set.size.should eql(1)
- it "returns self" do
- @set.delete_if { |x| x }.should equal(@set)
- end
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+
+ it "returns self" do
+ @set.delete_if { |x| x }.should equal(@set)
+ end
- it "returns an Enumerator when passed no block" do
- enum = @set.delete_if
- enum.should be_an_instance_of(Enumerator)
+ it "returns an Enumerator when passed no block" do
+ enum = @set.delete_if
+ enum.should be_an_instance_of(Enumerator)
- enum.each { |x| x.size == 3 }
+ enum.each { |x| x.size == 3 }
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/delete_spec.rb b/spec/ruby/library/set/sortedset/delete_spec.rb
index 71583c7f13..0e2a6accf3 100644
--- a/spec/ruby/library/set/sortedset/delete_spec.rb
+++ b/spec/ruby/library/set/sortedset/delete_spec.rb
@@ -1,37 +1,40 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#delete" do
- before :each do
- @set = SortedSet["a", "b", "c"]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "deletes the passed Object from self" do
- @set.delete("a")
- @set.should_not include("a")
- end
+ describe "SortedSet#delete" do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
- it "returns self" do
- @set.delete("a").should equal(@set)
- @set.delete("x").should equal(@set)
- end
-end
+ it "deletes the passed Object from self" do
+ @set.delete("a")
+ @set.should_not include("a")
+ end
-describe "SortedSet#delete?" do
- before :each do
- @set = SortedSet["a", "b", "c"]
+ it "returns self" do
+ @set.delete("a").should equal(@set)
+ @set.delete("x").should equal(@set)
+ end
end
- it "deletes the passed Object from self" do
- @set.delete?("a")
- @set.should_not include("a")
- end
+ describe "SortedSet#delete?" do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
- it "returns self when the passed Object is in self" do
- @set.delete?("a").should equal(@set)
- end
+ it "deletes the passed Object from self" do
+ @set.delete?("a")
+ @set.should_not include("a")
+ end
+
+ it "returns self when the passed Object is in self" do
+ @set.delete?("a").should equal(@set)
+ end
- it "returns nil when the passed Object is not in self" do
- @set.delete?("x").should be_nil
+ it "returns nil when the passed Object is not in self" do
+ @set.delete?("x").should be_nil
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/difference_spec.rb b/spec/ruby/library/set/sortedset/difference_spec.rb
index c3d679aff8..fb064bdff9 100644
--- a/spec/ruby/library/set/sortedset/difference_spec.rb
+++ b/spec/ruby/library/set/sortedset/difference_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require 'set'
-require_relative 'shared/difference'
-describe "SortedSet#difference" do
- it_behaves_like :sorted_set_difference, :difference
+ruby_version_is ""..."3.0" do
+ require 'set'
+ require_relative 'shared/difference'
+
+ describe "SortedSet#difference" do
+ it_behaves_like :sorted_set_difference, :difference
+ end
end
diff --git a/spec/ruby/library/set/sortedset/divide_spec.rb b/spec/ruby/library/set/sortedset/divide_spec.rb
index 4b2135a8c9..31ab6037e4 100644
--- a/spec/ruby/library/set/sortedset/divide_spec.rb
+++ b/spec/ruby/library/set/sortedset/divide_spec.rb
@@ -1,34 +1,37 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#divide" do
- it "divides self into a set of subsets based on the blocks return values" do
- set = SortedSet["one", "two", "three", "four", "five"].divide { |x| x.length }
- set.map { |x| x.to_a }.to_a.sort.should == [["five", "four"], ["one", "two"], ["three"]]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "yields each Object in self in sorted order" do
- ret = []
- SortedSet["one", "two", "three", "four", "five"].divide { |x| ret << x }
- ret.should == ["one", "two", "three", "four", "five"].sort
- end
+ describe "SortedSet#divide" do
+ it "divides self into a set of subsets based on the blocks return values" do
+ set = SortedSet["one", "two", "three", "four", "five"].divide { |x| x.length }
+ set.map { |x| x.to_a }.to_a.sort.should == [["five", "four"], ["one", "two"], ["three"]]
+ end
- # BUG: Does not raise a LocalJumpError, but a NoMethodError
- #
- # it "raises a LocalJumpError when not passed a block" do
- # lambda { SortedSet[1].divide }.should raise_error(LocalJumpError)
- # end
-end
+ it "yields each Object in self in sorted order" do
+ ret = []
+ SortedSet["one", "two", "three", "four", "five"].divide { |x| ret << x }
+ ret.should == ["one", "two", "three", "four", "five"].sort
+ end
-describe "SortedSet#divide when passed a block with an arity of 2" do
- it "divides self into a set of subsets based on the blocks return values" do
- set = SortedSet[1, 3, 4, 6, 9, 10, 11].divide { |x, y| (x - y).abs == 1 }
- set.map { |x| x.to_a }.to_a.sort.should == [[1], [3, 4], [6], [9, 10, 11]]
+ # BUG: Does not raise a LocalJumpError, but a NoMethodError
+ #
+ # it "raises a LocalJumpError when not passed a block" do
+ # lambda { SortedSet[1].divide }.should raise_error(LocalJumpError)
+ # end
end
- it "yields each two Objects to the block" do
- ret = []
- SortedSet[1, 2].divide { |x, y| ret << [x, y] }
- ret.should == [[1, 1], [1, 2], [2, 1], [2, 2]]
+ describe "SortedSet#divide when passed a block with an arity of 2" do
+ it "divides self into a set of subsets based on the blocks return values" do
+ set = SortedSet[1, 3, 4, 6, 9, 10, 11].divide { |x, y| (x - y).abs == 1 }
+ set.map { |x| x.to_a }.to_a.sort.should == [[1], [3, 4], [6], [9, 10, 11]]
+ end
+
+ it "yields each two Objects to the block" do
+ ret = []
+ SortedSet[1, 2].divide { |x, y| ret << [x, y] }
+ ret.should == [[1, 1], [1, 2], [2, 1], [2, 2]]
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/each_spec.rb b/spec/ruby/library/set/sortedset/each_spec.rb
index bcf0d74d1f..79d8aee223 100644
--- a/spec/ruby/library/set/sortedset/each_spec.rb
+++ b/spec/ruby/library/set/sortedset/each_spec.rb
@@ -1,26 +1,29 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#each" do
- before :each do
- @set = SortedSet[1, 2, 3]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "yields each Object in self in sorted order" do
- ret = []
- SortedSet["one", "two", "three"].each { |x| ret << x }
- ret.should == ["one", "two", "three"].sort
- end
+ describe "SortedSet#each" do
+ before :each do
+ @set = SortedSet[1, 2, 3]
+ end
- it "returns self" do
- @set.each { |x| x }.should equal(@set)
- end
+ it "yields each Object in self in sorted order" do
+ ret = []
+ SortedSet["one", "two", "three"].each { |x| ret << x }
+ ret.should == ["one", "two", "three"].sort
+ end
+
+ it "returns self" do
+ @set.each { |x| x }.should equal(@set)
+ end
- it "returns an Enumerator when not passed a block" do
- enum = @set.each
+ it "returns an Enumerator when not passed a block" do
+ enum = @set.each
- ret = []
- enum.each { |x| ret << x }
- ret.sort.should == [1, 2, 3]
+ ret = []
+ enum.each { |x| ret << x }
+ ret.sort.should == [1, 2, 3]
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/empty_spec.rb b/spec/ruby/library/set/sortedset/empty_spec.rb
index deb3b567fb..2e52c3e81a 100644
--- a/spec/ruby/library/set/sortedset/empty_spec.rb
+++ b/spec/ruby/library/set/sortedset/empty_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#empty?" do
- it "returns true if self is empty" do
- SortedSet[].empty?.should be_true
- SortedSet[1].empty?.should be_false
- SortedSet[1,2,3].empty?.should be_false
+ruby_version_is ""..."3.0" do
+ require 'set'
+
+ describe "SortedSet#empty?" do
+ it "returns true if self is empty" do
+ SortedSet[].empty?.should be_true
+ SortedSet[1].empty?.should be_false
+ SortedSet[1,2,3].empty?.should be_false
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/eql_spec.rb b/spec/ruby/library/set/sortedset/eql_spec.rb
index b22858a362..050464994b 100644
--- a/spec/ruby/library/set/sortedset/eql_spec.rb
+++ b/spec/ruby/library/set/sortedset/eql_spec.rb
@@ -1,16 +1,19 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#eql?" do
- it "returns true when the passed argument is a SortedSet and contains the same elements" do
- SortedSet[].should eql(SortedSet[])
- SortedSet[1, 2, 3].should eql(SortedSet[1, 2, 3])
- SortedSet[1, 2, 3].should eql(SortedSet[3, 2, 1])
+ruby_version_is ""..."3.0" do
+ require 'set'
-# SortedSet["a", :b, ?c].should eql(SortedSet[?c, :b, "a"])
+ describe "SortedSet#eql?" do
+ it "returns true when the passed argument is a SortedSet and contains the same elements" do
+ SortedSet[].should eql(SortedSet[])
+ SortedSet[1, 2, 3].should eql(SortedSet[1, 2, 3])
+ SortedSet[1, 2, 3].should eql(SortedSet[3, 2, 1])
- SortedSet[1, 2, 3].should_not eql(SortedSet[1.0, 2, 3])
- SortedSet[1, 2, 3].should_not eql(SortedSet[2, 3])
- SortedSet[1, 2, 3].should_not eql(SortedSet[])
+ # SortedSet["a", :b, ?c].should eql(SortedSet[?c, :b, "a"])
+
+ SortedSet[1, 2, 3].should_not eql(SortedSet[1.0, 2, 3])
+ SortedSet[1, 2, 3].should_not eql(SortedSet[2, 3])
+ SortedSet[1, 2, 3].should_not eql(SortedSet[])
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/equal_value_spec.rb b/spec/ruby/library/set/sortedset/equal_value_spec.rb
index cb1b7c9443..30422f5b95 100644
--- a/spec/ruby/library/set/sortedset/equal_value_spec.rb
+++ b/spec/ruby/library/set/sortedset/equal_value_spec.rb
@@ -1,13 +1,16 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#==" do
- it "returns true when the passed Object is a SortedSet and self and the Object contain the same elements" do
- SortedSet[].should == SortedSet[]
- SortedSet[1, 2, 3].should == SortedSet[1, 2, 3]
- SortedSet["1", "2", "3"].should == SortedSet["1", "2", "3"]
+ruby_version_is ""..."3.0" do
+ require 'set'
- SortedSet[1, 2, 3].should_not == SortedSet[1.0, 2, 3]
- SortedSet[1, 2, 3].should_not == [1, 2, 3]
+ describe "SortedSet#==" do
+ it "returns true when the passed Object is a SortedSet and self and the Object contain the same elements" do
+ SortedSet[].should == SortedSet[]
+ SortedSet[1, 2, 3].should == SortedSet[1, 2, 3]
+ SortedSet["1", "2", "3"].should == SortedSet["1", "2", "3"]
+
+ SortedSet[1, 2, 3].should_not == SortedSet[1.0, 2, 3]
+ SortedSet[1, 2, 3].should_not == [1, 2, 3]
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/exclusion_spec.rb b/spec/ruby/library/set/sortedset/exclusion_spec.rb
index d0f1ab95cb..1967dfbfa6 100644
--- a/spec/ruby/library/set/sortedset/exclusion_spec.rb
+++ b/spec/ruby/library/set/sortedset/exclusion_spec.rb
@@ -1,18 +1,21 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#^" do
- before :each do
- @set = SortedSet[1, 2, 3, 4]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "returns a new SortedSet containing elements that are not in both self and the passed Enumerable" do
- (@set ^ SortedSet[3, 4, 5]).should == SortedSet[1, 2, 5]
- (@set ^ [3, 4, 5]).should == SortedSet[1, 2, 5]
- end
+ describe "SortedSet#^" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
+
+ it "returns a new SortedSet containing elements that are not in both self and the passed Enumerable" do
+ (@set ^ SortedSet[3, 4, 5]).should == SortedSet[1, 2, 5]
+ (@set ^ [3, 4, 5]).should == SortedSet[1, 2, 5]
+ end
- it "raises an ArgumentError when passed a non-Enumerable" do
- -> { @set ^ 3 }.should raise_error(ArgumentError)
- -> { @set ^ Object.new }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ -> { @set ^ 3 }.should raise_error(ArgumentError)
+ -> { @set ^ Object.new }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/filter_spec.rb b/spec/ruby/library/set/sortedset/filter_spec.rb
index cfaa8b2729..c6d881de67 100644
--- a/spec/ruby/library/set/sortedset/filter_spec.rb
+++ b/spec/ruby/library/set/sortedset/filter_spec.rb
@@ -1,9 +1,12 @@
require_relative '../../../spec_helper'
-require_relative 'shared/select'
-require 'set'
-ruby_version_is "2.6" do
- describe "SortedSet#filter!" do
- it_behaves_like :sorted_set_select_bang, :filter!
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/select'
+ require 'set'
+
+ ruby_version_is "2.6" do
+ describe "SortedSet#filter!" do
+ it_behaves_like :sorted_set_select_bang, :filter!
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/flatten_merge_spec.rb b/spec/ruby/library/set/sortedset/flatten_merge_spec.rb
index 9a8ed13f00..0d67cb331e 100644
--- a/spec/ruby/library/set/sortedset/flatten_merge_spec.rb
+++ b/spec/ruby/library/set/sortedset/flatten_merge_spec.rb
@@ -1,8 +1,11 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#flatten_merge" do
- it "is protected" do
- SortedSet.should have_protected_instance_method("flatten_merge")
+ruby_version_is ""..."3.0" do
+ require 'set'
+
+ describe "SortedSet#flatten_merge" do
+ it "is protected" do
+ SortedSet.should have_protected_instance_method("flatten_merge")
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/flatten_spec.rb b/spec/ruby/library/set/sortedset/flatten_spec.rb
index ca4e4637e6..e83ad1044a 100644
--- a/spec/ruby/library/set/sortedset/flatten_spec.rb
+++ b/spec/ruby/library/set/sortedset/flatten_spec.rb
@@ -1,44 +1,47 @@
require_relative '../../../spec_helper'
-require 'set'
-# Note: Flatten make little sens on sorted sets, because SortedSets are not (by default)
-# comparable. For a SortedSet to be both valid and nested, we need to define a comparison operator:
-module SortedSet_FlattenSpecs
- class ComparableSortedSet < SortedSet
- def <=>(other)
- return puts "#{other} vs #{self}" unless other.is_a?(ComparableSortedSet)
- to_a <=> other.to_a
+ruby_version_is ""..."3.0" do
+ require 'set'
+
+ # Note: Flatten make little sens on sorted sets, because SortedSets are not (by default)
+ # comparable. For a SortedSet to be both valid and nested, we need to define a comparison operator:
+ module SortedSet_FlattenSpecs
+ class ComparableSortedSet < SortedSet
+ def <=>(other)
+ return puts "#{other} vs #{self}" unless other.is_a?(ComparableSortedSet)
+ to_a <=> other.to_a
+ end
end
end
-end
-describe "SortedSet#flatten" do
- it "returns a copy of self with each included SortedSet flattened" do
- klass = SortedSet_FlattenSpecs::ComparableSortedSet
- set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]]
- flattened_set = set.flatten
+ describe "SortedSet#flatten" do
+ it "returns a copy of self with each included SortedSet flattened" do
+ klass = SortedSet_FlattenSpecs::ComparableSortedSet
+ set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]]
+ flattened_set = set.flatten
- flattened_set.should_not equal(set)
- flattened_set.should == klass[1, 2, 3, 4, 5, 6, 7, 8]
+ flattened_set.should_not equal(set)
+ flattened_set.should == klass[1, 2, 3, 4, 5, 6, 7, 8]
+ end
end
-end
-describe "SortedSet#flatten!" do
- it "flattens self" do
- klass = SortedSet_FlattenSpecs::ComparableSortedSet
- set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]]
- set.flatten!
- set.should == klass[1, 2, 3, 4, 5, 6, 7, 8]
- end
+ describe "SortedSet#flatten!" do
+ it "flattens self" do
+ klass = SortedSet_FlattenSpecs::ComparableSortedSet
+ set = klass[klass[1,2], klass[3,4], klass[5,6,7], klass[8]]
+ set.flatten!
+ set.should == klass[1, 2, 3, 4, 5, 6, 7, 8]
+ end
- it "returns self when self was modified" do
- klass = SortedSet_FlattenSpecs::ComparableSortedSet
- set = klass[klass[1,2], klass[3,4]]
- set.flatten!.should equal(set)
- end
+ it "returns self when self was modified" do
+ klass = SortedSet_FlattenSpecs::ComparableSortedSet
+ set = klass[klass[1,2], klass[3,4]]
+ set.flatten!.should equal(set)
+ end
- it "returns nil when self was not modified" do
- set = SortedSet[1, 2, 3, 4]
- set.flatten!.should be_nil
+ it "returns nil when self was not modified" do
+ set = SortedSet[1, 2, 3, 4]
+ set.flatten!.should be_nil
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/hash_spec.rb b/spec/ruby/library/set/sortedset/hash_spec.rb
index 7833c68a10..40676de7fc 100644
--- a/spec/ruby/library/set/sortedset/hash_spec.rb
+++ b/spec/ruby/library/set/sortedset/hash_spec.rb
@@ -1,13 +1,16 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#hash" do
- it "is static" do
- SortedSet[].hash.should == SortedSet[].hash
- SortedSet[1, 2, 3].hash.should == SortedSet[1, 2, 3].hash
- SortedSet["a", "b", "c"].hash.should == SortedSet["c", "b", "a"].hash
+ruby_version_is ""..."3.0" do
+ require 'set'
- SortedSet[].hash.should_not == SortedSet[1, 2, 3].hash
- SortedSet[1, 2, 3].hash.should_not == SortedSet["a", "b", "c"].hash
+ describe "SortedSet#hash" do
+ it "is static" do
+ SortedSet[].hash.should == SortedSet[].hash
+ SortedSet[1, 2, 3].hash.should == SortedSet[1, 2, 3].hash
+ SortedSet["a", "b", "c"].hash.should == SortedSet["c", "b", "a"].hash
+
+ SortedSet[].hash.should_not == SortedSet[1, 2, 3].hash
+ SortedSet[1, 2, 3].hash.should_not == SortedSet["a", "b", "c"].hash
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/include_spec.rb b/spec/ruby/library/set/sortedset/include_spec.rb
index 030a9e146a..ec2ad987d5 100644
--- a/spec/ruby/library/set/sortedset/include_spec.rb
+++ b/spec/ruby/library/set/sortedset/include_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/include'
-require 'set'
-describe "SortedSet#include?" do
- it_behaves_like :sorted_set_include, :include?
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/include'
+ require 'set'
+
+ describe "SortedSet#include?" do
+ it_behaves_like :sorted_set_include, :include?
+ end
end
diff --git a/spec/ruby/library/set/sortedset/initialize_spec.rb b/spec/ruby/library/set/sortedset/initialize_spec.rb
index 1238f4efc4..4d1707b72a 100644
--- a/spec/ruby/library/set/sortedset/initialize_spec.rb
+++ b/spec/ruby/library/set/sortedset/initialize_spec.rb
@@ -1,30 +1,33 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#initialize" do
- it "is private" do
- SortedSet.should have_private_instance_method("initialize")
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "adds all elements of the passed Enumerable to self" do
- s = SortedSet.new([1, 2, 3])
- s.size.should eql(3)
- s.should include(1)
- s.should include(2)
- s.should include(3)
- end
+ describe "SortedSet#initialize" do
+ it "is private" do
+ SortedSet.should have_private_instance_method("initialize")
+ end
- it "preprocesses all elements by a passed block before adding to self" do
- s = SortedSet.new([1, 2, 3]) { |x| x * x }
- s.size.should eql(3)
- s.should include(1)
- s.should include(4)
- s.should include(9)
- end
+ it "adds all elements of the passed Enumerable to self" do
+ s = SortedSet.new([1, 2, 3])
+ s.size.should eql(3)
+ s.should include(1)
+ s.should include(2)
+ s.should include(3)
+ end
+
+ it "preprocesses all elements by a passed block before adding to self" do
+ s = SortedSet.new([1, 2, 3]) { |x| x * x }
+ s.size.should eql(3)
+ s.should include(1)
+ s.should include(4)
+ s.should include(9)
+ end
- it "raises on incompatible <=> comparison" do
- # Use #to_a here as elements are sorted only when needed.
- # Therefore the <=> incompatibility is only noticed on sorting.
- -> { SortedSet.new(['00', nil]).to_a }.should raise_error(ArgumentError)
+ it "raises on incompatible <=> comparison" do
+ # Use #to_a here as elements are sorted only when needed.
+ # Therefore the <=> incompatibility is only noticed on sorting.
+ -> { SortedSet.new(['00', nil]).to_a }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/inspect_spec.rb b/spec/ruby/library/set/sortedset/inspect_spec.rb
index 7103bee3f5..1c4dd9e6e2 100644
--- a/spec/ruby/library/set/sortedset/inspect_spec.rb
+++ b/spec/ruby/library/set/sortedset/inspect_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#inspect" do
- it "returns a String representation of self" do
- SortedSet[].inspect.should be_kind_of(String)
- SortedSet[1, 2, 3].inspect.should be_kind_of(String)
- SortedSet["1", "2", "3"].inspect.should be_kind_of(String)
+ruby_version_is ""..."3.0" do
+ require 'set'
+
+ describe "SortedSet#inspect" do
+ it "returns a String representation of self" do
+ SortedSet[].inspect.should be_kind_of(String)
+ SortedSet[1, 2, 3].inspect.should be_kind_of(String)
+ SortedSet["1", "2", "3"].inspect.should be_kind_of(String)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/intersection_spec.rb b/spec/ruby/library/set/sortedset/intersection_spec.rb
index 6ff9c80ce1..6daa271b73 100644
--- a/spec/ruby/library/set/sortedset/intersection_spec.rb
+++ b/spec/ruby/library/set/sortedset/intersection_spec.rb
@@ -1,11 +1,14 @@
require_relative '../../../spec_helper'
-require_relative 'shared/intersection'
-require 'set'
-describe "SortedSet#intersection" do
- it_behaves_like :sorted_set_intersection, :intersection
-end
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/intersection'
+ require 'set'
+
+ describe "SortedSet#intersection" do
+ it_behaves_like :sorted_set_intersection, :intersection
+ end
-describe "SortedSet#&" do
- it_behaves_like :sorted_set_intersection, :&
+ describe "SortedSet#&" do
+ it_behaves_like :sorted_set_intersection, :&
+ end
end
diff --git a/spec/ruby/library/set/sortedset/keep_if_spec.rb b/spec/ruby/library/set/sortedset/keep_if_spec.rb
index 2235eb3766..3e5f3bbc47 100644
--- a/spec/ruby/library/set/sortedset/keep_if_spec.rb
+++ b/spec/ruby/library/set/sortedset/keep_if_spec.rb
@@ -1,31 +1,34 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#keep_if" do
- before :each do
- @set = SortedSet["one", "two", "three"]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "yields each Object in self in sorted order" do
- ret = []
- @set.keep_if { |x| ret << x }
- ret.should == ["one", "two", "three"].sort
- end
+ describe "SortedSet#keep_if" do
+ before :each do
+ @set = SortedSet["one", "two", "three"]
+ end
- it "keeps every element from self for which the passed block returns true" do
- @set.keep_if { |x| x.size != 3 }
- @set.to_a.should == ["three"]
- end
+ it "yields each Object in self in sorted order" do
+ ret = []
+ @set.keep_if { |x| ret << x }
+ ret.should == ["one", "two", "three"].sort
+ end
- it "returns self" do
- @set.keep_if {}.should equal(@set)
- end
+ it "keeps every element from self for which the passed block returns true" do
+ @set.keep_if { |x| x.size != 3 }
+ @set.to_a.should == ["three"]
+ end
+
+ it "returns self" do
+ @set.keep_if {}.should equal(@set)
+ end
- it "returns an Enumerator when passed no block" do
- enum = @set.keep_if
- enum.should be_an_instance_of(Enumerator)
+ it "returns an Enumerator when passed no block" do
+ enum = @set.keep_if
+ enum.should be_an_instance_of(Enumerator)
- enum.each { |x| x.size != 3 }
- @set.to_a.should == ["three"]
+ enum.each { |x| x.size != 3 }
+ @set.to_a.should == ["three"]
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/length_spec.rb b/spec/ruby/library/set/sortedset/length_spec.rb
index 5f138dd6f7..de6791f6bb 100644
--- a/spec/ruby/library/set/sortedset/length_spec.rb
+++ b/spec/ruby/library/set/sortedset/length_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/length'
-require 'set'
-describe "SortedSet#length" do
- it_behaves_like :sorted_set_length, :length
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/length'
+ require 'set'
+
+ describe "SortedSet#length" do
+ it_behaves_like :sorted_set_length, :length
+ end
end
diff --git a/spec/ruby/library/set/sortedset/map_spec.rb b/spec/ruby/library/set/sortedset/map_spec.rb
index 1d7b5954e5..4971b9529b 100644
--- a/spec/ruby/library/set/sortedset/map_spec.rb
+++ b/spec/ruby/library/set/sortedset/map_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require 'set'
-require_relative 'shared/collect'
-describe "SortedSet#map!" do
- it_behaves_like :sorted_set_collect_bang, :map!
+ruby_version_is ""..."3.0" do
+ require 'set'
+ require_relative 'shared/collect'
+
+ describe "SortedSet#map!" do
+ it_behaves_like :sorted_set_collect_bang, :map!
+ end
end
diff --git a/spec/ruby/library/set/sortedset/member_spec.rb b/spec/ruby/library/set/sortedset/member_spec.rb
index d6005557ab..142b09b651 100644
--- a/spec/ruby/library/set/sortedset/member_spec.rb
+++ b/spec/ruby/library/set/sortedset/member_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/include'
-require 'set'
-describe "SortedSet#member?" do
- it_behaves_like :sorted_set_include, :member?
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/include'
+ require 'set'
+
+ describe "SortedSet#member?" do
+ it_behaves_like :sorted_set_include, :member?
+ end
end
diff --git a/spec/ruby/library/set/sortedset/merge_spec.rb b/spec/ruby/library/set/sortedset/merge_spec.rb
index 31570ad4db..c4cbc6d2b4 100644
--- a/spec/ruby/library/set/sortedset/merge_spec.rb
+++ b/spec/ruby/library/set/sortedset/merge_spec.rb
@@ -1,19 +1,22 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#merge" do
- it "adds the elements of the passed Enumerable to self" do
- SortedSet["a", "b"].merge(SortedSet["b", "c", "d"]).should == SortedSet["a", "b", "c", "d"]
- SortedSet[1, 2].merge([3, 4]).should == SortedSet[1, 2, 3, 4]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "returns self" do
- set = SortedSet[1, 2]
- set.merge([3, 4]).should equal(set)
- end
+ describe "SortedSet#merge" do
+ it "adds the elements of the passed Enumerable to self" do
+ SortedSet["a", "b"].merge(SortedSet["b", "c", "d"]).should == SortedSet["a", "b", "c", "d"]
+ SortedSet[1, 2].merge([3, 4]).should == SortedSet[1, 2, 3, 4]
+ end
+
+ it "returns self" do
+ set = SortedSet[1, 2]
+ set.merge([3, 4]).should equal(set)
+ end
- it "raises an ArgumentError when passed a non-Enumerable" do
- -> { SortedSet[1, 2].merge(1) }.should raise_error(ArgumentError)
- -> { SortedSet[1, 2].merge(Object.new) }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ -> { SortedSet[1, 2].merge(1) }.should raise_error(ArgumentError)
+ -> { SortedSet[1, 2].merge(Object.new) }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/minus_spec.rb b/spec/ruby/library/set/sortedset/minus_spec.rb
index ffb8ee85d1..d6abc5e204 100644
--- a/spec/ruby/library/set/sortedset/minus_spec.rb
+++ b/spec/ruby/library/set/sortedset/minus_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require 'set'
-require_relative 'shared/difference'
-describe "SortedSet#-" do
- it_behaves_like :sorted_set_difference, :-
+ruby_version_is ""..."3.0" do
+ require 'set'
+ require_relative 'shared/difference'
+
+ describe "SortedSet#-" do
+ it_behaves_like :sorted_set_difference, :-
+ end
end
diff --git a/spec/ruby/library/set/sortedset/plus_spec.rb b/spec/ruby/library/set/sortedset/plus_spec.rb
index 355c775d7e..13fc873ad1 100644
--- a/spec/ruby/library/set/sortedset/plus_spec.rb
+++ b/spec/ruby/library/set/sortedset/plus_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/union'
-require 'set'
-describe "SortedSet#+" do
- it_behaves_like :sorted_set_union, :+
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/union'
+ require 'set'
+
+ describe "SortedSet#+" do
+ it_behaves_like :sorted_set_union, :+
+ end
end
diff --git a/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb b/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb
index fe15f1bf7d..e97f509406 100644
--- a/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb
+++ b/spec/ruby/library/set/sortedset/pretty_print_cycle_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#pretty_print_cycle" do
- it "passes the 'pretty print' representation of a self-referencing SortedSet to the pretty print writer" do
- pp = mock("PrettyPrint")
- pp.should_receive(:text).with("#<SortedSet: {...}>")
- SortedSet[1, 2, 3].pretty_print_cycle(pp)
+ruby_version_is ""..."3.0" do
+ require 'set'
+
+ describe "SortedSet#pretty_print_cycle" do
+ it "passes the 'pretty print' representation of a self-referencing SortedSet to the pretty print writer" do
+ pp = mock("PrettyPrint")
+ pp.should_receive(:text).with("#<SortedSet: {...}>")
+ SortedSet[1, 2, 3].pretty_print_cycle(pp)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/pretty_print_spec.rb b/spec/ruby/library/set/sortedset/pretty_print_spec.rb
index 601ff4d182..a8088bf797 100644
--- a/spec/ruby/library/set/sortedset/pretty_print_spec.rb
+++ b/spec/ruby/library/set/sortedset/pretty_print_spec.rb
@@ -1,17 +1,20 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#pretty_print" do
- it "passes the 'pretty print' representation of self to the pretty print writer" do
- pp = mock("PrettyPrint")
- set = SortedSet[1, 2, 3]
+ruby_version_is ""..."3.0" do
+ require 'set'
- pp.should_receive(:text).with("#<SortedSet: {")
- pp.should_receive(:text).with("}>")
+ describe "SortedSet#pretty_print" do
+ it "passes the 'pretty print' representation of self to the pretty print writer" do
+ pp = mock("PrettyPrint")
+ set = SortedSet[1, 2, 3]
- pp.should_receive(:nest).with(1).and_yield
- pp.should_receive(:seplist).with(set)
+ pp.should_receive(:text).with("#<SortedSet: {")
+ pp.should_receive(:text).with("}>")
- set.pretty_print(pp)
+ pp.should_receive(:nest).with(1).and_yield
+ pp.should_receive(:seplist).with(set)
+
+ set.pretty_print(pp)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/proper_subset_spec.rb b/spec/ruby/library/set/sortedset/proper_subset_spec.rb
index 818173a7f9..34fb89d13d 100644
--- a/spec/ruby/library/set/sortedset/proper_subset_spec.rb
+++ b/spec/ruby/library/set/sortedset/proper_subset_spec.rb
@@ -1,33 +1,36 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#proper_subset?" do
- before :each do
- @set = SortedSet[1, 2, 3, 4]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "returns true if passed a SortedSet that self is a proper subset of" do
- SortedSet[].proper_subset?(@set).should be_true
- SortedSet[].proper_subset?(SortedSet[1, 2, 3]).should be_true
- SortedSet[].proper_subset?(SortedSet["a", "b", "c"]).should be_true
+ describe "SortedSet#proper_subset?" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
- SortedSet[1, 2, 3].proper_subset?(@set).should be_true
- SortedSet[1, 3].proper_subset?(@set).should be_true
- SortedSet[1, 2].proper_subset?(@set).should be_true
- SortedSet[1].proper_subset?(@set).should be_true
+ it "returns true if passed a SortedSet that self is a proper subset of" do
+ SortedSet[].proper_subset?(@set).should be_true
+ SortedSet[].proper_subset?(SortedSet[1, 2, 3]).should be_true
+ SortedSet[].proper_subset?(SortedSet["a", "b", "c"]).should be_true
- SortedSet[5].proper_subset?(@set).should be_false
- SortedSet[1, 5].proper_subset?(@set).should be_false
- SortedSet["test"].proper_subset?(@set).should be_false
+ SortedSet[1, 2, 3].proper_subset?(@set).should be_true
+ SortedSet[1, 3].proper_subset?(@set).should be_true
+ SortedSet[1, 2].proper_subset?(@set).should be_true
+ SortedSet[1].proper_subset?(@set).should be_true
- @set.proper_subset?(@set).should be_false
- SortedSet[].proper_subset?(SortedSet[]).should be_false
- end
+ SortedSet[5].proper_subset?(@set).should be_false
+ SortedSet[1, 5].proper_subset?(@set).should be_false
+ SortedSet["test"].proper_subset?(@set).should be_false
+
+ @set.proper_subset?(@set).should be_false
+ SortedSet[].proper_subset?(SortedSet[]).should be_false
+ end
- it "raises an ArgumentError when passed a non-SortedSet" do
- -> { SortedSet[].proper_subset?([]) }.should raise_error(ArgumentError)
- -> { SortedSet[].proper_subset?(1) }.should raise_error(ArgumentError)
- -> { SortedSet[].proper_subset?("test") }.should raise_error(ArgumentError)
- -> { SortedSet[].proper_subset?(Object.new) }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when passed a non-SortedSet" do
+ -> { SortedSet[].proper_subset?([]) }.should raise_error(ArgumentError)
+ -> { SortedSet[].proper_subset?(1) }.should raise_error(ArgumentError)
+ -> { SortedSet[].proper_subset?("test") }.should raise_error(ArgumentError)
+ -> { SortedSet[].proper_subset?(Object.new) }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/proper_superset_spec.rb b/spec/ruby/library/set/sortedset/proper_superset_spec.rb
index 2699290f0e..8b92444f72 100644
--- a/spec/ruby/library/set/sortedset/proper_superset_spec.rb
+++ b/spec/ruby/library/set/sortedset/proper_superset_spec.rb
@@ -1,33 +1,36 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#proper_superset?" do
- before :each do
- @set = SortedSet[1, 2, 3, 4]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "returns true if passed a SortedSet that self is a proper superset of" do
- @set.proper_superset?(SortedSet[]).should be_true
- SortedSet[1, 2, 3].proper_superset?(SortedSet[]).should be_true
- SortedSet["a", "b", "c"].proper_superset?(SortedSet[]).should be_true
+ describe "SortedSet#proper_superset?" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
- @set.proper_superset?(SortedSet[1, 2, 3]).should be_true
- @set.proper_superset?(SortedSet[1, 3]).should be_true
- @set.proper_superset?(SortedSet[1, 2]).should be_true
- @set.proper_superset?(SortedSet[1]).should be_true
+ it "returns true if passed a SortedSet that self is a proper superset of" do
+ @set.proper_superset?(SortedSet[]).should be_true
+ SortedSet[1, 2, 3].proper_superset?(SortedSet[]).should be_true
+ SortedSet["a", "b", "c"].proper_superset?(SortedSet[]).should be_true
- @set.proper_superset?(SortedSet[5]).should be_false
- @set.proper_superset?(SortedSet[1, 5]).should be_false
- @set.proper_superset?(SortedSet["test"]).should be_false
+ @set.proper_superset?(SortedSet[1, 2, 3]).should be_true
+ @set.proper_superset?(SortedSet[1, 3]).should be_true
+ @set.proper_superset?(SortedSet[1, 2]).should be_true
+ @set.proper_superset?(SortedSet[1]).should be_true
- @set.proper_superset?(@set).should be_false
- SortedSet[].proper_superset?(SortedSet[]).should be_false
- end
+ @set.proper_superset?(SortedSet[5]).should be_false
+ @set.proper_superset?(SortedSet[1, 5]).should be_false
+ @set.proper_superset?(SortedSet["test"]).should be_false
+
+ @set.proper_superset?(@set).should be_false
+ SortedSet[].proper_superset?(SortedSet[]).should be_false
+ end
- it "raises an ArgumentError when passed a non-SortedSet" do
- -> { SortedSet[].proper_superset?([]) }.should raise_error(ArgumentError)
- -> { SortedSet[].proper_superset?(1) }.should raise_error(ArgumentError)
- -> { SortedSet[].proper_superset?("test") }.should raise_error(ArgumentError)
- -> { SortedSet[].proper_superset?(Object.new) }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when passed a non-SortedSet" do
+ -> { SortedSet[].proper_superset?([]) }.should raise_error(ArgumentError)
+ -> { SortedSet[].proper_superset?(1) }.should raise_error(ArgumentError)
+ -> { SortedSet[].proper_superset?("test") }.should raise_error(ArgumentError)
+ -> { SortedSet[].proper_superset?(Object.new) }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/reject_spec.rb b/spec/ruby/library/set/sortedset/reject_spec.rb
index da2a76e7a7..396b864cc5 100644
--- a/spec/ruby/library/set/sortedset/reject_spec.rb
+++ b/spec/ruby/library/set/sortedset/reject_spec.rb
@@ -1,42 +1,45 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#reject!" do
- before :each do
- @set = SortedSet["one", "two", "three"]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "yields each Object in self in sorted order" do
- res = []
- @set.reject! { |x| res << x }
- res.should == ["one", "two", "three"].sort
- end
+ describe "SortedSet#reject!" do
+ before :each do
+ @set = SortedSet["one", "two", "three"]
+ end
- it "deletes every element from self for which the passed block returns true" do
- @set.reject! { |x| x.size == 3 }
- @set.size.should eql(1)
+ it "yields each Object in self in sorted order" do
+ res = []
+ @set.reject! { |x| res << x }
+ res.should == ["one", "two", "three"].sort
+ end
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
- end
+ it "deletes every element from self for which the passed block returns true" do
+ @set.reject! { |x| x.size == 3 }
+ @set.size.should eql(1)
- it "returns self when self was modified" do
- @set.reject! { |x| true }.should equal(@set)
- end
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
- it "returns nil when self was not modified" do
- @set.reject! { |x| false }.should be_nil
- end
+ it "returns self when self was modified" do
+ @set.reject! { |x| true }.should equal(@set)
+ end
+
+ it "returns nil when self was not modified" do
+ @set.reject! { |x| false }.should be_nil
+ end
- it "returns an Enumerator when passed no block" do
- enum = @set.reject!
- enum.should be_an_instance_of(Enumerator)
+ it "returns an Enumerator when passed no block" do
+ enum = @set.reject!
+ enum.should be_an_instance_of(Enumerator)
- enum.each { |x| x.size == 3 }
+ enum.each { |x| x.size == 3 }
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/replace_spec.rb b/spec/ruby/library/set/sortedset/replace_spec.rb
index 2a7fa73efb..2900221c01 100644
--- a/spec/ruby/library/set/sortedset/replace_spec.rb
+++ b/spec/ruby/library/set/sortedset/replace_spec.rb
@@ -1,17 +1,20 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#replace" do
- before :each do
- @set = SortedSet["a", "b", "c"]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "replaces the contents with other and returns self" do
- @set.replace(SortedSet[1, 2, 3]).should == @set
- @set.should == SortedSet[1, 2, 3]
- end
+ describe "SortedSet#replace" do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
+
+ it "replaces the contents with other and returns self" do
+ @set.replace(SortedSet[1, 2, 3]).should == @set
+ @set.should == SortedSet[1, 2, 3]
+ end
- it "accepts any enumerable as other" do
- @set.replace([1, 2, 3]).should == SortedSet[1, 2, 3]
+ it "accepts any enumerable as other" do
+ @set.replace([1, 2, 3]).should == SortedSet[1, 2, 3]
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/select_spec.rb b/spec/ruby/library/set/sortedset/select_spec.rb
index 68326cd02c..fc4c15ee4d 100644
--- a/spec/ruby/library/set/sortedset/select_spec.rb
+++ b/spec/ruby/library/set/sortedset/select_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/select'
-require 'set'
-describe "SortedSet#select!" do
- it_behaves_like :sorted_set_select_bang, :select!
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/select'
+ require 'set'
+
+ describe "SortedSet#select!" do
+ it_behaves_like :sorted_set_select_bang, :select!
+ end
end
diff --git a/spec/ruby/library/set/sortedset/size_spec.rb b/spec/ruby/library/set/sortedset/size_spec.rb
index 13e5085b0c..d908b33b53 100644
--- a/spec/ruby/library/set/sortedset/size_spec.rb
+++ b/spec/ruby/library/set/sortedset/size_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require_relative 'shared/length'
-require 'set'
-describe "SortedSet#size" do
- it_behaves_like :sorted_set_length, :size
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/length'
+ require 'set'
+
+ describe "SortedSet#size" do
+ it_behaves_like :sorted_set_length, :size
+ end
end
diff --git a/spec/ruby/library/set/sortedset/subset_spec.rb b/spec/ruby/library/set/sortedset/subset_spec.rb
index 7768692df6..272e3f985e 100644
--- a/spec/ruby/library/set/sortedset/subset_spec.rb
+++ b/spec/ruby/library/set/sortedset/subset_spec.rb
@@ -1,33 +1,36 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#subset?" do
- before :each do
- @set = SortedSet[1, 2, 3, 4]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "returns true if passed a SortedSet that is equal to self or self is a subset of" do
- @set.subset?(@set).should be_true
- SortedSet[].subset?(SortedSet[]).should be_true
+ describe "SortedSet#subset?" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
- SortedSet[].subset?(@set).should be_true
- SortedSet[].subset?(SortedSet[1, 2, 3]).should be_true
- SortedSet[].subset?(SortedSet["a", "b", "c"]).should be_true
+ it "returns true if passed a SortedSet that is equal to self or self is a subset of" do
+ @set.subset?(@set).should be_true
+ SortedSet[].subset?(SortedSet[]).should be_true
- SortedSet[1, 2, 3].subset?(@set).should be_true
- SortedSet[1, 3].subset?(@set).should be_true
- SortedSet[1, 2].subset?(@set).should be_true
- SortedSet[1].subset?(@set).should be_true
+ SortedSet[].subset?(@set).should be_true
+ SortedSet[].subset?(SortedSet[1, 2, 3]).should be_true
+ SortedSet[].subset?(SortedSet["a", "b", "c"]).should be_true
- SortedSet[5].subset?(@set).should be_false
- SortedSet[1, 5].subset?(@set).should be_false
- SortedSet["test"].subset?(@set).should be_false
- end
+ SortedSet[1, 2, 3].subset?(@set).should be_true
+ SortedSet[1, 3].subset?(@set).should be_true
+ SortedSet[1, 2].subset?(@set).should be_true
+ SortedSet[1].subset?(@set).should be_true
+
+ SortedSet[5].subset?(@set).should be_false
+ SortedSet[1, 5].subset?(@set).should be_false
+ SortedSet["test"].subset?(@set).should be_false
+ end
- it "raises an ArgumentError when passed a non-SortedSet" do
- -> { SortedSet[].subset?([]) }.should raise_error(ArgumentError)
- -> { SortedSet[].subset?(1) }.should raise_error(ArgumentError)
- -> { SortedSet[].subset?("test") }.should raise_error(ArgumentError)
- -> { SortedSet[].subset?(Object.new) }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when passed a non-SortedSet" do
+ -> { SortedSet[].subset?([]) }.should raise_error(ArgumentError)
+ -> { SortedSet[].subset?(1) }.should raise_error(ArgumentError)
+ -> { SortedSet[].subset?("test") }.should raise_error(ArgumentError)
+ -> { SortedSet[].subset?(Object.new) }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/subtract_spec.rb b/spec/ruby/library/set/sortedset/subtract_spec.rb
index 64d66c3688..b2af127f89 100644
--- a/spec/ruby/library/set/sortedset/subtract_spec.rb
+++ b/spec/ruby/library/set/sortedset/subtract_spec.rb
@@ -1,17 +1,20 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#subtract" do
- before :each do
- @set = SortedSet["a", "b", "c"]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "deletes any elements contained in other and returns self" do
- @set.subtract(SortedSet["b", "c"]).should == @set
- @set.should == SortedSet["a"]
- end
+ describe "SortedSet#subtract" do
+ before :each do
+ @set = SortedSet["a", "b", "c"]
+ end
+
+ it "deletes any elements contained in other and returns self" do
+ @set.subtract(SortedSet["b", "c"]).should == @set
+ @set.should == SortedSet["a"]
+ end
- it "accepts any enumerable as other" do
- @set.subtract(["c"]).should == SortedSet["a", "b"]
+ it "accepts any enumerable as other" do
+ @set.subtract(["c"]).should == SortedSet["a", "b"]
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/superset_spec.rb b/spec/ruby/library/set/sortedset/superset_spec.rb
index 823781b860..a1bbacb966 100644
--- a/spec/ruby/library/set/sortedset/superset_spec.rb
+++ b/spec/ruby/library/set/sortedset/superset_spec.rb
@@ -1,33 +1,36 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#superset?" do
- before :each do
- @set = SortedSet[1, 2, 3, 4]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
- it "returns true if passed a SortedSet that equals self or self is a proper superset of" do
- @set.superset?(@set).should be_true
- SortedSet[].superset?(SortedSet[]).should be_true
+ describe "SortedSet#superset?" do
+ before :each do
+ @set = SortedSet[1, 2, 3, 4]
+ end
- @set.superset?(SortedSet[]).should be_true
- SortedSet[1, 2, 3].superset?(SortedSet[]).should be_true
- SortedSet["a", "b", "c"].superset?(SortedSet[]).should be_true
+ it "returns true if passed a SortedSet that equals self or self is a proper superset of" do
+ @set.superset?(@set).should be_true
+ SortedSet[].superset?(SortedSet[]).should be_true
- @set.superset?(SortedSet[1, 2, 3]).should be_true
- @set.superset?(SortedSet[1, 3]).should be_true
- @set.superset?(SortedSet[1, 2]).should be_true
- @set.superset?(SortedSet[1]).should be_true
+ @set.superset?(SortedSet[]).should be_true
+ SortedSet[1, 2, 3].superset?(SortedSet[]).should be_true
+ SortedSet["a", "b", "c"].superset?(SortedSet[]).should be_true
- @set.superset?(SortedSet[5]).should be_false
- @set.superset?(SortedSet[1, 5]).should be_false
- @set.superset?(SortedSet["test"]).should be_false
- end
+ @set.superset?(SortedSet[1, 2, 3]).should be_true
+ @set.superset?(SortedSet[1, 3]).should be_true
+ @set.superset?(SortedSet[1, 2]).should be_true
+ @set.superset?(SortedSet[1]).should be_true
+
+ @set.superset?(SortedSet[5]).should be_false
+ @set.superset?(SortedSet[1, 5]).should be_false
+ @set.superset?(SortedSet["test"]).should be_false
+ end
- it "raises an ArgumentError when passed a non-SortedSet" do
- -> { SortedSet[].superset?([]) }.should raise_error(ArgumentError)
- -> { SortedSet[].superset?(1) }.should raise_error(ArgumentError)
- -> { SortedSet[].superset?("test") }.should raise_error(ArgumentError)
- -> { SortedSet[].superset?(Object.new) }.should raise_error(ArgumentError)
+ it "raises an ArgumentError when passed a non-SortedSet" do
+ -> { SortedSet[].superset?([]) }.should raise_error(ArgumentError)
+ -> { SortedSet[].superset?(1) }.should raise_error(ArgumentError)
+ -> { SortedSet[].superset?("test") }.should raise_error(ArgumentError)
+ -> { SortedSet[].superset?(Object.new) }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/to_a_spec.rb b/spec/ruby/library/set/sortedset/to_a_spec.rb
index ba37d18cdb..bb54cd7cdb 100644
--- a/spec/ruby/library/set/sortedset/to_a_spec.rb
+++ b/spec/ruby/library/set/sortedset/to_a_spec.rb
@@ -1,17 +1,20 @@
require_relative '../../../spec_helper'
-require 'set'
-describe "SortedSet#to_a" do
- it "returns an array containing elements" do
- set = SortedSet.new [1, 2, 3]
- set.to_a.should == [1, 2, 3]
- end
+ruby_version_is ""..."3.0" do
+ require 'set'
+
+ describe "SortedSet#to_a" do
+ it "returns an array containing elements" do
+ set = SortedSet.new [1, 2, 3]
+ set.to_a.should == [1, 2, 3]
+ end
- it "returns a sorted array containing elements" do
- set = SortedSet[2, 3, 1]
- set.to_a.should == [1, 2, 3]
+ it "returns a sorted array containing elements" do
+ set = SortedSet[2, 3, 1]
+ set.to_a.should == [1, 2, 3]
- set = SortedSet.new [5, 6, 4, 4]
- set.to_a.should == [4, 5, 6]
+ set = SortedSet.new [5, 6, 4, 4]
+ set.to_a.should == [4, 5, 6]
+ end
end
end
diff --git a/spec/ruby/library/set/sortedset/union_spec.rb b/spec/ruby/library/set/sortedset/union_spec.rb
index eb77600fee..c942f20d3e 100644
--- a/spec/ruby/library/set/sortedset/union_spec.rb
+++ b/spec/ruby/library/set/sortedset/union_spec.rb
@@ -1,11 +1,14 @@
require_relative '../../../spec_helper'
-require_relative 'shared/union'
-require 'set'
-describe "SortedSet#union" do
- it_behaves_like :sorted_set_union, :union
-end
+ruby_version_is ""..."3.0" do
+ require_relative 'shared/union'
+ require 'set'
+
+ describe "SortedSet#union" do
+ it_behaves_like :sorted_set_union, :union
+ end
-describe "SortedSet#|" do
- it_behaves_like :sorted_set_union, :|
+ describe "SortedSet#|" do
+ it_behaves_like :sorted_set_union, :|
+ end
end
diff --git a/spec/ruby/library/set/to_s_spec.rb b/spec/ruby/library/set/to_s_spec.rb
index ca2806d669..7b9f7b6603 100644
--- a/spec/ruby/library/set/to_s_spec.rb
+++ b/spec/ruby/library/set/to_s_spec.rb
@@ -1,13 +1,11 @@
require_relative 'shared/inspect'
require 'set'
-ruby_version_is "2.5" do
- describe "Set#to_s" do
- it_behaves_like :set_inspect, :to_s
+describe "Set#to_s" do
+ it_behaves_like :set_inspect, :to_s
- it "is an alias of inspect" do
- set = Set.new
- set.method(:to_s).should == set.method(:inspect)
- end
+ it "is an alias of inspect" do
+ set = Set.new
+ set.method(:to_s).should == set.method(:inspect)
end
end
diff --git a/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb b/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb
index c5284f1c0f..76579de74c 100644
--- a/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb
@@ -21,18 +21,20 @@ describe 'Addrinfo#getnameinfo' do
end
platform_is :linux do
- with_feature :unix_socket do
- describe 'using a UNIX Addrinfo' do
- before do
- @addr = Addrinfo.unix('cats')
- @host = Socket.gethostname
- end
+ platform_is_not :android do
+ with_feature :unix_socket do
+ describe 'using a UNIX Addrinfo' do
+ before do
+ @addr = Addrinfo.unix('cats')
+ @host = Socket.gethostname
+ end
- it 'returns the hostname and UNIX socket path' do
- host, path = @addr.getnameinfo
+ it 'returns the hostname and UNIX socket path' do
+ host, path = @addr.getnameinfo
- host.should == @host
- path.should == 'cats'
+ host.should == @host
+ path.should == 'cats'
+ end
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/initialize_spec.rb b/spec/ruby/library/socket/addrinfo/initialize_spec.rb
index 8354553f61..00250439fd 100644
--- a/spec/ruby/library/socket/addrinfo/initialize_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/initialize_spec.rb
@@ -274,15 +274,17 @@ describe "Addrinfo#initialize" do
end
end
- with_feature :sock_packet do
- [:SOCK_SEQPACKET].each do |type|
- it "overwrites the socket type #{type}" do
- sockaddr = ['AF_INET', 80, 'hostname', '127.0.0.1']
+ platform_is_not :android do
+ with_feature :sock_packet do
+ [:SOCK_SEQPACKET].each do |type|
+ it "overwrites the socket type #{type}" do
+ sockaddr = ['AF_INET', 80, 'hostname', '127.0.0.1']
- value = Socket.const_get(type)
- addr = Addrinfo.new(sockaddr, nil, value)
+ value = Socket.const_get(type)
+ addr = Addrinfo.new(sockaddr, nil, value)
- addr.socktype.should == value
+ addr.socktype.should == value
+ end
end
end
end
@@ -448,28 +450,30 @@ describe "Addrinfo#initialize" do
end
platform_is :linux do
- describe 'and the socket type is set to SOCK_SEQPACKET' do
- before do
- @socktype = Socket::SOCK_SEQPACKET
- end
+ platform_is_not :android do
+ describe 'and the socket type is set to SOCK_SEQPACKET' do
+ before do
+ @socktype = Socket::SOCK_SEQPACKET
+ end
- valid = [:IPPROTO_IP, :IPPROTO_HOPOPTS]
+ valid = [:IPPROTO_IP, :IPPROTO_HOPOPTS]
- valid.each do |type|
- it "overwrites the protocol when using #{type}" do
- value = Socket.const_get(type)
- addr = Addrinfo.new(@sockaddr, nil, @socktype, value)
+ valid.each do |type|
+ it "overwrites the protocol when using #{type}" do
+ value = Socket.const_get(type)
+ addr = Addrinfo.new(@sockaddr, nil, @socktype, value)
- addr.protocol.should == value
+ addr.protocol.should == value
+ end
end
- end
- (Socket.constants.grep(/^IPPROTO/) - valid).each do |type|
- it "raises SocketError when using #{type}" do
- value = Socket.const_get(type)
- block = -> { Addrinfo.new(@sockaddr, nil, @socktype, value) }
+ (Socket.constants.grep(/^IPPROTO/) - valid).each do |type|
+ it "raises SocketError when using #{type}" do
+ value = Socket.const_get(type)
+ block = -> { Addrinfo.new(@sockaddr, nil, @socktype, value) }
- block.should raise_error(SocketError)
+ block.should raise_error(SocketError)
+ end
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb
index f5bab711db..10ad084fc9 100644
--- a/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb
@@ -3,10 +3,10 @@ require_relative '../spec_helper'
describe "Addrinfo#ipv4_loopback?" do
describe "for an ipv4 socket" do
it "returns true for the loopback address" do
- Addrinfo.ip('127.0.0.1').ipv4_loopback?.should == true
- Addrinfo.ip('127.0.0.2').ipv4_loopback?.should == true
- Addrinfo.ip('127.255.0.1').ipv4_loopback?.should == true
- Addrinfo.ip('127.255.255.255').ipv4_loopback?.should == true
+ Addrinfo.ip('127.0.0.1').should.ipv4_loopback?
+ Addrinfo.ip('127.0.0.2').should.ipv4_loopback?
+ Addrinfo.ip('127.255.0.1').should.ipv4_loopback?
+ Addrinfo.ip('127.255.255.255').should.ipv4_loopback?
end
it "returns false for another address" do
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb
index bdd14c1b00..f7fead8640 100644
--- a/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb
@@ -2,17 +2,17 @@ require_relative '../spec_helper'
describe "Addrinfo#ipv4_multicast?" do
it 'returns true for a multicast address' do
- Addrinfo.ip('224.0.0.0').ipv4_multicast?.should == true
- Addrinfo.ip('224.0.0.9').ipv4_multicast?.should == true
- Addrinfo.ip('239.255.255.250').ipv4_multicast?.should == true
+ Addrinfo.ip('224.0.0.0').should.ipv4_multicast?
+ Addrinfo.ip('224.0.0.9').should.ipv4_multicast?
+ Addrinfo.ip('239.255.255.250').should.ipv4_multicast?
end
it 'returns false for a regular address' do
- Addrinfo.ip('8.8.8.8').ipv4_multicast?.should == false
+ Addrinfo.ip('8.8.8.8').should_not.ipv4_multicast?
end
it 'returns false for an IPv6 address' do
- Addrinfo.ip('::1').ipv4_multicast?.should == false
+ Addrinfo.ip('::1').should_not.ipv4_multicast?
end
with_feature :unix_socket do
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb
index 733577609e..e5a33b4953 100644
--- a/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb
@@ -8,14 +8,14 @@ describe "Addrinfo#ipv4_private?" do
end
it "returns true for a private address" do
- Addrinfo.ip('10.0.0.0').ipv4_private?.should == true
- Addrinfo.ip('10.0.0.5').ipv4_private?.should == true
+ Addrinfo.ip('10.0.0.0').should.ipv4_private?
+ Addrinfo.ip('10.0.0.5').should.ipv4_private?
- Addrinfo.ip('172.16.0.0').ipv4_private?.should == true
- Addrinfo.ip('172.16.0.5').ipv4_private?.should == true
+ Addrinfo.ip('172.16.0.0').should.ipv4_private?
+ Addrinfo.ip('172.16.0.5').should.ipv4_private?
- Addrinfo.ip('192.168.0.0').ipv4_private?.should == true
- Addrinfo.ip('192.168.0.5').ipv4_private?.should == true
+ Addrinfo.ip('192.168.0.0').should.ipv4_private?
+ Addrinfo.ip('192.168.0.5').should.ipv4_private?
end
it "returns false for a public address" do
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb
index 291b4d7d6b..bfef396381 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_linklocal_spec.rb
@@ -5,19 +5,19 @@ guard -> { SocketSpecs.ipv6_available? } do
describe 'Addrinfo#ipv6_linklocal?' do
platform_is_not :aix do
it 'returns true for a link-local address' do
- Addrinfo.ip('fe80::').ipv6_linklocal?.should == true
- Addrinfo.ip('fe81::').ipv6_linklocal?.should == true
- Addrinfo.ip('fe8f::').ipv6_linklocal?.should == true
- Addrinfo.ip('fe80::1').ipv6_linklocal?.should == true
+ Addrinfo.ip('fe80::').should.ipv6_linklocal?
+ Addrinfo.ip('fe81::').should.ipv6_linklocal?
+ Addrinfo.ip('fe8f::').should.ipv6_linklocal?
+ Addrinfo.ip('fe80::1').should.ipv6_linklocal?
end
end
it 'returns false for a regular address' do
- Addrinfo.ip('::1').ipv6_linklocal?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_linklocal?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_linklocal?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_linklocal?
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb
index 9c8e4dccb4..01fa0992ba 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_mc_global_spec.rb
@@ -2,19 +2,19 @@ require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_global?' do
it 'returns true for a multi-cast address in the global scope' do
- Addrinfo.ip('ff1e::').ipv6_mc_global?.should == true
- Addrinfo.ip('fffe::').ipv6_mc_global?.should == true
- Addrinfo.ip('ff0e::').ipv6_mc_global?.should == true
- Addrinfo.ip('ff1e::1').ipv6_mc_global?.should == true
+ Addrinfo.ip('ff1e::').should.ipv6_mc_global?
+ Addrinfo.ip('fffe::').should.ipv6_mc_global?
+ Addrinfo.ip('ff0e::').should.ipv6_mc_global?
+ Addrinfo.ip('ff1e::1').should.ipv6_mc_global?
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_mc_global?.should == false
- Addrinfo.ip('ff1a::').ipv6_mc_global?.should == false
- Addrinfo.ip('ff1f::1').ipv6_mc_global?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_mc_global?
+ Addrinfo.ip('ff1a::').should_not.ipv6_mc_global?
+ Addrinfo.ip('ff1f::1').should_not.ipv6_mc_global?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_mc_global?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_global?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb
index dd52a9ad8b..a1298919eb 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_mc_linklocal_spec.rb
@@ -2,18 +2,18 @@ require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_linklocal?' do
it 'returns true for a multi-cast link-local address' do
- Addrinfo.ip('ff12::').ipv6_mc_linklocal?.should == true
- Addrinfo.ip('ff02::').ipv6_mc_linklocal?.should == true
- Addrinfo.ip('fff2::').ipv6_mc_linklocal?.should == true
- Addrinfo.ip('ff12::1').ipv6_mc_linklocal?.should == true
+ Addrinfo.ip('ff12::').should.ipv6_mc_linklocal?
+ Addrinfo.ip('ff02::').should.ipv6_mc_linklocal?
+ Addrinfo.ip('fff2::').should.ipv6_mc_linklocal?
+ Addrinfo.ip('ff12::1').should.ipv6_mc_linklocal?
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_mc_linklocal?.should == false
- Addrinfo.ip('fff1::').ipv6_mc_linklocal?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_mc_linklocal?
+ Addrinfo.ip('fff1::').should_not.ipv6_mc_linklocal?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_mc_linklocal?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_linklocal?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb
index b3cf5ffbab..0aee952d88 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_mc_nodelocal_spec.rb
@@ -2,17 +2,17 @@ require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_nodelocal?' do
it 'returns true for a multi-cast node-local address' do
- Addrinfo.ip('ff11::').ipv6_mc_nodelocal?.should == true
- Addrinfo.ip('ff01::').ipv6_mc_nodelocal?.should == true
- Addrinfo.ip('fff1::').ipv6_mc_nodelocal?.should == true
- Addrinfo.ip('ff11::1').ipv6_mc_nodelocal?.should == true
+ Addrinfo.ip('ff11::').should.ipv6_mc_nodelocal?
+ Addrinfo.ip('ff01::').should.ipv6_mc_nodelocal?
+ Addrinfo.ip('fff1::').should.ipv6_mc_nodelocal?
+ Addrinfo.ip('ff11::1').should.ipv6_mc_nodelocal?
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_mc_nodelocal?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_mc_nodelocal?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_mc_nodelocal?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_nodelocal?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb
index 90653dd49c..2977a98d30 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_mc_orglocal_spec.rb
@@ -2,17 +2,17 @@ require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_orglocal?' do
it 'returns true for a multi-cast org-local address' do
- Addrinfo.ip('ff18::').ipv6_mc_orglocal?.should == true
- Addrinfo.ip('ff08::').ipv6_mc_orglocal?.should == true
- Addrinfo.ip('fff8::').ipv6_mc_orglocal?.should == true
- Addrinfo.ip('ff18::1').ipv6_mc_orglocal?.should == true
+ Addrinfo.ip('ff18::').should.ipv6_mc_orglocal?
+ Addrinfo.ip('ff08::').should.ipv6_mc_orglocal?
+ Addrinfo.ip('fff8::').should.ipv6_mc_orglocal?
+ Addrinfo.ip('ff18::1').should.ipv6_mc_orglocal?
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_mc_orglocal?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_mc_orglocal?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_mc_orglocal?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_orglocal?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb
index 686b625e0d..58e5976a40 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_mc_sitelocal_spec.rb
@@ -2,17 +2,17 @@ require_relative '../spec_helper'
describe 'Addrinfo#ipv6_mc_sitelocal?' do
it 'returns true for a multi-cast site-local address' do
- Addrinfo.ip('ff15::').ipv6_mc_sitelocal?.should == true
- Addrinfo.ip('ff05::').ipv6_mc_sitelocal?.should == true
- Addrinfo.ip('fff5::').ipv6_mc_sitelocal?.should == true
- Addrinfo.ip('ff15::1').ipv6_mc_sitelocal?.should == true
+ Addrinfo.ip('ff15::').should.ipv6_mc_sitelocal?
+ Addrinfo.ip('ff05::').should.ipv6_mc_sitelocal?
+ Addrinfo.ip('fff5::').should.ipv6_mc_sitelocal?
+ Addrinfo.ip('ff15::1').should.ipv6_mc_sitelocal?
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_mc_sitelocal?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_mc_sitelocal?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_mc_sitelocal?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_mc_sitelocal?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb
index c25322869c..2c987b5921 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb
@@ -18,19 +18,19 @@ describe "Addrinfo#ipv6_multicast?" do
describe "for an ipv6 socket" do
it "returns true for a multicast address" do
- Addrinfo.ip('ff00::').ipv6_multicast?.should == true
- Addrinfo.ip('ff00::1').ipv6_multicast?.should == true
- Addrinfo.ip('ff08::1').ipv6_multicast?.should == true
- Addrinfo.ip('fff8::1').ipv6_multicast?.should == true
-
- Addrinfo.ip('ff02::').ipv6_multicast?.should == true
- Addrinfo.ip('ff02::1').ipv6_multicast?.should == true
- Addrinfo.ip('ff0f::').ipv6_multicast?.should == true
+ Addrinfo.ip('ff00::').should.ipv6_multicast?
+ Addrinfo.ip('ff00::1').should.ipv6_multicast?
+ Addrinfo.ip('ff08::1').should.ipv6_multicast?
+ Addrinfo.ip('fff8::1').should.ipv6_multicast?
+
+ Addrinfo.ip('ff02::').should.ipv6_multicast?
+ Addrinfo.ip('ff02::1').should.ipv6_multicast?
+ Addrinfo.ip('ff0f::').should.ipv6_multicast?
end
it "returns false for another address" do
- Addrinfo.ip('::1').ipv6_multicast?.should == false
- Addrinfo.ip('fe80::').ipv6_multicast?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_multicast?
+ Addrinfo.ip('fe80::').should_not.ipv6_multicast?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb
index dd202a1749..9158eb5809 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_sitelocal_spec.rb
@@ -5,19 +5,19 @@ guard -> { SocketSpecs.ipv6_available? } do
describe 'Addrinfo#ipv6_sitelocal?' do
platform_is_not :aix do
it 'returns true for a site-local address' do
- Addrinfo.ip('feef::').ipv6_sitelocal?.should == true
- Addrinfo.ip('fee0::').ipv6_sitelocal?.should == true
- Addrinfo.ip('fee2::').ipv6_sitelocal?.should == true
- Addrinfo.ip('feef::1').ipv6_sitelocal?.should == true
+ Addrinfo.ip('feef::').should.ipv6_sitelocal?
+ Addrinfo.ip('fee0::').should.ipv6_sitelocal?
+ Addrinfo.ip('fee2::').should.ipv6_sitelocal?
+ Addrinfo.ip('feef::1').should.ipv6_sitelocal?
end
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_sitelocal?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_sitelocal?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_sitelocal?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_sitelocal?
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb
index b80a15fcb0..22f0fa3b75 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_unique_local_spec.rb
@@ -2,17 +2,17 @@ require_relative '../spec_helper'
describe 'Addrinfo#ipv6_unique_local?' do
it 'returns true for an unique local IPv6 address' do
- Addrinfo.ip('fc00::').ipv6_unique_local?.should == true
- Addrinfo.ip('fd00::').ipv6_unique_local?.should == true
- Addrinfo.ip('fcff::').ipv6_unique_local?.should == true
+ Addrinfo.ip('fc00::').should.ipv6_unique_local?
+ Addrinfo.ip('fd00::').should.ipv6_unique_local?
+ Addrinfo.ip('fcff::').should.ipv6_unique_local?
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_unique_local?.should == false
- Addrinfo.ip('fe00::').ipv6_unique_local?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_unique_local?
+ Addrinfo.ip('fe00::').should_not.ipv6_unique_local?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_unique_local?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_unique_local?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb
index dd79d57503..d63979ceda 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_unspecified_spec.rb
@@ -2,14 +2,14 @@ require_relative '../spec_helper'
describe 'Addrinfo#ipv6_unspecified?' do
it 'returns true for an unspecified IPv6 address' do
- Addrinfo.ip('::').ipv6_unspecified?.should == true
+ Addrinfo.ip('::').should.ipv6_unspecified?
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_unspecified?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_unspecified?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_unspecified?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_unspecified?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb
index ab8388a21b..21ca85af99 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_v4compat_spec.rb
@@ -2,19 +2,19 @@ require_relative '../spec_helper'
describe 'Addrinfo#ipv6_v4compat?' do
it 'returns true for an IPv4 compatible address' do
- Addrinfo.ip('::127.0.0.1').ipv6_v4compat?.should == true
- Addrinfo.ip('::192.168.1.1').ipv6_v4compat?.should == true
+ Addrinfo.ip('::127.0.0.1').should.ipv6_v4compat?
+ Addrinfo.ip('::192.168.1.1').should.ipv6_v4compat?
end
it 'returns false for an IPv4 mapped address' do
- Addrinfo.ip('::ffff:192.168.1.1').ipv6_v4compat?.should == false
+ Addrinfo.ip('::ffff:192.168.1.1').should_not.ipv6_v4compat?
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_v4compat?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_v4compat?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_v4compat?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_v4compat?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb
index 82b272c165..7dac0e75db 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_v4mapped_spec.rb
@@ -2,19 +2,19 @@ require_relative '../spec_helper'
describe 'Addrinfo#ipv6_v4mapped?' do
it 'returns true for an IPv4 compatible address' do
- Addrinfo.ip('::ffff:192.168.1.1').ipv6_v4mapped?.should == true
+ Addrinfo.ip('::ffff:192.168.1.1').should.ipv6_v4mapped?
end
it 'returns false for an IPv4 compatible address' do
- Addrinfo.ip('::192.168.1.1').ipv6_v4mapped?.should == false
- Addrinfo.ip('::127.0.0.1').ipv6_v4mapped?.should == false
+ Addrinfo.ip('::192.168.1.1').should_not.ipv6_v4mapped?
+ Addrinfo.ip('::127.0.0.1').should_not.ipv6_v4mapped?
end
it 'returns false for a regular IPv6 address' do
- Addrinfo.ip('::1').ipv6_v4mapped?.should == false
+ Addrinfo.ip('::1').should_not.ipv6_v4mapped?
end
it 'returns false for an IPv4 address' do
- Addrinfo.ip('127.0.0.1').ipv6_v4mapped?.should == false
+ Addrinfo.ip('127.0.0.1').should_not.ipv6_v4mapped?
end
end
diff --git a/spec/ruby/library/socket/addrinfo/listen_spec.rb b/spec/ruby/library/socket/addrinfo/listen_spec.rb
index 714a96ed6c..931093f732 100644
--- a/spec/ruby/library/socket/addrinfo/listen_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/listen_spec.rb
@@ -29,6 +29,6 @@ describe 'Addrinfo#listen' do
socket = sock
end
- socket.closed?.should == true
+ socket.should.closed?
end
end
diff --git a/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb b/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb
index 1823f3d75d..df44a50afa 100644
--- a/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/read_nonblock_spec.rb
@@ -1,45 +1,43 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-ruby_version_is "2.5" do
- describe "BasicSocket#read_nonblock" do
- SocketSpecs.each_ip_protocol do |family, ip_address|
- before :each do
- @r = Socket.new(family, :DGRAM)
- @w = Socket.new(family, :DGRAM)
+describe "BasicSocket#read_nonblock" do
+ SocketSpecs.each_ip_protocol do |family, ip_address|
+ before :each do
+ @r = Socket.new(family, :DGRAM)
+ @w = Socket.new(family, :DGRAM)
- @r.bind(Socket.pack_sockaddr_in(0, ip_address))
- @w.send("aaa", 0, @r.getsockname)
- end
+ @r.bind(Socket.pack_sockaddr_in(0, ip_address))
+ @w.send("aaa", 0, @r.getsockname)
+ end
- after :each do
- @r.close unless @r.closed?
- @w.close unless @w.closed?
- end
+ after :each do
+ @r.close unless @r.closed?
+ @w.close unless @w.closed?
+ end
- it "receives data after it's ready" do
- IO.select([@r], nil, nil, 2)
- @r.recv_nonblock(5).should == "aaa"
- end
+ it "receives data after it's ready" do
+ IO.select([@r], nil, nil, 2)
+ @r.recv_nonblock(5).should == "aaa"
+ end
- platform_is :linux do
- it 'does not set the IO in nonblock mode' do
- require 'io/nonblock'
- @r.nonblock?.should == false
- IO.select([@r], nil, nil, 2)
- @r.read_nonblock(3).should == "aaa"
- @r.nonblock?.should == false
- end
+ platform_is :linux do
+ it 'does not set the IO in nonblock mode' do
+ require 'io/nonblock'
+ @r.nonblock = false
+ IO.select([@r], nil, nil, 2)
+ @r.read_nonblock(3).should == "aaa"
+ @r.should_not.nonblock?
end
+ end
- platform_is_not :linux, :windows do
- it 'sets the IO in nonblock mode' do
- require 'io/nonblock'
- @r.nonblock?.should == false
- IO.select([@r], nil, nil, 2)
- @r.read_nonblock(3).should == "aaa"
- @r.nonblock?.should == true
- end
+ platform_is_not :linux, :windows do
+ it 'sets the IO in nonblock mode' do
+ require 'io/nonblock'
+ @r.nonblock = false
+ IO.select([@r], nil, nil, 2)
+ @r.read_nonblock(3).should == "aaa"
+ @r.should.nonblock?
end
end
end
diff --git a/spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb b/spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb
index f2e7366eb1..523e732959 100644
--- a/spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/write_nonblock_spec.rb
@@ -1,44 +1,42 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-ruby_version_is "2.5" do
- describe "BasicSocket#write_nonblock" do
- SocketSpecs.each_ip_protocol do |family, ip_address|
- before :each do
- @r = Socket.new(family, :DGRAM)
- @w = Socket.new(family, :DGRAM)
+describe "BasicSocket#write_nonblock" do
+ SocketSpecs.each_ip_protocol do |family, ip_address|
+ before :each do
+ @r = Socket.new(family, :DGRAM)
+ @w = Socket.new(family, :DGRAM)
- @r.bind(Socket.pack_sockaddr_in(0, ip_address))
- @w.connect(@r.getsockname)
- end
+ @r.bind(Socket.pack_sockaddr_in(0, ip_address))
+ @w.connect(@r.getsockname)
+ end
- after :each do
- @r.close unless @r.closed?
- @w.close unless @w.closed?
- end
+ after :each do
+ @r.close unless @r.closed?
+ @w.close unless @w.closed?
+ end
- it "sends data" do
- @w.write_nonblock("aaa").should == 3
- IO.select([@r], nil, nil, 2)
- @r.recv_nonblock(5).should == "aaa"
- end
+ it "sends data" do
+ @w.write_nonblock("aaa").should == 3
+ IO.select([@r], nil, nil, 2)
+ @r.recv_nonblock(5).should == "aaa"
+ end
- platform_is :linux do
- it 'does not set the IO in nonblock mode' do
- require 'io/nonblock'
- @w.nonblock?.should == false
- @w.write_nonblock("aaa").should == 3
- @w.nonblock?.should == false
- end
+ platform_is :linux do
+ it 'does not set the IO in nonblock mode' do
+ require 'io/nonblock'
+ @w.nonblock = false
+ @w.write_nonblock("aaa").should == 3
+ @w.should_not.nonblock?
end
+ end
- platform_is_not :linux, :windows do
- it 'sets the IO in nonblock mode' do
- require 'io/nonblock'
- @w.nonblock?.should == false
- @w.write_nonblock("aaa").should == 3
- @w.nonblock?.should == true
- end
+ platform_is_not :linux, :windows do
+ it 'sets the IO in nonblock mode' do
+ require 'io/nonblock'
+ @w.nonblock = false
+ @w.write_nonblock("aaa").should == 3
+ @w.should.nonblock?
end
end
end
diff --git a/spec/ruby/library/socket/constants/constants_spec.rb b/spec/ruby/library/socket/constants/constants_spec.rb
index 710af12828..637bc6740a 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 do
+ platform_is_not :solaris, :windows, :aix, :android do
it "defines multicast options" do
consts = ["IP_MAX_MEMBERSHIPS"]
consts.each do |c|
diff --git a/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb b/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb
index 5d97341103..a4c8355520 100644
--- a/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb
+++ b/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb
@@ -10,12 +10,12 @@ describe 'Socket.gethostbyaddr' do
describe 'without an explicit address family' do
it 'returns an Array' do
- Socket.gethostbyaddr(@addr).should be_an_instance_of(Array)
+ suppress_warning { Socket.gethostbyaddr(@addr) }.should be_an_instance_of(Array)
end
describe 'the returned Array' do
before do
- @array = Socket.gethostbyaddr(@addr)
+ @array = suppress_warning { Socket.gethostbyaddr(@addr) }
end
# RubyCI Solaris 11x defines 127.0.0.1 as unstable11x
@@ -49,15 +49,15 @@ describe 'Socket.gethostbyaddr' do
describe 'with an explicit address family' do
it 'returns an Array when using an Integer as the address family' do
- Socket.gethostbyaddr(@addr, Socket::AF_INET).should be_an_instance_of(Array)
+ suppress_warning { Socket.gethostbyaddr(@addr, Socket::AF_INET) }.should be_an_instance_of(Array)
end
it 'returns an Array when using a Symbol as the address family' do
- Socket.gethostbyaddr(@addr, :INET).should be_an_instance_of(Array)
+ suppress_warning { Socket.gethostbyaddr(@addr, :INET) }.should be_an_instance_of(Array)
end
it 'raises SocketError when the address is not supported by the family' do
- -> { Socket.gethostbyaddr(@addr, :INET6) }.should raise_error(SocketError)
+ -> { suppress_warning { Socket.gethostbyaddr(@addr, :INET6) } }.should raise_error(SocketError)
end
end
end
@@ -70,12 +70,12 @@ describe 'Socket.gethostbyaddr' do
describe 'without an explicit address family' do
it 'returns an Array' do
- Socket.gethostbyaddr(@addr).should be_an_instance_of(Array)
+ suppress_warning { Socket.gethostbyaddr(@addr) }.should be_an_instance_of(Array)
end
describe 'the returned Array' do
before do
- @array = Socket.gethostbyaddr(@addr)
+ @array = suppress_warning { Socket.gethostbyaddr(@addr) }
end
it 'includes the hostname as the first value' do
@@ -106,16 +106,16 @@ describe 'Socket.gethostbyaddr' do
describe 'with an explicit address family' do
it 'returns an Array when using an Integer as the address family' do
- Socket.gethostbyaddr(@addr, Socket::AF_INET6).should be_an_instance_of(Array)
+ suppress_warning { Socket.gethostbyaddr(@addr, Socket::AF_INET6) }.should be_an_instance_of(Array)
end
it 'returns an Array when using a Symbol as the address family' do
- Socket.gethostbyaddr(@addr, :INET6).should be_an_instance_of(Array)
+ suppress_warning { Socket.gethostbyaddr(@addr, :INET6) }.should be_an_instance_of(Array)
end
- platform_is_not :windows do
+ platform_is_not :windows, :wsl do
it 'raises SocketError when the address is not supported by the family' do
- -> { Socket.gethostbyaddr(@addr, :INET) }.should raise_error(SocketError)
+ -> { suppress_warning { Socket.gethostbyaddr(@addr, :INET) } }.should raise_error(SocketError)
end
end
end
diff --git a/spec/ruby/library/socket/socket/gethostbyname_spec.rb b/spec/ruby/library/socket/socket/gethostbyname_spec.rb
index 2696f44566..0858e255e4 100644
--- a/spec/ruby/library/socket/socket/gethostbyname_spec.rb
+++ b/spec/ruby/library/socket/socket/gethostbyname_spec.rb
@@ -4,24 +4,24 @@ require_relative '../fixtures/classes'
describe "Socket.gethostbyname" do
it "returns broadcast address info for '<broadcast>'" do
- addr = Socket.gethostbyname('<broadcast>');
+ addr = suppress_warning { Socket.gethostbyname('<broadcast>') }
addr.should == ["255.255.255.255", [], 2, "\xFF\xFF\xFF\xFF"]
end
it "returns broadcast address info for '<any>'" do
- addr = Socket.gethostbyname('<any>');
+ addr = suppress_warning { Socket.gethostbyname('<any>') }
addr.should == ["0.0.0.0", [], 2, "\x00\x00\x00\x00"]
end
end
describe 'Socket.gethostbyname' do
it 'returns an Array' do
- Socket.gethostbyname('127.0.0.1').should be_an_instance_of(Array)
+ suppress_warning { Socket.gethostbyname('127.0.0.1') }.should be_an_instance_of(Array)
end
describe 'the returned Array' do
before do
- @array = Socket.gethostbyname('127.0.0.1')
+ @array = suppress_warning { Socket.gethostbyname('127.0.0.1') }
end
it 'includes the hostname as the first value' do
@@ -54,7 +54,7 @@ describe 'Socket.gethostbyname' do
describe 'using <broadcast> as the input address' do
describe 'the returned Array' do
before do
- @addr = Socket.gethostbyname('<broadcast>')
+ @addr = suppress_warning { Socket.gethostbyname('<broadcast>') }
end
it 'includes the broadcast address as the first value' do
@@ -74,7 +74,7 @@ describe 'Socket.gethostbyname' do
describe 'using <any> as the input address' do
describe 'the returned Array' do
before do
- @addr = Socket.gethostbyname('<any>')
+ @addr = suppress_warning { Socket.gethostbyname('<any>') }
end
it 'includes the wildcard address as the first value' do
@@ -94,7 +94,7 @@ describe 'Socket.gethostbyname' do
describe 'using an IPv4 address' do
describe 'the returned Array' do
before do
- @addr = Socket.gethostbyname('127.0.0.1')
+ @addr = suppress_warning { Socket.gethostbyname('127.0.0.1') }
end
it 'includes the IP address as the first value' do
@@ -115,7 +115,7 @@ describe 'Socket.gethostbyname' do
describe 'using an IPv6 address' do
describe 'the returned Array' do
before do
- @addr = Socket.gethostbyname('::1')
+ @addr = suppress_warning { Socket.gethostbyname('::1') }
end
it 'includes the IP address as the first value' do
diff --git a/spec/ruby/library/socket/socket/listen_spec.rb b/spec/ruby/library/socket/socket/listen_spec.rb
index 5de70d6db0..4d2aedab19 100644
--- a/spec/ruby/library/socket/socket/listen_spec.rb
+++ b/spec/ruby/library/socket/socket/listen_spec.rb
@@ -34,8 +34,10 @@ describe 'Socket#listen' do
@server.close
end
- it 'raises Errno::EOPNOTSUPP' do
- -> { @server.listen(1) }.should raise_error(Errno::EOPNOTSUPP)
+ it 'raises Errno::EOPNOTSUPP or Errno::EACCES' do
+ -> { @server.listen(1) }.should raise_error { |e|
+ [Errno::EOPNOTSUPP, Errno::EACCES].should.include?(e.class)
+ }
end
end
diff --git a/spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb b/spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb
index 10c030a8ce..bd496d3015 100644
--- a/spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb
+++ b/spec/ruby/library/socket/socket/tcp_server_sockets_spec.rb
@@ -32,7 +32,7 @@ describe 'Socket.tcp_server_sockets' do
Socket.tcp_server_sockets(0) { |socks| sockets = socks }
sockets.each do |socket|
- socket.closed?.should == true
+ socket.should.closed?
end
end
end
diff --git a/spec/ruby/library/socket/socket/tcp_spec.rb b/spec/ruby/library/socket/socket/tcp_spec.rb
index d36e3e6adb..faf020b1ea 100644
--- a/spec/ruby/library/socket/socket/tcp_spec.rb
+++ b/spec/ruby/library/socket/socket/tcp_spec.rb
@@ -36,7 +36,7 @@ describe 'Socket.tcp' do
@socket = socket
end
- @socket.closed?.should == true
+ @socket.should.closed?
end
it 'binds to a local address and port when specified' do
diff --git a/spec/ruby/library/socket/socket/udp_server_sockets_spec.rb b/spec/ruby/library/socket/socket/udp_server_sockets_spec.rb
index 3aeb472dda..f8be672612 100644
--- a/spec/ruby/library/socket/socket/udp_server_sockets_spec.rb
+++ b/spec/ruby/library/socket/socket/udp_server_sockets_spec.rb
@@ -32,7 +32,7 @@ describe 'Socket.udp_server_sockets' do
Socket.udp_server_sockets(0) { |socks| sockets = socks }
sockets.each do |socket|
- socket.closed?.should == true
+ socket.should.closed?
end
end
end
diff --git a/spec/ruby/library/socket/socket/unix_spec.rb b/spec/ruby/library/socket/socket/unix_spec.rb
index add54a097d..4bff59bd4b 100644
--- a/spec/ruby/library/socket/socket/unix_spec.rb
+++ b/spec/ruby/library/socket/socket/unix_spec.rb
@@ -38,7 +38,7 @@ with_feature :unix_socket do
socket = sock
end
- socket.closed?.should == true
+ socket.should.closed?
end
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 bd95f1db08..12f970f89b 100644
--- a/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb
+++ b/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb
@@ -13,7 +13,7 @@ with_feature :unix_socket do
Socket.unpack_sockaddr_un(addrinfo).should == '/tmp/sock'
end
- it 'raises an ArgumentError when the sin_family is not AF_UNIX' do
+ it 'raises an ArgumentError when the sa_family is not AF_UNIX' do
sockaddr = Socket.sockaddr_in(0, '127.0.0.1')
-> { Socket.unpack_sockaddr_un(sockaddr) }.should raise_error(ArgumentError)
end
diff --git a/spec/ruby/library/socket/tcpserver/accept_spec.rb b/spec/ruby/library/socket/tcpserver/accept_spec.rb
index 0da4e2218b..d38d95e0e1 100644
--- a/spec/ruby/library/socket/tcpserver/accept_spec.rb
+++ b/spec/ruby/library/socket/tcpserver/accept_spec.rb
@@ -58,6 +58,26 @@ describe "TCPServer#accept" do
t.join
end
+ it "is automatically retried when interrupted by SIGVTALRM" do
+ t = Thread.new do
+ client = @server.accept
+ value = client.read(2)
+ client.close
+ value
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ # Thread#backtrace uses SIGVTALRM on TruffleRuby and potentially other implementations.
+ # Sending a signal to a thread is not possible with Ruby APIs.
+ t.backtrace.join("\n").should.include?("in `accept'")
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.write("OK")
+ socket.close
+
+ t.value.should == "OK"
+ end
+
it "raises an IOError if the socket is closed" do
@server.close
-> { @server.accept }.should raise_error(IOError)
diff --git a/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb b/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb
index 703abff81c..f0e98778f5 100644
--- a/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb
+++ b/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb
@@ -4,7 +4,9 @@ require_relative '../fixtures/classes'
# TODO: verify these for windows
describe "TCPSocket#gethostbyname" do
before :each do
- @host_info = TCPSocket.gethostbyname(SocketSpecs.hostname)
+ suppress_warning do
+ @host_info = TCPSocket.gethostbyname(SocketSpecs.hostname)
+ end
end
it "returns an array elements of information on the hostname" do
@@ -52,13 +54,17 @@ end
describe 'TCPSocket#gethostbyname' do
it 'returns an Array' do
- TCPSocket.gethostbyname('127.0.0.1').should be_an_instance_of(Array)
+ suppress_warning do
+ TCPSocket.gethostbyname('127.0.0.1').should be_an_instance_of(Array)
+ end
end
describe 'using a hostname' do
describe 'the returned Array' do
before do
- @array = TCPSocket.gethostbyname('127.0.0.1')
+ suppress_warning do
+ @array = TCPSocket.gethostbyname('127.0.0.1')
+ end
end
it 'includes the canonical name as the 1st value' do
@@ -88,7 +94,9 @@ describe 'TCPSocket#gethostbyname' do
SocketSpecs.each_ip_protocol do |family, ip_address|
describe 'the returned Array' do
before do
- @array = TCPSocket.gethostbyname(ip_address)
+ suppress_warning do
+ @array = TCPSocket.gethostbyname(ip_address)
+ end
end
it 'includes the IP address as the 1st value' do
diff --git a/spec/ruby/library/socket/udpsocket/inspect_spec.rb b/spec/ruby/library/socket/udpsocket/inspect_spec.rb
index 201e8b3fc6..e212120b14 100644
--- a/spec/ruby/library/socket/udpsocket/inspect_spec.rb
+++ b/spec/ruby/library/socket/udpsocket/inspect_spec.rb
@@ -10,16 +10,8 @@ describe 'UDPSocket#inspect' do
@socket.close
end
- ruby_version_is ""..."2.5" do
- it 'returns a String with the fd' do
- @socket.inspect.should == "#<UDPSocket:fd #{@socket.fileno}>"
- end
- end
-
- ruby_version_is "2.5" do
- it 'returns a String with the fd, family, address and port' do
- port = @socket.addr[1]
- @socket.inspect.should == "#<UDPSocket:fd #{@socket.fileno}, AF_INET, 127.0.0.1, #{port}>"
- end
+ it 'returns a String with the fd, family, address and port' do
+ port = @socket.addr[1]
+ @socket.inspect.should == "#<UDPSocket:fd #{@socket.fileno}, AF_INET, 127.0.0.1, #{port}>"
end
end
diff --git a/spec/ruby/library/socket/unixsocket/open_spec.rb b/spec/ruby/library/socket/unixsocket/open_spec.rb
index ad5048fedd..99ad151bb8 100644
--- a/spec/ruby/library/socket/unixsocket/open_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/open_spec.rb
@@ -21,7 +21,7 @@ describe "UNIXSocket.open" do
it "opens a unix socket on the specified file and yields it to the block" do
UNIXSocket.open(@path) do |client|
client.addr[0].should == "AF_UNIX"
- client.closed?.should == false
+ client.should_not.closed?
end
end
end
diff --git a/spec/ruby/library/socket/unixsocket/shared/new.rb b/spec/ruby/library/socket/unixsocket/shared/new.rb
index 76a4e1701e..bfb7ed3886 100644
--- a/spec/ruby/library/socket/unixsocket/shared/new.rb
+++ b/spec/ruby/library/socket/unixsocket/shared/new.rb
@@ -18,7 +18,7 @@ describe :unixsocket_new, shared: true do
@client = UNIXSocket.send(@method, @path)
@client.addr[0].should == "AF_UNIX"
- @client.closed?.should == false
+ @client.should_not.closed?
end
end
end
diff --git a/spec/ruby/library/stringio/append_spec.rb b/spec/ruby/library/stringio/append_spec.rb
index c46dc59ee5..d0cf5550cd 100644
--- a/spec/ruby/library/stringio/append_spec.rb
+++ b/spec/ruby/library/stringio/append_spec.rb
@@ -36,9 +36,11 @@ describe "StringIO#<< when passed [Object]" do
end
end
- it "does not taint self when the passed argument is tainted" do
- (@io << "test".taint)
- @io.tainted?.should be_false
+ ruby_version_is ""..."3.0" do
+ it "does not taint self when the passed argument is tainted" do
+ (@io << "test".taint)
+ @io.tainted?.should be_false
+ end
end
it "updates self's position" do
diff --git a/spec/ruby/library/stringio/binmode_spec.rb b/spec/ruby/library/stringio/binmode_spec.rb
index 5d9a8c41df..853d9c9bd6 100644
--- a/spec/ruby/library/stringio/binmode_spec.rb
+++ b/spec/ruby/library/stringio/binmode_spec.rb
@@ -6,4 +6,18 @@ describe "StringIO#binmode" do
io = StringIO.new("example")
io.binmode.should equal(io)
end
+
+ it "changes external encoding to BINARY" do
+ io = StringIO.new
+ io.external_encoding.should == Encoding.find('external')
+ io.binmode
+ io.external_encoding.should == Encoding::BINARY
+ end
+
+ it "does not set internal encoding" do
+ io = StringIO.new
+ io.internal_encoding.should == nil
+ io.binmode
+ io.internal_encoding.should == nil
+ end
end
diff --git a/spec/ruby/library/stringio/bytes_spec.rb b/spec/ruby/library/stringio/bytes_spec.rb
index 692fba997f..1c0607db6e 100644
--- a/spec/ruby/library/stringio/bytes_spec.rb
+++ b/spec/ruby/library/stringio/bytes_spec.rb
@@ -2,10 +2,12 @@ require_relative '../../spec_helper'
require 'stringio'
require_relative 'shared/each_byte'
-describe "StringIO#bytes" do
- it_behaves_like :stringio_each_byte, :bytes
-end
+ruby_version_is ''...'3.0' do
+ describe "StringIO#bytes" do
+ it_behaves_like :stringio_each_byte, :bytes
+ end
-describe "StringIO#bytes when self is not readable" do
- it_behaves_like :stringio_each_byte_not_readable, :bytes
+ describe "StringIO#bytes when self is not readable" do
+ it_behaves_like :stringio_each_byte_not_readable, :bytes
+ end
end
diff --git a/spec/ruby/library/stringio/chars_spec.rb b/spec/ruby/library/stringio/chars_spec.rb
index 7dc55d4b37..3383dcfc57 100644
--- a/spec/ruby/library/stringio/chars_spec.rb
+++ b/spec/ruby/library/stringio/chars_spec.rb
@@ -2,10 +2,12 @@ require_relative '../../spec_helper'
require 'stringio'
require_relative 'shared/each_char'
-describe "StringIO#chars" do
- it_behaves_like :stringio_each_char, :chars
-end
+ruby_version_is ''...'3.0' do
+ describe "StringIO#chars" do
+ it_behaves_like :stringio_each_char, :chars
+ end
-describe "StringIO#chars when self is not readable" do
- it_behaves_like :stringio_each_char_not_readable, :chars
+ describe "StringIO#chars when self is not readable" do
+ it_behaves_like :stringio_each_char_not_readable, :chars
+ end
end
diff --git a/spec/ruby/library/stringio/codepoints_spec.rb b/spec/ruby/library/stringio/codepoints_spec.rb
index cc2e5d1b5d..0dfaac2a29 100644
--- a/spec/ruby/library/stringio/codepoints_spec.rb
+++ b/spec/ruby/library/stringio/codepoints_spec.rb
@@ -3,7 +3,10 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/codepoints'
-# See redmine #1667
-describe "StringIO#codepoints" do
- it_behaves_like :stringio_codepoints, :codepoints
+ruby_version_is ''...'3.0' do
+
+ # See redmine #1667
+ describe "StringIO#codepoints" do
+ it_behaves_like :stringio_codepoints, :codepoints
+ end
end
diff --git a/spec/ruby/library/stringio/each_char_spec.rb b/spec/ruby/library/stringio/each_char_spec.rb
index 7305162ee6..14b2f09a17 100644
--- a/spec/ruby/library/stringio/each_char_spec.rb
+++ b/spec/ruby/library/stringio/each_char_spec.rb
@@ -7,5 +7,5 @@ describe "StringIO#each_char" do
end
describe "StringIO#each_char when self is not readable" do
- it_behaves_like :stringio_each_char_not_readable, :chars
+ it_behaves_like :stringio_each_char_not_readable, :each_char
end
diff --git a/spec/ruby/library/stringio/each_codepoint_spec.rb b/spec/ruby/library/stringio/each_codepoint_spec.rb
index 85aa34d9d8..f18de22aad 100644
--- a/spec/ruby/library/stringio/each_codepoint_spec.rb
+++ b/spec/ruby/library/stringio/each_codepoint_spec.rb
@@ -5,5 +5,5 @@ require_relative 'shared/codepoints'
# See redmine #1667
describe "StringIO#each_codepoint" do
- it_behaves_like :stringio_codepoints, :codepoints
+ it_behaves_like :stringio_codepoints, :each_codepoint
end
diff --git a/spec/ruby/library/stringio/getpass_spec.rb b/spec/ruby/library/stringio/getpass_spec.rb
new file mode 100644
index 0000000000..60fc64f0c5
--- /dev/null
+++ b/spec/ruby/library/stringio/getpass_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../spec_helper'
+require 'stringio'
+
+# This method is added by io/console on require.
+describe "StringIO#getpass" do
+ require 'io/console'
+
+ it "is defined by io/console" do
+ StringIO.new("example").should.respond_to?(:getpass)
+ end
+end
diff --git a/spec/ruby/library/stringio/gets_spec.rb b/spec/ruby/library/stringio/gets_spec.rb
index 69880672a3..97429e6a29 100644
--- a/spec/ruby/library/stringio/gets_spec.rb
+++ b/spec/ruby/library/stringio/gets_spec.rb
@@ -76,12 +76,13 @@ describe "StringIO#gets when passed no argument" do
@io.gets.should == "this is\n"
begin
- old_sep, $/ = $/, " "
+ old_sep = $/
+ suppress_warning {$/ = " "}
@io.gets.should == "an "
@io.gets.should == "example\nfor "
@io.gets.should == "StringIO#gets"
ensure
- $/ = old_sep
+ suppress_warning {$/ = old_sep}
end
end
diff --git a/spec/ruby/library/stringio/initialize_spec.rb b/spec/ruby/library/stringio/initialize_spec.rb
index 8aae47dacb..1e8096e3bb 100644
--- a/spec/ruby/library/stringio/initialize_spec.rb
+++ b/spec/ruby/library/stringio/initialize_spec.rb
@@ -110,9 +110,9 @@ describe "StringIO#initialize when passed [Object, mode]" do
io.closed_write?.should be_false
end
- it "raises a #{frozen_error_class} when passed a frozen String in truncate mode as StringIO backend" do
+ it "raises a FrozenError when passed a frozen String in truncate mode as StringIO backend" do
io = StringIO.allocate
- -> { io.send(:initialize, "example".freeze, IO::TRUNC) }.should raise_error(frozen_error_class)
+ -> { io.send(:initialize, "example".freeze, IO::TRUNC) }.should raise_error(FrozenError)
end
it "tries to convert the passed mode to a String using #to_str" do
@@ -184,7 +184,7 @@ describe "StringIO#initialize when passed no arguments" do
end
end
-describe "StringIO#initialize sets the encoding to" do
+describe "StringIO#initialize sets" do
before :each do
@external = Encoding.default_external
@internal = Encoding.default_internal
@@ -197,16 +197,26 @@ describe "StringIO#initialize sets the encoding to" do
Encoding.default_internal = @internal
end
- it "Encoding.default_external when passed no arguments" do
+ it "the encoding to Encoding.default_external when passed no arguments" do
io = StringIO.new
io.external_encoding.should == Encoding::ISO_8859_2
io.string.encoding.should == Encoding::ISO_8859_2
end
- it "the same as the encoding of the String when passed a String" do
+ it "the encoding to the encoding of the String when passed a String" do
s = ''.force_encoding(Encoding::EUC_JP)
io = StringIO.new(s)
- io.external_encoding.should == Encoding::EUC_JP
io.string.encoding.should == Encoding::EUC_JP
end
+
+ guard_not -> { # [Bug #16497]
+ stringio_version = StringIO.const_defined?(:VERSION) ? StringIO::VERSION : "0.0.2"
+ version_is(stringio_version, "0.0.3"..."0.1.1")
+ } do
+ it "the #external_encoding to the encoding of the String when passed a String" do
+ s = ''.force_encoding(Encoding::EUC_JP)
+ io = StringIO.new(s)
+ io.external_encoding.should == Encoding::EUC_JP
+ end
+ end
end
diff --git a/spec/ruby/library/stringio/inspect_spec.rb b/spec/ruby/library/stringio/inspect_spec.rb
new file mode 100644
index 0000000000..7c02f8d360
--- /dev/null
+++ b/spec/ruby/library/stringio/inspect_spec.rb
@@ -0,0 +1,19 @@
+require_relative '../../spec_helper'
+require "stringio"
+
+describe "StringIO#inspect" do
+ it "returns the same as #to_s" do
+ io = StringIO.new("example")
+ io.inspect.should == io.to_s
+ end
+
+ it "does not include the contents" do
+ io = StringIO.new("contents")
+ io.inspect.should_not include("contents")
+ end
+
+ it "uses the regular Object#inspect without any instance variable" do
+ io = StringIO.new("example")
+ io.inspect.should =~ /\A#<StringIO:0x\h+>\z/
+ end
+end
diff --git a/spec/ruby/library/stringio/lines_spec.rb b/spec/ruby/library/stringio/lines_spec.rb
index d9dd26c2e2..4a2aeac37e 100644
--- a/spec/ruby/library/stringio/lines_spec.rb
+++ b/spec/ruby/library/stringio/lines_spec.rb
@@ -2,18 +2,20 @@ require_relative '../../spec_helper'
require 'stringio'
require_relative 'shared/each'
-describe "StringIO#lines when passed a separator" do
- it_behaves_like :stringio_each_separator, :lines
-end
+ruby_version_is ''...'3.0' do
+ describe "StringIO#lines when passed a separator" do
+ it_behaves_like :stringio_each_separator, :lines
+ end
-describe "StringIO#lines when passed no arguments" do
- it_behaves_like :stringio_each_no_arguments, :lines
-end
+ describe "StringIO#lines when passed no arguments" do
+ it_behaves_like :stringio_each_no_arguments, :lines
+ end
-describe "StringIO#lines when self is not readable" do
- it_behaves_like :stringio_each_not_readable, :lines
-end
+ describe "StringIO#lines when self is not readable" do
+ it_behaves_like :stringio_each_not_readable, :lines
+ end
-describe "StringIO#lines when passed chomp" do
- it_behaves_like :stringio_each_chomp, :lines
+ describe "StringIO#lines when passed chomp" do
+ it_behaves_like :stringio_each_chomp, :lines
+ end
end
diff --git a/spec/ruby/library/stringio/open_spec.rb b/spec/ruby/library/stringio/open_spec.rb
index adb784c890..acab6e9056 100644
--- a/spec/ruby/library/stringio/open_spec.rb
+++ b/spec/ruby/library/stringio/open_spec.rb
@@ -134,8 +134,8 @@ describe "StringIO.open when passed [Object, mode]" do
io.closed_write?.should be_false
end
- it "raises a #{frozen_error_class} when passed a frozen String in truncate mode as StringIO backend" do
- -> { StringIO.open("example".freeze, IO::TRUNC) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed a frozen String in truncate mode as StringIO backend" do
+ -> { StringIO.open("example".freeze, IO::TRUNC) }.should raise_error(FrozenError)
end
it "tries to convert the passed mode to a String using #to_str" do
diff --git a/spec/ruby/library/stringio/print_spec.rb b/spec/ruby/library/stringio/print_spec.rb
index d0f07d1e50..6ac6430900 100644
--- a/spec/ruby/library/stringio/print_spec.rb
+++ b/spec/ruby/library/stringio/print_spec.rb
@@ -39,13 +39,14 @@ describe "StringIO#print" do
end
it "honors the output record separator global" do
- old_rs, $\ = $\, 'x'
+ old_rs = $\
+ suppress_warning {$\ = 'x'}
begin
@io.print(5, 6, 7, 8)
@io.string.should == '5678xle'
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
@@ -58,13 +59,14 @@ describe "StringIO#print" do
end
it "correctly updates the current position when honoring the output record separator global" do
- old_rs, $\ = $\, 'x'
+ old_rs = $\
+ suppress_warning {$\ = 'x'}
begin
@io.print(5, 6, 7, 8)
@io.pos.should eql(5)
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
end
diff --git a/spec/ruby/library/stringio/printf_spec.rb b/spec/ruby/library/stringio/printf_spec.rb
index f88ca1eb20..9dd1a3b410 100644
--- a/spec/ruby/library/stringio/printf_spec.rb
+++ b/spec/ruby/library/stringio/printf_spec.rb
@@ -32,7 +32,7 @@ describe "StringIO#printf" do
describe "formatting" do
it_behaves_like :kernel_sprintf, -> format, *args {
- io = StringIO.new
+ io = StringIO.new(+"")
io.printf(format, *args)
io.string
}
diff --git a/spec/ruby/library/stringio/puts_spec.rb b/spec/ruby/library/stringio/puts_spec.rb
index 2d3db25c5f..a9f289a5a5 100644
--- a/spec/ruby/library/stringio/puts_spec.rb
+++ b/spec/ruby/library/stringio/puts_spec.rb
@@ -30,11 +30,12 @@ describe "StringIO#puts when passed an Array" do
it "does not honor the global output record separator $\\" do
begin
- old_rs, $\ = $\, "test"
+ old_rs = $\
+ suppress_warning {$\ = "test"}
@io.puts([1, 2, 3, 4])
@io.string.should == "1\n2\n3\n4\n"
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
@@ -68,11 +69,12 @@ describe "StringIO#puts when passed 1 or more objects" do
it "does not honor the global output record separator $\\" do
begin
- old_rs, $\ = $\, "test"
+ old_rs = $\
+ suppress_warning {$\ = "test"}
@io.puts(1, 2, 3, 4)
@io.string.should == "1\n2\n3\n4\n"
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
@@ -117,11 +119,12 @@ describe "StringIO#puts when passed no arguments" do
it "does not honor the global output record separator $\\" do
begin
- old_rs, $\ = $\, "test"
+ old_rs = $\
+ suppress_warning {$\ = "test"}
@io.puts
@io.string.should == "\n"
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
end
diff --git a/spec/ruby/library/stringio/readline_spec.rb b/spec/ruby/library/stringio/readline_spec.rb
index 9af633472e..94b67bc92d 100644
--- a/spec/ruby/library/stringio/readline_spec.rb
+++ b/spec/ruby/library/stringio/readline_spec.rb
@@ -64,12 +64,13 @@ describe "StringIO#readline when passed no argument" do
@io.readline.should == "this is\n"
begin
- old_sep, $/ = $/, " "
+ old_sep = $/
+ suppress_warning {$/ = " "}
@io.readline.should == "an "
@io.readline.should == "example\nfor "
@io.readline.should == "StringIO#readline"
ensure
- $/ = old_sep
+ suppress_warning {$/ = old_sep}
end
end
diff --git a/spec/ruby/library/stringio/readlines_spec.rb b/spec/ruby/library/stringio/readlines_spec.rb
index 7f9f9f5846..4b007787e2 100644
--- a/spec/ruby/library/stringio/readlines_spec.rb
+++ b/spec/ruby/library/stringio/readlines_spec.rb
@@ -51,10 +51,11 @@ describe "StringIO#readlines when passed no argument" do
it "returns an Array containing lines based on $/" do
begin
- old_sep, $/ = $/, " "
+ old_sep = $/;
+ suppress_warning {$/ = " "}
@io.readlines.should == ["this ", "is\nan ", "example\nfor ", "StringIO#readlines"]
ensure
- $/ = old_sep
+ suppress_warning {$/ = old_sep}
end
end
diff --git a/spec/ruby/library/stringio/reopen_spec.rb b/spec/ruby/library/stringio/reopen_spec.rb
index 34e38a63b4..6752cf9970 100644
--- a/spec/ruby/library/stringio/reopen_spec.rb
+++ b/spec/ruby/library/stringio/reopen_spec.rb
@@ -23,13 +23,15 @@ describe "StringIO#reopen when passed [Object, Integer]" do
@io.string.should == "reopened, another time"
end
- # NOTE: WEIRD!
- it "does not taint self when the passed Object was tainted" do
- @io.reopen("reopened".taint, IO::RDONLY)
- @io.tainted?.should be_false
-
- @io.reopen("reopened".taint, IO::WRONLY)
- @io.tainted?.should be_false
+ ruby_version_is ""..."3.0" do
+ # NOTE: WEIRD!
+ it "does not taint self when the passed Object was tainted" do
+ @io.reopen("reopened".taint, IO::RDONLY)
+ @io.tainted?.should be_false
+
+ @io.reopen("reopened".taint, IO::WRONLY)
+ @io.tainted?.should be_false
+ end
end
it "tries to convert the passed Object to a String using #to_str" do
@@ -48,8 +50,8 @@ describe "StringIO#reopen when passed [Object, Integer]" do
-> { @io.reopen("burn".freeze, IO::WRONLY | IO::APPEND) }.should raise_error(Errno::EACCES)
end
- it "raises a #{frozen_error_class} when trying to reopen self with a frozen String in truncate-mode" do
- -> { @io.reopen("burn".freeze, IO::RDONLY | IO::TRUNC) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when trying to reopen self with a frozen String in truncate-mode" do
+ -> { @io.reopen("burn".freeze, IO::RDONLY | IO::TRUNC) }.should raise_error(FrozenError)
end
it "does not raise IOError when passed a frozen String in read-mode" do
@@ -90,13 +92,15 @@ describe "StringIO#reopen when passed [Object, Object]" do
str.should == ""
end
- # NOTE: WEIRD!
- it "does not taint self when the passed Object was tainted" do
- @io.reopen("reopened".taint, "r")
- @io.tainted?.should be_false
+ ruby_version_is ""..."3.0" do
+ # NOTE: WEIRD!
+ it "does not taint self when the passed Object was tainted" do
+ @io.reopen("reopened".taint, "r")
+ @io.tainted?.should be_false
- @io.reopen("reopened".taint, "w")
- @io.tainted?.should be_false
+ @io.reopen("reopened".taint, "w")
+ @io.tainted?.should be_false
+ end
end
it "tries to convert the passed Object to a String using #to_str" do
@@ -160,10 +164,12 @@ describe "StringIO#reopen when passed [String]" do
@io.string.should == "reopened"
end
- # NOTE: WEIRD!
- it "does not taint self when the passed Object was tainted" do
- @io.reopen("reopened".taint)
- @io.tainted?.should be_false
+ ruby_version_is ""..."3.0" do
+ # NOTE: WEIRD!
+ it "does not taint self when the passed Object was tainted" do
+ @io.reopen("reopened".taint)
+ @io.tainted?.should be_false
+ end
end
it "resets self's position to 0" do
@@ -277,7 +283,7 @@ describe "StringIO#reopen" do
new_io = StringIO.new("tainted")
new_io.taint
@io.reopen(new_io)
- @io.tainted?.should == true
+ @io.should.tainted?
end
end
diff --git a/spec/ruby/library/stringio/shared/each.rb b/spec/ruby/library/stringio/shared/each.rb
index c08d40344c..14b0a013b3 100644
--- a/spec/ruby/library/stringio/shared/each.rb
+++ b/spec/ruby/library/stringio/shared/each.rb
@@ -71,11 +71,12 @@ describe :stringio_each_no_arguments, shared: true do
it "uses $/ as the default line separator" do
seen = []
begin
- old_rs, $/ = $/, " "
+ old_rs = $/
+ suppress_warning {$/ = " "}
@io.send(@method) {|s| seen << s }
seen.should eql(["a ", "b ", "c ", "d ", "e\n1 ", "2 ", "3 ", "4 ", "5"])
ensure
- $/ = old_rs
+ suppress_warning {$/ = old_rs}
end
end
diff --git a/spec/ruby/library/stringio/shared/read.rb b/spec/ruby/library/stringio/shared/read.rb
index 15ce58ae6a..c60677bba7 100644
--- a/spec/ruby/library/stringio/shared/read.rb
+++ b/spec/ruby/library/stringio/shared/read.rb
@@ -27,8 +27,8 @@ describe :stringio_read, shared: true do
-> { @io.send(@method, 7, Object.new) }.should raise_error(TypeError)
end
- it "raises a #{frozen_error_class} error when passed a frozen String as buffer" do
- -> { @io.send(@method, 7, "".freeze) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError error when passed a frozen String as buffer" do
+ -> { @io.send(@method, 7, "".freeze) }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/library/stringio/shared/write.rb b/spec/ruby/library/stringio/shared/write.rb
index 28683e3cb1..080729217b 100644
--- a/spec/ruby/library/stringio/shared/write.rb
+++ b/spec/ruby/library/stringio/shared/write.rb
@@ -52,9 +52,11 @@ describe :stringio_write_string, shared: true do
end
end
- it "does not taint self when the passed argument is tainted" do
- @io.send(@method, "test".taint)
- @io.tainted?.should be_false
+ ruby_version_is ""..."3.0" do
+ it "does not taint self when the passed argument is tainted" do
+ @io.send(@method, "test".taint)
+ @io.tainted?.should be_false
+ end
end
end
diff --git a/spec/ruby/library/stringscanner/append_spec.rb b/spec/ruby/library/stringscanner/append_spec.rb
index 378c62e2b1..fef5dcf2bd 100644
--- a/spec/ruby/library/stringscanner/append_spec.rb
+++ b/spec/ruby/library/stringscanner/append_spec.rb
@@ -6,6 +6,6 @@ describe "StringScanner#<<" do
it_behaves_like :strscan_concat, :<<
end
-describe "StringScanner#<< when passed a Fixnum" do
+describe "StringScanner#<< when passed an Integer" do
it_behaves_like :strscan_concat_fixnum, :<<
end
diff --git a/spec/ruby/library/stringscanner/concat_spec.rb b/spec/ruby/library/stringscanner/concat_spec.rb
index 17a699dd2e..4f790e2505 100644
--- a/spec/ruby/library/stringscanner/concat_spec.rb
+++ b/spec/ruby/library/stringscanner/concat_spec.rb
@@ -6,6 +6,6 @@ describe "StringScanner#concat" do
it_behaves_like :strscan_concat, :concat
end
-describe "StringScanner#concat when passed a Fixnum" do
+describe "StringScanner#concat when passed an Integer" do
it_behaves_like :strscan_concat_fixnum, :concat
end
diff --git a/spec/ruby/library/stringscanner/shared/peek.rb b/spec/ruby/library/stringscanner/shared/peek.rb
index 4e2e643353..768f5f2d58 100644
--- a/spec/ruby/library/stringscanner/shared/peek.rb
+++ b/spec/ruby/library/stringscanner/shared/peek.rb
@@ -22,7 +22,7 @@ describe :strscan_peek, shared: true do
-> { @s.send(@method, -2) }.should raise_error(ArgumentError)
end
- it "raises a RangeError when the passed argument is a Bignum" do
+ it "raises a RangeError when the passed argument is an Integer" do
-> { @s.send(@method, bignum_value) }.should raise_error(RangeError)
end
diff --git a/spec/ruby/library/syslog/close_spec.rb b/spec/ruby/library/syslog/close_spec.rb
index 8186ecf125..8c3b67c05b 100644
--- a/spec/ruby/library/syslog/close_spec.rb
+++ b/spec/ruby/library/syslog/close_spec.rb
@@ -30,7 +30,7 @@ platform_is_not :windows do
-> {
Syslog.open { |s| s.close }
}.should raise_error(RuntimeError)
- Syslog.opened?.should == false
+ Syslog.should_not.opened?
end
it "sets the identity to nil" do
diff --git a/spec/ruby/library/syslog/ident_spec.rb b/spec/ruby/library/syslog/ident_spec.rb
index e8345ebb49..3b08327140 100644
--- a/spec/ruby/library/syslog/ident_spec.rb
+++ b/spec/ruby/library/syslog/ident_spec.rb
@@ -21,7 +21,7 @@ platform_is_not :windows do
end
it "returns nil if the log is closed" do
- Syslog.opened?.should == false
+ Syslog.should_not.opened?
Syslog.ident.should == nil
end
diff --git a/spec/ruby/library/syslog/log_spec.rb b/spec/ruby/library/syslog/log_spec.rb
index 389da775b1..8589fb1f73 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 do
+ platform_is_not :windows, :darwin, :solaris, :aix, :android do
before :each do
Syslog.opened?.should be_false
diff --git a/spec/ruby/library/syslog/mask_spec.rb b/spec/ruby/library/syslog/mask_spec.rb
index 6581f6a756..b3f1250b24 100644
--- a/spec/ruby/library/syslog/mask_spec.rb
+++ b/spec/ruby/library/syslog/mask_spec.rb
@@ -32,7 +32,7 @@ platform_is_not :windows do
end
it "returns nil if the log is closed" do
- Syslog.opened?.should == false
+ Syslog.should_not.opened?
Syslog.mask.should == nil
end
diff --git a/spec/ruby/library/syslog/shared/log.rb b/spec/ruby/library/syslog/shared/log.rb
index 2947f5d062..12e4ea8366 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 do
+ platform_is_not :windows, :darwin, :solaris, :aix, :android do
before :each do
Syslog.opened?.should be_false
end
diff --git a/spec/ruby/library/timeout/timeout_spec.rb b/spec/ruby/library/timeout/timeout_spec.rb
index a9a60fdeb9..584b38d8ec 100644
--- a/spec/ruby/library/timeout/timeout_spec.rb
+++ b/spec/ruby/library/timeout/timeout_spec.rb
@@ -18,6 +18,22 @@ describe "Timeout.timeout" do
end.should raise_error(StandardError)
end
+ it "raises specified error type with specified message when it times out" do
+ -> do
+ Timeout.timeout(1, StandardError, "foobar") do
+ sleep
+ end
+ end.should raise_error(StandardError, "foobar")
+ end
+
+ it "raises specified error type with a default message when it times out if message is nil" do
+ -> do
+ Timeout.timeout(1, StandardError, nil) do
+ sleep
+ end
+ end.should raise_error(StandardError, "execution expired")
+ end
+
it "returns back the last value in the block" do
Timeout.timeout(1) do
42
diff --git a/spec/ruby/library/weakref/weakref_alive_spec.rb b/spec/ruby/library/weakref/weakref_alive_spec.rb
index 173ea01485..1ebf9c1ee3 100644
--- a/spec/ruby/library/weakref/weakref_alive_spec.rb
+++ b/spec/ruby/library/weakref/weakref_alive_spec.rb
@@ -5,7 +5,7 @@ describe "WeakRef#weakref_alive?" do
it "returns true if the object is reachable" do
obj = Object.new
ref = WeakRef.new(obj)
- ref.weakref_alive?.should == true
+ ref.weakref_alive?.should be_true
end
it "returns a falsy value if the object is no longer reachable" do
diff --git a/spec/ruby/library/win32ole/win32ole_param/input_spec.rb b/spec/ruby/library/win32ole/win32ole_param/input_spec.rb
index a0022fef13..e2a90daa56 100644
--- a/spec/ruby/library/win32ole/win32ole_param/input_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/input_spec.rb
@@ -13,7 +13,7 @@ platform_is :windows do
end
it "returns true for 3rd parameter of FileSystemObject's 'CopyFile' method" do
- @param_overwritefiles.input?.should == true
+ @param_overwritefiles.should.input?
end
end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb
index c15f64c2c5..4f240b561c 100644
--- a/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb
@@ -9,7 +9,7 @@ platform_is :windows do
@var = ole_type.variables[0]
end
- it "returns a Integer" do
+ it "returns an Integer" do
# according to doc, this could return nil
@var.value.should be_kind_of Integer
end
diff --git a/spec/ruby/library/yaml/add_builtin_type_spec.rb b/spec/ruby/library/yaml/add_builtin_type_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/add_builtin_type_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/add_domain_type_spec.rb b/spec/ruby/library/yaml/add_domain_type_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/add_domain_type_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/add_private_type_spec.rb b/spec/ruby/library/yaml/add_private_type_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/add_private_type_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/add_ruby_type_spec.rb b/spec/ruby/library/yaml/add_ruby_type_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/add_ruby_type_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/detect_implicit_spec.rb b/spec/ruby/library/yaml/detect_implicit_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/detect_implicit_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/dump_spec.rb b/spec/ruby/library/yaml/dump_spec.rb
index 5af794b7f8..3107a8f51d 100644
--- a/spec/ruby/library/yaml/dump_spec.rb
+++ b/spec/ruby/library/yaml/dump_spec.rb
@@ -37,7 +37,12 @@ describe "YAML.dump" do
it "dumps an OpenStruct" do
require "ostruct"
os = OpenStruct.new("age" => 20, "name" => "John")
- YAML.dump(os).should match_yaml("--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n")
+ yaml_dump = YAML.dump(os)
+
+ [
+ "--- !ruby/object:OpenStruct\nage: 20\nname: John\n",
+ "--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n",
+ ].should.include?(yaml_dump)
end
it "dumps a File without any state" do
diff --git a/spec/ruby/library/yaml/each_node_spec.rb b/spec/ruby/library/yaml/each_node_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/each_node_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/emitter_spec.rb b/spec/ruby/library/yaml/emitter_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/emitter_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/generic_parser_spec.rb b/spec/ruby/library/yaml/generic_parser_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/generic_parser_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/load_documents_spec.rb b/spec/ruby/library/yaml/load_documents_spec.rb
deleted file mode 100644
index 27edbcaa86..0000000000
--- a/spec/ruby/library/yaml/load_documents_spec.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
-require_relative 'fixtures/strings'
-require_relative 'shared/each_document'
-
-ruby_version_is ''...'2.5' do
- describe "YAML.load_documents" do
- it_behaves_like :yaml_each_document, :load_documents
- end
-end
diff --git a/spec/ruby/library/yaml/object_maker_spec.rb b/spec/ruby/library/yaml/object_maker_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/object_maker_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/parse_documents_spec.rb b/spec/ruby/library/yaml/parse_documents_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/parse_documents_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/parser_spec.rb b/spec/ruby/library/yaml/parser_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/parser_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/quick_emit_spec.rb b/spec/ruby/library/yaml/quick_emit_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/quick_emit_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/read_type_class_spec.rb b/spec/ruby/library/yaml/read_type_class_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/read_type_class_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/tagurize_spec.rb b/spec/ruby/library/yaml/tagurize_spec.rb
deleted file mode 100644
index cc1b757ce9..0000000000
--- a/spec/ruby/library/yaml/tagurize_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
-
-ruby_version_is ''...'2.5' do
- describe "YAML.tagurize" do
- it "converts a type_id to a taguri" do
- YAML.tagurize('wtf').should == "tag:yaml.org,2002:wtf"
- YAML.tagurize(1).should == 1
- end
- end
-end
diff --git a/spec/ruby/library/yaml/transfer_spec.rb b/spec/ruby/library/yaml/transfer_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/transfer_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/yaml/try_implicit_spec.rb b/spec/ruby/library/yaml/try_implicit_spec.rb
deleted file mode 100644
index 44c820940f..0000000000
--- a/spec/ruby/library/yaml/try_implicit_spec.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/common'
diff --git a/spec/ruby/library/zlib/adler32_spec.rb b/spec/ruby/library/zlib/adler32_spec.rb
index 62240e2de7..226aa18522 100644
--- a/spec/ruby/library/zlib/adler32_spec.rb
+++ b/spec/ruby/library/zlib/adler32_spec.rb
@@ -22,7 +22,7 @@ describe "Zlib.adler32" do
-> { Zlib.adler32(test_string, 2**128) }.should raise_error(RangeError)
end
- it "calculates the Adler checksum for string and initial Adler value for Bignums" do
+ it "calculates the Adler checksum for string and initial Adler value for Integers" do
test_string = "This is a test string! How exciting!%?"
Zlib.adler32(test_string, 2**30).should == 1137642779
end
diff --git a/spec/ruby/library/zlib/crc32_spec.rb b/spec/ruby/library/zlib/crc32_spec.rb
index 4c1d6ce2e9..d5f5c199cc 100644
--- a/spec/ruby/library/zlib/crc32_spec.rb
+++ b/spec/ruby/library/zlib/crc32_spec.rb
@@ -29,7 +29,7 @@ describe "Zlib.crc32" do
-> { Zlib.crc32(test_string, 2**128) }.should raise_error(RangeError)
end
- it "calculates the CRC checksum for string and initial CRC value for Bignums" do
+ it "calculates the CRC checksum for string and initial CRC value for Integers" do
test_string = "This is a test string! How exciting!%?"
# Zlib.crc32(test_string, -2**30).should == 277228695
Zlib.crc32(test_string, 2**30).should == 46597132
diff --git a/spec/ruby/library/zlib/gzipfile/close_spec.rb b/spec/ruby/library/zlib/gzipfile/close_spec.rb
index 870870f2fa..964b5ffb4d 100644
--- a/spec/ruby/library/zlib/gzipfile/close_spec.rb
+++ b/spec/ruby/library/zlib/gzipfile/close_spec.rb
@@ -8,7 +8,7 @@ describe "Zlib::GzipFile#close" do
Zlib::GzipWriter.wrap io do |gzio|
gzio.close
- gzio.closed?.should == true
+ gzio.should.closed?
-> { gzio.orig_name }.should \
raise_error(Zlib::GzipFile::Error, 'closed gzip stream')
diff --git a/spec/ruby/library/zlib/gzipfile/closed_spec.rb b/spec/ruby/library/zlib/gzipfile/closed_spec.rb
index b885add485..726f391b41 100644
--- a/spec/ruby/library/zlib/gzipfile/closed_spec.rb
+++ b/spec/ruby/library/zlib/gzipfile/closed_spec.rb
@@ -6,11 +6,11 @@ describe "Zlib::GzipFile#closed?" do
it "returns the closed status" do
io = StringIO.new
Zlib::GzipWriter.wrap io do |gzio|
- gzio.closed?.should == false
+ gzio.should_not.closed?
gzio.close
- gzio.closed?.should == true
+ gzio.should.closed?
end
end
end
diff --git a/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb b/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb
index 59a0622903..63676a8203 100644
--- a/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb
+++ b/spec/ruby/library/zlib/zstream/flush_next_out_spec.rb
@@ -8,7 +8,7 @@ describe "Zlib::ZStream#flush_next_out" do
zs << [120, 156, 75, 203, 207, 7, 0, 2, 130, 1, 69].pack('C*')
zs.flush_next_out.should == 'foo'
- zs.finished?.should == true
+ zs.should.finished?
zs.flush_next_out.should == ''
end
end
diff --git a/spec/ruby/optional/capi/README b/spec/ruby/optional/capi/README
index 57b0c51f01..069ca3c106 100644
--- a/spec/ruby/optional/capi/README
+++ b/spec/ruby/optional/capi/README
@@ -8,9 +8,6 @@ specs:
optional/capi/array_spec.rb
2. Put the C file containing the C functions for array_spec.rb in
optional/capi/ext/array_spec.c
-3. Add a '#define HAVE_RB_ARY_NEW 1' to rubyspec.h
-4. Name the C extension class 'CApiArraySpecs'.
-5. Name the C functions 'array_spec_rb_ary_new'.
-6. Wrap the code in the optional/capi/ext/array_spec.c in
- '#ifdef HAVE_RB_ARY_NEW'
-7. Attach the C function to the class using the name 'rb_ary_new'
+3. Name the C extension class 'CApiArraySpecs'.
+4. Name the C functions 'array_spec_rb_ary_new'.
+5. Attach the C function to the class using the name 'rb_ary_new'
diff --git a/spec/ruby/optional/capi/array_spec.rb b/spec/ruby/optional/capi/array_spec.rb
index cf65bc19b6..8d003fb2b1 100644
--- a/spec/ruby/optional/capi/array_spec.rb
+++ b/spec/ruby/optional/capi/array_spec.rb
@@ -83,8 +83,8 @@ describe "C-API Array function" do
@s.rb_ary_cat([1, 2], 3, 4).should == [1, 2, 3, 4]
end
- it "raises a #{frozen_error_class} if the array is frozen" do
- -> { @s.rb_ary_cat([].freeze, 1) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if the array is frozen" do
+ -> { @s.rb_ary_cat([].freeze, 1) }.should raise_error(FrozenError)
end
end
@@ -130,8 +130,8 @@ describe "C-API Array function" do
@s.rb_ary_rotate([1, 2, 3, 4], -3).should == [2, 3, 4, 1]
end
- it "raises a #{frozen_error_class} if the array is frozen" do
- -> { @s.rb_ary_rotate([].freeze, 1) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if the array is frozen" do
+ -> { @s.rb_ary_rotate([].freeze, 1) }.should raise_error(FrozenError)
end
end
@@ -190,6 +190,22 @@ describe "C-API Array function" do
end
end
+ describe "rb_ary_sort" do
+ it "returns a new sorted array" do
+ a = [2, 1, 3]
+ @s.rb_ary_sort(a).should == [1, 2, 3]
+ a.should == [2, 1, 3]
+ end
+ end
+
+ describe "rb_ary_sort_bang" do
+ it "sorts the given array" do
+ a = [2, 1, 3]
+ @s.rb_ary_sort_bang(a).should == [1, 2, 3]
+ a.should == [1, 2, 3]
+ end
+ end
+
describe "rb_ary_store" do
it "overwrites the element at the given position" do
a = [1, 2, 3]
@@ -214,9 +230,9 @@ describe "C-API Array function" do
a.should == [nil, nil, 7]
end
- it "raises a #{frozen_error_class} if the array is frozen" do
+ it "raises a FrozenError if the array is frozen" do
a = [1, 2, 3].freeze
- -> { @s.rb_ary_store(a, 1, 5) }.should raise_error(frozen_error_class)
+ -> { @s.rb_ary_store(a, 1, 5) }.should raise_error(FrozenError)
end
end
@@ -272,6 +288,16 @@ describe "C-API Array function" do
end
end
+ describe "RARRAY_ASET" do
+ # This macro does NOT do any bounds checking!
+ it "writes an element in the array" do
+ ary = [1, 2, 3]
+ @s.RARRAY_ASET(ary, 0, 0)
+ @s.RARRAY_ASET(ary, 2, 42)
+ ary.should == [0, 2, 42]
+ end
+ end
+
describe "rb_assoc_new" do
it "returns an array containing the two elements" do
@s.rb_assoc_new(1, 2).should == [1, 2]
diff --git a/spec/ruby/optional/capi/basic_object_spec.rb b/spec/ruby/optional/capi/basic_object_spec.rb
new file mode 100644
index 0000000000..2922a421da
--- /dev/null
+++ b/spec/ruby/optional/capi/basic_object_spec.rb
@@ -0,0 +1,24 @@
+require_relative 'spec_helper'
+
+load_extension("basic_object")
+
+describe "C-API basic object" do
+ before :each do
+ @s = CApiBasicObjectSpecs.new
+ end
+
+ describe "RBASIC_CLASS" do
+ it "returns the class of an object" do
+ c = Class.new
+ o = c.new
+ @s.RBASIC_CLASS(o).should == c
+ end
+
+ it "returns the singleton class" do
+ o = Object.new
+ @s.RBASIC_CLASS(o).should == Object
+ singleton_class = o.singleton_class
+ @s.RBASIC_CLASS(o).should == singleton_class
+ end
+ end
+end
diff --git a/spec/ruby/optional/capi/class_spec.rb b/spec/ruby/optional/capi/class_spec.rb
index 0b03fb9e6c..c2424668b9 100644
--- a/spec/ruby/optional/capi/class_spec.rb
+++ b/spec/ruby/optional/capi/class_spec.rb
@@ -1,5 +1,6 @@
require_relative 'spec_helper'
require_relative 'fixtures/class'
+require_relative '../../core/module/fixtures/classes'
load_extension("class")
compile_extension("class_under_autoload")
@@ -39,6 +40,69 @@ describe "C-API Class function" do
@s = CApiClassSpecs.new
end
+ describe "rb_class_instance_methods" do
+ it "returns the public and protected methods of self and its ancestors" do
+ methods = @s.rb_class_instance_methods(ModuleSpecs::Basic)
+ methods.should include(:protected_module, :public_module)
+
+ methods = @s.rb_class_instance_methods(ModuleSpecs::Basic, true)
+ methods.should include(:protected_module, :public_module)
+ end
+
+ it "when passed false as a parameter, returns the instance methods of the class" do
+ methods = @s.rb_class_instance_methods(ModuleSpecs::Child, false)
+ methods.should include(:protected_child, :public_child)
+ end
+ end
+
+ describe "rb_class_public_instance_methods" do
+ it "returns a list of public methods in module and its ancestors" do
+ methods = @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild)
+ methods.should include(:public_3)
+ methods.should include(:public_2)
+ methods.should include(:public_1)
+
+ methods = @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, true)
+ methods.should include(:public_3)
+ methods.should include(:public_2)
+ methods.should include(:public_1)
+ end
+
+ it "when passed false as a parameter, should return only methods defined in that module" do
+ @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, false).should == [:public_1]
+ end
+ end
+
+ describe "rb_class_protected_instance_methods" do
+ it "returns a list of protected methods in module and its ancestors" do
+ methods = @s.rb_class_protected_instance_methods(ModuleSpecs::CountsChild)
+ methods.should include(:protected_3)
+ methods.should include(:protected_2)
+ methods.should include(:protected_1)
+
+ methods = @s.rb_class_protected_instance_methods(ModuleSpecs::CountsChild, true)
+ methods.should include(:protected_3)
+ methods.should include(:protected_2)
+ methods.should include(:protected_1)
+ end
+
+ it "when passed false as a parameter, should return only methods defined in that module" do
+ @s.rb_class_public_instance_methods(ModuleSpecs::CountsChild, false).should == [:public_1]
+ end
+ end
+
+ describe "rb_class_private_instance_methods" do
+ it "returns a list of private methods in module and its ancestors" do
+ @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild).should == ModuleSpecs::CountsChild.private_instance_methods
+ @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild, true).should == ModuleSpecs::CountsChild.private_instance_methods
+ end
+
+ it "when passed false as a parameter, should return only methods defined in that module" do
+ methods = @s.rb_class_private_instance_methods(ModuleSpecs::CountsChild, false)
+ methods.should == [:private_1]
+ end
+ end
+
describe "rb_class_new_instance" do
it "allocates and initializes a new object" do
o = @s.rb_class_new_instance(0, nil, CApiClassSpecs::Alloc)
@@ -338,7 +402,7 @@ describe "C-API Class function" do
end
describe "rb_class_new" do
- it "returns an new subclass of the superclass" do
+ it "returns a new subclass of the superclass" do
subclass = @s.rb_class_new(CApiClassSpecs::NewClass)
CApiClassSpecs::NewClass.should be_ancestor_of(subclass)
end
diff --git a/spec/ruby/optional/capi/constants_spec.rb b/spec/ruby/optional/capi/constants_spec.rb
index 11a328a91f..172d10a788 100644
--- a/spec/ruby/optional/capi/constants_spec.rb
+++ b/spec/ruby/optional/capi/constants_spec.rb
@@ -11,24 +11,42 @@ describe "C-API constant" do
@s.rb_cArray.should == Array
end
+ specify "rb_cBasicObject references the BasicObject class" do
+ @s.rb_cBasicObject.should == BasicObject
+ end
+
+ specify "rb_cBinding references the Binding class" do
+ @s.rb_cBinding.should == Binding
+ end
+
specify "rb_cClass references the Class class" do
@s.rb_cClass.should == Class
end
+ specify "rb_cComplex references the Complex class" do
+ @s.rb_cComplex.should == Complex
+ end
+
specify "rb_mComparable references the Comparable module" do
@s.rb_mComparable.should == Comparable
end
- ruby_version_is ""..."2.5" do
- specify "rb_cData references the Data class" do
- @s.rb_cData.should == Data
- end
+ specify "rb_cDir references the Dir class" do
+ @s.rb_cDir.should == Dir
+ end
+
+ specify "rb_cEncoding references the Encoding class" do
+ @s.rb_cEncoding.should == Encoding
end
specify "rb_mEnumerable references the Enumerable module" do
@s.rb_mEnumerable.should == Enumerable
end
+ specify "rb_cEnumerator references the Enumerator class" do
+ @s.rb_cEnumerator.should == Enumerator
+ end
+
specify "rb_cFalseClass references the FalseClass class" do
@s.rb_cFalseClass.should == FalseClass
end
@@ -37,10 +55,18 @@ describe "C-API constant" do
@s.rb_cFile.should == File
end
+ specify "rb_mFileTest references the FileTest module" do
+ @s.rb_mFileTest.should == FileTest
+ end
+
specify "rb_cFloat references the Float class" do
@s.rb_cFloat.should == Float
end
+ specify "rb_mGC references the GC module" do
+ @s.rb_mGC.should == GC
+ end
+
specify "rb_cHash references the Hash class" do
@s.rb_cHash.should == Hash
end
@@ -57,10 +83,18 @@ describe "C-API constant" do
@s.rb_mKernel.should == Kernel
end
+ specify "rb_mMath references the Math module" do
+ @s.rb_mMath.should == Math
+ end
+
specify "rb_cMatch references the MatchData class" do
@s.rb_cMatch.should == MatchData
end
+ specify "rb_cMethod references the Method class" do
+ @s.rb_cMethod.should == Method
+ end
+
specify "rb_cModule references the Module class" do
@s.rb_cModule.should == Module
end
@@ -77,14 +111,34 @@ describe "C-API constant" do
@s.rb_cObject.should == Object
end
+ specify "rb_cProc references the Proc class" do
+ @s.rb_cProc.should == Proc
+ end
+
+ specify "rb_mProcess references the Process module" do
+ @s.rb_mProcess.should == Process
+ end
+
+ specify "rb_cRandom references the Random class" do
+ @s.rb_cRandom.should == Random
+ end
+
specify "rb_cRange references the Range class" do
@s.rb_cRange.should == Range
end
+ specify "rb_cRational references the Rational class" do
+ @s.rb_cRational.should == Rational
+ end
+
specify "rb_cRegexp references the Regexp class" do
@s.rb_cRegexp.should == Regexp
end
+ specify "rb_cStat references the File::Stat class" do
+ @s.rb_cStat.should == File::Stat
+ end
+
specify "rb_cString references the String class" do
@s.rb_cString.should == String
end
@@ -109,18 +163,9 @@ describe "C-API constant" do
@s.rb_cTrueClass.should == TrueClass
end
- specify "rb_cProc references the Proc class" do
- @s.rb_cProc.should == Proc
- end
-
- specify "rb_cMethod references the Method class" do
- @s.rb_cMethod.should == Method
- end
-
- specify "rb_cDir references the Dir class" do
- @s.rb_cDir.should == Dir
+ specify "rb_cUnboundMethod references the UnboundMethod class" do
+ @s.rb_cUnboundMethod.should == UnboundMethod
end
-
end
describe "C-API exception constant" do
@@ -132,6 +177,14 @@ describe "C-API exception constant" do
@s.rb_eArgError.should == ArgumentError
end
+ specify "rb_eEncodingError references the EncodingError class" do
+ @s.rb_eEncodingError.should == EncodingError
+ end
+
+ specify "rb_eEncCompatError references the Encoding::CompatibilityError" do
+ @s.rb_eEncCompatError.should == Encoding::CompatibilityError
+ end
+
specify "rb_eEOFError references the EOFError class" do
@s.rb_eEOFError.should == EOFError
end
@@ -144,10 +197,20 @@ describe "C-API exception constant" do
@s.rb_eException.should == Exception
end
+ specify "rb_eFatal references the fatal class" do
+ fatal = @s.rb_eFatal
+ fatal.should be_kind_of(Class)
+ fatal.should < Exception
+ end
+
specify "rb_eFloatDomainError references the FloatDomainError class" do
@s.rb_eFloatDomainError.should == FloatDomainError
end
+ specify "rb_eFrozenError references the FrozenError class" do
+ @s.rb_eFrozenError.should == FrozenError
+ end
+
specify "rb_eIndexError references the IndexError class" do
@s.rb_eIndexError.should == IndexError
end
@@ -160,6 +223,10 @@ describe "C-API exception constant" do
@s.rb_eIOError.should == IOError
end
+ specify "rb_eKeyError references the KeyError class" do
+ @s.rb_eKeyError.should == KeyError
+ end
+
specify "rb_eLoadError references the LoadError class" do
@s.rb_eLoadError.should == LoadError
end
@@ -172,10 +239,6 @@ describe "C-API exception constant" do
@s.rb_eMathDomainError.should == Math::DomainError
end
- specify "rb_eEncCompatError references the Encoding::CompatibilityError" do
- @s.rb_eEncCompatError.should == Encoding::CompatibilityError
- end
-
specify "rb_eNameError references the NameError class" do
@s.rb_eNameError.should == NameError
end
@@ -220,6 +283,10 @@ describe "C-API exception constant" do
@s.rb_eStandardError.should == StandardError
end
+ specify "rb_eStopIteration references the StopIteration class" do
+ @s.rb_eStopIteration.should == StopIteration
+ end
+
specify "rb_eSyntaxError references the SyntaxError class" do
@s.rb_eSyntaxError.should == SyntaxError
end
diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb
index 003edc9669..93bde54069 100644
--- a/spec/ruby/optional/capi/encoding_spec.rb
+++ b/spec/ruby/optional/capi/encoding_spec.rb
@@ -58,6 +58,15 @@ describe "C-API Encoding function" do
end
end
+ describe "rb_enc_codelen" do
+ it "returns the correct length for the given codepoint" do
+ @s.rb_enc_codelen(0x24, Encoding::UTF_8).should == 1
+ @s.rb_enc_codelen(0xA2, Encoding::UTF_8).should == 2
+ @s.rb_enc_codelen(0x20AC, Encoding::UTF_8).should == 3
+ @s.rb_enc_codelen(0x24B62, Encoding::UTF_8).should == 4
+ end
+ end
+
describe "rb_enc_find" do
it "returns the encoding of an Encoding" do
@s.rb_enc_find("UTF-8").should == "UTF-8"
@@ -82,12 +91,66 @@ describe "C-API Encoding function" do
end
end
+ describe "rb_enc_isalnum" do
+ it "returns non-zero for alpha-numeric characters" do
+ @s.rb_enc_isalnum("a".ord, Encoding::US_ASCII).should == true
+ @s.rb_enc_isalnum("2".ord, Encoding::US_ASCII).should == true
+ @s.rb_enc_isalnum("a".ord, Encoding::UTF_8).should == true
+ @s.rb_enc_isalnum("2".ord, Encoding::UTF_8).should == true
+ @s.rb_enc_isalnum("é".encode(Encoding::ISO_8859_1).ord, Encoding::ISO_8859_1).should == true
+ end
+
+ it "returns zero for non alpha-numeric characters" do
+ @s.rb_enc_isalnum("-".ord, Encoding::US_ASCII).should == false
+ @s.rb_enc_isalnum(" ".ord, Encoding::US_ASCII).should == false
+ @s.rb_enc_isalnum("-".ord, Encoding::UTF_8).should == false
+ @s.rb_enc_isalnum(" ".ord, Encoding::UTF_8).should == false
+ end
+ end
+
+ describe "rb_enc_isspace" do
+ it "returns non-zero for space characters" do
+ @s.rb_enc_isspace(" ".ord, Encoding::US_ASCII).should == true
+ @s.rb_enc_isspace(" ".ord, Encoding::UTF_8).should == true
+ end
+
+ it "returns zero for non space characters" do
+ @s.rb_enc_isspace("-".ord, Encoding::US_ASCII).should == false
+ @s.rb_enc_isspace("A".ord, Encoding::US_ASCII).should == false
+ @s.rb_enc_isspace("3".ord, Encoding::US_ASCII).should == false
+ @s.rb_enc_isspace("-".ord, Encoding::UTF_8).should == false
+ @s.rb_enc_isspace("A".ord, Encoding::UTF_8).should == false
+ @s.rb_enc_isspace("3".ord, Encoding::UTF_8).should == false
+ end
+ end
+
describe "rb_enc_from_index" do
it "returns an Encoding" do
@s.rb_enc_from_index(0).should be_an_instance_of(String)
end
end
+ describe "rb_enc_mbc_to_codepoint" do
+ it "returns the correct codepoint for the given character and size" do
+ @s.rb_enc_mbc_to_codepoint("é", 2).should == 0x00E9
+ @s.rb_enc_mbc_to_codepoint("éa", 2).should == 0x00E9
+ @s.rb_enc_mbc_to_codepoint("éa", 1).should == 0xC3
+ @s.rb_enc_mbc_to_codepoint("éa", 3).should == 0x00E9
+ end
+ end
+
+ describe "rb_enc_mbcput" do
+ it "writes the correct bytes to the buffer" do
+ @s.rb_enc_mbcput(0x24, Encoding::UTF_8).should == "$"
+ @s.rb_enc_mbcput(0xA2, Encoding::UTF_8).should == "¢"
+ @s.rb_enc_mbcput(0x20AC, Encoding::UTF_8).should == "€"
+ @s.rb_enc_mbcput(0x24B62, Encoding::UTF_8).should == "𤭢"
+
+ @s.rb_enc_mbcput(0x24, Encoding::UTF_16BE).bytes.should == [0, 0x24]
+ @s.rb_enc_mbcput(0x24B62, Encoding::UTF_16LE).bytes.should == [82, 216, 98, 223]
+ end
+ end
+
describe "rb_usascii_encoding" do
it "returns the encoding for Encoding::US_ASCII" do
@s.rb_usascii_encoding.should == "US-ASCII"
@@ -131,6 +194,29 @@ describe "C-API Encoding function" do
end
end
+ describe "rb_enc_precise_mbclen" do
+ it "returns the correct length for single byte characters" do
+ @s.rb_enc_precise_mbclen("hello", 7).should == 1
+ @s.rb_enc_precise_mbclen("hello", 5).should == 1
+ @s.rb_enc_precise_mbclen("hello", 1).should == 1
+ @s.rb_enc_precise_mbclen("hello", 0).should == -2
+ @s.rb_enc_precise_mbclen("hello", -1).should == -2
+ @s.rb_enc_precise_mbclen("hello", -5).should == -2
+ end
+
+ it "returns the correct length for multi-byte characters" do
+ @s.rb_enc_precise_mbclen("ésumé", 2).should == 2
+ @s.rb_enc_precise_mbclen("ésumé", 3).should == 2
+ @s.rb_enc_precise_mbclen("ésumé", 0).should == -2
+ @s.rb_enc_precise_mbclen("ésumé", 1).should == -2
+ @s.rb_enc_precise_mbclen("あ", 20).should == 3
+ @s.rb_enc_precise_mbclen("あ", 3).should == 3
+ @s.rb_enc_precise_mbclen("あ", 2).should == -2
+ @s.rb_enc_precise_mbclen("あ", 0).should == -2
+ @s.rb_enc_precise_mbclen("あ", -2).should == -2
+ end
+ end
+
describe "rb_obj_encoding" do
it "returns the encoding associated with an object" do
str = "abc".encode Encoding::BINARY
@@ -173,6 +259,26 @@ describe "C-API Encoding function" do
end
end
+ describe "rb_enc_str_new_cstr" do
+ it "creates a new ruby string from a c string literal" do
+ result = @s.rb_enc_str_new_cstr_constant(Encoding::US_ASCII)
+ result.should == "test string literal"
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "creates a new ruby string from a c string variable" do
+ result = @s.rb_enc_str_new_cstr("test string", Encoding::US_ASCII)
+ result.should == "test string"
+ result.encoding.should == Encoding::US_ASCII
+ end
+
+ it "when null encoding is given with a c string literal, it creates a new ruby string with ASCII_8BIT encoding" do
+ result = @s.rb_enc_str_new_cstr_constant(nil)
+ result.should == "test string literal"
+ result.encoding.should == Encoding::ASCII_8BIT
+ end
+ end
+
describe "rb_enc_str_coderange" do
describe "when the encoding is BINARY" do
it "returns ENC_CODERANGE_7BIT if there are no high bits set" do
@@ -217,6 +323,17 @@ describe "C-API Encoding function" do
end
end
+ describe "MBCLEN_CHARFOUND_P" do
+ it "returns non-zero for valid character" do
+ @s.MBCLEN_CHARFOUND_P("a".ord).should == 1
+ end
+
+ it "returns zero for invalid characters" do
+ @s.MBCLEN_CHARFOUND_P(0).should == 0
+ @s.MBCLEN_CHARFOUND_P(-1).should == 0
+ end
+ end
+
describe "ENCODING_GET" do
it_behaves_like :rb_enc_get_index, :ENCODING_GET
end
@@ -257,6 +374,14 @@ describe "C-API Encoding function" do
@s.rb_to_encoding(obj).should == "UTF-8"
end
+
+ describe "when the rb_encoding struct is stored in native memory" do
+ it "can still read the name of the encoding" do
+ address = @s.rb_to_encoding_native_store(Encoding::UTF_8)
+ address.should be_kind_of(Integer)
+ @s.rb_to_encoding_native_name(address).should == "UTF-8"
+ end
+ end
end
describe "rb_to_encoding_index" do
@@ -312,7 +437,7 @@ describe "C-API Encoding function" do
end
it "sets the encoding of a Regexp to that of the second argument" do
- @s.rb_enc_copy(/regexp/, @obj).encoding.should == Encoding::US_ASCII
+ @s.rb_enc_copy(/regexp/.dup, @obj).encoding.should == Encoding::US_ASCII
end
end
@@ -363,7 +488,7 @@ describe "C-API Encoding function" do
end
it "sets the encoding of a Regexp to the encoding" do
- @s.rb_enc_associate(/regexp/, "BINARY").encoding.should == Encoding::BINARY
+ @s.rb_enc_associate(/regexp/.dup, "BINARY").encoding.should == Encoding::BINARY
end
it "sets the encoding of a String to a default when the encoding is NULL" do
@@ -380,7 +505,7 @@ describe "C-API Encoding function" do
it "sets the encoding of a Regexp to the encoding" do
index = @s.rb_enc_find_index("UTF-8")
- enc = @s.rb_enc_associate_index(/regexp/, index).encoding
+ enc = @s.rb_enc_associate_index(/regexp/.dup, index).encoding
enc.should == Encoding::UTF_8
end
@@ -479,4 +604,48 @@ describe "C-API Encoding function" do
length.should == 4
end
end
+
+ describe "rb_enc_str_asciionly_p" do
+ it "returns true for an ASCII string" do
+ @s.rb_enc_str_asciionly_p("hello").should be_true
+ end
+
+ it "returns false for a non-ASCII string" do
+ @s.rb_enc_str_asciionly_p("hüllo").should be_false
+ end
+ end
+
+ describe "rb_uv_to_utf8" do
+ it 'converts a Unicode codepoint to a UTF-8 C string' do
+ str = ' ' * 6
+ {
+ 0 => "\x01",
+ 0x7f => "\xC2\x80",
+ 0x7ff => "\xE0\xA0\x80",
+ 0xffff => "\xF0\x90\x80\x80",
+ 0x1fffff => "\xF8\x88\x80\x80\x80",
+ 0x3ffffff => "\xFC\x84\x80\x80\x80\x80",
+ }.each do |num, result|
+ len = @s.rb_uv_to_utf8(str, num + 1)
+ str[0..len-1].should == result
+ end
+ end
+ end
+
+ describe "ONIGENC_MBC_CASE_FOLD" do
+ it "returns the correct case fold for the given string" do
+ @s.ONIGENC_MBC_CASE_FOLD("lower").should == ["l", 1]
+ @s.ONIGENC_MBC_CASE_FOLD("Upper").should == ["u", 1]
+ end
+
+ it "works with other encodings" do
+ @s.ONIGENC_MBC_CASE_FOLD("lower".force_encoding("binary")).should == ["l", 1]
+ @s.ONIGENC_MBC_CASE_FOLD("Upper".force_encoding("binary")).should == ["u", 1]
+ @s.ONIGENC_MBC_CASE_FOLD("É").should == ["é", 2]
+
+ str, length = @s.ONIGENC_MBC_CASE_FOLD('$'.encode(Encoding::UTF_16BE))
+ length.should == 2
+ str.bytes.should == [0, 0x24]
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/exception_spec.rb b/spec/ruby/optional/capi/exception_spec.rb
index 62d7d3706e..9e82e5c7dd 100644
--- a/spec/ruby/optional/capi/exception_spec.rb
+++ b/spec/ruby/optional/capi/exception_spec.rb
@@ -55,4 +55,49 @@ describe "C-API Exception function" do
-> { @s.rb_set_errinfo("error") }.should raise_error(TypeError)
end
end
+
+ describe "rb_make_exception" do
+ it "returns a RuntimeError when given a String argument" do
+ e = @s.rb_make_exception(["Message"])
+ e.class.should == RuntimeError
+ e.message.should == "Message"
+ end
+
+ it "returns the exception when given an Exception argument" do
+ exc = Exception.new
+ e = @s.rb_make_exception([exc])
+ e.should == exc
+ end
+
+ it "returns the exception with the given class and message" do
+ e = @s.rb_make_exception([Exception, "Message"])
+ e.class.should == Exception
+ e.message.should == "Message"
+ end
+
+ it "returns the exception with the given class, message, and backtrace" do
+ e = @s.rb_make_exception([Exception, "Message", ["backtrace 1"]])
+ e.class.should == Exception
+ e.message.should == "Message"
+ e.backtrace.should == ["backtrace 1"]
+ end
+
+ it "raises a TypeError for incorrect types" do
+ -> { @s.rb_make_exception([nil]) }.should raise_error(TypeError)
+ -> { @s.rb_make_exception([Object.new]) }.should raise_error(TypeError)
+ obj = Object.new
+ def obj.exception
+ "not exception type"
+ end
+ -> { @s.rb_make_exception([obj]) }.should raise_error(TypeError)
+ end
+
+ it "raises an ArgumentError for too many arguments" do
+ -> { @s.rb_make_exception([Exception, "Message", ["backtrace 1"], "extra"]) }.should raise_error(ArgumentError)
+ end
+
+ it "returns nil for empty arguments" do
+ @s.rb_make_exception([]).should == nil
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/ext/array_spec.c b/spec/ruby/optional/capi/ext/array_spec.c
index 454cf03303..39ed1ed18b 100644
--- a/spec/ruby/optional/capi/ext/array_spec.c
+++ b/spec/ruby/optional/capi/ext/array_spec.c
@@ -54,6 +54,11 @@ static VALUE array_spec_RARRAY_AREF(VALUE self, VALUE array, VALUE index) {
return RARRAY_AREF(array, FIX2INT(index));
}
+static VALUE array_spec_RARRAY_ASET(VALUE self, VALUE array, VALUE index, VALUE value) {
+ RARRAY_ASET(array, FIX2INT(index), value);
+ return value;
+}
+
static VALUE array_spec_rb_ary_aref(int argc, VALUE *argv, VALUE self) {
VALUE ary, args;
rb_scan_args(argc, argv, "1*", &ary, &args);
@@ -157,6 +162,14 @@ static VALUE array_spec_rb_ary_shift(VALUE self, VALUE array) {
return rb_ary_shift(array);
}
+static VALUE array_spec_rb_ary_sort(VALUE self, VALUE array) {
+ return rb_ary_sort(array);
+}
+
+static VALUE array_spec_rb_ary_sort_bang(VALUE self, VALUE array) {
+ return rb_ary_sort_bang(array);
+}
+
static VALUE array_spec_rb_ary_store(VALUE self, VALUE array, VALUE offset, VALUE value) {
rb_ary_store(array, FIX2INT(offset), value);
@@ -244,6 +257,7 @@ void Init_array_spec(void) {
rb_define_method(cls, "RARRAY_PTR_assign", array_spec_RARRAY_PTR_assign, 2);
rb_define_method(cls, "RARRAY_PTR_memcpy", array_spec_RARRAY_PTR_memcpy, 2);
rb_define_method(cls, "RARRAY_AREF", array_spec_RARRAY_AREF, 2);
+ rb_define_method(cls, "RARRAY_ASET", array_spec_RARRAY_ASET, 3);
rb_define_method(cls, "rb_ary_aref", array_spec_rb_ary_aref, -1);
rb_define_method(cls, "rb_ary_clear", array_spec_rb_ary_clear, 1);
rb_define_method(cls, "rb_ary_delete", array_spec_rb_ary_delete, 2);
@@ -266,6 +280,8 @@ void Init_array_spec(void) {
rb_define_method(cls, "rb_ary_reverse", array_spec_rb_ary_reverse, 1);
rb_define_method(cls, "rb_ary_rotate", array_spec_rb_ary_rotate, 2);
rb_define_method(cls, "rb_ary_shift", array_spec_rb_ary_shift, 1);
+ rb_define_method(cls, "rb_ary_sort", array_spec_rb_ary_sort, 1);
+ rb_define_method(cls, "rb_ary_sort_bang", array_spec_rb_ary_sort_bang, 1);
rb_define_method(cls, "rb_ary_store", array_spec_rb_ary_store, 3);
rb_define_method(cls, "rb_ary_concat", array_spec_rb_ary_concat, 2);
rb_define_method(cls, "rb_ary_plus", array_spec_rb_ary_plus, 2);
diff --git a/spec/ruby/optional/capi/ext/basic_object_spec.c b/spec/ruby/optional/capi/ext/basic_object_spec.c
new file mode 100644
index 0000000000..1618670ceb
--- /dev/null
+++ b/spec/ruby/optional/capi/ext/basic_object_spec.c
@@ -0,0 +1,19 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static VALUE basic_object_spec_RBASIC_CLASS(VALUE self, VALUE obj) {
+ return RBASIC_CLASS(obj);
+}
+
+void Init_basic_object_spec(void) {
+ VALUE cls = rb_define_class("CApiBasicObjectSpecs", rb_cObject);
+ rb_define_method(cls, "RBASIC_CLASS", basic_object_spec_RBASIC_CLASS, 1);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/ruby/optional/capi/ext/bignum_spec.c b/spec/ruby/optional/capi/ext/bignum_spec.c
index 14a51f5099..a950d8b16f 100644
--- a/spec/ruby/optional/capi/ext/bignum_spec.c
+++ b/spec/ruby/optional/capi/ext/bignum_spec.c
@@ -65,7 +65,7 @@ static VALUE bignum_spec_rb_big_pack_array(VALUE self, VALUE val, VALUE len) {
long long_len = NUM2LONG(len);
VALUE ary = rb_ary_new_capa(long_len);
- unsigned long *buf = malloc(long_len * SIZEOF_LONG);
+ unsigned long *buf = (unsigned long*) malloc(long_len * SIZEOF_LONG);
/* The array should be filled with recognisable junk so we can check
it is all cleared properly. */
@@ -102,5 +102,5 @@ void Init_bignum_spec(void) {
}
#ifdef __cplusplus
-extern "C" {
+}
#endif
diff --git a/spec/ruby/optional/capi/ext/boolean_spec.c b/spec/ruby/optional/capi/ext/boolean_spec.c
index 7bb6fe569d..081cffa103 100644
--- a/spec/ruby/optional/capi/ext/boolean_spec.c
+++ b/spec/ruby/optional/capi/ext/boolean_spec.c
@@ -29,5 +29,5 @@ void Init_boolean_spec(void) {
}
#ifdef __cplusplus
-extern "C" {
+}
#endif
diff --git a/spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c b/spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c
index 64393a9397..cc5550f041 100644
--- a/spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c
+++ b/spec/ruby/optional/capi/ext/class_id_under_autoload_spec.c
@@ -1,5 +1,13 @@
#include "ruby.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void Init_class_id_under_autoload_spec(void) {
rb_define_class_id_under(rb_cObject, rb_intern("ClassIdUnderAutoload"), rb_cObject);
}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/ruby/optional/capi/ext/class_spec.c b/spec/ruby/optional/capi/ext/class_spec.c
index 6e5c02e657..36b8c8f2f3 100644
--- a/spec/ruby/optional/capi/ext/class_spec.c
+++ b/spec/ruby/optional/capi/ext/class_spec.c
@@ -37,6 +37,26 @@ static VALUE class_spec_rb_path_to_class(VALUE self, VALUE path) {
return rb_path_to_class(path);
}
+static VALUE class_spec_rb_class_instance_methods(int argc, VALUE* argv, VALUE self) {
+ VALUE mod = argv[0];
+ return rb_class_instance_methods(--argc, ++argv, mod);
+}
+
+static VALUE class_spec_rb_class_public_instance_methods(int argc, VALUE* argv, VALUE self) {
+ VALUE mod = argv[0];
+ return rb_class_public_instance_methods(--argc, ++argv, mod);
+}
+
+static VALUE class_spec_rb_class_protected_instance_methods(int argc, VALUE* argv, VALUE self) {
+ VALUE mod = argv[0];
+ return rb_class_protected_instance_methods(--argc, ++argv, mod);
+}
+
+static VALUE class_spec_rb_class_private_instance_methods(int argc, VALUE* argv, VALUE self) {
+ VALUE mod = argv[0];
+ return rb_class_private_instance_methods(--argc, ++argv, mod);
+}
+
static VALUE class_spec_rb_class_new(VALUE self, VALUE super) {
return rb_class_new(super);
}
@@ -45,7 +65,7 @@ static VALUE class_spec_rb_class_new_instance(VALUE self,
VALUE nargs, VALUE args,
VALUE klass) {
int c_nargs = FIX2INT(nargs);
- VALUE *c_args = alloca(sizeof(VALUE) * c_nargs);
+ VALUE *c_args = (VALUE*)alloca(sizeof(VALUE) * c_nargs);
int i;
for (i = 0; i < c_nargs; i++)
@@ -146,6 +166,10 @@ void Init_class_spec(void) {
rb_define_method(cls, "rb_class2name", class_spec_rb_class2name, 1);
rb_define_method(cls, "rb_path2class", class_spec_rb_path2class, 1);
rb_define_method(cls, "rb_path_to_class", class_spec_rb_path_to_class, 1);
+ rb_define_method(cls, "rb_class_instance_methods", class_spec_rb_class_instance_methods, -1);
+ rb_define_method(cls, "rb_class_public_instance_methods", class_spec_rb_class_public_instance_methods, -1);
+ rb_define_method(cls, "rb_class_protected_instance_methods", class_spec_rb_class_protected_instance_methods, -1);
+ rb_define_method(cls, "rb_class_private_instance_methods", class_spec_rb_class_private_instance_methods, -1);
rb_define_method(cls, "rb_class_new", class_spec_rb_class_new, 1);
rb_define_method(cls, "rb_class_new_instance", class_spec_rb_class_new_instance, 3);
rb_define_method(cls, "rb_class_real", class_spec_rb_class_real, 1);
diff --git a/spec/ruby/optional/capi/ext/class_under_autoload_spec.c b/spec/ruby/optional/capi/ext/class_under_autoload_spec.c
index 120dec7327..e0b1f249c0 100644
--- a/spec/ruby/optional/capi/ext/class_under_autoload_spec.c
+++ b/spec/ruby/optional/capi/ext/class_under_autoload_spec.c
@@ -1,5 +1,13 @@
#include "ruby.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void Init_class_under_autoload_spec(void) {
rb_define_class_under(rb_cObject, "ClassUnderAutoload", rb_cObject);
}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/ruby/optional/capi/ext/constants_spec.c b/spec/ruby/optional/capi/ext/constants_spec.c
index c8ae843016..9aee8db37f 100644
--- a/spec/ruby/optional/capi/ext/constants_spec.c
+++ b/spec/ruby/optional/capi/ext/constants_spec.c
@@ -5,310 +5,151 @@
extern "C" {
#endif
-static VALUE constants_spec_rb_cArray(VALUE self) {
- return rb_cArray;
-}
-
-#ifndef RUBY_INTEGER_UNIFICATION
-static VALUE constants_spec_rb_cBignum(VALUE self) {
- return rb_cBignum;
-}
+#define defconstfunc(name) \
+static VALUE constants_spec_##name(VALUE self) { return name; }
+
+defconstfunc(rb_cArray)
+defconstfunc(rb_cBasicObject)
+defconstfunc(rb_cBinding)
+defconstfunc(rb_cClass)
+defconstfunc(rb_cComplex)
+defconstfunc(rb_mComparable)
+#ifndef RUBY_VERSION_IS_3_0
+defconstfunc(rb_cData)
#endif
-
-static VALUE constants_spec_rb_cClass(VALUE self) {
- return rb_cClass;
-}
-
-static VALUE constants_spec_rb_cData(VALUE self) {
- return rb_cData;
-}
-
-static VALUE constants_spec_rb_cFalseClass(VALUE self) {
- return rb_cFalseClass;
-}
-
-static VALUE constants_spec_rb_cFile(VALUE self) {
- return rb_cFile;
-}
-
-#ifndef RUBY_INTEGER_UNIFICATION
-static VALUE constants_spec_rb_cFixnum(VALUE self) {
- return rb_cFixnum;
-}
-#endif
-
-static VALUE constants_spec_rb_cFloat(VALUE self) {
- return rb_cFloat;
-}
-
-static VALUE constants_spec_rb_cHash(VALUE self) {
- return rb_cHash;
-}
-
-static VALUE constants_spec_rb_cInteger(VALUE self) {
- return rb_cInteger;
-}
-
-static VALUE constants_spec_rb_cIO(VALUE self) {
- return rb_cIO;
-}
-
-static VALUE constants_spec_rb_cModule(VALUE self) {
- return rb_cModule;
-}
-
-static VALUE constants_spec_rb_cMatch(VALUE self) {
- return rb_cMatch;
-}
-
-static VALUE constants_spec_rb_cNilClass(VALUE self) {
- return rb_cNilClass;
-}
-
-static VALUE constants_spec_rb_cNumeric(VALUE self) {
- return rb_cNumeric;
-}
-
-static VALUE constants_spec_rb_cObject(VALUE self) {
- return rb_cObject;
-}
-
-static VALUE constants_spec_rb_cRange(VALUE self) {
- return rb_cRange;
-}
-
-static VALUE constants_spec_rb_cRegexp(VALUE self) {
- return rb_cRegexp;
-}
-
-static VALUE constants_spec_rb_cString(VALUE self) {
- return rb_cString;
-}
-
-static VALUE constants_spec_rb_cStruct(VALUE self) {
- return rb_cStruct;
-}
-
-static VALUE constants_spec_rb_cSymbol(VALUE self) {
- return rb_cSymbol;
-}
-
-static VALUE constants_spec_rb_cTime(VALUE self) {
- return rb_cTime;
-}
-
-static VALUE constants_spec_rb_cThread(VALUE self) {
- return rb_cThread;
-}
-
-static VALUE constants_spec_rb_cTrueClass(VALUE self) {
- return rb_cTrueClass;
-}
-
-static VALUE constants_spec_rb_cProc(VALUE self) {
- return rb_cProc;
-}
-
-static VALUE constants_spec_rb_cMethod(VALUE self) {
- return rb_cMethod;
-}
-
-static VALUE constants_spec_rb_cEnumerator(VALUE self) {
- return rb_cEnumerator;
-}
-
-static VALUE constants_spec_rb_mComparable(VALUE self) {
- return rb_mComparable;
-}
-
-static VALUE constants_spec_rb_mEnumerable(VALUE self) {
- return rb_mEnumerable;
-}
-
-static VALUE constants_spec_rb_mKernel(VALUE self) {
- return rb_mKernel;
-}
-
-static VALUE constants_spec_rb_eArgError(VALUE self) {
- return rb_eArgError;
-}
-
-static VALUE constants_spec_rb_eEOFError(VALUE self) {
- return rb_eEOFError;
-}
-
-static VALUE constants_spec_rb_mErrno(VALUE self) {
- return rb_mErrno;
-}
-
-static VALUE constants_spec_rb_eException(VALUE self) {
- return rb_eException;
-}
-
-static VALUE constants_spec_rb_eFloatDomainError(VALUE self) {
- return rb_eFloatDomainError;
-}
-
-static VALUE constants_spec_rb_eIndexError(VALUE self) {
- return rb_eIndexError;
-}
-
-static VALUE constants_spec_rb_eInterrupt(VALUE self) {
- return rb_eInterrupt;
-}
-
-static VALUE constants_spec_rb_eIOError(VALUE self) {
- return rb_eIOError;
-}
-
-static VALUE constants_spec_rb_eLoadError(VALUE self) {
- return rb_eLoadError;
-}
-
-static VALUE constants_spec_rb_eLocalJumpError(VALUE self) {
- return rb_eLocalJumpError;
-}
-
-static VALUE constants_spec_rb_eNameError(VALUE self) {
- return rb_eNameError;
-}
-
-static VALUE constants_spec_rb_eNoMemError(VALUE self) {
- return rb_eNoMemError;
-}
-
-static VALUE constants_spec_rb_eNoMethodError(VALUE self) {
- return rb_eNoMethodError;
-}
-
-static VALUE constants_spec_rb_eNotImpError(VALUE self) {
- return rb_eNotImpError;
-}
-
-static VALUE constants_spec_rb_eRangeError(VALUE self) {
- return rb_eRangeError;
-}
-
-static VALUE constants_spec_rb_eRegexpError(VALUE self) {
- return rb_eRegexpError;
-}
-
-static VALUE constants_spec_rb_eRuntimeError(VALUE self) {
- return rb_eRuntimeError;
-}
-
-static VALUE constants_spec_rb_eScriptError(VALUE self) {
- return rb_eScriptError;
-}
-
-static VALUE constants_spec_rb_eSecurityError(VALUE self) {
- return rb_eSecurityError;
-}
-
-static VALUE constants_spec_rb_eSignal(VALUE self) {
- return rb_eSignal;
-}
-
-static VALUE constants_spec_rb_eStandardError(VALUE self) {
- return rb_eStandardError;
-}
-
-static VALUE constants_spec_rb_eSyntaxError(VALUE self) {
- return rb_eSyntaxError;
-}
-
-static VALUE constants_spec_rb_eSystemCallError(VALUE self) {
- return rb_eSystemCallError;
-}
-
-static VALUE constants_spec_rb_eSystemExit(VALUE self) {
- return rb_eSystemExit;
-}
-
-static VALUE constants_spec_rb_eSysStackError(VALUE self) {
- return rb_eSysStackError;
-}
-
-static VALUE constants_spec_rb_eTypeError(VALUE self) {
- return rb_eTypeError;
-}
-
-static VALUE constants_spec_rb_eThreadError(VALUE self) {
- return rb_eThreadError;
-}
-
-static VALUE constants_spec_rb_eZeroDivError(VALUE self) {
- return rb_eZeroDivError;
-}
-
-static VALUE constants_spec_rb_eMathDomainError(VALUE self) {
- return rb_eMathDomainError;
-}
-
-static VALUE constants_spec_rb_eEncCompatError(VALUE self) {
- return rb_eEncCompatError;
-}
-
-static VALUE constants_spec_rb_mWaitReadable(VALUE self) {
- return rb_mWaitReadable;
-}
-
-static VALUE constants_spec_rb_mWaitWritable(VALUE self) {
- return rb_mWaitWritable;
-}
-
-static VALUE constants_spec_rb_cDir(VALUE self) {
- return rb_cDir;
-}
+defconstfunc(rb_cDir)
+defconstfunc(rb_cEncoding)
+defconstfunc(rb_mEnumerable)
+defconstfunc(rb_cEnumerator)
+defconstfunc(rb_cFalseClass)
+defconstfunc(rb_cFile)
+defconstfunc(rb_mFileTest)
+defconstfunc(rb_cFloat)
+defconstfunc(rb_mGC)
+defconstfunc(rb_cHash)
+defconstfunc(rb_cInteger)
+defconstfunc(rb_cIO)
+defconstfunc(rb_mKernel)
+defconstfunc(rb_mMath)
+defconstfunc(rb_cMatch)
+defconstfunc(rb_cMethod)
+defconstfunc(rb_cModule)
+defconstfunc(rb_cNilClass)
+defconstfunc(rb_cNumeric)
+defconstfunc(rb_cObject)
+defconstfunc(rb_cProc)
+defconstfunc(rb_mProcess)
+defconstfunc(rb_cRandom)
+defconstfunc(rb_cRange)
+defconstfunc(rb_cRational)
+defconstfunc(rb_cRegexp)
+defconstfunc(rb_cStat)
+defconstfunc(rb_cString)
+defconstfunc(rb_cStruct)
+defconstfunc(rb_cSymbol)
+defconstfunc(rb_cTime)
+defconstfunc(rb_cThread)
+defconstfunc(rb_cTrueClass)
+defconstfunc(rb_cUnboundMethod)
+defconstfunc(rb_eArgError)
+defconstfunc(rb_eEncodingError)
+defconstfunc(rb_eEncCompatError)
+defconstfunc(rb_eEOFError)
+defconstfunc(rb_mErrno)
+defconstfunc(rb_eException)
+defconstfunc(rb_eFatal)
+defconstfunc(rb_eFloatDomainError)
+defconstfunc(rb_eFrozenError)
+defconstfunc(rb_eIndexError)
+defconstfunc(rb_eInterrupt)
+defconstfunc(rb_eIOError)
+defconstfunc(rb_eKeyError)
+defconstfunc(rb_eLoadError)
+defconstfunc(rb_eLocalJumpError)
+defconstfunc(rb_eMathDomainError)
+defconstfunc(rb_eNameError)
+defconstfunc(rb_eNoMemError)
+defconstfunc(rb_eNoMethodError)
+defconstfunc(rb_eNotImpError)
+defconstfunc(rb_eRangeError)
+defconstfunc(rb_eRegexpError)
+defconstfunc(rb_eRuntimeError)
+defconstfunc(rb_eScriptError)
+defconstfunc(rb_eSecurityError)
+defconstfunc(rb_eSignal)
+defconstfunc(rb_eStandardError)
+defconstfunc(rb_eStopIteration)
+defconstfunc(rb_eSyntaxError)
+defconstfunc(rb_eSystemCallError)
+defconstfunc(rb_eSystemExit)
+defconstfunc(rb_eSysStackError)
+defconstfunc(rb_eTypeError)
+defconstfunc(rb_eThreadError)
+defconstfunc(rb_mWaitReadable)
+defconstfunc(rb_mWaitWritable)
+defconstfunc(rb_eZeroDivError)
void Init_constants_spec(void) {
VALUE cls = rb_define_class("CApiConstantsSpecs", rb_cObject);
rb_define_method(cls, "rb_cArray", constants_spec_rb_cArray, 0);
-#ifndef RUBY_INTEGER_UNIFICATION
- rb_define_method(cls, "rb_cBignum", constants_spec_rb_cBignum, 0);
-#endif
-
+ rb_define_method(cls, "rb_cBasicObject", constants_spec_rb_cBasicObject, 0);
+ rb_define_method(cls, "rb_cBinding", constants_spec_rb_cBinding, 0);
rb_define_method(cls, "rb_cClass", constants_spec_rb_cClass, 0);
+ rb_define_method(cls, "rb_cComplex", constants_spec_rb_cComplex, 0);
+ rb_define_method(cls, "rb_mComparable", constants_spec_rb_mComparable, 0);
+ #ifndef RUBY_VERSION_IS_3_0
rb_define_method(cls, "rb_cData", constants_spec_rb_cData, 0);
+ #endif
+ rb_define_method(cls, "rb_cDir", constants_spec_rb_cDir, 0);
+ rb_define_method(cls, "rb_cEncoding", constants_spec_rb_cEncoding, 0);
+ rb_define_method(cls, "rb_mEnumerable", constants_spec_rb_mEnumerable, 0);
+ rb_define_method(cls, "rb_cEnumerator", constants_spec_rb_cEnumerator, 0);
rb_define_method(cls, "rb_cFalseClass", constants_spec_rb_cFalseClass, 0);
rb_define_method(cls, "rb_cFile", constants_spec_rb_cFile, 0);
-#ifndef RUBY_INTEGER_UNIFICATION
- rb_define_method(cls, "rb_cFixnum", constants_spec_rb_cFixnum, 0);
-#endif
-
+ rb_define_method(cls, "rb_mFileTest", constants_spec_rb_mFileTest, 0);
rb_define_method(cls, "rb_cFloat", constants_spec_rb_cFloat, 0);
+ rb_define_method(cls, "rb_mGC", constants_spec_rb_mGC, 0);
rb_define_method(cls, "rb_cHash", constants_spec_rb_cHash, 0);
rb_define_method(cls, "rb_cInteger", constants_spec_rb_cInteger, 0);
rb_define_method(cls, "rb_cIO", constants_spec_rb_cIO, 0);
+ rb_define_method(cls, "rb_mKernel", constants_spec_rb_mKernel, 0);
+ rb_define_method(cls, "rb_mMath", constants_spec_rb_mMath, 0);
rb_define_method(cls, "rb_cMatch", constants_spec_rb_cMatch, 0);
+ rb_define_method(cls, "rb_cMethod", constants_spec_rb_cMethod, 0);
rb_define_method(cls, "rb_cModule", constants_spec_rb_cModule, 0);
rb_define_method(cls, "rb_cNilClass", constants_spec_rb_cNilClass, 0);
rb_define_method(cls, "rb_cNumeric", constants_spec_rb_cNumeric, 0);
rb_define_method(cls, "rb_cObject", constants_spec_rb_cObject, 0);
+ rb_define_method(cls, "rb_cProc", constants_spec_rb_cProc, 0);
+ rb_define_method(cls, "rb_mProcess", constants_spec_rb_mProcess, 0);
+ rb_define_method(cls, "rb_cRandom", constants_spec_rb_cRandom, 0);
rb_define_method(cls, "rb_cRange", constants_spec_rb_cRange, 0);
+ rb_define_method(cls, "rb_cRational", constants_spec_rb_cRational, 0);
rb_define_method(cls, "rb_cRegexp", constants_spec_rb_cRegexp, 0);
+ rb_define_method(cls, "rb_cStat", constants_spec_rb_cStat, 0);
rb_define_method(cls, "rb_cString", constants_spec_rb_cString, 0);
rb_define_method(cls, "rb_cStruct", constants_spec_rb_cStruct, 0);
rb_define_method(cls, "rb_cSymbol", constants_spec_rb_cSymbol, 0);
rb_define_method(cls, "rb_cTime", constants_spec_rb_cTime, 0);
rb_define_method(cls, "rb_cThread", constants_spec_rb_cThread, 0);
rb_define_method(cls, "rb_cTrueClass", constants_spec_rb_cTrueClass, 0);
- rb_define_method(cls, "rb_cProc", constants_spec_rb_cProc, 0);
- rb_define_method(cls, "rb_cMethod", constants_spec_rb_cMethod, 0);
- rb_define_method(cls, "rb_cEnumerator", constants_spec_rb_cEnumerator, 0);
- rb_define_method(cls, "rb_mComparable", constants_spec_rb_mComparable, 0);
- rb_define_method(cls, "rb_mEnumerable", constants_spec_rb_mEnumerable, 0);
- rb_define_method(cls, "rb_mKernel", constants_spec_rb_mKernel, 0);
+ rb_define_method(cls, "rb_cUnboundMethod", constants_spec_rb_cUnboundMethod, 0);
rb_define_method(cls, "rb_eArgError", constants_spec_rb_eArgError, 0);
+ rb_define_method(cls, "rb_eEncodingError", constants_spec_rb_eEncodingError, 0);
+ rb_define_method(cls, "rb_eEncCompatError", constants_spec_rb_eEncCompatError, 0);
rb_define_method(cls, "rb_eEOFError", constants_spec_rb_eEOFError, 0);
rb_define_method(cls, "rb_mErrno", constants_spec_rb_mErrno, 0);
rb_define_method(cls, "rb_eException", constants_spec_rb_eException, 0);
+ rb_define_method(cls, "rb_eFatal", constants_spec_rb_eFatal, 0);
rb_define_method(cls, "rb_eFloatDomainError", constants_spec_rb_eFloatDomainError, 0);
+ rb_define_method(cls, "rb_eFrozenError", constants_spec_rb_eFrozenError, 0);
rb_define_method(cls, "rb_eIndexError", constants_spec_rb_eIndexError, 0);
rb_define_method(cls, "rb_eInterrupt", constants_spec_rb_eInterrupt, 0);
rb_define_method(cls, "rb_eIOError", constants_spec_rb_eIOError, 0);
+ rb_define_method(cls, "rb_eKeyError", constants_spec_rb_eKeyError, 0);
rb_define_method(cls, "rb_eLoadError", constants_spec_rb_eLoadError, 0);
rb_define_method(cls, "rb_eLocalJumpError", constants_spec_rb_eLocalJumpError, 0);
+ rb_define_method(cls, "rb_eMathDomainError", constants_spec_rb_eMathDomainError, 0);
rb_define_method(cls, "rb_eNameError", constants_spec_rb_eNameError, 0);
rb_define_method(cls, "rb_eNoMemError", constants_spec_rb_eNoMemError, 0);
rb_define_method(cls, "rb_eNoMethodError", constants_spec_rb_eNoMethodError, 0);
@@ -320,18 +161,16 @@ void Init_constants_spec(void) {
rb_define_method(cls, "rb_eSecurityError", constants_spec_rb_eSecurityError, 0);
rb_define_method(cls, "rb_eSignal", constants_spec_rb_eSignal, 0);
rb_define_method(cls, "rb_eStandardError", constants_spec_rb_eStandardError, 0);
+ rb_define_method(cls, "rb_eStopIteration", constants_spec_rb_eStopIteration, 0);
rb_define_method(cls, "rb_eSyntaxError", constants_spec_rb_eSyntaxError, 0);
rb_define_method(cls, "rb_eSystemCallError", constants_spec_rb_eSystemCallError, 0);
rb_define_method(cls, "rb_eSystemExit", constants_spec_rb_eSystemExit, 0);
rb_define_method(cls, "rb_eSysStackError", constants_spec_rb_eSysStackError, 0);
rb_define_method(cls, "rb_eTypeError", constants_spec_rb_eTypeError, 0);
rb_define_method(cls, "rb_eThreadError", constants_spec_rb_eThreadError, 0);
- rb_define_method(cls, "rb_eZeroDivError", constants_spec_rb_eZeroDivError, 0);
- rb_define_method(cls, "rb_eMathDomainError", constants_spec_rb_eMathDomainError, 0);
- rb_define_method(cls, "rb_eEncCompatError", constants_spec_rb_eEncCompatError, 0);
rb_define_method(cls, "rb_mWaitReadable", constants_spec_rb_mWaitReadable, 0);
rb_define_method(cls, "rb_mWaitWritable", constants_spec_rb_mWaitWritable, 0);
- rb_define_method(cls, "rb_cDir", constants_spec_rb_cDir, 0);
+ rb_define_method(cls, "rb_eZeroDivError", constants_spec_rb_eZeroDivError, 0);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/data_spec.c b/spec/ruby/optional/capi/ext/data_spec.c
index a41666f655..109bded1d1 100644
--- a/spec/ruby/optional/capi/ext/data_spec.c
+++ b/spec/ruby/optional/capi/ext/data_spec.c
@@ -19,7 +19,7 @@ void sample_wrapped_struct_mark(void* st) {
}
VALUE sdaf_alloc_func(VALUE klass) {
- struct sample_wrapped_struct* bar = malloc(sizeof(struct sample_wrapped_struct));
+ struct sample_wrapped_struct* bar = (struct sample_wrapped_struct*) malloc(sizeof(struct sample_wrapped_struct));
bar->foo = 42;
return Data_Wrap_Struct(klass, &sample_wrapped_struct_mark, &sample_wrapped_struct_free, bar);
}
@@ -32,7 +32,7 @@ VALUE sdaf_get_struct(VALUE self) {
}
VALUE sws_wrap_struct(VALUE self, VALUE val) {
- struct sample_wrapped_struct* bar = malloc(sizeof(struct sample_wrapped_struct));
+ struct sample_wrapped_struct* bar = (struct sample_wrapped_struct*) malloc(sizeof(struct sample_wrapped_struct));
bar->foo = FIX2INT(val);
return Data_Wrap_Struct(rb_cObject, &sample_wrapped_struct_mark, &sample_wrapped_struct_free, bar);
}
@@ -58,9 +58,9 @@ VALUE sws_get_struct_data_ptr(VALUE self, VALUE obj) {
VALUE sws_change_struct(VALUE self, VALUE obj, VALUE new_val) {
struct sample_wrapped_struct *old_struct, *new_struct;
- new_struct = malloc(sizeof(struct sample_wrapped_struct));
+ new_struct = (struct sample_wrapped_struct*) malloc(sizeof(struct sample_wrapped_struct));
new_struct->foo = FIX2INT(new_val);
- old_struct = RDATA(obj)->data;
+ old_struct = (struct sample_wrapped_struct*) RDATA(obj)->data;
free(old_struct);
RDATA(obj)->data = new_struct;
return Qnil;
diff --git a/spec/ruby/optional/capi/ext/encoding_spec.c b/spec/ruby/optional/capi/ext/encoding_spec.c
index 3cde884225..cde4d0c351 100644
--- a/spec/ruby/optional/capi/ext/encoding_spec.c
+++ b/spec/ruby/optional/capi/ext/encoding_spec.c
@@ -7,6 +7,10 @@
extern "C" {
#endif
+static VALUE encoding_spec_MBCLEN_CHARFOUND_P(VALUE self, VALUE obj) {
+ return INT2FIX(MBCLEN_CHARFOUND_P(FIX2INT(obj)));
+}
+
static VALUE encoding_spec_ENC_CODERANGE_ASCIIONLY(VALUE self, VALUE obj) {
if(ENC_CODERANGE_ASCIIONLY(obj)) {
return Qtrue;
@@ -102,10 +106,39 @@ static VALUE encoding_spec_rb_enc_find_index(VALUE self, VALUE name) {
return INT2NUM(rb_enc_find_index(RSTRING_PTR(name)));
}
+static VALUE encoding_spec_rb_enc_isalnum(VALUE self, VALUE chr, VALUE encoding) {
+ rb_encoding *e = rb_to_encoding(encoding);
+ return rb_enc_isalnum(FIX2INT(chr), e) ? Qtrue : Qfalse;
+}
+
+static VALUE encoding_spec_rb_enc_isspace(VALUE self, VALUE chr, VALUE encoding) {
+ rb_encoding *e = rb_to_encoding(encoding);
+ return rb_enc_isspace(FIX2INT(chr), e) ? Qtrue : Qfalse;
+}
+
static VALUE encoding_spec_rb_enc_from_index(VALUE self, VALUE index) {
return rb_str_new2(rb_enc_from_index(NUM2INT(index))->name);
}
+static VALUE encoding_spec_rb_enc_mbc_to_codepoint(VALUE self, VALUE str, VALUE offset) {
+ int o = FIX2INT(offset);
+ char *p = RSTRING_PTR(str);
+ char *e = p + o;
+ return INT2FIX(rb_enc_mbc_to_codepoint(p, e, rb_enc_get(str)));
+}
+
+static VALUE encoding_spec_rb_enc_mbcput(VALUE self, VALUE code, VALUE encoding) {
+ unsigned int c = FIX2UINT(code);
+ rb_encoding *enc = rb_to_encoding(encoding);
+ char buf[ONIGENC_CODE_TO_MBC_MAXLEN];
+ memset(buf, '\1', sizeof(buf));
+ int len = rb_enc_mbcput(c, buf, enc);
+ if (buf[len] != '\1') {
+ rb_raise(rb_eRuntimeError, "should not change bytes after len");
+ }
+ return rb_enc_str_new(buf, len, enc);
+}
+
static VALUE encoding_spec_rb_enc_from_encoding(VALUE self, VALUE name) {
return rb_enc_from_encoding(rb_enc_find(RSTRING_PTR(name)));
}
@@ -114,6 +147,13 @@ static VALUE encoding_spec_rb_enc_get(VALUE self, VALUE obj) {
return rb_str_new2(rb_enc_get(obj)->name);
}
+static VALUE encoding_spec_rb_enc_precise_mbclen(VALUE self, VALUE str, VALUE offset) {
+ int o = FIX2INT(offset);
+ char *p = RSTRING_PTR(str);
+ char *e = p + o;
+ return INT2FIX(rb_enc_precise_mbclen(p, e, rb_enc_get(str)));
+}
+
static VALUE encoding_spec_rb_obj_encoding(VALUE self, VALUE obj) {
return rb_obj_encoding(obj);
}
@@ -149,6 +189,21 @@ static VALUE encoding_spec_rb_enc_str_coderange(VALUE self, VALUE str) {
}
}
+static VALUE encoding_spec_rb_enc_str_new_cstr(VALUE self, VALUE str, VALUE enc) {
+ rb_encoding *e = rb_to_encoding(enc);
+ return rb_enc_str_new_cstr(StringValueCStr(str), e);
+}
+
+static VALUE encoding_spec_rb_enc_str_new_cstr_constant(VALUE self, VALUE enc) {
+ if (NIL_P(enc)) {
+ rb_encoding *e = NULL;
+ return rb_enc_str_new_static("test string literal", strlen("test string literal"), e);
+ } else {
+ rb_encoding *e = rb_to_encoding(enc);
+ return rb_enc_str_new_cstr("test string literal", e);
+ }
+}
+
static VALUE encoding_spec_rb_enc_str_new(VALUE self, VALUE str, VALUE len, VALUE enc) {
return rb_enc_str_new(RSTRING_PTR(str), FIX2INT(len), rb_to_encoding(enc));
}
@@ -175,6 +230,21 @@ static VALUE encoding_spec_rb_to_encoding(VALUE self, VALUE obj) {
return rb_str_new2(rb_to_encoding(obj)->name);
}
+static rb_encoding** native_rb_encoding_pointer;
+
+static VALUE encoding_spec_rb_to_encoding_native_store(VALUE self, VALUE obj) {
+ rb_encoding* enc = rb_to_encoding(obj);
+ VALUE address = SIZET2NUM((size_t) native_rb_encoding_pointer);
+ *native_rb_encoding_pointer = enc;
+ return address;
+}
+
+static VALUE encoding_spec_rb_to_encoding_native_name(VALUE self, VALUE address) {
+ rb_encoding** ptr = (rb_encoding**) NUM2SIZET(address);
+ rb_encoding* enc = *ptr;
+ return rb_str_new2(enc->name);
+}
+
static VALUE encoding_spec_rb_to_encoding_index(VALUE self, VALUE obj) {
return INT2NUM(rb_to_encoding_index(obj));
}
@@ -196,8 +266,45 @@ static VALUE encoding_spec_rb_enc_codepoint_len(VALUE self, VALUE str) {
return rb_ary_new3(2, LONG2NUM(codepoint), LONG2NUM(len));
}
+static VALUE encoding_spec_rb_enc_str_asciionly_p(VALUE self, VALUE str) {
+ if (rb_enc_str_asciionly_p(str)) {
+ return Qtrue;
+ } else {
+ return Qfalse;
+ }
+}
+
+static VALUE encoding_spec_rb_uv_to_utf8(VALUE self, VALUE buf, VALUE num) {
+ return INT2NUM(rb_uv_to_utf8(RSTRING_PTR(buf), NUM2INT(num)));
+}
+
+static VALUE encoding_spec_ONIGENC_MBC_CASE_FOLD(VALUE self, VALUE str) {
+ char *beg = RSTRING_PTR(str);
+ char *beg_initial = beg;
+ char *end = beg + 2;
+ OnigUChar fold[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
+ memset(fold, '\1', sizeof(fold));
+ rb_encoding *enc = rb_enc_get(str);
+ int r = ONIGENC_MBC_CASE_FOLD(enc, ONIGENC_CASE_FOLD, &beg, (const OnigUChar *)end, fold);
+ if (r > 0 && fold[r] != '\1') {
+ rb_raise(rb_eRuntimeError, "should not change bytes after len");
+ }
+ VALUE str_result = r <= 0 ? Qnil : rb_enc_str_new((char *)fold, r, enc);
+ long bytes_used = beg - beg_initial;
+ return rb_ary_new3(2, str_result, INT2FIX(bytes_used));
+}
+
+static VALUE encoding_spec_rb_enc_codelen(VALUE self, VALUE code, VALUE encoding) {
+ unsigned int c = FIX2UINT(code);
+ rb_encoding *enc = rb_to_encoding(encoding);
+ return INT2FIX(rb_enc_codelen(c, enc));
+}
+
void Init_encoding_spec(void) {
- VALUE cls = rb_define_class("CApiEncodingSpecs", rb_cObject);
+ VALUE cls;
+ native_rb_encoding_pointer = (rb_encoding**) malloc(sizeof(rb_encoding*));
+
+ cls = rb_define_class("CApiEncodingSpecs", rb_cObject);
rb_define_method(cls, "ENC_CODERANGE_ASCIIONLY",
encoding_spec_ENC_CODERANGE_ASCIIONLY, 1);
@@ -221,27 +328,41 @@ void Init_encoding_spec(void) {
rb_define_method(cls, "rb_enc_alias", encoding_spec_rb_enc_alias, 2);
#endif
+ rb_define_method(cls, "MBCLEN_CHARFOUND_P", encoding_spec_MBCLEN_CHARFOUND_P, 1);
rb_define_method(cls, "rb_enc_associate", encoding_spec_rb_enc_associate, 2);
rb_define_method(cls, "rb_enc_associate_index", encoding_spec_rb_enc_associate_index, 2);
rb_define_method(cls, "rb_enc_compatible", encoding_spec_rb_enc_compatible, 2);
rb_define_method(cls, "rb_enc_copy", encoding_spec_rb_enc_copy, 2);
+ rb_define_method(cls, "rb_enc_codelen", encoding_spec_rb_enc_codelen, 2);
rb_define_method(cls, "rb_enc_find", encoding_spec_rb_enc_find, 1);
rb_define_method(cls, "rb_enc_find_index", encoding_spec_rb_enc_find_index, 1);
+ rb_define_method(cls, "rb_enc_isalnum", encoding_spec_rb_enc_isalnum, 2);
+ rb_define_method(cls, "rb_enc_isspace", encoding_spec_rb_enc_isspace, 2);
rb_define_method(cls, "rb_enc_from_index", encoding_spec_rb_enc_from_index, 1);
+ rb_define_method(cls, "rb_enc_mbc_to_codepoint", encoding_spec_rb_enc_mbc_to_codepoint, 2);
+ rb_define_method(cls, "rb_enc_mbcput", encoding_spec_rb_enc_mbcput, 2);
rb_define_method(cls, "rb_enc_from_encoding", encoding_spec_rb_enc_from_encoding, 1);
rb_define_method(cls, "rb_enc_get", encoding_spec_rb_enc_get, 1);
+ rb_define_method(cls, "rb_enc_precise_mbclen", encoding_spec_rb_enc_precise_mbclen, 2);
rb_define_method(cls, "rb_obj_encoding", encoding_spec_rb_obj_encoding, 1);
rb_define_method(cls, "rb_enc_get_index", encoding_spec_rb_enc_get_index, 1);
rb_define_method(cls, "rb_enc_set_index", encoding_spec_rb_enc_set_index, 2);
rb_define_method(cls, "rb_enc_str_coderange", encoding_spec_rb_enc_str_coderange, 1);
+ rb_define_method(cls, "rb_enc_str_new_cstr", encoding_spec_rb_enc_str_new_cstr, 2);
+ rb_define_method(cls, "rb_enc_str_new_cstr_constant", encoding_spec_rb_enc_str_new_cstr_constant, 1);
rb_define_method(cls, "rb_enc_str_new", encoding_spec_rb_enc_str_new, 3);
rb_define_method(cls, "ENCODING_GET", encoding_spec_ENCODING_GET, 1);
rb_define_method(cls, "ENCODING_SET", encoding_spec_ENCODING_SET, 2);
rb_define_method(cls, "rb_enc_to_index", encoding_spec_rb_enc_to_index, 1);
rb_define_method(cls, "rb_to_encoding", encoding_spec_rb_to_encoding, 1);
+ rb_define_method(cls, "rb_to_encoding_native_store", encoding_spec_rb_to_encoding_native_store, 1);
+ rb_define_method(cls, "rb_to_encoding_native_name", encoding_spec_rb_to_encoding_native_name, 1);
rb_define_method(cls, "rb_to_encoding_index", encoding_spec_rb_to_encoding_index, 1);
rb_define_method(cls, "rb_enc_nth", encoding_spec_rb_enc_nth, 2);
rb_define_method(cls, "rb_enc_codepoint_len", encoding_spec_rb_enc_codepoint_len, 1);
+ rb_define_method(cls, "rb_enc_str_asciionly_p", encoding_spec_rb_enc_str_asciionly_p, 1);
+ rb_define_method(cls, "rb_uv_to_utf8", encoding_spec_rb_uv_to_utf8, 2);
+ rb_define_method(cls, "ONIGENC_MBC_CASE_FOLD", encoding_spec_ONIGENC_MBC_CASE_FOLD, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/exception_spec.c b/spec/ruby/optional/capi/ext/exception_spec.c
index cdd86b183e..7250792b70 100644
--- a/spec/ruby/optional/capi/ext/exception_spec.c
+++ b/spec/ruby/optional/capi/ext/exception_spec.c
@@ -32,6 +32,13 @@ VALUE exception_spec_rb_set_errinfo(VALUE self, VALUE exc) {
return Qnil;
}
+
+VALUE exception_spec_rb_make_exception(VALUE self, VALUE ary) {
+ int argc = RARRAY_LENINT(ary);
+ VALUE *argv = RARRAY_PTR(ary);
+ return rb_make_exception(argc, argv);
+}
+
void Init_exception_spec(void) {
VALUE cls = rb_define_class("CApiExceptionSpecs", rb_cObject);
rb_define_method(cls, "rb_exc_new", exception_spec_rb_exc_new, 1);
@@ -39,6 +46,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_make_exception", exception_spec_rb_make_exception, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/float_spec.c b/spec/ruby/optional/capi/ext/float_spec.c
index 34be917965..3db05cef8c 100644
--- a/spec/ruby/optional/capi/ext/float_spec.c
+++ b/spec/ruby/optional/capi/ext/float_spec.c
@@ -25,12 +25,21 @@ static VALUE float_spec_RFLOAT_VALUE(VALUE self, VALUE float_h) {
return rb_float_new(RFLOAT_VALUE(float_h));
}
+static VALUE float_spec_RB_FLOAT_TYPE_P(VALUE self, VALUE val) {
+ if (RB_FLOAT_TYPE_P(val)) {
+ return Qtrue;
+ } else {
+ return Qfalse;
+ }
+}
+
void Init_float_spec(void) {
VALUE cls = rb_define_class("CApiFloatSpecs", rb_cObject);
rb_define_method(cls, "new_zero", float_spec_new_zero, 0);
rb_define_method(cls, "new_point_five", float_spec_new_point_five, 0);
rb_define_method(cls, "rb_Float", float_spec_rb_Float, 1);
rb_define_method(cls, "RFLOAT_VALUE", float_spec_RFLOAT_VALUE, 1);
+ rb_define_method(cls, "RB_FLOAT_TYPE_P", float_spec_RB_FLOAT_TYPE_P, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/gc_spec.c b/spec/ruby/optional/capi/ext/gc_spec.c
index 57b1f11faa..7dc9c347c7 100644
--- a/spec/ruby/optional/capi/ext/gc_spec.c
+++ b/spec/ruby/optional/capi/ext/gc_spec.c
@@ -16,24 +16,33 @@ static VALUE registered_reference_address(VALUE self) {
return registered_reference_value;
}
-static VALUE gc_spec_rb_gc_enable() {
+static VALUE gc_spec_rb_gc_enable(VALUE self) {
return rb_gc_enable();
}
-static VALUE gc_spec_rb_gc_disable() {
+static VALUE gc_spec_rb_gc_disable(VALUE self) {
return rb_gc_disable();
}
-static VALUE gc_spec_rb_gc() {
+static VALUE gc_spec_rb_gc(VALUE self) {
rb_gc();
return Qnil;
}
+static VALUE gc_spec_rb_gc_latest_gc_info(VALUE self, VALUE hash_or_key){
+ return rb_gc_latest_gc_info(hash_or_key);
+}
+
static VALUE gc_spec_rb_gc_adjust_memory_usage(VALUE self, VALUE diff) {
rb_gc_adjust_memory_usage(NUM2SSIZET(diff));
return Qnil;
}
+static VALUE gc_spec_rb_gc_register_mark_object(VALUE self, VALUE obj) {
+ rb_gc_register_mark_object(obj);
+ return Qnil;
+}
+
void Init_gc_spec(void) {
VALUE cls = rb_define_class("CApiGCSpecs", rb_cObject);
registered_tagged_value = INT2NUM(10);
@@ -48,6 +57,8 @@ void Init_gc_spec(void) {
rb_define_method(cls, "rb_gc_disable", gc_spec_rb_gc_disable, 0);
rb_define_method(cls, "rb_gc", gc_spec_rb_gc, 0);
rb_define_method(cls, "rb_gc_adjust_memory_usage", gc_spec_rb_gc_adjust_memory_usage, 1);
+ rb_define_method(cls, "rb_gc_register_mark_object", gc_spec_rb_gc_register_mark_object, 1);
+ rb_define_method(cls, "rb_gc_latest_gc_info", gc_spec_rb_gc_latest_gc_info, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/globals_spec.c b/spec/ruby/optional/capi/ext/globals_spec.c
index f70622f66c..28a9633f98 100644
--- a/spec/ruby/optional/capi/ext/globals_spec.c
+++ b/spec/ruby/optional/capi/ext/globals_spec.c
@@ -7,12 +7,16 @@ extern "C" {
VALUE g_hooked_var;
+VALUE var_2x_getter(ID id, VALUE *data) {
+ return *data;
+}
+
void var_2x_setter(VALUE val, ID id, VALUE *var) {
- *var = INT2NUM(NUM2INT(val) * 2);
+ *var = INT2NUM(NUM2INT(val) * 2);
}
static VALUE sb_define_hooked_variable(VALUE self, VALUE var_name) {
- rb_define_hooked_variable(StringValuePtr(var_name), &g_hooked_var, 0, var_2x_setter);
+ rb_define_hooked_variable(StringValuePtr(var_name), &g_hooked_var, var_2x_getter, var_2x_setter);
return Qnil;
}
@@ -64,6 +68,10 @@ static VALUE global_spec_rb_defout(VALUE self) {
return rb_defout;
}
+static VALUE global_spec_rb_fs(VALUE self) {
+ return rb_fs;
+}
+
static VALUE global_spec_rb_rs(VALUE self) {
return rb_rs;
}
@@ -105,6 +113,7 @@ void Init_globals_spec(void) {
rb_define_method(cls, "rb_stdout", global_spec_rb_stdout, 0);
rb_define_method(cls, "rb_stderr", global_spec_rb_stderr, 0);
rb_define_method(cls, "rb_defout", global_spec_rb_defout, 0);
+ rb_define_method(cls, "rb_fs", global_spec_rb_fs, 0);
rb_define_method(cls, "rb_rs", global_spec_rb_rs, 0);
rb_define_method(cls, "rb_default_rs", global_spec_rb_default_rs, 0);
rb_define_method(cls, "rb_output_rs", global_spec_rb_output_rs, 0);
diff --git a/spec/ruby/optional/capi/ext/hash_spec.c b/spec/ruby/optional/capi/ext/hash_spec.c
index c8735cec2c..7f38708915 100644
--- a/spec/ruby/optional/capi/ext/hash_spec.c
+++ b/spec/ruby/optional/capi/ext/hash_spec.c
@@ -105,6 +105,12 @@ VALUE hash_spec_rb_hash_new(VALUE self) {
return rb_hash_new();
}
+VALUE rb_ident_hash_new(void); /* internal.h, used in ripper */
+
+VALUE hash_spec_rb_ident_hash_new(VALUE self) {
+ return rb_ident_hash_new();
+}
+
VALUE hash_spec_rb_hash_size(VALUE self, VALUE hash) {
return rb_hash_size(hash);
}
@@ -113,6 +119,15 @@ VALUE hash_spec_rb_hash_set_ifnone(VALUE self, VALUE hash, VALUE def) {
return rb_hash_set_ifnone(hash, def);
}
+VALUE hash_spec_compute_a_hash_code(VALUE self, VALUE seed) {
+ int int_seed = FIX2INT(seed);
+ st_index_t h = rb_hash_start(int_seed);
+ h = rb_hash_uint32(h, 540u);
+ h = rb_hash_uint32(h, 340u);
+ h = rb_hash_end(h);
+ return ULONG2NUM(h);
+}
+
void Init_hash_spec(void) {
VALUE cls = rb_define_class("CApiHashSpecs", rb_cObject);
rb_define_method(cls, "rb_hash", hash_spec_rb_hash, 1);
@@ -134,8 +149,10 @@ void Init_hash_spec(void) {
rb_define_method(cls, "rb_hash_lookup2", hash_spec_rb_hash_lookup2, 3);
rb_define_method(cls, "rb_hash_lookup2_default_undef", hash_spec_rb_hash_lookup2_default_undef, 2);
rb_define_method(cls, "rb_hash_new", hash_spec_rb_hash_new, 0);
+ rb_define_method(cls, "rb_ident_hash_new", hash_spec_rb_ident_hash_new, 0);
rb_define_method(cls, "rb_hash_size", hash_spec_rb_hash_size, 1);
rb_define_method(cls, "rb_hash_set_ifnone", hash_spec_rb_hash_set_ifnone, 2);
+ rb_define_method(cls, "compute_a_hash_code", hash_spec_compute_a_hash_code, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/integer_spec.c b/spec/ruby/optional/capi/ext/integer_spec.c
index 7e9e8b26bd..5ed1d3fd73 100644
--- a/spec/ruby/optional/capi/ext/integer_spec.c
+++ b/spec/ruby/optional/capi/ext/integer_spec.c
@@ -13,6 +13,12 @@ static VALUE integer_spec_rb_integer_pack(VALUE self, VALUE value,
return INT2FIX(result);
}
+VALUE rb_int_positive_pow(long x, unsigned long y); /* internal.h, used in ripper */
+
+static VALUE integer_spec_rb_int_positive_pow(VALUE self, VALUE a, VALUE b){
+ return rb_int_positive_pow(FIX2INT(a), FIX2INT(b));
+}
+
void Init_integer_spec(void) {
VALUE cls = rb_define_class("CApiIntegerSpecs", rb_cObject);
rb_define_const(cls, "MSWORD", INT2NUM(INTEGER_PACK_MSWORD_FIRST));
@@ -27,8 +33,9 @@ void Init_integer_spec(void) {
rb_define_const(cls, "NEGATIVE", INT2NUM(INTEGER_PACK_NEGATIVE));
rb_define_method(cls, "rb_integer_pack", integer_spec_rb_integer_pack, 6);
+ rb_define_method(cls, "rb_int_positive_pow", integer_spec_rb_int_positive_pow, 2);
}
#ifdef __cplusplus
-extern "C" {
+}
#endif
diff --git a/spec/ruby/optional/capi/ext/io_spec.c b/spec/ruby/optional/capi/ext/io_spec.c
index b656de081a..73e6804013 100644
--- a/spec/ruby/optional/capi/ext/io_spec.c
+++ b/spec/ruby/optional/capi/ext/io_spec.c
@@ -43,7 +43,7 @@ VALUE io_spec_rb_io_addstr(VALUE self, VALUE io, VALUE str) {
VALUE io_spec_rb_io_printf(VALUE self, VALUE io, VALUE ary) {
long argc = RARRAY_LEN(ary);
- VALUE *argv = alloca(sizeof(VALUE) * argc);
+ VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc);
int i;
for (i = 0; i < argc; i++) {
@@ -55,7 +55,7 @@ VALUE io_spec_rb_io_printf(VALUE self, VALUE io, VALUE ary) {
VALUE io_spec_rb_io_print(VALUE self, VALUE io, VALUE ary) {
long argc = RARRAY_LEN(ary);
- VALUE *argv = alloca(sizeof(VALUE) * argc);
+ VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc);
int i;
for (i = 0; i < argc; i++) {
@@ -67,7 +67,7 @@ VALUE io_spec_rb_io_print(VALUE self, VALUE io, VALUE ary) {
VALUE io_spec_rb_io_puts(VALUE self, VALUE io, VALUE ary) {
long argc = RARRAY_LEN(ary);
- VALUE *argv = alloca(sizeof(VALUE) * argc);
+ VALUE *argv = (VALUE*) alloca(sizeof(VALUE) * argc);
int i;
for (i = 0; i < argc; i++) {
@@ -201,6 +201,21 @@ VALUE io_spec_rb_io_close(VALUE self, VALUE io) {
return rb_io_close(io);
}
+VALUE io_spec_rb_io_set_nonblock(VALUE self, VALUE io) {
+ rb_io_t* fp;
+#ifdef F_GETFL
+ int flags;
+#endif
+ GetOpenFile(io, fp);
+ rb_io_set_nonblock(fp);
+#ifdef F_GETFL
+ flags = fcntl(fp->fd, F_GETFL, 0);
+ return flags & O_NONBLOCK ? Qtrue : Qfalse;
+#else
+ return Qfalse;
+#endif
+}
+
/*
* this is needed to ensure rb_io_wait_*able functions behave
* predictably because errno may be set to unexpected values
@@ -225,6 +240,7 @@ void Init_io_spec(void) {
rb_define_method(cls, "rb_io_check_readable", io_spec_rb_io_check_readable, 1);
rb_define_method(cls, "rb_io_check_writable", io_spec_rb_io_check_writable, 1);
rb_define_method(cls, "rb_io_check_closed", io_spec_rb_io_check_closed, 1);
+ rb_define_method(cls, "rb_io_set_nonblock", io_spec_rb_io_set_nonblock, 1);
rb_define_method(cls, "rb_io_taint_check", io_spec_rb_io_taint_check, 1);
rb_define_method(cls, "rb_io_wait_readable", io_spec_rb_io_wait_readable, 2);
rb_define_method(cls, "rb_io_wait_writable", io_spec_rb_io_wait_writable, 1);
diff --git a/spec/ruby/optional/capi/ext/kernel_spec.c b/spec/ruby/optional/capi/ext/kernel_spec.c
index e98ae35067..4048684b2c 100644
--- a/spec/ruby/optional/capi/ext/kernel_spec.c
+++ b/spec/ruby/optional/capi/ext/kernel_spec.c
@@ -68,7 +68,7 @@ VALUE rb_block_call_extra_data(VALUE self, VALUE object) {
}
VALUE kernel_spec_rb_block_call_no_func(VALUE self, VALUE ary) {
- return rb_block_call(ary, rb_intern("map"), 0, NULL, NULL, Qnil);
+ return rb_block_call(ary, rb_intern("map"), 0, NULL, (rb_block_call_func_t)NULL, Qnil);
}
@@ -153,6 +153,10 @@ VALUE kernel_spec_rb_rescue(VALUE self, VALUE main_proc, VALUE arg,
rb_ary_push(main_array, main_proc);
rb_ary_push(main_array, arg);
+ if (raise_proc == Qnil) {
+ return rb_rescue(kernel_spec_call_proc, main_array, NULL, arg2);
+ }
+
raise_array = rb_ary_new();
rb_ary_push(raise_array, raise_proc);
rb_ary_push(raise_array, arg2);
@@ -187,6 +191,10 @@ static VALUE kernel_spec_rb_protect_yield(VALUE self, VALUE obj, VALUE ary) {
return res;
}
+static VALUE kernel_spec_rb_protect_null_status(VALUE self, VALUE obj) {
+ return rb_protect(rb_yield, obj, NULL);
+}
+
static VALUE kernel_spec_rb_eval_string_protect(VALUE self, VALUE str, VALUE ary) {
int status = 0;
VALUE res = rb_eval_string_protect(RSTRING_PTR(str), &status);
@@ -262,6 +270,15 @@ static VALUE kernel_spec_rb_yield_values(VALUE self, VALUE obj1, VALUE obj2) {
return rb_yield_values(2, obj1, obj2);
}
+static VALUE kernel_spec_rb_yield_values2(VALUE self, VALUE ary) {
+ long len = RARRAY_LEN(ary);
+ VALUE *args = (VALUE*)alloca(sizeof(VALUE) * len);
+ for (int i = 0; i < len; i++) {
+ args[i] = rb_ary_entry(ary, i);
+ }
+ return rb_yield_values2((int)len, args);
+}
+
static VALUE do_rec(VALUE obj, VALUE arg, int is_rec) {
if(is_rec) {
return obj;
@@ -277,7 +294,7 @@ static VALUE kernel_spec_rb_exec_recursive(VALUE self, VALUE obj) {
}
static void write_io(VALUE io) {
- rb_funcall(io, rb_intern("write"), 1, rb_str_new2("e"));
+ rb_funcall(io, rb_intern("write"), 1, rb_str_new2("in write_io"));
}
static VALUE kernel_spec_rb_set_end_proc(VALUE self, VALUE io) {
@@ -305,6 +322,13 @@ static VALUE kernel_spec_rb_funcall_with_block(VALUE self, VALUE obj, VALUE meth
return rb_funcall_with_block(obj, SYM2ID(method), 0, NULL, block);
}
+static VALUE kernel_spec_rb_funcall_many_args(VALUE self, VALUE obj, VALUE method) {
+ return rb_funcall(obj, SYM2ID(method), 15,
+ INT2FIX(15), INT2FIX(14), INT2FIX(13), INT2FIX(12), INT2FIX(11),
+ INT2FIX(10), INT2FIX(9), INT2FIX(8), INT2FIX(7), INT2FIX(6),
+ INT2FIX(5), INT2FIX(4), INT2FIX(3), INT2FIX(2), INT2FIX(1));
+}
+
void Init_kernel_spec(void) {
VALUE cls = rb_define_class("CApiKernelSpecs", rb_cObject);
rb_define_method(cls, "rb_block_given_p", kernel_spec_rb_block_given_p, 0);
@@ -325,6 +349,7 @@ void Init_kernel_spec(void) {
rb_define_method(cls, "rb_rescue", kernel_spec_rb_rescue, 4);
rb_define_method(cls, "rb_rescue2", kernel_spec_rb_rescue2, -1);
rb_define_method(cls, "rb_protect_yield", kernel_spec_rb_protect_yield, 2);
+ rb_define_method(cls, "rb_protect_null_status", kernel_spec_rb_protect_null_status, 1);
rb_define_method(cls, "rb_eval_string_protect", kernel_spec_rb_eval_string_protect, 2);
rb_define_method(cls, "rb_catch", kernel_spec_rb_catch, 2);
rb_define_method(cls, "rb_catch_obj", kernel_spec_rb_catch_obj, 2);
@@ -335,6 +360,7 @@ void Init_kernel_spec(void) {
rb_define_method(cls, "rb_yield_indirected", kernel_spec_rb_yield_indirected, 1);
rb_define_method(cls, "rb_yield_define_each", kernel_spec_rb_yield_define_each, 1);
rb_define_method(cls, "rb_yield_values", kernel_spec_rb_yield_values, 2);
+ rb_define_method(cls, "rb_yield_values2", kernel_spec_rb_yield_values2, 1);
rb_define_method(cls, "rb_yield_splat", kernel_spec_rb_yield_splat, 1);
rb_define_method(cls, "rb_exec_recursive", kernel_spec_rb_exec_recursive, 1);
rb_define_method(cls, "rb_set_end_proc", kernel_spec_rb_set_end_proc, 1);
@@ -342,6 +368,7 @@ void Init_kernel_spec(void) {
rb_define_method(cls, "rb_make_backtrace", kernel_spec_rb_make_backtrace, 0);
rb_define_method(cls, "rb_obj_method", kernel_spec_rb_obj_method, 2);
rb_define_method(cls, "rb_funcall3", kernel_spec_rb_funcall3, 2);
+ rb_define_method(cls, "rb_funcall_many_args", kernel_spec_rb_funcall_many_args, 2);
rb_define_method(cls, "rb_funcall_with_block", kernel_spec_rb_funcall_with_block, 3);
}
diff --git a/spec/ruby/optional/capi/ext/language_spec.c b/spec/ruby/optional/capi/ext/language_spec.c
new file mode 100644
index 0000000000..749c188956
--- /dev/null
+++ b/spec/ruby/optional/capi/ext/language_spec.c
@@ -0,0 +1,42 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static VALUE language_spec_switch(VALUE self, VALUE value) {
+ if (value == ID2SYM(rb_intern("undef"))) {
+ value = Qundef;
+ }
+
+ switch (value) {
+ case Qtrue:
+ return ID2SYM(rb_intern("true"));
+ case Qfalse:
+ return ID2SYM(rb_intern("false"));
+ case Qnil:
+ return ID2SYM(rb_intern("nil"));
+ case Qundef:
+ return ID2SYM(rb_intern("undef"));
+ default:
+ return ID2SYM(rb_intern("default"));
+ }
+}
+
+/* Defining a local variable rb_mProcess which already exists as a global variable
+ * For instance eventmachine does this in Init_rubyeventmachine() */
+static VALUE language_spec_global_local_var(VALUE self) {
+ VALUE rb_mProcess = rb_const_get(rb_cObject, rb_intern("Process"));
+ return rb_mProcess;
+}
+
+void Init_language_spec(void) {
+ VALUE cls = rb_define_class("CApiLanguageSpecs", rb_cObject);
+ rb_define_method(cls, "switch", language_spec_switch, 1);
+ rb_define_method(cls, "global_local_var", language_spec_global_local_var, 0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/ruby/optional/capi/ext/module_under_autoload_spec.c b/spec/ruby/optional/capi/ext/module_under_autoload_spec.c
index c8f19a287b..b19466e555 100644
--- a/spec/ruby/optional/capi/ext/module_under_autoload_spec.c
+++ b/spec/ruby/optional/capi/ext/module_under_autoload_spec.c
@@ -1,7 +1,15 @@
#include "ruby.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void Init_module_under_autoload_spec(void) {
VALUE specs = rb_const_get(rb_cObject, rb_intern("CApiModuleSpecs"));
rb_define_module_under(specs, "ModuleUnderAutoload");
rb_define_module_under(specs, "RubyUnderAutoload");
}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/ruby/optional/capi/ext/numeric_spec.c b/spec/ruby/optional/capi/ext/numeric_spec.c
index 556c71a587..d3639580a8 100644
--- a/spec/ruby/optional/capi/ext/numeric_spec.c
+++ b/spec/ruby/optional/capi/ext/numeric_spec.c
@@ -54,13 +54,17 @@ static VALUE numeric_spec_NUM2INT(VALUE self, VALUE num) {
}
static VALUE numeric_spec_INT2NUM(VALUE self, VALUE num) {
- return INT2NUM(NUM2LONG(num));
+ return INT2NUM(NUM2INT(num));
}
static VALUE numeric_spec_NUM2LONG(VALUE self, VALUE num) {
return LONG2NUM(NUM2LONG(num));
}
+static VALUE numeric_spec_NUM2SHORT(VALUE self, VALUE num) {
+ return LONG2NUM(NUM2SHORT(num));
+}
+
static VALUE numeric_spec_NUM2UINT(VALUE self, VALUE num) {
return ULONG2NUM(NUM2UINT(num));
}
@@ -109,6 +113,7 @@ void Init_numeric_spec(void) {
rb_define_method(cls, "NUM2DBL", numeric_spec_NUM2DBL, 1);
rb_define_method(cls, "NUM2INT", numeric_spec_NUM2INT, 1);
rb_define_method(cls, "NUM2LONG", numeric_spec_NUM2LONG, 1);
+ rb_define_method(cls, "NUM2SHORT", numeric_spec_NUM2SHORT, 1);
rb_define_method(cls, "INT2NUM", numeric_spec_INT2NUM, 1);
rb_define_method(cls, "NUM2UINT", numeric_spec_NUM2UINT, 1);
rb_define_method(cls, "NUM2ULONG", numeric_spec_NUM2ULONG, 1);
diff --git a/spec/ruby/optional/capi/ext/object_spec.c b/spec/ruby/optional/capi/ext/object_spec.c
index cd32050f14..fbdc19954f 100644
--- a/spec/ruby/optional/capi/ext/object_spec.c
+++ b/spec/ruby/optional/capi/ext/object_spec.c
@@ -102,7 +102,7 @@ static VALUE so_rb_obj_dup(VALUE self, VALUE klass) {
static VALUE so_rb_obj_call_init(VALUE self, VALUE object,
VALUE nargs, VALUE args) {
int c_nargs = FIX2INT(nargs);
- VALUE *c_args = alloca(sizeof(VALUE) * c_nargs);
+ VALUE *c_args = (VALUE*) alloca(sizeof(VALUE) * c_nargs);
int i;
for (i = 0; i < c_nargs; i++)
@@ -315,6 +315,10 @@ static VALUE object_spec_rb_iv_set(VALUE self, VALUE obj, VALUE name, VALUE valu
return rb_iv_set(obj, RSTRING_PTR(name), value);
}
+static VALUE object_spec_rb_ivar_count(VALUE self, VALUE obj) {
+ return ULONG2NUM(rb_ivar_count(obj));
+}
+
static VALUE object_spec_rb_ivar_get(VALUE self, VALUE obj, VALUE sym_name) {
return rb_ivar_get(obj, SYM2ID(sym_name));
}
@@ -345,6 +349,40 @@ static VALUE object_spec_rb_class_inherited_p(VALUE self, VALUE mod, VALUE arg)
return rb_class_inherited_p(mod, arg);
}
+static VALUE speced_allocator(VALUE klass) {
+ VALUE flags = 0;
+ VALUE instance;
+ if (RTEST(rb_class_inherited_p(klass, rb_cString))) {
+ flags = T_STRING;
+ } else if (RTEST(rb_class_inherited_p(klass, rb_cArray))) {
+ flags = T_ARRAY;
+ } else {
+ flags = T_OBJECT;
+ }
+ instance = rb_newobj_of(klass, flags);
+ rb_iv_set(instance, "@from_custom_allocator", Qtrue);
+ return instance;
+}
+
+static VALUE define_alloc_func(VALUE self, VALUE klass) {
+ rb_define_alloc_func(klass, speced_allocator);
+ return Qnil;
+}
+
+static VALUE undef_alloc_func(VALUE self, VALUE klass) {
+ rb_undef_alloc_func(klass);
+ return Qnil;
+}
+
+static VALUE speced_allocator_p(VALUE self, VALUE klass) {
+ rb_alloc_func_t allocator = rb_get_alloc_func(klass);
+ return (allocator == speced_allocator) ? Qtrue : Qfalse;
+}
+
+static VALUE custom_alloc_func_p(VALUE self, VALUE klass) {
+ rb_alloc_func_t allocator = rb_get_alloc_func(klass);
+ return allocator ? Qtrue : Qfalse;
+}
void Init_object_spec(void) {
VALUE cls = rb_define_class("CApiObjectSpecs", rb_cObject);
@@ -407,11 +445,16 @@ void Init_object_spec(void) {
rb_define_method(cls, "rb_obj_instance_eval", object_spec_rb_obj_instance_eval, 1);
rb_define_method(cls, "rb_iv_get", object_spec_rb_iv_get, 2);
rb_define_method(cls, "rb_iv_set", object_spec_rb_iv_set, 3);
+ rb_define_method(cls, "rb_ivar_count", object_spec_rb_ivar_count, 1);
rb_define_method(cls, "rb_ivar_get", object_spec_rb_ivar_get, 2);
rb_define_method(cls, "rb_ivar_set", object_spec_rb_ivar_set, 3);
rb_define_method(cls, "rb_ivar_defined", object_spec_rb_ivar_defined, 2);
rb_define_method(cls, "rb_copy_generic_ivar", object_spec_rb_copy_generic_ivar, 2);
rb_define_method(cls, "rb_free_generic_ivar", object_spec_rb_free_generic_ivar, 1);
+ rb_define_method(cls, "rb_define_alloc_func", define_alloc_func, 1);
+ rb_define_method(cls, "rb_undef_alloc_func", undef_alloc_func, 1);
+ rb_define_method(cls, "speced_allocator?", speced_allocator_p, 1);
+ rb_define_method(cls, "custom_alloc_func?", custom_alloc_func_p, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/proc_spec.c b/spec/ruby/optional/capi/ext/proc_spec.c
index 18fd1997ee..e0bd8b1bbc 100644
--- a/spec/ruby/optional/capi/ext/proc_spec.c
+++ b/spec/ruby/optional/capi/ext/proc_spec.c
@@ -23,6 +23,10 @@ VALUE proc_spec_rb_proc_call(VALUE self, VALUE prc, VALUE args) {
return rb_proc_call(prc, args);
}
+VALUE proc_spec_rb_obj_is_proc(VALUE self, VALUE prc) {
+ return rb_obj_is_proc(prc);
+}
+
/* This helper is not strictly necessary but reflects the code in wxRuby that
* originally exposed issues with this Proc.new behavior.
*/
@@ -61,6 +65,7 @@ void Init_proc_spec(void) {
rb_define_method(cls, "rb_proc_arity", proc_spec_rb_proc_arity, 1);
rb_define_method(cls, "rb_proc_call", proc_spec_rb_proc_call, 2);
rb_define_method(cls, "rb_Proc_new", proc_spec_rb_Proc_new, 1);
+ rb_define_method(cls, "rb_obj_is_proc", proc_spec_rb_obj_is_proc, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/rbasic_spec.c b/spec/ruby/optional/capi/ext/rbasic_spec.c
new file mode 100644
index 0000000000..cf10904294
--- /dev/null
+++ b/spec/ruby/optional/capi/ext/rbasic_spec.c
@@ -0,0 +1,94 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef FL_SHAREABLE
+static const VALUE VISIBLE_BITS = FL_TAINT | FL_FREEZE | ~(FL_USER0 - 1);
+#else
+static const VALUE VISIBLE_BITS = FL_FREEZE | ~(FL_USER0 - 1);
+#endif
+
+#if SIZEOF_VALUE == SIZEOF_LONG
+#define VALUE2NUM(v) ULONG2NUM(v)
+#define NUM2VALUE(n) NUM2ULONG(n)
+#elif SIZEOF_VALUE == SIZEOF_LONG_LONG
+#define VALUE2NUM(v) ULL2NUM(v)
+#define NUM2VALUE(n) NUM2ULL(n)
+#else
+#error "unsupported"
+#endif
+
+
+VALUE rbasic_spec_taint_flag(VALUE self) {
+ return VALUE2NUM(RUBY_FL_TAINT);
+}
+
+VALUE rbasic_spec_freeze_flag(VALUE self) {
+ return VALUE2NUM(RUBY_FL_FREEZE);
+}
+
+static VALUE spec_get_flags(const struct RBasic *b) {
+ VALUE flags = b->flags & VISIBLE_BITS;
+ return VALUE2NUM(flags);
+}
+
+static VALUE spec_set_flags(struct RBasic *b, VALUE flags) {
+ flags &= VISIBLE_BITS;
+ b->flags = (b->flags & ~VISIBLE_BITS) | flags;
+ return VALUE2NUM(flags);
+}
+
+VALUE rbasic_spec_get_flags(VALUE self, VALUE val) {
+ return spec_get_flags(RBASIC(val));
+}
+
+VALUE rbasic_spec_set_flags(VALUE self, VALUE val, VALUE flags) {
+ return spec_set_flags(RBASIC(val), NUM2VALUE(flags));
+}
+
+VALUE rbasic_spec_copy_flags(VALUE self, VALUE to, VALUE from) {
+ return spec_set_flags(RBASIC(to), RBASIC(from)->flags);
+}
+
+VALUE rbasic_spec_get_klass(VALUE self, VALUE val) {
+ return RBASIC(val)->klass;
+}
+
+VALUE rbasic_rdata_spec_get_flags(VALUE self, VALUE structure) {
+ return spec_get_flags(&RDATA(structure)->basic);
+}
+
+VALUE rbasic_rdata_spec_set_flags(VALUE self, VALUE structure, VALUE flags) {
+ return spec_set_flags(&RDATA(structure)->basic, NUM2VALUE(flags));
+}
+
+VALUE rbasic_rdata_spec_copy_flags(VALUE self, VALUE to, VALUE from) {
+ return spec_set_flags(&RDATA(to)->basic, RDATA(from)->basic.flags);
+}
+
+VALUE rbasic_rdata_spec_get_klass(VALUE self, VALUE structure) {
+ return RDATA(structure)->basic.klass;
+}
+
+void Init_rbasic_spec(void) {
+ VALUE cls = rb_define_class("CApiRBasicSpecs", rb_cObject);
+ rb_define_method(cls, "taint_flag", rbasic_spec_taint_flag, 0);
+ rb_define_method(cls, "freeze_flag", rbasic_spec_freeze_flag, 0);
+ rb_define_method(cls, "get_flags", rbasic_spec_get_flags, 1);
+ rb_define_method(cls, "set_flags", rbasic_spec_set_flags, 2);
+ rb_define_method(cls, "copy_flags", rbasic_spec_copy_flags, 2);
+ rb_define_method(cls, "get_klass", rbasic_spec_get_klass, 1);
+
+ cls = rb_define_class("CApiRBasicRDataSpecs", rb_cObject);
+ rb_define_method(cls, "get_flags", rbasic_rdata_spec_get_flags, 1);
+ rb_define_method(cls, "set_flags", rbasic_rdata_spec_set_flags, 2);
+ rb_define_method(cls, "copy_flags", rbasic_rdata_spec_copy_flags, 2);
+ rb_define_method(cls, "get_klass", rbasic_rdata_spec_get_klass, 1);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/ruby/optional/capi/ext/regexp_spec.c b/spec/ruby/optional/capi/ext/regexp_spec.c
index fc1c8b1e63..70780bae2a 100644
--- a/spec/ruby/optional/capi/ext/regexp_spec.c
+++ b/spec/ruby/optional/capi/ext/regexp_spec.c
@@ -9,8 +9,10 @@
extern "C" {
#endif
-VALUE regexp_spec_re(VALUE self) {
- return rb_reg_new("a", 1, 0);
+VALUE regexp_spec_re(VALUE self, VALUE str, VALUE options) {
+ char *cstr = StringValueCStr(str);
+ int opts = FIX2INT(options);
+ return rb_reg_new(cstr, strlen(cstr), opts);
}
VALUE regexp_spec_reg_1st_match(VALUE self, VALUE md) {
@@ -33,6 +35,11 @@ VALUE regexp_spec_backref_get(VALUE self) {
return rb_backref_get();
}
+VALUE regexp_spec_reg_match_backref_get(VALUE self, VALUE re, VALUE str) {
+ rb_reg_match(re, str);
+ return rb_backref_get();
+}
+
VALUE regexp_spec_match(VALUE self, VALUE regexp, VALUE str) {
return rb_funcall(regexp, rb_intern("match"), 1, str);
}
@@ -40,10 +47,11 @@ VALUE regexp_spec_match(VALUE self, VALUE regexp, VALUE str) {
void Init_regexp_spec(void) {
VALUE cls = rb_define_class("CApiRegexpSpecs", rb_cObject);
rb_define_method(cls, "match", regexp_spec_match, 2);
- rb_define_method(cls, "a_re", regexp_spec_re, 0);
+ rb_define_method(cls, "a_re", regexp_spec_re, 2);
rb_define_method(cls, "a_re_1st_match", regexp_spec_reg_1st_match, 1);
rb_define_method(cls, "rb_reg_match", regexp_spec_reg_match, 2);
rb_define_method(cls, "rb_backref_get", regexp_spec_backref_get, 0);
+ rb_define_method(cls, "rb_reg_match_backref_get", regexp_spec_reg_match_backref_get, 2);
rb_define_method(cls, "rb_reg_options", regexp_spec_rb_reg_options, 1);
rb_define_method(cls, "rb_reg_regcomp", regexp_spec_rb_reg_regcomp, 1);
}
diff --git a/spec/ruby/optional/capi/ext/rubyspec.h b/spec/ruby/optional/capi/ext/rubyspec.h
index 78e298fddb..b4d604e647 100644
--- a/spec/ruby/optional/capi/ext/rubyspec.h
+++ b/spec/ruby/optional/capi/ext/rubyspec.h
@@ -1,9 +1,8 @@
#ifndef RUBYSPEC_H
#define RUBYSPEC_H
-/* Define convenience macros similar to the mspec guards to assist
- * with version incompatibilities.
- */
+/* Define convenience macros similar to the mspec
+ * guards to assist with version incompatibilities. */
#include <ruby.h>
#ifdef HAVE_RUBY_VERSION_H
@@ -23,12 +22,38 @@
(RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR < (minor)) || \
(RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR == (minor) && RUBY_VERSION_TEENY < (teeny)))
+#if RUBY_VERSION_MAJOR > 3 || (RUBY_VERSION_MAJOR == 3 && RUBY_VERSION_MINOR >= 0)
+#define RUBY_VERSION_IS_3_0
+#endif
+
+#if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 7)
+#define RUBY_VERSION_IS_2_7
+#endif
+
#if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 6)
#define RUBY_VERSION_IS_2_6
#endif
-#if RUBY_VERSION_MAJOR > 2 || (RUBY_VERSION_MAJOR == 2 && RUBY_VERSION_MINOR >= 4)
-#define RUBY_VERSION_IS_2_4
+#if defined(__cplusplus) && !defined(RUBY_VERSION_IS_2_7)
+/* Ruby < 2.7 needs this to let these function with callbacks and compile in C++ code */
+#define rb_define_method(mod, name, func, argc) rb_define_method(mod, name, RUBY_METHOD_FUNC(func), argc)
+#define rb_define_protected_method(mod, name, func, argc) rb_define_protected_method(mod, name, RUBY_METHOD_FUNC(func), argc)
+#define rb_define_private_method(mod, name, func, argc) rb_define_private_method(mod, name, RUBY_METHOD_FUNC(func), argc)
+#define rb_define_singleton_method(mod, name, func, argc) rb_define_singleton_method(mod, name, RUBY_METHOD_FUNC(func), argc)
+#define rb_define_module_function(mod, name, func, argc) rb_define_module_function(mod, name, RUBY_METHOD_FUNC(func), argc)
+#define rb_define_global_function(name, func, argc) rb_define_global_function(name, RUBY_METHOD_FUNC(func), argc)
+#define rb_iterate(function, arg1, block, arg2) rb_iterate(function, arg1, RUBY_METHOD_FUNC(block), arg2)
+#define rb_hash_foreach(hash, func, farg) rb_hash_foreach(hash, (int (*)(...))func, farg)
+#define st_foreach(tab, func, arg) st_foreach(tab, (int (*)(...))func, arg)
+#define rb_block_call(object, name, args_count, args, block_call_func, data) rb_block_call(object, name, args_count, args, RUBY_METHOD_FUNC(block_call_func), data)
+#define rb_ensure(b_proc, data1, e_proc, data2) rb_ensure(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2)
+#define rb_rescue(b_proc, data1, e_proc, data2) rb_rescue(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2)
+#define rb_rescue2(b_proc, data1, e_proc, data2, ...) rb_rescue2(RUBY_METHOD_FUNC(b_proc), data1, RUBY_METHOD_FUNC(e_proc), data2, __VA_ARGS__)
+#define rb_catch(tag, func, data) rb_catch(tag, RUBY_METHOD_FUNC(func), data)
+#define rb_catch_obj(tag, func, data) rb_catch_obj(tag, RUBY_METHOD_FUNC(func), data)
+#define rb_proc_new(fn, arg) rb_proc_new(RUBY_METHOD_FUNC(fn), arg)
+#define rb_thread_create(fn, arg) rb_thread_create(RUBY_METHOD_FUNC(fn), arg)
+#define rb_define_hooked_variable(name, var, getter, setter) rb_define_hooked_variable(name, var, RUBY_METHOD_FUNC(getter), (void (*)(...))setter)
#endif
#endif
diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c
index a44e437bba..dd7bc397cd 100644
--- a/spec/ruby/optional/capi/ext/string_spec.c
+++ b/spec/ruby/optional/capi/ext/string_spec.c
@@ -49,6 +49,12 @@ VALUE string_spec_rb_str_set_len_RSTRING_LEN(VALUE self, VALUE str, VALUE len) {
return INT2FIX(RSTRING_LEN(str));
}
+VALUE rb_fstring(VALUE str); /* internal.h, used in ripper */
+
+VALUE string_spec_rb_str_fstring(VALUE self, VALUE str) {
+ return rb_fstring(str);
+}
+
VALUE string_spec_rb_str_buf_new(VALUE self, VALUE len, VALUE str) {
VALUE buf;
@@ -69,12 +75,28 @@ VALUE string_spec_rb_str_buf_new2(VALUE self) {
return rb_str_buf_new2("hello\0invisible");
}
+VALUE string_spec_rb_str_tmp_new(VALUE self, VALUE len) {
+ VALUE str = rb_str_tmp_new(NUM2LONG(len));
+ rb_obj_reveal(str, rb_cString);
+ return str;
+}
+
+VALUE string_spec_rb_str_tmp_new_klass(VALUE self, VALUE len) {
+ return RBASIC_CLASS(rb_str_tmp_new(NUM2LONG(len)));
+}
+
VALUE string_spec_rb_str_buf_cat(VALUE self, VALUE str) {
const char *question_mark = "?";
rb_str_buf_cat(str, question_mark, strlen(question_mark));
return str;
}
+VALUE string_spec_rb_enc_str_buf_cat(VALUE self, VALUE str, VALUE other, VALUE encoding) {
+ char *cstr = StringValueCStr(other);
+ rb_encoding* enc = rb_to_encoding(encoding);
+ return rb_enc_str_buf_cat(str, cstr, strlen(cstr), enc);
+}
+
VALUE string_spec_rb_str_cat(VALUE self, VALUE str) {
return rb_str_cat(str, "?", 1);
}
@@ -83,6 +105,14 @@ VALUE string_spec_rb_str_cat2(VALUE self, VALUE str) {
return rb_str_cat2(str, "?");
}
+VALUE string_spec_rb_str_cat_cstr(VALUE self, VALUE str, VALUE other) {
+ return rb_str_cat_cstr(str, StringValueCStr(other));
+}
+
+VALUE string_spec_rb_str_cat_cstr_constant(VALUE self, VALUE str) {
+ return rb_str_cat_cstr(str, "?");
+}
+
VALUE string_spec_rb_str_cmp(VALUE self, VALUE str1, VALUE str2) {
return INT2NUM(rb_str_cmp(str1, str2));
}
@@ -284,6 +314,25 @@ VALUE string_spec_RSTRING_PTR_iterate(VALUE self, VALUE str) {
return Qnil;
}
+VALUE string_spec_RSTRING_PTR_iterate_uint32(VALUE self, VALUE str) {
+ uint32_t* ptr;
+ long i, l = RSTRING_LEN(str) / sizeof(uint32_t);
+
+ ptr = (uint32_t *)RSTRING_PTR(str);
+ for(i = 0; i < l; i++) {
+ rb_yield(UINT2NUM(ptr[i]));
+ }
+ return Qnil;
+}
+
+VALUE string_spec_RSTRING_PTR_short_memcpy(VALUE self, VALUE str) {
+ /* Short memcpy operations may be optimised by the compiler to a single write. */
+ if (RSTRING_LEN(str) >= 8) {
+ memcpy(RSTRING_PTR(str), "Infinity", 8);
+ }
+ return str;
+}
+
VALUE string_spec_RSTRING_PTR_assign(VALUE self, VALUE str, VALUE chr) {
int i;
char c;
@@ -337,11 +386,7 @@ static VALUE string_spec_SafeStringValue(VALUE self, VALUE str) {
static VALUE string_spec_rb_str_hash(VALUE self, VALUE str) {
st_index_t val = rb_str_hash(str);
-#if SIZEOF_LONG == SIZEOF_VOIDP || SIZEOF_LONG_LONG == SIZEOF_VOIDP
- return LONG2FIX((long)val);
-#else
-#error unsupported platform
-#endif
+ return ST2FIX(val);
}
static VALUE string_spec_rb_str_update(VALUE self, VALUE str, VALUE beg, VALUE end, VALUE replacement) {
@@ -362,11 +407,11 @@ static VALUE string_spec_rb_sprintf2(VALUE self, VALUE str, VALUE repl1, VALUE r
}
static VALUE string_spec_rb_sprintf3(VALUE self, VALUE str) {
- return rb_sprintf("Result: %"PRIsVALUE".", str);
+ return rb_sprintf("Result: %" PRIsVALUE ".", str);
}
static VALUE string_spec_rb_sprintf4(VALUE self, VALUE str) {
- return rb_sprintf("Result: %+"PRIsVALUE".", str);
+ return rb_sprintf("Result: %+" PRIsVALUE ".", str);
}
static VALUE string_spec_rb_vsprintf_worker(char* fmt, ...) {
@@ -393,6 +438,14 @@ static VALUE string_spec_rb_usascii_str_new(VALUE self, VALUE str, VALUE len) {
return rb_usascii_str_new(RSTRING_PTR(str), NUM2INT(len));
}
+static VALUE string_spec_rb_usascii_str_new_lit(VALUE self) {
+ return rb_usascii_str_new_lit("nokogiri");
+}
+
+static VALUE string_spec_rb_usascii_str_new_lit_non_ascii(VALUE self) {
+ return rb_usascii_str_new_lit("r\xc3\xa9sum\xc3\xa9");
+}
+
static VALUE string_spec_rb_usascii_str_new_cstr(VALUE self, VALUE str) {
return rb_usascii_str_new_cstr(RSTRING_PTR(str));
}
@@ -427,14 +480,20 @@ void Init_string_spec(void) {
VALUE cls = rb_define_class("CApiStringSpecs", rb_cObject);
rb_define_method(cls, "rb_cstr2inum", string_spec_rb_cstr2inum, 2);
rb_define_method(cls, "rb_cstr_to_inum", string_spec_rb_cstr_to_inum, 3);
+ rb_define_method(cls, "rb_fstring", string_spec_rb_str_fstring, 1);
rb_define_method(cls, "rb_str2inum", string_spec_rb_str2inum, 2);
rb_define_method(cls, "rb_str_append", string_spec_rb_str_append, 2);
rb_define_method(cls, "rb_str_buf_new", string_spec_rb_str_buf_new, 2);
rb_define_method(cls, "rb_str_capacity", string_spec_rb_str_capacity, 1);
rb_define_method(cls, "rb_str_buf_new2", string_spec_rb_str_buf_new2, 0);
+ rb_define_method(cls, "rb_str_tmp_new", string_spec_rb_str_tmp_new, 1);
+ rb_define_method(cls, "rb_str_tmp_new_klass", string_spec_rb_str_tmp_new_klass, 1);
rb_define_method(cls, "rb_str_buf_cat", string_spec_rb_str_buf_cat, 1);
+ rb_define_method(cls, "rb_enc_str_buf_cat", string_spec_rb_enc_str_buf_cat, 3);
rb_define_method(cls, "rb_str_cat", string_spec_rb_str_cat, 1);
rb_define_method(cls, "rb_str_cat2", string_spec_rb_str_cat2, 1);
+ rb_define_method(cls, "rb_str_cat_cstr", string_spec_rb_str_cat_cstr, 2);
+ rb_define_method(cls, "rb_str_cat_cstr_constant", string_spec_rb_str_cat_cstr_constant, 1);
rb_define_method(cls, "rb_str_cmp", string_spec_rb_str_cmp, 2);
rb_define_method(cls, "rb_str_conv_enc", string_spec_rb_str_conv_enc, 3);
rb_define_method(cls, "rb_str_conv_enc_opts", string_spec_rb_str_conv_enc_opts, 5);
@@ -477,6 +536,8 @@ void Init_string_spec(void) {
rb_define_method(cls, "RSTRING_LEN", string_spec_RSTRING_LEN, 1);
rb_define_method(cls, "RSTRING_LENINT", string_spec_RSTRING_LENINT, 1);
rb_define_method(cls, "RSTRING_PTR_iterate", string_spec_RSTRING_PTR_iterate, 1);
+ rb_define_method(cls, "RSTRING_PTR_iterate_uint32", string_spec_RSTRING_PTR_iterate_uint32, 1);
+ rb_define_method(cls, "RSTRING_PTR_short_memcpy", string_spec_RSTRING_PTR_short_memcpy, 1);
rb_define_method(cls, "RSTRING_PTR_assign", string_spec_RSTRING_PTR_assign, 2);
rb_define_method(cls, "RSTRING_PTR_set", string_spec_RSTRING_PTR_set, 3);
rb_define_method(cls, "RSTRING_PTR_after_funcall", string_spec_RSTRING_PTR_after_funcall, 2);
@@ -493,6 +554,8 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_vsprintf", string_spec_rb_vsprintf, 4);
rb_define_method(cls, "rb_str_equal", string_spec_rb_str_equal, 2);
rb_define_method(cls, "rb_usascii_str_new", string_spec_rb_usascii_str_new, 2);
+ rb_define_method(cls, "rb_usascii_str_new_lit", string_spec_rb_usascii_str_new_lit, 0);
+ rb_define_method(cls, "rb_usascii_str_new_lit_non_ascii", string_spec_rb_usascii_str_new_lit_non_ascii, 0);
rb_define_method(cls, "rb_usascii_str_new_cstr", string_spec_rb_usascii_str_new_cstr, 1);
rb_define_method(cls, "rb_String", string_spec_rb_String, 1);
rb_define_method(cls, "rb_string_value_cstr", string_spec_rb_string_value_cstr, 1);
diff --git a/spec/ruby/optional/capi/ext/struct_spec.c b/spec/ruby/optional/capi/ext/struct_spec.c
index b9c3b902bf..0393d6937d 100644
--- a/spec/ruby/optional/capi/ext/struct_spec.c
+++ b/spec/ruby/optional/capi/ext/struct_spec.c
@@ -62,12 +62,10 @@ static VALUE struct_spec_rb_struct_new(VALUE self, VALUE klass,
return rb_struct_new(klass, a, b, c);
}
-#ifdef RUBY_VERSION_IS_2_4
static VALUE struct_spec_rb_struct_size(VALUE self, VALUE st)
{
return rb_struct_size(st);
}
-#endif
void Init_struct_spec(void) {
VALUE cls = rb_define_class("CApiStructSpecs", rb_cObject);
@@ -79,9 +77,7 @@ void Init_struct_spec(void) {
rb_define_method(cls, "rb_struct_define", struct_spec_struct_define, 4);
rb_define_method(cls, "rb_struct_define_under", struct_spec_struct_define_under, 5);
rb_define_method(cls, "rb_struct_new", struct_spec_rb_struct_new, 4);
-#ifdef RUBY_VERSION_IS_2_4
rb_define_method(cls, "rb_struct_size", struct_spec_rb_struct_size, 1);
-#endif
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/symbol_spec.c b/spec/ruby/optional/capi/ext/symbol_spec.c
index 28da69ea3c..7d9a7b4379 100644
--- a/spec/ruby/optional/capi/ext/symbol_spec.c
+++ b/spec/ruby/optional/capi/ext/symbol_spec.c
@@ -7,6 +7,10 @@
extern "C" {
#endif
+VALUE symbol_spec_SYMBOL_P(VALUE self, VALUE obj) {
+ return SYMBOL_P(obj) ? Qtrue : Qfalse;
+}
+
VALUE symbol_spec_rb_intern(VALUE self, VALUE string) {
return ID2SYM(rb_intern(RSTRING_PTR(string)));
}
@@ -51,6 +55,10 @@ VALUE symbol_spec_rb_intern_str(VALUE self, VALUE str) {
return ID2SYM(rb_intern_str(str));
}
+VALUE symbol_spec_rb_check_symbol_cstr(VALUE self, VALUE str) {
+ return rb_check_symbol_cstr(RSTRING_PTR(str), RSTRING_LEN(str), rb_enc_get(str));
+}
+
VALUE symbol_spec_rb_is_class_id(VALUE self, VALUE sym) {
return rb_is_class_id(SYM2ID(sym)) ? Qtrue : Qfalse;
}
@@ -67,8 +75,13 @@ VALUE symbol_spec_rb_sym2str(VALUE self, VALUE sym) {
return rb_sym2str(sym);
}
+VALUE symbol_spec_rb_to_symbol(VALUE self, VALUE val) {
+ return rb_to_symbol(val);
+}
+
void Init_symbol_spec(void) {
VALUE cls = rb_define_class("CApiSymbolSpecs", rb_cObject);
+ rb_define_method(cls, "SYMBOL_P", symbol_spec_SYMBOL_P, 1);
rb_define_method(cls, "rb_intern", symbol_spec_rb_intern, 1);
rb_define_method(cls, "rb_intern2", symbol_spec_rb_intern2, 2);
rb_define_method(cls, "rb_intern_const", symbol_spec_rb_intern_const, 1);
@@ -79,10 +92,12 @@ void Init_symbol_spec(void) {
rb_define_method(cls, "rb_id2name", symbol_spec_rb_id2name, 1);
rb_define_method(cls, "rb_id2str", symbol_spec_rb_id2str, 1);
rb_define_method(cls, "rb_intern_str", symbol_spec_rb_intern_str, 1);
+ rb_define_method(cls, "rb_check_symbol_cstr", symbol_spec_rb_check_symbol_cstr, 1);
rb_define_method(cls, "rb_is_class_id", symbol_spec_rb_is_class_id, 1);
rb_define_method(cls, "rb_is_const_id", symbol_spec_rb_is_const_id, 1);
rb_define_method(cls, "rb_is_instance_id", symbol_spec_rb_is_instance_id, 1);
rb_define_method(cls, "rb_sym2str", symbol_spec_rb_sym2str, 1);
+ rb_define_method(cls, "rb_to_symbol", symbol_spec_rb_to_symbol, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/thread_spec.c b/spec/ruby/optional/capi/ext/thread_spec.c
index 139652e326..21f98dec52 100644
--- a/spec/ruby/optional/capi/ext/thread_spec.c
+++ b/spec/ruby/optional/capi/ext/thread_spec.c
@@ -15,11 +15,13 @@
extern "C" {
#endif
-static VALUE thread_spec_rb_thread_alone() {
+static VALUE thread_spec_rb_thread_alone(VALUE self) {
return rb_thread_alone() ? Qtrue : Qfalse;
}
+#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
/* This is unblocked by unblock_func(). */
static void* blocking_gvl_func(void* data) {
@@ -89,7 +91,7 @@ static VALUE thread_spec_rb_thread_call_without_gvl_with_ubf_io(VALUE self) {
return (VALUE)ret;
}
-static VALUE thread_spec_rb_thread_current() {
+static VALUE thread_spec_rb_thread_current(VALUE self) {
return rb_thread_current();
}
diff --git a/spec/ruby/optional/capi/ext/tracepoint_spec.c b/spec/ruby/optional/capi/ext/tracepoint_spec.c
new file mode 100644
index 0000000000..78c459d6cb
--- /dev/null
+++ b/spec/ruby/optional/capi/ext/tracepoint_spec.c
@@ -0,0 +1,49 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include <ruby/debug.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static VALUE callback_called = Qnil;
+
+static void callback(VALUE tpval, void *data) {
+ callback_called = (VALUE) data;
+}
+
+static VALUE tracepoint_spec_rb_tracepoint_new(VALUE self, VALUE data) {
+ return rb_tracepoint_new(Qnil, RUBY_EVENT_LINE, callback, (void*) data);
+}
+
+static VALUE tracepoint_spec_callback_called(VALUE self){
+ return callback_called;
+}
+
+static VALUE tracepoint_spec_rb_tracepoint_disable(VALUE self, VALUE trace) {
+ rb_tracepoint_disable(trace);
+ return rb_tracepoint_enabled_p(trace);
+}
+
+static VALUE tracepoint_spec_rb_tracepoint_enable(VALUE self, VALUE trace) {
+ rb_tracepoint_enable(trace);
+ return rb_tracepoint_enabled_p(trace);
+}
+
+static VALUE tracepoint_spec_rb_tracepoint_enabled_p(VALUE self, VALUE trace) {
+ return rb_tracepoint_enabled_p(trace);
+}
+
+void Init_tracepoint_spec(void) {
+ VALUE cls = rb_define_class("CApiTracePointSpecs", rb_cObject);
+ rb_define_method(cls, "rb_tracepoint_new", tracepoint_spec_rb_tracepoint_new, 1);
+ rb_define_method(cls, "rb_tracepoint_disable", tracepoint_spec_rb_tracepoint_disable, 1);
+ rb_define_method(cls, "rb_tracepoint_enable", tracepoint_spec_rb_tracepoint_enable, 1);
+ rb_define_method(cls, "rb_tracepoint_enabled_p", tracepoint_spec_rb_tracepoint_enabled_p, 1);
+ rb_define_method(cls, "callback_called?", tracepoint_spec_callback_called, 0);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/ruby/optional/capi/ext/typed_data_spec.c b/spec/ruby/optional/capi/ext/typed_data_spec.c
index a2cc53f54d..70f21ce36f 100644
--- a/spec/ruby/optional/capi/ext/typed_data_spec.c
+++ b/spec/ruby/optional/capi/ext/typed_data_spec.c
@@ -8,7 +8,7 @@ extern "C" {
#endif
struct sample_typed_wrapped_struct_parent {
- int foo;
+ int foo;
};
void sample_typed_wrapped_struct_parent_free(void* st) {
@@ -32,7 +32,7 @@ static const rb_data_type_t sample_typed_wrapped_struct_parent_data_type = {
};
struct sample_typed_wrapped_struct {
- int foo;
+ int foo;
};
void sample_typed_wrapped_struct_free(void* st) {
@@ -61,7 +61,7 @@ static const rb_data_type_t sample_typed_wrapped_struct_data_type = {
};
struct sample_typed_wrapped_struct_other {
- int foo;
+ int foo;
};
void sample_typed_wrapped_struct_other_free(void* st) {
@@ -86,43 +86,45 @@ static const rb_data_type_t sample_typed_wrapped_struct_other_data_type = {
VALUE sdaf_alloc_typed_func(VALUE klass) {
- struct sample_typed_wrapped_struct* bar = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
- bar->foo = 42;
- return TypedData_Wrap_Struct(klass, &sample_typed_wrapped_struct_data_type, bar);
+ struct sample_typed_wrapped_struct* bar;
+ bar = (struct sample_typed_wrapped_struct *) malloc(sizeof(struct sample_typed_wrapped_struct));
+ bar->foo = 42;
+ return TypedData_Wrap_Struct(klass, &sample_typed_wrapped_struct_data_type, bar);
}
VALUE sdaf_typed_get_struct(VALUE self) {
- struct sample_typed_wrapped_struct* bar;
- TypedData_Get_Struct(self, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
+ struct sample_typed_wrapped_struct* bar;
+ TypedData_Get_Struct(self, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
- return INT2FIX((*bar).foo);
+ return INT2FIX((*bar).foo);
}
VALUE sws_typed_wrap_struct(VALUE self, VALUE val) {
- struct sample_typed_wrapped_struct* bar = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
- bar->foo = FIX2INT(val);
- return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar);
+ struct sample_typed_wrapped_struct* bar;
+ bar = (struct sample_typed_wrapped_struct *) malloc(sizeof(struct sample_typed_wrapped_struct));
+ bar->foo = FIX2INT(val);
+ return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar);
}
VALUE sws_typed_get_struct(VALUE self, VALUE obj) {
- struct sample_typed_wrapped_struct* bar;
- TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
+ struct sample_typed_wrapped_struct* bar;
+ TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct, &sample_typed_wrapped_struct_data_type, bar);
- return INT2FIX((*bar).foo);
+ return INT2FIX((*bar).foo);
}
VALUE sws_typed_get_struct_different_type(VALUE self, VALUE obj) {
- struct sample_typed_wrapped_struct_other* bar;
- TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_other, &sample_typed_wrapped_struct_other_data_type, bar);
+ struct sample_typed_wrapped_struct_other* bar;
+ TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_other, &sample_typed_wrapped_struct_other_data_type, bar);
- return INT2FIX((*bar).foo);
+ return INT2FIX((*bar).foo);
}
VALUE sws_typed_get_struct_parent_type(VALUE self, VALUE obj) {
- struct sample_typed_wrapped_struct_parent* bar;
- TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_parent, &sample_typed_wrapped_struct_parent_data_type, bar);
+ struct sample_typed_wrapped_struct_parent* bar;
+ TypedData_Get_Struct(obj, struct sample_typed_wrapped_struct_parent, &sample_typed_wrapped_struct_parent_data_type, bar);
- return INT2FIX((*bar).foo);
+ return INT2FIX((*bar).foo);
}
VALUE sws_typed_get_struct_rdata(VALUE self, VALUE obj) {
@@ -138,15 +140,26 @@ VALUE sws_typed_get_struct_data_ptr(VALUE self, VALUE obj) {
}
VALUE sws_typed_change_struct(VALUE self, VALUE obj, VALUE new_val) {
- struct sample_typed_wrapped_struct *old_struct, *new_struct;
- new_struct = (struct sample_typed_wrapped_struct *)malloc(sizeof(struct sample_typed_wrapped_struct));
+ struct sample_typed_wrapped_struct *new_struct;
+ new_struct = (struct sample_typed_wrapped_struct *) malloc(sizeof(struct sample_typed_wrapped_struct));
new_struct->foo = FIX2INT(new_val);
- old_struct = RTYPEDDATA(obj)->data;
- free(old_struct);
+ free(RTYPEDDATA(obj)->data);
RTYPEDDATA(obj)->data = new_struct;
return Qnil;
}
+VALUE sws_typed_rb_check_typeddata_same_type(VALUE self, VALUE obj) {
+ return rb_check_typeddata(obj, &sample_typed_wrapped_struct_data_type) == DATA_PTR(obj) ? Qtrue : Qfalse;
+}
+
+VALUE sws_typed_rb_check_typeddata_same_type_parent(VALUE self, VALUE obj) {
+ return rb_check_typeddata(obj, &sample_typed_wrapped_struct_parent_data_type) == DATA_PTR(obj) ? Qtrue : Qfalse;
+}
+
+VALUE sws_typed_rb_check_typeddata_different_type(VALUE self, VALUE obj) {
+ return rb_check_typeddata(obj, &sample_typed_wrapped_struct_other_data_type) == DATA_PTR(obj) ? Qtrue : Qfalse;
+}
+
void Init_typed_data_spec(void) {
VALUE cls = rb_define_class("CApiAllocTypedSpecs", rb_cObject);
rb_define_alloc_func(cls, sdaf_alloc_typed_func);
@@ -159,6 +172,9 @@ void Init_typed_data_spec(void) {
rb_define_method(cls, "typed_get_struct_rdata", sws_typed_get_struct_rdata, 1);
rb_define_method(cls, "typed_get_struct_data_ptr", sws_typed_get_struct_data_ptr, 1);
rb_define_method(cls, "typed_change_struct", sws_typed_change_struct, 2);
+ rb_define_method(cls, "rb_check_typeddata_same_type", sws_typed_rb_check_typeddata_same_type, 1);
+ rb_define_method(cls, "rb_check_typeddata_same_type_parent", sws_typed_rb_check_typeddata_same_type_parent, 1);
+ rb_define_method(cls, "rb_check_typeddata_different_type", sws_typed_rb_check_typeddata_different_type, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/util_spec.c b/spec/ruby/optional/capi/ext/util_spec.c
index f3c6a1ba58..a7269353c2 100644
--- a/spec/ruby/optional/capi/ext/util_spec.c
+++ b/spec/ruby/optional/capi/ext/util_spec.c
@@ -1,4 +1,5 @@
#include "ruby.h"
+#include "ruby/util.h"
#include "rubyspec.h"
#ifdef __cplusplus
@@ -60,8 +61,8 @@ static VALUE util_spec_rb_get_kwargs(VALUE self, VALUE keyword_hash, VALUE keys,
int values_len = req + (opt < 0 ? -1 - opt : opt);
int i = 0;
- ID *ids = malloc(sizeof(VALUE) * len);
- VALUE *results = malloc(sizeof(VALUE) * values_len);
+ ID *ids = (ID*) malloc(sizeof(VALUE) * len);
+ VALUE *results = (VALUE*) malloc(sizeof(VALUE) * values_len);
int extracted = 0;
VALUE ary = Qundef;
@@ -93,6 +94,18 @@ static VALUE util_spec_rb_sourceline(VALUE self) {
return INT2NUM(rb_sourceline());
}
+static VALUE util_spec_strtod(VALUE self, VALUE string) {
+ char *endptr = NULL;
+ double value = strtod(RSTRING_PTR(string), &endptr);
+ return rb_ary_new_from_args(2, rb_float_new(value), endptr ? rb_str_new2(endptr) : Qnil);
+}
+
+static VALUE util_spec_ruby_strtod(VALUE self, VALUE string) {
+ char *endptr = NULL;
+ double value = ruby_strtod(RSTRING_PTR(string), &endptr);
+ return rb_ary_new_from_args(2, rb_float_new(value), endptr ? rb_str_new2(endptr) : Qnil);
+}
+
void Init_util_spec(void) {
VALUE cls = rb_define_class("CApiUtilSpecs", rb_cObject);
rb_define_method(cls, "rb_scan_args", util_spec_rb_scan_args, 4);
@@ -101,6 +114,8 @@ void Init_util_spec(void) {
rb_define_method(cls, "rb_iter_break", util_spec_rb_iter_break, 0);
rb_define_method(cls, "rb_sourcefile", util_spec_rb_sourcefile, 0);
rb_define_method(cls, "rb_sourceline", util_spec_rb_sourceline, 0);
+ rb_define_method(cls, "strtod", util_spec_strtod, 1);
+ rb_define_method(cls, "ruby_strtod", util_spec_ruby_strtod, 1);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/float_spec.rb b/spec/ruby/optional/capi/float_spec.rb
index 8381945315..4b98902b59 100644
--- a/spec/ruby/optional/capi/float_spec.rb
+++ b/spec/ruby/optional/capi/float_spec.rb
@@ -27,4 +27,17 @@ describe "CApiFloatSpecs" do
f.should eql(101.99)
end
end
+
+ describe "RB_FLOAT_TYPE_P" do
+ it "returns true for floats" do
+ @f.RB_FLOAT_TYPE_P(2.0).should == true
+ end
+
+ it "returns false for non-floats" do
+ @f.RB_FLOAT_TYPE_P(nil).should == false
+ @f.RB_FLOAT_TYPE_P(10).should == false
+ @f.RB_FLOAT_TYPE_P("string").should == false
+ @f.RB_FLOAT_TYPE_P(Object.new).should == false
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/gc_spec.rb b/spec/ruby/optional/capi/gc_spec.rb
index 46c03156e4..23e2b7c9ab 100644
--- a/spec/ruby/optional/capi/gc_spec.rb
+++ b/spec/ruby/optional/capi/gc_spec.rb
@@ -58,4 +58,30 @@ describe "CApiGCSpecs" do
}.should_not raise_error
end
end
+
+ describe "rb_gc_register_mark_object" do
+ it "can be called with an object" do
+ @f.rb_gc_register_mark_object(Object.new).should be_nil
+ end
+ end
+
+ describe "rb_gc_latest_gc_info" do
+ it "raises a TypeError when hash or symbol not given" do
+ -> { @f.rb_gc_latest_gc_info("foo") }.should raise_error(TypeError)
+ end
+
+ it "raises an ArgumentError when unknown symbol given" do
+ -> { @f.rb_gc_latest_gc_info(:unknown) }.should raise_error(ArgumentError)
+ end
+
+ it "returns the populated hash when a hash is given" do
+ h = {}
+ @f.rb_gc_latest_gc_info(h).should == h
+ h.size.should_not == 0
+ end
+
+ it "returns a value when symbol is given" do
+ @f.rb_gc_latest_gc_info(:state).should be_kind_of(Symbol)
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/globals_spec.rb b/spec/ruby/optional/capi/globals_spec.rb
index 84694b1375..cc6f6ef3a8 100644
--- a/spec/ruby/optional/capi/globals_spec.rb
+++ b/spec/ruby/optional/capi/globals_spec.rb
@@ -53,13 +53,32 @@ describe "CApiGlobalSpecs" do
$hooked_gvar.should == 4
end
+ describe "rb_fs" do
+ before :each do
+ @field_separator = $;
+ end
+
+ after :each do
+ suppress_warning { $; = @field_separator }
+ end
+
+ it "returns nil by default" do
+ @f.rb_fs.should == nil
+ end
+
+ it "returns the value of $;" do
+ suppress_warning { $; = "foo" }
+ @f.rb_fs.should == "foo"
+ end
+ end
+
describe "rb_rs" do
before :each do
@dollar_slash = $/
end
after :each do
- $/ = @dollar_slash
+ suppress_warning { $/ = @dollar_slash }
end
it "returns \\n by default" do
@@ -67,7 +86,7 @@ describe "CApiGlobalSpecs" do
end
it "returns the value of $/" do
- $/ = "foo"
+ suppress_warning { $/ = "foo" }
@f.rb_rs.should == "foo"
end
end
@@ -121,7 +140,7 @@ describe "CApiGlobalSpecs" do
$stdout = STDOUT
end
- it "returns $stdout" do
+ it "is an alias of rb_stdout" do
$stdout = @stream
@f.rb_defout.should equal($stdout)
end
@@ -140,7 +159,7 @@ describe "CApiGlobalSpecs" do
end
after :each do
- $\ = @dollar_backslash
+ suppress_warning {$\ = @dollar_backslash}
end
it "returns nil by default" do
@@ -148,7 +167,7 @@ describe "CApiGlobalSpecs" do
end
it "returns the value of $\\" do
- $\ = "foo"
+ suppress_warning {$\ = "foo"}
@f.rb_output_rs.should == "foo"
end
end
diff --git a/spec/ruby/optional/capi/hash_spec.rb b/spec/ruby/optional/capi/hash_spec.rb
index 2923faf7de..75f1978585 100644
--- a/spec/ruby/optional/capi/hash_spec.rb
+++ b/spec/ruby/optional/capi/hash_spec.rb
@@ -50,6 +50,14 @@ describe "C-API Hash function" do
end
end
+ describe "rb_ident_hash_new" do
+ it "returns a new compare by identity hash" do
+ result = @s.rb_ident_hash_new
+ result.should == {}
+ result.compare_by_identity?.should == true
+ end
+ end
+
describe "rb_hash_dup" do
it "returns a copy of the hash" do
hsh = {}
@@ -254,4 +262,13 @@ describe "C-API Hash function" do
-> { @s.rb_Hash(h) }.should raise_error(TypeError)
end
end
+
+ describe "hash code functions" do
+ it "computes a deterministic number" do
+ hash_code = @s.compute_a_hash_code(53)
+ hash_code.should be_an_instance_of(Integer)
+ hash_code.should == @s.compute_a_hash_code(53)
+ @s.compute_a_hash_code(90).should == @s.compute_a_hash_code(90)
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/integer_spec.rb b/spec/ruby/optional/capi/integer_spec.rb
index 56f7ca3034..e26735824e 100644
--- a/spec/ruby/optional/capi/integer_spec.rb
+++ b/spec/ruby/optional/capi/integer_spec.rb
@@ -272,4 +272,19 @@ describe "CApiIntegerSpecs" do
end
end
end
+
+ describe "rb_int_positive_pow" do
+ it "raises an integer to given power" do
+ @s.rb_int_positive_pow(2, 3).should == 8
+ end
+
+ it "raises a negative integer to given power" do
+ @s.rb_int_positive_pow(-2, 3).should == -8
+ @s.rb_int_positive_pow(-2, 4).should == 16
+ end
+
+ it "overflows for large inputs" do
+ @s.rb_int_positive_pow(8, 23).should == 590295810358705651712
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/io_spec.rb b/spec/ruby/optional/capi/io_spec.rb
index 4d61fc8755..c3c1189a43 100644
--- a/spec/ruby/optional/capi/io_spec.rb
+++ b/spec/ruby/optional/capi/io_spec.rb
@@ -151,6 +151,16 @@ describe "C-API IO function" do
end
end
+ describe "rb_io_set_nonblock" do
+ platform_is_not :windows do
+ it "returns true when nonblock flag is set" do
+ require 'io/nonblock'
+ @o.rb_io_set_nonblock(@io)
+ @io.nonblock?.should be_true
+ end
+ end
+ end
+
# NOTE: unlike the name might suggest in MRI this function checks if an
# object is frozen, *not* if it's tainted.
describe "rb_io_taint_check" do
diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb
index 32cdd3f421..7539e0c01c 100644
--- a/spec/ruby/optional/capi/kernel_spec.rb
+++ b/spec/ruby/optional/capi/kernel_spec.rb
@@ -1,6 +1,6 @@
require_relative 'spec_helper'
-load_extension("kernel")
+kernel_path = load_extension("kernel")
describe "C-API Kernel function" do
before :each do
@@ -9,7 +9,7 @@ describe "C-API Kernel function" do
describe "rb_block_given_p" do
it "returns false if no block is passed" do
- @s.rb_block_given_p.should == false
+ @s.should_not.rb_block_given_p
end
it "returns true if a block is passed" do
@@ -238,6 +238,18 @@ describe "C-API Kernel function" do
end
end
+ describe "rb_yield_values2" do
+ it "yields passed arguments" do
+ ret = nil
+ @s.rb_yield_values2([1, 2]) { |x, y| ret = x + y }
+ ret.should == 3
+ end
+
+ it "returns the result from block evaluation" do
+ @s.rb_yield_values2([1, 2]) { |x, y| x + y }.should == 3
+ end
+ end
+
describe "rb_yield_splat" do
it "yields with passed array's contents" do
ret = nil
@@ -261,28 +273,28 @@ describe "C-API Kernel function" do
describe "rb_protect" do
it "will run a function with an argument" do
proof = [] # Hold proof of work performed after the yield.
- res = @s.rb_protect_yield(7, proof) { |x| x + 1 }
- res.should == 8
+ res = @s.rb_protect_yield(77, proof) { |x| x + 1 }
+ res.should == 78
proof[0].should == 23
end
it "will allow cleanup code to run after break" do
proof = [] # Hold proof of work performed after the yield.
- @s.rb_protect_yield(7, proof) { |x| break }
+ @s.rb_protect_yield(77, proof) { |x| break }
proof[0].should == 23
end
it "will allow cleanup code to run after break with value" do
proof = [] # Hold proof of work performed after the yield.
- res = @s.rb_protect_yield(7, proof) { |x| break x + 1 }
- res.should == 8
+ res = @s.rb_protect_yield(77, proof) { |x| break x + 1 }
+ res.should == 78
proof[0].should == 23
end
it "will allow cleanup code to run after a raise" do
proof = [] # Hold proof of work performed after the yield.
-> do
- @s.rb_protect_yield(7, proof) { |x| raise NameError}
+ @s.rb_protect_yield(77, proof) { |x| raise NameError}
end.should raise_error(NameError)
proof[0].should == 23
end
@@ -290,11 +302,16 @@ 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(7, proof) { |x| raise NameError}
+ @s.rb_protect_yield(77, proof) { |x| raise NameError}
end.should raise_error(NameError)
proof[0].should == 23
proof[1].should == nil
end
+
+ it "accepts NULL as status and returns nil if it failed" do
+ @s.rb_protect_null_status(42) { |x| x + 1 }.should == 43
+ @s.rb_protect_null_status(42) { |x| raise }.should == nil
+ end
end
describe "rb_eval_string_protect" do
@@ -316,47 +333,47 @@ describe "C-API Kernel function" do
describe "rb_rescue" do
before :each do
@proc = -> x { x }
- @raise_proc_returns_sentinel = -> *_ { :raise_proc_executed }
- @raise_proc_returns_arg = -> *a { a }
+ @rescue_proc_returns_sentinel = -> *_ { :rescue_proc_executed }
+ @rescue_proc_returns_arg = -> *a { a }
@arg_error_proc = -> *_ { raise ArgumentError, '' }
@std_error_proc = -> *_ { raise StandardError, '' }
@exc_error_proc = -> *_ { raise Exception, '' }
end
it "executes passed function" do
- @s.rb_rescue(@proc, :no_exc, @raise_proc_returns_arg, :exc).should == :no_exc
+ @s.rb_rescue(@proc, :no_exc, @rescue_proc_returns_arg, :exc).should == :no_exc
end
- it "executes passed 'raise function' if a StandardError exception is raised" do
- @s.rb_rescue(@arg_error_proc, nil, @raise_proc_returns_sentinel, :exc).should == :raise_proc_executed
- @s.rb_rescue(@std_error_proc, nil, @raise_proc_returns_sentinel, :exc).should == :raise_proc_executed
+ it "executes the passed 'rescue function' if a StandardError exception is raised" do
+ @s.rb_rescue(@arg_error_proc, nil, @rescue_proc_returns_sentinel, :exc).should == :rescue_proc_executed
+ @s.rb_rescue(@std_error_proc, nil, @rescue_proc_returns_sentinel, :exc).should == :rescue_proc_executed
end
- it "passes the user supplied argument to the 'raise function' if a StandardError exception is raised" do
- arg1, _ = @s.rb_rescue(@arg_error_proc, nil, @raise_proc_returns_arg, :exc1)
+ it "passes the user supplied argument to the 'rescue function' if a StandardError exception is raised" do
+ arg1, _ = @s.rb_rescue(@arg_error_proc, nil, @rescue_proc_returns_arg, :exc1)
arg1.should == :exc1
- arg2, _ = @s.rb_rescue(@std_error_proc, nil, @raise_proc_returns_arg, :exc2)
+ arg2, _ = @s.rb_rescue(@std_error_proc, nil, @rescue_proc_returns_arg, :exc2)
arg2.should == :exc2
end
- it "passes the raised exception to the 'raise function' if a StandardError exception is raised" do
- _, exc1 = @s.rb_rescue(@arg_error_proc, nil, @raise_proc_returns_arg, :exc)
+ it "passes the raised exception to the 'rescue function' if a StandardError exception is raised" do
+ _, exc1 = @s.rb_rescue(@arg_error_proc, nil, @rescue_proc_returns_arg, :exc)
exc1.class.should == ArgumentError
- _, exc2 = @s.rb_rescue(@std_error_proc, nil, @raise_proc_returns_arg, :exc)
+ _, exc2 = @s.rb_rescue(@std_error_proc, nil, @rescue_proc_returns_arg, :exc)
exc2.class.should == StandardError
end
it "raises an exception if passed function raises an exception other than StandardError" do
- -> { @s.rb_rescue(@exc_error_proc, nil, @raise_proc_returns_arg, nil) }.should raise_error(Exception)
+ -> { @s.rb_rescue(@exc_error_proc, nil, @rescue_proc_returns_arg, nil) }.should raise_error(Exception)
end
- it "raises an exception if any exception is raised inside 'raise function'" do
+ it "raises an exception if any exception is raised inside the 'rescue function'" do
-> { @s.rb_rescue(@std_error_proc, nil, @std_error_proc, nil) }.should raise_error(StandardError)
end
- it "makes $! available only during 'raise function' execution" do
+ it "makes $! available only during the 'rescue function' execution" do
@s.rb_rescue(@std_error_proc, nil, -> *_ { $! }, nil).class.should == StandardError
$!.should == nil
end
@@ -368,6 +385,10 @@ describe "C-API Kernel function" do
proc_caller { break :value }.should == :value
end
+
+ it "returns nil if the 'rescue function' is null" do
+ @s.rb_rescue(@std_error_proc, nil, nil, nil).should == nil
+ end
end
describe "rb_rescue2" do
@@ -375,12 +396,20 @@ describe "C-API Kernel function" do
proc = -> x { x }
arg_error_proc = -> *_ { raise ArgumentError, '' }
run_error_proc = -> *_ { raise RuntimeError, '' }
- type_error_proc = -> *_ { raise TypeError, '' }
+ type_error_proc = -> *_ { raise Exception, 'custom error' }
@s.rb_rescue2(arg_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError).should == :exc
@s.rb_rescue2(run_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError).should == :exc
-> {
@s.rb_rescue2(type_error_proc, :no_exc, proc, :exc, ArgumentError, RuntimeError)
- }.should raise_error(TypeError)
+ }.should raise_error(Exception, 'custom error')
+ end
+
+ ruby_bug "#17305", ""..."2.7" do
+ it "raises TypeError if one of the passed exceptions is not a Module" do
+ -> {
+ @s.rb_rescue2(-> *_ { raise RuntimeError, "foo" }, :no_exc, -> x { x }, :exc, Object.new, 42)
+ }.should raise_error(TypeError, /class or module required/)
+ end
end
end
@@ -474,7 +503,7 @@ describe "C-API Kernel function" do
proc = @s.rb_block_proc { 1+1 }
proc.should be_kind_of(Proc)
proc.call.should == 2
- proc.lambda?.should == false
+ proc.should_not.lambda?
end
it "passes through an existing lambda and does not convert to a proc" do
@@ -482,7 +511,7 @@ describe "C-API Kernel function" do
proc = @s.rb_block_proc(&b)
proc.should equal(b)
proc.call.should == 2
- proc.lambda?.should == true
+ proc.should.lambda?
end
end
@@ -491,7 +520,7 @@ describe "C-API Kernel function" do
proc = @s.rb_block_lambda { 1+1 }
proc.should be_kind_of(Proc)
proc.call.should == 2
- proc.lambda?.should == true
+ proc.should.lambda?
end
it "passes through an existing Proc and does not convert to a lambda" do
@@ -499,7 +528,7 @@ describe "C-API Kernel function" do
proc = @s.rb_block_lambda(&b)
proc.should equal(b)
proc.call.should == 2
- proc.lambda?.should == false
+ proc.should_not.lambda?
end
end
@@ -510,25 +539,9 @@ describe "C-API Kernel function" do
end
end
- platform_is_not :windows do
- describe "rb_set_end_proc" do
- before :each do
- @r, @w = IO.pipe
- end
-
- after :each do
- @r.close
- @w.close
- Process.wait @pid
- end
-
- it "runs a C function on shutdown" do
- @pid = fork {
- @s.rb_set_end_proc(@w)
- }
-
- @r.read(1).should == "e"
- end
+ describe "rb_set_end_proc" do
+ it "runs a C function on shutdown" do
+ ruby_exe("require #{kernel_path.inspect}; CApiKernelSpecs.new.rb_set_end_proc(STDOUT)").should == "in write_io"
end
end
@@ -578,6 +591,20 @@ describe "C-API Kernel function" do
end
end
+ describe 'rb_funcall' do
+ before :each do
+ @obj = Object.new
+ class << @obj
+ def many_args(*args)
+ args
+ end
+ end
+ end
+
+ it "can call a public method with 15 arguments" do
+ @s.rb_funcall_many_args(@obj, :many_args).should == 15.downto(1).to_a
+ end
+ end
describe 'rb_funcall_with_block' do
before :each do
@obj = Object.new
diff --git a/spec/ruby/optional/capi/language_spec.rb b/spec/ruby/optional/capi/language_spec.rb
new file mode 100644
index 0000000000..f59b87f2a1
--- /dev/null
+++ b/spec/ruby/optional/capi/language_spec.rb
@@ -0,0 +1,37 @@
+require_relative 'spec_helper'
+
+load_extension("language")
+
+describe "C language construct" do
+ before :each do
+ @s = CApiLanguageSpecs.new
+ end
+
+ describe "switch (VALUE)" do
+ it "works for Qtrue" do
+ @s.switch(true).should == :true
+ end
+
+ it "works for Qfalse" do
+ @s.switch(false).should == :false
+ end
+
+ it "works for Qnil" do
+ @s.switch(nil).should == :nil
+ end
+
+ it "works for Qundef" do
+ @s.switch(:undef).should == :undef
+ end
+
+ it "works for the default case" do
+ @s.switch(Object.new).should == :default
+ end
+ end
+
+ describe "local variable assignment with the same name as a global" do
+ it "works for rb_mProcess" do
+ @s.global_local_var.should.equal?(Process)
+ end
+ end
+end
diff --git a/spec/ruby/optional/capi/module_spec.rb b/spec/ruby/optional/capi/module_spec.rb
index bf09e9d8a5..fde86d2223 100644
--- a/spec/ruby/optional/capi/module_spec.rb
+++ b/spec/ruby/optional/capi/module_spec.rb
@@ -135,7 +135,7 @@ describe "CApiModule" do
end
it "returns a constant defined at toplevel" do
- @m.rb_const_get(CApiModuleSpecs::A, :Fixnum).should == Fixnum
+ @m.rb_const_get(CApiModuleSpecs::A, :Integer).should == Integer
end
it "returns a constant defined in a superclass" do
@@ -176,8 +176,8 @@ describe "CApiModule" do
end
it "calls #const_missing if the constant is not defined in the class or ancestors" do
- CApiModuleSpecs::M.should_receive(:const_missing).with(:Fixnum)
- @m.rb_const_get_from(CApiModuleSpecs::M, :Fixnum)
+ CApiModuleSpecs::M.should_receive(:const_missing).with(:Integer)
+ @m.rb_const_get_from(CApiModuleSpecs::M, :Integer)
end
it "resolves autoload constants" do
@@ -336,12 +336,12 @@ describe "CApiModule" do
@frozen = @class.dup.freeze
end
- it "raises a #{frozen_error_class} when passed a name" do
- -> { @m.rb_undef_method @frozen, "ruby_test_method" }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed a name" do
+ -> { @m.rb_undef_method @frozen, "ruby_test_method" }.should raise_error(FrozenError)
end
- it "raises a #{frozen_error_class} when passed a missing name" do
- -> { @m.rb_undef_method @frozen, "not_exist" }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed a missing name" do
+ -> { @m.rb_undef_method @frozen, "not_exist" }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/optional/capi/numeric_spec.rb b/spec/ruby/optional/capi/numeric_spec.rb
index d76f353850..d433d19274 100644
--- a/spec/ruby/optional/capi/numeric_spec.rb
+++ b/spec/ruby/optional/capi/numeric_spec.rb
@@ -143,6 +143,34 @@ describe "CApiNumericSpecs" do
end
end
+ describe "NUM2SHORT" do
+ it "raises a TypeError if passed nil" do
+ -> { @s.NUM2SHORT(nil) }.should raise_error(TypeError)
+ end
+
+ it "converts a Float" do
+ @s.NUM2SHORT(4.2).should == 4
+ end
+
+ it "converts a Fixnum" do
+ @s.NUM2SHORT(5).should == 5
+ end
+
+ it "converts -1 to an signed number" do
+ @s.NUM2SHORT(-1).should == -1
+ end
+
+ it "raises a RangeError if the value is more than 32bits" do
+ -> { @s.NUM2SHORT(0xffff_ffff+1) }.should raise_error(RangeError)
+ end
+
+ it "calls #to_int to coerce the value" do
+ obj = mock("number")
+ obj.should_receive(:to_int).and_return(2)
+ @s.NUM2SHORT(obj).should == 2
+ end
+ end
+
describe "INT2NUM" do
it "raises a TypeError if passed nil" do
-> { @s.INT2NUM(nil) }.should raise_error(TypeError)
@@ -409,23 +437,12 @@ describe "CApiNumericSpecs" do
@s.rb_num_coerce_cmp(2, obj, :<=>).should == -1
end
- ruby_version_is ""..."2.5" do
- it "returns nil if passed nil" do
- -> {
- @result = @s.rb_num_coerce_cmp(nil, 2, :<=>)
- }.should complain(/comparison operators will no more rescue exceptions/)
- @result.should be_nil
- end
- end
-
- ruby_version_is "2.5" do
- it "lets the exception go through if #coerce raises an exception" do
- obj = mock("rb_num_coerce_cmp")
- obj.should_receive(:coerce).with(2).and_raise(RuntimeError.new("my error"))
- -> {
- @s.rb_num_coerce_cmp(2, obj, :<=>)
- }.should raise_error(RuntimeError, "my error")
- end
+ it "lets the exception go through if #coerce raises an exception" do
+ obj = mock("rb_num_coerce_cmp")
+ obj.should_receive(:coerce).with(2).and_raise(RuntimeError.new("my error"))
+ -> {
+ @s.rb_num_coerce_cmp(2, obj, :<=>)
+ }.should raise_error(RuntimeError, "my error")
end
it "returns nil if #coerce does not return an Array" do
diff --git a/spec/ruby/optional/capi/object_spec.rb b/spec/ruby/optional/capi/object_spec.rb
index 30abe715e7..e8e905b237 100644
--- a/spec/ruby/optional/capi/object_spec.rb
+++ b/spec/ruby/optional/capi/object_spec.rb
@@ -110,6 +110,11 @@ describe "CApiObject" do
@o.rb_respond_to(ObjectTest.new, :foo).should == true
@o.rb_respond_to(ObjectTest.new, :bar).should == false
end
+
+ it "can be used with primitives" do
+ @o.rb_respond_to(true, :object_id).should == true
+ @o.rb_respond_to(14, :succ).should == true
+ end
end
describe "rb_obj_respond_to" do
@@ -313,8 +318,8 @@ describe "CApiObject" do
it "does not rescue exceptions raised by #to_ary" do
obj = mock("to_ary")
- obj.should_receive(:to_ary).and_raise(frozen_error_class)
- -> { @o.rb_check_array_type obj }.should raise_error(frozen_error_class)
+ obj.should_receive(:to_ary).and_raise(FrozenError)
+ -> { @o.rb_check_array_type obj }.should raise_error(FrozenError)
end
end
@@ -670,20 +675,20 @@ describe "CApiObject" do
ruby_version_is ''...'2.7' do
it "marks the object passed as tainted" do
obj = ""
- obj.tainted?.should == false
+ obj.should_not.tainted?
@o.rb_obj_taint(obj)
- obj.tainted?.should == true
+ obj.should.tainted?
end
- it "raises a #{frozen_error_class} if the object passed is frozen" do
- -> { @o.rb_obj_taint("".freeze) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if the object passed is frozen" do
+ -> { @o.rb_obj_taint("".freeze) }.should raise_error(FrozenError)
end
end
end
describe "rb_check_frozen" do
- it "raises a #{frozen_error_class} if the obj is frozen" do
- -> { @o.rb_check_frozen("".freeze) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError if the obj is frozen" do
+ -> { @o.rb_check_frozen("".freeze) }.should raise_error(FrozenError)
end
it "does nothing when object isn't frozen" do
@@ -815,6 +820,15 @@ describe "CApiObject" do
end
end
+ describe "rb_ivar_count" do
+ it "returns the number of instance variables" do
+ obj = Object.new
+ @o.rb_ivar_count(obj).should == 0
+ obj.instance_variable_set(:@foo, 42)
+ @o.rb_ivar_count(obj).should == 1
+ end
+ end
+
describe "rb_ivar_get" do
it "returns the instance variable on an object" do
@o.rb_ivar_get(@test, :@foo).should == @test.instance_eval { @foo }
@@ -826,6 +840,7 @@ describe "CApiObject" do
it "returns nil if the instance variable has not been initialized and is not a valid Ruby name" do
@o.rb_ivar_get(@test, :bar).should == nil
+ @o.rb_ivar_get(@test, :mesg).should == nil
end
it 'returns the instance variable when it is not a valid Ruby name' do
@@ -861,6 +876,7 @@ describe "CApiObject" do
it "does not throw an error if the instance variable is not a valid Ruby name" do
@o.rb_ivar_defined(@test, :bar).should == false
+ @o.rb_ivar_defined(@test, :mesg).should == false
end
end
@@ -887,4 +903,78 @@ describe "CApiObject" do
end
end
end
+
+ describe "allocator accessors" do
+ describe "rb_define_alloc_func" do
+ it "sets up the allocator" do
+ klass = Class.new
+ @o.rb_define_alloc_func(klass)
+ obj = klass.allocate
+ obj.class.should.equal?(klass)
+ obj.should have_instance_variable(:@from_custom_allocator)
+ end
+
+ it "sets up the allocator for a subclass of String" do
+ klass = Class.new(String)
+ @o.rb_define_alloc_func(klass)
+ obj = klass.allocate
+ obj.class.should.equal?(klass)
+ obj.should have_instance_variable(:@from_custom_allocator)
+ obj.should == ""
+ end
+
+ it "sets up the allocator for a subclass of Array" do
+ klass = Class.new(Array)
+ @o.rb_define_alloc_func(klass)
+ obj = klass.allocate
+ obj.class.should.equal?(klass)
+ obj.should have_instance_variable(:@from_custom_allocator)
+ obj.should == []
+ end
+ end
+
+ describe "rb_get_alloc_func" do
+ it "gets the allocator that is defined directly on a class" do
+ klass = Class.new
+ @o.rb_define_alloc_func(klass)
+ @o.speced_allocator?(Object).should == false
+ @o.speced_allocator?(klass).should == true
+ end
+
+ it "gets the allocator that is inherited" do
+ parent = Class.new
+ @o.rb_define_alloc_func(parent)
+ klass = Class.new(parent)
+ @o.speced_allocator?(Object).should == false
+ @o.speced_allocator?(klass).should == true
+ end
+ end
+
+ describe "rb_undef_alloc_func" do
+ it "makes rb_get_alloc_func() return NULL for a class without a custom allocator" do
+ klass = Class.new
+ @o.rb_undef_alloc_func(klass)
+ @o.custom_alloc_func?(klass).should == false
+ end
+
+ it "undefs the allocator for the class" do
+ klass = Class.new
+ @o.rb_define_alloc_func(klass)
+ @o.speced_allocator?(klass).should == true
+ @o.rb_undef_alloc_func(klass)
+ @o.custom_alloc_func?(klass).should == false
+ end
+
+ it "undefs the allocator for a class that inherits a allocator" do
+ parent = Class.new
+ @o.rb_define_alloc_func(parent)
+ klass = Class.new(parent)
+ @o.speced_allocator?(klass).should == true
+ @o.rb_undef_alloc_func(klass)
+ @o.custom_alloc_func?(klass).should == false
+
+ @o.speced_allocator?(parent).should == true
+ end
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/proc_spec.rb b/spec/ruby/optional/capi/proc_spec.rb
index 9f9a37cc98..ff119416f6 100644
--- a/spec/ruby/optional/capi/proc_spec.rb
+++ b/spec/ruby/optional/capi/proc_spec.rb
@@ -54,6 +54,25 @@ describe "C-API Proc function" do
@p.rb_proc_call(prc, [6, 7]).should == 42
end
end
+
+ describe "rb_obj_is_proc" do
+ it "returns true for Proc" do
+ prc = Proc.new {|a,b| a * b }
+ @p.rb_obj_is_proc(prc).should be_true
+ end
+
+ it "returns true for subclass of Proc" do
+ prc = Class.new(Proc).new {}
+ @p.rb_obj_is_proc(prc).should be_true
+ end
+
+ it "returns false for non Proc instances" do
+ @p.rb_obj_is_proc("aoeui").should be_false
+ @p.rb_obj_is_proc(123).should be_false
+ @p.rb_obj_is_proc(true).should be_false
+ @p.rb_obj_is_proc([]).should be_false
+ end
+ end
end
describe "C-API when calling Proc.new from a C function" do
diff --git a/spec/ruby/optional/capi/rbasic_spec.rb b/spec/ruby/optional/capi/rbasic_spec.rb
new file mode 100644
index 0000000000..283e70db70
--- /dev/null
+++ b/spec/ruby/optional/capi/rbasic_spec.rb
@@ -0,0 +1,22 @@
+require_relative 'spec_helper'
+require_relative 'shared/rbasic'
+load_extension("rbasic")
+load_extension("data")
+load_extension("array")
+
+describe "RBasic support for regular objects" do
+ before :all do
+ @specs = CApiRBasicSpecs.new
+ @data = -> { [Object.new, Object.new] }
+ end
+ it_should_behave_like :rbasic
+end
+
+describe "RBasic support for RData" do
+ before :all do
+ @specs = CApiRBasicRDataSpecs.new
+ @wrapping = CApiWrappedStructSpecs.new
+ @data = -> { [@wrapping.wrap_struct(1024), @wrapping.wrap_struct(1025)] }
+ end
+ it_should_behave_like :rbasic
+end
diff --git a/spec/ruby/optional/capi/regexp_spec.rb b/spec/ruby/optional/capi/regexp_spec.rb
index 52aae6bb01..806157368d 100644
--- a/spec/ruby/optional/capi/regexp_spec.rb
+++ b/spec/ruby/optional/capi/regexp_spec.rb
@@ -9,12 +9,20 @@ describe "C-API Regexp function" do
describe "rb_reg_new" do
it "returns a new valid Regexp" do
- my_re = @p.a_re
+ my_re = @p.a_re("a", 0)
my_re.kind_of?(Regexp).should == true
('1a' =~ my_re).should == 1
('1b' =~ my_re).should == nil
my_re.source.should == 'a'
end
+
+ it "returns a Regexp with the given options" do
+ @p.a_re("a", 0).options == 0
+ @p.a_re("a", Regexp::IGNORECASE).options.should == Regexp::IGNORECASE
+ @p.a_re("a", Regexp::EXTENDED).options.should == Regexp::EXTENDED
+ @p.a_re("a", Regexp::EXTENDED | Regexp::IGNORECASE).options.should == Regexp::EXTENDED | Regexp::IGNORECASE
+ @p.a_re("a", Regexp::MULTILINE).options.should == Regexp::MULTILINE
+ end
end
describe "rb_reg_nth_match" do
@@ -67,5 +75,9 @@ describe "C-API Regexp function" do
md = /c/.match('ab')
@p.rb_backref_get.should == md
end
+
+ it "returns MatchData when used with rb_reg_match" do
+ @p.rb_reg_match_backref_get(/a/, 'ab')[0].should == 'a'
+ end
end
end
diff --git a/spec/ruby/optional/capi/shared/rbasic.rb b/spec/ruby/optional/capi/shared/rbasic.rb
new file mode 100644
index 0000000000..f202b72f33
--- /dev/null
+++ b/spec/ruby/optional/capi/shared/rbasic.rb
@@ -0,0 +1,83 @@
+describe :rbasic, shared: true do
+
+ before :all do
+ specs = CApiRBasicSpecs.new
+ @taint = specs.taint_flag
+ @freeze = specs.freeze_flag
+ end
+
+ it "reports the appropriate FREEZE flag for the object when reading" do
+ obj, _ = @data.call
+ initial = @specs.get_flags(obj)
+ obj.freeze
+ @specs.get_flags(obj).should == @freeze | initial
+ end
+
+ it "supports setting the FREEZE flag" do
+ obj, _ = @data.call
+ initial = @specs.get_flags(obj)
+ @specs.set_flags(obj, @freeze | initial).should == @freeze | initial
+ obj.should.frozen?
+ end
+
+ ruby_version_is ""..."2.7" do
+ it "reports the appropriate FREEZE and TAINT flags for the object when reading" do
+ obj, _ = @data.call
+ initial = @specs.get_flags(obj)
+ obj.taint
+ @specs.get_flags(obj).should == @taint | initial
+ obj.untaint
+ @specs.get_flags(obj).should == initial
+ obj.freeze
+ @specs.get_flags(obj).should == @freeze | initial
+
+ obj, _ = @data.call
+ obj.taint
+ obj.freeze
+ @specs.get_flags(obj).should == @freeze | @taint | initial
+ end
+
+ it "supports setting the FREEZE and TAINT flags" do
+ obj, _ = @data.call
+ initial = @specs.get_flags(obj)
+ @specs.set_flags(obj, @taint | initial).should == @taint | initial
+ obj.should.tainted?
+ @specs.set_flags(obj, initial).should == initial
+ obj.should_not.tainted?
+ @specs.set_flags(obj, @freeze | initial).should == @freeze | initial
+ obj.should.frozen?
+
+ obj, _ = @data.call
+ @specs.set_flags(obj, @freeze | @taint | initial).should == @freeze | @taint | initial
+ obj.should.tainted?
+ obj.should.frozen?
+ end
+ end
+
+ it "supports user flags" do
+ obj, _ = @data.call
+ initial = @specs.get_flags(obj)
+ @specs.set_flags(obj, 1 << 14 | 1 << 16 | initial).should == 1 << 14 | 1 << 16 | initial
+ @specs.get_flags(obj).should == 1 << 14 | 1 << 16 | initial
+ @specs.set_flags(obj, initial).should == initial
+ end
+
+ it "supports copying the flags from one object over to the other" do
+ obj1, obj2 = @data.call
+ initial = @specs.get_flags(obj1)
+ @specs.get_flags(obj2).should == initial
+ @specs.set_flags(obj1, 1 << 14 | 1 << 16 | initial)
+ @specs.copy_flags(obj2, obj1)
+ @specs.get_flags(obj2).should == 1 << 14 | 1 << 16 | initial
+ @specs.set_flags(obj1, initial)
+ @specs.copy_flags(obj2, obj1)
+ @specs.get_flags(obj2).should == initial
+ end
+
+ it "supports retrieving the (meta)class" do
+ obj, _ = @data.call
+ @specs.get_klass(obj).should == obj.class
+ obj.singleton_class # ensure the singleton class exists
+ @specs.get_klass(obj).should == obj.singleton_class
+ end
+end
diff --git a/spec/ruby/optional/capi/spec_helper.rb b/spec/ruby/optional/capi/spec_helper.rb
index eda4964b69..2c36ead8d0 100644
--- a/spec/ruby/optional/capi/spec_helper.rb
+++ b/spec/ruby/optional/capi/spec_helper.rb
@@ -8,12 +8,17 @@ require 'rbconfig'
OBJDIR ||= File.expand_path("../../../ext/#{RUBY_ENGINE}/#{RUBY_VERSION}", __FILE__)
def object_path
- mkdir_p(OBJDIR)
- OBJDIR
+ path = OBJDIR
+ if ENV['SPEC_CAPI_CXX'] == 'true'
+ path = "#{path}/cxx"
+ end
+ mkdir_p(path)
+ path
end
def compile_extension(name)
debug = false
+ cxx = ENV['SPEC_CAPI_CXX'] == 'true'
run_mkmf_in_process = RUBY_ENGINE == 'truffleruby'
core_ext_dir = File.expand_path("../ext", __FILE__)
@@ -27,11 +32,9 @@ def compile_extension(name)
ruby_header = "#{RbConfig::CONFIG['rubyhdrdir']}/ruby.h"
if RbConfig::CONFIG["ENABLE_SHARED"] == "yes"
- if PlatformGuard.windows?
- libruby_so = "#{RbConfig::CONFIG['bindir']}/#{RbConfig::CONFIG['LIBRUBY_SO']}"
- else
- libruby_so = "#{RbConfig::CONFIG['libdir']}/#{RbConfig::CONFIG['LIBRUBY_SO']}"
- end
+ libdirname = RbConfig::CONFIG['LIBPATHENV'] == 'PATH' ? 'bindir' :
+ RbConfig::CONFIG['libdirname'] # defined since 2.1
+ libruby_so = "#{RbConfig::CONFIG[libdirname]}/#{RbConfig::CONFIG['LIBRUBY_SO']}"
end
begin
@@ -54,7 +57,11 @@ def compile_extension(name)
Dir.mkdir(tmpdir)
begin
["#{core_ext_dir}/rubyspec.h", "#{spec_ext_dir}/#{ext}.c"].each do |file|
- cp file, "#{tmpdir}/#{File.basename(file)}"
+ if cxx and file.end_with?('.c')
+ cp file, "#{tmpdir}/#{File.basename(file, '.c')}.cpp"
+ else
+ cp file, "#{tmpdir}/#{File.basename(file)}"
+ end
end
Dir.chdir(tmpdir) do
@@ -64,11 +71,14 @@ def compile_extension(name)
init_mkmf unless required
create_makefile(ext, tmpdir)
else
- File.write("extconf.rb", "require 'mkmf'\n" +
- "$ruby = ENV.values_at('RUBY_EXE', 'RUBY_FLAGS').join(' ')\n" +
+ File.write("extconf.rb", <<-RUBY)
+ require 'mkmf'
+ $ruby = ENV.values_at('RUBY_EXE', 'RUBY_FLAGS').join(' ')
# MRI magic to consider building non-bundled extensions
- "$extout = nil\n" +
- "create_makefile(#{ext.inspect})\n")
+ $extout = nil
+ append_cflags '-Wno-declaration-after-statement'
+ create_makefile(#{ext.inspect})
+ RUBY
output = ruby_exe("extconf.rb")
raise "extconf failed:\n#{output}" unless $?.success?
$stderr.puts output if debug
@@ -116,7 +126,9 @@ def setup_make
end
def load_extension(name)
- require compile_extension(name)
+ ext_path = compile_extension(name)
+ require ext_path
+ ext_path
rescue LoadError => e
if %r{/usr/sbin/execerror ruby "\(ld 3 1 main ([/a-zA-Z0-9_\-.]+_spec\.so)"} =~ e.message
system('/usr/sbin/execerror', "#{RbConfig::CONFIG["bindir"]}/ruby", "(ld 3 1 main #{$1}")
diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb
index 1ad35b9e8a..7c33b79348 100644
--- a/spec/ruby/optional/capi/string_spec.rb
+++ b/spec/ruby/optional/capi/string_spec.rb
@@ -76,7 +76,7 @@ describe "C-API String function" do
it "invalidates the code range" do
@s.rb_str_set_len(@str, 4)
- @str.ascii_only?.should == true
+ @str.should.ascii_only?
end
it "updates the string's attributes visible in C code" do
@@ -158,6 +158,20 @@ describe "C-API String function" do
end
end
+ describe "rb_str_tmp_new" do
+ it "returns a hidden string (RBasic->klass is NULL)" do
+ @s.rb_str_tmp_new_klass(4).should == false
+ end
+
+ it "returns a new String object filled with \\0 bytes" do
+ s = @s.rb_str_tmp_new(4)
+ s.encoding.should == Encoding::BINARY
+ s.bytesize.should == 4
+ s.size.should == 4
+ s.should == "\x00\x00\x00\x00"
+ end
+ end
+
describe "rb_str_new" do
it "creates a new String with BINARY Encoding" do
@s.rb_str_new("", 0).encoding.should == Encoding::BINARY
@@ -169,7 +183,7 @@ describe "C-API String function" do
ruby_version_is ''...'2.7' do
it "returns a non-tainted string" do
- @s.rb_str_new("hello", 5).tainted?.should == false
+ @s.rb_str_new("hello", 5).should_not.tainted?
end
end
@@ -204,6 +218,20 @@ describe "C-API String function" do
end
end
+ describe "rb_usascii_str_new_lit" do
+ it "returns a US-ASCII string of the correct characters" do
+ str = @s.rb_usascii_str_new_lit
+ str.should == "nokogiri"
+ str.encoding.should == Encoding::US_ASCII
+ end
+
+ it "returns US-ASCII string for non-US-ASCII string literal" do
+ str = @s.rb_usascii_str_new_lit_non_ascii
+ str.should == "r\xC3\xA9sum\xC3\xA9".force_encoding(Encoding::US_ASCII)
+ str.encoding.should == Encoding::US_ASCII
+ end
+ end
+
describe "rb_usascii_str_new_cstr" do
it "creates a new String with US-ASCII Encoding" do
str = "abc".force_encoding("us-ascii")
@@ -274,8 +302,8 @@ describe "C-API String function" do
str2 = @s.rb_str_new4 str1
str1.should == str2
str1.should equal(str2)
- str1.frozen?.should == true
- str2.frozen?.should == true
+ str1.should.frozen?
+ str2.should.frozen?
end
it "returns a frozen copy of the string" do
@@ -283,7 +311,7 @@ describe "C-API String function" do
str2 = @s.rb_str_new4 str1
str1.should == str2
str1.should_not equal(str2)
- str2.frozen?.should == true
+ str2.should.frozen?
end
end
@@ -368,6 +396,26 @@ describe "C-API String function" do
end
end
+ describe "rb_str_cat_cstr" do
+ it "concatenates a C string literal to a ruby string" do
+ @s.rb_str_cat_cstr_constant("Your house is on fire").should == "Your house is on fire?"
+ end
+
+ it "concatenates a variable C string to a ruby string" do
+ @s.rb_str_cat_cstr("Your house is on fire", "?").should == "Your house is on fire?"
+ end
+ end
+
+ describe "rb_enc_str_buf_cat" do
+ it "concatenates a C string literal to a ruby string with the given encoding" do
+ input = "hello ".force_encoding(Encoding::US_ASCII)
+ result = @s.rb_enc_str_buf_cat(input, "résumé", Encoding::UTF_8)
+ result.should == "hello résumé"
+ result.encoding.should == Encoding::UTF_8
+ result.object_id.should == input.object_id
+ end
+ end
+
describe "rb_str_cmp" do
it "returns 0 if two strings are identical" do
@s.rb_str_cmp("ppp", "ppp").should == 0
@@ -440,6 +488,25 @@ describe "C-API String function" do
end
end
+ describe "rb_fstring" do
+ it 'returns self if the String is frozen' do
+ input = 'foo'.freeze
+ output = @s.rb_fstring(input)
+
+ output.should equal(input)
+ output.should.frozen?
+ end
+
+ it 'returns a frozen copy if the String is not frozen' do
+ input = 'foo'
+ output = @s.rb_fstring(input)
+
+ output.should.frozen?
+ output.should_not equal(input)
+ output.should == 'foo'
+ end
+ end
+
describe "rb_str_subseq" do
it "returns a byte-indexed substring" do
str = "\x00\x01\x02\x03\x04".force_encoding("binary")
@@ -513,6 +580,24 @@ describe "C-API String function" do
end
chars.should == [55, 48, 227, 131, 145, 227, 130, 175]
end
+
+ it "returns a pointer which can be cast and used as another type" do
+ s = "70パク".
+ encode(Encoding::UTF_16LE).
+ force_encoding(Encoding::UTF_16LE).
+ encode(Encoding::UTF_8)
+
+ ints = []
+ @s.RSTRING_PTR_iterate_uint32(s) do |i|
+ ints << i
+ end
+ ints.should == s.unpack('LL')
+ end
+
+ it "allows a short memcpy to the string which may be converted to a single write operation by the compiler" do
+ str = " "
+ @s.RSTRING_PTR_short_memcpy(str).should == "Infinity"
+ end
end
describe "RSTRING_LEN" do
diff --git a/spec/ruby/optional/capi/struct_spec.rb b/spec/ruby/optional/capi/struct_spec.rb
index 6254b098a9..0e9e366908 100644
--- a/spec/ruby/optional/capi/struct_spec.rb
+++ b/spec/ruby/optional/capi/struct_spec.rb
@@ -62,7 +62,7 @@ describe "C-API Struct function" do
end
describe "C-API Struct function" do
- before :each do
+ before :all do
@s = CApiStructSpecs.new
@struct = @s.rb_struct_define_under(CApiStructSpecs, "CAPIStructUnder", "a", "b", "c")
end
@@ -188,9 +188,9 @@ describe "C-API Struct function" do
-> { @s.rb_struct_aset(@struct, 3, 1) }.should raise_error(IndexError)
end
- it "raises a #{frozen_error_class} if the struct is frozen" do
+ it "raises a FrozenError if the struct is frozen" do
@struct.freeze
- -> { @s.rb_struct_aset(@struct, :a, 1) }.should raise_error(frozen_error_class)
+ -> { @s.rb_struct_aset(@struct, :a, 1) }.should raise_error(FrozenError)
end
end
diff --git a/spec/ruby/optional/capi/symbol_spec.rb b/spec/ruby/optional/capi/symbol_spec.rb
index ddc748c8d8..b8fda34c0e 100644
--- a/spec/ruby/optional/capi/symbol_spec.rb
+++ b/spec/ruby/optional/capi/symbol_spec.rb
@@ -8,6 +8,16 @@ describe "C-API Symbol function" do
@s = CApiSymbolSpecs.new
end
+ describe "SYMBOL_P" do
+ it "returns true for a Symbol" do
+ @s.SYMBOL_P(:foo).should == true
+ end
+
+ it "returns false for non-Symbols" do
+ @s.SYMBOL_P('bar').should == false
+ end
+ end
+
describe "rb_intern" do
it "converts a string to a symbol, uniquely" do
@s.rb_intern("test_symbol").should == :test_symbol
@@ -71,6 +81,19 @@ describe "C-API Symbol function" do
end
end
+ describe "rb_check_symbol_cstr" do
+ it "returns a Symbol if a Symbol already exists for the given C string" do
+ sym = :test_symbol
+ @s.rb_check_symbol_cstr('test_symbol').should == sym
+ end
+
+ it "returns nil if the Symbol does not exist yet and does not create it" do
+ str = "symbol_does_not_exist_#{Object.new.object_id}_#{rand}"
+ @s.rb_check_symbol_cstr(str).should == nil # does not create the Symbol
+ @s.rb_check_symbol_cstr(str).should == nil
+ end
+ end
+
describe "rb_is_const_id" do
it "returns true given a const-like symbol" do
@s.rb_is_const_id(:Foo).should == true
@@ -130,4 +153,20 @@ describe "C-API Symbol function" do
@s.rb_sym2str(:bacon).should == "bacon"
end
end
+
+ describe "rb_to_symbol" do
+ it "returns a Symbol for a Symbol" do
+ @s.rb_to_symbol(:foo).should == :foo
+ end
+
+ it "returns a Symbol for a String" do
+ @s.rb_to_symbol("foo").should == :foo
+ end
+
+ it "coerces to Symbol using to_str" do
+ o = mock('o')
+ o.should_receive(:to_str).and_return("foo")
+ @s.rb_to_symbol(o).should == :foo
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/time_spec.rb b/spec/ruby/optional/capi/time_spec.rb
index 2c824bb566..579e81fc19 100644
--- a/spec/ruby/optional/capi/time_spec.rb
+++ b/spec/ruby/optional/capi/time_spec.rb
@@ -165,30 +165,28 @@ describe "CApiTimeSpecs" do
usec.should == 500000
end
- guard -> { platform_is_not :mingw or ruby_version_is '2.5' } do
- it "creates a timeval for a negative Fixnum" do
- sec, usec = @s.rb_time_timeval(-1232141421)
- sec.should be_kind_of(Integer)
- sec.should == -1232141421
- usec.should be_kind_of(Integer)
- usec.should == 0
- end
+ it "creates a timeval for a negative Fixnum" do
+ sec, usec = @s.rb_time_timeval(-1232141421)
+ sec.should be_kind_of(Integer)
+ sec.should == -1232141421
+ usec.should be_kind_of(Integer)
+ usec.should == 0
+ end
- it "creates a timeval for a negative Float" do
- sec, usec = @s.rb_time_timeval(-1.5)
- sec.should be_kind_of(Integer)
- sec.should == -2
- usec.should be_kind_of(Integer)
- usec.should == 500000
- end
+ it "creates a timeval for a negative Float" do
+ sec, usec = @s.rb_time_timeval(-1.5)
+ sec.should be_kind_of(Integer)
+ sec.should == -2
+ usec.should be_kind_of(Integer)
+ usec.should == 500000
+ end
- it "creates a timeval for a negative Rational" do
- sec, usec = @s.rb_time_timeval(Rational(-3, 2))
- sec.should be_kind_of(Integer)
- sec.should == -2
- usec.should be_kind_of(Integer)
- usec.should == 500000
- end
+ it "creates a timeval for a negative Rational" do
+ sec, usec = @s.rb_time_timeval(Rational(-3, 2))
+ sec.should be_kind_of(Integer)
+ sec.should == -2
+ usec.should be_kind_of(Integer)
+ usec.should == 500000
end
it "creates a timeval from a Time object" do
@@ -224,30 +222,28 @@ describe "CApiTimeSpecs" do
nsec.should == 500000000
end
- guard -> { platform_is_not :mingw or ruby_version_is '2.5' } do
- it "creates a timespec for a negative Fixnum" do
- sec, nsec = @s.rb_time_timespec(-1232141421)
- sec.should be_kind_of(Integer)
- sec.should == -1232141421
- nsec.should be_kind_of(Integer)
- nsec.should == 0
- end
+ it "creates a timespec for a negative Fixnum" do
+ sec, nsec = @s.rb_time_timespec(-1232141421)
+ sec.should be_kind_of(Integer)
+ sec.should == -1232141421
+ nsec.should be_kind_of(Integer)
+ nsec.should == 0
+ end
- it "creates a timespec for a negative Float" do
- sec, nsec = @s.rb_time_timespec(-1.5)
- sec.should be_kind_of(Integer)
- sec.should == -2
- nsec.should be_kind_of(Integer)
- nsec.should == 500000000
- end
+ it "creates a timespec for a negative Float" do
+ sec, nsec = @s.rb_time_timespec(-1.5)
+ sec.should be_kind_of(Integer)
+ sec.should == -2
+ nsec.should be_kind_of(Integer)
+ nsec.should == 500000000
+ end
- it "creates a timespec for a negative Rational" do
- sec, nsec = @s.rb_time_timespec(Rational(-3, 2))
- sec.should be_kind_of(Integer)
- sec.should == -2
- nsec.should be_kind_of(Integer)
- nsec.should == 500000000
- end
+ it "creates a timespec for a negative Rational" do
+ sec, nsec = @s.rb_time_timespec(Rational(-3, 2))
+ sec.should be_kind_of(Integer)
+ sec.should == -2
+ nsec.should be_kind_of(Integer)
+ nsec.should == 500000000
end
it "creates a timespec from a Time object" do
diff --git a/spec/ruby/optional/capi/tracepoint_spec.rb b/spec/ruby/optional/capi/tracepoint_spec.rb
new file mode 100644
index 0000000000..2043b7c941
--- /dev/null
+++ b/spec/ruby/optional/capi/tracepoint_spec.rb
@@ -0,0 +1,56 @@
+require_relative 'spec_helper'
+
+load_extension("tracepoint")
+
+describe "CApiTracePointSpecs" do
+ before :each do
+ @s = CApiTracePointSpecs.new
+ end
+
+ after :each do
+ @trace.disable if @trace and @trace.enabled?
+ end
+
+ describe "rb_tracepoint_new" do
+ it "returns a tracepoint object" do
+ @trace = @s.rb_tracepoint_new(7)
+ @trace.should be_an_instance_of(TracePoint)
+ @trace.should_not.enabled?
+ end
+
+ it "traces lines when given RUBY_EVENT_LINE" do
+ @trace = @s.rb_tracepoint_new(8)
+ @trace.enable
+ @s.callback_called?.should == 8
+ end
+ end
+
+ describe "rb_tracepoint_disable" do
+ it "disables an enabled TracePoint" do
+ @trace = @s.rb_tracepoint_new(9)
+ @trace.should_not.enabled?
+ @trace.enable
+ @trace.should.enabled?
+ @s.rb_tracepoint_disable(@trace).should == false
+ @trace.should_not.enabled?
+ end
+ end
+
+ describe "rb_tracepoint_enable" do
+ it "enables a disabled TracePoint" do
+ @trace = @s.rb_tracepoint_new(10)
+ @trace.should_not.enabled?
+ @s.rb_tracepoint_enable(@trace).should == true
+ @trace.should.enabled?
+ end
+ end
+
+ describe "rb_tracepoint_enabled_p" do
+ it "returns correct enabled status" do
+ @trace = @s.rb_tracepoint_new(11)
+ @s.rb_tracepoint_enabled_p(@trace).should == false
+ @trace.enable
+ @s.rb_tracepoint_enabled_p(@trace).should == true
+ end
+ end
+end
diff --git a/spec/ruby/optional/capi/typed_data_spec.rb b/spec/ruby/optional/capi/typed_data_spec.rb
index da56a050fd..9ccfa562d1 100644
--- a/spec/ruby/optional/capi/typed_data_spec.rb
+++ b/spec/ruby/optional/capi/typed_data_spec.rb
@@ -57,4 +57,21 @@ describe "CApiWrappedTypedStruct" do
@s.typed_get_struct_data_ptr(a).should == 1024
end
end
+
+ describe "rb_check_typeddata" do
+ it "returns data pointer when the struct has the given type" do
+ a = @s.typed_wrap_struct(1024)
+ @s.rb_check_typeddata_same_type(a).should == true
+ end
+
+ it "returns data pointer when the parent struct has the given type" do
+ a = @s.typed_wrap_struct(1024)
+ @s.rb_check_typeddata_same_type_parent(a).should == true
+ end
+
+ it "raises an error for different types" do
+ a = @s.typed_wrap_struct(1024)
+ -> { @s.rb_check_typeddata_different_type(a) }.should raise_error(TypeError)
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/util_spec.rb b/spec/ruby/optional/capi/util_spec.rb
index 3556c8c010..0251c7c62b 100644
--- a/spec/ruby/optional/capi/util_spec.rb
+++ b/spec/ruby/optional/capi/util_spec.rb
@@ -115,11 +115,22 @@ describe "C-API Util function" do
ScratchPad.recorded.should == [1, nil]
end
- it "assigns required and Hash arguments with nil Hash" do
- suppress_warning do
- @o.rb_scan_args([1, nil], "1:", 2, @acc).should == 1
+ ruby_version_is ''...'3.0' do
+ it "assigns required and Hash arguments with nil Hash" do
+ suppress_warning do
+ @o.rb_scan_args([1, nil], "1:", 2, @acc).should == 1
+ end
+ ScratchPad.recorded.should == [1, nil]
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "rejects the use of nil as a hash" do
+ -> {
+ @o.rb_scan_args([1, nil], "1:", 2, @acc).should == 1
+ }.should raise_error(ArgumentError)
+ ScratchPad.recorded.should == []
end
- ScratchPad.recorded.should == [1, nil]
end
it "assigns required and optional arguments with no hash argument given" do
@@ -133,33 +144,55 @@ describe "C-API Util function" do
ScratchPad.recorded.should == [1, 2, [3, 4], 5, h, @prc]
end
- # r43934
- it "rejects non-keyword arguments" do
- h = {1 => 2, 3 => 4}
- -> {
- suppress_warning do
- @o.rb_scan_args([h], "#{@keyword_prefix}0:", 1, @acc)
- end
- }.should raise_error(ArgumentError)
- ScratchPad.recorded.should == []
- end
+ ruby_version_is ''...'3.0' do
+ # r43934
+ it "rejects non-keyword arguments" do
+ h = {1 => 2, 3 => 4}
+ -> {
+ suppress_warning do
+ @o.rb_scan_args([h], "#{@keyword_prefix}0:", 1, @acc)
+ end
+ }.should raise_error(ArgumentError)
+ ScratchPad.recorded.should == []
+ end
- it "rejects required and non-keyword arguments" do
- h = {1 => 2, 3 => 4}
- -> {
+ it "rejects required and non-keyword arguments" do
+ h = {1 => 2, 3 => 4}
+ -> {
+ suppress_warning do
+ @o.rb_scan_args([1, h], "#{@keyword_prefix}1:", 2, @acc)
+ end
+ }.should raise_error(ArgumentError)
+ ScratchPad.recorded.should == []
+ end
+
+ it "considers the hash as a post argument when there is a splat" do
+ h = {1 => 2, 3 => 4}
suppress_warning do
- @o.rb_scan_args([1, h], "#{@keyword_prefix}1:", 2, @acc)
+ @o.rb_scan_args([1, 2, 3, 4, 5, h], "#{@keyword_prefix}11*1:&", 6, @acc, &@prc).should == 6
end
- }.should raise_error(ArgumentError)
- ScratchPad.recorded.should == []
+ ScratchPad.recorded.should == [1, 2, [3, 4, 5], h, nil, @prc]
+ end
end
- it "considers the hash as a post argument when there is a splat" do
- h = {1 => 2, 3 => 4}
- suppress_warning do
- @o.rb_scan_args([1, 2, 3, 4, 5, h], "#{@keyword_prefix}11*1:&", 6, @acc, &@prc).should == 6
+ ruby_version_is '3.0' do
+ it "does not reject non-symbol keys in keyword arguments" do
+ h = {1 => 2, 3 => 4}
+ @o.rb_scan_args([h], "#{@keyword_prefix}0:", 1, @acc).should == 0
+ ScratchPad.recorded.should == [h]
+ end
+
+ it "does not reject non-symbol keys in keyword arguments with required argument" do
+ h = {1 => 2, 3 => 4}
+ @o.rb_scan_args([1, h], "#{@keyword_prefix}1:", 2, @acc).should == 1
+ ScratchPad.recorded.should == [1, h]
+ end
+
+ it "considers keyword arguments with non-symbol keys as keywords when using splat and post arguments" do
+ h = {1 => 2, 3 => 4}
+ @o.rb_scan_args([1, 2, 3, 4, 5, h], "#{@keyword_prefix}11*1:&", 6, @acc, &@prc).should == 5
+ ScratchPad.recorded.should == [1, 2, [3, 4], 5, h, @prc]
end
- ScratchPad.recorded.should == [1, 2, [3, 4, 5], h, nil, @prc]
end
end
@@ -260,4 +293,34 @@ describe "C-API Util function" do
end
end
+ # ruby/util.h redefines strtod as a macro calling ruby_strtod
+
+ describe "strtod" do
+ it "converts a string to a double and returns the remaining string" do
+ d, s = @o.strtod("14.25test")
+ d.should == 14.25
+ s.should == "test"
+ end
+
+ it "returns 0 and the full string if there's no numerical value" do
+ d, s = @o.strtod("test")
+ d.should == 0
+ s.should == "test"
+ end
+ end
+
+ describe "ruby_strtod" do
+ it "converts a string to a double and returns the remaining string" do
+ d, s = @o.ruby_strtod("14.25test")
+ d.should == 14.25
+ s.should == "test"
+ end
+
+ it "returns 0 and the full string if there's no numerical value" do
+ d, s = @o.ruby_strtod("test")
+ d.should == 0
+ s.should == "test"
+ end
+ end
+
end
diff --git a/spec/ruby/security/cve_2014_8080_spec.rb b/spec/ruby/security/cve_2014_8080_spec.rb
index 64e22cf3a7..a3f4483994 100644
--- a/spec/ruby/security/cve_2014_8080_spec.rb
+++ b/spec/ruby/security/cve_2014_8080_spec.rb
@@ -1,32 +1,35 @@
require_relative '../spec_helper'
-require 'rexml/document'
-describe "REXML::Document.new" do
+ruby_version_is ''...'3.0' do
+ require 'rexml/document'
- it "resists CVE-2014-8080 by raising an exception when entity expansion has grown too large" do
- xml = <<XML
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE x [
- <!ENTITY % x0 "xxxxxxxxxx">
- <!ENTITY % x1 "%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;">
- <!ENTITY % x2 "%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;">
- <!ENTITY % x3 "%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;">
- <!ENTITY % x4 "%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;">
- <!ENTITY % x5 "%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;">
- <!ENTITY % x6 "%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;">
- <!ENTITY % x7 "%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;">
- <!ENTITY % x8 "%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;">
- <!ENTITY % x9 "%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;">
- ]>
- <x>
- %x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;
- </x>
+ describe "REXML::Document.new" do
+
+ it "resists CVE-2014-8080 by raising an exception when entity expansion has grown too large" do
+ xml = <<XML
+ <?xml version="1.0" encoding="UTF-8" ?>
+ <!DOCTYPE x [
+ <!ENTITY % x0 "xxxxxxxxxx">
+ <!ENTITY % x1 "%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;%x0;">
+ <!ENTITY % x2 "%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;%x1;">
+ <!ENTITY % x3 "%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;%x2;">
+ <!ENTITY % x4 "%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;%x3;">
+ <!ENTITY % x5 "%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;%x4;">
+ <!ENTITY % x6 "%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;%x5;">
+ <!ENTITY % x7 "%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;%x6;">
+ <!ENTITY % x8 "%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;%x7;">
+ <!ENTITY % x9 "%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;%x8;">
+ ]>
+ <x>
+ %x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;%x9;
+ </x>
XML
- -> {
- REXML::Document.new(xml).doctype.entities['x9'].value
- }.should raise_error(REXML::ParseException, /entity expansion has grown too large/)
- end
+ -> {
+ REXML::Document.new(xml).doctype.entities['x9'].value
+ }.should raise_error(REXML::ParseException, /entity expansion has grown too large/)
+ end
+ end
end
diff --git a/spec/ruby/security/cve_2018_8780_spec.rb b/spec/ruby/security/cve_2018_8780_spec.rb
index 555ce9365c..9942e07ee2 100644
--- a/spec/ruby/security/cve_2018_8780_spec.rb
+++ b/spec/ruby/security/cve_2018_8780_spec.rb
@@ -29,17 +29,15 @@ describe "CVE-2018-8780 is resisted by" do
}.should raise_error(ArgumentError, /(path name|string) contains null byte/)
end
- ruby_version_is "2.5" do
- it "Dir.children by raising an exception when there is a NUL byte" do
- -> {
- Dir.children(@root+"\0")
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
- end
+ it "Dir.children by raising an exception when there is a NUL byte" do
+ -> {
+ Dir.children(@root+"\0")
+ }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
+ end
- it "Dir.each_child by raising an exception when there is a NUL byte" do
- -> {
- Dir.each_child(@root+"\0").to_a
- }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
- end
+ it "Dir.each_child by raising an exception when there is a NUL byte" do
+ -> {
+ Dir.each_child(@root+"\0").to_a
+ }.should raise_error(ArgumentError, /(path name|string) contains null byte/)
end
end
diff --git a/spec/ruby/security/cve_2020_10663_spec.rb b/spec/ruby/security/cve_2020_10663_spec.rb
new file mode 100644
index 0000000000..634afda525
--- /dev/null
+++ b/spec/ruby/security/cve_2020_10663_spec.rb
@@ -0,0 +1,41 @@
+require_relative '../spec_helper'
+require 'json'
+
+module JSONSpecs
+ class MyClass
+ def initialize(foo)
+ @foo = foo
+ end
+
+ def self.json_create(hash)
+ new(*hash['args'])
+ end
+
+ def to_json(*args)
+ { 'json_class' => self.class.name, 'args' => [ @foo ] }.to_json(*args)
+ end
+ end
+end
+
+guard -> {
+ ruby_version_is "2.5.8"..."2.6.0" or
+ ruby_version_is "2.6.6" or
+ 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).class.should == Hash
+ JSON.parse(json, nil).class.should == Hash
+ JSON(json).class.should == Hash
+ end
+ end
+end
diff --git a/spec/ruby/shared/enumerable/minmax.rb b/spec/ruby/shared/enumerable/minmax.rb
new file mode 100644
index 0000000000..8af2626d2a
--- /dev/null
+++ b/spec/ruby/shared/enumerable/minmax.rb
@@ -0,0 +1,24 @@
+describe :enumerable_minmax, shared: true do
+ it "min should return the minimum element" do
+ @enum.minmax.should == [4, 10]
+ @strs.minmax.should == ["1010", "60"]
+ end
+
+ it "returns the minimum when using a block rule" do
+ @enum.minmax {|a,b| b <=> a }.should == [10, 4]
+ @strs.minmax {|a,b| a.length <=> b.length }.should == ["2", "55555"]
+ end
+
+ it "returns [nil, nil] for an empty Enumerable" do
+ @empty_enum.minmax.should == [nil, nil]
+ end
+
+ it "raises a NoMethodError for elements without #<=>" do
+ -> { @incomparable_enum.minmax }.should raise_error(NoMethodError)
+ end
+
+ it "raises an ArgumentError when elements are incompatible" do
+ -> { @incompatible_enum.minmax }.should raise_error(ArgumentError)
+ -> { @enum.minmax{ |a, b| nil } }.should raise_error(ArgumentError)
+ end
+end
diff --git a/spec/ruby/shared/enumerator/enum_for.rb b/spec/ruby/shared/enumerator/enum_for.rb
index 9030ffbd7d..a67a76c461 100644
--- a/spec/ruby/shared/enumerator/enum_for.rb
+++ b/spec/ruby/shared/enumerator/enum_for.rb
@@ -12,6 +12,13 @@ describe :enum_for, shared: true do
enum.map { |v| v }.should == [1,2].each { |v| v }
end
+ it "sets regexp matches in the caller" do
+ "wawa".send(@method, :scan, /./).map {|o| $& }.should == ["w", "a", "w", "a"]
+ a = []
+ "wawa".send(@method, :scan, /./).each {|o| a << $& }
+ a.should == ["w", "a", "w", "a"]
+ end
+
it "exposes multi-arg yields as an array" do
o = Object.new
def o.each
diff --git a/spec/ruby/shared/fiber/resume.rb b/spec/ruby/shared/fiber/resume.rb
index d3dc438ae2..f3477804ad 100644
--- a/spec/ruby/shared/fiber/resume.rb
+++ b/spec/ruby/shared/fiber/resume.rb
@@ -35,32 +35,11 @@ describe :fiber_resume, shared: true do
fiber.send(@method)
end
- it "runs until Fiber.yield" do
- obj = mock('obj')
- obj.should_not_receive(:do)
- fiber = Fiber.new { 1 + 2; Fiber.yield; obj.do }
- fiber.send(@method)
- end
-
- it "resumes from the last call to Fiber.yield on subsequent invocations" do
- fiber = Fiber.new { Fiber.yield :first; :second }
- fiber.send(@method).should == :first
- fiber.send(@method).should == :second
- end
-
it "accepts any number of arguments" do
fiber = Fiber.new { |a| }
-> { fiber.send(@method, *(1..10).to_a) }.should_not raise_error
end
- it "sets the block parameters to its arguments on the first invocation" do
- first = mock('first')
- first.should_receive(:arg).with(:first).twice
- fiber = Fiber.new { |arg| first.arg arg; Fiber.yield; first.arg arg; }
- fiber.send(@method, :first)
- fiber.send(@method, :second)
- end
-
it "raises a FiberError if the Fiber is dead" do
fiber = Fiber.new { true }
fiber.send(@method)
diff --git a/spec/ruby/shared/file/executable.rb b/spec/ruby/shared/file/executable.rb
index 2987d0aabb..7b5c4c580c 100644
--- a/spec/ruby/shared/file/executable.rb
+++ b/spec/ruby/shared/file/executable.rb
@@ -13,7 +13,7 @@ describe :file_executable, shared: true do
rm_r @file1, @file2
end
- platform_is_not :windows do
+ platform_is_not :windows, :android do
it "returns true if named file is executable by the effective user id of the process, otherwise false" do
@object.send(@method, '/etc/passwd').should == false
@object.send(@method, @file1).should == true
diff --git a/spec/ruby/shared/file/identical.rb b/spec/ruby/shared/file/identical.rb
index ecc21727ca..b7a2904839 100644
--- a/spec/ruby/shared/file/identical.rb
+++ b/spec/ruby/shared/file/identical.rb
@@ -9,7 +9,11 @@ describe :file_identical, shared: true do
touch(@file2) { |f| f.puts "file2" }
rm_r @link
- File.link(@file1, @link)
+ begin
+ File.link(@file1, @link)
+ rescue Errno::EACCES
+ File.symlink(@file1, @link)
+ end
end
after :each do
diff --git a/spec/ruby/shared/file/readable.rb b/spec/ruby/shared/file/readable.rb
index 74f58caaff..eb2ca06812 100644
--- a/spec/ruby/shared/file/readable.rb
+++ b/spec/ruby/shared/file/readable.rb
@@ -4,9 +4,12 @@ describe :file_readable, shared: true do
platform_is :windows do
@file2 = File.join(ENV["WINDIR"], "system32/drivers/etc/services").tr(File::SEPARATOR, File::ALT_SEPARATOR)
end
- platform_is_not :windows do
+ platform_is_not :windows, :android do
@file2 = "/etc/passwd"
end
+ platform_is :android do
+ @file2 = "/system/bin/sh"
+ end
end
after :each do
diff --git a/spec/ruby/shared/file/world_readable.rb b/spec/ruby/shared/file/world_readable.rb
index 85761e633f..1dce7a580f 100644
--- a/spec/ruby/shared/file/world_readable.rb
+++ b/spec/ruby/shared/file/world_readable.rb
@@ -28,18 +28,18 @@ describe :file_world_readable, shared: true do
end
end
- # We don't specify what the Fixnum is because it's system dependent
- it "returns a Fixnum if the file is chmod 644" do
+ # We don't specify what the Integer is because it's system dependent
+ it "returns an Integer if the file is chmod 644" do
File.chmod(0644, @file)
- @object.world_readable?(@file).should be_an_instance_of(Fixnum)
+ @object.world_readable?(@file).should be_an_instance_of(Integer)
end
- it "returns a Fixnum if the file is a directory and chmod 644" do
- dir = rand().to_s + '-ww'
+ it "returns an Integer if the file is a directory and chmod 644" do
+ dir = tmp(rand().to_s + '-ww')
Dir.mkdir(dir)
Dir.should.exist?(dir)
File.chmod(0644, dir)
- @object.world_readable?(dir).should be_an_instance_of(Fixnum)
+ @object.world_readable?(dir).should be_an_instance_of(Integer)
Dir.rmdir(dir)
end
diff --git a/spec/ruby/shared/file/world_writable.rb b/spec/ruby/shared/file/world_writable.rb
index 61b691bcb6..7ed252dcf3 100644
--- a/spec/ruby/shared/file/world_writable.rb
+++ b/spec/ruby/shared/file/world_writable.rb
@@ -27,18 +27,18 @@ describe :file_world_writable, shared: true do
@object.world_writable?(@file).should be_nil
end
- # We don't specify what the Fixnum is because it's system dependent
- it "returns a Fixnum if the file is chmod 777" do
+ # We don't specify what the Integer is because it's system dependent
+ it "returns an Integer if the file is chmod 777" do
File.chmod(0777, @file)
- @object.world_writable?(@file).should be_an_instance_of(Fixnum)
+ @object.world_writable?(@file).should be_an_instance_of(Integer)
end
- it "returns a Fixnum if the file is a directory and chmod 777" do
- dir = rand().to_s + '-ww'
+ it "returns an Integer if the file is a directory and chmod 777" do
+ dir = tmp(rand().to_s + '-ww')
Dir.mkdir(dir)
Dir.should.exist?(dir)
File.chmod(0777, dir)
- @object.world_writable?(dir).should be_an_instance_of(Fixnum)
+ @object.world_writable?(dir).should be_an_instance_of(Integer)
Dir.rmdir(dir)
end
end
diff --git a/spec/ruby/shared/file/writable.rb b/spec/ruby/shared/file/writable.rb
index 902d545da1..4bb8aedce6 100644
--- a/spec/ruby/shared/file/writable.rb
+++ b/spec/ruby/shared/file/writable.rb
@@ -8,7 +8,7 @@ describe :file_writable, shared: true do
end
it "returns true if named file is writable by the effective user id of the process, otherwise false" do
- platform_is_not :windows do
+ platform_is_not :windows, :android do
as_user do
@object.send(@method, "/etc/passwd").should == false
end
diff --git a/spec/ruby/shared/hash/key_error.rb b/spec/ruby/shared/hash/key_error.rb
index 061c88c483..54dcb89e91 100644
--- a/spec/ruby/shared/hash/key_error.rb
+++ b/spec/ruby/shared/hash/key_error.rb
@@ -5,21 +5,19 @@ describe :key_error, shared: true do
}.should raise_error(KeyError)
end
- ruby_version_is "2.5" do
- it "sets the Hash as the receiver of KeyError" do
- -> {
- @method.call(@object, 'foo')
- }.should raise_error(KeyError) { |err|
- err.receiver.should equal(@object)
- }
- end
+ it "sets the Hash as the receiver of KeyError" do
+ -> {
+ @method.call(@object, 'foo')
+ }.should raise_error(KeyError) { |err|
+ err.receiver.should equal(@object)
+ }
+ end
- it "sets the unmatched key as the key of KeyError" do
- -> {
- @method.call(@object, 'foo')
- }.should raise_error(KeyError) { |err|
- err.key.to_s.should == 'foo'
- }
- end
+ it "sets the unmatched key as the key of KeyError" do
+ -> {
+ @method.call(@object, 'foo')
+ }.should raise_error(KeyError) { |err|
+ err.key.to_s.should == 'foo'
+ }
end
end
diff --git a/spec/ruby/shared/io/putc.rb b/spec/ruby/shared/io/putc.rb
index fac14886ee..e6012c0098 100644
--- a/spec/ruby/shared/io/putc.rb
+++ b/spec/ruby/shared/io/putc.rb
@@ -6,7 +6,7 @@ describe :io_putc, shared: true do
rm_r @name
end
- describe "with a Fixnum argument" do
+ describe "with an Integer argument" do
it "writes one character as a String" do
@io.should_receive(:write).with("A")
@io_object.send(@method, 65).should == 65
diff --git a/spec/ruby/shared/kernel/object_id.rb b/spec/ruby/shared/kernel/object_id.rb
index 7acdb27554..175f3fb749 100644
--- a/spec/ruby/shared/kernel/object_id.rb
+++ b/spec/ruby/shared/kernel/object_id.rb
@@ -16,7 +16,7 @@ describe :object_id, shared: true do
o1.__send__(@method).should_not == o2.__send__(@method)
end
- it "returns the same value for two Fixnums with the same value" do
+ it "returns the same value for two Integers with the same value" do
o1 = 1
o2 = 1
o1.send(@method).should == o2.send(@method)
@@ -46,7 +46,7 @@ describe :object_id, shared: true do
o1.send(@method).should == o2.send(@method)
end
- it "returns a different value for two Bignum literals" do
+ it "returns a different value for two Integer literals" do
o1 = 2e100.to_i
o2 = 2e100.to_i
o1.send(@method).should_not == o2.send(@method)
@@ -64,14 +64,14 @@ describe :object_id, shared: true do
o1.send(@method).should_not == o2.send(@method)
end
- it "returns a different value for two numbers near the 32 bit Fixnum limit" do
+ it "returns a different value for two numbers near the 32 bit Integer limit" do
o1 = -1
o2 = 2 ** 30 - 1
o1.send(@method).should_not == o2.send(@method)
end
- it "returns a different value for two numbers near the 64 bit Fixnum limit" do
+ it "returns a different value for two numbers near the 64 bit Integer limit" do
o1 = -1
o2 = 2 ** 62 - 1
diff --git a/spec/ruby/shared/kernel/raise.rb b/spec/ruby/shared/kernel/raise.rb
index d4553775f4..f00a6ef294 100644
--- a/spec/ruby/shared/kernel/raise.rb
+++ b/spec/ruby/shared/kernel/raise.rb
@@ -25,6 +25,14 @@ describe :kernel_raise, shared: true do
-> { @object.raise("a bad thing") }.should raise_error(RuntimeError)
end
+ it "passes no arguments to the constructor when given only an exception class" do
+ klass = Class.new(Exception) do
+ def initialize
+ end
+ end
+ -> { @object.raise(klass) }.should raise_error(klass) { |e| e.message.should == klass.to_s }
+ end
+
it "raises a TypeError when passed a non-Exception object" do
-> { @object.raise(Object.new) }.should raise_error(TypeError)
end
@@ -41,40 +49,44 @@ describe :kernel_raise, shared: true do
-> { @object.raise(nil) }.should raise_error(TypeError)
end
- it "re-raises the previously rescued exception if no exception is specified" do
- -> do
- begin
- @object.raise Exception, "outer"
- ScratchPad.record :no_abort
- rescue
+ it "re-raises a previously rescued exception without overwriting the backtrace" do
+ # This spec is written using #backtrace and matching the line number
+ # from the string, as backtrace_locations is a more advanced
+ # method that is not always supported by implementations.
+ #
+ initial_raise_line = nil
+ raise_again_line = nil
+ raised_again = nil
+
+ if defined?(FiberSpecs::NewFiberToRaise) and @object == FiberSpecs::NewFiberToRaise
+ fiber = Fiber.new do
begin
- @object.raise StandardError, "inner"
- rescue
+ initial_raise_line = __LINE__; Fiber.yield
+ rescue => raised
+ begin
+ raise_again_line = __LINE__; Fiber.yield raised
+ rescue => raised_again
+ raised_again
+ end
end
-
- @object.raise
- ScratchPad.record :no_reraise
end
- end.should raise_error(Exception, "outer")
-
- ScratchPad.recorded.should be_nil
- end
-
- it "re-raises a previously rescued exception without overwriting the backtrace" do
- begin
- initial_raise_line = __LINE__; @object.raise 'raised'
- rescue => raised
+ fiber.resume
+ raised = fiber.raise 'raised'
+ raised_again = fiber.raise raised
+ else
begin
- raise_again_line = __LINE__; @object.raise raised
- rescue => raised_again
- # This spec is written using #backtrace and matching the line number
- # from the string, as backtrace_locations is a more advanced
- # method that is not always supported by implementations.
-
- raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:")
- raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
+ initial_raise_line = __LINE__; @object.raise 'raised'
+ rescue => raised
+ begin
+ raise_again_line = __LINE__; @object.raise raised
+ rescue => raised_again
+ raised_again
+ end
end
end
+
+ raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:")
+ raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
end
it "allows Exception, message, and backtrace parameters" do
diff --git a/spec/ruby/shared/process/exit.rb b/spec/ruby/shared/process/exit.rb
index 1820dd17fd..e633afc73a 100644
--- a/spec/ruby/shared/process/exit.rb
+++ b/spec/ruby/shared/process/exit.rb
@@ -91,4 +91,24 @@ describe :process_exit!, shared: true do
out.should == ""
$?.exitstatus.should == 21
end
+
+ it "skips at_exit handlers" do
+ out = ruby_exe("at_exit { STDERR.puts 'at_exit' }; #{@object}.send(:exit!, 21)", args: '2>&1')
+ out.should == ""
+ $?.exitstatus.should == 21
+ end
+
+ it "overrides the original exception and exit status when called from #at_exit" do
+ code = <<-RUBY
+ at_exit do
+ STDERR.puts 'in at_exit'
+ STDERR.puts "$! is \#{$!.class}:\#{$!.message}"
+ #{@object}.send(:exit!, 21)
+ end
+ raise 'original error'
+ RUBY
+ out = ruby_exe(code, args: '2>&1')
+ out.should == "in at_exit\n$! is RuntimeError:original error\n"
+ $?.exitstatus.should == 21
+ end
end
diff --git a/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb b/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb
index 9377814732..0dff91d522 100644
--- a/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb
+++ b/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb
@@ -1,33 +1,11 @@
require_relative '../../fixtures/rational'
describe :rational_arithmetic_exception_in_coerce, shared: true do
- ruby_version_is ""..."2.5" do
- it "rescues exception (StandardError and subclasses) raised in other#coerce and raises TypeError" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError)
+ it "does not rescue exception raised in other#coerce" do
+ b = mock("numeric with failed #coerce")
+ b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError)
- # e.g. Rational(3, 4) + b
- -> { Rational(3, 4).send(@method, b) }.should raise_error(TypeError, /MockObject can't be coerced into Rational/)
- end
-
- it "does not rescue Exception and StandardError siblings raised in other#coerce" do
- [Exception, NoMemoryError].each do |exception|
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(exception)
-
- # e.g. Rational(3, 4) + b
- -> { Rational(3, 4).send(@method, b) }.should raise_error(exception)
- end
- end
- end
-
- ruby_version_is "2.5" do
- it "does not rescue exception raised in other#coerce" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError)
-
- # e.g. Rational(3, 4) + b
- -> { Rational(3, 4).send(@method, b) }.should raise_error(RationalSpecs::CoerceError)
- end
+ # e.g. Rational(3, 4) + b
+ -> { Rational(3, 4).send(@method, b) }.should raise_error(RationalSpecs::CoerceError)
end
end
diff --git a/spec/ruby/shared/rational/coerce.rb b/spec/ruby/shared/rational/coerce.rb
index ffb118e2a7..ccc8901ba0 100644
--- a/spec/ruby/shared/rational/coerce.rb
+++ b/spec/ruby/shared/rational/coerce.rb
@@ -17,6 +17,11 @@ describe :rational_coerce, shared: true do
result.last.is_a?(Rational).should be_true
end
+ it "coerces to Rational, when given a Complex" do
+ Rational(3, 4).coerce(Complex(5)).should == [Rational(5, 1), Rational(3, 4)]
+ Rational(12, 4).coerce(Complex(5, 1)).should == [Complex(5, 1), Complex(3)]
+ end
+
it "returns [argument, self] when given a Rational" do
Rational(3, 7).coerce(Rational(9, 2)).should == [Rational(9, 2), Rational(3, 7)]
end
diff --git a/spec/ruby/shared/rational/comparison.rb b/spec/ruby/shared/rational/comparison.rb
index 0c8b3d0ac1..860462f579 100644
--- a/spec/ruby/shared/rational/comparison.rb
+++ b/spec/ruby/shared/rational/comparison.rb
@@ -80,33 +80,11 @@ describe :rational_cmp_coerce, shared: true do
end
describe :rational_cmp_coerce_exception, shared: true do
- ruby_version_is ""..."2.5" do
- it "rescues exception (StandardError and subclasses) raised in other#coerce and returns nil" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError)
-
- -> {
- (Rational(3, 4) <=> b).should == nil
- }.should complain(/Numerical comparison operators will no more rescue exceptions of #coerce/)
- end
-
- it "does not rescue Exception and StandardError siblings raised in other#coerce" do
- [Exception, NoMemoryError].each do |exception|
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(exception)
-
- -> { Rational(3, 4) <=> b }.should raise_error(exception)
- end
- end
- end
-
- ruby_version_is "2.5" do
- it "does not rescue exception raised in other#coerce" do
- b = mock("numeric with failed #coerce")
- b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError)
+ it "does not rescue exception raised in other#coerce" do
+ b = mock("numeric with failed #coerce")
+ b.should_receive(:coerce).and_raise(RationalSpecs::CoerceError)
- -> { Rational(3, 4) <=> b }.should raise_error(RationalSpecs::CoerceError)
- end
+ -> { Rational(3, 4) <=> b }.should raise_error(RationalSpecs::CoerceError)
end
end
diff --git a/spec/ruby/shared/rational/exponent.rb b/spec/ruby/shared/rational/exponent.rb
index 1d808177e9..0f6abcd634 100644
--- a/spec/ruby/shared/rational/exponent.rb
+++ b/spec/ruby/shared/rational/exponent.rb
@@ -59,7 +59,7 @@ describe :rational_exponent, shared: true do
end
end
- describe "when passed Bignum" do
+ describe "when passed Integer" 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))
diff --git a/spec/ruby/shared/string/end_with.rb b/spec/ruby/shared/string/end_with.rb
new file mode 100644
index 0000000000..5f2a011235
--- /dev/null
+++ b/spec/ruby/shared/string/end_with.rb
@@ -0,0 +1,54 @@
+describe :end_with, shared: true do
+ # the @method should either be :to_s or :to_sym
+
+ it "returns true only if ends match" do
+ s = "hello".send(@method)
+ s.should.end_with?('o')
+ s.should.end_with?('llo')
+ end
+
+ it 'returns false if the end does not match' do
+ s = 'hello'.send(@method)
+ s.should_not.end_with?('ll')
+ end
+
+ it "returns true if the search string is empty" do
+ "hello".send(@method).should.end_with?("")
+ "".send(@method).should.end_with?("")
+ end
+
+ it "returns true only if any ending match" do
+ "hello".send(@method).should.end_with?('x', 'y', 'llo', 'z')
+ end
+
+ it "converts its argument using :to_str" do
+ s = "hello".send(@method)
+ find = mock('o')
+ find.should_receive(:to_str).and_return("o")
+ s.should.end_with?(find)
+ end
+
+ it "ignores arguments not convertible to string" do
+ "hello".send(@method).should_not.end_with?()
+ -> { "hello".send(@method).end_with?(1) }.should raise_error(TypeError)
+ -> { "hello".send(@method).end_with?(["o"]) }.should raise_error(TypeError)
+ -> { "hello".send(@method).end_with?(1, nil, "o") }.should raise_error(TypeError)
+ end
+
+ it "uses only the needed arguments" do
+ find = mock('h')
+ find.should_not_receive(:to_str)
+ "hello".send(@method).should.end_with?("o",find)
+ end
+
+ it "works for multibyte strings" do
+ "céréale".send(@method).should.end_with?("réale")
+ end
+
+ it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
+ pat = "ア".encode Encoding::EUC_JP
+ -> do
+ "あれ".send(@method).end_with?(pat)
+ end.should raise_error(Encoding::CompatibilityError)
+ end
+end
diff --git a/spec/ruby/shared/string/start_with.rb b/spec/ruby/shared/string/start_with.rb
new file mode 100644
index 0000000000..d8d6e13f6a
--- /dev/null
+++ b/spec/ruby/shared/string/start_with.rb
@@ -0,0 +1,72 @@
+describe :start_with, shared: true do
+ # the @method should either be :to_s or :to_sym
+
+ it "returns true only if beginning match" do
+ s = "hello".send(@method)
+ s.should.start_with?('h')
+ s.should.start_with?('hel')
+ s.should_not.start_with?('el')
+ end
+
+ it "returns true only if any beginning match" do
+ "hello".send(@method).should.start_with?('x', 'y', 'he', 'z')
+ end
+
+ it "returns true if the search string is empty" do
+ "hello".send(@method).should.start_with?("")
+ "".send(@method).should.start_with?("")
+ end
+
+ it "converts its argument using :to_str" do
+ s = "hello".send(@method)
+ find = mock('h')
+ find.should_receive(:to_str).and_return("h")
+ s.should.start_with?(find)
+ end
+
+ it "ignores arguments not convertible to string" do
+ "hello".send(@method).should_not.start_with?()
+ -> { "hello".send(@method).start_with?(1) }.should raise_error(TypeError)
+ -> { "hello".send(@method).start_with?(["h"]) }.should raise_error(TypeError)
+ -> { "hello".send(@method).start_with?(1, nil, "h") }.should raise_error(TypeError)
+ end
+
+ it "uses only the needed arguments" do
+ find = mock('h')
+ find.should_not_receive(:to_str)
+ "hello".send(@method).should.start_with?("h",find)
+ end
+
+ it "works for multibyte strings" do
+ "céréale".send(@method).should.start_with?("cér")
+ end
+
+ it "supports regexps" do
+ regexp = /[h1]/
+ "hello".send(@method).should.start_with?(regexp)
+ "1337".send(@method).should.start_with?(regexp)
+ "foxes are 1337".send(@method).should_not.start_with?(regexp)
+ "chunky\n12bacon".send(@method).should_not.start_with?(/12/)
+ end
+
+ it "supports regexps with ^ and $ modifiers" do
+ regexp1 = /^\d{2}/
+ regexp2 = /\d{2}$/
+ "12test".send(@method).should.start_with?(regexp1)
+ "test12".send(@method).should_not.start_with?(regexp1)
+ "12test".send(@method).should_not.start_with?(regexp2)
+ "test12".send(@method).should_not.start_with?(regexp2)
+ end
+
+ it "sets Regexp.last_match if it returns true" do
+ regexp = /test-(\d+)/
+ "test-1337".send(@method).start_with?(regexp).should be_true
+ Regexp.last_match.should_not be_nil
+ Regexp.last_match[1].should == "1337"
+ $1.should == "1337"
+
+ "test-asdf".send(@method).start_with?(regexp).should be_false
+ Regexp.last_match.should be_nil
+ $1.should be_nil
+ end
+end
diff --git a/spec/ruby/shared/string/times.rb b/spec/ruby/shared/string/times.rb
index 6b45f7aa1e..fcc9d00fd6 100644
--- a/spec/ruby/shared/string/times.rb
+++ b/spec/ruby/shared/string/times.rb
@@ -20,16 +20,32 @@ describe :string_times, shared: true do
it "raises an ArgumentError when given integer is negative" do
-> { @object.call("cool", -3) }.should raise_error(ArgumentError)
-> { @object.call("cool", -3.14) }.should raise_error(ArgumentError)
+ -> { @object.call("cool", min_long) }.should raise_error(ArgumentError)
end
- it "raises a RangeError when given integer is a Bignum" do
+ it "raises a RangeError when given integer is an Integer" do
-> { @object.call("cool", 999999999999999999999) }.should raise_error(RangeError)
+ -> { @object.call("", 999999999999999999999) }.should raise_error(RangeError)
end
- it "returns subclass instances" do
- @object.call(MyString.new("cool"), 0).should be_an_instance_of(MyString)
- @object.call(MyString.new("cool"), 1).should be_an_instance_of(MyString)
- @object.call(MyString.new("cool"), 2).should be_an_instance_of(MyString)
+ it "works with huge long values when string is empty" do
+ @object.call("", max_long).should == ""
+ end
+
+ ruby_version_is ''...'3.0' do
+ it "returns subclass instances" do
+ @object.call(MyString.new("cool"), 0).should be_an_instance_of(MyString)
+ @object.call(MyString.new("cool"), 1).should be_an_instance_of(MyString)
+ @object.call(MyString.new("cool"), 2).should be_an_instance_of(MyString)
+ end
+ end
+
+ ruby_version_is '3.0' do
+ it "returns String instances" do
+ @object.call(MyString.new("cool"), 0).should be_an_instance_of(String)
+ @object.call(MyString.new("cool"), 1).should be_an_instance_of(String)
+ @object.call(MyString.new("cool"), 2).should be_an_instance_of(String)
+ end
end
ruby_version_is ''...'2.7' do
@@ -38,7 +54,7 @@ describe :string_times, shared: true do
str.taint
[0, 1, 2].each do |arg|
- @object.call(str, arg).tainted?.should == true
+ @object.call(str, arg).should.tainted?
end
end
end
diff --git a/sprintf.c b/sprintf.c
index 23eb39a73b..62b7503d98 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -11,17 +11,27 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/re.h"
-#include "internal.h"
-#include "id.h"
+#include "ruby/internal/config.h"
+
#include <math.h>
#include <stdarg.h>
#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
+# include <ieeefp.h>
#endif
+#include "id.h"
+#include "internal.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/sanitizers.h"
+#include "internal/symbol.h"
+#include "internal/util.h"
+#include "ruby/encoding.h"
+#include "ruby/re.h"
+
#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
static char *fmt_setup(char*,size_t,int,int,int,int);
@@ -247,7 +257,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
blen = 0;
bsiz = 120;
result = rb_str_buf_new(bsiz);
- rb_enc_copy(result, fmt);
+ rb_enc_associate(result, enc);
buf = RSTRING_PTR(result);
memset(buf, 0, bsiz);
ENC_CODERANGE_SET(result, coderange);
@@ -984,10 +994,6 @@ fmt_setup(char *buf, size_t size, int c, int flags, int width, int prec)
#endif
#define lower_hexdigits (ruby_hexdigits+0)
#define upper_hexdigits (ruby_hexdigits+16)
-#if defined RUBY_USE_SETJMPEX && RUBY_USE_SETJMPEX
-# undef MAYBE_UNUSED
-# define MAYBE_UNUSED(x) x = 0
-#endif
#include "vsnprintf.c"
static char *
diff --git a/st.c b/st.c
index 599f93a463..9131dc13c2 100644
--- a/st.c
+++ b/st.c
@@ -105,6 +105,9 @@
#include "st.h"
#else
#include "internal.h"
+#include "internal/bits.h"
+#include "internal/hash.h"
+#include "internal/sanitizers.h"
#endif
#include <stdio.h>
@@ -124,12 +127,6 @@
#define ATTRIBUTE_UNUSED
#endif
-#ifdef ST_DEBUG
-#define st_assert assert
-#else
-#define st_assert(cond) ((void)(0 && (cond)))
-#endif
-
/* The type of hashes. */
typedef st_index_t st_hash_t;
@@ -316,9 +313,6 @@ static const struct st_features features[] = {
#define RESERVED_HASH_VAL (~(st_hash_t) 0)
#define RESERVED_HASH_SUBSTITUTION_VAL ((st_hash_t) 0)
-const st_hash_t st_reserved_hash_val = RESERVED_HASH_VAL;
-const st_hash_t st_reserved_hash_substitution_val = RESERVED_HASH_SUBSTITUTION_VAL;
-
/* Return hash value of KEY for table TAB. */
static inline st_hash_t
do_hash(st_data_t key, st_table *tab)
@@ -405,8 +399,6 @@ set_bin(st_index_t *bins, int s, st_index_t n, st_index_t v)
corresponding to deleted entries. */
#define MARK_BIN_DELETED(tab, i) \
do { \
- st_assert(i != UNDEFINED_BIN_IND); \
- st_assert(! IND_EMPTY_OR_DELETED_BIN_P(tab, i)); \
set_bin((tab)->bins, get_size_ind(tab), i, DELETED_BIN); \
} while (0)
@@ -487,59 +479,6 @@ make_tab_empty(st_table *tab)
initialize_bins(tab);
}
-#ifdef ST_DEBUG
-#define st_assert_notinitial(ent) \
- do { \
- st_assert(ent.hash != (st_hash_t) ST_INIT_VAL); \
- st_assert(ent.key != ST_INIT_VAL); \
- st_assert(ent.record != ST_INIT_VAL); \
- } while (0)
-/* Check the table T consistency. It can be extremely slow. So use
- it only for debugging. */
-static void
-st_check(st_table *tab)
-{
- st_index_t d, e, i, n, p;
-
- for (p = get_allocated_entries(tab), i = 0; p > 1; i++, p>>=1)
- ;
- p = i;
- st_assert(p >= MINIMAL_POWER2);
- st_assert(tab->entries_bound <= get_allocated_entries(tab));
- st_assert(tab->entries_start <= tab->entries_bound);
- n = 0;
- return;
- if (tab->entries_bound != 0)
- for (i = tab->entries_start; i < tab->entries_bound; i++) {
- st_assert_notinitial(tab->entries[i]);
- if (! DELETED_ENTRY_P(&tab->entries[i]))
- n++;
- }
- st_assert(n == tab->num_entries);
- if (tab->bins == NULL)
- st_assert(p <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS);
- else {
- st_assert(p > MAX_POWER2_FOR_TABLES_WITHOUT_BINS);
- for (n = d = i = 0; i < get_bins_num(tab); i++) {
- st_assert(get_bin(tab->bins, tab->size_ind, i) != ST_INIT_VAL);
- if (IND_DELETED_BIN_P(tab, i)) {
- d++;
- continue;
- }
- else if (IND_EMPTY_BIN_P(tab, i))
- continue;
- n++;
- e = get_bin(tab->bins, tab->size_ind, i) - ENTRY_BASE;
- st_assert(tab->entries_start <= e && e < tab->entries_bound);
- st_assert(! DELETED_ENTRY_P(&tab->entries[e]));
- st_assert_notinitial(tab->entries[e]);
- }
- st_assert(n == tab->num_entries);
- st_assert(n + d < get_bins_num(tab));
- }
-}
-#endif
-
#ifdef HASH_LOG
#ifdef HAVE_UNISTD_H
#include <unistd.h>
@@ -625,17 +564,8 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
return NULL;
}
#endif
-#ifdef ST_DEBUG
- memset(tab->entries, ST_INIT_VAL_BYTE,
- get_allocated_entries(tab) * sizeof(st_table_entry));
- if (tab->bins != NULL)
- memset(tab->bins, ST_INIT_VAL_BYTE, bins_size(tab));
-#endif
make_tab_empty(tab);
tab->rebuilds_num = 0;
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return tab;
}
@@ -699,9 +629,6 @@ st_clear(st_table *tab)
{
make_tab_empty(tab);
tab->rebuilds_num++;
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
}
/* Free table TAB space. */
@@ -784,7 +711,6 @@ rebuild_table(st_table *tab)
st_index_t *bins;
st_index_t bin_ind;
- st_assert(tab != NULL);
bound = tab->entries_bound;
entries = tab->entries;
if ((2 * tab->num_entries <= get_allocated_entries(tab)
@@ -815,9 +741,6 @@ rebuild_table(st_table *tab)
if (EXPECT(bins != NULL, 1)) {
bin_ind = find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
curr_entry_ptr->key);
- st_assert(bin_ind != UNDEFINED_BIN_IND);
- st_assert(tab == new_tab || new_tab->rebuilds_num == 0);
- st_assert(IND_EMPTY_BIN_P(new_tab, bin_ind));
set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
}
new_tab->num_entries++;
@@ -827,8 +750,6 @@ rebuild_table(st_table *tab)
tab->entry_power = new_tab->entry_power;
tab->bin_power = new_tab->bin_power;
tab->size_ind = new_tab->size_ind;
- st_assert(tab->num_entries == ni);
- st_assert(new_tab->num_entries == ni);
if (tab->bins != NULL)
free(tab->bins);
tab->bins = new_tab->bins;
@@ -839,9 +760,6 @@ rebuild_table(st_table *tab)
tab->entries_start = 0;
tab->entries_bound = tab->num_entries;
tab->rebuilds_num++;
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
}
/* Return the next secondary hash index for table TAB using previous
@@ -908,8 +826,6 @@ find_table_entry_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
st_index_t bin;
st_table_entry *entries = tab->entries;
- st_assert(tab != NULL);
- st_assert(tab->bins != NULL);
ind = hash_bin(hash_value, tab);
#ifdef QUADRATIC_PROBE
d = 1;
@@ -955,8 +871,6 @@ find_table_bin_ind(st_table *tab, st_hash_t hash_value, st_data_t key)
st_index_t bin;
st_table_entry *entries = tab->entries;
- st_assert(tab != NULL);
- st_assert(tab->bins != NULL);
ind = hash_bin(hash_value, tab);
#ifdef QUADRATIC_PROBE
d = 1;
@@ -998,10 +912,7 @@ find_table_bin_ind_direct(st_table *tab, st_hash_t hash_value, st_data_t key)
st_index_t peterb;
#endif
st_index_t bin;
- st_table_entry *entries = tab->entries;
- st_assert(tab != NULL);
- st_assert(tab->bins != NULL);
ind = hash_bin(hash_value, tab);
#ifdef QUADRATIC_PROBE
d = 1;
@@ -1013,7 +924,6 @@ find_table_bin_ind_direct(st_table *tab, st_hash_t hash_value, st_data_t key)
bin = get_bin(tab->bins, get_size_ind(tab), ind);
if (EMPTY_OR_DELETED_BIN_P(bin))
return ind;
- st_assert (entries[bin - ENTRY_BASE].hash != hash_value);
#ifdef QUADRATIC_PROBE
ind = hash_bin(ind + d, tab);
d++;
@@ -1049,10 +959,6 @@ find_table_bin_ptr_and_reserve(st_table *tab, st_hash_t *hash_value,
st_index_t first_deleted_bin_ind;
st_table_entry *entries;
- st_assert(tab != NULL);
- st_assert(tab->bins != NULL);
- st_assert(tab->entries_bound <= get_allocated_entries(tab));
- st_assert(tab->entries_start <= tab->entries_bound);
ind = hash_bin(curr_hash_value, tab);
#ifdef QUADRATIC_PROBE
d = 1;
@@ -1161,11 +1067,10 @@ rebuild_table_if_necessary (st_table *tab)
if (bound == get_allocated_entries(tab))
rebuild_table(tab);
- st_assert(tab->entries_bound < get_allocated_entries(tab));
}
/* Insert (KEY, VALUE) into table TAB and return zero. If there is
- already entry with KEY in the table, return nonzero and and update
+ already entry with KEY in the table, return nonzero and update
the value of the found entry. */
int
st_insert(st_table *tab, st_data_t key, st_data_t value)
@@ -1198,7 +1103,6 @@ st_insert(st_table *tab, st_data_t key, st_data_t value)
bin -= ENTRY_BASE;
}
if (new_p) {
- st_assert(tab->entries_bound < get_allocated_entries(tab));
ind = tab->entries_bound++;
entry = &tab->entries[ind];
entry->hash = hash_value;
@@ -1206,15 +1110,9 @@ st_insert(st_table *tab, st_data_t key, st_data_t value)
entry->record = value;
if (bin_ind != UNDEFINED_BIN_IND)
set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return 0;
}
tab->entries[bin].record = value;
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return 1;
}
@@ -1237,12 +1135,8 @@ st_add_direct_with_hash(st_table *tab,
tab->num_entries++;
if (tab->bins != NULL) {
bin_ind = find_table_bin_ind_direct(tab, hash, key);
- st_assert (bin_ind != UNDEFINED_BIN_IND);
set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
}
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
}
/* Insert (KEY, VALUE) into table TAB. The table should not have
@@ -1258,14 +1152,14 @@ st_add_direct(st_table *tab, st_data_t key, st_data_t value)
/* Insert (FUNC(KEY), VALUE) into table TAB and return zero. If
there is already entry with KEY in the table, return nonzero and
- and update the value of the found entry. */
+ update the value of the found entry. */
int
st_insert2(st_table *tab, st_data_t key, st_data_t value,
st_data_t (*func)(st_data_t))
{
st_table_entry *entry;
st_index_t bin;
- st_index_t ind, check;
+ st_index_t ind;
st_hash_t hash_value;
st_index_t bin_ind;
int new_p;
@@ -1291,10 +1185,7 @@ st_insert2(st_table *tab, st_data_t key, st_data_t value,
bin -= ENTRY_BASE;
}
if (new_p) {
- st_assert(tab->entries_bound < get_allocated_entries(tab));
- check = tab->rebuilds_num;
key = (*func)(key);
- st_assert(check == tab->rebuilds_num);
ind = tab->entries_bound++;
entry = &tab->entries[ind];
entry->hash = hash_value;
@@ -1302,16 +1193,9 @@ st_insert2(st_table *tab, st_data_t key, st_data_t value,
entry->record = value;
if (bin_ind != UNDEFINED_BIN_IND)
set_bin(tab->bins, get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
- st_assert(do_hash(key, tab) == hash_value);
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return 0;
}
tab->entries[bin].record = value;
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return 1;
}
@@ -1350,9 +1234,6 @@ st_copy(st_table *old_tab)
get_allocated_entries(old_tab));
if (old_tab->bins != NULL)
MEMCPY(new_tab->bins, old_tab->bins, char, bins_size(old_tab));
-#ifdef ST_DEBUG
- st_check(new_tab);
-#endif
return new_tab;
}
@@ -1379,7 +1260,6 @@ st_general_delete(st_table *tab, st_data_t *key, st_data_t *value)
st_index_t bin_ind;
st_hash_t hash;
- st_assert(tab != NULL);
hash = do_hash(*key, tab);
retry:
if (tab->bins == NULL) {
@@ -1408,9 +1288,6 @@ st_general_delete(st_table *tab, st_data_t *key, st_data_t *value)
MARK_ENTRY_DELETED(entry);
tab->num_entries--;
update_range_for_deleted(tab, bin);
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return 1;
}
@@ -1461,7 +1338,6 @@ st_shift(st_table *tab, st_data_t *key, st_data_t *value)
entries = tab->entries;
goto retry;
}
- st_assert(bin != UNDEFINED_ENTRY_IND);
curr_entry_ptr = &entries[bin];
}
else {
@@ -1470,22 +1346,16 @@ st_shift(st_table *tab, st_data_t *key, st_data_t *value)
entries = tab->entries;
goto retry;
}
- st_assert(bin_ind != UNDEFINED_BIN_IND);
curr_entry_ptr = &entries[get_bin(tab->bins, get_size_ind(tab), bin_ind)
- ENTRY_BASE];
MARK_BIN_DELETED(tab, bin_ind);
}
- st_assert(entry_hash != curr_entry_ptr->hash && entry_key == curr_entry_ptr->key);
MARK_ENTRY_DELETED(curr_entry_ptr);
tab->num_entries--;
update_range_for_deleted(tab, i);
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return 1;
}
}
- st_assert(tab->num_entries == 0);
if (value != 0) *value = 0;
return 0;
}
@@ -1497,14 +1367,15 @@ st_cleanup_safe(st_table *tab ATTRIBUTE_UNUSED,
{
}
-/* Find entry with KEY in table TAB, call FUNC with the key and the
- value of the found entry, and non-zero as the 3rd argument. If the
- entry is not found, call FUNC with KEY, and 2 zero arguments. If
- the call returns ST_CONTINUE, the table will have an entry with key
- and value returned by FUNC through the 1st and 2nd parameters. If
- the call of FUNC returns ST_DELETE, the table will not have entry
- with KEY. The function returns flag of that the entry with KEY was
- in the table before the call. */
+/* Find entry with KEY in table TAB, call FUNC with pointers to copies
+ of the key and the value of the found entry, and non-zero as the
+ 3rd argument. If the entry is not found, call FUNC with a pointer
+ to KEY, a pointer to zero, and a zero argument. If the call
+ returns ST_CONTINUE, the table will have an entry with key and
+ value returned by FUNC through the 1st and 2nd parameters. If the
+ call of FUNC returns ST_DELETE, the table will not have entry with
+ KEY. The function returns flag of that the entry with KEY was in
+ the table before the call. */
int
st_update(st_table *tab, st_data_t key,
st_update_callback_func *func, st_data_t arg)
@@ -1514,7 +1385,6 @@ st_update(st_table *tab, st_data_t key,
st_table_entry *entries;
st_index_t bin_ind;
st_data_t value = 0, old_key;
- st_index_t check;
int retval, existing;
st_hash_t hash = do_hash(key, tab);
@@ -1543,9 +1413,7 @@ st_update(st_table *tab, st_data_t key,
value = entry->record;
}
old_key = key;
- check = tab->rebuilds_num;
retval = (*func)(&key, &value, arg, existing);
- st_assert(check == tab->rebuilds_num);
switch (retval) {
case ST_CONTINUE:
if (! existing) {
@@ -1564,15 +1432,9 @@ st_update(st_table *tab, st_data_t key,
MARK_ENTRY_DELETED(entry);
tab->num_entries--;
update_range_for_deleted(tab, bin);
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
}
break;
}
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return existing;
}
@@ -1597,10 +1459,9 @@ st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_updat
st_data_t key;
int error_p, packed_p = tab->bins == NULL;
- st_assert(tab->entries_start <= tab->entries_bound);
entries = tab->entries;
/* The bound can change inside the loop even without rebuilding
- the table, e.g. by an entry inesrtion. */
+ the table, e.g. by an entry insertion. */
for (i = tab->entries_start; i < tab->entries_bound; i++) {
curr_entry_ptr = &entries[i];
if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
@@ -1638,60 +1499,48 @@ st_general_foreach(st_table *tab, st_foreach_check_callback_func *func, st_updat
if (error_p && check_p) {
/* call func with error notice */
retval = (*func)(0, 0, arg, 1);
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return 1;
}
curr_entry_ptr = &entries[i];
}
switch (retval) {
- case ST_REPLACE:
- break;
+ case ST_REPLACE:
+ break;
case ST_CONTINUE:
- break;
+ break;
case ST_CHECK:
- if (check_p)
- break;
+ if (check_p)
+ break;
case ST_STOP:
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
- return 0;
+ return 0;
case ST_DELETE: {
- st_data_t key = curr_entry_ptr->key;
+ st_data_t key = curr_entry_ptr->key;
again:
- if (packed_p) {
- bin = find_entry(tab, hash, key);
- if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
- goto again;
- if (bin == UNDEFINED_ENTRY_IND)
- break;
- }
- else {
- bin_ind = find_table_bin_ind(tab, hash, key);
- if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
- goto again;
- if (bin_ind == UNDEFINED_BIN_IND)
- break;
- bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE;
- MARK_BIN_DELETED(tab, bin_ind);
- }
- curr_entry_ptr = &entries[bin];
- MARK_ENTRY_DELETED(curr_entry_ptr);
- tab->num_entries--;
- update_range_for_deleted(tab, bin);
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
- break;
+ if (packed_p) {
+ bin = find_entry(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto again;
+ if (bin == UNDEFINED_ENTRY_IND)
+ break;
+ }
+ else {
+ bin_ind = find_table_bin_ind(tab, hash, key);
+ if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
+ goto again;
+ if (bin_ind == UNDEFINED_BIN_IND)
+ break;
+ bin = get_bin(tab->bins, get_size_ind(tab), bin_ind) - ENTRY_BASE;
+ MARK_BIN_DELETED(tab, bin_ind);
+ }
+ curr_entry_ptr = &entries[bin];
+ MARK_ENTRY_DELETED(curr_entry_ptr);
+ tab->num_entries--;
+ update_range_for_deleted(tab, bin);
+ break;
}
}
}
-#ifdef ST_DEBUG
- st_check(tab);
-#endif
return 0;
}
@@ -1717,7 +1566,7 @@ int
st_foreach(st_table *tab, st_foreach_callback_func *func, st_data_t arg)
{
const struct functor f = { func, arg };
- return st_general_foreach(tab, apply_functor, NULL, (st_data_t)&f, FALSE);
+ return st_general_foreach(tab, apply_functor, 0, (st_data_t)&f, FALSE);
}
/* See comments for function st_delete_safe. */
@@ -1725,7 +1574,7 @@ int
st_foreach_check(st_table *tab, st_foreach_check_callback_func *func, st_data_t arg,
st_data_t never ATTRIBUTE_UNUSED)
{
- return st_general_foreach(tab, func, NULL, arg, TRUE);
+ return st_general_foreach(tab, func, 0, arg, TRUE);
}
/* Set up array KEYS by at most SIZE keys of head table TAB entries.
@@ -1778,7 +1627,6 @@ st_general_values(st_table *tab, st_data_t *values, st_index_t size)
values_start = values;
values_end = values + size;
bound = tab->entries_bound;
- st_assert(bound != 0);
for (i = tab->entries_start; i < bound; i++) {
if (values == values_end)
break;
@@ -2231,7 +2079,6 @@ st_rehash_linear(st_table *tab)
if (EXPECT(rebuilt_p, 0))
return TRUE;
if (eq_p) {
- st_assert(p < q);
*p = *q;
MARK_ENTRY_DELETED(q);
tab->num_entries--;
@@ -2252,7 +2099,6 @@ st_rehash_indexed(st_table *tab)
st_index_t const n = bins_size(tab);
unsigned int const size_ind = get_size_ind(tab);
st_index_t *bins = realloc(tab->bins, n);
- st_assert(bins != NULL);
tab->bins = bins;
initialize_bins(tab);
for (i = tab->entries_start; i < tab->entries_bound; i++) {
@@ -2282,7 +2128,6 @@ st_rehash_indexed(st_table *tab)
return TRUE;
if (eq_p) {
/* duplicated key; delete it */
- st_assert(q < p);
q->record = p->record;
MARK_ENTRY_DELETED(p);
tab->num_entries--;
@@ -2393,4 +2238,19 @@ rb_hash_bulk_insert_into_st_table(long argc, const VALUE *argv, VALUE hash)
else
st_insert_generic(tab, argc, argv, hash);
}
+
+// to iterate iv_index_tbl
+st_data_t
+rb_st_nth_key(st_table *tab, st_index_t index)
+{
+ if (LIKELY(tab->entries_start == 0 &&
+ tab->num_entries == tab->entries_bound &&
+ index < tab->num_entries)) {
+ return tab->entries[index].key;
+ }
+ else {
+ rb_bug("unreachable");
+ }
+}
+
#endif
diff --git a/strftime.c b/strftime.c
index 446be7d338..f4180fdb9e 100644
--- a/strftime.c
+++ b/strftime.c
@@ -47,10 +47,7 @@
* January 1996
*/
-#include "ruby/ruby.h"
-#include "ruby/encoding.h"
-#include "timev.h"
-#include "internal.h"
+#include "ruby/internal/config.h"
#ifndef GAWK
#include <stdio.h>
@@ -68,6 +65,14 @@
#endif
#include <math.h>
+#include "internal.h"
+#include "internal/string.h"
+#include "internal/util.h"
+#include "internal/vm.h"
+#include "ruby/encoding.h"
+#include "ruby/ruby.h"
+#include "timev.h"
+
/* defaults: season to taste */
#define SYSV_EXT 1 /* stuff in System V ascftime routine */
#define SUNOS_EXT 1 /* stuff in SunOS strftime routine */
@@ -261,8 +266,7 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len,
static const char ampm[][3] = { "AM", "PM", };
if (format == NULL || format_len == 0 || vtm == NULL) {
- err:
- return 0;
+ goto err;
}
if (enc &&
@@ -906,6 +910,9 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len,
rb_str_set_len(ftime, len);
rb_str_resize(ftime, len);
return ftime;
+
+err:
+ return 0;
}
static size_t
diff --git a/string.c b/string.c
index c6dec224f1..4d55406dea 100644
--- a/string.c
+++ b/string.c
@@ -11,37 +11,53 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/re.h"
-#include "internal.h"
-#include "encindex.h"
-#include "probes.h"
-#include "gc.h"
-#include "ruby_assert.h"
-#include "id.h"
-#include "debug_counter.h"
-#include "ruby/util.h"
-
-#define BEG(no) (regs->beg[(no)])
-#define END(no) (regs->end[(no)])
+#include "ruby/internal/config.h"
+#include <ctype.h>
#include <errno.h>
#include <math.h>
-#include <ctype.h>
#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+# include <unistd.h>
#endif
#if defined HAVE_CRYPT_R
# if defined HAVE_CRYPT_H
-# include <crypt.h>
+# include <crypt.h>
# endif
#elif !defined HAVE_CRYPT
# include "missing/crypt.h"
# define HAVE_CRYPT_R 1
#endif
+#include "debug_counter.h"
+#include "encindex.h"
+#include "gc.h"
+#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/compar.h"
+#include "internal/compilers.h"
+#include "internal/encoding.h"
+#include "internal/error.h"
+#include "internal/gc.h"
+#include "internal/numeric.h"
+#include "internal/object.h"
+#include "internal/proc.h"
+#include "internal/re.h"
+#include "internal/sanitizers.h"
+#include "internal/string.h"
+#include "internal/transcode.h"
+#include "probes.h"
+#include "ruby/encoding.h"
+#include "ruby/re.h"
+#include "ruby/util.h"
+#include "ruby_assert.h"
+#include "vm_sync.h"
+
+#define BEG(no) (regs->beg[(no)])
+#define END(no) (regs->end[(no)])
+
#undef rb_str_new
#undef rb_usascii_str_new
#undef rb_utf8_str_new
@@ -61,8 +77,6 @@
#undef rb_str_cat_cstr
#undef rb_fstring_cstr
-static VALUE rb_str_clear(VALUE str);
-
VALUE rb_cString;
VALUE rb_cSymbol;
@@ -166,6 +180,7 @@ VALUE rb_cSymbol;
#define STR_HEAP_PTR(str) (RSTRING(str)->as.heap.ptr)
#define STR_HEAP_SIZE(str) ((size_t)RSTRING(str)->as.heap.aux.capa + TERM_LEN(str))
+/* TODO: include the terminator size in capa. */
#define STR_ENC_GET(str) get_encoding(str)
@@ -184,7 +199,9 @@ VALUE rb_cSymbol;
static VALUE str_replace_shared_without_enc(VALUE str2, VALUE str);
static VALUE str_new_shared(VALUE klass, VALUE str);
static VALUE str_new_frozen(VALUE klass, VALUE orig);
+static VALUE str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding);
static VALUE str_new_static(VALUE klass, const char *ptr, long len, int encindex);
+static VALUE str_new(VALUE klass, const char *ptr, long len);
static void str_make_independent_expand(VALUE str, long len, long expand, const int termlen);
static inline void str_modifiable(VALUE str);
static VALUE rb_str_downcase(int argc, VALUE *argv, VALUE str);
@@ -197,6 +214,16 @@ str_make_independent(VALUE str)
str_make_independent_expand((str), len, 0L, termlen);
}
+static inline int str_dependent_p(VALUE str);
+
+void
+rb_str_make_independent(VALUE str)
+{
+ if (str_dependent_p(str)) {
+ str_make_independent(str);
+ }
+}
+
/* symbols for [up|down|swap]case/capitalize options */
static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
@@ -255,7 +282,7 @@ mustnot_wchar(VALUE str)
static int fstring_cmp(VALUE a, VALUE b);
-static VALUE register_fstring(VALUE str);
+static VALUE register_fstring(VALUE str, bool copy);
const struct st_hash_type rb_fstring_hash_type = {
fstring_cmp,
@@ -264,10 +291,16 @@ const struct st_hash_type rb_fstring_hash_type = {
#define BARE_STRING_P(str) (!FL_ANY_RAW(str, FL_EXIVAR) && RBASIC_CLASS(str) == rb_cString)
+struct fstr_update_arg {
+ VALUE fstr;
+ bool copy;
+};
+
static int
-fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int existing)
{
- VALUE *fstr = (VALUE *)arg;
+
+ struct fstr_update_arg *arg = (struct fstr_update_arg *)data;
VALUE str = (VALUE)*key;
if (existing) {
@@ -275,25 +308,33 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existi
* at next time */
if (rb_objspace_garbage_object_p(str)) {
- *fstr = Qundef;
+ arg->fstr = Qundef;
return ST_DELETE;
}
- *fstr = str;
+ arg->fstr = str;
return ST_STOP;
}
else {
if (FL_TEST_RAW(str, STR_FAKESTR)) {
- str = str_new_static(rb_cString, RSTRING(str)->as.heap.ptr,
- RSTRING(str)->as.heap.len,
- ENCODING_GET(str));
+ if (arg->copy) {
+ VALUE new_str = str_new(rb_cString, RSTRING(str)->as.heap.ptr, RSTRING(str)->as.heap.len);
+ rb_enc_copy(new_str, str);
+ str = new_str;
+ }
+ else {
+ str = str_new_static(rb_cString, RSTRING(str)->as.heap.ptr,
+ RSTRING(str)->as.heap.len,
+ ENCODING_GET(str));
+ }
OBJ_FREEZE_RAW(str);
}
else {
- str = str_new_frozen(rb_cString, str);
+ if (!OBJ_FROZEN(str))
+ str = str_new_frozen(rb_cString, str);
if (STR_SHARED_P(str)) { /* str should not be shared */
/* shared substring */
- str_make_independent(str);
+ str_make_independent(str);
assert(OBJ_FROZEN(str));
}
if (!BARE_STRING_P(str)) {
@@ -302,7 +343,7 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, int existi
}
RBASIC(str)->flags |= RSTRING_FSTR;
- *key = *value = *fstr = str;
+ *key = *value = arg->fstr = str;
return ST_CONTINUE;
}
}
@@ -334,7 +375,7 @@ rb_fstring(VALUE str)
if (!OBJ_FROZEN(str))
rb_str_resize(str, RSTRING_LEN(str));
- fstr = register_fstring(str);
+ fstr = register_fstring(str, FALSE);
if (!bare) {
str_replace_shared_without_enc(str, fstr);
@@ -345,22 +386,26 @@ rb_fstring(VALUE str)
}
static VALUE
-register_fstring(VALUE str)
+register_fstring(VALUE str, bool copy)
{
- VALUE ret;
- st_table *frozen_strings = rb_vm_fstring_table();
+ struct fstr_update_arg args;
+ args.copy = copy;
- do {
- ret = str;
- st_update(frozen_strings, (st_data_t)str,
- fstr_update_callback, (st_data_t)&ret);
- } while (ret == Qundef);
-
- assert(OBJ_FROZEN(ret));
- assert(!FL_TEST_RAW(ret, STR_FAKESTR));
- assert(!FL_TEST_RAW(ret, FL_EXIVAR));
- assert(RBASIC_CLASS(ret) == rb_cString);
- return ret;
+ RB_VM_LOCK_ENTER();
+ {
+ st_table *frozen_strings = rb_vm_fstring_table();
+ do {
+ args.fstr = str;
+ st_update(frozen_strings, (st_data_t)str, fstr_update_callback, (st_data_t)&args);
+ } while (args.fstr == Qundef);
+ }
+ RB_VM_LOCK_LEAVE();
+
+ assert(OBJ_FROZEN(args.fstr));
+ assert(!FL_TEST_RAW(args.fstr, STR_FAKESTR));
+ assert(!FL_TEST_RAW(args.fstr, FL_EXIVAR));
+ assert(RBASIC_CLASS(args.fstr) == rb_cString);
+ return args.fstr;
}
static VALUE
@@ -396,14 +441,14 @@ MJIT_FUNC_EXPORTED VALUE
rb_fstring_new(const char *ptr, long len)
{
struct RString fake_str;
- return register_fstring(setup_fake_str(&fake_str, ptr, len, ENCINDEX_US_ASCII));
+ return register_fstring(setup_fake_str(&fake_str, ptr, len, ENCINDEX_US_ASCII), FALSE);
}
VALUE
rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc)
{
struct RString fake_str;
- return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc));
+ return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), FALSE);
}
VALUE
@@ -653,6 +698,24 @@ rb_enc_cr_str_exact_copy(VALUE dest, VALUE src)
ENC_CODERANGE_SET(dest, ENC_CODERANGE(src));
}
+static int
+enc_coderange_scan(VALUE str, rb_encoding *enc, int encidx)
+{
+ if (rb_enc_mbminlen(enc) > 1 && rb_enc_dummy_p(enc) &&
+ rb_enc_mbminlen(enc = get_actual_encoding(encidx, str)) == 1) {
+ return ENC_CODERANGE_BROKEN;
+ }
+ else {
+ return coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc);
+ }
+}
+
+int
+rb_enc_str_coderange_scan(VALUE str, rb_encoding *enc)
+{
+ return enc_coderange_scan(str, enc, rb_enc_to_index(enc));
+}
+
int
rb_enc_str_coderange(VALUE str)
{
@@ -661,14 +724,7 @@ rb_enc_str_coderange(VALUE str)
if (cr == ENC_CODERANGE_UNKNOWN) {
int encidx = ENCODING_GET(str);
rb_encoding *enc = rb_enc_from_index(encidx);
- if (rb_enc_mbminlen(enc) > 1 && rb_enc_dummy_p(enc) &&
- rb_enc_mbminlen(enc = get_actual_encoding(encidx, str)) == 1) {
- cr = ENC_CODERANGE_BROKEN;
- }
- else {
- cr = coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str),
- enc);
- }
+ cr = enc_coderange_scan(str, enc, encidx);
ENC_CODERANGE_SET(str, cr);
}
return cr;
@@ -895,14 +951,14 @@ rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc)
VALUE
rb_tainted_str_new(const char *ptr, long len)
{
- rb_warning("rb_tainted_str_new is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("rb_tainted_str_new", "3.2");
return rb_str_new(ptr, len);
}
VALUE
rb_tainted_str_new_cstr(const char *ptr)
{
- rb_warning("rb_tainted_str_new_cstr is deprecated and will be removed in Ruby 3.2.");
+ rb_warn_deprecated_to_remove("rb_tainted_str_new_cstr", "3.2");
return rb_str_new_cstr(ptr);
}
@@ -910,6 +966,15 @@ static VALUE str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long
rb_encoding *from, rb_encoding *to,
int ecflags, VALUE ecopts);
+static inline bool
+is_enc_ascii_string(VALUE str, rb_encoding *enc)
+{
+ int encidx = rb_enc_to_index(enc);
+ if (rb_enc_get_index(str) == encidx)
+ return is_ascii_string(str);
+ return enc_coderange_scan(str, enc, encidx) == ENC_CODERANGE_7BIT;
+}
+
VALUE
rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
{
@@ -920,7 +985,7 @@ rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags,
if (!to) return str;
if (!from) from = rb_enc_get(str);
if (from == to) return str;
- if ((rb_enc_asciicompat(to) && is_ascii_string(str)) ||
+ if ((rb_enc_asciicompat(to) && is_enc_ascii_string(str, from)) ||
to == rb_ascii8bit_encoding()) {
if (STR_ENC_GET(str) != to) {
str = rb_str_dup(str);
@@ -1206,11 +1271,18 @@ rb_str_new_frozen(VALUE orig)
return str_new_frozen(rb_obj_class(orig), orig);
}
+static VALUE
+rb_str_new_frozen_String(VALUE orig)
+{
+ if (OBJ_FROZEN(orig) && rb_obj_class(orig) == rb_cString) return orig;
+ return str_new_frozen(rb_cString, orig);
+}
+
VALUE
rb_str_tmp_frozen_acquire(VALUE orig)
{
if (OBJ_FROZEN_RAW(orig)) return orig;
- return str_new_frozen(0, orig);
+ return str_new_frozen_buffer(0, orig, FALSE);
}
void
@@ -1242,6 +1314,12 @@ rb_str_tmp_frozen_release(VALUE orig, VALUE tmp)
static VALUE
str_new_frozen(VALUE klass, VALUE orig)
{
+ return str_new_frozen_buffer(klass, orig, TRUE);
+}
+
+static VALUE
+str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding)
+{
VALUE str;
if (STR_EMBED_P(orig)) {
@@ -1289,7 +1367,7 @@ str_new_frozen(VALUE klass, VALUE orig)
}
}
- rb_enc_cr_str_exact_copy(str, orig);
+ if (copy_encoding) rb_enc_cr_str_exact_copy(str, orig);
OBJ_FREEZE(str);
return str;
}
@@ -1301,9 +1379,9 @@ rb_str_new_with_class(VALUE obj, const char *ptr, long len)
}
static VALUE
-str_new_empty(VALUE str)
+str_new_empty_String(VALUE str)
{
- VALUE v = rb_str_new_with_class(str, 0, 0);
+ VALUE v = rb_str_new(0, 0);
rb_enc_copy(v, str);
return v;
}
@@ -1316,6 +1394,7 @@ rb_str_buf_new(long capa)
{
VALUE str = str_alloc(rb_cString);
+ if (capa <= RSTRING_EMBED_LEN_MAX) return str;
if (capa < STR_BUF_MIN_SIZE) {
capa = STR_BUF_MIN_SIZE;
}
@@ -1350,8 +1429,13 @@ rb_str_free(VALUE str)
{
if (FL_TEST(str, RSTRING_FSTR)) {
st_data_t fstr = (st_data_t)str;
- st_delete(rb_vm_fstring_table(), &fstr, NULL);
- RB_DEBUG_COUNTER_INC(obj_str_fstr);
+
+ RB_VM_LOCK_ENTER();
+ {
+ st_delete(rb_vm_fstring_table(), &fstr, NULL);
+ RB_DEBUG_COUNTER_INC(obj_str_fstr);
+ }
+ RB_VM_LOCK_LEAVE();
}
if (STR_EMBED_P(str)) {
@@ -1479,7 +1563,14 @@ str_replace(VALUE str, VALUE str2)
}
static inline VALUE
-str_duplicate(VALUE klass, VALUE str)
+ec_str_alloc(struct rb_execution_context_struct *ec, VALUE klass)
+{
+ RB_EC_NEWOBJ_OF(ec, str, struct RString, klass, T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0));
+ return (VALUE)str;
+}
+
+static inline VALUE
+str_duplicate_setup(VALUE klass, VALUE str, VALUE dup)
{
enum {embed_size = RSTRING_EMBED_LEN_MAX + 1};
const VALUE flag_mask =
@@ -1488,7 +1579,7 @@ str_duplicate(VALUE klass, VALUE str)
FL_FREEZE
;
VALUE flags = FL_TEST_RAW(str, flag_mask);
- VALUE dup = str_alloc(klass);
+ int encidx = 0;
MEMCPY(RSTRING(dup)->as.ary, RSTRING(str)->as.ary,
char, embed_size);
if (flags & STR_NOEMBED) {
@@ -1508,10 +1599,29 @@ str_duplicate(VALUE klass, VALUE str)
char, embed_size);
}
}
+ if ((flags & ENCODING_MASK) == (ENCODING_INLINE_MAX<<ENCODING_SHIFT)) {
+ encidx = rb_enc_get_index(str);
+ flags &= ~ENCODING_MASK;
+ }
FL_SET_RAW(dup, flags & ~FL_FREEZE);
+ if (encidx) rb_enc_associate_index(dup, encidx);
return dup;
}
+static inline VALUE
+ec_str_duplicate(struct rb_execution_context_struct *ec, VALUE klass, VALUE str)
+{
+ VALUE dup = ec_str_alloc(ec, klass);
+ return str_duplicate_setup(klass, str, dup);
+}
+
+static inline VALUE
+str_duplicate(VALUE klass, VALUE str)
+{
+ VALUE dup = str_alloc(klass);
+ return str_duplicate_setup(klass, str, dup);
+}
+
VALUE
rb_str_dup(VALUE str)
{
@@ -1525,23 +1635,55 @@ rb_str_resurrect(VALUE str)
return str_duplicate(rb_cString, str);
}
+VALUE
+rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str)
+{
+ RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
+ return ec_str_duplicate(ec, rb_cString, str);
+}
+
/*
* call-seq:
- * String.new(str="") -> new_str
- * String.new(str="", encoding: enc) -> new_str
- * String.new(str="", capacity: size) -> new_str
+ * String.new(string = '') -> new_string
+ * String.new(string = '', encoding: encoding) -> new_string
+ * String.new(string = '', capacity: size) -> new_string
+ *
+ * Returns a new \String that is a copy of +string+.
+ *
+ * With no arguments, returns the empty string with the Encoding <tt>ASCII-8BIT</tt>:
+ * s = String.new
+ * s # => ""
+ * s.encoding # => #<Encoding:ASCII-8BIT>
+ *
+ * With the single \String argument +string+, returns a copy of +string+
+ * with the same encoding as +string+:
+ * s = String.new("Que veut dire \u{e7}a?")
+ * s # => "Que veut dire \u{e7}a?"
+ * s.encoding # => #<Encoding:UTF-8>
+ *
+ * Literal strings like <tt>""</tt> or here-documents always use
+ * {script encoding}[Encoding.html#class-Encoding-label-Script+encoding], unlike String.new.
+ *
+ * With keyword +encoding+, returns a copy of +str+
+ * with the specified encoding:
+ * s = String.new(encoding: 'ASCII')
+ * s.encoding # => #<Encoding:US-ASCII>
+ * s = String.new('foo', encoding: 'ASCII')
+ * s.encoding # => #<Encoding:US-ASCII>
*
- * Returns a new string object containing a copy of <i>str</i>.
+ * Note that these are equivalent:
+ * s0 = String.new('foo', encoding: 'ASCII')
+ * s1 = 'foo'.force_encoding('ASCII')
+ * s0.encoding == s1.encoding # => true
*
- * The optional <i>encoding</i> keyword argument specifies the encoding
- * of the new string.
- * If not specified, the encoding of <i>str</i> is used
- * (or ASCII-8BIT, if <i>str</i> is not specified).
+ * With keyword +capacity+, returns a copy of +str+;
+ * the given +capacity+ may set the size of the internal buffer,
+ * which may affect performance:
+ * String.new(capacity: 1) # => ""
+ * String.new(capacity: 4096) # => ""
*
- * The optional <i>capacity</i> keyword argument specifies the size
- * of the internal buffer.
- * This may improve performance, when the string will be concatenated many
- * times (causing many realloc calls).
+ * The +string+, +encoding+, and +capacity+ arguments may all be used together:
+ * String.new('hello', encoding: 'UTF-8', capacity: 25)
*/
static VALUE
@@ -1629,7 +1771,7 @@ rb_str_init(int argc, VALUE *argv, VALUE str)
/*
* UTF-8 leading bytes have either 0xxxxxxx or 11xxxxxx
- * bit representation. (see http://en.wikipedia.org/wiki/UTF-8)
+ * bit representation. (see https://en.wikipedia.org/wiki/UTF-8)
* Therefore, the following pseudocode can detect UTF-8 leading bytes.
*
* if (!(byte & 0x80))
@@ -1833,10 +1975,15 @@ rb_str_strlen(VALUE str)
/*
* call-seq:
- * str.length -> integer
- * str.size -> integer
+ * string.length -> integer
*
- * Returns the character length of <i>str</i>.
+ * Returns the count of characters (not bytes) in +self+:
+ * "\x80\u3042".length # => 2
+ * "hello".length # => 5
+ *
+ * String#size is an alias for String#length.
+ *
+ * Related: String#bytesize.
*/
VALUE
@@ -1847,12 +1994,13 @@ rb_str_length(VALUE str)
/*
* call-seq:
- * str.bytesize -> integer
+ * string.bytesize -> integer
*
- * Returns the length of +str+ in bytes.
+ * Returns the count of bytes in +self+:
+ * "\x80\u3042".bytesize # => 4
+ * "hello".bytesize # => 5
*
- * "\x80\u3042".bytesize #=> 4
- * "hello".bytesize #=> 5
+ * Related: String#length.
*/
static VALUE
@@ -1863,13 +2011,12 @@ rb_str_bytesize(VALUE str)
/*
* call-seq:
- * str.empty? -> true or false
- *
- * Returns <code>true</code> if <i>str</i> has a length of zero.
+ * string.empty? -> true or false
*
- * "hello".empty? #=> false
- * " ".empty? #=> false
- * "".empty? #=> true
+ * Returns +true+ if the length of +self+ is zero, +false+ otherwise:
+ * "hello".empty? # => false
+ * " ".empty? # => false
+ * "".empty? # => true
*/
static VALUE
@@ -1882,12 +2029,10 @@ rb_str_empty(VALUE str)
/*
* call-seq:
- * str + other_str -> new_str
+ * string + other_string -> new_string
*
- * Concatenation---Returns a new String containing
- * <i>other_str</i> concatenated to <i>str</i>.
- *
- * "Hello from " + self.to_s #=> "Hello from main"
+ * Returns a new \String containing +other_string+ concatenated to +self+:
+ * "Hello from " + self.to_s # => "Hello from main"
*/
VALUE
@@ -1953,13 +2098,11 @@ rb_str_opt_plus(VALUE str1, VALUE str2)
/*
* call-seq:
- * str * integer -> new_str
- *
- * Copy --- Returns a new String containing +integer+ copies of the receiver.
- * +integer+ must be greater than or equal to 0.
+ * string * integer -> new_string
*
- * "Ho! " * 3 #=> "Ho! Ho! Ho! "
- * "Ho! " * 0 #=> ""
+ * Returns a new \String containing +integer+ copies of +self+:
+ * "Ho! " * 3 # => "Ho! Ho! Ho! "
+ * "Ho! " * 0 # => ""
*/
VALUE
@@ -1971,10 +2114,10 @@ rb_str_times(VALUE str, VALUE times)
int termlen;
if (times == INT2FIX(1)) {
- return rb_str_dup(str);
+ return str_duplicate(rb_cString, str);
}
if (times == INT2FIX(0)) {
- str2 = str_alloc(rb_obj_class(str));
+ str2 = str_alloc(rb_cString);
rb_enc_copy(str2, str);
return str2;
}
@@ -1983,7 +2126,7 @@ rb_str_times(VALUE str, VALUE times)
rb_raise(rb_eArgError, "negative argument");
}
if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
- str2 = str_alloc(rb_obj_class(str));
+ str2 = str_alloc(rb_cString);
if (!STR_EMBEDDABLE_P(len, 1)) {
RSTRING(str2)->as.heap.aux.capa = len;
RSTRING(str2)->as.heap.ptr = ZALLOC_N(char, (size_t)len + 1);
@@ -1999,7 +2142,7 @@ rb_str_times(VALUE str, VALUE times)
len *= RSTRING_LEN(str);
termlen = TERM_LEN(str);
- str2 = str_new0(rb_obj_class(str), 0, len, termlen);
+ str2 = str_new0(rb_cString, 0, len, termlen);
ptr2 = RSTRING_PTR(str2);
if (len) {
n = RSTRING_LEN(str);
@@ -2019,17 +2162,17 @@ rb_str_times(VALUE str, VALUE times)
/*
* call-seq:
- * str % arg -> new_str
+ * string % object -> new_string
*
- * Format---Uses <i>str</i> as a format specification, and returns
- * the result of applying it to <i>arg</i>. If the format
- * specification contains more than one substitution, then <i>arg</i>
- * must be an Array or Hash containing the values to be
- * substituted. See Kernel#sprintf for details of the format string.
+ * Returns the result of formatting +object+ into the format specification +self+
+ * (see Kernel#sprintf for formatting details):
+ * "%05d" % 123 # => "00123"
*
- * "%05d" % 123 #=> "00123"
- * "%-5s: %016x" % [ "ID", self.object_id ] #=> "ID : 00002b054ec93168"
- * "foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar"
+ * If +self+ contains multiple substitutions, +object+ must be
+ * an \Array or \Hash containing the values to be substituted:
+ * "%-5s: %016x" % [ "ID", self.object_id ] # => "ID : 00002b054ec93168"
+ * "foo = %{foo}" % {foo: 'bar'} # => "foo = bar"
+ * "foo = %{foo}, baz = %{baz}" % {foo: 'bar', baz: 'bat'} # => "foo = bar, baz = bat"
*/
static VALUE
@@ -2319,14 +2462,16 @@ rb_check_string_type(VALUE str)
/*
* call-seq:
- * String.try_convert(obj) -> string or nil
+ * String.try_convert(object) -> object, new_string, or nil
*
- * Try to convert <i>obj</i> into a String, using to_str method.
- * Returns converted string or nil if <i>obj</i> cannot be converted
- * for any reason.
+ * If +object+ is a \String object, returns +object+.
*
- * String.try_convert("str") #=> "str"
- * String.try_convert(/re/) #=> nil
+ * 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.
*/
static VALUE
rb_str_s_try_convert(VALUE dummy, VALUE str)
@@ -2478,13 +2623,13 @@ rb_str_subseq(VALUE str, long beg, long len)
if (!STR_EMBEDDABLE_P(len, TERM_LEN(str)) &&
SHARABLE_SUBSTRING_P(beg, len, RSTRING_LEN(str))) {
long olen;
- str2 = rb_str_new_shared(rb_str_new_frozen(str));
+ str2 = rb_str_new_shared(rb_str_new_frozen_String(str));
RSTRING(str2)->as.heap.ptr += beg;
olen = RSTRING(str2)->as.heap.len;
if (olen > len) RSTRING(str2)->as.heap.len = len;
}
else {
- str2 = rb_str_new_with_class(str, RSTRING_PTR(str)+beg, len);
+ str2 = rb_str_new(RSTRING_PTR(str)+beg, len);
RB_GC_GUARD(str);
}
@@ -2597,14 +2742,14 @@ str_substr(VALUE str, long beg, long len, int empty)
SHARABLE_SUBSTRING_P(p, len, RSTRING_END(str))) {
long ofs = p - RSTRING_PTR(str);
str2 = rb_str_new_frozen(str);
- str2 = str_new_shared(rb_obj_class(str2), str2);
+ str2 = str_new_shared(rb_cString, str2);
RSTRING(str2)->as.heap.ptr += ofs;
RSTRING(str2)->as.heap.len = len;
ENC_CODERANGE_CLEAR(str2);
}
else {
if (!len && !empty) return Qnil;
- str2 = rb_str_new_with_class(str, p, len);
+ str2 = rb_str_new(p, len);
RB_GC_GUARD(str);
}
rb_enc_cr_str_copy_for_substr(str2, str);
@@ -2623,11 +2768,11 @@ rb_str_freeze(VALUE str)
/*
* call-seq:
- * +str -> str (mutable)
+ * +string -> new_string or self
*
- * If the string is frozen, then return duplicated mutable string.
+ * Returns +self+ if +self+ is not frozen.
*
- * If the string is not frozen, then return the string itself.
+ * Otherwise. returns <tt>self.dup</tt>, which is not frozen.
*/
static VALUE
str_uplus(VALUE str)
@@ -2642,11 +2787,11 @@ str_uplus(VALUE str)
/*
* call-seq:
- * -str -> str (frozen)
+ * -string -> frozen_string
*
* Returns a frozen, possibly pre-existing copy of the string.
*
- * The string will be deduplicated as long as it does not have
+ * The returned \String will be deduplicated as long as it does not have
* any instance variables set on it.
*/
static VALUE
@@ -2875,9 +3020,7 @@ rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len,
ptr_cr != ENC_CODERANGE_7BIT) {
str_enc = rb_enc_from_index(str_encindex);
ptr_enc = rb_enc_from_index(ptr_encindex);
- incompatible:
- rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
- rb_enc_name(str_enc), rb_enc_name(ptr_enc));
+ goto incompatible;
}
if (str_cr == ENC_CODERANGE_UNKNOWN) {
@@ -2913,6 +3056,11 @@ rb_enc_cr_str_buf_cat(VALUE str, const char *ptr, long len,
str_buf_cat(str, ptr, len);
ENCODING_CODERANGE_SET(str, res_encindex, res_cr);
return str;
+
+ incompatible:
+ rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s",
+ rb_enc_name(str_enc), rb_enc_name(ptr_enc));
+ UNREACHABLE_RETURN(Qundef);
}
VALUE
@@ -3007,23 +3155,20 @@ rb_str_concat_literals(size_t num, const VALUE *strary)
/*
* call-seq:
- * str.concat(obj1, obj2, ...) -> str
+ * string.concat(*objects) -> string
*
- * Concatenates the given object(s) to <i>str</i>. If an object is an
- * Integer, it is considered a codepoint and converted to a character
- * before concatenation.
+ * Concatenates each object in +objects+ to +self+ and returns +self+:
*
- * +concat+ can take multiple arguments, and all the arguments are
- * concatenated in order.
+ * s = 'foo'
+ * s.concat('bar', 'baz') # => "foobarbaz"
+ * s # => "foobarbaz"
*
- * a = "hello "
- * a.concat("world", 33) #=> "hello world!"
- * a #=> "hello world!"
+ * For each given object +object+ that is an \Integer,
+ * the value is considered a codepoint and converted to a character before concatenation:
+ * s = 'foo'
+ * s.concat(32, 'bar', 32, 'baz') # => "foo bar baz"
*
- * b = "sn"
- * b.concat("_", b, "_", b) #=> "sn_sn_sn"
- *
- * See also String#<<, which takes a single argument.
+ * Related: String#<<, which takes a single argument.
*/
static VALUE
rb_str_concat_multi(int argc, VALUE *argv, VALUE str)
@@ -3048,18 +3193,20 @@ rb_str_concat_multi(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str << obj -> str
- * str << integer -> str
+ * string << object -> string
+ *
+ * Concatenates +object+ to +self+ and returns +self+:
*
- * Appends the given object to <i>str</i>. If the object is an
- * Integer, it is considered a codepoint and converted to a character
- * before being appended.
+ * s = 'foo'
+ * s << 'bar' # => "foobar"
+ * s # => "foobar"
*
- * a = "hello "
- * a << "world" #=> "hello world"
- * a << 33 #=> "hello world!"
+ * If +object+ is an \Integer,
+ * the value is considered a codepoint and converted to a character before concatenation:
+ * s = 'foo'
+ * s << 33 # => "foo!"
*
- * See also String#concat, which takes multiple arguments.
+ * Related: String#concat, which takes multiple arguments.
*/
VALUE
rb_str_concat(VALUE str1, VALUE str2)
@@ -3127,15 +3274,14 @@ rb_str_concat(VALUE str1, VALUE str2)
/*
* call-seq:
- * str.prepend(other_str1, other_str2, ...) -> str
+ * string.prepend(*other_strings) -> string
*
- * Prepend---Prepend the given strings to <i>str</i>.
+ * Prepends each string in +other_strings+ to +self+ and returns +self+:
+ * s = 'foo'
+ * s.prepend('bar', 'baz') # => "barbazfoo"
+ * s # => "barbazfoo"
*
- * a = "!"
- * a.prepend("hello ", "world") #=> "hello world!"
- * a #=> "hello world!"
- *
- * See also String#concat.
+ * Related: String#concat.
*/
static VALUE
@@ -3183,11 +3329,10 @@ rb_str_hash_cmp(VALUE str1, VALUE str2)
/*
* call-seq:
- * str.hash -> integer
- *
- * Returns a hash based on the string's length, content and encoding.
+ * string.hash -> integer
*
- * See also Object#hash.
+ * Returns the integer hash value for +self+.
+ * The value is based on the length, content and encoding of +self+.
*/
static VALUE
@@ -3252,15 +3397,21 @@ rb_str_cmp(VALUE str1, VALUE str2)
/*
* call-seq:
- * str == obj -> true or false
- * str === obj -> true or false
+ * string == object -> true or false
+ * string === object -> true or false
*
- * Equality---Returns whether +str+ == +obj+, similar to Object#==.
+ * Returns +true+ if +object+ has the same length and content;
+ * as +self+; +false+ otherwise:
+ * s = 'foo'
+ * s == 'foo' # => true
+ * s == 'food' # => false
+ * s == 'FOO' # => false
*
- * If +obj+ is not an instance of String but responds to +to_str+, then the
- * two strings are compared using <code>obj.==</code>.
+ * Returns +false+ if the two strings' encodings are not compatible:
+ * "\u{e4 f6 fc}".encode("ISO-8859-1") == ("\u{c4 d6 dc}") # => false
*
- * Otherwise, returns similarly to String#eql?, comparing length and content.
+ * If +object+ is not an instance of \String but responds to +to_str+, then the
+ * two strings are compared using <code>object.==</code>.
*/
VALUE
@@ -3278,9 +3429,17 @@ rb_str_equal(VALUE str1, VALUE str2)
/*
* call-seq:
- * str.eql?(other) -> true or false
+ * string.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
*
- * Two strings are equal if they have the same length and content.
+ * Returns +false+ if the two strings' encodings are not compatible:
+ * "\u{e4 f6 fc}".encode("ISO-8859-1").eql?("\u{c4 d6 dc}") # => false
*/
MJIT_FUNC_EXPORTED VALUE
@@ -3293,27 +3452,21 @@ rb_str_eql(VALUE str1, VALUE str2)
/*
* call-seq:
- * string <=> other_string -> -1, 0, +1, or nil
- *
- * Comparison---Returns -1, 0, +1, or +nil+ depending on whether +string+ is
- * less than, equal to, or greater than +other_string+.
- *
- * +nil+ is returned if the two values are incomparable.
- *
- * If the strings are of different lengths, and the strings are equal when
- * compared up to the shortest length, then the longer string is considered
- * greater than the shorter one.
+ * string <=> other_string -> -1, 0, 1, or nil
*
- * <code><=></code> is the basis for the methods <code><</code>,
- * <code><=</code>, <code>></code>, <code>>=</code>, and
- * <code>between?</code>, included from module Comparable. The method
- * String#== does not use Comparable#==.
+ * Compares +self+ and +other_string+, returning:
+ * - -1 if +other_string+ is larger.
+ * - 0 if the two are equal.
+ * - 1 if +other_string+ is smaller.
+ * - +nil+ if the two are incomparable.
*
- * "abcdef" <=> "abcde" #=> 1
- * "abcdef" <=> "abcdef" #=> 0
- * "abcdef" <=> "abcdefg" #=> -1
- * "abcdef" <=> "ABCDEF" #=> 1
- * "abcdef" <=> 1 #=> nil
+ * Examples:
+ * 'foo' <=> 'foo' # => 0
+ * 'foo' <=> 'food' # => -1
+ * 'food' <=> 'foo' # => 1
+ * 'FOO' <=> 'foo' # => -1
+ * 'foo' <=> 'FOO' # => 1
+ * 'foo' <=> 1 # => nil
*/
static VALUE
@@ -3333,22 +3486,21 @@ static VALUE str_casecmp_p(VALUE str1, VALUE str2);
/*
* call-seq:
- * str.casecmp(other_str) -> -1, 0, +1, or nil
+ * str.casecmp(other_str) -> -1, 0, 1, or nil
*
- * Case-insensitive version of String#<=>.
- * Currently, case-insensitivity only works on characters A-Z/a-z,
- * not all of Unicode. This is different from String#casecmp?.
+ * Compares +self+ and +other_string+, ignoring case, and returning:
+ * - -1 if +other_string+ is larger.
+ * - 0 if the two are equal.
+ * - 1 if +other_string+ is smaller.
+ * - +nil+ if the two are incomparable.
*
- * "aBcDeF".casecmp("abcde") #=> 1
- * "aBcDeF".casecmp("abcdef") #=> 0
- * "aBcDeF".casecmp("abcdefg") #=> -1
- * "abcdef".casecmp("ABCDEF") #=> 0
- *
- * +nil+ is returned if the two strings have incompatible encodings,
- * or if +other_str+ is not a string.
- *
- * "foo".casecmp(2) #=> nil
- * "\u{e4 f6 fc}".encode("ISO-8859-1").casecmp("\u{c4 d6 dc}") #=> nil
+ * Examples:
+ * 'foo'.casecmp('foo') # => 0
+ * 'foo'.casecmp('food') # => -1
+ * 'food'.casecmp('foo') # => 1
+ * 'FOO'.casecmp('foo') # => 0
+ * 'foo'.casecmp('FOO') # => 0
+ * 'foo'.casecmp(1) # => nil
*/
static VALUE
@@ -3420,22 +3572,18 @@ str_casecmp(VALUE str1, VALUE str2)
/*
* call-seq:
- * str.casecmp?(other_str) -> true, false, or nil
- *
- * Returns +true+ if +str+ and +other_str+ are equal after
- * Unicode case folding, +false+ if they are not equal.
+ * string.casecmp?(other_string) -> true, false, or nil
*
- * "aBcDeF".casecmp?("abcde") #=> false
- * "aBcDeF".casecmp?("abcdef") #=> true
- * "aBcDeF".casecmp?("abcdefg") #=> false
- * "abcdef".casecmp?("ABCDEF") #=> true
- * "\u{e4 f6 fc}".casecmp?("\u{c4 d6 dc}") #=> true
+ * 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') # => true
+ * 'FOO'.casecmp?('foo') # => true
+ * 'foo'.casecmp?('FOO') # => true
*
- * +nil+ is returned if the two strings have incompatible encodings,
- * or if +other_str+ is not a string.
- *
- * "foo".casecmp?(2) #=> nil
- * "\u{e4 f6 fc}".encode("ISO-8859-1").casecmp?("\u{c4 d6 dc}") #=> nil
+ * Returns +nil+ if the two values are incomparable:
+ * 'foo'.casecmp?(1) # => nil
*/
static VALUE
@@ -3494,7 +3642,6 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte)
{
const char *str_ptr, *str_ptr_end, *sub_ptr;
long str_len, sub_len;
- int single_byte = single_byte_optimizable(str);
rb_encoding *enc;
enc = rb_enc_check(str, sub);
@@ -3510,6 +3657,7 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte)
if (offset != 0) {
long str_len_char, sub_len_char;
+ int single_byte = single_byte_optimizable(str);
str_len_char = (in_byte || single_byte) ? str_len : str_strlen(str, enc);
sub_len_char = in_byte ? sub_len : str_strlen(sub, enc);
if (offset < 0) {
@@ -3529,19 +3677,36 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte)
/*
* call-seq:
- * str.index(substring [, offset]) -> integer or nil
- * str.index(regexp [, offset]) -> integer or nil
+ * string.index(substring, offset = 0) -> integer or nil
+ * string.index(regexp, offset = 0) -> integer or nil
+ *
+ * Returns the \Integer index of the first occurrence of the given +substring+,
+ * or +nil+ if none found:
+ * 'foo'.index('f') # => 0
+ * 'foo'.index('o') # => 1
+ * 'foo'.index('oo') # => 1
+ * 'foo'.index('ooo') # => nil
*
- * Returns the index of the first occurrence of the given <i>substring</i> or
- * pattern (<i>regexp</i>) in <i>str</i>. Returns <code>nil</code> if not
- * found. If the second parameter is present, it specifies the position in the
- * string to begin the search.
+ * Returns the \Integer index of the first match for the given \Regexp +regexp+,
+ * or +nil+ if none found:
+ * 'foo'.index(/f/) # => 0
+ * 'foo'.index(/o/) # => 1
+ * 'foo'.index(/oo/) # => 1
+ * 'foo'.index(/ooo/) # => nil
*
- * "hello".index('e') #=> 1
- * "hello".index('lo') #=> 3
- * "hello".index('a') #=> nil
- * "hello".index(?e) #=> 1
- * "hello".index(/[aeiou]/, -3) #=> 4
+ * \Integer argument +offset+, if given, specifies the position in the
+ * string to begin the search:
+ * 'foo'.index('o', 1) # => 1
+ * 'foo'.index('o', 2) # => 2
+ * 'foo'.index('o', 3) # => nil
+ *
+ * If +offset+ is negative, counts backward from the end of +self+:
+ * 'foo'.index('o', -1) # => 2
+ * 'foo'.index('o', -2) # => 1
+ * 'foo'.index('o', -3) # => 1
+ * 'foo'.index('o', -4) # => nil
+ *
+ * Related: String#rindex
*/
static VALUE
@@ -3567,34 +3732,25 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)
}
}
- if (SPECIAL_CONST_P(sub)) goto generic;
- switch (BUILTIN_TYPE(sub)) {
- case T_REGEXP:
+ if (RB_TYPE_P(sub, T_REGEXP)) {
if (pos > str_strlen(str, NULL))
return Qnil;
pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
rb_enc_check(str, sub), single_byte_optimizable(str));
- pos = rb_reg_search(sub, str, pos, 0);
- pos = rb_str_sublen(str, pos);
- break;
-
- generic:
- default: {
- VALUE tmp;
-
- tmp = rb_check_string_type(sub);
- if (NIL_P(tmp)) {
- rb_raise(rb_eTypeError, "type mismatch: %s given",
- rb_obj_classname(sub));
- }
- sub = tmp;
- }
- /* fall through */
- case T_STRING:
+ if (rb_reg_search(sub, str, pos, 0) < 0) {
+ return Qnil;
+ } else {
+ VALUE match = rb_backref_get();
+ struct re_registers *regs = RMATCH_REGS(match);
+ pos = rb_str_sublen(str, BEG(0));
+ return LONG2NUM(pos);
+ }
+ }
+ else {
+ StringValue(sub);
pos = rb_str_index(str, sub, pos);
pos = rb_str_sublen(str, pos);
- break;
}
if (pos == -1) return Qnil;
@@ -3690,23 +3846,57 @@ rb_str_rindex(VALUE str, VALUE sub, long pos)
return str_rindex(str, sub, s, pos, enc);
}
-
/*
* call-seq:
- * str.rindex(substring [, integer]) -> integer or nil
- * str.rindex(regexp [, integer]) -> integer or nil
+ * string.rindex(substring, offset = self.length) -> integer or nil
+ * string.rindex(regexp, offset = self.length) -> integer or nil
+ *
+ * Returns the \Integer index of the _last_ occurrence of the given +substring+,
+ * or +nil+ if none found:
+ * 'foo'.rindex('f') # => 0
+ * 'foo'.rindex('o') # => 2
+ * 'foo'.rindex('oo') # => 1
+ * 'foo'.rindex('ooo') # => nil
+ *
+ * Returns the \Integer index of the _last_ match for the given \Regexp +regexp+,
+ * or +nil+ if none found:
+ * 'foo'.rindex(/f/) # => 0
+ * 'foo'.rindex(/o/) # => 2
+ * 'foo'.rindex(/oo/) # => 1
+ * 'foo'.rindex(/ooo/) # => nil
+ *
+ * The _last_ match means starting at the possible last position, not
+ * the last of longest matches.
+ *
+ * 'foo'.rindex(/o+/) # => 2
+ * $~ #=> #<MatchData "o">
+ *
+ * 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.
*
- * Returns the index of the last occurrence of the given <i>substring</i> or
- * pattern (<i>regexp</i>) in <i>str</i>. Returns <code>nil</code> if not
- * found. If the second parameter is present, it specifies the position in the
- * string to end the search---characters beyond this point will not be
- * considered.
+ * 'foo'.index(/o+(?!.*o)/) # => 1
+ * $~ #=> #<MatchData "oo">
*
- * "hello".rindex('e') #=> 1
- * "hello".rindex('l') #=> 3
- * "hello".rindex('a') #=> nil
- * "hello".rindex(?e) #=> 1
- * "hello".rindex(/[aeiou]/, -2) #=> 1
+ * \Integer argument +offset+, if given and non-negative, specifies the maximum starting position in the
+ * string to _end_ the search:
+ * 'foo'.rindex('o', 0) # => nil
+ * 'foo'.rindex('o', 1) # => 1
+ * 'foo'.rindex('o', 2) # => 2
+ * 'foo'.rindex('o', 3) # => 2
+ *
+ * If +offset+ is a negative \Integer, the maximum starting position in the
+ * string to _end_ the search is the sum of the string's length and +offset+:
+ * 'foo'.rindex('o', -1) # => 2
+ * 'foo'.rindex('o', -2) # => 1
+ * 'foo'.rindex('o', -3) # => nil
+ * 'foo'.rindex('o', -4) # => nil
+ *
+ * Related: String#index
*/
static VALUE
@@ -3734,68 +3924,62 @@ rb_str_rindex_m(int argc, VALUE *argv, VALUE str)
pos = len;
}
- if (SPECIAL_CONST_P(sub)) goto generic;
- switch (BUILTIN_TYPE(sub)) {
- case T_REGEXP:
+ if (RB_TYPE_P(sub, T_REGEXP)) {
/* enc = rb_get_check(str, sub); */
pos = str_offset(RSTRING_PTR(str), RSTRING_END(str), pos,
enc, single_byte_optimizable(str));
- pos = rb_reg_search(sub, str, pos, 1);
- pos = rb_str_sublen(str, pos);
- if (pos >= 0) return LONG2NUM(pos);
- break;
-
- generic:
- default: {
- VALUE tmp;
-
- tmp = rb_check_string_type(sub);
- if (NIL_P(tmp)) {
- rb_raise(rb_eTypeError, "type mismatch: %s given",
- rb_obj_classname(sub));
- }
- sub = tmp;
- }
- /* fall through */
- case T_STRING:
+ if (rb_reg_search(sub, str, pos, 1) >= 0) {
+ VALUE match = rb_backref_get();
+ struct re_registers *regs = RMATCH_REGS(match);
+ pos = rb_str_sublen(str, BEG(0));
+ return LONG2NUM(pos);
+ }
+ }
+ else {
+ StringValue(sub);
pos = rb_str_rindex(str, sub, pos);
if (pos >= 0) return LONG2NUM(pos);
- break;
}
return Qnil;
}
/*
* call-seq:
- * str =~ obj -> integer or nil
+ * string =~ regexp -> integer or nil
+ * string =~ object -> integer or nil
+ *
+ * Returns the \Integer index of the first substring that matches
+ * the given +regexp+, or +nil+ if no match found:
+ * 'foo' =~ /f/ # => 0
+ * 'foo' =~ /o/ # => 1
+ * 'foo' =~ /x/ # => nil
*
- * Match---If <i>obj</i> is a Regexp, use it as a pattern to match
- * against <i>str</i>,and returns the position the match starts, or
- * <code>nil</code> if there is no match. Otherwise, invokes
- * <i>obj.=~</i>, passing <i>str</i> as an argument. The default
- * <code>=~</code> in Object returns <code>nil</code>.
+ * Note: also updates
+ * {Regexp-related global variables}[Regexp.html#class-Regexp-label-Special+global+variables].
*
- * Note: <code>str =~ regexp</code> is not the same as
- * <code>regexp =~ str</code>. Strings captured from named capture groups
- * are assigned to local variables only in the second case.
+ * If the given +object+ is not a \Regexp, returns the value
+ * returned by <tt>object =~ self</tt>.
*
- * "cat o' 9 tails" =~ /\d/ #=> 7
- * "cat o' 9 tails" =~ 9 #=> nil
+ * Note that <tt>string =~ regexp</tt> is different from <tt>regexp =~ string</tt>
+ * (see {Regexp#=~}[https://ruby-doc.org/core-2.7.1/Regexp.html#method-i-3D-7E]):
+ * number= nil
+ * "no. 9" =~ /(?<number>\d+)/
+ * number # => nil (not assigned)
+ * /(?<number>\d+)/ =~ "no. 9"
+ * number #=> "9"
*/
static VALUE
rb_str_match(VALUE x, VALUE y)
{
- if (SPECIAL_CONST_P(y)) goto generic;
- switch (BUILTIN_TYPE(y)) {
+ switch (OBJ_BUILTIN_TYPE(y)) {
case T_STRING:
rb_raise(rb_eTypeError, "type mismatch: String given");
case T_REGEXP:
return rb_reg_match(y, x);
- generic:
default:
return rb_funcall(y, idEqTilde, 1, x);
}
@@ -3807,32 +3991,34 @@ static VALUE get_pat(VALUE);
/*
* call-seq:
- * str.match(pattern) -> matchdata or nil
- * str.match(pattern, pos) -> matchdata or nil
+ * string.match(pattern, offset = 0) -> matchdata or nil
+ * string.match(pattern, offset = 0) {|matchdata| ... } -> object
*
- * Converts <i>pattern</i> to a Regexp (if it isn't already one),
- * then invokes its <code>match</code> method on <i>str</i>. If the second
- * parameter is present, it specifies the position in the string to begin the
- * search.
+ * Returns a \Matchdata object (or +nil+) based on +self+ and the given +pattern+.
*
- * 'hello'.match('(.)\1') #=> #<MatchData "ll" 1:"l">
- * 'hello'.match('(.)\1')[0] #=> "ll"
- * 'hello'.match(/(.)\1/)[0] #=> "ll"
- * 'hello'.match(/(.)\1/, 3) #=> nil
- * 'hello'.match('xx') #=> nil
+ * Note: also updates
+ * {Regexp-related global variables}[Regexp.html#class-Regexp-label-Special+global+variables].
*
- * If a block is given, invoke the block with MatchData if match succeed, so
- * that you can write
+ * - Computes +regexp+ by converting +pattern+ (if not already a \Regexp).
+ * regexp = Regexp.new(pattern)
+ * - Computes +matchdata+, which will be either a \MatchData object or +nil+
+ * (see Regexp#match):
+ * matchdata = <tt>regexp.match(self)
*
- * str.match(pat) {|m| ...}
+ * With no block given, returns the computed +matchdata+:
+ * 'foo'.match('f') # => #<MatchData "f">
+ * 'foo'.match('o') # => #<MatchData "o">
+ * 'foo'.match('x') # => nil
*
- * instead of
+ * If \Integer argument +offset+ is given, the search begins at index +offset+:
+ * 'foo'.match('f', 1) # => nil
+ * 'foo'.match('o', 1) # => #<MatchData "o">
*
- * if m = str.match(pat)
- * ...
- * end
- *
- * The return value is a value from block execution in this case.
+ * With a block given, calls the block with the computed +matchdata+
+ * and 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
*/
static VALUE
@@ -3852,19 +4038,25 @@ rb_str_match_m(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.match?(pattern) -> true or false
- * str.match?(pattern, pos) -> true or false
+ * string.match?(pattern, offset = 0) -> true or false
+ *
+ * Returns +true+ or +false+ based on whether a match is found for +self+ and +pattern+.
+ *
+ * Note: does not update
+ * {Regexp-related global variables}[Regexp.html#class-Regexp-label-Special+global+variables].
+ *
+ * Computes +regexp+ by converting +pattern+ (if not already a \Regexp).
+ * regexp = Regexp.new(pattern)
*
- * Converts _pattern_ to a +Regexp+ (if it isn't already one), then
- * returns a +true+ or +false+ indicates whether the regexp is
- * matched _str_ or not without updating <code>$~</code> and other
- * related variables. If the second parameter is present, it
- * specifies the position in the string to begin the search.
+ * Returns +true+ if <tt>self+.match(regexp)</tt> returns a \Matchdata object,
+ * +false+ otherwise:
+ * 'foo'.match?(/o/) # => true
+ * 'foo'.match?('o') # => true
+ * 'foo'.match?(/x/) # => false
*
- * "Ruby".match?(/R.../) #=> true
- * "Ruby".match?(/R.../, 1) #=> false
- * "Ruby".match?(/P.../) #=> false
- * $& #=> nil
+ * If \Integer argument +offset+ is given, the search begins at index +offset+:
+ * 'foo'.match?('f', 1) # => false
+ * 'foo'.match?('o', 1) # => true
*/
static VALUE
@@ -4063,34 +4255,62 @@ static VALUE str_succ(VALUE str);
/*
* call-seq:
- * str.succ -> new_str
- * str.next -> new_str
- *
- * Returns the successor to <i>str</i>. The successor is calculated by
- * incrementing characters starting from the rightmost alphanumeric (or
- * the rightmost character if there are no alphanumerics) in the
- * string. Incrementing a digit always results in another digit, and
- * incrementing a letter results in another letter of the same case.
- * Incrementing nonalphanumerics uses the underlying character set's
- * collating sequence.
- *
- * If the increment generates a ``carry,'' the character to the left of
- * it is incremented. This process repeats until there is no carry,
- * adding an additional character if necessary.
- *
- * "abcd".succ #=> "abce"
- * "THX1138".succ #=> "THX1139"
- * "<<koala>>".succ #=> "<<koalb>>"
- * "1999zzz".succ #=> "2000aaa"
- * "ZZZ9999".succ #=> "AAAA0000"
- * "***".succ #=> "**+"
+ * string.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 # => ""
+ *
+ * String#next is an alias for String#succ.
*/
VALUE
rb_str_succ(VALUE orig)
{
VALUE str;
- str = rb_str_new_with_class(orig, RSTRING_PTR(orig), RSTRING_LEN(orig));
+ str = rb_str_new(RSTRING_PTR(orig), RSTRING_LEN(orig));
rb_enc_cr_str_copy_for_substr(str, orig);
return str_succ(str);
}
@@ -4185,10 +4405,11 @@ str_succ(VALUE str)
/*
* call-seq:
- * str.succ! -> str
- * str.next! -> str
+ * string.succ! -> self
*
- * Equivalent to String#succ, but modifies the receiver in place.
+ * Equivalent to String#succ, but modifies +self+ in place; returns +self+.
+ *
+ * String#next! is an alias for String#succ!.
*/
static VALUE
@@ -4218,35 +4439,29 @@ str_upto_i(VALUE str, VALUE arg)
/*
* call-seq:
- * str.upto(other_str, exclusive=false) {|s| block } -> str
- * str.upto(other_str, exclusive=false) -> an_enumerator
+ * string.upto(other_string, exclusive = false) {|string| ... } -> self
+ * string.upto(other_string, exclusive = false) -> new_enumerator
*
- * Iterates through successive values, starting at <i>str</i> and
- * ending at <i>other_str</i> inclusive, passing each value in turn
- * to the block. The String#succ method is used to generate each
- * value. If optional second argument exclusive is omitted or is
- * false, the last value will be included; otherwise it will be
- * excluded.
+ * With a block given, calls the block with each \String value
+ * returned by successive calls to String#succ;
+ * the first value is +self+, the next is <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 no block is given, an enumerator is returned instead.
+ * 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
*
- * "a8".upto("b6") {|s| print s, ' ' }
- * for s in "a8".."b6"
- * print s, ' '
- * end
+ * If +other_string+ would not be reached, does not call the block:
+ * '25'.upto('5') {|s| fail s }
+ * 'aa'.upto('a') {|s| fail s }
*
- * <em>produces:</em>
- *
- * a8 a9 b0 b1 b2 b3 b4 b5 b6
- * a8 a9 b0 b1 b2 b3 b4 b5 b6
- *
- * If <i>str</i> and <i>other_str</i> contains only ascii numeric characters,
- * both are recognized as decimal numbers. In addition, the width of
- * string (e.g. leading zeros) is handled appropriately.
- *
- * "9".upto("11").to_a #=> ["9", "10", "11"]
- * "25".upto("5").to_a #=> []
- * "07".upto("11").to_a #=> ["07", "08", "09", "10", "11"]
+ * With no block given, returns a new \Enumerator:
+ * 'a8'.upto('b6') # => #<Enumerator: "a8":upto("b6")>
*/
static VALUE
@@ -4324,7 +4539,7 @@ rb_str_upto_each(VALUE beg, VALUE end, int excl, int (*each)(VALUE, VALUE), VALU
if (n > 0 || (excl && n == 0)) return beg;
after_end = rb_funcallv(end, succ, 0, 0);
- current = rb_str_dup(beg);
+ current = str_duplicate(rb_cString, beg);
while (!rb_str_equal(current, after_end)) {
VALUE next = Qnil;
if (excl || !rb_str_equal(current, end))
@@ -4372,7 +4587,7 @@ rb_str_upto_endless_each(VALUE beg, int (*each)(VALUE, VALUE), VALUE arg)
}
}
/* normal case */
- current = rb_str_dup(beg);
+ current = str_duplicate(rb_cString, beg);
while (1) {
VALUE next = rb_funcallv(current, succ, 0, 0);
if ((*each)(current, arg)) break;
@@ -4462,7 +4677,7 @@ rb_str_aref(VALUE str, VALUE indx)
}
else if (RB_TYPE_P(indx, T_STRING)) {
if (rb_str_index(str, indx, 0) != -1)
- return rb_str_dup(indx);
+ return str_duplicate(rb_cString, indx);
return Qnil;
}
else {
@@ -4485,71 +4700,73 @@ rb_str_aref(VALUE str, VALUE indx)
/*
* call-seq:
- * str[index] -> new_str or nil
- * str[start, length] -> new_str or nil
- * str[range] -> new_str or nil
- * str[regexp] -> new_str or nil
- * str[regexp, capture] -> new_str or nil
- * str[match_str] -> new_str or nil
- * str.slice(index) -> new_str or nil
- * str.slice(start, length) -> new_str or nil
- * str.slice(range) -> new_str or nil
- * str.slice(regexp) -> new_str or nil
- * str.slice(regexp, capture) -> new_str or nil
- * str.slice(match_str) -> new_str or nil
- *
- * Element Reference --- If passed a single +index+, returns a substring of
- * one character at that index. If passed a +start+ index and a +length+,
- * returns a substring containing +length+ characters starting at the
- * +start+ index. If passed a +range+, its beginning and end are interpreted as
- * offsets delimiting the substring to be returned.
- *
- * In these three cases, if an index is negative, it is counted from the end
- * of the string. For the +start+ and +range+ cases the starting index
- * is just before a character and an index matching the string's size.
- * Additionally, an empty string is returned when the starting index for a
- * character range is at the end of the string.
- *
- * Returns +nil+ if the initial index falls outside the string or the length
- * is negative.
- *
- * If a +Regexp+ is supplied, the matching portion of the string is
- * returned. If a +capture+ follows the regular expression, which may be a
- * capture group index or name, follows the regular expression that component
- * of the MatchData is returned instead.
- *
- * If a +match_str+ is given, that string is returned if it occurs in
- * the string.
- *
- * Returns +nil+ if the regular expression does not match or the match string
- * cannot be found.
- *
- * a = "hello there"
- *
- * a[1] #=> "e"
- * a[2, 3] #=> "llo"
- * a[2..3] #=> "ll"
- *
- * a[-3, 2] #=> "er"
- * a[7..-2] #=> "her"
- * a[-4..-2] #=> "her"
- * a[-2..-4] #=> ""
- *
- * a[11, 0] #=> ""
- * a[11] #=> nil
- * a[12, 0] #=> nil
- * a[12..-1] #=> nil
- *
- * a[/[aeiou](.)\1/] #=> "ell"
- * a[/[aeiou](.)\1/, 0] #=> "ell"
- * a[/[aeiou](.)\1/, 1] #=> "l"
- * a[/[aeiou](.)\1/, 2] #=> nil
- *
- * a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] #=> "l"
- * a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "vowel"] #=> "e"
- *
- * a["lo"] #=> "lo"
- * a["bye"] #=> nil
+ * string[index] -> new_string or nil
+ * string[start, length] -> new_string or nil
+ * string[range] -> new_string or nil
+ * string[regexp, capture = 0] -> new_string or nil
+ * string[substring] -> new_string or nil
+ *
+ * Returns the substring of +self+ specified by the arguments.
+ *
+ * When the single \Integer argument +index+ is given,
+ * returns the 1-character substring found in +self+ at offset +index+:
+ * 'bar'[2] # => "r"
+ * Counts backward from the end of +self+ if +index+ is negative:
+ * 'foo'[-3] # => "f"
+ * Returns +nil+ if +index+ is out of range:
+ * 'foo'[3] # => nil
+ * 'foo'[-4] # => nil
+ *
+ * When the two \Integer arguments +start+ and +length+ are given,
+ * returns the substring of the given +length+ found in +self+ at offset +start+:
+ * 'foo'[0, 2] # => "fo"
+ * 'foo'[0, 0] # => ""
+ * Counts backward from the end of +self+ if +start+ is negative:
+ * 'foo'[-2, 2] # => "oo"
+ * Special case: returns a new empty \String if +start+ is equal to the length of +self+:
+ * 'foo'[3, 2] # => ""
+ * Returns +nil+ if +start+ is out of range:
+ * 'foo'[4, 2] # => nil
+ * 'foo'[-4, 2] # => nil
+ * Returns the trailing substring of +self+ if +length+ is large:
+ * 'foo'[1, 50] # => "oo"
+ * Returns +nil+ if +length+ is negative:
+ * 'foo'[0, -1] # => nil
+ *
+ * When the single \Range argument +range+ is given,
+ * derives +start+ and +length+ values from the given +range+,
+ * and returns values as above:
+ * - <tt>'foo'[0..1]</tt> is equivalent to <tt>'foo'[0, 2]</tt>.
+ * - <tt>'foo'[0...1]</tt> is equivalent to <tt>'foo'[0, 1]</tt>.
+ *
+ * When the \Regexp argument +regexp+ is given,
+ * and the +capture+ argument is <tt>0</tt>,
+ * returns the first matching substring found in +self+,
+ * or +nil+ if none found:
+ * 'foo'[/o/] # => "o"
+ * 'foo'[/x/] # => nil
+ * s = 'hello there'
+ * s[/[aeiou](.)\1/] # => "ell"
+ * s[/[aeiou](.)\1/, 0] # => "ell"
+ *
+ * If argument +capture+ is given and not <tt>0</tt>,
+ * it should be either an \Integer capture group index or a \String or \Symbol capture group name;
+ * the method call returns only the specified capture
+ * (see {Regexp Capturing}[Regexp.html#class-Regexp-label-Capturing]):
+ * s = 'hello there'
+ * s[/[aeiou](.)\1/, 1] # => "l"
+ * s[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] # => "l"
+ * s[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, :vowel] # => "e"
+ *
+ * If an invalid capture group index is given, +nil+ is returned. If an invalid
+ * capture group name is given, +IndexError+ is raised.
+ *
+ * When the single \String argument +substring+ is given,
+ * returns the substring from +self+ if found, otherwise +nil+:
+ * 'foo'['oo'] # => "oo"
+ * 'foo'['xx'] # => nil
+ *
+ * String#slice is an alias for String#[].
*/
static VALUE
@@ -4654,14 +4871,10 @@ rb_str_update(VALUE str, long beg, long len, VALUE val)
enc = rb_enc_check(str, val);
slen = str_strlen(str, enc); /* rb_enc_check */
- if (slen < beg) {
- out_of_range:
+ if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) {
rb_raise(rb_eIndexError, "index %ld out of string", beg);
}
if (beg < 0) {
- if (beg + slen < 0) {
- goto out_of_range;
- }
beg += slen;
}
assert(beg >= 0);
@@ -4701,14 +4914,10 @@ rb_str_subpat_set(VALUE str, VALUE re, VALUE backref, VALUE val)
match = rb_backref_get();
nth = rb_reg_backref_number(match, backref);
regs = RMATCH_REGS(match);
- if (nth >= regs->num_regs) {
- out_of_range:
+ if ((nth >= regs->num_regs) || ((nth < 0) && (-nth >= regs->num_regs))) {
rb_raise(rb_eIndexError, "index %d out of regexp", nth);
}
if (nth < 0) {
- if (-nth >= regs->num_regs) {
- goto out_of_range;
- }
nth += regs->num_regs;
}
@@ -4729,15 +4938,7 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val)
{
long idx, beg;
- if (FIXNUM_P(indx)) {
- idx = FIX2LONG(indx);
- num_index:
- rb_str_splice(str, idx, 1, val);
- return val;
- }
-
- if (SPECIAL_CONST_P(indx)) goto generic;
- switch (BUILTIN_TYPE(indx)) {
+ switch (TYPE(indx)) {
case T_REGEXP:
rb_str_subpat_set(str, indx, INT2FIX(0), val);
return val;
@@ -4751,7 +4952,6 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val)
rb_str_splice(str, beg, str_strlen(indx, NULL), val);
return val;
- generic:
default:
/* check if indx is Range */
{
@@ -4761,8 +4961,12 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val)
return val;
}
}
+ /* FALLTHROUGH */
+
+ case T_FIXNUM:
idx = NUM2LONG(indx);
- goto num_index;
+ rb_str_splice(str, idx, 1, val);
+ return val;
}
}
@@ -4808,19 +5012,17 @@ rb_str_aset_m(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * str.insert(index, other_str) -> str
+ * string.insert(index, other_string) -> self
+ *
+ * Inserts the given +other_string+ into +self+; returns +self+.
*
- * Inserts <i>other_str</i> before the character at the given
- * <i>index</i>, modifying <i>str</i>. Negative indices count from the
- * end of the string, and insert <em>after</em> the given character.
- * The intent is insert <i>aString</i> so that it starts at the given
- * <i>index</i>.
+ * If the \Integer +index+ is positive, inserts +other_string+ at offset +index+:
+ * 'foo'.insert(1, 'bar') # => "fbaroo"
*
- * "abcd".insert(0, 'X') #=> "Xabcd"
- * "abcd".insert(3, 'X') #=> "abcXd"
- * "abcd".insert(4, 'X') #=> "abcdX"
- * "abcd".insert(-3, 'X') #=> "abXcd"
- * "abcd".insert(-1, 'X') #=> "abcdX"
+ * 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"
*/
static VALUE
@@ -4861,19 +5063,86 @@ rb_str_insert(VALUE str, VALUE idx, VALUE str2)
static VALUE
rb_str_slice_bang(int argc, VALUE *argv, VALUE str)
{
- VALUE result;
- VALUE buf[3];
- int i;
+ VALUE result = Qnil;
+ VALUE indx;
+ long beg, len = 1;
+ char *p;
rb_check_arity(argc, 1, 2);
- for (i=0; i<argc; i++) {
- buf[i] = argv[i];
- }
str_modify_keep_cr(str);
- result = rb_str_aref_m(argc, buf, str);
- if (!NIL_P(result)) {
- buf[i] = rb_str_new(0,0);
- rb_str_aset_m(argc+1, buf, str);
+ indx = argv[0];
+ if (RB_TYPE_P(indx, T_REGEXP)) {
+ if (rb_reg_search(indx, str, 0, 0) < 0) return Qnil;
+ VALUE match = rb_backref_get();
+ struct re_registers *regs = RMATCH_REGS(match);
+ int nth = 0;
+ if (argc > 1 && (nth = rb_reg_backref_number(match, argv[1])) < 0) {
+ if ((nth += regs->num_regs) <= 0) return Qnil;
+ }
+ else if (nth >= regs->num_regs) return Qnil;
+ beg = BEG(nth);
+ len = END(nth) - beg;
+ goto subseq;
+ }
+ else if (argc == 2) {
+ beg = NUM2LONG(indx);
+ len = NUM2LONG(argv[1]);
+ goto num_index;
+ }
+ else if (FIXNUM_P(indx)) {
+ beg = FIX2LONG(indx);
+ if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
+ if (!len) return Qnil;
+ beg = p - RSTRING_PTR(str);
+ goto subseq;
+ }
+ else if (RB_TYPE_P(indx, T_STRING)) {
+ beg = rb_str_index(str, indx, 0);
+ if (beg == -1) return Qnil;
+ len = RSTRING_LEN(indx);
+ result = str_duplicate(rb_cString, indx);
+ goto squash;
+ }
+ else {
+ switch (rb_range_beg_len(indx, &beg, &len, str_strlen(str, NULL), 0)) {
+ case Qnil:
+ return Qnil;
+ case Qfalse:
+ beg = NUM2LONG(indx);
+ if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
+ if (!len) return Qnil;
+ beg = p - RSTRING_PTR(str);
+ goto subseq;
+ default:
+ goto num_index;
+ }
+ }
+
+ num_index:
+ if (!(p = rb_str_subpos(str, beg, &len))) return Qnil;
+ beg = p - RSTRING_PTR(str);
+
+ subseq:
+ result = rb_str_new(RSTRING_PTR(str)+beg, len);
+ rb_enc_cr_str_copy_for_substr(result, str);
+
+ squash:
+ if (len > 0) {
+ if (beg == 0) {
+ rb_str_drop_bytes(str, len);
+ }
+ else {
+ char *sptr = RSTRING_PTR(str);
+ long slen = RSTRING_LEN(str);
+ if (beg + len > slen) /* pathological check */
+ len = slen - beg;
+ memmove(sptr + beg,
+ sptr + beg + len,
+ slen - (beg + len));
+ slen -= len;
+ STR_SET_LEN(str, slen);
+ TERM_FILL(&sptr[slen], TERM_LEN(str));
+ }
}
return result;
}
@@ -4883,8 +5152,7 @@ get_pat(VALUE pat)
{
VALUE val;
- if (SPECIAL_CONST_P(pat)) goto to_string;
- switch (BUILTIN_TYPE(pat)) {
+ switch (OBJ_BUILTIN_TYPE(pat)) {
case T_REGEXP:
return pat;
@@ -4892,7 +5160,6 @@ get_pat(VALUE pat)
break;
default:
- to_string:
val = rb_check_string_type(pat);
if (NIL_P(val)) {
Check_Type(pat, T_REGEXP);
@@ -4908,8 +5175,7 @@ get_pat_quoted(VALUE pat, int check)
{
VALUE val;
- if (SPECIAL_CONST_P(pat)) goto to_string;
- switch (BUILTIN_TYPE(pat)) {
+ switch (OBJ_BUILTIN_TYPE(pat)) {
case T_REGEXP:
return pat;
@@ -4917,7 +5183,6 @@ get_pat_quoted(VALUE pat, int check)
break;
default:
- to_string:
val = rb_check_string_type(pat);
if (NIL_P(val)) {
Check_Type(pat, T_REGEXP);
@@ -4937,7 +5202,7 @@ rb_pat_search(VALUE pat, VALUE str, long pos, int set_backref_str)
pos = rb_strseq_index(str, pat, pos, 1);
if (set_backref_str) {
if (pos >= 0) {
- str = rb_str_new_frozen(str);
+ str = rb_str_new_frozen_String(str);
rb_backref_set_string(str, pos, RSTRING_LEN(pat));
}
else {
@@ -5131,7 +5396,7 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
static VALUE
rb_str_sub(int argc, VALUE *argv, VALUE str)
{
- str = rb_str_dup(str);
+ str = str_duplicate(rb_cString, str);
rb_str_sub_bang(argc, argv, str);
return str;
}
@@ -5171,7 +5436,7 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
beg = rb_pat_search(pat, str, 0, need_backref);
if (beg < 0) {
if (bang) return Qnil; /* no match, no substitution */
- return rb_str_dup(str);
+ return str_duplicate(rb_cString, str);
}
offset = 0;
@@ -5252,7 +5517,6 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
str_shared_replace(str, dest);
}
else {
- RBASIC_SET_CLASS(dest, rb_obj_class(str));
str = dest;
}
@@ -5515,12 +5779,12 @@ str_byte_substr(VALUE str, long beg, long len, int empty)
if (!STR_EMBEDDABLE_P(len, TERM_LEN(str)) && SHARABLE_SUBSTRING_P(beg, len, n)) {
str2 = rb_str_new_frozen(str);
- str2 = str_new_shared(rb_obj_class(str2), str2);
+ str2 = str_new_shared(rb_cString, str2);
RSTRING(str2)->as.heap.ptr += beg;
RSTRING(str2)->as.heap.len = len;
}
else {
- str2 = rb_str_new_with_class(str, p, len);
+ str2 = rb_str_new(p, len);
}
str_enc_copy(str2, str);
@@ -5622,9 +5886,9 @@ rb_str_reverse(VALUE str)
char *s, *e, *p;
int cr;
- if (RSTRING_LEN(str) <= 1) return rb_str_dup(str);
+ if (RSTRING_LEN(str) <= 1) return str_duplicate(rb_cString, str);
enc = STR_ENC_GET(str);
- rev = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
+ rev = rb_str_new(0, RSTRING_LEN(str));
s = RSTRING_PTR(str); e = RSTRING_END(str);
p = RSTRING_END(rev);
cr = ENC_CODERANGE(str);
@@ -6103,7 +6367,7 @@ rb_str_dump(VALUE str)
len += clen;
}
- result = rb_str_new_with_class(str, 0, len);
+ result = rb_str_new(0, len);
p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
q = RSTRING_PTR(result); qend = q + len + 1;
@@ -6205,9 +6469,8 @@ unescape_ascii(unsigned int c)
return '\007';
case 'e':
return 033;
- default:
- UNREACHABLE;
}
+ UNREACHABLE_RETURN(-1);
}
static void
@@ -6345,7 +6608,7 @@ str_undump(VALUE str)
rb_raise(rb_eRuntimeError, "non-ASCII character detected");
}
if (!str_null_check(str, &w)) {
- rb_raise(rb_eRuntimeError, "string contains null byte");
+ rb_raise(rb_eRuntimeError, "string contains null byte");
}
if (RSTRING_LEN(str) < 2) goto invalid_format;
if (*s != '"') goto invalid_format;
@@ -6527,7 +6790,7 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
size_t buffer_count = 0;
int buffer_length_or_invalid;
- if (RSTRING_LEN(source) == 0) return rb_str_dup(source);
+ if (RSTRING_LEN(source) == 0) return str_duplicate(rb_cString, source);
source_current = (OnigUChar*)RSTRING_PTR(source);
source_end = (OnigUChar*)RSTRING_END(source);
@@ -6563,12 +6826,12 @@ rb_str_casemap(VALUE source, OnigCaseFoldType *flags, rb_encoding *enc)
}
if (buffer_count==1) {
- target = rb_str_new_with_class(source, (const char*)current_buffer->space, target_length);
+ target = rb_str_new((const char*)current_buffer->space, target_length);
}
else {
char *target_current;
- target = rb_str_new_with_class(source, 0, target_length);
+ target = rb_str_new(0, target_length);
target_current = RSTRING_PTR(target);
current_buffer = DATA_PTR(buffer_anchor);
while (current_buffer) {
@@ -6701,12 +6964,12 @@ rb_str_upcase(int argc, VALUE *argv, VALUE str)
flags = check_case_options(argc, argv, flags);
enc = str_true_enc(str);
if (case_option_single_p(flags, enc, str)) {
- ret = rb_str_new_with_class(str, RSTRING_PTR(str), RSTRING_LEN(str));
+ ret = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
str_enc_copy(ret, str);
upcase_single(ret);
}
else if (flags&ONIGENC_CASE_ASCII_ONLY) {
- ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
+ ret = rb_str_new(0, RSTRING_LEN(str));
rb_str_ascii_casemap(str, ret, &flags, enc);
}
else {
@@ -6829,12 +7092,12 @@ rb_str_downcase(int argc, VALUE *argv, VALUE str)
flags = check_case_options(argc, argv, flags);
enc = str_true_enc(str);
if (case_option_single_p(flags, enc, str)) {
- ret = rb_str_new_with_class(str, RSTRING_PTR(str), RSTRING_LEN(str));
+ ret = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
str_enc_copy(ret, str);
downcase_single(ret);
}
else if (flags&ONIGENC_CASE_ASCII_ONLY) {
- ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
+ ret = rb_str_new(0, RSTRING_LEN(str));
rb_str_ascii_casemap(str, ret, &flags, enc);
}
else {
@@ -6909,7 +7172,7 @@ rb_str_capitalize(int argc, VALUE *argv, VALUE str)
enc = str_true_enc(str);
if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str;
if (flags&ONIGENC_CASE_ASCII_ONLY) {
- ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
+ ret = rb_str_new(0, RSTRING_LEN(str));
rb_str_ascii_casemap(str, ret, &flags, enc);
}
else {
@@ -6973,9 +7236,9 @@ rb_str_swapcase(int argc, VALUE *argv, VALUE str)
flags = check_case_options(argc, argv, flags);
enc = str_true_enc(str);
- if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str;
+ if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str)) return str_duplicate(rb_cString, str);
if (flags&ONIGENC_CASE_ASCII_ONLY) {
- ret = rb_str_new_with_class(str, 0, RSTRING_LEN(str));
+ ret = rb_str_new(0, RSTRING_LEN(str));
rb_str_ascii_casemap(str, ret, &flags, enc);
}
else {
@@ -6998,8 +7261,8 @@ trnext(struct tr *t, rb_encoding *enc)
int n;
for (;;) {
+ nextpart:
if (!t->gen) {
-nextpart:
if (t->p == t->pend) return -1;
if (rb_enc_ascget(t->p, t->pend, &n, enc) == '\\' && t->p + n < t->pend) {
t->p += n;
@@ -7349,18 +7612,19 @@ rb_str_tr_bang(VALUE str, VALUE src, VALUE repl)
static VALUE
rb_str_tr(VALUE str, VALUE src, VALUE repl)
{
- str = rb_str_dup(str);
+ str = str_duplicate(rb_cString, str);
tr_trans(str, src, repl, 0);
return str;
}
-#define TR_TABLE_SIZE 257
+#define TR_TABLE_MAX (UCHAR_MAX+1)
+#define TR_TABLE_SIZE (TR_TABLE_MAX+1)
static void
tr_setup_table(VALUE str, char stable[TR_TABLE_SIZE], int first,
VALUE *tablep, VALUE *ctablep, rb_encoding *enc)
{
const unsigned int errc = -1;
- char buf[256];
+ char buf[TR_TABLE_MAX];
struct tr tr;
unsigned int c;
VALUE table = 0, ptable = 0;
@@ -7374,26 +7638,26 @@ tr_setup_table(VALUE str, char stable[TR_TABLE_SIZE], int first,
tr.p += l;
}
if (first) {
- for (i=0; i<256; i++) {
+ for (i=0; i<TR_TABLE_MAX; i++) {
stable[i] = 1;
}
- stable[256] = cflag;
+ stable[TR_TABLE_MAX] = cflag;
}
- else if (stable[256] && !cflag) {
- stable[256] = 0;
+ else if (stable[TR_TABLE_MAX] && !cflag) {
+ stable[TR_TABLE_MAX] = 0;
}
- for (i=0; i<256; i++) {
+ for (i=0; i<TR_TABLE_MAX; i++) {
buf[i] = cflag;
}
while ((c = trnext(&tr, enc)) != errc) {
- if (c < 256) {
- buf[c & 0xff] = !cflag;
+ if (c < TR_TABLE_MAX) {
+ buf[(unsigned char)c] = !cflag;
}
else {
VALUE key = UINT2NUM(c);
- if (!table && (first || *tablep || stable[256])) {
+ if (!table && (first || *tablep || stable[TR_TABLE_MAX])) {
if (cflag) {
ptable = *ctablep;
table = ptable ? ptable : rb_hash_new();
@@ -7410,7 +7674,7 @@ tr_setup_table(VALUE str, char stable[TR_TABLE_SIZE], int first,
}
}
}
- for (i=0; i<256; i++) {
+ for (i=0; i<TR_TABLE_MAX; i++) {
stable[i] = stable[i] && buf[i];
}
if (!table && !cflag) {
@@ -7422,7 +7686,7 @@ tr_setup_table(VALUE str, char stable[TR_TABLE_SIZE], int first,
static int
tr_find(unsigned int c, const char table[TR_TABLE_SIZE], VALUE del, VALUE nodel)
{
- if (c < 256) {
+ if (c < TR_TABLE_MAX) {
return table[c] != 0;
}
else {
@@ -7437,7 +7701,7 @@ tr_find(unsigned int c, const char table[TR_TABLE_SIZE], VALUE del, VALUE nodel)
else if (nodel && !NIL_P(rb_hash_lookup(nodel, v))) {
return FALSE;
}
- return table[256] ? TRUE : FALSE;
+ return table[TR_TABLE_MAX] ? TRUE : FALSE;
}
}
@@ -7528,7 +7792,7 @@ rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
static VALUE
rb_str_delete(int argc, VALUE *argv, VALUE str)
{
- str = rb_str_dup(str);
+ str = str_duplicate(rb_cString, str);
rb_str_delete_bang(argc, argv, str);
return str;
}
@@ -7636,7 +7900,7 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
static VALUE
rb_str_squeeze(int argc, VALUE *argv, VALUE str)
{
- str = rb_str_dup(str);
+ str = str_duplicate(rb_cString, str);
rb_str_squeeze_bang(argc, argv, str);
return str;
}
@@ -7673,7 +7937,7 @@ rb_str_tr_s_bang(VALUE str, VALUE src, VALUE repl)
static VALUE
rb_str_tr_s(VALUE str, VALUE src, VALUE repl)
{
- str = rb_str_dup(str);
+ str = str_duplicate(rb_cString, str);
tr_trans(str, src, repl, 1);
return str;
}
@@ -7817,12 +8081,12 @@ split_string(VALUE result, VALUE str, long beg, long len, long empty_count)
/* make different substrings */
if (result) {
do {
- rb_ary_push(result, str_new_empty(str));
+ rb_ary_push(result, str_new_empty_String(str));
} while (--empty_count > 0);
}
else {
do {
- rb_yield(str_new_empty(str));
+ rb_yield(str_new_empty_String(str));
} while (--empty_count > 0);
}
}
@@ -7836,6 +8100,35 @@ split_string(VALUE result, VALUE str, long beg, long len, long empty_count)
return empty_count;
}
+typedef enum {
+ SPLIT_TYPE_AWK, SPLIT_TYPE_STRING, SPLIT_TYPE_REGEXP, SPLIT_TYPE_CHARS
+} split_type_t;
+
+static split_type_t
+literal_split_pattern(VALUE spat, split_type_t default_type)
+{
+ rb_encoding *enc = STR_ENC_GET(spat);
+ const char *ptr;
+ long len;
+ RSTRING_GETMEM(spat, ptr, len);
+ if (len == 0) {
+ /* Special case - split into chars */
+ return SPLIT_TYPE_CHARS;
+ }
+ else if (rb_enc_asciicompat(enc)) {
+ if (len == 1 && ptr[0] == ' ') {
+ return SPLIT_TYPE_AWK;
+ }
+ }
+ else {
+ int l;
+ if (rb_enc_ascget(ptr, ptr + len, &l, enc) == ' ' && len == l) {
+ return SPLIT_TYPE_AWK;
+ }
+ }
+ return default_type;
+}
+
/*
* call-seq:
* str.split(pattern=nil, [limit]) -> an_array
@@ -7897,7 +8190,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
rb_encoding *enc;
VALUE spat;
VALUE limit;
- enum {awk, string, regexp, chars} split_type;
+ split_type_t split_type;
long beg, end, i = 0, empty_count = -1;
int lim = 0;
VALUE result, tmp;
@@ -7908,11 +8201,11 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
if (lim <= 0) limit = Qnil;
else if (lim == 1) {
if (RSTRING_LEN(str) == 0)
- return result ? rb_ary_new2(0) : str;
- tmp = rb_str_dup(str);
+ return result ? rb_ary_new2(0) : str;
+ tmp = str_duplicate(rb_cString, str);
if (!result) {
rb_yield(tmp);
- return str;
+ return str;
}
return rb_ary_new3(1, tmp);
}
@@ -7921,41 +8214,38 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
if (NIL_P(limit) && !lim) empty_count = 0;
enc = STR_ENC_GET(str);
- split_type = regexp;
+ split_type = SPLIT_TYPE_REGEXP;
if (!NIL_P(spat)) {
spat = get_pat_quoted(spat, 0);
}
else if (NIL_P(spat = rb_fs)) {
- split_type = awk;
+ split_type = SPLIT_TYPE_AWK;
}
else if (!(spat = rb_fs_check(spat))) {
rb_raise(rb_eTypeError, "value of $; must be String or Regexp");
}
else {
- rb_warn("$; is set to non-nil value");
- }
- if (split_type != awk) {
- if (BUILTIN_TYPE(spat) == T_STRING) {
- rb_encoding *enc2 = STR_ENC_GET(spat);
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$; is set to non-nil value");
+ }
+ if (split_type != SPLIT_TYPE_AWK) {
+ switch (BUILTIN_TYPE(spat)) {
+ case T_REGEXP:
+ rb_reg_options(spat); /* check if uninitialized */
+ tmp = RREGEXP_SRC(spat);
+ split_type = literal_split_pattern(tmp, SPLIT_TYPE_REGEXP);
+ if (split_type == SPLIT_TYPE_AWK) {
+ spat = tmp;
+ split_type = SPLIT_TYPE_STRING;
+ }
+ break;
+ case T_STRING:
mustnot_broken(spat);
- split_type = string;
- if (RSTRING_LEN(spat) == 0) {
- /* Special case - split into chars */
- split_type = chars;
- }
- else if (rb_enc_asciicompat(enc2) == 1) {
- if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') {
- split_type = awk;
- }
- }
- else {
- int l;
- if (rb_enc_ascget(RSTRING_PTR(spat), RSTRING_END(spat), &l, enc2) == ' ' &&
- RSTRING_LEN(spat) == l) {
- split_type = awk;
- }
- }
+ split_type = literal_split_pattern(spat, SPLIT_TYPE_STRING);
+ break;
+
+ default:
+ UNREACHABLE_RETURN(Qnil);
}
}
@@ -7965,7 +8255,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
beg = 0;
char *ptr = RSTRING_PTR(str);
char *eptr = RSTRING_END(str);
- if (split_type == awk) {
+ if (split_type == SPLIT_TYPE_AWK) {
char *bptr = ptr;
int skip = 1;
unsigned int c;
@@ -8023,7 +8313,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
}
}
}
- else if (split_type == string) {
+ else if (split_type == SPLIT_TYPE_STRING) {
char *str_start = ptr;
char *substr_start = ptr;
char *sptr = RSTRING_PTR(spat);
@@ -8046,7 +8336,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
}
beg = ptr - str_start;
}
- else if (split_type == chars) {
+ else if (split_type == SPLIT_TYPE_CHARS) {
char *str_start = ptr;
int n;
@@ -8068,11 +8358,12 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
struct re_registers *regs;
VALUE match = 0;
- for (; (end = rb_reg_search(spat, str, start, 0)) >= 0;
+ for (; rb_reg_search(spat, str, start, 0) >= 0;
(match ? (rb_match_unbusy(match), rb_backref_set(match)) : (void)0)) {
match = rb_backref_get();
if (!result) rb_match_busy(match);
regs = RMATCH_REGS(match);
+ end = BEG(0);
if (start == end && BEG(0) == END(0)) {
if (!ptr) {
SPLIT_STR(0, 0);
@@ -8153,6 +8444,21 @@ chomp_newline(const char *p, const char *e, rb_encoding *enc)
}
static VALUE
+get_rs(void)
+{
+ VALUE rs = rb_rs;
+ if (!NIL_P(rs) &&
+ (!RB_TYPE_P(rs, T_STRING) ||
+ RSTRING_LEN(rs) != 1 ||
+ RSTRING_PTR(rs)[0] != '\n')) {
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$/ is set to non-default value");
+ }
+ return rs;
+}
+
+#define rb_rs get_rs()
+
+static VALUE
rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, VALUE ary)
{
rb_encoding *enc;
@@ -8379,7 +8685,7 @@ rb_str_enumerate_bytes(VALUE str, VALUE ary)
long i;
for (i=0; i<RSTRING_LEN(str); i++) {
- ENUM_ELEM(ary, INT2FIX(RSTRING_PTR(str)[i] & 0xff));
+ ENUM_ELEM(ary, INT2FIX((unsigned char)RSTRING_PTR(str)[i]));
}
if (ary)
return ary;
@@ -8798,6 +9104,37 @@ rb_str_chop(VALUE str)
return rb_str_subseq(str, 0, chopped_length(str));
}
+static long
+smart_chomp(VALUE str, const char *e, const char *p)
+{
+ rb_encoding *enc = rb_enc_get(str);
+ if (rb_enc_mbminlen(enc) > 1) {
+ const char *pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
+ if (rb_enc_is_newline(pp, e, enc)) {
+ e = pp;
+ }
+ pp = e - rb_enc_mbminlen(enc);
+ if (pp >= p) {
+ pp = rb_enc_left_char_head(p, pp, e, enc);
+ if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
+ e = pp;
+ }
+ }
+ }
+ else {
+ switch (*(e-1)) { /* not e[-1] to get rid of VC bug */
+ case '\n':
+ if (--e > p && *(e-1) == '\r') {
+ --e;
+ }
+ break;
+ case '\r':
+ --e;
+ break;
+ }
+ }
+ return e - p;
+}
static long
chompped_length(VALUE str, VALUE rs)
@@ -8812,34 +9149,7 @@ chompped_length(VALUE str, VALUE rs)
if (len == 0) return 0;
e = p + len;
if (rs == rb_default_rs) {
- smart_chomp:
- enc = rb_enc_get(str);
- if (rb_enc_mbminlen(enc) > 1) {
- pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
- if (rb_enc_is_newline(pp, e, enc)) {
- e = pp;
- }
- pp = e - rb_enc_mbminlen(enc);
- if (pp >= p) {
- pp = rb_enc_left_char_head(p, pp, e, enc);
- if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
- e = pp;
- }
- }
- }
- else {
- switch (*(e-1)) { /* not e[-1] to get rid of VC bug */
- case '\n':
- if (--e > p && *(e-1) == '\r') {
- --e;
- }
- break;
- case '\r':
- --e;
- break;
- }
- }
- return e - p;
+ return smart_chomp(str, e, p);
}
enc = rb_enc_get(str);
@@ -8875,11 +9185,11 @@ chompped_length(VALUE str, VALUE rs)
if (rslen == rb_enc_mbminlen(enc)) {
if (rslen == 1) {
if (newline == '\n')
- goto smart_chomp;
+ return smart_chomp(str, e, p);
}
else {
if (rb_enc_is_newline(rsptr, rsptr+rslen, enc))
- goto smart_chomp;
+ return smart_chomp(str, e, p);
}
}
@@ -8979,7 +9289,7 @@ static VALUE
rb_str_chomp(int argc, VALUE *argv, VALUE str)
{
VALUE rs = chomp_rs(argc, argv);
- if (NIL_P(rs)) return rb_str_dup(str);
+ if (NIL_P(rs)) return str_duplicate(rb_cString, str);
return rb_str_subseq(str, 0, chompped_length(str, rs));
}
@@ -8992,14 +9302,14 @@ lstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
/* remove spaces at head */
if (single_byte_optimizable(str)) {
- while (s < e && ascii_isspace(*s)) s++;
+ while (s < e && (*s == '\0' || ascii_isspace(*s))) s++;
}
else {
while (s < e) {
int n;
unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
- if (!rb_isspace(cc)) break;
+ if (cc && !rb_isspace(cc)) break;
s += n;
}
}
@@ -9066,7 +9376,7 @@ rb_str_lstrip(VALUE str)
long len, loffset;
RSTRING_GETMEM(str, start, len);
loffset = lstrip_offset(str, start, start+len, STR_ENC_GET(str));
- if (loffset <= 0) return rb_str_dup(str);
+ if (loffset <= 0) return str_duplicate(rb_cString, str);
return rb_str_subseq(str, loffset, len - loffset);
}
@@ -9159,7 +9469,7 @@ rb_str_rstrip(VALUE str)
RSTRING_GETMEM(str, start, olen);
roffset = rstrip_offset(str, start, start+olen, enc);
- if (roffset <= 0) return rb_str_dup(str);
+ if (roffset <= 0) return str_duplicate(rb_cString, str);
return rb_str_subseq(str, 0, olen-roffset);
}
@@ -9232,7 +9542,7 @@ rb_str_strip(VALUE str)
loffset = lstrip_offset(str, start, start+olen, enc);
roffset = rstrip_offset(str, start+loffset, start+olen, enc);
- if (loffset <= 0 && roffset <= 0) return rb_str_dup(str);
+ if (loffset <= 0 && roffset <= 0) return str_duplicate(rb_cString, str);
return rb_str_subseq(str, loffset, olen-loffset-roffset);
}
@@ -9479,8 +9789,7 @@ rb_str_crypt(VALUE str, VALUE salt)
mustnot_wchar(str);
mustnot_wchar(salt);
if (RSTRING_LEN(salt) < 2) {
- short_salt:
- rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
+ goto short_salt;
}
s = StringValueCStr(str);
@@ -9511,6 +9820,10 @@ rb_str_crypt(VALUE str, VALUE salt)
result = rb_str_new_cstr(res);
CRYPT_END();
return result;
+
+ short_salt:
+ rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
+ UNREACHABLE_RETURN(Qundef);
}
@@ -9523,7 +9836,7 @@ rb_str_crypt(VALUE str, VALUE salt)
* "a".ord #=> 97
*/
-VALUE
+static VALUE
rb_str_ord(VALUE s)
{
unsigned int c;
@@ -9625,7 +9938,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
}
}
len = str_strlen(str, enc); /* rb_enc_check */
- if (width < 0 || len >= width) return rb_str_dup(str);
+ if (width < 0 || len >= width) return str_duplicate(rb_cString, str);
n = width - len;
llen = (jflag == 'l') ? 0 : ((jflag == 'r') ? n : n/2);
rlen = n - llen;
@@ -9641,7 +9954,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
rb_raise(rb_eArgError, "argument too big");
}
len += size;
- res = str_new0(rb_obj_class(str), 0, len, termlen);
+ res = str_new0(rb_cString, 0, len, termlen);
p = RSTRING_PTR(res);
if (flen <= 1) {
memset(p, *f, llen);
@@ -9769,13 +10082,14 @@ rb_str_partition(VALUE str, VALUE sep)
sep = get_pat_quoted(sep, 0);
if (RB_TYPE_P(sep, T_REGEXP)) {
- pos = rb_reg_search(sep, str, 0, 0);
- if (pos < 0) {
- failed:
- return rb_ary_new3(3, rb_str_dup(str), str_new_empty(str), str_new_empty(str));
+ if (rb_reg_search(sep, str, 0, 0) < 0) {
+ goto failed;
}
- sep = rb_str_subpat(str, sep, INT2FIX(0));
- if (pos == 0 && RSTRING_LEN(sep) == 0) goto failed;
+ VALUE match = rb_backref_get();
+ struct re_registers *regs = RMATCH_REGS(match);
+
+ pos = BEG(0);
+ sep = rb_str_subseq(str, pos, END(0) - pos);
}
else {
pos = rb_str_index(str, sep, 0);
@@ -9785,6 +10099,9 @@ rb_str_partition(VALUE str, VALUE sep)
sep,
rb_str_subseq(str, pos+RSTRING_LEN(sep),
RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
+
+ failed:
+ return rb_ary_new3(3, str_duplicate(rb_cString, str), str_new_empty_String(str), str_new_empty_String(str));
}
/*
@@ -9800,43 +10117,53 @@ rb_str_partition(VALUE str, VALUE sep)
* "hello".rpartition("l") #=> ["hel", "l", "o"]
* "hello".rpartition("x") #=> ["", "", "hello"]
* "hello".rpartition(/.l/) #=> ["he", "ll", "o"]
+ *
+ * The match from the end means starting at the possible last position, not
+ * the last of longest matches.
+ *
+ * "hello".rpartition(/l+/) #=> ["hel", "l", "o"]
+ *
+ * To partition at the last longest match, needs to combine with
+ * negative lookbehind.
+ *
+ * "hello".rpartition(/(?<!l)l+/) #=> ["he", "ll", "o"]
+ *
+ * Or String#partition with negative lookforward.
+ *
+ * "hello".partition(/l+(?!.*l)/) #=> ["he", "ll", "o"]
*/
static VALUE
rb_str_rpartition(VALUE str, VALUE sep)
{
long pos = RSTRING_LEN(str);
- int regex = FALSE;
+ sep = get_pat_quoted(sep, 0);
if (RB_TYPE_P(sep, T_REGEXP)) {
- pos = rb_reg_search(sep, str, pos, 1);
- regex = TRUE;
+ if (rb_reg_search(sep, str, pos, 1) < 0) {
+ goto failed;
+ }
+ VALUE match = rb_backref_get();
+ struct re_registers *regs = RMATCH_REGS(match);
+
+ pos = BEG(0);
+ sep = rb_str_subseq(str, pos, END(0) - pos);
}
else {
- VALUE tmp;
-
- tmp = rb_check_string_type(sep);
- if (NIL_P(tmp)) {
- rb_raise(rb_eTypeError, "type mismatch: %s given",
- rb_obj_classname(sep));
- }
- sep = tmp;
pos = rb_str_sublen(str, pos);
pos = rb_str_rindex(str, sep, pos);
+ if(pos < 0) {
+ goto failed;
+ }
+ pos = rb_str_offset(str, pos);
}
- if (pos < 0) {
- return rb_ary_new3(3, str_new_empty(str), str_new_empty(str), rb_str_dup(str));
- }
- if (regex) {
- sep = rb_reg_nth_match(0, rb_backref_get());
- }
- else {
- pos = rb_str_offset(str, pos);
- }
+
return rb_ary_new3(3, rb_str_subseq(str, 0, pos),
sep,
rb_str_subseq(str, pos+RSTRING_LEN(sep),
RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
+ failed:
+ return rb_ary_new3(3, str_new_empty_String(str), str_new_empty_String(str), str_duplicate(rb_cString, str));
}
/*
@@ -9982,7 +10309,7 @@ rb_str_delete_prefix(VALUE str, VALUE prefix)
long prefixlen;
prefixlen = deleted_prefix_length(str, prefix);
- if (prefixlen <= 0) return rb_str_dup(str);
+ if (prefixlen <= 0) return str_duplicate(rb_cString, str);
return rb_str_subseq(str, prefixlen, RSTRING_LEN(str) - prefixlen);
}
@@ -10068,7 +10395,7 @@ rb_str_delete_suffix(VALUE str, VALUE suffix)
long suffixlen;
suffixlen = deleted_suffix_length(str, suffix);
- if (suffixlen <= 0) return rb_str_dup(str);
+ if (suffixlen <= 0) return str_duplicate(rb_cString, str);
return rb_str_subseq(str, 0, RSTRING_LEN(str) - suffixlen);
}
@@ -10199,7 +10526,7 @@ rb_str_ellipsize(VALUE str, long len)
else if (len <= ellipsislen ||
!(e = rb_enc_step_back(p, e, e, len = ellipsislen, enc))) {
if (rb_enc_asciicompat(enc)) {
- ret = rb_str_new_with_class(str, ellipsis, len);
+ ret = rb_str_new(ellipsis, len);
rb_enc_associate(ret, enc);
}
else {
@@ -10524,7 +10851,7 @@ str_scrub(int argc, VALUE *argv, VALUE str)
{
VALUE repl = argc ? (rb_check_arity(argc, 0, 1), argv[0]) : Qnil;
VALUE new = rb_str_scrub(str, repl);
- return NIL_P(new) ? rb_str_dup(str): new;
+ return NIL_P(new) ? str_duplicate(rb_cString, str): new;
}
/*
@@ -10776,6 +11103,26 @@ sym_inspect(VALUE sym)
return str;
}
+#if 0 /* for RDoc */
+/*
+ * call-seq:
+ * sym.name -> string
+ *
+ * Returns the name or string corresponding to <i>sym</i>. Unlike #to_s, the
+ * returned string is frozen.
+ *
+ * :fred.name #=> "fred"
+ * :fred.name.frozen? #=> true
+ * :fred.to_s #=> "fred"
+ * :fred.to_s.frozen? #=> false
+ */
+VALUE
+rb_sym2str(VALUE sym)
+{
+
+}
+#endif
+
/*
* call-seq:
@@ -10786,6 +11133,9 @@ sym_inspect(VALUE sym)
*
* :fred.id2name #=> "fred"
* :ginger.to_s #=> "ginger"
+ *
+ * Note that this string is not frozen (unlike the symbol itself).
+ * To get a frozen string, use #name.
*/
@@ -11184,6 +11534,42 @@ sym_all_symbols(VALUE _)
return rb_sym_all_symbols();
}
+VALUE
+rb_str_to_interned_str(VALUE str)
+{
+ return rb_fstring(str);
+}
+
+VALUE
+rb_interned_str(const char *ptr, long len)
+{
+ struct RString fake_str;
+ return register_fstring(setup_fake_str(&fake_str, ptr, len, ENCINDEX_US_ASCII), TRUE);
+}
+
+VALUE
+rb_interned_str_cstr(const char *ptr)
+{
+ return rb_interned_str(ptr, strlen(ptr));
+}
+
+VALUE
+rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc)
+{
+ if (UNLIKELY(rb_enc_autoload_p(enc))) {
+ rb_enc_autoload(enc);
+ }
+
+ struct RString fake_str;
+ return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), TRUE);
+}
+
+VALUE
+rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc)
+{
+ return rb_enc_interned_str(ptr, strlen(ptr), enc);
+}
+
/*
* A String object holds and manipulates an arbitrary sequence of
* bytes, typically representing characters. String objects may be created
@@ -11200,9 +11586,6 @@ sym_all_symbols(VALUE _)
void
Init_String(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
rb_cString = rb_define_class("String", rb_cObject);
assert(rb_vm_fstring_table());
st_foreach(rb_vm_fstring_table(), fstring_set_class_i, rb_cString);
@@ -11258,10 +11641,10 @@ Init_String(void)
rb_define_method(rb_cString, "dump", rb_str_dump, 0);
rb_define_method(rb_cString, "undump", str_undump, 0);
- sym_ascii = ID2SYM(rb_intern("ascii"));
- sym_turkic = ID2SYM(rb_intern("turkic"));
- sym_lithuanian = ID2SYM(rb_intern("lithuanian"));
- sym_fold = ID2SYM(rb_intern("fold"));
+ sym_ascii = ID2SYM(rb_intern_const("ascii"));
+ sym_turkic = ID2SYM(rb_intern_const("turkic"));
+ sym_lithuanian = ID2SYM(rb_intern_const("lithuanian"));
+ sym_fold = ID2SYM(rb_intern_const("fold"));
rb_define_method(rb_cString, "upcase", rb_str_upcase, -1);
rb_define_method(rb_cString, "downcase", rb_str_downcase, -1);
@@ -11354,8 +11737,8 @@ Init_String(void)
/* define UnicodeNormalize module here so that we don't have to look it up */
mUnicodeNormalize = rb_define_module("UnicodeNormalize");
- id_normalize = rb_intern("normalize");
- id_normalized_p = rb_intern("normalized?");
+ id_normalize = rb_intern_const("normalize");
+ id_normalized_p = rb_intern_const("normalized?");
rb_define_method(rb_cString, "unicode_normalize", rb_str_unicode_normalize, -1);
rb_define_method(rb_cString, "unicode_normalize!", rb_str_unicode_normalize_bang, -1);
@@ -11377,6 +11760,7 @@ Init_String(void)
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
rb_define_method(rb_cSymbol, "to_s", rb_sym_to_s, 0);
rb_define_method(rb_cSymbol, "id2name", rb_sym_to_s, 0);
+ rb_define_method(rb_cSymbol, "name", rb_sym2str, 0);
rb_define_method(rb_cSymbol, "intern", sym_to_sym, 0);
rb_define_method(rb_cSymbol, "to_sym", sym_to_sym, 0);
rb_define_method(rb_cSymbol, "to_proc", rb_sym_to_proc, 0);
diff --git a/struct.c b/struct.c
index 3fb5649c99..d62b6ca021 100644
--- a/struct.c
+++ b/struct.c
@@ -9,10 +9,18 @@
**********************************************************************/
-#include "internal.h"
-#include "vm_core.h"
#include "id.h"
+#include "internal.h"
+#include "internal/class.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/object.h"
+#include "internal/proc.h"
+#include "internal/struct.h"
+#include "internal/symbol.h"
#include "transient_heap.h"
+#include "vm_core.h"
+#include "builtin.h"
/* only for struct[:field] access */
enum {
@@ -20,8 +28,8 @@ enum {
AREF_HASH_THRESHOLD = 10
};
-const rb_iseq_t *rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func);
-const rb_iseq_t *rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func);
+const rb_iseq_t *rb_method_for_self_aref(VALUE name, VALUE arg, const struct rb_builtin_function *func);
+const rb_iseq_t *rb_method_for_self_aset(VALUE name, VALUE arg, const struct rb_builtin_function *func);
VALUE rb_cStruct;
static ID id_members, id_back_members, id_keyword_init;
@@ -281,11 +289,42 @@ new_struct(VALUE name, VALUE super)
return rb_define_class_id_under(super, id, super);
}
+NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx));
+
+static inline long
+struct_pos_num(VALUE s, VALUE idx)
+{
+ long i = NUM2INT(idx);
+ if (i < 0 || i >= RSTRUCT_LEN(s)) invalid_struct_pos(s, idx);
+ return i;
+}
+
+static VALUE
+opt_struct_aref(rb_execution_context_t *ec, VALUE self, VALUE idx)
+{
+ long i = struct_pos_num(self, idx);
+ return RSTRUCT_GET(self, i);
+}
+
+static VALUE
+opt_struct_aset(rb_execution_context_t *ec, VALUE self, VALUE val, VALUE idx)
+{
+ long i = struct_pos_num(self, idx);
+ rb_struct_modify(self);
+ RSTRUCT_SET(self, i, val);
+ return val;
+}
+
+static const struct rb_builtin_function struct_aref_builtin =
+ RB_BUILTIN_FUNCTION(0, struct_aref, opt_struct_aref, 1, 0);
+static const struct rb_builtin_function struct_aset_builtin =
+ RB_BUILTIN_FUNCTION(1, struct_aref, opt_struct_aset, 2, 0);
+
static void
define_aref_method(VALUE nstr, VALUE name, VALUE off)
{
- rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aref)(rb_execution_context_t *, rb_control_frame_t *);
- const rb_iseq_t *iseq = rb_method_for_self_aref(name, off, rb_vm_opt_struct_aref);
+ const rb_iseq_t *iseq = rb_method_for_self_aref(name, off, &struct_aref_builtin);
+ iseq->body->builtin_inline_p = true;
rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC);
}
@@ -293,8 +332,7 @@ define_aref_method(VALUE nstr, VALUE name, VALUE off)
static void
define_aset_method(VALUE nstr, VALUE name, VALUE off)
{
- rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_execution_context_t *, rb_control_frame_t *);
- const rb_iseq_t *iseq = rb_method_for_self_aset(name, off, rb_vm_opt_struct_aset);
+ const rb_iseq_t *iseq = rb_method_for_self_aset(name, off, &struct_aset_builtin);
rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, METHOD_VISI_PUBLIC);
}
@@ -310,12 +348,6 @@ rb_struct_s_inspect(VALUE klass)
}
static VALUE
-struct_new_kw(int argc, const VALUE *argv, VALUE klass)
-{
- return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
-}
-
-static VALUE
setup_struct(VALUE nstr, VALUE members)
{
long i, len;
@@ -323,8 +355,8 @@ setup_struct(VALUE nstr, VALUE members)
members = struct_set_members(nstr, members);
rb_define_alloc_func(nstr, struct_alloc);
- rb_define_singleton_method(nstr, "new", struct_new_kw, -1);
- rb_define_singleton_method(nstr, "[]", struct_new_kw, -1);
+ rb_define_singleton_method(nstr, "new", rb_class_new_instance_pass_kw, -1);
+ rb_define_singleton_method(nstr, "[]", rb_class_new_instance_pass_kw, -1);
rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0);
rb_define_singleton_method(nstr, "inspect", rb_struct_s_inspect, 0);
len = RARRAY_LEN(members);
@@ -356,9 +388,10 @@ struct_make_members_list(va_list ar)
{
char *mem;
VALUE ary, list = rb_ident_hash_new();
- st_table *tbl = RHASH_TBL(list);
+ st_table *tbl = RHASH_TBL_RAW(list);
RBASIC_CLEAR_CLASS(list);
+ OBJ_WB_UNPROTECT(list);
while ((mem = va_arg(ar, char*)) != 0) {
VALUE sym = rb_sym_intern_ascii_cstr(mem);
if (st_insert(tbl, sym, Qtrue)) {
@@ -551,7 +584,8 @@ rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
rest = rb_ident_hash_new();
RBASIC_CLEAR_CLASS(rest);
- tbl = RHASH_TBL(rest);
+ OBJ_WB_UNPROTECT(rest);
+ tbl = RHASH_TBL_RAW(rest);
for (i=0; i<argc; i++) {
VALUE mem = rb_to_symbol(argv[i]);
if (rb_is_attrset_sym(mem)) {
@@ -658,7 +692,9 @@ rb_struct_initialize_m(int argc, const VALUE *argv, VALUE self)
VALUE
rb_struct_initialize(VALUE self, VALUE values)
{
- return rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self);
+ rb_struct_initialize_m(RARRAY_LENINT(values), RARRAY_CONST_PTR(values), self);
+ RB_GC_GUARD(values);
+ return Qnil;
}
static VALUE *
@@ -811,7 +847,7 @@ rb_struct_each_pair(VALUE s)
RETURN_SIZED_ENUMERATOR(s, 0, 0, struct_enum_size);
members = rb_struct_members(s);
- if (rb_block_arity() > 1) {
+ if (rb_block_pair_yield_optimizable()) {
for (i=0; i<RSTRUCT_LEN(s); i++) {
VALUE key = rb_ary_entry(members, i);
VALUE value = RSTRUCT_GET(s, i);
@@ -1020,7 +1056,6 @@ rb_struct_pos(VALUE s, VALUE *name)
}
}
-NORETURN(static void invalid_struct_pos(VALUE s, VALUE idx));
static void
invalid_struct_pos(VALUE s, VALUE idx)
{
@@ -1295,18 +1330,21 @@ rb_struct_size(VALUE s)
/*
* call-seq:
- * struct.dig(key, ...) -> object
+ * struct.dig(key, *identifiers) -> object
*
- * Extracts the nested value specified by the sequence of +key+
- * objects by calling +dig+ at each step, returning +nil+ if any
- * intermediate step is +nil+.
+ * 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:doc/dig_methods.rdoc].
*
+ * Examples:
* Foo = Struct.new(:a)
* f = Foo.new(Foo.new({b: [1, 2, 3]}))
- *
- * f.dig(:a, :a, :b, 0) # => 1
- * f.dig(:b, 0) # => nil
- * f.dig(:a, :a, :b, :c) # TypeError: no implicit conversion of Symbol into Integer
+ * f.dig(:a) # => #<struct Foo a={:b=>[1, 2, 3]}>
+ * f.dig(:a, :a) # => {:b=>[1, 2, 3]}
+ * f.dig(:a, :a, :b) # => [1, 2, 3]
+ * f.dig(:a, :a, :b, 0) # => 1
+ * f.dig(:b, 0) # => nil
*/
static VALUE
diff --git a/symbol.c b/symbol.c
index 14517df01e..1a46985531 100644
--- a/symbol.c
+++ b/symbol.c
@@ -9,13 +9,23 @@
**********************************************************************/
+#include "gc.h"
+#include "internal.h"
+#include "internal/error.h"
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/object.h"
+#include "internal/symbol.h"
+#include "internal/vm.h"
+#include "probes.h"
#include "ruby/encoding.h"
#include "ruby/st.h"
-#include "internal.h"
#include "symbol.h"
-#include "gc.h"
-#include "probes.h"
+#include "vm_sync.h"
+#ifndef USE_SYMBOL_GC
+# define USE_SYMBOL_GC 1
+#endif
#ifndef SYMBOL_DEBUG
# define SYMBOL_DEBUG 0
#endif
@@ -64,7 +74,6 @@ enum id_entry_type {
};
rb_symbols_t ruby_global_symbols = {tNEXT_ID-1};
-#define global_symbols ruby_global_symbols
static const struct st_hash_type symhash = {
rb_str_hash_cmp,
@@ -74,26 +83,32 @@ static const struct st_hash_type symhash = {
void
Init_sym(void)
{
+ rb_symbols_t *symbols = &ruby_global_symbols;
+
VALUE dsym_fstrs = rb_ident_hash_new();
- global_symbols.dsymbol_fstr_hash = dsym_fstrs;
+ symbols->dsymbol_fstr_hash = dsym_fstrs;
rb_gc_register_mark_object(dsym_fstrs);
rb_obj_hide(dsym_fstrs);
- global_symbols.str_sym = st_init_table_with_size(&symhash, 1000);
- global_symbols.ids = rb_ary_tmp_new(0);
- rb_gc_register_mark_object(global_symbols.ids);
+ symbols->str_sym = st_init_table_with_size(&symhash, 1000);
+ symbols->ids = rb_ary_tmp_new(0);
+ rb_gc_register_mark_object(symbols->ids);
Init_op_tbl();
Init_id();
}
-WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type));
-WARN_UNUSED_RESULT(static VALUE dsymbol_check(const VALUE sym));
+WARN_UNUSED_RESULT(static VALUE dsymbol_alloc(rb_symbols_t *symbols, const VALUE klass, const VALUE str, rb_encoding *const enc, const ID type));
+WARN_UNUSED_RESULT(static VALUE dsymbol_check(rb_symbols_t *symbols, const VALUE sym));
WARN_UNUSED_RESULT(static ID lookup_str_id(VALUE str));
+WARN_UNUSED_RESULT(static VALUE lookup_str_sym_with_lock(rb_symbols_t *symbols, const VALUE str));
WARN_UNUSED_RESULT(static VALUE lookup_str_sym(const VALUE str));
WARN_UNUSED_RESULT(static VALUE lookup_id_str(ID id));
WARN_UNUSED_RESULT(static ID intern_str(VALUE str, int mutable));
+#define GLOBAL_SYMBOLS_ENTER(symbols) rb_symbols_t *symbols = &ruby_global_symbols; RB_VM_LOCK_ENTER()
+#define GLOBAL_SYMBOLS_LEAVE() RB_VM_LOCK_LEAVE()
+
ID
rb_id_attrset(ID id)
{
@@ -229,109 +244,162 @@ rb_sym_constant_char_p(const char *name, long nlen, rb_encoding *enc)
#define IDSET_ATTRSET_FOR_SYNTAX ((1U<<ID_LOCAL)|(1U<<ID_CONST))
#define IDSET_ATTRSET_FOR_INTERN (~(~0U<<(1<<ID_SCOPE_SHIFT)) & ~(1U<<ID_ATTRSET))
-int
-rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset)
+struct enc_synmane_type_leading_chars_tag {
+ const enum { invalid, stophere, needmore, } kind;
+ const enum ruby_id_types type;
+ const long nread;
+};
+
+#define t struct enc_synmane_type_leading_chars_tag
+
+static struct enc_synmane_type_leading_chars_tag
+enc_synmane_type_leading_chars(const char *name, long len, rb_encoding *enc, int allowed_attrset)
{
const char *m = name;
const char *e = m + len;
- int type = ID_JUNK;
- if (!rb_enc_asciicompat(enc)) return -1;
- if (!m || len <= 0) return -1;
+ if (! rb_enc_asciicompat(enc)) {
+ return (t) { invalid, 0, 0, };
+ }
+ else if (! m) {
+ return (t) { invalid, 0, 0, };
+ }
+ else if ( len <= 0 ) {
+ return (t) { invalid, 0, 0, };
+ }
switch (*m) {
case '\0':
- return -1;
+ return (t) { invalid, 0, 0, };
case '$':
- type = ID_GLOBAL;
- if (is_special_global_name(++m, e, enc)) return type;
- goto id;
+ if (is_special_global_name(++m, e, enc)) {
+ return (t) { stophere, ID_GLOBAL, len, };
+ }
+ else {
+ return (t) { needmore, ID_GLOBAL, 1, };
+ }
case '@':
- type = ID_INSTANCE;
- if (*++m == '@') {
- ++m;
- type = ID_CLASS;
- }
- goto id;
+ switch (*++m) {
+ default: return (t) { needmore, ID_INSTANCE, 1, };
+ case '@': return (t) { needmore, ID_CLASS, 2, };
+ }
case '<':
switch (*++m) {
- case '<': ++m; break;
- case '=': if (*++m == '>') ++m; break;
- default: break;
+ default: return (t) { stophere, ID_JUNK, 1, };
+ case '<': return (t) { stophere, ID_JUNK, 2, };
+ case '=':
+ switch (*++m) {
+ default: return (t) { stophere, ID_JUNK, 2, };
+ case '>': return (t) { stophere, ID_JUNK, 3, };
+ }
}
- break;
case '>':
switch (*++m) {
- case '>': case '=': ++m; break;
+ default: return (t) { stophere, ID_JUNK, 1, };
+ case '>': case '=': return (t) { stophere, ID_JUNK, 2, };
}
- break;
case '=':
switch (*++m) {
- case '~': ++m; break;
- case '=': if (*++m == '=') ++m; break;
- default: return -1;
+ default: return (t) { invalid, 0, 1, };
+ case '~': return (t) { stophere, ID_JUNK, 2, };
+ case '=':
+ switch (*++m) {
+ default: return (t) { stophere, ID_JUNK, 2, };
+ case '=': return (t) { stophere, ID_JUNK, 3, };
+ }
}
- break;
case '*':
- if (*++m == '*') ++m;
- break;
+ switch (*++m) {
+ default: return (t) { stophere, ID_JUNK, 1, };
+ case '*': return (t) { stophere, ID_JUNK, 2, };
+ }
case '+': case '-':
- if (*++m == '@') ++m;
- break;
+ switch (*++m) {
+ default: return (t) { stophere, ID_JUNK, 1, };
+ case '@': return (t) { stophere, ID_JUNK, 2, };
+ }
case '|': case '^': case '&': case '/': case '%': case '~': case '`':
- ++m;
- break;
+ return (t) { stophere, ID_JUNK, 1, };
case '[':
- if (m[1] != ']') goto id;
- ++m;
- if (*++m == '=') ++m;
- break;
+ switch (*++m) {
+ default: return (t) { needmore, ID_JUNK, 0, };
+ case ']':
+ switch (*++m) {
+ default: return (t) { stophere, ID_JUNK, 2, };
+ case '=': return (t) { stophere, ID_JUNK, 3, };
+ }
+ }
case '!':
- if (len == 1) return ID_JUNK;
switch (*++m) {
- case '=': case '~': ++m; break;
+ case '=': case '~': return (t) { stophere, ID_JUNK, 2, };
default:
- if (allowed_attrset & (1U << ID_JUNK)) goto id;
- return -1;
+ if (allowed_attrset & (1U << ID_JUNK)) {
+ return (t) { needmore, ID_JUNK, 1, };
+ }
+ else {
+ return (t) { stophere, ID_JUNK, 1, };
+ }
}
- break;
default:
- type = rb_sym_constant_char_p(m, e-m, enc) ? ID_CONST : ID_LOCAL;
- id:
- if (m >= e || (*m != '_' && !ISALPHA(*m) && ISASCII(*m))) {
- if (len > 1 && *(e-1) == '=') {
- type = rb_enc_symname_type(name, len-1, enc, allowed_attrset);
- if (type != ID_ATTRSET) return ID_ATTRSET;
- }
- return -1;
- }
- while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
- if (m >= e) break;
- switch (*m) {
- case '!': case '?':
- if (type == ID_GLOBAL || type == ID_CLASS || type == ID_INSTANCE) return -1;
- type = ID_JUNK;
- ++m;
- if (m + 1 < e || *m != '=') break;
- /* fall through */
- case '=':
- if (!(allowed_attrset & (1U << type))) return -1;
- type = ID_ATTRSET;
- ++m;
- break;
- }
- break;
+ if (rb_sym_constant_char_p(name, len, enc)) {
+ return (t) { needmore, ID_CONST, 0, };
+ }
+ else {
+ return (t) { needmore, ID_LOCAL, 0, };
+ }
+ }
+}
+#undef t
+
+int
+rb_enc_symname_type(const char *name, long len, rb_encoding *enc, unsigned int allowed_attrset)
+{
+ const struct enc_synmane_type_leading_chars_tag f =
+ enc_synmane_type_leading_chars(name, len, enc, allowed_attrset);
+ const char *m = name + f.nread;
+ const char *e = name + len;
+ int type = (int)f.type;
+
+ switch (f.kind) {
+ case invalid: return -1;
+ case stophere: goto stophere;
+ case needmore: break;
}
+
+ if (m >= e || (*m != '_' && !ISALPHA(*m) && ISASCII(*m))) {
+ if (len > 1 && *(e-1) == '=') {
+ type = rb_enc_symname_type(name, len-1, enc, allowed_attrset);
+ if (type != ID_ATTRSET) return ID_ATTRSET;
+ }
+ return -1;
+ }
+ while (m < e && is_identchar(m, e, enc)) m += rb_enc_mbclen(m, e, enc);
+ if (m >= e) goto stophere;
+ switch (*m) {
+ case '!': case '?':
+ if (type == ID_GLOBAL || type == ID_CLASS || type == ID_INSTANCE) return -1;
+ type = ID_JUNK;
+ ++m;
+ if (m + 1 < e || *m != '=') break;
+ /* fall through */
+ case '=':
+ if (!(allowed_attrset & (1U << type))) return -1;
+ type = ID_ATTRSET;
+ ++m;
+ break;
+ }
+
+ stophere:
return m == e ? type : -1;
}
@@ -352,10 +420,12 @@ rb_str_symname_type(VALUE name, unsigned int allowed_attrset)
}
static void
-set_id_entry(rb_id_serial_t num, VALUE str, VALUE sym)
+set_id_entry(rb_symbols_t *symbols, rb_id_serial_t num, VALUE str, VALUE sym)
{
+ ASSERT_vm_locking();
size_t idx = num / ID_ENTRY_UNIT;
- VALUE ary, ids = global_symbols.ids;
+
+ VALUE ary, ids = symbols->ids;
if (idx >= (size_t)RARRAY_LEN(ids) || NIL_P(ary = rb_ary_entry(ids, (long)idx))) {
ary = rb_ary_tmp_new(ID_ENTRY_UNIT * ID_ENTRY_SIZE);
rb_ary_store(ids, (long)idx, ary);
@@ -368,31 +438,42 @@ set_id_entry(rb_id_serial_t num, VALUE str, VALUE sym)
static VALUE
get_id_serial_entry(rb_id_serial_t num, ID id, const enum id_entry_type t)
{
- if (num && num <= global_symbols.last_id) {
- size_t idx = num / ID_ENTRY_UNIT;
- VALUE ids = global_symbols.ids;
- VALUE ary;
- if (idx < (size_t)RARRAY_LEN(ids) && !NIL_P(ary = rb_ary_entry(ids, (long)idx))) {
- long pos = (long)(num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE;
- VALUE result = rb_ary_entry(ary, pos + t);
- if (NIL_P(result)) return 0;
-#if CHECK_ID_SERIAL
- if (id) {
- VALUE sym = result;
- if (t != ID_ENTRY_SYM)
- sym = rb_ary_entry(ary, pos + ID_ENTRY_SYM);
- if (STATIC_SYM_P(sym)) {
- if (STATIC_SYM2ID(sym) != id) return 0;
+ VALUE result = 0;
+
+ GLOBAL_SYMBOLS_ENTER(symbols);
+ {
+ if (num && num <= symbols->last_id) {
+ size_t idx = num / ID_ENTRY_UNIT;
+ VALUE ids = symbols->ids;
+ VALUE ary;
+ if (idx < (size_t)RARRAY_LEN(ids) && !NIL_P(ary = rb_ary_entry(ids, (long)idx))) {
+ long pos = (long)(num % ID_ENTRY_UNIT) * ID_ENTRY_SIZE;
+ result = rb_ary_entry(ary, pos + t);
+
+ if (NIL_P(result)) {
+ result = 0;
}
else {
- if (RSYMBOL(sym)->id != id) return 0;
+#if CHECK_ID_SERIAL
+ if (id) {
+ VALUE sym = result;
+ if (t != ID_ENTRY_SYM)
+ sym = rb_ary_entry(ary, pos + ID_ENTRY_SYM);
+ if (STATIC_SYM_P(sym)) {
+ if (STATIC_SYM2ID(sym) != id) result = 0;
+ }
+ else {
+ if (RSYMBOL(sym)->id != id) result = 0;
+ }
+ }
+#endif
}
}
-#endif
- return result;
- }
+ }
}
- return 0;
+ GLOBAL_SYMBOLS_LEAVE();
+
+ return result;
}
static VALUE
@@ -430,22 +511,26 @@ register_sym_update_callback(st_data_t *key, st_data_t *value, st_data_t arg, in
#endif
static void
-register_sym(VALUE str, VALUE sym)
+register_sym(rb_symbols_t *symbols, VALUE str, VALUE sym)
{
+ ASSERT_vm_locking();
+
#if SYMBOL_DEBUG
- st_update(global_symbols.str_sym, (st_data_t)str,
- register_sym_update_callback, (st_data_t)sym);
+ st_update(symbols->str_sym, (st_data_t)str,
+ register_sym_update_callback, (st_data_t)sym);
#else
- st_add_direct(global_symbols.str_sym, (st_data_t)str, (st_data_t)sym);
+ st_add_direct(symbols->str_sym, (st_data_t)str, (st_data_t)sym);
#endif
}
static void
-unregister_sym(VALUE str, VALUE sym)
+unregister_sym(rb_symbols_t *symbols, VALUE str, VALUE sym)
{
+ ASSERT_vm_locking();
+
st_data_t str_data = (st_data_t)str;
- if (!st_delete(global_symbols.str_sym, &str_data, NULL)) {
- rb_bug("%p can't remove str from str_id (%s)", (void *)sym, RSTRING_PTR(str));
+ if (!st_delete(symbols->str_sym, &str_data, NULL)) {
+ rb_bug("%p can't remove str from str_id (%s)", (void *)sym, RSTRING_PTR(str));
}
}
@@ -467,8 +552,12 @@ register_static_symid_str(ID id, VALUE str)
RUBY_DTRACE_CREATE_HOOK(SYMBOL, RSTRING_PTR(str));
- register_sym(str, sym);
- set_id_entry(num, str, sym);
+ GLOBAL_SYMBOLS_ENTER(symbols)
+ {
+ register_sym(symbols, str, sym);
+ set_id_entry(symbols, num, str, sym);
+ }
+ GLOBAL_SYMBOLS_LEAVE();
return id;
}
@@ -516,8 +605,10 @@ must_be_dynamic_symbol(VALUE x)
#endif
static VALUE
-dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc, const ID type)
+dsymbol_alloc(rb_symbols_t *symbols, const VALUE klass, const VALUE str, rb_encoding * const enc, const ID type)
{
+ ASSERT_vm_locking();
+
const VALUE dsym = rb_newobj_of(klass, T_SYMBOL | FL_WB_PROTECTED);
long hashval;
@@ -529,25 +620,24 @@ dsymbol_alloc(const VALUE klass, const VALUE str, rb_encoding * const enc, const
/* we want hashval to be in Fixnum range [ruby-core:15713] r15672 */
hashval = (long)rb_str_hash(str);
RSYMBOL(dsym)->hashval = RSHIFT((long)hashval, 1);
-
- register_sym(str, dsym);
- rb_hash_aset(global_symbols.dsymbol_fstr_hash, str, Qtrue);
-
+ register_sym(symbols, str, dsym);
+ rb_hash_aset(symbols->dsymbol_fstr_hash, str, Qtrue);
RUBY_DTRACE_CREATE_HOOK(SYMBOL, RSTRING_PTR(RSYMBOL(dsym)->fstr));
return dsym;
}
static inline VALUE
-dsymbol_check(const VALUE sym)
+dsymbol_check(rb_symbols_t *symbols, const VALUE sym)
{
+ ASSERT_vm_locking();
+
if (UNLIKELY(rb_objspace_garbage_object_p(sym))) {
const VALUE fstr = RSYMBOL(sym)->fstr;
const ID type = RSYMBOL(sym)->id & ID_SCOPE_MASK;
RSYMBOL(sym)->fstr = 0;
-
- unregister_sym(fstr, sym);
- return dsymbol_alloc(rb_cSymbol, fstr, rb_enc_get(fstr), type);
+ unregister_sym(symbols, fstr, sym);
+ return dsymbol_alloc(symbols, rb_cSymbol, fstr, rb_enc_get(fstr), type);
}
else {
return sym;
@@ -558,7 +648,15 @@ static ID
lookup_str_id(VALUE str)
{
st_data_t sym_data;
- if (st_lookup(global_symbols.str_sym, (st_data_t)str, &sym_data)) {
+ int found;
+
+ GLOBAL_SYMBOLS_ENTER(symbols);
+ {
+ found = st_lookup(symbols->str_sym, (st_data_t)str, &sym_data);
+ }
+ GLOBAL_SYMBOLS_LEAVE();
+
+ if (found) {
const VALUE sym = (VALUE)sym_data;
if (STATIC_SYM_P(sym)) {
@@ -577,23 +675,36 @@ lookup_str_id(VALUE str)
}
static VALUE
-lookup_str_sym(const VALUE str)
+lookup_str_sym_with_lock(rb_symbols_t *symbols, const VALUE str)
{
st_data_t sym_data;
- if (st_lookup(global_symbols.str_sym, (st_data_t)str, &sym_data)) {
- VALUE sym = (VALUE)sym_data;
-
- if (DYNAMIC_SYM_P(sym)) {
- sym = dsymbol_check(sym);
- }
- return sym;
+ if (st_lookup(symbols->str_sym, (st_data_t)str, &sym_data)) {
+ VALUE sym = (VALUE)sym_data;
+ if (DYNAMIC_SYM_P(sym)) {
+ sym = dsymbol_check(symbols, sym);
+ }
+ return sym;
}
else {
- return (VALUE)0;
+ return Qfalse;
}
}
static VALUE
+lookup_str_sym(const VALUE str)
+{
+ VALUE sym;
+
+ GLOBAL_SYMBOLS_ENTER(symbols);
+ {
+ sym = lookup_str_sym_with_lock(symbols, str);
+ }
+ GLOBAL_SYMBOLS_LEAVE();
+
+ return sym;
+}
+
+static VALUE
lookup_id_str(ID id)
{
return get_id_entry(id, ID_ENTRY_STR);
@@ -606,7 +717,6 @@ rb_intern3(const char *name, long len, rb_encoding *enc)
struct RString fake_str;
VALUE str = rb_setup_fake_str(&fake_str, name, len, enc);
OBJ_FREEZE(str);
-
sym = lookup_str_sym(str);
if (sym) return rb_sym2id(sym);
str = rb_enc_str_new(name, len, enc); /* make true string */
@@ -614,17 +724,32 @@ rb_intern3(const char *name, long len, rb_encoding *enc)
}
static ID
-next_id_base(void)
+next_id_base_with_lock(rb_symbols_t *symbols)
{
- rb_id_serial_t next_serial = global_symbols.last_id + 1;
+ ID id;
+ rb_id_serial_t next_serial = symbols->last_id + 1;
if (next_serial == 0) {
- return (ID)-1;
+ id = (ID)-1;
}
else {
- const size_t num = ++global_symbols.last_id;
- return num << ID_SCOPE_SHIFT;
+ const size_t num = ++symbols->last_id;
+ id = num << ID_SCOPE_SHIFT;
}
+
+ return id;
+}
+
+static ID
+next_id_base(void)
+{
+ ID id;
+ GLOBAL_SYMBOLS_ENTER(symbols);
+ {
+ id = next_id_base_with_lock(symbols);
+ }
+ GLOBAL_SYMBOLS_LEAVE();
+ return id;
}
static ID
@@ -681,8 +806,13 @@ rb_gc_free_dsymbol(VALUE sym)
if (str) {
RSYMBOL(sym)->fstr = 0;
- unregister_sym(str, sym);
- rb_hash_delete_entry(global_symbols.dsymbol_fstr_hash, str);
+
+ GLOBAL_SYMBOLS_ENTER(symbols);
+ {
+ unregister_sym(symbols, str, sym);
+ rb_hash_delete_entry(symbols->dsymbol_fstr_hash, str);
+ }
+ GLOBAL_SYMBOLS_LEAVE();
}
}
@@ -709,39 +839,46 @@ rb_gc_free_dsymbol(VALUE sym)
VALUE
rb_str_intern(VALUE str)
{
+ VALUE sym;
#if USE_SYMBOL_GC
rb_encoding *enc, *ascii;
int type;
#else
ID id;
#endif
- VALUE sym = lookup_str_sym(str);
-
- if (sym) {
- return sym;
- }
-
+ GLOBAL_SYMBOLS_ENTER(symbols);
+ {
+ sym = lookup_str_sym_with_lock(symbols, str);
+
+ if (sym) {
+ // ok
+ }
+ else {
#if USE_SYMBOL_GC
- enc = rb_enc_get(str);
- ascii = rb_usascii_encoding();
- if (enc != ascii && sym_check_asciionly(str)) {
- str = rb_str_dup(str);
- rb_enc_associate(str, ascii);
- OBJ_FREEZE(str);
- enc = ascii;
- }
- else {
- str = rb_str_dup(str);
- OBJ_FREEZE(str);
- }
- str = rb_fstring(str);
- type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
- if (type < 0) type = ID_JUNK;
- return dsymbol_alloc(rb_cSymbol, str, enc, type);
+ enc = rb_enc_get(str);
+ ascii = rb_usascii_encoding();
+ if (enc != ascii && sym_check_asciionly(str)) {
+ str = rb_str_dup(str);
+ rb_enc_associate(str, ascii);
+ OBJ_FREEZE(str);
+ enc = ascii;
+ }
+ else {
+ str = rb_str_dup(str);
+ OBJ_FREEZE(str);
+ }
+ str = rb_fstring(str);
+ type = rb_str_symname_type(str, IDSET_ATTRSET_FOR_INTERN);
+ if (type < 0) type = ID_JUNK;
+ sym = dsymbol_alloc(symbols, rb_cSymbol, str, enc, type);
#else
- id = intern_str(str, 0);
- return ID2SYM(id);
+ id = intern_str(str, 0);
+ sym = ID2SYM(id);
#endif
+ }
+ }
+ GLOBAL_SYMBOLS_LEAVE();
+ return sym;
}
ID
@@ -752,17 +889,23 @@ rb_sym2id(VALUE sym)
id = STATIC_SYM2ID(sym);
}
else if (DYNAMIC_SYM_P(sym)) {
- sym = dsymbol_check(sym);
- id = RSYMBOL(sym)->id;
- if (UNLIKELY(!(id & ~ID_SCOPE_MASK))) {
- VALUE fstr = RSYMBOL(sym)->fstr;
- ID num = next_id_base();
-
- RSYMBOL(sym)->id = id |= num;
- /* make it permanent object */
- set_id_entry(rb_id_to_serial(num), fstr, sym);
- rb_hash_delete_entry(global_symbols.dsymbol_fstr_hash, fstr);
+ GLOBAL_SYMBOLS_ENTER(symbols);
+ {
+ sym = dsymbol_check(symbols, sym);
+ id = RSYMBOL(sym)->id;
+
+ if (UNLIKELY(!(id & ~ID_SCOPE_MASK))) {
+ VALUE fstr = RSYMBOL(sym)->fstr;
+ ID num = next_id_base_with_lock(symbols);
+
+ RSYMBOL(sym)->id = id |= num;
+ /* make it permanent object */
+
+ set_id_entry(symbols, rb_id_to_serial(num), fstr, sym);
+ rb_hash_delete_entry(symbols->dsymbol_fstr_hash, fstr);
+ }
}
+ GLOBAL_SYMBOLS_LEAVE();
}
else {
rb_raise(rb_eTypeError, "wrong argument type %s (expected Symbol)",
@@ -839,15 +982,22 @@ symbols_i(st_data_t key, st_data_t value, st_data_t arg)
VALUE
rb_sym_all_symbols(void)
{
- VALUE ary = rb_ary_new2(global_symbols.str_sym->num_entries);
- st_foreach(global_symbols.str_sym, symbols_i, ary);
+ VALUE ary;
+
+ GLOBAL_SYMBOLS_ENTER(symbols);
+ {
+ ary = rb_ary_new2(symbols->str_sym->num_entries);
+ st_foreach(symbols->str_sym, symbols_i, ary);
+ }
+ GLOBAL_SYMBOLS_LEAVE();
+
return ary;
}
size_t
rb_sym_immortal_count(void)
{
- return (size_t)global_symbols.last_id;
+ return (size_t)ruby_global_symbols.last_id;
}
int
@@ -948,6 +1098,18 @@ rb_check_id(volatile VALUE *namep)
return lookup_str_id(name);
}
+/**
+ * Returns Symbol for the given name if it is interned already, or
+ * nil.
+ *
+ * \param namep the pointer to the name object
+ * \return the Symbol for *namep
+ * \pre the object referred by \p namep must be a Symbol or
+ * a String, or possible to convert with to_str method.
+ * \post the object referred by \p namep is a Symbol or a
+ * String if non-nil value is returned, or is a String
+ * if nil is returned.
+ */
VALUE
rb_check_symbol(volatile VALUE *namep)
{
@@ -960,8 +1122,13 @@ rb_check_symbol(volatile VALUE *namep)
}
else if (DYNAMIC_SYM_P(name)) {
if (!SYMBOL_PINNED_P(name)) {
- name = dsymbol_check(name);
- *namep = name;
+ GLOBAL_SYMBOLS_ENTER(symbols);
+ {
+ name = dsymbol_check(symbols, name);
+ }
+ GLOBAL_SYMBOLS_LEAVE();
+
+ *namep = name;
}
return name;
}
diff --git a/symbol.h b/symbol.h
index 4b5c676d55..e2710ba61b 100644
--- a/symbol.h
+++ b/symbol.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_SYMBOL_H
+#define RUBY_SYMBOL_H 1
/**********************************************************************
symbol.h -
@@ -9,10 +11,8 @@
**********************************************************************/
-#ifndef RUBY_SYMBOL_H
-#define RUBY_SYMBOL_H 1
-
#include "id.h"
+#include "ruby/encoding.h"
#define DYNAMIC_ID_P(id) (!(id&ID_STATIC_SYM)&&id>tLAST_OP_ID)
#define STATIC_ID2SYM(id) (((VALUE)(id)<<RUBY_SPECIAL_SHIFT)|SYMBOL_FLAG)
@@ -30,7 +30,7 @@ struct RSymbol {
ID id;
};
-#define RSYMBOL(obj) (R_CAST(RSymbol)(obj))
+#define RSYMBOL(obj) ((struct RSymbol *)(obj))
#define is_notop_id(id) ((id)>tLAST_OP_ID)
#define is_local_id(id) (id_type(id)==ID_LOCAL)
diff --git a/template/Doxyfile.tmpl b/template/Doxyfile.tmpl
index a16e43bc65..4f6c432871 100644
--- a/template/Doxyfile.tmpl
+++ b/template/Doxyfile.tmpl
@@ -214,12 +214,51 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
-MACRO_EXPANSION = NO
-EXPAND_ONLY_PREDEF = NO
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH = <%=srcdir%> <%=srcdir%>/include
INCLUDE_FILE_PATTERNS =
-PREDEFINED =
+PREDEFINED = \
+ ALWAYS_INLINE(_)=_ \
+ COLDFUNC= \
+ CONSTFUNC(_)=_ \
+ DEPRECATED(_)=_ \
+ DEPRECATED_BY(__,_)=_ \
+ ERRORFUNC(__,_)=_ \
+ MJIT_FUNC_EXPORTED= \
+ MJIT_STATIC=extern \
+ MJIT_SYMBOL_EXPORT_BEGIN= \
+ MJIT_SYMBOL_EXPORT_END= \
+ NOINLINE(_)=_ \
+ NORETURN(_)=_ \
+ PRINTF_ARGS(_,__,___)=_ \
+ PUREFUNC(_)=_ \
+ RUBY_EXTERN=extern \
+ RUBY_FUNC_EXPORTED= \
+ RUBY_FUNC_NONNULL(__,_)=_ \
+ RUBY_SYMBOL_EXPORT_BEGIN= \
+ RUBY_SYMBOL_EXPORT_END= \
+ WARNINGFUNC(__,_)=_ \
+ _MSC_VER=1924 \
+ __DOXYGEN__ \
+ __GNUC_MINOR__=0 \
+ __GNUC_PATCHLEVEL__=0 \
+ __GNUC__=10 \
+ __STDC_VERSION__=201710L \
+ __clang__=10 \
+ __clang_major__=10 \
+ __clang_minor__=0 \
+ __clang_patchlevel__=0 \
+ __cplusplus=201704L \
+ __has_attribute(_)=1 \
+ __has_builtin(_)=1 \
+ __has_c_attribute(_)=1 \
+ __has_cpp_attribute(_)=1 \
+ __has_declspec_attribute(_)=1 \
+ __has_extension(_)=1 \
+ __has_feature(_)=1 \
+ __has_warning(_)=1
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
diff --git a/template/GNUmakefile.in b/template/GNUmakefile.in
index d0444d37e2..444e44b3d3 100644
--- a/template/GNUmakefile.in
+++ b/template/GNUmakefile.in
@@ -1,3 +1,5 @@
+gnumake = yes
+
include Makefile
ifeq ($(HAVE_BASERUBY),yes)
diff --git a/template/Makefile.in b/template/Makefile.in
index 3845f02dc7..f5a31499b3 100644
--- a/template/Makefile.in
+++ b/template/Makefile.in
@@ -16,6 +16,8 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
srcdir = @srcdir@
top_srcdir = $(srcdir)
hdrdir = $(srcdir)/include
+tooldir = $(srcdir)/tool
+
PLATFORM_DIR = @PLATFORM_DIR@
CC_WRAPPER = @XCC_WRAPPER@
@@ -82,8 +84,7 @@ optflags = @optflags@
debugflags = @debugflags@
warnflags = @warnflags@ @strict_warnflags@
cppflags = @cppflags@
-MATHN = @MATHN@
-XCFLAGS = @XCFLAGS@ $(MATHN:yes=-DCANONICALIZATION_FOR_MATHN) $(INCFLAGS)
+XCFLAGS = @XCFLAGS@ $(INCFLAGS)
USE_RUBYGEMS = @USE_RUBYGEMS@
USE_RUBYGEMS_ = $(USE_RUBYGEMS:yes=)
CPPFLAGS = @CPPFLAGS@ $(USE_RUBYGEMS_:no=-DDISABLE_RUBYGEMS=1)
@@ -97,11 +98,12 @@ MJIT_CFLAGS = @MJIT_CFLAGS@
MJIT_OPTFLAGS = @MJIT_OPTFLAGS@
MJIT_DEBUGFLAGS = @MJIT_DEBUGFLAGS@
MJIT_LDSHARED = @MJIT_LDSHARED@
-MJIT_DLDFLAGS = @DLDFLAGS@
+MJIT_DLDFLAGS = $(XDLDFLAGS)
MJIT_HEADER = rb_mjit_header.h
MJIT_MIN_HEADER_NAME = rb_mjit_min_header-$(RUBY_PROGRAM_VERSION).h
MJIT_MIN_HEADER = $(MJIT_HEADER_BUILD_DIR)/$(MJIT_MIN_HEADER_NAME)
MJIT_HEADER_BUILD_DIR = $(EXTOUT)/include/$(arch)
+MJIT_TABS=@MJIT_TABS@
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
EXTLDFLAGS = @EXTLDFLAGS@
XLDFLAGS = @XLDFLAGS@ $(EXTLDFLAGS)
@@ -111,6 +113,7 @@ MISSING = @LIBOBJS@ @ALLOCA@
ENABLE_SHARED = @ENABLE_SHARED@
LDSHARED = @LIBRUBY_LDSHARED@
DLDSHARED = @DLDSHARED@
+XDLDFLAGS = @DLDFLAGS@
DLDFLAGS = @LIBRUBY_DLDFLAGS@ $(XLDFLAGS) $(ARCH_FLAG)
SOLIBS = @SOLIBS@
ENABLE_DEBUG_ENV = @ENABLE_DEBUG_ENV@
@@ -205,13 +208,14 @@ RM = rm -f
RMDIR = @RMDIR@
RMDIRS = @RMDIRS@
RMALL = @RMALL@
+LN_S = @LN_S@
NM = @NM@
AR = @AR@
ARFLAGS = @ARFLAGS@$(empty)
RANLIB = @RANLIB@
AS = @AS@
ASFLAGS = @ASFLAGS@ $(INCFLAGS)
-IFCHANGE = $(srcdir)/tool/ifchange
+IFCHANGE = $(tooldir)/ifchange
OBJDUMP = @OBJDUMP@
OBJCOPY = @OBJCOPY@
HAVE_GIT = @HAVE_GIT@
@@ -390,7 +394,7 @@ lex.c: defs/keywords
else \
[ $(Q) ] && echo generating $@ || set -x; \
gperf -C -P -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$$ $? \
- | sed -f $(srcdir)/tool/gperf.sed \
+ | sed -f $(tooldir)/gperf.sed \
> $@.tmp && \
$(MV) $@.tmp $@ && \
$(CP) $? $(srcdir)/defs/lex.c.src && \
@@ -408,7 +412,7 @@ $(srcdir)/enc/jis/props.h: enc/jis/props.kwd
else \
set -x; \
gperf $(JIS_PROPS_OPTIONS) $? | \
- sed -f $(srcdir)/tool/gperf.sed > $@ && \
+ sed -f $(tooldir)/gperf.sed > $@ && \
$(CP) $? $(?:.kwd=.src) && \
$(CP) $@ $(?:.kwd=.h.blt); \
fi
@@ -474,9 +478,9 @@ clean-local::
$(Q)$(RM) \
ext/extinit.c ext/extinit.$(OBJEXT) ext/ripper/y.output \
enc/encinit.c enc/encinit.$(OBJEXT) $(pkgconfig_DATA) \
- ruby-runner.$(OBJEXT) ruby-runner.h *.dSYM \
+ ruby-runner.$(OBJEXT) ruby-runner.h \
|| $(NULLCMD)
- -$(Q)$(RMALL) exe/
+ -$(Q)$(RMALL) exe/ *.dSYM
distclean-local::
$(Q)$(RM) \
@@ -544,28 +548,28 @@ update-download:: update-config_files
after-update:: prereq
gcov:
- $(Q) $(BASERUBY) $(srcdir)/tool/run-gcov.rb
+ $(Q) $(BASERUBY) $(tooldir)/run-gcov.rb
lcov:
- $(Q) $(BASERUBY) $(srcdir)/tool/run-lcov.rb
+ $(Q) $(BASERUBY) $(tooldir)/run-lcov.rb
update-benchmark-driver:
- $(Q) $(srcdir)/tool/git-refresh -C $(srcdir)/benchmark $(Q1:0=-q) \
+ $(Q) $(tooldir)/git-refresh -C $(srcdir)/benchmark $(Q1:0=-q) \
--branch $(BENCHMARK_DRIVER_GIT_REF) \
$(BENCHMARK_DRIVER_GIT_URL) benchmark-driver $(GIT_OPTS)
update-doclie:
- $(Q) $(srcdir)/tool/git-refresh -C $(srcdir)/coverage $(Q1:0=-q) \
+ $(Q) $(tooldir)/git-refresh -C $(srcdir)/coverage $(Q1:0=-q) \
--branch $(DOCLIE_GIT_REF) \
$(DOCLIE_GIT_URL) doclie $(GIT_OPTS)
update-simplecov-html:
- $(Q) $(srcdir)/tool/git-refresh -C $(srcdir)/coverage $(Q1:0=-q) \
+ $(Q) $(tooldir)/git-refresh -C $(srcdir)/coverage $(Q1:0=-q) \
--branch $(SIMPLECOV_HTML_GIT_REF) \
$(SIMPLECOV_HTML_GIT_URL) simplecov-html $(GIT_OPTS)
update-simplecov:
- $(Q) $(srcdir)/tool/git-refresh -C $(srcdir)/coverage $(Q1:0=-q) \
+ $(Q) $(tooldir)/git-refresh -C $(srcdir)/coverage $(Q1:0=-q) \
--branch $(SIMPLECOV_GIT_REF) \
$(SIMPLECOV_GIT_URL) simplecov $(GIT_OPTS)
@@ -580,54 +584,54 @@ INSNS = opt_sc.inc optinsn.inc optunifs.inc insns.inc insns_info.inc \
$(INSNS): $(srcdir)/insns.def vm_opts.h \
$(srcdir)/defs/opt_operand.def $(srcdir)/defs/opt_insn_unif.def \
- $(srcdir)/tool/insns2vm.rb \
- $(srcdir)/tool/ruby_vm/controllers/application_controller.rb \
- $(srcdir)/tool/ruby_vm/helpers/c_escape.rb \
- $(srcdir)/tool/ruby_vm/helpers/dumper.rb \
- $(srcdir)/tool/ruby_vm/helpers/scanner.rb \
- $(srcdir)/tool/ruby_vm/loaders/insns_def.rb \
- $(srcdir)/tool/ruby_vm/loaders/opt_insn_unif_def.rb \
- $(srcdir)/tool/ruby_vm/loaders/opt_operand_def.rb \
- $(srcdir)/tool/ruby_vm/loaders/vm_opts_h.rb \
- $(srcdir)/tool/ruby_vm/models/attribute.rb \
- $(srcdir)/tool/ruby_vm/models/bare_instructions.rb \
- $(srcdir)/tool/ruby_vm/models/c_expr.rb \
- $(srcdir)/tool/ruby_vm/models/instructions.rb \
- $(srcdir)/tool/ruby_vm/models/instructions_unifications.rb \
- $(srcdir)/tool/ruby_vm/models/operands_unifications.rb \
- $(srcdir)/tool/ruby_vm/models/trace_instructions.rb \
- $(srcdir)/tool/ruby_vm/models/typemap.rb \
- $(srcdir)/tool/ruby_vm/scripts/converter.rb \
- $(srcdir)/tool/ruby_vm/scripts/insns2vm.rb \
- $(srcdir)/tool/ruby_vm/views/_attributes.erb \
- $(srcdir)/tool/ruby_vm/views/_c_expr.erb \
- $(srcdir)/tool/ruby_vm/views/_comptime_insn_stack_increase.erb \
- $(srcdir)/tool/ruby_vm/views/_copyright.erb \
- $(srcdir)/tool/ruby_vm/views/_insn_entry.erb \
- $(srcdir)/tool/ruby_vm/views/_insn_len_info.erb \
- $(srcdir)/tool/ruby_vm/views/_insn_name_info.erb \
- $(srcdir)/tool/ruby_vm/views/_insn_operand_info.erb \
- $(srcdir)/tool/ruby_vm/views/_insn_sp_pc_dependency.erb \
- $(srcdir)/tool/ruby_vm/views/_insn_type_chars.erb \
- $(srcdir)/tool/ruby_vm/views/_leaf_helpers.erb \
- $(srcdir)/tool/ruby_vm/views/_mjit_compile_insn.erb \
- $(srcdir)/tool/ruby_vm/views/_mjit_compile_insn_body.erb \
- $(srcdir)/tool/ruby_vm/views/_mjit_compile_ivar.erb \
- $(srcdir)/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb \
- $(srcdir)/tool/ruby_vm/views/_mjit_compile_send.erb \
- $(srcdir)/tool/ruby_vm/views/_notice.erb \
- $(srcdir)/tool/ruby_vm/views/_sp_inc_helpers.erb \
- $(srcdir)/tool/ruby_vm/views/_trace_instruction.erb \
- $(srcdir)/tool/ruby_vm/views/insns.inc.erb \
- $(srcdir)/tool/ruby_vm/views/insns_info.inc.erb \
- $(srcdir)/tool/ruby_vm/views/mjit_compile.inc.erb \
- $(srcdir)/tool/ruby_vm/views/opt_sc.inc.erb \
- $(srcdir)/tool/ruby_vm/views/optinsn.inc.erb \
- $(srcdir)/tool/ruby_vm/views/optunifs.inc.erb \
- $(srcdir)/tool/ruby_vm/views/vm.inc.erb \
- $(srcdir)/tool/ruby_vm/views/vmtc.inc.erb
+ $(tooldir)/insns2vm.rb \
+ $(tooldir)/ruby_vm/controllers/application_controller.rb \
+ $(tooldir)/ruby_vm/helpers/c_escape.rb \
+ $(tooldir)/ruby_vm/helpers/dumper.rb \
+ $(tooldir)/ruby_vm/helpers/scanner.rb \
+ $(tooldir)/ruby_vm/loaders/insns_def.rb \
+ $(tooldir)/ruby_vm/loaders/opt_insn_unif_def.rb \
+ $(tooldir)/ruby_vm/loaders/opt_operand_def.rb \
+ $(tooldir)/ruby_vm/loaders/vm_opts_h.rb \
+ $(tooldir)/ruby_vm/models/attribute.rb \
+ $(tooldir)/ruby_vm/models/bare_instructions.rb \
+ $(tooldir)/ruby_vm/models/c_expr.rb \
+ $(tooldir)/ruby_vm/models/instructions.rb \
+ $(tooldir)/ruby_vm/models/instructions_unifications.rb \
+ $(tooldir)/ruby_vm/models/operands_unifications.rb \
+ $(tooldir)/ruby_vm/models/trace_instructions.rb \
+ $(tooldir)/ruby_vm/models/typemap.rb \
+ $(tooldir)/ruby_vm/scripts/converter.rb \
+ $(tooldir)/ruby_vm/scripts/insns2vm.rb \
+ $(tooldir)/ruby_vm/views/_attributes.erb \
+ $(tooldir)/ruby_vm/views/_c_expr.erb \
+ $(tooldir)/ruby_vm/views/_comptime_insn_stack_increase.erb \
+ $(tooldir)/ruby_vm/views/_copyright.erb \
+ $(tooldir)/ruby_vm/views/_insn_entry.erb \
+ $(tooldir)/ruby_vm/views/_insn_len_info.erb \
+ $(tooldir)/ruby_vm/views/_insn_name_info.erb \
+ $(tooldir)/ruby_vm/views/_insn_operand_info.erb \
+ $(tooldir)/ruby_vm/views/_insn_sp_pc_dependency.erb \
+ $(tooldir)/ruby_vm/views/_insn_type_chars.erb \
+ $(tooldir)/ruby_vm/views/_leaf_helpers.erb \
+ $(tooldir)/ruby_vm/views/_mjit_compile_insn.erb \
+ $(tooldir)/ruby_vm/views/_mjit_compile_insn_body.erb \
+ $(tooldir)/ruby_vm/views/_mjit_compile_ivar.erb \
+ $(tooldir)/ruby_vm/views/_mjit_compile_pc_and_sp.erb \
+ $(tooldir)/ruby_vm/views/_mjit_compile_send.erb \
+ $(tooldir)/ruby_vm/views/_notice.erb \
+ $(tooldir)/ruby_vm/views/_sp_inc_helpers.erb \
+ $(tooldir)/ruby_vm/views/_trace_instruction.erb \
+ $(tooldir)/ruby_vm/views/insns.inc.erb \
+ $(tooldir)/ruby_vm/views/insns_info.inc.erb \
+ $(tooldir)/ruby_vm/views/mjit_compile.inc.erb \
+ $(tooldir)/ruby_vm/views/opt_sc.inc.erb \
+ $(tooldir)/ruby_vm/views/optinsn.inc.erb \
+ $(tooldir)/ruby_vm/views/optunifs.inc.erb \
+ $(tooldir)/ruby_vm/views/vm.inc.erb \
+ $(tooldir)/ruby_vm/views/vmtc.inc.erb
$(ECHO) generating $@
- $(Q) $(BASERUBY) -Ku $(srcdir)/tool/insns2vm.rb $(INSNS2VMOPT) $@
+ $(Q) $(BASERUBY) -Ku $(tooldir)/insns2vm.rb $(INSNS2VMOPT) $@
verconf.h: $(RBCONFIG)
@@ -643,7 +647,7 @@ un-runnable:
mjit_config.h:
$(ECHO) making $@
@{ \
- . $(srcdir)/tool/mjit_archflag.sh; \
+ . $(tooldir)/mjit_archflag.sh; \
parse_arch_flags "$(UNIVERSAL_ARCHNAMES)" $(ARCH_FLAG); \
test "$(Q)" = @ || set -x; \
echo '#ifndef RUBY_MJIT_CONFIG_H'; \
@@ -671,7 +675,7 @@ mjit_config.h:
echo '#endif /* RUBY_MJIT_CONFIG_H */'; \
} > $@
-yes-test-almost yes-test-all: mjit_build_dir.$(SOEXT)
+yes-test-almost yes-test-all programs: mjit_build_dir.$(SOEXT)
mjit_build_dir.$(SOEXT): $(MJIT_MIN_HEADER) $(srcdir)/ruby-runner.c ruby-runner.h
$(ECHO) making $@
$(Q) $(DLDSHARED) $(MJIT_DLDFLAGS) $(ARCH_FLAG) $(CFLAGS) $(INCFLAGS) $(CPPFLAGS) \
@@ -679,5 +683,5 @@ mjit_build_dir.$(SOEXT): $(MJIT_MIN_HEADER) $(srcdir)/ruby-runner.c ruby-runner.
$(OUTFLAG)$@ $(srcdir)/ruby-runner.c
# yes-test-basic: leaked-globals
-leaked-globals: $(COMMONOBJS) prog $(srcdir)/tool/leaked-globals PHONY
- $(Q) $(XRUBY) $(srcdir)/tool/leaked-globals NM=$(NM) SYMBOL_PREFIX=$(SYMBOL_PREFIX) $(srcdir)/configure.ac $(COMMONOBJS)
+leaked-globals: $(COMMONOBJS) prog $(tooldir)/leaked-globals PHONY
+ $(Q) $(XRUBY) $(tooldir)/leaked-globals NM=$(NM) SYMBOL_PREFIX=$(SYMBOL_PREFIX) $(srcdir)/configure.ac $(COMMONOBJS)
diff --git a/template/builtin_binary.inc.tmpl b/template/builtin_binary.inc.tmpl
new file mode 100644
index 0000000000..787ced5f3d
--- /dev/null
+++ b/template/builtin_binary.inc.tmpl
@@ -0,0 +1,30 @@
+// -*- c -*-
+// DO NOT MODIFY THIS FILE DIRECTLY.
+// auto-generated file by tool/generic_erb.rb
+// with template/builtin_binary.inc.tmpl
+% unless ARGV.include?('--cross=yes')
+% ary = RubyVM.enum_for(:each_builtin).to_a
+% ary.each{|feature, iseq|
+
+static const unsigned char <%= feature %>_bin[] = {
+% iseq \
+% . to_binary \
+% . each_byte \
+% . map(&:ord) \
+% . map{ '0x%02x' % _1 } \
+% . each_slice(12) {|a|
+ <%= a.join(', ') %>,
+% }
+};
+% }
+
+static const struct builtin_binary builtin_binary[] = {
+% ary.each{|feature, |
+ { <%= feature.dump %>, <%= feature %>_bin, sizeof(<%= feature %>_bin), },
+% }
+ { NULL, },<%# dummy entry %>
+};
+
+#define BUILTIN_BINARY_SIZE <%= ary.size %>
+STATIC_ASSERT(n_builtin, numberof(builtin_binary) == BUILTIN_BINARY_SIZE + 1);
+% end
diff --git a/template/call_iseq_optimized.inc.tmpl b/template/call_iseq_optimized.inc.tmpl
new file mode 100644
index 0000000000..2d3ad40f7e
--- /dev/null
+++ b/template/call_iseq_optimized.inc.tmpl
@@ -0,0 +1,68 @@
+/* -*- c -*- */
+% P = (0..3)
+% L = (0..5)
+%
+% def fname param, local
+% "vm_call_iseq_setup_normal_0start_#{param}params_#{local}locals"
+% end
+#if 1 /* enable or disable this optimization */
+
+/* DO NOT EDIT THIS FILE DIRECTLY
+ *
+ * This file is generated by tool/generic_erb.rb
+ * with template/call_iseq_optimized.inc.tmpl
+ */
+
+% P.each{|param|
+% L.each{|local|
+static VALUE
+<%= fname(param, local) %>(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling)
+{
+ RB_DEBUG_COUNTER_INC(ccf_iseq_fix);
+ return vm_call_iseq_setup_normal(ec, cfp, calling, vm_cc_cme(calling->cc), 0, <%= param %>, <%= local %>);
+}
+
+% }
+% }
+/* vm_call_iseq_handlers[param][local] */
+static const vm_call_handler vm_call_iseq_handlers[][<%= L.to_a.size %>] = {
+% P.each{|param|
+ {
+% L.each{|local|
+ <%= fname(param, local) %>,
+% }
+ },
+% }
+};
+
+static inline vm_call_handler
+vm_call_iseq_setup_func(const struct rb_callinfo *ci, const int param_size, const int local_size)
+{
+ if (UNLIKELY(vm_ci_flag(ci) & VM_CALL_TAILCALL)) {
+ return &vm_call_iseq_setup_tailcall_0start;
+ }
+ else if (0) { /* to disable optimize */
+ return &vm_call_iseq_setup_normal_0start;
+ }
+ else if (param_size <= <%= P.end %> && local_size <= <%= L.end %>) {
+ VM_ASSERT(local_size >= 0);
+ return vm_call_iseq_handlers[param_size][local_size];
+ }
+ else {
+ return &vm_call_iseq_setup_normal_0start;
+ }
+}
+
+#else
+
+static inline vm_call_handler
+vm_call_iseq_setup_func(const struct rb_callinfo *ci, const int param_size, const int local_size)
+{
+ if (UNLIKELY(vm_ci_flag(ci) & VM_CALL_TAILCALL)) {
+ return &vm_call_iseq_setup_tailcall_0start;
+ }
+ else {
+ return &vm_call_iseq_setup_normal_0start;
+ }
+}
+#endif
diff --git a/template/configure-ext.mk.tmpl b/template/configure-ext.mk.tmpl
index 438e109eba..9921e2225b 100644
--- a/template/configure-ext.mk.tmpl
+++ b/template/configure-ext.mk.tmpl
@@ -16,13 +16,13 @@ srcdir ||= File.dirname(File.dirname(__FILE__))
exts = {}
[
["exts", "ext", "--extstatic $(EXTSTATIC)"],
- ["gems", "gems", "--no-extstatic"],
+ ["gems", ".bundle/gems", "--no-extstatic"],
].each do |t, d, o|
exts[t] = [o, Dir.glob("#{srcdir}/#{d}/*/").map {|n| n[(srcdir.size+1)..-2]}]
end
%>
MINIRUBY = <%=miniruby%>
-SCRIPT_ARGS = <%=script_args%>
+SCRIPT_ARGS = <%=script_args.gsub("#", "\\#")%>
EXTMK_ARGS = $(SCRIPT_ARGS) --gnumake=$(gnumake) --extflags="$(EXTLDFLAGS)" \
--make-flags="MINIRUBY='$(MINIRUBY)'"
@@ -32,6 +32,7 @@ gems:
% exts.each do |t, (o, dirs)|
% dirs.each do |d|
+% next if Dir.glob("#{srcdir}/#{d}/**/extconf.rb").empty?
<%=t%>: <%=d%>/exts.mk
<%=d%>/exts.mk: FORCE
$(Q)$(MINIRUBY) $(srcdir)/ext/extmk.rb --make='$(MAKE)' \
diff --git a/template/encdb.h.tmpl b/template/encdb.h.tmpl
index 06afb5dbe1..b3bd54548a 100644
--- a/template/encdb.h.tmpl
+++ b/template/encdb.h.tmpl
@@ -58,7 +58,7 @@ encdirs.each do |encdir|
else
name = $1
end
- check_duplication(defs, $1, fn, $.)
+ check_duplication(defs, $1, fn, f.lineno)
next if BUILTIN_ENCODINGS[name]
encodings << $1
count += 1
@@ -71,18 +71,18 @@ encdirs.each do |encdir|
when /^ENC_REPLICATE\(\s*"([^"]+)"\s*,\s*"([^"]+)"/
raise ArgumentError,
'%s:%d: ENC_REPLICATE: %s is not defined yet. (replica %s)' %
- [fn, $., $2, $1] unless defs[$2.upcase]
+ [fn, f.lineno, $2, $1] unless defs[$2.upcase]
count += 1
when /^ENC_ALIAS\(\s*"([^"]+)"\s*,\s*"([^"]+)"/
raise ArgumentError,
'%s:%d: ENC_ALIAS: %s is not defined yet. (alias %s)' %
- [fn, $., $2, $1] unless defs[$2.upcase]
+ [fn, f.lineno, $2, $1] unless defs[$2.upcase]
when /^ENC_DUMMY\w*\(\s*"([^"]+)"/
count += 1
else
next
end
- check_duplication(defs, $1, fn, $.)
+ check_duplication(defs, $1, fn, f.lineno)
lines << line.sub(/;.*/m, "").chomp + ";" if line
end
end
diff --git a/template/exts.mk.tmpl b/template/exts.mk.tmpl
index ea1219805b..e4706be373 100644
--- a/template/exts.mk.tmpl
+++ b/template/exts.mk.tmpl
@@ -12,18 +12,25 @@ notes = {}
rubies = []
exeext = RbConfig::CONFIG['EXEEXT']
gnumake = false
+confexts = nil
opt = OptionParser.new do |o|
o.on('--gnumake=BOOL') {|v| gnumake = v == 'yes'}
+ o.on('--configure-exts=FILE') {|v| confexts = v}
o.order!(ARGV)
end
+confexts &&= File.read(confexts).scan(/^exts: (.*\.mk)/).flatten rescue nil
+confexts ||= []
+macros["old_extensions"] = []
+
contpat = /(?>(?>[^\\\n]|\\.)*\\\n)*(?>[^\\\n]|\\.)*/
-Dir.glob("{ext,gems}/*/exts.mk") do |e|
+Dir.glob("{ext,.bundle/gems}/*/exts.mk") do |e|
gem = /\Agems(?=\/)/ =~ e
s = File.read(e)
s.scan(/^(extensions|SUBMAKEOPTS|EXT[A-Z]+|MFLAGS|NOTE_[A-Z]+)[ \t]*=[ \t]*(#{contpat})$/o) do |n, v|
v.gsub!(/\\\n[ \t]*/, ' ')
next if v.empty?
next if gem and n != "extensions"
+ n = "old_extensions" if n == "extensions" and !confexts.include?(e)
v = v.split
m = macros[n] ||= []
case n
@@ -32,6 +39,7 @@ Dir.glob("{ext,gems}/*/exts.mk") do |e|
else
macros[n] = m | v
end
+ break if n == "old_extensions"
end
if gem
r = ""
@@ -128,7 +136,8 @@ libencs:
ext/extinit.<%=objext%>:
$(Q)$(MAKE)<%=mflags%> V=$(V) EXTINITS="$(EXTINITS)" $@
-% exts = macros["extensions"].map {|e|e.chomp("/.")}.sort
+% exts = (macros["extensions"] + macros["old_extensions"])
+% exts.map! {|e|e.chomp("/.")}.sort
% targets.each do |tgt|
% exts.each do |d|
% t = "#{d}/#{tgt}"
@@ -145,6 +154,7 @@ ext/extinit.<%=objext%>:
% end
$(Q)<%= submake %><%=mflags%> V=$(V) $(@F)
% if /^(dist|real)clean$/ =~ tgt
+ $(Q)$(RM) $(@D)/exts.mk
$(Q)$(RMDIRS) $(@D)
% end
% end
@@ -157,3 +167,5 @@ extso:
<%= k %>:<%= d.join(' ') %>
<%= n.join("") %>
% end
+
+remove-old-extensions: $(old_extensions:/.=/distclean)
diff --git a/template/id.c.tmpl b/template/id.c.tmpl
index 477a76bc26..4f30875c04 100644
--- a/template/id.c.tmpl
+++ b/template/id.c.tmpl
@@ -33,8 +33,6 @@ static const struct {
static void
Init_id(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
rb_encoding *enc = rb_usascii_encoding();
% ids[:predefined].each do |token, name|
diff --git a/template/prelude.c.tmpl b/template/prelude.c.tmpl
index b582e2ddd6..eec8a32da9 100644
--- a/template/prelude.c.tmpl
+++ b/template/prelude.c.tmpl
@@ -5,24 +5,12 @@
# Since $(BASERUBY) may be older than Ruby 1.9,
# Ruby 1.9 feature should not be used.
+require_relative '../tool/ruby_vm/helpers/c_escape'
+
class Prelude
+ include RubyVM::CEscape
LINE_LIMIT = 509 # by C89
- C_ESC = {
- "/*" => "/\\*",
- "*/" => "*\\/",
- "\\" => "\\\\",
- '"' => '\"',
- "\n" => '\n',
- }
-
- 0x00.upto(0x1f) {|ch| C_ESC[[ch].pack("C")] ||= "\\%03o" % ch }
- 0x7f.upto(0xff) {|ch| C_ESC[[ch].pack("C")] = "\\%03o" % ch }
- C_ESC_PAT = Regexp.union(*C_ESC.keys)
-
- def c_esc(str)
- str.gsub(C_ESC_PAT) { C_ESC[$&] }
- end
def prelude_base(filename)
filename.chomp(".rb")
end
@@ -87,16 +75,21 @@ Prelude.new(output, ARGV, vpath).instance_eval do
sources: <%= @preludes.map {|n,*| prelude_base(n)}.join(', ') %><%=%>
*/
%unless @preludes.empty?
-#include "ruby/ruby.h"
#include "internal.h"
-#include "vm_core.h"
+#include "internal/warnings.h"
#include "iseq.h"
+#include "ruby/ruby.h"
+#include "vm_core.h"
+COMPILER_WARNING_PUSH
+#if __has_warning("-Wstring-concatenation")
+COMPILER_WARNING_IGNORED(-Wstring-concatenation)
+#endif
% preludes = @preludes.values.sort
% preludes.each {|i, prelude, lines, sub|
% name = prelude_name(*prelude)
-static const char prelude_name<%=i%><%=%>[] = "<%=c_esc(name)%>";
+static const char prelude_name<%=i%><%=%>[] = <%=rstring2cstr(name)%>;
static const struct {
% size = beg = 0
% lines.each_with_index {|(line, comment), n|
@@ -113,20 +106,22 @@ static const struct {
% end
} prelude_code<%=i%><%=%> = {
% size = 0
-#line 1 "<%=c_esc(prelude)%>"
+#line 1 <%=rstring2cstr(prelude)%>
% lines.each_with_index {|(line, comment), n|
% if size + line.size >= Prelude::LINE_LIMIT
% size = 0
,
-#line <%=n+1%> "<%=c_esc(prelude)%>"
+#line <%=n+1%> <%=rstring2cstr(prelude)%>
% end
% size += line.size
-"<%=c_esc(line)%>"<%if comment%>/* <%=c_esc(comment)%> */<%end%>
+<%=rstring2cstr(line)%><%if comment%><%=commentify(comment)%><%end%>
% }
#line <%=_erbout.count("\n")+2%> "<%=@output%>"
};
% }
+COMPILER_WARNING_POP
+
% if @have_sublib
#define PRELUDE_COUNT <%=preludes.size%>
@@ -207,7 +202,7 @@ prelude_eval(VALUE code, VALUE name, int line)
rb_ast_t *ast = prelude_ast(name, code, line);
rb_iseq_eval(rb_iseq_new_with_opt(&ast->body, name, name, Qnil, INT2FIX(line),
- NULL, ISEQ_TYPE_TOP, &optimization));
+ NULL, 0, ISEQ_TYPE_TOP, &optimization));
rb_ast_dispose(ast);
}
COMPILER_WARNING_POP
diff --git a/template/ruby-gdb.in b/template/ruby-gdb.in
new file mode 100755
index 0000000000..7ab4e976c6
--- /dev/null
+++ b/template/ruby-gdb.in
@@ -0,0 +1,6 @@
+#!/bin/sh
+prefix="/${0%/*}"
+prefix="${prefix%/*}"
+ruby="${bindir}/${RUBY_INSTALL_NAME}"
+gdbinit="${rubylibdir}/gdbinit"
+exec gdb --command="$gdbinit" --args "$ruby" "$@"
diff --git a/template/ruby-lldb.in b/template/ruby-lldb.in
new file mode 100755
index 0000000000..c33603b94d
--- /dev/null
+++ b/template/ruby-lldb.in
@@ -0,0 +1,6 @@
+#!/bin/sh
+prefix="/${0%/*}"
+prefix="${prefix%/*}"
+ruby="${bindir}/${RUBY_INSTALL_NAME}"
+lldbinit="${rubylibdir}/lldb_cruby.py"
+exec lldb -O "command script import $lldbinit" "$ruby" -- "$@"
diff --git a/template/transdb.h.tmpl b/template/transdb.h.tmpl
index 16565dd638..990a8639d0 100644
--- a/template/transdb.h.tmpl
+++ b/template/transdb.h.tmpl
@@ -44,9 +44,9 @@ transdirs.each do |transdir|
from_to = "%s to %s" % [$1, $2]
if converters[from_to]
raise ArgumentError, '%s:%d: transcode "%s" is already registered at %s:%d' %
- [path, $., from_to, *converters[from_to].values_at(3, 4)]
+ [path, f.lineno, from_to, *converters[from_to].values_at(3, 4)]
else
- converters[from_to] = [$1, $2, fn[0..-3], path, $.]
+ converters[from_to] = [$1, $2, fn[0..-3], path, f.lineno]
converter_list << from_to
end
end
diff --git a/test/-ext-/array/test_to_ary_concat.rb b/test/-ext-/array/test_to_ary_concat.rb
new file mode 100644
index 0000000000..feb1bc1109
--- /dev/null
+++ b/test/-ext-/array/test_to_ary_concat.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: false
+require 'test/unit'
+require '-test-/array/to_ary_concat'
+
+class TestConcatStress < Test::Unit::TestCase
+ def setup
+ @stress_level = GC.stress
+ GC.stress = true
+ end
+
+ def teardown
+ GC.stress = @stress_level
+ end
+
+ def test_concat
+ arr = [nil]
+ bar = Bug::Bar.new
+ arr.concat(bar)
+ end
+end
diff --git a/test/-ext-/bug_reporter/test_bug_reporter.rb b/test/-ext-/bug_reporter/test_bug_reporter.rb
index 576628d63e..6b8e1754a7 100644
--- a/test/-ext-/bug_reporter/test_bug_reporter.rb
+++ b/test/-ext-/bug_reporter/test_bug_reporter.rb
@@ -4,8 +4,10 @@ require 'tmpdir'
class TestBugReporter < Test::Unit::TestCase
def test_bug_reporter_add
+ skip if ENV['RUBY_ON_BUG']
+
description = RUBY_DESCRIPTION
- description = description.sub(/\+JIT /, '') if RubyVM::MJIT.enabled?
+ description = description.sub(/\+JIT /, '') if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
expected_stderr = [
:*,
/\[BUG\]\sSegmentation\sfault.*\n/,
diff --git a/test/-ext-/debug/test_profile_frames.rb b/test/-ext-/debug/test_profile_frames.rb
index 0335267ee9..e0152247e7 100644
--- a/test/-ext-/debug/test_profile_frames.rb
+++ b/test/-ext-/debug/test_profile_frames.rb
@@ -44,6 +44,7 @@ class TestProfileFrames < Test::Unit::TestCase
}.resume
labels = [
+ nil,
"test_profile_frames",
"zab",
"baz",
@@ -54,6 +55,7 @@ class TestProfileFrames < Test::Unit::TestCase
"test_profile_frames",
]
base_labels = [
+ nil,
"test_profile_frames",
"zab",
"baz",
@@ -64,6 +66,7 @@ class TestProfileFrames < Test::Unit::TestCase
"test_profile_frames",
]
full_labels = [
+ "Bug::Debug.profile_frames",
"TestProfileFrames#test_profile_frames",
"#{obj.inspect}.zab",
"SampleClassForTestProfileFrames::Sample2#baz",
@@ -74,6 +77,7 @@ class TestProfileFrames < Test::Unit::TestCase
"TestProfileFrames#test_profile_frames",
]
classes = [
+ Bug::Debug,
TestProfileFrames,
obj,
SampleClassForTestProfileFrames::Sample2,
@@ -84,9 +88,10 @@ class TestProfileFrames < Test::Unit::TestCase
TestProfileFrames,
]
singleton_method_p = [
- false, true, false, true, true, true, false, false, false,
+ true, false, true, false, true, true, true, false, false, false,
]
method_names = [
+ "profile_frames",
"test_profile_frames",
"zab",
"baz",
@@ -97,6 +102,7 @@ class TestProfileFrames < Test::Unit::TestCase
"test_profile_frames",
]
qualified_method_names = [
+ "Bug::Debug.profile_frames",
"TestProfileFrames#test_profile_frames",
"#{obj.inspect}.zab",
"SampleClassForTestProfileFrames::Sample2#baz",
@@ -106,8 +112,8 @@ class TestProfileFrames < Test::Unit::TestCase
"SampleClassForTestProfileFrames#foo",
"TestProfileFrames#test_profile_frames",
]
- paths = [ file=__FILE__, "(eval)", file, file, file, file, file, file ]
- absolute_paths = [ file, nil, file, file, file, file, file, file ]
+ paths = [ nil, file=__FILE__, "(eval)", file, file, file, file, file, file, nil ]
+ absolute_paths = [ "<cfunc>", file, nil, file, file, file, file, file, file, nil ]
assert_equal(labels.size, frames.size)
@@ -120,8 +126,8 @@ class TestProfileFrames < Test::Unit::TestCase
assert_equal(base_labels[i], base_label, err_msg)
assert_equal(singleton_method_p[i], singleton_p, err_msg)
assert_equal(method_names[i], method_name, err_msg)
- assert_match(qualified_method_names[i], qualified_method_name, err_msg)
- assert_match(full_labels[i], full_label, err_msg)
+ assert_equal(qualified_method_names[i], qualified_method_name, err_msg)
+ assert_equal(full_labels[i], full_label, err_msg)
assert_match(classes[i].inspect, classpath, err_msg)
if label == method_name
c = classes[i]
diff --git a/test/-ext-/funcall/test_passing_block.rb b/test/-ext-/funcall/test_passing_block.rb
index d1164871b0..71c9d905be 100644
--- a/test/-ext-/funcall/test_passing_block.rb
+++ b/test/-ext-/funcall/test_passing_block.rb
@@ -24,14 +24,10 @@ class TestFuncall < Test::Unit::TestCase
def test_with_funcall_passing_block_kw
block = ->(*a, **kw) { [a, kw] }
assert_equal([[1], {}], Relay.with_funcall_passing_block_kw(0, 1, &block))
+ assert_equal([[{a: 1}], {}], Relay.with_funcall_passing_block_kw(0, a: 1, &block))
assert_equal([[], {a: 1}], Relay.with_funcall_passing_block_kw(1, a: 1, &block))
assert_equal([[1], {a: 1}], Relay.with_funcall_passing_block_kw(1, 1, a: 1, &block))
- assert_equal([[{}], {}], Relay.with_funcall_passing_block_kw(2, {}, **{}, &block))
assert_equal([[], {a: 1}], Relay.with_funcall_passing_block_kw(3, a: 1, &block))
- assert_equal([[{a: 1}], {}], Relay.with_funcall_passing_block_kw(3, {a: 1}, **{}, &block))
- assert_warn(/warning: Passing the keyword argument as the last hash parameter is deprecated.*The called method is defined here/m) do
- assert_equal({}, Relay.with_funcall_passing_block_kw(3, **{}, &->(a){a}))
- end
end
def test_with_funcallv_public_kw
@@ -47,29 +43,18 @@ class TestFuncall < Test::Unit::TestCase
arg
end
assert_equal([[1], {}], Relay.with_funcallv_public_kw(o, :foo, 0, 1))
+ assert_equal([[{a: 1}], {}], Relay.with_funcallv_public_kw(o, :foo, 0, a: 1))
assert_equal([[], {a: 1}], Relay.with_funcallv_public_kw(o, :foo, 1, a: 1))
assert_equal([[1], {a: 1}], Relay.with_funcallv_public_kw(o, :foo, 1, 1, a: 1))
- assert_equal([[{}], {}], Relay.with_funcallv_public_kw(o, :foo, 2, {}, **{}))
assert_equal([[], {a: 1}], Relay.with_funcallv_public_kw(o, :foo, 3, a: 1))
- assert_equal([[{a: 1}], {}], Relay.with_funcallv_public_kw(o, :foo, 3, {a: 1}, **{}))
- assert_raise(NoMethodError) { Relay.with_funcallv_public_kw(o, :bar, 3, {a: 1}, **{}) }
- assert_warn(/warning: Passing the keyword argument as the last hash parameter is deprecated.*The called method `baz'/m) do
- assert_equal({}, Relay.with_funcallv_public_kw(o, :baz, 3, **{}))
- end
end
def test_with_yield_splat_kw
block = ->(*a, **kw) { [a, kw] }
assert_equal([[1], {}], Relay.with_yield_splat_kw(0, [1], &block))
+ assert_equal([[{a: 1}], {}], Relay.with_yield_splat_kw(0, [{a: 1}], &block))
assert_equal([[], {a: 1}], Relay.with_yield_splat_kw(1, [{a: 1}], &block))
assert_equal([[1], {a: 1}], Relay.with_yield_splat_kw(1, [1, {a: 1}], &block))
- assert_equal([[{}], {}], Relay.with_yield_splat_kw(2, [{}], **{}, &block))
- assert_warn(/warning: Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([[], {a: 1}], Relay.with_yield_splat_kw(3, [{a: 1}], &block))
- end
- assert_equal([[{a: 1}], {}], Relay.with_yield_splat_kw(3, [{a: 1}], **{}, &block))
- assert_warn(/warning: Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal({}, Relay.with_yield_splat_kw(3, [], **{}, &->(a){a}))
- end
+ assert_equal([[], {a: 1}], Relay.with_yield_splat_kw(3, [{a: 1}], &block))
end
end
diff --git a/test/-ext-/postponed_job/test_postponed_job.rb b/test/-ext-/postponed_job/test_postponed_job.rb
index 7dc28776d0..fee0172d11 100644
--- a/test/-ext-/postponed_job/test_postponed_job.rb
+++ b/test/-ext-/postponed_job/test_postponed_job.rb
@@ -25,4 +25,11 @@ class TestPostponed_job < Test::Unit::TestCase
Bug.postponed_job_register_one(ary = [])
assert_equal [1], ary
end
+
+ if Bug.respond_to?(:postponed_job_register_in_c_thread)
+ def test_register_in_c_thread
+ assert Bug.postponed_job_register_in_c_thread(ary = [])
+ assert_equal [1], ary
+ end
+ end
end
diff --git a/test/-ext-/rational/test_rat.rb b/test/-ext-/rational/test_rat.rb
index 626ffb9661..7683483e66 100644
--- a/test/-ext-/rational/test_rat.rb
+++ b/test/-ext-/rational/test_rat.rb
@@ -29,4 +29,42 @@ class TestRational < Test::Unit::TestCase
rescue NotImplementedError
end
end
+
+ def test_rb_rational_raw
+ rat = Rational.raw(1, 2)
+ assert_equal(1, rat.numerator)
+ assert_equal(2, rat.denominator)
+
+ rat = Rational.raw(-1, 2)
+ assert_equal(-1, rat.numerator)
+ assert_equal(2, rat.denominator)
+
+ rat = Rational.raw(1, -2)
+ assert_equal(-1, rat.numerator)
+ assert_equal(2, rat.denominator)
+
+ assert_equal(1/2r, Rational.raw(1.0, 2.0))
+
+ assert_raise(TypeError) { Rational.raw("1", 2) }
+ assert_raise(TypeError) { Rational.raw(1, "2") }
+
+ class << (o = Object.new)
+ def to_i; 42; end
+ end
+
+ assert_raise(TypeError) { Rational.raw(o, 2) }
+ assert_raise(TypeError) { Rational.raw(1, o) }
+
+ class << (o = Object.new)
+ def to_int; 42; end
+ end
+
+ rat = Rational.raw(o, 2)
+ assert_equal(42, rat.numerator)
+ assert_equal(2, rat.denominator)
+
+ rat = Rational.raw(2, o)
+ assert_equal(2, rat.numerator)
+ assert_equal(42, rat.denominator)
+ end
end
diff --git a/test/-ext-/string/test_cstr.rb b/test/-ext-/string/test_cstr.rb
index 2083016db2..d909781700 100644
--- a/test/-ext-/string/test_cstr.rb
+++ b/test/-ext-/string/test_cstr.rb
@@ -13,13 +13,13 @@ class Test_StringCStr < Test::Unit::TestCase
end
def test_long
- s = Bug::String.new("abcdef")*100000
+ s = Bug::String.new(Bug::String.new("abcdef")*100000)
s.cstr_unterm('x')
assert_equal(0, s.cstr_term, Bug4319)
end
def test_shared
- s = Bug::String.new("abcdef")*5
+ s = Bug::String.new(Bug::String.new("abcdef")*5)
s = s.unterminated_substring(0, 29)
assert_equal(0, s.cstr_term, Bug4319)
end
@@ -28,7 +28,7 @@ class Test_StringCStr < Test::Unit::TestCase
s0 = Bug::String.new("abcdefgh"*8)
[4, 4*3-1, 8*3-1, 64].each do |n|
- s = s0[0, n]
+ s = Bug::String.new(s0[0, n])
s.cstr_unterm('x')
s.freeze
assert_equal(0, s.cstr_term)
@@ -67,7 +67,7 @@ class Test_StringCStr < Test::Unit::TestCase
n = 100
len = str.size * n
WCHARS.each do |enc|
- s = Bug::String.new(str.encode(enc))*n
+ s = Bug::String.new(Bug::String.new(str.encode(enc))*n)
s.cstr_unterm('x')
assert_nothing_raised(ArgumentError, enc.name) {s.cstr_term}
s.set_len(s.bytesize / 2)
diff --git a/test/-ext-/string/test_ellipsize.rb b/test/-ext-/string/test_ellipsize.rb
index d7947041d5..d340abd58a 100644
--- a/test/-ext-/string/test_ellipsize.rb
+++ b/test/-ext-/string/test_ellipsize.rb
@@ -10,7 +10,7 @@ class Test_StringEllipsize < Test::Unit::TestCase
def assert_equal_with_class(expected, result, *rest)
assert_equal(expected.encoding, result.encoding, *rest)
assert_equal(expected, result, result.encoding.name)
- assert_instance_of(Bug::String, result, *rest)
+ assert_instance_of(String, result, *rest)
end
def test_longer
diff --git a/test/-ext-/string/test_enc_str_buf_cat.rb b/test/-ext-/string/test_enc_str_buf_cat.rb
index 72f903903c..b9a63ec2de 100644
--- a/test/-ext-/string/test_enc_str_buf_cat.rb
+++ b/test/-ext-/string/test_enc_str_buf_cat.rb
@@ -13,4 +13,13 @@ class Test_StringEncStrBufCat < Test::Unit::TestCase
assert_equal(:unknown, Bug::String.new(cr_unknown_str).coderange, "an assertion for following tests")
assert_equal(:valid, Bug::String.new(a8_str).enc_str_buf_cat(cr_unknown_str).coderange, Bug6509)
end
+
+ def test_str_conv_enc
+ str = Bug::String.new("aaa".encode("US-ASCII"))
+ assert_same(str, str.str_conv_enc_opts("UTF-8", "US-ASCII", 0, nil))
+
+ str = Bug::String.new("aaa".encode("UTF-16LE").force_encoding("UTF-8"))
+ assert_predicate(str, :ascii_only?) # cache coderange
+ assert_equal("aaa", str.str_conv_enc_opts("UTF-16LE", "UTF-8", 0, nil))
+ end
end
diff --git a/test/-ext-/string/test_fstring.rb b/test/-ext-/string/test_fstring.rb
index 76afa30e14..9b4956ecef 100644
--- a/test/-ext-/string/test_fstring.rb
+++ b/test/-ext-/string/test_fstring.rb
@@ -12,6 +12,22 @@ class Test_String_Fstring < Test::Unit::TestCase
yield fstr
end
+ def test_rb_enc_interned_str_autoloaded_encoding
+ assert_separately([], <<~RUBY)
+ require '-test-/string'
+ assert_include(Encoding::Windows_31J.inspect, 'autoload')
+ Bug::String.rb_enc_interned_str(Encoding::Windows_31J)
+ RUBY
+ end
+
+ def test_rb_enc_str_new_autoloaded_encoding
+ assert_separately([], <<~RUBY)
+ require '-test-/string'
+ assert_include(Encoding::Windows_31J.inspect, 'autoload')
+ Bug::String.rb_enc_str_new(Encoding::Windows_31J)
+ RUBY
+ end
+
def test_instance_variable
str = __method__.to_s * 3
str.instance_variable_set(:@test, 42)
diff --git a/test/-ext-/string/test_interned_str.rb b/test/-ext-/string/test_interned_str.rb
new file mode 100644
index 0000000000..340dba41e8
--- /dev/null
+++ b/test/-ext-/string/test_interned_str.rb
@@ -0,0 +1,12 @@
+require 'test/unit'
+require '-test-/string'
+
+class Test_RbInternedStr < Test::Unit::TestCase
+ def test_interned_str
+ src = "a" * 20
+ interned_str = Bug::String.rb_interned_str_dup(src)
+ src.clear
+ src << "b" * 20
+ assert_equal "a" * 20, interned_str
+ end
+end
diff --git a/test/-ext-/string/test_normalize.rb b/test/-ext-/string/test_normalize.rb
index 8c11bfe3d4..80b21dff38 100644
--- a/test/-ext-/string/test_normalize.rb
+++ b/test/-ext-/string/test_normalize.rb
@@ -63,7 +63,7 @@ class Test_StringNormalize < Test::Unit::TestCase
end
def test_not_normalize_kc
- %[
+ %W[
\u2460
\u2162
\u3349
@@ -74,7 +74,7 @@ class Test_StringNormalize < Test::Unit::TestCase
\u2121
\u32A4
\u3231
- ].split.each do |src|
+ ].each do |src|
result = Bug::String.new(src).normalize_ospath
assert_equal src, result,
"#{src.dump} is expected not to be normalized, but #{result.dump}"
@@ -82,7 +82,7 @@ class Test_StringNormalize < Test::Unit::TestCase
end
def test_dont_normalize_hfsplus
- %[
+ %W[
\u2190\u0338
\u219A
\u212B
@@ -95,7 +95,7 @@ class Test_StringNormalize < Test::Unit::TestCase
\uFA10
\uFA19
\uFA26
- ].split.each do |src|
+ ].each do |src|
result = Bug::String.new(src).normalize_ospath
assert_equal src, result,
"#{src.dump} is expected not to be normalized, but #{result.dump}"
diff --git a/test/-ext-/symbol/test_inadvertent_creation.rb b/test/-ext-/symbol/test_inadvertent_creation.rb
index 40b3f59f7f..995e01ee15 100644
--- a/test/-ext-/symbol/test_inadvertent_creation.rb
+++ b/test/-ext-/symbol/test_inadvertent_creation.rb
@@ -255,7 +255,7 @@ module Test_Symbol
Thread.current.thread_variable_set(:test, nil)
name = noninterned_name
assert_not_send([Thread.current, :thread_variable?, name])
- assert_not_interned(name)
+ assert_not_pinneddown(name)
end
def test_enumerable_inject_op
@@ -485,10 +485,8 @@ module Test_Symbol
def test_iv_get
obj = Object.new
- assert_warning(/not initialized/) do
- assert_no_immortal_symbol_created("rb_iv_get") do |name|
- Bug::Symbol.iv_get(obj, name)
- end
+ assert_no_immortal_symbol_created("rb_iv_get") do |name|
+ Bug::Symbol.iv_get(obj, name)
end
end
end
diff --git a/test/-ext-/test_random.rb b/test/-ext-/test_random.rb
new file mode 100644
index 0000000000..838e5d2f14
--- /dev/null
+++ b/test/-ext-/test_random.rb
@@ -0,0 +1,27 @@
+require 'test/unit'
+
+module TestRandomExt
+ class TestLoop < Test::Unit::TestCase
+ def setup
+ super
+ assert_nothing_raised(LoadError) {require '-test-/random'}
+ end
+
+ def test_bytes
+ rnd = Bug::Random::Loop.new(1)
+ assert_equal("\1", rnd.bytes(1))
+ end
+
+ def test_rand
+ rnd = Bug::Random::Loop.new(1)
+ assert_equal(1, rnd.rand(10))
+ end
+
+ def test_real
+ assert_equal(0.25, Bug::Random::Loop.new(1<<14).rand)
+ assert_equal(0.50, Bug::Random::Loop.new(2<<14).rand)
+ assert_equal(0.75, Bug::Random::Loop.new(3<<14).rand)
+ assert_equal(1.00, Bug::Random::Loop.new(4<<14).rand)
+ end
+ end
+end
diff --git a/test/-ext-/test_scan_args.rb b/test/-ext-/test_scan_args.rb
index dda016d6af..92d696d69e 100644
--- a/test/-ext-/test_scan_args.rb
+++ b/test/-ext-/test_scan_args.rb
@@ -93,14 +93,10 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([1, "a", nil], Bug::ScanArgs.lead_hash("a"))
assert_raise(ArgumentError) {Bug::ScanArgs.lead_hash("a", "b")}
assert_equal([1, "a", {b: 1}], Bug::ScanArgs.lead_hash("a", b: 1))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, {b: 1}, nil], Bug::ScanArgs.lead_hash(b: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.lead_hash(b: 1)}
assert_equal([1, {"a"=>0, b: 1}, nil], Bug::ScanArgs.lead_hash({"a"=>0, b: 1}, **{}))
assert_raise(ArgumentError) {Bug::ScanArgs.lead_hash(1, {"a"=>0, b: 1}, **{})}
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, {}, nil], Bug::ScanArgs.lead_hash(**{}))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.lead_hash(**{})}
end
def test_opt_hash
@@ -109,9 +105,7 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([0, nil, {b: 1}], Bug::ScanArgs.opt_hash(b: 1))
assert_equal([1, "a", {b: 1}], Bug::ScanArgs.opt_hash("a", b: 1))
assert_raise(ArgumentError) {Bug::ScanArgs.opt_hash("a", "b")}
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([1, {"a"=>0}, {b: 1}], Bug::ScanArgs.opt_hash("a"=>0, b: 1))
- end
+ assert_equal([0, nil, {"a"=>0, b: 1}], Bug::ScanArgs.opt_hash("a"=>0, b: 1))
assert_equal([1, {"a"=>0, b: 1}, nil], Bug::ScanArgs.opt_hash({"a"=>0, b: 1}, **{}))
end
@@ -120,13 +114,9 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([2, "a", "b", nil], Bug::ScanArgs.lead_opt_hash("a", "b"))
assert_equal([1, "a", nil, {c: 1}], Bug::ScanArgs.lead_opt_hash("a", c: 1))
assert_equal([2, "a", "b", {c: 1}], Bug::ScanArgs.lead_opt_hash("a", "b", c: 1))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, {c: 1}, nil, nil], Bug::ScanArgs.lead_opt_hash(c: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_hash(c: 1)}
assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_hash("a", "b", "c")}
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([2, "a", {"b"=>0}, {c: 1}], Bug::ScanArgs.lead_opt_hash("a", "b"=>0, c: 1))
- end
+ assert_equal([1, "a", nil, {"b"=>0, c: 1}], Bug::ScanArgs.lead_opt_hash("a", "b"=>0, c: 1))
end
def test_var_hash
@@ -134,9 +124,7 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([1, ["a"], nil], Bug::ScanArgs.var_hash("a"))
assert_equal([1, ["a"], {b: 1}], Bug::ScanArgs.var_hash("a", b: 1))
assert_equal([0, [], {b: 1}], Bug::ScanArgs.var_hash(b: 1))
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([1, [{"a"=>0}], {b: 1}], Bug::ScanArgs.var_hash("a"=>0, b: 1))
- end
+ assert_equal([0, [], {"a"=>0, b: 1}], Bug::ScanArgs.var_hash("a"=>0, b: 1))
end
def test_lead_var_hash
@@ -145,13 +133,9 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([2, "a", ["b"], nil], Bug::ScanArgs.lead_var_hash("a", "b"))
assert_equal([2, "a", ["b"], {c: 1}], Bug::ScanArgs.lead_var_hash("a", "b", c: 1))
assert_equal([1, "a", [], {c: 1}], Bug::ScanArgs.lead_var_hash("a", c: 1))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, {c: 1}, [], nil], Bug::ScanArgs.lead_var_hash(c: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.lead_var_hash(c: 1)}
assert_equal([3, "a", ["b", "c"], nil], Bug::ScanArgs.lead_var_hash("a", "b", "c"))
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([2, "a", [{"b"=>0}], {c: 1}], Bug::ScanArgs.lead_var_hash("a", "b"=>0, c: 1))
- end
+ assert_equal([1, "a", [], {"b"=>0, c: 1}], Bug::ScanArgs.lead_var_hash("a", "b"=>0, c: 1))
end
def test_opt_var_hash
@@ -162,9 +146,7 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([1, "a", [], {c: 1}], Bug::ScanArgs.opt_var_hash("a", c: 1))
assert_equal([0, nil, [], {c: 1}], Bug::ScanArgs.opt_var_hash(c: 1))
assert_equal([3, "a", ["b", "c"], nil], Bug::ScanArgs.opt_var_hash("a", "b", "c"))
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([2, "a", [{"b"=>0}], {c: 1}], Bug::ScanArgs.opt_var_hash("a", "b"=>0, c: 1))
- end
+ assert_equal([1, "a", [], {"b"=>0, c: 1}], Bug::ScanArgs.opt_var_hash("a", "b"=>0, c: 1))
end
def test_lead_opt_var_hash
@@ -173,14 +155,10 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([2, "a", "b", [], nil], Bug::ScanArgs.lead_opt_var_hash("a", "b"))
assert_equal([2, "a", "b", [], {c: 1}], Bug::ScanArgs.lead_opt_var_hash("a", "b", c: 1))
assert_equal([1, "a", nil, [], {c: 1}], Bug::ScanArgs.lead_opt_var_hash("a", c: 1))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, {c: 1}, nil, [], nil], Bug::ScanArgs.lead_opt_var_hash(c: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_var_hash(c: 1)}
assert_equal([3, "a", "b", ["c"], nil], Bug::ScanArgs.lead_opt_var_hash("a", "b", "c"))
assert_equal([3, "a", "b", ["c"], {d: 1}], Bug::ScanArgs.lead_opt_var_hash("a", "b", "c", d: 1))
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([3, "a", "b", [{"c"=>0}], {d: 1}], Bug::ScanArgs.lead_opt_var_hash("a", "b", "c"=>0, d: 1))
- end
+ assert_equal([2, "a", "b", [], {"c"=>0, d: 1}], Bug::ScanArgs.lead_opt_var_hash("a", "b", "c"=>0, d: 1))
end
def test_opt_trail_hash
@@ -189,13 +167,9 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([2, "a", "b", nil], Bug::ScanArgs.opt_trail_hash("a", "b"))
assert_equal([1, nil, "a", {c: 1}], Bug::ScanArgs.opt_trail_hash("a", c: 1))
assert_equal([2, "a", "b", {c: 1}], Bug::ScanArgs.opt_trail_hash("a", "b", c: 1))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, nil, {c: 1}, nil], Bug::ScanArgs.opt_trail_hash(c: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.opt_trail_hash(c: 1)}
assert_raise(ArgumentError) {Bug::ScanArgs.opt_trail_hash("a", "b", "c")}
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([2, "a", {"b"=>0}, {c: 1}], Bug::ScanArgs.opt_trail_hash("a", "b"=>0, c: 1))
- end
+ assert_equal([1, nil, "a", {"b"=>0, c: 1}], Bug::ScanArgs.opt_trail_hash("a", "b"=>0, c: 1))
end
def test_lead_opt_trail_hash
@@ -203,16 +177,12 @@ class TestScanArgs < Test::Unit::TestCase
assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_trail_hash("a")}
assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_trail_hash(c: 1)}
assert_equal([2, "a", nil, "b", nil], Bug::ScanArgs.lead_opt_trail_hash("a", "b"))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([2, "a", nil, {c: 1}, nil], Bug::ScanArgs.lead_opt_trail_hash("a", c: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_trail_hash("a", c: 1)}
assert_equal([2, "a", nil, "b", {c: 1}], Bug::ScanArgs.lead_opt_trail_hash("a", "b", c: 1))
assert_equal([3, "a", "b", "c", nil], Bug::ScanArgs.lead_opt_trail_hash("a", "b", "c"))
assert_equal([3, "a", "b", "c", {c: 1}], Bug::ScanArgs.lead_opt_trail_hash("a", "b", "c", c: 1))
assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_trail_hash("a", "b", "c", "d")}
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([3, "a", "b", {"c"=>0}, {c: 1}], Bug::ScanArgs.lead_opt_trail_hash("a", "b", "c"=>0, c: 1))
- end
+ assert_equal([2, "a", nil, "b", {"c"=>0, c: 1}], Bug::ScanArgs.lead_opt_trail_hash("a", "b", "c"=>0, c: 1))
end
def test_var_trail_hash
@@ -221,62 +191,46 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([2, ["a"], "b", nil], Bug::ScanArgs.var_trail_hash("a", "b"))
assert_equal([1, [], "a", {c: 1}], Bug::ScanArgs.var_trail_hash("a", c: 1))
assert_equal([2, ["a"], "b", {c: 1}], Bug::ScanArgs.var_trail_hash("a", "b", c: 1))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, [], {c: 1}, nil], Bug::ScanArgs.var_trail_hash(c: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.var_trail_hash(c: 1)}
assert_equal([3, ["a", "b"], "c", nil], Bug::ScanArgs.var_trail_hash("a", "b", "c"))
assert_equal([3, ["a", "b"], "c", {c: 1}], Bug::ScanArgs.var_trail_hash("a", "b", "c", c: 1))
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([3, ["a", "b"], {"c"=>0}, {c: 1}], Bug::ScanArgs.var_trail_hash("a", "b", "c"=>0, c: 1))
- end
+ assert_equal([2, ["a"], "b", {"c"=>0, c: 1}], Bug::ScanArgs.var_trail_hash("a", "b", "c"=>0, c: 1))
end
def test_lead_var_trail_hash
assert_raise(ArgumentError) {Bug::ScanArgs.lead_var_trail_hash()}
assert_raise(ArgumentError) {Bug::ScanArgs.lead_var_trail_hash("a")}
assert_raise(ArgumentError) {Bug::ScanArgs.lead_var_trail_hash(c: 1)}
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([2, "a", [], {c: 1}, nil], Bug::ScanArgs.lead_var_trail_hash("a", c: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.lead_var_trail_hash("a", c: 1)}
assert_equal([2, "a", [], "b", nil], Bug::ScanArgs.lead_var_trail_hash("a", "b"))
assert_equal([2, "a", [], "b", {c: 1}], Bug::ScanArgs.lead_var_trail_hash("a", "b", c: 1))
assert_equal([3, "a", ["b"], "c", nil], Bug::ScanArgs.lead_var_trail_hash("a", "b", "c"))
assert_equal([3, "a", ["b"], "c", {c: 1}], Bug::ScanArgs.lead_var_trail_hash("a", "b", "c", c: 1))
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([3, "a", ["b"], {"c"=>0}, {c: 1}], Bug::ScanArgs.lead_var_trail_hash("a", "b", c: 1, "c"=>0))
- end
+ assert_equal([2, "a", [], "b", {"c"=>0, c: 1}], Bug::ScanArgs.lead_var_trail_hash("a", "b", c: 1, "c"=>0))
end
def test_opt_var_trail_hash
assert_raise(ArgumentError) {Bug::ScanArgs.opt_var_trail_hash()}
assert_equal([1, nil, [], "a", nil], Bug::ScanArgs.opt_var_trail_hash("a"))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, nil, [], {c: 1}, nil], Bug::ScanArgs.opt_var_trail_hash(c: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.opt_var_trail_hash(c: 1)}
assert_equal([1, nil, [], "a", {c: 1}], Bug::ScanArgs.opt_var_trail_hash("a", c: 1))
assert_equal([2, "a", [], "b", nil], Bug::ScanArgs.opt_var_trail_hash("a", "b"))
assert_equal([2, "a", [], "b", {c: 1}], Bug::ScanArgs.opt_var_trail_hash("a", "b", c: 1))
assert_equal([3, "a", ["b"], "c", nil], Bug::ScanArgs.opt_var_trail_hash("a", "b", "c"))
assert_equal([3, "a", ["b"], "c", {c: 1}], Bug::ScanArgs.opt_var_trail_hash("a", "b", "c", c: 1))
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([3, "a", ["b"], {"c"=>0}, {c: 1}], Bug::ScanArgs.opt_var_trail_hash("a", "b", "c"=>0, c: 1))
- end
+ assert_equal([2, "a", [], "b", {"c"=>0, c: 1}], Bug::ScanArgs.opt_var_trail_hash("a", "b", "c"=>0, c: 1))
end
def test_lead_opt_var_trail_hash
assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_var_trail_hash()}
assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_var_trail_hash("a")}
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([2, "a", nil, [], {b: 1}, nil], Bug::ScanArgs.lead_opt_var_trail_hash("a", b: 1))
- end
+ assert_raise(ArgumentError) {Bug::ScanArgs.lead_opt_var_trail_hash("a", b: 1)}
assert_equal([2, "a", nil, [], "b", nil], Bug::ScanArgs.lead_opt_var_trail_hash("a", "b"))
assert_equal([2, "a", nil, [], "b", {c: 1}], Bug::ScanArgs.lead_opt_var_trail_hash("a", "b", c: 1))
assert_equal([3, "a", "b", [], "c", nil], Bug::ScanArgs.lead_opt_var_trail_hash("a", "b", "c"))
assert_equal([3, "a", "b", [], "c", {c: 1}], Bug::ScanArgs.lead_opt_var_trail_hash("a", "b", "c", c: 1))
assert_equal([4, "a", "b", ["c"], "d", nil], Bug::ScanArgs.lead_opt_var_trail_hash("a", "b", "c", "d"))
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([4, "a", "b", ["c"], {"d"=>0}, {c: 1}], Bug::ScanArgs.lead_opt_var_trail_hash("a", "b", "c", "d"=>0, c: 1))
- end
+ assert_equal([3, "a", "b", [], "c", {"d"=>0, c: 1}], Bug::ScanArgs.lead_opt_var_trail_hash("a", "b", "c", "d"=>0, c: 1))
end
def test_k_lead_opt_hash
@@ -285,25 +239,8 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([1, "a", nil, {c: 1}], Bug::ScanArgs.k_lead_opt_hash("a", {c: 1}))
assert_equal([2, "a", "b", {c: 1}], Bug::ScanArgs.k_lead_opt_hash("a", "b", c: 1))
assert_equal([2, "a", "b", {c: 1}], Bug::ScanArgs.k_lead_opt_hash("a", "b", {c: 1}))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, {c: 1}, nil, nil], Bug::ScanArgs.k_lead_opt_hash(c: 1))
- end
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([2, "a", {"b"=>0}, {c: 1}], Bug::ScanArgs.k_lead_opt_hash("a", "b"=>0, c: 1))
- end
- end
-
- def test_e_lead_opt_hash
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([1, {}, nil, nil], Bug::ScanArgs.e_lead_opt_hash)
- end
- assert_equal([1, "a", nil, nil], Bug::ScanArgs.e_lead_opt_hash("a"))
- assert_equal([2, "a", "b", nil], Bug::ScanArgs.e_lead_opt_hash("a", "b"))
- assert_equal([2, "a", {c: 1}, nil], Bug::ScanArgs.e_lead_opt_hash("a", c: 1))
- assert_raise(ArgumentError) {Bug::ScanArgs.e_lead_opt_hash("a", "b", c: 1)}
- assert_equal([1, {c: 1}, nil, nil], Bug::ScanArgs.e_lead_opt_hash(c: 1))
- assert_raise(ArgumentError) {Bug::ScanArgs.e_lead_opt_hash("a", "b", "c")}
- assert_equal([2, "a", {"b"=>0, c: 1}, nil], Bug::ScanArgs.e_lead_opt_hash("a", "b"=>0, c: 1))
+ assert_raise(ArgumentError) {Bug::ScanArgs.k_lead_opt_hash(c: 1)}
+ assert_equal([1, "a", nil, {"b"=>0, c: 1}], Bug::ScanArgs.k_lead_opt_hash("a", "b"=>0, c: 1))
end
def test_n_lead_opt_hash
@@ -314,11 +251,9 @@ class TestScanArgs < Test::Unit::TestCase
assert_equal([1, "a", nil, {c: 1}], Bug::ScanArgs.n_lead_opt_hash("a", {c: 1}))
assert_equal([2, "a", "b", {c: 1}], Bug::ScanArgs.n_lead_opt_hash("a", "b", c: 1))
assert_equal([2, "a", "b", {c: 1}], Bug::ScanArgs.n_lead_opt_hash("a", "b", {c: 1}))
- assert_equal([1, {c: 1}, nil, nil], Bug::ScanArgs.n_lead_opt_hash(c: 1))
- assert_equal([1, {c: 1}, nil, nil], Bug::ScanArgs.n_lead_opt_hash({c: 1}))
+ assert_raise(ArgumentError) {Bug::ScanArgs.n_lead_opt_hash(c: 1)}
+ assert_raise(ArgumentError) {Bug::ScanArgs.n_lead_opt_hash({c: 1})}
assert_raise(ArgumentError) {Bug::ScanArgs.n_lead_opt_hash("a", "b", "c")}
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- assert_equal([2, "a", {"b"=>0}, {c: 1}], Bug::ScanArgs.n_lead_opt_hash("a", "b"=>0, c: 1))
- end
+ assert_equal([1, "a", nil, {"b"=>0, c: 1}], Bug::ScanArgs.n_lead_opt_hash("a", "b"=>0, c: 1))
end
end
diff --git a/test/-ext-/tracepoint/test_tracepoint.rb b/test/-ext-/tracepoint/test_tracepoint.rb
index 60bdefd9e0..9d1679602a 100644
--- a/test/-ext-/tracepoint/test_tracepoint.rb
+++ b/test/-ext-/tracepoint/test_tracepoint.rb
@@ -15,16 +15,14 @@ class TestTracepointObj < Test::Unit::TestCase
99
'abc'
_="foobar"
- Object.new
nil
}
EOS
newobj_count, free_count, gc_start_count, gc_end_mark_count, gc_end_sweep_count, *newobjs = *result
- assert_equal 2, newobj_count
- assert_equal 2, newobjs.size
+ assert_equal 1, newobj_count
+ assert_equal 1, newobjs.size
assert_equal 'foobar', newobjs[0]
- assert_equal Object, newobjs[1].class
assert_operator free_count, :>=, 0
assert_operator gc_start_count, :==, gc_end_mark_count
assert_operator gc_start_count, :>=, gc_end_sweep_count
@@ -64,9 +62,11 @@ class TestTracepointObj < Test::Unit::TestCase
bug8492 = '[ruby-dev:47400] [Bug #8492]: infinite after_gc_start_hook reentrance'
assert_nothing_raised(Timeout::Error, bug8492) do
assert_in_out_err(%w[-r-test-/tracepoint], <<-'end;', /\A[1-9]/, timeout: 2)
- stress, GC.stress = GC.stress, false
count = 0
- Bug.after_gc_start_hook = proc {count += 1}
+ hook = proc {count += 1}
+ def run(hook)
+ stress, GC.stress = GC.stress, false
+ Bug.after_gc_start_hook = hook
begin
GC.stress = true
3.times {Object.new}
@@ -74,6 +74,8 @@ class TestTracepointObj < Test::Unit::TestCase
GC.stress = stress
Bug.after_gc_start_hook = nil
end
+ end
+ run(hook)
puts count
end;
end
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
index 0e76081431..16f5505706 100644
--- a/test/bigdecimal/test_bigdecimal.rb
+++ b/test/bigdecimal/test_bigdecimal.rb
@@ -54,11 +54,6 @@ class TestBigDecimal < Test::Unit::TestCase
assert_equal(111, BigDecimal("1_1_1_"))
assert_equal(10**(-1), BigDecimal("1E-1"), '#4825')
assert_equal(1234, BigDecimal(" \t\n\r \r1234 \t\n\r \r"))
- bd = BigDecimal("1.12", 1)
- assert_same(bd, BigDecimal(bd))
- assert_same(bd, BigDecimal(bd, exception: false))
- assert_not_same(bd, BigDecimal(bd, 1))
- assert_not_same(bd, BigDecimal(bd, 1, exception: false))
assert_raise(ArgumentError) { BigDecimal("1", -1) }
assert_raise_with_message(ArgumentError, /"1__1_1"/) { BigDecimal("1__1_1") }
@@ -142,6 +137,14 @@ class TestBigDecimal < Test::Unit::TestCase
end
end
+ def test_BigDecimal_with_complex
+ assert_equal(BigDecimal("1"), BigDecimal(Complex(1, 0)))
+ assert_equal(BigDecimal("0.333333333333333333333"), BigDecimal(Complex(1.quo(3), 0), 21))
+ assert_equal(BigDecimal("0.1235"), BigDecimal(Complex(0.1234567, 0), 4))
+
+ assert_raise_with_message(ArgumentError, "Unable to make a BigDecimal from non-zero imaginary number") { BigDecimal(Complex(1, 1)) }
+ end
+
def test_BigDecimal_with_big_decimal
assert_equal(BigDecimal(1), BigDecimal(BigDecimal(1)))
assert_equal(BigDecimal('+0'), BigDecimal(BigDecimal('+0')))
@@ -228,7 +231,7 @@ class TestBigDecimal < Test::Unit::TestCase
end
def test_s_allocate
- assert_raise_with_message(NoMethodError, /undefined method `allocate'/) { BigDecimal.allocate }
+ assert_raise_with_message(TypeError, /allocator undefined for BigDecimal/) { BigDecimal.allocate }
end
def test_s_new
@@ -331,6 +334,8 @@ class TestBigDecimal < Test::Unit::TestCase
end
def test_save_rounding_mode
+ saved_mode = BigDecimal.mode(BigDecimal::ROUND_MODE)
+
BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR)
BigDecimal.save_rounding_mode do
BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
@@ -338,6 +343,8 @@ class TestBigDecimal < Test::Unit::TestCase
assert_equal(BigDecimal::ROUND_FLOOR, BigDecimal.mode(BigDecimal::ROUND_MODE))
assert_equal(42, BigDecimal.save_rounding_mode { 42 })
+ ensure
+ BigDecimal.mode(BigDecimal::ROUND_MODE, saved_mode)
end
def test_save_limit
@@ -603,12 +610,26 @@ class TestBigDecimal < Test::Unit::TestCase
assert_operator(BigDecimal((2**100).to_s), :==, d)
end
+ def test_precs_deprecated
+ saved = Warning[:deprecated]
+ Warning[:deprecated] = true
+ assert_warn(/BigDecimal#precs is deprecated and will be removed in the future/) do
+ BigDecimal("1").precs
+ end
+ ensure
+ Warning[:deprecated] = saved
+ end
+
def test_precs
- a = BigDecimal("1").precs
- assert_instance_of(Array, a)
- assert_equal(2, a.size)
- assert_kind_of(Integer, a[0])
- assert_kind_of(Integer, a[1])
+ assert_separately(["-rbigdecimal"], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ $VERBOSE = nil
+ a = BigDecimal("1").precs
+ assert_instance_of(Array, a)
+ assert_equal(2, a.size)
+ assert_kind_of(Integer, a[0])
+ assert_kind_of(Integer, a[1])
+ end;
end
def test_hash
@@ -757,7 +778,7 @@ class TestBigDecimal < Test::Unit::TestCase
assert_equal(BigDecimal("0.1"), a, '[ruby-core:34318]')
a, b = BigDecimal("0.11111").coerce(1.quo(3))
- assert_equal(BigDecimal("0." + "3"*a.precs[0]), a)
+ assert_equal(BigDecimal("0." + "3"*a.precision), a)
assert_nothing_raised(TypeError, '#7176') do
BigDecimal('1') + Rational(1)
@@ -1097,6 +1118,11 @@ class TestBigDecimal < Test::Unit::TestCase
assert_equal(-1, x.round(0, BigDecimal::ROUND_HALF_DOWN), bug3803)
assert_equal(-1, x.round(0, BigDecimal::ROUND_HALF_EVEN), bug3803)
end
+
+ assert_instance_of(Integer, x.round)
+ assert_instance_of(Integer, x.round(0))
+ assert_instance_of(Integer, x.round(-1))
+ assert_instance_of(BigDecimal, x.round(1))
end
def test_round_half_even
@@ -1449,8 +1475,13 @@ class TestBigDecimal < Test::Unit::TestCase
def test_power_without_prec
pi = BigDecimal("3.14159265358979323846264338327950288419716939937511")
e = BigDecimal("2.71828182845904523536028747135266249775724709369996")
- pow = BigDecimal("22.4591577183610454734271522045437350275893151339967843873233068")
+ pow = BigDecimal("0.2245915771836104547342715220454373502758931513399678438732330680117143493477164265678321738086407229773690574073268002736527e2")
assert_equal(pow, pi.power(e))
+
+ n = BigDecimal("2222")
+ assert_equal(BigDecimal("0.5171353084572525892492416e12"), (n ** 3.5))
+ assert_equal(BigDecimal("0.517135308457252592e12"), (n ** 3.5r))
+ assert_equal(BigDecimal("0.517135308457252589249241582e12"), (n ** BigDecimal("3.5",15)))
end
def test_power_with_prec
@@ -1531,29 +1562,34 @@ class TestBigDecimal < Test::Unit::TestCase
assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (-1 / inf).sign)
end
+ def assert_equal_us_ascii_string(a, b)
+ assert_equal(a, b)
+ assert_equal(Encoding::US_ASCII, b.encoding)
+ end
+
def test_to_special_string
BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
nan = BigDecimal("NaN")
- assert_equal("NaN", nan.to_s)
+ assert_equal_us_ascii_string("NaN", nan.to_s)
inf = BigDecimal("Infinity")
- assert_equal("Infinity", inf.to_s)
- assert_equal(" Infinity", inf.to_s(" "))
- assert_equal("+Infinity", inf.to_s("+"))
- assert_equal("-Infinity", (-inf).to_s)
+ assert_equal_us_ascii_string("Infinity", inf.to_s)
+ assert_equal_us_ascii_string(" Infinity", inf.to_s(" "))
+ assert_equal_us_ascii_string("+Infinity", inf.to_s("+"))
+ assert_equal_us_ascii_string("-Infinity", (-inf).to_s)
pzero = BigDecimal("0")
- assert_equal("0.0", pzero.to_s)
- assert_equal(" 0.0", pzero.to_s(" "))
- assert_equal("+0.0", pzero.to_s("+"))
- assert_equal("-0.0", (-pzero).to_s)
+ assert_equal_us_ascii_string("0.0", pzero.to_s)
+ assert_equal_us_ascii_string(" 0.0", pzero.to_s(" "))
+ assert_equal_us_ascii_string("+0.0", pzero.to_s("+"))
+ assert_equal_us_ascii_string("-0.0", (-pzero).to_s)
end
def test_to_string
- assert_equal("0.01", BigDecimal("0.01").to_s("F"))
+ assert_equal_us_ascii_string("0.01", BigDecimal("0.01").to_s("F"))
s = "0." + "0" * 100 + "1"
- assert_equal(s, BigDecimal(s).to_s("F"))
+ assert_equal_us_ascii_string(s, BigDecimal(s).to_s("F"))
s = "1" + "0" * 100 + ".0"
- assert_equal(s, BigDecimal(s).to_s("F"))
+ assert_equal_us_ascii_string(s, BigDecimal(s).to_s("F"))
end
def test_ctov
@@ -1881,6 +1917,115 @@ class TestBigDecimal < Test::Unit::TestCase
EOS
end
+ def test_precision_only_integer
+ assert_equal(0, BigDecimal(0).precision)
+ assert_equal(1, BigDecimal(1).precision)
+ assert_equal(1, BigDecimal(-1).precision)
+ assert_equal(2, BigDecimal(10).precision)
+ assert_equal(2, BigDecimal(-10).precision)
+ assert_equal(21, BigDecimal(100_000_000_000_000_000_000).precision)
+ assert_equal(21, BigDecimal(-100_000_000_000_000_000_000).precision)
+ assert_equal(103, BigDecimal("111e100").precision)
+ assert_equal(103, BigDecimal("-111e100").precision)
+ end
+
+ def test_precision_only_fraction
+ assert_equal(1, BigDecimal("0.1").precision)
+ assert_equal(1, BigDecimal("-0.1").precision)
+ assert_equal(1, BigDecimal("0.01").precision)
+ assert_equal(1, BigDecimal("-0.01").precision)
+ assert_equal(2, BigDecimal("0.11").precision)
+ assert_equal(2, BigDecimal("-0.11").precision)
+ assert_equal(21, BigDecimal("0.000_000_000_000_000_000_001").precision)
+ assert_equal(21, BigDecimal("-0.000_000_000_000_000_000_001").precision)
+ assert_equal(100, BigDecimal("111e-100").precision)
+ assert_equal(100, BigDecimal("-111e-100").precision)
+ end
+
+ def test_precision_full
+ assert_equal(1, BigDecimal("0.1").precision)
+ assert_equal(1, BigDecimal("-0.1").precision)
+ assert_equal(1, BigDecimal("0.01").precision)
+ assert_equal(1, BigDecimal("-0.01").precision)
+ assert_equal(2, BigDecimal("0.11").precision)
+ assert_equal(2, BigDecimal("-0.11").precision)
+ assert_equal(5, BigDecimal("11111e-2").precision)
+ assert_equal(5, BigDecimal("-11111e-2").precision)
+ assert_equal(21, BigDecimal("100.000_000_000_000_000_001").precision)
+ assert_equal(21, BigDecimal("-100.000_000_000_000_000_001").precision)
+ end
+
+ def test_precision_special
+ BigDecimal.save_exception_mode do
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+
+ assert_equal(0, BigDecimal("Infinity").precision)
+ assert_equal(0, BigDecimal("-Infinity").precision)
+ assert_equal(0, BigDecimal("NaN").precision)
+ end
+ end
+
+ def test_n_significant_digits_only_integer
+ assert_equal(0, BigDecimal(0).n_significant_digits)
+ assert_equal(1, BigDecimal(1).n_significant_digits)
+ assert_equal(1, BigDecimal(-1).n_significant_digits)
+ assert_equal(1, BigDecimal(10).n_significant_digits)
+ assert_equal(1, BigDecimal(-10).n_significant_digits)
+ assert_equal(3, BigDecimal(101).n_significant_digits)
+ assert_equal(3, BigDecimal(-101).n_significant_digits)
+ assert_equal(1, BigDecimal(100_000_000_000_000_000_000).n_significant_digits)
+ assert_equal(1, BigDecimal(-100_000_000_000_000_000_000).n_significant_digits)
+ assert_equal(21, BigDecimal(100_000_000_000_000_000_001).n_significant_digits)
+ assert_equal(21, BigDecimal(-100_000_000_000_000_000_001).n_significant_digits)
+ assert_equal(3, BigDecimal("111e100").n_significant_digits)
+ assert_equal(3, BigDecimal("-111e100").n_significant_digits)
+ end
+
+ def test_n_significant_digits_only_fraction
+ assert_equal(1, BigDecimal("0.1").n_significant_digits)
+ assert_equal(1, BigDecimal("-0.1").n_significant_digits)
+ assert_equal(1, BigDecimal("0.01").n_significant_digits)
+ assert_equal(1, BigDecimal("-0.01").n_significant_digits)
+ assert_equal(2, BigDecimal("0.11").n_significant_digits)
+ assert_equal(2, BigDecimal("-0.11").n_significant_digits)
+ assert_equal(1, BigDecimal("0.000_000_000_000_000_000_001").n_significant_digits)
+ assert_equal(1, BigDecimal("-0.000_000_000_000_000_000_001").n_significant_digits)
+ assert_equal(3, BigDecimal("111e-100").n_significant_digits)
+ assert_equal(3, BigDecimal("-111e-100").n_significant_digits)
+ end
+
+ def test_n_significant_digits_full
+ assert_equal(2, BigDecimal("1.1").n_significant_digits)
+ assert_equal(2, BigDecimal("-1.1").n_significant_digits)
+ assert_equal(3, BigDecimal("1.01").n_significant_digits)
+ assert_equal(3, BigDecimal("-1.01").n_significant_digits)
+ assert_equal(5, BigDecimal("11111e-2").n_significant_digits)
+ assert_equal(5, BigDecimal("-11111e-2").n_significant_digits)
+ assert_equal(21, BigDecimal("100.000_000_000_000_000_001").n_significant_digits)
+ assert_equal(21, BigDecimal("-100.000_000_000_000_000_001").n_significant_digits)
+ end
+
+ def test_n_significant_digits_special
+ BigDecimal.save_exception_mode do
+ BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
+ BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
+
+ assert_equal(0, BigDecimal("Infinity").n_significant_digits)
+ assert_equal(0, BigDecimal("-Infinity").n_significant_digits)
+ assert_equal(0, BigDecimal("NaN").n_significant_digits)
+ end
+ end
+
+ def test_initialize_copy_dup_clone_frozen_error
+ bd = BigDecimal(1)
+ bd2 = BigDecimal(2)
+ err = RUBY_VERSION >= '2.5' ? FrozenError : TypeError
+ assert_raise(err) { bd.send(:initialize_copy, bd2) }
+ assert_raise(err) { bd.send(:initialize_clone, bd2) }
+ assert_raise(err) { bd.send(:initialize_dup, bd2) }
+ end
+
def assert_no_memory_leak(code, *rest, **opt)
code = "8.times {20_000.times {begin #{code}; rescue NoMemoryError; end}; GC.start}"
super(["-rbigdecimal"],
diff --git a/test/bigdecimal/test_bigdecimal_util.rb b/test/bigdecimal/test_bigdecimal_util.rb
index b963fcdeeb..b855fd58a0 100644
--- a/test/bigdecimal/test_bigdecimal_util.rb
+++ b/test/bigdecimal/test_bigdecimal_util.rb
@@ -17,10 +17,12 @@ class TestBigDecimalUtil < Test::Unit::TestCase
end
def test_Float_to_d_without_precision
- delta = 1.0/10**(Float::DIG)
- assert_in_delta(BigDecimal(0.5, Float::DIG), 0.5.to_d, delta)
- assert_in_delta(BigDecimal(355.0/113.0, Float::DIG), (355.0/113.0).to_d, delta)
- assert_equal(9.05.to_d.to_s('F'), "9.05")
+ delta = 1.0/10**(Float::DIG+1)
+ assert_in_delta(BigDecimal(0.5, Float::DIG+1), 0.5.to_d, delta)
+ assert_in_delta(BigDecimal(355.0/113.0, Float::DIG+1), (355.0/113.0).to_d, delta)
+
+ assert_equal(9.05, 9.05.to_d.to_f)
+ assert_equal("9.050000000000001", 9.05.to_d.to_s('F'))
bug9214 = '[ruby-core:58858]'
assert_equal((-0.0).to_d.sign, -1, bug9214)
@@ -43,6 +45,12 @@ class TestBigDecimalUtil < Test::Unit::TestCase
assert(1.1.to_d(digits).frozen?)
end
+ def test_Float_to_d_bug13331
+ assert_equal(64.4.to_d,
+ 1.to_d * 64.4,
+ "[ruby-core:80234] [Bug #13331]")
+ end
+
def test_Rational_to_d
digits = 100
delta = 1.0/10**(digits)
@@ -60,6 +68,22 @@ class TestBigDecimalUtil < Test::Unit::TestCase
assert_raise(ArgumentError) { 355.quo(113).to_d(-42) }
end
+ def test_Complex_to_d
+ BigDecimal.save_rounding_mode do
+ BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
+
+ assert_equal(BigDecimal("1"), Complex(1, 0).to_d)
+ assert_equal(BigDecimal("0.333333333333333333333"),
+ Complex(1.quo(3), 0).to_d(21))
+ assert_equal(BigDecimal("0.1234567"), Complex(0.1234567, 0).to_d)
+ assert_equal(BigDecimal("0.1235"), Complex(0.1234567, 0).to_d(4))
+
+ assert_raise_with_message(ArgumentError, "can't omit precision for a Rational.") { Complex(1.quo(3), 0).to_d }
+
+ assert_raise_with_message(ArgumentError, "Unable to make a BigDecimal from non-zero imaginary number") { Complex(1, 1).to_d }
+ end
+ end
+
def test_String_to_d
assert_equal(BigDecimal('1'), "1__1_1".to_d)
assert_equal(BigDecimal('2.5'), "2.5".to_d)
diff --git a/test/bigdecimal/test_ractor.rb b/test/bigdecimal/test_ractor.rb
new file mode 100644
index 0000000000..3ccd7c8073
--- /dev/null
+++ b/test/bigdecimal/test_ractor.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+require_relative "testbase"
+
+class TestBigDecimalRactor < Test::Unit::TestCase
+ include TestBigDecimalBase
+
+ def setup
+ super
+ skip unless defined? Ractor
+ end
+
+ def test_ractor_shareable
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ $VERBOSE = nil
+ require "bigdecimal"
+ r = Ractor.new BigDecimal(Math::PI, Float::DIG+1) do |pi|
+ BigDecimal('2.0')*pi
+ end
+ assert_equal(2*Math::PI, r.take)
+ end;
+ end
+end
diff --git a/test/cgi/test_cgi_cookie.rb b/test/cgi/test_cgi_cookie.rb
index e3ec4bea52..985cc0d7a1 100644
--- a/test/cgi/test_cgi_cookie.rb
+++ b/test/cgi/test_cgi_cookie.rb
@@ -60,24 +60,6 @@ class CGICookieTest < Test::Unit::TestCase
end
- def test_cgi_cookie_new_with_domain
- h = {'name'=>'name1', 'value'=>'value1'}
- cookie = CGI::Cookie.new('domain'=>'a.example.com', **h)
- assert_equal('a.example.com', cookie.domain)
-
- cookie = CGI::Cookie.new('domain'=>'1.example.com', **h)
- assert_equal('1.example.com', cookie.domain, 'enhanced by RFC 1123')
-
- assert_raise(ArgumentError) {
- CGI::Cookie.new('domain'=>'-a.example.com', **h)
- }
-
- assert_raise(ArgumentError) {
- CGI::Cookie.new('domain'=>'a-.example.com', **h)
- }
- end
-
-
def test_cgi_cookie_scriptname
cookie = CGI::Cookie.new('name1', 'value1')
assert_equal('', cookie.path)
@@ -136,70 +118,6 @@ class CGICookieTest < Test::Unit::TestCase
end
- def test_cgi_cookie_domain_injection_into_name
- name = "a=b; domain=example.com;"
- path = "/"
- domain = "example.jp"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
-
- def test_cgi_cookie_newline_injection_into_name
- name = "a=b;\r\nLocation: http://example.com#"
- path = "/"
- domain = "example.jp"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
-
- def test_cgi_cookie_multibyte_injection_into_name
- name = "a=b;\u3042"
- path = "/"
- domain = "example.jp"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
-
- def test_cgi_cookie_injection_into_path
- name = "name"
- path = "/; samesite=none"
- domain = "example.jp"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
-
- def test_cgi_cookie_injection_into_domain
- name = "name"
- path = "/"
- domain = "example.jp; samesite=none"
- assert_raise(ArgumentError) do
- CGI::Cookie.new('name' => name,
- 'value' => "value",
- 'domain' => domain,
- 'path' => path)
- end
- end
-
instance_methods.each do |method|
private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
diff --git a/test/cgi/test_cgi_core.rb b/test/cgi/test_cgi_core.rb
index 255203dc17..f7adb7e99f 100644
--- a/test/cgi/test_cgi_core.rb
+++ b/test/cgi/test_cgi_core.rb
@@ -88,6 +88,8 @@ class CGICoreTest < Test::Unit::TestCase
## invalid parameter name
assert_equal('', cgi['*notfound*'])
assert_equal([], cgi.params['*notfound*'])
+ ensure
+ $stdin = STDIN
end
def test_cgi_core_params_encoding_check
@@ -125,6 +127,8 @@ class CGICoreTest < Test::Unit::TestCase
else
assert(true)
end
+ ensure
+ $stdin = STDIN
end
diff --git a/test/cgi/test_cgi_header.rb b/test/cgi/test_cgi_header.rb
index ec2f4deb72..bab2d0348a 100644
--- a/test/cgi/test_cgi_header.rb
+++ b/test/cgi/test_cgi_header.rb
@@ -176,14 +176,6 @@ class CGIHeaderTest < Test::Unit::TestCase
end
- def test_cgi_http_header_crlf_injection
- cgi = CGI.new
- assert_raise(RuntimeError) { cgi.http_header("text/xhtml\r\nBOO") }
- assert_raise(RuntimeError) { cgi.http_header("type" => "text/xhtml\r\nBOO") }
- assert_raise(RuntimeError) { cgi.http_header("status" => "200 OK\r\nBOO") }
- assert_raise(RuntimeError) { cgi.http_header("location" => "text/xhtml\r\nBOO") }
- end
-
instance_methods.each do |method|
private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
diff --git a/test/coverage/test_coverage.rb b/test/coverage/test_coverage.rb
index 1de39bf569..a80e33379c 100644
--- a/test/coverage/test_coverage.rb
+++ b/test/coverage/test_coverage.rb
@@ -740,4 +740,24 @@ class TestCoverage < Test::Unit::TestCase
end
end;
end
+
+ def test_branch_coverage_in_ensure_clause
+ result = {
+ :branches => {
+ [:if, 0, 4, 2, 4, 11] => {
+ [:then, 1, 4, 2, 4, 5] => 1,
+ [:else, 2, 4, 2, 4, 11] => 1,
+ }
+ }
+ }
+ assert_coverage(<<~"end;", { branches: true }, result) # Bug #16967
+ def foo
+ yield
+ ensure
+ :ok if $!
+ end
+ foo {}
+ foo { raise } rescue nil
+ end;
+ end
end
diff --git a/test/csv/helper.rb b/test/csv/helper.rb
index eadff54408..1f9cf96979 100644
--- a/test/csv/helper.rb
+++ b/test/csv/helper.rb
@@ -15,4 +15,28 @@ module Helper
ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] = chunk_size_keep
end
end
+
+ def with_verbose(verbose)
+ original = $VERBOSE
+ begin
+ $VERBOSE = verbose
+ yield
+ ensure
+ $VERBOSE = original
+ end
+ end
+
+ def with_default_internal(encoding)
+ original = Encoding.default_internal
+ begin
+ with_verbose(false) do
+ Encoding.default_internal = encoding
+ end
+ yield
+ ensure
+ with_verbose(false) do
+ Encoding.default_internal = original
+ end
+ end
+ end
end
diff --git a/test/csv/interface/test_read.rb b/test/csv/interface/test_read.rb
index 58ec188f94..b86c54fc9f 100644
--- a/test/csv/interface/test_read.rb
+++ b/test/csv/interface/test_read.rb
@@ -125,6 +125,68 @@ class TestCSVInterfaceRead < Test::Unit::TestCase
end
end
+ def test_open_invalid_byte_sequence_in_utf_8
+ CSV.open(@input.path, "w", encoding: Encoding::CP932) do |rows|
+ error = assert_raise(Encoding::InvalidByteSequenceError) do
+ rows << ["\x82\xa0"]
+ end
+ assert_equal('"\x82" on UTF-8',
+ error.message)
+ end
+ end
+
+ def test_open_with_invalid_nil
+ CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: nil) do |rows|
+ error = assert_raise(Encoding::InvalidByteSequenceError) do
+ rows << ["\x82\xa0"]
+ end
+ assert_equal('"\x82" on UTF-8',
+ error.message)
+ end
+ end
+
+ def test_open_with_invalid_replace
+ CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: :replace) do |rows|
+ rows << ["\x82\xa0".force_encoding(Encoding::UTF_8)]
+ end
+ CSV.open(@input.path, encoding: Encoding::CP932) do |csv|
+ assert_equal([["??"]],
+ csv.to_a)
+ end
+ end
+
+ def test_open_with_invalid_replace_and_replace_string
+ CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: :replace, replace: "X") do |rows|
+ rows << ["\x82\xa0".force_encoding(Encoding::UTF_8)]
+ end
+ CSV.open(@input.path, encoding: Encoding::CP932) do |csv|
+ assert_equal([["XX"]],
+ csv.to_a)
+ end
+ end
+
+ def test_open_with_undef_replace
+ # U+00B7 Middle Dot
+ CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace) do |rows|
+ rows << ["\u00B7"]
+ end
+ CSV.open(@input.path, encoding: Encoding::CP932) do |csv|
+ assert_equal([["?"]],
+ csv.to_a)
+ end
+ end
+
+ def test_open_with_undef_replace_and_replace_string
+ # U+00B7 Middle Dot
+ CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace, replace: "X") do |rows|
+ rows << ["\u00B7"]
+ end
+ CSV.open(@input.path, encoding: Encoding::CP932) do |csv|
+ assert_equal([["X"]],
+ csv.to_a)
+ end
+ end
+
def test_parse
assert_equal(@rows,
CSV.parse(@data, col_sep: "\t", row_sep: "\r\n"))
diff --git a/test/csv/interface/test_read_write.rb b/test/csv/interface/test_read_write.rb
index 877e5f355e..20c9fe317e 100644
--- a/test/csv/interface/test_read_write.rb
+++ b/test/csv/interface/test_read_write.rb
@@ -6,7 +6,7 @@ class TestCSVInterfaceReadWrite < Test::Unit::TestCase
extend DifferentOFS
def test_filter
- input = <<-CSV
+ input = <<-CSV.freeze
1;2;3
4;5
CSV
@@ -24,6 +24,71 @@ class TestCSVInterfaceReadWrite < Test::Unit::TestCase
CSV
end
+ def test_filter_headers_true
+ input = <<-CSV.freeze
+Name,Value
+foo,0
+bar,1
+baz,2
+ CSV
+ output = ""
+ CSV.filter(input, output, headers: true) do |row|
+ row[0] += "X"
+ row[1] = row[1].to_i + 1
+ end
+ assert_equal(<<-CSV, output)
+fooX,1
+barX,2
+bazX,3
+ CSV
+ end
+
+ def test_filter_headers_true_write_headers
+ input = <<-CSV.freeze
+Name,Value
+foo,0
+bar,1
+baz,2
+ CSV
+ output = ""
+ CSV.filter(input, output, headers: true, out_write_headers: true) do |row|
+ if row.is_a?(Array)
+ row[0] += "X"
+ row[1] += "Y"
+ else
+ row[0] += "X"
+ row[1] = row[1].to_i + 1
+ end
+ end
+ assert_equal(<<-CSV, output)
+NameX,ValueY
+fooX,1
+barX,2
+bazX,3
+ CSV
+ end
+
+ def test_filter_headers_array_write_headers
+ input = <<-CSV.freeze
+foo,0
+bar,1
+baz,2
+ CSV
+ output = ""
+ CSV.filter(input, output,
+ headers: ["Name", "Value"],
+ out_write_headers: true) do |row|
+ row[0] += "X"
+ row[1] = row[1].to_i + 1
+ end
+ assert_equal(<<-CSV, output)
+Name,Value
+fooX,1
+barX,2
+bazX,3
+ CSV
+ end
+
def test_instance_same
data = ""
assert_equal(CSV.instance(data, col_sep: ";").object_id,
diff --git a/test/csv/parse/test_general.rb b/test/csv/parse/test_general.rb
index 655bb26560..52b0cab000 100644
--- a/test/csv/parse/test_general.rb
+++ b/test/csv/parse/test_general.rb
@@ -246,7 +246,11 @@ line,5,jkl
private
def assert_parse_errors_out(data, **options)
assert_raise(CSV::MalformedCSVError) do
- Timeout.timeout(0.2) do
+ timeout = 0.2
+ if defined?(RubyVM::MJIT.enabled?) and RubyVM::MJIT.enabled?
+ timeout = 5 # for --jit-wait
+ end
+ Timeout.timeout(timeout) do
CSV.parse(data, **options)
fail("Parse didn't error out")
end
diff --git a/test/csv/parse/test_skip_lines.rb b/test/csv/parse/test_skip_lines.rb
index 196858f1b0..98d67ae51c 100644
--- a/test/csv/parse/test_skip_lines.rb
+++ b/test/csv/parse/test_skip_lines.rb
@@ -102,4 +102,17 @@ class TestCSVParseSkipLines < Test::Unit::TestCase
:skip_lines => /\A#/))
end
end
+
+ def test_empty_line_and_liberal_parsing
+ assert_equal([["a", "b"]],
+ CSV.parse("a,b\n",
+ :liberal_parsing => true,
+ :skip_lines => /^$/))
+ end
+
+ def test_crlf
+ assert_equal([["a", "b"]],
+ CSV.parse("a,b\r\n,\r\n",
+ :skip_lines => /^,+$/))
+ end
end
diff --git a/test/csv/parse/test_strip.rb b/test/csv/parse/test_strip.rb
index 0255bb9a30..3564fcb3ba 100644
--- a/test/csv/parse/test_strip.rb
+++ b/test/csv/parse/test_strip.rb
@@ -21,6 +21,11 @@ class TestCSVParseStrip < Test::Unit::TestCase
CSV.parse_line(%Q{a ,b }, strip: true))
end
+ def test_middle
+ assert_equal(["a b"],
+ CSV.parse_line(%Q{a b}, strip: true))
+ end
+
def test_quoted
assert_equal([" a ", " b "],
CSV.parse_line(%Q{" a "," b "}, strip: true))
diff --git a/test/csv/test_encodings.rb b/test/csv/test_encodings.rb
index acee03db45..8d228c05f3 100644
--- a/test/csv/test_encodings.rb
+++ b/test/csv/test_encodings.rb
@@ -5,6 +5,7 @@ require_relative "helper"
class TestCSVEncodings < Test::Unit::TestCase
extend DifferentOFS
+ include Helper
def setup
super
@@ -241,6 +242,18 @@ class TestCSVEncodings < Test::Unit::TestCase
assert_equal("UTF-8", data.to_csv.encoding.name)
end
+ def test_encoding_is_not_upgraded_for_non_ascii_content_during_writing_as_needed
+ data = ["\u00c0".encode("ISO-8859-1"), "\u3042"]
+ assert_equal([
+ "ISO-8859-1",
+ "UTF-8",
+ ],
+ data.collect {|field| field.encoding.name})
+ assert_raise(Encoding::CompatibilityError) do
+ data.to_csv
+ end
+ end
+
def test_explicit_encoding
bug9766 = '[ruby-core:62113] [Bug #9766]'
s = CSV.generate(encoding: "Windows-31J") do |csv|
@@ -249,6 +262,15 @@ class TestCSVEncodings < Test::Unit::TestCase
assert_equal(["foo,\u3042\n".encode(Encoding::Windows_31J), Encoding::Windows_31J], [s, s.encoding], bug9766)
end
+ def test_encoding_with_default_internal
+ with_default_internal(Encoding::UTF_8) do
+ s = CSV.generate(String.new(encoding: Encoding::Big5), encoding: Encoding::Big5) do |csv|
+ csv << ["漢字"]
+ end
+ assert_equal(["漢字\n".encode(Encoding::Big5), Encoding::Big5], [s, s.encoding])
+ end
+ end
+
def test_row_separator_detection_with_invalid_encoding
csv = CSV.new("invalid,\xF8\r\nvalid,x\r\n".force_encoding("UTF-8"),
encoding: "UTF-8")
diff --git a/test/csv/test_row.rb b/test/csv/test_row.rb
index f709dd3f13..b717945041 100644
--- a/test/csv/test_row.rb
+++ b/test/csv/test_row.rb
@@ -425,6 +425,9 @@ class TestCSVRow < Test::Unit::TestCase
def test_dup
row = CSV::Row.new(["A"], ["foo"])
dupped_row = row.dup
+ dupped_row["A"] = "bar"
+ assert_equal(["foo", "bar"],
+ [row["A"], dupped_row["A"]])
dupped_row.delete("A")
assert_equal(["foo", nil],
[row["A"], dupped_row["A"]])
diff --git a/test/csv/test_table.rb b/test/csv/test_table.rb
index 50edc77e40..3202963a67 100644
--- a/test/csv/test_table.rb
+++ b/test/csv/test_table.rb
@@ -16,7 +16,7 @@ class TestCSVTable < Test::Unit::TestCase
@header_table = CSV::Table.new(
[CSV::Row.new(%w{A B C}, %w{A B C}, true)] + @rows
)
-
+
@header_only_table = CSV::Table.new([], headers: %w{A B C})
end
diff --git a/test/csv/write/test_converters.rb b/test/csv/write/test_converters.rb
index a93b1040ac..0e0080b4c5 100644
--- a/test/csv/write/test_converters.rb
+++ b/test/csv/write/test_converters.rb
@@ -20,14 +20,14 @@ module TestCSVWriteConverters
end
def test_nil_value
- assert_equal(%Q[a,NaN,c\n],
- generate_line(["a", nil, "c"],
+ assert_equal(%Q[a,NaN,29\n],
+ generate_line(["a", nil, 29],
write_nil_value: "NaN"))
end
def test_empty_value
- assert_equal(%Q[a,,c\n],
- generate_line(["a", "", "c"],
+ assert_equal(%Q[a,,29\n],
+ generate_line(["a", "", 29],
write_empty_value: nil))
end
end
diff --git a/test/csv/write/test_force_quotes.rb b/test/csv/write/test_force_quotes.rb
new file mode 100644
index 0000000000..622dcb021b
--- /dev/null
+++ b/test/csv/write/test_force_quotes.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: false
+
+require_relative "../helper"
+
+module TestCSVWriteForceQuotes
+ def test_default
+ assert_equal(%Q[1,2,3#{$INPUT_RECORD_SEPARATOR}],
+ generate_line(["1", "2", "3"]))
+ end
+
+ def test_true
+ assert_equal(%Q["1","2","3"#{$INPUT_RECORD_SEPARATOR}],
+ generate_line(["1", "2", "3"],
+ force_quotes: true))
+ end
+
+ def test_false
+ assert_equal(%Q[1,2,3#{$INPUT_RECORD_SEPARATOR}],
+ generate_line(["1", "2", "3"],
+ force_quotes: false))
+ end
+
+ def test_field_name
+ assert_equal(%Q["1",2,"3"#{$INPUT_RECORD_SEPARATOR}],
+ generate_line(["1", "2", "3"],
+ headers: ["a", "b", "c"],
+ force_quotes: ["a", :c]))
+ end
+
+ def test_field_name_without_headers
+ force_quotes = ["a", "c"]
+ error = assert_raise(ArgumentError) do
+ generate_line(["1", "2", "3"],
+ force_quotes: force_quotes)
+ end
+ assert_equal(":headers is required when you use field name " +
+ "in :force_quotes: " +
+ "#{force_quotes.first.inspect}: #{force_quotes.inspect}",
+ error.message)
+ end
+
+ def test_field_index
+ assert_equal(%Q["1",2,"3"#{$INPUT_RECORD_SEPARATOR}],
+ generate_line(["1", "2", "3"],
+ force_quotes: [0, 2]))
+ end
+
+ def test_field_unknown
+ force_quotes = [1.1]
+ error = assert_raise(ArgumentError) do
+ generate_line(["1", "2", "3"],
+ force_quotes: force_quotes)
+ end
+ assert_equal(":force_quotes element must be field index or field name: " +
+ "#{force_quotes.first.inspect}: #{force_quotes.inspect}",
+ error.message)
+ end
+end
+
+class TestCSVWriteForceQuotesGenerateLine < Test::Unit::TestCase
+ include TestCSVWriteForceQuotes
+ extend DifferentOFS
+
+ def generate_line(row, **kwargs)
+ CSV.generate_line(row, **kwargs)
+ end
+end
+
+class TestCSVWriteForceQuotesGenerate < Test::Unit::TestCase
+ include TestCSVWriteForceQuotes
+ extend DifferentOFS
+
+ def generate_line(row, **kwargs)
+ CSV.generate(**kwargs) do |csv|
+ csv << row
+ end
+ end
+end
diff --git a/test/csv/write/test_general.rb b/test/csv/write/test_general.rb
index f39456b98a..677119e1ae 100644
--- a/test/csv/write/test_general.rb
+++ b/test/csv/write/test_general.rb
@@ -4,6 +4,8 @@
require_relative "../helper"
module TestCSVWriteGeneral
+ include Helper
+
def test_tab
assert_equal("\t#{$INPUT_RECORD_SEPARATOR}",
generate_line(["\t"]))
@@ -221,20 +223,6 @@ module TestCSVWriteGeneral
generate_line(row))
end
end
-
- def with_default_internal(encoding)
- original = Encoding.default_internal
- begin
- $VERBOSE, verbose_bak = nil, $VERBOSE
- Encoding.default_internal = encoding
- $VERBOSE = verbose_bak
- yield
- ensure
- $VERBOSE, verbose_bak = nil, $VERBOSE
- Encoding.default_internal = original
- $VERBOSE = verbose_bak
- end
- end
end
class TestCSVWriteGeneralGenerateLine < Test::Unit::TestCase
diff --git a/test/date/test_date_ractor.rb b/test/date/test_date_ractor.rb
new file mode 100644
index 0000000000..7b0c3f4911
--- /dev/null
+++ b/test/date/test_date_ractor.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+require 'test/unit'
+require 'date'
+
+class TestDateParse < Test::Unit::TestCase
+ def code(klass = Date, share: false)
+ <<~RUBY.gsub('Date', klass.name)
+ share = #{share}
+ d = Date.parse('Aug 23:55')
+ Ractor.make_shareable(d) if share
+ d2, d3 = Ractor.new(d) { |d| [d, Date.parse(d.to_s)] }.take
+ if share
+ assert_same d, d2
+ else
+ assert_equal d, d2
+ end
+ assert_equal d, d3
+ RUBY
+ end
+
+ def test_date_ractor
+ assert_ractor(code , require: 'date')
+ assert_ractor(code( share: true), require: 'date')
+ assert_ractor(code(DateTime ), require: 'date')
+ assert_ractor(code(DateTime, share: true), require: 'date')
+ end
+end
diff --git a/test/did_you_mean/fixtures/book.rb b/test/did_you_mean/fixtures/book.rb
index e6644a6263..e31e629d43 100644
--- a/test/did_you_mean/fixtures/book.rb
+++ b/test/did_you_mean/fixtures/book.rb
@@ -1,4 +1,4 @@
class Book
- class Cover
+ class Spine
end
end
diff --git a/test/did_you_mean/spell_checking/test_class_name_check.rb b/test/did_you_mean/spell_checking/test_class_name_check.rb
index ffe7a4c31b..1b863ee27c 100644
--- a/test/did_you_mean/spell_checking/test_class_name_check.rb
+++ b/test/did_you_mean/spell_checking/test_class_name_check.rb
@@ -66,7 +66,9 @@ class ClassNameCheckTest < Test::Unit::TestCase
end
def test_does_not_suggest_user_input
- error = assert_raise(NameError) { ::Book::Cover }
+ Book.send(:remove_const, :Spine) if Book.constants.include?(:Spine)
+
+ error = assert_raise(NameError) { ::Book::Spine }
# This is a weird require, but in a multi-threaded condition, a constant may
# be loaded between when a NameError occurred and when the spell checker
diff --git a/test/did_you_mean/spell_checking/test_method_name_check.rb b/test/did_you_mean/spell_checking/test_method_name_check.rb
index f3a6b1c7c7..6e14e6acc4 100644
--- a/test/did_you_mean/spell_checking/test_method_name_check.rb
+++ b/test/did_you_mean/spell_checking/test_method_name_check.rb
@@ -137,4 +137,11 @@ class MethodNameCheckTest < Test::Unit::TestCase
assert_correction :yield, error.corrections
assert_match "Did you mean? yield", error.to_s
end
+
+ def test_does_not_suggest_yield
+ error = assert_raise(NoMethodError) { 1.yeild }
+
+ assert_correction [], error.corrections
+ assert_not_match(/Did you mean\? +yield/, error.to_s)
+ end if RUBY_ENGINE != "jruby"
end
diff --git a/test/did_you_mean/spell_checking/test_require_path_check.rb b/test/did_you_mean/spell_checking/test_require_path_check.rb
new file mode 100644
index 0000000000..f67fab0568
--- /dev/null
+++ b/test/did_you_mean/spell_checking/test_require_path_check.rb
@@ -0,0 +1,32 @@
+require_relative '../helper'
+
+return if !(RUBY_VERSION >= '2.8.0')
+
+class RequirePathCheckTest < Test::Unit::TestCase
+ include DidYouMean::TestHelper
+
+ def test_load_error_from_require_has_suggestions
+ error = assert_raise LoadError do
+ require 'open_struct'
+ end
+
+ assert_correction 'ostruct', error.corrections
+ assert_match "Did you mean? ostruct", error.to_s
+ end
+
+ def test_load_error_from_require_for_nested_files_has_suggestions
+ error = assert_raise LoadError do
+ require 'net/htt'
+ end
+
+ assert_correction 'net/http', error.corrections
+ assert_match "Did you mean? net/http", error.to_s
+
+ error = assert_raise LoadError do
+ require 'net-http'
+ end
+
+ assert_correction ['net/http', 'net/https'], error.corrections
+ assert_match "Did you mean? net/http", error.to_s
+ end
+end
diff --git a/test/did_you_mean/test_tree_spell_checker.rb b/test/did_you_mean/test_tree_spell_checker.rb
index b61a491e20..9ab1c1bc9e 100644
--- a/test/did_you_mean/test_tree_spell_checker.rb
+++ b/test/did_you_mean/test_tree_spell_checker.rb
@@ -1,11 +1,12 @@
-require 'set'
-require 'yaml'
+# frozen_string_literal: true
-require_relative './helper'
+require "yaml"
+
+require_relative "./helper"
class TreeSpellCheckerTest < Test::Unit::TestCase
- MINI_DIRECTORIES = YAML.load_file(File.expand_path('fixtures/mini_dir.yml', __dir__))
- RSPEC_DIRECTORIES = YAML.load_file(File.expand_path('fixtures/rspec_dir.yml', __dir__))
+ MINI_DIRECTORIES = YAML.load_file(File.expand_path("fixtures/mini_dir.yml", __dir__))
+ RSPEC_DIRECTORIES = YAML.load_file(File.expand_path("fixtures/rspec_dir.yml", __dir__))
def setup
@dictionary =
@@ -20,154 +21,150 @@ class TreeSpellCheckerTest < Test::Unit::TestCase
spec/models/gfsga_spec.rb
spec/controllers/vixen_controller_spec.rb
)
- @test_str = 'spek/modeks/confirns/viken_spec.rb'
- @tsp = DidYouMean::TreeSpellChecker.new(dictionary: @dictionary)
+ @test_str = "spek/modeks/confirns/viken_spec.rb"
+ @tree_spell_checker = DidYouMean::TreeSpellChecker.new(dictionary: @dictionary)
end
def test_corrupt_root
- word = 'test/verbose_formatter_test.rb'
- word_error = 'btets/cverbose_formatter_etst.rb suggestions'
- tsp = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES)
- s = tsp.correct(word_error).first
- assert_match s, word
+ assert_tree_spell "test/verbose_formatter_test.rb",
+ input: "btets/cverbose_formatter_etst.rb suggestions",
+ dictionary: MINI_DIRECTORIES
end
def test_leafless_state
- tsp = DidYouMean::TreeSpellChecker.new(dictionary: @dictionary.push('spec/features'))
- word = 'spec/modals/confirms/efgh_spec.rb'
- word_error = 'spec/modals/confirXX/efgh_spec.rb'
- s = tsp.correct(word_error).first
- assert_equal s, word
- s = tsp.correct('spec/featuresXX')
- assert_equal 'spec/features', s.first
+ assert_tree_spell "spec/modals/confirms/efgh_spec.rb",
+ input: "spec/modals/confirXX/efgh_spec.rb",
+ dictionary: [*@dictionary, "spec/features"]
+
+ assert_tree_spell "spec/features",
+ input: "spec/featuresXX",
+ dictionary: [*@dictionary, "spec/features"]
end
def test_rake_dictionary
- dict = %w(parallel:prepare parallel:create parallel:rake parallel:migrate)
- word_error = 'parallel:preprare'
- tsp = DidYouMean::TreeSpellChecker.new(dictionary: dict, separator: ':')
- s = tsp.correct(word_error).first
- assert_match s, 'parallel:prepare'
+ assert_tree_spell "parallel:prepare",
+ input: "parallel:preprare",
+ dictionary: %w[parallel:prepare parallel:create parallel:rake parallel:migrate],
+ separator: ":"
end
def test_special_words_mini
- tsp = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES)
- special_words_mini.each do |word, word_error|
- s = tsp.correct(word_error).first
- assert_match s, word
+ [
+ %w(test/fixtures/book.rb test/fixture/book.rb),
+ %w(test/edit_distance/jaro_winkler_test.rb test/edit_distace/jaro_winkler_test.rb),
+ %w(test/edit_distance/jaro_winkler_test.rb teste/dit_distane/jaro_winkler_test.rb),
+ %w(test/fixtures/book.rb test/fixturWes/book.rb),
+ %w(test/test_helper.rb tes!t/test_helper.rb),
+ %w(test/fixtures/book.rb test/hfixtures/book.rb),
+ %w(test/edit_distance/jaro_winkler_test.rb test/eidt_distance/jaro_winkler_test.@rb),
+ %w(test/spell_checker_test.rb test/spell_checke@r_test.rb),
+ %w(test/tree_spell_human_typo_test.rb testt/ree_spell_human_typo_test.rb),
+ %w(test/edit_distance/jaro_winkler_test.rb test/edit_distance/jaro_winkler_tuest.rb),
+ ].each do |expected, user_input|
+ assert_tree_spell expected, input: user_input, dictionary: MINI_DIRECTORIES
end
- end
- def test_special_words_rspec
- tsp = DidYouMean::TreeSpellChecker.new(dictionary: RSPEC_DIRECTORIES)
- special_words_rspec.each do |word, word_error|
- s = tsp.correct(word_error)
- assert_match s.first, word
- end
- end
-
- def special_words_rspec
[
- ['spec/rspec/core/formatters/exception_presenter_spec.rb','spec/rspec/core/formatters/eception_presenter_spec.rb'],
- ['spec/rspec/core/ordering_spec.rb', 'spec/spec/core/odrering_spec.rb'],
- ['spec/rspec/core/metadata_spec.rb', 'spec/rspec/core/metadata_spe.crb'],
- ['spec/support/mathn_integration_support.rb', 'spec/support/mathn_itegrtion_support.rb']
- ]
+ %w(test/spell_checking/variable_name_check_test.rb test/spell_checking/vriabl_ename_check_test.rb),
+ %w(test/spell_checking/key_name_check_test.rb tesit/spell_checking/key_name_choeck_test.rb),
+ ].each do |expected, user_input|
+ assert_equal expected, DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct(user_input)[0]
+ end
end
- def special_words_mini
+ def test_special_words_rspec
[
- ['test/fixtures/book.rb', 'test/fixture/book.rb'],
- ['test/fixtures/book.rb', 'test/fixture/book.rb'],
- ['test/edit_distance/jaro_winkler_test.rb', 'test/edit_distace/jaro_winkler_test.rb'],
- ['test/edit_distance/jaro_winkler_test.rb', 'teste/dit_distane/jaro_winkler_test.rb'],
- ['test/fixtures/book.rb', 'test/fixturWes/book.rb'],
- ['test/test_helper.rb', 'tes!t/test_helper.rb'],
- ['test/fixtures/book.rb', 'test/hfixtures/book.rb'],
- ['test/edit_distance/jaro_winkler_test.rb', 'test/eidt_distance/jaro_winkler_test.@rb'],
- ['test/spell_checker_test.rb', 'test/spell_checke@r_test.rb'],
- ['test/tree_spell_human_typo_test.rb', 'testt/ree_spell_human_typo_test.rb'],
- ['test/spell_checking/variable_name_check_test.rb', 'test/spell_checking/vriabl_ename_check_test.rb'],
- ['test/spell_checking/key_name_check_test.rb', 'tesit/spell_checking/key_name_choeck_test.rb'],
- ['test/edit_distance/jaro_winkler_test.rb', 'test/edit_distance/jaro_winkler_tuest.rb']
- ]
+ %w(spec/rspec/core/formatters/exception_presenter_spec.rb spec/rspec/core/formatters/eception_presenter_spec.rb),
+ %w(spec/rspec/core/metadata_spec.rb spec/rspec/core/metadata_spe.crb),
+ %w(spec/rspec/core/ordering_spec.rb spec/spec/core/odrering_spec.rb),
+ %w(spec/support/mathn_integration_support.rb spec/support/mathn_itegrtion_support.rb),
+ ].each do |expected, user_input|
+ assert_tree_spell expected, input: user_input, dictionary: RSPEC_DIRECTORIES
+ end
end
def test_file_in_root
- word = 'test/spell_checker_test.rb'
- word_error = 'test/spell_checker_test.r'
- suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct word_error
- assert_equal word, suggestions.first
+ assert_tree_spell "test/spell_checker_test.rb", input: "test/spell_checker_test.r", dictionary: MINI_DIRECTORIES
end
def test_no_plausible_states
- word_error = 'testspell_checker_test.rb'
- suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct word_error
- assert_equal [], suggestions
+ assert_tree_spell [], input: "testspell_checker_test.rb", dictionary: MINI_DIRECTORIES
end
def test_no_plausible_states_with_augmentation
- word_error = 'testspell_checker_test.rb'
- suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct word_error
- assert_equal [], suggestions
- suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES, augment: true).correct word_error
- assert_equal 'test/spell_checker_test.rb', suggestions.first
+ assert_tree_spell [], input: "testspell_checker_test.rb", dictionary: MINI_DIRECTORIES
+
+ suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES, augment: true).correct("testspell_checker_test.rb")
+
+ assert_equal suggestions.first, "test/spell_checker_test.rb"
end
def test_no_idea_with_augmentation
- word_error = 'test/spell_checking/key_name.rb'
- suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES).correct word_error
- assert_equal [], suggestions
- suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES, augment: true).correct word_error
- assert_equal 'test/spell_checking/key_name_check_test.rb', suggestions.first
+ assert_tree_spell [], input: "test/spell_checking/key_name.rb", dictionary: MINI_DIRECTORIES
+
+ suggestions = DidYouMean::TreeSpellChecker.new(dictionary: MINI_DIRECTORIES, augment: true).correct("test/spell_checking/key_name.rb")
+
+ assert_equal suggestions.first, "test/spell_checking/key_name_check_test.rb"
end
def test_works_out_suggestions
- exp = ['spec/models/concerns/vixen_spec.rb',
- 'spec/models/concerns/vixenus_spec.rb']
- suggestions = @tsp.correct(@test_str)
- assert_equal suggestions.to_set, exp.to_set
+ assert_tree_spell %w(spec/models/concerns/vixen_spec.rb spec/models/concerns/vixenus_spec.rb),
+ input: "spek/modeks/confirns/viken_spec.rb",
+ dictionary: %w(spec/models/concerns/vixen_spec.rb spec/models/concerns/vixenus_spec.rb)
end
def test_works_when_input_is_correct
- correct_input = 'spec/models/concerns/vixenus_spec.rb'
- suggestions = @tsp.correct correct_input
- assert_equal suggestions.first, correct_input
+ assert_tree_spell "spec/models/concerns/vixenus_spec.rb",
+ input: "spec/models/concerns/vixenus_spec.rb",
+ dictionary: @dictionary
end
def test_find_out_leaves_in_a_path
- path = 'spec/modals/confirms'
- names = @tsp.send(:find_leaves, path)
- assert_equal names.to_set, %w(abcd_spec.rb efgh_spec.rb).to_set
+ names = @tree_spell_checker.find_leaves("spec/modals/confirms")
+
+ assert_equal %w[abcd_spec.rb efgh_spec.rb], names
end
def test_works_out_nodes
- exp_paths = ['spec/models/concerns',
- 'spec/models/confirms',
- 'spec/modals/concerns',
- 'spec/modals/confirms',
- 'spec/controllers/concerns',
- 'spec/controllers/confirms'].to_set
- states = @tsp.send(:parse_dimensions)
- nodes = states[0].product(*states[1..-1])
- paths = @tsp.send(:possible_paths, nodes)
- assert_equal paths.to_set, exp_paths.to_set
+ exp_paths = ["spec/models/concerns",
+ "spec/models/confirms",
+ "spec/modals/concerns",
+ "spec/modals/confirms",
+ "spec/controllers/concerns",
+ "spec/controllers/confirms"]
+
+ states = @tree_spell_checker.dimensions
+ nodes = states[0].product(*states[1..-1])
+ paths = @tree_spell_checker.possible_paths(nodes)
+
+ assert_equal paths, exp_paths
end
def test_works_out_state_space
- suggestions = @tsp.send(:plausible_dimensions, @test_str)
- assert_equal suggestions, [["spec"], ["models", "modals"], ["confirms", "concerns"]]
+ suggestions = @tree_spell_checker.plausible_dimensions(@test_str)
+
+ assert_equal [["spec"], %w[models modals], %w[confirms concerns]], suggestions
end
def test_parses_dictionary
- states = @tsp.send(:parse_dimensions)
- assert_equal states, [["spec"], ["models", "modals", "controllers"], ["concerns", "confirms"]]
+ states = @tree_spell_checker.dimensions
+
+ assert_equal [["spec"], %w[models modals controllers], %w[concerns confirms]], states
end
def test_parses_elementary_dictionary
- dictionary = ['spec/models/user_spec.rb', 'spec/services/account_spec.rb']
- tsp = DidYouMean::TreeSpellChecker.new(dictionary: dictionary)
- states = tsp.send(:parse_dimensions)
- assert_equal states, [['spec'], ['models', 'services']]
+ dimensions = DidYouMean::TreeSpellChecker
+ .new(dictionary: %w(spec/models/user_spec.rb spec/services/account_spec.rb))
+ .dimensions
+
+ assert_equal [["spec"], %w[models services]], dimensions
+ end
+
+ private
+
+ def assert_tree_spell(expected, input:, dictionary:, separator: "/")
+ suggestions = DidYouMean::TreeSpellChecker.new(dictionary: dictionary, separator: separator).correct(input)
+
+ assert_equal Array(expected), suggestions, "Expected to suggest #{expected}, but got #{suggestions.inspect}"
end
end
diff --git a/test/did_you_mean/test_verbose_formatter.rb b/test/did_you_mean/test_verbose_formatter.rb
index 6639d60a4a..d8f2f46273 100644
--- a/test/did_you_mean/test_verbose_formatter.rb
+++ b/test/did_you_mean/test_verbose_formatter.rb
@@ -3,6 +3,8 @@ require_relative './helper'
class VerboseFormatterTest < Test::Unit::TestCase
def setup
require_relative File.join(DidYouMean::TestHelper.root, 'verbose')
+
+ DidYouMean.formatter = DidYouMean::VerboseFormatter.new
end
def teardown
diff --git a/test/did_you_mean/tree_spell/human_typo.rb b/test/did_you_mean/tree_spell/human_typo.rb
index 302d4d6902..9d410a17c4 100644
--- a/test/did_you_mean/tree_spell/human_typo.rb
+++ b/test/did_you_mean/tree_spell/human_typo.rb
@@ -4,6 +4,9 @@ module TreeSpell
# Simulate an error prone human typist
# see doc/human_typo_api.md for the api description
class HumanTypo
+ POPULAR_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ?<>,.!`+=-_":;@#$%^&*()'.split("").freeze
+ ACTION_TYPES = %i(insert transpose delete substitute).freeze
+
def initialize(input, lambda: 0.05)
@input = input
check_input
@@ -15,7 +18,7 @@ module TreeSpell
@word = input.dup
i_place = initialize_i_place
loop do
- action = action_type
+ action = ACTION_TYPES.sample
@word = make_change action, i_place
@len = word.length
i_place += exponential
@@ -41,40 +44,17 @@ module TreeSpell
(rand / (lambda / 2)).to_i
end
- def rand_char
- popular_chars = alphabetic_characters + special_characters
- n = popular_chars.length
- popular_chars[rand(n)]
- end
-
- def alphabetic_characters
- ('a'..'z').to_a.join + ('A'..'Z').to_a.join
- end
-
- def special_characters
- '?<>,.!`+=-_":;@#$%^&*()'
- end
-
- def toss
- return +1 if rand >= 0.5
- -1
- end
-
- def action_type
- [:insert, :transpose, :delete, :substitute][rand(4)]
- end
-
def make_change(action, i_place)
cw = ChangeWord.new(word)
case action
when :delete
cw.deletion(i_place)
when :insert
- cw.insertion(i_place, rand_char)
+ cw.insertion(i_place, POPULAR_CHARS.sample)
when :substitute
- cw.substitution(i_place, rand_char)
+ cw.substitution(i_place, POPULAR_CHARS.sample)
when :transpose
- cw.transposition(i_place, toss)
+ cw.transposition(i_place, rand >= 0.5 ? +1 : -1)
end
end
diff --git a/test/digest/test_digest.rb b/test/digest/test_digest.rb
index 4cae455076..c9b2c68051 100644
--- a/test/digest/test_digest.rb
+++ b/test/digest/test_digest.rb
@@ -247,10 +247,10 @@ module TestDigest
end
def test_race
- assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-'end;')
+ assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-"end;")
assert_nothing_raised {
t = Thread.start {
- sleep 0.1
+ sleep #{ EnvUtil.apply_timeout_scale(0.1) }
Digest(:Foo).new
}
Digest(:Foo).new
@@ -260,10 +260,10 @@ module TestDigest
end
def test_race_mixed
- assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-'end;')
+ assert_separately(['-rdigest', "-I#{File.dirname(__FILE__)}"], <<-"end;")
assert_nothing_raised {
t = Thread.start {
- sleep 0.1
+ sleep #{ EnvUtil.apply_timeout_scale(0.1) }
Thread.current.report_on_exception = false
Digest::Foo.new
}
diff --git a/test/digest/test_ractor.rb b/test/digest/test_ractor.rb
new file mode 100644
index 0000000000..9929f69543
--- /dev/null
+++ b/test/digest/test_ractor.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+require 'digest'
+%w[digest/md5 digest/rmd160 digest/sha1 digest/sha2 digest/bubblebabble].each do |lib|
+ begin
+ require lib
+ rescue LoadError
+ end
+end
+
+module TestDigestRactor
+ Data1 = "abc"
+ Data2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+
+ def setup
+ skip unless defined?(Ractor)
+ end
+
+ def test_s_hexdigest
+ assert_in_out_err([], <<-"end;", ["true", "true"], [])
+ $VERBOSE = nil
+ require "digest"
+ require "#{self.class::LIB}"
+ DATA = #{self.class::DATA.inspect}
+ rs = DATA.map do |str, hexdigest|
+ r = Ractor.new str do |x|
+ #{self.class::ALGO}.hexdigest(x)
+ end
+ [r, hexdigest]
+ end
+ rs.each do |r, hexdigest|
+ puts r.take == hexdigest
+ end
+ end;
+ end
+
+ class TestMD5Ractor < Test::Unit::TestCase
+ include TestDigestRactor
+ LIB = "digest/md5"
+ ALGO = Digest::MD5
+ DATA = {
+ Data1 => "900150983cd24fb0d6963f7d28e17f72",
+ Data2 => "8215ef0796a20bcaaae116d3876c664a",
+ }
+ end if defined?(Digest::MD5)
+
+ class TestSHA1Ractor < Test::Unit::TestCase
+ include TestDigestRactor
+ LIB = "digest/sha1"
+ ALGO = Digest::SHA1
+ DATA = {
+ Data1 => "a9993e364706816aba3e25717850c26c9cd0d89d",
+ Data2 => "84983e441c3bd26ebaae4aa1f95129e5e54670f1",
+ }
+ end if defined?(Digest::SHA1)
+
+ class TestSHA256Ractor < Test::Unit::TestCase
+ include TestDigestRactor
+ LIB = "digest/sha2"
+ ALGO = Digest::SHA256
+ DATA = {
+ Data1 => "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
+ Data2 => "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
+ }
+ end if defined?(Digest::SHA256)
+
+ class TestSHA384Ractor < Test::Unit::TestCase
+ include TestDigestRactor
+ LIB = "digest/sha2"
+ ALGO = Digest::SHA384
+ DATA = {
+ Data1 => "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"\
+ "8086072ba1e7cc2358baeca134c825a7",
+ Data2 => "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6"\
+ "b0455a8520bc4e6f5fe95b1fe3c8452b",
+ }
+ end if defined?(Digest::SHA384)
+
+ class TestSHA512Ractor < Test::Unit::TestCase
+ include TestDigestRactor
+ LIB = "digest/sha2"
+ ALGO = Digest::SHA512
+ DATA = {
+ Data1 => "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"\
+ "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
+ Data2 => "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c335"\
+ "96fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445",
+ }
+ end if defined?(Digest::SHA512)
+
+ class TestRMD160Ractor < Test::Unit::TestCase
+ include TestDigestRactor
+ LIB = "digest/rmd160"
+ ALGO = Digest::RMD160
+ DATA = {
+ Data1 => "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
+ Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
+ }
+ end if defined?(Digest::RMD160)
+end
diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb
index a8363b0c43..16ffec904b 100644
--- a/test/drb/drbtest.rb
+++ b/test/drb/drbtest.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: false
require 'test/unit'
+require 'envutil'
require 'drb/drb'
require 'drb/extservm'
require 'timeout'
@@ -215,6 +216,7 @@ module DRbCore
def test_06_timeout
skip if RUBY_PLATFORM.include?("armv7l-linux")
skip if RUBY_PLATFORM.include?("sparc-solaris2.10")
+ skip if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # expecting a certain delay is difficult for --jit-wait CI
Timeout.timeout(60) do
ten = Onecky.new(10)
assert_raise(Timeout::Error) do
diff --git a/test/drb/test_drbssl.rb b/test/drb/test_drbssl.rb
index 58606119f3..0254c7ab50 100644
--- a/test/drb/test_drbssl.rb
+++ b/test/drb/test_drbssl.rb
@@ -59,6 +59,7 @@ end
class TestDRbSSLAry < Test::Unit::TestCase
include DRbAry
def setup
+ LeakChecker.skip if defined?(LeakChecker)
@drb_service = DRbSSLService.new
super
setup_service 'ut_array_drbssl.rb'
diff --git a/test/drb/ut_drb.rb b/test/drb/ut_drb.rb
index e7bd2dff73..7c0603b009 100644
--- a/test/drb/ut_drb.rb
+++ b/test/drb/ut_drb.rb
@@ -69,7 +69,7 @@ class DRbEx
private def priv; 3; end
end
def basic_object
- BO.new
+ @basic_object = BO.new
end
def unknown_class
diff --git a/test/erb/test_erb_command.rb b/test/erb/test_erb_command.rb
index ed13c29c96..93e3522edb 100644
--- a/test/erb/test_erb_command.rb
+++ b/test/erb/test_erb_command.rb
@@ -5,14 +5,14 @@ require 'test/unit'
class TestErbCommand < Test::Unit::TestCase
def test_var
assert_in_out_err(["-w",
- File.expand_path("../../../bin/erb", __FILE__),
+ File.expand_path("../../../libexec/erb", __FILE__),
"var=hoge"],
"<%=var%>", ["hoge"])
end
def test_template_file_encoding
assert_in_out_err(["-w",
- File.expand_path("../../../bin/erb", __FILE__)],
+ File.expand_path("../../../libexec/erb", __FILE__)],
"<%=''.encoding.to_s%>", ["UTF-8"])
end
@@ -20,10 +20,10 @@ class TestErbCommand < Test::Unit::TestCase
def test_deprecated_option
warnings = [
"warning: -S option of erb command is deprecated. Please do not use this.",
- /\n.+\/bin\/erb:\d+: warning: Passing safe_level with the 2nd argument of ERB\.new is deprecated\. Do not use it, and specify other arguments as keyword arguments\.\n/,
+ /\n.+\/libexec\/erb:\d+: warning: Passing safe_level with the 2nd argument of ERB\.new is deprecated\. Do not use it, and specify other arguments as keyword arguments\.\n/,
]
assert_in_out_err(["-w",
- File.expand_path("../../../bin/erb", __FILE__),
+ File.expand_path("../../../libexec/erb", __FILE__),
"-S", "0"],
"hoge", ["hoge"], warnings)
end
diff --git a/test/etc/test_etc.rb b/test/etc/test_etc.rb
index 365c27021c..2eddcf49d7 100644
--- a/test/etc/test_etc.rb
+++ b/test/etc/test_etc.rb
@@ -44,7 +44,7 @@ class TestEtc < Test::Unit::TestCase
unless s.empty?
assert_include(s, Etc.getpwuid)
end
- end
+ end unless RUBY_PLATFORM.include?("android")
def test_getpwnam
passwd = {}
@@ -54,7 +54,7 @@ class TestEtc < Test::Unit::TestCase
passwd.each_value do |s|
assert_equal(s, Etc.getpwnam(s.name))
end
- end
+ end unless RUBY_PLATFORM.include?("android")
def test_passwd_with_low_level_api
a = []
@@ -169,4 +169,28 @@ class TestEtc < Test::Unit::TestCase
assert_operator(1, :<=, n)
end
+ def test_ractor
+ return unless Etc.passwd # => skip test if no platform support
+ Etc.endpwent
+
+ assert_ractor(<<~RUBY, require: 'etc')
+ ractor = Ractor.new do
+ Etc.passwd do |s|
+ Ractor.yield :sync
+ Ractor.yield s.name
+ break :done
+ end
+ end
+ ractor.take # => :sync
+ assert_raise RuntimeError, /parallel/ do
+ Etc.passwd {}
+ end
+ name = ractor.take # => first name
+ ractor.take # => :done
+ name2 = Etc.passwd do |s|
+ break s.name
+ end
+ assert_equal(name2, name)
+ RUBY
+ end
end
diff --git a/test/fiber/http.rb b/test/fiber/http.rb
new file mode 100644
index 0000000000..ad51ae3c76
--- /dev/null
+++ b/test/fiber/http.rb
@@ -0,0 +1,53 @@
+
+require 'benchmark'
+
+TOPICS = ["cats", "dogs", "pigs", "skeletons", "zombies", "ocelots", "villagers", "pillagers"]
+
+require 'net/http'
+require 'uri'
+require 'json'
+
+require_relative 'scheduler'
+
+def fetch_topics(topics)
+ responses = {}
+
+ topics.each do |topic|
+ Fiber.new(blocking: Fiber.current.blocking?) do
+ uri = URI("https://www.google.com/search?q=#{topic}")
+ responses[topic] = Net::HTTP.get(uri).scan(topic).size
+ end.resume
+ end
+
+ Thread.fiber_scheduler&.run
+
+ return responses
+end
+
+def sweep(repeats: 3, **options)
+ times = (1..8).map do |i|
+ $stderr.puts "Measuring #{i} topic(s)..."
+ topics = TOPICS[0...i]
+
+ Thread.new do
+ Benchmark.realtime do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ repeats.times do
+ Fiber.new(**options) do
+ pp fetch_topics(topics)
+ end.resume
+
+ scheduler.run
+ end
+ end
+ end.value / repeats
+ end
+
+ puts options.inspect
+ puts JSON.dump(times.map{|value| value.round(3)})
+end
+
+sweep(blocking: true)
+sweep(blocking: false)
diff --git a/test/fiber/scheduler.rb b/test/fiber/scheduler.rb
new file mode 100644
index 0000000000..df82c2ff93
--- /dev/null
+++ b/test/fiber/scheduler.rb
@@ -0,0 +1,210 @@
+# frozen_string_literal: true
+
+# This is an example and simplified scheduler for test purposes.
+# It is not efficient for a large number of file descriptors as it uses IO.select().
+# Production Fiber schedulers should use epoll/kqueue/etc.
+
+require 'fiber'
+require 'socket'
+
+begin
+ require 'io/nonblock'
+rescue LoadError
+ # Ignore.
+end
+
+class Scheduler
+ def initialize
+ @readable = {}
+ @writable = {}
+ @waiting = {}
+
+ @closed = false
+
+ @lock = Mutex.new
+ @blocking = 0
+ @ready = []
+
+ @urgent = IO.pipe
+ end
+
+ attr :readable
+ attr :writable
+ attr :waiting
+
+ def next_timeout
+ _fiber, timeout = @waiting.min_by{|key, value| value}
+
+ if timeout
+ offset = timeout - current_time
+
+ if offset < 0
+ return 0
+ else
+ return offset
+ end
+ end
+ end
+
+ def run
+ while @readable.any? or @writable.any? or @waiting.any? or @blocking.positive?
+ # Can only handle file descriptors up to 1024...
+ readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], next_timeout)
+
+ # puts "readable: #{readable}" if readable&.any?
+ # puts "writable: #{writable}" if writable&.any?
+
+ readable&.each do |io|
+ if fiber = @readable.delete(io)
+ fiber.resume
+ elsif io == @urgent.first
+ @urgent.first.read_nonblock(1024)
+ end
+ end
+
+ writable&.each do |io|
+ if fiber = @writable.delete(io)
+ fiber.resume
+ end
+ end
+
+ if @waiting.any?
+ time = current_time
+ waiting, @waiting = @waiting, {}
+
+ waiting.each do |fiber, timeout|
+ if timeout <= time
+ fiber.resume
+ else
+ @waiting[fiber] = timeout
+ end
+ end
+ end
+
+ if @ready.any?
+ ready = nil
+
+ @lock.synchronize do
+ ready, @ready = @ready, []
+ end
+
+ ready.each do |fiber|
+ fiber.resume
+ end
+ end
+ end
+ end
+
+ def close
+ raise "Scheduler already closed!" if @closed
+
+ self.run
+ ensure
+ if @urgent
+ @urgent.each(&:close)
+ @urgent = nil
+ end
+
+ @closed = true
+
+ # We freeze to detect any unintended modifications after the scheduler is closed:
+ self.freeze
+ end
+
+ def closed?
+ @closed
+ end
+
+ def current_time
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ end
+
+ def process_wait(pid, flags)
+ # This is a very simple way to implement a non-blocking wait:
+ Thread.new do
+ Process::Status.wait(pid, flags)
+ end.value
+ end
+
+ def io_wait(io, events, duration)
+ unless (events & IO::READABLE).zero?
+ @readable[io] = Fiber.current
+ end
+
+ unless (events & IO::WRITABLE).zero?
+ @writable[io] = Fiber.current
+ end
+
+ Fiber.yield
+
+ return true
+ end
+
+ # Used for Kernel#sleep and Mutex#sleep
+ def kernel_sleep(duration = nil)
+ self.block(:sleep, duration)
+
+ return true
+ end
+
+ # Used when blocking on synchronization (Mutex#lock, Queue#pop, SizedQueue#push, ...)
+ def block(blocker, timeout = nil)
+ # $stderr.puts [__method__, blocker, timeout].inspect
+
+ if timeout
+ @waiting[Fiber.current] = current_time + timeout
+ begin
+ Fiber.yield
+ ensure
+ # Remove from @waiting in the case #unblock was called before the timeout expired:
+ @waiting.delete(Fiber.current)
+ end
+ else
+ @blocking += 1
+ begin
+ Fiber.yield
+ ensure
+ @blocking -= 1
+ end
+ end
+ end
+
+ # Used when synchronization wakes up a previously-blocked fiber (Mutex#unlock, Queue#push, ...).
+ # This might be called from another thread.
+ def unblock(blocker, fiber)
+ # $stderr.puts [__method__, blocker, fiber].inspect
+
+ @lock.synchronize do
+ @ready << fiber
+ end
+
+ io = @urgent.last
+ io.write_nonblock('.')
+ end
+
+ def fiber(&block)
+ fiber = Fiber.new(blocking: false, &block)
+
+ fiber.resume
+
+ return fiber
+ end
+end
+
+class BrokenUnblockScheduler < Scheduler
+ def unblock(blocker, fiber)
+ super
+
+ raise "Broken unblock!"
+ end
+end
+
+class SleepingUnblockScheduler < Scheduler
+ # This method is invoked when the thread is exiting.
+ def unblock(blocker, fiber)
+ super
+
+ # This changes the current thread state to `THREAD_RUNNING` which causes `thread_join_sleep` to hang.
+ sleep(0.1)
+ end
+end
diff --git a/test/fiber/test_backtrace.rb b/test/fiber/test_backtrace.rb
new file mode 100644
index 0000000000..ba05ca2983
--- /dev/null
+++ b/test/fiber/test_backtrace.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+require 'test/unit'
+require 'fiber'
+
+class TestFiberBacktrace < Test::Unit::TestCase
+ def test_backtrace
+ backtrace = Fiber.current.backtrace
+ assert_kind_of Array, backtrace
+ assert_match(/test_backtrace/, backtrace[0])
+ end
+
+ def test_backtrace_locations
+ backtrace = Fiber.current.backtrace_locations
+ assert_kind_of Array, backtrace
+ assert_match(/test_backtrace_locations/, backtrace[1].label)
+ end
+
+ def test_local_backtrace
+ backtrace = Fiber.current.backtrace(2)
+ assert_equal backtrace, caller
+ end
+end
diff --git a/test/fiber/test_enumerator.rb b/test/fiber/test_enumerator.rb
new file mode 100644
index 0000000000..cd4ccd1de5
--- /dev/null
+++ b/test/fiber/test_enumerator.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+class TestFiberEnumerator < Test::Unit::TestCase
+ MESSAGE = "Hello World"
+
+ def test_read_characters
+ skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+
+ unless i.nonblock? && o.nonblock?
+ i.close
+ o.close
+ skip "I/O is not non-blocking!"
+ end
+
+ message = String.new
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ e = i.to_enum(:each_char)
+
+ Fiber.schedule do
+ o.write("Hello World")
+ o.close
+ end
+
+ Fiber.schedule do
+ begin
+ while c = e.next
+ message << c
+ end
+ rescue StopIteration
+ # Ignore.
+ end
+
+ i.close
+ end
+ end
+
+ thread.join
+
+ assert_equal(MESSAGE, message)
+ assert_predicate(i, :closed?)
+ assert_predicate(o, :closed?)
+ end
+end
diff --git a/test/fiber/test_io.rb b/test/fiber/test_io.rb
new file mode 100644
index 0000000000..fafda7c310
--- /dev/null
+++ b/test/fiber/test_io.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+class TestFiberIO < Test::Unit::TestCase
+ MESSAGE = "Hello World"
+
+ def test_read
+ skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+
+ unless i.nonblock? && o.nonblock?
+ i.close
+ o.close
+ skip "I/O is not non-blocking!"
+ end
+
+ message = nil
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ message = i.read(20)
+ i.close
+ end
+
+ Fiber.schedule do
+ o.write("Hello World")
+ o.close
+ end
+ end
+
+ thread.join
+
+ assert_equal MESSAGE, message
+ assert_predicate(i, :closed?)
+ assert_predicate(o, :closed?)
+ end
+
+ def test_heavy_read
+ skip unless defined?(UNIXSocket)
+
+ 16.times.map do
+ Thread.new do
+ i, o = UNIXSocket.pair
+
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ i.read(20)
+ i.close
+ end
+
+ Fiber.schedule do
+ o.write("Hello World")
+ o.close
+ end
+ end
+ end.each(&:join)
+ end
+
+ def test_epipe_on_read
+ skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+
+ unless i.nonblock? && o.nonblock?
+ i.close
+ o.close
+ skip "I/O is not non-blocking!"
+ end
+
+ error = nil
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ begin
+ i.close
+ o.write(MESSAGE)
+ rescue => error
+ # Saved into error.
+ end
+ end
+ end
+
+ thread.join
+
+ i.close
+ o.close
+
+ assert_kind_of Errno::EPIPE, error
+ end
+end
diff --git a/test/fiber/test_mutex.rb b/test/fiber/test_mutex.rb
new file mode 100644
index 0000000000..0842427760
--- /dev/null
+++ b/test/fiber/test_mutex.rb
@@ -0,0 +1,220 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+class TestFiberMutex < Test::Unit::TestCase
+ def test_mutex_synchronize
+ mutex = Mutex.new
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ assert_not_predicate Fiber, :blocking?
+
+ mutex.synchronize do
+ assert_not_predicate Fiber, :blocking?
+ end
+ end
+ end
+
+ thread.join
+ end
+
+ def test_mutex_interleaved_locking
+ mutex = Mutex.new
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ mutex.lock
+ sleep 0.1
+ mutex.unlock
+ end
+
+ Fiber.schedule do
+ mutex.lock
+ sleep 0.1
+ mutex.unlock
+ end
+
+ scheduler.run
+ end
+
+ thread.join
+ end
+
+ def test_mutex_thread
+ mutex = Mutex.new
+ mutex.lock
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ mutex.lock
+ sleep 0.1
+ mutex.unlock
+ end
+
+ scheduler.run
+ end
+
+ sleep 0.1
+ mutex.unlock
+
+ thread.join
+ end
+
+ def test_mutex_fiber_raise
+ mutex = Mutex.new
+ ran = false
+
+ main = Thread.new do
+ mutex.lock
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ f = Fiber.schedule do
+ assert_raise_with_message(RuntimeError, "bye") do
+ mutex.lock
+ end
+
+ ran = true
+ end
+
+ Fiber.schedule do
+ f.raise "bye"
+ end
+ end
+
+ thread.join
+ end
+
+ main.join # causes mutex to be released
+ assert_equal false, mutex.locked?
+ assert_equal true, ran
+ end
+
+ def test_condition_variable
+ mutex = Mutex.new
+ condition = ConditionVariable.new
+
+ signalled = 0
+
+ Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ mutex.synchronize do
+ 3.times do
+ condition.wait(mutex)
+ signalled += 1
+ end
+ end
+ end
+
+ Fiber.schedule do
+ 3.times do
+ mutex.synchronize do
+ condition.signal
+ end
+
+ sleep 0.1
+ end
+ end
+
+ scheduler.run
+ end.join
+
+ assert_equal 3, signalled
+ end
+
+ def test_queue
+ queue = Queue.new
+ processed = 0
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ 3.times do |i|
+ queue << i
+ sleep 0.1
+ end
+
+ queue.close
+ end
+
+ Fiber.schedule do
+ while item = queue.pop
+ processed += 1
+ end
+ end
+
+ scheduler.run
+ end
+
+ thread.join
+
+ assert_equal 3, processed
+ end
+
+ def test_queue_pop_waits
+ queue = Queue.new
+ running = false
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ result = nil
+ Fiber.schedule do
+ result = queue.pop
+ end
+
+ running = true
+ scheduler.run
+ result
+ end
+
+ Thread.pass until running
+ sleep 0.1
+
+ queue << :done
+ assert_equal :done, thread.value
+ end
+
+ def test_mutex_deadlock
+ error_pattern = /No live threads left. Deadlock\?/
+
+ assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['in synchronize'], error_pattern, success: false
+ require 'scheduler'
+ mutex = Mutex.new
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ mutex.synchronize do
+ puts 'in synchronize'
+ Fiber.yield
+ end
+ end
+
+ mutex.lock
+ end
+
+ thread.join
+ RUBY
+ end
+end
diff --git a/test/fiber/test_process.rb b/test/fiber/test_process.rb
new file mode 100644
index 0000000000..a5990be204
--- /dev/null
+++ b/test/fiber/test_process.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+class TestFiberProcess < Test::Unit::TestCase
+ def test_process_wait
+ Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ pid = Process.spawn("true")
+ Process.wait(pid)
+
+ # TODO test that scheduler was invoked.
+
+ assert_predicate $?, :success?
+ end
+ end.join
+ end
+
+ def test_system
+ Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ system("true")
+
+ # TODO test that scheduler was invoked (currently it's not).
+
+ assert_predicate $?, :success?
+ end
+ end.join
+ end
+
+ def test_fork
+ omit 'fork not supported' unless Process.respond_to?(:fork)
+ Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ pid = Process.fork {}
+ Process.wait(pid)
+
+ assert_predicate $?, :success?
+ end
+ end.join
+ end
+end
diff --git a/test/fiber/test_ractor.rb b/test/fiber/test_ractor.rb
new file mode 100644
index 0000000000..d03455a9f7
--- /dev/null
+++ b/test/fiber/test_ractor.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+require "test/unit"
+require "fiber"
+
+class TestFiberCurrentRactor < Test::Unit::TestCase
+ def setup
+ skip unless defined? Ractor
+ end
+
+ def test_ractor_shareable
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ $VERBOSE = nil
+ require "fiber"
+ r = Ractor.new do
+ Fiber.new do
+ Fiber.current.class
+ end.resume
+ end
+ assert_equal(Fiber, r.take)
+ end;
+ end
+end
diff --git a/test/fiber/test_scheduler.rb b/test/fiber/test_scheduler.rb
new file mode 100644
index 0000000000..d1fb89d693
--- /dev/null
+++ b/test/fiber/test_scheduler.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+class TestFiberScheduler < Test::Unit::TestCase
+ def test_fiber_without_scheduler
+ # Cannot create fiber without scheduler.
+ assert_raise RuntimeError do
+ Fiber.schedule do
+ end
+ end
+ end
+
+ def test_fiber_new
+ f = Fiber.new{}
+ refute f.blocking?
+ end
+
+ def test_fiber_new_with_options
+ f = Fiber.new(blocking: true){}
+ assert f.blocking?
+
+ f = Fiber.new(blocking: false){}
+ refute f.blocking?
+
+ f = Fiber.new(pool: nil){}
+ refute f.blocking?
+ end
+
+ def test_closed_at_thread_exit
+ scheduler = Scheduler.new
+
+ thread = Thread.new do
+ Fiber.set_scheduler scheduler
+ end
+
+ thread.join
+
+ assert scheduler.closed?
+ end
+
+ def test_closed_when_set_to_nil
+ scheduler = Scheduler.new
+
+ thread = Thread.new do
+ Fiber.set_scheduler scheduler
+ Fiber.set_scheduler nil
+
+ assert scheduler.closed?
+ end
+
+ thread.join
+ end
+
+ def test_close_at_exit
+ assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['Running Fiber'], [], success: true
+ require 'scheduler'
+
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ sleep(0)
+ puts "Running Fiber"
+ end
+ RUBY
+ end
+
+ def test_minimal_interface
+ scheduler = Object.new
+
+ def scheduler.block
+ end
+
+ def scheduler.unblock
+ end
+
+ def scheduler.io_wait
+ end
+
+ def scheduler.kernel_sleep
+ end
+
+ thread = Thread.new do
+ Fiber.set_scheduler scheduler
+ end
+
+ thread.join
+ end
+end
diff --git a/test/fiber/test_sleep.rb b/test/fiber/test_sleep.rb
new file mode 100644
index 0000000000..a7e88c0367
--- /dev/null
+++ b/test/fiber/test_sleep.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+class TestFiberSleep < Test::Unit::TestCase
+ ITEMS = [0, 1, 2, 3, 4]
+
+ def test_sleep
+ items = []
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ 5.times do |i|
+ Fiber.schedule do
+ assert_operator sleep(i/100.0), :>=, 0
+ items << i
+ end
+ end
+
+ # Should be 5 fibers waiting:
+ assert_equal scheduler.waiting.size, 5
+ end
+
+ thread.join
+
+ assert_equal ITEMS, items
+ end
+
+ def test_sleep_returns_seconds_slept
+ seconds = nil
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+ Fiber.schedule do
+ seconds = sleep(2)
+ end
+ end
+
+ thread.join
+
+ assert_operator seconds, :>=, 2, "actual: %p" % seconds
+ end
+
+ def test_broken_sleep
+ thread = Thread.new do
+ Thread.current.report_on_exception = false
+
+ scheduler = Scheduler.new
+
+ def scheduler.kernel_sleep(duration = nil)
+ raise "Broken sleep!"
+ end
+
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ sleep 0
+ end
+
+ ensure
+ scheduler.close
+ end
+
+ assert_raise(RuntimeError) do
+ thread.join
+ end
+ end
+end
diff --git a/test/fiber/test_thread.rb b/test/fiber/test_thread.rb
new file mode 100644
index 0000000000..5c25c43de2
--- /dev/null
+++ b/test/fiber/test_thread.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+require "test/unit"
+require_relative 'scheduler'
+
+class TestFiberThread < Test::Unit::TestCase
+ def test_thread_join
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ result = nil
+ Fiber.schedule do
+ result = Thread.new{:done}.value
+ end
+
+ scheduler.run
+ result
+ end
+
+ assert_equal :done, thread.value
+ end
+
+ def test_thread_join_implicit
+ sleeping = false
+ finished = false
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ sleeping = true
+ sleep(0.1)
+ finished = true
+ end
+
+ :done
+ end
+
+ Thread.pass until sleeping
+
+ thread.join
+
+ assert_equal :done, thread.value
+ assert finished, "Scheduler thread's task should be finished!"
+ end
+
+ def test_thread_join_blocking
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ result = nil
+ Fiber.schedule do
+ Fiber.new(blocking: true) do
+ # This can deadlock if the blocking state is not taken into account:
+ Thread.new do
+ sleep(0)
+ result = :done
+ end.join
+ end.resume
+ end
+
+ scheduler.run
+ result
+ end
+
+ assert_equal :done, thread.value
+ end
+
+ def test_broken_unblock
+ thread = Thread.new do
+ Thread.current.report_on_exception = false
+
+ scheduler = BrokenUnblockScheduler.new
+
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ Thread.new{
+ Thread.current.report_on_exception = false
+ }.join
+ end
+
+ scheduler.run
+ ensure
+ scheduler.close
+ end
+
+ assert_raise(RuntimeError) do
+ thread.join
+ end
+ end
+
+ def test_thread_join_hang
+ thread = Thread.new do
+ scheduler = SleepingUnblockScheduler.new
+
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ Thread.new{sleep(0.01)}.value
+ end
+ end
+
+ thread.join
+ end
+end
diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb
index 73f6f78d6d..a6e2019924 100644
--- a/test/fiddle/helper.rb
+++ b/test/fiddle/helper.rb
@@ -17,6 +17,10 @@ when /android/
end
libc_so = File.join(libdir, "libc.so")
libm_so = File.join(libdir, "libm.so")
+when /linux-musl/
+ Dir.glob('/lib/ld-musl-*.so.1') do |ld|
+ libc_so = libm_so = ld
+ end
when /linux/
libdir = '/lib'
case RbConfig::SIZEOF['void*']
@@ -27,8 +31,8 @@ when /linux/
# In the ARM 32-bit libc package such as libc6:armhf libc6:armel,
# libc.so and libm.so are installed to /lib/arm-linux-gnu*.
# It's not installed to /lib32.
- dirs = Dir.glob('/lib/arm-linux-gnu*')
- libdir = dirs[0] if dirs && File.directory?(dirs[0])
+ dir, = Dir.glob('/lib/arm-linux-gnu*')
+ libdir = dir if dir && File.directory?(dir)
else
libdir = '/lib32' if File.directory? '/lib32'
end
@@ -36,8 +40,16 @@ when /linux/
# 64-bit ruby
libdir = '/lib64' if File.directory? '/lib64'
end
- libc_so = File.join(libdir, "libc.so.6")
- libm_so = File.join(libdir, "libm.so.6")
+
+ # Handle musl libc
+ libc_so, = Dir.glob(File.join(libdir, "libc.musl*.so*"))
+ if libc_so
+ libm_so = libc_so
+ else
+ # glibc
+ libc_so = "libc.so.6"
+ libm_so = "libm.so.6"
+ end
when /mingw/, /mswin/
require "rbconfig"
crtname = RbConfig::CONFIG["RUBY_SO_NAME"][/msvc\w+/] || 'ucrtbase'
@@ -80,9 +92,9 @@ when /aix/
funcs=%w!sin sinf strcpy strncpy!
expfile='dltest.exp'
require 'tmpdir'
- Dir.mktmpdir do |dir|
+ Dir.mktmpdir do |_dir|
begin
- Dir.chdir dir
+ Dir.chdir _dir
%x!/usr/bin/ar x /usr/lib/libc.a #{cobjs.join(' ')}!
%x!/usr/bin/ar x /usr/lib/libm.a #{mobjs.join(' ')}!
%x!echo "#{funcs.join("\n")}\n" > #{expfile}!
@@ -99,6 +111,18 @@ when /aix/
end
end
end
+when /haiku/
+ libdir = '/system/lib'
+ case [0].pack('L!').size
+ when 4
+ # 32-bit ruby
+ libdir = '/system/lib/x86' if File.directory? '/system/lib/x86'
+ when 8
+ # 64-bit ruby
+ libdir = '/system/lib/' if File.directory? '/system/lib/'
+ end
+ libc_so = File.join(libdir, "libroot.so")
+ libm_so = File.join(libdir, "libroot.so")
else
libc_so = ARGV[0] if ARGV[0] && ARGV[0][0] == ?/
libm_so = ARGV[1] if ARGV[1] && ARGV[1][0] == ?/
diff --git a/test/fiddle/test_c_struct_entry.rb b/test/fiddle/test_c_struct_entry.rb
index 8ece438f54..9fd16d7101 100644
--- a/test/fiddle/test_c_struct_entry.rb
+++ b/test/fiddle/test_c_struct_entry.rb
@@ -43,35 +43,123 @@ module Fiddle
end
def test_set_ctypes
- union = CStructEntity.malloc [TYPE_INT, TYPE_LONG]
- union.assign_names %w[int long]
+ CStructEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |struct|
+ struct.assign_names %w[int long]
- # this test is roundabout because the stored ctypes are not accessible
- union['long'] = 1
- union['int'] = 2
+ # this test is roundabout because the stored ctypes are not accessible
+ struct['long'] = 1
+ struct['int'] = 2
- assert_equal 1, union['long']
- assert_equal 2, union['int']
+ assert_equal 1, struct['long']
+ assert_equal 2, struct['int']
+ end
end
def test_aref_pointer_array
- team = CStructEntity.malloc([[TYPE_VOIDP, 2]])
- team.assign_names(["names"])
- alice = Fiddle::Pointer.malloc(6)
- alice[0, 6] = "Alice\0"
- bob = Fiddle::Pointer.malloc(4)
- bob[0, 4] = "Bob\0"
- team["names"] = [alice, bob]
- assert_equal(["Alice", "Bob"], team["names"].map(&:to_s))
+ CStructEntity.malloc([[TYPE_VOIDP, 2]], Fiddle::RUBY_FREE) do |team|
+ team.assign_names(["names"])
+ Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice|
+ alice[0, 6] = "Alice\0"
+ Fiddle::Pointer.malloc(4, Fiddle::RUBY_FREE) do |bob|
+ bob[0, 4] = "Bob\0"
+ team["names"] = [alice, bob]
+ assert_equal(["Alice", "Bob"], team["names"].map(&:to_s))
+ end
+ end
+ end
end
def test_aref_pointer
- user = CStructEntity.malloc([TYPE_VOIDP])
- user.assign_names(["name"])
- alice = Fiddle::Pointer.malloc(6)
- alice[0, 6] = "Alice\0"
- user["name"] = alice
- assert_equal("Alice", user["name"].to_s)
+ CStructEntity.malloc([TYPE_VOIDP], Fiddle::RUBY_FREE) do |user|
+ user.assign_names(["name"])
+ Fiddle::Pointer.malloc(6, Fiddle::RUBY_FREE) do |alice|
+ alice[0, 6] = "Alice\0"
+ user["name"] = alice
+ assert_equal("Alice", user["name"].to_s)
+ end
+ end
+ end
+
+ def test_new_double_free
+ types = [TYPE_INT]
+ Pointer.malloc(CStructEntity.size(types), Fiddle::RUBY_FREE) do |pointer|
+ assert_raise ArgumentError do
+ CStructEntity.new(pointer, types, Fiddle::RUBY_FREE)
+ end
+ end
+ end
+
+ def test_malloc_block
+ escaped_struct = nil
+ returned = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct|
+ assert_equal Fiddle::SIZEOF_INT, struct.size
+ assert_equal Fiddle::RUBY_FREE, struct.free.to_i
+ escaped_struct = struct
+ :returned
+ end
+ assert_equal :returned, returned
+ assert escaped_struct.freed?
+ end
+
+ def test_malloc_block_no_free
+ assert_raise ArgumentError do
+ CStructEntity.malloc([TYPE_INT]) { |struct| }
+ end
+ end
+
+ def test_free
+ struct = CStructEntity.malloc([TYPE_INT])
+ begin
+ assert_nil struct.free
+ ensure
+ Fiddle.free struct
+ end
+ end
+
+ def test_free_with_func
+ struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE)
+ refute struct.freed?
+ struct.call_free
+ assert struct.freed?
+ struct.call_free # you can safely run it again
+ assert struct.freed?
+ GC.start # you can safely run the GC routine
+ assert struct.freed?
+ end
+
+ def test_free_with_no_func
+ struct = CStructEntity.malloc([TYPE_INT])
+ refute struct.freed?
+ struct.call_free
+ refute struct.freed?
+ struct.call_free # you can safely run it again
+ refute struct.freed?
+ end
+
+ def test_freed?
+ struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE)
+ refute struct.freed?
+ struct.call_free
+ assert struct.freed?
+ end
+
+ def test_null?
+ struct = CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE)
+ refute struct.null?
+ end
+
+ def test_size
+ CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct|
+ assert_equal Fiddle::SIZEOF_INT, struct.size
+ end
+ end
+
+ def test_size=
+ CStructEntity.malloc([TYPE_INT], Fiddle::RUBY_FREE) do |struct|
+ assert_raise NoMethodError do
+ struct.size = 1
+ end
+ end
end
end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_c_union_entity.rb b/test/fiddle/test_c_union_entity.rb
index 5727a20e3b..e0a3757562 100644
--- a/test/fiddle/test_c_union_entity.rb
+++ b/test/fiddle/test_c_union_entity.rb
@@ -21,15 +21,16 @@ module Fiddle
end
def test_set_ctypes
- union = CUnionEntity.malloc [TYPE_INT, TYPE_LONG]
- union.assign_names %w[int long]
+ CUnionEntity.malloc([TYPE_INT, TYPE_LONG], Fiddle::RUBY_FREE) do |union|
+ union.assign_names %w[int long]
- # this test is roundabout because the stored ctypes are not accessible
- union['long'] = 1
- assert_equal 1, union['long']
+ # this test is roundabout because the stored ctypes are not accessible
+ union['long'] = 1
+ assert_equal 1, union['long']
- union['int'] = 1
- assert_equal 1, union['int']
+ union['int'] = 1
+ assert_equal 1, union['int']
+ end
end
end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb
index 2de0660725..9e748bf5ee 100644
--- a/test/fiddle/test_closure.rb
+++ b/test/fiddle/test_closure.rb
@@ -20,6 +20,18 @@ module Fiddle
end
end
+ def test_type_symbol
+ closure = Closure.new(:int, [:void])
+ assert_equal([
+ TYPE_INT,
+ [TYPE_VOID],
+ ],
+ [
+ closure.instance_variable_get(:@ctype),
+ closure.instance_variable_get(:@args),
+ ])
+ end
+
def test_call
closure = Class.new(Closure) {
def call
@@ -42,6 +54,19 @@ module Fiddle
assert_equal 10, func.call(10)
end
+ def test_const_string
+ closure_class = Class.new(Closure) do
+ def call(string)
+ @return_string = "Hello! #{string}"
+ @return_string
+ end
+ end
+ closure = closure_class.new(:const_string, [:const_string])
+
+ func = Function.new(closure, [:const_string], :const_string)
+ assert_equal("Hello! World!", func.call("World!"))
+ end
+
def test_block_caller
cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one|
one
diff --git a/test/fiddle/test_cparser.rb b/test/fiddle/test_cparser.rb
index 5d9ac3c815..24e1800e59 100644
--- a/test/fiddle/test_cparser.rb
+++ b/test/fiddle/test_cparser.rb
@@ -2,6 +2,7 @@
begin
require_relative 'helper'
require 'fiddle/cparser'
+ require 'fiddle/import'
rescue LoadError
end
@@ -11,53 +12,77 @@ module Fiddle
def test_char_ctype
assert_equal(TYPE_CHAR, parse_ctype('char'))
+ assert_equal(TYPE_CHAR, parse_ctype('const char'))
assert_equal(TYPE_CHAR, parse_ctype('signed char'))
+ assert_equal(TYPE_CHAR, parse_ctype('const signed char'))
assert_equal(-TYPE_CHAR, parse_ctype('unsigned char'))
+ assert_equal(-TYPE_CHAR, parse_ctype('const unsigned char'))
end
def test_short_ctype
assert_equal(TYPE_SHORT, parse_ctype('short'))
+ assert_equal(TYPE_SHORT, parse_ctype('const short'))
assert_equal(TYPE_SHORT, parse_ctype('short int'))
+ assert_equal(TYPE_SHORT, parse_ctype('const short int'))
assert_equal(TYPE_SHORT, parse_ctype('signed short'))
+ assert_equal(TYPE_SHORT, parse_ctype('const signed short'))
assert_equal(TYPE_SHORT, parse_ctype('signed short int'))
+ assert_equal(TYPE_SHORT, parse_ctype('const signed short int'))
assert_equal(-TYPE_SHORT, parse_ctype('unsigned short'))
+ assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short'))
assert_equal(-TYPE_SHORT, parse_ctype('unsigned short int'))
+ assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short int'))
end
def test_int_ctype
assert_equal(TYPE_INT, parse_ctype('int'))
+ assert_equal(TYPE_INT, parse_ctype('const int'))
assert_equal(TYPE_INT, parse_ctype('signed int'))
+ assert_equal(TYPE_INT, parse_ctype('const signed int'))
assert_equal(-TYPE_INT, parse_ctype('uint'))
+ assert_equal(-TYPE_INT, parse_ctype('const uint'))
assert_equal(-TYPE_INT, parse_ctype('unsigned int'))
+ assert_equal(-TYPE_INT, parse_ctype('const unsigned int'))
end
def test_long_ctype
assert_equal(TYPE_LONG, parse_ctype('long'))
+ assert_equal(TYPE_LONG, parse_ctype('const long'))
assert_equal(TYPE_LONG, parse_ctype('long int'))
+ assert_equal(TYPE_LONG, parse_ctype('const long int'))
assert_equal(TYPE_LONG, parse_ctype('signed long'))
+ assert_equal(TYPE_LONG, parse_ctype('const signed long'))
assert_equal(TYPE_LONG, parse_ctype('signed long int'))
+ assert_equal(TYPE_LONG, parse_ctype('const signed long int'))
assert_equal(-TYPE_LONG, parse_ctype('unsigned long'))
+ assert_equal(-TYPE_LONG, parse_ctype('const unsigned long'))
assert_equal(-TYPE_LONG, parse_ctype('unsigned long int'))
+ assert_equal(-TYPE_LONG, parse_ctype('const unsigned long int'))
end
def test_size_t_ctype
assert_equal(TYPE_SIZE_T, parse_ctype("size_t"))
+ assert_equal(TYPE_SIZE_T, parse_ctype("const size_t"))
end
def test_ssize_t_ctype
assert_equal(TYPE_SSIZE_T, parse_ctype("ssize_t"))
+ assert_equal(TYPE_SSIZE_T, parse_ctype("const ssize_t"))
end
def test_ptrdiff_t_ctype
assert_equal(TYPE_PTRDIFF_T, parse_ctype("ptrdiff_t"))
+ assert_equal(TYPE_PTRDIFF_T, parse_ctype("const ptrdiff_t"))
end
def test_intptr_t_ctype
assert_equal(TYPE_INTPTR_T, parse_ctype("intptr_t"))
+ assert_equal(TYPE_INTPTR_T, parse_ctype("const intptr_t"))
end
def test_uintptr_t_ctype
assert_equal(TYPE_UINTPTR_T, parse_ctype("uintptr_t"))
+ assert_equal(TYPE_UINTPTR_T, parse_ctype("const uintptr_t"))
end
def test_undefined_ctype
@@ -65,27 +90,147 @@ module Fiddle
end
def test_undefined_ctype_with_type_alias
- assert_equal(-TYPE_LONG, parse_ctype('DWORD', {"DWORD" => "unsigned long"}))
+ assert_equal(-TYPE_LONG,
+ parse_ctype('DWORD', {"DWORD" => "unsigned long"}))
+ assert_equal(-TYPE_LONG,
+ parse_ctype('const DWORD', {"DWORD" => "unsigned long"}))
+ end
+
+ def expand_struct_types(types)
+ types.collect do |type|
+ case type
+ when Class
+ [expand_struct_types(type.types)]
+ when Array
+ [expand_struct_types([type[0]])[0][0], type[1]]
+ else
+ type
+ end
+ end
end
def test_struct_basic
- assert_equal [[TYPE_INT, TYPE_CHAR], ['i', 'c']], parse_struct_signature(['int i', 'char c'])
+ assert_equal([[TYPE_INT, TYPE_CHAR], ['i', 'c']],
+ parse_struct_signature(['int i', 'char c']))
+ assert_equal([[TYPE_INT, TYPE_CHAR], ['i', 'c']],
+ parse_struct_signature(['const int i', 'const char c']))
end
def test_struct_array
- assert_equal [[[TYPE_CHAR,80],[TYPE_INT,5]], ['buffer','x']], parse_struct_signature(['char buffer[80]', 'int[5] x'])
+ assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]],
+ ['buffer', 'x']],
+ parse_struct_signature(['char buffer[80]',
+ 'int[5] x']))
+ assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]],
+ ['buffer', 'x']],
+ parse_struct_signature(['const char buffer[80]',
+ 'const int[5] x']))
+ end
+
+ def test_struct_nested_struct
+ types, members = parse_struct_signature([
+ 'int x',
+ {inner: ['int i', 'char c']},
+ ])
+ assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]],
+ ['x', ['inner', ['i', 'c']]]],
+ [expand_struct_types(types),
+ members])
+ end
+
+ def test_struct_nested_defined_struct
+ inner = Fiddle::Importer.struct(['int i', 'char c'])
+ assert_equal([[TYPE_INT, inner],
+ ['x', ['inner', ['i', 'c']]]],
+ parse_struct_signature([
+ 'int x',
+ {inner: inner},
+ ]))
+ end
+
+ def test_struct_double_nested_struct
+ types, members = parse_struct_signature([
+ 'int x',
+ {
+ outer: [
+ 'int y',
+ {inner: ['int i', 'char c']},
+ ],
+ },
+ ])
+ assert_equal([[TYPE_INT, [[TYPE_INT, [[TYPE_INT, TYPE_CHAR]]]]],
+ ['x', ['outer', ['y', ['inner', ['i', 'c']]]]]],
+ [expand_struct_types(types),
+ members])
+ end
+
+ def test_struct_nested_struct_array
+ types, members = parse_struct_signature([
+ 'int x',
+ {
+ 'inner[2]' => [
+ 'int i',
+ 'char c',
+ ],
+ },
+ ])
+ assert_equal([[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]],
+ ['x', ['inner', ['i', 'c']]]],
+ [expand_struct_types(types),
+ members])
+ end
+
+ def test_struct_double_nested_struct_inner_array
+ types, members = parse_struct_signature(outer: [
+ 'int x',
+ {
+ 'inner[2]' => [
+ 'int i',
+ 'char c',
+ ],
+ },
+ ])
+ assert_equal([[[[TYPE_INT, [[TYPE_INT, TYPE_CHAR], 2]]]],
+ [['outer', ['x', ['inner', ['i', 'c']]]]]],
+ [expand_struct_types(types),
+ members])
+ end
+
+ def test_struct_double_nested_struct_outer_array
+ types, members = parse_struct_signature([
+ 'int x',
+ {
+ 'outer[2]' => {
+ inner: [
+ 'int i',
+ 'char c',
+ ],
+ },
+ },
+ ])
+ assert_equal([[TYPE_INT, [[[[TYPE_INT, TYPE_CHAR]]], 2]],
+ ['x', ['outer', [['inner', ['i', 'c']]]]]],
+ [expand_struct_types(types),
+ members])
end
def test_struct_array_str
- assert_equal [[[TYPE_CHAR,80],[TYPE_INT,5]], ['buffer','x']], parse_struct_signature('char buffer[80], int[5] x')
+ assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]],
+ ['buffer', 'x']],
+ parse_struct_signature('char buffer[80], int[5] x'))
+ assert_equal([[[TYPE_CHAR, 80], [TYPE_INT, 5]],
+ ['buffer', 'x']],
+ parse_struct_signature('const char buffer[80], const int[5] x'))
end
def test_struct_function_pointer
- assert_equal [[TYPE_VOIDP], ['cb']], parse_struct_signature(['void (*cb)(const char*)'])
+ assert_equal([[TYPE_VOIDP], ['cb']],
+ parse_struct_signature(['void (*cb)(const char*)']))
end
def test_struct_function_pointer_str
- assert_equal [[TYPE_VOIDP,TYPE_VOIDP], ['cb', 'data']], parse_struct_signature('void (*cb)(const char*), const char* data')
+ assert_equal([[TYPE_VOIDP, TYPE_VOIDP], ['cb', 'data']],
+ parse_struct_signature('void (*cb)(const char*), const char* data'))
end
def test_struct_string
@@ -179,6 +324,18 @@ module Fiddle
assert_equal [TYPE_VOIDP, TYPE_INT, TYPE_INT], args
end
+ def test_signature_variadic_arguments
+ unless Fiddle.const_defined?("TYPE_VARIADIC")
+ skip "libffi doesn't support variadic arguments"
+ end
+ assert_equal([
+ "printf",
+ TYPE_INT,
+ [TYPE_VOIDP, TYPE_VARIADIC],
+ ],
+ parse_signature('int printf(const char *format, ...)'))
+ end
+
def test_signature_return_pointer
func, ret, args = parse_signature('void* malloc(size_t)')
assert_equal 'malloc', func
diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb
index ca89173766..d3604c79c3 100644
--- a/test/fiddle/test_func.rb
+++ b/test/fiddle/test_func.rb
@@ -79,5 +79,60 @@ module Fiddle
EnvUtil.under_gc_stress {qsort.call(buff, buff.size, 1, cb)}
assert_equal("1349", buff, bug4929)
end
+
+ def test_snprintf
+ unless Fiddle.const_defined?("TYPE_VARIADIC")
+ skip "libffi doesn't support variadic arguments"
+ end
+ if Fiddle::WINDOWS
+ snprintf_name = "_snprintf"
+ else
+ snprintf_name = "snprintf"
+ end
+ begin
+ snprintf_pointer = @libc[snprintf_name]
+ rescue Fiddle::DLError
+ skip "Can't find #{snprintf_name}: #{$!.message}"
+ end
+ snprintf = Function.new(snprintf_pointer,
+ [
+ :voidp,
+ :size_t,
+ :const_string,
+ :variadic,
+ ],
+ :int)
+ output_buffer = " " * 1024
+ output = Pointer[output_buffer]
+
+ written = snprintf.call(output,
+ output.size,
+ "int: %d, string: %.*s, const string: %s\n",
+ :int, -29,
+ :int, 4,
+ :voidp, "Hello",
+ :const_string, "World")
+ assert_equal("int: -29, string: Hell, const string: World\n",
+ output_buffer[0, written])
+
+ string_like_class = Class.new do
+ def initialize(string)
+ @string = string
+ end
+
+ def to_str
+ @string
+ end
+ end
+ written = snprintf.call(output,
+ output.size,
+ "string: %.*s, const string: %s, uint: %u\n",
+ :int, 2,
+ :voidp, "Hello",
+ :const_string, string_like_class.new("World"),
+ :int, 29)
+ assert_equal("string: He, const string: World, uint: 29\n",
+ output_buffer[0, written])
+ end
end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb
index a58d7afcb1..742615a56b 100644
--- a/test/fiddle/test_function.rb
+++ b/test/fiddle/test_function.rb
@@ -21,6 +21,17 @@ module Fiddle
assert_equal 'sin', func.name
end
+ def test_need_gvl?
+ libruby = Fiddle.dlopen(nil)
+ rb_str_dup = Function.new(libruby['rb_str_dup'],
+ [:voidp],
+ :voidp,
+ need_gvl: true)
+ assert(rb_str_dup.need_gvl?)
+ assert_equal('Hello',
+ Fiddle.dlunwrap(rb_str_dup.call(Fiddle.dlwrap('Hello'))))
+ end
+
def test_argument_errors
assert_raise(TypeError) do
Function.new(@libm['sin'], TYPE_DOUBLE, TYPE_DOUBLE)
@@ -35,6 +46,25 @@ module Fiddle
end
end
+ def test_argument_type_conversion
+ type = Struct.new(:int, :call_count) do
+ def initialize(int)
+ super(int, 0)
+ end
+ def to_int
+ raise "exhausted" if (self.call_count += 1) > 1
+ self.int
+ end
+ end
+ type_arg = type.new(TYPE_DOUBLE)
+ type_result = type.new(TYPE_DOUBLE)
+ assert_nothing_raised(RuntimeError) do
+ Function.new(@libm['sin'], [type_arg], type_result)
+ end
+ assert_equal(1, type_arg.call_count)
+ assert_equal(1, type_result.call_count)
+ end
+
def test_call
func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE)
assert_in_delta 1.0, func.call(90 * Math::PI / 180), 0.0001
@@ -98,7 +128,7 @@ module Fiddle
end
def test_no_memory_leak
- prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_frozen"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"'
+ prep = 'r = Fiddle::Function.new(Fiddle.dlopen(nil)["rb_obj_frozen_p"], [Fiddle::TYPE_UINTPTR_T], Fiddle::TYPE_UINTPTR_T); a = "a"'
code = 'begin r.call(a); rescue TypeError; end'
assert_no_memory_leak(%w[-W0 -rfiddle], "#{prep}\n1000.times{#{code}}", "10_000.times {#{code}}", limit: 1.2)
end
diff --git a/test/fiddle/test_import.rb b/test/fiddle/test_import.rb
index 99294ea161..afa8df9e00 100644
--- a/test/fiddle/test_import.rb
+++ b/test/fiddle/test_import.rb
@@ -36,6 +36,29 @@ module Fiddle
"char c",
"unsigned char buff[7]",
]
+ StructNestedStruct = struct [
+ {
+ "vertices[2]" => {
+ position: ["float x", "float y", "float z"],
+ texcoord: ["float u", "float v"]
+ },
+ object: ["int id", "void *user_data"],
+ },
+ "int id"
+ ]
+ UnionNestedStruct = union [
+ {
+ keyboard: [
+ 'unsigned int state',
+ 'char key'
+ ],
+ mouse: [
+ 'unsigned int button',
+ 'unsigned short x',
+ 'unsigned short y'
+ ]
+ }
+ ]
CallCallback = bind("void call_callback(void*, void*)"){ | ptr1, ptr2|
f = Function.new(ptr1.to_i, [TYPE_VOIDP], TYPE_VOID)
@@ -54,25 +77,61 @@ module Fiddle
assert_match(/call dlload before/, err.message)
end
+ def test_struct_memory_access()
+ # check memory operations performed directly on struct
+ Fiddle::Importer.struct(['int id']).malloc(Fiddle::RUBY_FREE) do |my_struct|
+ my_struct[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT
+ assert_equal 0x01010101, my_struct.id
+
+ my_struct.id = 0
+ assert_equal "\x00".b * Fiddle::SIZEOF_INT, my_struct[0, Fiddle::SIZEOF_INT]
+ end
+ end
+
+ def test_struct_ptr_array_subscript_multiarg()
+ # check memory operations performed on struct#to_ptr
+ Fiddle::Importer.struct([ 'int x' ]).malloc(Fiddle::RUBY_FREE) do |struct|
+ ptr = struct.to_ptr
+
+ struct.x = 0x02020202
+ assert_equal("\x02".b * Fiddle::SIZEOF_INT, ptr[0, Fiddle::SIZEOF_INT])
+
+ ptr[0, Fiddle::SIZEOF_INT] = "\x01".b * Fiddle::SIZEOF_INT
+ assert_equal 0x01010101, struct.x
+ end
+ end
+
def test_malloc()
- s1 = LIBC::Timeval.malloc()
- s2 = LIBC::Timeval.malloc()
- refute_equal(s1.to_ptr.to_i, s2.to_ptr.to_i)
+ LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s1|
+ LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |s2|
+ refute_equal(s1.to_ptr.to_i, s2.to_ptr.to_i)
+ end
+ end
end
def test_sizeof()
assert_equal(SIZEOF_VOIDP, LIBC.sizeof("FILE*"))
assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(LIBC::MyStruct))
- assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(LIBC::MyStruct.malloc()))
+ LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |my_struct|
+ assert_equal(LIBC::MyStruct.size(), LIBC.sizeof(my_struct))
+ end
assert_equal(SIZEOF_LONG_LONG, LIBC.sizeof("long long")) if defined?(SIZEOF_LONG_LONG)
+ assert_equal(LIBC::StructNestedStruct.size(), LIBC.sizeof(LIBC::StructNestedStruct))
end
- Fiddle.constants.grep(/\ATYPE_(?!VOID\z)(.*)/) do
+ Fiddle.constants.grep(/\ATYPE_(?!VOID|VARIADIC\z)(.*)/) do
type = $&
- size = Fiddle.const_get("SIZEOF_#{$1}")
- name = $1.sub(/P\z/,"*").gsub(/_(?!T\z)/, " ").downcase
+ const_type_name = $1
+ size = Fiddle.const_get("SIZEOF_#{const_type_name}")
+ if const_type_name == "CONST_STRING"
+ name = "const_string"
+ type_name = "const char*"
+ else
+ name = $1.sub(/P\z/,"*").gsub(/_(?!T\z)/, " ").downcase
+ type_name = name
+ end
define_method("test_sizeof_#{name}") do
- assert_equal(size, Fiddle::Importer.sizeof(name), type)
+ assert_equal(size, Fiddle::Importer.sizeof(type_name), type)
end
end
@@ -107,23 +166,292 @@ module Fiddle
assert_equal([0,1,2], ary.value)
end
+ def test_struct_array_assignment()
+ Fiddle::Importer.struct(["unsigned int stages[3]"]).malloc(Fiddle::RUBY_FREE) do |instance|
+ instance.stages[0] = 1024
+ instance.stages[1] = 10
+ instance.stages[2] = 100
+ assert_equal 1024, instance.stages[0]
+ assert_equal 10, instance.stages[1]
+ assert_equal 100, instance.stages[2]
+ assert_equal [1024, 10, 100].pack(Fiddle::PackInfo::PACK_MAP[-Fiddle::TYPE_INT] * 3),
+ instance.to_ptr[0, 3 * Fiddle::SIZEOF_INT]
+ assert_raise(IndexError) { instance.stages[-1] = 5 }
+ assert_raise(IndexError) { instance.stages[3] = 5 }
+ end
+ end
+
+ def test_nested_struct_reusing_other_structs()
+ position_struct = Fiddle::Importer.struct(['float x', 'float y', 'float z'])
+ texcoord_struct = Fiddle::Importer.struct(['float u', 'float v'])
+ vertex_struct = Fiddle::Importer.struct(position: position_struct, texcoord: texcoord_struct)
+ mesh_struct = Fiddle::Importer.struct([
+ {
+ "vertices[2]" => vertex_struct,
+ object: [
+ "int id",
+ "void *user_data",
+ ],
+ },
+ "int id",
+ ])
+ assert_equal LIBC::StructNestedStruct.size, mesh_struct.size
+
+
+ keyboard_event_struct = Fiddle::Importer.struct(['unsigned int state', 'char key'])
+ mouse_event_struct = Fiddle::Importer.struct(['unsigned int button', 'unsigned short x', 'unsigned short y'])
+ event_union = Fiddle::Importer.union([{ keboard: keyboard_event_struct, mouse: mouse_event_struct}])
+ assert_equal LIBC::UnionNestedStruct.size, event_union.size
+ end
+
+ def test_nested_struct_alignment_is_not_its_size()
+ inner = Fiddle::Importer.struct(['int x', 'int y', 'int z', 'int w'])
+ outer = Fiddle::Importer.struct(['char a', { 'nested' => inner }, 'char b'])
+ outer.malloc(Fiddle::RUBY_FREE) do |instance|
+ offset = instance.to_ptr.instance_variable_get(:"@offset")
+ assert_equal Fiddle::SIZEOF_INT * 5, offset.last
+ assert_equal Fiddle::SIZEOF_INT * 6, outer.size
+ assert_equal instance.to_ptr.size, outer.size
+ end
+ end
+
+ def test_struct_nested_struct_members()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ Fiddle::Pointer.malloc(24, Fiddle::RUBY_FREE) do |user_data|
+ s.vertices[0].position.x = 1
+ s.vertices[0].position.y = 2
+ s.vertices[0].position.z = 3
+ s.vertices[0].texcoord.u = 4
+ s.vertices[0].texcoord.v = 5
+ s.vertices[1].position.x = 6
+ s.vertices[1].position.y = 7
+ s.vertices[1].position.z = 8
+ s.vertices[1].texcoord.u = 9
+ s.vertices[1].texcoord.v = 10
+ s.object.id = 100
+ s.object.user_data = user_data
+ s.id = 101
+ assert_equal({
+ "vertices" => [
+ {
+ "position" => {
+ "x" => 1,
+ "y" => 2,
+ "z" => 3,
+ },
+ "texcoord" => {
+ "u" => 4,
+ "v" => 5,
+ },
+ },
+ {
+ "position" => {
+ "x" => 6,
+ "y" => 7,
+ "z" => 8,
+ },
+ "texcoord" => {
+ "u" => 9,
+ "v" => 10,
+ },
+ },
+ ],
+ "object" => {
+ "id" => 100,
+ "user_data" => user_data,
+ },
+ "id" => 101,
+ },
+ s.to_h)
+ end
+ end
+ end
+
+ def test_union_nested_struct_members()
+ LIBC::UnionNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ s.keyboard.state = 100
+ s.keyboard.key = 101
+ assert_equal(100, s.mouse.button)
+ refute_equal( 0, s.mouse.x)
+ end
+ end
+
+ def test_struct_nested_struct_replace_array_element()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ s.vertices[0].position.x = 5
+
+ vertex_struct = Fiddle::Importer.struct [{
+ position: ["float x", "float y", "float z"],
+ texcoord: ["float u", "float v"]
+ }]
+ vertex_struct.malloc(Fiddle::RUBY_FREE) do |vertex|
+ vertex.position.x = 100
+ s.vertices[0] = vertex
+
+ # make sure element was copied by value, but things like memory address
+ # should not be changed
+ assert_equal(100, s.vertices[0].position.x)
+ refute_equal(vertex.object_id, s.vertices[0].object_id)
+ refute_equal(vertex.to_ptr, s.vertices[0].to_ptr)
+ end
+ end
+ end
+
+ def test_struct_nested_struct_replace_array_element_nil()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ s.vertices[0].position.x = 5
+ s.vertices[0] = nil
+ assert_equal({
+ "position" => {
+ "x" => 0.0,
+ "y" => 0.0,
+ "z" => 0.0,
+ },
+ "texcoord" => {
+ "u" => 0.0,
+ "v" => 0.0,
+ },
+ },
+ s.vertices[0].to_h)
+ end
+ end
+
+ def test_struct_nested_struct_replace_array_element_hash()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ s.vertices[0] = {
+ position: {
+ x: 10,
+ y: 100,
+ }
+ }
+ assert_equal({
+ "position" => {
+ "x" => 10.0,
+ "y" => 100.0,
+ "z" => 0.0,
+ },
+ "texcoord" => {
+ "u" => 0.0,
+ "v" => 0.0,
+ },
+ },
+ s.vertices[0].to_h)
+ end
+ end
+
+ def test_struct_nested_struct_replace_entire_array()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ vertex_struct = Fiddle::Importer.struct [{
+ position: ["float x", "float y", "float z"],
+ texcoord: ["float u", "float v"]
+ }]
+
+ vertex_struct.malloc(Fiddle::RUBY_FREE) do |same0|
+ vertex_struct.malloc(Fiddle::RUBY_FREE) do |same1|
+ same = [same0, same1]
+ same[0].position.x = 1; same[1].position.x = 6
+ same[0].position.y = 2; same[1].position.y = 7
+ same[0].position.z = 3; same[1].position.z = 8
+ same[0].texcoord.u = 4; same[1].texcoord.u = 9
+ same[0].texcoord.v = 5; same[1].texcoord.v = 10
+ s.vertices = same
+ assert_equal([
+ {
+ "position" => {
+ "x" => 1.0,
+ "y" => 2.0,
+ "z" => 3.0,
+ },
+ "texcoord" => {
+ "u" => 4.0,
+ "v" => 5.0,
+ },
+ },
+ {
+ "position" => {
+ "x" => 6.0,
+ "y" => 7.0,
+ "z" => 8.0,
+ },
+ "texcoord" => {
+ "u" => 9.0,
+ "v" => 10.0,
+ },
+ }
+ ],
+ s.vertices.collect(&:to_h))
+ end
+ end
+ end
+ end
+
+ def test_struct_nested_struct_replace_entire_array_with_different_struct()
+ LIBC::StructNestedStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ different_struct_same_size = Fiddle::Importer.struct [{
+ a: ['float i', 'float j', 'float k'],
+ b: ['float l', 'float m']
+ }]
+
+ different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different0|
+ different_struct_same_size.malloc(Fiddle::RUBY_FREE) do |different1|
+ different = [different0, different1]
+ different[0].a.i = 11; different[1].a.i = 16
+ different[0].a.j = 12; different[1].a.j = 17
+ different[0].a.k = 13; different[1].a.k = 18
+ different[0].b.l = 14; different[1].b.l = 19
+ different[0].b.m = 15; different[1].b.m = 20
+ s.vertices[0][0, s.vertices[0].class.size] = different[0].to_ptr
+ s.vertices[1][0, s.vertices[1].class.size] = different[1].to_ptr
+ assert_equal([
+ {
+ "position" => {
+ "x" => 11.0,
+ "y" => 12.0,
+ "z" => 13.0,
+ },
+ "texcoord" => {
+ "u" => 14.0,
+ "v" => 15.0,
+ },
+ },
+ {
+ "position" => {
+ "x" => 16.0,
+ "y" => 17.0,
+ "z" => 18.0,
+ },
+ "texcoord" => {
+ "u" => 19.0,
+ "v" => 20.0,
+ },
+ }
+ ],
+ s.vertices.collect(&:to_h))
+ end
+ end
+ end
+ end
+
def test_struct()
- s = LIBC::MyStruct.malloc()
- s.num = [0,1,2,3,4]
- s.c = ?a.ord
- s.buff = "012345\377"
- assert_equal([0,1,2,3,4], s.num)
- assert_equal(?a.ord, s.c)
- assert_equal([?0.ord,?1.ord,?2.ord,?3.ord,?4.ord,?5.ord,?\377.ord], s.buff)
+ LIBC::MyStruct.malloc(Fiddle::RUBY_FREE) do |s|
+ s.num = [0,1,2,3,4]
+ s.c = ?a.ord
+ s.buff = "012345\377"
+ assert_equal([0,1,2,3,4], s.num)
+ assert_equal(?a.ord, s.c)
+ assert_equal([?0.ord,?1.ord,?2.ord,?3.ord,?4.ord,?5.ord,?\377.ord], s.buff)
+ end
end
def test_gettimeofday()
if( defined?(LIBC.gettimeofday) )
- timeval = LIBC::Timeval.malloc()
- timezone = LIBC::Timezone.malloc()
- LIBC.gettimeofday(timeval, timezone)
- cur = Time.now()
- assert(cur.to_i - 2 <= timeval.tv_sec && timeval.tv_sec <= cur.to_i)
+ LIBC::Timeval.malloc(Fiddle::RUBY_FREE) do |timeval|
+ LIBC::Timezone.malloc(Fiddle::RUBY_FREE) do |timezone|
+ LIBC.gettimeofday(timeval, timezone)
+ end
+ cur = Time.now()
+ assert(cur.to_i - 2 <= timeval.tv_sec && timeval.tv_sec <= cur.to_i)
+ end
end
end
@@ -147,9 +475,5 @@ module Fiddle
r = LIBC.atof("12.34")
assert_includes(12.00..13.00, r)
end
-
- def test_no_message_with_debug
- assert_in_out_err(%w[--debug --disable=gems -rfiddle/import], 'p Fiddle::Importer', ['Fiddle::Importer'])
- end
end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_memory_view.rb b/test/fiddle/test_memory_view.rb
new file mode 100644
index 0000000000..c673d2633a
--- /dev/null
+++ b/test/fiddle/test_memory_view.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+begin
+ require_relative 'helper'
+rescue LoadError
+end
+
+begin
+ require '-test-/memory_view'
+rescue LoadError
+end
+
+module Fiddle
+ class TestMemoryView < TestCase
+ def setup
+ skip "MemoryView is unavailable" unless defined? Fiddle::MemoryView
+ end
+
+ def test_null_ptr
+ assert_raise(ArgumentError) do
+ MemoryView.new(Fiddle::NULL)
+ end
+ end
+
+ def test_memory_view_from_unsupported_obj
+ obj = Object.new
+ assert_raise(ArgumentError) do
+ MemoryView.new(obj)
+ end
+ end
+
+ def test_memory_view_from_pointer
+ str = Marshal.load(Marshal.dump("hello world"))
+ ptr = Pointer[str]
+ mview = MemoryView.new(ptr)
+ assert_same(ptr, mview.obj)
+ assert_equal(str.bytesize, mview.byte_size)
+ assert_equal(true, mview.readonly?)
+ assert_equal(nil, mview.format)
+ assert_equal(1, mview.item_size)
+ assert_equal(1, mview.ndim)
+ assert_equal(nil, mview.shape)
+ assert_equal(nil, mview.strides)
+ assert_equal(nil, mview.sub_offsets)
+
+ codes = str.codepoints
+ assert_equal(codes, (0...str.bytesize).map {|i| mview[i] })
+ end
+
+ def test_memory_view_multi_dimensional
+ skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+
+ buf = [ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12 ].pack("l!*")
+ shape = [3, 4]
+ md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, nil)
+ mview = Fiddle::MemoryView.new(md)
+ assert_equal(buf.bytesize, mview.byte_size)
+ assert_equal("l!", mview.format)
+ assert_equal(Fiddle::SIZEOF_LONG, mview.item_size)
+ assert_equal(2, mview.ndim)
+ assert_equal(shape, mview.shape)
+ assert_equal([Fiddle::SIZEOF_LONG*4, Fiddle::SIZEOF_LONG], mview.strides)
+ assert_equal(nil, mview.sub_offsets)
+ assert_equal(1, mview[0, 0])
+ assert_equal(4, mview[0, 3])
+ assert_equal(6, mview[1, 1])
+ assert_equal(10, mview[2, 1])
+ end
+
+ def test_memory_view_multi_dimensional_with_strides
+ skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+
+ buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16 ].pack("l!*")
+ shape = [2, 8]
+ strides = [4*Fiddle::SIZEOF_LONG*2, Fiddle::SIZEOF_LONG*2]
+ md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, strides)
+ mview = Fiddle::MemoryView.new(md)
+ assert_equal("l!", mview.format)
+ assert_equal(Fiddle::SIZEOF_LONG, mview.item_size)
+ assert_equal(buf.bytesize, mview.byte_size)
+ assert_equal(2, mview.ndim)
+ assert_equal(shape, mview.shape)
+ assert_equal(strides, mview.strides)
+ assert_equal(nil, mview.sub_offsets)
+ assert_equal(1, mview[0, 0])
+ assert_equal(5, mview[0, 2])
+ assert_equal(9, mview[1, 0])
+ assert_equal(15, mview[1, 3])
+ end
+
+ def test_memory_view_multi_dimensional_with_multiple_members
+ skip "MemoryViewTestUtils is unavailable" unless defined? MemoryViewTestUtils
+
+ buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
+ -1, -2, -3, -4, -5, -6, -7, -8].pack("s*")
+ shape = [2, 4]
+ strides = [4*Fiddle::SIZEOF_SHORT*2, Fiddle::SIZEOF_SHORT*2]
+ md = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides)
+ mview = Fiddle::MemoryView.new(md)
+ assert_equal("ss", mview.format)
+ assert_equal(Fiddle::SIZEOF_SHORT*2, mview.item_size)
+ assert_equal(buf.bytesize, mview.byte_size)
+ assert_equal(2, mview.ndim)
+ assert_equal(shape, mview.shape)
+ assert_equal(strides, mview.strides)
+ assert_equal(nil, mview.sub_offsets)
+ assert_equal([1, 2], mview[0, 0])
+ assert_equal([5, 6], mview[0, 2])
+ assert_equal([-1, -2], mview[1, 0])
+ assert_equal([-7, -8], mview[1, 3])
+ end
+ end
+end
diff --git a/test/fiddle/test_pinned.rb b/test/fiddle/test_pinned.rb
new file mode 100644
index 0000000000..5bfae2172a
--- /dev/null
+++ b/test/fiddle/test_pinned.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+begin
+ require_relative 'helper'
+rescue LoadError
+end
+
+module Fiddle
+ class TestPinned < Fiddle::TestCase
+ def test_pin_object
+ x = Object.new
+ pinner = Pinned.new x
+ assert_same x, pinner.ref
+ end
+
+ def test_clear
+ pinner = Pinned.new Object.new
+ refute pinner.cleared?
+ pinner.clear
+ assert pinner.cleared?
+ ex = assert_raise(Fiddle::ClearedReferenceError) do
+ pinner.ref
+ end
+ assert_match "called on", ex.message
+ end
+ end
+end
+
diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb
index 5581c1dea7..88dad75138 100644
--- a/test/fiddle/test_pointer.rb
+++ b/test/fiddle/test_pointer.rb
@@ -32,6 +32,31 @@ module Fiddle
assert_equal free.to_i, ptr.free.to_i
end
+ def test_malloc_block
+ escaped_ptr = nil
+ returned = Pointer.malloc(10, Fiddle::RUBY_FREE) do |ptr|
+ assert_equal 10, ptr.size
+ assert_equal Fiddle::RUBY_FREE, ptr.free.to_i
+ escaped_ptr = ptr
+ :returned
+ end
+ assert_equal :returned, returned
+ assert escaped_ptr.freed?
+ end
+
+ def test_malloc_block_no_free
+ assert_raise ArgumentError do
+ Pointer.malloc(10) { |ptr| }
+ end
+ end
+
+ def test_malloc_subclass
+ subclass = Class.new(Pointer)
+ subclass.malloc(10, Fiddle::RUBY_FREE) do |ptr|
+ assert ptr.is_a?(subclass)
+ end
+ end
+
def test_to_str
str = Marshal.load(Marshal.dump("hello world"))
ptr = Pointer[str]
@@ -84,17 +109,18 @@ module Fiddle
end
def test_to_ptr_io
- buf = Pointer.malloc(10)
- File.open(__FILE__, 'r') do |f|
- ptr = Pointer.to_ptr f
- fread = Function.new(@libc['fread'],
- [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP],
- TYPE_INT)
- fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i)
- end
-
- File.open(__FILE__, 'r') do |f|
- assert_equal f.read(9), buf.to_s
+ Pointer.malloc(10, Fiddle::RUBY_FREE) do |buf|
+ File.open(__FILE__, 'r') do |f|
+ ptr = Pointer.to_ptr f
+ fread = Function.new(@libc['fread'],
+ [TYPE_VOIDP, TYPE_INT, TYPE_INT, TYPE_VOIDP],
+ TYPE_INT)
+ fread.call(buf.to_i, Fiddle::SIZEOF_CHAR, buf.size - 1, ptr.to_i)
+ end
+
+ File.open(__FILE__, 'r') do |f|
+ assert_equal f.read(9), buf.to_s
+ end
end
end
@@ -145,7 +171,11 @@ module Fiddle
def test_free
ptr = Pointer.malloc(4)
- assert_nil ptr.free
+ begin
+ assert_nil ptr.free
+ ensure
+ Fiddle.free ptr
+ end
end
def test_free=
@@ -166,22 +196,49 @@ module Fiddle
assert_equal free.ptr, ptr.free.ptr
end
+ def test_free_with_func
+ ptr = Pointer.malloc(4, Fiddle::RUBY_FREE)
+ refute ptr.freed?
+ ptr.call_free
+ assert ptr.freed?
+ ptr.call_free # you can safely run it again
+ assert ptr.freed?
+ GC.start # you can safely run the GC routine
+ assert ptr.freed?
+ end
+
+ def test_free_with_no_func
+ ptr = Pointer.malloc(4)
+ refute ptr.freed?
+ ptr.call_free
+ refute ptr.freed?
+ ptr.call_free # you can safely run it again
+ refute ptr.freed?
+ end
+
+ def test_freed?
+ ptr = Pointer.malloc(4, Fiddle::RUBY_FREE)
+ refute ptr.freed?
+ ptr.call_free
+ assert ptr.freed?
+ end
+
def test_null?
ptr = Pointer.new(0)
assert ptr.null?
end
def test_size
- ptr = Pointer.malloc(4)
- assert_equal 4, ptr.size
- Fiddle.free ptr.to_i
+ Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr|
+ assert_equal 4, ptr.size
+ end
end
def test_size=
- ptr = Pointer.malloc(4)
- ptr.size = 10
- assert_equal 10, ptr.size
- Fiddle.free ptr.to_i
+ Pointer.malloc(4, Fiddle::RUBY_FREE) do |ptr|
+ ptr.size = 10
+ assert_equal 10, ptr.size
+ end
end
def test_aref_aset
diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb
index ca435ed1ff..63936d1a05 100644
--- a/test/fileutils/test_fileutils.rb
+++ b/test/fileutils/test_fileutils.rb
@@ -51,7 +51,11 @@ class TestFileUtils < Test::Unit::TestCase
end
def check_have_symlink?
- File.symlink "", ""
+ Dir.mktmpdir do |dir|
+ Dir.chdir(dir) do
+ File.symlink "symlink", "symlink"
+ end
+ end
rescue NotImplementedError, Errno::EACCES
return false
rescue
@@ -68,8 +72,13 @@ class TestFileUtils < Test::Unit::TestCase
end
def check_have_hardlink?
- File.link nil, nil
- rescue NotImplementedError
+ Dir.mktmpdir do |dir|
+ Dir.chdir(dir) do
+ File.write "dummy", "dummy"
+ File.link "dummy", "hardlink"
+ end
+ end
+ rescue NotImplementedError, Errno::EACCES
return false
rescue
return true
@@ -741,6 +750,34 @@ class TestFileUtils < Test::Unit::TestCase
assert_file_not_exist 'tmp/tmpdir3'
end
+ def test_remove_entry_cjk_path
+ dir = "tmpdir\u3042"
+ my_rm_rf dir
+
+ Dir.mkdir dir
+ File.write("#{dir}/\u3042.txt", "test_remove_entry_cjk_path")
+
+ remove_entry dir
+ assert_file_not_exist dir
+ end
+
+ def test_remove_entry_multibyte_path
+ c = "\u00a7"
+ begin
+ c = c.encode('filesystem')
+ rescue EncodingError
+ c = c.b
+ end
+ dir = "tmpdir#{c}"
+ my_rm_rf dir
+
+ Dir.mkdir dir
+ File.write("#{dir}/#{c}.txt", "test_remove_entry_multibyte_path")
+
+ remove_entry dir
+ assert_file_not_exist dir
+ end
+
def test_remove_entry_secure
check_singleton :remove_entry_secure
@@ -1182,6 +1219,8 @@ class TestFileUtils < Test::Unit::TestCase
assert_filemode 04500, 'tmp/j'
install 'tmp/j', 'tmp/k', :mode => "+s"
assert_filemode 06500, 'tmp/k'
+ install 'tmp/a', 'tmp/l', :mode => "o+X"
+ assert_equal_filemode 'tmp/a', 'tmp/l'
end if have_file_perm?
def test_chmod
@@ -1709,16 +1748,16 @@ class TestFileUtils < Test::Unit::TestCase
o.extend(FileUtils)
o.singleton_class.send(:public, :chdir)
o.freeze
- orig_stderr = $stderr
- $stderr = StringIO.new
+ orig_stdout = $stdout
+ $stdout = StringIO.new
o.chdir('.', verbose: true){}
- $stderr.rewind
- assert_equal(<<-END, $stderr.read)
+ $stdout.rewind
+ assert_equal(<<-END, $stdout.read)
cd .
cd -
END
ensure
- $stderr = orig_stderr if orig_stderr
+ $stdout = orig_stdout if orig_stdout
end
def test_getwd
diff --git a/test/fixtures/fake_sorted_set_gem/sorted_set.rb b/test/fixtures/fake_sorted_set_gem/sorted_set.rb
new file mode 100644
index 0000000000..f45a766303
--- /dev/null
+++ b/test/fixtures/fake_sorted_set_gem/sorted_set.rb
@@ -0,0 +1,9 @@
+Object.instance_exec do
+ # Remove the constant to cancel autoload that would be fired by
+ # `class SortedSet` and cause circular require.
+ remove_const :SortedSet if const_defined?(:SortedSet)
+end
+
+class SortedSet < Set
+ # ...
+end
diff --git a/test/gdbm/test_gdbm.rb b/test/gdbm/test_gdbm.rb
index 64692a4465..e02282b451 100644
--- a/test/gdbm/test_gdbm.rb
+++ b/test/gdbm/test_gdbm.rb
@@ -143,7 +143,7 @@ if defined? GDBM
def open_db_child(dbname, *opts)
opts = [0644, *opts].map(&:inspect).join(', ')
- args = [EnvUtil.rubybin, "-rgdbm", "-e", <<-SRC, dbname]
+ args = [EnvUtil.rubybin, "-Ilib", "-rgdbm", "-e", <<-SRC, dbname]
STDOUT.sync = true
gdbm = GDBM.open(ARGV.shift, #{opts})
puts gdbm.class
diff --git a/test/io/console/test_io_console.rb b/test/io/console/test_io_console.rb
index a02605dd1e..bec10c5da0 100644
--- a/test/io/console/test_io_console.rb
+++ b/test/io/console/test_io_console.rb
@@ -29,6 +29,20 @@ class TestIO_Console < Test::Unit::TestCase
def set_winsize_teardown
trap(:TTOU, @old_ttou) if defined?(@old_ttou) and @old_ttou
end
+
+ def test_failed_path
+ exceptions = %w[ENODEV ENOTTY EBADF ENXIO].map {|e|
+ Errno.const_get(e) if Errno.const_defined?(e)
+ }
+ exceptions.compact!
+ skip if exceptions.empty?
+ File.open(IO::NULL) do |f|
+ e = assert_raise(*exceptions) do
+ f.echo?
+ end
+ assert_include(e.message, IO::NULL)
+ end
+ end
end
defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
@@ -221,6 +235,15 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
assert_equal("\r\n", r.gets)
assert_equal("\"asdf\"", r.gets.chomp)
end
+
+ run_pty("p IO.console.getpass('> ')") do |r, w|
+ assert_equal("> ", r.readpartial(10))
+ sleep 0.1
+ w.print "asdf\C-D\C-D"
+ sleep 0.1
+ assert_equal("\r\n", r.gets)
+ assert_equal("\"asdf\"", r.gets.chomp)
+ end
end
def test_iflush
@@ -429,10 +452,14 @@ defined?(IO.console) and TestIO_Console.class_eval do
s = IO.console.winsize
assert_nothing_raised(TypeError) {IO.console.winsize = s}
bug = '[ruby-core:82741] [Bug #13888]'
- IO.console.winsize = [s[0], s[1]+1]
- assert_equal([s[0], s[1]+1], IO.console.winsize, bug)
- IO.console.winsize = s
- assert_equal(s, IO.console.winsize, bug)
+ begin
+ IO.console.winsize = [s[0], s[1]+1]
+ assert_equal([s[0], s[1]+1], IO.console.winsize, bug)
+ rescue Errno::EINVAL # Error if run on an actual console.
+ else
+ IO.console.winsize = s
+ assert_equal(s, IO.console.winsize, bug)
+ end
ensure
set_winsize_teardown
end
@@ -453,6 +480,10 @@ defined?(IO.console) and TestIO_Console.class_eval do
ensure
IO.console(:close)
end
+
+ def test_getch_timeout
+ assert_nil(IO.console.getch(intr: true, time: 0.1, min: 0))
+ end
end
end
diff --git a/test/io/wait/test_io_wait_uncommon.rb b/test/io/wait/test_io_wait_uncommon.rb
index e7f222c578..b6f1c29bcd 100644
--- a/test/io/wait/test_io_wait_uncommon.rb
+++ b/test/io/wait/test_io_wait_uncommon.rb
@@ -6,19 +6,15 @@ require 'io/wait'
# We may optimize IO#wait_*able for non-Linux kernels in the future
class TestIOWaitUncommon < Test::Unit::TestCase
def test_tty_wait
- begin
- tty = File.open('/dev/tty', 'w+')
- rescue Errno::ENOENT, Errno::ENXIO => e
- skip "/dev/tty: #{e.message} (#{e.class})"
+ check_dev('/dev/tty', mode: 'w+') do |tty|
+ assert_include [ nil, tty ], tty.wait_readable(0)
+ assert_equal tty, tty.wait_writable(1), 'portability test'
end
- assert_include [ nil, tty ], tty.wait_readable(0)
- assert_equal tty, tty.wait_writable(1), 'portability test'
- ensure
- tty&.close
end
def test_fifo_wait
skip 'no mkfifo' unless File.respond_to?(:mkfifo) && IO.const_defined?(:NONBLOCK)
+ require 'tmpdir'
Dir.mktmpdir('rubytest-fifo') do |dir|
fifo = "#{dir}/fifo"
assert_equal 0, File.mkfifo(fifo)
@@ -43,36 +39,40 @@ class TestIOWaitUncommon < Test::Unit::TestCase
# used to find portability problems because some ppoll implementations
# are incomplete and do not work for certain "file" types
- def check_dev(dev, m = :wait_readable)
+ def check_dev(dev, m = :wait_readable, mode: m == :wait_readable ? 'r' : 'w', &block)
begin
- fp = File.open("/dev/#{dev}", m == :wait_readable ? 'r' : 'w')
+ fp = File.open(dev, mode)
+ rescue Errno::ENOENT
+ return # Ignore silently
rescue SystemCallError => e
skip "#{dev} could not be opened #{e.message} (#{e.class})"
end
- assert_same fp, fp.__send__(m)
+ if block
+ yield fp
+ else
+ assert_same fp, fp.__send__(m)
+ end
ensure
fp&.close
end
def test_wait_readable_urandom
- check_dev 'urandom'
+ check_dev('/dev/urandom')
end
def test_wait_readable_random
- File.open('/dev/random') do |fp|
+ check_dev('/dev/random') do |fp|
assert_nothing_raised do
fp.wait_readable(0)
end
end
- rescue SystemCallError => e
- skip "/dev/random could not be opened #{e.message} (#{e.class})"
end
def test_wait_readable_zero
- check_dev 'zero'
+ check_dev('/dev/zero')
end
def test_wait_writable_null
- check_dev 'null', :wait_writable
+ check_dev(IO::NULL, :wait_writable)
end
end
diff --git a/test/io/wait/test_ractor.rb b/test/io/wait/test_ractor.rb
new file mode 100644
index 0000000000..3d286af77f
--- /dev/null
+++ b/test/io/wait/test_ractor.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+require 'test/unit'
+require 'rbconfig'
+require 'io/wait'
+
+class TestIOWaitInRactor < Test::Unit::TestCase
+ def setup
+ omit unless defined? Ractor
+ end
+
+ def test_ractor
+ ext = "/io/wait.#{RbConfig::CONFIG['DLEXT']}"
+ path = $".find {|path| path.end_with?(ext)}
+ assert_in_out_err(%W[-r#{path}], <<-"end;", ["true"], [])
+ $VERBOSE = nil
+ r = Ractor.new do
+ $stdout.equal?($stdout.wait_writable)
+ end
+ puts r.take
+ end;
+ end
+end
diff --git a/test/irb/test_cmd.rb b/test/irb/test_cmd.rb
index d0f1ac645c..044d852a32 100644
--- a/test/irb/test_cmd.rb
+++ b/test/irb/test_cmd.rb
@@ -5,6 +5,32 @@ require "irb/extend-command"
module TestIRB
class ExtendCommand < Test::Unit::TestCase
+ class TestInputMethod < ::IRB::InputMethod
+ attr_reader :list, :line_no
+
+ def initialize(list = [])
+ super("test")
+ @line_no = 0
+ @list = list
+ end
+
+ def gets
+ @list[@line_no]&.tap {@line_no += 1}
+ end
+
+ def eof?
+ @line_no >= @list.size
+ end
+
+ def encoding
+ Encoding.default_external
+ end
+
+ def reset
+ @line_no = 0
+ end
+ end
+
def setup
@pwd = Dir.pwd
@tmpdir = File.join(Dir.tmpdir, "test_reline_config_#{$$}")
@@ -44,13 +70,14 @@ module TestIRB
IRB.conf[:USE_SINGLELINE] = false
IRB.conf[:VERBOSE] = false
workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace)
+ irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
IRB.conf[:MAIN_CONTEXT] = irb.context
expected = %r{
Ruby\sversion: .+\n
IRB\sversion:\sirb .+\n
- InputMethod:\sReidlineInputMethod\swith\sReline .+ and .+\n
- \.irbrc\spath: .+
+ InputMethod:\sAbstract\sInputMethod\n
+ \.irbrc\spath: .+\n
+ RUBY_PLATFORM: .+
}x
assert_match expected, irb.context.main.irb_info.to_s
end
@@ -63,13 +90,14 @@ module TestIRB
IRB.conf[:USE_SINGLELINE] = true
IRB.conf[:VERBOSE] = false
workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace)
+ irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
IRB.conf[:MAIN_CONTEXT] = irb.context
expected = %r{
Ruby\sversion: .+\n
IRB\sversion:\sirb .+\n
- InputMethod:\sReadlineInputMethod\swith .+ and .+\n
- \.irbrc\spath: .+
+ InputMethod:\sAbstract\sInputMethod\n
+ \.irbrc\spath: .+\n
+ RUBY_PLATFORM: .+
}x
assert_match expected, irb.context.main.irb_info.to_s
end
@@ -85,12 +113,13 @@ module TestIRB
IRB.conf[:USE_SINGLELINE] = false
IRB.conf[:VERBOSE] = false
workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace)
+ irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
IRB.conf[:MAIN_CONTEXT] = irb.context
expected = %r{
Ruby\sversion: .+\n
IRB\sversion:\sirb .+\n
- InputMethod:\sReidlineInputMethod\swith\sReline\s[^ ]+(?!\sand\s.+)\n
+ InputMethod:\sAbstract\sInputMethod\n
+ RUBY_PLATFORM: .+\n
\z
}x
assert_match expected, irb.context.main.irb_info.to_s
@@ -111,12 +140,13 @@ module TestIRB
IRB.conf[:USE_SINGLELINE] = true
IRB.conf[:VERBOSE] = false
workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace)
+ irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
IRB.conf[:MAIN_CONTEXT] = irb.context
expected = %r{
Ruby\sversion: .+\n
IRB\sversion:\sirb .+\n
- InputMethod:\sReadlineInputMethod\swith\s(?~.*\sand\s.+)\n
+ InputMethod:\sAbstract\sInputMethod\n
+ RUBY_PLATFORM: .+\n
\z
}x
assert_match expected, irb.context.main.irb_info.to_s
@@ -125,5 +155,275 @@ module TestIRB
IRB.__send__(:remove_const, :IRBRC_EXT)
IRB.const_set(:IRBRC_EXT, ext_backup)
end
+
+ def test_measure
+ IRB.init_config(nil)
+ IRB.conf[:PROMPT] = {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ }
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :DEFAULT
+ IRB.conf[:MEASURE] = false
+ input = TestInputMethod.new([
+ "3\n",
+ "measure\n",
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ ])
+ c = Class.new(Object)
+ irb = IRB::Irb.new(IRB::WorkSpace.new(c.new), input)
+ irb.context.return_format = "=> %s\n"
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_match(/\A=> 3\nTIME is added\.\n=> nil\nprocessing time: .+\n=> 3\n=> nil\n=> 3\n/, out)
+ assert_empty(c.class_variables)
+ end
+
+ def test_measure_enabled_by_rc
+ IRB.init_config(nil)
+ IRB.conf[:PROMPT] = {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ }
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :DEFAULT
+ IRB.conf[:MEASURE] = true
+ input = TestInputMethod.new([
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ irb.context.return_format = "=> %s\n"
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_match(/\Aprocessing time: .+\n=> 3\n=> nil\n=> 3\n/, out)
+ end
+
+ def test_measure_enabled_by_rc_with_custom
+ IRB.init_config(nil)
+ IRB.conf[:PROMPT] = {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ }
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :DEFAULT
+ IRB.conf[:MEASURE] = true
+ IRB.conf[:MEASURE_PROC][:CUSTOM] = proc { |line, line_no, &block|
+ time = Time.now
+ result = block.()
+ puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
+ result
+ }
+ input = TestInputMethod.new([
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ irb.context.return_format = "=> %s\n"
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_match(/\Acustom processing time: .+\n=> 3\n=> nil\n=> 3\n/, out)
+ end
+
+ def test_measure_with_custom
+ IRB.init_config(nil)
+ IRB.conf[:PROMPT] = {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ }
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :DEFAULT
+ IRB.conf[:MEASURE] = false
+ IRB.conf[:MEASURE_PROC][:CUSTOM] = proc { |line, line_no, &block|
+ time = Time.now
+ result = block.()
+ puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
+ result
+ }
+ input = TestInputMethod.new([
+ "3\n",
+ "measure\n",
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ irb.context.return_format = "=> %s\n"
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_match(/\A=> 3\nCUSTOM is added\.\n=> nil\ncustom processing time: .+\n=> 3\n=> nil\n=> 3\n/, out)
+ end
+
+ def test_measure_with_proc
+ IRB.init_config(nil)
+ IRB.conf[:PROMPT] = {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> ',
+ PROMPT_N: '> '
+ }
+ }
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :DEFAULT
+ IRB.conf[:MEASURE] = false
+ input = TestInputMethod.new([
+ "3\n",
+ "measure { |context, code, line_no, &block|\n",
+ " result = block.()\n",
+ " puts 'aaa' if IRB.conf[:MEASURE]\n",
+ " result\n",
+ "}\n",
+ "3\n",
+ "measure { |context, code, line_no, &block|\n",
+ " result = block.()\n",
+ " puts 'bbb' if IRB.conf[:MEASURE]\n",
+ " result\n",
+ "}\n",
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ ])
+ c = Class.new(Object)
+ irb = IRB::Irb.new(IRB::WorkSpace.new(c.new), input)
+ irb.context.return_format = "=> %s\n"
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_match(/\A=> 3\nBLOCK is added\.\n=> nil\naaa\n=> 3\nBLOCK is added.\naaa\n=> nil\nbbb\n=> 3\n=> nil\n=> 3\n/, out)
+ assert_empty(c.class_variables)
+ end
+
+ def test_irb_source
+ IRB.init_config(nil)
+ File.write("#{@tmpdir}/a.rb", "a = 'hi'\n")
+ input = TestInputMethod.new([
+ "a = 'bug17564'\n",
+ "a\n",
+ "irb_source '#{@tmpdir}/a.rb'\n",
+ "a\n",
+ ])
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :SIMPLE
+ irb = IRB::Irb.new(IRB::WorkSpace.new(self), input)
+ IRB.conf[:MAIN_CONTEXT] = irb.context
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_pattern_list([
+ /=> "bug17564"\n/,
+ /=> "bug17564"\n/,
+ / => "hi"\n/,
+ / => nil\n/,
+ /=> "hi"\n/,
+ ], out)
+ end
+
+ def test_irb_load
+ IRB.init_config(nil)
+ File.write("#{@tmpdir}/a.rb", "a = 'hi'\n")
+ input = TestInputMethod.new([
+ "a = 'bug17564'\n",
+ "a\n",
+ "irb_load '#{@tmpdir}/a.rb'\n",
+ "a\n",
+ ])
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :SIMPLE
+ irb = IRB::Irb.new(IRB::WorkSpace.new(self), input)
+ IRB.conf[:MAIN_CONTEXT] = irb.context
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_pattern_list([
+ /=> "bug17564"\n/,
+ /=> "bug17564"\n/,
+ / => "hi"\n/,
+ / => nil\n/,
+ /=> "bug17564"\n/,
+ ], out)
+ end
+
+ def test_ls
+ input = TestInputMethod.new([
+ "ls Object.new.tap { |o| o.instance_variable_set(:@a, 1) }\n",
+ ])
+ IRB.init_config(nil)
+ workspace = IRB::WorkSpace.new(self)
+ IRB.conf[:VERBOSE] = false
+ irb = IRB::Irb.new(workspace, input)
+ IRB.conf[:MAIN_CONTEXT] = irb.context
+ irb.context.return_format = "=> %s\n"
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_match(/^instance variables:\s+@a\n/m, out)
+ end
+
+ def test_show_source
+ input = TestInputMethod.new([
+ "show_source 'IRB.conf'\n",
+ ])
+ IRB.init_config(nil)
+ workspace = IRB::WorkSpace.new(self)
+ irb = IRB::Irb.new(workspace, input)
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:MAIN_CONTEXT] = irb.context
+ irb.context.return_format = "=> %s\n"
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_match(%r[/irb\.rb], out)
+ end
+
+ def test_whereami
+ input = TestInputMethod.new([
+ "whereami\n",
+ ])
+ IRB.init_config(nil)
+ workspace = IRB::WorkSpace.new(self)
+ IRB.conf[:VERBOSE] = false
+ irb = IRB::Irb.new(workspace, input)
+ IRB.conf[:MAIN_CONTEXT] = irb.context
+ irb.context.return_format = "=> %s\n"
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_match(/^From: .+ @ line \d+ :\n/, out)
+ end
end
end
diff --git a/test/irb/test_color.rb b/test/irb/test_color.rb
index cb90d29c9d..a28ae06117 100644
--- a/test/irb/test_color.rb
+++ b/test/irb/test_color.rb
@@ -34,7 +34,6 @@ module TestIRB
'"foo#{a} #{b}"' => "#{RED}#{BOLD}\"#{CLEAR}#{RED}foo#{CLEAR}#{RED}\#{#{CLEAR}a#{RED}}#{CLEAR}#{RED} #{CLEAR}#{RED}\#{#{CLEAR}b#{RED}}#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}",
'/r#{e}g/' => "#{RED}#{BOLD}/#{CLEAR}#{RED}r#{CLEAR}#{RED}\#{#{CLEAR}e#{RED}}#{CLEAR}#{RED}g#{CLEAR}#{RED}#{BOLD}/#{CLEAR}",
"'a\nb'" => "#{RED}#{BOLD}'#{CLEAR}#{RED}a#{CLEAR}\n#{RED}b#{CLEAR}#{RED}#{BOLD}'#{CLEAR}",
- "[1]]]\u0013" => "[1]]]^S",
"%[str]" => "#{RED}#{BOLD}%[#{CLEAR}#{RED}str#{CLEAR}#{RED}#{BOLD}]#{CLEAR}",
"%Q[str]" => "#{RED}#{BOLD}%Q[#{CLEAR}#{RED}str#{CLEAR}#{RED}#{BOLD}]#{CLEAR}",
"%q[str]" => "#{RED}#{BOLD}%q[#{CLEAR}#{RED}str#{CLEAR}#{RED}#{BOLD}]#{CLEAR}",
@@ -50,7 +49,7 @@ module TestIRB
'"#{}"' => "#{RED}#{BOLD}\"#{CLEAR}#{RED}\#{#{CLEAR}#{RED}}#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}",
':"a#{}b"' => "#{YELLOW}:\"#{CLEAR}#{YELLOW}a#{CLEAR}#{YELLOW}\#{#{CLEAR}#{YELLOW}}#{CLEAR}#{YELLOW}b#{CLEAR}#{YELLOW}\"#{CLEAR}",
':"a#{ def b; end; \'c\' + "#{ :d }" }e"' => "#{YELLOW}:\"#{CLEAR}#{YELLOW}a#{CLEAR}#{YELLOW}\#{#{CLEAR} #{GREEN}def#{CLEAR} #{BLUE}#{BOLD}b#{CLEAR}; #{GREEN}end#{CLEAR}; #{RED}#{BOLD}'#{CLEAR}#{RED}c#{CLEAR}#{RED}#{BOLD}'#{CLEAR} + #{RED}#{BOLD}\"#{CLEAR}#{RED}\#{#{CLEAR} #{YELLOW}:#{CLEAR}#{YELLOW}d#{CLEAR} #{RED}}#{CLEAR}#{RED}#{BOLD}\"#{CLEAR} #{YELLOW}}#{CLEAR}#{YELLOW}e#{CLEAR}#{YELLOW}\"#{CLEAR}",
- "[__FILE__, __LINE__]" => "[#{CYAN}#{BOLD}__FILE__#{CLEAR}, #{CYAN}#{BOLD}__LINE__#{CLEAR}]",
+ "[__FILE__, __LINE__, __ENCODING__]" => "[#{CYAN}#{BOLD}__FILE__#{CLEAR}, #{CYAN}#{BOLD}__LINE__#{CLEAR}, #{CYAN}#{BOLD}__ENCODING__#{CLEAR}]",
":self" => "#{YELLOW}:#{CLEAR}#{YELLOW}self#{CLEAR}",
":class" => "#{YELLOW}:#{CLEAR}#{YELLOW}class#{CLEAR}",
"[:end, 2]" => "[#{YELLOW}:#{CLEAR}#{YELLOW}end#{CLEAR}, #{BLUE}#{BOLD}2#{CLEAR}]",
@@ -67,6 +66,7 @@ module TestIRB
"\t" => "\t", # not ^I
"foo(*%W(bar))" => "foo(*#{RED}#{BOLD}%W(#{CLEAR}#{RED}bar#{CLEAR}#{RED}#{BOLD})#{CLEAR})",
"$stdout" => "#{GREEN}#{BOLD}$stdout#{CLEAR}",
+ "__END__" => "#{GREEN}__END__#{CLEAR}",
}
# specific to Ruby 2.7+
@@ -78,6 +78,31 @@ module TestIRB
})
end
+ # specific to Ruby 3.0+
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0')
+ tests.merge!({
+ "[1]]]\u0013" => "[#{BLUE}#{BOLD}1#{CLEAR}]#{RED}#{REVERSE}]#{CLEAR}#{RED}#{REVERSE}]#{CLEAR}#{RED}#{REVERSE}^S#{CLEAR}",
+ })
+ tests.merge!({
+ "def req(true) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{RED}#{REVERSE}true#{CLEAR}) #{RED}#{REVERSE}end#{CLEAR}",
+ "nil = 1" => "#{RED}#{REVERSE}nil#{CLEAR} = #{BLUE}#{BOLD}1#{CLEAR}",
+ "alias $x $1" => "#{GREEN}alias#{CLEAR} #{GREEN}#{BOLD}$x#{CLEAR} #{RED}#{REVERSE}$1#{CLEAR}",
+ "class bad; end" => "#{GREEN}class#{CLEAR} #{RED}#{REVERSE}bad#{CLEAR}; #{GREEN}end#{CLEAR}",
+ "def req(@a) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{RED}#{REVERSE}@a#{CLEAR}) #{GREEN}end#{CLEAR}",
+ })
+ else
+ tests.merge!({
+ "[1]]]\u0013" => "[1]]]^S",
+ })
+ tests.merge!({
+ "def req(true) end" => "def req(true) end",
+ "nil = 1" => "#{CYAN}#{BOLD}nil#{CLEAR} = #{BLUE}#{BOLD}1#{CLEAR}",
+ "alias $x $1" => "#{GREEN}alias#{CLEAR} #{GREEN}#{BOLD}$x#{CLEAR} $1",
+ "class bad; end" => "#{GREEN}class#{CLEAR} bad; #{GREEN}end#{CLEAR}",
+ "def req(@a) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(@a) #{GREEN}end#{CLEAR}",
+ })
+ end
+
tests.each do |code, result|
if colorize_code_supported?
actual = with_term { IRB::Color.colorize_code(code, complete: true) }
diff --git a/test/irb/test_color_printer.rb b/test/irb/test_color_printer.rb
new file mode 100644
index 0000000000..1afc7ccf55
--- /dev/null
+++ b/test/irb/test_color_printer.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'irb/color_printer'
+require 'rubygems'
+require 'stringio'
+
+module TestIRB
+ class TestColorPrinter < Test::Unit::TestCase
+ CLEAR = "\e[0m"
+ BOLD = "\e[1m"
+ RED = "\e[31m"
+ GREEN = "\e[32m"
+ BLUE = "\e[34m"
+ CYAN = "\e[36m"
+
+ def setup
+ @get_screen_size = Reline.method(:get_screen_size)
+ Reline.instance_eval { undef :get_screen_size }
+ def Reline.get_screen_size
+ [36, 80]
+ end
+ end
+
+ def teardown
+ Reline.instance_eval { undef :get_screen_size }
+ Reline.define_singleton_method(:get_screen_size, @get_screen_size)
+ end
+
+ IRBTestColorPrinter = Struct.new(:a)
+
+ def test_color_printer
+ unless ripper_lexer_scan_supported?
+ skip 'Ripper::Lexer#scan is supported in Ruby 2.7+'
+ end
+ {
+ 1 => "#{BLUE}#{BOLD}1#{CLEAR}\n",
+ "a\nb" => %[#{RED}#{BOLD}"#{CLEAR}#{RED}a\\nb#{CLEAR}#{RED}#{BOLD}"#{CLEAR}\n],
+ IRBTestColorPrinter.new('test') => "#{GREEN}#<struct TestIRB::TestColorPrinter::IRBTestColorPrinter#{CLEAR} a#{GREEN}=#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{RED}test#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{GREEN}>#{CLEAR}\n",
+ Ripper::Lexer.new('1').scan => "[#{GREEN}#<Ripper::Lexer::Elem:#{CLEAR} on_int@1:0 END token: #{RED}#{BOLD}\"#{CLEAR}#{RED}1#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{GREEN}>#{CLEAR}]\n",
+ Class.new{define_method(:pretty_print){|q| q.text("[__FILE__, __LINE__, __ENCODING__]")}}.new => "[#{CYAN}#{BOLD}__FILE__#{CLEAR}, #{CYAN}#{BOLD}__LINE__#{CLEAR}, #{CYAN}#{BOLD}__ENCODING__#{CLEAR}]\n",
+ }.each do |object, result|
+ actual = with_term { IRB::ColorPrinter.pp(object, '') }
+ assert_equal(result, actual, "Case: IRB::ColorPrinter.pp(#{object.inspect}, '')")
+ end
+ end
+
+ private
+
+ def ripper_lexer_scan_supported?
+ Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
+ end
+
+ def with_term
+ stdout = $stdout
+ io = StringIO.new
+ def io.tty?; true; end
+ $stdout = io
+
+ env = ENV.to_h.dup
+ ENV['TERM'] = 'xterm-256color'
+
+ yield
+ ensure
+ $stdout = stdout
+ ENV.replace(env) if env
+ end
+ end
+end
diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb
index a765bbf3a5..535690ae22 100644
--- a/test/irb/test_completion.rb
+++ b/test/irb/test_completion.rb
@@ -47,5 +47,41 @@ module TestIRB
assert_include candidates, word
end
end
+
+ def test_complete_predicate?
+ candidates = IRB::InputCompletor.retrieve_completion_data("1.posi", bind: binding)
+ assert_include candidates, '1.positive?'
+
+ namespace = IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true)
+ assert_equal "Integer.positive?", namespace
+ end
+
+ def test_complete_require
+ candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "")
+ %w['irb/init 'irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
+ # Test cache
+ candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "")
+ %w['irb/init 'irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
+ end
+
+ def test_complete_require_relative
+ candidates = Dir.chdir(__dir__ + "/../..") do
+ IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "")
+ end
+ %w['lib/irb/init 'lib/irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
+ # Test cache
+ candidates = Dir.chdir(__dir__ + "/../..") do
+ IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "")
+ end
+ %w['lib/irb/init 'lib/irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
+ end
end
end
diff --git a/test/irb/test_context.rb b/test/irb/test_context.rb
index fa628bba46..71e8ad1c0d 100644
--- a/test/irb/test_context.rb
+++ b/test/irb/test_context.rb
@@ -42,6 +42,17 @@ module TestIRB
IRB.conf[:VERBOSE] = false
workspace = IRB::WorkSpace.new(Object.new)
@context = IRB::Context.new(nil, workspace, TestInputMethod.new)
+
+ @get_screen_size = Reline.method(:get_screen_size)
+ Reline.instance_eval { undef :get_screen_size }
+ def Reline.get_screen_size
+ [36, 80]
+ end
+ end
+
+ def teardown
+ Reline.instance_eval { undef :get_screen_size }
+ Reline.define_singleton_method(:get_screen_size, @get_screen_size)
end
def test_last_value
@@ -68,6 +79,7 @@ module TestIRB
end
def test_evaluate_with_encoding_error_without_lineno
+ skip if RUBY_ENGINE == 'truffleruby'
assert_raise_with_message(EncodingError, /invalid symbol/) {
@context.evaluate(%q[{"\xAE": 1}], 1)
# The backtrace of this invalid encoding hash doesn't contain lineno.
@@ -75,12 +87,14 @@ module TestIRB
end
def test_evaluate_with_onigmo_warning
+ skip if RUBY_ENGINE == 'truffleruby'
assert_warning("(irb):1: warning: character class has duplicated range: /[aa]/\n") do
@context.evaluate('/[aa]/', 1)
end
end
def test_eval_input
+ skip if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
input = TestInputMethod.new([
"raise 'Foo'\n",
@@ -93,7 +107,7 @@ module TestIRB
irb.eval_input
end
assert_empty err
- assert_pattern_list([:*, /RuntimeError \(.*Foo.*\).*\n/,
+ assert_pattern_list([:*, /\(irb\):1:in `<main>': Foo \(RuntimeError\)\n/,
:*, /#<RuntimeError: Foo>\n/,
:*, /0$/,
:*, /0$/,
@@ -102,17 +116,43 @@ module TestIRB
$VERBOSE = verbose
end
- def test_eval_object_without_inspect_method
- verbose, $VERBOSE = $VERBOSE, nil
+ def test_eval_input_raise2x
+ skip if RUBY_ENGINE == 'truffleruby'
input = TestInputMethod.new([
- "BasicObject.new\n",
+ "raise 'Foo'\n",
+ "raise 'Bar'\n",
+ "_\n",
])
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
out, err = capture_output do
irb.eval_input
end
assert_empty err
- assert(/\(Object doesn't support #inspect\)\n(=> )?\n/, out)
+ assert_pattern_list([
+ :*, /\(irb\):1:in `<main>': Foo \(RuntimeError\)\n/,
+ :*, /\(irb\):2:in `<main>': Bar \(RuntimeError\)\n/,
+ :*, /#<RuntimeError: Bar>\n/,
+ ], out)
+ end
+
+ def test_eval_object_without_inspect_method
+ verbose, $VERBOSE = $VERBOSE, nil
+ all_assertions do |all|
+ IRB::Inspector::INSPECTORS.invert.each_value do |mode|
+ all.for(mode) do
+ input = TestInputMethod.new([
+ "[BasicObject.new, Class.new]\n",
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ irb.context.inspect_mode = mode
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_match(/\(Object doesn't support #inspect\)\n(=> )?\n/, out)
+ end
+ end
+ end
ensure
$VERBOSE = verbose
end
@@ -228,37 +268,33 @@ module TestIRB
irb.context.echo = true
irb.context.echo_on_assignment = false
- irb.context.omit_on_assignment = true
out, err = capture_io do
irb.eval_input
end
assert_empty err
- assert_equal("=> #{value.inspect}\n", out)
+ assert_equal("=> \n#{value.pretty_inspect}", out)
input.reset
irb.context.echo = true
- irb.context.echo_on_assignment = true
- irb.context.omit_on_assignment = true
+ irb.context.echo_on_assignment = :truncate
out, err = capture_io do
irb.eval_input
end
assert_empty err
- assert_equal("=> #{value.inspect[0..(input.winsize.last - 9)]}...\e[0m\n=> #{value.inspect}\n", out)
+ assert_equal("=> \n#{value.pretty_inspect[0..3]}...\n=> \n#{value.pretty_inspect}", out)
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = true
- irb.context.omit_on_assignment = false
out, err = capture_io do
irb.eval_input
end
assert_empty err
- assert_equal("=> #{value.inspect}\n=> #{value.inspect}\n", out)
+ assert_equal("=> \n#{value.pretty_inspect}=> \n#{value.pretty_inspect}", out)
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = false
- irb.context.omit_on_assignment = true
out, err = capture_io do
irb.eval_input
end
@@ -267,8 +303,7 @@ module TestIRB
input.reset
irb.context.echo = false
- irb.context.echo_on_assignment = true
- irb.context.omit_on_assignment = true
+ irb.context.echo_on_assignment = :truncate
out, err = capture_io do
irb.eval_input
end
@@ -278,7 +313,6 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = true
- irb.context.omit_on_assignment = false
out, err = capture_io do
irb.eval_input
end
@@ -298,7 +332,6 @@ module TestIRB
irb.context.echo = true
irb.context.echo_on_assignment = false
- irb.context.omit_on_assignment = true
out, err = capture_io do
irb.eval_input
end
@@ -308,8 +341,7 @@ module TestIRB
input.reset
irb.context.echo = true
- irb.context.echo_on_assignment = true
- irb.context.omit_on_assignment = true
+ irb.context.echo_on_assignment = :truncate
out, err = capture_io do
irb.eval_input
end
@@ -320,7 +352,6 @@ module TestIRB
input.reset
irb.context.echo = true
irb.context.echo_on_assignment = true
- irb.context.omit_on_assignment = false
out, err = capture_io do
irb.eval_input
end
@@ -331,7 +362,6 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = false
- irb.context.omit_on_assignment = true
out, err = capture_io do
irb.eval_input
end
@@ -341,8 +371,7 @@ module TestIRB
input.reset
irb.context.echo = false
- irb.context.echo_on_assignment = true
- irb.context.omit_on_assignment = true
+ irb.context.echo_on_assignment = :truncate
out, err = capture_io do
irb.eval_input
end
@@ -353,7 +382,6 @@ module TestIRB
input.reset
irb.context.echo = false
irb.context.echo_on_assignment = true
- irb.context.omit_on_assignment = false
out, err = capture_io do
irb.eval_input
end
@@ -370,26 +398,22 @@ module TestIRB
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
assert(irb.context.echo?, "echo? should be true by default")
- assert(irb.context.echo_on_assignment?, "echo_on_assignment? should be true by default")
- assert(irb.context.omit_on_assignment?, "omit_on_assignment? should be true by default")
+ assert_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default")
# Explicitly set :ECHO to false
IRB.conf[:ECHO] = false
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
refute(irb.context.echo?, "echo? should be false when IRB.conf[:ECHO] is set to false")
- assert(irb.context.echo_on_assignment?, "echo_on_assignment? should be true by default")
- assert(irb.context.omit_on_assignment?, "omit_on_assignment? should be true by default")
+ assert_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default")
# Explicitly set :ECHO_ON_ASSIGNMENT to true
IRB.conf[:ECHO] = nil
IRB.conf[:ECHO_ON_ASSIGNMENT] = false
- IRB.conf[:OMIT_ON_ASSIGNMENT] = false
irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
assert(irb.context.echo?, "echo? should be true by default")
refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to false")
- refute(irb.context.omit_on_assignment?, "omit_on_assignment? should be false when IRB.conf[:OMIT_ON_ASSIGNMENT] is set to false")
end
def test_multiline_output_on_default_inspector
@@ -422,5 +446,152 @@ module TestIRB
assert_equal("=> abc\ndef\n",
out)
end
+
+ def test_eval_input_with_exception
+ skip if RUBY_ENGINE == 'truffleruby'
+ verbose, $VERBOSE = $VERBOSE, nil
+ input = TestInputMethod.new([
+ "def hoge() fuga; end; def fuga() raise; end; hoge\n",
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
+ expected = [
+ :*, /Traceback \(most recent call last\):\n/,
+ :*, /\t 2: from \(irb\):1:in `<main>'\n/,
+ :*, /\t 1: from \(irb\):1:in `hoge'\n/,
+ :*, /\(irb\):1:in `fuga': unhandled exception\n/,
+ ]
+ else
+ expected = [
+ :*, /\(irb\):1:in `fuga': unhandled exception\n/,
+ :*, /\tfrom \(irb\):1:in `hoge'\n/,
+ :*, /\tfrom \(irb\):1:in `<main>'\n/,
+ ]
+ end
+ assert_pattern_list(expected, out)
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def test_eval_input_with_invalid_byte_sequence_exception
+ skip if RUBY_ENGINE == 'truffleruby'
+ verbose, $VERBOSE = $VERBOSE, nil
+ input = TestInputMethod.new([
+ %Q{def hoge() fuga; end; def fuga() raise "A\\xF3B"; end; hoge\n},
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
+ expected = [
+ :*, /Traceback \(most recent call last\):\n/,
+ :*, /\t 2: from \(irb\):1:in `<main>'\n/,
+ :*, /\t 1: from \(irb\):1:in `hoge'\n/,
+ :*, /\(irb\):1:in `fuga': A\\xF3B \(RuntimeError\)\n/,
+ ]
+ else
+ expected = [
+ :*, /\(irb\):1:in `fuga': A\\xF3B \(RuntimeError\)\n/,
+ :*, /\tfrom \(irb\):1:in `hoge'\n/,
+ :*, /\tfrom \(irb\):1:in `<main>'\n/,
+ ]
+ end
+ assert_pattern_list(expected, out)
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def test_eval_input_with_long_exception
+ skip if RUBY_ENGINE == 'truffleruby'
+ verbose, $VERBOSE = $VERBOSE, nil
+ nesting = 20
+ generated_code = ''
+ nesting.times do |i|
+ generated_code << "def a#{i}() a#{i + 1}; end; "
+ end
+ generated_code << "def a#{nesting}() raise; end; a0\n"
+ input = TestInputMethod.new([
+ generated_code
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
+ expected = [
+ :*, /Traceback \(most recent call last\):\n/,
+ :*, /\t... 5 levels...\n/,
+ :*, /\t16: from \(irb\):1:in `a4'\n/,
+ :*, /\t15: from \(irb\):1:in `a5'\n/,
+ :*, /\t14: from \(irb\):1:in `a6'\n/,
+ :*, /\t13: from \(irb\):1:in `a7'\n/,
+ :*, /\t12: from \(irb\):1:in `a8'\n/,
+ :*, /\t11: from \(irb\):1:in `a9'\n/,
+ :*, /\t10: from \(irb\):1:in `a10'\n/,
+ :*, /\t 9: from \(irb\):1:in `a11'\n/,
+ :*, /\t 8: from \(irb\):1:in `a12'\n/,
+ :*, /\t 7: from \(irb\):1:in `a13'\n/,
+ :*, /\t 6: from \(irb\):1:in `a14'\n/,
+ :*, /\t 5: from \(irb\):1:in `a15'\n/,
+ :*, /\t 4: from \(irb\):1:in `a16'\n/,
+ :*, /\t 3: from \(irb\):1:in `a17'\n/,
+ :*, /\t 2: from \(irb\):1:in `a18'\n/,
+ :*, /\t 1: from \(irb\):1:in `a19'\n/,
+ :*, /\(irb\):1:in `a20': unhandled exception\n/,
+ ]
+ else
+ expected = [
+ :*, /\(irb\):1:in `a20': unhandled exception\n/,
+ :*, /\tfrom \(irb\):1:in `a19'\n/,
+ :*, /\tfrom \(irb\):1:in `a18'\n/,
+ :*, /\tfrom \(irb\):1:in `a17'\n/,
+ :*, /\tfrom \(irb\):1:in `a16'\n/,
+ :*, /\tfrom \(irb\):1:in `a15'\n/,
+ :*, /\tfrom \(irb\):1:in `a14'\n/,
+ :*, /\tfrom \(irb\):1:in `a13'\n/,
+ :*, /\tfrom \(irb\):1:in `a12'\n/,
+ :*, /\tfrom \(irb\):1:in `a11'\n/,
+ :*, /\tfrom \(irb\):1:in `a10'\n/,
+ :*, /\tfrom \(irb\):1:in `a9'\n/,
+ :*, /\tfrom \(irb\):1:in `a8'\n/,
+ :*, /\tfrom \(irb\):1:in `a7'\n/,
+ :*, /\tfrom \(irb\):1:in `a6'\n/,
+ :*, /\tfrom \(irb\):1:in `a5'\n/,
+ :*, /\tfrom \(irb\):1:in `a4'\n/,
+ :*, /\t... 5 levels...\n/,
+ ]
+ end
+ assert_pattern_list(expected, out)
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def test_lineno
+ input = TestInputMethod.new([
+ "\n",
+ "__LINE__\n",
+ "__LINE__\n",
+ "\n",
+ "\n",
+ "__LINE__\n",
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_pattern_list([
+ :*, /\b2\n/,
+ :*, /\b3\n/,
+ :*, /\b6\n/,
+ ], out)
+ end
end
end
diff --git a/test/irb/test_history.rb b/test/irb/test_history.rb
index 1ba4d2e515..81b7fe8679 100644
--- a/test/irb/test_history.rb
+++ b/test/irb/test_history.rb
@@ -127,6 +127,37 @@ module TestIRB
INPUT
end
+ def test_history_concurrent_use
+ omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
+ IRB.conf[:SAVE_HISTORY] = 1
+ assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT) do |history_file|
+ exit
+ 5
+ exit
+ EXPECTED_HISTORY
+ 1
+ 2
+ 3
+ 4
+ INITIAL_HISTORY
+ 5
+ exit
+ INPUT
+ assert_history(<<~EXPECTED_HISTORY2, <<~INITIAL_HISTORY2, <<~INPUT2)
+ exit
+ EXPECTED_HISTORY2
+ 1
+ 2
+ 3
+ 4
+ INITIAL_HISTORY2
+ 5
+ exit
+ INPUT2
+ File.utime(File.atime(history_file), File.mtime(history_file) + 2, history_file)
+ end
+ end
+
private
def assert_history(expected_history, initial_irb_history, input)
@@ -144,6 +175,11 @@ module TestIRB
io = TestInputMethod.new
io.class::HISTORY.clear
io.load_history
+ if block_given?
+ history = io.class::HISTORY.dup
+ yield IRB.rc_file("_history")
+ io.class::HISTORY.replace(history)
+ end
io.class::HISTORY.concat(input.split)
io.save_history
diff --git a/test/irb/test_init.rb b/test/irb/test_init.rb
index 83b4b5a543..2c50b5da3a 100644
--- a/test/irb/test_init.rb
+++ b/test/irb/test_init.rb
@@ -64,6 +64,12 @@ module TestIRB
ENV["IRBRC"] = backup_irbrc
end
+ def test_recovery_sigint
+ bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
+ status = assert_in_out_err(bundle_exec + %w[-W0 -rirb -e binding.irb;loop{Process.kill("SIGINT",$$)} -- -f --], "exit\n", //, //)
+ Process.kill("SIGKILL", status.pid) if !status.exited? && !status.stopped? && !status.signaled?
+ end
+
private
def with_argv(argv)
diff --git a/test/irb/test_raise_no_backtrace_exception.rb b/test/irb/test_raise_no_backtrace_exception.rb
index 2174600082..40ee0c52bf 100644
--- a/test/irb/test_raise_no_backtrace_exception.rb
+++ b/test/irb/test_raise_no_backtrace_exception.rb
@@ -4,6 +4,7 @@ require 'test/unit'
module TestIRB
class TestRaiseNoBacktraceException < Test::Unit::TestCase
def test_raise_exception
+ skip if RUBY_ENGINE == 'truffleruby'
bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<-IRB, /Exception: foo/, [])
e = Exception.new("foo")
@@ -12,5 +13,13 @@ module TestIRB
raise e
IRB
end
+
+ def test_raise_exception_with_invalid_byte_sequence
+ skip if RUBY_ENGINE == 'truffleruby'
+ bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
+ assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<~IRB, /A\\xF3B \(StandardError\)/, [])
+ raise StandardError, "A\\xf3B"
+ IRB
+ end
end
end
diff --git a/test/irb/test_ruby_lex.rb b/test/irb/test_ruby_lex.rb
index 14b43f5718..556afbd776 100644
--- a/test/irb/test_ruby_lex.rb
+++ b/test/irb/test_ruby_lex.rb
@@ -7,7 +7,7 @@ module TestIRB
class TestRubyLex < Test::Unit::TestCase
Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :nesting_level)
- class MockIO
+ class MockIO_AutoIndent
def initialize(params, &assertion)
@params = params
@assertion = assertion
@@ -25,7 +25,7 @@ module TestIRB
byte_pointer = lines.last.length
ruby_lex = RubyLex.new()
- io = MockIO.new([lines, last_line_index, byte_pointer, add_new_line]) do |auto_indent|
+ io = MockIO_AutoIndent.new([lines, last_line_index, byte_pointer, add_new_line]) do |auto_indent|
error_message = "Calculated the wrong number of spaces for:\n #{lines.join("\n")}"
assert_equal(correct_space_count, auto_indent, error_message)
end
@@ -136,6 +136,20 @@ module TestIRB
end
end
+ def test_endless_range_at_end_of_line
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6.0')
+ skip 'Endless range is available in 2.6.0 or later'
+ end
+ input_with_prompt = [
+ PromptRow.new('001:0: :> ', %q(a = 3..)),
+ PromptRow.new('002:0: :* ', %q()),
+ ]
+
+ lines = input_with_prompt.map(&:content)
+ expected_prompt_list = input_with_prompt.map(&:prompt)
+ assert_dynamic_prompt(lines, expected_prompt_list)
+ end
+
def test_incomplete_coding_magic_comment
input_with_correct_indents = [
Row.new(%q(#coding:u), nil, 0),
@@ -233,6 +247,8 @@ module TestIRB
Row.new(%q( def bar0() = 3), nil, 2),
Row.new(%q( def bar1(a) = a), nil, 2),
Row.new(%q( def bar2(a, b) = a + b), nil, 2),
+ Row.new(%q( def bar3() = :s), nil, 2),
+ Row.new(%q( def bar4() = Time.now), nil, 2),
Row.new(%q(end), 0, 0),
]
@@ -260,5 +276,311 @@ module TestIRB
assert_nesting_level(lines, row.nesting_level)
end
end
+
+ def test_corresponding_syntax_to_keyword_do_in_class
+ input_with_correct_indents = [
+ Row.new(%q(class C), nil, 2, 1),
+ Row.new(%q( while method_name do), nil, 4, 2),
+ Row.new(%q( 3), nil, 4, 2),
+ Row.new(%q( end), 2, 2, 1),
+ Row.new(%q( foo do), nil, 4, 2),
+ Row.new(%q( 3), nil, 4, 2),
+ Row.new(%q( end), 2, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_corresponding_syntax_to_keyword_do
+ input_with_correct_indents = [
+ Row.new(%q(while i > 0), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(while true), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(while ->{i > 0}.call), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(while ->{true}.call), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(while i > 0 do), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(while true do), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(while ->{i > 0}.call do), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(while ->{true}.call do), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(foo do), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(foo true do), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(foo ->{true} do), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ Row.new(%q(foo ->{i > 0} do), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_corresponding_syntax_to_keyword_for
+ input_with_correct_indents = [
+ Row.new(%q(for i in [1]), nil, 2, 1),
+ Row.new(%q( puts i), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_corresponding_syntax_to_keyword_for_with_do
+ input_with_correct_indents = [
+ Row.new(%q(for i in [1] do), nil, 2, 1),
+ Row.new(%q( puts i), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_bracket_corresponding_to_times
+ input_with_correct_indents = [
+ Row.new(%q(3.times { |i|), nil, 2, 1),
+ Row.new(%q( puts i), nil, 2, 1),
+ Row.new(%q(}), 0, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_do_corresponding_to_times
+ input_with_correct_indents = [
+ Row.new(%q(3.times do |i|), nil, 2, 1),
+ #Row.new(%q( puts i), nil, 2, 1),
+ #Row.new(%q(end), 0, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_bracket_corresponding_to_loop
+ input_with_correct_indents = [
+ Row.new(%q(loop {), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(}), 0, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_do_corresponding_to_loop
+ input_with_correct_indents = [
+ Row.new(%q(loop do), nil, 2, 1),
+ Row.new(%q( 3), nil, 2, 1),
+ Row.new(%q(end), 0, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_heredoc_with_indent
+ input_with_correct_indents = [
+ Row.new(%q(<<~Q), nil, 0, 0),
+ Row.new(%q({), nil, 0, 0),
+ Row.new(%q( #), nil, 0, 0),
+ Row.new(%q(}), nil, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_oneliner_def_in_multiple_lines
+ input_with_correct_indents = [
+ Row.new(%q(def a()=[), nil, 4, 2),
+ Row.new(%q( 1,), nil, 4, 1),
+ Row.new(%q(].), 0, 0, 0),
+ Row.new(%q(to_s), nil, 0, 0),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ def test_broken_heredoc
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
+ skip 'This test needs Ripper::Lexer#scan to take broken tokens'
+ end
+ input_with_correct_indents = [
+ Row.new(%q(def foo), nil, 2, 1),
+ Row.new(%q( <<~Q), nil, 2, 1),
+ Row.new(%q( Qend), nil, 2, 1),
+ ]
+
+ lines = []
+ input_with_correct_indents.each do |row|
+ lines << row.content
+ assert_indenting(lines, row.current_line_spaces, false)
+ assert_indenting(lines, row.new_line_spaces, true)
+ assert_nesting_level(lines, row.nesting_level)
+ end
+ end
+
+ PromptRow = Struct.new(:prompt, :content)
+
+ class MockIO_DynamicPrompt
+ def initialize(params, &assertion)
+ @params = params
+ @assertion = assertion
+ end
+
+ def dynamic_prompt(&block)
+ result = block.call(@params)
+ @assertion.call(result)
+ end
+ end
+
+ def assert_dynamic_prompt(lines, expected_prompt_list)
+ skip if RUBY_ENGINE == 'truffleruby'
+ ruby_lex = RubyLex.new()
+ io = MockIO_DynamicPrompt.new(lines) do |prompt_list|
+ error_message = <<~EOM
+ Expected dynamic prompt:
+ #{expected_prompt_list.join("\n")}
+
+ Actual dynamic prompt:
+ #{prompt_list.join("\n")}
+ EOM
+ assert_equal(expected_prompt_list, prompt_list, error_message)
+ end
+ ruby_lex.set_prompt do |ltype, indent, continue, line_no|
+ '%03d:%01d:%1s:%s ' % [line_no, indent, ltype, continue ? '*' : '>']
+ end
+ ruby_lex.set_input(io)
+ end
+
+ def test_dyanmic_prompt
+ input_with_prompt = [
+ PromptRow.new('001:1: :* ', %q(def hoge)),
+ PromptRow.new('002:1: :* ', %q( 3)),
+ PromptRow.new('003:0: :> ', %q(end)),
+ ]
+
+ lines = input_with_prompt.map(&:content)
+ expected_prompt_list = input_with_prompt.map(&:prompt)
+ assert_dynamic_prompt(lines, expected_prompt_list)
+ end
+
+ def test_dyanmic_prompt_with_blank_line
+ input_with_prompt = [
+ PromptRow.new('001:0:]:* ', %q(%w[)),
+ PromptRow.new('002:0:]:* ', %q()),
+ PromptRow.new('003:0: :> ', %q(])),
+ ]
+
+ lines = input_with_prompt.map(&:content)
+ expected_prompt_list = input_with_prompt.map(&:prompt)
+ assert_dynamic_prompt(lines, expected_prompt_list)
+ end
+
+ def test_broken_percent_literal
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
+ skip 'This test needs Ripper::Lexer#scan to take broken tokens'
+ end
+
+ tokens = RubyLex.ripper_lex_without_warning('%wwww')
+ pos_to_index = {}
+ tokens.each_with_index { |t, i|
+ assert_nil(pos_to_index[t[0]], "There is already another token in the position of #{t.inspect}.")
+ pos_to_index[t[0]] = i
+ }
+ end
+
+ def test_broken_percent_literal_in_method
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
+ skip 'This test needs Ripper::Lexer#scan to take broken tokens'
+ end
+
+ tokens = RubyLex.ripper_lex_without_warning(<<~EOC.chomp)
+ def foo
+ %wwww
+ end
+ EOC
+ pos_to_index = {}
+ tokens.each_with_index { |t, i|
+ assert_nil(pos_to_index[t[0]], "There is already another token in the position of #{t.inspect}.")
+ pos_to_index[t[0]] = i
+ }
+ end
end
end
diff --git a/test/irb/test_workspace.rb b/test/irb/test_workspace.rb
index 15c77315a8..f028fc3aa2 100644
--- a/test/irb/test_workspace.rb
+++ b/test/irb/test_workspace.rb
@@ -9,6 +9,7 @@ require 'irb/color'
module TestIRB
class TestWorkSpace < Test::Unit::TestCase
def test_code_around_binding
+ IRB.conf[:USE_COLORIZE] = false
Tempfile.create('irb') do |f|
code = <<~RUBY
# 1
@@ -33,6 +34,8 @@ module TestIRB
EOS
end
+ ensure
+ IRB.conf.delete(:USE_COLORIZE)
end
def test_code_around_binding_with_existing_unreadable_file
@@ -52,6 +55,7 @@ module TestIRB
end
def test_code_around_binding_with_script_lines__
+ IRB.conf[:USE_COLORIZE] = false
with_script_lines do |script_lines|
Tempfile.create('irb') do |f|
code = "IRB::WorkSpace.new(binding)\n"
@@ -67,6 +71,8 @@ module TestIRB
EOS
end
end
+ ensure
+ IRB.conf.delete(:USE_COLORIZE)
end
def test_code_around_binding_on_irb
diff --git a/test/irb/yamatanooroti/test_rendering.rb b/test/irb/yamatanooroti/test_rendering.rb
new file mode 100644
index 0000000000..8f55b38a93
--- /dev/null
+++ b/test/irb/yamatanooroti/test_rendering.rb
@@ -0,0 +1,165 @@
+require 'irb'
+
+begin
+ require 'yamatanooroti'
+
+ class IRB::TestRendering < Yamatanooroti::TestCase
+ def setup
+ @pwd = Dir.pwd
+ suffix = '%010d' % Random.rand(0..65535)
+ @tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_irb_#{$$}_#{suffix}")
+ begin
+ Dir.mkdir(@tmpdir)
+ rescue Errno::EEXIST
+ FileUtils.rm_rf(@tmpdir)
+ Dir.mkdir(@tmpdir)
+ end
+ @irbrc_backup = ENV['IRBRC']
+ @irbrc_file = ENV['IRBRC'] = File.join(@tmpdir, 'temporaty_irbrc')
+ File.unlink(@irbrc_file) if File.exist?(@irbrc_file)
+ end
+
+ def teardown
+ FileUtils.rm_rf(@tmpdir)
+ ENV['IRBRC'] = @irbrc_backup
+ ENV.delete('RELINE_TEST_PROMPT') if ENV['RELINE_TEST_PROMPT']
+ end
+
+ def test_launch
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib -I#{@pwd}/../reline/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write(<<~EOC)
+ 'Hello, World!'
+ EOC
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001:0> 'Hello, World!'
+ => "Hello, World!"
+ irb(main):002:0>
+ EOC
+ end
+
+ def test_multiline_paste
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib -I#{@pwd}/../reline/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write(<<~EOC)
+ class A
+ def inspect; '#<A>'; end
+ def a; self; end
+ def b; true; end
+ end
+
+ a = A.new
+
+ a
+ .a
+ .b
+ EOC
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001:1* class A
+ irb(main):002:1* def inspect; '#<A>'; end
+ irb(main):003:1* def a; self; end
+ irb(main):004:1* def b; true; end
+ irb(main):005:0> end
+ => :b
+ irb(main):006:0>
+ irb(main):007:0> a = A.new
+ => #<A>
+ irb(main):008:0>
+ irb(main):009:0> a
+ irb(main):010:0> .a
+ irb(main):011:0> .b
+ => true
+ irb(main):012:0>
+ EOC
+ end
+
+ def test_evaluate_each_toplevel_statement_by_multiline_paste
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib -I#{@pwd}/../reline/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write(<<~EOC)
+ class A
+ def inspect; '#<A>'; end
+ def b; self; end
+ def c; true; end
+ end
+
+ a = A.new
+
+ a
+ .b
+ # aaa
+ .c
+
+ (a)
+ &.b()
+
+
+ class A def b; self; end; def c; true; end; end;
+ a = A.new
+ a
+ .b
+ # aaa
+ .c
+ (a)
+ &.b()
+ EOC
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001:1* class A
+ irb(main):002:1* def inspect; '#<A>'; end
+ irb(main):003:1* def b; self; end
+ irb(main):004:1* def c; true; end
+ irb(main):005:0> end
+ => :c
+ irb(main):006:0>
+ irb(main):007:0> a = A.new
+ => #<A>
+ irb(main):008:0>
+ irb(main):009:0> a
+ irb(main):010:0> .b
+ irb(main):011:0> # aaa
+ irb(main):012:0> .c
+ => true
+ irb(main):013:0>
+ irb(main):014:0> (a)
+ irb(main):015:0> &.b()
+ => #<A>
+ irb(main):016:0>
+ irb(main):017:0>
+ irb(main):018:0> class A def b; self; end; def c; true; end; end;
+ => :c
+ irb(main):019:0> a = A.new
+ => #<A>
+ irb(main):020:0> a
+ irb(main):021:0> .b
+ irb(main):022:0> # aaa
+ irb(main):023:0> .c
+ => true
+ irb(main):024:0> (a)
+ irb(main):025:0> &.b()
+ => #<A>
+ irb(main):026:0>
+ EOC
+ end
+
+ private def write_irbrc(content)
+ File.open(@irbrc_file, 'w') do |f|
+ f.write content
+ end
+ end
+ end
+rescue LoadError, NameError
+ # On Ruby repository, this test suit doesn't run because Ruby repo doesn't
+ # have the yamatanooroti gem.
+end
diff --git a/test/json/fixtures/fail29.json b/test/json/fixtures/fail29.json
new file mode 100644
index 0000000000..98232c64fc
--- /dev/null
+++ b/test/json/fixtures/fail29.json
@@ -0,0 +1 @@
+{
diff --git a/test/json/fixtures/fail30.json b/test/json/fixtures/fail30.json
new file mode 100644
index 0000000000..558ed37d93
--- /dev/null
+++ b/test/json/fixtures/fail30.json
@@ -0,0 +1 @@
+[
diff --git a/test/json/fixtures/fail31.json b/test/json/fixtures/fail31.json
new file mode 100644
index 0000000000..70773e47f7
--- /dev/null
+++ b/test/json/fixtures/fail31.json
@@ -0,0 +1 @@
+[1, 2, 3,
diff --git a/test/json/fixtures/fail32.json b/test/json/fixtures/fail32.json
new file mode 100644
index 0000000000..b18d550ca5
--- /dev/null
+++ b/test/json/fixtures/fail32.json
@@ -0,0 +1 @@
+{"foo": "bar"
diff --git a/test/json/json_addition_test.rb b/test/json/json_addition_test.rb
index 61625f89e2..e95ace8375 100644
--- a/test/json/json_addition_test.rb
+++ b/test/json/json_addition_test.rb
@@ -195,9 +195,5 @@ class JSONAdditionTest < Test::Unit::TestCase
def test_set
s = Set.new([:a, :b, :c, :a])
assert_equal s, JSON.parse(JSON(s), :create_additions => true)
- ss = SortedSet.new([:d, :b, :a, :c])
- ss_again = JSON.parse(JSON(ss), :create_additions => true)
- assert_kind_of ss.class, ss_again
- assert_equal ss, ss_again
end
end
diff --git a/test/json/json_common_interface_test.rb b/test/json/json_common_interface_test.rb
index 53f335ed3b..9148b78c8b 100644
--- a/test/json/json_common_interface_test.rb
+++ b/test/json/json_common_interface_test.rb
@@ -123,4 +123,47 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
assert_equal @json, JSON(@hash)
assert_equal @hash, JSON(@json)
end
+
+ def test_load_file
+ test_load_shared(:load_file)
+ end
+
+ def test_load_file!
+ test_load_shared(:load_file!)
+ end
+
+ def test_load_file_with_option
+ test_load_file_with_option_shared(:load_file)
+ end
+
+ def test_load_file_with_option!
+ test_load_file_with_option_shared(:load_file!)
+ end
+
+ private
+
+ def test_load_shared(method_name)
+ temp_file_containing(@json) do |filespec|
+ assert_equal JSON.public_send(method_name, filespec), @hash
+ end
+ end
+
+ def test_load_file_with_option_shared(method_name)
+ temp_file_containing(@json) do |filespec|
+ parsed_object = JSON.public_send(method_name, filespec, symbolize_names: true)
+ key_classes = parsed_object.keys.map(&:class)
+ assert_include(key_classes, Symbol)
+ assert_not_include(key_classes, String)
+ end
+ end
+
+ def temp_file_containing(text, file_prefix = '')
+ raise "This method must be called with a code block." unless block_given?
+
+ Tempfile.create(file_prefix) do |file|
+ file << text
+ file.close
+ yield file.path
+ end
+ end
end
diff --git a/test/json/json_fixtures_test.rb b/test/json/json_fixtures_test.rb
index 01954fe707..845abb4867 100644
--- a/test/json/json_fixtures_test.rb
+++ b/test/json/json_fixtures_test.rb
@@ -3,13 +3,14 @@ require 'test_helper'
class JSONFixturesTest < Test::Unit::TestCase
def setup
- fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}.json')
+ fixtures = File.join(File.dirname(__FILE__), 'fixtures/{fail,pass}*.json')
passed, failed = Dir[fixtures].partition { |f| f['pass'] }
@passed = passed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
@failed = failed.inject([]) { |a, f| a << [ f, File.read(f) ] }.sort
end
def test_passing
+ verbose_bak, $VERBOSE = $VERBOSE, nil
for name, source in @passed
begin
assert JSON.parse(source),
@@ -19,6 +20,8 @@ class JSONFixturesTest < Test::Unit::TestCase
raise e
end
end
+ ensure
+ $VERBOSE = verbose_bak
end
def test_failing
@@ -29,4 +32,9 @@ class JSONFixturesTest < Test::Unit::TestCase
end
end
end
+
+ def test_sanity
+ assert(@passed.size > 5)
+ assert(@failed.size > 20)
+ end
end
diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb
index ee19fa5e6c..f31b6b290e 100644
--- a/test/json/json_generator_test.rb
+++ b/test/json/json_generator_test.rb
@@ -48,36 +48,6 @@ EOT
$VERBOSE = v
end
- def test_remove_const_segv
- return if RUBY_ENGINE == 'jruby'
- stress = GC.stress
- const = JSON::SAFE_STATE_PROTOTYPE.dup
-
- bignum_too_long_to_embed_as_string = 1234567890123456789012345
- expect = bignum_too_long_to_embed_as_string.to_s
- GC.stress = true
-
- 10.times do |i|
- tmp = bignum_too_long_to_embed_as_string.to_json
- raise "'\#{expect}' is expected, but '\#{tmp}'" unless tmp == expect
- end
-
- silence do
- JSON.const_set :SAFE_STATE_PROTOTYPE, nil
- end
-
- 10.times do |i|
- assert_raise TypeError do
- bignum_too_long_to_embed_as_string.to_json
- end
- end
- ensure
- GC.stress = stress
- silence do
- JSON.const_set :SAFE_STATE_PROTOTYPE, const
- end
- end if JSON.const_defined?("Ext")
-
def test_generate
json = generate(@hash)
assert_equal(parse(@json2), parse(json))
@@ -93,6 +63,11 @@ EOT
end
def test_generate_pretty
+ json = pretty_generate({})
+ assert_equal(<<'EOT'.chomp, json)
+{
+}
+EOT
json = pretty_generate(@hash)
# hashes aren't (insertion) ordered on every ruby implementation
# assert_equal(@json3, json)
@@ -167,13 +142,14 @@ EOT
end
def test_pretty_state
- state = PRETTY_STATE_PROTOTYPE.dup
+ state = JSON.create_pretty_state
assert_equal({
:allow_nan => false,
:array_nl => "\n",
:ascii_only => false,
:buffer_initial_length => 1024,
:depth => 0,
+ :escape_slash => false,
:indent => " ",
:max_nesting => 100,
:object_nl => "\n",
@@ -183,13 +159,14 @@ EOT
end
def test_safe_state
- state = SAFE_STATE_PROTOTYPE.dup
+ state = JSON::State.new
assert_equal({
:allow_nan => false,
:array_nl => "",
:ascii_only => false,
:buffer_initial_length => 1024,
:depth => 0,
+ :escape_slash => false,
:indent => "",
:max_nesting => 100,
:object_nl => "",
@@ -199,13 +176,14 @@ EOT
end
def test_fast_state
- state = FAST_STATE_PROTOTYPE.dup
+ state = JSON.create_fast_state
assert_equal({
:allow_nan => false,
:array_nl => "",
:ascii_only => false,
:buffer_initial_length => 1024,
:depth => 0,
+ :escape_slash => false,
:indent => "",
:max_nesting => 0,
:object_nl => "",
@@ -234,12 +212,8 @@ EOT
def test_depth
ary = []; ary << ary
- assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
assert_raise(JSON::NestingError) { generate(ary) }
- assert_equal 0, JSON::SAFE_STATE_PROTOTYPE.depth
- assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
assert_raise(JSON::NestingError) { JSON.pretty_generate(ary) }
- assert_equal 0, JSON::PRETTY_STATE_PROTOTYPE.depth
s = JSON.state.new
assert_equal 0, s.depth
assert_raise(JSON::NestingError) { ary.to_json(s) }
@@ -258,7 +232,7 @@ EOT
end
def test_gc
- if respond_to?(:assert_in_out_err)
+ if respond_to?(:assert_in_out_err) && !(RUBY_PLATFORM =~ /java/)
assert_in_out_err(%w[-rjson --disable-gems], <<-EOS, [], [])
bignum_too_long_to_embed_as_string = 1234567890123456789012345
expect = bignum_too_long_to_embed_as_string.to_s
@@ -394,6 +368,10 @@ EOT
json = '["/"]'
assert_equal json, generate(data)
#
+ data = [ '/' ]
+ json = '["\/"]'
+ assert_equal json, generate(data, :escape_slash => true)
+ #
data = ['"']
json = '["\""]'
assert_equal json, generate(data)
diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb
index 9946dd93e7..dce693e548 100644
--- a/test/json/json_parser_test.rb
+++ b/test/json/json_parser_test.rb
@@ -218,6 +218,17 @@ class JSONParserTest < Test::Unit::TestCase
end
end
+ def test_freeze
+ assert_predicate parse('{}', :freeze => true), :frozen?
+ assert_predicate parse('[]', :freeze => true), :frozen?
+ assert_predicate parse('"foo"', :freeze => true), :frozen?
+
+ if string_deduplication_available?
+ assert_same(-'foo', parse('"foo"', :freeze => true))
+ assert_same(-'foo', parse('{"foo": 1}', :freeze => true).keys.first)
+ end
+ end
+
def test_parse_comments
json = <<EOT
{
@@ -293,6 +304,10 @@ EOT
json = '["\\\'"]'
data = ["'"]
assert_equal data, parse(json)
+
+ json = '["\/"]'
+ data = [ '/' ]
+ assert_equal data, parse(json)
end
class SubArray < Array
@@ -464,6 +479,16 @@ EOT
private
+ def string_deduplication_available?
+ r1 = rand.to_s
+ r2 = r1.dup
+ begin
+ (-r1).equal?(-r2)
+ rescue NoMethodError
+ false # No String#-@
+ end
+ end
+
def assert_equal_float(expected, actual, delta = 1e-2)
Array === expected and expected = expected.first
Array === actual and actual = actual.first
diff --git a/test/json/ractor_test.rb b/test/json/ractor_test.rb
new file mode 100644
index 0000000000..71105e55ec
--- /dev/null
+++ b/test/json/ractor_test.rb
@@ -0,0 +1,30 @@
+# encoding: utf-8
+# frozen_string_literal: false
+
+require 'test_helper'
+
+class JSONInRactorTest < Test::Unit::TestCase
+ def test_generate
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ $VERBOSE = nil
+ require "json"
+ r = Ractor.new do
+ json = JSON.generate({
+ 'a' => 2,
+ 'b' => 3.141,
+ 'c' => 'c',
+ 'd' => [ 1, "b", 3.14 ],
+ 'e' => { 'foo' => 'bar' },
+ 'g' => "\"\0\037",
+ 'h' => 1000.0,
+ 'i' => 0.001
+ })
+ JSON.parse(json)
+ end
+ expected_json = '{"a":2,"b":3.141,"c":"c","d":[1,"b",3.14],"e":{"foo":"bar"},' +
+ '"g":"\\"\\u0000\\u001f","h":1000.0,"i":0.001}'
+ assert_equal(JSON.parse(expected_json), r.take)
+ end;
+ end
+end if defined?(Ractor)
diff --git a/test/json/test_helper.rb b/test/json/test_helper.rb
index c5ec0fca7b..446c020e8f 100644
--- a/test/json/test_helper.rb
+++ b/test/json/test_helper.rb
@@ -1,12 +1,12 @@
case ENV['JSON']
when 'pure'
- $:.unshift 'lib'
+ $:.unshift File.join(__dir__, '../lib')
require 'json/pure'
when 'ext'
- $:.unshift 'ext', 'lib'
+ $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib')
require 'json/ext'
else
- $:.unshift 'ext', 'lib'
+ $:.unshift File.join(__dir__, '../ext'), File.join(__dir__, '../lib')
require 'json'
end
diff --git a/test/lib/jit_support.rb b/test/lib/jit_support.rb
index 3785c31ed2..2f6d637ec9 100644
--- a/test/lib/jit_support.rb
+++ b/test/lib/jit_support.rb
@@ -3,15 +3,18 @@ require 'rbconfig'
module JITSupport
JIT_TIMEOUT = 600 # 10min for each...
JIT_SUCCESS_PREFIX = 'JIT success \(\d+\.\dms\)'
+ JIT_RECOMPILE_PREFIX = 'JIT recompile'
JIT_COMPACTION_PREFIX = 'JIT compaction \(\d+\.\dms\)'
UNSUPPORTED_COMPILERS = [
- %r[\A/opt/intel/.*/bin/intel64/icc\b],
+ %r[\A.*/bin/intel64/icc\b],
%r[\A/opt/developerstudio\d+\.\d+/bin/cc\z],
]
+ # debian-riscv64: "gcc: internal compiler error: Segmentation fault signal terminated program cc1" https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian-riscv64/ruby-master/log/20200420T083601Z.fail.html.gz
# freebsd12: cc1 internal failure https://rubyci.org/logs/rubyci.s3.amazonaws.com/freebsd12/ruby-master/log/20200306T103003Z.fail.html.gz
# rhel8: one or more PCH files were found, but they were invalid https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20200306T153003Z.fail.html.gz
# centos8: ditto https://rubyci.org/logs/rubyci.s3.amazonaws.com/centos8/ruby-master/log/20200512T003004Z.fail.html.gz
PENDING_RUBYCI_NICKNAMES = %w[
+ debian-riscv64
freebsd12
rhel8
centos8
@@ -53,13 +56,25 @@ module JITSupport
def supported?
return @supported if defined?(@supported)
- @supported = UNSUPPORTED_COMPILERS.all? do |regexp|
+ @supported = RbConfig::CONFIG["MJIT_SUPPORT"] != 'no' && UNSUPPORTED_COMPILERS.all? do |regexp|
!regexp.match?(RbConfig::CONFIG['MJIT_CC'])
- end && RbConfig::CONFIG["MJIT_SUPPORT"] != 'no' && !PENDING_RUBYCI_NICKNAMES.include?(ENV['RUBYCI_NICKNAME'])
+ end && !appveyor_pdb_corrupted? && !PENDING_RUBYCI_NICKNAMES.include?(ENV['RUBYCI_NICKNAME'])
+ end
+
+ # AppVeyor's Visual Studio 2013 / 2015 are known to spuriously generate broken pch / pdb, like:
+ # error C2859: c:\projects\ruby\x64-mswin_120\include\ruby-2.8.0\x64-mswin64_120\rb_mjit_header-2.8.0.pdb
+ # is not the pdb file that was used when this precompiled header was created, recreate the precompiled header.
+ # https://ci.appveyor.com/project/ruby/ruby/builds/32159878/job/l2p38snw8yxxpp8h
+ #
+ # Until we figure out why, this allows us to skip testing JIT when it happens.
+ def appveyor_pdb_corrupted?
+ return false unless ENV.key?('APPVEYOR')
+ stdout, _stderr, _status = eval_with_jit_without_retry('proc {}.call', verbose: 2, min_calls: 1)
+ stdout.include?('.pdb is not the pdb file that was used when this precompiled header was created, recreate the precompiled header.')
end
def remove_mjit_logs(stderr)
- if RubyVM::MJIT.enabled? # utility for -DFORCE_MJIT_ENABLE
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # utility for -DFORCE_MJIT_ENABLE
stderr.gsub(/^MJIT warning: Skipped to compile unsupported instruction: \w+\n/m, '')
else
stderr
diff --git a/test/logger/test_logdevice.rb b/test/logger/test_logdevice.rb
index 2a01dab17f..6fefd356cd 100644
--- a/test/logger/test_logdevice.rb
+++ b/test/logger/test_logdevice.rb
@@ -451,7 +451,7 @@ class TestLogDevice < Test::Unit::TestCase
end
ensure
logdev0.close
- end unless /mswin|mingw/ =~ RUBY_PLATFORM
+ end unless /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
def test_shifting_midnight
Dir.mktmpdir do |tmpdir|
diff --git a/test/logger/test_logger.rb b/test/logger/test_logger.rb
index 521b5627d4..4bbfd523c0 100644
--- a/test/logger/test_logger.rb
+++ b/test/logger/test_logger.rb
@@ -216,6 +216,13 @@ class TestLogger < Test::Unit::TestCase
assert_equal(STDOUT, logger.instance_variable_get(:@logdev).dev)
end
+ def test_reopen_nil_logdevice
+ logger = Logger.new(File::NULL)
+ assert_nothing_raised do
+ logger.reopen(STDOUT)
+ end
+ end
+
def test_add
logger = Logger.new(nil)
logger.progname = "my_progname"
@@ -378,4 +385,9 @@ class TestLogger < Test::Unit::TestCase
log = log(logger, :debug) { "msg" }
assert_nil log.msg
end
+
+ def test_does_not_instantiate_log_device_for_File_NULL
+ l = Logger.new(File::NULL)
+ assert_nil(l.instance_variable_get(:@logdev))
+ end
end
diff --git a/test/matrix/test_matrix.rb b/test/matrix/test_matrix.rb
index 7dbb1000d9..04e8a5bf34 100644
--- a/test/matrix/test_matrix.rb
+++ b/test/matrix/test_matrix.rb
@@ -18,6 +18,7 @@ class TestMatrix < Test::Unit::TestCase
@a3 = Matrix[[4, 1, -3], [0, 3, 7], [11, -4, 2]]
@a5 = Matrix[[2, 0, 9, 3, 9], [8, 7, 0, 1, 9], [7, 5, 6, 6, 5], [0, 7, 8, 3, 0], [7, 8, 2, 3, 1]]
@b3 = Matrix[[-7, 7, -10], [9, -3, -2], [-1, 3, 9]]
+ @rot = Matrix[[0, -1, 0], [1, 0, 0], [0, 0, -1]]
end
def test_matrix
@@ -447,6 +448,12 @@ class TestMatrix < Test::Unit::TestCase
assert_equal(Matrix[[67,96],[48,99]], Matrix[[7,6],[3,9]] ** 2)
assert_equal(Matrix.I(5), Matrix.I(5) ** -1)
assert_raise(Matrix::ErrOperationNotDefined) { Matrix.I(5) ** Object.new }
+
+ m = Matrix[[0,2],[1,0]]
+ exp = 0b11101000
+ assert_equal(Matrix.scalar(2, 1 << (exp/2)), m ** exp)
+ exp = 0b11101001
+ assert_equal(Matrix[[0, 2 << (exp/2)], [1 << (exp/2), 0]], m ** exp)
end
def test_det
@@ -792,4 +799,34 @@ class TestMatrix < Test::Unit::TestCase
assert_in_epsilon(vectors[0][0], vectors[0][1])
assert_in_epsilon(-4 * vectors[1][0], vectors[1][1])
end
+
+ def test_unitary?
+ assert_equal true, @rot.unitary?
+ assert_equal true, ((0+1i) * @rot).unitary?
+ assert_equal false, @a3.unitary?
+ assert_raise(Matrix::ErrDimensionMismatch) { @m1.unitary? }
+ end
+
+ def test_orthogonal
+ assert_equal true, @rot.orthogonal?
+ assert_equal false, ((0+1i) * @rot).orthogonal?
+ assert_equal false, @a3.orthogonal?
+ assert_raise(Matrix::ErrDimensionMismatch) { @m1.orthogonal? }
+ end
+
+ def test_adjoint
+ assert_equal(Matrix[[(1-2i), 1], [(0-1i), 2], [0, 3]], @c1.adjoint)
+ assert_equal(Matrix.empty(0,2), @e1.adjoint)
+ end
+
+ def test_ractor
+ assert_ractor(<<~RUBY, require: 'matrix')
+ obj1 = Matrix[[1, 2], [3, 4]].freeze
+
+ obj2 = Ractor.new obj1 do |obj|
+ obj
+ end.take
+ assert_same obj1, obj2
+ RUBY
+ end
end
diff --git a/test/misc/test_ruby_mode.rb b/test/misc/test_ruby_mode.rb
deleted file mode 100644
index bc5101911b..0000000000
--- a/test/misc/test_ruby_mode.rb
+++ /dev/null
@@ -1,183 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'tempfile'
-
-class TestRubyMode < Test::Unit::TestCase
- MISCDIR = File.expand_path("../../../misc", __FILE__)
- e = ENV["EMACS"] || "emacs"
- emacs = %W"#{e} -q --no-site-file --batch --load #{MISCDIR}/ruby-mode.el"
- begin
- raise if IO.popen([e, "--version", :err=>[:child, :out]]) {|f| f.read}[/[0-9]+/].to_i < 23
- IO.popen([*emacs, :err=>[:child, :out]]) {|f| f.read}
- rescue
- EMACS = nil
- else
- EMACS = (emacs if $? and $?.success?)
- end
-end
-
-class TestRubyMode
- EVAL_OPT = "--eval"
- EXPR_SAVE = "(save-buffer 0)"
- finish_mark = "ok-#{$$}"
- FINISH_MARK = /^#{finish_mark}$/
- EXPR_FINISH = "(print \'#{finish_mark})"
- EXPR_RUBYMODE = "(ruby-mode)"
-
- def run_emacs(src, *exprs)
- tmp = Tempfile.new(%w"ruby-mode.test. .rb")
- tmp.puts(src)
- tmp.close
- exprs = exprs.map {|expr| [EVAL_OPT, expr]}.flatten
- exprs.unshift(EVAL_OPT, EXPR_RUBYMODE)
- exprs.push(EVAL_OPT, EXPR_SAVE)
- exprs.push(EVAL_OPT, EXPR_FINISH)
- output = IO.popen([*EMACS, tmp.path, *exprs, err:[:child, :out]], "r") {|e| e.read}
- tmp.open
- result = tmp.read
- return result, output
- ensure
- tmp.close!
- end
-
- class TestIndent < self
- EXPR_INDENT = "(indent-region (point-min) (point-max))"
-
- def assert_indent(expected, source, *message)
- if space = expected[/\A\n?(\s*\|)/, 1]
- space = /^#{Regexp.quote(space)}/m
- expected.gsub!(space, '')
- source.gsub!(space, '')
- end
- result, output = run_emacs(source, EXPR_INDENT)
- assert_match(FINISH_MARK, output)
- assert_equal(expected, result, message(*message) {diff expected, result})
- end
-
- def test_simple
- assert_indent('
- |if foo
- | bar
- |end
- |zot
- |', '
- |if foo
- |bar
- | end
- | zot
- |')
- end
-
- def test_keyword_label
- assert_indent('
- |bar(class: XXX) do
- | foo
- |end
- |bar
- |', '
- |bar(class: XXX) do
- | foo
- | end
- | bar
- |')
- end
-
- def test_method_with_question_mark
- assert_indent('
- |if x.is_a?(XXX)
- | foo
- |end
- |', '
- |if x.is_a?(XXX)
- | foo
- | end
- |')
- end
-
- def test_expr_in_regexp
- assert_indent('
- |if /#{foo}/ =~ s
- | x = 1
- |end
- |', '
- |if /#{foo}/ =~ s
- | x = 1
- | end
- |')
- end
-
- def test_singleton_class
- skip("pending")
- assert_indent('
- |class<<bar
- | foo
- |end
- |', '
- |class<<bar
- |foo
- | end
- |')
- end
-
- def test_array_literal
- assert_indent('
- |foo = [
- | bar
- |]
- |', '
- |foo = [
- | bar
- | ]
- |')
- assert_indent('
- |foo do
- | [bar]
- |end
- |', '
- |foo do
- |[bar]
- | end
- |')
- end
-
- def test_begin_end
- assert_indent('
- |begin
- | a[b]
- |end
- |', '
- |begin
- | a[b]
- | end
- |')
- end
-
- def test_array_after_paren_and_space
- assert_indent('
- |class A
- | def foo
- | foo( [])
- | end
- |end
- |', '
- |class A
- | def foo
- |foo( [])
- |end
- | end
- |')
- end
-
- def test_spread_arguments
- assert_indent('
- |foo(1,
- | 2,
- | 3)
- |', '
- |foo(1,
- | 2,
- | 3)
- |')
- end
- end
-end if TestRubyMode::EMACS
diff --git a/test/mkmf/test_install.rb b/test/mkmf/test_install.rb
new file mode 100644
index 0000000000..7f8c603d42
--- /dev/null
+++ b/test/mkmf/test_install.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: false
+require_relative 'base'
+
+class TestMkmf
+ class TestInstall < TestMkmf
+ def test_install_dirs
+ Dir.mktmpdir do |dir|
+ File.write(dir+"/extconf.rb", "require 'mkmf'; create_makefile('test')")
+ all_assertions do |a|
+ a.foreach(
+ ["site"],
+ ["vendor", "--vendor"],
+ ) do |dest, *options|
+ assert_ruby_status(["-C", dir, "extconf.rb", *options])
+ mf = File.read(dir+"/Makefile")
+ a.foreach(
+ ["RUBYCOMMONDIR", "$(#{dest}dir)$(target_prefix)"],
+ ["RUBYLIBDIR", "$(#{dest}libdir)$(target_prefix)"],
+ ["RUBYARCHDIR", "$(#{dest}archdir)$(target_prefix)"],
+ ["HDRDIR", "$(#{dest}hdrdir)$(target_prefix)"],
+ ["ARCHHDRDIR", "$(#{dest}archhdrdir)$(target_prefix)"],
+ ) do |(var, path)|
+ assert_equal path, mf[/^#{var}\s*=\s*(.*)$/, 1]
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/test/mkmf/test_mkmf.rb b/test/mkmf/test_mkmf.rb
new file mode 100644
index 0000000000..adb86eca8d
--- /dev/null
+++ b/test/mkmf/test_mkmf.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'mkmf'
+
+class TestMkmf < Test::Unit::TestCase
+ class TestGlobal < TestMkmf
+ main = TOPLEVEL_BINDING.receiver
+ MakeMakefile.public_instance_methods(false).each do |m|
+ define_method(:"test_global_#{m}") do
+ assert_respond_to(main, [m, true])
+ assert_not_respond_to(main, [m, false])
+ end
+ end
+ end
+end
diff --git a/test/monitor/test_monitor.rb b/test/monitor/test_monitor.rb
index 721c848d68..0f17d58f71 100644
--- a/test/monitor/test_monitor.rb
+++ b/test/monitor/test_monitor.rb
@@ -10,6 +10,13 @@ class TestMonitor < Test::Unit::TestCase
@monitor = Monitor.new
end
+ def test_enter_in_different_fibers
+ @monitor.enter
+ Fiber.new {
+ assert_equal false, @monitor.try_enter
+ }.resume
+ end
+
def test_enter
ary = []
queue = Queue.new
@@ -236,6 +243,22 @@ class TestMonitor < Test::Unit::TestCase
assert NewCondTest.new.cond.instance_variable_get(:@monitor) != nil
end
+ class KeywordInitializeParent
+ def initialize(x:)
+ end
+ end
+
+ class KeywordInitializeChild < KeywordInitializeParent
+ include MonitorMixin
+ def initialize
+ super(x: 1)
+ end
+ end
+
+ def test_initialize_with_keyword_arg
+ assert KeywordInitializeChild.new
+ end
+
def test_timedwait
cond = @monitor.new_cond
b = "foo"
diff --git a/test/net/ftp/test_ftp.rb b/test/net/ftp/test_ftp.rb
index 24c5d3a12f..a480da4a4f 100644
--- a/test/net/ftp/test_ftp.rb
+++ b/test/net/ftp/test_ftp.rb
@@ -433,7 +433,7 @@ class FTPTest < Test::Unit::TestCase
end
conn.print(l, "\r\n")
end
- rescue Errno::EPIPE
+ rescue Errno::EPIPE, Errno::ECONNRESET
ensure
assert_nil($!)
conn.close
@@ -770,6 +770,7 @@ class FTPTest < Test::Unit::TestCase
begin
begin
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
ftp.login
assert_match(/\AUSER /, commands.shift)
@@ -814,6 +815,7 @@ class FTPTest < Test::Unit::TestCase
begin
begin
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
ftp.login
assert_match(/\AUSER /, commands.shift)
@@ -888,6 +890,40 @@ class FTPTest < Test::Unit::TestCase
end
end
+ def test_getbinaryfile_error
+ commands = []
+ server = create_ftp_server { |sock|
+ sock.print("220 (test_ftp).\r\n")
+ commands.push(sock.gets)
+ sock.print("331 Please specify the password.\r\n")
+ commands.push(sock.gets)
+ sock.print("230 Login successful.\r\n")
+ commands.push(sock.gets)
+ sock.print("200 Switching to Binary mode.\r\n")
+ line = sock.gets
+ commands.push(line)
+ sock.print("450 No Dice\r\n")
+ }
+ begin
+ begin
+ ftp = Net::FTP.new
+ ftp.passive = true
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
+ ftp.connect(SERVER_ADDR, server.port)
+ ftp.login
+ assert_match(/\AUSER /, commands.shift)
+ assert_match(/\APASS /, commands.shift)
+ assert_equal("TYPE I\r\n", commands.shift)
+ assert_raise(Net::FTPTempError) {ftp.getbinaryfile("foo", nil)}
+ assert_match(/\A(PASV|EPSV)\r\n/, commands.shift)
+ ensure
+ ftp.close if ftp
+ end
+ ensure
+ server.close
+ end
+ end
+
def test_storbinary
commands = []
binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3
@@ -1551,6 +1587,7 @@ EOF
begin
begin
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
assert_equal(['LANG EN*', 'UTF8'], ftp.features)
assert_equal("FEAT\r\n", commands.shift)
@@ -1573,6 +1610,7 @@ EOF
begin
begin
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
assert_raise(Net::FTPPermError) do
ftp.features
@@ -1598,6 +1636,7 @@ EOF
begin
begin
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
ftp.option("UTF8", "ON")
assert_equal("OPTS UTF8 ON\r\n", commands.shift)
@@ -1656,6 +1695,7 @@ EOF
begin
begin
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
entry = ftp.mlst("foo")
assert_equal("/foo", entry.pathname)
@@ -1742,6 +1782,7 @@ EOF
begin
begin
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
ftp.login
assert_match(/\AUSER /, commands.shift)
@@ -1780,6 +1821,7 @@ EOF
def test_parse257
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
assert_equal('/foo/bar',
ftp.send(:parse257, '257 "/foo/bar" directory created'))
assert_equal('/foo/bar"baz',
@@ -1918,6 +1960,7 @@ EOF
port: port,
ssl: { ca_file: CA_FILE },
passive: false)
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
begin
assert_equal("AUTH TLS\r\n", commands.shift)
assert_equal("PBSZ 0\r\n", commands.shift)
@@ -1934,7 +1977,7 @@ EOF
assert_equal(nil, commands.shift)
# FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h.
# See https://github.com/openssl/openssl/pull/5967 for details.
- if OpenSSL::OPENSSL_LIBRARY_VERSION !~ /OpenSSL 1.1.0h/
+ if OpenSSL::OPENSSL_LIBRARY_VERSION !~ /OpenSSL 1.1.0h|LibreSSL/
assert_equal(true, session_reused_for_data_connection)
end
ensure
@@ -2002,6 +2045,7 @@ EOF
port: port,
ssl: { ca_file: CA_FILE },
passive: true)
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
begin
assert_equal("AUTH TLS\r\n", commands.shift)
assert_equal("PBSZ 0\r\n", commands.shift)
@@ -2017,7 +2061,7 @@ EOF
assert_equal("RETR foo\r\n", commands.shift)
assert_equal(nil, commands.shift)
# FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h.
- if OpenSSL::OPENSSL_LIBRARY_VERSION !~ /OpenSSL 1.1.0h/
+ if OpenSSL::OPENSSL_LIBRARY_VERSION !~ /OpenSSL 1.1.0h|LibreSSL/
assert_equal(true, session_reused_for_data_connection)
end
ensure
@@ -2077,6 +2121,7 @@ EOF
ssl: { ca_file: CA_FILE },
private_data_connection: false,
passive: false)
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
begin
assert_equal("AUTH TLS\r\n", commands.shift)
ftp.login
@@ -2146,6 +2191,7 @@ EOF
ssl: { ca_file: CA_FILE },
private_data_connection: false,
passive: true)
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
begin
assert_equal("AUTH TLS\r\n", commands.shift)
ftp.login
@@ -2226,6 +2272,7 @@ EOF
ftp = Net::FTP.new(SERVER_NAME,
port: server.port,
ssl: { ca_file: CA_FILE })
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
assert_equal("AUTH TLS\r\n", commands.shift)
assert_equal("PBSZ 0\r\n", commands.shift)
assert_equal("PROT P\r\n", commands.shift)
@@ -2278,7 +2325,7 @@ EOF
begin
ftp = Net::FTP.new
ftp.resume = resume
- ftp.read_timeout = RubyVM::MJIT.enabled? ? 5 : 0.2 # use large timeout for --jit-wait
+ ftp.read_timeout = (defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?) ? 300 : 0.2 # use large timeout for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
ftp.login
assert_match(/\AUSER /, commands.shift)
@@ -2337,6 +2384,7 @@ EOF
chdir_to_tmpdir do
begin
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
ftp.login
assert_match(/\AUSER /, commands.shift)
@@ -2387,7 +2435,7 @@ EOF
File.binwrite("./|echo hello", binary_data)
begin
ftp = Net::FTP.new
- ftp.read_timeout = 0.2
+ ftp.read_timeout = RubyVM::MJIT.enabled? ? 300 : 0.2 # use large timeout for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
ftp.login
assert_match(/\AUSER /, commands.shift)
@@ -2442,6 +2490,7 @@ EOF
end
begin
ftp = Net::FTP.new
+ ftp.read_timeout *= 5 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # for --jit-wait
ftp.connect(SERVER_ADDR, server.port)
ftp.login
assert_match(/\AUSER /, commands.shift)
@@ -2467,6 +2516,23 @@ EOF
end
end
+ def test_time_parser
+ s = "20371231000000"
+ assert_equal(Time.utc(2037, 12, 31, 0, 0, 0),
+ Net::FTP::TIME_PARSER[s])
+ s = "20371231000000.123456"
+ assert_equal(Time.utc(2037, 12, 31, 0, 0, 0, 123456),
+ Net::FTP::TIME_PARSER[s])
+ s = "20371231000000." + "9" * 999999
+ assert_equal(Time.utc(2037, 12, 31, 0, 0, 0,
+ 99999999999999999r / 100000000000),
+ Net::FTP::TIME_PARSER[s])
+ e = assert_raise(Net::FTPProtoError) {
+ Net::FTP::TIME_PARSER["x" * 999999]
+ }
+ assert_equal("invalid time-val: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...", e.message)
+ end
+
def test_ignore_pasv_ip
commands = []
binary_data = (0..0xff).map {|i| i.chr}.join * 4 * 3
diff --git a/test/net/http/test_http.rb b/test/net/http/test_http.rb
index 231aa48557..22448d828f 100644
--- a/test/net/http/test_http.rb
+++ b/test/net/http/test_http.rb
@@ -283,6 +283,27 @@ module TestNetHTTP_version_1_1_methods
def test_s_get
assert_equal $test_net_http_data,
Net::HTTP.get(config('host'), '/', config('port'))
+
+ assert_equal $test_net_http_data, Net::HTTP.get(
+ URI.parse("http://#{config('host')}:#{config('port')}")
+ )
+ assert_equal $test_net_http_data, Net::HTTP.get(
+ URI.parse("http://#{config('host')}:#{config('port')}"), "Accept" => "text/plain"
+ )
+ end
+
+ def test_s_get_response
+ res = Net::HTTP.get_response(
+ URI.parse("http://#{config('host')}:#{config('port')}")
+ )
+ assert_equal "application/octet-stream", res["Content-Type"]
+ assert_equal $test_net_http_data, res.body
+
+ res = Net::HTTP.get_response(
+ URI.parse("http://#{config('host')}:#{config('port')}"), "Accept" => "text/plain"
+ )
+ assert_equal "text/plain", res["Content-Type"]
+ assert_equal $test_net_http_data, res.body
end
def test_head
@@ -548,7 +569,7 @@ module TestNetHTTP_version_1_1_methods
conn = Net::HTTP.new('localhost', port)
conn.read_timeout = EnvUtil.apply_timeout_scale(0.01)
- conn.open_timeout = EnvUtil.apply_timeout_scale(0.1)
+ conn.open_timeout = EnvUtil.apply_timeout_scale(1)
th = Thread.new do
assert_raise(Net::ReadTimeout) {
diff --git a/test/net/http/test_httpresponse.rb b/test/net/http/test_httpresponse.rb
index a03bb2e152..a70a9bce34 100644
--- a/test/net/http/test_httpresponse.rb
+++ b/test/net/http/test_httpresponse.rb
@@ -77,6 +77,8 @@ EOS
end
def test_read_body_block_mod
+ # http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/3019353
+ skip 'too unstable with --jit-wait, and extending read_timeout did not help it' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
IO.pipe do |r, w|
buf = 'x' * 1024
buf.freeze
diff --git a/test/net/http/test_https.rb b/test/net/http/test_https.rb
index a501222668..7b97e39586 100644
--- a/test/net/http/test_https.rb
+++ b/test/net/http/test_https.rb
@@ -12,14 +12,14 @@ end
class TestNetHTTPS < Test::Unit::TestCase
include TestNetHTTPUtils
- def self.fixture(key)
+ def self.read_fixture(key)
File.read(File.expand_path("../fixtures/#{key}", __dir__))
end
- CA_CERT = OpenSSL::X509::Certificate.new(fixture("cacert.pem"))
- SERVER_KEY = OpenSSL::PKey.read(fixture("server.key"))
- SERVER_CERT = OpenSSL::X509::Certificate.new(fixture("server.crt"))
- DHPARAMS = OpenSSL::PKey::DH.new(fixture("dhparams.pem"))
+ CA_CERT = OpenSSL::X509::Certificate.new(read_fixture("cacert.pem"))
+ SERVER_KEY = OpenSSL::PKey.read(read_fixture("server.key"))
+ SERVER_CERT = OpenSSL::X509::Certificate.new(read_fixture("server.crt"))
+ DHPARAMS = OpenSSL::PKey::DH.new(read_fixture("dhparams.pem"))
TEST_STORE = OpenSSL::X509::Store.new.tap {|s| s.add_cert(CA_CERT) }
CONFIG = {
@@ -112,7 +112,7 @@ class TestNetHTTPS < Test::Unit::TestCase
def test_get_SNI_failure
TestNetHTTPUtils.clean_http_proxy_env do
- http = Net::HTTP.new("invalid_servername", config("port"))
+ http = Net::HTTP.new("invalidservername", config("port"))
http.ipaddr = config('host')
http.use_ssl = true
http.cert_store = TEST_STORE
@@ -143,10 +143,23 @@ class TestNetHTTPS < Test::Unit::TestCase
# See https://github.com/openssl/openssl/pull/5967 for details.
skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/
+ # FIXME: GitHub Actions for MinGW failed. Maybe it's because of OpenSSL on MiNGW
+ if /mingw/ =~ RUBY_PLATFORM
+ skip "Skip net/https test using openssl on MinGW"
+ end
+
http = Net::HTTP.new("localhost", config("port"))
http.use_ssl = true
http.cert_store = TEST_STORE
+ if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /LibreSSL (\d+\.\d+)/ && $1.to_f > 3.19
+ # LibreSSL 3.2 defaults to TLSv1.3 in server and client, which doesn't currently
+ # support session resuse. Limiting the version to the TLSv1.2 stack allows
+ # this test to continue to work on LibreSSL 3.2+. LibreSSL may eventually
+ # support session reuse, but there are no current plans to do so.
+ http.ssl_version = :TLSv1
+ end
+
http.start
http.get("/")
http.finish
@@ -208,6 +221,31 @@ class TestNetHTTPS < Test::Unit::TestCase
skip $!
end
+ def test_skip_hostname_verification
+ TestNetHTTPUtils.clean_http_proxy_env do
+ http = Net::HTTP.new('invalidservername', config('port'))
+ http.ipaddr = config('host')
+ http.use_ssl = true
+ http.cert_store = TEST_STORE
+ http.verify_hostname = false
+ assert_nothing_raised { http.start }
+ ensure
+ http.finish if http&.started?
+ end
+ end
+
+ def test_fail_if_verify_hostname_is_true
+ TestNetHTTPUtils.clean_http_proxy_env do
+ http = Net::HTTP.new('invalidservername', config('port'))
+ http.ipaddr = config('host')
+ http.use_ssl = true
+ http.cert_store = TEST_STORE
+ http.verify_hostname = true
+ @log_tester = lambda { |_| }
+ assert_raise(OpenSSL::SSL::SSLError) { http.start }
+ end
+ end
+
def test_certificate_verify_failure
http = Net::HTTP.new("localhost", config("port"))
http.use_ssl = true
diff --git a/test/net/http/utils.rb b/test/net/http/utils.rb
index 53f3be0b88..e343e16712 100644
--- a/test/net/http/utils.rb
+++ b/test/net/http/utils.rb
@@ -81,7 +81,11 @@ module TestNetHTTPUtils
end
def do_GET(req, res)
- res['Content-Type'] = $test_net_http_data_type
+ if req['Accept'] != '*/*'
+ res['Content-Type'] = req['Accept']
+ else
+ res['Content-Type'] = $test_net_http_data_type
+ end
res.body = $test_net_http_data
res.chunked = @chunked
end
diff --git a/test/net/imap/test_imap.rb b/test/net/imap/test_imap.rb
index 0ce0eb67ba..85fb71d440 100644
--- a/test/net/imap/test_imap.rb
+++ b/test/net/imap/test_imap.rb
@@ -482,25 +482,75 @@ class IMAPTest < Test::Unit::TestCase
def test_connection_closed_without_greeting
server = create_tcp_server
port = server.addr[1]
- h = {'server before close': server.inspect} # inspect info before close
+ h = {
+ server: server,
+ port: port,
+ server_created: {
+ server: server.inspect,
+ t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
+ }
+ }
+ net_imap = Class.new(Net::IMAP) do
+ @@h = h
+ def tcp_socket(host, port)
+ @@h[:in_tcp_socket] = {
+ host: host,
+ port: port,
+ server: @@h[:server].inspect,
+ t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
+ }
+ #super
+ s = Socket.tcp(host, port, :connect_timeout => @open_timeout)
+ @@h[:in_tcp_socket_2] = {
+ s: s.inspect,
+ local_address: s.local_address,
+ remote_address: s.remote_address,
+ t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
+ }
+ s.setsockopt(:SOL_SOCKET, :SO_KEEPALIVE, true)
+ s
+ end
+ end
start_server do
begin
+ h[:in_start_server_before_accept] = {
+ t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
+ }
sock = server.accept
- h[:sock_addr], h[:sock_peeraddr] = sock.addr, sock.peeraddr
+ h[:in_start_server] = {
+ sock_addr: sock.addr,
+ sock_peeraddr: sock.peeraddr,
+ t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
+ sockets: ObjectSpace.each_object(BasicSocket).map{|s| [s.inspect, connect_address: (s.connect_address rescue nil).inspect, local_address: (s.local_address rescue nil).inspect, remote_address: (s.remote_address rescue nil).inspect] },
+ }
sock.close
+ h[:in_start_server_sock_closed] = {
+ t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
+ }
ensure
server.close
end
end
assert_raise(Net::IMAP::Error) do
- #begin
- Net::IMAP.new(server_addr, :port => port)
- #rescue Net::IMAP::Error
- # raise Errno::EINVAL
- #end
- rescue Errno::EINVAL => e # for debug on OpenCSW
- h.merge!({e: e, server: server, port: port, server_addr: server_addr})
- raise(h.inspect)
+ #Net::IMAP.new(server_addr, :port => port)
+ if true
+ net_imap.new(server_addr, :port => port)
+ else
+ # for testing debug print
+ begin
+ net_imap.new(server_addr, :port => port)
+ rescue Net::IMAP::Error
+ raise Errno::EINVAL
+ end
+ end
+ rescue SystemCallError => e # for debug on OpenCSW
+ h[:in_rescue] = {
+ e: e,
+ server_addr: server_addr,
+ t: Process.clock_gettime(Process::CLOCK_MONOTONIC),
+ }
+ require 'pp'
+ raise(PP.pp(h, +''))
end
end
diff --git a/test/net/smtp/test_smtp.rb b/test/net/smtp/test_smtp.rb
index 90c92e06f8..af30bb7221 100644
--- a/test/net/smtp/test_smtp.rb
+++ b/test/net/smtp/test_smtp.rb
@@ -28,6 +28,14 @@ module Net
end
end
+ def setup
+ @server_threads = []
+ end
+
+ def teardown
+ @server_threads.each {|th| th.join }
+ end
+
def test_critical
smtp = Net::SMTP.new 'localhost', 25
@@ -129,7 +137,7 @@ module Net
smtp = Net::SMTP.new("localhost", servers[0].local_address.ip_port)
smtp.enable_tls
smtp.open_timeout = 1
- smtp.start do
+ smtp.start(tls_verify: false) do
end
ensure
sock.close if sock
@@ -184,17 +192,99 @@ module Net
end
end
+ def test_start
+ port = fake_server_start
+ smtp = Net::SMTP.start('localhost', port)
+ smtp.finish
+ end
+
+ def test_start_with_position_argument
+ port = fake_server_start(helo: 'myname', user: 'account', password: 'password')
+ smtp = Net::SMTP.start('localhost', port, 'myname', 'account', 'password', :plain)
+ smtp.finish
+ end
+
+ def test_start_with_keyword_argument
+ port = fake_server_start(helo: 'myname', user: 'account', password: 'password')
+ smtp = Net::SMTP.start('localhost', port, helo: 'myname', user: 'account', secret: 'password', authtype: :plain)
+ smtp.finish
+ end
+
+ def test_start_password_is_secret
+ port = fake_server_start(helo: 'myname', user: 'account', password: 'password')
+ smtp = Net::SMTP.start('localhost', port, helo: 'myname', user: 'account', password: 'password', authtype: :plain)
+ smtp.finish
+ end
+
+ def test_start_invalid_number_of_arguments
+ err = assert_raise ArgumentError do
+ Net::SMTP.start('localhost', 25, 'myname', 'account', 'password', :plain, :invalid_arg)
+ end
+ assert_equal('wrong number of arguments (given 7, expected 1..6)', err.message)
+ end
+
+ def test_start_instance
+ port = fake_server_start
+ smtp = Net::SMTP.new('localhost', port)
+ smtp.start
+ smtp.finish
+ end
+
+ def test_start_instance_with_position_argument
+ port = fake_server_start(helo: 'myname', user: 'account', password: 'password')
+ smtp = Net::SMTP.new('localhost', port)
+ smtp.start('myname', 'account', 'password', :plain)
+ smtp.finish
+ end
+
+ def test_start_instance_with_keyword_argument
+ port = fake_server_start(helo: 'myname', user: 'account', password: 'password')
+ smtp = Net::SMTP.new('localhost', port)
+ smtp.start(helo: 'myname', user: 'account', secret: 'password', authtype: :plain)
+ smtp.finish
+ end
+
+ def test_start_instance_password_is_secret
+ port = fake_server_start(helo: 'myname', user: 'account', password: 'password')
+ smtp = Net::SMTP.new('localhost', port)
+ smtp.start(helo: 'myname', user: 'account', password: 'password', authtype: :plain)
+ smtp.finish
+ end
+
+ def test_start_instance_invalid_number_of_arguments
+ smtp = Net::SMTP.new('localhost')
+ err = assert_raise ArgumentError do
+ smtp.start('myname', 'account', 'password', :plain, :invalid_arg)
+ end
+ assert_equal('wrong number of arguments (given 5, expected 0..4)', err.message)
+ end
+
private
def accept(servers)
- loop do
- readable, = IO.select(servers.map(&:to_io))
- readable.each do |r|
- sock, = r.accept_nonblock(exception: false)
- next if sock == :wait_readable
- return sock
+ Socket.accept_loop(servers) { |s, _| break s }
+ end
+
+ def fake_server_start(helo: 'localhost', user: nil, password: nil)
+ servers = Socket.tcp_server_sockets('localhost', 0)
+ @server_threads << Thread.start do
+ Thread.current.abort_on_exception = true
+ sock = accept(servers)
+ sock.puts "220 ready\r\n"
+ assert_equal("EHLO #{helo}\r\n", sock.gets)
+ sock.puts "220-servername\r\n220 AUTH PLAIN\r\n"
+ if user
+ credential = ["\0#{user}\0#{password}"].pack('m0')
+ assert_equal("AUTH PLAIN #{credential}\r\n", sock.gets)
+ sock.puts "235 2.7.0 Authentication successful\r\n"
end
+ assert_equal("QUIT\r\n", sock.gets)
+ sock.puts "221 2.0.0 Bye\r\n"
+ sock.close
+ servers.each(&:close)
end
+ port = servers[0].local_address.ip_port
+ return port
end
end
end
diff --git a/test/net/smtp/test_ssl_socket.rb b/test/net/smtp/test_ssl_socket.rb
index 342391f159..dd9529f25e 100644
--- a/test/net/smtp/test_ssl_socket.rb
+++ b/test/net/smtp/test_ssl_socket.rb
@@ -53,8 +53,10 @@ module Net
end
}
+ ssl_context = OpenSSL::SSL::SSLContext.new
+ ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
connection = MySMTP.new('localhost', 25)
- connection.enable_starttls_auto
+ connection.enable_starttls_auto(ssl_context)
connection.fake_tcp = tcp_socket
connection.fake_ssl = ssl_socket
diff --git a/test/net/smtp/test_sslcontext.rb b/test/net/smtp/test_sslcontext.rb
new file mode 100644
index 0000000000..4f1dcfe669
--- /dev/null
+++ b/test/net/smtp/test_sslcontext.rb
@@ -0,0 +1,129 @@
+require 'net/smtp'
+require 'test/unit'
+
+module Net
+ class TestSSLContext < Test::Unit::TestCase
+ class MySMTP < SMTP
+ attr_reader :__ssl_context, :__tls_hostname
+
+ def initialize(socket)
+ @fake_socket = socket
+ super("smtp.example.com")
+ end
+
+ def tcp_socket(*)
+ @fake_socket
+ end
+
+ def ssl_socket_connect(*)
+ end
+
+ def tlsconnect(*)
+ super
+ @fake_socket
+ end
+
+ def ssl_socket(socket, context)
+ @__ssl_context = context
+ s = super
+ hostname = @__tls_hostname = ''
+ s.define_singleton_method(:post_connection_check){ |name| hostname.replace(name) }
+ s
+ end
+ end
+
+ def teardown
+ @server_thread&.exit&.join
+ @server_socket&.close
+ @client_socket&.close
+ end
+
+ def start_smtpd(starttls)
+ @server_socket, @client_socket = Object.const_defined?(:UNIXSocket) ?
+ UNIXSocket.pair : Socket.pair(:INET, :STREAM, 0)
+ @starttls_executed = false
+ @server_thread = Thread.new(@server_socket) do |s|
+ s.puts "220 fakeserver\r\n"
+ while cmd = s.gets&.chomp
+ case cmd
+ when /\AEHLO /
+ s.puts "250-fakeserver\r\n"
+ s.puts "250-STARTTLS\r\n" if starttls
+ s.puts "250 8BITMIME\r\n"
+ when /\ASTARTTLS/
+ @starttls_executed = true
+ s.puts "220 2.0.0 Ready to start TLS\r\n"
+ else
+ raise "unsupported command: #{cmd}"
+ end
+ end
+ end
+ @client_socket
+ end
+
+ def test_default
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.start
+ assert_equal(OpenSSL::SSL::VERIFY_PEER, smtp.__ssl_context.verify_mode)
+ end
+
+ def test_enable_tls
+ smtp = MySMTP.new(start_smtpd(true))
+ context = OpenSSL::SSL::SSLContext.new
+ smtp.enable_tls(context)
+ smtp.start
+ assert_equal(context, smtp.__ssl_context)
+ end
+
+ def test_enable_tls_before_disable_starttls
+ smtp = MySMTP.new(start_smtpd(true))
+ context = OpenSSL::SSL::SSLContext.new
+ smtp.enable_tls(context)
+ smtp.disable_starttls
+ smtp.start
+ assert_equal(context, smtp.__ssl_context)
+ end
+
+ def test_enable_starttls
+ smtp = MySMTP.new(start_smtpd(true))
+ context = OpenSSL::SSL::SSLContext.new
+ smtp.enable_starttls(context)
+ smtp.start
+ assert_equal(context, smtp.__ssl_context)
+ end
+
+ def test_enable_starttls_before_disable_tls
+ smtp = MySMTP.new(start_smtpd(true))
+ context = OpenSSL::SSL::SSLContext.new
+ smtp.enable_starttls(context)
+ smtp.disable_tls
+ smtp.start
+ assert_equal(context, smtp.__ssl_context)
+ end
+
+ def test_start_with_tls_verify_true
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.start(tls_verify: true)
+ assert_equal(OpenSSL::SSL::VERIFY_PEER, smtp.__ssl_context.verify_mode)
+ end
+
+ def test_start_with_tls_verify_false
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.start(tls_verify: false)
+ assert_equal(OpenSSL::SSL::VERIFY_NONE, smtp.__ssl_context.verify_mode)
+ end
+
+ def test_start_with_tls_hostname
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.start(tls_hostname: "localhost")
+ assert_equal("localhost", smtp.__tls_hostname)
+ end
+
+ def test_start_without_tls_hostname
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.start
+ assert_equal("smtp.example.com", smtp.__tls_hostname)
+ end
+
+ end
+end
diff --git a/test/net/smtp/test_starttls.rb b/test/net/smtp/test_starttls.rb
new file mode 100644
index 0000000000..4a29fa6d70
--- /dev/null
+++ b/test/net/smtp/test_starttls.rb
@@ -0,0 +1,122 @@
+require 'net/smtp'
+require 'test/unit'
+
+module Net
+ class TestStarttls < Test::Unit::TestCase
+ class MySMTP < SMTP
+ def initialize(socket)
+ @fake_socket = socket
+ super("smtp.example.com")
+ end
+
+ def tcp_socket(*)
+ @fake_socket
+ end
+
+ def tlsconnect(*)
+ @fake_socket
+ end
+ end
+
+ def teardown
+ @server_thread&.exit&.join
+ @server_socket&.close
+ @client_socket&.close
+ end
+
+ def start_smtpd(starttls)
+ @server_socket, @client_socket = Object.const_defined?(:UNIXSocket) ?
+ UNIXSocket.pair : Socket.pair(:INET, :STREAM, 0)
+ @starttls_executed = false
+ @server_thread = Thread.new(@server_socket) do |s|
+ s.puts "220 fakeserver\r\n"
+ while cmd = s.gets&.chomp
+ case cmd
+ when /\AEHLO /
+ s.puts "250-fakeserver\r\n"
+ s.puts "250-STARTTLS\r\n" if starttls
+ s.puts "250 8BITMIME\r\n"
+ when /\ASTARTTLS/
+ @starttls_executed = true
+ s.puts "220 2.0.0 Ready to start TLS\r\n"
+ else
+ raise "unsupported command: #{cmd}"
+ end
+ end
+ end
+ @client_socket
+ end
+
+ def test_default_with_starttls_capable
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.start
+ assert(@starttls_executed)
+ end
+
+ def test_default_without_starttls_capable
+ smtp = MySMTP.new(start_smtpd(false))
+ smtp.start
+ assert(!@starttls_executed)
+ end
+
+ def test_enable_starttls_with_starttls_capable
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.enable_starttls
+ smtp.start
+ assert(@starttls_executed)
+ end
+
+ def test_enable_starttls_without_starttls_capable
+ smtp = MySMTP.new(start_smtpd(false))
+ smtp.enable_starttls
+ err = assert_raise(Net::SMTPUnsupportedCommand) { smtp.start }
+ assert_equal("STARTTLS is not supported on this server", err.message)
+ end
+
+ def test_enable_starttls_auto_with_starttls_capable
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.enable_starttls_auto
+ smtp.start
+ assert(@starttls_executed)
+ end
+
+ def test_tls_with_starttls_capable
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.enable_tls
+ smtp.start
+ assert(!@starttls_executed)
+ end
+
+ def test_tls_without_starttls_capable
+ smtp = MySMTP.new(start_smtpd(false))
+ smtp.enable_tls
+ end
+
+ def test_disable_starttls
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.disable_starttls
+ smtp.start
+ assert(!@starttls_executed)
+ end
+
+ def test_enable_tls_and_enable_starttls
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.enable_tls
+ err = assert_raise(ArgumentError) { smtp.enable_starttls }
+ assert_equal("SMTPS and STARTTLS is exclusive", err.message)
+ end
+
+ def test_enable_tls_and_enable_starttls_auto
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.enable_tls
+ err = assert_raise(ArgumentError) { smtp.enable_starttls_auto }
+ assert_equal("SMTPS and STARTTLS is exclusive", err.message)
+ end
+
+ def test_enable_starttls_and_enable_starttls_auto
+ smtp = MySMTP.new(start_smtpd(true))
+ smtp.enable_starttls
+ assert_nothing_raised { smtp.enable_starttls_auto }
+ end
+ end
+end
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 336b30f75a..5fd41134ba 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -164,7 +164,17 @@ class TestObjSpace < Test::Unit::TestCase
end;
end
+ def test_trace_object_allocations_stop_first
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ require "objspace"
+ # Make sure stoping before the tracepoints are initialized doesn't raise. See [Bug #17020]
+ ObjectSpace.trace_object_allocations_stop
+ end;
+ end
+
def test_trace_object_allocations
+ ObjectSpace.trace_object_allocations_clear # clear object_table to get rid of erroneous detection for c0
Class.name
o0 = Object.new
ObjectSpace.trace_object_allocations{
@@ -233,6 +243,19 @@ class TestObjSpace < Test::Unit::TestCase
GC.enable
end
+ def test_trace_object_allocations_gc_stress
+ prev = GC.stress
+ GC.stress = true
+
+ ObjectSpace.trace_object_allocations{
+ proc{}
+ }
+
+ assert true # success
+ ensure
+ GC.stress = prev
+ end
+
def test_dump_flags
info = ObjectSpace.dump("foo".freeze)
assert_match(/"wb_protected":true, "old":true/, info)
@@ -275,6 +298,11 @@ class TestObjSpace < Test::Unit::TestCase
JSON.parse(info) if defined?(JSON)
end
+ def test_dump_control_char
+ assert_include(ObjectSpace.dump("\x0f"), '"value":"\u000f"')
+ assert_include(ObjectSpace.dump("\C-?"), '"value":"\u007f"')
+ end
+
def test_dump_special_consts
# [ruby-core:69692] [Bug #11291]
assert_equal('null', ObjectSpace.dump(nil))
@@ -284,6 +312,12 @@ class TestObjSpace < Test::Unit::TestCase
assert_equal('{"type":"SYMBOL", "value":"foo"}', ObjectSpace.dump(:foo))
end
+ def test_dump_special_floats
+ assert_match(/"value":"NaN"/, ObjectSpace.dump(Float::NAN))
+ assert_match(/"value":"Inf"/, ObjectSpace.dump(Float::INFINITY))
+ assert_match(/"value":"\-Inf"/, ObjectSpace.dump(-Float::INFINITY))
+ end
+
def test_dump_dynamic_symbol
dump = ObjectSpace.dump(("foobar%x" % rand(0x10000)).to_sym)
assert_match(/"type":"SYMBOL"/, dump)
@@ -297,8 +331,9 @@ class TestObjSpace < Test::Unit::TestCase
ObjectSpace.dump_all(output: :stdout)
end
- dump_my_heap_please
+ p dump_my_heap_please
end;
+ assert_equal 'nil', output.pop
heap = output.find_all { |l|
obj = JSON.parse(l)
obj['type'] == "IMEMO" && obj['imemo_type']
@@ -314,13 +349,38 @@ class TestObjSpace < Test::Unit::TestCase
ObjectSpace.dump_all(output: :stdout, full: true)
end
- dump_my_heap_please
+ p dump_my_heap_please
end;
+ assert_equal 'nil', output.pop
heap = output.find_all { |l| JSON.parse(l)['type'] == "NONE" }
assert_operator heap.length, :>, 0
end
end
+ def test_dump_all_single_generation
+ assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
+ begin;
+ def dump_my_heap_please
+ GC.start
+ ObjectSpace.trace_object_allocations_start
+ gc_gen = GC.count
+ puts gc_gen
+ @obj1 = Object.new
+ GC.start
+ @obj2 = Object.new
+ ObjectSpace.dump_all(output: :stdout, since: gc_gen)
+ end
+
+ p dump_my_heap_please
+ end;
+ assert_equal 'nil', output.pop
+ since = output.shift.to_i
+ assert_operator output.size, :>, 0
+ generations = output.map { |l| JSON.parse(l)["generation"] }.uniq.sort
+ assert_equal [since, since + 1], generations
+ end
+ end
+
def test_dump_addresses_match_dump_all_addresses
assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
begin;
@@ -330,8 +390,9 @@ class TestObjSpace < Test::Unit::TestCase
ObjectSpace.dump_all(output: $stdout)
end
- dump_my_heap_please
+ p $stdout == dump_my_heap_please
end;
+ assert_equal 'true', output.pop
needle = JSON.parse(output.first)
addr = needle['address']
found = output.drop(1).find { |l| JSON.parse(l)['address'] == addr }
@@ -348,8 +409,9 @@ class TestObjSpace < Test::Unit::TestCase
ObjectSpace.dump_all(output: $stdout)
end
- dump_my_heap_please
+ p $stdout == dump_my_heap_please
end;
+ assert_equal 'true', output.pop
needle = JSON.parse(output.first)
addr = needle['class']
found = output.drop(1).find { |l| JSON.parse(l)['address'] == addr }
@@ -357,6 +419,24 @@ class TestObjSpace < Test::Unit::TestCase
end
end
+ def test_dump_escapes_method_name
+ method_name = "foo\"bar"
+ klass = Class.new do
+ define_method(method_name) { "TEST STRING" }
+ end
+ ObjectSpace.trace_object_allocations_start
+
+ obj = klass.new.send(method_name)
+
+ dump = ObjectSpace.dump(obj)
+ assert_includes dump, '"method":"foo\"bar"'
+
+ parsed = JSON.parse(dump)
+ assert_equal "foo\"bar", parsed["method"]
+ ensure
+ ObjectSpace.trace_object_allocations_stop
+ end
+
def test_dump_reference_addresses_match_dump_all_addresses
assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
begin;
@@ -368,8 +448,9 @@ class TestObjSpace < Test::Unit::TestCase
ObjectSpace.dump_all(output: $stdout)
end
- dump_my_heap_please
+ p $stdout == dump_my_heap_please
end;
+ assert_equal 'true', output.pop
needle = JSON.parse(output.first)
addr = needle['address']
found = output.drop(1).find { |l| (JSON.parse(l)['references'] || []).include? addr }
@@ -390,8 +471,9 @@ class TestObjSpace < Test::Unit::TestCase
ObjectSpace.dump_all(output: :stdout)
end
- dump_my_heap_please
+ p dump_my_heap_please
end;
+ assert_equal 'nil', output.pop
assert_match(entry, output.grep(/TEST STRING/).join("\n"))
end
@@ -454,6 +536,20 @@ class TestObjSpace < Test::Unit::TestCase
assert_operator i, :>, 0
end
+ def test_internal_class_of_on_ast
+ children = ObjectSpace.reachable_objects_from(RubyVM::AbstractSyntaxTree.parse("kadomatsu"))
+ children.each {|child| ObjectSpace.internal_class_of(child).itself} # this used to crash
+ end
+
+ def test_name_error_message
+ begin
+ bar
+ rescue => err
+ _, m = ObjectSpace.reachable_objects_from(err)
+ end
+ assert_equal(m, m.clone)
+ end
+
def traverse_super_classes klass
while klass
klass = ObjectSpace.internal_super_of(klass)
@@ -503,4 +599,9 @@ class TestObjSpace < Test::Unit::TestCase
assert_equal h[:immortal_symbol], h[:immortal_dynamic_symbol] + h[:immortal_static_symbol], m
;;;
end
+
+ def test_anonymous_class_name
+ assert_not_include ObjectSpace.dump(Class.new), '"name"'
+ assert_not_include ObjectSpace.dump(Module.new), '"name"'
+ end
end
diff --git a/test/open-uri/test_open-uri.rb b/test/open-uri/test_open-uri.rb
index 0c7d77c305..9a52e7a287 100644
--- a/test/open-uri/test_open-uri.rb
+++ b/test/open-uri/test_open-uri.rb
@@ -68,18 +68,6 @@ class TestOpenURI < Test::Unit::TestCase
@proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] }
end
- def test_deprecated_kernel_open
- with_http {|srv, dr, url|
- srv.mount_proc("/foo200", lambda { |req, res| res.body = "foo200" } )
- assert_warning(/calling URI.open via Kernel#open is deprecated, call URI.open directly/) {
- open("#{url}/foo200") {|f|
- assert_equal("200", f.status[0])
- assert_equal("foo200", f.read)
- }
- }
- }
- end
-
def test_200_uri_open
with_http {|srv, dr, url|
srv.mount_proc("/urifoo200", lambda { |req, res| res.body = "urifoo200" } )
diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb
index 1170703775..af069cad6e 100644
--- a/test/openssl/test_asn1.rb
+++ b/test/openssl/test_asn1.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -14,7 +14,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
["keyUsage","keyCertSign, cRLSign",true],
["subjectKeyIdentifier","hash",false],
]
- dgst = OpenSSL::Digest::SHA1.new
+ dgst = OpenSSL::Digest.new('SHA1')
cert = OpenSSL::TestUtils.issue_cert(
subj, key, s, exts, nil, nil, digest: dgst, not_before: now, not_after: now+3600)
@@ -167,7 +167,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
assert_equal(OpenSSL::ASN1::OctetString, ext.value[2].class)
extv = OpenSSL::ASN1.decode(ext.value[2].value)
assert_equal(OpenSSL::ASN1::BitString, extv.class)
- str = "\000"; str[0] = 0b00000110.chr
+ str = +"\000"; str[0] = 0b00000110.chr
assert_equal(str, extv.value)
ext = extensions.value[0].value[2] # subjetKeyIdentifier
@@ -178,7 +178,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
assert_equal(OpenSSL::ASN1::OctetString, ext.value[1].class)
extv = OpenSSL::ASN1.decode(ext.value[1].value)
assert_equal(OpenSSL::ASN1::OctetString, extv.class)
- sha1 = OpenSSL::Digest::SHA1.new
+ sha1 = OpenSSL::Digest.new('SHA1')
sha1.update(pkey.value[1].value)
assert_equal(sha1.digest, extv.value)
@@ -189,7 +189,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
assert_equal(OpenSSL::ASN1::Null, pkey.value[0].value[1].class)
assert_equal(OpenSSL::ASN1::BitString, sig_val.class)
- cululated_sig = key.sign(OpenSSL::Digest::SHA1.new, tbs_cert.to_der)
+ cululated_sig = key.sign(OpenSSL::Digest.new('SHA1'), tbs_cert.to_der)
assert_equal(cululated_sig, sig_val.value)
end
@@ -332,6 +332,32 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
pend "OBJ_obj2txt() not working (LibreSSL?)" if $!.message =~ /OBJ_obj2txt/
raise
end
+
+ aki = [
+ OpenSSL::ASN1::ObjectId.new("authorityKeyIdentifier"),
+ OpenSSL::ASN1::ObjectId.new("X509v3 Authority Key Identifier"),
+ OpenSSL::ASN1::ObjectId.new("2.5.29.35")
+ ]
+
+ ski = [
+ OpenSSL::ASN1::ObjectId.new("subjectKeyIdentifier"),
+ OpenSSL::ASN1::ObjectId.new("X509v3 Subject Key Identifier"),
+ OpenSSL::ASN1::ObjectId.new("2.5.29.14")
+ ]
+
+ aki.each do |a|
+ aki.each do |b|
+ assert a == b
+ end
+
+ ski.each do |b|
+ refute a == b
+ end
+ end
+
+ assert_raise(TypeError) {
+ OpenSSL::ASN1::ObjectId.new("authorityKeyIdentifier") == nil
+ }
end
def test_sequence
@@ -635,6 +661,11 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
assert_equal data, seq.entries
end
+ # Very time consuming test.
+ # def test_gc_stress
+ # assert_ruby_status(['--disable-gems', '-eGC.stress=true', '-erequire "openssl.so"'])
+ # end
+
private
def B(ary)
diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb
index 274afba3bb..547d334c64 100644
--- a/test/openssl/test_bn.rb
+++ b/test/openssl/test_bn.rb
@@ -1,5 +1,5 @@
# coding: us-ascii
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
require "prime"
@@ -15,6 +15,10 @@ class OpenSSL::TestBN < OpenSSL::TestCase
end
def test_new
+ assert_raise(ArgumentError) { OpenSSL::BN.new }
+ assert_raise(ArgumentError) { OpenSSL::BN.new(nil) }
+ assert_raise(ArgumentError) { OpenSSL::BN.new(nil, 2) }
+
assert_equal(@e1, OpenSSL::BN.new("999"))
assert_equal(@e1, OpenSSL::BN.new("999", 10))
assert_equal(@e1, OpenSSL::BN.new("\x03\xE7", 2))
@@ -272,6 +276,11 @@ class OpenSSL::TestBN < OpenSSL::TestCase
assert_equal(0, @e1.ucmp(-999))
assert_instance_of(String, @e1.hash.to_s)
end
+
+ def test_argument_error
+ bug15760 = '[ruby-core:92231] [Bug #15760]'
+ assert_raise(ArgumentError, bug15760) { OpenSSL::BN.new(nil, 2) }
+ end
end
end
diff --git a/test/openssl/test_buffering.rb b/test/openssl/test_buffering.rb
index c85a6f020b..7575c5b4fe 100644
--- a/test/openssl/test_buffering.rb
+++ b/test/openssl/test_buffering.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -10,7 +10,7 @@ class OpenSSL::TestBuffering < OpenSSL::TestCase
attr_accessor :sync
def initialize
- @io = ""
+ @io = Buffer.new
def @io.sync
true
end
@@ -41,6 +41,13 @@ class OpenSSL::TestBuffering < OpenSSL::TestCase
@io = IO.new
end
+ def test_encoding
+ @io.write '😊'
+ @io.flush
+
+ assert_equal @io.string.encoding, Encoding::BINARY
+ end
+
def test_flush
@io.write 'a'
diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb
index d83fa4ec3d..ef8c4f3a4a 100644
--- a/test/openssl/test_cipher.rb
+++ b/test/openssl/test_cipher.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -36,8 +36,8 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
cipher.pkcs5_keyivgen(pass, salt, num, "MD5")
s1 = cipher.update(pt) << cipher.final
- d1 = num.times.inject(pass + salt) {|out, _| OpenSSL::Digest::MD5.digest(out) }
- d2 = num.times.inject(d1 + pass + salt) {|out, _| OpenSSL::Digest::MD5.digest(out) }
+ d1 = num.times.inject(pass + salt) {|out, _| OpenSSL::Digest.digest('MD5', out) }
+ d2 = num.times.inject(d1 + pass + salt) {|out, _| OpenSSL::Digest.digest('MD5', out) }
key = (d1 + d2)[0, 24]
iv = (d1 + d2)[24, 8]
cipher = new_encryptor("DES-EDE3-CBC", key: key, iv: iv)
@@ -148,12 +148,12 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
def test_AES
pt = File.read(__FILE__)
%w(ECB CBC CFB OFB).each{|mode|
- c1 = OpenSSL::Cipher::AES256.new(mode)
+ c1 = OpenSSL::Cipher.new("AES-256-#{mode}")
c1.encrypt
c1.pkcs5_keyivgen("passwd")
ct = c1.update(pt) + c1.final
- c2 = OpenSSL::Cipher::AES256.new(mode)
+ c2 = OpenSSL::Cipher.new("AES-256-#{mode}")
c2.decrypt
c2.pkcs5_keyivgen("passwd")
assert_equal(pt, c2.update(ct) + c2.final)
@@ -163,7 +163,7 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
def test_update_raise_if_key_not_set
assert_raise(OpenSSL::Cipher::CipherError) do
# it caused OpenSSL SEGV by uninitialized key [Bug #2768]
- OpenSSL::Cipher::AES128.new("ECB").update "." * 17
+ OpenSSL::Cipher.new("AES-128-ECB").update "." * 17
end
end
@@ -174,6 +174,54 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
assert_not_predicate(cipher, :authenticated?)
end
+ def test_aes_ccm
+ # RFC 3610 Section 8, Test Case 1
+ key = ["c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"].pack("H*")
+ iv = ["00000003020100a0a1a2a3a4a5"].pack("H*")
+ aad = ["0001020304050607"].pack("H*")
+ pt = ["08090a0b0c0d0e0f101112131415161718191a1b1c1d1e"].pack("H*")
+ ct = ["588c979a61c663d2f066d0c2c0f989806d5f6b61dac384"].pack("H*")
+ tag = ["17e8d12cfdf926e0"].pack("H*")
+
+ kwargs = {auth_tag_len: 8, iv_len: 13, key: key, iv: iv}
+ cipher = new_encryptor("aes-128-ccm", **kwargs, ccm_data_len: pt.length, auth_data: aad)
+ assert_equal ct, cipher.update(pt) << cipher.final
+ assert_equal tag, cipher.auth_tag
+ cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag, auth_data: aad)
+ assert_equal pt, cipher.update(ct) << cipher.final
+
+ # truncated tag is accepted
+ cipher = new_encryptor("aes-128-ccm", **kwargs, ccm_data_len: pt.length, auth_data: aad)
+ assert_equal ct, cipher.update(pt) << cipher.final
+ assert_equal tag[0, 8], cipher.auth_tag(8)
+ cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag[0, 8], auth_data: aad)
+ assert_equal pt, cipher.update(ct) << cipher.final
+
+ # wrong tag is rejected
+ tag2 = tag.dup
+ tag2.setbyte(-1, (tag2.getbyte(-1) + 1) & 0xff)
+ cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag2, auth_data: aad)
+ assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct) }
+
+ # wrong aad is rejected
+ aad2 = aad[0..-2] << aad[-1].succ
+ cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct.length, auth_tag: tag, auth_data: aad2)
+ assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct) }
+
+ # wrong ciphertext is rejected
+ ct2 = ct[0..-2] << ct[-1].succ
+ cipher = new_decryptor("aes-128-ccm", **kwargs, ccm_data_len: ct2.length, auth_tag: tag, auth_data: aad)
+ assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct2) }
+ rescue OpenSSL::Cipher::CipherError
+ if /mingw/i =~ RUBY_PLATFORM
+ omit "skip on OpenSSL::Cipher::CipherError from 'ccm_data_len=': Maybe it's because of OpenSSL in MinGW"
+ else
+ raise
+ end
+ end if has_cipher?("aes-128-ccm") &&
+ OpenSSL::Cipher.new("aes-128-ccm").authenticated? &&
+ OpenSSL::OPENSSL_VERSION_NUMBER >= 0x1010103f # version >= 1.1.1c
+
def test_aes_gcm
# GCM spec Appendix B Test Case 4
key = ["feffe9928665731c6d6a8f9467308308"].pack("H*")
@@ -305,6 +353,21 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
}
end
+ def test_crypt_after_key
+ key = ["2b7e151628aed2a6abf7158809cf4f3c"].pack("H*")
+ %w'ecb cbc cfb ctr gcm'.each do |c|
+ cipher = OpenSSL::Cipher.new("aes-128-#{c}")
+ cipher.key = key
+ cipher.encrypt
+ assert_raise(OpenSSL::Cipher::CipherError) { cipher.update("") }
+
+ cipher = OpenSSL::Cipher.new("aes-128-#{c}")
+ cipher.key = key
+ cipher.decrypt
+ assert_raise(OpenSSL::Cipher::CipherError) { cipher.update("") }
+ end
+ end
+
private
def new_encryptor(algo, **kwargs)
diff --git a/test/openssl/test_config.rb b/test/openssl/test_config.rb
index c1a01d4dbe..e041c1a3ba 100644
--- a/test/openssl/test_config.rb
+++ b/test/openssl/test_config.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -254,45 +254,54 @@ __EOC__
def test_sections
assert_equal(['CA_default', 'ca', 'default'], @it.sections.sort)
- @it['new_section'] = {'foo' => 'bar'}
- assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort)
- @it['new_section'] = {}
- assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort)
+ # OpenSSL::Config#[]= is deprecated
+ EnvUtil.suppress_warning do
+ @it['new_section'] = {'foo' => 'bar'}
+ assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort)
+ @it['new_section'] = {}
+ assert_equal(['CA_default', 'ca', 'default', 'new_section'], @it.sections.sort)
+ end
end
def test_add_value
- c = OpenSSL::Config.new
- assert_equal("", c.to_s)
- # add key
- c.add_value('default', 'foo', 'bar')
- assert_equal("[ default ]\nfoo=bar\n\n", c.to_s)
- # add another key
- c.add_value('default', 'baz', 'qux')
- assert_equal('bar', c['default']['foo'])
- assert_equal('qux', c['default']['baz'])
- # update the value
- c.add_value('default', 'baz', 'quxxx')
- assert_equal('bar', c['default']['foo'])
- assert_equal('quxxx', c['default']['baz'])
- # add section and key
- c.add_value('section', 'foo', 'bar')
- assert_equal('bar', c['default']['foo'])
- assert_equal('quxxx', c['default']['baz'])
- assert_equal('bar', c['section']['foo'])
+ # OpenSSL::Config#add_value is deprecated
+ EnvUtil.suppress_warning do
+ c = OpenSSL::Config.new
+ assert_equal("", c.to_s)
+ # add key
+ c.add_value('default', 'foo', 'bar')
+ assert_equal("[ default ]\nfoo=bar\n\n", c.to_s)
+ # add another key
+ c.add_value('default', 'baz', 'qux')
+ assert_equal('bar', c['default']['foo'])
+ assert_equal('qux', c['default']['baz'])
+ # update the value
+ c.add_value('default', 'baz', 'quxxx')
+ assert_equal('bar', c['default']['foo'])
+ assert_equal('quxxx', c['default']['baz'])
+ # add section and key
+ c.add_value('section', 'foo', 'bar')
+ assert_equal('bar', c['default']['foo'])
+ assert_equal('quxxx', c['default']['baz'])
+ assert_equal('bar', c['section']['foo'])
+ end
end
def test_aset
- @it['foo'] = {'bar' => 'baz'}
- assert_equal({'bar' => 'baz'}, @it['foo'])
- @it['foo'] = {'bar' => 'qux', 'baz' => 'quxx'}
- assert_equal({'bar' => 'qux', 'baz' => 'quxx'}, @it['foo'])
-
- # OpenSSL::Config is add only for now.
- @it['foo'] = {'foo' => 'foo'}
- assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo'])
- # you cannot override or remove any section and key.
- @it['foo'] = {}
- assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo'])
+ # OpenSSL::Config#[]= is deprecated
+ EnvUtil.suppress_warning do
+ @it['foo'] = {'bar' => 'baz'}
+ assert_equal({'bar' => 'baz'}, @it['foo'])
+ @it['foo'] = {'bar' => 'qux', 'baz' => 'quxx'}
+ assert_equal({'bar' => 'qux', 'baz' => 'quxx'}, @it['foo'])
+
+ # OpenSSL::Config is add only for now.
+ @it['foo'] = {'foo' => 'foo'}
+ assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo'])
+ # you cannot override or remove any section and key.
+ @it['foo'] = {}
+ assert_equal({'foo' => 'foo', 'bar' => 'qux', 'baz' => 'quxx'}, @it['foo'])
+ end
end
def test_each
@@ -315,32 +324,39 @@ __EOC__
end
def test_freeze
- c = OpenSSL::Config.new
- c['foo'] = [['key', 'value']]
- c.freeze
+ @it.freeze
- bug = '[ruby-core:18377]'
- # RuntimeError for 1.9, TypeError for 1.8
- e = assert_raise(TypeError, bug) do
- c['foo'] = [['key', 'wrong']]
+ # Modifying OpenSSL::Config produces a warning
+ EnvUtil.suppress_warning do
+ bug = '[ruby-core:18377]'
+ # RuntimeError for 1.9, TypeError for 1.8
+ e = assert_raise(TypeError, bug) do
+ @it['foo'] = [['key', 'wrong']]
+ end
+ assert_match(/can't modify/, e.message, bug)
end
- assert_match(/can't modify/, e.message, bug)
end
def test_dup
assert(!@it.sections.empty?)
c = @it.dup
assert_equal(@it.sections.sort, c.sections.sort)
- @it['newsection'] = {'a' => 'b'}
- assert_not_equal(@it.sections.sort, c.sections.sort)
+ # OpenSSL::Config#[]= is deprecated
+ EnvUtil.suppress_warning do
+ @it['newsection'] = {'a' => 'b'}
+ assert_not_equal(@it.sections.sort, c.sections.sort)
+ end
end
def test_clone
assert(!@it.sections.empty?)
c = @it.clone
assert_equal(@it.sections.sort, c.sections.sort)
- @it['newsection'] = {'a' => 'b'}
- assert_not_equal(@it.sections.sort, c.sections.sort)
+ # OpenSSL::Config#[]= is deprecated
+ EnvUtil.suppress_warning do
+ @it['newsection'] = {'a' => 'b'}
+ assert_not_equal(@it.sections.sort, c.sections.sort)
+ end
end
private
diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb
index 2cb878b6fa..8d7046e831 100644
--- a/test/openssl/test_digest.rb
+++ b/test/openssl/test_digest.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -21,8 +21,8 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
@d1 << data
assert_equal(bin, @d1.digest)
assert_equal(hex, @d1.hexdigest)
- assert_equal(bin, OpenSSL::Digest::MD5.digest(data))
- assert_equal(hex, OpenSSL::Digest::MD5.hexdigest(data))
+ assert_equal(bin, OpenSSL::Digest.digest('MD5', data))
+ assert_equal(hex, OpenSSL::Digest.hexdigest('MD5', data))
end
def test_eql
@@ -54,13 +54,9 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
end
def test_digest_constants
- algs = %w(MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512)
- if !libressl? && !openssl?(1, 1, 0)
- algs += %w(DSS1 SHA)
- end
- algs.each do |alg|
- assert_not_nil(OpenSSL::Digest.new(alg))
- klass = OpenSSL::Digest.const_get(alg)
+ %w{MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512}.each do |name|
+ assert_not_nil(OpenSSL::Digest.new(name))
+ klass = OpenSSL::Digest.const_get(name.tr('-', '_'))
assert_not_nil(klass.new)
end
end
@@ -80,15 +76,39 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
sha384_a = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31"
sha512_a = "1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75"
- assert_equal(sha224_a, OpenSSL::Digest::SHA224.hexdigest("a"))
- assert_equal(sha256_a, OpenSSL::Digest::SHA256.hexdigest("a"))
- assert_equal(sha384_a, OpenSSL::Digest::SHA384.hexdigest("a"))
- assert_equal(sha512_a, OpenSSL::Digest::SHA512.hexdigest("a"))
+ assert_equal(sha224_a, OpenSSL::Digest.hexdigest('SHA224', "a"))
+ assert_equal(sha256_a, OpenSSL::Digest.hexdigest('SHA256', "a"))
+ assert_equal(sha384_a, OpenSSL::Digest.hexdigest('SHA384', "a"))
+ assert_equal(sha512_a, OpenSSL::Digest.hexdigest('SHA512', "a"))
+
+ assert_equal(sha224_a, encode16(OpenSSL::Digest.digest('SHA224', "a")))
+ assert_equal(sha256_a, encode16(OpenSSL::Digest.digest('SHA256', "a")))
+ assert_equal(sha384_a, encode16(OpenSSL::Digest.digest('SHA384', "a")))
+ assert_equal(sha512_a, encode16(OpenSSL::Digest.digest('SHA512', "a")))
+ end
+
+ def test_sha512_truncate
+ pend "SHA512_224 is not implemented" unless digest_available?('SHA512-224')
+ sha512_224_a = "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327"
+ sha512_256_a = "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8"
+
+ assert_equal(sha512_224_a, OpenSSL::Digest.hexdigest('SHA512-224', "a"))
+ assert_equal(sha512_256_a, OpenSSL::Digest.hexdigest('SHA512-256', "a"))
- assert_equal(sha224_a, encode16(OpenSSL::Digest::SHA224.digest("a")))
- assert_equal(sha256_a, encode16(OpenSSL::Digest::SHA256.digest("a")))
- assert_equal(sha384_a, encode16(OpenSSL::Digest::SHA384.digest("a")))
- assert_equal(sha512_a, encode16(OpenSSL::Digest::SHA512.digest("a")))
+ assert_equal(sha512_224_a, encode16(OpenSSL::Digest.digest('SHA512-224', "a")))
+ assert_equal(sha512_256_a, encode16(OpenSSL::Digest.digest('SHA512-256', "a")))
+ end
+
+ def test_sha3
+ pend "SHA3 is not implemented" unless digest_available?('SHA3-224')
+ s224 = '6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7'
+ s256 = 'a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a'
+ s384 = '0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004'
+ s512 = 'a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26'
+ assert_equal(OpenSSL::Digest.hexdigest('SHA3-224', ""), s224)
+ assert_equal(OpenSSL::Digest.hexdigest('SHA3-256', ""), s256)
+ assert_equal(OpenSSL::Digest.hexdigest('SHA3-384', ""), s384)
+ assert_equal(OpenSSL::Digest.hexdigest('SHA3-512', ""), s512)
end
def test_digest_by_oid_and_name_sha2
@@ -116,6 +136,14 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
d = OpenSSL::Digest.new(oid.oid)
assert_not_nil(d)
end
+
+ def digest_available?(name)
+ begin
+ OpenSSL::Digest.new(name)
+ rescue RuntimeError
+ false
+ end
+ end
end
end
diff --git a/test/openssl/test_engine.rb b/test/openssl/test_engine.rb
index bb1123d516..1ede6ed086 100644
--- a/test/openssl/test_engine.rb
+++ b/test/openssl/test_engine.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL) && defined?(OpenSSL::Engine)
@@ -47,7 +47,7 @@ class OpenSSL::TestEngine < OpenSSL::TestCase
digest = engine.digest("SHA1")
assert_not_nil(digest)
data = "test"
- assert_equal(OpenSSL::Digest::SHA1.digest(data), digest.digest(data))
+ assert_equal(OpenSSL::Digest.digest('SHA1', data), digest.digest(data))
end;
end
diff --git a/test/openssl/test_fips.rb b/test/openssl/test_fips.rb
index a577d7891e..8cd474f9a3 100644
--- a/test/openssl/test_fips.rb
+++ b/test/openssl/test_fips.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb
index 831a5b6b37..9cb3c5a864 100644
--- a/test/openssl/test_hmac.rb
+++ b/test/openssl/test_hmac.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -39,6 +39,16 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase
second = h1.update("test").hexdigest
assert_equal first, second
end
+
+ def test_eq
+ h1 = OpenSSL::HMAC.new("KEY", "MD5")
+ h2 = OpenSSL::HMAC.new("KEY", OpenSSL::Digest.new("MD5"))
+ h3 = OpenSSL::HMAC.new("FOO", "MD5")
+
+ assert_equal h1, h2
+ refute_equal h1, h2.digest
+ refute_equal h1, h3
+ end
end
end
diff --git a/test/openssl/test_kdf.rb b/test/openssl/test_kdf.rb
index 5e1db80c5f..f4790c96af 100644
--- a/test/openssl/test_kdf.rb
+++ b/test/openssl/test_kdf.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
diff --git a/test/openssl/test_ns_spki.rb b/test/openssl/test_ns_spki.rb
index aa1e61824f..ed3be86e2c 100644
--- a/test/openssl/test_ns_spki.rb
+++ b/test/openssl/test_ns_spki.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -9,7 +9,7 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase
# This request data is adopt from the specification of
# "Netscape Extensions for User Key Generation".
# -- http://wp.netscape.com/eng/security/comm4-keygen.html
- @b64 = "MIHFMHEwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAnX0TILJrOMUue+PtwBRE6XfV"
+ @b64 = +"MIHFMHEwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAnX0TILJrOMUue+PtwBRE6XfV"
@b64 << "WtKQbsshxk5ZhcUwcwyvcnIq9b82QhJdoACdD34rqfCAIND46fXKQUnb0mvKzQID"
@b64 << "AQABFhFNb3ppbGxhSXNNeUZyaWVuZDANBgkqhkiG9w0BAQQFAANBAAKv2Eex2n/S"
@b64 << "r/7iJNroWlSzSMtTiQTEB+ADWHGj9u1xrUrOilq/o2cuQxIfZcNZkYAkWP4DubqW"
@@ -22,7 +22,7 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase
spki = OpenSSL::Netscape::SPKI.new
spki.challenge = "RandomString"
spki.public_key = key1.public_key
- spki.sign(key1, OpenSSL::Digest::SHA1.new)
+ spki.sign(key1, OpenSSL::Digest.new('SHA1'))
assert(spki.verify(spki.public_key))
assert(spki.verify(key1.public_key))
assert(!spki.verify(key2.public_key))
diff --git a/test/openssl/test_ocsp.rb b/test/openssl/test_ocsp.rb
index 50ad6c31f5..b3c4caf578 100644
--- a/test/openssl/test_ocsp.rb
+++ b/test/openssl/test_ocsp.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
@@ -50,26 +50,26 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert)
assert_kind_of OpenSSL::OCSP::CertificateId, cid
assert_equal @cert.serial, cid.serial
- cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA256.new)
+ cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA256'))
assert_kind_of OpenSSL::OCSP::CertificateId, cid
assert_equal @cert.serial, cid.serial
end
def test_certificate_id_issuer_name_hash
cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert)
- assert_equal OpenSSL::Digest::SHA1.hexdigest(@cert.issuer.to_der), cid.issuer_name_hash
+ assert_equal OpenSSL::Digest.hexdigest('SHA1', @cert.issuer.to_der), cid.issuer_name_hash
assert_equal "d91f736ac4dc3242f0fb9b77a3149bd83c5c43d0", cid.issuer_name_hash
end
def test_certificate_id_issuer_key_hash
cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert)
- assert_equal OpenSSL::Digest::SHA1.hexdigest(OpenSSL::ASN1.decode(@ca_cert.to_der).value[0].value[6].value[1].value), cid.issuer_key_hash
+ assert_equal OpenSSL::Digest.hexdigest('SHA1', OpenSSL::ASN1.decode(@ca_cert.to_der).value[0].value[6].value[1].value), cid.issuer_key_hash
assert_equal "d1fef9fbf8ae1bc160cbfa03e2596dd873089213", cid.issuer_key_hash
end
def test_certificate_id_hash_algorithm
- cid_sha1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new)
- cid_sha256 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA256.new)
+ cid_sha1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
+ cid_sha256 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA256'))
assert_equal "sha1", cid_sha1.hash_algorithm
assert_equal "sha256", cid_sha256.hash_algorithm
end
@@ -84,6 +84,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
assert_equal [cid.issuer_key_hash].pack("H*"), asn1.value[2].value
assert_equal @cert.serial, asn1.value[3].value
assert_equal der, OpenSSL::OCSP::CertificateId.new(der).to_der
+ assert_equal der, OpenSSL::OCSP::CertificateId.new(asn1).to_der
end
def test_certificate_id_dup
@@ -93,7 +94,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
def test_request_der
request = OpenSSL::OCSP::Request.new
- cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new)
+ cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
request.add_certid(cid)
request.sign(@cert, @cert_key, [@ca_cert], 0)
asn1 = OpenSSL::ASN1.decode(request.to_der)
@@ -163,14 +164,14 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
def test_request_dup
request = OpenSSL::OCSP::Request.new
- cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new)
+ cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
request.add_certid(cid)
assert_equal request.to_der, request.dup.to_der
end
def test_basic_response_der
bres = OpenSSL::OCSP::BasicResponse.new
- cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new)
+ cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0, nil, -300, 500, [])
bres.add_nonce("NONCE")
bres.sign(@ocsp_cert, @ocsp_key, [@ca_cert], 0)
@@ -213,7 +214,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
def test_basic_response_dup
bres = OpenSSL::OCSP::BasicResponse.new
- cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new)
+ cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0, nil, -300, 500, [])
bres.sign(@ocsp_cert, @ocsp_key, [@ca_cert], 0)
assert_equal bres.to_der, bres.dup.to_der
@@ -222,9 +223,9 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
def test_basic_response_response_operations
bres = OpenSSL::OCSP::BasicResponse.new
now = Time.at(Time.now.to_i)
- cid1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new)
- cid2 = OpenSSL::OCSP::CertificateId.new(@ocsp_cert, @ca_cert, OpenSSL::Digest::SHA1.new)
- cid3 = OpenSSL::OCSP::CertificateId.new(@ca_cert, @ca_cert, OpenSSL::Digest::SHA1.new)
+ cid1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
+ cid2 = OpenSSL::OCSP::CertificateId.new(@ocsp_cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
+ cid3 = OpenSSL::OCSP::CertificateId.new(@ca_cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
bres.add_status(cid1, OpenSSL::OCSP::V_CERTSTATUS_REVOKED, OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, now - 400, -300, nil, nil)
bres.add_status(cid2, OpenSSL::OCSP::V_CERTSTATUS_GOOD, nil, nil, -300, 500, [])
@@ -256,8 +257,8 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
def test_single_response_check_validity
bres = OpenSSL::OCSP::BasicResponse.new
- cid1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new)
- cid2 = OpenSSL::OCSP::CertificateId.new(@ocsp_cert, @ca_cert, OpenSSL::Digest::SHA1.new)
+ cid1 = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
+ cid2 = OpenSSL::OCSP::CertificateId.new(@ocsp_cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
bres.add_status(cid1, OpenSSL::OCSP::V_CERTSTATUS_REVOKED, OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, -400, -300, -50, [])
bres.add_status(cid2, OpenSSL::OCSP::V_CERTSTATUS_REVOKED, OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, -400, -300, nil, [])
bres.add_status(cid2, OpenSSL::OCSP::V_CERTSTATUS_GOOD, nil, nil, Time.now + 100, nil, nil)
@@ -276,7 +277,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
def test_response
bres = OpenSSL::OCSP::BasicResponse.new
- cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new)
+ cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0, nil, -300, 500, [])
bres.sign(@ocsp_cert, @ocsp_key, [])
res = OpenSSL::OCSP::Response.create(OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL, bres)
@@ -287,7 +288,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
def test_response_der
bres = OpenSSL::OCSP::BasicResponse.new
- cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest::SHA1.new)
+ cid = OpenSSL::OCSP::CertificateId.new(@cert, @ca_cert, OpenSSL::Digest.new('SHA1'))
bres.add_status(cid, OpenSSL::OCSP::V_CERTSTATUS_GOOD, 0, nil, -300, 500, [])
bres.sign(@ocsp_cert, @ocsp_key, [@ca_cert], 0)
res = OpenSSL::OCSP::Response.create(OpenSSL::OCSP::RESPONSE_STATUS_SUCCESSFUL, bres)
diff --git a/test/openssl/test_ossl.rb b/test/openssl/test_ossl.rb
new file mode 100644
index 0000000000..e1d86bd40b
--- /dev/null
+++ b/test/openssl/test_ossl.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+require_relative "utils"
+
+require 'benchmark'
+
+if defined?(OpenSSL)
+
+class OpenSSL::OSSL < OpenSSL::SSLTestCase
+ def test_fixed_length_secure_compare
+ assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "a") }
+ assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "aa") }
+
+ assert OpenSSL.fixed_length_secure_compare("aaa", "aaa")
+ assert OpenSSL.fixed_length_secure_compare(
+ OpenSSL::Digest.digest('SHA256', "aaa"), OpenSSL::Digest::SHA256.digest("aaa")
+ )
+
+ assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "aaaa") }
+ refute OpenSSL.fixed_length_secure_compare("aaa", "baa")
+ refute OpenSSL.fixed_length_secure_compare("aaa", "aba")
+ refute OpenSSL.fixed_length_secure_compare("aaa", "aab")
+ assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "aaab") }
+ assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "b") }
+ assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "bb") }
+ refute OpenSSL.fixed_length_secure_compare("aaa", "bbb")
+ assert_raise(ArgumentError) { OpenSSL.fixed_length_secure_compare("aaa", "bbbb") }
+ end
+
+ def test_secure_compare
+ refute OpenSSL.secure_compare("aaa", "a")
+ refute OpenSSL.secure_compare("aaa", "aa")
+
+ assert OpenSSL.secure_compare("aaa", "aaa")
+
+ refute OpenSSL.secure_compare("aaa", "aaaa")
+ refute OpenSSL.secure_compare("aaa", "baa")
+ refute OpenSSL.secure_compare("aaa", "aba")
+ refute OpenSSL.secure_compare("aaa", "aab")
+ refute OpenSSL.secure_compare("aaa", "aaab")
+ refute OpenSSL.secure_compare("aaa", "b")
+ refute OpenSSL.secure_compare("aaa", "bb")
+ refute OpenSSL.secure_compare("aaa", "bbb")
+ refute OpenSSL.secure_compare("aaa", "bbbb")
+ end
+
+ def test_memcmp_timing
+ # Ensure using fixed_length_secure_compare takes almost exactly the same amount of time to compare two different strings.
+ # Regular string comparison will short-circuit on the first non-matching character, failing this test.
+ # NOTE: this test may be susceptible to noise if the system running the tests is otherwise under load.
+ a = "x" * 512_000
+ b = "#{a}y"
+ c = "y#{a}"
+ a = "#{a}x"
+
+ a_b_time = a_c_time = 0
+ 100.times do
+ a_b_time += Benchmark.measure { 100.times { OpenSSL.fixed_length_secure_compare(a, b) } }.real
+ a_c_time += Benchmark.measure { 100.times { OpenSSL.fixed_length_secure_compare(a, c) } }.real
+ end
+ assert_operator(a_b_time, :<, a_c_time * 10, "fixed_length_secure_compare timing test failed")
+ assert_operator(a_c_time, :<, a_b_time * 10, "fixed_length_secure_compare timing test failed")
+ end
+end
+
+end
diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb
index 08c15a0f75..8316ec2a9c 100644
--- a/test/openssl/test_pair.rb
+++ b/test/openssl/test_pair.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
require_relative 'ut_eof'
@@ -128,11 +128,11 @@ module OpenSSL::TestPairM
ssl_pair {|s1, s2|
s2.write "a\nbcd"
assert_equal("a\n", s1.gets)
- result = ""
+ result = String.new
result << s1.readpartial(10) until result.length == 3
assert_equal("bcd", result)
s2.write "efg"
- result = ""
+ result = String.new
result << s1.readpartial(10) until result.length == 3
assert_equal("efg", result)
s2.close
@@ -156,20 +156,6 @@ module OpenSSL::TestPairM
}
end
- def test_puts_meta
- ssl_pair {|s1, s2|
- begin
- old = $/
- $/ = '*'
- s1.puts 'a'
- ensure
- $/ = old
- end
- s1.close
- assert_equal("a\n", s2.read)
- }
- end
-
def test_puts_empty
ssl_pair {|s1, s2|
s1.puts
@@ -242,22 +228,22 @@ module OpenSSL::TestPairM
def test_read_with_outbuf
ssl_pair { |s1, s2|
s1.write("abc\n")
- buf = ""
+ buf = String.new
ret = s2.read(2, buf)
assert_same ret, buf
assert_equal "ab", ret
- buf = "garbage"
+ buf = +"garbage"
ret = s2.read(2, buf)
assert_same ret, buf
assert_equal "c\n", ret
- buf = "garbage"
+ buf = +"garbage"
assert_equal :wait_readable, s2.read_nonblock(100, buf, exception: false)
assert_equal "", buf
s1.close
- buf = "garbage"
+ buf = +"garbage"
assert_equal nil, s2.read(100, buf)
assert_equal "", buf
}
diff --git a/test/openssl/test_pkcs12.rb b/test/openssl/test_pkcs12.rb
index de8e35ed79..fdbe753b17 100644
--- a/test/openssl/test_pkcs12.rb
+++ b/test/openssl/test_pkcs12.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
diff --git a/test/openssl/test_pkcs7.rb b/test/openssl/test_pkcs7.rb
index 149d3b9b5d..d0d9dcaf81 100644
--- a/test/openssl/test_pkcs7.rb
+++ b/test/openssl/test_pkcs7.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -133,6 +133,8 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase
assert_equal(@ca_cert.subject.to_s, recip[1].issuer.to_s)
assert_equal(3, recip[1].serial)
assert_equal(data, p7.decrypt(@rsa1024, @ee2_cert))
+
+ assert_equal(data, p7.decrypt(@rsa1024))
end
def test_graceful_parsing_failure #[ruby-core:43250]
@@ -170,6 +172,28 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase
assert_equal(:encrypted, p7.type)
end
+ def test_smime
+ store = OpenSSL::X509::Store.new
+ store.add_cert(@ca_cert)
+ ca_certs = [@ca_cert]
+
+ data = "aaaaa\r\nbbbbb\r\nccccc\r\n"
+ tmp = OpenSSL::PKCS7.sign(@ee1_cert, @rsa1024, data, ca_certs)
+ p7 = OpenSSL::PKCS7.new(tmp.to_der)
+ smime = OpenSSL::PKCS7.write_smime(p7)
+ assert_equal(true, smime.start_with?(<<END))
+MIME-Version: 1.0
+Content-Disposition: attachment; filename="smime.p7m"
+Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m"
+Content-Transfer-Encoding: base64
+
+END
+ assert_equal(p7.to_der, OpenSSL::PKCS7.read_smime(smime).to_der)
+
+ smime = OpenSSL::PKCS7.write_smime(p7, nil, 0)
+ assert_equal(p7.to_der, OpenSSL::PKCS7.read_smime(smime).to_der)
+ end
+
def test_degenerate_pkcs7
ca_cert_pem = <<END
-----BEGIN CERTIFICATE-----
diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb
new file mode 100644
index 0000000000..0bdc9795cc
--- /dev/null
+++ b/test/openssl/test_pkey.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+require_relative "utils"
+
+class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
+ def test_generic_oid_inspect
+ # RSA private key
+ rsa = Fixtures.pkey("rsa-1")
+ assert_instance_of OpenSSL::PKey::RSA, rsa
+ assert_equal "rsaEncryption", rsa.oid
+ assert_match %r{oid=rsaEncryption}, rsa.inspect
+
+ # X25519 private key
+ x25519_pem = <<~EOF
+ -----BEGIN PRIVATE KEY-----
+ MC4CAQAwBQYDK2VuBCIEIHcHbQpzGKV9PBbBclGyZkXfTC+H68CZKrF3+6UduSwq
+ -----END PRIVATE KEY-----
+ EOF
+ begin
+ x25519 = OpenSSL::PKey.read(x25519_pem)
+ rescue OpenSSL::PKey::PKeyError
+ # OpenSSL < 1.1.0
+ pend "X25519 is not implemented"
+ end
+ assert_instance_of OpenSSL::PKey::PKey, x25519
+ assert_equal "X25519", x25519.oid
+ assert_match %r{oid=X25519}, x25519.inspect
+ end
+end
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
index 8c8fbaeefb..fd2c7a66a9 100644
--- a/test/openssl/test_pkey_dh.rb
+++ b/test/openssl/test_pkey_dh.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL) && defined?(OpenSSL::PKey::DH)
@@ -74,6 +74,13 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
assert_equal dh2.g, dh.g
end
+ def test_marshal
+ dh = Fixtures.pkey("dh1024")
+ deserialized = Marshal.load(Marshal.dump(dh))
+
+ assert_equal dh.to_der, deserialized.to_der
+ end
+
private
def assert_equal_params(dh1, dh2)
diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
index d651949842..4bf8a7b374 100644
--- a/test/openssl/test_pkey_dsa.rb
+++ b/test/openssl/test_pkey_dsa.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL) && defined?(OpenSSL::PKey::DSA)
@@ -37,8 +37,8 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
dsa512 = Fixtures.pkey("dsa512")
data = "Sign me!"
if defined?(OpenSSL::Digest::DSS1)
- signature = dsa512.sign(OpenSSL::Digest::DSS1.new, data)
- assert_equal true, dsa512.verify(OpenSSL::Digest::DSS1.new, signature, data)
+ signature = dsa512.sign(OpenSSL::Digest.new('DSS1'), data)
+ assert_equal true, dsa512.verify(OpenSSL::Digest.new('DSS1'), signature, data)
end
signature = dsa512.sign("SHA1", data)
@@ -56,7 +56,7 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
def test_sys_sign_verify
key = Fixtures.pkey("dsa256")
data = 'Sign me!'
- digest = OpenSSL::Digest::SHA1.digest(data)
+ digest = OpenSSL::Digest.digest('SHA1', data)
sig = key.syssign(digest)
assert(key.sysverify(digest, sig))
end
@@ -191,6 +191,13 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ==
assert_not_equal key.params, key2.params
end
+ def test_marshal
+ key = Fixtures.pkey("dsa1024")
+ deserialized = Marshal.load(Marshal.dump(key))
+
+ assert_equal key.to_der, deserialized.to_der
+ end
+
private
def assert_same_dsa(expected, key)
check_component(expected, key, [:p, :q, :g, :pub_key, :priv_key])
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index 95b5a6426e..a0e6a23ff8 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL) && defined?(OpenSSL::PKey::EC)
@@ -52,6 +52,13 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
assert_equal(true, ec.private?)
end
+ def test_marshal
+ key = Fixtures.pkey("p256")
+ deserialized = Marshal.load(Marshal.dump(key))
+
+ assert_equal key.to_der, deserialized.to_der
+ end
+
def test_check_key
key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
assert_equal(true, key.check_key)
@@ -289,6 +296,27 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
assert_equal true, point.on_curve?
end
+ def test_ec_point_add
+ begin
+ group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2)
+ group.point_conversion_form = :uncompressed
+ gen = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 05 01 }))
+ group.set_generator(gen, 19, 1)
+
+ point_a = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 06 03 }))
+ point_b = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 10 0D }))
+ rescue OpenSSL::PKey::EC::Group::Error
+ pend "Patched OpenSSL rejected curve" if /unsupported field/ =~ $!.message
+ raise
+ end
+
+ result = point_a.add(point_b)
+ assert_equal B(%w{ 04 0D 07 }), result.to_octet_string(:uncompressed)
+
+ assert_raise(TypeError) { point_a.add(nil) }
+ assert_raise(ArgumentError) { point_a.add }
+ end
+
def test_ec_point_mul
begin
# y^2 = x^3 + 2x + 2 over F_17
diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
index ef02717d8b..88164c3b52 100644
--- a/test/openssl/test_pkey_rsa.rb
+++ b/test/openssl/test_pkey_rsa.rb
@@ -1,9 +1,18 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
+ def test_no_private_exp
+ key = OpenSSL::PKey::RSA.new
+ rsa = Fixtures.pkey("rsa2048")
+ key.set_key(rsa.n, rsa.e, nil)
+ key.set_factors(rsa.p, rsa.q)
+ assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt("foo") }
+ assert_raise(OpenSSL::PKey::RSAError){ key.private_decrypt("foo") }
+ end
+
def test_padding
key = OpenSSL::PKey::RSA.new(512, 3)
@@ -31,14 +40,32 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
end
def test_private
+ # Generated by key size and public exponent
key = OpenSSL::PKey::RSA.new(512, 3)
assert(key.private?)
+
+ # Generated by DER
key2 = OpenSSL::PKey::RSA.new(key.to_der)
assert(key2.private?)
+
+ # public key
key3 = key.public_key
assert(!key3.private?)
+
+ # Generated by public key DER
key4 = OpenSSL::PKey::RSA.new(key3.to_der)
assert(!key4.private?)
+ rsa1024 = Fixtures.pkey("rsa1024")
+
+ # Generated by RSA#set_key
+ key5 = OpenSSL::PKey::RSA.new
+ key5.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
+ assert(key5.private?)
+
+ # Generated by RSA#set_key, without d
+ key6 = OpenSSL::PKey::RSA.new
+ key6.set_key(rsa1024.n, rsa1024.e, nil)
+ assert(!key6.private?)
end
def test_new
@@ -92,8 +119,8 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_digest_state_irrelevant_sign
key = Fixtures.pkey("rsa1024")
- digest1 = OpenSSL::Digest::SHA1.new
- digest2 = OpenSSL::Digest::SHA1.new
+ digest1 = OpenSSL::Digest.new('SHA1')
+ digest2 = OpenSSL::Digest.new('SHA1')
data = 'Sign me!'
digest1 << 'Change state of digest1'
sig1 = key.sign(digest1, data)
@@ -103,8 +130,8 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_digest_state_irrelevant_verify
key = Fixtures.pkey("rsa1024")
- digest1 = OpenSSL::Digest::SHA1.new
- digest2 = OpenSSL::Digest::SHA1.new
+ digest1 = OpenSSL::Digest.new('SHA1')
+ digest2 = OpenSSL::Digest.new('SHA1')
data = 'Sign me!'
sig = key.sign(digest1, data)
digest1.reset
@@ -153,6 +180,40 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
}
end
+ def test_export
+ rsa1024 = Fixtures.pkey("rsa1024")
+ key = OpenSSL::PKey::RSA.new
+
+ # key has only n, e and d
+ key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
+ assert_equal rsa1024.public_key.export, key.export
+
+ # key has only n, e, d, p and q
+ key.set_factors(rsa1024.p, rsa1024.q)
+ assert_equal rsa1024.public_key.export, key.export
+
+ # key has n, e, d, p, q, dmp1, dmq1 and iqmp
+ key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
+ assert_equal rsa1024.export, key.export
+ end
+
+ def test_to_der
+ rsa1024 = Fixtures.pkey("rsa1024")
+ key = OpenSSL::PKey::RSA.new
+
+ # key has only n, e and d
+ key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
+ assert_equal rsa1024.public_key.to_der, key.to_der
+
+ # key has only n, e, d, p and q
+ key.set_factors(rsa1024.p, rsa1024.q)
+ assert_equal rsa1024.public_key.to_der, key.to_der
+
+ # key has n, e, d, p, q, dmp1, dmq1 and iqmp
+ key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
+ assert_equal rsa1024.to_der, key.to_der
+ end
+
def test_RSAPrivateKey
rsa1024 = Fixtures.pkey("rsa1024")
asn1 = OpenSSL::ASN1::Sequence([
@@ -295,6 +356,85 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
}
end
+ def test_private_encoding
+ rsa1024 = Fixtures.pkey("rsa1024")
+ asn1 = OpenSSL::ASN1::Sequence([
+ OpenSSL::ASN1::Integer(0),
+ OpenSSL::ASN1::Sequence([
+ OpenSSL::ASN1::ObjectId("rsaEncryption"),
+ OpenSSL::ASN1::Null(nil)
+ ]),
+ OpenSSL::ASN1::OctetString(rsa1024.to_der)
+ ])
+ assert_equal asn1.to_der, rsa1024.private_to_der
+ assert_same_rsa rsa1024, OpenSSL::PKey.read(asn1.to_der)
+
+ pem = <<~EOF
+ -----BEGIN PRIVATE KEY-----
+ MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAMvCxLDUQKc+1P4+
+ Q6AeFwYDvWfALb+cvzlUEadGoPE6qNWHsLFoo8RFgeyTgE8KQTduu1OE9Zz2SMcR
+ BDu5/1jWtsLPSVrI2ofLLBARUsWanVyki39DeB4u/xkP2mKGjAokPIwOI3oCthSZ
+ lzO9bj3voxTf6XngTqUX8l8URTmHAgMBAAECgYEApKX8xBqvJ7XI7Kypfo/x8MVC
+ 3rxW+1eQ2aVKIo4a7PKGjQz5RVIVyzqTUvSZoMTbkAxlSIbO5YfJpTnl3tFcOB6y
+ QMxqQPW/pl6Ni3EmRJdsRM5MsPBRZOfrXxOCdvXu1TWOS1S1TrvEr/TyL9eh2WCd
+ CGzpWgdO4KHce7vs7pECQQDv6DGoG5lHnvbvj9qSJb9K5ebRJc8S+LI7Uy5JHC0j
+ zsHTYPSqBXwPVQdGbgCEycnwwKzXzT2QxAQmJBQKun2ZAkEA2W3aeAE7Xi6zo2eG
+ 4Cx4UNMHMIdfBRS7VgoekwybGmcapqV0aBew5kHeWAmxP1WUZ/dgZh2QtM1VuiBA
+ qUqkHwJBAOJLCRvi/JB8N7z82lTk2i3R8gjyOwNQJv6ilZRMyZ9vFZFHcUE27zCf
+ Kb+bX03h8WPwupjMdfgpjShU+7qq8nECQQDBrmyc16QVyo40sgTgblyiysitvviy
+ ovwZsZv4q5MCmvOPnPUrwGbRRb2VONUOMOKpFiBl9lIv7HU//nj7FMVLAkBjUXED
+ 83dA8JcKM+HlioXEAxCzZVVhN+D63QwRwkN08xAPklfqDkcqccWDaZm2hdCtaYlK
+ funwYkrzI1OikQSs
+ -----END PRIVATE KEY-----
+ EOF
+ assert_equal pem, rsa1024.private_to_pem
+ assert_same_rsa rsa1024, OpenSSL::PKey.read(pem)
+ end
+
+ def test_private_encoding_encrypted
+ rsa1024 = Fixtures.pkey("rsa1024")
+ encoded = rsa1024.private_to_der("aes-128-cbc", "abcdef")
+ asn1 = OpenSSL::ASN1.decode(encoded) # PKCS #8 EncryptedPrivateKeyInfo
+ assert_kind_of OpenSSL::ASN1::Sequence, asn1
+ assert_equal 2, asn1.value.size
+ assert_not_equal rsa1024.private_to_der, encoded
+ assert_same_rsa rsa1024, OpenSSL::PKey.read(encoded, "abcdef")
+ assert_same_rsa rsa1024, OpenSSL::PKey.read(encoded) { "abcdef" }
+ assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.read(encoded, "abcxyz") }
+
+ encoded = rsa1024.private_to_pem("aes-128-cbc", "abcdef")
+ assert_match (/BEGIN ENCRYPTED PRIVATE KEY/), encoded.lines[0]
+ assert_same_rsa rsa1024, OpenSSL::PKey.read(encoded, "abcdef")
+
+ # certtool --load-privkey=test/fixtures/pkey/rsa1024.pem --to-p8 --password=abcdef
+ pem = <<~EOF
+ -----BEGIN ENCRYPTED PRIVATE KEY-----
+ MIICojAcBgoqhkiG9w0BDAEDMA4ECLqajUdSNfzwAgIEkQSCAoCDWhxr1HUrKLXA
+ FsFGGQfPT0aKH4gZipaSXXQRl0KwifHwHoDtfo/mAkJVZMnUVOm1AQ4LTFS3EdTy
+ JUwICGEQHb7QAiokIRoi0K2yHhOxVO8qgbnWuisWpiT6Ru1jCqTs/wcqlqF7z2jM
+ oXDk/vuekKst1DDXDcHrzhDkwhCQWj6jt1r2Vwaryy0FyeqsWAgBDiK2LsnCgkGD
+ 21uhNZ/iWMG6tvY9hB8MDdiBJ41YdSG/AKLulAxQ1ibJz0Tasu66TmwFvWhBlME+
+ QbqfgmkgWg5buu53SvDfCA47zXihclbtdfW+U3CJ9OJkx0535TVdZbuC1QgKXvG7
+ 4iKGFRMWYJqZvZM3GL4xbC75AxjXZsdCfV81VjZxjeU6ung/NRzCuCUcmBOQzo1D
+ Vv6COwAa6ttQWM0Ti8oIQHdu5Qi+nuOEHDLxCxD962M37H99sEO5cESjmrGVxhEo
+ 373L4+11geGSCajdp0yiAGnXQfwaKta8cL693bRObN+b1Y+vqtDKH26N9a4R3qgg
+ 2XwgQ5GH5CODoXZpi0wxncXO+3YuuhGeArtzKSXLNxHzIMlY7wZX+0e9UU03zfV/
+ aOe4/q5DpkNxgHePt0oEpamSKY5W3jzVi1dlFWsRjud1p/Grt2zjSWTYClBlJqG1
+ A/3IeDZCu+acaePJjFyv5dFffIj2l4bAYB+LFrZlSu3F/EimO/dCDWJ9JGlMK0aF
+ l9brh7786Mo+YfyklaqMMEHBbbR2Es7PR6Gt7lrcIXmzy9XSsxT6IiD1rG9KKR3i
+ CQxTup6JAx9w1q+adL+Ypikoy3gGD/ccUY6TtPoCmkQwSCS+JqQnFlCiThDJbu+V
+ eqqUNkZq
+ -----END ENCRYPTED PRIVATE KEY-----
+ EOF
+ assert_same_rsa rsa1024, OpenSSL::PKey.read(pem, "abcdef")
+ end
+
+ def test_public_encoding
+ rsa1024 = Fixtures.pkey("rsa1024")
+ assert_equal dup_public(rsa1024).to_der, rsa1024.public_to_der
+ assert_equal dup_public(rsa1024).to_pem, rsa1024.public_to_pem
+ end
+
def test_dup
key = Fixtures.pkey("rsa1024")
key2 = key.dup
@@ -303,6 +443,13 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
assert_not_equal key.params, key2.params
end
+ def test_marshal
+ key = Fixtures.pkey("rsa2048")
+ deserialized = Marshal.load(Marshal.dump(key))
+
+ assert_equal key.to_der, deserialized.to_der
+ end
+
private
def assert_same_rsa(expected, key)
check_component(expected, key, [:n, :e, :d, :p, :q, :dmp1, :dmq1, :iqmp])
diff --git a/test/openssl/test_random.rb b/test/openssl/test_random.rb
index d5a374540d..33af375720 100644
--- a/test/openssl/test_random.rb
+++ b/test/openssl/test_random.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index 53457e21d3..2d9ee7bc70 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
@@ -56,6 +56,56 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
+ def test_socket_open
+ start_server { |port|
+ begin
+ ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port)
+ ssl.sync_close = true
+ ssl.connect
+
+ ssl.puts "abc"; assert_equal "abc\n", ssl.gets
+ ensure
+ ssl&.close
+ end
+ }
+ end
+
+ def test_socket_open_with_context
+ start_server { |port|
+ begin
+ ctx = OpenSSL::SSL::SSLContext.new
+ ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port, context: ctx)
+ ssl.sync_close = true
+ ssl.connect
+
+ assert_equal ssl.context, ctx
+ ssl.puts "abc"; assert_equal "abc\n", ssl.gets
+ ensure
+ ssl&.close
+ end
+ }
+ end
+
+ def test_socket_open_with_local_address_port_context
+ start_server { |port|
+ begin
+ # Guess a free port number
+ random_port = rand(49152..65535)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port, "127.0.0.1", random_port, context: ctx)
+ ssl.sync_close = true
+ ssl.connect
+
+ assert_equal ctx, ssl.context
+ assert_equal random_port, ssl.io.local_address.ip_port
+ ssl.puts "abc"; assert_equal "abc\n", ssl.gets
+ rescue Errno::EADDRINUSE
+ ensure
+ ssl&.close
+ end
+ }
+ end
+
def test_add_certificate
ctx_proc = -> ctx {
# Unset values set by start_server
@@ -81,7 +131,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
add0_chain_supported = openssl?(1, 0, 2)
if add0_chain_supported
- ca2_key = Fixtures.pkey("rsa2048")
+ ca2_key = Fixtures.pkey("rsa-3")
ca2_exts = [
["basicConstraints", "CA:TRUE", true],
["keyUsage", "cRLSign, keyCertSign", true],
@@ -142,12 +192,12 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
def test_sysread_and_syswrite
start_server { |port|
server_connect(port) { |ssl|
- str = "x" * 100 + "\n"
+ str = +("x" * 100 + "\n")
ssl.syswrite(str)
newstr = ssl.sysread(str.bytesize)
assert_equal(str, newstr)
- buf = ""
+ buf = String.new
ssl.syswrite(str)
assert_same buf, ssl.sysread(str.size, buf)
assert_equal(str, buf)
@@ -156,7 +206,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_sync_close
- start_server { |port|
+ start_server do |port|
begin
sock = TCPSocket.new("127.0.0.1", port)
ssl = OpenSSL::SSL::SSLSocket.new(sock)
@@ -179,7 +229,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
ensure
sock&.close
end
- }
+ end
end
def test_copy_stream
@@ -424,6 +474,32 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
+ def test_finished_messages
+ server_finished = nil
+ server_peer_finished = nil
+ client_finished = nil
+ client_peer_finished = nil
+
+ start_server(accept_proc: proc { |server|
+ server_finished = server.finished_message
+ server_peer_finished = server.peer_finished_message
+ }) { |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ ctx.max_version = :TLS1_2 if libressl?(3, 2, 0) && !libressl?(3, 3, 0)
+ server_connect(port, ctx) { |ssl|
+ ssl.puts "abc"; ssl.gets
+
+ client_finished = ssl.finished_message
+ client_peer_finished = ssl.peer_finished_message
+ }
+ }
+ assert_not_nil(server_finished)
+ assert_not_nil(client_finished)
+ assert_equal(server_finished, client_peer_finished)
+ assert_equal(server_peer_finished, client_finished)
+ end
+
def test_sslctx_set_params
ctx = OpenSSL::SSL::SSLContext.new
ctx.set_params
@@ -1342,11 +1418,16 @@ end
ctx.ssl_version = :TLSv1_2
ctx.ciphers = "kRSA"
}
- start_server(ctx_proc: ctx_proc1) do |port|
+ start_server(ctx_proc: ctx_proc1, ignore_listener_error: true) do |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.ssl_version = :TLSv1_2
ctx.ciphers = "kRSA"
- server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key }
+ begin
+ server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key }
+ rescue OpenSSL::SSL::SSLError
+ # kRSA seems disabled
+ raise unless $!.message =~ /no cipher/
+ end
end
end
@@ -1624,6 +1705,20 @@ end
}
end
+ def test_fileno
+ ctx = OpenSSL::SSL::SSLContext.new
+ sock1, sock2 = socketpair
+
+ socket = OpenSSL::SSL::SSLSocket.new(sock1)
+ server = OpenSSL::SSL::SSLServer.new(sock2, ctx)
+
+ assert_equal socket.fileno, socket.to_io.fileno
+ assert_equal server.fileno, server.to_io.fileno
+ ensure
+ sock1.close
+ sock2.close
+ end
+
private
def start_server_version(version, ctx_proc = nil,
@@ -1656,8 +1751,8 @@ end
def assert_handshake_error
# different OpenSSL versions react differently when facing a SSL/TLS version
- # that has been marked as forbidden, therefore either of these may be raised
- assert_raise(OpenSSL::SSL::SSLError, Errno::ECONNRESET) {
+ # that has been marked as forbidden, therefore any of these may be raised
+ assert_raise(OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::EPIPE) {
yield
}
end
diff --git a/test/openssl/test_ssl_session.rb b/test/openssl/test_ssl_session.rb
index 1d82aebfd5..a98efdae2a 100644
--- a/test/openssl/test_ssl_session.rb
+++ b/test/openssl/test_ssl_session.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
diff --git a/test/openssl/test_ts.rb b/test/openssl/test_ts.rb
new file mode 100644
index 0000000000..7cb1a1fe8e
--- /dev/null
+++ b/test/openssl/test_ts.rb
@@ -0,0 +1,680 @@
+require_relative "utils"
+
+if defined?(OpenSSL) && defined?(OpenSSL::Timestamp)
+
+class OpenSSL::TestTimestamp < OpenSSL::TestCase
+ def intermediate_key
+ @intermediate_key ||= OpenSSL::PKey::RSA.new <<-_end_of_pem_
+-----BEGIN RSA PRIVATE KEY-----
+MIICWwIBAAKBgQCcyODxH+oTrr7l7MITWcGaYnnBma6vidCCJjuSzZpaRmXZHAyH
+0YcY4ttC0BdJ4uV+cE05IySVC7tyvVfFb8gFQ6XJV+AEktP+XkLbcxZgj9d2NVu1
+ziXdI+ldXkPnMhyWpMS5E7SD6gflv9NhUYEsmAGsUgdK6LDmm2W2/4TlewIDAQAB
+AoGAYgx6KDFWONLqjW3f/Sv/mGYHUNykUyDzpcD1Npyf797gqMMSzwlo3FZa2tC6
+D7n23XirwpTItvEsW9gvgMikJDPlThAeGLZ+L0UbVNNBHVxGP998Nda1kxqKvhRE
+pfZCKc7PLM9ZXc6jBTmgxdcAYfVCCVUoa2mEf9Ktr3BlI4kCQQDQAM09+wHDXGKP
+o2UnCwCazGtyGU2r0QCzHlh9BVY+KD2KjjhuWh86rEbdWN7hEW23Je1vXIhuM6Pa
+/Ccd+XYnAkEAwPZ91PK6idEONeGQ4I3dyMKV2SbaUjfq3MDL4iIQPQPuj7QsBO/5
+3Nf9ReSUUTRFCUVwoC8k4Z1KAJhR/K/ejQJANE7PTnPuGJQGETs09+GTcFpR9uqY
+FspDk8fg1ufdrVnvSAXF+TJewiGK3KU5v33jinhWQngRsyz3Wt2odKhEZwJACbjh
+oicQqvzzgFd7GzVKpWDYd/ZzLY1PsgusuhoJQ2m9TVRAm4cTycLAKhNYPbcqe0sa
+X5fAffWU0u7ZwqeByQJAOUAbYET4RU3iymAvAIDFj8LiQnizG9t5Ty3HXlijKQYv
+y8gsvWd4CdxwOPatWpBUX9L7IXcMJmD44xXTUvpbfQ==
+-----END RSA PRIVATE KEY-----
+_end_of_pem_
+ end
+
+ def ee_key
+ @ee_key ||= OpenSSL::PKey::RSA.new <<-_end_of_pem_
+-----BEGIN RSA PRIVATE KEY-----
+MIICWwIBAAKBgQDA6eB5r2O5KOKNbKMBhzadl43lgpwqq28m+G0gH38kKCL1f3o9
+P8xUZm7sZqcWEervZMSSXMGBV9DgeoSR+U6FMJywgQGx/JNRx7wZTMNym3PvgLkl
+xCXh6ZA0/xbtJtcNI+UUv0ENBkTIuUWBhkAf3jQclAr9aQ0ktYBuHAcRcQIDAQAB
+AoGAKNhcAuezwZx6e18pFEXAtpVEIfgJgK9TlXi8AjUpAkrNPBWFmDpN1QDrM3p4
+nh+lEpLPW/3vqqchPqYyM4YJraMLpS3KUG+s7+m9QIia0ri2WV5Cig7WL+Tl9p7K
+b3oi2Aj/wti8GfOLFQXOQQ4Ea4GoCv2Sxe0GZR39UBxzTsECQQD1zuVIwBvqU2YR
+8innsoa+j4u2hulRmQO6Zgpzj5vyRYfA9uZxQ9nKbfJvzuWwUv+UzyS9RqxarqrP
+5nQw5EmVAkEAyOmJg6+AfGrgvSWfSpXEds/WA/sHziCO3rE4/sd6cnDc6XcTgeMs
+mT8Z3kAYGpqFDew5orUylPfJJa+PUueJbQJAY+gkvw3+Cp69FLw1lgu0wo07fwOU
+n2qu3jsNMm0DOFRUWfTAMvcd9S385L7WEnWZldUfnKK1+OGXYYrMXPbchQJAChU2
+UoaHQzc16iguM1cK0g+iJPb/MEgQA3sPajHmokGpxIm2T+lvvo0dJjs/Om6QyN8X
+EWRYkoNQ8/Q4lCeMjQJAfvDIGtyqF4PieFHYgluQAv5pGgYpakdc8SYyeRH9NKey
+GaL27FRs4fRWf9OmxPhUVgIyGzLGXrueemvQUDHObA==
+-----END RSA PRIVATE KEY-----
+_end_of_pem_
+ end
+
+ def ca_cert
+ @ca_cert ||= OpenSSL::Certs.ca_cert
+ end
+
+ def ca_store
+ @ca_store ||= OpenSSL::X509::Store.new.tap { |s| s.add_cert(ca_cert) }
+ end
+
+ def ts_cert_direct
+ @ts_cert_direct ||= OpenSSL::Certs.ts_cert_direct(ee_key, ca_cert)
+ end
+
+ def intermediate_cert
+ @intermediate_cert ||= OpenSSL::Certs.intermediate_cert(intermediate_key, ca_cert)
+ end
+
+ def intermediate_store
+ @intermediate_store ||= OpenSSL::X509::Store.new.tap { |s| s.add_cert(intermediate_cert) }
+ end
+
+ def ts_cert_ee
+ @ts_cert_ee ||= OpenSSL::Certs.ts_cert_ee(ee_key, intermediate_cert, intermediate_key)
+ end
+
+ def test_request_mandatory_fields
+ req = OpenSSL::Timestamp::Request.new
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ tmp = req.to_der
+ pp OpenSSL::ASN1.decode(tmp)
+ end
+ req.algorithm = "sha1"
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ req.to_der
+ end
+ req.message_imprint = OpenSSL::Digest.digest('SHA1', "data")
+ req.to_der
+ end
+
+ def test_request_assignment
+ req = OpenSSL::Timestamp::Request.new
+
+ req.version = 2
+ assert_equal(2, req.version)
+ assert_raise(TypeError) { req.version = nil }
+ assert_raise(TypeError) { req.version = "foo" }
+
+ req.algorithm = "SHA1"
+ assert_equal("SHA1", req.algorithm)
+ assert_raise(TypeError) { req.algorithm = nil }
+ assert_raise(OpenSSL::ASN1::ASN1Error) { req.algorithm = "xxx" }
+
+ req.message_imprint = "test"
+ assert_equal("test", req.message_imprint)
+ assert_raise(TypeError) { req.message_imprint = nil }
+
+ req.policy_id = "1.2.3.4.5"
+ assert_equal("1.2.3.4.5", req.policy_id)
+ assert_raise(TypeError) { req.policy_id = 123 }
+ assert_raise(TypeError) { req.policy_id = nil }
+
+ req.nonce = 42
+ assert_equal(42, req.nonce)
+ assert_raise(TypeError) { req.nonce = "foo" }
+ assert_raise(TypeError) { req.nonce = nil }
+
+ req.cert_requested = false
+ assert_equal(false, req.cert_requested?)
+ req.cert_requested = nil
+ assert_equal(false, req.cert_requested?)
+ req.cert_requested = 123
+ assert_equal(true, req.cert_requested?)
+ req.cert_requested = "asdf"
+ assert_equal(true, req.cert_requested?)
+ end
+
+ def test_request_serialization
+ req = OpenSSL::Timestamp::Request.new
+
+ req.version = 2
+ req.algorithm = "SHA1"
+ req.message_imprint = "test"
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+ req.cert_requested = true
+
+ req = OpenSSL::Timestamp::Request.new(req.to_der)
+
+ assert_equal(2, req.version)
+ assert_equal("SHA1", req.algorithm)
+ assert_equal("test", req.message_imprint)
+ assert_equal("1.2.3.4.5", req.policy_id)
+ assert_equal(42, req.nonce)
+ assert_equal(true, req.cert_requested?)
+
+ end
+
+ def test_request_re_assignment
+ #tests whether the potential 'freeing' of previous values in C works properly
+ req = OpenSSL::Timestamp::Request.new
+ req.version = 2
+ req.version = 3
+ req.algorithm = "SHA1"
+ req.algorithm = "SHA256"
+ req.message_imprint = "test"
+ req.message_imprint = "test2"
+ req.policy_id = "1.2.3.4.5"
+ req.policy_id = "1.2.3.4.6"
+ req.nonce = 42
+ req.nonce = 24
+ req.cert_requested = false
+ req.cert_requested = true
+ req.to_der
+ end
+
+ def test_request_encode_decode
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+
+ qer = OpenSSL::Timestamp::Request.new(req.to_der)
+ assert_equal(1, qer.version)
+ assert_equal("SHA1", qer.algorithm)
+ assert_equal(digest, qer.message_imprint)
+ assert_equal("1.2.3.4.5", qer.policy_id)
+ assert_equal(42, qer.nonce)
+
+ #put OpenSSL::ASN1.decode inbetween
+ qer2 = OpenSSL::Timestamp::Request.new(OpenSSL::ASN1.decode(req.to_der))
+ assert_equal(1, qer2.version)
+ assert_equal("SHA1", qer2.algorithm)
+ assert_equal(digest, qer2.message_imprint)
+ assert_equal("1.2.3.4.5", qer2.policy_id)
+ assert_equal(42, qer2.nonce)
+ end
+
+ def test_request_invalid_asn1
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ OpenSSL::Timestamp::Request.new("*" * 44)
+ end
+ end
+
+ def test_response_constants
+ assert_equal(0, OpenSSL::Timestamp::Response::GRANTED)
+ assert_equal(1, OpenSSL::Timestamp::Response::GRANTED_WITH_MODS)
+ assert_equal(2, OpenSSL::Timestamp::Response::REJECTION)
+ assert_equal(3, OpenSSL::Timestamp::Response::WAITING)
+ assert_equal(4, OpenSSL::Timestamp::Response::REVOCATION_WARNING)
+ assert_equal(5, OpenSSL::Timestamp::Response::REVOCATION_NOTIFICATION)
+ end
+
+ def test_response_creation
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+
+ fac = OpenSSL::Timestamp::Factory.new
+ time = Time.now
+ fac.gen_time = time
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+
+ resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ resp = OpenSSL::Timestamp::Response.new(resp)
+ assert_equal(OpenSSL::Timestamp::Response::GRANTED, resp.status)
+ assert_nil(resp.failure_info)
+ assert_equal([], resp.status_text)
+ assert_equal(1, resp.token_info.version)
+ assert_equal("1.2.3.4.5", resp.token_info.policy_id)
+ assert_equal("SHA1", resp.token_info.algorithm)
+ assert_equal(digest, resp.token_info.message_imprint)
+ assert_equal(1, resp.token_info.serial_number)
+ assert_equal(time.to_i, resp.token_info.gen_time.to_i)
+ assert_equal(false, resp.token_info.ordering)
+ assert_nil(resp.token_info.nonce)
+ assert_cert(ts_cert_ee, resp.tsa_certificate)
+ #compare PKCS7
+ token = OpenSSL::ASN1.decode(resp.to_der).value[1]
+ assert_equal(token.to_der, resp.token.to_der)
+ end
+
+ def test_response_failure_info
+ resp = OpenSSL::Timestamp::Response.new("0\"0 \x02\x01\x020\x17\f\x15Invalid TimeStampReq.\x03\x02\x06\x80")
+ assert_equal(:BAD_ALG, resp.failure_info)
+ end
+
+ def test_response_mandatory_fields
+ fac = OpenSSL::Timestamp::Factory.new
+ req = OpenSSL::Timestamp::Request.new
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ fac.create_timestamp(ee_key, ts_cert_ee, req)
+ end
+ req.algorithm = "sha1"
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ fac.create_timestamp(ee_key, ts_cert_ee, req)
+ end
+ req.message_imprint = OpenSSL::Digest.digest('SHA1', "data")
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ fac.create_timestamp(ee_key, ts_cert_ee, req)
+ end
+ fac.gen_time = Time.now
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ fac.create_timestamp(ee_key, ts_cert_ee, req)
+ end
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ fac.create_timestamp(ee_key, ts_cert_ee, req)
+ end
+ fac.default_policy_id = "1.2.3.4.5"
+ assert_equal OpenSSL::Timestamp::Response::GRANTED, fac.create_timestamp(ee_key, ts_cert_ee, req).status
+ fac.default_policy_id = nil
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ fac.create_timestamp(ee_key, ts_cert_ee, req)
+ end
+ req.policy_id = "1.2.3.4.5"
+ assert_equal OpenSSL::Timestamp::Response::GRANTED, fac.create_timestamp(ee_key, ts_cert_ee, req).status
+ end
+
+ def test_response_allowed_digests
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ req.message_imprint = OpenSSL::Digest.digest('SHA1', "test")
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.default_policy_id = "1.2.3.4.6"
+
+ # None allowed by default
+ resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal OpenSSL::Timestamp::Response::REJECTION, resp.status
+
+ # Explicitly allow SHA1 (string)
+ fac.allowed_digests = ["sha1"]
+ resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal OpenSSL::Timestamp::Response::GRANTED, resp.status
+
+ # Explicitly allow SHA1 (object)
+ fac.allowed_digests = [OpenSSL::Digest.new('SHA1')]
+ resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal OpenSSL::Timestamp::Response::GRANTED, resp.status
+
+ # Others not allowed
+ req.algorithm = "SHA256"
+ req.message_imprint = OpenSSL::Digest.digest('SHA256', "test")
+ resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal OpenSSL::Timestamp::Response::REJECTION, resp.status
+
+ # Non-Array
+ fac.allowed_digests = 123
+ resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal OpenSSL::Timestamp::Response::REJECTION, resp.status
+
+ # Non-String, non-Digest Array element
+ fac.allowed_digests = ["sha1", OpenSSL::Digest.new('SHA1'), 123]
+ assert_raise(TypeError) do
+ fac.create_timestamp(ee_key, ts_cert_ee, req)
+ end
+ end
+
+ def test_response_default_policy
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ fac.default_policy_id = "1.2.3.4.6"
+
+ resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal(OpenSSL::Timestamp::Response::GRANTED, resp.status)
+ assert_equal("1.2.3.4.6", resp.token_info.policy_id)
+ end
+
+ def test_response_bad_purpose
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+
+
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ fac.create_timestamp(ee_key, intermediate_cert, req)
+ end
+ end
+
+ def test_response_invalid_asn1
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ OpenSSL::Timestamp::Response.new("*" * 44)
+ end
+ end
+
+ def test_no_cert_requested
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.cert_requested = false
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ fac.default_policy_id = "1.2.3.4.5"
+
+ resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal(OpenSSL::Timestamp::Response::GRANTED, resp.status)
+ assert_nil(resp.tsa_certificate)
+ end
+
+ def test_response_no_policy_defined
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+
+ fac.create_timestamp(ee_key, ts_cert_ee, req)
+ end
+ end
+
+ def test_verify_ee_no_req
+ assert_raise(TypeError) do
+ ts, _ = timestamp_ee
+ ts.verify(nil, ca_cert)
+ end
+ end
+
+ def test_verify_ee_no_store
+ assert_raise(TypeError) do
+ ts, req = timestamp_ee
+ ts.verify(req, nil)
+ end
+ end
+
+ def test_verify_ee_wrong_root_no_intermediate
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ ts, req = timestamp_ee
+ ts.verify(req, intermediate_store)
+ end
+ end
+
+ def test_verify_ee_wrong_root_wrong_intermediate
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ ts, req = timestamp_ee
+ ts.verify(req, intermediate_store, [ca_cert])
+ end
+ end
+
+ def test_verify_ee_nonce_mismatch
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ ts, req = timestamp_ee
+ req.nonce = 1
+ ts.verify(req, ca_store, [intermediate_cert])
+ end
+ end
+
+ def test_verify_ee_intermediate_missing
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ ts, req = timestamp_ee
+ ts.verify(req, ca_store)
+ end
+ end
+
+ def test_verify_ee_intermediate
+ ts, req = timestamp_ee
+ ts.verify(req, ca_store, [intermediate_cert])
+ end
+
+ def test_verify_ee_intermediate_type_error
+ ts, req = timestamp_ee
+ assert_raise(TypeError) { ts.verify(req, [ca_cert], 123) }
+ end
+
+ def test_verify_ee_def_policy
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.nonce = 42
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ fac.default_policy_id = "1.2.3.4.5"
+
+ ts = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ ts.verify(req, ca_store, [intermediate_cert])
+ end
+
+ def test_verify_direct
+ ts, req = timestamp_direct
+ ts.verify(req, ca_store)
+ end
+
+ def test_verify_direct_redundant_untrusted
+ ts, req = timestamp_direct
+ ts.verify(req, ca_store, [ts.tsa_certificate, ts.tsa_certificate])
+ end
+
+ def test_verify_direct_unrelated_untrusted
+ ts, req = timestamp_direct
+ ts.verify(req, ca_store, [intermediate_cert])
+ end
+
+ def test_verify_direct_wrong_root
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ ts, req = timestamp_direct
+ ts.verify(req, intermediate_store)
+ end
+ end
+
+ def test_verify_direct_no_cert_no_intermediate
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ ts, req = timestamp_direct_no_cert
+ ts.verify(req, ca_store)
+ end
+ end
+
+ def test_verify_ee_no_cert
+ ts, req = timestamp_ee_no_cert
+ ts.verify(req, ca_store, [ts_cert_ee, intermediate_cert])
+ end
+
+ def test_verify_ee_no_cert_no_intermediate
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ ts, req = timestamp_ee_no_cert
+ ts.verify(req, ca_store, [ts_cert_ee])
+ end
+ end
+
+ def test_verify_ee_additional_certs_array
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ fac.additional_certs = [intermediate_cert]
+ ts = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal(2, ts.token.certificates.size)
+ fac.additional_certs = nil
+ ts.verify(req, ca_store)
+ ts = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal(1, ts.token.certificates.size)
+ end
+
+ def test_verify_ee_additional_certs_with_root
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ fac.additional_certs = [intermediate_cert, ca_cert]
+ ts = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_equal(3, ts.token.certificates.size)
+ ts.verify(req, ca_store)
+ end
+
+ def test_verify_ee_cert_inclusion_not_requested
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.nonce = 42
+ req.cert_requested = false
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ #needed because the Request contained no policy identifier
+ fac.default_policy_id = '1.2.3.4.5'
+ fac.additional_certs = [ ts_cert_ee, intermediate_cert ]
+ ts = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ assert_nil(ts.token.certificates) #since cert_requested? == false
+ ts.verify(req, ca_store, [ts_cert_ee, intermediate_cert])
+ end
+
+ def test_reusable
+ #test if req and faq are reusable, i.e. the internal
+ #CTX_free methods don't mess up e.g. the certificates
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ fac.additional_certs = [ intermediate_cert ]
+ ts1 = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ ts1.verify(req, ca_store)
+ ts2 = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ ts2.verify(req, ca_store)
+ refute_nil(ts1.tsa_certificate)
+ refute_nil(ts2.tsa_certificate)
+ end
+
+ def test_token_info_creation
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = OpenSSL::BN.new(123)
+
+ fac = OpenSSL::Timestamp::Factory.new
+ time = Time.now
+ fac.gen_time = time
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+
+ resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
+ info = resp.token_info
+ info = OpenSSL::Timestamp::TokenInfo.new(info.to_der)
+
+ assert_equal(1, info.version)
+ assert_equal("1.2.3.4.5", info.policy_id)
+ assert_equal("SHA1", info.algorithm)
+ assert_equal(digest, info.message_imprint)
+ assert_equal(1, info.serial_number)
+ assert_equal(time.to_i, info.gen_time.to_i)
+ assert_equal(false, info.ordering)
+ assert_equal(123, info.nonce)
+ end
+
+ def test_token_info_invalid_asn1
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ OpenSSL::Timestamp::TokenInfo.new("*" * 44)
+ end
+ end
+
+ private
+
+ def assert_cert expected, actual
+ assert_equal expected.to_der, actual.to_der
+ end
+
+ def timestamp_ee
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ return fac.create_timestamp(ee_key, ts_cert_ee, req), req
+ end
+
+ def timestamp_ee_no_cert
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+ req.cert_requested = false
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ return fac.create_timestamp(ee_key, ts_cert_ee, req), req
+ end
+
+ def timestamp_direct
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ return fac.create_timestamp(ee_key, ts_cert_direct, req), req
+ end
+
+ def timestamp_direct_no_cert
+ req = OpenSSL::Timestamp::Request.new
+ req.algorithm = "SHA1"
+ digest = OpenSSL::Digest.digest('SHA1', "test")
+ req.message_imprint = digest
+ req.policy_id = "1.2.3.4.5"
+ req.nonce = 42
+ req.cert_requested = false
+
+ fac = OpenSSL::Timestamp::Factory.new
+ fac.gen_time = Time.now
+ fac.serial_number = 1
+ fac.allowed_digests = ["sha1"]
+ return fac.create_timestamp(ee_key, ts_cert_direct, req), req
+ end
+end
+
+end
diff --git a/test/openssl/test_x509attr.rb b/test/openssl/test_x509attr.rb
index c6c48e86ab..2919d23d2d 100644
--- a/test/openssl/test_x509attr.rb
+++ b/test/openssl/test_x509attr.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
@@ -79,6 +79,16 @@ class OpenSSL::TestX509Attribute < OpenSSL::TestCase
assert_equal true, attr1 == attr2
assert_equal false, attr1 == attr3
end
+
+ def test_marshal
+ val = OpenSSL::ASN1::Set([
+ OpenSSL::ASN1::UTF8String("abc123")
+ ])
+ attr = OpenSSL::X509::Attribute.new("challengePassword", val)
+ deserialized = Marshal.load(Marshal.dump(attr))
+
+ assert_equal attr.to_der, deserialized.to_der
+ end
end
end
diff --git a/test/openssl/test_x509cert.rb b/test/openssl/test_x509cert.rb
index 40a5b0ad74..848a314c9f 100644
--- a/test/openssl/test_x509cert.rb
+++ b/test/openssl/test_x509cert.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
@@ -73,9 +73,12 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
["basicConstraints","CA:TRUE",true],
["keyUsage","keyCertSign, cRLSign",true],
["subjectKeyIdentifier","hash",false],
- ["authorityKeyIdentifier","keyid:always",false],
+ ["authorityKeyIdentifier","issuer:always,keyid:always",false],
]
ca_cert = issue_cert(@ca, @rsa2048, 1, ca_exts, nil, nil)
+ keyid = get_subject_key_id(ca_cert.to_der, hex: false)
+ assert_equal keyid, ca_cert.authority_key_identifier
+ assert_equal keyid, ca_cert.subject_key_identifier
ca_cert.extensions.each_with_index{|ext, i|
assert_equal(ca_exts[i].first, ext.oid)
assert_equal(ca_exts[i].last, ext.critical?)
@@ -84,9 +87,10 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
ee1_exts = [
["keyUsage","Non Repudiation, Digital Signature, Key Encipherment",true],
["subjectKeyIdentifier","hash",false],
- ["authorityKeyIdentifier","keyid:always",false],
+ ["authorityKeyIdentifier","issuer:always,keyid:always",false],
["extendedKeyUsage","clientAuth, emailProtection, codeSigning",false],
["subjectAltName","email:ee1@ruby-lang.org",false],
+ ["authorityInfoAccess","caIssuers;URI:http://www.example.com/caIssuers,OCSP;URI:http://www.example.com/ocsp",false],
]
ee1_cert = issue_cert(@ee1, @rsa1024, 2, ee1_exts, ca_cert, @rsa2048)
assert_equal(ca_cert.subject.to_der, ee1_cert.issuer.to_der)
@@ -94,6 +98,78 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
assert_equal(ee1_exts[i].first, ext.oid)
assert_equal(ee1_exts[i].last, ext.critical?)
}
+ assert_nil(ee1_cert.crl_uris)
+
+ ef = OpenSSL::X509::ExtensionFactory.new
+ ef.config = OpenSSL::Config.parse(<<~_cnf_)
+ [crlDistPts]
+ URI.1 = http://www.example.com/crl
+ URI.2 = ldap://ldap.example.com/cn=ca?certificateRevocationList;binary
+ _cnf_
+ cdp_cert = generate_cert(@ee1, @rsa1024, 3, ca_cert)
+ ef.subject_certificate = cdp_cert
+ cdp_cert.add_extension(ef.create_extension("crlDistributionPoints", "@crlDistPts"))
+ cdp_cert.sign(@rsa2048, "sha256")
+ assert_equal(
+ ["http://www.example.com/crl", "ldap://ldap.example.com/cn=ca?certificateRevocationList;binary"],
+ cdp_cert.crl_uris
+ )
+
+ ef = OpenSSL::X509::ExtensionFactory.new
+ aia_cert = generate_cert(@ee1, @rsa1024, 4, ca_cert)
+ ef.subject_certificate = aia_cert
+ aia_cert.add_extension(
+ ef.create_extension(
+ "authorityInfoAccess",
+ "caIssuers;URI:http://www.example.com/caIssuers," \
+ "caIssuers;URI:ldap://ldap.example.com/cn=ca?authorityInfoAccessCaIssuers;binary," \
+ "OCSP;URI:http://www.example.com/ocsp," \
+ "OCSP;URI:ldap://ldap.example.com/cn=ca?authorityInfoAccessOcsp;binary",
+ false
+ )
+ )
+ aia_cert.sign(@rsa2048, "sha256")
+ assert_equal(
+ ["http://www.example.com/caIssuers", "ldap://ldap.example.com/cn=ca?authorityInfoAccessCaIssuers;binary"],
+ aia_cert.ca_issuer_uris
+ )
+ assert_equal(
+ ["http://www.example.com/ocsp", "ldap://ldap.example.com/cn=ca?authorityInfoAccessOcsp;binary"],
+ aia_cert.ocsp_uris
+ )
+
+ no_exts_cert = issue_cert(@ca, @rsa2048, 5, [], nil, nil)
+ assert_equal nil, no_exts_cert.authority_key_identifier
+ assert_equal nil, no_exts_cert.subject_key_identifier
+ assert_equal nil, no_exts_cert.crl_uris
+ assert_equal nil, no_exts_cert.ca_issuer_uris
+ assert_equal nil, no_exts_cert.ocsp_uris
+ end
+
+ def test_invalid_extension
+ integer = OpenSSL::ASN1::Integer.new(0)
+ invalid_exts_cert = generate_cert(@ee1, @rsa1024, 1, nil)
+ ["subjectKeyIdentifier", "authorityKeyIdentifier", "crlDistributionPoints", "authorityInfoAccess"].each do |ext|
+ invalid_exts_cert.add_extension(
+ OpenSSL::X509::Extension.new(ext, integer.to_der)
+ )
+ end
+
+ assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") {
+ invalid_exts_cert.authority_key_identifier
+ }
+ assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") {
+ invalid_exts_cert.subject_key_identifier
+ }
+ assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") {
+ invalid_exts_cert.crl_uris
+ }
+ assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") {
+ invalid_exts_cert.ca_issuer_uris
+ }
+ assert_raise(OpenSSL::ASN1::ASN1Error, "invalid extension") {
+ invalid_exts_cert.ocsp_uris
+ }
end
def test_sign_and_verify_rsa_sha1
@@ -129,7 +205,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
end
def test_sign_and_verify_rsa_dss1
- cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: OpenSSL::Digest::DSS1.new)
+ cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: OpenSSL::Digest.new('DSS1'))
assert_equal(false, cert.verify(@rsa1024))
assert_equal(true, cert.verify(@rsa2048))
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) })
@@ -189,6 +265,17 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
assert_equal false, cert3 == cert4
end
+ def test_marshal
+ now = Time.now
+ cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil,
+ not_before: now, not_after: now + 3600)
+ cert = issue_cert(@ee1, @rsa2048, 2, [], cacert, @rsa1024,
+ not_before: now, not_after: now + 3600)
+ deserialized = Marshal.load(Marshal.dump(cert))
+
+ assert_equal cert.to_der, deserialized.to_der
+ end
+
private
def certificate_error_returns_false
diff --git a/test/openssl/test_x509crl.rb b/test/openssl/test_x509crl.rb
index 03fdf64dd4..bcdb0a697c 100644
--- a/test/openssl/test_x509crl.rb
+++ b/test/openssl/test_x509crl.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
@@ -20,7 +20,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
crl = issue_crl([], 1, now, now+1600, [],
- cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
assert_equal(1, crl.version)
assert_equal(cert.issuer.to_der, crl.issuer.to_der)
assert_equal(now, crl.last_update)
@@ -57,7 +57,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
]
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
revoked = crl.revoked
assert_equal(5, revoked.size)
assert_equal(1, revoked[0].serial)
@@ -98,7 +98,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
revoke_info = (1..1000).collect{|i| [i, now, 0] }
crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
revoked = crl.revoked
assert_equal(1000, revoked.size)
assert_equal(1, revoked[0].serial)
@@ -118,19 +118,22 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
["keyUsage", "cRLSign, keyCertSign", true],
]
crl_exts = [
- ["authorityKeyIdentifier", "keyid:always", false],
+ ["authorityKeyIdentifier", "issuer:always,keyid:always", false],
["issuerAltName", "issuer:copy", false],
]
cert = issue_cert(@ca, @rsa2048, 1, cert_exts, nil, nil)
crl = issue_crl([], 1, Time.now, Time.now+1600, crl_exts,
- cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
exts = crl.extensions
assert_equal(3, exts.size)
assert_equal("1", exts[0].value)
assert_equal("crlNumber", exts[0].oid)
assert_equal(false, exts[0].critical?)
+ expected_keyid = OpenSSL::TestUtils.get_subject_key_id(cert, hex: false)
+ assert_equal expected_keyid, crl.authority_key_identifier
+
assert_equal("authorityKeyIdentifier", exts[1].oid)
keyid = OpenSSL::TestUtils.get_subject_key_id(cert)
assert_match(/^keyid:#{keyid}/, exts[1].value)
@@ -155,22 +158,26 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
assert_equal("issuerAltName", exts[2].oid)
assert_equal("email:xyzzy@ruby-lang.org", exts[2].value)
assert_equal(false, exts[2].critical?)
+
+ no_ext_crl = issue_crl([], 1, Time.now, Time.now+1600, [],
+ cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
+ assert_equal nil, no_ext_crl.authority_key_identifier
end
def test_crlnumber
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
assert_match(1.to_s, crl.extensions[0].value)
assert_match(/X509v3 CRL Number:\s+#{1}/m, crl.to_text)
crl = issue_crl([], 2**32, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
assert_match((2**32).to_s, crl.extensions[0].value)
assert_match(/X509v3 CRL Number:\s+#{2**32}/m, crl.to_text)
crl = issue_crl([], 2**100, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
assert_match(/X509v3 CRL Number:\s+#{2**100}/m, crl.to_text)
assert_match((2**100).to_s, crl.extensions[0].value)
end
@@ -178,7 +185,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
def test_sign_and_verify
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
assert_equal(false, crl.verify(@rsa1024))
assert_equal(true, crl.verify(@rsa2048))
assert_equal(false, crl_error_returns_false { crl.verify(@dsa256) })
@@ -188,7 +195,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
cert = issue_cert(@ca, @dsa512, 1, [], nil, nil)
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
- cert, @dsa512, OpenSSL::Digest::SHA1.new)
+ cert, @dsa512, OpenSSL::Digest.new('SHA1'))
assert_equal(false, crl_error_returns_false { crl.verify(@rsa1024) })
assert_equal(false, crl_error_returns_false { crl.verify(@rsa2048) })
assert_equal(false, crl.verify(@dsa256))
@@ -249,6 +256,22 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
assert_equal true, rev2 == crl2.revoked[1]
end
+ def test_marshal
+ now = Time.now
+
+ cacert = issue_cert(@ca, @rsa1024, 1, [], nil, nil)
+ crl = issue_crl([], 1, now, now + 3600, [], cacert, @rsa1024, "sha256")
+ rev = OpenSSL::X509::Revoked.new.tap { |rev|
+ rev.serial = 1
+ rev.time = now
+ }
+ crl.add_revoked(rev)
+ deserialized = Marshal.load(Marshal.dump(crl))
+
+ assert_equal crl.to_der, deserialized.to_der
+ assert_equal crl.revoked[0].to_der, deserialized.revoked[0].to_der
+ end
+
private
def crl_error_returns_false
diff --git a/test/openssl/test_x509ext.rb b/test/openssl/test_x509ext.rb
index 91ce202fec..7ad010d1ed 100644
--- a/test/openssl/test_x509ext.rb
+++ b/test/openssl/test_x509ext.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -86,6 +86,19 @@ class OpenSSL::TestX509Extension < OpenSSL::TestCase
assert_equal true, ext1 == ext2
assert_equal false, ext1 == ext3
end
+
+ def test_marshal
+ ef = OpenSSL::X509::ExtensionFactory.new
+ ext = ef.create_extension("basicConstraints", "critical, CA:TRUE, pathlen:2")
+ deserialized = Marshal.load(Marshal.dump(ext))
+
+ assert_equal ext.to_der, deserialized.to_der
+ end
+
+ def test_value_der
+ ext = OpenSSL::X509::Extension.new(@basic_constraints.to_der)
+ assert_equal @basic_constraints_value.to_der, ext.value_der
+ end
end
end
diff --git a/test/openssl/test_x509name.rb b/test/openssl/test_x509name.rb
index f0146595d6..c6d15219f5 100644
--- a/test/openssl/test_x509name.rb
+++ b/test/openssl/test_x509name.rb
@@ -1,5 +1,5 @@
# coding: ASCII-8BIT
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative 'utils'
if defined?(OpenSSL)
@@ -389,7 +389,7 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase
dn.each { |x| name.add_entry(*x) }
str = name.to_utf8
- expected = "CN=フー\\, バー,DC=ruby-lang,DC=org".force_encoding("UTF-8")
+ expected = String.new("CN=フー\\, バー,DC=ruby-lang,DC=org").force_encoding("UTF-8")
assert_equal expected, str
assert_equal Encoding.find("UTF-8"), str.encoding
@@ -402,6 +402,9 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase
n2 = OpenSSL::X509::Name.parse_rfc2253 'CN=a'
assert_equal n1, n2
+
+ assert_equal(false, n1 == 'abc')
+ assert_equal(false, n2 == nil)
end
def test_spaceship
@@ -415,6 +418,9 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase
assert_equal(-1, n2 <=> n3)
assert_equal(1, n3 <=> n1)
assert_equal(1, n3 <=> n2)
+ assert_equal(nil, n1 <=> 'abc')
+ assert_equal(nil, n2 <=> 123)
+ assert_equal(nil, n3 <=> nil)
end
def name_hash(name)
@@ -426,13 +432,13 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase
def test_hash
dn = "/DC=org/DC=ruby-lang/CN=www.ruby-lang.org"
name = OpenSSL::X509::Name.parse(dn)
- d = OpenSSL::Digest::MD5.digest(name.to_der)
+ d = OpenSSL::Digest.digest('MD5', name.to_der)
expected = (d[0].ord & 0xff) | (d[1].ord & 0xff) << 8 | (d[2].ord & 0xff) << 16 | (d[3].ord & 0xff) << 24
assert_equal(expected, name_hash(name))
#
dn = "/DC=org/DC=ruby-lang/CN=baz.ruby-lang.org"
name = OpenSSL::X509::Name.parse(dn)
- d = OpenSSL::Digest::MD5.digest(name.to_der)
+ d = OpenSSL::Digest.digest('MD5', name.to_der)
expected = (d[0].ord & 0xff) | (d[1].ord & 0xff) << 8 | (d[2].ord & 0xff) << 16 | (d[3].ord & 0xff) << 24
assert_equal(expected, name_hash(name))
end
@@ -447,6 +453,13 @@ class OpenSSL::TestX509Name < OpenSSL::TestCase
assert_equal false, name0.eql?(name2)
end
+ def test_marshal
+ name = OpenSSL::X509::Name.new([["DC", "org"], ["DC", "ruby-lang"], ["CN", "bar.ruby-lang.org"]])
+ deserialized = Marshal.load(Marshal.dump(name))
+
+ assert_equal name.to_der, deserialized.to_der
+ end
+
def test_dup
name = OpenSSL::X509::Name.parse("/CN=ruby-lang.org")
assert_equal(name.to_der, name.dup.to_der)
diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb
index 2c447ccdd5..ee9c678fbb 100644
--- a/test/openssl/test_x509req.rb
+++ b/test/openssl/test_x509req.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
@@ -23,31 +23,31 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_public_key
- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der)
req = OpenSSL::X509::Request.new(req.to_der)
assert_equal(@rsa1024.public_key.to_der, req.public_key.to_der)
- req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest::SHA1.new)
+ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1'))
assert_equal(@dsa512.public_key.to_der, req.public_key.to_der)
req = OpenSSL::X509::Request.new(req.to_der)
assert_equal(@dsa512.public_key.to_der, req.public_key.to_der)
end
def test_version
- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
assert_equal(0, req.version)
req = OpenSSL::X509::Request.new(req.to_der)
assert_equal(0, req.version)
- req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ req = issue_csr(1, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
assert_equal(1, req.version)
req = OpenSSL::X509::Request.new(req.to_der)
assert_equal(1, req.version)
end
def test_subject
- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
assert_equal(@dn.to_der, req.subject.to_der)
req = OpenSSL::X509::Request.new(req.to_der)
assert_equal(@dn.to_der, req.subject.to_der)
@@ -78,9 +78,9 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
OpenSSL::X509::Attribute.new("msExtReq", attrval),
]
- req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
attrs.each{|attr| req0.add_attribute(attr) }
- req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
req1.attributes = attrs
assert_equal(req0.to_der, req1.to_der)
@@ -101,7 +101,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_sign_and_verify_rsa_sha1
- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
assert_equal(true, req.verify(@rsa1024))
assert_equal(false, req.verify(@rsa2048))
assert_equal(false, request_error_returns_false { req.verify(@dsa256) })
@@ -111,7 +111,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_sign_and_verify_rsa_md5
- req = issue_csr(0, @dn, @rsa2048, OpenSSL::Digest::MD5.new)
+ req = issue_csr(0, @dn, @rsa2048, OpenSSL::Digest.new('MD5'))
assert_equal(false, req.verify(@rsa1024))
assert_equal(true, req.verify(@rsa2048))
assert_equal(false, request_error_returns_false { req.verify(@dsa256) })
@@ -122,7 +122,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_sign_and_verify_dsa
- req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest::SHA1.new)
+ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1'))
assert_equal(false, request_error_returns_false { req.verify(@rsa1024) })
assert_equal(false, request_error_returns_false { req.verify(@rsa2048) })
assert_equal(false, req.verify(@dsa256))
@@ -133,11 +133,11 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
def test_sign_and_verify_dsa_md5
assert_raise(OpenSSL::X509::RequestError){
- issue_csr(0, @dn, @dsa512, OpenSSL::Digest::MD5.new) }
+ issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('MD5')) }
end
def test_dup
- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest::SHA1.new)
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
assert_equal(req.to_der, req.dup.to_der)
end
@@ -151,6 +151,13 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
assert_equal false, req1 == req3
end
+ def test_marshal
+ req = issue_csr(0, @dn, @rsa1024, "sha256")
+ deserialized = Marshal.load(Marshal.dump(req))
+
+ assert_equal req.to_der, deserialized.to_der
+ end
+
private
def request_error_returns_false
diff --git a/test/openssl/test_x509store.rb b/test/openssl/test_x509store.rb
index 6412249b93..e9602e3434 100644
--- a/test/openssl/test_x509store.rb
+++ b/test/openssl/test_x509store.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require_relative "utils"
if defined?(OpenSSL)
@@ -72,16 +72,16 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase
revoke_info = []
crl1 = issue_crl(revoke_info, 1, now, now+1800, [],
- ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
revoke_info = [ [2, now, 1], ]
crl1_2 = issue_crl(revoke_info, 2, now, now+1800, [],
- ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
revoke_info = [ [20, now, 1], ]
crl2 = issue_crl(revoke_info, 1, now, now+1800, [],
- ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
+ ca2_cert, @rsa1024, OpenSSL::Digest.new('SHA1'))
revoke_info = []
crl2_2 = issue_crl(revoke_info, 2, now-100, now-1, [],
- ca2_cert, @rsa1024, OpenSSL::Digest::SHA1.new)
+ ca2_cert, @rsa1024, OpenSSL::Digest.new('SHA1'))
assert_equal(true, ca1_cert.verify(ca1_cert.public_key)) # self signed
assert_equal(true, ca2_cert.verify(ca1_cert.public_key)) # issued by ca1
@@ -220,10 +220,10 @@ class OpenSSL::TestX509Store < OpenSSL::TestCase
revoke_info = []
crl1 = issue_crl(revoke_info, 1, now, now+1800, [],
- ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
revoke_info = [ [2, now, 1], ]
crl2 = issue_crl(revoke_info, 2, now+1800, now+3600, [],
- ca1_cert, @rsa2048, OpenSSL::Digest::SHA1.new)
+ ca1_cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
store.add_crl(crl1)
assert_raise(OpenSSL::X509::StoreError){
store.add_crl(crl2) # add CRL issued by same CA twice.
diff --git a/test/openssl/ut_eof.rb b/test/openssl/ut_eof.rb
index bd62fd50f9..cf1f2d423e 100644
--- a/test/openssl/ut_eof.rb
+++ b/test/openssl/ut_eof.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require 'test/unit'
if defined?(OpenSSL)
@@ -18,12 +18,12 @@ module OpenSSL::TestEOF
assert_nil(f.read(1))
}
open_file("") {|f|
- s = "x"
+ s = +"x"
assert_equal("", f.read(nil, s))
assert_equal("", s)
}
open_file("") {|f|
- s = "x"
+ s = +"x"
assert_nil(f.read(10, s))
assert_equal("", s)
}
@@ -75,12 +75,12 @@ module OpenSSL::TestEOF
assert_equal("", f.read(0))
}
open_file("a") {|f|
- s = "x"
+ s = +"x"
assert_equal("a", f.read(nil, s))
assert_equal("a", s)
}
open_file("a") {|f|
- s = "x"
+ s = +"x"
assert_equal("a", f.read(10, s))
assert_equal("a", s)
}
diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb
index 34c89a2e04..ee734d98a4 100644
--- a/test/openssl/utils.rb
+++ b/test/openssl/utils.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
begin
require "openssl"
@@ -52,15 +52,18 @@ module OpenSSL::TestUtils
@file_cache[[category, name]] ||=
File.read(File.join(__dir__, "fixtures", category, name + ".pem"))
end
+
+ def file_path(category, name)
+ File.join(__dir__, "fixtures", category, name)
+ end
end
module_function
- def issue_cert(dn, key, serial, extensions, issuer, issuer_key,
- not_before: nil, not_after: nil, digest: "sha256")
+ def generate_cert(dn, key, serial, issuer,
+ not_before: nil, not_after: nil)
cert = OpenSSL::X509::Certificate.new
issuer = cert unless issuer
- issuer_key = key unless issuer_key
cert.version = 2
cert.serial = serial
cert.subject = dn
@@ -69,6 +72,16 @@ module OpenSSL::TestUtils
now = Time.now
cert.not_before = not_before || now - 3600
cert.not_after = not_after || now + 3600
+ cert
+ end
+
+
+ def issue_cert(dn, key, serial, extensions, issuer, issuer_key,
+ not_before: nil, not_after: nil, digest: "sha256")
+ cert = generate_cert(dn, key, serial, issuer,
+ not_before: not_before, not_after: not_after)
+ issuer = cert unless issuer
+ issuer_key = key unless issuer_key
ef = OpenSSL::X509::ExtensionFactory.new
ef.subject_certificate = cert
ef.issuer_certificate = issuer
@@ -107,13 +120,18 @@ module OpenSSL::TestUtils
crl
end
- def get_subject_key_id(cert)
+ def get_subject_key_id(cert, hex: true)
asn1_cert = OpenSSL::ASN1.decode(cert)
tbscert = asn1_cert.value[0]
pkinfo = tbscert.value[6]
publickey = pkinfo.value[1]
pkvalue = publickey.value
- OpenSSL::Digest::SHA1.hexdigest(pkvalue).scan(/../).join(":").upcase
+ digest = OpenSSL::Digest.digest('SHA1', pkvalue)
+ if hex
+ digest.unpack("H2"*20).join(":").upcase
+ else
+ digest
+ end
end
def openssl?(major = nil, minor = nil, fix = nil, patch = 0)
@@ -197,6 +215,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
def start_server(verify_mode: OpenSSL::SSL::VERIFY_NONE, start_immediately: true,
ctx_proc: nil, server_proc: method(:readwrite_loop),
+ accept_proc: proc{},
ignore_listener_error: false, &block)
IO.pipe {|stop_pipe_r, stop_pipe_w|
store = OpenSSL::X509::Store.new
@@ -230,6 +249,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
readable, = IO.select([ssls, stop_pipe_r])
break if readable.include? stop_pipe_r
ssl = ssls.accept
+ accept_proc.call(ssl)
rescue OpenSSL::SSL::SSLError, IOError, Errno::EBADF, Errno::EINVAL,
Errno::ECONNABORTED, Errno::ENOTSOCK, Errno::ECONNRESET
retry if ignore_listener_error
@@ -276,7 +296,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
begin
timeout = EnvUtil.apply_timeout_scale(30)
th.join(timeout) or
- th.raise(RuntimeError, "[start_server] thread did not exit in #{ timeout } secs")
+ th.raise(RuntimeError, "[start_server] thread did not exit in #{timeout} secs")
rescue (defined?(MiniTest::Skip) ? MiniTest::Skip : Test::Unit::PendedError)
# MiniTest::Skip is for the Ruby tree
pend = $!
@@ -324,4 +344,62 @@ class OpenSSL::PKeyTestCase < OpenSSL::TestCase
end
end
+module OpenSSL::Certs
+ include OpenSSL::TestUtils
+
+ module_function
+
+ def ca_cert
+ ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Timestamp Root CA")
+
+ ca_exts = [
+ ["basicConstraints","CA:TRUE,pathlen:1",true],
+ ["keyUsage","keyCertSign, cRLSign",true],
+ ["subjectKeyIdentifier","hash",false],
+ ["authorityKeyIdentifier","keyid:always",false],
+ ]
+ OpenSSL::TestUtils.issue_cert(ca, Fixtures.pkey("rsa2048"), 1, ca_exts, nil, nil)
+ end
+
+ def ts_cert_direct(key, ca_cert)
+ dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/OU=Timestamp/CN=Server Direct")
+
+ exts = [
+ ["basicConstraints","CA:FALSE",true],
+ ["keyUsage","digitalSignature, nonRepudiation", true],
+ ["subjectKeyIdentifier", "hash",false],
+ ["authorityKeyIdentifier","keyid,issuer", false],
+ ["extendedKeyUsage", "timeStamping", true]
+ ]
+
+ OpenSSL::TestUtils.issue_cert(dn, key, 2, exts, ca_cert, Fixtures.pkey("rsa2048"))
+ end
+
+ def intermediate_cert(key, ca_cert)
+ dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/OU=Timestamp/CN=Timestamp Intermediate CA")
+
+ exts = [
+ ["basicConstraints","CA:TRUE,pathlen:0",true],
+ ["keyUsage","keyCertSign, cRLSign",true],
+ ["subjectKeyIdentifier","hash",false],
+ ["authorityKeyIdentifier","keyid:always",false],
+ ]
+
+ OpenSSL::TestUtils.issue_cert(dn, key, 3, exts, ca_cert, Fixtures.pkey("rsa2048"))
+ end
+
+ def ts_cert_ee(key, intermediate, im_key)
+ dn = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/OU=Timestamp/CN=Server End Entity")
+
+ exts = [
+ ["keyUsage","digitalSignature, nonRepudiation", true],
+ ["subjectKeyIdentifier", "hash",false],
+ ["authorityKeyIdentifier","keyid,issuer", false],
+ ["extendedKeyUsage", "timeStamping", true]
+ ]
+
+ OpenSSL::TestUtils.issue_cert(dn, key, 4, exts, intermediate, im_key)
+ end
+end
+
end
diff --git a/test/optparse/test_acceptable.rb b/test/optparse/test_acceptable.rb
index 5c3fbdb10c..12f7886538 100644
--- a/test/optparse/test_acceptable.rb
+++ b/test/optparse/test_acceptable.rb
@@ -196,4 +196,3 @@ class TestOptionParser::Acceptable < TestOptionParser
end
end
-
diff --git a/test/optparse/test_optparse.rb b/test/optparse/test_optparse.rb
index e4aeb07aac..5f5ea183b0 100644
--- a/test/optparse/test_optparse.rb
+++ b/test/optparse/test_optparse.rb
@@ -75,4 +75,34 @@ class TestOptionParser < Test::Unit::TestCase
assert_equal({host: "localhost", port: 8000, verbose: true}, result)
assert_equal(true, @verbose)
end
+
+ def test_require_exact
+ @opt.def_option('-F', '--zrs=IRS', 'zrs')
+ %w(--zrs --zr --z -zfoo -z -F -Ffoo).each do |arg|
+ result = {}
+ @opt.parse([arg, 'foo'], into: result)
+ assert_equal({zrs: 'foo'}, result)
+ end
+
+ @opt.require_exact = true
+ %w(--zrs -F -Ffoo).each do |arg|
+ result = {}
+ @opt.parse([arg, 'foo'], into: result)
+ assert_equal({zrs: 'foo'}, result)
+ end
+
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--zr foo))}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--z foo))}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zrs foo))}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zr foo))}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-z foo))}
+ end
+
+ def test_nonopt_pattern
+ @opt.def_option(/^[^-]/) do |arg|
+ assert(false, "Never gets called")
+ end
+ e = assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-t))}
+ assert_equal(["-t"], e.args)
+ end
end
diff --git a/test/ostruct/test_ostruct.rb b/test/ostruct/test_ostruct.rb
index 61a4822810..3ca98ee739 100644
--- a/test/ostruct/test_ostruct.rb
+++ b/test/ostruct/test_ostruct.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'test/unit'
require 'ostruct'
+require 'yaml'
class TC_OpenStruct < Test::Unit::TestCase
def test_initialize
@@ -66,16 +67,15 @@ class TC_OpenStruct < Test::Unit::TestCase
o = OpenStruct.new(foo: 42)
o.a = 'a'
o.freeze
- expected_error = defined?(FrozenError) ? FrozenError : RuntimeError
- assert_raise(expected_error) {o.b = 'b'}
+ assert_raise(FrozenError) {o.b = 'b'}
assert_not_respond_to(o, :b)
- assert_raise(expected_error) {o.a = 'z'}
+ assert_raise(FrozenError) {o.a = 'z'}
assert_equal('a', o.a)
assert_equal(42, o.foo)
o = OpenStruct.new :a => 42
def o.frozen?; nil end
o.freeze
- assert_raise(expected_error, '[ruby-core:22559]') {o.a = 1764}
+ assert_raise(FrozenError, '[ruby-core:22559]') {o.a = 1764}
end
def test_delete_field
@@ -179,19 +179,21 @@ class TC_OpenStruct < Test::Unit::TestCase
def test_accessor_defines_method
os = OpenStruct.new(foo: 42)
- assert os.respond_to? :foo
- assert_equal([], os.singleton_methods)
+ assert_respond_to(os, :foo)
assert_equal(42, os.foo)
assert_equal([:foo, :foo=], os.singleton_methods.sort)
end
def test_does_not_redefine
+ $VERBOSE, verbose_bak = nil, $VERBOSE
os = OpenStruct.new(foo: 42)
def os.foo
43
end
os.foo = 44
assert_equal(43, os.foo)
+ ensure
+ $VERBOSE = verbose_bak
end
def test_allocate_subclass
@@ -203,6 +205,15 @@ class TC_OpenStruct < Test::Unit::TestCase
assert_instance_of(c, os)
end
+ def test_initialize_subclass
+ c = Class.new(OpenStruct) {
+ def initialize(x,y={})super(y);end
+ }
+ o = c.new(1, {a: 42})
+ assert_equal(42, o.dup.a)
+ assert_equal(42, o.clone.a)
+ end
+
def test_private_method
os = OpenStruct.new
class << os
@@ -226,4 +237,105 @@ class TC_OpenStruct < Test::Unit::TestCase
os.foo true, true
end
end
+
+ def test_access_undefined
+ os = OpenStruct.new
+ assert_nil os.foo
+ end
+
+ def test_overridden_private_methods
+ os = OpenStruct.new(puts: :foo, format: :bar)
+ assert_equal(:foo, os.puts)
+ assert_equal(:bar, os.format)
+ end
+
+ def test_overridden_public_methods
+ os = OpenStruct.new(method: :foo, class: :bar)
+ assert_equal(:foo, os.method)
+ assert_equal(:bar, os.class)
+ end
+
+ def test_access_original_methods
+ os = OpenStruct.new(method: :foo, hash: 42)
+ assert_equal(os.object_id, os.method!(:object_id).call)
+ assert_not_equal(42, os.hash!)
+ end
+
+ def test_override_subclass
+ c = Class.new(OpenStruct) {
+ def foo; :protect_me; end
+ private def bar; :protect_me; end
+ def inspect; 'protect me'; end
+ }
+ o = c.new(
+ foo: 1, bar: 2, inspect: '3', # in subclass: protected
+ table!: 4, # bang method: protected
+ each_pair: 5, to_s: 'hello', # others: not protected
+ )
+ # protected:
+ assert_equal(:protect_me, o.foo)
+ assert_equal(:protect_me, o.send(:bar))
+ assert_equal('protect me', o.inspect)
+ assert_not_equal(4, o.send(:table!))
+ # not protected:
+ assert_equal(5, o.each_pair)
+ assert_equal('hello', o.to_s)
+ end
+
+ def test_mistaken_subclass
+ sub = Class.new(OpenStruct) do
+ def [](k)
+ __send__(k)
+ super
+ end
+
+ def []=(k, v)
+ @item_set = true
+ __send__("#{k}=", v)
+ super
+ end
+ end
+ o = sub.new
+ o.foo = 42
+ assert_equal 42, o.foo
+ end
+
+ def test_ractor
+ assert_ractor(<<~RUBY, require: 'ostruct')
+ obj1 = OpenStruct.new(a: 42, b: 42)
+ obj1.c = 42
+ obj1.freeze
+
+ obj2 = Ractor.new obj1 do |obj|
+ obj
+ end.take
+ assert obj1.object_id == obj2.object_id
+ RUBY
+ end
+
+ def test_legacy_yaml
+ s = "--- !ruby/object:OpenStruct\ntable:\n :foo: 42\n"
+ o = YAML.load(s)
+ assert_equal(42, o.foo)
+
+ o = OpenStruct.new(table: {foo: 42})
+ assert_equal({foo: 42}, YAML.load(YAML.dump(o)).table)
+ end
+
+ def test_yaml
+ h = {name: "John Smith", age: 70, pension: 300.42}
+ yaml = "--- !ruby/object:OpenStruct\nname: John Smith\nage: 70\npension: 300.42\n"
+ os1 = OpenStruct.new(h)
+ os2 = YAML.load(os1.to_yaml)
+ assert_equal yaml, os1.to_yaml
+ assert_equal os1, os2
+ assert_equal true, os1.eql?(os2)
+ assert_equal 300.42, os2.pension
+ end
+
+ def test_marshal
+ o = OpenStruct.new(name: "John Smith", age: 70, pension: 300.42)
+ o2 = Marshal.load(Marshal.dump(o))
+ assert_equal o, o2
+ end
end
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index e5168d5e2e..113bb818ce 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -269,17 +269,17 @@ class TestPathname < Test::Unit::TestCase
Pathname.new(path).relative?
end
+ defassert(:relative?, true, '')
defassert(:relative?, false, '/')
defassert(:relative?, false, '/a')
defassert(:relative?, false, '/..')
defassert(:relative?, true, 'a')
defassert(:relative?, true, 'a/b')
- if DOSISH_DRIVE_LETTER
- defassert(:relative?, false, 'A:')
- defassert(:relative?, false, 'A:/')
- defassert(:relative?, false, 'A:/a')
- end
+ defassert(:relative?, !DOSISH_DRIVE_LETTER, 'A:.')
+ defassert(:relative?, !DOSISH_DRIVE_LETTER, 'A:')
+ defassert(:relative?, !DOSISH_DRIVE_LETTER, 'A:/')
+ defassert(:relative?, !DOSISH_DRIVE_LETTER, 'A:/a')
if File.dirname('//') == '//'
defassert(:relative?, false, '//')
@@ -345,9 +345,26 @@ class TestPathname < Test::Unit::TestCase
def has_symlink?
begin
File.symlink("", "")
- rescue NotImplementedError, Errno::EACCES
+ rescue NotImplementedError
return false
rescue Errno::ENOENT
+ return false
+ rescue Errno::EACCES
+ return false
+ end
+ return true
+ end
+
+ def has_hardlink?
+ begin
+ with_tmpchdir("rubytest-pathname") {|dir|
+ File.write("dummy", "dummy")
+ File.link("dummy", "hardlink")
+ }
+ rescue NotImplementedError
+ return false
+ rescue Errno::EACCES
+ return false
end
return true
end
@@ -616,7 +633,7 @@ class TestPathname < Test::Unit::TestCase
def test_kernel_open
count = 0
result = Kernel.open(Pathname.new(__FILE__)) {|f|
- assert(File.identical?(__FILE__, f))
+ assert_file.identical?(__FILE__, f)
count += 1
2
}
@@ -912,6 +929,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_make_link
+ return if !has_hardlink?
with_tmpchdir('rubytest-pathname') {|dir|
open("a", "w") {|f| f.write "abc" }
Pathname("l").make_link(Pathname("a"))
@@ -1324,18 +1342,18 @@ class TestPathname < Test::Unit::TestCase
def test_mkdir
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("d").mkdir
- assert(File.directory?("d"))
+ assert_file.directory?("d")
Pathname("e").mkdir(0770)
- assert(File.directory?("e"))
+ assert_file.directory?("e")
}
end
def test_rmdir
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("d").mkdir
- assert(File.directory?("d"))
+ assert_file.directory?("d")
Pathname("d").rmdir
- assert(!File.exist?("d"))
+ assert_file.not_exist?("d")
}
end
@@ -1398,16 +1416,16 @@ class TestPathname < Test::Unit::TestCase
def test_mkpath
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("a/b/c/d").mkpath
- assert(File.directory?("a/b/c/d"))
+ assert_file.directory?("a/b/c/d")
}
end
def test_rmtree
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("a/b/c/d").mkpath
- assert(File.exist?("a/b/c/d"))
+ assert_file.exist?("a/b/c/d")
Pathname("a").rmtree
- assert(!File.exist?("a"))
+ assert_file.not_exist?("a")
}
end
@@ -1415,10 +1433,10 @@ class TestPathname < Test::Unit::TestCase
with_tmpchdir('rubytest-pathname') {|dir|
open("f", "w") {|f| f.write "abc" }
Pathname("f").unlink
- assert(!File.exist?("f"))
+ assert_file.not_exist?("f")
Dir.mkdir("d")
Pathname("d").unlink
- assert(!File.exist?("d"))
+ assert_file.not_exist?("d")
}
end
@@ -1443,7 +1461,7 @@ class TestPathname < Test::Unit::TestCase
end
def test_file_fnmatch
- assert(File.fnmatch("*.*", Pathname.new("bar.baz")))
+ assert_file.fnmatch("*.*", Pathname.new("bar.baz"))
end
def test_relative_path_from_casefold
diff --git a/test/pathname/test_ractor.rb b/test/pathname/test_ractor.rb
new file mode 100644
index 0000000000..9ce43ef640
--- /dev/null
+++ b/test/pathname/test_ractor.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+require "test/unit"
+require "pathname"
+
+class TestPathnameRactor < Test::Unit::TestCase
+ def setup
+ skip unless defined? Ractor
+ end
+
+ def test_ractor_shareable
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ $VERBOSE = nil
+ require "pathname"
+ r = Ractor.new Pathname("a") do |x|
+ x.join(Pathname("b"), Pathname("c"))
+ end
+ assert_equal(Pathname("a/b/c"), r.take)
+ end;
+ end
+end
+
diff --git a/test/psych/helper.rb b/test/psych/helper.rb
index 9348457958..0643139d8c 100644
--- a/test/psych/helper.rb
+++ b/test/psych/helper.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'minitest/autorun'
+require 'test/unit'
require 'stringio'
require 'tempfile'
require 'date'
@@ -7,13 +7,7 @@ require 'date'
require 'psych'
module Psych
- superclass = if defined?(Minitest::Test)
- Minitest::Test
- else
- MiniTest::Unit::TestCase
- end
-
- class TestCase < superclass
+ class TestCase < Test::Unit::TestCase
def self.suppress_warning
verbose, $VERBOSE = $VERBOSE, nil
yield
@@ -47,24 +41,30 @@ module Psych
# Convert between Psych and the object to verify correct parsing and
# emitting
#
- def assert_to_yaml( obj, yaml )
- assert_equal( obj, Psych::load( yaml ) )
+ def assert_to_yaml( obj, yaml, loader = :load )
+ assert_equal( obj, Psych.send(loader, yaml) )
assert_equal( obj, Psych::parse( yaml ).transform )
- assert_equal( obj, Psych::load( obj.to_yaml ) )
+ assert_equal( obj, Psych.send(loader, obj.to_yaml) )
assert_equal( obj, Psych::parse( obj.to_yaml ).transform )
- assert_equal( obj, Psych::load(
+ assert_equal( obj, Psych.send(loader,
obj.to_yaml(
:UseVersion => true, :UseHeader => true, :SortKeys => true
)
))
+ rescue Psych::DisallowedClass, Psych::BadAlias
+ assert_to_yaml obj, yaml, :unsafe_load
end
#
# Test parser only
#
def assert_parse_only( obj, yaml )
- assert_equal( obj, Psych::load( yaml ) )
- assert_equal( obj, Psych::parse( yaml ).transform )
+ begin
+ assert_equal obj, Psych::load( yaml )
+ rescue Psych::DisallowedClass, Psych::BadAlias
+ assert_equal obj, Psych::unsafe_load( yaml )
+ end
+ assert_equal obj, Psych::parse( yaml ).transform
end
def assert_cycle( obj )
@@ -75,9 +75,15 @@ module Psych
assert_nil Psych::load(Psych.dump(obj))
assert_nil Psych::load(obj.to_yaml)
else
- assert_equal(obj, Psych.load(v.tree.yaml))
- assert_equal(obj, Psych::load(Psych.dump(obj)))
- assert_equal(obj, Psych::load(obj.to_yaml))
+ begin
+ assert_equal(obj, Psych.load(v.tree.yaml))
+ assert_equal(obj, Psych::load(Psych.dump(obj)))
+ assert_equal(obj, Psych::load(obj.to_yaml))
+ rescue Psych::DisallowedClass, Psych::BadAlias
+ assert_equal(obj, Psych.unsafe_load(v.tree.yaml))
+ assert_equal(obj, Psych::unsafe_load(Psych.dump(obj)))
+ assert_equal(obj, Psych::unsafe_load(obj.to_yaml))
+ end
end
end
diff --git a/test/psych/test_alias_and_anchor.rb b/test/psych/test_alias_and_anchor.rb
index 91c09dfdfa..81ebd66bed 100644
--- a/test/psych/test_alias_and_anchor.rb
+++ b/test/psych/test_alias_and_anchor.rb
@@ -19,7 +19,7 @@ module Psych
- *id001
- *id001
EOYAML
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each {|el| assert_same(result[0], el) }
end
@@ -33,7 +33,7 @@ EOYAML
- *id001
EOYAML
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each do |el|
assert_same(result[0], el)
assert_equal('test1', el.var1)
@@ -50,7 +50,7 @@ EOYAML
- *id001
- *id001
EOYAML
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each do |el|
assert_same(result[0], el)
assert_equal('test', el.var1)
@@ -62,7 +62,7 @@ EOYAML
original = [o,o,o]
yaml = Psych.dump original
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each {|el| assert_same(result[0], el) }
end
@@ -73,7 +73,7 @@ EOYAML
original = [o,o,o]
yaml = Psych.dump original
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each do |el|
assert_same(result[0], el)
assert_equal('test1', el.var1)
@@ -87,7 +87,7 @@ EOYAML
original = [o,o,o]
yaml = Psych.dump original
- result = Psych.load yaml
+ result = Psych.unsafe_load yaml
result.each do |el|
assert_same(result[0], el)
assert_equal('test', el.var1)
diff --git a/test/psych/test_array.rb b/test/psych/test_array.rb
index f2bbdcab88..28b76da785 100644
--- a/test/psych/test_array.rb
+++ b/test/psych/test_array.rb
@@ -24,7 +24,7 @@ module Psych
def test_another_subclass_with_attributes
y = Y.new.tap {|o| o.val = 1}
y << "foo" << "bar"
- y = Psych.load Psych.dump y
+ y = Psych.unsafe_load Psych.dump y
assert_equal %w{foo bar}, y
assert_equal Y, y.class
@@ -42,13 +42,13 @@ module Psych
end
def test_subclass_with_attributes
- y = Psych.load Psych.dump Y.new.tap {|o| o.val = 1}
+ y = Psych.unsafe_load Psych.dump Y.new.tap {|o| o.val = 1}
assert_equal Y, y.class
assert_equal 1, y.val
end
def test_backwards_with_syck
- x = Psych.load "--- !seq:#{X.name} []\n\n"
+ x = Psych.unsafe_load "--- !seq:#{X.name} []\n\n"
assert_equal X, x.class
end
diff --git a/test/psych/test_class.rb b/test/psych/test_class.rb
index 71f7ec31fd..faa504c7e2 100644
--- a/test/psych/test_class.rb
+++ b/test/psych/test_class.rb
@@ -7,13 +7,13 @@ module Psych
end
def test_cycle_anonymous_class
- assert_raises(::TypeError) do
+ assert_raise(::TypeError) do
assert_cycle(Class.new)
end
end
def test_cycle_anonymous_module
- assert_raises(::TypeError) do
+ assert_raise(::TypeError) do
assert_cycle(Module.new)
end
end
diff --git a/test/psych/test_coder.rb b/test/psych/test_coder.rb
index 5ea8cab966..b2be0a4109 100644
--- a/test/psych/test_coder.rb
+++ b/test/psych/test_coder.rb
@@ -112,9 +112,19 @@ module Psych
end
end
+ class CustomEncode
+ def initialize(**opts)
+ @opts = opts
+ end
+
+ def encode_with(coder)
+ @opts.each { |k,v| coder.public_send :"#{k}=", v }
+ end
+ end
+
def test_self_referential
x = Referential.new
- copy = Psych.load Psych.dump x
+ copy = Psych.unsafe_load Psych.dump x
assert_equal copy, copy.a
end
@@ -153,23 +163,23 @@ module Psych
end
def test_represent_map
- thing = Psych.load(Psych.dump(RepresentWithMap.new))
+ thing = Psych.unsafe_load(Psych.dump(RepresentWithMap.new))
assert_equal({ "string" => 'a', :symbol => 'b' }, thing.map)
end
def test_represent_sequence
- thing = Psych.load(Psych.dump(RepresentWithSeq.new))
+ thing = Psych.unsafe_load(Psych.dump(RepresentWithSeq.new))
assert_equal %w{ foo bar }, thing.seq
end
def test_represent_with_init
- thing = Psych.load(Psych.dump(RepresentWithInit.new))
+ thing = Psych.unsafe_load(Psych.dump(RepresentWithInit.new))
assert_equal 'bar', thing.str
end
def test_represent!
assert_match(/foo/, Psych.dump(Represent.new))
- assert_instance_of(Represent, Psych.load(Psych.dump(Represent.new)))
+ assert_instance_of(Represent, Psych.unsafe_load(Psych.dump(Represent.new)))
end
def test_scalar_coder
@@ -179,7 +189,7 @@ module Psych
def test_load_dumped_tagging
foo = InitApi.new
- bar = Psych.load(Psych.dump(foo))
+ bar = Psych.unsafe_load(Psych.dump(foo))
assert_equal false, bar.implicit
assert_equal "!ruby/object:Psych::TestCoder::InitApi", bar.tag
assert_equal Psych::Nodes::Mapping::BLOCK, bar.style
@@ -198,10 +208,121 @@ module Psych
def test_dump_init_with
foo = InitApi.new
- bar = Psych.load(Psych.dump(foo))
+ bar = Psych.unsafe_load(Psych.dump(foo))
assert_equal foo.a, bar.a
assert_equal foo.b, bar.b
assert_nil bar.c
end
+
+ def test_coder_style_map_default
+ foo = Psych.dump a: 1, b: 2
+ assert_equal "---\n:a: 1\n:b: 2\n", foo
+ end
+
+ def test_coder_style_map_any
+ foo = Psych.dump CustomEncode.new \
+ map: {a: 1, b: 2},
+ style: Psych::Nodes::Mapping::ANY,
+ tag: nil
+ assert_equal "---\n:a: 1\n:b: 2\n", foo
+ end
+
+ def test_coder_style_map_block
+ foo = Psych.dump CustomEncode.new \
+ map: {a: 1, b: 2},
+ style: Psych::Nodes::Mapping::BLOCK,
+ tag: nil
+ assert_equal "---\n:a: 1\n:b: 2\n", foo
+ end
+
+ def test_coder_style_map_flow
+ foo = Psych.dump CustomEncode.new \
+ map: { a: 1, b: 2 },
+ style: Psych::Nodes::Mapping::FLOW,
+ tag: nil
+ assert_equal "--- {! ':a': 1, ! ':b': 2}\n", foo
+ end
+
+ def test_coder_style_seq_default
+ foo = Psych.dump [ 1, 2, 3 ]
+ assert_equal "---\n- 1\n- 2\n- 3\n", foo
+ end
+
+ def test_coder_style_seq_any
+ foo = Psych.dump CustomEncode.new \
+ seq: [ 1, 2, 3 ],
+ style: Psych::Nodes::Sequence::ANY,
+ tag: nil
+ assert_equal "---\n- 1\n- 2\n- 3\n", foo
+ end
+
+ def test_coder_style_seq_block
+ foo = Psych.dump CustomEncode.new \
+ seq: [ 1, 2, 3 ],
+ style: Psych::Nodes::Sequence::BLOCK,
+ tag: nil
+ assert_equal "---\n- 1\n- 2\n- 3\n", foo
+ end
+
+ def test_coder_style_seq_flow
+ foo = Psych.dump CustomEncode.new \
+ seq: [ 1, 2, 3 ],
+ style: Psych::Nodes::Sequence::FLOW,
+ tag: nil
+ assert_equal "--- [1, 2, 3]\n", foo
+ end
+
+ def test_coder_style_scalar_default
+ foo = Psych.dump 'some scalar'
+ assert_match(/\A--- some scalar\n(?:\.\.\.\n)?\z/, foo)
+ end
+
+ def test_coder_style_scalar_any
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::ANY,
+ tag: nil
+ assert_match(/\A--- some scalar\n(?:\.\.\.\n)?\z/, foo)
+ end
+
+ def test_coder_style_scalar_plain
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::PLAIN,
+ tag: nil
+ assert_match(/\A--- some scalar\n(?:\.\.\.\n)?\z/, foo)
+ end
+
+ def test_coder_style_scalar_single_quoted
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::SINGLE_QUOTED,
+ tag: nil
+ assert_equal "--- ! 'some scalar'\n", foo
+ end
+
+ def test_coder_style_scalar_double_quoted
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::DOUBLE_QUOTED,
+ tag: nil
+ assert_equal %Q'--- ! "some scalar"\n', foo
+ end
+
+ def test_coder_style_scalar_literal
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::LITERAL,
+ tag: nil
+ assert_equal "--- ! |-\n some scalar\n", foo
+ end
+
+ def test_coder_style_scalar_folded
+ foo = Psych.dump CustomEncode.new \
+ scalar: 'some scalar',
+ style: Psych::Nodes::Scalar::FOLDED,
+ tag: nil
+ assert_equal "--- ! >-\n some scalar\n", foo
+ end
end
end
diff --git a/test/psych/test_date_time.rb b/test/psych/test_date_time.rb
index f73f34628f..6f1e8b509e 100644
--- a/test/psych/test_date_time.rb
+++ b/test/psych/test_date_time.rb
@@ -22,7 +22,7 @@ module Psych
def test_timezone_offset
times = [Time.new(2017, 4, 13, 12, 0, 0, "+09:00"),
Time.new(2017, 4, 13, 12, 0, 0, "-05:00")]
- cycled = Psych::load(Psych.dump times)
+ cycled = Psych::unsafe_load(Psych.dump times)
assert_match(/12:00:00 \+0900/, cycled.first.to_s)
assert_match(/12:00:00 -0500/, cycled.last.to_s)
end
@@ -39,7 +39,7 @@ module Psych
def test_datetime_timezone_offset
times = [DateTime.new(2017, 4, 13, 12, 0, 0, "+09:00"),
DateTime.new(2017, 4, 13, 12, 0, 0, "-05:00")]
- cycled = Psych::load(Psych.dump times)
+ cycled = Psych::unsafe_load(Psych.dump times)
assert_match(/12:00:00\+09:00/, cycled.first.to_s)
assert_match(/12:00:00-05:00/, cycled.last.to_s)
end
diff --git a/test/psych/test_deprecated.rb b/test/psych/test_deprecated.rb
index 624f4379a6..af3379909a 100644
--- a/test/psych/test_deprecated.rb
+++ b/test/psych/test_deprecated.rb
@@ -41,7 +41,7 @@ module Psych
def test_recursive_quick_emit_encode_with
qeew = QuickEmitterEncodeWith.new
hash = { :qe => qeew }
- hash2 = Psych.load Psych.dump hash
+ hash2 = Psych.unsafe_load Psych.dump hash
qe = hash2[:qe]
assert_equal qeew.name, qe.name
@@ -72,7 +72,7 @@ module Psych
# receive the yaml_initialize call.
def test_yaml_initialize_and_init_with
hash = { :yi => YamlInitAndInitWith.new }
- hash2 = Psych.load Psych.dump hash
+ hash2 = Psych.unsafe_load Psych.dump hash
yi = hash2[:yi]
assert_equal 'TGIF!', yi.name
diff --git a/test/psych/test_document.rb b/test/psych/test_document.rb
index a88dd32f0d..cf3b7001fc 100644
--- a/test/psych/test_document.rb
+++ b/test/psych/test_document.rb
@@ -30,7 +30,7 @@ module Psych
end
def test_emit_bad_tag
- assert_raises(RuntimeError) do
+ assert_raise(RuntimeError) do
@doc.tag_directives = [['!']]
@stream.yaml
end
diff --git a/test/psych/test_emitter.rb b/test/psych/test_emitter.rb
index 52d5e9d1c1..506d72241c 100644
--- a/test/psych/test_emitter.rb
+++ b/test/psych/test_emitter.rb
@@ -40,7 +40,7 @@ module Psych
end
def test_start_stream_arg_error
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.start_stream 'asdfasdf'
end
end
@@ -56,7 +56,7 @@ module Psych
[[], [nil,nil], false],
[[1,1], [[nil, "tag:TALOS"]], 0],
].each do |args|
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.start_document(*args)
end
end
@@ -73,7 +73,7 @@ module Psych
['foo', nil, nil, false, true, :foo],
[nil, nil, nil, false, true, 1],
].each do |args|
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.scalar(*args)
end
end
@@ -83,11 +83,11 @@ module Psych
@emitter.start_stream Psych::Nodes::Stream::UTF8
@emitter.start_document [], [], false
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.start_sequence(nil, Object.new, true, 1)
end
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@emitter.start_sequence(nil, nil, true, :foo)
end
end
diff --git a/test/psych/test_encoding.rb b/test/psych/test_encoding.rb
index ef6653142f..e5831c9045 100644
--- a/test/psych/test_encoding.rb
+++ b/test/psych/test_encoding.rb
@@ -63,7 +63,7 @@ module Psych
# If the external encoding isn't utf8, utf16le, or utf16be, we cannot
# process the file.
File.open(t.path, 'r', :encoding => 'SHIFT_JIS') do |f|
- assert_raises Psych::SyntaxError do
+ assert_raise Psych::SyntaxError do
Psych.load(f)
end
end
@@ -121,7 +121,7 @@ module Psych
def test_emit_alias
@emitter.start_stream Psych::Parser::UTF8
@emitter.start_document [], [], true
- e = assert_raises(RuntimeError) do
+ e = assert_raise(RuntimeError) do
@emitter.alias 'ドラえもん'.encode('EUC-JP')
end
assert_match(/alias value/, e.message)
diff --git a/test/psych/test_exception.rb b/test/psych/test_exception.rb
index e7fc88c706..d2ae76a7d2 100644
--- a/test/psych/test_exception.rb
+++ b/test/psych/test_exception.rb
@@ -33,42 +33,42 @@ module Psych
def test_backtrace
err = make_ex
- new_err = Psych.load(Psych.dump(err))
+ new_err = Psych.unsafe_load(Psych.dump(err))
assert_equal err.backtrace, new_err.backtrace
end
def test_naming_exception
err = String.xxx rescue $!
- new_err = Psych.load(Psych.dump(err))
+ new_err = Psych.unsafe_load(Psych.dump(err))
assert_equal err.message, new_err.message
end
def test_load_takes_file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load '--- `'
end
assert_nil ex.file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load '--- `', filename: 'meow'
end
assert_equal 'meow', ex.file
# deprecated interface
- ex = assert_raises(Psych::SyntaxError) do
- Psych.load '--- `', 'deprecated'
+ ex = assert_raise(Psych::SyntaxError) do
+ Psych.unsafe_load '--- `', 'deprecated'
end
assert_equal 'deprecated', ex.file
end
def test_psych_parse_stream_takes_file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse_stream '--- `'
end
assert_nil ex.file
assert_match '(<unknown>)', ex.message
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse_stream '--- `', filename: 'omg!'
end
assert_equal 'omg!', ex.file
@@ -76,19 +76,19 @@ module Psych
end
def test_load_stream_takes_file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load_stream '--- `'
end
assert_nil ex.file
assert_match '(<unknown>)', ex.message
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load_stream '--- `', filename: 'omg!'
end
assert_equal 'omg!', ex.file
# deprecated interface
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load_stream '--- `', 'deprecated'
end
assert_equal 'deprecated', ex.file
@@ -99,7 +99,7 @@ module Psych
t.binmode
t.write '--- `'
t.close
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse_file t.path
end
assert_equal t.path, ex.file
@@ -111,34 +111,46 @@ module Psych
t.binmode
t.write '--- `'
t.close
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.load_file t.path
end
assert_equal t.path, ex.file
}
end
+ def test_safe_load_file_exception
+ Tempfile.create(['loadfile', 'yml']) {|t|
+ t.binmode
+ t.write '--- `'
+ t.close
+ ex = assert_raise(Psych::SyntaxError) do
+ Psych.safe_load_file t.path
+ end
+ assert_equal t.path, ex.file
+ }
+ end
+
def test_psych_parse_takes_file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse '--- `'
end
assert_match '(<unknown>)', ex.message
assert_nil ex.file
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse '--- `', filename: 'omg!'
end
assert_match 'omg!', ex.message
# deprecated interface
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
Psych.parse '--- `', 'deprecated'
end
assert_match 'deprecated', ex.message
end
def test_attributes
- e = assert_raises(Psych::SyntaxError) {
+ e = assert_raise(Psych::SyntaxError) {
Psych.load '--- `foo'
}
@@ -153,8 +165,9 @@ module Psych
end
def test_convert
- w = Psych.load(Psych.dump(@wups))
- assert_equal @wups, w
+ w = Psych.unsafe_load(Psych.dump(@wups))
+ assert_equal @wups.message, w.message
+ assert_equal @wups.backtrace, w.backtrace
assert_equal 1, w.foo
assert_equal 2, w.bar
end
diff --git a/test/psych/test_hash.rb b/test/psych/test_hash.rb
index ba11b827da..5374781339 100644
--- a/test/psych/test_hash.rb
+++ b/test/psych/test_hash.rb
@@ -39,7 +39,7 @@ module Psych
def test_hash_with_ivar
t1 = HashWithIvar.new
t1[:foo] = :bar
- t2 = Psych.load(Psych.dump(t1))
+ t2 = Psych.unsafe_load(Psych.dump(t1))
assert_equal t1, t2
assert_cycle t1
end
@@ -54,14 +54,14 @@ module Psych
def test_custom_initialized
a = [1,2,3,4,5]
t1 = HashWithCustomInit.new(a)
- t2 = Psych.load(Psych.dump(t1))
+ t2 = Psych.unsafe_load(Psych.dump(t1))
assert_equal t1, t2
assert_cycle t1
end
def test_custom_initialize_no_ivar
t1 = HashWithCustomInitNoIvar.new(nil)
- t2 = Psych.load(Psych.dump(t1))
+ t2 = Psych.unsafe_load(Psych.dump(t1))
assert_equal t1, t2
assert_cycle t1
end
@@ -70,25 +70,25 @@ module Psych
x = X.new
x[:a] = 'b'
x.instance_variable_set :@foo, 'bar'
- dup = Psych.load Psych.dump x
+ dup = Psych.unsafe_load Psych.dump x
assert_cycle x
assert_equal 'bar', dup.instance_variable_get(:@foo)
assert_equal X, dup.class
end
def test_load_with_class_syck_compatibility
- hash = Psych.load "--- !ruby/object:Hash\n:user_id: 7\n:username: Lucas\n"
+ hash = Psych.unsafe_load "--- !ruby/object:Hash\n:user_id: 7\n:username: Lucas\n"
assert_equal({ user_id: 7, username: 'Lucas'}, hash)
end
def test_empty_subclass
assert_match "!ruby/hash:#{X}", Psych.dump(X.new)
- x = Psych.load Psych.dump X.new
+ x = Psych.unsafe_load Psych.dump X.new
assert_equal X, x.class
end
def test_map
- x = Psych.load "--- !map:#{X} { }\n"
+ x = Psych.unsafe_load "--- !map:#{X} { }\n"
assert_equal X, x.class
end
@@ -102,7 +102,7 @@ module Psych
end
def test_ref_append
- hash = Psych.load(<<-eoyml)
+ hash = Psych.unsafe_load(<<-eoyml)
---
foo: &foo
hello: world
@@ -114,7 +114,7 @@ eoyml
def test_key_deduplication
unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20)))
- skip "This Ruby implementation doesn't support string deduplication"
+ pend "This Ruby implementation doesn't support string deduplication"
end
hashes = Psych.load(<<-eoyml)
diff --git a/test/psych/test_marshalable.rb b/test/psych/test_marshalable.rb
index b1f4a837f5..74ee902887 100644
--- a/test/psych/test_marshalable.rb
+++ b/test/psych/test_marshalable.rb
@@ -6,7 +6,7 @@ module Psych
class TestMarshalable < TestCase
def test_objects_defining_marshal_dump_and_marshal_load_can_be_dumped
sd = SimpleDelegator.new(1)
- loaded = Psych.load(Psych.dump(sd))
+ loaded = Psych.unsafe_load(Psych.dump(sd))
assert_instance_of(SimpleDelegator, loaded)
assert_equal(sd, loaded)
@@ -46,7 +46,15 @@ module Psych
def test_init_with_takes_priority_over_marshal_methods
obj = PsychCustomMarshalable.new(1)
- loaded = Psych.load(Psych.dump(obj))
+ loaded = Psych.unsafe_load(Psych.dump(obj))
+
+ assert(PsychCustomMarshalable === loaded)
+ assert_equal(2, loaded.foo)
+ end
+
+ def test_init_symbolize_names
+ obj = PsychCustomMarshalable.new(1)
+ loaded = Psych.unsafe_load(Psych.dump(obj), symbolize_names: true)
assert(PsychCustomMarshalable === loaded)
assert_equal(2, loaded.foo)
diff --git a/test/psych/test_merge_keys.rb b/test/psych/test_merge_keys.rb
index 1bc3dd1cb6..dcf4f1fce3 100644
--- a/test/psych/test_merge_keys.rb
+++ b/test/psych/test_merge_keys.rb
@@ -17,6 +17,16 @@ map:
assert_equal hash, doc
end
+ def test_merge_key_with_bare_hash_symbolized_names
+ doc = Psych.load <<-eodoc, symbolize_names: true
+map:
+ <<:
+ hello: world
+ eodoc
+ hash = { map: { hello: "world" } }
+ assert_equal hash, doc
+ end
+
def test_roundtrip_with_chevron_key
h = {}
v = { 'a' => h, '<<' => h }
@@ -24,7 +34,7 @@ map:
end
def test_explicit_string
- doc = Psych.load <<-eoyml
+ doc = Psych.unsafe_load <<-eoyml
a: &me { hello: world }
b: { !!str '<<': *me }
eoyml
@@ -45,7 +55,7 @@ product:
!ruby/object:#{Product.name}
<<: *foo
eoyml
- hash = Psych.load s
+ hash = Psych.unsafe_load s
assert_equal({"bar" => 10}, hash["foo"])
product = hash["product"]
assert_equal 10, product.bar
@@ -57,7 +67,7 @@ defaults: &defaults
development:
<<: *defaults
eoyml
- assert_equal({'<<' => nil }, Psych.load(yaml)['development'])
+ assert_equal({'<<' => nil }, Psych.unsafe_load(yaml)['development'])
end
def test_merge_array
@@ -67,7 +77,7 @@ foo: &hello
baz:
<<: *hello
eoyml
- assert_equal({'<<' => [1]}, Psych.load(yaml)['baz'])
+ assert_equal({'<<' => [1]}, Psych.unsafe_load(yaml)['baz'])
end
def test_merge_is_not_partial
@@ -79,9 +89,9 @@ foo: &hello
baz:
<<: [*hello, *default]
eoyml
- doc = Psych.load yaml
+ doc = Psych.unsafe_load yaml
refute doc['baz'].key? 'hello'
- assert_equal({'<<' => [[1], {"hello"=>"world"}]}, Psych.load(yaml)['baz'])
+ assert_equal({'<<' => [[1], {"hello"=>"world"}]}, Psych.unsafe_load(yaml)['baz'])
end
def test_merge_seq_nil
@@ -90,7 +100,7 @@ foo: &hello
baz:
<<: [*hello]
eoyml
- assert_equal({'<<' => [nil]}, Psych.load(yaml)['baz'])
+ assert_equal({'<<' => [nil]}, Psych.unsafe_load(yaml)['baz'])
end
def test_bad_seq_merge
@@ -99,7 +109,7 @@ defaults: &defaults [1, 2, 3]
development:
<<: *defaults
eoyml
- assert_equal({'<<' => [1,2,3]}, Psych.load(yaml)['development'])
+ assert_equal({'<<' => [1,2,3]}, Psych.unsafe_load(yaml)['development'])
end
def test_missing_merge_key
@@ -107,7 +117,7 @@ development:
bar:
<< : *foo
eoyml
- exp = assert_raises(Psych::BadAlias) { Psych.load yaml }
+ exp = assert_raise(Psych::BadAlias) { Psych.load yaml }
assert_match 'foo', exp.message
end
@@ -124,7 +134,7 @@ bar:
hash = {
"foo" => { "hello" => "world"},
"bar" => { "hello" => "world", "baz" => "boo" } }
- assert_equal hash, Psych.load(yaml)
+ assert_equal hash, Psych.unsafe_load(yaml)
end
def test_multiple_maps
@@ -149,7 +159,7 @@ bar:
'label' => 'center/big'
}
- assert_equal hash, Psych.load(yaml)[4]
+ assert_equal hash, Psych.unsafe_load(yaml)[4]
end
def test_override
@@ -175,7 +185,7 @@ bar:
'label' => 'center/big'
}
- assert_equal hash, Psych.load(yaml)[4]
+ assert_equal hash, Psych.unsafe_load(yaml)[4]
end
end
end
diff --git a/test/psych/test_object.rb b/test/psych/test_object.rb
index f1c61451d0..0faf6b244d 100644
--- a/test/psych/test_object.rb
+++ b/test/psych/test_object.rb
@@ -28,7 +28,7 @@ module Psych
def test_tag_round_trip
tag = Tagged.new
- tag2 = Psych.load(Psych.dump(tag))
+ tag2 = Psych.unsafe_load(Psych.dump(tag))
assert_equal tag.baz, tag2.baz
assert_instance_of(Tagged, tag2)
end
@@ -36,7 +36,7 @@ module Psych
def test_cyclic_references
foo = Foo.new(nil)
foo.parent = foo
- loaded = Psych.load Psych.dump foo
+ loaded = Psych.unsafe_load Psych.dump foo
assert_instance_of(Foo, loaded)
assert_equal loaded, loaded.parent
diff --git a/test/psych/test_object_references.rb b/test/psych/test_object_references.rb
index ca69c7d288..269d72242e 100644
--- a/test/psych/test_object_references.rb
+++ b/test/psych/test_object_references.rb
@@ -34,12 +34,16 @@ module Psych
def assert_reference_trip obj
yml = Psych.dump([obj, obj])
assert_match(/\*-?\d+/, yml)
- data = Psych.load yml
+ begin
+ data = Psych.load yml
+ rescue Psych::DisallowedClass
+ data = Psych.unsafe_load yml
+ end
assert_equal data.first.object_id, data.last.object_id
end
def test_float_references
- data = Psych.load <<-eoyml
+ data = Psych.unsafe_load <<-eoyml
---\s
- &name 1.2
- *name
@@ -49,7 +53,7 @@ module Psych
end
def test_binary_references
- data = Psych.load <<-eoyml
+ data = Psych.unsafe_load <<-eoyml
---
- &name !binary |-
aGVsbG8gd29ybGQh
@@ -60,7 +64,7 @@ module Psych
end
def test_regexp_references
- data = Psych.load <<-eoyml
+ data = Psych.unsafe_load <<-eoyml
---\s
- &name !ruby/regexp /pattern/i
- *name
diff --git a/test/psych/test_omap.rb b/test/psych/test_omap.rb
index 98636ded97..6de0286406 100644
--- a/test/psych/test_omap.rb
+++ b/test/psych/test_omap.rb
@@ -4,7 +4,7 @@ require_relative 'helper'
module Psych
class TestOmap < TestCase
def test_parse_as_map
- o = Psych.load "--- !!omap\na: 1\nb: 2"
+ o = Psych.unsafe_load "--- !!omap\na: 1\nb: 2"
assert_kind_of Psych::Omap, o
assert_equal 1, o['a']
assert_equal 2, o['b']
@@ -14,7 +14,7 @@ module Psych
map = Psych::Omap.new
map['foo'] = 'bar'
map['self'] = map
- assert_equal(map, Psych.load(Psych.dump(map)))
+ assert_equal(map, Psych.unsafe_load(Psych.dump(map)))
end
def test_keys
diff --git a/test/psych/test_parser.rb b/test/psych/test_parser.rb
index e8225dabb6..3604e7c985 100644
--- a/test/psych/test_parser.rb
+++ b/test/psych/test_parser.rb
@@ -63,7 +63,7 @@ module Psych
parser = Psych::Parser.new klass.new
2.times {
- assert_raises(RuntimeError, method.to_s) do
+ assert_raise(RuntimeError, method.to_s) do
parser.parse yaml
end
}
@@ -77,7 +77,7 @@ module Psych
end
def test_filename
- ex = assert_raises(Psych::SyntaxError) do
+ ex = assert_raise(Psych::SyntaxError) do
@parser.parse '--- `', 'omg!'
end
assert_match 'omg!', ex.message
@@ -180,7 +180,7 @@ module Psych
def o.external_encoding; nil end
def o.read len; self end
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@parser.parse o
end
end
@@ -193,23 +193,23 @@ module Psych
end
def test_syntax_error
- assert_raises(Psych::SyntaxError) do
+ assert_raise(Psych::SyntaxError) do
@parser.parse("---\n\"foo\"\n\"bar\"\n")
end
end
def test_syntax_error_twice
- assert_raises(Psych::SyntaxError) do
+ assert_raise(Psych::SyntaxError) do
@parser.parse("---\n\"foo\"\n\"bar\"\n")
end
- assert_raises(Psych::SyntaxError) do
+ assert_raise(Psych::SyntaxError) do
@parser.parse("---\n\"foo\"\n\"bar\"\n")
end
end
def test_syntax_error_has_path_for_string
- e = assert_raises(Psych::SyntaxError) do
+ e = assert_raise(Psych::SyntaxError) do
@parser.parse("---\n\"foo\"\n\"bar\"\n")
end
assert_match '(<unknown>):', e.message
@@ -219,7 +219,7 @@ module Psych
io = StringIO.new "---\n\"foo\"\n\"bar\"\n"
def io.path; "hello!"; end
- e = assert_raises(Psych::SyntaxError) do
+ e = assert_raise(Psych::SyntaxError) do
@parser.parse(io)
end
assert_match "(#{io.path}):", e.message
diff --git a/test/psych/test_psych.rb b/test/psych/test_psych.rb
index e557feffb7..912bcb9a78 100644
--- a/test/psych/test_psych.rb
+++ b/test/psych/test_psych.rb
@@ -16,7 +16,7 @@ class TestPsych < Psych::TestCase
end
def test_line_width_invalid
- assert_raises(ArgumentError) { Psych.dump('x', { :line_width => -2 }) }
+ assert_raise(ArgumentError) { Psych.dump('x', { :line_width => -2 }) }
end
def test_line_width_no_limit
@@ -61,7 +61,7 @@ class TestPsych < Psych::TestCase
end
def test_load_argument_error
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
Psych.load nil
end
end
@@ -75,7 +75,7 @@ class TestPsych < Psych::TestCase
end
def test_parse_raises_on_bad_input
- assert_raises(Psych::SyntaxError) { Psych.parse("--- `") }
+ assert_raise(Psych::SyntaxError) { Psych.parse("--- `") }
end
def test_parse_with_fallback
@@ -83,8 +83,8 @@ class TestPsych < Psych::TestCase
end
def test_non_existing_class_on_deserialize
- e = assert_raises(ArgumentError) do
- Psych.load("--- !ruby/object:NonExistent\nfoo: 1")
+ e = assert_raise(ArgumentError) do
+ Psych.unsafe_load("--- !ruby/object:NonExistent\nfoo: 1")
end
assert_equal 'undefined class/module NonExistent', e.message
end
@@ -125,12 +125,25 @@ class TestPsych < Psych::TestCase
assert_equal %w{ foo bar }, docs
end
+ def test_load_stream_freeze
+ docs = Psych.load_stream("--- foo\n...\n--- bar\n...", freeze: true)
+ assert_equal %w{ foo bar }, docs
+ docs.each do |string|
+ assert_predicate string, :frozen?
+ end
+ end
+
+ def test_load_stream_symbolize_names
+ docs = Psych.load_stream("---\nfoo: bar", symbolize_names: true)
+ assert_equal [{foo: 'bar'}], docs
+ end
+
def test_load_stream_default_fallback
assert_equal [], Psych.load_stream("")
end
def test_load_stream_raises_on_bad_input
- assert_raises(Psych::SyntaxError) { Psych.load_stream("--- `") }
+ assert_raise(Psych::SyntaxError) { Psych.load_stream("--- `") }
end
def test_parse_stream
@@ -162,7 +175,7 @@ class TestPsych < Psych::TestCase
end
def test_parse_stream_raises_on_bad_input
- assert_raises(Psych::SyntaxError) { Psych.parse_stream("--- `") }
+ assert_raise(Psych::SyntaxError) { Psych.parse_stream("--- `") }
end
def test_add_builtin_type
@@ -192,29 +205,45 @@ class TestPsych < Psych::TestCase
assert_equal({ 'hello' => 'world' }, got)
end
+ def test_load_freeze
+ data = Psych.load("--- {foo: ['a']}", freeze: true)
+ assert_predicate data, :frozen?
+ assert_predicate data['foo'], :frozen?
+ assert_predicate data['foo'].first, :frozen?
+ end
+
+ def test_load_freeze_deduplication
+ unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20)))
+ pend "This Ruby implementation doesn't support string deduplication"
+ end
+
+ data = Psych.load("--- ['a']", freeze: true)
+ assert_same 'a', data.first
+ end
+
def test_load_default_fallback
- assert_equal false, Psych.load("")
+ assert_equal false, Psych.unsafe_load("")
end
def test_load_with_fallback
- assert_equal 42, Psych.load("", "file", fallback: 42)
+ assert_equal 42, Psych.load("", filename: "file", fallback: 42)
end
def test_load_with_fallback_nil_or_false
- assert_nil Psych.load("", "file", fallback: nil)
- assert_equal false, Psych.load("", "file", fallback: false)
+ assert_nil Psych.load("", filename: "file", fallback: nil)
+ assert_equal false, Psych.load("", filename: "file", fallback: false)
end
def test_load_with_fallback_hash
- assert_equal Hash.new, Psych.load("", "file", fallback: Hash.new)
+ assert_equal Hash.new, Psych.load("", filename: "file", fallback: Hash.new)
end
def test_load_with_fallback_for_nil
- assert_nil Psych.load("--- null", "file", fallback: 42)
+ assert_nil Psych.unsafe_load("--- null", "file", fallback: 42)
end
def test_load_with_fallback_for_false
- assert_equal false, Psych.load("--- false", "file", fallback: 42)
+ assert_equal false, Psych.unsafe_load("--- false", "file", fallback: 42)
end
def test_load_file
@@ -226,9 +255,30 @@ class TestPsych < Psych::TestCase
}
end
+ def test_load_file_freeze
+ Tempfile.create(['yikes', 'yml']) {|t|
+ t.binmode
+ t.write('--- hello world')
+ t.close
+
+ object = Psych.load_file(t.path, freeze: true)
+ assert_predicate object, :frozen?
+ }
+ end
+
+ def test_load_file_symbolize_names
+ Tempfile.create(['yikes', 'yml']) {|t|
+ t.binmode
+ t.write("---\nfoo: bar")
+ t.close
+
+ assert_equal({foo: 'bar'}, Psych.load_file(t.path, symbolize_names: true))
+ }
+ end
+
def test_load_file_default_fallback
Tempfile.create(['empty', 'yml']) {|t|
- assert_equal false, Psych.load_file(t.path)
+ assert_equal false, Psych.unsafe_load_file(t.path)
}
end
@@ -269,6 +319,18 @@ class TestPsych < Psych::TestCase
}
end
+ def test_safe_load_file_with_permitted_classe
+ Tempfile.create(['false', 'yml']) {|t|
+ t.binmode
+ t.write("--- !ruby/range\nbegin: 0\nend: 42\nexcl: false\n")
+ t.close
+ assert_equal 0..42, Psych.safe_load_file(t.path, permitted_classes: [Range])
+ assert_raise(Psych::DisallowedClass) {
+ Psych.safe_load_file(t.path)
+ }
+ }
+ end
+
def test_parse_file
Tempfile.create(['yikes', 'yml']) {|t|
t.binmode
@@ -285,9 +347,9 @@ class TestPsych < Psych::TestCase
end
def test_degenerate_strings
- assert_equal false, Psych.load(' ')
+ assert_equal false, Psych.unsafe_load(' ')
assert_equal false, Psych.parse(' ')
- assert_equal false, Psych.load('')
+ assert_equal false, Psych.unsafe_load('')
assert_equal false, Psych.parse('')
end
@@ -309,17 +371,18 @@ class TestPsych < Psych::TestCase
yaml = <<-eoyml
foo:
bar: baz
+ 1: 2
hoge:
- fuga: piyo
eoyml
result = Psych.load(yaml)
- assert_equal result, { "foo" => { "bar" => "baz"}, "hoge" => [{ "fuga" => "piyo" }] }
+ assert_equal result, { "foo" => { "bar" => "baz", 1 => 2 }, "hoge" => [{ "fuga" => "piyo" }] }
result = Psych.load(yaml, symbolize_names: true)
- assert_equal result, { foo: { bar: "baz" }, hoge: [{ fuga: "piyo" }] }
+ assert_equal result, { foo: { bar: "baz", 1 => 2 }, hoge: [{ fuga: "piyo" }] }
result = Psych.safe_load(yaml, symbolize_names: true)
- assert_equal result, { foo: { bar: "baz" }, hoge: [{ fuga: "piyo" }] }
+ assert_equal result, { foo: { bar: "baz", 1 => 2 }, hoge: [{ fuga: "piyo" }] }
end
end
diff --git a/test/psych/test_ractor.rb b/test/psych/test_ractor.rb
new file mode 100644
index 0000000000..1b0d810609
--- /dev/null
+++ b/test/psych/test_ractor.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+require_relative 'helper'
+
+class TestPsychRactor < Test::Unit::TestCase
+ def test_ractor_round_trip
+ assert_ractor(<<~RUBY, require_relative: 'helper')
+ obj = {foo: [42]}
+ obj2 = Ractor.new(obj) do |obj|
+ Psych.unsafe_load(Psych.dump(obj))
+ end.take
+ assert_equal obj, obj2
+ RUBY
+ end
+
+ def test_not_shareable
+ # There's no point in making these frozen / shareable
+ # and the C-ext disregards begin frozen
+ assert_ractor(<<~RUBY, require_relative: 'helper')
+ parser = Psych::Parser.new
+ emitter = Psych::Emitter.new(nil)
+ assert_raise(Ractor::Error) { Ractor.make_shareable(parser) }
+ assert_raise(Ractor::Error) { Ractor.make_shareable(emitter) }
+ RUBY
+ end
+
+ def test_ractor_config
+ # Config is ractor-local
+ # Test is to make sure it works, even though usage is probably very low.
+ # The methods are not documented and might be deprecated one day
+ assert_ractor(<<~RUBY, require_relative: 'helper')
+ r = Ractor.new do
+ Psych.add_builtin_type 'omap' do |type, val|
+ val * 2
+ end
+ Psych.load('--- !!omap hello')
+ end.take
+ assert_equal 'hellohello', r
+ assert_equal 'hello', Psych.load('--- !!omap hello')
+ RUBY
+ end
+
+ def test_ractor_constants
+ assert_ractor(<<~RUBY, require_relative: 'helper')
+ r = Ractor.new do
+ Psych.libyaml_version.join('.') == Psych::LIBYAML_VERSION
+ end.take
+ assert_equal true, r
+ RUBY
+ end
+end if defined?(Ractor)
diff --git a/test/psych/test_safe_load.rb b/test/psych/test_safe_load.rb
index e3972712fc..d13ce7c722 100644
--- a/test/psych/test_safe_load.rb
+++ b/test/psych/test_safe_load.rb
@@ -22,7 +22,7 @@ module Psych
def test_no_recursion
x = []
x << x
- assert_raises(Psych::BadAlias) do
+ assert_raise(Psych::BadAlias) do
Psych.safe_load Psych.dump(x)
end
end
@@ -37,7 +37,7 @@ module Psych
def test_permitted_symbol
yml = Psych.dump :foo
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load yml
end
assert_equal(
@@ -54,15 +54,15 @@ module Psych
end
def test_symbol
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
assert_safe_cycle :foo
end
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load '--- !ruby/symbol foo', permitted_classes: []
end
# deprecated interface
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load '--- !ruby/symbol foo', []
end
@@ -75,16 +75,16 @@ module Psych
end
def test_foo
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load '--- !ruby/object:Foo {}', permitted_classes: [Foo]
end
# deprecated interface
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load '--- !ruby/object:Foo {}', [Foo]
end
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
assert_safe_cycle Foo.new
end
assert_kind_of(Foo, Psych.safe_load(Psych.dump(Foo.new), permitted_classes: [Foo]))
@@ -96,7 +96,7 @@ module Psych
X = Struct.new(:x)
def test_struct_depends_on_sym
assert_safe_cycle(X.new, permitted_classes: [X, Symbol])
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
cycle X.new, permitted_classes: [X]
end
end
@@ -107,14 +107,14 @@ module Psych
foo: bar
eoyml
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load(<<-eoyml, permitted_classes: [Struct])
--- !ruby/struct
foo: bar
eoyml
end
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load(<<-eoyml, permitted_classes: [Symbol])
--- !ruby/struct
foo: bar
@@ -128,14 +128,14 @@ module Psych
foo: bar
eoyml
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load(<<-eoyml, [Struct])
--- !ruby/struct
foo: bar
eoyml
end
- assert_raises(Psych::DisallowedClass) do
+ assert_raise(Psych::DisallowedClass) do
Psych.safe_load(<<-eoyml, [Symbol])
--- !ruby/struct
foo: bar
@@ -152,7 +152,7 @@ module Psych
end
def test_safe_load_raises_on_bad_input
- assert_raises(Psych::SyntaxError) { Psych.safe_load("--- `") }
+ assert_raise(Psych::SyntaxError) { Psych.safe_load("--- `") }
end
private
diff --git a/test/psych/test_scalar_scanner.rb b/test/psych/test_scalar_scanner.rb
index d12a905330..1bd6488e75 100644
--- a/test/psych/test_scalar_scanner.rb
+++ b/test/psych/test_scalar_scanner.rb
@@ -120,6 +120,7 @@ module Psych
assert_equal 123_456_789, ss.tokenize('123_456_789')
assert_equal 123_456_789, ss.tokenize('123,456,789')
assert_equal 123_456_789, ss.tokenize('1_2,3,4_5,6_789')
+ assert_equal 123_456_789, ss.tokenize('1_2,3,4_5,6_789_')
assert_equal 0b010101010, ss.tokenize('0b010101010')
assert_equal 0b010101010, ss.tokenize('0b0,1_0,1_,0,1_01,0')
@@ -129,6 +130,8 @@ module Psych
assert_equal 0x123456789abcdef, ss.tokenize('0x123456789abcdef')
assert_equal 0x123456789abcdef, ss.tokenize('0x12_,34,_56,_789abcdef')
+ assert_equal 0x123456789abcdef, ss.tokenize('0x_12_,34,_56,_789abcdef')
+ assert_equal 0x123456789abcdef, ss.tokenize('0x12_,34,_56,_789abcdef__')
end
end
end
diff --git a/test/psych/test_serialize_subclasses.rb b/test/psych/test_serialize_subclasses.rb
index 8e1d0d354d..344c79b3ef 100644
--- a/test/psych/test_serialize_subclasses.rb
+++ b/test/psych/test_serialize_subclasses.rb
@@ -17,7 +17,7 @@ module Psych
def test_some_object
so = SomeObject.new('foo', [1,2,3])
- assert_equal so, Psych.load(Psych.dump(so))
+ assert_equal so, Psych.unsafe_load(Psych.dump(so))
end
class StructSubclass < Struct.new(:foo)
@@ -33,7 +33,7 @@ module Psych
def test_struct_subclass
so = StructSubclass.new('foo', [1,2,3])
- assert_equal so, Psych.load(Psych.dump(so))
+ assert_equal so, Psych.unsafe_load(Psych.dump(so))
end
end
end
diff --git a/test/psych/test_set.rb b/test/psych/test_set.rb
index 5690957eff..87944d839e 100644
--- a/test/psych/test_set.rb
+++ b/test/psych/test_set.rb
@@ -21,7 +21,7 @@ module Psych
###
# FIXME: Syck should also support !!set as shorthand
def test_load_from_yaml
- loaded = Psych.load(<<-eoyml)
+ loaded = Psych.unsafe_load(<<-eoyml)
--- !set
foo: bar
bar: baz
@@ -30,11 +30,11 @@ bar: baz
end
def test_loaded_class
- assert_instance_of(Psych::Set, Psych.load(Psych.dump(@set)))
+ assert_instance_of(Psych::Set, Psych.unsafe_load(Psych.dump(@set)))
end
def test_set_shorthand
- loaded = Psych.load(<<-eoyml)
+ loaded = Psych.unsafe_load(<<-eoyml)
--- !!set
foo: bar
bar: baz
diff --git a/test/psych/test_string.rb b/test/psych/test_string.rb
index 973f38b9c2..20ab79c05a 100644
--- a/test/psych/test_string.rb
+++ b/test/psych/test_string.rb
@@ -104,7 +104,7 @@ module Psych
end
def test_string_subclass_with_anchor
- y = Psych.load <<-eoyml
+ y = Psych.unsafe_load <<-eoyml
---
body:
string: &70121654388580 !ruby/string
@@ -116,7 +116,7 @@ body:
end
def test_self_referential_string
- y = Psych.load <<-eoyml
+ y = Psych.unsafe_load <<-eoyml
---
string: &70121654388580 !ruby/string
str: ! 'foo'
@@ -129,32 +129,32 @@ string: &70121654388580 !ruby/string
end
def test_another_subclass_with_attributes
- y = Psych.load Psych.dump Y.new("foo").tap {|o| o.val = 1}
+ y = Psych.unsafe_load Psych.dump Y.new("foo").tap {|o| o.val = 1}
assert_equal "foo", y
assert_equal Y, y.class
assert_equal 1, y.val
end
def test_backwards_with_syck
- x = Psych.load "--- !str:#{X.name} foo\n\n"
+ x = Psych.unsafe_load "--- !str:#{X.name} foo\n\n"
assert_equal X, x.class
assert_equal 'foo', x
end
def test_empty_subclass
assert_match "!ruby/string:#{X}", Psych.dump(X.new)
- x = Psych.load Psych.dump X.new
+ x = Psych.unsafe_load Psych.dump X.new
assert_equal X, x.class
end
def test_empty_character_subclass
assert_match "!ruby/string:#{Z}", Psych.dump(Z.new)
- x = Psych.load Psych.dump Z.new
+ x = Psych.unsafe_load Psych.dump Z.new
assert_equal Z, x.class
end
def test_subclass_with_attributes
- y = Psych.load Psych.dump Y.new.tap {|o| o.val = 1}
+ y = Psych.unsafe_load Psych.dump Y.new.tap {|o| o.val = 1}
assert_equal Y, y.class
assert_equal 1, y.val
end
diff --git a/test/psych/test_struct.rb b/test/psych/test_struct.rb
index 721df44216..1479798b1f 100644
--- a/test/psych/test_struct.rb
+++ b/test/psych/test_struct.rb
@@ -22,7 +22,7 @@ module Psych
ss = StructSubclass.new(nil, 'foo')
ss.foo = ss
- loaded = Psych.load(Psych.dump(ss))
+ loaded = Psych.unsafe_load(Psych.dump(ss))
assert_instance_of(StructSubclass, loaded.foo)
assert_equal(ss, loaded)
@@ -30,14 +30,14 @@ module Psych
def test_roundtrip
thing = PsychStructWithIvar.new('bar')
- struct = Psych.load(Psych.dump(thing))
+ struct = Psych.unsafe_load(Psych.dump(thing))
assert_equal 'hello', struct.bar
assert_equal 'bar', struct.foo
end
def test_load
- obj = Psych.load(<<-eoyml)
+ obj = Psych.unsafe_load(<<-eoyml)
--- !ruby/struct:PsychStructWithIvar
:foo: bar
:@bar: hello
diff --git a/test/psych/test_yaml.rb b/test/psych/test_yaml.rb
index 0dfd60f894..e12b9769fe 100644
--- a/test/psych/test_yaml.rb
+++ b/test/psych/test_yaml.rb
@@ -17,7 +17,7 @@ class Psych_Unit_Tests < Psych::TestCase
end
def test_y_method
- assert_raises(NoMethodError) do
+ assert_raise(NoMethodError) do
OpenStruct.new.y 1
end
end
@@ -573,7 +573,7 @@ EOY
end
def test_spec_root_mapping
- y = Psych::load( <<EOY
+ y = Psych::unsafe_load( <<EOY
# This stream is an example of a top-level mapping.
invoice : 34843
date : 2001-01-23
@@ -1034,6 +1034,7 @@ EOY
end
def test_ruby_struct
+ Struct.send(:remove_const, :MyBookStruct) if Struct.const_defined?(:MyBookStruct)
# Ruby structures
book_struct = Struct::new( "MyBookStruct", :author, :title, :year, :isbn )
assert_to_yaml(
@@ -1076,7 +1077,7 @@ EOY
# Read Psych dumped by the ruby 1.8.3.
assert_to_yaml( Rational(1, 2), "!ruby/object:Rational 1/2\n" )
- assert_raises( ArgumentError ) { Psych.load("!ruby/object:Rational INVALID/RATIONAL\n") }
+ assert_raise( ArgumentError ) { Psych.unsafe_load("!ruby/object:Rational INVALID/RATIONAL\n") }
end
def test_ruby_complex
@@ -1088,7 +1089,7 @@ EOY
# Read Psych dumped by the ruby 1.8.3.
assert_to_yaml( Complex(3, 4), "!ruby/object:Complex 3+4i\n" )
- assert_raises( ArgumentError ) { Psych.load("!ruby/object:Complex INVALID+COMPLEXi\n") }
+ assert_raise( ArgumentError ) { Psych.unsafe_load("!ruby/object:Complex INVALID+COMPLEXi\n") }
end
def test_emitting_indicators
@@ -1208,7 +1209,7 @@ EOY
def test_circular_references
a = []; a[0] = a; a[1] = a
inspect_str = "[[...], [...]]"
- assert_equal( inspect_str, Psych::load(Psych.dump(a)).inspect )
+ assert_equal( inspect_str, Psych::unsafe_load(Psych.dump(a)).inspect )
end
#
@@ -1263,11 +1264,11 @@ EOY
end
def test_date_out_of_range
- Psych::load('1900-01-01T00:00:00+00:00')
+ Psych::unsafe_load('1900-01-01T00:00:00+00:00')
end
def test_normal_exit
- Psych.load("2000-01-01 00:00:00.#{"0"*1000} +00:00\n")
+ Psych.unsafe_load("2000-01-01 00:00:00.#{"0"*1000} +00:00\n")
# '[ruby-core:13735]'
end
diff --git a/test/psych/test_yaml_special_cases.rb b/test/psych/test_yaml_special_cases.rb
index 4501704030..205457bcae 100644
--- a/test/psych/test_yaml_special_cases.rb
+++ b/test/psych/test_yaml_special_cases.rb
@@ -13,7 +13,7 @@ module Psych
def test_empty_string
s = ""
- assert_equal false, Psych.load(s)
+ assert_equal false, Psych.unsafe_load(s)
assert_equal [], Psych.load_stream(s)
assert_equal false, Psych.parse(s)
assert_equal [], Psych.parse_stream(s).transform
@@ -58,8 +58,8 @@ module Psych
def test_NaN
s = ".NaN"
- assert Float::NAN, Psych.load(s).nan?
- assert [Float::NAN], Psych.load_stream(s).first.nan?
+ assert Psych.load(s).nan?
+ assert Psych.load_stream(s).first.nan?
assert Psych.parse(s).transform.nan?
assert Psych.parse_stream(s).transform.first.nan?
assert Psych.safe_load(s).nan?
diff --git a/test/psych/test_yamlstore.rb b/test/psych/test_yamlstore.rb
index d1e927cefe..1a1be3700e 100644
--- a/test/psych/test_yamlstore.rb
+++ b/test/psych/test_yamlstore.rb
@@ -4,7 +4,22 @@ require 'yaml/store'
require 'tmpdir'
module Psych
- Psych::Store = YAML::Store unless defined?(Psych::Store)
+ class YAML::Store
+ alias :old_load :load
+
+ def load(content)
+ table = YAML.load(content, fallback: false)
+ if table == false
+ {}
+ else
+ table
+ end
+ end
+ end
+
+ unless defined?(Psych::Store)
+ Psych::Store = YAML::Store
+ end
class YAMLStoreTest < TestCase
def setup
@@ -24,61 +39,61 @@ module Psych
def test_opening_new_file_in_readonly_mode_should_result_in_empty_values
@yamlstore.transaction(true) do
- assert_nil @yamlstore[:foo]
- assert_nil @yamlstore[:bar]
+ assert_nil @yamlstore["foo"]
+ assert_nil @yamlstore["bar"]
end
end
def test_opening_new_file_in_readwrite_mode_should_result_in_empty_values
@yamlstore.transaction do
- assert_nil @yamlstore[:foo]
- assert_nil @yamlstore[:bar]
+ assert_nil @yamlstore["foo"]
+ assert_nil @yamlstore["bar"]
end
end
def test_data_should_be_loaded_correctly_when_in_readonly_mode
@yamlstore.transaction do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
end
@yamlstore.transaction(true) do
- assert_equal "bar", @yamlstore[:foo]
+ assert_equal "bar", @yamlstore["foo"]
end
end
def test_data_should_be_loaded_correctly_when_in_readwrite_mode
@yamlstore.transaction do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
end
@yamlstore.transaction do
- assert_equal "bar", @yamlstore[:foo]
+ assert_equal "bar", @yamlstore["foo"]
end
end
def test_changes_after_commit_are_discarded
@yamlstore.transaction do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
@yamlstore.commit
- @yamlstore[:foo] = "baz"
+ @yamlstore["foo"] = "baz"
end
@yamlstore.transaction(true) do
- assert_equal "bar", @yamlstore[:foo]
+ assert_equal "bar", @yamlstore["foo"]
end
end
def test_changes_are_not_written_on_abort
@yamlstore.transaction do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
@yamlstore.abort
end
@yamlstore.transaction(true) do
- assert_nil @yamlstore[:foo]
+ assert_nil @yamlstore["foo"]
end
end
def test_writing_inside_readonly_transaction_raises_error
- assert_raises(PStore::Error) do
+ assert_raise(PStore::Error) do
@yamlstore.transaction(true) do
- @yamlstore[:foo] = "bar"
+ @yamlstore["foo"] = "bar"
end
end
end
diff --git a/test/psych/visitors/test_to_ruby.rb b/test/psych/visitors/test_to_ruby.rb
index f342bf0a1a..3d4608b903 100644
--- a/test/psych/visitors/test_to_ruby.rb
+++ b/test/psych/visitors/test_to_ruby.rb
@@ -20,12 +20,13 @@ module Psych
end
def test_tz_00_00_loads_without_error
- assert Psych.load('1900-01-01T00:00:00+00:00')
+ assert Psych.unsafe_load('1900-01-01T00:00:00+00:00')
end
def test_legacy_struct
+ Struct.send(:remove_const, :AWESOME) if Struct.const_defined?(:AWESOME)
foo = Struct.new('AWESOME', :bar)
- assert_equal foo.new('baz'), Psych.load(<<-eoyml)
+ assert_equal foo.new('baz'), Psych.unsafe_load(<<-eoyml)
!ruby/struct:AWESOME
bar: baz
eoyml
diff --git a/test/psych/visitors/test_yaml_tree.rb b/test/psych/visitors/test_yaml_tree.rb
index 69885ee9c6..6a9dbc1ec3 100644
--- a/test/psych/visitors/test_yaml_tree.rb
+++ b/test/psych/visitors/test_yaml_tree.rb
@@ -62,19 +62,19 @@ module Psych
def test_struct_anon
s = Struct.new(:foo).new('bar')
- obj = Psych.load(Psych.dump(s))
+ obj = Psych.unsafe_load(Psych.dump(s))
assert_equal s.foo, obj.foo
end
def test_override_method
s = Struct.new(:method).new('override')
- obj = Psych.load(Psych.dump(s))
+ obj = Psych.unsafe_load(Psych.dump(s))
assert_equal s.method, obj.method
end
def test_exception
ex = Exception.new 'foo'
- loaded = Psych.load(Psych.dump(ex))
+ loaded = Psych.unsafe_load(Psych.dump(ex))
assert_equal ex.message, loaded.message
assert_equal ex.class, loaded.class
@@ -88,7 +88,7 @@ module Psych
def test_time
t = Time.now
- assert_equal t, Psych.load(Psych.dump(t))
+ assert_equal t, Psych.unsafe_load(Psych.dump(t))
end
def test_date
@@ -127,11 +127,11 @@ module Psych
end
def test_anon_class
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
@v.accept Class.new
end
- assert_raises(TypeError) do
+ assert_raise(TypeError) do
Psych.dump(Class.new)
end
end
diff --git a/test/racc/assets/ifelse.y b/test/racc/assets/ifelse.y
new file mode 100644
index 0000000000..18dbe4b1a7
--- /dev/null
+++ b/test/racc/assets/ifelse.y
@@ -0,0 +1,14 @@
+class C::Parser
+token tSOMETHING
+rule
+ statement
+ : tSOMETHING
+ | 'if' statement 'then' statement
+ | 'if' statement 'then' statement 'else' statement
+ ;
+
+ dummy
+ : tSOMETHING '+' tSOMETHING
+ | tSOMETHING '-' tSOMETHING
+ ;
+
diff --git a/test/racc/helper.rb b/test/racc/helper.rb
index 2862a7903e..146beb5a73 100644
--- a/test/racc/helper.rb
+++ b/test/racc/helper.rb
@@ -86,11 +86,11 @@ module Racc
end
def assert_output_unchanged(asset)
- # racc generates the difference results in GitHub Actions
- omit unless RUBY_PLATFORM =~ /darwin/
-
file = File.basename(asset, '.y')
+ # Code to re-generate the expectation files
+ # File.write("#{REGRESS_DIR}/#{file}", File.read("#{@TAB_DIR}/#{file}"))
+
expected = File.read("#{REGRESS_DIR}/#{file}")
actual = File.read("#{@TAB_DIR}/#{file}")
result = (strip_version(expected) == strip_version(actual))
diff --git a/test/racc/regress/cadenza b/test/racc/regress/cadenza
index b8f940465a..dafce3c9f3 100644
--- a/test/racc/regress/cadenza
+++ b/test/racc/regress/cadenza
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -17,81 +17,81 @@ module_eval(<<'...end cadenza.y/module_eval...', 'cadenza.y', 171)
##### State transition tables begin ###
racc_action_table = [
- 37, 89, 90, 20, 21, 22, 23, 24, 121, 3,
- 89, 4, 72, 37, 71, 3, 68, 39, 3, 29,
- 43, 37, 65, 66, 33, 9, 34, 110, 74, 50,
- 35, 9, 37, 36, 9, 122, 38, 33, 128, 34,
- 77, 78, 79, 35, 89, 33, 36, 34, 37, 38,
- 3, 35, 46, 17, 36, 85, 33, 38, 34, 37,
- 76, 103, 35, 75, 83, 36, 9, 131, 38, 54,
- 55, 3, 33, 4, 34, 124, 78, 79, 35, 65,
- 66, 36, 67, 33, 38, 34, 125, 9, 109, 35,
- 56, 57, 36, 54, 55, 38, 20, 21, 22, 23,
- 24, 20, 21, 22, 23, 24, 20, 21, 22, 23,
- 24, 108, 29, 65, 66, 54, 55, 29, 56, 57,
- 111, 107, 29, 20, 21, 22, 23, 24, 20, 21,
- 22, 23, 24, 20, 21, 22, 23, 24, 112, 29,
- 3, 113, 116, 114, 29, 115, 3, 103, 39, 29,
- 20, 21, 22, 23, 24, 120, 9, 20, 21, 22,
- 23, 24, 9, 3, nil, 4, 29, 3, 3, 43,
- 46, nil, 3, 29, 87, 3, 3, 4, 116, 9,
- 56, 57, nil, 9, 9, 56, 57, 3, 9, 116,
- nil, 9, 9, 20, 21, 22, 23, 24, 20, 21,
- 22, 23, 24, 9, 65, 66, 56, 57, nil, 29,
- 56, 57, 106, nil, 29, 58, 59, 60, 61, 62,
- 63, 58, 59, 60, 61, 62, 63, 20, 21, 22,
- 23, 24, 20, 21, 22, 23, 24, 20, 21, 22,
- 23, 24, 20, 21, 22, 23, 24, 20, 21, 22,
- 23, 24, 20, 21, 22, 23, 24, 20, 21, 22,
- 23, 24, 20, 21, 22, 23, 24, 20, 21, 22,
- 23, 24, 20, 21, 22, 23, 24, 20, 21, 22,
- 23, 24, 56, 57, 65, 66 ]
+ 37, 89, 65, 66, 20, 21, 22, 23, 24, 17,
+ 106, 37, 3, 76, 4, 3, 75, 4, 50, 37,
+ 29, 68, 65, 66, 33, 67, 34, 110, 9, 74,
+ 35, 9, 37, 36, 71, 33, 38, 34, 77, 78,
+ 79, 35, 72, 33, 36, 34, 37, 38, 3, 35,
+ 39, 83, 36, 54, 55, 38, 33, 89, 34, 37,
+ 90, 3, 35, 43, 9, 36, 85, 103, 38, 108,
+ 33, 109, 34, 56, 57, 111, 35, 9, 3, 36,
+ 46, 122, 38, 33, 112, 34, 113, 78, 79, 35,
+ 114, 3, 36, 4, 9, 38, 20, 21, 22, 23,
+ 24, 20, 21, 22, 23, 24, 115, 9, 65, 66,
+ 65, 66, 29, 54, 55, 120, 107, 29, 20, 21,
+ 22, 23, 24, 20, 21, 22, 23, 24, 20, 21,
+ 22, 23, 24, 3, 29, 39, 3, 121, 4, 29,
+ 3, 3, 43, 46, 29, 3, 124, 87, 125, 9,
+ 54, 55, 9, 56, 57, 128, 9, 9, 3, 103,
+ 116, 9, 20, 21, 22, 23, 24, 20, 21, 22,
+ 23, 24, 131, 3, 9, 116, 56, 57, 29, 3,
+ 89, 116, nil, 29, 20, 21, 22, 23, 24, 9,
+ 20, 21, 22, 23, 24, 9, 56, 57, 56, 57,
+ 29, 20, 21, 22, 23, 24, 29, 58, 59, 60,
+ 61, 62, 63, 56, 57, 56, 57, 29, 58, 59,
+ 60, 61, 62, 63, 20, 21, 22, 23, 24, 20,
+ 21, 22, 23, 24, 20, 21, 22, 23, 24, 20,
+ 21, 22, 23, 24, 20, 21, 22, 23, 24, 20,
+ 21, 22, 23, 24, 20, 21, 22, 23, 24, 20,
+ 21, 22, 23, 24, 20, 21, 22, 23, 24, 20,
+ 21, 22, 23, 24, 20, 21, 22, 23, 24, 65,
+ 66 ]
racc_action_check = [
- 87, 73, 53, 37, 37, 37, 37, 37, 85, 2,
- 52, 2, 36, 39, 35, 5, 32, 5, 6, 37,
- 6, 46, 51, 51, 87, 2, 87, 73, 37, 17,
- 87, 5, 43, 87, 6, 87, 87, 39, 122, 39,
- 39, 39, 39, 39, 129, 46, 39, 46, 116, 39,
- 7, 46, 7, 1, 46, 46, 43, 46, 43, 4,
- 38, 125, 43, 38, 43, 43, 7, 126, 43, 26,
- 26, 8, 116, 8, 116, 103, 116, 116, 116, 31,
- 31, 116, 31, 4, 116, 4, 105, 8, 72, 4,
- 27, 27, 4, 93, 93, 4, 24, 24, 24, 24,
- 24, 33, 33, 33, 33, 33, 34, 34, 34, 34,
- 34, 71, 24, 70, 70, 94, 94, 33, 95, 95,
- 75, 70, 34, 108, 108, 108, 108, 108, 89, 89,
- 89, 89, 89, 124, 124, 124, 124, 124, 76, 108,
- 118, 77, 118, 78, 89, 79, 41, 67, 41, 124,
- 3, 3, 3, 3, 3, 83, 118, 20, 20, 20,
- 20, 20, 41, 42, nil, 42, 3, 45, 48, 45,
- 48, nil, 49, 20, 49, 0, 82, 0, 82, 42,
- 96, 96, nil, 45, 48, 97, 97, 81, 49, 81,
- nil, 0, 82, 65, 65, 65, 65, 65, 66, 66,
- 66, 66, 66, 81, 69, 69, 98, 98, nil, 65,
- 99, 99, 69, nil, 66, 28, 28, 28, 28, 28,
- 28, 64, 64, 64, 64, 64, 64, 57, 57, 57,
- 57, 57, 29, 29, 29, 29, 29, 58, 58, 58,
- 58, 58, 59, 59, 59, 59, 59, 63, 63, 63,
- 63, 63, 54, 54, 54, 54, 54, 55, 55, 55,
- 55, 55, 56, 56, 56, 56, 56, 61, 61, 61,
- 61, 61, 62, 62, 62, 62, 62, 60, 60, 60,
- 60, 60, 100, 100, 123, 123 ]
+ 4, 73, 69, 69, 37, 37, 37, 37, 37, 1,
+ 69, 39, 0, 38, 0, 2, 38, 2, 17, 43,
+ 37, 32, 31, 31, 4, 31, 4, 73, 0, 37,
+ 4, 2, 46, 4, 35, 39, 4, 39, 39, 39,
+ 39, 39, 36, 43, 39, 43, 87, 39, 5, 43,
+ 5, 43, 43, 26, 26, 43, 46, 52, 46, 116,
+ 53, 6, 46, 6, 5, 46, 46, 67, 46, 71,
+ 87, 72, 87, 27, 27, 75, 87, 6, 7, 87,
+ 7, 87, 87, 116, 76, 116, 77, 116, 116, 116,
+ 78, 8, 116, 8, 7, 116, 3, 3, 3, 3,
+ 3, 20, 20, 20, 20, 20, 79, 8, 70, 70,
+ 51, 51, 3, 93, 93, 83, 70, 20, 24, 24,
+ 24, 24, 24, 33, 33, 33, 33, 33, 34, 34,
+ 34, 34, 34, 41, 24, 41, 42, 85, 42, 33,
+ 45, 48, 45, 48, 34, 49, 103, 49, 105, 41,
+ 94, 94, 42, 95, 95, 122, 45, 48, 81, 125,
+ 81, 49, 65, 65, 65, 65, 65, 66, 66, 66,
+ 66, 66, 126, 82, 81, 82, 96, 96, 65, 118,
+ 129, 118, nil, 66, 89, 89, 89, 89, 89, 82,
+ 108, 108, 108, 108, 108, 118, 97, 97, 98, 98,
+ 89, 124, 124, 124, 124, 124, 108, 28, 28, 28,
+ 28, 28, 28, 99, 99, 100, 100, 124, 64, 64,
+ 64, 64, 64, 64, 29, 29, 29, 29, 29, 54,
+ 54, 54, 54, 54, 55, 55, 55, 55, 55, 56,
+ 56, 56, 56, 56, 57, 57, 57, 57, 57, 58,
+ 58, 58, 58, 58, 59, 59, 59, 59, 59, 60,
+ 60, 60, 60, 60, 61, 61, 61, 61, 61, 62,
+ 62, 62, 62, 62, 63, 63, 63, 63, 63, 123,
+ 123 ]
racc_action_pointer = [
- 151, 53, -15, 147, 56, -9, -6, 26, 47, nil,
- nil, nil, nil, nil, nil, nil, nil, 29, nil, nil,
- 154, nil, nil, nil, 93, nil, 60, 79, 202, 229,
- nil, 59, -9, 98, 103, 11, 9, 0, 57, 10,
- nil, 122, 139, 29, nil, 143, 18, nil, 144, 148,
- nil, 2, 8, -6, 249, 254, 259, 224, 234, 239,
- 274, 264, 269, 244, 208, 190, 195, 144, nil, 184,
- 93, 77, 60, -1, nil, 92, 110, 113, 115, 117,
- nil, 163, 152, 127, nil, -20, nil, -3, nil, 125,
- nil, nil, nil, 84, 106, 107, 169, 174, 195, 199,
- 271, nil, nil, 53, nil, 63, nil, nil, 120, nil,
- nil, nil, nil, nil, nil, nil, 45, nil, 116, nil,
- nil, nil, 10, 264, 130, 58, 39, nil, nil, 42,
+ -12, 9, -9, 93, -3, 24, 37, 54, 67, nil,
+ nil, nil, nil, nil, nil, nil, nil, 18, nil, nil,
+ 98, nil, nil, nil, 115, nil, 44, 62, 194, 221,
+ nil, 2, -4, 120, 125, 31, 39, 1, 10, 8,
+ nil, 109, 112, 16, nil, 116, 29, nil, 117, 121,
+ nil, 90, 55, 52, 226, 231, 236, 241, 246, 251,
+ 256, 261, 266, 271, 205, 159, 164, 64, nil, -18,
+ 88, 35, 43, -1, nil, 47, 56, 58, 62, 78,
+ nil, 134, 149, 87, nil, 109, nil, 43, nil, 181,
+ nil, nil, nil, 104, 141, 142, 165, 185, 187, 202,
+ 204, nil, nil, 124, nil, 125, nil, nil, 187, nil,
+ nil, nil, nil, nil, nil, nil, 56, nil, 155, nil,
+ nil, nil, 127, 259, 198, 156, 144, nil, nil, 178,
nil, nil ]
racc_action_default = [
@@ -111,37 +111,37 @@ racc_action_default = [
-32, -46 ]
racc_goto_table = [
- 18, 40, 19, 32, 104, 51, 52, 105, 2, 88,
- 47, 101, 102, 41, 45, 48, 49, 44, 69, 70,
- 1, 42, 51, 73, 53, 95, 96, 97, 98, 99,
- 100, 91, 92, 93, 94, 64, nil, 80, nil, 18,
- nil, 19, nil, 18, nil, 19, 18, 18, 19, 19,
- 82, 86, nil, nil, nil, nil, 84, 81, nil, nil,
+ 19, 40, 18, 32, 104, 52, 51, 1, 2, 64,
+ 47, 91, 92, 41, 45, 48, 49, 44, 42, 69,
+ 70, 105, 73, 51, 53, 95, 96, 97, 98, 99,
+ 100, 93, 94, 101, 102, 88, nil, 80, nil, 19,
+ nil, 18, nil, 19, nil, 18, 19, 19, 18, 18,
+ 82, 86, nil, nil, 81, nil, 84, nil, nil, nil,
nil, nil, 130, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 123, nil, nil, 117, 119, nil,
- 18, nil, 19, nil, nil, nil, nil, nil, nil, 118,
+ nil, nil, nil, nil, nil, 123, nil, 117, 119, nil,
+ 19, nil, 18, nil, nil, nil, nil, nil, nil, 118,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 126, 51,
- 129, nil, nil, nil, 127, nil, 18, nil, 19 ]
+ nil, nil, nil, nil, nil, nil, nil, nil, 126, 129,
+ 51, nil, nil, nil, 127, nil, 19, nil, 18 ]
racc_goto_check = [
- 28, 16, 27, 6, 11, 4, 3, 12, 2, 25,
- 22, 10, 10, 2, 2, 2, 2, 19, 4, 4,
- 1, 15, 4, 3, 6, 8, 8, 8, 8, 8,
- 8, 5, 5, 7, 7, 9, nil, 16, nil, 28,
- nil, 27, nil, 28, nil, 27, 28, 28, 27, 27,
- 2, 22, nil, nil, nil, nil, 19, 15, nil, nil,
+ 27, 16, 28, 6, 11, 3, 4, 1, 2, 9,
+ 22, 5, 5, 2, 2, 2, 2, 19, 15, 4,
+ 4, 12, 3, 4, 6, 8, 8, 8, 8, 8,
+ 8, 7, 7, 10, 10, 25, nil, 16, nil, 27,
+ nil, 28, nil, 27, nil, 28, 27, 27, 28, 28,
+ 2, 22, nil, nil, 15, nil, 19, nil, nil, nil,
nil, nil, 11, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 4, nil, nil, 16, 16, nil,
- 28, nil, 27, nil, nil, nil, nil, nil, nil, 2,
+ nil, nil, nil, nil, nil, 4, nil, 16, 16, nil,
+ 27, nil, 28, nil, nil, nil, nil, nil, nil, 2,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 6, 4,
- 3, nil, nil, nil, 16, nil, 28, nil, 27 ]
+ nil, nil, nil, nil, nil, nil, nil, nil, 6, 3,
+ 4, nil, nil, nil, 16, nil, 27, nil, 28 ]
racc_goto_pointer = [
- nil, 20, 8, -14, -15, -23, 0, -23, -33, 6,
- -54, -63, -60, nil, nil, 16, -4, nil, nil, 11,
- nil, nil, 3, nil, nil, -40, nil, 0, -2 ]
+ nil, 7, 8, -15, -14, -43, 0, -25, -33, -20,
+ -32, -63, -46, nil, nil, 13, -4, nil, nil, 11,
+ nil, nil, 3, nil, nil, -14, nil, -2, 0 ]
racc_goto_default = [
nil, nil, nil, nil, 31, 25, nil, 26, 27, 28,
diff --git a/test/racc/regress/cast b/test/racc/regress/cast
index ede36bad79..1892c73e01 100644
--- a/test/racc/regress/cast
+++ b/test/racc/regress/cast
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -376,44 +376,42 @@ restrict return short signed sizeof static struct switch typedef union
##### State transition tables begin ###
clist = [
-'99,100,65,277,108,109,120,38,373,110,111,112,113,114,115,116,117,99',
-'100,65,48,108,109,120,312,424,110,111,112,113,114,115,116,117,43,293',
-'48,425,196,366,281,72,49,50,56,128,426,38,59,294,123,124,126,127,129',
-'130,131,132,312,290,372,281,128,49,38,386,416,123,124,126,127,129,130',
-'131,132,49,365,309,71,196,50,391,183,50,147,148,149,150,88,38,196,48',
-'185,38,88,281,184,50,442,196,50,147,148,149,150,99,100,65,277,108,109',
-'120,366,50,110,111,112,113,114,115,116,117,99,100,65,50,108,109,120',
-'50,49,110,111,112,113,114,115,116,117,88,88,48,249,250,72,281,241,242',
-'169,365,128,238,38,413,89,123,124,126,127,129,130,131,132,88,239,240',
-'196,128,50,38,349,84,123,124,126,127,129,130,131,132,49,71,83,440,288',
-'50,195,346,50,147,148,149,150,445,43,262,48,439,289,196,263,347,77,196',
-'428,50,147,148,149,150,99,100,65,50,108,109,120,196,50,110,111,112,113',
-'114,115,116,117,99,100,65,50,108,109,120,238,49,110,111,112,113,114',
-'115,116,117,227,238,315,239,240,245,246,247,248,243,244,128,283,38,239',
-'240,123,124,126,127,129,130,131,132,314,284,243,244,128,50,38,379,68',
-'123,124,126,127,129,130,131,132,34,35,36,196,69,308,49,307,50,147,148',
-'149,150,303,228,229,230,231,232,233,234,235,236,237,192,50,147,148,149',
-'150,99,100,65,296,108,109,120,243,244,110,111,112,113,114,115,116,117',
-'99,100,65,50,108,109,120,447,376,110,111,112,113,114,115,116,117,196',
-'196,387,353,313,273,245,246,247,248,355,128,388,38,196,274,123,124,126',
-'127,129,130,131,132,245,246,247,248,128,285,38,454,437,123,124,126,127',
-'129,130,131,132,196,196,357,427,450,377,433,375,50,147,148,149,150,196',
-'196,196,196,196,34,35,36,241,242,50,49,50,147,148,149,150,99,100,65',
-'61,108,109,120,241,242,110,111,112,113,114,115,116,117,99,100,65,275',
-'108,109,120,243,244,110,111,112,113,114,115,116,117,249,250,243,244',
-'255,256,272,271,268,67,254,128,378,38,253,252,123,124,126,127,129,130',
-'131,132,251,389,390,251,128,252,38,253,254,123,124,126,127,129,130,131',
-'132,395,396,397,398,399,209,405,406,50,147,148,149,150,206,205,202,199',
-'198,197,192,191,384,384,187,88,50,147,148,149,150,99,100,65,103,108',
-'109,120,423,,110,111,112,113,114,115,116,117,,,10,11,12,13,14,15,16',
-'17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,,,128,,38,,,123,124',
-'126,127,129,130,131,132,99,100,65,,108,109,120,,,110,111,112,113,114',
-'115,116,117,,,,,,,,,50,147,148,149,150,,,,,,178,,,,,,,48,,,128,,38,',
-',123,124,126,127,129,130,131,132,99,100,65,,108,109,120,,,110,111,112',
-'113,114,115,116,117,,,,,,,49,,50,147,148,149,150,,,,,,178,,,,,,,48,',
-',128,,38,,,123,124,126,127,129,130,131,132,99,100,65,50,108,109,120',
-',,110,111,112,113,114,115,116,117,,,,,,,49,,50,147,148,149,150,,,,,',
-',,,,,,,,,,128,,38,,,123,124,126,127,129,130,131,132,99,100,65,50,108',
+'99,100,65,103,108,109,120,312,61,110,111,112,113,114,115,116,117,77',
+'48,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35',
+'36,37,72,281,128,49,38,196,391,123,124,126,127,129,130,131,132,183,277',
+'83,273,84,238,288,293,88,196,72,290,38,274,184,372,373,386,239,240,289',
+'294,71,241,242,50,147,148,149,150,99,100,65,193,108,109,120,50,281,110',
+'111,112,113,114,115,116,117,71,50,10,11,12,13,14,15,16,17,18,19,20,21',
+'22,23,24,25,26,31,32,33,34,35,36,37,56,366,128,89,38,50,169,123,124',
+'126,127,129,130,131,132,99,100,65,88,108,109,120,88,88,110,111,112,113',
+'114,115,116,117,346,349,238,59,68,48,365,195,50,147,148,149,150,38,347',
+'239,240,69,178,283,196,312,366,243,244,48,262,88,128,185,38,263,284',
+'123,124,126,127,129,130,131,132,99,100,65,49,108,109,120,38,50,110,111',
+'112,113,114,115,116,117,281,365,309,440,249,250,49,238,50,147,148,149',
+'150,313,379,196,227,439,178,413,239,240,88,196,50,48,50,196,128,187',
+'38,191,196,123,124,126,127,129,130,131,132,99,100,65,50,108,109,120',
+'416,428,110,111,112,113,114,115,116,117,255,256,192,196,196,197,49,198',
+'50,147,148,149,150,228,229,230,231,232,233,234,235,236,237,43,199,48',
+'241,242,128,202,38,241,242,123,124,126,127,129,130,131,132,99,100,65',
+'50,108,109,120,375,376,110,111,112,113,114,115,116,117,196,196,205,377',
+'387,427,49,433,50,147,148,149,150,196,388,196,437,196,206,445,209,447',
+'450,43,251,48,196,252,128,196,38,196,196,123,124,126,127,129,130,131',
+'132,99,100,65,50,108,109,120,454,253,110,111,112,113,114,115,116,117',
+'196,34,35,36,243,244,49,49,50,147,148,149,150,34,35,36,243,244,254,49',
+'245,246,247,248,67,48,243,244,128,268,38,243,244,123,124,126,127,129',
+'130,131,132,99,100,65,50,108,109,120,249,250,110,111,112,113,114,115',
+'116,117,245,246,247,248,271,272,49,275,50,147,148,149,150,245,246,247',
+'248,285,296,192,303,307,308,314,315,277,50,50,128,50,38,353,355,123',
+'124,126,127,129,130,131,132,99,100,65,50,108,109,120,357,50,110,111',
+'112,113,114,115,116,117,378,389,390,251,281,252,49,253,50,147,148,149',
+'150,254,395,396,397,398,399,405,406,384,384,423,424,425,426,442,128',
+',38,,,123,124,126,127,129,130,131,132,99,100,65,50,108,109,120,,,110',
+'111,112,113,114,115,116,117,,,,,,,,,50,147,148,149,150,,,,,,,,,,,,,',
+',,128,,38,,,123,124,126,127,129,130,131,132,99,100,65,,108,109,120,',
+',110,111,112,113,114,115,116,117,,,,,,,,,50,147,148,149,150,,,,,,,,',
+',,,,,,,128,,38,,,123,124,126,127,129,130,131,132,99,100,65,,108,109',
+'120,,,110,111,112,113,114,115,116,117,,,,,,,,,50,147,148,149,150,,,',
+',,,,,,,,,,,,128,,38,,,123,124,126,127,129,130,131,132,99,100,65,,108',
'109,120,,,110,111,112,113,114,115,116,117,,,,,,,,,50,147,148,149,150',
',,,,,,,,,,,,,,,128,,38,,,123,124,126,127,129,130,131,132,99,100,65,',
'108,109,120,,,110,111,112,113,114,115,116,117,,,,,,,,,50,147,148,149',
@@ -425,63 +423,71 @@ clist = [
'99,100,65,,108,109,120,,,110,111,112,113,114,115,116,117,,,,,,,,,50',
'147,148,149,150,,,,,,,,,,,,,,,,128,,38,,,123,124,126,127,129,130,131',
'132,99,100,65,,108,109,120,,,110,111,112,113,114,115,116,117,,,,,,,',
-',50,147,148,149,150,,,,,,,,,,,,,,,,128,,38,,120,123,124,126,127,129',
+',50,147,148,149,150,,,,,,,,,,,,,,,,128,,38,,,123,124,126,127,129,130',
+'131,132,99,100,65,,108,109,120,,,110,111,112,113,114,115,116,117,,,',
+',,,,,50,147,148,149,150,,,,,,,,,,,,,,,,128,,38,,,123,124,126,127,129',
'130,131,132,99,100,65,,108,109,120,,,110,111,112,113,114,115,116,117',
-',,,,215,,,,50,147,148,149,150,128,,,,,123,124,126,127,129,130,131,132',
-',,128,,38,,,123,124,126,127,129,130,131,132,214,,,,,216,217,218,219',
-',50,147,148,149,150,,,,,,,,,,,50,147,148,149,150,99,100,65,193,108,109',
-'120,,,110,111,112,113,114,115,116,117,,,10,11,12,13,14,15,16,17,18,19',
-'20,21,22,23,24,25,26,31,32,33,34,35,36,37,,,128,,38,,,123,124,126,127',
+',,,,,,,,50,147,148,149,150,,,,,,,,,,,,,,,,128,,38,,,123,124,126,127',
'129,130,131,132,99,100,65,,108,109,120,,,110,111,112,113,114,115,116',
-'117,154,453,,,120,,,,50,147,148,149,150,,,,,,,,,,,,,,,,128,,38,,,123',
-'124,126,127,129,130,131,132,262,,128,,,263,,123,124,126,127,129,130',
-'131,132,,,,,,,,,,,50,147,148,149,150,65,,,,120,,,,,,50,147,148,149,150',
-'154,,,,120,,,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,',
-',,128,,38,,,123,124,126,127,129,130,131,132,,,128,,,,,123,124,126,127',
-'129,130,131,132,154,,,,120,,,,,,50,147,148,149,150,384,,,,120,,,,,,50',
-'147,148,149,150,,,,,,,,,,,,,,128,,,,,123,124,126,127,129,130,131,132',
-',,128,,,,,123,124,126,127,129,130,131,132,154,,,,120,,,,,,50,147,148',
-'149,150,154,392,,,120,,,,,,50,147,148,149,150,,,,,,,,,,,,262,,128,,',
-'263,,123,124,126,127,129,130,131,132,262,,128,,,263,,123,124,126,127',
-'129,130,131,132,,,,,,,,,,,50,147,148,149,150,65,,,,120,,,,,,50,147,148',
-'149,150,154,,,,120,,,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34',
-'35,36,,,,128,,38,,,123,124,126,127,129,130,131,132,,,128,,,,,123,124',
-'126,127,129,130,131,132,154,,,,120,,,,,,50,147,148,149,150,,,,,,,,,',
-',50,147,148,149,150,,,,,,,,,,,,262,,128,,,263,,123,124,126,127,129,130',
-'131,132,,,,,,,,,65,,,,120,,,,,,,,,,,,,50,147,148,149,150,15,16,17,18',
-'19,20,21,22,23,24,25,26,31,32,33,34,35,36,,,,128,,38,,,123,124,126,127',
-'129,130,131,132,381,,120,,,,,,,,,,,383,,120,,,,,,,,,,50,147,148,149',
-'150,,,,,,,,,,,,128,,,,,123,124,126,127,129,130,131,132,128,,,,,123,124',
-'126,127,129,130,131,132,,,,,,,,,,,,,50,147,148,149,150,305,,120,,,,',
-',50,147,148,149,150,,,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25',
-'26,31,32,33,34,35,36,37,,,128,,38,,,123,124,126,127,129,130,131,132',
-'208,,120,,,,,,,,,,,412,,120,,,,,,,,,,50,147,148,149,150,,,,,,,,,,,,128',
+'117,,,,,,,,,50,147,148,149,150,,,,,,,,,,,,,,,,128,,38,,,123,124,126',
+'127,129,130,131,132,99,100,65,,108,109,120,,,110,111,112,113,114,115',
+'116,117,,,,,,,,,50,147,148,149,150,,,,,,,,,,,,,,,,128,,38,,,123,124',
+'126,127,129,130,131,132,99,100,65,,108,109,120,,,110,111,112,113,114',
+'115,116,117,154,,,,120,,,,50,147,148,149,150,,,,,,,215,,,,,,,,,128,',
+'38,,,123,124,126,127,129,130,131,132,,,128,,,,,123,124,126,127,129,130',
+'131,132,214,,,,,216,217,218,219,,50,147,148,149,150,65,,,,120,,,,,,50',
+'147,148,149,150,154,,,,120,,,15,16,17,18,19,20,21,22,23,24,25,26,31',
+'32,33,34,35,36,,,,128,,38,,,123,124,126,127,129,130,131,132,262,,128',
+',,263,,123,124,126,127,129,130,131,132,,,,,,,,,,,50,147,148,149,150',
+'65,,,,120,,,,,,50,147,148,149,150,,,,,,,,15,16,17,18,19,20,21,22,23',
+'24,25,26,31,32,33,34,35,36,,,,128,,38,,,123,124,126,127,129,130,131',
+'132,,,,,,,,,65,,,,120,,,,,,,,,,,,,50,147,148,149,150,15,16,17,18,19',
+'20,21,22,23,24,25,26,31,32,33,34,35,36,,,,128,,38,,,123,124,126,127',
+'129,130,131,132,154,,,,120,,,,,,,,,384,,,,120,,,,,,,,50,147,148,149',
+'150,,,,,,,,,,,,,,128,,,,,123,124,126,127,129,130,131,132,128,,,,,123',
+'124,126,127,129,130,131,132,154,392,,,120,,,,,,,,50,147,148,149,150',
+'154,,,,120,,,,50,147,148,149,150,,,,,,,,,,,,262,,128,,,263,,123,124',
+'126,127,129,130,131,132,,,262,,128,,,263,,123,124,126,127,129,130,131',
+'132,154,,,,120,,,,50,147,148,149,150,,,154,453,,,120,,,,,,50,147,148',
+'149,150,,,,,,,,,,,,,,128,,,,,123,124,126,127,129,130,131,132,262,,128',
+',208,263,120,123,124,126,127,129,130,131,132,,,,,,,,,,,50,147,148,149',
+'150,,,,,,,,,,,50,147,148,149,150,128,,,,,123,124,126,127,129,130,131',
+'132,,,,,,,,,,,,,,,,305,,120,,,,,,,,50,147,148,149,150,10,11,12,13,14',
+'15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,,,128,,38,',
+',123,124,126,127,129,130,131,132,381,,120,,,,,,,,,,,383,,120,,,,,,,',
+',,50,147,148,149,150,,,,,,,,,,,,128,,,,,123,124,126,127,129,130,131',
+'132,128,,412,,120,123,124,126,127,129,130,131,132,,,,,,,,,,,,,50,147',
+'148,149,150,,,,,,,,,50,147,148,149,150,128,,,,,123,124,126,127,129,130',
+'131,132,120,,,,,,,,,,,,,120,,160,,,,,,,,,,50,147,148,149,150,,,,34,35',
+'36,,,159,161,,,,,123,124,126,127,129,130,131,132,128,,,,220,123,124',
+'126,127,129,130,131,132,,,,,220,,,,,,,,50,147,148,149,150,,,,,,,,,50',
+'147,148,149,150,128,,,,,123,124,126,127,129,130,131,132,128,,,,120,123',
+'124,126,127,129,130,131,132,,,,,224,,,,,,,,50,147,148,149,150,,,,,,',
+',,50,147,148,149,150,128,,,,,123,124,126,127,129,130,131,132,128,,,',
+',123,124,126,127,129,130,131,132,,,120,,,,,,,,,,50,147,148,149,150,266',
+',,,120,,,,50,147,148,149,150,,,,,,34,35,36,,,265,267,,,,120,123,124',
+'126,127,129,130,131,132,34,35,36,,,,128,,,,120,123,124,126,127,129,130',
+'131,132,,,,,,,50,147,148,149,150,128,,,,120,123,124,126,127,129,130',
+'131,132,,50,147,148,149,150,128,,,,120,123,124,126,127,129,130,131,132',
+',,,,,,50,147,148,149,150,128,,,,120,123,124,126,127,129,130,131,132',
+',50,147,148,149,150,128,,,,120,123,124,126,127,129,130,131,132,,,,,',
+',50,147,148,149,150,128,,,,120,123,124,126,127,129,130,131,132,,50,147',
+'148,149,150,128,,,,,123,124,126,127,129,130,131,132,,,,,,,50,147,148',
+'149,150,128,,,,,123,124,126,127,129,130,131,132,,50,147,148,149,150',
+',,,,,,120,318,,,,,,,,,,,,50,147,148,149,150,15,16,17,18,19,20,21,22',
+'23,24,25,26,31,32,33,34,35,36,,,,128,,38,,120,123,124,126,127,129,130',
+'131,132,,,,,120,,,,,,,,,,,,,,,,,,,,,50,147,148,149,150,128,,,,,123,124',
+'126,127,129,130,131,132,128,,,,120,123,124,126,127,129,130,131,132,',
+',,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50,147,148,149,150,128,,,,',
+'123,124,126,127,129,130,131,132,128,,,,120,123,124,126,127,129,130,131',
+'132,,,,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50,147,148,149,150,128',
',,,,123,124,126,127,129,130,131,132,128,,,,120,123,124,126,127,129,130',
'131,132,,,,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50,147,148,149,150',
'128,,,,,123,124,126,127,129,130,131,132,128,,,,120,123,124,126,127,129',
'130,131,132,,,,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50,147,148,149',
-'150,128,,,,,123,124,126,127,129,130,131,132,128,,,,,123,124,126,127',
-'129,130,131,132,,,120,,,,,,,,,,50,147,148,149,150,160,120,444,,,,,,50',
-'147,148,149,150,,,,,,34,35,36,,,159,161,,,,,123,124,126,127,129,130',
-'131,132,,,,128,,,,,123,124,126,127,129,130,131,132,120,436,,,,,,,,50',
-'147,148,149,150,120,432,,,,,,,,,,50,147,148,149,150,,,,,,,,,,128,,,',
-',123,124,126,127,129,130,131,132,,128,,,,,123,124,126,127,129,130,131',
-'132,120,430,,,,,,,,,,50,147,148,149,150,120,,,,,,,,,50,147,148,149,150',
-',,,,,,,,,128,,,,,123,124,126,127,129,130,131,132,,,,128,,,,120,123,124',
-'126,127,129,130,131,132,,,,,,,,,,50,147,148,149,150,,,,,,,,,,,,50,147',
-'148,149,150,128,,,,,123,124,126,127,129,130,131,132,,,,,,,,,,,,,120',
-',,,,,,,,,,,,50,147,148,149,150,15,16,17,18,19,20,21,22,23,24,25,26,31',
-'32,33,34,35,36,,,,128,,38,,,123,124,126,127,129,130,131,132,120,418',
-',,,,,,,,,,,120,415,,,,,,,,,,,50,147,148,149,150,,,,,,,,,,128,,,,,123',
-'124,126,127,129,130,131,132,128,,,,120,123,124,126,127,129,130,131,132',
-',,,,,,,,,,,,50,147,148,149,150,,,,,,,,,50,147,148,149,150,128,,,,,123',
-'124,126,127,129,130,131,132,120,,,,,,,,,,,,,120,,266,,,,,,,,,,50,147',
-'148,149,150,,,,34,35,36,,,265,267,,,,,123,124,126,127,129,130,131,132',
-'128,,,,,123,124,126,127,129,130,131,132,120,,,,,,,,,,,,50,147,148,149',
-'150,120,,,,,,,,50,147,148,149,150,,,,34,35,36,,,,128,,,,,123,124,126',
-'127,129,130,131,132,,,,368,369,,,,,123,124,126,127,129,130,131,132,120',
-',,,,,,,50,147,148,149,150,120,,,,,,,,,,,,50,147,148,149,150,,,,34,35',
-'36,,,,128,,,,,123,124,126,127,129,130,131,132,128,,,,120,123,124,126',
+'150,128,,,,,123,124,126,127,129,130,131,132,128,,,,120,123,124,126,127',
+'129,130,131,132,,,,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50,147,148',
+'149,150,128,,,,,123,124,126,127,129,130,131,132,128,,,,120,123,124,126',
'127,129,130,131,132,,,,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50,147',
'148,149,150,128,,,,,123,124,126,127,129,130,131,132,128,,,,120,123,124',
'126,127,129,130,131,132,,,,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50',
@@ -492,55 +498,50 @@ clist = [
',,,,,,,,50,147,148,149,150,128,,,,,123,124,126,127,129,130,131,132,128',
',,,120,123,124,126,127,129,130,131,132,,,,,120,,,,,,,,50,147,148,149',
'150,,,,,,,,,50,147,148,149,150,128,,,,,123,124,126,127,129,130,131,132',
-'128,,,,120,123,124,126,127,129,130,131,132,,,,,120,,,,,,,,50,147,148',
-'149,150,,,,,,,,,50,147,148,149,150,128,,,,,123,124,126,127,129,130,131',
-'132,128,,,,120,123,124,126,127,129,130,131,132,,,,,120,,,,,,,,50,147',
-'148,149,150,,,,,,,,,50,147,148,149,150,128,,,,,123,124,126,127,129,130',
-'131,132,128,,,,120,123,124,126,127,129,130,131,132,,,,,,,,,,,,,50,147',
-'148,149,150,,,,,,,,,50,147,148,149,150,128,,,,,123,124,126,127,129,130',
-'131,132,,,,,,,,,,,,,120,318,,,,,,,,,,,,50,147,148,149,150,15,16,17,18',
-'19,20,21,22,23,24,25,26,31,32,33,34,35,36,,,,128,,38,,120,123,124,126',
-'127,129,130,131,132,,,,,120,,,,,,,,,,,,,,,,,,,,,50,147,148,149,150,128',
-',,,,123,124,126,127,129,130,131,132,128,,,,120,123,124,126,127,129,130',
-'131,132,,,,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50,147,148,149,150',
-'128,,,,,123,124,126,127,129,130,131,132,128,,,,120,123,124,126,127,129',
-'130,131,132,,,,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50,147,148,149',
-'150,128,,,,,123,124,126,127,129,130,131,132,128,,,,120,123,124,126,127',
-'129,130,131,132,,,,,120,,,,,,,,50,147,148,149,150,,,,,,,,,50,147,148',
-'149,150,128,,,,,123,124,126,127,129,130,131,132,128,,,,220,123,124,126',
-'127,129,130,131,132,,,,,220,,,,,,,,50,147,148,149,150,,,,,,,,,50,147',
-'148,149,150,128,,,,,123,124,126,127,129,130,131,132,128,,,,120,123,124',
-'126,127,129,130,131,132,,,,,224,,,,,,,,50,147,148,149,150,,,,,,,,,50',
-'147,148,149,150,128,,,,,123,124,126,127,129,130,131,132,128,,,,,123',
-'124,126,127,129,130,131,132,120,,,,,,,,,,,,50,147,148,149,150,,,,,,',
-',,50,147,148,149,150,,,,,,,,,401,402,,,,,123,124,126,127,129,130,131',
-'132,,,,,,,,,,,,,,,,,,277,364,,,,,,,50,147,148,149,150,10,11,12,13,14',
-'15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,281,164,49',
-',38,,,,,,,,,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32',
-'33,34,35,36,37,,,,50,38,,,,,,,,,,,,,,,39,,,,,,,,,,,,,,,,,,,,,50,10,11',
-'12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,65',
-',,,38,,,,,,,,,,,,67,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25',
-'26,31,32,33,34,35,36,37,65,,,,38,,,,,,,,,,,,,10,11,12,13,14,15,16,17',
-'18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,173,,,,38,,,,,,,,,,',
-',,,,,,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,282,,,,',
-'38,,,,,,,,,,,,,,,,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35',
-'36,287,,,,,38,,,,,,,,,,,,,,,,15,16,17,18,19,20,21,22,23,24,25,26,31',
-'32,33,34,35,36,312,364,,,,38,,,,,,,,10,11,12,13,14,15,16,17,18,19,20',
-'21,22,23,24,25,26,31,32,33,34,35,36,37,281,404,49,,38,,,,,,,,,10,11',
-'12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,,',
-',,38,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34',
-'35,36,37,,,,,38,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,31',
-'32,33,34,35,36,37,,,,,38,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24',
-'25,26,31,32,33,34,35,36,37,,,,,38,10,11,12,13,14,15,16,17,18,19,20,21',
-'22,23,24,25,26,31,32,33,34,35,36,37,,,,,38,10,11,12,13,14,15,16,17,18',
-'19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,,,,,38,10,11,12,13,14,15',
-'16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,,,,359,38,15,16',
-'17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,,,,,,38,15,16,17,18',
+'128,,,,,123,124,126,127,129,130,131,132,120,,,,,,,,,,,,50,147,148,149',
+'150,120,,,,,,,,50,147,148,149,150,,,,34,35,36,,,,128,,,,,123,124,126',
+'127,129,130,131,132,,,,368,369,,,,120,123,124,126,127,129,130,131,132',
+',,,,,120,,,50,147,148,149,150,,,,,,,,,,,,,50,147,148,149,150,128,,,',
+',123,124,126,127,129,130,131,132,401,402,,,,120,123,124,126,127,129',
+'130,131,132,,,,,120,415,,,,,,50,147,148,149,150,,,,,,,,,,50,147,148',
+'149,150,128,,,,,123,124,126,127,129,130,131,132,128,,,,,123,124,126',
+'127,129,130,131,132,120,418,,,,,,,,,,,50,147,148,149,150,,,,,,,,,50',
+'147,148,149,150,,,,,,,,,,128,,,,,123,124,126,127,129,130,131,132,,,',
+',,,,,,,,,120,,,,,,,,,,,,,50,147,148,149,150,15,16,17,18,19,20,21,22',
+'23,24,25,26,31,32,33,34,35,36,,,,128,,38,,120,123,124,126,127,129,130',
+'131,132,,,,,120,430,,,,,,,,,,,,,,,,,,,,50,147,148,149,150,128,,,,,123',
+'124,126,127,129,130,131,132,128,,,,,123,124,126,127,129,130,131,132',
+'120,432,,,,,,,,,,,50,147,148,149,150,120,436,,,,,,,50,147,148,149,150',
+',,,,,,,,,128,,,,,123,124,126,127,129,130,131,132,,,,,128,,,,,123,124',
+'126,127,129,130,131,132,120,444,,,,,,,50,147,148,149,150,,,,,,,,,,,',
+',50,147,148,149,150,,,,,,,,,,128,,,,,123,124,126,127,129,130,131,132',
+',,,,,,,,,,,,,,,,,277,364,,,,,,,50,147,148,149,150,10,11,12,13,14,15',
+'16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,281,164,49,,38',
+',,,,,,,,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33',
+'34,35,36,37,,,,50,38,,,,,,,,,,,,,,,39,,,,,,,,,,,,,,,,,,,,,50,10,11,12',
+'13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,65,,',
+',38,,,,,,,,,,,,67,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26',
+'31,32,33,34,35,36,37,65,,,,38,,,,,,,,,,,,,10,11,12,13,14,15,16,17,18',
+'19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,173,,,,38,,,,,,,,,,,,,',
+',,,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,282,,,,,38',
+',,,,,,,,,,,,,,,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36',
+'287,,,,,38,,,,,,,,,,,,,,,,15,16,17,18,19,20,21,22,23,24,25,26,31,32',
+'33,34,35,36,312,364,,,,38,,,,,,,,10,11,12,13,14,15,16,17,18,19,20,21',
+'22,23,24,25,26,31,32,33,34,35,36,37,281,404,49,,38,,,,,,,,,10,11,12',
+'13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,,,,,38',
+'10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33,34,35,36',
+'37,,,,,38,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,31,32,33',
+'34,35,36,37,,,,,38,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26',
+'31,32,33,34,35,36,37,,,,,38,10,11,12,13,14,15,16,17,18,19,20,21,22,23',
+'24,25,26,31,32,33,34,35,36,37,,,,,38,10,11,12,13,14,15,16,17,18,19,20',
+'21,22,23,24,25,26,31,32,33,34,35,36,37,,,,,38,10,11,12,13,14,15,16,17',
+'18,19,20,21,22,23,24,25,26,31,32,33,34,35,36,37,,,,359,38,15,16,17,18',
'19,20,21,22,23,24,25,26,31,32,33,34,35,36,,,,,,38,15,16,17,18,19,20',
'21,22,23,24,25,26,31,32,33,34,35,36,,,,,,38,15,16,17,18,19,20,21,22',
'23,24,25,26,31,32,33,34,35,36,,,,,,38,15,16,17,18,19,20,21,22,23,24',
-'25,26,31,32,33,34,35,36,,,,,,38' ]
- racc_action_table = arr = ::Array.new(4308, nil)
+'25,26,31,32,33,34,35,36,,,,,,38,15,16,17,18,19,20,21,22,23,24,25,26',
+'31,32,33,34,35,36,,,,,,38' ]
+ racc_action_table = arr = ::Array.new(4321, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -550,175 +551,175 @@ clist = [
end
clist = [
-'112,112,112,167,112,112,112,114,294,112,112,112,112,112,112,112,112',
-'445,445,445,45,445,445,445,210,402,445,445,445,445,445,445,445,445,66',
-'186,66,403,316,280,167,46,167,114,30,112,407,112,33,186,112,112,112',
-'112,112,112,112,112,311,184,289,210,445,210,445,316,382,445,445,445',
-'445,445,445,445,445,66,280,207,46,382,167,345,85,112,112,112,112,112',
-'294,30,207,48,87,33,84,311,85,45,427,345,445,445,445,445,445,444,444',
-'444,276,444,444,444,361,66,444,444,444,444,444,444,444,444,377,377,377',
-'30,377,377,377,33,48,377,377,377,377,377,377,377,377,184,289,69,340',
-'340,70,276,136,136,73,361,444,135,444,380,60,444,444,444,444,444,444',
-'444,444,59,135,135,380,377,48,377,260,58,377,377,377,377,377,377,377',
-'377,69,70,57,419,182,276,107,257,444,444,444,444,444,429,5,260,5,419',
-'182,107,260,257,55,429,411,377,377,377,377,377,376,376,376,216,376,376',
-'376,411,69,376,376,376,376,376,376,376,376,375,375,375,217,375,375,375',
-'330,5,375,375,375,375,375,375,375,375,133,331,213,330,330,138,138,138',
-'138,336,336,376,175,376,331,331,376,376,376,376,376,376,376,376,212',
-'175,335,335,375,5,375,304,42,375,375,375,375,375,375,375,375,49,49,49',
-'304,42,204,49,203,376,376,376,376,376,201,133,133,133,133,133,133,133',
-'133,133,133,200,375,375,375,375,375,437,437,437,188,437,437,437,334',
-'334,437,437,437,437,437,437,437,437,436,436,436,263,436,436,436,431',
-'301,436,436,436,436,436,436,436,436,431,301,317,264,211,163,338,338',
-'338,338,267,437,317,437,211,163,437,437,437,437,437,437,437,437,339',
-'339,339,339,436,177,436,443,417,436,436,436,436,436,436,436,436,443',
-'417,270,410,435,302,414,300,437,437,437,437,437,410,435,302,414,300',
-'74,74,74,333,333,274,74,436,436,436,436,436,433,433,433,39,433,433,433',
-'332,332,433,433,433,433,433,433,433,433,187,187,187,165,187,187,187',
-'137,137,187,187,187,187,187,187,187,187,139,139,337,337,144,144,162',
-'161,158,151,143,433,303,433,142,141,433,433,433,433,433,433,433,433',
-'140,324,325,341,187,342,187,343,344,187,187,187,187,187,187,187,187',
-'351,354,356,362,363,119,367,369,433,433,433,433,433,116,115,113,111',
-'110,109,101,100,389,390,98,89,187,187,187,187,187,65,65,65,65,65,65',
-'65,400,,65,65,65,65,65,65,65,65,,,65,65,65,65,65,65,65,65,65,65,65,65',
-'65,65,65,65,65,65,65,65,65,65,65,65,,,65,,65,,,65,65,65,65,65,65,65',
-'65,296,296,296,,296,296,296,,,296,296,296,296,296,296,296,296,,,,,,',
-',,65,65,65,65,65,,,,,,80,,,,,,,80,,,296,,296,,,296,296,296,296,296,296',
-'296,296,432,432,432,,432,432,432,,,432,432,432,432,432,432,432,432,',
-',,,,,80,,296,296,296,296,296,,,,,,284,,,,,,,284,,,432,,432,,,432,432',
-'432,432,432,432,432,432,430,430,430,80,430,430,430,,,430,430,430,430',
-'430,430,430,430,,,,,,,284,,432,432,432,432,432,,,,,,,,,,,,,,,,430,,430',
-',,430,430,430,430,430,430,430,430,426,426,426,284,426,426,426,,,426',
-'426,426,426,426,426,426,426,,,,,,,,,430,430,430,430,430,,,,,,,,,,,,',
-',,,426,,426,,,426,426,426,426,426,426,426,426,418,418,418,,418,418,418',
-',,418,418,418,418,418,418,418,418,,,,,,,,,426,426,426,426,426,,,,,,',
-',,,,,,,,,418,,418,,,418,418,418,418,418,418,418,418,454,454,454,,454',
-'454,454,,,454,454,454,454,454,454,454,454,,,,,,,,,418,418,418,418,418',
-',,,,,,,,,,,,,,,454,,454,,,454,454,454,454,454,454,454,454,415,415,415',
-',415,415,415,,,415,415,415,415,415,415,415,415,,,,,,,,,454,454,454,454',
-'454,,,,,,,,,,,,,,,,415,,415,,,415,415,415,415,415,415,415,415,450,450',
-'450,,450,450,450,,,450,450,450,450,450,450,450,450,,,,,,,,,415,415,415',
-'415,415,,,,,,,,,,,,,,,,450,,450,,,450,450,450,450,450,450,450,450,192',
-'192,192,,192,192,192,,,192,192,192,192,192,192,192,192,,,,,,,,,450,450',
-'450,450,450,,,,,,,,,,,,,,,,192,,192,,262,192,192,192,192,192,192,192',
-'192,191,191,191,,191,191,191,,,191,191,191,191,191,191,191,191,,,,,122',
-',,,192,192,192,192,192,262,,,,,262,262,262,262,262,262,262,262,,,191',
-',191,,,191,191,191,191,191,191,191,191,122,,,,,122,122,122,122,,262',
-'262,262,262,262,,,,,,,,,,,191,191,191,191,191,102,102,102,102,102,102',
-'102,,,102,102,102,102,102,102,102,102,,,102,102,102,102,102,102,102',
-'102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102',
-',,102,,102,,,102,102,102,102,102,102,102,102,447,447,447,,447,447,447',
-',,447,447,447,447,447,447,447,447,439,439,,,439,,,,102,102,102,102,102',
-',,,,,,,,,,,,,,,447,,447,,,447,447,447,447,447,447,447,447,439,,439,',
-',439,,439,439,439,439,439,439,439,439,,,,,,,,,,,447,447,447,447,447',
-'224,,,,224,,,,,,439,439,439,439,439,393,,,,393,,,224,224,224,224,224',
-'224,224,224,224,224,224,224,224,224,224,224,224,224,,,,224,,224,,,224',
-'224,224,224,224,224,224,224,,,393,,,,,393,393,393,393,393,393,393,393',
-'67,,,,67,,,,,,224,224,224,224,224,315,,,,315,,,,,,393,393,393,393,393',
-',,,,,,,,,,,,,67,,,,,67,67,67,67,67,67,67,67,,,315,,,,,315,315,315,315',
-'315,315,315,315,154,,,,154,,,,,,67,67,67,67,67,347,347,,,347,,,,,,315',
-'315,315,315,315,,,,,,,,,,,,154,,154,,,154,,154,154,154,154,154,154,154',
-'154,347,,347,,,347,,347,347,347,347,347,347,347,347,,,,,,,,,,,154,154',
-'154,154,154,120,,,,120,,,,,,347,347,347,347,347,258,,,,258,,,120,120',
-'120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,,,,120',
-',120,,,120,120,120,120,120,120,120,120,,,258,,,,,258,258,258,258,258',
-'258,258,258,384,,,,384,,,,,,120,120,120,120,120,,,,,,,,,,,258,258,258',
-'258,258,,,,,,,,,,,,384,,384,,,384,,384,384,384,384,384,384,384,384,',
-',,,,,,,220,,,,220,,,,,,,,,,,,,384,384,384,384,384,220,220,220,220,220',
-'220,220,220,220,220,220,220,220,220,220,220,220,220,,,,220,,220,,,220',
-'220,220,220,220,220,220,220,305,,305,,,,,,,,,,,306,,306,,,,,,,,,,220',
-'220,220,220,220,,,,,,,,,,,,305,,,,,305,305,305,305,305,305,305,305,306',
-',,,,306,306,306,306,306,306,306,306,,,,,,,,,,,,,305,305,305,305,305',
-'202,,202,,,,,,306,306,306,306,306,,,202,202,202,202,202,202,202,202',
-'202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,,,202',
-',202,,,202,202,202,202,202,202,202,202,117,,117,,,,,,,,,,,379,,379,',
-',,,,,,,,202,202,202,202,202,,,,,,,,,,,,117,,,,,117,117,117,117,117,117',
-'117,117,379,,,,244,379,379,379,379,379,379,379,379,,,,,245,,,,,,,,117',
-'117,117,117,117,,,,,,,,,379,379,379,379,379,244,,,,,244,244,244,244',
-'244,244,244,244,245,,,,246,245,245,245,245,245,245,245,245,,,,,247,',
-',,,,,,244,244,244,244,244,,,,,,,,,245,245,245,245,245,246,,,,,246,246',
-'246,246,246,246,246,246,247,,,,,247,247,247,247,247,247,247,247,,,71',
-',,,,,,,,,246,246,246,246,246,71,428,428,,,,,,247,247,247,247,247,,,',
-',,71,71,71,,,71,71,,,,,71,71,71,71,71,71,71,71,,,,428,,,,,428,428,428',
-'428,428,428,428,428,416,416,,,,,,,,71,71,71,71,71,413,413,,,,,,,,,,428',
-'428,428,428,428,,,,,,,,,,416,,,,,416,416,416,416,416,416,416,416,,413',
-',,,,413,413,413,413,413,413,413,413,412,412,,,,,,,,,,416,416,416,416',
-'416,391,,,,,,,,,413,413,413,413,413,,,,,,,,,,412,,,,,412,412,412,412',
-'412,412,412,412,,,,391,,,,99,391,391,391,391,391,391,391,391,,,,,,,',
-',,412,412,412,412,412,,,,,,,,,,,,391,391,391,391,391,99,,,,,99,99,99',
-'99,99,99,99,99,,,,,,,,,,,,,388,,,,,,,,,,,,,99,99,99,99,99,388,388,388',
-'388,388,388,388,388,388,388,388,388,388,388,388,388,388,388,,,,388,',
-'388,,,388,388,388,388,388,388,388,388,383,383,,,,,,,,,,,,381,381,,,',
-',,,,,,,388,388,388,388,388,,,,,,,,,,383,,,,,383,383,383,383,383,383',
-'383,383,381,,,,378,381,381,381,381,381,381,381,381,,,,,,,,,,,,,383,383',
-'383,383,383,,,,,,,,,381,381,381,381,381,378,,,,,378,378,378,378,378',
-'378,378,378,157,,,,,,,,,,,,,285,,157,,,,,,,,,,378,378,378,378,378,,',
-',157,157,157,,,157,157,,,,,157,157,157,157,157,157,157,157,285,,,,,285',
-'285,285,285,285,285,285,285,160,,,,,,,,,,,,157,157,157,157,157,281,',
-',,,,,,285,285,285,285,285,,,,160,160,160,,,,160,,,,,160,160,160,160',
-'160,160,160,160,,,,281,281,,,,,281,281,281,281,281,281,281,281,269,',
-',,,,,,160,160,160,160,160,178,,,,,,,,,,,,281,281,281,281,281,,,,269',
-'269,269,,,,269,,,,,269,269,269,269,269,269,269,269,178,,,,266,178,178',
-'178,178,178,178,178,178,,,,,185,,,,,,,,269,269,269,269,269,,,,,,,,,178',
-'178,178,178,178,266,,,,,266,266,266,266,266,266,266,266,185,,,,243,185',
-'185,185,185,185,185,185,185,,,,,196,,,,,,,,266,266,266,266,266,,,,,',
-',,,185,185,185,185,185,243,,,,,243,243,243,243,243,243,243,243,196,',
-',,197,196,196,196,196,196,196,196,196,,,,,198,,,,,,,,243,243,243,243',
-'243,,,,,,,,,196,196,196,196,196,197,,,,,197,197,197,197,197,197,197',
-'197,198,,,,199,198,198,198,198,198,198,198,198,,,,,256,,,,,,,,197,197',
-'197,197,197,,,,,,,,,198,198,198,198,198,199,,,,,199,199,199,199,199',
-'199,199,199,256,,,,255,256,256,256,256,256,256,256,256,,,,,254,,,,,',
-',,199,199,199,199,199,,,,,,,,,256,256,256,256,256,255,,,,,255,255,255',
-'255,255,255,255,255,254,,,,253,254,254,254,254,254,254,254,254,,,,,252',
-',,,,,,,255,255,255,255,255,,,,,,,,,254,254,254,254,254,253,,,,,253,253',
-'253,253,253,253,253,253,252,,,,251,252,252,252,252,252,252,252,252,',
-',,,250,,,,,,,,253,253,253,253,253,,,,,,,,,252,252,252,252,252,251,,',
-',,251,251,251,251,251,251,251,251,250,,,,214,250,250,250,250,250,250',
-'250,250,,,,,,,,,,,,,251,251,251,251,251,,,,,,,,,250,250,250,250,250',
-'214,,,,,214,214,214,214,214,214,214,214,,,,,,,,,,,,,215,215,,,,,,,,',
-',,,214,214,214,214,214,215,215,215,215,215,215,215,215,215,215,215,215',
-'215,215,215,215,215,215,,,,215,,215,,249,215,215,215,215,215,215,215',
-'215,,,,,248,,,,,,,,,,,,,,,,,,,,,215,215,215,215,215,249,,,,,249,249',
-'249,249,249,249,249,249,248,,,,226,248,248,248,248,248,248,248,248,',
-',,,238,,,,,,,,249,249,249,249,249,,,,,,,,,248,248,248,248,248,226,,',
-',,226,226,226,226,226,226,226,226,238,,,,239,238,238,238,238,238,238',
+'65,65,65,65,65,65,65,210,39,65,65,65,65,65,65,65,65,55,45,65,65,65,65',
+'65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,46,210,65',
+'210,65,316,345,65,65,65,65,65,65,65,65,85,276,57,163,58,135,182,186',
+'59,345,70,184,114,163,85,289,294,316,135,135,182,186,46,136,136,65,65',
+'65,65,65,102,102,102,102,102,102,102,45,276,102,102,102,102,102,102',
+'102,102,70,114,102,102,102,102,102,102,102,102,102,102,102,102,102,102',
+'102,102,102,102,102,102,102,102,102,102,30,280,102,60,102,276,73,102',
+'102,102,102,102,102,102,102,112,112,112,184,112,112,112,289,294,112',
+'112,112,112,112,112,112,112,257,260,330,33,42,48,280,107,102,102,102',
+'102,102,30,257,330,330,42,80,175,107,311,361,137,137,80,260,84,112,87',
+'112,260,175,112,112,112,112,112,112,112,112,187,187,187,48,187,187,187',
+'33,30,187,187,187,187,187,187,187,187,311,361,207,419,139,139,80,331',
+'112,112,112,112,112,211,304,207,133,419,284,380,331,331,89,211,48,284',
+'33,304,187,98,187,100,380,187,187,187,187,187,187,187,187,191,191,191',
+'80,191,191,191,382,411,191,191,191,191,191,191,191,191,144,144,101,382',
+'411,109,284,110,187,187,187,187,187,133,133,133,133,133,133,133,133',
+'133,133,5,111,5,332,332,191,113,191,333,333,191,191,191,191,191,191',
+'191,191,192,192,192,284,192,192,192,300,301,192,192,192,192,192,192',
+'192,192,300,301,115,302,317,410,5,414,191,191,191,191,191,302,317,410',
+'417,414,116,429,119,431,435,66,140,66,417,141,192,429,192,431,435,192',
+'192,192,192,192,192,192,192,296,296,296,5,296,296,296,443,142,296,296',
+'296,296,296,296,296,296,443,49,49,49,334,334,66,49,192,192,192,192,192',
+'74,74,74,335,335,143,74,138,138,138,138,151,69,336,336,296,158,296,337',
+'337,296,296,296,296,296,296,296,296,375,375,375,66,375,375,375,340,340',
+'375,375,375,375,375,375,375,375,338,338,338,338,161,162,69,165,296,296',
+'296,296,296,339,339,339,339,177,188,200,201,203,204,212,213,167,216',
+'217,375,263,375,264,267,375,375,375,375,375,375,375,375,376,376,376',
+'69,376,376,376,270,274,376,376,376,376,376,376,376,376,303,324,325,341',
+'167,342,167,343,375,375,375,375,375,344,351,354,356,362,363,367,369',
+'389,390,400,402,403,407,427,376,,376,,,376,376,376,376,376,376,376,376',
+'377,377,377,167,377,377,377,,,377,377,377,377,377,377,377,377,,,,,,',
+',,376,376,376,376,376,,,,,,,,,,,,,,,,377,,377,,,377,377,377,377,377',
+'377,377,377,415,415,415,,415,415,415,,,415,415,415,415,415,415,415,415',
+',,,,,,,,377,377,377,377,377,,,,,,,,,,,,,,,,415,,415,,,415,415,415,415',
+'415,415,415,415,418,418,418,,418,418,418,,,418,418,418,418,418,418,418',
+'418,,,,,,,,,415,415,415,415,415,,,,,,,,,,,,,,,,418,,418,,,418,418,418',
+'418,418,418,418,418,426,426,426,,426,426,426,,,426,426,426,426,426,426',
+'426,426,,,,,,,,,418,418,418,418,418,,,,,,,,,,,,,,,,426,,426,,,426,426',
+'426,426,426,426,426,426,430,430,430,,430,430,430,,,430,430,430,430,430',
+'430,430,430,,,,,,,,,426,426,426,426,426,,,,,,,,,,,,,,,,430,,430,,,430',
+'430,430,430,430,430,430,430,432,432,432,,432,432,432,,,432,432,432,432',
+'432,432,432,432,,,,,,,,,430,430,430,430,430,,,,,,,,,,,,,,,,432,,432',
+',,432,432,432,432,432,432,432,432,433,433,433,,433,433,433,,,433,433',
+'433,433,433,433,433,433,,,,,,,,,432,432,432,432,432,,,,,,,,,,,,,,,,433',
+',433,,,433,433,433,433,433,433,433,433,436,436,436,,436,436,436,,,436',
+'436,436,436,436,436,436,436,,,,,,,,,433,433,433,433,433,,,,,,,,,,,,',
+',,,436,,436,,,436,436,436,436,436,436,436,436,437,437,437,,437,437,437',
+',,437,437,437,437,437,437,437,437,,,,,,,,,436,436,436,436,436,,,,,,',
+',,,,,,,,,437,,437,,,437,437,437,437,437,437,437,437,444,444,444,,444',
+'444,444,,,444,444,444,444,444,444,444,444,,,,,,,,,437,437,437,437,437',
+',,,,,,,,,,,,,,,444,,444,,,444,444,444,444,444,444,444,444,445,445,445',
+',445,445,445,,,445,445,445,445,445,445,445,445,,,,,,,,,444,444,444,444',
+'444,,,,,,,,,,,,,,,,445,,445,,,445,445,445,445,445,445,445,445,447,447',
+'447,,447,447,447,,,447,447,447,447,447,447,447,447,,,,,,,,,445,445,445',
+'445,445,,,,,,,,,,,,,,,,447,,447,,,447,447,447,447,447,447,447,447,450',
+'450,450,,450,450,450,,,450,450,450,450,450,450,450,450,,,,,,,,,447,447',
+'447,447,447,,,,,,,,,,,,,,,,450,,450,,,450,450,450,450,450,450,450,450',
+'454,454,454,,454,454,454,,,454,454,454,454,454,454,454,454,67,,,,67',
+',,,450,450,450,450,450,,,,,,,122,,,,,,,,,454,,454,,,454,454,454,454',
+'454,454,454,454,,,67,,,,,67,67,67,67,67,67,67,67,122,,,,,122,122,122',
+'122,,454,454,454,454,454,120,,,,120,,,,,,67,67,67,67,67,154,,,,154,',
+',120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120',
+'120,,,,120,,120,,,120,120,120,120,120,120,120,120,154,,154,,,154,,154',
+'154,154,154,154,154,154,154,,,,,,,,,,,120,120,120,120,120,220,,,,220',
+',,,,,154,154,154,154,154,,,,,,,,220,220,220,220,220,220,220,220,220',
+'220,220,220,220,220,220,220,220,220,,,,220,,220,,,220,220,220,220,220',
+'220,220,220,,,,,,,,,224,,,,224,,,,,,,,,,,,,220,220,220,220,220,224,224',
+'224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,,,,224',
+',224,,,224,224,224,224,224,224,224,224,258,,,,258,,,,,,,,,315,,,,315',
+',,,,,,,224,224,224,224,224,,,,,,,,,,,,,,258,,,,,258,258,258,258,258',
+'258,258,258,315,,,,,315,315,315,315,315,315,315,315,347,347,,,347,,',
+',,,,,258,258,258,258,258,384,,,,384,,,,315,315,315,315,315,,,,,,,,,',
+',,347,,347,,,347,,347,347,347,347,347,347,347,347,,,384,,384,,,384,',
+'384,384,384,384,384,384,384,384,393,,,,393,,,,347,347,347,347,347,,',
+'439,439,,,439,,,,,,384,384,384,384,384,,,,,,,,,,,,,,393,,,,,393,393',
+'393,393,393,393,393,393,439,,439,,117,439,117,439,439,439,439,439,439',
+'439,439,,,,,,,,,,,393,393,393,393,393,,,,,,,,,,,439,439,439,439,439',
+'117,,,,,117,117,117,117,117,117,117,117,,,,,,,,,,,,,,,,202,,202,,,,',
+',,,117,117,117,117,117,202,202,202,202,202,202,202,202,202,202,202,202',
+'202,202,202,202,202,202,202,202,202,202,202,202,,,202,,202,,,202,202',
+'202,202,202,202,202,202,305,,305,,,,,,,,,,,306,,306,,,,,,,,,,202,202',
+'202,202,202,,,,,,,,,,,,305,,,,,305,305,305,305,305,305,305,305,306,',
+'379,,379,306,306,306,306,306,306,306,306,,,,,,,,,,,,,305,305,305,305',
+'305,,,,,,,,,306,306,306,306,306,379,,,,,379,379,379,379,379,379,379',
+'379,71,,,,,,,,,,,,,99,,71,,,,,,,,,,379,379,379,379,379,,,,71,71,71,',
+',71,71,,,,,71,71,71,71,71,71,71,71,99,,,,123,99,99,99,99,99,99,99,99',
+',,,,124,,,,,,,,71,71,71,71,71,,,,,,,,,99,99,99,99,99,123,,,,,123,123',
+'123,123,123,123,123,123,124,,,,125,124,124,124,124,124,124,124,124,',
+',,,126,,,,,,,,123,123,123,123,123,,,,,,,,,124,124,124,124,124,125,,',
+',,125,125,125,125,125,125,125,125,126,,,,,126,126,126,126,126,126,126',
+'126,,,157,,,,,,,,,,125,125,125,125,125,157,,,,160,,,,126,126,126,126',
+'126,,,,,,157,157,157,,,157,157,,,,178,157,157,157,157,157,157,157,157',
+'160,160,160,,,,160,,,,185,160,160,160,160,160,160,160,160,,,,,,,157',
+'157,157,157,157,178,,,,196,178,178,178,178,178,178,178,178,,160,160',
+'160,160,160,185,,,,197,185,185,185,185,185,185,185,185,,,,,,,178,178',
+'178,178,178,196,,,,198,196,196,196,196,196,196,196,196,,185,185,185',
+'185,185,197,,,,199,197,197,197,197,197,197,197,197,,,,,,,196,196,196',
+'196,196,198,,,,214,198,198,198,198,198,198,198,198,,197,197,197,197',
+'197,199,,,,,199,199,199,199,199,199,199,199,,,,,,,198,198,198,198,198',
+'214,,,,,214,214,214,214,214,214,214,214,,199,199,199,199,199,,,,,,,215',
+'215,,,,,,,,,,,,214,214,214,214,214,215,215,215,215,215,215,215,215,215',
+'215,215,215,215,215,215,215,215,215,,,,215,,215,,226,215,215,215,215',
+'215,215,215,215,,,,,238,,,,,,,,,,,,,,,,,,,,,215,215,215,215,215,226',
+',,,,226,226,226,226,226,226,226,226,238,,,,239,238,238,238,238,238,238',
'238,238,,,,,240,,,,,,,,226,226,226,226,226,,,,,,,,,238,238,238,238,238',
'239,,,,,239,239,239,239,239,239,239,239,240,,,,241,240,240,240,240,240',
'240,240,240,,,,,242,,,,,,,,239,239,239,239,239,,,,,,,,,240,240,240,240',
-'240,241,,,,,241,241,241,241,241,241,241,241,242,,,,123,242,242,242,242',
-'242,242,242,242,,,,,124,,,,,,,,241,241,241,241,241,,,,,,,,,242,242,242',
-'242,242,123,,,,,123,123,123,123,123,123,123,123,124,,,,125,124,124,124',
-'124,124,124,124,124,,,,,126,,,,,,,,123,123,123,123,123,,,,,,,,,124,124',
-'124,124,124,125,,,,,125,125,125,125,125,125,125,125,126,,,,,126,126',
-'126,126,126,126,126,126,365,,,,,,,,,,,,125,125,125,125,125,,,,,,,,,126',
-'126,126,126,126,,,,,,,,,365,365,,,,,365,365,365,365,365,365,365,365',
-',,,,,,,,,,,,,,,,,277,277,,,,,,,365,365,365,365,365,277,277,277,277,277',
+'240,241,,,,,241,241,241,241,241,241,241,241,242,,,,243,242,242,242,242',
+'242,242,242,242,,,,,244,,,,,,,,241,241,241,241,241,,,,,,,,,242,242,242',
+'242,242,243,,,,,243,243,243,243,243,243,243,243,244,,,,245,244,244,244',
+'244,244,244,244,244,,,,,246,,,,,,,,243,243,243,243,243,,,,,,,,,244,244',
+'244,244,244,245,,,,,245,245,245,245,245,245,245,245,246,,,,247,246,246',
+'246,246,246,246,246,246,,,,,248,,,,,,,,245,245,245,245,245,,,,,,,,,246',
+'246,246,246,246,247,,,,,247,247,247,247,247,247,247,247,248,,,,249,248',
+'248,248,248,248,248,248,248,,,,,250,,,,,,,,247,247,247,247,247,,,,,',
+',,,248,248,248,248,248,249,,,,,249,249,249,249,249,249,249,249,250,',
+',,251,250,250,250,250,250,250,250,250,,,,,252,,,,,,,,249,249,249,249',
+'249,,,,,,,,,250,250,250,250,250,251,,,,,251,251,251,251,251,251,251',
+'251,252,,,,253,252,252,252,252,252,252,252,252,,,,,254,,,,,,,,251,251',
+'251,251,251,,,,,,,,,252,252,252,252,252,253,,,,,253,253,253,253,253',
+'253,253,253,254,,,,255,254,254,254,254,254,254,254,254,,,,,256,,,,,',
+',,253,253,253,253,253,,,,,,,,,254,254,254,254,254,255,,,,,255,255,255',
+'255,255,255,255,255,256,,,,262,256,256,256,256,256,256,256,256,,,,,266',
+',,,,,,,255,255,255,255,255,,,,,,,,,256,256,256,256,256,262,,,,,262,262',
+'262,262,262,262,262,262,266,,,,,266,266,266,266,266,266,266,266,269',
+',,,,,,,,,,,262,262,262,262,262,281,,,,,,,,266,266,266,266,266,,,,269',
+'269,269,,,,269,,,,,269,269,269,269,269,269,269,269,,,,281,281,,,,285',
+'281,281,281,281,281,281,281,281,,,,,,365,,,269,269,269,269,269,,,,,',
+',,,,,,,281,281,281,281,281,285,,,,,285,285,285,285,285,285,285,285,365',
+'365,,,,378,365,365,365,365,365,365,365,365,,,,,381,381,,,,,,285,285',
+'285,285,285,,,,,,,,,,365,365,365,365,365,378,,,,,378,378,378,378,378',
+'378,378,378,381,,,,,381,381,381,381,381,381,381,381,383,383,,,,,,,,',
+',,378,378,378,378,378,,,,,,,,,381,381,381,381,381,,,,,,,,,,383,,,,,383',
+'383,383,383,383,383,383,383,,,,,,,,,,,,,388,,,,,,,,,,,,,383,383,383',
+'383,383,388,388,388,388,388,388,388,388,388,388,388,388,388,388,388',
+'388,388,388,,,,388,,388,,391,388,388,388,388,388,388,388,388,,,,,412',
+'412,,,,,,,,,,,,,,,,,,,,388,388,388,388,388,391,,,,,391,391,391,391,391',
+'391,391,391,412,,,,,412,412,412,412,412,412,412,412,413,413,,,,,,,,',
+',,391,391,391,391,391,416,416,,,,,,,412,412,412,412,412,,,,,,,,,,413',
+',,,,413,413,413,413,413,413,413,413,,,,,416,,,,,416,416,416,416,416',
+'416,416,416,428,428,,,,,,,413,413,413,413,413,,,,,,,,,,,,,416,416,416',
+'416,416,,,,,,,,,,428,,,,,428,428,428,428,428,428,428,428,,,,,,,,,,,',
+',,,,,,277,277,,,,,,,428,428,428,428,428,277,277,277,277,277,277,277',
'277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277',
-'277,277,277,72,277,,277,,,,,,,,,72,72,72,72,72,72,72,72,72,72,72,72',
-'72,72,72,72,72,72,72,72,72,72,72,72,,,,277,72,,,,,,,,,,,,,,,1,,,,,,',
-',,,,,,,,,,,,,,72,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,41',
-',,,1,,,,,,,,,,,,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41',
-'41,41,41,41,41,41,41,62,,,,41,,,,,,,,,,,,,62,62,62,62,62,62,62,62,62',
-'62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,78,,,,62,,,,,,,,,,,,,,',
-',,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,172,,,,,78,',
-',,,,,,,,,,,,,,172,172,172,172,172,172,172,172,172,172,172,172,172,172',
-'172,172,172,172,181,,,,,172,,,,,,,,,,,,,,,,181,181,181,181,181,181,181',
-'181,181,181,181,181,181,181,181,181,181,181,312,312,,,,181,,,,,,,,312',
+'277,72,277,,277,,,,,,,,,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72',
+'72,72,72,72,72,72,72,72,72,,,,277,72,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,',
+',,,,,72,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,41,,,,1,,,,',
+',,,,,,,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41',
+'41,41,41,41,62,,,,41,,,,,,,,,,,,,62,62,62,62,62,62,62,62,62,62,62,62',
+'62,62,62,62,62,62,62,62,62,62,62,62,78,,,,62,,,,,,,,,,,,,,,,,78,78,78',
+'78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,172,,,,,78,,,,,,,,,,,,',
+',,,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172,172',
+'172,181,,,,,172,,,,,,,,,,,,,,,,181,181,181,181,181,181,181,181,181,181',
+'181,181,181,181,181,181,181,181,312,312,,,,181,,,,,,,,312,312,312,312',
'312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312,312',
-'312,312,312,312,312,312,312,366,312,,312,,,,,,,,,366,366,366,366,366',
-'366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366',
-'366,366,,,,,366,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,',
-'0,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,,,,,6,7,7,7,7,7,7',
-'7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,,,,,7,8,8,8,8,8,8,8,8,8,8,8,8,8',
-'8,8,8,8,8,8,8,8,8,8,8,,,,,8,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,275,275,275,275,275,275,275,275,275,275,275,275,275,275',
-'275,275,275,275,275,275,275,275,275,275,,,,275,275,82,82,82,82,82,82',
-'82,82,82,82,82,82,82,82,82,82,82,82,,,,,,82,77,77,77,77,77,77,77,77',
-'77,77,77,77,77,77,77,77,77,77,,,,,,77,83,83,83,83,83,83,83,83,83,83',
-'83,83,83,83,83,83,83,83,,,,,,83,56,56,56,56,56,56,56,56,56,56,56,56',
-'56,56,56,56,56,56,,,,,,56,81,81,81,81,81,81,81,81,81,81,81,81,81,81',
-'81,81,81,81,,,,,,81' ]
- racc_action_check = arr = ::Array.new(4308, nil)
+'312,312,312,312,366,312,,312,,,,,,,,,366,366,366,366,366,366,366,366',
+'366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,,,,',
+'366,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,,,,0,6,6,6,6,6',
+'6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,,,,,6,7,7,7,7,7,7,7,7,7,7,7,7',
+'7,7,7,7,7,7,7,7,7,7,7,7,,,,,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8',
+'8,8,8,8,8,,,,,8,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,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275,275',
+'275,275,275,275,275,275,275,,,,275,275,56,56,56,56,56,56,56,56,56,56',
+'56,56,56,56,56,56,56,56,,,,,,56,77,77,77,77,77,77,77,77,77,77,77,77',
+'77,77,77,77,77,77,,,,,,77,81,81,81,81,81,81,81,81,81,81,81,81,81,81',
+'81,81,81,81,,,,,,81,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82',
+'82,82,,,,,,82,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83',
+',,,,,83' ]
+ racc_action_check = arr = ::Array.new(4321, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -728,52 +729,52 @@ clist = [
end
racc_action_pointer = [
- 3992, 3690, nil, nil, nil, 187, 4021, 4050, 4079, 4108,
+ 4005, 3703, nil, nil, nil, 295, 4034, 4063, 4092, 4121,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 39, nil, nil, 43, nil, nil, nil, nil, nil, 423,
- nil, 3731, 269, nil, nil, 11, 32, nil, 82, 243,
- nil, nil, nil, nil, nil, 197, 4233, 177, 166, 77,
- 149, nil, 3772, nil, nil, 522, 27, 1405, nil, 132,
- 135, 2068, 3625, 138, 366, nil, nil, 4185, 3812, nil,
- 616, 4257, 4161, 4209, 8, 76, nil, 71, nil, 433,
- nil, nil, nil, nil, nil, nil, nil, nil, 516, 2261,
- 513, 512, 1190, nil, nil, nil, nil, 179, nil, 504,
- 503, 502, -3, 501, -43, 502, 501, 1889, nil, 410,
- 1562, nil, 1117, 3398, 3411, 3454, 3467, nil, nil, nil,
- nil, nil, nil, 223, nil, 103, 89, 381, 184, 385,
- 422, 398, 396, 391, 384, nil, nil, nil, nil, nil,
- nil, 442, nil, nil, 1476, nil, nil, 2485, 415, nil,
- 2550, 414, 450, 344, nil, 420, nil, -6, nil, nil,
- nil, nil, 3851, nil, nil, 249, nil, 376, 2632, nil,
- nil, 3890, 178, nil, 53, 2688, 29, 434, 316, nil,
- nil, 1102, 1044, nil, nil, nil, 2744, 2787, 2800, 2843,
- 307, 285, 1835, 285, 283, nil, nil, 70, nil, nil,
- 15, 343, 258, 236, 3067, 3131, 127, 144, nil, nil,
- 1697, nil, nil, nil, 1334, nil, 3230, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 3243, 3286,
- 3299, 3342, 3355, 2731, 1945, 1958, 2001, 2014, 3187, 3174,
- 3024, 3011, 2968, 2955, 2912, 2899, 2856, 181, 1577, nil,
- 149, nil, 1087, 249, 305, nil, 2675, 312, nil, 2619,
- 345, nil, nil, nil, 327, 4137, 99, 3588, nil, nil,
- 30, 2567, nil, nil, 674, 2498, nil, nil, nil, 54,
- nil, nil, nil, nil, 2, nil, 580, nil, nil, nil,
- 387, 330, 385, 457, 268, 1751, 1764, nil, nil, nil,
- nil, 49, 3926, nil, nil, 1420, 18, 341, nil, nil,
- nil, nil, nil, nil, 469, 470, nil, nil, nil, nil,
- 186, 197, 370, 354, 259, 207, 190, 393, 290, 308,
- 73, 425, 412, 413, 413, 79, nil, 1491, nil, nil,
- nil, 448, nil, nil, 449, nil, 450, nil, nil, nil,
- nil, 103, 488, 489, nil, 3519, 3963, 454, nil, 455,
- nil, nil, nil, nil, nil, 224, 207, 119, 2433, 1902,
- 146, 2390, 59, 2377, 1633, nil, nil, nil, 2325, 511,
- 512, 2218, nil, 1349, nil, nil, nil, nil, nil, nil,
- 485, nil, -22, 27, nil, nil, nil, 35, nil, nil,
- 383, 197, 2202, 2150, 386, 928, 2136, 371, 812, 177,
- nil, nil, nil, nil, nil, nil, 754, 91, 2084, 183,
- 696, 329, 638, 417, nil, 384, 329, 312, nil, 1263,
- nil, nil, nil, 370, 102, 14, nil, 1248, nil, nil,
- 986, nil, nil, nil, 870, nil, nil, nil, nil, nil ]
+ 126, nil, nil, 161, nil, nil, nil, nil, nil, 8,
+ nil, 3744, 160, nil, nil, 9, 34, nil, 159, 354,
+ nil, nil, nil, nil, nil, 12, 4174, 55, 57, -20,
+ 129, nil, 3785, nil, nil, -3, 353, 1318, nil, 411,
+ 59, 2026, 3638, 127, 366, nil, nil, 4198, 3825, nil,
+ 179, 4222, 4246, 4270, 104, 52, nil, 171, nil, 157,
+ nil, nil, nil, nil, nil, nil, nil, nil, 248, 2039,
+ 250, 279, 85, nil, nil, nil, nil, 163, nil, 275,
+ 277, 294, 143, 299, 20, 332, 348, 1795, nil, 267,
+ 1389, nil, 1333, 2082, 2095, 2138, 2151, nil, nil, nil,
+ nil, nil, nil, 216, nil, 15, 24, 123, 350, 156,
+ 305, 293, 314, 340, 205, nil, nil, nil, nil, nil,
+ nil, 398, nil, nil, 1404, nil, nil, 2205, 377, nil,
+ 2224, 410, 448, 51, nil, 440, nil, 469, nil, nil,
+ nil, nil, 3864, nil, nil, 175, nil, 468, 2248, nil,
+ nil, 3903, 58, nil, 63, 2267, 59, 201, 469, nil,
+ nil, 259, 317, nil, nil, nil, 2291, 2310, 2334, 2353,
+ 470, 460, 1864, 467, 468, nil, nil, 216, nil, nil,
+ -2, 224, 466, 467, 2377, 2441, 393, 394, nil, nil,
+ 1475, nil, nil, nil, 1539, nil, 2484, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, 2497, 2540,
+ 2553, 2596, 2609, 2652, 2665, 2708, 2721, 2764, 2777, 2820,
+ 2833, 2876, 2889, 2932, 2945, 2988, 3001, 157, 1595, nil,
+ 143, nil, 3044, 396, 437, nil, 3057, 438, nil, 3109,
+ 454, nil, nil, nil, 416, 4150, 50, 3601, nil, nil,
+ 123, 3126, nil, nil, 237, 3169, nil, nil, nil, 67,
+ nil, nil, nil, nil, 68, nil, 375, nil, nil, nil,
+ 317, 318, 330, 502, 228, 1918, 1931, nil, nil, nil,
+ nil, 175, 3939, nil, nil, 1608, 28, 331, nil, nil,
+ nil, nil, nil, nil, 502, 503, nil, nil, nil, nil,
+ 117, 180, 248, 253, 336, 348, 358, 363, 388, 401,
+ 374, 458, 445, 446, 451, 47, nil, 1664, nil, nil,
+ nil, 478, nil, nil, 479, nil, 480, nil, nil, nil,
+ nil, 176, 518, 519, nil, 3183, 3976, 483, nil, 484,
+ nil, nil, nil, nil, nil, 433, 491, 549, 3226, 1974,
+ 233, 3239, 262, 3291, 1681, nil, nil, nil, 3355, 527,
+ 528, 3398, nil, 1737, nil, nil, nil, nil, nil, nil,
+ 487, nil, 488, 526, nil, nil, nil, 526, nil, nil,
+ 332, 263, 3411, 3463, 334, 607, 3480, 343, 665, 218,
+ nil, nil, nil, nil, nil, nil, 723, 531, 3532, 346,
+ 781, 348, 839, 897, nil, 349, 955, 1013, nil, 1752,
+ nil, nil, nil, 375, 1071, 1129, nil, 1187, nil, nil,
+ 1245, nil, nil, nil, 1303, nil, nil, nil, nil, nil ]
racc_action_default = [
-265, -265, -1, -3, -4, -265, -53, -55, -57, -59,
@@ -824,146 +825,148 @@ racc_action_default = [
-265, -41, -42, -193, -265, -33, -34, -36, -40, -32 ]
racc_goto_table = [
- 47, 162, 57, 152, 70, 60, 153, 5, 5, 176,
- 158, 75, 257, 51, 52, 53, 54, 76, 319, 41,
- 393, 62, 104, 279, 82, 55, 291, 340, 58, 330,
- 331, 81, 179, 180, 341, 207, 170, 101, 211, 76,
- 47, 64, 171, 47, 190, 82, 82, 188, 63, 82,
- 82, 82, 81, 81, 223, 342, 81, 81, 81, 194,
- 98, 47, 91, 361, 47, 105, 310, 168, 74, 90,
- 343, 210, 344, 213, 101, 47, 85, 338, 339, 167,
- 151, 163, 174, 151, 200, 226, 204, 78, 82, 360,
- 157, 332, 333, 153, 177, 81, 264, 98, 361, 270,
- 175, 182, 105, 2, 40, 156, 186, 98, 172, 203,
- 350, 317, 393, 1, 181, 300, 301, 302, 102, nil,
- 304, nil, nil, 190, nil, 171, 286, 212, 76, 276,
- 190, 291, 316, 292, nil, 299, 291, nil, 211, nil,
- 82, nil, 211, 334, 335, 336, 337, 81, nil, 82,
- nil, nil, nil, nil, 320, nil, 81, nil, nil, 200,
- nil, nil, 47, 200, 200, 326, 210, 327, 328, 329,
- 201, 210, 311, 324, 345, 210, 174, 325, nil, 269,
- nil, 278, 98, 82, nil, 174, 98, 98, 82, nil,
- 81, 420, 82, nil, 348, 81, nil, 153, nil, 81,
- nil, nil, 306, nil, nil, 354, nil, 190, 356, nil,
- 351, 322, 323, 370, nil, nil, nil, nil, nil, nil,
- 367, nil, nil, 380, 382, nil, nil, 212, nil, nil,
- 190, 212, nil, 371, nil, 70, nil, 171, nil, 276,
- nil, nil, 419, nil, 385, 295, nil, nil, nil, 297,
+ 47, 152, 57, 162, 75, 60, 70, 319, 153, 5,
+ 5, 257, 158, 176, 174, 51, 52, 53, 54, 76,
+ 393, 291, 279, 361, 74, 55, 82, 1, 58, 170,
+ 62, 104, 179, 180, 190, 223, 63, 101, 102, 41,
+ 47, 76, 188, 47, 171, 64, 157, 82, 82, 78,
+ 156, 82, 82, 82, 213, 85, 175, 90, 361, 163,
+ 98, 47, 2, 40, 47, 310, 91, 168, 194, 105,
+ 172, 210, 330, 331, 101, 47, 181, 332, 333, 360,
+ 182, 167, 338, 339, 200, 186, 204, 350, 317, 340,
+ 82, 334, 335, 336, 337, 153, 341, 98, 264, 342,
+ 151, 270, 343, 151, 344, 226, 105, 98, 174, 203,
+ nil, nil, 393, 190, 177, 212, nil, 174, nil, 81,
+ 190, 286, 276, nil, nil, nil, 291, 171, 292, nil,
+ 76, 291, nil, nil, nil, 269, nil, 299, nil, nil,
+ 81, 81, 82, nil, 81, 81, 81, nil, 327, 328,
+ 329, 82, nil, nil, 324, nil, 320, nil, 325, 200,
+ nil, nil, 47, 200, 200, 311, 210, 326, nil, nil,
+ 201, 210, nil, nil, nil, 210, nil, nil, nil, nil,
+ 420, nil, 98, 81, nil, 82, 98, 98, nil, nil,
+ 82, nil, 348, nil, 82, nil, nil, 190, nil, 153,
+ nil, 278, nil, nil, nil, 351, 306, 354, nil, nil,
+ 356, 322, 323, nil, nil, 212, nil, 370, nil, 212,
+ 190, nil, 367, nil, nil, 385, nil, nil, 371, nil,
+ nil, nil, 276, nil, nil, 81, nil, 70, nil, 171,
+ nil, 419, nil, nil, 81, 295, nil, nil, nil, 297,
298, nil, nil, nil, nil, nil, nil, nil, 352, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, 358,
- nil, 47, 47, nil, 311, nil, nil, nil, nil, 47,
- nil, nil, 167, 394, 167, nil, 153, nil, nil, nil,
- nil, 98, nil, nil, nil, 403, 410, 411, 177, 414,
- nil, 417, nil, nil, 400, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 167,
- nil, nil, nil, 153, nil, nil, nil, 320, nil, 422,
- 429, 431, 153, nil, 435, nil, 421, nil, nil, 210,
- nil, nil, nil, nil, nil, nil, 443, 200, 200, 200,
- nil, nil, nil, nil, 374, nil, 82, nil, nil, nil,
- nil, nil, nil, 81, nil, nil, nil, nil, nil, nil,
- 98, 98, 98, 167, nil, 394, nil, nil, 153, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 311, 200, 358,
+ nil, 47, 47, nil, nil, nil, nil, nil, 81, 47,
+ nil, 394, nil, 81, 167, nil, 167, 81, 153, nil,
+ nil, 98, nil, nil, nil, nil, nil, 403, nil, nil,
+ nil, nil, nil, nil, 207, nil, 400, 211, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, 177, nil,
+ nil, 167, nil, nil, nil, 153, 421, 422, nil, 320,
+ nil, nil, nil, nil, 153, nil, nil, nil, nil, 210,
+ nil, nil, nil, nil, nil, nil, nil, 200, 200, 200,
+ nil, nil, nil, nil, 374, nil, nil, nil, 82, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 98, 98, 98, 394, nil, 167, nil, nil, nil, nil,
+ 153, nil, nil, nil, 300, 301, 302, 200, nil, 304,
200, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, nil, 200, nil, 200, 200, nil, nil, 200, 200,
- 98, nil, nil, 98, nil, nil, 200, 200, nil, 200,
+ nil, 316, 200, nil, 200, 200, nil, 211, 200, 200,
+ 98, 211, nil, 98, nil, nil, 200, 200, nil, 200,
nil, 98, 200, nil, nil, 98, 200, 98, 98, nil,
- 189, 98, 98, 407, 408, 409, nil, nil, nil, 98,
- 98, nil, 98, nil, nil, 98, nil, nil, nil, 98,
- nil, nil, nil, nil, 221, 222, 189, 225, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, 98, 98, 407, 408, 409, nil, nil, 189, 98,
+ 98, nil, 98, 345, nil, 98, nil, nil, nil, 98,
+ nil, 81, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 221, 222, 189, 225, nil, nil, nil, nil,
nil, nil, nil, 434, nil, nil, 438, nil, nil, nil,
nil, nil, nil, nil, 441, nil, nil, nil, 446, nil,
- 448, 449, nil, nil, 451, 452, nil, nil, nil, nil,
- nil, nil, 455, 456, nil, 457, nil, nil, 458, 189,
- nil, nil, 459, nil, nil, nil, 189, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 448, 449, 380, 382, 451, 452, nil, nil, nil, nil,
+ nil, nil, 455, 456, nil, 457, nil, nil, 458, nil,
+ nil, nil, 459, nil, nil, nil, nil, 189, nil, nil,
+ nil, nil, nil, nil, 189, 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, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 189,
+ nil, nil, nil, nil, nil, 410, 411, nil, 414, nil,
+ 417, nil, nil, nil, nil, nil, nil, 189, 189, 189,
189, 189, 189, 189, 189, 189, 189, 189, 189, 189,
- 189, 189, 189, 189, 189, 189, 189, nil, nil, nil,
- nil, nil, nil, 189, nil, nil, nil, nil, nil, nil,
+ 189, 189, 189, 189, 189, nil, nil, nil, nil, 429,
+ 431, 189, nil, 435, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 443, nil, nil, nil, nil,
+ nil, nil, nil, nil, 189, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 189, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, 189, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 189, 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, 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, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 189 ]
+ 189 ]
racc_goto_check = [
- 15, 43, 17, 27, 40, 17, 42, 5, 5, 35,
- 42, 39, 50, 5, 5, 5, 5, 24, 59, 6,
- 51, 7, 19, 47, 24, 15, 37, 67, 15, 63,
- 63, 23, 33, 33, 68, 20, 39, 17, 20, 24,
- 15, 4, 24, 15, 73, 24, 24, 16, 8, 24,
- 24, 24, 23, 23, 62, 69, 23, 23, 23, 19,
- 15, 15, 4, 49, 15, 4, 47, 15, 41, 8,
- 70, 33, 71, 48, 17, 15, 36, 66, 66, 5,
- 6, 44, 32, 6, 17, 74, 17, 31, 24, 46,
- 41, 64, 64, 42, 6, 23, 42, 15, 49, 42,
- 34, 36, 4, 2, 2, 26, 36, 15, 31, 15,
- 53, 58, 51, 1, 31, 20, 20, 20, 18, nil,
- 20, nil, nil, 73, nil, 24, 16, 8, 24, 39,
- 73, 37, 20, 16, nil, 42, 37, nil, 20, nil,
- 24, nil, 20, 65, 65, 65, 65, 23, nil, 24,
- nil, nil, nil, nil, 42, nil, 23, nil, nil, 17,
- nil, nil, 15, 17, 17, 42, 33, 62, 62, 62,
- 9, 33, 39, 48, 20, 33, 32, 48, nil, 41,
- nil, 6, 15, 24, nil, 32, 15, 15, 24, nil,
- 23, 59, 24, nil, 27, 23, nil, 42, nil, 23,
- nil, nil, 4, nil, nil, 42, nil, 73, 42, nil,
- 16, 15, 15, 35, nil, nil, nil, nil, nil, nil,
- 42, nil, nil, 20, 20, nil, nil, 8, nil, nil,
- 73, 8, nil, 16, nil, 40, nil, 24, nil, 39,
- nil, nil, 50, nil, 62, 9, nil, nil, nil, 9,
+ 15, 27, 17, 43, 39, 17, 40, 59, 42, 5,
+ 5, 50, 42, 35, 32, 5, 5, 5, 5, 24,
+ 51, 37, 47, 49, 41, 15, 24, 1, 15, 39,
+ 7, 19, 33, 33, 73, 62, 8, 17, 18, 6,
+ 15, 24, 16, 15, 24, 4, 41, 24, 24, 31,
+ 26, 24, 24, 24, 48, 36, 34, 8, 49, 44,
+ 15, 15, 2, 2, 15, 47, 4, 15, 19, 4,
+ 31, 33, 63, 63, 17, 15, 31, 64, 64, 46,
+ 36, 5, 66, 66, 17, 36, 17, 53, 58, 67,
+ 24, 65, 65, 65, 65, 42, 68, 15, 42, 69,
+ 6, 42, 70, 6, 71, 74, 4, 15, 32, 15,
+ nil, nil, 51, 73, 6, 8, nil, 32, nil, 23,
+ 73, 16, 39, nil, nil, nil, 37, 24, 16, nil,
+ 24, 37, nil, nil, nil, 41, nil, 42, nil, nil,
+ 23, 23, 24, nil, 23, 23, 23, nil, 62, 62,
+ 62, 24, nil, nil, 48, nil, 42, nil, 48, 17,
+ nil, nil, 15, 17, 17, 39, 33, 42, nil, nil,
+ 9, 33, nil, nil, nil, 33, nil, nil, nil, nil,
+ 59, nil, 15, 23, nil, 24, 15, 15, nil, nil,
+ 24, nil, 27, nil, 24, nil, nil, 73, nil, 42,
+ nil, 6, nil, nil, nil, 16, 4, 42, nil, nil,
+ 42, 15, 15, nil, nil, 8, nil, 35, nil, 8,
+ 73, nil, 42, nil, nil, 62, nil, nil, 16, nil,
+ nil, nil, 39, nil, nil, 23, nil, 40, nil, 24,
+ nil, 50, nil, nil, 23, 9, nil, nil, nil, 9,
9, nil, nil, nil, nil, nil, nil, nil, 15, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 17, 15,
- nil, 15, 15, nil, 39, nil, nil, nil, nil, 15,
- nil, nil, 5, 27, 5, nil, 42, nil, nil, nil,
- nil, 15, nil, nil, nil, 43, 20, 20, 6, 20,
- nil, 20, nil, nil, 42, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 5,
- nil, nil, nil, 42, nil, nil, nil, 42, nil, 27,
- 20, 20, 42, nil, 20, nil, 73, nil, nil, 33,
- nil, nil, nil, nil, nil, nil, 20, 17, 17, 17,
- nil, nil, nil, nil, 9, nil, 24, nil, nil, nil,
- nil, nil, nil, 23, nil, nil, nil, nil, nil, nil,
- 15, 15, 15, 5, nil, 27, nil, nil, 42, nil,
- nil, nil, nil, nil, nil, nil, nil, 17, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 39, 17, 15,
+ nil, 15, 15, nil, nil, nil, nil, nil, 23, 15,
+ nil, 27, nil, 23, 5, nil, 5, 23, 42, nil,
+ nil, 15, nil, nil, nil, nil, nil, 43, nil, nil,
+ nil, nil, nil, nil, 20, nil, 42, 20, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, 6, nil,
+ nil, 5, nil, nil, nil, 42, 73, 27, nil, 42,
+ nil, nil, nil, nil, 42, nil, nil, nil, nil, 33,
+ nil, nil, nil, nil, nil, nil, nil, 17, 17, 17,
+ nil, nil, nil, nil, 9, nil, nil, nil, 24, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 15, 15, 15, 27, nil, 5, nil, nil, nil, nil,
+ 42, nil, nil, nil, 20, 20, 20, 17, nil, 20,
17, nil, nil, nil, nil, nil, nil, nil, 17, nil,
- nil, nil, 17, nil, 17, 17, nil, nil, 17, 17,
- 15, nil, nil, 15, nil, nil, 17, 17, nil, 17,
+ nil, 20, 17, nil, 17, 17, nil, 20, 17, 17,
+ 15, 20, nil, 15, nil, nil, 17, 17, nil, 17,
nil, 15, 17, nil, nil, 15, 17, 15, 15, nil,
- 60, 15, 15, 9, 9, 9, nil, nil, nil, 15,
- 15, nil, 15, nil, nil, 15, nil, nil, nil, 15,
- nil, nil, nil, nil, 60, 60, 60, 60, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, 15, 15, 9, 9, 9, nil, nil, 60, 15,
+ 15, nil, 15, 20, nil, 15, nil, nil, nil, 15,
+ nil, 23, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 60, 60, 60, 60, nil, nil, nil, nil,
nil, nil, nil, 9, nil, nil, 9, nil, nil, nil,
nil, nil, nil, nil, 9, nil, nil, nil, 9, nil,
- 9, 9, nil, nil, 9, 9, nil, nil, nil, nil,
- nil, nil, 9, 9, nil, 9, nil, nil, 9, 60,
- nil, nil, 9, nil, nil, nil, 60, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 9, 9, 20, 20, 9, 9, nil, nil, nil, nil,
+ nil, nil, 9, 9, nil, 9, nil, nil, 9, nil,
+ nil, nil, 9, nil, nil, nil, nil, 60, nil, nil,
+ nil, nil, nil, nil, 60, 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, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 60,
+ nil, nil, nil, nil, nil, 20, 20, nil, 20, nil,
+ 20, nil, nil, nil, nil, nil, nil, 60, 60, 60,
60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, nil, nil, nil,
- nil, nil, nil, 60, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 60, nil, nil, nil,
+ 60, 60, 60, 60, 60, nil, nil, nil, nil, 20,
+ 20, 60, nil, 20, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 20, nil, nil, nil, nil,
+ nil, nil, nil, nil, 60, 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, nil, nil, nil, 60, nil, nil, nil,
+ nil, nil, nil, nil, 60, 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, nil, nil, nil, nil, nil, nil, nil,
@@ -971,17 +974,17 @@ racc_goto_check = [
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, nil, nil,
- nil, nil, 60 ]
+ 60 ]
racc_goto_pointer = [
- nil, 113, 103, nil, 0, 7, 14, -20, 7, 58,
- nil, nil, nil, nil, nil, -5, -52, -28, 53, -43,
- -82, nil, nil, -25, -32, nil, 36, -64, nil, nil,
- nil, 31, 4, -49, 20, -71, 17, -158, nil, -38,
- -41, 19, -61, -71, 9, nil, -186, -144, -47, -213,
- -142, -327, nil, -150, nil, nil, nil, nil, -104, -197,
- 331, nil, -71, -212, -152, -102, -172, -224, -218, -198,
- -184, -183, nil, -55, -48 ]
+ nil, 27, 62, nil, 4, 9, 34, -11, -5, 58,
+ nil, nil, nil, nil, nil, -5, -57, -28, -27, -34,
+ 187, nil, nil, 63, -30, nil, -19, -66, nil, nil,
+ nil, -7, -64, -49, -24, -67, -4, -163, nil, -45,
+ -39, -25, -59, -69, -13, nil, -196, -145, -66, -253,
+ -143, -327, nil, -173, nil, nil, nil, nil, -127, -208,
+ 339, nil, -90, -169, -166, -154, -167, -162, -156, -154,
+ -152, -151, nil, -65, -28 ]
racc_goto_default = [
nil, nil, nil, 3, 4, 66, 73, nil, 93, 106,
diff --git a/test/racc/regress/csspool b/test/racc/regress/csspool
index 0a68d99bfd..a3d14a9b34 100644
--- a/test/racc/regress/csspool
+++ b/test/racc/regress/csspool
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -74,194 +74,190 @@ end
##### State transition tables begin ###
racc_action_table = [
- 9, 10, 137, 83, 37, 31, 55, 139, 59, 39,
- 45, 47, 45, 47, 85, 9, 10, 55, 129, 37,
- 31, 103, 84, 130, 39, 45, 47, 157, 158, 108,
- 113, 20, 113, 56, 37, 114, 23, 114, 163, 39,
- 45, 47, 104, 27, 56, 11, 20, 346, 48, 25,
- 48, 23, 224, 29, 138, 319, 38, 46, 27, 46,
+ 9, 10, 137, 129, 37, 31, 55, 139, 130, 39,
+ 45, 47, 45, 47, 123, 9, 10, 103, 3, 37,
+ 31, 98, 229, 103, 39, 45, 47, 230, 124, 125,
+ 224, 20, 113, 56, 37, 31, 23, 114, 104, 39,
+ 45, 47, 245, 27, 104, 11, 20, 126, 48, 25,
+ 48, 23, 242, 29, 138, 244, 38, 46, 27, 46,
11, 108, 113, 48, 25, 9, 10, 114, 29, 37,
- 31, 38, 46, 242, 39, 45, 47, 115, 48, 115,
- 9, 10, 319, 163, 37, 31, 38, 46, 339, 39,
- 45, 47, 351, 306, 245, 223, 20, 108, 113, 37,
- 31, 23, 118, 114, 39, 45, 47, 244, 27, 115,
- 11, 20, 344, 48, 25, 243, 23, 313, 29, 340,
- 314, 38, 46, 27, 345, 11, 20, 55, 48, 25,
- 155, 23, 163, 29, 37, 64, 38, 46, 27, 39,
- 45, 47, 231, 48, 25, 115, 103, 232, 29, -89,
- 229, 38, 46, 203, 56, 230, 123, 250, 37, 319,
- 251, 20, 357, 39, 45, 47, 23, 104, 75, 204,
- 124, 125, 188, 27, 59, 322, 45, 47, 48, 25,
- 187, 3, 359, 29, 74, 73, 38, 46, 83, 126,
- 198, 49, 190, 197, 192, 191, 193, 194, 195, 85,
- 37, 31, 48, 108, 113, 39, 45, 47, 107, 114,
- 38, 46, 53, 105, 48, 103, 153, 170, 151, 98,
- 116, 181, 186, 46, 185, 196, 120, 20, 108, 113,
- 45, 47, 23, 215, 114, 298, 104, 297, 188, 27,
- 59, 201, 45, 47, 48, 25, 187, 121, 252, 29,
- 151, 115, 38, 46, 83, 128, 198, 202, 190, 197,
- 192, 191, 193, 194, 195, 85, 37, 31, 48, 131,
- 77, 39, 45, 47, 45, 47, 115, 46, 203, 37,
- 48, 136, 148, 170, 39, 45, 47, 181, 186, 46,
- 185, 196, 92, 20, 204, 37, 31, -28, 23, 87,
- 39, 45, 47, 156, 201, 27, 160, 163, 94, 75,
- 48, 25, 48, 164, 296, 29, 295, 83, 38, 46,
- 202, 46, 20, 48, 165, 74, 73, 23, 85, 166,
- 167, 38, 46, 188, 27, 59, 84, 168, 169, 48,
- 25, 187, 199, 294, 29, 293, 200, 38, 46, 83,
- 292, 198, 291, 190, 197, 192, 191, 193, 194, 195,
- 85, 37, 31, 92, 37, 31, 39, 45, 47, 39,
- 45, 47, 289, 163, 290, 113, 210, -33, 170, 288,
- 114, 287, 181, 186, 212, 185, 196, 92, 20, -33,
- 216, 37, 217, 23, 218, 219, 39, 45, 47, 108,
- 27, 108, 225, 94, 226, 48, 25, 188, 48, 59,
- 29, 258, 233, 38, 46, 187, 38, 46, 260, 150,
- 152, 151, 115, 83, 129, 198, 259, 190, 197, 192,
- 191, 193, 194, 195, 85, 48, 234, 163, 255, 256,
- 155, 263, 169, 38, 46, 264, 188, 168, 59, 265,
- 266, 92, 170, 92, 187, 92, 181, 186, 92, 185,
- 196, 184, 83, 278, 198, 279, 190, 197, 192, 191,
- 193, 194, 195, 85, 37, 31, 281, 286, 229, 39,
- 45, 47, 198, 231, 190, 197, 192, 191, 193, 194,
- 195, 170, 163, 300, 301, 181, 186, 302, 185, 196,
- 303, 20, 37, 306, 307, 255, 23, 39, 45, 47,
- 75, 163, 188, 27, 59, 185, 168, 312, 48, 25,
- 187, 317, 319, 29, 323, 324, 38, 46, 83, 325,
- 198, 326, 190, 197, 192, 191, 193, 194, 195, 85,
- 327, 328, 329, 330, 331, 332, 48, 333, 334, 306,
- 188, 163, 59, 338, 38, 46, nil, 170, 187, nil,
- nil, 181, 186, nil, 185, 196, 83, nil, 198, nil,
- 190, 197, 192, 191, 193, 194, 195, 85, 37, 31,
- nil, nil, nil, 39, 45, 47, nil, nil, 188, nil,
- 59, 285, nil, nil, nil, 170, 187, nil, nil, 181,
- 186, nil, 185, 196, 83, 141, 198, nil, 190, 197,
- 192, 191, 193, 194, 195, 85, nil, nil, nil, 143,
- nil, nil, 48, 241, 235, 236, 237, nil, nil, nil,
- 38, 46, nil, 170, nil, nil, 145, 181, 186, nil,
- 185, 196, nil, 144, nil, 146, nil, 147, nil, 142,
- 238, 239, 240, 272, nil, 83, nil, 198, nil, 190,
- 197, 192, 191, 193, 194, 195, 272, nil, 83, nil,
- 198, nil, 190, 197, 192, 191, 193, 194, 195, 272,
+ 31, 38, 46, 223, 39, 45, 47, 49, 48, 115,
+ 9, 10, 108, 113, 37, 31, 38, 46, 114, 39,
+ 45, 47, 55, 339, 243, 155, 20, 108, 113, 37,
+ 31, 23, 107, 114, 39, 45, 47, 231, 27, 115,
+ 11, 20, 232, 48, 25, 55, 23, 59, 29, 56,
+ 344, 38, 46, 27, 340, 11, 20, 53, 48, 25,
+ 115, 23, 345, 29, 37, 31, 38, 46, 27, 39,
+ 45, 47, 56, 48, 25, 115, -28, 105, 29, 37,
+ 31, 38, 46, 116, 39, 45, 47, 250, 75, 120,
+ 251, 20, 108, 113, 37, 31, 23, 118, 114, 39,
+ 45, 47, 121, 27, 74, 73, 20, 313, 48, 25,
+ 314, 23, 128, 29, 108, 113, 38, 46, 27, 215,
+ 114, 20, 131, 48, 25, 75, 23, 136, 29, 37,
+ 64, 38, 46, 27, 39, 45, 47, 92, 48, 25,
+ 115, 74, 73, 29, 37, 31, 38, 46, 77, 39,
+ 45, 47, 148, 94, 103, 156, 20, -89, 83, 37,
+ 31, 23, 115, 87, 39, 45, 47, 160, 27, 85,
+ 153, 20, 151, 48, 25, 104, 23, 84, 29, 157,
+ 158, 38, 46, 27, 163, 252, 20, 151, 48, 25,
+ 201, 23, 164, 29, 37, 31, 38, 46, 27, 39,
+ 45, 47, 203, 48, 25, 188, 202, 59, 29, 37,
+ 165, 38, 46, 187, 39, 45, 47, 201, 204, 166,
+ 184, 83, 288, 198, 287, 190, 197, 192, 191, 193,
+ 194, 195, 85, 202, 37, 45, 47, 37, 48, 39,
+ 45, 47, 39, 45, 47, 167, 38, 46, 168, 83,
+ 170, 113, 210, 48, 181, 186, 114, 185, 196, 37,
+ 85, 38, 46, 92, 39, 45, 47, 203, 84, 150,
+ 152, 151, 289, 48, 290, 292, 163, 291, 48, 94,
+ -33, 48, 46, 204, 169, 199, 38, 46, 37, 38,
+ 46, 200, -33, 39, 45, 47, 92, 188, 115, 59,
+ 294, 258, 293, 48, 296, 187, 295, 298, 260, 297,
+ 212, 38, 46, 83, 216, 198, 259, 190, 197, 192,
+ 191, 193, 194, 195, 85, 45, 47, 45, 47, 45,
+ 47, 217, 48, 218, 219, 188, 108, 59, 285, 108,
+ 38, 46, 170, 187, 225, 226, 181, 186, 233, 185,
+ 196, 83, 129, 198, 234, 190, 197, 192, 191, 193,
+ 194, 195, 85, 48, 163, 48, 255, 48, 256, 155,
+ 263, 169, 46, 188, 46, 59, 46, 264, 168, 265,
+ 170, 187, 266, 92, 181, 186, 92, 185, 196, 83,
+ 92, 198, 92, 190, 197, 192, 191, 193, 194, 195,
+ 85, 198, 278, 190, 197, 192, 191, 193, 194, 195,
+ 279, 188, 281, 59, 241, 235, 236, 237, 170, 187,
+ 286, 229, 181, 186, 231, 185, 196, 83, 163, 198,
+ 300, 190, 197, 192, 191, 193, 194, 195, 85, 301,
+ 302, 238, 239, 240, 303, 306, 307, 255, 141, 188,
+ 75, 59, 322, 163, 185, 168, 170, 187, 312, 317,
+ 181, 186, 143, 185, 196, 83, 319, 198, 323, 190,
+ 197, 192, 191, 193, 194, 195, 85, 324, 325, 145,
+ 326, 327, 328, 329, 330, 331, 144, 188, 146, 59,
+ 147, 332, 142, 333, 170, 187, 334, 306, 181, 186,
+ 163, 185, 196, 83, 338, 198, 163, 190, 197, 192,
+ 191, 193, 194, 195, 85, 346, 319, 319, 163, 351,
+ 306, 163, 319, 357, 359, 188, nil, 59, nil, nil,
+ nil, nil, 170, 187, nil, nil, 181, 186, nil, 185,
+ 196, 83, nil, 198, nil, 190, 197, 192, 191, 193,
+ 194, 195, 85, 272, nil, 83, nil, 198, nil, 190,
+ 197, 192, 191, 193, 194, 195, nil, nil, nil, nil,
+ 170, nil, nil, nil, 181, 186, nil, 185, 196, 272,
nil, 83, nil, 198, nil, 190, 197, 192, 191, 193,
194, 195, 272, nil, 83, nil, 198, nil, 190, 197,
192, 191, 193, 194, 195, 272, nil, 83, nil, 198,
nil, 190, 197, 192, 191, 193, 194, 195, 272, nil,
83, nil, 198, nil, 190, 197, 192, 191, 193, 194,
- 195 ]
+ 195, 272, nil, 83, nil, 198, nil, 190, 197, 192,
+ 191, 193, 194, 195 ]
racc_action_check = [
- 2, 2, 47, 22, 2, 2, 11, 47, 11, 2,
- 2, 2, 41, 41, 22, 5, 5, 10, 38, 5,
- 5, 217, 22, 38, 5, 5, 5, 70, 70, 221,
- 221, 2, 210, 11, 144, 221, 2, 210, 312, 144,
- 144, 144, 217, 2, 10, 2, 5, 316, 2, 2,
- 41, 5, 112, 2, 47, 320, 2, 2, 5, 41,
+ 2, 2, 47, 38, 2, 2, 10, 47, 38, 2,
+ 2, 2, 35, 35, 34, 5, 5, 26, 1, 5,
+ 5, 26, 128, 217, 5, 5, 5, 128, 34, 34,
+ 112, 2, 210, 10, 31, 31, 2, 210, 26, 31,
+ 31, 31, 143, 2, 217, 2, 5, 34, 2, 2,
+ 35, 5, 142, 2, 47, 143, 2, 2, 5, 35,
5, 110, 110, 5, 5, 6, 6, 110, 5, 6,
- 6, 5, 5, 142, 6, 6, 6, 221, 144, 210,
- 7, 7, 321, 335, 7, 7, 144, 144, 309, 7,
- 7, 7, 337, 338, 143, 112, 6, 30, 30, 15,
- 15, 6, 30, 30, 15, 15, 15, 143, 6, 110,
- 6, 7, 315, 6, 6, 142, 7, 269, 6, 309,
- 269, 6, 6, 7, 315, 7, 15, 58, 7, 7,
- 58, 15, 340, 7, 19, 19, 7, 7, 15, 19,
- 19, 19, 131, 15, 15, 30, 99, 131, 15, 99,
- 128, 15, 15, 91, 58, 128, 34, 149, 302, 349,
- 149, 19, 350, 302, 302, 302, 19, 99, 157, 91,
- 34, 34, 286, 19, 286, 286, 42, 42, 19, 19,
- 286, 1, 358, 19, 157, 157, 19, 19, 286, 34,
- 286, 3, 286, 286, 286, 286, 286, 286, 286, 286,
- 13, 13, 302, 28, 28, 13, 13, 13, 28, 28,
- 302, 302, 9, 27, 42, 26, 57, 286, 57, 26,
- 29, 286, 286, 42, 286, 286, 32, 13, 100, 100,
- 43, 43, 13, 100, 100, 240, 26, 240, 285, 13,
- 285, 206, 44, 44, 13, 13, 285, 33, 154, 13,
- 154, 28, 13, 13, 285, 37, 285, 206, 285, 285,
- 285, 285, 285, 285, 285, 285, 21, 21, 43, 39,
- 21, 21, 21, 21, 35, 35, 100, 43, 207, 122,
- 44, 46, 53, 285, 122, 122, 122, 285, 285, 44,
- 285, 285, 25, 21, 207, 24, 24, 20, 21, 24,
- 24, 24, 24, 67, 90, 21, 71, 75, 25, 20,
- 21, 21, 35, 76, 239, 21, 239, 166, 21, 21,
- 90, 35, 24, 122, 78, 20, 20, 24, 166, 79,
- 80, 122, 122, 353, 24, 353, 166, 81, 82, 24,
- 24, 353, 86, 238, 24, 238, 88, 24, 24, 353,
- 237, 353, 237, 353, 353, 353, 353, 353, 353, 353,
- 353, 14, 14, 94, 31, 31, 14, 14, 14, 31,
- 31, 31, 236, 270, 236, 92, 92, 270, 353, 235,
- 92, 235, 353, 353, 97, 353, 353, 92, 14, 270,
- 101, 121, 102, 14, 105, 106, 121, 121, 121, 108,
- 14, 109, 114, 92, 117, 14, 14, 171, 31, 171,
- 14, 171, 137, 14, 14, 171, 31, 31, 171, 54,
- 54, 54, 92, 171, 138, 171, 171, 171, 171, 171,
- 171, 171, 171, 171, 171, 121, 139, 147, 161, 162,
- 172, 175, 176, 121, 121, 177, 83, 179, 83, 183,
- 185, 201, 171, 202, 83, 203, 171, 171, 204, 171,
- 171, 83, 83, 208, 83, 209, 83, 83, 83, 83,
- 83, 83, 83, 83, 12, 12, 214, 224, 233, 12,
- 12, 12, 189, 234, 189, 189, 189, 189, 189, 189,
- 189, 83, 243, 245, 246, 83, 83, 247, 83, 83,
- 248, 12, 146, 249, 251, 254, 12, 146, 146, 146,
- 255, 256, 261, 12, 261, 266, 267, 268, 12, 12,
- 261, 280, 284, 12, 287, 288, 12, 12, 261, 289,
- 261, 290, 261, 261, 261, 261, 261, 261, 261, 261,
- 291, 292, 293, 294, 295, 296, 146, 297, 298, 299,
- 322, 304, 322, 306, 146, 146, nil, 261, 322, nil,
- nil, 261, 261, nil, 261, 261, 322, nil, 322, nil,
- 322, 322, 322, 322, 322, 322, 322, 322, 64, 64,
- nil, nil, nil, 64, 64, 64, nil, nil, 223, nil,
- 223, 223, nil, nil, nil, 322, 223, nil, nil, 322,
- 322, nil, 322, 322, 223, 48, 223, nil, 223, 223,
- 223, 223, 223, 223, 223, 223, nil, nil, nil, 48,
- nil, nil, 64, 140, 140, 140, 140, nil, nil, nil,
- 64, 64, nil, 223, nil, nil, 48, 223, 223, nil,
- 223, 223, nil, 48, nil, 48, nil, 48, nil, 48,
- 140, 140, 140, 272, nil, 272, nil, 272, nil, 272,
- 272, 272, 272, 272, 272, 272, 313, nil, 313, nil,
- 313, nil, 313, 313, 313, 313, 313, 313, 313, 314,
- nil, 314, nil, 314, nil, 314, 314, 314, 314, 314,
- 314, 314, 344, nil, 344, nil, 344, nil, 344, 344,
- 344, 344, 344, 344, 344, 345, nil, 345, nil, 345,
- nil, 345, 345, 345, 345, 345, 345, 345, 186, nil,
- 186, nil, 186, nil, 186, 186, 186, 186, 186, 186,
- 186 ]
+ 6, 5, 5, 112, 6, 6, 6, 3, 31, 210,
+ 7, 7, 221, 221, 7, 7, 31, 31, 221, 7,
+ 7, 7, 58, 309, 142, 58, 6, 28, 28, 12,
+ 12, 6, 28, 28, 12, 12, 12, 131, 6, 110,
+ 6, 7, 131, 6, 6, 11, 7, 11, 6, 58,
+ 315, 6, 6, 7, 309, 7, 12, 9, 7, 7,
+ 221, 12, 315, 7, 13, 13, 7, 7, 12, 13,
+ 13, 13, 11, 12, 12, 28, 20, 27, 12, 14,
+ 14, 12, 12, 29, 14, 14, 14, 149, 20, 32,
+ 149, 13, 30, 30, 15, 15, 13, 30, 30, 15,
+ 15, 15, 33, 13, 20, 20, 14, 269, 13, 13,
+ 269, 14, 37, 13, 100, 100, 13, 13, 14, 100,
+ 100, 15, 39, 14, 14, 157, 15, 46, 14, 19,
+ 19, 14, 14, 15, 19, 19, 19, 25, 15, 15,
+ 30, 157, 157, 15, 21, 21, 15, 15, 21, 21,
+ 21, 21, 53, 25, 99, 67, 19, 99, 22, 24,
+ 24, 19, 100, 24, 24, 24, 24, 71, 19, 22,
+ 57, 21, 57, 19, 19, 99, 21, 22, 19, 70,
+ 70, 19, 19, 21, 75, 154, 24, 154, 21, 21,
+ 90, 24, 76, 21, 64, 64, 21, 21, 24, 64,
+ 64, 64, 91, 24, 24, 83, 90, 83, 24, 121,
+ 78, 24, 24, 83, 121, 121, 121, 206, 91, 79,
+ 83, 83, 235, 83, 235, 83, 83, 83, 83, 83,
+ 83, 83, 83, 206, 122, 41, 41, 144, 64, 122,
+ 122, 122, 144, 144, 144, 80, 64, 64, 81, 166,
+ 83, 92, 92, 121, 83, 83, 92, 83, 83, 146,
+ 166, 121, 121, 92, 146, 146, 146, 207, 166, 54,
+ 54, 54, 236, 41, 236, 237, 270, 237, 122, 92,
+ 270, 144, 41, 207, 82, 86, 122, 122, 302, 144,
+ 144, 88, 270, 302, 302, 302, 94, 171, 92, 171,
+ 238, 171, 238, 146, 239, 171, 239, 240, 171, 240,
+ 97, 146, 146, 171, 101, 171, 171, 171, 171, 171,
+ 171, 171, 171, 171, 171, 42, 42, 43, 43, 44,
+ 44, 102, 302, 105, 106, 223, 108, 223, 223, 109,
+ 302, 302, 171, 223, 114, 117, 171, 171, 137, 171,
+ 171, 223, 138, 223, 139, 223, 223, 223, 223, 223,
+ 223, 223, 223, 42, 147, 43, 161, 44, 162, 172,
+ 175, 176, 42, 261, 43, 261, 44, 177, 179, 183,
+ 223, 261, 185, 201, 223, 223, 202, 223, 223, 261,
+ 203, 261, 204, 261, 261, 261, 261, 261, 261, 261,
+ 261, 189, 208, 189, 189, 189, 189, 189, 189, 189,
+ 209, 285, 214, 285, 140, 140, 140, 140, 261, 285,
+ 224, 233, 261, 261, 234, 261, 261, 285, 243, 285,
+ 245, 285, 285, 285, 285, 285, 285, 285, 285, 246,
+ 247, 140, 140, 140, 248, 249, 251, 254, 48, 286,
+ 255, 286, 286, 256, 266, 267, 285, 286, 268, 280,
+ 285, 285, 48, 285, 285, 286, 284, 286, 287, 286,
+ 286, 286, 286, 286, 286, 286, 286, 288, 289, 48,
+ 290, 291, 292, 293, 294, 295, 48, 322, 48, 322,
+ 48, 296, 48, 297, 286, 322, 298, 299, 286, 286,
+ 304, 286, 286, 322, 306, 322, 312, 322, 322, 322,
+ 322, 322, 322, 322, 322, 316, 320, 321, 335, 337,
+ 338, 340, 349, 350, 358, 353, nil, 353, nil, nil,
+ nil, nil, 322, 353, nil, nil, 322, 322, nil, 322,
+ 322, 353, nil, 353, nil, 353, 353, 353, 353, 353,
+ 353, 353, 353, 186, nil, 186, nil, 186, nil, 186,
+ 186, 186, 186, 186, 186, 186, nil, nil, nil, nil,
+ 353, nil, nil, nil, 353, 353, nil, 353, 353, 272,
+ nil, 272, nil, 272, nil, 272, 272, 272, 272, 272,
+ 272, 272, 313, nil, 313, nil, 313, nil, 313, 313,
+ 313, 313, 313, 313, 313, 314, nil, 314, nil, 314,
+ nil, 314, 314, 314, 314, 314, 314, 314, 344, nil,
+ 344, nil, 344, nil, 344, 344, 344, 344, 344, 344,
+ 344, 345, nil, 345, nil, 345, nil, 345, 345, 345,
+ 345, 345, 345, 345 ]
racc_action_pointer = [
- nil, 181, -2, 191, nil, 13, 63, 78, nil, 208,
- 13, 2, 468, 194, 355, 93, nil, nil, nil, 128,
- 291, 260, -17, nil, 289, 274, 209, 207, 198, 211,
- 92, 358, 217, 239, 149, 262, nil, 197, 12, 211,
- nil, 0, 164, 218, 230, nil, 275, -4, 599, nil,
- nil, nil, nil, 277, 414, nil, nil, 211, 123, nil,
- nil, nil, nil, nil, 572, nil, nil, 293, nil, nil,
- 19, 300, nil, nil, nil, 300, 303, nil, 315, 321,
- 323, 330, 331, 442, nil, nil, 332, nil, 337, nil,
- 268, 117, 369, nil, 345, nil, nil, 374, nil, 140,
- 223, 381, 384, nil, nil, 385, 385, nil, 394, 396,
- 56, nil, 45, nil, 396, nil, nil, 394, nil, nil,
- nil, 385, 273, nil, nil, nil, nil, nil, 144, nil,
- nil, 136, nil, nil, nil, nil, nil, 354, 418, 378,
- 609, nil, 67, 88, 28, nil, 496, 430, nil, 152,
- nil, nil, nil, nil, 243, nil, nil, 150, nil, nil,
- nil, 402, 433, nil, nil, nil, 297, nil, nil, nil,
- nil, 403, 433, nil, nil, 434, 435, 438, nil, 440,
- nil, nil, nil, 430, nil, 442, 700, nil, nil, 460,
+ nil, 18, -2, 77, nil, 13, 63, 78, nil, 123,
+ 2, 111, 93, 128, 143, 158, nil, nil, nil, 193,
+ 140, 208, 208, nil, 223, 189, 11, 141, 92, 144,
+ 157, 28, 150, 164, 7, 0, nil, 124, -3, 134,
+ nil, 293, 383, 385, 387, nil, 191, -4, 512, nil,
+ nil, nil, nil, 217, 334, nil, nil, 235, 88, nil,
+ nil, nil, nil, nil, 258, nil, nil, 215, nil, nil,
+ 241, 231, nil, nil, nil, 247, 252, nil, 271, 281,
+ 308, 311, 347, 271, nil, nil, 345, nil, 352, nil,
+ 224, 236, 315, nil, 348, nil, nil, 370, nil, 218,
+ 179, 375, 393, nil, nil, 394, 394, nil, 401, 404,
+ 56, nil, 23, nil, 408, nil, nil, 405, nil, nil,
+ nil, 273, 298, nil, nil, nil, nil, nil, 16, nil,
+ nil, 101, nil, nil, nil, nil, nil, 360, 416, 366,
+ 470, nil, 46, 36, 301, nil, 323, 427, nil, 152,
+ nil, nil, nil, nil, 250, nil, nil, 177, nil, nil,
+ nil, 400, 432, nil, nil, nil, 299, nil, nil, nil,
+ nil, 363, 432, nil, nil, 433, 434, 440, nil, 441,
+ nil, nil, nil, 430, nil, 444, 605, nil, nil, 449,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 433, 435, 437, 440, nil, 205, 242, 444, 446,
- 26, nil, nil, nil, 466, nil, nil, 15, nil, nil,
- nil, 24, nil, 584, 427, nil, nil, nil, nil, nil,
- nil, nil, nil, 472, 477, 375, 368, 346, 339, 310,
- 231, nil, nil, 485, nil, 474, 475, 489, 481, 497,
- nil, 498, nil, nil, 469, 492, 504, nil, nil, nil,
- nil, 508, nil, nil, nil, nil, 459, 509, 498, 95,
- 366, nil, 635, nil, nil, nil, nil, nil, nil, nil,
- 502, nil, nil, nil, 490, 234, 168, 510, 511, 515,
- 517, 526, 527, 528, 529, 530, 531, 533, 534, 543,
- nil, nil, 152, nil, 544, nil, 545, nil, nil, 69,
- nil, nil, 31, 648, 661, 101, 28, nil, nil, nil,
- 23, 50, 546, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 76, nil, 73, 87, nil,
- 125, nil, nil, nil, 674, 687, nil, nil, nil, 127,
- 143, nil, nil, 329, nil, nil, nil, nil, 163, nil ]
+ nil, 435, 438, 442, 444, nil, 251, 301, 453, 461,
+ 26, nil, nil, nil, 472, nil, nil, 17, nil, nil,
+ nil, 77, nil, 401, 440, nil, nil, nil, nil, nil,
+ nil, nil, nil, 485, 488, 288, 338, 341, 366, 370,
+ 373, nil, nil, 491, nil, 481, 490, 502, 495, 509,
+ nil, 510, nil, nil, 481, 502, 516, nil, nil, nil,
+ nil, 439, nil, nil, nil, nil, 468, 518, 509, 155,
+ 339, nil, 631, nil, nil, nil, nil, nil, nil, nil,
+ 510, nil, nil, nil, 504, 477, 515, 524, 533, 534,
+ 536, 537, 538, 539, 540, 541, 547, 549, 552, 561,
+ nil, nil, 352, nil, 563, nil, 566, nil, nil, 74,
+ nil, nil, 569, 644, 657, 109, 566, nil, nil, nil,
+ 554, 555, 553, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 581, nil, 570, 584, nil,
+ 584, nil, nil, nil, 670, 683, nil, nil, nil, 560,
+ 574, nil, nil, 591, nil, nil, nil, nil, 575, nil ]
racc_action_default = [
-1, -229, -10, -229, -2, -6, -7, -8, -9, -229,
@@ -303,14 +299,14 @@ racc_action_default = [
racc_goto_table = [
81, 248, 183, 68, 106, 91, 117, 271, 78, 246,
- 273, 247, 82, 69, 209, 161, 97, 90, 268, 304,
- 89, 119, 54, 57, 354, 355, 318, 60, 61, 62,
- 63, 220, 221, 58, 65, 127, 76, 282, 70, 86,
- 227, 132, 133, 134, 135, 4, 228, 208, 50, 51,
- 52, 122, 159, 308, 119, 140, 67, 352, 66, 162,
- 1, 261, 347, 348, 2, 311, 88, 149, nil, 335,
+ 273, 247, 82, 69, 209, 161, 97, 89, 268, 304,
+ 90, 119, 54, 57, 220, 221, 318, 60, 61, 62,
+ 63, 354, 355, 1, 65, 127, 76, 2, 149, 86,
+ 58, 132, 133, 134, 135, 4, 70, 159, 50, 51,
+ 52, 308, 67, 66, 119, 88, 208, 282, 227, 162,
+ 228, 122, 347, 348, 140, 352, 261, 311, nil, 335,
154, nil, 207, nil, 211, nil, 214, nil, nil, nil,
- nil, nil, nil, nil, 206, nil, 222, 205, nil, 213,
+ nil, nil, nil, nil, 205, nil, 222, 206, nil, 213,
262, 356, nil, 271, nil, nil, nil, nil, nil, nil,
nil, nil, 254, nil, 316, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
@@ -338,14 +334,14 @@ racc_goto_table = [
racc_goto_check = [
35, 62, 18, 17, 51, 41, 51, 77, 32, 58,
- 77, 58, 36, 12, 46, 15, 48, 40, 82, 68,
- 39, 55, 8, 8, 84, 84, 73, 7, 7, 7,
- 7, 70, 70, 10, 7, 61, 7, 52, 11, 7,
- 56, 61, 61, 61, 61, 2, 57, 42, 2, 2,
- 2, 59, 14, 16, 55, 63, 27, 69, 28, 17,
- 1, 74, 73, 73, 3, 81, 38, 9, nil, 68,
+ 77, 58, 36, 12, 46, 15, 48, 39, 82, 68,
+ 40, 55, 8, 8, 70, 70, 73, 7, 7, 7,
+ 7, 84, 84, 1, 7, 61, 7, 3, 9, 7,
+ 10, 61, 61, 61, 61, 2, 11, 14, 2, 2,
+ 2, 16, 27, 28, 55, 38, 42, 52, 56, 17,
+ 57, 59, 73, 73, 63, 69, 74, 81, nil, 68,
8, nil, 41, nil, 41, nil, 51, nil, nil, nil,
- nil, nil, nil, nil, 40, nil, 51, 39, nil, 48,
+ nil, nil, nil, nil, 39, nil, 51, 40, nil, 48,
18, 73, nil, 77, nil, nil, nil, nil, nil, nil,
nil, nil, 15, nil, 82, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
@@ -372,15 +368,15 @@ racc_goto_check = [
nil, nil, 35, 35, 17 ]
racc_goto_pointer = [
- nil, 60, 43, 64, nil, nil, nil, 15, 12, 13,
- 22, 18, -7, nil, -19, -57, -202, -16, -81, nil,
- nil, nil, nil, nil, nil, nil, nil, 37, 39, nil,
- nil, nil, -14, nil, nil, -22, -10, nil, 41, -5,
- -8, -20, -45, nil, nil, nil, -78, nil, -10, nil,
- nil, -24, -180, nil, nil, -10, -81, -76, -135, 17,
- nil, 0, -145, 8, nil, nil, nil, nil, -230, -281,
- -77, nil, nil, -258, -110, nil, nil, -179, nil, nil,
- nil, -201, -168, nil, -320, nil ]
+ nil, 33, 43, 37, nil, nil, nil, 15, 12, -16,
+ 29, 26, -7, nil, -24, -57, -204, -16, -81, nil,
+ nil, nil, nil, nil, nil, nil, nil, 33, 34, nil,
+ nil, nil, -14, nil, nil, -22, -10, nil, 30, -8,
+ -5, -20, -36, nil, nil, nil, -78, nil, -10, nil,
+ nil, -24, -160, nil, nil, -10, -63, -62, -135, 27,
+ nil, 0, -145, 17, nil, nil, nil, nil, -230, -273,
+ -84, nil, nil, -258, -105, nil, nil, -179, nil, nil,
+ nil, -199, -168, nil, -313, nil ]
racc_goto_default = [
nil, nil, nil, nil, 5, 6, 7, 8, nil, nil,
diff --git a/test/racc/regress/edtf b/test/racc/regress/edtf
index 82a59a6454..5947931260 100644
--- a/test/racc/regress/edtf
+++ b/test/racc/regress/edtf
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -132,218 +132,218 @@ module_eval(<<'...end edtf.y/module_eval...', 'edtf.y', 468)
##### State transition tables begin ###
racc_action_table = [
- 208, 207, 52, 111, 236, 112, 149, 129, 128, 57,
- 253, 43, 45, 40, 55, 42, 157, 44, 43, 45,
- 40, -48, 42, 53, 44, 254, 58, 46, 47, 48,
- 49, 50, 207, 56, 46, 47, 48, 49, 50, 128,
- 94, 255, 43, 45, 40, 244, 42, 239, 44, 43,
- 45, 40, 55, 42, 54, 44, 202, 95, 46, 47,
- 48, 49, 50, 25, 141, 46, 47, 48, 49, 50,
- 12, 56, 43, 45, 40, 55, 42, 214, 44, 148,
- 55, 233, 147, 258, 92, 36, 193, 192, 46, 47,
- 48, 49, 50, 25, 56, 26, 57, 232, 234, 56,
- 12, 93, 43, 45, 40, 261, 42, 159, 44, 111,
- 33, 112, 34, 58, 111, 36, 112, 180, 46, 47,
- 48, 49, 50, 87, 58, 108, 12, 165, 43, 45,
- 40, 101, 42, 103, 44, 104, 178, 111, 166, 112,
- 111, 36, 112, 167, 46, 47, 48, 49, 50, 87,
- 218, 200, 12, 201, 43, 45, 40, 188, 42, 186,
- 44, 187, 111, 190, 112, 177, 111, 36, 112, 168,
- 46, 47, 48, 49, 50, 69, 264, 43, 45, 189,
- 191, 42, 124, 44, 12, 125, 43, 45, 40, 240,
- 42, 239, 44, 46, 47, 48, 49, 50, 265, 36,
- 133, 192, 46, 47, 48, 49, 50, 12, 266, 43,
- 45, 40, 111, 42, 112, 44, 12, 158, 43, 45,
- 40, 269, 42, 270, 44, 46, 47, 48, 49, 50,
- 156, 36, 154, 153, 46, 47, 48, 49, 50, 12,
- 275, 43, 45, 40, 152, 42, 150, 44, 146, 43,
- 45, 40, 125, 42, 36, 44, 280, 46, 47, 48,
- 49, 50, 124, 284, 285, 46, 47, 48, 49, 50,
- 43, 45, 40, 286, 42, 96, 44, 43, 45, 40,
- -66, 42, -65, 44, 290, 67, 46, 47, 48, 49,
- 50, 292, 293, 46, 47, 48, 49, 50, 43, 45,
- 40, 66, 42, 295, 44, 43, 45, 40, 296, 42,
- 297, 44, 65, 300, 46, 47, 48, 49, 50, 301,
- 180, 46, 47, 48, 49, 50, 43, 45, 40, 303,
- 42, 304, 44, 43, 45, 40, 305, 42, 281, 44,
- 306, 307, 46, 47, 48, 49, 50, 308, 64, 46,
- 47, 48, 49, 50, 43, 45, 40, -50, 42, 311,
- 44, 43, 45, 40, 312, 42, 313, 44, 314, 51,
- 46, 47, 48, 49, 50, 316, 317, 46, 47, 48,
- 49, 50, 43, 45, 318, 215, 42, 319, 44, 43,
- 45, 40, 213, 42, 212, 44, 229, 210, 46, 47,
- 48, 49, 50, 180, 209, 46, 47, 48, 49, 50,
- 43, 45, 180, nil, 42, nil, 44, 43, 45, 40,
- nil, 42, nil, 44, nil, nil, 46, 47, 48, 49,
- 50, nil, nil, 46, 47, 48, 49, 50, 43, 45,
+ 129, 128, 52, 111, 51, 112, 149, 208, 207, 57,
+ -50, 43, 45, 40, 55, 42, 54, 44, 43, 45,
+ 40, -48, 42, 53, 44, 64, 58, 46, 47, 48,
+ 49, 50, 128, 56, 46, 47, 48, 49, 50, 207,
+ 57, 65, 43, 45, 40, 55, 42, 157, 44, 43,
+ 45, 40, 55, 42, 214, 44, 92, 58, 46, 47,
+ 48, 49, 50, 66, 56, 46, 47, 48, 49, 50,
+ 25, 56, 26, 93, 94, 67, 108, 12, -65, 43,
+ 45, 40, -66, 42, 159, 44, 110, 33, 111, 34,
+ 112, 95, 36, 25, 141, 46, 47, 48, 49, 50,
+ 12, 58, 43, 45, 40, 101, 42, 103, 44, 104,
+ 96, 148, 55, 133, 147, 36, 124, 125, 46, 47,
+ 48, 49, 50, 87, 165, 111, 12, 112, 43, 45,
+ 40, 56, 42, 146, 44, 166, 111, 150, 112, 218,
+ 167, 36, 152, 153, 46, 47, 48, 49, 50, 87,
+ 108, 111, 12, 112, 43, 45, 40, 188, 42, 186,
+ 44, 187, 111, 190, 112, 154, 111, 36, 112, 156,
+ 46, 47, 48, 49, 50, 69, 158, 43, 45, 189,
+ 191, 42, 12, 44, 43, 45, 40, 200, 42, 201,
+ 44, 168, 177, 46, 47, 48, 49, 50, 233, 178,
+ 46, 47, 48, 49, 50, 12, 180, 43, 45, 40,
+ 111, 42, 112, 44, 232, 234, 111, 240, 112, 239,
+ 36, 192, 193, 46, 47, 48, 49, 50, 12, 202,
+ 43, 45, 40, 118, 42, 117, 44, 104, 118, 121,
+ 117, 209, 104, 36, 121, 210, 46, 47, 48, 49,
+ 50, 12, 212, 43, 45, 40, 244, 42, 239, 44,
+ 213, 43, 45, 40, 215, 42, 36, 44, 229, 46,
+ 47, 48, 49, 50, 180, 180, 236, 46, 47, 48,
+ 49, 50, 43, 45, 40, 253, 42, 254, 44, 43,
+ 45, 40, 255, 42, 258, 44, 261, 264, 46, 47,
+ 48, 49, 50, 124, 125, 46, 47, 48, 49, 50,
+ 43, 45, 40, 265, 42, 192, 44, 43, 45, 266,
+ 269, 42, 270, 44, 275, 280, 46, 47, 48, 49,
+ 50, 284, 285, 46, 47, 48, 49, 50, 43, 45,
+ 40, 286, 42, 290, 44, 43, 45, 292, 293, 42,
+ 295, 44, 296, 297, 46, 47, 48, 49, 50, 300,
+ 301, 46, 47, 48, 49, 50, 43, 45, 40, 180,
+ 42, 303, 44, 43, 45, 40, 304, 42, 305, 44,
+ 281, 306, 46, 47, 48, 49, 50, 307, 308, 46,
+ 47, 48, 49, 50, 43, 45, 175, 311, 42, 312,
+ 44, 43, 45, 40, 313, 42, 314, 44, 316, 317,
+ 46, 47, 48, 49, 50, 318, 319, 46, 47, 48,
+ 49, 50, 43, 45, nil, nil, 42, nil, 44, 43,
+ 45, nil, nil, 42, nil, 44, nil, nil, 46, 47,
+ 48, 49, 50, nil, nil, 46, 47, 48, 49, 50,
+ 172, 194, 170, nil, 171, nil, 173, 43, 45, 40,
+ nil, 42, nil, 44, nil, nil, 195, 196, 197, 198,
+ 199, nil, nil, 46, 47, 48, 49, 50, 43, 45,
40, nil, 42, nil, 44, 43, 45, 40, nil, 42,
nil, 44, nil, nil, 46, 47, 48, 49, 50, nil,
nil, 46, 47, 48, 49, 50, 43, 45, 40, nil,
- 42, nil, 44, 43, 45, 276, nil, 42, nil, 44,
+ 42, nil, 44, 43, 45, nil, nil, 42, nil, 44,
nil, nil, 46, 47, 48, 49, 50, nil, nil, 46,
- 47, 48, 49, 50, 43, 45, 274, nil, 42, nil,
- 44, 43, 45, 273, nil, 42, nil, 44, nil, nil,
+ 47, 48, 49, 50, 43, 45, 40, nil, 42, nil,
+ 44, 43, 45, 40, nil, 42, nil, 44, nil, nil,
46, 47, 48, 49, 50, nil, nil, 46, 47, 48,
49, 50, 43, 45, 40, nil, 42, nil, 44, 43,
- 45, 175, nil, 42, nil, 44, nil, nil, 46, 47,
+ 45, 40, nil, 42, nil, 44, nil, nil, 46, 47,
48, 49, 50, nil, nil, 46, 47, 48, 49, 50,
- 43, 45, 40, nil, 42, nil, 44, 43, 45, 40,
+ 43, 45, nil, nil, 42, nil, 44, 43, 45, 40,
nil, 42, nil, 44, nil, nil, 46, 47, 48, 49,
50, nil, nil, 46, 47, 48, 49, 50, 43, 45,
- nil, nil, 42, nil, 44, 43, 45, nil, nil, 42,
+ 40, nil, 42, nil, 44, 43, 45, 273, nil, 42,
nil, 44, nil, nil, 46, 47, 48, 49, 50, nil,
- nil, 46, 47, 48, 49, 50, 43, 45, 315, nil,
- 42, nil, 44, 43, 45, 40, nil, 42, nil, 44,
+ nil, 46, 47, 48, 49, 50, 43, 45, 274, nil,
+ 42, nil, 44, 43, 45, 276, nil, 42, nil, 44,
nil, nil, 46, 47, 48, 49, 50, nil, nil, 46,
- 47, 48, 49, 50, 43, 45, nil, nil, 42, nil,
- 44, 172, 194, 170, nil, 171, nil, 173, nil, nil,
- 46, 47, 48, 49, 50, nil, nil, 195, 196, 197,
- 198, 199, 43, 45, 40, nil, 42, nil, 44, 43,
+ 47, 48, 49, 50, 43, 45, 40, nil, 42, nil,
+ 44, 43, 45, 40, nil, 42, nil, 44, nil, nil,
+ 46, 47, 48, 49, 50, nil, nil, 46, 47, 48,
+ 49, 50, 43, 45, 40, nil, 42, nil, 44, 43,
45, 40, nil, 42, nil, 44, nil, nil, 46, 47,
48, 49, 50, nil, nil, 46, 47, 48, 49, 50,
- 43, 45, 40, nil, 42, nil, 44, 43, 45, 40,
+ 43, 45, 40, nil, 42, nil, 44, 43, 45, 315,
nil, 42, nil, 44, nil, nil, 46, 47, 48, 49,
- 50, nil, nil, 46, 47, 48, 49, 50, 43, 45,
- nil, nil, 42, nil, 44, 43, 45, 40, nil, 42,
- nil, 44, nil, nil, 46, 47, 48, 49, 50, 116,
- nil, 46, 47, 48, 49, 50, 118, 250, 247, 118,
- 104, 117, 249, 104, 260, 121, nil, 288, nil, 118,
- 250, 247, 251, 104, 118, 249, 117, 118, 104, 117,
- 121, 104, nil, 121, nil, 251, 118, 250, 247, nil,
- 104, 281, 249, 118, 250, 310, nil, 104, nil, 249,
- nil, 118, 251, 117, nil, 104, nil, 121, 108, 251,
- 118, 250, 117, 118, 104, 117, 249, 104, 110, 121,
- 111, nil, 112, 182, 184, nil, 251, 181, 118, 183,
- 117, 118, 104, 117, 121, 104, 118, 121, 117, 118,
- 104, 117, 121, 104, 118, 121, 117, nil, 104, nil,
- 121, 188, 271, 186, 118, 187, 117, 272, 104, 118,
- 121, 117, nil, 104, nil, 121, 172, 169, 170, 118,
- 171, 117, 173, 104, 118, 121, 117, nil, 104, nil,
- 121 ]
+ 50, 116, nil, 46, 47, 48, 49, 50, 118, 250,
+ 247, 118, 104, 117, 249, 104, 260, 121, nil, 281,
+ nil, nil, nil, nil, 251, nil, 118, 288, 117, 118,
+ 104, 117, 121, 104, 118, 121, 117, 118, 104, 117,
+ 121, 104, nil, 121, 118, 250, 247, nil, 104, nil,
+ 249, 118, 250, 247, nil, 104, nil, 249, nil, nil,
+ 251, nil, 118, 250, 117, nil, 104, 251, 249, 118,
+ 250, 310, nil, 104, nil, 249, nil, nil, 251, nil,
+ 172, 169, 170, nil, 171, 251, 173, 182, 184, nil,
+ 118, 181, 117, 183, 104, 118, 121, 117, 118, 104,
+ 117, 121, 104, 118, 121, 117, 118, 104, 117, 121,
+ 104, 118, 121, 117, nil, 104, nil, 121, 188, 271,
+ 186, 118, 187, 117, 272, 104, nil, 121 ]
racc_action_check = [
- 127, 127, 5, 93, 163, 93, 73, 63, 63, 73,
- 169, 127, 127, 127, 89, 127, 89, 127, 63, 63,
- 63, 5, 63, 5, 63, 178, 73, 127, 127, 127,
- 127, 127, 224, 89, 63, 63, 63, 63, 63, 151,
- 38, 189, 224, 224, 224, 167, 224, 167, 224, 151,
- 151, 151, 9, 151, 9, 151, 123, 38, 224, 224,
- 224, 224, 224, 67, 67, 151, 151, 151, 151, 151,
- 67, 9, 67, 67, 67, 134, 67, 134, 67, 72,
- 72, 161, 72, 202, 37, 67, 116, 115, 67, 67,
- 67, 67, 67, 0, 134, 0, 10, 161, 161, 72,
- 0, 37, 0, 0, 0, 213, 0, 91, 0, 124,
- 0, 124, 0, 10, 56, 0, 56, 109, 0, 0,
- 0, 0, 0, 33, 91, 214, 33, 98, 33, 33,
- 33, 52, 33, 52, 33, 52, 108, 214, 98, 214,
- 92, 33, 92, 98, 33, 33, 33, 33, 33, 34,
- 147, 121, 34, 121, 34, 34, 34, 112, 34, 112,
- 34, 112, 147, 113, 147, 107, 157, 34, 157, 99,
- 34, 34, 34, 34, 34, 26, 218, 26, 26, 113,
- 113, 26, 220, 26, 154, 222, 154, 154, 154, 166,
- 154, 166, 154, 26, 26, 26, 26, 26, 225, 154,
- 66, 230, 154, 154, 154, 154, 154, 87, 232, 87,
- 87, 87, 66, 87, 66, 87, 265, 90, 265, 265,
- 265, 236, 265, 238, 265, 87, 87, 87, 87, 87,
- 88, 265, 79, 78, 265, 265, 265, 265, 265, 153,
- 245, 153, 153, 153, 77, 153, 74, 153, 71, 205,
- 205, 205, 60, 205, 153, 205, 253, 153, 153, 153,
- 153, 153, 59, 256, 257, 205, 205, 205, 205, 205,
- 150, 150, 150, 260, 150, 51, 150, 12, 12, 12,
- 24, 12, 23, 12, 264, 22, 150, 150, 150, 150,
- 150, 267, 268, 12, 12, 12, 12, 12, 13, 13,
- 13, 18, 13, 271, 13, 263, 263, 263, 273, 263,
- 274, 263, 17, 280, 13, 13, 13, 13, 13, 281,
- 283, 263, 263, 263, 263, 263, 262, 262, 262, 284,
- 262, 285, 262, 36, 36, 36, 288, 36, 290, 36,
- 292, 293, 262, 262, 262, 262, 262, 295, 16, 36,
- 36, 36, 36, 36, 251, 251, 251, 14, 251, 300,
- 251, 62, 62, 62, 304, 62, 307, 62, 308, 1,
- 251, 251, 251, 251, 251, 311, 312, 62, 62, 62,
- 62, 62, 64, 64, 313, 144, 64, 316, 64, 68,
- 68, 68, 133, 68, 132, 68, 158, 129, 64, 64,
- 64, 64, 64, 160, 128, 68, 68, 68, 68, 68,
- 69, 69, 162, nil, 69, nil, 69, 70, 70, 70,
- nil, 70, nil, 70, nil, nil, 69, 69, 69, 69,
- 69, nil, nil, 70, 70, 70, 70, 70, 250, 250,
- 250, nil, 250, nil, 250, 249, 249, 249, nil, 249,
- nil, 249, nil, nil, 250, 250, 250, 250, 250, nil,
- nil, 249, 249, 249, 249, 249, 75, 75, 75, nil,
- 75, nil, 75, 247, 247, 247, nil, 247, nil, 247,
- nil, nil, 75, 75, 75, 75, 75, nil, nil, 247,
- 247, 247, 247, 247, 244, 244, 244, nil, 244, nil,
- 244, 240, 240, 240, nil, 240, nil, 240, nil, nil,
- 244, 244, 244, 244, 244, nil, nil, 240, 240, 240,
- 240, 240, 217, 217, 217, nil, 217, nil, 217, 103,
- 103, 103, nil, 103, nil, 103, nil, nil, 217, 217,
- 217, 217, 217, nil, nil, 103, 103, 103, 103, 103,
- 104, 104, 104, nil, 104, nil, 104, 216, 216, 216,
- nil, 216, nil, 216, nil, nil, 104, 104, 104, 104,
- 104, nil, nil, 216, 216, 216, 216, 216, 215, 215,
- nil, nil, 215, nil, 215, 111, 111, nil, nil, 111,
- nil, 111, nil, nil, 215, 215, 215, 215, 215, nil,
- nil, 111, 111, 111, 111, 111, 310, 310, 310, nil,
- 310, nil, 310, 149, 149, 149, nil, 149, nil, 149,
- nil, nil, 310, 310, 310, 310, 310, nil, nil, 149,
- 149, 149, 149, 149, 117, 117, nil, nil, 117, nil,
- 117, 118, 118, 118, nil, 118, nil, 118, nil, nil,
- 117, 117, 117, 117, 117, nil, nil, 118, 118, 118,
- 118, 118, 126, 126, 126, nil, 126, nil, 126, 130,
- 130, 130, nil, 130, nil, 130, nil, nil, 126, 126,
- 126, 126, 126, nil, nil, 130, 130, 130, 130, 130,
- 143, 143, 143, nil, 143, nil, 143, 145, 145, 145,
- nil, 145, nil, 145, nil, nil, 143, 143, 143, 143,
- 143, nil, nil, 145, 145, 145, 145, 145, 146, 146,
- nil, nil, 146, nil, 146, 148, 148, 148, nil, 148,
- nil, 148, nil, nil, 146, 146, 146, 146, 146, 57,
- nil, 148, 148, 148, 148, 148, 168, 168, 168, 57,
- 168, 57, 168, 57, 212, 57, nil, 261, nil, 275,
- 275, 275, 168, 275, 212, 275, 212, 261, 212, 261,
- 212, 261, nil, 261, nil, 275, 270, 270, 270, nil,
- 270, 254, 270, 297, 297, 297, nil, 297, nil, 297,
- nil, 254, 270, 254, nil, 254, nil, 254, 54, 297,
- 296, 296, 296, 95, 296, 95, 296, 95, 54, 95,
- 54, nil, 54, 110, 110, nil, 296, 110, 94, 110,
- 94, 58, 94, 58, 94, 58, 191, 58, 191, 190,
- 191, 190, 191, 190, 255, 190, 255, nil, 255, nil,
- 255, 239, 239, 239, 125, 239, 125, 239, 125, 234,
- 125, 234, nil, 234, nil, 234, 101, 101, 101, 233,
- 101, 233, 101, 233, 159, 233, 159, nil, 159, nil,
- 159 ]
+ 63, 63, 5, 56, 1, 56, 73, 127, 127, 73,
+ 14, 63, 63, 63, 9, 63, 9, 63, 127, 127,
+ 127, 5, 127, 5, 127, 16, 73, 63, 63, 63,
+ 63, 63, 151, 9, 127, 127, 127, 127, 127, 224,
+ 10, 17, 151, 151, 151, 89, 151, 89, 151, 224,
+ 224, 224, 134, 224, 134, 224, 37, 10, 151, 151,
+ 151, 151, 151, 18, 89, 224, 224, 224, 224, 224,
+ 0, 134, 0, 37, 38, 22, 54, 0, 23, 0,
+ 0, 0, 24, 0, 91, 0, 54, 0, 54, 0,
+ 54, 38, 0, 67, 67, 0, 0, 0, 0, 0,
+ 67, 91, 67, 67, 67, 52, 67, 52, 67, 52,
+ 51, 72, 72, 66, 72, 67, 59, 60, 67, 67,
+ 67, 67, 67, 33, 98, 66, 33, 66, 33, 33,
+ 33, 72, 33, 71, 33, 98, 92, 74, 92, 147,
+ 98, 33, 77, 78, 33, 33, 33, 33, 33, 34,
+ 214, 147, 34, 147, 34, 34, 34, 112, 34, 112,
+ 34, 112, 214, 113, 214, 79, 93, 34, 93, 88,
+ 34, 34, 34, 34, 34, 26, 90, 26, 26, 113,
+ 113, 26, 87, 26, 87, 87, 87, 121, 87, 121,
+ 87, 99, 107, 26, 26, 26, 26, 26, 161, 108,
+ 87, 87, 87, 87, 87, 153, 109, 153, 153, 153,
+ 124, 153, 124, 153, 161, 161, 157, 166, 157, 166,
+ 153, 115, 116, 153, 153, 153, 153, 153, 154, 123,
+ 154, 154, 154, 58, 154, 58, 154, 58, 94, 58,
+ 94, 128, 94, 154, 94, 129, 154, 154, 154, 154,
+ 154, 265, 132, 265, 265, 265, 167, 265, 167, 265,
+ 133, 12, 12, 12, 144, 12, 265, 12, 158, 265,
+ 265, 265, 265, 265, 160, 162, 163, 12, 12, 12,
+ 12, 12, 13, 13, 13, 169, 13, 178, 13, 36,
+ 36, 36, 189, 36, 202, 36, 213, 218, 13, 13,
+ 13, 13, 13, 220, 222, 36, 36, 36, 36, 36,
+ 62, 62, 62, 225, 62, 230, 62, 64, 64, 232,
+ 236, 64, 238, 64, 245, 253, 62, 62, 62, 62,
+ 62, 256, 257, 64, 64, 64, 64, 64, 68, 68,
+ 68, 260, 68, 264, 68, 69, 69, 267, 268, 69,
+ 271, 69, 273, 274, 68, 68, 68, 68, 68, 280,
+ 281, 69, 69, 69, 69, 69, 70, 70, 70, 283,
+ 70, 284, 70, 75, 75, 75, 285, 75, 288, 75,
+ 290, 292, 70, 70, 70, 70, 70, 293, 295, 75,
+ 75, 75, 75, 75, 103, 103, 103, 300, 103, 304,
+ 103, 104, 104, 104, 307, 104, 308, 104, 311, 312,
+ 103, 103, 103, 103, 103, 313, 316, 104, 104, 104,
+ 104, 104, 111, 111, nil, nil, 111, nil, 111, 117,
+ 117, nil, nil, 117, nil, 117, nil, nil, 111, 111,
+ 111, 111, 111, nil, nil, 117, 117, 117, 117, 117,
+ 118, 118, 118, nil, 118, nil, 118, 126, 126, 126,
+ nil, 126, nil, 126, nil, nil, 118, 118, 118, 118,
+ 118, nil, nil, 126, 126, 126, 126, 126, 130, 130,
+ 130, nil, 130, nil, 130, 143, 143, 143, nil, 143,
+ nil, 143, nil, nil, 130, 130, 130, 130, 130, nil,
+ nil, 143, 143, 143, 143, 143, 145, 145, 145, nil,
+ 145, nil, 145, 146, 146, nil, nil, 146, nil, 146,
+ nil, nil, 145, 145, 145, 145, 145, nil, nil, 146,
+ 146, 146, 146, 146, 148, 148, 148, nil, 148, nil,
+ 148, 149, 149, 149, nil, 149, nil, 149, nil, nil,
+ 148, 148, 148, 148, 148, nil, nil, 149, 149, 149,
+ 149, 149, 150, 150, 150, nil, 150, nil, 150, 205,
+ 205, 205, nil, 205, nil, 205, nil, nil, 150, 150,
+ 150, 150, 150, nil, nil, 205, 205, 205, 205, 205,
+ 215, 215, nil, nil, 215, nil, 215, 216, 216, 216,
+ nil, 216, nil, 216, nil, nil, 215, 215, 215, 215,
+ 215, nil, nil, 216, 216, 216, 216, 216, 217, 217,
+ 217, nil, 217, nil, 217, 240, 240, 240, nil, 240,
+ nil, 240, nil, nil, 217, 217, 217, 217, 217, nil,
+ nil, 240, 240, 240, 240, 240, 244, 244, 244, nil,
+ 244, nil, 244, 247, 247, 247, nil, 247, nil, 247,
+ nil, nil, 244, 244, 244, 244, 244, nil, nil, 247,
+ 247, 247, 247, 247, 249, 249, 249, nil, 249, nil,
+ 249, 250, 250, 250, nil, 250, nil, 250, nil, nil,
+ 249, 249, 249, 249, 249, nil, nil, 250, 250, 250,
+ 250, 250, 251, 251, 251, nil, 251, nil, 251, 262,
+ 262, 262, nil, 262, nil, 262, nil, nil, 251, 251,
+ 251, 251, 251, nil, nil, 262, 262, 262, 262, 262,
+ 263, 263, 263, nil, 263, nil, 263, 310, 310, 310,
+ nil, 310, nil, 310, nil, nil, 263, 263, 263, 263,
+ 263, 57, nil, 310, 310, 310, 310, 310, 168, 168,
+ 168, 57, 168, 57, 168, 57, 212, 57, nil, 254,
+ nil, nil, nil, nil, 168, nil, 212, 261, 212, 254,
+ 212, 254, 212, 254, 95, 254, 95, 261, 95, 261,
+ 95, 261, nil, 261, 270, 270, 270, nil, 270, nil,
+ 270, 275, 275, 275, nil, 275, nil, 275, nil, nil,
+ 270, nil, 296, 296, 296, nil, 296, 275, 296, 297,
+ 297, 297, nil, 297, nil, 297, nil, nil, 296, nil,
+ 101, 101, 101, nil, 101, 297, 101, 110, 110, nil,
+ 125, 110, 125, 110, 125, 159, 125, 159, 190, 159,
+ 190, 159, 190, 191, 190, 191, 233, 191, 233, 191,
+ 233, 234, 233, 234, nil, 234, nil, 234, 239, 239,
+ 239, 255, 239, 255, 239, 255, nil, 255 ]
racc_action_pointer = [
- 86, 369, nil, nil, nil, 0, nil, nil, nil, 40,
- 82, nil, 261, 282, 336, nil, 344, 289, 287, nil,
- nil, nil, 264, 282, 280, nil, 161, nil, nil, nil,
- nil, nil, nil, 112, 138, nil, 317, 70, 26, nil,
+ 63, 4, nil, nil, nil, 0, nil, nil, nil, 2,
+ 26, nil, 245, 266, -11, nil, 21, 18, 49, nil,
+ nil, nil, 54, 78, 82, nil, 161, nil, nil, nil,
+ nil, nil, nil, 112, 138, nil, 273, 42, 60, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 275, 115, nil, 792, nil, 96, 733, 805, 248,
- 238, nil, 345, 2, 366, nil, 194, 56, 373, 394,
- 401, 244, 68, -5, 235, 450, nil, 219, 205, 204,
- nil, nil, nil, nil, nil, nil, nil, 193, 203, 2,
- 187, 93, 122, -15, 802, 787, nil, nil, 124, 154,
- nil, 840, nil, 513, 534, nil, nil, 153, 130, 105,
- 797, 569, 141, 149, nil, 75, 80, 618, 625, nil,
- nil, 133, nil, 26, 91, 828, 646, -5, 398, 392,
- 653, nil, 380, 386, 63, nil, nil, nil, nil, nil,
- nil, nil, nil, 674, 381, 681, 702, 144, 709, 597,
- 254, 33, nil, 225, 170, nil, nil, 148, 384, 848,
- 391, 67, 400, -26, nil, nil, 171, 27, 730, -5,
- nil, nil, nil, nil, nil, nil, nil, nil, 11, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 29,
- 813, 810, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 71, nil, nil, 233, nil, nil, nil, nil,
- nil, nil, 748, 91, 119, 562, 541, 506, 170, nil,
- 168, nil, 171, nil, 26, 170, nil, nil, nil, nil,
- 189, nil, 196, 843, 833, nil, 209, nil, 208, 825,
- 485, nil, nil, nil, 478, 225, nil, 457, nil, 429,
- 422, 338, nil, 238, 775, 818, 233, 234, nil, nil,
- 267, 751, 310, 289, 270, 202, nil, 261, 262, nil,
- 760, 288, nil, 293, 295, 743, nil, nil, nil, nil,
- 295, 313, nil, 308, 317, 319, nil, nil, 330, nil,
- 332, nil, 328, 329, nil, 329, 784, 767, nil, nil,
- 344, nil, nil, nil, 334, nil, nil, 336, 350, nil,
- 590, 357, 364, 372, nil, nil, 369, nil, nil, nil ]
+ nil, 110, 89, nil, 70, nil, -15, 745, 217, 102,
+ 103, nil, 294, -5, 301, nil, 107, 86, 322, 329,
+ 350, 129, 100, -5, 126, 357, nil, 117, 115, 137,
+ nil, nil, nil, nil, nil, nil, nil, 168, 142, 33,
+ 146, 70, 118, 148, 222, 768, nil, nil, 121, 176,
+ nil, 814, nil, 378, 385, nil, nil, 180, 193, 194,
+ 821, 406, 141, 149, nil, 209, 216, 413, 434, nil,
+ nil, 169, nil, 199, 192, 824, 441, 2, 235, 240,
+ 462, nil, 238, 254, 40, nil, nil, nil, nil, nil,
+ nil, nil, nil, 469, 260, 490, 497, 133, 518, 525,
+ 546, 26, nil, 191, 214, nil, nil, 198, 256, 829,
+ 262, 184, 263, 246, nil, nil, 199, 238, 742, 270,
+ nil, nil, nil, nil, nil, nil, nil, nil, 273, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 280,
+ 832, 837, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 282, nil, nil, 553, nil, nil, nil, nil,
+ nil, nil, 760, 282, 144, 574, 581, 602, 291, nil,
+ 289, nil, 290, nil, 33, 285, nil, nil, nil, nil,
+ 303, nil, 307, 840, 845, nil, 308, nil, 307, 852,
+ 609, nil, nil, nil, 630, 309, nil, 637, nil, 658,
+ 665, 686, nil, 307, 763, 855, 301, 302, nil, nil,
+ 335, 771, 693, 714, 329, 237, nil, 317, 318, nil,
+ 778, 335, nil, 337, 338, 785, nil, nil, nil, nil,
+ 341, 354, nil, 357, 359, 364, nil, nil, 372, nil,
+ 374, nil, 369, 375, nil, 370, 796, 803, nil, nil,
+ 382, nil, nil, nil, 369, nil, nil, 374, 388, nil,
+ 721, 390, 397, 403, nil, nil, 398, nil, nil, nil ]
racc_action_default = [
-176, -176, -1, -2, -3, -4, -5, -6, -7, -8,
@@ -381,22 +381,22 @@ racc_action_default = [
racc_goto_table = [
70, 179, 130, 13, 228, 11, 248, 115, 123, 226,
- 227, 113, 245, 5, 10, 23, 63, 11, 68, 9,
- 22, 132, 14, 18, 71, 2, 60, 24, 77, 88,
- 102, 59, 237, 243, 309, 309, 75, 75, 131, 241,
- 241, 15, 16, 70, 162, 163, 17, 160, 161, 242,
- 91, 100, 231, 135, 235, 89, 298, 99, 164, 98,
- 109, 143, 97, 27, 28, 126, 127, 144, 29, 30,
- 75, 142, 11, 145, 31, 204, 32, 174, 151, 203,
- 136, 10, 137, 61, 217, 185, 134, 140, 6, 138,
- 18, 174, 11, 1, 139, 225, 4, 3, 90, 105,
- 155, 60, 299, nil, nil, nil, 59, 176, 248, 230,
+ 227, 113, 245, 5, 14, 9, 63, 11, 68, 10,
+ 18, 132, 22, 23, 71, 1, 24, 59, 237, 243,
+ 2, 60, 309, 309, 241, 241, 75, 75, 131, 77,
+ 88, 3, 4, 70, 162, 163, 6, 160, 161, 61,
+ 97, 89, 231, 98, 235, 91, 164, 99, 298, 100,
+ 242, 143, 102, 299, 15, 126, 127, 144, 16, 17,
+ 75, 142, 11, 145, 135, 204, 109, 174, 151, 203,
+ 136, 138, 134, 27, 217, 185, 10, 18, 28, 140,
+ 137, 174, 11, 139, 29, 30, 31, 32, 225, 90,
+ 155, 105, 59, nil, nil, nil, 60, 176, 248, 230,
nil, nil, nil, 248, 294, 228, nil, nil, nil, nil,
131, 291, nil, nil, nil, nil, nil, nil, nil, 205,
206, nil, nil, 211, 248, 248, nil, nil, nil, nil,
256, 257, nil, nil, nil, nil, 142, nil, 216, nil,
nil, nil, nil, 262, 224, 223, 75, 75, nil, nil,
- nil, nil, 259, 221, 222, nil, nil, 219, 220, 220,
+ nil, nil, 259, 219, 220, 220, nil, nil, 221, 222,
nil, nil, nil, nil, nil, 302, nil, nil, nil, nil,
nil, nil, nil, 267, 268, nil, nil, nil, nil, 131,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
@@ -412,22 +412,22 @@ racc_goto_table = [
racc_goto_check = [
43, 45, 52, 23, 58, 11, 66, 26, 26, 57,
- 57, 24, 16, 5, 10, 40, 23, 11, 42, 9,
- 38, 24, 30, 34, 53, 2, 10, 41, 54, 54,
- 28, 9, 19, 19, 22, 22, 23, 23, 43, 25,
- 25, 31, 32, 43, 26, 26, 33, 24, 24, 20,
- 10, 18, 45, 39, 45, 9, 17, 15, 14, 13,
- 44, 42, 12, 46, 47, 23, 23, 53, 48, 49,
- 23, 23, 11, 23, 50, 26, 51, 43, 23, 24,
- 5, 10, 40, 7, 52, 43, 9, 38, 6, 30,
- 34, 43, 11, 1, 41, 56, 4, 3, 61, 65,
- 5, 10, 29, nil, nil, nil, 9, 23, 66, 26,
+ 57, 24, 16, 5, 30, 9, 23, 11, 42, 10,
+ 34, 24, 38, 40, 53, 1, 41, 9, 19, 19,
+ 2, 10, 22, 22, 25, 25, 23, 23, 43, 54,
+ 54, 3, 4, 43, 26, 26, 6, 24, 24, 7,
+ 12, 9, 45, 13, 45, 10, 14, 15, 17, 18,
+ 20, 42, 28, 29, 31, 23, 23, 53, 32, 33,
+ 23, 23, 11, 23, 39, 26, 44, 43, 23, 24,
+ 5, 30, 9, 46, 52, 43, 10, 34, 47, 38,
+ 40, 43, 11, 41, 48, 49, 50, 51, 56, 61,
+ 5, 65, 9, nil, nil, nil, 10, 23, 66, 26,
nil, nil, nil, 66, 16, 58, nil, nil, nil, nil,
43, 57, nil, nil, nil, nil, nil, nil, nil, 23,
23, nil, nil, 23, 66, 66, nil, nil, nil, nil,
26, 26, nil, nil, nil, nil, 23, nil, 23, nil,
nil, nil, nil, 52, 23, 11, 23, 23, nil, nil,
- nil, nil, 26, 10, 10, nil, nil, 9, 9, 9,
+ nil, nil, 26, 9, 9, 9, nil, nil, 10, 10,
nil, nil, nil, nil, nil, 45, nil, nil, nil, nil,
nil, nil, nil, 26, 26, nil, nil, nil, nil, 43,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
@@ -442,13 +442,13 @@ racc_goto_check = [
nil, nil, nil, nil, 43 ]
racc_goto_pointer = [
- nil, 93, 25, 97, 96, 13, 88, 71, nil, 19,
- 14, 5, 10, 7, -40, 5, -156, -219, -1, -134,
- -118, nil, -262, 3, -45, -127, -50, nil, -22, -173,
- 22, 41, 42, 46, 23, nil, nil, nil, 20, -14,
- 15, 27, -8, -26, 6, -108, 63, 64, 68, 69,
- 74, 76, -62, -2, -5, nil, -58, -144, -150, nil,
- nil, 62, nil, nil, nil, 47, -162, nil ]
+ nil, 25, 30, 41, 42, 13, 46, 37, nil, 15,
+ 19, 5, -2, 1, -42, 5, -156, -217, 7, -138,
+ -107, nil, -264, 3, -45, -132, -50, nil, 10, -212,
+ 14, 64, 68, 69, 20, nil, nil, nil, 22, 7,
+ 23, 26, -8, -26, 22, -108, 83, 88, 94, 95,
+ 96, 97, -62, -2, 6, nil, -55, -144, -150, nil,
+ nil, 63, nil, nil, nil, 49, -162, nil ]
racc_goto_default = [
nil, nil, nil, nil, nil, 84, nil, 7, 8, 72,
diff --git a/test/racc/regress/huia b/test/racc/regress/huia
index fc8ccfe847..0b75d39735 100644
--- a/test/racc/regress/huia
+++ b/test/racc/regress/huia
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -121,17 +121,13 @@ end
##### State transition tables begin ###
clist = [
-'81,137,40,180,61,62,164,153,182,71,72,77,155,178,179,39,135,37,37,5',
-'6,106,152,73,74,75,36,36,76,28,154,80,164,166,123,22,23,37,26,27,37',
-'60,63,19,186,40,36,61,62,172,,33,71,72,77,,,134,39,133,129,37,134,,169',
-'129,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33',
-'71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63',
-'19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,',
-',22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,160,39,,,37,5,6,',
-',73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71',
-'72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19',
-',40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22',
-'23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,160,39,,,37,5,6,,,73',
+'81,106,40,37,61,62,123,153,135,71,72,77,155,178,179,39,164,37,37,5,6',
+'137,152,73,74,75,36,36,76,28,154,80,166,172,180,22,23,37,26,27,182,60',
+'63,19,164,40,36,61,62,186,,33,71,72,77,,,134,39,133,129,37,5,6,,,73',
+'74,75,,36,76,28,134,80,169,129,,22,23,,26,27,,60,63,19,,40,,61,62,,',
+'33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60',
+'63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80',
+',,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73',
'74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72',
'77,,114,,39,,,37,,,113,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63',
'19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,',
@@ -144,42 +140,46 @@ clist = [
',37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62',
',,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27',
',60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28',
-',80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,5',
-'6,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33',
+',80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,',
+',,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71',
+'72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19',
+',40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22',
+'23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75',
+',36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,',
+'39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61',
+'62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26',
+'27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76',
+'28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37',
+',,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33',
'71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63',
'19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,',
',22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74',
'75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77',
-',,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40',
-',61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23',
-',26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36',
-'76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,',
-',37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62',
-',,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27',
-',60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28',
-',80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,',
-',,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71',
-'72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19',
+',,160,39,,,37,5,6,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19',
',40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22',
'23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75',
',36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,',
'39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61',
'62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26',
-'27,,60,63,19,85,86,87,88,,,,33,89,,,,,84,,85,86,87,88,,,,91,89,,,,,84',
-',5,6,,,,,,91,,,92,93,94,95,96,97,98,,90,,,,,,,92,93,94,95,96,97,98,',
-'90,85,86,87,88,,,,,89,,,,,84,,85,86,87,88,,,,91,89,,,,,84,,,,,,,,,91',
+'27,,60,63,19,,40,,61,62,,,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76',
+'28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62,,,33,71,72,77,,,160,39,',
+',37,5,6,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27,,60,63,19,,40,,61,62',
+',,33,71,72,77,,,,39,,,37,,,,,73,74,75,,36,76,28,,80,,,,22,23,,26,27',
+',60,63,19,85,86,87,88,,84,,33,89,,,,,84,91,5,6,85,86,87,88,,91,,,89',
+',,,,84,,92,93,94,95,96,97,98,91,92,93,94,95,96,97,98,,90,,,,,,,,,92',
+'93,94,95,96,97,98,,90,85,86,87,88,,,,,89,,,,,84,,85,86,87,88,156,,,91',
+'89,,,,,84,,,,,,,,,91,,,92,93,94,95,96,97,98,,90,,,,,,,92,93,94,95,96',
+'97,98,,90,85,86,87,88,,,,,89,,,,,84,,165,85,86,87,88,,,91,,89,,,,167',
+'84,,,,,,,,,91,,92,93,94,95,96,97,98,,90,,,,,,,,92,93,94,95,96,97,98',
+',90,85,86,87,88,,,,,89,,,,,84,,85,86,87,88,,,,91,89,,,,,84,,,,,,,,,91',
',,92,93,94,95,96,97,98,,90,,,,,,,92,93,94,95,96,97,98,,90,85,86,87,88',
-'156,,,,89,,,,,84,,85,86,87,88,,,,91,89,,,,,84,,165,,,,,,,91,,,92,93',
-'94,95,96,97,98,,90,,,,,,,92,93,94,95,96,97,98,,90,85,86,87,88,,,,,89',
-',,,167,84,,85,86,87,88,,,,91,89,,,,,84,,,,,,,,,91,,,92,93,94,95,96,97',
-'98,,90,,,,,,,92,93,94,95,96,97,98,,90,85,86,87,88,,,,,89,,,,,84,,85',
-'86,87,88,,,,91,89,,,,,84,,,,,,,,,91,,,92,93,94,95,96,97,98,,90,,,,,',
-',92,93,94,95,96,97,98,,90,85,86,87,88,,,,,89,,,,,84,,85,86,87,88,,,',
-'91,89,,,,,84,,,,,,,,,91,,,92,93,94,95,96,97,98,,90,,,,,,,92,93,94,95',
-'96,97,98,,90,85,86,87,88,,,,,89,,,,,84,,85,86,87,88,,,,91,89,,,,,84',
-',,,,,,,,91,,,92,93,94,95,96,97,98,,90,,,,,,,92,93,94,95,96,97,98,,90',
-'85,86,87,88,,84,,,89,,160,,,84,91,5,6,85,86,87,88,,91,,,89,,,,,84,,92',
-'93,94,95,96,97,98,91,92,93,94,95,96,97,98,,90,,,,,,,,,92,93,94,95,96',
+',,,,89,,,,,84,,85,86,87,88,,,,91,89,,,,,84,,,,,,,,,91,,,92,93,94,95',
+'96,97,98,,90,,,,,,,92,93,94,95,96,97,98,,90,85,86,87,88,,,,,89,,,,,84',
+',85,86,87,88,,,,91,89,,,,,84,,,,,,,,,91,,,92,93,94,95,96,97,98,,90,',
+',,,,,92,93,94,95,96,97,98,,90,85,86,87,88,,,,,89,,,,,84,,85,86,87,88',
+',,,91,89,,,,,84,,,,,,,,,91,,,92,93,94,95,96,97,98,,90,,,,,,,92,93,94',
+'95,96,97,98,,90,85,86,87,88,,,,,89,,160,,,84,,5,6,85,86,87,88,,91,,',
+'89,,,,,84,,,,,,,,,91,92,93,94,95,96,97,98,,90,,,,,,,,,92,93,94,95,96',
'97,98,,90,85,86,87,88,,,,,89,,,,,84,,85,86,87,88,,,,91,89,,,,,84,,181',
',,,,,,91,,,92,93,94,95,96,97,98,,90,,,,,,,92,93,94,95,96,97,98,,90,85',
'86,87,88,,,,,89,,,,,84,,85,86,87,88,,,,91,89,,,,,84,,,,,,,,,91,,,92',
@@ -190,7 +190,7 @@ clist = [
'91,92,93,94,95,96,97,98,,90,,89,,,,,84,,92,93,94,95,96,97,98,91,89,',
',,,84,,,,,89,,,,91,84,,92,93,94,95,96,97,98,91,,,,,,,,92,93,94,95,96',
'97,98,,,,92,93,94,95,96,97,98' ]
- racc_action_table = arr = ::Array.new(2246, nil)
+ racc_action_table = arr = ::Array.new(2249, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -200,83 +200,83 @@ clist = [
end
clist = [
-'1,84,1,163,1,1,179,100,178,1,1,1,102,161,161,1,81,84,1,1,1,33,100,1',
-'1,1,84,1,1,1,102,1,112,121,40,1,1,33,1,1,34,1,1,1,183,19,33,19,19,131',
-',1,19,19,19,,,80,19,80,80,19,128,,128,128,19,19,19,,19,19,19,,19,,,',
-'19,19,,19,19,,19,19,19,,123,,123,123,,,19,123,123,123,,,,123,,,123,',
-',,,123,123,123,,123,123,123,,123,,,,123,123,,123,123,,123,123,123,,23',
-',23,23,,,123,23,23,23,,,,23,,,23,,,,,23,23,23,,23,23,23,,23,,,,23,23',
-',23,23,,23,23,23,,111,,111,111,,,23,111,111,111,,,111,111,,,111,111',
-'111,,,111,111,111,,111,111,111,,111,,,,111,111,,111,111,,111,111,111',
-',27,,27,27,,,111,27,27,27,,,,27,,,27,,,,,27,27,27,,27,27,27,,27,,,,27',
-'27,,27,27,,27,27,27,,180,,180,180,,,27,180,180,180,,,,180,,,180,,,,',
-'180,180,180,,180,180,180,,180,,,,180,180,,180,180,,180,180,180,,157',
-',157,157,,,180,157,157,157,,,157,157,,,157,157,157,,,157,157,157,,157',
-'157,157,,157,,,,157,157,,157,157,,157,157,157,,37,,37,37,,,157,37,37',
-'37,,37,,37,,,37,,,37,,37,37,37,,37,37,37,,37,,,,37,37,,37,37,,37,37',
-'37,,39,,39,39,,,37,39,39,39,,,,39,,,39,,,,,39,39,39,,39,39,39,,39,,',
-',39,39,,39,39,,39,39,39,,156,,156,156,,,39,156,156,156,,,,156,,,156',
-',,,,156,156,156,,156,156,156,,156,,,,156,156,,156,156,,156,156,156,',
-'60,,60,60,,,156,60,60,60,,,,60,,,60,,,,,60,60,60,,60,60,60,,60,,,,60',
-'60,,60,60,,60,60,60,,61,,61,61,,,60,61,61,61,,,,61,,,61,,,,,61,61,61',
-',61,61,61,,61,,,,61,61,,61,61,,61,61,61,,62,,62,62,,,61,62,62,62,,,',
-'62,,,62,,,,,62,62,62,,62,62,62,,62,,,,62,62,,62,62,,62,62,62,,63,,63',
-'63,,,62,63,63,63,,,,63,,,63,,,,,63,63,63,,63,63,63,,63,,,,63,63,,63',
-'63,,63,63,63,,155,,155,155,,,63,155,155,155,,,,155,,,155,,,,,155,155',
-'155,,155,155,155,,155,,,,155,155,,155,155,,155,155,155,,129,,129,129',
-',,155,129,129,129,,,,129,,,129,,,,,129,129,129,,129,129,129,,129,,,',
-'129,129,,129,129,,129,129,129,,0,,0,0,,,129,0,0,0,,,,0,,,0,0,0,,,0,0',
-'0,,0,0,0,,0,,,,0,0,,0,0,,0,0,0,,85,,85,85,,,0,85,85,85,,,,85,,,85,,',
-',,85,85,85,,85,85,85,,85,,,,85,85,,85,85,,85,85,85,,86,,86,86,,,85,86',
-'86,86,,,,86,,,86,,,,,86,86,86,,86,86,86,,86,,,,86,86,,86,86,,86,86,86',
-',87,,87,87,,,86,87,87,87,,,,87,,,87,,,,,87,87,87,,87,87,87,,87,,,,87',
-'87,,87,87,,87,87,87,,88,,88,88,,,87,88,88,88,,,,88,,,88,,,,,88,88,88',
-',88,88,88,,88,,,,88,88,,88,88,,88,88,88,,89,,89,89,,,88,89,89,89,,,',
-'89,,,89,,,,,89,89,89,,89,89,89,,89,,,,89,89,,89,89,,89,89,89,,90,,90',
-'90,,,89,90,90,90,,,,90,,,90,,,,,90,90,90,,90,90,90,,90,,,,90,90,,90',
-'90,,90,90,90,,91,,91,91,,,90,91,91,91,,,,91,,,91,,,,,91,91,91,,91,91',
-'91,,91,,,,91,91,,91,91,,91,91,91,,92,,92,92,,,91,92,92,92,,,,92,,,92',
-',,,,92,92,92,,92,92,92,,92,,,,92,92,,92,92,,92,92,92,,93,,93,93,,,92',
-'93,93,93,,,,93,,,93,,,,,93,93,93,,93,93,93,,93,,,,93,93,,93,93,,93,93',
-'93,,94,,94,94,,,93,94,94,94,,,,94,,,94,,,,,94,94,94,,94,94,94,,94,,',
-',94,94,,94,94,,94,94,94,,95,,95,95,,,94,95,95,95,,,,95,,,95,,,,,95,95',
-'95,,95,95,95,,95,,,,95,95,,95,95,,95,95,95,,96,,96,96,,,95,96,96,96',
-',,,96,,,96,,,,,96,96,96,,96,96,96,,96,,,,96,96,,96,96,,96,96,96,,97',
-',97,97,,,96,97,97,97,,,,97,,,97,,,,,97,97,97,,97,97,97,,97,,,,97,97',
-',97,97,,97,97,97,,98,,98,98,,,97,98,98,98,,,,98,,,98,,,,,98,98,98,,98',
-'98,98,,98,,,,98,98,,98,98,,98,98,98,,153,,153,153,,,98,153,153,153,',
-',,153,,,153,,,,,153,153,153,,153,153,153,,153,,,,153,153,,153,153,,153',
-'153,153,147,147,147,147,,,,153,147,,,,,147,,3,3,3,3,,,,147,3,,,,,3,',
-'3,3,,,,,,3,,,147,147,147,147,147,147,147,,147,,,,,,,3,3,3,3,3,3,3,,3',
-'99,99,99,99,,,,,99,,,,,99,,101,101,101,101,,,,99,101,,,,,101,,,,,,,',
-',101,,,99,99,99,99,99,99,99,,99,,,,,,,101,101,101,101,101,101,101,,101',
-'104,104,104,104,104,,,,104,,,,,104,,117,117,117,117,,,,104,117,,,,,117',
-',117,,,,,,,117,,,104,104,104,104,104,104,104,,104,,,,,,,117,117,117',
-'117,117,117,117,,117,122,122,122,122,,,,,122,,,,122,122,,144,144,144',
-'144,,,,122,144,,,,,144,,,,,,,,,144,,,122,122,122,122,122,122,122,,122',
-',,,,,,144,144,144,144,144,144,144,,144,145,145,145,145,,,,,145,,,,,145',
-',146,146,146,146,,,,145,146,,,,,146,,,,,,,,,146,,,145,145,145,145,145',
-'145,145,,145,,,,,,,146,146,146,146,146,146,146,,146,148,148,148,148',
-',,,,148,,,,,148,,149,149,149,149,,,,148,149,,,,,149,,,,,,,,,149,,,148',
-'148,148,148,148,148,148,,148,,,,,,,149,149,149,149,149,149,149,,149',
-'150,150,150,150,,,,,150,,,,,150,,151,151,151,151,,,,150,151,,,,,151',
-',,,,,,,,151,,,150,150,150,150,150,150,150,,150,,,,,,,151,151,151,151',
-'151,151,151,,151,158,158,158,158,,142,,,158,,158,,,158,142,158,158,168',
-'168,168,168,,158,,,168,,,,,168,,142,142,142,142,142,142,142,168,158',
-'158,158,158,158,158,158,,158,,,,,,,,,168,168,168,168,168,168,168,,168',
-'171,171,171,171,,,,,171,,,,,171,,173,173,173,173,,,,171,173,,,,,173',
-',171,,,,,,,173,,,171,171,171,171,171,171,171,,171,,,,,,,173,173,173',
-'173,173,173,173,,173,175,175,175,175,,,,,175,,,,,175,,185,185,185,185',
-',,,175,185,,,,,185,,,,,,,,,185,,,175,175,175,175,175,175,175,,175,,',
-',,,,185,185,185,185,185,185,185,,185,126,126,,,,,126,,,,,126,125,125',
-',,,,125,,126,,,125,,139,139,,,,,139,125,,,,139,,126,126,126,126,126',
-'126,126,139,126,,,,125,125,125,125,125,125,125,,125,,,,,139,139,139',
-'139,139,139,139,141,139,138,138,,141,,,138,,,,,138,141,,,,,,,,138,,',
-'143,,,,,143,,141,141,141,141,141,141,141,143,138,138,138,138,138,138',
-'138,,138,,124,,,,,124,,143,143,143,143,143,143,143,124,127,,,,,127,',
-',,,140,,,,127,140,,124,124,124,124,124,124,124,140,,,,,,,,127,127,127',
-'127,127,127,127,,,,140,140,140,140,140,140,140' ]
- racc_action_check = arr = ::Array.new(2246, nil)
+'1,33,1,34,1,1,40,100,81,1,1,1,102,161,161,1,112,33,1,1,1,84,100,1,1',
+'1,33,1,1,1,102,1,121,131,163,1,1,84,1,1,178,1,1,1,179,0,84,0,0,183,',
+'1,0,0,0,,,80,0,80,80,0,0,0,,,0,0,0,,0,0,0,128,0,128,128,,0,0,,0,0,,0',
+'0,0,,19,,19,19,,,0,19,19,19,,,,19,,,19,,,,,19,19,19,,19,19,19,,19,,',
+',19,19,,19,19,,19,19,19,,23,,23,23,,,19,23,23,23,,,,23,,,23,,,,,23,23',
+'23,,23,23,23,,23,,,,23,23,,23,23,,23,23,23,,27,,27,27,,,23,27,27,27',
+',,,27,,,27,,,,,27,27,27,,27,27,27,,27,,,,27,27,,27,27,,27,27,27,,37',
+',37,37,,,27,37,37,37,,37,,37,,,37,,,37,,37,37,37,,37,37,37,,37,,,,37',
+'37,,37,37,,37,37,37,,39,,39,39,,,37,39,39,39,,,,39,,,39,,,,,39,39,39',
+',39,39,39,,39,,,,39,39,,39,39,,39,39,39,,60,,60,60,,,39,60,60,60,,,',
+'60,,,60,,,,,60,60,60,,60,60,60,,60,,,,60,60,,60,60,,60,60,60,,61,,61',
+'61,,,60,61,61,61,,,,61,,,61,,,,,61,61,61,,61,61,61,,61,,,,61,61,,61',
+'61,,61,61,61,,62,,62,62,,,61,62,62,62,,,,62,,,62,,,,,62,62,62,,62,62',
+'62,,62,,,,62,62,,62,62,,62,62,62,,63,,63,63,,,62,63,63,63,,,,63,,,63',
+',,,,63,63,63,,63,63,63,,63,,,,63,63,,63,63,,63,63,63,,85,,85,85,,,63',
+'85,85,85,,,,85,,,85,,,,,85,85,85,,85,85,85,,85,,,,85,85,,85,85,,85,85',
+'85,,86,,86,86,,,85,86,86,86,,,,86,,,86,,,,,86,86,86,,86,86,86,,86,,',
+',86,86,,86,86,,86,86,86,,87,,87,87,,,86,87,87,87,,,,87,,,87,,,,,87,87',
+'87,,87,87,87,,87,,,,87,87,,87,87,,87,87,87,,88,,88,88,,,87,88,88,88',
+',,,88,,,88,,,,,88,88,88,,88,88,88,,88,,,,88,88,,88,88,,88,88,88,,89',
+',89,89,,,88,89,89,89,,,,89,,,89,,,,,89,89,89,,89,89,89,,89,,,,89,89',
+',89,89,,89,89,89,,90,,90,90,,,89,90,90,90,,,,90,,,90,,,,,90,90,90,,90',
+'90,90,,90,,,,90,90,,90,90,,90,90,90,,91,,91,91,,,90,91,91,91,,,,91,',
+',91,,,,,91,91,91,,91,91,91,,91,,,,91,91,,91,91,,91,91,91,,92,,92,92',
+',,91,92,92,92,,,,92,,,92,,,,,92,92,92,,92,92,92,,92,,,,92,92,,92,92',
+',92,92,92,,93,,93,93,,,92,93,93,93,,,,93,,,93,,,,,93,93,93,,93,93,93',
+',93,,,,93,93,,93,93,,93,93,93,,94,,94,94,,,93,94,94,94,,,,94,,,94,,',
+',,94,94,94,,94,94,94,,94,,,,94,94,,94,94,,94,94,94,,95,,95,95,,,94,95',
+'95,95,,,,95,,,95,,,,,95,95,95,,95,95,95,,95,,,,95,95,,95,95,,95,95,95',
+',96,,96,96,,,95,96,96,96,,,,96,,,96,,,,,96,96,96,,96,96,96,,96,,,,96',
+'96,,96,96,,96,96,96,,97,,97,97,,,96,97,97,97,,,,97,,,97,,,,,97,97,97',
+',97,97,97,,97,,,,97,97,,97,97,,97,97,97,,98,,98,98,,,97,98,98,98,,,',
+'98,,,98,,,,,98,98,98,,98,98,98,,98,,,,98,98,,98,98,,98,98,98,,111,,111',
+'111,,,98,111,111,111,,,111,111,,,111,111,111,,,111,111,111,,111,111',
+'111,,111,,,,111,111,,111,111,,111,111,111,,123,,123,123,,,111,123,123',
+'123,,,,123,,,123,,,,,123,123,123,,123,123,123,,123,,,,123,123,,123,123',
+',123,123,123,,129,,129,129,,,123,129,129,129,,,,129,,,129,,,,,129,129',
+'129,,129,129,129,,129,,,,129,129,,129,129,,129,129,129,,153,,153,153',
+',,129,153,153,153,,,,153,,,153,,,,,153,153,153,,153,153,153,,153,,,',
+'153,153,,153,153,,153,153,153,,155,,155,155,,,153,155,155,155,,,,155',
+',,155,,,,,155,155,155,,155,155,155,,155,,,,155,155,,155,155,,155,155',
+'155,,156,,156,156,,,155,156,156,156,,,,156,,,156,,,,,156,156,156,,156',
+'156,156,,156,,,,156,156,,156,156,,156,156,156,,157,,157,157,,,156,157',
+'157,157,,,157,157,,,157,157,157,,,157,157,157,,157,157,157,,157,,,,157',
+'157,,157,157,,157,157,157,,180,,180,180,,,157,180,180,180,,,,180,,,180',
+',,,,180,180,180,,180,180,180,,180,,,,180,180,,180,180,,180,180,180,3',
+'3,3,3,,142,,180,3,,,,,3,142,3,3,99,99,99,99,,3,,,99,,,,,99,,142,142',
+'142,142,142,142,142,99,3,3,3,3,3,3,3,,3,,,,,,,,,99,99,99,99,99,99,99',
+',99,101,101,101,101,,,,,101,,,,,101,,104,104,104,104,104,,,101,104,',
+',,,104,,,,,,,,,104,,,101,101,101,101,101,101,101,,101,,,,,,,104,104',
+'104,104,104,104,104,,104,117,117,117,117,,,,,117,,,,,117,,117,122,122',
+'122,122,,,117,,122,,,,122,122,,,,,,,,,122,,117,117,117,117,117,117,117',
+',117,,,,,,,,122,122,122,122,122,122,122,,122,144,144,144,144,,,,,144',
+',,,,144,,145,145,145,145,,,,144,145,,,,,145,,,,,,,,,145,,,144,144,144',
+'144,144,144,144,,144,,,,,,,145,145,145,145,145,145,145,,145,146,146',
+'146,146,,,,,146,,,,,146,,147,147,147,147,,,,146,147,,,,,147,,,,,,,,',
+'147,,,146,146,146,146,146,146,146,,146,,,,,,,147,147,147,147,147,147',
+'147,,147,148,148,148,148,,,,,148,,,,,148,,149,149,149,149,,,,148,149',
+',,,,149,,,,,,,,,149,,,148,148,148,148,148,148,148,,148,,,,,,,149,149',
+'149,149,149,149,149,,149,150,150,150,150,,,,,150,,,,,150,,151,151,151',
+'151,,,,150,151,,,,,151,,,,,,,,,151,,,150,150,150,150,150,150,150,,150',
+',,,,,,151,151,151,151,151,151,151,,151,158,158,158,158,,,,,158,,158',
+',,158,,158,158,168,168,168,168,,158,,,168,,,,,168,,,,,,,,,168,158,158',
+'158,158,158,158,158,,158,,,,,,,,,168,168,168,168,168,168,168,,168,171',
+'171,171,171,,,,,171,,,,,171,,173,173,173,173,,,,171,173,,,,,173,,171',
+',,,,,,173,,,171,171,171,171,171,171,171,,171,,,,,,,173,173,173,173,173',
+'173,173,,173,175,175,175,175,,,,,175,,,,,175,,185,185,185,185,,,,175',
+'185,,,,,185,,,,,,,,,185,,,175,175,175,175,175,175,175,,175,,,,,,,185',
+'185,185,185,185,185,185,,185,125,125,,,,,125,,,,,125,126,126,,,,,126',
+',125,,,126,,138,138,,,,,138,126,,,,138,,125,125,125,125,125,125,125',
+'138,125,,,,126,126,126,126,126,126,126,,126,,,,,138,138,138,138,138',
+'138,138,124,138,139,139,,124,,,139,,,,,139,124,,,,,,,,139,,,127,,,,',
+'127,,124,124,124,124,124,124,124,127,139,139,139,139,139,139,139,,139',
+',140,,,,,140,,127,127,127,127,127,127,127,140,141,,,,,141,,,,,143,,',
+',141,143,,140,140,140,140,140,140,140,143,,,,,,,,141,141,141,141,141',
+'141,141,,,,143,143,143,143,143,143,143' ]
+ racc_action_check = arr = ::Array.new(2249, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -286,25 +286,25 @@ clist = [
end
racc_action_pointer = [
- 731, 0, nil, 1431, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 43,
- nil, nil, nil, 129, nil, nil, nil, 215, nil, nil,
- nil, nil, nil, 19, 22, nil, nil, 344, nil, 387,
- 31, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 43, 0, nil, 1416, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 86,
+ nil, nil, nil, 129, nil, nil, nil, 172, nil, nil,
+ nil, nil, nil, -1, -15, nil, nil, 215, nil, 258,
+ 3, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 473, 516, 559, 602, nil, nil, nil, nil, nil, nil,
+ 301, 344, 387, 430, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 27, 16, nil, nil, -1, 774, 817, 860, 903, 946,
- 989, 1032, 1075, 1118, 1161, 1204, 1247, 1290, 1333, 1480,
- -15, 1495, -10, nil, 1544, nil, nil, nil, nil, nil,
- nil, 172, 30, nil, nil, nil, nil, 1559, nil, nil,
- nil, 14, 1608, 86, 2170, 2068, 2056, 2185, 32, 688,
- nil, 19, nil, nil, nil, nil, nil, nil, 2128, 2081,
- 2195, 2120, 1856, 2145, 1623, 1672, 1687, 1416, 1736, 1751,
- 1800, 1815, nil, 1376, nil, 645, 430, 301, 1864, nil,
- nil, -8, nil, 0, nil, nil, nil, nil, 1881, nil,
- nil, 1930, nil, 1945, nil, 1994, nil, nil, -11, 4,
- 258, nil, nil, 31, nil, 2009, nil ]
+ 27, 8, nil, nil, 19, 473, 516, 559, 602, 645,
+ 688, 731, 774, 817, 860, 903, 946, 989, 1032, 1433,
+ -15, 1482, -10, nil, 1497, nil, nil, nil, nil, nil,
+ nil, 1075, 14, nil, nil, nil, nil, 1546, nil, nil,
+ nil, 13, 1562, 1118, 2123, 2059, 2071, 2148, 43, 1161,
+ nil, 3, nil, nil, nil, nil, nil, nil, 2084, 2131,
+ 2173, 2188, 1408, 2198, 1611, 1626, 1675, 1690, 1739, 1754,
+ 1803, 1818, nil, 1204, nil, 1247, 1290, 1333, 1867, nil,
+ nil, -8, nil, 31, nil, nil, nil, nil, 1884, nil,
+ nil, 1933, nil, 1948, nil, 1997, nil, nil, 21, 42,
+ 1376, nil, nil, 36, nil, 2012, nil ]
racc_action_default = [
-140, -140, -1, -4, -5, -6, -7, -10, -11, -12,
@@ -328,9 +328,9 @@ racc_action_default = [
-140, -132, -8, -140, -51, -53, -45 ]
racc_goto_table = [
- 99, 82, 103, 83, 101, 1, 105, 130, 104, 108,
- 109, 110, 159, 162, 111, 115, 112, 161, 117, 116,
- 122, 102, 100, 107, 118, 119, 120, 128, 121, 183,
+ 99, 82, 103, 83, 101, 1, 105, 130, 104, 183,
+ 100, 102, 159, 162, 121, 108, 109, 110, 117, 111,
+ 122, 115, 112, 161, 116, 107, 118, 119, 120, 128,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, 124, 125, 126, 127, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 170, nil, 136, 176, 177,
@@ -347,9 +347,9 @@ racc_goto_table = [
nil, 185 ]
racc_goto_check = [
- 3, 2, 24, 4, 3, 1, 40, 77, 3, 26,
- 27, 28, 30, 35, 29, 31, 32, 33, 3, 34,
- 3, 23, 20, 43, 44, 45, 46, 75, 25, 5,
+ 3, 2, 24, 4, 3, 1, 40, 77, 3, 5,
+ 20, 23, 30, 35, 25, 26, 27, 28, 3, 29,
+ 3, 31, 32, 33, 34, 43, 44, 45, 46, 75,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, 3, 3, 3, 3, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 77, nil, 40, 30, 30,
@@ -366,14 +366,14 @@ racc_goto_check = [
nil, 3 ]
racc_goto_pointer = [
- nil, 5, 0, -19, 0, -149, nil, nil, nil, nil,
+ nil, 5, 0, -19, 0, -169, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- -1, nil, nil, -6, -25, -9, -28, -27, -26, -23,
- -99, -22, -21, -95, -18, -99, nil, nil, nil, nil,
- -27, nil, nil, -11, -13, -12, -11, nil, nil, nil,
+ -13, nil, nil, -16, -25, -23, -22, -21, -20, -18,
+ -99, -16, -15, -89, -13, -99, nil, nil, nil, nil,
+ -27, nil, nil, -9, -11, -10, -9, 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, -53, nil, -73, nil ]
+ nil, nil, nil, nil, nil, -51, nil, -73, nil ]
racc_goto_default = [
nil, nil, 2, 3, 4, nil, 7, 8, 9, 10,
diff --git a/test/racc/regress/journey b/test/racc/regress/journey
index c532dd6eeb..3daf81dac0 100644
--- a/test/racc/regress/journey
+++ b/test/racc/regress/journey
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
diff --git a/test/racc/regress/liquor b/test/racc/regress/liquor
index 4dec55c976..9fa2ca4da0 100644
--- a/test/racc/regress/liquor
+++ b/test/racc/regress/liquor
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -111,30 +111,30 @@ module_eval(<<'...end liquor.y/module_eval...', 'liquor.y', 216)
##### State transition tables begin ###
racc_action_table = [
- 76, 26, 26, 6, 77, 70, 5, 6, 25, 25,
+ 76, 26, 26, 6, 7, 22, 5, 6, 25, 25,
5, 28, 32, 36, 37, 34, 35, 31, 29, 27,
- 33, 2, 30, 26, 26, 2, 6, 43, 52, 5,
+ 33, 2, 30, 26, 26, 2, 6, 23, 41, 5,
25, 25, 38, 39, 28, 32, 36, 37, 34, 35,
- 31, 29, 27, 33, 2, 30, 26, 94, 51, 98,
- 26, 96, 26, 25, 97, 38, 39, 25, 111, 25,
- 28, 32, 36, 37, 34, 35, 31, 29, 27, 33,
- 41, 30, 26, 26, 43, 6, 107, 74, 5, 25,
- 25, 38, 39, 28, 32, 36, 37, 34, 35, 31,
- 29, 27, 33, 2, 30, 7, 26, 70, 6, 96,
- 102, 5, 97, 25, 38, 39, 28, 32, 36, 37,
- 34, 35, 31, 29, 27, 33, 2, 30, 54, 26,
- 74, 6, 96, 74, 5, 97, 25, 38, 39, 28,
- 32, 36, 37, 34, 35, 31, 29, 27, 33, 2,
- 30, 87, 26, 96, 6, 22, 97, 5, 84, 25,
+ 31, 29, 27, 33, 2, 30, 40, 26, 96, 6,
+ 24, 97, 5, 43, 25, 38, 39, 28, 32, 36,
+ 37, 34, 35, 31, 29, 27, 33, 2, 30, 26,
+ 54, 70, 77, 26, 75, 26, 25, 52, 38, 39,
+ 25, 43, 25, 28, 32, 36, 37, 34, 35, 31,
+ 29, 27, 33, 26, 30, 84, 26, 51, 6, 96,
+ 25, 5, 97, 25, 38, 39, 28, 32, 36, 37,
+ 34, 35, 31, 29, 27, 33, 2, 30, 74, 26,
+ 87, 82, 96, 74, 70, 97, 25, 38, 39, 28,
+ 32, 36, 37, 34, 35, 31, 29, 27, 33, 94,
+ 30, 98, 26, 107, 6, 111, 52, 5, nil, 25,
38, 39, 28, 32, 36, 37, 34, 35, 31, 29,
- 27, 33, 2, 30, 40, 26, 23, nil, 24, nil,
- nil, nil, 25, 38, 39, 28, 32, 36, 37, 34,
- 35, 31, 29, 27, 33, nil, 30, nil, 26, nil,
- 82, nil, 52, nil, nil, 25, 38, 39, 28, 32,
+ 27, 33, 2, 30, nil, 26, 51, 6, nil, 74,
+ 5, nil, 25, 38, 39, 28, 32, 36, 37, 34,
+ 35, 31, 29, 27, 33, 2, 30, nil, 26, nil,
+ nil, nil, 102, nil, nil, 25, 38, 39, 28, 32,
36, 37, 34, 35, 31, 29, 27, 33, nil, 30,
- nil, 26, 51, nil, nil, nil, nil, nil, 25, 38,
+ nil, 26, 96, nil, nil, 97, nil, nil, 25, 38,
39, 28, 32, 36, 37, 34, 35, 31, 29, 27,
- 33, nil, 30, nil, 26, nil, nil, nil, 75, nil,
+ 33, nil, 30, nil, 26, nil, nil, nil, nil, nil,
nil, 25, 38, 39, 28, 32, 36, 37, 34, 35,
31, 29, 27, 33, nil, 30, 13, 15, nil, 13,
15, 21, nil, 14, 21, 38, 14, nil, nil, nil,
@@ -142,119 +142,119 @@ racc_action_table = [
15, nil, 16, nil, 21, 16, 14, nil, nil, 13,
15, nil, nil, 18, 21, nil, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
+ 15, 52, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
+ 15, 51, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, 74, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, 52, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, 51, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
+ 15, 74, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, 81, nil, 18, 21, 16, 14, 19, nil, 13,
+ 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
15, nil, 26, 18, 21, 16, 14, 19, nil, 25,
- nil, 101, 28, 18, nil, 16, 26, 19, nil, 29,
- 27, 106, nil, 25, nil, 16, 28, 32, 36, 37,
- 34, 35, 31, 29, 27, 33, 26, 30, nil, nil,
- nil, nil, nil, 25, nil, nil, 28, nil, 26, nil,
- nil, nil, 31, 29, 27, 25, nil, 30, 28, nil,
- 26, nil, nil, nil, 31, 29, 27, 25, nil, 30,
- 28, nil, 26, nil, nil, nil, 31, 29, 27, 25,
- nil, 30, 28, nil, 26, nil, nil, nil, 31, 29,
+ nil, 101, 28, 18, nil, 16, nil, 19, 31, 29,
+ 27, 106, 26, 30, nil, 16, nil, nil, nil, 25,
+ nil, nil, 28, nil, 26, nil, nil, nil, 31, 29,
27, 25, nil, 30, 28, nil, 26, nil, nil, nil,
31, 29, 27, 25, nil, 30, 28, nil, 26, nil,
nil, nil, 31, 29, 27, 25, nil, 30, 28, nil,
- nil, nil, nil, nil, nil, 29, 27 ]
+ 26, nil, nil, nil, 31, 29, 27, 25, nil, 30,
+ 28, nil, 26, nil, nil, nil, 31, 29, 27, 25,
+ nil, 30, 28, 32, 36, 37, 34, 35, 31, 29,
+ 27, 33, 26, 30, 26, nil, nil, nil, nil, 25,
+ nil, 25, 28, nil, 28, nil, nil, nil, nil, 29,
+ 27, 29, 27 ]
racc_action_check = [
- 47, 47, 55, 101, 48, 84, 101, 4, 47, 55,
- 4, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 101, 47, 56, 79, 4, 0, 54, 79, 0,
- 56, 79, 47, 47, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 0, 79, 57, 91, 79, 96,
- 104, 104, 45, 57, 104, 79, 79, 104, 109, 45,
- 104, 104, 104, 104, 104, 104, 104, 104, 104, 104,
- 12, 104, 46, 71, 13, 2, 103, 71, 2, 46,
- 71, 104, 104, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 2, 71, 1, 99, 40, 3, 107,
- 99, 3, 107, 99, 71, 71, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 3, 99, 26, 88,
- 70, 81, 94, 88, 81, 94, 88, 99, 99, 88,
- 88, 88, 88, 88, 88, 88, 88, 88, 88, 81,
- 88, 72, 11, 111, 106, 6, 111, 106, 69, 11,
- 88, 88, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 106, 11, 11, 53, 7, nil, 11, nil,
- nil, nil, 53, 11, 11, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, nil, 53, nil, 49, nil,
- 53, nil, 49, nil, nil, 49, 53, 53, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, nil, 49,
- nil, 44, 49, nil, nil, nil, nil, nil, 44, 49,
- 49, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, nil, 44, nil, 67, nil, nil, nil, 44, nil,
- nil, 67, 44, 44, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, nil, 67, 30, 30, nil, 31,
- 31, 30, nil, 30, 31, 67, 31, nil, nil, nil,
- 30, nil, nil, 31, 30, nil, nil, 31, nil, 32,
- 32, nil, 30, nil, 32, 31, 32, nil, nil, 33,
- 33, nil, nil, 32, 33, nil, 33, 32, nil, 34,
+ 47, 47, 45, 0, 1, 6, 0, 2, 47, 45,
+ 2, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 0, 47, 46, 11, 2, 3, 7, 12, 3,
+ 46, 11, 47, 47, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 3, 11, 11, 44, 94, 4,
+ 11, 94, 4, 13, 44, 11, 11, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 4, 44, 55,
+ 26, 40, 48, 49, 44, 56, 55, 49, 44, 44,
+ 49, 54, 56, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 57, 49, 69, 53, 49, 81, 107,
+ 57, 81, 107, 53, 49, 49, 53, 53, 53, 53,
+ 53, 53, 53, 53, 53, 53, 81, 53, 70, 71,
+ 72, 53, 111, 71, 84, 111, 71, 53, 53, 71,
+ 71, 71, 71, 71, 71, 71, 71, 71, 71, 91,
+ 71, 96, 79, 103, 101, 109, 79, 101, nil, 79,
+ 71, 71, 79, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 101, 79, nil, 88, 79, 106, nil, 88,
+ 106, nil, 88, 79, 79, 88, 88, 88, 88, 88,
+ 88, 88, 88, 88, 88, 106, 88, nil, 99, nil,
+ nil, nil, 99, nil, nil, 99, 88, 88, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, nil, 99,
+ nil, 104, 104, nil, nil, 104, nil, nil, 104, 99,
+ 99, 104, 104, 104, 104, 104, 104, 104, 104, 104,
+ 104, nil, 104, nil, 67, nil, nil, nil, nil, nil,
+ nil, 67, 104, 104, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, nil, 67, 5, 5, nil, 14,
+ 14, 5, nil, 5, 14, 67, 14, nil, nil, nil,
+ 5, nil, nil, 14, 5, nil, nil, 14, nil, 18,
+ 18, nil, 5, nil, 18, 14, 18, nil, nil, 19,
+ 19, nil, nil, 18, 19, nil, 19, 18, nil, 21,
+ 21, nil, nil, 19, 21, 18, 21, 19, nil, 22,
+ 22, 22, nil, 21, 22, 19, 22, 21, nil, 25,
+ 25, nil, nil, 22, 25, 21, 25, 22, nil, 27,
+ 27, 22, nil, 25, 27, 22, 27, 25, nil, 28,
+ 28, nil, nil, 27, 28, 25, 28, 27, nil, 29,
+ 29, nil, nil, 28, 29, 27, 29, 28, nil, 30,
+ 30, nil, nil, 29, 30, 28, 30, 29, nil, 31,
+ 31, nil, nil, 30, 31, 29, 31, 30, nil, 32,
+ 32, nil, nil, 31, 32, 30, 32, 31, nil, 33,
+ 33, nil, nil, 32, 33, 31, 33, 32, nil, 34,
34, nil, nil, 33, 34, 32, 34, 33, nil, 35,
35, nil, nil, 34, 35, 33, 35, 34, nil, 36,
36, nil, nil, 35, 36, 34, 36, 35, nil, 37,
37, nil, nil, 36, 37, 35, 37, 36, nil, 38,
38, nil, nil, 37, 38, 36, 38, 37, nil, 39,
39, nil, nil, 38, 39, 37, 39, 38, nil, 43,
- 43, 43, nil, 39, 43, 38, 43, 39, nil, 74,
- 74, nil, nil, 43, 74, 39, 74, 43, nil, 5,
- 5, nil, nil, 74, 5, 43, 5, 74, nil, 14,
- 14, nil, nil, 5, 14, 74, 14, 5, nil, 18,
- 18, nil, nil, 14, 18, 5, 18, 14, nil, 19,
- 19, nil, nil, 18, 19, 14, 19, 18, nil, 21,
- 21, nil, nil, 19, 21, 18, 21, 19, nil, 22,
- 22, 22, nil, 21, 22, 19, 22, 21, nil, 25,
- 25, nil, nil, 22, 25, 21, 25, 22, nil, 27,
- 27, 22, nil, 25, 27, 22, 27, 25, nil, 28,
- 28, nil, nil, 27, 28, 25, 28, 27, nil, 29,
- 29, nil, nil, 28, 29, 27, 29, 28, nil, 52,
- 52, nil, nil, 29, 52, 28, 52, 29, nil, 76,
- 76, nil, nil, 52, 76, 29, 76, 52, nil, 97,
- 97, 52, nil, 76, 97, 52, 97, 76, nil, 102,
- 102, nil, 58, 97, 102, 76, 102, 97, nil, 58,
- nil, 97, 58, 102, nil, 97, 66, 102, nil, 58,
- 58, 102, nil, 66, nil, 102, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 60, 66, nil, nil,
- nil, nil, nil, 60, nil, nil, 60, nil, 61, nil,
- nil, nil, 60, 60, 60, 61, nil, 60, 61, nil,
- 62, nil, nil, nil, 61, 61, 61, 62, nil, 61,
- 62, nil, 63, nil, nil, nil, 62, 62, 62, 63,
- nil, 62, 63, nil, 64, nil, nil, nil, 63, 63,
- 63, 64, nil, 63, 64, nil, 65, nil, nil, nil,
- 64, 64, 64, 65, nil, 64, 65, nil, 59, nil,
- nil, nil, 65, 65, 65, 59, nil, 65, 59, nil,
- nil, nil, nil, nil, nil, 59, 59 ]
+ 43, 43, nil, 39, 43, 38, 43, 39, nil, 52,
+ 52, nil, nil, 43, 52, 39, 52, 43, nil, 74,
+ 74, nil, nil, 52, 74, 43, 74, 52, nil, 76,
+ 76, 52, nil, 74, 76, 52, 76, 74, nil, 97,
+ 97, nil, nil, 76, 97, 74, 97, 76, nil, 102,
+ 102, nil, 60, 97, 102, 76, 102, 97, nil, 60,
+ nil, 97, 60, 102, nil, 97, nil, 102, 60, 60,
+ 60, 102, 61, 60, nil, 102, nil, nil, nil, 61,
+ nil, nil, 61, nil, 62, nil, nil, nil, 61, 61,
+ 61, 62, nil, 61, 62, nil, 63, nil, nil, nil,
+ 62, 62, 62, 63, nil, 62, 63, nil, 64, nil,
+ nil, nil, 63, 63, 63, 64, nil, 63, 64, nil,
+ 65, nil, nil, nil, 64, 64, 64, 65, nil, 64,
+ 65, nil, 66, nil, nil, nil, 65, 65, 65, 66,
+ nil, 65, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 58, 66, 59, nil, nil, nil, nil, 58,
+ nil, 59, 58, nil, 59, nil, nil, nil, nil, 58,
+ 58, 59, 59 ]
racc_action_pointer = [
- 18, 95, 67, 90, -1, 374, 140, 166, nil, nil,
- nil, 139, 41, 62, 384, nil, nil, nil, 394, 404,
- nil, 414, 424, nil, nil, 434, 113, 444, 454, 464,
- 251, 254, 274, 284, 294, 304, 314, 324, 334, 344,
- 92, nil, nil, 354, 208, 49, 69, -2, -24, 185,
- nil, nil, 474, 162, 15, -1, 20, 43, 509, 615,
- 543, 555, 567, 579, 591, 603, 523, 231, nil, 123,
- 113, 70, 111, nil, 364, nil, 484, nil, nil, 21,
- nil, 113, nil, nil, 0, nil, nil, nil, 116, nil,
- nil, 38, nil, nil, 118, nil, 22, 494, nil, 93,
- nil, -5, 504, 67, 47, nil, 136, 95, nil, 49,
- nil, 139, nil ]
+ -5, 4, -1, 18, 41, 251, 0, 27, nil, nil,
+ nil, 21, -1, 41, 254, nil, nil, nil, 274, 284,
+ nil, 294, 304, nil, nil, 314, 65, 324, 334, 344,
+ 354, 364, 374, 384, 394, 404, 414, 424, 434, 444,
+ 66, nil, nil, 454, 44, -1, 20, -2, 44, 70,
+ nil, nil, 464, 93, 69, 66, 72, 90, 609, 611,
+ 509, 529, 541, 553, 565, 577, 589, 231, nil, 70,
+ 111, 116, 90, nil, 474, nil, 484, nil, nil, 139,
+ nil, 90, nil, nil, 119, nil, nil, nil, 162, nil,
+ nil, 130, nil, nil, 44, nil, 114, 494, nil, 185,
+ nil, 136, 504, 134, 208, nil, 159, 95, nil, 136,
+ nil, 118, nil ]
racc_action_default = [
-1, -57, -1, -1, -1, -57, -57, -57, -2, -3,
@@ -271,8 +271,8 @@ racc_action_default = [
-53, -57, -55 ]
racc_goto_table = [
- 1, 11, 8, 9, 10, 48, 68, 100, 42, 50,
- 44, 72, 105, 73, 45, 46, 12, 80, 49, nil,
+ 1, 11, 8, 9, 10, 48, 68, 12, 42, 50,
+ 44, 72, 80, 73, 45, 46, 100, 105, 49, nil,
nil, 53, nil, 55, 56, 57, 58, 59, 60, 61,
62, 63, 64, 65, 66, 67, 78, nil, nil, 71,
85, 86, 95, nil, nil, nil, nil, nil, 79, 83,
@@ -284,8 +284,8 @@ racc_goto_table = [
nil, 103, nil, nil, nil, nil, 109 ]
racc_goto_check = [
- 1, 4, 1, 1, 1, 9, 12, 17, 8, 14,
- 4, 10, 18, 11, 4, 4, 5, 15, 4, nil,
+ 1, 4, 1, 1, 1, 9, 12, 5, 8, 14,
+ 4, 10, 15, 11, 4, 4, 17, 18, 4, nil,
nil, 4, nil, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 14, nil, nil, 4,
11, 11, 16, nil, nil, nil, nil, nil, 4, 8,
@@ -297,8 +297,8 @@ racc_goto_check = [
nil, 1, nil, nil, nil, nil, 1 ]
racc_goto_pointer = [
- nil, 0, nil, nil, -4, 11, nil, nil, -5, -16,
- -32, -30, -34, nil, -13, -35, -52, -90, -90 ]
+ nil, 0, nil, nil, -4, 2, nil, nil, -5, -16,
+ -32, -30, -34, nil, -13, -40, -52, -81, -85 ]
racc_goto_default = [
nil, nil, 3, 4, 47, nil, 20, 17, nil, nil,
diff --git a/test/racc/regress/machete b/test/racc/regress/machete
index 08e4cb3a6f..6297fe2ac9 100644
--- a/test/racc/regress/machete
+++ b/test/racc/regress/machete
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -262,42 +262,42 @@ end
##### State transition tables begin ###
racc_action_table = [
- 75, 24, 9, 10, 11, 12, 13, 14, 15, 16,
- 66, 67, 68, 7, 48, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 74, 8, 7, 76, 9, 10,
- 11, 12, 13, 14, 15, 16, 71, 18, 8, 7,
- 72, 9, 10, 11, 12, 13, 14, 15, 16, 73,
- 70, 8, 7, 19, 9, 10, 11, 12, 13, 14,
+ 75, 19, 9, 10, 11, 12, 13, 14, 15, 16,
+ 66, 67, 68, 7, 24, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 74, 8, 7, 47, 9, 10,
+ 11, 12, 13, 14, 15, 16, 48, 18, 8, 7,
+ 71, 9, 10, 11, 12, 13, 14, 15, 16, 72,
+ 70, 8, 7, 73, 9, 10, 11, 12, 13, 14,
15, 16, 69, 18, 8, 7, 30, 31, 32, 51,
52, 53, 54, 33, 34, 35, 29, 8, 41, 38,
- 39, 77, 30, 31, 32, 47, 36, 37, 40, 33,
+ 39, 76, 30, 31, 32, 77, 36, 37, 40, 33,
34, 35, 29, nil, 41, 38, 39, 18, 49, 50,
62, 63, 36, 37, 40, 43, 44, 55, 64, 65,
45, 46, 57, 58, nil, nil, nil, nil, nil, 56 ]
racc_action_check = [
- 70, 17, 0, 0, 0, 0, 0, 0, 0, 0,
- 54, 54, 54, 0, 22, 8, 8, 8, 8, 8,
- 8, 8, 8, 1, 70, 0, 8, 71, 18, 18,
- 18, 18, 18, 18, 18, 18, 56, 1, 8, 18,
- 57, 48, 48, 48, 48, 48, 48, 48, 48, 58,
- 55, 18, 48, 7, 51, 51, 51, 51, 51, 51,
+ 70, 7, 0, 0, 0, 0, 0, 0, 0, 0,
+ 54, 54, 54, 0, 17, 8, 8, 8, 8, 8,
+ 8, 8, 8, 1, 70, 0, 8, 21, 18, 18,
+ 18, 18, 18, 18, 18, 18, 22, 1, 8, 18,
+ 56, 48, 48, 48, 48, 48, 48, 48, 48, 57,
+ 55, 18, 48, 58, 51, 51, 51, 51, 51, 51,
51, 51, 55, 61, 48, 51, 19, 19, 19, 28,
28, 28, 28, 19, 19, 19, 19, 51, 19, 19,
- 19, 75, 50, 50, 50, 21, 19, 19, 19, 50,
+ 19, 71, 50, 50, 50, 75, 19, 19, 19, 50,
50, 50, 50, nil, 50, 50, 50, 20, 26, 26,
52, 52, 50, 50, 50, 20, 20, 46, 53, 53,
20, 20, 46, 46, nil, nil, nil, nil, nil, 46 ]
racc_action_pointer = [
- 0, 23, nil, nil, nil, nil, nil, 38, 13, nil,
- nil, nil, nil, nil, nil, nil, nil, 1, 26, 64,
- 83, 59, -3, nil, nil, nil, 82, nil, 51, nil,
+ 0, 23, nil, nil, nil, nil, nil, -14, 13, nil,
+ nil, nil, nil, nil, nil, nil, nil, 14, 26, 64,
+ 83, 1, 19, nil, nil, nil, 82, nil, 51, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, 102, nil, 39, nil,
- 80, 52, 94, 102, 4, 33, 31, 11, 20, nil,
+ 80, 52, 94, 102, 4, 33, 35, 20, 24, nil,
nil, 49, nil, nil, nil, nil, nil, nil, nil, nil,
- -5, -2, nil, nil, nil, 52, nil, nil ]
+ -5, 52, nil, nil, nil, 56, nil, nil ]
racc_action_default = [
-56, -56, -1, -3, -4, -5, -6, -7, -33, -48,
@@ -310,7 +310,7 @@ racc_action_default = [
-56, -56, -46, -47, -43, -56, -44, -45 ]
racc_goto_table = [
- 1, 23, 27, 21, 22, 42, 25, 26, nil, nil,
+ 1, 23, 27, 25, 26, 21, 22, 42, 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, 60, nil, nil, nil, nil, nil, nil,
@@ -318,7 +318,7 @@ racc_goto_table = [
nil, 61 ]
racc_goto_check = [
- 1, 12, 8, 10, 11, 13, 2, 7, nil, nil,
+ 1, 12, 8, 2, 7, 10, 11, 13, 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, 8, nil, nil, nil, nil, nil, nil,
@@ -326,8 +326,8 @@ racc_goto_check = [
nil, 1 ]
racc_goto_pointer = [
- nil, 0, -12, nil, nil, nil, nil, -12, -17, nil,
- -5, -4, -7, -15 ]
+ nil, 0, -15, nil, nil, nil, nil, -15, -17, nil,
+ -3, -2, -7, -13 ]
racc_goto_default = [
nil, 20, 2, 3, 4, 5, 6, nil, nil, 28,
diff --git a/test/racc/regress/mediacloth b/test/racc/regress/mediacloth
index 15430d7ad4..cca7d3c7e4 100644
--- a/test/racc/regress/mediacloth
+++ b/test/racc/regress/mediacloth
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -51,38 +51,38 @@ end
##### State transition tables begin ###
racc_action_table = [
- 22, 28, 132, 29, 50, 13, 106, 44, 15, 86,
- 37, 87, 24, 33, 86, 34, 87, 35, 46, 23,
- 26, 25, 27, 12, 85, 30, 86, 31, 87, 42,
- 86, 32, 87, 61, 86, 63, 87, 17, 48, 81,
- 48, 21, 57, 22, 28, 53, 29, 51, 13, 11,
- 36, 15, 36, 14, 57, 24, 33, 67, 34, 45,
- 35, 68, 23, 26, 25, 27, 12, 69, 30, 86,
- 31, 87, 75, 73, 32, 70, 71, 72, 76, 77,
- 17, 82, 22, 28, 21, 29, 55, 13, 51, -65,
- 15, -65, 11, 36, 24, 33, 14, 34, 63, 35,
- 96, 23, 26, 25, 27, 12, 63, 30, 109, 31,
- 110, 113, 114, 32, 48, 117, 118, 124, 57, 17,
- 127, 22, 28, 21, 29, 128, 13, 131, 136, 15,
- 137, 11, 36, 24, 33, 14, 34, 138, 35, 75,
- 23, 26, 25, 27, 12, 51, 30, 141, 31, -63,
- 106, 106, 32, 150, 153, 51, nil, nil, 17, nil,
- 22, 28, 21, 29, nil, 13, nil, nil, 15, nil,
- 11, 36, 24, 33, 14, 34, nil, 35, nil, 23,
+ 22, 28, 50, 29, 61, 13, 63, 132, 15, 86,
+ 37, 87, 24, 33, 86, 34, 87, 35, 85, 23,
+ 26, 25, 27, 12, 86, 30, 87, 31, 86, 42,
+ 87, 32, 44, 86, 48, 87, 57, 17, 57, 22,
+ 28, 21, 29, 46, 13, 51, 67, 15, 68, 11,
+ 36, 24, 33, 14, 34, 69, 35, 36, 23, 26,
+ 25, 27, 12, 86, 30, 87, 31, 75, 73, 70,
+ 32, 48, 81, 71, 72, 76, 17, 77, 22, 28,
+ 21, 29, 82, 13, 45, 51, 15, -65, 11, 36,
+ 24, 33, 14, 34, -65, 35, 63, 23, 26, 25,
+ 27, 12, 96, 30, 63, 31, 106, 109, 110, 32,
+ 113, 114, 48, 117, 118, 17, 124, 22, 28, 21,
+ 29, 57, 13, 127, 128, 15, 131, 11, 36, 24,
+ 33, 14, 34, 136, 35, 137, 23, 26, 25, 27,
+ 12, 138, 30, 75, 31, 51, 141, -63, 32, 106,
+ 106, 150, 153, 51, 17, nil, nil, nil, 21, nil,
+ 22, 28, 53, 29, nil, 13, 11, 36, 15, nil,
+ 14, nil, 24, 33, nil, 34, nil, 35, nil, 23,
26, 25, 27, 12, nil, 30, nil, 31, nil, nil,
nil, 32, nil, nil, nil, nil, nil, 17, nil, 22,
- 28, 21, 29, nil, 13, nil, nil, 15, nil, 11,
+ 28, 21, 29, 55, 13, nil, nil, 15, nil, 11,
36, 24, 33, 14, 34, nil, 35, nil, 23, 26,
25, 27, 12, nil, 30, nil, 31, nil, nil, nil,
32, nil, nil, nil, nil, nil, 17, nil, 22, 28,
- 21, 29, nil, 13, nil, 142, 15, nil, 11, 36,
+ 21, 29, nil, 13, nil, nil, 15, nil, 11, 36,
24, 33, 14, 34, nil, 35, nil, 23, 26, 25,
27, 12, nil, 30, nil, 31, nil, nil, nil, 32,
nil, nil, nil, nil, nil, 17, nil, 22, 28, 21,
- 29, nil, 13, nil, nil, 15, 144, 11, 36, 24,
+ 29, nil, 13, nil, nil, 15, nil, 11, 36, 24,
33, 14, 34, nil, 35, nil, 23, 26, 25, 27,
12, nil, 30, nil, 31, nil, nil, nil, 32, nil,
- nil, 98, nil, nil, 17, nil, 22, 28, 21, 29,
+ nil, nil, nil, nil, 17, nil, 22, 28, 21, 29,
nil, 13, nil, nil, 15, nil, 11, 36, 24, 33,
14, 34, nil, 35, nil, 23, 26, 25, 27, 12,
nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
@@ -90,67 +90,65 @@ racc_action_table = [
13, nil, nil, 15, nil, 11, 36, 24, 33, 14,
34, nil, 35, nil, 23, 26, 25, 27, 12, nil,
30, nil, 31, nil, nil, nil, 32, nil, nil, nil,
- nil, 101, 17, nil, 22, 28, 21, 29, nil, 13,
+ nil, nil, 17, nil, 22, 28, 21, 29, nil, 13,
nil, nil, 15, nil, 11, 36, 24, 33, 14, 34,
nil, 35, nil, 23, 26, 25, 27, 12, nil, 30,
nil, 31, nil, nil, nil, 32, nil, nil, nil, nil,
- nil, 17, nil, nil, nil, 21, nil, 22, 28, nil,
+ nil, 17, 78, nil, nil, 21, nil, 22, 28, 88,
29, nil, 13, 11, 36, 15, nil, 14, nil, 24,
- 33, 102, 34, nil, 35, nil, 23, 26, 25, 27,
- 12, nil, 30, nil, 31, nil, nil, nil, 32, nil,
- nil, nil, nil, nil, 17, nil, nil, nil, 21, nil,
- nil, nil, nil, nil, nil, nil, 11, 36, 22, 28,
- 14, 29, nil, 13, nil, nil, 15, nil, 136, nil,
- 24, 33, nil, 34, nil, 35, nil, 23, 26, 25,
- 27, 12, nil, 30, nil, 31, nil, nil, nil, 32,
- nil, nil, nil, nil, nil, 17, nil, 22, 28, 21,
- 29, nil, 13, nil, nil, 15, nil, 11, 36, 24,
- 33, 14, 34, 103, 35, nil, 23, 26, 25, 27,
- 12, nil, 30, nil, 31, nil, nil, nil, 32, nil,
- nil, nil, nil, nil, 17, nil, 22, 28, 21, 29,
- nil, 13, nil, nil, 15, nil, 11, 36, 24, 33,
- 14, 34, nil, 35, 104, 23, 26, 25, 27, 12,
- nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
- nil, nil, nil, 17, nil, nil, nil, 21, nil, nil,
- nil, nil, nil, nil, nil, 11, 36, 22, 28, 14,
- 29, nil, 13, nil, nil, 15, nil, 136, nil, 24,
33, nil, 34, nil, 35, nil, 23, 26, 25, 27,
12, nil, 30, nil, 31, nil, nil, nil, 32, nil,
nil, nil, nil, nil, 17, nil, 22, 28, 21, 29,
- nil, 13, nil, nil, 15, nil, 11, 36, 24, 33,
+ 89, 13, nil, nil, 15, nil, 11, 36, 24, 33,
14, 34, nil, 35, nil, 23, 26, 25, 27, 12,
nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
nil, nil, nil, 17, nil, 22, 28, 21, 29, nil,
13, nil, nil, 15, nil, 11, 36, 24, 33, 14,
34, nil, 35, nil, 23, 26, 25, 27, 12, nil,
- 30, nil, 31, nil, nil, nil, 32, nil, nil, nil,
- nil, nil, 17, 115, 22, 28, 21, 29, nil, 13,
+ 30, nil, 31, nil, nil, 93, 32, nil, nil, nil,
+ nil, nil, 17, nil, 22, 28, 21, 29, nil, 13,
nil, nil, 15, nil, 11, 36, 24, 33, 14, 34,
nil, 35, nil, 23, 26, 25, 27, 12, nil, 30,
+ nil, 31, nil, nil, nil, 32, nil, nil, 98, nil,
+ nil, 17, nil, 22, 28, 21, 29, nil, 13, nil,
+ nil, 15, nil, 11, 36, 24, 33, 14, 34, nil,
+ 35, nil, 23, 26, 25, 27, 12, nil, 30, nil,
+ 31, nil, nil, nil, 32, nil, nil, nil, nil, 101,
+ 17, nil, nil, nil, 21, nil, 22, 28, nil, 29,
+ nil, 13, 11, 36, 15, nil, 14, nil, 24, 33,
+ 102, 34, nil, 35, nil, 23, 26, 25, 27, 12,
+ nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
+ nil, nil, nil, 17, nil, 22, 28, 21, 29, nil,
+ 13, nil, nil, 15, nil, 11, 36, 24, 33, 14,
+ 34, 103, 35, nil, 23, 26, 25, 27, 12, nil,
+ 30, nil, 31, nil, nil, nil, 32, nil, nil, nil,
+ nil, nil, 17, nil, 22, 28, 21, 29, nil, 13,
+ nil, nil, 15, nil, 11, 36, 24, 33, 14, 34,
+ nil, 35, 104, 23, 26, 25, 27, 12, nil, 30,
nil, 31, nil, nil, nil, 32, nil, nil, nil, nil,
nil, 17, nil, 22, 28, 21, 29, nil, 13, nil,
nil, 15, nil, 11, 36, 24, 33, 14, 34, nil,
35, nil, 23, 26, 25, 27, 12, nil, 30, nil,
31, nil, nil, nil, 32, nil, nil, nil, nil, nil,
- 17, 78, 22, 28, 21, 29, nil, 13, nil, nil,
+ 17, nil, 22, 28, 21, 29, nil, 13, nil, nil,
15, nil, 11, 36, 24, 33, 14, 34, nil, 35,
nil, 23, 26, 25, 27, 12, nil, 30, nil, 31,
nil, nil, nil, 32, nil, nil, nil, nil, nil, 17,
- nil, 22, 28, 21, 29, nil, 13, nil, 121, 15,
+ nil, 22, 28, 21, 29, nil, 13, nil, nil, 15,
nil, 11, 36, 24, 33, 14, 34, nil, 35, nil,
23, 26, 25, 27, 12, nil, 30, nil, 31, nil,
- nil, nil, 32, nil, nil, nil, nil, nil, 17, nil,
- 22, 28, 21, 29, nil, 13, nil, nil, 15, 123,
+ nil, nil, 32, nil, nil, nil, nil, nil, 17, 115,
+ 22, 28, 21, 29, nil, 13, nil, nil, 15, nil,
11, 36, 24, 33, 14, 34, nil, 35, nil, 23,
26, 25, 27, 12, nil, 30, nil, 31, nil, nil,
nil, 32, nil, nil, nil, nil, nil, 17, nil, 22,
- 28, 21, 29, nil, 13, nil, nil, 15, nil, 11,
+ 28, 21, 29, nil, 13, nil, 121, 15, nil, 11,
36, 24, 33, 14, 34, nil, 35, nil, 23, 26,
- 25, 27, 12, nil, 30, nil, 31, nil, nil, 126,
+ 25, 27, 12, nil, 30, nil, 31, nil, nil, nil,
32, nil, nil, nil, nil, nil, 17, nil, 22, 28,
- 21, 29, nil, 13, nil, nil, 15, nil, 11, 36,
+ 21, 29, nil, 13, nil, nil, 15, 123, 11, 36,
24, 33, 14, 34, nil, 35, nil, 23, 26, 25,
- 27, 12, nil, 30, nil, 31, nil, nil, nil, 32,
+ 27, 12, nil, 30, nil, 31, nil, nil, 126, 32,
nil, nil, nil, nil, nil, 17, nil, 22, 28, 21,
29, nil, 13, nil, nil, 15, nil, 11, 36, 24,
33, 14, 34, nil, 35, nil, 23, 26, 25, 27,
@@ -159,194 +157,196 @@ racc_action_table = [
nil, 13, nil, nil, 15, nil, 11, 36, 24, 33,
14, 34, nil, 35, nil, 23, 26, 25, 27, 12,
nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
- nil, nil, 130, 17, nil, nil, nil, 21, nil, 22,
- 28, 88, 29, nil, 13, 11, 36, 15, nil, 14,
- nil, 24, 33, nil, 34, nil, 35, nil, 23, 26,
- 25, 27, 12, nil, 30, nil, 31, nil, nil, nil,
- 32, nil, nil, nil, nil, nil, 17, nil, 22, 28,
- 21, 29, nil, 13, nil, 134, 15, nil, 11, 36,
- 24, 33, 14, 34, nil, 35, nil, 23, 26, 25,
- 27, 12, nil, 30, nil, 31, nil, nil, nil, 32,
- nil, nil, nil, nil, nil, 17, nil, 22, 28, 21,
- 29, 89, 13, nil, nil, 15, nil, 11, 36, 24,
- 33, 14, 34, nil, 35, nil, 23, 26, 25, 27,
- 12, nil, 30, nil, 31, nil, nil, nil, 32, nil,
- nil, nil, nil, nil, 17, nil, 22, 28, 21, 29,
- nil, 13, nil, nil, 15, nil, 11, 36, 24, 33,
- 14, 34, nil, 35, nil, 23, 26, 25, 27, 12,
- nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
- nil, nil, nil, 17, nil, 22, 28, 21, 29, nil,
- 13, nil, nil, 15, nil, 11, 36, 24, 33, 14,
+ nil, nil, 130, 17, nil, 22, 28, 21, 29, nil,
+ 13, nil, 134, 15, nil, 11, 36, 24, 33, 14,
34, nil, 35, nil, 23, 26, 25, 27, 12, nil,
30, nil, 31, nil, nil, nil, 32, nil, nil, nil,
nil, nil, 17, nil, 22, 28, 21, 29, nil, 13,
nil, nil, 15, nil, 11, 36, 24, 33, 14, 34,
nil, 35, nil, 23, 26, 25, 27, 12, nil, 30,
- nil, 31, nil, nil, 93, 32, nil, nil, nil, nil,
+ nil, 31, nil, nil, nil, 32, nil, nil, nil, nil,
nil, 17, nil, 22, 28, 21, 29, nil, 13, nil,
nil, 15, nil, 11, 36, 24, 33, 14, 34, nil,
35, nil, 23, 26, 25, 27, 12, nil, 30, nil,
31, nil, nil, nil, 32, nil, nil, nil, nil, nil,
+ 17, nil, 22, 28, 21, 29, nil, 13, nil, 142,
+ 15, nil, 11, 36, 24, 33, 14, 34, nil, 35,
+ nil, 23, 26, 25, 27, 12, nil, 30, nil, 31,
+ nil, nil, nil, 32, nil, nil, nil, nil, nil, 17,
+ nil, 22, 28, 21, 29, nil, 13, nil, nil, 15,
+ 144, 11, 36, 24, 33, 14, 34, nil, 35, nil,
+ 23, 26, 25, 27, 12, nil, 30, nil, 31, nil,
+ nil, nil, 32, nil, nil, nil, nil, nil, 17, nil,
+ nil, nil, 21, nil, nil, nil, nil, nil, nil, nil,
+ 11, 36, 22, 28, 14, 29, nil, 13, nil, nil,
+ 15, nil, 136, nil, 24, 33, nil, 34, nil, 35,
+ nil, 23, 26, 25, 27, 12, nil, 30, nil, 31,
+ nil, nil, nil, 32, nil, nil, nil, nil, nil, 17,
+ nil, nil, nil, 21, nil, nil, nil, nil, nil, nil,
+ nil, 11, 36, 22, 28, 14, 29, nil, 13, nil,
+ nil, 15, nil, 136, nil, 24, 33, nil, 34, nil,
+ 35, nil, 23, 26, 25, 27, 12, nil, 30, nil,
+ 31, nil, nil, nil, 32, nil, nil, nil, nil, nil,
17, nil, nil, nil, 21, nil, nil, nil, nil, nil,
nil, nil, 11, 36, nil, nil, 14 ]
racc_action_check = [
- 0, 0, 106, 0, 21, 0, 67, 15, 0, 85,
- 1, 85, 0, 0, 123, 0, 123, 0, 15, 0,
- 0, 0, 0, 0, 51, 0, 142, 0, 142, 13,
- 121, 0, 121, 32, 144, 32, 144, 0, 48, 48,
- 17, 0, 30, 28, 28, 28, 28, 21, 28, 0,
- 0, 28, 106, 0, 31, 28, 28, 36, 28, 15,
- 28, 37, 28, 28, 28, 28, 28, 39, 28, 51,
- 28, 51, 44, 44, 28, 41, 42, 43, 45, 46,
- 28, 49, 29, 29, 28, 29, 29, 29, 50, 56,
- 29, 58, 28, 28, 29, 29, 28, 29, 59, 29,
- 60, 29, 29, 29, 29, 29, 62, 29, 73, 29,
- 74, 76, 77, 29, 81, 83, 84, 90, 91, 29,
- 94, 75, 75, 29, 75, 95, 75, 105, 109, 75,
- 112, 29, 29, 75, 75, 29, 75, 113, 75, 114,
- 75, 75, 75, 75, 75, 118, 75, 119, 75, 125,
- 132, 133, 75, 135, 139, 141, nil, nil, 75, nil,
- 2, 2, 75, 2, nil, 2, nil, nil, 2, nil,
- 75, 75, 2, 2, 75, 2, nil, 2, nil, 2,
- 2, 2, 2, 2, nil, 2, nil, 2, nil, nil,
- nil, 2, nil, nil, nil, nil, nil, 2, nil, 120,
- 120, 2, 120, nil, 120, nil, nil, 120, nil, 2,
- 2, 120, 120, 2, 120, nil, 120, nil, 120, 120,
- 120, 120, 120, nil, 120, nil, 120, nil, nil, nil,
- 120, nil, nil, nil, nil, nil, 120, nil, 122, 122,
- 120, 122, nil, 122, nil, 120, 122, nil, 120, 120,
- 122, 122, 120, 122, nil, 122, nil, 122, 122, 122,
- 122, 122, nil, 122, nil, 122, nil, nil, nil, 122,
- nil, nil, nil, nil, nil, 122, nil, 61, 61, 122,
- 61, nil, 61, nil, nil, 61, 122, 122, 122, 61,
- 61, 122, 61, nil, 61, nil, 61, 61, 61, 61,
- 61, nil, 61, nil, 61, nil, nil, nil, 61, nil,
- nil, 61, nil, nil, 61, nil, 40, 40, 61, 40,
- nil, 40, nil, nil, 40, nil, 61, 61, 40, 40,
- 61, 40, nil, 40, nil, 40, 40, 40, 40, 40,
- nil, 40, nil, 40, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, 40, nil, 63, 63, 40, 63, nil,
- 63, nil, nil, 63, nil, 40, 40, 63, 63, 40,
- 63, nil, 63, nil, 63, 63, 63, 63, 63, nil,
- 63, nil, 63, nil, nil, nil, 63, nil, nil, nil,
- nil, 63, 63, nil, 134, 134, 63, 134, nil, 134,
- nil, nil, 134, nil, 63, 63, 134, 134, 63, 134,
- nil, 134, nil, 134, 134, 134, 134, 134, nil, 134,
- nil, 134, nil, nil, nil, 134, nil, nil, nil, nil,
- nil, 134, nil, nil, nil, 134, nil, 64, 64, nil,
- 64, nil, 64, 134, 134, 64, nil, 134, nil, 64,
- 64, 64, 64, nil, 64, nil, 64, 64, 64, 64,
- 64, nil, 64, nil, 64, nil, nil, nil, 64, nil,
- nil, nil, nil, nil, 64, nil, nil, nil, 64, nil,
- nil, nil, nil, nil, nil, nil, 64, 64, 136, 136,
- 64, 136, nil, 136, nil, nil, 136, nil, 136, nil,
- 136, 136, nil, 136, nil, 136, nil, 136, 136, 136,
- 136, 136, nil, 136, nil, 136, nil, nil, nil, 136,
- nil, nil, nil, nil, nil, 136, nil, 65, 65, 136,
- 65, nil, 65, nil, nil, 65, nil, 136, 136, 65,
- 65, 136, 65, 65, 65, nil, 65, 65, 65, 65,
- 65, nil, 65, nil, 65, nil, nil, nil, 65, nil,
- nil, nil, nil, nil, 65, nil, 66, 66, 65, 66,
- nil, 66, nil, nil, 66, nil, 65, 65, 66, 66,
- 65, 66, nil, 66, 66, 66, 66, 66, 66, 66,
- nil, 66, nil, 66, nil, nil, nil, 66, nil, nil,
- nil, nil, nil, 66, nil, nil, nil, 66, nil, nil,
- nil, nil, nil, nil, nil, 66, 66, 152, 152, 66,
- 152, nil, 152, nil, nil, 152, nil, 152, nil, 152,
- 152, nil, 152, nil, 152, nil, 152, 152, 152, 152,
- 152, nil, 152, nil, 152, nil, nil, nil, 152, nil,
- nil, nil, nil, nil, 152, nil, 71, 71, 152, 71,
- nil, 71, nil, nil, 71, nil, 152, 152, 71, 71,
- 152, 71, nil, 71, nil, 71, 71, 71, 71, 71,
- nil, 71, nil, 71, nil, nil, nil, 71, nil, nil,
- nil, nil, nil, 71, nil, 79, 79, 71, 79, nil,
- 79, nil, nil, 79, nil, 71, 71, 79, 79, 71,
- 79, nil, 79, nil, 79, 79, 79, 79, 79, nil,
- 79, nil, 79, nil, nil, nil, 79, nil, nil, nil,
- nil, nil, 79, 79, 14, 14, 79, 14, nil, 14,
- nil, nil, 14, nil, 79, 79, 14, 14, 79, 14,
- nil, 14, nil, 14, 14, 14, 14, 14, nil, 14,
- nil, 14, nil, nil, nil, 14, nil, nil, nil, nil,
- nil, 14, nil, 47, 47, 14, 47, nil, 47, nil,
- nil, 47, nil, 14, 14, 47, 47, 14, 47, nil,
- 47, nil, 47, 47, 47, 47, 47, nil, 47, nil,
- 47, nil, nil, nil, 47, nil, nil, nil, nil, nil,
- 47, 47, 86, 86, 47, 86, nil, 86, nil, nil,
- 86, nil, 47, 47, 86, 86, 47, 86, nil, 86,
- nil, 86, 86, 86, 86, 86, nil, 86, nil, 86,
- nil, nil, nil, 86, nil, nil, nil, nil, nil, 86,
- nil, 87, 87, 86, 87, nil, 87, nil, 86, 87,
- nil, 86, 86, 87, 87, 86, 87, nil, 87, nil,
- 87, 87, 87, 87, 87, nil, 87, nil, 87, nil,
- nil, nil, 87, nil, nil, nil, nil, nil, 87, nil,
- 33, 33, 87, 33, nil, 33, nil, nil, 33, 87,
- 87, 87, 33, 33, 87, 33, nil, 33, nil, 33,
- 33, 33, 33, 33, nil, 33, nil, 33, nil, nil,
- nil, 33, nil, nil, nil, nil, nil, 33, nil, 92,
- 92, 33, 92, nil, 92, nil, nil, 92, nil, 33,
- 33, 92, 92, 33, 92, nil, 92, nil, 92, 92,
- 92, 92, 92, nil, 92, nil, 92, nil, nil, 92,
- 92, nil, nil, nil, nil, nil, 92, nil, 34, 34,
- 92, 34, nil, 34, nil, nil, 34, nil, 92, 92,
- 34, 34, 92, 34, nil, 34, nil, 34, 34, 34,
- 34, 34, nil, 34, nil, 34, nil, nil, nil, 34,
- nil, nil, nil, nil, nil, 34, nil, 97, 97, 34,
- 97, nil, 97, nil, nil, 97, nil, 34, 34, 97,
- 97, 34, 97, nil, 97, nil, 97, 97, 97, 97,
+ 0, 0, 21, 0, 32, 0, 32, 106, 0, 85,
+ 1, 85, 0, 0, 121, 0, 121, 0, 51, 0,
+ 0, 0, 0, 0, 123, 0, 123, 0, 142, 13,
+ 142, 0, 15, 144, 17, 144, 30, 0, 31, 2,
+ 2, 0, 2, 15, 2, 21, 36, 2, 37, 0,
+ 0, 2, 2, 0, 2, 39, 2, 106, 2, 2,
+ 2, 2, 2, 51, 2, 51, 2, 44, 44, 41,
+ 2, 48, 48, 42, 43, 45, 2, 46, 12, 12,
+ 2, 12, 49, 12, 15, 50, 12, 56, 2, 2,
+ 12, 12, 2, 12, 58, 12, 59, 12, 12, 12,
+ 12, 12, 60, 12, 62, 12, 67, 73, 74, 12,
+ 76, 77, 81, 83, 84, 12, 90, 14, 14, 12,
+ 14, 91, 14, 94, 95, 14, 105, 12, 12, 14,
+ 14, 12, 14, 109, 14, 112, 14, 14, 14, 14,
+ 14, 113, 14, 114, 14, 118, 119, 125, 14, 132,
+ 133, 135, 139, 141, 14, nil, nil, nil, 14, nil,
+ 28, 28, 28, 28, nil, 28, 14, 14, 28, nil,
+ 14, nil, 28, 28, nil, 28, nil, 28, nil, 28,
+ 28, 28, 28, 28, nil, 28, nil, 28, nil, nil,
+ nil, 28, nil, nil, nil, nil, nil, 28, nil, 29,
+ 29, 28, 29, 29, 29, nil, nil, 29, nil, 28,
+ 28, 29, 29, 28, 29, nil, 29, nil, 29, 29,
+ 29, 29, 29, nil, 29, nil, 29, nil, nil, nil,
+ 29, nil, nil, nil, nil, nil, 29, nil, 33, 33,
+ 29, 33, nil, 33, nil, nil, 33, nil, 29, 29,
+ 33, 33, 29, 33, nil, 33, nil, 33, 33, 33,
+ 33, 33, nil, 33, nil, 33, nil, nil, nil, 33,
+ nil, nil, nil, nil, nil, 33, nil, 34, 34, 33,
+ 34, nil, 34, nil, nil, 34, nil, 33, 33, 34,
+ 34, 33, 34, nil, 34, nil, 34, 34, 34, 34,
+ 34, nil, 34, nil, 34, nil, nil, nil, 34, nil,
+ nil, nil, nil, nil, 34, nil, 35, 35, 34, 35,
+ nil, 35, nil, nil, 35, nil, 34, 34, 35, 35,
+ 34, 35, nil, 35, nil, 35, 35, 35, 35, 35,
+ nil, 35, nil, 35, nil, nil, nil, 35, nil, nil,
+ nil, nil, nil, 35, nil, 40, 40, 35, 40, nil,
+ 40, nil, nil, 40, nil, 35, 35, 40, 40, 35,
+ 40, nil, 40, nil, 40, 40, 40, 40, 40, nil,
+ 40, nil, 40, nil, nil, nil, 40, nil, nil, nil,
+ nil, nil, 40, nil, 47, 47, 40, 47, nil, 47,
+ nil, nil, 47, nil, 40, 40, 47, 47, 40, 47,
+ nil, 47, nil, 47, 47, 47, 47, 47, nil, 47,
+ nil, 47, nil, nil, nil, 47, nil, nil, nil, nil,
+ nil, 47, 47, nil, nil, 47, nil, 52, 52, 52,
+ 52, nil, 52, 47, 47, 52, nil, 47, nil, 52,
+ 52, nil, 52, nil, 52, nil, 52, 52, 52, 52,
+ 52, nil, 52, nil, 52, nil, nil, nil, 52, nil,
+ nil, nil, nil, nil, 52, nil, 54, 54, 52, 54,
+ 54, 54, nil, nil, 54, nil, 52, 52, 54, 54,
+ 52, 54, nil, 54, nil, 54, 54, 54, 54, 54,
+ nil, 54, nil, 54, nil, nil, nil, 54, nil, nil,
+ nil, nil, nil, 54, nil, 57, 57, 54, 57, nil,
+ 57, nil, nil, 57, nil, 54, 54, 57, 57, 54,
+ 57, nil, 57, nil, 57, 57, 57, 57, 57, nil,
+ 57, nil, 57, nil, nil, 57, 57, nil, nil, nil,
+ nil, nil, 57, nil, 61, 61, 57, 61, nil, 61,
+ nil, nil, 61, nil, 57, 57, 61, 61, 57, 61,
+ nil, 61, nil, 61, 61, 61, 61, 61, nil, 61,
+ nil, 61, nil, nil, nil, 61, nil, nil, 61, nil,
+ nil, 61, nil, 63, 63, 61, 63, nil, 63, nil,
+ nil, 63, nil, 61, 61, 63, 63, 61, 63, nil,
+ 63, nil, 63, 63, 63, 63, 63, nil, 63, nil,
+ 63, nil, nil, nil, 63, nil, nil, nil, nil, 63,
+ 63, nil, nil, nil, 63, nil, 64, 64, nil, 64,
+ nil, 64, 63, 63, 64, nil, 63, nil, 64, 64,
+ 64, 64, nil, 64, nil, 64, 64, 64, 64, 64,
+ nil, 64, nil, 64, nil, nil, nil, 64, nil, nil,
+ nil, nil, nil, 64, nil, 65, 65, 64, 65, nil,
+ 65, nil, nil, 65, nil, 64, 64, 65, 65, 64,
+ 65, 65, 65, nil, 65, 65, 65, 65, 65, nil,
+ 65, nil, 65, nil, nil, nil, 65, nil, nil, nil,
+ nil, nil, 65, nil, 66, 66, 65, 66, nil, 66,
+ nil, nil, 66, nil, 65, 65, 66, 66, 65, 66,
+ nil, 66, 66, 66, 66, 66, 66, 66, nil, 66,
+ nil, 66, nil, nil, nil, 66, nil, nil, nil, nil,
+ nil, 66, nil, 71, 71, 66, 71, nil, 71, nil,
+ nil, 71, nil, 66, 66, 71, 71, 66, 71, nil,
+ 71, nil, 71, 71, 71, 71, 71, nil, 71, nil,
+ 71, nil, nil, nil, 71, nil, nil, nil, nil, nil,
+ 71, nil, 75, 75, 71, 75, nil, 75, nil, nil,
+ 75, nil, 71, 71, 75, 75, 71, 75, nil, 75,
+ nil, 75, 75, 75, 75, 75, nil, 75, nil, 75,
+ nil, nil, nil, 75, nil, nil, nil, nil, nil, 75,
+ nil, 79, 79, 75, 79, nil, 79, nil, nil, 79,
+ nil, 75, 75, 79, 79, 75, 79, nil, 79, nil,
+ 79, 79, 79, 79, 79, nil, 79, nil, 79, nil,
+ nil, nil, 79, nil, nil, nil, nil, nil, 79, 79,
+ 86, 86, 79, 86, nil, 86, nil, nil, 86, nil,
+ 79, 79, 86, 86, 79, 86, nil, 86, nil, 86,
+ 86, 86, 86, 86, nil, 86, nil, 86, nil, nil,
+ nil, 86, nil, nil, nil, nil, nil, 86, nil, 87,
+ 87, 86, 87, nil, 87, nil, 86, 87, nil, 86,
+ 86, 87, 87, 86, 87, nil, 87, nil, 87, 87,
+ 87, 87, 87, nil, 87, nil, 87, nil, nil, nil,
+ 87, nil, nil, nil, nil, nil, 87, nil, 92, 92,
+ 87, 92, nil, 92, nil, nil, 92, 87, 87, 87,
+ 92, 92, 87, 92, nil, 92, nil, 92, 92, 92,
+ 92, 92, nil, 92, nil, 92, nil, nil, 92, 92,
+ nil, nil, nil, nil, nil, 92, nil, 97, 97, 92,
+ 97, nil, 97, nil, nil, 97, nil, 92, 92, 97,
+ 97, 92, 97, nil, 97, nil, 97, 97, 97, 97,
97, nil, 97, nil, 97, nil, nil, nil, 97, nil,
nil, 97, nil, nil, 97, nil, 100, 100, 97, 100,
nil, 100, nil, nil, 100, nil, 97, 97, 100, 100,
97, 100, nil, 100, nil, 100, 100, 100, 100, 100,
nil, 100, nil, 100, nil, nil, nil, 100, nil, nil,
- nil, nil, 100, 100, nil, nil, nil, 100, nil, 52,
- 52, 52, 52, nil, 52, 100, 100, 52, nil, 100,
- nil, 52, 52, nil, 52, nil, 52, nil, 52, 52,
- 52, 52, 52, nil, 52, nil, 52, nil, nil, nil,
- 52, nil, nil, nil, nil, nil, 52, nil, 108, 108,
- 52, 108, nil, 108, nil, 108, 108, nil, 52, 52,
- 108, 108, 52, 108, nil, 108, nil, 108, 108, 108,
- 108, 108, nil, 108, nil, 108, nil, nil, nil, 108,
- nil, nil, nil, nil, nil, 108, nil, 54, 54, 108,
- 54, 54, 54, nil, nil, 54, nil, 108, 108, 54,
- 54, 108, 54, nil, 54, nil, 54, 54, 54, 54,
- 54, nil, 54, nil, 54, nil, nil, nil, 54, nil,
- nil, nil, nil, nil, 54, nil, 111, 111, 54, 111,
- nil, 111, nil, nil, 111, nil, 54, 54, 111, 111,
- 54, 111, nil, 111, nil, 111, 111, 111, 111, 111,
- nil, 111, nil, 111, nil, nil, nil, 111, nil, nil,
- nil, nil, nil, 111, nil, 35, 35, 111, 35, nil,
- 35, nil, nil, 35, nil, 111, 111, 35, 35, 111,
- 35, nil, 35, nil, 35, 35, 35, 35, 35, nil,
- 35, nil, 35, nil, nil, nil, 35, nil, nil, nil,
- nil, nil, 35, nil, 57, 57, 35, 57, nil, 57,
- nil, nil, 57, nil, 35, 35, 57, 57, 35, 57,
- nil, 57, nil, 57, 57, 57, 57, 57, nil, 57,
- nil, 57, nil, nil, 57, 57, nil, nil, nil, nil,
- nil, 57, nil, 12, 12, 57, 12, nil, 12, nil,
- nil, 12, nil, 57, 57, 12, 12, 57, 12, nil,
- 12, nil, 12, 12, 12, 12, 12, nil, 12, nil,
- 12, nil, nil, nil, 12, nil, nil, nil, nil, nil,
- 12, nil, nil, nil, 12, nil, nil, nil, nil, nil,
- nil, nil, 12, 12, nil, nil, 12 ]
+ nil, nil, 100, 100, nil, 108, 108, 100, 108, nil,
+ 108, nil, 108, 108, nil, 100, 100, 108, 108, 100,
+ 108, nil, 108, nil, 108, 108, 108, 108, 108, nil,
+ 108, nil, 108, nil, nil, nil, 108, nil, nil, nil,
+ nil, nil, 108, nil, 111, 111, 108, 111, nil, 111,
+ nil, nil, 111, nil, 108, 108, 111, 111, 108, 111,
+ nil, 111, nil, 111, 111, 111, 111, 111, nil, 111,
+ nil, 111, nil, nil, nil, 111, nil, nil, nil, nil,
+ nil, 111, nil, 120, 120, 111, 120, nil, 120, nil,
+ nil, 120, nil, 111, 111, 120, 120, 111, 120, nil,
+ 120, nil, 120, 120, 120, 120, 120, nil, 120, nil,
+ 120, nil, nil, nil, 120, nil, nil, nil, nil, nil,
+ 120, nil, 122, 122, 120, 122, nil, 122, nil, 120,
+ 122, nil, 120, 120, 122, 122, 120, 122, nil, 122,
+ nil, 122, 122, 122, 122, 122, nil, 122, nil, 122,
+ nil, nil, nil, 122, nil, nil, nil, nil, nil, 122,
+ nil, 134, 134, 122, 134, nil, 134, nil, nil, 134,
+ 122, 122, 122, 134, 134, 122, 134, nil, 134, nil,
+ 134, 134, 134, 134, 134, nil, 134, nil, 134, nil,
+ nil, nil, 134, nil, nil, nil, nil, nil, 134, nil,
+ nil, nil, 134, nil, nil, nil, nil, nil, nil, nil,
+ 134, 134, 136, 136, 134, 136, nil, 136, nil, nil,
+ 136, nil, 136, nil, 136, 136, nil, 136, nil, 136,
+ nil, 136, 136, 136, 136, 136, nil, 136, nil, 136,
+ nil, nil, nil, 136, nil, nil, nil, nil, nil, 136,
+ nil, nil, nil, 136, nil, nil, nil, nil, nil, nil,
+ nil, 136, 136, 152, 152, 136, 152, nil, 152, nil,
+ nil, 152, nil, 152, nil, 152, 152, nil, 152, nil,
+ 152, nil, 152, 152, 152, 152, 152, nil, 152, nil,
+ 152, nil, nil, nil, 152, nil, nil, nil, nil, nil,
+ 152, nil, nil, nil, 152, nil, nil, nil, nil, nil,
+ nil, nil, 152, 152, nil, nil, 152 ]
racc_action_pointer = [
- -2, 10, 158, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 1321, 27, 732, 5, nil, -1, nil, nil,
- nil, 2, nil, nil, nil, nil, nil, nil, 41, 80,
- 11, 23, -2, 888, 966, 1243, 55, 61, nil, 41,
- 314, 67, 67, 21, 60, 76, 25, 771, -3, 37,
- 43, 22, 1087, nil, 1165, nil, 61, 1282, 61, 61,
- 66, 275, 69, 353, 435, 525, 564, -6, nil, nil,
- nil, 654, nil, 106, 99, 119, 99, 110, nil, 693,
- nil, 73, nil, 71, 70, -38, 810, 849, nil, nil,
- 89, 87, 927, nil, 90, 91, nil, 1005, nil, nil,
- 1044, nil, nil, nil, nil, 74, 0, nil, 1126, 116,
- nil, 1204, 119, 135, 127, nil, nil, nil, 100, 101,
- 197, -17, 236, -33, nil, 118, nil, nil, nil, nil,
- nil, nil, 138, 139, 392, 142, 486, nil, nil, 143,
- nil, 110, -21, nil, -13, nil, nil, nil, nil, nil,
- nil, nil, 615, nil, nil, nil, nil, nil ]
+ -2, 10, 37, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 76, 27, 115, 30, nil, -7, nil, nil,
+ nil, 0, nil, nil, nil, nil, nil, nil, 158, 197,
+ 5, 7, -31, 236, 275, 314, 44, 48, nil, 29,
+ 353, 61, 64, 18, 55, 73, 23, 392, 30, 38,
+ 40, 16, 435, nil, 474, nil, 59, 513, 64, 59,
+ 68, 552, 67, 591, 634, 673, 712, 94, nil, nil,
+ nil, 751, nil, 105, 97, 790, 98, 109, nil, 829,
+ nil, 71, nil, 69, 68, -38, 868, 907, nil, nil,
+ 88, 90, 946, nil, 93, 90, nil, 985, nil, nil,
+ 1024, nil, nil, nil, nil, 73, 5, nil, 1063, 121,
+ nil, 1102, 124, 139, 131, nil, nil, nil, 100, 100,
+ 1141, -33, 1180, -23, nil, 116, nil, nil, nil, nil,
+ nil, nil, 137, 138, 1219, 140, 1270, nil, nil, 141,
+ nil, 108, -19, nil, -14, nil, nil, nil, nil, nil,
+ nil, nil, 1321, nil, nil, nil, nil, nil ]
racc_action_default = [
-83, -83, -1, -2, -3, -4, -5, -6, -7, -8,
@@ -368,7 +368,7 @@ racc_action_default = [
racc_goto_table = [
38, 84, 74, 105, 49, 39, 90, 43, 94, 60,
- 135, 133, 1, 2, 47, 41, 107, 59, 112, 56,
+ 135, 1, 133, 2, 47, 41, 107, 112, 59, 56,
58, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, 83, nil, 119, 95, 151, 38, 99,
nil, 52, 54, nil, nil, 80, 64, 65, 66, nil,
@@ -386,7 +386,7 @@ racc_goto_table = [
racc_goto_check = [
3, 23, 15, 30, 22, 12, 25, 12, 25, 28,
- 14, 11, 1, 2, 18, 13, 19, 27, 16, 24,
+ 14, 1, 11, 2, 18, 13, 19, 16, 27, 24,
24, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, 22, nil, 23, 28, 14, 3, 28,
nil, 2, 2, nil, nil, 18, 2, 2, 2, nil,
@@ -403,9 +403,9 @@ racc_goto_check = [
3 ]
racc_goto_pointer = [
- nil, 12, 13, -2, nil, nil, nil, nil, nil, nil,
- nil, -95, -7, 2, -99, -42, -58, nil, -3, -55,
- nil, nil, -17, -50, -11, -50, nil, -15, -23, nil,
+ nil, 11, 13, -2, nil, nil, nil, nil, nil, nil,
+ nil, -94, -7, 2, -99, -42, -59, nil, -3, -55,
+ nil, nil, -17, -50, -11, -50, nil, -14, -23, nil,
-64 ]
racc_goto_default = [
diff --git a/test/racc/regress/mof b/test/racc/regress/mof
index 6f2cbc8464..836604744b 100644
--- a/test/racc/regress/mof
+++ b/test/racc/regress/mof
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -102,94 +102,94 @@ include Scanner
##### State transition tables begin ###
racc_action_table = [
- 13, 172, 163, 197, 174, 200, 63, 17, 145, 146,
- 147, 62, 121, 172, 11, 173, 174, 173, 148, 11,
- 144, 149, 150, 151, 152, 18, 163, 173, 207, 153,
- 106, 107, 108, 109, 110, 112, 111, 199, 15, 16,
- 174, 55, 57, 68, 69, 71, 72, 52, 53, 54,
- 56, 163, 7, 40, -59, 42, 42, 7, 10, 10,
- 115, 102, 114, 121, 10, 55, 57, 68, 69, 71,
- 72, 52, 53, 54, 56, 51, -77, 209, 190, 42,
- 211, 10, 10, 189, 135, 102, 51, 170, 135, 10,
+ 13, 172, 163, 197, 174, 27, 63, 17, 145, 146,
+ 147, 62, 28, 172, 11, 173, 174, 173, 148, 11,
+ 144, 149, 150, 151, 152, 18, 163, 173, 33, 153,
+ 106, 107, 108, 109, 110, 112, 111, 40, 15, 16,
+ 42, 55, 57, 68, 69, 71, 72, 52, 53, 54,
+ 56, 163, 7, 199, 35, 42, 174, 7, 10, 10,
+ 115, 102, 114, 36, 10, 55, 57, 68, 69, 71,
+ 72, 52, 53, 54, 56, 51, 190, 44, -77, 42,
+ 33, 189, 10, 10, 33, 102, 51, 164, 60, 10,
55, 57, 68, 69, 71, 72, 52, 53, 54, 56,
- 164, 218, 10, 21, 42, 22, 23, 10, 95, 96,
- 102, 35, 191, 192, 55, 57, 25, 220, 24, 221,
- 52, 53, 54, 56, 226, 55, 57, 35, 180, 181,
- 228, 52, 53, 54, 56, 93, 79, 80, 81, 82,
+ 170, 35, 10, 21, 42, 22, 23, 10, 29, 31,
+ 102, 35, 95, 96, 55, 57, 25, 65, 24, 78,
+ 52, 53, 54, 56, 97, 55, 57, 35, 180, 181,
+ 100, 52, 53, 54, 56, 93, 79, 80, 81, 82,
83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
-25, 93, 79, 80, 81, 82, 83, 84, 85, 86,
- 87, 88, 89, 90, 91, 92, 29, 31, 229, 231,
+ 87, 88, 89, 90, 91, 92, 191, 192, 102, 60,
55, 57, 68, 69, 71, 72, 52, 53, 54, 56,
- 145, 146, 147, 172, 10, 121, 174, 10, 135, 27,
- 148, 28, 144, 149, 150, 151, 152, 173, 33, 35,
- 36, 153, 55, 57, 68, 69, 71, 72, 52, 53,
+ 145, 146, 147, 172, 113, 97, 174, 10, 18, 118,
+ 148, 119, 144, 149, 150, 151, 152, 173, 121, 124,
+ 35, 153, 55, 57, 68, 69, 71, 72, 52, 53,
54, 56, 106, 107, 108, 109, 110, 112, 111, 10,
55, 57, 68, 69, 71, 72, 52, 53, 54, 56,
- 21, 44, 22, 23, 33, 33, 21, 10, 22, 23,
- 60, 35, 65, 25, 78, 24, 97, 100, 102, 25,
- 60, 24, 93, 79, 80, 81, 82, 83, 84, 85,
+ 21, 126, 22, 23, 127, 129, 21, 10, 22, 23,
+ 130, 131, 133, 25, 135, 24, 10, 141, 154, 25,
+ 35, 24, 93, 79, 80, 81, 82, 83, 84, 85,
86, 87, 88, 89, 90, 91, 92, 106, 107, 108,
- 109, 110, 112, 111, 113, 97, 18, 118, 119, 121,
- 124, 35, 126, 127, 129, 130, 131, 133, 135, 10,
- 141, 154, 35, 184, 185, 194 ]
+ 109, 110, 112, 111, 184, 185, 194, 200, 121, 207,
+ -59, 121, 209, 211, 135, 135, 218, 220, 221, 226,
+ 228, 229, 231, 10, 121, 135 ]
racc_action_check = [
- 1, 140, 211, 186, 140, 188, 37, 8, 131, 131,
- 131, 37, 195, 194, 0, 140, 194, 186, 131, 1,
- 131, 131, 131, 131, 131, 8, 189, 194, 196, 131,
- 192, 192, 192, 192, 192, 192, 192, 187, 7, 7,
- 187, 211, 211, 211, 211, 211, 211, 211, 211, 211,
- 211, 135, 0, 20, 197, 211, 20, 1, 211, 0,
- 75, 211, 75, 198, 1, 189, 189, 189, 189, 189,
- 189, 189, 189, 189, 189, 33, 207, 201, 177, 189,
- 205, 207, 189, 177, 206, 189, 96, 138, 208, 138,
- 135, 135, 135, 135, 135, 135, 135, 135, 135, 135,
- 137, 210, 137, 10, 135, 10, 10, 135, 47, 47,
- 135, 169, 178, 178, 33, 33, 10, 212, 10, 213,
- 33, 33, 33, 33, 217, 96, 96, 216, 142, 142,
- 221, 96, 96, 96, 96, 169, 169, 169, 169, 169,
+ 1, 140, 135, 186, 140, 12, 37, 8, 131, 131,
+ 131, 37, 13, 194, 0, 140, 194, 186, 131, 1,
+ 131, 131, 131, 131, 131, 8, 189, 194, 16, 131,
+ 65, 65, 65, 65, 65, 65, 65, 20, 7, 7,
+ 20, 135, 135, 135, 135, 135, 135, 135, 135, 135,
+ 135, 211, 0, 187, 17, 135, 187, 1, 135, 0,
+ 75, 135, 75, 18, 1, 189, 189, 189, 189, 189,
+ 189, 189, 189, 189, 189, 33, 177, 26, 207, 189,
+ 29, 177, 189, 207, 30, 189, 96, 137, 34, 137,
+ 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
+ 138, 36, 138, 10, 211, 10, 10, 211, 15, 15,
+ 211, 169, 47, 47, 33, 33, 10, 38, 10, 43,
+ 33, 33, 33, 33, 49, 96, 96, 216, 142, 142,
+ 58, 96, 96, 96, 96, 169, 169, 169, 169, 169,
169, 169, 169, 169, 169, 169, 169, 169, 169, 169,
42, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 15, 15, 222, 223,
+ 216, 216, 216, 216, 216, 216, 178, 178, 60, 61,
42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 181, 181, 181, 218, 229, 230, 218, 42, 233, 12,
- 181, 13, 181, 181, 181, 181, 181, 218, 16, 17,
- 18, 181, 40, 40, 40, 40, 40, 40, 40, 40,
+ 181, 181, 181, 218, 66, 70, 218, 42, 74, 77,
+ 181, 78, 181, 181, 181, 181, 181, 218, 94, 98,
+ 100, 181, 40, 40, 40, 40, 40, 40, 40, 40,
40, 40, 141, 141, 141, 141, 141, 141, 141, 40,
115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
- 11, 26, 11, 11, 29, 30, 63, 115, 63, 63,
- 34, 36, 38, 11, 43, 11, 49, 58, 60, 63,
- 61, 63, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 65, 65, 65,
- 65, 65, 65, 65, 66, 70, 74, 77, 78, 94,
- 98, 100, 102, 103, 116, 118, 119, 121, 122, 127,
- 130, 132, 161, 162, 164, 183 ]
+ 11, 102, 11, 11, 103, 116, 63, 115, 63, 63,
+ 118, 119, 121, 11, 122, 11, 127, 130, 132, 63,
+ 161, 63, 44, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 192, 192, 192,
+ 192, 192, 192, 192, 162, 164, 183, 188, 195, 196,
+ 197, 198, 201, 205, 206, 208, 210, 212, 213, 217,
+ 221, 222, 223, 229, 230, 233 ]
racc_action_pointer = [
-5, 0, nil, nil, nil, nil, nil, 32, -2, nil,
- 95, 222, 126, 191, nil, 159, 140, 191, 169, nil,
- -5, nil, nil, nil, nil, nil, 165, nil, nil, 176,
- 177, nil, nil, 67, 212, nil, 233, -54, 176, nil,
- 155, nil, 123, 184, 220, nil, nil, 49, nil, 198,
- nil, nil, nil, nil, nil, nil, nil, nil, 181, nil,
- 181, 222, nil, 228, nil, 255, 215, nil, nil, nil,
- 227, nil, nil, nil, 249, 0, nil, 217, 258, nil,
+ 95, 222, -58, 12, nil, 101, -30, 46, 32, nil,
+ -21, nil, nil, nil, nil, nil, 11, nil, nil, 22,
+ 26, nil, nil, 67, 60, nil, 93, -54, 51, nil,
+ 155, nil, 123, 59, 220, nil, nil, 53, nil, 76,
+ nil, nil, nil, nil, nil, nil, nil, nil, 64, nil,
+ 101, 141, nil, 228, nil, 18, 125, nil, nil, nil,
+ 137, nil, nil, nil, 161, 0, nil, 129, 171, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 215, nil, 78, nil, 219, nil,
- 273, nil, 274, 222, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 173, 221, nil, 259, 228,
- nil, 240, 220, nil, nil, nil, nil, 225, nil, nil,
- 232, -1, 226, nil, nil, 43, nil, 38, 25, nil,
+ nil, nil, nil, nil, 134, nil, 78, nil, 138, nil,
+ 192, nil, 223, 173, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 173, 172, nil, 214, 183,
+ nil, 195, 176, nil, nil, nil, nil, 182, nil, nil,
+ 189, -1, 183, nil, nil, -6, nil, 25, 38, nil,
-7, 200, 69, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 284, 227, nil, 231, nil, nil, nil, nil, 103,
- nil, nil, nil, nil, nil, nil, nil, 15, 53, nil,
- nil, 171, nil, 226, nil, nil, -5, 29, -24, 18,
- nil, nil, 18, nil, 5, -52, -30, -4, -1, nil,
- nil, 14, nil, nil, nil, 12, 16, 17, 20, nil,
- 41, -6, 54, 60, nil, nil, 119, 61, 175, nil,
- nil, 67, 108, 161, nil, nil, nil, nil, nil, 120,
- 121, nil, nil, 120, nil, nil ]
+ nil, 242, 208, nil, 212, nil, nil, nil, nil, 103,
+ nil, nil, nil, nil, nil, nil, nil, 13, 107, nil,
+ nil, 171, nil, 207, nil, nil, -5, 45, 248, 18,
+ nil, nil, 255, nil, 5, 214, 221, 222, 217, nil,
+ nil, 219, nil, nil, nil, 215, 216, 19, 217, nil,
+ 226, 43, 224, 229, nil, nil, 119, 226, 175, nil,
+ nil, 227, 231, 284, nil, nil, nil, nil, nil, 229,
+ 230, nil, nil, 227, nil, nil ]
racc_action_default = [
-1, -25, -2, -4, -5, -6, -7, -161, -161, -26,
@@ -218,14 +218,14 @@ racc_action_default = [
-86, -85, -81, -88, -82, -89 ]
racc_goto_table = [
- 8, 8, 34, 94, 122, 105, 136, 155, 50, 66,
- 49, 76, 48, 19, 143, 187, 58, 204, 215, 32,
- 139, 61, 12, 12, 2, 14, 30, 38, 39, 26,
- 41, 171, 45, 46, 99, 101, 37, 195, 168, 167,
- 232, 227, 166, 103, 198, 196, 213, 214, 165, 222,
- 223, 230, 234, 235, 132, 137, 75, 1, 182, 203,
- 98, 201, 225, 210, 193, 177, 104, 43, 77, 116,
- 117, 50, 142, 49, 47, 123, 178, 138, 64, nil,
+ 8, 8, 34, 94, 122, 105, 136, 155, 48, 66,
+ 49, 76, 50, 19, 143, 187, 58, 204, 215, 32,
+ 139, 61, 2, 14, 12, 12, 1, 30, 47, 98,
+ 137, 171, 45, 46, 165, 166, 167, 168, 37, 26,
+ 232, 227, 38, 103, 64, 39, 41, 99, 101, 195,
+ 198, 196, 213, 214, 222, 223, 230, 234, 235, 132,
+ 75, 201, 225, 182, 193, 203, 104, 210, 177, 43,
+ 77, 123, 116, 49, 117, 50, 142, 178, 138, nil,
nil, 179, nil, 219, 128, 125, nil, nil, nil, nil,
212, nil, 217, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 206, nil, nil, 208, nil,
@@ -243,14 +243,14 @@ racc_goto_table = [
nil, nil, nil, nil, nil, nil, nil, nil, nil, 216 ]
racc_goto_check = [
- 13, 13, 14, 35, 37, 28, 38, 52, 12, 30,
- 11, 30, 10, 23, 69, 39, 15, 61, 44, 7,
- 72, 14, 55, 55, 2, 2, 8, 26, 29, 25,
- 31, 72, 7, 7, 33, 34, 24, 36, 21, 20,
- 44, 61, 19, 15, 40, 41, 42, 43, 18, 45,
- 46, 47, 48, 50, 51, 17, 54, 1, 58, 60,
- 16, 52, 39, 62, 69, 63, 23, 64, 65, 66,
- 67, 12, 68, 11, 9, 10, 70, 71, 27, nil,
+ 13, 13, 14, 35, 37, 28, 38, 52, 10, 30,
+ 11, 30, 12, 23, 69, 39, 15, 61, 44, 7,
+ 72, 14, 2, 2, 55, 55, 1, 8, 9, 16,
+ 17, 72, 7, 7, 18, 19, 20, 21, 24, 25,
+ 44, 61, 26, 15, 27, 29, 31, 33, 34, 36,
+ 40, 41, 42, 43, 45, 46, 47, 48, 50, 51,
+ 54, 52, 39, 58, 69, 60, 23, 62, 63, 64,
+ 65, 10, 66, 11, 67, 12, 68, 70, 71, nil,
nil, 28, nil, 52, 30, 14, nil, nil, nil, nil,
38, nil, 38, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 37, nil, nil, 37, nil,
@@ -268,14 +268,14 @@ racc_goto_check = [
nil, nil, nil, nil, nil, nil, nil, nil, nil, 13 ]
racc_goto_pointer = [
- nil, 57, 24, nil, nil, nil, nil, 3, 11, 41,
- -21, -23, -25, 0, -15, -18, 2, -69, -89, -95,
- -98, -99, nil, 3, 17, 18, 7, 40, -60, 8,
- -31, 10, nil, -24, -25, -41, -149, -90, -116, -154,
- -143, -141, -161, -160, -189, -166, -166, -172, -181, nil,
- -180, -67, -128, nil, 14, 22, nil, nil, -103, nil,
- -135, -177, -141, -75, 41, 25, -8, -7, -59, -117,
- -65, -50, -107 ]
+ nil, 26, 22, nil, nil, nil, nil, 3, 12, -5,
+ -25, -23, -21, 0, -15, -18, -29, -94, -103, -102,
+ -101, -100, nil, 3, 19, 28, 22, 6, -60, 25,
+ -31, 26, nil, -11, -12, -41, -137, -90, -116, -154,
+ -137, -135, -155, -154, -189, -161, -161, -167, -176, nil,
+ -175, -62, -128, nil, 18, 24, nil, nil, -98, nil,
+ -129, -177, -137, -72, 43, 27, -5, -3, -55, -117,
+ -64, -49, -107 ]
racc_goto_default = [
nil, nil, nil, 3, 4, 5, 6, nil, nil, nil,
diff --git a/test/racc/regress/namae b/test/racc/regress/namae
index 43f1b09abb..5a795e4579 100644
--- a/test/racc/regress/namae
+++ b/test/racc/regress/namae
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -185,40 +185,40 @@ module_eval(<<'...end namae.y/module_eval...', 'namae.y', 135)
##### State transition tables begin ###
racc_action_table = [
- -39, 53, 52, 54, -40, 39, 62, -39, 39, -39,
- -39, -40, 67, -40, -40, 66, 53, 52, 54, 32,
- 59, 16, 58, -34, 53, 52, 54, -38, 17, -22,
- 30, 39, 31, 45, -38, 53, 52, 54, 14, 12,
- 15, 68, 39, 7, 8, 14, 12, 15, 58, 33,
- 7, 8, 14, 22, 15, 24, 14, 22, 15, 24,
- -19, -19, -19, 30, 42, 31, 30, 28, 31, -20,
- -20, -20, 30, 46, 31, 53, 52, 54, 30, 28,
- 31, 30, 28, 31, 30, 28, 31, -19, -19, -19,
- 30, 28, 31, 14, 22, 15, 53, 52, 54, 39,
- 58, 59, 39, 59, 39 ]
+ -39, 16, 32, 30, -40, 31, 33, -39, 17, -39,
+ -39, -40, 67, -40, -40, 66, 53, 52, 54, -38,
+ 59, -22, 39, -34, 45, 58, -38, 53, 52, 54,
+ 53, 52, 54, 59, 39, 39, 62, 39, 53, 52,
+ 54, 14, 12, 15, 68, 39, 7, 8, 14, 12,
+ 15, 58, 39, 7, 8, 14, 22, 15, 24, 14,
+ 22, 15, 24, 14, 22, 15, 30, 28, 31, 30,
+ 28, 31, -19, -19, -19, 30, 42, 31, 30, 28,
+ 31, -20, -20, -20, 30, 46, 31, 30, 28, 31,
+ 30, 28, 31, -19, -19, -19, 53, 52, 54, 53,
+ 52, 54, 39, 58, 59 ]
racc_action_check = [
- 14, 32, 32, 32, 15, 64, 44, 14, 32, 14,
- 14, 15, 50, 15, 15, 49, 49, 49, 49, 11,
- 50, 1, 70, 49, 45, 45, 45, 12, 1, 12,
- 43, 45, 43, 27, 12, 62, 62, 62, 0, 0,
- 0, 57, 62, 0, 0, 17, 17, 17, 60, 16,
- 17, 17, 20, 20, 20, 20, 9, 9, 9, 9,
- 22, 22, 22, 24, 24, 24, 25, 25, 25, 28,
- 28, 28, 29, 29, 29, 73, 73, 73, 21, 21,
- 21, 35, 35, 35, 41, 41, 41, 42, 42, 42,
- 10, 10, 10, 5, 5, 5, 67, 67, 67, 61,
- 37, 38, 40, 72, 23 ]
+ 14, 1, 11, 43, 15, 43, 16, 14, 1, 14,
+ 14, 15, 50, 15, 15, 49, 49, 49, 49, 12,
+ 50, 12, 23, 49, 27, 37, 12, 32, 32, 32,
+ 45, 45, 45, 38, 32, 40, 44, 45, 62, 62,
+ 62, 0, 0, 0, 57, 62, 0, 0, 17, 17,
+ 17, 60, 61, 17, 17, 9, 9, 9, 9, 20,
+ 20, 20, 20, 5, 5, 5, 10, 10, 10, 21,
+ 21, 21, 22, 22, 22, 24, 24, 24, 25, 25,
+ 25, 28, 28, 28, 29, 29, 29, 35, 35, 35,
+ 41, 41, 41, 42, 42, 42, 67, 67, 67, 73,
+ 73, 73, 64, 70, 72 ]
racc_action_pointer = [
- 35, 21, nil, nil, nil, 90, nil, nil, nil, 53,
- 87, 17, 27, nil, 0, 4, 49, 42, nil, nil,
- 49, 75, 57, 94, 60, 63, nil, 31, 66, 69,
- nil, nil, -2, nil, nil, 78, nil, 91, 91, nil,
- 92, 81, 84, 27, 4, 21, nil, nil, nil, 13,
- 10, nil, nil, nil, nil, nil, nil, 32, nil, nil,
- 39, 89, 32, nil, -5, nil, nil, 93, nil, nil,
- 13, nil, 93, 72, nil ]
+ 38, 1, nil, nil, nil, 60, nil, nil, nil, 52,
+ 63, 0, 19, nil, 0, 4, 6, 45, nil, nil,
+ 56, 66, 69, 12, 72, 75, nil, 22, 78, 81,
+ nil, nil, 24, nil, nil, 84, nil, 16, 23, nil,
+ 25, 87, 90, 0, 34, 27, nil, nil, nil, 13,
+ 10, nil, nil, nil, nil, nil, nil, 35, nil, nil,
+ 42, 42, 35, nil, 92, nil, nil, 93, nil, nil,
+ 94, nil, 94, 96, nil ]
racc_action_default = [
-1, -49, -2, -4, -5, -49, -8, -9, -10, -23,
@@ -232,7 +232,7 @@ racc_action_default = [
racc_goto_table = [
3, 37, 26, 50, 56, 18, 2, 9, 47, 23,
- 73, 64, 20, 26, 19, 27, 50, 3, 60, 1,
+ 1, 19, 20, 26, 73, 27, 50, 3, 60, 64,
23, 63, 26, 34, 9, nil, 36, 69, 21, 40,
44, 43, 25, 50, nil, 72, 26, 74, 71, 70,
55, nil, nil, 35, nil, nil, 61, 41, nil, 65,
@@ -242,7 +242,7 @@ racc_goto_table = [
racc_goto_check = [
3, 8, 17, 16, 9, 3, 2, 7, 12, 3,
- 14, 15, 7, 17, 4, 10, 16, 3, 8, 1,
+ 1, 4, 7, 17, 14, 10, 16, 3, 8, 15,
3, 12, 17, 2, 7, nil, 10, 9, 11, 10,
10, 7, 11, 16, nil, 16, 17, 9, 12, 8,
10, nil, nil, 11, nil, nil, 10, 11, nil, 3,
@@ -251,8 +251,8 @@ racc_goto_check = [
nil, nil, nil, 3 ]
racc_goto_pointer = [
- nil, 19, 6, 0, 9, nil, nil, 7, -22, -33,
- 5, 23, -24, nil, -57, -38, -29, -7, nil ]
+ nil, 10, 6, 0, 6, nil, nil, 7, -22, -33,
+ 5, 23, -24, nil, -53, -30, -29, -7, nil ]
racc_goto_default = [
nil, nil, nil, 51, 4, 5, 6, 29, nil, nil,
diff --git a/test/racc/regress/nasl b/test/racc/regress/nasl
index ea47343001..9173795a1d 100644
--- a/test/racc/regress/nasl
+++ b/test/racc/regress/nasl
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -98,63 +98,47 @@ end
clist = [
'144,143,161,162,163,164,165,166,157,158,159,160,153,152,151,154,155',
-'156,145,146,147,149,150,82,54,111,148,81,218,83,55,51,50,72,54,54,80',
-'102,103,65,55,55,53,68,54,54,66,95,102,103,55,55,53,53,43,54,218,269',
-'67,226,96,55,53,53,97,98,99,100,101,102,103,104,82,53,267,217,81,130',
-'83,131,51,50,130,54,131,80,130,54,131,55,51,50,225,55,54,195,95,147',
-'149,150,55,53,192,148,54,53,185,37,172,96,55,167,53,97,98,99,100,101',
-'102,103,104,82,53,141,148,81,54,83,148,51,50,148,55,253,80,254,54,255',
-'256,51,50,257,55,54,53,95,147,149,150,55,10,11,148,54,53,258,259,37',
-'96,55,260,53,97,98,99,100,101,102,103,104,82,53,262,138,81,54,83,137',
-'51,50,136,55,54,80,54,54,306,134,55,64,55,55,54,53,95,63,300,56,55,301',
-'53,266,53,53,268,133,94,96,270,43,53,97,98,99,100,101,102,103,104,82',
-'273,11,274,81,275,83,148,51,50,148,54,148,80,179,148,276,55,114,112',
-'109,74,54,73,95,,,,55,53,97,98,99,100,101,102,103,96,,,53,97,98,99,100',
-'101,102,103,104,82,,,,81,,83,,51,50,,54,,80,,,,55,,,,,54,,95,,,,55,53',
-'97,98,99,100,101,102,103,96,,,53,97,98,99,100,101,102,103,104,82,,,',
-'81,,83,,51,50,,,,80,154,155,156,145,146,147,149,150,54,,95,148,,,55',
-',145,146,147,149,150,,,96,148,,53,97,98,99,100,101,102,103,104,82,,',
-',81,,83,,51,50,,,,80,,145,146,147,149,150,,,54,148,95,,,,55,,145,146',
-'147,149,150,,,96,148,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,',
-'51,50,,,,80,97,98,99,100,101,,,,54,,95,,,,55,97,98,99,100,101,,,,96',
-',,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,97,98,99',
-'100,101,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104',
-'82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98',
-'99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55',
-',,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,',
-'80,208,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99,100,101,102,103',
-'104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97',
-'98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,',
-',,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50',
-',,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103',
-'104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53',
-'97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95',
+'156,145,146,147,149,150,82,54,111,148,81,218,83,55,51,50,56,54,54,80',
+'11,78,65,55,55,53,63,54,54,66,95,102,103,55,55,53,53,64,54,218,269,67',
+'94,96,55,53,53,97,98,99,100,101,102,103,104,82,53,267,217,81,130,83',
+'131,51,50,130,54,131,80,130,54,131,55,51,50,68,55,54,72,95,147,149,150',
+'55,53,73,148,54,53,102,103,74,96,55,109,53,97,98,99,100,101,102,103',
+'104,82,53,112,114,81,54,83,133,51,50,134,55,136,80,137,54,138,141,51',
+'50,167,55,54,53,95,147,149,150,55,10,11,148,54,53,172,37,37,96,55,185',
+'53,97,98,99,100,101,102,103,104,82,53,192,195,81,225,83,226,51,50,148',
+'54,148,80,179,148,253,55,254,255,54,54,54,256,95,257,55,55,55,53,97',
+'98,99,100,101,102,103,96,53,53,53,97,98,99,100,101,102,103,104,82,54',
+'258,259,81,260,83,55,51,50,262,54,266,80,268,270,43,55,273,53,54,274',
+'54,275,95,148,55,148,55,53,97,98,99,100,101,102,103,96,53,148,53,97',
+'98,99,100,101,102,103,104,82,148,276,43,81,300,83,301,51,50,306,,,80',
+'154,155,156,145,146,147,149,150,54,,95,148,,,55,,145,146,147,149,150',
+',,96,148,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80',
+',145,146,147,149,150,,,54,148,95,,,,55,,,145,146,147,149,150,94,96,184',
+'148,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,97,98',
+'99,100,101,,,,54,,95,,,,55,97,98,99,100,101,,,,96,,,53,97,98,99,100',
+'101,102,103,104,82,,,,81,,83,,51,50,,,,80,97,98,99,100,101,,,,54,,95',
',,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51',
-'50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103',
-'104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97',
-'98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,',
-',,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50',
-',,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103',
-'104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97',
-'98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,',
-',,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50',
-',,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103',
-'104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97',
-'98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,',
-',,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50',
-',,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103',
-'104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53',
-'97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95',
-',,,55,,,,,,,,94,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51',
-'50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103',
-'104,82,,,,81,,83,,51,50,,,,80,,78,,,,,,,54,,95,,,,55,,,,,,,,94,96,,',
+'50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99,100,101,102',
+'103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,',
'53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54',
',95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83',
-',51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99,100,101',
-'102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94',
-'96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,',
-',,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99,100,101,102,103,104,82,,',
-',81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99',
+',51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102',
+'103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,',
+'53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54',
+',95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83',
+',51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102',
+'103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,',
+'53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54',
+',95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83',
+',51,50,,,,80,208,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99,100',
+'101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,',
+',,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,',
+',,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99,100,101,102,103,104,82',
+',,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99',
+'100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,',
+',,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80',
+',,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82',
+',,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99',
'100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,',
',,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80',
',,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82',
@@ -172,45 +156,57 @@ clist = [
',,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82',
',,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99',
'100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,',
-',,,,,,94,96,184,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50',
-',,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103',
-'104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97',
+',,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80',
+',,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82',
+',,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99',
+'100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,',
+',,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80',
+',,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82',
+',,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99',
+'100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,',
+',,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80',
+',,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82',
+',,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99',
+'100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,',
+',,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80',
+',,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99,100,101,102,103,104',
+'82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97',
'98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,',
-',,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50',
-',,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103',
-'104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,,53,97',
-'98,99,100,101,102,103,104,115,116,117,118,119,120,123,122,121,115,116',
-'117,118,119,120,123,122,121,153,152,151,154,155,156,145,146,147,149',
-'150,,,,148,,,,126,125,,,,124,,,,126,125,,,,124,144,143,161,162,163,164',
-'165,166,157,158,159,160,153,152,151,154,155,156,145,146,147,149,150',
-',,,148,,,,,,,,142,144,143,161,162,163,164,165,166,157,158,159,160,153',
-'152,151,154,155,156,145,146,147,149,150,,,,148,,,,,,,,221,144,143,161',
+',,55,,,,,,,,94,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51',
+'50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99,100,101,102',
+'103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,,96,,',
+'53,97,98,99,100,101,102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54',
+',95,,,,55,,,,,,,,,96,,,53,97,98,99,100,101,102,103,104,82,,,,81,,83',
+',51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94,96,,,53,97,98,99,100,101',
+'102,103,104,82,,,,81,,83,,51,50,,,,80,,,,,,,,,54,,95,,,,55,,,,,,,,94',
+'96,,,53,97,98,99,100,101,102,103,104,115,116,117,118,119,120,123,122',
+'121,115,116,117,118,119,120,123,122,121,153,152,151,154,155,156,145',
+'146,147,149,150,,,,148,,,,126,125,,,,124,,,,126,125,,,,124,144,143,161',
'162,163,164,165,166,157,158,159,160,153,152,151,154,155,156,145,146',
-'147,149,150,,,,148,,,,,,,,297,144,143,161,162,163,164,165,166,157,158',
-'159,160,153,152,151,154,155,156,145,146,147,149,150,,,,148,,,,,,,,289',
+'147,149,150,,,,148,,,,,,,,142,144,143,161,162,163,164,165,166,157,158',
+'159,160,153,152,151,154,155,156,145,146,147,149,150,,,,148,,,,,,,,221',
'144,143,161,162,163,164,165,166,157,158,159,160,153,152,151,154,155',
-'156,145,146,147,149,150,,,,148,,,,,,,286,144,143,161,162,163,164,165',
+'156,145,146,147,149,150,,,,148,,,,,,,,289,144,143,161,162,163,164,165',
'166,157,158,159,160,153,152,151,154,155,156,145,146,147,149,150,,,,148',
-',,,,,,265,144,143,161,162,163,164,165,166,157,158,159,160,153,152,151',
-'154,155,156,145,146,147,149,150,,,,148,,,,,,,299,144,143,161,162,163',
+',,,,,,,297,144,143,161,162,163,164,165,166,157,158,159,160,153,152,151',
+'154,155,156,145,146,147,149,150,,,,148,,,,,,,251,144,143,161,162,163',
'164,165,166,157,158,159,160,153,152,151,154,155,156,145,146,147,149',
'150,,,,148,,,,,,,263,144,143,161,162,163,164,165,166,157,158,159,160',
-'153,152,151,154,155,156,145,146,147,149,150,,,,148,51,50,4,10,11,,251',
+'153,152,151,154,155,156,145,146,147,149,150,,,,148,,,,,,,265,144,143',
+'161,162,163,164,165,166,157,158,159,160,153,152,151,154,155,156,145',
+'146,147,149,150,,,,148,,,,,,,286,144,143,161,162,163,164,165,166,157',
+'158,159,160,153,152,151,154,155,156,145,146,147,149,150,,,,148,51,50',
+'4,10,11,,299,36,32,34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50',
+'4,10,11,,53,36,32,34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50',
+'105,,,,53,36,32,34,37,39,40,41,54,42,43,107,44,45,55,46,,47,,48,51,50',
+'105,,,,53,36,32,34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105',
+',,,53,36,32,34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,',
+',,53,36,32,34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,',
+',53,36,32,34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,,',
+'53,36,32,34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,,,53',
'36,32,34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,,,53,36',
'32,34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,,,53,36,32',
-'34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,,,53,36,32,34',
-'37,39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,,,53,36,32,34,37',
-'39,40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,,,53,36,32,34,37,39',
-'40,41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,,,53,36,32,34,37,39,40',
-'41,54,42,43,107,44,45,55,46,,47,,48,51,50,105,,,,53,36,32,34,37,39,40',
-'41,54,42,43,,44,45,55,46,,47,,48,51,50,105,,,,53,36,32,34,37,39,40,41',
-'54,42,43,,44,45,55,46,,47,,48,51,50,4,10,11,,53,36,32,34,37,39,40,41',
-'54,42,43,,44,45,55,46,,47,,48,51,50,105,,,,53,36,32,34,37,39,40,41,54',
-'42,43,,44,45,55,46,,47,,48,,,,,,,53,144,143,161,162,163,164,165,166',
-'157,158,159,160,153,152,151,154,155,156,145,146,147,149,150,,,,148,144',
-'143,161,162,163,164,165,166,157,158,159,160,153,152,151,154,155,156',
-'145,146,147,149,150,,,,148,144,143,161,162,163,164,165,166,157,158,159',
-'160,153,152,151,154,155,156,145,146,147,149,150,,,,148,144,143,161,162',
+'34,37,39,40,41,54,42,43,,44,45,55,46,,47,,48,,,,,,,53,144,143,161,162',
'163,164,165,166,157,158,159,160,153,152,151,154,155,156,145,146,147',
'149,150,,,,148,144,143,161,162,163,164,165,166,157,158,159,160,153,152',
'151,154,155,156,145,146,147,149,150,,,,148,144,143,161,162,163,164,165',
@@ -229,17 +225,21 @@ clist = [
'146,147,149,150,,,,148,144,143,161,162,163,164,165,166,157,158,159,160',
'153,152,151,154,155,156,145,146,147,149,150,,,,148,144,143,161,162,163',
'164,165,166,157,158,159,160,153,152,151,154,155,156,145,146,147,149',
-'150,,,,148,143,161,162,163,164,165,166,157,158,159,160,153,152,151,154',
-'155,156,145,146,147,149,150,,,,148,161,162,163,164,165,166,157,158,159',
-'160,153,152,151,154,155,156,145,146,147,149,150,,,,148,153,152,151,154',
-'155,156,145,146,147,149,150,,,,148,153,152,151,154,155,156,145,146,147',
-'149,150,,,,148,153,152,151,154,155,156,145,146,147,149,150,,,,148,153',
-'152,151,154,155,156,145,146,147,149,150,,,,148,153,152,151,154,155,156',
-'145,146,147,149,150,,,,148,153,152,151,154,155,156,145,146,147,149,150',
-',,,148,153,152,151,154,155,156,145,146,147,149,150,,,,148,153,152,151',
-'154,155,156,145,146,147,149,150,,,,148,153,152,151,154,155,156,145,146',
-'147,149,150,,,,148,152,151,154,155,156,145,146,147,149,150,,,,148,151',
-'154,155,156,145,146,147,149,150,,,,148' ]
+'150,,,,148,144,143,161,162,163,164,165,166,157,158,159,160,153,152,151',
+'154,155,156,145,146,147,149,150,,,,148,144,143,161,162,163,164,165,166',
+'157,158,159,160,153,152,151,154,155,156,145,146,147,149,150,,,,148,144',
+'143,161,162,163,164,165,166,157,158,159,160,153,152,151,154,155,156',
+'145,146,147,149,150,,,,148,143,161,162,163,164,165,166,157,158,159,160',
+'153,152,151,154,155,156,145,146,147,149,150,,,,148,161,162,163,164,165',
+'166,157,158,159,160,153,152,151,154,155,156,145,146,147,149,150,,,,148',
+'153,152,151,154,155,156,145,146,147,149,150,,,,148,153,152,151,154,155',
+'156,145,146,147,149,150,,,,148,153,152,151,154,155,156,145,146,147,149',
+'150,,,,148,153,152,151,154,155,156,145,146,147,149,150,,,,148,153,152',
+'151,154,155,156,145,146,147,149,150,,,,148,153,152,151,154,155,156,145',
+'146,147,149,150,,,,148,153,152,151,154,155,156,145,146,147,149,150,',
+',,148,153,152,151,154,155,156,145,146,147,149,150,,,,148,153,152,151',
+'154,155,156,145,146,147,149,150,,,,148,152,151,154,155,156,145,146,147',
+'149,150,,,,148,151,154,155,156,145,146,147,149,150,,,,148' ]
racc_action_table = arr = ::Array.new(4010, nil)
idx = 0
clist.each do |str|
@@ -251,132 +251,132 @@ clist = [
clist = [
'213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213,213',
-'213,213,213,213,213,213,150,138,45,213,150,273,150,138,150,150,38,45',
-'94,150,74,74,33,45,94,138,35,51,150,33,150,73,73,51,150,45,94,270,273',
-'134,213,34,140,150,273,51,150,150,150,150,150,150,150,150,150,157,273',
-'210,134,157,210,157,210,157,157,52,134,52,157,132,50,132,134,297,297',
-'139,50,157,113,157,230,230,230,157,134,110,230,297,50,106,105,90,157',
-'297,77,157,157,157,157,157,157,157,157,157,114,297,75,169,114,11,114',
-'170,114,114,171,11,174,114,175,41,176,177,109,109,178,41,114,11,114',
-'229,229,229,114,4,4,229,109,41,182,183,4,114,109,187,114,114,114,114',
-'114,114,114,114,114,115,109,193,71,115,37,115,70,115,115,69,37,111,115',
-'131,218,302,62,111,32,131,218,115,37,115,31,288,1,115,296,111,207,131',
-'218,212,56,115,115,216,217,115,115,115,115,115,115,115,115,115,116,220',
-'10,225,116,226,116,231,116,116,232,95,233,116,95,234,252,95,48,46,44',
-'40,116,39,116,,,,116,95,95,95,95,95,95,95,95,116,,,116,116,116,116,116',
-'116,116,116,116,117,,,,117,,117,,117,117,,256,,117,,,,256,,,,,117,,117',
-',,,117,256,256,256,256,256,256,256,256,117,,,117,117,117,117,117,117',
-'117,117,117,118,,,,118,,118,,118,118,,,,118,235,235,235,235,235,235',
-'235,235,118,,118,235,,,118,,238,238,238,238,238,,,118,238,,118,118,118',
-'118,118,118,118,118,118,119,,,,119,,119,,119,119,,,,119,,239,239,239',
-'239,239,,,119,239,119,,,,119,,240,240,240,240,240,,,119,240,,119,119',
-'119,119,119,119,119,119,119,120,,,,120,,120,,120,120,,,,120,276,276',
-'276,276,276,,,,120,,120,,,,120,172,172,172,172,172,,,,120,,,120,120',
-'120,120,120,120,120,120,120,121,,,,121,,121,,121,121,,,,121,301,301',
-'301,301,301,,,,121,,121,,,,121,,,,,,,,,121,,,121,121,121,121,121,121',
-'121,121,121,122,,,,122,,122,,122,122,,,,122,,,,,,,,,122,,122,,,,122',
-',,,,,,,,122,,,122,122,122,122,122,122,122,122,122,123,,,,123,,123,,123',
-'123,,,,123,,,,,,,,,123,,123,,,,123,,,,,,,,,123,,,123,123,123,123,123',
-'123,123,123,123,124,,,,124,,124,,124,124,,,,124,124,,,,,,,,124,,124',
-',,,124,,,,,,,,124,124,,,124,124,124,124,124,124,124,124,124,130,,,,130',
-',130,,130,130,,,,130,,,,,,,,,130,,130,,,,130,,,,,,,,,130,,,130,130,130',
-'130,130,130,130,130,130,156,,,,156,,156,,156,156,,,,156,,,,,,,,,156',
-',156,,,,156,,,,,,,,,156,,,156,156,156,156,156,156,156,156,156,155,,',
-',155,,155,,155,155,,,,155,,,,,,,,,155,,155,,,,155,,,,,,,,,155,,,155',
-'155,155,155,155,155,155,155,155,137,,,,137,,137,,137,137,,,,137,,,,',
-',,,,137,,137,,,,137,,,,,,,,137,137,,,137,137,137,137,137,137,137,137',
-'137,154,,,,154,,154,,154,154,,,,154,,,,,,,,,154,,154,,,,154,,,,,,,,',
-'154,,,154,154,154,154,154,154,154,154,154,153,,,,153,,153,,153,153,',
-',,153,,,,,,,,,153,,153,,,,153,,,,,,,,,153,,,153,153,153,153,153,153',
-'153,153,153,152,,,,152,,152,,152,152,,,,152,,,,,,,,,152,,152,,,,152',
-',,,,,,,,152,,,152,152,152,152,152,152,152,152,152,143,,,,143,,143,,143',
-'143,,,,143,,,,,,,,,143,,143,,,,143,,,,,,,,,143,,,143,143,143,143,143',
-'143,143,143,143,144,,,,144,,144,,144,144,,,,144,,,,,,,,,144,,144,,,',
-'144,,,,,,,,,144,,,144,144,144,144,144,144,144,144,144,145,,,,145,,145',
-',145,145,,,,145,,,,,,,,,145,,145,,,,145,,,,,,,,,145,,,145,145,145,145',
-'145,145,145,145,145,146,,,,146,,146,,146,146,,,,146,,,,,,,,,146,,146',
-',,,146,,,,,,,,,146,,,146,146,146,146,146,146,146,146,146,147,,,,147',
-',147,,147,147,,,,147,,,,,,,,,147,,147,,,,147,,,,,,,,,147,,,147,147,147',
-'147,147,147,147,147,147,148,,,,148,,148,,148,148,,,,148,,,,,,,,,148',
-',148,,,,148,,,,,,,,,148,,,148,148,148,148,148,148,148,148,148,149,,',
-',149,,149,,149,149,,,,149,,,,,,,,,149,,149,,,,149,,,,,,,,,149,,,149',
-'149,149,149,149,149,149,149,149,151,,,,151,,151,,151,151,,,,151,,,,',
-',,,,151,,151,,,,151,,,,,,,,,151,,,151,151,151,151,151,151,151,151,151',
-'268,,,,268,,268,,268,268,,,,268,,,,,,,,,268,,268,,,,268,,,,,,,,268,268',
-',,268,268,268,268,268,268,268,268,268,267,,,,267,,267,,267,267,,,,267',
-',,,,,,,,267,,267,,,,267,,,,,,,,267,267,,,267,267,267,267,267,267,267',
-'267,267,262,,,,262,,262,,262,262,,,,262,,,,,,,,,262,,262,,,,262,,,,',
-',,,,262,,,262,262,262,262,262,262,262,262,262,42,,,,42,,42,,42,42,,',
-',42,,42,,,,,,,42,,42,,,,42,,,,,,,,42,42,,,42,42,42,42,42,42,42,42,42',
-'260,,,,260,,260,,260,260,,,,260,,,,,,,,,260,,260,,,,260,,,,,,,,,260',
-',,260,260,260,260,260,260,260,260,260,258,,,,258,,258,,258,258,,,,258',
-',,,,,,,,258,,258,,,,258,,,,,,,,258,258,,,258,258,258,258,258,258,258',
-'258,258,255,,,,255,,255,,255,255,,,,255,,,,,,,,,255,,255,,,,255,,,,',
-',,,255,255,,,255,255,255,255,255,255,255,255,255,254,,,,254,,254,,254',
-'254,,,,254,,,,,,,,,254,,254,,,,254,,,,,,,,254,254,,,254,254,254,254',
-'254,254,254,254,254,253,,,,253,,253,,253,253,,,,253,,,,,,,,,253,,253',
-',,,253,,,,,,,,253,253,,,253,253,253,253,253,253,253,253,253,66,,,,66',
-',66,,66,66,,,,66,,,,,,,,,66,,66,,,,66,,,,,,,,,66,,,66,66,66,66,66,66',
-'66,66,66,195,,,,195,,195,,195,195,,,,195,,,,,,,,,195,,195,,,,195,,,',
-',,,,,195,,,195,195,195,195,195,195,195,195,195,192,,,,192,,192,,192',
-'192,,,,192,,,,,,,,,192,,192,,,,192,,,,,,,,,192,,,192,192,192,192,192',
-'192,192,192,192,166,,,,166,,166,,166,166,,,,166,,,,,,,,,166,,166,,,',
-'166,,,,,,,,,166,,,166,166,166,166,166,166,166,166,166,165,,,,165,,165',
-',165,165,,,,165,,,,,,,,,165,,165,,,,165,,,,,,,,,165,,,165,165,165,165',
-'165,165,165,165,165,80,,,,80,,80,,80,80,,,,80,,,,,,,,,80,,80,,,,80,',
-',,,,,,,80,,,80,80,80,80,80,80,80,80,80,81,,,,81,,81,,81,81,,,,81,,,',
-',,,,,81,,81,,,,81,,,,,,,,,81,,,81,81,81,81,81,81,81,81,81,82,,,,82,',
-'82,,82,82,,,,82,,,,,,,,,82,,82,,,,82,,,,,,,,,82,,,82,82,82,82,82,82',
-'82,82,82,83,,,,83,,83,,83,83,,,,83,,,,,,,,,83,,83,,,,83,,,,,,,,,83,',
-',83,83,83,83,83,83,83,83,83,164,,,,164,,164,,164,164,,,,164,,,,,,,,',
-'164,,164,,,,164,,,,,,,,,164,,,164,164,164,164,164,164,164,164,164,163',
-',,,163,,163,,163,163,,,,163,,,,,,,,,163,,163,,,,163,,,,,,,,,163,,,163',
-'163,163,163,163,163,163,163,163,162,,,,162,,162,,162,162,,,,162,,,,',
-',,,,162,,162,,,,162,,,,,,,,,162,,,162,162,162,162,162,162,162,162,162',
-'96,,,,96,,96,,96,96,,,,96,,,,,,,,,96,,96,,,,96,,,,,,,,96,96,96,,96,96',
-'96,96,96,96,96,96,96,161,,,,161,,161,,161,161,,,,161,,,,,,,,,161,,161',
-',,,161,,,,,,,,,161,,,161,161,161,161,161,161,161,161,161,160,,,,160',
-',160,,160,160,,,,160,,,,,,,,,160,,160,,,,160,,,,,,,,,160,,,160,160,160',
-'160,160,160,160,160,160,159,,,,159,,159,,159,159,,,,159,,,,,,,,,159',
-',159,,,,159,,,,,,,,,159,,,159,159,159,159,159,159,159,159,159,158,,',
-',158,,158,,158,158,,,,158,,,,,,,,,158,,158,,,,158,,,,,,,,,158,,,158',
-'158,158,158,158,158,158,158,158,112,,,,112,,112,,112,112,,,,112,,,,',
-',,,,112,,112,,,,112,,,,,,,,,112,,,112,112,112,112,112,112,112,112,112',
-'79,79,79,79,79,79,79,79,79,49,49,49,49,49,49,49,49,49,242,242,242,242',
-'242,242,242,242,242,242,242,,,,242,,,,79,79,,,,79,,,,49,49,,,,49,76',
-'76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,,',
-',76,,,,,,,,76,135,135,135,135,135,135,135,135,135,135,135,135,135,135',
-'135,135,135,135,135,135,135,135,135,,,,135,,,,,,,,135,285,285,285,285',
-'285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285,285',
-'285,285,,,,285,,,,,,,,285,264,264,264,264,264,264,264,264,264,264,264',
-'264,264,264,264,264,264,264,264,264,264,264,264,,,,264,,,,,,,,264,261',
+'213,213,213,213,213,213,42,11,45,213,42,273,42,11,42,42,1,45,37,42,10',
+'42,33,45,37,11,31,41,42,33,42,73,73,41,42,45,37,32,273,134,213,34,42',
+'42,273,41,42,42,42,42,42,42,42,42,42,66,273,210,134,66,210,66,210,66',
+'66,52,134,52,66,132,50,132,134,109,109,35,50,66,38,66,229,229,229,66',
+'134,39,229,109,50,74,74,40,66,109,44,66,66,66,66,66,66,66,66,66,80,109',
+'46,48,80,51,80,56,80,80,62,51,69,80,70,94,71,75,297,297,77,94,80,51',
+'80,230,230,230,80,4,4,230,297,94,90,105,4,80,297,106,80,80,80,80,80',
+'80,80,80,80,81,297,110,113,81,139,81,140,81,81,169,95,170,81,95,171',
+'174,95,175,176,111,131,81,177,81,178,111,131,81,95,95,95,95,95,95,95',
+'95,81,111,131,81,81,81,81,81,81,81,81,81,82,138,182,183,82,187,82,138',
+'82,82,193,256,207,82,212,216,217,256,220,138,218,225,82,226,82,231,218',
+'232,82,256,256,256,256,256,256,256,256,82,218,233,82,82,82,82,82,82',
+'82,82,82,83,234,252,270,83,288,83,296,83,83,302,,,83,235,235,235,235',
+'235,235,235,235,83,,83,235,,,83,,238,238,238,238,238,,,83,238,,83,83',
+'83,83,83,83,83,83,83,96,,,,96,,96,,96,96,,,,96,,239,239,239,239,239',
+',,96,239,96,,,,96,,,240,240,240,240,240,96,96,96,240,96,96,96,96,96',
+'96,96,96,96,112,,,,112,,112,,112,112,,,,112,172,172,172,172,172,,,,112',
+',112,,,,112,276,276,276,276,276,,,,112,,,112,112,112,112,112,112,112',
+'112,112,114,,,,114,,114,,114,114,,,,114,301,301,301,301,301,,,,114,',
+'114,,,,114,,,,,,,,,114,,,114,114,114,114,114,114,114,114,114,115,,,',
+'115,,115,,115,115,,,,115,,,,,,,,,115,,115,,,,115,,,,,,,,115,115,,,115',
+'115,115,115,115,115,115,115,115,116,,,,116,,116,,116,116,,,,116,,,,',
+',,,,116,,116,,,,116,,,,,,,,,116,,,116,116,116,116,116,116,116,116,116',
+'117,,,,117,,117,,117,117,,,,117,,,,,,,,,117,,117,,,,117,,,,,,,,,117',
+',,117,117,117,117,117,117,117,117,117,118,,,,118,,118,,118,118,,,,118',
+',,,,,,,,118,,118,,,,118,,,,,,,,,118,,,118,118,118,118,118,118,118,118',
+'118,119,,,,119,,119,,119,119,,,,119,,,,,,,,,119,,119,,,,119,,,,,,,,',
+'119,,,119,119,119,119,119,119,119,119,119,120,,,,120,,120,,120,120,',
+',,120,,,,,,,,,120,,120,,,,120,,,,,,,,,120,,,120,120,120,120,120,120',
+'120,120,120,121,,,,121,,121,,121,121,,,,121,,,,,,,,,121,,121,,,,121',
+',,,,,,,,121,,,121,121,121,121,121,121,121,121,121,122,,,,122,,122,,122',
+'122,,,,122,,,,,,,,,122,,122,,,,122,,,,,,,,,122,,,122,122,122,122,122',
+'122,122,122,122,123,,,,123,,123,,123,123,,,,123,,,,,,,,,123,,123,,,',
+'123,,,,,,,,,123,,,123,123,123,123,123,123,123,123,123,124,,,,124,,124',
+',124,124,,,,124,124,,,,,,,,124,,124,,,,124,,,,,,,,124,124,,,124,124',
+'124,124,124,124,124,124,124,130,,,,130,,130,,130,130,,,,130,,,,,,,,',
+'130,,130,,,,130,,,,,,,,,130,,,130,130,130,130,130,130,130,130,130,137',
+',,,137,,137,,137,137,,,,137,,,,,,,,,137,,137,,,,137,,,,,,,,137,137,',
+',137,137,137,137,137,137,137,137,137,143,,,,143,,143,,143,143,,,,143',
+',,,,,,,,143,,143,,,,143,,,,,,,,,143,,,143,143,143,143,143,143,143,143',
+'143,144,,,,144,,144,,144,144,,,,144,,,,,,,,,144,,144,,,,144,,,,,,,,',
+'144,,,144,144,144,144,144,144,144,144,144,145,,,,145,,145,,145,145,',
+',,145,,,,,,,,,145,,145,,,,145,,,,,,,,,145,,,145,145,145,145,145,145',
+'145,145,145,146,,,,146,,146,,146,146,,,,146,,,,,,,,,146,,146,,,,146',
+',,,,,,,,146,,,146,146,146,146,146,146,146,146,146,147,,,,147,,147,,147',
+'147,,,,147,,,,,,,,,147,,147,,,,147,,,,,,,,,147,,,147,147,147,147,147',
+'147,147,147,147,148,,,,148,,148,,148,148,,,,148,,,,,,,,,148,,148,,,',
+'148,,,,,,,,,148,,,148,148,148,148,148,148,148,148,148,149,,,,149,,149',
+',149,149,,,,149,,,,,,,,,149,,149,,,,149,,,,,,,,,149,,,149,149,149,149',
+'149,149,149,149,149,150,,,,150,,150,,150,150,,,,150,,,,,,,,,150,,150',
+',,,150,,,,,,,,,150,,,150,150,150,150,150,150,150,150,150,151,,,,151',
+',151,,151,151,,,,151,,,,,,,,,151,,151,,,,151,,,,,,,,,151,,,151,151,151',
+'151,151,151,151,151,151,152,,,,152,,152,,152,152,,,,152,,,,,,,,,152',
+',152,,,,152,,,,,,,,,152,,,152,152,152,152,152,152,152,152,152,153,,',
+',153,,153,,153,153,,,,153,,,,,,,,,153,,153,,,,153,,,,,,,,,153,,,153',
+'153,153,153,153,153,153,153,153,154,,,,154,,154,,154,154,,,,154,,,,',
+',,,,154,,154,,,,154,,,,,,,,,154,,,154,154,154,154,154,154,154,154,154',
+'155,,,,155,,155,,155,155,,,,155,,,,,,,,,155,,155,,,,155,,,,,,,,,155',
+',,155,155,155,155,155,155,155,155,155,156,,,,156,,156,,156,156,,,,156',
+',,,,,,,,156,,156,,,,156,,,,,,,,,156,,,156,156,156,156,156,156,156,156',
+'156,157,,,,157,,157,,157,157,,,,157,,,,,,,,,157,,157,,,,157,,,,,,,,',
+'157,,,157,157,157,157,157,157,157,157,157,158,,,,158,,158,,158,158,',
+',,158,,,,,,,,,158,,158,,,,158,,,,,,,,,158,,,158,158,158,158,158,158',
+'158,158,158,159,,,,159,,159,,159,159,,,,159,,,,,,,,,159,,159,,,,159',
+',,,,,,,,159,,,159,159,159,159,159,159,159,159,159,160,,,,160,,160,,160',
+'160,,,,160,,,,,,,,,160,,160,,,,160,,,,,,,,,160,,,160,160,160,160,160',
+'160,160,160,160,161,,,,161,,161,,161,161,,,,161,,,,,,,,,161,,161,,,',
+'161,,,,,,,,,161,,,161,161,161,161,161,161,161,161,161,162,,,,162,,162',
+',162,162,,,,162,,,,,,,,,162,,162,,,,162,,,,,,,,,162,,,162,162,162,162',
+'162,162,162,162,162,163,,,,163,,163,,163,163,,,,163,,,,,,,,,163,,163',
+',,,163,,,,,,,,,163,,,163,163,163,163,163,163,163,163,163,164,,,,164',
+',164,,164,164,,,,164,,,,,,,,,164,,164,,,,164,,,,,,,,,164,,,164,164,164',
+'164,164,164,164,164,164,165,,,,165,,165,,165,165,,,,165,,,,,,,,,165',
+',165,,,,165,,,,,,,,,165,,,165,165,165,165,165,165,165,165,165,166,,',
+',166,,166,,166,166,,,,166,,,,,,,,,166,,166,,,,166,,,,,,,,,166,,,166',
+'166,166,166,166,166,166,166,166,192,,,,192,,192,,192,192,,,,192,,,,',
+',,,,192,,192,,,,192,,,,,,,,,192,,,192,192,192,192,192,192,192,192,192',
+'195,,,,195,,195,,195,195,,,,195,,,,,,,,,195,,195,,,,195,,,,,,,,,195',
+',,195,195,195,195,195,195,195,195,195,253,,,,253,,253,,253,253,,,,253',
+',,,,,,,,253,,253,,,,253,,,,,,,,253,253,,,253,253,253,253,253,253,253',
+'253,253,254,,,,254,,254,,254,254,,,,254,,,,,,,,,254,,254,,,,254,,,,',
+',,,254,254,,,254,254,254,254,254,254,254,254,254,255,,,,255,,255,,255',
+'255,,,,255,,,,,,,,,255,,255,,,,255,,,,,,,,255,255,,,255,255,255,255',
+'255,255,255,255,255,258,,,,258,,258,,258,258,,,,258,,,,,,,,,258,,258',
+',,,258,,,,,,,,258,258,,,258,258,258,258,258,258,258,258,258,260,,,,260',
+',260,,260,260,,,,260,,,,,,,,,260,,260,,,,260,,,,,,,,,260,,,260,260,260',
+'260,260,260,260,260,260,262,,,,262,,262,,262,262,,,,262,,,,,,,,,262',
+',262,,,,262,,,,,,,,,262,,,262,262,262,262,262,262,262,262,262,267,,',
+',267,,267,,267,267,,,,267,,,,,,,,,267,,267,,,,267,,,,,,,,267,267,,,267',
+'267,267,267,267,267,267,267,267,268,,,,268,,268,,268,268,,,,268,,,,',
+',,,,268,,268,,,,268,,,,,,,,268,268,,,268,268,268,268,268,268,268,268',
+'268,49,49,49,49,49,49,49,49,49,79,79,79,79,79,79,79,79,79,241,241,241',
+'241,241,241,241,241,241,241,241,,,,241,,,,49,49,,,,49,,,,79,79,,,,79',
+'76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76',
+',,,76,,,,,,,,76,135,135,135,135,135,135,135,135,135,135,135,135,135',
+'135,135,135,135,135,135,135,135,135,135,,,,135,,,,,,,,135,264,264,264',
+'264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264,264',
+'264,264,264,,,,264,,,,,,,,264,285,285,285,285,285,285,285,285,285,285',
+'285,285,285,285,285,285,285,285,285,285,285,285,285,,,,285,,,,,,,,285',
+'168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168',
+'168,168,168,168,168,168,,,,168,,,,,,,168,194,194,194,194,194,194,194',
+'194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,,,,194',
+',,,,,,194,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196',
+'196,196,196,196,196,196,196,196,,,,196,,,,,,,196,261,261,261,261,261',
'261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261,261',
-'261,261,261,261,261,,,,261,,,,,,,261,196,196,196,196,196,196,196,196',
-'196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,,,,196,',
-',,,,,196,287,287,287,287,287,287,287,287,287,287,287,287,287,287,287',
-'287,287,287,287,287,287,287,287,,,,287,,,,,,,287,194,194,194,194,194',
-'194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194,194',
-'194,,,,194,,,,,,,194,168,168,168,168,168,168,168,168,168,168,168,168',
-'168,168,168,168,168,168,168,168,168,168,168,,,,168,0,0,0,0,0,,168,0',
-'0,0,0,0,0,0,0,0,0,,0,0,0,0,,0,,0,300,300,300,,,,0,300,300,300,300,300',
-'300,300,300,300,300,,300,300,300,300,,300,,300,299,299,299,,,,300,299',
-'299,299,299,299,299,299,299,299,299,,299,299,299,299,,299,,299,286,286',
-'286,,,,299,286,286,286,286,286,286,286,286,286,286,,286,286,286,286',
-',286,,286,265,265,265,,,,286,265,265,265,265,265,265,265,265,265,265',
-',265,265,265,265,,265,,265,263,263,263,,,,265,263,263,263,263,263,263',
-'263,263,263,263,,263,263,263,263,,263,,263,43,43,43,,,,263,43,43,43',
-'43,43,43,43,43,43,43,43,43,43,43,43,,43,,43,47,47,47,,,,43,47,47,47',
-'47,47,47,47,47,47,47,,47,47,47,47,,47,,47,108,108,108,,,,47,108,108',
-'108,108,108,108,108,108,108,108,,108,108,108,108,,108,,108,3,3,3,3,3',
-',108,3,3,3,3,3,3,3,3,3,3,,3,3,3,3,,3,,3,306,306,306,,,,3,306,306,306',
-'306,306,306,306,306,306,306,,306,306,306,306,,306,,306,,,,,,,306,201',
-'201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201',
-'201,201,201,201,201,,,,201,180,180,180,180,180,180,180,180,180,180,180',
-'180,180,180,180,180,180,180,180,180,180,180,180,,,,180,197,197,197,197',
-'197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197,197',
-'197,197,,,,197,199,199,199,199,199,199,199,199,199,199,199,199,199,199',
-'199,199,199,199,199,199,199,199,199,,,,199,200,200,200,200,200,200,200',
-'200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,,,,200',
+'261,,,,261,,,,,,,261,287,287,287,287,287,287,287,287,287,287,287,287',
+'287,287,287,287,287,287,287,287,287,287,287,,,,287,0,0,0,0,0,,287,0',
+'0,0,0,0,0,0,0,0,0,,0,0,0,0,,0,,0,3,3,3,3,3,,0,3,3,3,3,3,3,3,3,3,3,,3',
+'3,3,3,,3,,3,43,43,43,,,,3,43,43,43,43,43,43,43,43,43,43,43,43,43,43',
+'43,,43,,43,47,47,47,,,,43,47,47,47,47,47,47,47,47,47,47,,47,47,47,47',
+',47,,47,108,108,108,,,,47,108,108,108,108,108,108,108,108,108,108,,108',
+'108,108,108,,108,,108,263,263,263,,,,108,263,263,263,263,263,263,263',
+'263,263,263,,263,263,263,263,,263,,263,265,265,265,,,,263,265,265,265',
+'265,265,265,265,265,265,265,,265,265,265,265,,265,,265,286,286,286,',
+',,265,286,286,286,286,286,286,286,286,286,286,,286,286,286,286,,286',
+',286,299,299,299,,,,286,299,299,299,299,299,299,299,299,299,299,,299',
+'299,299,299,,299,,299,300,300,300,,,,299,300,300,300,300,300,300,300',
+'300,300,300,,300,300,300,300,,300,,300,306,306,306,,,,300,306,306,306',
+'306,306,306,306,306,306,306,,306,306,306,306,,306,,306,,,,,,,306,180',
+'180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180',
+'180,180,180,180,180,,,,180,197,197,197,197,197,197,197,197,197,197,197',
+'197,197,197,197,197,197,197,197,197,197,197,197,,,,197,199,199,199,199',
+'199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199,199',
+'199,199,,,,199,200,200,200,200,200,200,200,200,200,200,200,200,200,200',
+'200,200,200,200,200,200,200,200,200,,,,200,201,201,201,201,201,201,201',
+'201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,,,,201',
'202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202,202',
'202,202,202,202,202,202,,,,202,203,203,203,203,203,203,203,203,203,203',
'203,203,203,203,203,203,203,203,203,203,203,203,203,,,,203,204,204,204',
@@ -395,10 +395,10 @@ clist = [
'291,291,291,291,291,291,291,291,,,,291,228,228,228,228,228,228,228,228',
'228,228,228,228,228,228,228,228,228,228,228,228,228,228,,,,228,227,227',
'227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227,227',
-'227,227,,,,227,245,245,245,245,245,245,245,245,245,245,245,,,,245,243',
+'227,227,,,,227,242,242,242,242,242,242,242,242,242,242,242,,,,242,243',
'243,243,243,243,243,243,243,243,243,243,,,,243,244,244,244,244,244,244',
-'244,244,244,244,244,,,,244,241,241,241,241,241,241,241,241,241,241,241',
-',,,241,246,246,246,246,246,246,246,246,246,246,246,,,,246,247,247,247',
+'244,244,244,244,244,,,,244,245,245,245,245,245,245,245,245,245,245,245',
+',,,245,246,246,246,246,246,246,246,246,246,246,246,,,,246,247,247,247',
'247,247,247,247,247,247,247,247,,,,247,248,248,248,248,248,248,248,248',
'248,248,248,,,,248,249,249,249,249,249,249,249,249,249,249,249,,,,249',
'250,250,250,250,250,250,250,250,250,250,250,,,,250,237,237,237,237,237',
@@ -413,37 +413,37 @@ clist = [
end
racc_action_pointer = [
- 3034, 197, nil, 3268, 109, nil, nil, nil, nil, nil,
- 179, 74, nil, nil, nil, nil, nil, nil, nil, nil,
+ 3034, 33, nil, 3060, 109, nil, nil, nil, nil, nil,
+ -5, -28, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 150, 144, -6, 13, -2, nil, 123, -12, 199,
- 197, 84, 1512, 3190, 196, -18, 195, 3216, 194, 2725,
- 35, -8, 15, nil, nil, nil, 205, nil, nil, nil,
- nil, nil, 144, nil, nil, nil, 1806, nil, nil, 135,
- 175, 108, nil, -28, -39, 78, 2758, 66, nil, 2716,
- 2051, 2100, 2149, 2198, nil, nil, nil, nil, nil, nil,
- 39, nil, nil, nil, -17, 178, 2394, nil, nil, nil,
- nil, nil, nil, nil, nil, 59, 51, nil, 3242, 101,
- 59, 130, 2639, 33, 91, 140, 189, 238, 287, 336,
- 385, 434, 483, 532, 581, nil, nil, nil, nil, nil,
- 630, 132, 19, nil, 31, 2793, nil, 777, -28, 48,
- 15, nil, nil, 973, 1022, 1071, 1120, 1169, 1218, 1267,
- -7, 1316, 924, 875, 826, 728, 679, 42, 2590, 2541,
- 2492, 2443, 2345, 2296, 2247, 2002, 1953, nil, 3034, 87,
- 91, 94, 373, nil, 69, 71, 73, 73, 86, nil,
- 3381, nil, 90, 88, nil, nil, nil, 115, nil, nil,
- nil, nil, 1904, 114, 3000, 1855, 2932, 3408, nil, 3435,
- 3462, 3354, 3489, 3516, 3543, 3570, 3597, 157, nil, 3624,
- 10, nil, 139, -11, nil, nil, 164, 155, 133, nil,
- 155, nil, 3651, nil, nil, 177, 179, 3810, 3785, 115,
- 66, 189, 192, 194, 197, 305, 3972, 3959, 318, 352,
- 367, 3870, 2713, 3840, 3855, 3825, 3885, 3900, 3915, 3930,
- 3945, nil, 166, 1757, 1708, 1659, 227, nil, 1610, nil,
- 1561, 2898, 1463, 3164, 2863, 3138, nil, 1414, 1365, nil,
- 0, nil, nil, 3, nil, nil, 358, 3678, nil, 3705,
- nil, 3732, nil, nil, nil, 2828, 3112, 2966, 136, nil,
- nil, 3759, nil, nil, nil, nil, 130, 52, nil, 3086,
- 3060, 407, 142, nil, nil, nil, 3294, nil ]
+ nil, -2, 9, -6, 13, 47, nil, -17, 50, 59,
+ 65, -8, -7, 3086, 68, -18, 80, 3112, 81, 2716,
+ 35, 74, 15, nil, nil, nil, 128, nil, nil, nil,
+ nil, nil, 88, nil, nil, nil, 42, nil, nil, 88,
+ 133, 72, nil, -28, 30, 93, 2758, 96, nil, 2725,
+ 91, 140, 189, 238, nil, nil, nil, nil, nil, nil,
+ 86, nil, nil, nil, 84, 129, 287, nil, nil, nil,
+ nil, nil, nil, nil, nil, 108, 105, nil, 3138, 52,
+ 129, 138, 336, 111, 385, 434, 483, 532, 581, 630,
+ 679, 728, 777, 826, 875, nil, nil, nil, nil, nil,
+ 924, 139, 19, nil, 31, 2793, nil, 973, 168, 131,
+ 133, nil, nil, 1022, 1071, 1120, 1169, 1218, 1267, 1316,
+ 1365, 1414, 1463, 1512, 1561, 1610, 1659, 1708, 1757, 1806,
+ 1855, 1904, 1953, 2002, 2051, 2100, 2149, nil, 2898, 143,
+ 145, 148, 309, nil, 122, 124, 125, 128, 140, nil,
+ 3354, nil, 156, 154, nil, nil, nil, 179, nil, nil,
+ nil, nil, 2198, 171, 2932, 2247, 2966, 3381, nil, 3408,
+ 3435, 3462, 3489, 3516, 3543, 3570, 3597, 187, nil, 3624,
+ 10, nil, 168, -11, nil, nil, 190, 181, 187, nil,
+ 172, nil, 3651, nil, nil, 195, 197, 3810, 3785, 66,
+ 115, 207, 209, 221, 232, 256, 3972, 3959, 269, 303,
+ 319, 2713, 3825, 3840, 3855, 3870, 3885, 3900, 3915, 3930,
+ 3945, nil, 201, 2296, 2345, 2394, 178, nil, 2443, nil,
+ 2492, 3000, 2541, 3164, 2828, 3190, nil, 2590, 2639, nil,
+ 217, nil, nil, 3, nil, nil, 324, 3678, nil, 3705,
+ nil, 3732, nil, nil, nil, 2863, 3216, 3034, 213, nil,
+ nil, 3759, nil, nil, nil, nil, 206, 101, nil, 3242,
+ 3268, 358, 234, nil, nil, nil, 3294, nil ]
racc_action_default = [
-2, -172, -1, -4, -172, -6, -8, -9, -10, -11,
@@ -479,40 +479,40 @@ racc_action_default = [
-172, -172, -172, -54, -56, -168, -172, -52 ]
racc_goto_table = [
- 31, 175, 62, 31, 187, 38, 77, 183, 38, 178,
- 49, 139, 140, 49, 207, 35, 216, 106, 35, 69,
- 60, 2, 271, 75, 57, 1, 58, 33, 70, 215,
- 33, 108, 70, 174, 59, 113, 110, nil, nil, nil,
- 61, nil, nil, 31, nil, nil, nil, 31, 38, nil,
- nil, nil, 38, 49, nil, nil, nil, 49, 35, nil,
- 127, 128, 35, nil, nil, nil, nil, nil, nil, nil,
- 33, nil, nil, nil, 33, 294, nil, nil, 252, 198,
- nil, nil, 186, nil, nil, 173, 176, nil, 211, nil,
+ 31, 187, 62, 31, 175, 33, 77, 183, 33, 178,
+ 35, 139, 140, 35, 207, 38, 216, 106, 38, 60,
+ 69, 1, 271, 59, 75, 58, 215, 49, 70, 61,
+ 49, 108, 70, 174, 2, 113, 110, 57, nil, nil,
+ nil, nil, nil, 31, nil, nil, nil, 31, 33, nil,
+ nil, nil, 33, 35, nil, nil, nil, 35, 38, nil,
+ nil, nil, 38, nil, nil, nil, nil, nil, nil, nil,
+ 49, nil, nil, nil, 49, 294, nil, 127, 128, 198,
+ nil, 252, 186, nil, nil, 173, 176, nil, 211, nil,
nil, nil, nil, nil, nil, nil, 108, nil, nil, nil,
nil, 223, 193, nil, nil, nil, nil, nil, 31, 188,
- nil, nil, nil, 38, 191, 210, nil, nil, 49, 49,
- 224, 60, 214, 35, 190, 219, nil, nil, nil, 70,
- nil, nil, nil, nil, nil, 33, 189, nil, nil, nil,
+ nil, nil, nil, 33, 189, 210, nil, nil, 35, 190,
+ 60, 224, 214, 38, 191, 219, nil, nil, nil, 70,
+ nil, nil, nil, nil, nil, 49, 49, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 295, nil, nil, 293, nil,
- nil, nil, 175, nil, nil, nil, nil, nil, nil, 284,
+ nil, nil, nil, nil, nil, 175, nil, nil, nil, 284,
283, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 296, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 302, nil, 174, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 305, nil, 272,
- nil, nil, nil, nil, nil, nil, nil, 278, 280, 282,
+ nil, nil, nil, nil, nil, 296, nil, nil, nil, 302,
+ nil, nil, nil, nil, 174, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 272,
+ 305, nil, nil, nil, nil, nil, nil, 278, 280, 282,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, 292, 211, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, 176, nil, nil,
nil, 288, nil, 290, nil, nil, nil, nil, nil, 210,
- nil, nil, nil, 31, 219, 31, nil, nil, 38, nil,
- 38, nil, nil, 49, 298, 49, nil, nil, 35, 76,
- 35, nil, nil, nil, nil, nil, 31, 303, 304, nil,
- 33, 38, 33, nil, 307, nil, 49, 188, nil, 31,
- 31, 35, 191, 135, 38, 38, 31, 49, nil, 49,
- 49, 38, 190, 33, 35, 35, 49, 168, 169, 170,
- 171, 35, nil, nil, 189, nil, 33, 33, nil, nil,
- nil, nil, nil, 33, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, 31, 219, 31, nil, nil, 33, nil,
+ 33, nil, nil, 35, 298, 35, nil, nil, 38, 76,
+ 38, nil, nil, nil, nil, nil, 31, 303, 304, nil,
+ 49, 33, 49, nil, 307, nil, 35, 188, nil, 31,
+ 31, 38, 189, 135, 33, 33, 31, 190, nil, 35,
+ 35, 33, 191, 49, 38, 38, 35, 168, 169, 170,
+ 171, 38, nil, nil, 49, nil, 49, 49, nil, nil,
+ nil, nil, nil, 49, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, 194,
nil, 196, 197, 199, 200, 201, 202, 203, 204, 205,
206, 209, nil, nil, nil, nil, nil, 213, nil, nil,
@@ -532,40 +532,40 @@ racc_goto_table = [
nil, nil, nil, nil, 291, 209 ]
racc_goto_check = [
- 30, 43, 9, 30, 39, 34, 37, 53, 34, 49,
- 40, 35, 35, 40, 41, 32, 10, 38, 32, 33,
- 18, 2, 11, 33, 2, 1, 4, 31, 9, 50,
- 31, 6, 9, 35, 5, 6, 9, nil, nil, nil,
- 5, nil, nil, 30, nil, nil, nil, 30, 34, nil,
- nil, nil, 34, 40, nil, nil, nil, 40, 32, nil,
- 40, 40, 32, nil, nil, nil, nil, nil, nil, nil,
- 31, nil, nil, nil, 31, 11, nil, nil, 43, 37,
- nil, nil, 38, nil, nil, 9, 9, nil, 37, nil,
+ 30, 39, 9, 30, 43, 31, 37, 53, 31, 49,
+ 32, 35, 35, 32, 41, 34, 10, 38, 34, 18,
+ 33, 1, 11, 5, 33, 4, 50, 40, 9, 5,
+ 40, 6, 9, 35, 2, 6, 9, 2, nil, nil,
+ nil, nil, nil, 30, nil, nil, nil, 30, 31, nil,
+ nil, nil, 31, 32, nil, nil, nil, 32, 34, nil,
+ nil, nil, 34, nil, nil, nil, nil, nil, nil, nil,
+ 40, nil, nil, nil, 40, 11, nil, 40, 40, 37,
+ nil, 43, 38, nil, nil, 9, 9, nil, 37, nil,
nil, nil, nil, nil, nil, nil, 6, nil, nil, nil,
nil, 37, 9, nil, nil, nil, nil, nil, 30, 30,
- nil, nil, nil, 34, 34, 9, nil, nil, 40, 40,
- 33, 18, 9, 32, 32, 9, nil, nil, nil, 9,
- nil, nil, nil, nil, nil, 31, 31, nil, nil, nil,
+ nil, nil, nil, 31, 31, 9, nil, nil, 32, 32,
+ 18, 33, 9, 34, 34, 9, nil, nil, nil, 9,
+ nil, nil, nil, nil, nil, 40, 40, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 10, nil, nil, 41, nil,
- nil, nil, 43, nil, nil, nil, nil, nil, nil, 53,
+ nil, nil, nil, nil, nil, 43, nil, nil, nil, 53,
49, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 43, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 39, nil, 35, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 43, nil, 9,
- nil, nil, nil, nil, nil, nil, nil, 37, 37, 37,
+ nil, nil, nil, nil, nil, 43, nil, nil, nil, 39,
+ nil, nil, nil, nil, 35, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 9,
+ 43, nil, nil, nil, nil, nil, nil, 37, 37, 37,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, 37, 37, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, 9, nil, nil,
nil, 6, nil, 6, nil, nil, nil, nil, nil, 9,
- nil, nil, nil, 30, 9, 30, nil, nil, 34, nil,
- 34, nil, nil, 40, 6, 40, nil, nil, 32, 36,
- 32, nil, nil, nil, nil, nil, 30, 6, 6, nil,
- 31, 34, 31, nil, 6, nil, 40, 30, nil, 30,
- 30, 32, 34, 36, 34, 34, 30, 40, nil, 40,
- 40, 34, 32, 31, 32, 32, 40, 36, 36, 36,
- 36, 32, nil, nil, 31, nil, 31, 31, nil, nil,
- nil, nil, nil, 31, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, 30, 9, 30, nil, nil, 31, nil,
+ 31, nil, nil, 32, 6, 32, nil, nil, 34, 36,
+ 34, nil, nil, nil, nil, nil, 30, 6, 6, nil,
+ 40, 31, 40, nil, 6, nil, 32, 30, nil, 30,
+ 30, 34, 31, 36, 31, 31, 30, 32, nil, 32,
+ 32, 31, 34, 40, 34, 34, 32, 36, 36, 36,
+ 36, 34, nil, nil, 40, nil, 40, 40, nil, nil,
+ nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, 36,
nil, 36, 36, 36, 36, 36, 36, 36, 36, 36,
36, 36, nil, nil, nil, nil, nil, 36, nil, nil,
@@ -585,12 +585,12 @@ racc_goto_check = [
nil, nil, nil, nil, 36, 36 ]
racc_goto_pointer = [
- nil, 25, 21, nil, 22, 30, -12, nil, nil, -9,
- -118, -195, nil, nil, nil, nil, nil, nil, 16, nil,
+ nil, 21, 34, nil, 21, 19, -12, nil, nil, -9,
+ -118, -195, nil, nil, nil, nil, nil, nil, 15, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 0, 27, 15, -18, 5, -62, 237, -36, -26, -105,
- 10, -110, nil, -94, nil, nil, nil, nil, nil, -86,
- -103, nil, nil, -89, nil, nil ]
+ 0, 5, 10, -17, 15, -62, 237, -36, -26, -108,
+ 27, -110, nil, -91, nil, nil, nil, nil, nil, -86,
+ -106, nil, nil, -89, nil, nil ]
racc_goto_default = [
nil, nil, nil, 3, 5, 6, 7, 8, 9, 52,
diff --git a/test/racc/regress/nokogiri-css b/test/racc/regress/nokogiri-css
index 0aad3a394a..bc2faf8702 100644
--- a/test/racc/regress/nokogiri-css
+++ b/test/racc/regress/nokogiri-css
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -15,64 +15,64 @@ module Nokogiri
racc_action_table = [
24, 93, 56, 57, 33, 55, 94, 23, 24, 22,
- 12, 93, 33, 27, 89, 52, 92, 22, -23, 25,
- 108, 98, 23, 33, 26, 18, 20, 25, 27, -23,
+ 12, 93, 33, 27, 35, 52, 44, 22, -23, 25,
+ 45, 98, 23, 33, 26, 18, 20, 25, 27, -23,
23, 24, 26, 18, 20, 33, 27, 11, 39, 24,
- 22, 23, 95, 33, 18, 101, 100, 27, 22, 12,
- 25, 91, 90, 23, 33, 26, 18, 20, 25, 27,
- 90, 23, 24, 26, 18, 20, 33, 27, 96, 39,
- -23, 22, 23, 74, 24, 18, 33, 99, 27, 56,
- 87, 25, 60, 46, 23, 49, 26, 18, 20, 102,
- 27, 39, 24, 51, 23, 103, 93, 18, 26, 33,
- 27, 66, 44, 56, 58, 105, 60, 33, 35, 33,
- 109, 51, 56, 87, 39, 60, 26, 23, 85, 33,
- 18, 20, 39, 27, 39, 23, 45, 23, 18, 33,
- 18, 27, 86, 27, 39, 88, 33, 23, nil, nil,
- 18, 22, nil, 27, 39, 56, 87, 23, 60, nil,
- 18, 39, nil, 27, 23, 82, 83, 18, 20, nil,
- 27, nil, nil, nil, 82, 83, 78, 79, 80, nil,
- 81, nil, nil, nil, 77, 78, 79, 80, nil, 81,
- 4, 5, 43, 77, 4, 5, 10, nil, 56, 87,
- 6, 60, 8, 7, 6, nil, 8, 7, 4, 5,
- 10, nil, nil, nil, nil, nil, nil, nil, 6, nil,
- 8, 7 ]
+ 22, 23, 74, 33, 18, 91, 90, 27, 22, 12,
+ 25, 24, -23, 23, 85, 26, 18, 20, 25, 27,
+ 66, 23, 24, 26, 18, 20, 33, 27, 101, 100,
+ 51, 22, 86, 88, 24, 26, 56, 87, 89, 60,
+ 92, 25, 95, 46, 23, 49, 26, 18, 20, 90,
+ 27, 33, 33, 51, 96, 99, 56, 58, 26, 60,
+ 102, 103, 33, 33, 33, 93, 39, 39, 105, 23,
+ 23, 108, 18, 18, 20, 27, 27, 39, 39, 39,
+ 23, 23, 23, 18, 18, 18, 27, 27, 27, 33,
+ 33, 56, 87, 109, 60, 22, 56, 87, nil, 60,
+ 33, nil, nil, nil, 39, 39, nil, 23, 23, nil,
+ 18, 18, 20, 27, 27, 39, 82, 83, 23, 56,
+ 87, 18, 60, nil, 27, 82, 83, 78, 79, 80,
+ nil, 81, nil, nil, nil, 77, 78, 79, 80, nil,
+ 81, 4, 5, 10, 77, 4, 5, 43, nil, nil,
+ nil, 6, nil, 8, 7, 6, nil, 8, 7, 4,
+ 5, 10, nil, nil, nil, nil, nil, nil, nil, 6,
+ nil, 8, 7 ]
racc_action_check = [
- 3, 58, 24, 24, 3, 24, 57, 15, 42, 3,
- 64, 57, 42, 15, 54, 24, 56, 42, 58, 3,
- 94, 64, 3, 31, 3, 3, 3, 42, 3, 22,
- 42, 9, 42, 42, 42, 9, 42, 1, 31, 43,
- 9, 31, 59, 43, 31, 76, 76, 31, 43, 1,
- 9, 55, 55, 9, 30, 9, 9, 9, 43, 9,
- 60, 43, 12, 43, 43, 43, 12, 43, 61, 30,
- 46, 12, 30, 45, 23, 30, 29, 75, 30, 93,
- 93, 12, 93, 23, 12, 23, 12, 12, 12, 84,
- 12, 29, 27, 23, 29, 86, 87, 29, 23, 25,
- 29, 27, 18, 25, 25, 91, 25, 28, 11, 62,
- 105, 27, 51, 51, 25, 51, 27, 25, 49, 14,
- 25, 25, 28, 25, 62, 28, 21, 62, 28, 32,
- 62, 28, 50, 62, 14, 53, 39, 14, nil, nil,
- 14, 39, nil, 14, 32, 90, 90, 32, 90, nil,
- 32, 39, nil, 32, 39, 47, 47, 39, 39, nil,
- 39, nil, nil, nil, 48, 48, 47, 47, 47, nil,
- 47, nil, nil, nil, 47, 48, 48, 48, nil, 48,
- 17, 17, 17, 48, 0, 0, 0, nil, 92, 92,
- 17, 92, 17, 17, 0, nil, 0, 0, 26, 26,
- 26, nil, nil, nil, nil, nil, nil, nil, 26, nil,
- 26, 26 ]
+ 3, 58, 24, 24, 3, 24, 57, 15, 9, 3,
+ 64, 57, 9, 15, 11, 24, 18, 9, 58, 3,
+ 21, 64, 3, 14, 3, 3, 3, 9, 3, 22,
+ 9, 12, 9, 9, 9, 12, 9, 1, 14, 42,
+ 12, 14, 45, 42, 14, 55, 55, 14, 42, 1,
+ 12, 27, 46, 12, 49, 12, 12, 12, 42, 12,
+ 27, 42, 43, 42, 42, 42, 43, 42, 76, 76,
+ 27, 43, 50, 53, 23, 27, 51, 51, 54, 51,
+ 56, 43, 59, 23, 43, 23, 43, 43, 43, 60,
+ 43, 28, 25, 23, 61, 75, 25, 25, 23, 25,
+ 84, 86, 29, 30, 31, 87, 28, 25, 91, 28,
+ 25, 94, 28, 25, 25, 28, 25, 29, 30, 31,
+ 29, 30, 31, 29, 30, 31, 29, 30, 31, 32,
+ 39, 90, 90, 105, 90, 39, 92, 92, nil, 92,
+ 62, nil, nil, nil, 32, 39, nil, 32, 39, nil,
+ 32, 39, 39, 32, 39, 62, 47, 47, 62, 93,
+ 93, 62, 93, nil, 62, 48, 48, 47, 47, 47,
+ nil, 47, nil, nil, nil, 47, 48, 48, 48, nil,
+ 48, 0, 0, 0, 48, 17, 17, 17, nil, nil,
+ nil, 0, nil, 0, 0, 17, nil, 17, 17, 26,
+ 26, 26, nil, nil, nil, nil, nil, nil, nil, 26,
+ nil, 26, 26 ]
racc_action_pointer = [
- 177, 37, nil, -2, nil, nil, nil, nil, nil, 29,
- nil, 108, 60, nil, 113, -17, nil, 173, 91, nil,
- nil, 97, 0, 72, -8, 93, 191, 90, 101, 70,
- 48, 17, 123, nil, nil, nil, nil, nil, nil, 130,
- nil, nil, 6, 37, nil, 62, 41, 152, 161, 93,
- 103, 102, nil, 112, -9, 40, 4, -1, -11, 19,
- 48, 45, 103, nil, -2, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 52, 35, nil, nil, nil,
- nil, nil, nil, nil, 64, nil, 84, 84, nil, nil,
- 135, 98, 178, 69, 7, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 97, nil, nil, nil, nil ]
+ 174, 37, nil, -2, nil, nil, nil, nil, nil, 6,
+ nil, 14, 29, nil, 17, -17, nil, 178, 5, nil,
+ nil, -9, 0, 72, -8, 86, 192, 49, 85, 96,
+ 97, 98, 123, nil, nil, nil, nil, nil, nil, 124,
+ nil, nil, 37, 60, nil, 31, 23, 153, 162, 29,
+ 43, 66, nil, 50, 55, 34, 68, -1, -11, 59,
+ 77, 71, 134, nil, -2, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 70, 58, nil, nil, nil,
+ nil, nil, nil, nil, 75, nil, 90, 93, nil, nil,
+ 121, 101, 126, 149, 98, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 120, nil, nil, nil, nil ]
racc_action_default = [
-74, -75, -2, -24, -4, -5, -6, -7, -8, -24,
@@ -88,26 +88,26 @@ racc_action_default = [
-59, -60, -26, -28, -35, -75, -36, -37, -42, -41 ]
racc_goto_table = [
- 53, 38, 13, 1, 54, 48, 62, 42, 34, 65,
- 37, 36, 63, 75, 84, 67, 68, 69, 70, 71,
- 62, 40, 41, 50, 47, nil, 63, nil, nil, 64,
+ 53, 38, 13, 1, 42, 48, 62, 37, 34, 65,
+ 40, 36, 63, 75, 84, 67, 68, 69, 70, 71,
+ 62, 41, 50, 47, 54, nil, 63, nil, nil, 64,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, 72, 73, nil, nil, nil, nil, nil, nil, 97,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, 104, nil, 106, 107 ]
racc_goto_check = [
- 18, 12, 2, 1, 19, 9, 7, 5, 2, 9,
- 8, 2, 12, 17, 17, 12, 12, 12, 12, 12,
- 7, 10, 11, 15, 16, nil, 12, nil, nil, 1,
+ 18, 12, 2, 1, 5, 9, 7, 8, 2, 9,
+ 10, 2, 12, 17, 17, 12, 12, 12, 12, 12,
+ 7, 11, 15, 16, 19, nil, 12, nil, nil, 1,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, 2, 2, nil, nil, nil, nil, nil, nil, 12,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, 18, nil, 18, 18 ]
racc_goto_pointer = [
- nil, 3, -1, nil, nil, -10, nil, -19, -4, -18,
- 6, 7, -13, nil, nil, 0, 1, -34, -24, -20,
+ nil, 3, -1, nil, nil, -13, nil, -19, -7, -18,
+ -5, 6, -13, nil, nil, -1, 0, -34, -24, 0,
nil, nil, nil, nil ]
racc_goto_default = [
diff --git a/test/racc/regress/opal b/test/racc/regress/opal
index 1bd6c0f255..710ccdfe88 100644
--- a/test/racc/regress/opal
+++ b/test/racc/regress/opal
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -14,428 +14,238 @@ module_eval(<<'...end opal.y/module_eval...', 'opal.y', 1808)
##### State transition tables begin ###
clist = [
-'63,64,65,619,51,-94,-96,-94,57,58,268,205,206,61,73,59,60,62,23,24,66',
-'67,74,544,205,206,546,22,28,27,90,89,91,92,777,653,17,607,273,273,205',
-'206,531,41,-99,-92,94,93,575,84,50,86,85,87,273,88,95,96,-68,81,82,-97',
-'38,39,-95,597,618,-100,718,652,-98,205,206,-534,-452,575,552,716,205',
-'206,810,-452,575,-85,-93,210,575,581,214,582,575,52,-99,227,54,-79,649',
-'-92,609,608,40,101,877,-100,268,268,100,770,18,-99,-95,-87,-85,79,73',
-'75,76,77,78,-94,-97,-94,74,80,-94,272,272,63,64,65,56,51,813,53,582',
-'57,58,-535,37,83,61,272,59,60,62,258,259,66,67,-90,-84,-85,-94,876,257',
-'291,295,90,89,91,92,308,101,219,574,227,-88,100,308,-86,292,596,-91',
-'94,93,-89,84,50,86,85,361,551,88,95,96,-458,81,82,-85,101,101,574,832',
-'813,100,100,101,-85,574,900,101,100,574,-93,101,100,574,344,343,100',
-'-96,-92,362,-92,-98,214,-92,-100,52,-100,-86,54,-100,-99,-95,-99,-95',
-'-89,-99,-95,-91,813,101,277,-97,-92,-97,100,726,-97,79,73,75,76,77,78',
-'653,-88,819,74,80,-87,-90,726,63,64,65,56,51,-84,53,607,57,58,612,296',
-'83,61,653,59,60,62,258,259,66,67,544,820,653,546,652,257,291,295,90',
-'89,91,92,-86,-534,219,-331,-331,-535,-535,-89,204,41,-91,-331,94,93',
-'652,84,50,86,85,87,558,88,95,96,652,81,82,-88,38,39,-534,-87,-90,726',
-'609,608,-96,-86,-96,-84,-98,-96,-98,561,-89,-98,-86,-91,454,-91,101',
-'210,725,-89,214,100,-91,52,-100,-331,54,-331,527,528,-88,101,40,725',
-'-87,-90,100,706,544,-88,218,546,-84,-87,-90,79,73,75,76,77,78,-84,823',
-'630,74,80,824,631,561,63,64,65,56,51,-100,53,544,57,58,543,37,83,61',
-'789,59,60,62,258,259,66,67,827,-532,400,401,308,257,291,295,90,89,91',
-'92,813,-86,219,788,836,-88,101,625,725,41,-95,100,94,93,-97,84,50,86',
-'85,87,-453,88,95,96,607,81,82,-453,38,39,-97,227,231,236,237,238,233',
-'235,243,244,239,240,-449,-449,220,221,205,206,241,242,-449,210,602,-95',
-'214,-532,412,52,837,603,54,414,413,224,268,230,40,226,225,222,223,234',
-'232,228,218,229,-532,344,343,79,73,75,76,77,78,609,608,620,74,80,839',
-'245,702,63,64,65,56,51,-449,53,-449,57,58,701,37,83,61,607,59,60,62',
-'258,259,66,67,700,754,-458,840,754,257,291,295,90,89,91,92,751,607,219',
-'751,-446,531,607,-449,776,41,415,-446,94,93,-449,84,50,86,85,87,-456',
-'88,95,96,532,81,82,-456,38,39,101,-84,-534,344,343,100,344,343,842,227',
-'-92,609,608,605,264,265,-90,533,101,-85,694,210,266,100,214,-99,101',
-'52,-94,402,54,100,609,608,610,-455,40,609,608,614,752,224,-455,752,218',
-'226,225,524,946,79,73,75,76,77,78,947,537,101,74,80,850,-454,100,63',
-'64,65,56,51,-454,53,-451,57,58,852,37,83,61,-451,59,60,62,258,259,66',
-'67,103,104,105,106,107,257,28,27,90,89,91,92,101,855,219,524,593,100',
-'945,856,586,41,858,591,94,93,860,84,50,86,85,87,261,88,95,96,862,81',
-'82,227,38,39,864,227,231,236,237,238,233,235,243,244,239,240,524,584',
-'220,221,832,813,241,242,585,210,301,302,214,205,206,52,684,592,54,523',
-'256,224,308,230,40,226,225,222,223,234,232,228,218,229,-265,-283,-283',
-'79,73,75,76,77,78,-283,391,388,74,80,-535,245,650,63,64,65,56,51,583',
-'53,586,57,58,682,37,83,61,-79,59,60,62,258,259,66,67,103,104,105,106',
-'107,257,28,27,90,89,91,92,681,679,219,203,201,671,-283,670,-283,41,308',
-'202,94,93,547,84,50,86,85,87,261,88,95,96,548,81,82,878,38,39,879,227',
-'231,236,237,238,233,235,243,244,239,240,524,593,220,221,880,881,241',
-'242,822,210,883,884,214,694,491,52,886,199,54,200,256,224,308,230,40',
-'226,225,222,223,234,232,228,218,229,-263,524,534,79,73,75,76,77,78,535',
-'890,227,74,80,227,245,895,-255,-255,-255,56,-255,592,53,523,-255,-255',
-'897,37,83,-255,300,-255,-255,-255,-255,-255,-255,-255,103,104,105,106',
-'107,-255,-255,-255,-255,-255,-255,-255,227,227,-255,203,449,555,452',
-'558,451,-255,903,450,-255,-255,905,-255,-255,-255,-255,-255,-255,-255',
-'-255,-255,906,-255,-255,308,-255,-255,559,227,231,236,237,238,233,235',
-'243,244,239,240,524,521,220,221,561,570,241,242,522,-255,571,299,-255',
-'268,919,-255,-266,452,-255,451,-255,224,-255,230,-255,226,225,222,223',
-'234,232,228,-255,229,268,-284,-284,-255,-255,-255,-255,-255,-255,-284',
-'246,921,-255,-255,404,245,964,-537,-537,-537,-255,-537,520,-255,523',
-'-537,-537,-535,-255,-255,-537,561,-537,-537,-537,-537,-537,-537,-537',
-'860,931,932,629,628,-537,-537,-537,-537,-537,-537,-537,198,937,-537',
-'-286,-286,855,-284,939,-284,-537,227,-286,-537,-537,860,-537,-537,-537',
-'-537,-537,-537,-537,-537,-537,860,-537,-537,862,-537,-537,-263,227,231',
-'236,237,238,233,235,243,244,239,240,224,197,220,221,226,225,241,242',
-'196,-537,966,627,-537,-537,948,-537,967,-286,-537,-286,-537,224,-537',
-'230,-537,226,225,222,223,234,232,228,-537,229,195,108,954,-537,-537',
-'-537,-537,-537,-537,708,624,700,-537,-537,587,245,621,-536,-536,-536',
-'-537,-536,97,-537,589,-536,-536,617,-537,-537,-536,613,-536,-536,-536',
-'-536,-536,-536,-536,708,588,497,497,497,-536,-536,-536,-536,-536,-536',
-'-536,497,491,-536,-264,489,341,340,344,343,-536,791,792,-536,-536,487',
-'-536,-536,-536,-536,-536,-536,-536,-536,-536,772,-536,-536,-67,-536',
-'-536,489,227,491,215,456,341,340,344,343,227,866,867,800,915,868,95',
-'96,455,754,514,802,-536,803,453,-536,-536,515,-536,516,751,-536,729',
-'-536,224,-536,694,-536,226,225,222,223,224,807,582,-536,226,225,222',
-'223,-536,-536,-536,-536,-536,-536,525,268,721,-536,-536,341,340,344',
-'343,268,808,-536,915,,-536,,,754,,-536,-536,63,64,65,8,51,,,751,57,58',
-',,,61,,59,60,62,23,24,66,67,,752,,,,22,28,27,90,89,91,92,,,17,,341,340',
-'344,343,7,41,6,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227',
-'231,236,237,238,233,235,243,244,239,240,,752,220,221,,,241,242,,36,',
-',30,,,52,,,54,,32,224,,230,40,226,225,222,223,234,232,228,18,229,,,',
-'79,73,75,76,77,78,,,,74,80,,245,,63,64,65,56,51,,53,,57,58,,37,83,61',
-',59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,563,219,336,334',
-'333,,335,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,227',
-'231,236,237,238,233,235,243,244,239,240,,,220,221,,,241,242,,210,,,214',
-',,52,,,54,,256,224,,230,40,226,225,222,223,234,232,228,218,229,,,,79',
+'63,64,65,8,51,575,552,-92,57,58,619,205,206,61,73,59,60,62,23,24,66',
+'67,74,544,754,607,543,22,28,27,90,89,91,92,97,751,17,607,273,-458,612',
+'653,7,41,6,9,94,93,575,84,50,86,85,87,273,88,95,96,653,81,82,-100,38',
+'39,-99,-68,597,-446,344,343,-95,205,206,618,-446,652,-97,581,575,582',
+'-94,205,206,-96,575,36,609,608,30,-92,575,52,652,108,54,770,32,-84,609',
+'608,40,101,-79,-92,268,752,100,195,18,-100,-99,551,-84,79,73,75,76,77',
+'78,101,-95,574,74,80,100,272,-98,63,64,65,56,51,-97,53,653,57,58,196',
+'37,83,61,272,59,60,62,23,24,66,67,454,-534,205,206,197,22,28,27,90,89',
+'91,92,308,101,17,574,-84,-91,100,652,-90,41,308,596,94,93,-86,84,50',
+'86,85,87,-88,88,95,96,-85,81,82,-87,38,39,101,101,-535,574,900,100,100',
+'101,-100,574,-449,-84,100,101,198,574,649,-449,100,-96,-84,210,246,-98',
+'214,215,-92,52,-92,-91,54,-92,-100,-99,-100,-99,40,-100,-99,-94,-89',
+'273,607,-95,18,-95,299,726,-95,79,73,75,76,77,78,-97,-90,-97,74,80,-97',
+'-86,726,63,64,65,56,51,-88,53,544,57,58,546,37,83,61,531,59,60,62,23',
+'24,66,67,205,206,653,205,206,22,28,27,90,89,91,92,-91,-534,219,777,300',
+'-535,609,608,605,41,268,227,94,93,308,84,50,86,85,87,388,88,95,96,652',
+'81,82,-90,38,39,-99,272,-86,726,301,302,-96,-91,-96,-88,-98,-96,-98',
+'224,810,-98,-91,226,225,-87,101,210,725,-93,214,100,-94,52,-94,-85,54',
+'-94,391,-89,-90,101,40,725,788,-86,100,402,101,-90,218,415,-88,100,-86',
+'79,73,75,76,77,78,-88,453,101,74,80,455,204,100,63,64,65,56,51,607,53',
+'544,57,58,546,37,83,61,789,59,60,62,258,259,66,67,876,-534,-87,-95,877',
+'257,28,27,90,89,91,92,-85,456,219,-535,-89,-91,101,607,725,41,607,100',
+'94,93,-100,84,50,86,85,87,261,88,95,96,-456,81,82,-87,38,39,-97,-456',
+'609,608,610,101,-87,-85,-93,215,100,-89,-94,487,264,265,-85,754,-455',
+'-454,-89,210,266,489,214,-455,-454,52,751,813,54,582,256,491,254,497',
+'40,-67,609,608,614,609,608,620,218,400,401,203,201,79,73,75,76,77,78',
+'202,514,544,74,80,546,344,343,63,64,65,56,51,101,53,-451,57,58,100,37',
+'83,61,-451,59,60,62,258,259,66,67,515,-532,527,528,516,257,28,27,90',
+'89,91,92,101,752,219,-331,-331,100,199,625,200,41,525,-331,94,93,277',
+'84,50,86,85,87,261,88,95,96,308,81,82,268,38,39,532,227,231,236,237',
+'238,233,235,243,244,239,240,-449,-449,220,221,-452,101,241,242,-449',
+'210,100,-452,214,-532,533,52,227,-331,54,-331,256,224,254,230,40,226',
+'225,222,223,234,232,228,218,229,-532,203,449,79,73,75,76,77,78,450,308',
+'-458,74,80,547,245,548,63,64,65,56,51,-449,53,-449,57,58,491,37,83,61',
+'555,59,60,62,258,259,66,67,103,104,105,106,107,257,28,27,90,89,91,92',
+'-453,-84,219,524,521,531,452,-453,451,41,-92,522,94,93,558,84,50,86',
+'85,87,261,88,95,96,559,81,82,561,38,39,570,227,231,236,237,238,233,235',
+'243,244,239,240,524,534,220,221,-90,412,241,242,535,210,414,413,214',
+'-99,571,52,404,520,54,523,256,224,254,230,40,226,225,222,223,234,232',
+'228,218,229,587,524,584,79,73,75,76,77,78,585,588,630,74,80,589,245',
+'650,-255,-255,-255,56,-255,452,53,451,-255,-255,613,37,83,-255,617,-255',
+'-255,-255,-255,-255,-255,-255,103,104,105,106,107,-255,-255,-255,-255',
+'-255,-255,-255,621,-86,-255,524,593,624,583,625,586,-255,-95,591,-255',
+'-255,627,-255,-255,-255,-255,-255,-255,-255,-255,-255,-263,-255,-255',
+'628,-255,-255,629,227,231,236,237,238,233,235,243,244,239,240,-284,-284',
+'220,221,205,206,241,242,-284,-255,268,631,-255,268,227,-255,227,592',
+'-255,523,-255,224,-255,230,-255,226,225,222,223,234,232,228,-255,229',
+'344,343,602,-255,-255,-255,-255,-255,-255,603,832,813,-255,-255,776',
+'245,227,-233,-88,227,-255,915,-284,-255,-284,308,754,-97,-255,-255,63',
+'64,65,8,51,344,343,751,57,58,832,813,670,61,671,59,60,62,23,24,66,67',
+'679,681,-79,-85,682,22,28,27,90,89,91,92,-94,684,17,537,341,340,344',
+'343,7,41,227,9,94,93,694,84,50,86,85,87,700,88,95,96,701,81,82,702,38',
+'39,706,227,231,236,237,238,233,235,243,244,239,240,224,752,220,221,226',
+'225,241,242,716,36,718,721,281,582,729,52,772,-264,54,497,32,224,497',
+'230,40,226,225,222,223,234,232,228,18,229,497,524,593,79,73,75,76,77',
+'78,822,791,792,74,80,489,245,491,63,64,65,56,51,800,53,802,57,58,803',
+'37,83,61,694,59,60,62,258,259,66,67,708,807,268,268,808,257,291,295',
+'90,89,91,92,268,227,219,-286,-286,227,592,813,523,292,819,-286,94,93',
+'820,84,50,86,85,87,558,88,95,96,561,81,82,823,327,824,336,334,333,561',
+'335,341,340,344,343,827,866,867,-283,-283,868,95,96,813,836,837,-283',
+'289,839,840,286,-535,-534,52,842,-286,54,-286,285,850,852,855,856,338',
+'858,915,860,862,864,-265,754,341,340,344,343,79,73,75,76,77,78,751,794',
+'878,74,80,879,880,881,63,64,65,56,51,-283,53,-283,57,58,883,296,83,61',
+'884,59,60,62,258,259,66,67,708,341,340,344,343,257,291,295,90,89,91',
+'92,524,946,219,103,104,105,106,107,947,292,227,694,94,93,886,84,50,86',
+'85,87,-263,88,95,96,890,81,82,764,752,336,334,333,754,335,895,341,340',
+'344,343,897,903,905,224,751,906,308,226,225,222,223,919,289,-266,921',
+'214,-535,945,52,586,563,54,336,334,333,561,335,338,749,931,932,937,855',
+'939,860,341,340,344,343,860,79,73,75,76,77,78,862,948,954,74,80,700',
+'964,860,298,966,967,56,,,53,,,,,296,83,63,64,65,227,51,,,752,57,58,',
+',,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,224,219,',
+',226,225,222,223,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
+',227,231,236,237,238,233,235,243,244,239,240,,,220,221,,,241,242,,210',
+',,214,,,52,,,54,,,224,,230,40,226,225,222,223,234,232,228,218,229,,',
+',79,73,75,76,77,78,,,,74,80,,245,,63,64,65,56,51,,53,,57,58,,37,83,61',
+',59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,563,219,336,334',
+'333,,335,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,231',
+'236,237,238,233,235,243,244,239,240,,,220,221,,,241,242,,210,,,214,',
+',52,,,54,,,224,,230,40,226,225,222,223,234,232,228,218,229,,,,79,73',
+'75,76,77,78,,,,74,80,,245,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60',
+'62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93',
+',84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,231,236,237,238,233,235',
+'243,244,239,240,,,220,221,,,241,242,,210,,,214,,,52,,,54,,,224,,230',
+'40,226,225,222,223,234,232,228,218,229,,,,79,73,75,76,77,78,,,,74,80',
+',245,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,',
+',22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96',
+',81,82,,38,39,,227,231,236,237,238,233,235,243,244,239,240,,,220,221',
+',,241,242,,210,,,214,,,52,,,54,,,224,,230,40,226,225,222,223,234,232',
+'228,18,229,,,,79,73,75,76,77,78,,,,74,80,,245,,63,64,65,56,51,,53,,57',
+'58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219',
+',,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,227,231',
+'236,237,238,233,235,243,244,239,240,,,220,221,,,241,242,,210,,,214,',
+',52,,,54,,256,224,,230,40,226,225,222,223,234,232,228,218,229,,,,79',
'73,75,76,77,78,,,,74,80,,245,,63,64,65,56,51,,53,,57,58,,37,83,61,,59',
-'60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,563,17,336,334,333,,335',
-',41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,231,236,237',
-'238,233,235,243,244,239,240,,,220,221,,,241,242,,210,,,214,,,52,,,54',
-',,224,,230,40,226,225,222,223,234,232,228,18,229,,,,79,73,75,76,77,78',
-',,,74,80,,245,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66',
-'67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,',
-'88,95,96,,81,82,,38,39,,227,231,236,237,238,233,235,243,244,239,240',
-',,220,221,,,241,242,,210,,,214,,,52,,,54,,,224,,230,40,226,225,222,223',
-'234,232,228,18,229,,,,79,73,75,76,77,78,,,,74,80,,245,,-255,-255,-255',
-'56,-255,,53,,-255,-255,,37,83,-255,,-255,-255,-255,-255,-255,-255,-255',
-',,,,,-255,-255,-255,-255,-255,-255,-255,,,-255,,,,,,,-255,,,-255,-255',
-',-255,-255,-255,-255,-255,-255,-255,-255,-255,,-255,-255,,-255,-255',
-',227,231,236,237,238,233,235,243,244,239,240,,,220,221,,,241,242,,-255',
-',,-255,268,,-255,,,-255,,-255,224,-255,230,-255,226,225,222,223,234',
-'232,228,-255,229,,,,-255,-255,-255,-255,-255,-255,,,,-255,-255,,245',
-',63,64,65,-255,51,,-255,,57,58,,-255,-255,61,,59,60,62,258,259,66,67',
-',,,,,257,291,295,90,89,91,92,,,219,,,,,625,,41,,,94,93,,84,50,86,85',
+'60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94',
+'93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,227,231,236,237,238,233',
+'235,243,244,239,240,,,220,221,,,241,242,,210,,,214,,,52,,,54,,,224,',
+'230,40,226,225,222,223,234,232,228,218,229,,,,79,73,75,76,77,78,,,,74',
+'80,,245,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,',
+',,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95',
+'96,,81,82,,38,39,,227,231,236,237,238,233,235,243,244,239,240,,,220',
+'221,,,241,242,,210,,,214,,,52,,,54,,,224,,230,40,226,225,222,223,234',
+'232,228,18,229,,,,79,73,75,76,77,78,,,,74,80,,245,,63,64,65,56,51,,53',
+',57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17',
+',,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,231,236',
+'237,238,233,235,243,244,239,240,,,220,221,,,241,242,,210,,,214,,,52',
+',,54,,,224,,230,40,226,225,222,223,234,232,228,18,229,,,,79,73,75,76',
+'77,78,,,,74,80,,245,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23',
+'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85',
'87,,88,95,96,,81,82,,38,39,,227,231,236,237,238,233,235,243,244,239',
'240,,,220,221,,,241,242,,210,,,214,,,52,,,54,,,224,,230,40,226,225,222',
-'223,234,232,228,218,229,,,,79,73,75,76,77,78,,,,74,80,,245,,-233,,,56',
-',,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,',
-',,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88',
-'95,96,,81,82,,38,39,,227,231,236,237,238,233,235,243,244,239,240,,,220',
-'221,,,241,242,,36,,,30,,,52,,,54,,32,224,,230,40,226,225,222,223,234',
-'232,228,18,229,,,,79,73,75,76,77,78,,,,74,80,,245,,-233,,,56,,,53,,',
-',,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28',
-'27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81',
-'82,,38,39,,227,231,236,237,238,233,235,243,244,239,240,,,220,221,,,241',
-'242,,36,,,30,,,52,,,54,,32,224,,230,40,226,225,222,223,234,232,228,18',
-'229,,,,79,73,75,76,77,78,,,,74,80,,245,,,,,56,,,53,,,,,37,83,63,64,65',
-'8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92',
-',,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227',
-'231,236,237,238,233,235,243,244,239,240,,,220,221,,,241,242,,36,,,30',
-',,52,,,54,,32,224,,230,40,226,225,222,223,234,232,228,18,229,,,,79,73',
-'75,76,77,78,,,,74,80,,245,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57',
-'58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7',
-'41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,231,236,237',
-'238,233,235,243,244,239,240,,,220,221,,,241,242,,36,,,30,,,52,,,54,',
-'32,224,,230,40,226,225,222,223,234,232,228,18,229,,,,79,73,75,76,77',
-'78,,,,74,80,,245,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258',
-'259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50',
-'86,85,87,,88,95,96,,81,82,,38,39,,227,231,236,237,238,233,235,243,244',
-'239,240,,,220,221,,,241,242,,210,,,214,,,52,,,54,,658,224,254,230,40',
-'226,225,222,223,234,232,228,218,229,,,,79,73,75,76,77,78,,,,74,80,,245',
-',,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66',
-'67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87',
+'223,234,232,228,18,229,,,,79,73,75,76,77,78,,,,74,80,101,245,,-233,',
+'100,56,,,53,,,,,37,83,63,64,65,,51,,,,57,58,,,,61,,59,60,62,258,259',
+'66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,292,,,94,93,,84,50,86',
+'85,87,,88,95,96,,81,82,227,231,236,237,238,233,235,243,244,239,240,227',
+',220,221,,,241,242,,,,,,356,,,30,241,242,52,,224,54,230,32,226,225,222',
+'223,234,232,228,224,229,230,,226,225,222,223,,79,73,75,76,77,78,,,245',
+'74,80,,,,63,64,65,56,51,,53,,57,58,,296,83,61,,59,60,62,258,259,66,67',
+',,,,,257,291,295,90,89,91,92,,,219,,,,,,,292,,,94,93,,84,50,86,85,361',
+',88,95,96,,81,82,227,231,236,237,238,233,235,243,244,239,240,227,,220',
+'221,,,241,242,,,367,,,362,,,214,241,242,52,,224,54,230,,226,225,222',
+'223,234,232,228,224,229,230,,226,225,222,223,,79,73,75,76,77,78,,,245',
+'74,80,,,,-531,-531,-531,56,-531,,53,,-531,-531,,296,83,-531,,-531,-531',
+'-531,-531,-531,-531,-531,,-531,,,,-531,-531,-531,-531,-531,-531,-531',
+',,-531,,,,,,,-531,,,-531,-531,,-531,-531,-531,-531,-531,-531,-531,-531',
+'-531,,-531,-531,,-531,-531,,227,231,236,237,238,233,235,243,244,239',
+'240,,,220,221,,,241,242,,-531,,,-531,-531,,-531,,,-531,,-531,224,-531',
+'230,-531,226,225,222,223,234,232,228,-531,229,-531,,,-531,-531,-531',
+'-531,-531,-531,,,,-531,-531,,245,,-532,-532,-532,-531,-532,,-531,,-532',
+'-532,,-531,-531,-532,,-532,-532,-532,-532,-532,-532,-532,,-532,,,,-532',
+'-532,-532,-532,-532,-532,-532,,,-532,,,,,,,-532,,,-532,-532,,-532,-532',
+'-532,-532,-532,-532,-532,-532,-532,,-532,-532,,-532,-532,,227,231,236',
+'237,238,233,235,243,244,239,240,,,220,221,,,241,242,,-532,,,-532,-532',
+',-532,,,-532,,-532,224,-532,230,-532,226,225,222,223,234,232,228,-532',
+'229,-532,,,-532,-532,-532,-532,-532,-532,,,,-532,-532,,245,,,,,-532',
+',,-532,,,,,-532,-532,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66',
+'67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,6,9,94,93,,84,50,86,85,87',
',88,95,96,,81,82,,38,39,,227,231,236,237,238,233,235,243,244,239,240',
',,220,221,,,241,242,,36,,,30,,,52,,,54,,32,224,,230,40,226,225,222,223',
-'234,232,228,18,229,,,,79,73,75,76,77,78,,,,74,80,,245,,,,,56,,,53,,',
-',,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28',
-'27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81',
-'82,,38,39,,227,231,236,237,238,233,235,243,244,239,240,,,220,221,,,241',
-'242,,36,,,30,,,52,,,54,,32,224,,230,40,226,225,222,223,234,232,228,18',
-'229,,,,79,73,75,76,77,78,,,,74,80,,245,,63,64,65,56,51,,53,,57,58,,37',
-'83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,563,219',
-'336,334,333,,335,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
-'563,,336,334,333,,335,,,563,566,336,334,333,,335,,,829,,,210,,,214,',
-',52,,,54,,658,,,,40,,,566,,,,,218,,,569,566,79,73,75,76,77,78,,569,',
-'74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67',
-',,,,,257,291,295,90,89,91,92,,,219,,,,,,,292,,,94,93,,84,50,86,85,87',
-',88,95,96,,81,82,327,,336,334,333,227,335,,,,,,,,,,,,,,,,241,242,926',
-',,214,,,52,,,54,,,,224,,338,,226,225,222,223,,,341,340,344,343,,79,73',
-'75,76,77,78,794,,,74,80,,,,63,64,65,56,51,,53,,57,58,,296,83,61,,59',
-'60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84',
-'50,86,85,87,,88,95,96,,81,82,,38,39,,227,-555,-555,-555,-555,233,235',
-',,-555,-555,,,,,,,241,242,,210,,,214,215,,52,,,54,,,224,,230,40,226',
+'234,232,228,18,229,,,,79,73,75,76,77,78,,,,74,80,,245,,,,404,56,,,53',
+',,,,37,83,63,64,65,,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22',
+'28,27,90,89,91,92,,563,17,336,334,333,,335,,41,,,94,93,,84,50,86,85',
+'87,,88,95,96,,81,82,,38,39,563,,336,334,333,,335,,,563,566,336,334,333',
+',335,,,569,,,210,,,214,,,52,,,54,,,,,,40,,,566,,,,,18,,,569,566,79,73',
+'75,76,77,78,,829,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60',
+'62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50',
+'86,85,87,,88,95,96,,81,82,,38,39,,227,231,236,237,238,233,235,243,244',
+'239,240,,,-555,-555,,,241,242,,210,,,214,,,52,,,54,,,224,,230,40,226',
'225,222,223,234,232,228,18,229,,,,79,73,75,76,77,78,,,,74,80,,,,63,64',
'65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90',
-'89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38',
-'39,,227,-555,-555,-555,-555,233,235,,,-555,-555,,,,,,,241,242,,210,',
-',214,,,52,,,54,,,224,,230,40,226,225,222,223,234,232,228,218,229,,,',
-'79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,',
-'57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,',
-',,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,-555,-555',
-'-555,-555,233,235,,,-555,-555,,,,,,,241,242,,36,,,30,,,52,,,54,,32,224',
-',230,40,226,225,222,223,234,232,228,18,229,,,,79,73,75,76,77,78,,,,74',
-'80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,',
-',,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261',
-'88,95,96,,81,82,,38,39,,227,-555,-555,-555,-555,233,235,,,-555,-555',
-',,,,,,241,242,,210,,,214,,,52,,,54,,,224,254,230,40,226,225,222,223',
-'234,232,228,218,229,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51',
-',53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91',
-'92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39',
-',227,-555,-555,-555,-555,233,235,,,-555,-555,,,,,,,241,242,,210,,,214',
-',,52,,,54,,256,224,254,230,40,226,225,222,223,234,232,228,218,229,,',
-',79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,',
-'59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94',
-'93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,227,,,,,,,,,,,,,,,,,241',
-'242,,210,,,214,,,52,,,54,,256,224,254,230,40,226,225,222,223,,,228,218',
+'89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38',
+'39,,227,231,236,237,238,233,235,243,244,239,240,,,-555,-555,,,241,242',
+',210,,,214,,,52,,,54,,,224,,230,40,226,225,222,223,234,232,228,18,229',
+',,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
+',59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93',
+',84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,-555,-555,-555,-555,233',
+'235,,,-555,-555,,,,,,,241,242,,210,,,214,,,52,,,54,,,224,,230,40,226',
+'225,222,223,234,232,228,18,229,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56',
+',,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,',
+',,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88',
+'95,96,,81,82,,38,39,,227,,,,,,,,,,,,,,,,,241,242,,36,,,30,,,52,,,54',
+',32,224,,230,40,226,225,222,223,,,228,18,229,,,,79,73,75,76,77,78,,',
+',74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62',
+'23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,6,9,94,93,,84,50',
+'86,85,87,,88,95,96,,81,82,,38,39,,227,,,,,,,,,,,,,,,,,241,242,,36,,',
+'30,,,52,,,54,,32,224,,230,40,226,225,222,223,,,228,18,229,,,,79,73,75',
+'76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,',
+'61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9',
+'94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,,,,,,,,,,,,,,,,,241',
+'242,,36,,,30,,,52,,,54,,32,224,,230,40,226,225,222,223,,,228,18,229',
+',,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
+',59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,219,,,,,,,41,,,94',
+'93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,,,,,,,,,,,,,,,,,241',
+'242,,210,,,214,,,52,,,54,,421,224,,230,40,226,225,222,223,,,228,218',
+'229,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83',
+'61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,219,,,,,,,41,,',
+'94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,-555,-555,-555,-555',
+'233,235,,,-555,-555,,,,,,,241,242,,210,,,214,,,52,,,54,,421,224,,230',
+'40,226,225,222,223,234,232,228,218,229,,,,79,73,75,76,77,78,,,,74,80',
+',,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22',
+'28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,',
+'81,82,,38,39,,227,-555,-555,-555,-555,233,235,,,-555,-555,,,,,,,241',
+'242,,210,,,214,,,52,,,54,,,224,,230,40,226,225,222,223,234,232,228,218',
'229,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83',
'61,,59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41',
-',,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,227,,,,,,,,,,,,',
-',,,,241,242,,210,,,214,,,52,,,54,,256,224,254,230,40,226,225,222,223',
-',,228,218,229,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57',
-'58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,',
-'219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,,',
-',,,,,,,,,,,,,,241,242,,210,,,214,,,52,,,54,,,224,,230,40,226,225,222',
-'223,,,228,218,229,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
-',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
-',,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227',
-'231,236,237,238,233,235,243,,239,240,,,,,,,241,242,,210,,,214,,,52,',
-',54,,,224,,230,40,226,225,222,223,234,232,228,218,229,,,,79,73,75,76',
-'77,78,,,,74,80,,,,-255,-255,-255,56,-255,,53,,-255,-255,,37,83,-255',
-',-255,-255,-255,-255,-255,-255,-255,,,,,,-255,-255,-255,-255,-255,-255',
-'-255,,,-255,,,,,,,-255,,,-255,-255,,-255,-255,-255,-255,-255,-255,-255',
-'-255,-255,,-255,-255,,-255,-255,,227,231,236,237,238,233,235,,,239,240',
-',,,,,,241,242,,-255,,,-255,268,,-255,,,-255,,-255,224,-255,230,-255',
-'226,225,222,223,234,232,228,-255,229,,,,-255,-255,-255,-255,-255,-255',
-',,,-255,-255,,,,,,,-255,,,-255,,,,,-255,-255,63,64,65,8,51,,,,57,58',
-',,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41',
-',9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,,,,,,,,,,,,,,',
-',,241,242,,36,,,281,,,52,,,54,,32,224,,230,40,226,225,222,223,,,228',
-'18,229,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37',
-'83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,',
-',,,292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,327,,336,334,333,,335',
-',,,,,,,,,,,,,,,,,289,,,286,,,52,,,54,,285,,,,338,,554,,,,,,341,340,344',
-'343,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,296,83',
-'61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,',
-'292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,764,,336,334,333,754,335',
-',,,,,,,,,751,,,,,,,,289,,,214,,,52,,,54,,,,,,338,,,,,,,,341,340,344',
-'343,,79,73,75,76,77,78,,,,74,80,,,,298,,,56,,,53,,,,,296,83,63,64,65',
-',51,,,752,57,58,,,,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89',
-'91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
-',227,-555,-555,-555,-555,233,235,,,-555,-555,,,,,,,241,242,,210,,,214',
-',,52,,,54,,,224,,230,40,226,225,222,223,234,232,228,218,229,,,,79,73',
-'75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58',
-',,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41',
-',9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,231,236,237,238',
-'233,235,243,244,239,240,,,-555,-555,,,241,242,,36,,,30,,,52,,,54,,32',
-'224,,230,40,226,225,222,223,234,232,228,18,229,,,,79,73,75,76,77,78',
-',,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60',
-'62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84',
-'50,86,85,87,,88,95,96,,81,82,,38,39,,227,231,236,237,238,233,235,243',
-'244,239,240,,,-555,-555,,,241,242,,36,,,30,,,52,,,54,,32,224,,230,40',
-'226,225,222,223,234,232,228,18,229,,,,79,73,75,76,77,78,,,,74,80,,,',
-'63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28',
-'27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82',
-',38,39,,227,,,,,,,,,,,,,,,,,241,242,,210,,,214,,,52,,,54,,,224,,230',
-'40,226,225,222,223,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65',
-'56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295',
-'90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82',
-',38,39,,227,,,,,,,,,,,,,,,,,241,242,,210,,,214,,,52,,,54,,,224,,230',
-'40,226,225,222,223,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65',
-'56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295',
-'90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82',
-',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,',
-',,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
-',59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41',
-',,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,',
-',210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74',
-'80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23',
-'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86',
-'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54',
-',32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51',
-',53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89',
-'91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
-',,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218,,,,,79',
-'73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60',
-'62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50',
-'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
-',,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
-'51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90,89',
-'91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38',
-'39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218,,',
-',,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
-',59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41',
-',,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,',
-',,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,',
+',,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,227,-555,-555,-555',
+'-555,233,235,,,-555,-555,,,,,,,241,242,,210,,,214,,,52,,,54,,256,224',
+',230,40,226,225,222,223,234,232,228,218,229,,,,79,73,75,76,77,78,,,',
'74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67',
-',,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87',
-',88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,',
-',,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
-',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
-',,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,',
-',,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75',
-'76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23',
-'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85',
-'87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54',
-',,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,',
-'53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92',
-',,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,',
-',,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76',
+',,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261',
+'88,95,96,,81,82,,38,39,,227,-555,-555,-555,-555,233,235,,,-555,-555',
+',,,,,,241,242,,210,,,214,,,52,,,54,,256,224,,230,40,226,225,222,223',
+'234,232,228,218,229,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51',
+',53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92',
+',,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227',
+'-555,-555,-555,-555,233,235,,,-555,-555,,,,,,,241,242,,210,,,214,,,52',
+',,54,,,224,,230,40,226,225,222,223,234,232,228,218,229,,,,79,73,75,76',
'77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24',
'66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87',
-',88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,',
-',,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,101,,,,,100,56,,,53,,',
-',,37,83,63,64,65,,51,,,,57,58,,,,61,,59,60,62,258,259,66,67,,,,,,257',
-'291,295,90,89,91,92,,,219,,,,,,,292,,,94,93,,84,50,86,85,87,,88,95,96',
-',81,82,327,,336,334,333,,335,,,,,,,,,,,,,,,,,,356,,,30,,,52,,,54,,32',
-',,,338,322,,,,,,,341,340,344,343,,79,73,75,76,77,78,,,,74,80,,,,63,64',
-'65,56,51,,53,,57,58,,296,83,61,,59,60,62,258,259,66,67,,,,,,257,291',
-'295,90,89,91,92,,,219,,,,,,,292,,,94,93,,84,50,86,85,361,,88,95,96,',
-'81,82,327,,336,334,333,,335,,,,,,,,,,,,,,,367,,,362,,,214,,,52,,,54',
-',,,,,338,,,,,,,,341,340,344,343,,79,73,75,76,77,78,,,,74,80,,,,63,64',
-'65,56,51,,53,,57,58,,296,83,61,,59,60,62,258,259,66,67,,,,,,257,291',
-'295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81',
-'82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218',
-',,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
-',59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,219,,,,,,,41,,,94',
-'93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210',
-',,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,',
-',63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28',
-'27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81',
-'82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218',
-',,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
-',59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41',
-',,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,',
-',210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74',
-'80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23',
-'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86',
-'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54',
-',32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51',
-',53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89',
-'91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
-',,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73',
-'75,76,77,78,,,,74,80,,,,-531,-531,-531,56,-531,,53,,-531,-531,,37,83',
-'-531,,-531,-531,-531,-531,-531,-531,-531,,-531,,,,-531,-531,-531,-531',
-'-531,-531,-531,,,-531,,,,,,,-531,,,-531,-531,,-531,-531,-531,-531,-531',
-'-531,-531,-531,-531,,-531,-531,,-531,-531,,,,,,,,,,,,,,,,,,,,,,-531',
-',,-531,-531,,-531,,,-531,,-531,,-531,,-531,,,,,,,,-531,,-531,,,-531',
-'-531,-531,-531,-531,-531,,,,-531,-531,,,,-532,-532,-532,-531,-532,,-531',
-',-532,-532,,-531,-531,-532,,-532,-532,-532,-532,-532,-532,-532,,-532',
-',,,-532,-532,-532,-532,-532,-532,-532,,,-532,,,,,,,-532,,,-532,-532',
-',-532,-532,-532,-532,-532,-532,-532,-532,-532,,-532,-532,,-532,-532',
-',,,,,,,,,,,,,,,,,,,,,-532,,,-532,-532,,-532,,,-532,,-532,,-532,,-532',
-',,,,,,,-532,,-532,,,-532,-532,-532,-532,-532,-532,,,,-532,-532,,,,,',
-',-532,,,-532,,,,,-532,-532,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23',
-'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86',
-'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54',
-',32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,',
-',37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28',
-'27,90,89,91,92,,,17,,,,,,7,41,6,9,94,93,,84,50,86,85,87,,88,95,96,,81',
-'82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18',
-',,,,79,73,75,76,77,78,,,,74,80,,,,,,404,56,,,53,,,,,37,83,63,64,65,',
-'51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,',
-'17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,',
-',,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76,77',
-'78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66',
-'67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,',
-'88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,',
-',40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,',
-'57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17',
-',,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,',
-',,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78',
-',,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67',
-',,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88',
-'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40',
-',,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63',
-'64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89',
-'91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
-',,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73',
-'75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58',
-',,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41',
-'6,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,',
-',,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74',
-'80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23',
-'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86',
-'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54',
-',32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,',
-',37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28',
-'27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81',
-'82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18',
-',,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
-',59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93',
-',84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214',
-',,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56',
-',,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,',
-',,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88',
-'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40',
-',,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
-',37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,219,,,,',
-',,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,',
-',,,,,,210,,,214,,,52,,,54,,421,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78',
-',,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67',
-',,,,,22,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88',
-'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,421,,',
-',40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
-',57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,219',
+',88,95,96,,81,82,,38,39,,227,231,236,237,238,233,235,,,239,240,,,,,',
+',241,242,,210,,,214,,,52,,,54,,,224,,230,40,226,225,222,223,234,232',
+'228,18,229,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
+',37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,',
+',41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,227,231,236,237',
+'238,233,235,243,,239,240,,,,,,,241,242,,210,,,214,,,52,,,54,,,224,,230',
+'40,226,225,222,223,234,232,228,18,229,,,,79,73,75,76,77,78,,,,74,80',
+',,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24',
+'66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85',
+'87,,88,95,96,,81,82,,38,39,,227,,,,,,,,,,,,,,,,,241,242,,36,,,30,,,52',
+',,54,,32,224,,,40,226,225,222,223,,,,18,,,,,79,73,75,76,77,78,,,,74',
+'80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,',
+',22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96',
+',81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,458,52,,,54,,,,,,40,,',
+',,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
+',37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219',
',,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,',
',,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77',
'78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259',
-'66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85',
-'87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,',
-'54,,256,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65',
-'56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90',
-'89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82',
-',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218',
-',,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
-',59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41',
-',,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,',
-',210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,',
-'74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67',
-',,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87',
-',88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,421',
-',,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
-',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
-',,219,,,,,,,292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,,,,,,,,,,',
-',,,,,,,,,,,,,289,,,286,,,52,,,54,,,,,,,,,,,,,,,,,,,79,73,75,76,77,78',
-',,,74,80,,,,63,64,65,56,51,,53,,57,58,,296,83,61,,59,60,62,23,24,66',
-'67,,,,,,22,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87',
-',88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,',
-',,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
-',57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17',
-',,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,',
-',,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78',
-',,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67',
-',,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88',
-'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40',
-',,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
-',37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219',
-',,,,,,292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,764,,336,334,333',
-'754,335,,,,,,,,,,751,,,,,,,,289,,,286,,,52,,,54,,,,,,338,749,,,,,,,341',
-'340,344,343,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,296,83,63',
-'64,65,8,51,,,752,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90',
-'89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38',
-'39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79',
-'73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57',
-'58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7',
-'41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,',
-',,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,',
-'74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67',
-',,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87',
-'261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54',
-',,,254,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
+'66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86',
+'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,',
+'54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
'51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90',
-'89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82',
-',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,658,,254,,40,,,,,,',
-',218,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65',
-'8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92',
-',,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,',
-',,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75',
-'76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,',
-'61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9',
-'94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36',
-',,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,',
-',63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28',
-'27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82',
-',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,458,52,,,54,,,,,,40,,,,,,,,18',
-',,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
+'89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38',
+'39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79',
+'73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60',
+'62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93',
+',84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214',
+',,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64',
+'65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295',
+'90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82',
+',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,',
+',,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
',59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41',
',,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,',
',210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74',
@@ -525,133 +335,314 @@ clist = [
'259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50',
'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
',,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
+'51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90,89',
+'91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38',
+'39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,254,,40,,,,,,,,218',
+',,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
+',59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,',
+'94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,',
+',,210,,,214,,,506,,,54,,256,,254,,40,,,,,,,,218,,,,,79,73,75,76,77,78',
+',,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66',
+'67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87',
+'261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,510,52,,',
+'54,,256,,254,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56',
+',,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,',
+',,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88',
+'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,281,,,52,,,54,,32,,,,40',
+',,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
+',37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219',
+',,,,,,292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,764,,336,334,333',
+'754,335,,,,,,,,,,751,,,,,,,,289,,,214,,,52,,,54,,,,,,338,,,,,,,,341',
+'340,344,343,,79,73,75,76,77,78,,,,74,80,,,,518,,,56,,,53,,,,,296,83',
+'63,64,65,8,51,,,752,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27',
+'90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82',
+',38,39,,,,,,,,,,,,,,,,,,,,,,36,,,281,,,52,,,54,,32,,,,40,,,,,,,,18,',
+',,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
+',59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,292',
+',,94,93,,84,50,86,85,87,,88,95,96,,81,82,327,,336,334,333,,335,,,,,',
+',,,,,,,,,,,,289,,,286,,,52,,,54,,,,,,338,322,,,,,,,341,340,344,343,',
+'79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,296,83,61,',
+'59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,',
+',94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,',
+'210,,,214,537,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74',
+'80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23',
+'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86',
+'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54',
+',32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51',
+',53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92',
+',,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,',
+',,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76',
+'77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24',
+'66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87',
+',88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,',
+',,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
+',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
+',,219,,,,,,,292,,,94,93,,84,50,86,85,361,,88,95,96,,81,82,327,,336,334',
+'333,,335,,,,,,,,,,,,,,,,,,362,,,214,,,52,,,54,,,,,,338,,554,,,,,,341',
+'340,344,343,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
+',296,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,',
+',,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,',
+',,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,',
+',74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67',
+',,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87',
+',88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,',
+',,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,-255,-255,-255,56',
+'-255,,53,,-255,-255,,37,83,-255,,-255,-255,-255,-255,-255,-255,-255',
+',,,,,-255,-255,-255,-255,-255,-255,-255,,,-255,,,,,,,-255,,,-255,-255',
+',-255,-255,-255,-255,-255,-255,-255,-255,-255,,-255,-255,,-255,-255',
+',,,,,,,,,,,,,,,,,,,,,-255,,,-255,268,,-255,,,-255,,-255,,-255,,-255',
+',,,,,,,-255,,,,,-255,-255,-255,-255,-255,-255,,,,-255,-255,,,,-536,-536',
+'-536,-255,-536,,-255,,-536,-536,,-255,-255,-536,,-536,-536,-536,-536',
+'-536,-536,-536,,,,,,-536,-536,-536,-536,-536,-536,-536,,,-536,,,,,,',
+'-536,,,-536,-536,,-536,-536,-536,-536,-536,-536,-536,-536,-536,,-536',
+'-536,,-536,-536,,,,,,,,,,,,,,,,,,,,,,-536,,,-536,-536,,-536,,,-536,',
+'-536,,-536,,-536,,,,,,,,-536,,,,,-536,-536,-536,-536,-536,-536,,,,-536',
+'-536,,,,-537,-537,-537,-536,-537,,-536,,-537,-537,,-536,-536,-537,,-537',
+'-537,-537,-537,-537,-537,-537,,,,,,-537,-537,-537,-537,-537,-537,-537',
+',,-537,,,,,,,-537,,,-537,-537,,-537,-537,-537,-537,-537,-537,-537,-537',
+'-537,,-537,-537,,-537,-537,,,,,,,,,,,,,,,,,,,,,,-537,,,-537,-537,,-537',
+',,-537,,-537,,-537,,-537,,,,,,,,-537,,,,,-537,-537,-537,-537,-537,-537',
+',,,-537,-537,,,,-255,-255,-255,-537,-255,,-537,,-255,-255,,-537,-537',
+'-255,,-255,-255,-255,-255,-255,-255,-255,,,,,,-255,-255,-255,-255,-255',
+'-255,-255,,,-255,,,,,,,-255,,,-255,-255,,-255,-255,-255,-255,-255,-255',
+'-255,-255,-255,,-255,-255,,-255,-255,,,,,,,,,,,,,,,,,,,,,,-255,,,-255',
+'268,,-255,,,-255,,-255,,-255,,-255,,,,,,,,-255,,,,,-255,-255,-255,-255',
+'-255,-255,,,,-255,-255,,,,63,64,65,-255,51,,-255,,57,58,,-255,-255,61',
+',59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,',
+'94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,',
+',,210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,',
+',74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67',
+',,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261',
+'88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256',
+',,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
+',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
+',,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,',
+',,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75',
+'76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258',
+'259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50',
+'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
+',,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
'51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90',
'89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38',
'39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79',
'73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60',
'62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93',
-',84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214',
-',,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64',
-'65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295',
-'90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82',
-',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,',
-',,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51',
-',,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17',
-',,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,',
-',,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77',
+',84,50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210',
+',,214,,,52,,,54,,658,,254,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74',
+'80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,',
+',,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261',
+'88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,254',
+',40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
+',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
+',,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,',
+',,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75',
+'76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23',
+'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85',
+'87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,675,52,,',
+'54,,,,254,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53',
+',,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22',
+'28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96',
+',81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,',
+',,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,404,56,,,53,,,,,37,83,63,64',
+'65,,51,,,,57,58,,,,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89',
+'91,92,,,219,,,,,,,292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,327,',
+'336,334,333,,335,,,,,,,,,,,,,,,,,,289,,,286,,,52,,,54,,,,,,338,,,,,',
+',,341,340,344,343,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
+',57,58,,296,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92',
+',,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,',
+',,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218,,,,,79',
+'73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60',
+'62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,',
+'84,50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,',
+',214,,,52,,,54,,256,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80',
+',,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,',
+'257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95',
+'96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,',
+',,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
+',37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219',
+',,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,',
+',,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77',
'78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259',
'66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86',
'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,',
'54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
+'51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91',
+'92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,',
+',,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75',
+'76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258',
+'259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50',
+'86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,',
+',52,,,54,,658,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63',
+'64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291',
+'295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96',
+',81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,',
+',,218,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65',
+'8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92',
+',,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,',
+',,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75',
+'76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,',
+'61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9',
+'94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36',
+',,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,',
+',63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257',
+'291,295,90,89,91,92,,,219,,,,,,,292,,,94,93,,84,50,86,85,87,,88,95,96',
+',81,82,764,,336,334,333,754,335,,,,,,,,,,751,,,,,,,,712,,,214,,,52,',
+',54,,,,,,338,,,,,,,,341,340,344,343,,79,73,75,76,77,78,,,,74,80,,,,',
+',,56,,,53,,,,,296,83,63,64,65,8,51,,,752,57,58,,,,61,,59,60,62,23,24',
+'66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85',
+'87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32',
+',,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37',
+'83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27',
+'90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82',
+',38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,',
+',,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,',
+',,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,',
+',,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,',
+',,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77',
+'78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259',
+'66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85',
+'87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,',
+'54,,256,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65',
+'56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90',
+'89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82',
+',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218',
+',,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
+',59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,',
+'94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,',
+',,210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,',
+',74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67',
+',,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88',
+'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40',
+',,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
+',37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,',
+',41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,',
+',,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,',
+'74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67',
+',,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87',
+',88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,',
+',,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
+',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
+',,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,',
+',,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,775,,,,40,,,,,,,,218,,,,,79,73',
+'75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62',
+'23,24,66,67,,,,,,22,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50',
+'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
+',,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
+'51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91',
+'92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,',
+',,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73',
+'75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62',
+'23,24,66,67,,,,,,22,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50',
+'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
+',,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
'51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90',
'89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38',
'39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79',
'73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60',
'62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93',
',84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214',
-',,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64',
+',,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56',
+',,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,',
+',,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88',
+'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40',
+',,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
+',37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219',
+',,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,',
+',,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77',
+'78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59',
+'60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93',
+',84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30',
+',,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64',
'65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295',
-'90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82',
-',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,',
-',,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
+'90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81',
+'82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,658,,254,,40,,,',
+',,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
+',37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219',
+',,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,',
+',,,,,,,,,,,,,210,,,214,,,52,,,54,,,,254,,40,,,,,,,,218,,,,,79,73,75',
+'76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,',
+'61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9',
+'94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36',
+',,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,',
+',,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66',
+'67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87',
+',88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,',
+',,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
+',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
+',,219,,,,,,,292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,,,,,,,,,,',
+',,,,,,,,,,,,,289,,,286,,,52,,,54,,,,,,,,,,,,,,,,,,,79,73,75,76,77,78',
+',,,74,80,,,,63,64,65,56,51,,53,,57,58,,296,83,61,,59,60,62,258,259,66',
+'67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,292,,,94,93,,84,50,86,85',
+'87,,88,95,96,,81,82,,,,,,,,,,,,,,,,,,,,,,,,,289,,,286,,,52,,,54,,,,',
+',,,,,,,,,,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
+',296,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219',
+',,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,',
+',,,,,,,,,,210,,,214,,,52,,,54,,421,,,,40,,,,,,,,218,,,,,79,73,75,76',
+'77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258',
+'259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50',
+'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
+',,54,,256,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65',
+'56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89',
+'91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
+',,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73',
+'75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58',
+',,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41',
+',9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,',
+',,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74',
+'80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23',
+'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86',
+'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54',
+',32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,',
+',37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28',
+'27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81',
+'82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18',
+',,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
',59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41',
',,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,',
',210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74',
-'80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,',
-',22,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95',
-'96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,',
-',,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
-',37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,219,,,,',
-',,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,',
-',,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,',
-',,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67',
-',,,,,22,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88',
-'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40',
-',,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57',
-'58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219',
-',,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,',
-',,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,254,,40,,,,,,,,218,,,,,79,73',
+'80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23',
+'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86',
+'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54',
+',32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51',
+',53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89',
+'91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
+',,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73',
'75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62',
-'258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84',
-'50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214',
-',,506,,,54,,256,,254,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,',
-',,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257',
-'28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96',
-',81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,510,52,,,54,,256,,254',
-',40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
-',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
-',,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,',
-',,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,775,,,,40,,,,,,,,218,,,,,79,73',
+'23,24,66,67,,,,,,22,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50',
+'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
+',,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
+'51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91',
+'92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,',
+',,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73',
'75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62',
'258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84',
'50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,',
',52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64',
-'65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90',
-'89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38',
-'39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79',
-'73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57',
-'58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7',
-'41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,',
-',,,,,36,,,281,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,',
-',74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,23,24,66,67',
-',,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88',
-'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40',
-',,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58',
-',37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219,',
-',,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,',
-',,,,,,,,,,,,210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218,,,,,79,73,75,76',
-'77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258',
-'259,66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86',
-'85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
-',,54,,256,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65',
-'56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295',
-'90,89,91,92,,,219,,,,,,,292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82',
-'764,,336,334,333,754,335,,,,,,,,,,751,,,,,,,,289,,,214,,,52,,,54,,,',
-',,338,749,,,,,,,341,340,344,343,,79,73,75,76,77,78,,,,74,80,,,,518,',
-',56,,,53,,,,,296,83,63,64,65,8,51,,,752,57,58,,,,61,,59,60,62,23,24',
-'66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85',
-'87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,281,,,52,,,54,',
-'32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51',
-',53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27,90,89,91',
-'92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39',
-',,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,,,40,,,,,,,,218,,,,,79',
-'73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57',
-'58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7',
-'41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,',
-',,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,',
-'74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62',
-'23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50',
-'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,',
-',54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53',
+'65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295',
+'90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82',
+',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,',
+',,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61',
+',59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41',
+',,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,',
+',210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74',
+'80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,',
+',,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88',
+'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,',
+',40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83',
+'63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90',
+'89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38',
+'39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79',
+'73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60',
+'62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50',
+'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
+',,54,,,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53',
',,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22',
'28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96',
',81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,',
-',,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37',
-'83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,',
-',,,292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,764,,336,334,333,754',
-'335,,,,,,,,,,751,,,,,,,,712,,,214,,,52,,,54,,,,,,338,,,,,,,,341,340',
-'344,343,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,296,83,63,64,65',
-'8,51,,,752,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91',
-'92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,',
-',,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73',
-'75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58',
-',,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41',
-',9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,',
-',,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74',
-'80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,',
-',,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261',
-'88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,',
-',40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53',
-',57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
-',,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82,,38,39,,',
-',,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,658,,,,40,,,,,,,,218,,,,,79',
-'73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60',
-'62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,292,,,94,93',
-',84,50,86,85,87,,88,95,96,,81,82,,,,,,,,,,,,,,,,,,,,,,,,,289,,,286,',
-',52,,,54,,,,,,,,,,,,,,,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
-'51,,53,,57,58,,296,83,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91',
-'92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,',
-',,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,18,,,,,79,73,75',
+',,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65',
+'8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92',
+',,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,',
+',,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75',
'76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258',
'259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50',
'86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52',
@@ -663,158 +654,145 @@ clist = [
'62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93',
',84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214',
',,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64',
-'65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27',
+'65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295',
'90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81',
-'82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,,,40,,,,,,',
-',218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37',
-'83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,',
-',,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,',
-',,,,,,,210,,,214,537,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77',
+'82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,,,254,,40,,,,,,',
+',218,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65',
+'8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92',
+',,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,',
+',,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75',
+'76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258',
+'259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,,292,,,94,93,,84,50',
+'86,85,87,,88,95,96,,81,82,,,,,,,,,,,,,,,,,,,,,,,,,926,,,214,,,52,,,54',
+',,,,,,,,,,,,,,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,',
+'57,58,,296,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92',
+',,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,',
+',,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,658,,,,40,,,,,,,,218,,,,,79,73',
+'75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58',
+',,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41',
+',9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,',
+',,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74',
+'80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23',
+'24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86',
+'85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54',
+',32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51',
+',53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89',
+'91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
+',,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,658,,254,,40,,,,,,,,218,,',
+',,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,',
+',,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,',
+',,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,',
+',,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77',
'78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59',
'60,62,23,24,66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93',
',84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30',
-',,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64',
-'65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,28,27',
-'90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81',
-'82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,256,,,,40,,,,,,',
-',218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37',
-'83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,',
-',,,292,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,,,,,,,,,,,,,,,,,,,',
-',,,,289,,,286,,,52,,,54,,,,,,,,,,,,,,,,,,,79,73,75,76,77,78,,,,74,80',
-',,,,,,56,,,53,,,,,296,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24',
-'66,67,,,,,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85',
-'87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32',
-',,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,404,56,,,53,,,,',
-'37,83,63,64,65,,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27',
-'90,89,91,92,,,17,,,,,,,41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,',
-'38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,675,52,,,54,,,,254,,40,,,,,,,',
-'18,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83',
-'61,,59,60,62,258,259,66,67,,,,,,257,291,295,90,89,91,92,,,219,,,,,,',
-'41,,,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,',
-',,,,210,,,214,,,52,,,54,,,,,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,',
-'74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67',
-',,,,,257,291,295,90,89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87',
-'261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54',
-',,,254,,40,,,,,,,,218,,,,,79,73,75,76,77,78,,,,74,80,,,,63,64,65,56',
-'51,,53,,57,58,,37,83,61,,59,60,62,258,259,66,67,,,,,,257,291,295,90',
-'89,91,92,,,219,,,,,,,41,,,94,93,,84,50,86,85,87,261,88,95,96,,81,82',
-',38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214,,,52,,,54,,658,,254,,40,,,,,,',
-',218,,,,-283,79,73,75,76,77,78,-283,-283,-283,74,80,,-283,-283,,-283',
-',56,,,53,,,,,37,83,,,,,,,,,-283,-283,,-283,-283,-283,-283,-283,,,,,',
-',,,,,,,,,,,,,,,,,,-283,-283,-283,-283,-283,-283,-283,-283,-283,-283',
-'-283,-283,-283,-283,-283,,,-283,-283,-283,,639,,,,-283,,,,,,,-283,,-283',
-',-283,-283,-283,-283,-283,-283,-283,,-283,,-283,,,,,,,,,,,,,-283,-283',
-',-89,,-283,-538,,-283,,-283,,-98,-538,-538,-538,,,-538,-538,-538,,-538',
-',,,,,,,,-538,-538,-538,,,,,,,,,-538,-538,,-538,-538,-538,-538,-538,',
-',,,,,,,,,,,,,,,,,,,,,,-538,-538,-538,-538,-538,-538,-538,-538,-538,-538',
-'-538,-538,-538,-538,-538,,,-538,-538,-538,,790,-538,,,-538,,,-538,,-538',
-',-538,,-538,,-538,-538,-538,-538,-538,-538,-538,,-538,-538,-538,,,,',
-',,,,,,,,-538,-538,-538,-538,,-538,-283,,-538,,-538,,-96,-283,-283,-283',
-',,-283,-283,-283,,-283,,,,,,,,,,-283,-283,,,,,,,,,-283,-283,,-283,-283',
-'-283,-283,-283,,,,,,,,,,,,,,,,,,,,,,,,-283,-283,-283,-283,-283,-283',
-'-283,-283,-283,-283,-283,-283,-283,-283,-283,,,-283,-283,-283,,639,-283',
-',,-283,,,-283,,-283,,-283,,-283,,-283,-283,-283,-283,-283,-283,-283',
-',-283,,-283,,,,,,,,,,,,,-283,-283,-283,-283,,-283,-538,,-283,,-283,',
-'-98,-538,-538,-538,,,,-538,-538,,-538,,,,,,,,,-538,,,,,,,,,,,-538,-538',
+',,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56',
+',,53,,,,,37,83,63,64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,',
+',,,22,28,27,90,89,91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88',
+'95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40',
+',,,,,,,18,,,,,79,73,75,76,77,78,,,,74,80,,,,,,,56,,,53,,,,,37,83,63',
+'64,65,8,51,,,,57,58,,,,61,,59,60,62,23,24,66,67,,,,,,22,28,27,90,89',
+'91,92,,,17,,,,,,7,41,,9,94,93,,84,50,86,85,87,,88,95,96,,81,82,,38,39',
+',,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,,,54,,32,,,,40,,,,,,,,18,,,,,79,73',
+'75,76,77,78,,,,74,80,,,,63,64,65,56,51,,53,,57,58,,37,83,61,,59,60,62',
+'258,259,66,67,,,,,,257,28,27,90,89,91,92,,,219,,,,,,,41,,,94,93,,84',
+'50,86,85,87,261,88,95,96,,81,82,,38,39,,,,,,,,,,,,,,,,,,,,,,210,,,214',
+',,52,,,54,,256,,,,40,,,,,,,,218,,,,-538,79,73,75,76,77,78,-538,-538',
+'-538,74,80,,-538,-538,,-538,,56,,,53,,,,-538,37,83,,,,,,,,,-538,-538',
',-538,-538,-538,-538,-538,,,,,,,,,,,,,,,,,,,,,,,,-538,-538,-538,-538',
-'-538,-538,-538,-538,-538,-538,-538,-538,-538,-538,-538,,,-538,-538,-538',
-',636,,,,-538,,,,,,,-538,,-538,,-538,-538,-538,-538,-538,-538,-538,,-538',
-'-538,-538,,,,,,,,,,,,,-538,-538,,-87,,-538,-278,,-538,,-538,,-96,-278',
+'-538,-538,-538,-538,-538,-538,-538,-538,-538,-538,-538,-283,,-538,-538',
+'-538,,636,-283,-283,-283,-538,,,-283,-283,,-283,-538,,-538,,-538,-538',
+'-538,-538,-538,-538,-538,,-538,-538,-538,,,,,-283,-283,,-283,-283,-283',
+'-283,-283,-538,-538,,-87,,-538,,,-538,,-538,,-96,,,,,,,,,,,-283,-283',
+'-283,-283,-283,-283,-283,-283,-283,-283,-283,-283,-283,-283,-283,,,-283',
+'-283,-283,,639,,,,-283,,,,,,,-283,,-283,,-283,-283,-283,-283,-283,-283',
+'-283,,-283,,-283,,,,,,,,,,,,,-283,-283,,-89,,-283,-538,,-283,,-283,',
+'-98,-538,-538,-538,,,-538,-538,-538,,-538,,,,,,,,,-538,-538,-538,,,',
+',,,,,-538,-538,,-538,-538,-538,-538,-538,,,,,,,,,,,,,,,,,,,,,,,,-538',
+'-538,-538,-538,-538,-538,-538,-538,-538,-538,-538,-538,-538,-538,-538',
+',,-538,-538,-538,,790,-538,,,-538,,,-538,,-538,,-538,,-538,,-538,-538',
+'-538,-538,-538,-538,-538,,-538,-538,-538,,,,,,,,,,,,,-538,-538,-538',
+'-538,,-538,-283,,-538,,-538,,-96,-283,-283,-283,,,-283,-283,-283,,-283',
+',,,,,,,,,-283,-283,,,,,,,,,-283,-283,,-283,-283,-283,-283,-283,,,,,',
+',,,,,,,,,,,,,,,,,,-283,-283,-283,-283,-283,-283,-283,-283,-283,-283',
+'-283,-283,-283,-283,-283,,,-283,-283,-283,,639,-283,,,-283,,,-283,,-283',
+',-283,,-283,,-283,-283,-283,-283,-283,-283,-283,,-283,,-283,,,,,,,,',
+',,,,-283,-283,-283,-283,,-283,-292,,-283,,-283,,-98,-292,-292,-292,',
+',-292,-292,-292,,-292,,,,,,,,,,-292,-292,,,,,,,,,-292,-292,,-292,-292',
+'-292,-292,-292,,,,,,,,,,,,,,,,,,,,,,,,-292,-292,-292,-292,-292,-292',
+'-292,-292,-292,-292,-292,-292,-292,-292,-292,,,-292,-292,-292,,,-292',
+',277,-292,,,-292,,-292,,-292,,-292,,-292,-292,-292,-292,-292,-292,-292',
+',-292,,-292,,,,,,,,,,,,,-292,-292,-292,-292,-278,-292,,,-292,,-292,-278',
'-278,-278,,,-278,-278,-278,,-278,,,,,,,,,,-278,-278,-278,,,,,,,,-278',
'-278,,-278,-278,-278,-278,-278,,,,,,,,,,,,,,,,,,,,,,,,-278,-278,-278',
'-278,-278,-278,-278,-278,-278,-278,-278,-278,-278,-278,-278,,,-278,-278',
'-278,,,-278,,,-278,,,-278,,-278,,-278,,-278,,-278,-278,-278,-278,-278',
-'-278,-278,,-278,,-278,,,,,,,,,,,,,-278,-278,-278,-278,-292,-278,,-278',
-'-278,,-278,-292,-292,-292,,,-292,-292,-292,,-292,,,,,,,,,,-292,-292',
-',,,,,,,,-292,-292,,-292,-292,-292,-292,-292,,,,,,,,,,,,,,,,,,,,,,,,-292',
-'-292,-292,-292,-292,-292,-292,-292,-292,-292,-292,-292,-292,-292,-292',
-',,-292,-292,-292,,,-292,,277,-292,,,-292,,-292,,-292,,-292,,-292,-292',
-'-292,-292,-292,-292,-292,,-292,,-292,,,,,,,,,,,,,-292,-292,-292,-292',
-'-554,-292,,,-292,,-292,-554,-554,-554,,,-554,-554,-554,,-554,,,,,,,',
-',,-554,,,,,,,,,,-554,-554,,-554,-554,-554,-554,-554,,,,,,,,,,,,,,-554',
-',,,,,,-554,-554,-554,,,-554,-554,-554,,-554,,,,,-554,-554,,,,-554,,',
-'-554,,,,,268,-554,-554,-554,,-554,-554,-554,-554,-554,,,,,,,,,,,,,-554',
-',,,,,,,,,,,-554,-554,,-554,,,-554,-554,-554,-554,-554,-554,-554,-554',
-'-554,,-554,,-554,,,,,268,-554,,-554,,,,,,,,,,-554,-554,,-554,-554,-554',
-'-554,-554,,-554,,,,,,436,440,,,438,,,-554,,-554,,,-554,142,143,,139',
-'121,122,123,130,127,129,,,124,125,-554,-554,,,144,145,131,132,-554,',
-',,,268,-554,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119',
-',-554,146,,,,,,,,,,,,-554,,-554,,,-554,156,167,157,180,153,173,163,162',
-'188,191,178,161,160,155,181,189,190,165,154,168,172,174,166,159,,,,175',
-'182,177,176,169,179,164,152,171,170,183,184,185,186,187,151,158,149',
-'150,147,148,,111,113,,,112,,,,,,,,,142,143,,139,121,122,123,130,127',
-'129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137',
-'133,134,128,126,118,140,119,,,146,192,,,,,,,,,,80,156,167,157,180,153',
-'173,163,162,188,191,178,161,160,155,181,189,190,165,154,168,172,174',
-'166,159,,,,175,182,177,176,169,179,164,152,171,170,183,184,185,186,187',
-'151,158,149,150,147,148,,111,113,,,112,,,,,,,,,142,143,,139,121,122',
-'123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120',
-'141,138,137,133,134,128,126,118,140,119,,,146,192,,,,,,,,,,80,156,167',
-'157,180,153,173,163,162,188,191,178,161,160,155,181,189,190,165,154',
-'168,172,174,166,159,,,,175,182,177,176,169,179,164,152,171,170,183,184',
-'185,186,187,151,158,149,150,147,148,,111,113,,,112,,,,,,,,,142,143,',
-'139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,,',
-',,136,135,,120,141,138,137,133,134,128,126,118,140,119,,,146,192,,,',
-',,,,,,80,156,167,157,180,153,173,163,162,188,191,178,161,160,155,181',
-'189,190,165,154,168,172,174,166,159,,,,175,182,177,176,169,179,164,152',
-'171,170,183,184,185,186,187,151,158,149,150,147,148,,111,113,110,,112',
-',,,,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131',
+'-278,-278,,-278,,-278,,,,,,,,,,,,,-278,-278,-278,-278,-554,-278,,-278',
+'-278,,-278,-554,-554,-554,,,-554,-554,-554,,-554,,,,,,,,,,-554,,,,,',
+',,,,-554,-554,,-554,-554,-554,-554,-554,,,,,,,,,,,,,,-554,,,,,,,-554',
+'-554,-554,,,-554,-554,-554,,-554,,,,,-554,-554,,,,-554,,,-554,,,,,268',
+'-554,-554,-554,,-554,-554,-554,-554,-554,,,,,764,,336,334,333,754,335',
+',-554,,,,,,,,751,,,,-554,-554,,-554,,,-554,-554,-554,-554,-554,-554',
+'-554,-554,-554,,-554,,-554,338,749,,,268,-554,,-554,341,340,344,343',
+',,,,,-554,-554,,-554,-554,-554,-554,-554,,-554,,,,,,436,440,,,438,,',
+'-554,,-554,,,-554,142,143,752,139,121,122,123,130,127,129,,,124,125',
+'-554,-554,,,144,145,131,132,-554,,,,,268,-554,,,,,,136,135,,120,141',
+'138,137,133,134,128,126,118,140,119,,-554,146,,,,,,,,,,,,-554,,-554',
+',,-554,156,167,157,180,153,173,163,162,188,191,178,161,160,155,181,189',
+'190,165,154,168,172,174,166,159,,,,175,182,177,176,169,179,164,152,171',
+'170,183,184,185,186,187,151,158,149,150,147,148,,111,113,110,,112,,',
+',,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131',
'132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119',
',,146,192,,,,,,,,,,80,156,167,157,180,153,173,163,162,188,191,178,161',
'160,155,181,189,190,165,154,168,172,174,166,159,,,,175,182,177,176,169',
'179,164,152,171,170,183,184,185,186,187,151,158,149,150,147,148,,111',
-'113,398,397,112,,399,,,,,,,142,143,,139,121,122,123,130,127,129,,,124',
-'125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134',
-'128,126,118,140,119,,,146,156,167,157,180,153,173,163,162,188,191,178',
-'161,160,155,181,189,190,165,154,168,172,174,166,159,,,,175,182,177,176',
-'169,179,164,152,171,170,183,184,185,186,187,151,158,149,150,147,148',
-',111,113,398,397,112,,399,,,,,,,142,143,,139,121,122,123,130,127,129',
+'113,,,112,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,',
+',144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134,128,126',
+'118,140,119,,,146,192,,,,,,,,,,80,156,167,157,180,153,173,163,162,188',
+'191,178,161,160,155,181,189,190,165,154,168,172,174,166,159,,,,175,182',
+'177,176,169,179,164,152,171,170,183,184,185,186,187,151,158,149,150',
+'147,148,,111,113,,,112,,,,,,,,,142,143,,139,121,122,123,130,127,129',
',,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137,133',
-'134,128,126,118,140,119,,,146,156,167,157,180,153,173,163,162,188,191',
-'178,161,160,155,181,189,190,165,154,168,172,174,166,159,,,,175,182,177',
-'176,169,179,164,152,171,170,183,184,185,186,187,151,158,149,150,147',
-'148,,111,113,,,112,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124',
-'125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134',
-'128,126,118,140,119,,,146,156,167,157,180,153,173,163,162,188,191,178',
-'161,160,155,181,189,190,165,154,168,172,174,166,159,,,,175,182,177,376',
-'375,377,374,152,171,170,183,184,185,186,187,151,158,149,150,372,373',
-',370,113,86,85,371,,88,,,,,,,142,143,,139,121,122,123,130,127,129,,',
-'124,125,,,,,144,145,131,132,,,,,,381,,,,,,,136,135,,120,141,138,137',
-'133,134,128,126,118,140,119,642,434,146,,643,,,,,,,,,142,143,,139,121',
-'122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,268,,,,,,,136',
-'135,,120,141,138,137,133,134,128,126,118,140,119,644,440,146,,645,,',
+'134,128,126,118,140,119,,,146,192,,,,,,,,,,80,156,167,157,180,153,173',
+'163,162,188,191,178,161,160,155,181,189,190,165,154,168,172,174,166',
+'159,,,,175,182,177,176,169,179,164,152,171,170,183,184,185,186,187,151',
+'158,149,150,147,148,,111,113,,,112,,,,,,,,,142,143,,139,121,122,123',
+'130,127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141',
+'138,137,133,134,128,126,118,140,119,,,146,192,,,,,,,,,,80,156,167,157',
+'180,153,173,163,162,188,191,178,161,160,155,181,189,190,165,154,168',
+'172,174,166,159,,,,175,182,177,376,375,377,374,152,171,170,183,184,185',
+'186,187,151,158,149,150,372,373,,370,113,86,85,371,,88,,,,,,,142,143',
+',139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,381',
+',,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119,,,146,156',
+'167,157,180,153,173,163,162,188,191,178,161,160,155,181,189,190,165',
+'154,168,172,174,166,159,,,,175,182,177,176,169,179,164,152,171,170,183',
+'184,185,186,187,151,158,149,150,147,148,,111,113,398,397,112,,399,,',
+',,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132',
+',,,,,,,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119,,,146',
+'156,167,157,180,153,173,163,162,188,191,178,161,160,155,181,189,190',
+'165,154,168,172,174,166,159,,,,175,182,177,176,169,179,164,152,171,170',
+'183,184,185,186,187,151,158,149,150,147,148,,111,113,398,397,112,,399',
',,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131',
'132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119',
-'430,434,146,,431,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124',
-'125,,,,,144,145,131,132,,,,,,268,,,,,,,136,135,,120,141,138,137,133',
-'134,128,126,118,140,119,961,440,146,,962,,,,,,,,,142,143,,139,121,122',
-'123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120',
-'141,138,137,133,134,128,126,118,140,119,959,434,146,,960,,,,,,,,,142',
-'143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,',
-'268,,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119,443,434',
-'146,,444,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,',
-'144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134,128,126',
-'118,140,119,443,434,146,,444,,,,,,,,,142,143,,139,121,122,123,130,127',
-'129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137',
-'133,134,128,126,118,140,119,443,434,146,,444,,,,,,,,,142,143,,139,121',
-'122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135',
-',120,141,138,137,133,134,128,126,118,140,119,642,434,146,,643,,,,,,',
-',,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132',
-',,,,,268,,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119',
-'644,440,146,,645,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124',
-'125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134',
-'128,126,118,140,119,741,440,146,,892,,,,,,,,,142,143,,139,121,122,123',
+',,146,156,167,157,180,153,173,163,162,188,191,178,161,160,155,181,189',
+'190,165,154,168,172,174,166,159,,,,175,182,177,176,169,179,164,152,171',
+'170,183,184,185,186,187,151,158,149,150,147,148,,111,113,,,112,,,,,',
+',,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132',
+',,,,,,,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119,430',
+'434,146,,431,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124,125',
+',,,,144,145,131,132,,,,,,268,,,,,,,136,135,,120,141,138,137,133,134',
+'128,126,118,140,119,443,434,146,,444,,,,,,,,,142,143,,139,121,122,123',
'130,127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141',
'138,137,133,134,128,126,118,140,119,443,434,146,,444,,,,,,,,,142,143',
-',139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,268',
-',,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119,741,440,146',
-',739,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144',
+',139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,',
+',,,136,135,,120,141,138,137,133,134,128,126,118,140,119,443,434,146',
+',444,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144',
'145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134,128,126,118',
-'140,119,735,440,146,,736,,,,,,,,,142,143,,139,121,122,123,130,127,129',
+'140,119,443,434,146,,444,,,,,,,,,142,143,,139,121,122,123,130,127,129',
',,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137,133',
-'134,128,126,118,140,119,733,434,146,,734,,,,,,,,,142,143,,139,121,122',
+'134,128,126,118,140,119,642,434,146,,643,,,,,,,,,142,143,,139,121,122',
'123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,268,,,,,,,136,135',
-',120,141,138,137,133,134,128,126,118,140,119,443,434,146,,444,,,,,,',
+',120,141,138,137,133,134,128,126,118,140,119,644,440,146,,645,,,,,,',
',,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132',
',,,,,,,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119,686',
'434,146,,687,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124,125',
@@ -823,8 +801,29 @@ clist = [
'130,127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141',
'138,137,133,134,128,126,118,140,119,443,434,146,,444,,,,,,,,,142,143',
',139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,',
-',,,136,135,,120,141,138,137,133,134,128,126,118,140,119,,,146' ]
- racc_action_table = arr = ::Array.new(25094, nil)
+',,,136,135,,120,141,138,137,133,134,128,126,118,140,119,642,434,146',
+',643,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144',
+'145,131,132,,,,,,268,,,,,,,136,135,,120,141,138,137,133,134,128,126',
+'118,140,119,644,440,146,,645,,,,,,,,,142,143,,139,121,122,123,130,127',
+'129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137',
+'133,134,128,126,118,140,119,733,434,146,,734,,,,,,,,,142,143,,139,121',
+'122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,,268,,,,,,,136',
+'135,,120,141,138,137,133,134,128,126,118,140,119,735,440,146,,736,,',
+',,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131',
+'132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119',
+'741,440,146,,739,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124',
+'125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138,137,133,134',
+'128,126,118,140,119,443,434,146,,444,,,,,,,,,142,143,,139,121,122,123',
+'130,127,129,,,124,125,,,,,144,145,131,132,,,,,,268,,,,,,,136,135,,120',
+'141,138,137,133,134,128,126,118,140,119,741,440,146,,892,,,,,,,,,142',
+'143,,139,121,122,123,130,127,129,,,124,125,,,,,144,145,131,132,,,,,',
+',,,,,,,136,135,,120,141,138,137,133,134,128,126,118,140,119,959,434',
+'146,,960,,,,,,,,,142,143,,139,121,122,123,130,127,129,,,124,125,,,,',
+'144,145,131,132,,,,,,268,,,,,,,136,135,,120,141,138,137,133,134,128',
+'126,118,140,119,961,440,146,,962,,,,,,,,,142,143,,139,121,122,123,130',
+'127,129,,,124,125,,,,,144,145,131,132,,,,,,,,,,,,,136,135,,120,141,138',
+'137,133,134,128,126,118,140,119,,,146' ]
+ racc_action_table = arr = ::Array.new(25031, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -834,892 +833,890 @@ clist = [
end
clist = [
-'58,58,58,392,58,967,735,839,58,58,693,746,746,58,71,58,58,58,58,58,58',
-'58,71,703,698,698,703,58,58,58,58,58,58,58,629,485,58,615,26,293,457',
-'457,453,58,587,354,58,58,347,58,58,58,58,58,55,58,58,58,681,58,58,734',
-'58,58,733,366,392,357,568,485,736,604,604,735,376,348,321,564,310,310',
-'698,376,838,807,629,58,889,352,58,352,896,58,453,696,58,681,457,924',
-'615,615,58,746,792,927,26,293,746,615,58,948,959,735,839,58,58,58,58',
-'58,58,967,960,967,58,58,967,26,293,369,369,369,58,369,934,58,934,369',
-'369,736,58,58,369,55,369,369,369,369,369,369,369,587,354,807,792,791',
-'369,369,369,369,369,369,369,604,347,369,347,697,734,347,310,733,369',
-'366,357,369,369,736,369,369,369,369,369,321,369,369,369,209,369,369',
-'807,348,366,348,949,949,348,366,838,807,838,838,889,838,889,791,896',
-'889,896,561,561,896,961,924,369,924,962,369,924,927,369,927,686,369',
-'927,948,959,948,959,690,948,959,290,699,3,291,960,209,960,3,577,960',
-'369,369,369,369,369,369,497,687,704,369,369,689,525,578,456,456,456',
-'369,456,287,369,387,456,456,387,369,369,456,508,456,456,456,456,456',
-'456,456,314,705,507,314,497,456,456,456,456,456,456,456,686,961,456',
-'42,42,962,690,690,14,456,290,42,456,456,508,456,456,456,456,456,708',
-'456,456,456,507,456,456,687,456,456,689,689,525,841,387,387,961,686',
-'961,287,962,961,962,710,690,962,686,290,211,14,577,456,577,690,456,577',
-'290,456,14,42,456,42,296,296,687,578,456,578,689,525,578,553,317,687',
-'456,317,287,689,525,456,456,456,456,456,456,287,712,430,456,456,713',
-'431,714,455,455,455,456,455,211,456,313,455,455,313,456,456,455,643',
-'455,455,455,455,455,455,455,717,361,83,83,292,455,455,455,455,455,455',
-'455,722,430,455,642,728,431,841,648,841,455,430,841,455,455,431,455',
-'455,455,455,455,377,455,455,455,394,455,455,377,455,455,643,648,648',
-'648,648,648,648,648,648,648,648,648,361,361,648,648,346,346,648,648',
-'361,455,379,642,455,361,110,455,730,379,455,110,110,648,295,648,455',
-'648,648,648,648,648,648,648,455,648,361,855,855,455,455,455,455,455',
-'455,394,394,394,455,455,732,648,540,454,454,454,455,454,361,455,361',
-'454,454,539,455,455,454,383,454,454,454,454,454,454,454,538,860,35,737',
-'852,454,454,454,454,454,454,454,860,385,454,852,370,300,389,371,628',
-'454,193,370,454,454,371,454,454,454,454,454,372,454,454,454,301,454',
-'454,372,454,454,351,35,741,860,860,351,852,852,742,462,35,383,383,383',
-'25,25,300,302,750,628,529,454,25,750,454,300,597,454,628,97,454,597',
-'385,385,385,373,454,389,389,389,860,462,373,852,454,462,462,925,925',
-'454,454,454,454,454,454,925,526,744,454,454,753,374,744,452,452,452',
-'454,452,374,454,375,452,452,757,454,454,452,375,452,452,452,452,452',
-'452,452,5,5,5,5,5,452,452,452,452,452,452,452,278,758,452,364,364,278',
-'925,760,925,452,761,364,452,452,762,452,452,452,452,452,452,452,452',
-'452,764,452,452,305,452,452,767,484,484,484,484,484,484,484,484,484',
-'484,484,355,355,484,484,720,720,484,484,355,452,37,37,452,15,15,452',
-'519,364,452,364,452,484,312,484,452,484,484,484,484,484,484,484,452',
-'484,774,739,739,452,452,452,452,452,452,739,78,77,452,452,739,484,484',
-'451,451,451,452,451,355,452,355,451,451,517,452,452,451,514,451,451',
-'451,451,451,451,451,680,680,680,680,680,451,451,451,451,451,451,451',
-'513,509,451,13,13,503,739,502,739,451,499,13,451,451,315,451,451,451',
-'451,451,451,451,451,451,316,451,451,795,451,451,796,784,784,784,784',
-'784,784,784,784,784,784,784,711,711,784,784,799,801,784,784,711,451',
-'804,805,451,806,318,451,811,13,451,13,451,784,41,784,451,784,784,784',
-'784,784,784,784,451,784,814,303,303,451,451,451,451,451,451,303,815',
-'466,451,451,465,784,830,442,442,442,451,442,711,451,711,442,442,833',
-'451,451,442,36,442,442,442,442,442,442,442,279,279,279,279,279,442,442',
-'442,442,442,442,442,464,463,442,208,208,326,303,327,303,442,843,208',
-'442,442,846,442,442,442,442,442,442,442,442,442,847,442,442,848,442',
-'442,329,779,779,779,779,779,779,779,779,779,779,779,288,288,779,779',
-'330,342,779,779,288,442,345,34,442,442,870,442,871,208,442,208,442,779',
-'442,779,442,779,779,779,779,779,779,779,442,779,437,589,589,442,442',
-'442,442,442,442,589,20,882,442,442,353,779,953,441,441,441,442,441,288',
-'442,288,441,441,892,442,442,441,893,441,441,441,441,441,441,441,955',
-'898,899,429,428,441,441,441,441,441,441,441,12,907,441,840,840,909,589',
-'912,589,441,461,840,441,441,913,441,441,441,441,441,441,441,441,441',
-'914,441,441,915,441,441,424,446,446,446,446,446,446,446,446,446,446',
-'446,461,11,446,446,461,461,446,446,10,441,956,422,441,441,926,441,958',
-'840,441,840,441,446,441,446,441,446,446,446,446,446,446,446,441,446',
-'9,6,936,441,441,441,441,441,441,824,416,944,441,441,356,446,410,440',
-'440,440,441,440,1,441,362,440,440,391,441,441,440,388,440,440,440,440',
-'440,440,440,555,358,632,637,267,440,440,440,440,440,440,440,640,255',
-'440,626,252,824,824,824,824,440,646,647,440,440,251,440,440,440,440',
-'440,440,440,440,440,619,440,440,280,440,440,655,480,657,219,213,555',
-'555,555,555,481,768,768,669,939,768,768,768,212,939,282,673,440,676',
-'210,440,440,283,440,284,939,440,580,440,480,440,683,440,480,480,480',
-'480,481,685,579,440,481,481,481,481,440,440,440,440,440,440,289,688',
-'573,440,440,939,939,939,939,691,692,440,858,,440,,,858,,440,440,0,0',
-'0,0,0,,,858,0,0,,,,0,,0,0,0,0,0,0,0,,939,,,,0,0,0,0,0,0,0,,,0,,858,858',
-'858,858,0,0,0,0,0,0,,0,0,0,0,0,,0,0,0,,0,0,,0,0,,773,773,773,773,773',
-'773,773,773,773,773,773,,858,773,773,,,773,773,,0,,,0,,,0,,,0,,0,773',
-',773,0,773,773,773,773,773,773,773,0,773,,,,0,0,0,0,0,0,,,,0,0,,773',
-',945,945,945,0,945,,0,,945,945,,0,0,945,,945,945,945,945,945,945,945',
-',,,,,945,945,945,945,945,945,945,,829,945,829,829,829,,829,,945,,,945',
-'945,,945,945,945,945,945,945,945,945,945,,945,945,,945,945,,19,19,19',
-'19,19,19,19,19,19,19,19,,,19,19,,,19,19,,945,,,945,,,945,,,945,,945',
-'19,,19,945,19,19,19,19,19,19,19,945,19,,,,945,945,945,945,945,945,,',
-',945,945,,19,,349,349,349,945,349,,945,,349,349,,945,945,349,,349,349',
-'349,349,349,349,349,,,,,,349,349,349,349,349,349,349,,569,349,569,569',
-'569,,569,,349,,,349,349,,349,349,349,349,349,,349,349,349,,349,349,',
-'349,349,,793,793,793,793,793,793,793,793,793,793,793,,,793,793,,,793',
-'793,,349,,,349,,,349,,,349,,,793,,793,349,793,793,793,793,793,793,793',
-'349,793,,,,349,349,349,349,349,349,,,,349,349,,793,,350,350,350,349',
-'350,,349,,350,350,,349,349,350,,350,350,350,350,350,350,350,,,,,,350',
-'350,350,350,350,350,350,,,350,,,,,,,350,,,350,350,,350,350,350,350,350',
-',350,350,350,,350,350,,350,350,,873,873,873,873,873,873,873,873,873',
-'873,873,,,873,873,,,873,873,,350,,,350,,,350,,,350,,,873,,873,350,873',
-'873,873,873,873,873,873,350,873,,,,350,350,350,350,350,350,,,,350,350',
-',873,,432,432,432,350,432,,350,,432,432,,350,350,432,,432,432,432,432',
-'432,432,432,,,,,,432,432,432,432,432,432,432,,,432,,,,,,,432,,,432,432',
-',432,432,432,432,432,432,432,432,432,,432,432,,432,432,,536,536,536',
-'536,536,536,536,536,536,536,536,,,536,536,,,536,536,,432,,,432,432,',
-'432,,,432,,432,536,432,536,432,536,536,536,536,536,536,536,432,536,',
-',,432,432,432,432,432,432,,,,432,432,,536,,421,421,421,432,421,,432',
-',421,421,,432,432,421,,421,421,421,421,421,421,421,,,,,,421,421,421',
-'421,421,421,421,,,421,,,,,419,,421,,,421,421,,421,421,421,421,421,,421',
-'421,421,,421,421,,421,421,,419,419,419,419,419,419,419,419,419,419,419',
-',,419,419,,,419,419,,421,,,421,,,421,,,421,,,419,,419,421,419,419,419',
-'419,419,419,419,421,419,,,,421,421,421,421,421,421,,,,421,421,,419,',
-'419,,,421,,,421,,,,,421,421,943,943,943,943,943,,,,943,943,,,,943,,943',
-'943,943,943,943,943,943,,,,,,943,943,943,943,943,943,943,,,943,,,,,',
-'943,943,,943,943,943,,943,943,943,943,943,,943,943,943,,943,943,,943',
-'943,,672,672,672,672,672,672,672,672,672,672,672,,,672,672,,,672,672',
-',943,,,943,,,943,,,943,,943,672,,672,943,672,672,672,672,672,672,672',
-'943,672,,,,943,943,943,943,943,943,,,,943,943,,672,,672,,,943,,,943',
-',,,,943,943,935,935,935,935,935,,,,935,935,,,,935,,935,935,935,935,935',
-'935,935,,,,,,935,935,935,935,935,935,935,,,935,,,,,,935,935,,935,935',
-'935,,935,935,935,935,935,,935,935,935,,935,935,,935,935,,427,427,427',
-'427,427,427,427,427,427,427,427,,,427,427,,,427,427,,935,,,935,,,935',
-',,935,,935,427,,427,935,427,427,427,427,427,427,427,935,427,,,,935,935',
-'935,935,935,935,,,,935,935,,427,,,,,935,,,935,,,,,935,935,930,930,930',
-'930,930,,,,930,930,,,,930,,930,930,930,930,930,930,930,,,,,,930,930',
-'930,930,930,930,930,,,930,,,,,,930,930,,930,930,930,,930,930,930,930',
-'930,,930,930,930,,930,930,,930,930,,875,875,875,875,875,875,875,875',
-'875,875,875,,,875,875,,,875,875,,930,,,930,,,930,,,930,,930,875,,875',
-'930,875,875,875,875,875,875,875,930,875,,,,930,930,930,930,930,930,',
-',,930,930,,875,,,,,930,,,930,,,,,930,930,923,923,923,923,923,,,,923',
-'923,,,,923,,923,923,923,923,923,923,923,,,,,,923,923,923,923,923,923',
-'923,,,923,,,,,,923,923,,923,923,923,,923,923,923,923,923,,923,923,923',
-',923,923,,923,923,,695,695,695,695,695,695,695,695,695,695,695,,,695',
-'695,,,695,695,,923,,,923,,,923,,,923,,923,695,,695,923,695,695,695,695',
-'695,695,695,923,695,,,,923,923,923,923,923,923,,,,923,923,,695,,921',
-'921,921,923,921,,923,,921,921,,923,923,921,,921,921,921,921,921,921',
-'921,,,,,,921,921,921,921,921,921,921,,,921,,,,,,,921,,,921,921,,921',
-'921,921,921,921,,921,921,921,,921,921,,921,921,,249,249,249,249,249',
-'249,249,249,249,249,249,,,249,249,,,249,249,,921,,,921,,,921,,,921,',
-'921,249,921,249,921,249,249,249,249,249,249,249,921,249,,,,921,921,921',
-'921,921,921,,,,921,921,,249,,,,,921,,,921,,,,,921,921,904,904,904,904',
-'904,,,,904,904,,,,904,,904,904,904,904,904,904,904,,,,,,904,904,904',
-'904,904,904,904,,,904,,,,,,904,904,,904,904,904,,904,904,904,904,904',
-',904,904,904,,904,904,,904,904,,786,786,786,786,786,786,786,786,786',
-'786,786,,,786,786,,,786,786,,904,,,904,,,904,,,904,,904,786,,786,904',
-'786,786,786,786,786,786,786,904,786,,,,904,904,904,904,904,904,,,,904',
-'904,,786,,,,,904,,,904,,,,,904,904,901,901,901,901,901,,,,901,901,,',
-',901,,901,901,901,901,901,901,901,,,,,,901,901,901,901,901,901,901,',
-',901,,,,,,901,901,,901,901,901,,901,901,901,901,901,,901,901,901,,901',
-'901,,901,901,,781,781,781,781,781,781,781,781,781,781,781,,,781,781',
-',,781,781,,901,,,901,,,901,,,901,,901,781,,781,901,781,781,781,781,781',
-'781,781,901,781,,,,901,901,901,901,901,901,,,,901,901,,781,,900,900',
-'900,901,900,,901,,900,900,,901,901,900,,900,900,900,900,900,900,900',
-',,,,,900,900,900,900,900,900,900,,718,900,718,718,718,,718,,900,,,900',
-'900,,900,900,900,900,900,,900,900,900,,900,900,,900,900,338,,338,338',
-'338,,338,,,566,718,566,566,566,,566,,,718,,,900,,,900,,,900,,,900,,900',
-',,,900,,,338,,,,,900,,,338,566,900,900,900,900,900,900,,566,,900,900',
-',,,890,890,890,900,890,,900,,890,890,,900,900,890,,890,890,890,890,890',
-'890,890,,,,,,890,890,890,890,890,890,890,,,890,,,,,,,890,,,890,890,',
-'890,890,890,890,890,,890,890,890,,890,890,652,,652,652,652,469,652,',
-',,,,,,,,,,,,,,469,469,890,,,890,,,890,,,890,,,,469,,652,,469,469,469',
-'469,,,652,652,652,652,,890,890,890,890,890,890,652,,,890,890,,,,17,17',
-'17,890,17,,890,,17,17,,890,890,17,,17,17,17,17,17,17,17,,,,,,17,17,17',
-'17,17,17,17,,,17,,,,,,,17,,,17,17,,17,17,17,17,17,,17,17,17,,17,17,',
-'17,17,,479,479,479,479,479,479,479,,,479,479,,,,,,,479,479,,17,,,17',
-'17,,17,,,17,,,479,,479,17,479,479,479,479,479,479,479,17,479,,,,17,17',
-'17,17,17,17,,,,17,17,,,,18,18,18,17,18,,17,,18,18,,17,17,18,,18,18,18',
-'18,18,18,18,,,,,,18,18,18,18,18,18,18,,,18,,,,,,,18,,,18,18,,18,18,18',
-'18,18,,18,18,18,,18,18,,18,18,,478,478,478,478,478,478,478,,,478,478',
-',,,,,,478,478,,18,,,18,,,18,,,18,,,478,,478,18,478,478,478,478,478,478',
-'478,18,478,,,,18,18,18,18,18,18,,,,18,18,,,,,,,18,,,18,,,,,18,18,886',
-'886,886,886,886,,,,886,886,,,,886,,886,886,886,886,886,886,886,,,,,',
-'886,886,886,886,886,886,886,,,886,,,,,,886,886,,886,886,886,,886,886',
-'886,886,886,,886,886,886,,886,886,,886,886,,477,477,477,477,477,477',
-'477,,,477,477,,,,,,,477,477,,886,,,886,,,886,,,886,,886,477,,477,886',
-'477,477,477,477,477,477,477,886,477,,,,886,886,886,886,886,886,,,,886',
-'886,,,,881,881,881,886,881,,886,,881,881,,886,886,881,,881,881,881,881',
-'881,881,881,,,,,,881,881,881,881,881,881,881,,,881,,,,,,,881,,,881,881',
-',881,881,881,881,881,881,881,881,881,,881,881,,881,881,,476,476,476',
-'476,476,476,476,,,476,476,,,,,,,476,476,,881,,,881,,,881,,,881,,,476',
-'881,476,881,476,476,476,476,476,476,476,881,476,,,,881,881,881,881,881',
-'881,,,,881,881,,,,22,22,22,881,22,,881,,22,22,,881,881,22,,22,22,22',
-'22,22,22,22,,,,,,22,22,22,22,22,22,22,,,22,,,,,,,22,,,22,22,,22,22,22',
-'22,22,22,22,22,22,,22,22,,22,22,,475,475,475,475,475,475,475,,,475,475',
-',,,,,,475,475,,22,,,22,,,22,,,22,,22,475,22,475,22,475,475,475,475,475',
-'475,475,22,475,,,,22,22,22,22,22,22,,,,22,22,,,,23,23,23,22,23,,22,',
-'23,23,,22,22,23,,23,23,23,23,23,23,23,,,,,,23,23,23,23,23,23,23,,,23',
-',,,,,,23,,,23,23,,23,23,23,23,23,23,23,23,23,,23,23,,23,23,,474,,,,',
-',,,,,,,,,,,,474,474,,23,,,23,,,23,,,23,,23,474,23,474,23,474,474,474',
-'474,,,474,23,474,,,,23,23,23,23,23,23,,,,23,23,,,,24,24,24,23,24,,23',
-',24,24,,23,23,24,,24,24,24,24,24,24,24,,,,,,24,24,24,24,24,24,24,,,24',
-',,,,,,24,,,24,24,,24,24,24,24,24,24,24,24,24,,24,24,,24,24,,473,,,,',
-',,,,,,,,,,,,473,473,,24,,,24,,,24,,,24,,24,473,24,473,24,473,473,473',
-'473,,,473,24,473,,,,24,24,24,24,24,24,,,,24,24,,,,877,877,877,24,877',
-',24,,877,877,,24,24,877,,877,877,877,877,877,877,877,,,,,,877,877,877',
-'877,877,877,877,,,877,,,,,,,877,,,877,877,,877,877,877,877,877,,877',
-'877,877,,877,877,,877,877,,471,,,,,,,,,,,,,,,,,471,471,,877,,,877,,',
-'877,,,877,,,471,,471,877,471,471,471,471,,,471,877,471,,,,877,877,877',
-'877,877,877,,,,877,877,,,,876,876,876,877,876,,877,,876,876,,877,877',
-'876,,876,876,876,876,876,876,876,,,,,,876,876,876,876,876,876,876,,',
-'876,,,,,,,876,,,876,876,,876,876,876,876,876,,876,876,876,,876,876,',
-'876,876,,483,483,483,483,483,483,483,483,,483,483,,,,,,,483,483,,876',
-',,876,,,876,,,876,,,483,,483,876,483,483,483,483,483,483,483,876,483',
-',,,876,876,876,876,876,876,,,,876,876,,,,27,27,27,876,27,,876,,27,27',
-',876,876,27,,27,27,27,27,27,27,27,,,,,,27,27,27,27,27,27,27,,,27,,,',
-',,,27,,,27,27,,27,27,27,27,27,27,27,27,27,,27,27,,27,27,,482,482,482',
-'482,482,482,482,,,482,482,,,,,,,482,482,,27,,,27,27,,27,,,27,,27,482',
-'27,482,27,482,482,482,482,482,482,482,27,482,,,,27,27,27,27,27,27,,',
-',27,27,,,,,,,27,,,27,,,,,27,27,30,30,30,30,30,,,,30,30,,,,30,,30,30',
-'30,30,30,30,30,,,,,,30,30,30,30,30,30,30,,,30,,,,,,30,30,,30,30,30,',
-'30,30,30,30,30,,30,30,30,,30,30,,30,30,,472,,,,,,,,,,,,,,,,,472,472',
-',30,,,30,,,30,,,30,,30,472,,472,30,472,472,472,472,,,472,30,472,,,,30',
-'30,30,30,30,30,,,,30,30,,,,31,31,31,30,31,,30,,31,31,,30,30,31,,31,31',
-'31,31,31,31,31,,,,,,31,31,31,31,31,31,31,,,31,,,,,,,31,,,31,31,,31,31',
-'31,31,31,,31,31,31,,31,31,322,,322,322,322,,322,,,,,,,,,,,,,,,,,,31',
-',,31,,,31,,,31,,31,,,,322,,322,,,,,,322,322,322,322,,31,31,31,31,31',
-'31,,,,31,31,,,,32,32,32,31,32,,31,,32,32,,31,31,32,,32,32,32,32,32,32',
-'32,,,,,,32,32,32,32,32,32,32,,,32,,,,,,,32,,,32,32,,32,32,32,32,32,',
-'32,32,32,,32,32,749,,749,749,749,749,749,,,,,,,,,,749,,,,,,,,32,,,32',
-',,32,,,32,,,,,,749,,,,,,,,749,749,749,749,,32,32,32,32,32,32,,,,32,32',
-',,,32,,,32,,,32,,,,,32,32,862,862,862,,862,,,749,862,862,,,,862,,862',
-'862,862,862,862,862,862,,,,,,862,862,862,862,862,862,862,,,862,,,,,',
-',862,,,862,862,,862,862,862,862,862,,862,862,862,,862,862,,862,862,',
-'470,470,470,470,470,470,470,,,470,470,,,,,,,470,470,,862,,,862,,,862',
-',,862,,,470,,470,862,470,470,470,470,470,470,470,862,470,,,,862,862',
-'862,862,862,862,,,,862,862,,,,,,,862,,,862,,,,,862,862,835,835,835,835',
-'835,,,,835,835,,,,835,,835,835,835,835,835,835,835,,,,,,835,835,835',
-'835,835,835,835,,,835,,,,,,835,835,,835,835,835,,835,835,835,835,835',
-',835,835,835,,835,835,,835,835,,460,460,460,460,460,460,460,460,460',
-'460,460,,,460,460,,,460,460,,835,,,835,,,835,,,835,,835,460,,460,835',
-'460,460,460,460,460,460,460,835,460,,,,835,835,835,835,835,835,,,,835',
-'835,,,,,,,835,,,835,,,,,835,835,834,834,834,834,834,,,,834,834,,,,834',
-',834,834,834,834,834,834,834,,,,,,834,834,834,834,834,834,834,,,834',
-',,,,,834,834,,834,834,834,,834,834,834,834,834,,834,834,834,,834,834',
-',834,834,,459,459,459,459,459,459,459,459,459,459,459,,,459,459,,,459',
-'459,,834,,,834,,,834,,,834,,834,459,,459,834,459,459,459,459,459,459',
-'459,834,459,,,,834,834,834,834,834,834,,,,834,834,,,,832,832,832,834',
-'832,,834,,832,832,,834,834,832,,832,832,832,832,832,832,832,,,,,,832',
-'832,832,832,832,832,832,,,832,,,,,,,832,,,832,832,,832,832,832,832,832',
-',832,832,832,,832,832,,832,832,,468,,,,,,,,,,,,,,,,,468,468,,832,,,832',
-',,832,,,832,,,468,,468,832,468,468,468,468,,,,832,,,,,832,832,832,832',
-'832,832,,,,832,832,,,,38,38,38,832,38,,832,,38,38,,832,832,38,,38,38',
-'38,38,38,38,38,,,,,,38,38,38,38,38,38,38,,,38,,,,,,,38,,,38,38,,38,38',
-'38,38,38,,38,38,38,,38,38,,38,38,,467,,,,,,,,,,,,,,,,,467,467,,38,,',
-'38,,,38,,,38,,,467,,467,38,467,467,467,467,,,,38,,,,,38,38,38,38,38',
-'38,,,,38,38,,,,39,39,39,38,39,,38,,39,39,,38,38,39,,39,39,39,39,39,39',
-'39,,,,,,39,39,39,39,39,39,39,,,39,,,,,,,39,,,39,39,,39,39,39,39,39,',
-'39,39,39,,39,39,,39,39,,,,,,,,,,,,,,,,,,,,,,39,,,39,,,39,,,39,,,,,,39',
-',,,,,,,39,,,,,39,39,39,39,39,39,,,,39,39,,,,40,40,40,39,40,,39,,40,40',
-',39,39,40,,40,40,40,40,40,40,40,,,,,,40,40,40,40,40,40,40,,,40,,,,,',
-',40,,,40,40,,40,40,40,40,40,,40,40,40,,40,40,,40,40,,,,,,,,,,,,,,,,',
-',,,,,40,,,40,,,40,,,40,,,,,,40,,,,,,,,40,,,,,40,40,40,40,40,40,,,,40',
-'40,,,,,,,40,,,40,,,,,40,40,813,813,813,813,813,,,,813,813,,,,813,,813',
-'813,813,813,813,813,813,,,,,,813,813,813,813,813,813,813,,,813,,,,,',
-'813,813,,813,813,813,,813,813,813,813,813,,813,813,813,,813,813,,813',
-'813,,,,,,,,,,,,,,,,,,,,,,813,,,813,,,813,,,813,,813,,,,813,,,,,,,,813',
-',,,,813,813,813,813,813,813,,,,813,813,,,,802,802,802,813,802,,813,',
-'802,802,,813,813,802,,802,802,802,802,802,802,802,,,,,,802,802,802,802',
-'802,802,802,,,802,,,,,,,802,,,802,802,,802,802,802,802,802,,802,802',
-'802,,802,802,,802,802,,,,,,,,,,,,,,,,,,,,,,802,,,802,,,802,,,802,,802',
-',,,802,,,,,,,,802,,,,,802,802,802,802,802,802,,,,802,802,,,,52,52,52',
-'802,52,,802,,52,52,,802,802,52,,52,52,52,52,52,52,52,,,,,,52,52,52,52',
-'52,52,52,,,52,,,,,,,52,,,52,52,,52,52,52,52,52,,52,52,52,,52,52,,52',
-'52,,,,,,,,,,,,,,,,,,,,,,52,,,52,,,52,,,52,,,,,,52,,,,,,,,52,,,,,52,52',
-'52,52,52,52,,,,52,52,,,,53,53,53,52,53,,52,,53,53,,52,52,53,,53,53,53',
-'53,53,53,53,,,,,,53,53,53,53,53,53,53,,,53,,,,,,,53,,,53,53,,53,53,53',
-'53,53,53,53,53,53,,53,53,,53,53,,,,,,,,,,,,,,,,,,,,,,53,,,53,,,53,,',
-'53,,53,,,,53,,,,,,,,53,,,,,53,53,53,53,53,53,,,,53,53,,,,54,54,54,53',
-'54,,53,,54,54,,53,53,54,,54,54,54,54,54,54,54,,,,,,54,54,54,54,54,54',
-'54,,,54,,,,,,,54,,,54,54,,54,54,54,54,54,54,54,54,54,,54,54,,54,54,',
-',,,,,,,,,,,,,,,,,,,,54,,,54,,,54,,,54,,,,,,54,,,,,,,,54,,,,,54,54,54',
-'54,54,54,,,,54,54,,,,790,790,790,54,790,,54,,790,790,,54,54,790,,790',
-'790,790,790,790,790,790,,,,,,790,790,790,790,790,790,790,,,790,,,,,',
-',790,,,790,790,,790,790,790,790,790,,790,790,790,,790,790,,790,790,',
-',,,,,,,,,,,,,,,,,,,,790,,,790,,,790,,,790,,,,,,790,,,,,,,,790,,,,,790',
-'790,790,790,790,790,,,,790,790,,,,789,789,789,790,789,,790,,789,789',
-',790,790,789,,789,789,789,789,789,789,789,,,,,,789,789,789,789,789,789',
-'789,,,789,,,,,,,789,,,789,789,,789,789,789,789,789,,789,789,789,,789',
-'789,,789,789,,,,,,,,,,,,,,,,,,,,,,789,,,789,,,789,,,789,,,,,,789,,,',
-',,,,789,,,,,789,789,789,789,789,789,,,,789,789,,,,57,57,57,789,57,,789',
-',57,57,,789,789,57,,57,57,57,57,57,57,57,,,,,,57,57,57,57,57,57,57,',
-',57,,,,,,,57,,,57,57,,57,57,57,57,57,,57,57,57,,57,57,,57,57,,,,,,,',
-',,,,,,,,,,,,,,57,,,57,,,57,,,57,,,,,,57,,,,,,,,57,,,,,57,57,57,57,57',
-'57,,,,57,57,,,,381,381,381,57,381,,57,,381,381,,57,57,381,,381,381,381',
-'381,381,381,381,,,,,,381,381,381,381,381,381,381,,,381,,,,,,,381,,,381',
-'381,,381,381,381,381,381,,381,381,381,,381,381,,381,381,,,,,,,,,,,,',
-',,,,,,,,,381,,,381,,,381,,,381,,,,,,381,,,,,,,,381,,,,,381,381,381,381',
-'381,381,,,,381,381,,,,61,61,61,381,61,,381,,61,61,,381,381,61,,61,61',
-'61,61,61,61,61,,,,,,61,61,61,61,61,61,61,,,61,,,,,,,61,,,61,61,,61,61',
-'61,61,61,,61,61,61,,61,61,,61,61,,,,,,,,,,,,,,,,,,,,,,61,,,61,,,61,',
-',61,,,,,,61,,,,,,,,61,,,,,61,61,61,61,61,61,,,,61,61,61,,,,,61,61,,',
-'61,,,,,61,61,62,62,62,,62,,,,62,62,,,,62,,62,62,62,62,62,62,62,,,,,',
-'62,62,62,62,62,62,62,,,62,,,,,,,62,,,62,62,,62,62,62,62,62,,62,62,62',
-',62,62,56,,56,56,56,,56,,,,,,,,,,,,,,,,,,62,,,62,,,62,,,62,,62,,,,56',
-'56,,,,,,,56,56,56,56,,62,62,62,62,62,62,,,,62,62,,,,63,63,63,62,63,',
-'62,,63,63,,62,62,63,,63,63,63,63,63,63,63,,,,,,63,63,63,63,63,63,63',
-',,63,,,,,,,63,,,63,63,,63,63,63,63,63,,63,63,63,,63,63,559,,559,559',
-'559,,559,,,,,,,,,,,,,,,63,,,63,,,63,,,63,,,63,,,,,,559,,,,,,,,559,559',
-'559,559,,63,63,63,63,63,63,,,,63,63,,,,788,788,788,63,788,,63,,788,788',
-',63,63,788,,788,788,788,788,788,788,788,,,,,,788,788,788,788,788,788',
-'788,,,788,,,,,,,788,,,788,788,,788,788,788,788,788,,788,788,788,,788',
-'788,,788,788,,,,,,,,,,,,,,,,,,,,,,788,,,788,,,788,,,788,,,,,,788,,,',
-',,,,788,,,,,788,788,788,788,788,788,,,,788,788,,,,777,777,777,788,777',
-',788,,777,777,,788,788,777,,777,777,777,777,777,777,777,,,,,,777,777',
-'777,777,777,777,777,,,777,,,,,,,777,,,777,777,,777,777,777,777,777,',
-'777,777,777,,777,777,,777,777,,,,,,,,,,,,,,,,,,,,,,777,,,777,,,777,',
-',777,,,,,,777,,,,,,,,777,,,,,777,777,777,777,777,777,,,,777,777,,,,776',
-'776,776,777,776,,777,,776,776,,777,777,776,,776,776,776,776,776,776',
-'776,,,,,,776,776,776,776,776,776,776,,,776,,,,,,,776,,,776,776,,776',
-'776,776,776,776,,776,776,776,,776,776,,776,776,,,,,,,,,,,,,,,,,,,,,',
-'776,,,776,,,776,,,776,,,,,,776,,,,,,,,776,,,,,776,776,776,776,776,776',
-',,,776,776,,,,775,775,775,776,775,,776,,775,775,,776,776,775,,775,775',
-'775,775,775,775,775,,,,,,775,775,775,775,775,775,775,,,775,,,,,,,775',
-',,775,775,,775,775,775,775,775,,775,775,775,,775,775,,775,775,,,,,,',
-',,,,,,,,,,,,,,,775,,,775,,,775,,,775,,,,,,775,,,,,,,,775,,,,,775,775',
-'775,775,775,775,,,,775,775,,,,,,,775,,,775,,,,,775,775,769,769,769,769',
-'769,,,,769,769,,,,769,,769,769,769,769,769,769,769,,,,,,769,769,769',
-'769,769,769,769,,,769,,,,,,769,769,,769,769,769,,769,769,769,769,769',
-',769,769,769,,769,769,,769,769,,,,,,,,,,,,,,,,,,,,,,769,,,769,,,769',
-',,769,,769,,,,769,,,,,,,,769,,,,,769,769,769,769,769,769,,,,769,769',
-',,,755,755,755,769,755,,769,,755,755,,769,769,755,,755,755,755,755,755',
-'755,755,,,,,,755,755,755,755,755,755,755,,,755,,,,,,,755,,,755,755,',
-'755,755,755,755,755,,755,755,755,,755,755,,755,755,,,,,,,,,,,,,,,,,',
-',,,,755,,,755,,,755,,,755,,,,,,755,,,,,,,,755,,,,,755,755,755,755,755',
-'755,,,,755,755,,,,84,84,84,755,84,,755,,84,84,,755,755,84,,84,84,84',
-'84,84,84,84,,84,,,,84,84,84,84,84,84,84,,,84,,,,,,,84,,,84,84,,84,84',
-'84,84,84,84,84,84,84,,84,84,,84,84,,,,,,,,,,,,,,,,,,,,,,84,,,84,84,',
-'84,,,84,,84,,84,,84,,,,,,,,84,,84,,,84,84,84,84,84,84,,,,84,84,,,,87',
-'87,87,84,87,,84,,87,87,,84,84,87,,87,87,87,87,87,87,87,,87,,,,87,87',
-'87,87,87,87,87,,,87,,,,,,,87,,,87,87,,87,87,87,87,87,87,87,87,87,,87',
-'87,,87,87,,,,,,,,,,,,,,,,,,,,,,87,,,87,87,,87,,,87,,87,,87,,87,,,,,',
-',,87,,87,,,87,87,87,87,87,87,,,,87,87,,,,,,,87,,,87,,,,,87,87,748,748',
-'748,748,748,,,,748,748,,,,748,,748,748,748,748,748,748,748,,,,,,748',
-'748,748,748,748,748,748,,,748,,,,,,748,748,,748,748,748,,748,748,748',
-'748,748,,748,748,748,,748,748,,748,748,,,,,,,,,,,,,,,,,,,,,,748,,,748',
-',,748,,,748,,748,,,,748,,,,,,,,748,,,,,748,748,748,748,748,748,,,,748',
-'748,,,,,,,748,,,748,,,,,748,748,99,99,99,99,99,,,,99,99,,,,99,,99,99',
-'99,99,99,99,99,,,,,,99,99,99,99,99,99,99,,,99,,,,,,99,99,99,99,99,99',
-',99,99,99,99,99,,99,99,99,,99,99,,99,99,,,,,,,,,,,,,,,,,,,,,,99,,,99',
-',,99,,,99,,99,,,,99,,,,,,,,99,,,,,99,99,99,99,99,99,,,,99,99,,,,,,99',
+'0,0,0,0,0,347,321,354,0,0,392,746,746,0,71,0,0,0,0,0,0,0,71,313,852',
+'615,313,0,0,0,0,0,0,0,1,852,0,387,26,209,387,485,0,0,0,0,0,0,348,0,0',
+'0,0,0,55,0,0,0,497,0,0,357,0,0,587,681,366,370,852,852,733,310,310,392',
+'370,485,734,352,838,352,839,604,604,735,889,0,615,615,0,209,896,0,497',
+'6,0,615,0,287,387,387,0,746,681,924,26,852,746,9,0,927,948,321,354,0',
+'0,0,0,0,0,347,959,347,0,0,347,26,736,17,17,17,0,17,960,0,507,17,17,10',
+'0,0,17,55,17,17,17,17,17,17,17,211,735,457,457,11,17,17,17,17,17,17',
+'17,310,348,17,348,287,357,348,507,587,17,604,366,17,17,733,17,17,17',
+'17,17,734,17,17,17,839,17,17,735,17,17,366,838,736,838,838,366,838,889',
+'211,889,371,287,889,896,12,896,457,371,896,961,287,17,20,962,17,17,924',
+'17,924,290,17,924,927,948,927,948,17,927,948,967,736,293,383,959,17',
+'959,34,577,959,17,17,17,17,17,17,960,525,960,17,17,960,686,578,18,18',
+'18,17,18,687,17,314,18,18,314,17,17,18,453,18,18,18,18,18,18,18,698',
+'698,508,15,15,18,18,18,18,18,18,18,290,961,18,629,36,962,383,383,383',
+'18,293,461,18,18,41,18,18,18,18,18,77,18,18,18,508,18,18,525,18,18,453',
+'293,686,841,37,37,961,290,961,687,962,961,962,461,698,962,290,461,461',
+'689,577,18,577,629,18,577,967,18,967,807,18,967,78,690,525,578,18,578',
+'642,686,578,97,3,525,18,193,687,3,686,18,18,18,18,18,18,687,210,278',
+'18,18,212,14,278,22,22,22,18,22,385,18,317,22,22,317,18,18,22,643,22',
+'22,22,22,22,22,22,791,689,689,642,792,22,22,22,22,22,22,22,807,213,22',
+'690,690,14,841,389,841,22,394,841,22,22,14,22,22,22,22,22,22,22,22,22',
+'372,22,22,689,22,22,643,372,385,385,385,351,689,807,791,219,351,690',
+'792,251,25,25,807,860,373,374,690,22,25,252,22,373,374,22,860,934,22',
+'934,22,255,22,267,22,280,389,389,389,394,394,394,22,83,83,13,13,22,22',
+'22,22,22,22,13,282,703,22,22,703,860,860,23,23,23,22,23,597,22,375,23',
+'23,597,22,22,23,375,23,23,23,23,23,23,23,283,361,296,296,284,23,23,23',
+'23,23,23,23,744,860,23,42,42,744,13,648,13,23,289,42,23,23,291,23,23',
+'23,23,23,23,23,23,23,292,23,23,295,23,23,301,648,648,648,648,648,648',
+'648,648,648,648,648,361,361,648,648,376,750,648,648,361,23,750,376,23',
+'361,302,23,305,42,23,42,23,648,23,648,23,648,648,648,648,648,648,648',
+'23,648,361,208,208,23,23,23,23,23,23,208,312,35,23,23,315,648,316,24',
+'24,24,23,24,361,23,361,24,24,318,23,23,24,326,24,24,24,24,24,24,24,5',
+'5,5,5,5,24,24,24,24,24,24,24,377,35,24,288,288,300,208,377,208,24,35',
+'288,24,24,327,24,24,24,24,24,24,24,24,24,329,24,24,330,24,24,342,484',
+'484,484,484,484,484,484,484,484,484,484,303,303,484,484,300,110,484',
+'484,303,24,110,110,24,300,345,24,353,288,24,288,24,484,24,484,24,484',
+'484,484,484,484,484,484,24,484,356,355,355,24,24,24,24,24,24,355,358',
+'430,24,24,362,484,484,27,27,27,24,27,303,24,303,27,27,388,24,24,27,391',
+'27,27,27,27,27,27,27,279,279,279,279,279,27,27,27,27,27,27,27,410,430',
+'27,364,364,416,355,419,355,27,430,364,27,27,422,27,27,27,27,27,27,27',
+'27,27,424,27,27,428,27,27,429,419,419,419,419,419,419,419,419,419,419',
+'419,589,589,419,419,346,346,419,419,589,27,437,431,27,27,463,27,464',
+'364,27,364,27,419,27,419,27,419,419,419,419,419,419,419,27,419,561,561',
+'379,27,27,27,27,27,27,379,720,720,27,27,628,419,465,419,431,466,27,858',
+'589,27,589,499,858,431,27,27,30,30,30,30,30,855,855,858,30,30,949,949',
+'502,30,503,30,30,30,30,30,30,30,509,513,514,628,517,30,30,30,30,30,30',
+'30,628,519,30,526,858,858,858,858,30,30,462,30,30,30,529,30,30,30,30',
+'30,538,30,30,30,539,30,30,540,30,30,553,19,19,19,19,19,19,19,19,19,19',
+'19,462,858,19,19,462,462,19,19,564,30,568,573,30,579,580,30,619,626',
+'30,632,30,19,637,19,30,19,19,19,19,19,19,19,30,19,640,711,711,30,30',
+'30,30,30,30,711,646,647,30,30,655,19,657,31,31,31,30,31,669,30,673,31',
+'31,676,30,30,31,683,31,31,31,31,31,31,31,555,685,688,691,692,31,31,31',
+'31,31,31,31,693,696,31,840,840,697,711,699,711,31,704,840,31,31,705',
+'31,31,31,31,31,708,31,31,31,710,31,31,712,652,713,652,652,652,714,652',
+'555,555,555,555,717,768,768,739,739,768,768,768,722,728,730,739,31,732',
+'737,31,739,741,31,742,840,31,840,31,753,757,758,760,652,761,939,762',
+'764,767,774,939,652,652,652,652,31,31,31,31,31,31,939,652,795,31,31',
+'796,799,801,32,32,32,31,32,739,31,739,32,32,804,31,31,32,805,32,32,32',
+'32,32,32,32,824,939,939,939,939,32,32,32,32,32,32,32,925,925,32,680',
+'680,680,680,680,925,32,480,806,32,32,811,32,32,32,32,32,814,32,32,32',
+'815,32,32,600,939,600,600,600,600,600,830,824,824,824,824,833,843,846',
+'480,600,847,848,480,480,480,480,870,32,871,882,32,892,925,32,925,569',
+'32,569,569,569,893,569,600,600,898,899,907,909,912,913,600,600,600,600',
+'914,32,32,32,32,32,32,915,926,936,32,32,944,953,955,32,956,958,32,,',
+'32,,,,,32,32,38,38,38,481,38,,,600,38,38,,,,38,,38,38,38,38,38,38,38',
+',,,,,38,38,38,38,38,38,38,,481,38,,,481,481,481,481,38,,,38,38,,38,38',
+'38,38,38,,38,38,38,,38,38,,38,38,,249,249,249,249,249,249,249,249,249',
+'249,249,,,249,249,,,249,249,,38,,,38,,,38,,,38,,,249,,249,38,249,249',
+'249,249,249,249,249,38,249,,,,38,38,38,38,38,38,,,,38,38,,249,,39,39',
+'39,38,39,,38,,39,39,,38,38,39,,39,39,39,39,39,39,39,,,,,,39,39,39,39',
+'39,39,39,,829,39,829,829,829,,829,,39,,,39,39,,39,39,39,39,39,,39,39',
+'39,,39,39,,39,39,,427,427,427,427,427,427,427,427,427,427,427,,,427',
+'427,,,427,427,,39,,,39,,,39,,,39,,,427,,427,39,427,427,427,427,427,427',
+'427,39,427,,,,39,39,39,39,39,39,,,,39,39,,427,,40,40,40,39,40,,39,,40',
+'40,,39,39,40,,40,40,40,40,40,40,40,,,,,,40,40,40,40,40,40,40,,,40,,',
+',,,,40,,,40,40,,40,40,40,40,40,,40,40,40,,40,40,,40,40,,446,446,446',
+'446,446,446,446,446,446,446,446,,,446,446,,,446,446,,40,,,40,,,40,,',
+'40,,,446,,446,40,446,446,446,446,446,446,446,40,446,,,,40,40,40,40,40',
+'40,,,,40,40,,446,,52,52,52,40,52,,40,,52,52,,40,40,52,,52,52,52,52,52',
+'52,52,,,,,,52,52,52,52,52,52,52,,,52,,,,,,,52,,,52,52,,52,52,52,52,52',
+',52,52,52,,52,52,,52,52,,536,536,536,536,536,536,536,536,536,536,536',
+',,536,536,,,536,536,,52,,,52,,,52,,,52,,,536,,536,52,536,536,536,536',
+'536,536,536,52,536,,,,52,52,52,52,52,52,,,,52,52,,536,,53,53,53,52,53',
+',52,,53,53,,52,52,53,,53,53,53,53,53,53,53,,,,,,53,53,53,53,53,53,53',
+',,53,,,,,,,53,,,53,53,,53,53,53,53,53,53,53,53,53,,53,53,,53,53,,695',
+'695,695,695,695,695,695,695,695,695,695,,,695,695,,,695,695,,53,,,53',
+',,53,,,53,,53,695,,695,53,695,695,695,695,695,695,695,53,695,,,,53,53',
+'53,53,53,53,,,,53,53,,695,,54,54,54,53,54,,53,,54,54,,53,53,54,,54,54',
+'54,54,54,54,54,,,,,,54,54,54,54,54,54,54,,,54,,,,,,,54,,,54,54,,54,54',
+'54,54,54,54,54,54,54,,54,54,,54,54,,773,773,773,773,773,773,773,773',
+'773,773,773,,,773,773,,,773,773,,54,,,54,,,54,,,54,,,773,,773,54,773',
+'773,773,773,773,773,773,54,773,,,,54,54,54,54,54,54,,,,54,54,,773,,57',
+'57,57,54,57,,54,,57,57,,54,54,57,,57,57,57,57,57,57,57,,,,,,57,57,57',
+'57,57,57,57,,,57,,,,,,,57,,,57,57,,57,57,57,57,57,,57,57,57,,57,57,',
+'57,57,,779,779,779,779,779,779,779,779,779,779,779,,,779,779,,,779,779',
+',57,,,57,,,57,,,57,,,779,,779,57,779,779,779,779,779,779,779,57,779',
+',,,57,57,57,57,57,57,,,,57,57,,779,,58,58,58,57,58,,57,,58,58,,57,57',
+'58,,58,58,58,58,58,58,58,,,,,,58,58,58,58,58,58,58,,,58,,,,,,,58,,,58',
+'58,,58,58,58,58,58,,58,58,58,,58,58,,58,58,,781,781,781,781,781,781',
+'781,781,781,781,781,,,781,781,,,781,781,,58,,,58,,,58,,,58,,,781,,781',
+'58,781,781,781,781,781,781,781,58,781,,,,58,58,58,58,58,58,,,,58,58',
+',781,,61,61,61,58,61,,58,,61,61,,58,58,61,,61,61,61,61,61,61,61,,,,',
+',61,61,61,61,61,61,61,,,61,,,,,,,61,,,61,61,,61,61,61,61,61,,61,61,61',
+',61,61,,61,61,,672,672,672,672,672,672,672,672,672,672,672,,,672,672',
+',,672,672,,61,,,61,,,61,,,61,,,672,,672,61,672,672,672,672,672,672,672',
+'61,672,,,,61,61,61,61,61,61,,,,61,61,61,672,,672,,61,61,,,61,,,,,61',
+'61,62,62,62,,62,,,,62,62,,,,62,,62,62,62,62,62,62,62,,,,,,62,62,62,62',
+'62,62,62,,,62,,,,,,,62,,,62,62,,62,62,62,62,62,,62,62,62,,62,62,784',
+'784,784,784,784,784,784,784,784,784,784,467,,784,784,,,784,784,,,,,',
+'62,,,62,467,467,62,,784,62,784,62,784,784,784,784,784,784,784,467,784',
+'467,,467,467,467,467,,62,62,62,62,62,62,,,784,62,62,,,,63,63,63,62,63',
+',62,,63,63,,62,62,63,,63,63,63,63,63,63,63,,,,,,63,63,63,63,63,63,63',
+',,63,,,,,,,63,,,63,63,,63,63,63,63,63,,63,63,63,,63,63,786,786,786,786',
+'786,786,786,786,786,786,786,468,,786,786,,,786,786,,,63,,,63,,,63,468',
+'468,63,,786,63,786,,786,786,786,786,786,786,786,468,786,468,,468,468',
+'468,468,,63,63,63,63,63,63,,,786,63,63,,,,84,84,84,63,84,,63,,84,84',
+',63,63,84,,84,84,84,84,84,84,84,,84,,,,84,84,84,84,84,84,84,,,84,,,',
+',,,84,,,84,84,,84,84,84,84,84,84,84,84,84,,84,84,,84,84,,793,793,793',
+'793,793,793,793,793,793,793,793,,,793,793,,,793,793,,84,,,84,84,,84',
+',,84,,84,793,84,793,84,793,793,793,793,793,793,793,84,793,84,,,84,84',
+'84,84,84,84,,,,84,84,,793,,87,87,87,84,87,,84,,87,87,,84,84,87,,87,87',
+'87,87,87,87,87,,87,,,,87,87,87,87,87,87,87,,,87,,,,,,,87,,,87,87,,87',
+'87,87,87,87,87,87,87,87,,87,87,,87,87,,873,873,873,873,873,873,873,873',
+'873,873,873,,,873,873,,,873,873,,87,,,87,87,,87,,,87,,87,873,87,873',
+'87,873,873,873,873,873,873,873,87,873,87,,,87,87,87,87,87,87,,,,87,87',
+',873,,,,,87,,,87,,,,,87,87,99,99,99,99,99,,,,99,99,,,,99,,99,99,99,99',
+'99,99,99,,,,,,99,99,99,99,99,99,99,,,99,,,,,,99,99,99,99,99,99,,99,99',
+'99,99,99,,99,99,99,,99,99,,99,99,,875,875,875,875,875,875,875,875,875',
+'875,875,,,875,875,,,875,875,,99,,,99,,,99,,,99,,99,875,,875,99,875,875',
+'875,875,875,875,875,99,875,,,,99,99,99,99,99,99,,,,99,99,,875,,,,99',
'99,,,99,,,,,99,99,103,103,103,,103,,,,103,103,,,,103,,103,103,103,103',
-'103,103,103,,,,,,103,103,103,103,103,103,103,,,103,,,,,,,103,,,103,103',
-',103,103,103,103,103,,103,103,103,,103,103,,103,103,,,,,,,,,,,,,,,,',
-',,,,,103,,,103,,,103,,,103,,,,,,103,,,,,,,,103,,,,,103,103,103,103,103',
-'103,,,,103,103,,,,104,104,104,103,104,,103,,104,104,,103,103,104,,104',
-'104,104,104,104,104,104,,,,,,104,104,104,104,104,104,104,,,104,,,,,',
-',104,,,104,104,,104,104,104,104,104,,104,104,104,,104,104,,104,104,',
-',,,,,,,,,,,,,,,,,,,,104,,,104,,,104,,,104,,,,,,104,,,,,,,,104,,,,,104',
+'103,103,103,,,,,,103,103,103,103,103,103,103,,338,103,338,338,338,,338',
+',103,,,103,103,,103,103,103,103,103,,103,103,103,,103,103,,103,103,566',
+',566,566,566,,566,,,718,338,718,718,718,,718,,,338,,,103,,,103,,,103',
+',,103,,,,,,103,,,566,,,,,103,,,566,718,103,103,103,103,103,103,,718',
+',103,103,,,,104,104,104,103,104,,103,,104,104,,103,103,104,,104,104',
+'104,104,104,104,104,,,,,,104,104,104,104,104,104,104,,,104,,,,,,,104',
+',,104,104,,104,104,104,104,104,,104,104,104,,104,104,,104,104,,459,459',
+'459,459,459,459,459,459,459,459,459,,,459,459,,,459,459,,104,,,104,',
+',104,,,104,,,459,,459,104,459,459,459,459,459,459,459,104,459,,,,104',
'104,104,104,104,104,,,,104,104,,,,105,105,105,104,105,,104,,105,105',
',104,104,105,,105,105,105,105,105,105,105,,,,,,105,105,105,105,105,105',
'105,,,105,,,,,,,105,,,105,105,,105,105,105,105,105,,105,105,105,,105',
-'105,,105,105,,,,,,,,,,,,,,,,,,,,,,105,,,105,,,105,,,105,,,,,,105,,,',
-',,,,105,,,,,105,105,105,105,105,105,,,,105,105,,,,106,106,106,105,106',
-',105,,106,106,,105,105,106,,106,106,106,106,106,106,106,,,,,,106,106',
-'106,106,106,106,106,,,106,,,,,,,106,,,106,106,,106,106,106,106,106,',
-'106,106,106,,106,106,,106,106,,,,,,,,,,,,,,,,,,,,,,106,,,106,,,106,',
-',106,,,,,,106,,,,,,,,106,,,,,106,106,106,106,106,106,,,,106,106,,,,',
-',,106,,,106,,,,,106,106,107,107,107,107,107,,,,107,107,,,,107,,107,107',
-'107,107,107,107,107,,,,,,107,107,107,107,107,107,107,,,107,,,,,,107',
-'107,,107,107,107,,107,107,107,107,107,,107,107,107,,107,107,,107,107',
-',,,,,,,,,,,,,,,,,,,,,107,,,107,,,107,,,107,,107,,,,107,,,,,,,,107,,',
-',,107,107,107,107,107,107,,,,107,107,,,,,,,107,,,107,,,,,107,107,108',
-'108,108,108,108,,,,108,108,,,,108,,108,108,108,108,108,108,108,,,,,',
-'108,108,108,108,108,108,108,,,108,,,,,,108,108,108,108,108,108,,108',
-'108,108,108,108,,108,108,108,,108,108,,108,108,,,,,,,,,,,,,,,,,,,,,',
-'108,,,108,,,108,,,108,,108,,,,108,,,,,,,,108,,,,,108,108,108,108,108',
-'108,,,,108,108,,,,,,,108,,,108,,,,,108,108,747,747,747,747,747,,,,747',
-'747,,,,747,,747,747,747,747,747,747,747,,,,,,747,747,747,747,747,747',
-'747,,,747,,,,,,747,747,,747,747,747,,747,747,747,747,747,,747,747,747',
-',747,747,,747,747,,,,,,,,,,,,,,,,,,,,,,747,,,747,,,747,,,747,,747,,',
-',747,,,,,,,,747,,,,,747,747,747,747,747,747,,,,747,747,,,,,,,747,,,747',
-',,,,747,747,743,743,743,743,743,,,,743,743,,,,743,,743,743,743,743,743',
-'743,743,,,,,,743,743,743,743,743,743,743,,,743,,,,,,743,743,,743,743',
-'743,,743,743,743,743,743,,743,743,743,,743,743,,743,743,,,,,,,,,,,,',
-',,,,,,,,,743,,,743,,,743,,,743,,743,,,,743,,,,,,,,743,,,,,743,743,743',
-'743,743,743,,,,743,743,,,,738,738,738,743,738,,743,,738,738,,743,743',
-'738,,738,738,738,738,738,738,738,,,,,,738,738,738,738,738,738,738,,',
-'738,,,,,,,738,,,738,738,,738,738,738,738,738,,738,738,738,,738,738,',
-'738,738,,,,,,,,,,,,,,,,,,,,,,738,,,738,,,738,,,738,,,,,,738,,,,,,,,738',
-',,,,738,738,738,738,738,738,,,,738,738,,,,,,,738,,,738,,,,,738,738,195',
-'195,195,195,195,,,,195,195,,,,195,,195,195,195,195,195,195,195,,,,,',
-'195,195,195,195,195,195,195,,,195,,,,,,195,195,,195,195,195,,195,195',
-'195,195,195,,195,195,195,,195,195,,195,195,,,,,,,,,,,,,,,,,,,,,,195',
-',,195,,,195,,,195,,195,,,,195,,,,,,,,195,,,,,195,195,195,195,195,195',
+'105,,105,105,,460,460,460,460,460,460,460,460,460,460,460,,,460,460',
+',,460,460,,105,,,105,,,105,,,105,,,460,,460,105,460,460,460,460,460',
+'460,460,105,460,,,,105,105,105,105,105,105,,,,105,105,,,,106,106,106',
+'105,106,,105,,106,106,,105,105,106,,106,106,106,106,106,106,106,,,,',
+',106,106,106,106,106,106,106,,,106,,,,,,,106,,,106,106,,106,106,106',
+'106,106,,106,106,106,,106,106,,106,106,,470,470,470,470,470,470,470',
+',,470,470,,,,,,,470,470,,106,,,106,,,106,,,106,,,470,,470,106,470,470',
+'470,470,470,470,470,106,470,,,,106,106,106,106,106,106,,,,106,106,,',
+',,,,106,,,106,,,,,106,106,107,107,107,107,107,,,,107,107,,,,107,,107',
+'107,107,107,107,107,107,,,,,,107,107,107,107,107,107,107,,,107,,,,,',
+'107,107,,107,107,107,,107,107,107,107,107,,107,107,107,,107,107,,107',
+'107,,471,,,,,,,,,,,,,,,,,471,471,,107,,,107,,,107,,,107,,107,471,,471',
+'107,471,471,471,471,,,471,107,471,,,,107,107,107,107,107,107,,,,107',
+'107,,,,,,,107,,,107,,,,,107,107,108,108,108,108,108,,,,108,108,,,,108',
+',108,108,108,108,108,108,108,,,,,,108,108,108,108,108,108,108,,,108',
+',,,,,108,108,108,108,108,108,,108,108,108,108,108,,108,108,108,,108',
+'108,,108,108,,472,,,,,,,,,,,,,,,,,472,472,,108,,,108,,,108,,,108,,108',
+'472,,472,108,472,472,472,472,,,472,108,472,,,,108,108,108,108,108,108',
+',,,108,108,,,,,,,108,,,108,,,,,108,108,195,195,195,195,195,,,,195,195',
+',,,195,,195,195,195,195,195,195,195,,,,,,195,195,195,195,195,195,195',
+',,195,,,,,,195,195,,195,195,195,,195,195,195,195,195,,195,195,195,,195',
+'195,,195,195,,473,,,,,,,,,,,,,,,,,473,473,,195,,,195,,,195,,,195,,195',
+'473,,473,195,473,473,473,473,,,473,195,473,,,,195,195,195,195,195,195',
',,,195,195,,,,196,196,196,195,196,,195,,196,196,,195,195,196,,196,196',
'196,196,196,196,196,,,,,,196,196,196,196,196,196,196,,,196,,,,,,,196',
-',,196,196,,196,196,196,196,196,,196,196,196,,196,196,,196,196,,,,,,',
-',,,,,,,,,,,,,,,196,,,196,,,196,,,196,,196,,,,196,,,,,,,,196,,,,,196',
-'196,196,196,196,196,,,,196,196,,,,197,197,197,196,197,,196,,197,197',
-',196,196,197,,197,197,197,197,197,197,197,,,,,,197,197,197,197,197,197',
-'197,,,197,,,,,,,197,,,197,197,,197,197,197,197,197,,197,197,197,,197',
-'197,,197,197,,,,,,,,,,,,,,,,,,,,,,197,,,197,,,197,,,197,,197,,,,197',
-',,,,,,,197,,,,,197,197,197,197,197,197,,,,197,197,,,,198,198,198,197',
-'198,,197,,198,198,,197,197,198,,198,198,198,198,198,198,198,,,,,,198',
-'198,198,198,198,198,198,,,198,,,,,,,198,,,198,198,,198,198,198,198,198',
-',198,198,198,,198,198,,198,198,,,,,,,,,,,,,,,,,,,,,,198,,,198,,,198',
-',,198,,,,,,198,,,,,,,,198,,,,,198,198,198,198,198,198,,,,198,198,,,',
-'199,199,199,198,199,,198,,199,199,,198,198,199,,199,199,199,199,199',
-'199,199,,,,,,199,199,199,199,199,199,199,,,199,,,,,,,199,,,199,199,',
-'199,199,199,199,199,199,199,199,199,,199,199,,199,199,,,,,,,,,,,,,,',
-',,,,,,,199,,,199,,,199,,,199,,199,,,,199,,,,,,,,199,,,,,199,199,199',
-'199,199,199,,,,199,199,,,,200,200,200,199,200,,199,,200,200,,199,199',
-'200,,200,200,200,200,200,200,200,,,,,,200,200,200,200,200,200,200,,',
-'200,,,,,,,200,,,200,200,,200,200,200,200,200,200,200,200,200,,200,200',
-',200,200,,,,,,,,,,,,,,,,,,,,,,200,,,200,,,200,,,200,,200,,,,200,,,,',
-',,,200,,,,,200,200,200,200,200,200,,,,200,200,,,,731,731,731,200,731',
-',200,,731,731,,200,200,731,,731,731,731,731,731,731,731,,,,,,731,731',
-'731,731,731,731,731,,,731,,,,,,,731,,,731,731,,731,731,731,731,731,',
-'731,731,731,,731,731,,731,731,,,,,,,,,,,,,,,,,,,,,,731,,,731,,,731,',
-',731,,731,,,,731,,,,,,,,731,,,,,731,731,731,731,731,731,,,,731,731,',
-',,700,700,700,731,700,,731,,700,700,,731,731,700,,700,700,700,700,700',
-'700,700,,,,,,700,700,700,700,700,700,700,,,700,,,,,,,700,,,700,700,',
-'700,700,700,700,700,,700,700,700,,700,700,,700,700,,,,,,,,,,,,,,,,,',
-',,,,700,,,700,,,700,,,700,,700,,,,700,,,,,,,,700,,,,,700,700,700,700',
-'700,700,,,,700,700,,,,694,694,694,700,694,,700,,694,694,,700,700,694',
-',694,694,694,694,694,694,694,,,,,,694,694,694,694,694,694,694,,,694',
-',,,,,,694,,,694,694,,694,694,694,694,694,,694,694,694,,694,694,,,,,',
-',,,,,,,,,,,,,,,,,,,694,,,694,,,694,,,694,,,,,,,,,,,,,,,,,,,694,694,694',
-'694,694,694,,,,694,694,,,,204,204,204,694,204,,694,,204,204,,694,694',
-'204,,204,204,204,204,204,204,204,,,,,,204,204,204,204,204,204,204,,',
-'204,,,,,,,204,,,204,204,,204,204,204,204,204,,204,204,204,,204,204,',
-'204,204,,,,,,,,,,,,,,,,,,,,,,204,,,204,,,204,,,204,,,,,,204,,,,,,,,204',
-',,,,204,204,204,204,204,204,,,,204,204,,,,205,205,205,204,205,,204,',
-'205,205,,204,204,205,,205,205,205,205,205,205,205,,,,,,205,205,205,205',
-'205,205,205,,,205,,,,,,,205,,,205,205,,205,205,205,205,205,,205,205',
-'205,,205,205,,205,205,,,,,,,,,,,,,,,,,,,,,,205,,,205,,,205,,,205,,,',
-',,205,,,,,,,,205,,,,,205,205,205,205,205,205,,,,205,205,,,,206,206,206',
-'205,206,,205,,206,206,,205,205,206,,206,206,206,206,206,206,206,,,,',
-',206,206,206,206,206,206,206,,,206,,,,,,,206,,,206,206,,206,206,206',
-'206,206,,206,206,206,,206,206,,206,206,,,,,,,,,,,,,,,,,,,,,,206,,,206',
-',,206,,,206,,,,,,206,,,,,,,,206,,,,,206,206,206,206,206,206,,,,206,206',
-',,,682,682,682,206,682,,206,,682,682,,206,206,682,,682,682,682,682,682',
-'682,682,,,,,,682,682,682,682,682,682,682,,,682,,,,,,,682,,,682,682,',
-'682,682,682,682,682,,682,682,682,,682,682,600,,600,600,600,600,600,',
-',,,,,,,,600,,,,,,,,682,,,682,,,682,,,682,,,,,,600,600,,,,,,,600,600',
-'600,600,,682,682,682,682,682,682,,,,682,682,,,,,,,682,,,682,,,,,682',
-'682,678,678,678,678,678,,,600,678,678,,,,678,,678,678,678,678,678,678',
-'678,,,,,,678,678,678,678,678,678,678,,,678,,,,,,678,678,,678,678,678',
-',678,678,678,678,678,,678,678,678,,678,678,,678,678,,,,,,,,,,,,,,,,',
-',,,,,678,,,678,,,678,,,678,,678,,,,678,,,,,,,,678,,,,,678,678,678,678',
-'678,678,,,,678,678,,,,,,,678,,,678,,,,,678,678,677,677,677,677,677,',
-',,677,677,,,,677,,677,677,677,677,677,677,677,,,,,,677,677,677,677,677',
-'677,677,,,677,,,,,,677,677,,677,677,677,,677,677,677,677,677,,677,677',
-'677,,677,677,,677,677,,,,,,,,,,,,,,,,,,,,,,677,,,677,,,677,,,677,,677',
-',,,677,,,,,,,,677,,,,,677,677,677,677,677,677,,,,677,677,,,,671,671',
-'671,677,671,,677,,671,671,,677,677,671,,671,671,671,671,671,671,671',
-',,,,,671,671,671,671,671,671,671,,,671,,,,,,,671,,,671,671,,671,671',
-'671,671,671,671,671,671,671,,671,671,,671,671,,,,,,,,,,,,,,,,,,,,,,671',
-',,671,,,671,,,671,,,,671,,671,,,,,,,,671,,,,,671,671,671,671,671,671',
-',,,671,671,,,,670,670,670,671,670,,671,,670,670,,671,671,670,,670,670',
-'670,670,670,670,670,,,,,,670,670,670,670,670,670,670,,,670,,,,,,,670',
-',,670,670,,670,670,670,670,670,670,670,670,670,,670,670,,670,670,,,',
-',,,,,,,,,,,,,,,,,,670,,,670,,,670,,,670,,670,,670,,670,,,,,,,,670,,',
-',,670,670,670,670,670,670,,,,670,670,,,,,,,670,,,670,,,,,670,670,667',
-'667,667,667,667,,,,667,667,,,,667,,667,667,667,667,667,667,667,,,,,',
-'667,667,667,667,667,667,667,,,667,,,,,,667,667,,667,667,667,,667,667',
-'667,667,667,,667,667,667,,667,667,,667,667,,,,,,,,,,,,,,,,,,,,,,667',
-',,667,,,667,,,667,,667,,,,667,,,,,,,,667,,,,,667,667,667,667,667,667',
-',,,667,667,,,,,,,667,,,667,,,,,667,667,214,214,214,214,214,,,,214,214',
-',,,214,,214,214,214,214,214,214,214,,,,,,214,214,214,214,214,214,214',
-',,214,,,,,,214,214,,214,214,214,,214,214,214,214,214,,214,214,214,,214',
-'214,,214,214,,,,,,,,,,,,,,,,,,,,,,214,,,214,,,214,,,214,,214,,,,214',
-',,,,,,,214,,,,,214,214,214,214,214,214,,,,214,214,,,,215,215,215,214',
-'215,,214,,215,215,,214,214,215,,215,215,215,215,215,215,215,,,,,,215',
-'215,215,215,215,215,215,,,215,,,,,,,215,,,215,215,,215,215,215,215,215',
-',215,215,215,,215,215,,215,215,,,,,,,,,,,,,,,,,,,,,,215,,,215,,215,215',
-',,215,,,,,,215,,,,,,,,215,,,,,215,215,215,215,215,215,,,,215,215,,,',
-'218,218,218,215,218,,215,,218,218,,215,215,218,,218,218,218,218,218',
-'218,218,,,,,,218,218,218,218,218,218,218,,,218,,,,,,,218,,,218,218,',
-'218,218,218,218,218,,218,218,218,,218,218,,218,218,,,,,,,,,,,,,,,,,',
-',,,,218,,,218,,,218,,,218,,,,,,218,,,,,,,,218,,,,,218,218,218,218,218',
-'218,,,,218,218,,,,658,658,658,218,658,,218,,658,658,,218,218,658,,658',
-'658,658,658,658,658,658,,,,,,658,658,658,658,658,658,658,,,658,,,,,',
-',658,,,658,658,,658,658,658,658,658,,658,658,658,,658,658,,658,658,',
-',,,,,,,,,,,,,,,,,,,,658,,,658,,,658,,,658,,,,,,658,,,,,,,,658,,,,,658',
-'658,658,658,658,658,,,,658,658,,,,220,220,220,658,220,,658,,220,220',
-',658,658,220,,220,220,220,220,220,220,220,,,,,,220,220,220,220,220,220',
-'220,,,220,,,,,,,220,,,220,220,,220,220,220,220,220,,220,220,220,,220',
-'220,,220,220,,,,,,,,,,,,,,,,,,,,,,220,,,220,,,220,,,220,,,,,,220,,,',
-',,,,220,,,,,220,220,220,220,220,220,,,,220,220,,,,221,221,221,220,221',
-',220,,221,221,,220,220,221,,221,221,221,221,221,221,221,,,,,,221,221',
-'221,221,221,221,221,,,221,,,,,,,221,,,221,221,,221,221,221,221,221,',
-'221,221,221,,221,221,,221,221,,,,,,,,,,,,,,,,,,,,,,221,,,221,,,221,',
-',221,,,,,,221,,,,,,,,221,,,,,221,221,221,221,221,221,,,,221,221,,,,222',
-'222,222,221,222,,221,,222,222,,221,221,222,,222,222,222,222,222,222',
-'222,,,,,,222,222,222,222,222,222,222,,,222,,,,,,,222,,,222,222,,222',
-'222,222,222,222,,222,222,222,,222,222,,222,222,,,,,,,,,,,,,,,,,,,,,',
-'222,,,222,,,222,,,222,,,,,,222,,,,,,,,222,,,,,222,222,222,222,222,222',
-',,,222,222,,,,223,223,223,222,223,,222,,223,223,,222,222,223,,223,223',
-'223,223,223,223,223,,,,,,223,223,223,223,223,223,223,,,223,,,,,,,223',
-',,223,223,,223,223,223,223,223,,223,223,223,,223,223,,223,223,,,,,,',
-',,,,,,,,,,,,,,,223,,,223,,,223,,,223,,,,,,223,,,,,,,,223,,,,,223,223',
-'223,223,223,223,,,,223,223,,,,224,224,224,223,224,,223,,224,224,,223',
-'223,224,,224,224,224,224,224,224,224,,,,,,224,224,224,224,224,224,224',
-',,224,,,,,,,224,,,224,224,,224,224,224,224,224,,224,224,224,,224,224',
-',224,224,,,,,,,,,,,,,,,,,,,,,,224,,,224,,,224,,,224,,,,,,224,,,,,,,',
-'224,,,,,224,224,224,224,224,224,,,,224,224,,,,225,225,225,224,225,,224',
-',225,225,,224,224,225,,225,225,225,225,225,225,225,,,,,,225,225,225',
-'225,225,225,225,,,225,,,,,,,225,,,225,225,,225,225,225,225,225,,225',
-'225,225,,225,225,,225,225,,,,,,,,,,,,,,,,,,,,,,225,,,225,,,225,,,225',
-',,,,,225,,,,,,,,225,,,,,225,225,225,225,225,225,,,,225,225,,,,226,226',
-'226,225,226,,225,,226,226,,225,225,226,,226,226,226,226,226,226,226',
-',,,,,226,226,226,226,226,226,226,,,226,,,,,,,226,,,226,226,,226,226',
-'226,226,226,,226,226,226,,226,226,,226,226,,,,,,,,,,,,,,,,,,,,,,226',
-',,226,,,226,,,226,,,,,,226,,,,,,,,226,,,,,226,226,226,226,226,226,,',
-',226,226,,,,227,227,227,226,227,,226,,227,227,,226,226,227,,227,227',
-'227,227,227,227,227,,,,,,227,227,227,227,227,227,227,,,227,,,,,,,227',
-',,227,227,,227,227,227,227,227,,227,227,227,,227,227,,227,227,,,,,,',
-',,,,,,,,,,,,,,,227,,,227,,,227,,,227,,,,,,227,,,,,,,,227,,,,,227,227',
-'227,227,227,227,,,,227,227,,,,228,228,228,227,228,,227,,228,228,,227',
-'227,228,,228,228,228,228,228,228,228,,,,,,228,228,228,228,228,228,228',
-',,228,,,,,,,228,,,228,228,,228,228,228,228,228,,228,228,228,,228,228',
-',228,228,,,,,,,,,,,,,,,,,,,,,,228,,,228,,,228,,,228,,,,,,228,,,,,,,',
-'228,,,,,228,228,228,228,228,228,,,,228,228,,,,229,229,229,228,229,,228',
-',229,229,,228,228,229,,229,229,229,229,229,229,229,,,,,,229,229,229',
-'229,229,229,229,,,229,,,,,,,229,,,229,229,,229,229,229,229,229,,229',
-'229,229,,229,229,,229,229,,,,,,,,,,,,,,,,,,,,,,229,,,229,,,229,,,229',
-',,,,,229,,,,,,,,229,,,,,229,229,229,229,229,229,,,,229,229,,,,230,230',
-'230,229,230,,229,,230,230,,229,229,230,,230,230,230,230,230,230,230',
-',,,,,230,230,230,230,230,230,230,,,230,,,,,,,230,,,230,230,,230,230',
-'230,230,230,,230,230,230,,230,230,,230,230,,,,,,,,,,,,,,,,,,,,,,230',
-',,230,,,230,,,230,,,,,,230,,,,,,,,230,,,,,230,230,230,230,230,230,,',
-',230,230,,,,231,231,231,230,231,,230,,231,231,,230,230,231,,231,231',
-'231,231,231,231,231,,,,,,231,231,231,231,231,231,231,,,231,,,,,,,231',
-',,231,231,,231,231,231,231,231,,231,231,231,,231,231,,231,231,,,,,,',
-',,,,,,,,,,,,,,,231,,,231,,,231,,,231,,,,,,231,,,,,,,,231,,,,,231,231',
-'231,231,231,231,,,,231,231,,,,232,232,232,231,232,,231,,232,232,,231',
-'231,232,,232,232,232,232,232,232,232,,,,,,232,232,232,232,232,232,232',
-',,232,,,,,,,232,,,232,232,,232,232,232,232,232,,232,232,232,,232,232',
-',232,232,,,,,,,,,,,,,,,,,,,,,,232,,,232,,,232,,,232,,,,,,232,,,,,,,',
-'232,,,,,232,232,232,232,232,232,,,,232,232,,,,233,233,233,232,233,,232',
-',233,233,,232,232,233,,233,233,233,233,233,233,233,,,,,,233,233,233',
-'233,233,233,233,,,233,,,,,,,233,,,233,233,,233,233,233,233,233,,233',
-'233,233,,233,233,,233,233,,,,,,,,,,,,,,,,,,,,,,233,,,233,,,233,,,233',
-',,,,,233,,,,,,,,233,,,,,233,233,233,233,233,233,,,,233,233,,,,234,234',
-'234,233,234,,233,,234,234,,233,233,234,,234,234,234,234,234,234,234',
-',,,,,234,234,234,234,234,234,234,,,234,,,,,,,234,,,234,234,,234,234',
-'234,234,234,,234,234,234,,234,234,,234,234,,,,,,,,,,,,,,,,,,,,,,234',
-',,234,,,234,,,234,,,,,,234,,,,,,,,234,,,,,234,234,234,234,234,234,,',
-',234,234,,,,235,235,235,234,235,,234,,235,235,,234,234,235,,235,235',
-'235,235,235,235,235,,,,,,235,235,235,235,235,235,235,,,235,,,,,,,235',
-',,235,235,,235,235,235,235,235,,235,235,235,,235,235,,235,235,,,,,,',
-',,,,,,,,,,,,,,,235,,,235,,,235,,,235,,,,,,235,,,,,,,,235,,,,,235,235',
-'235,235,235,235,,,,235,235,,,,236,236,236,235,236,,235,,236,236,,235',
-'235,236,,236,236,236,236,236,236,236,,,,,,236,236,236,236,236,236,236',
-',,236,,,,,,,236,,,236,236,,236,236,236,236,236,,236,236,236,,236,236',
-',236,236,,,,,,,,,,,,,,,,,,,,,,236,,,236,,,236,,,236,,,,,,236,,,,,,,',
-'236,,,,,236,236,236,236,236,236,,,,236,236,,,,237,237,237,236,237,,236',
-',237,237,,236,236,237,,237,237,237,237,237,237,237,,,,,,237,237,237',
-'237,237,237,237,,,237,,,,,,,237,,,237,237,,237,237,237,237,237,,237',
-'237,237,,237,237,,237,237,,,,,,,,,,,,,,,,,,,,,,237,,,237,,,237,,,237',
-',,,,,237,,,,,,,,237,,,,,237,237,237,237,237,237,,,,237,237,,,,238,238',
-'238,237,238,,237,,238,238,,237,237,238,,238,238,238,238,238,238,238',
-',,,,,238,238,238,238,238,238,238,,,238,,,,,,,238,,,238,238,,238,238',
-'238,238,238,,238,238,238,,238,238,,238,238,,,,,,,,,,,,,,,,,,,,,,238',
-',,238,,,238,,,238,,,,,,238,,,,,,,,238,,,,,238,238,238,238,238,238,,',
-',238,238,,,,239,239,239,238,239,,238,,239,239,,238,238,239,,239,239',
-'239,239,239,239,239,,,,,,239,239,239,239,239,239,239,,,239,,,,,,,239',
-',,239,239,,239,239,239,239,239,,239,239,239,,239,239,,239,239,,,,,,',
-',,,,,,,,,,,,,,,239,,,239,,,239,,,239,,,,,,239,,,,,,,,239,,,,,239,239',
-'239,239,239,239,,,,239,239,,,,240,240,240,239,240,,239,,240,240,,239',
-'239,240,,240,240,240,240,240,240,240,,,,,,240,240,240,240,240,240,240',
-',,240,,,,,,,240,,,240,240,,240,240,240,240,240,,240,240,240,,240,240',
-',240,240,,,,,,,,,,,,,,,,,,,,,,240,,,240,,,240,,,240,,,,,,240,,,,,,,',
-'240,,,,,240,240,240,240,240,240,,,,240,240,,,,241,241,241,240,241,,240',
-',241,241,,240,240,241,,241,241,241,241,241,241,241,,,,,,241,241,241',
-'241,241,241,241,,,241,,,,,,,241,,,241,241,,241,241,241,241,241,,241',
-'241,241,,241,241,,241,241,,,,,,,,,,,,,,,,,,,,,,241,,,241,,,241,,,241',
-',,,,,241,,,,,,,,241,,,,,241,241,241,241,241,241,,,,241,241,,,,242,242',
-'242,241,242,,241,,242,242,,241,241,242,,242,242,242,242,242,242,242',
-',,,,,242,242,242,242,242,242,242,,,242,,,,,,,242,,,242,242,,242,242',
-'242,242,242,,242,242,242,,242,242,,242,242,,,,,,,,,,,,,,,,,,,,,,242',
-',,242,,,242,,,242,,,,,,242,,,,,,,,242,,,,,242,242,242,242,242,242,,',
-',242,242,,,,243,243,243,242,243,,242,,243,243,,242,242,243,,243,243',
-'243,243,243,243,243,,,,,,243,243,243,243,243,243,243,,,243,,,,,,,243',
-',,243,243,,243,243,243,243,243,,243,243,243,,243,243,,243,243,,,,,,',
-',,,,,,,,,,,,,,,243,,,243,,,243,,,243,,,,,,243,,,,,,,,243,,,,,243,243',
-'243,243,243,243,,,,243,243,,,,244,244,244,243,244,,243,,244,244,,243',
-'243,244,,244,244,244,244,244,244,244,,,,,,244,244,244,244,244,244,244',
-',,244,,,,,,,244,,,244,244,,244,244,244,244,244,,244,244,244,,244,244',
-',244,244,,,,,,,,,,,,,,,,,,,,,,244,,,244,,,244,,,244,,,,,,244,,,,,,,',
-'244,,,,,244,244,244,244,244,244,,,,244,244,,,,245,245,245,244,245,,244',
-',245,245,,244,244,245,,245,245,245,245,245,245,245,,,,,,245,245,245',
-'245,245,245,245,,,245,,,,,,,245,,,245,245,,245,245,245,245,245,,245',
-'245,245,,245,245,,245,245,,,,,,,,,,,,,,,,,,,,,,245,,,245,,,245,,,245',
-',,,,,245,,,,,,,,245,,,,,245,245,245,245,245,245,,,,245,245,,,,,,,245',
-',,245,,,,,245,245,654,654,654,654,654,,,,654,654,,,,654,,654,654,654',
-'654,654,654,654,,,,,,654,654,654,654,654,654,654,,,654,,,,,,654,654',
-',654,654,654,,654,654,654,654,654,,654,654,654,,654,654,,654,654,,,',
-',,,,,,,,,,,,,,,,,,654,,,654,,,654,,,654,,654,,,,654,,,,,,,,654,,,,,654',
-'654,654,654,654,654,,,,654,654,,,,650,650,650,654,650,,654,,650,650',
-',654,654,650,,650,650,650,650,650,650,650,,,,,,650,650,650,650,650,650',
-'650,,,650,,,,,,,650,,,650,650,,650,650,650,650,650,,650,650,650,,650',
-'650,,650,650,,,,,,,,,,,,,,,,,,,,,,650,,,650,,,650,,,650,,,,,,650,,,',
-',,,,650,,,,,650,650,650,650,650,650,,,,650,650,,,,254,254,254,650,254',
-',650,,254,254,,650,650,254,,254,254,254,254,254,254,254,,,,,,254,254',
-'254,254,254,254,254,,,254,,,,,,,254,,,254,254,,254,254,254,254,254,',
-'254,254,254,,254,254,,254,254,,,,,,,,,,,,,,,,,,,,,,254,,,254,,,254,',
-',254,,,,,,254,,,,,,,,254,,,,,254,254,254,254,254,254,,,,254,254,,,,256',
-'256,256,254,256,,254,,256,256,,254,254,256,,256,256,256,256,256,256',
-'256,,,,,,256,256,256,256,256,256,256,,,256,,,,,,,256,,,256,256,,256',
-'256,256,256,256,,256,256,256,,256,256,,256,256,,,,,,,,,,,,,,,,,,,,,',
-'256,,,256,,,256,,,256,,,,,,256,,,,,,,,256,,,,,256,256,256,256,256,256',
-',,,256,256,,,,261,261,261,256,261,,256,,261,261,,256,256,261,,261,261',
-'261,261,261,261,261,,,,,,261,261,261,261,261,261,261,,,261,,,,,,,261',
-',,261,261,,261,261,261,261,261,,261,261,261,,261,261,,261,261,,,,,,',
-',,,,,,,,,,,,,,,261,,,261,,,261,,,261,,,,,,261,,,,,,,,261,,,,,261,261',
-'261,261,261,261,,,,261,261,,,,639,639,639,261,639,,261,,639,639,,261',
-'261,639,,639,639,639,639,639,639,639,,,,,,639,639,639,639,639,639,639',
-',,639,,,,,,,639,,,639,639,,639,639,639,639,639,,639,639,639,,639,639',
-',639,639,,,,,,,,,,,,,,,,,,,,,,639,,,639,,,639,,,639,,,,,,639,,,,,,,',
-'639,,,,,639,639,639,639,639,639,,,,639,639,,,,636,636,636,639,636,,639',
-',636,636,,639,639,636,,636,636,636,636,636,636,636,,,,,,636,636,636',
-'636,636,636,636,,,636,,,,,,,636,,,636,636,,636,636,636,636,636,,636',
-'636,636,,636,636,,636,636,,,,,,,,,,,,,,,,,,,,,,636,,,636,,,636,,,636',
-',,,,,636,,,,,,,,636,,,,,636,636,636,636,636,636,,,,636,636,,,,631,631',
-'631,636,631,,636,,631,631,,636,636,631,,631,631,631,631,631,631,631',
-',,,,,631,631,631,631,631,631,631,,,631,,,,,,,631,,,631,631,,631,631',
-'631,631,631,,631,631,631,,631,631,,631,631,,,,,,,,,,,,,,,,,,,,,,631',
-',,631,,,631,,,631,,,,,,631,,,,,,,,631,,,,,631,631,631,631,631,631,,',
-',631,631,,,,630,630,630,631,630,,631,,630,630,,631,631,630,,630,630',
-'630,630,630,630,630,,,,,,630,630,630,630,630,630,630,,,630,,,,,,,630',
-',,630,630,,630,630,630,630,630,,630,630,630,,630,630,,630,630,,,,,,',
-',,,,,,,,,,,,,,,630,,,630,,,630,,,630,,,,,,630,,,,,,,,630,,,,,630,630',
-'630,630,630,630,,,,630,630,,,,268,268,268,630,268,,630,,268,268,,630',
-'630,268,,268,268,268,268,268,268,268,,,,,,268,268,268,268,268,268,268',
-',,268,,,,,,,268,,,268,268,,268,268,268,268,268,268,268,268,268,,268',
-'268,,268,268,,,,,,,,,,,,,,,,,,,,,,268,,,268,,,268,,,268,,268,,268,,268',
-',,,,,,,268,,,,,268,268,268,268,268,268,,,,268,268,,,,269,269,269,268',
-'269,,268,,269,269,,268,268,269,,269,269,269,269,269,269,269,,,,,,269',
-'269,269,269,269,269,269,,,269,,,,,,,269,,,269,269,,269,269,269,269,269',
-'269,269,269,269,,269,269,,269,269,,,,,,,,,,,,,,,,,,,,,,269,,,269,,,269',
-',,269,,269,,269,,269,,,,,,,,269,,,,,269,269,269,269,269,269,,,,269,269',
-',,,277,277,277,269,277,,269,,277,277,,269,269,277,,277,277,277,277,277',
-'277,277,,,,,,277,277,277,277,277,277,277,,,277,,,,,,,277,,,277,277,',
-'277,277,277,277,277,277,277,277,277,,277,277,,277,277,,,,,,,,,,,,,,',
-',,,,,,,277,,,277,,277,277,,,277,,277,,277,,277,,,,,,,,277,,,,,277,277',
-'277,277,277,277,,,,277,277,,,,627,627,627,277,627,,277,,627,627,,277',
-'277,627,,627,627,627,627,627,627,627,,,,,,627,627,627,627,627,627,627',
-',,627,,,,,,,627,,,627,627,,627,627,627,627,627,,627,627,627,,627,627',
-',627,627,,,,,,,,,,,,,,,,,,,,,,627,,,627,,,627,,,627,,627,,,,627,,,,',
-',,,627,,,,,627,627,627,627,627,627,,,,627,627,,,,625,625,625,627,625',
-',627,,625,625,,627,627,625,,625,625,625,625,625,625,625,,,,,,625,625',
-'625,625,625,625,625,,,625,,,,,,,625,,,625,625,,625,625,625,625,625,',
-'625,625,625,,625,625,,625,625,,,,,,,,,,,,,,,,,,,,,,625,,,625,,,625,',
-',625,,,,,,625,,,,,,,,625,,,,,625,625,625,625,625,625,,,,625,625,,,,598',
-'598,598,625,598,,625,,598,598,,625,625,598,,598,598,598,598,598,598',
-'598,,,,,,598,598,598,598,598,598,598,,,598,,,,,,,598,,,598,598,,598',
-'598,598,598,598,,598,598,598,,598,598,,598,598,,,,,,,,,,,,,,,,,,,,,',
-'598,,,598,,,598,,,598,,,,,,598,,,,,,,,598,,,,,598,598,598,598,598,598',
-',,,598,598,,,,,,,598,,,598,,,,,598,598,281,281,281,281,281,,,,281,281',
-',,,281,,281,281,281,281,281,281,281,,,,,,281,281,281,281,281,281,281',
-',,281,,,,,,281,281,,281,281,281,,281,281,281,281,281,,281,281,281,,281',
-'281,,281,281,,,,,,,,,,,,,,,,,,,,,,281,,,281,,,281,,,281,,281,,,,281',
-',,,,,,,281,,,,,281,281,281,281,281,281,,,,281,281,,,,596,596,596,281',
-'596,,281,,596,596,,281,281,596,,596,596,596,596,596,596,596,,,,,,596',
-'596,596,596,596,596,596,,,596,,,,,,,596,,,596,596,,596,596,596,596,596',
-',596,596,596,,596,596,,596,596,,,,,,,,,,,,,,,,,,,,,,596,,,596,,,596',
-',,596,,,,,,596,,,,,,,,596,,,,,596,596,596,596,596,596,,,,596,596,,,',
-'592,592,592,596,592,,596,,592,592,,596,596,592,,592,592,592,592,592',
-'592,592,,,,,,592,592,592,592,592,592,592,,,592,,,,,,,592,,,592,592,',
-'592,592,592,592,592,592,592,592,592,,592,592,,592,592,,,,,,,,,,,,,,',
-',,,,,,,592,,,592,,,592,,,592,,592,,,,592,,,,,,,,592,,,,,592,592,592',
-'592,592,592,,,,592,592,,,,586,586,586,592,586,,592,,586,586,,592,592',
-'586,,586,586,586,586,586,586,586,,,,,,586,586,586,586,586,586,586,,',
-'586,,,,,,,586,,,586,586,,586,586,586,586,586,586,586,586,586,,586,586',
-',586,586,,,,,,,,,,,,,,,,,,,,,,586,,,586,,,586,,,586,,586,,,,586,,,,',
-',,,586,,,,,586,586,586,586,586,586,,,,586,586,,,,285,285,285,586,285',
-',586,,285,285,,586,586,285,,285,285,285,285,285,285,285,,,,,,285,285',
-'285,285,285,285,285,,,285,,,,,,,285,,,285,285,,285,285,285,285,285,',
-'285,285,285,,285,285,918,,918,918,918,918,918,,,,,,,,,,918,,,,,,,,285',
-',,285,,,285,,,285,,,,,,918,918,,,,,,,918,918,918,918,,285,285,285,285',
-'285,285,,,,285,285,,,,285,,,285,,,285,,,,,285,285,286,286,286,286,286',
-',,918,286,286,,,,286,,286,286,286,286,286,286,286,,,,,,286,286,286,286',
-'286,286,286,,,286,,,,,,286,286,,286,286,286,,286,286,286,286,286,,286',
-'286,286,,286,286,,286,286,,,,,,,,,,,,,,,,,,,,,,286,,,286,,,286,,,286',
-',286,,,,286,,,,,,,,286,,,,,286,286,286,286,286,286,,,,286,286,,,,583',
-'583,583,286,583,,286,,583,583,,286,286,583,,583,583,583,583,583,583',
-'583,,,,,,583,583,583,583,583,583,583,,,583,,,,,,,583,,,583,583,,583',
-'583,583,583,583,583,583,583,583,,583,583,,583,583,,,,,,,,,,,,,,,,,,',
-',,,583,,,583,,,583,,,583,,583,,,,583,,,,,,,,583,,,,,583,583,583,583',
-'583,583,,,,583,583,,,,,,,583,,,583,,,,,583,583,581,581,581,581,581,',
-',,581,581,,,,581,,581,581,581,581,581,581,581,,,,,,581,581,581,581,581',
-'581,581,,,581,,,,,,581,581,,581,581,581,,581,581,581,581,581,,581,581',
-'581,,581,581,,581,581,,,,,,,,,,,,,,,,,,,,,,581,,,581,,,581,,,581,,581',
-',,,581,,,,,,,,581,,,,,581,581,581,581,581,581,,,,581,581,,,,,,,581,',
-',581,,,,,581,581,576,576,576,576,576,,,,576,576,,,,576,,576,576,576',
-'576,576,576,576,,,,,,576,576,576,576,576,576,576,,,576,,,,,,576,576',
-',576,576,576,,576,576,576,576,576,,576,576,576,,576,576,,576,576,,,',
-',,,,,,,,,,,,,,,,,,576,,,576,,,576,,,576,,576,,,,576,,,,,,,,576,,,,,576',
-'576,576,576,576,576,,,,576,576,,,,,,,576,,,576,,,,,576,576,572,572,572',
-'572,572,,,,572,572,,,,572,,572,572,572,572,572,572,572,,,,,,572,572',
-'572,572,572,572,572,,,572,,,,,,572,572,,572,572,572,,572,572,572,572',
-'572,,572,572,572,,572,572,,572,572,,,,,,,,,,,,,,,,,,,,,,572,,,572,,',
-'572,,,572,,572,,,,572,,,,,,,,572,,,,,572,572,572,572,572,572,,,,572',
-'572,,,,558,558,558,572,558,,572,,558,558,,572,572,558,,558,558,558,558',
-'558,558,558,,,,,,558,558,558,558,558,558,558,,,558,,,,,,,558,,,558,558',
-',558,558,558,558,558,,558,558,558,,558,558,856,,856,856,856,856,856',
-',,,,,,,,,856,,,,,,,,558,,,558,,,558,,,558,,,,,,856,,,,,,,,856,856,856',
-'856,,558,558,558,558,558,558,,,,558,558,,,,,,,558,,,558,,,,,558,558',
-'552,552,552,552,552,,,856,552,552,,,,552,,552,552,552,552,552,552,552',
-',,,,,552,552,552,552,552,552,552,,,552,,,,,,552,552,,552,552,552,,552',
-'552,552,552,552,,552,552,552,,552,552,,552,552,,,,,,,,,,,,,,,,,,,,,',
-'552,,,552,,,552,,,552,,552,,,,552,,,,,,,,552,,,,,552,552,552,552,552',
-'552,,,,552,552,,,,,,,552,,,552,,,,,552,552,551,551,551,551,551,,,,551',
-'551,,,,551,,551,551,551,551,551,551,551,,,,,,551,551,551,551,551,551',
-'551,,,551,,,,,,551,551,,551,551,551,,551,551,551,551,551,,551,551,551',
-',551,551,,551,551,,,,,,,,,,,,,,,,,,,,,,551,,,551,,,551,,,551,,551,,',
-',551,,,,,,,,551,,,,,551,551,551,551,551,551,,,,551,551,,,,546,546,546',
-'551,546,,551,,546,546,,551,551,546,,546,546,546,546,546,546,546,,,,',
-',546,546,546,546,546,546,546,,,546,,,,,,,546,,,546,546,,546,546,546',
-'546,546,546,546,546,546,,546,546,,546,546,,,,,,,,,,,,,,,,,,,,,,546,',
-',546,,,546,,,546,,,,,,546,,,,,,,,546,,,,,546,546,546,546,546,546,,,',
-'546,546,,,,543,543,543,546,543,,546,,543,543,,546,546,543,,543,543,543',
-'543,543,543,543,,,,,,543,543,543,543,543,543,543,,,543,,,,,,,543,,,543',
-'543,,543,543,543,543,543,543,543,543,543,,543,543,,543,543,,,,,,,,,',
-',,,,,,,,,,,,543,,,543,,,543,,,543,,543,,,,543,,,,,,,,543,,,,,543,543',
-'543,543,543,543,,,,543,543,,,,298,298,298,543,298,,543,,298,298,,543',
-'543,298,,298,298,298,298,298,298,298,,,,,,298,298,298,298,298,298,298',
-',,298,,,,,,,298,,,298,298,,298,298,298,298,298,,298,298,298,,298,298',
-',,,,,,,,,,,,,,,,,,,,,,,,298,,,298,,,298,,,298,,,,,,,,,,,,,,,,,,,298',
-'298,298,298,298,298,,,,298,298,,,,537,537,537,298,537,,298,,537,537',
-',298,298,537,,537,537,537,537,537,537,537,,,,,,537,537,537,537,537,537',
-'537,,,537,,,,,,,537,,,537,537,,537,537,537,537,537,,537,537,537,,537',
-'537,,537,537,,,,,,,,,,,,,,,,,,,,,,537,,,537,,,537,,,537,,,,,,537,,,',
-',,,,537,,,,,537,537,537,537,537,537,,,,537,537,,,,533,533,533,537,533',
-',537,,533,533,,537,537,533,,533,533,533,533,533,533,533,,,,,,533,533',
-'533,533,533,533,533,,,533,,,,,,,533,,,533,533,,533,533,533,533,533,',
-'533,533,533,,533,533,,533,533,,,,,,,,,,,,,,,,,,,,,,533,,,533,,,533,',
-',533,,,,,,533,,,,,,,,533,,,,,533,533,533,533,533,533,,,,533,533,,,,532',
-'532,532,533,532,,533,,532,532,,533,533,532,,532,532,532,532,532,532',
-'532,,,,,,532,532,532,532,532,532,532,,,532,,,,,,,532,,,532,532,,532',
-'532,532,532,532,,532,532,532,,532,532,,532,532,,,,,,,,,,,,,,,,,,,,,',
-'532,,,532,,,532,,,532,,,,,,532,,,,,,,,532,,,,,532,532,532,532,532,532',
-',,,532,532,,,,531,531,531,532,531,,532,,531,531,,532,532,531,,531,531',
-'531,531,531,531,531,,,,,,531,531,531,531,531,531,531,,,531,,,,,,,531',
-',,531,531,,531,531,531,531,531,,531,531,531,,531,531,,531,531,,,,,,',
-',,,,,,,,,,,,,,,531,,,531,,,531,,,531,,,,,,531,,,,,,,,531,,,,,531,531',
-'531,531,531,531,,,,531,531,,,,523,523,523,531,523,,531,,523,523,,531',
-'531,523,,523,523,523,523,523,523,523,,,,,,523,523,523,523,523,523,523',
-',,523,,,,,,,523,,,523,523,,523,523,523,523,523,523,523,523,523,,523',
-'523,,523,523,,,,,,,,,,,,,,,,,,,,,,523,,,523,,,523,,,523,,523,,,,523',
-',,,,,,,523,,,,,523,523,523,523,523,523,,,,523,523,,,,307,307,307,523',
-'307,,523,,307,307,,523,523,307,,307,307,307,307,307,307,307,,,,,,307',
-'307,307,307,307,307,307,,,307,,,,,,,307,,,307,307,,307,307,307,307,307',
-',307,307,307,,307,307,,307,307,,,,,,,,,,,,,,,,,,,,,,307,,,307,307,,307',
-',,307,,,,,,307,,,,,,,,307,,,,,307,307,307,307,307,307,,,,307,307,,,',
-',,,307,,,307,,,,,307,307,309,309,309,309,309,,,,309,309,,,,309,,309',
-'309,309,309,309,309,309,,,,,,309,309,309,309,309,309,309,,,309,,,,,',
-'309,309,,309,309,309,,309,309,309,309,309,,309,309,309,,309,309,,309',
-'309,,,,,,,,,,,,,,,,,,,,,,309,,,309,,,309,,,309,,309,,,,309,,,,,,,,309',
-',,,,309,309,309,309,309,309,,,,309,309,,,,520,520,520,309,520,,309,',
-'520,520,,309,309,520,,520,520,520,520,520,520,520,,,,,,520,520,520,520',
-'520,520,520,,,520,,,,,,,520,,,520,520,,520,520,520,520,520,520,520,520',
-'520,,520,520,,520,520,,,,,,,,,,,,,,,,,,,,,,520,,,520,,,520,,,520,,520',
-',,,520,,,,,,,,520,,,,,520,520,520,520,520,520,,,,520,520,,,,518,518',
-'518,520,518,,520,,518,518,,520,520,518,,518,518,518,518,518,518,518',
-',,,,,518,518,518,518,518,518,518,,,518,,,,,,,518,,,518,518,,518,518',
-'518,518,518,,518,518,518,,518,518,,,,,,,,,,,,,,,,,,,,,,,,,518,,,518',
-',,518,,,518,,,,,,,,,,,,,,,,,,,518,518,518,518,518,518,,,,518,518,,,',
-',,,518,,,518,,,,,518,518,512,512,512,512,512,,,,512,512,,,,512,,512',
-'512,512,512,512,512,512,,,,,,512,512,512,512,512,512,512,,,512,,,,,',
-'512,512,,512,512,512,,512,512,512,512,512,,512,512,512,,512,512,,512',
-'512,,,,,,,,,,,,,,,,,,,,,,512,,,512,,,512,,,512,,512,,,,512,,,,,,,,512',
-',,,,512,512,512,512,512,512,,,,512,512,,,,,,512,512,,,512,,,,,512,512',
-'506,506,506,,506,,,,506,506,,,,506,,506,506,506,506,506,506,506,,,,',
-',506,506,506,506,506,506,506,,,506,,,,,,,506,,,506,506,,506,506,506',
-'506,506,,506,506,506,,506,506,,506,506,,,,,,,,,,,,,,,,,,,,,,506,,,506',
-',506,506,,,506,,,,506,,506,,,,,,,,506,,,,,506,506,506,506,506,506,,',
-',506,506,,,,491,491,491,506,491,,506,,491,491,,506,506,491,,491,491',
+',,196,196,,196,196,196,196,196,,196,196,196,,196,196,,196,196,,474,',
+',,,,,,,,,,,,,,,474,474,,196,,,196,,,196,,,196,,196,474,,474,196,474',
+'474,474,474,,,474,196,474,,,,196,196,196,196,196,196,,,,196,196,,,,197',
+'197,197,196,197,,196,,197,197,,196,196,197,,197,197,197,197,197,197',
+'197,,,,,,197,197,197,197,197,197,197,,,197,,,,,,,197,,,197,197,,197',
+'197,197,197,197,,197,197,197,,197,197,,197,197,,475,475,475,475,475',
+'475,475,,,475,475,,,,,,,475,475,,197,,,197,,,197,,,197,,197,475,,475',
+'197,475,475,475,475,475,475,475,197,475,,,,197,197,197,197,197,197,',
+',,197,197,,,,198,198,198,197,198,,197,,198,198,,197,197,198,,198,198',
+'198,198,198,198,198,,,,,,198,198,198,198,198,198,198,,,198,,,,,,,198',
+',,198,198,,198,198,198,198,198,,198,198,198,,198,198,,198,198,,476,476',
+'476,476,476,476,476,,,476,476,,,,,,,476,476,,198,,,198,,,198,,,198,',
+',476,,476,198,476,476,476,476,476,476,476,198,476,,,,198,198,198,198',
+'198,198,,,,198,198,,,,199,199,199,198,199,,198,,199,199,,198,198,199',
+',199,199,199,199,199,199,199,,,,,,199,199,199,199,199,199,199,,,199',
+',,,,,,199,,,199,199,,199,199,199,199,199,199,199,199,199,,199,199,,199',
+'199,,477,477,477,477,477,477,477,,,477,477,,,,,,,477,477,,199,,,199',
+',,199,,,199,,199,477,,477,199,477,477,477,477,477,477,477,199,477,,',
+',199,199,199,199,199,199,,,,199,199,,,,200,200,200,199,200,,199,,200',
+'200,,199,199,200,,200,200,200,200,200,200,200,,,,,,200,200,200,200,200',
+'200,200,,,200,,,,,,,200,,,200,200,,200,200,200,200,200,200,200,200,200',
+',200,200,,200,200,,478,478,478,478,478,478,478,,,478,478,,,,,,,478,478',
+',200,,,200,,,200,,,200,,200,478,,478,200,478,478,478,478,478,478,478',
+'200,478,,,,200,200,200,200,200,200,,,,200,200,,,,204,204,204,200,204',
+',200,,204,204,,200,200,204,,204,204,204,204,204,204,204,,,,,,204,204',
+'204,204,204,204,204,,,204,,,,,,,204,,,204,204,,204,204,204,204,204,',
+'204,204,204,,204,204,,204,204,,479,479,479,479,479,479,479,,,479,479',
+',,,,,,479,479,,204,,,204,,,204,,,204,,,479,,479,204,479,479,479,479',
+'479,479,479,204,479,,,,204,204,204,204,204,204,,,,204,204,,,,205,205',
+'205,204,205,,204,,205,205,,204,204,205,,205,205,205,205,205,205,205',
+',,,,,205,205,205,205,205,205,205,,,205,,,,,,,205,,,205,205,,205,205',
+'205,205,205,,205,205,205,,205,205,,205,205,,482,482,482,482,482,482',
+'482,,,482,482,,,,,,,482,482,,205,,,205,,,205,,,205,,,482,,482,205,482',
+'482,482,482,482,482,482,205,482,,,,205,205,205,205,205,205,,,,205,205',
+',,,206,206,206,205,206,,205,,206,206,,205,205,206,,206,206,206,206,206',
+'206,206,,,,,,206,206,206,206,206,206,206,,,206,,,,,,,206,,,206,206,',
+'206,206,206,206,206,,206,206,206,,206,206,,206,206,,483,483,483,483',
+'483,483,483,483,,483,483,,,,,,,483,483,,206,,,206,,,206,,,206,,,483',
+',483,206,483,483,483,483,483,483,483,206,483,,,,206,206,206,206,206',
+'206,,,,206,206,,,,,,,206,,,206,,,,,206,206,214,214,214,214,214,,,,214',
+'214,,,,214,,214,214,214,214,214,214,214,,,,,,214,214,214,214,214,214',
+'214,,,214,,,,,,214,214,,214,214,214,,214,214,214,214,214,,214,214,214',
+',214,214,,214,214,,469,,,,,,,,,,,,,,,,,469,469,,214,,,214,,,214,,,214',
+',214,469,,,214,469,469,469,469,,,,214,,,,,214,214,214,214,214,214,,',
+',214,214,,,,215,215,215,214,215,,214,,215,215,,214,214,215,,215,215',
+'215,215,215,215,215,,,,,,215,215,215,215,215,215,215,,,215,,,,,,,215',
+',,215,215,,215,215,215,215,215,,215,215,215,,215,215,,215,215,,,,,,',
+',,,,,,,,,,,,,,,215,,,215,,215,215,,,215,,,,,,215,,,,,,,,215,,,,,215',
+'215,215,215,215,215,,,,215,215,,,,218,218,218,215,218,,215,,218,218',
+',215,215,218,,218,218,218,218,218,218,218,,,,,,218,218,218,218,218,218',
+'218,,,218,,,,,,,218,,,218,218,,218,218,218,218,218,,218,218,218,,218',
+'218,,218,218,,,,,,,,,,,,,,,,,,,,,,218,,,218,,,218,,,218,,,,,,218,,,',
+',,,,218,,,,,218,218,218,218,218,218,,,,218,218,,,,220,220,220,218,220',
+',218,,220,220,,218,218,220,,220,220,220,220,220,220,220,,,,,,220,220',
+'220,220,220,220,220,,,220,,,,,,,220,,,220,220,,220,220,220,220,220,',
+'220,220,220,,220,220,,220,220,,,,,,,,,,,,,,,,,,,,,,220,,,220,,,220,',
+',220,,,,,,220,,,,,,,,220,,,,,220,220,220,220,220,220,,,,220,220,,,,221',
+'221,221,220,221,,220,,221,221,,220,220,221,,221,221,221,221,221,221',
+'221,,,,,,221,221,221,221,221,221,221,,,221,,,,,,,221,,,221,221,,221',
+'221,221,221,221,,221,221,221,,221,221,,221,221,,,,,,,,,,,,,,,,,,,,,',
+'221,,,221,,,221,,,221,,,,,,221,,,,,,,,221,,,,,221,221,221,221,221,221',
+',,,221,221,,,,222,222,222,221,222,,221,,222,222,,221,221,222,,222,222',
+'222,222,222,222,222,,,,,,222,222,222,222,222,222,222,,,222,,,,,,,222',
+',,222,222,,222,222,222,222,222,,222,222,222,,222,222,,222,222,,,,,,',
+',,,,,,,,,,,,,,,222,,,222,,,222,,,222,,,,,,222,,,,,,,,222,,,,,222,222',
+'222,222,222,222,,,,222,222,,,,223,223,223,222,223,,222,,223,223,,222',
+'222,223,,223,223,223,223,223,223,223,,,,,,223,223,223,223,223,223,223',
+',,223,,,,,,,223,,,223,223,,223,223,223,223,223,,223,223,223,,223,223',
+',223,223,,,,,,,,,,,,,,,,,,,,,,223,,,223,,,223,,,223,,,,,,223,,,,,,,',
+'223,,,,,223,223,223,223,223,223,,,,223,223,,,,224,224,224,223,224,,223',
+',224,224,,223,223,224,,224,224,224,224,224,224,224,,,,,,224,224,224',
+'224,224,224,224,,,224,,,,,,,224,,,224,224,,224,224,224,224,224,,224',
+'224,224,,224,224,,224,224,,,,,,,,,,,,,,,,,,,,,,224,,,224,,,224,,,224',
+',,,,,224,,,,,,,,224,,,,,224,224,224,224,224,224,,,,224,224,,,,225,225',
+'225,224,225,,224,,225,225,,224,224,225,,225,225,225,225,225,225,225',
+',,,,,225,225,225,225,225,225,225,,,225,,,,,,,225,,,225,225,,225,225',
+'225,225,225,,225,225,225,,225,225,,225,225,,,,,,,,,,,,,,,,,,,,,,225',
+',,225,,,225,,,225,,,,,,225,,,,,,,,225,,,,,225,225,225,225,225,225,,',
+',225,225,,,,226,226,226,225,226,,225,,226,226,,225,225,226,,226,226',
+'226,226,226,226,226,,,,,,226,226,226,226,226,226,226,,,226,,,,,,,226',
+',,226,226,,226,226,226,226,226,,226,226,226,,226,226,,226,226,,,,,,',
+',,,,,,,,,,,,,,,226,,,226,,,226,,,226,,,,,,226,,,,,,,,226,,,,,226,226',
+'226,226,226,226,,,,226,226,,,,227,227,227,226,227,,226,,227,227,,226',
+'226,227,,227,227,227,227,227,227,227,,,,,,227,227,227,227,227,227,227',
+',,227,,,,,,,227,,,227,227,,227,227,227,227,227,,227,227,227,,227,227',
+',227,227,,,,,,,,,,,,,,,,,,,,,,227,,,227,,,227,,,227,,,,,,227,,,,,,,',
+'227,,,,,227,227,227,227,227,227,,,,227,227,,,,228,228,228,227,228,,227',
+',228,228,,227,227,228,,228,228,228,228,228,228,228,,,,,,228,228,228',
+'228,228,228,228,,,228,,,,,,,228,,,228,228,,228,228,228,228,228,,228',
+'228,228,,228,228,,228,228,,,,,,,,,,,,,,,,,,,,,,228,,,228,,,228,,,228',
+',,,,,228,,,,,,,,228,,,,,228,228,228,228,228,228,,,,228,228,,,,229,229',
+'229,228,229,,228,,229,229,,228,228,229,,229,229,229,229,229,229,229',
+',,,,,229,229,229,229,229,229,229,,,229,,,,,,,229,,,229,229,,229,229',
+'229,229,229,,229,229,229,,229,229,,229,229,,,,,,,,,,,,,,,,,,,,,,229',
+',,229,,,229,,,229,,,,,,229,,,,,,,,229,,,,,229,229,229,229,229,229,,',
+',229,229,,,,230,230,230,229,230,,229,,230,230,,229,229,230,,230,230',
+'230,230,230,230,230,,,,,,230,230,230,230,230,230,230,,,230,,,,,,,230',
+',,230,230,,230,230,230,230,230,,230,230,230,,230,230,,230,230,,,,,,',
+',,,,,,,,,,,,,,,230,,,230,,,230,,,230,,,,,,230,,,,,,,,230,,,,,230,230',
+'230,230,230,230,,,,230,230,,,,231,231,231,230,231,,230,,231,231,,230',
+'230,231,,231,231,231,231,231,231,231,,,,,,231,231,231,231,231,231,231',
+',,231,,,,,,,231,,,231,231,,231,231,231,231,231,,231,231,231,,231,231',
+',231,231,,,,,,,,,,,,,,,,,,,,,,231,,,231,,,231,,,231,,,,,,231,,,,,,,',
+'231,,,,,231,231,231,231,231,231,,,,231,231,,,,232,232,232,231,232,,231',
+',232,232,,231,231,232,,232,232,232,232,232,232,232,,,,,,232,232,232',
+'232,232,232,232,,,232,,,,,,,232,,,232,232,,232,232,232,232,232,,232',
+'232,232,,232,232,,232,232,,,,,,,,,,,,,,,,,,,,,,232,,,232,,,232,,,232',
+',,,,,232,,,,,,,,232,,,,,232,232,232,232,232,232,,,,232,232,,,,233,233',
+'233,232,233,,232,,233,233,,232,232,233,,233,233,233,233,233,233,233',
+',,,,,233,233,233,233,233,233,233,,,233,,,,,,,233,,,233,233,,233,233',
+'233,233,233,,233,233,233,,233,233,,233,233,,,,,,,,,,,,,,,,,,,,,,233',
+',,233,,,233,,,233,,,,,,233,,,,,,,,233,,,,,233,233,233,233,233,233,,',
+',233,233,,,,234,234,234,233,234,,233,,234,234,,233,233,234,,234,234',
+'234,234,234,234,234,,,,,,234,234,234,234,234,234,234,,,234,,,,,,,234',
+',,234,234,,234,234,234,234,234,,234,234,234,,234,234,,234,234,,,,,,',
+',,,,,,,,,,,,,,,234,,,234,,,234,,,234,,,,,,234,,,,,,,,234,,,,,234,234',
+'234,234,234,234,,,,234,234,,,,235,235,235,234,235,,234,,235,235,,234',
+'234,235,,235,235,235,235,235,235,235,,,,,,235,235,235,235,235,235,235',
+',,235,,,,,,,235,,,235,235,,235,235,235,235,235,,235,235,235,,235,235',
+',235,235,,,,,,,,,,,,,,,,,,,,,,235,,,235,,,235,,,235,,,,,,235,,,,,,,',
+'235,,,,,235,235,235,235,235,235,,,,235,235,,,,236,236,236,235,236,,235',
+',236,236,,235,235,236,,236,236,236,236,236,236,236,,,,,,236,236,236',
+'236,236,236,236,,,236,,,,,,,236,,,236,236,,236,236,236,236,236,,236',
+'236,236,,236,236,,236,236,,,,,,,,,,,,,,,,,,,,,,236,,,236,,,236,,,236',
+',,,,,236,,,,,,,,236,,,,,236,236,236,236,236,236,,,,236,236,,,,237,237',
+'237,236,237,,236,,237,237,,236,236,237,,237,237,237,237,237,237,237',
+',,,,,237,237,237,237,237,237,237,,,237,,,,,,,237,,,237,237,,237,237',
+'237,237,237,,237,237,237,,237,237,,237,237,,,,,,,,,,,,,,,,,,,,,,237',
+',,237,,,237,,,237,,,,,,237,,,,,,,,237,,,,,237,237,237,237,237,237,,',
+',237,237,,,,238,238,238,237,238,,237,,238,238,,237,237,238,,238,238',
+'238,238,238,238,238,,,,,,238,238,238,238,238,238,238,,,238,,,,,,,238',
+',,238,238,,238,238,238,238,238,,238,238,238,,238,238,,238,238,,,,,,',
+',,,,,,,,,,,,,,,238,,,238,,,238,,,238,,,,,,238,,,,,,,,238,,,,,238,238',
+'238,238,238,238,,,,238,238,,,,239,239,239,238,239,,238,,239,239,,238',
+'238,239,,239,239,239,239,239,239,239,,,,,,239,239,239,239,239,239,239',
+',,239,,,,,,,239,,,239,239,,239,239,239,239,239,,239,239,239,,239,239',
+',239,239,,,,,,,,,,,,,,,,,,,,,,239,,,239,,,239,,,239,,,,,,239,,,,,,,',
+'239,,,,,239,239,239,239,239,239,,,,239,239,,,,240,240,240,239,240,,239',
+',240,240,,239,239,240,,240,240,240,240,240,240,240,,,,,,240,240,240',
+'240,240,240,240,,,240,,,,,,,240,,,240,240,,240,240,240,240,240,,240',
+'240,240,,240,240,,240,240,,,,,,,,,,,,,,,,,,,,,,240,,,240,,,240,,,240',
+',,,,,240,,,,,,,,240,,,,,240,240,240,240,240,240,,,,240,240,,,,241,241',
+'241,240,241,,240,,241,241,,240,240,241,,241,241,241,241,241,241,241',
+',,,,,241,241,241,241,241,241,241,,,241,,,,,,,241,,,241,241,,241,241',
+'241,241,241,,241,241,241,,241,241,,241,241,,,,,,,,,,,,,,,,,,,,,,241',
+',,241,,,241,,,241,,,,,,241,,,,,,,,241,,,,,241,241,241,241,241,241,,',
+',241,241,,,,242,242,242,241,242,,241,,242,242,,241,241,242,,242,242',
+'242,242,242,242,242,,,,,,242,242,242,242,242,242,242,,,242,,,,,,,242',
+',,242,242,,242,242,242,242,242,,242,242,242,,242,242,,242,242,,,,,,',
+',,,,,,,,,,,,,,,242,,,242,,,242,,,242,,,,,,242,,,,,,,,242,,,,,242,242',
+'242,242,242,242,,,,242,242,,,,243,243,243,242,243,,242,,243,243,,242',
+'242,243,,243,243,243,243,243,243,243,,,,,,243,243,243,243,243,243,243',
+',,243,,,,,,,243,,,243,243,,243,243,243,243,243,,243,243,243,,243,243',
+',243,243,,,,,,,,,,,,,,,,,,,,,,243,,,243,,,243,,,243,,,,,,243,,,,,,,',
+'243,,,,,243,243,243,243,243,243,,,,243,243,,,,244,244,244,243,244,,243',
+',244,244,,243,243,244,,244,244,244,244,244,244,244,,,,,,244,244,244',
+'244,244,244,244,,,244,,,,,,,244,,,244,244,,244,244,244,244,244,,244',
+'244,244,,244,244,,244,244,,,,,,,,,,,,,,,,,,,,,,244,,,244,,,244,,,244',
+',,,,,244,,,,,,,,244,,,,,244,244,244,244,244,244,,,,244,244,,,,245,245',
+'245,244,245,,244,,245,245,,244,244,245,,245,245,245,245,245,245,245',
+',,,,,245,245,245,245,245,245,245,,,245,,,,,,,245,,,245,245,,245,245',
+'245,245,245,,245,245,245,,245,245,,245,245,,,,,,,,,,,,,,,,,,,,,,245',
+',,245,,,245,,,245,,,,,,245,,,,,,,,245,,,,,245,245,245,245,245,245,,',
+',245,245,,,,254,254,254,245,254,,245,,254,254,,245,245,254,,254,254',
+'254,254,254,254,254,,,,,,254,254,254,254,254,254,254,,,254,,,,,,,254',
+',,254,254,,254,254,254,254,254,,254,254,254,,254,254,,254,254,,,,,,',
+',,,,,,,,,,,,,,,254,,,254,,,254,,,254,,,,,,254,,,,,,,,254,,,,,254,254',
+'254,254,254,254,,,,254,254,,,,256,256,256,254,256,,254,,256,256,,254',
+'254,256,,256,256,256,256,256,256,256,,,,,,256,256,256,256,256,256,256',
+',,256,,,,,,,256,,,256,256,,256,256,256,256,256,,256,256,256,,256,256',
+',256,256,,,,,,,,,,,,,,,,,,,,,,256,,,256,,,256,,,256,,,,,,256,,,,,,,',
+'256,,,,,256,256,256,256,256,256,,,,256,256,,,,261,261,261,256,261,,256',
+',261,261,,256,256,261,,261,261,261,261,261,261,261,,,,,,261,261,261',
+'261,261,261,261,,,261,,,,,,,261,,,261,261,,261,261,261,261,261,,261',
+'261,261,,261,261,,261,261,,,,,,,,,,,,,,,,,,,,,,261,,,261,,,261,,,261',
+',,,,,261,,,,,,,,261,,,,,261,261,261,261,261,261,,,,261,261,,,,268,268',
+'268,261,268,,261,,268,268,,261,261,268,,268,268,268,268,268,268,268',
+',,,,,268,268,268,268,268,268,268,,,268,,,,,,,268,,,268,268,,268,268',
+'268,268,268,268,268,268,268,,268,268,,268,268,,,,,,,,,,,,,,,,,,,,,,268',
+',,268,,,268,,,268,,268,,268,,268,,,,,,,,268,,,,,268,268,268,268,268',
+'268,,,,268,268,,,,269,269,269,268,269,,268,,269,269,,268,268,269,,269',
+'269,269,269,269,269,269,,,,,,269,269,269,269,269,269,269,,,269,,,,,',
+',269,,,269,269,,269,269,269,269,269,269,269,269,269,,269,269,,269,269',
+',,,,,,,,,,,,,,,,,,,,,269,,,269,,,269,,,269,,269,,269,,269,,,,,,,,269',
+',,,,269,269,269,269,269,269,,,,269,269,,,,277,277,277,269,277,,269,',
+'277,277,,269,269,277,,277,277,277,277,277,277,277,,,,,,277,277,277,277',
+'277,277,277,,,277,,,,,,,277,,,277,277,,277,277,277,277,277,277,277,277',
+'277,,277,277,,277,277,,,,,,,,,,,,,,,,,,,,,,277,,,277,,277,277,,,277',
+',277,,277,,277,,,,,,,,277,,,,,277,277,277,277,277,277,,,,277,277,,,',
+',,,277,,,277,,,,,277,277,281,281,281,281,281,,,,281,281,,,,281,,281',
+'281,281,281,281,281,281,,,,,,281,281,281,281,281,281,281,,,281,,,,,',
+'281,281,,281,281,281,,281,281,281,281,281,,281,281,281,,281,281,,281',
+'281,,,,,,,,,,,,,,,,,,,,,,281,,,281,,,281,,,281,,281,,,,281,,,,,,,,281',
+',,,,281,281,281,281,281,281,,,,281,281,,,,285,285,285,281,285,,281,',
+'285,285,,281,281,285,,285,285,285,285,285,285,285,,,,,,285,285,285,285',
+'285,285,285,,,285,,,,,,,285,,,285,285,,285,285,285,285,285,,285,285',
+'285,,285,285,749,,749,749,749,749,749,,,,,,,,,,749,,,,,,,,285,,,285',
+',,285,,,285,,,,,,749,,,,,,,,749,749,749,749,,285,285,285,285,285,285',
+',,,285,285,,,,285,,,285,,,285,,,,,285,285,286,286,286,286,286,,,749',
+'286,286,,,,286,,286,286,286,286,286,286,286,,,,,,286,286,286,286,286',
+'286,286,,,286,,,,,,286,286,,286,286,286,,286,286,286,286,286,,286,286',
+'286,,286,286,,286,286,,,,,,,,,,,,,,,,,,,,,,286,,,286,,,286,,,286,,286',
+',,,286,,,,,,,,286,,,,,286,286,286,286,286,286,,,,286,286,,,,298,298',
+'298,286,298,,286,,298,298,,286,286,298,,298,298,298,298,298,298,298',
+',,,,,298,298,298,298,298,298,298,,,298,,,,,,,298,,,298,298,,298,298',
+'298,298,298,,298,298,298,,298,298,56,,56,56,56,,56,,,,,,,,,,,,,,,,,',
+'298,,,298,,,298,,,298,,,,,,56,56,,,,,,,56,56,56,56,,298,298,298,298',
+'298,298,,,,298,298,,,,307,307,307,298,307,,298,,307,307,,298,298,307',
+',307,307,307,307,307,307,307,,,,,,307,307,307,307,307,307,307,,,307',
+',,,,,,307,,,307,307,,307,307,307,307,307,,307,307,307,,307,307,,307',
+'307,,,,,,,,,,,,,,,,,,,,,,307,,,307,307,,307,,,307,,,,,,307,,,,,,,,307',
+',,,,307,307,307,307,307,307,,,,307,307,,,,,,,307,,,307,,,,,307,307,309',
+'309,309,309,309,,,,309,309,,,,309,,309,309,309,309,309,309,309,,,,,',
+'309,309,309,309,309,309,309,,,309,,,,,,309,309,,309,309,309,,309,309',
+'309,309,309,,309,309,309,,309,309,,309,309,,,,,,,,,,,,,,,,,,,,,,309',
+',,309,,,309,,,309,,309,,,,309,,,,,,,,309,,,,,309,309,309,309,309,309',
+',,,309,309,,,,349,349,349,309,349,,309,,349,349,,309,309,349,,349,349',
+'349,349,349,349,349,,,,,,349,349,349,349,349,349,349,,,349,,,,,,,349',
+',,349,349,,349,349,349,349,349,,349,349,349,,349,349,,349,349,,,,,,',
+',,,,,,,,,,,,,,,349,,,349,,,349,,,349,,,,,,349,,,,,,,,349,,,,,349,349',
+'349,349,349,349,,,,349,349,,,,350,350,350,349,350,,349,,350,350,,349',
+'349,350,,350,350,350,350,350,350,350,,,,,,350,350,350,350,350,350,350',
+',,350,,,,,,,350,,,350,350,,350,350,350,350,350,,350,350,350,,350,350',
+',350,350,,,,,,,,,,,,,,,,,,,,,,350,,,350,,,350,,,350,,,,,,350,,,,,,,',
+'350,,,,,350,350,350,350,350,350,,,,350,350,,,,369,369,369,350,369,,350',
+',369,369,,350,350,369,,369,369,369,369,369,369,369,,,,,,369,369,369',
+'369,369,369,369,,,369,,,,,,,369,,,369,369,,369,369,369,369,369,,369',
+'369,369,,369,369,322,,322,322,322,,322,,,,,,,,,,,,,,,,,,369,,,369,,',
+'369,,,369,,,,,,322,,322,,,,,,322,322,322,322,,369,369,369,369,369,369',
+',,,369,369,,,,381,381,381,369,381,,369,,381,381,,369,369,381,,381,381',
+'381,381,381,381,381,,,,,,381,381,381,381,381,381,381,,,381,,,,,,,381',
+',,381,381,,381,381,381,381,381,,381,381,381,,381,381,,381,381,,,,,,',
+',,,,,,,,,,,,,,,381,,,381,,,381,,,381,,,,,,381,,,,,,,,381,,,,,381,381',
+'381,381,381,381,,,,381,381,,,,421,421,421,381,421,,381,,421,421,,381',
+'381,421,,421,421,421,421,421,421,421,,,,,,421,421,421,421,421,421,421',
+',,421,,,,,,,421,,,421,421,,421,421,421,421,421,,421,421,421,,421,421',
+',421,421,,,,,,,,,,,,,,,,,,,,,,421,,,421,,,421,,,421,,,,,,421,,,,,,,',
+'421,,,,,421,421,421,421,421,421,,,,421,421,,,,432,432,432,421,432,,421',
+',432,432,,421,421,432,,432,432,432,432,432,432,432,,,,,,432,432,432',
+'432,432,432,432,,,432,,,,,,,432,,,432,432,,432,432,432,432,432,432,432',
+'432,432,,432,432,,432,432,,,,,,,,,,,,,,,,,,,,,,432,,,432,432,,432,,',
+'432,,432,,432,,432,,,,,,,,432,,,,,432,432,432,432,432,432,,,,432,432',
+',,,440,440,440,432,440,,432,,440,440,,432,432,440,,440,440,440,440,440',
+'440,440,,,,,,440,440,440,440,440,440,440,,,440,,,,,,,440,,,440,440,',
+'440,440,440,440,440,440,440,440,440,,440,440,,440,440,,,,,,,,,,,,,,',
+',,,,,,,440,,,440,440,,440,,,440,,440,,440,,440,,,,,,,,440,,,,,440,440',
+'440,440,440,440,,,,440,440,,,,441,441,441,440,441,,440,,441,441,,440',
+'440,441,,441,441,441,441,441,441,441,,,,,,441,441,441,441,441,441,441',
+',,441,,,,,,,441,,,441,441,,441,441,441,441,441,441,441,441,441,,441',
+'441,,441,441,,,,,,,,,,,,,,,,,,,,,,441,,,441,441,,441,,,441,,441,,441',
+',441,,,,,,,,441,,,,,441,441,441,441,441,441,,,,441,441,,,,442,442,442',
+'441,442,,441,,442,442,,441,441,442,,442,442,442,442,442,442,442,,,,',
+',442,442,442,442,442,442,442,,,442,,,,,,,442,,,442,442,,442,442,442',
+'442,442,442,442,442,442,,442,442,,442,442,,,,,,,,,,,,,,,,,,,,,,442,',
+',442,442,,442,,,442,,442,,442,,442,,,,,,,,442,,,,,442,442,442,442,442',
+'442,,,,442,442,,,,451,451,451,442,451,,442,,451,451,,442,442,451,,451',
+'451,451,451,451,451,451,,,,,,451,451,451,451,451,451,451,,,451,,,,,',
+',451,,,451,451,,451,451,451,451,451,451,451,451,451,,451,451,,451,451',
+',,,,,,,,,,,,,,,,,,,,,451,,,451,,,451,,,451,,451,,,,451,,,,,,,,451,,',
+',,451,451,451,451,451,451,,,,451,451,,,,452,452,452,451,452,,451,,452',
+'452,,451,451,452,,452,452,452,452,452,452,452,,,,,,452,452,452,452,452',
+'452,452,,,452,,,,,,,452,,,452,452,,452,452,452,452,452,452,452,452,452',
+',452,452,,452,452,,,,,,,,,,,,,,,,,,,,,,452,,,452,,,452,,,452,,452,,',
+',452,,,,,,,,452,,,,,452,452,452,452,452,452,,,,452,452,,,,454,454,454',
+'452,454,,452,,454,454,,452,452,454,,454,454,454,454,454,454,454,,,,',
+',454,454,454,454,454,454,454,,,454,,,,,,,454,,,454,454,,454,454,454',
+'454,454,,454,454,454,,454,454,,454,454,,,,,,,,,,,,,,,,,,,,,,454,,,454',
+',,454,,,454,,,,,,454,,,,,,,,454,,,,,454,454,454,454,454,454,,,,454,454',
+',,,455,455,455,454,455,,454,,455,455,,454,454,455,,455,455,455,455,455',
+'455,455,,,,,,455,455,455,455,455,455,455,,,455,,,,,,,455,,,455,455,',
+'455,455,455,455,455,,455,455,455,,455,455,,455,455,,,,,,,,,,,,,,,,,',
+',,,,455,,,455,,,455,,,455,,,,,,455,,,,,,,,455,,,,,455,455,455,455,455',
+'455,,,,455,455,,,,456,456,456,455,456,,455,,456,456,,455,455,456,,456',
+'456,456,456,456,456,456,,,,,,456,456,456,456,456,456,456,,,456,,,,,',
+',456,,,456,456,,456,456,456,456,456,,456,456,456,,456,456,,456,456,',
+',,,,,,,,,,,,,,,,,,,,456,,,456,,,456,,,456,,,,,,456,,,,,,,,456,,,,,456',
+'456,456,456,456,456,,,,456,456,,,,487,487,487,456,487,,456,,487,487',
+',456,456,487,,487,487,487,487,487,487,487,,,,,,487,487,487,487,487,487',
+'487,,,487,,,,,,,487,,,487,487,,487,487,487,487,487,487,487,487,487,',
+'487,487,,487,487,,,,,,,,,,,,,,,,,,,,,,487,,,487,,,487,,,487,,487,,487',
+',487,,,,,,,,487,,,,,487,487,487,487,487,487,,,,487,487,,,,489,489,489',
+'487,489,,487,,489,489,,487,487,489,,489,489,489,489,489,489,489,,,,',
+',489,489,489,489,489,489,489,,,489,,,,,,,489,,,489,489,,489,489,489',
+'489,489,489,489,489,489,,489,489,,489,489,,,,,,,,,,,,,,,,,,,,,,489,',
+',489,,,489,,,489,,,,489,,489,,,,,,,,489,,,,,489,489,489,489,489,489',
+',,,489,489,,,,491,491,491,489,491,,489,,491,491,,489,489,491,,491,491',
'491,491,491,491,491,,,,,,491,491,491,491,491,491,491,,,491,,,,,,,491',
',,491,491,,491,491,491,491,491,,491,491,491,,491,491,,491,491,,,,,,',
',,,,,,,,,,,,,,,491,,,491,,,491,,,491,,,,,,491,,,,,,,,491,,,,,491,491',
-'491,491,491,491,,,,491,491,,,,489,489,489,491,489,,491,,489,489,,491',
-'491,489,,489,489,489,489,489,489,489,,,,,,489,489,489,489,489,489,489',
-',,489,,,,,,,489,,,489,489,,489,489,489,489,489,489,489,489,489,,489',
-'489,,489,489,,,,,,,,,,,,,,,,,,,,,,489,,,489,,,489,,,489,,,,489,,489',
-',,,,,,,489,,,,,489,489,489,489,489,489,,,,489,489,,,,487,487,487,489',
-'487,,489,,487,487,,489,489,487,,487,487,487,487,487,487,487,,,,,,487',
-'487,487,487,487,487,487,,,487,,,,,,,487,,,487,487,,487,487,487,487,487',
-'487,487,487,487,,487,487,,487,487,,,,,,,,,,,,,,,,,,,,,,487,,,487,,,487',
-',,487,,487,,487,,487,,,,,,,,487,,,,438,487,487,487,487,487,487,438,438',
-'438,487,487,,438,438,,438,,487,,,487,,,,,487,487,,,,,,,,,438,438,,438',
-'438,438,438,438,,,,,,,,,,,,,,,,,,,,,,,,438,438,438,438,438,438,438,438',
-'438,438,438,438,438,438,438,,,438,438,438,,438,,,,438,,,,,,,438,,438',
-',438,438,438,438,438,438,438,,438,,438,,,,,,,,,,,,,438,438,,438,,438',
-'644,,438,,438,,438,644,644,644,,,644,644,644,,644,,,,,,,,,644,644,644',
-',,,,,,,,644,644,,644,644,644,644,644,,,,,,,,,,,,,,,,,,,,,,,,644,644',
-'644,644,644,644,644,644,644,644,644,644,644,644,644,,,644,644,644,,644',
-'644,,,644,,,644,,644,,644,,644,,644,644,644,644,644,644,644,,644,644',
-'644,,,,,,,,,,,,,644,644,644,644,,644,645,,644,,644,,644,645,645,645',
-',,645,645,645,,645,,,,,,,,,,645,645,,,,,,,,,645,645,,645,645,645,645',
-'645,,,,,,,,,,,,,,,,,,,,,,,,645,645,645,645,645,645,645,645,645,645,645',
-'645,645,645,645,,,645,645,645,,645,645,,,645,,,645,,645,,645,,645,,645',
-'645,645,645,645,645,645,,645,,645,,,,,,,,,,,,,645,645,645,645,,645,436',
-',645,,645,,645,436,436,436,,,,436,436,,436,,,,,,,,,436,,,,,,,,,,,436',
-'436,,436,436,436,436,436,,,,,,,,,,,,,,,,,,,,,,,,436,436,436,436,436',
-'436,436,436,436,436,436,436,436,436,436,,,436,436,436,,436,,,,436,,',
-',,,,436,,436,,436,436,436,436,436,436,436,,436,436,436,,,,,,,,,,,,,436',
-'436,,436,,436,50,,436,,436,,436,50,50,50,,,50,50,50,,50,,,,,,,,,,50',
-'50,50,,,,,,,,50,50,,50,50,50,50,50,,,,,,,,,,,,,,,,,,,,,,,,50,50,50,50',
-'50,50,50,50,50,50,50,50,50,50,50,,,50,50,50,,,50,,,50,,,50,,50,,50,',
-'50,,50,50,50,50,50,50,50,,50,,50,,,,,,,,,,,,,50,50,50,50,28,50,,50,50',
-',50,28,28,28,,,28,28,28,,28,,,,,,,,,,28,28,,,,,,,,,28,28,,28,28,28,28',
-'28,,,,,,,,,,,,,,,,,,,,,,,,28,28,28,28,28,28,28,28,28,28,28,28,28,28',
-'28,,,28,28,28,,,28,,28,28,,,28,,28,,28,,28,,28,28,28,28,28,28,28,,28',
-',28,,,,,,,,,,,,,28,28,28,28,495,28,,,28,,28,495,495,495,,,495,495,495',
-',495,,,,,,,,,,495,,,,,,,,,,495,495,,495,495,495,495,495,,,,,,,,,,,,',
-',496,,,,,,,496,496,496,,,496,496,496,,496,,,,,495,495,,,,496,,,495,',
-',,,495,495,496,496,,496,496,496,496,496,,,,,,,,,,,,,495,,,,,,,,,,,,494',
-'495,,495,,,495,494,494,494,496,496,494,494,494,,494,,496,,,,,496,496',
-',494,,,,,,,,,,494,494,,494,494,494,494,494,,496,,,,,,202,202,,,202,',
-',496,,496,,,496,202,202,,202,202,202,202,202,202,202,,,202,202,494,494',
-',,202,202,202,202,494,,,,,494,494,,,,,,202,202,,202,202,202,202,202',
-'202,202,202,202,202,202,,494,202,,,,,,,,,,,,494,,494,,,494,411,411,411',
-'411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411',
-'411,411,411,411,,,,411,411,411,411,411,411,411,411,411,411,411,411,411',
-'411,411,411,411,411,411,411,411,,411,411,,,411,,,,,,,,,411,411,,411',
-'411,411,411,411,411,411,,,411,411,,,,,411,411,411,411,,,,,,,,,,,,,411',
-'411,,411,411,411,411,411,411,411,411,411,411,411,,,411,411,,,,,,,,,',
-'411,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415',
-'415,415,415,415,415,415,415,415,,,,415,415,415,415,415,415,415,415,415',
-'415,415,415,415,415,415,415,415,415,415,415,415,,415,415,,,415,,,,,',
-',,,415,415,,415,415,415,415,415,415,415,,,415,415,,,,,415,415,415,415',
-',,,,,,,,,,,,415,415,,415,415,415,415,415,415,415,415,415,415,415,,,415',
-'415,,,,,,,,,,415,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,,,',
-'8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,,8,8,,,8,,,,,,,,,8,8,,8,8',
-'8,8,8,8,8,,,8,8,,,,,8,8,8,8,,,,,,,,,,,,,8,8,,8,8,8,8,8,8,8,8,8,8,8,',
-',8,8,,,,,,,,,,8,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,,,,7',
+'491,491,491,491,,,,491,491,,,,506,506,506,491,506,,491,,506,506,,491',
+'491,506,,506,506,506,506,506,506,506,,,,,,506,506,506,506,506,506,506',
+',,506,,,,,,,506,,,506,506,,506,506,506,506,506,,506,506,506,,506,506',
+',506,506,,,,,,,,,,,,,,,,,,,,,,506,,,506,,506,506,,,506,,,,506,,506,',
+',,,,,,506,,,,,506,506,506,506,506,506,,,,506,506,,,,,,,506,,,506,,,',
+',506,506,512,512,512,512,512,,,,512,512,,,,512,,512,512,512,512,512',
+'512,512,,,,,,512,512,512,512,512,512,512,,,512,,,,,,512,512,,512,512',
+'512,,512,512,512,512,512,,512,512,512,,512,512,,512,512,,,,,,,,,,,,',
+',,,,,,,,,512,,,512,,,512,,,512,,512,,,,512,,,,,,,,512,,,,,512,512,512',
+'512,512,512,,,,512,512,,,,,,512,512,,,512,,,,,512,512,518,518,518,,518',
+',,,518,518,,,,518,,518,518,518,518,518,518,518,,,,,,518,518,518,518',
+'518,518,518,,,518,,,,,,,518,,,518,518,,518,518,518,518,518,,518,518',
+'518,,518,518,559,,559,559,559,,559,,,,,,,,,,,,,,,,,,518,,,518,,,518',
+',,518,,,,,,559,,,,,,,,559,559,559,559,,518,518,518,518,518,518,,,,518',
+'518,,,,520,520,520,518,520,,518,,520,520,,518,518,520,,520,520,520,520',
+'520,520,520,,,,,,520,520,520,520,520,520,520,,,520,,,,,,,520,,,520,520',
+',520,520,520,520,520,520,520,520,520,,520,520,,520,520,,,,,,,,,,,,,',
+',,,,,,,,520,,,520,,,520,,,520,,520,,,,520,,,,,,,,520,,,,,520,520,520',
+'520,520,520,,,,520,520,,,,523,523,523,520,523,,520,,523,523,,520,520',
+'523,,523,523,523,523,523,523,523,,,,,,523,523,523,523,523,523,523,,',
+'523,,,,,,,523,,,523,523,,523,523,523,523,523,523,523,523,523,,523,523',
+',523,523,,,,,,,,,,,,,,,,,,,,,,523,,,523,,,523,,,523,,523,,,,523,,,,',
+',,,523,,,,,523,523,523,523,523,523,,,,523,523,,,,531,531,531,523,531',
+',523,,531,531,,523,523,531,,531,531,531,531,531,531,531,,,,,,531,531',
+'531,531,531,531,531,,,531,,,,,,,531,,,531,531,,531,531,531,531,531,',
+'531,531,531,,531,531,,531,531,,,,,,,,,,,,,,,,,,,,,,531,,,531,,,531,',
+',531,,,,,,531,,,,,,,,531,,,,,531,531,531,531,531,531,,,,531,531,,,,532',
+'532,532,531,532,,531,,532,532,,531,531,532,,532,532,532,532,532,532',
+'532,,,,,,532,532,532,532,532,532,532,,,532,,,,,,,532,,,532,532,,532',
+'532,532,532,532,,532,532,532,,532,532,,532,532,,,,,,,,,,,,,,,,,,,,,',
+'532,,,532,,,532,,,532,,,,,,532,,,,,,,,532,,,,,532,532,532,532,532,532',
+',,,532,532,,,,533,533,533,532,533,,532,,533,533,,532,532,533,,533,533',
+'533,533,533,533,533,,,,,,533,533,533,533,533,533,533,,,533,,,,,,,533',
+',,533,533,,533,533,533,533,533,,533,533,533,,533,533,,533,533,,,,,,',
+',,,,,,,,,,,,,,,533,,,533,,,533,,,533,,,,,,533,,,,,,,,533,,,,,533,533',
+'533,533,533,533,,,,533,533,,,,537,537,537,533,537,,533,,537,537,,533',
+'533,537,,537,537,537,537,537,537,537,,,,,,537,537,537,537,537,537,537',
+',,537,,,,,,,537,,,537,537,,537,537,537,537,537,,537,537,537,,537,537',
+',537,537,,,,,,,,,,,,,,,,,,,,,,537,,,537,,,537,,,537,,,,,,537,,,,,,,',
+'537,,,,,537,537,537,537,537,537,,,,537,537,,,,543,543,543,537,543,,537',
+',543,543,,537,537,543,,543,543,543,543,543,543,543,,,,,,543,543,543',
+'543,543,543,543,,,543,,,,,,,543,,,543,543,,543,543,543,543,543,543,543',
+'543,543,,543,543,,543,543,,,,,,,,,,,,,,,,,,,,,,543,,,543,,,543,,,543',
+',543,,,,543,,,,,,,,543,,,,,543,543,543,543,543,543,,,,543,543,,,,546',
+'546,546,543,546,,543,,546,546,,543,543,546,,546,546,546,546,546,546',
+'546,,,,,,546,546,546,546,546,546,546,,,546,,,,,,,546,,,546,546,,546',
+'546,546,546,546,546,546,546,546,,546,546,,546,546,,,,,,,,,,,,,,,,,,',
+',,,546,,,546,,,546,,,546,,,,,,546,,,,,,,,546,,,,,546,546,546,546,546',
+'546,,,,546,546,,,,,,,546,,,546,,,,,546,546,551,551,551,551,551,,,,551',
+'551,,,,551,,551,551,551,551,551,551,551,,,,,,551,551,551,551,551,551',
+'551,,,551,,,,,,551,551,,551,551,551,,551,551,551,551,551,,551,551,551',
+',551,551,,551,551,,,,,,,,,,,,,,,,,,,,,,551,,,551,,,551,,,551,,551,,',
+',551,,,,,,,,551,,,,,551,551,551,551,551,551,,,,551,551,,,,,,,551,,,551',
+',,,,551,551,552,552,552,552,552,,,,552,552,,,,552,,552,552,552,552,552',
+'552,552,,,,,,552,552,552,552,552,552,552,,,552,,,,,,552,552,,552,552',
+'552,,552,552,552,552,552,,552,552,552,,552,552,,552,552,,,,,,,,,,,,',
+',,,,,,,,,552,,,552,,,552,,,552,,552,,,,552,,,,,,,,552,,,,,552,552,552',
+'552,552,552,,,,552,552,,,,558,558,558,552,558,,552,,558,558,,552,552',
+'558,,558,558,558,558,558,558,558,,,,,,558,558,558,558,558,558,558,,',
+'558,,,,,,,558,,,558,558,,558,558,558,558,558,,558,558,558,,558,558,856',
+',856,856,856,856,856,,,,,,,,,,856,,,,,,,,558,,,558,,,558,,,558,,,,,',
+'856,,,,,,,,856,856,856,856,,558,558,558,558,558,558,,,,558,558,,,,,',
+',558,,,558,,,,,558,558,572,572,572,572,572,,,856,572,572,,,,572,,572',
+'572,572,572,572,572,572,,,,,,572,572,572,572,572,572,572,,,572,,,,,',
+'572,572,,572,572,572,,572,572,572,572,572,,572,572,572,,572,572,,572',
+'572,,,,,,,,,,,,,,,,,,,,,,572,,,572,,,572,,,572,,572,,,,572,,,,,,,,572',
+',,,,572,572,572,572,572,572,,,,572,572,,,,,,,572,,,572,,,,,572,572,576',
+'576,576,576,576,,,,576,576,,,,576,,576,576,576,576,576,576,576,,,,,',
+'576,576,576,576,576,576,576,,,576,,,,,,576,576,,576,576,576,,576,576',
+'576,576,576,,576,576,576,,576,576,,576,576,,,,,,,,,,,,,,,,,,,,,,576',
+',,576,,,576,,,576,,576,,,,576,,,,,,,,576,,,,,576,576,576,576,576,576',
+',,,576,576,,,,,,,576,,,576,,,,,576,576,581,581,581,581,581,,,,581,581',
+',,,581,,581,581,581,581,581,581,581,,,,,,581,581,581,581,581,581,581',
+',,581,,,,,,581,581,,581,581,581,,581,581,581,581,581,,581,581,581,,581',
+'581,,581,581,,,,,,,,,,,,,,,,,,,,,,581,,,581,,,581,,,581,,581,,,,581',
+',,,,,,,581,,,,,581,581,581,581,581,581,,,,581,581,,,,583,583,583,581',
+'583,,581,,583,583,,581,581,583,,583,583,583,583,583,583,583,,,,,,583',
+'583,583,583,583,583,583,,,583,,,,,,,583,,,583,583,,583,583,583,583,583',
+'583,583,583,583,,583,583,,583,583,,,,,,,,,,,,,,,,,,,,,,583,,,583,,,583',
+',,583,,583,,,,583,,,,,,,,583,,,,,583,583,583,583,583,583,,,,583,583',
+',,,586,586,586,583,586,,583,,586,586,,583,583,586,,586,586,586,586,586',
+'586,586,,,,,,586,586,586,586,586,586,586,,,586,,,,,,,586,,,586,586,',
+'586,586,586,586,586,586,586,586,586,,586,586,,586,586,,,,,,,,,,,,,,',
+',,,,,,,586,,,586,,,586,,,586,,586,,,,586,,,,,,,,586,,,,,586,586,586',
+'586,586,586,,,,586,586,,,,592,592,592,586,592,,586,,592,592,,586,586',
+'592,,592,592,592,592,592,592,592,,,,,,592,592,592,592,592,592,592,,',
+'592,,,,,,,592,,,592,592,,592,592,592,592,592,592,592,592,592,,592,592',
+',592,592,,,,,,,,,,,,,,,,,,,,,,592,,,592,,,592,,,592,,592,,,,592,,,,',
+',,,592,,,,,592,592,592,592,592,592,,,,592,592,,,,596,596,596,592,596',
+',592,,596,596,,592,592,596,,596,596,596,596,596,596,596,,,,,,596,596',
+'596,596,596,596,596,,,596,,,,,,,596,,,596,596,,596,596,596,596,596,',
+'596,596,596,,596,596,,596,596,,,,,,,,,,,,,,,,,,,,,,596,,,596,,,596,',
+',596,,,,,,596,,,,,,,,596,,,,,596,596,596,596,596,596,,,,596,596,,,,598',
+'598,598,596,598,,596,,598,598,,596,596,598,,598,598,598,598,598,598',
+'598,,,,,,598,598,598,598,598,598,598,,,598,,,,,,,598,,,598,598,,598',
+'598,598,598,598,,598,598,598,,598,598,,598,598,,,,,,,,,,,,,,,,,,,,,',
+'598,,,598,,,598,,,598,,,,,,598,,,,,,,,598,,,,,598,598,598,598,598,598',
+',,,598,598,,,,625,625,625,598,625,,598,,625,625,,598,598,625,,625,625',
+'625,625,625,625,625,,,,,,625,625,625,625,625,625,625,,,625,,,,,,,625',
+',,625,625,,625,625,625,625,625,,625,625,625,,625,625,,625,625,,,,,,',
+',,,,,,,,,,,,,,,625,,,625,,,625,,,625,,,,,,625,,,,,,,,625,,,,,625,625',
+'625,625,625,625,,,,625,625,,,,627,627,627,625,627,,625,,627,627,,625',
+'625,627,,627,627,627,627,627,627,627,,,,,,627,627,627,627,627,627,627',
+',,627,,,,,,,627,,,627,627,,627,627,627,627,627,,627,627,627,,627,627',
+',627,627,,,,,,,,,,,,,,,,,,,,,,627,,,627,,,627,,,627,,627,,,,627,,,,',
+',,,627,,,,,627,627,627,627,627,627,,,,627,627,,,,630,630,630,627,630',
+',627,,630,630,,627,627,630,,630,630,630,630,630,630,630,,,,,,630,630',
+'630,630,630,630,630,,,630,,,,,,,630,,,630,630,,630,630,630,630,630,',
+'630,630,630,,630,630,,630,630,,,,,,,,,,,,,,,,,,,,,,630,,,630,,,630,',
+',630,,,,,,630,,,,,,,,630,,,,,630,630,630,630,630,630,,,,630,630,,,,631',
+'631,631,630,631,,630,,631,631,,630,630,631,,631,631,631,631,631,631',
+'631,,,,,,631,631,631,631,631,631,631,,,631,,,,,,,631,,,631,631,,631',
+'631,631,631,631,,631,631,631,,631,631,,631,631,,,,,,,,,,,,,,,,,,,,,',
+'631,,,631,,,631,,,631,,,,,,631,,,,,,,,631,,,,,631,631,631,631,631,631',
+',,,631,631,,,,636,636,636,631,636,,631,,636,636,,631,631,636,,636,636',
+'636,636,636,636,636,,,,,,636,636,636,636,636,636,636,,,636,,,,,,,636',
+',,636,636,,636,636,636,636,636,,636,636,636,,636,636,,636,636,,,,,,',
+',,,,,,,,,,,,,,,636,,,636,,,636,,,636,,,,,,636,,,,,,,,636,,,,,636,636',
+'636,636,636,636,,,,636,636,,,,639,639,639,636,639,,636,,639,639,,636',
+'636,639,,639,639,639,639,639,639,639,,,,,,639,639,639,639,639,639,639',
+',,639,,,,,,,639,,,639,639,,639,639,639,639,639,,639,639,639,,639,639',
+',639,639,,,,,,,,,,,,,,,,,,,,,,639,,,639,,,639,,,639,,,,,,639,,,,,,,',
+'639,,,,,639,639,639,639,639,639,,,,639,639,,,,650,650,650,639,650,,639',
+',650,650,,639,639,650,,650,650,650,650,650,650,650,,,,,,650,650,650',
+'650,650,650,650,,,650,,,,,,,650,,,650,650,,650,650,650,650,650,,650',
+'650,650,,650,650,,650,650,,,,,,,,,,,,,,,,,,,,,,650,,,650,,,650,,,650',
+',,,,,650,,,,,,,,650,,,,,650,650,650,650,650,650,,,,650,650,,,,,,,650',
+',,650,,,,,650,650,654,654,654,654,654,,,,654,654,,,,654,,654,654,654',
+'654,654,654,654,,,,,,654,654,654,654,654,654,654,,,654,,,,,,654,654',
+',654,654,654,,654,654,654,654,654,,654,654,654,,654,654,,654,654,,,',
+',,,,,,,,,,,,,,,,,,654,,,654,,,654,,,654,,654,,,,654,,,,,,,,654,,,,,654',
+'654,654,654,654,654,,,,654,654,,,,658,658,658,654,658,,654,,658,658',
+',654,654,658,,658,658,658,658,658,658,658,,,,,,658,658,658,658,658,658',
+'658,,,658,,,,,,,658,,,658,658,,658,658,658,658,658,,658,658,658,,658',
+'658,,658,658,,,,,,,,,,,,,,,,,,,,,,658,,,658,,,658,,,658,,,,,,658,,,',
+',,,,658,,,,,658,658,658,658,658,658,,,,658,658,,,,,,,658,,,658,,,,,658',
+'658,667,667,667,667,667,,,,667,667,,,,667,,667,667,667,667,667,667,667',
+',,,,,667,667,667,667,667,667,667,,,667,,,,,,667,667,,667,667,667,,667',
+'667,667,667,667,,667,667,667,,667,667,,667,667,,,,,,,,,,,,,,,,,,,,,',
+'667,,,667,,,667,,,667,,667,,,,667,,,,,,,,667,,,,,667,667,667,667,667',
+'667,,,,667,667,,,,670,670,670,667,670,,667,,670,670,,667,667,670,,670',
+'670,670,670,670,670,670,,,,,,670,670,670,670,670,670,670,,,670,,,,,',
+',670,,,670,670,,670,670,670,670,670,670,670,670,670,,670,670,,670,670',
+',,,,,,,,,,,,,,,,,,,,,670,,,670,,,670,,,670,,670,,670,,670,,,,,,,,670',
+',,,,670,670,670,670,670,670,,,,670,670,,,,671,671,671,670,671,,670,',
+'671,671,,670,670,671,,671,671,671,671,671,671,671,,,,,,671,671,671,671',
+'671,671,671,,,671,,,,,,,671,,,671,671,,671,671,671,671,671,671,671,671',
+'671,,671,671,,671,671,,,,,,,,,,,,,,,,,,,,,,671,,,671,,,671,,,671,,,',
+'671,,671,,,,,,,,671,,,,,671,671,671,671,671,671,,,,671,671,,,,,,,671',
+',,671,,,,,671,671,677,677,677,677,677,,,,677,677,,,,677,,677,677,677',
+'677,677,677,677,,,,,,677,677,677,677,677,677,677,,,677,,,,,,677,677',
+',677,677,677,,677,677,677,677,677,,677,677,677,,677,677,,677,677,,,',
+',,,,,,,,,,,,,,,,,,677,,,677,,,677,,,677,,677,,,,677,,,,,,,,677,,,,,677',
+'677,677,677,677,677,,,,677,677,,,,,,,677,,,677,,,,,677,677,678,678,678',
+'678,678,,,,678,678,,,,678,,678,678,678,678,678,678,678,,,,,,678,678',
+'678,678,678,678,678,,,678,,,,,,678,678,,678,678,678,,678,678,678,678',
+'678,,678,678,678,,678,678,,678,678,,,,,,,,,,,,,,,,,,,,,,678,,,678,,',
+'678,,,678,,678,,,,678,,,,,,,,678,,,,,678,678,678,678,678,678,,,,678',
+'678,,,,682,682,682,678,682,,678,,682,682,,678,678,682,,682,682,682,682',
+'682,682,682,,,,,,682,682,682,682,682,682,682,,,682,,,,,,,682,,,682,682',
+',682,682,682,682,682,,682,682,682,,682,682,,,,,,,,,,,,,,,,,,,,,,,,,682',
+',,682,,,682,,,682,,,,,,,,,,,,,,,,,,,682,682,682,682,682,682,,,,682,682',
+',,,694,694,694,682,694,,682,,694,694,,682,682,694,,694,694,694,694,694',
+'694,694,,,,,,694,694,694,694,694,694,694,,,694,,,,,,,694,,,694,694,',
+'694,694,694,694,694,,694,694,694,,694,694,,,,,,,,,,,,,,,,,,,,,,,,,694',
+',,694,,,694,,,694,,,,,,,,,,,,,,,,,,,694,694,694,694,694,694,,,,694,694',
+',,,700,700,700,694,700,,694,,700,700,,694,694,700,,700,700,700,700,700',
+'700,700,,,,,,700,700,700,700,700,700,700,,,700,,,,,,,700,,,700,700,',
+'700,700,700,700,700,,700,700,700,,700,700,,700,700,,,,,,,,,,,,,,,,,',
+',,,,700,,,700,,,700,,,700,,700,,,,700,,,,,,,,700,,,,,700,700,700,700',
+'700,700,,,,700,700,,,,731,731,731,700,731,,700,,731,731,,700,700,731',
+',731,731,731,731,731,731,731,,,,,,731,731,731,731,731,731,731,,,731',
+',,,,,,731,,,731,731,,731,731,731,731,731,,731,731,731,,731,731,,731',
+'731,,,,,,,,,,,,,,,,,,,,,,731,,,731,,,731,,,731,,731,,,,731,,,,,,,,731',
+',,,,731,731,731,731,731,731,,,,731,731,,,,738,738,738,731,738,,731,',
+'738,738,,731,731,738,,738,738,738,738,738,738,738,,,,,,738,738,738,738',
+'738,738,738,,,738,,,,,,,738,,,738,738,,738,738,738,738,738,,738,738',
+'738,,738,738,,738,738,,,,,,,,,,,,,,,,,,,,,,738,,,738,,,738,,,738,,,',
+',,738,,,,,,,,738,,,,,738,738,738,738,738,738,,,,738,738,,,,,,,738,,',
+'738,,,,,738,738,743,743,743,743,743,,,,743,743,,,,743,,743,743,743,743',
+'743,743,743,,,,,,743,743,743,743,743,743,743,,,743,,,,,,743,743,,743',
+'743,743,,743,743,743,743,743,,743,743,743,,743,743,,743,743,,,,,,,,',
+',,,,,,,,,,,,,743,,,743,,,743,,,743,,743,,,,743,,,,,,,,743,,,,,743,743',
+'743,743,743,743,,,,743,743,,,,,,,743,,,743,,,,,743,743,747,747,747,747',
+'747,,,,747,747,,,,747,,747,747,747,747,747,747,747,,,,,,747,747,747',
+'747,747,747,747,,,747,,,,,,747,747,,747,747,747,,747,747,747,747,747',
+',747,747,747,,747,747,,747,747,,,,,,,,,,,,,,,,,,,,,,747,,,747,,,747',
+',,747,,747,,,,747,,,,,,,,747,,,,,747,747,747,747,747,747,,,,747,747',
+',,,,,,747,,,747,,,,,747,747,748,748,748,748,748,,,,748,748,,,,748,,748',
+'748,748,748,748,748,748,,,,,,748,748,748,748,748,748,748,,,748,,,,,',
+'748,748,,748,748,748,,748,748,748,748,748,,748,748,748,,748,748,,748',
+'748,,,,,,,,,,,,,,,,,,,,,,748,,,748,,,748,,,748,,748,,,,748,,,,,,,,748',
+',,,,748,748,748,748,748,748,,,,748,748,,,,755,755,755,748,755,,748,',
+'755,755,,748,748,755,,755,755,755,755,755,755,755,,,,,,755,755,755,755',
+'755,755,755,,,755,,,,,,,755,,,755,755,,755,755,755,755,755,,755,755',
+'755,,755,755,,755,755,,,,,,,,,,,,,,,,,,,,,,755,,,755,,,755,,,755,,,',
+',,755,,,,,,,,755,,,,,755,755,755,755,755,755,,,,755,755,,,,,,,755,,',
+'755,,,,,755,755,769,769,769,769,769,,,,769,769,,,,769,,769,769,769,769',
+'769,769,769,,,,,,769,769,769,769,769,769,769,,,769,,,,,,769,769,,769',
+'769,769,,769,769,769,769,769,,769,769,769,,769,769,,769,769,,,,,,,,',
+',,,,,,,,,,,,,769,,,769,,,769,,,769,,769,,,,769,,,,,,,,769,,,,,769,769',
+'769,769,769,769,,,,769,769,,,,775,775,775,769,775,,769,,775,775,,769',
+'769,775,,775,775,775,775,775,775,775,,,,,,775,775,775,775,775,775,775',
+',,775,,,,,,,775,,,775,775,,775,775,775,775,775,,775,775,775,,775,775',
+',775,775,,,,,,,,,,,,,,,,,,,,,,775,,,775,,,775,,,775,,,,,,775,,,,,,,',
+'775,,,,,775,775,775,775,775,775,,,,775,775,,,,776,776,776,775,776,,775',
+',776,776,,775,775,776,,776,776,776,776,776,776,776,,,,,,776,776,776',
+'776,776,776,776,,,776,,,,,,,776,,,776,776,,776,776,776,776,776,,776',
+'776,776,,776,776,,776,776,,,,,,,,,,,,,,,,,,,,,,776,,,776,,,776,,,776',
+',,,,,776,,,,,,,,776,,,,,776,776,776,776,776,776,,,,776,776,,,,777,777',
+'777,776,777,,776,,777,777,,776,776,777,,777,777,777,777,777,777,777',
+',,,,,777,777,777,777,777,777,777,,,777,,,,,,,777,,,777,777,,777,777',
+'777,777,777,,777,777,777,,777,777,,777,777,,,,,,,,,,,,,,,,,,,,,,777',
+',,777,,,777,,,777,,,,,,777,,,,,,,,777,,,,,777,777,777,777,777,777,,',
+',777,777,,,,788,788,788,777,788,,777,,788,788,,777,777,788,,788,788',
+'788,788,788,788,788,,,,,,788,788,788,788,788,788,788,,,788,,,,,,,788',
+',,788,788,,788,788,788,788,788,,788,788,788,,788,788,,788,788,,,,,,',
+',,,,,,,,,,,,,,,788,,,788,,,788,,,788,,,,,,788,,,,,,,,788,,,,,788,788',
+'788,788,788,788,,,,788,788,,,,789,789,789,788,789,,788,,789,789,,788',
+'788,789,,789,789,789,789,789,789,789,,,,,,789,789,789,789,789,789,789',
+',,789,,,,,,,789,,,789,789,,789,789,789,789,789,,789,789,789,,789,789',
+',789,789,,,,,,,,,,,,,,,,,,,,,,789,,,789,,,789,,,789,,,,,,789,,,,,,,',
+'789,,,,,789,789,789,789,789,789,,,,789,789,,,,790,790,790,789,790,,789',
+',790,790,,789,789,790,,790,790,790,790,790,790,790,,,,,,790,790,790',
+'790,790,790,790,,,790,,,,,,,790,,,790,790,,790,790,790,790,790,,790',
+'790,790,,790,790,,790,790,,,,,,,,,,,,,,,,,,,,,,790,,,790,,,790,,,790',
+',,,,,790,,,,,,,,790,,,,,790,790,790,790,790,790,,,,790,790,,,,802,802',
+'802,790,802,,790,,802,802,,790,790,802,,802,802,802,802,802,802,802',
+',,,,,802,802,802,802,802,802,802,,,802,,,,,,,802,,,802,802,,802,802',
+'802,802,802,,802,802,802,,802,802,,802,802,,,,,,,,,,,,,,,,,,,,,,802',
+',,802,,,802,,,802,,802,,,,802,,,,,,,,802,,,,,802,802,802,802,802,802',
+',,,802,802,,,,,,,802,,,802,,,,,802,802,813,813,813,813,813,,,,813,813',
+',,,813,,813,813,813,813,813,813,813,,,,,,813,813,813,813,813,813,813',
+',,813,,,,,,813,813,,813,813,813,,813,813,813,813,813,,813,813,813,,813',
+'813,,813,813,,,,,,,,,,,,,,,,,,,,,,813,,,813,,,813,,,813,,813,,,,813',
+',,,,,,,813,,,,,813,813,813,813,813,813,,,,813,813,,,,832,832,832,813',
+'832,,813,,832,832,,813,813,832,,832,832,832,832,832,832,832,,,,,,832',
+'832,832,832,832,832,832,,,832,,,,,,,832,,,832,832,,832,832,832,832,832',
+',832,832,832,,832,832,,832,832,,,,,,,,,,,,,,,,,,,,,,832,,,832,,,832',
+',,832,,,,,,832,,,,,,,,832,,,,,832,832,832,832,832,832,,,,832,832,,,',
+',,,832,,,832,,,,,832,832,834,834,834,834,834,,,,834,834,,,,834,,834',
+'834,834,834,834,834,834,,,,,,834,834,834,834,834,834,834,,,834,,,,,',
+'834,834,,834,834,834,,834,834,834,834,834,,834,834,834,,834,834,,834',
+'834,,,,,,,,,,,,,,,,,,,,,,834,,,834,,,834,,,834,,834,,,,834,,,,,,,,834',
+',,,,834,834,834,834,834,834,,,,834,834,,,,,,,834,,,834,,,,,834,834,835',
+'835,835,835,835,,,,835,835,,,,835,,835,835,835,835,835,835,835,,,,,',
+'835,835,835,835,835,835,835,,,835,,,,,,835,835,,835,835,835,,835,835',
+'835,835,835,,835,835,835,,835,835,,835,835,,,,,,,,,,,,,,,,,,,,,,835',
+',,835,,,835,,,835,,835,,,,835,,,,,,,,835,,,,,835,835,835,835,835,835',
+',,,835,835,,,,862,862,862,835,862,,835,,862,862,,835,835,862,,862,862',
+'862,862,862,862,862,,,,,,862,862,862,862,862,862,862,,,862,,,,,,,862',
+',,862,862,,862,862,862,862,862,,862,862,862,,862,862,,862,862,,,,,,',
+',,,,,,,,,,,,,,,862,,,862,,,862,,,862,,,,,,862,,,,,,,,862,,,,,862,862',
+'862,862,862,862,,,,862,862,,,,876,876,876,862,876,,862,,876,876,,862',
+'862,876,,876,876,876,876,876,876,876,,,,,,876,876,876,876,876,876,876',
+',,876,,,,,,,876,,,876,876,,876,876,876,876,876,,876,876,876,,876,876',
+',876,876,,,,,,,,,,,,,,,,,,,,,,876,,,876,,,876,,,876,,,,,,876,,,,,,,',
+'876,,,,,876,876,876,876,876,876,,,,876,876,,,,877,877,877,876,877,,876',
+',877,877,,876,876,877,,877,877,877,877,877,877,877,,,,,,877,877,877',
+'877,877,877,877,,,877,,,,,,,877,,,877,877,,877,877,877,877,877,,877',
+'877,877,,877,877,,877,877,,,,,,,,,,,,,,,,,,,,,,877,,,877,,,877,,,877',
+',,,,,877,,,,,,,,877,,,,,877,877,877,877,877,877,,,,877,877,,,,881,881',
+'881,877,881,,877,,881,881,,877,877,881,,881,881,881,881,881,881,881',
+',,,,,881,881,881,881,881,881,881,,,881,,,,,,,881,,,881,881,,881,881',
+'881,881,881,881,881,881,881,,881,881,,881,881,,,,,,,,,,,,,,,,,,,,,,881',
+',,881,,,881,,,881,,,,881,,881,,,,,,,,881,,,,,881,881,881,881,881,881',
+',,,881,881,,,,,,,881,,,881,,,,,881,881,886,886,886,886,886,,,,886,886',
+',,,886,,886,886,886,886,886,886,886,,,,,,886,886,886,886,886,886,886',
+',,886,,,,,,886,886,,886,886,886,,886,886,886,886,886,,886,886,886,,886',
+'886,,886,886,,,,,,,,,,,,,,,,,,,,,,886,,,886,,,886,,,886,,886,,,,886',
+',,,,,,,886,,,,,886,886,886,886,886,886,,,,886,886,,,,890,890,890,886',
+'890,,886,,890,890,,886,886,890,,890,890,890,890,890,890,890,,,,,,890',
+'890,890,890,890,890,890,,,890,,,,,,,890,,,890,890,,890,890,890,890,890',
+',890,890,890,,890,890,,,,,,,,,,,,,,,,,,,,,,,,,890,,,890,,,890,,,890',
+',,,,,,,,,,,,,,,,,,890,890,890,890,890,890,,,,890,890,,,,900,900,900',
+'890,900,,890,,900,900,,890,890,900,,900,900,900,900,900,900,900,,,,',
+',900,900,900,900,900,900,900,,,900,,,,,,,900,,,900,900,,900,900,900',
+'900,900,,900,900,900,,900,900,,900,900,,,,,,,,,,,,,,,,,,,,,,900,,,900',
+',,900,,,900,,900,,,,900,,,,,,,,900,,,,,900,900,900,900,900,900,,,,900',
+'900,,,,,,,900,,,900,,,,,900,900,901,901,901,901,901,,,,901,901,,,,901',
+',901,901,901,901,901,901,901,,,,,,901,901,901,901,901,901,901,,,901',
+',,,,,901,901,,901,901,901,,901,901,901,901,901,,901,901,901,,901,901',
+',901,901,,,,,,,,,,,,,,,,,,,,,,901,,,901,,,901,,,901,,901,,,,901,,,,',
+',,,901,,,,,901,901,901,901,901,901,,,,901,901,,,,,,,901,,,901,,,,,901',
+'901,904,904,904,904,904,,,,904,904,,,,904,,904,904,904,904,904,904,904',
+',,,,,904,904,904,904,904,904,904,,,904,,,,,,904,904,,904,904,904,,904',
+'904,904,904,904,,904,904,904,,904,904,,904,904,,,,,,,,,,,,,,,,,,,,,',
+'904,,,904,,,904,,,904,,904,,,,904,,,,,,,,904,,,,,904,904,904,904,904',
+'904,,,,904,904,,,,921,921,921,904,921,,904,,921,921,,904,904,921,,921',
+'921,921,921,921,921,921,,,,,,921,921,921,921,921,921,921,,,921,,,,,',
+',921,,,921,921,,921,921,921,921,921,,921,921,921,,921,921,,921,921,',
+',,,,,,,,,,,,,,,,,,,,921,,,921,,,921,,,921,,921,,921,,921,,,,,,,,921',
+',,,,921,921,921,921,921,921,,,,921,921,,,,,,,921,,,921,,,,,921,921,923',
+'923,923,923,923,,,,923,923,,,,923,,923,923,923,923,923,923,923,,,,,',
+'923,923,923,923,923,923,923,,,923,,,,,,923,923,,923,923,923,,923,923',
+'923,923,923,,923,923,923,,923,923,,923,923,,,,,,,,,,,,,,,,,,,,,,923',
+',,923,,,923,,,923,,923,,,,923,,,,,,,,923,,,,,923,923,923,923,923,923',
+',,,923,923,,,,,,,923,,,923,,,,,923,923,930,930,930,930,930,,,,930,930',
+',,,930,,930,930,930,930,930,930,930,,,,,,930,930,930,930,930,930,930',
+',,930,,,,,,930,930,,930,930,930,,930,930,930,930,930,,930,930,930,,930',
+'930,,930,930,,,,,,,,,,,,,,,,,,,,,,930,,,930,,,930,,,930,,930,,,,930',
+',,,,,,,930,,,,,930,930,930,930,930,930,,,,930,930,,,,,,,930,,,930,,',
+',,930,930,935,935,935,935,935,,,,935,935,,,,935,,935,935,935,935,935',
+'935,935,,,,,,935,935,935,935,935,935,935,,,935,,,,,,935,935,,935,935',
+'935,,935,935,935,935,935,,935,935,935,,935,935,,935,935,,,,,,,,,,,,',
+',,,,,,,,,935,,,935,,,935,,,935,,935,,,,935,,,,,,,,935,,,,,935,935,935',
+'935,935,935,,,,935,935,,,,,,,935,,,935,,,,,935,935,943,943,943,943,943',
+',,,943,943,,,,943,,943,943,943,943,943,943,943,,,,,,943,943,943,943',
+'943,943,943,,,943,,,,,,943,943,,943,943,943,,943,943,943,943,943,,943',
+'943,943,,943,943,,943,943,,,,,,,,,,,,,,,,,,,,,,943,,,943,,,943,,,943',
+',943,,,,943,,,,,,,,943,,,,,943,943,943,943,943,943,,,,943,943,,,,945',
+'945,945,943,945,,943,,945,945,,943,943,945,,945,945,945,945,945,945',
+'945,,,,,,945,945,945,945,945,945,945,,,945,,,,,,,945,,,945,945,,945',
+'945,945,945,945,945,945,945,945,,945,945,,945,945,,,,,,,,,,,,,,,,,,',
+',,,945,,,945,,,945,,,945,,945,,,,945,,,,,,,,945,,,,436,945,945,945,945',
+'945,945,436,436,436,945,945,,436,436,,436,,945,,,945,,,,436,945,945',
+',,,,,,,,436,436,,436,436,436,436,436,,,,,,,,,,,,,,,,,,,,,,,,436,436',
+'436,436,436,436,436,436,436,436,436,436,436,436,436,438,,436,436,436',
+',436,438,438,438,436,,,438,438,,438,436,,436,,436,436,436,436,436,436',
+'436,,436,436,436,,,,,438,438,,438,438,438,438,438,436,436,,436,,436',
+',,436,,436,,436,,,,,,,,,,,438,438,438,438,438,438,438,438,438,438,438',
+'438,438,438,438,,,438,438,438,,438,,,,438,,,,,,,438,,438,,438,438,438',
+'438,438,438,438,,438,,438,,,,,,,,,,,,,438,438,,438,,438,644,,438,,438',
+',438,644,644,644,,,644,644,644,,644,,,,,,,,,644,644,644,,,,,,,,,644',
+'644,,644,644,644,644,644,,,,,,,,,,,,,,,,,,,,,,,,644,644,644,644,644',
+'644,644,644,644,644,644,644,644,644,644,,,644,644,644,,644,644,,,644',
+',,644,,644,,644,,644,,644,644,644,644,644,644,644,,644,644,644,,,,,',
+',,,,,,,644,644,644,644,,644,645,,644,,644,,644,645,645,645,,,645,645',
+'645,,645,,,,,,,,,,645,645,,,,,,,,,645,645,,645,645,645,645,645,,,,,',
+',,,,,,,,,,,,,,,,,,645,645,645,645,645,645,645,645,645,645,645,645,645',
+'645,645,,,645,645,645,,645,645,,,645,,,645,,645,,645,,645,,645,645,645',
+'645,645,645,645,,645,,645,,,,,,,,,,,,,645,645,645,645,,645,28,,645,',
+'645,,645,28,28,28,,,28,28,28,,28,,,,,,,,,,28,28,,,,,,,,,28,28,,28,28',
+'28,28,28,,,,,,,,,,,,,,,,,,,,,,,,28,28,28,28,28,28,28,28,28,28,28,28',
+'28,28,28,,,28,28,28,,,28,,28,28,,,28,,28,,28,,28,,28,28,28,28,28,28',
+'28,,28,,28,,,,,,,,,,,,,28,28,28,28,50,28,,,28,,28,50,50,50,,,50,50,50',
+',50,,,,,,,,,,50,50,50,,,,,,,,50,50,,50,50,50,50,50,,,,,,,,,,,,,,,,,',
+',,,,,,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,,,50,50,50,,,50,',
+',50,,,50,,50,,50,,50,,50,50,50,50,50,50,50,,50,,50,,,,,,,,,,,,,50,50',
+'50,50,494,50,,50,50,,50,494,494,494,,,494,494,494,,494,,,,,,,,,,494',
+',,,,,,,,,494,494,,494,494,494,494,494,,,,,,,,,,,,,,495,,,,,,,495,495',
+'495,,,495,495,495,,495,,,,,494,494,,,,495,,,494,,,,,494,494,495,495',
+',495,495,495,495,495,,,,,918,,918,918,918,918,918,,494,,,,,,,,918,,',
+',496,494,,494,,,494,496,496,496,495,495,496,496,496,,496,,495,918,918',
+',,495,495,,496,918,918,918,918,,,,,,496,496,,496,496,496,496,496,,495',
+',,,,,202,202,,,202,,,495,,495,,,495,202,202,918,202,202,202,202,202',
+'202,202,,,202,202,496,496,,,202,202,202,202,496,,,,,496,496,,,,,,202',
+'202,,202,202,202,202,202,202,202,202,202,202,202,,496,202,,,,,,,,,,',
+',496,,496,,,496,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,,,,7',
'7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,,7,7,7,,7,,,,,,,,,7,7,,7,7,7',
'7,7,7,7,,,7,7,,,,,7,7,7,7,,,,,,,,,,,,,7,7,,7,7,7,7,7,7,7,7,7,7,7,,,7',
-'7,,,,,,,,,,7,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79',
-'79,79,79,79,79,,,,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79',
-'79,79,79,79,,79,79,79,79,79,,79,,,,,,,79,79,,79,79,79,79,79,79,79,,',
-'79,79,,,,,79,79,79,79,,,,,,,,,,,,,79,79,,79,79,79,79,79,79,79,79,79',
-'79,79,,,79,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192',
-'192,192,192,192,192,192,192,192,192,,,,192,192,192,192,192,192,192,192',
-'192,192,192,192,192,192,192,192,192,192,192,192,192,,192,192,192,192',
-'192,,192,,,,,,,192,192,,192,192,192,192,192,192,192,,,192,192,,,,,192',
-'192,192,192,,,,,,,,,,,,,192,192,,192,192,192,192,192,192,192,192,192',
-'192,192,,,192,766,766,766,766,766,766,766,766,766,766,766,766,766,766',
-'766,766,766,766,766,766,766,766,766,766,,,,766,766,766,766,766,766,766',
-'766,766,766,766,766,766,766,766,766,766,766,766,766,766,,766,766,,,766',
-',,,,,,,,766,766,,766,766,766,766,766,766,766,,,766,766,,,,,766,766,766',
-'766,,,,,,,,,,,,,766,766,,766,766,766,766,766,766,766,766,766,766,766',
-',,766,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65',
-'65,65,65,,,,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65',
-'65,65,,65,65,65,65,65,,65,,,,,,,65,65,,65,65,65,65,65,65,65,,,65,65',
-',,,,65,65,65,65,,,,,,65,,,,,,,65,65,,65,65,65,65,65,65,65,65,65,65,65',
-'534,534,65,,534,,,,,,,,,534,534,,534,534,534,534,534,534,534,,,534,534',
-',,,,534,534,534,534,,,,,,534,,,,,,,534,534,,534,534,534,534,534,534',
-'534,534,534,534,534,535,535,534,,535,,,,,,,,,535,535,,535,535,535,535',
-'535,535,535,,,535,535,,,,,535,535,535,535,,,,,,,,,,,,,535,535,,535,535',
-'535,535,535,535,535,535,535,535,535,201,201,535,,201,,,,,,,,,201,201',
-',201,201,201,201,201,201,201,,,201,201,,,,,201,201,201,201,,,,,,201',
-',,,,,,201,201,,201,201,201,201,201,201,201,201,201,201,201,947,947,201',
-',947,,,,,,,,,947,947,,947,947,947,947,947,947,947,,,947,947,,,,,947',
-'947,947,947,,,,,,,,,,,,,947,947,,947,947,947,947,947,947,947,947,947',
-'947,947,946,946,947,,946,,,,,,,,,946,946,,946,946,946,946,946,946,946',
-',,946,946,,,,,946,946,946,946,,,,,,946,,,,,,,946,946,,946,946,946,946',
-'946,946,946,946,946,946,946,266,266,946,,266,,,,,,,,,266,266,,266,266',
-'266,266,266,266,266,,,266,266,,,,,266,266,266,266,,,,,,,,,,,,,266,266',
-',266,266,266,266,266,266,266,266,266,266,266,265,265,266,,265,,,,,,',
-',,265,265,,265,265,265,265,265,265,265,,,265,265,,,,,265,265,265,265',
-',,,,,,,,,,,,265,265,,265,265,265,265,265,265,265,265,265,265,265,264',
-'264,265,,264,,,,,,,,,264,264,,264,264,264,264,264,264,264,,,264,264',
-',,,,264,264,264,264,,,,,,,,,,,,,264,264,,264,264,264,264,264,264,264',
-'264,264,264,264,449,449,264,,449,,,,,,,,,449,449,,449,449,449,449,449',
-'449,449,,,449,449,,,,,449,449,449,449,,,,,,449,,,,,,,449,449,,449,449',
-'449,449,449,449,449,449,449,449,449,450,450,449,,450,,,,,,,,,450,450',
-',450,450,450,450,450,450,450,,,450,450,,,,,450,450,450,450,,,,,,,,,',
-',,,450,450,,450,450,450,450,450,450,450,450,450,450,450,822,822,450',
-',822,,,,,,,,,822,822,,822,822,822,822,822,822,822,,,822,822,,,,,822',
-'822,822,822,,,,,,,,,,,,,822,822,,822,822,822,822,822,822,822,822,822',
-'822,822,593,593,822,,593,,,,,,,,,593,593,,593,593,593,593,593,593,593',
-',,593,593,,,,,593,593,593,593,,,,,,593,,,,,,,593,593,,593,593,593,593',
-'593,593,593,593,593,593,593,591,591,593,,591,,,,,,,,,591,591,,591,591',
-'591,591,591,591,591,,,591,591,,,,,591,591,591,591,,,,,,,,,,,,,591,591',
-',591,591,591,591,591,591,591,591,591,591,591,585,585,591,,585,,,,,,',
-',,585,585,,585,585,585,585,585,585,585,,,585,585,,,,,585,585,585,585',
-',,,,,,,,,,,,585,585,,585,585,585,585,585,585,585,585,585,585,585,584',
-'584,585,,584,,,,,,,,,584,584,,584,584,584,584,584,584,584,,,584,584',
-',,,,584,584,584,584,,,,,,584,,,,,,,584,584,,584,584,584,584,584,584',
-'584,584,584,584,584,203,203,584,,203,,,,,,,,,203,203,,203,203,203,203',
-'203,203,203,,,203,203,,,,,203,203,203,203,,,,,,,,,,,,,203,203,,203,203',
-'203,203,203,203,203,203,203,203,203,521,521,203,,521,,,,,,,,,521,521',
-',521,521,521,521,521,521,521,,,521,521,,,,,521,521,521,521,,,,,,521',
-',,,,,,521,521,,521,521,521,521,521,521,521,521,521,521,521,522,522,521',
-',522,,,,,,,,,522,522,,522,522,522,522,522,522,522,,,522,522,,,,,522',
-'522,522,522,,,,,,,,,,,,,522,522,,522,522,522,522,522,522,522,522,522',
-'522,522,524,524,522,,524,,,,,,,,,524,524,,524,524,524,524,524,524,524',
-',,524,524,,,,,524,524,524,524,,,,,,,,,,,,,524,524,,524,524,524,524,524',
-'524,524,524,524,524,524,,,524' ]
- racc_action_check = arr = ::Array.new(25094, nil)
+'7,,,,,,,,,,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,,,,8,8',
+'8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,,8,8,,,8,,,,,,,,,8,8,,8,8,8,8',
+'8,8,8,,,8,8,,,,,8,8,8,8,,,,,,,,,,,,,8,8,,8,8,8,8,8,8,8,8,8,8,8,,,8,8',
+',,,,,,,,,8,411,411,411,411,411,411,411,411,411,411,411,411,411,411,411',
+'411,411,411,411,411,411,411,411,411,,,,411,411,411,411,411,411,411,411',
+'411,411,411,411,411,411,411,411,411,411,411,411,411,,411,411,,,411,',
+',,,,,,,411,411,,411,411,411,411,411,411,411,,,411,411,,,,,411,411,411',
+'411,,,,,,,,,,,,,411,411,,411,411,411,411,411,411,411,411,411,411,411',
+',,411,411,,,,,,,,,,411,415,415,415,415,415,415,415,415,415,415,415,415',
+'415,415,415,415,415,415,415,415,415,415,415,415,,,,415,415,415,415,415',
+'415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,415,,415',
+'415,,,415,,,,,,,,,415,415,,415,415,415,415,415,415,415,,,415,415,,,',
+',415,415,415,415,,,,,,,,,,,,,415,415,,415,415,415,415,415,415,415,415',
+'415,415,415,,,415,415,,,,,,,,,,415,65,65,65,65,65,65,65,65,65,65,65',
+'65,65,65,65,65,65,65,65,65,65,65,65,65,,,,65,65,65,65,65,65,65,65,65',
+'65,65,65,65,65,65,65,65,65,65,65,65,,65,65,65,65,65,,65,,,,,,,65,65',
+',65,65,65,65,65,65,65,,,65,65,,,,,65,65,65,65,,,,,,65,,,,,,,65,65,,65',
+'65,65,65,65,65,65,65,65,65,65,,,65,79,79,79,79,79,79,79,79,79,79,79',
+'79,79,79,79,79,79,79,79,79,79,79,79,79,,,,79,79,79,79,79,79,79,79,79',
+'79,79,79,79,79,79,79,79,79,79,79,79,,79,79,79,79,79,,79,,,,,,,79,79',
+',79,79,79,79,79,79,79,,,79,79,,,,,79,79,79,79,,,,,,,,,,,,,79,79,,79',
+'79,79,79,79,79,79,79,79,79,79,,,79,192,192,192,192,192,192,192,192,192',
+'192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,,,,192,192',
+'192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192',
+'192,192,,192,192,192,192,192,,192,,,,,,,192,192,,192,192,192,192,192',
+'192,192,,,192,192,,,,,192,192,192,192,,,,,,,,,,,,,192,192,,192,192,192',
+'192,192,192,192,192,192,192,192,,,192,766,766,766,766,766,766,766,766',
+'766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,,,,766',
+'766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766',
+'766,766,766,,766,766,,,766,,,,,,,,,766,766,,766,766,766,766,766,766',
+'766,,,766,766,,,,,766,766,766,766,,,,,,,,,,,,,766,766,,766,766,766,766',
+'766,766,766,766,766,766,766,201,201,766,,201,,,,,,,,,201,201,,201,201',
+'201,201,201,201,201,,,201,201,,,,,201,201,201,201,,,,,,201,,,,,,,201',
+'201,,201,201,201,201,201,201,201,201,201,201,201,203,203,201,,203,,',
+',,,,,,203,203,,203,203,203,203,203,203,203,,,203,203,,,,,203,203,203',
+'203,,,,,,,,,,,,,203,203,,203,203,203,203,203,203,203,203,203,203,203',
+'264,264,203,,264,,,,,,,,,264,264,,264,264,264,264,264,264,264,,,264',
+'264,,,,,264,264,264,264,,,,,,,,,,,,,264,264,,264,264,264,264,264,264',
+'264,264,264,264,264,265,265,264,,265,,,,,,,,,265,265,,265,265,265,265',
+'265,265,265,,,265,265,,,,,265,265,265,265,,,,,,,,,,,,,265,265,,265,265',
+'265,265,265,265,265,265,265,265,265,266,266,265,,266,,,,,,,,,266,266',
+',266,266,266,266,266,266,266,,,266,266,,,,,266,266,266,266,,,,,,,,,',
+',,,266,266,,266,266,266,266,266,266,266,266,266,266,266,449,449,266',
+',449,,,,,,,,,449,449,,449,449,449,449,449,449,449,,,449,449,,,,,449',
+'449,449,449,,,,,,449,,,,,,,449,449,,449,449,449,449,449,449,449,449',
+'449,449,449,450,450,449,,450,,,,,,,,,450,450,,450,450,450,450,450,450',
+'450,,,450,450,,,,,450,450,450,450,,,,,,,,,,,,,450,450,,450,450,450,450',
+'450,450,450,450,450,450,450,521,521,450,,521,,,,,,,,,521,521,,521,521',
+'521,521,521,521,521,,,521,521,,,,,521,521,521,521,,,,,,521,,,,,,,521',
+'521,,521,521,521,521,521,521,521,521,521,521,521,522,522,521,,522,,',
+',,,,,,522,522,,522,522,522,522,522,522,522,,,522,522,,,,,522,522,522',
+'522,,,,,,,,,,,,,522,522,,522,522,522,522,522,522,522,522,522,522,522',
+'524,524,522,,524,,,,,,,,,524,524,,524,524,524,524,524,524,524,,,524',
+'524,,,,,524,524,524,524,,,,,,,,,,,,,524,524,,524,524,524,524,524,524',
+'524,524,524,524,524,534,534,524,,534,,,,,,,,,534,534,,534,534,534,534',
+'534,534,534,,,534,534,,,,,534,534,534,534,,,,,,534,,,,,,,534,534,,534',
+'534,534,534,534,534,534,534,534,534,534,535,535,534,,535,,,,,,,,,535',
+'535,,535,535,535,535,535,535,535,,,535,535,,,,,535,535,535,535,,,,,',
+',,,,,,,535,535,,535,535,535,535,535,535,535,535,535,535,535,584,584',
+'535,,584,,,,,,,,,584,584,,584,584,584,584,584,584,584,,,584,584,,,,',
+'584,584,584,584,,,,,,584,,,,,,,584,584,,584,584,584,584,584,584,584',
+'584,584,584,584,585,585,584,,585,,,,,,,,,585,585,,585,585,585,585,585',
+'585,585,,,585,585,,,,,585,585,585,585,,,,,,,,,,,,,585,585,,585,585,585',
+'585,585,585,585,585,585,585,585,591,591,585,,591,,,,,,,,,591,591,,591',
+'591,591,591,591,591,591,,,591,591,,,,,591,591,591,591,,,,,,,,,,,,,591',
+'591,,591,591,591,591,591,591,591,591,591,591,591,593,593,591,,593,,',
+',,,,,,593,593,,593,593,593,593,593,593,593,,,593,593,,,,,593,593,593',
+'593,,,,,,593,,,,,,,593,593,,593,593,593,593,593,593,593,593,593,593',
+'593,822,822,593,,822,,,,,,,,,822,822,,822,822,822,822,822,822,822,,',
+'822,822,,,,,822,822,822,822,,,,,,,,,,,,,822,822,,822,822,822,822,822',
+'822,822,822,822,822,822,946,946,822,,946,,,,,,,,,946,946,,946,946,946',
+'946,946,946,946,,,946,946,,,,,946,946,946,946,,,,,,946,,,,,,,946,946',
+',946,946,946,946,946,946,946,946,946,946,946,947,947,946,,947,,,,,,',
+',,947,947,,947,947,947,947,947,947,947,,,947,947,,,,,947,947,947,947',
+',,,,,,,,,,,,947,947,,947,947,947,947,947,947,947,947,947,947,947,,,947' ]
+ racc_action_check = arr = ::Array.new(25031, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -1729,18 +1726,18 @@ clist = [
end
racc_action_pointer = [
- 1281, 1148, nil, 106, nil, 618, 1015, 23357, 23233, 1014,
- 962, 955, 962, 721, 208, 688, nil, 3264, 3391, 1408,
- 982, nil, 3785, 3912, 4039, 508, 13, 4420, 22600, nil,
- 4560, 4687, 4814, nil, 847, 444, 848, 660, 5488, 5615,
- 5742, 734, 213, nil, nil, nil, nil, nil, nil, nil,
- 22470, nil, 6136, 6263, 6390, 29, 7177, 6771, -2, nil,
- nil, 7025, 7165, 7292, nil, 23820, nil, nil, nil, nil,
- nil, -102, nil, nil, nil, nil, nil, 626, 625, 23481,
- nil, nil, nil, 344, 8194, nil, nil, 8321, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 601, nil, 8601,
- nil, nil, nil, 8741, 8868, 8995, 9122, 9262, 9402, nil,
- 418, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ -2, 34, nil, 234, nil, 618, -19, 22922, 23046, -5,
+ -1, 15, 117, 414, 291, 243, nil, 125, 252, 900,
+ 186, nil, 379, 506, 633, 381, 13, 760, 22407, nil,
+ 900, 1027, 1154, nil, 108, 541, 237, 261, 1294, 1421,
+ 1548, 176, 467, nil, nil, nil, nil, nil, nil, nil,
+ 22537, nil, 1675, 1802, 1929, 29, 9932, 2056, 2183, nil,
+ nil, 2310, 2450, 2577, nil, 23418, nil, nil, nil, nil,
+ nil, -102, nil, nil, nil, nil, nil, 178, 220, 23531,
+ nil, nil, nil, 429, 2704, nil, nil, 2831, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 359, nil, 2971,
+ nil, nil, nil, 3111, 3238, 3365, 3492, 3632, 3772, nil,
+ 663, 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, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
@@ -1748,84 +1745,84 @@ racc_action_pointer = [
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, nil, nil,
- nil, nil, 23594, 423, nil, 9949, 10076, 10203, 10330, 10457,
- 10584, 24003, 22855, 24796, 11092, 11219, 11346, nil, 848, 97,
- 1175, 248, 1086, 1123, 12287, 12414, nil, nil, 12541, 1119,
- 12795, 12922, 13049, 13176, 13303, 13430, 13557, 13684, 13811, 13938,
- 14065, 14192, 14319, 14446, 14573, 14700, 14827, 14954, 15081, 15208,
- 15335, 15462, 15589, 15716, 15843, 15970, nil, nil, nil, 2603,
- nil, 1062, 1052, nil, 16364, 1089, 16491, nil, nil, nil,
- nil, 16618, nil, nil, 24308, 24247, 24186, 1072, 17253, 17380,
- nil, nil, nil, nil, nil, nil, nil, 17507, 543, 872,
- 1112, 18028, 1134, 1141, 1106, 18536, 18676, 235, 887, 1207,
- 206, 142, 281, 14, nil, 388, 289, nil, 20011, nil,
- 459, 499, 522, 795, nil, 629, nil, 20773, nil, 20913,
- 42, nil, 607, 262, 150, 715, 707, 234, 763, nil,
- nil, 48, 4699, nil, nil, nil, 799, 792, nil, 824,
- 840, nil, nil, nil, nil, nil, nil, nil, 3025, nil,
- nil, nil, 919, nil, nil, 924, 425, 36, 63, 1535,
- 1662, 446, 73, 882, 21, 633, 1085, 43, 1142, nil,
- nil, 379, 1095, nil, 594, nil, 64, nil, nil, 125,
- 467, 470, 483, 528, 554, 563, -5, 356, nil, 388,
- nil, 6898, nil, 462, nil, 483, nil, 201, 1034, 488,
- nil, 1030, -57, nil, 379, nil, nil, nil, nil, nil,
+ nil, nil, 23644, 234, nil, 3912, 4039, 4166, 4293, 4420,
+ 4547, 23818, 22792, 23879, 4674, 4801, 4928, nil, 541, -49,
+ 319, 61, 240, 328, 5068, 5195, nil, nil, 5322, 363,
+ 5449, 5576, 5703, 5830, 5957, 6084, 6211, 6338, 6465, 6592,
+ 6719, 6846, 6973, 7100, 7227, 7354, 7481, 7608, 7735, 7862,
+ 7989, 8116, 8243, 8370, 8497, 8624, nil, nil, nil, 1294,
+ nil, 329, 339, nil, 8751, 389, 8878, nil, nil, nil,
+ nil, 9005, nil, nil, 23940, 24001, 24062, 383, 9132, 9259,
+ nil, nil, nil, nil, nil, nil, nil, 9386, 249, 745,
+ 390, 9526, 409, 438, 405, 9653, 9793, 73, 594, 497,
+ 196, 465, 440, 207, nil, 478, 471, nil, 9920, nil,
+ 586, 505, 531, 633, nil, 533, nil, 10047, nil, 10187,
+ 35, nil, 502, -103, 135, 537, 521, 262, 556, nil,
+ nil, -22, 10580, nil, nil, nil, 520, 545, nil, 564,
+ 567, nil, nil, nil, nil, nil, nil, nil, 3097, nil,
+ nil, nil, 648, nil, nil, 674, 806, -7, 36, 10314,
+ 10441, 324, 63, 596, -17, 668, 690, 37, 731, nil,
+ nil, 506, 704, nil, 721, nil, 65, nil, nil, 10568,
+ -12, 122, 360, 384, 385, 436, 509, 590, nil, 795,
+ nil, 10695, nil, 173, nil, 326, nil, -23, 649, 362,
+ nil, 653, -50, nil, 365, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 1029, 22985, nil, nil, nil, 23109, 1023, nil, nil, 1916,
- nil, 1916, 974, nil, 951, nil, nil, 2196, 947, 946,
- 287, 291, 1789, nil, nil, nil, 22338, 908, 21942, nil,
- 1141, 1014, 887, nil, nil, nil, 1014, nil, nil, 24369,
- 24430, 760, 633, -46, 506, 379, 252, 4, nil, 5234,
- 5094, 993, 514, 857, 856, 819, 816, 5488, 5361, 3138,
- 4954, 4166, 4560, 4039, 3912, 3785, 3658, 3531, 3391, 3264,
- 1141, 1149, 4420, 4293, 633, -40, nil, 21828, nil, 21701,
- nil, 21574, nil, nil, 22855, 22730, 22787, 171, nil, 680,
- nil, nil, 674, 672, nil, nil, 21447, 203, 193, 705,
- nil, nil, 21307, 704, 647, nil, nil, 643, 21167, 635,
- 21040, 24857, 24918, 20646, 24979, 228, 537, nil, nil, 463,
- nil, 20519, 20392, 20265, 23881, 23942, 1789, 20138, 523, 509,
- 415, nil, nil, 19884, nil, nil, 19757, nil, nil, nil,
- nil, 19630, 19490, 267, nil, 1114, nil, nil, 19350, 7304,
- nil, 107, nil, nil, -15, nil, 3034, nil, -61, 1521,
- nil, nil, 19223, 1252, nil, nil, 19083, 212, 227, 1234,
- 1229, 18943, nil, 18803, 24735, 24674, 18409, 20, nil, 922,
- nil, 24613, 18282, 24552, nil, nil, 18155, 472, 17888, nil,
- 11485, nil, nil, nil, 35, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, -23, nil, nil, nil, 1071,
- nil, nil, nil, nil, nil, 17761, 1051, 17634, 462, -54,
- 17126, 16999, 1070, nil, nil, nil, 16872, 1071, nil, 16745,
- 1080, nil, 330, 307, 22074, 22206, 1092, 1093, 379, nil,
- 16237, nil, 3149, nil, 16110, 1078, nil, 1120, 12668, nil,
- nil, nil, nil, nil, nil, nil, nil, 12147, nil, 1127,
- 12007, 11880, 2056, 1098, nil, nil, 1137, 11753, 11613, nil,
- 745, -34, 11473, 1113, nil, 1154, 196, 223, 1172, 227,
- 203, 1180, 1177, -81, 10965, 2476, 26, 98, -12, 217,
- 10838, nil, nil, -103, 135, 268, nil, nil, 170, nil,
- 202, 760, 319, 249, 251, nil, nil, 311, 2996, nil,
- 702, nil, 401, nil, nil, nil, nil, nil, 410, nil,
- 464, 10711, 410, 40, 37, -18, 46, 438, 9809, 668,
- nil, 483, 485, 9682, 503, nil, -25, 9542, 8461, 4826,
- 464, nil, nil, 581, nil, 8067, nil, 516, 541, nil,
- 547, 550, 554, nil, 555, nil, 23707, 607, 1164, 7940,
- nil, nil, nil, 1281, 616, 7800, 7673, 7546, nil, 887,
- nil, 2883, nil, nil, 760, nil, 2743, nil, 7419, 6644,
- 6517, 65, 14, 1535, nil, 714, 817, nil, nil, 729,
- nil, 714, 6009, nil, 735, 840, 722, 59, nil, nil,
- nil, 846, nil, 5882, 743, 793, nil, nil, nil, nil,
- nil, nil, 24491, nil, 1084, nil, nil, nil, nil, 1394,
- 879, nil, 5361, 890, 5234, 5094, nil, nil, 70, -17,
- 975, 295, nil, 924, nil, nil, 928, 938, 824, nil,
- nil, nil, 478, nil, nil, 392, 19362, nil, 1223, nil,
- 475, nil, 4954, nil, nil, nil, nil, nil, nil, nil,
- 866, 852, nil, 1662, nil, 2336, 4293, 4166, nil, nil,
- nil, 3658, 881, nil, nil, nil, 3531, nil, nil, 74,
- 3137, nil, 935, 901, nil, nil, 78, nil, 1030, 1031,
- 3010, 2883, nil, nil, 2743, nil, nil, 959, nil, 926,
- nil, nil, 928, 935, 945, 939, nil, nil, 18548, nil,
- nil, 2603, nil, 2476, 85, 541, 1051, 91, nil, nil,
- 2336, nil, nil, nil, 118, 2196, 1119, nil, nil, 1169,
- nil, nil, nil, 2056, 1130, 1408, 24125, 24064, 97, 179,
- nil, nil, nil, 1006, nil, 909, 1093, nil, 1013, 98,
- 108, 198, 202, nil, nil, nil, nil, -7 ]
+ 683, 23170, nil, nil, nil, 23294, 688, nil, nil, 760,
+ nil, 10822, 681, nil, 691, nil, nil, 1421, 728, 731,
+ 668, 761, 10949, nil, nil, nil, 21929, 757, 22011, nil,
+ 11076, 11203, 11330, nil, nil, nil, 1548, nil, nil, 24123,
+ 24184, 11457, 11584, 180, 11711, 11838, 11965, 115, nil, 3238,
+ 3365, 232, 879, 785, 787, 821, 824, 2457, 2584, 5068,
+ 3492, 3632, 3772, 3912, 4039, 4166, 4293, 4420, 4547, 4674,
+ 1133, 1232, 4801, 4928, 633, -34, nil, 12092, nil, 12219,
+ nil, 12346, nil, nil, 22667, 22724, 22792, -17, nil, 771,
+ nil, nil, 785, 787, nil, nil, 12473, 59, 203, 832,
+ nil, nil, 12613, 833, 797, nil, nil, 799, 12753, 845,
+ 12880, 24245, 24306, 13007, 24367, 223, 848, nil, nil, 821,
+ nil, 13134, 13261, 13388, 24428, 24489, 1675, 13515, 949, 951,
+ 871, nil, nil, 13642, nil, nil, 13769, nil, nil, nil,
+ nil, 13909, 14049, 874, nil, 1000, nil, nil, 14176, 12765,
+ nil, 772, nil, nil, 894, nil, 3126, nil, 859, 1198,
+ nil, nil, 14316, 977, nil, nil, 14456, 212, 227, 975,
+ 983, 14596, nil, 14723, 24550, 24611, 14850, 40, nil, 760,
+ nil, 24672, 14977, 24733, nil, nil, 15104, 387, 15231, nil,
+ 1166, nil, nil, nil, 45, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, -35, nil, nil, nil, 864,
+ nil, nil, nil, nil, nil, 15358, 866, 15485, 798, 203,
+ 15612, 15739, 900, nil, nil, nil, 15866, 903, nil, 15993,
+ 915, nil, 268, 307, 22143, 22275, 927, 928, 506, nil,
+ 16120, nil, 1040, nil, 16260, 897, nil, 939, 16387, nil,
+ nil, nil, nil, nil, nil, nil, nil, 16527, nil, 942,
+ 16654, 16781, 2310, 907, nil, nil, 947, 16921, 17061, nil,
+ 1154, -27, 17188, 914, nil, 957, 228, 235, 962, 313,
+ 327, 963, 960, 972, 17315, 1802, 997, 1001, 240, 1056,
+ 17442, nil, nil, 376, 960, 1068, nil, nil, 945, nil,
+ 958, 935, 1035, 963, 967, nil, nil, 1010, 3135, nil,
+ 869, nil, 1096, nil, nil, nil, nil, nil, 1102, nil,
+ 1103, 17569, 1020, 46, 52, 59, 102, 1021, 17696, 1027,
+ nil, 1028, 1026, 17836, 416, nil, -25, 17976, 18116, 9665,
+ 463, nil, nil, 1075, nil, 18243, nil, 998, 999, nil,
+ 1000, 1002, 1004, nil, 996, nil, 23757, 1043, 1050, 18383,
+ nil, nil, nil, 1929, 1007, 18510, 18637, 18764, nil, 2056,
+ nil, 2183, nil, nil, 2446, nil, 2573, nil, 18891, 19018,
+ 19145, 315, 319, 2704, nil, 1041, 1144, nil, nil, 1041,
+ nil, 1026, 19272, nil, 1053, 1161, 1072, 323, nil, nil,
+ nil, 1196, nil, 19412, 1081, 1125, nil, nil, nil, nil,
+ nil, nil, 24794, nil, 1127, nil, nil, nil, nil, 1407,
+ 1215, nil, 19539, 1220, 19679, 19819, nil, nil, 66, 56,
+ 988, 295, nil, 1221, nil, nil, 1222, 1225, 1109, nil,
+ nil, nil, -32, nil, nil, 807, 14188, nil, 842, nil,
+ 406, nil, 19946, nil, nil, nil, nil, nil, nil, nil,
+ 1127, 1113, nil, 2831, nil, 2971, 20073, 20200, nil, nil,
+ nil, 20327, 1114, nil, nil, nil, 20467, nil, nil, 72,
+ 20594, nil, 1154, 1125, nil, nil, 78, nil, 1249, 1250,
+ 20721, 20861, nil, nil, 21001, nil, nil, 1168, nil, 1132,
+ nil, nil, 1133, 1134, 1139, 1137, nil, nil, 22721, nil,
+ nil, 21128, nil, 21268, 91, 1112, 1221, 97, nil, nil,
+ 21408, nil, nil, nil, 460, 21548, 1268, nil, nil, 1081,
+ nil, nil, nil, 21688, 1273, 21815, 24855, 24916, 98, 899,
+ nil, nil, nil, 1272, nil, 1153, 1275, nil, 1190, 108,
+ 120, 198, 202, nil, nil, nil, nil, 218 ]
racc_action_default = [
-3, -555, -1, -543, -4, -6, -555, -555, -555, -555,
@@ -1927,81 +1924,84 @@ racc_action_default = [
-535, -538, -283, -347, -313, -481, -326, -285 ]
clist = [
-'13,307,580,251,251,251,315,378,284,699,250,250,250,5,565,529,102,208',
-'208,539,659,396,208,208,208,114,114,323,294,294,13,288,288,488,418,425',
-'498,748,331,347,348,312,99,351,715,763,109,194,14,707,366,830,208,208',
-'432,437,442,208,208,294,294,208,355,364,760,282,572,576,252,252,252',
-'723,727,98,102,117,117,659,14,290,290,590,834,114,759,405,406,407,408',
-'350,656,564,656,271,275,853,854,114,557,13,317,560,562,208,208,208,208',
-'13,13,674,357,365,5,2,280,297,641,494,495,496,409,5,606,542,545,835',
-'811,549,616,738,935,352,743,12,396,916,654,385,387,598,904,394,369,747',
-'600,766,918,14,667,833,321,550,428,429,713,14,14,411,677,678,360,193',
-'247,12,485,507,508,950,662,664,666,731,815,889,382,383,389,422,422,248',
-'262,263,615,392,865,768,710,312,312,10,714,769,848,909,763,13,208,208',
-'208,208,208,908,659,912,208,208,208,403,828,885,114,216,676,760,13,208',
-'916,504,380,10,441,410,316,319,320,668,1,499,358,728,594,762,12,759',
-'379,683,601,309,349,,12,12,565,14,,719,,938,,502,251,359,526,,,,250',
-'250,251,,,,14,,,250,,,208,208,540,,541,656,656,530,,208,,,963,13,294',
-',488,288,13,,10,,,102,,553,,294,10,10,288,,,,432,437,331,,,,,13,740',
-'267,274,276,503,252,513,512,707,717,,519,,252,,,,,12,14,,577,578,290',
-'14,902,910,,,910,759,715,759,,759,,290,12,511,208,208,,,,771,943,599',
-'14,,,271,951,275,763,102,280,294,641,517,364,280,,,,688,,,693,,595,762',
-'208,760,,10,,,688,,417,423,426,,,565,,,445,,806,,782,759,10,646,647',
-'785,,,787,,,659,,12,957,,365,,12,,579,,759,,501,505,,,114,,,,114,509',
-',797,688,,312,312,,12,,,,688,,,,622,208,208,843,623,893,,846,847,669',
-',,,,,857,859,861,441,,10,,,685,,10,692,,,117,,,821,117,656,825,826,913',
-',914,,,,,,530,,,10,634,,,,,638,894,208,,312,634,,312,13,818,,294,,,288',
-',208,,,208,656,680,,,,,,,,655,,,732,208,816,737,441,,,,,742,,,,762,',
-'13,13,441,,294,,901,711,,14,634,634,634,767,,290,,,,955,312,13,,312',
-',13,,744,,312,13,797,208,952,,208,,,703,724,724,208,,,,208,,208,14,14',
-',,441,,,365,,923,441,745,35,,,936,930,,940,941,942,14,,,795,14,,,,,14',
-'208,208,,,331,,208,,283,,,35,287,287,,12,,,,,318,,,956,13,,,,,530,965',
-',,920,,929,,13,,,,809,,354,368,,368,13,13,294,,422,288,,12,12,,,,,,294',
-',,288,,,,,,,10,14,,,12,,,863,12,35,,838,,12,14,801,632,35,35,841,,637',
-',,14,14,640,,,290,,,,,,,,208,,10,10,290,13,,,,13,13,,,,,,,634,,844,638',
-'845,634,10,,849,,10,,,,13,10,,,,,,208,208,,661,663,665,,882,114,,,12',
-',,,14,420,424,,14,14,,,688,12,,,416,,,35,,907,,12,12,,13,896,,869,14',
-',,,,283,778,780,35,,,,783,,,208,,13,13,,,,,441,,,10,,,,,,,490,,492,',
-'724,,10,493,,,,14,,,,,10,10,,,,,,,,,12,,,,12,12,14,14,,,13,294,,283',
-'925,,35,,283,,287,35,958,,,13,12,,13,,,,,287,,,,,,,,,,,35,,,13,,,,,',
-',13,,10,312,14,13,10,10,927,,,,,13,,208,12,,,14,,,14,,,,,,10,,,,,,,441',
-'207,12,12,872,874,14,,,,,,,14,,368,,,14,,,,,,,,14,,217,,,,249,249,249',
-',310,10,,,,346,346,,,346,,,304,305,306,,626,,12,,,,10,10,,,,249,249',
-',,,,12,,,12,,,,,,,,,,,,,,,346,346,346,346,12,,,,,,,12,,,,,12,,,,,,,10',
-'12,,,928,,,,657,,318,,660,,,10,,,10,,,,,,,,,673,,,,,,,,,,10,,,,,,,10',
-',,,35,10,,,,,287,,,10,,,,,,,657,,,318,,,,,,,,,,,,447,448,,,,704,705',
-',35,35,457,,,,,368,,419,249,427,249,249,,,,446,720,,,35,722,,,35,,730',
-',,35,217,,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473',
-'474,475,476,477,478,479,480,481,482,483,484,,,774,,,,,,249,,249,,,,',
-'249,,,,,,,249,249,,,,,,,,249,,798,,,,,,,,796,,,35,657,318,,,,,,,,799',
-',,35,,,,536,,,804,805,,35,35,,,,287,,,814,,346,346,,,324,,,287,,,,,',
-',,,,,,,,384,,386,386,390,393,386,,420,,,604,,,,,,,,,,,,,,,,,,,,,851',
-',,35,,,,35,35,,,,,,,,,,,,871,,,,,,870,,,35,,,,,,,,,,,,,,,,249,,420,',
-',,,,,,,,,,,,,,,,,,,,,888,,,35,,249,249,,446,648,427,,,,,,,,,,,898,899',
-',35,35,,,,,,,,,310,,,917,,,,249,,249,,249,,,,,,,,,,,318,,,,672,,,,,698',
-',,,,,,,922,249,933,35,249,,,924,,,,,695,696,697,934,,,35,,500,35,,933',
-'249,,,249,,,,,,,,,,944,,,35,,,,949,,,35,,953,,346,35,746,,,,,,,35,,',
-',249,,,249,,,,,,249,,,,,556,,,556,556,,,,,,,,,,,,,,,,,,,,,,,,773,,249',
-',,779,781,,,293,293,784,,,786,,293,293,293,,,,,,,793,,,,,,,293,249,',
-',,,,,293,293,,,,249,249,,,,,,,,,,,,,,,,,,,,,,,,,,,,,249,,,633,,,,,,',
-',,346,633,,,,,,,,,,,,,,,,,,249,,,,,,,,,,,,,,,,,,,,,,,,249,651,,,,,,',
-',,633,633,633,651,,,,,,,249,873,875,651,651,,,,,,,,,779,781,784,,,,',
-',,,,,,,249,,,,346,,,,,,,,,,,,,,,293,,293,293,293,293,293,293,293,293',
+'13,315,307,699,323,378,498,114,114,539,250,250,250,432,437,442,5,208',
+'208,396,284,488,208,208,208,659,331,102,294,294,13,288,288,572,576,529',
+'10,98,12,557,748,312,560,562,251,251,251,366,565,109,194,580,208,208',
+'117,117,216,208,208,294,294,208,355,364,99,114,10,715,12,418,425,760',
+'707,267,274,276,494,495,496,114,542,545,659,2,549,102,280,297,252,252',
+'252,606,763,723,727,352,759,616,359,13,1,916,590,208,208,208,208,13',
+'13,347,348,403,282,351,641,5,564,710,385,387,317,714,394,409,5,885,830',
+'248,262,263,193,360,396,411,499,10,668,12,676,504,207,654,811,10,10',
+'12,12,428,429,853,854,380,316,667,319,405,406,407,408,320,358,594,762',
+'677,678,833,662,664,666,379,601,309,349,834,350,310,835,738,935,743',
+'346,346,916,598,346,904,369,312,312,747,600,410,114,766,918,13,208,208',
+'208,208,208,321,441,550,208,208,208,659,713,247,485,656,507,656,13,208',
+'508,950,422,422,760,731,815,889,382,383,346,346,346,346,674,10,389,12',
+'417,423,426,615,392,865,768,763,445,769,848,759,909,908,912,828,10,',
+'12,526,,683,250,250,,,,432,437,,,250,,,208,208,553,540,488,541,,,565',
+'208,728,719,,13,294,,,288,13,530,,,502,251,331,,,294,,,288,251,,938',
+'102,,,,,,,13,,762,511,,,,,10,,12,,,10,771,12,,271,275,447,448,14,740',
+',688,503,252,693,280,457,512,517,707,280,252,717,10,688,12,910,208,208',
+'910,759,599,759,963,759,902,943,,14,290,290,513,715,641,294,,519,364',
+',782,,501,505,102,785,951,,787,,208,509,,,579,893,,,760,595,,357,365',
+'656,656,688,,,646,647,577,578,,,688,,,,957,763,114,,,759,114,,659,913',
+'806,914,,,821,797,,825,826,565,14,,,,,,759,,14,14,312,312,,,843,,,,846',
+'847,,441,208,208,622,,,,623,117,,669,,117,,,,,,685,,818,692,346,346',
+',,,,,632,762,,,,637,,,,,640,,,,,,,,,,,,955,,,604,,208,530,312,,,312',
+'13,,,294,,,288,,208,,441,208,901,14,,,680,,,732,,,737,441,,208,,894',
+'742,661,663,665,14,,,,10,,12,13,13,655,,294,,,711,,,,,,,767,,,,,797',
+'312,13,816,312,923,13,857,859,861,312,13,930,208,,441,208,10,10,12,12',
+'441,208,271,35,275,208,,208,,795,724,724,,936,656,929,,10,703,12,14',
+'10,,12,290,14,10,,12,,745,331,,35,287,287,,290,310,208,208,,952,,,208',
+',,14,,,,956,,656,,,744,,,920,,,13,,354,368,,368,698,,283,,,,,13,778',
+'780,,530,,,783,,,13,13,294,,,288,809,,,,,,,10,294,12,35,288,,,,,365',
+',35,35,10,,12,863,,,,,,,10,10,12,12,,,346,,746,422,,,,,,,940,941,942',
+'634,,,,801,638,208,,,,634,13,,,,13,13,,,,,838,,,,,688,,,,,,,,114,,844',
+'13,845,,965,,849,,208,208,,10,,12,,10,10,12,12,,,35,841,,,,634,634,634',
+',,,,,,,,10,,12,35,907,,,,13,872,874,,,,,,,441,,882,,,416,,,,,208,318',
+'13,13,,,,,,,14,,,,283,,290,10,,12,,,,,,,,,,346,,,,724,,,,,10,10,12,12',
+',35,,,,287,35,14,14,,896,,13,294,365,,925,,287,958,,,,,,,,13,14,35,13',
+',14,,,,,14,,283,,,,,283,,,,10,13,12,,928,,,,13,,,312,,13,,10,,12,10',
+',12,13,,208,,441,,,,,,,,346,,,,10,,12,,368,,,10,,12,,,10,,12,,420,424',
+',,10,,12,,,14,,,,634,,,638,,634,,,,14,,,,,,,,,,14,14,,,,290,,,,,,,,',
+',,,290,,,,,,,,,490,,492,,,,,493,,,,,,,,,,,,,,,,,,,,,,324,,,,,,,,,,,14',
+',,,14,14,384,,386,386,390,393,386,,,,,,,,,,,,,869,14,,,,,,,35,,,,,,287',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,14,,35,35,,,,,,368,,,,,,,,,,,,14,14,35',
+'217,,,35,249,249,249,,35,,,,,,,,704,705,,,304,305,306,,,,,,,,,,,626',
+',249,249,720,,,,722,,,,,730,,,14,,,,927,,,,,,,,,,,14,,,14,,,,,,,,,,',
+',,,35,,,,,14,,,,,,,14,35,,,,14,657,,318,,660,35,35,14,500,,287,,,,,',
+',,,673,796,,287,,,,,,,,,,,799,,,,,,,,,,804,805,,,,,,,,,,,,657,,,318',
+',,,,,,556,,,556,556,35,,,,35,35,,,419,249,427,249,249,,,,446,,,,,,,',
+',,35,,,,217,,459,460,461,462,463,464,465,466,467,468,469,470,471,472',
+'473,474,475,476,477,478,479,480,481,482,483,484,,,,,,,870,,249,,249',
+'774,35,,,249,,,,,,,249,249,,,,,,,,249,,35,35,,,,,,,,798,633,,,,,,,888',
+',,633,657,318,,,,,,536,,,,,,,,,,898,899,,,,,,,,,,,,814,35,,,,924,,,',
+',,,651,,,,35,,,35,,633,633,633,651,,,,,,,420,,,651,651,,,35,922,,,,',
+',35,,,,,35,,,,934,851,,,35,,,,,,,,,,,,,,,,,871,944,,,,,,,949,,,,,953',
+',,249,,,,,,,,,,,420,,,,,,,,,,,,,,,,,,,249,249,,446,648,427,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,249,,249,,249,917,,,,,,,,,,,,,,672,,,,,318,,,,',
+',,,,249,,,249,,,,,,,933,695,696,697,,,,,,,,,,249,,633,249,,,,633,933',
+',,,,812,817,,,,,,,,,,556,,,556,556,,,,,,812,,812,,,,249,,,249,,,,,,249',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,773,,249,,,779,781,,,293,293,784,,,786',
+',293,293,293,,,,,,,793,,,,,,,293,249,,,,,,,293,293,,887,,249,249,891',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,249,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,249,,,',
+',,,,,,,,,,,,,,,556,,,,,249,,,,,,,,,,,,,,,,,,,,249,873,875,,,,,,,,,,',
+'779,781,784,812,,,,,,,,,,,249,,,,812,,,,,,,,,,,,,,,293,,293,293,293',
'293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293,293',
-'293,,,,,,,,,293,,293,,,249,,293,,,,,,,,,,,,875,873,,,,249,,,,,,,293',
-',,,,,,,,,,,249,293,,,,,,,,,293,,,,,,,,,,,249,,,,,,,,,,,,,,,,,,,,,,,',
-'249,,,,,,,,,,,,,,633,,,,,633,,,,,,812,817,293,,,,,,,,,556,,,556,556',
-',,,,,812,,812,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,293,,,,,,,,,,,,,,,,,,,,',
-',,,,,,,,,,,,293,293,293,,,,,,,,,,,,,,,,,,,,,,,887,,,,891,,,,293,,293',
-',293,,,,,,,,,,,,,,,,,,,,,,,,,,,293,,,,,,,,,,,,,293,293,293,,,,,,,,,',
-'293,,,293,,,,,,,,,,,,293,,,556,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
-',,,812,,,,,,,,,,,,,,,812,,,,,,,,293,,293,,,,,,,,,,,,293,,,,,,,,,,,293',
-',,,,,,,293,,,,,,,,,,,,293,293,,,,,,,,,,,293,,,,,,,,,,,,293,,,,,,293',
-',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,293,,,,,,,,,,,,,,,,,,,,,,,,293,,,,,,,',
-',,,,,,,,,,,,293,,,,,,,,,,,,,293,293,293,,,,,,,,,,,,293,,,,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,293,,,,,,,,,,,,,,293,293',
-',,,293,,,,,,,,,293,,,,,,,,,,293,,,,,,,,,,,,,,,,,,,,,293' ]
- racc_goto_table = arr = ::Array.new(2500, nil)
+'293,293,293,293,293,293,,,,,,,,,293,,293,,,249,,293,,,,,,,,,,,,875,873',
+',,,249,,,,,,,293,,,,,,,,,,,,249,293,,,,,,,,,293,,,,,,,,,,,249,,,,,,',
+',,,,,,,,,,,,,,,,,249,,,,,,,,,,,,,,,,,,,,,,,,,,,293,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,293,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,293,293,293,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,293,,293,,293,,,,,,,,,,',
+',,,,,,,,,,,,,,,,293,,,,,,,,,,,,,293,293,293,,,,,,,,,,293,,,293,,,,,',
+',,,,,,293,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,293,,293,,,,,,,,,,,,293,,,,,,,,,,,293,,,,,,,,293,,,,,,,,,,,',
+'293,293,,,,,,,,,,,293,,,,,,,,,,,,293,,,,,,293,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,293,,,,,,,,,,,,,,,,,,,,,,,,293,,,,,,,,,,,,,,,,,,,,293,,,,,,',
+',,,,,,293,293,293,,,,,,,,,,,,293,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,293,,,,,,,,,,,,,,293,293,,,,293,,,,,,,,,293',
+',,,,,,,,,293,,,,,,,,,,,,,,,,,,,,,293' ]
+ racc_goto_table = arr = ::Array.new(2674, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -2011,72 +2011,74 @@ clist = [
end
clist = [
-'21,51,80,54,54,54,22,47,41,10,29,29,29,7,145,43,83,21,21,8,154,47,21',
-'21,21,48,48,104,52,52,21,21,21,61,24,24,35,84,107,16,16,29,6,16,147',
-'141,14,14,23,106,46,78,21,21,33,33,33,21,21,52,52,21,21,21,110,39,77',
-'77,56,56,56,79,79,4,83,50,50,154,23,23,23,45,89,48,108,16,16,16,16,90',
-'62,148,62,57,57,142,142,48,109,21,56,109,109,21,21,21,21,21,21,62,23',
-'23,7,2,38,42,60,33,33,33,7,7,129,55,55,91,11,55,129,92,93,4,94,20,47',
-'151,36,126,126,95,96,126,97,98,99,100,101,23,36,11,102,103,22,22,105',
-'23,23,27,36,36,19,15,112,20,113,115,116,117,60,60,60,118,119,120,124',
-'125,127,54,54,31,31,31,128,130,131,132,111,29,29,17,111,133,135,137',
-'141,21,21,21,21,21,21,139,154,144,21,21,21,5,149,12,48,18,63,110,21',
-'21,151,64,72,17,48,2,73,74,76,59,1,58,81,80,82,111,20,108,85,43,86,87',
-'88,,20,20,145,23,,145,,142,,54,54,17,51,,,,29,29,54,,,,23,,,29,,,21',
-'21,51,,51,62,62,41,,21,,,78,21,52,,61,21,21,,17,,,83,,104,,52,17,17',
-'21,,,,33,33,107,,,,,21,45,34,34,34,56,56,39,6,106,148,,39,,56,,,,,20',
-'23,,16,16,23,23,79,108,,,108,108,147,108,,108,,23,20,4,21,21,,,,129',
-'84,46,23,,,57,11,57,141,83,38,52,60,42,21,38,,,,33,,,33,,83,111,21,110',
-',17,,,33,,18,18,18,,,145,,,18,,43,,35,108,17,22,22,35,,,35,,,154,,20',
-'10,,23,,20,,4,,108,,31,31,,,48,,,,48,31,,61,33,,29,29,,20,,,,33,,,,14',
-'21,21,8,14,111,,8,8,51,,,,,,143,143,143,48,,17,,,22,,17,22,,,50,,,109',
-'50,62,109,109,111,,111,,,,,,41,,,17,57,,,,,57,145,21,,29,57,,29,21,55',
-',52,,,21,,21,,,21,62,7,,,,,,,,56,,,22,21,24,22,48,,,,,22,,,,111,,21',
-'21,48,,52,,77,21,,23,57,57,57,51,,23,,,,111,29,21,,29,,21,,16,,29,21',
-'61,21,80,,21,,,56,83,83,21,,,,21,,21,23,23,,,48,,,23,,77,48,83,44,,',
-'8,77,,143,143,143,23,,,104,23,,,,,23,21,21,,,107,,21,,9,,,44,44,44,',
-'20,,,,,25,,,8,21,,,,,41,143,,,61,,109,,21,,,,41,,44,44,,44,21,21,52',
-',54,21,,20,20,,,,,,52,,,21,,,,,,,17,23,,,20,,,47,20,44,,54,,20,23,56',
-'34,44,44,16,,34,,,23,23,34,,,23,,,,,,,,21,,17,17,23,21,,,,21,21,,,,',
-',,57,,83,57,83,57,17,,83,,17,,,,21,17,,,,,,21,21,,34,34,34,,54,48,,',
-'20,,,,23,25,25,,23,23,,,33,20,,,9,,,44,,51,,20,20,,21,16,,23,23,,,,',
-'9,18,18,44,,,,18,,,21,,21,21,,,,,48,,,17,,,,,,,25,,25,,83,,17,25,,,',
-'23,,,,,17,17,,,,,,,,,20,,,,20,20,23,23,,,21,52,,9,21,,44,,9,,44,44,22',
-',,21,20,,21,,,,,44,,,,,,,,,,,44,,,21,,,,,,,21,,17,29,23,21,17,17,23',
-',,,,21,,21,20,,,23,,,23,,,,,,17,,,,,,,48,26,20,20,18,18,23,,,,,,,23',
-',44,,,23,,,,,,,,23,,28,,,,28,28,28,,26,17,,,,26,26,,,26,,,28,28,28,',
-'25,,20,,,,17,17,,,,28,28,,,,,20,,,20,,,,,,,,,,,,,,,26,26,26,26,20,,',
-',,,,20,,,,,20,,,,,,,17,20,,,17,,,,25,,25,,25,,,17,,,17,,,,,,,,,25,,',
-',,,,,,,17,,,,,,,17,,,,44,17,,,,,44,,,17,,,,,,,25,,,25,,,,,,,,,,,,26',
-'26,,,,9,9,,44,44,26,,,,,44,,28,28,28,28,28,,,,28,9,,,44,9,,,44,,9,,',
-'44,28,,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28',
-'28,28,28,28,28,,,25,,,,,,28,,28,,,,,28,,,,,,,28,28,,,,,,,,28,,25,,,',
-',,,,9,,,44,25,25,,,,,,,,9,,,44,,,,28,,,9,9,,44,44,,,,44,,,25,,26,26',
-',,53,,,44,,,,,,,,,,,,,,53,,53,53,53,53,53,,25,,,26,,,,,,,,,,,,,,,,,',
-',,,25,,,44,,,,44,44,,,,,,,,,,,,25,,,,,,9,,,44,,,,,,,,,,,,,,,,28,,25',
-',,,,,,,,,,,,,,,,,,,,,,9,,,44,,28,28,,28,28,28,,,,,,,,,,,9,9,,44,44,',
-',,,,,,,26,,,25,,,,28,,28,,28,,,,,,,,,,,25,,,,28,,,,,26,,,,,,,,9,28,25',
-'44,28,,,44,,,,,28,28,28,9,,,44,,53,44,,25,28,,,28,,,,,,,,,,9,,,44,,',
-',9,,,44,,9,,26,44,26,,,,,,,44,,,,28,,,28,,,,,,28,,,,,53,,,53,53,,,,',
-',,,,,,,,,,,,,,,,,,,28,,28,,,28,28,,,37,37,28,,,28,,37,37,37,,,,,,,28',
-',,,,,,37,28,,,,,,,37,37,,,,28,28,,,,,,,,,,,,,,,,,,,,,,,,,,,,,28,,,53',
-',,,,,,,,26,53,,,,,,,,,,,,,,,,,,28,,,,,,,,,,,,,,,,,,,,,,,,28,53,,,,,',
-',,,53,53,53,53,,,,,,,28,28,28,53,53,,,,,,,,,28,28,28,,,,,,,,,,,,28,',
-',,26,,,,,,,,,,,,,,,37,,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37',
-'37,37,37,37,37,37,37,37,37,37,37,,,,,,,,,37,,37,,,28,,37,,,,,,,,,,,',
-'28,28,,,,28,,,,,,,37,,,,,,,,,,,,28,37,,,,,,,,,37,,,,,,,,,,,28,,,,,,',
-',,,,,,,,,,,,,,,,,28,,,,,,,,,,,,,,53,,,,,53,,,,,,53,53,37,,,,,,,,,53',
-',,53,53,,,,,,53,,53,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,37,37,37,,,,,,,,,,,,,,,,,,,,,,,53,,,,53,,,,37,,37,',
-'37,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,37,37,37,,,,,,,,,,37,,,37',
-',,,,,,,,,,,37,,,53,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,53,,,,,,',
-',,,,,,,,53,,,,,,,,37,,37,,,,,,,,,,,,37,,,,,,,,,,,37,,,,,,,,37,,,,,,',
-',,,,,37,37,,,,,,,,,,,37,,,,,,,,,,,,37,,,,,,37,,,,,,,,,,,,,,,,,,,,,,',
-',,,,,,,,37,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,',
-',,,37,37,37,,,,,,,,,,,,37,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,37,37,,,,37,,,,,,,,,37,,,,,,,,,,37',
-',,,,,,,,,,,,,,,,,,,,37' ]
- racc_goto_check = arr = ::Array.new(2500, nil)
+'21,22,51,10,104,47,35,48,48,8,29,29,29,33,33,33,7,21,21,47,41,61,21',
+'21,21,154,107,83,52,52,21,21,21,77,77,43,17,4,20,109,84,29,109,109,54',
+'54,54,46,145,14,14,80,21,21,50,50,18,21,21,52,52,21,21,21,6,48,17,147',
+'20,24,24,110,106,34,34,34,33,33,33,48,55,55,154,2,55,83,38,42,56,56',
+'56,129,141,79,79,4,108,129,17,21,1,151,45,21,21,21,21,21,21,16,16,5',
+'39,16,60,7,148,111,126,126,56,111,126,7,7,12,78,31,31,31,15,19,47,27',
+'58,17,59,20,63,64,26,36,11,17,17,20,20,22,22,142,142,72,73,36,74,16',
+'16,16,16,76,81,82,111,36,36,11,60,60,60,85,86,87,88,89,90,26,91,92,93',
+'94,26,26,151,95,26,96,97,29,29,98,99,2,48,100,101,21,21,21,21,21,21',
+'102,48,103,21,21,21,154,105,112,113,62,115,62,21,21,116,117,54,54,110',
+'118,119,120,124,125,26,26,26,26,62,17,127,20,18,18,18,128,130,131,132',
+'141,18,133,135,108,137,139,144,149,17,,20,51,,43,29,29,,,,33,33,,,29',
+',,21,21,104,51,61,51,,,145,21,80,145,,21,52,,,21,21,41,,,54,54,107,',
+',52,,,21,54,,142,83,,,,,,,21,,111,4,,,,,17,,20,,,17,129,20,,57,57,26',
+'26,23,45,,33,56,56,33,38,26,6,42,106,38,56,148,17,33,20,108,21,21,108',
+'108,46,108,78,108,79,84,,23,23,23,39,147,60,52,,39,21,,35,,31,31,83',
+'35,11,,35,,21,31,,,4,111,,,110,83,,23,23,62,62,33,,,22,22,16,16,,,33',
+',,,10,141,48,,,108,48,,154,111,43,111,,,109,61,,109,109,145,23,,,,,',
+'108,,23,23,29,29,,,8,,,,8,8,,48,21,21,14,,,,14,50,,51,,50,,,,,,22,,55',
+'22,26,26,,,,,,34,111,,,,34,,,,,34,,,,,,,,,,,,111,,,26,,21,41,29,,,29',
+'21,,,52,,,21,,21,,48,21,77,23,,,7,,,22,,,22,48,,21,,145,22,34,34,34',
+'23,,,,17,,20,21,21,56,,52,,,21,,,,,,,51,,,,,61,29,21,24,29,77,21,143',
+'143,143,29,21,77,21,,48,21,17,17,20,20,48,21,57,44,57,21,,21,,104,83',
+'83,,8,62,109,,17,56,20,23,17,,20,23,23,17,,20,,83,107,,44,44,44,,23',
+'26,21,21,,80,,,21,,,23,,,,8,,62,,,16,,,61,,,21,,44,44,,44,26,,9,,,,',
+'21,18,18,,41,,,18,,,21,21,52,,,21,41,,,,,,,17,52,20,44,21,,,,,23,,44',
+'44,17,,20,47,,,,,,,17,17,20,20,,,26,,26,54,,,,,,,143,143,143,57,,,,56',
+'57,21,,,,57,21,,,,21,21,,,,,54,,,,,33,,,,,,,,48,,83,21,83,,143,,83,',
+'21,21,,17,,20,,17,17,20,20,,,44,16,,,,57,57,57,,,,,,,,,17,,20,44,51',
+',,,21,18,18,,,,,,,48,,54,,,9,,,,,21,25,21,21,,,,,,,23,,,,9,,23,17,,20',
+',,,,,,,,,26,,,,83,,,,,17,17,20,20,,44,,,,44,44,23,23,,16,,21,52,23,',
+'21,,44,22,,,,,,,,21,23,44,21,,23,,,,,23,,9,,,,,9,,,,17,21,20,,17,,,',
+'21,,,29,,21,,17,,20,17,,20,21,,21,,48,,,,,,,,26,,,,17,,20,,44,,,17,',
+'20,,,17,,20,,25,25,,,17,,20,,,23,,,,57,,,57,,57,,,,23,,,,,,,,,,23,23',
+',,,23,,,,,,,,,,,,23,,,,,,,,,25,,25,,,,,25,,,,,,,,,,,,,,,,,,,,,,53,,',
+',,,,,,,,23,,,,23,23,53,,53,53,53,53,53,,,,,,,,,,,,,23,23,,,,,,,44,,',
+',,,44,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,23,,44,44,,,,,,44,,,,,,,,,,,,23',
+'23,44,28,,,44,28,28,28,,44,,,,,,,,9,9,,,28,28,28,,,,,,,,,,,25,,28,28',
+'9,,,,9,,,,,9,,,23,,,,23,,,,,,,,,,,23,,,23,,,,,,,,,,,,,,44,,,,,23,,,',
+',,,23,44,,,,23,25,,25,,25,44,44,23,53,,44,,,,,,,,,25,9,,44,,,,,,,,,',
+',9,,,,,,,,,,9,9,,,,,,,,,,,,25,,,25,,,,,,,53,,,53,53,44,,,,44,44,,,28',
+'28,28,28,28,,,,28,,,,,,,,,,44,,,,28,,28,28,28,28,28,28,28,28,28,28,28',
+'28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,,,,,,,9,,28,,28,25,44,',
+',28,,,,,,,28,28,,,,,,,,28,,44,44,,,,,,,,25,53,,,,,,,9,,,53,25,25,,,',
+',,28,,,,,,,,,,9,9,,,,,,,,,,,,25,44,,,,44,,,,,,,53,,,,44,,,44,,53,53',
+'53,53,,,,,,,25,,,53,53,,,44,9,,,,,,44,,,,,44,,,,9,25,,,44,,,,,,,,,,',
+',,,,,,25,9,,,,,,,9,,,,,9,,,28,,,,,,,,,,,25,,,,,,,,,,,,,,,,,,,28,28,',
+'28,28,28,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,28,,28,,28,25,,,,,,,,,,,,,,28',
+',,,,25,,,,,,,,,28,,,28,,,,,,,25,28,28,28,,,,,,,,,,28,,53,28,,,,53,25',
+',,,,53,53,,,,,,,,,,53,,,53,53,,,,,,53,,53,,,,28,,,28,,,,,,28,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,28,,28,,,28,28,,,37,37,28,,,28,,37,37,37,,',
+',,,,28,,,,,,,37,28,,,,,,,37,37,,53,,28,28,53,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,28,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,28,,,,,,,,,,,,,,,,,,,53,,,,,28',
+',,,,,,,,,,,,,,,,,,,28,28,28,,,,,,,,,,,28,28,28,53,,,,,,,,,,,28,,,,53',
+',,,,,,,,,,,,,,37,,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37',
+'37,37,37,37,37,37,37,37,37,,,,,,,,,37,,37,,,28,,37,,,,,,,,,,,,28,28',
+',,,28,,,,,,,37,,,,,,,,,,,,28,37,,,,,,,,,37,,,,,,,,,,,28,,,,,,,,,,,,',
+',,,,,,,,,,,28,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,37,37',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,37,,37,,,,,,,,,,,,,,,,,,,,,,,,,,,37',
+',,,,,,,,,,,,37,37,37,,,,,,,,,,37,,,37,,,,,,,,,,,,37,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,37,,,,,,,,,,,',
+'37,,,,,,,,,,,37,,,,,,,,37,,,,,,,,,,,,37,37,,,,,,,,,,,37,,,,,,,,,,,,37',
+',,,,,37,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,,,,,,,,,,,37,',
+',,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,37,37,37,,,,,,,,,,,,37,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,37,,,,,,,,,,,,,,37,37',
+',,,37,,,,,,,,,37,,,,,,,,,,37,,,,,,,,,,,,,,,,,,,,,37' ]
+ racc_goto_check = arr = ::Array.new(2674, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -2086,22 +2088,22 @@ clist = [
end
racc_goto_pointer = [
- nil, 226, 113, nil, 70, 108, 39, 13, -290, 608,
- -529, -573, -602, nil, 39, 153, -18, 189, 193, 98,
- 133, 0, -47, 48, -162, 596, 949, 48, 975, -12,
- nil, 157, nil, -147, 285, -231, -349, 1578, 84, 35,
- nil, -23, 83, -283, 611, -281, -13, -58, 18, nil,
- 68, -40, -3, 1246, -19, -190, 46, 67, -41, -274,
- -326, -219, -397, -294, -52, nil, nil, nil, nil, nil,
- nil, nil, 153, 168, 168, nil, 168, -281, -669, -506,
- -350, 166, -136, 13, -563, 169, -143, 186, 179, -641,
- 29, -602, -459, -772, -462, -228, -705, 78, -456, -234,
- -456, -717, 94, -170, -29, -405, -506, -18, -516, -228,
- -536, -369, 142, -82, nil, -107, -107, -767, -411, -528,
- -642, nil, nil, nil, 103, 102, 62, 99, -207, -261,
- 105, -584, -423, -418, nil, -557, nil, -659, nil, -651,
- nil, -555, -662, -295, -653, -324, nil, -515, -247, -510,
- nil, -723, nil, nil, -469 ]
+ nil, 100, 83, nil, 34, 12, 61, 16, -300, 632,
+ -535, -557, -686, nil, 42, 122, 52, 36, 38, 69,
+ 38, 0, -52, 330, -127, 779, 123, 24, 1149, -12,
+ nil, 105, nil, -188, 47, -261, -344, 1752, 56, 82,
+ nil, -11, 55, -263, 594, -260, -16, -60, 0, nil,
+ 47, -39, -3, 1006, 22, -233, 66, 300, -134, -363,
+ -328, -231, -276, -368, -130, nil, nil, nil, nil, nil,
+ nil, nil, 86, 98, 99, nil, 103, -314, -594, -484,
+ -301, 98, -205, 24, -560, 104, -209, 120, 113, -550,
+ 114, -551, -411, -724, -415, -184, -660, 122, -410, -188,
+ -408, -669, 145, -118, -52, -351, -483, -30, -504, -287,
+ -529, -438, 189, -36, nil, -60, -57, -717, -361, -478,
+ -592, nil, nil, nil, 153, 152, 43, 155, -152, -292,
+ 160, -529, -368, -366, nil, -505, nil, -606, nil, -605,
+ nil, -508, -608, -183, -608, -290, nil, -492, -222, -469,
+ nil, -757, nil, nil, -464 ]
racc_goto_default = [
nil, nil, nil, 3, nil, 4, 353, 279, nil, 538,
diff --git a/test/racc/regress/php_serialization b/test/racc/regress/php_serialization
index 0aba4b4d3e..e412db1cc8 100644
--- a/test/racc/regress/php_serialization
+++ b/test/racc/regress/php_serialization
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -31,27 +31,27 @@ module_eval(<<'...end php_serialization.y/module_eval...', 'php_serialization.y'
##### State transition tables begin ###
racc_action_table = [
- 9, 10, 18, 20, 11, 12, 13, 21, 14, 9,
- 10, 15, 22, 11, 12, 13, 23, 14, 24, 46,
- 15, 9, 10, 25, 26, 11, 12, 13, 27, 14,
- 9, 10, 15, 28, 11, 12, 13, 29, 14, 30,
- 51, 15, 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 43, 49, 47, 16, 17, 19 ]
+ 9, 10, 16, 17, 11, 12, 13, 18, 14, 9,
+ 10, 15, 19, 11, 12, 13, 20, 14, 21, 46,
+ 15, 9, 10, 22, 23, 11, 12, 13, 24, 14,
+ 9, 10, 15, 25, 11, 12, 13, 26, 14, 27,
+ 51, 15, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 43, 47, 49 ]
racc_action_check = [
- 0, 0, 3, 5, 0, 0, 0, 6, 0, 42,
- 42, 0, 10, 42, 42, 42, 11, 42, 12, 42,
- 42, 45, 45, 13, 14, 45, 45, 45, 15, 45,
- 50, 50, 45, 16, 50, 50, 50, 22, 50, 23,
- 50, 50, 24, 25, 26, 27, 32, 33, 34, 35,
- 36, 37, 39, 41, 47, 43, 1, 2, 4 ]
+ 0, 0, 1, 2, 0, 0, 0, 3, 0, 42,
+ 42, 0, 4, 42, 42, 42, 5, 42, 6, 42,
+ 42, 45, 45, 10, 11, 45, 45, 45, 12, 45,
+ 50, 50, 45, 13, 50, 50, 50, 14, 50, 15,
+ 50, 50, 16, 22, 23, 24, 25, 26, 27, 32,
+ 33, 34, 35, 36, 37, 39, 41, 43, 47 ]
racc_action_pointer = [
- -3, 56, 55, 0, 56, 1, 5, nil, nil, nil,
- 7, 11, 13, 18, 19, 23, 33, nil, nil, nil,
- nil, nil, 31, 33, 36, 37, 38, 39, nil, nil,
- nil, nil, 41, 42, 43, 39, 40, 39, nil, 47,
- nil, 47, 6, 50, nil, 18, nil, 42, nil, nil,
+ -3, 2, 1, 5, 10, 14, 16, nil, nil, nil,
+ 18, 19, 23, 28, 32, 34, 42, nil, nil, nil,
+ nil, nil, 37, 38, 39, 40, 41, 42, nil, nil,
+ nil, nil, 44, 45, 46, 42, 43, 42, nil, 50,
+ nil, 50, 6, 52, nil, 18, nil, 46, nil, nil,
27, nil ]
racc_action_default = [
diff --git a/test/racc/regress/riml b/test/racc/regress/riml
index ce7f845426..965afc31f5 100644
--- a/test/racc/regress/riml
+++ b/test/racc/regress/riml
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -92,87 +92,101 @@ module_eval(<<'...end riml.y/module_eval...', 'riml.y', 592)
##### State transition tables begin ###
clist = [
-'135,211,60,265,136,139,417,418,211,211,448,211,409,411,146,56,199,89',
-'272,258,409,270,409,271,37,46,48,47,37,49,44,45,64,449,37,392,412,60',
-'50,70,-116,61,60,50,70,62,63,129,130,132,127,128,131,115,116,117,121',
+'135,265,60,139,136,211,417,418,48,47,411,211,448,274,146,56,199,89,272',
+'60,273,270,409,271,37,46,48,47,37,49,44,45,392,412,37,449,384,60,50',
+'70,316,61,386,385,317,62,63,129,130,132,127,128,131,115,116,117,121',
'122,123,118,119,120,124,125,126,102,104,103,109,111,110,112,114,113',
-'106,108,107,133,134,101,100,137,188,80,38,52,37,81,38,82,85,83,84,87',
+'106,108,107,133,134,101,100,137,171,80,38,173,37,81,38,82,85,83,84,87',
'38,105,86,37,75,76,153,152,57,56,88,89,77,37,90,58,59,78,37,46,48,47',
-'91,49,44,45,64,72,73,-116,211,60,50,70,79,61,48,47,319,62,63,409,274',
-'-178,-178,-178,-178,60,147,273,329,316,38,-43,-43,317,331,-85,-85,-85',
-'-85,48,47,38,320,258,141,-42,-42,313,272,161,60,38,139,271,29,161,38',
-'52,313,54,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120',
-'124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133,134',
-'101,100,137,182,80,277,279,164,81,164,82,85,83,84,87,164,105,86,164',
-'75,76,149,277,57,56,88,89,77,149,90,58,59,78,37,46,48,47,91,49,44,45',
-'64,72,73,-116,279,60,50,70,79,61,149,-204,462,62,63,384,164,164,400',
-'277,60,386,385,149,401,-178,-178,-178,-178,-99,147,-48,-48,164,-176',
-'-176,-176,-176,-44,-44,211,402,48,47,463,49,-98,60,50,70,29,403,38,52',
-'80,54,164,216,81,139,82,85,83,84,87,149,279,86,52,75,76,164,139,57,56',
-'88,89,77,-99,90,58,59,78,37,46,48,47,91,49,44,45,64,72,73,-116,-98,60',
-'50,70,79,61,371,-46,-46,62,63,-175,-175,-175,-175,60,50,70,-203,-47',
-'-47,-45,-45,164,153,152,129,130,132,211,215,48,47,371,49,191,192,193',
-'194,305,433,366,432,129,130,132,29,60,38,52,80,54,406,370,81,60,82,85',
-'83,84,87,149,465,86,99,75,76,153,152,57,56,88,89,77,105,90,58,59,78',
-'37,46,48,47,91,49,44,45,64,72,73,-116,105,60,50,70,79,61,164,354,323',
-'62,63,-175,-175,-175,-175,417,437,153,152,60,211,195,211,211,427,60',
-'139,430,92,431,434,435,438,440,320,441,442,443,211,129,130,132,127,128',
-'131,445,29,105,38,52,446,54,129,130,132,127,128,131,115,116,117,121',
+'91,49,44,45,64,72,73,-116,161,60,50,70,79,61,272,37,92,62,63,271,48',
+'47,-178,-178,-178,-178,211,147,211,211,38,60,-43,-43,153,152,329,409',
+'99,409,409,38,331,153,152,-42,-42,161,60,50,70,38,139,313,29,313,38',
+'52,80,54,164,277,81,277,82,85,83,84,87,279,279,86,149,75,76,38,182,57',
+'56,88,89,77,149,90,58,59,78,37,46,48,47,91,49,44,45,64,72,73,-116,164',
+'60,50,70,79,61,164,60,164,62,63,-204,277,149,164,279,164,-203,305,149',
+'366,141,164,164,-44,-44,129,130,132,-85,-85,-85,-85,142,-48,-48,-116',
+'258,60,50,70,-99,-98,60,50,70,29,149,38,52,80,54,371,149,81,52,82,85',
+'83,84,87,149,139,86,164,75,76,164,139,57,56,88,89,77,105,90,58,59,78',
+'37,46,48,47,91,49,44,45,64,72,73,-99,-98,60,50,70,79,61,-46,-46,370',
+'62,63,-175,-175,-175,-175,139,129,130,132,-47,-47,-45,-45,433,195,432',
+'129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125',
+'126,164,354,29,211,38,52,80,54,153,152,81,60,82,85,83,84,87,149,60,86',
+'105,75,76,417,437,57,56,88,89,77,105,90,58,59,78,215,46,48,47,91,49',
+'44,45,64,72,73,-116,216,60,50,70,79,61,139,218,319,62,63,-175,-175,-175',
+'-175,-178,-178,-178,-178,211,147,48,47,211,49,48,47,262,49,-176,-176',
+'-176,-176,263,320,191,192,193,194,267,129,130,132,127,128,131,29,269',
+'269,52,269,54,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
+'120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133',
+'134,101,100,137,323,105,258,276,294,295,149,139,302,305,306,105,139',
+'105,312,326,327,328,333,105,105,105,342,346,357,361,320,258,362,363',
+'60,129,130,132,127,128,131,129,130,132,127,128,131,368,129,130,132,127',
+'128,131,115,116,117,121,122,123,118,119,120,124,125,126,102,104,103',
+'109,111,110,112,114,113,106,108,107,133,134,101,100,137,105,80,129,130',
+'132,81,105,82,85,83,84,87,374,105,86,377,75,76,379,380,57,56,88,89,77',
+'393,90,58,59,78,37,46,48,47,91,49,44,45,64,72,73,-116,302,60,50,70,79',
+'61,394,397,105,62,63,269,258,129,130,132,127,128,131,115,116,117,121',
'122,123,118,119,120,124,125,126,102,104,103,109,111,110,112,114,113',
-'106,108,107,133,134,101,100,137,105,80,129,130,132,81,371,82,85,83,84',
-'87,371,105,86,105,75,76,149,342,57,56,88,89,77,105,90,58,59,78,37,46',
-'48,47,91,49,44,45,64,72,73,302,346,60,50,70,79,61,328,327,105,62,63',
-'326,312,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120',
+'106,108,107,133,134,101,29,400,38,52,80,54,401,402,81,-245,82,85,83',
+'84,87,105,403,86,406,75,76,60,211,57,56,88,89,77,211,90,58,59,78,37',
+'46,48,47,91,49,44,45,64,72,73,427,60,60,50,70,79,61,430,431,434,62,63',
+'435,438,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120',
'124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133,134',
-'101,29,139,38,52,80,54,105,306,81,305,82,85,83,84,87,105,333,86,139',
-'75,76,149,357,57,56,88,89,77,295,90,58,59,78,37,46,48,47,91,49,44,45',
-'64,72,73,294,149,60,50,70,79,61,361,258,362,62,63,363,276,129,130,132',
-'127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102,104',
-'103,109,111,110,112,114,113,106,108,107,133,134,60,29,211,38,52,80,54',
-'458,435,81,368,82,85,83,84,87,105,258,86,269,75,76,374,269,57,56,88',
-'89,77,269,90,58,59,78,37,46,48,47,91,49,44,45,64,72,73,377,267,60,50',
-'70,79,61,379,380,263,62,63,262,393,129,130,132,127,128,131,115,116,117',
-'121,122,123,118,119,120,124,125,126,302,394,218,468,397,139,142,269',
-',,,129,130,132,,29,,38,52,80,54,,,81,-245,82,85,83,84,87,105,,86,,75',
-'76,,,57,56,88,89,77,,90,58,59,78,37,46,48,47,91,49,44,45,64,72,73,105',
-',60,50,70,79,61,,,,62,63,,,129,130,132,127,128,131,115,116,117,121,122',
+'440,29,441,38,52,80,54,442,443,81,211,82,85,83,84,87,105,445,86,446',
+'75,76,371,371,57,56,88,89,77,211,90,58,59,78,37,46,48,47,91,49,44,45',
+'64,72,73,458,435,60,50,70,79,61,462,463,371,62,63,465,468,129,130,132',
+'127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,,,,,,,,',
+',,,129,130,132,,29,,38,52,80,54,,,81,,82,85,83,84,87,105,,86,,75,76',
+',,57,56,88,89,77,,90,58,59,78,37,46,48,47,91,49,44,45,64,72,73,105,',
+'60,50,70,79,61,,,,62,63,,,129,130,132,127,128,131,115,116,117,121,122',
'123,118,119,120,124,125,126,,,,,,,,,,,,129,130,132,,29,,38,52,80,54',
',,81,,82,85,83,84,87,105,,86,,75,76,,,57,56,88,89,77,,90,58,59,78,37',
-'46,48,47,91,49,44,45,64,72,73,105,,60,50,70,79,61,,,,62,63,419,,,,,',
+'46,48,47,91,49,44,45,64,72,73,105,,60,50,70,79,61,,,,62,63,414,,,,,',
',,,,,,,,,,,,,,,,,,,,,,,,,,,,,29,,38,52,,54,,129,130,132,127,128,131',
'115,116,117,121,122,123,118,119,120,124,125,126,102,104,103,109,111',
-'110,112,114,113,106,108,107,133,134,101,100,137,414,,,,,,,,,146,56,',
+'110,112,114,113,106,108,107,133,134,101,100,137,419,,,,,,,,,146,56,',
'89,105,,90,,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,129,130',
'132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102',
'104,103,109,111,110,112,114,113,106,108,107,133,134,101,100,137,29,',
',52,,54,,261,146,56,,89,,105,90,,,,,46,48,47,,49,44,45,64,,,,,60,50',
-'70,,61,,,,62,63,180,146,56,,89,,,90,,,,,46,48,47,,49,44,45,64,,,,,60',
-'50,70,,61,,,,62,63,,29,,,52,,54,,261,129,130,132,127,128,131,115,116',
-'117,121,122,123,118,119,120,124,125,126,,,,365,146,56,,89,29,-119,90',
-'52,,54,,46,48,47,,49,44,45,64,,,,,60,50,70,105,61,,,,62,63,180,146,56',
-',89,,,90,,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,,29,146',
-'56,52,89,54,,90,,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63',
-'29,-121,,52,,54,,,,129,130,132,127,128,131,115,116,117,121,122,123,118',
-'119,120,124,125,126,,,,180,146,56,,89,29,,90,52,,54,350,46,48,47,,49',
-'44,45,64,,,,,60,50,70,105,61,,,,62,63,180,146,56,,89,,,90,,,,,46,48',
-'47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,,29,-119,,52,,54,,,129,130',
-'132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,,,,180',
-'146,56,,89,29,-119,90,52,,54,,46,48,47,,49,44,45,64,,,,,60,50,70,105',
-'61,,,,62,63,180,146,56,,89,,,90,,,,,46,48,47,,49,44,45,64,,,,,60,50',
-'70,,61,,,,62,63,,29,-119,,52,,54,,,129,130,132,127,128,131,115,116,117',
-'121,122,123,118,119,120,124,125,126,,,,180,146,56,,89,29,-119,90,52',
-',54,,46,48,47,,49,44,45,64,,,,,60,50,70,105,61,,,,62,63,180,146,56,',
-'89,,,90,,,,,46,48,47,,49,44,45,64,,,-116,,60,50,70,,61,,,,62,63,,29',
-'-119,,52,,54,,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
-'120,124,125,126,,,,180,146,56,,89,,176,90,,52,,54,46,48,47,,49,44,45',
+'70,,61,,,,62,63,180,146,56,,89,,,90,,,,,46,48,47,,49,44,45,64,,,-116',
+',60,50,70,,61,,,,62,63,,29,,,52,,54,,261,,129,130,132,127,128,131,115',
+'116,117,121,122,123,118,119,120,124,125,126,,180,146,56,,89,,176,90',
+',52,,54,46,48,47,,49,44,45,64,,,,,60,50,70,,61,105,,,62,63,180,146,56',
+',89,,,90,,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,,29,-119',
+',52,,54,,,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120',
+'124,125,126,,,,180,146,56,,89,29,-119,90,52,,54,,46,48,47,,49,44,45',
'64,,,,,60,50,70,105,61,,,,62,63,180,146,56,,89,,,90,,,,,46,48,47,,49',
'44,45,64,,,,,60,50,70,,61,,,,62,63,,29,-119,,52,,54,,,129,130,132,127',
'128,131,115,116,117,121,122,123,118,119,120,124,125,126,,,,180,146,56',
',89,29,-119,90,52,,54,,46,48,47,,49,44,45,64,,,,,60,50,70,105,61,,,',
-'62,63,146,56,,89,,,90,,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,',
-'62,63,,,29,-119,,52,,54,129,130,132,127,128,131,115,116,117,121,122',
-'123,118,119,120,124,125,126,,,,,146,56,,89,,29,90,,52,,54,46,48,47,',
-'49,44,45,64,,,,,60,50,70,105,61,,,,62,63,146,56,,89,,,90,,,,,46,48,47',
+'62,63,180,146,56,,89,,,90,,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61',
+',,,62,63,,29,-121,,52,,54,,,129,130,132,127,128,131,115,116,117,121',
+'122,123,118,119,120,124,125,126,,,,,146,56,,89,29,-119,90,52,,54,,46',
+'48,47,,49,44,45,64,,,,,60,50,70,105,61,,,,62,63,180,146,56,,89,,,90',
+',,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,,29,,,52,,54,350',
+',129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125',
+'126,,,,180,146,56,,89,29,-119,90,52,,54,,46,48,47,,49,44,45,64,,,,,60',
+'50,70,105,61,,,,62,63,365,146,56,,89,,,90,,,,,46,48,47,,49,44,45,64',
+',,,,60,50,70,,61,,,,62,63,,29,-119,,52,,54,,129,130,132,127,128,131',
+'115,116,117,121,122,123,118,119,120,124,125,126,,,,180,146,56,,89,,29',
+'90,,52,,54,46,48,47,,49,44,45,64,,,,,60,50,70,105,61,,,,62,63,180,146',
+'56,,89,,,90,,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,,29',
+'-119,,52,,54,,,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
+'120,124,125,126,,,,,146,56,,89,29,-119,90,52,,54,,46,48,47,,49,44,45',
+'64,,,,,60,50,70,105,61,,,,62,63,146,56,,89,,,90,,,,,46,48,47,,49,44',
+'45,64,,,-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48',
+'47,,49,44,45,64,,,-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54',
+',,167,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,',
+'52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,165',
+'89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146',
+'56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63',
+'146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,-116,,60,50,70,,61',
+',,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70',
+',61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60',
+'50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,',
+',,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45',
+'64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49',
+'44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47',
',49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46',
'48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54',
',,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52',
@@ -204,30 +218,33 @@ clist = [
'49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48',
'47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,',
'46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90',
-'54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,,,29,,,52,348',
-'54,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125',
-'126,,,,,146,56,,89,,29,90,,52,,54,46,48,47,,49,44,45,64,,,,,60,50,70',
-'105,61,,,,62,63,146,56,,89,,,90,,,,,46,48,47,,49,44,45,64,,,,,60,50',
+'54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,',
+'52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29',
+'89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146',
+'56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63',
+'146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,',
+'62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,',
+'61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50',
'70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,',
'60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64',
',,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44',
-'45,64,,,-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48',
-'47,,49,44,45,64,,,-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54',
-',,167,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,',
-'52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,165',
+'45,64,,,-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,288,,,,46,48',
+'47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,',
+'46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90',
+'54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,',
+'52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29',
'89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146',
'56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63',
'146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,-116,,60,50,70,,61',
',,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70',
',61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60',
'50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,',
-',,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45',
-'64,,,-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47',
-',49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46',
-'48,47,,49,44,45,64,,,-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90',
-'54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,',
-'52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29',
-'89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146',
+',,,60,50,70,,61,,,,62,63,,,29,,,52,348,54,129,130,132,127,128,131,115',
+'116,117,121,122,123,118,119,120,124,125,126,,,,,146,56,,89,,29,90,,52',
+',54,46,48,47,,49,44,45,64,,,-116,,60,50,70,105,61,,,,62,63,146,56,,89',
+',,90,,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89',
+',52,90,288,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56',
+'29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146',
'56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63',
'146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,',
'62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,',
@@ -236,110 +253,79 @@ clist = [
'60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64',
',,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44',
'45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,',
-'49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48',
-'47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,',
+'49,44,45,64,,,-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,',
'46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90',
'54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,',
'52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29',
'89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146',
-'56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63',
-'146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,',
-'62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,',
-'61,,,,62,63,146,56,29,89,,52,90,288,,,,46,48,47,,49,44,45,64,,,,,60',
-'50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,',
-',-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46,48,47,,49',
-'44,45,64,,,-116,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,54,,,,46',
-'48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52,90,288',
-',,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89,,52',
-'90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56,29,89',
-',52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146,56',
-'29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63,146',
-'56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63',
-'146,56,29,89,,52,90,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,',
-'62,63,146,56,29,89,,52,,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61',
-',,,62,63,146,56,29,89,,52,,54,,,,46,48,47,,49,44,45,,,,,,60,50,70,,61',
-',,,62,63,146,56,188,89,,52,,,,,,46,48,47,,49,44,45,,,,,,60,50,70,,61',
-',,,62,63,,,171,,,173,,,,,,,,,,,,,,,,211,,,,,,129,130,132,127,128,131',
-',,188,,,52,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120',
-'124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133,134',
-'101,100,137,460,105,,,,,129,130,132,127,128,131,,105,,,,,129,130,132',
-'127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102,104',
-'103,109,111,110,112,114,113,106,108,107,133,134,101,100,137,211,105',
-',,,,129,130,132,127,128,131,,105,,,,,129,130,132,127,128,131,115,116',
-'117,121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112',
-'114,113,106,108,107,133,134,101,100,137,211,105,,,,,129,130,132,127',
-'128,131,,105,,,,,129,130,132,127,128,131,115,116,117,121,122,123,118',
-'119,120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107',
-'133,134,101,100,137,455,105,,,,,129,130,132,127,128,131,,105,,,,,129',
-'130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126',
-'102,104,103,109,111,110,112,114,113,106,108,107,133,134,101,100,137',
-'211,105,,,,,129,130,132,127,128,131,,105,,,,,129,130,132,127,128,131',
-'115,116,117,121,122,123,118,119,120,124,125,126,102,104,103,109,111',
-'110,112,114,113,106,108,107,133,134,101,100,137,211,105,,,,129,130,132',
-'127,128,131,,,105,,,,,129,130,132,127,128,131,115,116,117,121,122,123',
-'118,119,120,124,125,126,102,104,103,109,111,110,112,114,113,106,108',
-'107,133,134,101,100,137,105,129,130,132,127,128,131,129,130,132,127',
-'128,131,105,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
-'120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133',
-'134,101,100,137,105,,,,,,105,,,,,,,105,129,130,132,127,128,131,115,116',
-'117,121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112',
-'114,113,106,108,107,133,134,101,100,137,,,,,,,266,129,130,132,127,128',
-'131,105,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120',
-'124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133,134',
-'101,100,137,,,,,,,105,129,130,132,127,128,131,105,129,130,132,127,128',
-'131,115,116,117,121,122,123,118,119,120,124,125,126,102,104,103,109',
-'111,110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,105,,,,,,275',
-'105,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124',
+'56,29,89,,52,,54,,,,46,48,47,,49,44,45,,,,,,60,50,70,,61,,,,62,63,146',
+'56,29,89,,52,,54,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62,63',
+'146,56,188,89,,52,,,,,,46,48,47,,49,44,45,64,,,,,60,50,70,,61,,,,62',
+'63,,,188,,,52,,,,,,,,,,,,,,,,211,,,,,,129,130,132,127,128,131,,,188',
+',,52,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124',
'125,126,102,104,103,109,111,110,112,114,113,106,108,107,133,134,101',
-'100,137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122',
-'123,118,119,120,124,125,126,102,104,103,109,111,110,112,114,113,106',
-'108,107,133,134,101,100,137,,,,,,,,,,,,,,105,129,130,132,127,128,131',
-'115,116,117,121,122,123,118,119,120,124,125,126,102,104,103,109,111',
-'110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105,129',
-'130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126',
-'102,104,103,109,111,110,112,114,113,106,108,107,133,134,101,100,137',
-',,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122,123,118',
-'119,120,124,125,126,129,130,132,127,128,131,115,116,117,121,122,123',
-'118,119,120,124,125,126,,,,,,,,,,,,,105,,,,,,,,,,,,,,,,,,105,129,130',
+'100,137,211,105,,,,,129,130,132,127,128,131,,105,,,,,129,130,132,127',
+'128,131,115,116,117,121,122,123,118,119,120,124,125,126,102,104,103',
+'109,111,110,112,114,113,106,108,107,133,134,101,100,137,211,105,,,,',
+'129,130,132,127,128,131,,105,,,,,129,130,132,127,128,131,115,116,117',
+'121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112,114',
+'113,106,108,107,133,134,101,100,137,211,105,,,,,129,130,132,127,128',
+'131,,105,,,,,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
+'120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133',
+'134,101,100,137,211,105,,,,,129,130,132,127,128,131,,105,,,,,129,130',
'132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102',
-'104,103,109,111,110,112,114,113,106,108,107,,,,,,,,,,,,,,,,,,,105,129',
-'130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126',
-'102,104,103,109,111,110,112,114,113,106,108,107,,,,,,,,,,,,,,,,,,,105',
-'129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125',
-'126,102,104,103,109,111,110,112,114,113,106,108,107,133,134,101,100',
-'137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122,123',
-'118,119,120,124,125,126,102,104,103,109,111,110,112,114,113,106,108',
-'107,133,134,101,100,137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115',
+'104,103,109,111,110,112,114,113,106,108,107,133,134,101,100,137,455',
+'105,,,,,129,130,132,127,128,131,,105,,,,,129,130,132,127,128,131,115',
'116,117,121,122,123,118,119,120,124,125,126,102,104,103,109,111,110',
-'112,114,113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,337,105,129',
-'130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126',
-'102,104,103,109,111,110,112,114,113,106,108,107,133,134,101,100,137',
-',,,,,,,,,340,,,341,105,129,130,132,127,128,131,115,116,117,121,122,123',
-'118,119,120,124,125,126,102,104,103,109,111,110,112,114,113,106,108',
-'107,133,134,101,100,137,,,,,,,266,,,,,,,105,129,130,132,127,128,131',
-'115,116,117,121,122,123,118,119,120,124,125,126,102,104,103,109,111',
-'110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,360,,,,,,,105',
-'129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125',
-'126,102,104,103,109,111,110,112,114,113,106,108,107,133,134,101,100',
-'137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122,123',
-'118,119,120,124,125,126,102,104,103,109,111,110,112,114,113,106,108',
-'107,133,134,101,100,137,,,,,,,360,,,,,,,105,129,130,132,127,128,131',
-'115,116,117,121,122,123,118,119,120,124,125,126,102,104,103,109,111',
-'110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105,129',
-'130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126',
-'102,104,103,109,111,110,112,114,113,106,108,107,133,134,101,100,137',
-',,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122,123,118',
+'112,114,113,106,108,107,133,134,101,100,137,460,105,,,,129,130,132,127',
+'128,131,,,105,,,,,129,130,132,127,128,131,115,116,117,121,122,123,118',
'119,120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107',
-'133,134,101,100,137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116',
-'117,121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112',
-'114,113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105,129,130,132',
+'133,134,101,100,137,105,129,130,132,127,128,131,,,,,,,105,129,130,132',
+'127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102,104',
+'103,109,111,110,112,114,113,106,108,107,133,134,101,100,137,105,,,,',
+',266,129,130,132,127,128,131,105,129,130,132,127,128,131,115,116,117',
+'121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112,114',
+'113,106,108,107,133,134,101,100,137,,,,,,,105,,,,,,,105,129,130,132',
'127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102,104',
'103,109,111,110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,,',
-',396,,,341,105,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
+',,,,275,105,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
'120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133',
'134,101,100,137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117',
'121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112,114',
-'113,106,108,107,133,134,101,100,137,,,,,,,,,,399,,,,105,129,130,132',
+'113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105,129,130,132,127',
+'128,131,115,116,117,121,122,123,118,119,120,124,125,126,102,104,103',
+'109,111,110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,,,,,,',
+',105,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124',
+'125,126,102,104,103,109,111,110,112,114,113,106,108,107,133,134,101',
+'100,137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122',
+'123,118,119,120,124,125,126,129,130,132,127,128,131,115,116,117,121',
+'122,123,118,119,120,124,125,126,102,104,103,109,111,110,112,114,113',
+'106,108,107,105,,,,,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116',
+'117,121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112',
+'114,113,106,108,107,,,,,,,,,,,,,,,,,,,105,129,130,132,127,128,131,115',
+'116,117,121,122,123,118,119,120,124,125,126,102,104,103,109,111,110',
+'112,114,113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105,129,130',
+'132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102',
+'104,103,109,111,110,112,114,113,106,108,107,133,134,101,100,137,,,,',
+',,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
+'120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133',
+'134,101,100,137,,,,,,,,,,,,,337,105,129,130,132,127,128,131,115,116',
+'117,121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112',
+'114,113,106,108,107,133,134,101,100,137,,,,,,,,,,340,,,341,105,129,130',
+'132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102',
+'104,103,109,111,110,112,114,113,106,108,107,133,134,101,100,137,,,,',
+',,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
+'120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133',
+'134,101,100,137,,,,,,,266,,,,,,,105,129,130,132,127,128,131,115,116',
+'117,121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112',
+'114,113,106,108,107,133,134,101,100,137,,,,,,,360,,,,,,,105,129,130',
+'132,127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102',
+'104,103,109,111,110,112,114,113,106,108,107,133,134,101,100,137,,,,',
+',,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122,123,118,119',
+'120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133',
+'134,101,100,137,,,,,,,360,,,,,,,105,129,130,132,127,128,131,115,116',
+'117,121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112',
+'114,113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105,129,130,132',
'127,128,131,115,116,117,121,122,123,118,119,120,124,125,126,102,104',
'103,109,111,110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,,',
',,,,,105,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120',
@@ -348,6 +334,13 @@ clist = [
'122,123,118,119,120,124,125,126,102,104,103,109,111,110,112,114,113',
'106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105,129,130,132,127,128',
'131,115,116,117,121,122,123,118,119,120,124,125,126,102,104,103,109',
+'111,110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,,,,396,,,341',
+'105,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124',
+'125,126,102,104,103,109,111,110,112,114,113,106,108,107,133,134,101',
+'100,137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122',
+'123,118,119,120,124,125,126,102,104,103,109,111,110,112,114,113,106',
+'108,107,133,134,101,100,137,,,,,,,,,,399,,,,105,129,130,132,127,128',
+'131,115,116,117,121,122,123,118,119,120,124,125,126,102,104,103,109',
'111,110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105',
'129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124,125',
'126,102,104,103,109,111,110,112,114,113,106,108,107,133,134,101,100',
@@ -362,8 +355,15 @@ clist = [
'120,124,125,126,102,104,103,109,111,110,112,114,113,106,108,107,133',
'134,101,100,137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117',
'121,122,123,118,119,120,124,125,126,102,104,103,109,111,110,112,114',
-'113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105' ]
- racc_action_table = arr = ::Array.new(6677, nil)
+'113,106,108,107,133,134,101,100,137,,,,,,,,,,,,,,105,129,130,132,127',
+'128,131,115,116,117,121,122,123,118,119,120,124,125,126,102,104,103',
+'109,111,110,112,114,113,106,108,107,133,134,101,100,137,,,,,,,,,,,,',
+',105,129,130,132,127,128,131,115,116,117,121,122,123,118,119,120,124',
+'125,126,102,104,103,109,111,110,112,114,113,106,108,107,133,134,101',
+'100,137,,,,,,,,,,,,,,105,129,130,132,127,128,131,115,116,117,121,122',
+'123,118,119,120,124,125,126,102,104,103,109,111,110,112,114,113,106',
+'108,107,133,134,101,100,137,,,,,,,,,,,,,,105' ]
+ racc_action_table = arr = ::Array.new(6668, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -373,300 +373,300 @@ clist = [
end
clist = [
-'22,464,74,143,22,143,376,376,333,451,433,369,464,370,99,99,74,99,155',
-'345,451,155,369,155,3,99,99,99,461,99,99,99,99,433,376,333,370,99,99',
-'99,8,99,8,8,8,99,99,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22',
-'22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,99,95,3,99',
-'466,95,461,95,95,95,95,95,376,22,95,454,95,95,287,287,95,95,95,95,95',
-'332,95,95,95,95,93,95,95,95,95,95,95,95,95,95,95,95,447,95,95,95,95',
-'95,182,182,203,95,95,447,157,283,283,283,283,182,283,157,210,202,466',
-'283,283,202,210,138,138,138,138,59,59,454,203,138,24,287,287,213,298',
-'175,59,332,23,298,95,55,93,95,200,95,203,203,203,203,203,203,203,203',
+'22,143,74,143,22,333,376,376,182,182,370,369,433,157,57,57,74,57,155',
+'182,157,155,369,155,3,57,57,57,93,57,57,57,333,370,376,433,330,57,57',
+'57,202,57,330,330,202,57,57,22,22,22,22,22,22,22,22,22,22,22,22,22,22',
+'22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,57,0',
+'3,57,332,0,93,0,0,0,0,0,376,22,0,454,0,0,287,287,0,0,0,0,0,461,0,0,0',
+'0,0,0,0,0,0,0,0,0,0,0,0,0,55,0,0,0,0,0,298,466,1,0,0,298,59,59,283,283',
+'283,283,447,283,451,464,332,59,283,283,40,40,210,447,19,451,464,454',
+'210,181,181,287,287,175,72,72,72,461,23,200,0,213,0,0,2,0,55,277,2,161',
+'2,2,2,2,2,162,278,2,284,2,2,466,59,2,2,2,2,2,286,2,2,2,2,2,2,2,2,2,2',
+'2,2,2,2,2,2,175,2,2,2,2,2,200,86,213,2,2,161,313,266,277,314,161,162',
+'304,360,304,24,162,278,284,284,186,186,186,138,138,138,138,27,286,286',
+'8,138,8,8,8,403,430,73,73,73,2,32,2,2,94,2,315,35,94,86,94,94,94,94',
+'94,285,266,94,313,94,94,314,360,94,94,94,94,94,186,94,94,94,94,94,94',
+'94,94,94,94,94,94,94,94,94,403,430,94,94,94,94,94,281,281,315,94,94',
+'285,285,285,285,43,187,187,187,282,282,285,285,410,70,410,222,222,222',
+'222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,290,290',
+'94,87,94,94,95,94,387,387,95,88,95,95,95,95,95,33,89,95,187,95,95,416',
+'416,95,95,95,95,95,222,95,95,95,95,90,95,95,95,95,95,95,95,95,95,95',
+'95,92,95,95,95,95,95,96,97,203,95,95,33,33,33,33,31,31,31,31,331,31',
+'331,331,386,331,386,386,140,386,42,42,42,42,141,203,66,66,66,66,146',
+'235,235,235,235,235,235,95,148,150,95,151,95,203,203,203,203,203,203',
'203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203',
-'203,203,203,203,203,203,203,203,203,203,59,0,161,278,213,0,175,0,0,0',
-'0,0,55,203,0,200,0,0,286,277,0,0,0,0,0,284,0,0,0,0,0,0,0,0,0,0,0,0,0',
-'0,0,0,314,0,0,0,0,0,360,161,456,0,0,330,161,278,353,313,86,330,330,266',
-'355,31,31,31,31,403,31,286,286,277,42,42,42,42,284,284,386,356,386,386',
-'457,386,430,73,73,73,0,359,0,0,2,0,314,92,2,360,2,2,2,2,2,285,162,2',
-'86,2,2,313,266,2,2,2,2,2,403,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,430,2,2',
-'2,2,2,315,281,281,2,2,285,285,285,285,72,72,72,162,282,282,285,285,162',
-'40,40,186,186,186,331,90,331,331,458,331,66,66,66,66,304,410,304,410',
-'187,187,187,2,89,2,2,211,2,367,315,211,368,211,211,211,211,211,33,459',
-'211,19,211,211,181,181,211,211,211,211,211,186,211,211,211,211,211,211',
-'211,211,211,211,211,211,211,211,211,211,187,211,211,211,211,211,290',
-'290,204,211,211,33,33,33,33,416,416,387,387,88,87,70,385,389,391,392',
-'43,404,1,408,411,412,417,420,204,421,422,423,425,235,235,235,235,235',
-'235,428,211,252,211,211,429,211,204,204,204,204,204,204,204,204,204',
+'203,203,203,203,203,203,203,203,203,203,203,203,204,235,154,160,166',
+'169,170,174,178,183,184,185,189,203,199,207,208,209,212,249,250,252',
+'260,268,293,297,204,299,300,301,305,236,236,236,236,236,236,237,237',
+'237,237,237,237,312,204,204,204,204,204,204,204,204,204,204,204,204',
'204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204,204',
-'204,204,204,204,204,204,204,204,204,235,460,247,247,247,460,432,460',
-'460,460,460,460,434,204,460,250,460,460,35,260,460,460,460,460,460,249',
-'460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,178,268',
-'460,460,460,460,460,209,208,247,460,460,207,199,220,220,220,220,220',
+'204,204,204,204,204,204,236,211,247,247,247,211,237,211,211,211,211',
+'211,318,204,211,322,211,211,324,325,211,211,211,211,211,334,211,211',
+'211,211,211,211,211,211,211,211,211,211,211,211,211,211,335,211,211',
+'211,211,211,336,339,247,211,211,344,345,220,220,220,220,220,220,220',
'220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220,220',
-'220,220,220,220,220,220,220,220,220,220,220,460,189,460,460,455,460',
-'185,184,455,183,455,455,455,455,455,220,212,455,174,455,455,170,293',
-'455,455,455,455,455,169,455,455,455,455,455,455,455,455,455,455,455',
-'455,455,455,455,166,32,455,455,455,455,455,297,299,300,455,455,301,160',
+'220,220,220,220,220,220,220,220,220,211,353,211,211,320,211,355,356',
+'320,320,320,320,320,320,320,220,359,320,367,320,320,368,385,320,320',
+'320,320,320,389,320,320,320,320,320,320,320,320,320,320,320,320,320',
+'320,320,391,392,320,320,320,320,320,404,408,411,320,320,412,417,221',
'221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221',
-'221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,305,455',
-'445,455,455,94,455,448,449,94,312,94,94,94,94,94,221,154,94,151,94,94',
-'318,150,94,94,94,94,94,148,94,94,94,94,94,94,94,94,94,94,94,94,94,94',
-'94,322,146,94,94,94,94,94,324,325,141,94,94,140,334,222,222,222,222',
-'222,222,222,222,222,222,222,222,222,222,222,222,222,222,335,336,97,467',
-'339,96,27,344,,,,248,248,248,,94,,94,94,320,94,,,320,320,320,320,320',
-'320,320,222,,320,,320,320,,,320,320,320,320,320,,320,320,320,320,320',
-'320,320,320,320,320,320,320,320,320,320,248,,320,320,320,320,320,,,',
-'320,320,,,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223',
-'223,223,223,,,,,,,,,,,,251,251,251,,320,,320,320,438,320,,,438,,438',
-'438,438,438,438,223,,438,,438,438,,,438,438,438,438,438,,438,438,438',
-'438,438,438,438,438,438,438,438,438,438,438,438,251,,438,438,438,438',
-'438,,,,438,438,378,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,438,,438,438,,438',
-',378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378',
-'378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378',
-'378,375,,,,,,,,,258,258,,258,378,,258,,,,,258,258,258,,258,258,258,258',
-',,,,258,258,258,,258,,,,258,258,375,375,375,375,375,375,375,375,375',
+'221,221,221,221,221,221,221,221,221,221,221,221,221,221,420,320,421',
+'320,320,438,320,422,423,438,425,438,438,438,438,438,221,428,438,429',
+'438,438,432,434,438,438,438,438,438,445,438,438,438,438,438,438,438',
+'438,438,438,438,438,438,438,438,448,449,438,438,438,438,438,456,457',
+'458,438,438,459,467,223,223,223,223,223,223,223,223,223,223,223,223',
+'223,223,223,223,223,223,,,,,,,,,,,,248,248,248,,438,,438,438,455,438',
+',,455,,455,455,455,455,455,223,,455,,455,455,,,455,455,455,455,455,',
+'455,455,455,455,455,455,455,455,455,455,455,455,455,455,455,248,,455',
+'455,455,455,455,,,,455,455,,,224,224,224,224,224,224,224,224,224,224',
+'224,224,224,224,224,224,224,224,,,,,,,,,,,,251,251,251,,455,,455,455',
+'460,455,,,460,,460,460,460,460,460,224,,460,,460,460,,,460,460,460,460',
+'460,,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,251',
+',460,460,460,460,460,,,,460,460,375,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,460,,460,460,,460,,375,375,375,375,375,375,375,375,375,375,375,375',
'375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375,375',
-'375,375,375,375,375,375,375,375,375,258,,,258,,258,,258,139,139,,139',
-',375,139,,,,,139,139,139,,139,139,139,139,,,,,139,139,139,,139,,,,139',
-'139,295,295,295,,295,,,295,,,,,295,295,295,,295,295,295,295,,,,,295',
-'295,295,,295,,,,295,295,,139,,,139,,139,,139,224,224,224,224,224,224',
-'224,224,224,224,224,224,224,224,224,224,224,224,,,,302,302,302,,302',
-'295,295,302,295,,295,,302,302,302,,302,302,302,302,,,,,302,302,302,224',
-'302,,,,302,302,215,215,215,,215,,,215,,,,,215,215,215,,215,215,215,215',
-',,,,215,215,215,,215,,,,215,215,,302,274,274,302,274,302,,274,,,,,274',
-'274,274,,274,274,274,274,,,,,274,274,274,,274,,,,274,274,215,215,,215',
-',215,,,,226,226,226,226,226,226,226,226,226,226,226,226,226,226,226',
-'226,226,226,,,,267,267,267,,267,274,,267,274,,274,274,267,267,267,,267',
-'267,267,267,,,,,267,267,267,226,267,,,,267,267,176,176,176,,176,,,176',
-',,,,176,176,176,,176,176,176,176,,,,,176,176,176,,176,,,,176,176,,267',
-'267,,267,,267,,,227,227,227,227,227,227,227,227,227,227,227,227,227',
-'227,227,227,227,227,,,,362,362,362,,362,176,176,362,176,,176,,362,362',
-'362,,362,362,362,362,,,,,362,362,362,227,362,,,,362,362,147,147,147',
-',147,,,147,,,,,147,147,147,,147,147,147,147,,,,,147,147,147,,147,,,',
-'147,147,,362,362,,362,,362,,,228,228,228,228,228,228,228,228,228,228',
-'228,228,228,228,228,228,228,228,,,,276,276,276,,276,147,147,276,147',
-',147,,276,276,276,,276,276,276,276,,,,,276,276,276,228,276,,,,276,276',
-'58,58,58,,58,,,58,,,,,58,58,58,,58,58,58,58,,,58,,58,58,58,,58,,,,58',
-'58,,276,276,,276,,276,,229,229,229,229,229,229,229,229,229,229,229,229',
-'229,229,229,229,229,229,,,,171,171,171,,171,,58,171,,58,,58,171,171',
-'171,,171,171,171,171,,,,,171,171,171,229,171,,,,171,171,393,393,393',
-',393,,,393,,,,,393,393,393,,393,393,393,393,,,,,393,393,393,,393,,,',
-'393,393,,171,171,,171,,171,,,230,230,230,230,230,230,230,230,230,230',
-'230,230,230,230,230,230,230,230,,,,165,165,165,,165,393,393,165,393',
-',393,,165,165,165,,165,165,165,165,,,,,165,165,165,230,165,,,,165,165',
-'109,109,,109,,,109,,,,,109,109,109,,109,109,109,109,,,,,109,109,109',
-',109,,,,109,109,,,165,165,,165,,165,231,231,231,231,231,231,231,231',
-'231,231,231,231,231,231,231,231,231,231,,,,,110,110,,110,,109,110,,109',
-',109,110,110,110,,110,110,110,110,,,,,110,110,110,231,110,,,,110,110',
-'111,111,,111,,,111,,,,,111,111,111,,111,111,111,111,,,,,111,111,111',
-',111,,,,111,111,112,112,110,112,,110,112,110,,,,112,112,112,,112,112',
-'112,112,,,,,112,112,112,,112,,,,112,112,113,113,111,113,,111,113,111',
-',,,113,113,113,,113,113,113,113,,,,,113,113,113,,113,,,,113,113,114',
-'114,112,114,,112,114,112,,,,114,114,114,,114,114,114,114,,,,,114,114',
-'114,,114,,,,114,114,115,115,113,115,,113,115,113,,,,115,115,115,,115',
-'115,115,115,,,,,115,115,115,,115,,,,115,115,116,116,114,116,,114,116',
-'114,,,,116,116,116,,116,116,116,116,,,,,116,116,116,,116,,,,116,116',
-'117,117,115,117,,115,117,115,,,,117,117,117,,117,117,117,117,,,,,117',
-'117,117,,117,,,,117,117,118,118,116,118,,116,118,116,,,,118,118,118',
-',118,118,118,118,,,,,118,118,118,,118,,,,118,118,119,119,117,119,,117',
-'119,117,,,,119,119,119,,119,119,119,119,,,,,119,119,119,,119,,,,119',
-'119,120,120,118,120,,118,120,118,,,,120,120,120,,120,120,120,120,,,',
-',120,120,120,,120,,,,120,120,121,121,119,121,,119,121,119,,,,121,121',
-'121,,121,121,121,121,,,,,121,121,121,,121,,,,121,121,122,122,120,122',
-',120,122,120,,,,122,122,122,,122,122,122,122,,,,,122,122,122,,122,,',
-',122,122,123,123,121,123,,121,123,121,,,,123,123,123,,123,123,123,123',
-',,,,123,123,123,,123,,,,123,123,124,124,122,124,,122,124,122,,,,124',
-'124,124,,124,124,124,124,,,,,124,124,124,,124,,,,124,124,125,125,123',
-'125,,123,125,123,,,,125,125,125,,125,125,125,125,,,,,125,125,125,,125',
-',,,125,125,126,126,124,126,,124,126,124,,,,126,126,126,,126,126,126',
-'126,,,,,126,126,126,,126,,,,126,126,127,127,125,127,,125,127,125,,,',
-'127,127,127,,127,127,127,127,,,,,127,127,127,,127,,,,127,127,128,128',
-'126,128,,126,128,126,,,,128,128,128,,128,128,128,128,,,,,128,128,128',
-',128,,,,128,128,129,129,127,129,,127,129,127,,,,129,129,129,,129,129',
-'129,129,,,,,129,129,129,,129,,,,129,129,130,130,128,130,,128,130,128',
-',,,130,130,130,,130,130,130,130,,,,,130,130,130,,130,,,,130,130,131',
-'131,129,131,,129,131,129,,,,131,131,131,,131,131,131,131,,,,,131,131',
-'131,,131,,,,131,131,132,132,130,132,,130,132,130,,,,132,132,132,,132',
-'132,132,132,,,,,132,132,132,,132,,,,132,132,133,133,131,133,,131,133',
-'131,,,,133,133,133,,133,133,133,133,,,,,133,133,133,,133,,,,133,133',
-'134,134,132,134,,132,134,132,,,,134,134,134,,134,134,134,134,,,,,134',
-'134,134,,134,,,,134,134,135,135,133,135,,133,135,133,,,,135,135,135',
-',135,135,135,135,,,,,135,135,135,,135,,,,135,135,136,136,134,136,,134',
-'136,134,,,,136,136,136,,136,136,136,136,,,,,136,136,136,,136,,,,136',
-'136,137,137,135,137,,135,137,135,,,,137,137,137,,137,137,137,137,,,',
-',137,137,137,,137,,,,137,137,85,85,136,85,,136,85,136,,,,85,85,85,,85',
-'85,85,85,,,,,85,85,85,,85,,,,85,85,272,272,137,272,,137,272,137,,,,272',
-'272,272,,272,272,272,272,,,,,272,272,272,,272,,,,272,272,270,270,85',
-'270,,85,270,85,,,,270,270,270,,270,270,270,270,,,,,270,270,270,,270',
-',,,270,270,,,272,,,272,272,272,232,232,232,232,232,232,232,232,232,232',
-'232,232,232,232,232,232,232,232,,,,,29,29,,29,,270,29,,270,,270,29,29',
-'29,,29,29,29,29,,,,,29,29,29,232,29,,,,29,29,437,437,,437,,,437,,,,',
-'437,437,437,,437,437,437,437,,,,,437,437,437,,437,,,,437,437,435,435',
-'29,435,,29,435,29,,,,435,435,435,,435,435,435,435,,,,,435,435,435,,435',
-',,,435,435,418,418,437,418,,437,418,437,,,,418,418,418,,418,418,418',
-'418,,,,,418,418,418,,418,,,,418,418,52,52,435,52,,435,52,435,,,,52,52',
-'52,,52,52,52,52,,,52,,52,52,52,,52,,,,52,52,54,54,418,54,,418,54,418',
-',,,54,54,54,,54,54,54,54,,,54,,54,54,54,,54,,,,54,54,56,56,52,56,,52',
-'56,52,,,56,56,56,56,,56,56,56,56,,,,,56,56,56,,56,,,,56,56,61,61,54',
-'61,,54,61,54,,,,61,61,61,,61,61,61,61,,,,,61,61,61,,61,,,,61,61,62,62',
-'56,62,,56,62,56,,,,62,62,62,,62,62,62,62,,,,,62,62,62,,62,,,,62,62,63',
-'63,61,63,,61,63,61,,,,63,63,63,,63,63,63,63,,,,,63,63,63,,63,,,,63,63',
-'78,78,62,78,,62,78,62,,,,78,78,78,,78,78,78,78,,,78,,78,78,78,,78,,',
-',78,78,80,80,63,80,,63,80,63,,,,80,80,80,,80,80,80,80,,,,,80,80,80,',
-'80,,,,80,80,81,81,78,81,,78,81,78,,,,81,81,81,,81,81,81,81,,,,,81,81',
-'81,,81,,,,81,81,82,82,80,82,,80,82,80,,,,82,82,82,,82,82,82,82,,,,,82',
-'82,82,,82,,,,82,82,261,261,81,261,,81,261,81,,,,261,261,261,,261,261',
-'261,261,,,261,,261,261,261,,261,,,,261,261,365,365,82,365,,82,365,82',
-',,,365,365,365,,365,365,365,365,,,,,365,365,365,,365,,,,365,365,341',
-'341,261,341,,261,341,261,,,,341,341,341,,341,341,341,341,,,341,,341',
-'341,341,,341,,,,341,341,337,337,365,337,,365,337,365,,,,337,337,337',
-',337,337,337,337,,,,,337,337,337,,337,,,,337,337,100,100,341,100,,341',
-'100,341,,,,100,100,100,,100,100,100,100,,,,,100,100,100,,100,,,,100',
-'100,101,101,337,101,,337,101,337,,,,101,101,101,,101,101,101,101,,,',
-',101,101,101,,101,,,,101,101,102,102,100,102,,100,102,100,,,,102,102',
-'102,,102,102,102,102,,,,,102,102,102,,102,,,,102,102,103,103,101,103',
-',101,103,101,,,,103,103,103,,103,103,103,103,,,,,103,103,103,,103,,',
-',103,103,104,104,102,104,,102,104,102,,,,104,104,104,,104,104,104,104',
-',,,,104,104,104,,104,,,,104,104,105,105,103,105,,103,105,103,,,,105',
-'105,105,,105,105,105,105,,,,,105,105,105,,105,,,,105,105,106,106,104',
-'106,,104,106,104,,,,106,106,106,,106,106,106,106,,,,,106,106,106,,106',
-',,,106,106,107,107,105,107,,105,107,105,,,,107,107,107,,107,107,107',
-'107,,,,,107,107,107,,107,,,,107,107,108,108,106,108,,106,108,106,,,',
-'108,108,108,,108,108,108,108,,,,,108,108,108,,108,,,,108,108,328,328',
-'107,328,,107,328,107,,,,328,328,328,,328,328,328,328,,,,,328,328,328',
-',328,,,,328,328,327,327,108,327,,108,327,108,,,,327,327,327,,327,327',
-'327,327,,,,,327,327,327,,327,,,,327,327,326,326,328,326,,328,326,328',
-',,,326,326,326,,326,326,326,326,,,,,326,326,326,,326,,,,326,326,323',
-'323,327,323,,327,323,327,,,,323,323,323,,323,323,323,323,,,,,323,323',
-'323,,323,,,,323,323,319,319,326,319,,326,319,326,,,,319,319,319,,319',
-'319,319,319,,,,,319,319,319,,319,,,,319,319,317,317,323,317,,323,317',
-'323,,,,317,317,317,,317,317,317,317,,,,,317,317,317,,317,,,,317,317',
-'316,316,319,316,,319,316,319,,,,316,316,316,,316,316,316,316,,,,,316',
-'316,316,,316,,,,316,316,164,164,317,164,,317,164,317,,,,164,164,164',
-',164,164,164,164,,,,,164,164,164,,164,,,,164,164,294,294,316,294,,316',
-'294,316,,,,294,294,294,,294,294,294,294,,,,,294,294,294,,294,,,,294',
-'294,291,291,164,291,,164,291,164,,,,291,291,291,,291,291,291,291,,,',
-',291,291,291,,291,,,,291,291,173,173,294,173,,294,173,294,,,,173,173',
-'173,,173,173,173,173,,,173,,173,173,173,,173,,,,173,173,288,288,291',
-'288,,291,288,291,,,,288,288,288,,288,288,288,288,,,288,,288,288,288',
-',288,,,,288,288,180,180,173,180,,173,180,173,,,,180,180,180,,180,180',
-'180,180,,,,,180,180,180,,180,,,,180,180,188,188,288,188,,288,188,288',
-',,,188,188,188,,188,188,188,188,,,,,188,188,188,,188,,,,188,188,191',
-'191,180,191,,180,191,180,,,,191,191,191,,191,191,191,191,,,,,191,191',
-'191,,191,,,,191,191,192,192,188,192,,188,192,188,,,,192,192,192,,192',
-'192,192,192,,,,,192,192,192,,192,,,,192,192,193,193,191,193,,191,193',
-'191,,,,193,193,193,,193,193,193,193,,,,,193,193,193,,193,,,,193,193',
-'194,194,192,194,,192,194,192,,,,194,194,194,,194,194,194,194,,,,,194',
-'194,194,,194,,,,194,194,275,275,193,275,,193,275,193,,,,275,275,275',
-',275,275,275,275,,,,,275,275,275,,275,,,,275,275,142,142,194,142,,194',
-',194,,,,142,142,142,,142,142,142,142,,,,,142,142,142,,142,,,,142,142',
-'57,57,275,57,,275,,275,,,,57,57,57,,57,57,57,,,,,,57,57,57,,57,,,,57',
-'57,64,64,142,64,,142,,,,,,64,64,64,,64,64,64,,,,,,64,64,64,,64,,,,64',
-'64,,,57,,,57,,,,,,,,,,,,,,,,205,,,,,,236,236,236,236,236,236,,,64,,',
-'64,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205',
+'375,375,375,375,375,375,378,,,,,,,,,139,139,,139,375,,139,,,,,139,139',
+'139,,139,139,139,139,,,,,139,139,139,,139,,,,139,139,378,378,378,378',
+'378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378,378',
+'378,378,378,378,378,378,378,378,378,378,378,378,378,378,139,,,139,,139',
+',139,258,258,,258,,378,258,,,,,258,258,258,,258,258,258,258,,,,,258',
+'258,258,,258,,,,258,258,58,58,58,,58,,,58,,,,,58,58,58,,58,58,58,58',
+',,58,,58,58,58,,58,,,,58,58,,258,,,258,,258,,258,,226,226,226,226,226',
+'226,226,226,226,226,226,226,226,226,226,226,226,226,,147,147,147,,147',
+',58,147,,58,,58,147,147,147,,147,147,147,147,,,,,147,147,147,,147,226',
+',,147,147,165,165,165,,165,,,165,,,,,165,165,165,,165,165,165,165,,',
+',,165,165,165,,165,,,,165,165,,147,147,,147,,147,,,227,227,227,227,227',
+'227,227,227,227,227,227,227,227,227,227,227,227,227,,,,171,171,171,',
+'171,165,165,171,165,,165,,171,171,171,,171,171,171,171,,,,,171,171,171',
+'227,171,,,,171,171,176,176,176,,176,,,176,,,,,176,176,176,,176,176,176',
+'176,,,,,176,176,176,,176,,,,176,176,,171,171,,171,,171,,,228,228,228',
+'228,228,228,228,228,228,228,228,228,228,228,228,228,228,228,,,,215,215',
+'215,,215,176,176,215,176,,176,,215,215,215,,215,215,215,215,,,,,215',
+'215,215,228,215,,,,215,215,267,267,267,,267,,,267,,,,,267,267,267,,267',
+'267,267,267,,,,,267,267,267,,267,,,,267,267,,215,215,,215,,215,,,229',
+'229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229,229',
+',,,,274,274,,274,267,267,274,267,,267,,274,274,274,,274,274,274,274',
+',,,,274,274,274,229,274,,,,274,274,276,276,276,,276,,,276,,,,,276,276',
+'276,,276,276,276,276,,,,,276,276,276,,276,,,,276,276,,274,,,274,,274',
+'274,,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230',
+'230,230,,,,295,295,295,,295,276,276,295,276,,276,,295,295,295,,295,295',
+'295,295,,,,,295,295,295,230,295,,,,295,295,302,302,302,,302,,,302,,',
+',,302,302,302,,302,302,302,302,,,,,302,302,302,,302,,,,302,302,,295',
+'295,,295,,295,,231,231,231,231,231,231,231,231,231,231,231,231,231,231',
+'231,231,231,231,,,,362,362,362,,362,,302,362,,302,,302,362,362,362,',
+'362,362,362,362,,,,,362,362,362,231,362,,,,362,362,393,393,393,,393',
+',,393,,,,,393,393,393,,393,393,393,393,,,,,393,393,393,,393,,,,393,393',
+',362,362,,362,,362,,,232,232,232,232,232,232,232,232,232,232,232,232',
+'232,232,232,232,232,232,,,,,29,29,,29,393,393,29,393,,393,,29,29,29',
+',29,29,29,29,,,,,29,29,29,232,29,,,,29,29,52,52,,52,,,52,,,,,52,52,52',
+',52,52,52,52,,,52,,52,52,52,,52,,,,52,52,54,54,29,54,,29,54,29,,,,54',
+'54,54,,54,54,54,54,,,54,,54,54,54,,54,,,,54,54,56,56,52,56,,52,56,52',
+',,56,56,56,56,,56,56,56,56,,,,,56,56,56,,56,,,,56,56,61,61,54,61,,54',
+'61,54,,,,61,61,61,,61,61,61,61,,,,,61,61,61,,61,,,,61,61,62,62,56,62',
+',56,62,56,,,,62,62,62,,62,62,62,62,,,,,62,62,62,,62,,,,62,62,63,63,61',
+'63,,61,63,61,,,,63,63,63,,63,63,63,63,,,,,63,63,63,,63,,,,63,63,78,78',
+'62,78,,62,78,62,,,,78,78,78,,78,78,78,78,,,78,,78,78,78,,78,,,,78,78',
+'80,80,63,80,,63,80,63,,,,80,80,80,,80,80,80,80,,,,,80,80,80,,80,,,,80',
+'80,81,81,78,81,,78,81,78,,,,81,81,81,,81,81,81,81,,,,,81,81,81,,81,',
+',,81,81,82,82,80,82,,80,82,80,,,,82,82,82,,82,82,82,82,,,,,82,82,82',
+',82,,,,82,82,85,85,81,85,,81,85,81,,,,85,85,85,,85,85,85,85,,,,,85,85',
+'85,,85,,,,85,85,100,100,82,100,,82,100,82,,,,100,100,100,,100,100,100',
+'100,,,,,100,100,100,,100,,,,100,100,101,101,85,101,,85,101,85,,,,101',
+'101,101,,101,101,101,101,,,,,101,101,101,,101,,,,101,101,102,102,100',
+'102,,100,102,100,,,,102,102,102,,102,102,102,102,,,,,102,102,102,,102',
+',,,102,102,103,103,101,103,,101,103,101,,,,103,103,103,,103,103,103',
+'103,,,,,103,103,103,,103,,,,103,103,104,104,102,104,,102,104,102,,,',
+'104,104,104,,104,104,104,104,,,,,104,104,104,,104,,,,104,104,105,105',
+'103,105,,103,105,103,,,,105,105,105,,105,105,105,105,,,,,105,105,105',
+',105,,,,105,105,106,106,104,106,,104,106,104,,,,106,106,106,,106,106',
+'106,106,,,,,106,106,106,,106,,,,106,106,107,107,105,107,,105,107,105',
+',,,107,107,107,,107,107,107,107,,,,,107,107,107,,107,,,,107,107,108',
+'108,106,108,,106,108,106,,,,108,108,108,,108,108,108,108,,,,,108,108',
+'108,,108,,,,108,108,109,109,107,109,,107,109,107,,,,109,109,109,,109',
+'109,109,109,,,,,109,109,109,,109,,,,109,109,110,110,108,110,,108,110',
+'108,,,,110,110,110,,110,110,110,110,,,,,110,110,110,,110,,,,110,110',
+'111,111,109,111,,109,111,109,,,,111,111,111,,111,111,111,111,,,,,111',
+'111,111,,111,,,,111,111,112,112,110,112,,110,112,110,,,,112,112,112',
+',112,112,112,112,,,,,112,112,112,,112,,,,112,112,113,113,111,113,,111',
+'113,111,,,,113,113,113,,113,113,113,113,,,,,113,113,113,,113,,,,113',
+'113,114,114,112,114,,112,114,112,,,,114,114,114,,114,114,114,114,,,',
+',114,114,114,,114,,,,114,114,115,115,113,115,,113,115,113,,,,115,115',
+'115,,115,115,115,115,,,,,115,115,115,,115,,,,115,115,116,116,114,116',
+',114,116,114,,,,116,116,116,,116,116,116,116,,,,,116,116,116,,116,,',
+',116,116,117,117,115,117,,115,117,115,,,,117,117,117,,117,117,117,117',
+',,,,117,117,117,,117,,,,117,117,118,118,116,118,,116,118,116,,,,118',
+'118,118,,118,118,118,118,,,,,118,118,118,,118,,,,118,118,119,119,117',
+'119,,117,119,117,,,,119,119,119,,119,119,119,119,,,,,119,119,119,,119',
+',,,119,119,120,120,118,120,,118,120,118,,,,120,120,120,,120,120,120',
+'120,,,,,120,120,120,,120,,,,120,120,121,121,119,121,,119,121,119,,,',
+'121,121,121,,121,121,121,121,,,,,121,121,121,,121,,,,121,121,122,122',
+'120,122,,120,122,120,,,,122,122,122,,122,122,122,122,,,,,122,122,122',
+',122,,,,122,122,123,123,121,123,,121,123,121,,,,123,123,123,,123,123',
+'123,123,,,,,123,123,123,,123,,,,123,123,124,124,122,124,,122,124,122',
+',,,124,124,124,,124,124,124,124,,,,,124,124,124,,124,,,,124,124,125',
+'125,123,125,,123,125,123,,,,125,125,125,,125,125,125,125,,,,,125,125',
+'125,,125,,,,125,125,126,126,124,126,,124,126,124,,,,126,126,126,,126',
+'126,126,126,,,,,126,126,126,,126,,,,126,126,127,127,125,127,,125,127',
+'125,,,,127,127,127,,127,127,127,127,,,,,127,127,127,,127,,,,127,127',
+'128,128,126,128,,126,128,126,,,,128,128,128,,128,128,128,128,,,,,128',
+'128,128,,128,,,,128,128,129,129,127,129,,127,129,127,,,,129,129,129',
+',129,129,129,129,,,,,129,129,129,,129,,,,129,129,130,130,128,130,,128',
+'130,128,,,,130,130,130,,130,130,130,130,,,,,130,130,130,,130,,,,130',
+'130,131,131,129,131,,129,131,129,,,,131,131,131,,131,131,131,131,,,',
+',131,131,131,,131,,,,131,131,132,132,130,132,,130,132,130,,,,132,132',
+'132,,132,132,132,132,,,,,132,132,132,,132,,,,132,132,133,133,131,133',
+',131,133,131,,,,133,133,133,,133,133,133,133,,,,,133,133,133,,133,,',
+',133,133,134,134,132,134,,132,134,132,,,,134,134,134,,134,134,134,134',
+',,,,134,134,134,,134,,,,134,134,135,135,133,135,,133,135,133,,,,135',
+'135,135,,135,135,135,135,,,,,135,135,135,,135,,,,135,135,136,136,134',
+'136,,134,136,134,,,,136,136,136,,136,136,136,136,,,,,136,136,136,,136',
+',,,136,136,137,137,135,137,,135,137,135,,,,137,137,137,,137,137,137',
+'137,,,,,137,137,137,,137,,,,137,137,164,164,136,164,,136,164,136,,,',
+'164,164,164,,164,164,164,164,,,,,164,164,164,,164,,,,164,164,173,173',
+'137,173,,137,173,137,,,,173,173,173,,173,173,173,173,,,173,,173,173',
+'173,,173,,,,173,173,180,180,164,180,,164,180,164,,,,180,180,180,,180',
+'180,180,180,,,,,180,180,180,,180,,,,180,180,188,188,173,188,,173,188',
+'173,,,,188,188,188,,188,188,188,188,,,,,188,188,188,,188,,,,188,188',
+'191,191,180,191,,180,191,180,,,,191,191,191,,191,191,191,191,,,,,191',
+'191,191,,191,,,,191,191,192,192,188,192,,188,192,188,,,,192,192,192',
+',192,192,192,192,,,,,192,192,192,,192,,,,192,192,193,193,191,193,,191',
+'193,191,,,,193,193,193,,193,193,193,193,,,,,193,193,193,,193,,,,193',
+'193,194,194,192,194,,192,194,192,,,,194,194,194,,194,194,194,194,,,',
+',194,194,194,,194,,,,194,194,261,261,193,261,,193,261,193,,,,261,261',
+'261,,261,261,261,261,,,261,,261,261,261,,261,,,,261,261,270,270,194',
+'270,,194,270,194,,,,270,270,270,,270,270,270,270,,,,,270,270,270,,270',
+',,,270,270,272,272,261,272,,261,272,261,,,,272,272,272,,272,272,272',
+'272,,,,,272,272,272,,272,,,,272,272,275,275,270,275,,270,275,270,,,',
+'275,275,275,,275,275,275,275,,,,,275,275,275,,275,,,,275,275,,,272,',
+',272,272,272,233,233,233,233,233,233,233,233,233,233,233,233,233,233',
+'233,233,233,233,,,,,288,288,,288,,275,288,,275,,275,288,288,288,,288',
+'288,288,288,,,288,,288,288,288,233,288,,,,288,288,291,291,,291,,,291',
+',,,,291,291,291,,291,291,291,291,,,,,291,291,291,,291,,,,291,291,294',
+'294,288,294,,288,294,288,,,,294,294,294,,294,294,294,294,,,,,294,294',
+'294,,294,,,,294,294,316,316,291,316,,291,316,291,,,,316,316,316,,316',
+'316,316,316,,,,,316,316,316,,316,,,,316,316,317,317,294,317,,294,317',
+'294,,,,317,317,317,,317,317,317,317,,,,,317,317,317,,317,,,,317,317',
+'319,319,316,319,,316,319,316,,,,319,319,319,,319,319,319,319,,,,,319',
+'319,319,,319,,,,319,319,323,323,317,323,,317,323,317,,,,323,323,323',
+',323,323,323,323,,,,,323,323,323,,323,,,,323,323,326,326,319,326,,319',
+'326,319,,,,326,326,326,,326,326,326,326,,,,,326,326,326,,326,,,,326',
+'326,327,327,323,327,,323,327,323,,,,327,327,327,,327,327,327,327,,,',
+',327,327,327,,327,,,,327,327,328,328,326,328,,326,328,326,,,,328,328',
+'328,,328,328,328,328,,,,,328,328,328,,328,,,,328,328,337,337,327,337',
+',327,337,327,,,,337,337,337,,337,337,337,337,,,,,337,337,337,,337,,',
+',337,337,341,341,328,341,,328,341,328,,,,341,341,341,,341,341,341,341',
+',,341,,341,341,341,,341,,,,341,341,365,365,337,365,,337,365,337,,,,365',
+'365,365,,365,365,365,365,,,,,365,365,365,,365,,,,365,365,418,418,341',
+'418,,341,418,341,,,,418,418,418,,418,418,418,418,,,,,418,418,418,,418',
+',,,418,418,435,435,365,435,,365,435,365,,,,435,435,435,,435,435,435',
+'435,,,,,435,435,435,,435,,,,435,435,437,437,418,437,,418,437,418,,,',
+'437,437,437,,437,437,437,437,,,,,437,437,437,,437,,,,437,437,64,64,435',
+'64,,435,,435,,,,64,64,64,,64,64,64,,,,,,64,64,64,,64,,,,64,64,99,99',
+'437,99,,437,,437,,,,99,99,99,,99,99,99,99,,,,,99,99,99,,99,,,,99,99',
+'142,142,64,142,,64,,,,,,142,142,142,,142,142,142,142,,,,,142,142,142',
+',142,,,,142,142,,,99,,,99,,,,,,,,,,,,,,,,205,,,,,,238,238,238,238,238',
+'238,,,142,,,142,205,205,205,205,205,205,205,205,205,205,205,205,205',
'205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205,205',
-'205,453,236,,,,,237,237,237,237,237,237,,205,,,,,453,453,453,453,453',
-'453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453',
-'453,453,453,453,453,453,453,453,453,453,453,453,453,382,237,,,,,238',
-'238,238,238,238,238,,453,,,,,382,382,382,382,382,382,382,382,382,382',
+'205,205,205,205,205,206,238,,,,,239,239,239,239,239,239,,205,,,,,206',
+'206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206',
+'206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206',
+'381,239,,,,,240,240,240,240,240,240,,206,,,,,381,381,381,381,381,381',
+'381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381',
+'381,381,381,381,381,381,381,381,381,381,381,381,382,240,,,,,241,241',
+'241,241,241,241,,381,,,,,382,382,382,382,382,382,382,382,382,382,382',
'382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382',
-'382,382,382,382,382,382,382,382,383,238,,,,,239,239,239,239,239,239',
-',382,,,,,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383',
+'382,382,382,382,382,382,382,383,241,,,,,242,242,242,242,242,242,,382',
+',,,,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383',
'383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383,383',
-'383,383,383,439,239,,,,,240,240,240,240,240,240,,383,,,,,439,439,439',
+'383,383,439,242,,,,,243,243,243,243,243,243,,383,,,,,439,439,439,439',
'439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439',
-'439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,381,240',
-',,,,241,241,241,241,241,241,,439,,,,,381,381,381,381,381,381,381,381',
-'381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381,381',
-'381,381,381,381,381,381,381,381,381,381,206,241,,,,242,242,242,242,242',
-'242,,,381,,,,,206,206,206,206,206,206,206,206,206,206,206,206,206,206',
-'206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206,206',
-'206,206,206,206,242,243,243,243,243,243,243,244,244,244,244,244,244',
-'206,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289',
-'289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289',
-'289,289,243,,,,,,244,,,,,,,289,145,145,145,145,145,145,145,145,145,145',
+'439,439,439,439,439,439,439,439,439,439,439,439,439,439,453,243,,,,244',
+'244,244,244,244,244,,,439,,,,,453,453,453,453,453,453,453,453,453,453',
+'453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453,453',
+'453,453,453,453,453,453,453,453,244,245,245,245,245,245,245,,,,,,,453',
'145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145',
-'145,145,145,145,145,145,145,145,,,,,,,145,245,245,245,245,245,245,145',
-'156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156',
+'145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145,145',
+'145,245,,,,,,145,246,246,246,246,246,246,145,156,156,156,156,156,156',
'156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156',
-'156,,,,,,,245,246,246,246,246,246,246,156,159,159,159,159,159,159,159',
+'156,156,156,156,156,156,156,156,156,156,156,156,,,,,,,246,,,,,,,156',
'159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159',
-'159,159,159,159,159,159,159,159,159,159,159,,,,,,,246,,,,,,159,159,168',
-'168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168',
+'159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159',
+'159,,,,,,,,,,,,,159,159,168,168,168,168,168,168,168,168,168,168,168',
'168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168,168',
-',,,,,,,,,,,,,168,179,179,179,179,179,179,179,179,179,179,179,179,179',
+'168,168,168,168,168,168,168,,,,,,,,,,,,,,168,179,179,179,179,179,179',
'179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179,179',
-'179,179,179,179,179,,,,,,,,,,,,,,179,201,201,201,201,201,201,201,201',
+'179,179,179,179,179,179,179,179,179,179,179,179,,,,,,,,,,,,,,179,201',
+'201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201',
'201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201,201',
-'201,201,201,201,201,201,201,201,201,201,,,,,,,,,,,,,,201,225,225,225',
+',,,,,,,,,,,,,201,225,225,225,225,225,225,225,225,225,225,225,225,225',
'225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225',
-'225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,,,,,,,,',
-',,,,,225,233,233,233,233,233,233,233,233,233,233,233,233,233,233,233',
-'233,233,233,234,234,234,234,234,234,234,234,234,234,234,234,234,234',
-'234,234,234,234,,,,,,,,,,,,,233,,,,,,,,,,,,,,,,,,234,253,253,253,253',
+'225,225,225,225,225,,,,,,,,,,,,,,225,234,234,234,234,234,234,234,234',
+'234,234,234,234,234,234,234,234,234,234,253,253,253,253,253,253,253',
'253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253',
-'253,253,253,253,253,253,253,253,253,,,,,,,,,,,,,,,,,,,253,254,254,254',
+'253,253,253,253,253,253,234,,,,,,,,,,,,,,,,,,253,254,254,254,254,254',
'254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254,254',
-'254,254,254,254,254,254,254,254,254,254,,,,,,,,,,,,,,,,,,,254,255,255',
+'254,254,254,254,254,254,254,254,,,,,,,,,,,,,,,,,,,254,255,255,255,255',
'255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255',
-'255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,,,,',
-',,,,,,,,,255,256,256,256,256,256,256,256,256,256,256,256,256,256,256',
+'255,255,255,255,255,255,255,255,255,255,255,255,255,255,,,,,,,,,,,,',
+',255,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256',
'256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256',
-'256,256,256,256,,,,,,,,,,,,,,256,257,257,257,257,257,257,257,257,257',
+'256,256,,,,,,,,,,,,,,256,257,257,257,257,257,257,257,257,257,257,257',
'257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257,257',
-'257,257,257,257,257,257,257,257,257,,,,,,,,,,,,,257,257,259,259,259',
+'257,257,257,257,257,257,257,,,,,,,,,,,,,257,257,259,259,259,259,259',
'259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,259',
-'259,259,259,259,259,259,259,259,259,259,259,259,259,259,259,,,,,,,,',
-',259,,,259,259,292,292,292,292,292,292,292,292,292,292,292,292,292,292',
+'259,259,259,259,259,259,259,259,259,259,259,259,259,,,,,,,,,,259,,,259',
+'259,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289',
+'289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289,289',
+'289,289,,,,,,,,,,,,,,289,292,292,292,292,292,292,292,292,292,292,292',
'292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292,292',
-'292,292,292,292,,,,,,,292,,,,,,,292,296,296,296,296,296,296,296,296',
+'292,292,292,292,292,292,292,,,,,,,292,,,,,,,292,296,296,296,296,296',
'296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296',
-'296,296,296,296,296,296,296,296,296,296,,,,,,,296,,,,,,,296,303,303',
+'296,296,296,296,296,296,296,296,296,296,296,296,296,,,,,,,296,,,,,,',
+'296,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303',
'303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303',
-'303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,303,,,,',
-',,,,,,,,,303,307,307,307,307,307,307,307,307,307,307,307,307,307,307',
+'303,303,,,,,,,,,,,,,,303,307,307,307,307,307,307,307,307,307,307,307',
'307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307,307',
-'307,307,307,307,,,,,,,307,,,,,,,307,308,308,308,308,308,308,308,308',
+'307,307,307,307,307,307,307,,,,,,,307,,,,,,,307,308,308,308,308,308',
'308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308',
-'308,308,308,308,308,308,308,308,308,308,,,,,,,,,,,,,,308,309,309,309',
+'308,308,308,308,308,308,308,308,308,308,308,308,308,,,,,,,,,,,,,,308',
+'309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309',
'309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,309',
-'309,309,309,309,309,309,309,309,309,309,309,309,309,309,309,,,,,,,,',
-',,,,,309,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310',
+'309,,,,,,,,,,,,,,309,310,310,310,310,310,310,310,310,310,310,310,310',
'310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310,310',
-'310,310,310,,,,,,,,,,,,,,310,311,311,311,311,311,311,311,311,311,311',
+'310,310,310,310,310,310,,,,,,,,,,,,,,310,311,311,311,311,311,311,311',
'311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311',
-'311,311,311,311,311,311,311,311,,,,,,,,,,,,,,311,338,338,338,338,338',
+'311,311,311,311,311,311,311,311,311,311,311,,,,,,,,,,,,,,311,338,338',
'338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338',
-'338,338,338,338,338,338,338,338,338,338,338,338,338,,,,,,,,,,338,,,338',
-'338,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343',
+'338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,338,,,,',
+',,,,,338,,,338,338,343,343,343,343,343,343,343,343,343,343,343,343,343',
'343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343,343',
-'343,343,,,,,,,,,,,,,,343,347,347,347,347,347,347,347,347,347,347,347',
+'343,343,343,343,343,,,,,,,,,,,,,,343,347,347,347,347,347,347,347,347',
'347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347,347',
-'347,347,347,347,347,347,347,,,,,,,,,,347,,,,347,349,349,349,349,349',
+'347,347,347,347,347,347,347,347,347,347,,,,,,,,,,347,,,,347,349,349',
'349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349',
-'349,349,349,349,349,349,349,349,349,349,349,349,349,,,,,,,,,,,,,,349',
+'349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,349,,,,',
+',,,,,,,,,349,352,352,352,352,352,352,352,352,352,352,352,352,352,352',
'352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352',
-'352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352,352',
-'352,,,,,,,,,,,,,,352,358,358,358,358,358,358,358,358,358,358,358,358',
+'352,352,352,352,,,,,,,,,,,,,,352,358,358,358,358,358,358,358,358,358',
'358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358',
-'358,358,358,358,358,358,,,,,,,,,,,,,,358,364,364,364,364,364,364,364',
+'358,358,358,358,358,358,358,358,358,,,,,,,,,,,,,,358,364,364,364,364',
'364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364,364',
-'364,364,364,364,364,364,364,364,364,364,364,,,,,,,,,,,,,,364,372,372',
+'364,364,364,364,364,364,364,364,364,364,364,364,364,364,,,,,,,,,,,,',
+',364,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372',
'372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372',
-'372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,372,,,,',
-',,,,,,,,,372,373,373,373,373,373,373,373,373,373,373,373,373,373,373',
+'372,372,,,,,,,,,,,,,,372,373,373,373,373,373,373,373,373,373,373,373',
'373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373,373',
-'373,373,373,373,,,,,,,,,,,,,,373,395,395,395,395,395,395,395,395,395',
+'373,373,373,373,373,373,373,,,,,,,,,,,,,,373,395,395,395,395,395,395',
'395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395',
-'395,395,395,395,395,395,395,395,395,,,,,,,,,,,,,,395,398,398,398,398',
+'395,395,395,395,395,395,395,395,395,395,395,395,,,,,,,,,,,,,,395,398',
+'398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398',
'398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398,398',
-'398,398,398,398,398,398,398,398,398,398,398,398,398,398,,,,,,,,,,,,',
-',398,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405',
+',,,,,,,,,,,,,398,405,405,405,405,405,405,405,405,405,405,405,405,405',
'405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405,405',
-'405,405,,,,,,,,,,,,,,405,452,452,452,452,452,452,452,452,452,452,452',
+'405,405,405,405,405,,,,,,,,,,,,,,405,452,452,452,452,452,452,452,452',
'452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452,452',
-'452,452,452,452,452,452,452,,,,,,,,,,,,,,452' ]
- racc_action_check = arr = ::Array.new(6677, nil)
+'452,452,452,452,452,452,452,452,452,452,,,,,,,,,,,,,,452' ]
+ racc_action_check = arr = ::Array.new(6668, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -676,53 +676,53 @@ clist = [
end
racc_action_pointer = [
- 210, 463, 301, -7, nil, nil, nil, nil, -2, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 320,
- nil, nil, -2, 76, 106, nil, nil, 695, nil, 2851,
- nil, 190, 612, 362, nil, 497, nil, nil, nil, nil,
- 335, nil, 199, 369, nil, nil, nil, nil, nil, nil,
- nil, nil, 2983, nil, 3016, 129, 3049, 4402, 1541, 122,
- nil, 3082, 3115, 3148, 4435, nil, 295, nil, nil, nil,
- 414, nil, 315, 252, -42, nil, nil, nil, 3181, nil,
- 3214, 3247, 3280, nil, nil, 2722, 225, 424, 410, 347,
- 285, nil, 306, 81, 703, 81, 690, 737, nil, -7,
- 3445, 3478, 3511, 3544, 3577, 3610, 3643, 3676, 3709, 1735,
- 1798, 1831, 1864, 1897, 1930, 1963, 1996, 2029, 2062, 2095,
- 2128, 2161, 2194, 2227, 2260, 2293, 2326, 2359, 2392, 2425,
- 2458, 2491, 2524, 2557, 2590, 2623, 2656, 2689, 67, 1080,
- 714, 712, 4369, -87, nil, 4895, 657, 1443, 686, nil,
- 680, 676, nil, nil, 625, -70, 4944, 48, nil, 4993,
- 578, 171, 273, nil, 3973, 1702, 566, nil, 5042, 549,
- 588, 1604, nil, 4072, 536, 123, 1345, nil, 475, 5091,
- 4138, 378, 97, 531, 575, 519, 321, 338, 4171, 519,
- nil, 4204, 4237, 4270, 4303, nil, nil, nil, nil, 534,
- 132, 5140, 143, 127, 438, 4479, 4797, 559, 555, 554,
- 137, 392, 584, 121, nil, 1212, nil, nil, nil, nil,
- 528, 619, 710, 801, 1128, 5189, 1261, 1359, 1457, 1554,
- 1652, 1748, 2801, 5238, 5256, 425, 4467, 4520, 4573, 4626,
- 4679, 4732, 4784, 4833, 4839, 4937, 4986, 475, 739, 450,
- 440, 830, 385, 5305, 5354, 5403, 5452, 5501, 1004, 5550,
- 448, 3313, nil, nil, nil, nil, 229, 1311, 474, nil,
- 2788, nil, 2755, nil, 1247, 4336, 1507, 188, 172, nil,
- nil, 257, 269, 53, 193, 271, 186, 67, 4105, 4846,
- 347, 4039, 5599, 542, 4006, 1114, 5648, 571, 76, 570,
- 574, 576, 1178, 5697, 295, 656, nil, 5746, 5795, 5844,
- 5893, 5942, 655, 226, 211, 308, 3940, 3907, 715, 3874,
- 794, nil, 738, 3841, 745, 746, 3808, 3775, 3742, nil,
- 257, 342, 76, -23, 669, 689, 688, 3412, 5991, 688,
- nil, 3379, nil, 6040, 741, -73, nil, 6089, nil, 6138,
- nil, nil, 6187, 177, nil, 178, 195, nil, 6236, 210,
- 216, nil, 1409, nil, 6285, 3346, nil, 354, 355, -20,
- -6, nil, 6334, 6383, nil, 1009, 3, nil, 932, nil,
- nil, 4744, 4585, 4638, nil, 426, 258, 419, nil, 427,
- nil, 452, 416, 1638, nil, 6432, nil, nil, 6481, nil,
- nil, nil, nil, 235, 372, 6530, nil, nil, 457, nil,
- 296, 375, 382, nil, nil, nil, 447, 436, 2950, nil,
- 461, 463, 464, 465, nil, 442, nil, nil, 438, 395,
- 252, nil, 486, -9, 492, 2917, nil, 2884, 885, 4691,
- nil, nil, nil, nil, nil, 671, nil, 93, 617, 624,
- nil, -22, 6579, 4532, 66, 612, 254, 286, 335, 399,
- 521, -3, nil, nil, -30, nil, 55, 773, nil ]
+ 81, 132, 172, -7, nil, nil, nil, nil, 209, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 66,
+ nil, nil, -2, 76, 182, nil, nil, 160, nil, 1805,
+ nil, 328, 219, 324, nil, 225, nil, nil, nil, nil,
+ 117, nil, 342, 229, nil, nil, nil, nil, nil, nil,
+ nil, nil, 1838, nil, 1871, 82, 1904, -7, 1155, 103,
+ nil, 1937, 1970, 2003, 4409, nil, 348, nil, nil, nil,
+ 288, nil, 120, 214, -42, nil, nil, nil, 2036, nil,
+ 2069, 2102, 2135, nil, nil, 2168, 178, 322, 317, 324,
+ 296, nil, 397, -3, 263, 354, 311, 362, nil, 4442,
+ 2201, 2234, 2267, 2300, 2333, 2366, 2399, 2432, 2465, 2498,
+ 2531, 2564, 2597, 2630, 2663, 2696, 2729, 2762, 2795, 2828,
+ 2861, 2894, 2927, 2960, 2993, 3026, 3059, 3092, 3125, 3158,
+ 3191, 3224, 3257, 3290, 3323, 3356, 3389, 3422, 160, 1045,
+ 381, 388, 4475, -89, nil, 4886, 347, 1218, 401, nil,
+ 402, 404, nil, nil, 394, -70, 4935, -75, nil, 4984,
+ 398, 137, 143, nil, 3455, 1252, 400, nil, 5033, 400,
+ 447, 1316, nil, 3488, 399, 121, 1350, nil, 404, 5082,
+ 3521, 126, -25, 405, 452, 398, 192, 273, 3554, 404,
+ nil, 3587, 3620, 3653, 3686, nil, nil, nil, nil, 456,
+ 127, 5131, 38, 400, 479, 4519, 4572, 483, 484, 485,
+ 145, 562, 460, 129, nil, 1414, nil, nil, nil, nil,
+ 569, 660, 283, 751, 842, 5180, 1170, 1266, 1364, 1462,
+ 1560, 1657, 1755, 3831, 5229, 388, 466, 472, 4507, 4560,
+ 4613, 4666, 4719, 4772, 4824, 4873, 4928, 516, 780, 406,
+ 407, 871, 408, 5247, 5296, 5345, 5394, 5443, 1121, 5492,
+ 413, 3719, nil, nil, nil, nil, 185, 1448, 417, nil,
+ 3752, nil, 3785, nil, 1512, 3818, 1546, 135, 144, nil,
+ nil, 218, 231, 54, 145, 233, 155, 67, 3881, 5541,
+ 256, 3914, 5590, 418, 3947, 1610, 5639, 419, 42, 419,
+ 423, 423, 1644, 5688, 145, 470, nil, 5737, 5786, 5835,
+ 5884, 5933, 472, 185, 188, 225, 3980, 4013, 568, 4046,
+ 653, nil, 571, 4079, 574, 575, 4112, 4145, 4178, nil,
+ 29, 385, 55, -26, 499, 517, 521, 4211, 5982, 519,
+ nil, 4244, nil, 6031, 573, 525, nil, 6080, nil, 6129,
+ nil, nil, 6178, 562, nil, 562, 563, nil, 6227, 577,
+ 191, nil, 1707, nil, 6276, 4277, nil, 627, 628, -20,
+ -9, nil, 6325, 6374, nil, 973, 3, nil, 1050, nil,
+ nil, 4625, 4678, 4731, nil, 642, 389, 325, nil, 648,
+ nil, 688, 652, 1741, nil, 6423, nil, nil, 6472, nil,
+ nil, nil, nil, 213, 612, 6521, nil, nil, 696, nil,
+ 241, 614, 623, nil, nil, nil, 370, 677, 4310, nil,
+ 734, 736, 741, 742, nil, 720, nil, nil, 716, 670,
+ 214, nil, 721, -7, 722, 4343, nil, 4376, 744, 4784,
+ nil, nil, nil, nil, nil, 739, nil, 111, 696, 703,
+ nil, 113, 6570, 4837, 66, 835, 786, 787, 753, 791,
+ 926, 76, nil, nil, 114, nil, 100, 792, nil ]
racc_action_default = [
-1, -259, -2, -3, -4, -8, -9, -10, -11, -12,
@@ -774,134 +774,120 @@ racc_action_default = [
-116, -251, -254, -197, -259, -198, -252, -259, -199 ]
racc_goto_table = [
- 2, 183, 27, 95, 27, 3, 148, 170, 413, 151,
- 155, 389, 415, 390, 154, 177, 172, 416, 260, 217,
- 96, 318, 322, 169, 181, 282, 284, 98, 140, 356,
- 209, 351, 166, 214, 200, 335, 336, 190, 207, 410,
- 202, 330, 1, nil, nil, 208, nil, nil, nil, nil,
- nil, nil, 436, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 97, nil, nil, nil, 425, 154, 390, nil,
- nil, 450, 286, nil, nil, nil, 280, 162, 291, nil,
- nil, 281, nil, 145, 96, 96, 160, nil, nil, nil,
- nil, 196, 197, 95, nil, nil, 27, 27, nil, nil,
- nil, 219, nil, nil, 268, nil, 156, nil, 159, nil,
- 168, 175, 179, 184, 285, 185, 186, 187, nil, nil,
- nil, nil, 293, nil, 304, nil, 97, 97, 198, 287,
- 283, 298, 201, 301, 203, 204, 205, 339, nil, 206,
- 97, nil, 212, 213, 264, 299, 369, 181, nil, 282,
- 284, nil, 282, 284, 220, 221, 222, 223, 224, 225,
- 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
- 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
- 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
- 256, 257, 280, 259, nil, nil, 286, 162, 210, 286,
- nil, 179, 291, nil, 355, 281, 300, nil, 281, nil,
- nil, nil, nil, 27, nil, nil, 332, nil, 289, 292,
- nil, nil, 314, nil, nil, 296, nil, 156, 280, nil,
- 292, 315, nil, 353, 303, 314, 184, 345, 285, nil,
- 344, 285, 307, nil, 334, 308, 309, 310, 311, nil,
- 143, nil, 359, 287, 283, nil, 287, 283, 148, nil,
- 151, nil, nil, 447, nil, 451, nil, nil, nil, 179,
- nil, nil, nil, nil, nil, nil, nil, nil, 174, nil,
- nil, nil, nil, nil, nil, 189, nil, nil, nil, 464,
- nil, nil, nil, nil, nil, nil, 387, nil, nil, nil,
+ 2, 154, 3, 95, 27, 169, 27, 96, 210, 98,
+ 390, 170, 148, 281, 155, 151, 183, 369, 413, 260,
+ 389, 415, 172, 318, 322, 1, 282, 217, 140, 356,
+ 284, 286, 209, 351, 166, 214, 97, 200, 335, 336,
+ 190, 207, 410, 202, 177, 330, 416, nil, nil, nil,
+ nil, 208, nil, nil, 154, nil, nil, nil, nil, nil,
+ nil, 436, nil, nil, nil, 390, nil, nil, nil, nil,
+ nil, 96, 96, 196, 197, 425, nil, nil, nil, nil,
+ nil, 450, nil, nil, nil, 175, nil, 184, nil, nil,
+ nil, nil, 160, 95, nil, nil, 145, nil, 27, 27,
+ 97, 97, 198, 219, nil, nil, 181, nil, nil, nil,
+ nil, nil, 283, nil, 97, nil, 212, 213, 285, 156,
+ nil, 159, nil, 168, nil, 179, 324, 325, 185, 186,
+ 187, 162, 299, 268, 447, 298, 451, 281, 339, 304,
+ 281, 280, nil, 291, nil, 201, 264, 203, 204, 205,
+ 282, 293, 206, 282, 284, 286, nil, 284, 286, nil,
+ 464, nil, 301, nil, nil, nil, nil, 220, 221, 222,
+ 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
+ 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
+ 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
+ 253, 254, 255, 256, 257, nil, 259, nil, nil, nil,
+ 184, 287, 300, 332, 179, 27, nil, nil, nil, nil,
+ nil, nil, nil, nil, 345, nil, nil, nil, nil, 181,
+ nil, 289, 292, nil, nil, nil, 283, 315, 296, 283,
+ 156, nil, 285, 292, nil, 285, 344, 303, nil, nil,
+ 334, 162, 388, nil, 391, 307, nil, 280, 308, 309,
+ 310, 311, 353, nil, 148, nil, 151, 291, nil, 355,
+ nil, nil, nil, nil, nil, nil, 314, nil, nil, nil,
+ nil, 359, 179, nil, nil, nil, nil, nil, nil, 314,
+ 408, nil, nil, 280, nil, nil, nil, nil, nil, nil,
+ nil, nil, 420, 421, 422, nil, 423, 424, nil, nil,
+ 426, nil, nil, nil, nil, nil, nil, nil, 345, nil,
+ nil, nil, 376, nil, 27, 338, nil, nil, 343, nil,
+ nil, nil, 95, 367, 179, 287, 143, 347, 287, 349,
+ 344, 159, 352, 179, nil, nil, 444, nil, 404, nil,
+ nil, nil, nil, nil, nil, 159, nil, nil, 289, nil,
+ nil, 358, 179, nil, 174, nil, 456, nil, 457, 364,
+ nil, 189, 459, nil, nil, nil, 95, nil, 387, 429,
+ nil, nil, nil, 372, 373, 467, 375, nil, nil, nil,
+ 378, nil, nil, 381, 382, 383, 407, nil, nil, nil,
+ nil, nil, nil, nil, 395, nil, 189, nil, 398, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 338, nil, nil, 343, 324, 325, nil, 404,
- 189, 179, 27, nil, 347, 376, 349, nil, 159, 352,
- 179, 345, 95, nil, 344, nil, nil, nil, nil, nil,
- nil, nil, 159, nil, nil, 289, nil, nil, 358, 179,
- 429, 387, nil, nil, nil, nil, 364, nil, nil, 367,
- nil, nil, nil, 189, nil, nil, nil, nil, nil, nil,
- 372, 373, nil, 375, nil, nil, 95, 378, nil, nil,
- 381, 382, 383, nil, nil, nil, 143, nil, nil, nil,
- nil, 395, 143, nil, nil, 398, nil, 143, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 143,
- nil, nil, nil, nil, nil, nil, 179, nil, nil, 405,
- nil, nil, 407, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 27, nil, 388, 454, 391, nil, 428, 179, nil, nil,
- nil, nil, nil, nil, 95, nil, nil, 27, nil, nil,
- 461, 95, 27, nil, nil, 466, 95, nil, nil, nil,
- nil, nil, 439, nil, nil, nil, nil, nil, nil, nil,
- 408, nil, nil, nil, nil, nil, nil, nil, nil, 452,
- nil, 453, 420, 421, 422, nil, 423, 424, nil, nil,
- 426, 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, nil,
- nil, nil, nil, nil, nil, nil, 444, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 456, nil, 457, nil,
- nil, nil, 459, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 467 ]
+ 428, nil, nil, nil, nil, nil, nil, nil, nil, 179,
+ nil, nil, 405, 387, nil, nil, nil, nil, nil, nil,
+ 454, nil, 27, nil, nil, nil, nil, nil, nil, 189,
+ nil, nil, nil, nil, 95, nil, nil, 461, nil, 27,
+ 179, 95, 466, nil, 27, nil, 95, nil, nil, nil,
+ nil, nil, 143, nil, nil, nil, nil, nil, 143, nil,
+ nil, nil, nil, 143, nil, 439, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 143, nil, nil, nil, nil,
+ nil, nil, 452, nil, 453 ]
racc_goto_check = [
- 2, 58, 28, 2, 28, 3, 49, 33, 72, 49,
- 45, 76, 77, 40, 50, 55, 41, 78, 52, 4,
- 42, 74, 74, 31, 38, 27, 32, 64, 25, 37,
- 44, 48, 56, 57, 59, 60, 61, 62, 65, 71,
- 73, 75, 1, nil, nil, 41, nil, nil, nil, nil,
- nil, nil, 77, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 53, nil, nil, nil, 76, 50, 40, nil,
- nil, 72, 35, nil, nil, nil, 67, 66, 67, nil,
- nil, 26, nil, 22, 42, 42, 54, nil, nil, nil,
- nil, 64, 64, 2, nil, nil, 28, 28, nil, nil,
- nil, 28, nil, nil, 55, nil, 22, nil, 22, nil,
- 22, 53, 22, 53, 33, 22, 22, 22, nil, nil,
- nil, nil, 55, nil, 58, nil, 53, 53, 53, 38,
- 31, 45, 22, 55, 22, 22, 22, 52, nil, 22,
- 53, nil, 53, 53, 28, 50, 69, 38, nil, 27,
- 32, nil, 27, 32, 22, 22, 22, 22, 22, 22,
+ 2, 50, 3, 2, 28, 31, 28, 42, 70, 64,
+ 40, 33, 49, 26, 45, 49, 58, 69, 72, 52,
+ 76, 77, 41, 74, 74, 1, 27, 4, 25, 37,
+ 32, 35, 44, 48, 56, 57, 53, 59, 60, 61,
+ 62, 65, 71, 73, 55, 75, 78, nil, nil, nil,
+ nil, 41, nil, nil, 50, nil, nil, nil, nil, nil,
+ nil, 77, nil, nil, nil, 40, nil, nil, nil, nil,
+ nil, 42, 42, 64, 64, 76, nil, nil, nil, nil,
+ nil, 72, nil, nil, nil, 53, nil, 53, nil, nil,
+ nil, nil, 54, 2, nil, nil, 22, nil, 28, 28,
+ 53, 53, 53, 28, nil, nil, 38, nil, nil, nil,
+ nil, nil, 31, nil, 53, nil, 53, 53, 33, 22,
+ nil, 22, nil, 22, nil, 22, 70, 70, 22, 22,
+ 22, 66, 50, 55, 69, 45, 69, 26, 52, 58,
+ 26, 67, nil, 67, nil, 22, 28, 22, 22, 22,
+ 27, 55, 22, 27, 32, 35, nil, 32, 35, nil,
+ 69, nil, 55, nil, nil, nil, nil, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 67, 22, nil, nil, 35, 66, 70, 35,
- nil, 22, 67, nil, 67, 26, 54, nil, 26, nil,
- nil, nil, nil, 28, nil, nil, 3, nil, 22, 22,
- nil, nil, 66, nil, nil, 22, nil, 22, 67, nil,
- 22, 54, nil, 55, 22, 66, 53, 50, 33, nil,
- 49, 33, 22, nil, 54, 22, 22, 22, 22, nil,
- 23, nil, 55, 38, 31, nil, 38, 31, 49, nil,
- 49, nil, nil, 69, nil, 69, nil, nil, nil, 22,
- nil, nil, nil, nil, nil, nil, nil, nil, 23, nil,
- nil, nil, nil, nil, nil, 23, nil, nil, nil, 69,
- nil, nil, nil, nil, nil, nil, 38, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 22, nil, nil, 22, 70, 70, nil, 55,
- 23, 22, 28, nil, 22, 3, 22, nil, 22, 22,
- 22, 50, 2, nil, 49, nil, nil, nil, nil, nil,
- nil, nil, 22, nil, nil, 22, nil, nil, 22, 22,
- 55, 38, nil, nil, nil, nil, 22, nil, nil, 53,
- nil, nil, nil, 23, nil, nil, nil, nil, nil, nil,
- 22, 22, nil, 22, nil, nil, 2, 22, nil, nil,
- 22, 22, 22, nil, nil, nil, 23, nil, nil, nil,
- nil, 22, 23, nil, nil, 22, nil, 23, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 23,
- nil, nil, nil, nil, nil, nil, 22, nil, nil, 22,
- nil, nil, 53, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 28, nil, 70, 3, 70, nil, 53, 22, nil, nil,
- nil, nil, nil, nil, 2, nil, nil, 28, nil, nil,
- 3, 2, 28, nil, nil, 3, 2, nil, nil, nil,
- nil, nil, 22, nil, nil, nil, nil, nil, nil, nil,
- 70, nil, nil, nil, nil, nil, nil, nil, nil, 22,
- nil, 22, 70, 70, 70, nil, 70, 70, nil, nil,
- 70, 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, nil,
- nil, nil, nil, nil, nil, nil, 70, nil, nil, nil,
+ 22, 22, 22, 22, 22, nil, 22, nil, nil, nil,
+ 53, 38, 54, 3, 22, 28, nil, nil, nil, nil,
+ nil, nil, nil, nil, 50, nil, nil, nil, nil, 38,
+ nil, 22, 22, nil, nil, nil, 31, 54, 22, 31,
+ 22, nil, 33, 22, nil, 33, 49, 22, nil, nil,
+ 54, 66, 70, nil, 70, 22, nil, 67, 22, 22,
+ 22, 22, 55, nil, 49, nil, 49, 67, nil, 67,
+ nil, nil, nil, nil, nil, nil, 66, nil, nil, nil,
+ nil, 55, 22, nil, nil, nil, nil, nil, nil, 66,
+ 70, nil, nil, 67, nil, nil, nil, nil, nil, nil,
+ nil, nil, 70, 70, 70, nil, 70, 70, nil, nil,
+ 70, nil, nil, nil, nil, nil, nil, nil, 50, nil,
+ nil, nil, 3, nil, 28, 22, nil, nil, 22, nil,
+ nil, nil, 2, 53, 22, 38, 23, 22, 38, 22,
+ 49, 22, 22, 22, nil, nil, 70, nil, 55, nil,
+ nil, nil, nil, nil, nil, 22, nil, nil, 22, nil,
+ nil, 22, 22, nil, 23, nil, 70, nil, 70, 22,
+ nil, 23, 70, nil, nil, nil, 2, nil, 38, 55,
+ nil, nil, nil, 22, 22, 70, 22, nil, nil, nil,
+ 22, nil, nil, 22, 22, 22, 53, nil, nil, nil,
+ nil, nil, nil, nil, 22, nil, 23, nil, 22, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 70, nil, 70, nil,
- nil, nil, 70, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 70 ]
+ 53, nil, nil, nil, nil, nil, nil, nil, nil, 22,
+ nil, nil, 22, 38, nil, nil, nil, nil, nil, nil,
+ 3, nil, 28, nil, nil, nil, nil, nil, nil, 23,
+ nil, nil, nil, nil, 2, nil, nil, 3, nil, 28,
+ 22, 2, 3, nil, 28, nil, 2, nil, nil, nil,
+ nil, nil, 23, nil, nil, nil, nil, nil, 23, nil,
+ nil, nil, nil, 23, nil, 22, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 23, nil, nil, nil, nil,
+ nil, nil, 22, nil, 22 ]
racc_goto_pointer = [
- nil, 42, 0, 5, -76, nil, nil, nil, nil, nil,
+ nil, 25, 0, 2, -68, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 54, 221, nil, 4, -83, -139, 2, nil,
- nil, -34, -138, -50, nil, -92, nil, -262, -35, nil,
- -318, -41, 12, nil, -56, -42, nil, nil, -243, -26,
- -29, nil, -121, 54, 31, -43, -24, -56, -58, -40,
- -180, -179, -27, nil, 19, -48, 22, -86, nil, -169,
- 111, -331, -362, -38, -182, -169, -320, -364, -359 ]
+ nil, nil, 67, 307, nil, 4, -151, -138, 4, nil,
+ nil, -52, -134, -46, nil, -133, nil, -262, 47, nil,
+ -321, -35, -1, nil, -54, -38, nil, nil, -241, -20,
+ -42, nil, -120, 28, 37, -14, -22, -54, -43, -37,
+ -177, -176, -24, nil, 1, -45, 76, -21, nil, -298,
+ -79, -328, -352, -35, -180, -165, -311, -355, -330 ]
racc_goto_default = [
nil, nil, 94, 93, 4, 5, 6, 7, 8, 9,
diff --git a/test/racc/regress/ruby18 b/test/racc/regress/ruby18
index 24852df6fc..a21fa611a5 100644
--- a/test/racc/regress/ruby18
+++ b/test/racc/regress/ruby18
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -25,110 +25,112 @@ module_eval(<<'...end ruby18.y/module_eval...', 'ruby18.y', 1936)
##### State transition tables begin ###
clist = [
-'-277,195,196,195,196,489,-84,-277,-277,-277,511,814,578,-277,-277,-81',
-'-277,-429,558,579,531,558,489,489,-425,-82,72,259,-87,568,578,-425,195',
-'196,73,-277,-277,579,-277,-277,-277,-277,-277,489,489,477,-426,-80,476',
-'-83,-86,395,557,-426,-61,557,535,659,658,662,661,291,-74,-80,-277,-277',
-'-277,-277,-277,-277,-277,-277,-277,-277,-277,-277,-277,-277,536,291',
-'-277,-277,-277,530,549,722,477,-76,-277,479,99,-277,291,-69,621,98,-277',
-'-87,-277,-85,-277,-277,-277,-277,-277,-277,-277,-480,-277,-76,-277,258',
-'-476,510,-480,-480,-480,99,-73,488,-480,-480,98,-480,-277,-277,-74,-77',
-'-74,-277,-85,-79,-480,99,99,99,488,488,98,98,98,621,-480,-480,-74,-480',
-'-480,-480,-480,-480,-72,-76,-75,-78,768,99,99,488,488,621,98,98,-477',
-'-427,431,-74,538,558,-74,-76,-427,-480,-480,-480,-480,-480,-480,-480',
-'-480,-480,-480,-480,-480,-480,-480,-476,259,-480,-480,-480,-76,546,99',
-'-76,620,-480,259,98,-480,463,-81,557,-77,-480,521,-480,713,-480,-480',
-'-480,-480,-480,-480,-480,-226,-480,-480,-480,542,734,606,-226,-226,-226',
-'-474,194,-226,-226,-226,-259,-226,-480,-480,680,-75,-476,-480,-83,691',
-'99,-226,620,-476,558,98,-86,814,-476,254,-226,-226,-476,-226,-226,-226',
-'-226,-226,99,254,620,521,-76,98,541,-84,523,522,-429,-79,-476,258,-87',
-'540,463,-421,673,-73,557,254,-81,258,-421,690,521,-84,-473,-474,521',
-'361,-226,-421,-272,659,658,662,661,-226,825,-272,-272,-272,254,-226',
-'-272,-272,-272,-74,-272,-474,-82,-72,477,215,-80,482,99,-78,-272,-272',
-'-86,98,523,522,532,-226,215,-272,-272,-82,-272,-272,-272,-272,-272,-421',
-'-417,477,215,-226,479,-226,-421,-417,-226,523,522,527,-473,523,522,526',
-'-417,495,215,496,-272,-272,-272,-272,-272,-272,-272,-272,-272,-272,-272',
-'-272,-272,-272,-473,-271,-272,-272,-272,-278,826,-272,-271,827,-272',
-'521,-278,-272,-272,521,-272,-271,-272,568,-272,-278,-272,-272,-272,-272',
-'-272,-272,-272,-226,-272,-480,-272,-417,-480,502,-226,-226,-226,503',
-'-417,-226,-226,-226,-477,-226,-272,-272,-272,-272,215,-272,568,215,-422',
-'-226,251,-480,606,-279,496,-422,575,252,-226,-226,-279,-226,-226,-226',
-'-226,-226,523,522,524,-279,523,522,519,195,196,-480,212,291,-480,212',
-'214,213,-480,214,213,-480,192,-476,-477,215,-476,-480,99,193,-480,-477',
-'516,98,-226,-319,-477,-480,191,517,-477,-226,-319,-277,-480,-480,254',
-'-226,-480,-476,-277,-319,580,-480,234,-477,829,212,-477,-277,-428,214',
-'213,210,211,284,285,-428,590,-226,655,-480,653,652,651,654,-428,-424',
-'-477,-477,-477,591,-477,-226,-424,-226,-477,-477,-226,734,606,-477,-69',
-'-477,-477,-477,-477,-477,-477,-477,461,462,662,661,-477,-477,-477,-477',
-'-477,-477,-477,195,196,592,-423,215,659,658,662,661,-477,-423,830,-477',
-'-477,-477,-477,-477,-477,-477,-477,-477,-477,469,-477,-477,832,-477',
-'-477,-477,215,-497,-497,-497,-497,221,223,212,457,-497,-497,214,213',
-'210,211,458,229,230,880,-477,549,835,-477,-477,456,-477,-477,195,196',
-'-477,568,-477,212,-477,218,-477,214,213,210,211,222,220,216,-477,217',
-'606,187,291,-477,-477,-477,-477,-477,-477,839,-271,840,-477,-477,-476',
-'-476,-476,-271,-476,349,358,-85,-476,-476,360,359,-271,-476,616,-476',
-'-476,-476,-476,-476,-476,-476,496,624,846,847,-476,-476,-476,-476,-476',
-'-476,-476,99,99,99,672,675,98,98,98,848,-476,758,758,-476,-476,-476',
-'-476,-476,-476,-476,-476,-476,-476,759,-476,-476,436,-476,-476,-476',
-'215,219,224,225,226,221,223,883,-279,227,228,466,436,186,-278,-279,229',
-'230,467,-476,692,-278,-476,-476,-279,-476,-476,393,291,-476,-278,-476',
-'212,-476,218,-476,214,213,210,211,222,220,216,-476,217,693,758,704,-476',
-'-476,-476,-476,-476,-476,431,498,431,-476,-476,62,63,64,499,51,243,707',
-'-83,56,57,708,861,497,60,715,58,59,61,23,24,65,66,885,717,283,721,22',
-'28,27,88,87,89,90,667,668,17,669,93,94,254,537,254,41,215,215,92,91',
-'82,50,84,83,86,85,93,94,724,80,81,282,38,39,37,215,219,224,225,226,221',
-'223,231,232,227,228,-277,208,209,-428,-259,229,230,-277,200,728,-428',
-'204,-477,730,52,53,-277,606,54,-428,738,212,739,218,40,214,213,210,211',
-'222,220,216,18,217,740,886,743,79,72,74,75,76,77,568,507,745,73,78,749',
-'99,233,505,-215,753,98,62,63,64,7,51,506,755,391,56,57,758,759,760,60',
-'392,58,59,61,23,24,65,66,761,393,763,234,22,28,27,88,87,89,90,-260,818',
-'17,101,102,103,104,105,6,41,8,9,92,91,82,50,84,83,86,85,93,94,568,80',
-'81,471,38,39,37,215,219,224,225,226,221,223,231,823,227,228,-277,769',
-'396,-278,824,229,230,-277,36,397,-278,30,-477,822,52,53,-277,777,54',
-'-278,32,212,778,218,40,214,213,210,211,222,220,216,18,217,568,95,568',
-'79,72,74,75,76,77,254,254,234,73,78,62,63,64,874,51,875,351,568,56,57',
-'790,791,792,60,876,58,59,61,246,247,65,66,797,799,190,426,245,275,279',
-'88,87,89,90,101,102,103,104,105,428,189,431,436,276,805,-60,92,91,82',
-'50,84,83,86,85,93,94,394,80,81,215,451,655,280,653,652,651,654,101,102',
-'103,104,105,452,453,188,229,230,459,263,291,254,464,772,465,215,204',
-'807,471,52,53,472,212,54,218,291,214,213,210,211,645,291,216,481,217',
-'484,351,500,659,658,662,661,79,72,74,75,76,77,501,,,73,78,,62,63,64',
-'855,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87',
-'89,90,,,,,,,,537,,276,,,92,91,82,50,84,83,86,85,93,94,,80,81,,,,280',
-'215,219,224,225,226,221,223,231,232,227,228,,208,209,,,229,230,,772',
-',,204,,,52,53,,,54,,,212,,218,,214,213,210,211,222,220,216,,217,,,,79',
-'72,74,75,76,77,,,,73,78,,,233,,775,5,62,63,64,7,51,,,,56,57,,,,60,,58',
-'59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91',
-'82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,,265',
-',,52,53,,,54,,32,,,,40,655,,653,652,651,654,,18,,,,,79,72,74,75,76,77',
-',,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,645,58,59,61,23,24,65,66,659',
-'658,662,661,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83',
-'86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,53,,,54',
-',32,,,,40,655,,653,652,651,654,,18,,,,,79,72,74,75,76,77,,,,73,78,5',
-'62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,659,658,662,661,22',
+'-480,195,196,195,196,489,814,-480,-480,-480,511,578,578,-480,-480,-80',
+'-480,-429,579,579,489,72,531,-87,558,-480,99,489,-86,73,95,98,395,195',
+'196,-480,-480,-82,-480,-480,-480,-480,-480,489,489,558,495,-84,496,-83',
+'-81,463,659,658,662,661,186,99,557,558,291,291,98,-80,-480,-480,-480',
+'-480,-480,-480,-480,-480,-480,-480,-480,-480,-480,-480,-87,557,-480',
+'-480,-480,259,546,530,722,-74,-480,-61,99,-480,291,557,621,98,-480,-86',
+'-480,-85,-480,-480,-480,-480,-480,-480,-480,-277,-480,-480,-480,187',
+'-476,510,-277,-277,-277,99,-72,488,-277,-277,98,-277,-480,-480,-79,-75',
+'-69,-480,-83,-78,99,99,488,621,-76,98,98,99,-74,488,-277,-277,98,-277',
+'-277,-277,-277,-277,-76,-74,-75,-73,431,99,99,488,488,621,98,98,-477',
+'259,502,195,196,258,503,-74,690,-277,-277,-277,-277,-277,-277,-277,-277',
+'-277,-277,-277,-277,-277,-277,558,259,-277,-277,-277,-74,549,99,-74',
+'620,-277,713,98,-277,691,-76,188,-77,-277,521,-277,521,-277,-277,-277',
+'-277,-277,-277,-277,-272,-277,-82,-277,-76,557,189,-272,-272,-272,99',
+'254,-272,-272,-272,98,-272,-277,-277,99,-77,620,-277,-85,98,-76,-272',
+'-272,-76,477,190,-84,476,258,254,-272,-272,768,-272,-272,-272,-272,-272',
+'99,194,620,477,234,98,479,521,523,522,523,522,519,258,477,358,282,482',
+'673,360,359,-272,-272,-272,-272,-272,-272,-272,-272,-272,-272,-272,-272',
+'-272,-272,521,192,-272,-272,-272,-81,283,-272,193,-79,-272,521,-87,-272',
+'-272,291,-272,191,-272,349,-272,215,-272,-272,-272,-272,-272,-272,-272',
+'-226,-272,361,-272,523,522,524,-226,-226,-226,814,394,-226,-226,-226',
+'521,-226,-272,-272,-272,-272,396,-272,-473,212,606,-226,496,214,213',
+'210,211,523,522,526,-226,-226,397,-226,-226,-226,-226,-226,523,522,527',
+'251,477,426,-474,479,-480,-480,252,-319,-226,659,658,662,661,428,-319',
+'-226,-226,-226,-417,-476,-226,-226,-226,-319,-226,-417,-417,431,-226',
+'523,522,532,-429,-417,-226,-226,284,285,-473,436,254,-226,-417,-226',
+'-226,-60,-226,-226,-226,-226,-226,463,-421,451,-480,-480,541,-477,542',
+'-421,-473,-480,-480,-226,-474,680,-476,-476,-421,-476,-480,-480,452',
+'215,453,-72,-476,-226,-80,-226,215,-476,-226,-226,391,-476,-474,99,-480',
+'-480,-226,392,98,99,-78,254,-226,-86,98,-74,393,-76,-82,-476,-84,212',
+'-428,-477,-73,214,213,-81,212,-428,-477,459,214,213,-226,-477,461,462',
+'-428,-477,195,196,-421,-476,-476,-476,263,-476,-226,-421,-226,-476,-476',
+'-226,291,-480,-476,-477,-476,-476,-476,-476,-476,-476,-476,195,196,734',
+'606,-476,-476,-476,-476,-476,-476,-476,-427,215,254,-426,-425,662,661',
+'-427,464,-476,-426,-425,-476,-476,-476,-476,-476,-476,-476,-476,-476',
+'-476,465,-476,-476,-422,-476,-476,-476,-480,734,606,-422,212,215,-423',
+'-480,214,213,210,211,-476,-423,457,471,-480,-424,472,-476,692,458,-476',
+'-476,-424,-476,-476,291,481,-476,456,-476,484,-476,-480,-476,351,516',
+'-271,466,498,500,501,-476,517,-271,467,499,-476,-476,-476,-476,-476',
+'-476,-271,393,497,-476,-476,-477,-477,-477,535,-477,536,538,-83,-477',
+'-477,-259,540,254,-477,215,-477,-477,-477,-477,-477,-477,-477,215,215',
+'215,568,-477,-477,-477,-477,-477,-477,-477,667,668,575,669,93,94,291',
+'580,234,-477,590,591,-477,-477,-477,-477,-477,-477,-477,-477,-477,-477',
+'-69,-477,-477,592,-477,-477,-477,215,219,224,225,226,221,223,231,232',
+'227,228,507,-497,-497,-278,469,229,230,505,-477,549,-278,-477,-477,606',
+'-477,-477,506,291,-477,-278,-477,212,-477,218,-477,214,213,210,211,222',
+'220,216,-477,217,616,496,624,-477,-477,-477,-477,-477,-477,672,-278',
+'675,-477,-477,62,63,64,-278,51,436,436,-85,56,57,693,704,-278,60,431',
+'58,59,61,23,24,65,66,431,243,707,708,22,28,27,88,87,89,90,715,717,17',
+'721,254,254,215,537,215,41,724,-259,92,91,82,50,84,83,86,85,93,94,728',
+'80,81,730,38,39,37,215,219,224,225,226,221,223,231,232,227,228,-277',
+'208,209,-279,606,229,230,-277,200,738,-279,204,-477,739,52,53,-277,740',
+'54,-279,743,212,745,218,40,214,213,210,211,222,220,216,18,217,749,753',
+'755,79,72,74,75,76,77,758,759,760,73,78,761,99,233,763,-215,-277,98',
+'62,63,64,7,51,-277,-260,769,56,57,-477,777,778,60,-277,58,59,61,23,24',
+'65,66,568,568,254,254,22,28,27,88,87,89,90,234,568,17,101,102,103,104',
+'105,6,41,8,9,92,91,82,50,84,83,86,85,93,94,790,80,81,791,38,39,37,215',
+'219,224,225,226,221,223,231,232,227,228,-428,-497,-497,823,792,229,230',
+'-428,36,797,824,30,799,805,52,53,-428,807,54,822,32,212,291,218,40,214',
+'213,210,211,222,220,216,18,217,818,825,826,79,72,74,75,76,77,827,-271',
+'829,73,78,62,63,64,-271,51,830,351,-278,56,57,832,835,-271,60,-278,58',
+'59,61,246,247,65,66,839,-278,840,846,245,275,279,88,87,89,90,101,102',
+'103,104,105,847,848,758,758,276,759,861,92,91,82,50,84,83,86,85,93,94',
+'568,80,81,215,568,655,280,653,652,651,654,-277,471,874,-279,875,876',
+'880,-277,229,230,-279,883,-477,758,885,772,-277,886,204,-279,568,52',
+'53,568,212,54,218,568,214,213,210,211,645,,216,,217,,,,659,658,662,661',
+'79,72,74,75,76,77,,,,73,78,,62,63,64,775,51,,,,56,57,,,,60,,58,59,61',
+'246,247,65,66,,,,,245,275,279,88,87,89,90,101,102,103,104,105,,,537',
+',276,,,92,91,82,50,84,83,86,85,93,94,,80,81,,,,280,215,219,224,225,226',
+'221,223,231,232,227,228,,208,209,,,229,230,,772,,,204,,,52,53,,,54,',
+',212,,218,,214,213,210,211,222,220,216,,217,,,,79,72,74,75,76,77,,,',
+'73,78,,,233,,855,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66',
+',,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85',
+'93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,53,,,54,,32,',
+',,40,655,,653,652,651,654,,18,,,,,79,72,74,75,76,77,,,,73,78,5,62,63',
+'64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,659,658,662,661,22,28,27',
+'88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81',
+',38,39,37,,,,,,,,,,,,,,,,,,,,36,,,265,,,52,53,,,54,,32,,,,40,655,,653',
+'652,651,654,,18,,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56',
+'57,,,,60,,58,59,61,23,24,65,66,659,658,662,661,22,28,27,88,87,89,90',
+',,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,',
+',,,,,,,,,,,,,,,,,36,,,30,,,52,53,,,54,,32,,,,40,655,,653,652,651,654',
+',18,,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,645',
+'58,59,61,23,24,65,66,659,658,662,661,22,28,27,88,87,89,90,,,17,,,,,',
+'6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,215,-497,-497',
+'-497,-497,221,223,,,-497,-497,,,,,,229,230,,36,,,30,,,52,53,,,54,,32',
+'212,,218,40,214,213,210,211,222,220,216,18,217,,,,79,72,74,75,76,77',
+',,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22',
'28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,',
'80,81,,38,39,37,215,,,,,,,,,,,,,,,,229,230,,36,,,30,,,52,53,,,54,,32',
'212,,218,40,214,213,210,211,,,216,18,217,,,,79,72,74,75,76,77,,,,73',
'78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27',
'88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81',
-',38,39,37,215,-497,-497,-497,-497,221,223,,,-497,-497,,,,,,229,230,',
-'36,,,30,,,52,53,,,54,,32,212,,218,40,214,213,210,211,222,220,216,18',
-'217,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58',
-'59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91',
-'82,50,84,83,86,85,93,94,,80,81,,38,39,37,215,,,,,,,,,,,,,,,,229,230',
-',36,,,30,,,52,53,,,54,,32,212,,218,40,214,213,210,211,,,216,18,217,',
-',,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61',
-'23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50',
-'84,83,86,85,93,94,,80,81,,38,39,37,215,219,224,225,226,221,223,231,232',
-'227,228,,-497,-497,,,229,230,,36,,,30,,,52,53,,,54,,32,212,,218,40,214',
-'213,210,211,222,220,216,18,217,,,,79,72,74,75,76,77,,,,73,78,5,62,63',
-'64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90',
-',,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,215',
-'219,224,225,226,221,223,231,232,227,228,,-497,-497,,,229,230,,36,,,30',
-',,52,53,,,54,,32,212,,218,40,214,213,210,211,222,220,216,18,217,,,,79',
-'72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23',
-'24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84',
-'83,86,85,93,94,,80,81,,38,39,37,215,-497,-497,-497,-497,221,223,,,-497',
+',38,39,37,215,,,,,,,,,,,,,,,,229,230,,36,,,30,,,52,53,,,54,,32,212,',
+'218,40,214,213,210,211,,,216,18,217,,,,79,72,74,75,76,77,,,,73,78,5',
+'62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87',
+'89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39',
+'37,215,,,,,,,,,,,,,,,,229,230,,36,,,265,,,52,53,,,54,,32,212,,218,40',
+'214,213,210,211,,,216,18,217,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64',
+'7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,',
+',17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,215',
+'-497,-497,-497,-497,221,223,,,-497,-497,,,,,,229,230,,36,,,265,,,52',
+'53,,,54,,32,212,,218,40,214,213,210,211,222,220,216,18,217,,,,79,72',
+'74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24',
+'65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83',
+'86,85,93,94,,80,81,,38,39,37,215,-497,-497,-497,-497,221,223,,,-497',
'-497,,,,,,229,230,,36,,,30,,,52,53,,,54,,32,212,,218,40,214,213,210',
'211,222,220,216,18,217,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51',
',,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,',
@@ -137,40 +139,38 @@ clist = [
',32,212,,218,40,214,213,210,211,222,220,216,18,217,,,,79,72,74,75,76',
'77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,',
',22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93',
-'94,,80,81,,38,39,37,215,,,,,,,,,,,,,,,,229,230,,36,,,30,,,52,53,,,54',
-',32,212,,218,40,214,213,210,211,,,216,18,217,,,,79,72,74,75,76,77,,',
-',73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28',
-'27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80',
-'81,,38,39,37,215,-497,-497,-497,-497,221,223,,,-497,-497,,,,,,229,230',
-',36,,,30,,,52,53,,,54,,32,212,,218,40,214,213,210,211,222,220,216,18',
-'217,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58',
-'59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91',
-'82,50,84,83,86,85,93,94,,80,81,,38,39,37,215,-497,-497,-497,-497,221',
-'223,,,-497,-497,,,,,,229,230,,36,,,30,,,52,53,,,54,,32,212,,218,40,214',
-'213,210,211,222,220,216,18,217,,,,79,72,74,75,76,77,,,,73,78,5,62,63',
-'64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90',
-',,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,215',
-',,,,,,,,,,,,,,,229,230,,36,,,30,,,52,53,,,54,,32,212,,,40,214,213,210',
-'211,,,,18,,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,',
+'94,,80,81,,38,39,37,215,-497,-497,-497,-497,221,223,,,-497,-497,,,,',
+',229,230,,36,,,30,,,52,53,,,54,,32,212,,218,40,214,213,210,211,222,220',
+'216,18,217,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,',
',60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8',
-'9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,215,,,,,,,,,,,,,,,',
-'229,230,,36,,,265,,,52,53,,,54,,32,212,,218,40,214,213,210,211,,,,18',
-',,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59',
-'61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82',
-'50,84,83,86,85,93,94,,80,81,,38,39,37,215,,,,,,,,,,,,,,,,229,230,,36',
-',,265,,,52,53,,,54,,32,212,,218,40,214,213,210,211,,,,18,,,,,79,72,74',
-'75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65',
-'66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86',
-'85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,53,,,54,,32',
-',,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56',
-'57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6',
-'41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,',
-',,,,,36,,,30,,,52,53,,,54,,32,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77',
-',,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22',
-'28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,',
-'80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,53,,,54,,32,,,,40,,',
-',,,,,18,,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60',
+'9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,215,-497,-497,-497',
+'-497,221,223,,,-497,-497,,,,,,229,230,,36,,,30,,,52,53,,,54,,32,212',
+',218,40,214,213,210,211,222,220,216,18,217,,,,79,72,74,75,76,77,,,,73',
+'78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27',
+'88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81',
+',38,39,37,215,219,224,225,226,221,223,,,227,228,,,,,,229,230,,36,,,30',
+',,52,53,,,54,,32,212,,218,40,214,213,210,211,222,220,216,18,217,,,,79',
+'72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23',
+'24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84',
+'83,86,85,93,94,,80,81,,38,39,37,215,219,224,225,226,221,223,231,,227',
+'228,,,,,,229,230,,36,,,30,,,52,53,,,54,,32,212,,218,40,214,213,210,211',
+'222,220,216,18,217,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,',
+'56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,',
+',6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,215,,,,,,,',
+',,,,,,,,229,230,,36,,,30,,,52,53,,,54,,32,212,,218,40,214,213,210,211',
+',,,18,,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60',
',58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92',
+'91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,215,,,,,,,,,,,,,,,,229,230',
+',36,,,30,,,52,53,,,54,,32,212,,218,40,214,213,210,211,,,,18,,,,,79,72',
+'74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24',
+'65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83',
+'86,85,93,94,,80,81,,38,39,37,215,,,,,,,,,,,,,,,,229,230,,36,,,30,,,52',
+'53,,,54,,32,212,,,40,214,213,210,211,,,,18,,,,,79,72,74,75,76,77,,,',
+'73,78,5,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28',
+'27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80',
+'81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,53,,,54,,32,,,,40,,,,,',
+',,18,,,,,79,72,74,75,76,77,,,,73,78,5,62,63,64,7,51,,,,56,57,,,,60,',
+'58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92',
'91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,',
'30,,,52,53,,,54,,32,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,5',
'62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87',
@@ -207,155 +207,145 @@ clist = [
'51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17',
',,,,,6,41,8,9,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,',
',,,,,,,,,,,,36,,,30,,,52,53,,,54,,32,,,,40,,,,,,,,18,,,,,79,72,74,75',
-'76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,',
-',,,245,275,279,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93',
-'94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40',
-',,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,7,51,,,,56,57,,,',
-'60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9',
-'92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36',
-',,30,,,52,53,,,54,,32,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78',
-'153,164,154,177,150,170,160,159,180,181,175,158,157,152,178,182,183',
-'162,151,165,169,171,163,156,,,172,179,174,173,166,176,161,149,168,167',
-',,,,,148,155,146,147,144,145,109,111,108,,110,,,,,,,,139,140,,137,121',
-'122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120',
-'138,136,135,131,132,127,125,118,,119,,,143,79,,,,,,,,,,78,153,164,154',
-'177,150,170,160,159,180,181,175,158,157,152,178,182,183,162,151,165',
-'169,171,163,156,,,172,179,174,173,166,176,161,149,168,167,,,,,,148,155',
-'146,147,144,145,109,111,,,110,,,,,,,,139,140,,137,121,122,123,,126,128',
-',,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131',
-'132,127,125,118,,119,,,143,79,,,62,63,64,,51,,,78,56,57,,,,60,,58,59',
-'61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50',
-'84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52',
-'53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51',
-',,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,,,,',
-',,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,',
-',,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77',
-',,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245',
-'28,27,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81',
-',38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,241,,243,,40,,',
-',,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60',
+'76,77,,,,73,78,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,',
+',,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85,93',
+'94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,53,,,54,,32,,,,40',
+',,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,153,164,154,177,150,170,160',
+'159,180,181,175,158,157,152,178,182,183,162,151,165,169,171,163,156',
+',,172,179,174,173,166,176,161,149,168,167,,,,,,148,155,146,147,144,145',
+'109,111,108,,110,,,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,',
+'141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125',
+'118,,119,,,143,79,,,,,,,,,,78,153,164,154,177,150,170,160,159,180,181',
+'175,158,157,152,178,182,183,162,151,165,169,171,163,156,,,172,179,174',
+'173,166,176,161,149,168,167,,,,,,148,155,146,147,144,145,109,111,,,110',
+',,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141,142,129,130,',
+',,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119,,,143',
+'79,,,62,63,64,,51,,,78,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27',
+'88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38',
+'39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,',
+',,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23',
+'24,65,66,,,,,22,28,27,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86',
+'85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54',
+',,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56',
+'57,,,,60,,58,59,61,246,247,65,66,,,,,245,28,27,88,87,89,90,,,,,,,,,',
+'41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,',
+',,,200,,,204,,,52,53,,,54,,241,,243,,40,,,,,,,,207,,,,,79,72,74,75,76',
+'77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,',
+'245,28,27,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80',
+'81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,241,,243,,40',
+',,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60',
',58,59,61,246,247,65,66,,,,,245,28,27,88,87,89,90,,,,,,,,,,41,,,92,91',
'82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204',
',,52,53,,,54,,241,,243,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78',
-'62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,28,27,88',
-'87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37',
-',,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,241,,243,,40,,,,,,,,207,',
-',,,79,72,74,75,76,77,,,,73,78,-249,-249,-249,,-249,,,,-249,-249,,,,-249',
-',-249,-249,-249,-249,-249,-249,-249,,,,,-249,-249,-249,-249,-249,-249',
-'-249,,,,,,,,,,-249,,,-249,-249,-249,-249,-249,-249,-249,-249,-249,-249',
-',-249,-249,,-249,-249,-249,,,,,,,,,,,,,,,,,,,,-249,,,-249,254,,-249',
-'-249,,,-249,,-249,,-249,,-249,,,,,,,,-249,,,,,-249,-249,-249,-249,-249',
-'-249,,,,-249,-249,-249,-249,-249,,-249,,,,-249,-249,,,,-249,,-249,-249',
-'-249,-249,-249,-249,-249,,,,,-249,-249,-249,-249,-249,-249,-249,,,,',
-',,,,,-249,,,-249,-249,-249,-249,-249,-249,-249,-249,-249,-249,,-249',
-'-249,,-249,-249,-249,,,,,,,,,,,,,,,,,,,,-249,,,-249,263,,-249,-249,',
-',-249,,-249,,-249,,-249,,,,,,,,-249,,,,,-249,-249,-249,-249,-249,-249',
-',,,-249,-249,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,',
-',245,275,279,88,87,89,90,,,,,,,,,,276,,,92,91,82,50,84,83,86,85,93,94',
-',80,81,,,,280,,215,219,224,225,226,221,223,231,232,227,228,,208,209',
-',,229,230,273,,,270,,,52,53,,,54,,269,,212,,218,,214,213,210,211,222',
-'220,216,,217,,,79,72,74,75,76,77,,,,73,78,62,63,64,233,51,568,,,56,57',
-',,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,276',
-',,92,91,82,50,84,83,86,85,93,94,,80,81,,,,280,,215,219,224,225,226,221',
-'223,231,232,227,228,,208,209,,,229,230,273,,,204,,,52,53,,,54,,,,212',
-',218,,214,213,210,211,222,220,216,,217,,,79,72,74,75,76,77,,,,73,78',
-'62,63,64,233,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279',
+'-249,-249,-249,,-249,,,,-249,-249,,,,-249,,-249,-249,-249,-249,-249',
+'-249,-249,,,,,-249,-249,-249,-249,-249,-249,-249,,,,,,,,,,-249,,,-249',
+'-249,-249,-249,-249,-249,-249,-249,-249,-249,,-249,-249,,-249,-249,-249',
+',,,,,,,,,,,,,,,,,,,-249,,,-249,254,,-249,-249,,,-249,,-249,,-249,,-249',
+',,,,,,,-249,,,,,-249,-249,-249,-249,-249,-249,,,,-249,-249,-249,-249',
+'-249,,-249,,,,-249,-249,,,,-249,,-249,-249,-249,-249,-249,-249,-249',
+',,,,-249,-249,-249,-249,-249,-249,-249,,,,,,,,,,-249,,,-249,-249,-249',
+'-249,-249,-249,-249,-249,-249,-249,,-249,-249,,-249,-249,-249,,,,,,',
+',,,,,,,,,,,,,-249,,,-249,263,,-249,-249,,,-249,,-249,,-249,,-249,,,',
+',,,,-249,,,,,-249,-249,-249,-249,-249,-249,,,,-249,-249,62,63,64,,51',
+',,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,',
+',,,,,,,,276,,,92,91,82,50,84,83,86,85,93,94,,80,81,,,,280,,215,219,224',
+'225,226,221,223,231,232,227,228,,208,209,,,229,230,273,,,270,,,52,53',
+',,54,,269,,212,,218,,214,213,210,211,222,220,216,,217,,,79,72,74,75',
+'76,77,,,,73,78,62,63,64,233,51,568,,,56,57,,,,60,,58,59,61,246,247,65',
+'66,,,,,245,275,279,88,87,89,90,,,,,,,,,,276,,,92,91,82,50,84,83,86,85',
+'93,94,,80,81,,,,280,,215,219,224,225,226,221,223,231,232,227,228,,208',
+'209,,,229,230,273,,,204,,,52,53,,,54,,,,212,,218,,214,213,210,211,222',
+'220,216,,217,,,79,72,74,75,76,77,,,,73,78,62,63,64,233,51,,,,56,57,',
+',,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,41',
+',,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,',
+'200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73',
+'78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279',
'88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39',
'37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,',
'79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246',
'247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83',
'86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,',
'54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,',
-',56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,,,',
-',,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,',
-',,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76',
-'77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22',
-'28,27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80',
-'81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,',
-',,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58',
-'59,61,246,247,65,66,,,,,245,28,27,88,87,89,90,,,,,,,,,,41,,,92,91,82',
-'50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,',
-',52,53,,,54,,299,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62',
-'63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88',
-'87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37',
-',,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79',
-'72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24',
-'65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84,83,86',
-'85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54',
-',,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56',
-'57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,,41',
-',,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,',
-'200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73',
-'78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279',
-'88,87,89,90,,,,,,,,,,276,,,92,91,82,50,84,83,86,85,93,94,,80,81,,,,280',
-',215,219,224,225,226,221,223,231,232,227,228,,208,209,,,229,230,315',
-',,30,,,52,53,,,54,,32,,212,,218,,214,213,210,211,222,220,216,,217,,',
-'79,72,74,75,76,77,,,,73,78,62,63,64,233,51,,,,56,57,,,,60,,58,59,61',
-'246,247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,276,,,92,91,320,50',
-'84,83,321,85,93,94,,80,81,,,,280,,215,219,224,225,226,221,223,231,232',
-'227,228,,208,209,,327,229,230,322,,,204,,,52,53,,,54,,,,212,,218,,214',
-'213,210,211,222,220,216,,217,,,79,72,74,75,76,77,,,,73,78,62,63,64,233',
-'51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90',
-',,,,,,,,,276,,,92,91,320,50,84,83,321,85,93,94,,80,81,,,,280,,215,219',
-'224,225,226,221,223,231,232,227,228,,208,209,,,229,230,322,,,204,,,52',
-'53,,,54,,,,212,,218,,214,213,210,211,222,220,216,,217,,,79,72,74,75',
-'76,77,,,,73,78,-473,-473,-473,233,-473,,,,-473,-473,,,,-473,,-473,-473',
-'-473,-473,-473,-473,-473,,-473,,,-473,-473,-473,-473,-473,-473,-473',
-',,,,,,,,,-473,,,-473,-473,-473,-473,-473,-473,-473,-473,-473,-473,,-473',
-'-473,,-473,-473,-473,,,,,,,,,,,,,,,,,,,,-473,,,-473,-473,,-473,-473',
-',,-473,,-473,,-473,,-473,,,,,,,,-473,,-473,,,-473,-473,-473,-473,-473',
-'-473,,,,-473,-473,-474,-474,-474,,-474,,,,-474,-474,,,,-474,,-474,-474',
-'-474,-474,-474,-474,-474,,-474,,,-474,-474,-474,-474,-474,-474,-474',
-',,,,,,,,,-474,,,-474,-474,-474,-474,-474,-474,-474,-474,-474,-474,,-474',
-'-474,,-474,-474,-474,,,,,,,,,,,,,,,,,,,,-474,,,-474,-474,,-474,-474',
-',,-474,,-474,,-474,,-474,,,,,,,,-474,,-474,,,-474,-474,-474,-474,-474',
-'-474,,,,-474,-474,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66',
+',56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,',
+',,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,',
+',,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77',
+',,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245',
+'28,27,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81',
+',38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,299,,,,40,,,,,',
+',,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58',
+'59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,41,,,92,91',
+'82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204',
+',,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63',
+'64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90',
+',,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,',
+',,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74',
+'75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66',
',,,,22,28,27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93',
'94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40',
',,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60',
-',58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,,41,,,92,91',
-'82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204',
-',,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63',
+',58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,276,,,92',
+'91,82,50,84,83,86,85,93,94,,80,81,,,,280,,215,219,224,225,226,221,223',
+'231,232,227,228,,208,209,,,229,230,315,,,30,,,52,53,,,54,,32,,212,,218',
+',214,213,210,211,222,220,216,,217,,,79,72,74,75,76,77,,,,73,78,62,63',
+'64,233,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88',
+'87,89,90,,,,,,,,,,276,,,92,91,320,50,84,83,321,85,93,94,,80,81,,,,280',
+',215,219,224,225,226,221,223,231,232,227,228,,208,209,,327,229,230,322',
+',,204,,,52,53,,,54,,,,212,,218,,214,213,210,211,222,220,216,,217,,,79',
+'72,74,75,76,77,,,,73,78,62,63,64,233,51,,,,56,57,,,,60,,58,59,61,246',
+'247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,276,,,92,91,320,50,84',
+'83,321,85,93,94,,80,81,,,,280,,215,219,224,225,226,221,223,231,232,227',
+'228,,208,209,,,229,230,322,,,204,,,52,53,,,54,,,,212,,218,,214,213,210',
+'211,222,220,216,,217,,,79,72,74,75,76,77,,,,73,78,-473,-473,-473,233',
+'-473,,,,-473,-473,,,,-473,,-473,-473,-473,-473,-473,-473,-473,,-473',
+',,-473,-473,-473,-473,-473,-473,-473,,,,,,,,,,-473,,,-473,-473,-473',
+'-473,-473,-473,-473,-473,-473,-473,,-473,-473,,-473,-473,-473,,,,,,',
+',,,,,,,,,,,,,-473,,,-473,-473,,-473,-473,,,-473,,-473,,-473,,-473,,',
+',,,,,-473,,-473,,,-473,-473,-473,-473,-473,-473,,,,-473,-473,-474,-474',
+'-474,,-474,,,,-474,-474,,,,-474,,-474,-474,-474,-474,-474,-474,-474',
+',-474,,,-474,-474,-474,-474,-474,-474,-474,,,,,,,,,,-474,,,-474,-474',
+'-474,-474,-474,-474,-474,-474,-474,-474,,-474,-474,,-474,-474,-474,',
+',,,,,,,,,,,,,,,,,,-474,,,-474,-474,,-474,-474,,,-474,,-474,,-474,,-474',
+',,,,,,,-474,,-474,,,-474,-474,-474,-474,-474,-474,,,,-474,-474,62,63',
'64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90',
',,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,',
',,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74',
'75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66',
',,,,22,28,27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93',
'94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40',
-',,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,7,51,,,,56,57,,,,60',
-',58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92',
-'91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,',
-'30,,,52,53,,,54,,32,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62',
-'63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89',
-'90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,',
-',,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,369,,,,40,,,,,,,,207,,,,,79,72',
-'74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65',
-'66,,,,,22,28,27,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93',
-'94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,369,',
-',,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57',
+',,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60',
+',58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,,41,,,92,91',
+'82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204',
+',,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63',
+'64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90',
+',,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,',
+',,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74',
+'75,76,77,,,,73,78,62,63,64,7,51,,,,56,57,,,,60,,58,59,61,23,24,65,66',
+',,,,22,28,27,88,87,89,90,,,17,,,,,,6,41,8,9,92,91,82,50,84,83,86,85',
+'93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,36,,,30,,,52,53,,,54,,32,',
+',,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57',
',,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,,,,,,,,41,,,92',
'91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,',
-',204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78',
-'62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,28,27,88',
+',204,,,52,53,,,54,,369,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73',
+'78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88',
'87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37',
-',,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,299,,,,40,,,,,,,,207,,,,',
+',,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,369,,,,40,,,,,,,,207,,,,',
'79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23',
'24,65,66,,,,,22,28,27,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86',
'85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54',
',,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56',
-'57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,,41',
-',,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,',
-'200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73',
-'78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88',
-'87,89,90,,,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39',
-'37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79',
-'72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247',
-'65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86',
-'85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54',
-',,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56',
-'57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,',
-',,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,',
-',,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77',
+'57,,,,60,,58,59,61,246,247,65,66,,,,,245,28,27,88,87,89,90,,,,,,,,,',
+'41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,',
+',,,200,,,204,,,52,53,,,54,,299,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77',
+',,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28',
+'27,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38',
+'39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,',
+',,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61',
+'23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84',
+'83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53',
+',,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,',
+',,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,',
+',,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,',
+',,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77',
',,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245',
'275,279,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80',
'81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,',
@@ -448,53 +438,63 @@ clist = [
'247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83',
'86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,',
'54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,',
-',56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,28,27,88,87,89,90,,,,,',
-',,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,',
-',,,,,,,200,,,204,,,52,53,,,54,,241,,243,,40,,,,,,,,207,,,,,79,72,74',
-'75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66',
-',,,,245,28,27,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94',
-',80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,445,53,,,54,,241,,243',
-',40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57',
-',,,60,,58,59,61,246,247,65,66,,,,,245,28,27,88,87,89,90,,,,,,,,,,41',
-',,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,',
-'200,,,204,,449,52,53,,,54,,241,,243,,40,,,,,,,,207,,,,,79,72,74,75,76',
+',56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,,,',
+',,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,',
+',,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76',
'77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,',
-'245,275,279,88,87,89,90,,,,,,,,,,276,,,92,91,82,50,84,83,86,85,93,94',
-',80,81,,,,280,,215,219,224,225,226,221,223,231,232,227,228,,208,209',
-',,229,230,273,,,204,,,52,53,,,54,,,,212,,218,,214,213,210,211,222,220',
-'216,,217,,,79,72,74,75,76,77,,,,73,78,62,63,64,233,51,,,,56,57,,,,60',
-',58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,,,,41,,,92',
-'91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,',
-',204,469,,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73',
-'78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279',
-'88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39',
-'37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,',
-'79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23',
-'24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84,83',
-'86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,',
-'54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,',
-'56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,',
+'245,275,279,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94',
+',80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,',
+',,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60',
+',58,59,61,246,247,65,66,,,,,245,28,27,88,87,89,90,,,,,,,,,,41,,,92,91',
+'82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204',
+',,52,53,,,54,,241,,243,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78',
+'62,63,64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,28,27,88',
+'87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37',
+',,,,,,,,,,,,,,,,,,,200,,,204,,,445,53,,,54,,241,,243,,40,,,,,,,,207',
+',,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61',
+'246,247,65,66,,,,,245,28,27,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84',
+'83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,449,52',
+'53,,,54,,241,,243,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63',
+'64,,51,,,,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87',
+'89,90,,,,,,,,,,276,,,92,91,82,50,84,83,86,85,93,94,,80,81,,,,280,,215',
+'219,224,225,226,221,223,231,232,227,228,,208,209,,,229,230,273,,,204',
+',,52,53,,,54,,,,212,,218,,214,213,210,211,222,220,216,,217,,,79,72,74',
+'75,76,77,,,,73,78,62,63,64,233,51,,,,56,57,,,,60,,58,59,61,246,247,65',
+'66,,,,,245,275,279,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85',
+'93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,469,,52,53,,,54',
+',,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56',
+'57,,,,60,,58,59,61,246,247,65,66,,,,,245,275,279,88,87,89,90,,,,,,,',
',,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,',
-',,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77',
+',,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207,,,,,79,72,74,75,76,77',
',,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28',
'27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81',
',38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18',
',,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61',
'23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84',
'83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53',
-',,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,153,164,154,177',
-'150,170,160,159,180,181,175,158,157,152,178,182,183,162,151,165,169',
-'171,163,156,,,172,179,174,173,166,176,161,149,168,167,,,,,,148,155,146',
-'147,144,145,109,111,,,110,,,,,,,,139,140,,137,121,122,123,,126,128,',
-',124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132',
-'127,125,118,,119,,,143,79,,,-249,-249,-249,,-249,,,78,-249,-249,,,,-249',
-',-249,-249,-249,-249,-249,-249,-249,,,,,-249,-249,-249,-249,-249,-249',
-'-249,,,,,,,,,,-249,,,-249,-249,-249,-249,-249,-249,-249,-249,-249,-249',
-',-249,-249,,-249,-249,-249,,,,,,,,,,,,,,,,,,,,-249,,,-249,254,,-249',
-'-249,,,-249,,-249,,-249,,-249,,,,,,,,-249,,,,,-249,-249,-249,-249,-249',
-'-249,,,,-249,-249,-478,-478,-478,,-478,,,,-478,-478,,,,-478,,-478,-478',
-'-478,-478,-478,-478,-478,,,,,-478,-478,-478,-478,-478,-478,-478,,,,',
-',,,,,-478,,,-478,-478,-478,-478,-478,-478,-478,-478,-478,-478,,-478',
+',,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77,,,,73,78,62,63,64,,51,',
+',,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28,27,88,87,89,90,,,17,,',
+',,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,,38,39,37,,,,,,,,,,,,',
+',,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18,,,,,79,72,74,75,76,77',
+',,,73,78,62,63,64,,51,,,,56,57,,,,60,,58,59,61,23,24,65,66,,,,,22,28',
+'27,88,87,89,90,,,17,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81',
+',38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,18',
+',,,,79,72,74,75,76,77,,,,73,78,153,164,154,177,150,170,160,159,180,181',
+'175,158,157,152,178,182,183,162,151,165,169,171,163,156,,,172,179,174',
+'173,166,176,161,149,168,167,,,,,,148,155,146,147,144,145,109,111,,,110',
+',,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141,142,129,130,',
+',,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119,,,143',
+'79,,,62,63,64,,51,,,78,56,57,,,,60,,58,59,61,246,247,65,66,,,,,245,275',
+'279,88,87,89,90,,,,,,,,,,41,,,92,91,82,50,84,83,86,85,93,94,,80,81,',
+'38,39,37,,,,,,,,,,,,,,,,,,,,200,,,204,,,52,53,,,54,,,,,,40,,,,,,,,207',
+',,,,79,72,74,75,76,77,,,,73,78,-249,-249,-249,,-249,,,,-249,-249,,,',
+'-249,,-249,-249,-249,-249,-249,-249,-249,,,,,-249,-249,-249,-249,-249',
+'-249,-249,,,,,,,,,,-249,,,-249,-249,-249,-249,-249,-249,-249,-249,-249',
+'-249,,-249,-249,,-249,-249,-249,,,,,,,,,,,,,,,,,,,,-249,,,-249,254,',
+'-249,-249,,,-249,,-249,,-249,,-249,,,,,,,,-249,,,,,-249,-249,-249,-249',
+'-249,-249,,,,-249,-249,-478,-478,-478,,-478,,,,-478,-478,,,,-478,,-478',
+'-478,-478,-478,-478,-478,-478,,,,,-478,-478,-478,-478,-478,-478,-478',
+',,,,,,,,,-478,,,-478,-478,-478,-478,-478,-478,-478,-478,-478,-478,,-478',
'-478,,-478,-478,-478,,,,,,,,,,,,,,,,,,,,-478,,,-478,-478,,-478,-478',
',,-478,,-478,,-478,,-478,,,,,,,,-478,,,,,-478,-478,-478,-478,-478,-478',
',,,-478,-478,-479,-479,-479,,-479,,,,-479,-479,,,,-479,,-479,-479,-479',
@@ -752,54 +752,54 @@ clist = [
'122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120',
'138,136,135,131,132,127,125,118,,119,,,143,215,219,224,225,226,221,223',
'231,232,227,228,,208,209,,,229,230,,,,-215,,,,,,,,,,,212,,218,,214,213',
-'210,211,222,220,216,,217,,,,,,,,635,385,,,636,,,,,233,,-215,139,140',
+'210,211,222,220,216,,217,,,,,,,,376,379,,,377,,,,,233,,-215,139,140',
',137,121,122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134',
-'133,,120,138,136,135,131,132,127,125,118,,119,433,379,143,,434,,,,,',
+'133,,120,138,136,135,131,132,127,125,118,,119,381,385,143,,383,,,,,',
',,139,140,,137,121,122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,',
-',,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119,632,385,143',
-',633,,,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141,142,129',
-'130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119,630',
-'379,143,,631,,,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141',
-'142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125,118',
-',119,550,379,143,,551,,,,,,,,139,140,,137,121,122,123,,126,128,,,124',
-',,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127',
-'125,118,,119,433,379,143,,434,,,,,,,,139,140,,137,121,122,123,,126,128',
-',,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131',
-'132,127,125,118,,119,433,379,143,,434,,,,,,,,139,140,,137,121,122,123',
-',126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136',
-'135,131,132,127,125,118,,119,,,143,215,219,224,225,226,221,223,231,232',
-'227,228,,208,209,,,229,230,,,,,,,,,,,,,,,212,,218,,214,213,210,211,222',
-'220,216,,217,,,,,,,552,385,,,553,,,,,,233,556,139,140,,137,121,122,123',
-',126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136',
-'135,131,132,127,125,118,,119,376,379,143,,377,,,,,,,,139,140,,137,121',
-'122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120',
-'138,136,135,131,132,127,125,118,,119,857,379,143,,858,,,,,,,,139,140',
-',137,121,122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134',
-'133,,120,138,136,135,131,132,127,125,118,,119,597,385,143,,598,,,,,',
-',,139,140,,137,121,122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,',
-',,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119,859,385,143',
-',860,,,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141,142,129',
-'130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119,594',
-'379,143,,595,,,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141',
+',,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119,433,379,143',
+',434,,,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141,142,129',
+'130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119,433',
+'379,143,,434,,,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141',
'142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125,118',
',119,550,379,143,,551,,,,,,,,139,140,,137,121,122,123,,126,128,,,124',
',,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127',
'125,118,,119,552,385,143,,553,,,,,,,,139,140,,137,121,122,123,,126,128',
',,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131',
-'132,127,125,118,,119,433,379,143,,434,,,,,,,,139,140,,137,121,122,123',
-',126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136',
-'135,131,132,127,125,118,,119,381,385,143,,383,,,,,,,,139,140,,137,121',
-'122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120',
-'138,136,135,131,132,127,125,118,,119,433,379,143,,434,,,,,,,,139,140',
-',137,121,122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134',
-'133,,120,138,136,135,131,132,127,125,118,,119,,,143,215,219,224,225',
-'226,221,223,231,232,227,228,,208,209,,,229,230,,,,,,,,,,,,,,,212,,218',
-',214,213,210,211,222,220,216,,217,,215,219,224,225,226,221,223,231,232',
-'227,228,,208,209,291,233,229,230,,,,,,,,,,,,,,,212,,218,,214,213,210',
-'211,222,220,216,,217,,215,219,224,225,226,221,223,231,232,227,228,,208',
-'209,291,233,229,230,,,,,,,,,,,,,,,212,,218,,214,213,210,211,222,220',
-'216,,217,,,,,,,,,,,,,,,,,233' ]
- racc_action_table = arr = ::Array.new(24362, nil)
+'132,127,125,118,,119,,,143,215,219,224,225,226,221,223,231,232,227,228',
+',208,209,,,229,230,,,,,,,,,,,,,,,212,,218,,214,213,210,211,222,220,216',
+',217,,,,,,,594,379,,,595,,,,,,233,556,139,140,,137,121,122,123,,126',
+'128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135',
+'131,132,127,125,118,,119,597,385,143,,598,,,,,,,,139,140,,137,121,122',
+'123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138',
+'136,135,131,132,127,125,118,,119,550,379,143,,551,,,,,,,,139,140,,137',
+'121,122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133',
+',120,138,136,135,131,132,127,125,118,,119,552,385,143,,553,,,,,,,,139',
+'140,,137,121,122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,',
+',134,133,,120,138,136,135,131,132,127,125,118,,119,630,379,143,,631',
+',,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141,142,129,130,',
+',,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119,632,385',
+'143,,633,,,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,,141,142',
+'129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125,118,,119',
+'635,385,143,,636,,,,,,,,139,140,,137,121,122,123,,126,128,,,124,,,,',
+'141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132,127,125',
+'118,,119,433,379,143,,434,,,,,,,,139,140,,137,121,122,123,,126,128,',
+',124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135,131,132',
+'127,125,118,,119,433,379,143,,434,,,,,,,,139,140,,137,121,122,123,,126',
+'128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138,136,135',
+'131,132,127,125,118,,119,433,379,143,,434,,,,,,,,139,140,,137,121,122',
+'123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133,,120,138',
+'136,135,131,132,127,125,118,,119,857,379,143,,858,,,,,,,,139,140,,137',
+'121,122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,,,134,133',
+',120,138,136,135,131,132,127,125,118,,119,859,385,143,,860,,,,,,,,139',
+'140,,137,121,122,123,,126,128,,,124,,,,,141,142,129,130,,,,,,,,,,,,',
+',134,133,,120,138,136,135,131,132,127,125,118,,119,,,143,215,219,224',
+'225,226,221,223,231,232,227,228,,208,209,,,229,230,,,,,,,,,,,,,,,212',
+',218,,214,213,210,211,222,220,216,,217,,215,219,224,225,226,221,223',
+'231,232,227,228,,208,209,291,233,229,230,,,,,,,,,,,,,,,212,,218,,214',
+'213,210,211,222,220,216,,217,,215,219,224,225,226,221,223,231,232,227',
+'228,,208,209,291,233,229,230,,,,,,,,,,,,,,,212,,218,,214,213,210,211',
+'222,220,216,,217,,,,,,,,,,,,,,,,,233' ]
+ racc_action_table = arr = ::Array.new(24340, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -809,484 +809,480 @@ clist = [
end
clist = [
-'383,512,512,518,518,798,631,383,383,383,326,848,440,383,383,743,383',
-'199,446,440,347,424,306,727,334,630,70,55,316,881,711,334,603,603,70',
-'383,383,711,383,383,383,383,383,307,627,297,333,313,297,632,500,201',
-'446,333,591,424,362,848,848,848,848,440,594,199,383,383,383,383,383',
-'383,383,383,383,383,383,383,383,383,363,711,383,383,383,347,383,603',
-'303,595,383,303,512,383,518,591,744,512,383,201,383,633,383,383,383',
-'383,383,383,383,381,383,631,383,55,632,326,381,381,381,798,743,798,381',
-'381,798,381,383,383,594,383,630,383,383,316,381,326,306,727,306,727',
-'326,306,727,491,381,381,594,381,381,381,381,381,313,595,632,500,693',
-'307,627,307,627,492,307,627,633,332,582,594,368,447,594,595,332,381',
-'381,381,381,381,381,381,381,381,381,381,381,381,381,857,277,381,381',
-'381,595,381,744,595,744,381,26,744,381,394,693,447,633,381,528,381,582',
-'381,381,381,381,381,381,381,432,381,381,381,377,615,615,432,432,432',
-'321,14,432,432,432,371,432,381,381,540,381,857,381,381,551,491,432,491',
-'857,574,491,394,755,857,277,432,432,857,432,432,432,432,432,492,26,492',
-'348,377,492,376,377,528,528,35,14,857,277,14,375,283,321,528,540,574',
-'382,540,26,321,550,346,551,320,321,345,184,432,321,50,755,755,755,755',
-'432,772,50,50,50,432,432,50,50,50,376,50,321,376,35,301,402,35,301,3',
-'283,50,50,283,3,348,348,348,432,403,50,50,550,50,50,50,50,50,331,320',
-'298,404,432,298,432,331,320,432,346,346,346,320,345,345,345,320,311',
-'405,311,50,50,50,50,50,50,50,50,50,50,50,50,50,50,320,773,50,50,50,503',
-'774,50,773,775,50,344,503,50,50,343,50,773,50,429,50,503,50,50,50,50',
-'50,50,50,435,50,859,50,330,597,322,435,435,435,322,330,435,435,435,858',
-'435,50,50,50,50,401,50,878,400,335,435,25,635,803,721,803,335,438,25',
-'435,435,721,435,435,435,435,435,344,344,344,721,343,343,343,15,15,859',
-'401,439,597,400,401,401,859,400,400,597,13,859,858,420,597,859,310,13',
-'597,858,339,310,435,42,858,635,13,339,858,435,42,636,635,859,435,435',
-'597,635,636,42,441,635,442,636,782,420,858,636,271,420,420,420,420,37',
-'37,271,448,435,645,635,645,645,645,645,271,337,553,553,553,450,553,435',
-'337,435,553,553,435,870,870,553,451,553,553,553,553,553,553,553,280',
-'280,758,758,553,553,553,553,553,553,553,294,294,455,336,419,645,645',
-'645,645,553,336,783,553,553,553,553,553,553,553,553,553,553,460,553',
-'553,784,553,553,553,415,415,415,415,415,415,415,419,272,415,415,419',
-'419,419,419,272,415,415,865,553,553,787,553,553,272,553,553,305,305',
-'553,892,553,415,553,415,553,415,415,415,415,415,415,415,553,415,470',
-'9,473,553,553,553,553,553,553,800,274,801,553,553,552,552,552,274,552',
-'95,108,553,552,552,108,108,274,552,487,552,552,552,552,552,552,552,493',
-'494,806,808,552,552,552,552,552,552,552,646,640,511,526,531,646,640',
-'511,809,552,810,813,552,552,552,552,552,552,552,552,552,552,814,552',
-'552,543,552,552,552,421,421,421,421,421,421,421,871,876,421,421,286',
-'547,8,825,876,421,421,286,552,552,825,552,552,876,552,552,286,41,552',
-'825,552,421,552,421,552,421,421,421,421,421,421,421,552,421,554,872',
-'561,552,552,552,552,552,552,563,314,566,552,552,60,60,60,314,60,568',
-'576,552,60,60,577,826,314,60,583,60,60,60,60,60,60,60,873,586,36,593',
-'60,60,60,60,60,60,60,522,522,60,522,522,522,596,366,599,60,601,602,60',
-'60,60,60,60,60,60,60,60,60,604,60,60,34,60,60,60,366,366,366,366,366',
-'366,366,366,366,366,366,860,366,366,770,607,366,366,860,60,608,770,60',
-'860,611,60,60,860,617,60,770,623,366,625,366,60,366,366,366,366,366',
-'366,366,60,366,626,874,629,60,60,60,60,60,60,833,324,638,60,60,643,60',
-'366,324,366,647,60,97,97,97,97,97,324,648,198,97,97,649,655,660,97,198',
-'97,97,97,97,97,97,97,663,198,665,20,97,97,97,97,97,97,97,678,764,97',
-'4,4,4,4,4,97,97,97,97,97,97,97,97,97,97,97,97,97,97,836,97,97,837,97',
-'97,97,422,422,422,422,422,422,422,422,771,422,422,598,696,202,459,771',
-'422,422,598,97,203,459,97,598,771,97,97,598,700,97,459,97,422,701,422',
-'97,422,422,422,422,422,422,422,97,422,702,1,705,97,97,97,97,97,97,709',
-'710,712,97,97,821,821,821,854,821,855,97,716,821,821,718,719,720,821',
-'856,821,821,821,821,821,821,821,732,735,12,239,821,821,821,821,821,821',
-'821,350,350,350,350,350,240,11,244,253,821,746,264,821,821,821,821,821',
-'821,821,821,821,821,200,821,821,413,266,817,821,817,817,817,817,106',
-'106,106,106,106,267,268,10,413,413,273,275,276,279,284,821,285,288,821',
-'750,292,821,821,293,413,821,413,296,413,413,413,413,817,751,413,300',
-'413,302,312,315,817,817,817,817,821,821,821,821,821,821,317,,,821,821',
-',697,697,697,821,697,,,,697,697,,,,697,,697,697,697,697,697,697,697',
-',,,,697,697,697,697,697,697,697,,,,,,,,555,,697,,,697,697,697,697,697',
-'697,697,697,697,697,,697,697,,,,697,555,555,555,555,555,555,555,555',
-'555,555,555,,555,555,,,555,555,,697,,,697,,,697,697,,,697,,,555,,555',
-',555,555,555,555,555,555,555,,555,,,,697,697,697,697,697,697,,,,697',
-'697,,,555,,697,30,30,30,30,30,30,,,,30,30,,,,30,,30,30,30,30,30,30,30',
-',,,,30,30,30,30,30,30,30,,,30,,,,,,30,30,30,30,30,30,30,30,30,30,30',
-'30,30,30,,30,30,,30,30,30,,,,,,,,,,,,,,,,,,,,30,,,30,,,30,30,,,30,,30',
-',,,30,514,,514,514,514,514,,30,,,,,30,30,30,30,30,30,,,,30,30,737,737',
-'737,737,737,737,,,,737,737,,,,737,514,737,737,737,737,737,737,737,514',
-'514,514,514,737,737,737,737,737,737,737,,,737,,,,,,737,737,737,737,737',
-'737,737,737,737,737,737,737,737,737,,737,737,,737,737,737,,,,,,,,,,',
-',,,,,,,,,737,,,737,,,737,737,,,737,,737,,,,737,753,,753,753,753,753',
-',737,,,,,737,737,737,737,737,737,,,,737,737,736,736,736,736,736,736',
-',,,736,736,,,,736,,736,736,736,736,736,736,736,753,753,753,753,736,736',
-'736,736,736,736,736,,,736,,,,,,736,736,736,736,736,736,736,736,736,736',
-'736,736,736,736,,736,736,,736,736,736,412,,,,,,,,,,,,,,,,412,412,,736',
-',,736,,,736,736,,,736,,736,412,,412,736,412,412,412,412,,,412,736,412',
-',,,736,736,736,736,736,736,,,,736,736,606,606,606,606,606,606,,,,606',
-'606,,,,606,,606,606,606,606,606,606,606,,,,,606,606,606,606,606,606',
-'606,,,606,,,,,,606,606,606,606,606,606,606,606,606,606,606,606,606,606',
-',606,606,,606,606,606,409,409,409,409,409,409,409,,,409,409,,,,,,409',
-'409,,606,,,606,,,606,606,,,606,,606,409,,409,606,409,409,409,409,409',
-'409,409,606,409,,,,606,606,606,606,606,606,,,,606,606,589,589,589,589',
-'589,589,,,,589,589,,,,589,,589,589,589,589,589,589,589,,,,,589,589,589',
-'589,589,589,589,,,589,,,,,,589,589,589,589,589,589,589,589,589,589,589',
-'589,589,589,,589,589,,589,589,589,410,,,,,,,,,,,,,,,,410,410,,589,,',
-'589,,,589,589,,,589,,589,410,,410,589,410,410,410,410,,,410,589,410',
-',,,589,589,589,589,589,589,,,,589,589,186,186,186,186,186,186,,,,186',
-'186,,,,186,,186,186,186,186,186,186,186,,,,,186,186,186,186,186,186',
-'186,,,186,,,,,,186,186,186,186,186,186,186,186,186,186,186,186,186,186',
-',186,186,,186,186,186,399,399,399,399,399,399,399,399,399,399,399,,399',
-'399,,,399,399,,186,,,186,,,186,186,,,186,,186,399,,399,186,399,399,399',
-'399,399,399,399,186,399,,,,186,186,186,186,186,186,,,,186,186,187,187',
-'187,187,187,187,,,,187,187,,,,187,,187,187,187,187,187,187,187,,,,,187',
-'187,187,187,187,187,187,,,187,,,,,,187,187,187,187,187,187,187,187,187',
-'187,187,187,187,187,,187,187,,187,187,187,398,398,398,398,398,398,398',
-'398,398,398,398,,398,398,,,398,398,,187,,,187,,,187,187,,,187,,187,398',
-',398,187,398,398,398,398,398,398,398,187,398,,,,187,187,187,187,187',
-'187,,,,187,187,588,588,588,588,588,588,,,,588,588,,,,588,,588,588,588',
-'588,588,588,588,,,,,588,588,588,588,588,588,588,,,588,,,,,,588,588,588',
-'588,588,588,588,588,588,588,588,588,588,588,,588,588,,588,588,588,414',
-'414,414,414,414,414,414,,,414,414,,,,,,414,414,,588,,,588,,,588,588',
-',,588,,588,414,,414,588,414,414,414,414,414,414,414,588,414,,,,588,588',
-'588,588,588,588,,,,588,588,559,559,559,559,559,559,,,,559,559,,,,559',
-',559,559,559,559,559,559,559,,,,,559,559,559,559,559,559,559,,,559,',
-',,,,559,559,559,559,559,559,559,559,559,559,559,559,559,559,,559,559',
-',559,559,559,418,418,418,418,418,418,418,,,418,418,,,,,,418,418,,559',
-',,559,,,559,559,,,559,,559,418,,418,559,418,418,418,418,418,418,418',
-'559,418,,,,559,559,559,559,559,559,,,,559,559,724,724,724,724,724,724',
-',,,724,724,,,,724,,724,724,724,724,724,724,724,,,,,724,724,724,724,724',
-'724,724,,,724,,,,,,724,724,724,724,724,724,724,724,724,724,724,724,724',
-'724,,724,724,,724,724,724,411,,,,,,,,,,,,,,,,411,411,,724,,,724,,,724',
-'724,,,724,,724,411,,411,724,411,411,411,411,,,411,724,411,,,,724,724',
-'724,724,724,724,,,,724,724,706,706,706,706,706,706,,,,706,706,,,,706',
-',706,706,706,706,706,706,706,,,,,706,706,706,706,706,706,706,,,706,',
-',,,,706,706,706,706,706,706,706,706,706,706,706,706,706,706,,706,706',
-',706,706,706,416,416,416,416,416,416,416,,,416,416,,,,,,416,416,,706',
-',,706,,,706,706,,,706,,706,416,,416,706,416,416,416,416,416,416,416',
-'706,416,,,,706,706,706,706,706,706,,,,706,706,0,0,0,0,0,0,,,,0,0,,,',
-'0,,0,0,0,0,0,0,0,,,,,0,0,0,0,0,0,0,,,0,,,,,,0,0,0,0,0,0,0,0,0,0,0,0',
-'0,0,,0,0,,0,0,0,417,417,417,417,417,417,417,,,417,417,,,,,,417,417,',
-'0,,,0,,,0,0,,,0,,0,417,,417,0,417,417,417,417,417,417,417,0,417,,,,0',
-'0,0,0,0,0,,,,0,0,852,852,852,852,852,852,,,,852,852,,,,852,,852,852',
-'852,852,852,852,852,,,,,852,852,852,852,852,852,852,,,852,,,,,,852,852',
-'852,852,852,852,852,852,852,852,852,852,852,852,,852,852,,852,852,852',
-'408,,,,,,,,,,,,,,,,408,408,,852,,,852,,,852,852,,,852,,852,408,,,852',
-'408,408,408,408,,,,852,,,,,852,852,852,852,852,852,,,,852,852,270,270',
-'270,270,270,270,,,,270,270,,,,270,,270,270,270,270,270,270,270,,,,,270',
-'270,270,270,270,270,270,,,270,,,,,,270,270,270,270,270,270,270,270,270',
-'270,270,270,270,270,,270,270,,270,270,270,407,,,,,,,,,,,,,,,,407,407',
-',270,,,270,,,270,270,,,270,,270,407,,407,270,407,407,407,407,,,,270',
-',,,,270,270,270,270,270,270,,,,270,270,265,265,265,265,265,265,,,,265',
-'265,,,,265,,265,265,265,265,265,265,265,,,,,265,265,265,265,265,265',
-'265,,,265,,,,,,265,265,265,265,265,265,265,265,265,265,265,265,265,265',
-',265,265,,265,265,265,406,,,,,,,,,,,,,,,,406,406,,265,,,265,,,265,265',
-',,265,,265,406,,406,265,406,406,406,406,,,,265,,,,,265,265,265,265,265',
-'265,,,,265,265,204,204,204,204,204,204,,,,204,204,,,,204,,204,204,204',
-'204,204,204,204,,,,,204,204,204,204,204,204,204,,,204,,,,,,204,204,204',
-'204,204,204,204,204,204,204,204,204,204,204,,204,204,,204,204,204,,',
-',,,,,,,,,,,,,,,,,204,,,204,,,204,204,,,204,,204,,,,204,,,,,,,,204,,',
-',,204,204,204,204,204,204,,,,204,204,51,51,51,51,51,51,,,,51,51,,,,51',
-',51,51,51,51,51,51,51,,,,,51,51,51,51,51,51,51,,,51,,,,,,51,51,51,51',
-'51,51,51,51,51,51,51,51,51,51,,51,51,,51,51,51,,,,,,,,,,,,,,,,,,,,51',
-',,51,,,51,51,,,51,,51,,,,51,,,,,,,,51,,,,,51,51,51,51,51,51,,,,51,51',
-'845,845,845,845,845,845,,,,845,845,,,,845,,845,845,845,845,845,845,845',
-',,,,845,845,845,845,845,845,845,,,845,,,,,,845,845,845,845,845,845,845',
-'845,845,845,845,845,845,845,,845,845,,845,845,845,,,,,,,,,,,,,,,,,,',
-',845,,,845,,,845,845,,,845,,845,,,,845,,,,,,,,845,,,,,845,845,845,845',
-'845,845,,,,845,845,671,671,671,671,671,671,,,,671,671,,,,671,,671,671',
-'671,671,671,671,671,,,,,671,671,671,671,671,671,671,,,671,,,,,,671,671',
-'671,671,671,671,671,671,671,671,671,671,671,671,,671,671,,671,671,671',
-',,,,,,,,,,,,,,,,,,,671,,,671,,,671,671,,,671,,671,,,,671,,,,,,,,671',
-',,,,671,671,671,671,671,671,,,,671,671,513,513,513,513,513,513,,,,513',
-'513,,,,513,,513,513,513,513,513,513,513,,,,,513,513,513,513,513,513',
-'513,,,513,,,,,,513,513,513,513,513,513,513,513,513,513,513,513,513,513',
-',513,513,,513,513,513,,,,,,,,,,,,,,,,,,,,513,,,513,,,513,513,,,513,',
-'513,,,,513,,,,,,,,513,,,,,513,513,513,513,513,513,,,,513,513,838,838',
-'838,838,838,838,,,,838,838,,,,838,,838,838,838,838,838,838,838,,,,,838',
-'838,838,838,838,838,838,,,838,,,,,,838,838,838,838,838,838,838,838,838',
-'838,838,838,838,838,,838,838,,838,838,838,,,,,,,,,,,,,,,,,,,,838,,,838',
-',,838,838,,,838,,838,,,,838,,,,,,,,838,,,,,838,838,838,838,838,838,',
-',,838,838,794,794,794,794,794,794,,,,794,794,,,,794,,794,794,794,794',
-'794,794,794,,,,,794,794,794,794,794,794,794,,,794,,,,,,794,794,794,794',
-'794,794,794,794,794,794,794,794,794,794,,794,794,,794,794,794,,,,,,',
-',,,,,,,,,,,,,794,,,794,,,794,794,,,794,,794,,,,794,,,,,,,,794,,,,,794',
-'794,794,794,794,794,,,,794,794,644,644,644,644,644,644,,,,644,644,,',
-',644,,644,644,644,644,644,644,644,,,,,644,644,644,644,644,644,644,,',
-'644,,,,,,644,644,644,644,644,644,644,644,644,644,644,644,644,644,,644',
-'644,,644,644,644,,,,,,,,,,,,,,,,,,,,644,,,644,,,644,644,,,644,,644,',
-',,644,,,,,,,,644,,,,,644,644,644,644,644,644,,,,644,644,639,639,639',
-'639,639,639,,,,639,639,,,,639,,639,639,639,639,639,639,639,,,,,639,639',
-'639,639,639,639,639,,,639,,,,,,639,639,639,639,639,639,639,639,639,639',
-'639,639,639,639,,639,639,,639,639,639,,,,,,,,,,,,,,,,,,,,639,,,639,',
-',639,639,,,639,,639,,,,639,,,,,,,,639,,,,,639,639,639,639,639,639,,',
-',639,639,495,495,495,495,495,495,,,,495,495,,,,495,,495,495,495,495',
+'381,512,512,518,518,306,755,381,381,381,326,440,711,381,381,313,381',
+'199,440,711,307,70,347,316,424,381,3,627,500,70,1,3,201,603,603,381',
+'381,630,381,381,381,381,381,727,798,446,311,631,311,632,743,394,755',
+'755,755,755,8,310,424,447,440,711,310,199,381,381,381,381,381,381,381',
+'381,381,381,381,381,381,381,201,446,381,381,381,55,381,347,603,594,381',
+'591,512,381,518,447,491,512,381,394,381,633,381,381,381,381,381,381',
+'381,383,381,381,381,9,632,326,383,383,383,306,313,306,383,383,306,383',
+'381,381,316,381,591,381,381,500,307,326,307,492,595,307,326,627,630',
+'627,383,383,627,383,383,383,383,383,631,594,632,743,582,727,798,727',
+'798,744,727,798,633,26,322,15,15,55,322,594,550,383,383,383,383,383',
+'383,383,383,383,383,383,383,383,383,574,277,383,383,383,594,383,491',
+'594,491,383,582,491,383,551,595,10,633,383,528,383,343,383,383,383,383',
+'383,383,383,50,383,550,383,595,574,11,50,50,50,511,26,50,50,50,511,50',
+'383,383,492,383,492,383,383,492,595,50,50,595,297,12,551,297,26,277',
+'50,50,693,50,50,50,50,50,744,14,744,298,20,744,298,344,528,528,343,343',
+'343,277,301,108,34,301,528,108,108,50,50,50,50,50,50,50,50,50,50,50',
+'50,50,50,345,13,50,50,50,693,36,50,13,14,50,346,14,50,50,41,50,13,50',
+'95,50,419,50,50,50,50,50,50,50,432,50,184,50,344,344,344,432,432,432',
+'848,200,432,432,432,348,432,50,50,50,50,202,50,320,419,803,432,803,419',
+'419,419,419,345,345,345,432,432,203,432,432,432,432,432,346,346,346',
+'25,303,239,321,303,597,635,25,42,435,848,848,848,848,240,42,435,435',
+'435,330,857,435,435,435,42,435,330,320,244,432,348,348,348,35,320,435',
+'432,37,37,320,253,432,432,320,435,435,264,435,435,435,435,435,283,321',
+'266,597,635,376,858,377,321,320,597,635,432,321,540,597,635,321,857',
+'597,635,267,400,268,35,857,432,35,432,401,857,432,435,198,857,321,640',
+'597,635,435,198,640,646,283,435,435,283,646,376,198,377,376,857,377',
+'400,271,858,540,400,400,540,401,271,858,273,401,401,435,858,280,280',
+'271,858,294,294,331,552,552,552,275,552,435,331,435,552,552,435,276',
+'859,552,858,552,552,552,552,552,552,552,305,305,615,615,552,552,552',
+'552,552,552,552,332,420,279,333,334,758,758,332,284,552,333,334,552',
+'552,552,552,552,552,552,552,552,552,285,552,552,335,552,552,552,859',
+'870,870,335,420,288,336,859,420,420,420,420,859,336,272,292,859,337',
+'293,552,552,272,552,552,337,552,552,296,300,552,272,552,302,552,859',
+'552,312,339,274,286,314,315,317,552,339,274,286,314,552,552,552,552',
+'552,552,274,286,314,552,552,553,553,553,362,553,363,368,552,553,553',
+'371,375,382,553,402,553,553,553,553,553,553,553,403,404,405,429,553',
+'553,553,553,553,553,553,522,522,438,522,522,522,439,441,442,553,448',
+'450,553,553,553,553,553,553,553,553,553,553,451,553,553,455,553,553',
+'553,398,398,398,398,398,398,398,398,398,398,398,324,398,398,459,460',
+'398,398,324,553,553,459,553,553,470,553,553,324,473,553,459,553,398',
+'553,398,553,398,398,398,398,398,398,398,553,398,487,493,494,553,553',
+'553,553,553,553,526,503,531,553,553,60,60,60,503,60,543,547,553,60,60',
+'554,561,503,60,563,60,60,60,60,60,60,60,566,568,576,577,60,60,60,60',
+'60,60,60,583,586,60,593,596,599,601,366,602,60,604,607,60,60,60,60,60',
+'60,60,60,60,60,608,60,60,611,60,60,60,366,366,366,366,366,366,366,366',
+'366,366,366,598,366,366,721,617,366,366,598,60,623,721,60,598,625,60',
+'60,598,626,60,721,629,366,638,366,60,366,366,366,366,366,366,366,60',
+'366,643,647,648,60,60,60,60,60,60,649,655,660,60,60,663,60,366,665,366',
+'636,60,97,97,97,97,97,636,678,696,97,97,636,700,701,97,636,97,97,97',
+'97,97,97,97,702,705,709,710,97,97,97,97,97,97,97,712,716,97,4,4,4,4',
+'4,97,97,97,97,97,97,97,97,97,97,97,97,97,97,718,97,97,719,97,97,97,399',
+'399,399,399,399,399,399,399,399,399,399,770,399,399,771,720,399,399',
+'770,97,732,771,97,735,746,97,97,770,750,97,771,97,399,751,399,97,399',
+'399,399,399,399,399,399,97,399,764,772,774,97,97,97,97,97,97,775,773',
+'782,97,97,697,697,697,773,697,783,97,825,697,697,784,787,773,697,825',
+'697,697,697,697,697,697,697,800,825,801,806,697,697,697,697,697,697',
+'697,106,106,106,106,106,808,809,810,813,697,814,826,697,697,697,697',
+'697,697,697,697,697,697,833,697,697,410,836,514,697,514,514,514,514',
+'860,837,854,876,855,856,865,860,410,410,876,871,860,872,873,697,860',
+'874,697,876,878,697,697,881,410,697,410,892,410,410,410,410,514,,410',
+',410,,,,514,514,514,514,697,697,697,697,697,697,,,,697,697,,821,821',
+'821,697,821,,,,821,821,,,,821,,821,821,821,821,821,821,821,,,,,821,821',
+'821,821,821,821,821,350,350,350,350,350,,,555,,821,,,821,821,821,821',
+'821,821,821,821,821,821,,821,821,,,,821,555,555,555,555,555,555,555',
+'555,555,555,555,,555,555,,,555,555,,821,,,821,,,821,821,,,821,,,555',
+',555,,555,555,555,555,555,555,555,,555,,,,821,821,821,821,821,821,,',
+',821,821,,,555,,821,0,0,0,0,0,0,,,,0,0,,,,0,,0,0,0,0,0,0,0,,,,,0,0,0',
+'0,0,0,0,,,0,,,,,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,,0,0,,0,0,0,,,,,,,,,,,',
+',,,,,,,,0,,,0,,,0,0,,,0,,0,,,,0,645,,645,645,645,645,,0,,,,,0,0,0,0',
+'0,0,,,,0,0,30,30,30,30,30,30,,,,30,30,,,,30,,30,30,30,30,30,30,30,645',
+'645,645,645,30,30,30,30,30,30,30,,,30,,,,,,30,30,30,30,30,30,30,30,30',
+'30,30,30,30,30,,30,30,,30,30,30,,,,,,,,,,,,,,,,,,,,30,,,30,,,30,30,',
+',30,,30,,,,30,753,,753,753,753,753,,30,,,,,30,30,30,30,30,30,,,,30,30',
+'51,51,51,51,51,51,,,,51,51,,,,51,,51,51,51,51,51,51,51,753,753,753,753',
+'51,51,51,51,51,51,51,,,51,,,,,,51,51,51,51,51,51,51,51,51,51,51,51,51',
+'51,,51,51,,51,51,51,,,,,,,,,,,,,,,,,,,,51,,,51,,,51,51,,,51,,51,,,,51',
+'817,,817,817,817,817,,51,,,,,51,51,51,51,51,51,,,,51,51,186,186,186',
+'186,186,186,,,,186,186,,,,186,817,186,186,186,186,186,186,186,817,817',
+'817,817,186,186,186,186,186,186,186,,,186,,,,,,186,186,186,186,186,186',
+'186,186,186,186,186,186,186,186,,186,186,,186,186,186,409,409,409,409',
+'409,409,409,,,409,409,,,,,,409,409,,186,,,186,,,186,186,,,186,,186,409',
+',409,186,409,409,409,409,409,409,409,186,409,,,,186,186,186,186,186',
+'186,,,,186,186,187,187,187,187,187,187,,,,187,187,,,,187,,187,187,187',
+'187,187,187,187,,,,,187,187,187,187,187,187,187,,,187,,,,,,187,187,187',
+'187,187,187,187,187,187,187,187,187,187,187,,187,187,,187,187,187,411',
+',,,,,,,,,,,,,,,411,411,,187,,,187,,,187,187,,,187,,187,411,,411,187',
+'411,411,411,411,,,411,187,411,,,,187,187,187,187,187,187,,,,187,187',
+'204,204,204,204,204,204,,,,204,204,,,,204,,204,204,204,204,204,204,204',
+',,,,204,204,204,204,204,204,204,,,204,,,,,,204,204,204,204,204,204,204',
+'204,204,204,204,204,204,204,,204,204,,204,204,204,412,,,,,,,,,,,,,,',
+',412,412,,204,,,204,,,204,204,,,204,,204,412,,412,204,412,412,412,412',
+',,412,204,412,,,,204,204,204,204,204,204,,,,204,204,265,265,265,265',
+'265,265,,,,265,265,,,,265,,265,265,265,265,265,265,265,,,,,265,265,265',
+'265,265,265,265,,,265,,,,,,265,265,265,265,265,265,265,265,265,265,265',
+'265,265,265,,265,265,,265,265,265,413,,,,,,,,,,,,,,,,413,413,,265,,',
+'265,,,265,265,,,265,,265,413,,413,265,413,413,413,413,,,413,265,413',
+',,,265,265,265,265,265,265,,,,265,265,270,270,270,270,270,270,,,,270',
+'270,,,,270,,270,270,270,270,270,270,270,,,,,270,270,270,270,270,270',
+'270,,,270,,,,,,270,270,270,270,270,270,270,270,270,270,270,270,270,270',
+',270,270,,270,270,270,414,414,414,414,414,414,414,,,414,414,,,,,,414',
+'414,,270,,,270,,,270,270,,,270,,270,414,,414,270,414,414,414,414,414',
+'414,414,270,414,,,,270,270,270,270,270,270,,,,270,270,486,486,486,486',
+'486,486,,,,486,486,,,,486,,486,486,486,486,486,486,486,,,,,486,486,486',
+'486,486,486,486,,,486,,,,,,486,486,486,486,486,486,486,486,486,486,486',
+'486,486,486,,486,486,,486,486,486,415,415,415,415,415,415,415,,,415',
+'415,,,,,,415,415,,486,,,486,,,486,486,,,486,,486,415,,415,486,415,415',
+'415,415,415,415,415,486,415,,,,486,486,486,486,486,486,,,,486,486,490',
+'490,490,490,490,490,,,,490,490,,,,490,,490,490,490,490,490,490,490,',
+',,,490,490,490,490,490,490,490,,,490,,,,,,490,490,490,490,490,490,490',
+'490,490,490,490,490,490,490,,490,490,,490,490,490,416,416,416,416,416',
+'416,416,,,416,416,,,,,,416,416,,490,,,490,,,490,490,,,490,,490,416,',
+'416,490,416,416,416,416,416,416,416,490,416,,,,490,490,490,490,490,490',
+',,,490,490,495,495,495,495,495,495,,,,495,495,,,,495,,495,495,495,495',
'495,495,495,,,,,495,495,495,495,495,495,495,,,495,,,,,,495,495,495,495',
-'495,495,495,495,495,495,495,495,495,495,,495,495,,495,495,495,,,,,,',
-',,,,,,,,,,,,,495,,,495,,,495,495,,,495,,495,,,,495,,,,,,,,495,,,,,495',
-'495,495,495,495,495,,,,495,495,490,490,490,490,490,490,,,,490,490,,',
-',490,,490,490,490,490,490,490,490,,,,,490,490,490,490,490,490,490,,',
-'490,,,,,,490,490,490,490,490,490,490,490,490,490,490,490,490,490,,490',
-'490,,490,490,490,,,,,,,,,,,,,,,,,,,,490,,,490,,,490,490,,,490,,490,',
-',,490,,,,,,,,490,,,,,490,490,490,490,490,490,,,,490,490,748,748,748',
-'748,748,748,,,,748,748,,,,748,,748,748,748,748,748,748,748,,,,,748,748',
-'748,748,748,748,748,,,748,,,,,,748,748,748,748,748,748,748,748,748,748',
-'748,748,748,748,,748,748,,748,748,748,,,,,,,,,,,,,,,,,,,,748,,,748,',
-',748,748,,,748,,748,,,,748,,,,,,,,748,,,,,748,748,748,748,748,748,,',
-',748,748,741,741,741,741,741,741,,,,741,741,,,,741,,741,741,741,741',
-'741,741,741,,,,,741,741,741,741,741,741,741,,,741,,,,,,741,741,741,741',
-'741,741,741,741,741,741,741,741,741,741,,741,741,,741,741,741,,,,,,',
-',,,,,,,,,,,,,741,,,741,,,741,741,,,741,,741,,,,741,,,,,,,,741,,,,,741',
-'741,741,741,741,741,,,,741,741,486,486,486,486,486,486,,,,486,486,,',
-',486,,486,486,486,486,486,486,486,,,,,486,486,486,486,486,486,486,,',
-'486,,,,,,486,486,486,486,486,486,486,486,486,486,486,486,486,486,,486',
-'486,,486,486,486,,,,,,,,,,,,,,,,,,,,486,,,486,,,486,486,,,486,,486,',
-',,486,,,,,,,,486,,,,,486,486,486,486,486,486,,,,486,486,369,369,369',
-',369,,,,369,369,,,,369,,369,369,369,369,369,369,369,,,,,369,369,369',
-'369,369,369,369,,,,,,,,,,369,,,369,369,369,369,369,369,369,369,369,369',
-',369,369,,369,369,369,,,,,,,,,,,,,,,,,,,,369,,,369,,,369,369,,,369,',
-',,,,369,,,,,,,,369,,,,,369,369,369,369,369,369,,,,369,369,5,5,5,5,5',
-',,,5,5,,,,5,,5,5,5,5,5,5,5,,,,,5,5,5,5,5,5,5,,,5,,,,,,5,5,5,5,5,5,5',
-'5,5,5,5,5,5,5,,5,5,,5,5,5,,,,,,,,,,,,,,,,,,,,5,,,5,,,5,5,,,5,,5,,,,5',
-',,,,,,,5,,,,,5,5,5,5,5,5,,,,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6',
-'6,6,6,6,6,6,,,6,6,6,6,6,6,6,6,6,6,,,,,,6,6,6,6,6,6,6,6,6,,6,,,,,,,,6',
-'6,,6,6,6,6,,6,6,,,6,,,,,6,6,6,6,,,,,,,,,,,,,,6,6,,6,6,6,6,6,6,6,6,6',
-',6,,,6,6,,,,,,,,,,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7',
-',,7,7,7,7,7,7,7,7,7,7,,,,,,7,7,7,7,7,7,7,7,,,7,,,,,,,,7,7,,7,7,7,7,',
-'7,7,,,7,,,,,7,7,7,7,,,,,,,,,,,,,,7,7,,7,7,7,7,7,7,7,7,7,,7,,,7,7,,,17',
-'17,17,,17,,,7,17,17,,,,17,,17,17,17,17,17,17,17,,,,,17,17,17,17,17,17',
-'17,,,17,,,,,,,17,,,17,17,17,17,17,17,17,17,17,17,,17,17,,17,17,17,,',
-',,,,,,,,,,,,,,,,,17,,,17,,,17,17,,,17,,,,,,17,,,,,,,,17,,,,,17,17,17',
-'17,17,17,,,,17,17,18,18,18,,18,,,,18,18,,,,18,,18,18,18,18,18,18,18',
-',,,,18,18,18,18,18,18,18,,,,,,,,,,18,,,18,18,18,18,18,18,18,18,18,18',
-',18,18,,18,18,18,,,,,,,,,,,,,,,,,,,,18,,,18,,,18,18,,,18,,,,,,18,,,',
-',,,,18,,,,,18,18,18,18,18,18,,,,18,18,22,22,22,,22,,,,22,22,,,,22,,22',
-'22,22,22,22,22,22,,,,,22,22,22,22,22,22,22,,,,,,,,,,22,,,22,22,22,22',
-'22,22,22,22,22,22,,22,22,,22,22,22,,,,,,,,,,,,,,,,,,,,22,,,22,,,22,22',
-',,22,,22,,22,,22,,,,,,,,22,,,,,22,22,22,22,22,22,,,,22,22,23,23,23,',
-'23,,,,23,23,,,,23,,23,23,23,23,23,23,23,,,,,23,23,23,23,23,23,23,,,',
-',,,,,,23,,,23,23,23,23,23,23,23,23,23,23,,23,23,,23,23,23,,,,,,,,,,',
-',,,,,,,,,23,,,23,,,23,23,,,23,,23,,23,,23,,,,,,,,23,,,,,23,23,23,23',
-'23,23,,,,23,23,24,24,24,,24,,,,24,24,,,,24,,24,24,24,24,24,24,24,,,',
-',24,24,24,24,24,24,24,,,,,,,,,,24,,,24,24,24,24,24,24,24,24,24,24,,24',
-'24,,24,24,24,,,,,,,,,,,,,,,,,,,,24,,,24,,,24,24,,,24,,24,,24,,24,,,',
-',,,,24,,,,,24,24,24,24,24,24,,,,24,24,27,27,27,,27,,,,27,27,,,,27,,27',
-'27,27,27,27,27,27,,,,,27,27,27,27,27,27,27,,,,,,,,,,27,,,27,27,27,27',
-'27,27,27,27,27,27,,27,27,,27,27,27,,,,,,,,,,,,,,,,,,,,27,,,27,27,,27',
-'27,,,27,,27,,27,,27,,,,,,,,27,,,,,27,27,27,27,27,27,,,,27,27,28,28,28',
-',28,,,,28,28,,,,28,,28,28,28,28,28,28,28,,,,,28,28,28,28,28,28,28,,',
-',,,,,,,28,,,28,28,28,28,28,28,28,28,28,28,,28,28,,28,28,28,,,,,,,,,',
-',,,,,,,,,,28,,,28,28,,28,28,,,28,,28,,28,,28,,,,,,,,28,,,,,28,28,28',
-'28,28,28,,,,28,28,31,31,31,,31,,,,31,31,,,,31,,31,31,31,31,31,31,31',
-',,,,31,31,31,31,31,31,31,,,,,,,,,,31,,,31,31,31,31,31,31,31,31,31,31',
-',31,31,,,,31,,828,828,828,828,828,828,828,828,828,828,828,,828,828,',
-',828,828,31,,,31,,,31,31,,,31,,31,,828,,828,,828,828,828,828,828,828',
-'828,,828,,,31,31,31,31,31,31,,,,31,31,32,32,32,828,32,828,,,32,32,,',
-',32,,32,32,32,32,32,32,32,,,,,32,32,32,32,32,32,32,,,,,,,,,,32,,,32',
-'32,32,32,32,32,32,32,32,32,,32,32,,,,32,,468,468,468,468,468,468,468',
-'468,468,468,468,,468,468,,,468,468,32,,,32,,,32,32,,,32,,,,468,,468',
-',468,468,468,468,468,468,468,,468,,,32,32,32,32,32,32,,,,32,32,38,38',
-'38,468,38,,,,38,38,,,,38,,38,38,38,38,38,38,38,,,,,38,38,38,38,38,38',
-'38,,,,,,,,,,38,,,38,38,38,38,38,38,38,38,38,38,,38,38,,38,38,38,,,,',
-',,,,,,,,,,,,,,,38,,,38,,,38,38,,,38,,,,,,38,,,,,,,,38,,,,,38,38,38,38',
-'38,38,,,,38,38,39,39,39,,39,,,,39,39,,,,39,,39,39,39,39,39,39,39,,,',
-',39,39,39,39,39,39,39,,,,,,,,,,39,,,39,39,39,39,39,39,39,39,39,39,,39',
-'39,,39,39,39,,,,,,,,,,,,,,,,,,,,39,,,39,,,39,39,,,39,,,,,,39,,,,,,,',
-'39,,,,,39,39,39,39,39,39,,,,39,39,40,40,40,,40,,,,40,40,,,,40,,40,40',
-'40,40,40,40,40,,,,,40,40,40,40,40,40,40,,,,,,,,,,40,,,40,40,40,40,40',
-'40,40,40,40,40,,40,40,,40,40,40,,,,,,,,,,,,,,,,,,,,40,,,40,,,40,40,',
-',40,,,,,,40,,,,,,,,40,,,,,40,40,40,40,40,40,,,,40,40,52,52,52,,52,,',
-',52,52,,,,52,,52,52,52,52,52,52,52,,,,,52,52,52,52,52,52,52,,,52,,,',
-',,,52,,,52,52,52,52,52,52,52,52,52,52,,52,52,,52,52,52,,,,,,,,,,,,,',
-',,,,,,52,,,52,,,52,52,,,52,,,,,,52,,,,,,,,52,,,,,52,52,52,52,52,52,',
-',,52,52,53,53,53,,53,,,,53,53,,,,53,,53,53,53,53,53,53,53,,,,,53,53',
-'53,53,53,53,53,,,,,,,,,,53,,,53,53,53,53,53,53,53,53,53,53,,53,53,,53',
-'53,53,,,,,,,,,,,,,,,,,,,,53,,,53,,,53,53,,,53,,53,,,,53,,,,,,,,53,,',
-',,53,53,53,53,53,53,,,,53,53,54,54,54,,54,,,,54,54,,,,54,,54,54,54,54',
-'54,54,54,,,,,54,54,54,54,54,54,54,,,,,,,,,,54,,,54,54,54,54,54,54,54',
-'54,54,54,,54,54,,54,54,54,,,,,,,,,,,,,,,,,,,,54,,,54,,,54,54,,,54,,',
-',,,54,,,,,,,,54,,,,,54,54,54,54,54,54,,,,54,54,56,56,56,,56,,,,56,56',
-',,,56,,56,56,56,56,56,56,56,,,,,56,56,56,56,56,56,56,,,56,,,,,,,56,',
-',56,56,56,56,56,56,56,56,56,56,,56,56,,56,56,56,,,,,,,,,,,,,,,,,,,,56',
-',,56,,,56,56,,,56,,,,,,56,,,,,,,,56,,,,,56,56,56,56,56,56,,,,56,56,57',
-'57,57,,57,,,,57,57,,,,57,,57,57,57,57,57,57,57,,,,,57,57,57,57,57,57',
-'57,,,57,,,,,,,57,,,57,57,57,57,57,57,57,57,57,57,,57,57,,57,57,57,,',
-',,,,,,,,,,,,,,,,,57,,,57,,,57,57,,,57,,,,,,57,,,,,,,,57,,,,,57,57,57',
-'57,57,57,,,,57,57,61,61,61,,61,,,,61,61,,,,61,,61,61,61,61,61,61,61',
-',,,,61,61,61,61,61,61,61,,,,,,,,,,61,,,61,61,61,61,61,61,61,61,61,61',
-',61,61,,,,61,,689,689,689,689,689,689,689,689,689,689,689,,689,689,',
-',689,689,61,,,61,,,61,61,,,61,,61,,689,,689,,689,689,689,689,689,689',
-'689,,689,,,61,61,61,61,61,61,,,,61,61,62,62,62,689,62,,,,62,62,,,,62',
-',62,62,62,62,62,62,62,,,,,62,62,62,62,62,62,62,,,,,,,,,,62,,,62,62,62',
-'62,62,62,62,62,62,62,,62,62,,,,62,,684,684,684,684,684,684,684,684,684',
-'684,684,,684,684,,62,684,684,62,,,62,,,62,62,,,62,,,,684,,684,,684,684',
-'684,684,684,684,684,,684,,,62,62,62,62,62,62,,,,62,62,63,63,63,684,63',
-',,,63,63,,,,63,,63,63,63,63,63,63,63,,,,,63,63,63,63,63,63,63,,,,,,',
-',,,63,,,63,63,63,63,63,63,63,63,63,63,,63,63,,,,63,,374,374,374,374',
-'374,374,374,374,374,374,374,,374,374,,,374,374,63,,,63,,,63,63,,,63',
-',,,374,,374,,374,374,374,374,374,374,374,,374,,,63,63,63,63,63,63,,',
-',63,63,82,82,82,374,82,,,,82,82,,,,82,,82,82,82,82,82,82,82,,82,,,82',
-'82,82,82,82,82,82,,,,,,,,,,82,,,82,82,82,82,82,82,82,82,82,82,,82,82',
-',82,82,82,,,,,,,,,,,,,,,,,,,,82,,,82,82,,82,82,,,82,,82,,82,,82,,,,',
-',,,82,,82,,,82,82,82,82,82,82,,,,82,82,86,86,86,,86,,,,86,86,,,,86,',
-'86,86,86,86,86,86,86,,86,,,86,86,86,86,86,86,86,,,,,,,,,,86,,,86,86',
-'86,86,86,86,86,86,86,86,,86,86,,86,86,86,,,,,,,,,,,,,,,,,,,,86,,,86',
-'86,,86,86,,,86,,86,,86,,86,,,,,,,,86,,86,,,86,86,86,86,86,86,,,,86,86',
-'101,101,101,,101,,,,101,101,,,,101,,101,101,101,101,101,101,101,,,,',
-'101,101,101,101,101,101,101,,,101,,,,,,,101,,,101,101,101,101,101,101',
-'101,101,101,101,,101,101,,101,101,101,,,,,,,,,,,,,,,,,,,,101,,,101,',
-',101,101,,,101,,,,,,101,,,,,,,,101,,,,,101,101,101,101,101,101,,,,101',
-'101,102,102,102,,102,,,,102,102,,,,102,,102,102,102,102,102,102,102',
-',,,,102,102,102,102,102,102,102,,,102,,,,,,,102,,,102,102,102,102,102',
-'102,102,102,102,102,,102,102,,102,102,102,,,,,,,,,,,,,,,,,,,,102,,,102',
-',,102,102,,,102,,,,,,102,,,,,,,,102,,,,,102,102,102,102,102,102,,,,102',
-'102,103,103,103,,103,,,,103,103,,,,103,,103,103,103,103,103,103,103',
-',,,,103,103,103,103,103,103,103,,,103,,,,,,,103,,,103,103,103,103,103',
-'103,103,103,103,103,,103,103,,103,103,103,,,,,,,,,,,,,,,,,,,,103,,,103',
-',,103,103,,,103,,,,,,103,,,,,,,,103,,,,,103,103,103,103,103,103,,,,103',
-'103,104,104,104,,104,,,,104,104,,,,104,,104,104,104,104,104,104,104',
-',,,,104,104,104,104,104,104,104,,,104,,,,,,,104,,,104,104,104,104,104',
-'104,104,104,104,104,,104,104,,104,104,104,,,,,,,,,,,,,,,,,,,,104,,,104',
-',,104,104,,,104,,,,,,104,,,,,,,,104,,,,,104,104,104,104,104,104,,,,104',
-'104,105,105,105,105,105,,,,105,105,,,,105,,105,105,105,105,105,105,105',
-',,,,105,105,105,105,105,105,105,,,105,,,,,,105,105,105,105,105,105,105',
-'105,105,105,105,105,105,105,,105,105,,105,105,105,,,,,,,,,,,,,,,,,,',
-',105,,,105,,,105,105,,,105,,105,,,,105,,,,,,,,105,,,,,105,105,105,105',
-'105,105,,,,105,105,188,188,188,,188,,,,188,188,,,,188,,188,188,188,188',
-'188,188,188,,,,,188,188,188,188,188,188,188,,,,,,,,,,188,,,188,188,188',
-'188,188,188,188,188,188,188,,188,188,,188,188,188,,,,,,,,,,,,,,,,,,',
-',188,,,188,,,188,188,,,188,,188,,,,188,,,,,,,,188,,,,,188,188,188,188',
-'188,188,,,,188,188,189,189,189,,189,,,,189,189,,,,189,,189,189,189,189',
-'189,189,189,,,,,189,189,189,189,189,189,189,,,,,,,,,,189,,,189,189,189',
-'189,189,189,189,189,189,189,,189,189,,189,189,189,,,,,,,,,,,,,,,,,,',
-',189,,,189,,,189,189,,,189,,189,,,,189,,,,,,,,189,,,,,189,189,189,189',
-'189,189,,,,189,189,190,190,190,,190,,,,190,190,,,,190,,190,190,190,190',
-'190,190,190,,,,,190,190,190,190,190,190,190,,,,,,,,,,190,,,190,190,190',
-'190,190,190,190,190,190,190,,190,190,,190,190,190,,,,,,,,,,,,,,,,,,',
-',190,,,190,,,190,190,,,190,,,,,,190,,,,,,,,190,,,,,190,190,190,190,190',
-'190,,,,190,190,191,191,191,,191,,,,191,191,,,,191,,191,191,191,191,191',
-'191,191,,,,,191,191,191,191,191,191,191,,,,,,,,,,191,,,191,191,191,191',
-'191,191,191,191,191,191,,191,191,,191,191,191,,,,,,,,,,,,,,,,,,,,191',
-',,191,,,191,191,,,191,,191,,,,191,,,,,,,,191,,,,,191,191,191,191,191',
-'191,,,,191,191,194,194,194,,194,,,,194,194,,,,194,,194,194,194,194,194',
-'194,194,,,,,194,194,194,194,194,194,194,,,,,,,,,,194,,,194,194,194,194',
-'194,194,194,194,194,194,,194,194,,194,194,194,,,,,,,,,,,,,,,,,,,,194',
-',,194,,,194,194,,,194,,,,,,194,,,,,,,,194,,,,,194,194,194,194,194,194',
-',,,194,194,195,195,195,,195,,,,195,195,,,,195,,195,195,195,195,195,195',
-'195,,,,,195,195,195,195,195,195,195,,,195,,,,,,,195,,,195,195,195,195',
-'195,195,195,195,195,195,,195,195,,195,195,195,,,,,,,,,,,,,,,,,,,,195',
-',,195,,,195,195,,,195,,,,,,195,,,,,,,,195,,,,,195,195,195,195,195,195',
-',,,195,195,196,196,196,,196,,,,196,196,,,,196,,196,196,196,196,196,196',
-'196,,,,,196,196,196,196,196,196,196,,,196,,,,,,,196,,,196,196,196,196',
-'196,196,196,196,196,196,,196,196,,196,196,196,,,,,,,,,,,,,,,,,,,,196',
-',,196,,,196,196,,,196,,,,,,196,,,,,,,,196,,,,,196,196,196,196,196,196',
-',,,196,196,207,207,207,,207,,,,207,207,,,,207,,207,207,207,207,207,207',
-'207,,,,,207,207,207,207,207,207,207,,,,,,,,,,207,,,207,207,207,207,207',
-'207,207,207,207,207,,207,207,,207,207,207,,,,,,,,,,,,,,,,,,,,207,,,207',
-',,207,207,,,207,,,,,,207,,,,,,,,207,,,,,207,207,207,207,207,207,,,,207',
-'207,208,208,208,,208,,,,208,208,,,,208,,208,208,208,208,208,208,208',
-',,,,208,208,208,208,208,208,208,,,,,,,,,,208,,,208,208,208,208,208,208',
-'208,208,208,208,,208,208,,208,208,208,,,,,,,,,,,,,,,,,,,,208,,,208,',
-',208,208,,,208,,,,,,208,,,,,,,,208,,,,,208,208,208,208,208,208,,,,208',
-'208,209,209,209,,209,,,,209,209,,,,209,,209,209,209,209,209,209,209',
-',,,,209,209,209,209,209,209,209,,,,,,,,,,209,,,209,209,209,209,209,209',
-'209,209,209,209,,209,209,,209,209,209,,,,,,,,,,,,,,,,,,,,209,,,209,',
-',209,209,,,209,,,,,,209,,,,,,,,209,,,,,209,209,209,209,209,209,,,,209',
-'209,210,210,210,,210,,,,210,210,,,,210,,210,210,210,210,210,210,210',
-',,,,210,210,210,210,210,210,210,,,,,,,,,,210,,,210,210,210,210,210,210',
-'210,210,210,210,,210,210,,210,210,210,,,,,,,,,,,,,,,,,,,,210,,,210,',
-',210,210,,,210,,,,,,210,,,,,,,,210,,,,,210,210,210,210,210,210,,,,210',
-'210,211,211,211,,211,,,,211,211,,,,211,,211,211,211,211,211,211,211',
-',,,,211,211,211,211,211,211,211,,,,,,,,,,211,,,211,211,211,211,211,211',
-'211,211,211,211,,211,211,,211,211,211,,,,,,,,,,,,,,,,,,,,211,,,211,',
-',211,211,,,211,,,,,,211,,,,,,,,211,,,,,211,211,211,211,211,211,,,,211',
-'211,212,212,212,,212,,,,212,212,,,,212,,212,212,212,212,212,212,212',
-',,,,212,212,212,212,212,212,212,,,,,,,,,,212,,,212,212,212,212,212,212',
-'212,212,212,212,,212,212,,212,212,212,,,,,,,,,,,,,,,,,,,,212,,,212,',
-',212,212,,,212,,,,,,212,,,,,,,,212,,,,,212,212,212,212,212,212,,,,212',
-'212,213,213,213,,213,,,,213,213,,,,213,,213,213,213,213,213,213,213',
-',,,,213,213,213,213,213,213,213,,,,,,,,,,213,,,213,213,213,213,213,213',
-'213,213,213,213,,213,213,,213,213,213,,,,,,,,,,,,,,,,,,,,213,,,213,',
-',213,213,,,213,,,,,,213,,,,,,,,213,,,,,213,213,213,213,213,213,,,,213',
-'213,214,214,214,,214,,,,214,214,,,,214,,214,214,214,214,214,214,214',
-',,,,214,214,214,214,214,214,214,,,,,,,,,,214,,,214,214,214,214,214,214',
-'214,214,214,214,,214,214,,214,214,214,,,,,,,,,,,,,,,,,,,,214,,,214,',
-',214,214,,,214,,,,,,214,,,,,,,,214,,,,,214,214,214,214,214,214,,,,214',
-'214,215,215,215,,215,,,,215,215,,,,215,,215,215,215,215,215,215,215',
-',,,,215,215,215,215,215,215,215,,,,,,,,,,215,,,215,215,215,215,215,215',
-'215,215,215,215,,215,215,,215,215,215,,,,,,,,,,,,,,,,,,,,215,,,215,',
-',215,215,,,215,,,,,,215,,,,,,,,215,,,,,215,215,215,215,215,215,,,,215',
-'215,216,216,216,,216,,,,216,216,,,,216,,216,216,216,216,216,216,216',
-',,,,216,216,216,216,216,216,216,,,,,,,,,,216,,,216,216,216,216,216,216',
-'216,216,216,216,,216,216,,216,216,216,,,,,,,,,,,,,,,,,,,,216,,,216,',
-',216,216,,,216,,,,,,216,,,,,,,,216,,,,,216,216,216,216,216,216,,,,216',
-'216,217,217,217,,217,,,,217,217,,,,217,,217,217,217,217,217,217,217',
-',,,,217,217,217,217,217,217,217,,,,,,,,,,217,,,217,217,217,217,217,217',
-'217,217,217,217,,217,217,,217,217,217,,,,,,,,,,,,,,,,,,,,217,,,217,',
-',217,217,,,217,,,,,,217,,,,,,,,217,,,,,217,217,217,217,217,217,,,,217',
-'217,218,218,218,,218,,,,218,218,,,,218,,218,218,218,218,218,218,218',
-',,,,218,218,218,218,218,218,218,,,,,,,,,,218,,,218,218,218,218,218,218',
-'218,218,218,218,,218,218,,218,218,218,,,,,,,,,,,,,,,,,,,,218,,,218,',
-',218,218,,,218,,,,,,218,,,,,,,,218,,,,,218,218,218,218,218,218,,,,218',
-'218,219,219,219,,219,,,,219,219,,,,219,,219,219,219,219,219,219,219',
-',,,,219,219,219,219,219,219,219,,,,,,,,,,219,,,219,219,219,219,219,219',
-'219,219,219,219,,219,219,,219,219,219,,,,,,,,,,,,,,,,,,,,219,,,219,',
-',219,219,,,219,,,,,,219,,,,,,,,219,,,,,219,219,219,219,219,219,,,,219',
-'219,220,220,220,,220,,,,220,220,,,,220,,220,220,220,220,220,220,220',
-',,,,220,220,220,220,220,220,220,,,,,,,,,,220,,,220,220,220,220,220,220',
-'220,220,220,220,,220,220,,220,220,220,,,,,,,,,,,,,,,,,,,,220,,,220,',
-',220,220,,,220,,,,,,220,,,,,,,,220,,,,,220,220,220,220,220,220,,,,220',
-'220,221,221,221,,221,,,,221,221,,,,221,,221,221,221,221,221,221,221',
-',,,,221,221,221,221,221,221,221,,,,,,,,,,221,,,221,221,221,221,221,221',
-'221,221,221,221,,221,221,,221,221,221,,,,,,,,,,,,,,,,,,,,221,,,221,',
-',221,221,,,221,,,,,,221,,,,,,,,221,,,,,221,221,221,221,221,221,,,,221',
-'221,222,222,222,,222,,,,222,222,,,,222,,222,222,222,222,222,222,222',
-',,,,222,222,222,222,222,222,222,,,,,,,,,,222,,,222,222,222,222,222,222',
-'222,222,222,222,,222,222,,222,222,222,,,,,,,,,,,,,,,,,,,,222,,,222,',
-',222,222,,,222,,,,,,222,,,,,,,,222,,,,,222,222,222,222,222,222,,,,222',
-'222,223,223,223,,223,,,,223,223,,,,223,,223,223,223,223,223,223,223',
-',,,,223,223,223,223,223,223,223,,,,,,,,,,223,,,223,223,223,223,223,223',
-'223,223,223,223,,223,223,,223,223,223,,,,,,,,,,,,,,,,,,,,223,,,223,',
-',223,223,,,223,,,,,,223,,,,,,,,223,,,,,223,223,223,223,223,223,,,,223',
-'223,224,224,224,,224,,,,224,224,,,,224,,224,224,224,224,224,224,224',
-',,,,224,224,224,224,224,224,224,,,,,,,,,,224,,,224,224,224,224,224,224',
-'224,224,224,224,,224,224,,224,224,224,,,,,,,,,,,,,,,,,,,,224,,,224,',
-',224,224,,,224,,,,,,224,,,,,,,,224,,,,,224,224,224,224,224,224,,,,224',
-'224,225,225,225,,225,,,,225,225,,,,225,,225,225,225,225,225,225,225',
-',,,,225,225,225,225,225,225,225,,,,,,,,,,225,,,225,225,225,225,225,225',
-'225,225,225,225,,225,225,,225,225,225,,,,,,,,,,,,,,,,,,,,225,,,225,',
-',225,225,,,225,,,,,,225,,,,,,,,225,,,,,225,225,225,225,225,225,,,,225',
-'225,226,226,226,,226,,,,226,226,,,,226,,226,226,226,226,226,226,226',
-',,,,226,226,226,226,226,226,226,,,,,,,,,,226,,,226,226,226,226,226,226',
-'226,226,226,226,,226,226,,226,226,226,,,,,,,,,,,,,,,,,,,,226,,,226,',
-',226,226,,,226,,,,,,226,,,,,,,,226,,,,,226,226,226,226,226,226,,,,226',
-'226,227,227,227,,227,,,,227,227,,,,227,,227,227,227,227,227,227,227',
-',,,,227,227,227,227,227,227,227,,,,,,,,,,227,,,227,227,227,227,227,227',
-'227,227,227,227,,227,227,,227,227,227,,,,,,,,,,,,,,,,,,,,227,,,227,',
-',227,227,,,227,,,,,,227,,,,,,,,227,,,,,227,227,227,227,227,227,,,,227',
-'227,228,228,228,,228,,,,228,228,,,,228,,228,228,228,228,228,228,228',
-',,,,228,228,228,228,228,228,228,,,,,,,,,,228,,,228,228,228,228,228,228',
-'228,228,228,228,,228,228,,228,228,228,,,,,,,,,,,,,,,,,,,,228,,,228,',
-',228,228,,,228,,,,,,228,,,,,,,,228,,,,,228,228,228,228,228,228,,,,228',
-'228,229,229,229,,229,,,,229,229,,,,229,,229,229,229,229,229,229,229',
-',,,,229,229,229,229,229,229,229,,,,,,,,,,229,,,229,229,229,229,229,229',
-'229,229,229,229,,229,229,,229,229,229,,,,,,,,,,,,,,,,,,,,229,,,229,',
-',229,229,,,229,,,,,,229,,,,,,,,229,,,,,229,229,229,229,229,229,,,,229',
-'229,230,230,230,,230,,,,230,230,,,,230,,230,230,230,230,230,230,230',
-',,,,230,230,230,230,230,230,230,,,,,,,,,,230,,,230,230,230,230,230,230',
-'230,230,230,230,,230,230,,230,230,230,,,,,,,,,,,,,,,,,,,,230,,,230,',
-',230,230,,,230,,,,,,230,,,,,,,,230,,,,,230,230,230,230,230,230,,,,230',
-'230,231,231,231,,231,,,,231,231,,,,231,,231,231,231,231,231,231,231',
-',,,,231,231,231,231,231,231,231,,,,,,,,,,231,,,231,231,231,231,231,231',
-'231,231,231,231,,231,231,,231,231,231,,,,,,,,,,,,,,,,,,,,231,,,231,',
-',231,231,,,231,,,,,,231,,,,,,,,231,,,,,231,231,231,231,231,231,,,,231',
-'231,232,232,232,,232,,,,232,232,,,,232,,232,232,232,232,232,232,232',
-',,,,232,232,232,232,232,232,232,,,,,,,,,,232,,,232,232,232,232,232,232',
-'232,232,232,232,,232,232,,232,232,232,,,,,,,,,,,,,,,,,,,,232,,,232,',
-',232,232,,,232,,,,,,232,,,,,,,,232,,,,,232,232,232,232,232,232,,,,232',
-'232,233,233,233,,233,,,,233,233,,,,233,,233,233,233,233,233,233,233',
-',,,,233,233,233,233,233,233,233,,,,,,,,,,233,,,233,233,233,233,233,233',
-'233,233,233,233,,233,233,,233,233,233,,,,,,,,,,,,,,,,,,,,233,,,233,',
-',233,233,,,233,,,,,,233,,,,,,,,233,,,,,233,233,233,233,233,233,,,,233',
-'233,241,241,241,,241,,,,241,241,,,,241,,241,241,241,241,241,241,241',
-',,,,241,241,241,241,241,241,241,,,,,,,,,,241,,,241,241,241,241,241,241',
-'241,241,241,241,,241,241,,241,241,241,,,,,,,,,,,,,,,,,,,,241,,,241,',
-',241,241,,,241,,,,,,241,,,,,,,,241,,,,,241,241,241,241,241,241,,,,241',
-'241,243,243,243,,243,,,,243,243,,,,243,,243,243,243,243,243,243,243',
-',,,,243,243,243,243,243,243,243,,,,,,,,,,243,,,243,243,243,243,243,243',
-'243,243,243,243,,243,243,,243,243,243,,,,,,,,,,,,,,,,,,,,243,,,243,',
-',243,243,,,243,,,,,,243,,,,,,,,243,,,,,243,243,243,243,243,243,,,,243',
-'243,254,254,254,,254,,,,254,254,,,,254,,254,254,254,254,254,254,254',
-',,,,254,254,254,254,254,254,254,,,,,,,,,,254,,,254,254,254,254,254,254',
-'254,254,254,254,,254,254,,254,254,254,,,,,,,,,,,,,,,,,,,,254,,,254,',
-',254,254,,,254,,254,,254,,254,,,,,,,,254,,,,,254,254,254,254,254,254',
-',,,254,254,255,255,255,,255,,,,255,255,,,,255,,255,255,255,255,255,255',
-'255,,,,,255,255,255,255,255,255,255,,,,,,,,,,255,,,255,255,255,255,255',
-'255,255,255,255,255,,255,255,,255,255,255,,,,,,,,,,,,,,,,,,,,255,,,255',
-',,255,255,,,255,,255,,255,,255,,,,,,,,255,,,,,255,255,255,255,255,255',
-',,,255,255,263,263,263,,263,,,,263,263,,,,263,,263,263,263,263,263,263',
-'263,,,,,263,263,263,263,263,263,263,,,,,,,,,,263,,,263,263,263,263,263',
-'263,263,263,263,263,,263,263,,263,263,263,,,,,,,,,,,,,,,,,,,,263,,,263',
-',263,263,263,,,263,,263,,263,,263,,,,,,,,263,,,,,263,263,263,263,263',
-'263,,,,263,263,269,269,269,,269,,,,269,269,,,,269,,269,269,269,269,269',
-'269,269,,,,,269,269,269,269,269,269,269,,,,,,,,,,269,,,269,269,269,269',
-'269,269,269,269,269,269,,269,269,,,,269,,687,687,687,687,687,687,687',
-'687,687,687,687,,687,687,,,687,687,269,,,269,,,269,269,,,269,,,,687',
-',687,,687,687,687,687,687,687,687,,687,,,269,269,269,269,269,269,,,',
-'269,269,290,290,290,687,290,,,,290,290,,,,290,,290,290,290,290,290,290',
-'290,,,,,290,290,290,290,290,290,290,,,,,,,,,,290,,,290,290,290,290,290',
-'290,290,290,290,290,,290,290,,290,290,290,,,,,,,,,,,,,,,,,,,,290,,,290',
-'290,,290,290,,,290,,,,,,290,,,,,,,,290,,,,,290,290,290,290,290,290,',
-',,290,290,299,299,299,,299,,,,299,299,,,,299,,299,299,299,299,299,299',
-'299,,,,,299,299,299,299,299,299,299,,,,,,,,,,299,,,299,299,299,299,299',
-'299,299,299,299,299,,299,299,,299,299,299,,,,,,,,,,,,,,,,,,,,299,,,299',
-',,299,299,,,299,,,,,,299,,,,,,,,299,,,,,299,299,299,299,299,299,,,,299',
+'495,495,495,495,495,495,495,495,495,495,,495,495,,495,495,495,417,417',
+'417,417,417,417,417,,,417,417,,,,,,417,417,,495,,,495,,,495,495,,,495',
+',495,417,,417,495,417,417,417,417,417,417,417,495,417,,,,495,495,495',
+'495,495,495,,,,495,495,513,513,513,513,513,513,,,,513,513,,,,513,,513',
+'513,513,513,513,513,513,,,,,513,513,513,513,513,513,513,,,513,,,,,,513',
+'513,513,513,513,513,513,513,513,513,513,513,513,513,,513,513,,513,513',
+'513,418,418,418,418,418,418,418,,,418,418,,,,,,418,418,,513,,,513,,',
+'513,513,,,513,,513,418,,418,513,418,418,418,418,418,418,418,513,418',
+',,,513,513,513,513,513,513,,,,513,513,559,559,559,559,559,559,,,,559',
+'559,,,,559,,559,559,559,559,559,559,559,,,,,559,559,559,559,559,559',
+'559,,,559,,,,,,559,559,559,559,559,559,559,559,559,559,559,559,559,559',
+',559,559,,559,559,559,421,421,421,421,421,421,421,,,421,421,,,,,,421',
+'421,,559,,,559,,,559,559,,,559,,559,421,,421,559,421,421,421,421,421',
+'421,421,559,421,,,,559,559,559,559,559,559,,,,559,559,588,588,588,588',
+'588,588,,,,588,588,,,,588,,588,588,588,588,588,588,588,,,,,588,588,588',
+'588,588,588,588,,,588,,,,,,588,588,588,588,588,588,588,588,588,588,588',
+'588,588,588,,588,588,,588,588,588,422,422,422,422,422,422,422,422,,422',
+'422,,,,,,422,422,,588,,,588,,,588,588,,,588,,588,422,,422,588,422,422',
+'422,422,422,422,422,588,422,,,,588,588,588,588,588,588,,,,588,588,589',
+'589,589,589,589,589,,,,589,589,,,,589,,589,589,589,589,589,589,589,',
+',,,589,589,589,589,589,589,589,,,589,,,,,,589,589,589,589,589,589,589',
+'589,589,589,589,589,589,589,,589,589,,589,589,589,406,,,,,,,,,,,,,,',
+',406,406,,589,,,589,,,589,589,,,589,,589,406,,406,589,406,406,406,406',
+',,,589,,,,,589,589,589,589,589,589,,,,589,589,606,606,606,606,606,606',
+',,,606,606,,,,606,,606,606,606,606,606,606,606,,,,,606,606,606,606,606',
+'606,606,,,606,,,,,,606,606,606,606,606,606,606,606,606,606,606,606,606',
+'606,,606,606,,606,606,606,407,,,,,,,,,,,,,,,,407,407,,606,,,606,,,606',
+'606,,,606,,606,407,,407,606,407,407,407,407,,,,606,,,,,606,606,606,606',
+'606,606,,,,606,606,639,639,639,639,639,639,,,,639,639,,,,639,,639,639',
+'639,639,639,639,639,,,,,639,639,639,639,639,639,639,,,639,,,,,,639,639',
+'639,639,639,639,639,639,639,639,639,639,639,639,,639,639,,639,639,639',
+'408,,,,,,,,,,,,,,,,408,408,,639,,,639,,,639,639,,,639,,639,408,,,639',
+'408,408,408,408,,,,639,,,,,639,639,639,639,639,639,,,,639,639,644,644',
+'644,644,644,644,,,,644,644,,,,644,,644,644,644,644,644,644,644,,,,,644',
+'644,644,644,644,644,644,,,644,,,,,,644,644,644,644,644,644,644,644,644',
+'644,644,644,644,644,,644,644,,644,644,644,,,,,,,,,,,,,,,,,,,,644,,,644',
+',,644,644,,,644,,644,,,,644,,,,,,,,644,,,,,644,644,644,644,644,644,',
+',,644,644,671,671,671,671,671,671,,,,671,671,,,,671,,671,671,671,671',
+'671,671,671,,,,,671,671,671,671,671,671,671,,,671,,,,,,671,671,671,671',
+'671,671,671,671,671,671,671,671,671,671,,671,671,,671,671,671,,,,,,',
+',,,,,,,,,,,,,671,,,671,,,671,671,,,671,,671,,,,671,,,,,,,,671,,,,,671',
+'671,671,671,671,671,,,,671,671,706,706,706,706,706,706,,,,706,706,,',
+',706,,706,706,706,706,706,706,706,,,,,706,706,706,706,706,706,706,,',
+'706,,,,,,706,706,706,706,706,706,706,706,706,706,706,706,706,706,,706',
+'706,,706,706,706,,,,,,,,,,,,,,,,,,,,706,,,706,,,706,706,,,706,,706,',
+',,706,,,,,,,,706,,,,,706,706,706,706,706,706,,,,706,706,724,724,724',
+'724,724,724,,,,724,724,,,,724,,724,724,724,724,724,724,724,,,,,724,724',
+'724,724,724,724,724,,,724,,,,,,724,724,724,724,724,724,724,724,724,724',
+'724,724,724,724,,724,724,,724,724,724,,,,,,,,,,,,,,,,,,,,724,,,724,',
+',724,724,,,724,,724,,,,724,,,,,,,,724,,,,,724,724,724,724,724,724,,',
+',724,724,736,736,736,736,736,736,,,,736,736,,,,736,,736,736,736,736',
+'736,736,736,,,,,736,736,736,736,736,736,736,,,736,,,,,,736,736,736,736',
+'736,736,736,736,736,736,736,736,736,736,,736,736,,736,736,736,,,,,,',
+',,,,,,,,,,,,,736,,,736,,,736,736,,,736,,736,,,,736,,,,,,,,736,,,,,736',
+'736,736,736,736,736,,,,736,736,737,737,737,737,737,737,,,,737,737,,',
+',737,,737,737,737,737,737,737,737,,,,,737,737,737,737,737,737,737,,',
+'737,,,,,,737,737,737,737,737,737,737,737,737,737,737,737,737,737,,737',
+'737,,737,737,737,,,,,,,,,,,,,,,,,,,,737,,,737,,,737,737,,,737,,737,',
+',,737,,,,,,,,737,,,,,737,737,737,737,737,737,,,,737,737,741,741,741',
+'741,741,741,,,,741,741,,,,741,,741,741,741,741,741,741,741,,,,,741,741',
+'741,741,741,741,741,,,741,,,,,,741,741,741,741,741,741,741,741,741,741',
+'741,741,741,741,,741,741,,741,741,741,,,,,,,,,,,,,,,,,,,,741,,,741,',
+',741,741,,,741,,741,,,,741,,,,,,,,741,,,,,741,741,741,741,741,741,,',
+',741,741,748,748,748,748,748,748,,,,748,748,,,,748,,748,748,748,748',
+'748,748,748,,,,,748,748,748,748,748,748,748,,,748,,,,,,748,748,748,748',
+'748,748,748,748,748,748,748,748,748,748,,748,748,,748,748,748,,,,,,',
+',,,,,,,,,,,,,748,,,748,,,748,748,,,748,,748,,,,748,,,,,,,,748,,,,,748',
+'748,748,748,748,748,,,,748,748,794,794,794,794,794,794,,,,794,794,,',
+',794,,794,794,794,794,794,794,794,,,,,794,794,794,794,794,794,794,,',
+'794,,,,,,794,794,794,794,794,794,794,794,794,794,794,794,794,794,,794',
+'794,,794,794,794,,,,,,,,,,,,,,,,,,,,794,,,794,,,794,794,,,794,,794,',
+',,794,,,,,,,,794,,,,,794,794,794,794,794,794,,,,794,794,838,838,838',
+'838,838,838,,,,838,838,,,,838,,838,838,838,838,838,838,838,,,,,838,838',
+'838,838,838,838,838,,,838,,,,,,838,838,838,838,838,838,838,838,838,838',
+'838,838,838,838,,838,838,,838,838,838,,,,,,,,,,,,,,,,,,,,838,,,838,',
+',838,838,,,838,,838,,,,838,,,,,,,,838,,,,,838,838,838,838,838,838,,',
+',838,838,845,845,845,845,845,845,,,,845,845,,,,845,,845,845,845,845',
+'845,845,845,,,,,845,845,845,845,845,845,845,,,845,,,,,,845,845,845,845',
+'845,845,845,845,845,845,845,845,845,845,,845,845,,845,845,845,,,,,,',
+',,,,,,,,,,,,,845,,,845,,,845,845,,,845,,845,,,,845,,,,,,,,845,,,,,845',
+'845,845,845,845,845,,,,845,845,852,852,852,852,852,852,,,,852,852,,',
+',852,,852,852,852,852,852,852,852,,,,,852,852,852,852,852,852,852,,',
+'852,,,,,,852,852,852,852,852,852,852,852,852,852,852,852,852,852,,852',
+'852,,852,852,852,,,,,,,,,,,,,,,,,,,,852,,,852,,,852,852,,,852,,852,',
+',,852,,,,,,,,852,,,,,852,852,852,852,852,852,,,,852,852,5,5,5,5,5,,',
+',5,5,,,,5,,5,5,5,5,5,5,5,,,,,5,5,5,5,5,5,5,,,5,,,,,,5,5,5,5,5,5,5,5',
+'5,5,5,5,5,5,,5,5,,5,5,5,,,,,,,,,,,,,,,,,,,,5,,,5,,,5,5,,,5,,5,,,,5,',
+',,,,,,5,,,,,5,5,5,5,5,5,,,,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6',
+'6,6,6,6,6,,,6,6,6,6,6,6,6,6,6,6,,,,,,6,6,6,6,6,6,6,6,6,,6,,,,,,,,6,6',
+',6,6,6,6,,6,6,,,6,,,,,6,6,6,6,,,,,,,,,,,,,,6,6,,6,6,6,6,6,6,6,6,6,,6',
+',,6,6,,,,,,,,,,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,,,7',
+'7,7,7,7,7,7,7,7,7,,,,,,7,7,7,7,7,7,7,7,,,7,,,,,,,,7,7,,7,7,7,7,,7,7',
+',,7,,,,,7,7,7,7,,,,,,,,,,,,,,7,7,,7,7,7,7,7,7,7,7,7,,7,,,7,7,,,17,17',
+'17,,17,,,7,17,17,,,,17,,17,17,17,17,17,17,17,,,,,17,17,17,17,17,17,17',
+',,17,,,,,,,17,,,17,17,17,17,17,17,17,17,17,17,,17,17,,17,17,17,,,,,',
+',,,,,,,,,,,,,,17,,,17,,,17,17,,,17,,,,,,17,,,,,,,,17,,,,,17,17,17,17',
+'17,17,,,,17,17,18,18,18,,18,,,,18,18,,,,18,,18,18,18,18,18,18,18,,,',
+',18,18,18,18,18,18,18,,,,,,,,,,18,,,18,18,18,18,18,18,18,18,18,18,,18',
+'18,,18,18,18,,,,,,,,,,,,,,,,,,,,18,,,18,,,18,18,,,18,,,,,,18,,,,,,,',
+'18,,,,,18,18,18,18,18,18,,,,18,18,22,22,22,,22,,,,22,22,,,,22,,22,22',
+'22,22,22,22,22,,,,,22,22,22,22,22,22,22,,,,,,,,,,22,,,22,22,22,22,22',
+'22,22,22,22,22,,22,22,,22,22,22,,,,,,,,,,,,,,,,,,,,22,,,22,,,22,22,',
+',22,,22,,22,,22,,,,,,,,22,,,,,22,22,22,22,22,22,,,,22,22,23,23,23,,23',
+',,,23,23,,,,23,,23,23,23,23,23,23,23,,,,,23,23,23,23,23,23,23,,,,,,',
+',,,23,,,23,23,23,23,23,23,23,23,23,23,,23,23,,23,23,23,,,,,,,,,,,,,',
+',,,,,,23,,,23,,,23,23,,,23,,23,,23,,23,,,,,,,,23,,,,,23,23,23,23,23',
+'23,,,,23,23,24,24,24,,24,,,,24,24,,,,24,,24,24,24,24,24,24,24,,,,,24',
+'24,24,24,24,24,24,,,,,,,,,,24,,,24,24,24,24,24,24,24,24,24,24,,24,24',
+',24,24,24,,,,,,,,,,,,,,,,,,,,24,,,24,,,24,24,,,24,,24,,24,,24,,,,,,',
+',24,,,,,24,24,24,24,24,24,,,,24,24,27,27,27,,27,,,,27,27,,,,27,,27,27',
+'27,27,27,27,27,,,,,27,27,27,27,27,27,27,,,,,,,,,,27,,,27,27,27,27,27',
+'27,27,27,27,27,,27,27,,27,27,27,,,,,,,,,,,,,,,,,,,,27,,,27,27,,27,27',
+',,27,,27,,27,,27,,,,,,,,27,,,,,27,27,27,27,27,27,,,,27,27,28,28,28,',
+'28,,,,28,28,,,,28,,28,28,28,28,28,28,28,,,,,28,28,28,28,28,28,28,,,',
+',,,,,,28,,,28,28,28,28,28,28,28,28,28,28,,28,28,,28,28,28,,,,,,,,,,',
+',,,,,,,,,28,,,28,28,,28,28,,,28,,28,,28,,28,,,,,,,,28,,,,,28,28,28,28',
+'28,28,,,,28,28,31,31,31,,31,,,,31,31,,,,31,,31,31,31,31,31,31,31,,,',
+',31,31,31,31,31,31,31,,,,,,,,,,31,,,31,31,31,31,31,31,31,31,31,31,,31',
+'31,,,,31,,828,828,828,828,828,828,828,828,828,828,828,,828,828,,,828',
+'828,31,,,31,,,31,31,,,31,,31,,828,,828,,828,828,828,828,828,828,828',
+',828,,,31,31,31,31,31,31,,,,31,31,32,32,32,828,32,828,,,32,32,,,,32',
+',32,32,32,32,32,32,32,,,,,32,32,32,32,32,32,32,,,,,,,,,,32,,,32,32,32',
+'32,32,32,32,32,32,32,,32,32,,,,32,,19,19,19,19,19,19,19,19,19,19,19',
+',19,19,,,19,19,32,,,32,,,32,32,,,32,,,,19,,19,,19,19,19,19,19,19,19',
+',19,,,32,32,32,32,32,32,,,,32,32,38,38,38,19,38,,,,38,38,,,,38,,38,38',
+'38,38,38,38,38,,,,,38,38,38,38,38,38,38,,,,,,,,,,38,,,38,38,38,38,38',
+'38,38,38,38,38,,38,38,,38,38,38,,,,,,,,,,,,,,,,,,,,38,,,38,,,38,38,',
+',38,,,,,,38,,,,,,,,38,,,,,38,38,38,38,38,38,,,,38,38,39,39,39,,39,,',
+',39,39,,,,39,,39,39,39,39,39,39,39,,,,,39,39,39,39,39,39,39,,,,,,,,',
+',39,,,39,39,39,39,39,39,39,39,39,39,,39,39,,39,39,39,,,,,,,,,,,,,,,',
+',,,,39,,,39,,,39,39,,,39,,,,,,39,,,,,,,,39,,,,,39,39,39,39,39,39,,,',
+'39,39,40,40,40,,40,,,,40,40,,,,40,,40,40,40,40,40,40,40,,,,,40,40,40',
+'40,40,40,40,,,,,,,,,,40,,,40,40,40,40,40,40,40,40,40,40,,40,40,,40,40',
+'40,,,,,,,,,,,,,,,,,,,,40,,,40,,,40,40,,,40,,,,,,40,,,,,,,,40,,,,,40',
+'40,40,40,40,40,,,,40,40,52,52,52,,52,,,,52,52,,,,52,,52,52,52,52,52',
+'52,52,,,,,52,52,52,52,52,52,52,,,52,,,,,,,52,,,52,52,52,52,52,52,52',
+'52,52,52,,52,52,,52,52,52,,,,,,,,,,,,,,,,,,,,52,,,52,,,52,52,,,52,,',
+',,,52,,,,,,,,52,,,,,52,52,52,52,52,52,,,,52,52,53,53,53,,53,,,,53,53',
+',,,53,,53,53,53,53,53,53,53,,,,,53,53,53,53,53,53,53,,,,,,,,,,53,,,53',
+'53,53,53,53,53,53,53,53,53,,53,53,,53,53,53,,,,,,,,,,,,,,,,,,,,53,,',
+'53,,,53,53,,,53,,53,,,,53,,,,,,,,53,,,,,53,53,53,53,53,53,,,,53,53,54',
+'54,54,,54,,,,54,54,,,,54,,54,54,54,54,54,54,54,,,,,54,54,54,54,54,54',
+'54,,,,,,,,,,54,,,54,54,54,54,54,54,54,54,54,54,,54,54,,54,54,54,,,,',
+',,,,,,,,,,,,,,,54,,,54,,,54,54,,,54,,,,,,54,,,,,,,,54,,,,,54,54,54,54',
+'54,54,,,,54,54,56,56,56,,56,,,,56,56,,,,56,,56,56,56,56,56,56,56,,,',
+',56,56,56,56,56,56,56,,,56,,,,,,,56,,,56,56,56,56,56,56,56,56,56,56',
+',56,56,,56,56,56,,,,,,,,,,,,,,,,,,,,56,,,56,,,56,56,,,56,,,,,,56,,,',
+',,,,56,,,,,56,56,56,56,56,56,,,,56,56,57,57,57,,57,,,,57,57,,,,57,,57',
+'57,57,57,57,57,57,,,,,57,57,57,57,57,57,57,,,57,,,,,,,57,,,57,57,57',
+'57,57,57,57,57,57,57,,57,57,,57,57,57,,,,,,,,,,,,,,,,,,,,57,,,57,,,57',
+'57,,,57,,,,,,57,,,,,,,,57,,,,,57,57,57,57,57,57,,,,57,57,61,61,61,,61',
+',,,61,61,,,,61,,61,61,61,61,61,61,61,,,,,61,61,61,61,61,61,61,,,,,,',
+',,,61,,,61,61,61,61,61,61,61,61,61,61,,61,61,,,,61,,237,237,237,237',
+'237,237,237,237,237,237,237,,237,237,,,237,237,61,,,61,,,61,61,,,61',
+',61,,237,,237,,237,237,237,237,237,237,237,,237,,,61,61,61,61,61,61',
+',,,61,61,62,62,62,237,62,,,,62,62,,,,62,,62,62,62,62,62,62,62,,,,,62',
+'62,62,62,62,62,62,,,,,,,,,,62,,,62,62,62,62,62,62,62,62,62,62,,62,62',
+',,,62,,374,374,374,374,374,374,374,374,374,374,374,,374,374,,62,374',
+'374,62,,,62,,,62,62,,,62,,,,374,,374,,374,374,374,374,374,374,374,,374',
+',,62,62,62,62,62,62,,,,62,62,63,63,63,374,63,,,,63,63,,,,63,,63,63,63',
+'63,63,63,63,,,,,63,63,63,63,63,63,63,,,,,,,,,,63,,,63,63,63,63,63,63',
+'63,63,63,63,,63,63,,,,63,,388,388,388,388,388,388,388,388,388,388,388',
+',388,388,,,388,388,63,,,63,,,63,63,,,63,,,,388,,388,,388,388,388,388',
+'388,388,388,,388,,,63,63,63,63,63,63,,,,63,63,82,82,82,388,82,,,,82',
+'82,,,,82,,82,82,82,82,82,82,82,,82,,,82,82,82,82,82,82,82,,,,,,,,,,82',
+',,82,82,82,82,82,82,82,82,82,82,,82,82,,82,82,82,,,,,,,,,,,,,,,,,,,',
+'82,,,82,82,,82,82,,,82,,82,,82,,82,,,,,,,,82,,82,,,82,82,82,82,82,82',
+',,,82,82,86,86,86,,86,,,,86,86,,,,86,,86,86,86,86,86,86,86,,86,,,86',
+'86,86,86,86,86,86,,,,,,,,,,86,,,86,86,86,86,86,86,86,86,86,86,,86,86',
+',86,86,86,,,,,,,,,,,,,,,,,,,,86,,,86,86,,86,86,,,86,,86,,86,,86,,,,',
+',,,86,,86,,,86,86,86,86,86,86,,,,86,86,101,101,101,,101,,,,101,101,',
+',,101,,101,101,101,101,101,101,101,,,,,101,101,101,101,101,101,101,',
+',101,,,,,,,101,,,101,101,101,101,101,101,101,101,101,101,,101,101,,101',
+'101,101,,,,,,,,,,,,,,,,,,,,101,,,101,,,101,101,,,101,,,,,,101,,,,,,',
+',101,,,,,101,101,101,101,101,101,,,,101,101,102,102,102,,102,,,,102',
+'102,,,,102,,102,102,102,102,102,102,102,,,,,102,102,102,102,102,102',
+'102,,,102,,,,,,,102,,,102,102,102,102,102,102,102,102,102,102,,102,102',
+',102,102,102,,,,,,,,,,,,,,,,,,,,102,,,102,,,102,102,,,102,,,,,,102,',
+',,,,,,102,,,,,102,102,102,102,102,102,,,,102,102,103,103,103,,103,,',
+',103,103,,,,103,,103,103,103,103,103,103,103,,,,,103,103,103,103,103',
+'103,103,,,103,,,,,,,103,,,103,103,103,103,103,103,103,103,103,103,,103',
+'103,,103,103,103,,,,,,,,,,,,,,,,,,,,103,,,103,,,103,103,,,103,,,,,,103',
+',,,,,,,103,,,,,103,103,103,103,103,103,,,,103,103,104,104,104,,104,',
+',,104,104,,,,104,,104,104,104,104,104,104,104,,,,,104,104,104,104,104',
+'104,104,,,104,,,,,,,104,,,104,104,104,104,104,104,104,104,104,104,,104',
+'104,,104,104,104,,,,,,,,,,,,,,,,,,,,104,,,104,,,104,104,,,104,,,,,,104',
+',,,,,,,104,,,,,104,104,104,104,104,104,,,,104,104,105,105,105,105,105',
+',,,105,105,,,,105,,105,105,105,105,105,105,105,,,,,105,105,105,105,105',
+'105,105,,,105,,,,,,105,105,105,105,105,105,105,105,105,105,105,105,105',
+'105,,105,105,,105,105,105,,,,,,,,,,,,,,,,,,,,105,,,105,,,105,105,,,105',
+',105,,,,105,,,,,,,,105,,,,,105,105,105,105,105,105,,,,105,105,188,188',
+'188,,188,,,,188,188,,,,188,,188,188,188,188,188,188,188,,,,,188,188',
+'188,188,188,188,188,,,,,,,,,,188,,,188,188,188,188,188,188,188,188,188',
+'188,,188,188,,188,188,188,,,,,,,,,,,,,,,,,,,,188,,,188,,,188,188,,,188',
+',188,,,,188,,,,,,,,188,,,,,188,188,188,188,188,188,,,,188,188,189,189',
+'189,,189,,,,189,189,,,,189,,189,189,189,189,189,189,189,,,,,189,189',
+'189,189,189,189,189,,,,,,,,,,189,,,189,189,189,189,189,189,189,189,189',
+'189,,189,189,,189,189,189,,,,,,,,,,,,,,,,,,,,189,,,189,,,189,189,,,189',
+',189,,,,189,,,,,,,,189,,,,,189,189,189,189,189,189,,,,189,189,190,190',
+'190,,190,,,,190,190,,,,190,,190,190,190,190,190,190,190,,,,,190,190',
+'190,190,190,190,190,,,,,,,,,,190,,,190,190,190,190,190,190,190,190,190',
+'190,,190,190,,190,190,190,,,,,,,,,,,,,,,,,,,,190,,,190,,,190,190,,,190',
+',,,,,190,,,,,,,,190,,,,,190,190,190,190,190,190,,,,190,190,191,191,191',
+',191,,,,191,191,,,,191,,191,191,191,191,191,191,191,,,,,191,191,191',
+'191,191,191,191,,,,,,,,,,191,,,191,191,191,191,191,191,191,191,191,191',
+',191,191,,191,191,191,,,,,,,,,,,,,,,,,,,,191,,,191,,,191,191,,,191,',
+'191,,,,191,,,,,,,,191,,,,,191,191,191,191,191,191,,,,191,191,194,194',
+'194,,194,,,,194,194,,,,194,,194,194,194,194,194,194,194,,,,,194,194',
+'194,194,194,194,194,,,,,,,,,,194,,,194,194,194,194,194,194,194,194,194',
+'194,,194,194,,194,194,194,,,,,,,,,,,,,,,,,,,,194,,,194,,,194,194,,,194',
+',,,,,194,,,,,,,,194,,,,,194,194,194,194,194,194,,,,194,194,195,195,195',
+',195,,,,195,195,,,,195,,195,195,195,195,195,195,195,,,,,195,195,195',
+'195,195,195,195,,,195,,,,,,,195,,,195,195,195,195,195,195,195,195,195',
+'195,,195,195,,195,195,195,,,,,,,,,,,,,,,,,,,,195,,,195,,,195,195,,,195',
+',,,,,195,,,,,,,,195,,,,,195,195,195,195,195,195,,,,195,195,196,196,196',
+',196,,,,196,196,,,,196,,196,196,196,196,196,196,196,,,,,196,196,196',
+'196,196,196,196,,,196,,,,,,,196,,,196,196,196,196,196,196,196,196,196',
+'196,,196,196,,196,196,196,,,,,,,,,,,,,,,,,,,,196,,,196,,,196,196,,,196',
+',,,,,196,,,,,,,,196,,,,,196,196,196,196,196,196,,,,196,196,207,207,207',
+',207,,,,207,207,,,,207,,207,207,207,207,207,207,207,,,,,207,207,207',
+'207,207,207,207,,,,,,,,,,207,,,207,207,207,207,207,207,207,207,207,207',
+',207,207,,207,207,207,,,,,,,,,,,,,,,,,,,,207,,,207,,,207,207,,,207,',
+',,,,207,,,,,,,,207,,,,,207,207,207,207,207,207,,,,207,207,208,208,208',
+',208,,,,208,208,,,,208,,208,208,208,208,208,208,208,,,,,208,208,208',
+'208,208,208,208,,,,,,,,,,208,,,208,208,208,208,208,208,208,208,208,208',
+',208,208,,208,208,208,,,,,,,,,,,,,,,,,,,,208,,,208,,,208,208,,,208,',
+',,,,208,,,,,,,,208,,,,,208,208,208,208,208,208,,,,208,208,209,209,209',
+',209,,,,209,209,,,,209,,209,209,209,209,209,209,209,,,,,209,209,209',
+'209,209,209,209,,,,,,,,,,209,,,209,209,209,209,209,209,209,209,209,209',
+',209,209,,209,209,209,,,,,,,,,,,,,,,,,,,,209,,,209,,,209,209,,,209,',
+',,,,209,,,,,,,,209,,,,,209,209,209,209,209,209,,,,209,209,210,210,210',
+',210,,,,210,210,,,,210,,210,210,210,210,210,210,210,,,,,210,210,210',
+'210,210,210,210,,,,,,,,,,210,,,210,210,210,210,210,210,210,210,210,210',
+',210,210,,210,210,210,,,,,,,,,,,,,,,,,,,,210,,,210,,,210,210,,,210,',
+',,,,210,,,,,,,,210,,,,,210,210,210,210,210,210,,,,210,210,211,211,211',
+',211,,,,211,211,,,,211,,211,211,211,211,211,211,211,,,,,211,211,211',
+'211,211,211,211,,,,,,,,,,211,,,211,211,211,211,211,211,211,211,211,211',
+',211,211,,211,211,211,,,,,,,,,,,,,,,,,,,,211,,,211,,,211,211,,,211,',
+',,,,211,,,,,,,,211,,,,,211,211,211,211,211,211,,,,211,211,212,212,212',
+',212,,,,212,212,,,,212,,212,212,212,212,212,212,212,,,,,212,212,212',
+'212,212,212,212,,,,,,,,,,212,,,212,212,212,212,212,212,212,212,212,212',
+',212,212,,212,212,212,,,,,,,,,,,,,,,,,,,,212,,,212,,,212,212,,,212,',
+',,,,212,,,,,,,,212,,,,,212,212,212,212,212,212,,,,212,212,213,213,213',
+',213,,,,213,213,,,,213,,213,213,213,213,213,213,213,,,,,213,213,213',
+'213,213,213,213,,,,,,,,,,213,,,213,213,213,213,213,213,213,213,213,213',
+',213,213,,213,213,213,,,,,,,,,,,,,,,,,,,,213,,,213,,,213,213,,,213,',
+',,,,213,,,,,,,,213,,,,,213,213,213,213,213,213,,,,213,213,214,214,214',
+',214,,,,214,214,,,,214,,214,214,214,214,214,214,214,,,,,214,214,214',
+'214,214,214,214,,,,,,,,,,214,,,214,214,214,214,214,214,214,214,214,214',
+',214,214,,214,214,214,,,,,,,,,,,,,,,,,,,,214,,,214,,,214,214,,,214,',
+',,,,214,,,,,,,,214,,,,,214,214,214,214,214,214,,,,214,214,215,215,215',
+',215,,,,215,215,,,,215,,215,215,215,215,215,215,215,,,,,215,215,215',
+'215,215,215,215,,,,,,,,,,215,,,215,215,215,215,215,215,215,215,215,215',
+',215,215,,215,215,215,,,,,,,,,,,,,,,,,,,,215,,,215,,,215,215,,,215,',
+',,,,215,,,,,,,,215,,,,,215,215,215,215,215,215,,,,215,215,216,216,216',
+',216,,,,216,216,,,,216,,216,216,216,216,216,216,216,,,,,216,216,216',
+'216,216,216,216,,,,,,,,,,216,,,216,216,216,216,216,216,216,216,216,216',
+',216,216,,216,216,216,,,,,,,,,,,,,,,,,,,,216,,,216,,,216,216,,,216,',
+',,,,216,,,,,,,,216,,,,,216,216,216,216,216,216,,,,216,216,217,217,217',
+',217,,,,217,217,,,,217,,217,217,217,217,217,217,217,,,,,217,217,217',
+'217,217,217,217,,,,,,,,,,217,,,217,217,217,217,217,217,217,217,217,217',
+',217,217,,217,217,217,,,,,,,,,,,,,,,,,,,,217,,,217,,,217,217,,,217,',
+',,,,217,,,,,,,,217,,,,,217,217,217,217,217,217,,,,217,217,218,218,218',
+',218,,,,218,218,,,,218,,218,218,218,218,218,218,218,,,,,218,218,218',
+'218,218,218,218,,,,,,,,,,218,,,218,218,218,218,218,218,218,218,218,218',
+',218,218,,218,218,218,,,,,,,,,,,,,,,,,,,,218,,,218,,,218,218,,,218,',
+',,,,218,,,,,,,,218,,,,,218,218,218,218,218,218,,,,218,218,219,219,219',
+',219,,,,219,219,,,,219,,219,219,219,219,219,219,219,,,,,219,219,219',
+'219,219,219,219,,,,,,,,,,219,,,219,219,219,219,219,219,219,219,219,219',
+',219,219,,219,219,219,,,,,,,,,,,,,,,,,,,,219,,,219,,,219,219,,,219,',
+',,,,219,,,,,,,,219,,,,,219,219,219,219,219,219,,,,219,219,220,220,220',
+',220,,,,220,220,,,,220,,220,220,220,220,220,220,220,,,,,220,220,220',
+'220,220,220,220,,,,,,,,,,220,,,220,220,220,220,220,220,220,220,220,220',
+',220,220,,220,220,220,,,,,,,,,,,,,,,,,,,,220,,,220,,,220,220,,,220,',
+',,,,220,,,,,,,,220,,,,,220,220,220,220,220,220,,,,220,220,221,221,221',
+',221,,,,221,221,,,,221,,221,221,221,221,221,221,221,,,,,221,221,221',
+'221,221,221,221,,,,,,,,,,221,,,221,221,221,221,221,221,221,221,221,221',
+',221,221,,221,221,221,,,,,,,,,,,,,,,,,,,,221,,,221,,,221,221,,,221,',
+',,,,221,,,,,,,,221,,,,,221,221,221,221,221,221,,,,221,221,222,222,222',
+',222,,,,222,222,,,,222,,222,222,222,222,222,222,222,,,,,222,222,222',
+'222,222,222,222,,,,,,,,,,222,,,222,222,222,222,222,222,222,222,222,222',
+',222,222,,222,222,222,,,,,,,,,,,,,,,,,,,,222,,,222,,,222,222,,,222,',
+',,,,222,,,,,,,,222,,,,,222,222,222,222,222,222,,,,222,222,223,223,223',
+',223,,,,223,223,,,,223,,223,223,223,223,223,223,223,,,,,223,223,223',
+'223,223,223,223,,,,,,,,,,223,,,223,223,223,223,223,223,223,223,223,223',
+',223,223,,223,223,223,,,,,,,,,,,,,,,,,,,,223,,,223,,,223,223,,,223,',
+',,,,223,,,,,,,,223,,,,,223,223,223,223,223,223,,,,223,223,224,224,224',
+',224,,,,224,224,,,,224,,224,224,224,224,224,224,224,,,,,224,224,224',
+'224,224,224,224,,,,,,,,,,224,,,224,224,224,224,224,224,224,224,224,224',
+',224,224,,224,224,224,,,,,,,,,,,,,,,,,,,,224,,,224,,,224,224,,,224,',
+',,,,224,,,,,,,,224,,,,,224,224,224,224,224,224,,,,224,224,225,225,225',
+',225,,,,225,225,,,,225,,225,225,225,225,225,225,225,,,,,225,225,225',
+'225,225,225,225,,,,,,,,,,225,,,225,225,225,225,225,225,225,225,225,225',
+',225,225,,225,225,225,,,,,,,,,,,,,,,,,,,,225,,,225,,,225,225,,,225,',
+',,,,225,,,,,,,,225,,,,,225,225,225,225,225,225,,,,225,225,226,226,226',
+',226,,,,226,226,,,,226,,226,226,226,226,226,226,226,,,,,226,226,226',
+'226,226,226,226,,,,,,,,,,226,,,226,226,226,226,226,226,226,226,226,226',
+',226,226,,226,226,226,,,,,,,,,,,,,,,,,,,,226,,,226,,,226,226,,,226,',
+',,,,226,,,,,,,,226,,,,,226,226,226,226,226,226,,,,226,226,227,227,227',
+',227,,,,227,227,,,,227,,227,227,227,227,227,227,227,,,,,227,227,227',
+'227,227,227,227,,,,,,,,,,227,,,227,227,227,227,227,227,227,227,227,227',
+',227,227,,227,227,227,,,,,,,,,,,,,,,,,,,,227,,,227,,,227,227,,,227,',
+',,,,227,,,,,,,,227,,,,,227,227,227,227,227,227,,,,227,227,228,228,228',
+',228,,,,228,228,,,,228,,228,228,228,228,228,228,228,,,,,228,228,228',
+'228,228,228,228,,,,,,,,,,228,,,228,228,228,228,228,228,228,228,228,228',
+',228,228,,228,228,228,,,,,,,,,,,,,,,,,,,,228,,,228,,,228,228,,,228,',
+',,,,228,,,,,,,,228,,,,,228,228,228,228,228,228,,,,228,228,229,229,229',
+',229,,,,229,229,,,,229,,229,229,229,229,229,229,229,,,,,229,229,229',
+'229,229,229,229,,,,,,,,,,229,,,229,229,229,229,229,229,229,229,229,229',
+',229,229,,229,229,229,,,,,,,,,,,,,,,,,,,,229,,,229,,,229,229,,,229,',
+',,,,229,,,,,,,,229,,,,,229,229,229,229,229,229,,,,229,229,230,230,230',
+',230,,,,230,230,,,,230,,230,230,230,230,230,230,230,,,,,230,230,230',
+'230,230,230,230,,,,,,,,,,230,,,230,230,230,230,230,230,230,230,230,230',
+',230,230,,230,230,230,,,,,,,,,,,,,,,,,,,,230,,,230,,,230,230,,,230,',
+',,,,230,,,,,,,,230,,,,,230,230,230,230,230,230,,,,230,230,231,231,231',
+',231,,,,231,231,,,,231,,231,231,231,231,231,231,231,,,,,231,231,231',
+'231,231,231,231,,,,,,,,,,231,,,231,231,231,231,231,231,231,231,231,231',
+',231,231,,231,231,231,,,,,,,,,,,,,,,,,,,,231,,,231,,,231,231,,,231,',
+',,,,231,,,,,,,,231,,,,,231,231,231,231,231,231,,,,231,231,232,232,232',
+',232,,,,232,232,,,,232,,232,232,232,232,232,232,232,,,,,232,232,232',
+'232,232,232,232,,,,,,,,,,232,,,232,232,232,232,232,232,232,232,232,232',
+',232,232,,232,232,232,,,,,,,,,,,,,,,,,,,,232,,,232,,,232,232,,,232,',
+',,,,232,,,,,,,,232,,,,,232,232,232,232,232,232,,,,232,232,233,233,233',
+',233,,,,233,233,,,,233,,233,233,233,233,233,233,233,,,,,233,233,233',
+'233,233,233,233,,,,,,,,,,233,,,233,233,233,233,233,233,233,233,233,233',
+',233,233,,233,233,233,,,,,,,,,,,,,,,,,,,,233,,,233,,,233,233,,,233,',
+',,,,233,,,,,,,,233,,,,,233,233,233,233,233,233,,,,233,233,241,241,241',
+',241,,,,241,241,,,,241,,241,241,241,241,241,241,241,,,,,241,241,241',
+'241,241,241,241,,,,,,,,,,241,,,241,241,241,241,241,241,241,241,241,241',
+',241,241,,241,241,241,,,,,,,,,,,,,,,,,,,,241,,,241,,,241,241,,,241,',
+',,,,241,,,,,,,,241,,,,,241,241,241,241,241,241,,,,241,241,243,243,243',
+',243,,,,243,243,,,,243,,243,243,243,243,243,243,243,,,,,243,243,243',
+'243,243,243,243,,,,,,,,,,243,,,243,243,243,243,243,243,243,243,243,243',
+',243,243,,243,243,243,,,,,,,,,,,,,,,,,,,,243,,,243,,,243,243,,,243,',
+',,,,243,,,,,,,,243,,,,,243,243,243,243,243,243,,,,243,243,254,254,254',
+',254,,,,254,254,,,,254,,254,254,254,254,254,254,254,,,,,254,254,254',
+'254,254,254,254,,,,,,,,,,254,,,254,254,254,254,254,254,254,254,254,254',
+',254,254,,254,254,254,,,,,,,,,,,,,,,,,,,,254,,,254,,,254,254,,,254,',
+'254,,254,,254,,,,,,,,254,,,,,254,254,254,254,254,254,,,,254,254,255',
+'255,255,,255,,,,255,255,,,,255,,255,255,255,255,255,255,255,,,,,255',
+'255,255,255,255,255,255,,,,,,,,,,255,,,255,255,255,255,255,255,255,255',
+'255,255,,255,255,,255,255,255,,,,,,,,,,,,,,,,,,,,255,,,255,,,255,255',
+',,255,,255,,255,,255,,,,,,,,255,,,,,255,255,255,255,255,255,,,,255,255',
+'263,263,263,,263,,,,263,263,,,,263,,263,263,263,263,263,263,263,,,,',
+'263,263,263,263,263,263,263,,,,,,,,,,263,,,263,263,263,263,263,263,263',
+'263,263,263,,263,263,,263,263,263,,,,,,,,,,,,,,,,,,,,263,,,263,,263',
+'263,263,,,263,,263,,263,,263,,,,,,,,263,,,,,263,263,263,263,263,263',
+',,,263,263,269,269,269,,269,,,,269,269,,,,269,,269,269,269,269,269,269',
+'269,,,,,269,269,269,269,269,269,269,,,,,,,,,,269,,,269,269,269,269,269',
+'269,269,269,269,269,,269,269,,,,269,,468,468,468,468,468,468,468,468',
+'468,468,468,,468,468,,,468,468,269,,,269,,,269,269,,,269,,,,468,,468',
+',468,468,468,468,468,468,468,,468,,,269,269,269,269,269,269,,,,269,269',
+'290,290,290,468,290,,,,290,290,,,,290,,290,290,290,290,290,290,290,',
+',,,290,290,290,290,290,290,290,,,,,,,,,,290,,,290,290,290,290,290,290',
+'290,290,290,290,,290,290,,290,290,290,,,,,,,,,,,,,,,,,,,,290,,,290,290',
+',290,290,,,290,,,,,,290,,,,,,,,290,,,,,290,290,290,290,290,290,,,,290',
+'290,299,299,299,,299,,,,299,299,,,,299,,299,299,299,299,299,299,299',
+',,,,299,299,299,299,299,299,299,,,,,,,,,,299,,,299,299,299,299,299,299',
+'299,299,299,299,,299,299,,299,299,299,,,,,,,,,,,,,,,,,,,,299,,,299,',
+',299,299,,,299,,,,,,299,,,,,,,,299,,,,,299,299,299,299,299,299,,,,299',
'299,308,308,308,,308,,,,308,308,,,,308,,308,308,308,308,308,308,308',
',,,,308,308,308,308,308,308,308,,,308,,,,,,,308,,,308,308,308,308,308',
'308,308,308,308,308,,308,308,,308,308,308,,,,,,,,,,,,,,,,,,,,308,,,308',
@@ -1307,10 +1303,14 @@ clist = [
'357,357,357,357,357,357,357,357,,,357,357,357,357,357,357,357,357,357',
'357,,,,,,357,357,357,357,357,357,357,357,,,357,,,,,,,,357,357,,357,357',
'357,357,,357,357,,,357,,,,,357,357,357,357,,,,,,,,,,,,,,357,357,,357',
-'357,357,357,357,357,357,357,357,,357,,,357,357,,,378,378,378,,378,,',
-'357,378,378,,,,378,,378,378,378,378,378,378,378,,,,,378,378,378,378',
-'378,378,378,,,,,,,,,,378,,,378,378,378,378,378,378,378,378,378,378,',
-'378,378,,378,378,378,,,,,,,,,,,,,,,,,,,,378,,,378,378,,378,378,,,378',
+'357,357,357,357,357,357,357,357,,357,,,357,357,,,369,369,369,,369,,',
+'357,369,369,,,,369,,369,369,369,369,369,369,369,,,,,369,369,369,369',
+'369,369,369,,,,,,,,,,369,,,369,369,369,369,369,369,369,369,369,369,',
+'369,369,,369,369,369,,,,,,,,,,,,,,,,,,,,369,,,369,,,369,369,,,369,,',
+',,,369,,,,,,,,369,,,,,369,369,369,369,369,369,,,,369,369,378,378,378',
+',378,,,,378,378,,,,378,,378,378,378,378,378,378,378,,,,,378,378,378',
+'378,378,378,378,,,,,,,,,,378,,,378,378,378,378,378,378,378,378,378,378',
+',378,378,,378,378,378,,,,,,,,,,,,,,,,,,,,378,,,378,378,,378,378,,,378',
',378,,378,,378,,,,,,,,378,,,,,378,378,378,378,378,378,,,,378,378,385',
'385,385,,385,,,,385,385,,,,385,,385,385,385,385,385,385,385,,,,,385',
'385,385,385,385,385,385,,,,,,,,,,385,,,385,385,385,385,385,385,385,385',
@@ -1491,9 +1491,9 @@ clist = [
',,,,692,,,,,,,,692,,,,,692,692,692,692,692,692,,,,692,692,698,698,698',
',698,,,,698,698,,,,698,,698,698,698,698,698,698,698,,,,,698,698,698',
'698,698,698,698,,,,,,,,,,698,,,698,698,698,698,698,698,698,698,698,698',
-',698,698,,,,698,,694,694,694,694,694,694,694,694,694,694,694,,694,694',
-',,694,694,698,,,698,,,698,698,,,698,,,,694,,694,,694,694,694,694,694',
-'694,694,,694,,,698,698,698,698,698,698,,,,698,698,704,704,704,694,704',
+',698,698,,,,698,,600,600,600,600,600,600,600,600,600,600,600,,600,600',
+',,600,600,698,,,698,,,698,698,,,698,,,,600,,600,,600,600,600,600,600',
+'600,600,,600,,,698,698,698,698,698,698,,,,698,698,704,704,704,600,704',
',,,704,704,,,,704,,704,704,704,704,704,704,704,,,,,704,704,704,704,704',
'704,704,,,,,,,,,,704,,,704,704,704,704,704,704,704,704,704,704,,704',
'704,,704,704,704,,,,,,,,,,,,,,,,,,,,704,,,704,,,704,704,,,704,,704,',
@@ -1508,10 +1508,10 @@ clist = [
',,715,,715,,715,,715,,,,,,,,715,,,,,715,715,715,715,715,715,,,,715,715',
'728,728,728,,728,,,,728,728,,,,728,,728,728,728,728,728,728,728,,,,',
'728,728,728,728,728,728,728,,,,,,,,,,728,,,728,728,728,728,728,728,728',
-'728,728,728,,728,728,,,,728,,767,767,767,767,767,767,767,767,767,767',
-'767,,767,767,,,767,767,728,,,728,,,728,728,,,728,,,,767,,767,,767,767',
-'767,767,767,767,767,,767,,,728,728,728,728,728,728,,,,728,728,734,734',
-'734,767,734,,,,734,734,,,,734,,734,734,734,734,734,734,734,,,,,734,734',
+'728,728,728,,728,728,,,,728,,677,677,677,677,677,677,677,677,677,677',
+'677,,677,677,,,677,677,728,,,728,,,728,728,,,728,,,,677,,677,,677,677',
+'677,677,677,677,677,,677,,,728,728,728,728,728,728,,,,728,728,734,734',
+'734,677,734,,,,734,734,,,,734,,734,734,734,734,734,734,734,,,,,734,734',
'734,734,734,734,734,,,734,,,,,,,734,,,734,734,734,734,734,734,734,734',
'734,734,,734,734,,734,734,734,,,,,,,,,,,,,,,,,,,,734,,,734,,,734,734',
',,734,,,,,,734,,,,,,,,734,,,,,734,734,734,734,734,734,,,,734,734,740',
@@ -1549,18 +1549,18 @@ clist = [
',,802,,,,,,802,,,,,,,,802,,,,,802,802,802,802,802,802,,,,802,802,820',
'820,820,,820,,,,820,820,,,,820,,820,820,820,820,820,820,820,,,,,820',
'820,820,820,820,820,820,,,,,,,,,,820,,,820,820,820,820,820,820,820,820',
-'820,820,,820,820,,,,820,,600,600,600,600,600,600,600,600,600,600,600',
-',600,600,,,600,600,820,,,820,,,820,820,,,820,,,,600,,600,,600,600,600',
-'600,600,600,600,,600,,,820,820,820,820,820,820,,,,820,820,822,822,822',
-'600,822,,,,822,822,,,,822,,822,822,822,822,822,822,822,,,,,822,822,822',
+'820,820,,820,820,,,,820,,682,682,682,682,682,682,682,682,682,682,682',
+',682,682,,,682,682,820,,,820,,,820,820,,,820,,,,682,,682,,682,682,682',
+'682,682,682,682,,682,,,820,820,820,820,820,820,,,,820,820,822,822,822',
+'682,822,,,,822,822,,,,822,,822,822,822,822,822,822,822,,,,,822,822,822',
'822,822,822,822,,,,,,,,,,822,,,822,822,822,822,822,822,822,822,822,822',
',822,822,,822,822,822,,,,,,,,,,,,,,,,,,,,822,,,822,,,822,822,,,822,',
'822,,,,822,,,,,,,,822,,,,,822,822,822,822,822,822,,,,822,822,827,827',
'827,,827,,,,827,827,,,,827,,827,827,827,827,827,827,827,,,,,827,827',
'827,827,827,827,827,,,,,,,,,,827,,,827,827,827,827,827,827,827,827,827',
-'827,,827,827,,,,827,,388,388,388,388,388,388,388,388,388,388,388,,388',
-'388,,,388,388,827,,,827,,,827,827,,,827,,,,388,,388,,388,388,388,388',
-'388,388,388,,388,,,827,827,827,827,827,827,,,,827,827,832,832,832,388',
+'827,,827,827,,,,827,,684,684,684,684,684,684,684,684,684,684,684,,684',
+'684,,,684,684,827,,,827,,,827,827,,,827,,,,684,,684,,684,684,684,684',
+'684,684,684,,684,,,827,827,827,827,827,827,,,,827,827,832,832,832,684',
'832,,,,832,832,,,,832,,832,832,832,832,832,832,832,,,,,832,832,832,832',
'832,832,832,,,,,,,,,,832,,,832,832,832,832,832,832,832,832,832,832,',
'832,832,,832,832,832,,,,,,,,,,,,,,,,,,,,832,,,832,,,832,832,,,832,,832',
@@ -1571,10 +1571,10 @@ clist = [
',835,,835,,835,,,,,,,,835,,,,,835,835,835,835,835,835,,,,835,835,861',
'861,861,,861,,,,861,861,,,,861,,861,861,861,861,861,861,861,,,,,861',
'861,861,861,861,861,861,,,,,,,,,,861,,,861,861,861,861,861,861,861,861',
-'861,861,,861,861,,,,861,,237,237,237,237,237,237,237,237,237,237,237',
-',237,237,,,237,237,861,,,861,,,861,861,,,861,,,,237,,237,,237,237,237',
-'237,237,237,237,,237,,,861,861,861,861,861,861,,,,861,861,864,864,864',
-'237,864,,,,864,864,,,,864,,864,864,864,864,864,864,864,,,,,864,864,864',
+'861,861,,861,861,,,,861,,687,687,687,687,687,687,687,687,687,687,687',
+',687,687,,,687,687,861,,,861,,,861,861,,,861,,,,687,,687,,687,687,687',
+'687,687,687,687,,687,,,861,861,861,861,861,861,,,,861,861,864,864,864',
+'687,864,,,,864,864,,,,864,,864,864,864,864,864,864,864,,,,,864,864,864',
'864,864,864,864,,,,,,,,,,864,,,864,864,864,864,864,864,864,864,864,864',
',864,864,,864,864,864,,,,,,,,,,,,,,,,,,,,864,,,864,,,864,864,,,864,',
',,,,864,,,,,,,,864,,,,,864,864,864,864,864,864,,,,864,864,867,867,867',
@@ -1584,79 +1584,79 @@ clist = [
',,,,867,,,,,,,,867,,,,,867,867,867,867,867,867,,,,867,867,875,875,875',
',875,,,,875,875,,,,875,,875,875,875,875,875,875,875,,,,,875,875,875',
'875,875,875,875,,,,,,,,,,875,,,875,875,875,875,875,875,875,875,875,875',
-',875,875,,,,875,,677,677,677,677,677,677,677,677,677,677,677,,677,677',
-',,677,677,875,,,875,,,875,875,,,875,,,,677,,677,,677,677,677,677,677',
-'677,677,,677,,,875,875,875,875,875,875,,,,875,875,880,880,880,677,880',
+',875,875,,,,875,,689,689,689,689,689,689,689,689,689,689,689,,689,689',
+',,689,689,875,,,875,,,875,875,,,875,,,,689,,689,,689,689,689,689,689',
+'689,689,,689,,,875,875,875,875,875,875,,,,875,875,880,880,880,689,880',
',,,880,880,,,,880,,880,880,880,880,880,880,880,,,,,880,880,880,880,880',
'880,880,,,,,,,,,,880,,,880,880,880,880,880,880,880,880,880,880,,880',
'880,,880,880,880,,,,,,,,,,,,,,,,,,,,880,,,880,,,880,880,,,880,,880,',
'880,,880,,,,,,,,880,,,,,880,880,880,880,880,880,,,,880,880,886,886,886',
',886,,,,886,886,,,,886,,886,886,886,886,886,886,886,,,,,886,886,886',
'886,886,886,886,,,,,,,,,,886,,,886,886,886,886,886,886,886,886,886,886',
-',886,886,,,,886,,19,19,19,19,19,19,19,19,19,19,19,,19,19,,,19,19,886',
-',,886,,,886,886,,,886,,,,19,,19,,19,19,19,19,19,19,19,,19,,,886,886',
-'886,886,886,886,,,,886,886,889,889,889,19,889,,,,889,889,,,,889,,889',
-'889,889,889,889,889,889,,,,,889,889,889,889,889,889,889,,,,,,,,,,889',
-',,889,889,889,889,889,889,889,889,889,889,,889,889,,889,889,889,,,,',
-',,,,,,,,,,,,,,,889,,,889,,,889,889,,,889,,,,,,889,,,,,,,,889,,,,,889',
-'889,889,889,889,889,,,,889,889,64,64,64,64,64,64,64,64,64,64,64,64,64',
-'64,64,64,64,64,64,64,64,64,64,64,,,64,64,64,64,64,64,64,64,64,64,,,',
-',,64,64,64,64,64,64,64,64,64,64,64,64,,,,,,,64,64,,64,64,64,64,,64,64',
-',,64,,,,,64,64,64,64,,,,,,64,,,,,,,,64,64,,64,64,64,64,64,64,64,64,64',
-',64,,,64,664,664,664,664,664,664,664,664,664,664,664,664,664,664,664',
-'664,664,664,664,664,664,664,664,664,,,664,664,664,664,664,664,664,664',
-'664,664,,,,,,664,664,664,664,664,664,664,664,,,664,,,,,,,,664,664,,664',
-'664,664,664,,664,664,,,664,,,,,664,664,664,664,,,,,,,,,,,,,,664,664',
-',664,664,664,664,664,664,664,664,664,,664,,,664,581,581,581,581,581',
-'581,581,581,581,581,581,,581,581,,,581,581,,,,581,,,,,,,,,,,581,,581',
-',581,581,581,581,581,581,581,,581,,,,,,,,505,505,,,505,,,,,581,,581',
-'505,505,,505,505,505,505,,505,505,,,505,,,,,505,505,505,505,,,,,,,,',
-',,,,,505,505,,505,505,505,505,505,505,505,505,505,,505,507,507,505,',
-'507,,,,,,,,507,507,,507,507,507,507,,507,507,,,507,,,,,507,507,507,507',
-',,,,,,,,,,,,,507,507,,507,507,507,507,507,507,507,507,507,,507,499,499',
-'507,,499,,,,,,,,499,499,,499,499,499,499,,499,499,,,499,,,,,499,499',
-'499,499,,,,,,,,,,,,,,499,499,,499,499,499,499,499,499,499,499,499,,499',
-'498,498,499,,498,,,,,,,,498,498,,498,498,498,498,,498,498,,,498,,,,',
-'498,498,498,498,,,,,,,,,,,,,,498,498,,498,498,498,498,498,498,498,498',
-'498,,498,466,466,498,,466,,,,,,,,466,466,,466,466,466,466,,466,466,',
-',466,,,,,466,466,466,466,,,,,,,,,,,,,,466,466,,466,466,466,466,466,466',
-'466,466,466,,466,251,251,466,,251,,,,,,,,251,251,,251,251,251,251,,251',
-'251,,,251,,,,,251,251,251,251,,,,,,,,,,,,,,251,251,,251,251,251,251',
-'251,251,251,251,251,,251,252,252,251,,252,,,,,,,,252,252,,252,252,252',
-'252,,252,252,,,252,,,,,252,252,252,252,,,,,,,,,,,,,,252,252,,252,252',
-'252,252,252,252,252,252,252,,252,,,252,423,423,423,423,423,423,423,423',
-'423,423,423,,423,423,,,423,423,,,,,,,,,,,,,,,423,,423,,423,423,423,423',
-'423,423,423,,423,,,,,,,467,467,,,467,,,,,,423,423,467,467,,467,467,467',
-'467,,467,467,,,467,,,,,467,467,467,467,,,,,,,,,,,,,,467,467,,467,467',
-'467,467,467,467,467,467,467,,467,192,192,467,,192,,,,,,,,192,192,,192',
-'192,192,192,,192,192,,,192,,,,,192,192,192,192,,,,,,,,,,,,,,192,192',
-',192,192,192,192,192,192,192,192,192,,192,823,823,192,,823,,,,,,,,823',
-'823,,823,823,823,823,,823,823,,,823,,,,,823,823,823,823,,,,,,,,,,,,',
-',823,823,,823,823,823,823,823,823,823,823,823,,823,458,458,823,,458',
+',886,886,,,,886,,694,694,694,694,694,694,694,694,694,694,694,,694,694',
+',,694,694,886,,,886,,,886,886,,,886,,,,694,,694,,694,694,694,694,694',
+'694,694,,694,,,886,886,886,886,886,886,,,,886,886,889,889,889,694,889',
+',,,889,889,,,,889,,889,889,889,889,889,889,889,,,,,889,889,889,889,889',
+'889,889,,,,,,,,,,889,,,889,889,889,889,889,889,889,889,889,889,,889',
+'889,,889,889,889,,,,,,,,,,,,,,,,,,,,889,,,889,,,889,889,,,889,,,,,,889',
+',,,,,,,889,,,,,889,889,889,889,889,889,,,,889,889,64,64,64,64,64,64',
+'64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,,,64,64,64,64',
+'64,64,64,64,64,64,,,,,,64,64,64,64,64,64,64,64,64,64,64,64,,,,,,,64',
+'64,,64,64,64,64,,64,64,,,64,,,,,64,64,64,64,,,,,,64,,,,,,,,64,64,,64',
+'64,64,64,64,64,64,64,64,,64,,,64,664,664,664,664,664,664,664,664,664',
+'664,664,664,664,664,664,664,664,664,664,664,664,664,664,664,,,664,664',
+'664,664,664,664,664,664,664,664,,,,,,664,664,664,664,664,664,664,664',
+',,664,,,,,,,,664,664,,664,664,664,664,,664,664,,,664,,,,,664,664,664',
+'664,,,,,,,,,,,,,,664,664,,664,664,664,664,664,664,664,664,664,,664,',
+',664,581,581,581,581,581,581,581,581,581,581,581,,581,581,,,581,581',
+',,,581,,,,,,,,,,,581,,581,,581,581,581,581,581,581,581,,581,,,,,,,,192',
+'192,,,192,,,,,581,,581,192,192,,192,192,192,192,,192,192,,,192,,,,,192',
+'192,192,192,,,,,,,,,,,,,,192,192,,192,192,192,192,192,192,192,192,192',
+',192,193,193,192,,193,,,,,,,,193,193,,193,193,193,193,,193,193,,,193',
+',,,,193,193,193,193,,,,,,,,,,,,,,193,193,,193,193,193,193,193,193,193',
+'193,193,,193,251,251,193,,251,,,,,,,,251,251,,251,251,251,251,,251,251',
+',,251,,,,,251,251,251,251,,,,,,,,,,,,,,251,251,,251,251,251,251,251',
+'251,251,251,251,,251,252,252,251,,252,,,,,,,,252,252,,252,252,252,252',
+',252,252,,,252,,,,,252,252,252,252,,,,,,,,,,,,,,252,252,,252,252,252',
+'252,252,252,252,252,252,,252,391,391,252,,391,,,,,,,,391,391,,391,391',
+'391,391,,391,391,,,391,,,,,391,391,391,391,,,,,,,,,,,,,,391,391,,391',
+'391,391,391,391,391,391,391,391,,391,392,392,391,,392,,,,,,,,392,392',
+',392,392,392,392,,392,392,,,392,,,,,392,392,392,392,,,,,,,,,,,,,,392',
+'392,,392,392,392,392,392,392,392,392,392,,392,,,392,423,423,423,423',
+'423,423,423,423,423,423,423,,423,423,,,423,423,,,,,,,,,,,,,,,423,,423',
+',423,423,423,423,423,423,423,,423,,,,,,,457,457,,,457,,,,,,423,423,457',
+'457,,457,457,457,457,,457,457,,,457,,,,,457,457,457,457,,,,,,,,,,,,',
+',457,457,,457,457,457,457,457,457,457,457,457,,457,458,458,457,,458',
',,,,,,,458,458,,458,458,458,458,,458,458,,,458,,,,,458,458,458,458,',
-',,,,,,,,,,,,458,458,,458,458,458,458,458,458,458,458,458,,458,824,824',
-'458,,824,,,,,,,,824,824,,824,824,824,824,,824,824,,,824,,,,,824,824',
-'824,824,,,,,,,,,,,,,,824,824,,824,824,824,824,824,824,824,824,824,,824',
-'457,457,824,,457,,,,,,,,457,457,,457,457,457,457,,457,457,,,457,,,,',
-'457,457,457,457,,,,,,,,,,,,,,457,457,,457,457,457,457,457,457,457,457',
-'457,,457,391,391,457,,391,,,,,,,,391,391,,391,391,391,391,,391,391,',
-',391,,,,,391,391,391,391,,,,,,,,,,,,,,391,391,,391,391,391,391,391,391',
-'391,391,391,,391,392,392,391,,392,,,,,,,,392,392,,392,392,392,392,,392',
-'392,,,392,,,,,392,392,392,392,,,,,,,,,,,,,,392,392,,392,392,392,392',
-'392,392,392,392,392,,392,578,578,392,,578,,,,,,,,578,578,,578,578,578',
-'578,,578,578,,,578,,,,,578,578,578,578,,,,,,,,,,,,,,578,578,,578,578',
-'578,578,578,578,578,578,578,,578,193,193,578,,193,,,,,,,,193,193,,193',
-'193,193,193,,193,193,,,193,,,,,193,193,193,193,,,,,,,,,,,,,,193,193',
-',193,193,193,193,193,193,193,193,193,,193,579,579,193,,579,,,,,,,,579',
-'579,,579,579,579,579,,579,579,,,579,,,,,579,579,579,579,,,,,,,,,,,,',
-',579,579,,579,579,579,579,579,579,579,579,579,,579,,,579,480,480,480',
-'480,480,480,480,480,480,480,480,,480,480,,,480,480,,,,,,,,,,,,,,,480',
-',480,,480,480,480,480,480,480,480,,480,,731,731,731,731,731,731,731',
-'731,731,731,731,,731,731,480,480,731,731,,,,,,,,,,,,,,,731,,731,,731',
-'731,731,731,731,731,731,,731,,682,682,682,682,682,682,682,682,682,682',
-'682,,682,682,731,731,682,682,,,,,,,,,,,,,,,682,,682,,682,682,682,682',
-'682,682,682,,682,,,,,,,,,,,,,,,,,682' ]
- racc_action_check = arr = ::Array.new(24362, nil)
+',,,,,,,,,,,,458,458,,458,458,458,458,458,458,458,458,458,,458,466,466',
+'458,,466,,,,,,,,466,466,,466,466,466,466,,466,466,,,466,,,,,466,466',
+'466,466,,,,,,,,,,,,,,466,466,,466,466,466,466,466,466,466,466,466,,466',
+'467,467,466,,467,,,,,,,,467,467,,467,467,467,467,,467,467,,,467,,,,',
+'467,467,467,467,,,,,,,,,,,,,,467,467,,467,467,467,467,467,467,467,467',
+'467,,467,498,498,467,,498,,,,,,,,498,498,,498,498,498,498,,498,498,',
+',498,,,,,498,498,498,498,,,,,,,,,,,,,,498,498,,498,498,498,498,498,498',
+'498,498,498,,498,499,499,498,,499,,,,,,,,499,499,,499,499,499,499,,499',
+'499,,,499,,,,,499,499,499,499,,,,,,,,,,,,,,499,499,,499,499,499,499',
+'499,499,499,499,499,,499,505,505,499,,505,,,,,,,,505,505,,505,505,505',
+'505,,505,505,,,505,,,,,505,505,505,505,,,,,,,,,,,,,,505,505,,505,505',
+'505,505,505,505,505,505,505,,505,507,507,505,,507,,,,,,,,507,507,,507',
+'507,507,507,,507,507,,,507,,,,,507,507,507,507,,,,,,,,,,,,,,507,507',
+',507,507,507,507,507,507,507,507,507,,507,578,578,507,,578,,,,,,,,578',
+'578,,578,578,578,578,,578,578,,,578,,,,,578,578,578,578,,,,,,,,,,,,',
+',578,578,,578,578,578,578,578,578,578,578,578,,578,579,579,578,,579',
+',,,,,,,579,579,,579,579,579,579,,579,579,,,579,,,,,579,579,579,579,',
+',,,,,,,,,,,,579,579,,579,579,579,579,579,579,579,579,579,,579,823,823',
+'579,,823,,,,,,,,823,823,,823,823,823,823,,823,823,,,823,,,,,823,823',
+'823,823,,,,,,,,,,,,,,823,823,,823,823,823,823,823,823,823,823,823,,823',
+'824,824,823,,824,,,,,,,,824,824,,824,824,824,824,,824,824,,,824,,,,',
+'824,824,824,824,,,,,,,,,,,,,,824,824,,824,824,824,824,824,824,824,824',
+'824,,824,,,824,480,480,480,480,480,480,480,480,480,480,480,,480,480',
+',,480,480,,,,,,,,,,,,,,,480,,480,,480,480,480,480,480,480,480,,480,',
+'731,731,731,731,731,731,731,731,731,731,731,,731,731,480,480,731,731',
+',,,,,,,,,,,,,,731,,731,,731,731,731,731,731,731,731,,731,,767,767,767',
+'767,767,767,767,767,767,767,767,,767,767,731,731,767,767,,,,,,,,,,,',
+',,,767,,767,,767,767,767,767,767,767,767,,767,,,,,,,,,,,,,,,,,767' ]
+ racc_action_check = arr = ::Array.new(24340, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -1666,17 +1666,17 @@ clist = [
end
racc_action_pointer = [
- 2597, 995, nil, 191, 885, 4913, 5034, 5155, 604, 516,
- 951, 917, 948, 386, 141, 413, nil, 5268, 5389, 22556,
- 885, nil, 5510, 5631, 5752, 350, 171, 5873, 5994, nil,
- 1255, 6115, 6236, nil, 690, 183, 730, 446, 6357, 6478,
- 6599, 604, 399, nil, nil, nil, nil, nil, nil, nil,
- 291, 3207, 6720, 6841, 6962, 2, 7083, 7204, nil, nil,
- 757, 7325, 7446, 7567, 22797, nil, nil, nil, nil, nil,
- -87, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 7688, nil, nil, nil, 7809, nil, nil, nil,
- nil, nil, nil, nil, nil, 643, nil, 885, nil, nil,
- nil, 7930, 8051, 8172, 8293, 8414, 1036, nil, 593, nil,
+ 1233, 30, nil, -98, 863, 4770, 4891, 5012, -53, 2,
+ 71, 90, 160, 218, 174, 130, nil, 5125, 5246, 6094,
+ 234, nil, 5367, 5488, 5609, 292, 138, 5730, 5851, nil,
+ 1355, 5972, 6093, nil, 146, 316, 245, 346, 6214, 6335,
+ 6456, 183, 300, nil, nil, nil, nil, nil, nil, nil,
+ 214, 1477, 6577, 6698, 6819, 58, 6940, 7061, nil, nil,
+ 735, 7182, 7303, 7424, 22775, nil, nil, nil, nil, nil,
+ -92, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 7545, nil, nil, nil, 7666, nil, nil, nil,
+ nil, nil, nil, nil, nil, 311, nil, 863, nil, nil,
+ nil, 7787, 7908, 8029, 8150, 8271, 981, nil, 221, 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, nil, nil, nil,
@@ -1684,78 +1684,78 @@ racc_action_pointer = [
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, nil, nil,
- nil, nil, nil, nil, 161, nil, 1865, 1987, 8535, 8656,
- 8777, 8898, 23556, 24036, 9019, 9140, 9261, nil, 819, -67,
- 1010, -33, 832, 885, 3085, nil, nil, 9382, 9503, 9624,
- 9745, 9866, 9987, 10108, 10229, 10350, 10471, 10592, 10713, 10834,
- 10955, 11076, 11197, 11318, 11439, 11560, 11681, 11802, 11923, 12044,
- 12165, 12286, 12407, 12528, nil, nil, nil, 21951, nil, 906,
- 919, 12649, nil, 12770, 963, nil, nil, nil, nil, nil,
- nil, 23322, 23382, 955, 12891, 13012, nil, nil, nil, nil,
- nil, nil, nil, 13133, 964, 2963, 979, 991, 953, 13254,
- 2841, 424, 512, 1031, 559, 998, 962, 161, nil, 1000,
- 481, nil, nil, 189, 1024, 1026, 636, nil, 1027, nil,
- 13375, nil, 1087, 1088, 515, nil, 977, -79, 212, 13496,
- 1017, 187, 1001, -38, nil, 571, 10, 31, 13617, 13738,
- 343, 338, 983, 23, 680, 1060, 4, 1100, nil, nil,
- 260, 199, 355, nil, 801, nil, 9, 13859, nil, nil,
- 327, 259, 88, -29, -51, 348, 478, 441, nil, 396,
- nil, 13980, nil, 327, 323, 230, 226, -37, 203, nil,
- 1003, nil, nil, nil, nil, nil, nil, 14101, nil, nil,
- nil, nil, -54, -32, nil, nil, 757, nil, 39, 4792,
- nil, 102, nil, nil, 7568, 180, 179, 134, 14214, nil,
- nil, 107, 191, 0, nil, 14335, 14456, nil, 21588, nil,
- nil, 23856, 23916, 14577, 115, 14698, 14819, 14940, 1987, 1865,
- 358, 355, 248, 261, 273, 289, 2963, 2841, 2719, 1621,
- 1743, 2353, 1499, 1002, 2109, 515, 2475, 2597, 2231, 490,
- 400, 636, 885, 23430, -51, nil, 15061, nil, 15182, 261,
- nil, 15303, 214, nil, nil, 398, nil, nil, 343, 328,
- -63, 364, 466, nil, nil, 15424, -54, 95, 419, nil,
- 432, 404, nil, nil, nil, 464, 15545, 23796, 23676, 888,
- 485, nil, nil, 15666, 15787, 15908, 23262, 23496, 6237, 16029,
- 610, 16150, nil, 502, nil, nil, 16271, nil, nil, 16392,
- 24144, nil, 16513, nil, nil, nil, 4671, 640, nil, nil,
- 4305, 115, 133, 644, 652, 4183, 16634, 16755, 23202, 23142,
- 26, nil, nil, 299, nil, 23022, 16876, 23082, nil, nil,
- 16997, 549, -34, 3573, 1306, nil, nil, nil, -32, nil,
- nil, nil, 741, nil, nil, nil, 551, nil, 147, nil,
- nil, 547, nil, nil, 17118, nil, nil, 17231, 17352, nil,
- 149, 17473, 17594, 602, nil, nil, 17715, 618, nil, 17836,
- 198, 154, 636, 515, 653, 1128, 17957, 18078, nil, 2231,
- 18199, 620, nil, 669, 18320, nil, 671, nil, 667, nil,
- nil, nil, nil, nil, 171, nil, 677, 681, 23976, 24096,
- 18441, 22955, 79, 646, 18562, nil, 694, nil, 2109, 1743,
- nil, -34, nil, 692, 38, 63, 711, 378, 885, 713,
- 21346, 738, 739, -3, 806, nil, 1621, 709, 756, nil,
- nil, 757, 18683, nil, nil, 206, nil, 835, nil, nil,
- nil, nil, nil, 843, nil, 845, 739, 32, 18804, 776,
- 1, -18, 25, 75, 18925, 401, 407, nil, 785, 4061,
- 548, nil, nil, 871, 3939, 460, 547, 758, 766, 770,
- nil, nil, nil, nil, nil, 768, nil, nil, nil, nil,
- 850, nil, nil, 860, 22907, 823, nil, nil, nil, nil,
- nil, 3451, nil, nil, nil, nil, nil, 22314, 793, 19046,
- 19167, nil, 24236, nil, 7447, nil, nil, 13255, nil, 7326,
- 19288, 19409, 19530, 70, 19652, nil, 834, 1128, 19651, nil,
- 871, 973, 867, nil, 19772, 869, 2475, nil, nil, 916,
- 917, -45, 978, 19893, nil, 20014, 888, nil, 930, 909,
- 1011, 353, nil, nil, 2353, nil, nil, 11, 20135, nil,
- nil, 24190, 1021, nil, 20256, 1022, 1499, 1377, nil, nil,
- 20377, 4549, nil, -9, 68, nil, 1042, nil, 4427, nil,
- 1084, 983, nil, 1428, nil, 197, nil, nil, 444, 20498,
- nil, nil, nil, nil, 811, nil, nil, 20136, 20619, 20740,
- 760, 882, 244, 295, 248, 281, nil, nil, nil, nil,
- 20861, nil, 385, 473, 448, nil, 20982, 473, 21103, nil,
- nil, nil, nil, nil, 3817, nil, nil, nil, -7, nil,
- 624, 626, 21224, 413, nil, nil, 653, nil, 575, 552,
- 554, nil, nil, 555, 563, nil, nil, 1019, nil, nil,
- 21345, 1006, 21466, 23616, 23736, 639, 673, 21587, 6116, nil,
- nil, nil, 21708, 748, nil, 21829, 815, 938, 3695, nil,
- nil, nil, nil, nil, nil, 3329, nil, nil, -38, nil,
- nil, nil, 2719, nil, 884, 916, 930, 160, 388, 375,
- 757, 21950, nil, nil, 22071, 470, nil, 22192, nil, nil,
- 515, 698, 619, 772, 770, 22313, 633, nil, 294, nil,
- 22434, -98, nil, nil, nil, nil, 22555, nil, nil, 22676,
- nil, nil, 482, nil ]
+ nil, nil, nil, nil, 196, nil, 1599, 1721, 8392, 8513,
+ 8634, 8755, 23000, 23060, 8876, 8997, 9118, nil, 377, -67,
+ 279, -52, 212, 274, 1843, nil, nil, 9239, 9360, 9481,
+ 9602, 9723, 9844, 9965, 10086, 10207, 10328, 10449, 10570, 10691,
+ 10812, 10933, 11054, 11175, 11296, 11417, 11538, 11659, 11780, 11901,
+ 12022, 12143, 12264, 12385, nil, nil, nil, 7183, nil, 242,
+ 254, 12506, nil, 12627, 310, nil, nil, nil, nil, nil,
+ nil, 23120, 23180, 313, 12748, 12869, nil, nil, nil, nil,
+ nil, nil, nil, 12990, 325, 1965, 333, 352, 315, 13111,
+ 2087, 399, 496, 430, 520, 411, 382, 161, nil, 443,
+ 430, nil, nil, 335, 472, 486, 521, nil, 498, nil,
+ 13232, nil, 565, 566, 457, nil, 460, 119, 136, 13353,
+ 493, 147, 479, 244, nil, 482, -7, 8, 13474, 13595,
+ -67, 32, 464, -9, 522, 545, -1, 575, nil, nil,
+ 319, 345, 115, nil, 614, nil, 9, 13716, nil, nil,
+ 311, 419, 453, 456, 457, 478, 488, 499, nil, 519,
+ nil, 13837, nil, 149, 207, 235, 246, -35, 279, nil,
+ 1103, nil, nil, nil, nil, nil, nil, 13958, nil, nil,
+ nil, nil, 509, 511, nil, nil, 735, nil, 495, 14071,
+ nil, 499, nil, nil, 7304, 535, 340, 342, 14192, nil,
+ nil, 0, 541, 107, nil, 14313, 14434, nil, 7425, nil,
+ nil, 23240, 23300, 14555, -33, 14676, 14797, 14918, 614, 863,
+ 377, 384, 566, 574, 575, 576, 2941, 3063, 3185, 1599,
+ 980, 1721, 1843, 1965, 2087, 2209, 2331, 2453, 2575, 249,
+ 465, 2697, 2819, 23348, -48, nil, 15039, nil, 15160, 514,
+ nil, 15281, 321, nil, nil, 376, nil, nil, 563, 531,
+ -64, 529, 630, nil, nil, 15402, -27, -13, 571, nil,
+ 572, 544, nil, nil, nil, 586, 15523, 23414, 23474, 617,
+ 606, nil, nil, 15644, 15765, 15886, 23534, 23594, 13112, 16007,
+ 688, 16128, nil, 582, nil, nil, 16249, nil, nil, 16370,
+ 24122, nil, 16491, nil, nil, nil, 2209, 711, nil, nil,
+ 2331, 68, 109, 708, 716, 2453, 16612, 16733, 23654, 23714,
+ 4, nil, nil, 658, nil, 23774, 16854, 23834, nil, nil,
+ 16975, 100, -34, 2575, 997, nil, nil, nil, -32, nil,
+ nil, nil, 598, nil, nil, nil, 609, nil, 147, nil,
+ nil, 606, nil, nil, 17096, nil, nil, 17209, 17330, nil,
+ 349, 17451, 17572, 648, nil, nil, 17693, 649, nil, 17814,
+ 86, 115, 493, 614, 655, 1106, 17935, 18056, nil, 2697,
+ 18177, 621, nil, 666, 18298, nil, 674, nil, 663, nil,
+ nil, nil, nil, nil, 113, nil, 673, 674, 23894, 23954,
+ 18419, 22933, 69, 643, 18540, nil, 683, nil, 2819, 2941,
+ nil, 1, nil, 681, 63, 112, 687, 347, 735, 688,
+ 19630, 712, 714, -2, 772, nil, 3063, 654, 707, nil,
+ nil, 707, 18661, nil, nil, 506, nil, 800, nil, nil,
+ nil, nil, nil, 810, nil, 814, 700, 15, 18782, 738,
+ 13, 23, 25, 75, 18903, 348, 788, nil, 740, 3185,
+ 331, nil, nil, 835, 3307, 1284, 337, 718, 719, 726,
+ nil, nil, nil, nil, nil, 724, nil, nil, nil, nil,
+ 806, nil, nil, 809, 22885, 773, nil, nil, nil, nil,
+ nil, 3429, nil, nil, nil, nil, nil, 20114, 744, 19024,
+ 19145, nil, 21324, nil, 21566, nil, nil, 21929, nil, 22292,
+ 19266, 19387, 19508, 167, 22534, nil, 745, 984, 19629, nil,
+ 770, 868, 760, nil, 19750, 761, 3551, nil, nil, 802,
+ 803, -63, 871, 19871, nil, 19992, 772, nil, 832, 813,
+ 933, 738, nil, nil, 3673, nil, nil, 31, 20113, nil,
+ nil, 24168, 938, nil, 20234, 941, 3795, 3917, nil, nil,
+ 20355, 4039, nil, 26, 133, nil, 942, nil, 4161, nil,
+ 946, 836, nil, 1406, nil, -43, nil, nil, 436, 20476,
+ nil, nil, nil, nil, 862, nil, nil, 24214, 20597, 20718,
+ 863, 866, 920, 907, 847, 884, nil, nil, nil, nil,
+ 20839, nil, 873, 903, 869, nil, 20960, 870, 21081, nil,
+ nil, nil, nil, nil, 4283, nil, nil, nil, 32, nil,
+ 999, 1001, 21202, 332, nil, nil, 1002, nil, 936, 898,
+ 899, nil, nil, 900, 899, nil, nil, 1528, nil, nil,
+ 21323, 1106, 21444, 24014, 24074, 918, 933, 21565, 5973, nil,
+ nil, nil, 21686, 914, nil, 21807, 918, 1046, 4405, nil,
+ nil, nil, nil, nil, nil, 4527, nil, nil, 282, nil,
+ nil, nil, 4649, nil, 927, 959, 965, 362, 400, 482,
+ 977, 21928, nil, nil, 22049, 931, nil, 22170, nil, nil,
+ 545, 1054, 938, 1057, 972, 22291, 980, nil, 945, nil,
+ 22412, 948, nil, nil, nil, nil, 22533, nil, nil, 22654,
+ nil, nil, 952, nil ]
racc_action_default = [
-4, -497, -1, -485, -5, -497, -497, -497, -497, -497,
@@ -1850,83 +1850,79 @@ racc_action_default = [
-245, -338, -258, -246 ]
clist = [
-'35,300,306,307,268,35,310,338,494,470,440,278,278,107,185,10,96,650',
-'117,117,10,565,293,437,115,115,644,240,240,240,35,271,271,112,112,604',
-'100,732,257,261,205,278,278,278,281,10,504,352,353,354,355,35,365,372',
-'238,238,238,618,622,303,438,313,328,328,328,106,10,266,242,242,242,264',
-'565,311,571,309,318,573,754,756,757,559,810,815,813,296,520,737,197',
-'529,634,112,845,100,486,490,639,35,236,249,250,344,345,588,589,35,348',
-'475,478,326,329,483,10,485,748,513,514,239,239,239,10,290,664,294,817',
-'378,382,305,305,696,700,305,424,446,447,627,842,427,608,375,727,342',
-'343,346,528,347,666,671,650,301,751,809,811,723,574,534,1,350,357,319',
-'184,587,443,586,718,356,253,260,262,340,302,304,305,305,305,305,815',
-'872,97,317,508,339,735,515,432,435,35,35,473,308,623,736,,,,,,,,,,10',
-'10,,35,,,,,,364,370,373,,,,387,,,10,386,,,296,,,,,,637,,706,,,,,,,,',
-'849,850,,,851,,,,,278,,,,,491,492,,,,240,240,,,,,35,389,390,240,271',
-'35,674,,,,,605,610,,,10,454,,368,368,10,442,238,,257,,261,882,,,238',
-',565,,,242,242,450,884,,,264,455,565,242,804,264,,685,,,,688,,,650,',
-',493,378,382,567,,,852,439,444,,,,609,711,,,448,,554,,100,,,,,,441,239',
-'571,573,,,,460,,239,509,,,,,533,,,,843,117,,,,,,115,474,,,305,305,,',
-',112,,,,,,,599,2,,548,,,,512,,599,,,,593,,,,,,725,,518,,729,741,,,,386',
-',605,267,605,,296,,,565,,,561,599,,,,,,599,,,,,,,629,13,,,,583,13,,',
-'638,,640,,703,,,,,198,198,,,,198,198,198,,,565,,,13,272,272,,714,,,',
-'643,386,35,,296,,35,585,,,386,35,,13,198,198,844,10,198,198,,10,198',
-'314,324,324,10,709,710,35,,794,294,,543,576,577,,547,,619,619,386,,10',
-'296,695,,386,,,,,278,296,,603,676,,13,641,642,117,198,198,198,198,13',
-'115,611,869,,,271,,35,614,112,,681,683,,368,,686,,,,570,,10,572,,,362',
-'363,744,305,,,,561,838,,35,35,,626,,,,,267,,665,779,,,781,10,10,,35',
-'762,,605,746,548,712,789,,750,,,,,,10,,,,,,,,,,,13,13,198,198,198,198',
-',35,198,198,198,,35,,,,,,13,,,,10,,,267,,10,,,267,,,,,,,,,35,,747,,',
-'605,278,278,752,798,831,,,834,,10,,,,,112,,,,,,770,770,,198,198,766',
-',,305,35,,278,198,,13,774,776,,272,13,,787,806,,10,,,35,863,,,770,,866',
-',,868,,,35,35,,10,,35,819,795,,,,,35,278,,10,10,,198,198,10,599,,785',
-',,879,10,,,,14,,271,856,,14,198,,888,,619,890,,,,,,,,,198,,893,,783',
-',,35,,,14,274,274,278,278,,,,305,,278,784,10,,796,,,,,,,14,,770,770',
-',873,,,,770,316,325,325,808,,,,853,854,865,35,198,,278,862,,,35,,,,',
-',386,35,10,296,278,,,,,10,770,,,14,,278,10,,,,,14,,,770,877,,615,,,',
-'617,,,,770,625,,,887,198,,,,,,,,,,891,198,,,,,,,,,,,,,198,,,,,,,,,,',
-',,,,,,13,,,,13,,,,,13,,198,,,,,,,,701,198,14,14,,198,,,13,,,,,,,,,,',
-',14,,,,,,,,,719,720,,,,,,198,198,,,,198,,,,,,726,,,,,272,,13,,,,,,,',
-',,,,,,,,,,,,,198,,,,,,14,,13,13,274,14,,,,,,,,,,,,,,,13,,,,,,,,,,,764',
-',,,,,,,,,,,,,,,,198,,,,,13,,,,,13,,,,,,,,782,,,,,,,,,,,,,,,,,,793,13',
-',,,,,,,,198,,800,801,,,,803,,,,,,,,,,771,771,,,,,,,,13,,,,,,,,,,,,,',
-',,,,13,,,,771,,,,,,198,,13,13,,,837,13,,,,,,,13,,,,,,,,,,,,,,,,,,,,',
-'272,,,,,,,,,,,,,,,870,,,,,,,871,,,13,,,,,,,,,,,,,14,,,,14,,,,,14,,,',
-'771,771,198,,,,,771,,,,,,,14,,,,13,,,,12,670,,13,,12,,,,,13,,,,,,,,',
-'771,,,,,,,,,,,12,,,771,,,274,,14,,,,,,771,,,,,,,12,,,,,,,,,,,,,,,,14',
-'14,,,,,,,,,,,,,,,,,14,,,,,,,,,,,,12,,,,,,,,12,,,,,,,,,,,,,14,,,,,14',
-',,,,,,,,,,,,,,,,,,,,,,,,,,14,,,,,,,,,,,,,,,,,,,,,,,,,,773,773,,,,,,',
-',14,12,12,206,,,,237,237,237,,,,,,,,,14,12,,,773,287,288,289,,,,,14',
-'14,,,,14,,,237,237,,,14,,,,,,,,,,,,,,,,,,,,,274,,,,,,,,,,,,,,,,,12,',
-',,,12,,,14,,,,,,,,,,,,,,,,,,,,,,,,,,773,773,,,,,,773,,,,,,,,,,,14,,',
-',,,,14,,,,,,,14,,,,,,,,,773,,,,,,,,,,,,,,773,,,,366,237,374,237,,,388',
-'773,,,,,,,,,,,,206,398,399,400,401,402,403,404,405,406,407,408,409,410',
+'10,205,240,240,240,10,268,438,112,112,100,300,338,470,293,644,242,242',
+'242,440,107,185,238,238,238,115,115,117,117,494,10,486,490,650,303,437',
+'239,239,239,253,260,262,604,290,365,372,732,618,622,96,565,10,815,296',
+'257,261,281,571,504,520,573,318,529,236,249,250,112,100,301,559,810',
+'264,813,266,106,475,478,344,345,483,1,485,348,723,754,756,757,326,329',
+'306,307,588,589,310,97,13,184,10,319,357,13,565,574,534,587,10,311,443',
+'586,718,340,302,198,198,304,317,508,198,198,198,339,515,473,308,736',
+'13,272,272,309,737,634,278,278,845,352,353,354,355,639,748,513,197,514',
+'664,817,815,13,198,198,375,696,198,198,700,424,198,314,324,324,446,447',
+'278,278,278,650,872,350,627,842,608,727,364,370,373,356,342,294,387',
+'343,346,305,305,528,347,305,666,10,10,671,735,751,296,13,809,811,386',
+'198,198,198,198,13,2,368,368,10,,,,,,,623,,,,,,,,706,,,,605,610,305',
+'305,305,305,,,267,,,240,240,,,,,,637,,240,674,,849,850,242,242,851,',
+',,442,238,,242,,,,,,238,,10,,,441,239,10,,,,,,,239,460,,,13,13,198,198',
+'198,198,,,198,198,198,14,454,,439,444,14,474,13,804,882,,427,448,257',
+'264,261,450,884,,264,,455,,,,100,852,389,390,,14,274,274,685,565,609',
+',688,,,,509,571,573,650,565,,,,491,492,14,,711,,,,198,198,554,741,316',
+'325,325,493,725,198,112,13,729,,,272,13,,,605,278,605,533,,,,843,115',
+',117,,,,,,,,,362,363,14,,543,,296,386,547,,14,,,,,,198,198,267,561,',
+',,548,,,,593,,,,,,,,198,,,583,,,,,,,305,305,,,198,,,585,,576,577,,,570',
+',,572,,,512,794,,,629,296,565,,,386,,,,638,518,267,,,386,,267,,,,611',
+'643,,14,14,,,614,,,368,10,,198,,10,,567,,,10,14,296,619,619,,386,565',
+',,,296,386,,,626,,,10,,,,,641,642,665,844,,838,681,683,,,,686,,,695',
+',,,112,,,,198,,,640,,,,,676,,,198,,115,,117,605,14,869,10,561,274,14',
+',198,,,,,294,,,,,,,,,,,712,13,,,,13,,,10,10,13,,198,603,,,378,382,35',
+',,198,746,35,,198,10,750,13,,,,762,12,,,,,12,,,,,605,703,,,548,35,271',
+'271,,,,305,,198,198,,10,,198,,12,10,,714,747,,35,,,272,752,13,432,435',
+'278,,313,328,328,328,766,12,,112,744,,,,10,,,,198,,,,,,,,13,13,,,615',
+',,,617,,787,,35,625,774,776,,,13,,35,,,10,785,,,12,806,,783,,,,,12,',
+',,,,10,,,784,795,198,,,,796,13,,10,10,,13,,10,,,819,,,,10,,,619,,808',
+',,,,305,,701,,,,,779,13,798,781,,,,,,,198,,,14,789,856,,14,,35,35,,14',
+',719,720,,771,771,10,378,382,278,278,12,12,13,35,,,14,,726,,,,,865,',
+'670,873,,12,,13,853,854,296,771,,,386,862,278,198,,13,13,,,,13,,10,',
+',,,13,,10,,831,,274,834,14,10,,,,,,305,,,877,599,35,272,,,271,35,278',
+',599,764,,,887,,,12,,14,14,,12,,,891,,,13,,863,,,,,866,,14,868,,,,599',
+',,,782,,599,,,,,,771,771,198,,,278,278,771,,,793,,278,879,,,14,,13,',
+',14,800,801,,13,888,803,,890,,,13,,,,,,,,893,771,,,,,278,,14,,,,,,,771',
+',,,,278,,,,,,771,709,710,,,278,,,773,773,,,,,837,,,14,,,,,,,,,,,,,,',
+',,,14,,,,773,,,,,,,,14,14,,,,14,,,,,,870,14,,,,,,871,,,,,,,,,,,,,,,274',
+',,,,,,,,,,,,,,,,,,,,,,35,,14,,35,,,,,35,,,,,,12,,,,12,,,,,12,,,35,773',
+'773,,,,,,773,,,,,,,12,,,,14,,,,,,,14,,,,,,,14,,,,,,,,,773,,271,,35,',
+',,,,,,,,773,,,,,12,,,,,,773,,,,,,,,35,35,,,,,,,,,,,,,,12,12,,35,,,,',
+',,,,,,,,,,12,,,,,,,,,599,,,,,,,,,35,,,,,35,,,,,,,,,,12,,,,,12,,,,,,',
+',,,,,35,,,,,,,,,,,,,,,12,,,,,,,,,,,770,770,,,,,,,,35,,,206,,,,237,237',
+'237,,,,,,12,,,35,,,,770,287,288,289,,,,,35,35,,12,,35,,,237,237,,,35',
+',,12,12,,,,12,,,,,367,371,12,,,,,,271,,,,,,,,,,,,,,,,,,,,,,,,,35,,,',
+',,,,,,,,,,,12,,,,,429,,430,,,,770,770,,,,,,770,,,,,,,,,,,35,,,,,,,35',
+',,,,,,35,12,,,,,,,12,770,,,,,,12,,,,,,,,770,,,,366,237,374,237,,,388',
+'770,,,,,,,,,,,,206,398,399,400,401,402,403,404,405,406,407,408,409,410',
'411,412,413,414,415,416,417,418,419,420,421,422,423,,,,,,,,237,,237',
-',,,,,,,,,,237,237,,,,,,,,237,,,,,,,,,,,,,,,,,,,,,,,,,,,468,,,,,,,,,480',
-',,,,,,,,,,,,,,,,12,,,,12,,,,,12,,,,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,',
-',,,,,,,,,237,367,371,,,,,,,,,,,,,,,,,,12,,,,237,,388,555,374,,,,,,,',
-',,,,,,,,,,,,,12,12,,,,429,,430,237,,237,,,237,,,,,12,,,,,,,,,581,,,',
-',,,,,,,237,,,,,,,600,601,602,,,,12,,237,,,12,,237,,,237,,,237,,,,,,',
-',,,,,,,237,237,,,,12,,,,,237,,,,,,,,,,,,,,,,,,,,,,,,,,,,,26,12,677,237',
-',26,682,684,,,,687,,,689,,539,26,26,12,,694,26,26,26,237,,,,237,26,12',
-'12,,,,12,,,,,,,12,,237,,,,237,,26,26,26,,,26,26,,,26,,,,,,,,,,,,,563',
-',566,,731,569,,,,,,,,,,,12,,,582,237,,,,26,,,,26,26,26,26,26,,,,,,,',
-',,,,,607,,,,,613,,,566,,,613,,,,12,,,,,,,12,,,367,237,767,,12,,,,,,',
-',682,684,687,,,,,,,,,,,,237,,,,,,,,,237,,237,,,,,678,26,26,26,26,26',
-'26,,,26,26,26,,,,,,,,26,237,,702,,,,705,,,,,,,,,,,,,237,,,563,,,,716',
-',767,,,,,,,,,,,,828,,,,,,237,,237,26,26,,,,,,,,26,,26,,237,,,26,,,,',
-'742,,,,,,,,,,,,237,,,,,,,,,,237,,,237,,,,,,,,26,26,,,,,,,,,,,,,,,,,765',
-'26,,237,,,237,,,,,,,,,26,,,,237,,,,,,566,,,237,,,,,,,,566,,,,,,,,,,',
-',,,,,,,,,,,,,,613,,,,,,26,,,,,,,,,,,,,816,,,,,,,,,,,,,,,,,,,,,,,,,,',
-'833,,836,,,,,,,,,,26,,,,841,,,,,,,26,,,,,,,,,,,,,26,,,,,,,,,,563,,,566',
-',,,26,,,,26,,,,,26,,26,,,,,,,,,26,,,,26,878,,26,881,,,,,,,,,,,,,566',
-',,,,,,,,892,,,,,26,26,,,,26,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,26,,',
-',,,,,26,26,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,26,,,,,26,',
-',,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,26,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,',
-',,,26,,,,,,,,,,,,,,,,,,26,,,,,,,,,,26,,26,26,,,,26,,,,,,,26,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,26',
-',,,,,,,,,,,,,,,26,,,,,,,26,,,,,,,26' ]
- racc_goto_table = arr = ::Array.new(2846, nil)
+',,,,,,,539,,,237,237,,,,,,,,237,,,,,,,,,,,,,,,,,,,,,,,,,,,468,,,,,,',
+',,480,,,,,,,,,563,,566,,,569,,,,,,,,,,,,,,582,,,,,,,,,,,,,,,,,,,,,,',
+',,,607,,,,,613,,,566,,,613,,,,,237,,,,,,,,,367,,,,,,,,,,,,,,,237,,388',
+'555,374,,,,,,,,,,,,,,,,,,,,,,,678,,,,,,237,,237,,,237,,,,,,,,,,,702',
+',,581,705,,,,,,,,,,237,,,,,,563,600,601,602,716,,26,,,237,,26,,,237',
+',,237,,,237,,,26,26,,,,26,26,26,,,,237,237,26,,,,,,,,237,,,,742,,,,',
+',,,,26,26,26,,,26,26,,,26,,,,,,,,,677,237,,,682,684,,,,687,,,689,,,',
+',,,694,,,,237,765,,,237,26,,,,26,26,26,26,26,,,,,,,237,,,,237,,566,',
+',,,,,,,,,566,,,,,,,,,,,,,,,731,,,,,,,,,,613,,,,,,237,,,,,,,,,,,,,816',
+',,,,,,,,,,,,26,26,26,26,26,26,,,26,26,26,,,,833,,836,,26,,,,,,,237,767',
+',,,841,,,,,,682,684,687,,,,,,,,,,,,237,,,,,,,,,237,563,237,,566,,,,',
+'26,26,,,,,,,,26,,26,,,,,26,,237,,,,,,878,,,881,,,,,,,,,,237,,,566,,',
+',,,767,,,892,,,,,26,26,,,828,,,,,,237,,237,,,,,,,26,,,,,,,237,,,,,,',
+'26,,,,,,,,,,,,,237,,,,,,,,,,237,,,237,,,,,,,,,,,,,,,,,,,,,,,,,,26,,',
+'237,,,237,,,,,,,,,,,,,237,,,,,,,,,237,,,,,,,,,,,,,,,,,,,,,,,,26,,,,',
+',,,,,,26,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,26,,,,26,,,,,26,,26,,,,,,,,',
+'26,,,,26,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,26,26,,,,26,,,,,,,,,,,,,26',
+',,,,,,,,,,,,,,,,,,,,26,,,,,,,,26,26,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,26,,,,,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,26,,,,,,,,',
+'26,,,,,,,,,,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,,,26,,,,,,,,,,26,,26,26',
+',,,26,,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,26,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,26,,,,,,,,,,,,,,,,26,,,,,,,26,,,,,,,26' ]
+ racc_goto_table = arr = ::Array.new(2610, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -1936,74 +1932,71 @@ clist = [
end
clist = [
-'41,19,13,13,39,41,13,44,79,4,29,52,52,11,11,14,8,126,49,49,14,131,3',
-'32,48,48,83,56,56,56,41,41,41,45,45,5,82,77,57,57,15,52,52,52,40,14',
-'42,13,13,13,13,41,21,21,26,26,26,78,78,56,53,41,41,41,41,9,14,37,60',
-'60,60,36,131,8,58,89,14,58,125,125,125,33,124,128,124,26,117,90,23,117',
-'91,45,92,82,76,76,93,41,28,28,28,114,114,33,33,41,114,55,55,43,43,55',
-'14,55,94,95,96,54,54,54,14,51,97,23,98,30,30,23,23,99,100,23,102,104',
-'105,106,107,59,108,19,109,112,113,115,116,118,119,120,126,54,121,123',
-'127,6,34,50,1,9,24,16,12,61,62,64,65,9,31,31,31,72,73,74,23,23,23,23',
-'128,124,10,80,81,84,5,85,30,30,41,41,86,87,79,88,,,,,,,,,,14,14,,41',
-',,,,,15,15,15,,,,15,,,14,45,,,26,,,,,,42,,33,,,,,,,,,125,125,,,125,',
-',,,52,,,,,13,13,,,,56,56,,,,,41,23,23,56,41,41,117,,,,,53,53,,,14,40',
-',54,54,14,26,26,,57,,57,77,,,26,,131,,,60,60,37,125,,,36,37,131,60,78',
-'36,,32,,,,32,,,126,,,8,30,30,59,,,83,28,28,,,,21,29,,,28,,19,,82,,,',
-',,54,54,58,58,,,,51,,54,82,,,,,11,,,,5,49,,,,,,48,51,,,23,23,,,,45,',
-',,,,,30,2,,57,,,,23,,30,,,,19,,,,,,53,,23,,53,76,,,,45,,53,2,53,,26',
-',,131,,,56,30,,,,,,30,,,,,,,19,18,,,,56,18,,,19,,13,,59,,,,,18,18,,',
-',18,18,18,,,131,,,18,18,18,,59,,,,3,45,41,,26,,41,60,,,45,41,,18,18',
-'18,79,14,18,18,,14,18,18,18,18,14,30,30,41,,76,23,,31,51,51,,31,,82',
-'82,45,,14,26,39,,45,,,,,52,26,,23,11,,18,82,82,49,18,18,18,18,18,48',
-'51,4,,,41,,41,51,45,,15,15,,54,,15,,,,31,,14,31,,,2,2,13,23,,,,56,76',
-',41,41,,54,,,,,2,,51,59,,,59,14,14,,41,44,,53,3,57,26,59,,3,,,,,,14',
-',,,,,,,,,,18,18,18,18,18,18,,41,18,18,18,,41,,,,,,18,,,,14,,,2,,14,',
-',2,,,,,,,,,41,,82,,,53,52,52,82,13,59,,,59,,14,,,,,45,,,,,,41,41,,18',
-'18,15,,,23,41,,52,18,,18,14,14,,18,18,,56,3,,14,,,41,59,,,41,,59,,,59',
-',,41,41,,14,,41,39,14,,,,,41,52,,14,14,,18,18,14,30,,60,,,59,14,,,,20',
-',41,19,,20,18,,59,,82,59,,,,,,,,,18,,59,,51,,,41,,,20,20,20,52,52,,',
-',23,,52,54,14,,51,,,,,,,20,,41,41,,3,,,,41,20,20,20,51,,,,14,14,56,41',
-'18,,52,14,,,41,,,,,,45,41,14,26,52,,,,,14,41,,,20,,52,14,,,,,20,,,41',
-'14,,2,,,,2,,,,41,2,,,14,18,,,,,,,,,,14,18,,,,,,,,,,,,,18,,,,,,,,,,,',
-',,,,,18,,,,18,,,,,18,,18,,,,,,,,2,18,20,20,,18,,,18,,,,,,,,,,,,20,,',
-',,,,,,2,2,,,,,,18,18,,,,18,,,,,,2,,,,,18,,18,,,,,,,,,,,,,,,,,,,,,18',
-',,,,,20,,18,18,20,20,,,,,,,,,,,,,,,18,,,,,,,,,,,2,,,,,,,,,,,,,,,,,18',
-',,,,18,,,,,18,,,,,,,,2,,,,,,,,,,,,,,,,,,2,18,,,,,,,,,18,,2,2,,,,2,,',
-',,,,,,,18,18,,,,,,,,18,,,,,,,,,,,,,,,,,,18,,,,18,,,,,,18,,18,18,,,2',
-'18,,,,,,,18,,,,,,,,,,,,,,,,,,,,,18,,,,,,,,,,,,,,,2,,,,,,,2,,,18,,,,',
-',,,,,,,,20,,,,20,,,,,20,,,,18,18,18,,,,,18,,,,,,,20,,,,18,,,,17,20,',
-'18,,17,,,,,18,,,,,,,,,18,,,,,,,,,,,17,,,18,,,20,,20,,,,,,18,,,,,,,17',
-',,,,,,,,,,,,,,,20,20,,,,,,,,,,,,,,,,,20,,,,,,,,,,,,17,,,,,,,,17,,,,',
-',,,,,,,,20,,,,,20,,,,,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,,,,,,,,,,,,,,,',
-',,,,20,20,,,,,,,,20,17,17,25,,,,25,25,25,,,,,,,,,20,17,,,20,25,25,25',
-',,,,20,20,,,,20,,,25,25,,,20,,,,,,,,,,,,,,,,,,,,,20,,,,,,,,,,,,,,,,',
-'17,,,,,17,,,20,,,,,,,,,,,,,,,,,,,,,,,,,,20,20,,,,,,20,,,,,,,,,,,20,',
-',,,,,20,,,,,,,20,,,,,,,,,20,,,,,,,,,,,,,,20,,,,25,25,25,25,,,25,20,',
-',,,,,,,,,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25',
-'25,25,25,25,25,25,25,,,,,,,,25,,25,,,,,,,,,,,25,25,,,,,,,,25,,,,,,,',
-',,,,,,,,,,,,,,,,,,,25,,,,,,,,,25,,,,,,,,,,,,,,,,,17,,,,17,,,,,17,,,',
-',,,,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,25,22,22,,,,,,,,,,,,,,,,,',
-'17,,,,25,,25,25,25,,,,,,,,,,,,,,,,,,,,,17,17,,,,22,,22,25,,25,,,25,',
-',,,17,,,,,,,,,25,,,,,,,,,,,25,,,,,,,25,25,25,,,,17,,25,,,17,,25,,,25',
-',,25,,,,,,,,,,,,,,25,25,,,,17,,,,,25,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35',
-'17,25,25,,35,25,25,,,,25,,,25,,22,35,35,17,,25,35,35,35,25,,,,25,35',
-'17,17,,,,17,,,,,,,17,,25,,,,25,,35,35,35,,,35,35,,,35,,,,,,,,,,,,,22',
-',22,,25,22,,,,,,,,,,,17,,,22,25,,,,35,,,,35,35,35,35,35,,,,,,,,,,,,',
-'22,,,,,22,,,22,,,22,,,,17,,,,,,,17,,,22,25,25,,17,,,,,,,,25,25,25,,',
-',,,,,,,,,25,,,,,,,,,25,,25,,,,,22,35,35,35,35,35,35,,,35,35,35,,,,,',
-',,35,25,,22,,,,22,,,,,,,,,,,,,25,,,22,,,,22,,25,,,,,,,,,,,,25,,,,,,25',
-',25,35,35,,,,,,,,35,,35,,25,,,35,,,,,22,,,,,,,,,,,,25,,,,,,,,,,25,,',
-'25,,,,,,,,35,35,,,,,,,,,,,,,,,,,22,35,,25,,,25,,,,,,,,,35,,,,25,,,,',
-',22,,,25,,,,,,,,22,,,,,,,,,,,,,,,,,,,,,,,,,22,,,,,,35,,,,,,,,,,,,,22',
-',,,,,,,,,,,,,,,,,,,,,,,,,,22,,22,,,,,,,,,,35,,,,22,,,,,,,35,,,,,,,,',
-',,,,35,,,,,,,,,,22,,,22,,,,35,,,,35,,,,,35,,35,,,,,,,,,35,,,,35,22,',
-'35,22,,,,,,,,,,,,,22,,,,,,,,,22,,,,,35,35,,,,35,,,,,,,,,,,,,35,,,,,',
-',,,,,,,,,,,,,,,35,,,,,,,,35,35,,,,,,,,,,,,,,,,,35,,,,,,,,,,,,,,,,,,',
-',,,,,,,,,35,,,,,35,,,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,,,,,,35,,',
-',,,,,,,,,,,,,,,,,,,,,,,35,,,,,,,,,,,,,,,,,,35,,,,,,,,,,35,,35,35,,,',
-'35,,,,,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,35,,,,,,,,,,,,,,,,35,,,,,,,35,,,,,,,35' ]
- racc_goto_check = arr = ::Array.new(2846, nil)
+'14,15,56,56,56,14,39,53,45,45,82,19,44,4,3,83,60,60,60,29,11,11,26,26',
+'26,48,48,49,49,79,14,76,76,126,56,32,54,54,54,31,31,31,5,51,21,21,77',
+'78,78,8,131,14,128,26,57,57,40,58,42,117,58,14,117,28,28,28,45,82,54',
+'33,124,36,124,37,9,55,55,114,114,55,1,55,114,6,125,125,125,43,43,13',
+'13,33,33,13,10,18,12,14,16,24,18,131,34,50,61,14,8,62,64,65,72,73,18',
+'18,74,80,81,18,18,18,84,85,86,87,88,18,18,18,89,90,91,52,52,92,13,13',
+'13,13,93,94,95,23,96,97,98,128,18,18,18,19,99,18,18,100,102,18,18,18',
+'18,104,105,52,52,52,126,124,9,106,107,108,109,15,15,15,9,112,23,15,113',
+'115,23,23,116,118,23,119,14,14,120,5,121,26,18,123,127,45,18,18,18,18',
+'18,2,54,54,14,,,,,,,79,,,,,,,,33,,,,53,53,23,23,23,23,,,2,,,56,56,,',
+',,,42,,56,117,,125,125,60,60,125,,,,26,26,,60,,,,,,26,,14,,,54,54,14',
+',,,,,,54,51,,,18,18,18,18,18,18,,,18,18,18,20,40,,28,28,20,51,18,78',
+'77,,59,28,57,36,57,37,125,,36,,37,,,,82,83,23,23,,20,20,20,32,131,21',
+',32,,,,82,58,58,126,131,,,,13,13,20,,29,,,,18,18,19,76,20,20,20,8,53',
+'18,45,18,53,,,18,18,,,53,52,53,11,,,,5,48,,49,,,,,,,,,2,2,20,,31,,26',
+'45,31,,20,,,,,,18,18,2,56,,,,57,,,,19,,,,,,,,18,,,56,,,,,,,23,23,,,18',
+',,60,,51,51,,,31,,,31,,,23,76,,,19,26,131,,,45,,,,19,23,2,,,45,,2,,',
+',51,3,,20,20,,,51,,,54,14,,18,,14,,59,,,14,20,26,82,82,,45,131,,,,26',
+'45,,,54,,,14,,,,,82,82,51,79,,76,15,15,,,,15,,,39,,,,45,,,,18,,,13,',
+',,,11,,,18,,48,,49,53,20,4,14,56,20,20,,18,,,,,23,,,,,,,,,,,26,18,,',
+',18,,,14,14,18,,18,23,,,30,30,41,,,18,3,41,,18,14,3,18,,,,44,17,,,,',
+'17,,,,,53,59,,,57,41,41,41,,,,23,,18,18,,14,,18,,17,14,,59,82,,41,,',
+'18,82,18,30,30,52,,41,41,41,41,15,17,,45,13,,,,14,,,,18,,,,,,,,18,18',
+',,2,,,,2,,56,,41,2,14,14,,,18,,41,,,14,60,,,17,3,,51,,,,,17,,,,,,14',
+',,54,14,18,,,,51,18,,14,14,,18,,14,,,39,,,,14,,,82,,51,,,,,23,,2,,,',
+',59,18,13,59,,,,,,,18,,,20,59,19,,20,,41,41,,20,,2,2,,18,18,14,30,30',
+'52,52,17,17,18,41,,,20,,2,,,,,56,,20,3,,17,,18,14,14,26,18,,,45,14,52',
+'18,,18,18,,,,18,,14,,,,,18,,14,,59,,20,59,20,14,,,,,,23,,,14,30,41,18',
+',,41,41,52,,30,2,,,14,,,17,,20,20,,17,,,14,,,18,,59,,,,,59,,20,59,,',
+',30,,,,2,,30,,,,,,18,18,18,,,52,52,18,,,2,,52,59,,,20,,18,,,20,2,2,',
+'18,59,2,,59,,,18,,,,,,,,59,18,,,,,52,,20,,,,,,,18,,,,,52,,,,,,18,30',
+'30,,,52,,,20,20,,,,,2,,,20,,,,,,,,,,,,,,,,,,20,,,,20,,,,,,,,20,20,,',
+',20,,,,,,2,20,,,,,,2,,,,,,,,,,,,,,,20,,,,,,,,,,,,,,,,,,,,,,,41,,20,',
+'41,,,,,41,,,,,,17,,,,17,,,,,17,,,41,20,20,,,,,,20,,,,,,,17,,,,20,,,',
+',,,20,,,,,,,20,,,,,,,,,20,,41,,41,,,,,,,,,,20,,,,,17,,,,,,20,,,,,,,',
+'41,41,,,,,,,,,,,,,,17,17,,41,,,,,,,,,,,,,,,17,,,,,,,,,30,,,,,,,,,41',
+',,,,41,,,,,,,,,,17,,,,,17,,,,,,,,,,,,41,,,,,,,,,,,,,,,17,,,,,,,,,,,41',
+'41,,,,,,,,41,,,25,,,,25,25,25,,,,,,17,,,41,,,,41,25,25,25,,,,,41,41',
+',17,,41,,,25,25,,,41,,,17,17,,,,17,,,,,22,22,17,,,,,,41,,,,,,,,,,,,',
+',,,,,,,,,,,,41,,,,,,,,,,,,,,,17,,,,,22,,22,,,,41,41,,,,,,41,,,,,,,,',
+',,41,,,,,,,41,,,,,,,41,17,,,,,,,17,41,,,,,,17,,,,,,,,41,,,,25,25,25',
+'25,,,25,41,,,,,,,,,,,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25',
+'25,25,25,25,25,25,25,25,25,25,25,,,,,,,,25,,25,,,,,,,,22,,,25,25,,,',
+',,,,25,,,,,,,,,,,,,,,,,,,,,,,,,,,25,,,,,,,,,25,,,,,,,,,22,,22,,,22,',
+',,,,,,,,,,,,22,,,,,,,,,,,,,,,,,,,,,,,,,,22,,,,,22,,,22,,,22,,,,,25,',
+',,,,,,,22,,,,,,,,,,,,,,,25,,25,25,25,,,,,,,,,,,,,,,,,,,,,,,22,,,,,,25',
+',25,,,25,,,,,,,,,,,22,,,25,22,,,,,,,,,,25,,,,,,22,25,25,25,22,,35,,',
+'25,,35,,,25,,,25,,,25,,,35,35,,,,35,35,35,,,,25,25,35,,,,,,,,25,,,,22',
+',,,,,,,,35,35,35,,,35,35,,,35,,,,,,,,,25,25,,,25,25,,,,25,,,25,,,,,',
+',25,,,,25,22,,,25,35,,,,35,35,35,35,35,,,,,,,25,,,,25,,22,,,,,,,,,,',
+'22,,,,,,,,,,,,,,,25,,,,,,,,,,22,,,,,,25,,,,,,,,,,,,,22,,,,,,,,,,,,,35',
+'35,35,35,35,35,,,35,35,35,,,,22,,22,,35,,,,,,,25,25,,,,22,,,,,,25,25',
+'25,,,,,,,,,,,,25,,,,,,,,,25,22,25,,22,,,,,35,35,,,,,,,,35,,35,,,,,35',
+',25,,,,,,22,,,22,,,,,,,,,,25,,,22,,,,,,25,,,22,,,,,35,35,,,25,,,,,,25',
+',25,,,,,,,35,,,,,,,25,,,,,,,35,,,,,,,,,,,,,25,,,,,,,,,,25,,,25,,,,,',
+',,,,,,,,,,,,,,,,,,,,35,,,25,,,25,,,,,,,,,,,,,25,,,,,,,,,25,,,,,,,,,',
+',,,,,,,,,,,,,,35,,,,,,,,,,,35,,,,,,,,,,,,,35,,,,,,,,,,,,,,,,,35,,,,35',
+',,,,35,,35,,,,,,,,,35,,,,35,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,35,,',
+',35,,,,,,,,,,,,,35,,,,,,,,,,,,,,,,,,,,,35,,,,,,,,35,35,,,,,,,,,,,,,',
+',,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,,35,,,,,35,,,,,,,,,,,,,,,,,,',
+',,,,,,,,35,,,,,,,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,,,,,,,,,,,,,,,35',
+',,,,,,,,,35,,35,35,,,,35,,,,,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,,,35,,,,,,,,,,,,,,,,35,,,,,,',
+'35,,,,,,,35' ]
+ racc_goto_check = arr = ::Array.new(2610, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -2013,20 +2006,20 @@ clist = [
end
racc_goto_pointer = [
- nil, 156, 392, -29, -283, -435, -451, nil, 13, 60,
- 175, 7, 153, -54, 15, 22, 98, 1288, 446, -52,
- 767, -136, 1640, 71, 51, 1458, 32, nil, 76, -244,
- -67, 140, -230, -343, -282, 1993, 41, 37, nil, -27,
- 12, 0, -276, 47, -57, 27, nil, nil, 18, 12,
- -206, 80, -20, -194, 95, -190, 5, 12, -358, -103,
- 46, -284, -93, nil, -282, -423, nil, nil, nil, nil,
- nil, nil, 105, 116, 116, nil, -212, -578, -434, -303,
- 118, -146, 33, -488, 117, -156, -106, 131, -427, 16,
- -535, -411, -712, -412, -528, -214, -222, -393, -638, -428,
- -427, nil, -102, nil, -125, -125, -361, -667, -333, -468,
- nil, nil, 71, 70, 27, 67, -202, -257, 68, -376,
- -376, -495, nil, -602, -671, -569, -497, -601, -672, nil,
- nil, -407 ]
+ nil, 80, 201, -37, -279, -428, -521, nil, 46, 69,
+ 91, 14, 89, 33, 0, -17, 37, 613, 95, -42,
+ 292, -144, 1171, 124, -8, 1289, 0, nil, 41, -235,
+ 404, 13, -218, -355, -334, 1757, 41, 43, nil, -25,
+ 24, 598, -264, 25, -52, 2, nil, nil, 19, 21,
+ -258, 2, 100, -247, 14, -222, -20, 28, -375, 63,
+ -6, -341, -148, nil, -337, -478, nil, nil, nil, nil,
+ nil, nil, 46, 57, 59, nil, -275, -569, -444, -282,
+ 54, -210, 7, -499, 56, -218, -172, 65, -494, 69,
+ -493, -371, -671, -370, -503, -189, -196, -372, -618, -407,
+ -404, nil, -80, nil, -99, -99, -329, -635, -302, -438,
+ nil, nil, 105, 106, 3, 103, -164, -284, 106, -337,
+ -335, -455, nil, -560, -683, -563, -481, -559, -703, nil,
+ nil, -378 ]
racc_goto_default = [
nil, nil, 292, nil, nil, 733, nil, 3, nil, 4,
diff --git a/test/racc/regress/ruby22 b/test/racc/regress/ruby22
index 8e68b5fe1c..101119a232 100644
--- a/test/racc/regress/ruby22
+++ b/test/racc/regress/ruby22
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -27,135 +27,120 @@ module_eval(<<'...end ruby22.y/module_eval...', 'ruby22.y', 2374)
##### State transition tables begin ###
clist = [
-'-291,568,-102,-100,860,-99,951,-291,-291,-291,-490,568,-291,-291,-291',
-'217,-291,589,214,215,959,-288,214,215,214,215,-291,-291,-291,-105,-99',
-'-97,-103,837,806,268,-291,-291,610,-291,-291,-291,-291,-291,568,568',
-'-102,568,113,-100,715,-101,268,112,-83,815,218,-88,-482,113,-99,-288',
-'-98,-69,112,-482,-97,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291',
-'-291,-291,-291,-291,-93,-104,-291,-291,-291,961,773,-291,715,612,-291',
-'-101,715,-291,-291,268,-291,-575,-291,263,-291,962,-291,-291,609,-291',
-'-291,-291,-291,-291,967,-291,113,-291,-90,-91,218,112,218,113,-102,-100',
-'267,588,112,-102,-100,-291,-574,113,-291,-291,-291,-291,112,-291,-578',
-'-291,-96,267,-88,-94,-103,-578,-578,-578,113,-93,-99,-578,-578,112,-578',
-'-99,113,-93,611,-574,-91,112,647,-578,113,113,814,113,842,112,112,-101',
-'112,-89,-578,-578,-101,-578,-578,-578,-578,-578,214,215,-91,267,580',
-'-476,268,-93,581,647,-93,-95,-476,113,736,646,-490,113,112,-93,574,-92',
-'112,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578',
-'-578,692,647,-578,-578,-578,-91,631,646,-91,-491,-578,113,626,-578,647',
-'971,112,-91,-578,515,-578,973,-578,-578,-571,-578,-578,-578,-578,-578',
-'-291,-578,-578,-578,263,-97,646,-291,-291,-291,91,92,79,-291,-291,-486',
-'-291,-578,975,646,-578,-578,-486,-92,80,-578,-89,267,218,-93,977,597',
-'-101,-412,81,-98,-291,-291,-102,-291,-291,-291,-291,-291,444,-104,548',
-'-476,545,544,543,597,546,527,-476,806,529,574,548,-571,545,544,543,-476',
-'546,91,92,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291',
-'-291,-291,260,-571,-291,-291,-291,-412,630,261,93,94,-291,977,-412,-291',
-'597,599,598,595,-291,-105,-291,-412,-291,-291,-578,-291,-291,-291,-291',
-'-291,-476,-291,662,-291,771,599,598,-476,-476,-476,-412,988,-476,-476',
-'-476,749,-476,-291,833,527,-291,-291,529,-94,-476,-291,-476,-476,-476',
-'238,957,-485,-103,93,94,989,-476,-476,-485,-476,-476,-476,-476,-476',
-'770,899,625,-578,-292,599,598,608,597,113,-578,-292,899,113,112,-574',
-'-102,235,112,-578,-292,237,236,-476,-476,-476,-476,-476,-476,-476,-476',
-'-476,-476,-476,-476,-476,-476,899,-578,-476,-476,-476,-491,-476,-476',
-'564,563,-476,597,-91,-476,-476,597,-476,994,-476,-100,-476,-100,-476',
-'-476,597,-476,-476,-476,-476,-476,597,-476,-479,-476,959,-487,599,598',
-'613,-479,-479,-479,-487,121,-479,-479,-479,-476,-479,113,-476,-476,-476',
-'-476,112,-476,-479,-476,-479,-479,-479,-98,-476,210,527,-578,212,526',
-'-479,-479,211,-479,-479,-479,-479,-479,599,598,584,209,599,598,602,597',
-'218,939,747,981,388,599,598,600,-572,-575,585,599,598,595,-574,-479',
-'-479,-479,-479,-479,-479,-479,-479,-479,-479,-479,-479,-479,-479,-96',
-'260,-479,-479,-479,-578,-479,-479,261,-105,-479,682,-578,-479,-479,109',
-'-479,-574,-479,756,-479,-578,-479,-479,515,-479,-479,-479,-479,-479',
-'959,-479,-479,-479,1013,599,598,604,-484,-479,-578,238,-291,527,-572',
-'-484,529,-479,-479,-291,-479,-479,-479,-479,-575,-479,-578,-479,-291',
-'837,806,1014,-479,-578,-578,-578,-90,-572,-578,-578,-578,-95,-578,235',
-'1015,-99,977,237,236,-481,-104,-578,-578,-578,-578,396,-481,-483,214',
-'215,398,397,-578,-578,-483,-578,-578,-578,-578,-578,548,-479,545,544',
-'543,576,546,548,-479,545,544,543,577,546,548,-263,545,544,543,238,546',
-'575,218,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578',
-'-578,-578,553,701,-578,-578,-578,584,772,-578,701,218,-578,556,583,-578',
-'-578,701,-578,704,-578,218,-578,585,-578,-578,704,-578,-578,-578,-578',
-'-578,-488,-578,-578,-578,214,215,548,-488,545,544,543,238,546,238,564',
-'563,-488,-578,516,557,-578,-578,-578,-578,-489,-578,218,-578,214,215',
-'-83,-489,-101,290,69,70,71,9,57,666,-489,986,63,64,701,218,512,67,987',
-'65,66,68,30,31,72,73,520,985,238,677,263,29,28,27,101,100,102,103,741',
-'742,19,238,743,107,108,635,8,45,292,10,105,104,106,95,56,97,96,98,977',
-'99,107,108,218,91,92,682,42,43,41,238,242,247,248,249,244,246,254,255',
-'250,251,517,231,232,-281,683,252,253,518,40,685,-281,33,272,689,58,59',
-'442,692,60,-281,35,235,693,241,44,237,236,695,233,234,245,243,239,20',
-'240,697,699,509,89,79,82,83,-489,84,86,85,87,707,708,-489,709,80,88',
-'711,256,574,-240,718,-489,62,502,81,93,94,290,69,70,71,9,57,501,218',
-'-292,63,64,736,530,746,67,-292,65,66,68,30,31,72,73,531,-292,750,751',
-'-264,29,28,27,101,100,102,103,-68,498,19,757,490,488,477,635,8,45,292',
-'10,105,104,106,95,56,97,96,98,486,99,107,108,977,91,92,477,42,43,41',
-'238,242,247,248,249,244,246,254,255,250,251,-291,231,232,-488,477,252',
-'253,-291,40,217,-488,33,-575,446,58,59,-291,218,60,-488,35,235,490,241',
-'44,237,236,218,233,234,245,243,239,20,240,445,257,443,89,79,82,83,507',
-'84,86,85,87,488,490,508,799,80,88,677,256,218,637,634,506,62,263,81',
-'93,94,290,69,70,71,9,57,977,263,-334,63,64,677,238,806,67,-334,65,66',
-'68,30,31,72,73,218,-334,263,218,399,29,28,27,101,100,102,103,831,218',
-'19,806,841,218,624,620,8,45,292,10,105,104,106,95,56,97,96,98,623,99',
-'107,108,218,91,92,619,42,43,41,238,242,247,248,249,244,246,254,255,250',
-'251,-291,231,232,-281,218,252,253,-291,40,386,-281,33,-575,850,58,59',
-'-291,-263,60,-281,35,235,617,241,44,237,236,614,233,234,245,243,239',
-'20,240,-265,579,859,89,79,82,83,584,84,86,85,87,578,899,939,959,80,88',
-'218,256,317,861,862,585,62,692,81,93,94,290,69,70,71,9,57,865,867,-292',
-'63,64,869,871,218,67,-292,65,66,68,30,31,72,73,873,-292,874,877,316',
-'29,28,27,101,100,102,103,879,936,19,545,544,543,880,546,8,45,292,10',
-'105,104,106,95,56,97,96,98,677,99,107,108,882,91,92,886,42,43,41,238',
-'242,247,248,249,244,246,254,255,250,251,440,231,232,888,891,252,253',
-'441,40,692,893,33,895,897,58,59,442,899,60,899,35,235,218,241,44,237',
-'236,905,233,234,245,243,239,20,240,907,909,257,89,79,82,83,915,84,86',
-'85,87,213,918,218,922,80,88,-266,256,933,208,940,941,62,207,81,93,94',
-'290,69,70,71,9,57,206,950,,63,64,,,,67,,65,66,68,30,31,72,73,116,117',
-'118,119,120,29,28,27,101,100,102,103,,936,19,545,544,543,,546,8,45,292',
+'-476,-97,268,214,215,-98,-105,-476,-476,-476,-490,568,-476,-476,-476',
+'610,-476,580,217,612,-288,581,214,215,-476,-491,-476,-476,-476,647,268',
+'268,214,215,-104,589,-476,-476,568,-476,-476,-476,-476,-476,568,568',
+'212,109,568,815,-100,121,-100,-83,-102,-99,214,215,268,218,-288,806',
+'-69,574,646,-102,-97,-476,-476,-476,-476,-476,-476,-476,-476,-476,-476',
+'-476,-476,-476,-476,-98,609,-476,-476,-476,611,-476,-476,715,267,-476',
+'206,-96,-476,-476,263,-476,218,-476,207,-476,-105,-476,-476,-99,-476',
+'-476,-476,-476,-476,-88,-476,-479,-476,-89,-96,218,267,267,-479,-479',
+'-479,263,-101,-479,-479,-479,-476,-479,113,-476,-476,-476,-476,112,-476',
+'-479,-476,-479,-479,-479,588,-476,-95,715,267,-101,715,-479,-479,218',
+'-479,-479,-479,-479,-479,113,208,814,-91,-91,112,113,113,113,842,113',
+'112,112,112,-100,112,-102,-99,-93,-100,213,-102,-99,-479,-479,-479,-479',
+'-479,-479,-479,-479,-479,-479,-479,-479,-479,-479,113,257,-479,-479',
+'-479,112,-479,-479,-574,-93,-479,316,-103,-479,-479,317,-479,597,-479',
+'-574,-479,-90,-479,-479,444,-479,-479,-479,-479,-479,-291,-479,218,-479',
+'-91,214,215,-291,-291,-291,647,260,527,-291,-291,526,-291,-479,261,-101',
+'-479,-479,-479,-479,-101,-479,113,-479,-571,113,113,112,-479,-92,112',
+'112,-291,-291,386,-291,-291,-291,-291,-291,-91,646,-93,-91,-575,396',
+'-105,399,599,598,398,397,-91,548,597,545,544,543,747,546,443,91,92,-291',
+'-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-476',
+'-572,-291,-291,-291,-93,630,-476,-93,-490,-291,-94,-571,-291,91,92,-476',
+'-93,-291,113,-291,515,-291,-291,112,-291,-291,-291,-291,-291,597,-291',
+'-578,-291,445,-571,-491,-476,446,-578,-578,-578,599,598,-476,-578,-578',
+'-291,-578,647,-291,-291,749,-94,-479,-291,-88,-578,217,833,-578,-479',
+'-103,93,94,-97,-572,477,-578,-578,-479,-578,-578,-578,-578,-578,548',
+'-104,545,544,543,515,546,-89,646,527,647,597,529,-572,597,486,-98,93',
+'94,599,598,595,-412,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578',
+'-578,-578,-578,-578,-578,625,-578,-578,-578,597,631,-578,646,113,-578',
+'626,-574,-578,112,-95,-578,597,-578,770,-578,-578,-578,-578,-104,-578',
+'-578,-578,-578,-578,488,-578,-578,-578,597,-578,490,597,-412,599,598',
+'595,599,598,600,-412,957,-578,-91,756,-578,-578,-578,-92,-412,-578,662',
+'-100,-93,-578,-578,-578,-101,498,-578,-578,-578,-102,-578,-479,599,598',
+'602,-412,-578,-100,-479,-578,-578,-578,-578,-578,599,598,604,771,-574',
+'-68,-578,-578,-578,-578,-578,-578,-578,-578,-90,218,860,599,598,608',
+'599,598,613,-99,214,215,-486,-578,548,-485,545,544,543,-486,546,501',
+'-485,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578,-578',
+'-578,553,502,-578,-578,-578,-487,772,-578,-102,509,-578,556,-487,-578',
+'-578,701,-578,272,-578,218,-578,-99,-578,-578,704,-578,-578,-578,-578',
+'-578,553,-578,-578,-578,527,-484,79,529,113,-481,263,556,-484,112,564',
+'563,-481,-578,80,557,-578,-578,-578,-578,238,-578,-291,-578,81,-482',
+'210,512,-101,-291,-291,-291,-482,211,-291,-291,-291,-334,-291,440,564',
+'563,209,516,-334,557,441,-483,-291,-291,-291,238,235,-334,-483,442,237',
+'236,-291,-291,260,-291,-291,-291,-291,-291,548,261,545,544,543,-488',
+'546,548,218,545,544,543,-488,546,548,530,545,544,543,527,546,-488,529',
+'-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291,-291',
+'238,701,-291,-291,-291,-489,773,-291,701,238,-291,531,-489,-291,-291',
+'701,-291,704,-291,490,-291,-489,-291,-291,904,-291,-291,-291,-291,-291',
+'113,-291,235,-291,574,112,237,236,238,233,234,235,214,215,388,237,236',
+'-291,233,234,-291,-291,-291,-291,113,-291,113,-291,578,112,579,112,-103',
+'5,69,70,71,9,57,614,235,507,63,64,237,236,617,67,508,65,66,68,30,31',
+'72,73,218,506,-263,981,619,29,28,27,101,100,102,103,741,742,19,218,743',
+'107,108,635,8,45,7,10,105,104,106,95,56,97,96,98,623,99,107,108,624',
+'91,92,263,42,43,41,238,242,247,248,249,244,246,254,255,250,251,-281',
+'231,232,517,634,252,253,-281,40,637,518,33,564,563,58,59,-281,238,60',
+'442,35,235,238,241,44,237,236,238,233,234,245,243,239,20,240,837,806',
+'238,89,79,82,83,576,84,86,85,87,837,806,577,218,80,88,218,256,218,-240',
+'-83,575,62,666,81,93,94,290,69,70,71,9,57,218,520,584,63,64,677,682',
+'683,67,583,65,66,68,30,31,72,73,685,585,689,692,693,29,28,27,101,100',
+'102,103,695,697,19,699,707,708,709,620,8,45,292,10,105,104,106,95,56',
+'97,96,98,711,99,107,108,574,91,92,718,42,43,41,238,242,247,248,249,244',
+'246,254,255,250,251,-292,231,232,-292,736,252,253,-292,40,746,-292,294',
+'750,751,58,59,-292,-264,60,-292,35,235,757,241,44,237,236,477,233,234',
+'245,243,239,20,240,477,218,257,89,79,82,83,584,84,86,85,87,488,490,939',
+'799,80,88,677,256,218,263,263,585,62,677,81,93,94,5,69,70,71,9,57,238',
+'806,584,63,64,218,218,831,67,939,65,66,68,30,31,72,73,218,585,806,841',
+'218,29,28,27,101,100,102,103,218,850,19,-265,859,861,862,635,8,45,7',
+'10,105,104,106,95,56,97,96,98,692,99,107,108,865,91,92,867,42,43,41',
+'238,242,247,248,249,244,246,254,255,250,251,-291,231,232,-488,869,252',
+'253,-291,40,871,-488,33,-575,218,58,59,-291,873,60,-488,35,235,874,241',
+'44,237,236,877,233,234,245,243,239,20,240,879,880,677,89,79,82,83,-489',
+'84,86,85,87,882,-263,-489,886,80,88,888,256,891,692,893,-489,62,895',
+'81,93,94,290,69,70,71,9,57,897,899,986,63,64,899,218,905,67,987,65,66',
+'68,30,31,72,73,907,985,909,915,918,29,28,27,101,100,102,103,218,936',
+'19,545,544,543,922,546,8,45,292,10,105,104,106,95,56,97,96,98,-266,99',
+'107,108,933,91,92,940,42,43,41,238,242,247,248,249,244,246,254,255,250',
+'251,-291,231,232,-281,941,252,253,-291,40,950,-281,33,-575,951,58,59',
+'-291,959,60,-281,35,235,961,241,44,237,236,962,233,234,245,243,239,20',
+'240,967,736,692,89,79,82,83,-292,84,86,85,87,971,973,-292,975,80,88',
+'977,256,977,988,989,-292,62,899,81,93,94,290,69,70,71,9,57,899,899,994',
+'63,64,959,-575,-574,67,682,65,66,68,30,31,72,73,116,117,118,119,120',
+'29,28,27,101,100,102,103,959,936,19,545,544,543,1013,546,8,45,292,10',
+'105,104,106,95,56,97,96,98,1014,99,107,108,1015,91,92,977,42,43,41,238',
+'242,247,248,249,244,246,254,255,250,251,-291,231,232,977,977,252,253',
+'-291,40,218,899,33,-575,959,58,59,-291,977,60,,35,235,,241,44,237,236',
+',233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,256',
+',,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72',
+'73,116,117,118,119,120,29,28,27,101,100,102,103,,,19,116,117,118,119',
+'120,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'41,238,242,247,248,249,244,246,254,255,250,251,,231,232,,,252,253,,40',
+',,294,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245,243,239,20,240',
+',,,89,79,82,83,,84,86,85,87,,,,,80,88,,256,,,,,62,,81,93,94,290,69,70',
+'71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102',
+'103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91',
+'92,,42,43,41,238,242,247,248,249,244,246,254,255,250,251,,231,232,,',
+'252,253,,40,,,294,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245',
+'243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,256,,,,,62,,81',
+'93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29',
+'28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96',
+'98,,99,107,108,,91,92,,42,43,41,238,242,247,248,249,244,246,254,255',
+'250,251,,231,232,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237',
+'236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88',
+'218,256,,,,,62,,81,93,94,5,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30',
+'31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,7,10,105,104,106',
+'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248,249,244',
+'246,254,255,250,251,,231,232,,,252,253,,40,,,33,,,58,59,,,60,,35,235',
+',241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85',
+'87,,,,,80,88,,256,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67',
+',65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292',
'10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247',
'248,249,244,246,254,255,250,251,,231,232,,,252,253,,40,,,33,,,58,59',
',,60,,35,235,,241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82',
'83,,84,86,85,87,,,,,80,88,,256,,,,,62,,81,93,94,290,69,70,71,9,57,,',
-',63,64,,,,67,,65,66,68,30,31,72,73,116,117,118,119,120,29,28,27,101',
-'100,102,103,,,19,116,117,118,119,120,8,45,292,10,105,104,106,95,56,97',
-'96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248,249,244,246,254,255',
-'250,251,,231,232,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237',
-'236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88',
-',256,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30',
-'31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104',
-'106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248,249',
-'244,246,254,255,250,251,,231,232,,,252,253,,40,,,33,,,58,59,,,60,,35',
-'235,,241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86',
-'85,87,,,,,80,88,,256,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,',
-'67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45',
-'292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242',
-'247,248,249,244,246,254,255,250,251,,231,232,,,252,253,,40,,,294,,,58',
-'59,,,60,,35,235,,241,44,237,236,,233,234,245,243,239,20,240,,,,89,79',
-'82,83,,84,86,85,87,,,,,80,88,218,256,,,,,62,,81,93,94,290,69,70,71,9',
-'57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103',
-',,19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92',
-',42,43,41,238,242,247,248,249,244,246,254,255,250,251,,231,232,,,252',
-'253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245,243,239',
-'20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,256,,,,,62,,81,93,94,5',
-'69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101',
-'100,102,103,,,19,,,,,,8,45,7,10,105,104,106,95,56,97,96,98,,99,107,108',
-',91,92,,42,43,41,238,242,247,248,249,244,246,254,255,250,251,,231,232',
-',,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245',
-'243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,256,,,,,62,,81',
-'93,94,5,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28',
-'27,101,100,102,103,,,19,,,,,,8,45,7,10,105,104,106,95,56,97,96,98,,99',
-'107,108,,91,92,,42,43,41,238,242,247,248,249,244,246,254,255,250,251',
-',231,232,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233',
-'234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,256,,',
-',,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73',
-',,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95,56',
-'97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248,249,244,246,254',
-'255,250,251,,231,232,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44',
-'237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,',
-'80,88,,256,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66',
-'68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105',
-'104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248',
-'249,244,246,254,255,250,251,,231,232,,,252,253,,40,,,33,,,58,59,,,60',
-',35,235,,241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,',
-'84,86,85,87,,,,,80,88,,256,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63',
-'64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,',
-',,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+',63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19',
+',,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
'41,238,242,247,248,249,244,246,254,255,250,251,,231,232,,,252,253,,40',
',,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245,243,239,20,240',
',,,89,79,82,83,,84,86,85,87,,,,,80,88,,256,,,,,62,,81,93,94,290,69,70',
@@ -175,58 +160,69 @@ clist = [
'254,255,250,251,,231,232,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241',
'44,237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,',
',,,80,88,,256,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65',
-'66,68,30,31,72,73,,553,,,,29,28,27,101,100,102,103,556,548,19,545,544',
-'543,,546,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,',
-'42,43,41,238,,564,563,,,238,557,701,548,,545,544,543,,546,,904,,40,',
-',33,,,58,59,,,60,,35,235,,,44,237,236,235,233,234,,237,236,20,233,234',
-'701,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,290,69,70',
+'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10',
+'105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247',
+'248,249,244,246,254,255,250,251,,231,232,,,252,253,,40,,,33,,,58,59',
+',,60,,35,235,,241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82',
+'83,,84,86,85,87,,,,,80,88,,256,,,,,62,,81,93,94,290,69,70,71,9,57,,',
+',63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19',
+',,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'41,238,242,247,248,249,244,246,254,255,250,251,,231,232,,,252,253,,40',
+',,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245,243,239,20,240',
+',,,89,79,82,83,,84,86,85,87,,,,,80,88,,256,,,,,62,,81,93,94,290,69,70',
'71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102',
+'103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91',
+'92,,42,43,41,238,242,247,248,249,244,246,254,255,250,251,,231,232,,',
+'252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245,243',
+'239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,256,,,,,62,,81,93',
+'94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28',
+'27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98',
+',99,107,108,,91,92,,42,43,41,238,242,247,248,249,244,246,254,255,250',
+'251,,-597,-597,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236',
+',233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,',
+',,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72',
+'73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95',
+'56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248,249,244,246',
+'254,255,250,251,,-597,-597,,,252,253,,40,,,33,,,58,59,,,60,,35,235,',
+'241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85',
+'87,,,,,80,88,,,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65',
+'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,548,19,545,544,543',
+',546,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'41,238,-597,-597,-597,-597,244,246,,701,-597,-597,,,,,,252,253,,40,',
+',33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245,243,239,20,240',
+',,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,290,69,70,71',
+'9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102',
'103,,548,19,545,544,543,,546,8,45,292,10,105,104,106,95,56,97,96,98',
',99,107,108,,91,92,,42,43,41,238,,,548,,545,544,543,701,546,,,,,,,252',
'253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,701,,239',
'20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,290',
'69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101',
+'100,102,103,,548,19,545,544,543,,546,8,45,292,10,105,104,106,95,56,97',
+'96,98,,99,107,108,,91,92,,42,43,41,238,,,,,,,,701,,,,,,,,252,253,,40',
+',,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,,,239,20,240,,,,89',
+'79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,290,69,70,71,9,57',
+',,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,',
+',19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,',
+'42,43,41,238,,,,,,,,,,,,,,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241',
+'44,237,236,,233,234,,,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80',
+'88,,,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30',
+'31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104',
+'106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,,,,,,,,,,,,,,,,252',
+'253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,,,239,20',
+'240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,290,69',
+'70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100',
+'102,103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108',
+',91,92,,42,43,41,238,-597,-597,-597,-597,244,246,,,-597,-597,,,,,,252',
+'253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245,243,239',
+'20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,290',
+'69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101',
'100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107',
-'108,,91,92,,42,43,41,238,,,,,,,,,,,,,,,,252,253,,40,,,33,,,58,59,,,60',
-',35,235,,241,44,237,236,,233,234,,,239,20,240,,,,89,79,82,83,,84,86',
-'85,87,,,,,80,88,,,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67',
-',65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292',
-'10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247',
-'248,249,244,246,,,250,251,,,,,,252,253,,40,,,33,,,58,59,,,60,,35,235',
-',241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85',
-'87,,,,,80,88,,,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65',
-'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10',
-'105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247',
-'248,249,244,246,254,255,250,251,,-597,-597,,,252,253,,40,,,33,,,58,59',
-',,60,,35,235,,241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82',
-'83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63',
-'64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,',
-',,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
-'41,238,,,,,,,,,,,,,,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44',
-'237,236,,233,234,,,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88',
-',,,,,,62,,81,93,94,5,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72',
-'73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,7,10,105,104,106,95',
-'56,97,96,98,,99,107,108,,91,92,,42,43,41,238,-597,-597,-597,-597,244',
-'246,,,-597,-597,,,,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237',
-'236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88',
-',,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31',
-'72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106',
-'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248,249,244',
-'246,254,255,250,251,,-597,-597,,,252,253,,40,,,33,,,58,59,,,60,,35,235',
-',241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85',
-'87,,,,,80,88,,,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65',
-'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10',
-'105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,,,,,,,,',
-',,,,,,,252,253,,40,,,294,,,58,59,,,60,,35,235,,241,44,237,236,,233,234',
-',,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94',
-'290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27',
-'101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99',
-'107,108,,91,92,,42,43,41,238,-597,-597,-597,-597,244,246,,,-597,-597',
-',,,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234',
-'245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81',
-'93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29',
-'28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96',
-'98,,99,107,108,,91,92,,42,43,41,238,-597,-597,-597,-597,244,246,,,-597',
+'108,,91,92,,42,43,41,238,-597,-597,-597,-597,244,246,,,-597,-597,,,',
+',,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,245',
+'243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93',
+'94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28',
+'27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98',
+',99,107,108,,91,92,,42,43,41,238,-597,-597,-597,-597,244,246,,,-597',
'-597,,,,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233',
'234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62',
',81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,',
@@ -237,74 +233,68 @@ clist = [
',,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72',
'73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95',
'56,97,96,98,,99,107,108,,91,92,,42,43,41,238,-597,-597,-597,-597,244',
-'246,,,-597,-597,,,,,,252,253,,40,,,294,,,58,59,,,60,,35,235,,241,44',
+'246,,,-597,-597,,,,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237',
+'236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88',
+',,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31',
+'72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106',
+'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248,249,244',
+'246,,,250,251,,,,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44,237',
+'236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88',
+',,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31',
+'72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106',
+'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248,249,244',
+'246,254,,250,251,,,,,,252,253,,40,,,33,,,58,59,,,60,,35,235,,241,44',
'237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,',
-'80,88,,,,,,,62,,81,93,94,290,69,70,71,9,57,,,,63,64,,,,67,,65,66,68',
-'30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,292,10,105',
-'104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,242,247,248',
-'249,244,246,254,,250,251,,,,,,252,253,,40,,,33,,,58,59,,,60,,35,235',
-',241,44,237,236,,233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85',
-'87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31',
-'72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56',
-'97,96,98,,99,107,108,,91,92,,42,43,41,238,-597,-597,-597,-597,244,246',
-',,-597,-597,,,,,,252,253,,223,,,229,,,58,59,,,60,,,235,,241,44,237,236',
-',233,234,245,243,239,20,240,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,',
-',69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28',
-'27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107',
-'108,,91,92,,42,43,41,238,,,,,,,,,,,,,,,,252,253,,223,,,229,,,58,59,',
-',60,,,235,,241,44,237,236,,233,234,,,,20,,,,,89,79,82,83,,84,86,85,87',
-',,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72',
-'73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97',
-'96,98,,99,107,108,,91,92,,42,43,41,238,,,,,,,,,,,,,,,,252,253,,223,',
-',229,,,58,59,,,60,,,235,,241,44,237,236,,233,234,,,,20,,,,,89,79,82',
-'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
-'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105',
-'104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,,,,,,,,,,,,',
-',,,252,253,,223,,,229,,,58,59,,,60,,,235,,,44,237,236,,233,234,,,,20',
-',,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,69,70,71,9',
-'57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103',
-',,19,,,,,,8,45,,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42',
-'43,41,,,,,,,,,,,,,,,,,,,,40,,,33,,,58,59,,,60,,35,,,,44,,,,,,,,,20,',
-',,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
-'64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,',
-',,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,',
-',,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79',
-'82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67',
-',65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,',
-',45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,',
-',,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82',
-'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
-'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105',
-'104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,',
-',,,223,,,229,,,58,59,,,60,,404,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84',
-'86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68',
-'30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106',
-'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,',
-',229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,',
-',,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73',
+'80,88,,,,,,,62,,81,93,94,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31',
+'72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,7,10,105,104,106',
+'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,,,,,,,,,,,,,,,,252,253',
+',40,,,33,,,58,59,,,60,,35,235,,241,44,237,236,,233,234,,,,20,,,,,89',
+'79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,',
+'67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45',
+',,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,238,,,,,,',
+',,,,,,,,,252,253,,223,,,229,,,58,59,,,60,,,235,,241,44,237,236,,233',
+'234,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57',
+'81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102',
+'103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92',
+',42,43,41,238,,,,,,,,,,,,,,,,252,253,,223,,,229,,,58,59,,,60,,281,235',
+'279,,44,237,236,285,233,234,,,,228,,,,,89,282,82,83,,84,86,85,87,,,',
+',80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73',
',,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97',
'96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,',
',58,59,,,60,,281,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85',
-'87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310',
-'72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106',
-'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,',
-',229,,,58,59,,,60,,404,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87',
+'87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31',
+'72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95',
+'56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,',
+',229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84',
+'86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68',
+'309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105',
+'104,106,95,56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,',
+'303,,,299,,,58,59,,,60,,298,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87',
',,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72',
'73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,95',
-'56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,303,,,299,',
-',58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,',
-',69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28',
-'27,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107',
-'108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,',
-'44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62',
-'57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100',
-'102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91',
-'92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,404,,,,44,,',
-',,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81',
-'93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103',
-',,19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
-'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,',
-'89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
+'56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,303,,,229,',
+',58,59,,,60,,548,,545,544,543,553,546,,,,,,,,,,556,,89,79,82,83,,84',
+'86,85,87,,,,,80,88,,,,315,,551,62,,81,93,94,69,70,71,,57,564,563,,63',
+'64,557,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103',
+',,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,',
+',89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
+',,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230',
+',,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,',
+',,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89',
+'79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,',
+'67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,',
+',,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,',
+',,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79',
+'82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67',
+',65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,',
+',45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,',
+',,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,,,44,,,285,,,,,,228,,,',
+',89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
+',,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230',
+',,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41',
+',,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,285,,,,,,228,,,',
+',89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
',,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,',
',45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,',
',,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82',
@@ -316,30 +306,77 @@ clist = [
'31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95',
'56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229',
',,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80',
-'88,218,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73',
-',,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,95,56',
-'97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,303,,,299,,,58',
-'59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69',
-'70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306',
-'312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99',
-'107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,',
-',,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71',
-'62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312',
-'101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107',
-'108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,',
-'44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62',
-'57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101',
-'100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108',
+'88,113,,,,,112,62,,81,93,94,69,70,71,,57,,,,63,64,,,,67,,65,66,68,309',
+'310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104',
+'106,95,56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,348',
+',,33,,,58,59,,,60,,35,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,',
+'80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73',
+',,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,353,56',
+'97,96,354,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,360,,,355,,,229',
+',,58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,',
+',,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305',
+'306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,353,56,97,96,354',
+',99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,355,,,229,,,58,59,,,60',
+',548,,545,544,543,553,546,,,,,,,,,,556,,89,79,82,83,,84,86,85,87,,,',
+',80,88,,,,,,551,62,,81,93,94,69,70,71,9,57,564,563,,63,64,557,,,67,',
+'65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,7',
+'10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,',
+',,,,,,,,,,40,,,33,,,58,59,,,60,,35,,,,44,,,,,,,,,20,,,,,89,79,82,83',
+',84,86,85,87,,,,,80,88,,,,,,388,62,,81,93,94,69,70,71,,57,,,,63,64,',
+',,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,',
+'45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,',
+',,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83',
+',84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66',
+'68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104',
+'106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223',
+',,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,',
+',,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73',
+',,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96',
+'98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59',
+',,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69',
+'70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27',
+'101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108',
',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,',
-',,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57',
-'81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100',
-'102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91',
-'92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,',
-',,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93',
-'94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102',
-'103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,',
-'42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228',
+',,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94',
+'69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101',
+'100,102,103,,,19,,,,,,8,45,,10,105,104,106,95,56,97,96,98,,99,107,108',
+',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,40,,,33,,,58,59,,,60,,35,,,,44,',
+',,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81',
+'93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103',
+',,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,404,,,,44,,,,,,,,,228',
',,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
+'64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,',
+',,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,',
+',,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79',
+'82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67',
+',65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,',
+',105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,',
+',,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228,,,,,89',
+'282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,',
+',67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,',
+'45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,',
+',,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82',
+'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
+'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105',
+'104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,',
+',,,223,,,229,,,58,59,,,60,,404,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84',
+'86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68',
+'30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106',
+'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,',
+',229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,',
+',,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73',
+',,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96',
+'98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59',
+',,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69',
+'70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27',
+'101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108',
+',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,',
+',,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81',
+'93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103',
+',,19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,',
+'89,79,82,83,,84,86,85,87,,,,,80,88,218,,,69,70,71,62,57,81,93,94,63',
'64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,',
'230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,',
@@ -434,8 +471,12 @@ clist = [
',,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97',
'96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58',
'59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,',
-',,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29',
-'28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99',
+',,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305',
+'306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98',
+',99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,',
+'60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69',
+'70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306',
+'312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99',
'107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,',
',,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71',
'62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100',
@@ -450,237 +491,181 @@ clist = [
'100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108',
',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,279',
',44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88,218,,,69',
-'70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27',
+'70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306',
+'312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99',
+'107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,',
+',,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71',
+'62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312',
'101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107',
'108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,',
'44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62',
-'57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100',
+'57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101',
+'100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108',
+',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,',
+',,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57',
+'81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100',
'102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91',
'92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,',
-',,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93',
-'94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,',
-',230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
-'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,',
-',89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
-',,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230',
-',,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,',
-',,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89',
-'79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,',
-'67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45',
-',,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,',
-',,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83',
-',84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66',
-'68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105',
+',,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,69',
+'70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100',
+'102,103,,,19,,,,,,8,45,,10,105,104,106,95,56,97,96,98,,99,107,108,,91',
+'92,,42,43,41,,,,,,,,,,,,,,,,,,,,40,,,33,,,58,59,,,60,,35,,,,44,,,,,',
+',,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93',
+'94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102',
+'103,,,230,,,,,,,307,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92',
+',,,313,,,,,,,,,,,,,,,,,,,,303,,,229,,,58,59,,,60,,548,,545,544,543,553',
+'546,,,,,,,,,,556,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,504,,551,62',
+',81,93,94,69,70,71,,57,564,563,,63,64,557,,,67,,65,66,68,309,310,72',
+'73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,95',
+'56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,303,,,299,',
+',58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,',
+',69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305',
+'306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98',
+',99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,520,,58,59',
+',,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69',
+'70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27',
+'101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108',
+',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,',
+',,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81',
+'93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103',
+',,19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,',
+'89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
+',,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,',
+',45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,',
+',,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82',
+'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
+'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105',
'104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,',
-',,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86',
-'85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309',
-'310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104',
-'106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223',
-',,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87',
-',,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72',
-'73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95',
+',,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86',
+'85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30',
+'31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95',
'56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229',
-',,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80',
+',,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80',
'88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,',
',,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97',
-'96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,',
-',58,59,,,60,,,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87',
-',,,,80,88,,,,,,,62,,81,93,94,69,70,71,9,57,,,,63,64,,,,67,,65,66,68',
-'30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,8,45,,10,105,104',
-'106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,40',
-',,33,,,58,59,,,60,,35,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87',
-',,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72',
-'73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95',
-'56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,',
-',229,,,58,59,,,60,,659,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84',
-'86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68',
-'309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105',
-'104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,',
-',,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86',
-'85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309',
-'310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104',
-'106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223',
-',,229,,,58,59,,,60,,754,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85',
-'87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31',
-'72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95',
-'56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,',
-',229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84',
-'86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68',
-'30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106',
-'95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223',
-',,229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84',
-'86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68',
-'309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105',
-'104,106,95,56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,',
-'303,,,229,,,58,59,,,60,,548,,545,544,543,553,546,,,,,,,,,,556,,89,79',
-'82,83,,84,86,85,87,,,,,80,88,,,,504,,551,62,,81,93,94,69,70,71,,57,564',
-'563,,63,64,557,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100',
-'102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91',
-'92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,,,44,,',
-',,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81',
-'93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102',
+'96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58',
+'59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,',
+',,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29',
+'28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,284',
+'99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60',
+',281,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88',
+',,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,',
+'305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96',
+'98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59',
+',,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69',
+'70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306',
+'312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99',
+'107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,',
+',,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71',
+'62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312',
+'101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107',
+'108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,',
+'44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62',
+'57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101',
+'100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108',
+',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,',
+',,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57',
+'81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100',
+'102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,',
+'91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,659,,279',
+',44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70',
+'71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312',
+'101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107',
+'108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,279',
+',44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70',
+'71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312',
+'101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107',
+'108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,',
+'44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93',
+'94,69,70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27',
+'101,100,102,103,,,19,,,,,,8,45,292,10,105,104,106,95,56,97,96,98,,99',
+'107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,40,,,33,,,58,59,,,60,,35',
+',,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,388,62',
+',81,93,94,69,70,71,,57,,,,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305',
+'306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,95,56,97,96,98',
+',99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,303,,,299,,,58,59,,,60',
+',,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62',
+'57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100',
+'102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,',
+'91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,279',
+',44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70',
+'71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312',
+'101,100,102,103,,,230,,,,,,,307,,,105,104,106,95,56,97,96,98,,99,107',
+'108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,303,,,299,,,58,59,,,60,,,,,,,,',
+',,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93',
+'94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102',
'103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,',
'42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228',
',,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
'64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,',
-'230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42',
-'43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,285,,,,,,228',
-',,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
-'64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,',
-'230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42',
-'43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,659,,,,44,,,285,,,',
-',,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93',
-'94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,',
-',19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
-'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,',
-'89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
+'230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,',
+',89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
+',,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,',
+',45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,',
+',,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82',
+'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
+'66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45',
+',,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,',
+',,,,,,,,,,,,223,,,229,,,58,59,,,60,,659,,,,44,,,285,,,,,,228,,,,,89',
+'282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,',
+',67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,',
+',,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41',
+',,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,285,,,,,,228,,,',
+',89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
',,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230',
',,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,',
',,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89',
'79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,',
'67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,',
',,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,',
-',,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79',
-'82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67',
-',65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,',
-',307,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,',
-',,,,,,,,,,,303,,,299,,,58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84',
-'86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68',
-'30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106',
-'95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223',
-',,229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84',
-'86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68',
-'309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105',
-'104,106,95,56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,',
-'303,,,299,,,58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,',
-',,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72',
-'73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,95',
-'56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,303,,,299,',
-',58,59,,,60,,548,,545,544,543,553,546,,,,,,,,,,556,,89,79,82,83,,84',
-'86,85,87,,,,,80,88,,,,,,551,62,,81,93,94,69,70,71,9,57,564,563,,63,64',
-'557,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,',
-',,,8,45,292,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
-'41,,,,,,,,,,,,,,,,,,,,40,,,33,,,58,59,,,60,,35,,,,44,,,,,,,,,20,,,,',
-'89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,388,62,,81,93,94,69,70,71,,57',
-',,,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102',
-'103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,',
-'42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228',
-',,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
+',,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,,,44,,,,,,,,,228,,,,,89',
+'79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,',
+'67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45',
+',,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,',
+',,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228,,,,',
+'89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
+',,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,',
+',,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,',
+',,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228',
+',,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
'64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,',
'230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
-'41,,,,,,,,,,,,,,,,,,,,223,,,229,520,,58,59,,,60,,,,,,44,,,,,,,,,228',
+'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,754,,,,44,,,,,,,,,228',
',,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
-'64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,',
-',,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,',
-',,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79',
-'82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67',
-',65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,',
-',45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,',
-',,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,279,,44,,,285,,,,,,228,,,',
-',89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
+'64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,',
+'230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,',
+',89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
',,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230',
',,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41',
',,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,659,,279,,44,,,285,,,,,,228',
',,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
'64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,',
-'230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
+'230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42',
+'43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,279,,44,,,285,,,',
+',,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93',
+'94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,',
+',230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,',
',89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
-',,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230',
-',,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,',
-',,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89',
-'79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,',
-'67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,',
-',,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,',
-',,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79',
-'82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67',
-',65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,',
-',45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,',
-',,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82',
+',,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,',
+',,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,',
+',,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82',
'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105',
-'104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,',
-',,,,,,223,,,229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228,,,,,89,282',
-'82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67',
-',65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,',
-',45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,',
-',,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82',
-'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
-'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105',
'104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,',
-',,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86',
+',,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86',
'85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30',
-'31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95',
-'56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229',
-',,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80',
-'88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,',
-',29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96,98',
-',99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,',
-'60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70',
-'71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101',
-'100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,',
-'91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,',
-',,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,69',
-'70,71,9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100',
-'102,103,,,19,,,,,,8,45,7,10,105,104,106,95,56,97,96,98,,99,107,108,',
-'91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,40,,,33,,,58,59,,,60,,35,,,,44,,',
-',,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81',
-'93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102',
-'103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,',
-'42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228',
-',,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
-'64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,',
-'230,,,,,,,307,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,,,313',
-',,,,,,,,,,,,,,,,,,,947,,,229,,,58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82',
-'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
-'66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307',
-',,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,',
-',,,,,,876,,,229,,,58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85',
-'87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310',
-'72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106',
+'31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106',
'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,',
',229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,',
-',,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72',
-'73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95',
-'56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,',
-',229,,,58,59,,,60,,,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84,86',
-'85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309',
-'310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104',
-'106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223',
-',,229,,,58,59,,,60,,659,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85',
-'87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31',
-'72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95',
-'56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229',
-',,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80',
-'88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,',
-',29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96,98',
-',99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,',
-'60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70',
-'71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101',
-'100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108',
-',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,279',
-',44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70',
-'71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101',
-'100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108',
-',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,279',
-',44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70',
-'71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101',
-'100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108',
-',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,279',
-',44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70',
-'71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312',
-'101,100,102,103,,,230,,,,,,,307,,,105,104,106,95,56,97,96,98,,99,107',
-'108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,303,,,299,,,58,59,,,60,,298,,,',
-',,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81',
-'93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102',
-'103,,,230,,,,,,,307,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92',
-',,,313,,,,,,,,,,,,,,,,,,,,303,,,229,,,58,59,,,60,,548,,545,544,543,553',
-'546,,,,,,,,,,556,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,315,,551,62',
-',81,93,94,69,70,71,,57,564,563,,63,64,557,,,67,,65,66,68,309,310,72',
-'73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,95',
-'56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,876,,,229,',
-',58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,',
-',69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305',
+',,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73',
+',,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97',
+'96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58',
+'59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,',
+',,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305',
'306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98',
',99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,',
'60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69',
@@ -693,10 +678,33 @@ clist = [
'108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,',
'44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62',
'57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101',
-'100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108',
-',91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,',
-',,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57',
-'81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100',
+'100,102,103,,,230,,,,,,,307,,,105,104,106,95,56,97,96,98,,99,107,108',
+',91,92,,,,313,,,,,,,,,,,,,,,,,,,,303,,,299,,,58,59,,,60,,,,,,,,,,,,',
+',,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94',
+'63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103',
+',,230,,,,,,,307,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,,,313',
+',,,,,,,,,,,,,,,,,,,303,,,299,,,58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82',
+'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
+'66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45',
+',,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,',
+',,,,,,,,,223,,,229,,,58,59,,,60,,404,,,,44,,,,,,,,,228,,,,,89,79,82',
+'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
+'66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45',
+',,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,',
+',,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83',
+',84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66',
+'68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104',
+'106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223',
+',,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,',
+',,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73',
+',,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96',
+'98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59',
+',,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69',
+'70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306',
+'312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99',
+'107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,',
+',,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71',
+'62,57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100',
'102,103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91',
'92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,',
',,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93',
@@ -708,176 +716,167 @@ clist = [
'230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43',
'41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,',
',89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
-',,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,',
-',,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,',
-',,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82',
-'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
-'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,,,,,,,45,,,105',
-'104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,',
-',,,,,,223,,,229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228,,,,,89,282',
+',,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230',
+',,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,',
+',,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89',
+'79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,',
+'67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,',
+',,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,',
+',,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79',
'82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67',
',65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,',
-',45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,',
-',,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82',
-'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
-'66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45',
-',,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,',
-',,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,,,44,,,285,,,,,,228,,,,,89',
-'282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,',
-',67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102,103,,,230,',
-',,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41',
-',,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,285,,,,,,228,,,',
-',89,282,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64',
-',,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,',
-',45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,',
-',,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82',
-'83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65',
-'66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105',
-'104,106,95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,',
-',,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86',
-'85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,30',
-'31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106,95',
+',307,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,',
+',,,,,,,,,,,876,,,229,,,58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84',
+'86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68',
+'30,31,72,73,,,,,,29,28,27,101,100,102,103,,,19,,,,,,,45,,,105,104,106',
+'95,56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,',
+',229,,,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,',
+',,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72',
+'73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95',
'56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229',
-',,58,59,,,60,,,,,,44,,,,,,,,,20,,,,,89,79,82,83,,84,86,85,87,,,,,80',
-'88,113,,,,,112,62,,81,93,94,69,70,71,,57,,,,63,64,,,,67,,65,66,68,309',
-'310,72,73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104',
-'106,95,56,97,96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,348',
-',,33,,,58,59,,,60,,35,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,',
-'80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73',
-',,,,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,353,56',
-'97,96,354,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,360,,,355,,,229',
-',,58,59,,,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,',
-',,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305',
-'306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,353,56,97,96,354',
-',99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,355,,,229,,,58,59,,,60',
-',,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62',
-'57,81,93,94,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100',
-'102,103,,,19,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92',
-',42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,',
-'20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,,,62,,81,93,94,69,70,71',
-'9,57,,,,63,64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102',
-'103,,,19,,,,,,8,45,7,10,105,104,106,95,56,97,96,98,,99,107,108,,91,92',
-',42,43,41,,,,,,,,,,,,,,,,,,,,40,,,33,,,58,59,,,60,,35,,,,44,,,,,,,,',
-'20,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,,-579,388,62,,81,93,94',
-'-579,-579,-579,,,-579,-579,-579,,-579,,,,,,,,,-579,-579,-579,-579,,',
-',,,,,-579,-579,,-579,-579,-579,-579,-579,,,,,,,,,,,,,,,,,,,,,,,,-579',
-'-579,-579,-579,-579,-579,-579,-579,-579,-579,-579,-579,-579,-579,,,-579',
-'-579,-579,,,-579,,,-579,,,-579,-579,,-579,,-579,,-579,,-579,-579,,-579',
-'-579,-579,-579,-579,,-579,-579,-579,,,,,,,,,,,,,,-579,,,-579,-579,-579',
-'-579,-282,-579,,-579,,,,-282,-282,-282,,,-282,-282,-282,,-282,,,,,,',
-',,,-282,-282,-282,,,,,,,,-282,-282,,-282,-282,-282,-282,-282,,,,,,,',
-',,,,,,,,,,,,,,,,-282,-282,-282,-282,-282,-282,-282,-282,-282,-282,-282',
-'-282,-282,-282,,,-282,-282,-282,,,-282,,,-282,,,-282,-282,,-282,,-282',
-',-282,,-282,-282,,-282,-282,-282,-282,-282,,-282,,-282,,,,,,,,,,,,,',
-'-282,,,-282,-282,-282,-282,-580,-282,,-282,,,,-580,-580,-580,,,-580',
-'-580,-580,,-580,,,,,,,,,-580,-580,-580,-580,,,,,,,,-580,-580,,-580,-580',
-'-580,-580,-580,,,,,,,,,,,,,,,,,,,,,,,,-580,-580,-580,-580,-580,-580',
-'-580,-580,-580,-580,-580,-580,-580,-580,,,-580,-580,-580,,,-580,,,-580',
-',,-580,-580,,-580,,-580,,-580,,-580,-580,,-580,-580,-580,-580,-580,',
-'-580,-580,-580,,,,,,,,,,,,,,-580,,,-580,-580,-580,-580,-411,-580,,-580',
-',,,-411,-411,-411,,,-411,-411,-411,,-411,,,,,,,,,-411,-411,-411,,,,',
-',,,,-411,-411,,-411,-411,-411,-411,-411,,,,,,,,,,,,,,,,,,,,,,,,-411',
-'-411,-411,-411,-411,-411,-411,-411,-411,-411,-411,-411,-411,-411,,,-411',
-'-411,-411,,,-411,,263,-411,,,-411,-411,,-411,,-411,,-411,,-411,-411',
-',-411,-411,-411,-411,-411,,-411,-411,-411,,,,,,,,,,,,,,-411,,-246,-411',
-'-411,,-411,,-411,-246,-246,-246,,,-246,-246,-246,548,-246,545,544,543',
-'553,546,,,,-246,-246,,,,,556,,,,,-246,-246,,-246,-246,-246,-246,-246',
-',,,,,,,,,551,,,,,,,,,561,560,564,563,,,,557,,,,,,,,,-246,,-298,,,,,-246',
-',-298,-298,-298,263,-246,-298,-298,-298,218,-298,,,,,,,,,,-298,-298',
-',,,,,-246,-246,,-298,-298,,-298,-298,-298,-298,-298,,,,,-246,,,-246',
-',,,,-246,,,,,,,,,,,-298,-298,-298,-298,-298,-298,-298,-298,-298,-298',
-'-298,-298,-298,-298,,,-298,-298,-298,,,-298,,272,-298,,,-298,-298,,-298',
-',-298,,-298,,-298,-298,,-298,-298,-298,-298,-298,,-298,-246,-298,,,',
-',,-246,-246,-246,,,-246,-246,-246,-298,-246,,-298,-298,,-298,,-298,',
-'-246,-246,-246,,,,,,,,,-246,-246,,-246,-246,-246,-246,-246,,,,,,,,,',
-',,,,,,,,,,,,,,-246,-246,-246,-246,-246,-246,-246,-246,-246,-246,-246',
-'-246,-246,-246,,,-246,-246,-246,,,-246,,263,-246,,,-246,-246,,-246,',
-'-246,,-246,,-246,-246,,-246,-246,-246,-246,-246,,-246,-246,-246,,,,',
-',,,,,,,,,-246,,,-246,-246,,-246,,-246,173,184,174,197,170,190,180,179',
-'200,201,195,178,177,172,198,202,203,182,171,185,189,191,183,176,,,,192',
-'199,194,193,186,196,181,169,188,187,,,,,,168,175,166,167,163,164,165',
-'124,126,,,125,,,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140',
-',,,159,160,146,147,,,,,,,,,,,,,,151,150,,135,156,153,152,161,148,149',
-'143,141,133,155,134,,,162,89,,,,,,,,,,,,,,88,173,184,174,197,170,190',
-'180,179,200,201,195,178,177,172,198,202,203,182,171,185,189,191,183',
-'176,,,,192,199,194,193,186,196,181,169,188,187,,,,,,168,175,166,167',
-'163,164,165,124,126,123,,125,,,,,,,,,157,158,,154,136,137,138,145,142',
-'144,,,139,140,,,,159,160,146,147,,,,,,,,,,,,,,151,150,,135,156,153,152',
-'161,148,149,143,141,133,155,134,,,162,89,,,,,,,,,,,,,,88,173,184,174',
-'197,170,190,180,179,200,201,195,178,177,172,198,202,203,182,171,185',
-'189,191,183,176,,,,192,199,194,193,186,196,181,169,188,187,,,,,,168',
-'175,166,167,163,164,165,124,126,,,125,,,,,,,,,157,158,,154,136,137,138',
-'145,142,144,,,139,140,,,,159,160,146,147,,,,,,,,,,,,,,151,150,,135,156',
-'153,152,161,148,149,143,141,133,155,134,,,162,89,,,,,,,,,,,,,,88,173',
+',,58,59,,,60,,659,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,',
+',80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73',
+',,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95,56',
+'97,96,98,284,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229',
+',,58,59,,,60,,,,279,,44,,,285,,,,,,228,,,,,89,282,82,83,,84,86,85,87',
+',,,,80,88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72',
+'73,,,,,,305,306,312,101,100,102,103,,,230,,,,,,,45,,,105,104,106,95',
+'56,97,96,98,,99,107,108,,91,92,,42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229',
+',,58,59,,,60,,,,,,44,,,,,,,,,228,,,,,89,79,82,83,,84,86,85,87,,,,,80',
+'88,,,,69,70,71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,',
+',,,305,306,312,101,100,102,103,,,230,,,,,,,307,,,105,104,106,95,56,97',
+'96,98,,99,107,108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,876,,,229,,,58,59',
+',,60,,,,,,,,,,,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70',
+'71,62,57,81,93,94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312',
+'101,100,102,103,,,230,,,,,,,307,,,105,104,106,95,56,97,96,98,,99,107',
+'108,,91,92,,,,313,,,,,,,,,,,,,,,,,,,,947,,,229,,,58,59,,,60,,,,,,,,',
+',,,,,,,,,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93',
+'94,63,64,,,,67,,65,66,68,309,310,72,73,,,,,,305,306,312,101,100,102',
+'103,,,230,,,,,,,45,,,105,104,106,95,56,97,96,98,,99,107,108,,91,92,',
+'42,43,41,,,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,,,,,44,,,,,,,,,228',
+',,,,89,79,82,83,,84,86,85,87,,,,,80,88,,,,69,70,71,62,57,81,93,94,63',
+'64,,,,67,,65,66,68,30,31,72,73,,,,,,29,28,27,101,100,102,103,,,230,',
+',,,,,45,,,105,104,106,95,56,97,96,98,284,99,107,108,,91,92,,42,43,41',
+',,,,,,,,,,,,,,,,,,,223,,,229,,,58,59,,,60,,281,,279,,44,,,285,,,,,,228',
+',,,,89,282,82,83,,84,86,85,87,,,,,80,88,,,,,-282,,62,,81,93,94,-282',
+'-282,-282,,,-282,-282,-282,,-282,,,,,,,,,,-282,-282,-282,,,,,,,,-282',
+'-282,,-282,-282,-282,-282,-282,,,,,,,,,,,,,,,,,,,,,,,,-282,-282,-282',
+'-282,-282,-282,-282,-282,-282,-282,-282,-282,-282,-282,,,-282,-282,-282',
+',,-282,,,-282,,,-282,-282,,-282,,-282,,-282,,-282,-282,,-282,-282,-282',
+'-282,-282,,-282,,-282,,,,,,,,,,,,,,-282,,,-282,-282,-282,-282,-579,-282',
+',-282,,,,-579,-579,-579,,,-579,-579,-579,,-579,,,,,,,,,-579,-579,-579',
+'-579,,,,,,,,-579,-579,,-579,-579,-579,-579,-579,,,,,,,,,,,,,,,,,,,,',
+',,,-579,-579,-579,-579,-579,-579,-579,-579,-579,-579,-579,-579,-579',
+'-579,,,-579,-579,-579,,,-579,,,-579,,,-579,-579,,-579,,-579,,-579,,-579',
+'-579,,-579,-579,-579,-579,-579,,-579,-579,-579,,,,,,,,,,,,,,-579,,,-579',
+'-579,-579,-579,-580,-579,,-579,,,,-580,-580,-580,,,-580,-580,-580,,-580',
+',,,,,,,,-580,-580,-580,-580,,,,,,,,-580,-580,,-580,-580,-580,-580,-580',
+',,,,,,,,,,,,,,,,,,,,,,,-580,-580,-580,-580,-580,-580,-580,-580,-580',
+'-580,-580,-580,-580,-580,,,-580,-580,-580,,,-580,,,-580,,,-580,-580',
+',-580,,-580,,-580,,-580,-580,,-580,-580,-580,-580,-580,,-580,-580,-580',
+',,,,,,,,,,,,,-580,,,-580,-580,-580,-580,-411,-580,,-580,,,,-411,-411',
+'-411,,,-411,-411,-411,,-411,,,,,,,,,-411,-411,-411,,,,,,,,,-411,-411',
+',-411,-411,-411,-411,-411,,,,,,,,,,,,,,,,,,,,,,,,-411,-411,-411,-411',
+'-411,-411,-411,-411,-411,-411,-411,-411,-411,-411,,,-411,-411,-411,',
+',-411,,263,-411,,,-411,-411,,-411,,-411,,-411,,-411,-411,,-411,-411',
+'-411,-411,-411,-298,-411,-411,-411,,,,-298,-298,-298,,,-298,-298,-298',
+',-298,-411,,,-411,-411,,-411,,-411,-298,-298,,,,,,,,,-298,-298,,-298',
+'-298,-298,-298,-298,,,,,,,,,,,,,,,,,,,,,,,,-298,-298,-298,-298,-298',
+'-298,-298,-298,-298,-298,-298,-298,-298,-298,,,-298,-298,-298,,,-298',
+',272,-298,,,-298,-298,,-298,,-298,,-298,,-298,-298,,-298,-298,-298,-298',
+'-298,,-298,-246,-298,,,,,,-246,-246,-246,,,-246,-246,-246,-298,-246',
+',-298,-298,,-298,,-298,,-246,-246,-246,,,,,,,,,-246,-246,,-246,-246',
+'-246,-246,-246,,,,,,,,,,,,,,,,,,,,,,,,-246,-246,-246,-246,-246,-246',
+'-246,-246,-246,-246,-246,-246,-246,-246,,,-246,-246,-246,,,-246,,263',
+'-246,,,-246,-246,,-246,,-246,,-246,,-246,-246,,-246,-246,-246,-246,-246',
+',-246,-246,-246,,,,,,,,,,,,,,-246,,-246,-246,-246,,-246,,-246,-246,-246',
+'-246,,,-246,-246,-246,548,-246,545,544,543,553,546,,,,-246,-246,,,,',
+'556,,,,,-246,-246,,-246,-246,-246,-246,-246,,,,,,,,,,551,548,,545,544',
+'543,553,546,,561,560,564,563,,,,557,556,548,,545,544,543,553,546,-246',
+',,,,,,-246,,556,,,263,-246,551,534,,218,,,,,,561,560,564,563,,,,557',
+'551,,,,-246,-246,,,,561,560,564,563,,,,557,,,-246,,,-246,,,,,-246,173',
'184,174,197,170,190,180,179,200,201,195,178,177,172,198,202,203,182',
'171,185,189,191,183,176,,,,192,199,194,193,186,196,181,169,188,187,',
-',,,,168,175,166,167,163,164,165,124,126,,,125,,,,,,,,,157,158,,154,136',
-'137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,,,,,,,,,151,150',
-',135,156,153,152,161,148,149,143,141,133,155,134,,,162,89,,,,,,,,,,',
-',,,88,173,184,174,197,170,190,180,179,200,201,195,178,177,172,198,202',
-'203,182,171,185,189,191,183,176,,,,192,199,194,193,186,196,181,169,188',
-'187,,,,,,168,175,166,167,163,164,165,124,126,,,125,,,,,,,,,157,158,',
-'154,136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,,,,,,',
-',,151,150,,135,156,153,152,161,148,149,143,141,133,155,134,,,162,173',
-'184,174,197,170,190,180,179,200,201,195,178,177,172,198,202,203,182',
-'171,185,189,191,183,176,,,,192,199,194,371,370,372,369,169,188,187,',
-',,,,168,175,166,167,366,367,368,364,126,97,96,365,,99,,,,,,,157,158',
-',154,136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,376,',
-',,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155,134,673,424',
-'162,,674,,,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159',
-'160,146,147,,,,,,263,,,,,,,,151,150,,135,156,153,152,161,148,149,143',
-'141,133,155,134,1008,424,162,,1009,,,,,,,,,157,158,,154,136,137,138',
-'145,142,144,,,139,140,,,,159,160,146,147,,,,,,263,,,,,,,,151,150,,135',
-'156,153,152,161,148,149,143,141,133,155,134,640,424,162,,641,,,,,,,',
-',157,158,,154,136,137,138,145,142,144,,,139,140,,,,159,160,146,147,',
-',,,,263,,,,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155',
-'134,638,417,162,,639,,,,,,,,,157,158,,154,136,137,138,145,142,144,,',
+',,,,168,175,166,167,163,164,165,124,126,123,,125,,,,,,,,,157,158,,154',
+'136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,,,,,,,,,151',
+'150,,135,156,153,152,161,148,149,143,141,133,155,134,,,162,89,,,,,,',
+',,,,,,,88,173,184,174,197,170,190,180,179,200,201,195,178,177,172,198',
+'202,203,182,171,185,189,191,183,176,,,,192,199,194,193,186,196,181,169',
+'188,187,,,,,,168,175,166,167,163,164,165,124,126,,,125,,,,,,,,,157,158',
+',154,136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,,,,,',
+',,,151,150,,135,156,153,152,161,148,149,143,141,133,155,134,,,162,89',
+',,,,,,,,,,,,,88,173,184,174,197,170,190,180,179,200,201,195,178,177',
+'172,198,202,203,182,171,185,189,191,183,176,,,,192,199,194,193,186,196',
+'181,169,188,187,,,,,,168,175,166,167,163,164,165,124,126,,,125,,,,,',
+',,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159,160,146,147',
+',,,,,,,,,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155,134',
+',,162,89,,,,,,,,,,,,,,88,173,184,174,197,170,190,180,179,200,201,195',
+'178,177,172,198,202,203,182,171,185,189,191,183,176,,,,192,199,194,193',
+'186,196,181,169,188,187,,,,,,168,175,166,167,163,164,165,124,126,,,125',
+',,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159,160,146',
+'147,,,,,,,,,,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155',
+'134,,,162,89,,,,,,,,,,,,,,88,173,184,174,197,170,190,180,179,200,201',
+'195,178,177,172,198,202,203,182,171,185,189,191,183,176,,,,192,199,194',
+'371,370,372,369,169,188,187,,,,,,168,175,166,167,366,367,368,364,126',
+'97,96,365,,99,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,',
+',,159,160,146,147,,,,,,376,,,,,,,,151,150,,135,156,153,152,161,148,149',
+'143,141,133,155,134,,,162,173,184,174,197,170,190,180,179,200,201,195',
+'178,177,172,198,202,203,182,171,185,189,191,183,176,,,,192,199,194,193',
+'186,196,181,169,188,187,,,,,,168,175,166,167,163,164,165,124,126,,,125',
+',,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159,160,146',
+'147,,,,,,,,,,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155',
+'134,413,417,162,,414,,,,,,,,,157,158,,154,136,137,138,145,142,144,,',
'139,140,,,,159,160,146,147,,,,,,263,,,,,,,,151,150,,135,156,153,152',
-'161,148,149,143,141,133,155,134,670,417,162,,671,,,,,,,,,157,158,,154',
+'161,148,149,143,141,133,155,134,420,424,162,,419,,,,,,,,,157,158,,154',
+'136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,263,,,,,,',
+',151,150,,135,156,153,152,161,148,149,143,141,133,155,134,475,417,162',
+',476,,,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159,160',
+'146,147,,,,,,,,,,,,,,151,150,,135,156,153,152,161,148,149,143,141,133',
+'155,134,638,417,162,,639,,,,,,,,,157,158,,154,136,137,138,145,142,144',
+',,139,140,,,,159,160,146,147,,,,,,263,,,,,,,,151,150,,135,156,153,152',
+'161,148,149,143,141,133,155,134,640,424,162,,641,,,,,,,,,157,158,,154',
'136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,263,,,,,,',
-',151,150,,135,156,153,152,161,148,149,143,141,133,155,134,721,417,162',
-',722,,,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159,160',
+',151,150,,135,156,153,152,161,148,149,143,141,133,155,134,670,417,162',
+',671,,,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159,160',
'146,147,,,,,,263,,,,,,,,151,150,,135,156,153,152,161,148,149,143,141',
-'133,155,134,723,424,162,,724,,,,,,,,,157,158,,154,136,137,138,145,142',
+'133,155,134,673,424,162,,674,,,,,,,,,157,158,,154,136,137,138,145,142',
'144,,,139,140,,,,159,160,146,147,,,,,,263,,,,,,,,151,150,,135,156,153',
-'152,161,148,149,143,141,133,155,134,983,424,162,,982,,,,,,,,,157,158',
+'152,161,148,149,143,141,133,155,134,638,417,162,,639,,,,,,,,,157,158',
',154,136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,263,',
-',,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155,134,726,424',
-'162,,727,,,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159',
+',,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155,134,640,424',
+'162,,641,,,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159',
'160,146,147,,,,,,263,,,,,,,,151,150,,135,156,153,152,161,148,149,143',
-'141,133,155,134,638,417,162,,639,,,,,,,,,157,158,,154,136,137,138,145',
+'141,133,155,134,721,417,162,,722,,,,,,,,,157,158,,154,136,137,138,145',
'142,144,,,139,140,,,,159,160,146,147,,,,,,263,,,,,,,,151,150,,135,156',
-'153,152,161,148,149,143,141,133,155,134,475,417,162,,476,,,,,,,,,157',
+'153,152,161,148,149,143,141,133,155,134,723,424,162,,724,,,,,,,,,157',
'158,,154,136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,263',
-',,,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155,134,640',
-'424,162,,641,,,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140',
+',,,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155,134,726',
+'424,162,,727,,,,,,,,,157,158,,154,136,137,138,145,142,144,,,139,140',
',,,159,160,146,147,,,,,,263,,,,,,,,151,150,,135,156,153,152,161,148',
'149,143,141,133,155,134,475,417,162,,476,,,,,,,,,157,158,,154,136,137',
-'138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,,,,,,,,,151,150,,135',
-'156,153,152,161,148,149,143,141,133,155,134,413,417,162,,414,,,,,,,',
-',157,158,,154,136,137,138,145,142,144,,,139,140,,,,159,160,146,147,',
-',,,,263,,,,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155',
-'134,1006,417,162,,1007,,,,,,,,,157,158,,154,136,137,138,145,142,144',
-',,139,140,,,,159,160,146,147,,,,,,263,,,,,,,,151,150,,135,156,153,152',
-'161,148,149,143,141,133,155,134,420,424,162,,419,,,,,,,,,157,158,,154',
-'136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,263,,,,,,',
-',151,150,,135,156,153,152,161,148,149,143,141,133,155,134,,548,162,545',
-'544,543,553,546,,548,,545,544,543,553,546,,556,548,,545,544,543,553',
-'546,556,548,,545,544,543,553,546,,556,,,,,551,,,556,,,,,551,561,560',
-'564,563,,,,557,551,534,564,563,,,,557,551,561,560,564,563,,,,557,561',
-'560,564,563,,,548,557,545,544,543,553,546,548,,545,544,543,553,546,',
-'548,556,545,544,543,553,546,,556,,,,,,,548,556,545,544,543,553,546,',
-'551,,,,,,,551,556,,,564,563,,,551,557,,564,563,,,,557,561,560,564,563',
-',,551,557,548,,545,544,543,553,546,561,560,564,563,,,,557,548,556,545',
-'544,543,553,546,,548,,545,544,543,553,546,,556,,,,,,,551,556,548,,545',
-'544,543,553,546,561,560,564,563,,,551,557,,556,,,,,551,561,560,564,563',
-',,,557,561,560,564,563,,,,557,551,548,,545,544,543,553,546,,561,560',
-'564,563,,,,557,556,548,,545,544,543,553,546,548,,545,544,543,553,546',
-',,556,,,,,551,,556,548,,545,544,543,553,546,,564,563,,,,557,551,,556',
-',,,,551,,561,560,564,563,,,,557,,564,563,,,,557,551,548,,545,544,543',
-'553,546,,,,564,563,,,,557,556,,,,,,,,,,,,,,,,,,,,,,551,,,,,,,,,,,564',
-'563,,,,557' ]
- racc_action_table = arr = ::Array.new(25310, nil)
+'138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,263,,,,,,,,151,150',
+',135,156,153,152,161,148,149,143,141,133,155,134,983,424,162,,982,,',
+',,,,,,157,158,,154,136,137,138,145,142,144,,,139,140,,,,159,160,146',
+'147,,,,,,263,,,,,,,,151,150,,135,156,153,152,161,148,149,143,141,133',
+'155,134,1006,417,162,,1007,,,,,,,,,157,158,,154,136,137,138,145,142',
+'144,,,139,140,,,,159,160,146,147,,,,,,263,,,,,,,,151,150,,135,156,153',
+'152,161,148,149,143,141,133,155,134,1008,424,162,,1009,,,,,,,,,157,158',
+',154,136,137,138,145,142,144,,,139,140,,,,159,160,146,147,,,,,,263,',
+',,,,,,151,150,,135,156,153,152,161,148,149,143,141,133,155,134,,548',
+'162,545,544,543,553,546,,548,,545,544,543,553,546,,556,,,,,,,548,556',
+'545,544,543,553,546,,,,,,,,,551,556,,,,,,,551,561,560,564,563,,,,557',
+'561,560,564,563,,,551,557,548,,545,544,543,553,546,561,560,564,563,',
+',,557,548,556,545,544,543,553,546,,548,,545,544,543,553,546,,556,,,',
+',,,551,556,548,,545,544,543,553,546,561,560,564,563,,,551,557,,556,',
+',,,551,561,560,564,563,,,,557,561,560,564,563,,,,557,551,548,,545,544',
+'543,553,546,,561,560,564,563,,,,557,556,548,,545,544,543,553,546,,548',
+',545,544,543,553,546,,556,,,,,551,,548,556,545,544,543,553,546,,,564',
+'563,,,,557,551,556,,,,,,,551,,,564,563,,,,557,561,560,564,563,,,551',
+'557,548,,545,544,543,553,546,,,564,563,,,,557,548,556,545,544,543,553',
+'546,,548,,545,544,543,553,546,548,556,545,544,543,553,546,,551,556,',
+',,,,,556,,,564,563,,,551,557,,,,,,,551,,,564,563,,,551,557,,,564,563',
+',,,557,,564,563,,,,557' ]
+ racc_action_table = arr = ::Array.new(25292, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -887,920 +886,919 @@ clist = [
end
clist = [
-'641,339,1007,1006,774,844,890,641,641,641,38,908,641,641,641,19,641',
-'359,590,590,906,58,437,437,594,594,641,641,641,349,1020,345,724,996',
-'996,308,641,641,383,641,641,641,641,641,338,719,722,885,3,721,845,1008',
-'650,3,665,687,19,38,371,342,774,58,346,665,342,371,38,641,641,641,641',
-'641,641,641,641,641,641,641,641,641,641,671,578,641,641,641,910,641',
-'641,571,384,641,723,570,641,641,61,641,724,641,308,641,911,641,641,383',
-'641,641,641,641,641,917,641,590,641,844,670,437,590,594,339,1007,1006',
-'308,359,339,1007,1006,641,1008,908,641,641,641,641,908,641,420,641,349',
-'650,345,724,641,420,420,420,359,671,1020,420,420,359,420,1020,845,722',
-'384,723,721,845,481,420,338,719,687,885,719,338,719,1008,885,346,420',
-'420,1008,420,420,420,420,420,680,680,670,61,355,364,26,671,355,473,671',
-'578,364,571,921,481,221,570,571,671,343,723,570,420,420,420,420,420',
-'420,420,420,420,420,420,420,420,420,924,482,420,420,420,670,420,473',
-'670,39,420,853,414,420,651,927,853,670,420,443,420,928,420,420,353,420',
-'420,420,420,420,419,420,420,420,26,221,482,419,419,419,41,41,77,419',
-'419,366,419,420,929,651,420,420,366,420,77,420,39,26,680,414,930,492',
-'420,801,77,39,419,419,414,419,419,419,419,419,224,443,704,353,704,704',
-'704,607,704,332,353,913,332,913,904,353,904,904,904,353,904,313,313',
-'419,419,419,419,419,419,419,419,419,419,419,419,419,419,374,353,419',
-'419,419,801,419,374,41,41,419,932,801,419,382,492,492,492,419,224,419',
-'801,419,419,726,419,419,419,419,419,95,419,492,419,639,607,607,95,95',
-'95,801,947,95,95,95,607,95,419,704,329,419,419,329,419,95,419,95,95',
-'95,450,904,367,419,313,313,952,95,95,367,95,95,95,95,95,638,953,413',
-'726,509,382,382,382,385,589,726,509,954,288,589,726,639,450,288,726',
-'509,450,450,95,95,95,95,95,95,95,95,95,95,95,95,95,95,955,726,95,95',
-'95,222,95,95,692,692,95,605,413,95,95,380,95,956,95,638,95,413,95,95',
-'379,95,95,95,95,95,378,95,98,95,958,368,385,385,385,98,98,98,368,7,98',
-'98,98,95,98,848,95,95,95,95,848,95,98,95,98,98,98,222,95,14,328,673',
-'15,328,98,98,14,98,98,98,98,98,605,605,938,14,380,380,380,381,934,938',
-'605,934,344,379,379,379,354,982,938,378,378,378,983,98,98,98,98,98,98',
-'98,98,98,98,98,98,98,98,15,24,98,98,98,673,98,98,24,15,98,984,673,98',
-'98,1,98,673,98,621,98,673,98,98,317,98,98,98,98,98,995,98,354,98,997',
-'381,381,381,369,354,673,449,727,686,354,369,686,98,354,727,98,98,98',
-'98,727,98,640,98,727,710,710,998,98,640,640,640,621,354,640,640,640',
-'317,640,449,999,621,1000,449,449,370,317,640,640,640,640,123,370,372',
-'17,17,123,123,640,640,372,640,640,640,640,640,994,365,994,994,994,347',
-'994,701,365,701,701,701,347,701,551,807,551,551,551,454,551,347,479',
-'640,640,640,640,640,640,640,640,640,640,640,640,640,640,689,994,640',
-'640,640,357,640,640,701,483,640,689,357,640,640,551,640,701,640,326',
-'640,357,640,640,551,640,640,640,640,640,944,640,640,640,337,337,833',
-'944,833,833,833,321,833,453,689,689,944,640,318,689,640,640,640,640',
-'945,640,499,640,523,523,500,945,640,569,569,569,569,569,569,503,945',
-'946,569,569,833,505,314,569,946,569,569,569,569,569,569,569,510,946',
-'452,513,312,569,569,569,569,569,569,569,598,598,569,451,598,598,598',
-'432,569,569,569,569,569,569,569,569,569,569,569,569,1001,569,569,569',
-'307,569,569,521,569,569,569,432,432,432,432,432,432,432,432,432,432',
-'432,319,432,432,948,522,432,432,319,569,524,948,569,306,536,569,569',
-'319,537,569,948,569,432,539,432,569,432,432,540,432,432,432,432,432',
-'569,432,541,550,303,569,569,569,569,301,569,569,569,569,558,562,301',
-'565,569,569,567,432,572,432,573,301,569,297,569,569,569,566,566,566',
-'566,566,566,296,295,988,566,566,592,330,602,566,988,566,566,566,566',
-'566,566,566,331,988,610,612,618,566,566,566,566,566,566,566,293,292',
-'566,622,280,277,627,643,566,566,566,566,566,566,566,566,566,566,566',
-'566,276,566,566,566,1002,566,566,632,566,566,566,643,643,643,643,643',
-'643,643,643,643,643,643,1009,643,643,300,262,643,643,1009,566,230,300',
-'566,1009,226,566,566,1009,642,566,300,566,643,333,643,566,643,643,1005',
-'643,643,643,643,643,566,643,225,649,223,566,566,566,566,302,566,566',
-'566,566,656,658,302,664,566,566,667,643,669,439,429,302,566,672,566',
-'566,566,654,654,654,654,654,654,1022,675,46,654,654,676,679,681,654',
-'46,654,654,654,654,654,654,654,684,46,421,688,204,654,654,654,654,654',
-'654,654,703,705,654,712,717,720,412,408,654,654,654,654,654,654,654',
-'654,654,654,654,654,411,654,654,654,409,654,654,405,654,654,654,408',
-'408,408,408,408,408,408,408,408,408,408,674,408,408,304,729,408,408',
-'674,654,109,304,654,674,734,654,654,674,403,654,304,654,408,400,408',
-'654,408,408,394,408,408,408,408,408,654,408,753,350,758,654,654,654',
-'654,875,654,654,654,654,348,1010,875,1011,654,654,45,408,40,775,776',
-'875,654,777,654,654,654,653,653,653,653,653,653,779,780,581,653,653',
-'781,783,784,653,581,653,653,653,653,653,653,653,785,581,786,790,37,653',
-'653,653,653,653,653,653,794,873,653,873,873,873,795,873,653,653,653',
-'653,653,653,653,653,653,653,653,653,800,653,653,653,804,653,653,808',
-'653,653,653,760,760,760,760,760,760,760,760,760,760,760,220,760,760',
-'811,816,760,760,220,653,817,821,653,822,824,653,653,220,825,653,827',
-'653,760,830,760,653,760,760,832,760,760,760,760,760,653,760,835,838',
-'22,653,653,653,653,847,653,653,653,653,16,851,852,855,653,653,856,760',
-'872,13,876,878,653,12,653,653,653,648,648,648,648,648,648,10,889,,648',
-'648,,,,648,,648,648,648,648,648,648,648,6,6,6,6,6,648,648,648,648,648',
-'648,648,,981,648,981,981,981,,981,648,648,648,648,648,648,648,648,648',
-'648,648,648,,648,648,648,,648,648,,648,648,648,427,427,427,427,427,427',
-'427,427,427,427,427,,427,427,,,427,427,,648,,,648,,,648,648,,,648,,648',
-'427,,427,648,427,427,,427,427,427,427,427,648,427,,,,648,648,648,648',
-',648,648,648,648,,,,,648,648,,427,,,,,648,,648,648,648,849,849,849,849',
-'849,849,,,,849,849,,,,849,,849,849,849,849,849,849,849,291,291,291,291',
-'291,849,849,849,849,849,849,849,,,849,497,497,497,497,497,849,849,849',
-'849,849,849,849,849,849,849,849,849,,849,849,849,,849,849,,849,849,849',
-'519,519,519,519,519,519,519,519,519,519,519,,519,519,,,519,519,,849',
-',,849,,,849,849,,,849,,849,519,,519,849,519,519,,519,519,519,519,519',
-'849,519,,,,849,849,849,849,,849,849,849,849,,,,,849,849,,519,,,,,849',
-',849,849,849,229,229,229,229,229,229,,,,229,229,,,,229,,229,229,229',
-'229,229,229,229,,,,,,229,229,229,229,229,229,229,,,229,,,,,,229,229',
-'229,229,229,229,229,229,229,229,229,229,,229,229,229,,229,229,,229,229',
-'229,274,274,274,274,274,274,274,274,274,274,274,,274,274,,,274,274,',
-'229,,,229,,,229,229,,,229,,229,274,,274,229,274,274,,274,274,274,274',
-'274,229,274,,,,229,229,229,229,,229,229,229,229,,,,,229,229,,274,,,',
-',229,,229,229,229,33,33,33,33,33,33,,,,33,33,,,,33,,33,33,33,33,33,33',
-'33,,,,,,33,33,33,33,33,33,33,,,33,,,,,,33,33,33,33,33,33,33,33,33,33',
-'33,33,,33,33,33,,33,33,,33,33,33,644,644,644,644,644,644,644,644,644',
-'644,644,,644,644,,,644,644,,33,,,33,,,33,33,,,33,,33,644,,644,33,644',
-'644,,644,644,644,644,644,33,644,,,,33,33,33,33,,33,33,33,33,,,,,33,33',
-'644,644,,,,,33,,33,33,33,843,843,843,843,843,843,,,,843,843,,,,843,',
-'843,843,843,843,843,843,843,,,,,,843,843,843,843,843,843,843,,,843,',
-',,,,843,843,843,843,843,843,843,843,843,843,843,843,,843,843,843,,843',
-'843,,843,843,843,678,678,678,678,678,678,678,678,678,678,678,,678,678',
-',,678,678,,843,,,843,,,843,843,,,843,,843,678,,678,843,678,678,,678',
-'678,678,678,678,843,678,,,,843,843,843,843,,843,843,843,843,,,,,843',
-'843,,678,,,,,843,,843,843,843,121,121,121,121,121,121,,,,121,121,,,',
-'121,,121,121,121,121,121,121,121,,,,,,121,121,121,121,121,121,121,,',
-'121,,,,,,121,121,121,121,121,121,121,121,121,121,121,121,,121,121,121',
-',121,121,,121,121,121,755,755,755,755,755,755,755,755,755,755,755,,755',
-'755,,,755,755,,121,,,121,,,121,121,,,121,,121,755,,755,121,755,755,',
-'755,755,755,755,755,121,755,,,,121,121,121,121,,121,121,121,121,,,,',
-'121,121,,755,,,,,121,,121,121,121,498,498,498,498,498,498,,,,498,498',
-',,,498,,498,498,498,498,498,498,498,,,,,,498,498,498,498,498,498,498',
-',,498,,,,,,498,498,498,498,498,498,498,498,498,498,498,498,,498,498',
-'498,,498,498,,498,498,498,762,762,762,762,762,762,762,762,762,762,762',
-',762,762,,,762,762,,498,,,498,,,498,498,,,498,,498,762,,762,498,762',
-'762,,762,762,762,762,762,498,762,,,,498,498,498,498,,498,498,498,498',
-',,,,498,498,,762,,,,,498,,498,498,498,966,966,966,966,966,966,,,,966',
-'966,,,,966,,966,966,966,966,966,966,966,,,,,,966,966,966,966,966,966',
-'966,,,966,,,,,,966,966,966,966,966,966,966,966,966,966,966,966,,966',
-'966,966,,966,966,,966,966,966,765,765,765,765,765,765,765,765,765,765',
-'765,,765,765,,,765,765,,966,,,966,,,966,966,,,966,,966,765,,765,966',
-'765,765,,765,765,765,765,765,966,765,,,,966,966,966,966,,966,966,966',
-'966,,,,,966,966,,765,,,,,966,,966,966,966,745,745,745,745,745,745,,',
-',745,745,,,,745,,745,745,745,745,745,745,745,,,,,,745,745,745,745,745',
-'745,745,,,745,,,,,,745,745,745,745,745,745,745,745,745,745,745,745,',
-'745,745,745,,745,745,,745,745,745,767,767,767,767,767,767,767,767,767',
-'767,767,,767,767,,,767,767,,745,,,745,,,745,745,,,745,,745,767,,767',
-'745,767,767,,767,767,767,767,767,745,767,,,,745,745,745,745,,745,745',
-'745,745,,,,,745,745,,767,,,,,745,,745,745,745,206,206,206,206,206,206',
-',,,206,206,,,,206,,206,206,206,206,206,206,206,,,,,,206,206,206,206',
-'206,206,206,,,206,,,,,,206,206,206,206,206,206,206,206,206,206,206,206',
-',206,206,206,,206,206,,206,206,206,769,769,769,769,769,769,769,769,769',
-'769,769,,769,769,,,769,769,,206,,,206,,,206,206,,,206,,206,769,,769',
-'206,769,769,,769,769,769,769,769,206,769,,,,206,206,206,206,,206,206',
-'206,206,,,,,206,206,,769,,,,,206,,206,206,206,324,324,324,324,324,324',
+'95,345,61,437,437,346,349,95,95,95,221,338,95,95,95,383,95,355,19,384',
+'58,355,594,594,95,222,95,95,95,473,650,26,17,17,578,359,95,95,339,95',
+'95,95,95,95,719,885,15,1,908,687,721,7,1006,665,1007,1020,680,680,308',
+'19,58,913,665,913,473,722,221,95,95,95,95,95,95,95,95,95,95,95,95,95',
+'95,222,383,95,95,95,384,95,95,570,61,95,10,15,95,95,26,95,437,95,12',
+'95,15,95,95,844,95,95,95,95,95,345,95,98,95,346,349,594,650,26,98,98',
+'98,308,1008,98,98,98,95,98,338,95,95,95,95,338,95,98,95,98,98,98,359',
+'95,578,571,308,723,845,98,98,680,98,98,98,98,98,339,13,687,721,670,339',
+'719,885,359,719,908,719,885,359,1006,908,1007,1020,722,1006,16,1007',
+'1020,98,98,98,98,98,98,98,98,98,98,98,98,98,98,570,22,98,98,98,570,98',
+'98,1008,671,98,37,724,98,98,40,98,605,98,723,98,844,98,98,224,98,98',
+'98,98,98,419,98,45,98,670,590,590,419,419,419,481,24,328,419,419,328',
+'419,98,24,1008,98,98,98,98,1008,98,571,98,353,845,3,571,98,723,845,3',
+'419,419,109,419,419,419,419,419,670,481,671,670,724,123,224,204,605',
+'605,123,123,670,704,607,704,704,704,605,704,223,41,41,419,419,419,419',
+'419,419,419,419,419,419,419,419,419,419,353,354,419,419,419,671,419',
+'353,671,38,419,724,353,419,313,313,353,671,419,590,419,443,419,419,590',
+'419,419,419,419,419,378,419,420,419,225,353,39,364,226,420,420,420,607',
+'607,364,420,420,419,420,482,419,419,607,419,354,419,38,420,230,704,673',
+'354,419,41,41,38,354,262,420,420,354,420,420,420,420,420,904,443,904',
+'904,904,317,904,39,482,329,651,492,329,354,379,276,39,313,313,378,378',
+'378,801,420,420,420,420,420,420,420,420,420,420,420,420,420,420,673',
+'413,420,420,420,380,420,673,651,288,420,414,673,420,288,317,673,381',
+'420,638,420,726,420,420,317,420,420,420,420,420,277,420,420,420,382',
+'673,280,385,801,492,492,492,379,379,379,801,904,420,413,621,420,420',
+'640,420,801,420,492,413,414,640,640,640,420,292,640,640,640,414,640',
+'365,380,380,380,801,726,638,365,640,640,640,640,726,381,381,381,639',
+'726,293,640,640,726,640,640,640,640,640,621,295,774,382,382,382,385',
+'385,385,621,337,337,366,726,551,367,551,551,551,366,551,296,367,640',
+'640,640,640,640,640,640,640,640,640,640,640,640,640,689,297,640,640',
+'640,368,640,640,639,303,640,689,368,640,640,551,640,306,640,307,640',
+'774,640,640,551,640,640,640,640,640,862,640,640,640,332,369,77,332,342',
+'370,312,862,369,342,689,689,370,640,77,689,640,640,640,640,449,640,641',
+'640,77,371,14,314,640,641,641,641,371,14,641,641,641,46,641,220,862',
+'862,14,318,46,862,220,372,641,641,641,321,449,46,372,220,449,449,641',
+'641,374,641,641,641,641,641,833,374,833,833,833,300,833,701,326,701',
+'701,701,300,701,831,330,831,831,831,686,831,300,686,641,641,641,641',
+'641,641,641,641,641,641,641,641,641,641,468,833,641,641,641,301,641',
+'641,701,469,641,331,301,641,641,831,641,701,641,333,641,301,641,641',
+'831,641,641,641,641,641,589,641,468,641,343,589,468,468,450,468,468',
+'469,523,523,344,469,469,641,469,469,641,641,641,641,848,641,853,641',
+'348,848,350,853,641,0,0,0,0,0,0,394,450,302,0,0,450,450,400,0,302,0',
+'0,0,0,0,0,0,934,302,403,934,405,0,0,0,0,0,0,0,598,598,0,409,598,598',
+'598,432,0,0,0,0,0,0,0,0,0,0,0,0,411,0,0,0,412,0,0,421,0,0,0,432,432',
+'432,432,432,432,432,432,432,432,432,304,432,432,319,429,432,432,304',
+'0,439,319,0,692,692,0,0,304,451,0,319,0,432,452,432,0,432,432,453,432',
+'432,432,432,432,0,432,710,710,454,0,0,0,0,347,0,0,0,0,996,996,347,479',
+'0,0,483,432,499,432,500,347,0,503,0,0,0,33,33,33,33,33,33,505,510,357',
+'33,33,513,521,522,33,357,33,33,33,33,33,33,33,524,357,536,537,539,33',
+'33,33,33,33,33,33,540,541,33,550,558,562,565,408,33,33,33,33,33,33,33',
+'33,33,33,33,33,567,33,33,33,572,33,33,573,33,33,33,408,408,408,408,408',
+'408,408,408,408,408,408,509,408,408,581,592,408,408,509,33,602,581,33',
+'610,612,33,33,509,618,33,581,33,408,622,408,33,408,408,627,408,408,408',
+'408,408,33,408,632,642,649,33,33,33,33,875,33,33,33,33,656,658,875,664',
+'33,33,667,408,669,672,675,875,33,676,33,33,33,121,121,121,121,121,121',
+'679,681,938,121,121,684,688,703,121,938,121,121,121,121,121,121,121',
+'705,938,712,717,720,121,121,121,121,121,121,121,729,734,121,753,758',
+'775,776,643,121,121,121,121,121,121,121,121,121,121,121,121,777,121',
+'121,121,779,121,121,780,121,121,121,643,643,643,643,643,643,643,643',
+'643,643,643,674,643,643,944,781,643,643,674,121,783,944,121,674,784',
+'121,121,674,785,121,944,121,643,786,643,121,643,643,790,643,643,643',
+'643,643,121,643,794,795,800,121,121,121,121,945,121,121,121,121,804',
+'807,945,808,121,121,811,643,816,817,821,945,121,822,121,121,121,206',
+'206,206,206,206,206,824,825,946,206,206,827,830,832,206,946,206,206',
+'206,206,206,206,206,835,946,838,847,851,206,206,206,206,206,206,206',
+'852,873,206,873,873,873,855,873,206,206,206,206,206,206,206,206,206',
+'206,206,206,856,206,206,206,872,206,206,876,206,206,206,21,21,21,21',
+'21,21,21,21,21,21,21,727,21,21,948,878,21,21,727,206,889,948,206,727',
+'890,206,206,727,906,206,948,206,21,910,21,206,21,21,911,21,21,21,21',
+'21,206,21,917,921,924,206,206,206,206,988,206,206,206,206,927,928,988',
+'929,206,206,930,21,932,947,952,988,206,953,206,206,206,229,229,229,229',
+'229,229,954,955,956,229,229,958,982,983,229,984,229,229,229,229,229',
+'229,229,6,6,6,6,6,229,229,229,229,229,229,229,995,981,229,981,981,981',
+'997,981,229,229,229,229,229,229,229,229,229,229,229,229,998,229,229',
+'229,999,229,229,1000,229,229,229,274,274,274,274,274,274,274,274,274',
+'274,274,1009,274,274,1001,1002,274,274,1009,229,1005,1010,229,1009,1011',
+'229,229,1009,1022,229,,229,274,,274,229,274,274,,274,274,274,274,274',
+'229,274,,,,229,229,229,229,,229,229,229,229,,,,,229,229,,274,,,,,229',
+',229,229,229,294,294,294,294,294,294,,,,294,294,,,,294,,294,294,294',
+'294,294,294,294,291,291,291,291,291,294,294,294,294,294,294,294,,,294',
+'497,497,497,497,497,294,294,294,294,294,294,294,294,294,294,294,294',
+',294,294,294,,294,294,,294,294,294,427,427,427,427,427,427,427,427,427',
+'427,427,,427,427,,,427,427,,294,,,294,,,294,294,,,294,,294,427,,427',
+'294,427,427,,427,427,427,427,427,294,427,,,,294,294,294,294,,294,294',
+'294,294,,,,,294,294,,427,,,,,294,,294,294,294,299,299,299,299,299,299',
+',,,299,299,,,,299,,299,299,299,299,299,299,299,,,,,,299,299,299,299',
+'299,299,299,,,299,,,,,,299,299,299,299,299,299,299,299,299,299,299,299',
+',299,299,299,,299,299,,299,299,299,519,519,519,519,519,519,519,519,519',
+'519,519,,519,519,,,519,519,,299,,,299,,,299,299,,,299,,299,519,,519',
+'299,519,519,,519,519,519,519,519,299,519,,,,299,299,299,299,,299,299',
+'299,299,,,,,299,299,,519,,,,,299,,299,299,299,324,324,324,324,324,324',
',,,324,324,,,,324,,324,324,324,324,324,324,324,,,,,,324,324,324,324',
'324,324,324,,,324,,,,,,324,324,324,324,324,324,324,324,324,324,324,324',
-',324,324,324,,324,324,,324,324,324,21,21,21,21,21,21,21,21,21,21,21',
-',21,21,,,21,21,,324,,,324,,,324,324,,,324,,324,21,,21,324,21,21,,21',
-'21,21,21,21,324,21,,,,324,324,324,324,,324,324,324,324,,,,,324,324,',
-'21,,,,,324,,324,324,324,793,793,793,793,793,793,,,,793,793,,,,793,,793',
-'793,793,793,793,793,793,,,,,,793,793,793,793,793,793,793,,,793,,,,,',
-'793,793,793,793,793,793,793,793,793,793,793,793,,793,793,793,,793,793',
-',793,793,793,858,858,858,858,858,858,858,858,858,858,858,,858,858,,',
-'858,858,,793,,,793,,,793,793,,,793,,793,858,,858,793,858,858,,858,858',
-'858,858,858,793,858,,,,793,793,793,793,,793,793,793,793,,,,,793,793',
-',858,,,,,793,,793,793,793,882,882,882,882,882,882,,,,882,882,,,,882',
-',882,882,882,882,882,882,882,,,,,,882,882,882,882,882,882,882,,,882',
-',,,,,882,882,882,882,882,882,882,882,882,882,882,882,,882,882,882,,882',
-'882,,882,882,882,969,969,969,969,969,969,969,969,969,969,969,,969,969',
-',,969,969,,882,,,882,,,882,882,,,882,,882,969,,969,882,969,969,,969',
-'969,969,969,969,882,969,,,,882,882,882,882,,882,882,882,882,,,,,882',
-'882,,969,,,,,882,,882,882,882,840,840,840,840,840,840,,,,840,840,,,',
-'840,,840,840,840,840,840,840,840,,862,,,,840,840,840,840,840,840,840',
-'862,831,840,831,831,831,,831,840,840,840,840,840,840,840,840,840,840',
-'840,840,,840,840,840,,840,840,,840,840,840,468,,862,862,,,469,862,831',
-'905,,905,905,905,,905,,831,,840,,,840,,,840,840,,,840,,840,468,,,840',
-'468,468,469,468,468,,469,469,840,469,469,905,,840,840,840,840,,840,840',
-'840,840,,,,,840,840,,,,,,,840,,840,840,840,839,839,839,839,839,839,',
-',,839,839,,,,839,,839,839,839,839,839,839,839,,,,,,839,839,839,839,839',
-'839,839,,957,839,957,957,957,,957,839,839,839,839,839,839,839,839,839',
-'839,839,839,,839,839,839,,839,839,,839,839,839,460,,,959,,959,959,959',
-'957,959,,,,,,,460,460,,839,,,839,,,839,839,,,839,,839,460,,460,839,460',
-'460,,460,460,959,,460,839,460,,,,839,839,839,839,,839,839,839,839,,',
-',,839,839,,,,,,,839,,839,839,839,960,960,960,960,960,960,,,,960,960',
-',,,960,,960,960,960,960,960,960,960,,,,,,960,960,960,960,960,960,960',
-',,960,,,,,,960,960,960,960,960,960,960,960,960,960,960,960,,960,960',
-'960,,960,960,,960,960,960,461,,,,,,,,,,,,,,,,461,461,,960,,,960,,,960',
-'960,,,960,,960,461,,461,960,461,461,,461,461,,,461,960,461,,,,960,960',
-'960,960,,960,960,960,960,,,,,960,960,,,,,,,960,,960,960,960,815,815',
-'815,815,815,815,,,,815,815,,,,815,,815,815,815,815,815,815,815,,,,,',
-'815,815,815,815,815,815,815,,,815,,,,,,815,815,815,815,815,815,815,815',
-'815,815,815,815,,815,815,815,,815,815,,815,815,815,470,470,470,470,470',
-'470,470,,,470,470,,,,,,470,470,,815,,,815,,,815,815,,,815,,815,470,',
-'470,815,470,470,,470,470,470,470,470,815,470,,,,815,815,815,815,,815',
-'815,815,815,,,,,815,815,,,,,,,815,,815,815,815,735,735,735,735,735,735',
-',,,735,735,,,,735,,735,735,735,735,735,735,735,,,,,,735,735,735,735',
-'735,735,735,,,735,,,,,,735,735,735,735,735,735,735,735,735,735,735,735',
-',735,735,735,,735,735,,735,735,735,447,447,447,447,447,447,447,447,447',
-'447,447,,447,447,,,447,447,,735,,,735,,,735,735,,,735,,735,447,,447',
-'735,447,447,,447,447,447,447,447,735,447,,,,735,735,735,735,,735,735',
-'735,735,,,,,735,735,,,,,,,735,,735,735,735,814,814,814,814,814,814,',
+',324,324,324,,324,324,,324,324,324,644,644,644,644,644,644,644,644,644',
+'644,644,,644,644,,,644,644,,324,,,324,,,324,324,,,324,,324,644,,644',
+'324,644,644,,644,644,644,644,644,324,644,,,,324,324,324,324,,324,324',
+'324,324,,,,,324,324,644,644,,,,,324,,324,324,324,498,498,498,498,498',
+'498,,,,498,498,,,,498,,498,498,498,498,498,498,498,,,,,,498,498,498',
+'498,498,498,498,,,498,,,,,,498,498,498,498,498,498,498,498,498,498,498',
+'498,,498,498,498,,498,498,,498,498,498,678,678,678,678,678,678,678,678',
+'678,678,678,,678,678,,,678,678,,498,,,498,,,498,498,,,498,,498,678,',
+'678,498,678,678,,678,678,678,678,678,498,678,,,,498,498,498,498,,498',
+'498,498,498,,,,,498,498,,678,,,,,498,,498,498,498,566,566,566,566,566',
+'566,,,,566,566,,,,566,,566,566,566,566,566,566,566,,,,,,566,566,566',
+'566,566,566,566,,,566,,,,,,566,566,566,566,566,566,566,566,566,566,566',
+'566,,566,566,566,,566,566,,566,566,566,755,755,755,755,755,755,755,755',
+'755,755,755,,755,755,,,755,755,,566,,,566,,,566,566,,,566,,566,755,',
+'755,566,755,755,,755,755,755,755,755,566,755,,,,566,566,566,566,,566',
+'566,566,566,,,,,566,566,,755,,,,,566,,566,566,566,569,569,569,569,569',
+'569,,,,569,569,,,,569,,569,569,569,569,569,569,569,,,,,,569,569,569',
+'569,569,569,569,,,569,,,,,,569,569,569,569,569,569,569,569,569,569,569',
+'569,,569,569,569,,569,569,,569,569,569,760,760,760,760,760,760,760,760',
+'760,760,760,,760,760,,,760,760,,569,,,569,,,569,569,,,569,,569,760,',
+'760,569,760,760,,760,760,760,760,760,569,760,,,,569,569,569,569,,569',
+'569,569,569,,,,,569,569,,760,,,,,569,,569,569,569,591,591,591,591,591',
+'591,,,,591,591,,,,591,,591,591,591,591,591,591,591,,,,,,591,591,591',
+'591,591,591,591,,,591,,,,,,591,591,591,591,591,591,591,591,591,591,591',
+'591,,591,591,591,,591,591,,591,591,591,762,762,762,762,762,762,762,762',
+'762,762,762,,762,762,,,762,762,,591,,,591,,,591,591,,,591,,591,762,',
+'762,591,762,762,,762,762,762,762,762,591,762,,,,591,591,591,591,,591',
+'591,591,591,,,,,591,591,,762,,,,,591,,591,591,591,648,648,648,648,648',
+'648,,,,648,648,,,,648,,648,648,648,648,648,648,648,,,,,,648,648,648',
+'648,648,648,648,,,648,,,,,,648,648,648,648,648,648,648,648,648,648,648',
+'648,,648,648,648,,648,648,,648,648,648,765,765,765,765,765,765,765,765',
+'765,765,765,,765,765,,,765,765,,648,,,648,,,648,648,,,648,,648,765,',
+'765,648,765,765,,765,765,765,765,765,648,765,,,,648,648,648,648,,648',
+'648,648,648,,,,,648,648,,765,,,,,648,,648,648,648,653,653,653,653,653',
+'653,,,,653,653,,,,653,,653,653,653,653,653,653,653,,,,,,653,653,653',
+'653,653,653,653,,,653,,,,,,653,653,653,653,653,653,653,653,653,653,653',
+'653,,653,653,653,,653,653,,653,653,653,767,767,767,767,767,767,767,767',
+'767,767,767,,767,767,,,767,767,,653,,,653,,,653,653,,,653,,653,767,',
+'767,653,767,767,,767,767,767,767,767,653,767,,,,653,653,653,653,,653',
+'653,653,653,,,,,653,653,,767,,,,,653,,653,653,653,654,654,654,654,654',
+'654,,,,654,654,,,,654,,654,654,654,654,654,654,654,,,,,,654,654,654',
+'654,654,654,654,,,654,,,,,,654,654,654,654,654,654,654,654,654,654,654',
+'654,,654,654,654,,654,654,,654,654,654,769,769,769,769,769,769,769,769',
+'769,769,769,,769,769,,,769,769,,654,,,654,,,654,654,,,654,,654,769,',
+'769,654,769,769,,769,769,769,769,769,654,769,,,,654,654,654,654,,654',
+'654,654,654,,,,,654,654,,769,,,,,654,,654,654,654,730,730,730,730,730',
+'730,,,,730,730,,,,730,,730,730,730,730,730,730,730,,,,,,730,730,730',
+'730,730,730,730,,,730,,,,,,730,730,730,730,730,730,730,730,730,730,730',
+'730,,730,730,730,,730,730,,730,730,730,858,858,858,858,858,858,858,858',
+'858,858,858,,858,858,,,858,858,,730,,,730,,,730,730,,,730,,730,858,',
+'858,730,858,858,,858,858,858,858,858,730,858,,,,730,730,730,730,,730',
+'730,730,730,,,,,730,730,,858,,,,,730,,730,730,730,735,735,735,735,735',
+'735,,,,735,735,,,,735,,735,735,735,735,735,735,735,,,,,,735,735,735',
+'735,735,735,735,,,735,,,,,,735,735,735,735,735,735,735,735,735,735,735',
+'735,,735,735,735,,735,735,,735,735,735,969,969,969,969,969,969,969,969',
+'969,969,969,,969,969,,,969,969,,735,,,735,,,735,735,,,735,,735,969,',
+'969,735,969,969,,969,969,969,969,969,735,969,,,,735,735,735,735,,735',
+'735,735,735,,,,,735,735,,969,,,,,735,,735,735,735,745,745,745,745,745',
+'745,,,,745,745,,,,745,,745,745,745,745,745,745,745,,,,,,745,745,745',
+'745,745,745,745,,,745,,,,,,745,745,745,745,745,745,745,745,745,745,745',
+'745,,745,745,745,,745,745,,745,745,745,447,447,447,447,447,447,447,447',
+'447,447,447,,447,447,,,447,447,,745,,,745,,,745,745,,,745,,745,447,',
+'447,745,447,447,,447,447,447,447,447,745,447,,,,745,745,745,745,,745',
+'745,745,745,,,,,745,745,,,,,,,745,,745,745,745,793,793,793,793,793,793',
+',,,793,793,,,,793,,793,793,793,793,793,793,793,,,,,,793,793,793,793',
+'793,793,793,,,793,,,,,,793,793,793,793,793,793,793,793,793,793,793,793',
+',793,793,793,,793,793,,793,793,793,448,448,448,448,448,448,448,448,448',
+'448,448,,448,448,,,448,448,,793,,,793,,,793,793,,,793,,793,448,,448',
+'793,448,448,,448,448,448,448,448,793,448,,,,793,793,793,793,,793,793',
+'793,793,,,,,793,793,,,,,,,793,,793,793,793,806,806,806,806,806,806,',
+',,806,806,,,,806,,806,806,806,806,806,806,806,,,,,,806,806,806,806,806',
+'806,806,,905,806,905,905,905,,905,806,806,806,806,806,806,806,806,806',
+'806,806,806,,806,806,806,,806,806,,806,806,806,458,458,458,458,458,458',
+'458,,905,458,458,,,,,,458,458,,806,,,806,,,806,806,,,806,,806,458,,458',
+'806,458,458,,458,458,458,458,458,806,458,,,,806,806,806,806,,806,806',
+'806,806,,,,,806,806,,,,,,,806,,806,806,806,814,814,814,814,814,814,',
',,814,814,,,,814,,814,814,814,814,814,814,814,,,,,,814,814,814,814,814',
-'814,814,,,814,,,,,,814,814,814,814,814,814,814,814,814,814,814,814,',
-'814,814,814,,814,814,,814,814,814,462,,,,,,,,,,,,,,,,462,462,,814,,',
-'814,,,814,814,,,814,,814,462,,462,814,462,462,,462,462,,,462,814,462',
-',,,814,814,814,814,,814,814,814,814,,,,,814,814,,,,,,,814,,814,814,814',
-'0,0,0,0,0,0,,,,0,0,,,,0,,0,0,0,0,0,0,0,,,,,,0,0,0,0,0,0,0,,,0,,,,,,0',
-'0,0,0,0,0,0,0,0,0,0,0,,0,0,0,,0,0,,0,0,0,458,458,458,458,458,458,458',
-',,458,458,,,,,,458,458,,0,,,0,,,0,0,,,0,,0,458,,458,0,458,458,,458,458',
-'458,458,458,0,458,,,,0,0,0,0,,0,0,0,0,,,,,0,0,,,,,,,0,,0,0,0,591,591',
-'591,591,591,591,,,,591,591,,,,591,,591,591,591,591,591,591,591,,,,,',
-'591,591,591,591,591,591,591,,,591,,,,,,591,591,591,591,591,591,591,591',
-'591,591,591,591,,591,591,591,,591,591,,591,591,591,448,448,448,448,448',
-'448,448,448,448,448,448,,448,448,,,448,448,,591,,,591,,,591,591,,,591',
-',591,448,,448,591,448,448,,448,448,448,448,448,591,448,,,,591,591,591',
-'591,,591,591,591,591,,,,,591,591,,,,,,,591,,591,591,591,294,294,294',
-'294,294,294,,,,294,294,,,,294,,294,294,294,294,294,294,294,,,,,,294',
-'294,294,294,294,294,294,,,294,,,,,,294,294,294,294,294,294,294,294,294',
-'294,294,294,,294,294,294,,294,294,,294,294,294,459,,,,,,,,,,,,,,,,459',
-'459,,294,,,294,,,294,294,,,294,,294,459,,459,294,459,459,,459,459,,',
-'459,294,459,,,,294,294,294,294,,294,294,294,294,,,,,294,294,,,,,,,294',
-',294,294,294,730,730,730,730,730,730,,,,730,730,,,,730,,730,730,730',
-'730,730,730,730,,,,,,730,730,730,730,730,730,730,,,730,,,,,,730,730',
-'730,730,730,730,730,730,730,730,730,730,,730,730,730,,730,730,,730,730',
-'730,463,463,463,463,463,463,463,,,463,463,,,,,,463,463,,730,,,730,,',
-'730,730,,,730,,730,463,,463,730,463,463,,463,463,463,463,463,730,463',
-',,,730,730,730,730,,730,730,730,730,,,,,730,730,,,,,,,730,,730,730,730',
-'806,806,806,806,806,806,,,,806,806,,,,806,,806,806,806,806,806,806,806',
-',,,,,806,806,806,806,806,806,806,,,806,,,,,,806,806,806,806,806,806',
-'806,806,806,806,806,806,,806,806,806,,806,806,,806,806,806,466,466,466',
-'466,466,466,466,,,466,466,,,,,,466,466,,806,,,806,,,806,806,,,806,,806',
-'466,,466,806,466,466,,466,466,466,466,466,806,466,,,,806,806,806,806',
-',806,806,806,806,,,,,806,806,,,,,,,806,,806,806,806,943,943,943,943',
-'943,943,,,,943,943,,,,943,,943,943,943,943,943,943,943,,,,,,943,943',
-'943,943,943,943,943,,,943,,,,,,943,943,943,943,943,943,943,943,943,943',
-'943,943,,943,943,943,,943,943,,943,943,943,464,464,464,464,464,464,464',
-',,464,464,,,,,,464,464,,943,,,943,,,943,943,,,943,,943,464,,464,943',
-'464,464,,464,464,464,464,464,943,464,,,,943,943,943,943,,943,943,943',
-'943,,,,,943,943,,,,,,,943,,943,943,943,299,299,299,299,299,299,,,,299',
-'299,,,,299,,299,299,299,299,299,299,299,,,,,,299,299,299,299,299,299',
-'299,,,299,,,,,,299,299,299,299,299,299,299,299,299,299,299,299,,299',
-'299,299,,299,299,,299,299,299,465,465,465,465,465,465,465,,,465,465',
-',,,,,465,465,,299,,,299,,,299,299,,,299,,299,465,,465,299,465,465,,465',
-'465,465,465,465,299,465,,,,299,299,299,299,,299,299,299,299,,,,,299',
-'299,,,,,,,299,,299,299,299,968,968,968,968,968,968,,,,968,968,,,,968',
-',968,968,968,968,968,968,968,,,,,,968,968,968,968,968,968,968,,,968',
-',,,,,968,968,968,968,968,968,968,968,968,968,968,968,,968,968,968,,968',
-'968,,968,968,968,471,471,471,471,471,471,471,471,,471,471,,,,,,471,471',
-',968,,,968,,,968,968,,,968,,968,471,,471,968,471,471,,471,471,471,471',
-'471,968,471,,,,968,968,968,968,,968,968,968,968,,,,,968,968,,,,116,116',
-'116,968,116,968,968,968,116,116,,,,116,,116,116,116,116,116,116,116',
+'814,814,,957,814,957,957,957,,957,814,814,814,814,814,814,814,814,814',
+'814,814,814,,814,814,814,,814,814,,814,814,814,459,,,959,,959,959,959',
+'957,959,,,,,,,459,459,,814,,,814,,,814,814,,,814,,814,459,,459,814,459',
+'459,,459,459,959,,459,814,459,,,,814,814,814,814,,814,814,814,814,,',
+',,814,814,,,,,,,814,,814,814,814,815,815,815,815,815,815,,,,815,815',
+',,,815,,815,815,815,815,815,815,815,,,,,,815,815,815,815,815,815,815',
+',994,815,994,994,994,,994,815,815,815,815,815,815,815,815,815,815,815',
+'815,,815,815,815,,815,815,,815,815,815,460,,,,,,,,994,,,,,,,,460,460',
+',815,,,815,,,815,815,,,815,,815,460,,460,815,460,460,,460,460,,,460',
+'815,460,,,,815,815,815,815,,815,815,815,815,,,,,815,815,,,,,,,815,,815',
+'815,815,839,839,839,839,839,839,,,,839,839,,,,839,,839,839,839,839,839',
+'839,839,,,,,,839,839,839,839,839,839,839,,,839,,,,,,839,839,839,839',
+'839,839,839,839,839,839,839,839,,839,839,839,,839,839,,839,839,839,461',
+',,,,,,,,,,,,,,,461,461,,839,,,839,,,839,839,,,839,,839,461,,461,839',
+'461,461,,461,461,,,461,839,461,,,,839,839,839,839,,839,839,839,839,',
+',,,839,839,,,,,,,839,,839,839,839,840,840,840,840,840,840,,,,840,840',
+',,,840,,840,840,840,840,840,840,840,,,,,,840,840,840,840,840,840,840',
+',,840,,,,,,840,840,840,840,840,840,840,840,840,840,840,840,,840,840',
+'840,,840,840,,840,840,840,462,,,,,,,,,,,,,,,,462,462,,840,,,840,,,840',
+'840,,,840,,840,462,,462,840,462,462,,462,462,,,462,840,462,,,,840,840',
+'840,840,,840,840,840,840,,,,,840,840,,,,,,,840,,840,840,840,843,843',
+'843,843,843,843,,,,843,843,,,,843,,843,843,843,843,843,843,843,,,,,',
+'843,843,843,843,843,843,843,,,843,,,,,,843,843,843,843,843,843,843,843',
+'843,843,843,843,,843,843,843,,843,843,,843,843,843,463,463,463,463,463',
+'463,463,,,463,463,,,,,,463,463,,843,,,843,,,843,843,,,843,,843,463,',
+'463,843,463,463,,463,463,463,463,463,843,463,,,,843,843,843,843,,843',
+'843,843,843,,,,,843,843,,,,,,,843,,843,843,843,849,849,849,849,849,849',
+',,,849,849,,,,849,,849,849,849,849,849,849,849,,,,,,849,849,849,849',
+'849,849,849,,,849,,,,,,849,849,849,849,849,849,849,849,849,849,849,849',
+',849,849,849,,849,849,,849,849,849,464,464,464,464,464,464,464,,,464',
+'464,,,,,,464,464,,849,,,849,,,849,849,,,849,,849,464,,464,849,464,464',
+',464,464,464,464,464,849,464,,,,849,849,849,849,,849,849,849,849,,,',
+',849,849,,,,,,,849,,849,849,849,882,882,882,882,882,882,,,,882,882,',
+',,882,,882,882,882,882,882,882,882,,,,,,882,882,882,882,882,882,882',
+',,882,,,,,,882,882,882,882,882,882,882,882,882,882,882,882,,882,882',
+'882,,882,882,,882,882,882,465,465,465,465,465,465,465,,,465,465,,,,',
+',465,465,,882,,,882,,,882,882,,,882,,882,465,,465,882,465,465,,465,465',
+'465,465,465,882,465,,,,882,882,882,882,,882,882,882,882,,,,,882,882',
+',,,,,,882,,882,882,882,943,943,943,943,943,943,,,,943,943,,,,943,,943',
+'943,943,943,943,943,943,,,,,,943,943,943,943,943,943,943,,,943,,,,,',
+'943,943,943,943,943,943,943,943,943,943,943,943,,943,943,943,,943,943',
+',943,943,943,466,466,466,466,466,466,466,,,466,466,,,,,,466,466,,943',
+',,943,,,943,943,,,943,,943,466,,466,943,466,466,,466,466,466,466,466',
+'943,466,,,,943,943,943,943,,943,943,943,943,,,,,943,943,,,,,,,943,,943',
+'943,943,960,960,960,960,960,960,,,,960,960,,,,960,,960,960,960,960,960',
+'960,960,,,,,,960,960,960,960,960,960,960,,,960,,,,,,960,960,960,960',
+'960,960,960,960,960,960,960,960,,960,960,960,,960,960,,960,960,960,467',
+'467,467,467,467,467,467,,,467,467,,,,,,467,467,,960,,,960,,,960,960',
+',,960,,960,467,,467,960,467,467,,467,467,467,467,467,960,467,,,,960',
+'960,960,960,,960,960,960,960,,,,,960,960,,,,,,,960,,960,960,960,966',
+'966,966,966,966,966,,,,966,966,,,,966,,966,966,966,966,966,966,966,',
+',,,,966,966,966,966,966,966,966,,,966,,,,,,966,966,966,966,966,966,966',
+'966,966,966,966,966,,966,966,966,,966,966,,966,966,966,470,470,470,470',
+'470,470,470,,,470,470,,,,,,470,470,,966,,,966,,,966,966,,,966,,966,470',
+',470,966,470,470,,470,470,470,470,470,966,470,,,,966,966,966,966,,966',
+'966,966,966,,,,,966,966,,,,,,,966,,966,966,966,968,968,968,968,968,968',
+',,,968,968,,,,968,,968,968,968,968,968,968,968,,,,,,968,968,968,968',
+'968,968,968,,,968,,,,,,968,968,968,968,968,968,968,968,968,968,968,968',
+',968,968,968,,968,968,,968,968,968,471,471,471,471,471,471,471,471,',
+'471,471,,,,,,471,471,,968,,,968,,,968,968,,,968,,968,471,,471,968,471',
+'471,,471,471,471,471,471,968,471,,,,968,968,968,968,,968,968,968,968',
+',,,,968,968,,,,,,,968,,968,968,968,5,5,5,5,5,,,,5,5,,,,5,,5,5,5,5,5',
+'5,5,,,,,,5,5,5,5,5,5,5,,,5,,,,,,5,5,5,5,5,5,5,5,5,5,5,5,,5,5,5,,5,5',
+',5,5,5,455,,,,,,,,,,,,,,,,455,455,,5,,,5,,,5,5,,,5,,5,455,,455,5,455',
+'455,,455,455,,,,5,,,,,5,5,5,5,,5,5,5,5,,,,,5,5,,,,20,20,20,5,20,5,5',
+'5,20,20,,,,20,,20,20,20,20,20,20,20,,,,,,20,20,20,20,20,20,20,,,20,',
+',,,,,20,,,20,20,20,20,20,20,20,20,,20,20,20,,20,20,,20,20,20,456,,,',
+',,,,,,,,,,,,456,456,,20,,,20,,,20,20,,,20,,,456,,456,20,456,456,,456',
+'456,,,,20,,,,,20,20,20,20,,20,20,20,20,,,,,20,20,,,,29,29,29,20,29,20',
+'20,20,29,29,,,,29,,29,29,29,29,29,29,29,,,,,,29,29,29,29,29,29,29,,',
+'29,,,,,,,29,,,29,29,29,29,29,29,29,29,29,29,29,29,,29,29,,29,29,29,457',
+',,,,,,,,,,,,,,,457,457,,29,,,29,,,29,29,,,29,,29,457,29,,29,457,457',
+'29,457,457,,,,29,,,,,29,29,29,29,,29,29,29,29,,,,,29,29,,,,30,30,30',
+'29,30,29,29,29,30,30,,,,30,,30,30,30,30,30,30,30,,,,,,30,30,30,30,30',
+'30,30,,,30,,,,,,,30,,,30,30,30,30,30,30,30,30,30,30,30,30,,30,30,,30',
+'30,30,,,,,,,,,,,,,,,,,,,,30,,,30,,,30,30,,,30,,30,,30,,30,,,30,,,,,',
+'30,,,,,30,30,30,30,,30,30,30,30,,,,,30,30,,,,31,31,31,30,31,30,30,30',
+'31,31,,,,31,,31,31,31,31,31,31,31,,,,,,31,31,31,31,31,31,31,,,31,,,',
+',,,31,,,31,31,31,31,31,31,31,31,31,31,31,31,,31,31,,31,31,31,,,,,,,',
+',,,,,,,,,,,,31,,,31,,,31,31,,,31,,31,,31,,31,,,31,,,,,,31,,,,,31,31',
+'31,31,,31,31,31,31,,,,,31,31,,,,34,34,34,31,34,31,31,31,34,34,,,,34',
+',34,34,34,34,34,34,34,,,,,,34,34,34,34,34,34,34,,,34,,,,,,,34,,,34,34',
+'34,34,34,34,34,34,,34,34,34,,34,34,,,,34,,,,,,,,,,,,,,,,,,,,34,,,34',
+',,34,34,,,34,,34,,,,,,,,,,,,,,,,,,34,34,34,34,,34,34,34,34,,,,,34,34',
+',,,35,35,35,34,35,34,34,34,35,35,,,,35,,35,35,35,35,35,35,35,,,,,,35',
+'35,35,35,35,35,35,,,35,,,,,,,35,,,35,35,35,35,35,35,35,35,,35,35,35',
+',35,35,,,,35,,,,,,,,,,,,,,,,,,,,35,,,35,,,35,35,,,35,,697,,697,697,697',
+'697,697,,,,,,,,,,697,,35,35,35,35,,35,35,35,35,,,,,35,35,,,,35,,697',
+'35,,35,35,35,42,42,42,,42,697,697,,42,42,697,,,42,,42,42,42,42,42,42',
+'42,,,,,,42,42,42,42,42,42,42,,,42,,,,,,,42,,,42,42,42,42,42,42,42,42',
+',42,42,42,,42,42,,42,42,42,,,,,,,,,,,,,,,,,,,,42,,,42,,,42,42,,,42,',
+',,,,42,,,,,,,,,42,,,,,42,42,42,42,,42,42,42,42,,,,,42,42,,,,43,43,43',
+'42,43,42,42,42,43,43,,,,43,,43,43,43,43,43,43,43,,,,,,43,43,43,43,43',
+'43,43,,,43,,,,,,,43,,,43,43,43,43,43,43,43,43,,43,43,43,,43,43,,43,43',
+'43,,,,,,,,,,,,,,,,,,,,43,,,43,,,43,43,,,43,,,,,,43,,,,,,,,,43,,,,,43',
+'43,43,43,,43,43,43,43,,,,,43,43,,,,44,44,44,43,44,43,43,43,44,44,,,',
+'44,,44,44,44,44,44,44,44,,,,,,44,44,44,44,44,44,44,,,44,,,,,,,44,,,44',
+'44,44,44,44,44,44,44,,44,44,44,,44,44,,44,44,44,,,,,,,,,,,,,,,,,,,,44',
+',,44,,,44,44,,,44,,,,,,44,,,,,,,,,44,,,,,44,44,44,44,,44,44,44,44,,',
+',,44,44,,,,59,59,59,44,59,44,44,44,59,59,,,,59,,59,59,59,59,59,59,59',
+',,,,,59,59,59,59,59,59,59,,,59,,,,,,,59,,,59,59,59,59,59,59,59,59,59',
+'59,59,59,,59,59,,59,59,59,,,,,,,,,,,,,,,,,,,,59,,,59,,,59,59,,,59,,59',
+',,,59,,,59,,,,,,59,,,,,59,59,59,59,,59,59,59,59,,,,,59,59,,,,60,60,60',
+'59,60,59,59,59,60,60,,,,60,,60,60,60,60,60,60,60,,,,,,60,60,60,60,60',
+'60,60,,,60,,,,,,,60,,,60,60,60,60,60,60,60,60,60,60,60,60,,60,60,,60',
+'60,60,,,,,,,,,,,,,,,,,,,,60,,,60,,,60,60,,,60,,,,,,60,,,60,,,,,,60,',
+',,,60,60,60,60,,60,60,60,60,,,,,60,60,,,,63,63,63,60,63,60,60,60,63',
+'63,,,,63,,63,63,63,63,63,63,63,,,,,,63,63,63,63,63,63,63,,,63,,,,,,',
+'63,,,63,63,63,63,63,63,63,63,,63,63,63,,63,63,,63,63,63,,,,,,,,,,,,',
+',,,,,,,63,,,63,,,63,63,,,63,,,,,,63,,,,,,,,,63,,,,,63,63,63,63,,63,63',
+'63,63,,,,,63,63,,,,64,64,64,63,64,63,63,63,64,64,,,,64,,64,64,64,64',
+'64,64,64,,,,,,64,64,64,64,64,64,64,,,64,,,,,,,64,,,64,64,64,64,64,64',
+'64,64,,64,64,64,,64,64,,64,64,64,,,,,,,,,,,,,,,,,,,,64,,,64,,,64,64',
+',,64,,,,,,64,,,,,,,,,64,,,,,64,64,64,64,,64,64,64,64,,,,,64,64,,,,67',
+'67,67,64,67,64,64,64,67,67,,,,67,,67,67,67,67,67,67,67,,,,,,67,67,67',
+'67,67,67,67,,,67,,,,,,,67,,,67,67,67,67,67,67,67,67,,67,67,67,,67,67',
+',67,67,67,,,,,,,,,,,,,,,,,,,,67,,,67,,,67,67,,,67,,,,,,67,,,,,,,,,67',
+',,,,67,67,67,67,,67,67,67,67,,,,,67,67,67,,,,,67,67,,67,67,67,68,68',
+'68,,68,,,,68,68,,,,68,,68,68,68,68,68,68,68,,,,,,68,68,68,68,68,68,68',
+',,68,,,,,,,68,,,68,68,68,68,68,68,68,68,,68,68,68,,68,68,,,,68,,,,,',
+',,,,,,,,,,,,,,68,,,68,,,68,68,,,68,,68,,,,,,,,,,,,,,,,,,68,68,68,68',
+',68,68,68,68,,,,,68,68,,,,69,69,69,68,69,68,68,68,69,69,,,,69,,69,69',
+'69,69,69,69,69,,,,,,69,69,69,69,69,69,69,,,69,,,,,,,69,,,69,69,69,69',
+'69,69,69,69,,69,69,69,,69,69,,,,69,,,,,,,,,,,,,,,,,69,,,69,,,69,,,69',
+'69,,,69,,,,,,,,,,,,,,,,,,,,69,69,69,69,,69,69,69,69,,,,,69,69,,,,70',
+'70,70,69,70,69,69,69,70,70,,,,70,,70,70,70,70,70,70,70,,,,,,70,70,70',
+'70,70,70,70,,,70,,,,,,,70,,,70,70,70,70,70,70,70,70,,70,70,70,,70,70',
+',,,70,,,,,,,,,,,,,,,,,,,,70,,,70,,,70,70,,,70,,869,,869,869,869,869',
+'869,,,,,,,,,,869,,70,70,70,70,,70,70,70,70,,,,,70,70,,,,,,869,70,,70',
+'70,70,111,111,111,111,111,869,869,,111,111,869,,,111,,111,111,111,111',
+'111,111,111,,,,,,111,111,111,111,111,111,111,,,111,,,,,,111,111,111',
+'111,111,111,111,111,111,111,111,111,,111,111,111,,111,111,,111,111,111',
+',,,,,,,,,,,,,,,,,,,111,,,111,,,111,111,,,111,,111,,,,111,,,,,,,,,111',
+',,,,111,111,111,111,,111,111,111,111,,,,,111,111,,,,,,111,111,,111,111',
+'111,116,116,116,,116,,,,116,116,,,,116,,116,116,116,116,116,116,116',
',,,,,116,116,116,116,116,116,116,,,116,,,,,,,116,,,116,116,116,116,116',
-'116,116,116,,116,116,116,,116,116,,116,116,116,467,467,467,467,467,467',
-'467,,,467,467,,,,,,467,467,,116,,,116,,,116,116,,,116,,,467,,467,116',
-'467,467,,467,467,467,467,467,116,467,,,,116,116,116,116,,116,116,116',
-'116,,,,,116,116,,,,117,117,117,116,117,116,116,116,117,117,,,,117,,117',
-'117,117,117,117,117,117,,,,,,117,117,117,117,117,117,117,,,117,,,,,',
-',117,,,117,117,117,117,117,117,117,117,,117,117,117,,117,117,,117,117',
-'117,455,,,,,,,,,,,,,,,,455,455,,117,,,117,,,117,117,,,117,,,455,,455',
-'117,455,455,,455,455,,,,117,,,,,117,117,117,117,,117,117,117,117,,,',
-',117,117,,,,118,118,118,117,118,117,117,117,118,118,,,,118,,118,118',
-'118,118,118,118,118,,,,,,118,118,118,118,118,118,118,,,118,,,,,,,118',
-',,118,118,118,118,118,118,118,118,,118,118,118,,118,118,,118,118,118',
-'456,,,,,,,,,,,,,,,,456,456,,118,,,118,,,118,118,,,118,,,456,,456,118',
-'456,456,,456,456,,,,118,,,,,118,118,118,118,,118,118,118,118,,,,,118',
-'118,,,,119,119,119,118,119,118,118,118,119,119,,,,119,,119,119,119,119',
-'119,119,119,,,,,,119,119,119,119,119,119,119,,,119,,,,,,,119,,,119,119',
-'119,119,119,119,119,119,,119,119,119,,119,119,,119,119,119,457,,,,,',
-',,,,,,,,,,457,457,,119,,,119,,,119,119,,,119,,,457,,,119,457,457,,457',
-'457,,,,119,,,,,119,119,119,119,,119,119,119,119,,,,,119,119,,,,,,,119',
-',119,119,119,120,120,120,120,120,,,,120,120,,,,120,,120,120,120,120',
-'120,120,120,,,,,,120,120,120,120,120,120,120,,,120,,,,,,120,120,,120',
-'120,120,120,120,120,120,120,120,,120,120,120,,120,120,,120,120,120,',
-',,,,,,,,,,,,,,,,,,120,,,120,,,120,120,,,120,,120,,,,120,,,,,,,,,120',
-',,,,120,120,120,120,,120,120,120,120,,,,,120,120,,,,725,725,725,120',
-'725,120,120,120,725,725,,,,725,,725,725,725,725,725,725,725,,,,,,725',
-'725,725,725,725,725,725,,,725,,,,,,,725,,,725,725,725,725,725,725,725',
-'725,,725,725,725,,725,725,,725,725,725,,,,,,,,,,,,,,,,,,,,725,,,725',
-',,725,725,,,725,,,,,,725,,,,,,,,,725,,,,,725,725,725,725,,725,725,725',
-'725,,,,,725,725,,,,699,699,699,725,699,725,725,725,699,699,,,,699,,699',
-'699,699,699,699,699,699,,,,,,699,699,699,699,699,699,699,,,699,,,,,',
-',699,,,699,699,699,699,699,699,699,699,,699,699,699,,699,699,,699,699',
-'699,,,,,,,,,,,,,,,,,,,,699,,,699,,,699,699,,,699,,,,,,699,,,,,,,,,699',
-',,,,699,699,699,699,,699,699,699,699,,,,,699,699,,,,207,207,207,699',
-'207,699,699,699,207,207,,,,207,,207,207,207,207,207,207,207,,,,,,207',
-'207,207,207,207,207,207,,,207,,,,,,,207,,,207,207,207,207,207,207,207',
-'207,,207,207,207,,207,207,,207,207,207,,,,,,,,,,,,,,,,,,,,207,,,207',
-',,207,207,,,207,,207,,,,207,,,,,,,,,207,,,,,207,207,207,207,,207,207',
-'207,207,,,,,207,207,,,,208,208,208,207,208,207,207,207,208,208,,,,208',
-',208,208,208,208,208,208,208,,,,,,208,208,208,208,208,208,208,,,208',
-',,,,,,208,,,208,208,208,208,208,208,208,208,,208,208,208,,208,208,,208',
-'208,208,,,,,,,,,,,,,,,,,,,,208,,,208,,,208,208,,,208,,,,,,208,,,,,,',
-',,208,,,,,208,208,208,208,,208,208,208,208,,,,,208,208,,,,209,209,209',
-'208,209,208,208,208,209,209,,,,209,,209,209,209,209,209,209,209,,,,',
-',209,209,209,209,209,209,209,,,209,,,,,,,209,,,209,209,209,209,209,209',
-'209,209,209,209,209,209,,209,209,,209,209,209,,,,,,,,,,,,,,,,,,,,209',
-',,209,,,209,209,,,209,,209,,209,,209,,,209,,,,,,209,,,,,209,209,209',
-'209,,209,209,209,209,,,,,209,209,,,,682,682,682,209,682,209,209,209',
-'682,682,,,,682,,682,682,682,682,682,682,682,,,,,,682,682,682,682,682',
-'682,682,,,682,,,,,,,682,,,682,682,682,682,682,682,682,682,,682,682,682',
-',682,682,,682,682,682,,,,,,,,,,,,,,,,,,,,682,,,682,,,682,682,,,682,',
-'682,,,,682,,,,,,,,,682,,,,,682,682,682,682,,682,682,682,682,,,,,682',
-'682,,,,677,677,677,682,677,682,682,682,677,677,,,,677,,677,677,677,677',
-'677,677,677,,,,,,677,677,677,677,677,677,677,,,677,,,,,,,677,,,677,677',
-'677,677,677,677,677,677,,677,677,677,,677,677,,,,677,,,,,,,,,,,,,,,',
-',,,,677,,,677,,,677,677,,,677,,,,,,,,,,,,,,,,,,,,677,677,677,677,,677',
-'677,677,677,,,,,677,677,,,,212,212,212,677,212,677,677,677,212,212,',
-',,212,,212,212,212,212,212,212,212,,,,,,212,212,212,212,212,212,212',
-',,212,,,,,,,212,,,212,212,212,212,212,212,212,212,,212,212,212,,212',
-'212,,212,212,212,,,,,,,,,,,,,,,,,,,,212,,,212,,,212,212,,,212,,,,,,212',
-',,,,,,,,212,,,,,212,212,212,212,,212,212,212,212,,,,,212,212,,,,213',
-'213,213,212,213,212,212,212,213,213,,,,213,,213,213,213,213,213,213',
-'213,,,,,,213,213,213,213,213,213,213,,,213,,,,,,,213,,,213,213,213,213',
-'213,213,213,213,,213,213,213,,213,213,,213,213,213,,,,,,,,,,,,,,,,,',
-',,213,,,213,,,213,213,,,213,,213,,,,213,,,,,,,,,213,,,,,213,213,213',
-'213,,213,213,213,213,,,,,213,213,,,,214,214,214,213,214,213,213,213',
-'214,214,,,,214,,214,214,214,214,214,214,214,,,,,,214,214,214,214,214',
-'214,214,,,214,,,,,,,214,,,214,214,214,214,214,214,214,214,,214,214,214',
-',214,214,,214,214,214,,,,,,,,,,,,,,,,,,,,214,,,214,,,214,214,,,214,',
-',,,,214,,,,,,,,,214,,,,,214,214,214,214,,214,214,214,214,,,,,214,214',
-',,,215,215,215,214,215,214,214,214,215,215,,,,215,,215,215,215,215,215',
-'215,215,,,,,,215,215,215,215,215,215,215,,,215,,,,,,,215,,,215,215,215',
-'215,215,215,215,215,,215,215,215,,215,215,,215,215,215,,,,,,,,,,,,,',
-',,,,,,215,,,215,,,215,215,,,215,,,,,,215,,,,,,,,,215,,,,,215,215,215',
-'215,,215,215,215,215,,,,,215,215,,,,216,216,216,215,216,215,215,215',
-'216,216,,,,216,,216,216,216,216,216,216,216,,,,,,216,216,216,216,216',
-'216,216,,,216,,,,,,,216,,,216,216,216,216,216,216,216,216,,216,216,216',
-',216,216,,216,216,216,,,,,,,,,,,,,,,,,,,,216,,,216,,,216,216,,,216,',
-',,,,216,,,,,,,,,216,,,,,216,216,216,216,,216,216,216,216,,,,,216,216',
-',,,217,217,217,216,217,216,216,216,217,217,,,,217,,217,217,217,217,217',
-'217,217,,,,,,217,217,217,217,217,217,217,,,217,,,,,,,217,,,217,217,217',
-'217,217,217,217,217,,217,217,217,,217,217,,217,217,217,,,,,,,,,,,,,',
-',,,,,,217,,,217,,,217,217,,,217,,,,,,217,,,,,,,,,217,,,,,217,217,217',
-'217,,217,217,217,217,,,,,217,217,217,,,666,666,666,217,666,217,217,217',
-'666,666,,,,666,,666,666,666,666,666,666,666,,,,,,666,666,666,666,666',
-'666,666,,,666,,,,,,,666,,,666,666,666,666,666,666,666,666,,666,666,666',
-',666,666,,,,666,,,,,,,,,,,,,,,,,,,,666,,,666,,,666,666,,,666,,,,,,,',
-',,,,,,,,,,,,666,666,666,666,,666,666,666,666,,,,,666,666,,,,662,662',
-'662,666,662,666,666,666,662,662,,,,662,,662,662,662,662,662,662,662',
-',,,,,662,662,662,662,662,662,662,,,662,,,,,,,662,,,662,662,662,662,662',
-'662,662,662,,662,662,662,,662,662,,662,662,662,,,,,,,,,,,,,,,,,,,,662',
-',,662,,,662,662,,,662,,,,,,662,,,,,,,,,662,,,,,662,662,662,662,,662',
-'662,662,662,,,,,662,662,,,,659,659,659,662,659,662,662,662,659,659,',
-',,659,,659,659,659,659,659,659,659,,,,,,659,659,659,659,659,659,659',
-',,659,,,,,,,659,,,659,659,659,659,659,659,659,659,,659,659,659,,659',
-'659,,659,659,659,,,,,,,,,,,,,,,,,,,,659,,,659,,,659,659,,,659,,,,,,659',
-',,,,,,,,659,,,,,659,659,659,659,,659,659,659,659,,,,,659,659,,,,228',
-'228,228,659,228,659,659,659,228,228,,,,228,,228,228,228,228,228,228',
-'228,,,,,,228,228,228,228,228,228,228,,,228,,,,,,,228,,,228,228,228,228',
-'228,228,228,228,,228,228,228,,228,228,,228,228,228,,,,,,,,,,,,,,,,,',
-',,228,,,228,,,228,228,,,228,,,,,,228,,,,,,,,,228,,,,,228,228,228,228',
-',228,228,228,228,,,,,228,228,,,,231,231,231,228,231,228,228,228,231',
-'231,,,,231,,231,231,231,231,231,231,231,,,,,,231,231,231,231,231,231',
-'231,,,231,,,,,,,231,,,231,231,231,231,231,231,231,231,,231,231,231,',
-'231,231,,231,231,231,,,,,,,,,,,,,,,,,,,,231,,,231,,,231,231,,,231,,',
-',,,231,,,,,,,,,231,,,,,231,231,231,231,,231,231,231,231,,,,,231,231',
-',,,232,232,232,231,232,231,231,231,232,232,,,,232,,232,232,232,232,232',
-'232,232,,,,,,232,232,232,232,232,232,232,,,232,,,,,,,232,,,232,232,232',
-'232,232,232,232,232,,232,232,232,,232,232,,232,232,232,,,,,,,,,,,,,',
-',,,,,,232,,,232,,,232,232,,,232,,,,,,232,,,,,,,,,232,,,,,232,232,232',
-'232,,232,232,232,232,,,,,232,232,,,,233,233,233,232,233,232,232,232',
-'233,233,,,,233,,233,233,233,233,233,233,233,,,,,,233,233,233,233,233',
-'233,233,,,233,,,,,,,233,,,233,233,233,233,233,233,233,233,,233,233,233',
-',233,233,,233,233,233,,,,,,,,,,,,,,,,,,,,233,,,233,,,233,233,,,233,',
-',,,,233,,,,,,,,,233,,,,,233,233,233,233,,233,233,233,233,,,,,233,233',
-',,,234,234,234,233,234,233,233,233,234,234,,,,234,,234,234,234,234,234',
-'234,234,,,,,,234,234,234,234,234,234,234,,,234,,,,,,,234,,,234,234,234',
-'234,234,234,234,234,,234,234,234,,234,234,,234,234,234,,,,,,,,,,,,,',
-',,,,,,234,,,234,,,234,234,,,234,,,,,,234,,,,,,,,,234,,,,,234,234,234',
-'234,,234,234,234,234,,,,,234,234,,,,235,235,235,234,235,234,234,234',
-'235,235,,,,235,,235,235,235,235,235,235,235,,,,,,235,235,235,235,235',
-'235,235,,,235,,,,,,,235,,,235,235,235,235,235,235,235,235,,235,235,235',
-',235,235,,235,235,235,,,,,,,,,,,,,,,,,,,,235,,,235,,,235,235,,,235,',
-',,,,235,,,,,,,,,235,,,,,235,235,235,235,,235,235,235,235,,,,,235,235',
-',,,236,236,236,235,236,235,235,235,236,236,,,,236,,236,236,236,236,236',
-'236,236,,,,,,236,236,236,236,236,236,236,,,236,,,,,,,236,,,236,236,236',
-'236,236,236,236,236,,236,236,236,,236,236,,236,236,236,,,,,,,,,,,,,',
-',,,,,,236,,,236,,,236,236,,,236,,,,,,236,,,,,,,,,236,,,,,236,236,236',
-'236,,236,236,236,236,,,,,236,236,,,,237,237,237,236,237,236,236,236',
-'237,237,,,,237,,237,237,237,237,237,237,237,,,,,,237,237,237,237,237',
-'237,237,,,237,,,,,,,237,,,237,237,237,237,237,237,237,237,,237,237,237',
-',237,237,,237,237,237,,,,,,,,,,,,,,,,,,,,237,,,237,,,237,237,,,237,',
-',,,,237,,,,,,,,,237,,,,,237,237,237,237,,237,237,237,237,,,,,237,237',
-',,,238,238,238,237,238,237,237,237,238,238,,,,238,,238,238,238,238,238',
-'238,238,,,,,,238,238,238,238,238,238,238,,,238,,,,,,,238,,,238,238,238',
-'238,238,238,238,238,,238,238,238,,238,238,,238,238,238,,,,,,,,,,,,,',
-',,,,,,238,,,238,,,238,238,,,238,,,,,,238,,,,,,,,,238,,,,,238,238,238',
-'238,,238,238,238,238,,,,,238,238,,,,239,239,239,238,239,238,238,238',
-'239,239,,,,239,,239,239,239,239,239,239,239,,,,,,239,239,239,239,239',
-'239,239,,,239,,,,,,,239,,,239,239,239,239,239,239,239,239,,239,239,239',
-',239,239,,239,239,239,,,,,,,,,,,,,,,,,,,,239,,,239,,,239,239,,,239,',
-',,,,239,,,,,,,,,239,,,,,239,239,239,239,,239,239,239,239,,,,,239,239',
-',,,240,240,240,239,240,239,239,239,240,240,,,,240,,240,240,240,240,240',
-'240,240,,,,,,240,240,240,240,240,240,240,,,240,,,,,,,240,,,240,240,240',
-'240,240,240,240,240,,240,240,240,,240,240,,240,240,240,,,,,,,,,,,,,',
-',,,,,,240,,,240,,,240,240,,,240,,,,,,240,,,,,,,,,240,,,,,240,240,240',
-'240,,240,240,240,240,,,,,240,240,,,,241,241,241,240,241,240,240,240',
-'241,241,,,,241,,241,241,241,241,241,241,241,,,,,,241,241,241,241,241',
-'241,241,,,241,,,,,,,241,,,241,241,241,241,241,241,241,241,,241,241,241',
-',241,241,,241,241,241,,,,,,,,,,,,,,,,,,,,241,,,241,,,241,241,,,241,',
-',,,,241,,,,,,,,,241,,,,,241,241,241,241,,241,241,241,241,,,,,241,241',
-',,,242,242,242,241,242,241,241,241,242,242,,,,242,,242,242,242,242,242',
-'242,242,,,,,,242,242,242,242,242,242,242,,,242,,,,,,,242,,,242,242,242',
-'242,242,242,242,242,,242,242,242,,242,242,,242,242,242,,,,,,,,,,,,,',
-',,,,,,242,,,242,,,242,242,,,242,,,,,,242,,,,,,,,,242,,,,,242,242,242',
-'242,,242,242,242,242,,,,,242,242,,,,243,243,243,242,243,242,242,242',
-'243,243,,,,243,,243,243,243,243,243,243,243,,,,,,243,243,243,243,243',
-'243,243,,,243,,,,,,,243,,,243,243,243,243,243,243,243,243,,243,243,243',
-',243,243,,243,243,243,,,,,,,,,,,,,,,,,,,,243,,,243,,,243,243,,,243,',
-',,,,243,,,,,,,,,243,,,,,243,243,243,243,,243,243,243,243,,,,,243,243',
-',,,244,244,244,243,244,243,243,243,244,244,,,,244,,244,244,244,244,244',
-'244,244,,,,,,244,244,244,244,244,244,244,,,244,,,,,,,244,,,244,244,244',
-'244,244,244,244,244,,244,244,244,,244,244,,244,244,244,,,,,,,,,,,,,',
-',,,,,,244,,,244,,,244,244,,,244,,,,,,244,,,,,,,,,244,,,,,244,244,244',
-'244,,244,244,244,244,,,,,244,244,,,,245,245,245,244,245,244,244,244',
-'245,245,,,,245,,245,245,245,245,245,245,245,,,,,,245,245,245,245,245',
-'245,245,,,245,,,,,,,245,,,245,245,245,245,245,245,245,245,,245,245,245',
-',245,245,,245,245,245,,,,,,,,,,,,,,,,,,,,245,,,245,,,245,245,,,245,',
-',,,,245,,,,,,,,,245,,,,,245,245,245,245,,245,245,245,245,,,,,245,245',
-',,,246,246,246,245,246,245,245,245,246,246,,,,246,,246,246,246,246,246',
-'246,246,,,,,,246,246,246,246,246,246,246,,,246,,,,,,,246,,,246,246,246',
-'246,246,246,246,246,,246,246,246,,246,246,,246,246,246,,,,,,,,,,,,,',
-',,,,,,246,,,246,,,246,246,,,246,,,,,,246,,,,,,,,,246,,,,,246,246,246',
-'246,,246,246,246,246,,,,,246,246,,,,247,247,247,246,247,246,246,246',
-'247,247,,,,247,,247,247,247,247,247,247,247,,,,,,247,247,247,247,247',
-'247,247,,,247,,,,,,,247,,,247,247,247,247,247,247,247,247,,247,247,247',
-',247,247,,247,247,247,,,,,,,,,,,,,,,,,,,,247,,,247,,,247,247,,,247,',
-',,,,247,,,,,,,,,247,,,,,247,247,247,247,,247,247,247,247,,,,,247,247',
-',,,248,248,248,247,248,247,247,247,248,248,,,,248,,248,248,248,248,248',
-'248,248,,,,,,248,248,248,248,248,248,248,,,248,,,,,,,248,,,248,248,248',
-'248,248,248,248,248,,248,248,248,,248,248,,248,248,248,,,,,,,,,,,,,',
-',,,,,,248,,,248,,,248,248,,,248,,,,,,248,,,,,,,,,248,,,,,248,248,248',
-'248,,248,248,248,248,,,,,248,248,,,,249,249,249,248,249,248,248,248',
-'249,249,,,,249,,249,249,249,249,249,249,249,,,,,,249,249,249,249,249',
-'249,249,,,249,,,,,,,249,,,249,249,249,249,249,249,249,249,,249,249,249',
-',249,249,,249,249,249,,,,,,,,,,,,,,,,,,,,249,,,249,,,249,249,,,249,',
-',,,,249,,,,,,,,,249,,,,,249,249,249,249,,249,249,249,249,,,,,249,249',
-',,,250,250,250,249,250,249,249,249,250,250,,,,250,,250,250,250,250,250',
-'250,250,,,,,,250,250,250,250,250,250,250,,,250,,,,,,,250,,,250,250,250',
-'250,250,250,250,250,,250,250,250,,250,250,,250,250,250,,,,,,,,,,,,,',
-',,,,,,250,,,250,,,250,250,,,250,,,,,,250,,,,,,,,,250,,,,,250,250,250',
-'250,,250,250,250,250,,,,,250,250,,,,251,251,251,250,251,250,250,250',
-'251,251,,,,251,,251,251,251,251,251,251,251,,,,,,251,251,251,251,251',
-'251,251,,,251,,,,,,,251,,,251,251,251,251,251,251,251,251,,251,251,251',
-',251,251,,251,251,251,,,,,,,,,,,,,,,,,,,,251,,,251,,,251,251,,,251,',
-',,,,251,,,,,,,,,251,,,,,251,251,251,251,,251,251,251,251,,,,,251,251',
-',,,252,252,252,251,252,251,251,251,252,252,,,,252,,252,252,252,252,252',
-'252,252,,,,,,252,252,252,252,252,252,252,,,252,,,,,,,252,,,252,252,252',
-'252,252,252,252,252,,252,252,252,,252,252,,252,252,252,,,,,,,,,,,,,',
-',,,,,,252,,,252,,,252,252,,,252,,,,,,252,,,,,,,,,252,,,,,252,252,252',
-'252,,252,252,252,252,,,,,252,252,,,,253,253,253,252,253,252,252,252',
-'253,253,,,,253,,253,253,253,253,253,253,253,,,,,,253,253,253,253,253',
-'253,253,,,253,,,,,,,253,,,253,253,253,253,253,253,253,253,,253,253,253',
-',253,253,,253,253,253,,,,,,,,,,,,,,,,,,,,253,,,253,,,253,253,,,253,',
-',,,,253,,,,,,,,,253,,,,,253,253,253,253,,253,253,253,253,,,,,253,253',
-',,,254,254,254,253,254,253,253,253,254,254,,,,254,,254,254,254,254,254',
-'254,254,,,,,,254,254,254,254,254,254,254,,,254,,,,,,,254,,,254,254,254',
-'254,254,254,254,254,,254,254,254,,254,254,,254,254,254,,,,,,,,,,,,,',
-',,,,,,254,,,254,,,254,254,,,254,,,,,,254,,,,,,,,,254,,,,,254,254,254',
-'254,,254,254,254,254,,,,,254,254,,,,255,255,255,254,255,254,254,254',
-'255,255,,,,255,,255,255,255,255,255,255,255,,,,,,255,255,255,255,255',
-'255,255,,,255,,,,,,,255,,,255,255,255,255,255,255,255,255,,255,255,255',
-',255,255,,255,255,255,,,,,,,,,,,,,,,,,,,,255,,,255,,,255,255,,,255,',
-',,,,255,,,,,,,,,255,,,,,255,255,255,255,,255,255,255,255,,,,,255,255',
-',,,635,635,635,255,635,255,255,255,635,635,,,,635,,635,635,635,635,635',
-'635,635,,,,,,635,635,635,635,635,635,635,,,635,,,,,,,635,,,635,635,635',
-'635,635,635,635,635,,635,635,635,,635,635,,635,635,635,,,,,,,,,,,,,',
-',,,,,,635,,,635,,,635,635,,,635,,,,,,635,,,,,,,,,635,,,,,635,635,635',
-'635,,635,635,635,635,,,,,635,635,,,,634,634,634,635,634,635,635,635',
-'634,634,,,,634,,634,634,634,634,634,634,634,,,,,,634,634,634,634,634',
-'634,634,,,634,,,,,,,634,,,634,634,634,634,634,634,634,634,,634,634,634',
-',634,634,,634,634,634,,,,,,,,,,,,,,,,,,,,634,,,634,,,634,634,,,634,',
-',,,,634,,,,,,,,,634,,,,,634,634,634,634,,634,634,634,634,,,,,634,634',
-',,,263,263,263,634,263,634,634,634,263,263,,,,263,,263,263,263,263,263',
-'263,263,,,,,,263,263,263,263,263,263,263,,,263,,,,,,,263,,,263,263,263',
-'263,263,263,263,263,263,263,263,263,,263,263,,263,263,263,,,,,,,,,,',
-',,,,,,,,,263,,,263,,,263,263,,,263,,263,,263,,263,,,263,,,,,,263,,,',
-',263,263,263,263,,263,263,263,263,,,,,263,263,,,,264,264,264,263,264',
-'263,263,263,264,264,,,,264,,264,264,264,264,264,264,264,,,,,,264,264',
-'264,264,264,264,264,,,264,,,,,,,264,,,264,264,264,264,264,264,264,264',
-'264,264,264,264,,264,264,,264,264,264,,,,,,,,,,,,,,,,,,,,264,,,264,',
-',264,264,,,264,,264,,264,,264,,,264,,,,,,264,,,,,264,264,264,264,,264',
-'264,264,264,,,,,264,264,,,,272,272,272,264,272,264,264,264,272,272,',
-',,272,,272,272,272,272,272,272,272,,,,,,272,272,272,272,272,272,272',
-',,272,,,,,,,272,,,272,272,272,272,272,272,272,272,272,272,272,272,,272',
-'272,,272,272,272,,,,,,,,,,,,,,,,,,,,272,,,272,,,272,272,,,272,,272,',
-'272,,272,,,272,,,,,,272,,,,,272,272,272,272,,272,272,272,272,,,,,272',
-'272,272,,,631,631,631,272,631,272,272,272,631,631,,,,631,,631,631,631',
-'631,631,631,631,,,,,,631,631,631,631,631,631,631,,,631,,,,,,,631,,,631',
-'631,631,631,631,631,631,631,,631,631,631,,631,631,,631,631,631,,,,,',
-',,,,,,,,,,,,,,631,,,631,,,631,631,,,631,,,,,,631,,,,,,,,,631,,,,,631',
-'631,631,631,,631,631,631,631,,,,,631,631,,,,630,630,630,631,630,631',
-'631,631,630,630,,,,630,,630,630,630,630,630,630,630,,,,,,630,630,630',
-'630,630,630,630,,,630,,,,,,,630,,,630,630,630,630,630,630,630,630,,630',
-'630,630,,630,630,,630,630,630,,,,,,,,,,,,,,,,,,,,630,,,630,,,630,630',
-',,630,,,,,,630,,,,,,,,,630,,,,,630,630,630,630,,630,630,630,630,,,,',
-'630,630,,,,626,626,626,630,626,630,630,630,626,626,,,,626,,626,626,626',
-'626,626,626,626,,,,,,626,626,626,626,626,626,626,,,626,,,,,,,626,,,626',
-'626,626,626,626,626,626,626,,626,626,626,,626,626,,626,626,626,,,,,',
-',,,,,,,,,,,,,,626,,,626,,,626,626,,,626,,,,,,626,,,,,,,,,626,,,,,626',
-'626,626,626,,626,626,626,626,,,,,626,626,,,,279,279,279,626,279,626',
-'626,626,279,279,,,,279,,279,279,279,279,279,279,279,,,,,,279,279,279',
-'279,279,279,279,,,279,,,,,,,279,,,279,279,279,279,279,279,279,279,,279',
-'279,279,,279,279,,279,279,279,,,,,,,,,,,,,,,,,,,,279,,,279,,,279,279',
-',,279,,,,,,279,,,,,,,,,279,,,,,279,279,279,279,,279,279,279,279,,,,',
-'279,279,,,,625,625,625,279,625,279,279,279,625,625,,,,625,,625,625,625',
-'625,625,625,625,,,,,,625,625,625,625,625,625,625,,,625,,,,,,,625,,,625',
-'625,625,625,625,625,625,625,,625,625,625,,625,625,,625,625,625,,,,,',
-',,,,,,,,,,,,,,625,,,625,,,625,625,,,625,,,,,,625,,,,,,,,,625,,,,,625',
-'625,625,625,,625,625,625,625,,,,,625,625,,,,281,281,281,625,281,625',
-'625,625,281,281,,,,281,,281,281,281,281,281,281,281,,,,,,281,281,281',
-'281,281,281,281,,,281,,,,,,,281,,,281,281,281,281,281,281,281,281,,281',
-'281,281,,281,281,,281,281,281,,,,,,,,,,,,,,,,,,,,281,,,281,,,281,281',
-',,281,,,,,,281,,,,,,,,,281,,,,,281,281,281,281,,281,281,281,281,,,,',
-'281,281,,,,284,284,284,281,284,281,281,281,284,284,,,,284,,284,284,284',
-'284,284,284,284,,,,,,284,284,284,284,284,284,284,,,284,,,,,,,284,,,284',
-'284,284,284,284,284,284,284,,284,284,284,,284,284,,284,284,284,,,,,',
-',,,,,,,,,,,,,,284,,,284,,,284,284,,,284,,,,,,284,,,,,,,,,284,,,,,284',
-'284,284,284,,284,284,284,284,,,,,284,284,,,,285,285,285,284,285,284',
-'284,284,285,285,,,,285,,285,285,285,285,285,285,285,,,,,,285,285,285',
-'285,285,285,285,,,285,,,,,,,285,,,285,285,285,285,285,285,285,285,,285',
-'285,285,,285,285,,285,285,285,,,,,,,,,,,,,,,,,,,,285,,,285,,,285,285',
-',,285,,,,,,285,,,,,,,,,285,,,,,285,285,285,285,,285,285,285,285,,,,',
-'285,285,,,,624,624,624,285,624,285,285,285,624,624,,,,624,,624,624,624',
-'624,624,624,624,,,,,,624,624,624,624,624,624,624,,,624,,,,,,,624,,,624',
-'624,624,624,624,624,624,624,624,624,624,624,,624,624,,624,624,624,,',
-',,,,,,,,,,,,,,,,,624,,,624,,,624,624,,,624,,,,624,,624,,,624,,,,,,624',
-',,,,624,624,624,624,,624,624,624,624,,,,,624,624,,,,,,,624,,624,624',
-'624,290,290,290,290,290,,,,290,290,,,,290,,290,290,290,290,290,290,290',
+'116,116,116,,116,116,116,,116,116,,116,116,116,,,,,,,,,,,,,,,,,,,,116',
+',,116,,,116,116,,,116,,,,,,116,,,,,,,,,116,,,,,116,116,116,116,,116',
+'116,116,116,,,,,116,116,,,,117,117,117,116,117,116,116,116,117,117,',
+',,117,,117,117,117,117,117,117,117,,,,,,117,117,117,117,117,117,117',
+',,117,,,,,,,117,,,117,117,117,117,117,117,117,117,,117,117,117,,117',
+'117,,117,117,117,,,,,,,,,,,,,,,,,,,,117,,,117,,,117,117,,,117,,,,,,117',
+',,,,,,,,117,,,,,117,117,117,117,,117,117,117,117,,,,,117,117,,,,118',
+'118,118,117,118,117,117,117,118,118,,,,118,,118,118,118,118,118,118',
+'118,,,,,,118,118,118,118,118,118,118,,,118,,,,,,,118,,,118,118,118,118',
+'118,118,118,118,,118,118,118,,118,118,,118,118,118,,,,,,,,,,,,,,,,,',
+',,118,,,118,,,118,118,,,118,,,,,,118,,,,,,,,,118,,,,,118,118,118,118',
+',118,118,118,118,,,,,118,118,,,,119,119,119,118,119,118,118,118,119',
+'119,,,,119,,119,119,119,119,119,119,119,,,,,,119,119,119,119,119,119',
+'119,,,119,,,,,,,119,,,119,119,119,119,119,119,119,119,,119,119,119,',
+'119,119,,119,119,119,,,,,,,,,,,,,,,,,,,,119,,,119,,,119,119,,,119,,',
+',,,119,,,,,,,,,119,,,,,119,119,119,119,,119,119,119,119,,,,,119,119',
+',,,,,,119,,119,119,119,120,120,120,120,120,,,,120,120,,,,120,,120,120',
+'120,120,120,120,120,,,,,,120,120,120,120,120,120,120,,,120,,,,,,120',
+'120,,120,120,120,120,120,120,120,120,120,,120,120,120,,120,120,,120',
+'120,120,,,,,,,,,,,,,,,,,,,,120,,,120,,,120,120,,,120,,120,,,,120,,,',
+',,,,,120,,,,,120,120,120,120,,120,120,120,120,,,,,120,120,,,,207,207',
+'207,120,207,120,120,120,207,207,,,,207,,207,207,207,207,207,207,207',
+',,,,,207,207,207,207,207,207,207,,,207,,,,,,,207,,,207,207,207,207,207',
+'207,207,207,,207,207,207,,207,207,,207,207,207,,,,,,,,,,,,,,,,,,,,207',
+',,207,,,207,207,,,207,,207,,,,207,,,,,,,,,207,,,,,207,207,207,207,,207',
+'207,207,207,,,,,207,207,,,,208,208,208,207,208,207,207,207,208,208,',
+',,208,,208,208,208,208,208,208,208,,,,,,208,208,208,208,208,208,208',
+',,208,,,,,,,208,,,208,208,208,208,208,208,208,208,,208,208,208,,208',
+'208,,208,208,208,,,,,,,,,,,,,,,,,,,,208,,,208,,,208,208,,,208,,,,,,208',
+',,,,,,,,208,,,,,208,208,208,208,,208,208,208,208,,,,,208,208,,,,209',
+'209,209,208,209,208,208,208,209,209,,,,209,,209,209,209,209,209,209',
+'209,,,,,,209,209,209,209,209,209,209,,,209,,,,,,,209,,,209,209,209,209',
+'209,209,209,209,209,209,209,209,,209,209,,209,209,209,,,,,,,,,,,,,,',
+',,,,,209,,,209,,,209,209,,,209,,209,,209,,209,,,209,,,,,,209,,,,,209',
+'209,209,209,,209,209,209,209,,,,,209,209,,,,212,212,212,209,212,209',
+'209,209,212,212,,,,212,,212,212,212,212,212,212,212,,,,,,212,212,212',
+'212,212,212,212,,,212,,,,,,,212,,,212,212,212,212,212,212,212,212,,212',
+'212,212,,212,212,,212,212,212,,,,,,,,,,,,,,,,,,,,212,,,212,,,212,212',
+',,212,,,,,,212,,,,,,,,,212,,,,,212,212,212,212,,212,212,212,212,,,,',
+'212,212,,,,213,213,213,212,213,212,212,212,213,213,,,,213,,213,213,213',
+'213,213,213,213,,,,,,213,213,213,213,213,213,213,,,213,,,,,,,213,,,213',
+'213,213,213,213,213,213,213,,213,213,213,,213,213,,213,213,213,,,,,',
+',,,,,,,,,,,,,,213,,,213,,,213,213,,,213,,213,,,,213,,,,,,,,,213,,,,',
+'213,213,213,213,,213,213,213,213,,,,,213,213,,,,214,214,214,213,214',
+'213,213,213,214,214,,,,214,,214,214,214,214,214,214,214,,,,,,214,214',
+'214,214,214,214,214,,,214,,,,,,,214,,,214,214,214,214,214,214,214,214',
+',214,214,214,,214,214,,214,214,214,,,,,,,,,,,,,,,,,,,,214,,,214,,,214',
+'214,,,214,,,,,,214,,,,,,,,,214,,,,,214,214,214,214,,214,214,214,214',
+',,,,214,214,,,,215,215,215,214,215,214,214,214,215,215,,,,215,,215,215',
+'215,215,215,215,215,,,,,,215,215,215,215,215,215,215,,,215,,,,,,,215',
+',,215,215,215,215,215,215,215,215,,215,215,215,,215,215,,215,215,215',
+',,,,,,,,,,,,,,,,,,,215,,,215,,,215,215,,,215,,,,,,215,,,,,,,,,215,,',
+',,215,215,215,215,,215,215,215,215,,,,,215,215,,,,216,216,216,215,216',
+'215,215,215,216,216,,,,216,,216,216,216,216,216,216,216,,,,,,216,216',
+'216,216,216,216,216,,,216,,,,,,,216,,,216,216,216,216,216,216,216,216',
+',216,216,216,,216,216,,216,216,216,,,,,,,,,,,,,,,,,,,,216,,,216,,,216',
+'216,,,216,,,,,,216,,,,,,,,,216,,,,,216,216,216,216,,216,216,216,216',
+',,,,216,216,,,,217,217,217,216,217,216,216,216,217,217,,,,217,,217,217',
+'217,217,217,217,217,,,,,,217,217,217,217,217,217,217,,,217,,,,,,,217',
+',,217,217,217,217,217,217,217,217,,217,217,217,,217,217,,217,217,217',
+',,,,,,,,,,,,,,,,,,,217,,,217,,,217,217,,,217,,,,,,217,,,,,,,,,217,,',
+',,217,217,217,217,,217,217,217,217,,,,,217,217,217,,,228,228,228,217',
+'228,217,217,217,228,228,,,,228,,228,228,228,228,228,228,228,,,,,,228',
+'228,228,228,228,228,228,,,228,,,,,,,228,,,228,228,228,228,228,228,228',
+'228,,228,228,228,,228,228,,228,228,228,,,,,,,,,,,,,,,,,,,,228,,,228',
+',,228,228,,,228,,,,,,228,,,,,,,,,228,,,,,228,228,228,228,,228,228,228',
+'228,,,,,228,228,,,,231,231,231,228,231,228,228,228,231,231,,,,231,,231',
+'231,231,231,231,231,231,,,,,,231,231,231,231,231,231,231,,,231,,,,,',
+',231,,,231,231,231,231,231,231,231,231,,231,231,231,,231,231,,231,231',
+'231,,,,,,,,,,,,,,,,,,,,231,,,231,,,231,231,,,231,,,,,,231,,,,,,,,,231',
+',,,,231,231,231,231,,231,231,231,231,,,,,231,231,,,,232,232,232,231',
+'232,231,231,231,232,232,,,,232,,232,232,232,232,232,232,232,,,,,,232',
+'232,232,232,232,232,232,,,232,,,,,,,232,,,232,232,232,232,232,232,232',
+'232,,232,232,232,,232,232,,232,232,232,,,,,,,,,,,,,,,,,,,,232,,,232',
+',,232,232,,,232,,,,,,232,,,,,,,,,232,,,,,232,232,232,232,,232,232,232',
+'232,,,,,232,232,,,,233,233,233,232,233,232,232,232,233,233,,,,233,,233',
+'233,233,233,233,233,233,,,,,,233,233,233,233,233,233,233,,,233,,,,,',
+',233,,,233,233,233,233,233,233,233,233,,233,233,233,,233,233,,233,233',
+'233,,,,,,,,,,,,,,,,,,,,233,,,233,,,233,233,,,233,,,,,,233,,,,,,,,,233',
+',,,,233,233,233,233,,233,233,233,233,,,,,233,233,,,,234,234,234,233',
+'234,233,233,233,234,234,,,,234,,234,234,234,234,234,234,234,,,,,,234',
+'234,234,234,234,234,234,,,234,,,,,,,234,,,234,234,234,234,234,234,234',
+'234,,234,234,234,,234,234,,234,234,234,,,,,,,,,,,,,,,,,,,,234,,,234',
+',,234,234,,,234,,,,,,234,,,,,,,,,234,,,,,234,234,234,234,,234,234,234',
+'234,,,,,234,234,,,,235,235,235,234,235,234,234,234,235,235,,,,235,,235',
+'235,235,235,235,235,235,,,,,,235,235,235,235,235,235,235,,,235,,,,,',
+',235,,,235,235,235,235,235,235,235,235,,235,235,235,,235,235,,235,235',
+'235,,,,,,,,,,,,,,,,,,,,235,,,235,,,235,235,,,235,,,,,,235,,,,,,,,,235',
+',,,,235,235,235,235,,235,235,235,235,,,,,235,235,,,,236,236,236,235',
+'236,235,235,235,236,236,,,,236,,236,236,236,236,236,236,236,,,,,,236',
+'236,236,236,236,236,236,,,236,,,,,,,236,,,236,236,236,236,236,236,236',
+'236,,236,236,236,,236,236,,236,236,236,,,,,,,,,,,,,,,,,,,,236,,,236',
+',,236,236,,,236,,,,,,236,,,,,,,,,236,,,,,236,236,236,236,,236,236,236',
+'236,,,,,236,236,,,,237,237,237,236,237,236,236,236,237,237,,,,237,,237',
+'237,237,237,237,237,237,,,,,,237,237,237,237,237,237,237,,,237,,,,,',
+',237,,,237,237,237,237,237,237,237,237,,237,237,237,,237,237,,237,237',
+'237,,,,,,,,,,,,,,,,,,,,237,,,237,,,237,237,,,237,,,,,,237,,,,,,,,,237',
+',,,,237,237,237,237,,237,237,237,237,,,,,237,237,,,,238,238,238,237',
+'238,237,237,237,238,238,,,,238,,238,238,238,238,238,238,238,,,,,,238',
+'238,238,238,238,238,238,,,238,,,,,,,238,,,238,238,238,238,238,238,238',
+'238,,238,238,238,,238,238,,238,238,238,,,,,,,,,,,,,,,,,,,,238,,,238',
+',,238,238,,,238,,,,,,238,,,,,,,,,238,,,,,238,238,238,238,,238,238,238',
+'238,,,,,238,238,,,,239,239,239,238,239,238,238,238,239,239,,,,239,,239',
+'239,239,239,239,239,239,,,,,,239,239,239,239,239,239,239,,,239,,,,,',
+',239,,,239,239,239,239,239,239,239,239,,239,239,239,,239,239,,239,239',
+'239,,,,,,,,,,,,,,,,,,,,239,,,239,,,239,239,,,239,,,,,,239,,,,,,,,,239',
+',,,,239,239,239,239,,239,239,239,239,,,,,239,239,,,,240,240,240,239',
+'240,239,239,239,240,240,,,,240,,240,240,240,240,240,240,240,,,,,,240',
+'240,240,240,240,240,240,,,240,,,,,,,240,,,240,240,240,240,240,240,240',
+'240,,240,240,240,,240,240,,240,240,240,,,,,,,,,,,,,,,,,,,,240,,,240',
+',,240,240,,,240,,,,,,240,,,,,,,,,240,,,,,240,240,240,240,,240,240,240',
+'240,,,,,240,240,,,,241,241,241,240,241,240,240,240,241,241,,,,241,,241',
+'241,241,241,241,241,241,,,,,,241,241,241,241,241,241,241,,,241,,,,,',
+',241,,,241,241,241,241,241,241,241,241,,241,241,241,,241,241,,241,241',
+'241,,,,,,,,,,,,,,,,,,,,241,,,241,,,241,241,,,241,,,,,,241,,,,,,,,,241',
+',,,,241,241,241,241,,241,241,241,241,,,,,241,241,,,,242,242,242,241',
+'242,241,241,241,242,242,,,,242,,242,242,242,242,242,242,242,,,,,,242',
+'242,242,242,242,242,242,,,242,,,,,,,242,,,242,242,242,242,242,242,242',
+'242,,242,242,242,,242,242,,242,242,242,,,,,,,,,,,,,,,,,,,,242,,,242',
+',,242,242,,,242,,,,,,242,,,,,,,,,242,,,,,242,242,242,242,,242,242,242',
+'242,,,,,242,242,,,,243,243,243,242,243,242,242,242,243,243,,,,243,,243',
+'243,243,243,243,243,243,,,,,,243,243,243,243,243,243,243,,,243,,,,,',
+',243,,,243,243,243,243,243,243,243,243,,243,243,243,,243,243,,243,243',
+'243,,,,,,,,,,,,,,,,,,,,243,,,243,,,243,243,,,243,,,,,,243,,,,,,,,,243',
+',,,,243,243,243,243,,243,243,243,243,,,,,243,243,,,,244,244,244,243',
+'244,243,243,243,244,244,,,,244,,244,244,244,244,244,244,244,,,,,,244',
+'244,244,244,244,244,244,,,244,,,,,,,244,,,244,244,244,244,244,244,244',
+'244,,244,244,244,,244,244,,244,244,244,,,,,,,,,,,,,,,,,,,,244,,,244',
+',,244,244,,,244,,,,,,244,,,,,,,,,244,,,,,244,244,244,244,,244,244,244',
+'244,,,,,244,244,,,,245,245,245,244,245,244,244,244,245,245,,,,245,,245',
+'245,245,245,245,245,245,,,,,,245,245,245,245,245,245,245,,,245,,,,,',
+',245,,,245,245,245,245,245,245,245,245,,245,245,245,,245,245,,245,245',
+'245,,,,,,,,,,,,,,,,,,,,245,,,245,,,245,245,,,245,,,,,,245,,,,,,,,,245',
+',,,,245,245,245,245,,245,245,245,245,,,,,245,245,,,,246,246,246,245',
+'246,245,245,245,246,246,,,,246,,246,246,246,246,246,246,246,,,,,,246',
+'246,246,246,246,246,246,,,246,,,,,,,246,,,246,246,246,246,246,246,246',
+'246,,246,246,246,,246,246,,246,246,246,,,,,,,,,,,,,,,,,,,,246,,,246',
+',,246,246,,,246,,,,,,246,,,,,,,,,246,,,,,246,246,246,246,,246,246,246',
+'246,,,,,246,246,,,,247,247,247,246,247,246,246,246,247,247,,,,247,,247',
+'247,247,247,247,247,247,,,,,,247,247,247,247,247,247,247,,,247,,,,,',
+',247,,,247,247,247,247,247,247,247,247,,247,247,247,,247,247,,247,247',
+'247,,,,,,,,,,,,,,,,,,,,247,,,247,,,247,247,,,247,,,,,,247,,,,,,,,,247',
+',,,,247,247,247,247,,247,247,247,247,,,,,247,247,,,,248,248,248,247',
+'248,247,247,247,248,248,,,,248,,248,248,248,248,248,248,248,,,,,,248',
+'248,248,248,248,248,248,,,248,,,,,,,248,,,248,248,248,248,248,248,248',
+'248,,248,248,248,,248,248,,248,248,248,,,,,,,,,,,,,,,,,,,,248,,,248',
+',,248,248,,,248,,,,,,248,,,,,,,,,248,,,,,248,248,248,248,,248,248,248',
+'248,,,,,248,248,,,,249,249,249,248,249,248,248,248,249,249,,,,249,,249',
+'249,249,249,249,249,249,,,,,,249,249,249,249,249,249,249,,,249,,,,,',
+',249,,,249,249,249,249,249,249,249,249,,249,249,249,,249,249,,249,249',
+'249,,,,,,,,,,,,,,,,,,,,249,,,249,,,249,249,,,249,,,,,,249,,,,,,,,,249',
+',,,,249,249,249,249,,249,249,249,249,,,,,249,249,,,,250,250,250,249',
+'250,249,249,249,250,250,,,,250,,250,250,250,250,250,250,250,,,,,,250',
+'250,250,250,250,250,250,,,250,,,,,,,250,,,250,250,250,250,250,250,250',
+'250,,250,250,250,,250,250,,250,250,250,,,,,,,,,,,,,,,,,,,,250,,,250',
+',,250,250,,,250,,,,,,250,,,,,,,,,250,,,,,250,250,250,250,,250,250,250',
+'250,,,,,250,250,,,,251,251,251,250,251,250,250,250,251,251,,,,251,,251',
+'251,251,251,251,251,251,,,,,,251,251,251,251,251,251,251,,,251,,,,,',
+',251,,,251,251,251,251,251,251,251,251,,251,251,251,,251,251,,251,251',
+'251,,,,,,,,,,,,,,,,,,,,251,,,251,,,251,251,,,251,,,,,,251,,,,,,,,,251',
+',,,,251,251,251,251,,251,251,251,251,,,,,251,251,,,,252,252,252,251',
+'252,251,251,251,252,252,,,,252,,252,252,252,252,252,252,252,,,,,,252',
+'252,252,252,252,252,252,,,252,,,,,,,252,,,252,252,252,252,252,252,252',
+'252,,252,252,252,,252,252,,252,252,252,,,,,,,,,,,,,,,,,,,,252,,,252',
+',,252,252,,,252,,,,,,252,,,,,,,,,252,,,,,252,252,252,252,,252,252,252',
+'252,,,,,252,252,,,,253,253,253,252,253,252,252,252,253,253,,,,253,,253',
+'253,253,253,253,253,253,,,,,,253,253,253,253,253,253,253,,,253,,,,,',
+',253,,,253,253,253,253,253,253,253,253,,253,253,253,,253,253,,253,253',
+'253,,,,,,,,,,,,,,,,,,,,253,,,253,,,253,253,,,253,,,,,,253,,,,,,,,,253',
+',,,,253,253,253,253,,253,253,253,253,,,,,253,253,,,,254,254,254,253',
+'254,253,253,253,254,254,,,,254,,254,254,254,254,254,254,254,,,,,,254',
+'254,254,254,254,254,254,,,254,,,,,,,254,,,254,254,254,254,254,254,254',
+'254,,254,254,254,,254,254,,254,254,254,,,,,,,,,,,,,,,,,,,,254,,,254',
+',,254,254,,,254,,,,,,254,,,,,,,,,254,,,,,254,254,254,254,,254,254,254',
+'254,,,,,254,254,,,,255,255,255,254,255,254,254,254,255,255,,,,255,,255',
+'255,255,255,255,255,255,,,,,,255,255,255,255,255,255,255,,,255,,,,,',
+',255,,,255,255,255,255,255,255,255,255,,255,255,255,,255,255,,255,255',
+'255,,,,,,,,,,,,,,,,,,,,255,,,255,,,255,255,,,255,,,,,,255,,,,,,,,,255',
+',,,,255,255,255,255,,255,255,255,255,,,,,255,255,,,,263,263,263,255',
+'263,255,255,255,263,263,,,,263,,263,263,263,263,263,263,263,,,,,,263',
+'263,263,263,263,263,263,,,263,,,,,,,263,,,263,263,263,263,263,263,263',
+'263,263,263,263,263,,263,263,,263,263,263,,,,,,,,,,,,,,,,,,,,263,,,263',
+',,263,263,,,263,,263,,263,,263,,,263,,,,,,263,,,,,263,263,263,263,,263',
+'263,263,263,,,,,263,263,,,,264,264,264,263,264,263,263,263,264,264,',
+',,264,,264,264,264,264,264,264,264,,,,,,264,264,264,264,264,264,264',
+',,264,,,,,,,264,,,264,264,264,264,264,264,264,264,264,264,264,264,,264',
+'264,,264,264,264,,,,,,,,,,,,,,,,,,,,264,,,264,,,264,264,,,264,,264,',
+'264,,264,,,264,,,,,,264,,,,,264,264,264,264,,264,264,264,264,,,,,264',
+'264,,,,272,272,272,264,272,264,264,264,272,272,,,,272,,272,272,272,272',
+'272,272,272,,,,,,272,272,272,272,272,272,272,,,272,,,,,,,272,,,272,272',
+'272,272,272,272,272,272,272,272,272,272,,272,272,,272,272,272,,,,,,',
+',,,,,,,,,,,,,272,,,272,,,272,272,,,272,,272,,272,,272,,,272,,,,,,272',
+',,,,272,272,272,272,,272,272,272,272,,,,,272,272,272,,,279,279,279,272',
+'279,272,272,272,279,279,,,,279,,279,279,279,279,279,279,279,,,,,,279',
+'279,279,279,279,279,279,,,279,,,,,,,279,,,279,279,279,279,279,279,279',
+'279,,279,279,279,,279,279,,279,279,279,,,,,,,,,,,,,,,,,,,,279,,,279',
+',,279,279,,,279,,,,,,279,,,,,,,,,279,,,,,279,279,279,279,,279,279,279',
+'279,,,,,279,279,,,,281,281,281,279,281,279,279,279,281,281,,,,281,,281',
+'281,281,281,281,281,281,,,,,,281,281,281,281,281,281,281,,,281,,,,,',
+',281,,,281,281,281,281,281,281,281,281,,281,281,281,,281,281,,281,281',
+'281,,,,,,,,,,,,,,,,,,,,281,,,281,,,281,281,,,281,,,,,,281,,,,,,,,,281',
+',,,,281,281,281,281,,281,281,281,281,,,,,281,281,,,,284,284,284,281',
+'284,281,281,281,284,284,,,,284,,284,284,284,284,284,284,284,,,,,,284',
+'284,284,284,284,284,284,,,284,,,,,,,284,,,284,284,284,284,284,284,284',
+'284,,284,284,284,,284,284,,284,284,284,,,,,,,,,,,,,,,,,,,,284,,,284',
+',,284,284,,,284,,,,,,284,,,,,,,,,284,,,,,284,284,284,284,,284,284,284',
+'284,,,,,284,284,,,,285,285,285,284,285,284,284,284,285,285,,,,285,,285',
+'285,285,285,285,285,285,,,,,,285,285,285,285,285,285,285,,,285,,,,,',
+',285,,,285,285,285,285,285,285,285,285,,285,285,285,,285,285,,285,285',
+'285,,,,,,,,,,,,,,,,,,,,285,,,285,,,285,285,,,285,,,,,,285,,,,,,,,,285',
+',,,,285,285,285,285,,285,285,285,285,,,,,285,285,,,,,,,285,,285,285',
+'285,290,290,290,290,290,,,,290,290,,,,290,,290,290,290,290,290,290,290',
',,,,,290,290,290,290,290,290,290,,,290,,,,,,290,290,,290,290,290,290',
'290,290,290,290,290,,290,290,290,,290,290,,290,290,290,,,,,,,,,,,,,',
',,,,,,290,,,290,,,290,290,,,290,,290,,,,290,,,,,,,,,290,,,,,290,290',
-'290,290,,290,290,290,290,,,,,290,290,,,,623,623,623,290,623,290,290',
-'290,623,623,,,,623,,623,623,623,623,623,623,623,,,,,,623,623,623,623',
-'623,623,623,,,623,,,,,,,623,,,623,623,623,623,623,623,623,623,623,623',
-'623,623,,623,623,,623,623,623,,,,,,,,,,,,,,,,,,,,623,,,623,,,623,623',
-',,623,,623,,623,,623,,,623,,,,,,623,,,,,623,623,623,623,,623,623,623',
-'623,,,,,623,623,,,,620,620,620,623,620,623,623,623,620,620,,,,620,,620',
-'620,620,620,620,620,620,,,,,,620,620,620,620,620,620,620,,,620,,,,,',
-',620,,,620,620,620,620,620,620,620,620,,620,620,620,,620,620,,620,620',
-'620,,,,,,,,,,,,,,,,,,,,620,,,620,,,620,620,,,620,,,,,,620,,,,,,,,,620',
-',,,,620,620,620,620,,620,620,620,620,,,,,620,620,,,,619,619,619,620',
-'619,620,620,620,619,619,,,,619,,619,619,619,619,619,619,619,,,,,,619',
-'619,619,619,619,619,619,,,619,,,,,,,619,,,619,619,619,619,619,619,619',
-'619,,619,619,619,,619,619,,619,619,619,,,,,,,,,,,,,,,,,,,,619,,,619',
-',,619,619,,,619,,619,,,,619,,,,,,,,,619,,,,,619,619,619,619,,619,619',
-'619,619,,,,,619,619,,,,585,585,585,619,585,619,619,619,585,585,,,,585',
-',585,585,585,585,585,585,585,,,,,,585,585,585,585,585,585,585,,,585',
-',,,,,,585,,,585,585,585,585,585,585,585,585,585,585,585,585,,585,585',
-',585,585,585,,,,,,,,,,,,,,,,,,,,585,,,585,,,585,585,,,585,,585,,585',
-',585,,,585,,,,,,585,,,,,585,585,585,585,,585,585,585,585,,,,,585,585',
-',,,575,575,575,585,575,585,585,585,575,575,,,,575,,575,575,575,575,575',
-'575,575,,,,,,575,575,575,575,575,575,575,,,575,,,,,,,575,,,575,575,575',
-'575,575,575,575,575,575,575,575,575,,575,575,,575,575,575,,,,,,,,,,',
-',,,,,,,,,575,,,575,,,575,575,,,575,,575,,575,,575,,,575,,,,,,575,,,',
-',575,575,575,575,,575,575,575,575,,,,,575,575,,,,298,298,298,575,298',
-'575,575,575,298,298,,,,298,,298,298,298,298,298,298,298,,,,,,298,298',
-'298,298,298,298,298,,,298,,,,,,,298,,,298,298,298,298,298,298,298,298',
-',298,298,298,,298,298,,,,298,,,,,,,,,,,,,,,,,,,,298,,,298,,,298,298',
-',,298,,897,,897,897,897,897,897,,,,,,,,,,897,,298,298,298,298,,298,298',
-'298,298,,,,,298,298,,,,298,,897,298,,298,298,298,574,574,574,,574,897',
-'897,,574,574,897,,,574,,574,574,574,574,574,574,574,,,,,,574,574,574',
-'574,574,574,574,,,574,,,,,,,574,,,574,574,574,574,574,574,574,574,,574',
-'574,574,,574,574,,574,574,574,,,,,,,,,,,,,,,,,,,,574,,,574,,,574,574',
-',,574,,574,,,,574,,,,,,,,,574,,,,,574,574,574,574,,574,574,574,574,',
-',,,574,574,,,,554,554,554,574,554,574,574,574,554,554,,,,554,,554,554',
-'554,554,554,554,554,,,,,,554,554,554,554,554,554,554,,,554,,,,,,,554',
-',,554,554,554,554,554,554,554,554,,554,554,554,,554,554,,554,554,554',
-',,,,,,,,,,,,,,,,,,,554,,,554,,,554,554,,,554,,,,,,554,,,,,,,,,554,,',
-',,554,554,554,554,,554,554,554,554,,,,,554,554,,,,529,529,529,554,529',
-'554,554,554,529,529,,,,529,,529,529,529,529,529,529,529,,,,,,529,529',
-'529,529,529,529,529,,,529,,,,,,,529,,,529,529,529,529,529,529,529,529',
-'529,529,529,529,,529,529,,529,529,529,,,,,,,,,,,,,,,,,,,,529,,,529,',
-',529,529,,,529,,,,,,529,,,529,,,,,,529,,,,,529,529,529,529,,529,529',
-'529,529,,,,,529,529,,,,526,526,526,529,526,529,529,529,526,526,,,,526',
-',526,526,526,526,526,526,526,,,,,,526,526,526,526,526,526,526,,,526',
-',,,,,,526,,,526,526,526,526,526,526,526,526,526,526,526,526,,526,526',
-',526,526,526,,,,,,,,,,,,,,,,,,,,526,,,526,,,526,526,,,526,,526,,,,526',
-',,526,,,,,,526,,,,,526,526,526,526,,526,526,526,526,,,,,526,526,,,,520',
-'520,520,526,520,526,526,526,520,520,,,,520,,520,520,520,520,520,520',
-'520,,,,,,520,520,520,520,520,520,520,,,520,,,,,,,520,,,520,520,520,520',
-'520,520,520,520,,520,520,520,,520,520,,520,520,520,,,,,,,,,,,,,,,,,',
-',,520,,,520,,,520,520,,,520,,,,,,520,,,,,,,,,520,,,,,520,520,520,520',
-',520,520,520,520,,,,,520,520,,,,516,516,516,520,516,520,520,520,516',
-'516,,,,516,,516,516,516,516,516,516,516,,,,,,516,516,516,516,516,516',
-'516,,,516,,,,,,,516,,,516,516,516,516,516,516,516,516,,516,516,516,',
-'516,516,,516,516,516,,,,,,,,,,,,,,,,,,,,516,,,516,,,516,516,,,516,,',
-',,,516,,,,,,,,,516,,,,,516,516,516,516,,516,516,516,516,,,,,516,516',
-',,,515,515,515,516,515,516,516,516,515,515,,,,515,,515,515,515,515,515',
-'515,515,,,,,,515,515,515,515,515,515,515,,,515,,,,,,,515,,,515,515,515',
-'515,515,515,515,515,,515,515,515,,515,515,,515,515,515,,,,,,,,,,,,,',
-',,,,,,515,,,515,,,515,515,,,515,,,,,,515,,,,,,,,,515,,,,,515,515,515',
-'515,,515,515,515,515,,,,,515,515,,,,512,512,512,515,512,515,515,515',
-'512,512,,,,512,,512,512,512,512,512,512,512,,,,,,512,512,512,512,512',
-'512,512,,,512,,,,,,,512,,,512,512,512,512,512,512,512,512,,512,512,512',
-',512,512,,,,512,,,,,,,,,,,,,,,,,,,,512,,,512,,,512,512,,,512,,,,,,,',
-',,,,,,,,,,,,512,512,512,512,,512,512,512,512,,,,,512,512,,,,506,506',
-'506,512,506,512,512,512,506,506,,,,506,,506,506,506,506,506,506,506',
-',,,,,506,506,506,506,506,506,506,,,506,,,,,,,506,,,506,506,506,506,506',
-'506,506,506,506,506,506,506,,506,506,,506,506,506,,,,,,,,,,,,,,,,,,',
-',506,,,506,,,506,506,,,506,,506,,506,,506,,,506,,,,,,506,,,,,506,506',
-'506,506,,506,506,506,506,,,,,506,506,,,,315,315,315,506,315,506,506',
-'506,315,315,,,,315,,315,315,315,315,315,315,315,,,,,,315,315,315,315',
-'315,315,315,,,315,,,,,,,315,,,315,315,315,315,315,315,315,315,,315,315',
-'315,,315,315,,,,315,,,,,,,,,,,,,,,,,,,,315,,,315,,,315,315,,,315,,,',
-',,,,,,,,,,,,,,,,315,315,315,315,,315,315,315,315,,,,,315,315,,,,504',
-'504,504,315,504,315,315,315,504,504,,,,504,,504,504,504,504,504,504',
-'504,,,,,,504,504,504,504,504,504,504,,,504,,,,,,,504,,,504,504,504,504',
-'504,504,504,504,,504,504,504,,504,504,,,,504,,,,,,,,,,,,,,,,,,,,504',
-',,504,,,504,504,,,504,,989,,989,989,989,989,989,,,,,,,,,,989,,504,504',
-'504,504,,504,504,504,504,,,,,504,504,,,,,,989,504,,504,504,504,496,496',
-'496,496,496,989,989,,496,496,989,,,496,,496,496,496,496,496,496,496',
-',,,,,496,496,496,496,496,496,496,,,496,,,,,,496,496,496,496,496,496',
-'496,496,496,496,496,496,,496,496,496,,496,496,,496,496,496,,,,,,,,,',
-',,,,,,,,,,496,,,496,,,496,496,,,496,,496,,,,496,,,,,,,,,496,,,,,496',
-'496,496,496,,496,496,496,496,,,,,496,496,,,,,,496,496,,496,496,496,490',
-'490,490,,490,,,,490,490,,,,490,,490,490,490,490,490,490,490,,,,,,490',
-'490,490,490,490,490,490,,,490,,,,,,,490,,,490,490,490,490,490,490,490',
-'490,,490,490,490,,490,490,,490,490,490,,,,,,,,,,,,,,,,,,,,490,,,490',
-',,490,490,,,490,,,,,,490,,,,,,,,,490,,,,,490,490,490,490,,490,490,490',
-'490,,,,,490,490,,,,323,323,323,490,323,490,490,490,323,323,,,,323,,323',
-'323,323,323,323,323,323,,,,,,323,323,323,323,323,323,323,,,323,,,,,',
-',323,,,323,323,323,323,323,323,323,323,,323,323,323,,323,323,,323,323',
-'323,,,,,,,,,,,,,,,,,,,,323,,,323,323,,323,323,,,323,,,,,,323,,,,,,,',
-',323,,,,,323,323,323,323,,323,323,323,323,,,,,323,323,,,,325,325,325',
-'323,325,323,323,323,325,325,,,,325,,325,325,325,325,325,325,325,,,,',
-',325,325,325,325,325,325,325,,,325,,,,,,,325,,,325,325,325,325,325,325',
-'325,325,,325,325,325,,325,325,,325,325,325,,,,,,,,,,,,,,,,,,,,325,,',
-'325,,,325,325,,,325,,,,,,325,,,,,,,,,325,,,,,325,325,325,325,,325,325',
-'325,325,,,,,325,325,,,,488,488,488,325,488,325,325,325,488,488,,,,488',
-',488,488,488,488,488,488,488,,,,,,488,488,488,488,488,488,488,,,488',
-',,,,,,488,,,488,488,488,488,488,488,488,488,488,488,488,488,,488,488',
-',488,488,488,,,,,,,,,,,,,,,,,,,,488,,,488,,,488,488,,,488,,,,488,,488',
-',,488,,,,,,488,,,,,488,488,488,488,,488,488,488,488,,,,,488,488,,,,486',
-'486,486,488,486,488,488,488,486,486,,,,486,,486,486,486,486,486,486',
-'486,,,,,,486,486,486,486,486,486,486,,,486,,,,,,,486,,,486,486,486,486',
-'486,486,486,486,486,486,486,486,,486,486,,486,486,486,,,,,,,,,,,,,,',
-',,,,,486,,,486,,,486,486,,,486,,486,,486,,486,,,486,,,,,,486,,,,,486',
-'486,486,486,,486,486,486,486,,,,,486,486,,,,472,472,472,486,472,486',
-'486,486,472,472,,,,472,,472,472,472,472,472,472,472,,,,,,472,472,472',
-'472,472,472,472,,,472,,,,,,,472,,,472,472,472,472,472,472,472,472,,472',
-'472,472,,472,472,,472,472,472,,,,,,,,,,,,,,,,,,,,472,,,472,,,472,472',
-',,472,,,,,,472,,,,,,,,,472,,,,,472,472,472,472,,472,472,472,472,,,,',
-'472,472,,,,446,446,446,472,446,472,472,472,446,446,,,,446,,446,446,446',
-'446,446,446,446,,,,,,446,446,446,446,446,446,446,,,446,,,,,,,446,,,446',
-'446,446,446,446,446,446,446,,446,446,446,,446,446,,446,446,446,,,,,',
-',,,,,,,,,,,,,,446,,,446,,,446,446,,,446,,,,,,446,,,,,,,,,446,,,,,446',
-'446,446,446,,446,446,446,446,,,,,446,446,,,,445,445,445,446,445,446',
-'446,446,445,445,,,,445,,445,445,445,445,445,445,445,,,,,,445,445,445',
-'445,445,445,445,,,445,,,,,,,445,,,445,445,445,445,445,445,445,445,,445',
-'445,445,,445,445,,445,445,445,,,,,,,,,,,,,,,,,,,,445,,,445,,,445,445',
-',,445,,,,,,445,,,,,,,,,445,,,,,445,445,445,445,,445,445,445,445,,,,',
-'445,445,,,,444,444,444,445,444,445,445,445,444,444,,,,444,,444,444,444',
-'444,444,444,444,,,,,,444,444,444,444,444,444,444,,,444,,,,,,,444,,,444',
-'444,444,444,444,444,444,444,,444,444,444,,444,444,,444,444,444,,,,,',
-',,,,,,,,,,,,,,444,,,444,,,444,444,,,444,,,,,,444,,,,,,,,,444,,,,,444',
-'444,444,444,,444,444,444,444,,,,,444,444,,,,442,442,442,444,442,444',
-'444,444,442,442,,,,442,,442,442,442,442,442,442,442,,,,,,442,442,442',
-'442,442,442,442,,,442,,,,,,,442,,,442,442,442,442,442,442,442,442,442',
-'442,442,442,,442,442,,442,442,442,,,,,,,,,,,,,,,,,,,,442,,,442,,,442',
-'442,,,442,,442,,442,,442,,,442,,,,,,442,,,,,442,442,442,442,,442,442',
-'442,442,,,,,442,442,,,,404,404,404,442,404,442,442,442,404,404,,,,404',
-',404,404,404,404,404,404,404,,,,,,404,404,404,404,404,404,404,,,404',
-',,,,,,404,,,404,404,404,404,404,404,404,404,,404,404,404,,404,404,,404',
-'404,404,,,,,,,,,,,,,,,,,,,,404,,,404,,,404,404,,,404,,,,,,404,,,,,,',
-',,404,,,,,404,404,404,404,,404,404,404,404,,,,,404,404,,,,340,340,340',
-'404,340,404,404,404,340,340,,,,340,,340,340,340,340,340,340,340,,,,',
-',340,340,340,340,340,340,340,,,340,,,,,,,340,,,340,340,340,340,340,340',
-'340,340,,340,340,340,,340,340,,340,340,340,,,,,,,,,,,,,,,,,,,,340,,',
-'340,,,340,340,,,340,,,,,,340,,,,,,,,,340,,,,,340,340,340,340,,340,340',
-'340,340,,,,,340,340,,,,376,376,376,340,376,340,340,340,376,376,,,,376',
-',376,376,376,376,376,376,376,,,,,,376,376,376,376,376,376,376,,,376',
-',,,,,,376,,,376,376,376,376,376,376,376,376,,376,376,376,,376,376,,376',
-'376,376,,,,,,,,,,,,,,,,,,,,376,,,376,,,376,376,,,376,,,,,,376,,,,,,',
-',,376,,,,,376,376,376,376,,376,376,376,376,,,,,376,376,,,,341,341,341',
-'376,341,376,376,376,341,341,,,,341,,341,341,341,341,341,341,341,,,,',
-',341,341,341,341,341,341,341,,,341,,,,,,,341,,,341,341,341,341,341,341',
-'341,341,,341,341,341,,341,341,,341,341,341,,,,,,,,,,,,,,,,,,,,341,,',
-'341,,,341,341,,,341,,,,,,341,,,,,,,,,341,,,,,341,341,341,341,,341,341',
-'341,341,,,,,341,341,,,,360,360,360,341,360,341,341,341,360,360,,,,360',
-',360,360,360,360,360,360,360,,,,,,360,360,360,360,360,360,360,,,360',
-',,,,,,360,,,360,360,360,360,360,360,360,360,,360,360,360,,360,360,,360',
-'360,360,,,,,,,,,,,,,,,,,,,,360,,,360,,,360,360,,,360,,,,,,360,,,,,,',
-',,360,,,,,360,360,360,360,,360,360,360,360,,,,,360,360,,,,,,,360,,360',
-'360,360,5,5,5,5,5,,,,5,5,,,,5,,5,5,5,5,5,5,5,,,,,,5,5,5,5,5,5,5,,,5',
-',,,,,5,5,5,5,5,5,5,5,5,5,5,5,,5,5,5,,5,5,,5,5,5,,,,,,,,,,,,,,,,,,,,5',
-',,5,,,5,5,,,5,,5,,,,5,,,,,,,,,5,,,,,5,5,5,5,,5,5,5,5,,,,,5,5,,,,923',
-'923,923,5,923,5,5,5,923,923,,,,923,,923,923,923,923,923,923,923,,,,',
-',923,923,923,923,923,923,923,,,923,,,,,,,923,,,923,923,923,923,923,923',
-'923,923,,923,923,923,,923,923,,923,923,923,,,,,,,,,,,,,,,,,,,,923,,',
-'923,,,923,923,,,923,,,,,,923,,,,,,,,,923,,,,,923,923,923,923,,923,923',
-'923,923,,,,,923,923,,,,886,886,886,923,886,923,923,923,886,886,,,,886',
-',886,886,886,886,886,886,886,,,,,,886,886,886,886,886,886,886,,,886',
-',,,,,,886,,,886,886,886,886,886,886,886,886,,886,886,886,,886,886,,',
-',886,,,,,,,,,,,,,,,,,,,,886,,,886,,,886,886,,,886,,,,,,,,,,,,,,,,,,',
-',886,886,886,886,,886,886,886,886,,,,,886,886,,,,874,874,874,886,874',
-'886,886,886,874,874,,,,874,,874,874,874,874,874,874,874,,,,,,874,874',
-'874,874,874,874,874,,,874,,,,,,,874,,,874,874,874,874,874,874,874,874',
-',874,874,874,,874,874,,,,874,,,,,,,,,,,,,,,,,,,,874,,,874,,,874,874',
-',,874,,,,,,,,,,,,,,,,,,,,874,874,874,874,,874,874,874,874,,,,,874,874',
-',,,860,860,860,874,860,874,874,874,860,860,,,,860,,860,860,860,860,860',
-'860,860,,,,,,860,860,860,860,860,860,860,,,860,,,,,,,860,,,860,860,860',
-'860,860,860,860,860,,860,860,860,,860,860,,860,860,860,,,,,,,,,,,,,',
-',,,,,,860,,,860,,,860,860,,,860,,,,,,860,,,,,,,,,860,,,,,860,860,860',
-'860,,860,860,860,860,,,,,860,860,,,,859,859,859,860,859,860,860,860',
-'859,859,,,,859,,859,859,859,859,859,859,859,,,,,,859,859,859,859,859',
-'859,859,,,859,,,,,,,859,,,859,859,859,859,859,859,859,859,859,859,859',
-'859,,859,859,,859,859,859,,,,,,,,,,,,,,,,,,,,859,,,859,,,859,859,,,859',
-',,,859,,859,,,859,,,,,,859,,,,,859,859,859,859,,859,859,859,859,,,,',
-'859,859,,,,842,842,842,859,842,859,859,859,842,842,,,,842,,842,842,842',
-'842,842,842,842,,,,,,842,842,842,842,842,842,842,,,842,,,,,,,842,,,842',
-'842,842,842,842,842,842,842,,842,842,842,,842,842,,842,842,842,,,,,',
-',,,,,,,,,,,,,,842,,,842,,,842,842,,,842,,842,,,,842,,,,,,,,,842,,,,',
-'842,842,842,842,,842,842,842,842,,,,,842,842,,,,20,20,20,842,20,842',
-'842,842,20,20,,,,20,,20,20,20,20,20,20,20,,,,,,20,20,20,20,20,20,20',
-',,20,,,,,,,20,,,20,20,20,20,20,20,20,20,,20,20,20,,20,20,,20,20,20,',
-',,,,,,,,,,,,,,,,,,20,,,20,,,20,20,,,20,,,,,,20,,,,,,,,,20,,,,,20,20',
-'20,20,,20,20,20,20,,,,,20,20,,,,837,837,837,20,837,20,20,20,837,837',
-',,,837,,837,837,837,837,837,837,837,,,,,,837,837,837,837,837,837,837',
-',,837,,,,,,,837,,,837,837,837,837,837,837,837,837,,837,837,837,,837',
-'837,,837,837,837,,,,,,,,,,,,,,,,,,,,837,,,837,,,837,837,,,837,,,,,,837',
-',,,,,,,,837,,,,,837,837,837,837,,837,837,837,837,,,,,837,837,,,,29,29',
-'29,837,29,837,837,837,29,29,,,,29,,29,29,29,29,29,29,29,,,,,,29,29,29',
-'29,29,29,29,,,29,,,,,,,29,,,29,29,29,29,29,29,29,29,29,29,29,29,,29',
-'29,,29,29,29,,,,,,,,,,,,,,,,,,,,29,,,29,,,29,29,,,29,,29,,29,,29,,,29',
-',,,,,29,,,,,29,29,29,29,,29,29,29,29,,,,,29,29,,,,30,30,30,29,30,29',
-'29,29,30,30,,,,30,,30,30,30,30,30,30,30,,,,,,30,30,30,30,30,30,30,,',
-'30,,,,,,,30,,,30,30,30,30,30,30,30,30,30,30,30,30,,30,30,,30,30,30,',
-',,,,,,,,,,,,,,,,,,30,,,30,,,30,30,,,30,,30,,30,,30,,,30,,,,,,30,,,,',
-'30,30,30,30,,30,30,30,30,,,,,30,30,,,,31,31,31,30,31,30,30,30,31,31',
-',,,31,,31,31,31,31,31,31,31,,,,,,31,31,31,31,31,31,31,,,31,,,,,,,31',
-',,31,31,31,31,31,31,31,31,31,31,31,31,,31,31,,31,31,31,,,,,,,,,,,,,',
-',,,,,,31,,,31,,,31,31,,,31,,31,,31,,31,,,31,,,,,,31,,,,,31,31,31,31',
-',31,31,31,31,,,,,31,31,,,,34,34,34,31,34,31,31,31,34,34,,,,34,,34,34',
-'34,34,34,34,34,,,,,,34,34,34,34,34,34,34,,,34,,,,,,,34,,,34,34,34,34',
-'34,34,34,34,,34,34,34,,34,34,,,,34,,,,,,,,,,,,,,,,,,,,34,,,34,,,34,34',
-',,34,,34,,,,,,,,,,,,,,,,,,34,34,34,34,,34,34,34,34,,,,,34,34,,,,35,35',
-'35,34,35,34,34,34,35,35,,,,35,,35,35,35,35,35,35,35,,,,,,35,35,35,35',
-'35,35,35,,,35,,,,,,,35,,,35,35,35,35,35,35,35,35,,35,35,35,,35,35,,',
-',35,,,,,,,,,,,,,,,,,,,,35,,,35,,,35,35,,,35,,1015,,1015,1015,1015,1015',
-'1015,,,,,,,,,,1015,,35,35,35,35,,35,35,35,35,,,,,35,35,,,,35,,1015,35',
-',35,35,35,787,787,787,,787,1015,1015,,787,787,1015,,,787,,787,787,787',
-'787,787,787,787,,,,,,787,787,787,787,787,787,787,,,787,,,,,,,787,,,787',
-'787,787,787,787,787,787,787,,787,787,787,,787,787,,,,787,,,,,,,,,,,',
-',,,,,,,,787,,,787,,,787,787,,,787,,,,,,,,,,,,,,,,,,,,787,787,787,787',
-',787,787,787,787,,,,,787,787,,,,773,773,773,787,773,787,787,787,773',
-'773,,,,773,,773,773,773,773,773,773,773,,,,,,773,773,773,773,773,773',
-'773,,,773,,,,,,,773,,,773,773,773,773,773,773,773,773,,773,773,773,',
-'773,773,,773,773,773,,,,,,,,,,,,,,,,,,,,773,,,773,,,773,773,,,773,,',
-',,,773,,,,,,,,,773,,,,,773,773,773,773,,773,773,773,773,,,,,773,773',
-',,,772,772,772,773,772,773,773,773,772,772,,,,772,,772,772,772,772,772',
-'772,772,,,,,,772,772,772,772,772,772,772,,,772,,,,,,,772,,,772,772,772',
-'772,772,772,772,772,,772,772,772,,772,772,,772,772,772,,,,,,,,,,,,,',
-',,,,,,772,,,772,,,772,772,,,772,,,,,,772,,,,,,,,,772,,,,,772,772,772',
-'772,,772,772,772,772,,,,,772,772,,,,771,771,771,772,771,772,772,772',
-'771,771,,,,771,,771,771,771,771,771,771,771,,,,,,771,771,771,771,771',
-'771,771,,,771,,,,,,,771,,,771,771,771,771,771,771,771,771,,771,771,771',
-',771,771,,771,771,771,,,,,,,,,,,,,,,,,,,,771,,,771,,,771,771,,,771,',
-',,,,771,,,,,,,,,771,,,,,771,771,771,771,,771,771,771,771,,,,,771,771',
-',,,42,42,42,771,42,771,771,771,42,42,,,,42,,42,42,42,42,42,42,42,,,',
-',,42,42,42,42,42,42,42,,,42,,,,,,,42,,,42,42,42,42,42,42,42,42,,42,42',
-'42,,42,42,,42,42,42,,,,,,,,,,,,,,,,,,,,42,,,42,,,42,42,,,42,,,,,,42',
-',,,,,,,,42,,,,,42,42,42,42,,42,42,42,42,,,,,42,42,,,,43,43,43,42,43',
-'42,42,42,43,43,,,,43,,43,43,43,43,43,43,43,,,,,,43,43,43,43,43,43,43',
-',,43,,,,,,,43,,,43,43,43,43,43,43,43,43,,43,43,43,,43,43,,43,43,43,',
-',,,,,,,,,,,,,,,,,,43,,,43,,,43,43,,,43,,,,,,43,,,,,,,,,43,,,,,43,43',
-'43,43,,43,43,43,43,,,,,43,43,,,,44,44,44,43,44,43,43,43,44,44,,,,44',
-',44,44,44,44,44,44,44,,,,,,44,44,44,44,44,44,44,,,44,,,,,,,44,,,44,44',
-'44,44,44,44,44,44,,44,44,44,,44,44,,44,44,44,,,,,,,,,,,,,,,,,,,,44,',
-',44,,,44,44,,,44,,,,,,44,,,,,,,,,44,,,,,44,44,44,44,,44,44,44,44,,,',
-',44,44,,,,770,770,770,44,770,44,44,44,770,770,,,,770,,770,770,770,770',
-'770,770,770,,,,,,770,770,770,770,770,770,770,,,770,,,,,,,770,,,770,770',
-'770,770,770,770,770,770,,770,770,770,,770,770,,770,770,770,,,,,,,,,',
-',,,,,,,,,,770,,,770,,,770,770,,,770,,,,,,770,,,,,,,,,770,,,,,770,770',
-'770,770,,770,770,770,770,,,,,770,770,,,,756,756,756,770,756,770,770',
-'770,756,756,,,,756,,756,756,756,756,756,756,756,,,,,,756,756,756,756',
-'756,756,756,,,756,,,,,,,756,,,756,756,756,756,756,756,756,756,,756,756',
-'756,,756,756,,756,756,756,,,,,,,,,,,,,,,,,,,,756,,,756,,,756,756,,,756',
-',,,,,756,,,,,,,,,756,,,,,756,756,756,756,,756,756,756,756,,,,,756,756',
-',,,985,985,985,756,985,756,756,756,985,985,,,,985,,985,985,985,985,985',
-'985,985,,,,,,985,985,985,985,985,985,985,,,985,,,,,,,985,,,985,985,985',
-'985,985,985,985,985,985,985,985,985,,985,985,,985,985,985,,,,,,,,,,',
-',,,,,,,,,985,,,985,,,985,985,,,985,,985,,985,,985,,,985,,,,,,985,,,',
-',985,985,985,985,,985,985,985,985,,,,,985,985,,,,754,754,754,985,754',
-'985,985,985,754,754,,,,754,,754,754,754,754,754,754,754,,,,,,754,754',
+'290,290,,290,290,290,290,,,,,290,290,,,,298,298,298,290,298,290,290',
+'290,298,298,,,,298,,298,298,298,298,298,298,298,,,,,,298,298,298,298',
+'298,298,298,,,298,,,,,,,298,,,298,298,298,298,298,298,298,298,,298,298',
+'298,,298,298,,,,298,,,,,,,,,,,,,,,,,,,,298,,,298,,,298,298,,,298,,895',
+',895,895,895,895,895,,,,,,,,,,895,,298,298,298,298,,298,298,298,298',
+',,,,298,298,,,,298,,895,298,,298,298,298,315,315,315,,315,895,895,,315',
+'315,895,,,315,,315,315,315,315,315,315,315,,,,,,315,315,315,315,315',
+'315,315,,,315,,,,,,,315,,,315,315,315,315,315,315,315,315,,315,315,315',
+',315,315,,,,315,,,,,,,,,,,,,,,,,,,,315,,,315,,,315,315,,,315,,,,,,,',
+',,,,,,,,,,,,315,315,315,315,,315,315,315,315,,,,,315,315,,,,323,323',
+'323,315,323,315,315,315,323,323,,,,323,,323,323,323,323,323,323,323',
+',,,,,323,323,323,323,323,323,323,,,323,,,,,,,323,,,323,323,323,323,323',
+'323,323,323,,323,323,323,,323,323,,323,323,323,,,,,,,,,,,,,,,,,,,,323',
+',,323,323,,323,323,,,323,,,,,,323,,,,,,,,,323,,,,,323,323,323,323,,323',
+'323,323,323,,,,,323,323,,,,325,325,325,323,325,323,323,323,325,325,',
+',,325,,325,325,325,325,325,325,325,,,,,,325,325,325,325,325,325,325',
+',,325,,,,,,,325,,,325,325,325,325,325,325,325,325,,325,325,325,,325',
+'325,,325,325,325,,,,,,,,,,,,,,,,,,,,325,,,325,,,325,325,,,325,,,,,,325',
+',,,,,,,,325,,,,,325,325,325,325,,325,325,325,325,,,,,325,325,,,,340',
+'340,340,325,340,325,325,325,340,340,,,,340,,340,340,340,340,340,340',
+'340,,,,,,340,340,340,340,340,340,340,,,340,,,,,,,340,,,340,340,340,340',
+'340,340,340,340,,340,340,340,,340,340,,340,340,340,,,,,,,,,,,,,,,,,',
+',,340,,,340,,,340,340,,,340,,,,,,340,,,,,,,,,340,,,,,340,340,340,340',
+',340,340,340,340,,,,,340,340,,,,341,341,341,340,341,340,340,340,341',
+'341,,,,341,,341,341,341,341,341,341,341,,,,,,341,341,341,341,341,341',
+'341,,,341,,,,,,,341,,,341,341,341,341,341,341,341,341,,341,341,341,',
+'341,341,,341,341,341,,,,,,,,,,,,,,,,,,,,341,,,341,,,341,341,,,341,,',
+',,,341,,,,,,,,,341,,,,,341,341,341,341,,341,341,341,341,,,,,341,341',
+',,,360,360,360,341,360,341,341,341,360,360,,,,360,,360,360,360,360,360',
+'360,360,,,,,,360,360,360,360,360,360,360,,,360,,,,,,,360,,,360,360,360',
+'360,360,360,360,360,,360,360,360,,360,360,,360,360,360,,,,,,,,,,,,,',
+',,,,,,360,,,360,,,360,360,,,360,,,,,,360,,,,,,,,,360,,,,,360,360,360',
+'360,,360,360,360,360,,,,,360,360,,,,376,376,376,360,376,360,360,360',
+'376,376,,,,376,,376,376,376,376,376,376,376,,,,,,376,376,376,376,376',
+'376,376,,,376,,,,,,,376,,,376,376,376,376,376,376,376,376,,376,376,376',
+',376,376,,376,376,376,,,,,,,,,,,,,,,,,,,,376,,,376,,,376,376,,,376,',
+',,,,376,,,,,,,,,376,,,,,376,376,376,376,,376,376,376,376,,,,,376,376',
+',,,404,404,404,376,404,376,376,376,404,404,,,,404,,404,404,404,404,404',
+'404,404,,,,,,404,404,404,404,404,404,404,,,404,,,,,,,404,,,404,404,404',
+'404,404,404,404,404,,404,404,404,,404,404,,404,404,404,,,,,,,,,,,,,',
+',,,,,,404,,,404,,,404,404,,,404,,,,,,404,,,,,,,,,404,,,,,404,404,404',
+'404,,404,404,404,404,,,,,404,404,,,,442,442,442,404,442,404,404,404',
+'442,442,,,,442,,442,442,442,442,442,442,442,,,,,,442,442,442,442,442',
+'442,442,,,442,,,,,,,442,,,442,442,442,442,442,442,442,442,442,442,442',
+'442,,442,442,,442,442,442,,,,,,,,,,,,,,,,,,,,442,,,442,,,442,442,,,442',
+',442,,442,,442,,,442,,,,,,442,,,,,442,442,442,442,,442,442,442,442,',
+',,,442,442,,,,444,444,444,442,444,442,442,442,444,444,,,,444,,444,444',
+'444,444,444,444,444,,,,,,444,444,444,444,444,444,444,,,444,,,,,,,444',
+',,444,444,444,444,444,444,444,444,,444,444,444,,444,444,,444,444,444',
+',,,,,,,,,,,,,,,,,,,444,,,444,,,444,444,,,444,,,,,,444,,,,,,,,,444,,',
+',,444,444,444,444,,444,444,444,444,,,,,444,444,,,,445,445,445,444,445',
+'444,444,444,445,445,,,,445,,445,445,445,445,445,445,445,,,,,,445,445',
+'445,445,445,445,445,,,445,,,,,,,445,,,445,445,445,445,445,445,445,445',
+',445,445,445,,445,445,,445,445,445,,,,,,,,,,,,,,,,,,,,445,,,445,,,445',
+'445,,,445,,,,,,445,,,,,,,,,445,,,,,445,445,445,445,,445,445,445,445',
+',,,,445,445,,,,446,446,446,445,446,445,445,445,446,446,,,,446,,446,446',
+'446,446,446,446,446,,,,,,446,446,446,446,446,446,446,,,446,,,,,,,446',
+',,446,446,446,446,446,446,446,446,,446,446,446,,446,446,,446,446,446',
+',,,,,,,,,,,,,,,,,,,446,,,446,,,446,446,,,446,,,,,,446,,,,,,,,,446,,',
+',,446,446,446,446,,446,446,446,446,,,,,446,446,,,,472,472,472,446,472',
+'446,446,446,472,472,,,,472,,472,472,472,472,472,472,472,,,,,,472,472',
+'472,472,472,472,472,,,472,,,,,,,472,,,472,472,472,472,472,472,472,472',
+',472,472,472,,472,472,,472,472,472,,,,,,,,,,,,,,,,,,,,472,,,472,,,472',
+'472,,,472,,,,,,472,,,,,,,,,472,,,,,472,472,472,472,,472,472,472,472',
+',,,,472,472,,,,486,486,486,472,486,472,472,472,486,486,,,,486,,486,486',
+'486,486,486,486,486,,,,,,486,486,486,486,486,486,486,,,486,,,,,,,486',
+',,486,486,486,486,486,486,486,486,486,486,486,486,,486,486,,486,486',
+'486,,,,,,,,,,,,,,,,,,,,486,,,486,,,486,486,,,486,,486,,486,,486,,,486',
+',,,,,486,,,,,486,486,486,486,,486,486,486,486,,,,,486,486,,,,488,488',
+'488,486,488,486,486,486,488,488,,,,488,,488,488,488,488,488,488,488',
+',,,,,488,488,488,488,488,488,488,,,488,,,,,,,488,,,488,488,488,488,488',
+'488,488,488,488,488,488,488,,488,488,,488,488,488,,,,,,,,,,,,,,,,,,',
+',488,,,488,,,488,488,,,488,,,,488,,488,,,488,,,,,,488,,,,,488,488,488',
+'488,,488,488,488,488,,,,,488,488,,,,490,490,490,488,490,488,488,488',
+'490,490,,,,490,,490,490,490,490,490,490,490,,,,,,490,490,490,490,490',
+'490,490,,,490,,,,,,,490,,,490,490,490,490,490,490,490,490,,490,490,490',
+',490,490,,490,490,490,,,,,,,,,,,,,,,,,,,,490,,,490,,,490,490,,,490,',
+',,,,490,,,,,,,,,490,,,,,490,490,490,490,,490,490,490,490,,,,,490,490',
+',,,,,,490,,490,490,490,496,496,496,496,496,,,,496,496,,,,496,,496,496',
+'496,496,496,496,496,,,,,,496,496,496,496,496,496,496,,,496,,,,,,496',
+'496,496,496,496,496,496,496,496,496,496,496,,496,496,496,,496,496,,496',
+'496,496,,,,,,,,,,,,,,,,,,,,496,,,496,,,496,496,,,496,,496,,,,496,,,',
+',,,,,496,,,,,496,496,496,496,,496,496,496,496,,,,,496,496,,,,,,496,496',
+',496,496,496,504,504,504,,504,,,,504,504,,,,504,,504,504,504,504,504',
+'504,504,,,,,,504,504,504,504,504,504,504,,,504,,,,,,,504,,,504,504,504',
+'504,504,504,504,504,,504,504,504,,504,504,,,,504,,,,,,,,,,,,,,,,,,,',
+'504,,,504,,,504,504,,,504,,,,,,,,,,,,,,,,,,,,504,504,504,504,,504,504',
+'504,504,,,,,504,504,,,,506,506,506,504,506,504,504,504,506,506,,,,506',
+',506,506,506,506,506,506,506,,,,,,506,506,506,506,506,506,506,,,506',
+',,,,,,506,,,506,506,506,506,506,506,506,506,506,506,506,506,,506,506',
+',506,506,506,,,,,,,,,,,,,,,,,,,,506,,,506,,,506,506,,,506,,506,,506',
+',506,,,506,,,,,,506,,,,,506,506,506,506,,506,506,506,506,,,,,506,506',
+',,,512,512,512,506,512,506,506,506,512,512,,,,512,,512,512,512,512,512',
+'512,512,,,,,,512,512,512,512,512,512,512,,,512,,,,,,,512,,,512,512,512',
+'512,512,512,512,512,,512,512,512,,512,512,,,,512,,,,,,,,,,,,,,,,,,,',
+'512,,,512,,,512,512,,,512,,,,,,,,,,,,,,,,,,,,512,512,512,512,,512,512',
+'512,512,,,,,512,512,,,,515,515,515,512,515,512,512,512,515,515,,,,515',
+',515,515,515,515,515,515,515,,,,,,515,515,515,515,515,515,515,,,515',
+',,,,,,515,,,515,515,515,515,515,515,515,515,,515,515,515,,515,515,,515',
+'515,515,,,,,,,,,,,,,,,,,,,,515,,,515,,,515,515,,,515,,,,,,515,,,,,,',
+',,515,,,,,515,515,515,515,,515,515,515,515,,,,,515,515,,,,516,516,516',
+'515,516,515,515,515,516,516,,,,516,,516,516,516,516,516,516,516,,,,',
+',516,516,516,516,516,516,516,,,516,,,,,,,516,,,516,516,516,516,516,516',
+'516,516,,516,516,516,,516,516,,516,516,516,,,,,,,,,,,,,,,,,,,,516,,',
+'516,,,516,516,,,516,,,,,,516,,,,,,,,,516,,,,,516,516,516,516,,516,516',
+'516,516,,,,,516,516,,,,520,520,520,516,520,516,516,516,520,520,,,,520',
+',520,520,520,520,520,520,520,,,,,,520,520,520,520,520,520,520,,,520',
+',,,,,,520,,,520,520,520,520,520,520,520,520,,520,520,520,,520,520,,520',
+'520,520,,,,,,,,,,,,,,,,,,,,520,,,520,,,520,520,,,520,,,,,,520,,,,,,',
+',,520,,,,,520,520,520,520,,520,520,520,520,,,,,520,520,,,,526,526,526',
+'520,526,520,520,520,526,526,,,,526,,526,526,526,526,526,526,526,,,,',
+',526,526,526,526,526,526,526,,,526,,,,,,,526,,,526,526,526,526,526,526',
+'526,526,526,526,526,526,,526,526,,526,526,526,,,,,,,,,,,,,,,,,,,,526',
+',,526,,,526,526,,,526,,526,,,,526,,,526,,,,,,526,,,,,526,526,526,526',
+',526,526,526,526,,,,,526,526,,,,529,529,529,526,529,526,526,526,529',
+'529,,,,529,,529,529,529,529,529,529,529,,,,,,529,529,529,529,529,529',
+'529,,,529,,,,,,,529,,,529,529,529,529,529,529,529,529,529,529,529,529',
+',529,529,,529,529,529,,,,,,,,,,,,,,,,,,,,529,,,529,,,529,529,,,529,',
+',,,,529,,,529,,,,,,529,,,,,529,529,529,529,,529,529,529,529,,,,,529',
+'529,,,,554,554,554,529,554,529,529,529,554,554,,,,554,,554,554,554,554',
+'554,554,554,,,,,,554,554,554,554,554,554,554,,,554,,,,,,,554,,,554,554',
+'554,554,554,554,554,554,,554,554,554,,554,554,,554,554,554,,,,,,,,,',
+',,,,,,,,,,554,,,554,,,554,554,,,554,,,,,,554,,,,,,,,,554,,,,,554,554',
+'554,554,,554,554,554,554,,,,,554,554,,,,574,574,574,554,574,554,554',
+'554,574,574,,,,574,,574,574,574,574,574,574,574,,,,,,574,574,574,574',
+'574,574,574,,,574,,,,,,,574,,,574,574,574,574,574,574,574,574,,574,574',
+'574,,574,574,,574,574,574,,,,,,,,,,,,,,,,,,,,574,,,574,,,574,574,,,574',
+',574,,,,574,,,,,,,,,574,,,,,574,574,574,574,,574,574,574,574,,,,,574',
+'574,,,,575,575,575,574,575,574,574,574,575,575,,,,575,,575,575,575,575',
+'575,575,575,,,,,,575,575,575,575,575,575,575,,,575,,,,,,,575,,,575,575',
+'575,575,575,575,575,575,575,575,575,575,,575,575,,575,575,575,,,,,,',
+',,,,,,,,,,,,,575,,,575,,,575,575,,,575,,575,,575,,575,,,575,,,,,,575',
+',,,,575,575,575,575,,575,575,575,575,,,,,575,575,,,,585,585,585,575',
+'585,575,575,575,585,585,,,,585,,585,585,585,585,585,585,585,,,,,,585',
+'585,585,585,585,585,585,,,585,,,,,,,585,,,585,585,585,585,585,585,585',
+'585,585,585,585,585,,585,585,,585,585,585,,,,,,,,,,,,,,,,,,,,585,,,585',
+',,585,585,,,585,,585,,585,,585,,,585,,,,,,585,,,,,585,585,585,585,,585',
+'585,585,585,,,,,585,585,,,,619,619,619,585,619,585,585,585,619,619,',
+',,619,,619,619,619,619,619,619,619,,,,,,619,619,619,619,619,619,619',
+',,619,,,,,,,619,,,619,619,619,619,619,619,619,619,,619,619,619,,619',
+'619,,619,619,619,,,,,,,,,,,,,,,,,,,,619,,,619,,,619,619,,,619,,619,',
+',,619,,,,,,,,,619,,,,,619,619,619,619,,619,619,619,619,,,,,619,619,',
+',,620,620,620,619,620,619,619,619,620,620,,,,620,,620,620,620,620,620',
+'620,620,,,,,,620,620,620,620,620,620,620,,,620,,,,,,,620,,,620,620,620',
+'620,620,620,620,620,,620,620,620,,620,620,,620,620,620,,,,,,,,,,,,,',
+',,,,,,620,,,620,,,620,620,,,620,,,,,,620,,,,,,,,,620,,,,,620,620,620',
+'620,,620,620,620,620,,,,,620,620,,,,623,623,623,620,623,620,620,620',
+'623,623,,,,623,,623,623,623,623,623,623,623,,,,,,623,623,623,623,623',
+'623,623,,,623,,,,,,,623,,,623,623,623,623,623,623,623,623,623,623,623',
+'623,,623,623,,623,623,623,,,,,,,,,,,,,,,,,,,,623,,,623,,,623,623,,,623',
+',623,,623,,623,,,623,,,,,,623,,,,,623,623,623,623,,623,623,623,623,',
+',,,623,623,,,,624,624,624,623,624,623,623,623,624,624,,,,624,,624,624',
+'624,624,624,624,624,,,,,,624,624,624,624,624,624,624,,,624,,,,,,,624',
+',,624,624,624,624,624,624,624,624,624,624,624,624,,624,624,,624,624',
+'624,,,,,,,,,,,,,,,,,,,,624,,,624,,,624,624,,,624,,,,624,,624,,,624,',
+',,,,624,,,,,624,624,624,624,,624,624,624,624,,,,,624,624,,,,625,625',
+'625,624,625,624,624,624,625,625,,,,625,,625,625,625,625,625,625,625',
+',,,,,625,625,625,625,625,625,625,,,625,,,,,,,625,,,625,625,625,625,625',
+'625,625,625,,625,625,625,,625,625,,625,625,625,,,,,,,,,,,,,,,,,,,,625',
+',,625,,,625,625,,,625,,,,,,625,,,,,,,,,625,,,,,625,625,625,625,,625',
+'625,625,625,,,,,625,625,,,,626,626,626,625,626,625,625,625,626,626,',
+',,626,,626,626,626,626,626,626,626,,,,,,626,626,626,626,626,626,626',
+',,626,,,,,,,626,,,626,626,626,626,626,626,626,626,,626,626,626,,626',
+'626,,626,626,626,,,,,,,,,,,,,,,,,,,,626,,,626,,,626,626,,,626,,,,,,626',
+',,,,,,,,626,,,,,626,626,626,626,,626,626,626,626,,,,,626,626,,,,630',
+'630,630,626,630,626,626,626,630,630,,,,630,,630,630,630,630,630,630',
+'630,,,,,,630,630,630,630,630,630,630,,,630,,,,,,,630,,,630,630,630,630',
+'630,630,630,630,,630,630,630,,630,630,,630,630,630,,,,,,,,,,,,,,,,,',
+',,630,,,630,,,630,630,,,630,,,,,,630,,,,,,,,,630,,,,,630,630,630,630',
+',630,630,630,630,,,,,630,630,,,,631,631,631,630,631,630,630,630,631',
+'631,,,,631,,631,631,631,631,631,631,631,,,,,,631,631,631,631,631,631',
+'631,,,631,,,,,,,631,,,631,631,631,631,631,631,631,631,,631,631,631,',
+'631,631,,631,631,631,,,,,,,,,,,,,,,,,,,,631,,,631,,,631,631,,,631,,',
+',,,631,,,,,,,,,631,,,,,631,631,631,631,,631,631,631,631,,,,,631,631',
+',,,634,634,634,631,634,631,631,631,634,634,,,,634,,634,634,634,634,634',
+'634,634,,,,,,634,634,634,634,634,634,634,,,634,,,,,,,634,,,634,634,634',
+'634,634,634,634,634,,634,634,634,,634,634,,634,634,634,,,,,,,,,,,,,',
+',,,,,,634,,,634,,,634,634,,,634,,,,,,634,,,,,,,,,634,,,,,634,634,634',
+'634,,634,634,634,634,,,,,634,634,,,,635,635,635,634,635,634,634,634',
+'635,635,,,,635,,635,635,635,635,635,635,635,,,,,,635,635,635,635,635',
+'635,635,,,635,,,,,,,635,,,635,635,635,635,635,635,635,635,,635,635,635',
+',635,635,,635,635,635,,,,,,,,,,,,,,,,,,,,635,,,635,,,635,635,,,635,',
+',,,,635,,,,,,,,,635,,,,,635,635,635,635,,635,635,635,635,,,,,635,635',
+',,,659,659,659,635,659,635,635,635,659,659,,,,659,,659,659,659,659,659',
+'659,659,,,,,,659,659,659,659,659,659,659,,,659,,,,,,,659,,,659,659,659',
+'659,659,659,659,659,,659,659,659,,659,659,,659,659,659,,,,,,,,,,,,,',
+',,,,,,659,,,659,,,659,659,,,659,,,,,,659,,,,,,,,,659,,,,,659,659,659',
+'659,,659,659,659,659,,,,,659,659,,,,662,662,662,659,662,659,659,659',
+'662,662,,,,662,,662,662,662,662,662,662,662,,,,,,662,662,662,662,662',
+'662,662,,,662,,,,,,,662,,,662,662,662,662,662,662,662,662,,662,662,662',
+',662,662,,662,662,662,,,,,,,,,,,,,,,,,,,,662,,,662,,,662,662,,,662,',
+',,,,662,,,,,,,,,662,,,,,662,662,662,662,,662,662,662,662,,,,,662,662',
+',,,666,666,666,662,666,662,662,662,666,666,,,,666,,666,666,666,666,666',
+'666,666,,,,,,666,666,666,666,666,666,666,,,666,,,,,,,666,,,666,666,666',
+'666,666,666,666,666,,666,666,666,,666,666,,,,666,,,,,,,,,,,,,,,,,,,',
+'666,,,666,,,666,666,,,666,,,,,,,,,,,,,,,,,,,,666,666,666,666,,666,666',
+'666,666,,,,,666,666,,,,677,677,677,666,677,666,666,666,677,677,,,,677',
+',677,677,677,677,677,677,677,,,,,,677,677,677,677,677,677,677,,,677',
+',,,,,,677,,,677,677,677,677,677,677,677,677,,677,677,677,,677,677,,',
+',677,,,,,,,,,,,,,,,,,,,,677,,,677,,,677,677,,,677,,,,,,,,,,,,,,,,,,',
+',677,677,677,677,,677,677,677,677,,,,,677,677,,,,682,682,682,677,682',
+'677,677,677,682,682,,,,682,,682,682,682,682,682,682,682,,,,,,682,682',
+'682,682,682,682,682,,,682,,,,,,,682,,,682,682,682,682,682,682,682,682',
+',682,682,682,,682,682,,682,682,682,,,,,,,,,,,,,,,,,,,,682,,,682,,,682',
+'682,,,682,,682,,,,682,,,,,,,,,682,,,,,682,682,682,682,,682,682,682,682',
+',,,,682,682,,,,699,699,699,682,699,682,682,682,699,699,,,,699,,699,699',
+'699,699,699,699,699,,,,,,699,699,699,699,699,699,699,,,699,,,,,,,699',
+',,699,699,699,699,699,699,699,699,,699,699,699,,699,699,,699,699,699',
+',,,,,,,,,,,,,,,,,,,699,,,699,,,699,699,,,699,,,,,,699,,,,,,,,,699,,',
+',,699,699,699,699,,699,699,699,699,,,,,699,699,,,,725,725,725,699,725',
+'699,699,699,725,725,,,,725,,725,725,725,725,725,725,725,,,,,,725,725',
+'725,725,725,725,725,,,725,,,,,,,725,,,725,725,725,725,725,725,725,725',
+',725,725,725,,725,725,,725,725,725,,,,,,,,,,,,,,,,,,,,725,,,725,,,725',
+'725,,,725,,,,,,725,,,,,,,,,725,,,,,725,725,725,725,,725,725,725,725',
+',,,,725,725,,,,731,731,731,725,731,725,725,725,731,731,,,,731,,731,731',
+'731,731,731,731,731,,,,,,731,731,731,731,731,731,731,,,731,,,,,,,731',
+',,731,731,731,731,731,731,731,731,,731,731,731,,731,731,,731,731,731',
+',,,,,,,,,,,,,,,,,,,731,,,731,,,731,731,,,731,,,,,,731,,,,,,,,,731,,',
+',,731,731,731,731,,731,731,731,731,,,,,731,731,,,,754,754,754,731,754',
+'731,731,731,754,754,,,,754,,754,754,754,754,754,754,754,,,,,,754,754',
'754,754,754,754,754,,,754,,,,,,,754,,,754,754,754,754,754,754,754,754',
',754,754,754,,754,754,,754,754,754,,,,,,,,,,,,,,,,,,,,754,,,754,,,754',
'754,,,754,,,,,,754,,,,,,,,,754,,,,,754,754,754,754,,754,754,754,754',
-',,,,754,754,,,,59,59,59,754,59,754,754,754,59,59,,,,59,,59,59,59,59',
-'59,59,59,,,,,,59,59,59,59,59,59,59,,,59,,,,,,,59,,,59,59,59,59,59,59',
-'59,59,59,59,59,59,,59,59,,59,59,59,,,,,,,,,,,,,,,,,,,,59,,,59,,,59,59',
-',,59,,59,,,,59,,,59,,,,,,59,,,,,59,59,59,59,,59,59,59,59,,,,,59,59,',
-',,60,60,60,59,60,59,59,59,60,60,,,,60,,60,60,60,60,60,60,60,,,,,,60',
-'60,60,60,60,60,60,,,60,,,,,,,60,,,60,60,60,60,60,60,60,60,60,60,60,60',
-',60,60,,60,60,60,,,,,,,,,,,,,,,,,,,,60,,,60,,,60,60,,,60,,,,,,60,,,60',
-',,,,,60,,,,,60,60,60,60,,60,60,60,60,,,,,60,60,,,,63,63,63,60,63,60',
-'60,60,63,63,,,,63,,63,63,63,63,63,63,63,,,,,,63,63,63,63,63,63,63,,',
-'63,,,,,,,63,,,63,63,63,63,63,63,63,63,,63,63,63,,63,63,,63,63,63,,,',
-',,,,,,,,,,,,,,,,63,,,63,,,63,63,,,63,,,,,,63,,,,,,,,,63,,,,,63,63,63',
-'63,,63,63,63,63,,,,,63,63,,,,64,64,64,63,64,63,63,63,64,64,,,,64,,64',
-'64,64,64,64,64,64,,,,,,64,64,64,64,64,64,64,,,64,,,,,,,64,,,64,64,64',
-'64,64,64,64,64,,64,64,64,,64,64,,64,64,64,,,,,,,,,,,,,,,,,,,,64,,,64',
-',,64,64,,,64,,,,,,64,,,,,,,,,64,,,,,64,64,64,64,,64,64,64,64,,,,,64',
-'64,,,,67,67,67,64,67,64,64,64,67,67,,,,67,,67,67,67,67,67,67,67,,,,',
-',67,67,67,67,67,67,67,,,67,,,,,,,67,,,67,67,67,67,67,67,67,67,,67,67',
-'67,,67,67,,67,67,67,,,,,,,,,,,,,,,,,,,,67,,,67,,,67,67,,,67,,,,,,67',
-',,,,,,,,67,,,,,67,67,67,67,,67,67,67,67,,,,,67,67,67,,,,,67,67,,67,67',
-'67,68,68,68,,68,,,,68,68,,,,68,,68,68,68,68,68,68,68,,,,,,68,68,68,68',
-'68,68,68,,,68,,,,,,,68,,,68,68,68,68,68,68,68,68,,68,68,68,,68,68,,',
-',68,,,,,,,,,,,,,,,,,,,,68,,,68,,,68,68,,,68,,68,,,,,,,,,,,,,,,,,,68',
-'68,68,68,,68,68,68,68,,,,,68,68,,,,69,69,69,68,69,68,68,68,69,69,,,',
-'69,,69,69,69,69,69,69,69,,,,,,69,69,69,69,69,69,69,,,69,,,,,,,69,,,69',
-'69,69,69,69,69,69,69,,69,69,69,,69,69,,,,69,,,,,,,,,,,,,,,,,69,,,69',
-',,69,,,69,69,,,69,,,,,,,,,,,,,,,,,,,,69,69,69,69,,69,69,69,69,,,,,69',
-'69,,,,70,70,70,69,70,69,69,69,70,70,,,,70,,70,70,70,70,70,70,70,,,,',
-',70,70,70,70,70,70,70,,,70,,,,,,,70,,,70,70,70,70,70,70,70,70,,70,70',
-'70,,70,70,,,,70,,,,,,,,,,,,,,,,,,,,70,,,70,,,70,70,,,70,,,,,,,,,,,,',
-',,,,,,,70,70,70,70,,70,70,70,70,,,,,70,70,,,,731,731,731,70,731,70,70',
-'70,731,731,,,,731,,731,731,731,731,731,731,731,,,,,,731,731,731,731',
-'731,731,731,,,731,,,,,,,731,,,731,731,731,731,731,731,731,731,,731,731',
-'731,,731,731,,731,731,731,,,,,,,,,,,,,,,,,,,,731,,,731,,,731,731,,,731',
-',,,,,731,,,,,,,,,731,,,,,731,731,731,731,,731,731,731,731,,,,,731,731',
-',,,,,,731,,731,731,731,111,111,111,111,111,,,,111,111,,,,111,,111,111',
-'111,111,111,111,111,,,,,,111,111,111,111,111,111,111,,,111,,,,,,111',
-'111,111,111,111,111,111,111,111,111,111,111,,111,111,111,,111,111,,111',
-'111,111,,,,,,,,,,,,,,,,,,,,111,,,111,,,111,111,,,111,,111,,,,111,,,',
-',,,,,111,,,,,111,111,111,111,,111,111,111,111,,,,,111,111,,,,,424,111',
-'111,,111,111,111,424,424,424,,,424,424,424,,424,,,,,,,,,424,424,424',
-'424,,,,,,,,424,424,,424,424,424,424,424,,,,,,,,,,,,,,,,,,,,,,,,424,424',
-'424,424,424,424,424,424,424,424,424,424,424,424,,,424,424,424,,,424',
-',,424,,,424,424,,424,,424,,424,,424,424,,424,424,424,424,424,,424,424',
-'424,,,,,,,,,,,,,,424,,,424,424,424,424,56,424,,424,,,,56,56,56,,,56',
-'56,56,,56,,,,,,,,,,56,56,56,,,,,,,,56,56,,56,56,56,56,56,,,,,,,,,,,',
-',,,,,,,,,,,,56,56,56,56,56,56,56,56,56,56,56,56,56,56,,,56,56,56,,,56',
-',,56,,,56,56,,56,,56,,56,,56,56,,56,56,56,56,56,,56,,56,,,,,,,,,,,,',
-',56,,,56,56,56,56,425,56,,56,,,,425,425,425,,,425,425,425,,425,,,,,',
-',,,425,425,425,425,,,,,,,,425,425,,425,425,425,425,425,,,,,,,,,,,,,',
-',,,,,,,,,,425,425,425,425,425,425,425,425,425,425,425,425,425,425,,',
-'425,425,425,,,425,,,425,,,425,425,,425,,425,,425,,425,425,,425,425,425',
-'425,425,,425,425,425,,,,,,,,,,,,,,425,,,425,425,425,425,27,425,,425',
-',,,27,27,27,,,27,27,27,,27,,,,,,,,,27,27,27,,,,,,,,,27,27,,27,27,27',
-'27,27,,,,,,,,,,,,,,,,,,,,,,,,27,27,27,27,27,27,27,27,27,27,27,27,27',
-'27,,,27,27,27,,,27,,27,27,,,27,27,,27,,27,,27,,27,27,,27,27,27,27,27',
-',27,27,27,,,,,,,,,,,,,,27,,474,27,27,,27,,27,474,474,474,,,474,474,474',
-'646,474,646,646,646,646,646,,,,474,474,,,,,646,,,,,474,474,,474,474',
-'474,474,474,,,,,,,,,,646,,,,,,,,,646,646,646,646,,,,646,,,,,,,,,474',
-',28,,,,,474,,28,28,28,474,474,28,28,28,646,28,,,,,,,,,,28,28,,,,,,474',
-'474,,28,28,,28,28,28,28,28,,,,,474,,,474,,,,,474,,,,,,,,,,,28,28,28',
-'28,28,28,28,28,28,28,28,28,28,28,,,28,28,28,,,28,,28,28,,,28,28,,28',
-',28,,28,,28,28,,28,28,28,28,28,,28,415,28,,,,,,415,415,415,,,415,415',
-'415,28,415,,28,28,,28,,28,,415,415,415,,,,,,,,,415,415,,415,415,415',
-'415,415,,,,,,,,,,,,,,,,,,,,,,,,415,415,415,415,415,415,415,415,415,415',
-'415,415,415,415,,,415,415,415,,,415,,415,415,,,415,415,,415,,415,,415',
-',415,415,,415,415,415,415,415,,415,415,415,,,,,,,,,,,,,,415,,,415,415',
-',415,,415,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616',
-'616,616,616,616,616,616,616,616,616,,,,616,616,616,616,616,616,616,616',
-'616,616,,,,,,616,616,616,616,616,616,616,616,616,,,616,,,,,,,,,616,616',
-',616,616,616,616,616,616,616,,,616,616,,,,616,616,616,616,,,,,,,,,,',
-',,,616,616,,616,616,616,616,616,616,616,616,616,616,616,616,,,616,616',
-',,,,,,,,,,,,,616,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,,,',
-'8,8,8,8,8,8,8,8,8,8,,,,,,8,8,8,8,8,8,8,8,8,8,,8,,,,,,,,,8,8,,8,8,8,8',
-'8,8,8,,,8,8,,,,8,8,8,8,,,,,,,,,,,,,,8,8,,8,8,8,8,8,8,8,8,8,8,8,8,,,8',
-'8,,,,,,,,,,,,,,8,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,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,9,9,9,9,9,9,9,9,9,,,9',
-'9,,,,,,,,,,,,,,9,395,395,395,395,395,395,395,395,395,395,395,395,395',
-'395,395,395,395,395,395,395,395,395,395,395,,,,395,395,395,395,395,395',
-'395,395,395,395,,,,,,395,395,395,395,395,395,395,395,395,,,395,,,,,',
-',,,395,395,,395,395,395,395,395,395,395,,,395,395,,,,395,395,395,395',
-',,,,,,,,,,,,,395,395,,395,395,395,395,395,395,395,395,395,395,395,395',
-',,395,395,,,,,,,,,,,,,,395,738,738,738,738,738,738,738,738,738,738,738',
-'738,738,738,738,738,738,738,738,738,738,738,738,738,,,,738,738,738,738',
-'738,738,738,738,738,738,,,,,,738,738,738,738,738,738,738,738,738,,,738',
-',,,,,,,,738,738,,738,738,738,738,738,738,738,,,738,738,,,,738,738,738',
-'738,,,,,,,,,,,,,,738,738,,738,738,738,738,738,738,738,738,738,738,738',
-'738,,,738,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71',
+',,,,754,754,,,,756,756,756,754,756,754,754,754,756,756,,,,756,,756,756',
+'756,756,756,756,756,,,,,,756,756,756,756,756,756,756,,,756,,,,,,,756',
+',,756,756,756,756,756,756,756,756,,756,756,756,,756,756,,756,756,756',
+',,,,,,,,,,,,,,,,,,,756,,,756,,,756,756,,,756,,,,,,756,,,,,,,,,756,,',
+',,756,756,756,756,,756,756,756,756,,,,,756,756,,,,770,770,770,756,770',
+'756,756,756,770,770,,,,770,,770,770,770,770,770,770,770,,,,,,770,770',
+'770,770,770,770,770,,,770,,,,,,,770,,,770,770,770,770,770,770,770,770',
+',770,770,770,,770,770,,770,770,770,,,,,,,,,,,,,,,,,,,,770,,,770,,,770',
+'770,,,770,,,,,,770,,,,,,,,,770,,,,,770,770,770,770,,770,770,770,770',
+',,,,770,770,,,,771,771,771,770,771,770,770,770,771,771,,,,771,,771,771',
+'771,771,771,771,771,,,,,,771,771,771,771,771,771,771,,,771,,,,,,,771',
+',,771,771,771,771,771,771,771,771,,771,771,771,,771,771,,771,771,771',
+',,,,,,,,,,,,,,,,,,,771,,,771,,,771,771,,,771,,,,,,771,,,,,,,,,771,,',
+',,771,771,771,771,,771,771,771,771,,,,,771,771,,,,772,772,772,771,772',
+'771,771,771,772,772,,,,772,,772,772,772,772,772,772,772,,,,,,772,772',
+'772,772,772,772,772,,,772,,,,,,,772,,,772,772,772,772,772,772,772,772',
+',772,772,772,,772,772,,772,772,772,,,,,,,,,,,,,,,,,,,,772,,,772,,,772',
+'772,,,772,,,,,,772,,,,,,,,,772,,,,,772,772,772,772,,772,772,772,772',
+',,,,772,772,,,,773,773,773,772,773,772,772,772,773,773,,,,773,,773,773',
+'773,773,773,773,773,,,,,,773,773,773,773,773,773,773,,,773,,,,,,,773',
+',,773,773,773,773,773,773,773,773,,773,773,773,,773,773,,773,773,773',
+',,,,,,,,,,,,,,,,,,,773,,,773,,,773,773,,,773,,,,,,773,,,,,,,,,773,,',
+',,773,773,773,773,,773,773,773,773,,,,,773,773,,,,787,787,787,773,787',
+'773,773,773,787,787,,,,787,,787,787,787,787,787,787,787,,,,,,787,787',
+'787,787,787,787,787,,,787,,,,,,,787,,,787,787,787,787,787,787,787,787',
+',787,787,787,,787,787,,,,787,,,,,,,,,,,,,,,,,,,,787,,,787,,,787,787',
+',,787,,,,,,,,,,,,,,,,,,,,787,787,787,787,,787,787,787,787,,,,,787,787',
+',,,837,837,837,787,837,787,787,787,837,837,,,,837,,837,837,837,837,837',
+'837,837,,,,,,837,837,837,837,837,837,837,,,837,,,,,,,837,,,837,837,837',
+'837,837,837,837,837,,837,837,837,,837,837,,837,837,837,,,,,,,,,,,,,',
+',,,,,,837,,,837,,,837,837,,,837,,,,,,837,,,,,,,,,837,,,,,837,837,837',
+'837,,837,837,837,837,,,,,837,837,,,,842,842,842,837,842,837,837,837',
+'842,842,,,,842,,842,842,842,842,842,842,842,,,,,,842,842,842,842,842',
+'842,842,,,842,,,,,,,842,,,842,842,842,842,842,842,842,842,,842,842,842',
+',842,842,,842,842,842,,,,,,,,,,,,,,,,,,,,842,,,842,,,842,842,,,842,',
+'842,,,,842,,,,,,,,,842,,,,,842,842,842,842,,842,842,842,842,,,,,842',
+'842,,,,859,859,859,842,859,842,842,842,859,859,,,,859,,859,859,859,859',
+'859,859,859,,,,,,859,859,859,859,859,859,859,,,859,,,,,,,859,,,859,859',
+'859,859,859,859,859,859,859,859,859,859,,859,859,,859,859,859,,,,,,',
+',,,,,,,,,,,,,859,,,859,,,859,859,,,859,,,,859,,859,,,859,,,,,,859,,',
+',,859,859,859,859,,859,859,859,859,,,,,859,859,,,,860,860,860,859,860',
+'859,859,859,860,860,,,,860,,860,860,860,860,860,860,860,,,,,,860,860',
+'860,860,860,860,860,,,860,,,,,,,860,,,860,860,860,860,860,860,860,860',
+',860,860,860,,860,860,,860,860,860,,,,,,,,,,,,,,,,,,,,860,,,860,,,860',
+'860,,,860,,,,,,860,,,,,,,,,860,,,,,860,860,860,860,,860,860,860,860',
+',,,,860,860,,,,874,874,874,860,874,860,860,860,874,874,,,,874,,874,874',
+'874,874,874,874,874,,,,,,874,874,874,874,874,874,874,,,874,,,,,,,874',
+',,874,874,874,874,874,874,874,874,,874,874,874,,874,874,,,,874,,,,,',
+',,,,,,,,,,,,,,874,,,874,,,874,874,,,874,,,,,,,,,,,,,,,,,,,,874,874,874',
+'874,,874,874,874,874,,,,,874,874,,,,886,886,886,874,886,874,874,874',
+'886,886,,,,886,,886,886,886,886,886,886,886,,,,,,886,886,886,886,886',
+'886,886,,,886,,,,,,,886,,,886,886,886,886,886,886,886,886,,886,886,886',
+',886,886,,,,886,,,,,,,,,,,,,,,,,,,,886,,,886,,,886,886,,,886,,,,,,,',
+',,,,,,,,,,,,886,886,886,886,,886,886,886,886,,,,,886,886,,,,923,923',
+'923,886,923,886,886,886,923,923,,,,923,,923,923,923,923,923,923,923',
+',,,,,923,923,923,923,923,923,923,,,923,,,,,,,923,,,923,923,923,923,923',
+'923,923,923,,923,923,923,,923,923,,923,923,923,,,,,,,,,,,,,,,,,,,,923',
+',,923,,,923,923,,,923,,,,,,923,,,,,,,,,923,,,,,923,923,923,923,,923',
+'923,923,923,,,,,923,923,,,,985,985,985,923,985,923,923,923,985,985,',
+',,985,,985,985,985,985,985,985,985,,,,,,985,985,985,985,985,985,985',
+',,985,,,,,,,985,,,985,985,985,985,985,985,985,985,985,985,985,985,,985',
+'985,,985,985,985,,,,,,,,,,,,,,,,,,,,985,,,985,,,985,985,,,985,,985,',
+'985,,985,,,985,,,,,,985,,,,,985,985,985,985,,985,985,985,985,,,,,985',
+'985,,,,,56,,985,,985,985,985,56,56,56,,,56,56,56,,56,,,,,,,,,,56,56',
+'56,,,,,,,,56,56,,56,56,56,56,56,,,,,,,,,,,,,,,,,,,,,,,,56,56,56,56,56',
+'56,56,56,56,56,56,56,56,56,,,56,56,56,,,56,,,56,,,56,56,,56,,56,,56',
+',56,56,,56,56,56,56,56,,56,,56,,,,,,,,,,,,,,56,,,56,56,56,56,424,56',
+',56,,,,424,424,424,,,424,424,424,,424,,,,,,,,,424,424,424,424,,,,,,',
+',424,424,,424,424,424,424,424,,,,,,,,,,,,,,,,,,,,,,,,424,424,424,424',
+'424,424,424,424,424,424,424,424,424,424,,,424,424,424,,,424,,,424,,',
+'424,424,,424,,424,,424,,424,424,,424,424,424,424,424,,424,424,424,,',
+',,,,,,,,,,,424,,,424,424,424,424,425,424,,424,,,,425,425,425,,,425,425',
+'425,,425,,,,,,,,,425,425,425,425,,,,,,,,425,425,,425,425,425,425,425',
+',,,,,,,,,,,,,,,,,,,,,,,425,425,425,425,425,425,425,425,425,425,425,425',
+'425,425,,,425,425,425,,,425,,,425,,,425,425,,425,,425,,425,,425,425',
+',425,425,425,425,425,,425,425,425,,,,,,,,,,,,,,425,,,425,425,425,425',
+'27,425,,425,,,,27,27,27,,,27,27,27,,27,,,,,,,,,27,27,27,,,,,,,,,27,27',
+',27,27,27,27,27,,,,,,,,,,,,,,,,,,,,,,,,27,27,27,27,27,27,27,27,27,27',
+'27,27,27,27,,,27,27,27,,,27,,27,27,,,27,27,,27,,27,,27,,27,27,,27,27',
+'27,27,27,28,27,27,27,,,,28,28,28,,,28,28,28,,28,27,,,27,27,,27,,27,28',
+'28,,,,,,,,,28,28,,28,28,28,28,28,,,,,,,,,,,,,,,,,,,,,,,,28,28,28,28',
+'28,28,28,28,28,28,28,28,28,28,,,28,28,28,,,28,,28,28,,,28,28,,28,,28',
+',28,,28,28,,28,28,28,28,28,,28,415,28,,,,,,415,415,415,,,415,415,415',
+'28,415,,28,28,,28,,28,,415,415,415,,,,,,,,,415,415,,415,415,415,415',
+'415,,,,,,,,,,,,,,,,,,,,,,,,415,415,415,415,415,415,415,415,415,415,415',
+'415,415,415,,,415,415,415,,,415,,415,415,,,415,415,,415,,415,,415,,415',
+'415,,415,415,415,415,415,,415,415,415,,,,,,,,,,,,,,415,,474,415,415',
+',415,,415,474,474,474,,,474,474,474,646,474,646,646,646,646,646,,,,474',
+'474,,,,,646,,,,,474,474,,474,474,474,474,474,,,,,,,,,,646,336,,336,336',
+'336,336,336,,646,646,646,646,,,,646,336,534,,534,534,534,534,534,474',
+',,,,,,474,,534,,,474,474,336,336,,646,,,,,,336,336,336,336,,,,336,534',
+',,,474,474,,,,534,534,534,534,,,,534,,,474,,,474,,,,,474,8,8,8,8,8,8',
+'8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,,,,8,8,8,8,8,8,8,8,8,8,,,,,,8,8',
+'8,8,8,8,8,8,8,8,,8,,,,,,,,,8,8,,8,8,8,8,8,8,8,,,8,8,,,,8,8,8,8,,,,,',
+',,,,,,,,8,8,,8,8,8,8,8,8,8,8,8,8,8,8,,,8,8,,,,,,,,,,,,,,8,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,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,9,9,9,9,9,9,9,9,9,,,9,9,,,,,,,,,,,,,,9,395,395,395',
+'395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395,395',
+'395,395,395,395,,,,395,395,395,395,395,395,395,395,395,395,,,,,,395',
+'395,395,395,395,395,395,395,395,,,395,,,,,,,,,395,395,,395,395,395,395',
+'395,395,395,,,395,395,,,,395,395,395,395,,,,,,,,,,,,,,395,395,,395,395',
+'395,395,395,395,395,395,395,395,395,395,,,395,395,,,,,,,,,,,,,,395,616',
+'616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616,616',
+'616,616,616,616,616,616,,,,616,616,616,616,616,616,616,616,616,616,',
+',,,,616,616,616,616,616,616,616,616,616,,,616,,,,,,,,,616,616,,616,616',
+'616,616,616,616,616,,,616,616,,,,616,616,616,616,,,,,,,,,,,,,,616,616',
+',616,616,616,616,616,616,616,616,616,616,616,616,,,616,616,,,,,,,,,',
+',,,,616,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71',
'71,71,71,71,,,,71,71,71,71,71,71,71,71,71,71,,,,,,71,71,71,71,71,71',
'71,71,71,71,71,71,,71,,,,,,,71,71,,71,71,71,71,71,71,71,,,71,71,,,,71',
-'71,71,71,,,,,,71,,,,,,,,71,71,,71,71,71,71,71,71,71,71,71,71,71,71,508',
-'508,71,,508,,,,,,,,,508,508,,508,508,508,508,508,508,508,,,508,508,',
-',,508,508,508,508,,,,,,508,,,,,,,,508,508,,508,508,508,508,508,508,508',
-'508,508,508,508,508,987,987,508,,987,,,,,,,,,987,987,,987,987,987,987',
-'987,987,987,,,987,987,,,,987,987,987,987,,,,,,987,,,,,,,,987,987,,987',
-'987,987,987,987,987,987,987,987,987,987,987,441,441,987,,441,,,,,,,',
-',441,441,,441,441,441,441,441,441,441,,,441,441,,,,441,441,441,441,',
-',,,,441,,,,,,,,441,441,,441,441,441,441,441,441,441,441,441,441,441',
-'441,440,440,441,,440,,,,,,,,,440,440,,440,440,440,440,440,440,440,,',
-'440,440,,,,440,440,440,440,,,,,,440,,,,,,,,440,440,,440,440,440,440',
-'440,440,440,440,440,440,440,440,507,507,440,,507,,,,,,,,,507,507,,507',
-'507,507,507,507,507,507,,,507,507,,,,507,507,507,507,,,,,,507,,,,,,',
-',507,507,,507,507,507,507,507,507,507,507,507,507,507,507,576,576,507',
-',576,,,,,,,,,576,576,,576,576,576,576,576,576,576,,,576,576,,,,576,576',
-'576,576,,,,,,576,,,,,,,,576,576,,576,576,576,576,576,576,576,576,576',
-'576,576,576,577,577,576,,577,,,,,,,,,577,577,,577,577,577,577,577,577',
-'577,,,577,577,,,,577,577,577,577,,,,,,577,,,,,,,,577,577,,577,577,577',
-'577,577,577,577,577,577,577,577,577,939,939,577,,939,,,,,,,,,939,939',
+'71,71,71,,,,,,71,,,,,,,,71,71,,71,71,71,71,71,71,71,71,71,71,71,71,',
+',71,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738',
+'738,738,738,738,738,738,738,738,,,,738,738,738,738,738,738,738,738,738',
+'738,,,,,,738,738,738,738,738,738,738,738,738,,,738,,,,,,,,,738,738,',
+'738,738,738,738,738,738,738,,,738,738,,,,738,738,738,738,,,,,,,,,,,',
+',,738,738,,738,738,738,738,738,738,738,738,738,738,738,738,210,210,738',
+',210,,,,,,,,,210,210,,210,210,210,210,210,210,210,,,210,210,,,,210,210',
+'210,210,,,,,,210,,,,,,,,210,210,,210,210,210,210,210,210,210,210,210',
+'210,210,210,211,211,210,,211,,,,,,,,,211,211,,211,211,211,211,211,211',
+'211,,,211,211,,,,211,211,211,211,,,,,,211,,,,,,,,211,211,,211,211,211',
+'211,211,211,211,211,211,211,211,211,259,259,211,,259,,,,,,,,,259,259',
+',259,259,259,259,259,259,259,,,259,259,,,,259,259,259,259,,,,,,,,,,',
+',,,259,259,,259,259,259,259,259,259,259,259,259,259,259,259,440,440',
+'259,,440,,,,,,,,,440,440,,440,440,440,440,440,440,440,,,440,440,,,,440',
+'440,440,440,,,,,,440,,,,,,,,440,440,,440,440,440,440,440,440,440,440',
+'440,440,440,440,441,441,440,,441,,,,,,,,,441,441,,441,441,441,441,441',
+'441,441,,,441,441,,,,441,441,441,441,,,,,,441,,,,,,,,441,441,,441,441',
+'441,441,441,441,441,441,441,441,441,441,507,507,441,,507,,,,,,,,,507',
+'507,,507,507,507,507,507,507,507,,,507,507,,,,507,507,507,507,,,,,,507',
+',,,,,,,507,507,,507,507,507,507,507,507,507,507,507,507,507,507,508',
+'508,507,,508,,,,,,,,,508,508,,508,508,508,508,508,508,508,,,508,508',
+',,,508,508,508,508,,,,,,508,,,,,,,,508,508,,508,508,508,508,508,508',
+'508,508,508,508,508,508,517,517,508,,517,,,,,,,,,517,517,,517,517,517',
+'517,517,517,517,,,517,517,,,,517,517,517,517,,,,,,517,,,,,,,,517,517',
+',517,517,517,517,517,517,517,517,517,517,517,517,518,518,517,,518,,',
+',,,,,,518,518,,518,518,518,518,518,518,518,,,518,518,,,,518,518,518',
+'518,,,,,,518,,,,,,,,518,518,,518,518,518,518,518,518,518,518,518,518',
+'518,518,576,576,518,,576,,,,,,,,,576,576,,576,576,576,576,576,576,576',
+',,576,576,,,,576,576,576,576,,,,,,576,,,,,,,,576,576,,576,576,576,576',
+'576,576,576,576,576,576,576,576,577,577,576,,577,,,,,,,,,577,577,,577',
+'577,577,577,577,577,577,,,577,577,,,,577,577,577,577,,,,,,577,,,,,,',
+',577,577,,577,577,577,577,577,577,577,577,577,577,577,577,583,583,577',
+',583,,,,,,,,,583,583,,583,583,583,583,583,583,583,,,583,583,,,,583,583',
+'583,583,,,,,,583,,,,,,,,583,583,,583,583,583,583,583,583,583,583,583',
+'583,583,583,584,584,583,,584,,,,,,,,,584,584,,584,584,584,584,584,584',
+'584,,,584,584,,,,584,584,584,584,,,,,,584,,,,,,,,584,584,,584,584,584',
+'584,584,584,584,584,584,584,584,584,939,939,584,,939,,,,,,,,,939,939',
',939,939,939,939,939,939,939,,,939,939,,,,939,939,939,939,,,,,,939,',
-',,,,,,939,939,,939,939,939,939,939,939,939,939,939,939,939,939,583,583',
-'939,,583,,,,,,,,,583,583,,583,583,583,583,583,583,583,,,583,583,,,,583',
-'583,583,583,,,,,,583,,,,,,,,583,583,,583,583,583,583,583,583,583,583',
-'583,583,583,583,517,517,583,,517,,,,,,,,,517,517,,517,517,517,517,517',
-'517,517,,,517,517,,,,517,517,517,517,,,,,,517,,,,,,,,517,517,,517,517',
-'517,517,517,517,517,517,517,517,517,517,584,584,517,,584,,,,,,,,,584',
-'584,,584,584,584,584,584,584,584,,,584,584,,,,584,584,584,584,,,,,,584',
-',,,,,,,584,584,,584,584,584,584,584,584,584,584,584,584,584,584,518',
-'518,584,,518,,,,,,,,,518,518,,518,518,518,518,518,518,518,,,518,518',
-',,,518,518,518,518,,,,,,518,,,,,,,,518,518,,518,518,518,518,518,518',
-'518,518,518,518,518,518,259,259,518,,259,,,,,,,,,259,259,,259,259,259',
-'259,259,259,259,,,259,259,,,,259,259,259,259,,,,,,,,,,,,,,259,259,,259',
-'259,259,259,259,259,259,259,259,259,259,259,210,210,259,,210,,,,,,,',
-',210,210,,210,210,210,210,210,210,210,,,210,210,,,,210,210,210,210,',
-',,,,210,,,,,,,,210,210,,210,210,210,210,210,210,210,210,210,210,210',
-'210,986,986,210,,986,,,,,,,,,986,986,,986,986,986,986,986,986,986,,',
-'986,986,,,,986,986,986,986,,,,,,986,,,,,,,,986,986,,986,986,986,986',
-'986,986,986,986,986,986,986,986,211,211,986,,211,,,,,,,,,211,211,,211',
-'211,211,211,211,211,211,,,211,211,,,,211,211,211,211,,,,,,211,,,,,,',
-',211,211,,211,211,211,211,211,211,211,211,211,211,211,211,,893,211,893',
-'893,893,893,893,,977,,977,977,977,977,977,,893,336,,336,336,336,336',
-'336,977,534,,534,534,534,534,534,,336,,,,,893,,,534,,,,,977,893,893',
-'893,893,,,,893,336,336,977,977,,,,977,534,336,336,336,336,,,,336,534',
-'534,534,534,,,975,534,975,975,975,975,975,973,,973,973,973,973,973,',
-'971,975,971,971,971,971,971,,973,,,,,,,737,971,737,737,737,737,737,',
-'975,,,,,,,973,737,,,975,975,,,971,975,,973,973,,,,973,971,971,971,971',
-',,737,971,736,,736,736,736,736,736,737,737,737,737,,,,737,693,736,693',
-'693,693,693,693,,865,,865,865,865,865,865,,693,,,,,,,736,865,867,,867',
-'867,867,867,867,736,736,736,736,,,693,736,,867,,,,,865,693,693,693,693',
-',,,693,865,865,865,865,,,,865,867,869,,869,869,869,869,869,,867,867',
-'867,867,,,,867,869,695,,695,695,695,695,695,697,,697,697,697,697,697',
-',,695,,,,,869,,697,899,,899,899,899,899,899,,869,869,,,,869,695,,899',
-',,,,697,,695,695,695,695,,,,695,,697,697,,,,697,899,895,,895,895,895',
-'895,895,,,,899,899,,,,899,895,,,,,,,,,,,,,,,,,,,,,,895,,,,,,,,,,,895',
-'895,,,,895' ]
- racc_action_check = arr = ::Array.new(25310, nil)
+',,,,,,939,939,,939,939,939,939,939,939,939,939,939,939,939,939,986,986',
+'939,,986,,,,,,,,,986,986,,986,986,986,986,986,986,986,,,986,986,,,,986',
+'986,986,986,,,,,,986,,,,,,,,986,986,,986,986,986,986,986,986,986,986',
+'986,986,986,986,987,987,986,,987,,,,,,,,,987,987,,987,987,987,987,987',
+'987,987,,,987,987,,,,987,987,987,987,,,,,,987,,,,,,,,987,987,,987,987',
+'987,987,987,987,987,987,987,987,987,987,,693,987,693,693,693,693,693',
+',695,,695,695,695,695,695,,693,,,,,,,736,695,736,736,736,736,736,,,',
+',,,,,693,736,,,,,,,695,693,693,693,693,,,,693,695,695,695,695,,,736',
+'695,737,,737,737,737,737,737,736,736,736,736,,,,736,865,737,865,865',
+'865,865,865,,867,,867,867,867,867,867,,865,,,,,,,737,867,893,,893,893',
+'893,893,893,737,737,737,737,,,865,737,,893,,,,,867,865,865,865,865,',
+',,865,867,867,867,867,,,,867,893,897,,897,897,897,897,897,,893,893,893',
+'893,,,,893,897,899,,899,899,899,899,899,,971,,971,971,971,971,971,,899',
+',,,,897,,973,971,973,973,973,973,973,,,897,897,,,,897,899,973,,,,,,',
+'971,,,899,899,,,,899,971,971,971,971,,,973,971,975,,975,975,975,975',
+'975,,,973,973,,,,973,977,975,977,977,977,977,977,,989,,989,989,989,989',
+'989,1015,977,1015,1015,1015,1015,1015,,975,989,,,,,,,1015,,,975,975',
+',,977,975,,,,,,,989,,,977,977,,,1015,977,,,989,989,,,,989,,1015,1015',
+',,,1015' ]
+ racc_action_check = arr = ::Array.new(25292, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -1810,19 +1808,19 @@ clist = [
end
racc_action_pointer = [
- 3995, 568, nil, -83, nil, 17702, 1301, 370, 23341, 23470,
- 1210, nil, 1170, 1222, 425, 419, 1157, 605, nil, -75,
- 18626, 2726, 1263, nil, 476, nil, 162, 22754, 22964, 18890,
- 19022, 19154, nil, 1739, 19286, 19418, nil, 1069, -77, 140,
- 1112, 197, 20086, 20218, 20350, 1034, 965, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 22484, nil, -70, 21010,
- 21142, 71, nil, 21274, 21406, nil, nil, 21538, 21678, 21810,
- 21942, 23842, nil, nil, nil, nil, nil, 143, nil, nil,
+ 750, 47, nil, 123, nil, 5120, 1299, -62, 23249, 23378,
+ -21, nil, -43, 71, 533, -41, 34, -4, nil, -72,
+ 5252, 1173, 168, nil, 157, nil, 6, 22760, 22871, 5384,
+ 5516, 5648, nil, 891, 5780, 5912, nil, 71, 227, 254,
+ 154, 228, 6052, 6184, 6316, 95, 544, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, 22355, nil, -71, 6448,
+ 6580, -23, nil, 6712, 6844, nil, nil, 6976, 7116, 7248,
+ 7380, 23765, nil, nil, nil, nil, nil, 470, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 359, nil, nil, 472, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 1121,
- nil, 22214, nil, nil, nil, nil, 5114, 5246, 5378, 5510,
- 5650, 2021, nil, 585, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, 0, nil, nil, 113, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, 262,
+ nil, 7520, nil, nil, nil, nil, 7660, 7792, 7924, 8056,
+ 8196, 1032, nil, 220, 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, nil, nil, nil, nil, nil, nil, nil, nil,
@@ -1830,89 +1828,89 @@ racc_action_pointer = [
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, nil, nil,
- nil, nil, nil, nil, 928, nil, 2585, 6046, 6178, 6310,
- 24710, 24834, 6706, 6838, 6970, 7102, 7234, 7366, nil, nil,
- 1175, 110, 358, 953, 205, 863, 897, nil, 7894, 1598,
- 890, 8026, 8158, 8290, 8422, 8554, 8686, 8818, 8950, 9082,
- 9214, 9346, 9478, 9610, 9742, 9874, 10006, 10138, 10270, 10402,
- 10534, 10666, 10798, 10930, 11062, 11194, nil, nil, nil, 24648,
- nil, nil, 878, 11590, 11722, nil, nil, nil, nil, nil,
- nil, nil, 11854, nil, 1598, nil, 815, 800, nil, 12382,
- 845, 12646, nil, nil, 12778, 12910, nil, nil, 285, nil,
- 13182, 1442, 817, 786, 4277, 770, 809, 756, 13974, 4841,
- 896, 794, 935, 812, 1037, nil, 752, 681, 10, nil,
- nil, nil, 690, 252, 632, 15302, nil, 490, 671, 752,
- nil, 664, nil, 15846, 2726, 15978, 578, nil, 373, 247,
- 811, 803, 170, 905, nil, nil, 24914, 688, 32, -11,
- 17166, 17430, -72, 185, 392, 7, 38, 580, 1104, 5,
- 1124, nil, nil, 217, 507, 134, nil, 617, nil, 16,
- 17562, nil, nil, nil, 108, 576, 185, 312, 397, 513,
- 554, -20, 562, nil, 251, nil, 17298, nil, 410, 404,
- 395, 463, 283, -22, 30, 351, nil, nil, nil, nil,
- nil, nil, nil, nil, 1025, 23599, nil, nil, nil, nil,
- 1020, nil, nil, 995, 17034, 963, nil, nil, 1034, 963,
- nil, 956, 942, 318, 143, 23077, nil, nil, nil, 248,
- 137, 970, nil, nil, 22349, 22619, nil, 1316, nil, 885,
- nil, nil, 752, nil, nil, nil, nil, -14, nil, 936,
- 24090, 24028, 16902, 150, 16770, 16638, 16506, 3713, 4136, 527,
- 321, 724, 711, 666, 605, 5246, 5378, 5510, 3995, 4277,
- 3290, 3431, 3854, 4418, 4700, 4841, 4559, 5114, 3149, 3155,
- 3572, 4982, 16374, 115, 22884, nil, nil, nil, nil, 544,
- nil, 86, 144, 568, nil, nil, 16242, nil, 16110, nil,
- 15714, nil, 219, nil, nil, nil, 15574, 1457, 2162, 615,
- 616, nil, nil, 625, 15434, 634, 15170, 24152, 23904, 329,
- 686, nil, 15038, 645, nil, 14906, 14774, 24462, 24586, 1457,
- 14642, 808, 825, 712, 748, nil, 14510, nil, nil, 14378,
- nil, nil, nil, nil, 24922, nil, 709, 713, nil, 718,
- 723, 731, nil, nil, nil, nil, nil, nil, nil, nil,
- 723, 616, nil, nil, 14246, nil, nil, nil, 826, nil,
- nil, nil, 827, nil, nil, 829, 893, 871, nil, 752,
- 67, 63, 869, 878, 14114, 13842, 24214, 24276, 58, nil,
- nil, 1106, nil, 24400, 24524, 13710, nil, nil, nil, 281,
- -18, 4136, 815, nil, -12, nil, nil, nil, 735, nil,
- nil, nil, 787, nil, nil, 391, nil, 239, nil, nil,
- 784, nil, 785, nil, nil, nil, 23212, nil, 787, 13578,
- 13446, 485, 837, 13314, 13042, 12514, 12250, 838, nil, nil,
- 12118, 11986, 859, nil, 11458, 11326, nil, nil, 316, 276,
- 609, 0, 857, 893, 1739, nil, 22848, nil, 1316, 980,
- 27, 157, nil, 1175, 1034, nil, 884, nil, 931, 7762,
- nil, nil, 7630, nil, 907, -80, 7498, 890, nil, 895,
- 92, 57, 941, 480, 1034, 952, 912, 6574, 1880, 980,
- 145, 1034, 6442, nil, 927, nil, 465, 27, 930, 634,
- nil, nil, 348, 25060, nil, 25141, nil, 25148, nil, 5914,
- nil, 609, nil, 936, 243, 940, nil, nil, nil, nil,
- 599, nil, 1059, nil, nil, nil, nil, 1065, nil, 33,
- 944, 25, 22, 68, 8, 5782, 328, 517, nil, 985,
- 4418, 22074, nil, nil, 1116, 3713, 25045, 25005, 23728, nil,
- nil, nil, nil, nil, nil, 2444, nil, nil, nil, nil,
- nil, nil, nil, 1013, 20878, 2021, 20614, nil, 1015, nil,
- 1175, nil, 2162, nil, nil, 2303, nil, 2444, nil, 2585,
- 20482, 19954, 19822, 19690, -83, 1035, 1035, 1038, nil, 1048,
- 1049, 1053, nil, 1078, 1058, 1063, 1058, 19558, nil, nil,
- 1193, nil, nil, 2867, 1097, 1208, nil, nil, nil, nil,
- 1097, 256, nil, nil, 1227, nil, 4559, 534, 1150, nil,
- nil, 1165, nil, nil, 3854, 3572, 1166, 1128, nil, nil,
- nil, 1129, 1131, nil, 1132, 1136, nil, 1138, nil, nil,
- 1144, 3135, 1146, 675, nil, 1279, nil, 18758, 1280, 3290,
- 3149, nil, 18494, 1880, -19, 24, nil, 1286, 358, 1457,
- nil, 1292, 1171, 98, nil, 1175, 1172, nil, 2867, 18362,
- 18230, nil, 3118, nil, nil, 25068, nil, 25085, nil, 25124,
- nil, nil, 1198, 1161, 18098, 1076, 1255, nil, 1197, nil,
- nil, nil, 3008, nil, nil, 35, 17966, nil, nil, 1210,
- -3, nil, nil, 24897, nil, 25204, nil, 14021, nil, 25165,
- nil, nil, nil, nil, 255, 3174, -114, nil, -1, nil,
- 77, 93, nil, 289, nil, nil, nil, 102, nil, nil,
- nil, 105, nil, 17834, 84, nil, nil, 99, 105, 132,
- 144, nil, 206, nil, 393, nil, nil, nil, 440, 24338,
- nil, nil, nil, 4700, 642, 666, 683, 315, 755, nil,
- nil, nil, 260, 270, 281, 306, 323, 3276, 340, 3309,
- 3431, nil, nil, nil, nil, nil, 2303, nil, 4982, 3008,
- nil, 24990, nil, 24982, nil, 24975, nil, 24905, nil, nil,
- nil, 1302, 443, 448, 557, 20746, 24772, 23966, 824, 15481,
- nil, nil, nil, nil, 602, 449, 20, 578, 605, 493,
- 495, 674, 819, nil, nil, 867, -9, -10, 39, 893,
- 1026, 1028, nil, nil, nil, 19465, nil, nil, nil, nil,
- 18, nil, 907, nil ]
+ nil, nil, nil, nil, 141, nil, 1173, 8328, 8460, 8592,
+ 23941, 24003, 8724, 8856, 8988, 9120, 9252, 9384, nil, nil,
+ 546, -77, -62, 233, 131, 196, 256, nil, 9516, 1314,
+ 273, 9648, 9780, 9912, 10044, 10176, 10308, 10440, 10572, 10704,
+ 10836, 10968, 11100, 11232, 11364, 11496, 11628, 11760, 11892, 12024,
+ 12156, 12288, 12420, 12552, 12684, 12816, nil, nil, nil, 24065,
+ nil, nil, 275, 12948, 13080, nil, nil, nil, nil, nil,
+ nil, nil, 13212, nil, 1314, nil, 262, 314, nil, 13344,
+ 366, 13476, nil, nil, 13608, 13740, nil, nil, 296, nil,
+ 13880, 1440, 368, 362, 1455, 384, 444, 418, 14012, 1596,
+ 578, 615, 681, 505, 750, nil, 478, 439, 33, nil,
+ nil, nil, 501, 258, 478, 14152, nil, 299, 561, 753,
+ nil, 569, nil, 14284, 1737, 14416, 528, nil, 105, 259,
+ 571, 585, 454, 619, nil, nil, 23117, 488, -1, 26,
+ 14548, 14680, 458, 706, 596, -23, -19, 792, 691, -18,
+ 724, nil, nil, 227, 281, -34, nil, 822, nil, 34,
+ 14812, nil, nil, nil, 264, 409, 448, 451, 478, 508,
+ 512, 532, 554, nil, 567, nil, 14944, nil, 275, 335,
+ 363, 375, 392, -45, -41, 395, nil, nil, nil, nil,
+ nil, nil, nil, nil, 643, 23507, nil, nil, nil, nil,
+ 650, nil, nil, 642, 15076, 644, nil, nil, 891, 658,
+ nil, 672, 676, 332, 342, 22984, nil, nil, nil, 224,
+ 337, 723, nil, nil, 22490, 22625, nil, 1455, nil, 689,
+ nil, nil, 750, nil, nil, nil, nil, -33, nil, 746,
+ 24127, 24189, 15208, 239, 15340, 15472, 15604, 3147, 3288, 538,
+ 659, 778, 783, 788, 798, 5120, 5252, 5384, 3429, 3570,
+ 3711, 3852, 3993, 4134, 4275, 4416, 4557, 4698, 621, 630,
+ 4839, 4980, 15736, -46, 23114, nil, nil, nil, nil, 747,
+ nil, 159, 279, 750, nil, nil, 15868, nil, 16000, nil,
+ 16132, nil, 332, nil, nil, nil, 16272, 1455, 1878, 752,
+ 751, nil, nil, 754, 16412, 767, 16544, 24251, 24313, 891,
+ 809, nil, 16676, 769, nil, 16808, 16940, 24375, 24437, 1596,
+ 17072, 897, 896, 694, 824, nil, 17204, nil, nil, 17336,
+ nil, nil, nil, nil, 23134, nil, 783, 784, nil, 785,
+ 793, 794, nil, nil, nil, nil, nil, nil, nil, nil,
+ 787, 477, nil, nil, 17468, nil, nil, nil, 880, nil,
+ nil, nil, 881, nil, nil, 882, 2019, 935, nil, 2160,
+ 63, 119, 935, 945, 17600, 17732, 24499, 24561, 10, nil,
+ nil, 894, nil, 24623, 24685, 17864, nil, nil, nil, 587,
+ 193, 2301, 883, nil, -14, nil, nil, nil, 733, nil,
+ nil, nil, 858, nil, nil, 151, nil, 222, nil, nil,
+ 846, nil, 847, nil, nil, nil, 23636, nil, 852, 17996,
+ 18128, 380, 896, 18260, 18392, 18524, 18656, 899, nil, nil,
+ 18788, 18920, 907, nil, 19052, 19184, nil, nil, 350, 416,
+ 470, 607, 874, 1032, 1737, nil, 23078, nil, 2442, 979,
+ 5, 316, nil, 2583, 2724, nil, 882, nil, 929, 19316,
+ nil, nil, 19448, nil, 905, -81, 19580, 888, nil, 893,
+ 137, 179, 935, 340, 1032, 936, 895, 19712, 1878, 972,
+ 20, 1026, 19844, nil, 913, nil, 539, 21, 914, 495,
+ nil, nil, 740, 24934, nil, 24942, nil, 5959, nil, 19976,
+ nil, 607, nil, 912, 230, 925, nil, nil, nil, nil,
+ 850, nil, 1044, nil, nil, nil, nil, 1050, nil, 32,
+ 929, 26, 41, 123, 182, 20108, 414, 1173, nil, 937,
+ 2865, 20240, nil, nil, 1060, 3006, 24957, 24997, 23879, nil,
+ nil, nil, nil, nil, nil, 3147, nil, nil, nil, nil,
+ nil, nil, nil, 937, 20372, 2019, 20504, nil, 938, nil,
+ 2160, nil, 2301, nil, nil, 2442, nil, 2583, nil, 2724,
+ 20636, 20768, 20900, 21032, 429, 940, 940, 954, nil, 958,
+ 961, 980, nil, 1009, 992, 991, 989, 21164, nil, nil,
+ 1128, nil, nil, 3288, 1031, 1137, nil, nil, nil, nil,
+ 1013, 378, nil, nil, 1149, nil, 3429, 1024, 1072, nil,
+ nil, 1072, nil, nil, 3570, 3711, 1074, 1032, nil, nil,
+ nil, 1033, 1036, nil, 1046, 1047, nil, 1051, nil, nil,
+ 1055, 614, 1053, 600, nil, 1188, nil, 21296, 1190, 3852,
+ 3993, nil, 21428, 4134, 81, 122, nil, 1191, 611, 4275,
+ nil, 1192, 1078, 613, nil, 1087, 1095, nil, 2865, 21560,
+ 21692, nil, 525, nil, nil, 25012, nil, 25020, nil, 7427,
+ nil, nil, 1123, 1159, 21824, 933, 1181, nil, 1141, nil,
+ nil, nil, 4416, nil, nil, 33, 21956, nil, nil, 1146,
+ 1255, nil, nil, 25037, nil, 14059, nil, 25076, nil, 25093,
+ nil, nil, nil, nil, 330, 3415, 1134, nil, 36, nil,
+ 1264, 1269, nil, 47, nil, nil, nil, 1277, nil, nil,
+ nil, 1197, nil, 22088, 1154, nil, nil, 1164, 1165, 1167,
+ 1170, nil, 1172, nil, 643, nil, nil, nil, 963, 24747,
+ nil, nil, nil, 4557, 1035, 1074, 1104, 1252, 1176, nil,
+ nil, nil, 1174, 1177, 1187, 1188, 1189, 3556, 1192, 3589,
+ 4698, nil, nil, nil, nil, nil, 4839, nil, 4980, 3006,
+ nil, 25101, nil, 25116, nil, 25156, nil, 25171, nil, nil,
+ nil, 1300, 1237, 1238, 1323, 22220, 24809, 24871, 1215, 25179,
+ nil, nil, nil, nil, 3697, 1216, 862, 1347, 1361, 1240,
+ 1243, 1261, 1262, nil, nil, 1270, 40, 42, 112, 1314,
+ 1268, 1271, nil, nil, nil, 25186, nil, nil, nil, nil,
+ 43, nil, 1275, nil ]
racc_action_default = [
-3, -597, -1, -583, -4, -597, -7, -597, -597, -597,
@@ -2020,92 +2018,95 @@ racc_action_default = [
-412, -508, -364, -366 ]
clist = [
-'216,275,275,275,14,373,681,415,421,14,327,522,409,334,266,270,311,311',
-'258,431,130,130,573,110,220,535,323,2,735,438,700,127,127,220,220,220',
-'406,14,302,302,487,259,428,566,569,297,276,276,276,660,311,311,311,111',
-'114,835,474,513,338,339,378,318,342,122,205,478,479,220,220,219,937',
-'220,347,357,357,705,328,582,132,132,6,542,690,691,484,6,293,343,337',
-'337,660,621,337,823,127,295,780,277,277,277,903,262,269,271,314,525',
-'528,500,826,532,783,389,390,391,392,14,804,966,114,935,220,220,220,220',
-'14,14,115,329,332,713,716,906,730,379,657,849,657,359,363,931,385,337',
-'337,337,337,605,607,838,394,591,781,592,816,13,738,921,684,325,13,324',
-'374,601,603,606,606,782,586,601,648,350,335,331,694,696,698,487,653',
-'654,937,784,700,275,375,832,650,660,13,330,273,286,287,6,923,934,1,533',
-'550,822,416,824,393,6,813,958,336,687,472,616,473,481,14,220,220,220',
-'482,963,220,220,220,220,220,220,808,688,405,830,885,1003,903,377,405',
-'380,387,14,425,275,275,415,421,434,435,436,437,931,275,642,667,381,872',
-'636,651,717,382,383,676,995,401,407,384,740,745,426,430,492,13,823,731',
-'220,220,395,402,657,657,13,13,821,220,352,734,542,311,276,204,663,818',
-'925,881,340,510,276,326,652,1011,839,14,655,266,311,14,823,270,341,302',
-'14,672,728,826,524,495,669,700,665,700,840,672,927,725,668,,302,,,863',
-'864,774,,514,,14,220,,,277,511,,570,571,,496,114,277,1012,,,220,220',
-'793,293,964,,523,801,293,,,,499,968,,13,,505,572,892,220,337,337,503',
-',928,497,929,,672,,,,823,720,,220,672,13,956,700,590,,748,729,748,622',
-'593,,114,550,,,952,,,,594,844,628,914,,739,130,800,633,587,846,,,275',
-',,847,127,796,660,,851,480,843,852,853,,416,,763,483,,,,768,700,,700',
-',431,,,13,,,220,13,,,615,,13,,894,896,,898,900,,901,,628,812,425,132',
-',,,1004,970,,,700,,999,,13,275,,296,542,542,,,,311,,,,627,,803,,311',
-'416,632,,,26,14,,14,,26,416,786,657,302,,220,809,,,,514,302,834,,26',
-',796,,514,220,664,,,26,26,26,425,26,,,,917,,,,,425,,,,680,,275,,649',
-',,,550,656,550,,275,,,,,26,26,416,,26,,,,14,,416,14,,,,,6,220,,,,,,990',
-'991,992,993,220,943,719,965,,686,14,550,550,,,425,,792,,,,425,,,,26',
-',,960,,26,26,26,26,26,26,714,714,622,,775,,785,130,220,220,,,810,220',
-'220,,,220,127,732,733,902,1021,,791,,,311,13,622,13,14,400,,998,,14',
-'14,311,628,,,633,919,811,,,,785,302,752,854,,759,761,296,514,,764,766',
-'302,,430,,,132,1020,802,,,758,,787,,,,,,405,,622,777,,,26,26,26,26,',
-'622,26,26,26,26,26,26,,,13,845,,13,,,786,848,786,26,220,,,,,14,220,',
-',,14,,296,,,13,817,296,,,14,337,,15,550,,883,337,15,,887,220,127,26',
-'26,,785,,,,311,,26,,,,,,,866,868,870,,,672,,15,304,304,1005,26,,875',
-',26,,,,14,26,,,13,,,,857,13,13,,778,14,,,,,,,,14,14,349,358,358,26,26',
-',,,,,,786,908,,,,779,,,26,26,220,,14,14,,,14,,,,,819,14,,819,311,,,26',
-',,337,15,,,,,311,,,,15,15,,26,,,938,,,,,13,,825,14,827,13,,946,,,,,',
-'714,,13,916,,,,,920,,,,,787,,,787,,787,980,787,,924,,,777,,777,,777',
-'972,974,976,978,,979,,,,,,,,,,26,,,,,13,14,,,333,,,,,,,275,15,13,,,425',
-',14,,,13,13,,14,,14,,416,,,,,,,15,,,,,622,,,220,,,13,13,,26,13,26,1016',
-'1017,1018,1019,13,,,26,,16,,,425,,16,710,,,712,,787,26,787,1023,787',
-',787,819,,777,778,777,778,777,778,777,,13,,,,,16,,15,,,,15,,,,304,15',
-',,,,,930,,932,,,787,,,26,,304,26,,,777,,39,26,351,15,,39,,,,,953,26',
-'954,,955,,,26,,,,,790,13,403,,,794,795,,433,,,39,301,301,,,,,13,,,,',
-'16,13,,13,,,26,26,,16,16,26,26,,,26,778,,778,,778,,778,346,362,362,362',
-',,26,,,,,26,26,,,,,,,,1000,,1001,,1002,,,,489,,491,,,493,494,,,778,1010',
-',,,,39,,,,,,,,855,39,39,,,,,,,,,,,1022,,,,,,,,16,,,,,,,429,,,,26,,,',
-',26,26,,,,26,,16,,,,878,,,,26,,,,15,,15,,,884,,26,304,,,,,889,890,,304',
-',,,,,,,,,,,,,,39,,,,,,,910,911,,,913,,26,,618,,,16,,,,16,39,,,26,16',
-',,,,,,26,26,,,,15,,,15,,,,,,,,942,,16,,,,,26,,26,26,,,26,15,,,,,26,',
-'744,,,,,,,,,,,,,39,,,,39,,,,301,39,,,,658,,333,,661,26,,,,,,,301,,984',
-',,,,,,39,,,15,,,,,15,15,996,,,,,,997,,,658,,304,333,,,,,,,,,,304,,,',
-',,,,,,,,,26,,706,,,,,,,,,,,,,,,26,,,,,433,26,,26,,,,,,,,,,,,,,,15,,26',
-',38,15,,,,38,,,,,,15,,,,,,16,,16,,,,753,,,,658,333,,,,,38,300,300,,',
-',,,,,,,,,,,,,,,358,,,,,,15,,,,797,,,798,,345,361,361,361,15,,,,,,,,15',
-'15,,39,,39,807,16,,,16,301,,,,,,,,301,,,,829,,15,15,,,15,,38,16,,,15',
-',,,,38,38,,,,,,,,,,,,,,,,,,,358,,,,,,,,15,,,,948,39,,429,39,,856,,,',
-',,,,,,,16,,,,,16,16,,,39,,,,,,,,,,,,,,,,,,,,,,,,,,,,38,,,15,,,,,,,,',
-',,,,,,,,15,,,38,,,15,,15,39,,,,,39,39,,,,,912,,,,,16,,301,,,16,,,,,',
-',333,301,,16,,,,,,,,,,,,,,,,,,,,,,,,38,,,,38,,,,300,38,,,,,,,,,,,,,',
-',16,300,,39,,,,,39,,38,,,16,,,,,39,,,16,16,,,,,,,,,,,,,,,,,,,,,,,,16',
-'16,,,16,,,,,,16,,,,362,,,,,,39,,,,,,,,,,,,,39,,,,,,,,39,39,16,,,,949',
-',,,,,,,,,,,,,,,,,,39,39,,,39,,,,,,39,,,,,,,,,,,,,,,,,,,,,,,,,362,,,16',
-',,,227,39,,,,945,,,,274,274,274,,16,,,,,,16,,16,320,321,322,,,,38,,38',
-',,,,,300,,,274,274,,,,300,,,,,,,,,,,,,,,,,,39,,,,,,,,,,,,,,,,,39,,,',
-',,39,,39,,,,,,,,,,,38,,,38,,,,,,,,,,,,,,,,,,,,,,38,,,,,,,,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,38,,,,,38,38,274,408,274,,,427',
-'432,,,,,300,,,,,,,,,,227,300,,447,448,449,450,451,452,453,454,455,456',
-'457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,,,,,,,,274',
-'274,,,,,,,,274,,,,,,,274,,274,38,,274,274,,38,,,,,,,,,,38,,,,,,,,,,',
-',,,,,,,,,,,,,,,519,,,,,,,,,,,,,,,,361,,,,,,38,,,,,,,,,,,,,38,,,,,,,',
-'38,38,,,,,,,,,,,,,,,,,,,,,,,,38,38,,,38,,,,,,38,,,274,,,,,,,,,,,,,,',
-',,,,,,,361,,,,,,,,38,,,,944,,,,274,,427,643,408,,,,,,,,,,,,,,,,,,,,',
-',,,,,644,,,,,,,,,,,,,,274,,274,,274,,,,,38,,,,,,,,,,,274,,,,,,38,,,678',
-'679,,38,,38,,,,,,274,,,274,,,,,,,,,,,,,,,,,,,,,,,,,274,,,,,,,,,,,,,',
-',,,,,,274,274,,,,,,,,,,274,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,274,755',
-',,274,274,760,762,,,,765,767,,,643,769,,,,,,,,,,,,,,,,,,,,,,,,274,,',
-'274,,,,,,,,,,,,,,,,,,,,274,,,,,,,,,,,,,,,,,274,,,,,,,,,,,,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,274,,858,,,,,,,,,,,,,,760,762,767,765',
-',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
-'274,,,,,,,,,,,,,,,,,274,858,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,,,,969,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,274' ]
- racc_goto_table = arr = ::Array.new(2920, nil)
+'216,275,275,275,14,327,373,409,573,14,522,276,276,276,266,270,311,311',
+'258,2,415,421,334,431,220,681,323,259,122,205,535,127,127,220,220,220',
+'406,14,302,302,550,328,428,478,297,130,130,132,132,542,311,311,311,110',
+'114,338,339,487,438,342,513,479,735,835,582,318,660,220,220,474,111',
+'220,347,357,357,705,621,826,219,6,314,690,691,804,6,783,566,569,713',
+'716,378,293,295,780,127,262,269,271,906,903,525,528,115,931,532,379',
+'935,660,389,390,391,392,385,484,838,14,937,343,114,1,220,220,220,220',
+'14,14,881,816,359,363,648,273,286,287,605,607,500,663,653,654,394,823',
+'204,352,402,395,277,277,277,651,616,472,657,13,657,923,330,650,13,375',
+'331,335,350,586,374,324,325,684,326,340,958,694,696,698,839,341,329',
+'332,840,725,966,275,730,849,591,592,13,738,921,405,6,782,487,784,934',
+'405,533,813,416,393,6,700,660,336,687,473,481,931,387,482,14,220,220',
+'220,1003,963,220,220,220,220,220,220,995,872,937,830,808,903,688,885',
+'377,296,380,14,425,275,275,717,550,381,642,382,383,384,275,740,276,542',
+'745,667,415,421,731,821,276,818,925,676,,1011,,,,,13,401,407,220,220',
+',426,430,,13,13,826,220,734,636,,311,601,603,606,606,,,601,510,657,657',
+',728,492,14,,266,311,14,,270,,302,14,669,,,524,793,774,,,927,823,,964',
+',672,,302,652,863,864,,655,514,,672,14,220,,,570,571,,,801,511,495,114',
+'665,,,503,220,220,668,823,,1012,786,700,293,499,832,496,,293,505,13',
+',,892,914,220,,480,,,497,,,,720,483,,,593,,,220,277,13,729,,,672,844',
+',277,622,968,572,114,672,,846,550,,550,,,,628,400,,,,763,633,587,800',
+',768,275,615,847,,127,,,851,,,,823,,296,416,,852,853,130,,132,739,796',
+'660,,,550,550,,13,431,,220,13,,542,542,,13,894,896,,898,900,812,901',
+',333,628,,425,,,843,,970,,,,,,,,13,275,,,700,,700,627,,311,,1004,,632',
+',296,,311,416,,296,,26,14,,14,,26,416,,748,302,748,220,809,781,,514',
+',302,664,,26,,803,514,,220,657,,,26,26,26,425,26,,,917,,,796,,,425,',
+'649,,,834,275,,,,,,,956,700,719,275,,822,,824,26,26,416,,26,,,786,14',
+'786,416,14,,,,6,965,220,,,,,990,991,992,993,,220,,,,,,14,,550,,,425',
+',,656,,,425,700,403,700,26,792,,,433,26,26,26,26,26,26,714,714,622,',
+'775,,785,810,220,220,,,943,220,220,752,,220,127,732,733,1021,686,700',
+'791,,,311,13,622,13,14,130,998,132,960,14,14,311,628,,,633,405,811,',
+',,785,302,902,1020,854,,786,514,,,,489,302,491,759,761,493,494,802,764',
+'766,,,430,919,,,,,,,,622,,,,26,26,26,26,,622,26,26,26,26,26,26,845,',
+'13,,,13,848,,,,,26,220,,928,,929,14,220,,,,14,758,,,,13,,,,,14,883,',
+'15,,887,,,15,,952,220,127,26,26,710,785,,712,,311,,26,,,,,,,,,,,,1005',
+',15,304,304,,26,,875,,26,,,672,14,26,,,13,,16,,618,13,13,16,,14,,,,857',
+',,,14,14,349,358,358,26,26,,,,,908,,,,,,,16,999,,26,26,220,,14,14,,790',
+'14,,,,794,795,14,777,,311,,,26,,,,15,,,778,,311,,,351,15,15,,26,,,938',
+',,,,13,,,14,658,13,333,946,661,,779,,,714,817,13,916,,,,,920,,,,,819',
+',,819,,16,980,,,,,,,,16,16,,,658,,,333,,,,,,,,787,,,26,825,855,827,',
+'13,14,,,,,,,,706,,275,15,13,,,425,,14,,,13,13,,14,,14,,416,433,,,,,',
+'15,,,,,622,,,220,,878,13,13,,26,13,26,,,,,13,,884,26,,,,16,425,,889',
+'890,,,429,,,26,753,,,,658,333,,,,,,,16,,,13,,910,911,,,913,15,,,,15',
+',,,304,15,,,,337,337,,,337,797,,,798,,26,,304,26,,924,,,777,26,777,15',
+'777,,,942,,819,807,26,778,,778,,778,26,,,16,,,13,16,,,829,,16,,,,,,337',
+'337,337,337,,13,930,,932,,,13,,13,,,26,26,,16,,26,26,,,26,866,868,870',
+',,,953,984,954,,955,,,26,,,,,26,26,787,856,,787,996,787,,787,,,997,',
+',,,,38,,,,,38,,,,777,,777,,777,,777,,,,,,778,,778,,778,,778,,,,,,38',
+'300,300,434,435,436,437,,,,,,,,,1000,,1001,,1002,777,26,,,,,26,26,,',
+',26,778,1010,,345,361,361,361,,912,26,,,,15,,15,,,,,26,304,,,,333,,1022',
+'787,304,787,,787,,787,,,,,,,,,,,,38,972,974,976,978,,979,,,38,38,26',
+',,,,,,16,,16,,,,26,,787,,,,,,26,26,,,523,15,,,15,,,,,,,,,,,337,337,',
+',26,,26,26,,,26,15,,,,,26,,744,,590,,1016,1017,1018,1019,,,,,,,,,,,594',
+'16,,,16,,,,38,1023,,,,26,,,,,,,,,,,,,16,,,,,38,15,,,,,15,15,,,,,,,,',
+',,,304,,,,,,,,,,,304,,,,,,,,429,,,,,26,,,,,,,,,16,,,,,16,16,39,26,38',
+',,39,38,26,,26,300,38,,,,,,,,,,,,,15,,26,300,,15,,,,39,301,301,38,,',
+'15,,,,,,,,,,,,,,,680,,,,,,,,,,,,,,346,362,362,362,,,,16,,,,,16,358,',
+',,,,15,,,16,,,,,,,,,,15,,,,,,,,15,15,,39,,,,,,,,,39,39,,,,,,,,,,,,15',
+'15,,,15,16,,,,,15,,,,,,,,16,,,,,,,,16,16,,,,,,,,358,,,,,,,,15,,,,948',
+',,,16,16,,,16,,,,,,16,,,,,,,,,,,,39,,38,,38,,,,,,300,,,,,,,,300,,,16',
+',39,,949,,,,,,15,,,,,,,,,,,,,,,,,15,,,,,337,15,,15,,,337,,,,,,,,,,,',
+',38,,,38,,,,,,,16,,39,,,,39,,,,301,39,,,,38,,16,,,,,,16,,16,,301,,,',
+',,,,,39,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,38,,,,,38,38,,,,,337,,,,',
+',,300,,,,,,,,,,,300,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,38,,,,,38,,,,,,,,,,38,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,39,',
+'39,361,,,,,301,38,,,,,,,301,,,,,,38,,,,,,,,38,38,,,,,,,,,,,,,,,,,,,',
+',,,,38,38,,,38,,,,,,38,,,,,39,,,39,,,,,,,,,,,,,,,,,361,,,,,39,,,38,',
+',,944,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,39,,,,,39,39',
+'38,,,,,,,,,,,301,,,,,,38,,,,227,301,38,,38,,,,,274,274,274,,,,,,,,,',
+',320,321,322,,,,,,,,,,,,,,,274,274,,,,,,,,,,,,,,39,,,,,39,,,,,,,,,,39',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,362,,,,,,39,,,,,,,,,,,,,39',
+',,,,,,,39,39,,,,,,,,,,,,,,,,,,,,,,,,39,39,,,39,,,,,,39,,,,,,,,,,,,,',
+'274,408,274,,,427,432,,,,,362,,,,,,,,39,,227,,945,447,448,449,450,451',
+'452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468',
+'469,470,471,,,,,,,,274,274,,,,,,,,274,,,,,,,274,,274,,,274,274,,39,',
+',,,,,,,,,,,,,,,39,,,,,,39,,39,,,,,,,,,,,519,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,274,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,274,,427,643,408,,,,,,,,,,,,,,,,,,,,,,',
+',,,644,,,,,,,,,,,,,,274,,274,,274,,,,,,,,,,,,,,,,274,,,,,,,,,678,679',
+',,,,,,,,,274,,,274,,,,,,,,,,,,,,,,,,,,,,,,,274,,,,,,,,,,,,,,,,,,,,274',
+'274,,,,,,,,,,274,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,274,755,,,274,274',
+'760,762,,,,765,767,,,643,769,,,,,,,,,,,,,,,,,,,,,,,,274,,,274,,,,,,',
+',,,,,,,,,,,,,274,,,,,,,,,,,,,,,,,274,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,274,,858,,,,,,,,,,,,,,760,762,767,765,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,274,,,',
+',,,,,,,,,,,,,274,858,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,969,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,274' ]
+ racc_goto_table = arr = ::Array.new(3100, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -2115,83 +2116,86 @@ clist = [
end
clist = [
-'31,33,33,33,22,56,10,37,37,22,69,8,23,88,73,73,64,64,140,18,60,60,94',
-'4,22,139,31,2,98,47,117,57,57,22,22,22,27,22,22,22,75,36,27,91,91,49',
-'70,70,70,178,64,64,64,6,97,92,37,51,17,17,151,63,17,15,15,39,23,22,22',
-'20,134,22,22,22,22,118,70,54,61,61,7,163,123,123,47,7,45,4,29,29,178',
-'24,29,169,57,46,128,72,72,72,116,38,38,38,50,71,71,47,174,71,131,17',
-'17,17,17,22,11,109,97,133,22,22,22,22,22,22,5,72,72,93,93,119,110,152',
-'76,111,76,55,55,175,152,29,29,29,29,155,155,11,2,112,129,113,131,21',
-'114,115,102,101,21,100,99,156,156,156,156,120,96,156,40,95,90,87,166',
-'166,166,75,40,40,134,126,117,33,86,117,74,178,21,68,44,44,44,7,67,132',
-'1,135,168,129,73,129,7,7,136,119,137,138,66,62,141,143,22,22,22,22,144',
-'145,22,22,22,22,22,22,146,139,70,118,147,133,116,150,70,153,5,22,57',
-'33,33,37,37,29,29,29,29,175,33,23,51,154,131,47,42,94,157,158,51,119',
-'20,20,159,160,161,20,20,151,21,169,162,22,22,30,28,76,76,21,21,167,22',
-'19,8,163,64,70,16,14,171,172,12,104,31,70,103,47,119,105,22,47,73,64',
-'22,169,73,106,22,22,37,54,174,31,4,23,117,47,117,107,37,128,108,47,',
-'22,,,123,123,24,,49,,22,22,,,72,63,,17,17,,6,97,72,92,,,22,22,40,45',
-'11,,29,24,45,,,,46,98,,21,,46,4,123,22,29,29,50,,129,7,129,,37,,,,169',
-'23,,22,37,21,117,117,29,,156,23,156,31,36,,97,168,,,129,,,,29,24,73',
-'93,,47,60,51,73,97,24,,,33,,,8,57,75,178,,8,44,91,139,139,,73,,39,44',
-',,,39,117,,117,,18,,,21,,,22,21,,,15,,21,,166,166,,166,166,,166,,73',
-'71,57,61,,,,10,123,,,117,,129,,21,33,,9,163,163,,,,64,,,,38,,47,,64',
-'73,38,,,41,22,,22,,41,73,168,76,22,,22,27,,,,49,22,47,,41,,75,,49,22',
-'2,,,41,41,41,57,41,,,,8,,,,,57,,,,29,,33,,38,,,,168,72,168,,33,,,,,41',
-'41,73,,41,,,,22,,73,22,,,,,7,22,,,,,,166,166,166,166,22,91,70,94,,72',
-'22,168,168,,,57,,88,,,,57,,,,41,,,91,,41,41,41,41,41,41,97,97,31,,31',
-',31,60,22,22,,,69,22,22,,,22,57,97,97,47,166,,140,,,64,21,31,21,22,9',
-',8,,22,22,64,73,,,73,47,31,,,,31,22,15,56,,20,20,9,49,,20,20,22,,20',
-',,61,24,49,,,72,,170,,,,,,70,,31,122,,,41,41,41,41,,31,41,41,41,41,41',
-'41,,,21,17,,21,,,168,17,168,41,22,,,,,22,22,,,,22,,9,,,21,122,9,,,22',
-'29,,25,168,,69,29,25,,69,22,57,41,41,,31,,,,64,,41,,,,,,,125,125,125',
-',,37,,25,25,25,23,41,,22,,41,,,,22,41,,,21,,,,20,21,21,,124,22,,,,,',
-',,22,22,25,25,25,41,41,,,,,,,168,17,,,,127,,,41,41,22,,22,22,,,22,,',
-',,124,22,,124,64,,,41,,,29,25,,,,,64,,,,25,25,,41,,,22,,,,,21,,127,22',
-'127,21,,22,,,,,,97,,21,97,,,,,97,,,,,170,,,170,,170,31,170,,122,,,122',
-',122,,122,125,125,125,125,,125,,,,,,,,,,41,,,,,21,22,,,65,,,,,,,33,25',
-'21,,,57,,22,,,21,21,,22,,22,,73,,,,,,,25,,,,,31,,,22,,,21,21,,41,21',
-'41,125,125,125,125,21,,,41,,26,,,57,,26,9,,,9,,170,41,170,125,170,,170',
-'124,,122,124,122,124,122,124,122,,21,,,,,26,,25,,,,25,,,,25,25,,,,,',
-'127,,127,,,170,,,41,,25,41,,,122,,53,41,26,25,,53,,,,,127,41,127,,127',
-',,41,,,,,9,21,65,,,9,9,,65,,,53,53,53,,,,,21,,,,,26,21,,21,,,41,41,',
-'26,26,41,41,,,41,124,,124,,124,,124,53,53,53,53,,,41,,,,,41,41,,,,,',
-',,127,,127,,127,,,,65,,65,,,65,65,,,124,127,,,,,53,,,,,,,,9,53,53,,',
-',,,,,,,,127,,,,,,,,26,,,,,,,26,,,,41,,,,,41,41,,,,41,,26,,,,9,,,,41',
-',,,25,,25,,,9,,41,25,,,,,9,9,,25,,,,,,,,,,,,,,,53,,,,,,,9,9,,,9,,41',
-',65,,,26,,,,26,53,,,41,26,,,,,,,41,41,,,,25,,,25,,,,,,,,9,,26,,,,,41',
-',41,41,,,41,25,,,,,41,,25,,,,,,,,,,,,,53,,,,53,,,,53,53,,,,65,,65,,65',
-'41,,,,,,,53,,9,,,,,,,53,,,25,,,,,25,25,9,,,,,,9,,,65,,25,65,,,,,,,,',
-',25,,,,,,,,,,,,,41,,65,,,,,,,,,,,,,,,41,,,,,65,41,,41,,,,,,,,,,,,,,',
-'25,,41,,52,25,,,,52,,,,,,25,,,,,,26,,26,,,,65,,,,65,65,,,,,52,52,52',
-',,,,,,,,,,,,,,,,,25,,,,,,25,,,,65,,,65,,52,52,52,52,25,,,,,,,,25,25',
-',53,,53,65,26,,,26,53,,,,,,,,53,,,,65,,25,25,,,25,,52,26,,,25,,,,,52',
-'52,,,,,,,,,,,,,,,,,,,25,,,,,,,,25,,,,25,53,,26,53,,65,,,,,,,,,,,26,',
-',,,26,26,,,53,,,,,,,,,,,,,,,,,,,,,,,,,,,,52,,,25,,,,,,,,,,,,,,,,,25',
-',,52,,,25,,25,53,,,,,53,53,,,,,65,,,,,26,,53,,,26,,,,,,,65,53,,26,,',
-',,,,,,,,,,,,,,,,,,,,,52,,,,52,,,,52,52,,,,,,,,,,,,,,,26,52,,53,,,,,53',
-',52,,,26,,,,,53,,,26,26,,,,,,,,,,,,,,,,,,,,,,,,26,26,,,26,,,,,,26,,',
-',53,,,,,,53,,,,,,,,,,,,,53,,,,,,,,53,53,26,,,,26,,,,,,,,,,,,,,,,,,,53',
-'53,,,53,,,,,,53,,,,,,,,,,,,,,,,,,,,,,,,,53,,,26,,,,32,53,,,,53,,,,32',
-'32,32,,26,,,,,,26,,26,32,32,32,,,,52,,52,,,,,,52,,,32,32,,,,52,,,,,',
-',,,,,,,,,,,,53,,,,,,,,,,,,,,,,,53,,,,,,53,,53,,,,,,,,,,,52,,,52,,,,',
-',,,,,,,,,,,,,,,,,52,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
-',,,,,,,,52,,,,,52,52,32,32,32,,,32,32,,,,,52,,,,,,,,,,32,52,,32,32,32',
-'32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,,',
-',,,,,32,32,,,,,,,,32,,,,,,,32,,32,52,,32,32,,52,,,,,,,,,,52,,,,,,,,',
-',,,,,,,,,,,,,,,,,32,,,,,,,,,,,,,,,,52,,,,,,52,,,,,,,,,,,,,52,,,,,,,',
-'52,52,,,,,,,,,,,,,,,,,,,,,,,,52,52,,,52,,,,,,52,,,32,,,,,,,,,,,,,,,',
-',,,,,,52,,,,,,,,52,,,,52,,,,32,,32,32,32,,,,,,,,,,,,,,,,,,,,,,,,,,32',
-',,,,,,,,,,,,,32,,32,,32,,,,,52,,,,,,,,,,,32,,,,,,52,,,32,32,,52,,52',
-',,,,,32,,,32,,,,,,,,,,,,,,,,,,,,,,,,,32,,,,,,,,,,,,,,,,,,,,32,32,,,',
-',,,,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32,32,,,32,32,32,32,,,,32',
-'32,,,32,32,,,,,,,,,,,,,,,,,,,,,,,,32,,,32,,,,,,,,,,,,,,,,,,,,32,,,,',
-',,,,,,,,,,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
-',32,,32,,,,,,,,,,,,,,32,32,32,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32,,,,,,,,,,,,,,,,,32,32,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32,,,,,,,,,,,,,',
-',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32' ]
- racc_goto_check = arr = ::Array.new(2920, nil)
+'31,33,33,33,22,69,56,23,94,22,8,70,70,70,73,73,64,64,140,2,37,37,88',
+'18,22,10,31,36,15,15,139,57,57,22,22,22,27,22,22,22,168,70,27,39,49',
+'60,60,61,61,163,64,64,64,4,97,17,17,75,47,17,51,23,98,92,54,63,178,22',
+'22,37,6,22,22,22,22,118,24,174,20,7,50,123,123,11,7,131,91,91,93,93',
+'151,45,46,128,57,38,38,38,119,116,71,71,5,175,71,152,133,178,17,17,17',
+'17,152,47,11,22,134,4,97,1,22,22,22,22,22,22,12,131,55,55,40,44,44,44',
+'155,155,47,14,40,40,2,169,16,19,28,30,72,72,72,42,62,66,76,21,76,67',
+'68,74,21,86,87,90,95,96,99,100,101,102,103,104,119,166,166,166,105,106',
+'72,72,107,108,109,33,110,111,112,113,21,114,115,70,7,120,75,126,132',
+'70,135,136,73,7,7,117,178,137,138,141,143,175,5,144,22,22,22,22,133',
+'145,22,22,22,22,22,22,119,131,134,118,146,116,139,147,150,9,153,22,57',
+'33,33,94,168,154,23,157,158,159,33,160,70,163,161,51,37,37,162,167,70',
+'171,172,51,,119,,,,,21,20,20,22,22,,20,20,,21,21,174,22,8,47,,64,156',
+'156,156,156,,,156,31,76,76,,54,151,22,,73,64,22,,73,,22,22,23,,,31,40',
+'24,,,128,169,,11,,37,,22,47,123,123,,47,49,,37,22,22,,,17,17,,,24,63',
+'4,97,47,,,50,22,22,47,169,,92,168,117,45,46,117,6,,45,46,21,,,123,93',
+'22,,44,,,7,,,,23,44,,,36,,,22,72,21,23,,,37,24,,72,31,98,4,97,37,,24',
+'168,,168,,,,73,9,,,,39,73,97,51,,39,33,15,8,,57,,,8,,,,169,,9,73,,139',
+'139,60,,61,47,75,178,,,168,168,,21,18,,22,21,,163,163,,21,166,166,,166',
+'166,71,166,,65,73,,57,,,91,,123,,,,,,,,21,33,,,117,,117,38,,64,,10,',
+'38,,9,,64,73,,9,,41,22,,22,,41,73,,156,22,156,22,27,129,,49,,22,2,,41',
+',47,49,,22,76,,,41,41,41,57,41,,,8,,,75,,,57,,38,,,47,33,,,,,,,117,117',
+'70,33,,129,,129,41,41,73,,41,,,168,22,168,73,22,,,,7,94,22,,,,,166,166',
+'166,166,,22,,,,,,22,,168,,,57,,,72,,,57,117,65,117,41,88,,,65,41,41',
+'41,41,41,41,97,97,31,,31,,31,69,22,22,,,91,22,22,15,,22,57,97,97,166',
+'72,117,140,,,64,21,31,21,22,60,8,61,91,22,22,64,73,,,73,70,31,,,,31',
+'22,47,24,56,,168,49,,,,65,22,65,20,20,65,65,49,20,20,,,20,47,,,,,,,',
+'31,,,,41,41,41,41,,31,41,41,41,41,41,41,17,,21,,,21,17,,,,,41,22,,129',
+',129,22,22,,,,22,72,,,,21,,,,,22,69,,25,,69,,,25,,129,22,57,41,41,9',
+'31,,9,,64,,41,,,,,,,,,,,,23,,25,25,25,,41,,22,,41,,,37,22,41,,,21,,26',
+',65,21,21,26,,22,,,,20,,,,22,22,25,25,25,41,41,,,,,17,,,,,,,26,129,',
+'41,41,22,,22,22,,9,22,,,,9,9,22,122,,64,,,41,,,,25,,,124,,64,,,26,25',
+'25,,41,,,22,,,,,21,,,22,65,21,65,22,65,,127,,,97,122,21,97,,,,,97,,',
+',,124,,,124,,26,31,,,,,,,,26,26,,,65,,,65,,,,,,,,170,,,41,127,9,127',
+',21,22,,,,,,,,65,,33,25,21,,,57,,22,,,21,21,,22,,22,,73,65,,,,,,25,',
+',,,31,,,22,,9,21,21,,41,21,41,,,,,21,,9,41,,,,26,57,,9,9,,,26,,,41,65',
+',,,65,65,,,,,,,26,,,21,,9,9,,,9,25,,,,25,,,,25,25,,,,29,29,,,29,65,',
+',65,,41,,25,41,,122,,,122,41,122,25,122,,,9,,124,65,41,124,,124,,124',
+'41,,,26,,,21,26,,,65,,26,,,,,,29,29,29,29,,21,127,,127,,,21,,21,,,41',
+'41,,26,,41,41,,,41,125,125,125,,,,127,9,127,,127,,,41,,,,,41,41,170',
+'65,,170,9,170,,170,,,9,,,,,,52,,,,,52,,,,122,,122,,122,,122,,,,,,124',
+',124,,124,,124,,,,,,52,52,52,29,29,29,29,,,,,,,,,127,,127,,127,122,41',
+',,,,41,41,,,,41,124,127,,52,52,52,52,,65,41,,,,25,,25,,,,,41,25,,,,65',
+',127,170,25,170,,170,,170,,,,,,,,,,,,52,125,125,125,125,,125,,,52,52',
+'41,,,,,,,26,,26,,,,41,,170,,,,,,41,41,,,29,25,,,25,,,,,,,,,,,29,29,',
+',41,,41,41,,,41,25,,,,,41,,25,,29,,125,125,125,125,,,,,,,,,,,29,26,',
+',26,,,,52,125,,,,41,,,,,,,,,,,,,26,,,,,52,25,,,,,25,25,,,,,,,,,,,,25',
+',,,,,,,,,,25,,,,,,,,26,,,,,41,,,,,,,,,26,,,,,26,26,53,41,52,,,53,52',
+'41,,41,52,52,,,,,,,,,,,,,25,,41,52,,25,,,,53,53,53,52,,,25,,,,,,,,,',
+',,,,,29,,,,,,,,,,,,,,53,53,53,53,,,,26,,,,,26,25,,,,,,25,,,26,,,,,,',
+',,,25,,,,,,,,25,25,,53,,,,,,,,,53,53,,,,,,,,,,,,25,25,,,25,26,,,,,25',
+',,,,,,,26,,,,,,,,26,26,,,,,,,,25,,,,,,,,25,,,,25,,,,26,26,,,26,,,,,',
+'26,,,,,,,,,,,,53,,52,,52,,,,,,52,,,,,,,,52,,,26,,53,,26,,,,,,25,,,,',
+',,,,,,,,,,,,25,,,,,29,25,,25,,,29,,,,,,,,,,,,,52,,,52,,,,,,,26,,53,',
+',,53,,,,53,53,,,,52,,26,,,,,,26,,26,,53,,,,,,,,,53,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,52,,,,,52,52,,,,,29,,,,,,,52,,,,,,,,,,,52,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,52,,,,,52,,,,,,,,,,52,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,53,,53,52,,,,,53,52,,,,,,,53,,,',
+',,52,,,,,,,,52,52,,,,,,,,,,,,,,,,,,,,,,,,52,52,,,52,,,,,,52,,,,,53,',
+',53,,,,,,,,,,,,,,,,,52,,,,,53,,,52,,,,52,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,53,,,,,53,53,52,,,,,,,,,,,53,,,,,,52,,,,32,53',
+'52,,52,,,,,32,32,32,,,,,,,,,,,32,32,32,,,,,,,,,,,,,,,32,32,,,,,,,,,',
+',,,,53,,,,,53,,,,,,,,,,53,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,53',
+',,,,,53,,,,,,,,,,,,,53,,,,,,,,53,53,,,,,,,,,,,,,,,,,,,,,,,,53,53,,,53',
+',,,,,53,,,,,,,,,,,,,,32,32,32,,,32,32,,,,,53,,,,,,,,53,,32,,53,32,32',
+'32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32',
+',,,,,,,32,32,,,,,,,,32,,,,,,,32,,32,,,32,32,,53,,,,,,,,,,,,,,,,,53,',
+',,,,53,,53,,,,,,,,,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,32,,32,32,32,,,,,,,,,,,,,,,,,,,,,,,,,,32,,,,,,,,,,,,,,32,,32',
+',32,,,,,,,,,,,,,,,,32,,,,,,,,,32,32,,,,,,,,,,32,,,32,,,,,,,,,,,,,,,',
+',,,,,,,,,32,,,,,,,,,,,,,,,,,,,,32,32,,,,,,,,,,32,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,32,32,,,32,32,32,32,,,,32,32,,,32,32,,,,,,,,,,,,,,,,,',
+',,,,,,32,,,32,,,,,,,,,,,,,,,,,,,,32,,,,,,,,,,,,,,,,,32,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,32,,32,,,,,,,,,,,,,,32,32,32',
+'32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,32,,,,,,,,,,,,,,,,,32,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,,,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,',
+',,,,,,,,,,,,,,,,,,32' ]
+ racc_goto_check = arr = ::Array.new(3100, nil)
idx = 0
clist.each do |str|
str.split(',', -1).each do |i|
@@ -2201,24 +2205,24 @@ clist = [
end
racc_goto_pointer = [
- nil, 194, 27, nil, 20, 121, 50, 80, -313, 447,
- -515, -565, -518, nil, -213, 55, 273, -5, -194, 209,
- 49, 153, 4, -197, -318, 752, 1007, -171, 63, 25,
- 147, -19, 1934, -28, nil, nil, 17, -203, 75, -197,
- -305, 499, -227, nil, 159, 53, 62, -188, nil, 11,
- 69, -258, 1486, 1073, -278, 68, -66, 23, nil, nil,
- 12, 70, -192, 20, -18, 890, -50, -669, 128, -49,
- 17, -223, 68, -12, -290, -237, -352, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 111, 111, -48, nil,
- 108, -295, -655, -441, -321, 101, -193, 51, -564, 89,
- 102, 99, -367, 232, 222, -420, 235, -403, -263, -797,
- -454, -598, -214, -222, -439, -699, -731, -521, -476, -702,
- -481, nil, 56, -454, 163, -1, -467, 190, -550, -496,
- nil, -536, -680, -754, -803, -141, -485, 142, -328, -311,
- -4, -49, nil, -58, -54, -698, -460, -582, nil, nil,
- 152, -19, 51, 148, 163, -236, -218, 167, 167, 171,
- -339, -339, -322, -255, nil, nil, -367, -418, -140, -600,
- 47, -405, -577, nil, -587, -728, nil, nil, -439 ]
+ nil, 119, 19, nil, 50, 97, 67, 79, -314, 198,
+ -496, -598, -678, nil, -359, 20, 133, -8, -190, 75,
+ 58, 153, 4, -202, -333, 752, 803, -171, -63, 992,
+ 23, -19, 2114, -28, nil, nil, 3, -190, 69, -219,
+ -343, 499, -328, nil, 102, 58, 59, -159, nil, 10,
+ 45, -255, 1170, 1458, -291, 59, -65, 23, nil, nil,
+ 37, 39, -249, 24, -18, 401, -105, -706, 97, -54,
+ -18, -228, 117, -12, -317, -220, -334, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, 88, 100, -39, nil,
+ 99, -252, -647, -482, -335, 94, -196, 51, -530, 93,
+ 108, 108, -356, 110, 104, -539, 109, -538, -400, -734,
+ -404, -550, -179, -188, -406, -666, -732, -350, -476, -735,
+ -455, nil, 208, -455, 220, 355, -453, 247, -553, -134,
+ nil, -561, -679, -767, -757, -140, -490, 141, -329, -306,
+ -4, -52, nil, -61, -59, -698, -456, -579, nil, nil,
+ 153, 11, 23, 149, 155, -247, -98, 156, 156, 156,
+ -353, -351, -336, -287, nil, nil, -368, -440, -296, -552,
+ 292, -434, -606, nil, -618, -764, nil, nil, -422 ]
racc_goto_default = [
nil, nil, nil, 3, nil, 4, 344, 291, nil, 521,
diff --git a/test/racc/regress/tp_plus b/test/racc/regress/tp_plus
index bb4e1f1a00..34b6284db7 100644
--- a/test/racc/regress/tp_plus
+++ b/test/racc/regress/tp_plus
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -46,179 +46,179 @@ module_eval(<<'...end tp_plus.y/module_eval...', 'tp_plus.y', 592)
racc_action_table = [
62, 62, 62, 62, 101, 122, 62, 41, 38, 130,
275, 265, 72, 41, 72, 98, 113, 72, 53, 114,
- 41, 67, 67, 67, 67, 234, 38, 26, 303, 304,
- 101, 36, 286, 159, 81, 82, 72, 308, 159, 81,
- 82, 72, 122, 287, 308, 60, 288, 60, 42, 308,
- 60, 43, 44, 131, 45, 31, 32, 355, 289, 34,
+ 41, 67, 67, 67, 67, 234, 38, 26, 152, 151,
+ 101, 36, 64, 159, 81, 82, 72, 308, 159, 81,
+ 82, 72, 122, 70, 308, 60, 74, 60, 42, 308,
+ 60, 43, 44, 131, 45, 31, 32, 300, 75, 34,
35, 46, 47, 102, 60, 273, 30, 72, 29, 28,
- 25, 63, 290, 37, 27, 24, 62, 41, 38, 37,
+ 25, 63, 76, 37, 27, 24, 62, 41, 38, 37,
69, 69, 69, 69, 33, 61, 37, 97, 53, 102,
- 61, 37, 81, 82, 300, 61, 82, 26, 82, 72,
- 60, 36, 159, 81, 82, 72, 223, 221, 224, 371,
- 336, 335, 105, 220, 292, 81, 82, 72, 42, 293,
- 317, 43, 44, 294, 45, 31, 32, 96, 122, 34,
- 35, 46, 47, 96, 60, 208, 30, 209, 29, 28,
- 25, 63, 122, 37, 27, 24, 62, 41, 38, 72,
- 60, 81, 82, 72, 33, 61, 298, 116, 53, 61,
- 301, 88, 94, 96, 321, 117, 118, 26, 317, 352,
- 302, 36, 323, 305, 203, 349, 350, 351, 353, 152,
- 151, 96, 367, 81, 82, 72, 60, 255, 42, 209,
- 306, 43, 44, 313, 45, 31, 32, 314, 94, 34,
- 35, 46, 47, 122, 60, 122, 30, 61, 29, 28,
- 25, 63, 321, 37, 27, 24, 62, 41, 38, 325,
- 323, 326, 203, 327, 33, 61, 82, 72, 53, 82,
- 72, 182, 181, 179, 180, 177, 173, 26, 176, 174,
- 328, 36, 81, 82, 72, 81, 82, 72, 81, 82,
- 72, 81, 82, 81, 82, 72, 97, 333, 42, 275,
- 122, 43, 44, 96, 45, 31, 32, 33, 188, 34,
- 35, 46, 47, 333, 60, 122, 30, 346, 29, 28,
- 25, 63, 347, 37, 27, 24, 348, 178, 356, 175,
- 81, 82, 72, 357, 33, 61, 81, 82, 72, 358,
- 88, 317, 96, 81, 82, 72, 88, 359, 96, 81,
- 82, 72, 360, 88, 96, 96, 81, 82, 72, 88,
- 361, 96, 81, 82, 72, 60, 88, 362, 96, 122,
- 364, 60, 88, 72, 96, 33, 378, 94, 60, 81,
- 82, 72, 379, 94, 60, 321, 61, 81, 82, 72,
- 94, 60, 61, 323, 380, 203, 94, 60, 381, 61,
- 382, 383, 385, 94, 386, 61, 390, 72, 392, 94,
- 64, 70, 61, 81, 82, 72, 74, 75, 61, 81,
- 82, 72, 76, 88, 103, 96, 81, 82, 72, 88,
- 33, 96, 81, 82, 72, 72, 88, 111, 96, 81,
- 82, 72, 88, 72, 96, 115, 72, 121, 60, 88,
- 122, 96, 125, 127, 60, 101, 122, 185, 186, 191,
- 94, 60, 188, 122, 122, 199, 94, 60, 200, 61,
- 201, 203, 204, 94, 60, 61, 210, 211, 212, 94,
- 213, 214, 61, 215, 216, 217, 94, 218, 61, 135,
+ 61, 37, 81, 82, 355, 61, 103, 26, 82, 72,
+ 60, 36, 159, 81, 82, 72, 208, 221, 209, 371,
+ 82, 72, 105, 220, 33, 81, 82, 72, 42, 72,
+ 317, 43, 44, 111, 45, 31, 32, 96, 72, 34,
+ 35, 46, 47, 96, 60, 223, 30, 224, 29, 28,
+ 25, 63, 115, 37, 27, 24, 62, 41, 38, 72,
+ 60, 81, 82, 72, 33, 61, 121, 116, 53, 61,
+ 122, 88, 94, 96, 321, 117, 118, 26, 317, 352,
+ 125, 36, 323, 127, 203, 349, 350, 351, 353, 303,
+ 304, 96, 367, 81, 82, 72, 60, 255, 42, 209,
+ 101, 43, 44, 122, 45, 31, 32, 185, 94, 34,
+ 35, 46, 47, 186, 60, 191, 30, 61, 29, 28,
+ 25, 63, 321, 37, 27, 24, 62, 41, 38, 188,
+ 323, 122, 203, 122, 33, 61, 82, 72, 53, 336,
+ 335, 182, 181, 179, 180, 177, 173, 26, 176, 174,
+ 199, 36, 81, 82, 72, 81, 82, 72, 81, 82,
+ 72, 81, 82, 81, 82, 72, 200, 201, 42, 203,
+ 204, 43, 44, 96, 45, 31, 32, 210, 211, 34,
+ 35, 46, 47, 212, 60, 213, 30, 214, 29, 28,
+ 25, 63, 215, 37, 27, 24, 216, 178, 217, 175,
+ 81, 82, 72, 218, 33, 61, 81, 82, 72, 219,
+ 88, 317, 96, 81, 82, 72, 88, 227, 96, 81,
+ 82, 72, 227, 88, 96, 96, 81, 82, 72, 88,
+ 229, 96, 81, 82, 72, 60, 88, 230, 96, 231,
+ 234, 60, 88, 235, 96, 238, 122, 94, 60, 81,
+ 82, 72, 122, 94, 60, 321, 61, 81, 82, 72,
+ 94, 60, 61, 323, 241, 203, 94, 60, 242, 61,
+ 244, 245, 246, 94, 247, 61, 248, 249, 250, 94,
+ 251, 252, 61, 81, 82, 72, 253, 254, 61, 81,
+ 82, 72, 257, 88, 188, 96, 81, 82, 72, 88,
+ 259, 96, 81, 82, 72, 269, 88, 271, 96, 81,
+ 82, 72, 88, 276, 96, 122, 281, 282, 60, 88,
+ 283, 96, 284, 285, 60, 286, 287, 288, 289, 290,
+ 94, 60, 82, 292, 293, 294, 94, 60, 122, 61,
+ 122, 72, 298, 94, 60, 61, 301, 302, 305, 94,
+ 306, 313, 61, 314, 122, 122, 94, 325, 61, 135,
136, 139, 140, 137, 138, 61, 141, 142, 144, 145,
146, 148, 143, 147, 135, 136, 139, 140, 137, 138,
- 219, 141, 142, 144, 145, 146, 148, 143, 147, 227,
- 227, 188, 229, 230, 231, 234, 235, 135, 136, 139,
- 140, 137, 138, 207, 141, 142, 144, 145, 146, 148,
- 143, 147, 238, 188, 122, 122, 241, 242, 205, 135,
- 136, 139, 140, 137, 138, 244, 141, 142, 144, 145,
- 146, 148, 143, 147, 188, 245, 246, 247, 248, 249,
- 135, 136, 139, 140, 137, 138, 250, 141, 142, 144,
+ 326, 141, 142, 144, 145, 146, 148, 143, 147, 327,
+ 328, 188, 97, 333, 275, 122, 33, 135, 136, 139,
+ 140, 137, 138, 205, 141, 142, 144, 145, 146, 148,
+ 143, 147, 188, 188, 333, 122, 346, 347, 207, 135,
+ 136, 139, 140, 137, 138, 348, 141, 142, 144, 145,
+ 146, 148, 143, 147, 188, 356, 357, 358, 359, 360,
+ 135, 136, 139, 140, 137, 138, 361, 141, 142, 144,
145, 146, 148, 143, 147, 135, 136, 139, 140, 137,
- 138, 251, 141, 142, 144, 145, 146, 148, 143, 147,
- 135, 136, 139, 140, 137, 138, 252, 141, 142, 144,
+ 138, 362, 141, 142, 144, 145, 146, 148, 143, 147,
+ 135, 136, 139, 140, 137, 138, 122, 141, 142, 144,
145, 146, 148, 143, 147, 135, 136, 139, 140, 137,
- 138, 253, 141, 142, 144, 145, 146, 148, 143, 147,
- 135, 136, 139, 140, 137, 138, 254, 141, 142, 144,
+ 138, 364, 141, 142, 144, 145, 146, 148, 143, 147,
+ 135, 136, 139, 140, 137, 138, 72, 141, 142, 144,
145, 146, 148, 143, 147, 135, 136, 139, 140, 137,
- 138, 257, 141, 142, 144, 145, 146, 148, 143, 147,
- 135, 136, 139, 140, 137, 138, 188, 141, 142, 144,
+ 138, 33, 141, 142, 144, 145, 146, 148, 143, 147,
+ 135, 136, 139, 140, 137, 138, 378, 141, 142, 144,
145, 146, 148, 143, 147, 135, 136, 139, 140, 137,
- 138, 259, 141, 142, 144, 145, 146, 148, 143, 147,
- 269, 271, 276, 122, 281, 282, 283, 284, 285 ]
+ 138, 379, 141, 142, 144, 145, 146, 148, 143, 147,
+ 380, 381, 382, 383, 385, 386, 390, 72, 392 ]
racc_action_check = [
- 309, 65, 312, 3, 72, 343, 188, 188, 188, 70,
- 240, 232, 105, 295, 28, 36, 48, 29, 188, 48,
- 296, 309, 65, 312, 3, 232, 383, 188, 280, 280,
- 36, 188, 249, 186, 186, 186, 186, 295, 97, 97,
- 97, 97, 272, 250, 296, 105, 251, 28, 188, 383,
- 29, 188, 188, 70, 188, 188, 188, 343, 252, 188,
- 188, 188, 188, 72, 188, 240, 188, 38, 188, 188,
- 188, 188, 253, 188, 188, 188, 225, 225, 225, 295,
- 309, 65, 312, 3, 188, 188, 296, 36, 225, 36,
- 186, 383, 224, 224, 272, 97, 254, 225, 358, 358,
- 38, 225, 209, 209, 209, 209, 187, 184, 187, 358,
- 320, 320, 38, 184, 256, 88, 88, 88, 225, 260,
- 337, 225, 225, 263, 225, 225, 225, 88, 265, 225,
- 225, 225, 225, 337, 225, 153, 225, 153, 225, 225,
- 225, 225, 266, 225, 225, 225, 2, 2, 2, 269,
- 88, 199, 199, 199, 225, 225, 270, 55, 2, 209,
- 275, 199, 88, 199, 337, 55, 55, 2, 301, 342,
- 277, 2, 337, 291, 337, 342, 342, 342, 342, 95,
- 95, 301, 357, 357, 357, 357, 199, 222, 2, 222,
- 292, 2, 2, 297, 2, 2, 2, 299, 199, 2,
- 2, 2, 2, 300, 2, 302, 2, 199, 2, 2,
- 2, 2, 301, 2, 2, 2, 0, 0, 0, 303,
- 301, 304, 301, 306, 2, 2, 293, 293, 0, 229,
- 229, 98, 98, 98, 98, 98, 98, 0, 98, 98,
- 307, 0, 326, 326, 326, 75, 75, 75, 238, 238,
- 238, 98, 98, 234, 234, 234, 308, 313, 0, 315,
- 323, 0, 0, 98, 0, 0, 0, 325, 328, 0,
- 0, 0, 0, 331, 0, 333, 0, 338, 0, 0,
- 0, 0, 339, 0, 0, 0, 340, 98, 347, 98,
- 42, 42, 42, 349, 0, 0, 114, 114, 114, 350,
- 42, 363, 42, 76, 76, 76, 114, 351, 114, 134,
- 134, 134, 352, 76, 363, 76, 116, 116, 116, 134,
- 353, 134, 200, 200, 200, 42, 116, 354, 116, 355,
- 356, 114, 200, 359, 200, 361, 365, 42, 76, 360,
- 360, 360, 366, 114, 134, 363, 42, 34, 34, 34,
- 76, 116, 114, 363, 368, 363, 134, 200, 371, 76,
- 372, 373, 376, 116, 379, 134, 384, 385, 387, 200,
- 1, 27, 116, 94, 94, 94, 30, 31, 200, 35,
- 35, 35, 32, 94, 37, 94, 43, 43, 43, 35,
- 41, 35, 45, 45, 45, 44, 43, 46, 43, 113,
- 113, 113, 45, 47, 45, 53, 58, 60, 94, 113,
- 63, 113, 64, 68, 35, 99, 101, 102, 103, 109,
- 94, 43, 111, 112, 115, 117, 35, 45, 118, 94,
- 121, 123, 132, 43, 113, 35, 173, 174, 175, 45,
- 176, 177, 43, 178, 179, 180, 113, 181, 45, 150,
- 150, 150, 150, 150, 150, 113, 150, 150, 150, 150,
- 150, 150, 150, 150, 133, 133, 133, 133, 133, 133,
- 182, 133, 133, 133, 133, 133, 133, 133, 133, 189,
- 190, 108, 191, 192, 193, 194, 197, 108, 108, 108,
- 108, 108, 108, 150, 108, 108, 108, 108, 108, 108,
- 108, 108, 201, 110, 202, 203, 204, 205, 133, 110,
- 110, 110, 110, 110, 110, 210, 110, 110, 110, 110,
- 110, 110, 110, 110, 107, 211, 212, 213, 214, 215,
- 107, 107, 107, 107, 107, 107, 216, 107, 107, 107,
- 107, 107, 107, 107, 107, 236, 236, 236, 236, 236,
- 236, 217, 236, 236, 236, 236, 236, 236, 236, 236,
- 195, 195, 195, 195, 195, 195, 218, 195, 195, 195,
+ 3, 65, 309, 312, 72, 272, 0, 0, 0, 70,
+ 240, 232, 28, 295, 29, 36, 48, 105, 0, 48,
+ 296, 3, 65, 309, 312, 232, 383, 0, 95, 95,
+ 36, 0, 1, 97, 97, 97, 97, 295, 186, 186,
+ 186, 186, 343, 27, 296, 28, 30, 29, 0, 383,
+ 105, 0, 0, 70, 0, 0, 0, 272, 31, 0,
+ 0, 0, 0, 72, 0, 240, 0, 38, 0, 0,
+ 0, 0, 32, 0, 0, 0, 2, 2, 2, 295,
+ 3, 65, 309, 312, 0, 0, 296, 36, 2, 36,
+ 97, 383, 224, 224, 343, 186, 37, 2, 358, 358,
+ 38, 2, 209, 209, 209, 209, 153, 184, 153, 358,
+ 229, 229, 38, 184, 41, 88, 88, 88, 2, 44,
+ 301, 2, 2, 46, 2, 2, 2, 88, 47, 2,
+ 2, 2, 2, 301, 2, 187, 2, 187, 2, 2,
+ 2, 2, 53, 2, 2, 2, 188, 188, 188, 58,
+ 88, 35, 35, 35, 2, 2, 60, 55, 188, 209,
+ 63, 35, 88, 35, 301, 55, 55, 188, 337, 342,
+ 64, 188, 301, 68, 301, 342, 342, 342, 342, 280,
+ 280, 337, 357, 357, 357, 357, 35, 222, 188, 222,
+ 99, 188, 188, 101, 188, 188, 188, 102, 35, 188,
+ 188, 188, 188, 103, 188, 109, 188, 35, 188, 188,
+ 188, 188, 337, 188, 188, 188, 225, 225, 225, 111,
+ 337, 112, 337, 115, 188, 188, 293, 293, 225, 320,
+ 320, 98, 98, 98, 98, 98, 98, 225, 98, 98,
+ 117, 225, 34, 34, 34, 75, 75, 75, 234, 234,
+ 234, 98, 98, 238, 238, 238, 118, 121, 225, 123,
+ 132, 225, 225, 98, 225, 225, 225, 173, 174, 225,
+ 225, 225, 225, 175, 225, 176, 225, 177, 225, 225,
+ 225, 225, 178, 225, 225, 225, 179, 98, 180, 98,
+ 42, 42, 42, 181, 225, 225, 43, 43, 43, 182,
+ 42, 363, 42, 45, 45, 45, 43, 189, 43, 76,
+ 76, 76, 190, 45, 363, 45, 94, 94, 94, 76,
+ 191, 76, 113, 113, 113, 42, 94, 192, 94, 193,
+ 194, 43, 113, 197, 113, 201, 202, 42, 45, 326,
+ 326, 326, 203, 43, 76, 363, 42, 360, 360, 360,
+ 45, 94, 43, 363, 204, 363, 76, 113, 205, 45,
+ 210, 211, 212, 94, 213, 76, 214, 215, 216, 113,
+ 217, 218, 94, 114, 114, 114, 219, 221, 113, 116,
+ 116, 116, 226, 114, 227, 114, 134, 134, 134, 116,
+ 228, 116, 199, 199, 199, 235, 134, 239, 134, 200,
+ 200, 200, 199, 241, 199, 242, 244, 245, 114, 200,
+ 246, 200, 247, 248, 116, 249, 250, 251, 252, 253,
+ 114, 134, 254, 256, 260, 263, 116, 199, 265, 114,
+ 266, 269, 270, 134, 200, 116, 275, 277, 291, 199,
+ 292, 297, 134, 299, 300, 302, 200, 303, 199, 133,
+ 133, 133, 133, 133, 133, 200, 133, 133, 133, 133,
+ 133, 133, 133, 133, 150, 150, 150, 150, 150, 150,
+ 304, 150, 150, 150, 150, 150, 150, 150, 150, 306,
+ 307, 107, 308, 313, 315, 323, 325, 107, 107, 107,
+ 107, 107, 107, 133, 107, 107, 107, 107, 107, 107,
+ 107, 107, 328, 108, 331, 333, 338, 339, 150, 108,
+ 108, 108, 108, 108, 108, 340, 108, 108, 108, 108,
+ 108, 108, 108, 108, 110, 347, 349, 350, 351, 352,
+ 110, 110, 110, 110, 110, 110, 353, 110, 110, 110,
+ 110, 110, 110, 110, 110, 83, 83, 83, 83, 83,
+ 83, 354, 83, 83, 83, 83, 83, 83, 83, 83,
+ 195, 195, 195, 195, 195, 195, 355, 195, 195, 195,
195, 195, 195, 195, 195, 196, 196, 196, 196, 196,
- 196, 219, 196, 196, 196, 196, 196, 196, 196, 196,
- 198, 198, 198, 198, 198, 198, 221, 198, 198, 198,
+ 196, 356, 196, 196, 196, 196, 196, 196, 196, 196,
+ 198, 198, 198, 198, 198, 198, 359, 198, 198, 198,
198, 198, 198, 198, 198, 206, 206, 206, 206, 206,
- 206, 226, 206, 206, 206, 206, 206, 206, 206, 206,
- 237, 237, 237, 237, 237, 237, 227, 237, 237, 237,
- 237, 237, 237, 237, 237, 83, 83, 83, 83, 83,
- 83, 228, 83, 83, 83, 83, 83, 83, 83, 83,
- 235, 239, 241, 242, 244, 245, 246, 247, 248 ]
+ 206, 361, 206, 206, 206, 206, 206, 206, 206, 206,
+ 236, 236, 236, 236, 236, 236, 365, 236, 236, 236,
+ 236, 236, 236, 236, 236, 237, 237, 237, 237, 237,
+ 237, 366, 237, 237, 237, 237, 237, 237, 237, 237,
+ 368, 371, 372, 373, 376, 379, 384, 385, 387 ]
racc_action_pointer = [
- 212, 370, 142, -1, nil, nil, nil, nil, nil, nil,
+ 2, 32, 72, -4, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 341, -15, -12,
- 350, 303, 308, nil, 320, 352, 13, 355, 38, nil,
- nil, 308, 263, 359, 366, 365, 368, 374, -30, nil,
- nil, nil, nil, 388, nil, 127, nil, nil, 377, nil,
- 333, nil, nil, 385, 412, -3, nil, nil, 388, nil,
- -17, nil, -13, nil, nil, 218, 276, nil, nil, nil,
- nil, nil, nil, 604, nil, nil, nil, nil, 88, nil,
- nil, nil, nil, nil, 346, 152, nil, 12, 224, 398,
- nil, 391, 341, 344, nil, -17, nil, 499, 456, 368,
- 478, 397, 398, 372, 269, 399, 289, 395, 398, nil,
- nil, 404, nil, 351, nil, nil, nil, nil, nil, nil,
- nil, nil, 355, 433, 282, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, 13, -17, -15,
+ 20, -16, -2, nil, 215, 124, 13, 67, 38, nil,
+ nil, 32, 263, 269, 90, 276, 94, 99, -30, nil,
+ nil, nil, nil, 125, nil, 127, nil, nil, 120, nil,
+ 82, nil, nil, 135, 170, -3, nil, nil, 148, nil,
+ -17, nil, -13, nil, nil, 218, 282, nil, nil, nil,
+ nil, nil, nil, 514, nil, nil, nil, nil, 88, nil,
+ nil, nil, nil, nil, 289, 1, nil, 7, 224, 173,
+ nil, 168, 121, 129, nil, -12, nil, 456, 478, 154,
+ 499, 194, 196, 295, 346, 198, 352, 210, 226, nil,
+ nil, 231, nil, 179, nil, nil, nil, nil, nil, nil,
+ nil, nil, 183, 418, 359, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 418, nil, nil, 60, nil, nil, nil, nil, nil, nil,
+ 433, nil, nil, 31, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 358, 359, 360, 362, 363, 365, 366,
- 367, 369, 392, nil, 84, nil, 7, 31, 2, 432,
- 433, 408, 435, 436, 424, 529, 544, 468, 559, 124,
- 295, 425, 479, 480, 480, 490, 574, nil, nil, 76,
- 487, 497, 498, 499, 500, 501, 508, 523, 538, 553,
- nil, 522, 112, nil, 65, 72, 563, 601, 593, 201,
- nil, nil, -36, nil, 226, 576, 514, 589, 221, 603,
- -16, 577, 628, nil, 575, 576, 577, 578, 579, -47,
- -36, -33, -21, -7, 68, nil, 37, nil, nil, nil,
- 101, nil, nil, 75, nil, 103, 117, nil, nil, 120,
- 81, nil, 17, nil, nil, 84, nil, 153, nil, nil,
- -27, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 98, 164, 198, nil, 8, 15, 118, nil, 116,
- 178, 142, 180, 145, 147, nil, 148, 165, 182, -4,
- nil, nil, -2, 240, nil, 233, nil, nil, nil, nil,
- 83, nil, nil, 235, nil, 185, 215, nil, 243, nil,
- nil, 256, nil, 250, nil, nil, nil, 94, 202, 205,
- 238, nil, 156, -20, nil, nil, nil, 262, nil, 219,
- 225, 233, 238, 246, 248, 304, 255, 156, 70, 304,
- 312, 253, nil, 275, nil, 261, 265, nil, 279, nil,
- nil, 330, 285, 284, nil, nil, 285, nil, nil, 338,
- nil, nil, nil, 20, 291, 338, nil, 293, nil, nil,
+ nil, nil, nil, 189, 190, 195, 197, 199, 204, 208,
+ 210, 215, 221, nil, 84, nil, 12, 60, 142, 260,
+ 265, 246, 279, 281, 269, 529, 544, 315, 559, 365,
+ 372, 258, 311, 317, 328, 341, 574, nil, nil, 76,
+ 332, 333, 334, 336, 338, 339, 340, 342, 343, 348,
+ nil, 303, 112, nil, 65, 212, 334, 359, 342, 82,
+ nil, nil, -36, nil, 221, 321, 589, 604, 226, 349,
+ -16, 328, 380, nil, 327, 328, 331, 333, 334, 336,
+ 337, 338, 339, 340, 394, nil, 346, nil, nil, nil,
+ 406, nil, nil, 377, nil, 403, 405, nil, nil, 402,
+ 357, nil, -20, nil, nil, 360, nil, 420, nil, nil,
+ 124, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, 363, 414, 198, nil, 8, 15, 366, nil, 362,
+ 419, 94, 420, 373, 396, nil, 404, 405, 408, -2,
+ nil, nil, -1, 466, nil, 458, nil, nil, nil, nil,
+ 202, nil, nil, 460, nil, 404, 312, nil, 477, nil,
+ nil, 487, nil, 480, nil, nil, nil, 142, 431, 430,
+ 467, nil, 156, 17, nil, nil, nil, 499, nil, 452,
+ 453, 454, 455, 462, 472, 541, 506, 156, 70, 567,
+ 320, 529, nil, 275, nil, 551, 564, nil, 575, nil,
+ nil, 623, 577, 576, nil, nil, 577, nil, nil, 629,
+ nil, nil, nil, 20, 581, 628, nil, 583, nil, nil,
nil, nil, nil ]
racc_action_default = [
@@ -264,38 +264,38 @@ racc_action_default = [
-97, -101, -96 ]
racc_goto_table = [
- 39, 106, 39, 68, 78, 65, 123, 66, 77, 184,
- 2, 9, 40, 9, 40, 153, 274, 83, 189, 190,
- 194, 192, 193, 197, 107, 108, 261, 110, 39, 39,
- 310, 310, 71, 73, 79, 260, 233, 344, 39, 332,
- 40, 40, 104, 277, 109, 78, 171, 112, 322, 132,
- 40, 291, 309, 312, 226, 228, 1, 341, 133, 311,
- 311, 202, 272, 377, 316, 68, 343, 155, 167, 126,
- 172, 128, 129, 243, 264, 79, 150, 389, 232, 263,
- 266, 331, 365, 368, 322, 373, 387, 384, 160, 119,
- 261, 334, 183, 120, 149, 195, 196, 156, 198, 307,
- 168, 161, 162, 324, 222, 39, 163, 164, 158, 187,
- 322, 165, 166, 169, 170, nil, 206, 40, 388, nil,
+ 39, 106, 39, 66, 78, 65, 123, 68, 77, 184,
+ 9, 2, 9, 153, 40, 261, 40, 274, 310, 310,
+ 194, 189, 190, 197, 192, 193, 71, 73, 39, 39,
+ 277, 260, 233, 344, 79, 1, 104, 322, 39, 332,
+ 291, 128, 40, 40, 109, 78, 129, 112, 243, 132,
+ 311, 311, 40, 83, 226, 228, 389, 341, 232, 377,
+ 107, 108, 263, 110, 266, 126, 331, 155, 167, 68,
+ 264, 309, 312, 322, 365, 79, 368, 373, 387, 261,
+ 384, 160, 119, 183, 120, 149, 168, 161, 162, 163,
+ 324, 164, 334, 165, 133, 307, 166, 156, 169, 322,
+ 170, 171, 222, 187, 172, 39, 388, 158, 202, 272,
+ 316, 343, 150, nil, nil, nil, nil, nil, nil, 40,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 258, nil,
- nil, nil, nil, nil, nil, 239, 240, nil, nil, nil,
- 280, nil, nil, nil, nil, 369, 155, nil, nil, nil,
+ nil, 195, 196, nil, 198, nil, nil, nil, nil, nil,
+ nil, 258, nil, nil, 369, 239, 240, nil, nil, nil,
+ 280, nil, 206, nil, nil, nil, 155, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, 295, 296, nil, nil, nil, nil, 155,
- nil, 236, 237, nil, nil, nil, 156, nil, 39, nil,
- nil, nil, nil, nil, 256, nil, nil, 158, 225, 9,
- 40, nil, nil, nil, 267, nil, nil, nil, 78, 156,
- 280, nil, 270, nil, nil, 299, nil, nil, nil, nil,
- 158, nil, nil, nil, nil, 39, nil, nil, 65, 262,
- nil, nil, nil, nil, 268, nil, 9, 40, 79, 340,
- nil, 342, nil, 315, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, 156, nil, 39, nil,
+ nil, nil, nil, nil, 256, nil, 158, nil, 9, 225,
+ nil, nil, 40, nil, 267, nil, nil, nil, 78, 156,
+ 280, nil, 270, nil, nil, 299, nil, 236, 237, 158,
+ nil, nil, nil, nil, nil, 39, nil, nil, 65, 262,
+ nil, nil, nil, nil, 268, 9, nil, nil, 79, 40,
+ nil, 342, 340, 315, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, 337, nil, nil, 297,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 338, 354, nil, nil, nil,
nil, nil, nil, 262, nil, nil, 78, nil, 363, nil,
- 339, nil, nil, nil, nil, nil, nil, nil, nil, 68,
- nil, nil, 68, 329, nil, nil, 330, nil, nil, nil,
+ 339, nil, nil, nil, nil, nil, nil, nil, nil, 329,
+ nil, nil, 330, 68, nil, nil, 68, nil, nil, nil,
nil, 376, nil, nil, nil, nil, 79, 78, nil, nil,
375, 366, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
@@ -305,38 +305,38 @@ racc_goto_table = [
nil, nil, nil, nil, nil, 391 ]
racc_goto_check = [
- 40, 35, 40, 7, 39, 3, 86, 4, 29, 34,
- 2, 12, 43, 12, 43, 37, 89, 30, 5, 5,
- 34, 5, 5, 34, 30, 30, 47, 30, 40, 40,
- 36, 36, 28, 28, 40, 46, 50, 94, 40, 56,
- 43, 43, 28, 31, 40, 39, 84, 40, 75, 29,
- 43, 47, 52, 52, 45, 45, 1, 56, 30, 44,
- 44, 87, 88, 94, 90, 7, 93, 39, 39, 4,
- 85, 6, 27, 38, 50, 40, 30, 42, 48, 49,
- 51, 55, 57, 58, 75, 59, 60, 61, 62, 63,
- 47, 89, 67, 68, 71, 30, 30, 40, 30, 46,
- 73, 76, 77, 31, 37, 40, 78, 79, 12, 28,
- 75, 80, 81, 82, 83, nil, 30, 43, 36, nil,
+ 40, 35, 40, 4, 39, 3, 86, 7, 29, 34,
+ 12, 2, 12, 37, 43, 47, 43, 89, 36, 36,
+ 34, 5, 5, 34, 5, 5, 28, 28, 40, 40,
+ 31, 46, 50, 94, 40, 1, 28, 75, 40, 56,
+ 47, 6, 43, 43, 40, 39, 27, 40, 38, 29,
+ 44, 44, 43, 30, 45, 45, 42, 56, 48, 94,
+ 30, 30, 49, 30, 51, 4, 55, 39, 39, 7,
+ 50, 52, 52, 75, 57, 40, 58, 59, 60, 47,
+ 61, 62, 63, 67, 68, 71, 73, 76, 77, 78,
+ 31, 79, 89, 80, 30, 46, 81, 40, 82, 75,
+ 83, 84, 37, 28, 85, 40, 36, 12, 87, 88,
+ 90, 93, 30, nil, nil, nil, nil, nil, nil, 43,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 5, nil,
- nil, nil, nil, nil, nil, 86, 86, nil, nil, nil,
- 34, nil, nil, nil, nil, 47, 39, nil, nil, nil,
+ nil, 30, 30, nil, 30, nil, nil, nil, nil, nil,
+ nil, 5, nil, nil, 47, 86, 86, nil, nil, nil,
+ 34, nil, 30, nil, nil, nil, 39, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, 34, 34, nil, nil, nil, nil, 39,
- nil, 30, 30, nil, nil, nil, 40, nil, 40, nil,
- nil, nil, nil, nil, 39, nil, nil, 12, 2, 12,
- 43, nil, nil, nil, 39, nil, nil, nil, 39, 40,
- 34, nil, 29, nil, nil, 86, nil, nil, nil, nil,
- 12, nil, nil, nil, nil, 40, nil, nil, 3, 40,
- nil, nil, nil, nil, 40, nil, 12, 43, 40, 5,
- nil, 34, nil, 86, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, 40, nil, 40, nil,
+ nil, nil, nil, nil, 39, nil, 12, nil, 12, 2,
+ nil, nil, 43, nil, 39, nil, nil, nil, 39, 40,
+ 34, nil, 29, nil, nil, 86, nil, 30, 30, 12,
+ nil, nil, nil, nil, nil, 40, nil, nil, 3, 40,
+ nil, nil, nil, nil, 40, 12, nil, nil, 40, 43,
+ nil, 34, 5, 86, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, 86, nil, nil, 40,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, 35, 86, nil, nil, nil,
nil, nil, nil, 40, nil, nil, 39, nil, 86, nil,
- 29, nil, nil, nil, nil, nil, nil, nil, nil, 7,
- nil, nil, 7, 4, nil, nil, 4, nil, nil, nil,
+ 29, nil, nil, nil, nil, nil, nil, nil, nil, 4,
+ nil, nil, 4, 7, nil, nil, 7, nil, nil, nil,
nil, 35, nil, nil, nil, nil, 40, 39, nil, nil,
39, 29, nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
@@ -346,16 +346,16 @@ racc_goto_check = [
nil, nil, nil, nil, nil, 40 ]
racc_goto_pointer = [
- nil, 56, 10, 3, 4, -89, 3, 0, nil, nil,
- nil, nil, 11, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 2, 4, -26,
- -18, -199, nil, nil, -92, -40, -265, -82, -136, -30,
- 0, nil, -306, 12, -236, -135, -194, -203, -116, -153,
- -158, -154, -243, nil, nil, -232, -274, -275, -275, -275,
- -297, -289, -10, 31, nil, nil, nil, -7, 35, nil,
- nil, 6, nil, 2, nil, -253, 3, 4, 8, 9,
- 13, 14, 15, 16, -52, -28, -57, -62, -178, -224,
- -237, nil, nil, -271, -300 ]
+ nil, 35, 11, 3, 0, -86, -27, 4, nil, nil,
+ nil, nil, 10, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, -24, -2, -26,
+ 18, -212, nil, nil, -92, -40, -277, -84, -161, -30,
+ 0, nil, -327, 14, -245, -135, -198, -214, -136, -170,
+ -162, -170, -224, nil, nil, -247, -274, -283, -282, -283,
+ -305, -296, -17, 24, nil, nil, nil, -16, 26, nil,
+ nil, -3, nil, -12, nil, -264, -11, -10, -9, -7,
+ -5, -2, 0, 2, 3, 6, -57, -15, -131, -223,
+ -191, nil, nil, -226, -304 ]
racc_goto_default = [
nil, nil, nil, 3, nil, nil, nil, 4, 5, 6,
diff --git a/test/racc/regress/twowaysql b/test/racc/regress/twowaysql
index 868850b320..219f1a8b04 100644
--- a/test/racc/regress/twowaysql
+++ b/test/racc/regress/twowaysql
@@ -1,6 +1,6 @@
#
# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.4.16
+# This file is automatically generated by Racc 1.5.0
# from Racc grammar file "".
#
@@ -145,34 +145,34 @@ end
racc_action_table = [
8, 36, 9, 37, 12, 13, 10, 11, 14, 15,
- 16, 17, 18, 19, 22, 23, 24, 8, 3, 9,
- 25, 12, 13, 10, 11, 14, 15, 16, 17, 18,
- 19, 22, 23, 24, 8, 38, 9, 46, 12, 13,
+ 16, 17, 18, 19, 22, 23, 24, 8, 38, 9,
+ 3, 12, 13, 10, 11, 14, 15, 16, 17, 18,
+ 19, 22, 23, 24, 8, 25, 9, 40, 12, 13,
10, 11, 14, 15, 16, 17, 18, 19, 22, 23,
- 24, 8, 40, 9, 45, 12, 13, 10, 11, 14,
+ 24, 8, 45, 9, 46, 12, 13, 10, 11, 14,
15, 16, 17, 18, 19, 22, 23, 24, 8, nil,
9, nil, 12, 13, 10, 11, 14, 15, 16, 17,
- 18, 19, 22, 23, 24, 35, 33, 34, 44, 43,
- 31, 32, 31, 32 ]
+ 18, 19, 22, 23, 24, 35, 33, 34, 31, 32,
+ 44, 43, 31, 32 ]
racc_action_check = [
- 42, 24, 42, 24, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 42, 42, 2, 1, 2,
- 3, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 26, 26, 26, 39, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 27, 28, 27, 37, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 41, nil,
- 41, nil, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 22, 22, 22, 34, 34,
- 9, 9, 40, 40 ]
+ 2, 24, 2, 24, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 26, 26, 26,
+ 1, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 3, 27, 28, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 41, 37, 41, 39, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41, 42, nil,
+ 42, nil, 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 22, 22, 22, 9, 9,
+ 34, 34, 40, 40 ]
racc_action_pointer = [
- nil, 18, 15, 20, nil, nil, nil, nil, nil, 84,
+ nil, 20, -2, 35, nil, nil, nil, nil, nil, 82,
nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 77, nil, -7, nil, 32, 49, 47, nil,
- nil, nil, nil, nil, 80, nil, nil, 46, nil, 34,
- 86, 66, -2, nil, nil, nil, nil, nil ]
+ nil, nil, 77, nil, -7, nil, 15, 32, 32, nil,
+ nil, nil, nil, nil, 82, nil, nil, 44, nil, 51,
+ 86, 49, 66, nil, nil, nil, nil, nil ]
racc_action_default = [
-2, -35, -1, -35, -3, -4, -5, -6, -2, -2,
diff --git a/test/racc/test_racc_command.rb b/test/racc/test_racc_command.rb
index b4fc0c6745..0d2c5829e4 100644
--- a/test/racc/test_racc_command.rb
+++ b/test/racc/test_racc_command.rb
@@ -318,5 +318,22 @@ module Racc
assert_debugfile 'tp_plus.y', [21, 0, 0, 0]
assert_output_unchanged 'tp_plus.y'
end
+
+ def test_ifelse
+ omit if RUBY_PLATFORM =~ /java/
+
+ stderr = nil
+ racc "-o#{@TAB_DIR}/ifelse", "#{ASSET_DIR}/ifelse.y", stdout_filter: ->(s) { stderr = s }
+ stderr = stderr.lines[1..-1].join if RUBY_PLATFORM.match?(/java/)
+ assert_equal(<<~STDERR, stderr)
+ 1 useless nonterminals:
+ dummy
+ 2 useless rules:
+ #4 (dummy)
+ #5 (dummy)
+ 1 shift/reduce conflicts
+ Turn on logging with "-v" and check ".output" file for details
+ STDERR
+ end
end
end
diff --git a/test/rdoc/support/test_case.rb b/test/rdoc/support/test_case.rb
index 9a4f04b76e..6d397625e8 100644
--- a/test/rdoc/support/test_case.rb
+++ b/test/rdoc/support/test_case.rb
@@ -49,6 +49,9 @@ class RDoc::TestCase < Test::Unit::TestCase
def setup
super
+ @orig_home = ENV["HOME"]
+ ENV["HOME"] = Dir.tmpdir
+
@top_level = nil
@RM = RDoc::Markup
@@ -70,6 +73,15 @@ class RDoc::TestCase < Test::Unit::TestCase
end
##
+ # Abstract test-case teardown
+
+ def teardown
+ ENV["HOME"] = @orig_home if defined?(@orig_home)
+
+ super
+ end
+
+ ##
# Asserts +path+ is a file
def assert_file path
diff --git a/test/rdoc/test_rdoc_context_section.rb b/test/rdoc/test_rdoc_context_section.rb
index c520ad05a5..24c68c49dd 100644
--- a/test/rdoc/test_rdoc_context_section.rb
+++ b/test/rdoc/test_rdoc_context_section.rb
@@ -143,13 +143,5 @@ class TestRDocContextSection < RDoc::TestCase
assert_equal doc(other_comment.parse), loaded.comments
end
- def test_sequence
- _, err = verbose_capture_output do
- assert_match(/\ASEC\d{5}\Z/, @s.sequence)
- end
-
- assert_equal "#{@S}#sequence is deprecated, use #aref\n", err
- end
-
end
diff --git a/test/rdoc/test_rdoc_markdown.rb b/test/rdoc/test_rdoc_markdown.rb
index 021d94297b..ad53e9473c 100644
--- a/test/rdoc/test_rdoc_markdown.rb
+++ b/test/rdoc/test_rdoc_markdown.rb
@@ -8,6 +8,8 @@ require 'rdoc/markdown'
class TestRDocMarkdown < RDoc::TestCase
def setup
+ super
+
@RM = RDoc::Markup
@parser = RDoc::Markdown.new
@@ -141,7 +143,7 @@ a block quote
end
def test_parse_code_github
- doc = parse <<-MD
+ doc = <<-MD
Example:
```
@@ -154,11 +156,25 @@ code goes here
para("Example:"),
verb("code goes here\n"))
- assert_equal expected, doc
+ assert_equal expected, parse(doc)
+ assert_equal expected, parse(doc.sub(/^\n/, ''))
+
+ @parser.github = false
+
+ expected =
+ doc(para("Example:"),
+ para("<code>\n""code goes here\n</code>"))
+
+ assert_equal expected, parse(doc)
+
+ expected =
+ doc(para("Example:\n<code>\n""code goes here\n</code>"))
+
+ assert_equal expected, parse(doc.sub(/^\n/, ''))
end
def test_parse_code_github_format
- doc = parse <<-MD
+ doc = <<-MD
Example:
``` ruby
@@ -174,7 +190,21 @@ code goes here
para("Example:"),
code)
- assert_equal expected, doc
+ assert_equal expected, parse(doc)
+ assert_equal expected, parse(doc.sub(/^\n/, ''))
+
+ @parser.github = false
+
+ expected =
+ doc(para("Example:"),
+ para("<code>ruby\n""code goes here\n</code>"))
+
+ assert_equal expected, parse(doc)
+
+ expected =
+ doc(para("Example:\n<code>ruby\n""code goes here\n</code>"))
+
+ assert_equal expected, parse(doc.sub(/^\n/, ''))
end
def test_parse_definition_list
@@ -1010,6 +1040,29 @@ and an extra note.[^2]
assert_equal expected, doc
end
+ def test_gfm_table
+ doc = parse <<~MD
+ | | |compare-ruby|built-ruby|
+ |------|:----------------|-----------:|---------:|
+ |test | 1 | 11.618M| 10.757M|
+ | | | 1.08x| -|
+ |test | 10 | 1.849M| 1.723M|
+ | | | 1.07x| -|
+ MD
+
+ head = ["", "", "compare-ruby", "built-ruby"]
+ align = [nil, :left, :right, :right]
+ body = [
+ ["test", "1", "11.618M", "10.757M"],
+ ["", "", "1.08x", "-"],
+ ["test", "10", "1.849M", "1.723M"],
+ ["", "", "1.07x", "-"],
+ ]
+ expected = doc(@RM::Table.new(head, align, body))
+
+ assert_equal expected, doc
+ end
+
def parse text
@parser.parse text
end
diff --git a/test/rdoc/test_rdoc_markup_attribute_manager.rb b/test/rdoc/test_rdoc_markup_attribute_manager.rb
index a180666867..944364ba89 100644
--- a/test/rdoc/test_rdoc_markup_attribute_manager.rb
+++ b/test/rdoc/test_rdoc_markup_attribute_manager.rb
@@ -172,22 +172,25 @@ class TestRDocMarkupAttributeManager < RDoc::TestCase
def test_convert_attrs
str = '+foo+'.dup
- attrs = RDoc::Markup::AttrSpan.new str.length
+ attrs = RDoc::Markup::AttrSpan.new str.length, @am.exclusive_bitmap
+ @am.convert_attrs str, attrs, true
@am.convert_attrs str, attrs
assert_equal "\000foo\000", str
str = '+:foo:+'.dup
- attrs = RDoc::Markup::AttrSpan.new str.length
+ attrs = RDoc::Markup::AttrSpan.new str.length, @am.exclusive_bitmap
+ @am.convert_attrs str, attrs, true
@am.convert_attrs str, attrs
assert_equal "\000:foo:\000", str
str = '+x-y+'.dup
- attrs = RDoc::Markup::AttrSpan.new str.length
+ attrs = RDoc::Markup::AttrSpan.new str.length, @am.exclusive_bitmap
+ @am.convert_attrs str, attrs, true
@am.convert_attrs str, attrs
assert_equal "\000x-y\000", str
@@ -243,6 +246,22 @@ class TestRDocMarkupAttributeManager < RDoc::TestCase
output('unhandled <p>tag</p> unchanged')
end
+ def test_exclude_tag
+ assert_equal '<CODE>aaa</CODE>[:symbol]', output('+aaa+[:symbol]')
+ assert_equal '<CODE>aaa[:symbol]</CODE>', output('+aaa[:symbol]+')
+ assert_equal 'aaa[:symbol]', output('aaa[:symbol]')
+ assert_equal '<B><CODE>index</CODE></B>', output('<b><tt>index</tt></b>')
+ end
+
+ def test_exclude_tag_flow
+ assert_equal [@tt_on, "aaa", @tt_off, "[:symbol]"],
+ @am.flow("+aaa+[:symbol]")
+ assert_equal [@tt_on, "aaa[:symbol]", @tt_off],
+ @am.flow("+aaa[:symbol]+")
+ assert_equal ["aaa[:symbol]"],
+ @am.flow("aaa[:symbol]")
+ end
+
def test_html_like_em_bold
assert_equal ["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off],
@am.flow("cat <i>and </i><b>dog</b>")
diff --git a/test/rdoc/test_rdoc_markup_to_html.rb b/test/rdoc/test_rdoc_markup_to_html.rb
index fb94269064..29da968abc 100644
--- a/test/rdoc/test_rdoc_markup_to_html.rb
+++ b/test/rdoc/test_rdoc_markup_to_html.rb
@@ -704,6 +704,17 @@ EXPECTED
assert_equal "\n<p><a href=\"irc://irc.freenode.net/#ruby-lang\">ruby-lang</a></p>\n", result
end
+ def test_convert_with_exclude_tag
+ assert_equal "\n<p><code>aaa</code>[:symbol]</p>\n", @to.convert('+aaa+[:symbol]')
+ assert_equal "\n<p><code>aaa[:symbol]</code></p>\n", @to.convert('+aaa[:symbol]+')
+ assert_equal "\n<p><a href=\":symbol\">aaa</a></p>\n", @to.convert('aaa[:symbol]')
+ end
+
+ def test_convert_underscore_adjacent_to_code
+ assert_equal "\n<p><code>aaa</code>_</p>\n", @to.convert(%q{+aaa+_})
+ assert_equal "\n<p>`<code>i386-mswin32_</code><em>MSRTVERSION</em>&#39;</p>\n", @to.convert(%q{`+i386-mswin32_+_MSRTVERSION_'})
+ end
+
def test_gen_url
assert_equal '<a href="example">example</a>',
@to.gen_url('link:example', 'example')
@@ -727,6 +738,27 @@ EXPECTED
assert_equal '<img src="https://example.com/image.png" />', @to.gen_url('https://example.com/image.png', 'ignored')
end
+ def test_gen_url_rdoc_file
+ assert_equal '<a href="doc/example_rdoc.html">example</a>',
+ @to.gen_url('doc/example.rdoc', 'example')
+ assert_equal '<a href="../ex_doc/example_rdoc.html">example</a>',
+ @to.gen_url('../ex.doc/example.rdoc', 'example')
+ end
+
+ def test_gen_url_md_file
+ assert_equal '<a href="doc/example_md.html">example</a>',
+ @to.gen_url('doc/example.md', 'example')
+ assert_equal '<a href="../ex_doc/example_md.html">example</a>',
+ @to.gen_url('../ex.doc/example.md', 'example')
+ end
+
+ def test_gen_url_rb_file
+ assert_equal '<a href="doc/example_rb.html">example</a>',
+ @to.gen_url('doc/example.rb', 'example')
+ assert_equal '<a href="../ex_doc/example_rb.html">example</a>',
+ @to.gen_url('../ex.doc/example.rb', 'example')
+ end
+
def test_handle_regexp_HYPERLINK_link
target = RDoc::Markup::RegexpHandling.new 0, 'link:README.txt'
diff --git a/test/rdoc/test_rdoc_markup_to_html_crossref.rb b/test/rdoc/test_rdoc_markup_to_html_crossref.rb
index bac2569f87..f6fabfb7db 100644
--- a/test/rdoc/test_rdoc_markup_to_html_crossref.rb
+++ b/test/rdoc/test_rdoc_markup_to_html_crossref.rb
@@ -89,6 +89,20 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase
assert_equal para("<a href=\"C1.html#method-c-25\"><code>C1::%</code></a>"), result
end
+ def test_convert_RDOCLINK_rdoc_ref_method_escape_html
+ m = @c1.add_method RDoc::AnyMethod.new nil, '<<'
+ m.singleton = false
+
+ result = @to.convert 'rdoc-ref:C1#<<'
+
+ assert_equal para("<a href=\"C1.html#method-i-3C-3C\"><code>C1#&lt;&lt;</code></a>"), result
+ m.singleton = true
+
+ result = @to.convert 'rdoc-ref:C1::<<'
+
+ assert_equal para("<a href=\"C1.html#method-c-3C-3C\"><code>C1::&lt;&lt;</code></a>"), result
+ end
+
def test_convert_RDOCLINK_rdoc_ref_method_percent_label
m = @c1.add_method RDoc::AnyMethod.new nil, '%'
m.singleton = false
@@ -137,6 +151,13 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase
REGEXP_HANDLING('#m')
end
+ def test_handle_regexp_CROSSREF_with_arg_looks_like_TIDYLINK
+ result = @to.convert 'C1.m[:sym]'
+
+ assert_equal para("<a href=\"C1.html#method-c-m\"><code>C1.m[:sym]</code></a>"), result,
+ 'C1.m[:sym]'
+ end
+
def test_handle_regexp_HYPERLINK_rdoc
readme = @store.add_file 'README.txt'
readme.parser = RDoc::Parser::Simple
diff --git a/test/rdoc/test_rdoc_markup_to_markdown.rb b/test/rdoc/test_rdoc_markup_to_markdown.rb
index 4d3a005381..c8c5fd4d52 100644
--- a/test/rdoc/test_rdoc_markup_to_markdown.rb
+++ b/test/rdoc/test_rdoc_markup_to_markdown.rb
@@ -363,9 +363,9 @@ words words words words
def test_convert_TIDYLINK
result = @to.convert \
- '{DSL}[http://en.wikipedia.org/wiki/Domain-specific_language]'
+ '{DSL}[https://en.wikipedia.org/wiki/Domain-specific_language]'
- expected = "[DSL](http://en.wikipedia.org/wiki/Domain-specific_language)\n"
+ expected = "[DSL](https://en.wikipedia.org/wiki/Domain-specific_language)\n"
assert_equal expected, result
end
diff --git a/test/rdoc/test_rdoc_parser_changelog.rb b/test/rdoc/test_rdoc_parser_changelog.rb
index cb6406259c..6584840572 100644
--- a/test/rdoc/test_rdoc_parser_changelog.rb
+++ b/test/rdoc/test_rdoc_parser_changelog.rb
@@ -14,6 +14,8 @@ class TestRDocParserChangeLog < RDoc::TestCase
def teardown
@tempfile.close!
+
+ super
end
def test_class_can_parse
@@ -210,6 +212,8 @@ Mon Dec 3 20:28:02 2012 Koichi Sasada <ko1@atdot.net>
change condition of using `opt_send_simple'.
More method invocations can be simple.
+commit\ 8187228de0142d3ac7950b7d977c2849e934c637
+
Other note that will be ignored
ChangeLog
@@ -268,6 +272,24 @@ Other note that will be ignored
assert_equal expected, parser.parse_entries
end
+ def test_parse_entries_git
+ parser = util_parser <<-ChangeLog
+commit\ 709bed2afaee50e2ce803f87bf1ee8291bea41e3
+ Author: git <svn-admin@ruby-lang.org>
+ Date: 2021-01-21 01:03:52 +0900
+
+ * 2021-01-21 [ci skip]
+ChangeLog
+
+ expected = [
+ [ "709bed2afaee50e2ce80",
+ [ "git", "svn-admin@ruby-lang.org",
+ "2021-01-21 01:03:52 +0900",
+ "* 2021-01-21 [ci skip]\n"]]]
+
+ assert_equal expected, parser.parse_entries
+ end
+
def test_scan
parser = util_parser <<-ChangeLog
Tue Dec 4 08:32:10 2012 Eric Hodel <drbrain@segment7.net>
@@ -307,10 +329,157 @@ Mon Dec 3 20:37:22 2012 Koichi Sasada <ko1@atdot.net>
assert_equal expected, @top_level.comment
end
+ def test_scan_git
+ parser = util_parser <<-ChangeLog
+commit\ 38816887962ec167ee46acf500f68df5c3013163
+Author: git <svn-admin@ruby-lang.org>
+Date: Sun Jan 24 14:35:51 2021 +0900
+
+ * 2021-01-24 [ci skip]
+
+commit\ db7d0b89f6eca66cc7eb155c95f9123133da1ffc
+Author: git <svn-admin@ruby-lang.org>
+Date: Sat, 23 Jan 2021 06:01:39 +0900
+
+ * 2021-01-23 [ci skip]
+
+commit\ a3efbda7128ef20b55505b32d1608ea48f80af4a
+Author: git <svn-admin@ruby-lang.org>
+Date: 2021-01-22T02:49:39+09:00
+
+ * 2021-01-22 [ci skip]
+
+commit\ 709bed2afaee50e2ce803f87bf1ee8291bea41e3
+ Author: git <svn-admin@ruby-lang.org>
+ Date: 2021-01-21 01:03:52 +0900
+
+ * 2021-01-21 [ci skip]
+
+commit\ a8dc5156e183489c5121fb1759bda5d9406d9175
+ Author: git <svn-admin@ruby-lang.org>
+ Date: 2021-01-20 01:58:26 +0900
+
+ * 2021-01-20 [ci skip]
+
+commit\ de5f8a92d5001799bedb3b1a271a2d9b23c6c8fb
+ Author: Masataka Pocke Kuwabara <kuwabara@pocke.me>
+ Date: 2021-01-01 14:25:08 +0900
+
+ Make args info for RubyVM::AST to available on endless method without parens
+
+ Problem
+ ===
+
+ Arguments information is missing for endless method without parens.
+ For example:
+
+ ```ruby
+ # ok
+ ```
+
+ It causes an error if a program expects `args` node exists.
+
+ Solution
+ ===
+
+ Call `new_args` on this case.
+ChangeLog
+
+ parser.scan
+
+ expected = doc(
+ head(1, File.basename(@tempfile.path)),
+ blank_line,
+ head(2, '2021-01-24'),
+ blank_line,
+ log_entry(nil, '38816887962ec167ee46',
+ 'git', 'svn-admin@ruby-lang.org', 'Sun Jan 24 14:35:51 2021 +0900',
+ [list(:BULLET, item(nil, para('2021-01-24 [ci skip]')))]),
+ head(2, '2021-01-23'),
+ blank_line,
+ log_entry(nil, 'db7d0b89f6eca66cc7eb',
+ 'git', 'svn-admin@ruby-lang.org', 'Sat, 23 Jan 2021 06:01:39 +0900',
+ [list(:BULLET, item(nil, para('2021-01-23 [ci skip]')))]),
+ head(2, '2021-01-22'),
+ blank_line,
+ log_entry(nil, 'a3efbda7128ef20b5550',
+ 'git', 'svn-admin@ruby-lang.org', '2021-01-22T02:49:39+09:00',
+ [list(:BULLET, item(nil, para('2021-01-22 [ci skip]')))]),
+ head(2, '2021-01-21'),
+ blank_line,
+ log_entry(nil, '709bed2afaee50e2ce80',
+ 'git', 'svn-admin@ruby-lang.org', '2021-01-21 01:03:52 +0900',
+ [list(:BULLET, item(nil, para('2021-01-21 [ci skip]')))]),
+ head(2, '2021-01-20'),
+ blank_line,
+ log_entry(nil, 'a8dc5156e183489c5121',
+ 'git', 'svn-admin@ruby-lang.org', '2021-01-20 01:58:26 +0900',
+ [list(:BULLET, item(nil, para('2021-01-20 [ci skip]')))]),
+ head(2, '2021-01-01'),
+ blank_line,
+ log_entry(nil, 'de5f8a92d5001799bedb',
+ 'Masataka Pocke Kuwabara', 'kuwabara@pocke.me', '2021-01-01 14:25:08 +0900',
+ [head(4, 'Make args info for RubyVM::AST to available on endless method without parens'),
+ head(5, 'Problem'),
+ para("Arguments information is missing for endless method without parens.\n" +
+ "For example:"),
+ verb("# ok\n").tap {|v| v.format = :ruby},
+ para('It causes an error if a program expects <code>args</code> node exists.'),
+ head(5, 'Solution'),
+ para('Call <code>new_args</code> on this case.')]))
+
+ expected.file = @top_level
+
+ assert_equal expected, @top_level.comment
+ end
+
+ def test_scan_git_commit_date
+ parser = util_parser <<-ChangeLog
+commit\ ee1e690a2df901adb279d7a63fbd92c64e0a5ae6
+ Author: Igor Zubkov <igor.zubkov@gmail.com>
+ AuthorDate: 2016-10-25 03:56:11 +0900
+ Commit: Nobuyoshi Nakada <nobu@ruby-lang.org>
+ CommitDate: 2021-01-07 13:40:42 +0900
+
+ We don't need "require 'uri'" after "require 'net/http'".
+
+commit\ 4d0985a7bd8f591dff4b430e288bfd83af782e51
+ Author: git <svn-admin@ruby-lang.org>
+ AuthorDate: 2021-01-07 10:21:34 +0900
+ Commit: git <svn-admin@ruby-lang.org>
+ CommitDate: 2021-01-07 10:21:34 +0900
+
+ * 2021-01-07 [ci skip]
+ChangeLog
+
+ parser.scan
+
+ expected = doc(
+ head(1, File.basename(@tempfile.path)),
+ blank_line,
+ head(2, "2021-01-07"),
+ blank_line,
+ log_entry(nil, 'ee1e690a2df901adb279',
+ 'Igor Zubkov', 'igor.zubkov@gmail.com',
+ '2016-10-25 03:56:11 +0900',
+ [head(4, %[We don't need "require 'uri'" after "require 'net/http'".])]),
+ log_entry(nil, '4d0985a7bd8f591dff4b',
+ 'git', 'svn-admin@ruby-lang.org',
+ '2021-01-07 10:21:34 +0900',
+ [list(:BULLET, item(nil, para("2021-01-07 [ci skip]")))]))
+
+ expected.file = @top_level
+
+ assert_equal expected, @top_level.comment
+ end
+
def util_parser content = ''
RDoc::Parser::ChangeLog.new \
@top_level, @tempfile.path, content, @options, @stats
end
+ def log_entry(*a)
+ RDoc::Parser::ChangeLog::Git::LogEntry.new(*a)
+ end
end
diff --git a/test/rdoc/test_rdoc_rdoc.rb b/test/rdoc/test_rdoc_rdoc.rb
index f3228c31e0..7b84bb698a 100644
--- a/test/rdoc/test_rdoc_rdoc.rb
+++ b/test/rdoc/test_rdoc_rdoc.rb
@@ -73,6 +73,11 @@ class TestRDocRDoc < RDoc::TestCase
b = File.expand_path '../test_rdoc_text.rb', __FILE__
assert_equal [a, b], @rdoc.gather_files([b, a, b])
+
+ assert_empty @rdoc.gather_files([b, a, b])
+
+ @rdoc.last_modified[a] -= 10
+ assert_equal [a, b], @rdoc.gather_files([b, a, b])
end
def test_handle_pipe
@@ -128,6 +133,29 @@ class TestRDocRDoc < RDoc::TestCase
end
end
+ def test_load_options_empty_file
+ temp_dir do
+ File.open '.rdoc_options', 'w' do |io|
+ end
+
+ options = @rdoc.load_options
+
+ assert_equal 'rdoc', options.markup
+ end
+ end
+
+ def test_load_options_partial_override
+ temp_dir do
+ File.open '.rdoc_options', 'w' do |io|
+ io.write "markup: Markdown"
+ end
+
+ options = @rdoc.load_options
+
+ assert_equal 'Markdown', options.markup
+ end
+ end
+
def load_options_no_file
temp_dir do
options = @rdoc.load_options
@@ -146,7 +174,7 @@ class TestRDocRDoc < RDoc::TestCase
@rdoc.normalized_file_list [test_path, flag_file]
end
- files = files.map { |file| File.expand_path file }
+ files = files.map { |file, *| File.expand_path file }
assert_equal [test_path], files
end
@@ -156,7 +184,9 @@ class TestRDocRDoc < RDoc::TestCase
files = @rdoc.normalized_file_list [__FILE__]
- assert_empty files
+ files = files.collect {|file, mtime| file if mtime}.compact
+
+ assert_empty(files)
end
def test_normalized_file_list_non_file_directory
@@ -205,7 +235,7 @@ class TestRDocRDoc < RDoc::TestCase
@rdoc.normalized_file_list [File.realpath(dir)]
end
- files = files.map { |file| File.expand_path file }
+ files = files.map { |file, *| File.expand_path file }
assert_equal expected_files, files
end
@@ -236,7 +266,7 @@ class TestRDocRDoc < RDoc::TestCase
@rdoc.normalized_file_list [File.realpath(dir)]
end
- files = files.map { |file| File.expand_path file }
+ files = files.map { |file, *| File.expand_path file }
assert_equal expected_files, files
end
@@ -427,11 +457,10 @@ class TestRDocRDoc < RDoc::TestCase
end
def test_remove_unparseable_CVE_2021_31799
- omit 'for Un*x platforms' if Gem.win_platform?
temp_dir do
file_list = ['| touch evil.txt && echo tags']
file_list.each do |f|
- FileUtils.touch f
+ FileUtils.touch f rescue omit
end
assert_equal file_list, @rdoc.remove_unparseable(file_list)
diff --git a/test/rdoc/test_rdoc_ri_driver.rb b/test/rdoc/test_rdoc_ri_driver.rb
index 6f17fecec9..f79d17b1cd 100644
--- a/test/rdoc/test_rdoc_ri_driver.rb
+++ b/test/rdoc/test_rdoc_ri_driver.rb
@@ -13,8 +13,9 @@ class TestRDocRIDriver < RDoc::TestCase
FileUtils.mkdir_p @home_ri
@orig_ri = ENV['RI']
- @orig_home = ENV['HOME']
ENV['HOME'] = @tmpdir
+ @rdoc_home = File.join ENV["HOME"], ".rdoc"
+ FileUtils.mkdir_p @rdoc_home
ENV.delete 'RI'
@options = RDoc::RI::Driver.default_options
@@ -31,11 +32,10 @@ class TestRDocRIDriver < RDoc::TestCase
end
def teardown
- super
-
- ENV['HOME'] = @orig_home
ENV['RI'] = @orig_ri
FileUtils.rm_rf @tmpdir
+
+ super
end
DUMMY_PAGER = ":;\n"
@@ -81,7 +81,7 @@ class TestRDocRIDriver < RDoc::TestCase
@RM::Rule.new(1),
@RM::Paragraph.new('Also found in:'),
@RM::Verbatim.new("ruby core", "\n",
- "~/.rdoc", "\n"))
+ @rdoc_home, "\n"))
assert_equal expected, out
end
@@ -231,7 +231,7 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Foo::Bar#blah'),
blank_line,
- para('(from ~/.rdoc)'),
+ para("(from #{@rdoc_home})"),
head(3, 'Implementation from Bar'),
rule(1),
verb("blah(5) => 5\n",
@@ -254,7 +254,7 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Qux#aliased'),
blank_line,
- para('(from ~/.rdoc)'),
+ para("(from #{@rdoc_home})"),
rule(1),
blank_line,
para('alias comment'),
@@ -280,7 +280,7 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Foo::Bar#attr'),
blank_line,
- para('(from ~/.rdoc)'),
+ para("(from #{@rdoc_home})"),
rule(1),
blank_line,
blank_line)
@@ -299,7 +299,7 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Bar#inherit'),
blank_line,
- para('(from ~/.rdoc)'),
+ para("(from #{@rdoc_home})"),
head(3, 'Implementation from Foo'),
rule(1),
blank_line,
@@ -343,13 +343,13 @@ class TestRDocRIDriver < RDoc::TestCase
doc(
head(1, 'Foo#inherit'),
blank_line,
- para('(from ~/.rdoc)'),
+ para("(from #{@rdoc_home})"),
rule(1),
blank_line,
blank_line,
head(1, 'Foo#override'),
blank_line,
- para('(from ~/.rdoc)'),
+ para("(from #{@rdoc_home})"),
rule(1),
blank_line,
para('must not be displayed in Bar#override'),
@@ -802,7 +802,7 @@ Foo::Bar#bother
@driver.display_page 'home:README'
end
- assert_match %r%= README pages in ~/\.rdoc%, out
+ assert_match %r%= README pages in #{@rdoc_home}%, out
assert_match %r%README\.rdoc%, out
assert_match %r%README\.md%, out
end
@@ -856,7 +856,7 @@ Foo::Bar#bother
@driver.display_page_list @store1
end
- assert_match %r%= Pages in ~/\.rdoc%, out
+ assert_match %r%= Pages in #{@rdoc_home}%, out
assert_match %r%README\.rdoc%, out
end
@@ -876,7 +876,7 @@ Foo::Bar#bother
@driver.display_page_list @store1
end
- assert_match %r%= Pages in ~/\.rdoc%, out
+ assert_match %r%= Pages in #{@rdoc_home}%, out
assert_match %r%README\.rdoc%, out
assert_match %r%OTHER\.rdoc%, out
end
diff --git a/test/rdoc/test_rdoc_ri_paths.rb b/test/rdoc/test_rdoc_ri_paths.rb
index 726922daf0..c01a4711ee 100644
--- a/test/rdoc/test_rdoc_ri_paths.rb
+++ b/test/rdoc/test_rdoc_ri_paths.rb
@@ -36,12 +36,12 @@ class TestRDocRIPaths < RDoc::TestCase
end
def teardown
- super
-
Gem.use_paths(*@orig_gem_path)
Gem::Specification.reset
FileUtils.rm_rf @tempdir
ENV.replace(@orig_env)
+
+ super
end
def test_class_each
@@ -51,7 +51,7 @@ class TestRDocRIPaths < RDoc::TestCase
assert_equal RDoc::RI::Paths.system_dir, path.shift
assert_equal RDoc::RI::Paths.site_dir, path.shift
- assert_equal RDoc::RI::Paths.home_dir, path.shift
+ assert_equal RDoc::RI::Paths.home_dir, path.shift if RDoc::RI::Paths.home_dir
assert_equal File.join(@nodoc.doc_dir, 'ri'), path.shift
assert_equal File.join(@rake_10.doc_dir, 'ri'), path.shift
assert_equal File.join(@rdoc_4_0.doc_dir, 'ri'), path.shift
@@ -128,7 +128,7 @@ class TestRDocRIPaths < RDoc::TestCase
assert_equal RDoc::RI::Paths.system_dir, path.shift
assert_equal RDoc::RI::Paths.site_dir, path.shift
- assert_equal RDoc::RI::Paths.home_dir, path.shift
+ assert_equal RDoc::RI::Paths.home_dir, path.shift if RDoc::RI::Paths.home_dir
assert_equal File.join(@rake_10.doc_dir, 'ri'), path.shift
end
@@ -138,7 +138,7 @@ class TestRDocRIPaths < RDoc::TestCase
assert_equal '/nonexistent', path.shift
assert_equal RDoc::RI::Paths.system_dir, path.shift
assert_equal RDoc::RI::Paths.site_dir, path.shift
- assert_equal RDoc::RI::Paths.home_dir, path.shift
+ assert_equal RDoc::RI::Paths.home_dir, path.shift if RDoc::RI::Paths.home_dir
assert_equal File.join(@rake_10.doc_dir, 'ri'), path.shift
end
diff --git a/test/rdoc/test_rdoc_rubygems_hook.rb b/test/rdoc/test_rdoc_rubygems_hook.rb
index 7d59577d97..959214b474 100644
--- a/test/rdoc/test_rdoc_rubygems_hook.rb
+++ b/test/rdoc/test_rdoc_rubygems_hook.rb
@@ -1,31 +1,62 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require "rubygems"
+require "fileutils"
+require "tmpdir"
require 'rdoc/rubygems_hook'
+require "test/unit"
-class TestRDocRubygemsHook < Gem::TestCase
-
+class TestRDocRubygemsHook < Test::Unit::TestCase
def setup
- super
-
- @a = util_spec 'a', 2 do |s|
+ @a = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = "a"
+ s.version = 2
s.rdoc_options = %w[--main MyTitle]
s.extra_rdoc_files = %w[README]
end
-
- write_file File.join(@tempdir, 'lib', 'a.rb')
- write_file File.join(@tempdir, 'README')
-
- install_gem @a
+ @tempdir = File.realpath(Dir.mktmpdir("test_rubygems_hook_"))
+
+ @orig_envs = %w[
+ GEM_VENDOR
+ GEMRC
+ XDG_CACHE_HOME
+ XDG_CONFIG_HOME
+ XDG_DATA_HOME
+ SOURCE_DATE_EPOCH
+ BUNDLER_VERSION
+ HOME
+ RDOCOPT
+ ].map {|e| [e, ENV.delete(e)]}.to_h
+ ENV["HOME"] = @tempdir
+
+ Gem.configuration = nil
+
+ @a.instance_variable_set(:@doc_dir, File.join(@tempdir, "doc"))
+ @a.instance_variable_set(:@gem_dir, File.join(@tempdir, "a-2"))
+ @a.instance_variable_set(:@full_gem_path, File.join(@tempdir, "a-2"))
+ @a.loaded_from = File.join(@tempdir, 'a-2', 'a-2.gemspec')
+
+ FileUtils.mkdir_p File.join(@tempdir, 'a-2', 'lib')
+ FileUtils.touch File.join(@tempdir, 'a-2', 'lib', 'a.rb')
+ FileUtils.touch File.join(@tempdir, 'a-2', 'README')
@hook = RDoc::RubygemsHook.new @a
begin
RDoc::RubygemsHook.load_rdoc
rescue Gem::DocumentError => e
- skip e.message
+ omit e.message
end
+ @old_ui = Gem::DefaultUserInteraction.ui
+ Gem::DefaultUserInteraction.ui = Gem::SilentUI.new
+ end
- Gem.configuration[:rdoc] = nil
+ def teardown
+ ui = Gem::DefaultUserInteraction.ui
+ Gem::DefaultUserInteraction.ui = @old_ui
+ FileUtils.rm_rf @tempdir
+ ui.close
+ ENV.update(@orig_envs)
end
def test_initialize
@@ -78,9 +109,11 @@ class TestRDocRubygemsHook < Gem::TestCase
refute rdoc.options.hyperlink_all
assert_equal Pathname(@a.full_gem_path), rdoc.options.root
- assert_equal %w[README lib], rdoc.options.files.sort
assert_equal 'MyTitle', rdoc.store.main
+
+ omit "skip rdoc rubygems integration test: maybe some fixes are required in rubygems."
+ assert_equal %w[README lib], rdoc.options.files.sort
end
def test_generate_all
@@ -99,9 +132,11 @@ class TestRDocRubygemsHook < Gem::TestCase
refute rdoc.options.hyperlink_all
assert_equal Pathname(@a.full_gem_path), rdoc.options.root
- assert_equal %w[README lib], rdoc.options.files.sort
assert_equal 'MyTitle', rdoc.store.main
+
+ omit "skip rdoc rubygems integration test: maybe some fixes are required in rubygems."
+ assert_equal %w[README lib], rdoc.options.files.sort
end
def test_generate_configuration_rdoc_array
@@ -165,8 +200,8 @@ class TestRDocRubygemsHook < Gem::TestCase
@hook.generate
- refute_path_exists File.join(@a.doc_dir('rdoc'), 'index.html')
- assert_path_exists File.join(@a.doc_dir('ri'), 'cache.ri')
+ assert_path_not_exist File.join(@a.doc_dir('rdoc'), 'index.html')
+ assert_path_exist File.join(@a.doc_dir('ri'), 'cache.ri')
end
def test_generate_no_overwrite
@@ -176,8 +211,8 @@ class TestRDocRubygemsHook < Gem::TestCase
@hook.generate
- refute_path_exists File.join(@a.doc_dir('rdoc'), 'index.html')
- refute_path_exists File.join(@a.doc_dir('ri'), 'cache.ri')
+ assert_path_not_exist File.join(@a.doc_dir('rdoc'), 'index.html')
+ assert_path_not_exist File.join(@a.doc_dir('ri'), 'cache.ri')
end
def test_new_rdoc
@@ -201,17 +236,17 @@ class TestRDocRubygemsHook < Gem::TestCase
refute @hook.rdoc_installed?
refute @hook.ri_installed?
- assert_path_exists @a.doc_dir
+ assert_path_exist @a.doc_dir
end
def test_remove_unwritable
- skip 'chmod not supported' if Gem.win_platform?
- skip "assumes that euid is not root" if Process.euid == 0
+ omit 'chmod not supported' if Gem.win_platform?
+ omit "assumes that euid is not root" if Process.euid == 0
FileUtils.mkdir_p @a.base_dir
FileUtils.chmod 0, @a.base_dir
- e = assert_raises Gem::FilePermissionError do
+ e = assert_raise Gem::FilePermissionError do
@hook.remove
end
@@ -231,17 +266,17 @@ class TestRDocRubygemsHook < Gem::TestCase
def test_setup
@hook.setup
- assert_path_exists @a.doc_dir
+ assert_path_exist @a.doc_dir
end
def test_setup_unwritable
- skip 'chmod not supported' if Gem.win_platform?
- skip "assumes that euid is not root" if Process.euid == 0
+ omit 'chmod not supported' if Gem.win_platform?
+ omit "assumes that euid is not root" if Process.euid == 0
FileUtils.mkdir_p @a.doc_dir
FileUtils.chmod 0, @a.doc_dir
- e = assert_raises Gem::FilePermissionError do
+ e = assert_raise Gem::FilePermissionError do
@hook.setup
end
diff --git a/test/rdoc/test_rdoc_servlet.rb b/test/rdoc/test_rdoc_servlet.rb
index 1127408193..c41c2c8ae7 100644
--- a/test/rdoc/test_rdoc_servlet.rb
+++ b/test/rdoc/test_rdoc_servlet.rb
@@ -45,7 +45,8 @@ class TestRDocServlet < RDoc::TestCase
@orig_base = RDoc::RI::Paths::BASE
RDoc::RI::Paths::BASE.replace @base
@orig_ri_path_homedir = RDoc::RI::Paths::HOMEDIR
- RDoc::RI::Paths::HOMEDIR.replace @home_dir
+ RDoc::RI::Paths.send :remove_const, :HOMEDIR
+ RDoc::RI::Paths.const_set :HOMEDIR, @home_dir
RDoc::RI::Paths.instance_variable_set \
:@gemdirs, %w[/nonexistent/gems/example-1.0/ri]
@@ -60,7 +61,8 @@ class TestRDocServlet < RDoc::TestCase
FileUtils.rm_rf @tempdir
RDoc::RI::Paths::BASE.replace @orig_base
- RDoc::RI::Paths::HOMEDIR.replace @orig_ri_path_homedir
+ RDoc::RI::Paths.send :remove_const, :HOMEDIR
+ RDoc::RI::Paths.const_set :HOMEDIR, @orig_ri_path_homedir
RDoc::RI::Paths.instance_variable_set :@gemdirs, nil
end
@@ -546,4 +548,4 @@ class TestRDocServlet < RDoc::TestCase
store.save
end
-end
+end if defined?(WEBrick)
diff --git a/test/rdoc/test_rdoc_store.rb b/test/rdoc/test_rdoc_store.rb
index 8332d9233e..82340e6b7a 100644
--- a/test/rdoc/test_rdoc_store.rb
+++ b/test/rdoc/test_rdoc_store.rb
@@ -317,6 +317,9 @@ class TestRDocStore < XrefTestCase
end
def test_friendly_path
+ @orig_xdg_data_home = ENV['XDG_DATA_HOME']
+ ENV.delete('XDG_DATA_HOME')
+
@s.path = @tmpdir
@s.type = nil
assert_equal @s.path, @s.friendly_path
@@ -331,11 +334,13 @@ class TestRDocStore < XrefTestCase
assert_equal "ruby site", @s.friendly_path
@s.type = :home
- assert_equal "~/.rdoc", @s.friendly_path
+ assert_equal File.expand_path("~/.local/share/rdoc"), @s.friendly_path
@s.type = :gem
@s.path = "#{@tmpdir}/gem_repository/doc/gem_name-1.0/ri"
assert_equal "gem gem_name-1.0", @s.friendly_path
+ ensure
+ ENV['XDG_DATA_HOME'] = @orig_xdg_data_home
end
def test_dry_run
@@ -606,6 +611,14 @@ class TestRDocStore < XrefTestCase
assert_equal page, @store.page('PAGE')
end
+ def test_page_with_extension
+ page = @store.add_file 'PAGE.txt', parser: RDoc::Parser::Simple
+
+ assert_nil @store.page 'no such page'
+
+ assert_equal page, @store.page('PAGE.txt')
+ end
+
def test_save
FileUtils.mkdir_p @tmpdir
diff --git a/test/rdoc/test_rdoc_top_level.rb b/test/rdoc/test_rdoc_top_level.rb
index e396791ab8..a954fde981 100644
--- a/test/rdoc/test_rdoc_top_level.rb
+++ b/test/rdoc/test_rdoc_top_level.rb
@@ -157,6 +157,9 @@ class TestRDocTopLevel < XrefTestCase
def test_http_url
assert_equal 'prefix/path/top_level_rb.html', @top_level.http_url('prefix')
+
+ other_level = @store.add_file 'path.other/level.rb'
+ assert_equal 'prefix/path_other/level_rb.html', other_level.http_url('prefix')
end
def test_last_modified
diff --git a/test/readline/test_readline.rb b/test/readline/test_readline.rb
index 12cac20918..15064ff986 100644
--- a/test/readline/test_readline.rb
+++ b/test/readline/test_readline.rb
@@ -176,7 +176,7 @@ module BasetestReadline
assert_equal("", line2)
begin
assert_equal("", Readline.line_buffer)
- rescue NotimplementedError
+ rescue NotImplementedError
end
end
end
diff --git a/test/reline/helper.rb b/test/reline/helper.rb
index 0b5b8af310..9712dde6c6 100644
--- a/test/reline/helper.rb
+++ b/test/reline/helper.rb
@@ -7,6 +7,7 @@ module Reline
def test_mode
remove_const('IOGate') if const_defined?('IOGate')
const_set('IOGate', Reline::GeneralIO)
+ Reline::GeneralIO.reset
send(:core).config.instance_variable_set(:@test_mode, true)
send(:core).config.reset
end
@@ -17,6 +18,14 @@ module Reline
end
end
+def start_pasting
+ Reline::GeneralIO.start_pasting
+end
+
+def finish_pasting
+ Reline::GeneralIO.finish_pasting
+end
+
RELINE_TEST_ENCODING ||=
if ENV['RELINE_TEST_ENCODING']
Encoding.find(ENV['RELINE_TEST_ENCODING'])
@@ -87,4 +96,18 @@ class Reline::TestCase < Test::Unit::TestCase
def assert_cursor_max(expected)
assert_equal(expected, @line_editor.instance_variable_get(:@cursor_max))
end
+
+ def assert_line_index(expected)
+ assert_equal(expected, @line_editor.instance_variable_get(:@line_index))
+ end
+
+ def assert_whole_lines(expected)
+ previous_line_index = @line_editor.instance_variable_get(:@previous_line_index)
+ if previous_line_index
+ lines = @line_editor.whole_lines(index: previous_line_index)
+ else
+ lines = @line_editor.whole_lines
+ end
+ assert_equal(expected, lines)
+ end
end
diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb
index a1e4015999..947685409f 100644
--- a/test/reline/test_key_actor_emacs.rb
+++ b/test/reline/test_key_actor_emacs.rb
@@ -1281,6 +1281,36 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
assert_equal(%w{foo_foo foo_bar foo_baz}, @line_editor.instance_variable_get(:@menu_info).list)
end
+ def test_completion_duplicated_list
+ @line_editor.completion_proc = proc { |word|
+ %w{
+ foo_foo
+ foo_foo
+ foo_bar
+ }.map { |i|
+ i.encode(@encoding)
+ }
+ }
+ input_keys('foo_')
+ assert_byte_pointer_size('foo_')
+ assert_cursor(4)
+ assert_cursor_max(4)
+ assert_line('foo_')
+ assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
+ input_keys("\C-i", false)
+ assert_byte_pointer_size('foo_')
+ assert_cursor(4)
+ assert_cursor_max(4)
+ assert_line('foo_')
+ assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
+ input_keys("\C-i", false)
+ assert_byte_pointer_size('foo_')
+ assert_cursor(4)
+ assert_cursor_max(4)
+ assert_line('foo_')
+ assert_equal(%w{foo_foo foo_bar}, @line_editor.instance_variable_get(:@menu_info).list)
+ end
+
def test_completion
@line_editor.completion_proc = proc { |word|
%w{
@@ -1864,6 +1894,36 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
assert_cursor_max(0)
end
+ def test_search_history_with_isearch_terminator
+ @config.read_lines(<<~LINES.split(/(?<=\n)/))
+ set isearch-terminators "XYZ"
+ LINES
+ Reline::HISTORY.concat([
+ '1235', # old
+ '12aa',
+ '1234' # new
+ ])
+ assert_line('')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(0)
+ input_keys("\C-r12a")
+ assert_line('12aa')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(0) # doesn't determine yet
+ input_keys('Y')
+ assert_line('12aa')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(4)
+ input_keys('x')
+ assert_line('x12aa')
+ assert_byte_pointer_size('x')
+ assert_cursor(1)
+ assert_cursor_max(5)
+ end
+
def test_em_set_mark_and_em_exchange_mark
input_keys('aaa bbb ccc ddd')
assert_byte_pointer_size('aaa bbb ccc ddd')
@@ -1896,6 +1956,26 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
assert_equal([0, 0], @line_editor.instance_variable_get(:@mark_pointer))
end
+ def test_em_exchange_mark_without_mark
+ input_keys('aaa bbb ccc ddd')
+ assert_byte_pointer_size('aaa bbb ccc ddd')
+ assert_cursor(15)
+ assert_cursor_max(15)
+ assert_line('aaa bbb ccc ddd')
+ input_keys("\C-a\M-f", false)
+ assert_byte_pointer_size('aaa')
+ assert_cursor(3)
+ assert_cursor_max(15)
+ assert_line('aaa bbb ccc ddd')
+ assert_equal(nil, @line_editor.instance_variable_get(:@mark_pointer))
+ input_key_by_symbol(:em_exchange_mark)
+ assert_byte_pointer_size('aaa')
+ assert_cursor(3)
+ assert_cursor_max(15)
+ assert_line('aaa bbb ccc ddd')
+ assert_equal(nil, @line_editor.instance_variable_get(:@mark_pointer))
+ end
+
def test_modify_lines_with_wrong_rs
verbose, $VERBOSE = $VERBOSE, nil
original_global_slash = $/
@@ -2055,6 +2135,159 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
assert_line('')
end
+ # Unicode emoji test
+ if RELINE_TEST_ENCODING == Encoding::UTF_8
+ def test_ed_insert_for_include_zwj_emoji
+ # U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 is family: man, woman, girl, boy "👨‍👩‍👧‍👦"
+ input_keys("\u{1F468}") # U+1F468 is man "👨"
+ assert_line("\u{1F468}")
+ assert_byte_pointer_size("\u{1F468}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u200D") # U+200D is ZERO WIDTH JOINER
+ assert_line("\u{1F468 200D}")
+ assert_byte_pointer_size("\u{1F468 200D}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u{1F469}") # U+1F469 is woman "👩"
+ assert_line("\u{1F468 200D 1F469}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u200D") # U+200D is ZERO WIDTH JOINER
+ assert_line("\u{1F468 200D 1F469 200D}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u{1F467}") # U+1F467 is girl "👧"
+ assert_line("\u{1F468 200D 1F469 200D 1F467}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u200D") # U+200D is ZERO WIDTH JOINER
+ assert_line("\u{1F468 200D 1F469 200D 1F467 200D}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ input_keys("\u{1F466}") # U+1F466 is boy "👦"
+ assert_line("\u{1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_cursor(2)
+ assert_cursor_max(2)
+ # U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 is family: man, woman, girl, boy "👨‍👩‍👧‍👦"
+ input_keys("\u{1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_line("\u{1F468 200D 1F469 200D 1F467 200D 1F466 1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D 1F466 1F468 200D 1F469 200D 1F467 200D 1F466}")
+ assert_cursor(4)
+ assert_cursor_max(4)
+ end
+
+ def test_ed_insert_for_include_valiation_selector
+ # U+0030 U+FE00 is DIGIT ZERO + VARIATION SELECTOR-1 "0︀"
+ input_keys("\u0030") # U+0030 is DIGIT ZERO
+ assert_line("\u0030")
+ assert_byte_pointer_size("\u0030")
+ assert_cursor(1)
+ assert_cursor_max(1)
+ input_keys("\uFE00") # U+FE00 is VARIATION SELECTOR-1
+ assert_line("\u{0030 FE00}")
+ assert_byte_pointer_size("\u{0030 FE00}")
+ assert_cursor(1)
+ assert_cursor_max(1)
+ end
+ end
+
+ def test_em_yank_pop
+ input_keys("def hoge\C-w\C-b\C-f\C-w", false)
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(0)
+ assert_line('')
+ input_keys("\C-y", false)
+ assert_byte_pointer_size('def ')
+ assert_cursor(4)
+ assert_cursor_max(4)
+ assert_line('def ')
+ input_keys("\M-\C-y", false)
+ assert_byte_pointer_size('hoge')
+ assert_cursor(4)
+ assert_cursor_max(4)
+ assert_line('hoge')
+ end
+
+ def test_em_kill_region_with_kill_ring
+ input_keys("def hoge\C-b\C-b\C-b\C-b", false)
+ assert_byte_pointer_size('def ')
+ assert_cursor(4)
+ assert_cursor_max(8)
+ assert_line('def hoge')
+ input_keys("\C-k\C-w", false)
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(0)
+ assert_line('')
+ input_keys("\C-y", false)
+ assert_byte_pointer_size('def hoge')
+ assert_cursor(8)
+ assert_cursor_max(8)
+ assert_line('def hoge')
+ end
+
+ def test_ed_search_prev_next_history_in_multibyte
+ Reline::HISTORY.concat([
+ "def hoge\n 67890\n 12345\nend", # old
+ "def aiu\n 0xDEADBEEF\nend",
+ "def foo\n 12345\nend" # new
+ ])
+ @line_editor.multiline_on
+ input_keys(' 123')
+ # The ed_search_prev_history doesn't have default binding
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_whole_lines(['def foo', ' 12345', 'end'])
+ assert_line_index(1)
+ assert_whole_lines(['def foo', ' 12345', 'end'])
+ assert_byte_pointer_size(' 123')
+ assert_cursor(5)
+ assert_cursor_max(7)
+ assert_line(' 12345')
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_line_index(2)
+ assert_whole_lines(['def hoge', ' 67890', ' 12345', 'end'])
+ assert_byte_pointer_size(' 123')
+ assert_cursor(5)
+ assert_cursor_max(7)
+ assert_line(' 12345')
+ @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
+ assert_line_index(2)
+ assert_whole_lines(['def hoge', ' 67890', ' 12345', 'end'])
+ assert_byte_pointer_size(' 123')
+ assert_cursor(5)
+ assert_cursor_max(7)
+ assert_line(' 12345')
+ @line_editor.__send__(:ed_search_next_history, "\C-n".ord)
+ assert_line_index(1)
+ assert_whole_lines(['def foo', ' 12345', 'end'])
+ assert_byte_pointer_size(' 123')
+ assert_cursor(5)
+ assert_cursor_max(7)
+ assert_line(' 12345')
+ @line_editor.__send__(:ed_search_next_history, "\C-n".ord)
+ assert_line_index(1)
+ assert_whole_lines(['def foo', ' 12345', 'end'])
+ assert_byte_pointer_size(' 123')
+ assert_cursor(5)
+ assert_cursor_max(7)
+ assert_line(' 12345')
+ end
+
+ def test_input_unknown_char
+ input_keys('͸') # U+0378 (unassigned)
+ assert_line('͸')
+ assert_byte_pointer_size('͸')
+ assert_cursor(1)
+ assert_cursor_max(1)
+ end
+
=begin # TODO: move KeyStroke instance from Reline to LineEditor
def test_key_delete
input_keys('ab')
diff --git a/test/reline/test_key_actor_vi.rb b/test/reline/test_key_actor_vi.rb
index c6337baea7..c6cd5eff48 100644
--- a/test/reline/test_key_actor_vi.rb
+++ b/test/reline/test_key_actor_vi.rb
@@ -615,6 +615,24 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
assert_cursor_max(6)
end
+ def test_vi_replace_char_with_mbchar
+ input_keys("あいうえお\C-[0l")
+ assert_line('あいうえお')
+ assert_byte_pointer_size('あ')
+ assert_cursor(2)
+ assert_cursor_max(10)
+ input_keys('rx')
+ assert_line('あxうえお')
+ assert_byte_pointer_size('あ')
+ assert_cursor(2)
+ assert_cursor_max(9)
+ input_keys('l2ry')
+ assert_line('あxyyお')
+ assert_byte_pointer_size('あxyy')
+ assert_cursor(5)
+ assert_cursor_max(7)
+ end
+
def test_vi_next_char
input_keys("abcdef\C-[0")
assert_line('abcdef')
@@ -1215,26 +1233,223 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
assert_line('aaa ddd eee')
end
+ def test_vi_delete_meta_with_vi_next_word_at_eol
+ input_keys("foo bar\C-[0w")
+ assert_byte_pointer_size('foo ')
+ assert_cursor(4)
+ assert_cursor_max(7)
+ assert_line('foo bar')
+ input_keys('w')
+ assert_byte_pointer_size('foo ba')
+ assert_cursor(6)
+ assert_cursor_max(7)
+ assert_line('foo bar')
+ input_keys('0dw')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(3)
+ assert_line('bar')
+ input_keys('dw')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(0)
+ assert_line('')
+ end
+
+ def test_vi_delete_meta_with_vi_next_char
+ input_keys("aaa bbb ccc ___ ddd\C-[02w")
+ assert_byte_pointer_size('aaa bbb ')
+ assert_cursor(8)
+ assert_cursor_max(19)
+ assert_line('aaa bbb ccc ___ ddd')
+ input_keys('df_')
+ assert_byte_pointer_size('aaa bbb ')
+ assert_cursor(8)
+ assert_cursor_max(14)
+ assert_line('aaa bbb __ ddd')
+ end
+
+ def test_vi_delete_meta_with_arg
+ input_keys("aaa bbb ccc\C-[02w")
+ assert_byte_pointer_size('aaa bbb ')
+ assert_cursor(8)
+ assert_cursor_max(11)
+ assert_line('aaa bbb ccc')
+ input_keys('2dl')
+ assert_byte_pointer_size('aaa bbb ')
+ assert_cursor(8)
+ assert_cursor_max(9)
+ assert_line('aaa bbb c')
+ end
+
def test_vi_change_meta
input_keys("aaa bbb ccc ddd eee\C-[02w")
assert_byte_pointer_size('aaa bbb ')
assert_cursor(8)
assert_cursor_max(19)
assert_line('aaa bbb ccc ddd eee')
- input_keys('cwaiueo ')
- assert_byte_pointer_size('aaa bbb aiueo ')
- assert_cursor(14)
+ input_keys('cwaiueo')
+ assert_byte_pointer_size('aaa bbb aiueo')
+ assert_cursor(13)
assert_cursor_max(21)
assert_line('aaa bbb aiueo ddd eee')
input_keys("\C-[")
- assert_byte_pointer_size('aaa bbb aiueo')
- assert_cursor(13)
+ assert_byte_pointer_size('aaa bbb aiue')
+ assert_cursor(12)
assert_cursor_max(21)
assert_line('aaa bbb aiueo ddd eee')
input_keys('cb')
assert_byte_pointer_size('aaa bbb ')
assert_cursor(8)
- assert_cursor_max(16)
- assert_line('aaa bbb ddd eee')
+ assert_cursor_max(17)
+ assert_line('aaa bbb o ddd eee')
+ end
+
+ def test_vi_change_meta_with_vi_next_word
+ input_keys("foo bar baz\C-[0w")
+ assert_byte_pointer_size('foo ')
+ assert_cursor(5)
+ assert_cursor_max(13)
+ assert_line('foo bar baz')
+ input_keys('cwhoge')
+ assert_byte_pointer_size('foo hoge')
+ assert_cursor(9)
+ assert_cursor_max(14)
+ assert_line('foo hoge baz')
+ input_keys("\C-[")
+ assert_byte_pointer_size('foo hog')
+ assert_cursor(8)
+ assert_cursor_max(14)
+ assert_line('foo hoge baz')
+ end
+
+ def test_unimplemented_vi_command_should_be_no_op
+ input_keys("abc\C-[h")
+ assert_byte_pointer_size('a')
+ assert_cursor(1)
+ assert_cursor_max(3)
+ assert_line('abc')
+ input_keys('@')
+ assert_byte_pointer_size('a')
+ assert_cursor(1)
+ assert_cursor_max(3)
+ assert_line('abc')
+ end
+
+ def test_vi_yank
+ input_keys("foo bar\C-[0")
+ assert_line('foo bar')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(7)
+ input_keys('y3l')
+ assert_line('foo bar')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(7)
+ input_keys('P')
+ assert_line('foofoo bar')
+ assert_byte_pointer_size('fo')
+ assert_cursor(2)
+ assert_cursor_max(10)
+ end
+
+ def test_vi_end_word_with_operator
+ input_keys("foo bar\C-[0")
+ assert_line('foo bar')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(7)
+ input_keys('de')
+ assert_line(' bar')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(4)
+ input_keys('de')
+ assert_line('')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(0)
+ input_keys('de')
+ assert_line('')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(0)
+ end
+
+ def test_vi_end_big_word_with_operator
+ input_keys("aaa b{b}}}b\C-[0")
+ assert_line('aaa b{b}}}b')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(13)
+ input_keys('dE')
+ assert_line(' b{b}}}b')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(10)
+ input_keys('dE')
+ assert_line('')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(0)
+ input_keys('dE')
+ assert_line('')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(0)
+ end
+
+ def test_vi_next_char_with_operator
+ input_keys("foo bar\C-[0")
+ assert_line('foo bar')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(7)
+ input_keys('df ')
+ assert_line('bar')
+ assert_byte_pointer_size('')
+ assert_cursor(0)
+ assert_cursor_max(3)
+ end
+
+ def test_pasting
+ start_pasting
+ input_keys('ab')
+ finish_pasting
+ input_keys('c')
+ assert_line('abc')
+ assert_byte_pointer_size('abc')
+ assert_cursor(3)
+ assert_cursor_max(3)
+ end
+
+ def test_pasting_fullwidth
+ start_pasting
+ input_keys('あ')
+ finish_pasting
+ input_keys('い')
+ assert_line('あい')
+ assert_byte_pointer_size('あい')
+ assert_cursor(4)
+ assert_cursor_max(4)
+ end
+
+ def test_ed_delete_next_char_at_eol
+ input_keys('"あ"')
+ assert_line('"あ"')
+ assert_byte_pointer_size('"あ"')
+ assert_cursor(4)
+ assert_cursor_max(4)
+ input_keys("\C-[")
+ assert_line('"あ"')
+ assert_byte_pointer_size('"あ')
+ assert_cursor(3)
+ assert_cursor_max(4)
+ input_keys('xa"')
+ assert_line('"あ"')
+ assert_byte_pointer_size('"あ"')
+ assert_cursor(4)
+ assert_cursor_max(4)
end
end
diff --git a/test/reline/test_kill_ring.rb b/test/reline/test_kill_ring.rb
index 8bebfe2177..9f6e0c3e74 100644
--- a/test/reline/test_kill_ring.rb
+++ b/test/reline/test_kill_ring.rb
@@ -253,4 +253,16 @@ class Reline::KillRing::Test < Reline::TestCase
assert_equal(['AB', 'abcde'], @kill_ring.yank_pop)
assert_equal(Reline::KillRing::State::YANK, @kill_ring.instance_variable_get(:@state))
end
+
+ def test_enumerable
+ @kill_ring.append('a')
+ @kill_ring.process
+ @kill_ring.process
+ @kill_ring.append('b')
+ @kill_ring.process
+ @kill_ring.process
+ @kill_ring.append('c')
+ @kill_ring.process
+ assert_equal(%w{c b a}, @kill_ring.to_a)
+ end
end
diff --git a/test/reline/test_reline.rb b/test/reline/test_reline.rb
index d2de4690d5..0f32ec4421 100644
--- a/test/reline/test_reline.rb
+++ b/test/reline/test_reline.rb
@@ -65,6 +65,8 @@ class Reline::Test < Reline::TestCase
Reline.completer_word_break_characters = "[".encode(Encoding::ASCII)
assert_equal("[", Reline.completer_word_break_characters)
assert_equal(get_reline_encoding, Reline.completer_word_break_characters.encoding)
+
+ assert_nothing_raised { Reline.completer_word_break_characters = '' }
ensure
Reline.completer_word_break_characters = completer_word_break_characters
end
@@ -89,6 +91,8 @@ class Reline::Test < Reline::TestCase
Reline.completer_quote_characters = "`".encode(Encoding::ASCII)
assert_equal("`", Reline.completer_quote_characters)
assert_equal(get_reline_encoding, Reline.completer_quote_characters.encoding)
+
+ assert_nothing_raised { Reline.completer_quote_characters = '' }
ensure
Reline.completer_quote_characters = completer_quote_characters
end
diff --git a/test/reline/test_string_processing.rb b/test/reline/test_string_processing.rb
index e76fa384f2..0e0ee9cc04 100644
--- a/test/reline/test_string_processing.rb
+++ b/test/reline/test_string_processing.rb
@@ -20,4 +20,58 @@ class Reline::LineEditor::StringProcessingTest < Reline::TestCase
width = @line_editor.send(:calculate_width, "\1\e[31m\2RubyColor\1\e[34m\2 default string \1\e[m\2>", true)
assert_equal('RubyColor default string >'.size, width)
end
+
+ def test_completion_proc_with_preposing_and_postposing
+ buf = ['def hoge', ' puts :aaa', 'end']
+
+ @line_editor.instance_variable_set(:@is_multiline, true)
+ @line_editor.instance_variable_set(:@buffer_of_lines, buf)
+ @line_editor.instance_variable_set(:@line, buf[1])
+ @line_editor.instance_variable_set(:@byte_pointer, 3)
+ @line_editor.instance_variable_set(:@cursor, 3)
+ @line_editor.instance_variable_set(:@cursor_max, 11)
+ @line_editor.instance_variable_set(:@line_index, 1)
+ @line_editor.instance_variable_set(:@completion_proc, proc { |target|
+ assert_equal('p', target)
+ })
+ @line_editor.__send__(:call_completion_proc)
+
+ @line_editor.instance_variable_set(:@is_multiline, true)
+ @line_editor.instance_variable_set(:@buffer_of_lines, buf)
+ @line_editor.instance_variable_set(:@line, buf[1])
+ @line_editor.instance_variable_set(:@byte_pointer, 6)
+ @line_editor.instance_variable_set(:@cursor, 6)
+ @line_editor.instance_variable_set(:@cursor_max, 11)
+ @line_editor.instance_variable_set(:@line_index, 1)
+ @line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post|
+ assert_equal('puts', target)
+ assert_equal("def hoge\n ", pre)
+ assert_equal(" :aaa\nend", post)
+ })
+ @line_editor.__send__(:call_completion_proc)
+
+ @line_editor.instance_variable_set(:@line, buf[0])
+ @line_editor.instance_variable_set(:@byte_pointer, 6)
+ @line_editor.instance_variable_set(:@cursor, 6)
+ @line_editor.instance_variable_set(:@cursor_max, 8)
+ @line_editor.instance_variable_set(:@line_index, 0)
+ @line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post|
+ assert_equal('ho', target)
+ assert_equal('def ', pre)
+ assert_equal("ge\n puts :aaa\nend", post)
+ })
+ @line_editor.__send__(:call_completion_proc)
+
+ @line_editor.instance_variable_set(:@line, buf[2])
+ @line_editor.instance_variable_set(:@byte_pointer, 1)
+ @line_editor.instance_variable_set(:@cursor, 1)
+ @line_editor.instance_variable_set(:@cursor_max, 3)
+ @line_editor.instance_variable_set(:@line_index, 2)
+ @line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post|
+ assert_equal('e', target)
+ assert_equal("def hoge\n puts :aaa\n", pre)
+ assert_equal('nd', post)
+ })
+ @line_editor.__send__(:call_completion_proc)
+ end
end
diff --git a/test/reline/test_unicode.rb b/test/reline/test_unicode.rb
new file mode 100644
index 0000000000..8b28cf1cee
--- /dev/null
+++ b/test/reline/test_unicode.rb
@@ -0,0 +1,16 @@
+require_relative 'helper'
+require "reline/unicode"
+
+class Reline::Unicode::Test < Reline::TestCase
+ def setup
+ Reline.send(:test_mode)
+ end
+
+ def test_get_mbchar_width
+ assert_equal Reline.ambiguous_width, Reline::Unicode.get_mbchar_width('é')
+ end
+
+ def test_ambiguous_width
+ assert_equal 2, Reline::Unicode.calculate_width('√', true)
+ end
+end
diff --git a/test/reline/test_within_pipe.rb b/test/reline/test_within_pipe.rb
index 53989a794f..36a2f1e805 100644
--- a/test/reline/test_within_pipe.rb
+++ b/test/reline/test_within_pipe.rb
@@ -8,6 +8,7 @@ class Reline::WithinPipeTest < Reline::TestCase
@reader, @output_writer = IO.pipe((RELINE_TEST_ENCODING rescue Encoding.default_external))
@output = Reline.output = @output_writer
@config = Reline.send(:core).config
+ @config.keyseq_timeout *= 600 if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # for --jit-wait CI
@line_editor = Reline.send(:core).line_editor
end
@@ -58,4 +59,17 @@ class Reline::WithinPipeTest < Reline::TestCase
@writer.write("abcde\C-b\C-b\C-b\C-x\C-d\C-x\C-h\C-x\C-v\C-a\C-f\C-f EF\C-x\C-t gh\C-x\M-t\C-b\C-b\C-b\C-b\C-b\C-b\C-b\C-b\C-x\M-u\C-x\M-l\C-x\M-c\n")
assert_equal "a\C-aDE gh Fe", Reline.readmultiline(&proc{ true })
end
+
+ def test_delete_text_in_multiline
+ @writer.write("abc\ndef\nxyz\n")
+ result = Reline.readmultiline(&proc{ |str|
+ if str.include?('xyz')
+ Reline.delete_text
+ true
+ else
+ false
+ end
+ })
+ assert_equal "abc\ndef", result
+ end
end
diff --git a/test/reline/yamatanooroti/multiline_repl b/test/reline/yamatanooroti/multiline_repl
new file mode 100755
index 0000000000..f2efdd4eaf
--- /dev/null
+++ b/test/reline/yamatanooroti/multiline_repl
@@ -0,0 +1,74 @@
+#!/usr/bin/env ruby
+
+require 'reline'
+require 'optparse'
+require_relative 'termination_checker'
+
+opt = OptionParser.new
+opt.on('--prompt-list-cache-timeout VAL') { |v|
+ Reline::LineEditor.__send__(:remove_const, :PROMPT_LIST_CACHE_TIMEOUT)
+ Reline::LineEditor::PROMPT_LIST_CACHE_TIMEOUT = v.to_f
+}
+opt.on('--dynamic-prompt') {
+ Reline.prompt_proc = proc { |lines|
+ lines.each_with_index.map { |l, i|
+ '[%04d]> ' % i
+ }
+ }
+}
+opt.on('--broken-dynamic-prompt') {
+ Reline.prompt_proc = proc { |lines|
+ range = lines.size > 1 ? (0..(lines.size - 2)) : (0..0)
+ lines[range].each_with_index.map { |l, i|
+ '[%04d]> ' % i
+ }
+ }
+}
+opt.on('--dynamic-prompt-returns-empty') {
+ Reline.prompt_proc = proc { |l| [] }
+}
+opt.on('--auto-indent') {
+ AutoIndent.new
+}
+opt.parse!(ARGV)
+
+begin
+ stty_save = `stty -g`.chomp
+rescue
+end
+
+begin
+ prompt = ENV['RELINE_TEST_PROMPT'] || 'prompt> '
+ puts 'Multiline REPL.'
+ checker = TerminationChecker.new
+ while code = Reline.readmultiline(prompt, true) { |code| checker.terminated?(code) }
+ case code.chomp
+ when 'exit', 'quit', 'q'
+ exit 0
+ when ''
+ # NOOP
+ else
+ begin
+ result = eval(code)
+ puts "=> #{result.inspect}"
+ rescue ScriptError, StandardError => e
+ puts "Traceback (most recent call last):"
+ e.backtrace.reverse_each do |f|
+ puts " #{f}"
+ end
+ puts e.message
+ end
+ end
+ end
+rescue Interrupt
+ puts '^C'
+ `stty #{stty_save}` if stty_save
+ exit 0
+ensure
+ `stty #{stty_save}` if stty_save
+end
+begin
+ puts
+rescue Errno::EIO
+ # Maybe the I/O has been closed.
+end
diff --git a/test/reline/yamatanooroti/termination_checker.rb b/test/reline/yamatanooroti/termination_checker.rb
new file mode 100644
index 0000000000..a36e075bde
--- /dev/null
+++ b/test/reline/yamatanooroti/termination_checker.rb
@@ -0,0 +1,30 @@
+require 'ripper'
+require 'irb/ruby-lex'
+
+class TerminationChecker < RubyLex
+ def terminated?(code)
+ code.gsub!(/\n*$/, '').concat("\n")
+ @tokens = Ripper.lex(code)
+ continue = process_continue
+ code_block_open = check_code_block(code)
+ indent = process_nesting_level
+ ltype = process_literal_type
+ if code_block_open or ltype or continue or indent > 0
+ false
+ else
+ true
+ end
+ end
+end
+
+class AutoIndent < RubyLex
+ def initialize
+ set_input(self)
+ context = Struct.new(:auto_indent_mode).new(true)
+ set_auto_indent(context)
+ end
+
+ def auto_indent(&block)
+ Reline.auto_indent_proc = block
+ end
+end
diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb
index 0ab43fa60c..13693e7c4d 100644
--- a/test/reline/yamatanooroti/test_rendering.rb
+++ b/test/reline/yamatanooroti/test_rendering.rb
@@ -6,28 +6,27 @@ begin
class Reline::TestRendering < Yamatanooroti::TestCase
def setup
@pwd = Dir.pwd
- @tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_reline_config_#{$$}")
+ suffix = '%010d' % Random.rand(0..65535)
+ @tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_reline_config_#{$$}_#{suffix}")
begin
Dir.mkdir(@tmpdir)
rescue Errno::EEXIST
FileUtils.rm_rf(@tmpdir)
Dir.mkdir(@tmpdir)
end
- Dir.chdir(@tmpdir)
@inputrc_backup = ENV['INPUTRC']
@inputrc_file = ENV['INPUTRC'] = File.join(@tmpdir, 'temporaty_inputrc')
File.unlink(@inputrc_file) if File.exist?(@inputrc_file)
end
def teardown
- Dir.chdir(@pwd)
FileUtils.rm_rf(@tmpdir)
ENV['INPUTRC'] = @inputrc_backup
+ ENV.delete('RELINE_TEST_PROMPT') if ENV['RELINE_TEST_PROMPT']
end
def test_history_back
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
- sleep 0.5
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write(":a\n")
write("\C-p")
close
@@ -40,8 +39,7 @@ begin
end
def test_backspace
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
- sleep 0.5
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write(":abc\C-h\n")
close
assert_screen(<<~EOC)
@@ -53,8 +51,7 @@ begin
end
def test_autowrap
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
- sleep 0.5
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write('01234567890123456789012')
close
assert_screen(<<~EOC)
@@ -64,9 +61,32 @@ begin
EOC
end
+ def test_fullwidth
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write(":あ\n")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> :あ
+ => :あ
+ prompt>
+ EOC
+ end
+
+ def test_two_fullwidth
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write(":あい\n")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> :あい
+ => :あい
+ prompt>
+ EOC
+ end
+
def test_finish_autowrapped_line
- start_terminal(10, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
- sleep 0.5
+ start_terminal(10, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("[{'user'=>{'email'=>'a@a', 'id'=>'ABC'}, 'version'=>4, 'status'=>'succeeded'}]\n")
close
assert_screen(<<~EOC)
@@ -82,9 +102,9 @@ begin
end
def test_finish_autowrapped_line_in_the_middle_of_lines
- start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
- sleep 0.5
- write("[{'user'=>{'email'=>'abcdef@abcdef', 'id'=>'ABC'}, 'version'=>4, 'status'=>'succeeded'}]#{"\C-b"*7}\n")
+ start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("[{'user'=>{'email'=>'abcdef@abcdef', 'id'=>'ABC'}, 'version'=>4, 'status'=>'succeeded'}]#{"\C-b"*7}")
+ write("\n")
close
assert_screen(<<~EOC)
Multiline REPL.
@@ -101,8 +121,7 @@ begin
end
def test_finish_autowrapped_line_in_the_middle_of_multilines
- start_terminal(30, 16, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
- sleep 0.5
+ start_terminal(30, 16, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("<<~EOM\n ABCDEFG\nEOM\n")
close
assert_screen(<<~'EOC')
@@ -117,13 +136,10 @@ begin
end
def test_prompt
- File.open(@inputrc_file, 'w') do |f|
- f.write <<~'LINES'
- "abc": "123"
- LINES
- end
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
- sleep 0.5
+ write_inputrc <<~'LINES'
+ "abc": "123"
+ LINES
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("abc\n")
close
assert_screen(<<~EOC)
@@ -134,14 +150,11 @@ begin
EOC
end
- def test_mode_icon_emacs
- File.open(@inputrc_file, 'w') do |f|
- f.write <<~LINES
- set show-mode-in-prompt on
- LINES
- end
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
- sleep 0.5
+ def test_mode_string_emacs
+ write_inputrc <<~LINES
+ set show-mode-in-prompt on
+ LINES
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
close
assert_screen(<<~EOC)
Multiline REPL.
@@ -149,15 +162,12 @@ begin
EOC
end
- def test_mode_icon_vi
- File.open(@inputrc_file, 'w') do |f|
- f.write <<~LINES
- set editing-mode vi
- set show-mode-in-prompt on
- LINES
- end
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
- sleep 0.5
+ def test_mode_string_vi
+ write_inputrc <<~LINES
+ set editing-mode vi
+ set show-mode-in-prompt on
+ LINES
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write(":a\n\C-[k")
close
assert_screen(<<~EOC)
@@ -168,14 +178,12 @@ begin
EOC
end
- def test_original_mode_icon_emacs
- File.open(@inputrc_file, 'w') do |f|
- f.write <<~LINES
- set show-mode-in-prompt on
- set emacs-mode-string [emacs]
- LINES
- end
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
+ def test_original_mode_string_emacs
+ write_inputrc <<~LINES
+ set show-mode-in-prompt on
+ set emacs-mode-string [emacs]
+ LINES
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
close
assert_screen(<<~EOC)
Multiline REPL.
@@ -183,14 +191,12 @@ begin
EOC
end
- def test_original_mode_icon_with_quote
- File.open(@inputrc_file, 'w') do |f|
- f.write <<~LINES
- set show-mode-in-prompt on
- set emacs-mode-string "[emacs]"
- LINES
- end
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
+ def test_original_mode_string_with_quote
+ write_inputrc <<~LINES
+ set show-mode-in-prompt on
+ set emacs-mode-string "[emacs]"
+ LINES
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
close
assert_screen(<<~EOC)
Multiline REPL.
@@ -198,16 +204,14 @@ begin
EOC
end
- def test_original_mode_icon_vi
- File.open(@inputrc_file, 'w') do |f|
- f.write <<~LINES
- set editing-mode vi
- set show-mode-in-prompt on
- set vi-ins-mode-string "{InS}"
- set vi-cmd-mode-string "{CmD}"
- LINES
- end
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/bin/multiline_repl})
+ def test_original_mode_string_vi
+ write_inputrc <<~LINES
+ set editing-mode vi
+ set show-mode-in-prompt on
+ set vi-ins-mode-string "{InS}"
+ set vi-cmd-mode-string "{CmD}"
+ LINES
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write(":a\n\C-[k")
close
assert_screen(<<~EOC)
@@ -217,6 +221,520 @@ begin
{CmD}prompt> :a
EOC
end
+
+ def test_mode_string_vi_changing
+ write_inputrc <<~LINES
+ set editing-mode vi
+ set show-mode-in-prompt on
+ LINES
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write(":a\C-[ab\C-[ac\C-h\C-h\C-h\C-h:a")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ (ins)prompt> :a
+ EOC
+ end
+
+ def test_prompt_with_escape_sequence
+ ENV['RELINE_TEST_PROMPT'] = "\1\e[30m\2prompt> \1\e[m\2"
+ start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("123\n")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> 123
+ => 123
+ prompt>
+ EOC
+ end
+
+ def test_prompt_with_escape_sequence_and_autowrap
+ ENV['RELINE_TEST_PROMPT'] = "\1\e[30m\2prompt> \1\e[m\2"
+ start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("1234567890123\n")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> 123456789012
+ 3
+ => 1234567890123
+ prompt>
+ EOC
+ end
+
+ def test_multiline_and_autowrap
+ start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def aaaaaaaaaa\n 33333333\n end\C-a\C-pputs\C-e\e\C-m888888888888888")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def aaaaaaaa
+ aa
+ prompt> puts 333333
+ 33
+ prompt> 888888888888
+ 888
+ prompt> e
+ nd
+ EOC
+ end
+
+ def test_clear
+ start_terminal(10, 15, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("3\C-l")
+ close
+ assert_screen(<<~EOC)
+ prompt> 3
+ EOC
+ end
+
+ def test_clear_multiline_and_autowrap
+ omit # FIXME clear logic is buggy
+ start_terminal(10, 15, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def aaaaaa\n 3\n\C-lend")
+ close
+ assert_screen(<<~EOC)
+ prompt> def aaa
+ aaa
+ prompt> 3
+ prompt> end
+ EOC
+ end
+
+ def test_nearest_cursor
+ start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def ああ\n :いい\nend\C-pbb\C-pcc")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def ccああ
+ prompt> :bbいい
+ prompt> end
+ EOC
+ end
+
+ def test_delete_line
+ start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def a\n\nend\C-p\C-h")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def a
+ prompt> end
+ EOC
+ end
+
+ def test_last_line_of_screen
+ start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("\n\n\n\n\ndef a\nend")
+ close
+ assert_screen(<<~EOC)
+ prompt>
+ prompt>
+ prompt>
+ prompt> def a
+ prompt> end
+ EOC
+ end
+
+ # c17a09b7454352e2aff5a7d8722e80afb73e454b
+ def test_autowrap_at_last_line_of_screen
+ start_terminal(5, 15, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def a\nend\n\C-p")
+ close
+ assert_screen(<<~EOC)
+ prompt> def a
+ prompt> end
+ => :a
+ prompt> def a
+ prompt> end
+ EOC
+ end
+
+ # f002483b27cdb325c5edf9e0fe4fa4e1c71c4b0e
+ def test_insert_line_in_the_middle_of_line
+ start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("333\C-b\C-b\e\C-m8")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> 3
+ prompt> 833
+ EOC
+ end
+
+ # 9d8978961c5de5064f949d56d7e0286df9e18f43
+ def test_insert_line_in_the_middle_of_line_at_last_line_of_screen
+ start_terminal(3, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("333333333333333\C-a\C-f\e\C-m")
+ close
+ assert_screen(<<~EOC)
+ prompt> 3
+ prompt> 333333333333
+ 33
+ EOC
+ end
+
+ def test_insert_after_clear
+ start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def a\n 01234\nend\C-l\C-p5678")
+ close
+ assert_screen(<<~EOC)
+ prompt> def a
+ prompt> 056781234
+ prompt> end
+ EOC
+ end
+
+ def test_foced_newline_insertion
+ start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ #write("def a\nend\C-p\C-e\e\C-m 3")
+ write("def a\nend\C-p\C-e\e\x0D")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def a
+ prompt>
+ prompt> end
+ EOC
+ end
+
+ def test_multiline_incremental_search
+ start_terminal(6, 25, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def a\n 8\nend\ndef b\n 3\nend\C-s8")
+ close
+ assert_screen(<<~EOC)
+ (i-search)`8'def a
+ (i-search)`8' 8
+ (i-search)`8'end
+ EOC
+ end
+
+ def test_multiline_incremental_search_finish
+ start_terminal(6, 25, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def a\n 8\nend\ndef b\n 3\nend\C-r8\C-j")
+ close
+ assert_screen(<<~EOC)
+ prompt> def a
+ prompt> 8
+ prompt> end
+ EOC
+ end
+
+ def test_binding_for_vi_movement_mode
+ write_inputrc <<~LINES
+ set editing-mode vi
+ "\\C-j": vi-movement-mode
+ LINES
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write(":1234\C-jhhhi0")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> :01234
+ EOC
+ end
+
+ def test_prompt_list_caching
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --prompt-list-cache-timeout 10 --dynamic-prompt}, startup_message: 'Multiline REPL.')
+ write("def hoge\n 3\nend")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ [0000]> def hoge
+ [0001]> 3
+ [0002]> end
+ EOC
+ end
+
+ def test_broken_prompt_list
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --broken-dynamic-prompt}, startup_message: 'Multiline REPL.')
+ write("def hoge\n 3\nend")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ [0000]> def hoge
+ [0001]> 3
+ [0001]> end
+ EOC
+ end
+
+ def test_enable_bracketed_paste
+ omit if Reline::IOGate.win?
+ write_inputrc <<~LINES
+ set enable-bracketed-paste on
+ LINES
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("\e[200~,")
+ write("def hoge\n 3\nend")
+ write("\e[200~.")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def hoge
+ prompt> 3
+ prompt> end
+ EOC
+ end
+
+ def test_backspace_until_returns_to_initial
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("ABC")
+ write("\C-h\C-h\C-h")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt>
+ EOC
+ end
+
+ def test_longer_than_screen_height
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write(<<~EOC.chomp)
+ def each_top_level_statement
+ initialize_input
+ catch(:TERM_INPUT) do
+ loop do
+ begin
+ prompt
+ unless l = lex
+ throw :TERM_INPUT if @line == ''
+ else
+ @line_no += l.count("\n")
+ next if l == "\n"
+ @line.concat l
+ if @code_block_open or @ltype or @continue or @indent > 0
+ next
+ end
+ end
+ if @line != "\n"
+ @line.force_encoding(@io.encoding)
+ yield @line, @exp_line_no
+ end
+ break if @io.eof?
+ @line = ''
+ @exp_line_no = @line_no
+ #
+ @indent = 0
+ rescue TerminateLineInput
+ initialize_input
+ prompt
+ end
+ end
+ end
+ end
+ EOC
+ sleep 1
+ close
+ assert_screen(<<~EOC)
+ prompt> prompt
+ prompt> end
+ prompt> end
+ prompt> end
+ prompt> end
+ EOC
+ end
+
+ def test_longer_than_screen_height_with_scroll_back
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write(<<~EOC.chomp)
+ def each_top_level_statement
+ initialize_input
+ catch(:TERM_INPUT) do
+ loop do
+ begin
+ prompt
+ unless l = lex
+ throw :TERM_INPUT if @line == ''
+ else
+ @line_no += l.count("\n")
+ next if l == "\n"
+ @line.concat l
+ if @code_block_open or @ltype or @continue or @indent > 0
+ next
+ end
+ end
+ if @line != "\n"
+ @line.force_encoding(@io.encoding)
+ yield @line, @exp_line_no
+ end
+ break if @io.eof?
+ @line = ''
+ @exp_line_no = @line_no
+ #
+ @indent = 0
+ rescue TerminateLineInput
+ initialize_input
+ prompt
+ end
+ end
+ end
+ end
+ EOC
+ sleep 1
+ write("\C-p" * 6)
+ close
+ assert_screen(<<~EOC)
+ prompt> rescue Terminate
+ LineInput
+ prompt> initialize_inp
+ ut
+ prompt> prompt
+ EOC
+ end
+
+ def test_longer_than_screen_height_with_complex_scroll_back
+ start_terminal(4, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write(<<~EOC.chomp)
+ def each_top_level_statement
+ initialize_input
+ catch(:TERM_INPUT) do
+ loop do
+ begin
+ prompt
+ unless l = lex
+ throw :TERM_INPUT if @line == ''
+ else
+ @line_no += l.count("\n")
+ next if l == "\n"
+ @line.concat l
+ if @code_block_open or @ltype or @continue or @indent > 0
+ next
+ end
+ end
+ if @line != "\n"
+ @line.force_encoding(@io.encoding)
+ yield @line, @exp_line_no
+ end
+ break if @io.eof?
+ @line = ''
+ @exp_line_no = @line_no
+ #
+ @indent = 0
+ rescue TerminateLineInput
+ initialize_input
+ prompt
+ end
+ end
+ end
+ end
+ EOC
+ sleep 1
+ write("\C-p" * 5)
+ write("\C-n" * 3)
+ close
+ assert_screen(<<~EOC)
+ ut
+ prompt> prompt
+ prompt> end
+ prompt> end
+ EOC
+ end
+
+ def test_update_cursor_correctly_when_just_cursor_moving
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def hoge\n 01234678")
+ write("\C-p")
+ write("\C-b")
+ write("\C-n")
+ write('5')
+ write("\C-e")
+ write('9')
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def hoge
+ prompt> 0123456789
+ EOC
+ end
+
+ def test_suppress_auto_indent_just_after_pasted
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ write("def hoge\n [[\n 3]]\ned")
+ write("\C-bn")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def hoge
+ prompt> [[
+ prompt> 3]]
+ prompt> end
+ EOC
+ end
+
+ def test_suppress_auto_indent_for_adding_newlines_in_pasting
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ write("<<~Q\n")
+ write("{\n #\n}")
+ write("#")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> <<~Q
+ prompt> {
+ prompt> #
+ prompt> }#
+ EOC
+ end
+
+ def test_autowrap_in_the_middle_of_a_line
+ start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def abcdefg; end\C-b\C-b\C-b\C-b\C-b")
+ %w{h i}.each do |c|
+ write(c)
+ end
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def abcdefgh
+ i; end
+ EOC
+ end
+
+ def test_terminate_in_the_middle_of_lines
+ start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def hoge\n 1\n 2\n 3\n 4\nend\n")
+ write("\C-p\C-p\C-p\C-e\n")
+ close
+ assert_screen(<<~EOC)
+ prompt> 3
+ prompt> 4
+ prompt> end
+ => :hoge
+ prompt>
+ EOC
+ end
+
+ def test_dynamic_prompt_returns_empty
+ start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dynamic-prompt-returns-empty}, startup_message: 'Multiline REPL.')
+ write("def hoge\nend\n")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def hoge
+ prompt> end
+ => :hoge
+ prompt>
+ EOC
+ end
+
+ def test_reset_rest_height_when_clear_screen
+ start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("\n\n\n\C-l3\n")
+ close
+ assert_screen(<<~EOC)
+ prompt> 3
+ => 3
+ prompt>
+ EOC
+ end
+
+ private def write_inputrc(content)
+ File.open(@inputrc_file, 'w') do |f|
+ f.write content
+ end
+ end
end
rescue LoadError, NameError
# On Ruby repository, this test suit doesn't run because Ruby repo doesn't
diff --git a/test/resolv/test_addr.rb b/test/resolv/test_addr.rb
index 14ec2651ab..62092676ba 100644
--- a/test/resolv/test_addr.rb
+++ b/test/resolv/test_addr.rb
@@ -16,6 +16,28 @@ class TestResolvAddr < Test::Unit::TestCase
}
end
+ def test_valid_ipv6_link_local_address
+ bug17112 = "[ruby-core:99539]"
+ assert_not_match(Resolv::IPv6::Regex, "fe80::1%", bug17112)
+ assert_not_match(Resolv::IPv6::Regex, "fe80:2:3:4:5:6:7:8%", bug17112)
+ assert_not_match(Resolv::IPv6::Regex, "fe90::1%em1", bug17112)
+ assert_not_match(Resolv::IPv6::Regex, "1:2:3:4:5:6:7:8%em1", bug17112)
+ assert_match(Resolv::IPv6::Regex, "fe80:2:3:4:5:6:7:8%em1", bug17112)
+ assert_match(Resolv::IPv6::Regex, "fe80::20d:3aff:fe7d:9760%eth0", bug17112)
+ assert_match(Resolv::IPv6::Regex, "fe80::1%em1", bug17112)
+ assert_match(Resolv::IPv6::Regex, "FE80:2:3:4:5:6:7:8%EM1", bug17112)
+ assert_match(Resolv::IPv6::Regex, "FE80::20D:3AFF:FE7D:9760%ETH0", bug17112)
+ assert_match(Resolv::IPv6::Regex, "FE80::1%EM1", bug17112)
+ end
+
+ def test_valid_socket_ip_address_list
+ Socket.ip_address_list.each do |addr|
+ ip = addr.ip_address
+ assert_match(Resolv::AddressRegex, ip)
+ assert_equal(ip, Resolv.getaddress(ip))
+ end
+ end
+
def test_invalid_byte_comment
bug9273 = '[ruby-core:59239] [Bug #9273]'
Tempfile.create('resolv_test_addr_') do |tmpfile|
diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb
index 617babf829..d3c4b1f3e9 100644
--- a/test/resolv/test_dns.rb
+++ b/test/resolv/test_dns.rb
@@ -156,7 +156,7 @@ class TestResolvDNS < Test::Unit::TestCase
ra = (flags & 0x0080) >> 7
z = (flags & 0x0070) >> 4
rcode = flags & 0x000f
- rest = msg[12..-1]
+ _rest = msg[12..-1]
questions = msg.bytes[12..-1]
labels = []
diff --git a/test/rexml/data/LostineRiver.kml.gz b/test/rexml/data/LostineRiver.kml.gz
deleted file mode 100644
index 68a00c51db..0000000000
--- a/test/rexml/data/LostineRiver.kml.gz
+++ /dev/null
Binary files differ
diff --git a/test/rexml/data/ProductionSupport.xml b/test/rexml/data/ProductionSupport.xml
deleted file mode 100644
index 083cf64a6e..0000000000
--- a/test/rexml/data/ProductionSupport.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-
-<ProductionSupport version="1.1" >
- <Errors>
- <CommonErrors>
- <CommonError>
- <Key><![CDATA[RoyUpdatePolicyBusReq(Object)>>#error:]]></Key>
- <Patterns>
- <Pattern><![CDATA[The error code is '9997']]></Pattern>
- </Patterns>
- <Message>
- <String>Update Policy request 9997: Please check CICS log</String>
- </Message>
- <BackendSupport/>
- </CommonError>
- <CommonError>
- <Key>MotorInsuranceContract(Object)>>#error:</Key>
- <Patterns>
- <Pattern>Have not got a complete</Pattern>
- </Patterns>
- <Message>
- <String>Have not got a complete and consistent set of price matrices for policy period - ask back-end prod supp to sort out</String>
- </Message>
- <BackendSupport/>
- </CommonError>
-</CommonErrors>
-</Errors>
-</ProductionSupport>
diff --git a/test/rexml/data/axis.xml b/test/rexml/data/axis.xml
deleted file mode 100644
index bc996c571d..0000000000
--- a/test/rexml/data/axis.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0"?>
-
-<root>
-
- <a>
- <a.1/>
- <a.2/>
- <a.3/>
- <a.4/>
- <a.5/>
- </a>
-
- <b>
- <b.1/>
- <b.2/>
- <b.3/>
- <b.4/>
- <b.5/>
- <b.6/>
- <b.7/>
- <b.8/>
- <b.9/>
- </b>
-
-</root>
diff --git a/test/rexml/data/bad.xml b/test/rexml/data/bad.xml
deleted file mode 100644
index 18786f2b43..0000000000
--- a/test/rexml/data/bad.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<a>
- Here is an XML document.
- <b>
- It has some elements, but it also has a hidden < error! (or two)
- </a>
diff --git a/test/rexml/data/basic.xml b/test/rexml/data/basic.xml
deleted file mode 100644
index 88385fb6e1..0000000000
--- a/test/rexml/data/basic.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-
-<foo>
- <bar>
- <baz/>
- <cheese/>
- <baz/>
- <cheese/>
- <baz/>
- </bar>
-</foo>
diff --git a/test/rexml/data/basicupdate.xml b/test/rexml/data/basicupdate.xml
deleted file mode 100644
index 57d458cf2a..0000000000
--- a/test/rexml/data/basicupdate.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-
-<xu:modifications xmlns:xu="http://www.xmldb.org/xupdate">
-
- <xu:append select="/foo/bar/cheese[1]">
- Goudse kaas
- <edam type="jong belegen">Rond</edam>
- </xu:append>
-
- <xu:remove select="/foo/bar/baz[2]"/>
-
- <xu:if test="/foo">
- <xu:insert-before select="/foo/bar/baz[2]">
- <cheese>More cheese!</cheese>
- </xu:insert-before>
- </xu:if>
-
- <xu:insert-before select="/foo/bar/baz[2]">
- <cheese>Even more cheese!</cheese>
- </xu:insert-before>
-
- <xu:if test="/bar">
- <xu:insert-before select="/foo/bar/baz[2]">
- <sausages>No sausages today</sausages>
- </xu:insert-before>
- </xu:if>
-
- <xu:variable
- xmlns:private="http://www.jaxen.org/private"
- name="private:twice">
- <cracker/>
- <!-- champagne -->
- <?oisters with a bit of lemon?>
- </xu:variable>
-
- <xu:variable name="twice" select="'Twice'"/>
-
- <xu:insert-after
- select="/foo/bar"
- xmlns:private="http://www.jaxen.org/private"
- >
- <xu:value-of select="$private:twice"/>
- <xu:value-of select="$private:twice"/>
- <xu:value-of select="$twice"/>
- </xu:insert-after>
-
-</xu:modifications>
diff --git a/test/rexml/data/broken.rss b/test/rexml/data/broken.rss
deleted file mode 100644
index d5f29e5d1f..0000000000
--- a/test/rexml/data/broken.rss
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE rdf:RDF [
- <!ENTITY % HTMLlat1 PUBLIC
- "-//W3C//ENTITIES Latin 1 for XHTML//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml-lat1.ent">
- %HTMLlat1;
-]>
-
-<rdf:RDF
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:on="http://www.oreillynet.com/csrss/"
- xmlns="http://purl.org/rss/1.0/"
->
-
- <channel rdf:about="http://www.oreillynet.com/">
- <title>O'Reilly Network Articles</title>
- <link>http://www.oreillynet.com/</link>
- </channel>
-</rdf:RDF>
diff --git a/test/rexml/data/contents.xml b/test/rexml/data/contents.xml
deleted file mode 100644
index 35e3ac7044..0000000000
--- a/test/rexml/data/contents.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0"?>
-
-<?xml-stylesheet href="XSL\JavaXML.html.xsl" type="text/xsl"?>
-<?xml-stylesheet href="XSL\JavaXML.wml.xsl" type="text/xsl"
- media="wap"?>
-<?cocoon-process type="xslt"?>
-
-<!-- Java and XML -->
-<JavaXML:Book xmlns:JavaXML="http://www.oreilly.com/catalog/javaxml/"
- xmlns:ora="http://www.oreilly.com"
- xmlns:unused="http://www.unused.com"
- ora:category="Java"
->
- <!-- comment one -->
- <!-- comment two -->
-
- <JavaXML:Title>Java and XML</JavaXML:Title>
- <JavaXML:Contents xmlns:topic="http://www.oreilly.com/topics">
- <JavaXML:Chapter topic:focus="XML">
- <JavaXML:Heading>Introduction</JavaXML:Heading>
- <JavaXML:Topic subSections="7">
- What Is It?
- </JavaXML:Topic>
- <JavaXML:Topic subSections="3">
- How Do I Use It?
- </JavaXML:Topic>
- <JavaXML:Topic subSections="4">
- Why Should I Use It?
- </JavaXML:Topic>
- <JavaXML:Topic subSections="0">
- What's Next?
- </JavaXML:Topic>
- </JavaXML:Chapter>
-
- <JavaXML:Chapter topic:focus="XML">
- <JavaXML:Heading>Creating XML</JavaXML:Heading>
- <JavaXML:Topic subSections="0">An XML Document</JavaXML:Topic>
- <JavaXML:Topic subSections="2">The Header</JavaXML:Topic>
- <JavaXML:Topic subSections="6">The Content</JavaXML:Topic>
- <JavaXML:Topic subSections="1">What's Next?</JavaXML:Topic>
- </JavaXML:Chapter>
-
- <JavaXML:Chapter topic:focus="Java">
- <JavaXML:Heading>Parsing XML</JavaXML:Heading>
- <JavaXML:Topic subSections="3">Getting Prepared</JavaXML:Topic>
- <JavaXML:Topic subSections="3">SAX Readers</JavaXML:Topic>
- <JavaXML:Topic subSections="9">Content Handlers</JavaXML:Topic>
- <JavaXML:Topic subSections="4">Error Handlers</JavaXML:Topic>
- <JavaXML:Topic subSections="0">
- A Better Way to Load a Parser
- </JavaXML:Topic>
- <JavaXML:Topic subSections="4">"Gotcha!"</JavaXML:Topic>
- <JavaXML:Topic subSections="0">What's Next?</JavaXML:Topic>
- </JavaXML:Chapter>
-
- <JavaXML:SectionBreak/>
-
- <JavaXML:Chapter topic:focus="Java">
- <JavaXML:Heading>Web Publishing Frameworks</JavaXML:Heading>
- <JavaXML:Topic subSections="4">Selecting a Framework</JavaXML:Topic>
- <JavaXML:Topic subSections="4">Installation</JavaXML:Topic>
- <JavaXML:Topic subSections="3">
- Using a Publishing Framework
- </JavaXML:Topic>
- <JavaXML:Topic subSections="2">XSP</JavaXML:Topic>
- <JavaXML:Topic subSections="3">Cocoon 2.0 and Beyond</JavaXML:Topic>
- <JavaXML:Topic subSections="0">What's Next?</JavaXML:Topic>
- </JavaXML:Chapter>
- </JavaXML:Contents>
-</JavaXML:Book>
diff --git a/test/rexml/data/dash.xml b/test/rexml/data/dash.xml
deleted file mode 100644
index e1be655750..0000000000
--- a/test/rexml/data/dash.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<content-repository>
- <content-repository-child-1>
- <content-1>content-1-text</content-1>
- </content-repository-child-1>
- <content-repository-child-2>
- <content-2>content-2-text</content-2>
- </content-repository-child-2>
- <content-repository-child-3>
- <content-3>content-3-text</content-3>
- </content-repository-child-3>
-</content-repository>
diff --git a/test/rexml/data/defaultNamespace.xml b/test/rexml/data/defaultNamespace.xml
deleted file mode 100644
index 1e32981506..0000000000
--- a/test/rexml/data/defaultNamespace.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0"?>
-<a xmlns="http://dummyNamespace/">
- <b>
- <c>Hello</c>
- </b>
-</a>
diff --git a/test/rexml/data/doctype_test.xml b/test/rexml/data/doctype_test.xml
deleted file mode 100644
index a690cab99d..0000000000
--- a/test/rexml/data/doctype_test.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<!DOCTYPE internationalization SYSTEM "l10n.dtd" [
-<!ENTITY af SYSTEM "af.xml">
-<!ENTITY ca SYSTEM "ca.xml">
-<!ENTITY cs SYSTEM "cs.xml">
-<!ENTITY da SYSTEM "da.xml">
-<!ENTITY de SYSTEM "de.xml">
-<!ENTITY el SYSTEM "el.xml">
-<!ENTITY en SYSTEM "en.xml">
-<!ENTITY es SYSTEM "es.xml">
-<!ENTITY et SYSTEM "et.xml">
-<!ENTITY fi SYSTEM "fi.xml">
-<!ENTITY fr SYSTEM "fr.xml">
-<!ENTITY hu SYSTEM "hu.xml">
-<!ENTITY id SYSTEM "id.xml">
-<!ENTITY it SYSTEM "it.xml">
-<!ENTITY ja SYSTEM "ja.xml">
-<!ENTITY ko SYSTEM "ko.xml">
-<!ENTITY nl SYSTEM "nl.xml">
-<!ENTITY no SYSTEM "no.xml">
-<!ENTITY no_ny SYSTEM "no_ny.xml">
-<!ENTITY pl SYSTEM "pl.xml">
-<!ENTITY pt SYSTEM "pt.xml">
-<!ENTITY pt_br SYSTEM "pt_br.xml">
-<!ENTITY ro SYSTEM "ro.xml">
-<!ENTITY ru SYSTEM "ru.xml">
-<!ENTITY sk SYSTEM "sk.xml">
-<!ENTITY sl SYSTEM "sl.xml">
-<!ENTITY sr SYSTEM "sr.xml">
-<!ENTITY sv SYSTEM "sv.xml">
-<!ENTITY tr SYSTEM "tr.xml">
-<!ENTITY zh_cn SYSTEM "zh_cn.xml">
-<!ENTITY zh_tw SYSTEM "zh_tw.xml">
-]>
-<x/>
diff --git a/test/rexml/data/documentation.xml b/test/rexml/data/documentation.xml
deleted file mode 100644
index a1ad6e878b..0000000000
--- a/test/rexml/data/documentation.xml
+++ /dev/null
@@ -1,542 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/css" href="http://www.germane-software.com/repositories/public/documentation/documentation.css"?>
-<?xml-stylesheet alternative="yes" type="text/css" href="file:/home/ser/Work/documentation/documentation.css"?>
-<?xml-stylesheet alternative="yes" type="text/xsl" href="http://www.germane-software.com/repositories/public/documentation/paged.xsl"?>
-<!DOCTYPE documentation SYSTEM "http://www.germane-software.com/repositories/public/documentation/documentation.dtd">
-<documentation>
- <head>
- <title>REXML</title>
-
- <banner href="img/rexml.png" />
-
- <version>@ANT_VERSION@</version>
-
- <date>@ANT_DATE@</date>
-
- <home>http://www.germane-software.com/software/rexml</home>
-
- <base>rexml</base>
-
- <language>ruby</language>
-
- <author email="ser@germane-software.com"
- href="http://www.ser1.net/" jabber="seanerussell@gmail.com">Sean
- Russell</author>
- </head>
-
- <overview>
- <purpose lang="en">
- <p>REXML is a conformant XML processor for the Ruby programming
- language. REXML passes 100% of the Oasis non-validating tests and
- includes full XPath support. It is reasonably fast, and is implemented
- in pure Ruby. Best of all, it has a clean, intuitive API. REXML is
- included in the standard library of Ruby</p>
-
- <p>This software is distribute under the <link href="LICENSE.txt">Ruby
- license</link>.</p>
- </purpose>
-
- <general>
- <p>REXML arose out of a desire for a straightforward XML API, and is an
- attempt at an API that doesn't require constant referencing of
- documentation to do common tasks. "Keep the common case simple, and the
- uncommon, possible."</p>
-
- <p>REXML avoids The DOM API, which violates the maxim of simplicity. It
- does provide <em>a</em> DOM model, but one that is Ruby-ized. It is an
- XML API oriented for Ruby programmers, not for XML programmers coming
- from Java.</p>
-
- <p>Some of the common differences are that the Ruby API relies on block
- enumerations, rather than iterators. For example, the Java code:</p>
-
- <example>for (Enumeration e=parent.getChildren(); e.hasMoreElements(); ) {
- Element child = (Element)e.nextElement(); // Do something with child
-}</example>
-
- <p>in Ruby becomes:</p>
-
- <example>parent.each_child{ |child| # Do something with child }</example>
-
- <p>Can't you feel the peace and contentment in this block of code? Ruby
- is the language Buddha would have programmed in.</p>
-
- <p>One last thing. If you use and like this software, and you're in a
- position of power in a company in Western Europe and are looking for a
- software architect or developer, drop me a line. I took a lot of French
- classes in college (all of which I've forgotten), and I lived in Munich
- long enough that I was pretty fluent by the time I left, and I'd love to
- get back over there.</p>
- </general>
-
- <features lang="en">
- <item>Four intuitive parsing APIs.</item>
-
- <item>Intuitive, powerful, and reasonably fast tree parsing API (a-la
- DOM</item>
-
- <item>Fast stream parsing API (a-la SAX)<footnote>This is not a SAX
- API.</footnote></item>
-
- <item>SAX2-based API<footnote>In addition to the native REXML streaming
- API. This is slower than the native REXML API, but does a lot more work
- for you.</footnote></item>
-
- <item>Pull parsing API.</item>
-
- <item>Small</item>
-
- <item>Reasonably fast (for interpreted code)</item>
-
- <item>Native Ruby</item>
-
- <item>Full XPath support<footnote>Currently only available for the tree
- API</footnote></item>
-
- <item>XML 1.0 conformant<footnote>REXML passes all of the non-validating
- OASIS tests. There are probably places where REXML isn't conformant, but
- I try to fix them as they're reported.</footnote></item>
-
- <item>ISO-8859-1, UNILE, UTF-16 and UTF-8 input and output; also,
- support for any encoding the iconv supports.</item>
-
- <item>Documentation</item>
- </features>
- </overview>
-
- <operation lang="en">
- <subsection title="Installation">
- <p>You don't <em>have</em> to install anything; if you're running a
- version of Ruby greater than 1.8, REXML is included. However, if you
- choose to upgrade from the REXML distribution, run the command:
- <code>ruby bin/install.rb</code>. By the way, you really should look at
- these sorts of files before you run them as root. They could contain
- anything, and since (in Ruby, at least) they tend to be mercifully
- short, it doesn't hurt to glance over them. If you want to uninstall
- REXML, run <code>ruby bin/install.rb -u</code>.</p>
- </subsection>
-
- <subsection title="Unit tests">
- <p>If you have Test::Unit installed, you can run the unit test cases.
- Run the command: <code>ruby bin/suite.rb</code>; it runs against the
- distribution, not against the installed version.</p>
- </subsection>
-
- <subsection title="Benchmarks">
- <p>There is a benchmark suite in <code>benchmarks/</code>. To run the
- benchmarks, change into that directory and run <code>ruby
- comparison.rb</code>. If you have nothing else installed, only the
- benchmarks for REXML will be run. However, if you have any of the
- following installed, benchmarks for those tools will also be run:</p>
-
- <list>
- <item>NQXML</item>
-
- <item>XMLParser</item>
-
- <item>Electric XML (you must copy <code>EXML.jar</code> into the
- <code>benchmarks</code> directory and compile
- <code>flatbench.java</code> before running the test)</item>
- </list>
-
- <p>The results will be written to <code>index.html</code>.</p>
- </subsection>
-
- <subsection title="General Usage">
- <p>Please see <link href="docs/tutorial.html">the Tutorial</link>.</p>
-
- <p>The API documentation is available <link
- href="http://www.germane-software.com/software/XML/rexml/doc">on-line</link>,
- or it can be downloaded as an archive <link
- href="http://www.germane-software.com/software/archives/rexml_api_@ANT_VERSION@.tgz">in
- tgz format (~70Kb)</link> or (if you're a masochist) <link
- href="http://www.germane-software.com/software/archives/rexml_api_@ANT_VERSION@.zip">in
- zip format (~280Kb)</link>. The best solution is to download and install
- Dave Thomas' most excellent <link
- href="http://rdoc.sourceforge.net">rdoc</link> and generate the API docs
- yourself; then you'll be sure to have the latest API docs and won't have
- to keep downloading the doc archive.</p>
-
- <p>The unit tests in <code>test/</code> and the benchmarking code in
- <code>benchmark/</code> provide additional examples of using REXML. The
- Tutorial provides examples with commentary. The documentation unpacks
- into <link href="doc/index.html"><code>rexml/doc</code></link>.</p>
-
- <p>Kouhei Sutou maintains a <link
- href="http://www.germane-software.com/software/rexml_doc_ja/current/index.html">Japanese
- version</link> of the REXML API docs. <link
- href="http://www.germane-software.com/software/rexml_doc_ja/current/japanese_documentation.html">Kou's
- documentation page</link> contains links to binary archives for various
- versions of the documentation.</p>
- </subsection>
- </operation>
-
- <status>
- <subsection title="Speed and Completeness">
- <p>Unfortunately, NQXML is the only package REXML can be compared
- against; XMLParser uses expat, which is a native library, and really is
- a different beast altogether. So in comparing NQXML and REXML you can
- look at four things: speed, size, completeness, and API.</p>
-
- <p><link href="benchmarks/index.html">Benchmarks</link></p>
-
- <p>REXML is faster than NQXML in some things, and slower than NQXML in a
- couple of things. You can see this for yourself by running the supplied
- benchmarks. Most of the places where REXML are slower are because of the
- convenience methods<footnote>For example,
- <code>element.elements[index]</code> isn't really an array operation;
- index can be an Integer or an XPath, and this feature is relatively time
- expensive.</footnote>. On the positive side, most of the convenience
- methods can be bypassed if you know what you are doing. Check the <link
- href="benchmarks/index.html"> benchmark comparison page</link> for a
- <em>general</em> comparison. You can look at the benchmark code yourself
- to decide how much salt to take with them.</p>
-
- <p>The sizes of the XML parsers are close<footnote>As measured with
- <code>ruby -nle 'print unless /^\s*(#.*|)$/' *.rb | wc -l</code>
- </footnote>. NQXML 1.1.3 has 1580 non-blank, non-comment lines of code;
- REXML 2.0 has 2340<footnote>REXML started out with about 1200, but that
- number has been steadily increasing as features are added. XPath
- accounts for 541 lines of that code, so the core REXML has about 1800
- LOC.</footnote>.</p>
-
- <p>REXML is a conformant XML 1.0 parser. It supports multiple language
- encodings, and internal processing uses the required UTF-8 and UTF-16
- encodings. It passes 100% of the Oasis non-validating tests.
- Furthermore, it provides a full implementation of XPath, a SAX2 and a
- PullParser API.</p>
- </subsection>
-
- <subsection title="XPath">
- <p>As of release 2.0, XPath 1.0 is fully implemented.</p>
-
- <p>I fully expect bugs to crop up from time to time, so if you see any
- bogus XPath results, please let me know. That said, since I'm now
- following the XPath grammar and spec fairly closely, I suspect that you
- won't be surprised by REXML's XPath very often, and it should become
- rock solid fairly quickly.</p>
-
- <p>Check the "bugs" section for known problems; there are little bits of
- XPath here and there that are not yet implemented, but I'll get to them
- soon.</p>
-
- <p>Namespace support is rather odd, but it isn't my fault. I can only do
- so much and still conform to the specs. In particular, XPath attempts to
- help as much as possible. Therefore, in the trivial cases, you can pass
- namespace prefixes to Element.elements[...] and so on -- in these cases,
- XPath will use the namespace environment of the base element you're
- starting your XPath search from. However, if you want to do something
- more complex, like pass in your own namespace environment, you have to
- use the XPath first(), each(), and match() methods. Also, default
- namespaces <em>force</em> you to use the XPath methods, rather than the
- convenience methods, because there is no way for XPath to know what the
- mappings for the default namespaces should be. This is exactly why I
- loath namespaces -- a pox on the person(s) who thought them up!</p>
- </subsection>
-
- <subsection title="Namespaces">
- <p>Namespace support is now fairly stable. One thing to be aware of is
- that REXML is not (yet) a validating parser. This means that some
- invalid namespace declarations are not caught.</p>
- </subsection>
-
- <subsection title="Mailing list">
- <p>There is a low-volume mailing list dedicated to REXML. To subscribe,
- send an empty email to <link
- href="mailto:ser-rexml-subscribe@germane-software.com">ser-rexml-subscribe@germane-software.com</link>.
- This list is more or less spam proof. To unsubscribe, similarly send a
- message to <link
- href="mailto:ser-rexml-unsubscribe@germane-software.com">ser-rexml-unsubscribe@germane-software.com</link>.</p>
- </subsection>
-
- <subsection title="RSS">
- <p>An <link
- href="http://www.germane-software.com/projects/rexml/timeline?ticket=on&amp;max=50&amp;daysback=90&amp;format=rss">RSS
- file</link> for REXML is now being generated from the change log. This
- allows you to be alerted of bug fixes and feature additions via "pull".
- <link href="http://www.germane-software.com/software/rexml/rss.xml">Another
- RSS</link> is available which contains a single item: the release notice
- for the most recent release. This is an abuse of the RSS
- mechanism, which was intended to be a distribution system for headlines
- linked back to full articles, but it works. The headline for REXML is
- the version number, and the description is the change log. The links all
- link back to the REXML home page. The URL for the RSS itself is
- http://www.germane-software.com/software/rexml/rss.xml.</p>
-
- <p>The <link href="release.html">changelog itself is here</link>.</p>
-
- <p>For those who are interested, there's a <link
- href="docs/sloccount.txt">SLOCCount</link> (by David A. Wheeler) file
- with stats on the REXML sourcecode. Note that the SLOCCount output
- includes the files in the test/, benchmarks/, and bin/ directories, as
- well as the main sourcecode for REXML itself.</p>
- </subsection>
-
- <subsection title="Applications that use REXML">
- <list>
- <item><link
- href="http://www.pablotron.org/software/raggle/">Raggle</link> is a
- console-based RSS aggregator.</item>
-
- <item><link
- href="http://www.zweknu.org/technical/index.rhtml?s=p|10/">getrss</link>
- is an RSS aggregator</item>
-
- <item>Ned Konz's <link
- href="http://www.bikenomad.microship.com/ruby/">ruby-htmltools</link>
- uses REXML</item>
-
- <item>Hiroshi NAKAMURA's <link
- href="http://www.ruby-lang.org/en/raa-list.rhtml?name=SOAP4R">SOAP4R</link>
- package can use REXML as the XML processor.</item>
-
- <item>Chris Morris' <link href="http://clabs.org/clxmlserial.htm">XML
- Serializer</link>. XML Serializer provides a serialization mechanism
- for Ruby that provides a bidirectional mapping between Ruby classes
- and XML documents.</item>
-
- <item>Much of the <link href="http://www.rubyxml.com">RubyXML</link>
- site is generated with scripts that use REXML. RubyXML is a great
- place to find information about th intersection between Ruby and
- XML.</item>
- </list>
- </subsection>
-
- <bugs lang="en">
- <p>You can submit bug reports and feature requests, and view the list of
- known bugs, at the <link
- href="http://www.germane-software.com/projects/rexml">REXML bug report
- page.</link> Please do submit bug reports. If you really want your bug
- fixed fast, include an runit or Test::Unit method (or methods) that
- illustrates the problem. At the very least, send me some XML that REXML
- doesn't process properly.</p>
-
- <p>You don't have to send an entire test suite -- just the unit test
- methods. If you don't send me a unit test, I'll have to write one
- myself, which will mean that your bug will take longer to fix.</p>
-
- <p>When submitting bug reports, please include the version of Ruby and
- of REXML that you're using, and the operating system you're running on.
- Just run: <code>ruby -vrrexml/rexml -e 'p
- REXML::VERSION,PLATFORM'</code> and paste the results in your bug
- report. Include your email if you want a response about the bug.</p>
-
- <item>Attributes are not handled internally as nodes, so you can't
- perform node functions on them. This will have to change. It'll also
- probably mean that, rather than returning attribute values, XPath will
- return the Attribute nodes.</item>
-
- <item>Some of the XPath <em>functions</em> are untested<footnote>Mike
- Stok has been testing, debugging, and implementing some of these
- Functions (and he's been doing a good job) so there's steady improvement
- in this area.</footnote>. Any XPath functions that don't work are also
- bugs... please report them. If you send a unit test that illustrates the
- problem, I'll try to fix the problem within a couple of days (if I can)
- and send you a patch, personally.</item>
-
- <item>Accessing prefixes for which there is no defined namespace in an
- XPath should throw an exception. It currently doesn't -- it just fails
- to match.</item>
- </bugs>
-
- <todo lang="en">
- <item>Reparsing a tree with a pull/SAX parser</item>
-
- <item>Better namespace support in SAX</item>
-
- <item>Lazy tree parsing</item>
-
- <item>Segregate parsers, for optimized minimal distributions</item>
-
- <item>XML &lt;-&gt; Ruby</item>
-
- <item>Validation support</item>
-
- <item>True XML character support</item>
-
- <item>Add XPath support for streaming APIs</item>
-
- <item status="request">XQuery support</item>
-
- <item status="request">XUpdate support</item>
-
- <item>Make sure namespaces are supported in pull parser</item>
-
- <item status="request">Add document start and entity replacement events
- in pull parser</item>
-
- <item>Better stream parsing exception handling</item>
-
- <item>I'd like to hack XMLRPC4R to use REXML, for my own
- purposes.</item>
- </todo>
- </status>
-
- <faq>
- <q>REXML is hanging while parsing one of my XML files.</q>
-
- <a>Your XML is probably malformed. Some malformed XML, especially XML that
- contains literal '&lt;' embedded in the document, causes REXML to hang.
- REXML should be throwing an exception, but it doesn't; this is a bug. I'm
- aware that it is an extremely annoying bug, and it is one I'm trying to
- solve in a way that doesn't significantly reduce REXML's parsing
- speed.</a>
-
- <q>I'm using the XPath '//foo' on an XML branch node X, and keep getting
- all of the 'foo' elements in the entire document. Why? Shouldn't it return
- only the 'foo' element descendants of X?</q>
-
- <a>No. XPath specifies that '/' returns the document root, regardless of
- the context node. '//' also starts at the document root. If you want to
- limit your search to a branch, you need to use the self:: axe. EG,
- 'self::node()//foo', or the shorthand './/foo'.</a>
-
- <q>I want to parse a document both as a tree, and as a stream. Can I do
- this?</q>
-
- <a>Yes, and no. There is no mechanism that directly supports this in
- REXML. However, aside from writing your own traversal layer, there is a
- way of doing this. To turn a tree into a stream, just turn the branch you
- want to process as a stream back into a string, and re-parse it with your
- preferred API. EG: pp = PullParser.new( some_element.to_s ). The other
- direction is more difficult; you basically have to build a tree from the
- events. REXML will have one of these builders, eventually, but it doesn't
- currently exist.</a>
-
- <q>Why is Element.elements indexed off of '1' instead of '0'?</q>
-
- <a>Because of XPath. The XPath specification states that the index of the
- first child node is '1'. Although it may be counter-intuitive to base
- elements on 1, it is more undesireable to have element.elements[0] ==
- element.elements[ 'node()[1]' ]. Since I can't change the XPath
- specification, the result is that Element.elements[1] is the first child
- element.</a>
-
- <q>Why isn't REXML a validating parser?</q>
-
- <a>Because validating parsers must include code that parses and interprets
- DTDs. I hate DTDs. REXML supports the barest minimum of DTD parsing, and
- even that isn't complete. There is DTD parsing code in the works, but I
- only work on it when I'm really, really bored. Rumor has it that a
- contributor is working on a DTD parser for REXML; rest assured that any
- such contribution will be included with REXML as soon as it is
- available.</a>
-
- <q>I'm trying to create an ISO-8859-1 document, but when I add text to the
- document it isn't being properly encoded.</q>
-
- <a>Regardless of what the encoding of your document is, when you add text
- programmatically to a REXML document you <em>must</em> ensure that you are
- only adding UTF-8 to the tree. In particular, you can't add ISO-8859-1
- encoded text that contains characters above 0x80 to REXML trees -- you
- must convert it to UTF-8 before doing so. Luckily, this is easy:
- <code>text.unpack('C*').pack('U*')</code> will do the trick. 7-bit ASCII
- is identical to UTF-8, so you probably won't need to worry about this.</a>
-
- <q>How do I get the tag name of an Element?</q>
-
- <a>You take a look at the APIs, and notice that <code>Element</code>
- includes <code>Namespace</code>. Then you click on the
- <code>Namespace</code> link and look at the methods that
- <code>Element</code> includes from <code>Namespace</code>. One of these is
- <code>name()</code>. Another is <code>expanded_name()</code>. Yet another
- is <code>prefix()</code>. Then, you email the author of rdoc and ask him
- to extend rdoc so that it lists methods in the API that are included from
- other files, so that you don't have to do all of that looking around for
- your method.</a>
- </faq>
-
- <credits>
- <p>I've had help from a number of resources; if I haven't listed you here,
- it means that I just haven't gotten around to adding you, or that I'm a
- dork and have forgotten. In either case, feel free to write me and
- complain.</p>
-
- <list>
- <item>Mike Stok has been very active, sending not only fixes for bugs
- (especially in Functions), but also by providing unit tests and making
- sure REXML runs under Ruby 1.7. He also sent the most awesome hand
- knitted tea cozy, with "REXML" and the Ruby knitted into it.</item>
-
- <item>Kouhei Sutou translated the REXML API documentation to Japanese!
- Links are in the API docs section of the main documentation. He has also
- contributed a large number of bug reports and patches to fix bugs in
- REXML.</item>
-
- <item>Erik Terpstra heard my pleas and submitted several logos for
- REXML. After sagely procrastinating for several weeks, I finally forced
- my poor slave of a wife to pick one (this is what we call "delegation").
- She did, with caveats; Erik quickly made the changes, and the result is
- what you now see at the top of this page. He also supplied a <link
- href="img/rexml_50p.png">smaller version</link> that you can include
- with your projects that use REXML, if you'd like.</item>
-
- <item>Ernest Ellingson contributed the sourcecode for turning UTF16 and
- UNILE encodings into UTF8, which allowed REXML to get the 100% OASIS
- valid tests rating.</item>
-
- <item>Ian Macdonald provided me with a comprehensive, well written RPM
- spec file.</item>
-
- <item>Oliver M . Bolzer is maintaining a Debian package distribution of
- REXML. He also has provided good feedback and bug reports about
- namespace support.</item>
-
- <item>Michael Granger supplied a patch for REXML that make the unit
- tests pass under Ruby 1.7.</item>
-
- <item>James Britt contributed code that makes using
- Document.parse_stream easier to use by allowing it to be passed either a
- Source, File, or String.</item>
-
- <item>Tobias Reif: Numerous bug reports, and suggestions for
- improvement.</item>
-
- <item>Stefan Scholl, who provided a lot of feedback and bug reports
- while I was trying to get ISO-8859-1 support working.</item>
-
- <item>Steven E Lumos for volunteering information about XPath
- particulars.</item>
-
- <item>Fumitoshi UKAI provided some bug fixes for CData metacharacter
- quoting.</item>
-
- <item>TAKAHASHI Masayoshi, for information on UTF</item>
-
- <item>Robert Feldt: Bug reports and suggestions/recommendations about
- improving REXML. Testing is one of the most important aspects of
- software development.</item>
-
- <item><link
- href="http://www.themindelectric.com/exml/index.html">Electric
- XML</link>: This was, after all, the inspiration for REXML. Originally,
- I was just going to do a straight port, and although REXML doesn't in
- any way, shape or form resemble Electric XML, still the basic framework
- and philosophy was inspired by E-XML. And I still use E-XML in my Java
- projects.</item>
-
- <item><link
- href="http://www.io.com/~jimm/downloads/nqxml/index.html">NQXML</link>:
- While I may complain about the NQXML API, I wrote a few applications
- using it that wouldn't have been written otherwise, and it was very
- useful to me. It also encouraged me to write REXML. Never complain about
- free software *slap*.</item>
-
- <item>See my <link
- href="http://www.germane-software.com/~ser/technology.html">technologies
- page</link> for a more comprehensive list of computer technologies that
- I depend on for my day-to-day work.</item>
-
- <item>rdoc, an excellent JavaDoc analog<footnote>When I was first
- working on REXML, rdoc wasn't, IMO, very good, so I wrote API2XML.
- API2XML was good enough for a while, and then there was a flurry of work
- on rdoc, and it quickly surpassed API2XML in features. Since I was never
- really interested in maintaining a JavaDoc analog, I stopped support of
- API2XML, and am now recommending that people use
- rdoc.</footnote>.</item>
-
- <item>Many, many other people who've submitted bug reports, suggestions,
- and positive feedback. You're all co-developers!</item>
- </list>
- </credits>
-</documentation>
diff --git a/test/rexml/data/euc.xml b/test/rexml/data/euc.xml
deleted file mode 100644
index a3c3419498..0000000000
--- a/test/rexml/data/euc.xml
+++ /dev/null
@@ -1,296 +0,0 @@
-<?xml version="1.0" encoding="euc-jp"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN">
-<html xml:lang="ja">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=euc-jp" />
-<meta http-equiv="Content-Style-Type" content="text/css" />
-<meta name="author" content="U.Nakamura" />
-<link rev="made" href="mailto:usa@ruby-lang.org" />
-<link rel="StyleSheet" href="./ruby.css" type="text/css" />
-<title>Ruby-mswin32</title>
-</head>
-<body>
-
-<h1><a id="top">Ruby-mswin32</a></h1>
-<p>뤤ϡWindowsȤνʤ襤 ;-(</p>
-<p>[ܸ / <a href="./index_en.html">English</a>]</p>
-
-
-
-<h2><a id="menu"> ܼ</a></h2>
-<ul>
-<li><a href="#remark">ջ</a></li>
-<li><a href="#ruby">RubyȤ?</a></li>
-<li><a href="#mswin32">mswin32rubyȤ?</a></li>
-<li><a href="#download">Хʥ </a></li>
-<li><a href="#install">󥹥ȡ</a></li>
-<li><a href="#recent">Ƕν</a></li>
-<li><a href="#link"></a></li>
-</ul>
-
-
-
-<h2><a id="remark"> ջ</a></h2>
-<p>ΥڡǤϡmswin32rubyۤѹΤΤ餻ԤäƤޤ</p>
-<p>̤˸ڡǤʤǤʤơ䤬˽񤤤ƤڡǤǤץࡦ(̵)ˤĤƤϡƼȽǤǤѤ<br />
-䤤碌<a href="mailto:usa@ruby-lang.org"></a>ءְäƤ¾οͤǤ򤫤褦ʤȤϤʤǤ͡</p>
-
-
-
-<h2><a id="ruby"> RubyȤ?</a></h2>
-<p><a href="http://www.ruby-lang.org/ja/">RubyΥ</a></p>
-
-
-
-<h2><a id="mswin32"> mswin32rubyȤ?</a></h2>
-<p>mswin32rubyȤϡ32bitWindows(Windows95Windows98WindowsMeWindows NTWindows 2000WindowsXPWindows 2003 ServerʲWindowsɽ)ưRubyΥХʥΰĤǤ<br />
-WindowsưRubyȤƤϡߡ5ΥХʥ꤬¸ߤޤϤ줾mswin32ǡcygwinǡmingw32ǡbccwin32ǡdjgppǤȸƤФƤޤ<br />
-줾ΰ㤤ޤȤȰʲΤ褦ˤʤޤ(¸ǧФΤ餻)</p>
-<dl>
-<dt><a id="label:1">mswin32</a></dt><dd>
-<p>VC++ǥѥ뤵롣Windows鸫ФäȤ̡פΥХʥȸ뤬ȿ̡RubyUNIXħŪʵǽΰѤǤʤ1.7.3ʹߤmingw32Ǥȳĥ饤֥ˤĤƤϥХʥߴ롣<br />
-RUBY_PLATFORM*-mswin32</p>
-</dd>
-<dt><a id="label:2">cygwin</a></dt><dd>
-<p>gccǥѥ뤵졢<a href="http://sources.redhat.com/cygwin/">cygwin</a>Ķư롣cygwinĶUNIX饤ʴĶWindowsǹۤΤǤΤǡcygwinrubyϰ̤UNIXѤΤΤȤƱ褦ư(ȤԤǤ)<br />
-RUBY_PLATFORM*-cygwin</p>
-</dd>
-<dt><a id="label:3">mingw32</a></dt><dd>
-<p>gccǥѥ뤵롣ϤۤȤmswin32Ǥȶ̤Ǥꡢ󥿥饤֥ⶦ(MSVCRT.dll)ʤΤǡư(餯)mswin32ǤȤۤƱ1.7.3ʹߤmswin32Ǥȳĥ饤֥ˤĤƤϥХʥߴ롣<br />
-RUBY_PLATFORM*-mingw32</p>
-</dd>
-<dt><a id="label:4">bccwin32</a></dt><dd>
-<p>BC++ǥѥ뤵롣Ϥʤʬmswin32Ǥȶ̤ǤϤ뤬󥿥饤֥꤬ۤʤΤǡ٤Ȥǵưmswin32ǤȤϰۤʤ(Ϥ)1.7ʹߤǥݡȤ롣<br />
-RUBY_PLATFORM*-bccwin32</p>
-</dd>
-<dt><a id="label:5">djgpp</a></dt><dd>
-<p>DJGPPǥѥ뤵롣DOSѤΥХʥʤΤǡDOSǤư롣ȿ̡WindowsˤäDOSˤʤǽ¿Ȥʤ(ͥåȥϢʤ)<br />
-RUBY_PLATFORM*-msdosdjgpp</p>
-</dd>
-</dl>
-<p>ΥڡǤϡ嵭Τmswin32ǤΤߤ򰷤äƤޤ<br />
-ʤcygwinǡmingw32ǡdjgppǤˤĤƤϤ錄ʤ٤<a href="http://www.os.rim.or.jp/~eban/">Ruby binaries</a>ǽǤޤbccwin32ǤˤĤƤϾ<a href="http://www001.upp.so-net.ne.jp/konishi/ruby/index.htm">Ruby</a>ǽǤ</p>
-
-
-
-<h2><a id="download"> Хʥ </a></h2>
-<p>ƤΥХʥVC++ 5.0(Version 11.00.7022 for 80x86)makeΤǤrubyΤ˴ؤƤϡ<a href="http://www.ruby-lang.org/ja/download.html">ɸۤΥ</a>(ޤ<a href="http://www.ruby-lang.org/~knu/cvsrepo-guide.html">CVS</a>Υ)餽Τޤ޺Ƥޤĥ饤֥ˤĤƤϳơΥ򻲾ȤƤ<br />
-ΥХʥzipǥ֤Ƥޤ</p>
-<p>md5sumΥåˡǤ㤨ruby󥹥ȡ뤵Ƥʤ鲼Τ褦ˡޤ<br />
-<code>ruby -r md5 -e "puts MD5.new(File.open('filename', 'rb').read).hexdigest"</code></p>
-
-
-
-<h3><a id="release">Release</a></h3>
-<ul>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.8.1-i386-mswin32.zip">ruby-1.8.1-i386-mswin32.zip</a> (3,764KB) <em>ǿRelease</em><br />
- ruby 1.8.1 (2003-12-25) [i386-mswin32]<br />
- md5sum : 6bbdabeb29f1a15fa69901e87d1108ac</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.8.0-i386-mswin32.zip">ruby-1.8.0-i386-mswin32.zip</a> (2,507KB)<br />
- ruby 1.8.0 (2003-08-04) [i386-mswin32]<br />
- md5sum : eaf9263062429fd4f722d9a70a38a9dc</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.6.8-i586-mswin32.zip">ruby-1.6.8-i586-mswin32.zip</a> (1,964KB)<br />
- ruby 1.6.8 (2002-12-24) [i586-mswin32]<br />
- md5sum : f704f1248ec25b96e3e1f3070afa915e</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.6.7-i586-mswin32.zip">ruby-1.6.7-i586-mswin32.zip</a> (1,972KB)<br />
- ruby 1.6.7 (2002-03-01) [i586-mswin32]<br />
- md5sum : ddedc40d0fc3b0ea1d6ac74f4976bfc6</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.6.6-i586-mswin32.zip">ruby-1.6.6-i586-mswin32.zip</a> (1,944KB)<br />
- ruby 1.6.6 (2001-12-26) [i586-mswin32]<br />
- md5sum : 96e0d1d19a37e5e7e50ae7ce99e34636</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.6.5-i586-mswin32.zip">ruby-1.6.5-i586-mswin32.zip</a> (1,896KB)<br />
- ruby 1.6.5 (2001-09-19) [i586-mswin32]<br />
- md5sum : c708ae98a05df2ff8dea5a70e3791bfa</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.6.4-i586-mswin32.zip">ruby-1.6.4-i586-mswin32.zip</a> (1,821KB)<br />
- ruby 1.6.4 (2001-06-04) [i586-mswin32]<br />
- md5sum : cf813ca19e40be164057b3562575e4da</li>
-</ul>
-
-
-
-
-
-
-
-<h3><a id="develop">Developing versions snapshots</a></h3>
-<ul>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.9.0-20040126-i386-mswin32.zip">ruby-1.9.0-20040126-i386-mswin32.zip</a> (3,849KB)<br />
- ruby 1.9.0 (2004-01-26) [i386-mswin32]<br />
- md5sum : fffafbf881cb6a85982220eae5a5b4f5</li>
-</ul>
-
-
-
-<h3><a id="stable">Stable versions snapshots</a></h3>
-<h4><a id="stable">1.8.0</a></h4>
-<ul>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.8.1-20040127-i386-mswin32.zip">ruby-1.8.1-20040127-i386-mswin32.zip</a> (3,822KB)<br />
- ruby 1.8.1 (2004-01-27) [i386-mswin32]<br />
- md5sum : 1fc0d5f53f0a75d0c6d1ca5d21082089</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.8.1-20031027-i386-mswin32.zip">ruby-1.8.1-20031027-i386-mswin32.zip</a> (3,075KB)<br />
- ruby 1.8.1 (2003-10-27) [i386-mswin32]<br />
- md5sum : 9dbdc644c529d207d0bda5d64478a5c4</li>
-</ul>
-<h4><a id="stable">1.6.8</a></h4>
-<ul>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.6.8-20030727-i586-mswin32.zip">ruby-1.6.8-20030727-i586-mswin32.zip</a> (2,093KB)<br />
- ruby 1.6.8 (2003-07-27) [i586-mswin32]<br />
- md5sum : 28c3b92b162319b3d6bc99c9996cad15</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.6.8-20030515-i586-mswin32.zip">ruby-1.6.8-20030515-i586-mswin32.zip</a> (2,091KB)<br />
- ruby 1.6.8 (2003-05-15) [i586-mswin32]<br />
- md5sum : e5f6558de261d111add4f657ad5e345f</li>
-</ul>
-
-
-
-<h3><a id="ext">Extension libraries</a></h3>
-<h4><a id="ext">1.8.0</a></h4>
-<ul>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/racc-1.4.4-all-i386-mswin32-1.8.zip">racc-1.4.4-all-i386-mswin32-1.8.zip</a> (70KB)<br />
- <a href="http://www.loveruby.net/en/racc.html">racc</a> 1.4.4-all (for ruby 1.8.1)<br />
- md5sum : 46c4d48b714fb1ded880e7e7af456b28</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/vrswin-030906-i386-mswin32-1.8.zip">vrswin-030906-i386-mswin32-1.8.zip</a> (54KB)<br />
- <a href="http://www.osk.3web.ne.jp/~nyasu/vruby/vrproject-e.html">VisualuRuby (swin)</a> 030906 (for ruby 1.8.0)<br />
- md5sum : 11c2d30e2a05e9ea7e097ec7b066cedf</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/vruby-030906-i386-mswin32-1.8.zip">vruby-030906-i386-mswin32-1.8.zip</a> (96KB)<br />
- <a href="http://www.osk.3web.ne.jp/~nyasu/vruby/vrproject-e.html">VisualuRuby (vruby)</a> 030906 (for ruby 1.8.0)<br />
- md5sum : 77a42995e42e869932f5fb282cc297ea</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/eruby-1.0.4-i386-mswin32-1.8.zip">eruby-1.0.4-i386-mswin32-1.8.zip</a> (75KB)<br />
- <a href="http://www.modruby.net/">eruby</a> 1.0.4 (for ruby 1.8.0)<br />
- md5sum : de7282647f015b1d20a28dcf7c2b8715</li>
-</ul>
-<h4><a id="ext">1.6.8</a></h4>
-<ul>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/vrswin-030521-i586-mswin32-1.6.zip">vrswin-030521-i586-mswin32-1.6.zip</a> (55KB)<br />
- <a href="http://www.osk.3web.ne.jp/~nyasu/vruby/vrproject-e.html">VisualuRuby (swin)</a> 030521 (for ruby 1.6.8)<br />
- md5sum : eae3284c6f79be7a119858ff9e940985</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/vruby-030517-i586-mswin32-1.6.zip">vruby-030517-i586-mswin32-1.6.zip</a> (95KB)<br />
- <a href="http://www.osk.3web.ne.jp/~nyasu/vruby/vrproject-e.html">VisualuRuby (vruby)</a> 030517 (for ruby 1.6.8)<br />
- md5sum : a32af752428cf3aa03000d66d8deca33</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/tmail-0.10.7-i586-mswin32-1.6.zip">tmail-0.10.7-i586-mswin32-1.6.zip</a> (160KB)<br />
- <a href="http://www.loveruby.net/en/tmail.html">TMail</a> 0.10.7 (for ruby 1.6.8)<br />
- md5sum : 74351ed81550dfbf3bfaf8252c316326</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/eruby-1.0.3-i586-mswin32-1.6.zip">eruby-1.0.3-i586-mswin32-1.6.zip</a> (74KB)<br />
- <a href="http://www.modruby.net/">eruby</a> 1.0.3 (for ruby 1.6.8)<br />
- md5sum : e05d654128422846f86ca84f55bf7bcb</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/rubywin-0.0.4.3-i586-mswin32-1.6.zip">rubywin-0.0.4.3-i586-mswin32-1.6.zip</a> (286KB)<br />
- <a href="http://homepage1.nifty.com/markey/ruby/rubywin/index_e.html">RubyWin</a> 0.0.4.3 (for ruby 1.6.8)<br />
- md5sum : 3f2226ef0c6e41b31c2f337f778e3e18</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/shim-20021224-i586-mswin32-1.6.zip">shim-20021224-i586-mswin32-1.6.zip</a> (138KB)<br />
- <a href="http://www.ruby-lang.org/~knu/cgi-bin/cvsweb.cgi/shim/">Ruby Shim</a> 20021224 (for ruby 1.6.8)<br />
- md5sum : 7ee4363195973a1df0584cb467e5ce82</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/racc-1.4.3-all-i586-mswin32-1.6.zip">racc-1.4.3-all-i586-mswin32-1.6.zip</a> (124KB)<br />
- <a href="http://www.loveruby.net/en/racc.html">racc</a> 1.4.3-all (for ruby 1.6.8)<br />
- md5sum : 1f093aabb464bef3074112949228a8c6</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/win32ole-0.5.2-i586-mswin32-1.6.zip">win32ole-0.5.2-i586-mswin32-1.6.zip</a> (59KB)<br />
- <a href="http://homepage1.nifty.com/markey/ruby/win32ole/index_e.html">Win32OLE</a> 0.5.2 (for ruby 1.6.8)&lt;<br />
- md5sum : 960f7205923a9243cff567d291b254ad</li>
-<li><a href="ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ext/uconv-0.4.11-i586-mswin32-1.6.zip">uconv-0.4.11-i586-mswin32-1.6.zip</a> (110KB)<br />
- <a href="http://www.yoshidam.net/Ruby.html#uconv">uconv</a> 0.4.11 (for ruby 1.6.8)<br />
- md5sum : c08f3662abee8e7186283741f89b88d7</li>
-</ul>
-
-
-
-<h2><a id="install"> 󥹥ȡ</a></h2>
-<p>嵭ΥХʥ򥤥󥹥ȡ뤹ϡߤΥǥ쥯ȥ(ʲ<code>$TOPDIR</code>ȵ)ŸƤǥ쥯ȥդǰ̤ƤޤΤǡŸˤϥǥ쥯ȥդŸΤ˺줺(̣狼ʤͤϵˤʤƤǤ)<br />
-Ÿϡ<code>$TOPDIR\bin</code><code>PATH</code>̤ƤƤ</p>
-<p>ʤʲγĥ饤֥ϡʪ˴ޤޤʤΥ饤֥˰¸Ƥޤ</p>
-<ul>
-<li>curses.so : PDCurses˰¸Ƥޤ</li>
-<li>dbm.so : GDBM˰¸Ƥޤ</li>
-<li>gdbm.so : GDBM˰¸Ƥޤ</li>
-<li>iconv.so : Iconv˰¸Ƥޤ</li>
-<li>openssl.so : OpenSSL˰¸Ƥޤ</li>
-<li>readline.so : readline˰¸Ƥޤ</li>
-<li>tcltklib.so : Tcl/Tk˰¸Ƥޤ</li>
-<li>zlib.so : Zlib˰¸Ƥޤ</li>
-</ul>
-<p>嵭ΤPDCursesGDBMOpenSSLreadlineZlibˤĤƤϡ<a href="http://jarp.jin.gr.jp/win32/">Porting Libraries to Win32</a>˥Хʥ꤬¸ߤޤ<br />
-IconvˤĤƤϡMeadowy.orgۤƤ<a href="http://www.meadowy.org/meadow/dists/snapshot/iconv-1.8.win32.zip">iconv-1.8.win32.zip</a>ѤƤޤ<br />
-Tcl/TkˤĤƤϡ<a href="http://www.activestate.com/">ActiveState</a>ۤƤ<a href="http://www.activestate.com/Products/ActiveTcl/">ActiveTcl</a>ѤƤޤ</p>
-
-
-
-<h2><a id="recent"> Ƕν</a></h2>
-
-
-
-<h3><a id="d20040127">2004-01-27</a></h3>
-<p>ޤƤǤȤޤä٤!</p>
-<p>ruby-1.8.1-20040127ruby-1.9.0-20040126֤ޤ<br />
-Ԥϼ1.8.1꡼Ǥȯ줿ԶνǤԤϳȯǡ</p>
-
-<h3><a id="d20031225">2003-12-25</a></h3>
-<p>꡼ꥹޥ! ruby-1.8.1꡼ޤ!<br />
-(previewФ㤤ޤʤ...)</p>
-
-<h3><a id="d20031206">2003-12-06</a></h3>
-<p>ruby-1.8.1-preview3֤ޤפΤ֤ۤ㤤ޤ͡</p>
-
-<h3><a id="d20031101">2003-11-01</a></h3>
-<p>ruby-1.8.1-preview2֤ޤ</p>
-
-<h3><a id="d20031028">2003-10-28</a></h3>
-<p>ruby-1.8.1-20031027֤ޤ<br />
-racc-1.4.4-all֤ޤ</p>
-
-<h3><a id="d20030907">2003-09-07</a></h3>
-<p>eruby-1.0.4vrswin-030906vruby-030906֤ޤ</p>
-
-<h3><a id="d20030812">2003-08-12</a></h3>
-<p>ruby-1.8.0-20030812֤ޤ</p>
-<p>vrswin-030811vruby-030811֤ޤ󤫤֤ĥ饤֥1.8Ѥˤʤޤ</p>
-
-<h3><a id="d20030804">2003-08-04</a></h3>
-<p>ruby-1.8.0֤ޤRuby 1.8ϺǽΥ꡼Ȥʤޤ<br />
-1.6ϤѹˤĤƤϡ<a href="ftp://ftp.ruby-lang.org/pub/ruby/1.8/changes.1.8.0">changes.1.8.0</a>ʤɤ</p>
-
-<h3><a id="d20030731">2003-07-31</a></h3>
-<p>ruby-1.8.0-preview6֤ޤȡޤƤ2previewФͤǤ :)</p>
-
-<h3><a id="d20030728">2003-07-28</a></h3>
-<p>ruby-1.8.0-preview5֤ޤ餯줬1.8.0κǸpreviewˤʤǤ礦<br />
-ruby-1.6.8-20030727֤ޤ</p>
-
-
-
-<h3><a id="old">ĤƤν</a></h3>
-<p><a href="./old.html"></a>ɤ</p>
-
-
-
-<h2><a id="link"> </a></h2>
-<p>mswin32Ǥ˴ؤ(Ȼפ)󥯤ǤĥäƤޤΤǡԹ礬<a href="mailto:usa@osb.att.ne.jp"></a>ޤǤϢ</p>
-<ul>
-<li><a href="http://www.ruby-lang.org/">Ruby Home Page</a> (<a href="http://www.ruby-lang.org/ja/">ܸ</a> / <a href="http://www.ruby-lang.org/en/">English</a>)<br />
- 鷺Ȥ줿ܲȥȡ</li>
-<li>Ģ (<a href="http://homepage1.nifty.com/markey/">ܸ</a> / <a href="http://homepage1.nifty.com/markey/index_e.html">English</a>)<br />
- ĤΥڡ<a href="http://homepage1.nifty.com/markey/ruby/rubywin/index.html">RubWin</a><a href="http://homepage1.nifty.com/markey/ruby/win32ole/index.html">Win32OLE</a>ʤɤޤ</li>
-<li><a href="http://www.moonwolf.com/ruby/">Script/Ruby</a> (ܸ)<br />
- MoonWolfΥڡWin32Moduleʤɤޤ</li>
-<li>ActiveScriptRuby (<a href="http://www.geocities.co.jp/SiliconValley-PaloAlto/9251/ruby/index.html">ܸ</a> / <a href="http://www.geocities.co.jp/SiliconValley-PaloAlto/9251/ruby/main.html">English</a>)<br />
- artonΥڡWindowsRuby̤ϤˤΤ⡣</li>
-<li>VisualuRubyײ() (<a href="http://www.osk.3web.ne.jp/~nyasu/software/vrproject.html">ܸ</a> / <a href="http://www.osk.3web.ne.jp/~nyasu/vruby/vrproject-e.html">English</a>)<br />
- nyasuΥڡVisualuRubyʤɤޤ(äƤ⤽Τޤ)WindowsRubyȤ<a href="http://www.osk.3web.ne.jp/~nyasu/software/rubyonwin.html">󥯽</a>¤ƤޤʤߤˡȤΥǥϤΥѥǤ¿!</li>
-<li>Ruby (<a href="http://www.yoshidam.net/Ruby_ja.html">ܸ</a> / <a href="http://www.yoshidam.net/Ruby.html">English</a>)<br />
- 褷वΥڡ<a href="http://www.yoshidam.net/Ruby_ja.html#susie">Susieץ饰饤֥</a><a href="http://www.yoshidam.net/Ruby_ja.html#rddraw">DirectDraw for Ruby</a>ʤɤޤ</li>
-<li><a href="http://homepage2.nifty.com/sakazuki/rde.html">RDE(Ruby Development Environment)</a> (ܸ)<br />
- sakazukiΥڡmswin32ǥ桼ʤɬǤ侩ĶartonȤActiveScriptRubyǤ (^^; ʪȤäƤʤưޤ</li>
-</ul>
-
-
-
-<p class="footer">
-[<a href="../"></a>]
-</p>
-<address>written by <a href="mailto:usa@ruby-lang.org">U.Nakamura</a></address>
-<p class="versions">
-ruby 1.9.0 (2004-01-13)<br />
-ERb 2.0.4<br />
-RDtool 0.6.11<br />
-rublog 0.0.2
-</p>
-
-</body>
-</html>
diff --git a/test/rexml/data/evaluate.xml b/test/rexml/data/evaluate.xml
deleted file mode 100644
index 90d06bd652..0000000000
--- a/test/rexml/data/evaluate.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-
-<evaluate>
- <data>
- <jumps>
- <subject>
- <the/>
- <fox color="brown"/>
- <speed category="quick"/>
- </subject>
- <over/>
- <object>
- <the/>
- <dog color="unspecified"/>
- <speed category="lazy"/>
- </object>
- </jumps>
- </data>
-
- <!-- there is one element with attribute color="brown" should this
- meta-test should succeed -->
-
- <metatest select="//@color">brown</metatest>
-
- <!-- there is no element with attribute category="moderate" -->
- <metatest select="//speed/@category">moderate</metatest>
-
-</evaluate>
diff --git a/test/rexml/data/fibo.xml b/test/rexml/data/fibo.xml
deleted file mode 100644
index 9b5d0ecd87..0000000000
--- a/test/rexml/data/fibo.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Fibonacci_Numbers>
- <fibonacci index="0">0</fibonacci>
- <fibonacci index="1">1</fibonacci>
- <fibonacci index="2">1</fibonacci>
- <fibonacci index="3">2</fibonacci>
- <fibonacci index="4">3</fibonacci>
- <fibonacci index="5">5</fibonacci>
- <fibonacci index="6">8</fibonacci>
- <fibonacci index="7">13</fibonacci>
- <fibonacci index="8">21</fibonacci>
- <fibonacci index="9">34</fibonacci>
- <fibonacci index="10">55</fibonacci>
- <fibonacci index="11">89</fibonacci>
- <fibonacci index="12">144</fibonacci>
- <fibonacci index="13">233</fibonacci>
- <fibonacci index="14">377</fibonacci>
- <fibonacci index="15">610</fibonacci>
- <fibonacci index="16">987</fibonacci>
- <fibonacci index="17">1597</fibonacci>
- <fibonacci index="18">2584</fibonacci>
- <fibonacci index="19">4181</fibonacci>
- <fibonacci index="20">6765</fibonacci>
- <fibonacci index="21">10946</fibonacci>
- <fibonacci index="22">17711</fibonacci>
- <fibonacci index="23">28657</fibonacci>
- <fibonacci index="24">46368</fibonacci>
- <fibonacci index="25">75025</fibonacci>
-</Fibonacci_Numbers>
diff --git a/test/rexml/data/foo.xml b/test/rexml/data/foo.xml
deleted file mode 100644
index 53b9a4e003..0000000000
--- a/test/rexml/data/foo.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE schema SYSTEM "foo.dtd" [
-<!ATTLIST root-el
- xmlns:human CDATA #FIXED "http://www.foo.com/human">
-]>
-<root-el xmlns="http://www.bar.com/doc"
- xmlns:table="http://www.foo.com/table">
- <human:leg>human leg</human:leg>
- <table:leg>table leg</table:leg>
-</root-el>
diff --git a/test/rexml/data/google.2.xml b/test/rexml/data/google.2.xml
deleted file mode 100644
index a1df93b107..0000000000
--- a/test/rexml/data/google.2.xml
+++ /dev/null
@@ -1,156 +0,0 @@
-<form xmlns='http://www.w3.org/1999/xhtml'
- enctype='application/x-www-form-urlencoded' class='rollover'
- action='ModifyCampaign' method='POST'
- onsubmit='return beforeRolloverSubmit(this, &apos;No campaigns selected.&apos;);'>
- <a name='campaigns' shape='rect'/>
- <tr bgcolor='#dbe6de'>
- <th class='boxcolumn' rowspan='1' align='left' colspan='1'
- width='1%'>
- <script type='text/javascript'>document.write(" &lt;input
- type\u003d\"checkbox\" name\u003d\"toggleAll\"
- onclick\u003d\"rowToggleAll(this);\" title\u003d\"Select or
- de-select all campaigns on this page\"&gt; ");</script>
- </th>
- <th bgcolor='#dbe6de' title='Sort by campaign name' nowrap='nowrap'
- rowspan='1' align='left' colspan='1'>
- <b>
- <a href='CampaignSummary?campaignsummaryt=0%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>Campaign Name</a>
- </b>
- </th>
- <th bgcolor='#dbe6de' title='Sort by campaign status'
- nowrap='nowrap' rowspan='1' align='left' colspan='1'>
- <a href='CampaignSummary?campaignsummaryt=1%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>Current Status</a>
- </th>
- <th bgcolor='#dbe6de'
- title='Sort by daily budget (maximum spending per day)'
- nowrap='nowrap' rowspan='1' align='right' colspan='1'>
- <a href='CampaignSummary?campaignsummaryt=2%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>Current Budget</a>
- <span style='white-space: nowrap'>
- <a href='/support/bin/answer.py?answer=6312&amp;hl=en_US'
- shape='rect' id='' onclick='return helpPopUp(this);' style=''
- target='google_popup'>[?]</a>
- </span>
- </th>
- <th bgcolor='#c6d7cf' title='Sort by clicks on your ads'
- nowrap='nowrap' rowspan='1' align='right' colspan='1'>
- <a href='CampaignSummary?campaignsummaryt=-3%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>Clicks</a>
- <a href='CampaignSummary?campaignsummaryt=-3%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- shape='rect' style='text-decoration:none;'>
- <img src='/select/images/sortdown.gif' border='0' alt=''/>
- </a>
- </th>
- <th bgcolor='#dbe6de' title='Sort by ad impressions served'
- nowrap='nowrap' rowspan='1' align='right' colspan='1'>
- <a href='CampaignSummary?campaignsummaryt=4%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>Impr.</a>
- </th>
- <th bgcolor='#dbe6de' title='Sort by CTR (clickthrough rate)'
- nowrap='nowrap' rowspan='1' align='right' colspan='1'>
- <a href='CampaignSummary?campaignsummaryt=5%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>CTR</a>
- </th>
- <th bgcolor='#dbe6de' title='Sort by average cost per click (USD)'
- nowrap='nowrap' rowspan='1' align='right' colspan='1'>
- <a href='CampaignSummary?campaignsummaryt=6%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>Avg. CPC</a>
- </th>
- <th bgcolor='#dbe6de' class='' title='Sort by total cost (USD)'
- nowrap='nowrap' rowspan='1' align='right' colspan='1'>
- <a href='CampaignSummary?campaignsummaryt=8%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>Cost</a>
- </th>
- <th bgcolor='#dbe6de' title='Conversion Rate' nowrap='nowrap'
- rowspan='1' align='right' colspan='1'>
- <a href='CampaignSummary?campaignsummaryt=11%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>Conv. Rate</a>
- </th>
- <th bgcolor='#dbe6de' class='rightcolumn'
- title='Cost per Conversion' nowrap='nowrap' rowspan='1'
- align='right' colspan='1'>
- <a href='CampaignSummary?campaignsummaryt=12%3Aa&amp;gsessionid=ezmXK9aaXnI#campaigns'
- class='bluelink' shape='rect'>Cost/Conv.</a>
- </th>
- </tr>
- <tr onmouseover='ron(3527627);' id='tr_3527627'
- onmouseout='roff(3527627);'>
- <td class='boxcolumn' rowspan='1' onclick='rowToggle(3527627);'
- colspan='1'>
- <input name='campaignid' type='checkbox' id='box_3527627'
- value='3527627' onclick='toggleRow(this);'/>
- </td>
- <td rowspan='1' colspan='1'>
- <a href='CampaignManagement?campaignid=3527627#a' shape='rect'>Test</a>
- </td>
- <td rowspan='1' colspan='1'>
- <b>
- <font size='-1' color='#b98b00'>Paused</font>
- </b>
- </td>
- <td class='r' rowspan='1' colspan='1'>
- <font color='#666666'>Test</font>
- </td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='' rowspan='1' align='right' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='rightcolumn' rowspan='1' align='right' colspan='1'>1</td>
- </tr>
- <tr onmouseover='ron(7680287);' id='tr_7680287'
- onmouseout='roff(7680287);'>
- <td class='boxcolumn' rowspan='1' onclick='rowToggle(7680287);'
- colspan='1'>
- <input name='campaignid' type='checkbox' id='box_7680287'
- value='7680287' onclick='toggleRow(this);'/>
- </td>
- <td rowspan='1' colspan='1'>
- <a href='CampaignManagement?campaignid=7680287#a' shape='rect'>Test</a>
- </td>
- <td rowspan='1' colspan='1'>
- <b>
- <font size='-1' color='#b98b00'>Paused</font>
- </b>
- </td>
- <td class='r' rowspan='1' colspan='1'>
- <font color='#666666'>Test</font>
- </td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='' rowspan='1' align='right' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='rightcolumn' rowspan='1' align='right' colspan='1'>1</td>
- </tr>
- <tr onmouseover='ron(6747347);' id='tr_6747347'
- onmouseout='roff(6747347);'>
- <td class='boxcolumn' rowspan='1' onclick='rowToggle(6747347);'
- colspan='1'>
- <input name='campaignid' type='checkbox' id='box_6747347'
- value='6747347' onclick='toggleRow(this);'/>
- </td>
- <td rowspan='1' colspan='1'>
- <a href='CampaignManagement?campaignid=6747347#a' shape='rect'>Test</a>
- </td>
- <td rowspan='1' colspan='1'>
- <b>
- <font size='-1' color='#b98b00'>Test</font>
- </b>
- </td>
- <td class='r' rowspan='1' colspan='1'>
- <font color='#666666'>Test</font>
- </td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='' rowspan='1' align='right' colspan='1'>1</td>
- <td class='r' rowspan='1' colspan='1'>1</td>
- <td class='rightcolumn' rowspan='1' align='right' colspan='1'>1</td>
- </tr>
-</form>
diff --git a/test/rexml/data/id.xml b/test/rexml/data/id.xml
deleted file mode 100644
index 749ab207ce..0000000000
--- a/test/rexml/data/id.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0"?>
-
-<!DOCTYPE foo [
-
-<!ELEMENT foo (bar)>
-<!ATTLIST foo id CDATA #IMPLIED>
-<!ELEMENT bar (#PCDATA|cheese)*>
-<!ATTLIST bar id ID #REQUIRED>
-<!ELEMENT cheese (#PCDATA)>
-<!ATTLIST cheese kind ID #IMPLIED>
-]>
-
-<foo id="foobar">
- <bar id="fb1">
- baz
- <cheese kind="edam">gouda</cheese>
- baz
- <cheese kind="gouda">cheddar</cheese>
- baz
- </bar>
-</foo>
diff --git a/test/rexml/data/iso8859-1.xml b/test/rexml/data/iso8859-1.xml
deleted file mode 100644
index 5fb04ec9ba..0000000000
--- a/test/rexml/data/iso8859-1.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version='1.0' encoding='ISO-8859-1'?>
-<booh>
- <image caption='andr is nice'/>
-</booh>
diff --git a/test/rexml/data/jaxen24.xml b/test/rexml/data/jaxen24.xml
deleted file mode 100644
index 9b819967ee..0000000000
--- a/test/rexml/data/jaxen24.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<body><p><span></span></p><div></div></body>
diff --git a/test/rexml/data/jaxen3.xml b/test/rexml/data/jaxen3.xml
deleted file mode 100644
index a87723a3b9..0000000000
--- a/test/rexml/data/jaxen3.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Configuration>
- <hostname>
- <val>2</val>
- <attrlist>
- <hostname>CE-A</hostname>
- </attrlist>
- </hostname>
- <hostname>
- <val>1</val>
- <attrlist>
- <hostname>CE-B</hostname>
- </attrlist>
- </hostname>
-</Configuration>
diff --git a/test/rexml/data/lang.xml b/test/rexml/data/lang.xml
deleted file mode 100644
index 49b45db291..0000000000
--- a/test/rexml/data/lang.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0"?>
-<e1 xml:lang="hr">
- <e2 xml:lang="en-US">
- <e3/>
- </e2>
- <e2 xml:lang="hu">
- <e3/>
- <e3/>
- <e3 xml:lang="es"/>
- </e2>
-</e1> \ No newline at end of file
diff --git a/test/rexml/data/lang0.xml b/test/rexml/data/lang0.xml
deleted file mode 100644
index 283b4e0f08..0000000000
--- a/test/rexml/data/lang0.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<programming_languages>
- <language oop='yes'>
- <name>
- Ruby
- </name>
- <creator>
- Yukihiro Matsumoto
- </creator>
- </language>
- <language oop='yes'>
- <name>
- Python
- </name>
- <creator>
- Guido van Rossum
- </creator>
- </language>
-</programming_languages>
diff --git a/test/rexml/data/message.xml b/test/rexml/data/message.xml
deleted file mode 100644
index 3b81df2a86..0000000000
--- a/test/rexml/data/message.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<message>
- <header>
- <service>lookupformservice</service>
- <connectionid>9</connectionid>
- <appid>stammdaten</appid>
- <action>new</action>
- </header>
- <body>
- <data>
- <items>
- <item>
- <name>iteminfo</name>
- <value>ELE</value>
- </item>
- <item>
- <name>parentinfo</name>
- <value>Pruefgebiete</value>
- </item>
- <item>
- <name>id</name>
- <value>1</value>
- </item>
- </items>
- </data>
- </body>
-</message>
diff --git a/test/rexml/data/moreover.xml b/test/rexml/data/moreover.xml
deleted file mode 100644
index 38d4c4f81c..0000000000
--- a/test/rexml/data/moreover.xml
+++ /dev/null
@@ -1,244 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
- <moreovernews>
- <article code="13563275">
- <url>http://c.moreover.com/click/here.pl?x13563273</url>
- <headline_text>e-Commerce Operators Present Version 1.0 of the XML Standard</headline_text>
- <source>StockAccess</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.stockaccess.com/index.html</document_url>
- <harvest_time>Dec 24 2000 6:28AM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13560996">
- <url>http://c.moreover.com/click/here.pl?x13560995</url>
- <headline_text>W3C Publishes XML Protocol Requirements Document</headline_text>
- <source>Xml</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.xml.com/</document_url>
- <harvest_time>Dec 24 2000 12:22AM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13553522">
- <url>http://c.moreover.com/click/here.pl?x13553521</url>
- <headline_text>Prowler: Open Source XML-Based Content Management Framework</headline_text>
- <source>Xml</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.xml.com/</document_url>
- <harvest_time>Dec 23 2000 2:05PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13549014">
- <url>http://c.moreover.com/click/here.pl?x13549013</url>
- <headline_text>The Middleware Company Debuts Public Training Courses in Ejb, J2ee And Xml</headline_text>
- <source>Java Industry Connection</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://industry.java.sun.com/javanews/more/hotnews/</document_url>
- <harvest_time>Dec 23 2000 12:15PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13544468">
- <url>http://c.moreover.com/click/here.pl?x13544467</url>
- <headline_text>Revised Working Draft for the W3C XML Information Set</headline_text>
- <source>Xml</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.xml.com/</document_url>
- <harvest_time>Dec 23 2000 5:50AM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13534837">
- <url>http://c.moreover.com/click/here.pl?x13534836</url>
- <headline_text>XML: Its The Great Peacemaker</headline_text>
- <source>ZDNet</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.zdnet.com/intweek/</document_url>
- <harvest_time>Dec 22 2000 9:05PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13533486">
- <url>http://c.moreover.com/click/here.pl?x13533485</url>
- <headline_text>Project eL - The XML Leningrad Codex Markup Project</headline_text>
- <source>Xml</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.xml.com/</document_url>
- <harvest_time>Dec 22 2000 8:34PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13533489">
- <url>http://c.moreover.com/click/here.pl?x13533488</url>
- <headline_text>XML Linking Language (XLink) and XML Base Specifications Issued as W3C Proposed Recommenda</headline_text>
- <source>Xml</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.xml.com/</document_url>
- <harvest_time>Dec 22 2000 8:34PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13533493">
- <url>http://c.moreover.com/click/here.pl?x13533492</url>
- <headline_text>W3C Releases XHTML Basic Specification as a W3C Recommendation</headline_text>
- <source>Xml</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.xml.com/</document_url>
- <harvest_time>Dec 22 2000 8:34PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13521835">
- <url>http://c.moreover.com/click/here.pl?x13521827</url>
- <headline_text>Java, Xml And Oracle9i(TM) Make A Great Team</headline_text>
- <source>Java Industry Connection</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://industry.java.sun.com/javanews/more/hotnews/</document_url>
- <harvest_time>Dec 22 2000 3:21PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13512020">
- <url>http://c.moreover.com/click/here.pl?x13511233</url>
- <headline_text>Competing initiatives to vie for security standard</headline_text>
- <source>ZDNet</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.zdnet.com/eweek/filters/news/</document_url>
- <harvest_time>Dec 22 2000 10:54AM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13492401">
- <url>http://c.moreover.com/click/here.pl?x13492397</url>
- <headline_text>Oracle Provides Developers with Great Xml Reading This Holiday Season</headline_text>
- <source>Java Industry Connection</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://industry.java.sun.com/javanews/more/hotnews/</document_url>
- <harvest_time>Dec 21 2000 8:08PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13491296">
- <url>http://c.moreover.com/click/here.pl?x13491292</url>
- <headline_text>XML as the great peacemaker - Extensible Markup Language Accomplished The Seemingly Impossible This Year: It B</headline_text>
- <source>Hospitality Net</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.hospitalitynet.org/news/list.htm?c=2000</document_url>
- <harvest_time>Dec 21 2000 7:45PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13484761">
- <url>http://c.moreover.com/click/here.pl?x13484758</url>
- <headline_text>XML as the great peacemaker</headline_text>
- <source>CNET</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://news.cnet.com/news/0-1003.html?tag=st.ne.1002.dir.1003</document_url>
- <harvest_time>Dec 21 2000 4:41PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13480897">
- <url>http://c.moreover.com/click/here.pl?x13480896</url>
- <headline_text>COOP Switzerland Selects Mercator as Integration Platform</headline_text>
- <source>Stockhouse Canada</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.stockhouse.ca/news/</document_url>
- <harvest_time>Dec 21 2000 1:55PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13471024">
- <url>http://c.moreover.com/click/here.pl?x13471023</url>
- <headline_text>Competing XML Specs Move Toward a Union</headline_text>
- <source>Internet World</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://www.internetworld.com/</document_url>
- <harvest_time>Dec 21 2000 11:14AM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13452281">
- <url>http://c.moreover.com/click/here.pl?x13452280</url>
- <headline_text>Next-generation XHTML stripped down for handhelds</headline_text>
- <source>CNET</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://news.cnet.com/news/0-1005.html?tag=st.ne.1002.dir.1005</document_url>
- <harvest_time>Dec 20 2000 9:11PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13451791">
- <url>http://c.moreover.com/click/here.pl?x13451789</url>
- <headline_text>Xml Powers Oracle9i(TM) Dynamic Services</headline_text>
- <source>Java Industry Connection</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://industry.java.sun.com/javanews/more/hotnews/</document_url>
- <harvest_time>Dec 20 2000 9:05PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13442098">
- <url>http://c.moreover.com/click/here.pl?x13442097</url>
- <headline_text>XML DOM reference guide</headline_text>
- <source>ASPWire</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://aspwire.com/</document_url>
- <harvest_time>Dec 20 2000 6:26PM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- <article code="13424118">
- <url>http://c.moreover.com/click/here.pl?x13424117</url>
- <headline_text>Repeat/Xqsite And Bowstreet Team to Deliver Integrated Xml Solutions</headline_text>
- <source>Java Industry Connection</source>
- <media_type>text</media_type>
- <cluster>moreover...</cluster>
- <tagline> </tagline>
- <document_url>http://industry.java.sun.com/javanews/more/hotnews/</document_url>
- <harvest_time>Dec 20 2000 9:04AM</harvest_time>
- <access_registration> </access_registration>
- <access_status> </access_status>
- </article>
- </moreovernews>
-
diff --git a/test/rexml/data/much_ado.xml b/test/rexml/data/much_ado.xml
deleted file mode 100644
index f008fadbb0..0000000000
--- a/test/rexml/data/much_ado.xml
+++ /dev/null
@@ -1,6850 +0,0 @@
-<?xml version="1.0"?>
-<PLAY>
-<TITLE>Much Ado about Nothing</TITLE>
-
-<FM>
-<P>Text placed in the public domain by Moby Lexical Tools, 1992.</P>
-<P>SGML markup by Jon Bosak, 1992-1994.</P>
-<P>XML version by Jon Bosak, 1996-1998.</P>
-<P>This work may be freely copied and distributed worldwide.</P>
-</FM>
-
-
-<PERSONAE>
-<TITLE>Dramatis Personae</TITLE>
-
-<PERSONA>DON PEDRO, prince of Arragon.</PERSONA>
-<PERSONA>DON JOHN, his bastard brother.</PERSONA>
-<PERSONA>CLAUDIO, a young lord of Florence.</PERSONA>
-<PERSONA>BENEDICK, a young lord of Padua.</PERSONA>
-<PERSONA>LEONATO, governor of Messina.</PERSONA>
-<PERSONA>ANTONIO, his brother.</PERSONA>
-<PERSONA>BALTHASAR, attendant on Don Pedro.</PERSONA>
-
-<PGROUP>
-<PERSONA>CONRADE</PERSONA>
-<PERSONA>BORACHIO</PERSONA>
-<GRPDESCR>followers of Don John.</GRPDESCR>
-</PGROUP>
-
-<PERSONA>FRIAR FRANCIS</PERSONA>
-<PERSONA>DOGBERRY, a constable.</PERSONA>
-<PERSONA>VERGES, a headborough.</PERSONA>
-<PERSONA>A Sexton.</PERSONA>
-<PERSONA>A Boy.</PERSONA>
-<PERSONA>HERO, daughter to Leonato.</PERSONA>
-<PERSONA>BEATRICE, niece to Leonato.</PERSONA>
-
-<PGROUP>
-<PERSONA>MARGARET</PERSONA>
-<PERSONA>URSULA</PERSONA>
-<GRPDESCR>gentlewomen attending on Hero.</GRPDESCR>
-</PGROUP>
-
-<PERSONA>Messengers, Watch, Attendants, &amp;c. </PERSONA>
-</PERSONAE>
-
-<SCNDESCR>SCENE Messina.</SCNDESCR>
-
-<PLAYSUBT>MUCH ADO ABOUT NOTHING</PLAYSUBT>
-
-<ACT><TITLE>ACT I</TITLE>
-
-<SCENE><TITLE>SCENE I. Before LEONATO'S house.</TITLE>
-<STAGEDIR>Enter LEONATO, HERO, and BEATRICE, with a
-Messenger</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I learn in this letter that Don Peter of Arragon</LINE>
-<LINE>comes this night to Messina.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>He is very near by this: he was not three leagues off</LINE>
-<LINE>when I left him.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>How many gentlemen have you lost in this action?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>But few of any sort, and none of name.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>A victory is twice itself when the achiever brings</LINE>
-<LINE>home full numbers. I find here that Don Peter hath</LINE>
-<LINE>bestowed much honour on a young Florentine called Claudio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>Much deserved on his part and equally remembered by</LINE>
-<LINE>Don Pedro: he hath borne himself beyond the</LINE>
-<LINE>promise of his age, doing, in the figure of a lamb,</LINE>
-<LINE>the feats of a lion: he hath indeed better</LINE>
-<LINE>bettered expectation than you must expect of me to</LINE>
-<LINE>tell you how.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>He hath an uncle here in Messina will be very much</LINE>
-<LINE>glad of it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>I have already delivered him letters, and there</LINE>
-<LINE>appears much joy in him; even so much that joy could</LINE>
-<LINE>not show itself modest enough without a badge of</LINE>
-<LINE>bitterness.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Did he break out into tears?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>In great measure.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>A kind overflow of kindness: there are no faces</LINE>
-<LINE>truer than those that are so washed. How much</LINE>
-<LINE>better is it to weep at joy than to joy at weeping!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I pray you, is Signior Mountanto returned from the</LINE>
-<LINE>wars or no?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>I know none of that name, lady: there was none such</LINE>
-<LINE>in the army of any sort.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>What is he that you ask for, niece?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>My cousin means Signior Benedick of Padua.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>O, he's returned; and as pleasant as ever he was.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>He set up his bills here in Messina and challenged</LINE>
-<LINE>Cupid at the flight; and my uncle's fool, reading</LINE>
-<LINE>the challenge, subscribed for Cupid, and challenged</LINE>
-<LINE>him at the bird-bolt. I pray you, how many hath he</LINE>
-<LINE>killed and eaten in these wars? But how many hath</LINE>
-<LINE>he killed? for indeed I promised to eat all of his killing.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Faith, niece, you tax Signior Benedick too much;</LINE>
-<LINE>but he'll be meet with you, I doubt it not.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>He hath done good service, lady, in these wars.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>You had musty victual, and he hath holp to eat it:</LINE>
-<LINE>he is a very valiant trencherman; he hath an</LINE>
-<LINE>excellent stomach.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>And a good soldier too, lady.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>And a good soldier to a lady: but what is he to a lord?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>A lord to a lord, a man to a man; stuffed with all</LINE>
-<LINE>honourable virtues.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>It is so, indeed; he is no less than a stuffed man:</LINE>
-<LINE>but for the stuffing,--well, we are all mortal.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>You must not, sir, mistake my niece. There is a</LINE>
-<LINE>kind of merry war betwixt Signior Benedick and her:</LINE>
-<LINE>they never meet but there's a skirmish of wit</LINE>
-<LINE>between them.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Alas! he gets nothing by that. In our last</LINE>
-<LINE>conflict four of his five wits went halting off, and</LINE>
-<LINE>now is the whole man governed with one: so that if</LINE>
-<LINE>he have wit enough to keep himself warm, let him</LINE>
-<LINE>bear it for a difference between himself and his</LINE>
-<LINE>horse; for it is all the wealth that he hath left,</LINE>
-<LINE>to be known a reasonable creature. Who is his</LINE>
-<LINE>companion now? He hath every month a new sworn brother.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>Is't possible?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Very easily possible: he wears his faith but as</LINE>
-<LINE>the fashion of his hat; it ever changes with the</LINE>
-<LINE>next block.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>I see, lady, the gentleman is not in your books.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>No; an he were, I would burn my study. But, I pray</LINE>
-<LINE>you, who is his companion? Is there no young</LINE>
-<LINE>squarer now that will make a voyage with him to the devil?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>He is most in the company of the right noble Claudio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>O Lord, he will hang upon him like a disease: he</LINE>
-<LINE>is sooner caught than the pestilence, and the taker</LINE>
-<LINE>runs presently mad. God help the noble Claudio! if</LINE>
-<LINE>he have caught the Benedick, it will cost him a</LINE>
-<LINE>thousand pound ere a' be cured.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>I will hold friends with you, lady.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Do, good friend.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>You will never run mad, niece.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>No, not till a hot January.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>Don Pedro is approached.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter DON PEDRO, DON JOHN, CLAUDIO, BENEDICK,
-and BALTHASAR</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Good Signior Leonato, you are come to meet your</LINE>
-<LINE>trouble: the fashion of the world is to avoid</LINE>
-<LINE>cost, and you encounter it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Never came trouble to my house in the likeness of</LINE>
-<LINE>your grace: for trouble being gone, comfort should</LINE>
-<LINE>remain; but when you depart from me, sorrow abides</LINE>
-<LINE>and happiness takes his leave.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>You embrace your charge too willingly. I think this</LINE>
-<LINE>is your daughter.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Her mother hath many times told me so.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Were you in doubt, sir, that you asked her?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Signior Benedick, no; for then were you a child.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>You have it full, Benedick: we may guess by this</LINE>
-<LINE>what you are, being a man. Truly, the lady fathers</LINE>
-<LINE>herself. Be happy, lady; for you are like an</LINE>
-<LINE>honourable father.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>If Signior Leonato be her father, she would not</LINE>
-<LINE>have his head on her shoulders for all Messina, as</LINE>
-<LINE>like him as she is.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I wonder that you will still be talking, Signior</LINE>
-<LINE>Benedick: nobody marks you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>What, my dear Lady Disdain! are you yet living?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Is it possible disdain should die while she hath</LINE>
-<LINE>such meet food to feed it as Signior Benedick?</LINE>
-<LINE>Courtesy itself must convert to disdain, if you come</LINE>
-<LINE>in her presence.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Then is courtesy a turncoat. But it is certain I</LINE>
-<LINE>am loved of all ladies, only you excepted: and I</LINE>
-<LINE>would I could find in my heart that I had not a hard</LINE>
-<LINE>heart; for, truly, I love none.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>A dear happiness to women: they would else have</LINE>
-<LINE>been troubled with a pernicious suitor. I thank God</LINE>
-<LINE>and my cold blood, I am of your humour for that: I</LINE>
-<LINE>had rather hear my dog bark at a crow than a man</LINE>
-<LINE>swear he loves me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>God keep your ladyship still in that mind! so some</LINE>
-<LINE>gentleman or other shall 'scape a predestinate</LINE>
-<LINE>scratched face.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Scratching could not make it worse, an 'twere such</LINE>
-<LINE>a face as yours were.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Well, you are a rare parrot-teacher.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>A bird of my tongue is better than a beast of yours.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I would my horse had the speed of your tongue, and</LINE>
-<LINE>so good a continuer. But keep your way, i' God's</LINE>
-<LINE>name; I have done.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>You always end with a jade's trick: I know you of old.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>That is the sum of all, Leonato. Signior Claudio</LINE>
-<LINE>and Signior Benedick, my dear friend Leonato hath</LINE>
-<LINE>invited you all. I tell him we shall stay here at</LINE>
-<LINE>the least a month; and he heartily prays some</LINE>
-<LINE>occasion may detain us longer. I dare swear he is no</LINE>
-<LINE>hypocrite, but prays from his heart.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>If you swear, my lord, you shall not be forsworn.</LINE>
-<STAGEDIR>To DON JOHN</STAGEDIR>
-<LINE>Let me bid you welcome, my lord: being reconciled to</LINE>
-<LINE>the prince your brother, I owe you all duty.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I thank you: I am not of many words, but I thank</LINE>
-<LINE>you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Please it your grace lead on?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Your hand, Leonato; we will go together.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt all except BENEDICK and CLAUDIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Benedick, didst thou note the daughter of Signior Leonato?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I noted her not; but I looked on her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Is she not a modest young lady?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Do you question me, as an honest man should do, for</LINE>
-<LINE>my simple true judgment; or would you have me speak</LINE>
-<LINE>after my custom, as being a professed tyrant to their sex?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>No; I pray thee speak in sober judgment.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Why, i' faith, methinks she's too low for a high</LINE>
-<LINE>praise, too brown for a fair praise and too little</LINE>
-<LINE>for a great praise: only this commendation I can</LINE>
-<LINE>afford her, that were she other than she is, she</LINE>
-<LINE>were unhandsome; and being no other but as she is, I</LINE>
-<LINE>do not like her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Thou thinkest I am in sport: I pray thee tell me</LINE>
-<LINE>truly how thou likest her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Would you buy her, that you inquire after her?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Can the world buy such a jewel?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Yea, and a case to put it into. But speak you this</LINE>
-<LINE>with a sad brow? or do you play the flouting Jack,</LINE>
-<LINE>to tell us Cupid is a good hare-finder and Vulcan a</LINE>
-<LINE>rare carpenter? Come, in what key shall a man take</LINE>
-<LINE>you, to go in the song?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>In mine eye she is the sweetest lady that ever I</LINE>
-<LINE>looked on.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I can see yet without spectacles and I see no such</LINE>
-<LINE>matter: there's her cousin, an she were not</LINE>
-<LINE>possessed with a fury, exceeds her as much in beauty</LINE>
-<LINE>as the first of May doth the last of December. But I</LINE>
-<LINE>hope you have no intent to turn husband, have you?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I would scarce trust myself, though I had sworn the</LINE>
-<LINE>contrary, if Hero would be my wife.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Is't come to this? In faith, hath not the world</LINE>
-<LINE>one man but he will wear his cap with suspicion?</LINE>
-<LINE>Shall I never see a bachelor of three-score again?</LINE>
-<LINE>Go to, i' faith; an thou wilt needs thrust thy neck</LINE>
-<LINE>into a yoke, wear the print of it and sigh away</LINE>
-<LINE>Sundays. Look Don Pedro is returned to seek you.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Re-enter DON PEDRO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>What secret hath held you here, that you followed</LINE>
-<LINE>not to Leonato's?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I would your grace would constrain me to tell.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>I charge thee on thy allegiance.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>You hear, Count Claudio: I can be secret as a dumb</LINE>
-<LINE>man; I would have you think so; but, on my</LINE>
-<LINE>allegiance, mark you this, on my allegiance. He is</LINE>
-<LINE>in love. With who? now that is your grace's part.</LINE>
-<LINE>Mark how short his answer is;--With Hero, Leonato's</LINE>
-<LINE>short daughter.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>If this were so, so were it uttered.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Like the old tale, my lord: 'it is not so, nor</LINE>
-<LINE>'twas not so, but, indeed, God forbid it should be</LINE>
-<LINE>so.'</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>If my passion change not shortly, God forbid it</LINE>
-<LINE>should be otherwise.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Amen, if you love her; for the lady is very well worthy.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>You speak this to fetch me in, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>By my troth, I speak my thought.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And, in faith, my lord, I spoke mine.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>And, by my two faiths and troths, my lord, I spoke mine.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>That I love her, I feel.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>That she is worthy, I know.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>That I neither feel how she should be loved nor</LINE>
-<LINE>know how she should be worthy, is the opinion that</LINE>
-<LINE>fire cannot melt out of me: I will die in it at the stake.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Thou wast ever an obstinate heretic in the despite</LINE>
-<LINE>of beauty.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And never could maintain his part but in the force</LINE>
-<LINE>of his will.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>That a woman conceived me, I thank her; that she</LINE>
-<LINE>brought me up, I likewise give her most humble</LINE>
-<LINE>thanks: but that I will have a recheat winded in my</LINE>
-<LINE>forehead, or hang my bugle in an invisible baldrick,</LINE>
-<LINE>all women shall pardon me. Because I will not do</LINE>
-<LINE>them the wrong to mistrust any, I will do myself the</LINE>
-<LINE>right to trust none; and the fine is, for the which</LINE>
-<LINE>I may go the finer, I will live a bachelor.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>I shall see thee, ere I die, look pale with love.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>With anger, with sickness, or with hunger, my lord,</LINE>
-<LINE>not with love: prove that ever I lose more blood</LINE>
-<LINE>with love than I will get again with drinking, pick</LINE>
-<LINE>out mine eyes with a ballad-maker's pen and hang me</LINE>
-<LINE>up at the door of a brothel-house for the sign of</LINE>
-<LINE>blind Cupid.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Well, if ever thou dost fall from this faith, thou</LINE>
-<LINE>wilt prove a notable argument.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>If I do, hang me in a bottle like a cat and shoot</LINE>
-<LINE>at me; and he that hits me, let him be clapped on</LINE>
-<LINE>the shoulder, and called Adam.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Well, as time shall try: 'In time the savage bull</LINE>
-<LINE>doth bear the yoke.'</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>The savage bull may; but if ever the sensible</LINE>
-<LINE>Benedick bear it, pluck off the bull's horns and set</LINE>
-<LINE>them in my forehead: and let me be vilely painted,</LINE>
-<LINE>and in such great letters as they write 'Here is</LINE>
-<LINE>good horse to hire,' let them signify under my sign</LINE>
-<LINE>'Here you may see Benedick the married man.'</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>If this should ever happen, thou wouldst be horn-mad.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Nay, if Cupid have not spent all his quiver in</LINE>
-<LINE>Venice, thou wilt quake for this shortly.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I look for an earthquake too, then.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Well, you temporize with the hours. In the</LINE>
-<LINE>meantime, good Signior Benedick, repair to</LINE>
-<LINE>Leonato's: commend me to him and tell him I will</LINE>
-<LINE>not fail him at supper; for indeed he hath made</LINE>
-<LINE>great preparation.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I have almost matter enough in me for such an</LINE>
-<LINE>embassage; and so I commit you--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>To the tuition of God: From my house, if I had it,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>The sixth of July: Your loving friend, Benedick.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Nay, mock not, mock not. The body of your</LINE>
-<LINE>discourse is sometime guarded with fragments, and</LINE>
-<LINE>the guards are but slightly basted on neither: ere</LINE>
-<LINE>you flout old ends any further, examine your</LINE>
-<LINE>conscience: and so I leave you.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>My liege, your highness now may do me good.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>My love is thine to teach: teach it but how,</LINE>
-<LINE>And thou shalt see how apt it is to learn</LINE>
-<LINE>Any hard lesson that may do thee good.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Hath Leonato any son, my lord?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>No child but Hero; she's his only heir.</LINE>
-<LINE>Dost thou affect her, Claudio?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>O, my lord,</LINE>
-<LINE>When you went onward on this ended action,</LINE>
-<LINE>I look'd upon her with a soldier's eye,</LINE>
-<LINE>That liked, but had a rougher task in hand</LINE>
-<LINE>Than to drive liking to the name of love:</LINE>
-<LINE>But now I am return'd and that war-thoughts</LINE>
-<LINE>Have left their places vacant, in their rooms</LINE>
-<LINE>Come thronging soft and delicate desires,</LINE>
-<LINE>All prompting me how fair young Hero is,</LINE>
-<LINE>Saying, I liked her ere I went to wars.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Thou wilt be like a lover presently</LINE>
-<LINE>And tire the hearer with a book of words.</LINE>
-<LINE>If thou dost love fair Hero, cherish it,</LINE>
-<LINE>And I will break with her and with her father,</LINE>
-<LINE>And thou shalt have her. Was't not to this end</LINE>
-<LINE>That thou began'st to twist so fine a story?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>How sweetly you do minister to love,</LINE>
-<LINE>That know love's grief by his complexion!</LINE>
-<LINE>But lest my liking might too sudden seem,</LINE>
-<LINE>I would have salved it with a longer treatise.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>What need the bridge much broader than the flood?</LINE>
-<LINE>The fairest grant is the necessity.</LINE>
-<LINE>Look, what will serve is fit: 'tis once, thou lovest,</LINE>
-<LINE>And I will fit thee with the remedy.</LINE>
-<LINE>I know we shall have revelling to-night:</LINE>
-<LINE>I will assume thy part in some disguise</LINE>
-<LINE>And tell fair Hero I am Claudio,</LINE>
-<LINE>And in her bosom I'll unclasp my heart</LINE>
-<LINE>And take her hearing prisoner with the force</LINE>
-<LINE>And strong encounter of my amorous tale:</LINE>
-<LINE>Then after to her father will I break;</LINE>
-<LINE>And the conclusion is, she shall be thine.</LINE>
-<LINE>In practise let us put it presently.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE II. A room in LEONATO's house.</TITLE>
-<STAGEDIR>Enter LEONATO and ANTONIO, meeting</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>How now, brother! Where is my cousin, your son?</LINE>
-<LINE>hath he provided this music?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>He is very busy about it. But, brother, I can tell</LINE>
-<LINE>you strange news that you yet dreamt not of.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Are they good?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>As the event stamps them: but they have a good</LINE>
-<LINE>cover; they show well outward. The prince and Count</LINE>
-<LINE>Claudio, walking in a thick-pleached alley in mine</LINE>
-<LINE>orchard, were thus much overheard by a man of mine:</LINE>
-<LINE>the prince discovered to Claudio that he loved my</LINE>
-<LINE>niece your daughter and meant to acknowledge it</LINE>
-<LINE>this night in a dance: and if he found her</LINE>
-<LINE>accordant, he meant to take the present time by the</LINE>
-<LINE>top and instantly break with you of it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Hath the fellow any wit that told you this?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>A good sharp fellow: I will send for him; and</LINE>
-<LINE>question him yourself.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>No, no; we will hold it as a dream till it appear</LINE>
-<LINE>itself: but I will acquaint my daughter withal,</LINE>
-<LINE>that she may be the better prepared for an answer,</LINE>
-<LINE>if peradventure this be true. Go you and tell her of it.</LINE>
-<STAGEDIR>Enter Attendants</STAGEDIR>
-<LINE>Cousins, you know what you have to do. O, I cry you</LINE>
-<LINE>mercy, friend; go you with me, and I will use your</LINE>
-<LINE>skill. Good cousin, have a care this busy time.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE III. The same.</TITLE>
-<STAGEDIR>Enter DON JOHN and CONRADE</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>What the good-year, my lord! why are you thus out</LINE>
-<LINE>of measure sad?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>There is no measure in the occasion that breeds;</LINE>
-<LINE>therefore the sadness is without limit.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>You should hear reason.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>And when I have heard it, what blessing brings it?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>If not a present remedy, at least a patient</LINE>
-<LINE>sufferance.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I wonder that thou, being, as thou sayest thou art,</LINE>
-<LINE>born under Saturn, goest about to apply a moral</LINE>
-<LINE>medicine to a mortifying mischief. I cannot hide</LINE>
-<LINE>what I am: I must be sad when I have cause and smile</LINE>
-<LINE>at no man's jests, eat when I have stomach and wait</LINE>
-<LINE>for no man's leisure, sleep when I am drowsy and</LINE>
-<LINE>tend on no man's business, laugh when I am merry and</LINE>
-<LINE>claw no man in his humour.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Yea, but you must not make the full show of this</LINE>
-<LINE>till you may do it without controlment. You have of</LINE>
-<LINE>late stood out against your brother, and he hath</LINE>
-<LINE>ta'en you newly into his grace; where it is</LINE>
-<LINE>impossible you should take true root but by the</LINE>
-<LINE>fair weather that you make yourself: it is needful</LINE>
-<LINE>that you frame the season for your own harvest.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I had rather be a canker in a hedge than a rose in</LINE>
-<LINE>his grace, and it better fits my blood to be</LINE>
-<LINE>disdained of all than to fashion a carriage to rob</LINE>
-<LINE>love from any: in this, though I cannot be said to</LINE>
-<LINE>be a flattering honest man, it must not be denied</LINE>
-<LINE>but I am a plain-dealing villain. I am trusted with</LINE>
-<LINE>a muzzle and enfranchised with a clog; therefore I</LINE>
-<LINE>have decreed not to sing in my cage. If I had my</LINE>
-<LINE>mouth, I would bite; if I had my liberty, I would do</LINE>
-<LINE>my liking: in the meantime let me be that I am and</LINE>
-<LINE>seek not to alter me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Can you make no use of your discontent?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I make all use of it, for I use it only.</LINE>
-<LINE>Who comes here?</LINE>
-<STAGEDIR>Enter BORACHIO</STAGEDIR>
-<LINE>What news, Borachio?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>I came yonder from a great supper: the prince your</LINE>
-<LINE>brother is royally entertained by Leonato: and I</LINE>
-<LINE>can give you intelligence of an intended marriage.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Will it serve for any model to build mischief on?</LINE>
-<LINE>What is he for a fool that betroths himself to</LINE>
-<LINE>unquietness?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Marry, it is your brother's right hand.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Who? the most exquisite Claudio?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Even he.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>A proper squire! And who, and who? which way looks</LINE>
-<LINE>he?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Marry, on Hero, the daughter and heir of Leonato.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>A very forward March-chick! How came you to this?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Being entertained for a perfumer, as I was smoking a</LINE>
-<LINE>musty room, comes me the prince and Claudio, hand</LINE>
-<LINE>in hand in sad conference: I whipt me behind the</LINE>
-<LINE>arras; and there heard it agreed upon that the</LINE>
-<LINE>prince should woo Hero for himself, and having</LINE>
-<LINE>obtained her, give her to Count Claudio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Come, come, let us thither: this may prove food to</LINE>
-<LINE>my displeasure. That young start-up hath all the</LINE>
-<LINE>glory of my overthrow: if I can cross him any way, I</LINE>
-<LINE>bless myself every way. You are both sure, and will assist me?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>To the death, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Let us to the great supper: their cheer is the</LINE>
-<LINE>greater that I am subdued. Would the cook were of</LINE>
-<LINE>my mind! Shall we go prove what's to be done?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>We'll wait upon your lordship.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-</ACT>
-
-<ACT><TITLE>ACT II</TITLE>
-
-<SCENE><TITLE>SCENE I. A hall in LEONATO'S house.</TITLE>
-<STAGEDIR>Enter LEONATO, ANTONIO, HERO, BEATRICE, and others</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Was not Count John here at supper?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>I saw him not.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>How tartly that gentleman looks! I never can see</LINE>
-<LINE>him but I am heart-burned an hour after.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>He is of a very melancholy disposition.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>He were an excellent man that were made just in the</LINE>
-<LINE>midway between him and Benedick: the one is too</LINE>
-<LINE>like an image and says nothing, and the other too</LINE>
-<LINE>like my lady's eldest son, evermore tattling.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Then half Signior Benedick's tongue in Count John's</LINE>
-<LINE>mouth, and half Count John's melancholy in Signior</LINE>
-<LINE>Benedick's face,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>With a good leg and a good foot, uncle, and money</LINE>
-<LINE>enough in his purse, such a man would win any woman</LINE>
-<LINE>in the world, if a' could get her good-will.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>By my troth, niece, thou wilt never get thee a</LINE>
-<LINE>husband, if thou be so shrewd of thy tongue.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>In faith, she's too curst.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Too curst is more than curst: I shall lessen God's</LINE>
-<LINE>sending that way; for it is said, 'God sends a curst</LINE>
-<LINE>cow short horns;' but to a cow too curst he sends none.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>So, by being too curst, God will send you no horns.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Just, if he send me no husband; for the which</LINE>
-<LINE>blessing I am at him upon my knees every morning and</LINE>
-<LINE>evening. Lord, I could not endure a husband with a</LINE>
-<LINE>beard on his face: I had rather lie in the woollen.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>You may light on a husband that hath no beard.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>What should I do with him? dress him in my apparel</LINE>
-<LINE>and make him my waiting-gentlewoman? He that hath a</LINE>
-<LINE>beard is more than a youth, and he that hath no</LINE>
-<LINE>beard is less than a man: and he that is more than</LINE>
-<LINE>a youth is not for me, and he that is less than a</LINE>
-<LINE>man, I am not for him: therefore, I will even take</LINE>
-<LINE>sixpence in earnest of the bear-ward, and lead his</LINE>
-<LINE>apes into hell.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Well, then, go you into hell?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>No, but to the gate; and there will the devil meet</LINE>
-<LINE>me, like an old cuckold, with horns on his head, and</LINE>
-<LINE>say 'Get you to heaven, Beatrice, get you to</LINE>
-<LINE>heaven; here's no place for you maids:' so deliver</LINE>
-<LINE>I up my apes, and away to Saint Peter for the</LINE>
-<LINE>heavens; he shows me where the bachelors sit, and</LINE>
-<LINE>there live we as merry as the day is long.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE><STAGEDIR>To HERO</STAGEDIR> Well, niece, I trust you will be ruled</LINE>
-<LINE>by your father.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Yes, faith; it is my cousin's duty to make curtsy</LINE>
-<LINE>and say 'Father, as it please you.' But yet for all</LINE>
-<LINE>that, cousin, let him be a handsome fellow, or else</LINE>
-<LINE>make another curtsy and say 'Father, as it please</LINE>
-<LINE>me.'</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Well, niece, I hope to see you one day fitted with a husband.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Not till God make men of some other metal than</LINE>
-<LINE>earth. Would it not grieve a woman to be</LINE>
-<LINE>overmastered with a pierce of valiant dust? to make</LINE>
-<LINE>an account of her life to a clod of wayward marl?</LINE>
-<LINE>No, uncle, I'll none: Adam's sons are my brethren;</LINE>
-<LINE>and, truly, I hold it a sin to match in my kindred.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Daughter, remember what I told you: if the prince</LINE>
-<LINE>do solicit you in that kind, you know your answer.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>The fault will be in the music, cousin, if you be</LINE>
-<LINE>not wooed in good time: if the prince be too</LINE>
-<LINE>important, tell him there is measure in every thing</LINE>
-<LINE>and so dance out the answer. For, hear me, Hero:</LINE>
-<LINE>wooing, wedding, and repenting, is as a Scotch jig,</LINE>
-<LINE>a measure, and a cinque pace: the first suit is hot</LINE>
-<LINE>and hasty, like a Scotch jig, and full as</LINE>
-<LINE>fantastical; the wedding, mannerly-modest, as a</LINE>
-<LINE>measure, full of state and ancientry; and then comes</LINE>
-<LINE>repentance and, with his bad legs, falls into the</LINE>
-<LINE>cinque pace faster and faster, till he sink into his grave.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Cousin, you apprehend passing shrewdly.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I have a good eye, uncle; I can see a church by daylight.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>The revellers are entering, brother: make good room.</LINE>
-</SPEECH>
-
-<STAGEDIR>All put on their masks</STAGEDIR>
-<STAGEDIR>Enter DON PEDRO, CLAUDIO, BENEDICK, BALTHASAR,
-DON JOHN, BORACHIO, MARGARET, URSULA and others, masked</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Lady, will you walk about with your friend?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>So you walk softly and look sweetly and say nothing,</LINE>
-<LINE>I am yours for the walk; and especially when I walk away.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>With me in your company?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>I may say so, when I please.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>And when please you to say so?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>When I like your favour; for God defend the lute</LINE>
-<LINE>should be like the case!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>My visor is Philemon's roof; within the house is Jove.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Why, then, your visor should be thatched.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Speak low, if you speak love.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Drawing her aside</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>Well, I would you did like me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>So would not I, for your own sake; for I have many</LINE>
-<LINE>ill-qualities.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>Which is one?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>I say my prayers aloud.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>I love you the better: the hearers may cry, Amen.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>God match me with a good dancer!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>Amen.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>And God keep him out of my sight when the dance is</LINE>
-<LINE>done! Answer, clerk.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>No more words: the clerk is answered.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>I know you well enough; you are Signior Antonio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>At a word, I am not.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>I know you by the waggling of your head.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>To tell you true, I counterfeit him.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>You could never do him so ill-well, unless you were</LINE>
-<LINE>the very man. Here's his dry hand up and down: you</LINE>
-<LINE>are he, you are he.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>At a word, I am not.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>Come, come, do you think I do not know you by your</LINE>
-<LINE>excellent wit? can virtue hide itself? Go to,</LINE>
-<LINE>mum, you are he: graces will appear, and there's an</LINE>
-<LINE>end.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Will you not tell me who told you so?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>No, you shall pardon me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Nor will you not tell me who you are?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Not now.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>That I was disdainful, and that I had my good wit</LINE>
-<LINE>out of the 'Hundred Merry Tales:'--well this was</LINE>
-<LINE>Signior Benedick that said so.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>What's he?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I am sure you know him well enough.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Not I, believe me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Did he never make you laugh?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I pray you, what is he?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Why, he is the prince's jester: a very dull fool;</LINE>
-<LINE>only his gift is in devising impossible slanders:</LINE>
-<LINE>none but libertines delight in him; and the</LINE>
-<LINE>commendation is not in his wit, but in his villany;</LINE>
-<LINE>for he both pleases men and angers them, and then</LINE>
-<LINE>they laugh at him and beat him. I am sure he is in</LINE>
-<LINE>the fleet: I would he had boarded me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>When I know the gentleman, I'll tell him what you say.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Do, do: he'll but break a comparison or two on me;</LINE>
-<LINE>which, peradventure not marked or not laughed at,</LINE>
-<LINE>strikes him into melancholy; and then there's a</LINE>
-<LINE>partridge wing saved, for the fool will eat no</LINE>
-<LINE>supper that night.</LINE>
-<STAGEDIR>Music</STAGEDIR>
-<LINE>We must follow the leaders.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>In every good thing.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Nay, if they lead to any ill, I will leave them at</LINE>
-<LINE>the next turning.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Dance. Then exeunt all except DON JOHN, BORACHIO,
-and CLAUDIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Sure my brother is amorous on Hero and hath</LINE>
-<LINE>withdrawn her father to break with him about it.</LINE>
-<LINE>The ladies follow her and but one visor remains.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>And that is Claudio: I know him by his bearing.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Are not you Signior Benedick?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>You know me well; I am he.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Signior, you are very near my brother in his love:</LINE>
-<LINE>he is enamoured on Hero; I pray you, dissuade him</LINE>
-<LINE>from her: she is no equal for his birth: you may</LINE>
-<LINE>do the part of an honest man in it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>How know you he loves her?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I heard him swear his affection.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>So did I too; and he swore he would marry her to-night.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Come, let us to the banquet.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt DON JOHN and BORACHIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Thus answer I in the name of Benedick,</LINE>
-<LINE>But hear these ill news with the ears of Claudio.</LINE>
-<LINE>'Tis certain so; the prince wooes for himself.</LINE>
-<LINE>Friendship is constant in all other things</LINE>
-<LINE>Save in the office and affairs of love:</LINE>
-<LINE>Therefore, all hearts in love use their own tongues;</LINE>
-<LINE>Let every eye negotiate for itself</LINE>
-<LINE>And trust no agent; for beauty is a witch</LINE>
-<LINE>Against whose charms faith melteth into blood.</LINE>
-<LINE>This is an accident of hourly proof,</LINE>
-<LINE>Which I mistrusted not. Farewell, therefore, Hero!</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Re-enter BENEDICK</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Count Claudio?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Yea, the same.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Come, will you go with me?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Whither?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Even to the next willow, about your own business,</LINE>
-<LINE>county. What fashion will you wear the garland of?</LINE>
-<LINE>about your neck, like an usurer's chain? or under</LINE>
-<LINE>your arm, like a lieutenant's scarf? You must wear</LINE>
-<LINE>it one way, for the prince hath got your Hero.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I wish him joy of her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Why, that's spoken like an honest drovier: so they</LINE>
-<LINE>sell bullocks. But did you think the prince would</LINE>
-<LINE>have served you thus?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I pray you, leave me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Ho! now you strike like the blind man: 'twas the</LINE>
-<LINE>boy that stole your meat, and you'll beat the post.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>If it will not be, I'll leave you.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Alas, poor hurt fowl! now will he creep into sedges.</LINE>
-<LINE>But that my Lady Beatrice should know me, and not</LINE>
-<LINE>know me! The prince's fool! Ha? It may be I go</LINE>
-<LINE>under that title because I am merry. Yea, but so I</LINE>
-<LINE>am apt to do myself wrong; I am not so reputed: it</LINE>
-<LINE>is the base, though bitter, disposition of Beatrice</LINE>
-<LINE>that puts the world into her person and so gives me</LINE>
-<LINE>out. Well, I'll be revenged as I may.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Re-enter DON PEDRO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Now, signior, where's the count? did you see him?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Troth, my lord, I have played the part of Lady Fame.</LINE>
-<LINE>I found him here as melancholy as a lodge in a</LINE>
-<LINE>warren: I told him, and I think I told him true,</LINE>
-<LINE>that your grace had got the good will of this young</LINE>
-<LINE>lady; and I offered him my company to a willow-tree,</LINE>
-<LINE>either to make him a garland, as being forsaken, or</LINE>
-<LINE>to bind him up a rod, as being worthy to be whipped.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>To be whipped! What's his fault?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>The flat transgression of a schoolboy, who, being</LINE>
-<LINE>overjoyed with finding a birds' nest, shows it his</LINE>
-<LINE>companion, and he steals it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Wilt thou make a trust a transgression? The</LINE>
-<LINE>transgression is in the stealer.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Yet it had not been amiss the rod had been made,</LINE>
-<LINE>and the garland too; for the garland he might have</LINE>
-<LINE>worn himself, and the rod he might have bestowed on</LINE>
-<LINE>you, who, as I take it, have stolen his birds' nest.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>I will but teach them to sing, and restore them to</LINE>
-<LINE>the owner.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>If their singing answer your saying, by my faith,</LINE>
-<LINE>you say honestly.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>The Lady Beatrice hath a quarrel to you: the</LINE>
-<LINE>gentleman that danced with her told her she is much</LINE>
-<LINE>wronged by you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>O, she misused me past the endurance of a block!</LINE>
-<LINE>an oak but with one green leaf on it would have</LINE>
-<LINE>answered her; my very visor began to assume life and</LINE>
-<LINE>scold with her. She told me, not thinking I had been</LINE>
-<LINE>myself, that I was the prince's jester, that I was</LINE>
-<LINE>duller than a great thaw; huddling jest upon jest</LINE>
-<LINE>with such impossible conveyance upon me that I stood</LINE>
-<LINE>like a man at a mark, with a whole army shooting at</LINE>
-<LINE>me. She speaks poniards, and every word stabs:</LINE>
-<LINE>if her breath were as terrible as her terminations,</LINE>
-<LINE>there were no living near her; she would infect to</LINE>
-<LINE>the north star. I would not marry her, though she</LINE>
-<LINE>were endowed with all that Adam bad left him before</LINE>
-<LINE>he transgressed: she would have made Hercules have</LINE>
-<LINE>turned spit, yea, and have cleft his club to make</LINE>
-<LINE>the fire too. Come, talk not of her: you shall find</LINE>
-<LINE>her the infernal Ate in good apparel. I would to God</LINE>
-<LINE>some scholar would conjure her; for certainly, while</LINE>
-<LINE>she is here, a man may live as quiet in hell as in a</LINE>
-<LINE>sanctuary; and people sin upon purpose, because they</LINE>
-<LINE>would go thither; so, indeed, all disquiet, horror</LINE>
-<LINE>and perturbation follows her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Look, here she comes.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter CLAUDIO, BEATRICE, HERO, and LEONATO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Will your grace command me any service to the</LINE>
-<LINE>world's end? I will go on the slightest errand now</LINE>
-<LINE>to the Antipodes that you can devise to send me on;</LINE>
-<LINE>I will fetch you a tooth-picker now from the</LINE>
-<LINE>furthest inch of Asia, bring you the length of</LINE>
-<LINE>Prester John's foot, fetch you a hair off the great</LINE>
-<LINE>Cham's beard, do you any embassage to the Pigmies,</LINE>
-<LINE>rather than hold three words' conference with this</LINE>
-<LINE>harpy. You have no employment for me?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>None, but to desire your good company.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>O God, sir, here's a dish I love not: I cannot</LINE>
-<LINE>endure my Lady Tongue.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Come, lady, come; you have lost the heart of</LINE>
-<LINE>Signior Benedick.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Indeed, my lord, he lent it me awhile; and I gave</LINE>
-<LINE>him use for it, a double heart for his single one:</LINE>
-<LINE>marry, once before he won it of me with false dice,</LINE>
-<LINE>therefore your grace may well say I have lost it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>You have put him down, lady, you have put him down.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>So I would not he should do me, my lord, lest I</LINE>
-<LINE>should prove the mother of fools. I have brought</LINE>
-<LINE>Count Claudio, whom you sent me to seek.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Why, how now, count! wherefore are you sad?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Not sad, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>How then? sick?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Neither, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>The count is neither sad, nor sick, nor merry, nor</LINE>
-<LINE>well; but civil count, civil as an orange, and</LINE>
-<LINE>something of that jealous complexion.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>I' faith, lady, I think your blazon to be true;</LINE>
-<LINE>though, I'll be sworn, if he be so, his conceit is</LINE>
-<LINE>false. Here, Claudio, I have wooed in thy name, and</LINE>
-<LINE>fair Hero is won: I have broke with her father,</LINE>
-<LINE>and his good will obtained: name the day of</LINE>
-<LINE>marriage, and God give thee joy!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Count, take of me my daughter, and with her my</LINE>
-<LINE>fortunes: his grace hath made the match, and an</LINE>
-<LINE>grace say Amen to it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Speak, count, 'tis your cue.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Silence is the perfectest herald of joy: I were</LINE>
-<LINE>but little happy, if I could say how much. Lady, as</LINE>
-<LINE>you are mine, I am yours: I give away myself for</LINE>
-<LINE>you and dote upon the exchange.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Speak, cousin; or, if you cannot, stop his mouth</LINE>
-<LINE>with a kiss, and let not him speak neither.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>In faith, lady, you have a merry heart.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Yea, my lord; I thank it, poor fool, it keeps on</LINE>
-<LINE>the windy side of care. My cousin tells him in his</LINE>
-<LINE>ear that he is in her heart.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And so she doth, cousin.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Good Lord, for alliance! Thus goes every one to the</LINE>
-<LINE>world but I, and I am sunburnt; I may sit in a</LINE>
-<LINE>corner and cry heigh-ho for a husband!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Lady Beatrice, I will get you one.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I would rather have one of your father's getting.</LINE>
-<LINE>Hath your grace ne'er a brother like you? Your</LINE>
-<LINE>father got excellent husbands, if a maid could come by them.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Will you have me, lady?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>No, my lord, unless I might have another for</LINE>
-<LINE>working-days: your grace is too costly to wear</LINE>
-<LINE>every day. But, I beseech your grace, pardon me: I</LINE>
-<LINE>was born to speak all mirth and no matter.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Your silence most offends me, and to be merry best</LINE>
-<LINE>becomes you; for, out of question, you were born in</LINE>
-<LINE>a merry hour.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>No, sure, my lord, my mother cried; but then there</LINE>
-<LINE>was a star danced, and under that was I born.</LINE>
-<LINE>Cousins, God give you joy!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Niece, will you look to those things I told you of?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I cry you mercy, uncle. By your grace's pardon.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>By my troth, a pleasant-spirited lady.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>There's little of the melancholy element in her, my</LINE>
-<LINE>lord: she is never sad but when she sleeps, and</LINE>
-<LINE>not ever sad then; for I have heard my daughter say,</LINE>
-<LINE>she hath often dreamed of unhappiness and waked</LINE>
-<LINE>herself with laughing.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>She cannot endure to hear tell of a husband.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>O, by no means: she mocks all her wooers out of suit.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>She were an excellent wife for Benedict.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>O Lord, my lord, if they were but a week married,</LINE>
-<LINE>they would talk themselves mad.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>County Claudio, when mean you to go to church?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>To-morrow, my lord: time goes on crutches till love</LINE>
-<LINE>have all his rites.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Not till Monday, my dear son, which is hence a just</LINE>
-<LINE>seven-night; and a time too brief, too, to have all</LINE>
-<LINE>things answer my mind.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Come, you shake the head at so long a breathing:</LINE>
-<LINE>but, I warrant thee, Claudio, the time shall not go</LINE>
-<LINE>dully by us. I will in the interim undertake one of</LINE>
-<LINE>Hercules' labours; which is, to bring Signior</LINE>
-<LINE>Benedick and the Lady Beatrice into a mountain of</LINE>
-<LINE>affection the one with the other. I would fain have</LINE>
-<LINE>it a match, and I doubt not but to fashion it, if</LINE>
-<LINE>you three will but minister such assistance as I</LINE>
-<LINE>shall give you direction.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>My lord, I am for you, though it cost me ten</LINE>
-<LINE>nights' watchings.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And I, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>And you too, gentle Hero?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>I will do any modest office, my lord, to help my</LINE>
-<LINE>cousin to a good husband.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>And Benedick is not the unhopefullest husband that</LINE>
-<LINE>I know. Thus far can I praise him; he is of a noble</LINE>
-<LINE>strain, of approved valour and confirmed honesty. I</LINE>
-<LINE>will teach you how to humour your cousin, that she</LINE>
-<LINE>shall fall in love with Benedick; and I, with your</LINE>
-<LINE>two helps, will so practise on Benedick that, in</LINE>
-<LINE>despite of his quick wit and his queasy stomach, he</LINE>
-<LINE>shall fall in love with Beatrice. If we can do this,</LINE>
-<LINE>Cupid is no longer an archer: his glory shall be</LINE>
-<LINE>ours, for we are the only love-gods. Go in with me,</LINE>
-<LINE>and I will tell you my drift.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE II. The same.</TITLE>
-<STAGEDIR>Enter DON JOHN and BORACHIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>It is so; the Count Claudio shall marry the</LINE>
-<LINE>daughter of Leonato.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Yea, my lord; but I can cross it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Any bar, any cross, any impediment will be</LINE>
-<LINE>medicinable to me: I am sick in displeasure to him,</LINE>
-<LINE>and whatsoever comes athwart his affection ranges</LINE>
-<LINE>evenly with mine. How canst thou cross this marriage?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Not honestly, my lord; but so covertly that no</LINE>
-<LINE>dishonesty shall appear in me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Show me briefly how.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>I think I told your lordship a year since, how much</LINE>
-<LINE>I am in the favour of Margaret, the waiting</LINE>
-<LINE>gentlewoman to Hero.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I remember.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>I can, at any unseasonable instant of the night,</LINE>
-<LINE>appoint her to look out at her lady's chamber window.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>What life is in that, to be the death of this marriage?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>The poison of that lies in you to temper. Go you to</LINE>
-<LINE>the prince your brother; spare not to tell him that</LINE>
-<LINE>he hath wronged his honour in marrying the renowned</LINE>
-<LINE>Claudio--whose estimation do you mightily hold</LINE>
-<LINE>up--to a contaminated stale, such a one as Hero.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>What proof shall I make of that?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Proof enough to misuse the prince, to vex Claudio,</LINE>
-<LINE>to undo Hero and kill Leonato. Look you for any</LINE>
-<LINE>other issue?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Only to despite them, I will endeavour any thing.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Go, then; find me a meet hour to draw Don Pedro and</LINE>
-<LINE>the Count Claudio alone: tell them that you know</LINE>
-<LINE>that Hero loves me; intend a kind of zeal both to the</LINE>
-<LINE>prince and Claudio, as,--in love of your brother's</LINE>
-<LINE>honour, who hath made this match, and his friend's</LINE>
-<LINE>reputation, who is thus like to be cozened with the</LINE>
-<LINE>semblance of a maid,--that you have discovered</LINE>
-<LINE>thus. They will scarcely believe this without trial:</LINE>
-<LINE>offer them instances; which shall bear no less</LINE>
-<LINE>likelihood than to see me at her chamber-window,</LINE>
-<LINE>hear me call Margaret Hero, hear Margaret term me</LINE>
-<LINE>Claudio; and bring them to see this the very night</LINE>
-<LINE>before the intended wedding,--for in the meantime I</LINE>
-<LINE>will so fashion the matter that Hero shall be</LINE>
-<LINE>absent,--and there shall appear such seeming truth</LINE>
-<LINE>of Hero's disloyalty that jealousy shall be called</LINE>
-<LINE>assurance and all the preparation overthrown.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Grow this to what adverse issue it can, I will put</LINE>
-<LINE>it in practise. Be cunning in the working this, and</LINE>
-<LINE>thy fee is a thousand ducats.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Be you constant in the accusation, and my cunning</LINE>
-<LINE>shall not shame me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I will presently go learn their day of marriage.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE III. LEONATO'S orchard.</TITLE>
-<STAGEDIR>Enter BENEDICK</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Boy!</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter Boy</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>Boy</SPEAKER>
-<LINE>Signior?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>In my chamber-window lies a book: bring it hither</LINE>
-<LINE>to me in the orchard.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Boy</SPEAKER>
-<LINE>I am here already, sir.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I know that; but I would have thee hence, and here again.</LINE>
-<STAGEDIR>Exit Boy</STAGEDIR>
-<LINE>I do much wonder that one man, seeing how much</LINE>
-<LINE>another man is a fool when he dedicates his</LINE>
-<LINE>behaviors to love, will, after he hath laughed at</LINE>
-<LINE>such shallow follies in others, become the argument</LINE>
-<LINE>of his own scorn by failing in love: and such a man</LINE>
-<LINE>is Claudio. I have known when there was no music</LINE>
-<LINE>with him but the drum and the fife; and now had he</LINE>
-<LINE>rather hear the tabour and the pipe: I have known</LINE>
-<LINE>when he would have walked ten mile a-foot to see a</LINE>
-<LINE>good armour; and now will he lie ten nights awake,</LINE>
-<LINE>carving the fashion of a new doublet. He was wont to</LINE>
-<LINE>speak plain and to the purpose, like an honest man</LINE>
-<LINE>and a soldier; and now is he turned orthography; his</LINE>
-<LINE>words are a very fantastical banquet, just so many</LINE>
-<LINE>strange dishes. May I be so converted and see with</LINE>
-<LINE>these eyes? I cannot tell; I think not: I will not</LINE>
-<LINE>be sworn, but love may transform me to an oyster; but</LINE>
-<LINE>I'll take my oath on it, till he have made an oyster</LINE>
-<LINE>of me, he shall never make me such a fool. One woman</LINE>
-<LINE>is fair, yet I am well; another is wise, yet I am</LINE>
-<LINE>well; another virtuous, yet I am well; but till all</LINE>
-<LINE>graces be in one woman, one woman shall not come in</LINE>
-<LINE>my grace. Rich she shall be, that's certain; wise,</LINE>
-<LINE>or I'll none; virtuous, or I'll never cheapen her;</LINE>
-<LINE>fair, or I'll never look on her; mild, or come not</LINE>
-<LINE>near me; noble, or not I for an angel; of good</LINE>
-<LINE>discourse, an excellent musician, and her hair shall</LINE>
-<LINE>be of what colour it please God. Ha! the prince and</LINE>
-<LINE>Monsieur Love! I will hide me in the arbour.</LINE>
-</SPEECH>
-
-<STAGEDIR>Withdraws</STAGEDIR>
-<STAGEDIR>Enter DON PEDRO, CLAUDIO, and LEONATO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Come, shall we hear this music?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Yea, my good lord. How still the evening is,</LINE>
-<LINE>As hush'd on purpose to grace harmony!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>See you where Benedick hath hid himself?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>O, very well, my lord: the music ended,</LINE>
-<LINE>We'll fit the kid-fox with a pennyworth.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter BALTHASAR with Music</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Come, Balthasar, we'll hear that song again.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>O, good my lord, tax not so bad a voice</LINE>
-<LINE>To slander music any more than once.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>It is the witness still of excellency</LINE>
-<LINE>To put a strange face on his own perfection.</LINE>
-<LINE>I pray thee, sing, and let me woo no more.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>Because you talk of wooing, I will sing;</LINE>
-<LINE>Since many a wooer doth commence his suit</LINE>
-<LINE>To her he thinks not worthy, yet he wooes,</LINE>
-<LINE>Yet will he swear he loves.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Now, pray thee, come;</LINE>
-<LINE>Or, if thou wilt hold longer argument,</LINE>
-<LINE>Do it in notes.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>Note this before my notes;</LINE>
-<LINE>There's not a note of mine that's worth the noting.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Why, these are very crotchets that he speaks;</LINE>
-<LINE>Note, notes, forsooth, and nothing.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Air</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Now, divine air! now is his soul ravished! Is it</LINE>
-<LINE>not strange that sheeps' guts should hale souls out</LINE>
-<LINE>of men's bodies? Well, a horn for my money, when</LINE>
-<LINE>all's done.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>The Song</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>Sigh no more, ladies, sigh no more,</LINE>
-<LINE>Men were deceivers ever,</LINE>
-<LINE>One foot in sea and one on shore,</LINE>
-<LINE>To one thing constant never:</LINE>
-<LINE>Then sigh not so, but let them go,</LINE>
-<LINE>And be you blithe and bonny,</LINE>
-<LINE>Converting all your sounds of woe</LINE>
-<LINE>Into Hey nonny, nonny.</LINE>
-<LINE>Sing no more ditties, sing no moe,</LINE>
-<LINE>Of dumps so dull and heavy;</LINE>
-<LINE>The fraud of men was ever so,</LINE>
-<LINE>Since summer first was leafy:</LINE>
-<LINE>Then sigh not so, &amp;c.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>By my troth, a good song.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>And an ill singer, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Ha, no, no, faith; thou singest well enough for a shift.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>An he had been a dog that should have howled thus,</LINE>
-<LINE>they would have hanged him: and I pray God his bad</LINE>
-<LINE>voice bode no mischief. I had as lief have heard the</LINE>
-<LINE>night-raven, come what plague could have come after</LINE>
-<LINE>it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Yea, marry, dost thou hear, Balthasar? I pray thee,</LINE>
-<LINE>get us some excellent music; for to-morrow night we</LINE>
-<LINE>would have it at the Lady Hero's chamber-window.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BALTHASAR</SPEAKER>
-<LINE>The best I can, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Do so: farewell.</LINE>
-<STAGEDIR>Exit BALTHASAR</STAGEDIR>
-<LINE>Come hither, Leonato. What was it you told me of</LINE>
-<LINE>to-day, that your niece Beatrice was in love with</LINE>
-<LINE>Signior Benedick?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>O, ay: stalk on. stalk on; the fowl sits. I did</LINE>
-<LINE>never think that lady would have loved any man.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>No, nor I neither; but most wonderful that she</LINE>
-<LINE>should so dote on Signior Benedick, whom she hath in</LINE>
-<LINE>all outward behaviors seemed ever to abhor.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Is't possible? Sits the wind in that corner?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>By my troth, my lord, I cannot tell what to think</LINE>
-<LINE>of it but that she loves him with an enraged</LINE>
-<LINE>affection: it is past the infinite of thought.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>May be she doth but counterfeit.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Faith, like enough.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>O God, counterfeit! There was never counterfeit of</LINE>
-<LINE>passion came so near the life of passion as she</LINE>
-<LINE>discovers it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Why, what effects of passion shows she?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Bait the hook well; this fish will bite.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>What effects, my lord? She will sit you, you heard</LINE>
-<LINE>my daughter tell you how.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>She did, indeed.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>How, how, pray you? You amaze me: I would have I</LINE>
-<LINE>thought her spirit had been invincible against all</LINE>
-<LINE>assaults of affection.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I would have sworn it had, my lord; especially</LINE>
-<LINE>against Benedick.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I should think this a gull, but that the</LINE>
-<LINE>white-bearded fellow speaks it: knavery cannot,</LINE>
-<LINE>sure, hide himself in such reverence.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>He hath ta'en the infection: hold it up.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Hath she made her affection known to Benedick?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>No; and swears she never will: that's her torment.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>'Tis true, indeed; so your daughter says: 'Shall</LINE>
-<LINE>I,' says she, 'that have so oft encountered him</LINE>
-<LINE>with scorn, write to him that I love him?'</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>This says she now when she is beginning to write to</LINE>
-<LINE>him; for she'll be up twenty times a night, and</LINE>
-<LINE>there will she sit in her smock till she have writ a</LINE>
-<LINE>sheet of paper: my daughter tells us all.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Now you talk of a sheet of paper, I remember a</LINE>
-<LINE>pretty jest your daughter told us of.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>O, when she had writ it and was reading it over, she</LINE>
-<LINE>found Benedick and Beatrice between the sheet?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>That.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>O, she tore the letter into a thousand halfpence;</LINE>
-<LINE>railed at herself, that she should be so immodest</LINE>
-<LINE>to write to one that she knew would flout her; 'I</LINE>
-<LINE>measure him,' says she, 'by my own spirit; for I</LINE>
-<LINE>should flout him, if he writ to me; yea, though I</LINE>
-<LINE>love him, I should.'</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Then down upon her knees she falls, weeps, sobs,</LINE>
-<LINE>beats her heart, tears her hair, prays, curses; 'O</LINE>
-<LINE>sweet Benedick! God give me patience!'</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>She doth indeed; my daughter says so: and the</LINE>
-<LINE>ecstasy hath so much overborne her that my daughter</LINE>
-<LINE>is sometime afeared she will do a desperate outrage</LINE>
-<LINE>to herself: it is very true.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>It were good that Benedick knew of it by some</LINE>
-<LINE>other, if she will not discover it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>To what end? He would make but a sport of it and</LINE>
-<LINE>torment the poor lady worse.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>An he should, it were an alms to hang him. She's an</LINE>
-<LINE>excellent sweet lady; and, out of all suspicion,</LINE>
-<LINE>she is virtuous.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And she is exceeding wise.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>In every thing but in loving Benedick.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>O, my lord, wisdom and blood combating in so tender</LINE>
-<LINE>a body, we have ten proofs to one that blood hath</LINE>
-<LINE>the victory. I am sorry for her, as I have just</LINE>
-<LINE>cause, being her uncle and her guardian.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>I would she had bestowed this dotage on me: I would</LINE>
-<LINE>have daffed all other respects and made her half</LINE>
-<LINE>myself. I pray you, tell Benedick of it, and hear</LINE>
-<LINE>what a' will say.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Were it good, think you?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Hero thinks surely she will die; for she says she</LINE>
-<LINE>will die, if he love her not, and she will die, ere</LINE>
-<LINE>she make her love known, and she will die, if he woo</LINE>
-<LINE>her, rather than she will bate one breath of her</LINE>
-<LINE>accustomed crossness.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>She doth well: if she should make tender of her</LINE>
-<LINE>love, 'tis very possible he'll scorn it; for the</LINE>
-<LINE>man, as you know all, hath a contemptible spirit.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>He is a very proper man.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>He hath indeed a good outward happiness.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Before God! and, in my mind, very wise.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>He doth indeed show some sparks that are like wit.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And I take him to be valiant.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>As Hector, I assure you: and in the managing of</LINE>
-<LINE>quarrels you may say he is wise; for either he</LINE>
-<LINE>avoids them with great discretion, or undertakes</LINE>
-<LINE>them with a most Christian-like fear.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>If he do fear God, a' must necessarily keep peace:</LINE>
-<LINE>if he break the peace, he ought to enter into a</LINE>
-<LINE>quarrel with fear and trembling.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>And so will he do; for the man doth fear God,</LINE>
-<LINE>howsoever it seems not in him by some large jests</LINE>
-<LINE>he will make. Well I am sorry for your niece. Shall</LINE>
-<LINE>we go seek Benedick, and tell him of her love?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Never tell him, my lord: let her wear it out with</LINE>
-<LINE>good counsel.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Nay, that's impossible: she may wear her heart out first.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Well, we will hear further of it by your daughter:</LINE>
-<LINE>let it cool the while. I love Benedick well; and I</LINE>
-<LINE>could wish he would modestly examine himself, to see</LINE>
-<LINE>how much he is unworthy so good a lady.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>My lord, will you walk? dinner is ready.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>If he do not dote on her upon this, I will never</LINE>
-<LINE>trust my expectation.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Let there be the same net spread for her; and that</LINE>
-<LINE>must your daughter and her gentlewomen carry. The</LINE>
-<LINE>sport will be, when they hold one an opinion of</LINE>
-<LINE>another's dotage, and no such matter: that's the</LINE>
-<LINE>scene that I would see, which will be merely a</LINE>
-<LINE>dumb-show. Let us send her to call him in to dinner.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt DON PEDRO, CLAUDIO, and LEONATO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE><STAGEDIR>Coming forward</STAGEDIR> This can be no trick: the</LINE>
-<LINE>conference was sadly borne. They have the truth of</LINE>
-<LINE>this from Hero. They seem to pity the lady: it</LINE>
-<LINE>seems her affections have their full bent. Love me!</LINE>
-<LINE>why, it must be requited. I hear how I am censured:</LINE>
-<LINE>they say I will bear myself proudly, if I perceive</LINE>
-<LINE>the love come from her; they say too that she will</LINE>
-<LINE>rather die than give any sign of affection. I did</LINE>
-<LINE>never think to marry: I must not seem proud: happy</LINE>
-<LINE>are they that hear their detractions and can put</LINE>
-<LINE>them to mending. They say the lady is fair; 'tis a</LINE>
-<LINE>truth, I can bear them witness; and virtuous; 'tis</LINE>
-<LINE>so, I cannot reprove it; and wise, but for loving</LINE>
-<LINE>me; by my troth, it is no addition to her wit, nor</LINE>
-<LINE>no great argument of her folly, for I will be</LINE>
-<LINE>horribly in love with her. I may chance have some</LINE>
-<LINE>odd quirks and remnants of wit broken on me,</LINE>
-<LINE>because I have railed so long against marriage: but</LINE>
-<LINE>doth not the appetite alter? a man loves the meat</LINE>
-<LINE>in his youth that he cannot endure in his age.</LINE>
-<LINE>Shall quips and sentences and these paper bullets of</LINE>
-<LINE>the brain awe a man from the career of his humour?</LINE>
-<LINE>No, the world must be peopled. When I said I would</LINE>
-<LINE>die a bachelor, I did not think I should live till I</LINE>
-<LINE>were married. Here comes Beatrice. By this day!</LINE>
-<LINE>she's a fair lady: I do spy some marks of love in</LINE>
-<LINE>her.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter BEATRICE</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Against my will I am sent to bid you come in to dinner.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Fair Beatrice, I thank you for your pains.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I took no more pains for those thanks than you take</LINE>
-<LINE>pains to thank me: if it had been painful, I would</LINE>
-<LINE>not have come.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>You take pleasure then in the message?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Yea, just so much as you may take upon a knife's</LINE>
-<LINE>point and choke a daw withal. You have no stomach,</LINE>
-<LINE>signior: fare you well.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Ha! 'Against my will I am sent to bid you come in</LINE>
-<LINE>to dinner;' there's a double meaning in that 'I took</LINE>
-<LINE>no more pains for those thanks than you took pains</LINE>
-<LINE>to thank me.' that's as much as to say, Any pains</LINE>
-<LINE>that I take for you is as easy as thanks. If I do</LINE>
-<LINE>not take pity of her, I am a villain; if I do not</LINE>
-<LINE>love her, I am a Jew. I will go get her picture.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-</SCENE>
-
-</ACT>
-
-<ACT><TITLE>ACT III</TITLE>
-
-<SCENE><TITLE>SCENE I. LEONATO'S garden.</TITLE>
-<STAGEDIR>Enter HERO, MARGARET, and URSULA</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Good Margaret, run thee to the parlor;</LINE>
-<LINE>There shalt thou find my cousin Beatrice</LINE>
-<LINE>Proposing with the prince and Claudio:</LINE>
-<LINE>Whisper her ear and tell her, I and Ursula</LINE>
-<LINE>Walk in the orchard and our whole discourse</LINE>
-<LINE>Is all of her; say that thou overheard'st us;</LINE>
-<LINE>And bid her steal into the pleached bower,</LINE>
-<LINE>Where honeysuckles, ripen'd by the sun,</LINE>
-<LINE>Forbid the sun to enter, like favourites,</LINE>
-<LINE>Made proud by princes, that advance their pride</LINE>
-<LINE>Against that power that bred it: there will she hide her,</LINE>
-<LINE>To listen our purpose. This is thy office;</LINE>
-<LINE>Bear thee well in it and leave us alone.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>I'll make her come, I warrant you, presently.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Now, Ursula, when Beatrice doth come,</LINE>
-<LINE>As we do trace this alley up and down,</LINE>
-<LINE>Our talk must only be of Benedick.</LINE>
-<LINE>When I do name him, let it be thy part</LINE>
-<LINE>To praise him more than ever man did merit:</LINE>
-<LINE>My talk to thee must be how Benedick</LINE>
-<LINE>Is sick in love with Beatrice. Of this matter</LINE>
-<LINE>Is little Cupid's crafty arrow made,</LINE>
-<LINE>That only wounds by hearsay.</LINE>
-<STAGEDIR>Enter BEATRICE, behind</STAGEDIR>
-<LINE>Now begin;</LINE>
-<LINE>For look where Beatrice, like a lapwing, runs</LINE>
-<LINE>Close by the ground, to hear our conference.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>The pleasant'st angling is to see the fish</LINE>
-<LINE>Cut with her golden oars the silver stream,</LINE>
-<LINE>And greedily devour the treacherous bait:</LINE>
-<LINE>So angle we for Beatrice; who even now</LINE>
-<LINE>Is couched in the woodbine coverture.</LINE>
-<LINE>Fear you not my part of the dialogue.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Then go we near her, that her ear lose nothing</LINE>
-<LINE>Of the false sweet bait that we lay for it.</LINE>
-<STAGEDIR>Approaching the bower</STAGEDIR>
-<LINE>No, truly, Ursula, she is too disdainful;</LINE>
-<LINE>I know her spirits are as coy and wild</LINE>
-<LINE>As haggerds of the rock.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>But are you sure</LINE>
-<LINE>That Benedick loves Beatrice so entirely?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>So says the prince and my new-trothed lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>And did they bid you tell her of it, madam?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>They did entreat me to acquaint her of it;</LINE>
-<LINE>But I persuaded them, if they loved Benedick,</LINE>
-<LINE>To wish him wrestle with affection,</LINE>
-<LINE>And never to let Beatrice know of it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>Why did you so? Doth not the gentleman</LINE>
-<LINE>Deserve as full as fortunate a bed</LINE>
-<LINE>As ever Beatrice shall couch upon?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>O god of love! I know he doth deserve</LINE>
-<LINE>As much as may be yielded to a man:</LINE>
-<LINE>But Nature never framed a woman's heart</LINE>
-<LINE>Of prouder stuff than that of Beatrice;</LINE>
-<LINE>Disdain and scorn ride sparkling in her eyes,</LINE>
-<LINE>Misprising what they look on, and her wit</LINE>
-<LINE>Values itself so highly that to her</LINE>
-<LINE>All matter else seems weak: she cannot love,</LINE>
-<LINE>Nor take no shape nor project of affection,</LINE>
-<LINE>She is so self-endeared.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>Sure, I think so;</LINE>
-<LINE>And therefore certainly it were not good</LINE>
-<LINE>She knew his love, lest she make sport at it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Why, you speak truth. I never yet saw man,</LINE>
-<LINE>How wise, how noble, young, how rarely featured,</LINE>
-<LINE>But she would spell him backward: if fair-faced,</LINE>
-<LINE>She would swear the gentleman should be her sister;</LINE>
-<LINE>If black, why, Nature, drawing of an antique,</LINE>
-<LINE>Made a foul blot; if tall, a lance ill-headed;</LINE>
-<LINE>If low, an agate very vilely cut;</LINE>
-<LINE>If speaking, why, a vane blown with all winds;</LINE>
-<LINE>If silent, why, a block moved with none.</LINE>
-<LINE>So turns she every man the wrong side out</LINE>
-<LINE>And never gives to truth and virtue that</LINE>
-<LINE>Which simpleness and merit purchaseth.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>Sure, sure, such carping is not commendable.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>No, not to be so odd and from all fashions</LINE>
-<LINE>As Beatrice is, cannot be commendable:</LINE>
-<LINE>But who dare tell her so? If I should speak,</LINE>
-<LINE>She would mock me into air; O, she would laugh me</LINE>
-<LINE>Out of myself, press me to death with wit.</LINE>
-<LINE>Therefore let Benedick, like cover'd fire,</LINE>
-<LINE>Consume away in sighs, waste inwardly:</LINE>
-<LINE>It were a better death than die with mocks,</LINE>
-<LINE>Which is as bad as die with tickling.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>Yet tell her of it: hear what she will say.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>No; rather I will go to Benedick</LINE>
-<LINE>And counsel him to fight against his passion.</LINE>
-<LINE>And, truly, I'll devise some honest slanders</LINE>
-<LINE>To stain my cousin with: one doth not know</LINE>
-<LINE>How much an ill word may empoison liking.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>O, do not do your cousin such a wrong.</LINE>
-<LINE>She cannot be so much without true judgment--</LINE>
-<LINE>Having so swift and excellent a wit</LINE>
-<LINE>As she is prized to have--as to refuse</LINE>
-<LINE>So rare a gentleman as Signior Benedick.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>He is the only man of Italy.</LINE>
-<LINE>Always excepted my dear Claudio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>I pray you, be not angry with me, madam,</LINE>
-<LINE>Speaking my fancy: Signior Benedick,</LINE>
-<LINE>For shape, for bearing, argument and valour,</LINE>
-<LINE>Goes foremost in report through Italy.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Indeed, he hath an excellent good name.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>His excellence did earn it, ere he had it.</LINE>
-<LINE>When are you married, madam?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Why, every day, to-morrow. Come, go in:</LINE>
-<LINE>I'll show thee some attires, and have thy counsel</LINE>
-<LINE>Which is the best to furnish me to-morrow.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>She's limed, I warrant you: we have caught her, madam.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>If it proves so, then loving goes by haps:</LINE>
-<LINE>Some Cupid kills with arrows, some with traps.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt HERO and URSULA</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE><STAGEDIR>Coming forward</STAGEDIR></LINE>
-<LINE>What fire is in mine ears? Can this be true?</LINE>
-<LINE>Stand I condemn'd for pride and scorn so much?</LINE>
-<LINE>Contempt, farewell! and maiden pride, adieu!</LINE>
-<LINE>No glory lives behind the back of such.</LINE>
-<LINE>And, Benedick, love on; I will requite thee,</LINE>
-<LINE>Taming my wild heart to thy loving hand:</LINE>
-<LINE>If thou dost love, my kindness shall incite thee</LINE>
-<LINE>To bind our loves up in a holy band;</LINE>
-<LINE>For others say thou dost deserve, and I</LINE>
-<LINE>Believe it better than reportingly.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE II. A room in LEONATO'S house</TITLE>
-<STAGEDIR>Enter DON PEDRO, CLAUDIO, BENEDICK, and LEONATO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>I do but stay till your marriage be consummate, and</LINE>
-<LINE>then go I toward Arragon.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I'll bring you thither, my lord, if you'll</LINE>
-<LINE>vouchsafe me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Nay, that would be as great a soil in the new gloss</LINE>
-<LINE>of your marriage as to show a child his new coat</LINE>
-<LINE>and forbid him to wear it. I will only be bold</LINE>
-<LINE>with Benedick for his company; for, from the crown</LINE>
-<LINE>of his head to the sole of his foot, he is all</LINE>
-<LINE>mirth: he hath twice or thrice cut Cupid's</LINE>
-<LINE>bow-string and the little hangman dare not shoot at</LINE>
-<LINE>him; he hath a heart as sound as a bell and his</LINE>
-<LINE>tongue is the clapper, for what his heart thinks his</LINE>
-<LINE>tongue speaks.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Gallants, I am not as I have been.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>So say I methinks you are sadder.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I hope he be in love.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Hang him, truant! there's no true drop of blood in</LINE>
-<LINE>him, to be truly touched with love: if he be sad,</LINE>
-<LINE>he wants money.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I have the toothache.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Draw it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Hang it!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>You must hang it first, and draw it afterwards.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>What! sigh for the toothache?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Where is but a humour or a worm.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Well, every one can master a grief but he that has</LINE>
-<LINE>it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Yet say I, he is in love.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>There is no appearance of fancy in him, unless it be</LINE>
-<LINE>a fancy that he hath to strange disguises; as, to be</LINE>
-<LINE>a Dutchman today, a Frenchman to-morrow, or in the</LINE>
-<LINE>shape of two countries at once, as, a German from</LINE>
-<LINE>the waist downward, all slops, and a Spaniard from</LINE>
-<LINE>the hip upward, no doublet. Unless he have a fancy</LINE>
-<LINE>to this foolery, as it appears he hath, he is no</LINE>
-<LINE>fool for fancy, as you would have it appear he is.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>If he be not in love with some woman, there is no</LINE>
-<LINE>believing old signs: a' brushes his hat o'</LINE>
-<LINE>mornings; what should that bode?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Hath any man seen him at the barber's?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>No, but the barber's man hath been seen with him,</LINE>
-<LINE>and the old ornament of his cheek hath already</LINE>
-<LINE>stuffed tennis-balls.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Indeed, he looks younger than he did, by the loss of a beard.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Nay, a' rubs himself with civet: can you smell him</LINE>
-<LINE>out by that?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>That's as much as to say, the sweet youth's in love.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>The greatest note of it is his melancholy.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And when was he wont to wash his face?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Yea, or to paint himself? for the which, I hear</LINE>
-<LINE>what they say of him.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Nay, but his jesting spirit; which is now crept into</LINE>
-<LINE>a lute-string and now governed by stops.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Indeed, that tells a heavy tale for him: conclude,</LINE>
-<LINE>conclude he is in love.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Nay, but I know who loves him.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>That would I know too: I warrant, one that knows him not.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Yes, and his ill conditions; and, in despite of</LINE>
-<LINE>all, dies for him.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>She shall be buried with her face upwards.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Yet is this no charm for the toothache. Old</LINE>
-<LINE>signior, walk aside with me: I have studied eight</LINE>
-<LINE>or nine wise words to speak to you, which these</LINE>
-<LINE>hobby-horses must not hear.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt BENEDICK and LEONATO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>For my life, to break with him about Beatrice.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>'Tis even so. Hero and Margaret have by this</LINE>
-<LINE>played their parts with Beatrice; and then the two</LINE>
-<LINE>bears will not bite one another when they meet.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter DON JOHN</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>My lord and brother, God save you!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Good den, brother.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>If your leisure served, I would speak with you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>In private?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>If it please you: yet Count Claudio may hear; for</LINE>
-<LINE>what I would speak of concerns him.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>What's the matter?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE><STAGEDIR>To CLAUDIO</STAGEDIR> Means your lordship to be married</LINE>
-<LINE>to-morrow?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>You know he does.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I know not that, when he knows what I know.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>If there be any impediment, I pray you discover it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>You may think I love you not: let that appear</LINE>
-<LINE>hereafter, and aim better at me by that I now will</LINE>
-<LINE>manifest. For my brother, I think he holds you</LINE>
-<LINE>well, and in dearness of heart hath holp to effect</LINE>
-<LINE>your ensuing marriage;--surely suit ill spent and</LINE>
-<LINE>labour ill bestowed.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Why, what's the matter?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I came hither to tell you; and, circumstances</LINE>
-<LINE>shortened, for she has been too long a talking of,</LINE>
-<LINE>the lady is disloyal.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Who, Hero?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Even she; Leonato's Hero, your Hero, every man's Hero:</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Disloyal?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>The word is too good to paint out her wickedness; I</LINE>
-<LINE>could say she were worse: think you of a worse</LINE>
-<LINE>title, and I will fit her to it. Wonder not till</LINE>
-<LINE>further warrant: go but with me to-night, you shall</LINE>
-<LINE>see her chamber-window entered, even the night</LINE>
-<LINE>before her wedding-day: if you love her then,</LINE>
-<LINE>to-morrow wed her; but it would better fit your honour</LINE>
-<LINE>to change your mind.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>May this be so?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>I will not think it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>If you dare not trust that you see, confess not</LINE>
-<LINE>that you know: if you will follow me, I will show</LINE>
-<LINE>you enough; and when you have seen more and heard</LINE>
-<LINE>more, proceed accordingly.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>If I see any thing to-night why I should not marry</LINE>
-<LINE>her to-morrow in the congregation, where I should</LINE>
-<LINE>wed, there will I shame her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>And, as I wooed for thee to obtain her, I will join</LINE>
-<LINE>with thee to disgrace her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>I will disparage her no farther till you are my</LINE>
-<LINE>witnesses: bear it coldly but till midnight, and</LINE>
-<LINE>let the issue show itself.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>O day untowardly turned!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>O mischief strangely thwarting!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>O plague right well prevented! so will you say when</LINE>
-<LINE>you have seen the sequel.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE III. A street.</TITLE>
-<STAGEDIR>Enter DOGBERRY and VERGES with the Watch</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Are you good men and true?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Yea, or else it were pity but they should suffer</LINE>
-<LINE>salvation, body and soul.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Nay, that were a punishment too good for them, if</LINE>
-<LINE>they should have any allegiance in them, being</LINE>
-<LINE>chosen for the prince's watch.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Well, give them their charge, neighbour Dogberry.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>First, who think you the most desertless man to be</LINE>
-<LINE>constable?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>First Watchman</SPEAKER>
-<LINE>Hugh Otecake, sir, or George Seacole; for they can</LINE>
-<LINE>write and read.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Come hither, neighbour Seacole. God hath blessed</LINE>
-<LINE>you with a good name: to be a well-favoured man is</LINE>
-<LINE>the gift of fortune; but to write and read comes by nature.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Second Watchman</SPEAKER>
-<LINE>Both which, master constable,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>You have: I knew it would be your answer. Well,</LINE>
-<LINE>for your favour, sir, why, give God thanks, and make</LINE>
-<LINE>no boast of it; and for your writing and reading,</LINE>
-<LINE>let that appear when there is no need of such</LINE>
-<LINE>vanity. You are thought here to be the most</LINE>
-<LINE>senseless and fit man for the constable of the</LINE>
-<LINE>watch; therefore bear you the lantern. This is your</LINE>
-<LINE>charge: you shall comprehend all vagrom men; you are</LINE>
-<LINE>to bid any man stand, in the prince's name.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Second Watchman</SPEAKER>
-<LINE>How if a' will not stand?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Why, then, take no note of him, but let him go; and</LINE>
-<LINE>presently call the rest of the watch together and</LINE>
-<LINE>thank God you are rid of a knave.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>If he will not stand when he is bidden, he is none</LINE>
-<LINE>of the prince's subjects.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>True, and they are to meddle with none but the</LINE>
-<LINE>prince's subjects. You shall also make no noise in</LINE>
-<LINE>the streets; for, for the watch to babble and to</LINE>
-<LINE>talk is most tolerable and not to be endured.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE>We will rather sleep than talk: we know what</LINE>
-<LINE>belongs to a watch.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Why, you speak like an ancient and most quiet</LINE>
-<LINE>watchman; for I cannot see how sleeping should</LINE>
-<LINE>offend: only, have a care that your bills be not</LINE>
-<LINE>stolen. Well, you are to call at all the</LINE>
-<LINE>ale-houses, and bid those that are drunk get them to bed.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE>How if they will not?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Why, then, let them alone till they are sober: if</LINE>
-<LINE>they make you not then the better answer, you may</LINE>
-<LINE>say they are not the men you took them for.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE>Well, sir.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>If you meet a thief, you may suspect him, by virtue</LINE>
-<LINE>of your office, to be no true man; and, for such</LINE>
-<LINE>kind of men, the less you meddle or make with them,</LINE>
-<LINE>why the more is for your honesty.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE>If we know him to be a thief, shall we not lay</LINE>
-<LINE>hands on him?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Truly, by your office, you may; but I think they</LINE>
-<LINE>that touch pitch will be defiled: the most peaceable</LINE>
-<LINE>way for you, if you do take a thief, is to let him</LINE>
-<LINE>show himself what he is and steal out of your company.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>You have been always called a merciful man, partner.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Truly, I would not hang a dog by my will, much more</LINE>
-<LINE>a man who hath any honesty in him.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>If you hear a child cry in the night, you must call</LINE>
-<LINE>to the nurse and bid her still it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE>How if the nurse be asleep and will not hear us?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Why, then, depart in peace, and let the child wake</LINE>
-<LINE>her with crying; for the ewe that will not hear her</LINE>
-<LINE>lamb when it baes will never answer a calf when he bleats.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>'Tis very true.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>This is the end of the charge:--you, constable, are</LINE>
-<LINE>to present the prince's own person: if you meet the</LINE>
-<LINE>prince in the night, you may stay him.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Nay, by'r our lady, that I think a' cannot.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Five shillings to one on't, with any man that knows</LINE>
-<LINE>the statutes, he may stay him: marry, not without</LINE>
-<LINE>the prince be willing; for, indeed, the watch ought</LINE>
-<LINE>to offend no man; and it is an offence to stay a</LINE>
-<LINE>man against his will.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>By'r lady, I think it be so.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Ha, ha, ha! Well, masters, good night: an there be</LINE>
-<LINE>any matter of weight chances, call up me: keep your</LINE>
-<LINE>fellows' counsels and your own; and good night.</LINE>
-<LINE>Come, neighbour.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE>Well, masters, we hear our charge: let us go sit here</LINE>
-<LINE>upon the church-bench till two, and then all to bed.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>One word more, honest neighbours. I pray you watch</LINE>
-<LINE>about Signior Leonato's door; for the wedding being</LINE>
-<LINE>there to-morrow, there is a great coil to-night.</LINE>
-<LINE>Adieu: be vigitant, I beseech you.</LINE>
-</SPEECH>
-
-<STAGEDIR>Exeunt DOGBERRY and VERGES</STAGEDIR>
-<STAGEDIR>Enter BORACHIO and CONRADE</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>What Conrade!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE><STAGEDIR>Aside</STAGEDIR> Peace! stir not.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Conrade, I say!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Here, man; I am at thy elbow.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Mass, and my elbow itched; I thought there would a</LINE>
-<LINE>scab follow.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>I will owe thee an answer for that: and now forward</LINE>
-<LINE>with thy tale.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Stand thee close, then, under this pent-house, for</LINE>
-<LINE>it drizzles rain; and I will, like a true drunkard,</LINE>
-<LINE>utter all to thee.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE><STAGEDIR>Aside</STAGEDIR> Some treason, masters: yet stand close.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Therefore know I have earned of Don John a thousand ducats.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Is it possible that any villany should be so dear?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Thou shouldst rather ask if it were possible any</LINE>
-<LINE>villany should be so rich; for when rich villains</LINE>
-<LINE>have need of poor ones, poor ones may make what</LINE>
-<LINE>price they will.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>I wonder at it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>That shows thou art unconfirmed. Thou knowest that</LINE>
-<LINE>the fashion of a doublet, or a hat, or a cloak, is</LINE>
-<LINE>nothing to a man.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Yes, it is apparel.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>I mean, the fashion.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Yes, the fashion is the fashion.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Tush! I may as well say the fool's the fool. But</LINE>
-<LINE>seest thou not what a deformed thief this fashion</LINE>
-<LINE>is?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE><STAGEDIR>Aside</STAGEDIR> I know that Deformed; a' has been a vile</LINE>
-<LINE>thief this seven year; a' goes up and down like a</LINE>
-<LINE>gentleman: I remember his name.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Didst thou not hear somebody?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>No; 'twas the vane on the house.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Seest thou not, I say, what a deformed thief this</LINE>
-<LINE>fashion is? how giddily a' turns about all the hot</LINE>
-<LINE>bloods between fourteen and five-and-thirty?</LINE>
-<LINE>sometimes fashioning them like Pharaoh's soldiers</LINE>
-<LINE>in the reeky painting, sometime like god Bel's</LINE>
-<LINE>priests in the old church-window, sometime like the</LINE>
-<LINE>shaven Hercules in the smirched worm-eaten tapestry,</LINE>
-<LINE>where his codpiece seems as massy as his club?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>All this I see; and I see that the fashion wears</LINE>
-<LINE>out more apparel than the man. But art not thou</LINE>
-<LINE>thyself giddy with the fashion too, that thou hast</LINE>
-<LINE>shifted out of thy tale into telling me of the fashion?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Not so, neither: but know that I have to-night</LINE>
-<LINE>wooed Margaret, the Lady Hero's gentlewoman, by the</LINE>
-<LINE>name of Hero: she leans me out at her mistress'</LINE>
-<LINE>chamber-window, bids me a thousand times good</LINE>
-<LINE>night,--I tell this tale vilely:--I should first</LINE>
-<LINE>tell thee how the prince, Claudio and my master,</LINE>
-<LINE>planted and placed and possessed by my master Don</LINE>
-<LINE>John, saw afar off in the orchard this amiable encounter.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>And thought they Margaret was Hero?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Two of them did, the prince and Claudio; but the</LINE>
-<LINE>devil my master knew she was Margaret; and partly</LINE>
-<LINE>by his oaths, which first possessed them, partly by</LINE>
-<LINE>the dark night, which did deceive them, but chiefly</LINE>
-<LINE>by my villany, which did confirm any slander that</LINE>
-<LINE>Don John had made, away went Claudio enraged; swore</LINE>
-<LINE>he would meet her, as he was appointed, next morning</LINE>
-<LINE>at the temple, and there, before the whole</LINE>
-<LINE>congregation, shame her with what he saw o'er night</LINE>
-<LINE>and send her home again without a husband.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>First Watchman</SPEAKER>
-<LINE>We charge you, in the prince's name, stand!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Second Watchman</SPEAKER>
-<LINE>Call up the right master constable. We have here</LINE>
-<LINE>recovered the most dangerous piece of lechery that</LINE>
-<LINE>ever was known in the commonwealth.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>First Watchman</SPEAKER>
-<LINE>And one Deformed is one of them: I know him; a'</LINE>
-<LINE>wears a lock.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Masters, masters,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Second Watchman</SPEAKER>
-<LINE>You'll be made bring Deformed forth, I warrant you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Masters,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>First Watchman</SPEAKER>
-<LINE>Never speak: we charge you let us obey you to go with us.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>We are like to prove a goodly commodity, being taken</LINE>
-<LINE>up of these men's bills.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>A commodity in question, I warrant you. Come, we'll obey you.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE IV. HERO's apartment.</TITLE>
-<STAGEDIR>Enter HERO, MARGARET, and URSULA</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Good Ursula, wake my cousin Beatrice, and desire</LINE>
-<LINE>her to rise.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>I will, lady.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>And bid her come hither.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>Well.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Troth, I think your other rabato were better.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>No, pray thee, good Meg, I'll wear this.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>By my troth, 's not so good; and I warrant your</LINE>
-<LINE>cousin will say so.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>My cousin's a fool, and thou art another: I'll wear</LINE>
-<LINE>none but this.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>I like the new tire within excellently, if the hair</LINE>
-<LINE>were a thought browner; and your gown's a most rare</LINE>
-<LINE>fashion, i' faith. I saw the Duchess of Milan's</LINE>
-<LINE>gown that they praise so.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>O, that exceeds, they say.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>By my troth, 's but a night-gown in respect of</LINE>
-<LINE>yours: cloth o' gold, and cuts, and laced with</LINE>
-<LINE>silver, set with pearls, down sleeves, side sleeves,</LINE>
-<LINE>and skirts, round underborne with a bluish tinsel:</LINE>
-<LINE>but for a fine, quaint, graceful and excellent</LINE>
-<LINE>fashion, yours is worth ten on 't.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>God give me joy to wear it! for my heart is</LINE>
-<LINE>exceeding heavy.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>'Twill be heavier soon by the weight of a man.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Fie upon thee! art not ashamed?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Of what, lady? of speaking honourably? Is not</LINE>
-<LINE>marriage honourable in a beggar? Is not your lord</LINE>
-<LINE>honourable without marriage? I think you would have</LINE>
-<LINE>me say, 'saving your reverence, a husband:' and bad</LINE>
-<LINE>thinking do not wrest true speaking, I'll offend</LINE>
-<LINE>nobody: is there any harm in 'the heavier for a</LINE>
-<LINE>husband'? None, I think, and it be the right husband</LINE>
-<LINE>and the right wife; otherwise 'tis light, and not</LINE>
-<LINE>heavy: ask my Lady Beatrice else; here she comes.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter BEATRICE</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Good morrow, coz.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Good morrow, sweet Hero.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Why how now? do you speak in the sick tune?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I am out of all other tune, methinks.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Clap's into 'Light o' love;' that goes without a</LINE>
-<LINE>burden: do you sing it, and I'll dance it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Ye light o' love, with your heels! then, if your</LINE>
-<LINE>husband have stables enough, you'll see he shall</LINE>
-<LINE>lack no barns.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>O illegitimate construction! I scorn that with my heels.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>'Tis almost five o'clock, cousin; tis time you were</LINE>
-<LINE>ready. By my troth, I am exceeding ill: heigh-ho!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>For a hawk, a horse, or a husband?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>For the letter that begins them all, H.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Well, and you be not turned Turk, there's no more</LINE>
-<LINE>sailing by the star.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>What means the fool, trow?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Nothing I; but God send every one their heart's desire!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>These gloves the count sent me; they are an</LINE>
-<LINE>excellent perfume.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I am stuffed, cousin; I cannot smell.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>A maid, and stuffed! there's goodly catching of cold.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>O, God help me! God help me! how long have you</LINE>
-<LINE>professed apprehension?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Even since you left it. Doth not my wit become me rarely?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>It is not seen enough, you should wear it in your</LINE>
-<LINE>cap. By my troth, I am sick.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Get you some of this distilled Carduus Benedictus,</LINE>
-<LINE>and lay it to your heart: it is the only thing for a qualm.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>There thou prickest her with a thistle.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Benedictus! why Benedictus? you have some moral in</LINE>
-<LINE>this Benedictus.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Moral! no, by my troth, I have no moral meaning; I</LINE>
-<LINE>meant, plain holy-thistle. You may think perchance</LINE>
-<LINE>that I think you are in love: nay, by'r lady, I am</LINE>
-<LINE>not such a fool to think what I list, nor I list</LINE>
-<LINE>not to think what I can, nor indeed I cannot think,</LINE>
-<LINE>if I would think my heart out of thinking, that you</LINE>
-<LINE>are in love or that you will be in love or that you</LINE>
-<LINE>can be in love. Yet Benedick was such another, and</LINE>
-<LINE>now is he become a man: he swore he would never</LINE>
-<LINE>marry, and yet now, in despite of his heart, he eats</LINE>
-<LINE>his meat without grudging: and how you may be</LINE>
-<LINE>converted I know not, but methinks you look with</LINE>
-<LINE>your eyes as other women do.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>What pace is this that thy tongue keeps?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Not a false gallop.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Re-enter URSULA</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>Madam, withdraw: the prince, the count, Signior</LINE>
-<LINE>Benedick, Don John, and all the gallants of the</LINE>
-<LINE>town, are come to fetch you to church.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Help to dress me, good coz, good Meg, good Ursula.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE V. Another room in LEONATO'S house.</TITLE>
-<STAGEDIR>Enter LEONATO, with DOGBERRY and VERGES</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>What would you with me, honest neighbour?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Marry, sir, I would have some confidence with you</LINE>
-<LINE>that decerns you nearly.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Brief, I pray you; for you see it is a busy time with me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Marry, this it is, sir.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Yes, in truth it is, sir.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>What is it, my good friends?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Goodman Verges, sir, speaks a little off the</LINE>
-<LINE>matter: an old man, sir, and his wits are not so</LINE>
-<LINE>blunt as, God help, I would desire they were; but,</LINE>
-<LINE>in faith, honest as the skin between his brows.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Yes, I thank God I am as honest as any man living</LINE>
-<LINE>that is an old man and no honester than I.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Comparisons are odorous: palabras, neighbour Verges.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Neighbours, you are tedious.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>It pleases your worship to say so, but we are the</LINE>
-<LINE>poor duke's officers; but truly, for mine own part,</LINE>
-<LINE>if I were as tedious as a king, I could find it in</LINE>
-<LINE>my heart to bestow it all of your worship.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>All thy tediousness on me, ah?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Yea, an 'twere a thousand pound more than 'tis; for</LINE>
-<LINE>I hear as good exclamation on your worship as of any</LINE>
-<LINE>man in the city; and though I be but a poor man, I</LINE>
-<LINE>am glad to hear it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>And so am I.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I would fain know what you have to say.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Marry, sir, our watch to-night, excepting your</LINE>
-<LINE>worship's presence, ha' ta'en a couple of as arrant</LINE>
-<LINE>knaves as any in Messina.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>A good old man, sir; he will be talking: as they</LINE>
-<LINE>say, when the age is in, the wit is out: God help</LINE>
-<LINE>us! it is a world to see. Well said, i' faith,</LINE>
-<LINE>neighbour Verges: well, God's a good man; an two men</LINE>
-<LINE>ride of a horse, one must ride behind. An honest</LINE>
-<LINE>soul, i' faith, sir; by my troth he is, as ever</LINE>
-<LINE>broke bread; but God is to be worshipped; all men</LINE>
-<LINE>are not alike; alas, good neighbour!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Indeed, neighbour, he comes too short of you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Gifts that God gives.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I must leave you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>One word, sir: our watch, sir, have indeed</LINE>
-<LINE>comprehended two aspicious persons, and we would</LINE>
-<LINE>have them this morning examined before your worship.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Take their examination yourself and bring it me: I</LINE>
-<LINE>am now in great haste, as it may appear unto you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>It shall be suffigance.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Drink some wine ere you go: fare you well.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter a Messenger</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>My lord, they stay for you to give your daughter to</LINE>
-<LINE>her husband.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I'll wait upon them: I am ready.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt LEONATO and Messenger</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Go, good partner, go, get you to Francis Seacole;</LINE>
-<LINE>bid him bring his pen and inkhorn to the gaol: we</LINE>
-<LINE>are now to examination these men.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>And we must do it wisely.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>We will spare for no wit, I warrant you; here's</LINE>
-<LINE>that shall drive some of them to a non-come: only</LINE>
-<LINE>get the learned writer to set down our</LINE>
-<LINE>excommunication and meet me at the gaol.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-</ACT>
-
-<ACT><TITLE>ACT IV</TITLE>
-
-<SCENE><TITLE>SCENE I. A church.</TITLE>
-<STAGEDIR>Enter DON PEDRO, DON JOHN, LEONATO, FRIAR FRANCIS,
-CLAUDIO, BENEDICK, HERO, BEATRICE, and Attendants</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Come, Friar Francis, be brief; only to the plain</LINE>
-<LINE>form of marriage, and you shall recount their</LINE>
-<LINE>particular duties afterwards.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>You come hither, my lord, to marry this lady.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>No.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>To be married to her: friar, you come to marry her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>Lady, you come hither to be married to this count.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>I do.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>If either of you know any inward impediment why you</LINE>
-<LINE>should not be conjoined, charge you, on your souls,</LINE>
-<LINE>to utter it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Know you any, Hero?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>None, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>Know you any, count?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I dare make his answer, none.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>O, what men dare do! what men may do! what men daily</LINE>
-<LINE>do, not knowing what they do!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>How now! interjections? Why, then, some be of</LINE>
-<LINE>laughing, as, ah, ha, he!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Stand thee by, friar. Father, by your leave:</LINE>
-<LINE>Will you with free and unconstrained soul</LINE>
-<LINE>Give me this maid, your daughter?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>As freely, son, as God did give her me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And what have I to give you back, whose worth</LINE>
-<LINE>May counterpoise this rich and precious gift?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Nothing, unless you render her again.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Sweet prince, you learn me noble thankfulness.</LINE>
-<LINE>There, Leonato, take her back again:</LINE>
-<LINE>Give not this rotten orange to your friend;</LINE>
-<LINE>She's but the sign and semblance of her honour.</LINE>
-<LINE>Behold how like a maid she blushes here!</LINE>
-<LINE>O, what authority and show of truth</LINE>
-<LINE>Can cunning sin cover itself withal!</LINE>
-<LINE>Comes not that blood as modest evidence</LINE>
-<LINE>To witness simple virtue? Would you not swear,</LINE>
-<LINE>All you that see her, that she were a maid,</LINE>
-<LINE>By these exterior shows? But she is none:</LINE>
-<LINE>She knows the heat of a luxurious bed;</LINE>
-<LINE>Her blush is guiltiness, not modesty.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>What do you mean, my lord?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Not to be married,</LINE>
-<LINE>Not to knit my soul to an approved wanton.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Dear my lord, if you, in your own proof,</LINE>
-<LINE>Have vanquish'd the resistance of her youth,</LINE>
-<LINE>And made defeat of her virginity,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I know what you would say: if I have known her,</LINE>
-<LINE>You will say she did embrace me as a husband,</LINE>
-<LINE>And so extenuate the 'forehand sin:</LINE>
-<LINE>No, Leonato,</LINE>
-<LINE>I never tempted her with word too large;</LINE>
-<LINE>But, as a brother to his sister, show'd</LINE>
-<LINE>Bashful sincerity and comely love.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>And seem'd I ever otherwise to you?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Out on thee! Seeming! I will write against it:</LINE>
-<LINE>You seem to me as Dian in her orb,</LINE>
-<LINE>As chaste as is the bud ere it be blown;</LINE>
-<LINE>But you are more intemperate in your blood</LINE>
-<LINE>Than Venus, or those pamper'd animals</LINE>
-<LINE>That rage in savage sensuality.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Is my lord well, that he doth speak so wide?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Sweet prince, why speak not you?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>What should I speak?</LINE>
-<LINE>I stand dishonour'd, that have gone about</LINE>
-<LINE>To link my dear friend to a common stale.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Are these things spoken, or do I but dream?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Sir, they are spoken, and these things are true.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>This looks not like a nuptial.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>True! O God!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Leonato, stand I here?</LINE>
-<LINE>Is this the prince? is this the prince's brother?</LINE>
-<LINE>Is this face Hero's? are our eyes our own?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>All this is so: but what of this, my lord?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Let me but move one question to your daughter;</LINE>
-<LINE>And, by that fatherly and kindly power</LINE>
-<LINE>That you have in her, bid her answer truly.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I charge thee do so, as thou art my child.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>O, God defend me! how am I beset!</LINE>
-<LINE>What kind of catechising call you this?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>To make you answer truly to your name.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Is it not Hero? Who can blot that name</LINE>
-<LINE>With any just reproach?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Marry, that can Hero;</LINE>
-<LINE>Hero itself can blot out Hero's virtue.</LINE>
-<LINE>What man was he talk'd with you yesternight</LINE>
-<LINE>Out at your window betwixt twelve and one?</LINE>
-<LINE>Now, if you are a maid, answer to this.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>I talk'd with no man at that hour, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Why, then are you no maiden. Leonato,</LINE>
-<LINE>I am sorry you must hear: upon mine honour,</LINE>
-<LINE>Myself, my brother and this grieved count</LINE>
-<LINE>Did see her, hear her, at that hour last night</LINE>
-<LINE>Talk with a ruffian at her chamber-window</LINE>
-<LINE>Who hath indeed, most like a liberal villain,</LINE>
-<LINE>Confess'd the vile encounters they have had</LINE>
-<LINE>A thousand times in secret.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Fie, fie! they are not to be named, my lord,</LINE>
-<LINE>Not to be spoke of;</LINE>
-<LINE>There is not chastity enough in language</LINE>
-<LINE>Without offence to utter them. Thus, pretty lady,</LINE>
-<LINE>I am sorry for thy much misgovernment.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>O Hero, what a Hero hadst thou been,</LINE>
-<LINE>If half thy outward graces had been placed</LINE>
-<LINE>About thy thoughts and counsels of thy heart!</LINE>
-<LINE>But fare thee well, most foul, most fair! farewell,</LINE>
-<LINE>Thou pure impiety and impious purity!</LINE>
-<LINE>For thee I'll lock up all the gates of love,</LINE>
-<LINE>And on my eyelids shall conjecture hang,</LINE>
-<LINE>To turn all beauty into thoughts of harm,</LINE>
-<LINE>And never shall it more be gracious.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Hath no man's dagger here a point for me?</LINE>
-</SPEECH>
-
-
-<STAGEDIR>HERO swoons</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Why, how now, cousin! wherefore sink you down?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON JOHN</SPEAKER>
-<LINE>Come, let us go. These things, come thus to light,</LINE>
-<LINE>Smother her spirits up.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt DON PEDRO, DON JOHN, and CLAUDIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>How doth the lady?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Dead, I think. Help, uncle!</LINE>
-<LINE>Hero! why, Hero! Uncle! Signior Benedick! Friar!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>O Fate! take not away thy heavy hand.</LINE>
-<LINE>Death is the fairest cover for her shame</LINE>
-<LINE>That may be wish'd for.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>How now, cousin Hero!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>Have comfort, lady.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Dost thou look up?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>Yea, wherefore should she not?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Wherefore! Why, doth not every earthly thing</LINE>
-<LINE>Cry shame upon her? Could she here deny</LINE>
-<LINE>The story that is printed in her blood?</LINE>
-<LINE>Do not live, Hero; do not ope thine eyes:</LINE>
-<LINE>For, did I think thou wouldst not quickly die,</LINE>
-<LINE>Thought I thy spirits were stronger than thy shames,</LINE>
-<LINE>Myself would, on the rearward of reproaches,</LINE>
-<LINE>Strike at thy life. Grieved I, I had but one?</LINE>
-<LINE>Chid I for that at frugal nature's frame?</LINE>
-<LINE>O, one too much by thee! Why had I one?</LINE>
-<LINE>Why ever wast thou lovely in my eyes?</LINE>
-<LINE>Why had I not with charitable hand</LINE>
-<LINE>Took up a beggar's issue at my gates,</LINE>
-<LINE>Who smirch'd thus and mired with infamy,</LINE>
-<LINE>I might have said 'No part of it is mine;</LINE>
-<LINE>This shame derives itself from unknown loins'?</LINE>
-<LINE>But mine and mine I loved and mine I praised</LINE>
-<LINE>And mine that I was proud on, mine so much</LINE>
-<LINE>That I myself was to myself not mine,</LINE>
-<LINE>Valuing of her,--why, she, O, she is fallen</LINE>
-<LINE>Into a pit of ink, that the wide sea</LINE>
-<LINE>Hath drops too few to wash her clean again</LINE>
-<LINE>And salt too little which may season give</LINE>
-<LINE>To her foul-tainted flesh!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Sir, sir, be patient.</LINE>
-<LINE>For my part, I am so attired in wonder,</LINE>
-<LINE>I know not what to say.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>O, on my soul, my cousin is belied!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Lady, were you her bedfellow last night?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>No, truly not; although, until last night,</LINE>
-<LINE>I have this twelvemonth been her bedfellow.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Confirm'd, confirm'd! O, that is stronger made</LINE>
-<LINE>Which was before barr'd up with ribs of iron!</LINE>
-<LINE>Would the two princes lie, and Claudio lie,</LINE>
-<LINE>Who loved her so, that, speaking of her foulness,</LINE>
-<LINE>Wash'd it with tears? Hence from her! let her die.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>Hear me a little; for I have only been</LINE>
-<LINE>Silent so long and given way unto</LINE>
-<LINE>This course of fortune</LINE>
-<LINE>By noting of the lady. I have mark'd</LINE>
-<LINE>A thousand blushing apparitions</LINE>
-<LINE>To start into her face, a thousand innocent shames</LINE>
-<LINE>In angel whiteness beat away those blushes;</LINE>
-<LINE>And in her eye there hath appear'd a fire,</LINE>
-<LINE>To burn the errors that these princes hold</LINE>
-<LINE>Against her maiden truth. Call me a fool;</LINE>
-<LINE>Trust not my reading nor my observations,</LINE>
-<LINE>Which with experimental seal doth warrant</LINE>
-<LINE>The tenor of my book; trust not my age,</LINE>
-<LINE>My reverence, calling, nor divinity,</LINE>
-<LINE>If this sweet lady lie not guiltless here</LINE>
-<LINE>Under some biting error.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Friar, it cannot be.</LINE>
-<LINE>Thou seest that all the grace that she hath left</LINE>
-<LINE>Is that she will not add to her damnation</LINE>
-<LINE>A sin of perjury; she not denies it:</LINE>
-<LINE>Why seek'st thou then to cover with excuse</LINE>
-<LINE>That which appears in proper nakedness?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>Lady, what man is he you are accused of?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>They know that do accuse me; I know none:</LINE>
-<LINE>If I know more of any man alive</LINE>
-<LINE>Than that which maiden modesty doth warrant,</LINE>
-<LINE>Let all my sins lack mercy! O my father,</LINE>
-<LINE>Prove you that any man with me conversed</LINE>
-<LINE>At hours unmeet, or that I yesternight</LINE>
-<LINE>Maintain'd the change of words with any creature,</LINE>
-<LINE>Refuse me, hate me, torture me to death!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>There is some strange misprision in the princes.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Two of them have the very bent of honour;</LINE>
-<LINE>And if their wisdoms be misled in this,</LINE>
-<LINE>The practise of it lives in John the bastard,</LINE>
-<LINE>Whose spirits toil in frame of villanies.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I know not. If they speak but truth of her,</LINE>
-<LINE>These hands shall tear her; if they wrong her honour,</LINE>
-<LINE>The proudest of them shall well hear of it.</LINE>
-<LINE>Time hath not yet so dried this blood of mine,</LINE>
-<LINE>Nor age so eat up my invention,</LINE>
-<LINE>Nor fortune made such havoc of my means,</LINE>
-<LINE>Nor my bad life reft me so much of friends,</LINE>
-<LINE>But they shall find, awaked in such a kind,</LINE>
-<LINE>Both strength of limb and policy of mind,</LINE>
-<LINE>Ability in means and choice of friends,</LINE>
-<LINE>To quit me of them throughly.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>Pause awhile,</LINE>
-<LINE>And let my counsel sway you in this case.</LINE>
-<LINE>Your daughter here the princes left for dead:</LINE>
-<LINE>Let her awhile be secretly kept in,</LINE>
-<LINE>And publish it that she is dead indeed;</LINE>
-<LINE>Maintain a mourning ostentation</LINE>
-<LINE>And on your family's old monument</LINE>
-<LINE>Hang mournful epitaphs and do all rites</LINE>
-<LINE>That appertain unto a burial.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>What shall become of this? what will this do?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>Marry, this well carried shall on her behalf</LINE>
-<LINE>Change slander to remorse; that is some good:</LINE>
-<LINE>But not for that dream I on this strange course,</LINE>
-<LINE>But on this travail look for greater birth.</LINE>
-<LINE>She dying, as it must so be maintain'd,</LINE>
-<LINE>Upon the instant that she was accused,</LINE>
-<LINE>Shall be lamented, pitied and excused</LINE>
-<LINE>Of every hearer: for it so falls out</LINE>
-<LINE>That what we have we prize not to the worth</LINE>
-<LINE>Whiles we enjoy it, but being lack'd and lost,</LINE>
-<LINE>Why, then we rack the value, then we find</LINE>
-<LINE>The virtue that possession would not show us</LINE>
-<LINE>Whiles it was ours. So will it fare with Claudio:</LINE>
-<LINE>When he shall hear she died upon his words,</LINE>
-<LINE>The idea of her life shall sweetly creep</LINE>
-<LINE>Into his study of imagination,</LINE>
-<LINE>And every lovely organ of her life</LINE>
-<LINE>Shall come apparell'd in more precious habit,</LINE>
-<LINE>More moving-delicate and full of life,</LINE>
-<LINE>Into the eye and prospect of his soul,</LINE>
-<LINE>Than when she lived indeed; then shall he mourn,</LINE>
-<LINE>If ever love had interest in his liver,</LINE>
-<LINE>And wish he had not so accused her,</LINE>
-<LINE>No, though he thought his accusation true.</LINE>
-<LINE>Let this be so, and doubt not but success</LINE>
-<LINE>Will fashion the event in better shape</LINE>
-<LINE>Than I can lay it down in likelihood.</LINE>
-<LINE>But if all aim but this be levell'd false,</LINE>
-<LINE>The supposition of the lady's death</LINE>
-<LINE>Will quench the wonder of her infamy:</LINE>
-<LINE>And if it sort not well, you may conceal her,</LINE>
-<LINE>As best befits her wounded reputation,</LINE>
-<LINE>In some reclusive and religious life,</LINE>
-<LINE>Out of all eyes, tongues, minds and injuries.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Signior Leonato, let the friar advise you:</LINE>
-<LINE>And though you know my inwardness and love</LINE>
-<LINE>Is very much unto the prince and Claudio,</LINE>
-<LINE>Yet, by mine honour, I will deal in this</LINE>
-<LINE>As secretly and justly as your soul</LINE>
-<LINE>Should with your body.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Being that I flow in grief,</LINE>
-<LINE>The smallest twine may lead me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>'Tis well consented: presently away;</LINE>
-<LINE>For to strange sores strangely they strain the cure.</LINE>
-<LINE>Come, lady, die to live: this wedding-day</LINE>
-<LINE>Perhaps is but prolong'd: have patience and endure.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt all but BENEDICK and BEATRICE</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Lady Beatrice, have you wept all this while?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Yea, and I will weep a while longer.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I will not desire that.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>You have no reason; I do it freely.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Surely I do believe your fair cousin is wronged.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Ah, how much might the man deserve of me that would right her!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Is there any way to show such friendship?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>A very even way, but no such friend.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>May a man do it?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>It is a man's office, but not yours.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I do love nothing in the world so well as you: is</LINE>
-<LINE>not that strange?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>As strange as the thing I know not. It were as</LINE>
-<LINE>possible for me to say I loved nothing so well as</LINE>
-<LINE>you: but believe me not; and yet I lie not; I</LINE>
-<LINE>confess nothing, nor I deny nothing. I am sorry for my cousin.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>By my sword, Beatrice, thou lovest me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Do not swear, and eat it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I will swear by it that you love me; and I will make</LINE>
-<LINE>him eat it that says I love not you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Will you not eat your word?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>With no sauce that can be devised to it. I protest</LINE>
-<LINE>I love thee.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Why, then, God forgive me!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>What offence, sweet Beatrice?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>You have stayed me in a happy hour: I was about to</LINE>
-<LINE>protest I loved you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>And do it with all thy heart.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I love you with so much of my heart that none is</LINE>
-<LINE>left to protest.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Come, bid me do any thing for thee.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Kill Claudio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Ha! not for the wide world.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>You kill me to deny it. Farewell.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Tarry, sweet Beatrice.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I am gone, though I am here: there is no love in</LINE>
-<LINE>you: nay, I pray you, let me go.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Beatrice,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>In faith, I will go.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>We'll be friends first.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>You dare easier be friends with me than fight with mine enemy.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Is Claudio thine enemy?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Is he not approved in the height a villain, that</LINE>
-<LINE>hath slandered, scorned, dishonoured my kinswoman? O</LINE>
-<LINE>that I were a man! What, bear her in hand until they</LINE>
-<LINE>come to take hands; and then, with public</LINE>
-<LINE>accusation, uncovered slander, unmitigated rancour,</LINE>
-<LINE>--O God, that I were a man! I would eat his heart</LINE>
-<LINE>in the market-place.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Hear me, Beatrice,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Talk with a man out at a window! A proper saying!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Nay, but, Beatrice,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Sweet Hero! She is wronged, she is slandered, she is undone.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Beat--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Princes and counties! Surely, a princely testimony,</LINE>
-<LINE>a goodly count, Count Comfect; a sweet gallant,</LINE>
-<LINE>surely! O that I were a man for his sake! or that I</LINE>
-<LINE>had any friend would be a man for my sake! But</LINE>
-<LINE>manhood is melted into courtesies, valour into</LINE>
-<LINE>compliment, and men are only turned into tongue, and</LINE>
-<LINE>trim ones too: he is now as valiant as Hercules</LINE>
-<LINE>that only tells a lie and swears it. I cannot be a</LINE>
-<LINE>man with wishing, therefore I will die a woman with grieving.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Tarry, good Beatrice. By this hand, I love thee.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Use it for my love some other way than swearing by it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Think you in your soul the Count Claudio hath wronged Hero?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Yea, as sure as I have a thought or a soul.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Enough, I am engaged; I will challenge him. I will</LINE>
-<LINE>kiss your hand, and so I leave you. By this hand,</LINE>
-<LINE>Claudio shall render me a dear account. As you</LINE>
-<LINE>hear of me, so think of me. Go, comfort your</LINE>
-<LINE>cousin: I must say she is dead: and so, farewell.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE II. A prison.</TITLE>
-<STAGEDIR>Enter DOGBERRY, VERGES, and Sexton, in gowns; and
-the Watch, with CONRADE and BORACHIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Is our whole dissembly appeared?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>O, a stool and a cushion for the sexton.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Sexton</SPEAKER>
-<LINE>Which be the malefactors?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Marry, that am I and my partner.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Nay, that's certain; we have the exhibition to examine.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Sexton</SPEAKER>
-<LINE>But which are the offenders that are to be</LINE>
-<LINE>examined? let them come before master constable.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Yea, marry, let them come before me. What is your</LINE>
-<LINE>name, friend?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Borachio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Pray, write down, Borachio. Yours, sirrah?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>I am a gentleman, sir, and my name is Conrade.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Write down, master gentleman Conrade. Masters, do</LINE>
-<LINE>you serve God?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Yea, sir, we hope.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Write down, that they hope they serve God: and</LINE>
-<LINE>write God first; for God defend but God should go</LINE>
-<LINE>before such villains! Masters, it is proved already</LINE>
-<LINE>that you are little better than false knaves; and it</LINE>
-<LINE>will go near to be thought so shortly. How answer</LINE>
-<LINE>you for yourselves?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Marry, sir, we say we are none.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>A marvellous witty fellow, I assure you: but I</LINE>
-<LINE>will go about with him. Come you hither, sirrah; a</LINE>
-<LINE>word in your ear: sir, I say to you, it is thought</LINE>
-<LINE>you are false knaves.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Sir, I say to you we are none.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Well, stand aside. 'Fore God, they are both in a</LINE>
-<LINE>tale. Have you writ down, that they are none?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Sexton</SPEAKER>
-<LINE>Master constable, you go not the way to examine:</LINE>
-<LINE>you must call forth the watch that are their accusers.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Yea, marry, that's the eftest way. Let the watch</LINE>
-<LINE>come forth. Masters, I charge you, in the prince's</LINE>
-<LINE>name, accuse these men.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>First Watchman</SPEAKER>
-<LINE>This man said, sir, that Don John, the prince's</LINE>
-<LINE>brother, was a villain.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Write down Prince John a villain. Why, this is flat</LINE>
-<LINE>perjury, to call a prince's brother villain.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Master constable,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Pray thee, fellow, peace: I do not like thy look,</LINE>
-<LINE>I promise thee.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Sexton</SPEAKER>
-<LINE>What heard you him say else?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Second Watchman</SPEAKER>
-<LINE>Marry, that he had received a thousand ducats of</LINE>
-<LINE>Don John for accusing the Lady Hero wrongfully.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Flat burglary as ever was committed.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Yea, by mass, that it is.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Sexton</SPEAKER>
-<LINE>What else, fellow?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>First Watchman</SPEAKER>
-<LINE>And that Count Claudio did mean, upon his words, to</LINE>
-<LINE>disgrace Hero before the whole assembly. and not marry her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>O villain! thou wilt be condemned into everlasting</LINE>
-<LINE>redemption for this.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Sexton</SPEAKER>
-<LINE>What else?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Watchman</SPEAKER>
-<LINE>This is all.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Sexton</SPEAKER>
-<LINE>And this is more, masters, than you can deny.</LINE>
-<LINE>Prince John is this morning secretly stolen away;</LINE>
-<LINE>Hero was in this manner accused, in this very manner</LINE>
-<LINE>refused, and upon the grief of this suddenly died.</LINE>
-<LINE>Master constable, let these men be bound, and</LINE>
-<LINE>brought to Leonato's: I will go before and show</LINE>
-<LINE>him their examination.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Come, let them be opinioned.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Let them be in the hands--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Off, coxcomb!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>God's my life, where's the sexton? let him write</LINE>
-<LINE>down the prince's officer coxcomb. Come, bind them.</LINE>
-<LINE>Thou naughty varlet!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CONRADE</SPEAKER>
-<LINE>Away! you are an ass, you are an ass.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Dost thou not suspect my place? dost thou not</LINE>
-<LINE>suspect my years? O that he were here to write me</LINE>
-<LINE>down an ass! But, masters, remember that I am an</LINE>
-<LINE>ass; though it be not written down, yet forget not</LINE>
-<LINE>that I am an ass. No, thou villain, thou art full of</LINE>
-<LINE>piety, as shall be proved upon thee by good witness.</LINE>
-<LINE>I am a wise fellow, and, which is more, an officer,</LINE>
-<LINE>and, which is more, a householder, and, which is</LINE>
-<LINE>more, as pretty a piece of flesh as any is in</LINE>
-<LINE>Messina, and one that knows the law, go to; and a</LINE>
-<LINE>rich fellow enough, go to; and a fellow that hath</LINE>
-<LINE>had losses, and one that hath two gowns and every</LINE>
-<LINE>thing handsome about him. Bring him away. O that</LINE>
-<LINE>I had been writ down an ass!</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-</ACT>
-
-<ACT><TITLE>ACT V</TITLE>
-
-<SCENE><TITLE>SCENE I. Before LEONATO'S house.</TITLE>
-<STAGEDIR>Enter LEONATO and ANTONIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>If you go on thus, you will kill yourself:</LINE>
-<LINE>And 'tis not wisdom thus to second grief</LINE>
-<LINE>Against yourself.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I pray thee, cease thy counsel,</LINE>
-<LINE>Which falls into mine ears as profitless</LINE>
-<LINE>As water in a sieve: give not me counsel;</LINE>
-<LINE>Nor let no comforter delight mine ear</LINE>
-<LINE>But such a one whose wrongs do suit with mine.</LINE>
-<LINE>Bring me a father that so loved his child,</LINE>
-<LINE>Whose joy of her is overwhelm'd like mine,</LINE>
-<LINE>And bid him speak of patience;</LINE>
-<LINE>Measure his woe the length and breadth of mine</LINE>
-<LINE>And let it answer every strain for strain,</LINE>
-<LINE>As thus for thus and such a grief for such,</LINE>
-<LINE>In every lineament, branch, shape, and form:</LINE>
-<LINE>If such a one will smile and stroke his beard,</LINE>
-<LINE>Bid sorrow wag, cry 'hem!' when he should groan,</LINE>
-<LINE>Patch grief with proverbs, make misfortune drunk</LINE>
-<LINE>With candle-wasters; bring him yet to me,</LINE>
-<LINE>And I of him will gather patience.</LINE>
-<LINE>But there is no such man: for, brother, men</LINE>
-<LINE>Can counsel and speak comfort to that grief</LINE>
-<LINE>Which they themselves not feel; but, tasting it,</LINE>
-<LINE>Their counsel turns to passion, which before</LINE>
-<LINE>Would give preceptial medicine to rage,</LINE>
-<LINE>Fetter strong madness in a silken thread,</LINE>
-<LINE>Charm ache with air and agony with words:</LINE>
-<LINE>No, no; 'tis all men's office to speak patience</LINE>
-<LINE>To those that wring under the load of sorrow,</LINE>
-<LINE>But no man's virtue nor sufficiency</LINE>
-<LINE>To be so moral when he shall endure</LINE>
-<LINE>The like himself. Therefore give me no counsel:</LINE>
-<LINE>My griefs cry louder than advertisement.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>Therein do men from children nothing differ.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I pray thee, peace. I will be flesh and blood;</LINE>
-<LINE>For there was never yet philosopher</LINE>
-<LINE>That could endure the toothache patiently,</LINE>
-<LINE>However they have writ the style of gods</LINE>
-<LINE>And made a push at chance and sufferance.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>Yet bend not all the harm upon yourself;</LINE>
-<LINE>Make those that do offend you suffer too.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>There thou speak'st reason: nay, I will do so.</LINE>
-<LINE>My soul doth tell me Hero is belied;</LINE>
-<LINE>And that shall Claudio know; so shall the prince</LINE>
-<LINE>And all of them that thus dishonour her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>Here comes the prince and Claudio hastily.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter DON PEDRO and CLAUDIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Good den, good den.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Good day to both of you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Hear you. my lords,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>We have some haste, Leonato.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Some haste, my lord! well, fare you well, my lord:</LINE>
-<LINE>Are you so hasty now? well, all is one.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Nay, do not quarrel with us, good old man.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>If he could right himself with quarreling,</LINE>
-<LINE>Some of us would lie low.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Who wrongs him?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Marry, thou dost wrong me; thou dissembler, thou:--</LINE>
-<LINE>Nay, never lay thy hand upon thy sword;</LINE>
-<LINE>I fear thee not.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Marry, beshrew my hand,</LINE>
-<LINE>If it should give your age such cause of fear:</LINE>
-<LINE>In faith, my hand meant nothing to my sword.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Tush, tush, man; never fleer and jest at me:</LINE>
-<LINE>I speak not like a dotard nor a fool,</LINE>
-<LINE>As under privilege of age to brag</LINE>
-<LINE>What I have done being young, or what would do</LINE>
-<LINE>Were I not old. Know, Claudio, to thy head,</LINE>
-<LINE>Thou hast so wrong'd mine innocent child and me</LINE>
-<LINE>That I am forced to lay my reverence by</LINE>
-<LINE>And, with grey hairs and bruise of many days,</LINE>
-<LINE>Do challenge thee to trial of a man.</LINE>
-<LINE>I say thou hast belied mine innocent child;</LINE>
-<LINE>Thy slander hath gone through and through her heart,</LINE>
-<LINE>And she lies buried with her ancestors;</LINE>
-<LINE>O, in a tomb where never scandal slept,</LINE>
-<LINE>Save this of hers, framed by thy villany!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>My villany?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Thine, Claudio; thine, I say.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>You say not right, old man.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>My lord, my lord,</LINE>
-<LINE>I'll prove it on his body, if he dare,</LINE>
-<LINE>Despite his nice fence and his active practise,</LINE>
-<LINE>His May of youth and bloom of lustihood.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Away! I will not have to do with you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Canst thou so daff me? Thou hast kill'd my child:</LINE>
-<LINE>If thou kill'st me, boy, thou shalt kill a man.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>He shall kill two of us, and men indeed:</LINE>
-<LINE>But that's no matter; let him kill one first;</LINE>
-<LINE>Win me and wear me; let him answer me.</LINE>
-<LINE>Come, follow me, boy; come, sir boy, come, follow me:</LINE>
-<LINE>Sir boy, I'll whip you from your foining fence;</LINE>
-<LINE>Nay, as I am a gentleman, I will.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Brother,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>Content yourself. God knows I loved my niece;</LINE>
-<LINE>And she is dead, slander'd to death by villains,</LINE>
-<LINE>That dare as well answer a man indeed</LINE>
-<LINE>As I dare take a serpent by the tongue:</LINE>
-<LINE>Boys, apes, braggarts, Jacks, milksops!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Brother Antony,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>Hold you content. What, man! I know them, yea,</LINE>
-<LINE>And what they weigh, even to the utmost scruple,--</LINE>
-<LINE>Scrambling, out-facing, fashion-monging boys,</LINE>
-<LINE>That lie and cog and flout, deprave and slander,</LINE>
-<LINE>Go anticly, show outward hideousness,</LINE>
-<LINE>And speak off half a dozen dangerous words,</LINE>
-<LINE>How they might hurt their enemies, if they durst;</LINE>
-<LINE>And this is all.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>But, brother Antony,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>Come, 'tis no matter:</LINE>
-<LINE>Do not you meddle; let me deal in this.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Gentlemen both, we will not wake your patience.</LINE>
-<LINE>My heart is sorry for your daughter's death:</LINE>
-<LINE>But, on my honour, she was charged with nothing</LINE>
-<LINE>But what was true and very full of proof.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>My lord, my lord,--</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>I will not hear you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>No? Come, brother; away! I will be heard.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>And shall, or some of us will smart for it.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt LEONATO and ANTONIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>See, see; here comes the man we went to seek.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter BENEDICK</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Now, signior, what news?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Good day, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Welcome, signior: you are almost come to part</LINE>
-<LINE>almost a fray.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>We had like to have had our two noses snapped off</LINE>
-<LINE>with two old men without teeth.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Leonato and his brother. What thinkest thou? Had</LINE>
-<LINE>we fought, I doubt we should have been too young for them.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>In a false quarrel there is no true valour. I came</LINE>
-<LINE>to seek you both.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>We have been up and down to seek thee; for we are</LINE>
-<LINE>high-proof melancholy and would fain have it beaten</LINE>
-<LINE>away. Wilt thou use thy wit?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>It is in my scabbard: shall I draw it?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Dost thou wear thy wit by thy side?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Never any did so, though very many have been beside</LINE>
-<LINE>their wit. I will bid thee draw, as we do the</LINE>
-<LINE>minstrels; draw, to pleasure us.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>As I am an honest man, he looks pale. Art thou</LINE>
-<LINE>sick, or angry?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>What, courage, man! What though care killed a cat,</LINE>
-<LINE>thou hast mettle enough in thee to kill care.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Sir, I shall meet your wit in the career, and you</LINE>
-<LINE>charge it against me. I pray you choose another subject.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Nay, then, give him another staff: this last was</LINE>
-<LINE>broke cross.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>By this light, he changes more and more: I think</LINE>
-<LINE>he be angry indeed.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>If he be, he knows how to turn his girdle.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Shall I speak a word in your ear?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>God bless me from a challenge!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE><STAGEDIR>Aside to CLAUDIO</STAGEDIR> You are a villain; I jest not:</LINE>
-<LINE>I will make it good how you dare, with what you</LINE>
-<LINE>dare, and when you dare. Do me right, or I will</LINE>
-<LINE>protest your cowardice. You have killed a sweet</LINE>
-<LINE>lady, and her death shall fall heavy on you. Let me</LINE>
-<LINE>hear from you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Well, I will meet you, so I may have good cheer.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>What, a feast, a feast?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I' faith, I thank him; he hath bid me to a calf's</LINE>
-<LINE>head and a capon; the which if I do not carve most</LINE>
-<LINE>curiously, say my knife's naught. Shall I not find</LINE>
-<LINE>a woodcock too?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Sir, your wit ambles well; it goes easily.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>I'll tell thee how Beatrice praised thy wit the</LINE>
-<LINE>other day. I said, thou hadst a fine wit: 'True,'</LINE>
-<LINE>said she, 'a fine little one.' 'No,' said I, 'a</LINE>
-<LINE>great wit:' 'Right,' says she, 'a great gross one.'</LINE>
-<LINE>'Nay,' said I, 'a good wit:' 'Just,' said she, 'it</LINE>
-<LINE>hurts nobody.' 'Nay,' said I, 'the gentleman</LINE>
-<LINE>is wise:' 'Certain,' said she, 'a wise gentleman.'</LINE>
-<LINE>'Nay,' said I, 'he hath the tongues:' 'That I</LINE>
-<LINE>believe,' said she, 'for he swore a thing to me on</LINE>
-<LINE>Monday night, which he forswore on Tuesday morning;</LINE>
-<LINE>there's a double tongue; there's two tongues.' Thus</LINE>
-<LINE>did she, an hour together, transshape thy particular</LINE>
-<LINE>virtues: yet at last she concluded with a sigh, thou</LINE>
-<LINE>wast the properest man in Italy.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>For the which she wept heartily and said she cared</LINE>
-<LINE>not.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Yea, that she did: but yet, for all that, an if she</LINE>
-<LINE>did not hate him deadly, she would love him dearly:</LINE>
-<LINE>the old man's daughter told us all.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>All, all; and, moreover, God saw him when he was</LINE>
-<LINE>hid in the garden.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>But when shall we set the savage bull's horns on</LINE>
-<LINE>the sensible Benedick's head?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Yea, and text underneath, 'Here dwells Benedick the</LINE>
-<LINE>married man'?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Fare you well, boy: you know my mind. I will leave</LINE>
-<LINE>you now to your gossip-like humour: you break jests</LINE>
-<LINE>as braggarts do their blades, which God be thanked,</LINE>
-<LINE>hurt not. My lord, for your many courtesies I thank</LINE>
-<LINE>you: I must discontinue your company: your brother</LINE>
-<LINE>the bastard is fled from Messina: you have among</LINE>
-<LINE>you killed a sweet and innocent lady. For my Lord</LINE>
-<LINE>Lackbeard there, he and I shall meet: and, till</LINE>
-<LINE>then, peace be with him.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>He is in earnest.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>In most profound earnest; and, I'll warrant you, for</LINE>
-<LINE>the love of Beatrice.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>And hath challenged thee.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Most sincerely.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>What a pretty thing man is when he goes in his</LINE>
-<LINE>doublet and hose and leaves off his wit!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>He is then a giant to an ape; but then is an ape a</LINE>
-<LINE>doctor to such a man.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>But, soft you, let me be: pluck up, my heart, and</LINE>
-<LINE>be sad. Did he not say, my brother was fled?</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter DOGBERRY, VERGES, and the Watch, with CONRADE
-and BORACHIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Come you, sir: if justice cannot tame you, she</LINE>
-<LINE>shall ne'er weigh more reasons in her balance: nay,</LINE>
-<LINE>an you be a cursing hypocrite once, you must be looked to.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>How now? two of my brother's men bound! Borachio</LINE>
-<LINE>one!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Hearken after their offence, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Officers, what offence have these men done?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Marry, sir, they have committed false report;</LINE>
-<LINE>moreover, they have spoken untruths; secondarily,</LINE>
-<LINE>they are slanders; sixth and lastly, they have</LINE>
-<LINE>belied a lady; thirdly, they have verified unjust</LINE>
-<LINE>things; and, to conclude, they are lying knaves.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>First, I ask thee what they have done; thirdly, I</LINE>
-<LINE>ask thee what's their offence; sixth and lastly, why</LINE>
-<LINE>they are committed; and, to conclude, what you lay</LINE>
-<LINE>to their charge.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Rightly reasoned, and in his own division: and, by</LINE>
-<LINE>my troth, there's one meaning well suited.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Who have you offended, masters, that you are thus</LINE>
-<LINE>bound to your answer? this learned constable is</LINE>
-<LINE>too cunning to be understood: what's your offence?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Sweet prince, let me go no farther to mine answer:</LINE>
-<LINE>do you hear me, and let this count kill me. I have</LINE>
-<LINE>deceived even your very eyes: what your wisdoms</LINE>
-<LINE>could not discover, these shallow fools have brought</LINE>
-<LINE>to light: who in the night overheard me confessing</LINE>
-<LINE>to this man how Don John your brother incensed me</LINE>
-<LINE>to slander the Lady Hero, how you were brought into</LINE>
-<LINE>the orchard and saw me court Margaret in Hero's</LINE>
-<LINE>garments, how you disgraced her, when you should</LINE>
-<LINE>marry her: my villany they have upon record; which</LINE>
-<LINE>I had rather seal with my death than repeat over</LINE>
-<LINE>to my shame. The lady is dead upon mine and my</LINE>
-<LINE>master's false accusation; and, briefly, I desire</LINE>
-<LINE>nothing but the reward of a villain.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Runs not this speech like iron through your blood?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I have drunk poison whiles he utter'd it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>But did my brother set thee on to this?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Yea, and paid me richly for the practise of it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>He is composed and framed of treachery:</LINE>
-<LINE>And fled he is upon this villany.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Sweet Hero! now thy image doth appear</LINE>
-<LINE>In the rare semblance that I loved it first.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Come, bring away the plaintiffs: by this time our</LINE>
-<LINE>sexton hath reformed Signior Leonato of the matter:</LINE>
-<LINE>and, masters, do not forget to specify, when time</LINE>
-<LINE>and place shall serve, that I am an ass.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>VERGES</SPEAKER>
-<LINE>Here, here comes master Signior Leonato, and the</LINE>
-<LINE>Sexton too.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Re-enter LEONATO and ANTONIO, with the Sexton</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Which is the villain? let me see his eyes,</LINE>
-<LINE>That, when I note another man like him,</LINE>
-<LINE>I may avoid him: which of these is he?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>If you would know your wronger, look on me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Art thou the slave that with thy breath hast kill'd</LINE>
-<LINE>Mine innocent child?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>Yea, even I alone.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>No, not so, villain; thou beliest thyself:</LINE>
-<LINE>Here stand a pair of honourable men;</LINE>
-<LINE>A third is fled, that had a hand in it.</LINE>
-<LINE>I thank you, princes, for my daughter's death:</LINE>
-<LINE>Record it with your high and worthy deeds:</LINE>
-<LINE>'Twas bravely done, if you bethink you of it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I know not how to pray your patience;</LINE>
-<LINE>Yet I must speak. Choose your revenge yourself;</LINE>
-<LINE>Impose me to what penance your invention</LINE>
-<LINE>Can lay upon my sin: yet sinn'd I not</LINE>
-<LINE>But in mistaking.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>By my soul, nor I:</LINE>
-<LINE>And yet, to satisfy this good old man,</LINE>
-<LINE>I would bend under any heavy weight</LINE>
-<LINE>That he'll enjoin me to.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I cannot bid you bid my daughter live;</LINE>
-<LINE>That were impossible: but, I pray you both,</LINE>
-<LINE>Possess the people in Messina here</LINE>
-<LINE>How innocent she died; and if your love</LINE>
-<LINE>Can labour ought in sad invention,</LINE>
-<LINE>Hang her an epitaph upon her tomb</LINE>
-<LINE>And sing it to her bones, sing it to-night:</LINE>
-<LINE>To-morrow morning come you to my house,</LINE>
-<LINE>And since you could not be my son-in-law,</LINE>
-<LINE>Be yet my nephew: my brother hath a daughter,</LINE>
-<LINE>Almost the copy of my child that's dead,</LINE>
-<LINE>And she alone is heir to both of us:</LINE>
-<LINE>Give her the right you should have given her cousin,</LINE>
-<LINE>And so dies my revenge.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>O noble sir,</LINE>
-<LINE>Your over-kindness doth wring tears from me!</LINE>
-<LINE>I do embrace your offer; and dispose</LINE>
-<LINE>For henceforth of poor Claudio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>To-morrow then I will expect your coming;</LINE>
-<LINE>To-night I take my leave. This naughty man</LINE>
-<LINE>Shall face to face be brought to Margaret,</LINE>
-<LINE>Who I believe was pack'd in all this wrong,</LINE>
-<LINE>Hired to it by your brother.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BORACHIO</SPEAKER>
-<LINE>No, by my soul, she was not,</LINE>
-<LINE>Nor knew not what she did when she spoke to me,</LINE>
-<LINE>But always hath been just and virtuous</LINE>
-<LINE>In any thing that I do know by her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Moreover, sir, which indeed is not under white and</LINE>
-<LINE>black, this plaintiff here, the offender, did call</LINE>
-<LINE>me ass: I beseech you, let it be remembered in his</LINE>
-<LINE>punishment. And also, the watch heard them talk of</LINE>
-<LINE>one Deformed: they say be wears a key in his ear and</LINE>
-<LINE>a lock hanging by it, and borrows money in God's</LINE>
-<LINE>name, the which he hath used so long and never paid</LINE>
-<LINE>that now men grow hard-hearted and will lend nothing</LINE>
-<LINE>for God's sake: pray you, examine him upon that point.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>I thank thee for thy care and honest pains.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>Your worship speaks like a most thankful and</LINE>
-<LINE>reverend youth; and I praise God for you.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>There's for thy pains.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>God save the foundation!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Go, I discharge thee of thy prisoner, and I thank thee.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DOGBERRY</SPEAKER>
-<LINE>I leave an arrant knave with your worship; which I</LINE>
-<LINE>beseech your worship to correct yourself, for the</LINE>
-<LINE>example of others. God keep your worship! I wish</LINE>
-<LINE>your worship well; God restore you to health! I</LINE>
-<LINE>humbly give you leave to depart; and if a merry</LINE>
-<LINE>meeting may be wished, God prohibit it! Come, neighbour.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt DOGBERRY and VERGES</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Until to-morrow morning, lords, farewell.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>Farewell, my lords: we look for you to-morrow.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>We will not fail.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>To-night I'll mourn with Hero.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE><STAGEDIR>To the Watch</STAGEDIR> Bring you these fellows on. We'll</LINE>
-<LINE>talk with Margaret,</LINE>
-<LINE>How her acquaintance grew with this lewd fellow.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt, severally</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE II. LEONATO'S garden.</TITLE>
-<STAGEDIR>Enter BENEDICK and MARGARET, meeting</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Pray thee, sweet Mistress Margaret, deserve well at</LINE>
-<LINE>my hands by helping me to the speech of Beatrice.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Will you then write me a sonnet in praise of my beauty?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>In so high a style, Margaret, that no man living</LINE>
-<LINE>shall come over it; for, in most comely truth, thou</LINE>
-<LINE>deservest it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>To have no man come over me! why, shall I always</LINE>
-<LINE>keep below stairs?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Thy wit is as quick as the greyhound's mouth; it catches.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>And yours as blunt as the fencer's foils, which hit,</LINE>
-<LINE>but hurt not.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>A most manly wit, Margaret; it will not hurt a</LINE>
-<LINE>woman: and so, I pray thee, call Beatrice: I give</LINE>
-<LINE>thee the bucklers.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Give us the swords; we have bucklers of our own.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>If you use them, Margaret, you must put in the</LINE>
-<LINE>pikes with a vice; and they are dangerous weapons for maids.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>MARGARET</SPEAKER>
-<LINE>Well, I will call Beatrice to you, who I think hath legs.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>And therefore will come.</LINE>
-<STAGEDIR>Exit MARGARET</STAGEDIR>
-<STAGEDIR>Sings</STAGEDIR>
-<LINE>The god of love,</LINE>
-<LINE>That sits above,</LINE>
-<LINE>And knows me, and knows me,</LINE>
-<LINE>How pitiful I deserve,--</LINE>
-<LINE>I mean in singing; but in loving, Leander the good</LINE>
-<LINE>swimmer, Troilus the first employer of panders, and</LINE>
-<LINE>a whole bookful of these quondam carpet-mangers,</LINE>
-<LINE>whose names yet run smoothly in the even road of a</LINE>
-<LINE>blank verse, why, they were never so truly turned</LINE>
-<LINE>over and over as my poor self in love. Marry, I</LINE>
-<LINE>cannot show it in rhyme; I have tried: I can find</LINE>
-<LINE>out no rhyme to 'lady' but 'baby,' an innocent</LINE>
-<LINE>rhyme; for 'scorn,' 'horn,' a hard rhyme; for,</LINE>
-<LINE>'school,' 'fool,' a babbling rhyme; very ominous</LINE>
-<LINE>endings: no, I was not born under a rhyming planet,</LINE>
-<LINE>nor I cannot woo in festival terms.</LINE>
-<STAGEDIR>Enter BEATRICE</STAGEDIR>
-<LINE>Sweet Beatrice, wouldst thou come when I called thee?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Yea, signior, and depart when you bid me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>O, stay but till then!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>'Then' is spoken; fare you well now: and yet, ere</LINE>
-<LINE>I go, let me go with that I came; which is, with</LINE>
-<LINE>knowing what hath passed between you and Claudio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Only foul words; and thereupon I will kiss thee.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Foul words is but foul wind, and foul wind is but</LINE>
-<LINE>foul breath, and foul breath is noisome; therefore I</LINE>
-<LINE>will depart unkissed.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Thou hast frighted the word out of his right sense,</LINE>
-<LINE>so forcible is thy wit. But I must tell thee</LINE>
-<LINE>plainly, Claudio undergoes my challenge; and either</LINE>
-<LINE>I must shortly hear from him, or I will subscribe</LINE>
-<LINE>him a coward. And, I pray thee now, tell me for</LINE>
-<LINE>which of my bad parts didst thou first fall in love with me?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>For them all together; which maintained so politic</LINE>
-<LINE>a state of evil that they will not admit any good</LINE>
-<LINE>part to intermingle with them. But for which of my</LINE>
-<LINE>good parts did you first suffer love for me?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Suffer love! a good epithet! I do suffer love</LINE>
-<LINE>indeed, for I love thee against my will.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>In spite of your heart, I think; alas, poor heart!</LINE>
-<LINE>If you spite it for my sake, I will spite it for</LINE>
-<LINE>yours; for I will never love that which my friend hates.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Thou and I are too wise to woo peaceably.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>It appears not in this confession: there's not one</LINE>
-<LINE>wise man among twenty that will praise himself.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>An old, an old instance, Beatrice, that lived in</LINE>
-<LINE>the lime of good neighbours. If a man do not erect</LINE>
-<LINE>in this age his own tomb ere he dies, he shall live</LINE>
-<LINE>no longer in monument than the bell rings and the</LINE>
-<LINE>widow weeps.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>And how long is that, think you?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Question: why, an hour in clamour and a quarter in</LINE>
-<LINE>rheum: therefore is it most expedient for the</LINE>
-<LINE>wise, if Don Worm, his conscience, find no</LINE>
-<LINE>impediment to the contrary, to be the trumpet of his</LINE>
-<LINE>own virtues, as I am to myself. So much for</LINE>
-<LINE>praising myself, who, I myself will bear witness, is</LINE>
-<LINE>praiseworthy: and now tell me, how doth your cousin?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Very ill.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>And how do you?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Very ill too.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Serve God, love me and mend. There will I leave</LINE>
-<LINE>you too, for here comes one in haste.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter URSULA</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>URSULA</SPEAKER>
-<LINE>Madam, you must come to your uncle. Yonder's old</LINE>
-<LINE>coil at home: it is proved my Lady Hero hath been</LINE>
-<LINE>falsely accused, the prince and Claudio mightily</LINE>
-<LINE>abused; and Don John is the author of all, who is</LINE>
-<LINE>fed and gone. Will you come presently?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Will you go hear this news, signior?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I will live in thy heart, die in thy lap, and be</LINE>
-<LINE>buried in thy eyes; and moreover I will go with</LINE>
-<LINE>thee to thy uncle's.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE III. A church.</TITLE>
-<STAGEDIR>Enter DON PEDRO, CLAUDIO, and three or four
-with tapers</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Is this the monument of Leonato?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>Lord</SPEAKER>
-<LINE>It is, my lord.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE><STAGEDIR>Reading out of a scroll</STAGEDIR></LINE>
-<LINE>Done to death by slanderous tongues</LINE>
-<LINE>Was the Hero that here lies:</LINE>
-<LINE>Death, in guerdon of her wrongs,</LINE>
-<LINE>Gives her fame which never dies.</LINE>
-<LINE>So the life that died with shame</LINE>
-<LINE>Lives in death with glorious fame.</LINE>
-<LINE>Hang thou there upon the tomb,</LINE>
-<LINE>Praising her when I am dumb.</LINE>
-<LINE>Now, music, sound, and sing your solemn hymn.</LINE>
-<SUBHEAD>SONG.</SUBHEAD>
-<LINE>Pardon, goddess of the night,</LINE>
-<LINE>Those that slew thy virgin knight;</LINE>
-<LINE>For the which, with songs of woe,</LINE>
-<LINE>Round about her tomb they go.</LINE>
-<LINE>Midnight, assist our moan;</LINE>
-<LINE>Help us to sigh and groan,</LINE>
-<LINE>Heavily, heavily:</LINE>
-<LINE>Graves, yawn and yield your dead,</LINE>
-<LINE>Till death be uttered,</LINE>
-<LINE>Heavily, heavily.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Now, unto thy bones good night!</LINE>
-<LINE>Yearly will I do this rite.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Good morrow, masters; put your torches out:</LINE>
-<LINE>The wolves have prey'd; and look, the gentle day,</LINE>
-<LINE>Before the wheels of Phoebus, round about</LINE>
-<LINE>Dapples the drowsy east with spots of grey.</LINE>
-<LINE>Thanks to you all, and leave us: fare you well.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Good morrow, masters: each his several way.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Come, let us hence, and put on other weeds;</LINE>
-<LINE>And then to Leonato's we will go.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And Hymen now with luckier issue speed's</LINE>
-<LINE>Than this for whom we render'd up this woe.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-
-<SCENE><TITLE>SCENE IV. A room in LEONATO'S house.</TITLE>
-<STAGEDIR>Enter LEONATO, ANTONIO, BENEDICK, BEATRICE,
-MARGARET, URSULA, FRIAR FRANCIS, and HERO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>Did I not tell you she was innocent?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>So are the prince and Claudio, who accused her</LINE>
-<LINE>Upon the error that you heard debated:</LINE>
-<LINE>But Margaret was in some fault for this,</LINE>
-<LINE>Although against her will, as it appears</LINE>
-<LINE>In the true course of all the question.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>Well, I am glad that all things sort so well.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>And so am I, being else by faith enforced</LINE>
-<LINE>To call young Claudio to a reckoning for it.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Well, daughter, and you gentle-women all,</LINE>
-<LINE>Withdraw into a chamber by yourselves,</LINE>
-<LINE>And when I send for you, come hither mask'd.</LINE>
-<STAGEDIR>Exeunt Ladies</STAGEDIR>
-<LINE>The prince and Claudio promised by this hour</LINE>
-<LINE>To visit me. You know your office, brother:</LINE>
-<LINE>You must be father to your brother's daughter</LINE>
-<LINE>And give her to young Claudio.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>Which I will do with confirm'd countenance.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Friar, I must entreat your pains, I think.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>To do what, signior?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>To bind me, or undo me; one of them.</LINE>
-<LINE>Signior Leonato, truth it is, good signior,</LINE>
-<LINE>Your niece regards me with an eye of favour.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>That eye my daughter lent her: 'tis most true.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>And I do with an eye of love requite her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>The sight whereof I think you had from me,</LINE>
-<LINE>From Claudio and the prince: but what's your will?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Your answer, sir, is enigmatical:</LINE>
-<LINE>But, for my will, my will is your good will</LINE>
-<LINE>May stand with ours, this day to be conjoin'd</LINE>
-<LINE>In the state of honourable marriage:</LINE>
-<LINE>In which, good friar, I shall desire your help.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>My heart is with your liking.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>And my help.</LINE>
-<LINE>Here comes the prince and Claudio.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter DON PEDRO and CLAUDIO, and two or
-three others</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Good morrow to this fair assembly.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Good morrow, prince; good morrow, Claudio:</LINE>
-<LINE>We here attend you. Are you yet determined</LINE>
-<LINE>To-day to marry with my brother's daughter?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I'll hold my mind, were she an Ethiope.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Call her forth, brother; here's the friar ready.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Exit ANTONIO</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>Good morrow, Benedick. Why, what's the matter,</LINE>
-<LINE>That you have such a February face,</LINE>
-<LINE>So full of frost, of storm and cloudiness?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I think he thinks upon the savage bull.</LINE>
-<LINE>Tush, fear not, man; we'll tip thy horns with gold</LINE>
-<LINE>And all Europa shall rejoice at thee,</LINE>
-<LINE>As once Europa did at lusty Jove,</LINE>
-<LINE>When he would play the noble beast in love.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Bull Jove, sir, had an amiable low;</LINE>
-<LINE>And some such strange bull leap'd your father's cow,</LINE>
-<LINE>And got a calf in that same noble feat</LINE>
-<LINE>Much like to you, for you have just his bleat.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>For this I owe you: here comes other reckonings.</LINE>
-<STAGEDIR>Re-enter ANTONIO, with the Ladies masked</STAGEDIR>
-<LINE>Which is the lady I must seize upon?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>ANTONIO</SPEAKER>
-<LINE>This same is she, and I do give you her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Why, then she's mine. Sweet, let me see your face.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>No, that you shall not, till you take her hand</LINE>
-<LINE>Before this friar and swear to marry her.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Give me your hand: before this holy friar,</LINE>
-<LINE>I am your husband, if you like of me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>And when I lived, I was your other wife:</LINE>
-<STAGEDIR>Unmasking</STAGEDIR>
-<LINE>And when you loved, you were my other husband.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>Another Hero!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>Nothing certainer:</LINE>
-<LINE>One Hero died defiled, but I do live,</LINE>
-<LINE>And surely as I live, I am a maid.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>The former Hero! Hero that is dead!</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>She died, my lord, but whiles her slander lived.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>FRIAR FRANCIS</SPEAKER>
-<LINE>All this amazement can I qualify:</LINE>
-<LINE>When after that the holy rites are ended,</LINE>
-<LINE>I'll tell you largely of fair Hero's death:</LINE>
-<LINE>Meantime let wonder seem familiar,</LINE>
-<LINE>And to the chapel let us presently.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Soft and fair, friar. Which is Beatrice?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE><STAGEDIR>Unmasking</STAGEDIR> I answer to that name. What is your will?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Do not you love me?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Why, no; no more than reason.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Why, then your uncle and the prince and Claudio</LINE>
-<LINE>Have been deceived; they swore you did.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Do not you love me?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Troth, no; no more than reason.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>Why, then my cousin Margaret and Ursula</LINE>
-<LINE>Are much deceived; for they did swear you did.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>They swore that you were almost sick for me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>They swore that you were well-nigh dead for me.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>'Tis no such matter. Then you do not love me?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>No, truly, but in friendly recompense.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>Come, cousin, I am sure you love the gentleman.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>And I'll be sworn upon't that he loves her;</LINE>
-<LINE>For here's a paper written in his hand,</LINE>
-<LINE>A halting sonnet of his own pure brain,</LINE>
-<LINE>Fashion'd to Beatrice.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>HERO</SPEAKER>
-<LINE>And here's another</LINE>
-<LINE>Writ in my cousin's hand, stolen from her pocket,</LINE>
-<LINE>Containing her affection unto Benedick.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>A miracle! here's our own hands against our hearts.</LINE>
-<LINE>Come, I will have thee; but, by this light, I take</LINE>
-<LINE>thee for pity.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BEATRICE</SPEAKER>
-<LINE>I would not deny you; but, by this good day, I yield</LINE>
-<LINE>upon great persuasion; and partly to save your life,</LINE>
-<LINE>for I was told you were in a consumption.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Peace! I will stop your mouth.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Kissing her</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>DON PEDRO</SPEAKER>
-<LINE>How dost thou, Benedick, the married man?</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>I'll tell thee what, prince; a college of</LINE>
-<LINE>wit-crackers cannot flout me out of my humour. Dost</LINE>
-<LINE>thou think I care for a satire or an epigram? No:</LINE>
-<LINE>if a man will be beaten with brains, a' shall wear</LINE>
-<LINE>nothing handsome about him. In brief, since I do</LINE>
-<LINE>purpose to marry, I will think nothing to any</LINE>
-<LINE>purpose that the world can say against it; and</LINE>
-<LINE>therefore never flout at me for what I have said</LINE>
-<LINE>against it; for man is a giddy thing, and this is my</LINE>
-<LINE>conclusion. For thy part, Claudio, I did think to</LINE>
-<LINE>have beaten thee, but in that thou art like to be my</LINE>
-<LINE>kinsman, live unbruised and love my cousin.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>CLAUDIO</SPEAKER>
-<LINE>I had well hoped thou wouldst have denied Beatrice,</LINE>
-<LINE>that I might have cudgelled thee out of thy single</LINE>
-<LINE>life, to make thee a double-dealer; which, out of</LINE>
-<LINE>question, thou wilt be, if my cousin do not look</LINE>
-<LINE>exceedingly narrowly to thee.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Come, come, we are friends: let's have a dance ere</LINE>
-<LINE>we are married, that we may lighten our own hearts</LINE>
-<LINE>and our wives' heels.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>LEONATO</SPEAKER>
-<LINE>We'll have dancing afterward.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>First, of my word; therefore play, music. Prince,</LINE>
-<LINE>thou art sad; get thee a wife, get thee a wife:</LINE>
-<LINE>there is no staff more reverend than one tipped with horn.</LINE>
-</SPEECH>
-
-
-<STAGEDIR>Enter a Messenger</STAGEDIR>
-
-<SPEECH>
-<SPEAKER>Messenger</SPEAKER>
-<LINE>My lord, your brother John is ta'en in flight,</LINE>
-<LINE>And brought with armed men back to Messina.</LINE>
-</SPEECH>
-
-<SPEECH>
-<SPEAKER>BENEDICK</SPEAKER>
-<LINE>Think not on him till to-morrow:</LINE>
-<LINE>I'll devise thee brave punishments for him.</LINE>
-<LINE>Strike up, pipers.</LINE>
-</SPEECH>
-
-<STAGEDIR>Dance</STAGEDIR>
-<STAGEDIR>Exeunt</STAGEDIR>
-</SCENE>
-</ACT>
-</PLAY>
diff --git a/test/rexml/data/namespaces.xml b/test/rexml/data/namespaces.xml
deleted file mode 100644
index e8e4df8364..0000000000
--- a/test/rexml/data/namespaces.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0"?>
-<foo:a xmlns:foo="http://fooNamespace/">
- <b>
- <c>Hello</c>
- </b>
-
- <foo:d>
- <foo:e>Hey</foo:e>
- </foo:d>
-
- <bar:f xmlns:bar="http://barNamespace/">
- <bar:g>Hey2</bar:g>
- </bar:f>
-
- <alias:x xmlns:alias="http://fooNamespace/">
- <alias:y>Hey3</alias:y>
- </alias:x>
-</foo:a>
diff --git a/test/rexml/data/nitf.xml b/test/rexml/data/nitf.xml
deleted file mode 100644
index 269d99e211..0000000000
--- a/test/rexml/data/nitf.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<nitf>
-
- <!-- Example of markup of URLs (at the bottom of the story) -->
-
- <head>
- <meta name="ap-cycle" content="AP"/>
- <meta name="ap-online-code" content="1700"/>
- <meta name="ap-company" content="CO:Media Metrix Inc;TS:MMXI;IG:SVC;"/>
- <meta name="ap-routing" content="ENTITLEMENTS,pfONLINE,pf1700"/>
- <meta name="ap-format" content="bx"/>
- <meta name="ap-category" content="f"/>
- <meta name="ap-selector" content="-----"/>
- <meta name="ap-transref" content="V0347"/>
- <docdata>
- <doc-id regsrc="AP" id-string="D76UIMO80"/>
- <urgency ed-urg="7"/>
- <date.issue norm="20000911T185842Z"/>
- <du-key key="Napster Traffic"/>
- <doc.copyright holder="(AP)"/>
- </docdata>
- </head>
- <body>
- <body.head>
- <hedline>
- <hl1>Use of Napster Quadruples</hl1>
- </hedline>
- <byline>By PETER SVENSSON
- <byttl>AP Business Writer</byttl>
- </byline>
- <distributor>The Associated Press</distributor>
- <dateline>
- <location>NEW YORK</location>
- </dateline>
- </body.head>
- <body.content>
- <block>
- <p>Despite the uncertain legality of the Napster online music-sharing service, the number of people
-using it more than quadrupled in just five months, Media Metrix said Monday.</p>
- <p>That made Napster the fastest-growing software application ever recorded by the Internet research
-company.</p>
- <p>From 1.1 million home users in the United States in February, the first month Media Metrix
-tracked the application, Napster use rocketed to 4.9 million users in July.</p>
- <p>That represents 6 percent of U.S. home PC users who have modems, said Media Metrix, which pays
-people to install monitoring software on their computers.</p>
- <p>It estimates total usage from a panel of about 50,000 people in the United States.</p>
- <p>Napster was also used at work by 887,000 people in July, Media Metrix said.</p>
- <p>Napster Inc. has been sued by the recording industry for allegedly enabling copyright
-infringement. The federal government weighed in on the case Friday, saying the service is not protected
-under a key copyright law, as the San Mateo, Calif., company claims.</p>
- <p>Bruce Ryon, head of Media Metrix&apos;s New Media Group, said Napster was used by &quot;the full spectrum of PC users, not just the youth with time on their hands and a passion for music.&quot;</p>
- <p>The Napster program allows users to copy digital music files from the hard drives of other
-users over the Internet.</p>
- <p>Napster Inc. said last week that 28 million people had downloaded its program. It does not reveal
-its own figures for how many people actually use the software.</p>
- <p>Because the program connects to the company&apos;s computers over the Internet every time
-it is run, Napster Inc. can track usage exactly.</p>
- <p>__</p>
- <p>On the Net:</p>
- <p><a href="http://www.napster.com">
-http://www.napster.com</a></p>
- <p><a href="http://www.mediametrix.com">
-http://www.mediametrix.com</a></p>
- </block>
- </body.content>
- </body>
-</nitf>
diff --git a/test/rexml/data/numbers.xml b/test/rexml/data/numbers.xml
deleted file mode 100644
index a1791cd638..0000000000
--- a/test/rexml/data/numbers.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0"?>
-
-<numbers>
- <set>
- <nr>3</nr>
- <nr>24</nr>
- <nr>55</nr>
- <nr>11</nr>
- <nr>2</nr>
- <nr>-3</nr>
- </set>
- <set>
- <nr value="66"/>
- <nr value="123"/>
- <nr value="55"/>
- <nr value="9999"/>
- </set>
-</numbers>
diff --git a/test/rexml/data/ofbiz-issues-full-177.xml b/test/rexml/data/ofbiz-issues-full-177.xml
deleted file mode 100644
index bfff771d12..0000000000
--- a/test/rexml/data/ofbiz-issues-full-177.xml
+++ /dev/null
@@ -1,13971 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE issuezilla [
- <!-- This DTD describes a structure that contains one or more -->
- <!-- IssueZilla issues. IssueZilla is a derivative of BugZilla -->
- <!-- (http://bugzilla.mozilla.org) developed for use with SourceCast -->
- <!-- $Id: issuezilla.dtd 34364 2003-11-18 00:30:16Z kmaples $ -->
-
- <!ELEMENT issuezilla (issue+)>
-
- <!-- Attributes of the root element 'issuezilla': -->
- <!-- -->
- <!-- version : Current version of IssueZilla. -->
- <!-- urlbase : Full url to source installation of issueZilla. -->
- <!-- maintainer : Email address of person responsible for -->
- <!-- installation usually 'webmaster@foo.com' -->
- <!-- exporter : Email address of the individual performing the -->
- <!-- XML export. -->
- <!-- charset : The originating charset for this issue. -->
- <!-- dtd_version : Version of this DTD; the cvs revision number. -->
-
- <!ATTLIST issuezilla version CDATA #REQUIRED>
- <!ATTLIST issuezilla urlbase CDATA #REQUIRED>
- <!ATTLIST issuezilla maintainer CDATA #REQUIRED>
- <!ATTLIST issuezilla exporter CDATA #IMPLIED>
- <!ATTLIST issuezilla charset CDATA #REQUIRED>
-
- <!-- Attributes of the Helm project from whence this export came: -->
-
- <!ATTLIST issuezilla project_domain CDATA #IMPLIED>
- <!ATTLIST issuezilla project_name CDATA #IMPLIED>
- <!ATTLIST issuezilla project_id CDATA #IMPLIED>
-
- <!-- Current cvs revision: $Revision: 1.6 $ -->
- <!-- Revision above should match hardcoded value below (hard-coded -->
- <!-- to facilitate development): -->
- <!ATTLIST issuezilla dtd_version CDATA #FIXED "Revision: 1.2">
-
- <!-- Elements comprising an issue. -->
-
- <!ELEMENT issue ( issue_id, (issue_status, priority, resolution,
- component, version, rep_platform, assigned_to,
- delta_ts, subcomponent, reporter, target_milestone?, issue_type,
- creation_ts, qa_contact?, status_whiteboard?, issue_file_loc?,
- votes?, op_sys, short_desc, keywords*, dependson*, blocks*,
- is_duplicate?, has_duplicates*, cc*, long_desc+, attachment*,
- activity*
- )?
- ) >
-
- <!-- Attribute(s) of the 'issue' element: -->
- <!-- -->
- <!-- status_code : Error code if issue requested is missing, or user -->
- <!-- performing the operation does not have the -->
- <!-- necessary role. Uses HTTP codes as defined in -->
- <!-- RFC 2616; will always return a three-digit code. -->
- <!-- status_message : String corresponding to status_code above. -->
-
- <!ATTLIST issue status_code (200|401|404) #REQUIRED>
- <!ATTLIST issue status_message (OK|Unauthorized|NotFound) #REQUIRED>
-
- <!-- Elements of issue and their definitions: -->
- <!-- -->
- <!-- issue_id : ID of this issue (unique key). -->
- <!-- issue_status : Current status of this issue. -->
- <!-- priority : Priority (severity) assigned to issue. -->
- <!-- resolution : The issue's resolution, if any -->
- <!-- component : Product against which issue is reported. -->
- <!-- version : Version associated with component. -->
- <!-- platform : Platform issue reported against (e.g. linux, etc.).-->
- <!-- assigned_to : Email of person issue currently assigned to. -->
- <!-- delta_ts : Last modified timestamp ('yyyy-mm-dd hh:mm:ss'). -->
- <!-- -->
- <!-- subcomponent : Component of component issue reported against. -->
- <!-- reporter : Email of initial issue reporter. -->
- <!-- target_milestone : Milestone for this issue's resolution. -->
- <!-- issue_type : Nature of issue, e.g. defect, task, etc. -->
- <!-- creation_ts : Issue creation timestamp ('yyyy-mm-dd hh:mm:ss').-->
- <!-- qa_contact : Email of the QA contact for this issue. -->
- <!-- status_whiteboard: Free text 'whiteboard' for issue comments. -->
- <!-- issue_file_loc : URL related to issue -->
- <!-- votes : current votes for issu -->
- <!-- op_sys : Operating system issue reported against. -->
- <!-- short_desc : Short description of issue. -->
-
- <!ELEMENT issue_id (#PCDATA)>
- <!ELEMENT issue_status (#PCDATA)>
- <!ELEMENT priority (#PCDATA)>
- <!ELEMENT resolution (#PCDATA)>
- <!ELEMENT component (#PCDATA)>
- <!ELEMENT version (#PCDATA)>
- <!ELEMENT rep_platform (#PCDATA)>
- <!ELEMENT assigned_to (#PCDATA)>
- <!ELEMENT delta_ts (#PCDATA)>
- <!ELEMENT subcomponent (#PCDATA)>
- <!ELEMENT reporter (#PCDATA)>
- <!ELEMENT target_milestone (#PCDATA)>
- <!ELEMENT issue_type (#PCDATA)>
- <!ELEMENT creation_ts (#PCDATA)>
- <!ELEMENT qa_contact (#PCDATA)>
- <!ELEMENT status_whiteboard (#PCDATA)>
- <!ELEMENT issue_file_loc (#PCDATA)>
- <!ELEMENT votes (#PCDATA)>
- <!ELEMENT op_sys (#PCDATA)>
- <!ELEMENT short_desc (#PCDATA)>
-
- <!-- Data from the longdescs table for this issue id. Essentially -->
- <!-- the log of additional comments. -->
- <!-- -->
- <!-- who : Email of person posting long_desc. -->
- <!-- issue_when : Timestamp when long_desc added ('yyy-mm-dd hh:mm') -->
- <!-- thetext : Free text that comprises the long desc. -->
-
- <!ELEMENT long_desc (who, issue_when, thetext)>
-
- <!ELEMENT who (#PCDATA)>
- <!ELEMENT issue_when (#PCDATA)>
- <!ELEMENT thetext (#PCDATA)>
-
- <!-- 'optional' elements.
- keywords : List of keywords for this issue.
- dependson : List of local issue IDs that depend on this one.
- blocks : List of local issue IDs blocked by this one.
- is_duplicate : The issue which this issue was closed as a
- duplicate of.
- has_duplicates : Other issues which were closed as a duplicate
- of this issue.
- cc : List of email addresses of interested parties.
-
- NOTE: elements of 'blocks', 'dependson', 'is_duplicate' and
- 'has_duplicates' are defined elsewhere in this document. -->
-
- <!ELEMENT keywords (#PCDATA)>
- <!ELEMENT dependson (issue_id, who, when)>
- <!ELEMENT blocks (issue_id, who, when)>
- <!ELEMENT is_duplicate (issue_id, who, when)>
- <!ELEMENT has_duplicates (issue_id, who, when)>
- <!ELEMENT cc (#PCDATA)>
-
- <!-- Data pertaining to attachments. NOTE - some of these fields -->
- <!-- are currently unimplemented (ispatch, filename, etc.). -->
-
- <!ELEMENT attachment (mimetype, attachid, date, desc, ispatch*, filename,
- submitter_id, submitting_username, data, attachment_iz_url)>
-
- <!-- encoding : How the inline attachment is encoded. -->
-
- <!ATTLIST attachment encoding CDATA #FIXED "Base64" >
-
- <!-- mimetype : Mime type for the attachment. -->
- <!-- attachid : A unique id for this attachment. -->
- <!-- date : Timestamp of when added 'yyyy-mm-dd hh:mm' -->
- <!-- desc : Short description for attachment. -->
- <!-- ispatch : Whether attachment is a patch file. -->
- <!-- filename : Filename of attachment. -->
- <!-- submitter_id : Issuezilla ID of attachement submitter. -->
- <!-- submitting_username : username of attachement submitter. -->
- <!-- data : Encoded attachment. -->
- <!-- attachment_iz_url : URL to attachment in iz. -->
-
- <!ELEMENT mimetype (#PCDATA)>
- <!ELEMENT attachid (#PCDATA)>
- <!ELEMENT date (#PCDATA)>
- <!ELEMENT desc (#PCDATA)>
- <!ELEMENT ispatch (#PCDATA)>
- <!ELEMENT filename (#PCDATA)>
- <!ELEMENT submitter_id (#PCDATA)>
- <!ELEMENT submitting_username (#PCDATA)>
- <!ELEMENT data (#PCDATA)>
- <!ELEMENT attachment_iz_url (#PCDATA)>
-
- <!-- Data pertaining to the issue's activity record. -->
-
- <!ELEMENT activity (user, when, field_name, field_desc, oldvalue,
- newvalue)>
-
- <!-- user : user who performed the action -->
- <!-- when : date the described change was made -->
- <!-- field_name : name of db field (in fielddefs) -->
- <!-- field_desc : description of the database field -->
- <!-- oldvalue : value changed from -->
- <!-- newvalue : value changed to -->
-
- <!ELEMENT user (#PCDATA)>
- <!ELEMENT when (#PCDATA)>
- <!ELEMENT field_name (#PCDATA)>
- <!ELEMENT field_desc (#PCDATA)>
- <!ELEMENT oldvalue (#PCDATA)>
- <!ELEMENT newvalue (#PCDATA)>
-
-
-]>
-<issuezilla exporter="guest" charset="UTF-8" version="2.11" urlbase="https://ofbiz.dev.java.net/issues/" maintainer="owner@ofbiz.dev.java.net" project_domain="dev.java.net" project_name="ofbiz" project_id="792" dtd_version="Revision: 1.2">
-<issue status_code="200" status_message="OK">
- <issue_id>1</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Documentation</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20030820210924</delta_ts>
- <subcomponent>website</subcomponent>
- <reporter>ajzeneski</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-08-13 22:35:10</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Website missing</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-08-13 22:35:10</issue_when>
- <thetext>Website is missing from CVS.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-08-19 12:09:17</issue_when>
- <thetext>Website starting to move</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-08-19 12:11:57</issue_when>
- <thetext>Changed milestone</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-08-20 21:09:24</issue_when>
- <thetext>Website has been imported into CVS</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2003-08-19 12:09:17</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>STARTED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2003-08-19 12:09:17</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>unspecified</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2003-08-19 12:11:57</when>
- <field_name>target_milestone</field_name>
- <field_desc>Target Milestone</field_desc>
- <oldvalue>milestone 1</oldvalue>
- <newvalue>not determined</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2003-08-20 21:09:24</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>STARTED</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2003-08-20 21:09:24</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>2</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20030824004146</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>ajzeneski</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-08-23 14:25:20</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Missing FTL</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-08-23 14:25:20</issue_when>
- <thetext>Missing FTL file:
-
-Error: File not found: /feature/EditFeatureCategoryFeatures.ftl</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2003-08-24 00:41:46</issue_when>
- <thetext>Converted JSP to FTL, made some small corrections.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2003-08-24 00:41:46</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2003-08-24 00:41:46</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>3</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20030828103031</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>ajzeneski</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-08-23 14:27:14</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Edit Promo Bug</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-08-23 14:27:14</issue_when>
- <thetext>When editing a promo rule; the drop down for the current condition contains only
-the existing condition (many times).</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2003-08-28 10:30:31</issue_when>
- <thetext>#list directive had a type. Fix in CVS.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2003-08-28 10:30:31</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2003-08-28 10:30:31</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>4</issue_id>
- <issue_status>VERIFIED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20030828103057</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>ajzeneski</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-08-23 14:30:52</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Price Rule Bug</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-08-23 14:30:52</issue_when>
- <thetext>When editing a price rule; changing the is &quot;sale price&quot; flag sets properly,
-however always displays &quot;no&quot; as the selected choice.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2003-08-28 10:20:59</issue_when>
- <thetext>Fixed conditional on the no button, now appears correctly.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2003-08-28 10:30:57</issue_when>
- <thetext>Done</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2003-08-28 10:20:59</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2003-08-28 10:20:59</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2003-08-28 10:30:57</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>RESOLVED</oldvalue>
- <newvalue>VERIFIED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>5</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20030823144138</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>ajzeneski</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-08-23 14:41:38</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Relationship missing button</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-08-23 14:41:38</issue_when>
- <thetext>View/Edit party relationships page first is still JSP and second is missing the
-links to communication event(s).</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>6</issue_id>
- <issue_status>CLOSED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20030918144334</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>robdawson</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-09-04 02:09:57</creation_ts>
- <qa_contact>jonesde</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Entity Engine ConnectionFactory and DBCPConnectionFactory issues with Oracle</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>robdawson</who>
- <issue_when>2003-09-04 02:09:57</issue_when>
- <thetext>When using the Inline JDBC Functionality of the Entity Engine to access an Oracle
-database the Entity Engine gives SQL no suitable driver exceptions.
-
-The fix for this involves changing:
- loader.loadClass(driverClassName);
-to
- Class clazz = loader.loadClass(driverClassName);
- clazz.newInstance();
-in both the ConnectionFactory and DBCPConnectionFactory classes.
-
-There will also need to be the appropriate exception handling.
-
-Please contact me if this requires any clarification.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-09-04 22:15:06</issue_when>
- <thetext>The message you are getting means that the JDBC drivers for Oracle cannot be
-found on the classpath. Contact the users mailing list if you need further help
-with this issue.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2003-09-04 22:17:28</issue_when>
- <thetext>Sorry; DBCP support is currently outdated and not used due to the fact that
-there is no transaction support. It is recommended you use the JOTM/XAPool
-connections. This issue will be addressed during a refactor of this class in the
-coming months.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2003-09-18 14:43:34</issue_when>
- <thetext>
-This issue has been resolved with code changes similar to those recommended.
-
-HOWEVER: There is one caveat with this: I would NOT recommend running using
-either of these blocks of code. Without a transaction aware connection pool
-performance will be severely affected or operations may be performed outside of
-transactions. So, I wouldn&apos;t use straight JDBC or DBCP right now. Hopefully in
-the future DBCP will support XADataSources, then it may be an option.
-
-Later,
--David Jones
-</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2003-09-04 22:15:06</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2003-09-04 22:15:06</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2003-09-18 14:43:34</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>RESOLVED</oldvalue>
- <newvalue>CLOSED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2003-09-18 14:43:34</when>
- <field_name>qa_contact</field_name>
- <field_desc>QA Contact</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>jonesde</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>7</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P4</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040304194045</delta_ts>
- <subcomponent>WebTools</subcomponent>
- <reporter>fzhu_genshare</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-09-21 07:35:08</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc>http://localhost:8080/webtools/control/view/ModelGroupWriter?savetofile=true</issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>&quot;Save Entity Group XML to File&quot; error</short_desc>
- <keywords></keywords>
- <has_duplicates>
- <issue_id>8</issue_id>
- <who>jonesde</who>
- <when>2003-11-04 01:04:02</when>
- </has_duplicates>
- <long_desc>
- <who>fzhu_genshare</who>
- <issue_when>2003-09-21 07:35:08</issue_when>
- <thetext>If click &quot;Save Entity Group XML to File&quot; on the webtools, the new page opens and
-the following error message appears:
-
-org.apache.jasper.JasperException: Unable to compile class for JSP
-
-An error occurred at line: -1 in the jsp file: null
-
-Generated servlet error:
-[javac] Since fork is true, ignoring compiler setting.
-[javac] Compiling 1 source file
-[javac] Since fork is true, ignoring compiler setting.
-[javac] C:\DOCUME~1\ADMINI~1\LOCALS~1
-\Temp\Jetty_0_0_0_0_8080__webtools\entity\ModelGroupWriter_jsp.java:72:
-cannot resolve symbol
-[javac] symbol : variable entityGroupResourceHandler
-[javac] location: class org.ofbiz.entity.model.ModelGroupReader
-[javac] ResourceHandler resourceHandler =
-modelGroupReader.entityGroupResourceHandler;
-[javac] ^
-[javac] 1 error</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2003-11-04 01:04:02</issue_when>
- <thetext>*** Issue 8 has been marked as a duplicate of this issue. ***</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-04 19:40:45</issue_when>
- <thetext>lower priority</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-03-04 19:40:45</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P4</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>8</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>DUPLICATE</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20031104010402</delta_ts>
- <subcomponent>WebTools</subcomponent>
- <reporter>fzhu_genshare</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-09-21 07:40:53</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc>http://localhost:8080/webtools/control/view/ModelGroupWriter</issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>&quot;Generate Entity Group XML&quot; error</short_desc>
- <keywords></keywords>
- <is_duplicate>
- <issue_id>7</issue_id>
- <who>jonesde</who>
- <when>2003-11-04 01:04:02</when>
- </is_duplicate>
- <long_desc>
- <who>fzhu_genshare</who>
- <issue_when>2003-09-21 07:40:53</issue_when>
- <thetext>If clicked &quot;Generate Entity Group XML&quot; on webtools, an error message occurs:
-
-org.apache.jasper.JasperException: Unable to compile class for JSP
-
-An error occurred at line: -1 in the jsp file: null
-
-Generated servlet error:
-[javac] Since fork is true, ignoring compiler setting.
-[javac] Compiling 1 source file
-[javac] Since fork is true, ignoring compiler setting.
-[javac] C:\DOCUME~1\ADMINI~1\LOCALS~1
-\Temp\Jetty_0_0_0_0_8080__webtools\entity\ModelGroupWriter_jsp.java:72:
-cannot resolve symbol
-[javac] symbol : variable entityGroupResourceHandler
-[javac] location: class org.ofbiz.entity.model.ModelGroupReader
-[javac] ResourceHandler resourceHandler =
-modelGroupReader.entityGroupResourceHandler;
-[javac] ^
-[javac] 1 error
-
-It seems the class ResourceHandler is missing. The same error result in several
-links of webtools concerning entity engine xml export broken.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2003-11-04 01:04:02</issue_when>
- <thetext>This issue is a duplicate of #7, they may be different links but they hit the same
-request and code.
-
-*** This issue has been marked as a duplicate of 7 ***</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2003-11-04 01:04:02</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2003-11-04 01:04:02</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>DUPLICATE</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>9</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>WONTFIX</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040223211140</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>byersa</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-10-28 09:27:31</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>GenericEntity.getBytes fails with HSQLDB</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>byersa</who>
- <issue_when>2003-10-28 09:27:31</issue_when>
- <thetext>getBytes internally casts to ByteWrapper which causes a ClassCastException.
-Casting directly to byte[] seems to work.
-
-Don&apos;t know if it fails with other dbs.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-23 21:11:40</issue_when>
- <thetext>This does not appear to be something that can be fixed in OFBiz, it appears to be a bug in HSQLDB, and
-only in certain versions. Trying it with an earlier version it worked, but various other things didn&apos;t. We
-may just have to be patient until HSQLDB has another stable release.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-02-23 21:11:40</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-02-23 21:11:40</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>WONTFIX</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>10</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P5</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040630193003</delta_ts>
- <subcomponent>Service</subcomponent>
- <reporter>byersa</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2003-10-31 08:53:59</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>missing or incorrect service parameter message</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>byersa</who>
- <issue_when>2003-10-31 08:53:59</issue_when>
- <thetext>If possible, I think it would be very helpful to developers if the message that
-informs on invalid service parameter conditions would clearly indicate whether
-it is in the IN or OUT mode that the problem is occurring.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 12:17:42</issue_when>
- <thetext>changed to enhancement</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 17:49:18</issue_when>
- <thetext>reassigned</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-06-30 19:30:03</issue_when>
- <thetext>The ServiceValidationException has been updated to support missing and extra fields as well as
-knowing which &quot;mode&quot; (IN/OUT) the error occured in.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 12:17:42</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>DEFECT</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 12:17:42</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P5</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:49:17</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:30:03</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:30:03</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>11</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>PC</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20031104002629</delta_ts>
- <subcomponent>Content</subcomponent>
- <reporter>cyf</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-11-03 22:26:18</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>Windows 2000</op_sys>
- <short_desc>&quot;response.sendRedirect&quot; in jsp could not take effect</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>cyf</who>
- <issue_when>2003-11-03 22:26:18</issue_when>
- <thetext>I have write a test.jsp code(like):
-.....
-hello world!
-&lt;%response.sendRedirect(&quot;control/main&quot;);%&gt;
-....
-
-define :
-in controller.xml:
-&lt;request-map uri=&quot;test&quot; edit=&quot;true&quot;&gt;
- &lt;response name=&quot;success&quot; type=&quot;view&quot; value=&quot;test&quot;/&gt;
- &lt;response name=&quot;error&quot; type=&quot;view&quot; value=&quot;error&quot;/&gt;
-&lt;/request-map&gt;
-.....
-&lt;view-map name=&quot;test&quot; type=&quot;region&quot;/&gt;
-
-in region also configued
-
-when I test the page :
-it&apos;s appear &quot;hello world!&quot;,but didn&apos;t redirect.
-
-When I use this code as jsp page in normal web app,redirect can take effect.
-
-I think this is a bug of in region process.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2003-11-04 00:26:29</issue_when>
- <thetext>
-If I understand your complaint correctly it is because the way you organized
-things the response output stream is committed before the sendRedirect is
-called. There is absolutely nothing that can be done about this.
-
-If you want to send a redirect you should do so in an event or a non-region view
-(and non-jpublish for that matter). Those composite view tools are meant for
-generating views and involve templates that may cause the response to be
-committed before you wrapped view is even called.
-
-BTW, this may be more appropriate as a question on the users list, not as a defect
-bug report.
-
-Later,
--David Jones</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2003-11-04 00:26:29</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2003-11-04 00:26:29</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>12</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040223213513</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>quake_wang</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-11-04 01:39:16</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>entity cache is not synchronized with DB</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>quake_wang</who>
- <issue_when>2003-11-04 01:39:16</issue_when>
- <thetext>Quake,
-
-It might make sense to have an issue created on the ofbiz.dev.java.net
-site that covers this problem, since it may take some time to resolve.
-Could you create one there? It could just include text from messages
-send back and forth in this email thread.
-
-Thanks,
--David
-
-On Nov 3, 2003, at 6:57 PM, Quake_Wang wrote:
-
-&gt; The immutable flag can solve some cache synchronize issues, it will
-&gt; help for debugging. But, please consider this scenario:
-&gt;
-&gt; Service A:
-&gt; OK, now base on policy: &quot;NEVER read from the cache if you are planning
-&gt; on updating&quot;, we directly read from DB,
-&gt; order = findByPK (&quot;Order&quot;, 10000);
-&gt; order.set(&quot;status&quot;, &quot;DEF&quot;);
-&gt; order.store();
-&gt;
-&gt;
-&gt; Service B:
-&gt; order = findByPKCache(&quot;Order&quot;, 10000);
-&gt; just query, do not change any fields, entity engine will put the order
-&gt; 10000 with &quot;DEF&quot; status in cache, after some other operations (not on
-&gt; the order generic value) throw exception, rolled back service A and B,
-&gt; then PKCache is not synchronized with DB too, the immutable flag can
-&gt; not help any......
-&gt;
-&gt; You wrote a service using cache for better performance, and someone
-&gt; may assembly your service in same transaction (group service, ECA
-&gt; service), the synchronizing may broken, it&apos;s really hard to find such
-&gt; problem.
-&gt;
-&gt; Any ideas?
-&gt;
-&gt; Quake
-&gt;
-&gt; -----Original Message-----
-&gt; From: David Jones [mailto:jonesde@ofbiz.org]
-&gt; Sent: Monday, November 03, 2003 11:05 PM
-&gt; To: dev@ofbiz.dev.java.net
-&gt; Subject: Re: [OFBiz] Dev - Important - [Bug] PKCache is not
-&gt; synchronized
-&gt; with DB
-&gt;
-&gt;
-&gt;
-&gt; Because of the possibility that this is happening and causing
-&gt; previously unexplained problems, I decided to go ahead and implement
-&gt; the immutable feature on the GenericEntity. This is now in CVS, but may
-&gt; cause problems with current code (and will most likely in many cases).
-&gt; Do disable this just comment out the line near the beginning of the set
-&gt; method in GenericEntity.java. It is around line 248 in the current
-&gt; revision of the file.
-&gt;
-&gt; I fixed a few places that had this problem, including createCustomer in
-&gt; ecommerce and the userLogin service. Creating a new customer and going
-&gt; through the checkout process works fine now, but variations on the way
-&gt; I did it may break.
-&gt;
-&gt; If we have too many problems with this, I&apos;m okay with disabling it
-&gt; temporarily, but it would be nice to go this direction in the future.
-&gt; It will help resolve the possibility that strange things happen because
-&gt; things are being changed in the cache when they shouldn&apos;t be and the
-&gt; cache is out of sync with the database, ie is dirty.
-&gt;
-&gt; Feel free to report bugs along these lines, or better yet send
-&gt; patches...
-&gt;
-&gt; Later,
-&gt; -David
-&gt;
-&gt;
-&gt; On Nov 3, 2003, at 5:24 AM, David Jones wrote:
-&gt;
-&gt;&gt;
-&gt;&gt; Quake,
-&gt;&gt;
-&gt;&gt; Yes, I know this is a problem, although I had forgotten about it since
-&gt;&gt; it hasn&apos;t come up for a long time.
-&gt;&gt;
-&gt;&gt; Our official answer on this, related to the use of the cache in
-&gt;&gt; general is: NEVER read from the cache if you are planning on updating
-&gt;&gt; something. It&apos;s tempting to change the GenericValue object to have an
-&gt;&gt; unchangeable flag that is set for all versions that go into the
-&gt;&gt; cache....
-&gt;&gt;
-&gt;&gt; I agree with you, there doesn&apos;t seem to be an easy way to
-&gt;&gt; automatically clear the cache on a rollback. In most cases the
-&gt;&gt; rollback doesn&apos;t even go through the Entity Engine, it is done in
-&gt;&gt; external code. So, the Entity Engine never gets a notification of the
-&gt;&gt; rollback, and if it did it would have to remember every operation that
-&gt;&gt; happened during that transaction so it could clear those dirty cache
-&gt;&gt; entries.
-&gt;&gt;
-&gt;&gt; Thus the policy: never use the cache to read when you are planning on
-&gt;&gt; writing to the database. And yeah, maybe I should throw some code in
-&gt;&gt; there to enforce this... Any thoughts from anyone on that?
-&gt;&gt;
-&gt;&gt; Later,
-&gt;&gt; -David
-&gt;&gt;
-&gt;&gt;
-&gt;&gt;
-&gt;&gt; On Nov 3, 2003, at 4:45 AM, Quake_Wang wrote:
-&gt;&gt;
-&gt;&gt;&gt; Found a bug in the PKCache, below is the scenario
-&gt;&gt;&gt;
-&gt;&gt;&gt; Service A:
-&gt;&gt;&gt; 1. find an order with the order No. 10000, dummy code:
-&gt;&gt;&gt; order = findByPKCache(&quot;Order&quot;, 10000);
-&gt;&gt;&gt; assume we get an order with the status &quot;ABC&quot;;
-&gt;&gt;&gt;
-&gt;&gt;&gt; 2. set the order status to &quot;DEF&quot; and store, dummy code:
-&gt;&gt;&gt; order.set(&quot;status&quot;, &quot;DEF&quot;);
-&gt;&gt;&gt; order.store();
-&gt;&gt;&gt;
-&gt;&gt;&gt; Service B:
-&gt;&gt;&gt; 1. find order 10000 again, dummy code:
-&gt;&gt;&gt; order = findByPKCache(&quot;Order&quot;, 10000);
-&gt;&gt;&gt; If the service A and B are in the same transaction (ex, group service
-&gt;&gt;&gt; or ECA service), entity engine will get the order with &quot;DEF&quot; status
-&gt;&gt;&gt; and put it in the PK cache.
-&gt;&gt;&gt;
-&gt;&gt;&gt; 2. some other operations, throw exception
-&gt;&gt;&gt; Service A and B are rolled back, as the result, the PKCache is not
-&gt;&gt;&gt; synchronized with DB:
-&gt;&gt;&gt; DB: order 10000, status &quot;ABC&quot;
-&gt;&gt;&gt; PKCache: order 10000, status &quot;DEF&quot;
-&gt;&gt;&gt;
-&gt;&gt;&gt; I spent some time to trace this bug, but can not find an easy way to
-&gt;&gt;&gt; fix it, just simply change the findByPKCache to findByPK in service
-&gt;&gt;&gt; B.
-&gt;&gt;&gt; I&apos;m sending out this email in hopes of helping who may encounter the
-&gt;&gt;&gt; same problem and receiving a better fix method.
-&gt;&gt;&gt;
-&gt;&gt;&gt; Regards
-&gt;&gt;&gt; Quake
-&gt;&gt;&gt;
-&gt;&gt;&gt; ---------------------------------------------------------------------
-&gt;&gt;&gt; To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net
-&gt;&gt;&gt; For additional commands, e-mail: dev-help@ofbiz.dev.java.net
-&gt;&gt;
-&gt;&gt;
-&gt;&gt; ---------------------------------------------------------------------
-&gt;&gt; To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net
-&gt;&gt; For additional commands, e-mail: dev-help@ofbiz.dev.java.net
-&gt;
-&gt;
-&gt; ---------------------------------------------------------------------
-&gt; To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net
-&gt; For additional commands, e-mail: dev-help@ofbiz.dev.java.net
-&gt;
-&gt;
-&gt; ---------------------------------------------------------------------
-&gt; To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net
-&gt; For additional commands, e-mail: dev-help@ofbiz.dev.java.net
-
-
----------------------------------------------------------------------
-To unsubscribe, e-mail: dev-unsubscribe@ofbiz.dev.java.net
-For additional commands, e-mail: dev-help@ofbiz.dev.java.net</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-23 21:35:13</issue_when>
- <thetext>
-Just a note on this. To fix it there need to be ThreadLocal caches that are maintained by a class that
-implements the Synchronization interface for transactions. The idea would be that cache reads look in
-the ThreadLocal cache first, then in the global cache, cache writes put everything in the ThreadLocal
-cache and when the transaction is committed all ThreadLocal cache entries go into the global cache.
--David</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>13</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20031112065558</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>byersa</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2003-11-12 06:15:27</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>setNonPKFields</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>byersa</who>
- <issue_when>2003-11-12 06:15:27</issue_when>
- <thetext>I had a situation in which I used setNonPKFields to populate an entity that had
-createdData and lastModifiedDate from parameters thinking that it would be a
-sort of parameter map. My intention was to then add the individual fields to a
-service input, but it turns out that instead of converting the date string to
-DateTime format, it kept them as strings and the service complained. I guess the
-GenericValue only converts datatypes during the persistence phase? If that is
-the case, it would be useful if it converted up loading.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2003-11-12 06:55:58</issue_when>
- <thetext>This is really not the responsibility of the GenericValue object (or really the
-GenericEntity object). This is difficult to handle as a defect report and should
-be sent to the dev mailing for discussion of the best way to go about what you
-are trying to do. The email message should perhaps include more detail about the
-overall goal you are trying to accomplish. Note that the GenericEntity, at the
-moment, does not enforce types going in, but may be changed to do that and throw
-an exception if the type is wrong. -David</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2003-11-12 06:55:58</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2003-11-12 06:55:58</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>14</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>Macintosh</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040107162053</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-01-07 16:20:53</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Order Summary pages don&apos;t show free shipping promo</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-01-07 16:20:53</issue_when>
- <thetext>Here is a description from Si Chen who reported the problem:
-
-One thing that I noticed that is anomalous, though, is that the order review
-pages still show an estimate for shipping charges, even though the customer
-should get free shipping. It seems that the checkout review pages are using
-org.ofbiz.order.shoppingcart.shipping.ShippingEvents.getShipEstimate, while on
-actual checkout it is using
-org.ofbiz.order.order.OrderReadHelper.getShippingTotal.
-
-The former is not taking into account shipping adjustments.</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>15</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040210064750</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>nowpulse</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-10 01:36:16</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Order Stats showing incorrect YTD info</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>nowpulse</who>
- <issue_when>2004-02-10 01:36:16</issue_when>
- <thetext>The YTD info is incorrect since the Java month starts at 0 instead of 1.
-
-ofbiz/components/order/webapp/ordermgr/WEB-INF/actions/order/orderstats.bsh
-On Line 71 the 1 should be replaced with a 0
-
-cal.set(Calendar.MONTH, 0);
-
-thank you,
-sterling</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-10 06:47:50</issue_when>
- <thetext>Fixed as recommended.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-02-10 06:47:50</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-02-10 06:47:50</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>16</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P4</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20040527233859</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-02-24 02:56:29</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Limit Categories Shown in Drop Downs</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-24 02:56:29</issue_when>
- <thetext>Add &quot;show in drop-down&quot; option ProductCategory, filter by it in all combo style category drop downs,
-and change existing category drop-downs to be combo-boxes, include those on the EditProduct,
-EditProductCategories, EditCategory, EditCategoryProducts, EditPromoRules pages.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-27 23:38:59</issue_when>
- <thetext>Some progress has been made on this, but something still needs to be done with the form tool, etc to
-limit the drop downs.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 11:59:21</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-27 23:38:59</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P1</oldvalue>
- <newvalue>P4</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>17</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P1</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20040318120731</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-02-24 02:58:45</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Filter Promotion Products to exclude discontinued</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-24 02:58:45</issue_when>
- <thetext>Add code to the ProductPromoWorker to (perhaps optionally) filter products included by the
-salesDiscontinuationDate, and of course make sure the category member from/thru dates are being
-honored.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-25 21:00:44</issue_when>
- <thetext>Now implemented.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-02-25 21:00:44</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-02-25 21:00:44</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:07:31</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>18</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P1</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20040318120740</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-24 03:01:49</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Back ordered, or insufficient quantities not handled right</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-24 03:01:49</issue_when>
- <thetext>It appears that when a product is back-ordered, or reserved in excess of the AvailableToPromise the
-calculations and setting of values are messed up.
-
-Here is a report on this from Bryce Ewing on Feb 5th, 2004:
-
-=================================================
-I have found something that appears to be a bug (but I am not totally sure), I will explain this in two
-cases below:
-
-case 1: buy 1 item of product1 with no inventory
- - inventory item created with 0 on hand, and -1 available to promise
- - order item inventory res created with quantity of 1 and quantity not available of 1
-
-case 2: buy 2 items of product2 with 1 item in inventory
- - inventory item updated with 1 on hand, and -1 available to promise
- - order item inventory res created with quantity of 2 and quantity not available of 0
-
-For case 1 the system is doing exactly what I would expect, but in case 2 I would have expected that
-the order item inventory res record would have had a quantity not available of 1 rather than 0.
-
-Am I mistaken in this expectation, or is this infact a bug?
-=================================================
-
-Here is a comment on some apparently related findings by Jacopo Cappellato:
-
-=================================================
-I&apos;m studying the simple method InventoryServices.reserveProductInventory
-that implements the inventory reservation of on order/order item, and I&apos;ve
-got a question about this issue.
-What is the meaning of the quantityNotAvailable field in
-OrderItemInventoryRes entity? Where and how is it used (or intended to be
-used for)? I&apos;ve noticed that this quantity is considered in the pick list
-reports...
-
-Probably the quantityNotAvailable field should contain the quantity reserved
-that caused inventory item&apos;s atp to be less than zero: if so, why in the
-reserveProductInventory method the quantityNotAvailable is set only in line
-498 and not also after line 458? And in which way, once set, could this
-quantity return to zero?
-=================================================</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-24 18:35:45</issue_when>
- <thetext>After a patch from Bryce Ewing it appears to be fixed.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-02-24 18:35:45</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-02-24 18:35:45</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:07:40</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>19</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120748</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-24 06:44:51</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Patch for bug in the Inventory Receive function</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-24 06:44:51</issue_when>
- <thetext>In Facility manager, when you receive a purchase order delivered with more than
-one shipments and you select to receive only one shipment the proposed
-quantities are the quantities of the original purchase order and not the
-quantities of the shipment.
-In my patches I tried to change the minimum amount of code and the
-result is that the code is not well written... obviously feel free to change
-my code.
-PS: I submitted this patches to the dev list in january 2004.
-PPS: the two patches are in Unified Output Format
-
-
-Index: ofbiz/components/product/webapp/facility/inventory/receiveInventory.ftl
-===================================================================
-RCS
-file: /cvs/ofbiz/components/product/webapp/facility/inventory/receiveInventory.f
-tl,v
-retrieving revision 1.5
-diff -u -r1.5 receiveInventory.ftl
---- ofbiz/components/product/webapp/facility/inventory/receiveInventory.ftl
- 17 Dec 2003 22:46:36 -0000 1.5
-+++ ofbiz/components/product/webapp/facility/inventory/receiveInventory.ftl
- 14 Jan 2004 11:05:06 -0000
-@@ -312,6 +312,9 @@
- &lt;/tr&gt;
- &lt;#list purchaseOrderItems as orderItem&gt;
- &lt;#assign defaultQuantity = orderItem.quantity - receivedQuantities
-[orderItem.orderItemSeqId]?double&gt;
-+ &lt;#if shipment?has_content&gt;
-+ &lt;#assign defaultQuantity = shippedQuantities
-[orderItem.orderItemSeqId]?double - receivedQuantities
-[orderItem.orderItemSeqId]?double&gt;
-+ &lt;/#if&gt;
- &lt;#if 0 &lt; defaultQuantity&gt;
- &lt;#assign orderItemType = orderItem.getRelatedOne(&quot;OrderItemType&quot;)&gt;
- &lt;input type=&quot;hidden&quot; name=&quot;orderId_o_${rowCount}&quot;
-value=&quot;${orderItem.orderId}&quot;&gt;
-
-
-
-
-
-
-
-Index: ofbiz/components/product/webapp/facility/WEB-
-INF/actions/inventory/receiveInventory.bsh
-===================================================================
-RCS file: /cvs/ofbiz/components/product/webapp/facility/WEB-
-INF/actions/inventory/receiveInventory.bsh,v
-retrieving revision 1.4
-diff -u -r1.4 receiveInventory.bsh
---- ofbiz/components/product/webapp/facility/WEB-
-INF/actions/inventory/receiveInventory.bsh 25 Aug 2003 15:28:00 -0000
- 1.4
-+++ ofbiz/components/product/webapp/facility/WEB-
-INF/actions/inventory/receiveInventory.bsh 14 Jan 2004 11:08:14 -0000
-@@ -69,6 +69,7 @@
- shipment = delegator.findByPrimaryKey(&quot;Shipment&quot;, UtilMisc.toMap
-(&quot;shipmentId&quot;, shipmentId));
- }
-
-+shippedQuantities = new HashMap();
- purchaseOrderItems = null;
- if (purchaseOrder != null) {
- if (product != null) {
-@@ -80,14 +81,18 @@
- exprs = new ArrayList();
- while (issueIter.hasNext()) {
- issuance = issueIter.next();
-- exprs.add(new EntityExpr(&quot;orderItemSeqId&quot;, EntityOperator.EQUALS,
-issuance.getString(&quot;orderItemSeqId&quot;)));
-+ exprs.add(new EntityExpr(&quot;orderItemSeqId&quot;, EntityOperator.EQUALS,
-issuance.getString(&quot;orderItemSeqId&quot;)));
-+ double issuanceQty = issuance.getDouble(&quot;quantity&quot;).doubleValue();
-+ if (shippedQuantities.containsKey(issuance.getString
-(&quot;orderItemSeqId&quot;))) {
-+ issuanceQty += ((Double)shippedQuantities.get
-(issuance.getString(&quot;orderItemSeqId&quot;))).doubleValue();
-+ }
-+ shippedQuantities.put(issuance.getString(&quot;orderItemSeqId&quot;),
-issuanceQty);
- }
- purchaseOrderItems = EntityUtil.filterByOr(orderItems, exprs);
- } else {
- purchaseOrderItems = purchaseOrder.getRelated(&quot;OrderItem&quot;);
- }
- }
--
- receivedQuantities = new HashMap();
- if (purchaseOrderItems != null &amp;&amp; purchaseOrderItems.size() &gt; 0) {
- context.put(&quot;firstOrderItem&quot;, EntityUtil.getFirst(purchaseOrderItems));
-@@ -100,7 +105,13 @@
- if (receipts != null &amp;&amp; receipts.size() &gt; 0) {
- recIter = receipts.iterator();
- while (recIter.hasNext()) {
-- rec = recIter.next();
-+ rec = recIter.next();
-+ if (shipment != null) {
-+ if (rec.getString(&quot;shipmentId&quot;) == null ||
-+ !rec.getString(&quot;shipmentId&quot;).equals(shipment.getString
-(&quot;shipmentId&quot;))) {
-+ continue;
-+ }
-+ }
- accepted = rec.getDouble(&quot;quantityAccepted&quot;);
- rejected = rec.getDouble(&quot;quantityRejected&quot;);
- if (accepted != null)
-@@ -140,6 +151,7 @@
- context.put(&quot;product&quot;, product);
- context.put(&quot;shipments&quot;, shipments);
- context.put(&quot;shipment&quot;, shipment);
-+context.put(&quot;shippedQuantities&quot;, shippedQuantities);
- context.put(&quot;purchaseOrderItems&quot;, purchaseOrderItems);
- context.put(&quot;receivedQuantities&quot;, receivedQuantities);
- context.put(&quot;rejectReasons&quot;, rejectReasons);</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-24 06:55:45</issue_when>
- <thetext>Created an attachment (id=1)
-Patch files in UOF for receiveInventory,bsh and receiveInventory.ftl
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 06:35:22</issue_when>
- <thetext>The changes are in CVS. Thanks Jacopo!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>1</attachid>
- <date>2004-02-24 06:55:45</date>
- <desc>Patch files in UOF for receiveInventory,bsh and receiveInventory.ftl</desc>
- <ispatch>1</ispatch>
- <filename>receiveInventory.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/1/receiveInventory.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-24 06:55:45</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=1)
-Patch files in UOF for receiveInventory,bsh and receiveInventory.ftl
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 06:35:22</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 06:35:22</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:07:48</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>20</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120758</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-24 07:36:49</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>List All Visits link in the Party Profile page returns an error with 0 visits</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-24 07:36:50</issue_when>
- <thetext>List All Visits link in the Party Profile page returns an error with 0 visits
-(see attached patch file) due to wrong bsh code.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-24 07:38:20</issue_when>
- <thetext>Created an attachment (id=2)
-Patch for bug in uof
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 06:39:57</issue_when>
- <thetext>The changes are in CVS. Thanks Jacopo!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>2</attachid>
- <date>2004-02-24 07:38:20</date>
- <desc>Patch for bug in uof</desc>
- <ispatch>1</ispatch>
- <filename>showvisits.bsh.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/2/showvisits.bsh.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-24 07:38:20</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=2)
-Patch for bug in uof
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 06:39:57</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 06:39:57</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:07:58</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>21</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120807</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-24 07:40:56</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>findparty page returns JavaScript errors when clicking on the LookupParty link and when the lookup fields are hidden</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-24 07:40:56</issue_when>
- <thetext>findparty page returns JavaScript errors when clicking on the LookupParty link
-and when the lookup fields are hidden. The attached patch should fix the
-problem.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-24 07:41:29</issue_when>
- <thetext>Created an attachment (id=3)
-Patch for bug in uof
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 06:44:01</issue_when>
- <thetext>Your changes are in CVS. Thanks Jacopo!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>3</attachid>
- <date>2004-02-24 07:41:29</date>
- <desc>Patch for bug in uof</desc>
- <ispatch>1</ispatch>
- <filename>findparty.ftl.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/3/findparty.ftl.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-24 07:41:29</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=3)
-Patch for bug in uof
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 06:44:01</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 06:44:01</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:08:07</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>22</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040318115951</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-24 08:52:07</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Errors in order entry when &quot;Payment Already Received&quot; type is selected.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-24 08:52:08</issue_when>
- <thetext>In Order Entry:
-when you finalize an order and, in the &quot;Order Entry Payment
-Settings&quot; page, you select the &quot;Payment Already Received&quot; type, in the
-following page you get JavaScript errors when you click over
-the links (stating that the object &quot;document.billsetupform&quot; doesn&apos;t exist);
-and so you cannot submit the order.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-26 07:08:20</issue_when>
- <thetext>
-This has been an issue for a while now. It&apos;s good to have it in the tracking system since it may not get
-fixed right away. Andy is more aware of what is happening there than I am, so he may have more
-feedback on it. -David</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-02-26 07:08:20</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-02-26 07:08:20</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P2</oldvalue>
- <newvalue>P3</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 11:59:51</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>23</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P4</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040318120006</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-24 08:56:40</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Inventory receive ignores the inventory item id field.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-24 08:56:40</issue_when>
- <thetext>In Facility Manager -&gt; Inventory receive:
-it always creates a new inventory item even if the &quot;inventory item id&quot; optional
-field is filled with an existing inventory item id.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 17:38:11</issue_when>
- <thetext>reassigned</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:38:11</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:00:06</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>24</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P4</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040318120024</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-24 09:01:59</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Receive return: it always creates serialized inventory items.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-24 09:01:59</issue_when>
- <thetext>In Facility Manager --&gt;Receive return
-
-it always creates a serialized inventory item (even if &apos;non-serialized&apos; is
-selected) and so the received quantities are lost (if more than one).</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 17:38:55</issue_when>
- <thetext>reassigned</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:38:55</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:00:24</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>25</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040318120814</delta_ts>
- <subcomponent>Accounting</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-25 14:58:53</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Permission Checks missing in various part of Accounting Manager</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-25 14:58:53</issue_when>
- <thetext>Various pages in the Accounting Manager have no view permission checking, including the billing
-account, invoice, etc pages.</thetext>
- </long_desc>
- <long_desc>
- <who>jaz</who>
- <issue_when>2004-02-25 15:36:03</issue_when>
- <thetext>I&apos;m not involved in this project.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-25 16:13:54</issue_when>
- <thetext>
-Fixed assigned to mistake.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 10:48:28</issue_when>
- <thetext>All components have a default VIEW permission based on the component configuration. Each page no
-longer needs to have the added code as long as require auth is set in the controller.xml file. The
-checkLogin event will make sure the user has the default permission for the specific component.
-Additional permissions are only necessary when not using the default permission.</thetext>
- </long_desc>
- <activity>
- <user>jaz</user>
- <when>2004-02-25 15:36:03</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>jaz</oldvalue>
- <newvalue>jonesde</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-02-25 16:13:54</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>jonesde</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 10:48:28</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 10:48:28</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:08:14</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>26</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040308115822</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-25 21:11:36</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Billing Account Errors</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-25 21:11:36</issue_when>
- <thetext>This issue was reported by Si Chen, Olivier Heintz, and some others.
-
-The following is some text from an email fro Si Chen on Jan 26, 2004; the attached patch is also from
-this email.
-
-=======================================
-Hello. After some work we have tracked down the problem with using
-billingAccount in the order manager and were able to fix it. The
-problem is stated in the order manager&apos;s billsettings.ftl, it was
-passing in &quot;EXT_BILLACT|10000&quot; for the checkoutPaymentId instead of
-separate checkoutPaymentId and billingAccountId. Olivier had suggested
-a good patch earlier which parses this form of checkoutPaymentId in the
-CheckOutEvents.java. We took a different approach and used code from
-ecommerce to pass both checkoutPaymentId and billingAccountId. We also
-fixed CheckOutEvents.java to get the billingAccountId from the request
-and associate it with the cart. Both are shown in the attached patch.
-
-One last problem: in ecommerce, in checkoutpayment.ftl, gift cards,
-credit cards, and billing accounts are all using &quot;amount_&lt;account_id&gt;&quot;
-as the name of the input fields. As a result, when the
-toggleBillingAccount javascript function tries to toggle the billing
-account selected for entering the amount to pay, it gets confused and
-cannot do this. As a result, when you use the multi-page rather than
-express checkout in ecommerce, it does not work properly. I&apos;ll be happy
-to elaborate on this if you need me to.
-=======================================</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-25 21:14:01</issue_when>
- <thetext>Created an attachment (id=4)
-Patch to fix BillingAccount issues
-</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 11:58:22</issue_when>
- <thetext>Applied patch; fixed JS in ecommerce </thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>4</attachid>
- <date>2004-02-25 21:14:01</date>
- <desc>Patch to fix BillingAccount issues</desc>
- <ispatch>1</ispatch>
- <filename>BillingAccountError.patch</filename>
- <submitter_id>3</submitter_id>
- <submitting_username>jonesde</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/4/BillingAccountError.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jonesde</user>
- <when>2004-02-25 21:14:01</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=4)
-Patch to fix BillingAccount issues
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 11:58:22</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 11:58:22</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 11:58:22</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>27</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120822</delta_ts>
- <subcomponent>WorkEffort</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-26 03:20:00</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Patch for missing pagedef file for popup template that causes lookup error (due to i18n changes)</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 03:20:00</issue_when>
- <thetext>The lookup link in New Event -&gt; Parties page is broken.
-The popup template doesn&apos;t run the envsetup script that loads the localized
-labels.
-
-PATCH: add a file named &quot;popup.xml&quot; to the template folder containing the
-following lines:
-
-&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
-&lt;page&gt;
- &lt;template-action name=&quot;/includes/envsetup.bsh&quot;/&gt;
-&lt;/page&gt;</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 07:16:55</issue_when>
- <thetext>
-I have added the popup.xml file to CVS. Thanks for sending it over Jacopo.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:16:55</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:16:55</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:08:22</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>28</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040806161040</delta_ts>
- <subcomponent>WorkEffort</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-26 03:32:11</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Added lookup link for parties in month view</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 03:32:11</issue_when>
- <thetext>Added lookup link for parties in month view.
-All the stuff was already in place... I just added the link.
-However I think this is a very useful enhancement.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 03:32:44</issue_when>
- <thetext>Created an attachment (id=5)
-Patch in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-03 08:10:20</issue_when>
- <thetext>Changed issue type as per email from Jacopo.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-08-06 16:10:40</issue_when>
- <thetext>Thanks Jacopo, this is now in CVS.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>5</attachid>
- <date>2004-02-26 03:32:44</date>
- <desc>Patch in UOF</desc>
- <ispatch>1</ispatch>
- <filename>month.ftl.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/5/month.ftl.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-26 03:32:44</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=5)
-Patch in UOF
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-03 08:10:20</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>ENHANCEMENT</oldvalue>
- <newvalue>PATCH</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:00:44</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-06 16:10:40</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-06 16:10:40</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>29</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120831</delta_ts>
- <subcomponent>WorkEffort</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-26 03:56:48</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>When creating a new event from calendar, start and end date were not filled properly in the form</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 03:56:48</issue_when>
- <thetext>When creating a new event from calendar, start and end date were not filled
-properly in the event form.
-The two patches (one for the event.ftl file and one for the event.bsh file)
-will solve this problem.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 03:59:24</issue_when>
- <thetext>Created an attachment (id=6)
-Patch for event.bsh in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 03:59:58</issue_when>
- <thetext>Created an attachment (id=7)
-Patch for event.ftl file in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 07:28:02</issue_when>
- <thetext>Your changes are in CVS, thanks Jacopo!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>6</attachid>
- <date>2004-02-26 03:59:24</date>
- <desc>Patch for event.bsh in UOF</desc>
- <ispatch>1</ispatch>
- <filename>event.bsh.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/6/event.bsh.patch</attachment_iz_url>
- </attachment>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>7</attachid>
- <date>2004-02-26 03:59:58</date>
- <desc>Patch for event.ftl file in UOF</desc>
- <ispatch>1</ispatch>
- <filename>event.ftl.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/7/event.ftl.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-26 03:59:24</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=6)
-Patch for event.bsh in UOF
-</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-02-26 03:59:58</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=7)
-Patch for event.ftl file in UOF
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:28:02</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:28:02</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:08:31</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>30</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P5</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040308175050</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jackhung</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-26 04:17:49</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Fail to approval order</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jackhung</who>
- <issue_when>2004-02-26 04:17:49</issue_when>
- <thetext>19285437[ ControlServlet.java:133:DEBUG] [[[updateactivityassign] Servlet
-Starting, doing setup- total:0.0,since last(Begin):0.0]]
-19285438[ ControlServlet.java:182:DEBUG] [[[updateactivityassign] Setup
-done, doing Event(s) and View(s)- total:0.0,since last([updateactivityas...):0.0]]
-19285440[ RequestHandler.java:200:INFO ] [Processing Request]:
-updateactivityassign
-19285744[ WfProcessMgrImpl.java:106:INFO ] [WfProcessMgr.init] : Create
-process manager (org.ofbiz.order[20030730144901] / ProcessOrder[20030730144901])
-19285890[ BshUtil.java:75 :ERROR] BSH Evaluation error.
-Sourced file: &lt;Inline eval of: approvalCode.equals(&quot;0&quot;); &gt; : Attempt to resolve
-method: equals() on undefined variable or class name: approvalCode : at Line: 1
-: in file: &lt;Inline eval of: approvalCode.equals(&quot;0&quot;); &gt; : approvalCode .equals (
-&quot;0&quot; )
-
- at bsh.UtilEvalError.toEvalError(UtilEvalError.java:82)
- at bsh.UtilEvalError.toEvalError(UtilEvalError.java:87)
- at bsh.BSHMethodInvocation.eval(BSHMethodInvocation.java:79)
- at bsh.BSHPrimaryExpression.eval(BSHPrimaryExpression.java:69)
- at bsh.Interpreter.evalParsedScript(Interpreter.java:1104)
- at bsh.Interpreter.eval(Interpreter.java:590)
- at bsh.Interpreter.eval(Interpreter.java:616)
- at bsh.Interpreter.eval(Interpreter.java:606)
- at org.ofbiz.base.util.BshUtil.eval(BshUtil.java:64)
- at
-org.ofbiz.workflow.impl.WfExecutionObjectImpl.evalBshCondition(WfExecutionObjectImpl.java:718)
- at
-org.ofbiz.workflow.impl.WfProcessImpl.getTransFrom(WfProcessImpl.java:477)
- at org.ofbiz.workflow.impl.WfProcessImpl.queueNext(WfProcessImpl.java:298)
- at
-org.ofbiz.workflow.impl.WfProcessImpl.activityComplete(WfProcessImpl.java:286)
- at org.ofbiz.workflow.impl.WfActivityImpl.complete(WfActivityImpl.java:408)
- at
-org.ofbiz.workflow.impl.WfAssignmentImpl.complete(WfAssignmentImpl.java:175)
- at
-org.ofbiz.workflow.client.WorkflowClient.complete(WorkflowClient.java:266)
- at
-org.ofbiz.workflow.client.WorkflowServices.completeAssignment(WorkflowServices.java:418)</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 12:08:46</issue_when>
- <thetext>I cannot duplicate this problem; please provide more information or we will have to close this has no
-longer an issue.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 17:50:50</issue_when>
- <thetext>reassigned</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 12:08:46</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>STARTED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 12:08:46</when>
- <field_name>op_sys</field_name>
- <field_desc>OS/Version</field_desc>
- <oldvalue>Linux</oldvalue>
- <newvalue>All</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 12:08:46</when>
- <field_name>rep_platform</field_name>
- <field_desc>Platform</field_desc>
- <oldvalue>PC</oldvalue>
- <newvalue>All</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 12:08:46</when>
- <field_name>short_desc</field_name>
- <field_desc>Summary</field_desc>
- <oldvalue>Fail to approval order </oldvalue>
- <newvalue>Fail to approval order</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:50:50</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:50:50</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>STARTED</oldvalue>
- <newvalue>NEW</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:50:50</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P2</oldvalue>
- <newvalue>P5</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>31</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120101</delta_ts>
- <subcomponent>WorkEffort</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-26 05:39:36</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Error message when you try to create new contact information under an event</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 05:39:36</issue_when>
- <thetext>An error message is returned when you try to create new contact information
-under an event: Cannot locate service by name (createWorkEffortContactMech)
-
-This is the complete message:
-
-ERROR: Could not complete the Create an email address for WorkEffort process
-[problem invoking the [createWorkEffortContactMech] service with the map named
-[context] containing [{locale=en_US, infoString=foo@bar.com, userLogin=
-[GenericEntity:UserLogin][partyId,admin(java.lang.String)][disabledDateTime,null
-()][passwordHint,null()][createdTxStamp,null()][successiveFailedLogins,null()]
-[enabled,Y(java.lang.String)][userLoginId,admin(java.lang.String)]
-[currentPassword,ofbiz(java.lang.String)][lastUpdatedTxStamp,null()]
-[lastUpdatedStamp,null()][createdStamp,null()], workEffortId=10030,
-contactMechTypeId=EMAIL_ADDRESS}]: Cannot locate service by name
-(createWorkEffortContactMech)]</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:01:01</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>32</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040409054533</delta_ts>
- <subcomponent>WorkEffort</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-26 05:50:01</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Errors that prevent adding a new phase to a project.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 05:50:01</issue_when>
- <thetext>It&apos;s impossible to add a new phase to a project. Even if you fill all the
-fields of the new phase form when you press the &apos;create&apos; button you get an
-error in the system log (however no error messages are shown in the html page).
-
-This is the complete error message:
-
-1160388[ ServiceDispatcher.java:309:ERROR] Service Error [createPhase]: ERROR:
-Could not complete the Create Project Phase process [problem creating the newEnt
-ity value: while inserting: [GenericEntity:WorkEffortAssoc][createdTxStamp,2004-
-02-26 14:44:26.096(java.sql.Timestamp)][workEffortIdTo,10034(java.lang.String)][
-workEffortIdFrom,10031(java.lang.String)][workEffortAssocTypeId,WORK_EFF_BREAKDO
-WN(java.lang.String)][lastUpdatedTxStamp,2004-02-26 14:44:26.096(java.sql.Timest
-amp)][createdStamp,2004-02-26 14:44:26.106(java.sql.Timestamp)][lastUpdatedStamp
-,2004-02-26 14:44:26.106(java.sql.Timestamp)] (SQL Exception while executing the
- following:INSERT INTO WORK_EFFORT_ASSOC (WORK_EFFORT_ID_FROM, WORK_EFFORT_ID_TO
-, WORK_EFFORT_ASSOC_TYPE_ID, SEQUENCE_NUM, FROM_DATE, THRU_DATE, LAST_UPDATED_ST
-AMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP, CREATED_TX_STAMP) VALUES (?, ?, ?, ?,
- ?, ?, ?, ?, ?, ?) ([-5005] (at 124): Missing non-NULL value))]</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-04-09 05:45:33</issue_when>
- <thetext>David Jones has fixed this problem in date 2004-04-08 (see the
-thread &quot;createphase ERROR in OFBiz 3.0 and OFBiz CVS versions&quot; in the dev-list).
-</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:01:18</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-04-09 05:45:33</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-04-09 05:45:33</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>33</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P4</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20050209023142</delta_ts>
- <subcomponent>WorkEffort</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-26 06:00:26</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>When you create a new request and you don&apos;t fill correctly all the fields no error messages are shown</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 06:00:26</issue_when>
- <thetext>When you create a new request and you don&apos;t fill correctly all the fields no
-error messages are shown.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2005-02-09 02:31:42</issue_when>
- <thetext>Fixed after the refactoring to screen widget.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:01:30</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2005-02-09 02:31:42</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2005-02-09 02:31:42</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>34</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P5</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120838</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-26 06:11:14</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Little JavaScript in &quot;find returns&quot; when lookup fields are hidden</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 06:11:14</issue_when>
- <thetext>Little JavaScript in &quot;find returns&quot; when lookup fields are hidden
-
-Patch for findReturns.ftl is attached.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 06:11:49</issue_when>
- <thetext>Created an attachment (id=8)
-Patch for findReturn.ftl in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 11:18:49</issue_when>
- <thetext>Your changes are in CVS. Thanks for sending that over.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>8</attachid>
- <date>2004-02-26 06:11:49</date>
- <desc>Patch for findReturn.ftl in UOF</desc>
- <ispatch>1</ispatch>
- <filename>findReturn.ftl.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/8/findReturn.ftl.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-26 06:11:49</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=8)
-Patch for findReturn.ftl in UOF
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 11:18:49</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 11:18:49</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:08:38</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>35</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P1</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040308103928</delta_ts>
- <subcomponent>E-Commerce</subcomponent>
- <reporter>razorb</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-26 06:18:48</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc>http://localhost:8080/ecommerce/control/product/~category_id=100/~product_id=GZ-1006</issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Single variant combo doesn&apos;t select properly</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>razorb</who>
- <issue_when>2004-02-26 06:18:48</issue_when>
- <thetext>Using the drop down menu to select a variantion i.e. LGPL does not set the
-selection on the menu. Using the swatch/images does correctly set the menu
-selection and allows adding to the basket.
-
-I suspect a little JS error somewhere for single variant items.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-26 06:52:49</issue_when>
- <thetext>
-I just reproduced this against the latest code base, appears to still be an issue with single feature type
-virtual products.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 09:54:51</issue_when>
- <thetext>Updated since this is a CVS bug and updated status</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 10:39:28</issue_when>
- <thetext>fixed JS bugs in productdetail</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-02-26 06:52:48</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-02-26 06:52:48</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P1</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 09:54:51</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>STARTED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 09:54:51</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 10:39:28</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>STARTED</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 10:39:28</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>36</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120846</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-26 23:17:51</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Facility Manager: in &apos;inventory receive&apos; the type of order is not checked and it&apos;s possible to receive a sales order if you enter its id in the &apos;purchase order id&apos; field</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-26 23:17:51</issue_when>
- <thetext>Facility Manager: in &apos;inventory receive&apos; the type of order is not checked and
-it&apos;s possible to receive a sales order if you enter its id in the &apos;purchase
-order id&apos; field.
-
-This is the patch in UOF for the receiveInventory.bsh file (pay attention that
-some days ago I&apos;ve submitted a patch for the same file against the same CVS
-release):
-
-Index: ofbiz/components/product/webapp/facility/WEB-
-INF/actions/inventory/receiveInventory.bsh
-===================================================================
-RCS file: /cvs/ofbiz/components/product/webapp/facility/WEB-
-INF/actions/inventory/receiveInventory.bsh,v
-retrieving revision 1.4
-diff -u -r1.4 receiveInventory.bsh
---- ofbiz/components/product/webapp/facility/WEB-
-INF/actions/inventory/receiveInventory.bsh 25 Aug 2003 15:28:00 -0000
- 1.4
-+++ ofbiz/components/product/webapp/facility/WEB-
-INF/actions/inventory/receiveInventory.bsh 27 Feb 2004 07:17:08 -0000
-@@ -43,6 +43,9 @@
- purchaseOrder = null;
- if (purchaseOrderId != null &amp;&amp; purchaseOrderId.length() &gt; 0) {
- purchaseOrder = delegator.findByPrimaryKey(&quot;OrderHeader&quot;, UtilMisc.toMap
-(&quot;orderId&quot;, purchaseOrderId));
-+ if (purchaseOrder != null &amp;&amp; !&quot;PURCHASE_ORDER&quot;.equals
-(purchaseOrder.getString(&quot;orderTypeId&quot;))) {
-+ purchaseOrder = null;
-+ }
- }
-
- product = null;</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-02-28 11:58:13</issue_when>
- <thetext>The patch is in CVS.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-02-28 11:58:13</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-02-28 11:58:13</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:08:46</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>37</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120856</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-27 02:05:25</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Facility Manager: error message when trying to confirm stock moves needed.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-27 02:05:25</issue_when>
- <thetext>In the Facility Manager, int the PickList -&gt; Stock Moves page, if I try to
-confirm the &quot;stock moves needed&quot; proposed by the system I get the following
-error:
-
-Error calling event: org.ofbiz.content.webapp.event.EventHandlerException: No
-rows to process
-
-And the movements are not performed.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 17:22:23</issue_when>
- <thetext>This is caused by some code that was added to display warning messages that wiped out the rowCount
-variable. The warning message loop now uses a variable names messageCount.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 17:22:23</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 17:22:23</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:08:56</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>38</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120905</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-27 02:23:36</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Facility Manager: in Edit shipment -&gt; items tab, a wrong link to EditProduct page caused a controller error.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-27 02:23:36</issue_when>
- <thetext>Facility Manager: in Edit shipment -&gt; items tab, a wrong link to EditProduct
-page caused a controller error.
-
-Patch for EditShipmentItems.ftl file is attached.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-27 02:24:16</issue_when>
- <thetext>Created an attachment (id=9)
-Patch for EditShipmentItems.ftl in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 07:38:50</issue_when>
- <thetext>Your changes are in CVS. Thanks for the patch Jacopo.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>9</attachid>
- <date>2004-02-27 02:24:16</date>
- <desc>Patch for EditShipmentItems.ftl in UOF</desc>
- <ispatch>1</ispatch>
- <filename>EditShipmentItems.ftl.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/9/EditShipmentItems.ftl.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-27 02:24:16</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=9)
-Patch for EditShipmentItems.ftl in UOF
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:38:50</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:38:50</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:09:05</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>39</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P2</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120141</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-27 04:05:34</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>SapDB problem when displaying order task list assigned to user role</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-27 04:05:34</issue_when>
- <thetext>SapDB problem when displaying order task list assigned to user role:
-if more than one order is assigned to user role, in &quot;Order List&quot; page the
-orders are shown 5 times!
-If only one order is assigned to the user role, the order is shown well (1
-time).
-
-See picture attached.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-27 04:07:00</issue_when>
- <thetext>Created an attachment (id=10)
-Bug example showing two orders waiting approval duplicated 5 times.
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>image/gif</mimetype>
- <attachid>10</attachid>
- <date>2004-02-27 04:07:00</date>
- <desc>Bug example showing two orders waiting approval duplicated 5 times.</desc>
- <ispatch></ispatch>
- <filename>order_list_bug.GIF</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/10/order_list_bug.GIF</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-27 04:07:00</when>
- <field_name>attachments.thedata</field_name>
- <field_desc>Attachment Data</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=10)
-Bug example showing two orders waiting approval duplicated 5 times.
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:01:41</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>40</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20050209023003</delta_ts>
- <subcomponent>WorkEffort</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-27 07:27:15</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Party lookup with empty fields returns only one person repeated many times (= number of persons).</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-27 07:27:15</issue_when>
- <thetext>If, in Party lookup, you perform a lookup with empty fields (all records),
-returns only one person repeated many times (= number of persons).
-I suspect that the problem is in the &quot;lookupParty&quot; simple method in common
-component.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2005-02-09 02:30:03</issue_when>
- <thetext>Fixed changing the way the lookup is implemented (see Jira issue OFBIZ-114).</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:01:50</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2005-02-09 02:30:03</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2005-02-09 02:30:03</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>41</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120912</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-27 08:53:04</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Facility Manager: in Edit shipment -&gt; items tab, a wrong link to EditProduct caused a controller error (same as issue #38)</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-27 08:53:04</issue_when>
- <thetext>Facility Manager: in View shipment tab, a wrong link to EditProduct
-page caused a controller error (same as issue #38).
-
-Patch for ViewShipmentItemInfo.ftl file is attached.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-27 08:53:50</issue_when>
- <thetext>Created an attachment (id=11)
-Patch for file ViewShipmentItemInfo.ftl in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 07:41:15</issue_when>
- <thetext>Your changes are now in CVS. Thanks for sending those over Jacopo.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>11</attachid>
- <date>2004-02-27 08:53:50</date>
- <desc>Patch for file ViewShipmentItemInfo.ftl in UOF</desc>
- <ispatch>1</ispatch>
- <filename>ViewShipmentItemInfo.ftl.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/11/ViewShipmentItemInfo.ftl.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-27 08:53:50</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=11)
-Patch for file ViewShipmentItemInfo.ftl in UOF
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:41:15</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:41:15</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:09:12</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>42</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P4</priority>
- <resolution>WONTFIX</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040630193328</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-28 22:34:42</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In shipment, the following error message appears: &quot;Applet Package Weight Reader notinited&quot;</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-28 22:34:42</issue_when>
- <thetext>In shipment, the following error message appears: &quot;Applet Package Weight Reader
-notinited&quot;.
-I think the problem is caused by the fact that the class ShipmentScaleApplet is
-not built in the ant task.
-Was this done intentionally? (I think this applet tries to connect to a scale
-device connected to a serial port and so probably this could cause some
-problems...).</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 17:39:52</issue_when>
- <thetext>reassigned; I will comment out the applet code until this is finished</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-06-30 19:33:28</issue_when>
- <thetext>The applet is going to be replaced with a think client shipment station UI</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:39:52</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:01:59</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:33:28</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:33:28</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>WONTFIX</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>43</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120921</delta_ts>
- <subcomponent>E-Commerce</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-02-28 22:46:49</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In &quot;Create Return&quot;, select-all checkbox doesn&apos;t work due to wrong form name.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-28 22:46:49</issue_when>
- <thetext>In &quot;Create Return&quot;, select-all checkbox doesn&apos;t work due to wrong form name.
-
-Patch attached for requestreturn.ftl in Unified Output Format.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-28 22:47:40</issue_when>
- <thetext>Created an attachment (id=12)
-Patch attached for requestreturn.ftl in UOF.
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 07:48:30</issue_when>
- <thetext>Your changes are in CVS. Thanks for fixing that.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>12</attachid>
- <date>2004-02-28 22:47:39</date>
- <desc>Patch attached for requestreturn.ftl in UOF.</desc>
- <ispatch>1</ispatch>
- <filename>requestreturn.ftl.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/12/requestreturn.ftl.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-02-28 22:47:40</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=12)
-Patch attached for requestreturn.ftl in UOF.
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:48:30</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 07:48:30</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:09:21</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>44</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P4</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040229030013</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-02-29 03:00:13</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Packages: ShipmentPackage&apos;s weight automatically updated when ShipmentPackageContent entries are added/deleted (weight taken from the Product entity).</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-29 03:00:13</issue_when>
- <thetext>Packages: ShipmentPackage&apos;s weight automatically updated when
-ShipmentPackageContent entries are added/deleted (weight taken from the Product
-entity).</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>45</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P1</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040301155709</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-02-29 06:17:33</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In orderview page, if you select the &quot;QuickShip order link&quot; you get a controller error.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-02-29 06:17:33</issue_when>
- <thetext>In orderview page (/ordermgr/control/orderview), if you select the &quot;QuickShip
-order link&quot; you get a controller error:
-
-org.ofbiz.content.webapp.control.RequestHandlerException: Unknown request
-[quickShipOrderMultiFacility]; this request does not exist or cannot be called
-directly.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 12:11:07</issue_when>
- <thetext>I&apos;ll get on this...</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-01 15:57:09</issue_when>
- <thetext>Changed the default behavior for this; also added request-map and service defs for the quick ship from
-multi facilites.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 12:11:07</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>STARTED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 15:57:09</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>STARTED</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-01 15:57:09</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>46</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040806152631</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-02 05:13:01</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Patch for multiple inventory facility reservation</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-02 05:13:01</issue_when>
- <thetext>Patch for multiple inventory facility reservation:
-the intent of this is to perform reservation only if all items are available in
-one facility: that, I think, is the declared behaviour, and what is checked
-with the isInventoryAvailable method.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-02 05:13:49</issue_when>
- <thetext>Created an attachment (id=13)
-Patch for ProductStoreWorker.java in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-08-06 15:26:31</issue_when>
- <thetext>Thanks Jacopo, your patch is now in CVS.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>13</attachid>
- <date>2004-03-02 05:13:49</date>
- <desc>Patch for ProductStoreWorker.java in UOF</desc>
- <ispatch>1</ispatch>
- <filename>ProductStoreWorker.java.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/13/ProductStoreWorker.java.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-03-02 05:13:49</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=13)
-Patch for ProductStoreWorker.java in UOF
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:02:10</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-06 15:26:31</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-06 15:26:31</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>47</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040323221326</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-02 06:06:51</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Facility -&gt; Shipment: patch for JavaScript error introduced during i18n process.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-02 06:06:51</issue_when>
- <thetext>Facility -&gt; Shipment: patch for JavaScript error introduced during i18n process.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-02 06:07:51</issue_when>
- <thetext>Created an attachment (id=14)
-Patch for AddItemsFromOrder.ftl file in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 17:42:45</issue_when>
- <thetext>reassigned</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-23 22:13:26</issue_when>
- <thetext>This bug has been fixed by the code for the new feature regarding shipment
-plans.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>14</attachid>
- <date>2004-03-02 06:07:51</date>
- <desc>Patch for AddItemsFromOrder.ftl file in UOF</desc>
- <ispatch>1</ispatch>
- <filename>AddItemsFromOrder.ftl.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/14/AddItemsFromOrder.ftl.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-03-02 06:07:51</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=14)
-Patch for AddItemsFromOrder.ftl file in UOF
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:42:45</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:02:18</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-03-23 22:13:26</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-03-23 22:13:26</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>48</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P2</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120228</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-02 06:28:37</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Facility -&gt; Shipment -&gt; Items: delete shipment item link returns a constraint violation error.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-02 06:28:37</issue_when>
- <thetext>Facility -&gt; Shipment -&gt; Items: delete shipment item link returns a constraint
-violation error:
-
-The following errors occurred:
-ERROR: Could not complete the Delete ShipmentItem process [problem removing the
-lookedUpValue value: Exception while deleting the following entity:
-[GenericEntity:ShipmentItem][shipmentId,10010(java.lang.String)]
-[shipmentItemSeqId,00001(java.lang.String)] (SQL Exception while executing the
-following:DELETE FROM SHIPMENT_ITEM WHERE SHIPMENT_ID=? AND
-SHIPMENT_ITEM_SEQ_ID=? (Integrity constraint violation ITEM_ISS_SHITM table:
-ITEM_ISSUANCE in statement [DELETE FROM SHIPMENT_ITEM WHERE SHIPMENT_ID=? AND
-SHIPMENT_ITEM_SEQ_ID=?]))]
-
-In my opinion, the delete shipment item link should perform something like this
-(instead of barely trying to remove the ShipmentItem entry): it should remove
-the item issuances, recreate the reservations and then remove the shipment item.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:02:28</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>49</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040528001027</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-03 03:11:18</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Facility -&gt; Receive PO: at now it&apos;s possible to receive multiple times the same shipment items. This is a partial patch for this problem.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-03 03:11:18</issue_when>
- <thetext>Facility -&gt; Receive PO: at now it&apos;s possible to receive multiple times the same
-shipment items. This is a partial patch for this problem. With the attached
-patch the shipment already delivered (or cancelled) are not shown (and so the
-user cannot receive them again).
-In order to completely fix this issue the best solution is, in my opinion, to
-automatically update the shipment status to &quot;delivered&quot; when the user receives
-an item: this could be done modifying the service
-group &quot;receiveInventoryProduct&quot; by adding to it the &quot;updateShipment&quot; service
-(to update the shipment status). However I&apos;m going to add this comments to a
-new &quot;DEFECT&quot; issue.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-03 03:12:11</issue_when>
- <thetext>Created an attachment (id=15)
-Patch for file receiveInventory.bsh in UOF.
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-28 00:10:27</issue_when>
- <thetext>This is now in CVS, thanks for sending it over Jacopo.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>15</attachid>
- <date>2004-03-03 03:12:11</date>
- <desc>Patch for file receiveInventory.bsh in UOF.</desc>
- <ispatch>1</ispatch>
- <filename>receiveInventory.bsh.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/15/receiveInventory.bsh.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-03-03 03:12:11</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=15)
-Patch for file receiveInventory.bsh in UOF.
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:02:37</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-28 00:10:27</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-28 00:10:27</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>50</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040528000924</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-03 03:15:23</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Facility -&gt; Receive PO: at now it&apos;s possible to receive multiple times the same shipment items.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-03 03:15:24</issue_when>
- <thetext>Facility -&gt; Receive PO: at now it&apos;s possible to receive multiple times the same
-shipment items.
-This problem was partially fixed by the patch attached to issue #49.
-With that patch the shipment already delivered (or cancelled) are not shown
-(and so the user cannot receive them again).
-In order to completely fix this issue the best solution is, in my opinion, to
-automatically update the shipment status to &quot;delivered&quot; when the user receives
-an item: this could be done modifying the service
-group &quot;receiveInventoryProduct&quot; by adding to it the &quot;updateShipment&quot; service
-(to update the shipment status). However I&apos;m going to add this comments to a
-new &quot;DEFECT&quot; issue.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-28 00:09:24</issue_when>
- <thetext>The patch is in, now just need to update the shipment status as mentioned in the description.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:02:49</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>51</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>REMIND</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040811004716</delta_ts>
- <subcomponent>Startup</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-03 06:37:30</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Several SapDB error messages are generated at startup when entities are created.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-03 06:37:30</issue_when>
- <thetext>Several SapDB error messages are generated at startup when entities are created.
-The messages appear during the indices&apos; generation phase, not for all entities
-(maybe 5-10%); here is an example:
-
-147042[ DatabaseUtil.java:319:ERROR] Could not create foreign key indices
-for entity &quot;EftAccount&quot;: SQL Exception while executing the following:
-CREATE INDEX EFTACCT_PMETH ON EFT_ACCOUNT (PAYMENT_METHOD_ID)
-Error was: com.sap.dbtech.jdbc.exceptions.DatabaseException: [-7055] (at 44):
-Column(s) already indexed:EFTACCT_PMETH
-SQL Exception while executing the following:
-CREATE INDEX EFTACCT_PADDR ON EFT_ACCOUNT (CONTACT_MECH_ID)
-Error was: com.sap.dbtech.jdbc.exceptions.DatabaseException: [-7055] (at 44):
-Column(s) already indexed:EFTACCT_PADDR</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-08-11 00:47:16</issue_when>
- <thetext>I&apos;ve created a new issue (OFBIZ-1) for this in Jira; in it you will find a lot
-of details.
-</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:03:00</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-08-11 00:47:16</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-08-11 00:47:16</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>REMIND</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>52</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040308121509</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-04 03:14:08</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Billing accounts selectable by users during order entry are not correctly filtered out.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-04 03:14:08</issue_when>
- <thetext>Billing accounts selectable by users as payment methods during order entry are
-not correctly filtered out: removed billing accounts are also shown (i.e.
-billing accounts with thru date &lt; now).</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 12:15:09</issue_when>
- <thetext>Billing accounts are now filtered by date so expired accounts no longer show on order manager order
-entry and the ecommerce checkout pages</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 12:15:09</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 12:15:09</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 12:15:09</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>53</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040528010450</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-05 06:01:05</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In Shipment: it&apos;s possible to issue 0 quantities from AddItemsFormOrder page.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-05 06:01:05</issue_when>
- <thetext>In Shipment: it&apos;s possible to issue 0 quantities from AddItemsFormOrder page
-(an ItemIssuance record is created with 0 quantity).
-I think this should be avoided by submitting only quantities &gt; 0.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-28 01:04:50</issue_when>
- <thetext>Now checks to see if quantity is empty or 0 when issuing OIIRs to the shipment.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:03:13</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-28 01:04:50</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-28 01:04:50</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>54</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P1</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040630124239</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-05 06:20:02</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In Shipment: if you enter a non numeric value (such as null quantity) in the issue field the program returns a bad error.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-05 06:20:02</issue_when>
- <thetext>In Shipment: if you enter a non numeric value (such as null quantity) in the
-issue field the program returns a bad error.
-See also issue#53.
-I&apos;m running SapDB and after this error I need to restart OFBiz because in every
-page I receive SQL errors like the following:
-
-Target exception: org.ofbiz.entity.GenericDataSourceException: SQL Exception
-occurred on commit (Cannot commit a transactional connection: See JDBC 2.0
-Optional Package Specification section 7.1 (p25))
-BSF info: ..\ofbiz\components\content\webapp\content\WEB-
-INF\actions\includes\envsetup.bsh at line: 0 column: 0)</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-06-30 12:42:39</issue_when>
- <thetext>Applied patch which fixes a bug in the service multi event handler</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:03:23</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 12:42:39</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 12:42:39</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>55</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040323221851</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-05 06:25:34</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In shipment, it&apos;s possible to issue to shipment items with negative reservations (atp &lt; 0); as a consequence of this, also the inventory items&apos; quantity on hand can be negative.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-05 06:25:34</issue_when>
- <thetext>I&apos;ve noticed that, in shipment, it&apos;s possible to issue to shipment items with
-negative reservations (atp &lt; 0); as a consequence of this, also the inventory
-items&apos; quantity on hand can be negative.
-In my opinion, in this situation at least a warning message should be
-provided.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-23 22:18:51</issue_when>
- <thetext>In &quot;Order Items&quot; page a new column has been added that tells users if they are
-issuing negative reservations and the default issuance value is also
-decremented by this quantity.
-However is still possible to override this value and force an issuance for a
-negative reservation.
-
-</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:03:32</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-03-23 22:18:51</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-03-23 22:18:51</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>56</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>WONTFIX</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>PC</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040308173638</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>vivalinux</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-08 14:07:32</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc>http://&lt;ofbiz_root_url&gt;/partymgr/control/findparty</issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Selecting &quot;Show All Records&quot; displays all names as &quot;(Not selected)&quot;</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>vivalinux</who>
- <issue_when>2004-03-08 14:07:32</issue_when>
- <thetext>The findparty.bsh constructs a dynamic view tailored to the search fields
-submited by the lookupparty form. Since selecting all does not give a hint about
-which fields the client is interested in, the findparty.bsh fails to include any
-of the name (firstName, lastName, groupName) fields.
-
-The can be corrected with the patch that follows or handling the select all
-records as yet another case. I think, I&apos;ll side with simplicity, and sacrify
-efficiency ....
-
-Hope this helps.
-
-
-Index: components/party/webapp/partymgr/WEB-INF/actions/party/findparty.bsh
-===================================================================
-RCS file:
-/cvs/ofbiz/components/party/webapp/partymgr/WEB-INF/actions/party/findparty.bsh,v
-retrieving revision 1.13
-diff -u -r1.13 findparty.bsh
---- components/party/webapp/partymgr/WEB-INF/actions/party/findparty.bsh 27 Jan
-2004 19:44:36 -0000 1.13
-+++ components/party/webapp/partymgr/WEB-INF/actions/party/findparty.bsh 8 Mar
-2004 22:06:24 -0000
-@@ -100,8 +100,15 @@
-
- // default view settings
- dynamicView.addMemberEntity(&quot;PT&quot;, &quot;Party&quot;);
-+ dynamicView.addMemberEntity(&quot;PG&quot;, &quot;PartyGroup&quot;);
-+ dynamicView.addMemberEntity(&quot;PP&quot;, &quot;Person&quot;);
- dynamicView.addAlias(&quot;PT&quot;, &quot;partyId&quot;);
- dynamicView.addAlias(&quot;PT&quot;, &quot;partyTypeId&quot;);
-+ dynamicView.addAlias(&quot;PG&quot;, &quot;groupName&quot;);
-+ dynamicView.addAlias(&quot;PP&quot;, &quot;firstName&quot;);
-+ dynamicView.addAlias(&quot;PP&quot;, &quot;lastName&quot;);
-+ dynamicView.addViewLink(&quot;PT&quot;,&quot;PG&quot;,true,UtilMisc.toList(new
-ModelKeyMap(&quot;partyId&quot;, &quot;partyId&quot;)));
-+ dynamicView.addViewLink(&quot;PT&quot;,&quot;PP&quot;,true,UtilMisc.toList(new
-ModelKeyMap(&quot;partyId&quot;, &quot;partyId&quot;)));
- dynamicView.addRelation(&quot;one-nofk&quot;, &quot;&quot;, &quot;PartyType&quot;,
-ModelKeyMap.makeKeyMapList(&quot;partyTypeId&quot;));
- dynamicView.addRelation(&quot;many&quot;, &quot;&quot;, &quot;UserLogin&quot;,
-ModelKeyMap.makeKeyMapList(&quot;partyId&quot;));
-
-@@ -143,11 +150,6 @@
- if (groupName != null &amp;&amp; groupName.length() &gt; 0) {
- paramList = paramList + &quot;&amp;groupName=&quot; + groupName;
-
-- // modify the dynamic view
-- dynamicView.addMemberEntity(&quot;PG&quot;, &quot;PartyGroup&quot;);
-- dynamicView.addAlias(&quot;PG&quot;, &quot;groupName&quot;);
-- dynamicView.addViewLink(&quot;PT&quot;, &quot;PG&quot;, Boolean.FALSE,
-ModelKeyMap.makeKeyMapList(&quot;partyId&quot;));
--
- // add the expr
- andExprs.add(new EntityExpr(&quot;groupName&quot;, true, EntityOperator.LIKE,
-&quot;%&quot;+groupName+&quot;%&quot;, true));
- }
-@@ -160,14 +162,6 @@
- firstName = request.getParameter(&quot;firstName&quot;);
- lastName = request.getParameter(&quot;lastName&quot;);
-
-- // modify the dynamic view
-- if ((firstName != null &amp;&amp; firstName.length() &gt; 0) || (lastName != null &amp;&amp;
-lastName.length() &gt; 0)) {
-- dynamicView.addMemberEntity(&quot;PE&quot;, &quot;Person&quot;);
-- dynamicView.addAlias(&quot;PE&quot;, &quot;firstName&quot;);
-- dynamicView.addAlias(&quot;PE&quot;, &quot;lastName&quot;);
-- dynamicView.addViewLink(&quot;PT&quot;, &quot;PE&quot;, Boolean.FALSE,
-ModelKeyMap.makeKeyMapList(&quot;partyId&quot;));
-- }
--
- // filter on firstName
- if (firstName != null &amp;&amp; firstName.length() &gt; 0) {
- paramList = paramList + &quot;&amp;firstName=&quot; + firstName;
-@@ -319,6 +313,12 @@
- List orderBy = new ArrayList();
- fieldsToSelect.add(&quot;partyId&quot;);
- fieldsToSelect.add(&quot;partyTypeId&quot;);
-+ fieldsToSelect.add(&quot;firstName&quot;);
-+ fieldsToSelect.add(&quot;lastName&quot;);
-+ fieldsToSelect.add(&quot;groupName&quot;);
-+ orderBy.add(&quot;-partyTypeId&quot;);
-+ orderBy.add(&quot;lastName&quot;);
-+ orderBy.add(&quot;groupName&quot;);
-
- // UserLogin
- if (userLoginId != null &amp;&amp; userLoginId.length() &gt; 0) {
-@@ -327,14 +327,11 @@
-
- // Person
- if ((firstName != null &amp;&amp; firstName.length() &gt; 0) || (lastName != null
-&amp;&amp; lastName.length() &gt; 0)) {
-- fieldsToSelect.add(&quot;firstName&quot;);
-- fieldsToSelect.add(&quot;lastName&quot;);
- orderBy.add(&quot;lastName&quot;);
- orderBy.add(&quot;firstName&quot;);
- }
- // PartyGroup
- if (groupName != null &amp;&amp; groupName.length() &gt; 0) {
-- fieldsToSelect.add(&quot;groupName&quot;);
- orderBy.add(&quot;groupName&quot;);
- }
- // RoleType
-Index: components/party/webapp/partymgr/party/findparty.ftl
-===================================================================
-RCS file: /cvs/ofbiz/components/party/webapp/partymgr/party/findparty.ftl,v
-retrieving revision 1.10
-diff -u -r1.10 findparty.ftl
---- components/party/webapp/partymgr/party/findparty.ftl 1 Mar 2004 14:43:27
--0000 1.10
-+++ components/party/webapp/partymgr/party/findparty.ftl 8 Mar 2004 22:06:24 -0000
-@@ -212,13 +212,12 @@
- &lt;/table&gt;
- &lt;input type=&quot;image&quot; src=&quot;/images/spacer.gif&quot;
-onClick=&quot;javascript:document.lookupparty.submit();&quot;&gt;
- &lt;/form&gt;
--&lt;#if requestParameters.hideFields?default(&quot;N&quot;) != &quot;Y&quot;&gt;
- &lt;script language=&quot;JavaScript&quot;&gt;
- &lt;!--//
- document.lookupparty.partyId.focus();
- //--&gt;
- &lt;/script&gt;
--&lt;/#if&gt;
-+
- &lt;#if partyList?exists&gt;
- &lt;br&gt;
- &lt;table border=0 width=&apos;100%&apos; cellspacing=&apos;0&apos; cellpadding=&apos;0&apos;
-class=&apos;boxoutside&apos;&gt;
-@@ -292,21 +291,13 @@
- &lt;/td&gt;
- &lt;td&gt;
- &lt;div class=&quot;tabletext&quot;&gt;
-- &lt;#if partyRow.containsKey(&quot;lastName&quot;)&gt;
- &lt;#if partyRow.lastName?has_content&gt;
- ${partyRow.lastName}&lt;#if
-partyRow.firstName?has_content&gt;, ${partyRow.firstName}&lt;/#if&gt;
-- &lt;#else&gt;
-- (No Name Found)
-- &lt;/#if&gt;
-- &lt;#elseif partyRow.containsKey(&quot;groupName&quot;)&gt;
-- &lt;#if partyRow.groupName?has_content&gt;
-+ &lt;#elseif partyRow.groupName?has_content&gt;
- ${partyRow.groupName}
- &lt;#else&gt;
-- (No Name Found)
-+ (Not Selected)
- &lt;/#if&gt;
-- &lt;#else&gt;
-- (Not Selected)
-- &lt;/#if&gt;
- &lt;/td&gt;
- &lt;#if extInfo?default(&quot;&quot;) == &quot;P&quot;&gt;
- &lt;td&gt;&lt;div
-class=&quot;tabletext&quot;&gt;${partyRow.postalCode?if_exists}&lt;/div&gt;&lt;/td&gt;</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 17:36:38</issue_when>
- <thetext>This page has been changed from using the left joins in the dynamic view. Using left joins performs too
-poorly for actual use. This patch has been rejected; a new task will be opened for fixing the problem of
-the name not being displayed.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:36:38</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:36:38</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>WONTFIX</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>57</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P4</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040308174641</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>ajzeneski</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-08 17:36:18</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Find Party - Show all does not show name</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 17:36:18</issue_when>
- <thetext>The name is not displayed when selecting show all in the party manager.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-03-08 17:46:41</issue_when>
- <thetext>reassigned</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-08 17:46:41</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>58</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040308185722</delta_ts>
- <subcomponent>Content</subcomponent>
- <reporter>vivalinux</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-08 18:57:22</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Inherited hidden fields overide child fields when they have use-when</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>vivalinux</who>
- <issue_when>2004-03-08 18:57:22</issue_when>
- <thetext>In working with inherited forms I noticed that hidden fields are hard
-to override if the overriding field has a use-when attribute:
-
- Since the HtmlFormRenderer gives precedence to hidden fields, and new
-fields with &quot;use-when&quot; are only placed in front of existing fields
-but not merged with, the resulting behavior is that hidden fields of
-parent forms always get rendered even when the use-when condition is
-true. This causes the hidden field to take precedence over the user
-input when the form is submitted.
-
- Here is a posible solution:
-
-Index: components/content/src/org/ofbiz/content/widget/form/ModelForm.java
-===================================================================
-RCS file:
-/usr/local/cvsrepos/newriverbiz/components/content/src/org/ofbiz/content/widget/form/ModelForm.java,v
-retrieving revision 1.1.1.4
-diff -u -r1.1.1.4 ModelForm.java
---- components/content/src/org/ofbiz/content/widget/form/ModelForm.java
-2004/01/08 14:19:55 1.1.1.4
-+++ components/content/src/org/ofbiz/content/widget/form/ModelForm.java
-2004/01/29 20:23:20
-@@ -277,15 +277,25 @@
- public ModelFormField addUpdateField(ModelFormField modelFormField) {
- if (!modelFormField.isUseWhenEmpty()) {
- // is a conditional field, add to the List but don&apos;t worry about
-the Map
-- //for adding to list, see if there is another field with that name
-in the list and if so, put it before that one
-+ //for adding to list, see if there is another field with that name
-+ //in the list and if so, put it before that one
- boolean inserted = false;
- for (int i = 0; i &lt; this.fieldList.size(); i++) {
- ModelFormField curField = (ModelFormField) this.fieldList.get(i);
-+ // BUG FIX: parent hidden fields are left and rendered even when they
-+ // are overriden with fields that have a use-when
- if (curField.getName() != null &amp;&amp;
-curField.getName().equals(modelFormField.getName())) {
-- this.fieldList.add(i, modelFormField);
-- inserted = true;
-- break;
-+ if ((curField.getFieldInfo().getFieldType() !=
-ModelFormField.FieldInfo.HIDDEN) &amp;&amp;
-+ (curField.getFieldInfo().getFieldType() != ModelFormField.FieldInfo.IGNORED)) {
-+ this.fieldList.add(i, modelFormField);
-+ inserted = true;
-+ break;
-+ } else {
-+ curField.mergeOverrideModelFormField(modelFormField);
-+ break;
-+ }
- }
-+ //End of BUG fix
- }
- if (!inserted) {
- this.fieldList.add(modelFormField);</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>59</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P1</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040318120354</delta_ts>
- <subcomponent>Workflow</subcomponent>
- <reporter>mbennani</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-09 06:47:17</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Serious Problem in Sub-flow Implementation: in-Memory Requester Used!!</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>mbennani</who>
- <issue_when>2004-03-09 06:47:17</issue_when>
- <thetext>I am running ofbiz almost v.3 :-) (image from late 2003 from cvs).
-(subflow implementation did not change since 1.2 anyways, I believe)
-
-Quick Description:
-------------------
-Subflows are using the in-memory requester object which
-does not persist over server re-starts. This is serious one guys.
-
-More Description (Scenario):
----------------------------
-I have a main process with 3 steps(step1,step2-subflow,step3). A subflow
-process being the second step. This second step calls another process that I
-call sub. sub has 2 simple steps (substep1,substep2).
-
-Now, in normal time (i.e no server restart), it all works fine and my main
-process runs fine, calls the subflow, subflow runs, the call returns and my
-step3 of the main process runs successfully and main completes fine.
-
-The problem arises when say I run step 1 of main process, subflow gets
-initiated, substep1 is executed, and before substep2 is executed, I stop the
-server (faking a server problem..., connection lost...whatever).
-When I restart the server, the subflow resumes at substep2 which executes fine,
-and eventually completes the subflow process. But, step-subflow activity in the
-workeffort table still shows WF_RUNNING. Therefore, my main process is hanging
-there and will never move along. The waitForResult() is not executed anymore
-after server restart.
-This is happening in WfActivitySubFlowImplementation on runService.
-
-Even More Details, code wise, if you want to look at it:
--------------------------------------------------------
-In a normal scenario (no server stopped), the runService of
-WfActivitySubFlowImplementation eventually calls the runSync in WorkflowEngine
-and then waitForResult. I put a system out message in the waiter class and I
-can see my message being displayed in the console forever (&quot;waiting...&quot;), until
-the subflow process finishes. And that&apos;s ok, that&apos;s what we want. When the
-subflow process finishes, the call is returned back to the runService in
-WfActivitySubFlowImplementation() and the setComplete is called, which changes
-the status of my step2-subflow activity in the main process to WF_COMPLETED to
-advance the main process. It also calls setResults() to propagate the results
-from the subflow up to the main process.
-
-BUT, now if I stop my server during that wait, and restart it the call never
-reachs the setComplete nor the setResults, making therefore my main process
-unusable anymore.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:03:54</when>
- <field_name>op_sys</field_name>
- <field_desc>OS/Version</field_desc>
- <oldvalue>Windows 2000</oldvalue>
- <newvalue>All</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:03:54</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>60</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040707152609</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 07:09:04</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Replace simplistic caching with complex reverse dependency resolver</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:09:04</issue_when>
- <thetext>This patch removes all simple caching from GenericDelegator, and replaces
-it with a stand-alone class, that handles all entity cache management. It
-uses new features in the entity model, that keeps track of view entities
-that are referenced by regular entities. As entities are updated, all
-cached lists of views or condition caches are cleared.
-
-With this patch applied, view entities can be cached, without worry that
-they will become stale. Which then allows very complex views to be
-created, that emulate complex code patterns, while still allowing for
-caching. This can speed up code tremendously.
-
-Additionally, since cache clearing now works, it almost always makes more
-sense to use the cache variation of the methods.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:14:24</issue_when>
- <thetext>Created an attachment (id=16)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 15:44:46</issue_when>
- <thetext>This patch is on hold, until some other patches are committed. Some of them
-need to have bugs filed, which I am working on. Plus, this patch needs to be
-updated to the latest code base(not a big task, done locally).</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-07 15:26:09</issue_when>
- <thetext>This is now in cvs.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>16</attachid>
- <date>2004-03-09 07:14:24</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>EntityCache.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/16/EntityCache.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:14:24</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=16)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 15:44:46</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>STARTED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:01</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-07-07 15:26:09</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>STARTED</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-07-07 15:26:09</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>61</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040422222023</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-09 07:18:26</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Allow for easier extension of this class.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:18:26</issue_when>
- <thetext>This patch makes a protected writeValues() method, which allows sub-classes
-to redirect the output to other places, as needed.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:18:49</issue_when>
- <thetext>Created an attachment (id=17)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-22 22:20:23</issue_when>
- <thetext>Applied the patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>17</attachid>
- <date>2004-03-09 07:18:49</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>EntitySaxReader-extension.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/17/EntitySaxReader-extension.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:18:49</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=17)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:20:23</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:20:23</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>62</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040422223418</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-09 07:34:07</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Allow for UPPER() and LOWER() sorting</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:34:07</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:34:26</issue_when>
- <thetext>Created an attachment (id=18)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-22 22:34:18</issue_when>
- <thetext>Applied patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>18</attachid>
- <date>2004-03-09 07:34:26</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>EntityUtil-UPPER_LOWER.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/18/EntityUtil-UPPER_LOWER.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:34:26</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=18)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:34:18</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:34:18</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>63</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429160209</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-09 07:36:19</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add support for turning off schemas completely</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:36:19</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:36:42</issue_when>
- <thetext>Created an attachment (id=19)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:02:09</issue_when>
- <thetext>Applied this patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>19</attachid>
- <date>2004-03-09 07:36:42</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>use-schemas.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/19/use-schemas.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:36:42</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=19)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:02:09</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:02:09</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>64</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040422222810</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-09 07:43:55</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Make the code look like the rest of the file.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:43:55</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:44:21</issue_when>
- <thetext>Created an attachment (id=20)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-22 22:28:10</issue_when>
- <thetext>Applied patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>20</attachid>
- <date>2004-03-09 07:44:21</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>SqlJdbcUtil-Cast.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/20/SqlJdbcUtil-Cast.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:44:21</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=20)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:28:10</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:28:10</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>65</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429163146</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 07:46:14</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add java.util.Date support.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:46:14</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:46:39</issue_when>
- <thetext>Created an attachment (id=21)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:31:46</issue_when>
- <thetext>Applied the patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>21</attachid>
- <date>2004-03-09 07:46:39</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>SqlJdbcUtil-Java_Util_Date.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/21/SqlJdbcUtil-Java_Util_Date.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:46:39</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=21)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:03</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:31:45</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:31:45</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>66</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040422221943</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-09 07:47:46</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Use UtilValidate.isNotEmpty.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:47:46</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:48:06</issue_when>
- <thetext>Created an attachment (id=22)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-22 22:19:43</issue_when>
- <thetext>Applied patch, which uses UtilValidate.isNotEmpty in SqlJdbcUtil.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>22</attachid>
- <date>2004-03-09 07:48:06</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>SqlJdbcUtil-UtilValidate.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/22/SqlJdbcUtil-UtilValidate.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:48:06</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=22)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:19:43</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:19:43</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>67</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429161604</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 07:49:20</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add support for &lt;constraint&gt; on relations and views.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:49:20</issue_when>
- <thetext>When defining a view or relation, you can now constrain the returned
-values to those that match an EntityCondition. This is really helpful
-for complex views.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:49:42</issue_when>
- <thetext>Created an attachment (id=23)
-The patch
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>23</attachid>
- <date>2004-03-09 07:49:42</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>model-constraint.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/23/model-constraint.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:49:42</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=23)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:04</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>68</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040423074926</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-09 07:51:20</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Use a NumberFormat for casting number objects to strings.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:51:20</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:51:40</issue_when>
- <thetext>Created an attachment (id=24)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-23 07:49:26</issue_when>
- <thetext>Applied patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>24</attachid>
- <date>2004-03-09 07:51:40</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>GenericEntity-NumberFormat.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/24/GenericEntity-NumberFormat.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:51:40</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=24)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-23 07:49:26</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-23 07:49:26</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>69</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040423075223</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-09 07:52:20</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add addToXmlElement method</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:52:20</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:52:42</issue_when>
- <thetext>Created an attachment (id=25)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-23 07:52:23</issue_when>
- <thetext>Applied patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>25</attachid>
- <date>2004-03-09 07:52:42</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>GenericEntity-addToXmlElement.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/25/GenericEntity-addToXmlElement.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:52:42</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=25)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-23 07:52:23</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-23 07:52:23</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>70</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040422221512</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-09 07:54:40</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Fix modelEntity dereferencing</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:54:40</issue_when>
- <thetext>When GenericEntities have been deserialized, modelEntity will be null.
-getModelEntity() should be called, to repopulate it.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:54:57</issue_when>
- <thetext>Created an attachment (id=26)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-22 22:15:12</issue_when>
- <thetext>Applied patch, plus fixed it in a few other areas.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>26</attachid>
- <date>2004-03-09 07:54:57</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>GenericEntity-getModelEntity.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/26/GenericEntity-getModelEntity.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:54:57</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=26)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:15:12</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:15:12</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>71</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P4</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501214447</delta_ts>
- <subcomponent>Content</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 07:56:46</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Factor out the code</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:56:46</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 07:57:40</issue_when>
- <thetext>Created an attachment (id=27)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:51</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 06:06:43</issue_when>
- <thetext>Not adding this patch, breaks the Server Stats Since Start page in WebTools, and not totally sure the
-cleanup is worth it yet.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-05-01 21:44:47</issue_when>
- <thetext>I&apos;ll fix that page then, and submit a revised patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>27</attachid>
- <date>2004-03-09 07:57:40</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>ServerHitBin-factor.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/27/ServerHitBin-factor.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 07:57:40</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=27)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:02</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:51</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:07:05</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P2</oldvalue>
- <newvalue>P4</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>72</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040422223139</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-09 08:04:05</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add a matches(condition) helper method.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:04:05</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:04:31</issue_when>
- <thetext>Created an attachment (id=28)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-22 22:31:39</issue_when>
- <thetext>Applied patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>28</attachid>
- <date>2004-03-09 08:04:31</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>GenericEntity-matches-condition.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/28/GenericEntity-matches-condition.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:04:31</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=28)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:31:39</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:31:39</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>73</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040422221835</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-09 08:05:30</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Fix deserializing of these objects.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:05:30</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:05:51</issue_when>
- <thetext>Created an attachment (id=29)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-22 22:18:35</issue_when>
- <thetext>Applied patch, which set delegatorName to &quot;default&quot; when it is null.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>29</attachid>
- <date>2004-03-09 08:05:50</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>GenericDelegator-fix-serialization.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/29/GenericDelegator-fix-serialization.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:05:51</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=29)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:18:35</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:18:35</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>74</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P2</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429200642</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 08:08:00</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Fix all fetchers of shopping cart to use a static method</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:08:00</issue_when>
- <thetext>This patch fixes all code that fetches the ShoppingCart from the session,
-to use a static method instead. It also adds the beginning of named
-ShoppingCart support.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:08:22</issue_when>
- <thetext>Created an attachment (id=30)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:51</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 20:05:04</issue_when>
- <thetext>This patch depends on EntityCache, which isn&apos;t ready for inclussion yet,
-reducing priority.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 20:06:42</issue_when>
- <thetext>Oops, modified wrong issue.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>30</attachid>
- <date>2004-03-09 08:08:22</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>ShoppingCart-getShoppingCart.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/30/ShoppingCart-getShoppingCart.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:08:22</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=30)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:03</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:51</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 20:05:04</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P2</oldvalue>
- <newvalue>P3</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 20:06:41</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>75</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429171641</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 08:09:21</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Allow code to detect whether a cacheline has expired.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:09:21</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:09:41</issue_when>
- <thetext>Created an attachment (id=31)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:57:47</issue_when>
- <thetext>Changing priority to P2, as I need these applied before I can commit my entity
-cache work.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-29 17:16:41</issue_when>
- <thetext>Now in CVS, thanks Adam.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>31</attachid>
- <date>2004-03-09 08:09:41</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-hasExpired.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/31/UtilCache-hasExpired.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:09:41</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=31)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:04</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:57:47</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:16:41</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:16:41</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>76</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429171643</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 08:10:31</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Allow code to get the values stored in the cache.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:10:31</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:10:58</issue_when>
- <thetext>Created an attachment (id=32)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:57:47</issue_when>
- <thetext>Changing priority to P2, as I need these applied before I can commit my entity
-cache work.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-29 17:16:43</issue_when>
- <thetext>Now in CVS, thanks Adam.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>32</attachid>
- <date>2004-03-09 08:10:58</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-getCacheLineValues.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/32/UtilCache-getCacheLineValues.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:10:58</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=32)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:05</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:57:47</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:16:43</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:16:43</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>77</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429171648</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 08:11:52</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Allow registering of listeners for the various events on caches.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:11:52</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:12:13</issue_when>
- <thetext>Created an attachment (id=33)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:57:48</issue_when>
- <thetext>Changing priority to P2, as I need these applied before I can commit my entity
-cache work.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-29 17:16:48</issue_when>
- <thetext>Now in CVS, thanks Adam.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>33</attachid>
- <date>2004-03-09 08:12:12</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-listeners.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/33/UtilCache-listeners.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:12:13</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=33)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:05</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:57:48</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:16:48</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:16:48</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>78</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040423080723</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-09 08:19:59</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Some additional methods to manipulate the embedded cache.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:19:59</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:20:20</issue_when>
- <thetext>Created an attachment (id=34)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-23 08:07:23</issue_when>
- <thetext>Add some more methods to GenericValue to manipulate the cache.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>34</attachid>
- <date>2004-03-09 08:20:20</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>GenericValue-EmbeddedCache.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/34/GenericValue-EmbeddedCache.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:20:20</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=34)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-23 08:07:23</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-23 08:07:23</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>79</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429200727</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 08:21:27</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>methods to fetch the list of available catalogs.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:21:27</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:21:46</issue_when>
- <thetext>Created an attachment (id=35)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:52</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 20:07:27</issue_when>
- <thetext>This patch depends on EntityCache, which isn&apos;t ready for inclussion yet,
-reducing priority.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>35</attachid>
- <date>2004-03-09 08:21:46</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>CatalogWorker-getCatalogsAvailable.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/35/CatalogWorker-getCatalogsAvailable.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:21:46</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=35)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:05</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:52</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 20:07:27</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P2</oldvalue>
- <newvalue>P3</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>80</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040422222535</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-09 08:22:53</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Create a separate makeIndexName helper method.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:22:53</issue_when>
- <thetext>This patch also truncates the index name, based on the clipping value.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:23:14</issue_when>
- <thetext>Created an attachment (id=36)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-22 22:25:35</issue_when>
- <thetext>Applied patch.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>36</attachid>
- <date>2004-03-09 08:23:14</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>DatabaseUtil-makeIndexName.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/36/DatabaseUtil-makeIndexName.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:23:14</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=36)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:25:35</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-22 22:25:35</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>81</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429172408</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 08:23:52</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add support for writing elements.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:23:52</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:24:13</issue_when>
- <thetext>Created an attachment (id=37)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:57:47</issue_when>
- <thetext>Changing priority to P2, as I need these applied before I can commit my entity
-cache work.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-29 17:24:08</issue_when>
- <thetext>Now in CVS, thanks Adam.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>37</attachid>
- <date>2004-03-09 08:24:12</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>UtilXml-writeElement.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/37/UtilXml-writeElement.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:24:13</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=37)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:03</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:57:47</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:24:08</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:24:08</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>82</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P2</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429195752</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 08:25:06</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Services/etc for manipulating PartyAttributes.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:25:06</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-09 08:25:27</issue_when>
- <thetext>Created an attachment (id=38)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:52</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>38</attachid>
- <date>2004-03-09 08:25:27</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>PartyAttributes.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/38/PartyAttributes.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-09 08:25:27</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=38)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:16:04</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>FEATURE</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:52</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>83</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P5</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040309095844</delta_ts>
- <subcomponent>Content</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-09 09:58:44</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Problems displaying the Euro symbol in order confirmation by email with MS Outlook</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-09 09:58:44</issue_when>
- <thetext>Problems displaying the Euro symbol in order confirmation by email with MS
-Outlook: instead of the beautyful Euro symbol you see a &apos;?&apos;.
-Ok, maybe I should create an issue to the Microsoft issue tracker... however
-I&apos;ve reported this for two reasons:
-1) other users reported this some time ago in the mailing lists
-2) maybe, in general, for the currency symbols in ftl templates we should use
-the html entity references (i.e. &amp;euro; for the Euro symbol): this will solve
-all the display problems with virtually any client software.</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>84</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040309101202</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-09 10:12:02</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In shipment, it&apos;s possible to issue to shipment items with negative reservations (atp &lt; 0); as a consequence of this, also the inventory items&apos; quantity on hand can be negative.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-09 10:12:02</issue_when>
- <thetext>In shipment, it&apos;s possible to issue to shipment items with negative
-reservations (atp &lt; 0); as a consequence of this, also the inventory items&apos;
-quantity on hand can be negative.
-In fact, when the issuance is performed, the (negative) reservation is deleted
-and a new issuance is created and the inventory&apos;s qoh is decremented.
-In my opinion, in this situation a warning message should be provided.
-Also, David Jones has suggested to create a report of all negative QOH
-InventoryItems and add a link for each one to get a physical inventory variance
-started.</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>85</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040730212116</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-03-11 08:14:35</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>The showvisits page in the Party Manager is very slow when there are many visits</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-11 08:14:35</issue_when>
- <thetext>The showvisits page is not coded to efficiently display a subset of the visits when there are many active.
-When there are tens of thousands the current code doesn&apos;t work very efficiently.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 21:21:16</issue_when>
- <thetext>The code for visit display utilized the entity list iterator and pulls a subset for each page. The query
-fields are indexed (as of now) so depending on the JDBC driver being used this should be quite efficient.
-If you experience further problems, send more information to the DEV list.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:04:04</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 21:21:16</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 21:21:16</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>86</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P4</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040312164734</delta_ts>
- <subcomponent>Content</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-12 16:45:26</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Error Message (esp Map) Improvements from Quake Wang</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-12 16:45:26</issue_when>
- <thetext>A description from an email from Quake:
-
-================================
-David,
- The attachment is my patch. The main changes are:
-
-1. Now the event and the service invoke will use the same message fields in SimpleMethod.
-2. Add the errorMessageMap and successMessageMap for the message handling
-
- I only change the envsetup.bsh and errormsg.ftl in the ecommerce component, please use the
-ecommerce to review the backward compatiblity.
-
-Regards
-Quake
-=============================</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-12 16:47:34</issue_when>
- <thetext>Created an attachment (id=39)
-Error Message patch from Quake Wang
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>39</attachid>
- <date>2004-03-12 16:47:34</date>
- <desc>Error Message patch from Quake Wang</desc>
- <ispatch>1</ispatch>
- <filename>quake.errormessages.patch</filename>
- <submitter_id>3</submitter_id>
- <submitting_username>jonesde</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/39/quake.errormessages.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jonesde</user>
- <when>2004-03-12 16:47:34</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=39)
-Error Message patch from Quake Wang
-</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>87</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040312165745</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-12 16:56:52</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>bsf.jar in base is old</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-12 16:56:52</issue_when>
- <thetext>bsf is no longer part of IBM. Instead, it has moved to jakarta.
-
-Attached patch changes imports, etc. It can&apos;t change the bsf.jar in
-base/lib/scripting/, however.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-03-12 16:57:45</issue_when>
- <thetext>Created an attachment (id=40)
-The patch.
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>40</attachid>
- <date>2004-03-12 16:57:45</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>IBM-Jakarta-BSF.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/40/IBM-Jakarta-BSF.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-03-12 16:57:45</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=40)
-The patch.
-</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>88</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040312165737</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-12 16:57:37</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Promotion/other adjustments not as expected when cancelling order items</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-12 16:57:37</issue_when>
- <thetext>When order items are cancelled some order level adjustments are not changed, like order level
-promotion adjustments. Because of this order totals can easily become negative. The question is what
-to do about it?
-
-Andy wrote this at one point in an email:
-
-============================
-I was aware of this; the only order level adjustments which are currently re-calculated are shipping and
-tax, order level promotions are not done at this time so we will need to add this in. In order to do this
-promotion evaluation will need to be able to be done without a shopping cart.
-============================
-
-I&apos;m not sure I totally agree with this, I think short of that it would still be good to at least pro-rate these
-order adjustments like we do with tax and shipping.
-
-Or would it be better on any order change to just cancel the order and create a new one with full re-
-calculations, including promotions, tax, shipping, etc, etc? If that is done should we apply promotions,
-etc as if it was the original order date, or using today&apos;s date? (could be a big difference based on
-promotions that come and go over time)</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>89</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040312171315</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-12 17:10:18</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In product detail show variant prices (from Brian Johnson)</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-12 17:10:18</issue_when>
- <thetext>Here is a description from an email from Brian Johnson:
-
-===================================
-I&apos;ve changed productdetail to better handle variants with different prices. When you first bring-up the
-page it says &quot;make selections&quot;, then when you select the features from the drop-downs it&apos;ll show the
-price for the product with those features.
---
-Brian Johnson
-===================================</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-12 17:13:15</issue_when>
- <thetext>Created an attachment (id=41)
-Show prices for variants along with drop down, patch from Brian Johnson
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>41</attachid>
- <date>2004-03-12 17:13:15</date>
- <desc>Show prices for variants along with drop down, patch from Brian Johnson</desc>
- <ispatch>1</ispatch>
- <filename>productdetail-variantprices.patch</filename>
- <submitter_id>3</submitter_id>
- <submitting_username>jonesde</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/41/productdetail-variantprices.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jonesde</user>
- <when>2004-03-12 17:11:11</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>DEFECT</oldvalue>
- <newvalue>PATCH</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-12 17:13:15</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=41)
-Show prices for variants along with drop down, patch from Brian Johnson
-</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>90</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040312172159</delta_ts>
- <subcomponent>E-Commerce</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-12 17:21:59</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Web/order/etc marketing reports like Core Metrics</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-12 17:21:59</issue_when>
- <thetext>The feature here is to create a standard set of reports commonly used to keep tabs on a web content
-and/or ecommerce site. These reports would be similar to what a company like Core Metrics offers.
-
-Would include reports for a given time period such as for things like hits, visits/sessions, orders,
-tracking codes, percent of customers that order, orders per customer, pages/products/etc viewed,
-searches done, referring sites &amp; search strings, etc, etc, etc.</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>91</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040315011245</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-15 01:12:45</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Shipment: potential problem when issuing negative reservations (quantityNotAvailable could be lost)</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-15 01:12:45</issue_when>
- <thetext>This is a potential problem when you issue negative reservation to a shipment.
-Here is the scenario:
-
-1) inventory item 9000 for product WG-1111 with atp/qoh = 10/10
-2) two orders are received for WG-1111: the first for 8 items, the second
-for 5 items
-3) two reservations are made: the first for 8 items and the second for 5
-items but with quantityNotAvailable = 3
-4) the inventory item 9000 is now: atp/qoh = -3/10
-5) only the second order is issued to shipment: the reservation record is
-deleted and the qoh is decremented
-6) the inventory item 9000 is now: atp/qoh = -3/5 but the reservation for
-the first order (for quantity = 8) has quantityNotAvailable = 0 (ERROR: it
-should be 3)
-
-A possible patch: if we issue a negative reservation we should try to assign
-the quantityNotAvailable to another reservation in the same inventory item.
-
-In order to do this, David Jones has proposed to do a re-reservation whenever a
-reservation is issued to a shipment, considering that (like in this scenario)
-shipments may occur in a different order than reservations.
-
-In fact, when new inventory is received a re-reservation is already done for
-all OIIR that are associated to inventory items (of the same product) that have
-negative ATP.
-In a similar way, when we issue a OIIR, we could do a re-reservation for all
-the OIIR associated to the inventory item.</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>92</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20040416115022</delta_ts>
- <subcomponent>E-Commerce</subcomponent>
- <reporter>holivier</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-16 06:35:41</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Simple Update for localization</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 06:35:41</issue_when>
- <thetext>In the ecommerce component
-2 UiLabels change (the # is now in the label)
-and some french UiLabel correction</thetext>
- </long_desc>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 06:38:00</issue_when>
- <thetext>Created an attachment (id=42)
-the Ecommerce UiLabel patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-16 11:50:22</issue_when>
- <thetext>Patch is in CVS. Thanks for doing these Olivier.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>42</attachid>
- <date>2004-03-16 06:38:00</date>
- <desc>the Ecommerce UiLabel patch</desc>
- <ispatch>1</ispatch>
- <filename>EcommerceUiLabel.update.patch</filename>
- <submitter_id>165</submitter_id>
- <submitting_username>holivier</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/42/EcommerceUiLabel.update.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>holivier</user>
- <when>2004-03-16 06:38:00</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=42)
-the Ecommerce UiLabel patch
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:04:15</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-16 11:50:22</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-16 11:50:22</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>93</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20040416115029</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>holivier</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-16 08:00:55</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Simple Update for localization</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 08:00:55</issue_when>
- <thetext>Order component, some french UiLabels correction</thetext>
- </long_desc>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 08:02:07</issue_when>
- <thetext>Created an attachment (id=43)
-The OrderUilabel properties patch file
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-16 11:50:29</issue_when>
- <thetext>Patch is in CVS. Thanks for doing these Olivier.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>43</attachid>
- <date>2004-03-16 08:02:07</date>
- <desc>The OrderUilabel properties patch file</desc>
- <ispatch>1</ispatch>
- <filename>OrderUilabelCorrection.patch</filename>
- <submitter_id>165</submitter_id>
- <submitting_username>holivier</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/43/OrderUilabelCorrection.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>holivier</user>
- <when>2004-03-16 08:02:07</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=43)
-The OrderUilabel properties patch file
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:04:26</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-16 11:50:29</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-16 11:50:29</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>94</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20040416115037</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>holivier</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-16 09:28:27</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Simple Update for localization</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 09:28:27</issue_when>
- <thetext>simple french correction &amp; translation in the Party and workeffort components</thetext>
- </long_desc>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 09:29:26</issue_when>
- <thetext>Created an attachment (id=44)
-the PartyUiLabel correction patch file
-</thetext>
- </long_desc>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 09:30:03</issue_when>
- <thetext>Created an attachment (id=45)
-the workeffortUilabel correction patch file
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-16 11:50:37</issue_when>
- <thetext>Patch is in CVS. Thanks for doing these Olivier.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>44</attachid>
- <date>2004-03-16 09:29:26</date>
- <desc>the PartyUiLabel correction patch file</desc>
- <ispatch>1</ispatch>
- <filename>PartyUiLabelCorrection040316.patch</filename>
- <submitter_id>165</submitter_id>
- <submitting_username>holivier</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/44/PartyUiLabelCorrection040316.patch</attachment_iz_url>
- </attachment>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>45</attachid>
- <date>2004-03-16 09:30:03</date>
- <desc>the workeffortUilabel correction patch file</desc>
- <ispatch>1</ispatch>
- <filename>WorkeffortUiLabelCorrection040316.patch</filename>
- <submitter_id>165</submitter_id>
- <submitting_username>holivier</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/45/WorkeffortUiLabelCorrection040316.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>holivier</user>
- <when>2004-03-16 09:29:26</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=44)
-the PartyUiLabel correction patch file
-</newvalue>
- </activity>
- <activity>
- <user>holivier</user>
- <when>2004-03-16 09:30:03</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=45)
-the workeffortUilabel correction patch file
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:04:35</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-16 11:50:37</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-16 11:50:37</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>95</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20040416115047</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>holivier</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-16 09:32:59</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Simple Update for localization</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 09:32:59</issue_when>
- <thetext>Product components internationalization and the UiLabel files associated</thetext>
- </long_desc>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 09:36:08</issue_when>
- <thetext>Created an attachment (id=46)
-the patch file for produt bsh, xml, ftl and properties
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-16 11:50:47</issue_when>
- <thetext>Patch is in CVS. Thanks for doing these Olivier.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>46</attachid>
- <date>2004-03-16 09:36:08</date>
- <desc>the patch file for produt bsh, xml, ftl and properties</desc>
- <ispatch>1</ispatch>
- <filename>ProductUiLabelMigration040316.patch</filename>
- <submitter_id>165</submitter_id>
- <submitting_username>holivier</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/46/ProductUiLabelMigration040316.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>holivier</user>
- <when>2004-03-16 09:36:08</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=46)
-the patch file for produt bsh, xml, ftl and properties
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:04:46</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-16 11:50:47</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-16 11:50:47</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>96</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jonesde</assigned_to>
- <delta_ts>20040730204543</delta_ts>
- <subcomponent>Security Extensions</subcomponent>
- <reporter>holivier</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-16 13:30:49</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Typo error correction in emailPassword (bcc in place of cc)</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 13:30:49</issue_when>
- <thetext>just a simple typo correction.In the emailPassword method when reading and
-populated the service fields they was an error.
- serviceContext.put(&quot;sendBcc&quot;, productStoreEmail.get(&quot;ccAddress&quot;));
-I have change cc to bcc</thetext>
- </long_desc>
- <long_desc>
- <who>holivier</who>
- <issue_when>2004-03-16 13:31:26</issue_when>
- <thetext>Created an attachment (id=47)
-the patch file
-</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 20:45:43</issue_when>
- <thetext>this has already been fixed in cvs.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>47</attachid>
- <date>2004-03-16 13:31:26</date>
- <desc>the patch file</desc>
- <ispatch>1</ispatch>
- <filename>EmailPassword040316.patch</filename>
- <submitter_id>165</submitter_id>
- <submitting_username>holivier</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/47/EmailPassword040316.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>holivier</user>
- <when>2004-03-16 13:31:26</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=47)
-the patch file
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-03-18 12:04:54</when>
- <field_name>version</field_name>
- <field_desc>Version</field_desc>
- <oldvalue>Pre3.0.0</oldvalue>
- <newvalue>CVS</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 20:45:43</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 20:45:43</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>97</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040527234819</delta_ts>
- <subcomponent>Accounting</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-18 06:59:56</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Error when creating an invoice with billing account payment type.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-18 06:59:56</issue_when>
- <thetext>The following error is generated when you try to create an invoice for an order
-with payment type == billing account:
-
-----------------------------------------
-803495[ InvoiceServices.java:583:ERROR] Problems storing invoice items
-org.ofbiz.entity.GenericEntityException: Exception occurred in storeAll (while i
-nserting: [GenericEntity:InvoiceContactMech][createdTxStamp,2004-03-18 15:29:46.
-156(java.sql.Timestamp)][invoiceId,10010(java.lang.String)][contactMechPurposeTy
-peId,BILLING_LOCATION(java.lang.String)][lastUpdatedTxStamp,2004-03-18 15:29:46.
-156(java.sql.Timestamp)][contactMechId,null()][createdStamp,2004-03-18 15:29:46.
-977(java.sql.Timestamp)][lastUpdatedStamp,2004-03-18 15:29:46.977(java.sql.Times
-tamp)] (SQL Exception while executing the following:INSERT INTO INVOICE_CONTACT_
-MECH (INVOICE_ID, CONTACT_MECH_PURPOSE_TYPE_ID, CONTACT_MECH_ID, LAST_UPDATED_ST
-AMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP, CREATED_TX_STAMP) VALUES (?, ?, ?, ?,
- ?, ?, ?) ([-5005] (at 83): Missing non-NULL value)))
-----------------------------------------
-
-I think I&apos;ve tracked down the source of this problem:
-the field contactMechId for the billing account entry in BillingAccount entity
-is empty.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-05-26 10:12:53</issue_when>
- <thetext>The error happens when no Billing Contact Mechanism is specified in the billing
-account.
-In order to fix this issue the input field &quot;Billing Contact Mech&quot; in the
-EditBillingAccount page should be marked as mandatory.
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-27 23:48:19</issue_when>
- <thetext>Fixed by changing the code to not try to create that record when the BillingAccount.contactMechId is
-empty.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-05-27 23:48:18</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-27 23:48:18</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>98</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040322173551</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-03-19 07:41:21</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>New Shipment Plan feature for the shipment process.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-19 07:41:21</issue_when>
- <thetext>New Shipment Plan feature for the shipment process.
-
-In order to support some of the tasks in the manufacturing industry there was
-the need of some simple shipment planning functionality: we need to assign a
-group of customer order items to a scheduled shipment (but without actually
-picking and issuing the items from warehouse).
-
-The patches in the attached zip file add this functionality to the shipment ui.
-This is the list of changes:
-
-NEW FILES (new page, within the shipment ui, for ShipmentPlan management)
-
-product/webapp/facility/shipment/EditShipmentPlan.ftl
-product/webapp/facility/WEB-INF/actions/shipment/EditShipmentPlan.bsh
-product/webapp/facility/WEB-INF/pagedefs/shipment/EditShipmentPlan.xml
-
-PATCHES
-product/webapp/facility/shipment/ShipmentTabBar.ftl (added new link to
-EditShipmentPlan page)
-
-product/webapp/facility/shipment/ShipmentForms.xml (some new forms for the
-EditShipmentPlan page)
-
-product/webapp/facility/WEB-INF/controller.xml (controller definitions for the
-EditShipmentPlan page)
-
-product/webapp/facility/shipment/AddItemsFromOrder.ftl (added some info, also
-fixed issues #47 and #55)
-product/webapp/facility/WEB-INF/actions/shipment/AddItemsFromOrder.bsh (added
-code to get reservations also from shipment plan)
-
-product/servicedef/services_shipment.xml (definitions for two new services to
-add/delete entries in the Shipment Plan)
-product/scripts/org/ofbiz/shipment/shipment/ShipmentSerices.xml (implementation
-of the two new services)
-
-product/entitydef/entitygroup.xml (declaration of the new entity ShipmentPlan)
-product/entitydef/entitymodel_shipment.xml (definition of the new entity
-ShipmentPlan)
-
-product/config/ProductUiLabels.properties (some new labels)
-product/config/ProductUiLabels_fr.properties (some new labels in ENGLISH)</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-19 07:42:41</issue_when>
- <thetext>Created an attachment (id=48)
-The patches and new files
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-03-22 17:35:51</issue_when>
- <thetext>This patch is now in place. Thanks for sending it in Jacopo. BTW, for future patches a consolidated
-patch file is nice.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>application/x-compressed</mimetype>
- <attachid>48</attachid>
- <date>2004-03-19 07:42:41</date>
- <desc>The patches and new files</desc>
- <ispatch></ispatch>
- <filename>ShipmentPlan.zip</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/48/ShipmentPlan.zip</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-03-19 07:42:41</when>
- <field_name>attachments.thedata</field_name>
- <field_desc>Attachment Data</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=48)
-The patches and new files
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-22 17:35:51</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-03-22 17:35:51</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>99</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P4</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040806160304</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-03-28 01:13:10</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>New html report that shows inventory availability by product</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-28 01:13:10</issue_when>
- <thetext>This is a new html report (patches are in the attached zip file) for the
-Facility Manager Application that shows info about stock levels and
-reservations from a product point of view (instead of inventory item).
-The action code is very simple (the bsh action calls a service to
-compute atp and qoh per product); the report is formatted by the form widget
-stuff.
-It is not internationalized.
-In my local setup I&apos;ve added a link to it from the Inventory Item page but fell
-free to modify it and put it where you want.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-03-28 01:14:46</issue_when>
- <thetext>Created an attachment (id=49)
-Files and patches for the new report.
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-08-06 16:03:04</issue_when>
- <thetext>Okay, this is in CVS, and I added a link to it from the facility inventory items page. Thanks for sending
-this over.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>application/x-compressed</mimetype>
- <attachid>49</attachid>
- <date>2004-03-28 01:14:46</date>
- <desc>Files and patches for the new report.</desc>
- <ispatch></ispatch>
- <filename>inventory_report.zip</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/49/inventory_report.zip</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-03-28 01:14:46</when>
- <field_name>attachments.thedata</field_name>
- <field_desc>Attachment Data</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=49)
-Files and patches for the new report.
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-06 16:03:04</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-06 16:03:04</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>100</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>REL 3.0.0</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040403232241</delta_ts>
- <subcomponent>E-Commerce</subcomponent>
- <reporter>dlouzado</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-03-28 13:50:10</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>crash on Shipping Information page</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>dlouzado</who>
- <issue_when>2004-03-28 13:50:10</issue_when>
- <thetext>I was logged as &quot;admin&quot; user and buying something on the test store on ofbiz
-instance running on a standalone machine (no connection with the internet).
-
-I was filling the shipping information and when I clicked &apos;continue&apos; the
-following exception was thrown:
-
-
-&quot;org.ofbiz.base.util.GeneralException: JPublish execution error (BeanShell
-script error: Sourced file:
-C:\jtools\ofbiz\components\ecommerce\webapp\ecommerce\WEB-INF\actions\order\optionsettings.bsh
-: Error in method invocation: Attempt to pass void argument (position 0) to
-method: getContactMechByType : at Line: 65 : in file:
-C:\jtools\ofbiz\components\ecommerce\webapp\ecommerce\WEB-INF\actions\order\optionsettings.bsh
-: ContactHelper .getContactMechByType ( party , &quot;EMAIL_ADDRESS&quot; , false )
-BSF info:
-C:\jtools\ofbiz\components\ecommerce\webapp\ecommerce\WEB-INF\actions\order\optionsettings.bsh
-at line: 0 column: 0)&quot;</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-03 23:22:41</issue_when>
- <thetext>Fixed so that &quot;party&quot; would exist where it is referenced there.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-04-03 23:22:41</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-03 23:22:41</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>101</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P5</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040730152858</delta_ts>
- <subcomponent>Content</subcomponent>
- <reporter>eckardjf</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-04-02 09:44:46</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>https Website Settings Ignored</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>eckardjf</who>
- <issue_when>2004-04-02 09:44:46</issue_when>
- <thetext>org.ofbiz.content.webapp.control.RequestHandler.doRequest() checks to see if a request should be
-secure, but is not - and will redirect to a secure url if necessary. However, when rewriting the url to
-make it secure, it does not check the website settings for the enableHttps, httpsHost and httpsPort. It
-uses the global defaults from url.properties instead, which means the website settings have no effect.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 15:28:58</issue_when>
- <thetext>this has now been corrected in CVS.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:43:50</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 15:28:58</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 15:28:58</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>102</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P4</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>REL 3.0.0</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040403233556</delta_ts>
- <subcomponent>Entity Extensions</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-03 23:35:56</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Easy way to disabling Entity Sync oriented information</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-03 23:35:56</issue_when>
- <thetext>Need an easy way to disable the saving of Entity Sync oriented information such as the entity remove
-information. May not want to disable the auto tx and individual timestamps because they are used in
-other code that takes advantage of the fact that they are always present (though we still need to get rid
-of the last updated and created timestamps that were added to various entities).</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>103</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P1</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040405070601</delta_ts>
- <subcomponent>Accounting</subcomponent>
- <reporter>bryce_nz</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-04-05 00:05:28</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Nasty little error in PaymentGatewayServices</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>bryce_nz</who>
- <issue_when>2004-04-05 00:05:28</issue_when>
- <thetext>In PaymentGatewayServices.refundPayment there is a section of code for creating
-the payment for the refund, then at line 1255 there is the following:
-
- Map result = ServiceUtil.returnSuccess();
- result.put(&quot;paymentId&quot;, &quot;10000&quot;);
- return result;
-
-Obviously the payment id being returned shouldn&apos;t be hardcoded in, should read:
-
- Map result = ServiceUtil.returnSuccess();
- result.put(&quot;paymentId&quot;, paymentId);
- return result;</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 07:06:01</issue_when>
- <thetext>This has been corrected in CVS, thank you.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 07:05:36</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 07:06:01</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 07:06:01</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>104</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040405134511</delta_ts>
- <subcomponent>Workflow</subcomponent>
- <reporter>elfring</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-04-05 13:22:20</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Job Definition</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>elfring</who>
- <issue_when>2004-04-05 13:22:20</issue_when>
- <thetext>This request might fit to the section &quot;Service Engine Tools&quot; on the page
-&quot;http://ofbiz.org/feature-list.html&quot;.
-
-Would you like to support the JDF
-standard?
-http://en.wikipedia.org/wiki/Job_Definition_Format</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 13:45:11</issue_when>
- <thetext>Not sure what this is supposed to be requesting. This issue contains no specific feature request.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 13:45:11</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 13:45:11</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>105</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040405134741</delta_ts>
- <subcomponent>Service</subcomponent>
- <reporter>elfring</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-04-05 13:28:41</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Support for dynamic Service Configuration</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>elfring</who>
- <issue_when>2004-04-05 13:28:41</issue_when>
- <thetext>Would you like to use a service configurator for your server?
--
-http://www.cs.wustl.edu/~schmidt/ACE-papers.html
--
-http://java.sun.com/j2se/1.5.0/docs/guide/jmx/tutorial/tutorialTOC.html
-
-Can this
-request solved with JMX?
-http://en.wikipedia.org/wiki/Java_Management_eXtensions</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 13:47:41</issue_when>
- <thetext>This issue contains no specific feature request. Not sure what you are requesting, so there is no way to
-determine if JMX will solve the problem. </thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 13:47:41</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 13:47:41</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>106</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040405134845</delta_ts>
- <subcomponent>WebTools</subcomponent>
- <reporter>elfring</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-04-05 13:42:12</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Portlet Interface</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>elfring</who>
- <issue_when>2004-04-05 13:42:12</issue_when>
- <thetext>Would you like to integrate components with web portals?
-
--
-http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-portlet2.html
--
-http://www.javaworld.net/javaworld/jw-11-2003/jw-1114-jsfredux.html
--
-http://en.wikipedia.org/wiki/Portlet</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 13:48:45</issue_when>
- <thetext>Sure we would love to integrate with web portals, however this issue contains no specific feature
-request.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 13:48:45</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 13:48:45</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>107</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040405135106</delta_ts>
- <subcomponent>WebTools</subcomponent>
- <reporter>elfring</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-04-05 13:47:12</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Vector graphics and XForms</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>elfring</who>
- <issue_when>2004-04-05 13:47:12</issue_when>
- <thetext>Will the application support .svgz or .x3dz files that contain XForms?
-
--
-http://en.wikipedia.org/wiki/Scalable_Vector_Graphics
--
-http://en.wikipedia.org/wiki/X3D
-- http://en.wikipedia.org/wiki/XForms
--
-http://xml.apache.org/batik/
-
-See also the request &quot;XForms&quot; in the discussion forum by
-Britton LaRoche from &quot;August 28, 2003 12:38:36 AM
-GMT&quot;.
-https://ofbiz.dev.java.net/servlets/ProjectForumMessageView?forumID=282&amp;messageID=1065</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 13:51:06</issue_when>
- <thetext>This issue contains no specific feature request. No information was provided regarding how support for
-these file types is desired and where the desired functionality is needed. </thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 13:51:06</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 13:51:06</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>108</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040405140048</delta_ts>
- <subcomponent>Rules</subcomponent>
- <reporter>elfring</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-04-05 13:51:31</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Integration with Knowledge Representation</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>elfring</who>
- <issue_when>2004-04-05 13:51:31</issue_when>
- <thetext>What is the current state of your support for this technology?
--
-http://en.wikipedia.org/wiki/Knowledge_representation
--
-http://en.wikipedia.org/wiki/Expert_system</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 14:00:48</issue_when>
- <thetext>This issue is not a valid feature request, questions of this sort should be discussed on the mailing lists.
-In addition, do expect readers to follow links and read articles to get your point across it is highly
-unlikely that people will spent the time to research something for you. Your best bet is to read the
-articles and post a question asking something specific, then your chances of getting an intelligent
-response is greater.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:00:48</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:00:48</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>109</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040405140138</delta_ts>
- <subcomponent>Service</subcomponent>
- <reporter>elfring</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-04-05 13:52:57</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Open Services Gateway</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>elfring</who>
- <issue_when>2004-04-05 13:52:57</issue_when>
- <thetext>Would you like to cooperate with these service APIs so that your software can be used over these
-interfaces?
-http://www.osgi.org/about/faqs.asp
-http://en.wikipedia.org/wiki/OSGi</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 14:01:37</issue_when>
- <thetext>This issue contains no specific feature request.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:01:37</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:01:37</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>110</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040405140228</delta_ts>
- <subcomponent>Entity</subcomponent>
- <reporter>elfring</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-04-05 13:56:20</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Content Storage API</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>elfring</who>
- <issue_when>2004-04-05 13:56:20</issue_when>
- <thetext>Would you like to support the programming interface &quot;Content
-Repository&quot;?
-http://jcp.org/en/jsr/detail?id=170
-
-This topic can be perhaps combined
-with requests for CVS and Subversion integration.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 14:02:28</issue_when>
- <thetext>This issue contains no specific feature request; please see issue #108 for more suggestions.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:02:28</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:02:28</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>111</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040405140305</delta_ts>
- <subcomponent>Workflow</subcomponent>
- <reporter>elfring</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-05 14:02:16</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Workflow Management</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>elfring</who>
- <issue_when>2004-04-05 14:02:17</issue_when>
- <thetext>How do you think about workflow modelling patterns?
-Which of them are supported by your
-software? (Is cooperation with other standards like BPML besides WfMC XPDL
-possible?)
-http://tmitwww.tm.tue.nl/research/patterns/</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 14:03:05</issue_when>
- <thetext>see issue #108</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:03:05</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:03:05</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>112</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040405141257</delta_ts>
- <subcomponent>Entity Extensions</subcomponent>
- <reporter>elfring</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-05 14:07:40</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>relationships and object mapping</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>elfring</who>
- <issue_when>2004-04-05 14:07:40</issue_when>
- <thetext>I&apos;ve got the impression from the discussion about the topic &quot;entity-engine: thoughts on extends
-(IS A) pattern and relationships&quot; that there might be something useful from other information
-sources.
-
-1. CORBA: Relationship Service
-Specification
-http://www.omg.org/technology/documents/formal/relationship_service.htm
-
-2.
-ObJectRelationalBridge
-http://db.apache.org/ojb/
-
-3. alternative open source
-implementation for JDO
-http://speedo.objectweb.org/
-
-4. Citations from
-CiteSeer
-http://citeseer.ist.psu.edu/cis?q=object+and+relational+and+mapping+and+database
-
-5.
-a detailed Wiki
-http://en.wikipedia.org/wiki/Object_database
-
-Would you like to reuse
-anything from those implementations and experiences?
-
-How does your use of the Java Open
-Transaction Manager (http://jotm.objectweb.org/) fit into this picture?</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-05 14:12:57</issue_when>
- <thetext>No specific enhancement requested.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:12:57</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-04-05 14:12:57</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>113</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>WORKSFORME</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040406101817</delta_ts>
- <subcomponent>WebTools</subcomponent>
- <reporter>ajzeneski</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-04-06 07:00:29</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>EditEntity.jsp displays wrong field length</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-04-06 07:00:29</issue_when>
- <thetext>Reported by prozelit@yahoo.com:
-
-On EditEntity.jsp, there is a fields table. It is
-supposed to display the length of each field, but it
-looks like it displays the length of the field name
-instead. It seems to me there is a bug at line 347.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-06 10:18:17</issue_when>
- <thetext>
-This is the expected behavior. The length in parenthesis there is meant to show you the length of the
-column name so that you can tell if it is within the required length of the database, we generally
-recommend (and always use) equal or less than 30 characters.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-04-06 10:18:17</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-06 10:18:17</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>WORKSFORME</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>114</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>PC</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040406100126</delta_ts>
- <subcomponent>WorkEffort</subcomponent>
- <reporter>vivalinux</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-04-06 10:01:26</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc>http://&lt;ofbiz_URL&gt;/workeffort/control/month?start=1083297600000</issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Daylight savings and the calendar</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>vivalinux</who>
- <issue_when>2004-04-06 10:01:26</issue_when>
- <thetext>On the months when daylight savings takes place, or stops taking place
-(April/September in the US), the way the start of the period is computed in the
-WorkEffortServices.getWorkEffortsByPeriod yields one extra hour after dayligh
-savings kicks in.
-The reason for this is that the absolute time is interpreted differently once
-daylight savings is in place.
-So I suggest using the attached patch which relies on UtilDateTime.getDayStart
-to get the period start/end.</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>115</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040730150719</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>lykins</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-04-06 13:56:51</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Product to Order Lookup Link</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>lykins</who>
- <issue_when>2004-04-06 13:56:51</issue_when>
- <thetext>Something that should bring great benefit is the ability to link the product to
-the orders from the product maintenance screen. It would be very beneficial to
-know what purchase order the product came from. I noticed that there are links
-to almost all other relations besides this.
-
-Thanks,
-Patrick</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 15:07:19</issue_when>
- <thetext>good idea; now in CVS</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 15:07:19</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 15:07:19</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>116</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040417174533</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-04-17 00:19:59</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Implementation of getProductVariant service.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-04-17 00:19:59</issue_when>
- <thetext>Implementation of getProductVariant service.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-04-17 00:20:48</issue_when>
- <thetext>Created an attachment (id=50)
-Patch for the java implementation
-</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-04-17 00:21:21</issue_when>
- <thetext>Created an attachment (id=51)
-Patch for the service definition.
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-17 17:45:33</issue_when>
- <thetext>It&apos;s in. Thanks Jacopo.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>50</attachid>
- <date>2004-04-17 00:20:48</date>
- <desc>Patch for the java implementation</desc>
- <ispatch>1</ispatch>
- <filename>ProductServices.java.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/50/ProductServices.java.patch</attachment_iz_url>
- </attachment>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>51</attachid>
- <date>2004-04-17 00:21:21</date>
- <desc>Patch for the service definition.</desc>
- <ispatch>1</ispatch>
- <filename>services.xml.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/51/services.xml.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-04-17 00:20:48</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=50)
-Patch for the java implementation
-</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-04-17 00:21:21</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=51)
-Patch for the service definition.
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-17 17:45:33</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-17 17:45:33</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>117</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P1</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040422201817</delta_ts>
- <subcomponent>Accounting</subcomponent>
- <reporter>colt_nz</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-04-20 14:45:56</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>editPayment has wrongly named fields</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>colt_nz</who>
- <issue_when>2004-04-20 14:45:56</issue_when>
- <thetext>/accounting/webapp/accounting/payment/editPayment.ftl
-
-Input fields partyIdTo and partyIdFrom are round the wrong way. ie switch &apos;em.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-22 20:18:17</issue_when>
- <thetext>
-Thanks for reporting this, the fix is in CVS. Looks like it was perhaps an issue with the i18n...</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-04-22 20:18:17</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-22 20:18:17</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>118</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P4</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040819001212</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>jonesde</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-04-23 21:32:35</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Make QuickAddVariants Easier to Use</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-23 21:32:35</issue_when>
- <thetext>Make QuickAddVariants Easier to Use:
-
-1. Change to multi-form
-2. Allow enter pattern to use to pre-populate the various IDs</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-08-19 00:12:11</issue_when>
- <thetext>Some time ago I did this and you put all the stuff in CVS, so now it&apos;s done.</thetext>
- </long_desc>
- <activity>
- <user>jacopo</user>
- <when>2004-08-19 00:12:10</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-08-19 00:12:10</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>119</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jacopo</assigned_to>
- <delta_ts>20040717041328</delta_ts>
- <subcomponent>Manufacturing</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-24 00:15:36</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Refactoring of the BOMEvent class that manages all the related to bill of materials editing.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-04-24 00:15:36</issue_when>
- <thetext>Refactoring of the BOMEvent class that manages all the related to bill of
-materials editing.
-
-Three new (simple) services should be created (create, update, delete).
-An sECA rule should be added to the create and update services to update the
-low level code.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-07-17 04:13:28</issue_when>
- <thetext>Ok, the BOMEvent class has gone away; I have implemented some simple services
-to add/update/remove/copy boms (performing all the needed checks for loops and
-updating the product&apos;s llc).
-</thetext>
- </long_desc>
- <activity>
- <user>jacopo</user>
- <when>2004-07-17 04:13:28</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-17 04:13:28</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>120</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jacopo</assigned_to>
- <delta_ts>20040424001903</delta_ts>
- <subcomponent>Manufacturing</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-24 00:19:03</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>searchDuplicateAncenstor service should resolve also virtual to variant products to search for loops.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-04-24 00:19:03</issue_when>
- <thetext>searchDuplicateAncenstor service should resolve also virtual to variant
-products to search for loops.</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>121</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jacopo</assigned_to>
- <delta_ts>20040717041557</delta_ts>
- <subcomponent>Manufacturing</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-24 00:24:11</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Refactoring of the Bill of Material editor&apos;s ui: migration to the forms widget.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-04-24 00:24:11</issue_when>
- <thetext>Refactoring of the Bill of Material editor&apos;s ui: migration to the forms widget.
-
-This will also include:
-- i18n and l10n issues
-- management of all the relavant fields that are missing
-- lookup fields
-- fields validation</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-07-17 04:15:57</issue_when>
- <thetext>I have not used the form widget (maybe in the future, together with some more
-clean ups) here, but most of these points has been fixed.</thetext>
- </long_desc>
- <activity>
- <user>jacopo</user>
- <when>2004-07-17 04:15:57</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-17 04:15:57</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>122</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jacopo</assigned_to>
- <delta_ts>20040424002537</delta_ts>
- <subcomponent>Manufacturing</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-24 00:25:37</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>updateLowLevelCode service - it should also update the low level code for variant products </short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-04-24 00:25:37</issue_when>
- <thetext>updateLowLevelCode service - it should also update the low level code for
-variant products</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>123</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501062848</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 16:05:20</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add methods to check against classes, instead of only objects.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:05:20</issue_when>
- <thetext>This patch adds new versions of interfaceOf, isOrSubOf, and instanceOf, that
-check against a class, instead of an Object.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:06:57</issue_when>
- <thetext>Created an attachment (id=52)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:52</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 06:28:48</issue_when>
- <thetext>This is now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>52</attachid>
- <date>2004-04-29 16:06:57</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>ObjectType-check-against-class.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/52/ObjectType-check-against-class.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:06:57</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=52)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:15:14</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>DEFECT</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:52</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:28:48</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:28:48</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>124</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501062855</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 16:08:48</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Handle is-* operators when value1 is null</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:08:48</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:09:11</issue_when>
- <thetext>Created an attachment (id=53)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:53</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 06:28:55</issue_when>
- <thetext>This is now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>53</attachid>
- <date>2004-04-29 16:09:11</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>ObjectType-is-compare-value1-null.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/53/ObjectType-is-compare-value1-null.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:09:11</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=53)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:15:14</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>DEFECT</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:53</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:28:55</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:28:55</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>125</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501062903</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 16:10:04</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Convert classnames to full names.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:10:04</issue_when>
- <thetext>See $summary.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:10:21</issue_when>
- <thetext>Created an attachment (id=54)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:48</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 06:29:03</issue_when>
- <thetext>This is now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>54</attachid>
- <date>2004-04-29 16:10:21</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>ObjectType-convert-classname-to-full.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/54/ObjectType-convert-classname-to-full.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:10:21</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=54)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:15:13</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>DEFECT</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:48</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:29:03</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:29:03</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>126</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501062243</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 16:13:25</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add some helper methods for objects implementing their own equals, compareTo, and hashCode</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:13:25</issue_when>
- <thetext>Name: UtilObject.patch
-Prune: 1
-Description: Add some helper methods for objects implementing their own equals,
-compareTo, and hashCode.
-DiffStat:
- base/src/base/org/ofbiz/base/util/UtilObject.java | 35 ++++++++++++++++++++++
- 1 files changed, 35 insertions(+)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:13:45</issue_when>
- <thetext>Created an attachment (id=55)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:49</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 06:22:43</issue_when>
- <thetext>This is now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>55</attachid>
- <date>2004-04-29 16:13:45</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilObject.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/55/UtilObject.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:13:45</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=55)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:15:13</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>DEFECT</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:49</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:22:43</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:22:43</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>127</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501055554</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 16:18:14</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Simplify the top-level build.xml</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:18:14</issue_when>
- <thetext>Name: simpler-build.xml.patch
-Prune: 1
-Description: Simplifies the top-level build.xml
- This patch makes use of ant 1.6 features, to automate calling of sub
- build.xmls. It also adds a &apos;test&apos; target; note, however, that the
- listed sub build.xmls don&apos;t actually have that test target yet.
-DiffStat:
- build.xml | 494 ++++----------------------------------------------------------
- 1 files changed, 32 insertions(+), 462 deletions(-)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:18:43</issue_when>
- <thetext>Created an attachment (id=56)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:50</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 05:55:54</issue_when>
- <thetext>This is now in, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>56</attachid>
- <date>2004-04-29 16:18:43</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>simpler-build.xml.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/56/simpler-build.xml.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:18:43</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=56)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:19:44</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>DEFECT</oldvalue>
- <newvalue>ENHANCEMENT</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:50</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 05:55:54</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 05:55:54</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>128</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501051820</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 16:20:39</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add support for formatting time intervals with human words</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:20:39</issue_when>
- <thetext>Name: UtilDateTime-time-interval.patch
-Prune: 1
-Description: Add support for formatting time intervals with human words
-DiffStat:
- base/config/DateTimeLabels.properties | 10 ++
- base/src/base/org/ofbiz/base/util/UtilDateTime.java | 90 ++++++++++++++++++++
- 2 files changed, 100 insertions(+)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:20:57</issue_when>
- <thetext>Created an attachment (id=57)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:51</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 05:18:20</issue_when>
- <thetext>These are now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>57</attachid>
- <date>2004-04-29 16:20:57</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilDateTime-time-interval.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/57/UtilDateTime-time-interval.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:20:58</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=57)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:51</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 05:18:20</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 05:18:20</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>129</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429172414</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 16:22:10</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add more childElementList and firstChildElement variants.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:22:10</issue_when>
- <thetext>Name: UtilXml-childElementList-firstChildElement.patch
-Prune: 1
-Depends: UtilXml-writeElement.patch
-Description: Add more childElementList and firstChildElement variants.
-DiffStat:
- base/src/base/org/ofbiz/base/component/ComponentLoaderConfig.java
- | 2
- base/src/base/org/ofbiz/base/util/UtilXml.java
- | 80 ++++++++++
- components/content/src/org/ofbiz/content/widget/form/ModelFormField.java
- | 4
- components/entity/src/org/ofbiz/entity/model/ModelViewEntity.java
- | 2
- components/minilang/src/org/ofbiz/minilang/SimpleMethod.java
- | 2
- components/minilang/src/org/ofbiz/minilang/method/callops/CallClassMethod.java
- | 2
- components/minilang/src/org/ofbiz/minilang/method/callops/CallObjectMethod.java
- | 2
- components/minilang/src/org/ofbiz/minilang/method/callops/CreateObject.java
- | 2
- components/minilang/src/org/ofbiz/minilang/method/conditional/CombinedCondition.java
-| 2
- components/minilang/src/org/ofbiz/minilang/method/conditional/MasterIf.java
- | 2
- components/minilang/src/org/ofbiz/minilang/method/otherops/Calculate.java
- | 4
- components/minilang/src/org/ofbiz/minilang/method/otherops/Log.java
- | 2
- components/minilang/src/org/ofbiz/minilang/operation/MakeInString.java
- | 2
- components/minilang/src/org/ofbiz/minilang/operation/SimpleMapProcess.java
- | 2
- 14 files changed, 95 insertions(+), 15 deletions(-)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:22:50</issue_when>
- <thetext>Created an attachment (id=58)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:57:47</issue_when>
- <thetext>Changing priority to P2, as I need these applied before I can commit my entity
-cache work.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-29 17:24:14</issue_when>
- <thetext>Now in CVS, thanks Adam.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>58</attachid>
- <date>2004-04-29 16:22:50</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilXml-childElementList-firstChildElement.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/58/UtilXml-childElementList-firstChildElement.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:22:50</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=58)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:57:47</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:24:14</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:24:14</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>130</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429174623</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 16:24:36</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>put now returns the previous value of the object, if it exists</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:24:36</issue_when>
- <thetext>Name: UtilCache-put-returns-object.patch
-Prune: 1
-Depends: UtilCache-listeners.patch
-Description: put now returns the previous value of the object, if it exists
-DiffStat:
- base/src/base/org/ofbiz/base/util/UtilCache.java | 16 ++++++++++------
- 1 files changed, 10 insertions(+), 6 deletions(-)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:24:58</issue_when>
- <thetext>Created an attachment (id=59)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:57:48</issue_when>
- <thetext>Changing priority to P2, as I need these applied before I can commit my entity
-cache work.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-29 17:46:23</issue_when>
- <thetext>Now in CVS, thanks Adam.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>59</attachid>
- <date>2004-04-29 16:24:58</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-put-returns-object.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/59/UtilCache-put-returns-object.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:24:58</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=59)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:57:48</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:46:23</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:46:23</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>131</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040429174619</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 16:55:31</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add getCacheLineKeys method.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:55:31</issue_when>
- <thetext>Name: UtilCache-getCacheLineKeys.patch
-Prune: 1
-Depends: UtilCache-put-returns-object.patch
-Description: Add getCacheLineKeys method.
-DiffStat:
- base/src/base/org/ofbiz/base/util/UtilCache.java | 4 ++++
- 1 files changed, 4 insertions(+)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:55:56</issue_when>
- <thetext>Created an attachment (id=60)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 16:57:48</issue_when>
- <thetext>Changing priority to P2, as I need these applied before I can commit my entity
-cache work.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-04-29 17:46:19</issue_when>
- <thetext>Now in CVS, thanks Adam.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>60</attachid>
- <date>2004-04-29 16:55:56</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-getCacheLineKeys.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/60/UtilCache-getCacheLineKeys.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:55:56</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=60)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 16:57:48</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:46:19</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-04-29 17:46:19</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>132</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501051751</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 19:39:13</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add entrySet(), which functions like Map.entrySet().</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:39:13</issue_when>
- <thetext>Name: UtilCache-entrySet.patch
-Prune: 1
-Description: Add entrySet(), which functions like Map.entrySet().
-DiffStat:
- base/src/base/org/ofbiz/base/util/UtilCache.java | 4 ++++
- 1 files changed, 4 insertions(+)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:41:28</issue_when>
- <thetext>Created an attachment (id=61)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:53</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 05:17:51</issue_when>
- <thetext>These are now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>61</attachid>
- <date>2004-04-29 19:41:27</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-entrySet.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/61/UtilCache-entrySet.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:41:28</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=61)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:53</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 05:17:51</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 05:17:51</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>133</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P1</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501042628</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 19:42:19</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Add a new constructor.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:42:19</issue_when>
- <thetext>Name: UtilCache-new-constructor.patch
-Prune: 1
-Depends: UtilCache-entrySet.patch
-Description: Add a new constructor.
-DiffStat:
- base/src/base/org/ofbiz/base/util/UtilCache.java | 13 +++++++++++++
- 1 files changed, 13 insertions(+)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:42:45</issue_when>
- <thetext>Created an attachment (id=62)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:48</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-30 10:42:15</issue_when>
- <thetext>Changing these issuses, as they are needed by EntityCache.patch.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 04:26:28</issue_when>
- <thetext>These are now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>62</attachid>
- <date>2004-04-29 19:42:45</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-new-constructor.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/62/UtilCache-new-constructor.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:42:45</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=62)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:48</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-30 10:42:15</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P2</oldvalue>
- <newvalue>P1</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 04:26:28</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 04:26:28</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>134</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501062248</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 19:43:49</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Change utilCacheTable to a WeakHashMap.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:43:49</issue_when>
- <thetext>Name: UtilCache-WeakHashMap.patch
-Prune: 1
-Depends: UtilCache-new-constructor.patch
-Description: Change utilCacheTable to a WeakHashMap.
-DiffStat:
- base/src/base/org/ofbiz/base/util/UtilCache.java | 3 ++-
- 1 files changed, 2 insertions(+), 1 deletion(-)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:44:39</issue_when>
- <thetext>Created an attachment (id=63)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:49</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 06:22:48</issue_when>
- <thetext>This is now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>63</attachid>
- <date>2004-04-29 19:44:39</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-WeakHashMap.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/63/UtilCache-WeakHashMap.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:44:39</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=63)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:49</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:22:48</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:22:48</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>135</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P1</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501042633</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 19:45:22</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Methods that clear a cache by name or pattern.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:45:22</issue_when>
- <thetext>Name: UtilCache-clearCache-helpers.patch
-Prune: 1
-Depends: UtilCache-WeakHashMap.patch
-Description: Methods that clear a cache by name or pattern.
-DiffStat:
- base/src/base/org/ofbiz/base/util/UtilCache.java | 22 ++++++++++++++++++++++
- 1 files changed, 22 insertions(+)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:45:43</issue_when>
- <thetext>Created an attachment (id=64)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:49</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-30 10:42:16</issue_when>
- <thetext>Changing these issuses, as they are needed by EntityCache.patch.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 04:26:33</issue_when>
- <thetext>These are now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>64</attachid>
- <date>2004-04-29 19:45:43</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-clearCache-helpers.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/64/UtilCache-clearCache-helpers.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:45:43</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=64)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:49</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-30 10:42:16</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P2</oldvalue>
- <newvalue>P1</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 04:26:33</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 04:26:33</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>136</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040501064335</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-04-29 19:46:54</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Place the loaded document object in a UtilCache instance.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:46:54</issue_when>
- <thetext>Name: ResourceLoader-document-in-cache.patch
-Prune: 1
-Depends: UtilCache-clearCache-helpers.patch
-Description: Place the loaded document object in a UtilCache instance.
-DiffStat:
- base/src/base/org/ofbiz/base/config/ResourceLoader.java | 11 ++++-------
- 1 files changed, 4 insertions(+), 7 deletions(-)</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:47:17</issue_when>
- <thetext>Created an attachment (id=65)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-04-29 19:57:50</issue_when>
- <thetext>Changing priority, so that someone else can see the ones I want applied next.</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-01 06:43:35</issue_when>
- <thetext>This is now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>65</attachid>
- <date>2004-04-29 19:47:17</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>ResourceLoader-document-in-cache.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/65/ResourceLoader-document-in-cache.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:47:17</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=65)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>doogie</user>
- <when>2004-04-29 19:57:50</when>
- <field_name>priority</field_name>
- <field_desc>Priority</field_desc>
- <oldvalue>P3</oldvalue>
- <newvalue>P2</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:43:35</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-01 06:43:35</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>137</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040527233355</delta_ts>
- <subcomponent>Accounting</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-05-03 14:48:41</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>createInvoiceForOrder not get correct fields for terms</short_desc>
- <keywords></keywords>
- <has_duplicates>
- <issue_id>141</issue_id>
- <who>jacopo</who>
- <when>2004-05-26 10:48:21</when>
- </has_duplicates>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-05-03 14:48:41</issue_when>
- <thetext>InvoiceServices.createInvoiceForOrder is not getting correct fields for terms.
-It is not automatically generating a key for InvoiceTerm entity and is also
-looking for &quot;termType&quot; from BillingAccount when the field is actually &quot;termTypeId.&quot;</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-05-03 14:50:09</issue_when>
- <thetext>Created an attachment (id=66)
-Patch fixes defect and allows invoices to be created correctly
-</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-05-04 00:50:17</issue_when>
- <thetext>See also issue #97</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-05-26 10:48:20</issue_when>
- <thetext>*** Issue 141 has been marked as a duplicate of this issue. ***</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-05-27 23:33:55</issue_when>
- <thetext>It&apos;s now in CVS, thanks to both Si Chen and Jacopo Cappellato for reporting/fixing this.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>66</attachid>
- <date>2004-05-03 14:50:09</date>
- <desc>Patch fixes defect and allows invoices to be created correctly</desc>
- <ispatch>1</ispatch>
- <filename>InvoiceServices.java.patch</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/66/InvoiceServices.java.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-05-03 14:50:09</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=66)
-Patch fixes defect and allows invoices to be created correctly
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-03 23:03:12</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-27 23:33:55</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-05-27 23:33:55</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>138</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>WORKSFORME</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040713022331</delta_ts>
- <subcomponent>Manufacturing</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-05-04 17:45:50</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>Windows XP</op_sys>
- <short_desc>Null delegator in FindProductRun</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-05-04 17:45:50</issue_when>
- <thetext>I am getting a
-4269781[ VisitHandler.java:130:ERROR] Could not find delegator with
-delegatorName [null] in session, not creating Visit entity
-
-Is this a Windows problem or a bug?
-
-Thanks,
-
-Si Chen</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-05-04 17:46:33</issue_when>
- <thetext>Created an attachment (id=67)
-error log from running FindProductRun in Manufacturing
-</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-07-13 02:23:31</issue_when>
- <thetext>I couldn&apos;t recreate this error.
-However, from the log it seems something related to the Visit stuff.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>67</attachid>
- <date>2004-05-04 17:46:33</date>
- <desc>error log from running FindProductRun in Manufacturing</desc>
- <ispatch></ispatch>
- <filename>findproductrun.log</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/67/findproductrun.log</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-05-04 17:46:33</when>
- <field_name>attachments.thedata</field_name>
- <field_desc>Attachment Data</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=67)
-error log from running FindProductRun in Manufacturing
-</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-13 02:23:31</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-13 02:23:31</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>WORKSFORME</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>139</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>david</assigned_to>
- <delta_ts>20040509064322</delta_ts>
- <subcomponent>E-Commerce</subcomponent>
- <reporter>arukala</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-05-09 06:43:22</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Reading UiLable Properties in Email templates</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>arukala</who>
- <issue_when>2004-05-09 06:43:22</issue_when>
- <thetext>Hallo David,
-
-We are looking for your suggestions. on how should i call the UiLabel
-Properties in eCommerce Email Templates. we are eager to see this feature in
-email Confirmation after placing an order for customers?. suggest us how to?</thetext>
- </long_desc>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>140</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>jacopo</assigned_to>
- <delta_ts>20040518040000</delta_ts>
- <subcomponent>Manufacturing</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-05-11 08:26:52</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Remove all the checks against the isVariant field.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-05-11 08:26:52</issue_when>
- <thetext>Remove all the checks against the isVariant field: the best way to see if a
-product is variant is to check the ProductAssoc entity.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-05-18 04:00:00</issue_when>
- <thetext>Committed with the last changes a few days ago.</thetext>
- </long_desc>
- <activity>
- <user>jacopo</user>
- <when>2004-05-18 04:00:00</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-05-18 04:00:00</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>141</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>DUPLICATE</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040526104821</delta_ts>
- <subcomponent>Accounting</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-05-26 09:01:42</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Patch for bug in invoice creation when terms are specified for a billing account.</short_desc>
- <keywords></keywords>
- <is_duplicate>
- <issue_id>137</issue_id>
- <who>jacopo</who>
- <when>2004-05-26 10:48:21</when>
- </is_duplicate>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-05-26 09:01:42</issue_when>
- <thetext>Patch for bug in invoice creation when terms are specified for billing account:
-A wrong field name was used.
-Also a non-null field was not set.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-05-26 09:02:49</issue_when>
- <thetext>Created an attachment (id=68)
-The patch file in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-05-26 10:48:21</issue_when>
- <thetext>Ok, Si Chen had already fixed this!!!
-
-*** This issue has been marked as a duplicate of 137 ***</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>68</attachid>
- <date>2004-05-26 09:02:49</date>
- <desc>The patch file in UOF</desc>
- <ispatch>1</ispatch>
- <filename>InvoiceServices.java.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/68/InvoiceServices.java.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-05-26 09:02:49</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=68)
-The patch file in UOF
-</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-05-26 10:48:21</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-05-26 10:48:21</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>DUPLICATE</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>142</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>PC</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040630194530</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>jackhung</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-06-15 03:33:20</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>Linux</op_sys>
- <short_desc>Party Profile [New Communication] throws exception</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jackhung</who>
- <issue_when>2004-06-15 03:33:20</issue_when>
- <thetext>Error: The application script threw an exception: Sourced file:
-/mnt/hda6/jackwork/ofbiz3/workspace/ofbiz/components/party/webapp/partymgr/WEB-INF/actions/communication/editCommunication.bsh
-: null : at Line: 47 : in file:
-/mnt/hda6/jackwork/ofbiz3/workspace/ofbiz/components/party/webapp/partymgr/WEB-INF/actions/communication/editCommunication.bsh
-: party .getRelatedOne ( &quot;Person&quot; ) Target exception:
-java.lang.NullPointerException: Null Pointer in Method Invocation BSF info:
-/mnt/hda6/jackwork/ofbiz3/workspace/ofbiz/components/party/webapp/partymgr/WEB-INF/actions/communication/editCommunication.bsh
-at line: 0 column: 0
-
-
-URL: https://jhpc:18443/partymgr/control/viewCommunicationEvent?partyIdFrom=ltdadmin
-
-partyId = request.getParameter(&quot;party_id&quot;);
-...
-party = delegator.findByPrimaryKey(&quot;Party&quot;, UtilMisc.toMap(&quot;partyId&quot;, partyId));
-context.put(&quot;party&quot;, party);
-context.put(&quot;lookupPerson&quot;, party.getRelatedOne(&quot;Person&quot;)); &lt;---</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-06-30 19:45:30</issue_when>
- <thetext>This has been fixed in CVS</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-06-15 03:39:27</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:45:30</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:45:30</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>143</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040630194322</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>FEATURE</issue_type>
- <creation_ts>2004-06-17 10:51:48</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Allows orders to have shipBeforeDate and shipAfterDate</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-06-17 10:51:48</issue_when>
- <thetext>Changed ShoppingCart.java and CheckoutHelper.java to allow ship before and
-after dates to be set using the OrderShipmentPreference entity.
-OrderServices.java is modified as well to allow these dates to go on the order
-confirmation email.</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-06-17 10:53:16</issue_when>
- <thetext>Created an attachment (id=69)
-Patches ShoppingCart.java, CheckoutHelper.java, OrderServices.java,
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>69</attachid>
- <date>2004-06-17 10:53:16</date>
- <desc>Patches ShoppingCart.java, CheckoutHelper.java, OrderServices.java,</desc>
- <ispatch>1</ispatch>
- <filename>order_dating_patch.txt</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/69/order_dating_patch.txt</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-06-17 10:53:16</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=69)
-Patches ShoppingCart.java, CheckoutHelper.java, OrderServices.java,
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:43:22</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:43:22</when>
- <field_name>short_desc</field_name>
- <field_desc>Summary</field_desc>
- <oldvalue>Allows orders to have shipBeforeDate and shipAfterDate </oldvalue>
- <newvalue>Allows orders to have shipBeforeDate and shipAfterDate</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>144</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>WORKSFORME</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>PC</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040630194017</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>jackhung</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-06-18 02:57:10</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>Linux</op_sys>
- <short_desc>https connection broke Mozilla 1.3 and 1.4</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jackhung</who>
- <issue_when>2004-06-18 02:57:10</issue_when>
- <thetext>I&apos;m getting a strange problem lately (2 days). I&apos;m at the ecommerce&apos;s main page
-and try to [Login] (url
-https://www.myhost.net:8443/ecommerce/control/checkLogin/main). The
-certification stuff comes up and I accepted it. On one of my system using
-Mozilla 1.3, the browser popup a dialog saying:
- &quot;www.myhost.net has received an incorrect or unexpected message. Error Code:
--12229&quot;
-For all subsequent attempt, the browser popup a dialog saying:
- &quot;The Document contains no data&quot;
-It appears that the browser is not sending any request to the server on
-subsequent attempt.
-
-On another system using Mozilla 1.4, i did not get the &quot;unexpected message&quot;, but
-still got the &quot;no data&quot; one.
-
-I have an Crozilla 1.3a browser around (from the Mozilla SVG project). I tried
-it and it works!!
-
-As a matter of fact, i&apos;m having the same problem with any of the secure
-components (webtools, partymgr, ...)</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-06-30 19:40:17</issue_when>
- <thetext>I cannot duplicate this issue with FireFox. It could be a bug in that version of mozilla. Is this still an
-issue w/ the 1.5-1.7?</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:40:17</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:40:17</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>WORKSFORME</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>145</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040619093839</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-06-18 09:57:41</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Fixes duplicated PartyContactMechPurposes when using updatePartyContactMech</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-06-18 09:57:41</issue_when>
- <thetext>Fixes duplicated PartyContactMechPurposes when using updatePartyContactMech to
-move a party&apos;s contact information from an old contactMechId to a
-newContactMechId by checking to make sure the PartyContactMechPurpose does not
-already exist.</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-06-18 09:58:34</issue_when>
- <thetext>Created an attachment (id=70)
-Patches PartyContactMechServices.xml
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-06-19 09:38:39</issue_when>
- <thetext>It&apos;s in CVS now. Thanks Si.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>70</attachid>
- <date>2004-06-18 09:58:34</date>
- <desc>Patches PartyContactMechServices.xml</desc>
- <ispatch>1</ispatch>
- <filename>PartyContactMechServices.patch</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/70/PartyContactMechServices.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-06-18 09:58:34</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=70)
-Patches PartyContactMechServices.xml
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-06-19 09:38:39</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-06-19 09:38:39</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>146</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040622094557</delta_ts>
- <subcomponent>Party</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-06-21 17:56:29</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Passes partyId into updatePostalAddress from updatepartyPostalAddress</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-06-21 17:56:29</issue_when>
- <thetext>Passes partyId into updatePostalAddress from updatePartyPostalAddress, to
-preserve it for updateCreditCard later.</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-06-21 17:57:02</issue_when>
- <thetext>Created an attachment (id=71)
-Passes partyId from updatePartyPostalAddress to updatePostalAddress
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-06-22 09:45:57</issue_when>
- <thetext>It&apos;s in. Thanks Si Chen.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>71</attachid>
- <date>2004-06-21 17:57:02</date>
- <desc>Passes partyId from updatePartyPostalAddress to updatePostalAddress</desc>
- <ispatch>1</ispatch>
- <filename>PartyContactMechServices.patch</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/71/PartyContactMechServices.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-06-21 17:57:02</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=71)
-Passes partyId from updatePartyPostalAddress to updatePostalAddress
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-06-22 09:45:57</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-06-22 09:45:57</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>147</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040623161518</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-06-22 15:58:48</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Minor additions to calculateProductPrice</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-06-22 15:58:48</issue_when>
- <thetext>Implements a &quot;Percent of Default Price&quot; price action for price rules and checks
-both default and list prices when there is a &quot;Promotional Price Override&quot; price
-action.</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-06-22 15:59:22</issue_when>
- <thetext>Created an attachment (id=72)
-minor additions to calculateProductPrice
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-06-23 16:15:18</issue_when>
- <thetext>Okay, this patch is in. Thanks for working on this and sending it over Si.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>72</attachid>
- <date>2004-06-22 15:59:22</date>
- <desc>minor additions to calculateProductPrice</desc>
- <ispatch>1</ispatch>
- <filename>calculateProductPrice.patch</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/72/calculateProductPrice.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-06-22 15:59:22</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=72)
-minor additions to calculateProductPrice
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-06-23 16:15:18</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-06-23 16:15:18</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>148</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>WORKSFORME</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040730233418</delta_ts>
- <subcomponent>Accounting</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-06-23 05:42:27</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Duplicate invoices for the same order under some cicumstances.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-23 05:42:27</issue_when>
- <thetext>With &quot;Offline Payments&quot;, from the order detail page it is possible to
-receive payments: when the payments cover the order&apos;s grand total an invoice
-is generated; also when the shipment to which the order is issued changes
-its status to PACKED an invoice is created: this can cause the creation
-of two different invoices for the same order.</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 21:11:52</issue_when>
- <thetext>I cannot duplicate this problem; I attempted an offline order, received the payment - no invoice was
-created; issued a quick ship a single invoice was created. Please provide more details.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-07-30 23:34:18</issue_when>
- <thetext>I cannot believe... I have tried again and the problem is gone away.
-However I&apos;m totally sure (99%) that this was an issue...
-</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-06-23 16:16:30</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-30 23:34:18</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-30 23:34:18</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>WORKSFORME</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>149</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040818085225</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-06-26 01:51:16</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Patch for bug that happens when you try to cancel an order item.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-26 01:51:16</issue_when>
- <thetext>In revision 1.30 of the services.xml file for the order component, the require-
-new-transaction=&quot;true&quot; was added to the resetGrandTotal service: this causes
-problems when you cancel an order item because the resetGrandTotal is one of
-the services that are triggered and it seems to hang up the process waiting for
-a transaction (at least this happens with SAP-DB).
-
-The attached patch removes the require-new-transaction=&quot;true&quot; parameter and
-this solves the problem; however I don&apos;t know if this could cause other
-problems in different parts of the system.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-26 01:51:58</issue_when>
- <thetext>Created an attachment (id=73)
-Patch in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-08-18 08:52:25</issue_when>
- <thetext>The patch has been applied.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>73</attachid>
- <date>2004-06-26 01:51:58</date>
- <desc>Patch in UOF</desc>
- <ispatch>1</ispatch>
- <filename>services.xml.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/73/services.xml.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-06-26 01:51:58</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=73)
-Patch in UOF
-</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-08-18 08:52:25</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-08-18 08:52:25</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>150</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040630190556</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-06-26 01:56:29</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>When you receive a purchase order the order lines are declared completed (also multiple times) even if it&apos;s not true.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-26 01:56:29</issue_when>
- <thetext>The attached patch fixes two bugs that caused the problem.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-26 01:56:53</issue_when>
- <thetext>Created an attachment (id=74)
-Tha patch in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-06-30 19:05:56</issue_when>
- <thetext>patch applied to CVS</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>74</attachid>
- <date>2004-06-26 01:56:53</date>
- <desc>Tha patch in UOF</desc>
- <ispatch>1</ispatch>
- <filename>OrderSimpleMethods.xml.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/74/OrderSimpleMethods.xml.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-06-26 01:56:53</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=74)
-Tha patch in UOF
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:05:56</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:05:56</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>151</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040630224402</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-06-26 02:01:14</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In order entry, if no party is selected, during the checkout process some errors are generated: this patch fix the problem by disabling the checkout link if the party is missing.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-26 02:01:14</issue_when>
- <thetext>In order entry, if no party is selected, during the checkout process some
-errors are generated: this patch fix the problem by disabling the checkout link
-if the party is missing.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-26 02:01:41</issue_when>
- <thetext>Created an attachment (id=75)
-Patch in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-06-30 19:19:39</issue_when>
- <thetext>I cannot duplicate this issue; is it still a problem?</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-30 22:44:02</issue_when>
- <thetext>Hmmm, now it seems to work for me, too.
-I&apos;m wondering if something is changed during the last 10 days... I was quite
-sure about this problem.
-By the way, I&apos;m going to declare resolved this issue, thanks.
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>75</attachid>
- <date>2004-06-26 02:01:41</date>
- <desc>Patch in UOF</desc>
- <ispatch>1</ispatch>
- <filename>noparty.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/75/noparty.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-06-26 02:01:41</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=75)
-Patch in UOF
-</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-06-30 22:44:02</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-06-30 22:44:02</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>152</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P4</priority>
- <resolution>LATER</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040630192805</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>jacopo</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-06-26 02:13:57</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Shipping location is missing in purchase orders: this causes problems when you try to cancel an order item.</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-26 02:13:57</issue_when>
- <thetext>In purchase order the shipping location address is not set and this causes
-problems when you try to cancel order items (the shipping location is used is
-some service that are triggered in this situation, such as the calcTax service
-etc...).
-In my opinion the best solution is to add a shipping location address to the
-purchase order.
-The address could be that of the facility that will receive the po.
-
-I have also attached a patch (not a good one, so probably you shouldn&apos;t apply
-it) that fix this problem by allowing, during order entry, to select one of the
-addresses of the facility that is linked to the productStore for which the
-purchase order is taken: so in the checkinits page the store selection should
-be enabled for purchase orders too.</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-06-26 02:14:21</issue_when>
- <thetext>Created an attachment (id=76)
-Patch in UOF
-</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-06-30 19:28:05</issue_when>
- <thetext>Sounds like there are more issues here. First off most likely tax should not be calculated for purchase
-orders; nor should the same shipping charges which apply to sales orders should not apply to purchase
-orders.
-
-I will see what I can do when working on some additional PO enhancements.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>76</attachid>
- <date>2004-06-26 02:14:20</date>
- <desc>Patch in UOF</desc>
- <ispatch>1</ispatch>
- <filename>shipping_address.patch</filename>
- <submitter_id>194</submitter_id>
- <submitting_username>jacopo</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/76/shipping_address.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>jacopo</user>
- <when>2004-06-26 02:14:22</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=76)
-Patch in UOF
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:28:05</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-06-30 19:28:05</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>LATER</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>153</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P5</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040707011403</delta_ts>
- <subcomponent>Service</subcomponent>
- <reporter>eckardjf</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-07-05 12:19:00</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>purgeOldJobs service leaves artifacts</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>eckardjf</who>
- <issue_when>2004-07-05 12:19:00</issue_when>
- <thetext>The purgeOldJobs service will remove qualifying JobSandbox entities, but will not remove the related
-RuntimeData, RecurrenceInfo and RecurrenceRule entities (even if they are not referenced by an
-existing WorkEffort).</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:14:03</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>154</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040707150844</delta_ts>
- <subcomponent>Content</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-07-06 12:49:26</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Unknown import</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-06 12:49:26</issue_when>
- <thetext>Region.java imports com.sun.rsasign.r. When compiling with jikes, this class is
-not available. Removing the import, and the class compiles fine, so it&apos;s
-obviously not needed.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-06 12:49:58</issue_when>
- <thetext>Created an attachment (id=77)
-Remove the bad import
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-07-07 15:08:44</issue_when>
- <thetext>This import has now been removed, not even sure why it was there in the first place... Thanks Adam.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>77</attachid>
- <date>2004-07-06 12:49:58</date>
- <desc>Remove the bad import</desc>
- <ispatch>1</ispatch>
- <filename>Region.java.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/77/Region.java.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-07-06 12:49:58</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=77)
-Remove the bad import
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 15:08:44</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 15:08:44</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>155</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040707011249</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-07-06 14:27:26</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>UtilCache does not allow for null keys</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-06 14:27:26</issue_when>
- <thetext>UtilCache doesn&apos;t allow null keys to be stored. This is sub-optimal, and
-actually causes problems with my enhanced entity cache code. Attached patch fixes.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-06 14:28:17</issue_when>
- <thetext>Created an attachment (id=78)
-Allow for null keys
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-07-07 01:12:49</issue_when>
- <thetext>This is now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>78</attachid>
- <date>2004-07-06 14:28:17</date>
- <desc>Allow for null keys</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-null-key.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/78/UtilCache-null-key.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-07-06 14:28:17</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=78)
-Allow for null keys
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:12:49</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:12:49</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>156</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040707011312</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-07-06 14:30:09</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Allow specifying the expire time on put in UtilCache</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-06 14:30:09</issue_when>
- <thetext>Add a new put method, that takes an expireTime parameter.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-06 14:30:31</issue_when>
- <thetext>Created an attachment (id=79)
-The patch.
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-07-07 01:13:12</issue_when>
- <thetext>This is now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>79</attachid>
- <date>2004-07-06 14:30:31</date>
- <desc>The patch.</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-put-takes-expireTime.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/79/UtilCache-put-takes-expireTime.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-07-06 14:30:31</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=79)
-The patch.
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:13:12</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:13:12</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>157</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040707011225</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-07-06 14:35:33</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>In UtilCache, allow for a list of property bases to be specified</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-06 14:35:33</issue_when>
- <thetext>When a UtilCache instance is created, it currently will only look for a single
-matching property value, by name. This patch allows for a list of base property
-names to be specified, and the first one found will be used.
-
-I make use of this in my entity cache code. For instance:
-==
-Cache.entity-list.${delegator-name}.${entity-name}.expireTime=1800000
-Cache.entity-list.${delegator-name}.${entity-name}.maxSize=500
-
-# high count, low access
-# 5 minute cache time
-Cache.entity-list.${delegator-name}.PartyAttribute=300000
-==</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-06 14:35:48</issue_when>
- <thetext>Created an attachment (id=80)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-07-07 01:12:25</issue_when>
- <thetext>This is now in CVS, thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>80</attachid>
- <date>2004-07-06 14:35:48</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>UtilCache-wildcard-config.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/80/UtilCache-wildcard-config.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-07-06 14:35:48</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=80)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:12:25</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:12:25</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>158</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040707011838</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-07-06 17:08:44</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>distinct attribute for getProductFeatures is not working</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-07-06 17:08:44</issue_when>
- <thetext>distinct attribute for getProductFeatures service does not work because it is
-trying to use ProductFeatureType rather than ProductFeatureTypeId in
-ProductServices.prodGetFeatures</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-07-06 17:16:51</issue_when>
- <thetext>Created an attachment (id=81)
-Corrects productFeatureType to productFeatureTypeId
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-07-07 01:18:38</issue_when>
- <thetext>It&apos;s in CVS now, thanks Si!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>81</attachid>
- <date>2004-07-06 17:16:51</date>
- <desc>Corrects productFeatureType to productFeatureTypeId</desc>
- <ispatch>1</ispatch>
- <filename>ProductServices_1.patch</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/81/ProductServices_1.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-07-06 17:16:51</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=81)
-Corrects productFeatureType to productFeatureTypeId
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:18:38</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:18:38</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>159</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040707012137</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-07-06 17:26:05</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Adds productFeatureApplTypeId field to getProductFeatureSet service</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-07-06 17:26:05</issue_when>
- <thetext>Adds productFeatureApplTypeId as optional field to getProductFeatureSet service.
- If none is specified, it will still search for &quot;SELECTABLE_FEATURE&quot;s (to be
-compatible with existing code), but if one is specified, it will use that
-productFeatureApplTypeId, so the same service can now be used to search for
-STANDARD, DISTINGUISHING, OPTIONAL features.</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-07-06 17:27:49</issue_when>
- <thetext>Created an attachment (id=82)
-Extends getProductFeatures with optional productFeatureApplTypeId field
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-07-07 01:21:37</issue_when>
- <thetext>It&apos;s in CVS now, thanks Si!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>82</attachid>
- <date>2004-07-06 17:27:49</date>
- <desc>Extends getProductFeatures with optional productFeatureApplTypeId field</desc>
- <ispatch>1</ispatch>
- <filename>ProductServices_2.patch</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/82/ProductServices_2.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-07-06 17:27:49</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=82)
-Extends getProductFeatures with optional productFeatureApplTypeId field
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:21:37</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 01:21:37</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>160</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040707144701</delta_ts>
- <subcomponent>Entity Extensions</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-07-07 07:27:45</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>implement condition versions of functions in entityext</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-07 07:27:45</issue_when>
- <thetext>I had sent an earlier version of this patch to the mailing list. I&apos;m now adding
-it as an issue, as I have for all the other patches.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-07 07:28:22</issue_when>
- <thetext>Created an attachment (id=83)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-07-07 14:47:01</issue_when>
- <thetext>This is now in CVS. Thanks Adam!</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>83</attachid>
- <date>2004-07-07 07:28:22</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>cache-entityext.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/83/cache-entityext.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-07-07 07:28:22</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=83)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 14:47:01</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-07 14:47:01</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>161</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040708153407</delta_ts>
- <subcomponent>WebTools</subcomponent>
- <reporter>doogie</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-07-08 11:51:01</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>NPE in FindUtilCacheElements.jsp</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-08 11:51:01</issue_when>
- <thetext>Missed one NPE when key is null(calls key.toString()).</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-08 11:51:22</issue_when>
- <thetext>Created an attachment (id=84)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-07-08 15:34:07</issue_when>
- <thetext>Thanks Adam, it is now in CVS.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>84</attachid>
- <date>2004-07-08 11:51:22</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>FindUtilCacheElements.jsp.patch</filename>
- <submitter_id>270</submitter_id>
- <submitting_username>doogie</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/84/FindUtilCacheElements.jsp.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>doogie</user>
- <when>2004-07-08 11:51:22</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=84)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-08 15:34:07</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-08 15:34:07</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>162</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>WORKSFORME</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040713170819</delta_ts>
- <subcomponent>Workflow</subcomponent>
- <reporter>ktippetts</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-07-12 09:32:42</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>Linux</op_sys>
- <short_desc>NoSuchMethodError in Entity Data Maintenance</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>ktippetts</who>
- <issue_when>2004-07-12 09:32:42</issue_when>
- <thetext>Getting this error when trying to view entity data in Webtools | Entity Data
-Maintenance:
-
-&lt;snip&gt;
-Exception: java.lang.NoSuchMethodError
-Message:
-org.ofbiz.entity.condition.EntityFieldMap.&lt;init&gt;(Ljava/util/Map;Lorg/ofbiz/entity/condition/EntityOperator;)V
------ stack trace ----------------------------------------
-java.lang.NoSuchMethodError:
-org.ofbiz.entity.condition.EntityFieldMap.&lt;init&gt;(Ljava/util/Map;Lorg/ofbiz/entity/condition/EntityOperator;)V
-org.apache.jsp.entity.FindGeneric_jsp._jspService(FindGeneric_jsp.java:159)
-&lt;snip&gt;
-
-To duplicate Using CVS code as of 09Jul2004:
-* Webtools &gt; Entity Data Maintenance
-* Click &apos;All&apos; on any entity.
-
-Possible Solution:
-* in FindGeneric.jsp (line 94) change 2nd parameter to EntityJoinOperator.AND</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-07-12 20:41:10</issue_when>
- <thetext>This works fine from a clean compile, but if have partial old code and partial new code in a build it may
-have problems. Try an &quot;ant clean&quot; and then an &quot;ant&quot;.</thetext>
- </long_desc>
- <long_desc>
- <who>doogie</who>
- <issue_when>2004-07-13 17:08:19</issue_when>
- <thetext>The signature of the constructor changed. It used to take an EntityOperator.
-However, the code only accepted an EntityJoinOperator. Passing in an
-EntityComparisonOperator would have caused it to fail.
-
-Also, running ant clean will *not* fix the problem. The parsed/compiled jsp
-pages need to be cleaned out.</thetext>
- </long_desc>
- <activity>
- <user>jonesde</user>
- <when>2004-07-12 20:41:10</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-12 20:41:10</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>WORKSFORME</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>163</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Documentation</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040730150851</delta_ts>
- <subcomponent>website</subcomponent>
- <reporter>michaelrempel</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>TASK</issue_type>
- <creation_ts>2004-07-13 11:11:43</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>cant get csv instructions</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>michaelrempel</who>
- <issue_when>2004-07-13 11:11:43</issue_when>
- <thetext>When I pull up csv instructions for either the wincsv or command line, I get a
-logon request screen, even though I am logged on.
-
-Thx
-
-Michael Rempel</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 15:08:51</issue_when>
- <thetext>This is a java.net related issue not OFBiz; please contact the Java.Net team for help.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 15:08:51</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 15:08:51</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>164</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040730204811</delta_ts>
- <subcomponent>Security</subcomponent>
- <reporter>adrianc</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-07-14 12:24:23</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>SecurityData.xml File</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>adrianc</who>
- <issue_when>2004-07-14 12:24:23</issue_when>
- <thetext>From mailing list:
-
-On Jul 14, 2004, at 12:03 PM, Adrian Crum wrote:
-
-&gt; I was just wondering...
-&gt;
-&gt; Why is the security data for ALL components in the SecurityData.xml file? This
-file looks monolithic. Shouldn&apos;t each component load its own security data?
-&gt;
-&gt; -Adrian
-
-
-Adrian,
-
-Yes, good point, monolithic is a good word for this. Ideally it should be split
-up, I think that&apos;s a good idea.
-
-If anyone wants to work on this please do... In the mean time it might be a good
-idea to create an issue for it.
-
--David</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 20:48:11</issue_when>
- <thetext>applied patch file(s); now in CVS</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 20:48:11</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 20:48:11</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>165</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P4</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040730065021</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>pgoron</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-07-15 06:34:37</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Allow user to specify default value for desired delivery date and comment fields in order entry GUI</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-07-15 06:34:37</issue_when>
- <thetext>This patch allows user to define default desired delivery date and default
-comment during quickaddform filling in OrderEntry page. Thus, users are not
-obliged any more to reinput these informations for each order item.</thetext>
- </long_desc>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-07-15 06:35:35</issue_when>
- <thetext>Created an attachment (id=85)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-07-30 06:50:21</issue_when>
- <thetext>The patch is in CVS.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>85</attachid>
- <date>2004-07-15 06:35:35</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>order20040707.patch</filename>
- <submitter_id>392</submitter_id>
- <submitting_username>pgoron</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/85/order20040707.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>pgoron</user>
- <when>2004-07-15 06:35:35</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=85)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-15 16:16:54</when>
- <field_name>assigned_to</field_name>
- <field_desc>Assigned To</field_desc>
- <oldvalue>issues@ofbiz</oldvalue>
- <newvalue>ajzeneski</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-07-15 16:16:54</when>
- <field_name>issue_type</field_name>
- <field_desc>Issue Type</field_desc>
- <oldvalue>ENHANCEMENT</oldvalue>
- <newvalue>PATCH</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-30 06:50:21</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-30 06:50:21</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>166</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040730115233</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>pgoron</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-07-21 02:46:56</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Allow user to associate parties to an order in OrderEntry website</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-07-21 02:46:56</issue_when>
- <thetext>Hi,
-
-Currently, I did not found any way to associate additional parties to an order.
-That&apos;s why I&apos;ve written this enhancement patch.
-
-
-This patch adds a new step during order entry in which user can associate
-additional party&amp;role to order. Then, these informations are stored in OrderRole
-entity.
-
-
-List of modifications :
-- I&apos;ve written a new view in which user can select a party and party&apos;s role to
-associate to order
-+ webapp/ordermgr/entry/SetAdditionalParty.ftl
-+ webapp/ordermgr/WEB-INF/actions/entry/SetAdditionalParty.bsh
-+ webapp/ordermgr/WEB-INF/pagedefs/entry/SetAdditionalParty.xml
-+ webapp/ordermgr/entry/AdditionalPartyListing.ftl
-+ webapp/ordermgr/WEB-INF/actions/entry/AdditionalPartyListing.bsh
-+ webapp/ordermgr/entry/PartySettingsForm.xml
-M webapp/ordermgr/WEB-INF/controller.xml
-
-- I&apos;ve included list of additional parties associated to order in confimorder view
-M webapp/ordermgr/entry/confirmorder.ftl
-M webapp/ordermgr/WEB-INF/pagedefs/entry/confirmorder.xml
-
-- I&apos;ve modified these files so that my view is shown before order confirmation
-M src/org/ofbiz/order/shoppingcart/CheckOutEvents.java
-M webapp/ordermgr/entry/showcart.ftl
-
-- I&apos;ve modified storeOrder service and ShoppingCart to take in account
-additional parties.
-M servicedef/services.xml
-M src/org/ofbiz/order/order/OrderServices.java
-M src/org/ofbiz/order/shoppingcart/ShoppingCartEvents.java
-M src/org/ofbiz/order/shoppingcart/ShoppingCart.java
-
-- I&apos;ve copied some files from content module to be able to use GenericLookup.
-+ src/org/ofbiz/order/lookupParams.java
-+ webapp/ordermgr/lookup/FieldLookupForms.xml
-+ webapp/ordermgr/lookup/GenericLookup.ftl
-+ webapp/ordermgr/templates/lookup.ftl
-+ webapp/ordermgr/templates/lookup.xml
-+ webapp/ordermgr/WEB-INF/actions/includes/findprepLk.bsh
-+ webapp/ordermgr/WEB-INF/actions/includes/formprep.bsh
-+ webapp/ordermgr/WEB-INF/actions/includes/pagelistprepLk.bsh
-+ webapp/ordermgr/WEB-INF/pagedefs/lookup/GenericLookup.xml</thetext>
- </long_desc>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-07-21 02:47:42</issue_when>
- <thetext>Created an attachment (id=86)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-07-22 00:38:39</issue_when>
- <thetext>I&apos;ve found some minor mistakes. I am correcting them and I will send a new patch
-as soon as possible.</thetext>
- </long_desc>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-07-22 01:29:07</issue_when>
- <thetext>Created an attachment (id=87)
-The corrected patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>jacopo</who>
- <issue_when>2004-07-30 11:52:33</issue_when>
- <thetext>The patches are in CVS.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>86</attachid>
- <date>2004-07-21 02:47:42</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>order20040721.patch</filename>
- <submitter_id>392</submitter_id>
- <submitting_username>pgoron</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/86/order20040721.patch</attachment_iz_url>
- </attachment>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>87</attachid>
- <date>2004-07-22 01:29:07</date>
- <desc>The corrected patch</desc>
- <ispatch>1</ispatch>
- <filename>order20040722.patch</filename>
- <submitter_id>392</submitter_id>
- <submitting_username>pgoron</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/87/order20040722.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>pgoron</user>
- <when>2004-07-21 02:47:42</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=86)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>pgoron</user>
- <when>2004-07-22 01:29:07</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=87)
-The corrected patch
-</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-30 11:52:33</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jacopo</user>
- <when>2004-07-30 11:52:33</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>167</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040730145814</delta_ts>
- <subcomponent>Accounting</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-07-28 17:15:09</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Fixes a couple of other getNextSeqId methods</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-07-28 17:15:09</issue_when>
- <thetext>getNextSeqId now returns a string(), so .toString() is no longer needed and will
-cause runtime exceptions.</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-07-28 17:19:29</issue_when>
- <thetext>Created an attachment (id=88)
-Changes getNextSeqId usage to PaymentGatewayServices and GenericAsyncEngine
-</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 14:58:14</issue_when>
- <thetext>patch applied</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>88</attachid>
- <date>2004-07-28 17:19:29</date>
- <desc>Changes getNextSeqId usage to PaymentGatewayServices and GenericAsyncEngine</desc>
- <ispatch>1</ispatch>
- <filename>changes.txt</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/88/changes.txt</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-07-28 17:19:29</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=88)
-Changes getNextSeqId usage to PaymentGatewayServices and GenericAsyncEngine
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 14:58:14</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 14:58:14</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>168</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040730144804</delta_ts>
- <subcomponent>Content</subcomponent>
- <reporter>pgoron</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-07-29 02:43:55</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>FreeMarker localization issues</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-07-29 02:43:55</issue_when>
- <thetext>Hi,
-
-This patch resolves some localization issues. Currently, FreeMarker formats
-number according to the machine&apos;s locale. My patch forces FreeMarker to use the
-user session&apos;s locale.
-
-It must be applied in ofbiz/components/content/src/org/ofbiz/content/webapp/ftl
-folder.</thetext>
- </long_desc>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-07-29 02:45:19</issue_when>
- <thetext>Created an attachment (id=89)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 14:48:04</issue_when>
- <thetext>This has been fixed in CVS</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>89</attachid>
- <date>2004-07-29 02:45:19</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>locale-freemaker-200040727.patch</filename>
- <submitter_id>392</submitter_id>
- <submitting_username>pgoron</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/89/locale-freemaker-200040727.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>pgoron</user>
- <when>2004-07-29 02:45:19</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=89)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 14:48:04</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 14:48:04</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>169</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>PC</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040730220642</delta_ts>
- <subcomponent>E-Commerce</subcomponent>
- <reporter>amheiss</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-07-30 09:53:11</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc>https://localhost:8443/ecommerce/control/finalizeOrder</issue_file_loc>
- <votes></votes>
- <op_sys>Linux</op_sys>
- <short_desc>Party/Userlogin issues</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>amheiss</who>
- <issue_when>2004-07-30 09:53:11</issue_when>
- <thetext>Application will not allow run of createPartyPostalAddress (due to null user
-login?). Sequence of events from july 30th, 11am build: goto ecommerce,
-login, then logout. attempt to use anonymous checkout after this, and shipping
-address feilds prepopulated with previous logins settings. After adjusting and
-trying to save, get error &apos;User authorization is required for this service:
-createPartyPostalAddress &apos; .
-
-Debug output from shipsettings.bsh:
-Debug.log(&quot;party ID : &quot; + partyId); ---&gt; output admin ( i logged in as admin,
-then logged out)
-Debug.log(&quot;ul: &quot; + session.getAttribute(&quot;userLogin&quot;)); ---&gt; (null)</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-07-30 22:06:42</issue_when>
- <thetext>Yes, if there is an autoUserLogin attribute available that will break anonymous checkout. In theory, the
-anonymous checkout links should not be displayed if there is an auto-userlogin. However, I have added
-some code to clear this when entering the anonymous checkout process.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 22:06:42</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-07-30 22:06:42</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>170</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040804093020</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>ENHANCEMENT</issue_type>
- <creation_ts>2004-08-03 17:02:41</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Optionally duplicates ProductContent when duplicating a Product</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-08-03 17:02:41</issue_when>
- <thetext>Will now optionally duplicate ProductContent entries when duplicating a Product</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-08-03 17:03:19</issue_when>
- <thetext>Created an attachment (id=90)
-Patches services.xml, EditProduct.ftl, and ProductServices.xml
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-08-04 09:30:20</issue_when>
- <thetext>Thanks Si. This is now in CVS. I also did a content remove option, and fixed an issue I noticed with the
-product IDs (GoodIdentification). BTW, this is from a slightly earlier version of OFBiz than the current
-CVS as this form has been moved to the file EditProductDupForm.ftl.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>90</attachid>
- <date>2004-08-03 17:03:19</date>
- <desc>Patches services.xml, EditProduct.ftl, and ProductServices.xml</desc>
- <ispatch>1</ispatch>
- <filename>duplicateProduct.patch</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/90/duplicateProduct.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-08-03 17:03:19</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=90)
-Patches services.xml, EditProduct.ftl, and ProductServices.xml
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-04 09:30:20</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-04 09:30:20</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>171</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P2</priority>
- <resolution>FIXED</resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040804091929</delta_ts>
- <subcomponent>Product</subcomponent>
- <reporter>pgoron</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-08-04 00:59:53</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Comparaison bug in InventoryServices.xml minilang script</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-08-04 00:59:53</issue_when>
- <thetext>Some if-compare element forget to declare type used to compare fields. By
-default, string comparison is used whereas Double is required.
-
-
-Applying patch :
-cd /ofbiz/components/product/script/org/ofbiz/product/inventory
-patch -p0 &lt; InventoryServices.xml.patch</thetext>
- </long_desc>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-08-04 01:01:13</issue_when>
- <thetext>Created an attachment (id=91)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-08-04 09:19:29</issue_when>
- <thetext>Thanks, it&apos;s now in CVS.</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>91</attachid>
- <date>2004-08-04 01:01:13</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>InventoryServices.xml.patch</filename>
- <submitter_id>392</submitter_id>
- <submitting_username>pgoron</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/91/InventoryServices.xml.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>pgoron</user>
- <when>2004-08-04 01:01:13</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=91)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-04 09:19:29</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-04 09:19:29</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>172</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P2</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040819033400</delta_ts>
- <subcomponent>Order</subcomponent>
- <reporter>pgoron</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-08-05 07:09:49</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Bug in shippableWeight calculation from OrderReadHelper.getShippableWeight method</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-08-05 07:09:49</issue_when>
- <thetext>Hi,
-
-The purpose of this patch is to solve a bug in
-OrderReadHelper.getShippableWeight method. The algorithm of shippable weight
-calculation don&apos;t care of order item&apos;s quantity. So there is an inconsistency
-with ShoppingCart.getShippableWeight method when order is modified after his
-creation (for example, by RecalcShippingTotal service).
-
-Applying patch:
-cd ofbiz/components/order/src/org/ofbiz/order/order
-patch -p0 &lt; OrderReadHelper-20040805.patch
-
-Peter Goron</thetext>
- </long_desc>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-08-05 07:10:36</issue_when>
- <thetext>Created an attachment (id=92)
-The patch
-</thetext>
- </long_desc>
- <long_desc>
- <who>pgoron</who>
- <issue_when>2004-08-19 03:34:00</issue_when>
- <thetext>Created an attachment (id=96)
-An up to date patch
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>92</attachid>
- <date>2004-08-05 07:10:36</date>
- <desc>The patch</desc>
- <ispatch>1</ispatch>
- <filename>OrderReadHelper-20040805.patch</filename>
- <submitter_id>392</submitter_id>
- <submitting_username>pgoron</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/92/OrderReadHelper-20040805.patch</attachment_iz_url>
- </attachment>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>96</attachid>
- <date>2004-08-19 03:34:00</date>
- <desc>An up to date patch</desc>
- <ispatch>1</ispatch>
- <filename>OrderReadHelper-200408019.patch</filename>
- <submitter_id>392</submitter_id>
- <submitting_username>pgoron</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/96/OrderReadHelper-200408019.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>pgoron</user>
- <when>2004-08-05 07:10:36</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=92)
-The patch
-</newvalue>
- </activity>
- <activity>
- <user>pgoron</user>
- <when>2004-08-19 03:34:00</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=96)
-An up to date patch
-</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>173</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>INVALID</resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>PC</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040809165336</delta_ts>
- <subcomponent>Startup</subcomponent>
- <reporter>mn</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-08-09 13:38:08</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>Linux</op_sys>
- <short_desc>typo in base/config/debug.properties</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>mn</who>
- <issue_when>2004-08-09 13:38:08</issue_when>
- <thetext>Index: base/config/debug.properties
-===================================================================
-RCS file: /cvs/ofbiz/base/config/debug.properties,v
-retrieving revision 1.10
-diff -u -r1.10 debug.properties
---- base/config/debug.properties 9 Jun 2004 18:12:59 -0000 1.10
-+++ base/config/debug.properties 9 Aug 2004 19:32:33 -0000
-@@ -7,7 +7,7 @@
- pack.exception=true
-
- # These top level switches are used before calling Log4J, or if Log4J is not used
--print.verbose=ftrue
-+print.verbose=true
- print.timing=true
- print.info=true
- print.important=true</thetext>
- </long_desc>
- <long_desc>
- <who>mn</who>
- <issue_when>2004-08-09 13:40:09</issue_when>
- <thetext>Created an attachment (id=93)
-corerct typo for print.verbose property
-</thetext>
- </long_desc>
- <long_desc>
- <who>jonesde</who>
- <issue_when>2004-08-09 16:25:29</issue_when>
- <thetext>In this case &quot;ftrue&quot; is not a misspelling of &quot;true&quot;, we add the &quot;f&quot; before &quot;true&quot; so that it is easier to switch
-between true and false than it would be to type out &quot;true&quot; and &quot;false&quot;. In other words, anything but
-&quot;true&quot; is false.</thetext>
- </long_desc>
- <long_desc>
- <who>mn</who>
- <issue_when>2004-08-09 16:53:36</issue_when>
- <thetext>What about placing comment into debug.properties about this decision?</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>93</attachid>
- <date>2004-08-09 13:40:09</date>
- <desc>corerct typo for print.verbose property</desc>
- <ispatch>1</ispatch>
- <filename>debug.properties.patch</filename>
- <submitter_id>377</submitter_id>
- <submitting_username>mn</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/93/debug.properties.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>mn</user>
- <when>2004-08-09 13:40:09</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=93)
-corerct typo for print.verbose property
-</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-09 16:25:29</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>jonesde</user>
- <when>2004-08-09 16:25:29</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>INVALID</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>174</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040810161004</delta_ts>
- <subcomponent>Accounting</subcomponent>
- <reporter>amheiss</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>PATCH</issue_type>
- <creation_ts>2004-08-10 16:08:36</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>retry failed auths fix</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>amheiss</who>
- <issue_when>2004-08-10 16:08:36</issue_when>
- <thetext>retryFailedAuths service was creating superfluous retryFailedOrderAuth
-services. I&apos;ll see if i can attach the patch to check on order status before
-dispatching retryFailedOrderAuth service. If not, patch will be to dev list
-soon enough.</thetext>
- </long_desc>
- <long_desc>
- <who>amheiss</who>
- <issue_when>2004-08-10 16:10:04</issue_when>
- <thetext>Created an attachment (id=94)
-Patch for retryFailedAuth fix
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>94</attachid>
- <date>2004-08-10 16:10:04</date>
- <desc>Patch for retryFailedAuth fix</desc>
- <ispatch>1</ispatch>
- <filename>retryAuth.patch</filename>
- <submitter_id>336</submitter_id>
- <submitting_username>amheiss</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/94/retryAuth.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>amheiss</user>
- <when>2004-08-10 16:10:04</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=94)
-Patch for retryFailedAuth fix
-</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>175</issue_id>
- <issue_status>RESOLVED</issue_status>
- <priority>P3</priority>
- <resolution>FIXED</resolution>
- <component>foo</component>
- <version>unspecified</version>
- <rep_platform>All</rep_platform>
- <assigned_to>ajzeneski</assigned_to>
- <delta_ts>20040817213241</delta_ts>
- <subcomponent>bar</subcomponent>
- <reporter>ajzeneski</reporter>
- <target_milestone>milestone 1</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-08-17 21:31:38</creation_ts>
- <qa_contact>ajzeneski</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>bar</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-08-17 21:31:38</issue_when>
- <thetext>foo</thetext>
- </long_desc>
- <long_desc>
- <who>ajzeneski</who>
- <issue_when>2004-08-17 21:32:41</issue_when>
- <thetext>.</thetext>
- </long_desc>
- <activity>
- <user>ajzeneski</user>
- <when>2004-08-17 21:32:41</when>
- <field_name>issue_status</field_name>
- <field_desc>Status</field_desc>
- <oldvalue>NEW</oldvalue>
- <newvalue>RESOLVED</newvalue>
- </activity>
- <activity>
- <user>ajzeneski</user>
- <when>2004-08-17 21:32:41</when>
- <field_name>resolution</field_name>
- <field_desc>Resolution</field_desc>
- <oldvalue></oldvalue>
- <newvalue>FIXED</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>176</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Components</component>
- <version>CVS</version>
- <rep_platform>All</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040818174622</delta_ts>
- <subcomponent>Content</subcomponent>
- <reporter>sichen</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>DEFECT</issue_type>
- <creation_ts>2004-08-18 17:45:44</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>All</op_sys>
- <short_desc>Possible bug in renderContentAsText</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-08-18 17:45:44</issue_when>
- <thetext>It seems that renderContentAsText is still trying to do a findByAnd on
-SubContentDataResourceView with a fromDate as the orderBy, whereas
-renderContentAsTextCache no longer does (it passes a null.) We got an
-exception from this in ProductContentWrapper and made this change to fix it.
-Is this a defect?</thetext>
- </long_desc>
- <long_desc>
- <who>sichen</who>
- <issue_when>2004-08-18 17:46:22</issue_when>
- <thetext>Created an attachment (id=95)
-Changes findByAnd of SubContentDataResourceView
-</thetext>
- </long_desc>
- <attachment encoding='Base64'>
- <mimetype>text/plain</mimetype>
- <attachid>95</attachid>
- <date>2004-08-18 17:46:22</date>
- <desc>Changes findByAnd of SubContentDataResourceView</desc>
- <ispatch>1</ispatch>
- <filename>ContentWorker.patch</filename>
- <submitter_id>178</submitter_id>
- <submitting_username>sichen</submitting_username>
- <data></data>
- <attachment_iz_url>https://ofbiz.dev.java.net/nonav/issues/showattachment.cgi/95/ContentWorker.patch</attachment_iz_url>
- </attachment>
- <activity>
- <user>sichen</user>
- <when>2004-08-18 17:46:22</when>
- <field_name>attachments.ispatch</field_name>
- <field_desc>Attachment is Patch</field_desc>
- <oldvalue></oldvalue>
- <newvalue>Created an attachment (id=95)
-Changes findByAnd of SubContentDataResourceView
-</newvalue>
- </activity>
-</issue>
-<issue status_code="200" status_message="OK">
- <issue_id>177</issue_id>
- <issue_status>NEW</issue_status>
- <priority>P3</priority>
- <resolution></resolution>
- <component>Base</component>
- <version>CVS</version>
- <rep_platform>Other</rep_platform>
- <assigned_to>issues@ofbiz</assigned_to>
- <delta_ts>20040910075014</delta_ts>
- <subcomponent>Base</subcomponent>
- <reporter>lrawley</reporter>
- <target_milestone>not determined</target_milestone>
- <issue_type>TASK</issue_type>
- <creation_ts>2004-09-10 07:50:14</creation_ts>
- <qa_contact>issues@ofbiz</qa_contact>
- <status_whiteboard></status_whiteboard>
- <issue_file_loc></issue_file_loc>
- <votes></votes>
- <op_sys>Windows XP</op_sys>
- <short_desc>HTTP Header needs Expires</short_desc>
- <keywords></keywords>
- <long_desc>
- <who>lrawley</who>
- <issue_when>2004-09-10 07:50:14</issue_when>
- <thetext>Using Internet Explorer 6.0 with settings for automatically obtaining newer
-versions of page.
-
-Images are cached and if changed are not refreshed on visits to the same page.
-Pages get cached with login page because the first time a user requested they
-were prompted to login first and then redirected to the page.
-
-This behavior is resolved if set to obtain newer versions on every visit,
-however, this causes performance issues. So, automatically is the desired
-browser setting.
-
-I would like to be able to set the EXPIRE in the HTTP header. I&apos;m not sure
-where this change needs to occur. Can you assist? Is this available in 3.0?
-I am using 2.1.1.
-
-Please contact me at lrawley@tla.com.
-
-Lisa Rawley</thetext>
- </long_desc>
-</issue>
-</issuezilla>
diff --git a/test/rexml/data/pi.xml b/test/rexml/data/pi.xml
deleted file mode 100644
index 980bbf98ec..0000000000
--- a/test/rexml/data/pi.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0"?>
-<foo>
- <?cheese is tasty?>
- <bar>
- <baz/>
- <cheese/>
- <baz/>
- <?toast is tasty?>
- <cheese/>
- <baz/>
- </bar>
- <?cheese is gooey?>
-</foo>
diff --git a/test/rexml/data/pi2.xml b/test/rexml/data/pi2.xml
deleted file mode 100644
index 46bce4505f..0000000000
--- a/test/rexml/data/pi2.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0"?>
-<a>
- <b>foo</b>
- <?toc order-by="x"?>
- <c>bar</c>
-</a>
diff --git a/test/rexml/data/project.xml b/test/rexml/data/project.xml
deleted file mode 100644
index a02582fde5..0000000000
--- a/test/rexml/data/project.xml
+++ /dev/null
@@ -1 +0,0 @@
-<Project id="17" Name="dave test" Deprecated="false"><Creator User="etools" Date="10/24/00 10:54 AM"></Creator><LastModifier User="Default" Date="Fri Jun 22 14:01:54 PDT 2001"></LastModifier><Description>tool testing</Description><Purpose> </Purpose><Datasets><link name="Test data 1" idref="18"></link><link name="veg plot data" idref="21"></link></Datasets></Project>
diff --git a/test/rexml/data/simple.xml b/test/rexml/data/simple.xml
deleted file mode 100644
index 3cff71a02b..0000000000
--- a/test/rexml/data/simple.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" ?>
-<root><a>a</a><b>b</b><c><d>d</d></c></root>
diff --git a/test/rexml/data/stream_accents.xml b/test/rexml/data/stream_accents.xml
deleted file mode 100644
index 6def54ee55..0000000000
--- a/test/rexml/data/stream_accents.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<g>
-<f a="" />
-</g>
diff --git a/test/rexml/data/t63-1.xml b/test/rexml/data/t63-1.xml
deleted file mode 100644
index f8d0c543ef..0000000000
--- a/test/rexml/data/t63-1.xml
+++ /dev/null
Binary files differ
diff --git a/test/rexml/data/t63-2.svg b/test/rexml/data/t63-2.svg
deleted file mode 100644
index 706c0e96bd..0000000000
--- a/test/rexml/data/t63-2.svg
+++ /dev/null
@@ -1,2828 +0,0 @@
-<?xml version="1.0" encoding="UTF-16"?>
-<svg height="647px" width="1024px" viewBox="-800000 -505508 1600000 1011016" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:rgr="http://www.abbnm.com/ranger">
- <defs>
- <font id="pedDef" horiz-adv-x="1470">
- <font-face font-family="PED2" units-per-em="2048" panose-1="0 0 0 0 0 0 0 0 0 0" ascent="1536" descent="-348" alphabetic="0"/>
- <missing-glyph horiz-adv-x="1024"/>
- <glyph unicode="!" glyph-name="down-arrow" horiz-adv-x="848" d="M14 819L424 0L834 819L526 614V1434H322V614L14 819Z"/>
- <glyph unicode="!" glyph-name="right-arrow" horiz-adv-x="1460" d="M625 410L1444 819L625 1229L829 922H10V717H829L625 410Z"/>
- <glyph unicode="!" glyph-name="left-arrow" horiz-adv-x="1460" d="M836 1229L16 819L836 410L631 717H1450V922H631L836 1229Z"/>
- <glyph unicode="!" glyph-name="up-arrow" horiz-adv-x="848" d="M834 614L424 1434L14 614L322 819V0H526V819L834 614Z"/>
- <glyph unicode="!" glyph-name="ne-arrow" horiz-adv-x="1118" d="M809 360L1098 1229L229 940L592 868L12 289L158 143L737 723L809 360Z"/>
- <glyph unicode="!" glyph-name="se-arrow" horiz-adv-x="1118" d="M229 494L1098 205L809 1073L737 711L158 1290L12 1145L592 565L229 494Z"/>
- <glyph unicode="!" glyph-name="nw-arrow" horiz-adv-x="1118" d="M889 940L20 1229L309 360L381 723L961 143L1106 289L526 868L889 940Z"/>
- <glyph unicode="!" glyph-name="sw-arrow" horiz-adv-x="1118" d="M309 1073L20 205L889 494L526 565L1106 1145L961 1290L381 711L309 1073Z"/>
- <glyph unicode="%" glyph-name="vert-bar" horiz-adv-x="2355" d="M1229 -410H1126V1843H1229V-410Z"/>
- <glyph unicode="%" glyph-name="sw-corner" horiz-adv-x="2355" d="M1126 1843V614H2355V717H1229V1843H1126Z"/>
- <glyph unicode="%" glyph-name="horiz-bar" horiz-adv-x="2355" d="M0 614H2355V717H0V614Z"/>
- <glyph unicode="%" glyph-name="right-t" horiz-adv-x="2355" d="M1229 614H2355V717H1229V1843H1126V-410H1229V614Z"/>
- <!-- The following glyphs reside in the private use area of the Unicode standard -->
- <glyph unicode="" glyph-name="thin-rt-arrow" horiz-adv-x="1808" d="M1741 666L1024 307L1229 614H0V717H1229L1024 1024L1741 666Z"/>
- <glyph unicode="" glyph-name="ground" horiz-adv-x="1128" d="M463 -51H666V-51V51H463V-51V-51ZM819 307V205H309V307H819ZM973 563V461H156V563H973ZM2 717H1126V819H614V1434H514V819H2V717Z"/>
- <glyph unicode="" glyph-name="ground-right" horiz-adv-x="1509" d="M1491 666V868V868H1389V666H1491V666ZM1133 1022H1235V512H1133V1022ZM877 1176H979V358H877V1176ZM723 205V1329H621V817H6V717H621V205H723Z"/>
- </font>
- <g id="symbol639">
- <title>SYMBOL 640</title>
- <g stroke="none" transform=" translate(27, -27)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">OFF</text>
- </g>
- </g>
- <g id="symbol641">
- <title>SYMBOL 642</title>
- <g stroke="none">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">NORMAL</text>
- </g>
- </g>
- <g id="symbol642">
- <title>SYMBOL 643</title>
- <g stroke="none" transform=" translate(27, -27)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">ARMED</text>
- </g>
- </g>
- <g id="symbol643">
- <title>SYMBOL 644</title>
- <g stroke="none">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">ALARM</text>
- </g>
- </g>
- <g id="symbol645">
- <title>SYMBOL 646</title>
- <g stroke="none">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">FAILED</text>
- </g>
- </g>
- <g id="symbol651">
- <title>SYMBOL 652</title>
- <g stroke="none" transform=" translate(27, -27)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">ON</text>
- </g>
- </g>
- <g id="symbol659">
- <title>SYMBOL 660</title>
- <g stroke="none" transform=" translate(27, -27)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">AUTO</text>
- </g>
- </g>
- <g id="symbol674">
- <title>SYMBOL 675</title>
- <g stroke="none">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">MARGINAL</text>
- </g>
- </g>
- <g id="symbol834">
- <title>SYMBOL 835</title>
- <g stroke="none" transform=" translate(0, 0)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">TRIPPED</text>
- </g>
- </g>
- <g id="symbol921">
- <title>SYMBOL 922</title>
- <g stroke="none">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">MANUAL</text>
- </g>
- </g>
- <g id="symbol1679">
- <title>Select</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">S</text>
- </g>
- </g>
- <g id="symbol1680">
- <title>Unack</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">U</text>
- </g>
- </g>
- <g id="symbol1681">
- <title>Alarm</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">A</text>
- </g>
- </g>
- <g id="symbol1682">
- <title>Deact</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">D</text>
- </g>
- </g>
- <g id="symbol1683">
- <title>Alinh</title>
- <g stroke="none" transform=" translate(-1790, 6666)">
- <text font-size="24357" font-family="PED2, Times New Roman" xml:space="preserve">I</text>
- </g>
- </g>
- <g id="symbol1684">
- <title>Telem</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">E</text>
- </g>
- </g>
- <g id="symbol1685">
- <title>Manual</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">M</text>
- </g>
- </g>
- <g id="symbol1686">
- <title>TagInfo</title>
- <g stroke="none" transform=" translate(-1751, 2911)">
- <text font-size="9955" font-family="PED2, Times New Roman" xml:space="preserve">I</text>
- </g>
- <g fill="none" stroke-width="1000" style=" stroke-dasharray: 16000 0 ;">
- <polygon points="-5833,-335 -509,5833 4659,-335 -509,-6326 -5833,-335 ">
- </polygon>
- </g>
- </g>
- <g id="symbol1687">
- <title>TagCtl</title>
- <g fill="none" stroke-width="1000" style=" stroke-dasharray: 16000 0 ;">
- <polygon points="-5000,81 323,6249 5493,81 323,-5909 -5000,81 ">
- </polygon>
- </g>
- <g stroke="none" transform=" translate(-3418, 3327)">
- <text font-size="9955" font-family="PED2, Arial" xml:space="preserve">N</text>
- </g>
- </g>
- <g id="symbol1688">
- <title>TagCls</title>
- <g fill="none" stroke-width="1000" style=" stroke-dasharray: 16000 0 ;">
- <polygon points="-5000,81 323,6249 5493,81 323,-5909 -5000,81 ">
- </polygon>
- </g>
- <g stroke="none" transform=" translate(-3418, 3327)">
- <text font-size="9955" font-family="PED2, Arial" xml:space="preserve">H</text>
- </g>
- </g>
- <g id="symbol1689">
- <title>TagOpn</title>
- <g stroke="none" transform=" translate(-3418, 3327)">
- <text font-size="9955" font-family="PED2, Arial" xml:space="preserve">O</text>
- </g>
- <g fill="none" stroke-width="1000" style=" stroke-dasharray: 16000 0 ;">
- <polygon points="-5000,81 323,6249 5493,81 323,-5909 -5000,81 ">
- </polygon>
- </g>
- </g>
- <g id="symbol1690">
- <title>RDV</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">R</text>
- </g>
- </g>
- <g id="symbol1691">
- <title>Gmerr</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">G</text>
- </g>
- </g>
- <g id="symbol1692">
- <title>Limovr</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">O</text>
- </g>
- </g>
- <g id="symbol1693">
- <title>Limit1</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">1</text>
- </g>
- </g>
- <g id="symbol1694">
- <title>Kimit2</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">2</text>
- </g>
- </g>
- <g id="symbol1695">
- <title>Limit3</title>
- <g stroke="none" transform=" translate(-8456, 6666)">
- <text font-size="24357" font-family="PED2, Arial" xml:space="preserve">3</text>
- </g>
- </g>
- </defs>
- <rgr:update display="A118TH-SO1">
- </rgr:update>
- <rgr:timestamp date="10301" time="57116000">
- </rgr:timestamp>
- <rect id="background" x="-800000" y="-505508" height="1011016" width="1600000" fill="#000000">
- </rect>
- <g id="layer32">
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-780000, -313333)">
- <text font-size="18018" font-family="PED2, Arial" xml:space="preserve">03/16/06 ADDED DFK 6 -- K. POPE</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-780000, -353333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">01/05/05 FIXED DFK'S -- K. POPE</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-780000, -373333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">10/14/04 CHANGED ACRONYM FOR REG CONTROL TO MANUAL / AUTO -- O. WAHLSTROM</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-780000, -473333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">12/24/03 DISPLAY BUILT AND DATA ADDED -- K. POPE</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-780000, -453333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">01/06/04 DISPLAY CORRECTED PER R. MCCORMICK -- N. FISHER</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-780000, -433333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">03/18/04 DISPLAY UPDATED/DFK'S FIXED/APPENDED SYMBOLS MOVED -- T. TURNER</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-780000, -413333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">03/29/04 REVIEWED -- O. WAHLSTROM</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-780000, -393333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">05/11/04 RTU BOX FIXED AND DISPLAY UPDATED -- K. POPE</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-780000, -333333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">10/18/05 REMOVED BUS VOLT MAXIMUM ALARM -- K. POPE</text>
- </g>
- </g>
- </g>
- <g id="layer1">
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-179999, -466666)">
- <text font-size="30029" font-family="PED2, Arial" xml:space="preserve">118TH SOUTH (118TH-SO)</text>
- </g>
- </g>
- <g>
- <g fill="none" stroke-width="1000" style=" stroke-dasharray: 16000 0 ;" stroke="#e1d3b3">
- <rect x="-753333" y="-500000" height="46666" width="1506666">
- </rect>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(481450, -466666)">
- <text font-size="25825" font-family="PED2, Arial" xml:space="preserve">Salt Lake County, Utah</text>
- </g>
- </g>
- <g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#e1d3b3">
- <rect x="-753333" y="-26666" height="520791" width="1506666">
- </rect>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-600000, 180000)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">REG 1 AUTOMATIC (C)</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-600000, 73333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">To control regulator, right click on the tap position</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-600000, 100000)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">indication and select the regulation option.</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(19999, -226666)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 TEMPERATURE</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(19999, -199999)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 NITROGEN CYL LOW</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(19999, -253333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 LOW OIL LEVEL</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(19999, -173333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 NITROGEN PRESSURE</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(20000, -146666)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 PRESSURE FAULT</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(20000, -119999)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 LTC CONTROL LOSS</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -93333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">RELAY LOSS OF AC</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -119999)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">STATION SERVICE</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(20000, -279999)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 LTC FAIL</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(20000, -306666)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 WINDING TEMP TRIP</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(20000, -333333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 LOCKOUT</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -253333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">CONTROL SYSTEM FAIL</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -279999)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">UNDER FREQ TRIP RELAY</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -306666)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">CB LOW SPRING CHARGE</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -333333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">RELAY FAILURE</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -146666)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">CAP 1 VOLT CONTROL (C)</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -173333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">HMI PLC STALLED</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -199999)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">XFMR 1 LTC FILTER</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-406666, -226666)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">CONTROL SYSTEM NON CRITICAL</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-86666, -406666)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">Station Alarms</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-140000, 20000)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">Regulator 1 Control and Tap Position</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-600000, 213333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">REG 1 TAP POSITION</text>
- </g>
- </g>
- <g transform="translate(-260000, 180000)" id="elm139">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol921" stroke="#ff0000" fill="#ff0000" visibility="inherit">
- </use>
- <use xlink:href="#symbol659" stroke="#00ffff" fill="#00ffff" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(77484, -6019) scale(0.678085)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(91920, -6019) scale(0.678085)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="REG 1 AUTOMATIC">
- </rgr:ranger>
- </g>
- <g>
- <g stroke="none" fill="#ba8864">
- <polygon points="-59607,187500 -59607,212499 59607,212499 59607,187500 -59607,187500 ">
- </polygon>
- </g>
- <g stroke="none" fill="#ffedb5">
- <polygon points="63333,183333 -63333,183333 -59607,187500 59607,187500 63333,183333 ">
- </polygon>
- </g>
- <g stroke="none" fill="#96825a">
- <polyline points="63333,216666 59607,212499 59607,187500 63333,183333 ">
- </polyline>
- </g>
- <g stroke="none" fill="#ffedb5">
- <polygon points="-63333,183333 -59607,187500 -59607,212499 -63333,216666 -63333,183333 ">
- </polygon>
- </g>
- <g stroke="none" fill="#96825a">
- <polyline points="-63333,216666 -59607,212500 59607,212500 63333,216666 ">
- </polyline>
- </g>
- </g>
- <g id="elm141">
- <g id="appended" transform="translate(-266371, 214890)">
- <g transform="translate(33332, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(43242, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <g stroke="none" fill="#00ffff" transform=" translate(-266371, 214890)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">- 12 </text>
- </g>
- <rgr:ranger type="analog" presentation="numeric" leftJust="false" pos=" " neg="-" substation="118TH.SO" point="REG 1 TAP POSITION">
- </rgr:ranger>
- </g>
- <g id="elm142">
- <g id="appended" transform="translate(-366666, 400000)">
- <g transform="translate(66365, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(76274, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <g stroke="none" fill="#00ffff" transform=" translate(-366666, 400000)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">- 1234.6 </text>
- </g>
- <rgr:ranger type="analog" presentation="numeric" leftJust="false" pos=" " neg="-" substation="118TH.SO" point="REG 1 A.PH 12KV BV">
- </rgr:ranger>
- </g>
- <g id="elm143">
- <g id="appended" transform="translate(-199999, 400000)">
- <g transform="translate(66365, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(76274, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <g stroke="none" fill="#00ffff" transform=" translate(-199999, 400000)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">- 1234.6 </text>
- </g>
- <rgr:ranger type="analog" presentation="numeric" leftJust="false" pos=" " neg="-" substation="118TH.SO" point="REG 1 B.PH 12KV BV">
- </rgr:ranger>
- </g>
- <g id="elm144">
- <g id="appended" transform="translate(-39999, 400000)">
- <g transform="translate(66365, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(76274, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <g stroke="none" fill="#00ffff" transform=" translate(-39999, 400000)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">- 1234.6 </text>
- </g>
- <rgr:ranger type="analog" presentation="numeric" leftJust="false" pos=" " neg="-" substation="118TH.SO" point="REG 1 C.PH 12KV BV">
- </rgr:ranger>
- </g>
- <g transform="translate(306666, -119999)" id="elm145">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 LTC CONTRL LOSS">
- </rgr:ranger>
- </g>
- <g transform="translate(306666, -146666)" id="elm146">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 PRESSURE FAULT">
- </rgr:ranger>
- </g>
- <g transform="translate(306666, -173333)" id="elm147">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 NITROGEN PRESS.">
- </rgr:ranger>
- </g>
- <g transform="translate(306666, -199999)" id="elm148">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 NITROGEN CYL LO">
- </rgr:ranger>
- </g>
- <g transform="translate(306666, -226666)" id="elm149">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 TEMP">
- </rgr:ranger>
- </g>
- <g transform="translate(306666, -253333)" id="elm150">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 LOW OIL LEVEL">
- </rgr:ranger>
- </g>
- <g transform="translate(306666, -333333)" id="elm151">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 LOCKOUT">
- </rgr:ranger>
- </g>
- <g transform="translate(306666, -306666)" id="elm152">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 WINDING TEMP">
- </rgr:ranger>
- </g>
- <g transform="translate(306666, -279999)" id="elm153">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 LTC FAIL">
- </rgr:ranger>
- </g>
- <g transform="translate(-120000, -93333)" id="elm154">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="RELAY LOSS OF AC">
- </rgr:ranger>
- </g>
- <g transform="translate(-119999, -119999)" id="elm155">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="STATION SERVICE">
- </rgr:ranger>
- </g>
- <g transform="translate(-119704, -146666)" id="elm156">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol639" stroke="#ff0000" fill="#ff0000" visibility="inherit">
- </use>
- <use xlink:href="#symbol651" stroke="#00ffff" fill="#00ffff" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(44470, -6033) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(58885, -6033) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="CAP 1 VOLT CTRL">
- </rgr:ranger>
- </g>
- <g transform="translate(-119999, -173333)" id="elm157">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="HMI PLC STALLED">
- </rgr:ranger>
- </g>
- <g transform="translate(-119999, -199999)" id="elm158">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="XFMR 1 LTC FILTER">
- </rgr:ranger>
- </g>
- <g transform="translate(-119999, -226666)" id="elm159">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="CTRL SYSTEM NON CRIT">
- </rgr:ranger>
- </g>
- <g transform="translate(-119999, -253333)" id="elm160">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="CTRL SYSTEM FAIL">
- </rgr:ranger>
- </g>
- <g transform="translate(-119999, -279999)" id="elm161">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="UNDER FREQ TRIP RELAY">
- </rgr:ranger>
- </g>
- <g transform="translate(-119999, -306666)" id="elm162">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="CB LOW SPRING CHARGE">
- </rgr:ranger>
- </g>
- <g transform="translate(-119999, -333333)" id="elm163">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="inherit">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(80479, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(94893, -6005) scale(0.677063)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="RELAY FAIL">
- </rgr:ranger>
- </g>
- <g id="elm164">
- <g stroke="none" fill="#bfbfbf" transform=" translate(476402, 49201)">
- <text font-size="29514" font-family="PED2, Arial" xml:space="preserve">16</text>
- </g>
- <g stroke="none" fill="#bfbfbf" transform=" translate(476402, 99717)">
- <text font-size="29514" font-family="PED2, Arial" xml:space="preserve">12</text>
- </g>
- <g stroke="none" fill="#bfbfbf" transform=" translate(476402, 150234)">
- <text font-size="29514" font-family="PED2, Arial" xml:space="preserve">8</text>
- </g>
- <g stroke="none" fill="#bfbfbf" transform=" translate(476402, 200750)">
- <text font-size="29514" font-family="PED2, Arial" xml:space="preserve">4</text>
- </g>
- <g stroke="none" fill="#bfbfbf" transform=" translate(476402, 251267)">
- <text font-size="29514" font-family="PED2, Arial" xml:space="preserve">0</text>
- </g>
- <g stroke="none" fill="#bfbfbf" transform=" translate(476402, 301783)">
- <text font-size="29514" font-family="PED2, Arial" xml:space="preserve">-4</text>
- </g>
- <g stroke="none" fill="#bfbfbf" transform=" translate(476402, 352300)">
- <text font-size="29514" font-family="PED2, Arial" xml:space="preserve">-8</text>
- </g>
- <g stroke="none" fill="#bfbfbf" transform=" translate(476402, 402816)">
- <text font-size="29514" font-family="PED2, Arial" xml:space="preserve">-12</text>
- </g>
- <g stroke="none" fill="#bfbfbf" transform=" translate(476402, 453333)">
- <text font-size="29514" font-family="PED2, Arial" xml:space="preserve">-16</text>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="414435,445954 414435,41822 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="462930,41822 414435,41822 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="462930,92339 414435,92339 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="462930,142855 414435,142855 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="462930,193372 414435,193372 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="462930,243888 414435,243888 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="462930,294405 414435,294405 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="462930,344921 414435,344921 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="462930,395438 414435,395438 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="462930,445954 414435,445954 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,54451 414435,54451 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,67081 414435,67081 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,79710 414435,79710 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,104968 414435,104968 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,117597 414435,117597 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,130226 414435,130226 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,155484 414435,155484 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,168113 414435,168113 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,180743 414435,180743 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,206001 414435,206001 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,218630 414435,218630 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,231259 414435,231259 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,256517 414435,256517 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,269146 414435,269146 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,281776 414435,281776 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,307034 414435,307034 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,319663 414435,319663 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,332292 414435,332292 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,357550 414435,357550 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,370179 414435,370179 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,382808 414435,382808 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,408067 414435,408067 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,420696 414435,420696 ">
- </polyline>
- </g>
- <g fill="none" stroke-width="2000" style=" stroke-dasharray: 16000 0 ;" stroke="#bfbfbf">
- <polyline points="438683,433325 414435,433325 ">
- </polyline>
- </g>
- <rgr:ranger type="analog" presentation="meter" min="-16.000000" max="16.000000" propagationDir="0" displayDir="1" substation="118TH.SO" point="REG 1 TAP POSITION">
- </rgr:ranger>
- <g fill="none" stroke="#ff0000" stroke-width="2000">
- <polyline points="0,0 0,0 0,0 0,0 0,0">
- </polyline>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-599290, 400000)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">REG 1 12KV BUS VOLTS</text>
- </g>
- </g>
- <g id="elm166">
- <g id="appended" transform="translate(-26371, 208223)">
- <g transform="translate(33332, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(43242, -6005) scale(0.677048)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <g stroke="none" fill="#1a1a1a" transform=" translate(-26371, 208223)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">- 12 </text>
- </g>
- <rgr:ranger type="analog" presentation="numeric" leftJust="false" pos=" " neg="-" substation="118TH.SO" point="REG 1 TAP POSITION">
- </rgr:ranger>
- </g>
- <g transform="translate(-506666, -353333)" id="elm167">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol834" stroke="#ff0000" fill="#ff0000" visibility="inherit">
- </use>
- <use xlink:href="#symbol642" stroke="#00ffff" fill="#00ffff" visibility="hidden">
- </use>
- </g>
- <g id="appended">
- <g transform="translate(83490, -6019) scale(0.678085)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- <g transform="translate(97926, -6019) scale(0.678085)">
- <use visibility="hidden" xlink:href="#symbol1679" stroke="#ffea00" fill="#ffea00">
- </use>
- <use visibility="hidden" xlink:href="#symbol1680" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1681" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1682" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1683" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1684" stroke="#377800" fill="#377800">
- </use>
- <use visibility="hidden" xlink:href="#symbol1685" stroke="#00ffff" fill="#00ffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1686" stroke="#ffffff" fill="#ffffff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1687" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1688" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1689" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1690" stroke="#5555ff" fill="#5555ff">
- </use>
- <use visibility="hidden" xlink:href="#symbol1691" stroke="#fe00fe" fill="#fe00fe">
- </use>
- <use visibility="hidden" xlink:href="#symbol1692" stroke="#ff6e05" fill="#ff6e05">
- </use>
- <use visibility="hidden" xlink:href="#symbol1693" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1694" stroke="#ff0000" fill="#ff0000">
- </use>
- <use visibility="hidden" xlink:href="#symbol1695" stroke="#ff0000" fill="#ff0000">
- </use>
- </g>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="118TH.SO" point="ENTRY">
- </rgr:ranger>
- </g>
- <g>
- <g stroke="none" fill="#ffffff" transform=" translate(-740000, -393333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">RTU STATUS:</text>
- </g>
- </g>
- <g transform="translate(-506666, -393333)" id="elm169">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol639" stroke="#ff0000" fill="#ff0000" visibility="inherit">
- </use>
- <use xlink:href="#symbol651" stroke="#00ffff" fill="#00ffff" visibility="hidden">
- </use>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="RTUERR.SE" point="481">
- </rgr:ranger>
- </g>
- <g>
- <g stroke="none" fill="#ffffff" transform=" translate(-740000, -373333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">RTU COMMUNICATIONS:</text>
- </g>
- </g>
- <g>
- <g stroke="none" fill="#eeeeee" transform=" translate(-740000, -353333)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">ENTRY</text>
- </g>
- </g>
- <g>
- <g fill="none" stroke-width="1000" style=" stroke-dasharray: 16000 0 ;" stroke="#e1d3b3">
- <rect x="-753333" y="-446666" height="106666" width="339999">
- </rect>
- </g>
- </g>
- <g>
- <g fill="none" stroke-width="1000" style=" stroke-dasharray: 16000 0 ;" stroke="#e1d3b3">
- <polyline points="-413333,-419999 -753333,-419999 ">
- </polyline>
- </g>
- </g>
- <g transform="translate(-506666, -373333)" id="elm174">
- <g id="status" transform="translate(0, 0)">
- <use xlink:href="#symbol645" stroke="#ff0000" fill="#ff0000" visibility="inherit">
- </use>
- <use xlink:href="#symbol641" stroke="#00ffff" fill="#00ffff" visibility="hidden">
- </use>
- <use xlink:href="#symbol674" stroke="#ffea00" fill="#ffea00" visibility="hidden">
- </use>
- <use xlink:href="#symbol643" stroke="#ff0000" fill="#ff0000" visibility="hidden">
- </use>
- </g>
- <rgr:ranger type="discrete" pos="+" neg="-" presentation="symbolic" substation="RTUERR.COM" point="481">
- </rgr:ranger>
- </g>
- <g>
- <g stroke="none" fill="#e1d3b3" transform=" translate(-626666, -426666)">
- <text font-size="18017" font-family="PED2, Arial" xml:space="preserve">RTU - 481</text>
- </g>
- </g>
- </g>
-</svg>
diff --git a/test/rexml/data/t75.xml b/test/rexml/data/t75.xml
deleted file mode 100644
index eb3cccee4b..0000000000
--- a/test/rexml/data/t75.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!-- generated by hnb 1.9.17 (http://hnb.sourceforge.net) -->
-
-<!DOCTYPE tree[
- <!ELEMENT tree (node*)>
- <!ELEMENT data (#PCDATA)> <!-- (max 4096 bytes long) -->
- <!ELEMENT node (data?,node*)>
- <!ATTLIST node done (yes|no) #IMPLIED
- type CDATA #IMPLIED
- >]>
-
-<tree>
-<node done="no" type="todo"><data>Next_Actions</data>
- <node done="no" type="todo"><data>@class</data></node>
- <node done="no" type="todo"><data>@agenda</data>
- <node done="yes" type="todo"><data>this is something I&apos;d like to do</data></node>
- </node>
- <node done="no" type="todo"><data>@dorm</data>
- <node done="no" type="todo"><data>clean room</data></node>
- </node>
- <node done="no" type="todo"><data>@computer</data>
- <node done="no" type="todo"><data>Write general makefile for cs projects</data></node>
- <node done="no" type="todo"><data>Set up bash podder</data></node>
- </node>
- <node done="no" type="todo"><data>@errands</data>
- <node done="no" type="todo"><data>Purchase geo lab book</data></node>
- </node>
- <node done="no" type="todo"><data>@dublin</data></node>
-</node>
-<node><data>projects</data></node>
-</tree>
diff --git a/test/rexml/data/test/tests.xml b/test/rexml/data/test/tests.xml
deleted file mode 100644
index cf03b42b0b..0000000000
--- a/test/rexml/data/test/tests.xml
+++ /dev/null
@@ -1,683 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<tests xmlns:var="http://jaxen.org/test-harness/var">
- <!-- test for jaxen-24 -->
- <document url="xml/jaxen24.xml">
- <context select="/body/div">
- <test select="preceding::*[1]" count="1"/>
- <valueOf select="local-name(preceding::*[1])">span</valueOf>
- </context>
- <!-- jaxen-58 -->
- <context select="/">
- <test select="//preceding::x" count="0"/>
- <test select="//following::x" count="0"/>
- <test select="/descendant::*/preceding::x" count="0"/>
- <test select="/descendant::node()/preceding::x" count="0"/>
- </context>
- </document>
-
- <!-- test for jaxen-3 -->
- <document url="xml/simple.xml">
- <context select="/">
- <valueOf select="string()">abd</valueOf>
- </context>
- <context select="/root">
- <valueOf select="string()">abd</valueOf>
- </context>
- <context select="/root/a">
- <valueOf select="string()">a</valueOf>
- </context>
- <context select="/root/c">
- <valueOf select="string()">d</valueOf>
- </context>
- </document>
-
-
- <!-- test for jaxen-3 -->
- <document url="xml/jaxen3.xml">
- <context select="/">
- <test select="/Configuration/hostname/attrlist/hostname[. = 'CE-A'] " count="1"/>
- </context>
- </document>
-
- <!-- parser test cases all of which should fail-->
- <document url="xml/numbers.xml">
- <context select="/">
- <!-- repeated xpaths, jaxen-35 -->
- <test exception="true" select="/numbers numbers" count="0"/>
- <!-- invalid xpath, jaxen-34 -->
- <test exception="true" select="/a/b[c > d]efg" count="0"/>
- <!-- invalid xpath, jaxen-27 -->
- <test exception="true" select="/inv/child::" count="0"/>
- <!-- invalid xpath, jaxen-26 -->
- <!--
-
- <test exception="true" select="/invoice/@test[abcd" count="0"/>
- <test exception="true" select="/invoice/@test[abcd > x" count="0"/>
-
- <test exception="true" select="string-length('a" count="0"/>
- <test exception="true" select="/descendant::()" count="0"/>
- <test exception="true" select="(1 + 1" count="0"/>
-
- -->
- </context>
- </document>
-
-
- <!-- test cases for the use of underscores in names -->
- <document url="xml/underscore.xml">
- <context select="/">
- <test select="/root/@a" count="1"/>
- <test select="/root/@_a" count="1"/>
- <test select="/root/b" count="1"/>
- <test select="/root/_b" count="1"/>
- <valueOf select="/root/@a">1</valueOf>
- <valueOf select="/root/@_a">2</valueOf>
- <valueOf select="/root/b">1</valueOf>
- <valueOf select="/root/_b">2</valueOf>
- </context>
- </document>
-
- <!-- test cases for the use of = with nodesets -->
- <document url="xml/web.xml">
- <context select="/">
- <valueOf select="/web-app/servlet/servlet-name = 'file'">true</valueOf>
- <valueOf select="/web-app/servlet/servlet-name = 'snoop'">true</valueOf>
- </context>
- </document>
-
- <document url="xml/numbers.xml">
- <context select="/">
- <valueOf select="/numbers/set/nr = '-3'">true</valueOf>
- <valueOf select="/numbers/set/nr = -3">true</valueOf>
- <valueOf select="/numbers/set/nr = 24">true</valueOf>
- <valueOf select="/numbers/set/nr/@value = '9999'">true</valueOf>
- <valueOf select="/numbers/set/nr/@value = 9999.0">true</valueOf>
- <valueOf select="/numbers/set/nr/@value = 66">true</valueOf>
- </context>
- </document>
-
- <!-- test basic math... -->
- <document url="xml/numbers.xml">
- <context select="/">
- <valueOf select="(8 * 2 + 1) = 17">true</valueOf>
- <valueOf select="(1 + 8 * 2) = 17">true</valueOf>
- <valueOf select="(7 - 3 + 1) = 5">true</valueOf>
- <valueOf select="(8 - 4 + 5 - 6) = 3">true</valueOf>
- <!-- left-assoc tests, comments show WRONG evaluation -->
- <!-- 3 - 2 - 1 != 2 -->
- <valueOf select="3 - 2 - 1">0</valueOf>
- <!-- 8 div 4 div 2 != 4 -->
- <valueOf select="8 div 4 div 2">1</valueOf>
- <!-- 3 mod 5 mod 7 != 1 -->
- <valueOf select="3 mod 7 mod 5">3</valueOf>
- <!-- 1=(2=2) is true-->
- <valueOf select="1 = 2 = 2">false</valueOf>
- <!-- 2!=(3!=1) => 2!=1 => true, (2!=3)!=1 => 1!=1 => false -->
- <valueOf select="2 != 3 != 1">false</valueOf>
- <!-- 3 > (2 > 1) is true -->
- <valueOf select="3 &gt; 2 &gt; 1">false</valueOf>
- <!-- 3 >= (2 >= 2) is true -->
- <valueOf select="3 &gt;= 2 &gt;= 2">false</valueOf>
- <!-- 1 < (2 < 3) is false -->
- <valueOf select="1 &lt; 2 &lt; 3">true</valueOf>
- <!-- 0 <= (2 <= 3) is true -->
- <valueOf select="2 &lt;= 2 &lt;= 3">true</valueOf>
- </context>
- </document>
-
- <!-- test cases for preceding axis with different node types -->
- <document url="xml/pi2.xml">
- <context select="/a/c">
- <test select="//processing-instruction()" count="1"/>
- <test select="preceding-sibling::*" count="1"/>
- <test select="preceding-sibling::node()" count="5"/>
- <test select="preceding-sibling::*[1]" count="1"/>
- <test select="preceding-sibling::processing-instruction()" count="1"/>
- <valueOf select="preceding-sibling::processing-instruction()">order-by="x"</valueOf>
- <valueOf select="preceding-sibling::*[1]">foo</valueOf>
- <valueOf select="preceding-sibling::node()[2]">order-by="x"</valueOf>
- </context>
- </document>
-
- <document url="xml/id.xml">
- <context select="/"
- var:foobar="foobar"
- var:foo="foo">
- <valueOf select="$foobar">foobar</valueOf>
- <test select="/foo[@id=$foobar]" count="1"/>
- <test select="/foo[@id='$foobar']" count="0"/>
- <test select="/foo[concat($foo, 'bar')=@id]" count="1"/>
- <test select="CD_Library/artist[@name=$artist]" count="0"/>
- </context>
- </document>
-
- <document url="xml/id.xml">
- <context select="/">
- <!-- attributes have a parent: their element -->
- <test select="/foo/@id/parent::foo" count="1"/>
- </context>
- <!-- attributes can also be used as context nodes -->
- <context select="/foo/@id">
- <test select="parent::foo" count="1"/>
- </context>
- </document>
-
- <document url="xml/pi.xml">
- <context select="/">
- <test select="//processing-instruction()" count="3"/>
- <test select="//processing-instruction('cheese')" count="2"/>
- <test select="//processing-instruction('toast')" count="1">
- <valueOf select="string()">is tasty</valueOf>
- </test>
- </context>
-
- </document>
-
- <!-- test evaluate() extension function -->
- <document url="xml/evaluate.xml">
- <context select="/">
- <test select="evaluate('//jumps/*')" count="3"/>
- <test select="evaluate('//jumps/object/dog')" count="1"/>
- <test select="evaluate('//jumps/object')/evaluate" count="0"/>
- <test select="evaluate('//jumps/object')/dog" count="1"/>
- <test select="evaluate('//jumps/*')/dog" count="1"/>
- <test select="//metatest[ evaluate(@select) = . ]" count="1"/>
- </context>
- </document>
-
- <document url="xml/numbers.xml">
- <context select="/numbers/set[1]">
- <test select="*[-3 = .]" count="1"/>
- <valueOf select="54 &lt; *">true</valueOf>
- <valueOf select="55 &lt;= *">true</valueOf>
- <valueOf select="69 &lt; *">false</valueOf>
- <valueOf select="-2 &gt; *">true</valueOf>
- <valueOf select="-3 &gt;= *">true</valueOf>
- <valueOf select="-4 &gt;= *">false</valueOf>
- </context>
- <!-- TODO
- This context should work, but needs a fixed version of saxpath to parse the right-hand side
- of the greater-than expression.
- <context select="/numbers/set[2]">
- <valueOf select="1 &gt; nr/@value">false</valueOf>
- <valueOf select="55 &gt; nr/@value">false</valueOf>
- <valueOf select="55 &gt;= nr/@value">true</valueOf>
- <valueOf select="1000000 &gt; nr/@value">true</valueOf>
- </context>
- -->
- </document>
-
-
- <!-- test sibling axes -->
- <document url="xml/axis.xml">
-
- <context select="/root">
- <test select="preceding-sibling::*" count="0"/>
- </context>
-
- <context select="/root/a/a.3">
- <test select="preceding::*" count="2"/>
- </context>
-
- <context select="/root/a/a.3">
- <test select="preceding-sibling::*" count="2"/>
- </context>
-
- <context select="/">
- <valueOf select="name(/root/a/a.3/preceding-sibling::*[1])">a.2</valueOf>
- <valueOf select="name(/root/a/a.3/preceding-sibling::*[2])">a.1</valueOf>
- </context>
-
- <context select="/">
- <valueOf select="name(/root/a/a.3/following-sibling::*[1])">a.4</valueOf>
- <valueOf select="name(/root/a/a.3/following-sibling::*[2])">a.5</valueOf>
- </context>
-
- </document>
-
-
- <document url="xml/web.xml">
-
- <context select="/">
- <valueOf select="/web-app/servlet[1]/servlet-name">snoop</valueOf>
- <valueOf select="/web-app/servlet[1]/servlet-name/text()">snoop</valueOf>
- <valueOf select="/web-app/servlet[2]/servlet-name">file</valueOf>
- <valueOf select="/web-app/servlet[2]/servlet-name/text()">file</valueOf>
- </context>
-
- <context select="/web-app/servlet[1]">
- <valueOf select="servlet-name">snoop</valueOf>
- <valueOf select="servlet-name/text()">snoop</valueOf>
- </context>
-
- <context select="/web-app/servlet[2]/servlet-name">
- <test select="preceding::*" count="3"/>
- </context>
-
- <context select="/web-app/servlet[2]/servlet-name">
- <test select="following::*" count="13"/>
- </context>
-
- </document>
-
-
- <!-- test name -->
-
- <document url="xml/web.xml">
- <context select="/">
-
- <test select="*" count="1">
- <valueOf select="name()">web-app</valueOf>
- </test>
-
- <!-- NOTE that the child::node() tests only work if the
- XML document does not comments or PIs
- -->
-
- <test select="./*" count="1">
- <valueOf select="name()">web-app</valueOf>
- </test>
- <test select="child::*" count="1">
- <valueOf select="name()">web-app</valueOf>
- </test>
- <test select="/*" count="1">
- <valueOf select="name()">web-app</valueOf>
- </test>
- <test select="/child::node()" count="1">
- <valueOf select="name(.)">web-app</valueOf>
- </test>
- <test select="child::node()" count="1">
- <valueOf select="name(.)">web-app</valueOf>
- </test>
-
- <!-- empty names -->
-
- <valueOf select="name()"></valueOf>
- <valueOf select="name(.)"></valueOf>
- <valueOf select="name(parent::*)"></valueOf>
- <valueOf select="name(/)"></valueOf>
- <valueOf select="name(/.)"></valueOf>
- <valueOf select="name(/self::node())"></valueOf>
-
- <!-- name of root elemet -->
- <valueOf select="name(node())">web-app</valueOf>
- <valueOf select="name(/node())">web-app</valueOf>
- <valueOf select="name(/*)">web-app</valueOf>
- <valueOf select="name(/child::*)">web-app</valueOf>
- <valueOf select="name(/child::node())">web-app</valueOf>
- <valueOf select="name(/child::node())">web-app</valueOf>
- <valueOf select="name(child::node())">web-app</valueOf>
- <valueOf select="name(./*)">web-app</valueOf>
- <valueOf select="name(*)">web-app</valueOf>
-
- </context>
-
- <context select="/*">
- <!-- empty names -->
- <valueOf select="name(..)"></valueOf>
- <valueOf select="name(parent::node())"></valueOf>
- <valueOf select="name(parent::*)"></valueOf>
-
- <!-- name of root elemet -->
- <valueOf select="name()">web-app</valueOf>
- <valueOf select="name(.)">web-app</valueOf>
- <valueOf select="name(../*)">web-app</valueOf>
- <valueOf select="name(../child::node())">web-app</valueOf>
- </context>
- </document>
-
-
-
- <!-- test predicates -->
-
- <document url="xml/nitf.xml">
- <context select="/nitf/head/docdata">
- <test select="doc-id[@regsrc='AP' and @id-string='D76UIMO80']" count="1"/>
- </context>
- <context select="/nitf/head">
- <test select="meta[@name='ap-cycle']" count="1"/>
- <test select="meta[@content='AP']" count="1"/>
- <test select="meta[@name and @content]" count="8"/>
- <test select="meta[@name='ap-cycle' and @content='AP']" count="1"/>
- <test select="meta[@name != 'ap-cycle']" count="7"/>
- </context>
- <context select="/">
- <test select="/nitf/head/meta[@name='ap-cycle']" count="1"/>
- <test select="/nitf/head/meta[@content='AP']" count="1"/>
- <test select="/nitf/head/meta[@name and @content]" count="8"/>
- <test select="/nitf/head/meta[@name='ap-cycle' and @content='AP']" count="1"/>
- <test select="/nitf/head/meta[@name != 'ap-cycle']" count="7"/>
- </context>
- </document>
-
-
- <document url="xml/moreover.xml">
- <context select="/">
- <test select="/child::node()" count="1"/>
- <test select="/*" count="1"/>
-
- <test select="/*/article" count="20"/>
- <test select="//*" count="221"/>
- <test select="//*[local-name()='article']" count="20"/>
- <test select="//article" count="20"/>
- <test select="/*/*[@code]" count="20"/>
-
- <test select="/moreovernews/article[@code='13563275']" count="1"/>
-
- <test select="/moreovernews/article[@code='13563275']">
- <valueOf select="url">http://c.moreover.com/click/here.pl?x13563273</valueOf>
- </test>
- <test select="/*/article[@code='13563275']">
- <valueOf select="url">http://c.moreover.com/click/here.pl?x13563273</valueOf>
- </test>
- <test select="//article[@code='13563275']">
- <valueOf select="url">http://c.moreover.com/click/here.pl?x13563273</valueOf>
- </test>
- <test select="//*[@code='13563275']">
- <valueOf select="url">http://c.moreover.com/click/here.pl?x13563273</valueOf>
- </test>
- <test select="/child::node()/child::node()[@code='13563275']">
- <valueOf select="url">http://c.moreover.com/click/here.pl?x13563273</valueOf>
- </test>
- <test select="/*/*[@code='13563275']">
- <valueOf select="url">http://c.moreover.com/click/here.pl?x13563273</valueOf>
- </test>
- </context>
- </document>
-
-
-
- <!-- test other node types-->
-
- <document url="xml/contents.xml">
- <context select="/">
- <test select="processing-instruction()" count="3"/>
- <test select="/processing-instruction()" count="3"/>
- <test select="/comment()" count="1"/>
- <test select="comment()" count="1"/>
- <test select="/child::node()/comment()" count="2"/>
- <test select="/*/comment()" count="2"/>
- <test select="//comment()" count="3"/>
- </context>
- </document>
-
-
-
- <!-- test positioning -->
-
- <document url="xml/fibo.xml">
- <context select="/">
- <test select="/*/fibonacci[position() &lt; 10]" count="9"/>
- <valueOf select="sum(//fibonacci)">196417</valueOf>
- <valueOf select="sum(//fibonacci/@index)">325</valueOf>
- <valueOf select="/*/fibonacci[2]">1</valueOf>
- <valueOf select="/*/fibonacci[ count(/*/fibonacci) ]">75025</valueOf>
- <valueOf select="/*/fibonacci[ count(/*/fibonacci) - 1 ]">46368</valueOf>
- </context>
- </document>
-
-
- <!-- test number functions -->
-
- <!-- test Axes -->
-
- <document url="xml/web.xml">
- <context select="/">
- <test select="descendant-or-self::*" count="19"/>
- <test select="descendant::*" count="19"/>
- <test select="/descendant::*" count="19"/>
- <test select="/descendant-or-self::*" count="19"/>
- <test select="/descendant::servlet" count="2"/>
- <test select="/descendant-or-self::servlet" count="2"/>
- <test select="descendant-or-self::servlet" count="2"/>
- <test select="descendant::servlet" count="2"/>
- <test select="/*/servlet" count="2"/>
- <valueOf select="count(/*/servlet)">2</valueOf>
- <test select="//servlet" count="2"/>
- <valueOf select="count(//servlet)">2</valueOf>
- </context>
- <context select="/web-app">
- <test select="/descendant::servlet" count="2"/>
- <test select="/descendant-or-self::servlet" count="2"/>
- <test select="descendant-or-self::servlet" count="2"/>
- <test select="descendant::servlet" count="2"/>
- </context>
- </document>
-
- <document url="xml/much_ado.xml">
- <context select="/">
- <test select="/descendant::ACT" count="5"/>
- <test select="descendant::ACT" count="5"/>
- <valueOf select="/PLAY/TITLE">Much Ado about Nothing</valueOf>
- <valueOf select="2+2">4</valueOf>
- <valueOf select="5 * 4 + 1">21</valueOf>
- <valueOf select="count(descendant::ACT)">5</valueOf>
- <valueOf select="10 + count(descendant::ACT) * 5">35</valueOf>
- <valueOf select="(10 + count(descendant::ACT)) * 5">75</valueOf>
- </context>
- <context select="/PLAY/ACT[2]/SCENE[1]">
- <test select="/descendant::ACT" count="5"/>
- <test select="../../descendant::ACT" count="5"/>
- <test select="/PLAY/ACT[2]/SCENE[1]/descendant::SPEAKER" count="141"/>
- <test select="descendant::SPEAKER" count="141"/>
- <valueOf select="count(descendant::*)+1">646</valueOf>
- <valueOf select="count(descendant::SPEAKER)+1">142</valueOf>
- <valueOf select="count(ancestor::*)">2</valueOf>
- <valueOf select="count(ancestor::PLAY)">1</valueOf>
- <valueOf select="count(ancestor-or-self::*)">3</valueOf>
- <valueOf select="count(ancestor-or-self::PLAY)">1</valueOf>
- <valueOf select="5+count(ancestor::*)-1">6</valueOf>
- </context>
- <context select="/">
- <!-- Test correct predicate application -->
- <valueOf select="count(/PLAY/ACT/SCENE[1])">5</valueOf>
- </context>
- </document>
-
- <!-- test axis node ordering -->
- <document url="xml/web.xml">
- <context select="/">
- <!-- Reported as Jira issue JAXEN-24 -->
- <test select="//servlet-mapping/preceding::*[1][name()='description']" count="1"/>
- <test select="/web-app/servlet//description/following::*[1][name()='servlet-mapping']" count="1"/>
- <test select="/web-app/servlet//description/following::*[2][name()='servlet-name']" count="1"/>
- </context>
- </document>
-
- <!-- test document function -->
- <document url="xml/text.xml">
- <context select="/">
- <test select="document('xml/web.xml')" count="1">
- <valueOf select="/web-app/servlet[1]/servlet-name">snoop</valueOf>
- <valueOf select="/web-app/servlet[1]/servlet-name/text()">snoop</valueOf>
- </test>
- <valueOf select="document('xml/web.xml')/web-app/servlet[1]/servlet-name">snoop</valueOf>
- </context>
- <!-- Test to check if the context changes when an extension function is used.
- First test is an example, second is the actual test.
- -->
- <context select="/foo/bar/cheese[1]">
- <valueOf select="concat(./@id,'foo',@id)">3foo3</valueOf>
- <valueOf select="concat(./@id,document('xml/web.xml')/web-app/servlet[1]/servlet-name,./@id)">3snoop3</valueOf>
- </context>
- </document>
-
- <document url="xml/message.xml">
- <context select="/">
- <valueOf select="/message/body/data/items/item[name/text()='parentinfo']/value">Pruefgebiete</valueOf>
- <valueOf select="document('xml/message.xml')/message/body/data/items/item[name/text()='parentinfo']/value">Pruefgebiete</valueOf>
- </context>
- </document>
-
- <document url="xml/simple.xml">
-
- <!-- test behaviour of AbsoluteLocationPath -->
- <context select="/root/a">
- <valueOf select="concat( ., /root/b )">ab</valueOf>
- <valueOf select="concat( ../b, . )">ba</valueOf>
- <valueOf select="concat( /root/b, . )">ba</valueOf>
- <valueOf select="concat( /root/c/d, ../b )">db</valueOf>
- </context>
-
- <!-- test the translate() function -->
- <context select="/">
- <valueOf select="translate( '', '', '' )"></valueOf>
- <valueOf select="translate( 'abcd', '', '' )">abcd</valueOf>
- <valueOf select="translate( 'abcd', 'abcd', 'abcd' )">abcd</valueOf>
- <valueOf select="translate( 'abcd', 'dcba', 'dcba' )">abcd</valueOf>
- <valueOf select="translate( 'abcd', 'abcd', 'dcba' )">dcba</valueOf>
- <valueOf select="translate( 'abcd', 'abcd', 'ab' )">ab</valueOf>
- <valueOf select="translate( 'abcd', 'cdab', 'cd' )">cd</valueOf>
- <valueOf select="translate( 'abcd', 'acbd', 'xy' )">xy</valueOf>
- <valueOf select="translate( 'abcd', 'abcdb', 'abcdb' )">abcd</valueOf>
- <valueOf select="translate( 'abcd', 'abcd', 'abcdb' )">abcd</valueOf>
- </context>
-
- <context select="/">
- <valueOf select="substring('12345', 1.5, 2.6)">234</valueOf>
- <valueOf select="substring('12345', 0, 3)">12</valueOf>
- <valueOf select="substring('12345', 0 div 0, 3)"></valueOf>
- <valueOf select="substring('12345', 1, 0 div 0)"></valueOf>
- <valueOf select="substring('12345', -42, 1 div 0)">12345</valueOf>
- <valueOf select="substring('12345', -1 div 0, 1 div 0)"></valueOf>
- <valueOf select="substring('12345', 3)">345</valueOf>
- <valueOf select="substring('12345',1,15)">12345</valueOf>
- </context>
-
- <!-- Some tests for the normalize-space() function -->
-
- <context select="/">
- <valueOf select="normalize-space(' abc ')">abc</valueOf>
- <valueOf select="normalize-space(' a b c ')">a b c</valueOf>
- <valueOf select="normalize-space(' a &#x0d; b &#x0a; c ')">a b c</valueOf>
- <!-- Next test case addresses issue JAXEN-22 -->
- <valueOf select="normalize-space(' ')"></valueOf>
- <!-- Next test case addresses issue JAXEN-29 -->
- <valueOf select="normalize-space('')"></valueOf>
- </context>
- </document>
-
-
-
- <!-- test cases for String extension functions -->
- <document url="xml/web.xml">
- <context select="/web-app/servlet[1]">
- <valueOf select="upper-case( servlet-class )">SNOOPSERVLET</valueOf>
- <valueOf select="lower-case( servlet-class )">snoopservlet</valueOf>
- <valueOf select="upper-case( servlet-class, 'fr' )">SNOOPSERVLET</valueOf>
- <valueOf select="upper-case( servlet-class, 'fr-CA' )">SNOOPSERVLET</valueOf>
- <valueOf select="upper-case( servlet-class, 'es-ES-Traditional_WIN' )">SNOOPSERVLET</valueOf>
- <valueOf select="ends-with( servlet-class, 'Servlet' )">true</valueOf>
- <valueOf select="ends-with( servlet-class, 'S' )">false</valueOf>
- </context>
- </document>
-
- <!-- test cases for the lang() function -->
- <document url="xml/lang.xml">
- <context select="/">
- <test select="/e1/e2[lang('hr')]" count="0"/>
- <test select="/e1/e2/e3[lang('en')]" count="1"/>
- <test select="/e1/e2/e3[lang('en-US')]" count="1"/>
- <test select="/e1/e2/e3[lang('en-GB')]" count="0"/>
- <test select="/e1/e2/e3[lang('hu')]" count="2"/>
- <test select="/e1/e2/e3[lang('hu-HU')]" count="0"/>
- <test select="/e1/e2/e3[lang('es')]" count="1"/>
- <test select="/e1/e2/e3[lang('es-BR')]" count="0"/>
- </context>
- </document>
-
- <!-- test namespace -->
- <document url="xml/namespaces.xml">
- <context select="/"
- xmlns:foo="http://fooNamespace/"
- xmlns:voo="http://fooNamespace/"
- xmlns:bar="http://barNamespace/"
- xmlns:alias="http://fooNamespace/">
- <test select="/*" count="1"/>
- <test select="/foo:a" count="1"/>
- <test select="/foo:a/b" count="1"/>
- <test select="/voo:a/b/c" count="1"/>
- <test select="/voo:a/bar:f" count="1"/>
- <test select="/*[namespace-uri()='http://fooNamespace/' and local-name()='a']" count="1"/>
- <test select="/*[local-name()='a' and namespace-uri()='http://fooNamespace/']/*[local-name()='x' and namespace-uri()='http://fooNamespace/']" count="1"/>
- <test select="/*[local-name()='a' and namespace-uri()='http://fooNamespace/']/*[local-name()='x' and namespace-uri()='http://fooNamespace/']/*[local-name()='y' and namespace-uri()='http://fooNamespace/']" count="1"/>
- </context>
- <!-- the prefix here and in the document have no relation; it's their
- namespace-uri binding that counts -->
- <context select="/" xmlns:foo="http://somethingElse/">
- <test select="/foo:a/b/c" count="0"/>
- </context>
-
- <context select="/"
- xmlns:foo="http://fooNamespace/"
- xmlns:bar="http://barNamespace/"
- xmlns:alias="http://fooNamespace/">
- <valueOf select="/foo:a/b/c">Hello</valueOf>
- <valueOf select="/foo:a/foo:d/foo:e">Hey</valueOf>
- <valueOf select="/foo:a/alias:x/alias:y">Hey3</valueOf>
- <valueOf select="/foo:a/foo:x/foo:y">Hey3</valueOf>
- <valueOf select="/*[local-name()='a' and namespace-uri()='http://fooNamespace/']/*[local-name()='x' and namespace-uri()='http://fooNamespace/']/*[local-name()='y' and namespace-uri()='http://fooNamespace/']">Hey3</valueOf>
- </context>
-
- </document>
-
- <document url="xml/defaultNamespace.xml">
- <context select="/">
- <!-- NOTE: /a/b/c selects elements in no namespace only! -->
- <test select="/a/b/c" count="0"/>
- <!--
- The following test uses an unbound prefix 'x' and should throw an exception.
- Addresses issue JAXEN-18.
- Turns out this isn't really tested as the test didn't fail when the exception wasn't thrown.
- <test select="/x:a/x:b/x:c" count="0" exception="true"/>
- -->
- </context>
- <context select="/"
- xmlns:dummy="http://dummyNamespace/">
- <test select="/dummy:a/dummy:b/dummy:c" count="1"/>
- </context>
- </document>
- <document url="xml/text.xml">
- <context select="/">
- <test select="/foo/bar/text()" count="3"/>
- <valueOf select="normalize-space(/foo/bar/text())">baz</valueOf>
- </context>
- </document>
-
- <document url="xml/testNamespaces.xml">
- <context select="/">
- <!-- the root is not an element, so no namespaces -->
- <test select="namespace::*" count="0" debug="off"/>
- <test select="/namespace::*" count="0" debug="off"/>
- <test select="/Template/Application1/namespace::*" count="3" debug="off"/>
- <test select="/Template/Application2/namespace::*" count="3" debug="off"/>
-
- <test select="//namespace::*" count="25" debug="off"/>
- </context>
-
- <!--
- <context select="/Template/Application1">
- <test select="namespace::*" count="3" debug="off"/>
- <test select="/namespace::*" count="0" debug="off"/>
- <test select="/Template/Application1/namespace::*" count="3" debug="off"/>
- <test select="/Template/Application2/namespace::*" count="3" debug="off"/>
- <test select="//namespace::*" count="25" debug="off"/>
- <test select="//namespace::xplt" count="8" debug="off"/>
- <test xmlns:somethingelse="http://www.xxxx.com/"
- select="//namespace::somethingelse" count="0" debug="off"/>
- </context>
- -->
- </document>
-
- <document url="xml/testNamespaces.xml">
- <context select="/">
- <!-- namespace nodes have their element as their parent -->
- <test select="/Template/namespace::xml/parent::Template" count="1"/>
- </context>
- <!-- namespace nodes can also be used as context nodes -->
- <context select="/Template/namespace::xml">
- <test select="parent::Template" count="1"/>
- </context>
- </document>
-
-</tests>
diff --git a/test/rexml/data/test/tests.xsl b/test/rexml/data/test/tests.xsl
deleted file mode 100644
index 3ecd648b3b..0000000000
--- a/test/rexml/data/test/tests.xsl
+++ /dev/null
@@ -1,369 +0,0 @@
-<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:var="http://jaxen.org/test-harness/var">
-<!-- this is what I used to generate XPathTestBase. After generating I fixed the illegal strings (its quicker
-than fixing the xsl for that few errors) and reformatted the code. Its unlikely this code will be needed
-again, its just in cvs for completeness -->
- <output method="text"/>
- <template match="/">
- <text>
- /*
- * $Header: /home/projects/jaxen/scm/jaxen/src/java/test/org/jaxen/XPathTestBase.java,v 1.32 2005/06/15 23:52:40 bewins Exp $
- * $Revision: 1.32 $
- * $Date: 2005/06/15 23:52:40 $
- *
- * ====================================================================
- *
- * Copyright (C) 2000-2002 bob mcwhirter &amp; James Strachan.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions, and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions, and the disclaimer that follows
- * these conditions in the documentation and/or other materials
- * provided with the distribution.
- *
- * 3. The name "Jaxen" must not be used to endorse or promote products
- * derived from this software without prior written permission. For
- * written permission, please contact license@jaxen.org.
- *
- * 4. Products derived from this software may not be called "Jaxen", nor
- * may "Jaxen" appear in their name, without prior written permission
- * from the Jaxen Project Management (pm@jaxen.org).
- *
- * In addition, we request (but do not require) that you include in the
- * end-user documentation provided with the redistribution and/or in the
- * software itself an acknowledgement equivalent to the following:
- * "This product includes software developed by the
- * Jaxen Project (http://www.jaxen.org/)."
- * Alternatively, the acknowledgment may be graphical using the logos
- * available at http://www.jaxen.org/
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 Jaxen AUTHORS OR THE PROJECT
- * 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.
- *
- * ====================================================================
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Jaxen Project and was originally
- * created by bob mcwhirter &lt;bob@werken.com> and
- * James Strachan &lt;jstrachan@apache.org>. For more information on the
- * Jaxen Project, please see &lt;http://www.jaxen.org/>.
- *
- * $Id: XPathTestBase.java,v 1.32 2005/06/15 23:52:40 bewins Exp $
- */
-
-
-package org.jaxen;
-
-import junit.framework.TestCase;
-import org.jaxen.function.StringFunction;
-import org.jaxen.saxpath.helpers.XPathReaderFactory;
-
-import javax.xml.parsers.ParserConfigurationException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-public abstract class XPathTestBase extends TestCase
-{
- protected static String VAR_URI = "http://jaxen.org/test-harness/var";
- protected static String TESTS_XML = "xml/test/tests.xml";
-
- protected static boolean verbose = true;
- protected static boolean debug = true;
- private ContextSupport contextSupport;
-
- public XPathTestBase(String name)
- {
- super( name );
- }
-
- public void setUp() throws ParserConfigurationException
- {
- this.contextSupport = null;
- System.setProperty( XPathReaderFactory.DRIVER_PROPERTY,
- "" );
- log( "-----------------------------" );
- }
-
- public void log(String text)
- {
- log( verbose,
- text );
- }
-
- public void log(boolean actualVerbose,
- String text)
- {
- if ( ! actualVerbose )
- {
- return;
- }
-
- System.out.println( text );
- }
-
- protected void assertCountXPath(int expectedSize, Object context, String xpathStr) throws JaxenException {
- try
- {
- assertCountXPath2(expectedSize, context, xpathStr);
- }
- catch (UnsupportedAxisException e)
- {
- log ( debug,
- " ## SKIPPED -- Unsupported Axis" );
- }
- }
-
- protected Object assertCountXPath2(int expectedSize, Object context, String xpathStr) throws JaxenException {
- log ( debug,
- " Select :: " + xpathStr );
- BaseXPath xpath = new BaseXPath( xpathStr );
- List results = xpath.selectNodes( getContext( context ) );
- log ( debug,
- " Expected Size :: " + expectedSize );
- log ( debug,
- " Result Size :: " + results.size() );
-
- if ( expectedSize != results.size() )
- {
- log ( debug,
- " ## FAILED" );
- log ( debug,
- " ## xpath: " + xpath + " = " + xpath.debug() );
-
- Iterator resultIter = results.iterator();
-
- while ( resultIter.hasNext() )
- {
- log ( debug,
- " --> " + resultIter.next() );
- }
- }
- assertEquals( xpathStr,
- expectedSize,
- results.size() );
- if (expectedSize > 0) {
- return results.get(0);
- }
- return null;
- }
-
- protected void assertInvalidXPath(Object context, String xpathStr) throws JaxenException {
- try
- {
- log ( debug,
- " Select :: " + xpathStr );
- BaseXPath xpath = new BaseXPath( xpathStr );
- List results = xpath.selectNodes( getContext( context ) );
- log ( debug,
- " Result Size :: " + results.size() );
- fail("An exception was expected.");
- }
- catch (UnsupportedAxisException e)
- {
- log ( debug,
- " ## SKIPPED -- Unsupported Axis" );
- }
- catch (JaxenException e) {
- log (debug, " Caught expected exception "+e.getMessage());
- }
- }
-
- protected void assertValueOfXPath(String expected, Object context, String xpathStr) throws JaxenException {
- try
- {
- BaseXPath xpath = new BaseXPath( xpathStr );
- Object node = xpath.evaluate( getContext( context ) );
-
- String result = StringFunction.evaluate( node,
- getNavigator() );
-
- log ( debug,
- " Select :: " + xpathStr );
- log ( debug,
- " Expected :: " + expected );
- log ( debug,
- " Result :: " + result );
-
- if ( ! expected.equals( result ) )
- {
- log ( debug,
- " ## FAILED" );
- log ( debug,
- " ## xpath: " + xpath + " = " + xpath.debug() );
- }
-
- assertEquals( xpathStr,
- expected,
- result );
- }
- catch (UnsupportedAxisException e)
- {
- log ( debug,
- " ## SKIPPED -- Unsupported Axis " );
-
- }
- }
- protected Context getContext(Object contextNode)
- {
- Context context = new Context( getContextSupport() );
-
- List list = new ArrayList( 1 );
- list.add( contextNode );
- context.setNodeSet( list );
-
- return context;
- }
-
- public ContextSupport getContextSupport()
- {
- if ( this.contextSupport == null )
- {
- this.contextSupport = new ContextSupport( new SimpleNamespaceContext(),
- XPathFunctionContext.getInstance(),
- new SimpleVariableContext(),
- getNavigator() );
- }
-
- return this.contextSupport;
- }
-
- public abstract Navigator getNavigator();
-
- public abstract Object getDocument(String url) throws Exception;
-
- public void testGetNodeType() throws FunctionCallException, UnsupportedAxisException
- {
- Navigator nav = getNavigator();
- Object document = nav.getDocument("xml/testNamespaces.xml");
- int count = 0;
- Iterator descendantOrSelfAxisIterator = nav.getDescendantOrSelfAxisIterator(document);
- while (descendantOrSelfAxisIterator.hasNext()) {
- Object node = descendantOrSelfAxisIterator.next();
- Iterator namespaceAxisIterator = nav.getNamespaceAxisIterator(node);
- while (namespaceAxisIterator.hasNext()) {
- count++;
- assertEquals("Node type mismatch", Pattern.NAMESPACE_NODE, nav.getNodeType(namespaceAxisIterator.next()));
- }
- }
- assertEquals(25, count);
- }
-
- </text>
- <apply-templates select="node()|@*"/>
- <text>
-}
- </text>
- </template>
- <template match="context">
- <text>
- public void test</text><value-of select="generate-id()"/><text>() throws JaxenException {
- Navigator nav = getNavigator();
- String url = "</text><value-of select="../@url"/><text>";
- log( "Document [" + url + "]" );
- Object document = nav.getDocument(url);
-
- XPath contextpath = new BaseXPath("</text><value-of select="@select"/><text>", nav);
- log( "Initial Context :: " + contextpath );
- List list = contextpath.selectNodes(document);
- </text>
- <if test="count(namespace::*) > count(../namespace::*)">
- <text>
- SimpleNamespaceContext nsContext = new SimpleNamespaceContext();</text>
- <for-each select="namespace::*[local-name() != 'var' and local-name() != 'xml']">
- <text>
- nsContext.addNamespace( "</text><value-of select="local-name()"/><text>", "</text><value-of select="."/><text>" );</text>
- </for-each>
- <text>
- getContextSupport().setNamespaceContext( nsContext );</text>
- </if>
- <if test="@*[namespace-uri() = 'http://jaxen.org/test-harness/var']">
- <text>
- SimpleVariableContext varContext = new SimpleVariableContext();</text>
- <for-each select="@*[namespace-uri() = 'http://jaxen.org/test-harness/var']">
- <text>
- varContext.setVariableValue(null, "</text><value-of select="local-name()"/><text>", "</text><value-of select="."/><text>" );</text>
- </for-each>
- <text>
- getContextSupport().setVariableContext( varContext );</text>
- </if>
- <text>
- Iterator iter = list.iterator();
- while (iter.hasNext()) {
- Object context = iter.next();</text>
- <apply-templates select="node()|@*"/>
- <text>
- }
- }</text>
- </template>
- <template match="test[@exception]">
- <text>
- assertInvalidXPath(context, "</text><value-of select='@select'/><text>");</text>
- </template>
- <template match="test[valueOf]">
- <choose>
- <when test="@count">
- <text>
- try
- {
- Object result = assertCountXPath2(</text><value-of select="@count"/><text>, context, "</text><value-of select="@select"/><text>");</text>
- <for-each select="valueOf">
- <text>
- assertValueOfXPath("</text><value-of select="."/><text>", result, "</text><value-of select="@select"/><text>");</text>
- </for-each>
- <text>
- }
- catch (UnsupportedAxisException e)
- {
- log ( debug, " ## SKIPPED -- Unsupported Axis" );
- }</text>
- </when>
- <otherwise>
- <text>
- try
- {
- BaseXPath xpath = new BaseXPath( "</text><value-of select="@select"/><text>" );
- List results = xpath.selectNodes( getContext( context ) );
- Object result = results.get(0);</text>
- <for-each select="valueOf">
- <text>
- assertValueOfXPath("</text><value-of select="."/><text>", result, "</text><value-of select="@select"/><text>");</text>
- </for-each>
- <text>
- }
- catch (UnsupportedAxisException e)
- {
- log ( debug, " ## SKIPPED -- Unsupported Axis" );
- }</text>
- </otherwise>
- </choose>
- </template>
- <template match="test">
- <text>
- assertCountXPath(</text><value-of select="@count"/><text>, context, "</text><value-of select="@select"/><text>");</text>
- </template>
- <template match="valueOf">
- <text>
- assertValueOfXPath("</text><value-of select="."/>", context, "<value-of select="@select"/><text>");</text>
- </template>
- <template match="comment()"><text>
- /*</text><value-of select="."/><text>
- */</text>
- </template>
- <template match="node()|@*"><apply-templates select="node()|@*"/></template>
-</stylesheet> \ No newline at end of file
diff --git a/test/rexml/data/testNamespaces.xml b/test/rexml/data/testNamespaces.xml
deleted file mode 100644
index 50f7c9306b..0000000000
--- a/test/rexml/data/testNamespaces.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<Template>
- <Application1 xmlns:xplt="http://www.xxxx.com/"
- xmlns:xpl="http://www.xxxx.com/"
- version="3.0"
- randomAttribute="foo"
- >
- <xpl:insertText/>
- <xplt:anyElement>
- <Name/>
- </xplt:anyElement>
- </Application1>
-
- <Application2 xmlns:xplt="http://www.xxxx.com/"
- xmlns:xpl="http://www.xxxx.com/"
- version="3.0"
- >
- <xpl:insertText/>
- <xplt:anyElement>
- <Name/>
- </xplt:anyElement>
- </Application2>
-</Template>
diff --git a/test/rexml/data/testsrc.xml b/test/rexml/data/testsrc.xml
deleted file mode 100644
index 9c7a78212f..0000000000
--- a/test/rexml/data/testsrc.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN"
- "http://my.netscape.com/publish/formats/rss-0.91.dtd">
-<rss version="0.91">
- <channel>
- <title>xmlhack</title>
- <link>http://www.xmlhack.com</link>
- <description>Developer news from the XML community</description>
- <language>en-us</language>
- <copyright>Copyright 1999-2001, xmlhack team.</copyright>
- <managingEditor>editor@xmlhack.com</managingEditor>
- <webMaster>webmaster@xmlhack.com</webMaster>
- <image>
- <title>xmlhack</title>
- <url>http://www.xmlhack.com/images/mynetscape88.gif</url>
- <link>http://www.xmlhack.com</link>
- <width>88</width>
- <height>31</height>
- <description>News, opinions, tips and issues concerning XML development</description>
- </image>
-<item x='0'>
-<title>Experimental non-XML syntax for RELAX NG</title>
-<link>http://www.xmlhack.com/read.php?item=1343</link>
-<description>
- James Clark has announced the release of an experimental non-XML syntax for RELAX
- NG and a Java translator implementation that converts
- instances of the syntax into RELAX NG's XML syntax.
-</description>
-<category>Schemas</category>
-</item>
-<item x='1'>
-<title>Long-awaited entity-resolver Java classes finally released</title>
-<link>http://www.xmlhack.com/read.php?item=1342</link>
-<description>Norman Walsh has
- announced the release of SAX entityResolver() and JAXP
- URIResolver() Java
- classes he wrote to implement the OASIS XML Catalogs
- Committee Specification (in addition to the TR9401 and
- Apache XCatalogs specifications).
-</description>
-<category>SGML/XML</category>
-<category>Java</category>
-</item>
-<item x='3'>
-
-<title>Beepcore-C framework released</title>
-<link>http://www.xmlhack.com/read.php?item=1341</link>
-<description>Invisible Worlds have announced the publication of Beepcore-C, an implementation of the BEEP framework written in C.</description>
-<category>Protocols</category>
-<category>C++</category>
-</item>
-<item>
-<title>SVG and XSL-FO by example</title>
-<link>http://www.xmlhack.com/read.php?item=1340</link>
-<description>Jirka Jirat has announced the
-addition of an XSL-FO and SVG examples repository to the Zvon developer
-reference site.</description>
-<category>SVG</category>
-<category>XSL-FO</category>
-</item>
-
-
-</channel>
-</rss>
diff --git a/test/rexml/data/text.xml b/test/rexml/data/text.xml
deleted file mode 100644
index e1865c7977..0000000000
--- a/test/rexml/data/text.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0"?>
-<foo>
- <bar>
- baz
- <cheese id="3"/>
- baz
- <cheese/>
- baz
- </bar>
-</foo>
diff --git a/test/rexml/data/ticket_61.xml b/test/rexml/data/ticket_61.xml
deleted file mode 100644
index 4df1cc9b86..0000000000
--- a/test/rexml/data/ticket_61.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<HTML>
-<body onload="RunOnLoads()" ms_positioning="FlowLayout"><form id="CollectiveForm" name="CollectiveForm" action="Matter_List.aspx" method="post" defaultbutton="btSearch"><input type="hidden" name="LinkID"/> <input type="hidden" name="Param"/><input type="hidden" name="__EVENTTARGET"/> <input type="hidden" name="__EVENTARGUMENT"/><input type="hidden" value="dDwtMjA3ODMxNDk3NDt0PDtsPGk8MD47aTwxPjs+O2w8dDxAPC9BSU1TL3N0eWxlc2hlZXRzL0RhdGFDZXJ0U3R5bGUuYXNweDs+Ozs+O3Q8cDxsPGRlZmF1bHRCdXR0b247PjtsPGJ0U2VhcmNoOz4+O2w8aTwxPjtpPDM+O2k8ND47aTw4PjtpPDExPjtpPDEzPjtpPDE1Pjs+O2w8dDxAPC9BSU1TL2ltYWdlcy9oZWFkZXItYWltc2xvZ28uZ2lmOy9BSU1TL2ltYWdlcy9oZWFkZXItYmtnZC5naWY7Pjs7Pjt0PEA8L0FJTVMvaW1hZ2VzL2hlYWRlci1yaWdodGVuZC5naWY7Oz47Oz47dDw7bDxpPDI+Oz47bDx0PDtsPGk8MT47aTwyPjs+O2w8dDxwPDtwPGw8b25wcm9wZXJ0eWNoYW5nZTs+O2w8Q29sbGVjdGl2ZVZhbGlkYXRpb25TdW1tYXJ5X09uUHJvcGVydHlDaGFuZ2UoKTs+Pj47Oz47dDxAPC9BSU1TL2ltYWdlcy9hbGVydExlZnRUb3AuZ2lmOy9BSU1TL2ltYWdlcy9hbGVydEhvcml6b250YWwuZ2lmOy9BSU1TL2ltYWdlcy9hbGVydC5naWY7L0FJTVMvaW1hZ2VzL2FsZXJ0SG9yaXpvbnRhbC5naWY7L0FJTVMvaW1hZ2VzL2FsZXJ0UmlnaHRUb3AuZ2lmOy9BSU1TL2ltYWdlcy9hbGVydExlZnRWZXJ0aWNhbC5naWY7L0FJTVMvaW1hZ2VzL2FsZXJ0UmlnaHRWZXJ0aWNhbC5naWY7L0FJTVMvaW1hZ2VzL2FsZXJ0TGVmdEJvdHRvbS5naWY7L0FJTVMvaW1hZ2VzL2FsZXJ0SG9yaXpvbnRhbC5naWY7L0FJTVMvaW1hZ2VzL2FsZXJ0UmlnaHRCb3R0b20uZ2lmOz47Oz47Pj47Pj47dDw7bDxpPDE+O2k8Mz47aTw3Pjs+O2w8dDxwPHA8bDxUZXh0O2luRXJyb3JTdGF0ZTs+O2w8WTtvPGY+Oz4+O3A8bDxvbmNoYW5nZTtjdXJyZW50dmFsdWU7PjtsPEluZGljYXRlQ2hhbmdlZCh0aGlzLCcnKVw7O1k7Pj4+Ozs+O3Q8cDxwPGw8VGV4dDtpbkVycm9yU3RhdGU7PjtsPE9wZW47bzxmPjs+PjtwPGw8b25jaGFuZ2U7Y3VycmVudHZhbHVlOz47bDxJbmRpY2F0ZUNoYW5nZWQodGhpcywnJylcOztPcGVuOz4+Pjs7Pjt0PHA8cDxsPFRvb2xUaXA7PjtsPFxlOz4+Oz47Oz47Pj47dDw7bDxpPDE+O2k8Mz47aTw1PjtpPDY+O2k8Nz47PjtsPHQ8cDxwPGw8aW5FcnJvclN0YXRlO1RleHQ7PjtsPG88Zj47XGU7Pj47cDxsPG9uY2hhbmdlO2N1cnJlbnR2YWx1ZTs+O2w8SW5kaWNhdGVDaGFuZ2VkKHRoaXMsJycpXDs7XGU7Pj4+Ozs+O3Q8cDxwPGw8aW5FcnJvclN0YXRlO1RleHQ7PjtsPG88Zj47XGU7Pj47cDxsPG9uY2hhbmdlO2N1cnJlbnR2YWx1ZTs+O2w8SW5kaWNhdGVDaGFuZ2VkKHRoaXMsJycpXDs7XGU7Pj4+Ozs+O3Q8cDxwPGw8aW5FcnJvclN0YXRlO1RleHQ7PjtsPG88Zj47XGU7Pj47cDxsPG9uY2hhbmdlO2N1cnJlbnR2YWx1ZTs+O2w8SW5kaWNhdGVDaGFuZ2VkKHRoaXMsJycpXDs7XGU7Pj4+Ozs+O3Q8QDxQcm9mZXNzaW9uYWwgaW4gQ2hhcmdlOz47Oz47dDxwPHA8bDxpbkVycm9yU3RhdGU7VGV4dDs+O2w8bzxmPjtcZTs+PjtwPGw8b25jaGFuZ2U7Y3VycmVudHZhbHVlOz47bDxJbmRpY2F0ZUNoYW5nZWQodGhpcywnJylcOztcZTs+Pj47Oz47Pj47dDxAMDxwPHA8bDxEYXRhS2V5cztQYWdpbmdWaWV3O1RvdGFsUmVjb3JkcztQYWdlQ291bnQ7UGFnZVNpemU7U29ydERpcmVjdGlvbjtVbmlxdWVJZDtTb3J0RXhwcmVzc2lvbjtDdXJyZW50UGFnZTtfIUl0ZW1Db3VudDtfIURhdGFTb3VyY2VJdGVtQ291bnQ7TWF4UGFnZU1vZGU7PjtsPGw8PjtPcGVuO2k8MD47aTwwPjtpPDIwPjtpPDE+O2MxNjA4M2Y4LTkwZjgtNDQ1Ni04YzM0LTc5ZTFhNjg2ZDhlMjttYXR0ZXJfbm87aTwxPjtpPC0xPjtpPC0xPjtEYXRhQ2VydC5XZWIuQ29udHJvbHMuTWF4UGFnZU1vZGUsIERhdGFDZXJ0LldlYiwgVmVyc2lvbj0xLjYuMi4xNCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1udWxsPE5PUk1BTD47Pj47PjtAMDw7OztAMDxwPGw8SGVhZGVyVGV4dDs+O2w8UHJvZmVzc2lvbmFsIGluIENoYXJnZTs+Pjs7Ozs+O0AwPHA8bDxWaXNpYmxlOz47bDxvPHQ+Oz4+Ozs7Oz47Oz47Ozs7Ozs7Ozs+Ozs+O3Q8QDwvQUlNUy9pbWFnZXMvZm9vdGVyLWJrZ2QuZ2lmOy9BSU1TL2ltYWdlcy9mb290ZXItYmtnZC5naWY7MjAwNjs7Pjs7Pjs+Pjs+Pjs+2T4SCaJMpmBYZKv3iwMGME7j8M0=" name="__VIEWSTATE"/> <input id="PageGuid" type="hidden" value="659179a1-bdcc-41f3-8f27-0495ae9356fd" name="PageGuid"/> <table style="BORDER-COLLAPSE: collapse" height="100%" cellSpacing="0" cellPadding="0" width="100%" border="0"><tbody ><tr ><td ><table cellSpacing="0" cellPadding="0" width="100%" border="0"><tbody ><tr ><td vAlign="top" align="left" width="325"><br /></td><td align="right" background="/AIMS/images/header-bkgd.gif"><table style="DISPLAY: inline" cellSpacing="0" cellPadding="0" border="0"><tbody ><tr ><td ><img src="/Aims/images/nav-leftend.gif"/></td><td background="/Aims/images/nav-center.gif"><span ><table id="NavControl__ctl0_group_1" style="Z-INDEX: 999" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl0_group_1', null, null, 0);" cellSpacing="0" cellPadding="0" border="0"><tbody ><tr ></tr></tbody></table></span><span ><table style="LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px"><tbody ><tr ><td ><br /></td></tr></tbody></table></span><span ><table class="MenuGroup" id="NavControl__ctl1_group_1" style="Z-INDEX: 999" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_1', null, null, 250);" cellSpacing="0" cellPadding="0" border="0"><tbody ><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_1" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_1', 'NavControl__ctl1_group_2', 'belowleft', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '10', '', 'MyWork/Inbox.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_1', 'NavControl__ctl1_group_1', 'NavControl__ctl1_group_2', 250, null);">MY WORK</td><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_6" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_6', 'NavControl__ctl1_group_7', 'belowleft', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '1', '', 'Matter/Matter_List.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_6', 'NavControl__ctl1_group_1', 'NavControl__ctl1_group_7', 250, null);">MATTER</td><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_7" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_7', 'NavControl__ctl1_group_8', 'belowleft', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '2', '', 'Administrator/Admin_Home.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_7', 'NavControl__ctl1_group_1', 'NavControl__ctl1_group_8', 250, null);">ADMINISTRATOR</td><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_20" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_20', 'NavControl__ctl1_group_21', 'belowleft', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '15', '', 'MyWork/AIE.aspx?ClearForm=true'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_20', 'NavControl__ctl1_group_1', 'NavControl__ctl1_group_21', 250, null);">AIE</td><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_21" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_21', 'NavControl__ctl1_group_22', 'belowleft', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '16', '', 'Reports/ReportsFrontPage.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_21', 'NavControl__ctl1_group_1', 'NavControl__ctl1_group_22', 250, null);">REPORTS</td><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_22" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_22', 'NavControl__ctl1_group_23', 'belowleft', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '17', '', 'javascript:window.open(&quot;[appRoot]/Documentation/PubAIMS_3_02/AIMS_Master_Page.htm&quot;)'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_22', 'NavControl__ctl1_group_1', 'NavControl__ctl1_group_23', 250, null);">HELP</td><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_23" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_23', 'NavControl__ctl1_group_24', 'belowleft', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '34', '', 'Logon.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_23', 'NavControl__ctl1_group_1', 'NavControl__ctl1_group_24', 250, null);">LOGOFF</td></tr></tbody></table></span><span ><table class="MenuGroup" id="NavControl__ctl1_group_2" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_2')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_2', 'NavControl__ctl1_item_1', 'NavControl__ctl1_group_1', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_2" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_2', 'NavControl__ctl1_group_3', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '11', '', 'MyWork/Inbox.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_2', 'NavControl__ctl1_group_2', 'NavControl__ctl1_group_3', 250, null);">INBOX</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_3" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_3', 'NavControl__ctl1_group_4', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '12', '', 'MyWork/Coordinator.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_3', 'NavControl__ctl1_group_2', 'NavControl__ctl1_group_4', 250, null);">COORDINATOR</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_4" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_4', 'NavControl__ctl1_group_5', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '13', '', 'MyWork/ErrorManagement.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_4', 'NavControl__ctl1_group_2', 'NavControl__ctl1_group_5', 250, null);">ERROR MANAGER</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_5" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_5', 'NavControl__ctl1_group_6', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '14', '', 'MyWork/Invoice_Search.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_5', 'NavControl__ctl1_group_2', 'NavControl__ctl1_group_6', 250, null);">SEARCH</td></tr></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_3" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_3')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_3', 'NavControl__ctl1_item_2', 'NavControl__ctl1_group_2', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_4" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_4')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_4', 'NavControl__ctl1_item_3', 'NavControl__ctl1_group_2', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_5" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_5')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_5', 'NavControl__ctl1_item_4', 'NavControl__ctl1_group_2', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_6" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_6')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_6', 'NavControl__ctl1_item_5', 'NavControl__ctl1_group_2', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_7" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_7')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_7', 'NavControl__ctl1_item_6', 'NavControl__ctl1_group_1', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_8" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_8')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_8', 'NavControl__ctl1_item_7', 'NavControl__ctl1_group_1', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_8" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_8', 'NavControl__ctl1_group_9', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '19', '', 'Administrator/GeneralSettings_View.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_8', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_9', 250, null);">GENERAL SETTINGS</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_9" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_9', 'NavControl__ctl1_group_10', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '30', '', 'Integration/Log_View.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_9', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_10', 250, null);">INTEGRATION LOG</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_10" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_10', 'NavControl__ctl1_group_11', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '20', '', 'Administrator/Lookup_List.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_10', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_11', 250, null);">LOOKUPS</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_11" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_11', 'NavControl__ctl1_group_12', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '37', '', 'NotificationLog/Log_View.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_11', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_12', 250, null);">NOTIFICATION LOG</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_12" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_12', 'NavControl__ctl1_group_13', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '7', '', 'Administrator/MatterType_List.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_12', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_13', 250, null);">MATTER TYPES</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_13" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_13', 'NavControl__ctl1_group_14', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '6', '', 'Professional/Prof_List.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_13', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_14', 250, null);">PROFESSIONALS</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_14" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_14', 'NavControl__ctl1_group_15', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '9', '', 'Vendor/Vendor_List.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_14', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_15', 250, null);">VENDORS</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_15" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_15', 'NavControl__ctl1_group_16', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '32', '', 'Workflow/WorkflowTitle_List.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_15', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_16', 250, null);">WORKFLOW TITLES</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_16" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_16', 'NavControl__ctl1_group_17', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '36', '', 'Professional/Prof_SubList.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_16', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_17', 250, null);">WORKFLOW SEARCH-REPLACE</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_17" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_17', 'NavControl__ctl1_group_18', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '5', '', 'Workgroup/Workgroup_List.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_17', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_18', 250, null);">WORKGROUPS</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_18" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_18', 'NavControl__ctl1_group_19', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '33', '', 'Administrator/System_View.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_18', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_19', 250, null);">SYSTEM POLICY</td></tr><tr ><td class="MenuItem" onmousemove="return false;" id="NavControl__ctl1_item_19" ondblclick="return false;" onmouseover="this.className='MenuItemOver';if (document.readyState == 'complete') aspnm_itemMsOver('NavControl__ctl1_item_19', 'NavControl__ctl1_group_20', 'rightdown', 0, 0, 250, null);" onclick="aspnm_hideAllGroups();Link_OnClick(this.id, '18', '', 'Timekeeper/TimekeeperClassification_List.aspx'); " onmouseout="this.className='MenuItem';if (document.readyState == 'complete') aspnm_itemMsOut('NavControl__ctl1_item_19', 'NavControl__ctl1_group_8', 'NavControl__ctl1_group_20', 250, null);">TIMEKEEPER CLASSIFICATIONS</td></tr></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_9" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_9')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_9', 'NavControl__ctl1_item_8', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_10" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_10')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_10', 'NavControl__ctl1_item_9', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_11" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_11')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_11', 'NavControl__ctl1_item_10', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_12" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_12')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_12', 'NavControl__ctl1_item_11', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_13" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_13')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_13', 'NavControl__ctl1_item_12', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_14" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_14')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_14', 'NavControl__ctl1_item_13', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_15" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_15')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_15', 'NavControl__ctl1_item_14', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_16" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_16')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_16', 'NavControl__ctl1_item_15', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_17" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_17')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_17', 'NavControl__ctl1_item_16', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_18" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_18')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_18', 'NavControl__ctl1_item_17', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_19" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_19')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_19', 'NavControl__ctl1_item_18', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_20" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_20')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_20', 'NavControl__ctl1_item_19', 'NavControl__ctl1_group_8', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_21" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_21')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_21', 'NavControl__ctl1_item_20', 'NavControl__ctl1_group_1', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_22" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_22')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_22', 'NavControl__ctl1_item_21', 'NavControl__ctl1_group_1', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_23" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_23')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_23', 'NavControl__ctl1_item_22', 'NavControl__ctl1_group_1', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table class="MenuGroup" id="NavControl__ctl1_group_24" onmouseover="aspnm_groupMsOver('NavControl__ctl1_group_24')" style="Z-INDEX: 999; LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px" onmouseout="if (document.readyState == 'complete') aspnm_groupMsOut('NavControl__ctl1_group_24', 'NavControl__ctl1_item_23', 'NavControl__ctl1_group_1', 250, null);" cellSpacing="0" cellPadding="0" border="0"><tbody ></tbody></table><table style="LEFT: 0px; VISIBILITY: hidden; POSITION: absolute; TOP: 0px"><tbody ><tr ><td ><br /></td></tr></tbody></table></span></td><td ><img src="/Aims/images/nav-rightend.gif"/></td></tr></tbody></table></td><td vAlign="top" align="left" width="20"><img height="70" alt="" src="/AIMS/images/header-rightend.gif" width="20" border="0"/></td></tr></tbody></table></td></tr><tr ><td width="100%" height="100%"><table height="100%" width="100%" border="0"><tbody ><tr ><td vAlign="top" align="middle"><table border="0"><tbody ><tr ><td align="left"><center ><div id="CustomValidationSummary" style="DISPLAY: none"><div style="DISPLAY: none"></div><table style="BORDER-COLLAPSE: collapse" cellSpacing="0" cellPadding="0"><tbody ><tr ><td ><img src="/AIMS/images/alertLeftTop.gif"/><br /><br /></td><td ><table style="BORDER-COLLAPSE: collapse" cellSpacing="0" cellPadding="0"><tbody ><tr ><td width="50%" background="/AIMS/images/alertHorizontal.gif"><br /><br /></td><td ><img src="/AIMS/images/alert.gif"/><br /><br /></td><td width="50%" background="/AIMS/images/alertHorizontal.gif"><br /><br /></td></tr></tbody></table><br /><br /></td><td ><img src="/AIMS/images/alertRightTop.gif"/><br /><br /></td></tr><tr ><td background="/AIMS/images/alertLeftVertical.gif"><br /><br /></td><td vAlign="center" align="middle"><div id="ValidationSummaryHeader">Header Text<br /><br /></div><div id="ValidationSummaryItem" style="DISPLAY: none">- Item Text<br /></div><br /><br /></td><td background="/AIMS/images/alertRightVertical.gif"><br /><br /></td></tr><tr ><td ><img src="/AIMS/images/alertLeftBottom.gif"/><br /><br /></td><td background="/AIMS/images/alertHorizontal.gif"><br /><br /></td><td ><img src="/AIMS/images/alertRightBottom.gif"/><br /><br /></td></tr></tbody></table></div></center><input id="Version_FetchMatterVendorSummaryBO" type="hidden" value="0" name="Version_FetchMatterVendorSummaryBO"/><input id="Version_DocumentBO" type="hidden" value="0" name="Version_DocumentBO"/><input id="Version_MatterBO" type="hidden" value="0" name="Version_MatterBO"/><input id="Version_CustomSettingsBO" type="hidden" value="0" name="Version_CustomSettingsBO"/> <table class="Clear"><tbody ><tr ><td class="Title">ListMatters</td></tr></tbody></table><br /><div id="Panel1" style="WIDTH: 400px; HEIGHT: 21px"><span class="DCViewListActive">Open</span><span class="DCViewListActive"> |</span> <a class="DCViewListInactive" id="DCViewLink2" onclick="setView('Closed',this);" href="javascript:__doPostBack('DCViewLink2','')" pagecontext="">Closed</a><span class="DCViewListActive"> |</span> <a class="DCViewListInactive" id="DCViewLink3" onclick="setView('All',this);" href="javascript:__doPostBack('DCViewLink3','')" pagecontext="">All</a> </div></td></tr><tr ><td ><div id="pnOpen" style="DISPLAY: block; WIDTH: 160px"><table class="Normal"><tbody ><tr class="Header"><td class="Header">Open Matters </td><td align="right"><table class="Invisible"><tbody ><tr ><td ><div id="DCImageButton1" title="Add Matter" onclick="DCImageButton1_onclick(this);return true;" anchorclicked="false"><table style="BORDER-COLLAPSE: collapse" cellSpacing="0" cellPadding="0" width="28" border="0"><tbody ><tr ><td width="1%"><img src="/AIMS/images/bt2Left26gray.gif" border="0"/></td><td style="PADDING-RIGHT: 2px; PADDING-LEFT: 4px" vAlign="center" align="middle" width="98%" background="/AIMS/images/bt2Center26gray.gif"><a class="ButtonText" id="imgbtaDCImageButton1" href="#AimsStandardLink"><nobr ><div class="ButtonText" id="dvbtDCImageButton1Text" style="DISPLAY: inline">Add</div></nobr></a></td><td style="PADDING-RIGHT: 4px; PADDING-LEFT: 2px" vAlign="center" align="middle" width="98%" background="/AIMS/images/bt2Center26gray.gif"><img id="imgbtDCImageButton1" src="/AIMS/images/add.gif" border="0"/></td><td width="1%"><img src="/AIMS/images/bt2Right26gray.gif" border="0"/></td></tr></tbody></table></div></td><td ><div id="DCCollapseButton1" title="" onclick="DCCollapseButton1_onclick(this);return true;" anchorclicked="false"><table style="BORDER-COLLAPSE: collapse" cellSpacing="0" cellPadding="0" width="0" border="0"><tbody ><tr ><td width="1%"><img src="/AIMS/images/bt2Left26gray.gif" border="0"/></td><td style="PADDING-RIGHT: 4px; PADDING-LEFT: 4px" vAlign="center" align="middle" width="98%" background="/AIMS/images/bt2Center26gray.gif"><a class="ButtonText" id="imgbtaDCCollapseButton1" href="#AimsStandardLink"><img id="imgbtDCCollapseButton1" src="/AIMS/images/blue-chevron_up.gif" border="0"/></a></td><td width="1%"><img src="/AIMS/images/bt2Right26gray.gif" border="0"/></td></tr></tbody></table></div><input id="SearchState" type="hidden" value="False" name="SearchState"/></td></tr></tbody></table></td></tr></tbody></table></div><div id="panelSearch" style="DISPLAY: block"><table class="Normal" id="Table1"><tbody ><tr class="Report"><td class="Report"><br /></td><td class="Report"><br /></td><td class="Report"><br /></td><td class="Report" style="WIDTH: 287px"><br /></td><td class="Report"><br /></td></tr><tr class="Report"><td class="Report"><br /></td><td class="Report"><br /></td><td class="Report"><br /></td><td class="Report" style="WIDTH: 283px"><br /></td><td class="Report" align="right"><br /></td></tr></tbody></table></div></td></tr></tbody></table></td></tr></tbody></table></td></tr><tr ><td ><table cellSpacing="0" cellPadding="0" width="100%"><tbody ><tr ><td vAlign="top" align="left" background="/AIMS/images/footer-bkgd.gif" colSpan="3"><img height="17" alt="" src="/AIMS/images/footer-bkgd.gif" width="50" border="0"/></td></tr><tr ><td vAlign="top" align="left" colSpan="3"><font face="verdana" color="#666666" size="1"><br /></font></td></tr></tbody></table></td></tr></tbody></table><input id="ViewLinkId" type="hidden" name="ViewLinkId"/><input id="View" type="hidden" value="Default" name="View"/><input id="CausesValidation" type="hidden" name="CausesValidation"/><input id="RenderLocation" type="hidden" value="Server" name="RenderLocation"/> </form></body>
-</HTML>
diff --git a/test/rexml/data/ticket_68.xml b/test/rexml/data/ticket_68.xml
deleted file mode 100644
index 7ab34b08cd..0000000000
--- a/test/rexml/data/ticket_68.xml
+++ /dev/null
@@ -1,590 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Rev 1.05
- Changed the <gram> element name to <pos>
- Added the g_gend attribute
- moved the s_inf element
--->
-<!-- Rev 1.04
- Changes:
- Rename the project "JMdict" and add the g_lang attribute to the
- <gloss> entity - 08 May 1999
- Moved the <gram>, <field> and <misc> elements down to be in the
- <sense> region, as suggested by Chris Czeyka. I have also tidied up
- some of the "*" as he suggested. - 27 May 2000
- Added the re_nokanji element - Sep 2003.
- -->
-<!DOCTYPE JMdict [
-<!ELEMENT JMdict (entry*)>
-<!-- -->
-<!ELEMENT entry (ent_seq, k_ele*, r_ele+, info*, sense+)>
- <!-- Entries consist of kanji elements, reading elements,
- general information and sense elements. Each entry must have at
- least one reading element and one sense element. Others are optional.
- -->
-<!ELEMENT ent_seq (#PCDATA)>
- <!-- A unique numeric sequence number for each entry
- -->
-<!ELEMENT k_ele (keb, ke_inf*, ke_pri*)>
- <!-- The kanji element, or in its absence, the reading element, is
- the defining component of each entry.
- The overwhelming majority of entries will have a single kanji
- element associated with a word in Japanese. Where there are
- multiple kanji elements within an entry, they will be orthographical
- variants of the same word, either using variations in okurigana, or
- alternative and equivalent kanji. Common "mis-spellings" may be
- included, provided they are associated with appropriate information
- fields. Synonyms are not included; they may be indicated in the
- cross-reference field associated with the sense element.
- -->
-<!ELEMENT keb (#PCDATA)>
- <!-- This element will contain a word or short phrase in Japanese
- which is written using at least one kanji. The valid characters are
- kanji, kana, related characters such as chouon and kurikaeshi, and
- in exceptional cases, letters from other alphabets.
- -->
-<!ELEMENT ke_inf (#PCDATA)>
- <!-- This is a coded information field related specifically to the
- orthography of the keb, and will typically indicate some unusual
- aspect, such as okurigana irregularity.
- -->
-<!ELEMENT ke_pri (#PCDATA)>
- <!-- This and the equivalent re_pri field are provided to record
- information about the relative priority of the entry, and consist
- of codes indicating the word appears in various references which
- can be taken as an indication of the frequency with which the word
- is used. This field is intended for use either by applications which
- want to concentrate on entries of a particular priority, or to
- generate subset files.
- The current values in this field are:
- - news1/2: appears in the "wordfreq" file compiled by Alexandre Girardi
- from the Mainichi Shimbun. (See the Monash ftp archive for a copy.)
- Words in the first 12,000 in that file are marked "news1" and words
- in the second 12,000 are marked "news2".
- - ichi1/2: appears in the "Ichimango goi bunruishuu", Senmon Kyouiku
- Publishing, Tokyo, 1998.
- - spec1 and spec2: a small number of words use this marker when they
- are detected as being common, but are not included in other lists.
- - gai1: common loanwords, based on the wordfreq file.
- - nfxx: this is an indicator of frequency-of-use ranking in the
- wordfreq file. "xx" is the number of the set of 500 words in which
- the entry can be found, with "01" assigned to the first 500, "02"
- to the second, and so on.
-
- The reason both the kanji and reading elements are tagged is because
- on occasions a priority is only associated with a particular
- kanji/reading pair.
- -->
-<!-- -->
-<!ELEMENT r_ele (reb, re_nokanji?, re_restr*, re_inf*, re_pri*)>
- <!-- The reading element typically contains the valid readings
- of the word(s) in the kanji element using modern kanadzukai.
- Where there are multiple reading elements, they will typically be
- alternative readings of the kanji element. In the absence of a
- kanji element, i.e. in the case of a word or phrase written
- entirely in kana, these elements will define the entry.
- -->
-<!ELEMENT reb (#PCDATA)>
- <!-- this element content is restricted to kana and related
- characters such as chouon and kurikaeshi. Kana usage will be
- consistent between the keb and reb elements; e.g. if the keb
- contains katakana, so too will the reb.
- -->
-<!ELEMENT re_nokanji (#PCDATA)>
- <!-- This element, which will usually have a null value, indicates
- that the reb, while associated with the keb, cannot be regarded
- as a true reading of the kanji. It is typically used for words
- such as foreign place names, gairaigo which can be in kanji or
- katakana, etc.
- -->
-<!ELEMENT re_restr (#PCDATA)>
- <!-- This element is used to indicate when the reading only applies
- to a subset of the keb elements in the entry. In its absence, all
- readings apply to all kanji elements. The contents of this element
- must exactly match those of one of the keb elements.
- -->
-<!ELEMENT re_inf (#PCDATA)>
- <!-- General coded information pertaining to the specific reading.
- Typically it will be used to indicate some unusual aspect of
- the reading. -->
-<!ELEMENT re_pri (#PCDATA)>
- <!-- See the comment on ke_pri above. -->
-<!-- -->
-<!ELEMENT info (lang*, dial*, links*, bibl*, etym*, audit*)>
- <!-- general coded information relating to the entry as a whole.-->
-<!ELEMENT lang (#PCDATA)>
- <!-- For loan-words, the ISO 639 two-letter code for the originating
- language. -->
-<!ELEMENT dial (#PCDATA)>
- <!-- For words specifically associated with regional dialects in
- Japanese, the entity code for that dialect, e.g. ksb for Kansaiben.
- -->
-<!ELEMENT bibl (bib_tag?, bib_txt?)>
-<!ELEMENT bib_tag (#PCDATA)>
-<!ELEMENT bib_txt (#PCDATA)>
- <!-- Bibliographic information about the entry. The bib_tag will a
- coded reference to an entry in an external bibliographic database.
- The bib_txt field may be used for brief (local) descriptions.-->
-<!ELEMENT etym (#PCDATA)>
- <!-- This field is used to hold information about the etymology
- of the entry. -->
-<!ELEMENT links (link_tag, link_desc, link_uri)>
-<!ELEMENT link_tag (#PCDATA)>
-<!ELEMENT link_desc (#PCDATA)>
-<!ELEMENT link_uri (#PCDATA)>
- <!-- This element holds details of linking information to
- entries in other electronic repositories. The link_tag will be
- coded to indicate the type of link (text, image, sound), the
- link_desc will provided a textual label for the link, and the
- link_uri contains the actual URI. -->
-<!ELEMENT audit (upd_date, upd_detl)>
-<!ELEMENT upd_date (#PCDATA)>
-<!ELEMENT upd_detl (#PCDATA)>
- <!-- The audit element will contain the date and other information
- about updates to the entry. Can be used to record the source of
- the material. -->
-<!-- -->
-<!ELEMENT sense (stagk*, stagr*, pos*, xref*, ant*, field*, misc*, s_inf*, gloss*, example*)>
- <!-- The sense element will record the translational equivalent
- of the Japanese word, plus other related information. Where there
- are several distinctly different meanings of the word, multiple
- sense elements will be employed.
- -->
-<!ELEMENT stagk (#PCDATA)>
-<!ELEMENT stagr (#PCDATA)>
- <!-- These elements, if present, indicate that the sense is restricted
- to the lexeme represented by the keb and/or reb. -->
-<!ELEMENT xref (#PCDATA)*>
- <!-- This element is used to indicate a cross-reference to another
- entry with a similar or related meaning or sense. The content of
- this element must exactly match that of a keb or reb element in
- another entry.
- -->
-<!ELEMENT ant (#PCDATA)*>
- <!-- This element is used to indicate another entry which is an
- antonym of the current entry/sense. The content of this element
- must exactly match that of a keb or reb element in another entry.
- -->
-<!ELEMENT pos (#PCDATA)>
- <!-- Part-of-speech information about the entry/sense. Should use
- appropriate entity codes.
- -->
-<!ELEMENT field (#PCDATA)>
- <!-- Information about the field of application of the entry. When
- absent, general application is implied. Entity coding for specific
- fields of application. -->
-<!ELEMENT misc (#PCDATA)>
- <!-- This element is used for other relevant information about
- the entry. -->
-<!ELEMENT gloss (#PCDATA | pri)*>
- <!-- Within each sense will be one or more "glosses", i.e.
- target-language words or phrases which are equivalents to the
- Japanese word. This element would normally be present, however it
- may be omitted in entries which are purely for a cross-reference.
- -->
-<!ATTLIST gloss g_lang CDATA "en">
- <!-- The g_lang attribute defines the target language of the
- gloss. It will be coded using the two-letter language code from
- the ISO 639 standard. When absent, the value "en" (i.e. English)
- is the default value. -->
-<!ATTLIST gloss g_gend CDATA #IMPLIED>
- <!-- The g_gend attribute defines the gender of the gloss (typically
- a noun in the target language. When absent, the gender is either
- not relevant or has yet to be provided.
- -->
-<!ELEMENT pri (#PCDATA)>
- <!-- These elements highlight particular target-language words which
- are strongly associated with the Japanese word. The purpose is to
- establish a set of target-language words which can effectively be
- used as head-words in a reverse target-language/Japanese relationship.
- -->
-<!ELEMENT example (#PCDATA)>
- <!-- The example elements provide for pairs of short Japanese and
- target-language phrases or sentences which exemplify the usage of the
- Japanese head-word and the target-language gloss. Words in example
- fields would typically not be indexed by a dictionary application.
- -->
-<!ELEMENT s_inf (#PCDATA)>
- <!-- The sense-information elements provided for additional
- information to be recorded about a sense. Typical usage would
- be to indicate such things as level of currency of a sense, the
- regional variations, etc.
- -->
-<!-- The following entity codes are used for common elements within the
-various information fields.
--->
-<!ENTITY MA "martial arts term">
-<!ENTITY X "rude or X-rated term (not displayed in educational software)">
-<!ENTITY abbr "abbreviation">
-<!ENTITY adj "adjective (keiyoushi)">
-<!ENTITY adj-na "adjectival nouns or quasi-adjectives (keiyodoshi)">
-<!ENTITY adj-no "nouns which may take the genitive case particle `no'">
-<!ENTITY adj-pn "pre-noun adjectival (rentaishi)">
-<!ENTITY adj-t "`taru' adjective">
-<!ENTITY adv "adverb (fukushi)">
-<!ENTITY adv-n "adverbial noun">
-<!ENTITY adv-to "adverb taking the `to' particle">
-<!ENTITY arch "archaism">
-<!ENTITY ateji "ateji (phonetic) reading">
-<!ENTITY aux "auxiliary">
-<!ENTITY aux-v "auxiliary verb">
-<!ENTITY aux-adj "auxiliary adjective">
-<!ENTITY Buddh "Buddhist term">
-<!ENTITY chn "children's language">
-<!ENTITY col "colloquialism ">
-<!ENTITY comp "computer terminology">
-<!ENTITY conj "conjunction">
-<!ENTITY derog "derogatory">
-<!ENTITY ek "exclusively kanji">
-<!ENTITY exp "Expressions (phrases, clauses, etc.)">
-<!ENTITY fam "familiar language ">
-<!ENTITY fem "female term or language">
-<!ENTITY food "food term">
-<!ENTITY geom "geometry term">
-<!ENTITY gikun "gikun (meaning) reading">
-<!ENTITY gram "grammatical term">
-<!ENTITY hon "honorific or respectful (sonkeigo) language ">
-<!ENTITY hum "humble (kenjougo) language ">
-<!ENTITY iK "word containing irregular kanji usage">
-<!ENTITY id "idiomatic expression ">
-<!ENTITY ik "word containing irregular kana usage">
-<!ENTITY int "interjection (kandoushi)">
-<!ENTITY io "irregular okurigana usage">
-<!ENTITY iv "irregular verb">
-<!ENTITY ling "linguistics terminology">
-<!ENTITY m-sl "manga slang">
-<!ENTITY male "male term or language">
-<!ENTITY male-sl "male slang">
-<!ENTITY math "mathematics">
-<!ENTITY mil "military">
-<!ENTITY n "noun (common) (futsuumeishi)">
-<!ENTITY n-adv "adverbial noun (fukushitekimeishi)">
-<!ENTITY n-suf "noun, used as a suffix">
-<!ENTITY n-pref "noun, used as a prefix">
-<!ENTITY n-t "noun (temporal) (jisoumeishi)">
-<!ENTITY neg "negative (in a negative sentence, or with negative verb)">
-<!ENTITY neg-v "negative verb (when used with)">
-<!ENTITY num "numeric">
-<!ENTITY oK "word containing out-dated kanji ">
-<!ENTITY obs "obsolete term">
-<!ENTITY obsc "obscure term">
-<!ENTITY ok "out-dated or obsolete kana usage">
-<!ENTITY pol "polite (teineigo) language ">
-<!ENTITY pref "prefix ">
-<!ENTITY prt "particle ">
-<!ENTITY physics "physics terminology">
-<!ENTITY qv "quod vide (see another entry)">
-<!ENTITY rare "rare">
-<!ENTITY sl "slang">
-<!ENTITY suf "suffix ">
-<!ENTITY uK "word usually written using kanji alone ">
-<!ENTITY uk "word usually written using kana alone ">
-<!ENTITY v1 "Ichidan verb">
-<!ENTITY v5 "Godan verb (not completely classified)">
-<!ENTITY v5aru "Godan verb - -aru special class">
-<!ENTITY v5b "Godan verb with `bu' ending">
-<!ENTITY v5g "Godan verb with `gu' ending">
-<!ENTITY v5k "Godan verb with `ku' ending">
-<!ENTITY v5k-s "Godan verb - Iku/Yuku special class">
-<!ENTITY v5m "Godan verb with `mu' ending">
-<!ENTITY v5n "Godan verb with `nu' ending">
-<!ENTITY v5r "Godan verb with `ru' ending">
-<!ENTITY v5r-i "Godan verb with `ru' ending (irregular verb)">
-<!ENTITY v5s "Godan verb with `su' ending">
-<!ENTITY v5t "Godan verb with `tsu' ending">
-<!ENTITY v5u "Godan verb with `u' ending">
-<!ENTITY v5u-s "Godan verb with `u' ending (special class)">
-<!ENTITY v5uru "Godan verb - Uru old class verb (old form of Eru)">
-<!ENTITY vi "intransitive verb ">
-<!ENTITY vk "Kuru verb - special class">
-<!ENTITY vs "noun or participle which takes the aux. verb suru">
-<!ENTITY vs-s "suru verb - special class">
-<!ENTITY vs-i "suru verb - irregular">
-<!ENTITY vz "zuru verb - (alternative form of -jiru verbs)">
-<!ENTITY vt "transitive verb">
-<!ENTITY vulg "vulgar expression or word ">
-<!ENTITY mg "masculine gender">
-<!ENTITY fg "feminine gender">
-<!ENTITY ng "neuter gender">
-]>
-<!-- JMdict created: 2006-09-11 -->
-<JMdict>
-<!-- JMdict Japanese-Multilingual Dictionary file (XML format) -->
-<!-- Using V1.05 of the DTD -->
-<!-- Copyright J.W. Breen (jwb@csse.monash.edu.au) -->
-<entry>
-<ent_seq>1000000</ent_seq>
-<k_ele>
-<keb>ヽ</keb>
-</k_ele>
-<r_ele>
-<reb>くりかえし</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>repetition mark in katakana</gloss>
-<gloss g_lang="de">Wiederholungszeichen für Katakana</gloss>
-<gloss g_lang="de">normalerweise nur in vertikaler Schreibweise verwendet</gloss>
-<gloss g_lang="fr">marque de la répétition dans katakana</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000010</ent_seq>
-<k_ele>
-<keb>ヾ</keb>
-</k_ele>
-<r_ele>
-<reb>くりかえし</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>voiced repetition mark in katakana</gloss>
-<gloss g_lang="de">stimmhaftes Wiederholungszeichen für Katakana</gloss>
-<gloss g_lang="de">normalerweise nur in vertikaler Schreibweise verwendet</gloss>
-<gloss g_lang="fr">marque de la répétition sonore dans katakana</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000020</ent_seq>
-<k_ele>
-<keb>ゝ</keb>
-</k_ele>
-<r_ele>
-<reb>くりかえし</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>repetition mark in hiragana</gloss>
-<gloss g_lang="de">Wiederholungszeichen für Hiragana</gloss>
-<gloss g_lang="de">normalerweise nur in vertikaler Schreibweise verwendet</gloss>
-<gloss g_lang="fr">marque de la répétition dans hiragana</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000030</ent_seq>
-<k_ele>
-<keb>ゞ</keb>
-</k_ele>
-<r_ele>
-<reb>くりかえし</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>voiced repetition mark in hiragana</gloss>
-<gloss g_lang="de">stimmhaftes Wiederholungszeichen für Hiragana</gloss>
-<gloss g_lang="de">normalerweise nur in vertikaler Schreibweise verwendet</gloss>
-<gloss g_lang="fr">marque de la répétition sonore dans hiragana</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000040</ent_seq>
-<k_ele>
-<keb>〃</keb>
-</k_ele>
-<r_ele>
-<reb>おなじく</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>ditto mark</gloss>
-<gloss g_lang="ru">знак "то же самое"</gloss>
-<gloss g_lang="de">Wiederholungszeichen in Tabellen</gloss>
-<gloss g_lang="fr">idem marque</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000050</ent_seq>
-<k_ele>
-<keb>仝</keb>
-</k_ele>
-<r_ele>
-<reb>どうじょう</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>"as above" mark</gloss>
-<gloss g_lang="de">Abkürzung für "siehe oben"</gloss>
-<gloss g_lang="fr">comme au-dessus</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000060</ent_seq>
-<k_ele>
-<keb>々</keb>
-</k_ele>
-<r_ele>
-<reb>くりかえし</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>repetition of kanji (sometimes voiced)</gloss>
-<gloss g_lang="de">Wiederholungszeichen für Kanji</gloss>
-<gloss g_lang="de">(Laut wird durch Wiederholung manchmal stimmhaft)</gloss>
-<gloss g_lang="fr">répétition de kanji(quelquefois a exprimé)</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000070</ent_seq>
-<k_ele>
-<keb>〆</keb>
-</k_ele>
-<r_ele>
-<reb>しめ</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>end or closure mark</gloss>
-<gloss g_lang="de">Zeichen als eine Art Versiegelung über der zugeklebten Lasche auf der Rückseite eines Briefumschlages</gloss>
-<gloss g_lang="fr">fin ou marque de la fermeture</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000080</ent_seq>
-<k_ele>
-<keb>〇</keb>
-</k_ele>
-<k_ele>
-<keb>○</keb>
-<ke_inf>&iK;</ke_inf>
-</k_ele>
-<r_ele>
-<reb>かんすうじゼロ</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<xref>漢数字</xref>
-<xref>ゼロ</xref>
-<gloss>"kanji" zero</gloss>
-<gloss g_lang="de">Kanji-Ziffer für Null</gloss>
-<gloss g_lang="fr">kanji</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000090</ent_seq>
-<k_ele>
-<keb>○</keb>
-</k_ele>
-<k_ele>
-<keb>〇</keb>
-<ke_inf>&iK;</ke_inf>
-</k_ele>
-<r_ele>
-<reb>まる</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>circle (sometimes used for zero)</gloss>
-<gloss g_lang="ru">круг</gloss>
-<gloss g_lang="ru">но́ль</gloss>
-<gloss g_lang="de">Kreis</gloss>
-<gloss g_lang="de">Markierung für "richtig"</gloss>
-<gloss g_lang="de">Maru</gloss>
-<gloss g_lang="de">(ein japan. Schriftfont hat mindestens drei verschiedene Codierungen und Darstellungen für "maru")</gloss>
-<gloss g_lang="fr">entourez</gloss>
-<gloss g_lang="fr">mettez à zéro</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000100</ent_seq>
-<k_ele>
-<keb>ABC順</keb>
-</k_ele>
-<r_ele>
-<reb>エービーシーじゅん</reb>
-</r_ele>
-<r_ele>
-<reb>ええびいしいじゅん</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>alphabetical order</gloss>
-<gloss g_lang="de">alphabetische Ordnung</gloss>
-<gloss g_lang="de">alphabetische Reihenfolge</gloss>
-<gloss g_lang="fr">ordre alphabétique</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000110</ent_seq>
-<k_ele>
-<keb>CDプレーヤー</keb>
-</k_ele>
-<r_ele>
-<reb>シーディープレーヤー</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>CD player</gloss>
-<gloss g_lang="ru">CD плеер</gloss>
-<gloss g_lang="ru">проигрыватель компакт-дисков</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000120</ent_seq>
-<k_ele>
-<keb>Hな映画</keb>
-</k_ele>
-<k_ele>
-<keb>エッチな映画</keb>
-</k_ele>
-<r_ele>
-<reb>エッチなえいが</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>pornographic film</gloss>
-<gloss>salacious film</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000130</ent_seq>
-<k_ele>
-<keb>N響</keb>
-</k_ele>
-<r_ele>
-<reb>エヌきょう</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<misc>&abbr;</misc>
-<gloss>NHK Symphony Orchestra</gloss>
-<gloss g_lang="fr">NHK Symphonie Orchestre(abbr)</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000140</ent_seq>
-<r_ele>
-<reb>Oバック</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>O-back</gloss>
-<gloss>skirt with peek-a-boo hole in rump</gloss>
-<gloss g_lang="fr">O En arrière</gloss>
-<gloss g_lang="fr">contournez avec coucou trou dans croupe</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-<entry>
-<ent_seq>1000150</ent_seq>
-<r_ele>
-<reb>RS232ケーブル</reb>
-</r_ele>
-<sense>
-<pos>&n;</pos>
-<gloss>rs232 cable</gloss>
-<gloss g_lang="fr">les rs232 câblent</gloss>
-<gloss g_lang="fr">(JF2)</gloss>
-</sense>
-</entry>
-</JMdict>
diff --git a/test/rexml/data/tutorial.xml b/test/rexml/data/tutorial.xml
deleted file mode 100644
index bf5783d09a..0000000000
--- a/test/rexml/data/tutorial.xml
+++ /dev/null
@@ -1,678 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<?xml-stylesheet type="text/css"
-href="../../documentation/documentation.css"
-?>
-<?xml-stylesheet type="text/xsl"
-href="../../documentation/documentation.xsl"
-?>
-<!DOCTYPE documentation SYSTEM "http://www.germane-software.com/software/documentation/documentation.dtd">
-<documentation>
- <head>
- <title>REXML Tutorial</title>
-
- <version>$Revision: 1.1.2.1 $</version>
-
- <date>*2001-296+594</date>
-
- <home>http://www.germane-software.com/~ser/software/rexml</home>
-
- <base></base>
-
- <language>ruby</language>
-
- <author email="ser@germane-software.com"
- href="http://www.germane-software.com/~ser">Sean Russell</author>
- </head>
-
- <overview>
- <purpose lang="en">
- <p>This is a tutorial for using <link
- href="http://www.germane-software.com/~ser/software/rexml">REXML</link>,
- a pure Ruby XML processor.</p>
- </purpose>
-
- <general>
- <p>REXML was inspired by the Electric XML library for Java, which
- features an easy-to-use API, small size, and speed. Hopefully, REXML,
- designed with the same philosophy, has these same features. I've tried
- to keep the API as intuitive as possible, and have followed the Ruby
- methodology for method naming and code flow, rather than mirroring the
- Java API.</p>
-
- <p>REXML supports both tree and stream document parsing. Stream parsing
- is faster (about 1.5 times as fast). However, with stream parsing, you
- don't get access to features such as XPath.</p>
-
- <p>The <link href="../doc/index.html">API</link> documentation also
- contains code snippits to help you learn how to use various methods.
- This tutorial serves as a starting point and quick guide to using
- REXML.</p>
-
- <subsection title="Tree Parsing XML and accessing Elements">
- <p>We'll start with parsing an XML document</p>
-
- <example>require "rexml/document"
-file = File.new( "mydoc.xml" )
-doc = REXML::Document.new file</example>
-
- <p>Line 3 creates a new document and parses the supplied file. You can
- also do the following</p>
-
- <example>require "rexml/document"
-include REXML # so that we don't have to prefix everything with REXML::...
-string = &lt;&lt;EOF
- &lt;mydoc&gt;
- &lt;someelement attribute="nanoo"&gt;Text, text, text&lt;/someelement&gt;
- &lt;/mydoc&gt;
-EOF
-doc = Document.new string</example>
-
- <p>So parsing a string is just as easy as parsing a file. For future
- examples, I'm going to omit both the <code>require</code> and
- <code>include</code> lines.</p>
-
- <p>Once you have a document, you can access elements in that document
- in a number of ways:</p>
-
- <list>
- <item>The <code>Element</code> class itself has
- <code>each_element_with_attribute</code>, a common way of accessing
- elements.</item>
-
- <item>The attribute <code>Element.elements</code> is an
- <code>Elements</code> class instance which has the <code>each</code>
- and <code>[]</code> methods for accessing elements. Both methods can
- be supplied with an XPath for filtering, which makes them very
- powerful.</item>
-
- <item>Since <code>Element</code> is a subclass of Parent, you can
- also access the element's children directly through the Array-like
- methods <code>Element[], Element.each, Element.find,
- Element.delete</code>. This is the fastest way of accessing
- children, but note that, being a true array, XPath searches are not
- supported, and that all of the element children are contained in
- this array, not just the Element children.</item>
- </list>
-
- <p>Here are a few examples using these methods. First is the source
- document used in the examples. Save this as mydoc.xml before running
- any of the examples that require it:</p>
-
- <example title="The source document">&lt;inventory title="OmniCorp Store #45x10^3"&gt;
- &lt;section name="health"&gt;
- &lt;item upc="123456789" stock="12"&gt;
- &lt;name&gt;Invisibility Cream&lt;/name&gt;
- &lt;price&gt;14.50&lt;/price&gt;
- &lt;description&gt;Makes you invisible&lt;/description&gt;
- &lt;/item&gt;
- &lt;item upc="445322344" stock="18"&gt;
- &lt;name&gt;Levitation Salve&lt;/name&gt;
- &lt;price&gt;23.99&lt;/price&gt;
- &lt;description&gt;Levitate yourself for up to 3 hours per application&lt;/description&gt;
- &lt;/item&gt;
- &lt;/section&gt;
- &lt;section name="food"&gt;
- &lt;item upc="485672034" stock="653"&gt;
- &lt;name&gt;Blork and Freen Instameal&lt;/name&gt;
- &lt;price&gt;4.95&lt;/price&gt;
- &lt;description&gt;A tasty meal in a tablet; just add water&lt;/description&gt;
- &lt;/item&gt;
- &lt;item upc="132957764" stock="44"&gt;
- &lt;name&gt;Grob winglets&lt;/name&gt;
- &lt;price&gt;3.56&lt;/price&gt;
- &lt;description&gt;Tender winglets of Grob. Just add water&lt;/description&gt;
- &lt;/item&gt;
- &lt;/section&gt;
-&lt;/inventory&gt;</example>
-
- <example title="Accessing Elements">doc = Document.new File.new("mydoc.xml")
-doc.elements.each("inventory/section") { |element| puts element.attributes["name"] }
-# -&gt; health
-# -&gt; food
-doc.elements.each("*/section/item") { |element| puts element.attributes["upc"] }
-# -&gt; 123456789
-# -&gt; 445322344
-# -&gt; 485672034
-# -&gt; 132957764
-root = doc.root
-puts root.attributes["title"]
-# -&gt; OmniCorp Store #45x10^3
-puts root.elements["section/item[@stock='44']"].attributes["upc"]
-# -&gt; 132957764
-puts root.elements["section"].attributes["name"]
-# -&gt; health (returns the first encountered matching element)
-puts root.elements[1].attributes["name"]
-# -&gt; health (returns the FIRST child element)
-root.detect {|node| node.kind_of? Element and node.attributes["name"] == "food" }</example>
-
- <p>Notice the second-to-last line of code. Element children in REXML
- are indexed starting at 1, not 0. This is because XPath itself counts
- elements from 1, and REXML maintains this relationship; IE,
- <code>root.elements['*[1]'] == root.elements[1]</code>. The last line
- finds the first child element with the name of "food". As you can see
- in this example, accessing attributes is also straightforward.</p>
-
- <p>You can also access xpaths directly via the XPath class.</p>
-
- <example title="Using XPath"># The invisibility cream is the first &lt;item&gt;
-invisibility = XPath.first( doc, "//item" )
-# Prints out all of the prices
-XPath.each( doc, "//price") { |element| puts element.text }
-# Gets an array of all of the "name" elements in the document.
-names = XPath.match( doc, "//name" ) </example>
-
- <p>Another way of getting an array of matching nodes is through
- Element.elements.to_a(). Although this is a method on elements, if
- passed an XPath it can return an array of arbitrary objects. This is
- due to the fact that XPath itself can return arbitrary nodes
- (Attribute nodes, Text nodes, and Element nodes).</p>
-
- <example title="Using to_a()">all_elements = doc.elements.to_a
-all_children = doc.to_a
-all_upc_strings = doc.elements.to_a( "//item/attribute::upc" )
-all_name_elements = doc.elements.to_a( "//name" )</example>
- </subsection>
-
- <subsection title="Text Nodes">
- <p>REXML attempts to make the common case simple, but this means that
- the uncommon case can be complicated. This is especially true with
- Text nodes.</p>
-
- <p>Text nodes have a lot of behavior, and in the case of internal
- entities, what you get may be different from what you expect. When
- REXML reads an XML document, in parses the DTD and creates an internal
- table of entities. If it finds any of these entities in the document,
- it replaces them with their values:</p>
-
- <example title="Entity Replacement">doc = Document.new '&lt;!DOCTYPE foo [
-&lt;!ENTITY ent "replace"&gt;
-]&gt;&lt;a&gt;&amp;ent;&lt;/a&gt;'
-doc.root.text #-&gt; "replace"
-</example>
-
- <p>When you write the document back out, REXML replaces the values
- with the entity reference:</p>
-
- <example>doc.to_s
-# Generates:
-# &lt;!DOCTYPE foo [
-# &lt;!ENTITY ent "replace"&gt;
-# ]&gt;&lt;a&gt;&amp;ent;&lt;/a&gt;</example>
-
- <p>But there's a problem. What happens if only some of the words are
- also entity reference values?</p>
-
- <example>doc = Document.new '&lt;!DOCTYPE foo [
-&lt;!ENTITY ent "replace"&gt;
-]&gt;&lt;a&gt;replace &amp;ent;&lt;/a&gt;'
-doc.root.text #-&gt; "replace replace"
-</example>
-
- <p>Well, REXML does the only thing it can:</p>
-
- <example>doc.to_s
-# Generates:
-# &lt;!DOCTYPE foo [
-# &lt;!ENTITY ent "replace"&gt;
-# ]&gt;&lt;a&gt;&amp;ent; &amp;ent;&lt;/a&gt;</example>
-
- <p>This is probably not what you expect. However, when designing
- REXML, I had a choice between this behavior, and using immutable text
- nodes. The problem is that, if you can change the text in a node,
- REXML can never tell which tokens you want to have replaced with
- entities. There is a wrinkle: REXML will write what it gets in as long
- as you don't access the text. This is because REXML does lazy
- evaluation of entities. Therefore,</p>
-
- <example title="Lazy Evaluation">doc = Document.new( '&lt;!DOCTYPE foo
- [ &lt;!ENTITY ent "replace"&gt; ]&gt;&lt;a&gt;replace
- &amp;ent;&lt;/a&gt;' ) doc.to_s # Generates: # &lt;!DOCTYPE foo [ #
- &lt;!ENTITY ent "replace"&gt; # ]&gt;&lt;a&gt;<emphasis>replace
- &amp;ent;</emphasis>&lt;/a&gt; doc.root.text #-&gt; Now accessed,
- entities have been resolved doc.to_s # Generates: # &lt;!DOCTYPE foo [
- # &lt;!ENTITY ent "replace"&gt; # ]&gt;&lt;a&gt;<emphasis>&amp;ent;
- &amp;ent;</emphasis>&lt;/a&gt;</example>
-
- <p>There is a programmatic solution: <code>:raw</code>. If you set the
- <code>:raw</code> flag on any Text or Element node, the entities
- within that node will not be processed. This means that you'll have to
- deal with entities yourself:</p>
-
- <example title="Entity Replacement">doc = Document.new('&lt;!DOCTYPE
- foo [ &lt;!ENTITY ent "replace"&gt; ]&gt;&lt;a&gt;replace
- &amp;ent;&lt;/a&gt;',<emphasis>{:raw=&gt;:all})</emphasis>
- doc.root.text #-&gt; "replace &amp;ent;" doc.to_s # Generates: #
- &lt;!DOCTYPE foo [ # &lt;!ENTITY ent "replace"&gt; #
- ]&gt;&lt;a&gt;replace &amp;ent;&lt;/a&gt;</example>
- </subsection>
-
- <subsection title="Creating XML documents">
- <p>Again, there are a couple of mechanisms for creating XML documents
- in REXML. Adding elements by hand is faster than the convenience
- method, but which you use will probably be a matter of aesthetics.</p>
-
- <example title="Creating elements">el = someelement.add_element "myel"
-# creates an element named "myel", adds it to "someelement", and returns it
-el2 = el.add_element "another", {"id"=&gt;"10"}
-# does the same, but also sets attribute "id" of el2 to "10"
-el3 = Element.new "blah"
-el1.elements &lt;&lt; el3
-el3.attributes["myid"] = "sean"
-# creates el3 "blah", adds it to el1, then sets attribute "myid" to "sean"</example>
-
- <p>If you want to add text to an element, you can do it by either
- creating Text objects and adding them to the element, or by using the
- convenience method <code>text=</code></p>
-
- <example title="Adding text">el1 = Element.new "myelement"
-el1.text = "Hello world!"
-# -&gt; &lt;myelement&gt;Hello world!&lt;/myelement&gt;
-el1.add_text "Hello dolly"
-# -&gt; &lt;myelement&gt;Hello world!Hello dolly&lt;/element&gt;
-el1.add Text.new("Goodbye")
-# -&gt; &lt;myelement&gt;Hello world!Hello dollyGoodbye&lt;/element&gt;
-el1 &lt;&lt; Text.new(" cruel world")
-# -&gt; &lt;myelement&gt;Hello world!Hello dollyGoodbye cruel world&lt;/element&gt;</example>
-
- <p>But note that each of these text objects are still stored as
- separate objects; <code>el1.text</code> will return "Hello world!";
- <code>el1[2]</code> will return a Text object with the contents
- "Goodbye".</p>
-
- <p>Please be aware that all text nodes in REXML are UTF-8 encoded, and
- all of your code must reflect this. You may input and output other
- encodings (UTF-8, UTF-16, ISO-8859-1, and UNILE are all supported,
- input and output), but within your program, you must pass REXML UTF-8
- strings.</p>
-
- <p>I can't emphasize this enough, because people do have problems with
- this. REXML can't possibly alway guess correctly how your text is
- encoded, so it always assumes the text is UTF-8. It also does not warn
- you when you try to add text which isn't properly encoded, for the
- same reason. You must make sure that you are adding UTF-8 text.
- &#160;If you're adding standard 7-bit ASCII, which is most common, you
- don't have to worry. &#160;If you're using ISO-8859-1 text (characters
- above 0x80), you must convert it to UTF-8 before adding it to an
- element. &#160;You can do this with the shard:
- <code>text.unpack("C*").pack("U*")</code>. If you ignore this warning
- and add 8-bit ASCII characters to your documents, your code may
- work... or it may not. &#160;In either case, REXML is not at fault.
- You have been warned.</p>
-
- <p>One last thing: alternate encoding output support only works from
- Document.write() and Document.to_s(). If you want to write out other
- nodes with a particular encoding, you must wrap your output object
- with Output:</p>
-
- <example title="Encoded Output">e = Element.new "&lt;a/&gt;"
-e.text = "f\xfcr" # ISO-8859-1 'ü'
-o = ''
-e.write( Output.new( o, "ISO-8859-1" ) )
-</example>
-
- <p>You can pass Output any of the supported encodings.</p>
-
- <p>If you want to insert an element between two elements, you can use
- either the standard Ruby array notation, or
- <code>Parent.insert_before</code> and
- <code>Parent.insert_after</code>.</p>
-
- <example title="Inserts">doc = Document.new "&lt;a&gt;&lt;one/&gt;&lt;three/&gt;&lt;/a&gt;"
-doc.root[1,0] = Element.new "two"
-# -&gt; &lt;a&gt;&lt;one/&gt;&lt;two/&gt;&lt;three/&gt;&lt;/a&gt;
-three = doc.elements["a/three"]
-doc.root.insert_after three, Element.new "four"
-# -&gt; &lt;a&gt;&lt;one/&gt;&lt;two/&gt;&lt;three/&gt;&lt;four/&gt;&lt;/a&gt;
-# A convenience method allows you to insert before/after an XPath:
-doc.root.insert_after( "//one", Element.new("one-five") )
-# -&gt; &lt;a&gt;&lt;one/&gt;&lt;one-five/&gt;&lt;two/&gt;&lt;three/&gt;&lt;four/&gt;&lt;/a&gt;
-# Another convenience method allows you to insert after/before an element:
-four = doc.elements["//four"]
-four.previous_sibling = Element.new("three-five")
-# -&gt; &lt;a&gt;&lt;one/&gt;&lt;one-five/&gt;&lt;two/&gt;&lt;three/&gt;&lt;three-five/&gt;&lt;four/&gt;&lt;/a&gt;</example>
-
- <p>The <code>raw</code> flag in the <code>Text</code> constructor can
- be used to tell REXML to leave strings which have entities defined for
- them alone.</p>
-
- <example title="Raw text">doc = Document.new( "&lt;?xml version='1.0?&gt;
-&lt;!DOCTYPE foo SYSTEM 'foo.dtd' [
-&lt;!ENTITY % s "Sean"&gt;
-]&gt;
-&lt;a/&gt;"
-t = Text.new( "Sean", false, nil, false )
-doc.root.text = t
-t.to_s # -&gt; &amp;s;
-t = Text.new( "Sean", false, nil, true )
-doc.root.text = t
-t.to_s # -&gt; Sean</example>
-
- <p>Note that, in all cases, the <code>value()</code> method returns
- the text with entities expanded, so the <code>raw</code> flag only
- affects the <code>to_s()</code> method. If the <code>raw</code> is set
- for a text node, then <code>to_s()</code> will not entities will not
- normalize (turn into entities) entity values. You can not create raw
- text nodes that contain illegal XML, so the following will generate a
- parse error:</p>
-
- <example>t = Text.new( "&amp;", false, nil, true )</example>
-
- <p>You can also tell REXML to set the Text children of given elements
- to raw automatically, on parsing or creating:</p>
-
- <example title="Automatic raw text handling">doc = REXML::Document.new( source, { :raw =&gt; %w{ tag1 tag2 tag3 } }</example>
-
- <p>In this example, all tags named "tag1", "tag2", or "tag3" will have
- any Text children set to raw text. If you want to have all of the text
- processed as raw text, pass in the :all tag:</p>
-
- <example title="Raw documents">doc = REXML::Document.new( source, { :raw =&gt; :all })</example>
- </subsection>
-
- <subsection title="Writing a tree">
- <p>There aren't many things that are more simple than writing a REXML
- tree. Simply pass an object that supports <code>&lt;&lt;( String
- )</code> to the <code>write</code> method of any object. In Ruby, both
- IO instances (File) and String instances support &lt;&lt;.</p>
-
- <example>doc.write $stdout
-output = ""
-doc.write output</example>
-
- <p>If you want REXML to pretty-print output, pass <code>write()</code>
- an indent value greater than -1:</p>
-
- <example title="Write with pretty-printing">doc.write( $stdout, 0 )</example>
-
- <p>REXML will not, by default, write out the XML declaration unless
- you specifically ask for them. If a document is read that contains an
- XML declaration, that declaration <emphasis>will</emphasis> be written
- faithfully. The other way you can tell REXML to write the declaration
- is to specifically add the declaration:</p>
-
- <example title="Adding an XML Declaration to a Document">doc = Document.new
-doc.add_element 'foo'
-doc.to_s #-&gt; &lt;foo/&gt;
-doc &lt;&lt; XMLDecl.new
-doc.to_s #-&gt; &lt;?xml version='1.0'?&gt;&lt;foo/&gt;</example>
- </subsection>
-
- <subsection title="Iterating">
- <p>There are four main methods of iterating over children.
- <code>Element.each</code>, which iterates over all the children;
- <code>Element.elements.each</code>, which iterates over just the child
- Elements; <code>Element.next_element</code> and
- <code>Element.previous_element</code>, which can be used to fetch the
- next Element siblings; and <code>Element.next_sibling</code> and
- <code>Eleemnt.previous_sibling</code>, which fetches the next and
- previous siblings, regardless of type.</p>
- </subsection>
-
- <subsection title="Stream Parsing">
- <p>REXML stream parsing requires you to supply a Listener class. When
- REXML encounters events in a document (tag start, text, etc.) it
- notifies your listener class of the event. You can supply any subset
- of the methods, but make sure you implement method_missing if you
- don't implement them all. A StreamListener module has been supplied as
- a template for you to use.</p>
-
- <example title="Stream parsing">list = MyListener.new
-source = File.new "mydoc.xml"
-REXML::Document.parse_stream(source, list)</example>
-
- <p>Stream parsing in REXML is much like SAX, where events are
- generated when the parser encounters them in the process of parsing
- the document. When a tag is encountered, the stream listener's
- <code>tag_start()</code> method is called. When the tag end is
- encountered, <code>tag_end()</code> is called. When text is
- encountered, <code>text()</code> is called, and so on, until the end
- of the stream is reached. One other note: the method
- <code>entity()</code> is called when an <code>&amp;entity;</code> is
- encountered in text, and only then.</p>
-
- <p>Please look at the <link
- href="../doc/classes/REXML/StreamListener.html">StreamListener
- API</link> for more information.<footnote>You must generate the API
- documentation with rdoc or download the API documentation from the
- REXML website for this documentation.</footnote></p>
- </subsection>
-
- <subsection title="Whitespace">
- <p>By default, REXML respects whitespace in your document. In many
- applications, you want the parser to compress whitespace in your
- document. In these cases, you have to tell the parser which elements
- you want to respect whitespace in by passing a context to the
- parser:</p>
-
- <example title="Compressing whitespace">doc = REXML::Document.new( source, { :compress_whitespace =&gt; %w{ tag1 tag2 tag3 } }</example>
-
- <p>Whitespace for tags "tag1", "tag2", and "tag3" will be compressed;
- all other tags will have their whitespace respected. Like :raw, you
- can set :compress_whitespace to :all, and have all elements have their
- whitespace compressed.</p>
-
- <p>You may also use the tag <code>:respect_whitespace</code>, which
- flip-flops the behavior. If you use <code>:respect_whitespace</code>
- for one or more tags, only those elements will have their whitespace
- respected; all other tags will have their whitespace compressed.</p>
- </subsection>
-
- <subsection title="Automatic Entity Processing">
- <p>REXML does some automatic processing of entities for your
- convenience. The processed entities are &amp;, &lt;, &gt;, ", and '.
- If REXML finds any of these characters in Text or Attribute values, it
- automatically turns them into entity references when it writes them
- out. Additionally, when REXML finds any of these entity references in
- a document source, it converts them to their character equivalents.
- All other entity references are left unprocessed. If REXML finds an
- &amp;, &lt;, or &gt; in the document source, it will generate a
- parsing error.</p>
-
- <example title="Entity processing">bad_source = "&lt;a&gt;Cats &amp; dogs&lt;/a&gt;"
-good_source = "&lt;a&gt;Cats &amp;amp; &amp;#100;ogs&lt;/a&gt;"
-doc = REXML::Document.new bad_source
-# Generates a parse error
-doc = REXML::Document.new good_source
-puts doc.root.text
-# -&gt; "Cats &amp; &amp;#100;ogs"
-doc.root.write $stdout
-# -&gt; "&lt;a&gt;Cats &amp;amp; &amp;#100;ogs&lt;/a&gt;"
-doc.root.attributes["m"] = "x'y\"z"
-puts doc.root.attributes["m"]
-# -&gt; "x'y\"z"
-doc.root.write $stdout
-# -&gt; "&lt;a m='x&amp;apos;y&amp;quot;z'&gt;Cats &amp;amp; &amp;#100;ogs&lt;/a&gt;"</example>
- </subsection>
-
- <subsection title="Namespaces">
- <p>Namespaces are fully supported in REXML and within the XPath
- parser. There are a few caveats when using XPath, however:</p>
-
- <list>
- <item>If you don't supply a namespace mapping, the default namespace
- mapping of the context element is used. This has its limitations,
- but is convenient for most purposes.</item>
-
- <item>If you need to supply a namespace mapping, you must use the
- XPath methods <code>each</code>, <code>first</code>, and
- <code>match</code> and pass them the mapping.</item>
- </list>
-
- <example title="Using namespaces">source = "&lt;a xmlns:x='foo' xmlns:y='bar'&gt;&lt;x:b id='1'/&gt;&lt;y:b id='2'/&gt;&lt;/a&gt;"
-doc = Document.new source
-doc.elements["/a/x:b"].attributes["id"] # -&gt; '1'
-XPath.first(doc, "/a/m:b", {"m"=&gt;"bar"}).attributes["id"] # -&gt; '2'
-doc.elements["//x:b"].prefix # -&gt; 'x'
-doc.elements["//x:b"].namespace # -&gt; 'foo'
-XPath.first(doc, "//m:b", {"m"=&gt;"bar"}).prefix # -&gt; 'y'</example>
- </subsection>
-
- <subsection title="Pull parsing">
- <p>The pull parser API is not yet stable. When it settles down, I'll
- fill in this section. For now, you'll have to bite the bullet and read
- the <link
- href="http://www.germane-software.com/software/rexml_doc/classes/REXML/PullParser.html">PullParser</link>
- API docs. Ignore the PullListener class; it is a private helper
- class.</p>
- </subsection>
-
- <subsection title="SAX2 Stream Parsing">
- <p>The original REXML stream parsing API is very minimal. This also
- means that it is fairly fast. For a more complex, more "standard" API,
- REXML also includes a streaming parser with a SAX2+ API. This API
- differs from SAX2 in a couple of ways, such as having more filters and
- multiple notification mechanisms, but the core API is SAX2.</p>
-
- <p>The two classes in the SAX2 API are <link
- href="http://www.germane-software.com/software/rexml_doc/classes/REXML/SAX2Parser.html"><code>SAX2Parser</code></link>
- and <link
- href="http://www.germane-software.com/software/rexml_doc/classes/REXML/SAX2Listener.html"><code>SAX2Listener</code></link>.
- You can use the parser in one of five ways, depending on your needs.
- Three of the ways are useful if you are filtering for a small number
- of events in the document, such as just printing out the names of all
- of the elements in a document, or getting all of the text in a
- document. The other two ways are for more complex processing, where
- you want to be notified of multiple events. The first three involve
- Procs, and the last two involve listeners. The listener mechanisms are
- very similar to the original REXML streaming API, with the addition of
- filtering options, and are faster than the proc mechanisms.</p>
-
- <p>An example is worth a thousand words, so we'll just take a look at
- a small example of each of the mechanisms. The first example involves
- printing out only the text content of a document.</p>
-
- <example title="Filtering for Events with Procs">require 'rexml/sax2parser'
-parser = REXML::SAX2Parser.new( File.new( 'documentation.xml' ) )
-parser.listen( :characters ) {|text| puts text }
-parser.parse</example>
-
- <p>In this example, we tell the parser to call our block for every
- <code>characters</code> event. "characters" is what SAX2 calls Text
- nodes. The event is identified by the symbol <code>:characters</code>.
- There are a number of these events, including
- <code>:element_start</code>, <code>:end_prefix_mapping</code>, and so
- on; the events are named after the methods in the
- <code>SAX2Listener</code> API, so refer to that document for a
- complete list.</p>
-
- <p>You can additionally filter for particular elements by passing an
- array of tag names to the <code>listen</code> method. In further
- examples, we will not include the <code>require</code> or parser
- construction lines, as they are the same for all of these
- examples.</p>
-
- <example title="Filtering for Events on Particular Elements with Procs">parser.listen( :characters, %w{ changelog todo } ) {|text| puts text }
-parser.parse</example>
-
- <p>In this example, only the text content of changelog and todo
- elements will be printed. The array of tag names can also contain
- regular expressions which the element names will be matched
- against.</p>
-
- <p>Finally, as a shortcut, if you do not pass a symbol to the listen
- method, it will default to <code>:element_start</code></p>
-
- <example title="Default Events">parser.listen( %w{ item }) do |uri,localname,qname,attributes|
- puts attributes['version']
-end
-parser.parse</example>
-
- <p>This example prints the "version" attribute of all "item" elements
- in the document. Notice that the number of arguments passed to the
- block is larger than for <code>:text</code>; again, check the
- SAX2Listener API for a list of what arguments are passed the blocks
- for a given event.</p>
-
- <p>The last two mechanisms for parsing use the SAX2Listener API. Like
- StreamListener, SAX2Listener is a <code>module</code>, so you can
- <code>include</code> it in your class to give you an adapter. To use
- the listener model, create a class that implements some of the
- SAX2Listener methods, or all of them if you don't include the
- SAX2Listener model. Add them to a parser as you would blocks, and when
- the parser is run, the methods will be called when events occur.
- Listeners do not use event symbols, but they can filter on element
- names.</p>
-
- <example title="Filtering for Events with Listeners">listener1 = MySAX2Listener.new
-listener2 = MySAX2Listener.new
-parser.listen( listener1 )
-parser.listen( %{ changelog, todo, credits }, listener2 )
-parser.parse</example>
-
- <p>In the previous example, <code>listener1</code> will be notified of
- all events that occur, and <code>listener2</code> will only be
- notified of events that occur in <code>changelog</code>,
- <code>todo</code>, and <code>credits</code> elements. We also see that
- multiple listeners can be added to the same parser; multiple blocks
- can also be added, and listeners and blocks can be mixed together.</p>
-
- <p>There is, as yet, no mechanism for recursion. Two upcoming features
- of the SAX2 API will be the ability to filter based on an XPath, and
- the ability to specify filtering on an elemnt and all of its
- descendants.</p>
-
- <p><em>WARNING:</em> The SAX2 API for dealing with doctype (DTD)
- events almost <em>certainly</em> will change.</p>
- </subsection>
-
- <subsection title="Convenience methods">
- <p>Michael Neumann contributed some convenience functions for nodes,
- and they are general enough that I've included. Michael's use-case
- examples follow: <example title="Node convenience functions">#
- Starting with +root_node+, we recursively look for a node with the
- given # +tag+, the given +attributes+ (a Hash) and whoose text equals
- or matches the # +text+ string or regular expression. # # To find the
- following node: # # &lt;td class='abc'&gt;text&lt;/td&gt; # # We use:
- # # find_node(root, 'td', {'class' =&gt; 'abc'}, "text") # # Returns
- +nil+ if no matching node was found. def find_node(root_node, tag,
- attributes, text) root_node.find_first_recursive {|node| node.name ==
- tag and attributes.all? {|attr, val| node.attributes[attr] == val} and
- text === node.text } end # # Extract specific columns (specified by
- the position of it's corresponding # header column) from a table. # #
- Given the following table: # # &lt;table&gt; # &lt;tr&gt; #
- &lt;td&gt;A&lt;/td&gt; # &lt;td&gt;B&lt;/td&gt; #
- &lt;td&gt;C&lt;/td&gt; # &lt;/tr&gt; # &lt;tr&gt; #
- &lt;td&gt;A.1&lt;/td&gt; # &lt;td&gt;B.1&lt;/td&gt; #
- &lt;td&gt;C.1&lt;/td&gt; # &lt;/tr&gt; # &lt;tr&gt; #
- &lt;td&gt;A.2&lt;/td&gt; # &lt;td&gt;B.2&lt;/td&gt; #
- &lt;td&gt;C.2&lt;/td&gt; # &lt;/tr&gt; # &lt;/table&gt; # # To extract
- the first (A) and last (C) column: # # extract_from_table(root_node,
- ["A", "C"]) # # And you get this as result: # # [ # ["A.1", "C.1"], #
- ["A.2", "C.2"] # ] # def extract_from_table(root_node, headers) #
- extract and collect all header nodes header_nodes = headers.collect {
- |header| find_node(root_node, 'td', {}, header) } raise "some headers
- not found" if header_nodes.compact.size &lt; headers.size # assert
- that all headers have the same parent 'header_row', which is the row #
- in which the header_nodes are contained. 'table' is the surrounding
- table tag. header_row = header_nodes.first.parent table =
- header_row.parent raise "different parents" unless header_nodes.all?
- {|n| n.parent == header_row} # we now iterate over all rows in the
- table that follows the header_row. # for each row we collect the
- elements at the same positions as the header_nodes. # this is what we
- finally return from the method. (header_row.index_in_parent+1 ..
- table.elements.size).collect do |inx| row = table.elements[inx]
- header_nodes.collect { |n| row.elements[ n.index_in_parent ].text }
- end end</example></p>
- </subsection>
-
- <subsection title="Conclusion">
- <p>This isn't everything there is to REXML, but it should be enough to
- get started. Check the <link href="../doc/index.html">API
- documentation</link><footnote>You must generate the API documentation
- with rdoc or download the API documentation from the REXML website for
- this documentation.</footnote> for particulars and more examples.
- There are plenty of unit tests in the <code>test/</code> directory,
- and these are great sources of working examples.</p>
- </subsection>
- </general>
- </overview>
-
- <credits>
- <p>Among the people who've contributed to this document are:</p>
-
- <list>
- <item><link href="mailto:deicher@sandia.gov">Eichert, Diana</link> (bug
- fix)</item>
- </list>
- </credits>
-</documentation> \ No newline at end of file
diff --git a/test/rexml/data/underscore.xml b/test/rexml/data/underscore.xml
deleted file mode 100644
index 111446f4bd..0000000000
--- a/test/rexml/data/underscore.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" ?>
-<root a="1" _a="2">
- <b>1</b>
- <_b>2</_b>
-</root>
-
diff --git a/test/rexml/data/utf16.xml b/test/rexml/data/utf16.xml
deleted file mode 100644
index f7e5e90d0c..0000000000
--- a/test/rexml/data/utf16.xml
+++ /dev/null
Binary files differ
diff --git a/test/rexml/data/web.xml b/test/rexml/data/web.xml
deleted file mode 100644
index 972cf5d272..0000000000
--- a/test/rexml/data/web.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<web-app>
- <servlet>
- <servlet-name>snoop</servlet-name>
- <servlet-class>SnoopServlet</servlet-class>
- </servlet>
- <servlet>
- <servlet-name>file</servlet-name>
- <servlet-class>ViewFile</servlet-class>
- <init-param>
- <param-name>initial</param-name>
- <param-value>
- 1000
- </param-value>
- <description>
- The initial value for the counter <!-- optional -->
- </description>
- </init-param>
- </servlet>
- <servlet-mapping>
- <servlet-name>
- mv
- </servlet-name>
- <url-pattern>
- *.wm
- </url-pattern>
- </servlet-mapping>
-
- <distributed/>
-
- <security-role>
- <role-name>
- manager
- </role-name>
- <role-name>
- director
- </role-name>
- <role-name>
- president
- </role-name>
- </security-role>
-</web-app>
diff --git a/test/rexml/data/web2.xml b/test/rexml/data/web2.xml
deleted file mode 100644
index 7d479d37e9..0000000000
--- a/test/rexml/data/web2.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<root>
- <b>
- <d />
- </b>
- <c />
-</root>
diff --git a/test/rexml/data/working.rss b/test/rexml/data/working.rss
deleted file mode 100644
index b38c45f5d8..0000000000
--- a/test/rexml/data/working.rss
+++ /dev/null
@@ -1,202 +0,0 @@
-<?xml version="1.0"?>
-
-<rss version="0.92">
-<channel>
- <title>Paul Duncan</title>
- <link>http://www.paulduncan.org/</link>
- <description>Paul Duncan's personal blog.</description>
-</channel>
-
- <item>
- <title>Fun With Tense
-</title>
- <date>Wed Sep 3 19:37:18 2003</date>
- <creator>paul@paulduncan.org</creator>
- <link>http://www.paulduncan.org/?id=23</link>
- <description>
-&lt;pre&gt;
-&amp;lt;richlowe&amp;gt; blah.
-&amp;lt;richlowe&amp;gt; that's what I say.
-&amp;lt;pabs&amp;gt; if i say it too then what happens?
-&amp;lt;richlowe&amp;gt; then &quot;that's what we say&quot;
-&amp;lt;richlowe&amp;gt; duh.
-&amp;lt;pabs&amp;gt; what if i say it, then retract it?
-&amp;lt;richlowe&amp;gt; Did they teach you nothing in school!
-&amp;lt;richlowe&amp;gt; &quot;that's what I say, and he said&quot;
-&amp;lt;pabs&amp;gt; :(
-&amp;lt;pabs&amp;gt; okay what if i say it, retract it, but then plan on saying it
- again at some point in the indeterminite future?
-&amp;lt;richlowe&amp;gt; &quot;that's what I say, and he has said, and will possibly say
- again&quot;?
-&amp;lt;pabs&amp;gt; see now that's not concise at all
-&lt;/pre&gt;
-
- </description>
- </item>
-
- <item>
- <title>We'll Miss You, Michael
-</title>
- <date>Mon Aug 25 09:52:41 2003</date>
- <creator>paul@paulduncan.org</creator>
- <link>http://www.paulduncan.org/?id=22</link>
- <description>
-&lt;p&gt;
-Perhaps &lt;a href='http://www.dash-dash.org/pix/death.jpg'&gt;the image&lt;/a&gt;
-on &lt;a href='http://www.dash-dash.org/'&gt;his site&lt;/a&gt; was a bit more
-fitting than we realized. I'm frustrated that nothing and noone around
-him could help ease the pain that he was going through. We can take
-comfort in knowing that he felt the decision he made was best for him.
-We'll miss you, Michael.
-&lt;/p&gt;
-
- </description>
- </item>
-
- <item>
- <title>Horis, Isis, Osiris, Oh My!
-</title>
- <date>Fri Aug 22 22:39:23 2003</date>
- <creator>paul@paulduncan.org</creator>
- <link>http://www.paulduncan.org/?id=21</link>
- <description>
-&lt;p&gt;
-I started reading one of the several mythology books I checked out
-earlier this week (as part of a personal research project, the results
-of which will be available here eventually). I've only made it through
-about 60 pages of Egyptian mythology so far, but it's interesting stuff.
-One thing that's impressive to me is how the sexes appear to be on much
-more equal footing (as compared to the Judeo/Christian mythology we've
-been innundated with for most of our lives). For example, Isis revives
-her husband Osiris by collecting his body parts, which are scattered
-throughout Egypt. She also saves her son Horus from death and nurtures
-him until he can fend for himself. Really interesting stuff. Anyway,
-I'll have more about the project as I get farther along.
-&lt;/p&gt;
-
- </description>
- </item>
-
- <item>
- <title>Nature Sucks
-</title>
- <date>Fri Aug 22 08:33:41 2003</date>
- <creator>paul@paulduncan.org</creator>
- <link>http://www.paulduncan.org/?id=20</link>
- <description>
-&lt;p&gt;
-&lt;a href='http://www.linuxbrit.co.uk/'&gt;Tom&lt;/a&gt; has been having a rough
-couple of weeks. Apparently he's got &lt;a
-href='http://www.ninds.nih.gov/health_and_medical/disorders/bells_doc.htm'&gt;Bell's
-Palsy&lt;/a&gt; (link from ljlane), which, while treatable and rarely
-permanent, still leaves his face partially paralyzed. If you have a few
-minutes, you might consider sending him an &lt;abbr title='Electronic
-Card'&gt;E-Card&lt;/abbr&gt; or an &lt;a
-href='mailto:dr_spock@linuxbrit.co.uk'&gt;email&lt;/a&gt;.
-&lt;/p&gt;
-
- </description>
- </item>
-
- <item>
- <title>Or Maybe He Does
-</title>
- <date>Thu Aug 21 23:45:40 2003</date>
- <creator>paul@paulduncan.org</creator>
- <link>http://www.paulduncan.org/?id=19</link>
- <description>
-&lt;p&gt;
-Okay, apparently Ed &lt;em&gt;does&lt;/em&gt; read this page. :-D
-&lt;/p&gt;
-
- </description>
- </item>
-
- <item>
- <title>Ed Got Married!!
-</title>
- <date>Thu Aug 21 15:52:34 2003</date>
- <creator>paul@paulduncan.org</creator>
- <link>http://www.paulduncan.org/?id=18</link>
- <description>
-&lt;p&gt;
-Ed got married in the Bahamas! Here's a picture from the honeymoon:
-&lt;/p&gt;
-
-&lt;img src='/files/ed_dolphin.jpg' width='252' height='288'
- title='Ed on his honeymoon!' alt='Ed on his honeymoon!' /&gt;
-
-&lt;p&gt;
-(Fortunately he doesn't read this site).
-&lt;/p&gt;
-
-&lt;p&gt;
-One other thing. I weigh 186&lt;abbr title='Pounds'&gt;lbs&lt;/abbr&gt; now.
-The &lt;a href='http://www.pablotron.org/weight/'&gt;weight page&lt;/a&gt; has been
-updated.
-&lt;/p&gt;
-
- </description>
- </item>
-
- <item>
- <title>Gratuitous Douglas Adams Reference, #32427!
-</title>
- <date>Tue Aug 19 08:25:42 2003</date>
- <creator>paul@paulduncan.org</creator>
- <link>http://www.paulduncan.org/?id=17</link>
- <description>
-&lt;p&gt;
-Just saw this &lt;acronym title='Uniform Resource Locator'&gt;URL&lt;/acronym&gt;
-on &lt;a href='http://www.diveintomark.org/'&gt;Dive Into
-Mark&lt;/a&gt;:
-&lt;/p&gt;
-
-&lt;p&gt;
-&lt;a
-href='http://www.google.com/search?q=answer+to+life+the+universe+and+everything'&gt;http://www.google.com/search?q=answer+to+life+the+universe+and+everything&lt;/a&gt;
-&lt;/p&gt;
-
-&lt;p&gt;
-&lt;a href='http://www.bbc.co.uk/h2g2/guide/'&gt;&lt;acronym title='Hitchhikers
-Guide to the Galaxy'&gt;H2G2&lt;/acronym&gt;&lt;/a&gt; references never get old for me.
-&lt;/p&gt;
-
- </description>
- </item>
-
- <item>
- <title>Weekend Update, sans Norm McDonald
-</title>
- <date>Tue Aug 19 08:18:32 2003</date>
- <creator>paul@paulduncan.org</creator>
- <link>http://www.paulduncan.org/?id=16</link>
- <description>
-&lt;p&gt;
-What a nutty weekend. A friend of mine went to the &lt;acronym
-title='Emergency Room'&gt;ER&lt;/acronym&gt; on Friday night, so I spent 4 hours
-down there. It's really frustrating to see that many sick and injured
-people in once place, and not really be able to do anything about it.
-Also, for that much chaos, both the atmosphere and the staff are
-disturbingly calm.
-&lt;/p&gt;
-
-&lt;p&gt;
-I finally got &lt;a href='http://www.raggle.org/'&gt;Raggle&lt;/a&gt; to a point
-worthy of a new release. I'm not going to blather on about the new
-stuff; if you're interested you can &lt;a
-href='http://www.raggle.org/'&gt;check it out&lt;/a&gt; on your own.
-&lt;/p&gt;
-
-&lt;p&gt;
-&lt;a href='http://www.pablotron.org/weight/'&gt;The war against obesity&lt;/a&gt;
-continues! I'm down to 188 pounds now, a total of 75 pounds lost since
-the beginning of March. I've been having trouble losing these last 10
-pounds, so this week is officially &quot;Go to the Gym Every Night or Else&quot;
-week. 2 days down, 5 to go.
-&lt;/p&gt;
-
- </description>
- </item>
-
-</rss>
diff --git a/test/rexml/data/xmlfile-bug.xml b/test/rexml/data/xmlfile-bug.xml
deleted file mode 100644
index d4396682f7..0000000000
--- a/test/rexml/data/xmlfile-bug.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<intranet>
-<position><aktuell datum="01-10-11">Technik</aktuell></position>
-<hauptspalte>
-<headline>Technik</headline>
-Die Technik ist das Rckgrat der meisten Geschftsprozesse bei Home of the Brave. Deshalb sollen hier alle relevanten technischen Ablufe, Daten und Einrichtungen beschrieben werden, damit jeder im Bedarfsfall die ntigen Informationen, Anweisungen und Verhaltensempfehlungen nachlesen und/oder abrufen kann.
-</hauptspalte>
-<nebenspalte>
- <link ziel="Flash/">Flash</link><umbruch/>
- Ntzliches von Flashern fr Flasher.<umbruch/>
- <link neu="ja" ziel="Cvs/">CVS-FAQ</link><umbruch/>
- FAQ zur Benutzung von CVS bei HOB
-</nebenspalte>
-</intranet>
-
diff --git a/test/rexml/data/xp.tst b/test/rexml/data/xp.tst
deleted file mode 100644
index 6551372575..0000000000
--- a/test/rexml/data/xp.tst
+++ /dev/null
@@ -1,27 +0,0 @@
-/
-/rss
-//rss
-/rss/channel
-//link
-//image/*
-//link[2]
-//link[last()]
-rss/channel/link[last()]
-rss/channel/item/link[last()]
-rss/channel/item/link[1]
-rss/channel/item[@x='1']
-rss/channel/item[@x]
-//item[@x]
-//item[normalize-space(@name)='x']
-//*[count(title)=1]
-//*[name()='link']
-//*[starts-with(name(),'li')]
-//*[contains(name(),'y')]
-//*[string-length(name()) = 4]
-//copyright | //title
-/child::rss
-/descendant::*
-//language/parent::*
-/rss/channel/ancestor::*
-//item[position() mod 2 = 0 ]
-//item/ancestor::* \ No newline at end of file
diff --git a/test/rexml/data/yahoo.xml b/test/rexml/data/yahoo.xml
deleted file mode 100644
index b63a9440bc..0000000000
--- a/test/rexml/data/yahoo.xml
+++ /dev/null
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<rss version="2.0">
-<channel>
-<title><![CDATA[Yahoo! News Search Results for market]]></title>
-<link>http://news.search.yahoo.com/search/news?p=market&amp;ei=UTF-8</link>
-<description><![CDATA[Yahoo! News Search Results for market]]></description>
-<language>en-us</language>
-<copyright>Copyright (c) 2004 Yahoo! Inc. All rights reserved.</copyright>
-<lastBuildDate>Sun, 03 Sep 2006 16:34:54 GMT</lastBuildDate>
-<ttl>5</ttl>
-<image>
-<title>Yahoo! News</title>
-<width>142</width>
-<height>18</height>
-<link>http://news.search.yahoo.com/news</link>
-<url>http://us.i1.yimg.com/us.yimg.com/i/us/nws/th/main_142.gif</url>
-</image>
-<incremental xmlns="http://purl.org/syndication/history/1.0">false</incremental><item>
-<title><![CDATA[Toyota increases share in US auto market (Manila Bulletin)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=13ck33lrk/*http%3A//www.mb.com.ph/archive_pages.php?url=http://www.mb.com.ph/issues/2006/09/04/BSNS2006090473427.html</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=13ck33lrk/*http%3A//www.mb.com.ph/archive_pages.php?url=http://www.mb.com.ph/issues/2006/09/04/BSNS2006090473427.html</guid>
-<pubDate>Sun, 03 Sep 2006 16:21:30 GMT</pubDate>
-<description><![CDATA[DETROIT (AP) — With a model lineup that consumers love, Toyota Motor Corp. continued to take market share from other automakers last month, posting an industry-best 17 percent increase in sales.]]></description>
-</item><item>
-<title><![CDATA[ANALYSIS - North Korea finds market for missiles shrinking (Reuters via Yahoo! Asia News)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=11ibfq78e/*http%3A//asia.news.yahoo.com/060903/3/2pd1j.html</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=11ibfq78e/*http%3A//asia.news.yahoo.com/060903/3/2pd1j.html</guid>
-<pubDate>Sun, 03 Sep 2006 08:37:33 GMT</pubDate>
-<description><![CDATA[ SEOUL (Reuters) - The missile market is not what it used to be for North Korea, with fewer buyers for a key export product and a loss in prestige when its top-end rocket fizzled after a short test flight, U.S. officials and experts said.]]></description>
-</item><item>
-<title><![CDATA[Broward labor market's a solid performer (Miami Herald)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=13671c2t8/*http%3A//www.miami.com/mld/miamiherald/business/15427113.htm?source=rss&amp;channel=miamiherald_business</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=13671c2t8/*http%3A//www.miami.com/mld/miamiherald/business/15427113.htm?source=rss&amp;channel=miamiherald_business</guid>
-<pubDate>Sun, 03 Sep 2006 07:39:53 GMT</pubDate>
-<description><![CDATA[In looking at South Florida's labor market, it's a tale of two cities, with Fort Lauderdale coming out on top, by far, according to an annual Labor Day report by Florida International University's Bruce Nissen.]]></description>
-</item><item>
-<title><![CDATA[NID to help Jharkhand e-market crafts (Yahoo! India News)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=11hg1j19f/*http%3A//in.news.yahoo.com/060903/43/6780a.html</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=11hg1j19f/*http%3A//in.news.yahoo.com/060903/43/6780a.html</guid>
-<pubDate>Sun, 03 Sep 2006 10:02:54 GMT</pubDate>
-<description><![CDATA[Ranchi, Sep 3 (IANS) Jharkhand will e-market its indigenous products with the help of National Institute of Design (NID), Ahmedabad.]]></description>
-</item><item>
-<title><![CDATA[Reinsurance market goes high-tech to predict disasters (The Herald-Tribune)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12j43rdgp/*http%3A//www.heraldtribune.com/apps/pbcs.dll/article?AID=/20060903/NEWS/609030458</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12j43rdgp/*http%3A//www.heraldtribune.com/apps/pbcs.dll/article?AID=/20060903/NEWS/609030458</guid>
-<pubDate>Sun, 03 Sep 2006 10:34:36 GMT</pubDate>
-<description><![CDATA[Hurricane outlooks are closely watched at such places as the Lloyd's of London insurance market building.]]></description>
-</item><item>
-<title><![CDATA[Government warned against going into property market (Sunday Business Post)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12pru5k6v/*http%3A//www.sbpost.ie/breakingnews/breaking_story.asp?j=4126020&amp;p=4yz6x35&amp;n=4126112&amp;x=</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12pru5k6v/*http%3A//www.sbpost.ie/breakingnews/breaking_story.asp?j=4126020&amp;p=4yz6x35&amp;n=4126112&amp;x=</guid>
-<pubDate>Sun, 03 Sep 2006 09:31:34 GMT</pubDate>
-<description><![CDATA[A new report is expected to warn the Government not to intervene in the property market. The report by IIB Bank, which is due to be published tomorrow, will argue that it doesn't make sense for the Government to try and stop speculators buying new homes for profit.]]></description>
-</item><item>
-<title><![CDATA[Farmers Market gets shoulder-to-shoulder crowds on Saturdays (Great Falls Tribune)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12pfls0n1/*http%3A//www.greatfallstribune.com/apps/pbcs.dll/article?AID=/20060903/NEWS01/609030306</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12pfls0n1/*http%3A//www.greatfallstribune.com/apps/pbcs.dll/article?AID=/20060903/NEWS01/609030306</guid>
-<pubDate>Sun, 03 Sep 2006 11:12:36 GMT</pubDate>
-<description><![CDATA[The produce is bountiful at the Great Falls Farmers Market and so are the customers, vendors say. "Business is booming," said Heather Sands of Little Creek Nursery in Fort Shaw.]]></description>
-</item><item>
-<title><![CDATA[City Hall takes Plan B for SF market rehab (Sun Star)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=138rfnhvi/*http%3A//www.sunstar.com.ph/static/pam/2006/09/03/news/city.hall.takes.plan.b.for.sf.market.rehab.html</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=138rfnhvi/*http%3A//www.sunstar.com.ph/static/pam/2006/09/03/news/city.hall.takes.plan.b.for.sf.market.rehab.html</guid>
-<pubDate>Sun, 03 Sep 2006 08:18:46 GMT</pubDate>
-<description><![CDATA[CITY OF SAN FERNANDO -- The City Government here shelved an earlier proposal of constructing the old public market through a bond flotation scheme and instead took Plan B, which is the rehabilitation of the market's wet section.]]></description>
-</item><item>
-<title><![CDATA[Market watch (AG Weekly)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12ahobgi6/*http%3A//www.agweekly.com/articles/2006/09/02/news/markets/markets01.txt</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=12ahobgi6/*http%3A//www.agweekly.com/articles/2006/09/02/news/markets/markets01.txt</guid>
-<pubDate>Sun, 03 Sep 2006 04:20:37 GMT</pubDate>
-<description><![CDATA[The Market Sentiment Index can be an invaluable tool in forecasting important price tops and bottoms in the market. The index was developed by Market Vane, a California-based research company, in the 1960s and is still published by a variety of reliable sources.]]></description>
-</item><item>
-<title><![CDATA[Catholic War Vets Ladies Club sets flea market (Times Leader)]]></title>
-<link>http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=1383flil1/*http%3A//www.timesleader.com/mld/timesleader/living/15431391.htm?source=rss&amp;channel=timesleader_living</link>
-<guid isPermaLink="false">http://us.rd.yahoo.com/dailynews/rss/search/market/SIG=1383flil1/*http%3A//www.timesleader.com/mld/timesleader/living/15431391.htm?source=rss&amp;channel=timesleader_living</guid>
-<pubDate>Sun, 03 Sep 2006 07:07:50 GMT</pubDate>
-<description><![CDATA[Catholic War Veterans, Post 274, Ashley, Ladies Club will hold a flea market from 7 a.m. until 2 p.m. Sept. 10, Sept. 24 and Oct. 1 on the grounds of the Catholic War Veterans. The event will take place rain or shine. For more information, vendor information or to reserve a table, call Marsha Panetta at 823-6232 or Dorothy Liberaski at 474-9969. From left, members of the planning committee are ]]></description>
-</item></channel>
-</rss>
-<!-- s8.news.dcn.yahoo.com uncompressed/chunked Sun Sep 3 09:34:54 PDT 2006 -->
diff --git a/test/rexml/formatter/test_default.rb b/test/rexml/formatter/test_default.rb
deleted file mode 100644
index b5b131724b..0000000000
--- a/test/rexml/formatter/test_default.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require_relative "../rexml_test_utils"
-
-module REXMLTests
- class DefaultFormatterTest < Test::Unit::TestCase
- def format(node)
- formatter = REXML::Formatters::Default.new
- output = ""
- formatter.write(node, output)
- output
- end
-
- class InstructionTest < self
- def test_content_nil
- instruction = REXML::Instruction.new("target")
- assert_equal("<?target?>", format(instruction))
- end
- end
- end
-end
diff --git a/test/rexml/functions/test_base.rb b/test/rexml/functions/test_base.rb
deleted file mode 100644
index 74dc1a31de..0000000000
--- a/test/rexml/functions/test_base.rb
+++ /dev/null
@@ -1,261 +0,0 @@
-# frozen_string_literal: false
-require "test/unit/testcase"
-
-require "rexml/document"
-
-# TODO: Split me
-module REXMLTests
- class FunctionsTester < Test::Unit::TestCase
- include REXML
-
- def setup
- super
- REXML::Functions.context = nil
- end
-
- def test_functions
- # trivial text() test
- # confuse-a-function
- source = "<a>more <b id='1'/><b id='2'>dumb</b><b id='3'/><c/> text</a>"
- doc = Document.new source
- res = ""
- XPath::each(doc.root, "text()") {|val| res << val.to_s}
- assert_equal "more text", res
-
- res = XPath::first(doc.root, "b[last()]")
- assert_equal '3', res.attributes['id']
- res = XPath::first(doc.root, "b[position()=2]")
- assert_equal '2', res.attributes['id']
- res = XPath::first(doc.root, "*[name()='c']")
- assert_equal "c", res.name
- end
-
- # Contributed by Mike Stok
- def test_starts_with
- source = <<-EOF
- <foo>
- <a href="mailto:a@b.c">a@b.c</a>
- <a href="http://www.foo.com">http://www.foo.com</a>
- </foo>
- EOF
- doc = Document.new source
- mailtos = doc.elements.to_a("//a[starts-with(@href, 'mailto:')]")
- assert_equal 1, mailtos.size
- assert_equal "mailto:a@b.c", mailtos[0].attributes['href']
-
- ailtos = doc.elements.to_a("//a[starts-with(@href, 'ailto:')]")
- assert_equal 0, ailtos.size
- end
-
- def test_string_length
- doc = Document.new <<-EOF
- <AAA>
- <Q/>
- <SSSS/>
- <BB/>
- <CCC/>
- <DDDDDDDD/>
- <EEEE/>
- </AAA>
- EOF
- assert doc, "create doc"
-
- set = doc.elements.to_a("//*[string-length(name()) = 3]")
- assert_equal 2, set.size, "nodes with names length = 3"
-
- set = doc.elements.to_a("//*[string-length(name()) < 3]")
- assert_equal 2, set.size, "nodes with names length < 3"
-
- set = doc.elements.to_a("//*[string-length(name()) > 3]")
- assert_equal 3, set.size, "nodes with names length > 3"
- end
-
- # Test provided by Mike Stok
- def test_contains
- source = <<-EOF
- <foo>
- <a href="mailto:a@b.c">a@b.c</a>
- <a href="http://www.foo.com">http://www.foo.com</a>
- </foo>
- EOF
- doc = Document.new source
-
- [['o', 2], ['foo', 1], ['bar', 0]].each { |test|
- search, expected = test
- set = doc.elements.to_a("//a[contains(@href, '#{search}')]")
- assert_equal expected, set.size
- }
- end
-
- # Mike Stok and Sean Russell
- def test_substring
- # examples from http://www.w3.org/TR/xpath#function-substring
- doc = Document.new('<test string="12345" />')
-
- #puts XPath.first(d, 'node()[0 + 1]')
- #d = Document.new("<a b='1'/>")
- #puts XPath.first(d, 'a[0 mod 0]')
- [ [1.5, 2.6, '234'],
- [0, 3, '12'],
- [0, '0 div 0', ''],
- [1, '0 div 0', ''],
- ['-42', '1 div 0', '12345'],
- ['-1 div 0', '1 div 0', '']
- ].each { |start, length, expected|
- set = doc.elements.to_a("//test[substring(@string, #{start}, #{length}) = '#{expected}']")
- assert_equal 1, set.size, "#{start}, #{length}, '#{expected}'"
- }
- end
-
- def test_substring_angrez
- testString = REXML::Functions::substring_after("helloworld","hello")
- assert_equal( 'world', testString )
- end
-
- def test_translate
- source = <<-EOF
- <doc>
- <case name='w3c one' result='BAr' /> <!-- w3c -->
- <case name='w3c two' result='AAA' /> <!-- w3c -->
- <case name='alchemy' result="gold" /> <!-- mike -->
- <case name='vbxml one' result='A Space Odyssey' />
- <case name='vbxml two' result='AbCdEf' />
- </doc>
- EOF
-
- doc = Document.new(source)
-
- [ ['bar', 'abc', 'ABC', 'w3c one'],
- ['--aaa--','abc-','ABC', 'w3c two'],
- ['lead', 'dear language', 'doll groover', 'alchemy'],
- ['A Space Odissei', 'i', 'y', 'vbxml one'],
- ['abcdefg', 'aceg', 'ACE', 'vbxml two'],
- ].each { |arg1, arg2, arg3, name|
- translate = "translate('#{arg1}', '#{arg2}', '#{arg3}')"
- set = doc.elements.to_a("//case[@result = #{translate}]")
- assert_equal 1, set.size, translate
- assert_equal name, set[0].attributes['name']
- }
- end
-
- def test_name
- d = REXML::Document.new("<a xmlns:x='foo'><b/><x:b/></a>")
- assert_equal 1, d.root.elements.to_a('*[name() = "b"]').size
- assert_equal 1, d.elements.to_a('//*[name() = "x:b"]').size
- end
-
- def test_local_name
- d = REXML::Document.new("<a xmlns:x='foo'><b/><x:b/></a>")
- assert_equal 2, d.root.elements.to_a('*[local_name() = "b"]').size
- assert_equal 2, d.elements.to_a('//*[local_name() = "b"]').size
- end
-
- def test_substring2
- doc = Document.new('<test string="12345" />')
- assert_equal(1,doc.elements.to_a("//test[substring(@string,2)='2345']").size)
- end
-
- # Submitted by Kouhei
- def test_floor_ceiling_round
- source = "<a><b id='1'/><b id='2'/><b id='3'/></a>"
- doc = REXML::Document.new(source)
-
- id_1 = doc.elements["/a/b[@id='1']"]
- id_2 = doc.elements["/a/b[@id='2']"]
- id_3 = doc.elements["/a/b[@id='3']"]
-
- good = {
- "floor" => [[], [id_1], [id_2], [id_3]],
- "ceiling" => [[id_1], [id_2], [id_3], []],
- "round" => [[id_1], [id_2], [id_3], []]
- }
- good.each do |key, value|
- (0..3).each do |i|
- xpath = "//b[number(@id) = #{key}(#{i+0.5})]"
- assert_equal(value[i], REXML::XPath.match(doc, xpath))
- end
- end
-
- good["round"] = [[], [id_1], [id_2], [id_3]]
- good.each do |key, value|
- (0..3).each do |i|
- xpath = "//b[number(@id) = #{key}(#{i+0.4})]"
- assert_equal(value[i], REXML::XPath.match(doc, xpath))
- end
- end
- end
-
- # Submitted by Kou
- def test_lang
- d = Document.new(<<-XML)
- <a xml:lang="en">
- <b xml:lang="ja">
- <c xml:lang="fr"/>
- <d/>
- <e xml:lang="ja-JP"/>
- <f xml:lang="en-US"/>
- </b>
- </a>
- XML
-
- assert_equal(1, d.elements.to_a("//*[lang('fr')]").size)
- assert_equal(3, d.elements.to_a("//*[lang('ja')]").size)
- assert_equal(2, d.elements.to_a("//*[lang('en')]").size)
- assert_equal(1, d.elements.to_a("//*[lang('en-us')]").size)
-
- d = Document.new(<<-XML)
- <root>
- <para xml:lang="en"/>
- <div xml:lang="en"><para/></div>
- <para xml:lang="EN"/>
- <para xml:lang="en-us"/>
- </root>
- XML
-
- assert_equal(5, d.elements.to_a("//*[lang('en')]").size)
- end
-
- def test_ticket_60
- document = REXML::Document.new("<a><b>A</b><b>1</b></a>")
- assert_equal( "A", REXML::XPath.first(document, '//b[.="A"]').text )
- assert_equal( "1", REXML::XPath.first(document, '//b[.="1"]').text )
- end
-
- def test_normalize_space
- source = "<a><!--COMMENT A--><b><!-- COMMENT A --></b></a>"
- doc = REXML::Document.new(source)
- predicate = "string(.)=normalize_space('\nCOMMENT \n A \n\n ')"
- m = REXML::XPath.match(doc, "//comment()[#{predicate}]")
- assert_equal( [REXML::Comment.new("COMMENT A")], m )
- end
-
- def test_string_nil_without_context
- doc = REXML::Document.new(<<-XML)
- <?xml version="1.0" encoding="UTF-8"?>
- <root>
- <foo bar="baz"/>
- <foo bar=""/>
- </root>
- XML
-
- assert_equal([doc.root.elements[2]],
- REXML::XPath.match(doc,
- "//foo[@bar=$n]",
- nil,
- {"n" => nil}))
- end
-
- def test_unregistered_method
- doc = Document.new("<root/>")
- assert_nil(XPath::first(doc.root, "to_s()"))
- end
-
- def test_nonexistent_function
- doc = Document.new("<root><nonexistent/></root>")
- # TODO: Maybe, this is not XPath spec behavior.
- # This behavior must be reconsidered.
- assert_equal(doc.root.elements[1],
- XPath::first(doc.root, "nonexistent()"))
- end
- end
-end
diff --git a/test/rexml/functions/test_boolean.rb b/test/rexml/functions/test_boolean.rb
deleted file mode 100644
index b3e2117c10..0000000000
--- a/test/rexml/functions/test_boolean.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: false
-
-require "test/unit"
-require "rexml/document"
-require "rexml/functions"
-
-module REXMLTests
- class TestFunctionsBoolean < Test::Unit::TestCase
- def setup
- REXML::Functions.context = nil
- end
-
- def test_true
- assert_equal(true, REXML::Functions.boolean(true))
- end
-
- def test_false
- assert_equal(false, REXML::Functions.boolean(false))
- end
-
- def test_integer_true
- assert_equal(true, REXML::Functions.boolean(1))
- end
-
- def test_integer_positive_zero
- assert_equal(false, REXML::Functions.boolean(0))
- end
-
- def test_integer_negative_zero
- assert_equal(false, REXML::Functions.boolean(-0))
- end
-
- def test_float_true
- assert_equal(true, REXML::Functions.boolean(1.1))
- end
-
- def test_float_positive_zero
- assert_equal(false, REXML::Functions.boolean(-0.0))
- end
-
- def test_float_negative_zero
- assert_equal(false, REXML::Functions.boolean(-0.0))
- end
-
- def test_float_nan
- assert_equal(false, REXML::Functions.boolean(Float::NAN))
- end
-
- def test_string_true
- assert_equal(true, REXML::Functions.boolean("content"))
- end
-
- def test_string_empty
- assert_equal(false, REXML::Functions.boolean(""))
- end
-
- def test_node_set_true
- root = REXML::Document.new("<root/>").root
- assert_equal(true, REXML::Functions.boolean([root]))
- end
-
- def test_node_set_empty
- assert_equal(false, REXML::Functions.boolean([]))
- end
-
- def test_nil
- assert_equal(false, REXML::Functions.boolean(nil))
- end
-
- def test_context
- REXML::Functions.context = {node: true}
- assert_equal(true, REXML::Functions.boolean())
- end
- end
-end
diff --git a/test/rexml/functions/test_local_name.rb b/test/rexml/functions/test_local_name.rb
deleted file mode 100644
index 97c9e74852..0000000000
--- a/test/rexml/functions/test_local_name.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: false
-
-require "test/unit"
-require "rexml/document"
-require "rexml/functions"
-
-module REXMLTests
- class TestFunctionsLocalName < Test::Unit::TestCase
- def setup
- REXML::Functions.context = nil
- end
-
- def test_one
- document = REXML::Document.new(<<-XML)
-<root xmlns:x="http://example.com/x/">
- <x:child/>
-</root>
- XML
- node_set = document.root.children
- assert_equal("child", REXML::Functions.local_name(node_set))
- end
-
- def test_multiple
- document = REXML::Document.new(<<-XML)
-<root xmlns:x="http://example.com/x/">
- <x:child1/>
- <x:child2/>
-</root>
- XML
- node_set = document.root.children
- assert_equal("child1", REXML::Functions.local_name(node_set))
- end
-
- def test_nonexistent
- assert_equal("", REXML::Functions.local_name([]))
- end
-
- def test_context
- document = REXML::Document.new("<root/>")
- REXML::Functions.context = {node: document.root}
- assert_equal("root", REXML::Functions.local_name())
- end
- end
-end
diff --git a/test/rexml/functions/test_number.rb b/test/rexml/functions/test_number.rb
deleted file mode 100644
index 16e635701c..0000000000
--- a/test/rexml/functions/test_number.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: false
-
-require "test/unit"
-require "rexml/document"
-require "rexml/functions"
-
-module REXMLTests
- class TestFunctionsNumber < Test::Unit::TestCase
- def setup
- REXML::Functions.context = nil
- end
-
- def test_true
- assert_equal(1, REXML::Functions.number(true))
- end
-
- def test_false
- assert_equal(0, REXML::Functions.number(false))
- end
-
- def test_numeric
- assert_equal(29, REXML::Functions.number(29))
- end
-
- def test_string_integer
- assert_equal(100, REXML::Functions.number("100"))
- end
-
- def test_string_float
- assert_equal(-9.13, REXML::Functions.number("-9.13"))
- end
-
- def test_node_set
- root = REXML::Document.new("<root>100</root>").root
- assert_equal(100, REXML::Functions.number([root]))
- end
- end
-end
diff --git a/test/rexml/listener.rb b/test/rexml/listener.rb
deleted file mode 100644
index 6bede03c59..0000000000
--- a/test/rexml/listener.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: false
-class Listener
- attr_reader :ts, :te
- attr_reader :normalize
- def initialize
- @ts = false
- @te = false
- end
- def tag_start name, attrs
- @ts = true if name=="subsection" and attrs["title"]=="Namespaces"
- end
- def tag_end name
- @te = true if name=="documentation"
- end
- def text text
- @normalize = text
- #text.tr! "\n", ' '
- #puts "text #{text[0..10]}..."
- end
- def instruction name, instruction
- #puts "instruction"
- end
- def comment comment
- #puts "comment #{comment[0..10]}..."
- end
- def doctype name, pub_sys, long_name, uri
- #puts "doctype #{name}"
- end
- def attlistdecl content
- #puts "attlistdecl"
- end
- def elementdecl content
- #puts "elementdecl"
- end
- def entitydecl content
- #puts "entitydecl"
- end
- def notationdecl content
- #puts "notationdecl"
- end
- def entity content
- #puts "entity"
- end
- def cdata content
- #puts "cdata"
- end
- def xmldecl version, encoding, standalone
- #puts "xmldecl #{version}"
- end
-end
-
diff --git a/test/rexml/parse/test_document_type_declaration.rb b/test/rexml/parse/test_document_type_declaration.rb
deleted file mode 100644
index 55713909e7..0000000000
--- a/test/rexml/parse/test_document_type_declaration.rb
+++ /dev/null
@@ -1,229 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "rexml/document"
-
-module REXMLTests
- class TestParseDocumentTypeDeclaration < Test::Unit::TestCase
- private
- def parse(doctype)
- REXML::Document.new(<<-XML).doctype
-#{doctype}
-<r/>
- XML
- end
-
- class TestName < self
- def test_valid
- doctype = parse(<<-DOCTYPE)
-<!DOCTYPE r>
- DOCTYPE
- assert_equal("r", doctype.name)
- end
-
- def test_garbage_plus_before_name_at_line_start
- exception = assert_raise(REXML::ParseException) do
- parse(<<-DOCTYPE)
-<!DOCTYPE +
-r SYSTEM "urn:x-rexml:test" [
-]>
- DOCTYPE
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed DOCTYPE: invalid name
-Line: 5
-Position: 51
-Last 80 unconsumed characters:
-+ r SYSTEM "urn:x-rexml:test" [ ]> <r/>
- DETAIL
- end
- end
-
- class TestExternalID < self
- class TestSystem < self
- def test_left_bracket_in_system_literal
- doctype = parse(<<-DOCTYPE)
-<!DOCTYPE r SYSTEM "urn:x-rexml:[test" [
-]>
- DOCTYPE
- assert_equal([
- "r",
- "SYSTEM",
- nil,
- "urn:x-rexml:[test",
- ],
- [
- doctype.name,
- doctype.external_id,
- doctype.public,
- doctype.system,
- ])
- end
-
- def test_greater_than_in_system_literal
- doctype = parse(<<-DOCTYPE)
-<!DOCTYPE r SYSTEM "urn:x-rexml:>test" [
-]>
- DOCTYPE
- assert_equal([
- "r",
- "SYSTEM",
- nil,
- "urn:x-rexml:>test",
- ],
- [
- doctype.name,
- doctype.external_id,
- doctype.public,
- doctype.system,
- ])
- end
-
- def test_no_literal
- exception = assert_raise(REXML::ParseException) do
- parse(<<-DOCTYPE)
-<!DOCTYPE r SYSTEM>
- DOCTYPE
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed DOCTYPE: system literal is missing
-Line: 3
-Position: 26
-Last 80 unconsumed characters:
- SYSTEM> <r/>
- DETAIL
- end
-
- def test_garbage_after_literal
- exception = assert_raise(REXML::ParseException) do
- parse(<<-DOCTYPE)
-<!DOCTYPE r SYSTEM 'r.dtd'x'>
- DOCTYPE
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed DOCTYPE: garbage after external ID
-Line: 3
-Position: 36
-Last 80 unconsumed characters:
-x'> <r/>
- DETAIL
- end
-
- def test_single_quote
- doctype = parse(<<-DOCTYPE)
-<!DOCTYPE r SYSTEM 'r".dtd'>
- DOCTYPE
- assert_equal("r\".dtd", doctype.system)
- end
-
- def test_double_quote
- doctype = parse(<<-DOCTYPE)
-<!DOCTYPE r SYSTEM "r'.dtd">
- DOCTYPE
- assert_equal("r'.dtd", doctype.system)
- end
- end
-
- class TestPublic < self
- class TestPublicIDLiteral < self
- def test_content_double_quote
- exception = assert_raise(REXML::ParseException) do
- parse(<<-DOCTYPE)
-<!DOCTYPE r PUBLIC 'double quote " is invalid' "r.dtd">
- DOCTYPE
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed DOCTYPE: invalid public ID literal
-Line: 3
-Position: 62
-Last 80 unconsumed characters:
- PUBLIC 'double quote " is invalid' "r.dtd"> <r/>
- DETAIL
- end
-
- def test_single_quote
- doctype = parse(<<-DOCTYPE)
-<!DOCTYPE r PUBLIC 'public-id-literal' "r.dtd">
- DOCTYPE
- assert_equal("public-id-literal", doctype.public)
- end
-
- def test_double_quote
- doctype = parse(<<-DOCTYPE)
-<!DOCTYPE r PUBLIC "public'-id-literal" "r.dtd">
- DOCTYPE
- assert_equal("public'-id-literal", doctype.public)
- end
- end
-
- class TestSystemLiteral < self
- def test_garbage_after_literal
- exception = assert_raise(REXML::ParseException) do
- parse(<<-DOCTYPE)
-<!DOCTYPE r PUBLIC 'public-id-literal' 'system-literal'x'>
- DOCTYPE
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed DOCTYPE: garbage after external ID
-Line: 3
-Position: 65
-Last 80 unconsumed characters:
-x'> <r/>
- DETAIL
- end
-
- def test_single_quote
- doctype = parse(<<-DOCTYPE)
-<!DOCTYPE r PUBLIC "public-id-literal" 'system"-literal'>
- DOCTYPE
- assert_equal("system\"-literal", doctype.system)
- end
-
- def test_double_quote
- doctype = parse(<<-DOCTYPE)
-<!DOCTYPE r PUBLIC "public-id-literal" "system'-literal">
- DOCTYPE
- assert_equal("system'-literal", doctype.system)
- end
- end
- end
- end
-
- class TestMixed < self
- def test_entity_element
- doctype = parse(<<-INTERNAL_SUBSET)
-<!ENTITY entity-name "entity content">
-<!ELEMENT element-name EMPTY>
- INTERNAL_SUBSET
- assert_equal([REXML::Entity, REXML::ElementDecl],
- doctype.children.collect(&:class))
- end
-
- def test_attlist_entity
- doctype = parse(<<-INTERNAL_SUBSET)
-<!ATTLIST attribute-list-name attribute-name CDATA #REQUIRED>
-<!ENTITY entity-name "entity content">
- INTERNAL_SUBSET
- assert_equal([REXML::AttlistDecl, REXML::Entity],
- doctype.children.collect(&:class))
- end
-
- def test_notation_attlist
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION notation-name SYSTEM "system-literal">
-<!ATTLIST attribute-list-name attribute-name CDATA #REQUIRED>
- INTERNAL_SUBSET
- assert_equal([REXML::NotationDecl, REXML::AttlistDecl],
- doctype.children.collect(&:class))
- end
-
- private
- def parse(internal_subset)
- super(<<-DOCTYPE)
-<!DOCTYPE r SYSTEM "urn:x-rexml:test" [
-#{internal_subset}
-]>
- DOCTYPE
- end
- end
- end
-end
diff --git a/test/rexml/parse/test_element.rb b/test/rexml/parse/test_element.rb
deleted file mode 100644
index 9f172a28e8..0000000000
--- a/test/rexml/parse/test_element.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require "test/unit"
-require "rexml/document"
-
-module REXMLTests
- class TestParseElement < Test::Unit::TestCase
- def parse(xml)
- REXML::Document.new(xml)
- end
-
- class TestInvalid < self
- def test_top_level_end_tag
- exception = assert_raise(REXML::ParseException) do
- parse("</a>")
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Unexpected top-level end tag (got 'a')
-Line: 1
-Position: 4
-Last 80 unconsumed characters:
-
- DETAIL
- end
-
- def test_no_end_tag
- exception = assert_raise(REXML::ParseException) do
- parse("<a></")
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Missing end tag for 'a'
-Line: 1
-Position: 5
-Last 80 unconsumed characters:
-</
- DETAIL
- end
-
- def test_empty_namespace_attribute_name
- exception = assert_raise(REXML::ParseException) do
- parse("<x :a=\"\"></x>")
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Invalid attribute name: <:a="">
-Line: 1
-Position: 9
-Last 80 unconsumed characters:
-
- DETAIL
- end
-
- def test_garbage_less_than_before_root_element_at_line_start
- exception = assert_raise(REXML::ParseException) do
- parse("<\n<x/>")
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-malformed XML: missing tag start
-Line: 2
-Position: 6
-Last 80 unconsumed characters:
-< <x/>
- DETAIL
- end
-
- def test_garbage_less_than_slash_before_end_tag_at_line_start
- exception = assert_raise(REXML::ParseException) do
- parse("<x></\n</x>")
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Missing end tag for 'x'
-Line: 2
-Position: 10
-Last 80 unconsumed characters:
-</ </x>
- DETAIL
- end
- end
- end
-end
diff --git a/test/rexml/parse/test_notation_declaration.rb b/test/rexml/parse/test_notation_declaration.rb
deleted file mode 100644
index 19a0536d0a..0000000000
--- a/test/rexml/parse/test_notation_declaration.rb
+++ /dev/null
@@ -1,281 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'rexml/document'
-
-module REXMLTests
- class TestParseNotationDeclaration < Test::Unit::TestCase
- private
- def xml(internal_subset)
- <<-XML
-<!DOCTYPE r SYSTEM "urn:x-henrikmartensson:test" [
-#{internal_subset}
-]>
-<r/>
- XML
- end
-
- def parse(internal_subset)
- REXML::Document.new(xml(internal_subset)).doctype
- end
-
- class TestCommon < self
- def test_name
- doctype = parse("<!NOTATION name PUBLIC 'urn:public-id'>")
- assert_equal("name", doctype.notation("name").name)
- end
-
- def test_no_name
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: name is missing
-Line: 5
-Position: 72
-Last 80 unconsumed characters:
- <!NOTATION> ]> <r/>
- DETAIL
- end
-
- def test_invalid_name
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION '>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: invalid name
-Line: 5
-Position: 74
-Last 80 unconsumed characters:
-'> ]> <r/>
- DETAIL
- end
-
- def test_no_id_type
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION name>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: invalid ID type
-Line: 5
-Position: 77
-Last 80 unconsumed characters:
-> ]> <r/>
- DETAIL
- end
-
- def test_invalid_id_type
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION name INVALID>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: invalid ID type
-Line: 5
-Position: 85
-Last 80 unconsumed characters:
- INVALID> ]> <r/>
- DETAIL
- end
- end
-
- class TestExternalID < self
- class TestSystem < self
- def test_no_literal
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION name SYSTEM>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: system literal is missing
-Line: 5
-Position: 84
-Last 80 unconsumed characters:
- SYSTEM> ]> <r/>
- DETAIL
- end
-
- def test_garbage_after_literal
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION name SYSTEM 'system-literal'x'>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: garbage before end >
-Line: 5
-Position: 103
-Last 80 unconsumed characters:
-x'> ]> <r/>
- DETAIL
- end
-
- def test_single_quote
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION name SYSTEM 'system-literal'>
- INTERNAL_SUBSET
- assert_equal("system-literal", doctype.notation("name").system)
- end
-
- def test_double_quote
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION name SYSTEM "system-literal">
- INTERNAL_SUBSET
- assert_equal("system-literal", doctype.notation("name").system)
- end
- end
-
- class TestPublic < self
- class TestPublicIDLiteral < self
- def test_content_double_quote
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC 'double quote " is invalid' "system-literal">
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: invalid public ID literal
-Line: 5
-Position: 129
-Last 80 unconsumed characters:
- PUBLIC 'double quote " is invalid' "system-literal"> ]> <r/>
- DETAIL
- end
-
- def test_single_quote
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC 'public-id-literal' "system-literal">
- INTERNAL_SUBSET
- assert_equal("public-id-literal", doctype.notation("name").public)
- end
-
- def test_double_quote
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC "public-id-literal" "system-literal">
- INTERNAL_SUBSET
- assert_equal("public-id-literal", doctype.notation("name").public)
- end
- end
-
- class TestSystemLiteral < self
- def test_garbage_after_literal
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC 'public-id-literal' 'system-literal'x'>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: garbage before end >
-Line: 5
-Position: 123
-Last 80 unconsumed characters:
-x'> ]> <r/>
- DETAIL
- end
-
- def test_single_quote
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC "public-id-literal" 'system-literal'>
- INTERNAL_SUBSET
- assert_equal("system-literal", doctype.notation("name").system)
- end
-
- def test_double_quote
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC "public-id-literal" "system-literal">
- INTERNAL_SUBSET
- assert_equal("system-literal", doctype.notation("name").system)
- end
- end
- end
-
- class TestMixed < self
- def test_system_public
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION system-name SYSTEM "system-literal">
-<!NOTATION public-name PUBLIC "public-id-literal" 'system-literal'>
- INTERNAL_SUBSET
- assert_equal(["system-name", "public-name"],
- doctype.notations.collect(&:name))
- end
-
- def test_public_system
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION public-name PUBLIC "public-id-literal" 'system-literal'>
-<!NOTATION system-name SYSTEM "system-literal">
- INTERNAL_SUBSET
- assert_equal(["public-name", "system-name"],
- doctype.notations.collect(&:name))
- end
- end
- end
-
- class TestPublicID < self
- def test_no_literal
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: public ID literal is missing
-Line: 5
-Position: 84
-Last 80 unconsumed characters:
- PUBLIC> ]> <r/>
- DETAIL
- end
-
- def test_literal_content_double_quote
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC 'double quote " is invalid in PubidLiteral'>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: invalid public ID literal
-Line: 5
-Position: 128
-Last 80 unconsumed characters:
- PUBLIC 'double quote \" is invalid in PubidLiteral'> ]> <r/>
- DETAIL
- end
-
- def test_garbage_after_literal
- exception = assert_raise(REXML::ParseException) do
- parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC 'public-id-literal'x'>
- INTERNAL_SUBSET
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Malformed notation declaration: garbage before end >
-Line: 5
-Position: 106
-Last 80 unconsumed characters:
-x'> ]> <r/>
- DETAIL
- end
-
- def test_literal_single_quote
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC 'public-id-literal'>
- INTERNAL_SUBSET
- assert_equal("public-id-literal", doctype.notation("name").public)
- end
-
- def test_literal_double_quote
- doctype = parse(<<-INTERNAL_SUBSET)
-<!NOTATION name PUBLIC "public-id-literal">
- INTERNAL_SUBSET
- assert_equal("public-id-literal", doctype.notation("name").public)
- end
- end
- end
-end
diff --git a/test/rexml/parse/test_processing_instruction.rb b/test/rexml/parse/test_processing_instruction.rb
deleted file mode 100644
index f0c0c24e67..0000000000
--- a/test/rexml/parse/test_processing_instruction.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require "test/unit"
-require "rexml/document"
-
-module REXMLTests
- class TestParseProcessinInstruction < Test::Unit::TestCase
- def parse(xml)
- REXML::Document.new(xml)
- end
-
- class TestInvalid < self
- def test_no_name
- exception = assert_raise(REXML::ParseException) do
- parse("<??>")
- end
- assert_equal(<<-DETAIL.chomp, exception.to_s)
-Invalid processing instruction node
-Line: 1
-Position: 4
-Last 80 unconsumed characters:
-<??>
- DETAIL
- end
-
- def test_garbage_text
- # TODO: This should be parse error.
- # Create test/parse/test_document.rb or something and move this to it.
- doc = parse(<<-XML)
-x<?x y
-<!--?><?x -->?>
-<r/>
- XML
- pi = doc.children[1]
- assert_equal([
- "x",
- "y\n<!--",
- ],
- [
- pi.target,
- pi.content,
- ])
- end
- end
- end
-end
diff --git a/test/rexml/parser/test_sax2.rb b/test/rexml/parser/test_sax2.rb
deleted file mode 100644
index 91d135f5f7..0000000000
--- a/test/rexml/parser/test_sax2.rb
+++ /dev/null
@@ -1,203 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "rexml/parsers/sax2parser"
-require "rexml/sax2listener"
-
-module REXMLTests
-class TestSAX2Parser < Test::Unit::TestCase
- class TestDocumentTypeDeclaration < self
- private
- def xml(internal_subset)
- <<-XML
-<!DOCTYPE r SYSTEM "urn:x-henrikmartensson:test" [
-#{internal_subset}
-]>
-<r/>
- XML
- end
-
- class TestEntityDeclaration < self
- class Listener
- include REXML::SAX2Listener
- attr_reader :entity_declarations
- def initialize
- @entity_declarations = []
- end
-
- def entitydecl(declaration)
- super
- @entity_declarations << declaration
- end
- end
-
- private
- def parse(internal_subset)
- listener = Listener.new
- parser = REXML::Parsers::SAX2Parser.new(xml(internal_subset))
- parser.listen(listener)
- parser.parse
- listener.entity_declarations
- end
-
- class TestGeneralEntity < self
- class TestValue < self
- def test_double_quote
- assert_equal([["name", "value"]], parse(<<-INTERNAL_SUBSET))
-<!ENTITY name "value">
- INTERNAL_SUBSET
- end
-
- def test_single_quote
- assert_equal([["name", "value"]], parse(<<-INTERNAL_SUBSET))
-<!ENTITY name 'value'>
- INTERNAL_SUBSET
- end
- end
-
- class TestExternlID < self
- class TestSystem < self
- def test_with_ndata
- declaration = [
- "name",
- "SYSTEM", "system-literal",
- "NDATA", "ndata-name",
- ]
- assert_equal([declaration],
- parse(<<-INTERNAL_SUBSET))
-<!ENTITY name SYSTEM "system-literal" NDATA ndata-name>
- INTERNAL_SUBSET
- end
-
- def test_without_ndata
- declaration = [
- "name",
- "SYSTEM", "system-literal",
- ]
- assert_equal([declaration],
- parse(<<-INTERNAL_SUBSET))
-<!ENTITY name SYSTEM "system-literal">
- INTERNAL_SUBSET
- end
- end
-
- class TestPublic < self
- def test_with_ndata
- declaration = [
- "name",
- "PUBLIC", "public-literal", "system-literal",
- "NDATA", "ndata-name",
- ]
- assert_equal([declaration],
- parse(<<-INTERNAL_SUBSET))
-<!ENTITY name PUBLIC "public-literal" "system-literal" NDATA ndata-name>
- INTERNAL_SUBSET
- end
-
- def test_without_ndata
- declaration = [
- "name",
- "PUBLIC", "public-literal", "system-literal",
- ]
- assert_equal([declaration], parse(<<-INTERNAL_SUBSET))
-<!ENTITY name PUBLIC "public-literal" "system-literal">
- INTERNAL_SUBSET
- end
- end
- end
- end
-
- class TestParameterEntity < self
- class TestValue < self
- def test_double_quote
- assert_equal([["%", "name", "value"]], parse(<<-INTERNAL_SUBSET))
-<!ENTITY % name "value">
- INTERNAL_SUBSET
- end
-
- def test_single_quote
- assert_equal([["%", "name", "value"]], parse(<<-INTERNAL_SUBSET))
-<!ENTITY % name 'value'>
- INTERNAL_SUBSET
- end
- end
-
- class TestExternlID < self
- def test_system
- declaration = [
- "%",
- "name",
- "SYSTEM", "system-literal",
- ]
- assert_equal([declaration],
- parse(<<-INTERNAL_SUBSET))
-<!ENTITY % name SYSTEM "system-literal">
- INTERNAL_SUBSET
- end
-
- def test_public
- declaration = [
- "%",
- "name",
- "PUBLIC", "public-literal", "system-literal",
- ]
- assert_equal([declaration], parse(<<-INTERNAL_SUBSET))
-<!ENTITY % name PUBLIC "public-literal" "system-literal">
- INTERNAL_SUBSET
- end
- end
- end
- end
-
- class TestNotationDeclaration < self
- class Listener
- include REXML::SAX2Listener
- attr_reader :notation_declarations
- def initialize
- @notation_declarations = []
- end
-
- def notationdecl(*declaration)
- super
- @notation_declarations << declaration
- end
- end
-
- private
- def parse(internal_subset)
- listener = Listener.new
- parser = REXML::Parsers::SAX2Parser.new(xml(internal_subset))
- parser.listen(listener)
- parser.parse
- listener.notation_declarations
- end
-
- class TestExternlID < self
- def test_system
- declaration = ["name", "SYSTEM", nil, "system-literal"]
- assert_equal([declaration],
- parse(<<-INTERNAL_SUBSET))
-<!NOTATION name SYSTEM "system-literal">
- INTERNAL_SUBSET
- end
-
- def test_public
- declaration = ["name", "PUBLIC", "public-literal", "system-literal"]
- assert_equal([declaration], parse(<<-INTERNAL_SUBSET))
-<!NOTATION name PUBLIC "public-literal" "system-literal">
- INTERNAL_SUBSET
- end
- end
-
- class TestPublicID < self
- def test_literal
- declaration = ["name", "PUBLIC", "public-literal", nil]
- assert_equal([declaration],
- parse(<<-INTERNAL_SUBSET))
-<!NOTATION name PUBLIC "public-literal">
- INTERNAL_SUBSET
- end
- end
- end
- end
-end
-end
diff --git a/test/rexml/parser/test_stream.rb b/test/rexml/parser/test_stream.rb
deleted file mode 100644
index c315833e4b..0000000000
--- a/test/rexml/parser/test_stream.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require "test/unit"
-require "rexml/document"
-require "rexml/streamlistener"
-
-module REXMLTests
- class TestStreamParser < Test::Unit::TestCase
- class NullListener
- include REXML::StreamListener
- end
-
- class TestInvalid < self
- def test_no_end_tag
- xml = "<root><sub>"
- exception = assert_raise(REXML::ParseException) do
- parse(xml)
- end
- assert_equal(<<-MESSAGE, exception.to_s)
-Missing end tag for '/root/sub'
-Line: 1
-Position: #{xml.bytesize}
-Last 80 unconsumed characters:
- MESSAGE
- end
-
- private
- def parse(xml, listener=nil)
- listener ||= NullListener.new
- REXML::Document.parse_stream(xml, listener)
- end
- end
- end
-end
diff --git a/test/rexml/parser/test_tree.rb b/test/rexml/parser/test_tree.rb
deleted file mode 100644
index 8a5d9d1223..0000000000
--- a/test/rexml/parser/test_tree.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "rexml/document"
-require "rexml/parsers/treeparser"
-
-module REXMLTests
-class TestTreeParser < Test::Unit::TestCase
- class TestInvalid < self
- def test_unmatched_close_tag
- xml = "<root></not-root>"
- exception = assert_raise(REXML::ParseException) do
- parse(xml)
- end
- assert_equal(<<-MESSAGE, exception.to_s)
-Missing end tag for 'root' (got 'not-root')
-Line: 1
-Position: #{xml.bytesize}
-Last 80 unconsumed characters:
- MESSAGE
- end
-
- def test_no_close_tag
- xml = "<root>"
- exception = assert_raise(REXML::ParseException) do
- parse(xml)
- end
- assert_equal(<<-MESSAGE, exception.to_s)
-No close tag for /root
-Line: 1
-Position: #{xml.bytesize}
-Last 80 unconsumed characters:
- MESSAGE
- end
-
- private
- def parse(xml)
- document = REXML::Document.new
- parser = REXML::Parsers::TreeParser.new(xml, document)
- parser.parse
- end
- end
-end
-end
diff --git a/test/rexml/parser/test_ultra_light.rb b/test/rexml/parser/test_ultra_light.rb
deleted file mode 100644
index 44fd1d1ec0..0000000000
--- a/test/rexml/parser/test_ultra_light.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "rexml/parsers/ultralightparser"
-
-module REXMLTests
-class TestUltraLightParser < Test::Unit::TestCase
- class TestDocumentTypeDeclaration < self
- def test_entity_declaration
- assert_equal([
- [
- :start_doctype,
- :parent,
- "root",
- "SYSTEM",
- "urn:x-test",
- nil,
- [:entitydecl, "name", "value"]
- ],
- [:start_element, :parent, "root", {}],
- [:text, "\n"],
- ],
- parse(<<-INTERNAL_SUBSET))
-<!ENTITY name "value">
- INTERNAL_SUBSET
- end
-
- private
- def xml(internal_subset)
- <<-XML
-<!DOCTYPE root SYSTEM "urn:x-test" [
-#{internal_subset}
-]>
-<root/>
- XML
- end
-
- def parse(internal_subset)
- parser = REXML::Parsers::UltraLightParser.new(xml(internal_subset))
- normalize(parser.parse)
- end
-
- def normalize(root)
- root.collect do |child|
- normalize_child(child)
- end
- end
-
- def normalize_child(child)
- tag = child.first
- case tag
- when :start_doctype
- normalized_parent = :parent
- normalized_doctype = child.dup
- normalized_doctype[1] = normalized_parent
- normalized_doctype
- when :start_element
- tag, _parent, name, attributes, *children = child
- normalized_parent = :parent
- normalized_children = children.collect do |sub_child|
- normalize_child(sub_child)
- end
- [tag, normalized_parent, name, attributes, *normalized_children]
- else
- child
- end
- end
- end
-end
-end
diff --git a/test/rexml/rexml_test_utils.rb b/test/rexml/rexml_test_utils.rb
deleted file mode 100644
index 8bb002cee2..0000000000
--- a/test/rexml/rexml_test_utils.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: false
-
-require "test/unit"
-require "rexml/document"
-
-module REXMLTestUtils
- def fixture_path(*components)
- File.join(File.dirname(__FILE__), "data", *components)
- end
-end
diff --git a/test/rexml/test_attribute.rb b/test/rexml/test_attribute.rb
deleted file mode 100644
index 5175bd4454..0000000000
--- a/test/rexml/test_attribute.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative "rexml_test_utils"
-
-module REXMLTests
- class AttributeTest < Test::Unit::TestCase
- def test_empty_prefix
- error = assert_raise(ArgumentError) do
- REXML::Attribute.new(":x")
- end
- assert_equal("name must be " +
- "\#{PREFIX}:\#{LOCAL_NAME} or \#{LOCAL_NAME}: <\":x\">",
- error.message)
- end
- end
-end
diff --git a/test/rexml/test_attributes.rb b/test/rexml/test_attributes.rb
deleted file mode 100644
index d6f566bdf8..0000000000
--- a/test/rexml/test_attributes.rb
+++ /dev/null
@@ -1,223 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit/testcase'
-require 'rexml/document'
-
-module REXMLTests
- class AttributesTester < Test::Unit::TestCase
- include REXML
- def test_accessor
- doc = Document.new("<a xmlns:foo='a' xmlns:bar='b' foo:att='1' bar:att='2' att='3'/>")
- assert_equal '3', doc.root.attributes['att']
- assert_equal '2', doc.root.attributes['bar:att']
- doc.root.attributes['att'] = 5
- assert_equal '5', doc.root.attributes['att']
- end
-
- def test_each_attribute
- doc = Document.new('<a x="1" y="2"/>')
- doc.root.attributes.each_attribute {|attr|
- if attr.expanded_name == 'x'
- assert_equal '1', attr.value
- elsif attr.expanded_name == 'y'
- assert_equal '2', attr.value
- else
- assert_fail "No such attribute!!"
- end
- }
- end
-
- def test_each
- doc = Document.new('<a x="1" y="2"/>')
- doc.root.attributes.each {|name, value|
- if name == 'x'
- assert_equal '1', value
- elsif name == 'y'
- assert_equal '2', value
- else
- assert_fail "No such attribute!!"
- end
- }
- end
-
- def test_get_attribute
- doc = Document.new('<a xmlns:x="a" x:foo="1" foo="2" bar="3"/>')
- assert_equal '2', doc.root.attributes.get_attribute("foo").value
- assert_equal '1', doc.root.attributes.get_attribute("x:foo").value
- end
-
- def test_size
- doc = Document.new("<a xmlns:foo='a' x='1' y='2' foo:x='3'/>")
- assert_equal 4, doc.root.attributes.length
- end
-
- def test_setter
- doc = Document.new("<a xmlns:x='a' x:foo='1' foo='3'/>")
- doc.root.attributes['y:foo'] = '2'
- assert_equal '2', doc.root.attributes['y:foo']
- doc.root.attributes['foo'] = '4'
- assert_equal '4', doc.root.attributes['foo']
- doc.root.attributes['x:foo'] = nil
- assert_equal 3, doc.root.attributes.size
- end
-
- def test_delete
- doc = Document.new("<a xmlns:y='a' xmlns:x='b' xmlns:z='c' y:foo='0' x:foo='1' foo='3' z:foo='4'/>")
- doc.root.attributes.delete 'foo'
- assert_equal 6, doc.root.attributes.size
- assert_equal '1', doc.root.attributes['x:foo']
-
- doc.root.attributes.delete 'x:foo'
- assert_equal 5, doc.root.attributes.size
-
- attr = doc.root.attributes.get_attribute('y:foo')
- doc.root.attributes.delete attr
- assert_equal 4, doc.root.attributes.size
-
- assert_equal '4', doc.root.attributes['z:foo']
- end
-
- def test_prefixes
- doc = Document.new("<a xmlns='foo' xmlns:x='bar' xmlns:y='twee' z='glorp' x:k='gru'/>")
- prefixes = doc.root.attributes.prefixes
- assert_equal 2, prefixes.size
- assert_equal 0, (prefixes - ['x', 'y']).size
- end
-
- # Contributed by Mike Stok
- def test_values_with_apostrophes
- doc = Document.new(%q#<tag h1="1'2'" h2='1"2'/>#)
- s = doc.to_s
- assert(s =~ /h1='1&apos;2&apos;'/)
- assert(s =~ /h2='1"2'/)
- end
-
- # Submitted by Kou
- def test_namespace_conflict
- assert_raise( ParseException,
- "Declaring two attributes with the same namespace should be an error" ) do
- REXML::Document.new <<-XML
- <x xmlns:n1="http://www.w3.org"
- xmlns:n2="http://www.w3.org" >
- <bad n1:a="1" n2:a="2" />
- </x>
- XML
- end
-
- REXML::Document.new("<a xmlns:a='a' xmlns:b='a'></a>")
- end
-
- # Submitted by Kou
- def test_attribute_deletion
- e = REXML::Element.new
- e.add_namespace("a", "http://a/")
- e.add_namespace("b", "http://b/")
- e.add_attributes({"c" => "cc", "a:c" => "cC", "b:c" => "CC"})
-
- e.attributes.delete("c")
- assert_nil(e.attributes.get_attribute("c"))
-
- before_size = e.attributes.size
- e.attributes.delete("c")
- assert_nil(e.attributes.get_attribute("c"))
- assert_equal(before_size, e.attributes.size)
-
- e.attributes.delete(e.attributes.get_attribute("a:c"))
- assert_nil(e.attributes.get_attribute("a:c"))
-
- e.attributes.delete("b:c")
- assert_nil(e.attributes.get_attribute("b:c"))
-
- before_size = e.attributes.size
- e.attributes.delete(e.attributes.get_attribute("b:c"))
- assert_nil(e.attributes.get_attribute("b:c"))
- assert_equal(before_size, e.attributes.size)
-
- before_size = e.attributes.size
- e.attributes.delete("c")
- assert_nil(e.attributes.get_attribute("c"))
- assert_equal(before_size, e.attributes.size)
-
- e.add_attribute("c", "cc")
-
- e.attributes.delete(e.attributes.get_attribute("c"))
- assert_nil(e.attributes.get_attribute("c"))
- end
-
- # Submitted by Kou
- def test_element_usage
- attr = Attribute.new("name", "value")
- elem = Element.new("elem")
- a = Attribute.new(attr, elem)
- assert_equal(elem, a.element)
- end
-
- def attr_test(attr_name,attr_value)
- a1 = REXML::Attribute.new(attr_name,attr_value)
-
- s1 = a1.value
- s2 = a1.value
-
- #p s1
- #p s2
- assert_equal(s1,s2)
-
- a2 = REXML::Attribute.new(attr_name,attr_value)
-
- a2.to_s # NB invocation of to_s
- s1 = a2.value
- s2 = a2.value
-
- #p s1
- #p s2
- assert_equal(s1,s2)
- end
-
- def test_amp_attributes
- attr_test('name','value with &amp; ampersand only')
- end
-
- def test_amp_and_lf_attributes
- attr_test('name','value with LF &#x000a; &amp; ampersand')
- end
-
- def test_quoting
- d = Document.new(%q{<a x='1' y="2"/>})
- assert_equal( %q{<a x='1' y='2'/>}, d.to_s )
- d.root.context[:attribute_quote] = :quote
- assert_equal( %q{<a x="1" y="2"/>}, d.to_s )
-
- d = Document.new(%q{<a x='1' y="2"><b z='3'/></a>})
- assert_equal( %q{<a x='1' y='2'><b z='3'/></a>}, d.to_s )
- d.root.context[:attribute_quote] = :quote
- assert_equal( %q{<a x="1" y="2"><b z="3"/></a>}, d.to_s )
- end
-
- def test_ticket_127
- doc = Document.new
- doc.add_element 'a', { 'v' => 'x & y' }
- assert doc.to_s.index(';')
- end
-
- def test_to_a_with_namespaces
- document = Document.new(<<-XML)
-<root
- xmlns:ns1="http://example.org/ns1"
- xmlns:ns2="http://example.org/ns2">
- <child
- ns1:attribute="ns1"
- ns2:attribute="ns2"
- attribute="no-ns"
- other-attribute="other-value"/>
-</root>
-XML
- child = document.root.elements["child"]
- assert_equal([
- "attribute='no-ns'",
- "ns1:attribute='ns1'",
- "ns2:attribute='ns2'",
- "other-attribute='other-value'",
- ],
- child.attributes.to_a.collect(&:to_string).sort)
- end
- end
-end
diff --git a/test/rexml/test_attributes_mixin.rb b/test/rexml/test_attributes_mixin.rb
deleted file mode 100644
index 3a9f54eefd..0000000000
--- a/test/rexml/test_attributes_mixin.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'rexml/document'
-
-module REXMLTests
- class TestAttributes < Test::Unit::TestCase
- def setup
- @ns_a = "urn:x-test:a"
- @ns_b = "urn:x-test:b"
- element_string = <<-"XMLEND"
- <test xmlns:a="#{@ns_a}"
- xmlns:b="#{@ns_b}"
- a = "1"
- b = '2'
- a:c = "3"
- a:d = '4'
- a:e = "5"
- b:f = "6"/>
- XMLEND
- @attributes = REXML::Document.new(element_string).root.attributes
- end
-
- def test_get_attribute_ns
- assert_equal("1", @attributes.get_attribute_ns("", "a").value)
- assert_equal("2", @attributes.get_attribute_ns("", "b").value)
- assert_equal("3", @attributes.get_attribute_ns(@ns_a, "c").value)
- assert_equal("4", @attributes.get_attribute_ns(@ns_a, "d").value)
- assert_equal("5", @attributes.get_attribute_ns(@ns_a, "e").value)
- assert_equal("6", @attributes.get_attribute_ns(@ns_b, "f").value)
- end
- end
-end
diff --git a/test/rexml/test_changing_encoding.rb b/test/rexml/test_changing_encoding.rb
deleted file mode 100644
index a2dc07254a..0000000000
--- a/test/rexml/test_changing_encoding.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require 'rexml/encoding'
-
-module REXMLTests
- class ChangingEncodings < Test::Unit::TestCase
- def initialize a
- @u = 'テスト ほげ ふが 美しい'
- @e = @u.encode("EUC-JP")
- @f = Foo.new
- super
- end
-
- class Foo
- include REXML::Encoding
- end
-
- # Note that these tests must be executed in order for the third one to
- # actually test anything.
- def test_0_euc
- @f.encoding = 'EUC-JP'
- assert_equal( @u, @f.decode(@e) )
- # This doesn't happen anymore, for some reason
- #assert_raise( Iconv::IllegalSequence, "Decoding unicode should fail" ) {
- # @f.decode(@u) == @u
- #}
- end
-
- def test_1_utf
- @f.encoding = 'UTF-8'
- assert_not_equal( @u, @f.decode( @e ) )
- assert_equal( @u, @f.decode( @u ) )
- end
-
- def test_2_euc
- @f.encoding = 'EUC-JP'
- assert_equal( @u, @f.decode(@e) )
- # This doesn't happen anymore, for some reason
- #assert_raise( Iconv::IllegalSequence, "Decoding unicode should fail" ) {
- # @f.decode(@u) == @u
- #}
- end
- end
-end
diff --git a/test/rexml/test_comment.rb b/test/rexml/test_comment.rb
deleted file mode 100644
index 0af2f5ca76..0000000000
--- a/test/rexml/test_comment.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: false
-require "test/unit/testcase"
-
-require 'rexml/document'
-
-module REXMLTests
- class CommentTester < Test::Unit::TestCase
- # Bug #5278
- def test_hyphen_end_line_in_doctype
- xml = <<-XML
-<?xml version="1.0"?>
-<!DOCTYPE root [
-<!-- comment end with hyphen -
- here -->
-]>
-<root/>
- XML
- document = REXML::Document.new(xml)
- comments = document.doctype.children.find_all do |child|
- child.is_a?(REXML::Comment)
- end
- assert_equal([" comment end with hyphen -\n here "],
- comments.collect(&:to_s))
- end
- end
-end
diff --git a/test/rexml/test_contrib.rb b/test/rexml/test_contrib.rb
deleted file mode 100644
index 8462b3c23f..0000000000
--- a/test/rexml/test_contrib.rb
+++ /dev/null
@@ -1,585 +0,0 @@
-# coding: binary
-# frozen_string_literal: false
-
-require_relative "rexml_test_utils"
-
-require "rexml/document"
-require "rexml/parseexception"
-require "rexml/formatters/default"
-
-module REXMLTests
- class ContribTester < Test::Unit::TestCase
- include REXMLTestUtils
- include REXML
-
- XML_STRING_01 = <<DELIMITER
-<?xml version="1.0" encoding="UTF-8"?>
-<biblio>
- <entry type="Book">
- <author>Thomas, David; Hunt, Andrew</author>
- <language>english</language>
- <publisher>Addison-Wesley</publisher>
- <title>Programming Ruby. The Pragmatic Programmer's Guide</title>
- <year>2000</year>
- </entry>
- <entry type="Book">
- <author>Blammo, Blah</author>
- <language>english</language>
- <publisher>Hubbabubba</publisher>
- <title>Foozboozer's Life</title>
- <type>Book</type>
- <year>2002</year>
- </entry>
-</biblio>
-DELIMITER
-
- XML_STRING_02 = <<DELIMITER
-<biblio>
- <entry type="Book">
- <language>english</language>
- <publisher>Addison-Wesley</publisher>
- <title>Programming Ruby. The Pragmatic Programmer's Guide</title>
- <type>Book</type>
- <year>2000</year>
- </entry>
- <entry type="Book">
- <author>Blammo, Blah</author>
- <language>english</language>
- <publisher>Hubbabubba</publisher>
- <title>Foozboozer's Life</title>
- <type>Book</type>
- <year>2002</year>
- </entry>
-</biblio>
-DELIMITER
-
- # Tobias Reif <tobiasreif@pinkjuice.com>
- def test_bad_doctype_Tobias
- source = <<-EOF
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
- "http://www.w3.org/TR/SVG/DTD/svg10.dtd"
- [
- <!-- <!ENTITY % fast-slow "0 0 .5 1">-->
- <!--<!ENTITY % slow-fast ".5 0 1 1">-->
- <!ENTITY hover_ani
- '<animateTransform attributeName="transform"
- type="scale" restart="whenNotActive" values="1;0.96"
- dur="0.5s" calcMode="spline" keySplines="0 0 .5 1"
- fill="freeze" begin="mouseover"/>
- <animateTransform attributeName="transform"
- type="scale" restart="whenNotActive" values="0.96;1"
- dur="0.5s" calcMode="spline" keySplines=".5 0 1 1"
- fill="freeze" begin="mouseover+0.5s"/>'
- >
- ]
- >
- EOF
- doc = REXML::Document.new source
- doc.write(out="")
- assert(out[/>\'>/] != nil, "Couldn't find >'>")
- assert(out[/\]>/] != nil, "Couldn't find ]>")
- end
-
- # Peter Verhage
- def test_namespace_Peter
- source = <<-EOF
- <?xml version="1.0"?>
- <config:myprog-config xmlns:config="http://someurl/program/version">
- <!-- main options -->
- <config:main>
- <config:parameter name="name" value="value"/>
- </config:main>
- </config:myprog-config>
- EOF
- doc = REXML::Document.new source
- assert_equal "myprog-config", doc.root.name
- count = 0
- REXML::XPath.each(doc, "x:myprog-config/x:main/x:parameter",
- {"x"=>"http://someurl/program/version"}) { |element|
- assert_equal "name", element.attributes["name"]
- count += 1;
- }
- assert_equal 1, count
- assert_equal "myprog-config", doc.elements["config:myprog-config"].name
- end
-
- # Tobias Reif <tobiasreif@pinkjuice.com>
- def test_complex_xpath_Tobias
- source = <<-EOF
- <root>
- <foo>
- <bar style="baz"/>
- <blah style="baz"/>
- <blam style="baz"/>
- </foo>
- <wax>
- <fudge>
- <noodle/>
- </fudge>
- </wax>
- </root>
- EOF
- # elements that have child elements
- # but not grandchildren
- # and not children that don't have a style attribute
- # and not children that have a unique style attribute
- complex_path = "*[* "+
- "and not(*/node()) "+
- "and not(*[not(@style)]) "+
- "and not(*/@style != */@style)]"
- doc = REXML::Document.new source
- results = REXML::XPath.match( doc.root, complex_path )
- assert(results)
- assert_equal 1, results.size
- assert_equal "foo", results[0].name
- end
-
- # "Chris Morris" <chrismo@charter.net>
- def test_extra_newline_on_read_Chris
- text = 'test text'
- e = REXML::Element.new('Test')
- e.add_text(text)
- REXML::Formatters::Default.new.write(e,out="")
-
- doc = REXML::Document.new(out)
- outtext = doc.root.text
-
- assert_equal(text, outtext)
- end
-
- # Tobias Reif <tobiasreif@pinkjuice.com>
- def test_other_xpath_Tobias
- schema = <<-DELIM
- <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- elementFormDefault="qualified">
- <xs:element name="rect">
- <xs:complexType>
- <xs:attribute name="width" type="xs:byte" use="required"/>
- <xs:attribute name="height" type="xs:byte" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="svg">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="rect"/>
- </xs:sequence>
- </xs:complexType>
- </xs:element>
- </xs:schema>
- DELIM
-
- doc = REXML::Document.new schema
-
- result = REXML::XPath.first(doc.root, 'xs:element[descendant::xs:element[@ref]]')
- assert result
- assert_equal "svg", result.attributes['name']
- result = REXML::XPath.first(doc, 'element[descendant::element[@ref]]')
- assert_nil result
- end
-
- #this first test succeeds, to check if stuff is set up correctly
- def test_xpath_01_TobiasReif
- doc = Document.new XML_STRING_01.dup
- desired_result = Document.new '<author>Thomas, David; Hunt, Andrew</author>'
- xpath = '//author'
- result = XPath.first(doc, xpath)
- assert_equal desired_result.to_s, result.to_s
- end
-
- def test_xpath_whitespace_TobiasReif
- # same as above, with whitespace in XPath
- doc = Document.new(XML_STRING_01.dup)
- desired_result = Document.new('<author>Thomas, David; Hunt, Andrew</author>')
- xpath = "\/\/author\n \n"
- result = XPath.first(doc, xpath)
- failure_message = "\n[[[TR: AFAIK, whitespace should be allowed]]]\n"
- assert_equal(desired_result.to_s, result.to_s, failure_message)
- end
-
- def test_xpath_02_TobiasReif
- doc = Document.new XML_STRING_01.dup
- desired_result = Document.new '<author>Thomas, David; Hunt, Andrew</author>'
- # Could that quirky
- # Programmer',&quot;'&quot;,'s
- # be handled automatically, somehow?
- # Or is there a simpler way? (the below XPath should match the author element above,
- # AFAIK; I tested it inside an XSLT)
- xpath = %q{/biblio/entry[
- title/text()=concat('Programming Ruby. The Pragmatic Programmer',"'",'s Guide')
- and
- year='2000'
- ]/author}
- result = XPath.first(doc, xpath)
- failure_message = "\nHow to handle the apos inside the string inside the XPath?\nXPath = #{xpath}\n"
- assert_equal desired_result.to_s, result.to_s, failure_message
- end
-
- def test_xpath_03_TobiasReif
- doc = Document.new XML_STRING_02.dup
- desired_result_string = "<entry type='Book'>
- <language>english</language>
- <publisher>Addison-Wesley</publisher>
- <title>Programming Ruby. The Pragmatic Programmer's Guide</title>
- <type>Book</type>
- <year>2000</year>
- </entry>"
- Document.new desired_result_string
- xpath = "/biblio/entry[not(author)]"
- result = XPath.first(doc, xpath)
- assert_equal desired_result_string, result.to_s
- end
-
- def test_umlaut
- koln_iso = "K\xf6ln"
- koln_utf = "K\xc3\xb6ln"
- source_iso = "<?xml version='1.0' encoding='ISO-8859-1'?><test>#{koln_iso}</test>"
- source_utf = "<?xml version='1.0' encoding='UTF-8'?><test>#{koln_utf}</test>"
-
- if String.method_defined? :encode
- koln_iso.force_encoding('iso-8859-1')
- koln_utf.force_encoding('utf-8')
- source_iso.force_encoding('iso-8859-1')
- source_utf.force_encoding('utf-8')
- end
-
- doc = REXML::Document.new(source_iso)
- assert_equal('ISO-8859-1', doc.xml_decl.encoding)
- assert_equal(koln_utf, doc.root.text)
- doc.write(out="")
- assert_equal(source_iso, out )
- doc.xml_decl.encoding = 'UTF-8'
- doc.write(out="")
- assert_equal(source_utf, out)
-
- doc = Document.new <<-EOF
-<?xml version="1.0" encoding="ISO-8859-1"?>
-<intranet>
-<position><aktuell datum="01-10-11">Technik</aktuell></position>
-<hauptspalte>
-<headline>Technik</headline>
-Die Technik ist das R\xFCckgrat der meisten Gesch\xFCftsprozesse bei Home of the Brave. Deshalb sollen hier alle relevanten technischen Abl\xFCufe, Daten und Einrichtungen beschrieben werden, damit jeder im Bedarfsfall die n\xFCtigen Informationen, Anweisungen und Verhaltensempfehlungen nachlesen und/oder abrufen kann.
-</hauptspalte>
-<nebenspalte>
- <link ziel="Flash/">Flash</link><umbruch/>
- N\xFCtzliches von Flashern f\xFCr Flasher.<umbruch/>
- <link neu="ja" ziel="Cvs/">CVS-FAQ</link><umbruch/>
- FAQ zur Benutzung von CVS bei HOB
-</nebenspalte>
-</intranet>
-EOF
- tn = XPath.first(doc, "//nebenspalte/text()[2]")
- expected_iso = "N\xFCtzliches von Flashern f\xFCr Flasher."
- expected_utf = expected_iso.unpack('C*').pack('U*')
- expected_iso.force_encoding(::Encoding::ISO_8859_1)
- expected_utf.force_encoding(::Encoding::UTF_8)
- assert_equal(expected_utf, tn.to_s.strip)
- f = REXML::Formatters::Default.new
- f.write( tn, Output.new(o = "", "ISO-8859-1") )
- assert_equal(expected_iso, o.strip)
-
- doc = File.open(fixture_path('xmlfile-bug.xml')) {|file| Document.new file }
- tn = XPath.first(doc, "//nebenspalte/text()[2]")
- assert_equal(expected_utf, tn.to_s.strip)
- f.write( tn, Output.new(o = "", "ISO-8859-1") )
- assert_equal(expected_iso, o.strip)
- end
-
- def test_element_cloning_namespace_Chris
- aDoc = REXML::Document.new '<h1 tpl:content="title" xmlns:tpl="1">Dummy title</h1>'
-
- anElement = anElement = aDoc.elements[1]
- elementAttrPrefix = anElement.attributes.get_attribute('content').prefix
-
- aClone = anElement.clone
- cloneAttrPrefix = aClone.attributes.get_attribute('content').prefix
-
- assert_equal( elementAttrPrefix , cloneAttrPrefix )
- end
-
- def test_namespaces_in_attlist_tobias
- in_string = File.open(fixture_path('foo.xml'), 'r') do |file|
- file.read
- end
-
- doc = Document.new in_string
-
- assert_nil XPath.first(doc,'//leg')
- assert_equal 'http://www.foo.com/human', doc.root.elements[1].namespace
- assert_equal 'human leg',
- XPath.first(doc, '//x:leg/text()', {'x'=>'http://www.foo.com/human'}).to_s
- end
-
- # Alun ap Rhisiart
- def test_less_than_in_element_content
- doc = File.open(fixture_path('ProductionSupport.xml')) do |source|
- REXML::Document.new source
- end
- h = Hash.new
- doc.elements.each("//CommonError") { |el|
- h[el.elements['Key'].text] = 'okay'
- }
- assert(h.include?('MotorInsuranceContract(Object)>>#error:'))
- end
-
- # XPaths provided by Thomas Sawyer
- def test_various_xpath
- #@doc = REXML::Document.new('<r a="1"><p><c b="2"/></p></r>')
- doc = REXML::Document.new('<r a="1"><p><c b="2">3</c></p></r>')
-
- [['/r', REXML::Element],
- ['/r/p/c', REXML::Element],
- ['/r/attribute::a', Attribute],
- ['/r/@a', Attribute],
- ['/r/attribute::*', Attribute],
- ['/r/@*', Attribute],
- ['/r/p/c/attribute::b', Attribute],
- ['/r/p/c/@b', Attribute],
- ['/r/p/c/attribute::*', Attribute],
- ['/r/p/c/@*', Attribute],
- ['//c/attribute::b', Attribute],
- ['//c/@b', Attribute],
- ['//c/attribute::*', Attribute],
- ['//c/@*', Attribute],
- ['.//node()', REXML::Node ],
- ['.//node()[@a]', REXML::Element ],
- ['.//node()[@a="1"]', REXML::Element ],
- ['.//node()[@b]', REXML::Element ], # no show, why?
- ['.//node()[@b="2"]', REXML::Element ]
- ].each do |xpath,kind|
- begin
- REXML::XPath.each( doc, xpath ) do |what|
- assert_kind_of( kind, what, "\n\nWrong type (#{what.class}) returned for #{xpath} (expected #{kind.name})\n\n" )
- end
- rescue Exception
- puts "PATH WAS: #{xpath}"
- raise
- end
- end
-
- [
- ['/r', 'attribute::a', Attribute ],
- ['/r', '@a', Attribute ],
- ['/r', 'attribute::*', Attribute ],
- ['/r', '@*', Attribute ],
- ['/r/p/c', 'attribute::b', Attribute ],
- ['/r/p/c', '@b', Attribute ],
- ['/r/p/c', 'attribute::*', Attribute ],
- ['/r/p/c', '@*', Attribute ]
- ].each do |nodepath, xpath, kind|
- begin
- context = REXML::XPath.first(doc, nodepath)
- REXML::XPath.each( context, xpath ) do |what|
- assert_kind_of kind, what, "Wrong type (#{what.class}) returned for #{xpath} (expected #{kind.name})\n"
- end
- rescue Exception
- puts "PATH WAS: #{xpath}"
- raise
- end
- end
- end
-
- def test_entities_Holden_Glova
- document = <<-EOL
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE rubynet [
- <!ENTITY rbconfig.MAJOR "1">
- <!ENTITY rbconfig.MINOR "7">
- <!ENTITY rbconfig.TEENY "2">
- <!ENTITY rbconfig.ruby_version "&rbconfig.MAJOR;.&rbconfig.MINOR;">
- <!ENTITY rbconfig.arch "i386-freebsd5">
- <!ENTITY rbconfig.prefix "/usr/local">
- <!ENTITY rbconfig.libdir "&rbconfig.prefix;/lib">
- <!ENTITY rbconfig.includedir "&rbconfig.prefix;/include">
- <!ENTITY rbconfig.sitedir "&rbconfig.prefix;/lib/ruby/site_ruby">
- <!ENTITY rbconfig.sitelibdir "&rbconfig.sitedir;/&rbconfig.ruby_version;">
- <!ENTITY rbconfig.sitearchdir "&rbconfig.sitelibdir;/&rbconfig.arch;">
- ]>
- <rubynet>
- <pkg version="version1.0">
- <files>
- <file>
- <filename>uga.rb</filename>
- <mode>0444</mode>
- <path>&rbconfig.libdir;/rexml</path>
- <content encoding="xml">... the file here</content>
- </file>
- <file>
- <filename>booga.h</filename>
- <mode>0444</mode>
- <path>&rbconfig.includedir;</path>
- <content encoding="xml">... the file here</content>
- </file>
- <file>
- <filename>foo.so</filename>
- <mode>0555</mode>
- <path>&rbconfig.sitearchdir;/rexml</path>
- <content encoding="mime64">Li4uIHRoZSBmaWxlIGhlcmU=\n</content>
- </file>
- </files>
- </pkg>
- </rubynet>
- EOL
-
- file_xpath = '/rubynet/pkg/files/file'
-
- root = REXML::Document.new(document)
-
- root.elements.each(file_xpath) do |metadata|
- text = metadata.elements['path'].get_text.value
- assert text !~ /&rbconfig/, "'#{text}' failed"
- end
-
- #Error occurred in test_package_file_opens(TC_PackageInstall):
- # ArgumentError:
- #illegal access mode &rbconfig.prefix;/lib/rexml
- #
- #[synack@Evergreen] src $ ruby --version
- #ruby 1.6.7 (2002-03-01) [i686-linux-gnu]
- #
- #It looks like it expanded the first entity, but didn't reparse it for more
- #entities. possible bug - or have I mucked this up?
- end
-
- def test_whitespace_after_xml_decl
- Document.new <<EOL
-<?xml version='1.0'?>
- <blo>
- <wak>
- </wak>
-</blo>
-EOL
- end
-
- def test_external_entity
- xp = '//channel/title'
-
- %w{working.rss broken.rss}.each do |path|
- File.open(File.join(fixture_path(path))) do |file|
- doc = REXML::Document.new file.readlines.join('')
-
- # check to make sure everything is kosher
- assert_equal( doc.root.class, REXML::Element )
- assert_equal( doc.root.elements.class, REXML::Elements )
-
- # get the title of the feed
- assert( doc.root.elements[xp].kind_of?( REXML::Element ) )
- end
- end
- end
-
- def test_maintain_dtd
- src = %q{<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE ivattacks SYSTEM "../../ivacm.dtd" [
-<!ENTITY % extern-packages SYSTEM "../../ivpackages.dtd">
-<!ENTITY % extern-packages SYSTEM "../../common-declarations.dtd">
-%extern-packages;
-%extern-common;
-]>}
- doc = Document.new( src )
- doc.write( out="" )
- src = src.tr('"', "'")
- out = out.tr('"', "'")
- assert_equal( src, out )
- end
-
- def test_text_nodes_nomatch
- source = "<root><child>test</child></root>"
- d = REXML::Document.new( source )
- r = REXML::XPath.match( d, %q{/root/child[text()="no-test"]} )
- assert_equal( 0, r.size )
- end
-
- def test_raw_Terje_Elde
- f = REXML::Formatters::Default.new
- txt = 'abc&#248;def'
- a = Text.new( txt,false,nil,true )
- f.write(a,out="")
- assert_equal( txt, out )
-
- txt = '<sean><russell>abc&#248;def</russell></sean>'
- a = Document.new( txt, { :raw => ["russell"] } )
- f.write(a,out="")
- assert_equal( txt, out )
- end
-
- def test_indenting_error
- a=Element.new("test1")
- b=Element.new("test2")
- c=Element.new("test3")
- b << c
- a << b
-
- REXML::Formatters::Pretty.new.write(a,"")
- end
-
- def test_pos
- require 'tempfile'
- Tempfile.create("tidal") {|testfile|
- testdata = %Q{<calibration>
-<section name="parameters">
-<param name="barpress">760</param>
-<param name="hertz">50</param>
-</section>
-</calibration>
-}
-
- testfile.puts testdata
- testfile.rewind
- assert_nothing_raised do
- REXML::Document.new(testfile)
- end
- }
- end
-
- def test_deep_clone
- a = Document.new( '<?xml version="1.0"?><!DOCTYPE html PUBLIC
- "-//W3C//DTD
- XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html
- xmlns="http:///www.w3.org/1999/xhtml"></html>' )
- b = a.deep_clone
- assert_equal a.to_s, b.to_s
- end
-
- def test_double_escaping
- data = '<title>AT&amp;T</title>'
- xml = "<description><![CDATA[#{data}]]></description>"
-
- doc = REXML::Document.new(xml)
- description = doc.find {|e| e.name=="description"}
- assert_equal data, description.text
- end
-
- def test_ticket_12
- cfg = "<element><anotherelement><child1>a</child1><child2>b</child2></anotherelement></element>"
-
- config = REXML::Document.new( cfg )
-
- assert_equal( "a", config.elements[ "//child1" ].text )
- end
-
-=begin
- # This is a silly test, and is low priority
- def test_namespace_serialization_tobi_reif
- doc = Document.new '<doc xmlns:b="http://www.foo.foo">
- <b:p/>
- </doc>'
- ns = 'http://www.foo.foo'
- ns_declaration={'f'=>ns}
- returned = XPath.match(doc,'//f:p',ns_declaration)
- # passes:
- assert( (returned[0].namespace==ns), 'namespace should be '+ns)
- serialized = returned.to_s
- serialized_and_parsed = Document.new(serialized)
- puts 'serialized: '+serialized
- # ... currently brings <b:p/>
- # prefix b is undeclared (!)
- assert( (serialized_and_parsed.namespace==ns),
- 'namespace should still be '+ns.inspect+
- ' and not '+serialized_and_parsed.namespace.inspect)
- # ... currently results in a failure:
- # 'namespace should still be "http://www.foo.foo" and not ""'
- end
-=end
- end
-end
diff --git a/test/rexml/test_core.rb b/test/rexml/test_core.rb
deleted file mode 100644
index 26e5ecd22e..0000000000
--- a/test/rexml/test_core.rb
+++ /dev/null
@@ -1,1517 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "rexml_test_utils"
-
-require "rexml/document"
-require "rexml/parseexception"
-require "rexml/output"
-require "rexml/source"
-require "rexml/formatters/pretty"
-require "rexml/undefinednamespaceexception"
-
-require_relative "listener"
-
-module REXMLTests
- class Tester < Test::Unit::TestCase
- include REXMLTestUtils
- include REXML
- def setup
- @xsa_source = <<-EOL
- <?xml version="1.0"?>
- <?xsl stylesheet="blah.xsl"?>
- <!-- The first line tests the XMLDecl, the second tests PI.
- The next line tests DocType. This line tests comments. -->
- <!DOCTYPE xsa PUBLIC
- "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML"
- "http://www.garshol.priv.no/download/xsa/xsa.dtd">
-
- <xsa>
- <vendor id="blah">
- <name>Lars Marius Garshol</name>
- <email>larsga@garshol.priv.no</email>
- <url>http://www.stud.ifi.uio.no/~lmariusg/</url>
- </vendor>
- </xsa>
- EOL
- end
-
- def test_bad_markup
- [
- "<pkg='version'> foo </pkg>",
- '<0/>',
- '<a>&</a>',
- '<a>&a</a>',
-# '<a>&a;</a>', # FIXME
- '<a a="<"/>',
- '<a 3="<"/>',
- '<a a="1" a="2"/>',
- '<a><!-- -- --></a>',
- '<a><!-- ---></a>',
- '<a>&#x00;</a>',
- '<a>&#0;</a>',
- "<a a='&#0;' />",
- "<a>\f</a>",
- "<a a='\f' />",
- "<a>\000</a>",
-# FIXME '<a' + [65535].pack('U') + ' />',
- '<a>&#xfffe;</a>',
- '<a>&#65535;</a>',
-# FIXME '<a' + [0x0371].pack('U') + ' />',
-# FIXME '<a a' + [0x0371].pack('U') + '="" />',
- ].each do |src|
- assert_raise( ParseException, %Q{Parse #{src.inspect} should have failed!} ) do
- Document.new(src)
- end
- end
- end
-
- def test_attribute
- # Testing constructors
- #a = Attribute.new "hello", "dolly"
- #b = Attribute.new a
- #d = Document.new( "<a hello='dolly' href='blah'/>" )
- #c = d[0].attributes.get_attribute( "hello" )
-
- #assert_equal a, b
- #for attr in [ a, b, c]
- # assert_equal "hello", attr.name
- # assert_equal "dolly", attr.value
- #end
-
- # This because of a reported bug in attribute handling in 1.0a8
- source = '<a att="A">blah</a>'
- doc = Document.new source
- doc.elements.each do |a|
- a.attributes['att'] << 'B'
- assert_equal "AB", a.attributes['att']
- a.attributes['att'] = 'C'
- assert_equal "C", a.attributes['att']
- end
-
- # Bryan Murphy <murphybryanp@yahoo.com>
- text = "this is a {target[@name='test']/@value} test"
- source = <<-EOL
- <?xml version="1.0"?>
- <doc search="#{text}"/>
- EOL
-
- xml = Document.new source
- value = xml.root.attributes["search"]
- assert_equal text, value.to_s
-
- e = Element.new "test"
- e.add_attributes({ "name1" => "test1", "name4" => "test4" })
- e.add_attributes([["name3","test3"], ["name2","test2"]])
- assert_equal "test1", e.attributes["name1"]
- assert_equal "test2", e.attributes["name2"]
- assert_equal "test3", e.attributes["name3"]
- assert_equal "test4", e.attributes["name4"]
-
- # ensure that the attributes come out in sorted order
- assert_equal %w(<test
- name1='test1'
- name2='test2'
- name3='test3'
- name4='test4'/>).join(' '), e.to_s
- end
-
- def test_attribute_namespace_conflict
- # https://www.w3.org/TR/xml-names/#uniqAttrs
- message = <<-MESSAGE
-Duplicate attribute "a"
-Line: 4
-Position: 140
-Last 80 unconsumed characters:
- MESSAGE
- assert_raise_with_message(REXML::ParseException, message) do
- Document.new(<<-XML)
-<!-- http://www.w3.org is bound to n1 and n2 -->
-<x xmlns:n1="http://www.w3.org"
- xmlns:n2="http://www.w3.org" >
- <bad a="1" a="2" />
- <bad n1:a="1" n2:a="2" />
-</x>
- XML
- end
- end
-
- def test_attribute_default_namespace
- # https://www.w3.org/TR/xml-names/#uniqAttrs
- document = Document.new(<<-XML)
-<!-- http://www.w3.org is bound to n1 and is the default -->
-<x xmlns:n1="http://www.w3.org"
- xmlns="http://www.w3.org" >
- <good a="1" b="2" />
- <good a="1" n1:a="2" />
-</x>
- XML
- attributes = document.root.elements.collect do |element|
- element.attributes.each_attribute.collect do |attribute|
- [attribute.prefix, attribute.namespace, attribute.name]
- end
- end
- assert_equal([
- [
- ["", "", "a"],
- ["", "", "b"],
- ],
- [
- ["", "", "a"],
- ["n1", "http://www.w3.org", "a"],
- ],
- ],
- attributes)
- end
-
- def test_cdata
- test = "The quick brown fox jumped
- & < & < \" '
- over the lazy dog."
-
- source = "<a><![CDATA[#{test}]]></a>"
- d = REXML::Document.new( source )
-
- # Test constructors
- cdata = d[0][0]
- assert_equal test, cdata.value
- end
-
- def test_comment
- string = "This is a new comment!"
- source = "<!--#{string}-->"
- comment = Comment.new string
- REXML::Formatters::Default.new.write( comment, out = "" )
- assert_equal(source, out)
-
- comment2 = Comment.new comment
- assert_equal(comment, comment2)
-
- assert_raise(ParseException) {
- REXML::Document.new("<d><!- foo --></d>")
- }
- assert_raise(ParseException) {
- REXML::Document.new("<d><!-- foo -></d>")
- }
- end
-
- def test_whitespace
- doc = Document.new "<root-element><first-element/></root-element>"
- assert_equal 1, doc.root.size
- assert_equal 1, doc.root.elements.size
- doc = Document.new "<root-element>
- <first-element/>
- </root-element>"
- assert_equal 3, doc.root.size
- assert_equal 1, doc.root.elements.size
-
- text = " This is text
- with a lot of whitespace "
- source = "<a>#{text}<b>#{text}</b><c>#{text}</c>#{text}</a>"
-
- doc = Document.new( source, {
- :respect_whitespace => %w{ a c }
- } )
- assert_equal text, doc.elements["//c"].text
- string = ""
- doc.root.each { |n| string << n.to_s if n.kind_of? Text }
- assert_equal text+text, string
-
- string =" lots of blank
- space"
- doc.root.add_element("d").add_element("c").text = string
- doc.root.add_element("e").text = string
- assert_equal string, doc.elements["/a/d/c"].text
- assert string != doc.elements["/a/e"].text, "Text wasn't properly compressed"
-
- doc = Document.new source, { :respect_whitespace => :all }
- doc.root.add_element("d").text = string
- assert_equal text, doc.root.text
- nxt = ""
- doc.root.each { |n| nxt << n.to_s if n.kind_of? Text }
- assert_equal text+text, nxt
- assert_equal text, doc.root.elements["b"].text
- assert_equal text, doc.root.elements["c"].text
- assert_equal string, doc.root.elements["d"].text
- end
-
- # This isn't complete. We need to check declarations and comments
- def test_doctype
- string = "something"
- correct = "<!DOCTYPE something>"
- doc = DocType.new(string)
- assert_equal(string, doc.name)
- doc.write(out="")
- assert_equal(correct, out)
-
- doc2 = DocType.new(doc)
- assert_equal(doc.name, doc2.name)
- assert_equal(doc.external_id, doc2.external_id)
-
- correct = '<!DOCTYPE xsa PUBLIC "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML" "http://www.garshol.priv.no/download/xsa/xsa.dtd">'
-
- one_line_source = '<!DOCTYPE xsa PUBLIC "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML" "http://www.garshol.priv.no/download/xsa/xsa.dtd"><a/>'
- doc = Document.new( one_line_source )
- doc = doc[0]
- assert(doc)
- doc.write(test="")
- assert_equal(correct, test)
-
- multi_line_source = '<!DOCTYPE xsa PUBLIC
- "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML"
- "http://www.garshol.priv.no/download/xsa/xsa.dtd">
- <a/>'
- d = Document.new( multi_line_source )
- doc = d[0]
- assert(doc)
- doc.write(test="")
- assert_equal(correct, test)
-
- odd_space_source = ' <!DOCTYPE
- xsa PUBLIC "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML"
- "http://www.garshol.priv.no/download/xsa/xsa.dtd"> <a/>'
- d = Document.new( odd_space_source )
- dt = d.doctype
- dt.write(test="")
- assert_equal(correct, test)
-
- # OK, the BIG doctype test, numba wun
- doc = File.open(fixture_path("doctype_test.xml")) do |docin|
- Document.new(docin)
- end
- doc.write(test="")
- assert_equal(31, doc.doctype.size)
- end
-
- def test_document
- # Testing cloning
- source = "<element/>"
- doc = Document.new source
-
- # Testing Root
- assert_equal doc.root.name.to_s, "element"
-
- # Testing String source
- source = @xsa_source
- doc = Document.new source
- assert_instance_of XMLDecl, doc.xml_decl
- assert_instance_of DocType, doc.doctype
- assert_equal doc.version, "1.0"
-
- doc = File.open(fixture_path("dash.xml")) {|s| Document.new s }
- assert_equal "content-2", doc.elements["//content-2"].name
- end
-
- def test_instruction
- target = "use"
- content = "ruby"
- source = "<?#{target} #{content}?>"
-
- instruction = Instruction.new target, content
- instruction2 = Instruction.new instruction
- assert_equal(instruction, instruction2)
- REXML::Formatters::Default.new.write( instruction, out = "" )
- assert_equal(source, out)
-
- d = Document.new( source )
- instruction2 = d[0]
- assert_equal(instruction.to_s, instruction2.to_s)
-
- assert_raise(ParseException) {
- REXML::Document.new("<d><?foo bar></d>")
- }
- end
-
- def test_parent
- parent = Parent.new
- begin
- parent << "Something"
- rescue Exception
- parent << Comment.new("Some comment")
- assert parent.size == 1, "size of parent should be 1"
- else
- assert_fail "should have gotten an exception trying to add a "+ "String to a Parent"
- end
-
- source = "<a><one/><three/><five/></a>"
- doc = Document.new source
- three = doc.root.elements["three"]
- doc.root.insert_before( three, Element.new("two") )
- nxt = doc.root.elements["one"]
- string = ""
- while nxt
- string << nxt.name
- nxt = nxt.next_sibling
- end
- assert_equal "onetwothreefive", string
-
-
- doc.root.insert_after( three, Element.new("four") )
- string = ""
- doc.root.each { |element| string << element.name }
- assert_equal "onetwothreefourfive", string
-
- string = ""
- nxt = doc.root.elements["five"]
- while nxt
- string << nxt.name
- nxt = nxt.previous_sibling
- end
- assert_equal "fivefourthreetwoone", string
-
- doc.insert_after "//two", Element.new("two-and-half")
- string = doc.root.elements.collect {|x| x.name}.join
- assert_equal "onetwotwo-and-halfthreefourfive", string
- doc.elements["/a/five"].insert_before "../four", Element.new("three-and-half")
- string = doc.root.elements.collect {|x| x.name}.join
- assert_equal "onetwotwo-and-halfthreethree-and-halffourfive", string
-
- doc.elements["/a/five"].previous_sibling = Element.new("four-and-half")
- string = doc.root.elements.collect {|x| x.name}.join
- assert_equal "onetwotwo-and-halfthreethree-and-halffourfour-and-halffive", string
- doc.elements["/a/one"].next_sibling = Element.new("one-and-half")
- string = doc.root.elements.collect {|x| x.name}.join
- assert_equal "oneone-and-halftwotwo-and-halfthreethree-and-halffourfour-and-halffive", string
-
- doc = Document.new "<a><one/><three/></a>"
- doc.root[1,0] = Element.new "two"
- string = ""
- doc.root.each { |el| string << el.name }
- assert_equal "onetwothree", string
- end
-
- # The Source classes are tested extensively throughout the test suite
- def test_source
- # Testing string source
- source = @xsa_source
- doc = Document.new source
- assert_equal doc.root.name.to_s, "xsa"
-
- # Testing IO source
- doc = File.open(fixture_path("project.xml")) {|f| Document.new f }
- assert_equal doc.root.name.to_s, "Project"
- end
-
- def test_text
- f = REXML::Formatters::Default.new
- string = "Some text"
- text = Text.new(string)
- assert_equal(string, text.to_s)
- text2 = Text.new(text)
- assert_equal(text, text2)
- #testing substitution
- string = "0 < ( 1 & 1 )"
- correct = "0 &lt; ( 1 &amp; 1 )"
- text = Text.new(string, true)
- f.write(text,out="")
- assert_equal(correct, out)
-
- string = "Cats &amp; dogs"
- text = Text.new(string, false, nil, true)
- assert_equal(string, text.to_s)
-
- string2 = "<a>#{string}</a>"
- doc = Document.new( string2, {
- :raw => %w{ a b }
- } )
- f.write(doc,out="")
- assert_equal(string2, out)
- b = doc.root.add_element( "b" )
- b.text = string
- assert_equal(string, b.get_text.to_s)
-
- c = doc.root.add_element("c")
- c.text = string
- assert_equal("Cats &amp;amp; dogs", c.get_text.to_s)
-
- # test all
- string = "<a>&amp;<b>&lt;</b><c>&gt;<d>&quot;</d></c></a>"
- doc = Document.new(string, { :raw => :all })
- assert_equal( "&amp;", doc.elements["/a"][0].to_s )
- assert_equal( "&", doc.elements["/a"].text )
- assert_equal( "&lt;", doc.elements["/a/b"][0].to_s )
- assert_equal( "<", doc.elements["/a/b"].text )
- assert_equal( "&gt;", doc.elements["/a/c"][0].to_s )
- assert_equal( ">", doc.elements["/a/c"].text )
- assert_equal( '&quot;', doc.elements["//d"][0].to_s )
- assert_equal( '"', doc.elements["//d"].text )
-
- # test some other stuff
- doc = Document.new('<a><b/></a>')
- doc.root.text = 'Sean'
- assert_equal( '<a><b/>Sean</a>', doc.to_s )
- doc.root.text = 'Elliott'
- assert_equal( '<a><b/>Elliott</a>', doc.to_s )
- doc.root.add_element( 'c' )
- assert_equal( '<a><b/>Elliott<c/></a>', doc.to_s )
- doc.root.text = 'Russell'
- assert_equal( '<a><b/>Russell<c/></a>', doc.to_s )
- doc.root.text = nil
- assert_equal( '<a><b/><c/></a>', doc.to_s )
- end
-
- def test_text_frozen
- string = "Frozen".freeze
- text = Text.new(string)
- assert_equal(string, text.to_s)
- end
-
- def test_xmldecl
- source = "<?xml version='1.0'?>"
- # test args
- # test no args
- decl2 = XMLDecl.new
- assert_equal source, decl2.to_s
- # test XMLDecl
- decl2 = XMLDecl.new "1.0"
- assert_equal source, decl2.to_s
- end
-
- def test_xmldecl_utf_16be_encoding_name
- assert_equal("<?xml version='1.0' encoding='UTF-16'?>",
- XMLDecl.new("1.0", "UTF-16").to_s)
- end
-
- def each_test( element, xpath, num_children )
- count = 0
- element.each_element( xpath ) { |child|
- count += 1
- yield child if block_given?
- }
- assert_equal num_children, count
- end
-
- # This is the biggest test, as the number of permutations of xpath are
- # enormous.
- def test_element_access
- # Testing each_element
- doc = File.open(fixture_path("project.xml")) {|f| Document.new f }
-
- each_test( doc, "/", 1 ) { |child|
- assert_equal doc.name, child.name
- }
- each_test(doc, ".", 1) { |child| assert_equal doc, child }
- each_test(doc.root, "..", 1) { |child| assert_equal doc, child }
- each_test(doc.root, "*", 5)
- each_test(doc, "Project/Datasets", 1) { |child|
- assert_equal "Datasets", child.name
- }
- each_test(doc, "Project/Datasets/link", 2 )
- each_test(doc.root, "/Project/Description", 1) {|child|
- assert_equal "Description", child.name
- }
- each_test(doc.root, "./Description",1 ) { |child|
- assert_equal "Description",child.name
- }
- each_test(doc.root, "../Project",1 ) { |child|
- assert_equal doc.root, child
- }
- #each_test(doc,".../link",2) {|child| assert_equal "link",child.name.to_s}
-
- # test get_element
- first = doc.elements[ "Project" ]
- assert_equal doc.root, first
- second = doc.elements[ "Project" ].elements[1]
- third = doc.elements[ "Project/Creator" ]
- assert_equal second, third
- fourth = doc.elements[ "Project/Datasets/link[@idref='18']" ]
- assert_equal "Test data 1", fourth.attributes["name"]
-
- # Testing each_predicate
- each_test( doc, "Project/Datasets/link[@idref='18']", 1 ) { |child|
- assert_equal "Test data 1", child.attributes["name"]
- }
-
- # testing next/previous_element
- creator = doc.elements["//Creator"]
- lm = creator.next_element
- assert_equal "LastModifier", lm.name
- assert_equal "Creator", lm.previous_element.name
- end
-
- def test_child
- sean = Element.new "Sean"
- rubbell = Element.new "Rubbell"
- elliott = sean.add_element "Elliott"
- sean << rubbell
- assert_equal elliott, rubbell.previous_sibling
- assert_equal rubbell, elliott.next_sibling
-
- russell = Element.new "Russell"
- rubbell.replace_with russell
- assert_equal elliott, russell.previous_sibling
- assert_equal russell, elliott.next_sibling
-
- assert_nil russell.document
- assert_equal sean, russell.root
- end
-
- # Most of this class is tested elsewhere. Here are the methods which
- # aren't used in any other class
- def test_element
- sean = Element.new "Sean"
- string = "1) He's a great guy!"
- sean.text = string
- russell = Element.new "Russell"
- sean << russell
-
- russell.attributes["email"] = "ser@germane-software.com"
- assert_equal russell.attributes["email"], "ser@germane-software.com"
- russell.attributes["webpage"] = "http://www.germane-software.com/~ser"
-
- assert sean.has_text?, "element should have text"
- assert_equal sean.text, string
- assert sean.has_elements?, "element should have one element"
- string = "2) What a stud!"
- sean.add_text string
- sean.text = "3) Super programmer!"
- sean.text = nil
- assert sean.has_text?, "element should still have text"
- assert_equal sean.text, string
-
- russell.delete_attribute "email"
- assert_nil russell.attributes["email"]
- russell.attributes.delete "webpage"
- assert !russell.has_attributes?, "element should have no attributes"
- end
-
- def test_no_format
- source = "<a><b><c>blah</c><d/></b></a>"
- out = ""
- doc = Document.new( source )
- doc.write(out)
- assert_equal(source, out)
- end
-
- def test_namespace
- source = <<-EOF
- <x xmlns:foo="http://www.bar.com/schema">
- </x>
- EOF
- doc = Document.new(source)
- assert_equal("http://www.bar.com/schema", doc.root.namespace( "foo" ))
- source = <<-EOF
- <!-- bar namespace is "someuri" -->
- <foo:bar xmlns="default" xmlns:foo="someuri">
- <!-- a namespace is "default" -->
- <a/>
- <!-- foo:b namespace is "someuri" -->
- <foo:b>
- <!-- c namespace is "default" -->
- <c/>
- </foo:b>
- <!-- d namespace is "notdefault" -->
- <d xmlns="notdefault">
- <!-- e namespace is "notdefault" -->
- <e/>
- <f xmlns="">
- <g/>
- </f>
- </d>
- </foo:bar>
- EOF
- doc = Document.new source
- assert_equal "someuri", doc.root.namespace
- assert_equal "default", doc.root.elements[1].namespace
- assert_equal "someuri", doc.root.elements[2].namespace
- assert_equal "notdefault", doc.root.elements[ 3 ].namespace
-
- # Testing namespaces in attributes
- source = <<-EOF
- <a xmlns:b="uri">
- <b b:a="x" a="y"/>
- <c xmlns="foo">
- </c>
- </a>
- EOF
- doc = Document.new source
- b = doc.root.elements["b"]
- assert_equal "x", b.attributes["b:a"]
- assert_equal "y", b.attributes["a"]
-
- doc = Document.new
- doc.add_element "sean:blah"
- doc.root.text = "Some text"
- out = ""
- doc.write(out)
- assert_equal "<sean:blah>Some text</sean:blah>", out
- end
-
-
- def test_add_namespace
- e = Element.new 'a'
- e.add_namespace 'someuri'
- e.add_namespace 'foo', 'otheruri'
- e.add_namespace 'xmlns:bar', 'thirduri'
- assert_equal 'someuri', e.attributes['xmlns']
- assert_equal 'otheruri', e.attributes['xmlns:foo']
- assert_equal 'thirduri', e.attributes['xmlns:bar']
- end
-
-
- def test_big_documentation
- d = File.open(fixture_path("documentation.xml")) {|f| Document.new f }
- assert_equal "Sean Russell", d.elements["documentation/head/author"].text.tr("\n\t", " ").squeeze(" ")
- out = ""
- d.write out
- end
-
- def test_tutorial
- doc = File.open(fixture_path("tutorial.xml")) {|f| Document.new f }
- out = ""
- doc.write out
- end
-
- def test_stream
- c = Listener.new
- File.open(fixture_path("documentation.xml")) do |f|
- Document.parse_stream( f, c )
- end
- assert(c.ts, "Stream parsing apparently didn't parse the whole file")
- assert(c.te, "Stream parsing dropped end tag for documentation")
-
- Document.parse_stream("<a.b> <c/> </a.b>", c)
-
- Document.parse_stream("<a>&lt;&gt;&amp;</a>", c)
- assert_equal('<>&', c.normalize)
- end
-
- def test_line
- f = File.new(fixture_path("bad.xml"))
- Document.new f
- assert_fail "There should have been an error"
- rescue Exception
- # We should get here
- assert($!.line == 5, "Should have been an error on line 5, "+
- "but was reported as being on line #{$!.line}" )
- ensure
- f.close if f
- end
-
- def test_substitution
- val = "a'b\"c"
- el = Element.new("a")
- el.attributes["x"] = val
- REXML::Formatters::Default.new.write(el, out="")
-
- nel = Document.new( out)
- assert_equal( val, nel.root.attributes["x"] )
- end
-
- def test_exception
- source = SourceFactory.create_from "<a/>"
- p = ParseException.new( "dummy message", source )
- begin
- raise "dummy"
- rescue Exception
- p.continued_exception = $!
- end
- end
-
- def test_bad_content
- in_gt = '<root-el>content>content</root-el>'
- in_lt = '<root-el>content<content</root-el>'
-
- # This is OK
- tree_gt = Document.new in_gt
- assert_equal "content>content", tree_gt.elements[1].text
- # This isn't
- begin
- Document.new in_lt
- assert_fail "Should have gotten a parse error"
- rescue ParseException
- end
- end
-
- def test_iso_8859_1_output_function
- out = ""
- output = Output.new( out )
- koln_iso_8859_1 = "K\xF6ln"
- koln_utf8 = "K\xc3\xb6ln"
- source = Source.new( koln_iso_8859_1, 'iso-8859-1' )
- results = source.scan(/.*/)[0]
- koln_utf8.force_encoding('UTF-8') if koln_utf8.respond_to?(:force_encoding)
- assert_equal koln_utf8, results
- output << results
- if koln_iso_8859_1.respond_to?(:force_encoding)
- koln_iso_8859_1.force_encoding('ISO-8859-1')
- end
- assert_equal koln_iso_8859_1, out
- end
-
- def test_attributes_each
- doc = Document.new("<a xmlns:a='foo'><b x='1' y='2' z='3' a:x='4'/></a>")
- count = 0
- doc.root.elements[1].attributes.each {|k,v| count += 1 }
- assert_equal 4, count
- end
-
- def test_delete_namespace
- doc = Document.new "<a xmlns='1' xmlns:x='2'/>"
- doc.root.delete_namespace
- doc.root.delete_namespace 'x'
- assert_equal "<a/>", doc.to_s
- end
-
- def test_each_element_with_attribute
- doc = Document.new "<a><b id='1'/><c id='2'/><d id='1'/><e/></a>"
- arry = []
- block = proc { |e|
- assert arry.include?(e.name)
- arry.delete e.name
- }
- # Yields b, c, d
- arry = %w{b c d}
- doc.root.each_element_with_attribute( 'id', &block )
- assert_equal 0, arry.size
- # Yields b, d
- arry = %w{b d}
- doc.root.each_element_with_attribute( 'id', '1', &block )
- assert_equal 0, arry.size
- # Yields b
- arry = ['b']
- doc.root.each_element_with_attribute( 'id', '1', 1, &block )
- assert_equal 0, arry.size
- # Yields d
- arry = ['d']
- doc.root.each_element_with_attribute( 'id', '1', 0, 'd', &block )
- assert_equal 0, arry.size
- end
- def test_each_element_with_text
- doc = Document.new '<a><b>b</b><c>b</c><d>d</d><e/></a>'
- arry = []
- block = proc { |e|
- assert arry.include?(e.name)
- arry.delete e.name
- }
- # Yields b, c, d
- arry = %w{b c d}
- doc.root.each_element_with_text(&block)
- assert_equal 0, arry.size
- # Yields b, d
- arry = %w{b c}
- doc.root.each_element_with_text( 'b', &block )
- assert_equal 0, arry.size
- # Yields b
- arry = ['b']
- doc.root.each_element_with_text( 'b', 1, &block )
- assert_equal 0, arry.size
- # Yields d
- arry = ['d']
- doc.root.each_element_with_text( nil, 0, 'd', &block )
- assert_equal 0, arry.size
- end
-
- def test_element_parse_stream
- s = Source.new( "<a>some text</a>" )
- l = Listener.new
- class << l
- def tag_start name, attributes
- raise "Didn't find proper tag name" unless 'a'==name
- end
- end
-
- Document::parse_stream(s, l)
- end
-
- def test_deep_clone
- a = Document.new( '<?xml version="1"?><a x="y"><b>text</b>text<c><d><e>text</e></d></c></a>' )
- b = a.deep_clone
- assert_equal a.to_s, b.to_s
-
- a = Document.new( '<a>some &lt; text <b> more &gt; text </b> &gt; </a>' )
- b = a.deep_clone
- assert_equal a.to_s, b.to_s
- c = Document.new( b.to_s )
- assert_equal a.to_s, c.to_s
- end
-
- def test_whitespace_before_root
- a = <<EOL
-<?xml version='1.0'?>
- <blo>
- <wak>
- </wak>
- </blo>
-EOL
- d = Document.new(a)
- b = ""
- d.write( b )
- assert_equal a,b
- end
-
- def test_entities
- a = Document.new( '<a>&#101;&#x65;&#252;</a>' )
- assert_equal('eeü'.force_encoding("UTF-8"), a.root.text)
- end
-
- def test_element_decl
- element_decl = Source.new("<!DOCTYPE foo [
-<!ELEMENT bar (#PCDATA)>
-]>")
- doc = Document.new( element_decl )
- d = doc[0]
- assert_equal("<!ELEMENT bar (#PCDATA)>", d.to_s.split(/\n/)[1].strip)
- end
-
- def test_attlist_decl
- doc = Document.new <<-EOL
- <!DOCTYPE blah [
- <!ATTLIST blah
- xmlns CDATA "foo">
- <!ATTLIST a
- bar CDATA "gobble"
- xmlns:one CDATA "two"
- >
- ]>
- <a xmlns:three='xxx' three='yyy'><one:b/><three:c/></a>
- EOL
- assert_equal 'gobble', doc.root.attributes['bar']
- assert_equal 'xxx', doc.root.elements[2].namespace
- assert_equal 'two', doc.root.elements[1].namespace
- assert_equal 'foo', doc.root.namespace
-
- doc = Document.new <<-EOL
- <?xml version="1.0"?>
- <!DOCTYPE schema SYSTEM "XMLSchema.dtd" [
- <!ENTITY % p ''>
- <!ENTITY % s ''>
- <!ATTLIST schema
- xmlns:svg CDATA #FIXED "http://www.w3.org/2000/svg"
- xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink"
- xmlns:xml CDATA #FIXED "http://www.w3.org/XML/1998/namespace"
- >]>
- <schema/>
- EOL
- prefixes = doc.root.prefixes.sort
- correct = ['svg', 'xlink', 'xml']
- assert_equal correct, prefixes
- end
-
- def test_attlist_write
- doc = File.open(fixture_path("foo.xml")) {|file| Document.new file }
- out = ''
- doc.write(out)
- end
-
- def test_more_namespaces
- assert_raise( REXML::UndefinedNamespaceException,
- %Q{Should have gotten an Undefined Namespace error} ) {
- Document.new("<r><p><n:c/></p></r>")
- }
- doc2 = Document.new("<r xmlns:n='1'><p><n:c/></p></r>")
- es = XPath.match(doc2, '//c')
- assert_equal 0, es.size
- es = XPath.match(doc2, '//n:c')
- assert_equal 1, es.size
- doc2.root.add_namespace('m', '2')
- doc2.root.add_element("m:o")
- es = XPath.match(doc2, './/o')
- assert_equal 0, es.size
- es = XPath.match(doc2, '//n:c')
- assert_equal 1, es.size
- end
-
- def test_ticket_51
- doc = REXML::Document.new <<-EOL
- <test xmlns='1' xmlns:x='1'>
- <a>X</a>
- <x:a>Y</x:a>
-
- <b xmlns='2'>
- <a>Z</a>
- </b>
- </test>
- EOL
-
- # The most common case. People not caring about the namespaces much.
- assert_equal( "XY", XPath.match( doc, "/*:test/*:a/text()" ).join )
- assert_equal( "XY", XPath.match( doc, "/*:test/x:a/text()" ).join )
- # Surprising? I don't think so, if you believe my definition of the "common case"
- assert_equal( "XYZ", XPath.match( doc, "//*:a/text()" ).join )
-
- # These are the uncommon cases. Namespaces are actually important, so we define our own
- # mappings, and pass them in.
- assert_equal( "XY", XPath.match( doc, "/f:test/f:a/text()", { "f" => "1" } ).join )
- # The namespaces are defined, and override the original mappings
- assert_equal( "XY", XPath.match( doc, "/*:test/*:a/text()", { "f" => "1" } ).join )
- assert_equal( "", XPath.match( doc, "/x:test/x:a/text()", { "f" => "1" } ).join )
- assert_equal( "XYZ", XPath.match( doc, "//*:a/text()", { "f" => "1" } ).join )
- end
-
- def test_processing_instruction
- d = Document.new("<a><?foo bar?><?foo2 bar2?><b><?foo3 bar3?></b><?foo4 bar4?></a>")
- assert_equal 4, XPath.match(d, '//processing-instruction()' ).size
- match = XPath.match(d, "//processing-instruction('foo3')" )
- assert_equal 1, match.size
- assert_equal 'bar3', match[0].content
- end
-
- def test_oses_with_bad_EOLs
- Document.new("\n\n\n<?xml version='1.0'?>\n\n\n<a/>\n\n")
- end
-
- # Contributed (with patch to fix bug) by Kouhei
- def test_ignore_whitespace
- source = "<a> <b/> abc <![CDATA[def]]> </a>"
-
- context_all = {:ignore_whitespace_nodes => :all}
- context_a = {:ignore_whitespace_nodes => %(a)}
- context_b = {:ignore_whitespace_nodes => %(b)}
-
- tests = [[[" abc ", "def"], context_all],
- [[" abc ", "def"], context_a],
- [[" ", " abc ", "def", " "], context_b]]
-
- tests.each do |test|
- assert_equal(test[0], Document.new(source, test[1]).root.texts.collect{|x|
- x.to_s})
- end
- end
-
- def test_0xD_in_preface
- doc = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\x0D<opml version=\"1.0\">\x0D</opml>"
- doc = Document.new doc
- end
-
- def test_hyphens_in_doctype
- doc = REXML::Document.new <<-EOQ
- <?xml version="1.0"?>
- <!DOCTYPE a-b-c>
- <a-b-c>
- <a/>
- </a-b-c>
- EOQ
-
- assert_equal('a-b-c', doc.doctype.name)
- end
-
- def test_accents
- docs = [
- %Q{<?xml version="1.0" encoding="ISO-8859-1"?>
-<gnuPod>
-<files>
- <file id="57" artist="Coralie Cl\357\277\275ent" />
-</files>
-</gnuPod>},
- '<?xml version="1.0" encoding="ISO-8859-1"?>
-<gnuPod>
-<files>
- <file id="71" album="Astrakan Caf" />
-</files>
-</gnuPod>',
- %Q{<?xml version="1.0" encoding="ISO-8859-1"?>
-<gnuPod>
-<files>
- <file id="71" album="Astrakan Caf\357\277\275eria" />
-</files>
-</gnuPod>},
- %Q{<?xml version="1.0" encoding="ISO-8859-1"?>
-<gnuPod>
-<files>
- <file id="71" album="Astrakan Caf\357\277\275" />
-</files>
-</gnuPod>} ]
- docs.each_with_index { |d,i|
- begin
- REXML::Document.new(d)
- rescue
- puts "#{i} => #{docs[i]}"
- raise
- end
- }
- end
-
- def test_replace_text
- e = REXML::Element.new( "a" )
- e.add_text( "foo" )
- assert_equal( "<a>foo</a>", e.to_s )
- e[0].value = "bar"
- assert_equal( "<a>bar</a>", e.to_s )
- e[0].value = "<"
- assert_equal( "<a>&lt;</a>", e.to_s )
- assert_equal( "<", e[0].value )
- end
-
-
- def test_write_doctype
- ## XML Document and Declaration
- document = REXML::Document.new
- xmldecl = REXML::XMLDecl.new("1.0", "UTF-8")
- document.add(xmldecl)
- s = ""
- document.write(s)
-
- ## XML Doctype
- str = '<!DOCTYPE foo SYSTEM "bar">'
- source = REXML::Source.new(str)
- doctype = REXML::DocType.new(source)
- document.add(doctype)
- document.write(s)
-
- ## Element
- element = REXML::Element.new("hoge")
- document.add(element)
-
- document.write(s)
- end
-
- def test_write_cdata
- src = "<a>A</a>"
- doc = REXML::Document.new( src )
- out = ""
- doc.write( out )
- assert_equal( src, out )
-
- src = "<a><![CDATA[A]]></a>"
- doc = REXML::Document.new( src )
- out = ""
- doc.write( out )
- assert_equal( src, out )
- end
-
- def test_namespace_attributes
- source = <<-EOL
- <a xmlns:x="1">
- <x:b x:n="foo"/>
- </a>
- EOL
- d = Document.new( source )
- assert_equal( 'foo', REXML::XPath.first(d.root, "//x:b/@x:n").value )
- assert_equal( nil, REXML::XPath.first(d.root, "//x:b/@x:n", {}))
- end
-
- def test_null_element_name
- a = REXML::Document.new
- assert_raise( RuntimeError ) {
- a.add_element( nil )
- }
- end
-
- def test_text_raw
- # From the REXML tutorial
- # (http://www.germane-software.com/software/rexml/test/data/tutorial.html)
- doc = Document.new <<-EOL
- <?xml version="1.0"?>
- <!DOCTYPE schema SYSTEM "XMLSchema.dtd" [
- <!ENTITY % s 'Sean'>
- ]>
- <a/>
- EOL
- a = doc.root
-
- # This makes sure that RAW text nodes don't have their entity strings
- # replaced
- t = Text.new "Sean", false, nil, true
- a.text = t
- assert_equal( "Sean", t.to_s )
- assert_equal( "Sean", t.value )
-
- # This makes sure that they do
- t = Text.new "Sean", false, nil, false
- a.text = t
- assert_equal( "&s;", t.to_s )
- assert_equal( "Sean", t.value )
-
- t = Text.new "&s;", false, nil, true
- a.text = t
- assert_equal( "&s;", t.to_s )
- assert_equal( "Sean", t.value )
-
- t = Text.new "&s;", false, nil, true
- a.text = t
- assert_equal( "&s;", t.to_s )
- assert_equal( "Sean", t.value )
-
- # Ticket #44
- t = REXML::Text.new( "&amp;", false, nil, true )
- assert_equal( "&amp;", t.to_s )
-
- t = REXML::Text.new("&amp;", false, false)
- assert_equal( "&amp;amp;", t.to_s )
- end
-
- def test_to_xpath
- doc = REXML::Document.new( %q{<tag1>
- <tag2 name="tag2"/>
- <tag2 name="tag2"/>
- </tag1>})
- names = %w{ /tag1/tag2[1] /tag1/tag2[2] }
- doc.root.elements.each_with_index {|el, i|
- assert_equal( names[i], el.xpath )
- }
- end
-
- def test_transitive
- doc = REXML::Document.new( "<a/>")
- s = ""
- doc.write( s, 0, true )
- end
-
- # This is issue #40
- def test_replace_with
- old = '<doc>old<foo/>old</doc>'
- d = REXML::Document.new(old).root
- new = REXML::Text.new('new',true,nil,true)
- child = d.children[2]
- child.replace_with(new)
- assert_equal( new, d.children[2] )
- end
-
- def test_repeated_writes
- a = IO.read(fixture_path("iso8859-1.xml"))
- f = REXML::Formatters::Pretty.new
-
- xmldoc = REXML::Document.new( a )
- a_andre = xmldoc.elements['//image'].attributes['caption']
-
- f.write(xmldoc,b="")
-
- xmldoc = REXML::Document.new(b)
- b_andre = xmldoc.elements['//image'].attributes['caption']
- assert_equal( a_andre, b_andre )
-
- f.write(xmldoc,c="")
-
- xmldoc = REXML::Document.new(c)
- c_andre = xmldoc.elements['//image'].attributes['caption']
- assert_equal( b_andre, c_andre )
-
- o = Output.new(d="","UTF-8")
- f.write(xmldoc,o)
- assert_not_equal( c, d )
- end
-
- def test_pretty_format_long_text_finite
- n = 1_000_000
- long_text = 'aaaa ' * n
- xml = "<doc>#{long_text}</doc>"
- formatter = REXML::Formatters::Pretty.new
- document = nil
- begin
- document = REXML::Document.new(xml)
- rescue REXML::ParseException
- skip_message = "skip this test because we can't check Pretty#wrap " +
- "works without #<SystemStackError: stack level too deep> on " +
- "small memory system. #<RegexpError: failed to allocate memory> " +
- "will be raised on the system. See also [ruby-dev:42599]."
- return skip_message
- end
- output = ""
- formatter.write(document, output)
- assert_equal("<doc>\n" +
- ((" " + (" aaaa" * 15) + "\n") * (n / 15)) +
- " " + ("aaaa " * (n % 15)) + "\n" +
- "</doc>",
- output)
- end
-
- def test_pretty_format_deep_indent
- n = 6
- elements = ""
- n.times do |i|
- elements << "<element#{i}>"
- elements << "element#{i} " * 5
- end
- (n - 1).downto(0) do |i|
- elements << "</element#{i}>"
- end
- xml = "<doc>#{elements}</doc>"
- document = REXML::Document.new(xml)
- formatter = REXML::Formatters::Pretty.new
- formatter.width = 20
- output = ""
- formatter.write(document, output)
- assert_equal(<<-XML.strip, output)
-<doc>
- <element0>
- element0
- element0
- element0
- element0
- element0\s
- <element1>
- element1
- element1
- element1
- element1
- element1\s
- <element2>
- element2
- element2
- element2
- element2
- element2\s
- <element3>
- element3
- element3
- element3
- element3
- element3\s
- <element4>
- element4
- element4
- element4
- element4
- element4
- \s
- <element5>
- element5 element5 element5 element5 element5\s
- </element5>
- </element4>
- </element3>
- </element2>
- </element1>
- </element0>
-</doc>
- XML
- end
-
- def test_ticket_58
- doc = REXML::Document.new
- doc << REXML::XMLDecl.default
- doc << REXML::Element.new("a")
-
- str = ""
- doc.write(str)
-
- assert_equal("<a/>", str)
-
- doc = REXML::Document.new
- doc << REXML::XMLDecl.new("1.0", "UTF-8")
- doc << REXML::Element.new("a")
-
- str = ""
- doc.write(str)
-
- assert_equal("<?xml version='1.0' encoding='UTF-8'?><a/>", str)
- end
-
- # Incomplete tags should generate an error
- def test_ticket_53
- assert_raise( REXML::ParseException ) {
- REXML::Document.new( "<a><b></a>" )
- }
- assert_raise( REXML::ParseException ) {
- REXML::Document.new( "<a><b>" )
- }
- assert_raise( REXML::ParseException ) {
- REXML::Document.new( "<a><b/>" )
- }
- end
-
- def test_ticket_52
- source = "<!-- this is a single line comment -->"
- d = REXML::Document.new(source)
- d.write(k="")
- assert_equal( source, k )
-
- source = "<a><!-- Comment --></a>"
- target = "<a>\n <!-- Comment -->\n</a>"
- d = REXML::Document.new(source)
- REXML::Formatters::Pretty.new(4).write(d,k="")
- assert_equal( target, k )
- end
-
- def test_ticket_76
- src = "<div>at&t"
- assert_raise( ParseException, %Q{"#{src}" is invalid XML} ) {
- REXML::Document.new(src)
- }
- end
-
- def test_ticket_21
- src = "<foo bar=value/>"
- exception = assert_raise(ParseException) do
- Document.new(src)
- end
- assert_equal(<<-DETAIL, exception.to_s)
-Missing attribute value start quote: <bar>
-Line: 1
-Position: 16
-Last 80 unconsumed characters:
- DETAIL
- end
-
- def test_ticket_63
- File.open(fixture_path("t63-1.xml")) {|f| Document.new(f) }
- end
-
- def test_ticket_75
- d = File.open(fixture_path("t75.xml")) {|f| REXML::Document.new(f) }
- assert_equal("tree", d.root.name)
- end
-
- def test_ticket_48_part_II
- f = REXML::Formatters::Pretty.new
- #- rexml sanity check (bugs in ruby 1.8.4, ruby 1.8.6)
- xmldoc = Document.new("<test/>")
- xmldoc << XMLDecl.new(XMLDecl::DEFAULT_VERSION, "UTF-8")
- content = ['61c3a927223c3e26'].pack("H*")
- content.force_encoding('UTF-8') if content.respond_to?(:force_encoding)
- #- is some UTF-8 text but just to make sure my editor won't magically convert..
- xmldoc.root.add_attribute('attr', content)
- f.write(xmldoc,out=[])
-
- xmldoc = REXML::Document.new(out.join)
- sanity1 = xmldoc.root.attributes['attr']
- f.write(xmldoc,out=[])
-
- xmldoc = REXML::Document.new(out.join)
- sanity2 = xmldoc.root.attributes['attr']
- f.write(xmldoc,out=[])
-
- assert_equal( sanity1, sanity2 )
- end
-
- def test_ticket_88
- doc = REXML::Document.new("<?xml version=\"1.0\" encoding=\"shift_jis\"?>")
- assert_equal("<?xml version='1.0' encoding='SHIFT_JIS'?>", doc.to_s)
- doc = REXML::Document.new("<?xml version = \"1.0\" encoding = \"shift_jis\"?>")
- assert_equal("<?xml version='1.0' encoding='SHIFT_JIS'?>", doc.to_s)
- end
-
- def test_ticket_85
- xml = <<ENDXML
-<foo>
- <bar>
- <bob name='jimmy'/>
- </bar>
-</foo>
-ENDXML
-
- yml = "<foo>
- <bar>
- <bob name='jimmy'/>
- </bar>
-</foo>"
-
- # The pretty printer ignores all whitespace, anyway so output1 == output2
- f = REXML::Formatters::Pretty.new( 2 )
- d = Document.new( xml, :ignore_whitespace_nodes=>:all )
- f.write( d, output1="" )
-
- d = Document.new( xml )
- f.write( d, output2="" )
-
- # Output directives should override whitespace directives.
- assert_equal( output1, output2 )
-
- # The base case.
- d = Document.new(yml)
- f.write( d, output3="" )
-
- assert_equal( output3.strip, output2.strip )
-
- d = Document.new(yml)
- f.write( d, output4="" )
-
- assert_equal( output3.strip, output4.strip )
- end
-
- def test_ticket_91
- source="<root>
- <bah something='1' somethingelse='bah'>
- <something>great</something>
- </bah>
- </root>"
- expected="<root>
- <bah something='1' somethingelse='bah'>
- <something>great</something>
- </bah>
- <bah/>
-</root>"
- d = Document.new( source )
- d.root.add_element( "bah" )
- p=REXML::Formatters::Pretty.new(2)
- p.compact = true # Don't add whitespace to text nodes unless necessary
- p.write(d,out="")
- assert_equal( expected, out )
- end
-
- def test_ticket_95
- testd = REXML::Document.new "<a><b><c/><c/><c/></b></a>"
- testd.write(out1="")
- testd.elements["//c[2]"].xpath
- testd.write(out2="")
- assert_equal(out1,out2)
- end
-
- def test_ticket_102
- doc = REXML::Document.new '<doc xmlns="ns"><item name="foo"/></doc>'
- assert_equal( "foo", doc.root.elements["*:item"].attribute("name","ns").to_s )
- assert_equal( "item", doc.root.elements["*:item[@name='foo']"].name )
- end
-
- def test_ticket_14
- # Per .2.5 Node Tests of XPath spec
- assert_raise( REXML::UndefinedNamespaceException,
- %Q{Should have gotten an Undefined Namespace error} ) {
- Document.new("<a><n:b/></a>")
- }
- end
-
- # 5.7 Text Nodes
- # Character data is grouped into text nodes. As much character data as
- # possible is grouped into each text node: a text node never has an
- # immediately following or preceding sibling that is a text node. The
- # string-value of a text node is the character data. A text node always has
- # at least one character of data.
- def test_ticket_105
- d = Document.new("<a/>")
- d.root.add_text( "a" )
- d.root.add_text( "b" )
- assert_equal( 1, d.root.children.size )
- end
-
- # phantom namespace same as default namespace
- def test_ticket_121
- doc = REXML::Document.new(
- '<doc xmlns="ns" xmlns:phantom="ns"><item name="foo">text</item></doc>'
- )
- assert_equal 'text', doc.text( "/*:doc/*:item[@name='foo']" )
- assert_equal "name='foo'",
- doc.root.elements["*:item"].attribute("name", "ns").inspect
- assert_equal "<item name='foo'>text</item>",
- doc.root.elements["*:item[@name='foo']"].to_s
- end
-
- def test_ticket_135
- bean_element = REXML::Element.new("bean")
- textToAdd = "(&#38;(|(memberof=CN=somegroupabcdefgh,OU=OUsucks,DC=hookemhorns,DC=com)(mail=*someco.com))(acct=%u)(!(extraparameter:2.2.222.222222.2.2.222:=2)))"
- bean_element.add_element("prop", {"key"=> "filter"}).add_text(textToAdd)
- doc = REXML::Document.new
- doc.add_element(bean_element)
-
- REXML::Formatters::Pretty.new(3).write( doc, out = "" )
-
- assert_equal "<bean>\n <prop key='filter'>\n (&amp;#38;(|(memberof=CN=somegroupabcdefgh,OU=OUsucks,DC=hookemhorns,DC=com)(mail=*someco.com))(acct=%u)(!(extraparameter:2.2.222.222222.2.2.222:=2)))\n </prop>\n</bean>", out
- end
-
- def test_ticket_138
- doc = REXML::Document.new(
- '<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" ' +
- 'inkscape:version="0.44" version="1.0"/>'
- )
- expected = {
- "inkscape" => attribute("xmlns:inkscape",
- "http://www.inkscape.org/namespaces/inkscape"),
- "version" => {
- "inkscape" => attribute("inkscape:version", "0.44"),
- "" => attribute("version", "1.0"),
- },
- }
- assert_equal(expected, doc.root.attributes)
- assert_equal(expected, REXML::Document.new(doc.root.to_s).root.attributes)
- end
-
- def test_empty_doc
- assert(REXML::Document.new('').children.empty?)
- end
-
- private
- def attribute(name, value)
- REXML::Attribute.new(name, value)
- end
- end
-end
diff --git a/test/rexml/test_doctype.rb b/test/rexml/test_doctype.rb
deleted file mode 100644
index 915717de8e..0000000000
--- a/test/rexml/test_doctype.rb
+++ /dev/null
@@ -1,147 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "rexml_test_utils"
-
-module REXMLTests
- class TestDocTypeAccessor < Test::Unit::TestCase
- def setup
- @sysid = "urn:x-test:sysid1"
- @notation_id1 = "urn:x-test:notation1"
- @notation_id2 = "urn:x-test:notation2"
- xml_system = <<-XML
- <!DOCTYPE root SYSTEM "#{@sysid}" [
- <!NOTATION n1 SYSTEM "#{@notation_id1}">
- <!NOTATION n2 SYSTEM "#{@notation_id2}">
- ]>
- <root/>
- XML
- @doc_type_system = REXML::Document.new(xml_system).doctype
-
- @pubid = "TEST_ID"
- xml_public_system = <<-XML
- <!DOCTYPE root PUBLIC "#{@pubid}" "#{@sysid}">
- <root/>
- XML
- @doc_type_public_system = REXML::Document.new(xml_public_system).doctype
- end
-
- def test_public
- assert_equal([
- nil,
- @pubid,
- ],
- [
- @doc_type_system.public,
- @doc_type_public_system.public,
- ])
- end
-
- def test_to_s
- assert_equal("<!DOCTYPE root PUBLIC \"#{@pubid}\" \"#{@sysid}\">",
- @doc_type_public_system.to_s)
- end
-
- def test_to_s_apostrophe
- @doc_type_public_system.parent.context[:prologue_quote] = :apostrophe
- assert_equal("<!DOCTYPE root PUBLIC '#{@pubid}' '#{@sysid}'>",
- @doc_type_public_system.to_s)
- end
-
- def test_system
- assert_equal([
- @sysid,
- @sysid,
- ],
- [
- @doc_type_system.system,
- @doc_type_public_system.system,
- ])
- end
-
- def test_notation
- assert_equal([
- @notation_id1,
- @notation_id2,
- ],
- [
- @doc_type_system.notation("n1").system,
- @doc_type_system.notation("n2").system,
- ])
- end
-
- def test_notations
- notations = @doc_type_system.notations
- assert_equal([
- @notation_id1,
- @notation_id2,
- ],
- notations.collect(&:system))
- end
- end
-
- class TestNotationDeclPublic < Test::Unit::TestCase
- def setup
- @name = "vrml"
- @id = "VRML 1.0"
- @uri = "http://www.web3d.org/"
- end
-
- def test_to_s
- assert_equal("<!NOTATION #{@name} PUBLIC \"#{@id}\">",
- decl(@id, nil).to_s)
- end
-
- def test_to_s_with_uri
- assert_equal("<!NOTATION #{@name} PUBLIC \"#{@id}\" \"#{@uri}\">",
- decl(@id, @uri).to_s)
- end
-
- def test_to_s_apostrophe
- document = REXML::Document.new(<<-XML)
- <!DOCTYPE root SYSTEM "urn:x-test:sysid" [
- #{decl(@id, @uri).to_s}
- ]>
- <root/>
- XML
- document.context[:prologue_quote] = :apostrophe
- notation = document.doctype.notations[0]
- assert_equal("<!NOTATION #{@name} PUBLIC '#{@id}' '#{@uri}'>",
- notation.to_s)
- end
-
- private
- def decl(id, uri)
- REXML::NotationDecl.new(@name, "PUBLIC", id, uri)
- end
- end
-
- class TestNotationDeclSystem < Test::Unit::TestCase
- def setup
- @name = "gif"
- @id = "gif viewer"
- end
-
- def test_to_s
- assert_equal("<!NOTATION #{@name} SYSTEM \"#{@id}\">",
- decl(@id).to_s)
- end
-
- def test_to_s_apostrophe
- document = REXML::Document.new(<<-XML)
- <!DOCTYPE root SYSTEM "urn:x-test:sysid" [
- #{decl(@id).to_s}
- ]>
- <root/>
- XML
- document.context[:prologue_quote] = :apostrophe
- notation = document.doctype.notations[0]
- assert_equal("<!NOTATION #{@name} SYSTEM '#{@id}'>",
- notation.to_s)
- end
-
- private
- def decl(id)
- REXML::NotationDecl.new(@name, "SYSTEM", id, nil)
- end
- end
-end
diff --git a/test/rexml/test_document.rb b/test/rexml/test_document.rb
deleted file mode 100644
index c0faae4ae0..0000000000
--- a/test/rexml/test_document.rb
+++ /dev/null
@@ -1,416 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require "rexml/document"
-require "test/unit"
-
-module REXMLTests
- class TestDocument < Test::Unit::TestCase
- def test_version_attributes_to_s
- doc = REXML::Document.new(<<-eoxml)
- <?xml version="1.0" encoding="UTF-8" standalone="no"?>
- <svg id="svg2"
- xmlns:sodipodi="foo"
- xmlns:inkscape="bar"
- sodipodi:version="0.32"
- inkscape:version="0.44.1"
- >
- </svg>
- eoxml
-
- string = doc.to_s
- assert_match('xmlns:sodipodi', string)
- assert_match('xmlns:inkscape', string)
- assert_match('sodipodi:version', string)
- assert_match('inkscape:version', string)
- end
-
- def test_new
- doc = REXML::Document.new(<<EOF)
-<?xml version="1.0" encoding="UTF-8"?>
-<message>Hello world!</message>
-EOF
- assert_equal("Hello world!", doc.root.children.first.value)
- end
-
- class EntityExpansionLimitTest < Test::Unit::TestCase
- def setup
- @default_entity_expansion_limit = REXML::Security.entity_expansion_limit
- end
-
- def teardown
- REXML::Security.entity_expansion_limit = @default_entity_expansion_limit
- end
-
- class GeneralEntityTest < self
- def test_have_value
- xml = <<EOF
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE member [
- <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
- <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
- <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
- <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
- <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
- <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
- <!ENTITY g "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx">
-]>
-<member>
-&a;
-</member>
-EOF
-
- doc = REXML::Document.new(xml)
- assert_raise(RuntimeError) do
- doc.root.children.first.value
- end
- REXML::Security.entity_expansion_limit = 100
- assert_equal(100, REXML::Security.entity_expansion_limit)
- doc = REXML::Document.new(xml)
- assert_raise(RuntimeError) do
- doc.root.children.first.value
- end
- assert_equal(101, doc.entity_expansion_count)
- end
-
- def test_empty_value
- xml = <<EOF
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE member [
- <!ENTITY a "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
- <!ENTITY b "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
- <!ENTITY c "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
- <!ENTITY d "&e;&e;&e;&e;&e;&e;&e;&e;&e;&e;">
- <!ENTITY e "&f;&f;&f;&f;&f;&f;&f;&f;&f;&f;">
- <!ENTITY f "&g;&g;&g;&g;&g;&g;&g;&g;&g;&g;">
- <!ENTITY g "">
-]>
-<member>
-&a;
-</member>
-EOF
-
- doc = REXML::Document.new(xml)
- assert_raise(RuntimeError) do
- doc.root.children.first.value
- end
- REXML::Security.entity_expansion_limit = 100
- assert_equal(100, REXML::Security.entity_expansion_limit)
- doc = REXML::Document.new(xml)
- assert_raise(RuntimeError) do
- doc.root.children.first.value
- end
- assert_equal(101, doc.entity_expansion_count)
- end
-
- def test_with_default_entity
- xml = <<EOF
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE member [
- <!ENTITY a "a">
- <!ENTITY a2 "&a; &a;">
-]>
-<member>
-&a;
-&a2;
-&lt;
-</member>
-EOF
-
- REXML::Security.entity_expansion_limit = 4
- doc = REXML::Document.new(xml)
- assert_equal("\na\na a\n<\n", doc.root.children.first.value)
- REXML::Security.entity_expansion_limit = 3
- doc = REXML::Document.new(xml)
- assert_raise(RuntimeError) do
- doc.root.children.first.value
- end
- end
- end
-
- class ParameterEntityTest < self
- def test_have_value
- xml = <<EOF
-<!DOCTYPE root [
- <!ENTITY % a "BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.BOOM.">
- <!ENTITY % b "%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;">
- <!ENTITY % c "%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;">
- <!ENTITY % d "%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;">
- <!ENTITY % e "%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;">
- <!ENTITY % f "%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;">
- <!ENTITY % g "%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;">
- <!ENTITY test "test %g;">
-]>
-<cd></cd>
-EOF
-
- assert_raise(REXML::ParseException) do
- REXML::Document.new(xml)
- end
- REXML::Security.entity_expansion_limit = 100
- assert_equal(100, REXML::Security.entity_expansion_limit)
- assert_raise(REXML::ParseException) do
- REXML::Document.new(xml)
- end
- end
-
- def test_empty_value
- xml = <<EOF
-<!DOCTYPE root [
- <!ENTITY % a "">
- <!ENTITY % b "%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;%a;">
- <!ENTITY % c "%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;%b;">
- <!ENTITY % d "%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;%c;">
- <!ENTITY % e "%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;%d;">
- <!ENTITY % f "%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;%e;">
- <!ENTITY % g "%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;">
- <!ENTITY test "test %g;">
-]>
-<cd></cd>
-EOF
-
- assert_raise(REXML::ParseException) do
- REXML::Document.new(xml)
- end
- REXML::Security.entity_expansion_limit = 100
- assert_equal(100, REXML::Security.entity_expansion_limit)
- assert_raise(REXML::ParseException) do
- REXML::Document.new(xml)
- end
- end
- end
- end
-
- def test_tag_in_cdata_with_not_ascii_only_but_ascii8bit_encoding_source
- tag = "<b>...</b>"
- message = "こんにちは、世界!" # Hello world! in Japanese
- xml = <<EOX
-<?xml version="1.0" encoding="UTF-8"?>
-<message><![CDATA[#{tag}#{message}]]></message>
-EOX
- xml.force_encoding(Encoding::ASCII_8BIT)
- doc = REXML::Document.new(xml)
- assert_equal("#{tag}#{message}", doc.root.children.first.value)
- end
-
- def test_xml_declaration_standalone
- bug2539 = '[ruby-core:27345]'
- doc = REXML::Document.new('<?xml version="1.0" standalone="no" ?>')
- assert_equal('no', doc.stand_alone?, bug2539)
- doc = REXML::Document.new('<?xml version="1.0" standalone= "no" ?>')
- assert_equal('no', doc.stand_alone?, bug2539)
- doc = REXML::Document.new('<?xml version="1.0" standalone= "no" ?>')
- assert_equal('no', doc.stand_alone?, bug2539)
- end
-
- class WriteTest < Test::Unit::TestCase
- def setup
- @document = REXML::Document.new(<<-EOX)
-<?xml version="1.0" encoding="UTF-8"?>
-<message>Hello world!</message>
-EOX
- end
-
- class ArgumentsTest < self
- def test_output
- output = ""
- @document.write(output)
- assert_equal(<<-EOX, output)
-<?xml version='1.0' encoding='UTF-8'?>
-<message>Hello world!</message>
-EOX
- end
-
- def test_indent
- output = ""
- indent = 2
- @document.write(output, indent)
- assert_equal(<<-EOX.chomp, output)
-<?xml version='1.0' encoding='UTF-8'?>
-<message>
- Hello world!
-</message>
-EOX
- end
-
- def test_transitive
- output = ""
- indent = 2
- transitive = true
- @document.write(output, indent, transitive)
- assert_equal(<<-EOX, output)
-<?xml version='1.0' encoding='UTF-8'?>
-<message
->Hello world!</message
->
-EOX
- end
-
- def test_ie_hack
- output = ""
- indent = -1
- transitive = false
- ie_hack = true
- document = REXML::Document.new("<empty/>")
- document.write(output, indent, transitive, ie_hack)
- assert_equal("<empty />", output)
- end
-
- def test_encoding
- output = ""
- indent = -1
- transitive = false
- ie_hack = false
- encoding = "Windows-31J"
-
- @document.xml_decl.encoding = "Shift_JIS"
- japanese_text = "こんにちは"
- @document.root.text = japanese_text
- @document.write(output, indent, transitive, ie_hack, encoding)
- assert_equal(<<-EOX.encode(encoding), output)
-<?xml version='1.0' encoding='SHIFT_JIS'?>
-<message>#{japanese_text}</message>
-EOX
- end
- end
-
- class OptionsTest < self
- def test_output
- output = ""
- @document.write(:output => output)
- assert_equal(<<-EOX, output)
-<?xml version='1.0' encoding='UTF-8'?>
-<message>Hello world!</message>
-EOX
- end
-
- def test_indent
- output = ""
- @document.write(:output => output, :indent => 2)
- assert_equal(<<-EOX.chomp, output)
-<?xml version='1.0' encoding='UTF-8'?>
-<message>
- Hello world!
-</message>
-EOX
- end
-
- def test_transitive
- output = ""
- @document.write(:output => output, :indent => 2, :transitive => true)
- assert_equal(<<-EOX, output)
-<?xml version='1.0' encoding='UTF-8'?>
-<message
->Hello world!</message
->
-EOX
- end
-
- def test_ie_hack
- output = ""
- document = REXML::Document.new("<empty/>")
- document.write(:output => output, :ie_hack => true)
- assert_equal("<empty />", output)
- end
-
- def test_encoding
- output = ""
- encoding = "Windows-31J"
- @document.xml_decl.encoding = "Shift_JIS"
- japanese_text = "こんにちは"
- @document.root.text = japanese_text
- @document.write(:output => output, :encoding => encoding)
- assert_equal(<<-EOX.encode(encoding), output)
-<?xml version='1.0' encoding='SHIFT_JIS'?>
-<message>#{japanese_text}</message>
-EOX
- end
- end
- end
-
- class BomTest < Test::Unit::TestCase
- class HaveEncodingTest < self
- def test_utf_8
- xml = <<-EOX.force_encoding("ASCII-8BIT")
-<?xml version="1.0" encoding="UTF-8"?>
-<message>Hello world!</message>
-EOX
- bom = "\ufeff".force_encoding("ASCII-8BIT")
- document = REXML::Document.new(bom + xml)
- assert_equal("UTF-8", document.encoding)
- end
-
- def test_utf_16le
- xml = <<-EOX.encode("UTF-16LE").force_encoding("ASCII-8BIT")
-<?xml version="1.0" encoding="UTF-16"?>
-<message>Hello world!</message>
-EOX
- bom = "\ufeff".encode("UTF-16LE").force_encoding("ASCII-8BIT")
- document = REXML::Document.new(bom + xml)
- assert_equal("UTF-16", document.encoding)
- end
-
- def test_utf_16be
- xml = <<-EOX.encode("UTF-16BE").force_encoding("ASCII-8BIT")
-<?xml version="1.0" encoding="UTF-16"?>
-<message>Hello world!</message>
-EOX
- bom = "\ufeff".encode("UTF-16BE").force_encoding("ASCII-8BIT")
- document = REXML::Document.new(bom + xml)
- assert_equal("UTF-16", document.encoding)
- end
- end
-
- class NoEncodingTest < self
- def test_utf_8
- xml = <<-EOX.force_encoding("ASCII-8BIT")
-<?xml version="1.0"?>
-<message>Hello world!</message>
-EOX
- bom = "\ufeff".force_encoding("ASCII-8BIT")
- document = REXML::Document.new(bom + xml)
- assert_equal("UTF-8", document.encoding)
- end
-
- def test_utf_16le
- xml = <<-EOX.encode("UTF-16LE").force_encoding("ASCII-8BIT")
-<?xml version="1.0"?>
-<message>Hello world!</message>
-EOX
- bom = "\ufeff".encode("UTF-16LE").force_encoding("ASCII-8BIT")
- document = REXML::Document.new(bom + xml)
- assert_equal("UTF-16", document.encoding)
- end
-
- def test_utf_16be
- xml = <<-EOX.encode("UTF-16BE").force_encoding("ASCII-8BIT")
-<?xml version="1.0"?>
-<message>Hello world!</message>
-EOX
- bom = "\ufeff".encode("UTF-16BE").force_encoding("ASCII-8BIT")
- document = REXML::Document.new(bom + xml)
- assert_equal("UTF-16", document.encoding)
- end
- end
-
- class WriteTest < self
- def test_utf_16
- xml = <<-EOX.encode("UTF-16LE").force_encoding("ASCII-8BIT")
-<?xml version="1.0"?>
-<message>Hello world!</message>
-EOX
- bom = "\ufeff".encode("UTF-16LE").force_encoding("ASCII-8BIT")
- document = REXML::Document.new(bom + xml)
-
- actual_xml = ""
- document.write(actual_xml)
- expected_xml = <<-EOX.encode("UTF-16BE")
-\ufeff<?xml version='1.0' encoding='UTF-16'?>
-<message>Hello world!</message>
-EOX
- assert_equal(expected_xml, actual_xml)
- end
- end
- end
- end
-end
diff --git a/test/rexml/test_element.rb b/test/rexml/test_element.rb
deleted file mode 100644
index 82830b44e6..0000000000
--- a/test/rexml/test_element.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: false
-
-require "test/unit/testcase"
-require "rexml/document"
-
-module REXMLTests
- class ElementTester < Test::Unit::TestCase
- def test_array_reference_string
- doc = REXML::Document.new("<language name='Ruby'/>")
- assert_equal("Ruby", doc.root["name"])
- end
-
- def test_array_reference_symbol
- doc = REXML::Document.new("<language name='Ruby'/>")
- assert_equal("Ruby", doc.root[:name])
- end
- end
-end
diff --git a/test/rexml/test_elements.rb b/test/rexml/test_elements.rb
deleted file mode 100644
index a850e62209..0000000000
--- a/test/rexml/test_elements.rb
+++ /dev/null
@@ -1,119 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit/testcase'
-require 'rexml/document'
-
-module REXMLTests
- class ElementsTester < Test::Unit::TestCase
- include REXML
- def test_accessor
- doc = Document.new '<a><b/><c id="1"/><c id="2"/><d/></a>'
- assert_equal 'b', doc.root.elements[1].name
- assert_equal '1', doc.root.elements['c'].attributes['id']
- assert_equal '2', doc.root.elements[2,'c'].attributes['id']
- end
-
- def test_indexing
- doc = Document.new '<a/>'
- doc.root.elements[10] = Element.new('b')
- assert_equal 'b', doc.root.elements[1].name
- doc.root.elements[1] = Element.new('c')
- assert_equal 'c', doc.root.elements[1].name
- doc.root.elements['c'] = Element.new('d')
- assert_equal 'd', doc.root.elements[1].name
- end
-
- def test_delete
- doc = Document.new '<a><b/><c/><c id="1"/></a>'
- block = proc { |str|
- out = ''
- doc.write out
- assert_equal str, out
- }
- b = doc.root.elements[1]
- doc.root.elements.delete b
- block.call( "<a><c/><c id='1'/></a>" )
- doc.elements.delete("a/c[@id='1']")
- block.call( '<a><c/></a>' )
- doc.root.elements.delete 1
- block.call( '<a/>' )
- end
-
- def test_delete_all
- doc = Document.new '<a><c/><c/><c/><c/></a>'
- deleted = doc.elements.delete_all 'a/c'
- assert_equal 4, deleted.size
- end
-
- def test_ticket_36
- doc = Document.new( "<a xmlns:xi='foo'><b><xi:c id='1'/></b><xi:c id='2'/></a>" )
-
- deleted = doc.root.elements.delete_all( "xi:c" )
- assert_equal( 1, deleted.size )
-
- doc = Document.new( "<a xmlns:xi='foo'><b><xi:c id='1'/></b><xi:c id='2'/></a>" )
- deleted = doc.root.elements.delete_all( "//xi:c" )
- assert_equal( 2, deleted.size )
- end
-
- def test_add
- a = Element.new 'a'
- a.elements.add Element.new('b')
- assert_equal 'b', a.elements[1].name
- a.elements.add 'c'
- assert_equal 'c', a.elements[2].name
- end
-
- def test_size
- doc = Document.new '<a>sean<b/>elliott<b/>russell<b/></a>'
- assert_equal 6, doc.root.size
- assert_equal 3, doc.root.elements.size
- end
-
- def test_each
- doc = Document.new '<a><b/><c/><d/>sean<b/><c/><d/></a>'
- count = 0
- block = proc {|e| count += 1}
- doc.root.elements.each(&block)
- assert_equal 6, count
- count = 0
- doc.root.elements.each('b', &block)
- assert_equal 2, count
- count = 0
- doc.root.elements.each('child::node()', &block)
- assert_equal 6, count
- count = 0
- XPath.each(doc.root, 'child::node()', &block)
- assert_equal 7, count
- end
-
- def test_each_with_frozen_condition
- doc = Document.new('<books><book name="Ruby"/><book name="XML"/></books>')
- names = []
- doc.root.elements.each('book'.freeze) do |element|
- names << element.attributes["name"]
- end
- assert_equal(["Ruby", "XML"], names)
- end
-
- def test_to_a
- doc = Document.new '<a>sean<b/>elliott<c/></a>'
- assert_equal 2, doc.root.elements.to_a.size
- assert_equal 2, doc.root.elements.to_a("child::node()").size
- assert_equal 4, XPath.match(doc.root, "child::node()").size
- end
-
- def test_collect
- doc = Document.new( "<a><b id='1'/><b id='2'/></a>" )
- r = doc.elements.collect( "/a/b" ) { |e| e.attributes["id"].to_i }
- assert_equal( [1,2], r )
- end
-
- def test_inject
- doc = Document.new( "<a><b id='1'/><b id='2'/></a>" )
- r = doc.elements.inject( "/a/b", 3 ) { |s, e|
- s + e.attributes["id"].to_i
- }
- assert_equal 6, r
- end
- end
-end
diff --git a/test/rexml/test_encoding.rb b/test/rexml/test_encoding.rb
deleted file mode 100644
index 919db131f0..0000000000
--- a/test/rexml/test_encoding.rb
+++ /dev/null
@@ -1,108 +0,0 @@
-# coding: binary
-# frozen_string_literal: false
-
-require_relative "rexml_test_utils"
-
-require 'rexml/source'
-require 'rexml/document'
-
-module REXMLTests
- class EncodingTester < Test::Unit::TestCase
- include REXMLTestUtils
- include REXML
-
- def setup
- @encoded_root = "<a><b>\346</b></a>"
- @encoded = "<?xml version='1.0' encoding='ISO-8859-3'?>"+
- @encoded_root
- @not_encoded = "<a><b>ĉ</b></a>"
- end
-
- # Given an encoded document, try to write out to that encoding
- def test_encoded_in_encoded_out
- doc = Document.new( @encoded )
- doc.write( out="" )
- out.force_encoding(::Encoding::ASCII_8BIT)
- assert_equal( @encoded, out )
- end
-
- # Given an encoded document, try to change the encoding and write it out
- def test_encoded_in_change_out
- doc = Document.new( @encoded )
- doc.xml_decl.encoding = "UTF-8"
- assert_equal("UTF-8", doc.encoding)
- REXML::Formatters::Default.new.write( doc.root, out="" )
- out.force_encoding(::Encoding::ASCII_8BIT)
- assert_equal( @not_encoded, out )
- char = XPath.first( doc, "/a/b/text()" ).to_s
- char.force_encoding(::Encoding::ASCII_8BIT)
- assert_equal( "ĉ", char )
- end
-
- # * Given an encoded document, try to write it to a different encoding
- def test_encoded_in_different_out
- doc = Document.new( @encoded )
- REXML::Formatters::Default.new.write( doc.root, Output.new( out="", "UTF-8" ) )
- out.force_encoding(::Encoding::ASCII_8BIT)
- assert_equal( @not_encoded, out )
- end
-
- # * Given a non-encoded document, change the encoding
- def test_in_change_out
- doc = Document.new( @not_encoded )
- doc.xml_decl.encoding = "ISO-8859-3"
- assert_equal("ISO-8859-3", doc.encoding)
- doc.write( out="" )
- out.force_encoding(::Encoding::ASCII_8BIT)
- assert_equal( @encoded, out )
- end
-
- # * Given a non-encoded document, write to a different encoding
- def test_in_different_out
- doc = Document.new( @not_encoded )
- doc.write( Output.new( out="", "ISO-8859-3" ) )
- out.force_encoding(::Encoding::ASCII_8BIT)
- assert_equal( "<?xml version='1.0'?>#{@encoded_root}", out )
- end
-
- # * Given an encoded document, accessing text and attribute nodes
- # should provide UTF-8 text.
- def test_in_different_access
- doc = Document.new <<-EOL
- <?xml version='1.0' encoding='ISO-8859-1'?>
- <a a="\xFF">\xFF</a>
- EOL
- expect = "\303\277"
- expect.force_encoding(::Encoding::UTF_8)
- assert_equal( expect, doc.elements['a'].attributes['a'] )
- assert_equal( expect, doc.elements['a'].text )
- end
-
-
- def test_ticket_89
- doc = Document.new <<-EOL
- <?xml version="1.0" encoding="CP-1252" ?>
- <xml><foo></foo></xml>
- EOL
-
- REXML::Document.new doc
- end
-
- def test_parse_utf16
- utf16 = File.open(fixture_path("utf16.xml")) do |f|
- REXML::Document.new(f)
- end
- assert_equal("UTF-16", utf16.encoding)
- assert( utf16[0].kind_of?(REXML::XMLDecl))
- end
-
- def test_parse_utf16_with_utf8_default_internal
- EnvUtil.with_default_internal("UTF-8") do
- utf16 = File.open(fixture_path("utf16.xml")) do |f|
- REXML::Document.new(f)
- end
- assert_equal("UTF-16", utf16.encoding)
- end
- end
- end
-end
diff --git a/test/rexml/test_entity.rb b/test/rexml/test_entity.rb
deleted file mode 100644
index 6dc6637074..0000000000
--- a/test/rexml/test_entity.rb
+++ /dev/null
@@ -1,206 +0,0 @@
-# frozen_string_literal: false
-require "test/unit/testcase"
-
-require 'rexml/document'
-require 'rexml/entity'
-require 'rexml/source'
-
-module REXMLTests
- class EntityTester < Test::Unit::TestCase
- def test_parse_general_decl
- simple = "<!ENTITY foo 'bar'>"
- simple =~ /#{REXML::Entity::GEDECL}/
- assert $&
- assert_equal simple, $&
-
- REXML::Entity::ENTITYDECL =~ simple
- assert REXML::Entity::matches?(simple)
- match = REXML::Entity::ENTITYDECL.match(simple)
- assert_equal 'foo', match[1]
- assert_equal "'bar'", match[2]
-
- simple = '<!ENTITY Pub-Status
- "This is a pre-release of the specification.">'
- assert REXML::Entity::matches?(simple)
- match = REXML::Entity::ENTITYDECL.match(simple)
- assert_equal 'Pub-Status', match[1]
- assert_equal '"This is a pre-release of the specification."', match[2]
-
- txt = '"This is a
- pre-release of <the> specification."'
- simple = "<!ENTITY Pub-Status
- #{txt}>"
- assert REXML::Entity::matches?(simple)
- match = REXML::Entity::ENTITYDECL.match(simple)
- assert_equal 'Pub-Status', match[1]
- assert_equal txt, match[2]
- end
-
- def test_parse_external_decl
- zero = '<!ENTITY open-hatch SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml" >'
- one = '<!ENTITY open-hatch
- SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">'
- two = '<!ENTITY open-hatch
- PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
- "http://www.textuality.com/boilerplate/OpenHatch.xml">'
- three = '<!ENTITY hatch-pic
- SYSTEM "../grafix/OpenHatch.gif"
- NDATA gif >'
- assert REXML::Entity::matches?(zero)
- assert REXML::Entity::matches?(one)
- assert REXML::Entity::matches?(two)
- assert REXML::Entity::matches?(three)
- end
-
- def test_parse_entity
- one = %q{<!ENTITY % YN '"Yes"'>}
- two = %q{<!ENTITY WhatHeSaid "He said %YN;">}
- assert REXML::Entity::matches?(one)
- assert REXML::Entity::matches?(two)
- end
-
- def test_constructor
- one = [ %q{<!ENTITY % YN '"Yes"'>},
- %q{<!ENTITY % YN2 "Yes">},
- %q{<!ENTITY WhatHeSaid "He said %YN;">},
- '<!ENTITY open-hatch
- SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">',
- '<!ENTITY open-hatch2
- PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
- "http://www.textuality.com/boilerplate/OpenHatch.xml">',
- '<!ENTITY hatch-pic
- SYSTEM "../grafix/OpenHatch.gif"
- NDATA gif>' ]
- source = %q{<!DOCTYPE foo [
- <!ENTITY % YN '"Yes"'>
- <!ENTITY % YN2 "Yes">
- <!ENTITY WhatHeSaid "He said %YN;">
- <!ENTITY open-hatch
- SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
- <!ENTITY open-hatch2
- PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
- "http://www.textuality.com/boilerplate/OpenHatch.xml">
- <!ENTITY hatch-pic
- SYSTEM "../grafix/OpenHatch.gif"
- NDATA gif>
- ]>}
-
- d = REXML::Document.new( source )
- dt = d.doctype
- c = 0
- dt.each do |child|
- if child.kind_of? REXML::Entity
- str = one[c].tr("\r\n\t", ' ').squeeze(" ")
- assert_equal str, child.to_s
- c+=1
- end
- end
- end
-
- def test_replace_entities
- source = "<!DOCTYPE blah [\n<!ENTITY foo \"bar\">\n]><a>&foo;</a>"
- doc = REXML::Document.new(source)
- assert_equal 'bar', doc.root.text
- out = ''
- doc.write out
- assert_equal source, out
- end
-
- def test_entity_string_limit
- template = '<!DOCTYPE bomb [ <!ENTITY a "^" > ]> <bomb>$</bomb>'
- len = 5120 # 5k per entity
- template.sub!(/\^/, "B" * len)
-
- # 10k is OK
- entities = '&a;' * 2 # 5k entity * 2 = 10k
- xmldoc = REXML::Document.new(template.sub(/\$/, entities))
- assert_equal(len * 2, xmldoc.root.text.bytesize)
-
- # above 10k explodes
- entities = '&a;' * 3 # 5k entity * 2 = 15k
- xmldoc = REXML::Document.new(template.sub(/\$/, entities))
- assert_raise(RuntimeError) do
- xmldoc.root.text
- end
- end
-
- def test_entity_string_limit_for_parameter_entity
- template = '<!DOCTYPE bomb [ <!ENTITY % a "^" > <!ENTITY bomb "$" > ]><root/>'
- len = 5120 # 5k per entity
- template.sub!(/\^/, "B" * len)
-
- # 10k is OK
- entities = '%a;' * 2 # 5k entity * 2 = 10k
- REXML::Document.new(template.sub(/\$/, entities))
-
- # above 10k explodes
- entities = '%a;' * 3 # 5k entity * 2 = 15k
- assert_raise(REXML::ParseException) do
- REXML::Document.new(template.sub(/\$/, entities))
- end
- end
-
- def test_raw
- source = '<!DOCTYPE foo [
-<!ENTITY ent "replace">
-]><a>replace &ent;</a>'
- doc = REXML::Document.new( source, {:raw=>:all})
- assert_equal('replace &ent;', doc.root.get_text.to_s)
- assert_equal(source, doc.to_s)
- end
-
- def test_lazy_evaluation
- source = '<!DOCTYPE foo [
-<!ENTITY ent "replace">
-]><a>replace &ent;</a>'
- doc = REXML::Document.new( source )
- assert_equal(source, doc.to_s)
- assert_equal("replace replace", doc.root.text)
- assert_equal(source, doc.to_s)
- end
-
- # Contributed (not only test, but bug fix!!) by Kouhei Sutou
- def test_entity_replacement
- source = %q{<!DOCTYPE foo [
- <!ENTITY % YN '"Yes"'>
- <!ENTITY WhatHeSaid "He said %YN;">]>
- <a>&WhatHeSaid;</a>}
-
- d = REXML::Document.new( source )
- dt = d.doctype
- assert_equal( '"Yes"', dt.entities[ "YN" ].value )
- assert_equal( 'He said "Yes"', dt.entities[ "WhatHeSaid" ].value )
- assert_equal( 'He said "Yes"', d.elements[1].text )
- end
-
- # More unit tests from Kouhei. I looove users who give me unit tests.
- def test_entity_insertions
- assert_equal("&amp;", REXML::Text.new("&amp;", false, nil, true).to_s)
- #assert_equal("&", REXML::Text.new("&amp;", false, false).to_s)
- end
-
- def test_single_pass_unnormalization # ticket 123
- assert_equal '&amp;&', REXML::Text::unnormalize('&#38;amp;&amp;')
- end
-
- def test_entity_filter
- document = REXML::Document.new(<<-XML)
-<!DOCTYPE root [
-<!ENTITY copy "(c)">
-<!ENTITY release-year "2013">
-]>
-<root/>
-XML
- respect_whitespace = false
- parent = document.root
- raw = false
- entity_filter = ["copy"]
- assert_equal("(c) &release-year;",
- REXML::Text.new("(c) 2013",
- respect_whitespace,
- parent,
- raw,
- entity_filter).to_s)
- end
- end
-end
diff --git a/test/rexml/test_instruction.rb b/test/rexml/test_instruction.rb
deleted file mode 100644
index 96fa909e17..0000000000
--- a/test/rexml/test_instruction.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative "rexml_test_utils"
-
-module REXMLTests
- class InstructionTest < Test::Unit::TestCase
- def test_target_nil
- error = assert_raise(ArgumentError) do
- REXML::Instruction.new(nil)
- end
- assert_equal("processing instruction target must be String or " +
- "REXML::Instruction: <nil>",
- error.message)
- end
- end
-end
diff --git a/test/rexml/test_jaxen.rb b/test/rexml/test_jaxen.rb
deleted file mode 100644
index 9640b8290b..0000000000
--- a/test/rexml/test_jaxen.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-# frozen_string_literal: false
-require_relative 'rexml_test_utils'
-
-require "rexml/document"
-require "rexml/xpath"
-
-# Harness to test REXML's capabilities against the test suite from Jaxen
-# ryan.a.cox@gmail.com
-
-module REXMLTests
- class JaxenTester < Test::Unit::TestCase
- include REXMLTestUtils
- include REXML
-
- def test_axis ; process_test_case("axis") ; end
- def test_basic ; process_test_case("basic") ; end
- def test_basicupdate ; process_test_case("basicupdate") ; end
- def test_contents ; process_test_case("contents") ; end
- def test_defaultNamespace ; process_test_case("defaultNamespace") ; end
- def test_fibo ; process_test_case("fibo") ; end
- def test_id ; process_test_case("id") ; end
- def test_jaxen24 ; process_test_case("jaxen24") ; end
- def test_lang ; process_test_case("lang") ; end
- # document() function for XSLT isn't supported
- def _test_message ; process_test_case("message") ; end
- def test_moreover ; process_test_case("moreover") ; end
- def test_much_ado ; process_test_case("much_ado") ; end
- def test_namespaces ; process_test_case("namespaces") ; end
- def test_nitf ; process_test_case("nitf") ; end
- # Exception should be considered
- def _test_numbers ; process_test_case("numbers") ; end
- def test_pi ; process_test_case("pi") ; end
- def test_pi2 ; process_test_case("pi2") ; end
- def test_simple ; process_test_case("simple") ; end
- # TODO: namespace node is needed
- def _test_testNamespaces ; process_test_case("testNamespaces") ; end
- # document() function for XSLT isn't supported
- def _test_text ; process_test_case("text") ; end
- def test_underscore ; process_test_case("underscore") ; end
- def _test_web ; process_test_case("web") ; end
- def test_web2 ; process_test_case("web2") ; end
-
- private
- def process_test_case(name)
- xml_path = "#{name}.xml"
- doc = File.open(fixture_path(xml_path)) do |file|
- Document.new(file)
- end
- test_doc = File.open(fixture_path("test/tests.xml")) do |file|
- Document.new(file)
- end
- XPath.each(test_doc,
- "/tests/document[@url='xml/#{xml_path}']/context") do |context|
- process_context(doc, context)
- end
- end
-
- # processes a tests/document/context node
- def process_context(doc, context)
- test_context = XPath.match(doc, context.attributes["select"])
- namespaces = context.namespaces
- namespaces.delete("var")
- namespaces = nil if namespaces.empty?
- variables = {}
- var_namespace = "http://jaxen.org/test-harness/var"
- XPath.each(context,
- "@*[namespace-uri() = '#{var_namespace}']") do |attribute|
- variables[attribute.name] = attribute.value
- end
- XPath.each(context, "valueOf") do |value|
- process_value_of(test_context, variables, namespaces, value)
- end
- XPath.each(context,
- "test[not(@exception) or (@exception != 'true')]") do |test|
- process_nominal_test(test_context, variables, namespaces, test)
- end
- XPath.each(context,
- "test[@exception = 'true']") do |test|
- process_exceptional_test(test_context, variables, namespaces, test)
- end
- end
-
- # processes a tests/document/context/valueOf or tests/document/context/test/valueOf node
- def process_value_of(context, variables, namespaces, value_of)
- expected = value_of.text
- xpath = value_of.attributes["select"]
- matched = XPath.match(context, xpath, namespaces, variables, strict: true)
-
- message = user_message(context, xpath, matched)
- assert_equal(expected || "",
- REXML::Functions.string(matched),
- message)
- end
-
- # processes a tests/document/context/test node ( where @exception is false or doesn't exist )
- def process_nominal_test(context, variables, namespaces, test)
- xpath = test.attributes["select"]
- matched = XPath.match(context, xpath, namespaces, variables, strict: true)
- # might be a test with no count attribute, but nested valueOf elements
- expected = test.attributes["count"]
- if expected
- assert_equal(Integer(expected, 10),
- matched.size,
- user_message(context, xpath, matched))
- end
-
- XPath.each(test, "valueOf") do |value_of|
- process_value_of(matched, variables, namespaces, value_of)
- end
- end
-
- # processes a tests/document/context/test node ( where @exception is true )
- def process_exceptional_test(context, variables, namespaces, test)
- xpath = test.attributes["select"]
- assert_raise(REXML::ParseException) do
- XPath.match(context, xpath, namespaces, variables, strict: true)
- end
- end
-
- def user_message(context, xpath, matched)
- message = ""
- context.each_with_index do |node, i|
- message << "Node#{i}:\n"
- message << "#{node}\n"
- end
- message << "XPath: <#{xpath}>\n"
- message << "Matched <#{matched}>"
- message
- end
- end
-end
diff --git a/test/rexml/test_light.rb b/test/rexml/test_light.rb
deleted file mode 100644
index 99bd9cac3f..0000000000
--- a/test/rexml/test_light.rb
+++ /dev/null
@@ -1,107 +0,0 @@
-# frozen_string_literal: false
-require_relative "rexml_test_utils"
-require "rexml/light/node"
-require "rexml/parsers/lightparser"
-
-module REXMLTests
- class LightTester < Test::Unit::TestCase
- include REXMLTestUtils
- include REXML::Light
-
- def test_parse_large
- xml_string = fixture_path("documentation.xml")
- parser = REXML::Parsers::LightParser.new(xml_string)
- tag, content = parser.parse
- assert_equal([:document, :text], [tag, content.first])
- end
-
- # FIXME INCOMPLETE
- # This is because the light API is not yet ready to be used to produce
- # trees.
-=begin
- def test_add_element
- doc = Node.new
- foo = doc.add_element( 'foo' )
- assert_equal( "foo", foo.name )
- end
-
- def test_add_attribute
- foo = Node.new( "a" )
- foo["attr"] = "bar"
- assert_equal( "bar", foo["attr"] )
- end
-
- def test_write_document
- r = make_small_document
- assert_equal( "<a><b/><c/></a>", r.to_s )
- end
-
- def test_add_attribute_under_namespace
- foo = Node.new("a")
- foo["attr", "a"] = "1"
- foo["attr", "b"] = "2"
- foo["attr"] = "3"
- assert_equal( '1', foo['attr', 'a'] )
- assert_equal( '2', foo['attr', 'b'] )
- assert_equal( '3', foo['attr'] )
- end
-
- def test_change_namespace_of_element
- foo = Node.new
- assert_equal( '', foo.namespace )
- foo.namespace = 'a'
- assert_equal( 'a', foo.namespace )
- end
-
- def test_access_child_elements
- foo = make_small_document
- assert_equal( 1, foo.size )
- a = foo[0]
- assert_equal( 2, a.size )
- assert_equal( 'b', a[0].name )
- assert_equal( 'c', a[1].name )
- end
-
- def test_itterate_over_children
- foo = make_small_document
- ctr = 0
- foo[0].each { ctr += 1 }
- assert_equal( 2, ctr )
- end
-
- def test_add_text
- foo = Node.new( "a" )
- foo.add_text( "Sean" )
- sean = foo[0]
- assert( sean.node_type == :text )
- end
-
- def test_add_instruction
- foo = Node.new( "a" )
- foo.add_instruction( "target", "value" )
- assert( foo[0].node_type == :processing_instruction )
- end
-
- def test_add_comment
- foo = Node.new( "a" )
- foo.add_comment( "target", "value" )
- assert( foo[0].node_type == :comment )
- end
-
- def test_get_root
- foo = Node.new( 'a' )
- 10.times { foo = foo.add_element('b') }
- assert_equals( 'b', foo.name )
- assert_equals( 'a', foo.root.name )
- end
-
- def make_small_document
- r = Node.new
- a = r.add_element( "a" )
- a.add_element( 'b' )
- a.add_element( 'c' )
- r
- end
-=end
- end
-end
diff --git a/test/rexml/test_lightparser.rb b/test/rexml/test_lightparser.rb
deleted file mode 100644
index 1aeac072dd..0000000000
--- a/test/rexml/test_lightparser.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: false
-require_relative 'rexml_test_utils'
-require 'rexml/parsers/lightparser'
-
-module REXMLTests
- class LightParserTester < Test::Unit::TestCase
- include REXMLTestUtils
- include REXML
- def test_parsing
- File.open(fixture_path("documentation.xml")) do |f|
- parser = REXML::Parsers::LightParser.new( f )
- parser.parse
- end
- end
- end
-end
diff --git a/test/rexml/test_listener.rb b/test/rexml/test_listener.rb
deleted file mode 100644
index 322d368be8..0000000000
--- a/test/rexml/test_listener.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-# coding: binary
-# frozen_string_literal: false
-
-require_relative 'rexml_test_utils'
-
-require 'rexml/document'
-require 'rexml/streamlistener'
-
-module REXMLTests
- class BaseTester < Test::Unit::TestCase
- include REXMLTestUtils
- def test_empty
- return unless defined? @listener
- # Empty.
- t1 = %Q{<string></string>}
- assert_equal( "", @listener.parse( t1 ),
- "Empty" )
- end
-
- def test_space
- return unless defined? @listener
- # Space.
- t2 = %Q{<string> </string>}
- assert_equal( " ", @listener.parse( t2 ),
- "Space" )
- end
-
- def test_whitespace
- return unless defined? @listener
- # Whitespaces.
- t3 = %Q{<string>RE\n \t \n \t XML</string>}
- assert_equal( "RE\n \t \n \t XML", @listener.parse( t3 ),
- "Whitespaces" )
- end
-
- def test_leading_trailing_whitespace
- return unless defined? @listener
- # Leading and trailing whitespaces.
- t4 = %Q{<string> REXML </string>}
- assert_equal( " REXML ", @listener.parse( t4 ),
- "Leading and trailing whitespaces" )
- end
-
- def test_entity_reference
- return unless defined? @listener
- # Entity reference.
- t5 = %Q{<string>&lt;&gt;&amp;lt;&amp;gt;</string>}
- assert_equal( "<>&lt;&gt;", @listener.parse( t5 ),
- "Entity reference" )
- end
-
- def test_character_reference
- return unless defined? @listener
- # Character reference.
- t6 = %Q{<string>&#xd;</string>}
- assert_equal( "\r", @listener.parse( t6 ),
- "Character reference." )
- end
-
- def test_cr
- return unless defined? @listener
- # CR.
- t7 = %Q{<string> \r\n \r \n </string>}
- assert_equal( " \n \n \n ".unpack("C*").inspect,
- @listener.parse( t7 ).unpack("C*").inspect, "CR" )
- end
-
- # The accent bug, and the code that exhibits the bug, was contributed by
- # Guilhem Vellut
- class AccentListener
- def tag_start(name,attributes)
- #p name
- #p attributes
- end
- def tag_end(name)
- #p "/"+name
- end
- def xmldecl(a,b,c)
- #puts "#{a} #{b} #{c}"
- end
- def text(tx)
- #p tx
- end
- end
-
- def test_accents
- source = %[<?xml version="1.0" encoding="ISO-8859-1"?>
-<g>
-<f a="\xE9" />
-</g>]
- doc = REXML::Document.new( source )
- a = doc.elements['/g/f'].attribute('a')
- if a.value.respond_to? :force_encoding
- a.value.force_encoding('binary')
- end
- assert_equal( "\xC3\xA9", a.value)
- doc = File::open(fixture_path("stream_accents.xml")) do |f|
- REXML::Document.parse_stream(f, AccentListener::new)
- end
- end
- end
-
- class MyREXMLListener
- include REXML::StreamListener
-
- def initialize
- @text = nil
- end
-
- def parse( stringOrReadable )
- @text = ""
- REXML::Document.parse_stream( stringOrReadable, self )
- @text
- end
-
- def text( text )
- @text << text
- end
- end
-
- class REXMLTester < BaseTester
- def setup
- @listener = MyREXMLListener.new
- end
-
- def test_character_reference_2
- t6 = %Q{<string>&#xd;</string>}
- assert_equal( t6.strip, REXML::Document.new(t6).to_s )
- end
- end
-end
diff --git a/test/rexml/test_martin_fowler.rb b/test/rexml/test_martin_fowler.rb
deleted file mode 100644
index add3c82723..0000000000
--- a/test/rexml/test_martin_fowler.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'rexml/document'
-
-module REXMLTests
- class OrderTesterMF < Test::Unit::TestCase
- DOC = <<END
-<paper>
-<title>Remove this element and figs order differently</title>
-<figure src="fig1"/>
-<figure src="fig2"/>
-<p>Para of text</p>
-<p>Remove this and figs order differently</p>
-<section>
-<figure src="fig3"/>
-</section>
-<figure src="fig4"/>
-</paper>
-END
-
- def initialize n
- @doc = REXML::Document.new(DOC)
- @figs = REXML::XPath.match(@doc,'//figure')
- @names = @figs.collect {|f| f.attributes['src']}
- super
- end
- def test_fig1
- assert_equal 'fig1', @figs[0].attributes['src']
- end
- def test_fig2
- assert_equal 'fig2', @figs[1].attributes['src']
- end
- def test_fig3
- assert_equal 'fig3', @figs[2].attributes['src']
- end
- def test_fig4
- assert_equal 'fig4', @figs[3].attributes['src']
- end
- end
-end
diff --git a/test/rexml/test_namespace.rb b/test/rexml/test_namespace.rb
deleted file mode 100644
index 90e1d36945..0000000000
--- a/test/rexml/test_namespace.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: false
-require_relative "rexml_test_utils"
-
-require "rexml/document"
-
-module REXMLTests
- class TestNamespace < Test::Unit::TestCase
- include REXMLTestUtils
- include REXML
-
- def setup
- @xsa_source = <<-EOL
- <?xml version="1.0"?>
- <?xsl stylesheet="blah.xsl"?>
- <!-- The first line tests the XMLDecl, the second tests PI.
- The next line tests DocType. This line tests comments. -->
- <!DOCTYPE xsa PUBLIC
- "-//LM Garshol//DTD XML Software Autoupdate 1.0//EN//XML"
- "http://www.garshol.priv.no/download/xsa/xsa.dtd">
-
- <xsa>
- <vendor id="blah">
- <name>Lars Marius Garshol</name>
- <email>larsga@garshol.priv.no</email>
- <url>http://www.stud.ifi.uio.no/~lmariusg/</url>
- </vendor>
- </xsa>
- EOL
- end
-
- def test_xml_namespace
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root xmlns:xml="http://www.w3.org/XML/1998/namespace" />
-XML
- document = Document.new(xml)
- assert_equal("http://www.w3.org/XML/1998/namespace",
- document.root.namespace("xml"))
- end
- end
-end
diff --git a/test/rexml/test_order.rb b/test/rexml/test_order.rb
deleted file mode 100644
index 807d9faa96..0000000000
--- a/test/rexml/test_order.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# frozen_string_literal: false
-require_relative 'rexml_test_utils'
-require 'rexml/document'
-begin
- require 'zlib'
-rescue LoadError
-end
-
-module REXMLTests
- class OrderTester < Test::Unit::TestCase
- include REXMLTestUtils
-
- TESTDOC = <<END
-<a>
- <b/>
- <x id='1'/>
- <c/>
- <d>
- <x id='2'/>
- </d>
- <x id='3'/>
-</a>
-END
-
- def setup
- @doc = REXML::Document.new(TESTDOC)
- @items = REXML::XPath.match(@doc,'//x')
- end
- def test_first_element
- assert_equal '1', @items[0].attributes['id']
- end
- def test_second_element
- assert_equal '2', @items[1].attributes['id']
- end
- def test_third_element
- assert_equal '3', @items[2].attributes['id']
- end
- def test_order
- d = REXML::Document.new( "<a><x id='1'/><x id='2'/><x id='3'/>
- <x id='4'/><x id='5'/></a>" )
- items = REXML::XPath.match( d, '//x' )
- assert_equal( %w{1 2 3 4 5}, items.collect{|e| e.attributes['id']} )
- d = REXML::Document.new( "<a>
- <x><z><y id='1'/><y id='2'/></z><y id='3'/></x>
- <x><y id='4'/></x></a>" )
- items = REXML::XPath.match( d, '//y' )
- assert_equal( %w{1 2 3 4}, items.collect{|e| e.attributes['id']} )
- end
- # Provided by Tom Talbott
- def test_more_ordering
- doc = Zlib::GzipReader.open(fixture_path('LostineRiver.kml.gz'), encoding: 'utf-8') do |f|
- REXML::Document.new(f)
- end
- actual = [
- "Head south from Phinney Ave N",
- "Turn left at N 36th St",
- "Turn right at Fremont Ave N",
- "Continue on 4th Ave N",
- "Turn left at Westlake Ave N",
- "Bear right at 9th Ave N",
- "Turn left at Mercer St",
- "Take the I-5 ramp",
- "Take the I-5 S ramp",
- "Take the I-90 E exit #164 to Bellevue/Spokane/4th Ave S.",
- "Take the I-90 E ramp to Bellevue/Spokane",
- "Take exit #137 to Wanapum Dam/Richland",
- "Bear right at WA-26",
- "Bear right and head toward WA-243",
- "Continue on WA-243",
- "Bear right at WA-24",
- "Continue on WA-240",
- "Turn right at WA-240 E",
- "Take the I-182 W ramp to Yakima (I-82)/Pendleton",
- "Take the I-82 E ramp to Umatilla/Pendleton",
- "Take the I-84 E ramp to Pendleton",
- "Take the OR-82 exit #261 to La Grande/Elgin",
- "Turn right at Island Ave",
- "Continue on W 1st St",
- "Turn left at N McAlister Rd",
- "Bear right at OR-82",
- "Continue on Wallowa Lake Hwy",
- "Continue on OR-82",
- "Continue on Ruckman Ave",
- "Continue on OR-82",
- "Continue on S 8th Ave",
- "Turn right at Albany St",
- "Continue on OR-82",
- "Continue on Wallowa Lake Hwy",
- "Continue on N Madison St",
- "Bear left at W 1st St",
- "Continue on Wallowa Lake Hwy",
- "Continue on Water St",
- "Bear right at Lostine River Rd",
- "Bear right and head toward Lostine River Rd",
- "Turn right at Lostine River Rd",
- "Continue on NF-8210",
- "Turn right and head toward NF-8210",
- "Turn right at NF-8210",
- "",
- "Route"
- ]
- count = 0
- REXML::XPath.each( doc, "//Placemark") { |element|
- n = element.elements["name"].text.squeeze(" ")
- assert_equal( actual[count], n ) unless n =~ /Arrive at/
- count += 1
- }
- end if defined?(Zlib::GzipReader)
- end
-end
diff --git a/test/rexml/test_preceding_sibling.rb b/test/rexml/test_preceding_sibling.rb
deleted file mode 100644
index d89a1e1c90..0000000000
--- a/test/rexml/test_preceding_sibling.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: false
-# ISSUE 32
-require 'test/unit'
-require 'rexml/document'
-
-module REXMLTests
- # daz - for report by Dan Kohn in:
- # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/156328
- class XPathTesterDd < Test::Unit::TestCase
- include REXML
-
- def setup
- @@docDd = Document.new(<<-EOS, :ignore_whitespace_nodes => :all)
- <a>
- <b x='ab01A'>
- <c y='abc01A'>Success</c>
- </b>
- <b x='ab02A' y='ab02B'>
- <c>abc02C</c>
- </b>
- </a>
- EOS
- end
-
- def test_Dd_preceding_sibling_children
- arr = []
- XPath.each(@@docDd, "//b[@x='ab02A']/preceding-sibling::b/child::*") do |cell|
- arr << cell.texts.join
- end
- assert_equal( 'Success', arr.join )
- end
-
- def test_Dd_preceding_sibling_all
- arr = []
- XPath.each(@@docDd, "//b[@x='ab02A']/preceding-sibling::*") do |cell|
- arr << cell.to_s
- end
- assert_equal( "<b x='ab01A'><c y='abc01A'>Success</c></b>", arr.join )
- end
- end
-end
diff --git a/test/rexml/test_pullparser.rb b/test/rexml/test_pullparser.rb
deleted file mode 100644
index 31b5b74bd6..0000000000
--- a/test/rexml/test_pullparser.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: false
-require "test/unit/testcase"
-
-require 'rexml/parsers/pullparser'
-
-module REXMLTests
- class PullParserTester < Test::Unit::TestCase
- include REXML
- def test_basics
- source = '<?xml version="1.0"?>
- <!DOCTYPE blah>
- <a>foo &lt;<b attribute="value">bar</b> nooo</a>'
- parser = REXML::Parsers::PullParser.new(source)
- res = { :text=>0 }
- until parser.empty?
- results = parser.pull
- res[ :xmldecl ] = true if results.xmldecl?
- res[ :doctype ] = true if results.doctype?
- res[ :a ] = true if results.start_element? and results[0] == 'a'
- if results.start_element? and results[0] == 'b'
- res[ :b ] = true
- assert_equal 'value', results[1]['attribute']
- end
- res[ :text ] += 1 if results.text?
- end
- [ :xmldecl, :doctype, :a, :b ].each { |tag|
- assert res[tag] , "#{tag} wasn't processed"
- }
- assert_equal 4, res[ :text ]
- rescue ParseException
- puts $!
- end
-
- def test_bad_document
- source = "<a><b></a>"
- parser = REXML::Parsers::PullParser.new(source)
- assert_raise(ParseException, "Parsing should have failed") {
- parser.pull while parser.has_next?
- }
- end
-
- def test_entity_replacement
- source = '<!DOCTYPE foo [
- <!ENTITY la "1234">
- <!ENTITY lala "--&la;--">
- <!ENTITY lalal "&la;&la;">
- ]><a><la>&la;</la><lala>&lala;</lala></a>'
- pp = REXML::Parsers::PullParser.new( source )
- el_name = ''
- while pp.has_next?
- event = pp.pull
- case event.event_type
- when :start_element
- el_name = event[0]
- when :text
- case el_name
- when 'la'
- assert_equal('1234', event[1])
- when 'lala'
- assert_equal('--1234--', event[1])
- end
- end
- end
- end
-
- def test_peek_unshift
- source = "<a><b/></a>"
- REXML::Parsers::PullParser.new(source)
- # FINISH ME!
- end
-
- def test_inspect
- xml = '<a id="1"><b id="2">Hey</b></a>'
- parser = Parsers::PullParser.new( xml )
- while parser.has_next?
- pull_event = parser.pull
- if pull_event.start_element?
- peek = parser.peek()
- peek.inspect
- end
- end
- end
-
- def test_peek
- xml = '<a id="1"><b id="2">Hey</b></a>'
- parser = Parsers::PullParser.new( xml )
- names = %w{ a b }
- while parser.has_next?
- pull_event = parser.pull
- if pull_event.start_element?
- assert_equal( :start_element, pull_event.event_type )
- assert_equal( names.shift, pull_event[0] )
- if names[0] == 'b'
- peek = parser.peek()
- assert_equal( :start_element, peek.event_type )
- assert_equal( names[0], peek[0] )
- end
- end
- end
- assert_equal( 0, names.length )
- end
- end
-end
diff --git a/test/rexml/test_rexml_issuezilla.rb b/test/rexml/test_rexml_issuezilla.rb
deleted file mode 100644
index 1c54c9d53d..0000000000
--- a/test/rexml/test_rexml_issuezilla.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: false
-require_relative 'rexml_test_utils'
-require 'rexml/document'
-
-module REXMLTests
- class TestIssuezillaParsing < Test::Unit::TestCase
- include REXMLTestUtils
- def test_rexml
- doc = File.open(fixture_path("ofbiz-issues-full-177.xml")) do |f|
- REXML::Document.new(f)
- end
- ctr = 1
- doc.root.each_element('//issue') do |issue|
- assert_equal( ctr, issue.elements['issue_id'].text.to_i )
- ctr += 1
- end
- end
- end
-end
diff --git a/test/rexml/test_sax.rb b/test/rexml/test_sax.rb
deleted file mode 100644
index 00539f0d4c..0000000000
--- a/test/rexml/test_sax.rb
+++ /dev/null
@@ -1,287 +0,0 @@
-# frozen_string_literal: false
-require_relative "rexml_test_utils"
-require 'rexml/sax2listener'
-require 'rexml/parsers/sax2parser'
-require 'rexml/document'
-
-module REXMLTests
- class SAX2Tester < Test::Unit::TestCase
- include REXMLTestUtils
- include REXML
- def test_characters
- d = Document.new( "<A>@blah@</A>" )
- txt = d.root.text
- p = Parsers::SAX2Parser.new "<A>@blah@</A>"
- p.listen(:characters) {|x| assert_equal txt, x}
- p.listen(:characters, ["A"]) {|x| assert_equal txt,x}
- p.parse
- end
-
- def test_entity_replacement
- source = '<!DOCTYPE foo [
- <!ENTITY la "1234">
- <!ENTITY lala "--&la;--">
- <!ENTITY lalal "&la;&la;">
- ]><a><la>&la;</la><lala>&lala;</lala></a>'
- sax = Parsers::SAX2Parser.new( source )
- results = []
- sax.listen(:characters) {|x| results << x }
- sax.parse
- assert_equal 2, results.size
- assert_equal '1234', results[0]
- assert_equal '--1234--', results[1]
- end
-
- def test_sax2
- File.open(fixture_path("documentation.xml")) do |f|
- parser = Parsers::SAX2Parser.new( f )
- # Listen to all events on the following elements
- count = 0
- blok = proc { |uri,localname,qname,attributes|
- assert %w{ bugs todo }.include?(localname),
- "Mismatched name; we got '#{qname}'\nArgs were:\n\tURI: #{uri}\n\tLOCALNAME: #{localname}\n\tQNAME: #{qname}\n\tATTRIBUTES: #{attributes.inspect}\n\tSELF=#{blok}"
- count += 1
- }
-
- start_document = 0
- end_document = 0
- parser.listen( :start_document ) { start_document += 1 }
- parser.listen( :end_document ) { end_document += 1 }
- parser.listen( :start_element, %w{ changelog bugs todo }, &blok )
- # Listen to all events on the following elements. Synonymous with
- # listen( :start_element, %w{ ... } )
- parser.listen( %w{ changelog bugs todo }, &blok )
- # Listen for all start element events
- parser.listen( :start_element ) { |uri,localname,qname,attributes|
- }
- listener = MySAX2Listener.new
- # Listen for all events
- parser.listen( listener )
- # Listen for all events on the given elements. Does not include children
- # events. Regular expressions work as well!
- parser.listen( %w{ /change/ bugs todo }, listener )
- # Test the deafening method
- blok = proc { |uri,localname,qname,attributes|
- assert_fail "This listener should have been deafened!"
- }
- parser.listen( %w{ changelog }, &blok )
- parser.deafen( &blok )
-
- tc = 0
- parser.listen( :characters, %w{version} ) {|text|
- assert(text=~/@ANT_VERSION@/, "version was '#{text}'")
- tc += 1
- }
-
- begin
- parser.parse
- rescue => exception
- if exception.kind_of? Test::Unit::AssertionFailedError
- raise exception
- end
- puts $!
- puts exception.backtrace
- end
- assert_equal 2, count
- assert_equal 1, tc
- assert_equal 1, start_document
- assert_equal 1, end_document
- end
- end
-
- # used by test_simple_doctype_listener
- # submitted by Jeff Barczewski
- class SimpleDoctypeListener
- include REXML::SAX2Listener
- attr_reader :name, :pub_sys, :long_name, :uri
-
- def initialize
- @name = @pub_sys = @long_name = @uri = nil
- end
-
- def doctype(name, pub_sys, long_name, uri)
- @name = name
- @pub_sys = pub_sys
- @long_name = long_name
- @uri = uri
- end
- end
-
- # test simple non-entity doctype in sax listener
- # submitted by Jeff Barczewski
- def test_simple_doctype_listener
- xml = <<-END
- <?xml version="1.0"?>
- <!DOCTYPE greeting PUBLIC "Hello Greeting DTD" "http://foo/hello.dtd">
- <greeting>Hello, world!</greeting>
- END
- parser = Parsers::SAX2Parser.new(xml)
- dtl = SimpleDoctypeListener.new
- parser.listen(dtl)
- tname = nil
- tpub_sys = nil
- tlong_name = nil
- turi = nil
- parser.listen(:doctype) do |name, pub_sys, long_name, uri|
- tname = name
- tpub_sys = pub_sys
- tlong_name = long_name
- turi = uri
- end
- parser.parse
- assert_equal 'greeting', tname, 'simple doctype block listener failed - incorrect name'
- assert_equal 'PUBLIC', tpub_sys, 'simple doctype block listener failed - incorrect pub_sys'
- assert_equal 'Hello Greeting DTD', tlong_name, 'simple doctype block listener failed - incorrect long_name'
- assert_equal 'http://foo/hello.dtd', turi, 'simple doctype block listener failed - incorrect uri'
- assert_equal 'greeting', dtl.name, 'simple doctype listener failed - incorrect name'
- assert_equal 'PUBLIC', dtl.pub_sys, 'simple doctype listener failed - incorrect pub_sys'
- assert_equal 'Hello Greeting DTD', dtl.long_name, 'simple doctype listener failed - incorrect long_name'
- assert_equal 'http://foo/hello.dtd', dtl.uri, 'simple doctype listener failed - incorrect uri'
- end
-
- # test doctype with missing name, should throw ParseException
- # submitted by Jeff Barczewseki
- def test_doctype_with_mising_name_throws_exception
- xml = <<-END
- <?xml version="1.0"?>
- <!DOCTYPE >
- <greeting>Hello, world!</greeting>
- END
- parser = Parsers::SAX2Parser.new(xml)
- assert_raise(REXML::ParseException, 'doctype missing name did not throw ParseException') do
- parser.parse
- end
- end
-
-
- class KouListener
- include REXML::SAX2Listener
- attr_accessor :sdoc, :edoc
- attr_reader :selem, :decl, :pi
- def initialize
- @sdoc = @edoc = @selem = false
- @decl = 0
- @pi = 0
- end
- def start_document
- @sdoc = true
- end
- def end_document
- @edoc = true
- end
- def xmldecl( *arg )
- @decl += 1
- end
- def processing_instruction( *arg )
- @pi += 1
- end
- def start_element( *arg )
- @selem = true
- end
- end
-
- # Submitted by Kou
- def test_begin_end_document
- parser = Parsers::SAX2Parser.new("<a/>")
-
- kl = KouListener.new
- parser.listen(kl)
- sd = false
- ed = false
- parser.listen(:start_document) { sd = true }
- parser.listen(:end_document) { ed = true }
-
- parser.parse
- assert( sd, ':start_document block failed' )
- assert( ed, ':end_document block failed' )
- assert( kl.sdoc, ':start_document listener failed' )
- assert( kl.edoc, ':end_document listener failed' )
- end
-
- # Submitted by Kou
- def test_listen_before_start
- # FIXME: the following comment should be a test for validity. (The xml declaration
- # is invalid).
- #parser = Parsers::SAX2Parser.new( "<?xml ?><?pi?><a><?pi?></a>")
- parser = Parsers::SAX2Parser.new( "<?xml version='1.0'?><?pi?><a><?pi?></a>")
- k1 = KouListener.new
- parser.listen( k1 )
- xmldecl = false
- pi = 0
- parser.listen( :xmldecl ) { xmldecl = true }
- parser.listen( :processing_instruction ) { pi += 1 }
-
- parser.parse
-
- assert( xmldecl, ':xmldecl failed' )
- assert_equal( 2, pi, ':processing_instruction failed' )
- assert( k1.decl, 'Listener for xmldecl failed' )
- assert_equal( 2, k1.pi, 'Listener for processing instruction failed' )
- end
-
-
- def test_socket
- require 'socket'
-
- TCPServer.open('127.0.0.1', 0) do |server|
- TCPSocket.open('127.0.0.1', server.addr[1]) do |socket|
- ok = false
- session = server.accept
- begin
- session << '<foo>'
- parser = REXML::Parsers::SAX2Parser.new(socket)
- Fiber.new do
- parser.listen(:start_element) do
- ok = true
- Fiber.yield
- end
- parser.parse
- end.resume
- assert(ok)
- ensure
- session.close
- end
- end
- end
- end
-
- def test_char_ref_sax2()
- parser = REXML::Parsers::SAX2Parser.new('<ABC>&#252;</ABC>')
- result = nil
- parser.listen(:characters) {|text| result = text.unpack('U*')}
- parser.parse()
- assert_equal(1, result.size)
- assert_equal(252, result[0])
- end
-
-
- def test_char_ref_dom()
- doc = REXML::Document.new('<ABC>&#252;</ABC>')
- result = doc.root.text.unpack('U*')
- assert_equal(1, result.size)
- assert_equal(252, result[0])
- end
-
- class Ticket68
- include REXML::SAX2Listener
- end
- def test_ticket_68
- File.open(fixture_path('ticket_68.xml')) do |f|
- parser = REXML::Parsers::SAX2Parser.new(f)
- parser.listen( Ticket68.new )
- begin
- parser.parse
- rescue
- p parser.source.position
- p parser.source.current_line
- puts $!.backtrace.join("\n")
- flunk $!.message
- end
- end
- end
- end
-
- class MySAX2Listener
- include REXML::SAX2Listener
- end
-end
diff --git a/test/rexml/test_stream.rb b/test/rexml/test_stream.rb
deleted file mode 100644
index 08d4462ef9..0000000000
--- a/test/rexml/test_stream.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: false
-require "test/unit/testcase"
-require "rexml/document"
-require 'rexml/streamlistener'
-require 'stringio'
-
-module REXMLTests
- class MyListener
- include REXML::StreamListener
- end
-
-
- class StreamTester < Test::Unit::TestCase
- # Submitted by Han Holl
- def test_listener
- data = %Q{<session1 user="han" password="rootWeiler" />\n<session2 user="han" password="rootWeiler" />}
-
- RequestReader.new( data )
- RequestReader.new( data )
- end
-
- def test_ticket_49
- source = StringIO.new( <<-EOL )
- <!DOCTYPE foo [
- <!ENTITY ent "replace">
- ]>
- <a>&ent;</a>
- EOL
- REXML::Document.parse_stream(source, MyListener.new)
- end
-
- def test_ticket_10
- source = StringIO.new( <<-EOL )
- <!DOCTYPE foo [
- <!ENTITY ent "replace">
- <!ATTLIST a
- xmlns:human CDATA #FIXED "http://www.foo.com/human">
- <!ELEMENT bar (#PCDATA)>
- <!NOTATION n1 PUBLIC "-//HM//NOTATION TEST1//EN" 'urn:x-henrikmartensson.org:test5'>
- ]>
- <a/>
- EOL
- listener = MyListener.new
- class << listener
- attr_accessor :events
- def entitydecl( content )
- @events[ :entitydecl ] = true
- end
- def attlistdecl( element_name, attributes, raw_content )
- @events[ :attlistdecl ] = true
- end
- def elementdecl( content )
- @events[ :elementdecl ] = true
- end
- def notationdecl( content )
- @events[ :notationdecl ] = true
- end
- end
- listener.events = {}
-
- REXML::Document.parse_stream( source, listener )
-
- assert( listener.events[:entitydecl] )
- assert( listener.events[:attlistdecl] )
- assert( listener.events[:elementdecl] )
- assert( listener.events[:notationdecl] )
- end
-
- def test_entity
- listener = MyListener.new
- class << listener
- attr_accessor :entities
- def entity(content)
- @entities << content
- end
- end
- listener.entities = []
-
- source = StringIO.new(<<-XML)
-<!DOCTYPE root [
-<!ENTITY % ISOLat2
- SYSTEM "http://www.xml.com/iso/isolat2-xml.entities" >
-%ISOLat2;
-]>
-<root/>
- XML
- REXML::Document.parse_stream(source, listener)
-
- assert_equal(["ISOLat2"], listener.entities)
- end
- end
-
-
- # For test_listener
- class RequestReader
- attr_reader :doc
- def initialize(io)
- @stack = []
- @doc = nil
- catch(:fini) do
- REXML::Document.parse_stream(io, self)
- raise IOError
- end
- end
- def tag_start(name, args)
- if @doc
- @stack.push(REXML::Element.new(name, @stack.last))
- else
- @doc = REXML::Document.new("<#{name}/>")
- @stack.push(@doc.root)
- end
- args.each do |attr,val|
- @stack.last.add_attribute(attr, val)
- end
- end
- def tag_end(name, *args)
- @stack.pop
- throw(:fini) if @stack.empty?
- end
- def text(str)
- @stack.last.text = str
- end
- def comment(str)
- end
- def doctype( name, pub_sys, long_name, uri )
- end
- def doctype_end
- end
- end
-end
diff --git a/test/rexml/test_text.rb b/test/rexml/test_text.rb
deleted file mode 100644
index e9a246e27f..0000000000
--- a/test/rexml/test_text.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "rexml_test_utils"
-
-module REXMLTests
- class TextTester < Test::Unit::TestCase
- include REXML
-
- def test_new_text_response_whitespace_default
- text = Text.new("a b\t\tc", true)
- assert_equal("a b\tc", Text.new(text).to_s)
- end
-
- def test_new_text_response_whitespace_true
- text = Text.new("a b\t\tc", true)
- assert_equal("a b\t\tc", Text.new(text, true).to_s)
- end
-
- def test_new_text_raw_default
- text = Text.new("&amp;lt;", false, nil, true)
- assert_equal("&amp;lt;", Text.new(text).to_s)
- end
-
- def test_new_text_raw_false
- text = Text.new("&amp;lt;", false, nil, true)
- assert_equal("&amp;amp;lt;", Text.new(text, false, nil, false).to_s)
- end
-
- def test_new_text_entity_filter_default
- document = REXML::Document.new(<<-XML)
-<!DOCTYPE root [
- <!ENTITY a "aaa">
- <!ENTITY b "bbb">
-]>
-<root/>
- XML
- text = Text.new("aaa bbb", false, document.root, nil, ["a"])
- assert_equal("aaa &b;",
- Text.new(text, false, document.root).to_s)
- end
-
- def test_new_text_entity_filter_custom
- document = REXML::Document.new(<<-XML)
-<!DOCTYPE root [
- <!ENTITY a "aaa">
- <!ENTITY b "bbb">
-]>
-<root/>
- XML
- text = Text.new("aaa bbb", false, document.root, nil, ["a"])
- assert_equal("&a; bbb",
- Text.new(text, false, document.root, nil, ["b"]).to_s)
- end
-
- def test_shift_operator_chain
- text = Text.new("original\r\n")
- text << "append1\r\n" << "append2\r\n"
- assert_equal("original\nappend1\nappend2\n", text.to_s)
- end
-
- def test_shift_operator_cache
- text = Text.new("original\r\n")
- text << "append1\r\n" << "append2\r\n"
- assert_equal("original\nappend1\nappend2\n", text.to_s)
- text << "append3\r\n" << "append4\r\n"
- assert_equal("original\nappend1\nappend2\nappend3\nappend4\n", text.to_s)
- end
-
- def test_clone
- text = Text.new("&amp;lt; <")
- assert_equal(text.to_s,
- text.clone.to_s)
- end
- end
-end
diff --git a/test/rexml/test_ticket_80.rb b/test/rexml/test_ticket_80.rb
deleted file mode 100644
index ab6a57efaf..0000000000
--- a/test/rexml/test_ticket_80.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: false
-#------------------------------------------------------------------------------
-# file: rexml_test.rb
-# desc: test's REXML's XML/XPath implementation
-# auth: Philip J Grabner <grabner>at<uberdev>dot<org>
-# date: 2006/08/17
-# copy: (C) CopyLoose 2006 Bib Development Team <bib-devel>at<uberdev>dot<org>
-#------------------------------------------------------------------------------
-
-require 'test/unit'
-require 'rexml/document'
-
-module REXMLTests
- class Ticket80 < Test::Unit::TestCase
-
- @@xmlstr = '<?xml version="1.0"?>
-<root xmlns="urn:some-xml-ns" xmlns:other="urn:some-other-xml-ns">
- <l1-foo>
- <l2 value="foo-01"/>
- <l2 value="foo-02"/>
- <l2 value="foo-03"/>
- </l1-foo>
- <other:l1>
- <l2 value="no-show"/>
- </other:l1>
- <l1-bar>
- <l2 value="bar-01"/>
- <l2 value="bar-02"/>
- </l1-bar>
-</root>'
-
- #----------------------------------------------------------------------------
- def test_xpathNamespacedChildWildcard
- # tests the "prefix:*" node test syntax
- out = Array.new
- REXML::XPath.each( REXML::Document.new(@@xmlstr),
- '/ns:root/ns:*/ns:l2/@value',
- { 'ns' => 'urn:some-xml-ns' } ) do |node| out.push node.value ; end
- chk = [ 'foo-01', 'foo-02', 'foo-03', 'bar-01', 'bar-02' ]
- assert_equal chk, out
- end
-
- #----------------------------------------------------------------------------
- def test_xpathNamespacedChildWildcardWorkaround
- # tests a workaround for the "prefix:*" node test syntax
- out = Array.new
- REXML::XPath.each( REXML::Document.new(@@xmlstr),
- '/ns:root/*[namespace-uri()="urn:some-xml-ns"]/ns:l2/@value',
- { 'ns' => 'urn:some-xml-ns' } ) do |node| out.push node.value ; end
- chk = [ 'foo-01', 'foo-02', 'foo-03', 'bar-01', 'bar-02' ]
- assert_equal chk, out
- end
-
- end
-end
-
-#------------------------------------------------------------------------------
-# end of rexml_test.rb
-#------------------------------------------------------------------------------
diff --git a/test/rexml/test_validation_rng.rb b/test/rexml/test_validation_rng.rb
deleted file mode 100644
index b5b50450e0..0000000000
--- a/test/rexml/test_validation_rng.rb
+++ /dev/null
@@ -1,793 +0,0 @@
-# frozen_string_literal: false
-require "test/unit/testcase"
-
-require "rexml/document"
-require "rexml/validation/relaxng"
-
-module REXMLTests
- class RNGValidation < Test::Unit::TestCase
- include REXML
-
- def test_validate
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <element name="C">
- <attribute name="X"/>
- <zeroOrMore>
- <element name="E">
- <empty/>
- </element>
- </zeroOrMore>
- </element>
- <element name="D">
- <empty/>
- </element>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- no_error( validator, %q{<A><B><C X="x"><E/><E/></C><D/></B></A>} )
- error( validator, %q{<A><B><D/><C X="x"/></B></A>} )
- end
-
-
- def test_sequence
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <element name="C">
- <empty/>
- </element>
- <element name="D">
- <empty/>
- </element>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B><C/><C/><D/></B></A>} )
- error( validator, %q{<A><B><D/><C/></B></A>} )
- error( validator, %q{<A><C/><D/></A>} )
- no_error( validator, %q{<A><B><C/><D/></B></A>} )
- end
-
-
- def test_choice
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <choice>
- <element name="C">
- <empty/>
- </element>
- <element name="D">
- <empty/>
- </element>
- </choice>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B><C/><D/></B></A>} )
- no_error( validator, %q{<A><B><D/></B></A>} )
- no_error( validator, %q{<A><B><C/></B></A>} )
- end
-
- def test_optional
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <optional>
- <element name="C">
- <empty/>
- </element>
- </optional>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- no_error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><B><C/></B></A>} )
- error( validator, %q{<A><B><D/></B></A>} )
- error( validator, %q{<A><B><C/><C/></B></A>} )
- end
-
- def test_zero_or_more
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <zeroOrMore>
- <element name="C">
- <empty/>
- </element>
- </zeroOrMore>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
- no_error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><B><C/></B></A>} )
- no_error( validator, %q{<A><B><C/><C/><C/></B></A>} )
- error( validator, %q{<A><B><D/></B></A>} )
- error( validator, %q{<A></A>} )
-
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <zeroOrMore>
- <element name="C">
- <empty/>
- </element>
- <element name="D">
- <empty/>
- </element>
- </zeroOrMore>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- no_error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><B><C/><D/></B></A>} )
- no_error( validator, %q{<A><B><C/><D/><C/><D/></B></A>} )
- error( validator, %q{<A><B><D/></B></A>} )
- end
-
- def test_one_or_more
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <oneOrMore>
- <element name="C">
- <empty/>
- </element>
- </oneOrMore>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><B><C/></B></A>} )
- no_error( validator, %q{<A><B><C/><C/><C/></B></A>} )
- error( validator, %q{<A><B><D/></B></A>} )
- error( validator, %q{<A></A>} )
- end
-
- def test_attribute
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <attribute name="X"/>
- <attribute name="Y"/>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A/>} )
- error( validator, %q{<A X=""/>} )
- no_error( validator, %q{<A X="1" Y="1"/>} )
- end
-
- def test_choice_attributes
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <choice>
- <attribute name="X"/>
- <attribute name="Y"/>
- </choice>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A X="1" Y="1"/>} )
- error( validator, %q{<A/>} )
- no_error( validator, %q{<A X="1"/>})
- no_error( validator, %q{<A Y="1"/>} )
- end
-
- def test_choice_attribute_element
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <choice>
- <attribute name="X"/>
- <element name="B"/>
- </choice>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A X="1"><B/></A>} )
- error( validator, %q{<A/>} )
- no_error( validator, %q{<A X="1"/>})
- no_error( validator, %q{<A><B/></A>} )
- end
-
- def test_empty
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <empty/>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A>Text</A>} )
- no_error( validator, %q{<A/>})
- end
-
- def test_text_val
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <text/>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A>Text</A>} )
- error( validator, %q{<A/>})
- end
-
- def test_choice_text
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <choice>
- <element name="B"/>
- <text/>
- </choice>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/>Text</A>} )
- error( validator, %q{<A>Text<B/></A>} )
- no_error( validator, %q{<A>Text</A>} )
- no_error( validator, %q{<A><B/></A>} )
- end
-
- def test_group
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <choice>
- <element name="B"/>
- <group>
- <element name="C"/>
- <element name="D"/>
- </group>
- </choice>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/><C/></A>} )
- error( validator, %q{<A><C/></A>} )
- no_error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><C/><D/></A>} )
-
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B"/>
- <group>
- <element name="C"/>
- <element name="D"/>
- </group>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/><C/></A>} )
- error( validator, %q{<A><B/><D/></A>} )
- error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><B/><C/><D/></A>} )
- end
-
- def test_value
- # Values as text nodes
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <value>VaLuE</value>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B>X</B></A>} )
- error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><B>VaLuE</B></A>} )
-
- # Values as text nodes, via choice
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <choice>
- <value>Option 1</value>
- <value>Option 2</value>
- </choice>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A><B>XYZ</B></A>} )
- no_error( validator, %q{<A><B>Option 1</B></A>} )
- no_error( validator, %q{<A><B>Option 2</B></A>} )
-
- # Attribute values
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <attribute name="B">
- <value>VaLuE</value>
- </attribute>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A/>} )
- error( validator, %q{<A B=""/>} )
- error( validator, %q{<A B="Lala"/>} )
- no_error( validator, %q{<A B="VaLuE"/>} )
-
- # Attribute values via choice
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <attribute name="B">
- <choice>
- <value>Option 1</value>
- <value>Option 2</value>
- </choice>
- </attribute>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A B=""/>} )
- error( validator, %q{<A B="Value"/>} )
- no_error( validator, %q{<A B="Option 1"></A>} )
- no_error( validator, %q{<A B="Option 2"/>} )
- end
-
- def test_interleave
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <interleave>
- <element name="C"/>
- <element name="D"/>
- <element name="E"/>
- </interleave>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B><C/></B></A>} )
- error( validator, %q{<A><B><C/><D/><C/></B></A>} )
- no_error( validator, %q{<A><B><C/><D/><E/></B></A>} )
- no_error( validator, %q{<A><B><E/><D/><C/></B></A>} )
- no_error( validator, %q{<A><B><D/><C/><E/></B></A>} )
- no_error( validator, %q{<A><B><E/><C/><D/></B></A>} )
- error( validator, %q{<A><B><E/><C/><D/><C/></B></A>} )
- end
-
- def test_mixed
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<element name="A" xmlns="http://relaxng.org/ns/structure/1.0">
- <element name="B">
- <mixed>
- <element name="D"/>
- </mixed>
- </element>
-</element>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- no_error( validator, %q{<A><B>Text<D/></B></A>} )
- no_error( validator, %q{<A><B><D/>Text</B></A>} )
- end
-
- def test_ref_sequence
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <ref name="B"/>
- <ref name="B"/>
- </element>
- </start>
-
- <define name="B">
- <element name="B">
- <attribute name="X"/>
- </element>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- no_error( validator, %q{<A><B X=''/><B X=''/></A>} )
- error( validator, %q{<A><B X=''/></A>} )
- end
-
- def test_ref_choice
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <choice>
- <ref name="B"/>
- </choice>
- </element>
- </start>
-
- <define name="B">
- <element name="B"/>
- <element name="C"/>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><D/></A>} )
- error( validator, %q{<A><B/><C/></A>} )
- no_error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><C/></A>} )
-
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <ref name="B"/>
- </element>
- </start>
-
- <define name="B">
- <choice>
- <element name="B"/>
- <element name="C"/>
- </choice>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><D/></A>} )
- error( validator, %q{<A><B/><C/></A>} )
- no_error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><C/></A>} )
-
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <choice>
- <ref name="B"/>
- <element name="D"/>
- </choice>
- </element>
- </start>
-
- <define name="B">
- <element name="B"/>
- <element name="C"/>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/><C/></A>} )
- no_error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><C/></A>} )
- no_error( validator, %q{<A><D/></A>} )
- end
-
-
- def test_ref_zero_plus
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <zeroOrMore>
- <ref name="B"/>
- </zeroOrMore>
- </element>
- </start>
-
- <define name="B">
- <element name="B">
- <attribute name="X"/>
- </element>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A/>} )
- no_error( validator, %q{<A><B X=''/></A>} )
- no_error( validator, %q{<A><B X=''/><B X=''/><B X=''/></A>} )
-
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <ref name="B"/>
- </element>
- </start>
-
- <define name="B">
- <zeroOrMore>
- <element name="B">
- <attribute name="X"/>
- </element>
- </zeroOrMore>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A/>} )
- no_error( validator, %q{<A><B X=''/></A>} )
- no_error( validator, %q{<A><B X=''/><B X=''/><B X=''/></A>} )
- end
-
-
- def test_ref_one_plus
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <oneOrMore>
- <ref name="B"/>
- </oneOrMore>
- </element>
- </start>
-
- <define name="B">
- <element name="B">
- <attribute name="X"/>
- </element>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A/>} )
- no_error( validator, %q{<A><B X=''/></A>} )
- no_error( validator, %q{<A><B X=''/><B X=''/><B X=''/></A>} )
-
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <ref name="B"/>
- </element>
- </start>
-
- <define name="B">
- <oneOrMore>
- <element name="B">
- <attribute name="X"/>
- </element>
- </oneOrMore>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A/>} )
- no_error( validator, %q{<A><B X=''/></A>} )
- no_error( validator, %q{<A><B X=''/><B X=''/><B X=''/></A>} )
- end
-
- def test_ref_interleave
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <interleave>
- <ref name="B"/>
- </interleave>
- </element>
- </start>
-
- <define name="B">
- <element name="B"/>
- <element name="C"/>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A><C/></A>} )
- error( validator, %q{<A><C/><C/></A>} )
- no_error( validator, %q{<A><B/><C/></A>} )
- no_error( validator, %q{<A><C/><B/></A>} )
-
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <ref name="B"/>
- </element>
- </start>
-
- <define name="B">
- <interleave>
- <element name="B"/>
- <element name="C"/>
- </interleave>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A><C/></A>} )
- error( validator, %q{<A><C/><C/></A>} )
- no_error( validator, %q{<A><B/><C/></A>} )
- no_error( validator, %q{<A><C/><B/></A>} )
-
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <interleave>
- <ref name="B"/>
- <ref name="C"/>
- </interleave>
- </element>
- </start>
-
- <define name="B">
- <element name="B"/>
- </define>
- <define name="C">
- <element name="C"/>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A><C/></A>} )
- error( validator, %q{<A><C/><C/></A>} )
- no_error( validator, %q{<A><B/><C/></A>} )
- no_error( validator, %q{<A><C/><B/></A>} )
- end
-
- def test_ref_recurse
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <ref name="B"/>
- </element>
- </start>
-
- <define name="B">
- <element name="B">
- <optional>
- <ref name="B"/>
- </optional>
- </element>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- error( validator, %q{<A></A>} )
- no_error( validator, %q{<A><B/></A>} )
- no_error( validator, %q{<A><B><B/></B></A>} )
- end
-
- def test_ref_optional
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <optional>
- <ref name="B"/>
- </optional>
- </element>
- </start>
-
- <define name="B">
- <element name="B">
- </element>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- no_error( validator, %q{<A></A>} )
- no_error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A><B/><B/></A>} )
- error( validator, %q{<A><C/></A>} )
-
- rng = %q{
-<?xml version="1.0" encoding="UTF-8"?>
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
- <start>
- <element name="A">
- <ref name="B"/>
- </element>
- </start>
-
- <define name="B">
- <optional>
- <element name="B">
- </element>
- </optional>
- </define>
-</grammar>
- }
- validator = REXML::Validation::RelaxNG.new( rng )
-
- no_error( validator, %q{<A></A>} )
- no_error( validator, %q{<A><B/></A>} )
- error( validator, %q{<A><B/><B/></A>} )
- error( validator, %q{<A><C/></A>} )
- end
-
-
-
- def error( validator, source )
- parser = REXML::Parsers::TreeParser.new( source )
- parser.add_listener( validator.reset )
- assert_raise( REXML::Validation::ValidationException,
- "Expected a validation error" ) { parser.parse }
- end
-
- def no_error( validator, source )
- parser = REXML::Parsers::TreeParser.new( source )
- parser.add_listener( validator.reset )
- assert_nothing_raised { parser.parse }
- end
- end
-end
diff --git a/test/rexml/test_xml_declaration.rb b/test/rexml/test_xml_declaration.rb
deleted file mode 100644
index da7076126e..0000000000
--- a/test/rexml/test_xml_declaration.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: false
-#
-# Created by Henrik Mårtensson on 2007-02-18.
-# Copyright (c) 2007. All rights reserved.
-
-require "rexml/document"
-require "test/unit"
-
-module REXMLTests
- class TestXmlDeclaration < Test::Unit::TestCase
- def setup
- xml = <<-XML
- <?xml encoding= 'UTF-8' standalone='yes'?>
- <root>
- </root>
- XML
- @doc = REXML::Document.new xml
- @root = @doc.root
- @xml_declaration = @doc.children[0]
- end
-
- def test_is_first_child
- assert_kind_of(REXML::XMLDecl, @xml_declaration)
- end
-
- def test_has_document_as_parent
- assert_kind_of(REXML::Document, @xml_declaration.parent)
- end
-
- def test_has_sibling
- assert_kind_of(REXML::XMLDecl, @root.previous_sibling.previous_sibling)
- assert_kind_of(REXML::Element, @xml_declaration.next_sibling.next_sibling)
- end
-
- def test_write_prologue_quote
- @doc.context[:prologue_quote] = :quote
- assert_equal("<?xml version=\"1.0\" " +
- "encoding=\"UTF-8\" standalone=\"yes\"?>",
- @xml_declaration.to_s)
- end
-
- def test_is_writethis_attribute_copied_by_clone
- assert_equal(true, @xml_declaration.clone.writethis)
- @xml_declaration.nowrite
- assert_equal(false, @xml_declaration.clone.writethis)
- end
- end
-end
diff --git a/test/rexml/xpath/test_attribute.rb b/test/rexml/xpath/test_attribute.rb
deleted file mode 100644
index 713d77b22f..0000000000
--- a/test/rexml/xpath/test_attribute.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'rexml/document'
-
-module REXMLTests
- class TestXPathAttribute < Test::Unit::TestCase
- def setup
- @xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root xmlns="http://example.com/">
- <child name="one">child1</child>
- <child name="two">child2</child>
- <child name="three">child3</child>
-</root>
- XML
- @document = REXML::Document.new(@xml)
- end
-
- def test_elements
- root = @document.elements["root"]
- second_child = root.elements["child[@name='two']"]
- assert_equal("child2", second_child.text)
- end
-
- def test_xpath_each
- children = REXML::XPath.each(@document, "/root/child[@name='two']")
- assert_equal(["child2"], children.collect(&:text))
- end
-
- def test_no_namespace
- children = REXML::XPath.match(@document,
- "/root/child[@nothing:name='two']",
- "" => "http://example.com/",
- "nothing" => "")
- assert_equal(["child2"], children.collect(&:text))
- end
- end
-end
diff --git a/test/rexml/xpath/test_axis_preceding_sibling.rb b/test/rexml/xpath/test_axis_preceding_sibling.rb
deleted file mode 100644
index 5842c6bc50..0000000000
--- a/test/rexml/xpath/test_axis_preceding_sibling.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: false
-require "test/unit/testcase"
-require "rexml/document"
-
-module REXMLTests
- class TestXPathAxisPredcedingSibling < Test::Unit::TestCase
- include REXML
- SOURCE = <<-EOF
- <a id='1'>
- <e id='2'>
- <f id='3'/>
- <f id='4'/>
- <f id='5'/>
- <f id='6'/>
- </e>
- </a>
- EOF
-
- def setup
- @@doc = Document.new(SOURCE) unless defined? @@doc
- end
-
- def test_preceding_sibling_axis
- context = XPath.first(@@doc,"/a/e/f[last()]")
- assert_equal "6", context.attributes["id"]
-
- prev = XPath.first(context, "preceding-sibling::f")
- assert_equal "5", prev.attributes["id"]
-
- prev = XPath.first(context, "preceding-sibling::f[1]")
- assert_equal "5", prev.attributes["id"]
-
- prev = XPath.first(context, "preceding-sibling::f[2]")
- assert_equal "4", prev.attributes["id"]
-
- prev = XPath.first(context, "preceding-sibling::f[3]")
- assert_equal "3", prev.attributes["id"]
- end
- end
-end
diff --git a/test/rexml/xpath/test_base.rb b/test/rexml/xpath/test_base.rb
deleted file mode 100644
index 210d6c7c81..0000000000
--- a/test/rexml/xpath/test_base.rb
+++ /dev/null
@@ -1,1125 +0,0 @@
-# frozen_string_literal: false
-require_relative "../rexml_test_utils"
-
-require "rexml/document"
-
-module REXMLTests
- class TestXPathBase < Test::Unit::TestCase
- include REXMLTestUtils
- include REXML
- SOURCE = <<-EOF
- <a id='1'>
- <b id='2' x='y'>
- <c id='3'/>
- <c id='4'/>
- </b>
- <d id='5'>
- <c id='6' x='y'/>
- <c id='7'/>
- <c id='8'/>
- <q id='19'/>
- </d>
- <e id='9'>
- <f id='10' a='b'/>
- <f id='11' a='c'/>
- <f id='12' a='d'>
- <g id='13'/>
- </f>
- <f id='14' a='d'/>
- </e>
- <m id='15'>
- <n id='16'>
- <o id='17'>
- <p id='18'/>
- </o>
- </n>
- </m>
- </a>
- EOF
- JENI_TENNISON = <<-EOJT
- <a>
- <b>
- <c>
- <d>
- <e id='x'>
- <f/>
- </e>
- </d>
- </c>
- <c>
- <d>
- <e id='y'/>
- </d>
- </c>
- </b>
- <b>
- <c>
- <d>
- <e id='z'/>
- </d>
- </c>
- </b>
- </a>
- EOJT
-
- def setup
- @@doc = Document.new(SOURCE) unless defined? @@doc
- @@jeni = Document.new( JENI_TENNISON ) unless defined? @@jeni
- end
-
- def each_test( element, xpath )
- count = 0
- XPath::each( element, xpath ) { |child|
- count += 1
- yield child if block_given?
- }
- count
- end
-
- def test_descendant
- doc = Document.new("<a><b><c id='1'/></b><d><b><c id='2'/></b></d></a>")
- p = XPath.match( doc, "//c" )
- assert_equal( 2, p.size )
- p = XPath.first( @@doc, "//p" )
- assert_equal "p", p.name
- c = each_test( @@doc, "//c" ) { |child| assert_equal "c", child.name }
- assert_equal 5, c
- c = each_test( @@doc.root, "b//c" ) { |child|
- assert_equal "c", child.name
- }
- assert_equal 2, c
-
- doc = Document.new( "<a><z id='1'/><b><z id='11'/><z id='12'/></b><c><z id='21'/><z id='22'/><d><z id='31'/><z id='32'/></d></c></a>" )
- # //para[1] : all descendants which are the first para child of their parent
- assert_equal( 4, XPath.match( doc, "//z[1]" ).size )
- # /descendant::para[1] : the first descendant para element
- assert_equal( 1, XPath.match( doc, "/descendant::z[1]" ).size )
- end
-
- def test_root
- source = "<a><b/></a>"
- doc = Document.new( source )
- assert_equal doc, doc.root_node
- assert_equal "a", XPath::first( doc, "/" ).elements[1].name
- end
-
- def test_abbreviated_simple_child
- assert_equal "a", XPath::first(@@doc, "a").name
- end
-
- def test_child
- c = XPath::first( @@doc, "a/b/c" )
- assert_equal "c", c.name
- assert_equal "3", XPath::first(@@doc, "a/b/c").attributes["id"]
- end
-
- def test_root_child
- assert_equal "a", XPath::first(@@doc, "/a").name
- c = XPath::first( @@doc, "a/b/c" )
- assert_equal "a", XPath::first(c, "/a").name
- end
-
- def test_root_children
- c = XPath::first( @@doc, "a/b/c" )
- assert_equal "2", XPath::first(c, "/a/b").attributes["id"]
- end
-
- def test_abbreviated_step
- c = XPath::first( @@doc, "a/b/c" )
- assert_equal("c", c.name)
- assert_equal("a", XPath::first(@@doc.root, ".").name)
- assert_equal("b", XPath::first(c, "..").name)
- assert_equal("a", XPath::first(@@doc, "a/b/..").name)
-
- doc = File.open(fixture_path("project.xml")) do |f|
- REXML::Document.new(f)
- end
- c = each_test(doc.root, "./Description" ) { |child|
- assert_equal("Description",child.name)
- }
- assert_equal 1, c
- end
-
- # Things that aren't tested elsewhere
- def test_predicates
- assert_equal "12", XPath::first(@@doc, "a/e/f[3]").attributes["id"]
- assert_equal "13", XPath::first(@@doc, "a/e/f[3]/g").attributes["id"]
- assert_equal "14", XPath::first(@@doc, "a/e/f[@a='d'][2]").attributes["id"]
- assert_equal "14", XPath::first(@@doc, "a/e/f[@a='d'][@id='14']").attributes["id"]
- assert_equal "a", XPath::first( @@doc, "*[name()='a' and @id='1']" ).name
- c=each_test( @@doc, "//*[name()='f' and @a='d']") { |i|
- assert_equal "f", i.name
- }
- assert_equal 2, c
- c=each_test( @@doc, "//*[name()='m' or @a='d']") { |i|
- assert ["m","f"].include?(i.name)
- }
- assert_equal 3, c
-
- assert_equal "b", XPath::first( @@doc, "//b[@x]" ).name
- end
-
- def test_node_type
- doc = Document.new "<a><?foo bar?><!--comment-->text</a>"
- #res = XPath::first(doc.root, "text()")
- #assert_equal "text", res.to_s
-
- #res = XPath::first(doc, "*")
- #assert_equal "a", res.name
-
- assert_equal( :processing_instruction,
- XPath::first(doc.root, "processing-instruction()").node_type)
- assert_equal( :comment, XPath::first(doc.root, "comment()").node_type)
- end
-
- def test_functions
- # trivial text() test
- # confuse-a-function
- source = "<a>more <b id='1'/><b id='2'>dumb</b><b id='3'/><c/> text</a>"
- doc = Document.new source
- res = ""
- #XPath::each(doc.root, "text()") {|val| res << val.to_s}
- #assert_equal "more text", res
-
- #res = XPath::first(doc.root, "b[last()]")
- #assert_equal '3', res.attributes['id']
- res = XPath::first(doc.root, "b[position()=2]")
- assert_equal '2', res.attributes['id']
- res = XPath::first(doc.root, "*[name()='c']")
- assert_equal "c", res.name
- end
-
- def no_test_ancestor
- doc = REXML::Document.new(File.new(fixture_path("testsrc.xml")))
- doc.elements.each("//item") { |el| print el.name
- if el.attributes['x']
- puts " -- "+el.attributes['x']
- else
- puts
- end
- }
- doc.elements.each("//item/ancestor::") { |el| print el.name
- if el.attributes['x']
- puts " -- "+el.attributes['x']
- else
- puts
- end
- }
- end
-
- # Here are some XPath tests that were originally submitted by ...
- # The code has changed some, but the logic and the source documents are the
- # same.
- # This method reads a document from a file, and then a series of xpaths,
- # also from a file. It then checks each xpath against the source file.
- def test_more
- xmlsource = fixture_path("testsrc.xml")
- xpathtests = fixture_path("xp.tst")
-
- doc = File.open(xmlsource) {|f| REXML::Document.new(f) }
- #results = ""
- results = REXML::Document.new
- results.add_element "test-results"
- File.foreach(xpathtests) do |line|
- line.strip!
- begin
- doc.root
- #puts "#"*80
- #print "\nDoing #{line} " ; $stdout.flush
- doc.elements.each(line) do |el|
- #print "." ; $stdout.flush
- results.root << el.clone
- #results << el.to_s
- end
- #ObjectSpace.garbage_collect
- GC::start
- rescue Exception => z
- #puts "\n'#{line}' failed"
- fail("Error on line #{line}:\n#{z.message}\n"+z.backtrace[0,10].join("\n"))
- #results.root.add_element( "error", {"path"=>line}).text = z.message+"\n"+z.backtrace[0,10].join("\n")
- #results << "<error path='"+line+"'>"+z.message+"</error>"
- end
- end
- end
-
- def test_axe_descendant
- assert_equal "f", XPath::first( @@doc, "descendant::f").name
- end
-
- def test_axe_parent
- q = XPath.first( @@doc, "a/d/c/parent::*/q" )
- assert_equal 19, q.attributes["id"].to_i
- end
-
- def test_abbreviated_attribute
- assert_equal 'a', XPath::first( @@doc, "a[@id='1']" ).name
- c = XPath::first( @@doc, "a/b/c[@id='4']" )
- assert_equal 'c', c.name
- assert_equal '4', c.attributes['id']
-
- result = XPath::first( @@doc, "descendant::f[@a='c']")
- assert_equal "11", result.attributes['id']
-
- assert_equal "11", XPath::first(@@doc, "a/e/f[@a='c']").attributes["id"]
- assert_equal "11", XPath::first(@@doc, "a/e/*[@a='c']").attributes["id"]
- end
-
- def test_axe_self
- c = XPath::first( @@doc, "a/b/c" )
- assert c
- assert_equal "c", c.name
- assert_equal "c", XPath::first( c, "self::node()" ).name
- end
-
- def test_axe_ancestor
- doc = REXML::Document.new "
- <a>
- <b id='1'>
- <c>
- <b id='2'>
- <d/>
- </b>
- </c>
- </b>
- </a>"
-
- d = XPath.first( doc, "//d" )
- assert_equal "d", d.name
- b = each_test( d, "ancestor::b" ) { |el|
- assert((1..2) === el.attributes['id'].to_i,
- "Expected #{el.attributes['id']} to be either 1 or 2"
- )
- }
- assert_equal 2, b
- end
-
- def test_axe_child
- m = XPath.first( @@doc, "a/child::m" )
- assert_equal 15, m.attributes['id'].to_i
- end
-
- def test_axe_attribute
- a = XPath.first( @@doc, "a/attribute::id" )
- assert_equal "1", a.value
- a = XPath.first( @@doc, "a/e/f[@id='14']/attribute::a" )
- assert_equal "d", a.value
- end
-
- def test_axe_sibling
- doc = Document.new "<a><b><c/></b><e><f id='10'/><f id='11'/><f id='12'/></e></a>"
- first_f = XPath.first( doc, "a/e/f" )
- assert first_f
- assert_equal '10', first_f.attributes['id']
- next_f = XPath.first( doc, "a/e/f/following-sibling::node()" )
- assert_equal '11', next_f.attributes['id']
-
- b = XPath.first( doc, "a/e/preceding-sibling::node()" )
- assert_equal 'b', b.name
- end
-
- def test_lang
- doc = File.open(fixture_path("lang0.xml")) {|f| Document.new(f) }
- #puts IO.read( "test/lang.xml" )
-
- #puts XPath.match( doc, "//language/*" ).size
- c = each_test( doc, "//language/*" ) { |element|
- #puts "#{element.name}: #{element.text}"
- }
- assert_equal 4, c
- end
-
- def test_namespaces_1
- source = <<-EOF
- <foo xmlns:ts="this" xmlns:tt="that">
- <ts:bar>this bar</ts:bar>
- <tt:bar>that bar</tt:bar>
- </foo>
- EOF
- doc = Document.new source
- XPath.each( doc, "//bar" ) {
- fail "'bar' should match nothing in this case"
- }
-
- namespace = {"t"=>"this"}
- results = XPath.first( doc, "//t:bar", namespace )
- assert_equal "this bar", results.text
- end
-
- def test_namespaces_2
- source = <<-EOF
- <foo xmlns:ts="this" xmlns:tt="that">
- <ts:bar>this bar</ts:bar>
- <tt:bar>that bar</tt:bar>
- </foo>
- EOF
- doc = Document.new source
- res = XPath::first(doc, "//*[local_name()='bar']")
- assert res, "looking for //*[name()='bar']"
- assert_equal 'this', res.namespace
- res = XPath::first(doc.root, "*[namespace_uri()='that']")
- assert_equal 'that bar', res.text
- end
-
- def test_complex
- next_f = XPath.first( @@doc, "a/e/f[@id='11']/following-sibling::*" )
- assert_equal 12, next_f.attributes['id'].to_i
- prev_f = XPath.first( @@doc, "a/e/f[@id='11']/preceding-sibling::*" )
- assert_equal 10, prev_f.attributes['id'].to_i
- c = each_test( @@doc, "descendant-or-self::*[@x='y']" )
- assert_equal 2, c
- end
-
- def match(xpath)
- XPath.match(@@doc, xpath).collect(&:to_s)
- end
-
- def test_grouping
- assert_equal([],
- match("a/d/*[name()='d' and (name()='f' or name()='q')]"))
- assert_equal(["<q id='19'/>"],
- match("a/d/*[(name()='d' and name()='f') or name()='q']"))
- end
-
- def test_preceding
- d = Document.new "<a><b id='0'/><b id='2'/><b><c id='0'/><c id='1'/><c id='2'/></b><b id='1'/></a>"
- start = XPath.first( d, "/a/b[@id='1']" )
- assert_equal 'b', start.name
- c = XPath.first( start, "preceding::c" )
- assert_equal '2', c.attributes['id']
-
- c1, c0 = XPath.match( d, "/a/b/c[@id='2']/preceding::node()" )
- assert_equal '1', c1.attributes['id']
- assert_equal '0', c0.attributes['id']
-
- c2, c1, c0, b, b2, b0 = XPath.match( start, "preceding::node()" )
-
- assert_equal 'c', c2.name
- assert_equal 'c', c1.name
- assert_equal 'c', c0.name
- assert_equal 'b', b.name
- assert_equal 'b', b2.name
- assert_equal 'b', b0.name
-
- assert_equal '2', c2.attributes['id']
- assert_equal '1', c1.attributes['id']
- assert_equal '0', c0.attributes['id']
- assert b.attributes.empty?
- assert_equal '2', b2.attributes['id']
- assert_equal '0', b0.attributes['id']
-
- d = REXML::Document.new("<a><b/><c/><d/></a>")
- matches = REXML::XPath.match(d, "/a/d/preceding::node()")
- assert_equal("c", matches[0].name)
- assert_equal("b", matches[1].name)
-
- s = "<a><b><c id='1'/></b><b><b><c id='2'/><c id='3'/></b><c id='4'/></b><c id='NOMATCH'><c id='5'/></c></a>"
- d = REXML::Document.new(s)
- c = REXML::XPath.match( d, "//c[@id = '5']")
- cs = REXML::XPath.match( c, "preceding::c" )
- assert_equal( 4, cs.length )
- end
-
- def test_following
- d = Document.new "<a><b id='0'/><b/><b><c id='1'/><c id='2'/></b><b id='1'/></a>"
- start = XPath.first( d, "/a/b[@id='0']" )
- assert_equal 'b', start.name
- c = XPath.first( start, "following::c" )
- assert_equal '1', c.attributes['id']
-
- s = "<a><b><c><d/></c><e/></b><f><g><h/><i/></g></f><i/></a>"
- d = Document.new(s)
- c = XPath.first(d, '/a/b/c')
- assert_equal 'c', c.name
- res = XPath.match( c, 'following::*' )
- assert_equal 6, res.size
- res = XPath.match( c, 'following::i' )
- assert_equal 2, res.size
- end
-
- # The following three paths were provided by
- # Jeni Tennison <jeni@jenitennison.com>
- # a consultant who is also an XSL and XPath expert
- #def test_child_cubed
- # els = @@jeni.elements.to_a("*****")
- # assert_equal 3, els.size
- #end
-
- #def test_div_2
- # results = doc.elements.to_a("/ div 2")
- #end
-
- #def test_nested_predicates
- # puts @@jeni.root.elements[1].elements[1].name
- # results = @@jeni.root.elements[1].elements[1].elements.to_a("../following-sibling::*[*[name() = name(current())]]")
- # puts results
- #end
-
- # Contributed by Mike Stok
- def test_starts_with
- source = <<-EOF
- <foo>
- <a href="mailto:a@b.c">a@b.c</a>
- <a href="http://www.foo.com">http://www.foo.com</a>
- </foo>
- EOF
- doc = Document.new source
- mailtos = doc.elements.to_a("//a[starts-with(@href, 'mailto:')]")
- assert_equal 1, mailtos.size
- assert_equal "mailto:a@b.c", mailtos[0].attributes['href']
-
- ailtos = doc.elements.to_a("//a[starts-with(@href, 'ailto:')]")
- assert_equal 0, ailtos.size
- end
-
- def test_toms_text_node
- file = "<a>A<b>B</b><c>C<d>D</d>E</c>F</a>"
- doc = Document.new(file)
- assert_equal 'A', XPath.first(doc[0], 'text()').to_s
- assert_equal 'AF', XPath.match(doc[0], 'text()').collect { |n|
- n.to_s
- }.join('')
- assert_equal 'B', XPath.first(doc[0], 'b/text()').to_s
- assert_equal 'D', XPath.first(doc[0], '//d/text()').to_s
- assert_equal 'ABCDEF', XPath.match(doc[0], '//text()').collect {|n|
- n.to_s
- }.join('')
- end
-
- def test_string_length
- doc = Document.new <<-EOF
- <AAA>
- <Q/>
- <SSSS/>
- <BB/>
- <CCC/>
- <DDDDDDDD/>
- <EEEE/>
- </AAA>
- EOF
- assert doc, "create doc"
-
- set = doc.elements.to_a("//*[string-length(name()) = 3]")
- assert_equal 2, set.size, "nodes with names length = 3"
-
- set = doc.elements.to_a("//*[string-length(name()) < 3]")
- assert_equal 2, set.size, "nodes with names length < 3"
-
- set = doc.elements.to_a("//*[string-length(name()) > 3]")
- assert_equal 3, set.size, "nodes with names length > 3"
- end
-
- # Test provided by Mike Stok
- def test_contains
- source = <<-EOF
- <foo>
- <a href="mailto:a@b.c">a@b.c</a>
- <a href="http://www.foo.com">http://www.foo.com</a>
- </foo>
- EOF
- doc = Document.new source
-
- [
- #['o', 2],
- ['foo', 1], ['bar', 0]].each { |search, expected|
- set = doc.elements.to_a("//a[contains(@href, '#{search}')]")
- assert_equal expected, set.size
- }
- end
-
- # Mike Stok and Sean Russell
- def test_substring
- # examples from http://www.w3.org/TR/xpath#function-substring
- doc = Document.new('<test string="12345" />')
-
- Document.new("<a b='1'/>")
- #puts XPath.first(d, 'node()[0 + 1]')
- #d = Document.new("<a b='1'/>")
- #puts XPath.first(d, 'a[0 mod 0]')
- [ [1.5, 2.6, '234'],
- [0, 3, '12'],
- [0, '0 div 0', ''],
- [1, '0 div 0', ''],
- ['-42', '1 div 0', '12345'],
- ['-1 div 0', '1 div 0', '']
- ].each { |start, length, expected|
- set = doc.elements.to_a("//test[substring(@string, #{start}, #{length}) = '#{expected}']")
- assert_equal 1, set.size, "#{start}, #{length}, '#{expected}'"
- }
- end
-
- def test_translate
- source = <<-EOF
- <doc>
- <case name='w3c one' result='BAr' /> <!-- w3c -->
- <case name='w3c two' result='AAA' /> <!-- w3c -->
- <case name='alchemy' result="gold" /> <!-- mike -->
- <case name='vbxml one' result='A Space Odyssey' />
- <case name='vbxml two' result='AbCdEf' />
- </doc>
- EOF
-
- doc = Document.new(source)
-
- [ ['bar', 'abc', 'ABC', 'w3c one'],
- ['--aaa--','abc-','ABC', 'w3c two'],
- ['lead', 'dear language', 'doll groover', 'alchemy'],
- ['A Space Odissei', 'i', 'y', 'vbxml one'],
- ['abcdefg', 'aceg', 'ACE', 'vbxml two'],
- ].each { |arg1, arg2, arg3, name|
- translate = "translate('#{arg1}', '#{arg2}', '#{arg3}')"
- set = doc.elements.to_a("//case[@result = #{translate}]")
- assert_equal 1, set.size, translate
- assert_equal name, set[0].attributes['name']
- }
- end
-
- def test_math
- d = Document.new( '<a><b/><c/></a>' )
- assert XPath.first( d.root, 'node()[1]' )
- assert_equal 'b', XPath.first( d.root, 'node()[1]' ).name
- assert XPath.first( d.root, 'node()[0 + 1]' )
- assert_equal 'b', XPath.first( d.root, './node()[0 + 1]' ).name
- assert XPath.first( d.root, 'node()[1 + 1]' )
- assert_equal 'c', XPath.first( d.root, './node()[1 + 1]' ).name
- assert XPath.first( d.root, 'node()[4 div 2]' )
- assert_equal 'c', XPath.first( d.root, './node()[4 div 2]' ).name
- assert XPath.first( d.root, 'node()[2 - 1]' )
- assert_equal 'b', XPath.first( d.root, './node()[2 - 1]' ).name
- assert XPath.first( d.root, 'node()[5 mod 2]' )
- assert_equal 'b', XPath.first( d.root, './node()[5 mod 2]' ).name
- assert XPath.first( d.root, 'node()[8 mod 3]' )
- assert_equal 'c', XPath.first( d.root, './node()[8 mod 3]' ).name
- assert XPath.first( d.root, 'node()[1 * 2]' )
- assert_equal 'c', XPath.first( d.root, './node()[1 * 2]' ).name
- assert XPath.first( d.root, 'node()[2 + -1]' )
- assert_equal 'b', XPath.first( d.root, './node()[2 + -1]' ).name
- end
-
- def test_name
- assert_raise( UndefinedNamespaceException, "x should be undefined" ) {
- REXML::Document.new("<a x='foo'><b/><x:b/></a>")
- }
- d = REXML::Document.new("<a xmlns:x='foo'><b/><x:b/></a>")
- assert_equal 1, d.root.elements.to_a('*[name() = "b"]').size
- assert_equal 1, d.elements.to_a('//*[name() = "x:b"]').size
- end
-
- def test_local_name
- d = REXML::Document.new("<a xmlns:x='foo'><b/><x:b/></a>")
- assert_equal 2, d.root.elements.to_a('*[local_name() = "b"]').size
- assert_equal 2, d.elements.to_a('//*[local_name() = "b"]').size
- end
-
- def test_comparisons
- source = "<a><b id='1'/><b id='2'/><b id='3'/></a>"
- doc = REXML::Document.new(source)
-
- # NOTE TO SER: check that number() is required
- assert_equal 2, REXML::XPath.match(doc, "//b[number(@id) > 1]").size
- assert_equal 3, REXML::XPath.match(doc, "//b[number(@id) >= 1]").size
- assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) <= 1]").size
- assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (1 * 1)]").size
- assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (1 mod 2)]").size
- assert_equal 1, REXML::XPath.match(doc, "//b[number(@id) = (4 div 2)]").size
- end
-
- # Contributed by Kouhei
- def test_substring_before
- doc = Document.new("<r><a/><b/><c/></r>")
- assert_equal("a", doc.root.elements.to_a("*[name()=substring-before('abc', 'b')]")[0].name)
- assert_equal("c", doc.root.elements.to_a("*[name()=substring-after('abc', 'b')]")[0].name)
- end
-
- def test_spaces
- doc = Document.new("<a>
- <b>
- <c id='a'/>
- </b>
- <c id='b'/>
- <c id='c'/>
- <c/>
- </a>")
- match = lambda do |xpath|
- REXML::XPath.match(doc, xpath).collect(&:to_s)
- end
- assert_equal(["<c id='b'/>"],
- match.call("//*[local-name()='c' and @id='b']"))
- assert_equal(["<c id='b'/>"],
- match.call("//*[ local-name()='c' and @id='b' ]"))
- assert_equal(["<c id='b'/>"],
- match.call("//*[ local-name() = 'c' and @id = 'b' ]"))
- assert_equal(["<c id='b'/>", "<c id='c'/>"],
- match.call('/a/c[@id]'))
- assert_equal(["<c id='b'/>", "<c id='c'/>"],
- match.call('/a/c[(@id)]'))
- assert_equal(["<c id='b'/>", "<c id='c'/>"],
- match.call('/a/c[ @id ]'))
- assert_equal(["<c id='b'/>", "<c id='c'/>"],
- match.call('/a/c[ (@id) ]'))
- assert_equal(["<c id='b'/>", "<c id='c'/>"],
- match.call('/a/c[( @id )]'))
- assert_equal(["<c id='b'/>", "<c id='c'/>"],
- match.call('/a/c[ ( @id ) ]'))
- assert_equal(["<c id='b'/>", "<c id='c'/>"],
- match.call('/a/c [ ( @id ) ] '))
- assert_equal(["<c id='b'/>", "<c id='c'/>"],
- match.call(' / a / c [ ( @id ) ] '))
- assert_equal(["<c id='b'/>", "<c id='c'/>"],
- match.call('/ a / child:: c [( @id )] /'))
- end
-
- def test_text_nodes
- # source = "<root>
- #<child/>
- #<child>test</child>
- #</root>"
- source = "<root><child>test</child></root>"
- d = REXML::Document.new( source )
- r = REXML::XPath.match( d, %q{/root/child[text()="test"]} )
- assert_equal( 1, r.size )
- assert_equal( "child", r[0].name )
- assert_equal( "test", r[0].text )
- end
-
- def test_auto_string_value
- source = "<root><foo/><title>Introduction</title></root>"
- d = REXML::Document.new( source )
- #r = REXML::XPath.match( d, %q{/root[title="Introduction"]} )
- #assert_equal( 1, r.size )
- source = "<a><b/><c/><c>test</c></a>"
- d = REXML::Document.new( source )
- r = REXML::XPath.match( d, %q{/a[c='test']} )
- assert_equal( 1, r.size )
- r = REXML::XPath.match( d, %q{a[c='test']} )
- assert_equal( 1, r.size )
- r = d.elements["/a[c='test']"]
- assert_not_nil( r )
- r = d.elements["a[c='test']"]
- assert_not_nil( r )
- r = d.elements["a[c='xtest']"]
- assert_nil( r )
- r = REXML::XPath.match( d, %q{a[c='xtest']} )
- assert_equal( 0, r.size )
- end
-
- def test_ordering
- source = <<-XML
-<a>
- <b>
- <c id='1'/>
- <c id='2'/>
- </b>
- <b>
- <d id='3'/>
- <d id='4'/>
- </b>
-</a>
- XML
- d = REXML::Document.new( source )
- r = REXML::XPath.match( d, %q{/a/*/*[1]} )
- assert_equal(["1", "3"],
- r.collect {|element| element.attribute("id").value})
- end
-
- def test_descendant_or_self_ordering
- source = "<a>
- <b>
- <c id='1'/>
- <c id='2'/>
- </b>
- <b>
- <d id='1'>
- <c id='3'/>
- </d>
- <d id='2'>
- <e>
- <c id='4'/>
- </e>
- </d>
- </b>
- </a>"
- d = REXML::Document.new( source )
- cs = XPath.match( d, "/descendant-or-self::c" )
- assert_equal( 4, cs.length )
- 1.upto(4) {|x| assert_equal( x.to_s, cs[x-1].attributes['id'] ) }
- end
-
- def test_and
- d = Document.new %q{<doc><route run='*' title='HNO'
- destination='debian_production1' date='*' edition='*'
- source='debian_satellite1'/></doc>}
- assert_equal( nil, d.root.elements["route[@run='0']"] )
- assert_equal( nil, d.root.elements["route[@run='0' and @title='HNO']"] )
- end
-
-
- def test_numbers
- d = Document.new %q{<a x="0" y="*" z="4e" w="e4" v="a"/>}
-
- xp1 = "/a[ @x = 0 ]"
- xp2 = "/a[ @x = '0' ]"
- xp3 = "/a[ (@x + 1) = 1 ]"
- xp4 = "/a[ @y = 0 ]"
- xp5 = "/a[ (@z + 1) = 5 ]"
- xp6 = "/a[ (@w + 1) = 5 ]"
- xp7 = "/a[ (@v + 1) = 1 ]"
- xp8 = "/a[ @n = 0 ]"
-
- assert_equal( 1, XPath.match( d, xp1 ).length )
- assert_equal( 1, XPath.match( d, xp2 ).length )
- assert_equal( 1, XPath.match( d, xp3 ).length )
- assert_equal( 0, XPath.match( d, xp4 ).length )
- assert_equal( 0, XPath.match( d, xp5 ).length )
- assert_equal( 0, XPath.match( d, xp6 ).length )
- assert_equal( 0, XPath.match( d, xp7 ).length )
- assert_equal( 0, XPath.match( d, xp8 ).length )
- end
-
- def test_tobis_preceding
- doc_string = '<a>
- <b/>
- <c>
- <d/>
- <e/>
- </c>
-</a>'
-
- doc = Document.new(doc_string)
-
- # e = REXML::XPath.first(doc,'/a/c/e')
- e = doc.root.get_elements('/a/c/e')[0]
- assert_equal( 1, e.get_elements('preceding-sibling::*').length )
- assert_equal( 2, XPath.match(e, 'preceding::*').length )
- end
-
-
- def test_filtering
- #doc=Document.new("<a><b><c1/><c2/></b><b><c3/><c4/></b><b><c5/><c6/></b></a>")
- #assert_equal( 3, XPath.match( doc, '/a/b/*[1]' ).length )
- #assert_equal( 2, XPath.match( doc, '/a/b/following-sibling::*[1]' ).length )
- end
-
- # Submitted by Alex
- def test_union
- data = %Q{<div id="the_div">
- <span id="the_span">
- <strong id="the_strong">a</strong>
- </span>
- <em id="the_em2">b</em>
-</div>}
- rd = REXML::Document.new( data )
- #union = rd.get_elements("/div/span | /div/em")
- #assert_equal(2, union.length, "/div/span | /div/em" )
- union = rd.get_elements('//*[name()="em" or name()="strong"]')
- assert_equal(2, union.length, 'name() and "or" failed')
- union = rd.get_elements('//em|//strong')
- assert_equal(2, union.length,
- 'Both tag types are returned by XPath union operator')
- end
-
-
- def test_union2
- src = <<-EOL
-<div id="the_div">
-<span id="the_span">
-<strong id="the_strong">a</strong>
-</span>
-<em id="the_em2">b</em>
-</div>
- EOL
- rd = REXML::Document.new( src )
- union = rd.get_elements('//em|//strong')
- assert_equal(2, union.length,
- 'Both tag types are returned by XPath union operator')
- end
-
-
- def test_a_star_star_one
- string = <<-EOL
-<a>
- <b>
- <c1/>
- <d/>
- <e/>
- <f/>
- </b>
- <b>
- <c2/>
- <d/>
- <e/>
- <f/>
- </b>
-</a>
- EOL
- d = REXML::Document.new( string )
- cs = XPath.match( d, '/a/*/*[1]' )
- assert_equal(["c1", "c2"], cs.collect(&:name))
- end
-
- def test_sum
- d = Document.new(<<-XML)
-<a>
- <b>1</b>
- <b>2</b>
- <b>3</b>
- <c>
- <d>1</d>
- <d>2</d>
- </c>
- <e att='1'/>
- <e att='2'/>
-</a>
- XML
-
- assert_equal([6], XPath::match(d, "sum(/a/b)"))
- assert_equal([9], XPath::match(d, "sum(//b | //d)"))
- assert_equal([3], XPath::match(d, "sum(/a/e/@*)"))
- end
-
- def test_xpath_namespace
- d = REXML::Document.new(<<-XML)
-<tag1 xmlns='ns1'>
- <tag2 xmlns='ns2'/>
- <tada>xa</tada>
- <tada xmlns=''>xb</tada>
-</tag1>
- XML
- actual = []
- d.root.each_element('tada') do |element|
- actual << element.to_s
- end
- assert_equal(["<tada>xa</tada>", "<tada xmlns=''>xb</tada>"],
- actual)
- end
-
- def test_ticket_39
- doc = REXML::Document.new( <<-EOL )
- <rss>
- <channel>
- <!-- removing the namespace declaration makes the test pass -->
- <convertLineBreaks xmlns="http://www.blogger.com/atom/ns#">true</convertLineBreaks>
- <item>
- <title>Item 1</title>
- </item>
- <item>
- <title>Item 2</title>
- <pubDate>Thu, 13 Oct 2005 19:59:00 +0000</pubDate>
- </item>
- <item>
- <title>Item 3</title>
- </item>
- </channel>
- </rss>
- EOL
- root_node = XPath.first(doc, "rss")
- assert_not_nil root_node
- channel_node = XPath.first(root_node, "channel")
- assert_not_nil channel_node
- items = XPath.match(channel_node, "*")
- assert_equal 4, items.size
- items = XPath.match(channel_node, "item")
- assert_equal 3, items.size # fails
- end
-
-
- def test_ticket_42
- source = "<a></a>"
- doc = Document.new(source)
- bElem = Element.new('b')
- doc.root.add_element(bElem)
- doc.elements.each('//b[name(..) = "a"]') { |x|
- assert_equal x,bElem
- }
- end
-
- def test_ticket_56
- namespaces = {'h' => 'http://www.w3.org/1999/xhtml'}
-
- finaldoc = REXML::Document.new(File.read(fixture_path('google.2.xml')))
-
- column_headers = []
-
- REXML::XPath.each(finaldoc, '//h:form[@action="ModifyCampaign"]//h:th',
- namespaces) do |el|
- node = REXML::XPath.first(el, 'h:a/text()', namespaces)
- column_headers << (node ? node.value : nil)
- end
- column_headers.map! { |h| h.to_s.strip.chomp }
- expected = ["", "", "Current Status", "Current Budget",
- "Clicks", "Impr.", "CTR", "Avg. CPC", "Cost", "Conv. Rate",
- "Cost/Conv."]
- assert_equal( expected, column_headers )
- end
-
-
- def test_ticket_70
- string = <<EOF
-
-<mydoc>
-
- <someelement attribute="1.10">Text1, text,
-text</someelement>
-
- <someelement attribute="1.11">Text2, text,
-text</someelement>
-
-
-</mydoc>
-
-EOF
- doc = Document.new string
- assert_equal( 1, XPath.match( doc, "//someelement[contains(@attribute,'1.10')]" ).length )
- end
-
- def test_ticket_43
- #url = http://news.search.yahoo.com/news/rss?p=market&ei=UTF-8&fl=0&x=wrt
-
- sum = File.open(fixture_path("yahoo.xml")) do |f|
- Document.new(f).elements.to_a("//item").size
- end
- assert_equal( 10, sum )
-
- text = File.open(fixture_path("yahoo.xml")) do |f|
- Document.new(f).elements.to_a(%Q{//title[contains(text(), "'")]}).collect{|e| e.text}.join
- end
- assert_equal( "Broward labor market's a solid performer (Miami Herald)", text )
- end
-
- def test_ticket_57
- data = "<?xml version='1.0'?><a:x xmlns:a='1'><a:y p='p' q='q'><a:z>zzz</a:z></a:y></a:x>"
-
- r = Document.new(data)
-
- assert_equal(Text, REXML::XPath.first(r,"a:x/a:y[@p='p' and @q='q']/a:z/text()").class)
- assert_equal("zzz", REXML::XPath.first(r,"a:x/a:y[@p='p' and @q='q']/a:z/text()").to_s)
- end
-
- def test_ticket_59
- data = "<a>
- <c id='1'/>
- <c id='2'/>
- <b>
- <c id='3'/>
- </b>
- <c id='4'/>
- <b>
- <b>
- <c id='5'/>
- </b>
- <c id='6'/>
- </b>
- <c id='7'/>
- <b>
- <b>
- <c id='8'/>
- <b>
- <c id='9'/>
- <b>
- <c id='10'/>
- </b>
- <c id='11'/>
- </b>
- </b>
- </b>
- <c id='12'/>
- </a>"
- d = Document.new(data)
- res = d.elements.to_a( "//c" ).collect {|e| e.attributes['id'].to_i}
- assert_equal((1..12).to_a, res)
- end
-
- def ticket_61_fixture(doc, xpath)
- matches = []
- doc.elements.each(xpath) do |element|
- matches << element
- assert_equal('Add', element.text)
- assert_equal('ButtonText', element.attributes['class'])
- end
- assert_equal(1, matches.length)
- end
-
- def test_ticket_61_text
- doc = File.open(fixture_path("ticket_61.xml")) do |file|
- REXML::Document.new file
- end
- ticket_61_fixture( doc, "//div[text()='Add' and @class='ButtonText']" )
- end
-
- def test_ticket_61_contains
- doc = File.open(fixture_path("ticket_61.xml")) do |file|
- REXML::Document.new file
- end
- ticket_61_fixture( doc, "//div[contains(.,'Add') and @class='ButtonText']" )
- end
-
- def test_namespaces_0
- d = Document.new(%q{<x:a xmlns:x="y"/>})
- assert_equal( 1, XPath.match( d, "//x:a" ).size )
- assert_equal( 1, XPath.match( d, "//x:*" ).size )
- end
-
- def test_ticket_71
- doc = Document.new(%Q{<root xmlns:ns1="xyz" xmlns:ns2="123"><element ns1:attrname="foo" ns2:attrname="bar"/></root>})
- el = doc.root.elements[1]
- assert_equal( "element", el.name )
- el2 = XPath.first( doc.root, "element[@ns:attrname='foo']", { 'ns' => "xyz" } )
- assert_equal( el, el2 )
- end
-
- def test_ticket_78
- doc = <<-EOT
- <root>
- <element>
- <tag x='1'>123</tag>
- </element>
- <element>
- <tag x='2'>123a</tag>
- </element>
- </root>
- EOT
- seq = %w{BEGIN 123 END BEGIN 123a END}
-
- xmlDoc = Document.new(doc)
-
- ["//element[tag='123']/tag", "//element[tag='123a']/tag"].each do |query|
- assert_equal( "BEGIN", seq.shift )
- XPath.each(xmlDoc, query) { |element|
- assert_equal( seq.shift, element.text )
- }
- assert_equal( "END", seq.shift )
- end
- end
-
- def test_ticket_79
- source = "<a><b><c>test</c></b><b><c>3</c></b></a>"
- d = REXML::Document.new( source )
- r = REXML::XPath.match( d, %q{/a/b[c='test']} )
- assert_equal(1, r.size())
- r = REXML::XPath.match( d, %q{/a/b[c='3']} )
- assert_equal(1, r.size())
- end
-
- def test_or_and
- doc = "
-<html>
- <head>
- <title>test</title>
- </head>
- <body>
- <p>
- A <a rel=\"sub\" href=\"/\">link</a>.
- </p>
- </body>
-</html>
-"
-
- xmldoc = REXML::Document.new(doc)
- xpath = "descendant::node()[(local-name()='link' or local-name()='a') and @rel='sub']"
- hrefs = []
- xmldoc.elements.each(xpath) do |element|
- hrefs << element.attributes["href"]
- end
- assert_equal(["/"], hrefs, "Bug #3842 [ruby-core:32447]")
- end
- end
-end
diff --git a/test/rexml/xpath/test_compare.rb b/test/rexml/xpath/test_compare.rb
deleted file mode 100644
index bb666c9b12..0000000000
--- a/test/rexml/xpath/test_compare.rb
+++ /dev/null
@@ -1,256 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "../rexml_test_utils"
-
-require "rexml/document"
-
-module REXMLTests
- class TestXPathCompare < Test::Unit::TestCase
- def match(xml, xpath)
- document = REXML::Document.new(xml)
- REXML::XPath.match(document, xpath)
- end
-
- class TestEqual < self
- class TestNodeSet < self
- def test_boolean_true
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child/>
- <child/>
-</root>
- XML
- assert_equal([true],
- match(xml, "/root/child=true()"))
- end
-
- def test_boolean_false
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
-</root>
- XML
- assert_equal([false],
- match(xml, "/root/child=true()"))
- end
-
- def test_number_true
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child>100</child>
- <child>200</child>
-</root>
- XML
- assert_equal([true],
- match(xml, "/root/child=100"))
- end
-
- def test_number_false
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child>100</child>
- <child>200</child>
-</root>
- XML
- assert_equal([false],
- match(xml, "/root/child=300"))
- end
-
- def test_string_true
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child>text</child>
- <child>string</child>
-</root>
- XML
- assert_equal([true],
- match(xml, "/root/child='string'"))
- end
-
- def test_string_false
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child>text</child>
- <child>string</child>
-</root>
- XML
- assert_equal([false],
- match(xml, "/root/child='nonexistent'"))
- end
- end
-
- class TestBoolean < self
- def test_number_true
- xml = "<root/>"
- assert_equal([true],
- match(xml, "true()=1"))
- end
-
- def test_number_false
- xml = "<root/>"
- assert_equal([false],
- match(xml, "true()=0"))
- end
-
- def test_string_true
- xml = "<root/>"
- assert_equal([true],
- match(xml, "true()='string'"))
- end
-
- def test_string_false
- xml = "<root/>"
- assert_equal([false],
- match(xml, "true()=''"))
- end
- end
-
- class TestNumber < self
- def test_string_true
- xml = "<root/>"
- assert_equal([true],
- match(xml, "1='1'"))
- end
-
- def test_string_false
- xml = "<root/>"
- assert_equal([false],
- match(xml, "1='2'"))
- end
- end
- end
-
- class TestGreaterThan < self
- class TestNodeSet < self
- def test_boolean_truex
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child/>
-</root>
- XML
- assert_equal([true],
- match(xml, "/root/child>false()"))
- end
-
- def test_boolean_false
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child/>
-</root>
- XML
- assert_equal([false],
- match(xml, "/root/child>true()"))
- end
-
- def test_number_true
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child>100</child>
- <child>200</child>
-</root>
- XML
- assert_equal([true],
- match(xml, "/root/child>199"))
- end
-
- def test_number_false
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child>100</child>
- <child>200</child>
-</root>
- XML
- assert_equal([false],
- match(xml, "/root/child>200"))
- end
-
- def test_string_true
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child>100</child>
- <child>200</child>
-</root>
- XML
- assert_equal([true],
- match(xml, "/root/child>'199'"))
- end
-
- def test_string_false
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <child>100</child>
- <child>200</child>
-</root>
- XML
- assert_equal([false],
- match(xml, "/root/child>'200'"))
- end
- end
-
- class TestBoolean < self
- def test_string_true
- xml = "<root/>"
- assert_equal([true],
- match(xml, "true()>'0'"))
- end
-
- def test_string_false
- xml = "<root/>"
- assert_equal([false],
- match(xml, "true()>'1'"))
- end
- end
-
- class TestNumber < self
- def test_boolean_true
- xml = "<root/>"
- assert_equal([true],
- match(xml, "true()>0"))
- end
-
- def test_number_false
- xml = "<root/>"
- assert_equal([false],
- match(xml, "true()>1"))
- end
-
- def test_string_true
- xml = "<root/>"
- assert_equal([true],
- match(xml, "1>'0'"))
- end
-
- def test_string_false
- xml = "<root/>"
- assert_equal([false],
- match(xml, "1>'1'"))
- end
- end
-
- class TestString < self
- def test_string_true
- xml = "<root/>"
- assert_equal([true],
- match(xml, "'1'>'0'"))
- end
-
- def test_string_false
- xml = "<root/>"
- assert_equal([false],
- match(xml, "'1'>'1'"))
- end
- end
- end
- end
-end
diff --git a/test/rexml/xpath/test_node.rb b/test/rexml/xpath/test_node.rb
deleted file mode 100644
index e0e958e70f..0000000000
--- a/test/rexml/xpath/test_node.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../rexml_test_utils"
-
-require "rexml/document"
-
-module REXMLTests
- class TestXPathNode < Test::Unit::TestCase
- def matches(xml, xpath)
- document = REXML::Document.new(xml)
- REXML::XPath.each(document, xpath).collect(&:to_s)
- end
-
- class TestQName < self
- def test_ascii
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <ascii>
- <child>child</child>
- </ascii>
-</root>
- XML
- assert_equal(["<child>child</child>"],
- matches(xml, "/root/ascii/child"))
- end
-
- def test_non_ascii
- xml = <<-XML
-<?xml version="1.0" encoding="UTF-8"?>
-<root>
- <non-àscii>
- <child>child</child>
- </non-àscii>
-</root>
- XML
- assert_equal(["<child>child</child>"],
- matches(xml, "/root/non-àscii/child"))
- end
- end
- end
-end
diff --git a/test/rexml/xpath/test_predicate.rb b/test/rexml/xpath/test_predicate.rb
deleted file mode 100644
index ce1aaa324b..0000000000
--- a/test/rexml/xpath/test_predicate.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: false
-require "test/unit/testcase"
-require "rexml/document"
-require "rexml/xpath"
-require "rexml/parsers/xpathparser"
-
-module REXMLTests
- class TestXPathPredicate < Test::Unit::TestCase
- include REXML
- SRC=<<-EOL
- <article>
- <section role="subdivision" id="1">
- <para>free flowing text.</para>
- </section>
- <section role="division">
- <section role="subdivision" id="2">
- <para>free flowing text.</para>
- </section>
- <section role="division">
- <para>free flowing text.</para>
- </section>
- </section>
- </article>
- EOL
-
- def setup
- @doc = REXML::Document.new( SRC )
- @parser = REXML::Parsers::XPathParser.new
-
- end
-
- def test_predicates_parent
- path = '//section[../self::section[@role="division"]]'
- m = do_path( path )
- assert_equal( 2, m.size )
- assert_equal( "2", m[0].attributes["id"] )
- assert_nil( m[1].attributes["id"] )
- end
-
- def test_predicates_single
- path = '//section[@role="subdivision" and not(../self::section[@role="division"])]'
- m = do_path( path )
- assert_equal( 1, m.size )
- assert_equal( "1", m[0].attributes["id"] )
- end
-
- def test_predicates_multi
- path = '//section[@role="subdivision"][not(../self::section[@role="division"])]'
- m = do_path( path )
- assert_equal( 1, m.size )
- assert_equal( "1", m[0].attributes["id"] )
- end
-
- def do_path( path )
- m = REXML::XPath.match( @doc, path )
- #puts path, @parser.parse( path ).inspect
- return m
- end
-
- def test_get_no_siblings_terminal_nodes
- source = <<-XML
-<a>
- <b number='1' str='abc'>TEXT1</b>
- <c number='1'/>
- <c number='2' str='def'>
- <b number='3'/>
- <d number='1' str='abc'>TEXT2</d>
- <b number='2'><!--COMMENT--></b>
- </c>
-</a>
-XML
- doc = REXML::Document.new(source)
- predicate = "count(child::node()|" +
- "following-sibling::node()|" +
- "preceding-sibling::node())=0"
- m = REXML::XPath.match(doc, "/descendant-or-self::node()[#{predicate}]")
- assert_equal( [REXML::Text.new("TEXT1"),
- REXML::Text.new("TEXT2"),
- REXML::Comment.new("COMMENT")],
- m )
- end
- end
-end
diff --git a/test/rexml/xpath/test_text.rb b/test/rexml/xpath/test_text.rb
deleted file mode 100644
index 7222388e1b..0000000000
--- a/test/rexml/xpath/test_text.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'rexml/document'
-require 'rexml/element'
-require 'rexml/xpath'
-
-module REXMLTests
- class TestXPathText < Test::Unit::TestCase
- def setup
- @doc = REXML::Document.new
- end
-
- def tear_down
- end
-
- def test_text_as_element
- node1 = REXML::Element.new('a', @doc)
- node2 = REXML::Element.new('b', node1)
- REXML::Text.new('test', false, node2)
- assert_equal(1, @doc.elements.size, "doc owns 1 element node1")
- assert_same(node1, @doc.elements[1], "doc owns 1 element node1")
- assert_equal(1, node1.elements.size, "node1 owns 1 element node2")
- assert_same(node2, node1.elements[1], "node1 owns 1 element node2")
- assert_equal(1, node2.size, "node2 owns 1 text element")
- end
-
- def test_text_in_xpath_query
- node1 = REXML::Element.new('a', @doc)
- node2 = REXML::Element.new('b', node1)
- textnode = REXML::Text.new('test', false, node2)
- textnode.parent = node2 # should be unnecessary
- nodes = @doc.get_elements('//b')
- assert_equal(1, nodes.size, "document has one element")
- # why doesn't this query work right?
- nodes = REXML::XPath.match(@doc, '//text()')
- assert_equal(1, nodes.size, "//text() should yield one Text element")
- assert_equal(REXML::Text, nodes[0].class)
- end
-
- def test_comment_in_xpath_query
- node1 = REXML::Element.new('a', @doc)
- node2 = REXML::Element.new('b', node1)
- commentnode = REXML::Comment.new('test', node2)
- nodes = REXML::XPath.match(@doc, '//comment()')
- assert_equal(1, nodes.size, "//comment() should yield one Comment element")
- assert_same commentnode, nodes[0]
- end
-
- def test_parentage
- node1 = REXML::Element.new('a', @doc)
- assert_same(@doc, node1.parent, "node1 parent is document")
- node2 = REXML::Element.new('b', node1)
- assert_same(node1, node2.parent, "node2 parent is node1")
- textnode = REXML::Text.new('test', false, node2)
- # why isn't the text's parent node2?
- # Also look at Comment, etc.
- assert_same(node2, textnode.parent)
- comment = REXML::Comment.new('Test comment', node2)
- assert_same(node2, comment.parent)
- end
-
- def test_ancestors
- node1 = REXML::Element.new('a', @doc)
- node2 = REXML::Element.new('b', node1)
- textnode = REXML::Text.new('test', false, node2)
- #textnode.parent = node2 # should be unnecessary
- assert_same node2, textnode.parent
- nodes = @doc.get_elements('//b/ancestor::*')
- assert_equal(1, nodes.size, "<b> has one element ancestor")
- nodes = @doc.get_elements('//b/ancestor::node()')
- assert_equal(2, nodes.size, "<b> has two node ancestors")
- nodes.sort_by!(&:name)
- assert_kind_of REXML::Document, nodes[0]
- assert_kind_of REXML::Element, nodes[1]
- end
- end
-end
diff --git a/test/rinda/test_rinda.rb b/test/rinda/test_rinda.rb
index 22966532b7..f155e88de1 100644
--- a/test/rinda/test_rinda.rb
+++ b/test/rinda/test_rinda.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: false
require 'test/unit'
+require 'envutil'
require 'drb/drb'
require 'drb/eq'
@@ -401,6 +402,7 @@ module TupleSpaceTestModule
end
def test_cancel_02
+ skip 'this test is unstable with --jit-wait' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
entry = @ts.write([:removeme, 1])
assert_equal([[:removeme, 1]], @ts.read_all([nil, nil]))
entry.cancel
@@ -638,30 +640,30 @@ class TestRingServer < Test::Unit::TestCase
end
def test_do_reply
- with_timeout(10) {_test_do_reply}
+ with_timeout(30) {_test_do_reply}
end
def _test_do_reply
called = nil
- callback = proc { |ts|
+ callback_orig = proc { |ts|
called = ts
}
- callback = DRb::DRbObject.new callback
+ callback = DRb::DRbObject.new callback_orig
@ts.write [:lookup_ring, callback]
@rs.do_reply
- wait_for(10) {called}
+ wait_for(30) {called}
assert_same @ts, called
end
def test_do_reply_local
- skip 'timeout-based test becomes unstable with --jit-wait' if RubyVM::MJIT.enabled?
- with_timeout(10) {_test_do_reply_local}
+ skip 'timeout-based test becomes unstable with --jit-wait' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ with_timeout(30) {_test_do_reply_local}
end
def _test_do_reply_local
@@ -675,7 +677,7 @@ class TestRingServer < Test::Unit::TestCase
@rs.do_reply
- wait_for(10) {called}
+ wait_for(30) {called}
assert_same @ts, called
end
diff --git a/test/ripper/dummyparser.rb b/test/ripper/dummyparser.rb
index ca36985893..fa834bd0f7 100644
--- a/test/ripper/dummyparser.rb
+++ b/test/ripper/dummyparser.rb
@@ -101,7 +101,11 @@ class DummyParser < Ripper
Node.new('valias', a, b)
end
- def on_alias_error(a)
+ def on_assign_error(mesg = nil, a)
+ Node.new('assign_error', a)
+ end
+
+ def on_alias_error(mesg = nil, a)
Node.new('aliaserr', a)
end
diff --git a/test/ripper/test_lexer.rb b/test/ripper/test_lexer.rb
index 1794773d89..975976a381 100644
--- a/test/ripper/test_lexer.rb
+++ b/test/ripper/test_lexer.rb
@@ -90,6 +90,16 @@ class TestRipper::Lexer < Test::Unit::TestCase
assert_equal expect, Ripper.lex(src).map {|e| e[1]}
end
+ def test_stack_at_on_heredoc_beg
+ src = "a <<b"
+ expect = %I[
+ on_ident
+ on_sp
+ on_heredoc_beg
+ ]
+ assert_equal expect, Ripper.lex(src).map {|e| e[1]}
+ end
+
def test_slice
assert_equal "string\#{nil}\n",
Ripper.slice(%(<<HERE\nstring\#{nil}\nHERE), "heredoc_beg .*? nl $(.*?) heredoc_end", 1)
@@ -138,4 +148,83 @@ class TestRipper::Lexer < Test::Unit::TestCase
assert_equal pos, code.bytesize
assert_equal expected.size, result.size
end
+
+ def test_trailing_on_embexpr_end
+ # This is useful for scanning a template engine literal `{ foo, bar: baz }`
+ # whose body inside brackes works like trailing method arguments, like Haml.
+ token = Ripper.lex("a( foo, bar: baz }").last
+ assert_equal [[1, 17], :on_embexpr_end, "}", state(:EXPR_ARG)], token
+ end
+
+ BAD_CODE = [
+ [:parse_error, 'def req(true) end', %r[unexpected `true'], 'true'],
+ [:assign_error, 'begin; nil = 1; end', %r[assign to nil], 'nil'],
+ [:alias_error, 'begin; alias $x $1; end', %r[number variables], '$1'],
+ [:class_name_error, 'class bad; end', %r[class/module name], 'bad'],
+ [:param_error, 'def req(@a) end', %r[formal argument.*instance], '@a'],
+ [:param_error, 'def req(a?:) end', %r[formal argument must.*local], 'a?'],
+ ]
+
+ def test_raise_errors_keyword
+ all_assertions do |all|
+ BAD_CODE.each do |(err, code, message)|
+ all.for([err, code]) do
+ assert_raise_with_message(SyntaxError, message) { Ripper.tokenize(code, raise_errors: true) }
+ end
+ end
+ end
+ end
+
+ def test_tokenize_with_syntax_error
+ all_assertions do |all|
+ BAD_CODE.each do |(err, code)|
+ all.for([err, code]) do
+ assert_equal "end", Ripper.tokenize(code).last
+ end
+ end
+ end
+ end
+
+ def test_lex_with_syntax_error
+ all_assertions do |all|
+ BAD_CODE.each do |(err, code)|
+ all.for([err, code]) do
+ assert_equal [[1, code.size-3], :on_kw, "end", state(:EXPR_END)], Ripper.lex(code).last
+ end
+ end
+ end
+ end
+
+ def test_lexer_scan_with_syntax_error
+ all_assertions do |all|
+ BAD_CODE.each do |(err, code, message, token)|
+ all.for([err, code]) do
+ lexer = Ripper::Lexer.new(code)
+ elems = lexer.scan
+ assert_predicate lexer, :error?
+ error = lexer.errors.first
+ assert_match message, error.message
+ i = elems.find_index{|e| e == error}
+ assert_operator 0...elems.size, :include?, i
+ elem = elems[i + 1]
+ assert_not_equal error.event, elem.event
+ assert_equal error.pos, elem.pos
+ assert_equal error.tok, elem.tok
+ assert_equal error.state, elem.state
+ end
+ end
+ end
+ end
+
+ def test_lex_with_syntax_error_and_heredo
+ bug = '[Bug #17644]'
+ s = <<~EOF
+ foo
+ end
+ <<~EOS
+ bar
+ EOS
+ EOF
+ assert_equal([[5, 0], :on_heredoc_end, "EOS\n", state(:EXPR_BEG)], Ripper.lex(s).last, bug)
+ end
end
diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb
index d084f10f79..014403a784 100644
--- a/test/ripper/test_parser_events.rb
+++ b/test/ripper/test_parser_events.rb
@@ -26,11 +26,21 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
end
def warning(str)
- parse(str, :warning) {|e, *args| return args}
+ tree = parse(str, :warning) {|e, *args| return args}
+ if block_given?
+ yield tree
+ else
+ assert(false, "warning expected")
+ end
end
def warn(str)
- parse(str, :warn) {|e, *args| return args}
+ tree = parse(str, :warn) {|e, *args| return args}
+ if block_given?
+ yield tree
+ else
+ assert(false, "warning expected")
+ end
end
def test_program
@@ -86,7 +96,7 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
end
def test_alias_error
- assert_equal '[aliaserr(valias($a,$1))]', parse('alias $a $1')
+ assert_equal '[aliaserr($1)]', parse('alias $a $1')
end
def test_arglist
@@ -652,6 +662,30 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
assert_equal '[def(foo,[],bodystmt([void()]))]', parse('def foo ;end')
end
+ def test_endless_def
+ events = %i[on_def on_parse_error]
+ thru = nil
+ hook = ->(name, *) {thru[name] = true}
+
+ thru = {}
+ tree = parse('def foo() = 42', events, &hook)
+ assert_equal({on_def: true}, thru)
+ assert_equal '[def(foo,[],42)]', tree
+
+ thru = {}
+ tree = parse('def foo() = 42 rescue 0', events, &hook)
+ assert_equal({on_def: true}, thru)
+ assert_equal '[def(foo,[],rescue_mod(42,0))]', tree
+
+ thru = {}
+ tree = parse('def foo=() = 42', events, &hook)
+ assert_equal({on_def: true, on_parse_error: true}, thru)
+
+ thru = {}
+ tree = parse('def foo=() = 42 rescue 0', events, &hook)
+ assert_equal({on_def: true, on_parse_error: true}, thru)
+ end
+
def test_defined
thru_defined = false
parse('defined?(x)', :on_defined) {thru_defined = true}
@@ -669,6 +703,30 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
assert_equal(true, thru_parse_error)
end
+ def test_endless_defs
+ events = %i[on_defs on_parse_error]
+ thru = nil
+ hook = ->(name, *) {thru[name] = true}
+
+ thru = {}
+ tree = parse('def foo.bar() = 42', events, &hook)
+ assert_equal({on_defs: true}, thru)
+ assert_equal '[defs(vcall(foo),.,bar,[],42)]', tree
+
+ thru = {}
+ tree = parse('def foo.bar() = 42 rescue 0', events, &hook)
+ assert_equal({on_defs: true}, thru)
+ assert_equal '[defs(vcall(foo),.,bar,[],rescue_mod(42,0))]', tree
+
+ thru = {}
+ tree = parse('def foo.bar=() = 42', events, &hook)
+ assert_equal({on_defs: true, on_parse_error: true}, thru)
+
+ thru = {}
+ tree = parse('def foo.bar=() = 42 rescue 0', events, &hook)
+ assert_equal({on_defs: true, on_parse_error: true}, thru)
+ end
+
def test_do_block
thru_do_block = false
parse('proc do end', :on_do_block) {thru_do_block = true}
@@ -1530,6 +1588,12 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
assert_equal("frozen_string_literal", args[0])
end
+ def test_warning_invalid_magic_comment
+ fmt, *args = warning("#-*- frozen-string-literal: nottrue -*-")
+ assert_match(/invalid value/, fmt)
+ assert_equal(%w"frozen_string_literal nottrue", args)
+ end
+
def test_warn_cr_in_middle
fmt = nil
assert_warn("") {fmt, = warn("\r;")}
@@ -1540,6 +1604,10 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
fmt, tokend, tokbeg, line = assert_warning("") {break warn("if true\n end\n")}
assert_match(/mismatched indentations/, fmt)
assert_equal(["if", "end", 1], [tokbeg, tokend, line])
+ result = assert_warning("") {
+ warn("begin\n" " def f() = nil\n" "end\n") {break :ok}
+ }
+ assert_equal(:ok, result)
end
def test_in
@@ -1554,6 +1622,12 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
assert_equal true, thru_aryptn
end
+ def test_fndptn
+ thru_fndptn = false
+ parse('case 0; in [*,0,*]; end', :on_fndptn) {thru_fndptn = true}
+ assert_equal true, thru_fndptn
+ end
+
def test_hshptn
thru_hshptn = false
parse('case 0; in {a:}; end', :on_hshptn) {thru_hshptn = true}
diff --git a/test/ripper/test_sexp.rb b/test/ripper/test_sexp.rb
index 89b45941a3..22ee418abb 100644
--- a/test/ripper/test_sexp.rb
+++ b/test/ripper/test_sexp.rb
@@ -412,6 +412,43 @@ eot
[:@int, "0", [1, 5]],
[:in, [:aryptn, nil, nil, nil, nil], [[:void_stmt]], nil]],
+ [__LINE__, %q{ 0 => [*, a, *] }] =>
+ [:case,
+ [:@int, "0", [1, 0]],
+ [:in,
+ [:fndptn,
+ nil,
+ [:var_field, nil],
+ [[:var_field, [:@ident, "a", [1, 9]]]],
+ [:var_field, nil]],
+ nil,
+ nil]],
+
+ [__LINE__, %q{ 0 => [*a, b, *c] }] =>
+ [:case,
+ [:@int, "0", [1, 0]],
+ [:in,
+ [:fndptn,
+ nil,
+ [:var_field, [:@ident, "a", [1, 7]]],
+ [[:var_field, [:@ident, "b", [1, 10]]]],
+ [:var_field, [:@ident, "c", [1, 14]]]],
+ nil,
+ nil]],
+
+ [__LINE__, %q{ 0 => A(*a, b, c, *d) }] =>
+ [:case,
+ [:@int, "0", [1, 0]],
+ [:in,
+ [:fndptn,
+ [:var_ref, [:@const, "A", [1, 5]]],
+ [:var_field, [:@ident, "a", [1, 8]]],
+ [[:var_field, [:@ident, "b", [1, 11]]],
+ [:var_field, [:@ident, "c", [1, 14]]]],
+ [:var_field, [:@ident, "d", [1, 18]]]],
+ nil,
+ nil]],
+
[__LINE__, %q{ case 0; in {a: 0}; end }] =>
[:case,
[:@int, "0", [1, 5]],
@@ -470,4 +507,9 @@ eot
assert_equal(:hshptn, hshptn[0])
assert_equal([:@label, "a:"], hshptn.dig(2, 0, 0))
end
+
+ def test_raise_errors_keyword
+ assert_raise(SyntaxError) { Ripper.sexp('def req(true) end', raise_errors: true) }
+ assert_raise(SyntaxError) { Ripper.sexp_raw('def req(true) end', raise_errors: true) }
+ end
end if ripper_test
diff --git a/test/rss/dot.png b/test/rss/dot.png
deleted file mode 100644
index 9c6960fa2f..0000000000
--- a/test/rss/dot.png
+++ /dev/null
Binary files differ
diff --git a/test/rss/rss-assertions.rb b/test/rss/rss-assertions.rb
deleted file mode 100644
index 86fb91aa18..0000000000
--- a/test/rss/rss-assertions.rb
+++ /dev/null
@@ -1,2120 +0,0 @@
-# frozen_string_literal: false
-require 'erb'
-
-module RSS
- module Assertions
- def _wrap_assertion
- yield
- end
-
- def assert_parse(rss, assert_method, *args)
- __send__("assert_#{assert_method}", *args) do
- ::RSS::Parser.parse(rss)
- end
- __send__("assert_#{assert_method}", *args) do
- ::RSS::Parser.parse(rss, false).validate
- end
- end
-
- def assert_ns(prefix, uri)
- _wrap_assertion do
- begin
- yield
- flunk("Not raise NSError")
- rescue ::RSS::NSError => e
- assert_equal(prefix, e.prefix)
- assert_equal(uri, e.uri)
- end
- end
- end
-
- def assert_missing_tag(tag, parent)
- _wrap_assertion do
- begin
- yield
- flunk("Not raise MissingTagError")
- rescue ::RSS::MissingTagError => e
- assert_equal(tag, e.tag)
- assert_equal(parent, e.parent)
- end
- end
- end
-
- def assert_too_much_tag(tag, parent)
- _wrap_assertion do
- begin
- yield
- flunk("Not raise TooMuchTagError")
- rescue ::RSS::TooMuchTagError => e
- assert_equal(tag, e.tag)
- assert_equal(parent, e.parent)
- end
- end
- end
-
- def assert_missing_attribute(tag, attrname)
- _wrap_assertion do
- begin
- yield
- flunk("Not raise MissingAttributeError")
- rescue ::RSS::MissingAttributeError => e
- assert_equal(tag, e.tag)
- assert_equal(attrname, e.attribute)
- end
- end
- end
-
- def assert_not_expected_tag(tag, uri, parent)
- _wrap_assertion do
- begin
- yield
- flunk("Not raise NotExpectedTagError")
- rescue ::RSS::NotExpectedTagError => e
- assert_equal(tag, e.tag)
- assert_equal(uri, e.uri)
- assert_equal(parent, e.parent)
- end
- end
- end
-
- def assert_not_available_value(tag, value, attribute=nil)
- _wrap_assertion do
- begin
- yield
- flunk("Not raise NotAvailableValueError")
- rescue ::RSS::NotAvailableValueError => e
- assert_equal(tag, e.tag)
- assert_equal(value, e.value)
- assert_equal(attribute, e.attribute)
- end
- end
- end
-
- def assert_not_set_error(name, variables)
- _wrap_assertion do
- begin
- yield
- flunk("Not raise NotSetError")
- rescue ::RSS::NotSetError => e
- assert_equal(name, e.name)
- assert_kind_of(Array, variables)
- assert_equal(variables.sort, e.variables.sort)
- end
- end
- end
-
- def assert_xml_declaration(version, encoding, standalone, rss)
- _wrap_assertion do
- assert_equal(version, rss.version)
- assert_equal(encoding, rss.encoding)
- assert_equal(standalone, rss.standalone)
- end
- end
-
- def assert_xml_stylesheet_attrs(attrs, xsl)
- _wrap_assertion do
- n_attrs = normalized_attrs(attrs)
- ::RSS::XMLStyleSheet::ATTRIBUTES.each do |name|
- assert_equal(n_attrs[name], xsl.__send__(name))
- end
- end
- end
-
- def assert_xml_stylesheet(target, attrs, xsl)
- _wrap_assertion do
- if attrs.has_key?(:href)
- if !attrs.has_key?(:type) and attrs.has_key?(:guess_type)
- attrs[:type] = attrs[:guess_type]
- end
- assert_equal("xml-stylesheet", target)
- assert_xml_stylesheet_attrs(attrs, xsl)
- else
- assert_nil(target)
- assert_equal("", xsl.to_s)
- end
- end
- end
-
- def assert_xml_stylesheet_pis(attrs_ary, rss=nil)
- _wrap_assertion do
- if rss.nil?
- rss = ::RSS::RDF.new
- setup_rss10(rss)
- end
- xss_strs = []
- attrs_ary.each do |attrs|
- xss = ::RSS::XMLStyleSheet.new(attrs)
- xss_strs.push(xss.to_s)
- rss.xml_stylesheets.push(xss)
- end
- pi_str = rss.to_s.gsub(/<\?xml .*\n/, "").gsub(/\s*<[^\?].*\z/m, "")
- assert_equal(xss_strs.join("\n"), pi_str)
- end
- end
-
- def assert_xml_stylesheets(attrs, xss)
- _wrap_assertion do
- xss.each_with_index do |xs, i|
- assert_xml_stylesheet_attrs(attrs[i], xs)
- end
- end
- end
-
-
- def assert_atom_person(tag_name, generator)
- _wrap_assertion do
- name = "Mark Pilgrim"
- uri = "http://example.org/"
- email = "f8dy@example.com"
-
- assert_parse(generator.call(<<-EOA), :missing_tag, "name", tag_name)
- <#{tag_name}/>
-EOA
-
- assert_parse(generator.call(<<-EOA), :missing_tag, "name", tag_name)
- <#{tag_name}>
- <uri>#{uri}</uri>
- <email>#{email}</email>
- </#{tag_name}>
-EOA
-
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <#{tag_name}>
- <name>#{name}</name>
- </#{tag_name}>
-EOA
-
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <#{tag_name}>
- <name>#{name}</name>
- <uri>#{uri}</uri>
- <email>#{email}</email>
- </#{tag_name}>
-EOA
-
- person = yield(feed)
- assert_not_nil(person)
- assert_equal(name, person.name.content)
- assert_equal(uri, person.uri.content)
- assert_equal(email, person.email.content)
- end
- end
-
- def assert_atom_category(generator)
- _wrap_assertion do
- term = "Music"
- scheme = "http://xmlns.com/wordnet/1.6/"
- label = "music"
-
- missing_args = [:missing_attribute, "category", "term"]
- assert_parse(generator.call(<<-EOA), *missing_args)
- <category/>
-EOA
-
- assert_parse(generator.call(<<-EOA), *missing_args)
- <category scheme="#{scheme}" label="#{label}"/>
-EOA
-
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <category term="#{term}"/>
-EOA
-
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <category term="#{term}" scheme="#{scheme}" label="#{label}"/>
-EOA
-
- category = yield(feed)
- assert_not_nil(category)
- assert_equal(term, category.term)
- assert_equal(scheme, category.scheme)
- assert_equal(label, category.label)
- end
- end
-
- def assert_atom_link(generator)
- _wrap_assertion do
- href = "http://example.org/feed.atom"
- rel = "self"
- type = "application/atom+xml"
- hreflang = "en"
- title = "Atom"
- length = "1024"
-
- assert_parse(generator.call(<<-EOA), :missing_attribute, "link", "href")
- <link/>
-EOA
-
- assert_parse(generator.call(<<-EOA), :missing_attribute, "link", "href")
- <link rel="#{rel}" type="#{type}" hreflang="#{hreflang}"
- title="#{title}" length="#{length}"/>
-EOA
-
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <link href="#{href}"/>
-EOA
-
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <link href="#{href}" rel="#{rel}" type="#{type}" hreflang="#{hreflang}"
- title="#{title}" length="#{length}"/>
-EOA
-
- link = yield(feed)
- assert_not_nil(link)
- assert_equal(href, link.href)
- assert_equal(rel, link.rel)
- assert_equal(type, link.type)
- assert_equal(hreflang, link.hreflang)
- assert_equal(title, link.title)
- assert_equal(length, link.length)
-
-
- href = "http://example.org/index.html.ja"
- parent = link.parent.tag_name
- return if parent == "source"
-
- optional_attributes = %w(hreflang="ja" type="text/html")
- 0.upto(optional_attributes.size) do |i|
- combination(optional_attributes, i).each do |attributes|
- attrs = attributes.join(" ")
- assert_parse(generator.call(<<-EOA), :too_much_tag, "link", parent)
- <link rel="alternate" #{attrs} href="#{href}"/>
- <link rel="alternate" #{attrs} href="#{href}"/>
-EOA
- end
- end
- end
- end
-
- def assert_atom_generator(generator)
- _wrap_assertion do
- uri = "http://www.example.com/"
- version = "1.0"
- content = "Example Toolkit"
-
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <generator/>
-EOA
-
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <generator uri="#{uri}" version="#{version}"/>
-EOA
-
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <generator uri="#{uri}" version="#{version}">#{content}</generator>
-EOA
-
- gen = yield(feed)
- assert_not_nil(gen)
- assert_equal(uri, gen.uri)
- assert_equal(version, gen.version)
- assert_equal(content, gen.content)
- end
- end
-
- def assert_atom_icon(generator)
- _wrap_assertion do
- content = "http://www.example.com/example.png"
-
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <icon/>
-EOA
-
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <icon>#{content}</icon>
-EOA
-
- icon = yield(feed)
- assert_not_nil(icon)
- assert_equal(content, icon.content)
- end
- end
-
- def assert_atom_text_construct(tag_name, generator)
- _wrap_assertion do
- [nil, "text", "html"].each do |type|
- attr = ""
- attr = " type=\"#{type}\"" if type
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <#{tag_name}#{attr}/>
-EOA
- end
-
- assert_parse(generator.call(<<-EOA), :missing_tag, "div", tag_name)
- <#{tag_name} type="xhtml"/>
-EOA
-
- args = ["x", Atom::URI, tag_name]
- assert_parse(generator.call(<<-EOA), :not_expected_tag, *args)
- <#{tag_name} type="xhtml"><x/></#{tag_name}>
-EOA
-
- invalid_value = "invalid"
- args = ["type", invalid_value]
- assert_parse(generator.call(<<-EOA), :not_available_value, *args)
- <#{tag_name} type="#{invalid_value}"/>
-EOA
-
- [
- [nil, "A lot of effort went into making this effortless"],
- ["text", "A lot of effort went into making this effortless"],
- ["html", "A <em>lot</em> of effort went into making this effortless"],
- ].each do |type, content|
- attr = ""
- attr = " type=\"#{type}\"" if type
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <#{tag_name}#{attr}>#{h content}</#{tag_name}>
-EOA
-
- element = yield(feed)
- assert_not_nil(element)
- assert_equal(type, element.type)
- assert_equal(content, element.content)
- end
-
- [false, true].each do |with_space|
- xhtml_uri = "http://www.w3.org/1999/xhtml"
- xhtml_content = "<div xmlns=\"#{xhtml_uri}\">abc</div>"
- xhtml_element = RSS::XML::Element.new("div", nil, xhtml_uri,
- {"xmlns" => xhtml_uri},
- ["abc"])
- content = xhtml_content
- content = " #{content} " if with_space
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <#{tag_name} type="xhtml">#{content}</#{tag_name}>
-EOA
-
- element = yield(feed)
- assert_not_nil(element)
- assert_equal("xhtml", element.type)
- assert_equal(xhtml_content, element.content)
- assert_equal(xhtml_element, element.xhtml)
- end
- end
- end
-
- def assert_atom_date_construct(tag_name, generator)
- _wrap_assertion do
- args = [tag_name, ""]
- assert_parse(generator.call(<<-EOR), :not_available_value, *args)
- <#{tag_name}/>
-EOR
-
- [
- ["xxx", false],
- ["2007", false],
- ["2007/02/09", true],
- ].each do |invalid_value, can_parse|
- assert_not_available_value(tag_name, invalid_value) do
- RSS::Parser.parse(generator.call(<<-EOR))
- <#{tag_name}>#{invalid_value}</#{tag_name}>
-EOR
- end
-
- feed = RSS::Parser.parse(generator.call(<<-EOR), false)
- <#{tag_name}>#{invalid_value}</#{tag_name}>
-EOR
- value = yield(feed).content
- if can_parse
- assert_equal(Time.parse(invalid_value), value)
- else
- assert_nil(value)
- end
- end
-
- [
- "2003-12-13T18:30:02Z",
- "2003-12-13T18:30:02.25Z",
- "2003-12-13T18:30:02+01:00",
- "2003-12-13T18:30:02.25+01:00",
- ].each do |valid_value|
- assert_parse(generator.call(<<-EOR), :nothing_raised)
- <#{tag_name}>#{valid_value}</#{tag_name}>
-EOR
-
- feed = RSS::Parser.parse(generator.call(<<-EOR))
- <#{tag_name}>#{valid_value}</#{tag_name}>
-EOR
- assert_equal(Time.parse(valid_value), yield(feed).content)
- end
- end
- end
-
- def assert_atom_logo(generator)
- _wrap_assertion do
- content = "http://www.example.com/example.png"
-
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <logo/>
-EOA
-
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <logo>#{content}</logo>
-EOA
-
- logo = yield(feed)
- assert_not_nil(logo)
- assert_equal(content, logo.content)
- end
- end
-
- def assert_atom_content(generator, &getter)
- _wrap_assertion do
- assert_atom_content_inline_text(generator, &getter)
- assert_atom_content_inline_xhtml(generator, &getter)
- assert_atom_content_inline_other(generator, &getter)
- assert_atom_content_out_of_line(generator, &getter)
- end
- end
-
- def assert_atom_content_inline_text(generator)
- _wrap_assertion do
- [nil, "text", "html"].each do |type|
- content = "<content"
- content << " type='#{type}'" if type
-
- suffix = "/>"
- assert_parse(generator.call(content + suffix), :nothing_raised)
- suffix = ">xxx</content>"
- assert_parse(generator.call(content + suffix), :nothing_raised)
- end
-
- [
- ["text", "sample content"],
- ["text/plain", "sample content"],
- ["html", "<em>sample</em> content"]
- ].each do |type, content_content|
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <content type="#{type}">#{h content_content}</content>
-EOA
- content = yield(feed)
- assert_equal(type, content.type)
- if %w(text html).include?(type)
- assert(content.inline_text?)
- else
- assert(!content.inline_text?)
- end
- if type == "html"
- assert(content.inline_html?)
- else
- assert(!content.inline_html?)
- end
- assert(!content.inline_xhtml?)
- if type == "text/plain"
- assert(content.inline_other?)
- assert(content.inline_other_text?)
- else
- assert(!content.inline_other?)
- assert(!content.inline_other_text?)
- end
- assert(!content.inline_other_xml?)
- assert(!content.inline_other_base64?)
- assert(!content.out_of_line?)
- assert(!content.have_xml_content?)
- assert_equal(content_content, content.content)
- end
- end
- end
-
- def assert_atom_content_inline_xhtml(generator)
- _wrap_assertion do
- args = ["div", "content"]
- assert_parse(generator.call(<<-EOA), :missing_tag, *args)
- <content type="xhtml"/>
-EOA
-
- args = ["x", Atom::URI, "content"]
- assert_parse(generator.call(<<-EOA), :not_expected_tag, *args)
- <content type="xhtml"><x/></content>
-EOA
-
- xhtml_uri = "http://www.w3.org/1999/xhtml"
- xhtml_content = "<div xmlns=\"#{xhtml_uri}\">abc</div>"
- xhtml_element = RSS::XML::Element.new("div", nil, xhtml_uri,
- {"xmlns" => xhtml_uri},
- ["abc"])
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <content type="xhtml">#{xhtml_content}</content>
-EOA
-
- content = yield(feed)
- assert_not_nil(content)
- assert_equal("xhtml", content.type)
- assert(!content.inline_text?)
- assert(!content.inline_html?)
- assert(content.inline_xhtml?)
- assert(!content.inline_other?)
- assert(!content.inline_other_text?)
- assert(!content.inline_other_xml?)
- assert(!content.inline_other_base64?)
- assert(!content.out_of_line?)
- assert(content.have_xml_content?)
- assert_equal(xhtml_content, content.content)
- assert_equal(xhtml_element, content.xhtml)
- end
- end
-
- def assert_atom_content_inline_other(generator, &getter)
- _wrap_assertion do
- assert_atom_content_inline_other_text(generator, &getter)
- assert_atom_content_inline_other_xml(generator, &getter)
- end
- end
-
- def assert_atom_content_inline_other_text(generator)
- _wrap_assertion do
- type = "image/png"
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <content type="#{type}"/>
-EOA
-
- png_file = File.join(File.dirname(__FILE__), "dot.png")
- png = File.open(png_file, "rb") do |file|
- file.read.force_encoding("binary")
- end
- base64_content = [png].pack("m").delete("\n")
-
- [false, true].each do |with_space|
- xml_content = base64_content
- xml_content = " #{base64_content}" if with_space
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <content type="#{type}">#{xml_content}</content>
-EOA
-
- content = yield(feed)
- assert_not_nil(content)
- assert_equal(type, content.type)
- assert(!content.inline_text?)
- assert(!content.inline_html?)
- assert(!content.inline_xhtml?)
- assert(content.inline_other?)
- assert(!content.inline_other_text?)
- assert(!content.inline_other_xml?)
- assert(content.inline_other_base64?)
- assert(!content.out_of_line?)
- assert(!content.have_xml_content?)
- assert_equal(png, content.content)
-
- xml = REXML::Document.new(content.to_s).root
- assert_rexml_element([], {"type" => type}, base64_content, xml)
- end
- end
- end
-
- def assert_atom_content_inline_other_xml(generator)
- _wrap_assertion do
- type = "image/svg+xml"
-
- assert_parse(generator.call(<<-EOA), :nothing_raised)
- <content type="#{type}"/>
-EOA
-
- svg_uri = "http://www.w3.org/2000/svg"
- svg_width = "50pt"
- svg_height = "20pt"
- svg_version = "1.0"
- text_x = "15"
- text_y = "15"
- text = "text"
- svg_content = <<-EOS
-<svg
- xmlns="#{svg_uri}"
- width="#{svg_width}"
- height="#{svg_height}"
- version="#{svg_version}"
-><text x="#{text_x}" y="#{text_y}">#{text}</text
-></svg>
-EOS
-
- text_element = RSS::XML::Element.new("text", nil, svg_uri,
- {
- "x" => text_x,
- "y" => text_y,
- },
- [text])
- svg_element = RSS::XML::Element.new("svg", nil, svg_uri,
- {
- "xmlns" => svg_uri,
- "width" => svg_width,
- "height" => svg_height,
- "version" => svg_version,
- },
- [text_element])
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <content type="#{type}">#{svg_content}</content>
-EOA
-
- content = yield(feed)
- assert_not_nil(content)
- assert_equal(type, content.type)
- assert(!content.inline_text?)
- assert(!content.inline_html?)
- assert(!content.inline_xhtml?)
- assert(content.inline_other?)
- assert(!content.inline_other_text?)
- assert(content.inline_other_xml?)
- assert(!content.inline_other_base64?)
- assert(!content.out_of_line?)
- assert(content.have_xml_content?)
- assert_equal(REXML::Document.new(svg_content).to_s.chomp,
- REXML::Document.new(content.content).to_s.chomp)
- assert_equal(svg_element, content.xml)
- assert_nil(content.xhtml)
- end
- end
-
- def assert_atom_content_out_of_line(generator)
- _wrap_assertion do
- text_type = "text/plain"
- text_src = "http://example.com/README.txt"
-
- missing_args = [:missing_attribute, "content", "type"]
- # RSS Parser raises error even if this is "should" not "must".
- assert_parse(generator.call(<<-EOA), *missing_args)
- <content src="#{text_src}"/>
-EOA
-
- content_content = "xxx"
- not_available_value_args = [:not_available_value,
- "content", content_content]
- assert_parse(generator.call(<<-EOA), *not_available_value_args)
- <content type="#{text_type}" src="#{text_src}">#{content_content}</content>
-EOA
-
- feed = RSS::Parser.parse(generator.call(<<-EOA))
- <content type="#{text_type}" src="#{text_src}"/>
-EOA
- content = yield(feed)
- assert_not_nil(content)
- assert_equal(text_type, content.type)
- assert_equal(text_src, content.src)
- assert(!content.inline_text?)
- assert(!content.inline_html?)
- assert(!content.inline_xhtml?)
- assert(!content.inline_other?)
- assert(!content.inline_other_text?)
- assert(!content.inline_other_xml?)
- assert(!content.inline_other_base64?)
- assert(content.out_of_line?)
- assert(!content.have_xml_content?)
- assert_nil(content.xml)
- assert_nil(content.xhtml)
- assert_equal("", content.content)
- end
- end
-
- def assert_atom_source(generator, &getter)
- _wrap_assertion do
- assert_atom_source_author(generator, &getter)
- assert_atom_source_category(generator, &getter)
- assert_atom_source_contributor(generator, &getter)
- assert_atom_source_generator(generator, &getter)
- assert_atom_source_icon(generator, &getter)
- assert_atom_source_id(generator, &getter)
- assert_atom_source_link(generator, &getter)
- assert_atom_source_logo(generator, &getter)
- assert_atom_source_rights(generator, &getter)
- assert_atom_source_subtitle(generator, &getter)
- assert_atom_source_title(generator, &getter)
- assert_atom_source_updated(generator, &getter)
- end
- end
-
- def assert_atom_source_author(generator)
- assert_atom_person("author", generator) do |feed|
- source = yield(feed)
- assert_equal(1, source.authors.size)
- source.author
- end
- end
-
- def assert_atom_source_category(generator)
- assert_atom_category(generator) do |feed|
- source = yield(feed)
- assert_equal(1, source.categories.size)
- source.category
- end
- end
-
- def assert_atom_source_contributor(generator)
- assert_atom_person("contributor", generator) do |feed|
- source = yield(feed)
- assert_equal(1, source.contributors.size)
- source.contributor
- end
- end
-
- def assert_atom_source_generator(generator)
- assert_atom_generator(generator) do |feed|
- yield(feed).generator
- end
- end
-
- def assert_atom_source_icon(generator)
- assert_atom_icon(generator) do |feed|
- yield(feed).icon
- end
- end
-
- def assert_atom_source_id(generator)
- id_content = "urn:uuid:a2fb588b-5674-4898-b420-265a734fea69"
- id = "<id>#{id_content}</id>"
- feed = RSS::Parser.parse(generator.call(id))
- assert_equal(id_content, yield(feed).id.content)
- end
-
- def assert_atom_source_link(generator)
- assert_atom_link(generator) do |feed|
- source = yield(feed)
- assert_equal(1, source.links.size)
- source.link
- end
- end
-
- def assert_atom_source_logo(generator)
- assert_atom_logo(generator) do |feed|
- yield(feed).logo
- end
- end
-
- def assert_atom_source_rights(generator)
- assert_atom_text_construct("rights", generator) do |feed|
- yield(feed).rights
- end
- end
-
- def assert_atom_source_subtitle(generator)
- assert_atom_text_construct("subtitle", generator) do |feed|
- yield(feed).subtitle
- end
- end
-
- def assert_atom_source_title(generator)
- assert_atom_text_construct("title", generator) do |feed|
- yield(feed).title
- end
- end
-
- def assert_atom_source_updated(generator)
- assert_atom_date_construct("updated", generator) do |feed|
- yield(feed).updated
- end
- end
-
- def assert_dublin_core(elems, target)
- _wrap_assertion do
- elems.each do |name, value|
- assert_equal(value, target.__send__("dc_#{name}"))
- end
- end
- end
-
- def assert_multiple_dublin_core(elems, target)
- _wrap_assertion do
- elems.each do |name, values, plural|
- plural ||= "#{name}s"
- actual = target.__send__("dc_#{plural}").collect{|x| x.value}
- assert_equal(values, actual)
- end
- end
- end
-
- def assert_syndication(elems, target)
- _wrap_assertion do
- elems.each do |name, value|
- meth = "sy_#{name}"
- value = value.to_i if meth == "sy_updateFrequency"
- assert_equal(value, target.__send__(meth ))
- end
- end
- end
-
- def assert_content(elems, target)
- _wrap_assertion do
- elems.each do |name, value|
- assert_equal(value, target.__send__("content_#{name}"))
- end
- end
- end
-
- def assert_trackback(attrs, target)
- _wrap_assertion do
- n_attrs = normalized_attrs(attrs)
- if n_attrs["ping"]
- assert_equal(n_attrs["ping"], target.trackback_ping)
- end
- if n_attrs["abouts"]
- n_attrs["abouts"].each_with_index do |about, i|
- assert_equal(about, target.trackback_abouts[i].value)
- end
- end
- end
- end
-
- def assert_taxo_topic(topics, target)
- _wrap_assertion do
- topics.each_with_index do |topic, i|
- taxo_topic = target.taxo_topics[i]
- topic.each do |name, value|
- case name
- when :link
- assert_equal(value, taxo_topic.about)
- assert_equal(value, taxo_topic.taxo_link)
- when :topics
- assert_equal(value, taxo_topic.taxo_topics.resources)
- else
- assert_equal(value, taxo_topic.__send__("dc_#{name}"))
- end
- end
- end
- end
- end
-
-
- def assert_attributes(attrs, names, target)
- _wrap_assertion do
- n_attrs = normalized_attrs(attrs)
- names.each do |info|
- if info.is_a?(String)
- name = info
- type = nil
- else
- name, type = info
- end
- value = n_attrs[name]
- if value.is_a?(Time)
- actual = target.__send__(name)
- assert_instance_of(Time, actual)
- assert_equal(value.to_i, actual.to_i)
- elsif value
- case type
- when :integer
- value = value.to_i
- when :boolean
- value = value == "true" if value.is_a?(String)
- end
- assert_equal(value, target.__send__(name))
- end
- end
- end
- end
-
- def assert_rexml_element(children, attrs, text, element, text_type=nil)
- _wrap_assertion do
- if children
- children_info = element.elements.collect {|e| [e.namespace, e.name]}
- assert_equal(children.collect {|uri, name| [uri, name]}.sort,
- children_info.sort)
- end
- if attrs
- assert_equal(attrs.collect {|k, v| [k, v]}.sort,
- element.attributes.collect {|k, v| [k, v]}.sort)
- end
- case text_type
- when :time
- assert_not_nil(element.text)
- assert_equal(Time.parse(text).to_s, Time.parse(element.text).to_s)
- else
- assert_equal(text, element.text)
- end
- end
- end
-
- def _assert_maker_atom_persons(feed_type, maker_readers, feed_readers)
- _wrap_assertion do
- persons = []
- feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- targets.each do |target|
- person = {
- :name => target.name,
- :uri => target.uri,
- :email => target.email,
- }
- persons << person if person[:name]
- end
- end
-
- actual_persons = chain_reader(feed, feed_readers) || []
- actual_persons = actual_persons.collect do |person|
- {
- :name => person.name ? person.name.content : nil,
- :uri => person.uri ? person.uri.content : nil,
- :email => person.email ? person.email.content : nil,
- }
- end
- assert_equal(persons, actual_persons)
- end
- end
-
- def assert_maker_atom_persons(feed_type, maker_readers, feed_readers,
- not_set_error_name=nil,
- parent_not_set_error_name=nil,
- parent_not_set_variable=nil)
- _wrap_assertion do
- not_set_error_name ||= "maker.#{maker_readers.join('.')}"
-
- args = [feed_type, maker_readers, feed_readers]
- if parent_not_set_error_name or parent_not_set_variable
- assert_not_set_error(parent_not_set_error_name,
- parent_not_set_variable) do
- _assert_maker_atom_persons(*args) do |maker|
- yield maker
- end
- end
- else
- _assert_maker_atom_persons(*args) do |maker|
- yield maker
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(name)) do
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- targets.new_child
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(name)) do
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- target = targets.new_child
- target.uri = "http://example.com/~me/"
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(name)) do
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- target = targets.new_child
- target.email = "me@example.com"
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(name)) do
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- target = targets.new_child
- target.uri = "http://example.com/~me/"
- target.email = "me@example.com"
- end
- end
-
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- target = targets.new_child
- target.name = "me"
- end
-
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- target = targets.new_child
- target.name = "me"
- target.uri = "http://example.com/~me/"
- end
-
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- target = targets.new_child
- target.name = "me"
- target.email = "me@example.com"
- end
-
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- target = targets.new_child
- target.name = "me"
- target.uri = "http://example.com/~me/"
- target.email = "me@example.com"
- end
-
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
-
- target = targets.new_child
- target.name = "me"
- target.uri = "http://example.com/~me/"
- target.email = "me@example.com"
-
- target = targets.new_child
- target.name = "you"
- target.uri = "http://example.com/~you/"
- target.email = "you@example.com"
- end
-
- assert_not_set_error(not_set_error_name, %w(name)) do
- _assert_maker_atom_persons(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
-
- target = targets.new_child
- target.name = "me"
- target.uri = "http://example.com/~me/"
- target.email = "me@example.com"
-
- targets.new_child
- end
- end
- end
- end
-
- def _assert_maker_atom_text_construct(feed_type, maker_readers,
- feed_readers, &block)
- maker_extractor = Proc.new do |target|
- text = {
- :type => target.type,
- :content => target.content,
- :xml_content => target.xml_content,
- }
- if text[:type] == "xhtml"
- if text[:xml_content]
- xml_content = text[:xml_content]
- xhtml_uri = "http://www.w3.org/1999/xhtml"
- unless xml_content.is_a?(RSS::XML::Element) and
- ["div", xhtml_uri] == [xml_content.name, xml_content.uri]
- children = xml_content
- children = [children] unless children.is_a?(Array)
- xml_content = RSS::XML::Element.new("div", nil, xhtml_uri,
- {"xmlns" => xhtml_uri},
- children)
- text[:xml_content] = xml_content
- end
- text
- else
- nil
- end
- else
- text[:content] ? text : nil
- end
- end
- feed_extractor = Proc.new do |target|
- {
- :type => target.type,
- :content => target.content,
- :xml_content => target.xhtml,
- }
- end
- _assert_maker_atom_element(feed_type,
- maker_readers, true,
- feed_readers,
- maker_extractor,
- feed_extractor,
- &block)
- end
-
- def assert_maker_atom_text_construct(feed_type, maker_readers, feed_readers,
- parent_not_set_error_name=nil,
- parent_not_set_variable=nil,
- not_set_error_name=nil)
- _wrap_assertion do
- not_set_error_name ||= "maker.#{maker_readers.join('.')}"
-
- args = [feed_type, maker_readers, feed_readers]
- if parent_not_set_error_name or parent_not_set_variable
- assert_not_set_error(parent_not_set_error_name,
- parent_not_set_variable) do
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- end
- end
- else
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(content)) do
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- target.type = "text"
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(content)) do
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- target.type = "html"
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(xml_content)) do
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- target.type = "xhtml"
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(xml_content)) do
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- target.type = "xhtml"
- target.content = "Content"
- end
- end
-
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- target.type = "text"
- target.content = "Content"
- end
-
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- target.type = "html"
- target.content = "<em>Content</em>"
- end
-
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- target.type = "xhtml"
- target.xml_content = "text only"
- end
-
- _assert_maker_atom_text_construct(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- target.type = "xhtml"
- target.xml_content = RSS::XML::Element.new("unknown")
- end
- end
- end
-
- def _assert_maker_atom_date_construct(feed_type, maker_readers,
- feed_readers, &block)
- maker_extractor = Proc.new do |target|
- date = {
- :content => target,
- }
- date[:content] ? date : nil
- end
- feed_extractor = Proc.new do |target|
- {
- :content => target.content,
- }
- end
- _assert_maker_atom_element(feed_type,
- maker_readers, false,
- feed_readers,
- maker_extractor,
- feed_extractor,
- &block)
- end
-
- def assert_maker_atom_date_construct(feed_type, maker_readers, feed_readers,
- parent_not_set_error_name=nil,
- parent_not_set_variable=nil)
- _wrap_assertion do
- args = [feed_type, maker_readers, feed_readers]
- if parent_not_set_error_name or parent_not_set_variable
- assert_not_set_error(parent_not_set_error_name,
- parent_not_set_variable) do
- _assert_maker_atom_date_construct(*args) do |maker|
- yield maker
- end
- end
- else
- _assert_maker_atom_date_construct(*args) do |maker|
- yield maker
- end
- end
-
- maker_readers = maker_readers.dup
- writer = "#{maker_readers.pop}="
- _assert_maker_atom_date_construct(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.__send__(writer, Time.now)
- end
- end
- end
-
- def _assert_maker_atom_element(feed_type,
- maker_readers,
- maker_readers_need_block,
- feed_readers,
- maker_extractor,
- feed_extractor)
- _wrap_assertion do
- element = nil
- feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- if maker_readers_need_block
- target = chain_reader(maker, maker_readers) {|x| x}
- else
- target = chain_reader(maker, maker_readers)
- end
- element = maker_extractor.call(target)
- end
-
- target = chain_reader(feed, feed_readers)
- if target
- actual_element = feed_extractor.call(target)
- else
- actual_element = nil
- end
- assert_equal(element, actual_element)
- end
- end
-
- def _assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
- maker_extractor, feed_extractor,
- invalid_feed_checker=nil)
- _wrap_assertion do
- elements = []
- invalid_feed_exception = nil
- feed = nil
- begin
- feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- targets.each do |target|
- element = maker_extractor.call(target)
- elements << element if element
- end
- if invalid_feed_checker
- invalid_feed_exception = invalid_feed_checker.call(targets)
- end
- end
- rescue RSS::Error
- if invalid_feed_exception.is_a?(RSS::TooMuchTagError)
- assert_too_much_tag(invalid_feed_exception.tag,
- invalid_feed_exception.parent) do
- raise
- end
- else
- raise
- end
- end
-
- if invalid_feed_exception.nil?
- actual_elements = chain_reader(feed, feed_readers) || []
- actual_elements = actual_elements.collect do |target|
- feed_extractor.call(target)
- end
- assert_equal(elements, actual_elements)
- end
- end
- end
-
- def assert_maker_atom_element(feed_type, maker_readers, feed_readers,
- setup_target, optional_variables,
- required_variable, assert_method_name,
- not_set_error_name=nil,
- *additional_args)
- _wrap_assertion do
- not_set_error_name ||= "maker.#{maker_readers.join('.')}"
-
- 0.upto(optional_variables.size) do |i|
- combination(optional_variables, i).each do |names|
- have = {}
- names.each do |name|
- have[name.intern] = true
- end
- have_required_variable_too =
- have.merge({required_variable.intern => true})
-
- assert_not_set_error(not_set_error_name, [required_variable]) do
- __send__(assert_method_name, feed_type, maker_readers,
- feed_readers, *additional_args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- setup_target.call(target, have)
- end
- end
-
- __send__(assert_method_name, feed_type, maker_readers, feed_readers,
- *additional_args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers) {|x| x}
- setup_target.call(target, have_required_variable_too)
- end
- end
- end
- end
- end
-
- def assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
- setup_target, optional_variables,
- required_variable, assert_method_name,
- not_set_error_name=nil,
- *additional_args)
- _wrap_assertion do
- not_set_error_name ||= "maker.#{maker_readers.join('.')}"
-
- 0.upto(optional_variables.size) do |i|
- combination(optional_variables, i).each do |names|
- have = {}
- names.each do |name|
- have[name.intern] = true
- end
- have_required_variable_too =
- have.merge({required_variable.intern => true})
-
- assert_not_set_error(not_set_error_name, [required_variable]) do
- __send__(assert_method_name, feed_type, maker_readers,
- feed_readers, *additional_args) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- setup_target.call(targets, have)
- end
- end
-
- __send__(assert_method_name, feed_type, maker_readers, feed_readers,
- *additional_args) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- setup_target.call(targets, have_required_variable_too)
- end
-
- __send__(assert_method_name, feed_type, maker_readers, feed_readers,
- *additional_args) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- setup_target.call(targets, have_required_variable_too)
- setup_target.call(targets, have_required_variable_too)
- end
-
- assert_not_set_error(not_set_error_name, [required_variable]) do
- __send__(assert_method_name, feed_type, maker_readers, feed_readers,
- *additional_args) do |maker|
- yield maker
- targets = chain_reader(maker, maker_readers)
- setup_target.call(targets, have_required_variable_too)
- setup_target.call(targets, have)
- end
- end
- end
- end
- end
- end
-
- def _assert_maker_atom_categories(feed_type, maker_readers,
- feed_readers, &block)
- maker_extractor = Proc.new do |target|
- category = {
- :term => target.term,
- :scheme => target.scheme,
- :label => target.label,
- }
- category[:term] ? category : nil
- end
- feed_extractor = Proc.new do |target|
- {
- :term => target.term,
- :scheme => target.scheme,
- :label => target.label,
- }
- end
- _assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
- maker_extractor, feed_extractor, &block)
- end
-
- def assert_maker_atom_categories(feed_type, maker_readers, feed_readers,
- not_set_error_name=nil, &block)
- _wrap_assertion do
- _assert_maker_atom_categories(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- end
-
- setup_target = Proc.new do |targets, have|
- target = targets.new_child
- target.term = "music" if have[:term]
- target.scheme = "http://example.com/category/music" if have[:scheme]
- target.label = "Music" if have[:label]
- end
-
- optional_variables = %w(scheme label)
-
- assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
- setup_target, optional_variables,
- "term", :_assert_maker_atom_categories,
- not_set_error_name, &block)
- end
- end
-
- def _assert_maker_atom_generator(feed_type, maker_readers,
- feed_readers, &block)
- maker_extractor = Proc.new do |target|
- generator = {
- :uri => target.uri,
- :version => target.version,
- :content => target.content,
- }
- generator[:content] ? generator : nil
- end
- feed_extractor = Proc.new do |target|
- {
- :uri => target.uri,
- :version => target.version,
- :content => target.content,
- }
- end
- _assert_maker_atom_element(feed_type,
- maker_readers, true,
- feed_readers,
- maker_extractor,
- feed_extractor,
- &block)
- end
-
- def assert_maker_atom_generator(feed_type, maker_readers, feed_readers,
- not_set_error_name=nil, &block)
- _wrap_assertion do
- not_set_error_name ||= "maker.#{maker_readers.join('.')}"
-
- _assert_maker_atom_generator(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- end
-
- setup_target = Proc.new do |target, have|
- target.content = "RSS Maker" if have[:content]
- target.uri = "http://example.com/rss/maker" if have[:uri]
- target.version = "0.0.1" if have[:version]
- end
-
- optional_variables = %w(uri version)
-
- assert_maker_atom_element(feed_type, maker_readers, feed_readers,
- setup_target, optional_variables,
- "content", :_assert_maker_atom_generator,
- not_set_error_name, &block)
- end
- end
-
- def _assert_maker_atom_icon(feed_type, maker_readers, feed_readers,
- accessor_base, &block)
- maker_extractor = Proc.new do |target|
- icon = {
- :content => target.__send__(accessor_base),
- }
- icon[:content] ? icon : nil
- end
- feed_extractor = Proc.new do |target|
- {
- :content => target.content,
- }
- end
- _assert_maker_atom_element(feed_type,
- maker_readers, true,
- feed_readers,
- maker_extractor,
- feed_extractor,
- &block)
- end
-
- def assert_maker_atom_icon(feed_type, maker_readers, feed_readers,
- accessor_base=nil, not_set_error_name=nil)
- _wrap_assertion do
- accessor_base ||= "url"
- not_set_error_name ||= "maker.#{maker_readers.join('.')}"
-
- _assert_maker_atom_icon(feed_type, maker_readers, feed_readers,
- accessor_base) do |maker|
- yield maker
- end
-
- _assert_maker_atom_icon(feed_type, maker_readers, feed_readers,
- accessor_base) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.__send__("#{accessor_base}=", "http://example.com/icon.png")
- end
- end
- end
-
- def _assert_maker_atom_links(feed_type, maker_readers, feed_readers,
- allow_duplication=false, &block)
- maker_extractor = Proc.new do |target|
- link = {
- :href => target.href,
- :rel => target.rel,
- :type => target.type,
- :hreflang => target.hreflang,
- :title => target.title,
- :length => target.length,
- }
- link[:href] ? link : nil
- end
- feed_extractor = Proc.new do |target|
- {
- :href => target.href,
- :rel => target.rel,
- :type => target.type,
- :hreflang => target.hreflang,
- :title => target.title,
- :length => target.length,
- }
- end
-
- if feed_readers.first == "entries"
- parent = "entry"
- else
- parent = feed_type
- end
- invalid_feed_checker = Proc.new do |targets|
- infos = {}
- invalid_exception = nil
- targets.each do |target|
- key = [target.hreflang, target.type]
- if infos.has_key?(key)
- invalid_exception = RSS::TooMuchTagError.new("link", parent)
- break
- end
- infos[key] = true if target.rel.nil? or target.rel == "alternate"
- end
- invalid_exception
- end
- invalid_feed_checker = nil if allow_duplication
- _assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
- maker_extractor, feed_extractor,
- invalid_feed_checker,
- &block)
- end
-
- def assert_maker_atom_links(feed_type, maker_readers, feed_readers,
- not_set_error_name=nil, allow_duplication=false,
- &block)
- _wrap_assertion do
- _assert_maker_atom_links(feed_type, maker_readers,
- feed_readers) do |maker|
- yield maker
- end
-
- langs = %(ja en fr zh po)
- setup_target = Proc.new do |targets, have|
- target = targets.new_child
- lang = langs[targets.size % langs.size]
- target.href = "http://example.com/index.html.#{lang}" if have[:href]
- target.rel = "alternate" if have[:rel]
- target.type = "text/xhtml" if have[:type]
- target.hreflang = lang if have[:hreflang]
- target.title = "FrontPage(#{lang})" if have[:title]
- target.length = 1024 if have[:length]
- end
-
- optional_variables = %w(rel type hreflang title length)
-
- assert_maker_atom_elements(feed_type, maker_readers, feed_readers,
- setup_target, optional_variables,
- "href", :_assert_maker_atom_links,
- not_set_error_name, allow_duplication,
- &block)
- end
- end
-
- def _assert_maker_atom_logo(feed_type, maker_readers, feed_readers,
- accessor_base, &block)
- maker_extractor = Proc.new do |target|
- logo = {
- :uri => target.__send__(accessor_base),
- }
- logo[:uri] ? logo : nil
- end
- feed_extractor = Proc.new do |target|
- {
- :uri => target.content,
- }
- end
- _assert_maker_atom_element(feed_type,
- maker_readers, true,
- feed_readers,
- maker_extractor,
- feed_extractor,
- &block)
- end
-
- def assert_maker_atom_logo(feed_type, maker_readers, feed_readers,
- accessor_base=nil, not_set_error_name=nil)
- _wrap_assertion do
- accessor_base ||= "uri"
- not_set_error_name ||= "maker.#{maker_readers.join('.')}"
-
- _assert_maker_atom_logo(feed_type, maker_readers, feed_readers,
- accessor_base) do |maker|
- yield maker
- end
-
- _assert_maker_atom_logo(feed_type, maker_readers, feed_readers,
- accessor_base) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.__send__("#{accessor_base}=", "http://example.com/logo.png")
- end
- end
- end
-
- def _assert_maker_atom_id(feed_type, maker_readers, feed_readers, &block)
- maker_extractor = Proc.new do |target|
- id = {
- :uri => target.id,
- }
- id[:uri] ? id : nil
- end
- feed_extractor = Proc.new do |target|
- if target.id
- {
- :uri => target.id.content,
- }
- else
- nil
- end
- end
- _assert_maker_atom_element(feed_type,
- maker_readers, true,
- feed_readers,
- maker_extractor,
- feed_extractor,
- &block)
- end
-
- def assert_maker_atom_id(feed_type, maker_readers, feed_readers,
- not_set_error_name=nil)
- _wrap_assertion do
- not_set_error_name ||= "maker.#{maker_readers.join('.')}"
-
- args = [feed_type, maker_readers, feed_readers]
- _assert_maker_atom_id(*args) do |maker|
- yield maker
- end
-
- _assert_maker_atom_id(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.id = "http://example.com/id/1"
- end
- end
- end
-
- def _assert_maker_atom_content(feed_type, maker_readers,
- feed_readers, &block)
- maker_extractor = Proc.new do |target|
- content = {
- :type => target.type,
- :src => target.src,
- :content => target.content,
- :xml => target.xml,
- :inline_text => target.inline_text?,
- :inline_html => target.inline_html?,
- :inline_xhtml => target.inline_xhtml?,
- :inline_other => target.inline_other?,
- :inline_other_text => target.inline_other_text?,
- :inline_other_xml => target.inline_other_xml?,
- :inline_other_base64 => target.inline_other_base64?,
- :out_of_line => target.out_of_line?,
- }
- content[:src] = nil if content[:src] and content[:content]
- if content[:type] or content[:content]
- content
- else
- nil
- end
- end
- feed_extractor = Proc.new do |target|
- {
- :type => target.type,
- :src => target.src,
- :content => target.content,
- :xml => target.xml,
- :inline_text => target.inline_text?,
- :inline_html => target.inline_html?,
- :inline_xhtml => target.inline_xhtml?,
- :inline_other => target.inline_other?,
- :inline_other_text => target.inline_other_text?,
- :inline_other_xml => target.inline_other_xml?,
- :inline_other_base64 => target.inline_other_base64?,
- :out_of_line => target.out_of_line?,
- }
- end
- _assert_maker_atom_element(feed_type,
- maker_readers, true,
- feed_readers,
- maker_extractor,
- feed_extractor,
- &block)
- end
-
- def assert_maker_atom_content(feed_type, maker_readers, feed_readers,
- not_set_error_name=nil, &block)
- _wrap_assertion do
- not_set_error_name ||= "maker.#{maker_readers.join('.')}"
- args = [feed_type, maker_readers, feed_readers, not_set_error_name]
- assert_maker_atom_content_inline_text(*args, &block)
- assert_maker_atom_content_inline_xhtml(*args, &block)
- assert_maker_atom_content_inline_other(*args, &block)
- assert_maker_atom_content_out_of_line(*args, &block)
- end
- end
-
- def assert_maker_atom_content_inline_text(feed_type, maker_readers,
- feed_readers, not_set_error_name)
- _wrap_assertion do
- args = [feed_type, maker_readers, feed_readers]
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- end
-
- assert_not_set_error(not_set_error_name, %w(content)) do
- RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "text"
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(content)) do
- RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "html"
- end
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.content = ""
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "text"
- target.content = "example content"
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "html"
- target.content = "<em>text</em>"
- end
- end
- end
-
- def assert_maker_atom_content_inline_xhtml(feed_type, maker_readers,
- feed_readers, not_set_error_name)
- _wrap_assertion do
- args = [feed_type, maker_readers, feed_readers]
- assert_not_set_error(not_set_error_name, %w(xml_content)) do
- RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "xhtml"
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(xml_content)) do
- RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "xhtml"
- target.content = "dummy"
- end
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "xhtml"
- target.xml_content = "text"
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "xhtml"
- target.xml = "text"
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "xhtml"
- target.xml_content =
- RSS::XML::Element.new("em", nil, nil, {}, ["text"])
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "xhtml"
- target.xml = RSS::XML::Element.new("em", nil, nil, {}, ["text"])
- end
-
-
- xhtml_uri = "http://www.w3.org/1999/xhtml"
- em = RSS::XML::Element.new("em", nil, nil, {}, ["text"])
- em_with_xhtml_uri =
- RSS::XML::Element.new("em", nil, xhtml_uri, {}, ["text"])
- feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "xhtml"
- target.xml = em
- end
- assert_equal(RSS::XML::Element.new("div", nil, xhtml_uri,
- {"xmlns" => xhtml_uri},
- [em_with_xhtml_uri]),
- chain_reader(feed, feed_readers).xml)
-
- div = RSS::XML::Element.new("div", nil, xhtml_uri,
- {"xmlns" => xhtml_uri,
- "class" => "sample"},
- ["text"])
- feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "xhtml"
- target.xml = div
- end
- assert_equal(div, chain_reader(feed, feed_readers).xml)
- end
- end
-
- def assert_maker_atom_content_inline_other(*args, &block)
- _wrap_assertion do
- assert_maker_atom_content_inline_other_xml(*args, &block)
- assert_maker_atom_content_inline_other_text(*args, &block)
- assert_maker_atom_content_inline_other_base64(*args, &block)
- end
- end
-
- def assert_maker_atom_content_inline_other_xml(feed_type, maker_readers,
- feed_readers,
- not_set_error_name)
- _wrap_assertion do
- args = [feed_type, maker_readers, feed_readers]
- assert_not_set_error(not_set_error_name, %w(xml_content)) do
- RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "application/xml"
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(xml_content)) do
- RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "svg/image+xml"
- end
- end
-
- svg_uri = "http://www.w3.org/2000/svg"
- rect = RSS::XML::Element.new("rect", nil, svg_uri,
- {"x" => "0.5cm",
- "y" => "0.5cm",
- "width" => "2cm",
- "height" => "1cm"})
- svg = RSS::XML::Element.new("svg", nil, svg_uri,
- {"xmlns" => svg_uri,
- "version" => "1.1",
- "width" => "5cm",
- "height" => "4cm"},
- [rect])
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "image/svg+xml"
- target.xml = svg
- end
-
- feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "image/svg+xml"
- target.xml = svg
- end
- assert_equal(svg, chain_reader(feed, feed_readers).xml)
- end
- end
-
- def assert_maker_atom_content_inline_other_text(feed_type, maker_readers,
- feed_readers,
- not_set_error_name)
- _wrap_assertion do
- args = [feed_type, maker_readers, feed_readers]
- assert_not_set_error(not_set_error_name, %w(content)) do
- RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "text/plain"
- end
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "text/plain"
- target.content = "text"
- end
- end
- end
-
- def assert_maker_atom_content_inline_other_base64(feed_type, maker_readers,
- feed_readers,
- not_set_error_name)
- _wrap_assertion do
- args = [feed_type, maker_readers, feed_readers]
- content = "\211PNG\r\n\032\n"
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "image/png"
- target.content = content
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "image/png"
- target.src = "http://example.com/logo.png"
- target.content = content
- end
-
- feed = RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "image/png"
- target.src = "http://example.com/logo.png"
- target.content = content
- end
- target = chain_reader(feed, feed_readers)
- assert_nil(target.src)
- assert_equal(content, target.content)
- end
- end
-
- def assert_maker_atom_content_out_of_line(feed_type, maker_readers,
- feed_readers, not_set_error_name)
- _wrap_assertion do
- args = [feed_type, maker_readers, feed_readers]
- assert_not_set_error(not_set_error_name, %w(content)) do
- RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "image/png"
- end
- end
-
- assert_not_set_error(not_set_error_name, %w(type)) do
- RSS::Maker.make("atom:#{feed_type}") do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.src = "http://example.com/logo.png"
- end
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "image/png"
- target.src = "http://example.com/logo.png"
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "image/png"
- target.content = "\211PNG\r\n\032\n"
- end
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "application/xml"
- target.src = "http://example.com/sample.xml"
- end
-
-
- _assert_maker_atom_content(*args) do |maker|
- yield maker
- target = chain_reader(maker, maker_readers)
- target.type = "text/plain"
- target.src = "http://example.com/README.txt"
- end
- end
- end
-
- def assert_slash_elements(expected, target)
- assert_equal(expected,
- {
- "section" => target.slash_section,
- "department" => target.slash_department,
- "comments" => target.slash_comments,
- "hit_parades" => target.slash_hit_parades,
- })
- assert_equal(expected["hit_parades"].join(","),
- target.slash_hit_parade)
- end
-
- def chain_reader(target, readers, &block)
- readers.inject(target) do |result, reader|
- return nil if result.nil?
- result.__send__(reader, &block)
- end
- end
-
- def normalized_attrs(attrs)
- n_attrs = {}
- attrs.each do |name, value|
- n_attrs[name.to_s] = value
- end
- n_attrs
- end
-
- def combination(elements, n)
- if n <= 0 or elements.size < n
- []
- elsif n == 1
- elements.collect {|element| [element]}
- else
- first, *rest = elements
- combination(rest, n - 1).collect do |sub_elements|
- [first, *sub_elements]
- end + combination(rest, n)
- end
- end
-
- def tag(name, content=nil, attributes={})
- attributes = attributes.collect do |key, value|
- "#{ERB::Util.h(key)}=\"#{ERB::Util.h(value)}\""
- end.join(" ")
- begin_tag = "<#{name}"
- begin_tag << " #{attributes}" unless attributes.empty?
- if content
- "#{begin_tag}>#{content}</#{name}>\n"
- else
- "#{begin_tag}/>\n"
- end
- end
- end
-end
diff --git a/test/rss/rss-testcase.rb b/test/rss/rss-testcase.rb
deleted file mode 100644
index 30067d43b2..0000000000
--- a/test/rss/rss-testcase.rb
+++ /dev/null
@@ -1,479 +0,0 @@
-# frozen_string_literal: false
-require "erb"
-
-require "test/unit"
-require_relative 'rss-assertions'
-
-require "rss"
-
-module RSS
- class TestCase < Test::Unit::TestCase
- include ERB::Util
-
- include RSS
- include Assertions
-
- XMLDECL_VERSION = "1.0"
- XMLDECL_ENCODING = "UTF-8"
- XMLDECL_STANDALONE = "no"
-
- RDF_ABOUT = "http://www.xml.com/xml/news.rss"
- RDF_RESOURCE = "http://xml.com/universal/images/xml_tiny.gif"
- TITLE_VALUE = "XML.com"
- LINK_VALUE = "http://xml.com/pub"
- URL_VALUE = "http://xml.com/universal/images/xml_tiny.gif"
- NAME_VALUE = "hogehoge"
- LANGUAGE_VALUE = "ja"
- DESCRIPTION_VALUE = "
- XML.com features a rich mix of information and services
- for the XML community.
- "
- RESOURCES = [
- "http://xml.com/pub/2000/08/09/xslt/xslt.html",
- "http://xml.com/pub/2000/08/09/rdfdb/index.html",
- ]
-
- CLOUD_DOMAIN = "data.ourfavoritesongs.com"
- CLOUD_PORT = "80"
- CLOUD_PATH = "/RPC2"
- CLOUD_REGISTER_PROCEDURE = "ourFavoriteSongs.rssPleaseNotify"
- CLOUD_PROTOCOL = "xml-rpc"
-
- ENCLOSURE_URL = "http://www.scripting.com/mp3s/weatherReportSuite.mp3"
- ENCLOSURE_LENGTH = "12216320"
- ENCLOSURE_TYPE = "audio/mpeg"
-
- CATEGORY_DOMAIN = "http://www.superopendirectory.com/"
-
- FEED_TITLE = "dive into mark"
- FEED_UPDATED = "2003-12-13T18:30:02Z"
- FEED_AUTHOR_NAME = "John Doe"
- FEED_ID = "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6"
-
- ENTRY_TITLE = "Atom-Powered Robots Run Amok"
- ENTRY_LINK = "http://example.org/2003/12/13/atom03"
- ENTRY_ID = "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a"
- ENTRY_UPDATED = "2003-12-13T18:30:02Z"
- ENTRY_SUMMARY = "Some text."
-
- t = Time.iso8601("2000-01-01T12:00:05+00:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
-
- DC_ELEMENTS = {
- :title => "hoge",
- :description =>
- " XML is placing increasingly heavy loads on
- the existing technical infrastructure of the Internet.",
- :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
- :subject => "XML",
- :publisher => "The O'Reilly Network",
- :contributor => "hogehoge",
- :type => "fugafuga",
- :format => "hohoho",
- :identifier => "fufufu",
- :source => "barbar",
- :language => "ja",
- :relation => "cococo",
- :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
- :date => t,
- }
-
- DC_NODES = DC_ELEMENTS.collect do |name, value|
- "<#{DC_PREFIX}:#{name}>#{value}</#{DC_PREFIX}:#{name}>"
- end.join("\n")
-
- def default_test
- # This class isn't tested
- end
-
- private
- def make_xmldecl(v=XMLDECL_VERSION, e=XMLDECL_ENCODING, s=XMLDECL_STANDALONE)
- rv = "<?xml version='#{v}'"
- rv << " encoding='#{e}'" if e
- rv << " standalone='#{s}'" if s
- rv << "?>"
- rv
- end
-
- def make_RDF(content=nil, xmlns=[])
- <<-EORSS
-#{make_xmldecl}
-<rdf:RDF xmlns="#{URI}" xmlns:rdf="#{RDF::URI}"
-#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
-#{block_given? ? yield : content}
-</rdf:RDF>
-EORSS
- end
-
- def make_channel(content=nil)
- <<-EOC
-<channel rdf:about="#{RDF_ABOUT}">
- <title>#{TITLE_VALUE}</title>
- <link>#{LINK_VALUE}</link>
- <description>#{DESCRIPTION_VALUE}</description>
-
- <image rdf:resource="#{RDF_RESOURCE}" />
-
- <items>
- <rdf:Seq>
-#{RESOURCES.collect do |res| '<rdf:li resource="' + res + '" />' end.join("\n")}
- </rdf:Seq>
- </items>
-
- <textinput rdf:resource="#{RDF_RESOURCE}" />
-
-#{block_given? ? yield : content}
-</channel>
-EOC
- end
-
- def make_image(content=nil)
- <<-EOI
-<image rdf:about="#{RDF_ABOUT}">
- <title>#{TITLE_VALUE}</title>
- <url>#{URL_VALUE}</url>
- <link>#{LINK_VALUE}</link>
-#{block_given? ? yield : content}
-</image>
-EOI
- end
-
- def make_item(content=nil)
- <<-EOI
-<item rdf:about="#{RDF_ABOUT}">
- <title>#{TITLE_VALUE}</title>
- <link>#{LINK_VALUE}</link>
- <description>#{DESCRIPTION_VALUE}</description>
-#{block_given? ? yield : content}
-</item>
-EOI
- end
-
- def make_textinput(content=nil)
- <<-EOT
-<textinput rdf:about="#{RDF_ABOUT}">
- <title>#{TITLE_VALUE}</title>
- <description>#{DESCRIPTION_VALUE}</description>
- <name>#{NAME_VALUE}</name>
- <link>#{LINK_VALUE}</link>
-#{block_given? ? yield : content}
-</textinput>
-EOT
- end
-
- def make_sample_RDF
- make_RDF(<<-EOR)
-#{make_channel}
-#{make_image}
-#{make_item}
-#{make_textinput}
-EOR
- end
-
- def make_rss20(content=nil, xmlns=[])
- <<-EORSS
-#{make_xmldecl}
-<rss version="2.0"
-#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
-#{block_given? ? yield : content}
-</rss>
-EORSS
- end
-
- def make_sample_items20
- RESOURCES.collect do |res|
- elems = ["<link>#{res}</link>"]
- elems << "<title>title of #{res}</title>"
- elems = elems.join("\n")
- "<item>\n#{elems}\n</item>"
- end.join("\n")
- end
-
- def make_channel20(content=nil)
- <<-EOC
-<channel>
- <title>#{TITLE_VALUE}</title>
- <link>#{LINK_VALUE}</link>
- <description>#{DESCRIPTION_VALUE}</description>
- <language>#{LANGUAGE_VALUE}</language>
-
- <image>
- <url>#{RDF_RESOURCE}</url>
- <title>#{TITLE_VALUE}</title>
- <link>#{LINK_VALUE}</link>
- </image>
-
-#{make_sample_items20}
-
- <textInput>
- <title>#{TITLE_VALUE}</title>
- <description>#{DESCRIPTION_VALUE}</description>
- <name>#{NAME_VALUE}</name>
- <link>#{RDF_RESOURCE}</link>
- </textInput>
-
-#{block_given? ? yield : content}
-</channel>
-EOC
- end
-
- def make_item20(content=nil)
- <<-EOI
-<item>
- <title>#{TITLE_VALUE}</title>
- <link>#{LINK_VALUE}</link>
- <description>#{DESCRIPTION_VALUE}</description>
-#{block_given? ? yield : content}
-</item>
-EOI
- end
-
- def make_cloud20
- <<-EOC
-<cloud
- domain="#{CLOUD_DOMAIN}"
- port="#{CLOUD_PORT}"
- path="#{CLOUD_PATH}"
- registerProcedure="#{CLOUD_REGISTER_PROCEDURE}"
- protocol="#{CLOUD_PROTOCOL}" />
-EOC
- end
-
- def make_sample_rss20
- make_rss20(<<-EOR)
-#{make_channel20}
-EOR
- end
-
- def make_feed_without_entry(content=nil, xmlns=[])
- <<-EOA
-<feed xmlns="#{Atom::URI}"
-#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
- <id>#{FEED_ID}</id>
- <title>#{FEED_TITLE}</title>
- <updated>#{FEED_UPDATED}</updated>
- <author>
- <name>#{FEED_AUTHOR_NAME}</name>
- </author>
-#{block_given? ? yield : content}
-</feed>
-EOA
- end
-
- def make_entry(content=nil)
- <<-EOA
- <entry>
- <title>#{ENTRY_TITLE}</title>
- <id>#{ENTRY_ID}</id>
- <updated>#{ENTRY_UPDATED}</updated>
-#{block_given? ? yield : content}
- </entry>
-EOA
- end
-
- def make_feed_with_open_entry(content=nil, xmlns=[], &block)
- make_feed_without_entry(<<-EOA, xmlns)
-#{make_entry(content, &block)}
-EOA
- end
-
- def make_feed_with_open_entry_source(content=nil, xmlns=[])
- make_feed_with_open_entry(<<-EOA, xmlns)
- <source>
-#{block_given? ? yield : content}
- </source>
-EOA
- end
-
- def make_feed(content=nil, xmlns=[])
- make_feed_without_entry(<<-EOA, xmlns)
- <entry>
- <title>#{ENTRY_TITLE}</title>
- <link href="#{ENTRY_LINK}"/>
- <id>#{ENTRY_ID}</id>
- <updated>#{ENTRY_UPDATED}</updated>
- <summary>#{ENTRY_SUMMARY}</summary>
- </entry>
-#{block_given? ? yield : content}
-EOA
- end
-
- def make_entry_document(content=nil, xmlns=[])
- <<-EOA
-<entry xmlns="#{Atom::URI}"
-#{xmlns.collect {|pre, uri| "xmlns:#{pre}='#{uri}'"}.join(' ')}>
- <id>#{ENTRY_ID}</id>
- <title>#{ENTRY_TITLE}</title>
- <updated>#{ENTRY_UPDATED}</updated>
- <author>
- <name>#{FEED_AUTHOR_NAME}</name>
- </author>
-#{block_given? ? yield : content}
-</entry>
-EOA
- end
-
- def make_entry_document_with_open_source(content=nil, xmlns=[])
- make_entry_document(<<-EOA, xmlns)
- <source>
-#{block_given? ? yield : content}
- </source>
-EOA
- end
-
- def make_element(elem_name, attrs, contents)
- attrs_str = attrs.collect do |name, value|
- "#{h name}='#{h value}'"
- end.join(" ")
- attrs_str = " #{attrs_str}" unless attrs_str.empty?
-
- if contents.is_a?(String)
- contents_str = h(contents)
- else
- contents_str = contents.collect do |name, value|
- "#{Element::INDENT}<#{h name}>#{h value}</#{h name}>"
- end.join("\n")
- contents_str = "\n#{contents_str}\n"
- end
-
- "<#{h elem_name}#{attrs_str}>#{contents_str}</#{h elem_name}>"
- end
-
- def xmlns_container(xmlns_decls, content)
- attributes = xmlns_decls.collect do |prefix, uri|
- "xmlns:#{h prefix}=\"#{h uri}\""
- end.join(" ")
- "<dummy #{attributes}>#{content}</dummy>"
- end
-
- private
- def setup_rss10(rdf)
- assert_equal("", rdf.to_s)
-
- channel = RDF::Channel.new
- assert_equal("", channel.to_s)
- channel.about = "http://example.com/index.rdf"
- channel.title = "title"
- channel.link = "http://example.com/"
- channel.description = "description"
- assert_equal("", channel.to_s)
-
- item_title = "item title"
- item_link = "http://example.com/item"
- channel.items = RDF::Channel::Items.new
- channel.items.Seq.lis << RDF::Channel::Items::Seq::Li.new(item_link)
- assert_not_equal("", channel.to_s)
-
- rdf.channel = channel
- assert_equal("", rdf.to_s)
-
- item = RDF::Item.new
- item.title = item_title
- item.link = item_link
- item.about = item_link
- rdf.items << item
- assert_not_equal("", rdf.to_s)
- end
-
- def setup_rss20(rss)
- assert_equal("", rss.to_s)
-
- channel = Rss::Channel.new
- assert_equal("", channel.to_s)
- channel.title = "title"
- channel.link = "http://example.com/"
- channel.description = "description"
- assert_not_equal("", channel.to_s)
-
- rss.channel = channel
- assert_not_equal("", rss.to_s)
- end
-
- def setup_dummy_channel(maker)
- about = "http://hoge.com"
- title = "fugafuga"
- link = "http://hoge.com/feed.xml"
- description = "fugafugafugafuga"
- language = "ja"
-
- maker.channel.about = about
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- maker.channel.language = language
- end
-
- def setup_dummy_channel_atom(maker)
- updated = Time.now
- author = "Foo"
-
- setup_dummy_channel(maker)
- maker.channel.links.first.rel = "self"
- maker.channel.links.first.type = "application/atom+xml"
- maker.channel.updated = updated
- maker.channel.author = author
- end
-
- def setup_dummy_image(maker)
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
-
- maker.channel.link = link if maker.channel.link.nil?
-
- maker.image.title = title
- maker.image.url = url
- end
-
- def setup_dummy_textinput(maker)
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com/search.cgi"
-
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
-
- def setup_dummy_item(maker)
- title = "TITLE"
- link = "http://hoge.com/"
-
- item = maker.items.new_item
- item.title = title
- item.link = link
- end
-
- def setup_dummy_item_atom(maker)
- setup_dummy_item(maker)
-
- item = maker.items.first
- item.id = "http://example.net/xxx"
- item.updated = Time.now
- end
-
- def setup_taxo_topic(target, topics)
- topics.each do |topic|
- taxo_topic = target.taxo_topics.new_taxo_topic
- topic.each do |name, value|
- case name
- when :link
- taxo_topic.taxo_link = value
- when :topics
- value.each do |t|
- taxo_topic.taxo_topics << t
- end
- else
- dc_elems = taxo_topic.__send__("dc_#{name}s")
- dc_elem = dc_elems.__send__("new_#{name}")
- dc_elem.value = value
- end
- end
- end
- end
- end
-end
diff --git a/test/rss/test_1.0.rb b/test/rss/test_1.0.rb
deleted file mode 100644
index 33ae29141b..0000000000
--- a/test/rss/test_1.0.rb
+++ /dev/null
@@ -1,308 +0,0 @@
-# frozen_string_literal: false
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/1.0"
-
-module RSS
- class TestRSS10Core < TestCase
-
- def setup
- @rdf_prefix = "rdf"
- @rdf_uri = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- @uri = "http://purl.org/rss/1.0/"
- end
-
- def test_RDF
- version = "1.0"
- encoding = "UTF-8"
- standalone = false
-
- rdf = RDF.new(version, encoding, standalone)
- setup_rss10(rdf)
- doc = REXML::Document.new(rdf.to_s)
-
- xmldecl = doc.xml_decl
-
- assert_equal(version, xmldecl.version)
- assert_equal(encoding, xmldecl.encoding.to_s)
- assert_equal(standalone, !xmldecl.standalone.nil?)
-
- assert_equal(@rdf_uri, doc.root.namespace)
- end
-
- def test_not_displayed_xml_stylesheets
- rdf = RDF.new()
- plain_rdf = rdf.to_s
- 3.times do
- rdf.xml_stylesheets.push(XMLStyleSheet.new)
- assert_equal(plain_rdf, rdf.to_s)
- end
- end
-
- def test_xml_stylesheets
- [
- [{:href => "a.xsl", :type => "text/xsl"}],
- [
- {:href => "a.xsl", :type => "text/xsl"},
- {:href => "a.css", :type => "text/css"},
- ],
- ].each do |attrs_ary|
- assert_xml_stylesheet_pis(attrs_ary)
- end
- end
-
- def test_channel
- about = "http://hoge.com"
- resource = "http://hoge.com/hoge.png"
-
- item_title = "item title"
- item_link = "http://hoge.com/item"
-
- image = RDF::Channel::Image.new(resource)
- items = RDF::Channel::Items.new
- items.Seq.lis << items.class::Seq::Li.new(item_link)
- textinput = RDF::Channel::Textinput.new(resource)
-
- rss_item = RDF::Item.new
- rss_item.title = item_title
- rss_item.link = item_link
- rss_item.about = item_link
-
- h = {
- 'title' => "fugafuga",
- 'link' => "http://hoge.com",
- 'description' => "fugafugafugafuga",
- 'image' => image,
- 'items' => items,
- 'textinput' => textinput,
- }
-
- channel = RDF::Channel.new(about)
- %w(title link description image items textinput).each do |x|
- channel.__send__("#{x}=", h[x])
- end
-
- doc = REXML::Document.new(make_RDF(<<-EOR))
-#{channel}
-<items>
-#{rss_item}
-</items>
-EOR
- c = doc.root.elements[1]
-
- assert_equal(about, c.attributes["about"])
- %w(title link description image textinput).each do |x|
- elem = c.elements[x]
- assert_equal(x, elem.name)
- assert_equal(@uri, elem.namespace)
- if x == "image" or x == "textinput"
- excepted = resource
- res = elem.attributes.get_attribute("resource")
- assert_equal(@rdf_uri, res.namespace)
- value = res.value
- else
- excepted = h[x]
- value = elem.text
- end
- assert_equal(excepted, value)
- end
- assert_equal(@uri, c.elements["items"].namespace)
- assert_equal("items", c.elements["items"].name)
- end
-
- def test_channel_image
- resource = "http://hoge.com/hoge.png"
- image = RDF::Channel::Image.new(resource)
-
- doc = REXML::Document.new(make_RDF(image.to_s))
- i = doc.root.elements[1]
-
- assert_equal("image", i.name)
- assert_equal(@uri, i.namespace)
-
- res = i.attributes.get_attribute("resource")
-
- assert_equal(@rdf_uri, res.namespace)
- assert_equal(resource, res.value)
- end
-
- def test_channel_textinput
- resource = "http://hoge.com/hoge.png"
- textinput = RDF::Channel::Textinput.new(resource)
-
- doc = REXML::Document.new(make_RDF(textinput.to_s))
- t = doc.root.elements[1]
-
- assert_equal("textinput", t.name)
- assert_equal(@uri, t.namespace)
-
- res = t.attributes.get_attribute("resource")
-
- assert_equal(@rdf_uri, res.namespace)
- assert_equal(resource, res.value)
- end
-
- def test_channel_items
- item_link = "http://example.com/item"
-
- items = RDF::Channel::Items.new
- li = items.Seq.class::Li.new(item_link)
- items.Seq.lis << li
-
- doc = REXML::Document.new(make_RDF(items.to_s))
- i = doc.root.elements[1]
-
- assert_equal("items", i.name)
- assert_equal(@uri, i.namespace)
-
- assert_equal(1, i.elements.size)
- seq = i.elements[1]
- assert_equal("Seq", seq.name)
- assert_equal(@rdf_uri, seq.namespace)
-
- assert_equal(1, seq.elements.size)
- l = seq.elements[1]
- assert_equal("li", l.name)
- assert_equal(@rdf_uri, l.namespace)
- assert_equal(item_link, l.attributes["resource"])
- end
-
- def test_seq
- item_link = "http://example.com/item"
- seq = RDF::Seq.new
- li = seq.class::Li.new(item_link)
- seq.lis << li
-
- doc = REXML::Document.new(make_RDF(seq.to_s))
- s = doc.root.elements[1]
-
- assert_equal("Seq", s.name)
- assert_equal(@rdf_uri, s.namespace)
-
- assert_equal(1, s.elements.size)
- l = s.elements[1]
- assert_equal("li", l.name)
- assert_equal(@rdf_uri, l.namespace)
- assert_equal(item_link, l.attributes["resource"])
- end
-
- def test_li
- resource = "http://hoge.com/"
- li = RDF::Li.new(resource)
-
- doc = REXML::Document.new(make_RDF(li.to_s))
- l = doc.root.elements[1]
-
- assert_equal("li", l.name)
- assert_equal(@rdf_uri, l.namespace(l.prefix))
-
- res = l.attributes.get_attribute("resource")
-
- assert_equal('', res.instance_eval("@prefix"))
- assert_equal(resource, res.value)
- end
-
- def test_image
- about = "http://hoge.com"
- h = {
- 'title' => "fugafuga",
- 'url' => "http://hoge.com/hoge",
- 'link' => "http://hoge.com/fuga",
- }
-
- image = RDF::Image.new(about)
- %w(title url link).each do |x|
- image.__send__("#{x}=", h[x])
- end
-
- doc = REXML::Document.new(make_RDF(image.to_s))
- i = doc.root.elements[1]
-
- assert_equal(about, i.attributes["about"])
- %w(title url link).each do |x|
- elem = i.elements[x]
- assert_equal(x, elem.name)
- assert_equal(@uri, elem.namespace)
- assert_equal(h[x], elem.text)
- end
- end
-
- def test_item
- about = "http://hoge.com"
- h = {
- 'title' => "fugafuga",
- 'link' => "http://hoge.com/fuga",
- 'description' => "hogehogehoge",
- }
-
- item = RDF::Item.new(about)
- %w(title link description).each do |x|
- item.__send__("#{x}=", h[x])
- end
-
- doc = REXML::Document.new(make_RDF(item.to_s))
- i = doc.root.elements[1]
-
- assert_equal(about, i.attributes["about"])
- %w(title link description).each do |x|
- elem = i.elements[x]
- assert_equal(x, elem.name)
- assert_equal(@uri, elem.namespace)
- assert_equal(h[x], elem.text)
- end
- end
-
- def test_textinput
- about = "http://hoge.com"
- h = {
- 'title' => "fugafuga",
- 'link' => "http://hoge.com/fuga",
- 'name' => "foo",
- 'description' => "hogehogehoge",
- }
-
- textinput = RDF::Textinput.new(about)
- %w(title link name description).each do |x|
- textinput.__send__("#{x}=", h[x])
- end
-
- doc = REXML::Document.new(make_RDF(textinput.to_s))
- t = doc.root.elements[1]
-
- assert_equal(about, t.attributes["about"])
- %w(title link name description).each do |x|
- elem = t.elements[x]
- assert_equal(x, elem.name)
- assert_equal(@uri, elem.namespace)
- assert_equal(h[x], elem.text)
- end
- end
-
- def test_to_xml
- rss = RSS::Parser.parse(make_sample_RDF)
- assert_equal(rss.to_s, rss.to_xml)
- assert_equal(rss.to_s, rss.to_xml("1.0"))
- rss09 = rss.to_xml("0.91") do |maker|
- maker.channel.language = "en-us"
- end
- rss09 = RSS::Parser.parse(rss09)
- assert_equal("0.91", rss09.rss_version)
- assert_equal(["rss", "0.91", nil], rss09.feed_info)
- rss20 = RSS::Parser.parse(rss.to_xml("2.0"))
- assert_equal("2.0", rss20.rss_version)
- assert_equal(["rss", "2.0", nil], rss20.feed_info)
-
- atom_xml = rss.to_xml("atom") do |maker|
- maker.channel.author = "Alice"
- maker.channel.updated ||= Time.now
- maker.items.each do |item|
- item.updated ||= Time.now
- end
- end
- atom = RSS::Parser.parse(atom_xml)
- assert_equal(["atom", "1.0", "feed"], atom.feed_info)
- end
- end
-end
diff --git a/test/rss/test_2.0.rb b/test/rss/test_2.0.rb
deleted file mode 100644
index 650f835010..0000000000
--- a/test/rss/test_2.0.rb
+++ /dev/null
@@ -1,412 +0,0 @@
-# frozen_string_literal: false
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-module RSS
- class TestRSS20Core < TestCase
-
- def setup
- @rss_version = "2.0"
- end
-
- def test_Rss
- version = "1.0"
- encoding = "UTF-8"
- standalone = false
-
- rss = Rss.new(@rss_version, version, encoding, standalone)
- setup_rss20(rss)
-
- doc = REXML::Document.new(rss.to_s(false))
-
- xmldecl = doc.xml_decl
-
- assert_equal(version, xmldecl.version)
- assert_equal(encoding, xmldecl.encoding.to_s)
- assert_equal(standalone, !xmldecl.standalone.nil?)
-
- assert_equal("", doc.root.namespace)
- assert_equal(@rss_version, doc.root.attributes["version"])
- end
-
- def test_not_displayed_xml_stylesheets
- rss = Rss.new(@rss_version)
- plain_rss = rss.to_s
- 3.times do
- rss.xml_stylesheets.push(XMLStyleSheet.new)
- assert_equal(plain_rss, rss.to_s)
- end
- end
-
- def test_xml_stylesheets
- [
- [{:href => "a.xsl", :type => "text/xsl"}],
- [
- {:href => "a.xsl", :type => "text/xsl"},
- {:href => "a.css", :type => "text/css"},
- ],
- ].each do |attrs_ary|
- rss = Rss.new(@rss_version)
- setup_rss20(rss)
- assert_xml_stylesheet_pis(attrs_ary, rss)
- end
- end
-
- def test_channel
- h = {
- 'title' => "fugafuga",
- 'link' => "http://hoge.com",
- 'description' => "fugafugafugafuga",
-
- 'language' => "en-us",
- 'copyright' => "Copyright 2002, Spartanburg Herald-Journal",
- 'managingEditor' => "geo@herald.com (George Matesky)",
- 'webMaster' => "betty@herald.com (Betty Guernsey)",
- 'pubDate' => Time.parse("Sat, 07 Sep 2002 00:00:01 GMT"),
- 'lastBuildDate' => Time.parse("Sat, 07 Sep 2002 09:42:31 GMT"),
- 'generator' => "MightyInHouse Content System v2.3",
- 'docs' => "http://blogs.law.harvard.edu/tech/rss",
- 'ttl' => "60",
- 'rating' => '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))',
- }
- categories = [
- {
- :content => "Newspapers",
- },
- {
- :domain => "Syndic8",
- :content => "1765",
- }
- ]
-
- channel = Rss::Channel.new
-
- elems = %w(title link description language copyright
- managingEditor webMaster pubDate lastBuildDate
- generator docs ttl rating)
- elems.each do |x|
- value = h[x]
- value = value.rfc822 if %w(pubDate lastBuildDate).include?(x)
- channel.__send__("#{x}=", value)
- end
- categories.each do |cat|
- channel.categories << Rss::Channel::Category.new(cat[:domain],
- cat[:content])
- end
-
- doc = REXML::Document.new(make_rss20(channel.to_s))
- c = doc.root.elements[1]
-
- elems.each do |x|
- elem = c.elements[x]
- assert_equal(x, elem.name)
- assert_equal("", elem.namespace)
- expected = h[x]
- case x
- when "pubDate", "lastBuildDate"
- assert_equal(expected, Time.parse(elem.text))
- when "ttl"
- expected = channel.__send__(x)
- assert_equal(expected, elem.text.to_i)
- else
- assert_equal(expected, elem.text)
- end
- end
- categories.each_with_index do |cat, i|
- cat = cat.dup
- cat[:domain] ||= nil
- category = c.elements["category[#{i+1}]"]
- actual = {
- :domain => category.attributes["domain"],
- :content => category.text,
- }
- assert_equal(cat, actual)
- end
- end
-
- def test_channel_cloud
- cloud_params = {
- :domain => "rpc.sys.com",
- :port => "80",
- :path => "/RPC2",
- :registerProcedure => "myCloud.rssPleaseNotify",
- :protocol => "xml-rpc",
- }
- cloud = Rss::Channel::Cloud.new(cloud_params[:domain],
- cloud_params[:port],
- cloud_params[:path],
- cloud_params[:registerProcedure],
- cloud_params[:protocol])
- cloud_params[:port] = cloud.port
-
- doc = REXML::Document.new(cloud.to_s)
- cloud_elem = doc.root
-
- actual = {}
- cloud_elem.attributes.each do |name, value|
- value = value.to_i if name == "port"
- actual[name.intern] = value
- end
- assert_equal(cloud_params, actual)
- end
-
- def test_channel_image
- image_params = {
- :url => "http://hoge.com/hoge.png",
- :title => "fugafuga",
- :link => "http://hoge.com",
- :width => "144",
- :height => "400",
- :description => "an image",
- }
- image = Rss::Channel::Image.new(image_params[:url],
- image_params[:title],
- image_params[:link],
- image_params[:width],
- image_params[:height],
- image_params[:description])
-
- doc = REXML::Document.new(image.to_s)
- image_elem = doc.root
-
- image_params.each do |name, value|
- value = image.__send__(name)
- actual = image_elem.elements[name.to_s].text
- actual = actual.to_i if [:width, :height].include?(name)
- assert_equal(value, actual)
- end
- end
-
- def test_channel_textInput
- textInput_params = {
- :title => "fugafuga",
- :description => "text hoge fuga",
- :name => "hoge",
- :link => "http://hoge.com",
- }
- textInput = Rss::Channel::TextInput.new(textInput_params[:title],
- textInput_params[:description],
- textInput_params[:name],
- textInput_params[:link])
-
- doc = REXML::Document.new(textInput.to_s)
- input_elem = doc.root
-
- textInput_params.each do |name, value|
- actual = input_elem.elements[name.to_s].text
- assert_equal(value, actual)
- end
- end
-
- def test_channel_skip_days
- skipDays_values = [
- "Sunday",
- "Monday",
- ]
- skipDays = Rss::Channel::SkipDays.new
- skipDays_values.each do |value|
- skipDays.days << Rss::Channel::SkipDays::Day.new(value)
- end
-
- doc = REXML::Document.new(skipDays.to_s)
- days_elem = doc.root
-
- skipDays_values.each_with_index do |value, i|
- assert_equal(value, days_elem.elements[i + 1].text)
- end
- end
-
- def test_channel_skip_hours
- skipHours_values = [
- "0",
- "13",
- ]
- skipHours = Rss::Channel::SkipHours.new
- skipHours_values.each do |value|
- skipHours.hours << Rss::Channel::SkipHours::Hour.new(value)
- end
-
- doc = REXML::Document.new(skipHours.to_s)
- hours_elem = doc.root
-
- skipHours_values.each_with_index do |value, i|
- expected = skipHours.hours[i].content
- assert_equal(expected, hours_elem.elements[i + 1].text.to_i)
- end
- end
-
- def test_item
- h = {
- 'title' => "fugafuga",
- 'link' => "http://hoge.com/",
- 'description' => "text hoge fuga",
- 'author' => "oprah@oxygen.net",
- 'comments' => "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290",
- 'pubDate' => Time.parse("Sat, 07 Sep 2002 00:00:01 GMT"),
- }
- categories = [
- {
- :content => "Newspapers",
- },
- {
- :domain => "Syndic8",
- :content => "1765",
- }
- ]
-
- channel = Rss::Channel.new
- channel.title = "title"
- channel.link = "http://example.com/"
- channel.description = "description"
-
- item = Rss::Channel::Item.new
- channel.items << item
-
- elems = %w(title link description author comments pubDate)
- elems.each do |x|
- value = h[x]
- value = value.rfc822 if x == "pubDate"
- item.__send__("#{x}=", value)
- end
- categories.each do |cat|
- item.categories << Rss::Channel::Category.new(cat[:domain],
- cat[:content])
- end
-
- doc = REXML::Document.new(channel.to_s)
- channel_elem = doc.root
-
- item_elem = channel_elem.elements["item[1]"]
- elems.each do |x|
- elem = item_elem.elements[x]
- assert_equal(x, elem.name)
- assert_equal("", elem.namespace)
- expected = h[x]
- case x
- when "pubDate"
- assert_equal(expected, Time.parse(elem.text))
- else
- assert_equal(expected, elem.text)
- end
- end
- categories.each_with_index do |cat, i|
- cat = cat.dup
- cat[:domain] ||= nil
- category = item_elem.elements["category[#{i+1}]"]
- actual = {
- :domain => category.attributes["domain"],
- :content => category.text,
- }
- assert_equal(cat, actual)
- end
- end
-
- def test_item_enclosure
- enclosure_params = {
- :url => "http://www.scripting.com/mp3s/weatherReportSuite.mp3",
- :length => "12216320",
- :type => "audio/mpeg",
- }
-
- enclosure = Rss::Channel::Item::Enclosure.new(enclosure_params[:url],
- enclosure_params[:length],
- enclosure_params[:type])
- enclosure_params[:length] = enclosure.length
-
- doc = REXML::Document.new(enclosure.to_s)
- enclosure_elem = doc.root
-
- actual = {}
- enclosure_elem.attributes.each do |name, value|
- value = value.to_i if name == "length"
- actual[name.intern] = value
- end
- assert_equal(enclosure_params, actual)
- end
-
- def test_item_guid
- test_params = [
- {
- :content => "http://some.server.com/weblogItem3207",
- },
- {
- :isPermaLink => "true",
- :content => "http://inessential.com/2002/09/01.php#a2",
- },
- ]
-
- test_params.each do |guid_params|
- guid = Rss::Channel::Item::Guid.new(guid_params[:isPermaLink],
- guid_params[:content])
- if guid_params.has_key?(:isPermaLink)
- guid_params[:isPermaLink] = guid.isPermaLink
- end
- if guid.isPermaLink.nil?
- assert_equal(true, guid.PermaLink?)
- else
- assert_equal(guid.isPermaLink, guid.PermaLink?)
- end
-
- doc = REXML::Document.new(guid.to_s)
- guid_elem = doc.root
-
- actual = {}
- actual[:content] = guid_elem.text if guid_elem.text
- guid_elem.attributes.each do |name, value|
- value = value == "true" if name == "isPermaLink"
- actual[name.intern] = value
- end
- assert_equal(guid_params, actual)
- end
- end
-
- def test_item_source
- source_params = {
- :url => "http://www.tomalak.org/links2.xml",
- :content => "Tomalak's Realm",
- }
-
- source = Rss::Channel::Item::Source.new(source_params[:url],
- source_params[:content])
-
- doc = REXML::Document.new(source.to_s)
- source_elem = doc.root
-
- actual = {}
- actual[:content] = source_elem.text
- source_elem.attributes.each do |name, value|
- actual[name.intern] = value
- end
- assert_equal(source_params, actual)
- end
-
- def test_to_xml
- rss = RSS::Parser.parse(make_sample_rss20)
- assert_equal(rss.to_s, rss.to_xml)
- assert_equal(rss.to_s, rss.to_xml("2.0"))
- rss09_xml = rss.to_xml("0.91") do |maker|
- setup_dummy_image(maker)
- end
- rss09 = RSS::Parser.parse(rss09_xml)
- assert_equal("0.91", rss09.rss_version)
- rss10 = rss.to_xml("1.0") do |maker|
- maker.channel.about = "http://www.example.com/index.rdf"
- end
- rss10 = RSS::Parser.parse(rss10)
- assert_equal("1.0", rss10.rss_version)
-
- atom_xml = rss.to_xml("atom1.0") do |maker|
- maker.channel.id = "http://www.example.com/atom.xml"
- maker.channel.author = "Alice"
- maker.channel.updated = Time.now
- maker.items.each do |item|
- item.author = "Bob"
- item.updated = Time.now
- end
- end
- atom = RSS::Parser.parse(atom_xml)
- assert_equal(["atom", "1.0", "feed"], atom.feed_info)
- end
- end
-end
diff --git a/test/rss/test_accessor.rb b/test/rss/test_accessor.rb
deleted file mode 100644
index 7d4424dbbd..0000000000
--- a/test/rss/test_accessor.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/2.0"
-require "rss/syndication"
-require "rss/image"
-
-module RSS
- class TestAccessor < TestCase
- def test_date
- channel = Rss::Channel.new
- channel.pubDate = nil
- assert_nil(channel.pubDate)
-
- time = Time.now
- channel.pubDate = time
- assert_equal(time, channel.pubDate)
-
- time = Time.parse(Time.now.rfc822)
- channel.pubDate = time.rfc822
- assert_equal(time, channel.pubDate)
-
- time = Time.parse(Time.now.iso8601)
- value = time.iso8601
- assert_not_available_value("pubDate", value) do
- channel.pubDate = value
- end
-
- channel.do_validate = false
- time = Time.parse(Time.now.iso8601)
- value = time.iso8601
- channel.pubDate = value
- assert_equal(time, channel.pubDate)
-
- channel.pubDate = nil
- assert_nil(channel.pubDate)
- end
-
- def test_integer
- image_item = RDF::Item::ImageItem.new
-
- image_item.width = nil
- assert_nil(image_item.width)
-
- width = 10
- image_item.width = width
- assert_equal(width, image_item.width)
-
- width = 10.0
- image_item.width = width
- assert_equal(width, image_item.width)
-
- width = "10"
- image_item.width = width
- assert_equal(width.to_i, image_item.width)
-
- width = "10.0"
- assert_not_available_value("image:width", width) do
- image_item.width = width
- end
-
- image_item.do_validate = false
- width = "10.0"
- image_item.width = width
- assert_equal(width.to_i, image_item.width)
-
- image_item.width = nil
- assert_nil(image_item.width)
- end
-
- def test_positive_integer
- channel = RDF::Channel.new
-
- channel.sy_updateFrequency = nil
- assert_nil(channel.sy_updateFrequency)
-
- freq = 10
- channel.sy_updateFrequency = freq
- assert_equal(freq, channel.sy_updateFrequency)
-
- freq = 10.0
- channel.sy_updateFrequency = freq
- assert_equal(freq, channel.sy_updateFrequency)
-
- freq = "10"
- channel.sy_updateFrequency = freq
- assert_equal(freq.to_i, channel.sy_updateFrequency)
-
- freq = "10.0"
- assert_not_available_value("sy:updateFrequency", freq) do
- channel.sy_updateFrequency = freq
- end
-
- channel.do_validate = false
- freq = "10.0"
- channel.sy_updateFrequency = freq
- assert_equal(freq.to_i, channel.sy_updateFrequency)
-
- channel.sy_updateFrequency = nil
- assert_nil(channel.sy_updateFrequency)
- end
- end
-end
diff --git a/test/rss/test_atom.rb b/test/rss/test_atom.rb
deleted file mode 100644
index 774064eff7..0000000000
--- a/test/rss/test_atom.rb
+++ /dev/null
@@ -1,684 +0,0 @@
-# frozen_string_literal: false
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/atom"
-
-module RSS
- class TestAtomCore < TestCase
- def setup
- @uri = "http://www.w3.org/2005/Atom"
- @xhtml_uri = "http://www.w3.org/1999/xhtml"
- end
-
- def test_feed
- version = "1.0"
- encoding = "UTF-8"
- standalone = false
-
- feed = Atom::Feed.new(version, encoding, standalone)
- assert_equal("", feed.to_s)
-
- author = feed.class::Author.new
- name = feed.class::Author::Name.new
- name.content = "an author"
- author.name = name
- assert_not_equal("", author.to_s)
- feed.authors << author
- assert_equal("", feed.to_s)
-
- id = feed.class::Id.new
- id.content = "http://example.com/atom.xml"
- assert_not_equal("", id.to_s)
- feed.id = id
- assert_equal("", feed.to_s)
-
- title = feed.class::Title.new
- title.content = "a title"
- assert_not_equal("", title.to_s)
- feed.title = title
- assert_equal("", feed.to_s)
-
- updated = feed.class::Updated.new
- updated.content = Time.now
- assert_not_equal("", updated.to_s)
- feed.updated = updated
- assert_not_equal("", feed.to_s)
-
-
- feed.authors.clear
- assert_equal("", feed.to_s)
- entry = Atom::Feed::Entry.new
- setup_entry(entry)
- assert_not_equal("", entry.to_s)
-
- author = entry.authors.first
- entry.authors.clear
- assert_equal("", entry.to_s)
- entry.parent = feed
- assert_equal("", entry.to_s)
- feed.authors << author
- assert_not_equal("", entry.to_s)
- feed.authors.clear
- feed.entries << entry
- assert_equal("", feed.to_s)
- entry.authors << author
- assert_not_equal("", entry.to_s)
- assert_not_equal("", feed.to_s)
-
- doc = REXML::Document.new(feed.to_s)
- xmldecl = doc.xml_decl
-
- assert_equal(version, xmldecl.version)
- assert_equal(encoding, xmldecl.encoding.to_s)
- assert_equal(standalone, !xmldecl.standalone.nil?)
-
- assert_equal(@uri, doc.root.namespace)
- end
-
- def test_entry
- version = "1.0"
- encoding = "UTF-8"
- standalone = false
-
- entry = Atom::Entry.new(version, encoding, standalone)
- setup_entry(entry)
-
- author = entry.authors.first
- entry.authors.clear
- assert_equal("", entry.to_s)
- source = Atom::Entry::Source.new
- source.authors << author
- entry.source = source
- assert_not_equal("", entry.to_s)
-
- doc = REXML::Document.new(entry.to_s)
- xmldecl = doc.xml_decl
-
- assert_equal(version, xmldecl.version)
- assert_equal(encoding, xmldecl.encoding.to_s)
- assert_equal(standalone, !xmldecl.standalone.nil?)
-
- assert_equal(@uri, doc.root.namespace)
- end
-
- def test_not_displayed_xml_stylesheets
- feed = Atom::Feed.new
- plain_feed = feed.to_s
- 3.times do
- feed.xml_stylesheets.push(XMLStyleSheet.new)
- assert_equal(plain_feed, feed.to_s)
- end
- end
-
- def test_atom_author
- assert_atom_person_to_s(Atom::Feed::Author)
- assert_atom_person_to_s(Atom::Feed::Entry::Author)
- assert_atom_person_to_s(Atom::Entry::Author)
- assert_atom_person_to_s(Atom::Feed::Entry::Source::Author)
- assert_atom_person_to_s(Atom::Entry::Source::Author)
- end
-
- def test_atom_category
- assert_atom_category_to_s(Atom::Feed::Category)
- assert_atom_category_to_s(Atom::Feed::Entry::Category)
- assert_atom_category_to_s(Atom::Entry::Category)
- assert_atom_category_to_s(Atom::Feed::Entry::Source::Category)
- assert_atom_category_to_s(Atom::Entry::Source::Category)
- end
-
- def test_atom_contributor
- assert_atom_person_to_s(Atom::Feed::Contributor)
- assert_atom_person_to_s(Atom::Feed::Entry::Contributor)
- assert_atom_person_to_s(Atom::Entry::Contributor)
- assert_atom_person_to_s(Atom::Feed::Entry::Source::Contributor)
- assert_atom_person_to_s(Atom::Entry::Source::Contributor)
- end
-
- def test_atom_generator
- assert_atom_generator_to_s(Atom::Feed::Generator)
- assert_atom_generator_to_s(Atom::Feed::Entry::Source::Generator)
- assert_atom_generator_to_s(Atom::Entry::Source::Generator)
- end
-
- def test_atom_icon
- assert_atom_icon_to_s(Atom::Feed::Icon)
- assert_atom_icon_to_s(Atom::Feed::Entry::Source::Icon)
- assert_atom_icon_to_s(Atom::Entry::Source::Icon)
- end
-
- def test_atom_id
- assert_atom_id_to_s(Atom::Feed::Id)
- assert_atom_id_to_s(Atom::Feed::Entry::Id)
- assert_atom_id_to_s(Atom::Entry::Id)
- assert_atom_id_to_s(Atom::Feed::Entry::Source::Id)
- assert_atom_id_to_s(Atom::Entry::Source::Id)
- end
-
- def test_atom_link
- assert_atom_link_to_s(Atom::Feed::Link)
- assert_atom_link_to_s(Atom::Feed::Entry::Link)
- assert_atom_link_to_s(Atom::Entry::Link)
- assert_atom_link_to_s(Atom::Feed::Entry::Source::Link)
- assert_atom_link_to_s(Atom::Entry::Source::Link)
- end
-
- def test_atom_logo
- assert_atom_logo_to_s(Atom::Feed::Logo)
- assert_atom_logo_to_s(Atom::Feed::Entry::Source::Logo)
- assert_atom_logo_to_s(Atom::Entry::Source::Logo)
- end
-
- def test_atom_rights
- assert_atom_text_construct_to_s(Atom::Feed::Rights)
- assert_atom_text_construct_to_s(Atom::Feed::Entry::Rights)
- assert_atom_text_construct_to_s(Atom::Entry::Rights)
- assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Rights)
- assert_atom_text_construct_to_s(Atom::Entry::Source::Rights)
- end
-
- def test_atom_subtitle
- assert_atom_text_construct_to_s(Atom::Feed::Subtitle)
- assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Subtitle)
- assert_atom_text_construct_to_s(Atom::Entry::Source::Subtitle)
- end
-
- def test_atom_title
- assert_atom_text_construct_to_s(Atom::Feed::Title)
- assert_atom_text_construct_to_s(Atom::Feed::Entry::Title)
- assert_atom_text_construct_to_s(Atom::Entry::Title)
- assert_atom_text_construct_to_s(Atom::Feed::Entry::Source::Title)
- assert_atom_text_construct_to_s(Atom::Entry::Source::Title)
- end
-
- def test_atom_updated
- assert_atom_date_construct_to_s(Atom::Feed::Updated)
- assert_atom_date_construct_to_s(Atom::Feed::Entry::Updated)
- assert_atom_date_construct_to_s(Atom::Entry::Updated)
- assert_atom_date_construct_to_s(Atom::Feed::Entry::Source::Updated)
- assert_atom_date_construct_to_s(Atom::Entry::Source::Updated)
- end
-
- def test_atom_content
- assert_atom_content_to_s(Atom::Feed::Entry::Content)
- assert_atom_content_to_s(Atom::Entry::Content)
- end
-
- def test_atom_published
- assert_atom_date_construct_to_s(Atom::Feed::Entry::Published)
- assert_atom_date_construct_to_s(Atom::Entry::Published)
- end
-
- def test_atom_summary
- assert_atom_text_construct_to_s(Atom::Feed::Entry::Summary)
- assert_atom_text_construct_to_s(Atom::Entry::Summary)
- end
-
-
- def test_to_xml(with_convenience_way=true)
- atom = RSS::Parser.parse(make_feed)
- assert_equal(atom.to_s, atom.to_xml)
- assert_equal(atom.to_s, atom.to_xml("atom"))
- assert_equal(atom.to_s, atom.to_xml("atom1.0"))
- assert_equal(atom.to_s, atom.to_xml("atom1.0:feed"))
- assert_equal(atom.to_s, atom.to_xml("atom:feed"))
-
- rss09_xml = atom.to_xml("0.91") do |maker|
- maker.channel.language = "en-us"
- maker.channel.link = "http://example.com/"
- if with_convenience_way
- maker.channel.description = atom.title.content
- else
- maker.channel.description {|d| d.content = atom.title.content}
- end
-
- maker.image.url = "http://example.com/logo.png"
- maker.image.title = "Logo"
- end
- rss09 = RSS::Parser.parse(rss09_xml)
- assert_equal(["rss", "0.91", nil], rss09.feed_info)
-
- rss20_xml = atom.to_xml("2.0") do |maker|
- maker.channel.link = "http://example.com/"
- if with_convenience_way
- maker.channel.description = atom.title.content
- else
- maker.channel.description {|d| d.content = atom.title.content}
- end
- end
- rss20 = RSS::Parser.parse(rss20_xml)
- assert_equal("2.0", rss20.rss_version)
- assert_equal(["rss", "2.0", nil], rss20.feed_info)
- end
-
- def test_to_xml_with_new_api_since_018
- test_to_xml(false)
- end
-
- private
- def setup_entry(entry)
- _wrap_assertion do
- assert_equal("", entry.to_s)
-
- author = entry.class::Author.new
- name = entry.class::Author::Name.new
- name.content = "an author"
- author.name = name
- assert_not_equal("", author.to_s)
- entry.authors << author
- assert_equal("", entry.to_s)
-
- id = entry.class::Id.new
- id.content = "http://example.com/atom.xml"
- assert_not_equal("", id.to_s)
- entry.id = id
- assert_equal("", entry.to_s)
-
- title = entry.class::Title.new
- title.content = "a title"
- assert_not_equal("", title.to_s)
- entry.title = title
- assert_equal("", entry.to_s)
-
- updated = entry.class::Updated.new
- updated.content = Time.now
- assert_not_equal("", updated.to_s)
- entry.updated = updated
- assert_not_equal("", entry.to_s)
- end
- end
-
-
- def assert_atom_person_to_s(target_class)
- _wrap_assertion do
- name = "A person"
- uri = "http://example.com/person/"
- email = "person@example.com"
-
- target = target_class.new
- assert_equal("", target.to_s)
-
- target = target_class.new
- person_name = target_class::Name.new
- person_name.content = name
- target.name = person_name
- xml_target = REXML::Document.new(target.to_s).root
- assert_equal(["name"], xml_target.elements.collect {|e| e.name})
- assert_equal([name], xml_target.elements.collect {|e| e.text})
-
- person_uri = target_class::Uri.new
- person_uri.content = uri
- target.uri = person_uri
- xml_target = REXML::Document.new(target.to_s).root
- assert_equal(["name", "uri"], xml_target.elements.collect {|e| e.name})
- assert_equal([name, uri], xml_target.elements.collect {|e| e.text})
-
- person_email = target_class::Email.new
- person_email.content = email
- target.email = person_email
- xml_target = REXML::Document.new(target.to_s).root
- assert_equal(["name", "uri", "email"],
- xml_target.elements.collect {|e| e.name})
- assert_equal([name, uri, email],
- xml_target.elements.collect {|e| e.text})
- end
- end
-
- def assert_atom_category_to_s(target_class)
- _wrap_assertion do
- term = "music"
- scheme = "http://example.com/music"
- label = "Music"
-
- category = target_class.new
- assert_equal("", category.to_s)
-
- category = target_class.new
- category.scheme = scheme
- assert_equal("", category.to_s)
-
- category = target_class.new
- category.label = label
- assert_equal("", category.to_s)
-
- category = target_class.new
- category.scheme = scheme
- category.label = label
- assert_equal("", category.to_s)
-
- category = target_class.new
- category.term = term
- xml = REXML::Document.new(category.to_s).root
- assert_rexml_element([], {"term" => term}, nil, xml)
-
- category = target_class.new
- category.term = term
- category.scheme = scheme
- xml = REXML::Document.new(category.to_s).root
- assert_rexml_element([], {"term" => term, "scheme" => scheme}, nil, xml)
-
- category = target_class.new
- category.term = term
- category.label = label
- xml = REXML::Document.new(category.to_s).root
- assert_rexml_element([], {"term" => term, "label" => label}, nil, xml)
-
- category = target_class.new
- category.term = term
- category.scheme = scheme
- category.label = label
- xml = REXML::Document.new(category.to_s).root
- attrs = {"term" => term, "scheme" => scheme, "label" => label}
- assert_rexml_element([], attrs, nil, xml)
- end
- end
-
- def assert_atom_generator_to_s(target_class)
- _wrap_assertion do
- content = "Feed generator"
- uri = "http://example.com/generator"
- version = "0.0.1"
-
- generator = target_class.new
- assert_equal("", generator.to_s)
-
- generator = target_class.new
- generator.uri = uri
- assert_equal("", generator.to_s)
-
- generator = target_class.new
- generator.version = version
- assert_equal("", generator.to_s)
-
- generator = target_class.new
- generator.uri = uri
- generator.version = version
- assert_equal("", generator.to_s)
-
- generator = target_class.new
- generator.content = content
- xml = REXML::Document.new(generator.to_s).root
- assert_rexml_element([], {}, content, xml)
-
- generator = target_class.new
- generator.content = content
- generator.uri = uri
- xml = REXML::Document.new(generator.to_s).root
- assert_rexml_element([], {"uri" => uri}, content, xml)
-
- generator = target_class.new
- generator.content = content
- generator.version = version
- xml = REXML::Document.new(generator.to_s).root
- assert_rexml_element([], {"version" => version}, content, xml)
-
- generator = target_class.new
- generator.content = content
- generator.uri = uri
- generator.version = version
- xml = REXML::Document.new(generator.to_s).root
- assert_rexml_element([], {"uri" => uri, "version" => version},
- content, xml)
- end
- end
-
- def assert_atom_icon_to_s(target_class)
- _wrap_assertion do
- content = "http://example.com/icon.png"
-
- icon = target_class.new
- assert_equal("", icon.to_s)
-
- icon = target_class.new
- icon.content = content
- xml = REXML::Document.new(icon.to_s).root
- assert_rexml_element([], {}, content, xml)
- end
- end
-
- def assert_atom_id_to_s(target_class)
- _wrap_assertion do
- content = "http://example.com/1"
-
- id = target_class.new
- assert_equal("", id.to_s)
-
- id = target_class.new
- id.content = content
- xml = REXML::Document.new(id.to_s).root
- assert_rexml_element([], {}, content, xml)
- end
- end
-
- def assert_atom_link_to_s(target_class)
- _wrap_assertion do
- href = "http://example.com/atom.xml"
- optvs = {
- 'rel' => "self",
- 'type' => "application/atom+xml",
- 'hreflang' => "ja",
- 'title' => "Atom Feed",
- 'length' => "801",
- }
-
- link = target_class.new
- assert_equal("", link.to_s)
-
- link = target_class.new
- link.href = href
- xml = REXML::Document.new(link.to_s).root
- assert_rexml_element([], {"href" => href}, nil, xml)
-
- optional_arguments = %w(rel type hreflang title length)
- optional_arguments.each do |name|
- rest = optional_arguments.reject {|x| x == name}
-
- link = target_class.new
- link.__send__("#{name}=", optvs[name])
- assert_equal("", link.to_s)
-
- rest.each do |n|
- link.__send__("#{n}=", optvs[n])
- assert_equal("", link.to_s)
- end
-
- link = target_class.new
- link.href = href
- link.__send__("#{name}=", optvs[name])
- attrs = [["href", href], [name, optvs[name]]]
- xml = REXML::Document.new(link.to_s).root
- assert_rexml_element([], attrs, nil, xml)
-
- rest.each do |n|
- link.__send__("#{n}=", optvs[n])
- attrs << [n, optvs[n]]
- xml = REXML::Document.new(link.to_s).root
- assert_rexml_element([], attrs, nil, xml)
- end
- end
- end
- end
-
- def assert_atom_logo_to_s(target_class)
- _wrap_assertion do
- content = "http://example.com/logo.png"
-
- logo = target_class.new
- assert_equal("", logo.to_s)
-
- logo = target_class.new
- logo.content = content
- xml = REXML::Document.new(logo.to_s).root
- assert_rexml_element([], {}, content, xml)
- end
- end
-
- def assert_atom_text_construct_to_s(target_class)
- _wrap_assertion do
- text_content = "plain text"
- html_content = "<em>#{text_content}</em>"
- xhtml_uri = "http://www.w3.org/1999/xhtml"
- xhtml_em = RSS::XML::Element.new("em", nil, xhtml_uri, {}, text_content)
- xhtml_content = RSS::XML::Element.new("div", nil, xhtml_uri,
- {"xmlns" => xhtml_uri},
- [xhtml_em])
-
- text = target_class.new
- assert_equal("", text.to_s)
-
- text = target_class.new
- text.type = "text"
- assert_equal("", text.to_s)
-
- text = target_class.new
- text.content = text_content
- xml = REXML::Document.new(text.to_s).root
- assert_rexml_element([], {}, text_content, xml)
-
- text = target_class.new
- text.type = "text"
- text.content = text_content
- xml = REXML::Document.new(text.to_s).root
- assert_rexml_element([], {"type" => "text"}, text_content, xml)
-
- text = target_class.new
- text.type = "html"
- text.content = html_content
- xml = REXML::Document.new(text.to_s).root
- assert_rexml_element([], {"type" => "html"}, html_content, xml)
-
- text = target_class.new
- text.type = "xhtml"
- text.content = xhtml_content
- assert_equal("", text.to_s)
-
- text = target_class.new
- text.type = "xhtml"
- text.__send__(target_class.xml_setter, xhtml_content)
- xml = REXML::Document.new(text.to_s).root
- assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"},
- nil, xml)
- assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1])
- assert_rexml_element([], {}, text_content, xml.elements[1].elements[1])
-
- text = target_class.new
- text.type = "xhtml"
- text.__send__(target_class.xml_setter, xhtml_em)
- xml = REXML::Document.new(text.to_s).root
- assert_rexml_element([[xhtml_uri, "div"]], {"type" => "xhtml"},
- nil, xml)
- assert_rexml_element([[xhtml_uri, "em"]], nil, nil, xml.elements[1])
- assert_rexml_element([], {}, text_content, xml.elements[1].elements[1])
- end
- end
-
- def assert_atom_date_construct_to_s(target_class)
- _wrap_assertion do
- date = target_class.new
- assert_equal("", date.to_s)
-
- [
- "2003-12-13T18:30:02Z",
- "2003-12-13T18:30:02.25Z",
- "2003-12-13T18:30:02+01:00",
- "2003-12-13T18:30:02.25+01:00",
- ].each do |content|
- date = target_class.new
- date.content = content
- xml = REXML::Document.new(date.to_s).root
- assert_rexml_element([], {}, content, xml, :time)
-
- date = target_class.new
- date.content = Time.parse(content)
- xml = REXML::Document.new(date.to_s).root
- assert_rexml_element([], {}, content, xml, :time)
- end
- end
- end
-
- def assert_atom_content_to_s(target_class)
- _wrap_assertion do
- assert_atom_text_construct_to_s(target_class)
- assert_atom_content_inline_other_xml_to_s(target_class)
- assert_atom_content_inline_other_text_to_s(target_class)
- assert_atom_content_inline_other_base64_to_s(target_class)
- assert_atom_content_out_of_line_to_s(target_class)
- end
- end
-
- def assert_atom_content_inline_other_xml_to_s(target_class)
- _wrap_assertion do
- content = target_class.new
- content.type = "text/xml"
- assert_equal("", content.to_s)
-
- content = target_class.new
- content.type = "text/xml"
- content.xml = RSS::XML::Element.new("em")
- xml = REXML::Document.new(content.to_s).root
- assert_rexml_element([["", "em"]], {"type" => "text/xml"}, nil, xml)
- end
- end
-
- def assert_atom_content_inline_other_text_to_s(target_class)
- _wrap_assertion do
- content = target_class.new
- content.type = "text/plain"
- assert_equal("", content.to_s)
-
- content = target_class.new
- content.type = "text/plain"
- content.xml = RSS::XML::Element.new("em")
- assert_equal("", content.to_s)
-
- content = target_class.new
- content.type = "text/plain"
- content.content = "content"
- xml = REXML::Document.new(content.to_s).root
- assert_rexml_element([], {"type" => "text/plain"}, "content", xml)
- end
- end
-
- def assert_atom_content_inline_other_base64_to_s(target_class)
- _wrap_assertion do
- type = "image/png"
- png_file = File.join(File.dirname(__FILE__), "dot.png")
- original_content = File.open(png_file, "rb") do |file|
- file.read.force_encoding("binary")
- end
-
- content = target_class.new
- content.type = type
- content.content = original_content
- xml = REXML::Document.new(content.to_s).root
- assert_rexml_element([], {"type" => type},
- [original_content].pack("m").delete("\n"),
- xml)
- end
- end
-
- def assert_atom_content_out_of_line_to_s(target_class)
- _wrap_assertion do
- type = "application/zip"
- src = "http://example.com/xxx.zip"
-
- content = target_class.new
- assert(!content.out_of_line?)
- content.src = src
- assert(content.out_of_line?)
- xml = REXML::Document.new(content.to_s).root
- assert_rexml_element([], {"src" => src}, nil, xml)
-
- content = target_class.new
- assert(!content.out_of_line?)
- content.type = type
- assert(!content.out_of_line?)
- content.src = src
- assert(content.out_of_line?)
- xml = REXML::Document.new(content.to_s).root
- assert_rexml_element([], {"type" => type, "src" => src}, nil, xml)
- end
- end
- end
-end
diff --git a/test/rss/test_content.rb b/test/rss/test_content.rb
deleted file mode 100644
index fc8269df12..0000000000
--- a/test/rss/test_content.rb
+++ /dev/null
@@ -1,105 +0,0 @@
-# frozen_string_literal: false
-require "cgi"
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/content"
-
-module RSS
- class TestContent < TestCase
- def setup
- @prefix = "content"
- @uri = "http://purl.org/rss/1.0/modules/content/"
-
- @elems = {
- :encoded => "<em>ATTENTION</em>",
- }
-
- @content_nodes = @elems.collect do |name, value|
- "<#{@prefix}:#{name}>#{CGI.escapeHTML(value.to_s)}</#{@prefix}:#{name}>"
- end.join("\n")
-
- @rss10_source = make_RDF(<<-EOR, {@prefix => @uri})
-#{make_channel()}
-#{make_image()}
-#{make_item(@content_nodes)}
-#{make_textinput()}
-EOR
-
- @rss10 = Parser.parse(@rss10_source)
-
-
- @rss20_source = make_rss20(<<-EOR, {@prefix => @uri})
-#{make_channel20(make_item20(@content_nodes))}
-EOR
-
- @rss20 = Parser.parse(@rss20_source)
- end
-
- def test_parser
- assert_nothing_raised do
- Parser.parse(@rss10_source)
- end
-
- assert_nothing_raised do
- Parser.parse(@rss20_source)
- end
-
- @elems.each do |tag, value|
- tag_name = "#{@prefix}:#{tag}"
- content_encodes = make_element(tag_name, {}, value) * 2
-
- assert_too_much_tag(tag.to_s, "item") do
- Parser.parse(make_RDF(<<-EOR, {@prefix => @uri}))
-#{make_channel}
-#{make_item(content_encodes)}
-EOR
- end
-
- assert_too_much_tag(tag.to_s, "item") do
- Parser.parse(make_rss20(<<-EOR, {@prefix => @uri}))
-#{make_channel20(make_item20(content_encodes))}
-EOR
- end
- end
- end
-
- def test_accessor
- new_value = {
- :encoded => "<![CDATA[<it>hoge</it>]]>",
- }
-
- @elems.each do |name, value|
- [@rss10, @rss20].each do |rss|
- meth = "#{RSS::CONTENT_PREFIX}_#{name}"
- parent = rss.items.last
- assert_equal(value, parent.__send__(meth))
- parent.__send__("#{meth}=", new_value[name].to_s)
- assert_equal(new_value[name], parent.__send__(meth))
- end
- end
- end
-
- def test_to_s
- @elems.each do |name, value|
- excepted = make_element("#{@prefix}:#{name}", {}, value)
- meth = "#{RSS::CONTENT_PREFIX}_#{name}_element"
- [@rss10, @rss20].each do |rss|
- assert_equal(excepted, rss.items.last.__send__(meth))
- end
- end
-
- [@rss10_source, @rss20_source].each do |source|
- REXML::Document.new(source).root.each_element do |parent|
- next unless parent.name != "item"
- parent.each_element do |elem|
- if elem.namespace == @uri
- assert_equal(elem.text, @elems[elem.name.intern].to_s)
- end
- end
- end
- end
- end
- end
-end
diff --git a/test/rss/test_dublincore.rb b/test/rss/test_dublincore.rb
deleted file mode 100644
index 37ef177199..0000000000
--- a/test/rss/test_dublincore.rb
+++ /dev/null
@@ -1,270 +0,0 @@
-# frozen_string_literal: false
-require "cgi"
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/dublincore"
-
-module RSS
- class TestDublinCore < TestCase
- def setup
- @rss10_parents = [%w(channel), %w(image), %w(item), %w(textinput)]
-
- @rss10_source = make_RDF(<<-EOR, {DC_PREFIX => DC_URI})
-#{make_channel(DC_NODES)}
-#{make_image(DC_NODES)}
-#{make_item(DC_NODES)}
-#{make_textinput(DC_NODES)}
-EOR
-
- @rss20_parents = [%w(channel), %w(items last)]
-
- @rss20_source = make_rss20(<<-EOR, {DC_PREFIX => DC_URI})
-#{make_channel20(DC_NODES + make_item20(DC_NODES))}
-EOR
-
- @atom_feed_parents = [[], %w(entries last)]
-
- @atom_feed_source = make_feed(<<-EOR, {DC_PREFIX => DC_URI})
-#{DC_NODES}
-#{make_entry(DC_NODES)}
-EOR
-
- @atom_entry_parents = [[]]
-
- @atom_entry_source = make_entry_document(<<-EOR, {DC_PREFIX => DC_URI})
-#{DC_NODES}
-EOR
- end
-
- def test_parser
- rss10_maker = Proc.new do |content, xmlns|
- make_RDF(<<-EOR, xmlns)
-#{make_channel(content)}
-#{make_image(content)}
-#{make_item(content)}
-#{make_textinput(content)}
-EOR
- end
- assert_dc_parse(@rss10_source, @rss10_parents, false, &rss10_maker)
- assert_dc_parse(@rss10_source, @rss10_parents, true, &rss10_maker)
-
- rss20_maker = Proc.new do |content, xmlns|
- make_rss20(<<-EOR, xmlns)
-#{make_channel20(content + make_item20(content))}
-EOR
- end
- assert_dc_parse(@rss20_source, @rss20_parents, false, &rss20_maker)
- assert_dc_parse(@rss20_source, @rss20_parents, true, &rss20_maker)
-
- atom_feed_maker = Proc.new do |content, xmlns|
- make_feed(<<-EOR, xmlns)
-#{content}
-#{make_entry(content)}
-EOR
- end
- assert_dc_parse(@atom_feed_source, @atom_feed_parents, false,
- &atom_feed_maker)
- assert_dc_parse(@atom_feed_source, @atom_feed_parents, true,
- &atom_feed_maker)
-
- atom_entry_maker = Proc.new do |content, xmlns|
- make_entry_document(<<-EOR, xmlns)
-#{content}
-EOR
- end
- assert_dc_parse(@atom_entry_source, @atom_entry_parents, false,
- &atom_entry_maker)
- assert_dc_parse(@atom_entry_source, @atom_entry_parents, true,
- &atom_entry_maker)
- end
-
- def test_singular_accessor
- assert_dc_singular_accessor(@rss10_source, @rss10_parents)
- assert_dc_singular_accessor(@rss20_source, @rss20_parents)
- assert_dc_singular_accessor(@atom_feed_source, @atom_feed_parents)
- assert_dc_singular_accessor(@atom_entry_source, @atom_entry_parents)
- end
-
- def test_plural_accessor
- assert_dc_plural_accessor(@rss10_source, @rss10_parents, false)
- assert_dc_plural_accessor(@rss10_source, @rss10_parents, true)
-
- assert_dc_plural_accessor(@rss20_source, @rss20_parents, false)
- assert_dc_plural_accessor(@rss20_source, @rss20_parents, true)
-
- assert_dc_plural_accessor(@atom_feed_source, @atom_feed_parents, false)
- assert_dc_plural_accessor(@atom_feed_source, @atom_feed_parents, true)
-
- assert_dc_plural_accessor(@atom_entry_source, @atom_entry_parents, false)
- assert_dc_plural_accessor(@atom_entry_source, @atom_entry_parents, true)
- end
-
- def test_to_s
- assert_dc_to_s(@rss10_source, @rss10_parents, false)
- assert_dc_to_s(@rss10_source, @rss10_parents, true)
-
- targets = ["channel", "channel/item[3]"]
- assert_dc_to_s(@rss20_source, @rss20_parents, false, targets)
- assert_dc_to_s(@rss20_source, @rss20_parents, true, targets)
-
- targets = [".", "entry"]
- assert_dc_to_s(@atom_feed_source, @atom_feed_parents, false, targets)
- assert_dc_to_s(@atom_feed_source, @atom_feed_parents, true, targets)
-
- targets = ["."]
- assert_dc_to_s(@atom_entry_source, @atom_entry_parents, false, targets)
- assert_dc_to_s(@atom_entry_source, @atom_entry_parents, true, targets)
- end
-
- private
- def dc_plural_suffix(name, check_backward_compatibility)
- if name == :rights
- if check_backward_compatibility
- "es"
- else
- "_list"
- end
- else
- "s"
- end
- end
-
- def assert_dc_parse(source, parents, check_backward_compatibility, &maker)
- assert_nothing_raised do
- Parser.parse(source)
- end
-
- DC_ELEMENTS.each do |name, value|
- parents.each do |parent_readers|
- feed = nil
- assert_nothing_raised do
- tag = "#{DC_PREFIX}:#{name}"
- dc_content = "<#{tag}>#{value}</#{tag}>\n"
- dc_content *= 2
- feed = Parser.parse(maker.call(dc_content, {DC_PREFIX => DC_URI}))
- end
- parent = chain_reader(feed, parent_readers)
-
- plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
- plural_reader = "dc_#{name}#{plural_suffix}"
- values = parent.__send__(plural_reader).collect(&:value)
- value = CGI.unescapeHTML(value) if value.kind_of?(String)
- assert_equal([value, value], values)
- end
- end
- end
-
- def assert_dc_singular_accessor(source, parents)
- feed = Parser.parse(source)
- new_value = "hoge"
-
- parents.each do |parent_readers|
- parent = chain_reader(feed, parent_readers)
- DC_ELEMENTS.each do |name, value|
- parsed_value = parent.__send__("dc_#{name}")
- value = CGI.unescapeHTML(value) if value.kind_of?(String)
- assert_equal(value, parsed_value)
- if name == :date
- t = Time.iso8601("2003-01-01T02:30:23+09:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
- parent.__send__("dc_#{name}=", t.iso8601)
- assert_equal(t, parent.__send__("dc_#{name}"))
- if parent.class.method_defined?(:date_without_dc_date=)
- assert_nil(parent.date)
- else
- assert_equal(t, parent.date)
- end
-
- parent.date = value
- assert_equal(value, parent.date)
- assert_equal(value, parent.__send__("dc_#{name}"))
- else
- parent.__send__("dc_#{name}=", new_value)
- assert_equal(new_value, parent.__send__("dc_#{name}"))
- end
- end
- end
- end
-
- def assert_dc_plural_accessor(source, parents, check_backward_compatibility)
- feed = Parser.parse(source)
- new_value = "hoge"
-
- DC_ELEMENTS.each do |name, value|
- parents.each do |parent_readers|
- parent = chain_reader(feed, parent_readers)
- parsed_value = parent.__send__("dc_#{name}")
- value = CGI.unescapeHTML(value) if value.kind_of?(String)
- assert_equal(value, parsed_value)
-
- plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
- plural_reader = "dc_#{name}#{plural_suffix}"
- klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}"
- klass = DublinCoreModel.const_get(klass_name)
- if name == :date
- t = Time.iso8601("2003-01-01T02:30:23+09:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
- elems = parent.__send__(plural_reader)
- elems << klass.new(t.iso8601)
- new_elems = parent.__send__(plural_reader)
- values = new_elems.collect{|x| x.value}
- assert_equal([parent.__send__("dc_#{name}"), t], values)
- else
- elems = parent.__send__(plural_reader)
- elems << klass.new(new_value)
- new_elems = parent.__send__(plural_reader)
- values = new_elems.collect{|x| x.value}
- assert_equal([parent.__send__("dc_#{name}"), new_value],
- values)
- end
- end
- end
- end
-
- def assert_dc_to_s(source, parents, check_backward_compatibility,
- targets=nil)
- feed = Parser.parse(source)
-
- DC_ELEMENTS.each do |name, value|
- excepted = "<#{DC_PREFIX}:#{name}>#{value}</#{DC_PREFIX}:#{name}>"
- parents.each do |parent_readers|
- parent = chain_reader(feed, parent_readers)
- assert_equal(excepted, parent.__send__("dc_#{name}_elements"))
- end
-
- plural_suffix = dc_plural_suffix(name, check_backward_compatibility)
- reader = "dc_#{name}#{plural_suffix}"
- excepted = Array.new(2, excepted).join("\n")
- parents.each do |parent_readers|
- parent = chain_reader(feed, parent_readers)
- elems = parent.__send__(reader)
- klass_name = "DublinCore#{Utils.to_class_name(name.to_s)}"
- klass = DublinCoreModel.const_get(klass_name)
- elems << klass.new(parent.__send__("dc_#{name}"))
- assert_equal(excepted, parent.__send__("dc_#{name}_elements"))
- end
- end
-
- targets ||= parents.collect do |parent_readers|
- parent_readers.first
- end
- feed_root = REXML::Document.new(source).root
- targets.each do |target_xpath|
- parent = feed_root.elements[target_xpath]
- parent.each_element do |elem|
- if elem.namespace == DC_URI
- assert_equal(elem.text,
- CGI.unescapeHTML(DC_ELEMENTS[elem.name.intern].to_s))
- end
- end
- end
- end
- end
-end
diff --git a/test/rss/test_image.rb b/test/rss/test_image.rb
deleted file mode 100644
index 0f1cd8c9e2..0000000000
--- a/test/rss/test_image.rb
+++ /dev/null
@@ -1,215 +0,0 @@
-# frozen_string_literal: false
-require "cgi"
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/image"
-
-module RSS
- class TestImage < TestCase
-
- def setup
- @prefix = "image"
- @uri = "http://purl.org/rss/1.0/modules/image/"
-
- @favicon_attrs = {
- "rdf:about" => "http://www.kuro5hin.org/favicon.ico",
- "#{@prefix}:size" => "small",
- }
- @favicon_contents = {"dc:title" => "Kuro5hin",}
- @items = [
- [
- {
- "rdf:about" => "http://www.example.org/item.png",
- "rdf:resource" => "http://www.example.org/item",
- },
- {
- "dc:title" => "Example Image",
- "#{@prefix}:width" => "100",
- "#{@prefix}:height" => "65",
- },
- ],
- [
- {
- "rdf:about" => "http://www.kuro5hin.org/images/topics/culture.jpg",
- },
- {
- "dc:title" => "Culture",
- "#{@prefix}:width" => "80",
- "#{@prefix}:height" => "50",
- },
- ]
- ]
-
-
- @channel_nodes = make_element("#{@prefix}:favicon",
- @favicon_attrs,
- @favicon_contents)
- items = ""
- @items.each do |attrs, contents|
- image_item = make_element("#{@prefix}:item", attrs, contents)
- items << make_item(image_item)
- end
-
- @ns = {
- @prefix => @uri,
- DC_PREFIX => DC_URI,
- }
- @rss_source = make_RDF(<<-EOR, @ns)
-#{make_channel(@channel_nodes)}
-#{make_image}
-#{items}
-#{make_textinput}
-EOR
-
- @rss = Parser.parse(@rss_source)
- end
-
- def test_parser
- assert_nothing_raised do
- Parser.parse(@rss_source)
- end
-
- assert_too_much_tag("favicon", "channel") do
- Parser.parse(make_RDF(<<-EOR, @ns))
-#{make_channel(@channel_nodes * 2)}
-#{make_item}
-EOR
- end
-
- attrs = {"rdf:about" => "http://www.example.org/item.png"}
- contents = [["#{@prefix}:width", "80"]] * 5
- image_item = make_element("#{@prefix}:item", attrs, contents)
- assert_too_much_tag("width", "item") do
- Parser.parse(make_RDF(<<-EOR, @ns))
-#{make_channel}
-#{make_item(image_item)}
-EOR
- end
- end
-
- def test_favicon_accessor
- favicon = @rss.channel.image_favicon
- [
- %w(about rdf:about http://example.com/favicon.ico),
- %w(size image:size large),
- %w(image_size image:size medium),
- ].each do |name, full_name, new_value|
- assert_equal(@favicon_attrs[full_name], favicon.__send__(name))
- favicon.__send__("#{name}=", new_value)
- assert_equal(new_value, favicon.__send__(name))
- favicon.__send__("#{name}=", @favicon_attrs[full_name])
- assert_equal(@favicon_attrs[full_name], favicon.__send__(name))
- end
-
- %w(small medium large).each do |value|
- assert_nothing_raised do
- favicon.size = value
- favicon.image_size = value
- end
- end
-
- %w(aaa AAA SMALL MEDIUM LARGE).each do |value|
- args = ["#{@prefix}:favicon", value, "#{@prefix}:size"]
- assert_not_available_value(*args) do
- favicon.size = value
- end
- assert_not_available_value(*args) do
- favicon.image_size = value
- end
- end
-
- [
- %w(dc_title dc:title sample-favicon),
- ].each do |name, full_name, new_value|
- assert_equal(@favicon_contents[full_name], favicon.__send__(name))
- favicon.__send__("#{name}=", new_value)
- assert_equal(new_value, favicon.__send__(name))
- favicon.__send__("#{name}=", @favicon_contents[full_name])
- assert_equal(@favicon_contents[full_name], favicon.__send__(name))
- end
- end
-
- def test_item_accessor
- @rss.items.each_with_index do |item, i|
- image_item = item.image_item
- attrs, contents = @items[i]
- [
- %w(about rdf:about http://example.com/image.png),
- %w(resource rdf:resource http://example.com/),
- ].each do |name, full_name, new_value|
- assert_equal(attrs[full_name], image_item.__send__(name))
- image_item.__send__("#{name}=", new_value)
- assert_equal(new_value, image_item.__send__(name))
- image_item.__send__("#{name}=", attrs[full_name])
- assert_equal(attrs[full_name], image_item.__send__(name))
- end
-
- [
- ["width", "image:width", "111"],
- ["image_width", "image:width", "44"],
- ["height", "image:height", "222"],
- ["image_height", "image:height", "88"],
- ].each do |name, full_name, new_value|
- assert_equal(contents[full_name].to_i, image_item.__send__(name))
- image_item.__send__("#{name}=", new_value)
- assert_equal(new_value.to_i, image_item.__send__(name))
- image_item.__send__("#{name}=", contents[full_name])
- assert_equal(contents[full_name].to_i, image_item.__send__(name))
- end
-
- [
- ["dc_title", "dc:title", "sample-image"],
- ].each do |name, full_name, new_value|
- assert_equal(contents[full_name], image_item.__send__(name))
- image_item.__send__("#{name}=", new_value)
- assert_equal(new_value, image_item.__send__(name))
- image_item.__send__("#{name}=", contents[full_name])
- assert_equal(contents[full_name], image_item.__send__(name))
- end
- end
- end
-
- def test_favicon_to_s
- favicon = @rss.channel.image_favicon
- expected_xml = image_xmlns_container(make_element("#{@prefix}:favicon",
- @favicon_attrs,
- @favicon_contents))
- expected = REXML::Document.new(expected_xml)
- actual_xml = image_xmlns_container(favicon.to_s(false, ""))
- actual = REXML::Document.new(actual_xml)
- assert_equal(expected.to_s, actual.to_s)
- end
-
- def test_item_to_s
- @rss.items.each_with_index do |item, i|
- attrs, contents = @items[i]
- expected_xml = make_element("#{@prefix}:item", attrs, contents)
- expected_xml = image_xmlns_container(expected_xml)
- expected = REXML::Document.new(expected_xml)
- actual_xml = image_xmlns_container(item.image_item.to_s(false, ""))
- actual = REXML::Document.new(actual_xml)
-
- assert_equal(expected[0].attributes, actual[0].attributes)
-
- %w(image:height image:width dc:title).each do |name|
- actual_target = actual.elements["//#{name}"]
- expected_target = expected.elements["//#{name}"]
- assert_equal(expected_target.to_s, actual_target.to_s)
- end
- end
- end
-
- private
- def image_xmlns_container(content)
- xmlns_container({
- @prefix => @uri,
- "dc" => "http://purl.org/dc/elements/1.1/",
- "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
- },
- content)
- end
- end
-end
diff --git a/test/rss/test_inherit.rb b/test/rss/test_inherit.rb
deleted file mode 100644
index 020f066c5f..0000000000
--- a/test/rss/test_inherit.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/1.0"
-
-module RSS
- class TestInherit < TestCase
-
- class InheritedImage < RSS::RDF::Image
- def self.indent_size; 1; end
- def self.tag_name; 'image'; end
- end
-
- def setup
- @rss = make_RDF(<<-EOR)
-#{make_channel}
-#{make_image}
-#{make_item}
-#{make_textinput}
-EOR
- end
-
- def test_inherit
- rss = RSS::Parser.parse(@rss)
- orig_image = rss.image
- prefix = "[INHERIT]"
- image = InheritedImage.new("#{prefix} #{orig_image.about}")
- image.title = "#{prefix} #{orig_image.title}"
- image.url = "#{prefix} #{orig_image.url}"
- image.link = "#{prefix} #{orig_image.link}"
- rss.image = image
-
- new_rss = RSS::Parser.parse(rss.to_s)
- new_image = new_rss.image
- assert_equal("#{prefix} #{orig_image.about}", new_image.about)
- assert_equal("#{prefix} #{orig_image.title}", new_image.title)
- assert_equal("#{prefix} #{orig_image.url}", new_image.url)
- assert_equal("#{prefix} #{orig_image.link}", new_image.link)
- end
- end
-end
diff --git a/test/rss/test_itunes.rb b/test/rss/test_itunes.rb
deleted file mode 100644
index 4459d8bfc7..0000000000
--- a/test/rss/test_itunes.rb
+++ /dev/null
@@ -1,356 +0,0 @@
-# frozen_string_literal: false
-require "cgi"
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/2.0"
-require "rss/itunes"
-
-module RSS
- class TestITunes < TestCase
- def test_author
- assert_itunes_author(%w(channel)) do |content, xmlns|
- make_rss20(make_channel20(content), xmlns)
- end
-
- assert_itunes_author(%w(items last)) do |content, xmlns|
- make_rss20(make_channel20(make_item20(content)), xmlns)
- end
- end
-
- def test_block
- assert_itunes_block(%w(items last)) do |content, xmlns|
- make_rss20(make_channel20(make_item20(content)), xmlns)
- end
- end
-
- def test_category
- assert_itunes_category(%w(channel)) do |content, xmlns|
- make_rss20(make_channel20(content), xmlns)
- end
- end
-
- def test_image
- assert_itunes_image(%w(channel)) do |content, xmlns|
- make_rss20(make_channel20(content), xmlns)
- end
- end
-
- def test_duration
- assert_itunes_duration(%w(items last)) do |content, xmlns|
- make_rss20(make_channel20(make_item20(content)), xmlns)
- end
- end
-
- def test_explicit
- assert_itunes_explicit(%w(channel)) do |content, xmlns|
- make_rss20(make_channel20(content), xmlns)
- end
-
- assert_itunes_explicit(%w(items last)) do |content, xmlns|
- make_rss20(make_channel20(make_item20(content)), xmlns)
- end
- end
-
- def test_keywords
- assert_itunes_keywords(%w(channel)) do |content, xmlns|
- make_rss20(make_channel20(content), xmlns)
- end
-
- assert_itunes_keywords(%w(items last)) do |content, xmlns|
- make_rss20(make_channel20(make_item20(content)), xmlns)
- end
- end
-
- def test_new_feed_url
- assert_itunes_new_feed_url(%w(channel)) do |content, xmlns|
- make_rss20(make_channel20(content), xmlns)
- end
- end
-
- def test_owner
- assert_itunes_owner(%w(channel)) do |content, xmlns|
- make_rss20(make_channel20(content), xmlns)
- end
- end
-
- def test_subtitle
- assert_itunes_subtitle(%w(channel)) do |content, xmlns|
- make_rss20(make_channel20(content), xmlns)
- end
-
- assert_itunes_subtitle(%w(items last)) do |content, xmlns|
- make_rss20(make_channel20(make_item20(content)), xmlns)
- end
- end
-
- def test_summary
- assert_itunes_summary(%w(channel)) do |content, xmlns|
- make_rss20(make_channel20(content), xmlns)
- end
-
- assert_itunes_summary(%w(items last)) do |content, xmlns|
- make_rss20(make_channel20(make_item20(content)), xmlns)
- end
- end
-
- private
- def itunes_rss20_parse(content, &maker)
- xmlns = {"itunes" => "http://www.itunes.com/dtds/podcast-1.0.dtd"}
- rss20_xml = maker.call(content, xmlns)
- ::RSS::Parser.parse(rss20_xml)
- end
-
- def assert_itunes_author(readers, &rss20_maker)
- _wrap_assertion do
- author = "John Lennon"
- rss20 = itunes_rss20_parse(tag("itunes:author", author), &rss20_maker)
- target = chain_reader(rss20, readers)
- assert_equal(author, target.itunes_author)
- end
- end
-
- def _assert_itunes_block(value, boolean_value, readers, &rss20_maker)
- rss20 = itunes_rss20_parse(tag("itunes:block", value), &rss20_maker)
- target = chain_reader(rss20, readers)
- assert_equal(value, target.itunes_block)
- assert_equal(boolean_value, target.itunes_block?)
- end
-
- def assert_itunes_block(readers, &rss20_maker)
- _wrap_assertion do
- _assert_itunes_block("yes", true, readers, &rss20_maker)
- _assert_itunes_block("Yes", true, readers, &rss20_maker)
- _assert_itunes_block("no", false, readers, &rss20_maker)
- _assert_itunes_block("", false, readers, &rss20_maker)
- end
- end
-
- def _assert_itunes_category(categories, readers, &rss20_maker)
- cats = categories.collect do |category|
- if category.is_a?(Array)
- category, sub_category = category
- tag("itunes:category",
- tag("itunes:category", nil, {"text" => sub_category}),
- {"text" => category})
- else
- tag("itunes:category", nil, {"text" => category})
- end
- end.join
- rss20 = itunes_rss20_parse(cats, &rss20_maker)
- target = chain_reader(rss20, readers)
- actual_categories = target.itunes_categories.collect do |category|
- cat = category.text
- if category.itunes_categories.empty?
- cat
- else
- [cat, *category.itunes_categories.collect {|c| c.text}]
- end
- end
- assert_equal(categories, actual_categories)
- end
-
- def assert_itunes_category(readers, &rss20_maker)
- _wrap_assertion do
- _assert_itunes_category(["Audio Blogs"], readers, &rss20_maker)
- _assert_itunes_category([["Arts & Entertainment", "Games"]],
- readers, &rss20_maker)
- _assert_itunes_category([["Arts & Entertainment", "Games"],
- ["Technology", "Computers"],
- "Audio Blogs"],
- readers, &rss20_maker)
- end
- end
-
- def assert_itunes_image(readers, &rss20_maker)
- _wrap_assertion do
- url = "http://example.com/podcasts/everything/AllAboutEverything.jpg"
- content = tag("itunes:image", nil, {"href" => url})
- rss20 = itunes_rss20_parse(content, &rss20_maker)
- target = chain_reader(rss20, readers)
- assert_not_nil(target.itunes_image)
- assert_equal(url, target.itunes_image.href)
-
- assert_missing_attribute("image", "href") do
- content = tag("itunes:image")
- itunes_rss20_parse(content, &rss20_maker)
- end
- end
- end
-
- def _assert_itunes_duration(hour, minute, second, value,
- readers, &rss20_maker)
- content = tag("itunes:duration", value)
- rss20 = itunes_rss20_parse(content, &rss20_maker)
- duration = chain_reader(rss20, readers).itunes_duration
- assert_equal(value, duration.content)
- assert_equal(hour, duration.hour)
- assert_equal(minute, duration.minute)
- assert_equal(second, duration.second)
- end
-
- def _assert_itunes_duration_not_available_value(value, &rss20_maker)
- assert_not_available_value("duration", value) do
- content = tag("itunes:duration", value)
- itunes_rss20_parse(content, &rss20_maker)
- end
- end
-
- def assert_itunes_duration(readers, &rss20_maker)
- _wrap_assertion do
- _assert_itunes_duration(7, 14, 5, "07:14:05", readers, &rss20_maker)
- _assert_itunes_duration(7, 14, 5, "7:14:05", readers, &rss20_maker)
- _assert_itunes_duration(0, 4, 55, "04:55", readers, &rss20_maker)
- _assert_itunes_duration(0, 4, 5, "4:05", readers, &rss20_maker)
- _assert_itunes_duration(0, 0, 5, "5", readers, &rss20_maker)
- _assert_itunes_duration(0, 3, 15, "195", readers, &rss20_maker)
- _assert_itunes_duration(1, 0, 1, "3601", readers, &rss20_maker)
-
- _assert_itunes_duration_not_available_value("09:07:14:05", &rss20_maker)
- _assert_itunes_duration_not_available_value("10:5", &rss20_maker)
- _assert_itunes_duration_not_available_value("10:03:5", &rss20_maker)
- _assert_itunes_duration_not_available_value("10:3:05", &rss20_maker)
-
- _assert_itunes_duration_not_available_value("xx:xx:xx", &rss20_maker)
-
- _assert_itunes_duration_not_available_value("", &rss20_maker)
- end
- end
-
- def _assert_itunes_explicit(explicit, value, readers, &rss20_maker)
- content = tag("itunes:explicit", value)
- rss20 = itunes_rss20_parse(content, &rss20_maker)
- target = chain_reader(rss20, readers)
- assert_equal(value, target.itunes_explicit)
- assert_equal(explicit, target.itunes_explicit?)
- end
-
- def assert_itunes_explicit(readers, &rss20_maker)
- _wrap_assertion do
- _assert_itunes_explicit(true, "explicit", readers, &rss20_maker)
- _assert_itunes_explicit(true, "yes", readers, &rss20_maker)
- _assert_itunes_explicit(true, "true", readers, &rss20_maker)
- _assert_itunes_explicit(false, "clean", readers, &rss20_maker)
- _assert_itunes_explicit(false, "no", readers, &rss20_maker)
- _assert_itunes_explicit(false, "false", readers, &rss20_maker)
- _assert_itunes_explicit(nil, "invalid", readers, &rss20_maker)
- end
- end
-
- def _assert_itunes_keywords(keywords, value, readers, &rss20_maker)
- content = tag("itunes:keywords", value)
- rss20 = itunes_rss20_parse(content, &rss20_maker)
- target = chain_reader(rss20, readers)
- assert_equal(keywords, target.itunes_keywords)
- end
-
- def assert_itunes_keywords(readers, &rss20_maker)
- _wrap_assertion do
- _assert_itunes_keywords(["salt"], "salt", readers, &rss20_maker)
- _assert_itunes_keywords(["salt"], " salt ", readers, &rss20_maker)
- _assert_itunes_keywords(["salt", "pepper", "shaker", "exciting"],
- "salt, pepper, shaker, exciting",
- readers, &rss20_maker)
- _assert_itunes_keywords(["metric", "socket", "wrenches", "toolsalt"],
- "metric, socket, wrenches, toolsalt",
- readers, &rss20_maker)
- _assert_itunes_keywords(["olitics", "red", "blue", "state"],
- "olitics, red, blue, state",
- readers, &rss20_maker)
- end
- end
-
- def assert_itunes_new_feed_url(readers, &rss20_maker)
- _wrap_assertion do
- url = "http://newlocation.com/example.rss"
- content = tag("itunes:new-feed-url", url)
- rss20 = itunes_rss20_parse(content, &rss20_maker)
- target = chain_reader(rss20, readers)
- assert_equal(url, target.itunes_new_feed_url)
- end
- end
-
- def _assert_itunes_owner(name, email, readers, &rss20_maker)
- content = tag("itunes:owner",
- tag("itunes:name", name) + tag("itunes:email", email))
- rss20 = itunes_rss20_parse(content, &rss20_maker)
- owner = chain_reader(rss20, readers).itunes_owner
- assert_equal(name, owner.itunes_name)
- assert_equal(email, owner.itunes_email)
- end
-
- def assert_itunes_owner(readers, &rss20_maker)
- _wrap_assertion do
- _assert_itunes_owner("John Doe", "john.doe@example.com",
- readers, &rss20_maker)
-
- assert_missing_tag("name", "owner") do
- content = tag("itunes:owner")
- itunes_rss20_parse(content, &rss20_maker)
- end
-
- assert_missing_tag("name", "owner") do
- content = tag("itunes:owner",
- tag("itunes:email", "john.doe@example.com"))
- itunes_rss20_parse(content, &rss20_maker)
- end
-
- assert_missing_tag("email", "owner") do
- content = tag("itunes:owner", tag("itunes:name", "John Doe"))
- itunes_rss20_parse(content, &rss20_maker)
- end
- end
- end
-
- def _assert_itunes_subtitle(value, readers, &rss20_maker)
- content = tag("itunes:subtitle", value)
- rss20 = itunes_rss20_parse(content, &rss20_maker)
- target = chain_reader(rss20, readers)
- assert_equal(value, target.itunes_subtitle)
- end
-
- def assert_itunes_subtitle(readers, &rss20_maker)
- _wrap_assertion do
- _assert_itunes_subtitle("A show about everything", readers, &rss20_maker)
- _assert_itunes_subtitle("A short primer on table spices",
- readers, &rss20_maker)
- _assert_itunes_subtitle("Comparing socket wrenches is fun!",
- readers, &rss20_maker)
- _assert_itunes_subtitle("Red + Blue != Purple", readers, &rss20_maker)
- end
- end
-
- def _assert_itunes_summary(value, readers, &rss20_maker)
- content = tag("itunes:summary", value)
- rss20 = itunes_rss20_parse(content, &rss20_maker)
- target = chain_reader(rss20, readers)
- assert_equal(value, target.itunes_summary)
- end
-
- def assert_itunes_summary(readers, &rss20_maker)
- _wrap_assertion do
- _assert_itunes_summary("All About Everything is a show about " +
- "everything. Each week we dive into any " +
- "subject known to man and talk about it as " +
- "much as we can. Look for our Podcast in " +
- "the iTunes Music Store",
- readers, &rss20_maker)
- _assert_itunes_summary("This week we talk about salt and pepper " +
- "shakers, comparing and contrasting pour " +
- "rates, construction materials, and overall " +
- "aesthetics. Come and join the party!",
- readers, &rss20_maker)
- _assert_itunes_summary("This week we talk about metric vs. old " +
- "english socket wrenches. Which one is " +
- "better? Do you really need both? Get all " +
- "of your answers here.",
- readers, &rss20_maker)
- _assert_itunes_summary("This week we talk about surviving in a " +
- "Red state if you're a Blue person. Or " +
- "vice versa.",
- readers, &rss20_maker)
- end
- end
- end
-end
diff --git a/test/rss/test_maker_0.9.rb b/test/rss/test_maker_0.9.rb
deleted file mode 100644
index d07a724ab1..0000000000
--- a/test/rss/test_maker_0.9.rb
+++ /dev/null
@@ -1,477 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMaker09 < TestCase
- def test_supported?
- assert(RSS::Maker.supported?("0.9"))
- assert(RSS::Maker.supported?("rss0.9"))
- assert(RSS::Maker.supported?("0.91"))
- assert(RSS::Maker.supported?("rss0.91"))
- assert(RSS::Maker.supported?("0.92"))
- assert(RSS::Maker.supported?("rss0.92"))
- assert(!RSS::Maker.supported?("0.93"))
- assert(!RSS::Maker.supported?("rss0.93"))
- end
-
- def test_find_class
- assert_equal(RSS::Maker::RSS091, RSS::Maker["0.91"])
- assert_equal(RSS::Maker::RSS091, RSS::Maker["rss0.91"])
- assert_equal(RSS::Maker::RSS092, RSS::Maker["0.9"])
- assert_equal(RSS::Maker::RSS092, RSS::Maker["0.92"])
- assert_equal(RSS::Maker::RSS092, RSS::Maker["rss0.92"])
- end
-
- def test_rss
- assert_raise(LocalJumpError) do
- RSS::Maker.make("0.91")
- end
-
- rss = RSS::Maker.make("0.9") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
- end
- assert_equal("0.92", rss.rss_version)
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
- end
- assert_equal("0.91", rss.rss_version)
-
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- maker.encoding = "EUC-JP"
- end
- assert_equal("0.91", rss.rss_version)
- assert_equal("EUC-JP", rss.encoding)
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- maker.standalone = "yes"
- end
- assert_equal("0.91", rss.rss_version)
- assert_equal("yes", rss.standalone)
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- maker.encoding = "EUC-JP"
- maker.standalone = "yes"
- end
- assert_equal("0.91", rss.rss_version)
- assert_equal("EUC-JP", rss.encoding)
- assert_equal("yes", rss.standalone)
- end
-
- def test_channel
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
- language = "ja"
- copyright = "foo"
- managingEditor = "bar"
- webMaster = "web master"
- rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))'
- docs = "http://foo.com/doc"
- skipDays = [
- "Sunday",
- "Monday",
- ]
- skipHours = [
- "0",
- "13",
- ]
- pubDate = Time.now
- lastBuildDate = Time.now
-
- image_url = "http://example.com/logo.png"
- image_title = "Logo"
-
- rss = RSS::Maker.make("0.91") do |maker|
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- maker.channel.language = language
- maker.channel.copyright = copyright
- maker.channel.managingEditor = managingEditor
- maker.channel.webMaster = webMaster
- maker.channel.rating = rating
- maker.channel.docs = docs
- maker.channel.pubDate = pubDate
- maker.channel.lastBuildDate = lastBuildDate
-
- skipDays.each do |day|
- maker.channel.skipDays.new_day do |new_day|
- new_day.content = day
- end
- end
- skipHours.each do |hour|
- maker.channel.skipHours.new_hour do |new_hour|
- new_hour.content = hour
- end
- end
-
- maker.image.url = image_url
- maker.image.title = image_title
- end
- channel = rss.channel
-
- assert_equal(title, channel.title)
- assert_equal(link, channel.link)
- assert_equal(description, channel.description)
- assert_equal(language, channel.language)
- assert_equal(copyright, channel.copyright)
- assert_equal(managingEditor, channel.managingEditor)
- assert_equal(webMaster, channel.webMaster)
- assert_equal(rating, channel.rating)
- assert_equal(docs, channel.docs)
- assert_equal(pubDate, channel.pubDate)
- assert_equal(pubDate, channel.date)
- assert_equal(lastBuildDate, channel.lastBuildDate)
-
- skipDays.each_with_index do |day, i|
- assert_equal(day, channel.skipDays.days[i].content)
- end
- skipHours.each_with_index do |hour, i|
- assert_equal(hour.to_i, channel.skipHours.hours[i].content)
- end
-
- assert(channel.items.empty?)
-
- assert_equal(image_url, channel.image.url)
- assert_equal(image_title, channel.image.title)
- assert_equal(link, channel.image.link)
-
- assert_nil(channel.textInput)
- end
-
- def test_not_valid_channel
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
- language = "ja"
-
- assert_not_set_error("maker.channel", %w(title)) do
- RSS::Maker.make("0.91") do |maker|
- # maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- maker.channel.language = language
- end
- end
-
- assert_not_set_error("maker.channel", %w(link)) do
- RSS::Maker.make("0.91") do |maker|
- maker.channel.title = title
- # maker.channel.link = link
- maker.channel.link = nil
- maker.channel.description = description
- maker.channel.language = language
- end
- end
-
- assert_not_set_error("maker.channel", %w(description)) do
- RSS::Maker.make("0.91") do |maker|
- maker.channel.title = title
- maker.channel.link = link
- # maker.channel.description = description
- maker.channel.language = language
- end
- end
-
- assert_not_set_error("maker.channel", %w(language)) do
- RSS::Maker.make("0.91") do |maker|
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- # maker.channel.language = language
- end
- end
- end
-
- def test_image
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
- width = "144"
- height = "400"
- description = "an image"
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- image = rss.image
- assert_equal(title, image.title)
- assert_equal(link, image.link)
- assert_equal(url, image.url)
- assert_equal(width.to_i, image.width)
- assert_equal(height.to_i, image.height)
- assert_equal(description, image.description)
-
- assert_not_set_error("maker.channel", %w(description title language)) do
- RSS::Maker.make("0.91") do |maker|
- # setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- end
- end
-
- def test_not_valid_image
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
- width = "144"
- height = "400"
- description = "an image"
-
- assert_not_set_error("maker.image", %w(title)) do
- RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- # maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- end
-
- assert_not_set_error("maker.channel", %w(link)) do
- RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- # maker.channel.link = link
- maker.channel.link = nil
-
- maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- end
-
- assert_not_set_error("maker.image", %w(url)) do
- RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- # maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- end
- end
-
- def test_items(with_convenience_way=true)
- title = "TITLE"
- link = "http://hoge.com/"
- description = "text hoge fuga"
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
- end
- assert(rss.channel.items.empty?)
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
-
- maker.items.new_item do |item|
- item.title = title
- item.link = link
- # item.description = description
- end
-
- setup_dummy_image(maker)
- end
- assert_equal(1, rss.channel.items.size)
- item = rss.channel.items.first
- assert_equal(title, item.title)
- assert_equal(link, item.link)
- assert_nil(item.description)
-
- pubDate = Time.now
-
- item_size = 5
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |_item|
- _item.title = "#{title}#{i}"
- _item.link = "#{link}#{i}"
- _item.description = "#{description}#{i}"
- _item.date = pubDate - i
- end
- end
- maker.items.do_sort = true
-
- setup_dummy_image(maker)
- end
- assert_equal(item_size, rss.items.size)
- rss.channel.items.each_with_index do |_item, i|
- assert_equal("#{title}#{i}", _item.title)
- assert_equal("#{link}#{i}", _item.link)
- assert_equal("#{description}#{i}", _item.description)
- end
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |_item|
- _item.title = "#{title}#{i}"
- _item.link = "#{link}#{i}"
- _item.description = "#{description}#{i}"
- end
- end
- maker.items.do_sort = Proc.new do |x, y|
- if with_convenience_way
- y.title[-1] <=> x.title[-1]
- else
- y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]}
- end
- end
-
- setup_dummy_image(maker)
- end
- assert_equal(item_size, rss.items.size)
- rss.channel.items.reverse.each_with_index do |_item, i|
- assert_equal("#{title}#{i}", _item.title)
- assert_equal("#{link}#{i}", _item.link)
- assert_equal("#{description}#{i}", _item.description)
- end
- end
-
- def test_items_with_new_api_since_018
- test_items(false)
- end
-
- def test_textInput
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com"
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
- textInput = rss.channel.textInput
- assert_equal(title, textInput.title)
- assert_equal(description, textInput.description)
- assert_equal(name, textInput.name)
- assert_equal(link, textInput.link)
-
- assert_not_set_error("maker.channel",
- %w(link language description title)) do
- RSS::Maker.make("0.91") do |maker|
- # setup_dummy_channel(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
- end
- end
-
- def test_not_valid_textInput
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com"
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- # maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
- assert_nil(rss.channel.textInput)
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- maker.textinput.title = title
- # maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
- assert_nil(rss.channel.textInput)
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- # maker.textinput.name = name
- maker.textinput.link = link
- end
- assert_nil(rss.channel.textInput)
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- # maker.textinput.link = link
- end
- assert_nil(rss.channel.textInput)
- end
-
- def test_date_in_string
- date = Time.now
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- maker.items.new_item do |item|
- item.title = "The first item"
- item.link = "http://example.com/blog/1.html"
- item.date = date.rfc822
- end
- end
-
- assert_equal(date.iso8601, rss.items[0].date.iso8601)
- end
- end
-end
diff --git a/test/rss/test_maker_1.0.rb b/test/rss/test_maker_1.0.rb
deleted file mode 100644
index f3c0e50ceb..0000000000
--- a/test/rss/test_maker_1.0.rb
+++ /dev/null
@@ -1,519 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMaker10 < TestCase
- def test_supported?
- assert(RSS::Maker.supported?("1.0"))
- assert(RSS::Maker.supported?("rss1.0"))
- assert(!RSS::Maker.supported?("1.1"))
- assert(!RSS::Maker.supported?("rss1.1"))
- end
-
- def test_find_class
- assert_equal(RSS::Maker::RSS10, RSS::Maker["1.0"])
- assert_equal(RSS::Maker::RSS10, RSS::Maker["rss1.0"])
- end
-
- def test_rdf
- assert_raise(LocalJumpError) do
- RSS::Maker.make("1.0")
- end
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
- end
- assert_equal("1.0", rss.rss_version)
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- maker.encoding = "EUC-JP"
-
- setup_dummy_item(maker)
- end
- assert_equal("1.0", rss.rss_version)
- assert_equal("EUC-JP", rss.encoding)
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- maker.standalone = "yes"
-
- setup_dummy_item(maker)
- end
- assert_equal("1.0", rss.rss_version)
- assert_equal("yes", rss.standalone)
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- maker.encoding = "EUC-JP"
- maker.standalone = "yes"
-
- setup_dummy_item(maker)
- end
- assert_equal("1.0", rss.rss_version)
- assert_equal("EUC-JP", rss.encoding)
- assert_equal("yes", rss.standalone)
- end
-
- def test_channel
- about = "http://hoge.com"
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
-
- rss = RSS::Maker.make("1.0") do |maker|
- maker.channel.about = about
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
-
- setup_dummy_item(maker)
- end
- channel = rss.channel
- assert_equal(about, channel.about)
- assert_equal(title, channel.title)
- assert_equal(link, channel.link)
- assert_equal(description, channel.description)
- assert_equal(1, channel.items.Seq.lis.size)
- assert_nil(channel.image)
- assert_nil(channel.textinput)
-
- rss = RSS::Maker.make("1.0") do |maker|
- maker.channel.about = about
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
-
- setup_dummy_image(maker)
-
- setup_dummy_textinput(maker)
-
- setup_dummy_item(maker)
- end
- channel = rss.channel
- assert_equal(about, channel.about)
- assert_equal(title, channel.title)
- assert_equal(link, channel.link)
- assert_equal(description, channel.description)
- assert_equal(1, channel.items.Seq.lis.size)
- assert_equal(rss.image.about, channel.image.resource)
- assert_equal(rss.textinput.about, channel.textinput.resource)
- end
-
- def test_channel_language
- about = "http://hoge.com"
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
- language = "ja"
-
- rss = RSS::Maker.make("1.0") do |maker|
- maker.channel.about = about
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- maker.channel.language = language
-
- setup_dummy_item(maker)
- end
- channel = rss.channel
- assert_equal(language, channel.dc_language)
- end
-
- def test_not_valid_channel
- about = "http://hoge.com"
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
-
- assert_not_set_error("maker.channel", %w(about)) do
- RSS::Maker.make("1.0") do |maker|
- # maker.channel.about = about
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- end
- end
-
- assert_not_set_error("maker.channel", %w(title)) do
- RSS::Maker.make("1.0") do |maker|
- maker.channel.about = about
- # maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- end
- end
-
- assert_not_set_error("maker.channel", %w(link)) do
- RSS::Maker.make("1.0") do |maker|
- maker.channel.about = about
- maker.channel.title = title
- # maker.channel.link = link
- maker.channel.description = description
- end
- end
-
- assert_not_set_error("maker.channel", %w(description)) do
- RSS::Maker.make("1.0") do |maker|
- maker.channel.about = about
- maker.channel.title = title
- maker.channel.link = link
- # maker.channel.description = description
- end
- end
- end
-
-
- def test_image
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- maker.image.url = url
-
- setup_dummy_item(maker)
- end
- image = rss.image
- assert_equal(url, image.about)
- assert_equal(url, rss.channel.image.resource)
- assert_equal(title, image.title)
- assert_equal(link, image.link)
- assert_equal(url, image.url)
-
- assert_not_set_error("maker.channel", %w(about title description)) do
- RSS::Maker.make("1.0") do |maker|
- # setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- maker.image.url = url
- end
- end
- end
-
- def test_not_valid_image
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- # maker.image.url = url
- maker.image.title = title
-
- setup_dummy_item(maker)
- end
- assert_nil(rss.channel.image)
- assert_nil(rss.image)
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.url = url
- # maker.image.title = title
-
- setup_dummy_item(maker)
- end
- assert_nil(rss.channel.image)
- assert_nil(rss.image)
-
- assert_not_set_error("maker.channel", %w(link)) do
- RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- # maker.channel.link = link
- maker.channel.link = nil
-
- maker.image.url = url
- maker.image.title = title
-
- setup_dummy_item(maker)
- end
- end
- end
-
- def test_items(with_convenience_way=true)
- title = "TITLE"
- link = "http://hoge.com/"
- description = "text hoge fuga"
-
- assert_not_set_error("maker", %w(items)) do
- RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- end
- end
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.items.new_item do |item|
- item.title = title
- item.link = link
- # item.description = description
- end
- end
- assert_equal(1, rss.items.size)
- item = rss.items.first
- assert_equal(link, item.about)
- assert_equal(title, item.title)
- assert_equal(link, item.link)
- assert_nil(item.description)
-
- pubDate = Time.now
-
- item_size = 5
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |_item|
- _item.title = "#{title}#{i}"
- _item.link = "#{link}#{i}"
- _item.description = "#{description}#{i}"
- _item.date = pubDate - i
- end
- end
- maker.items.do_sort = true
- end
- assert_equal(item_size, rss.items.size)
- rss.items.each_with_index do |_item, i|
- assert_equal("#{link}#{i}", _item.about)
- assert_equal("#{title}#{i}", _item.title)
- assert_equal("#{link}#{i}", _item.link)
- assert_equal("#{description}#{i}", _item.description)
- end
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |_item|
- _item.title = "#{title}#{i}"
- _item.link = "#{link}#{i}"
- _item.description = "#{description}#{i}"
- end
- end
- maker.items.do_sort = Proc.new do |x, y|
- if with_convenience_way
- y.title[-1] <=> x.title[-1]
- else
- y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]}
- end
- end
- end
- assert_equal(item_size, rss.items.size)
- rss.items.reverse.each_with_index do |_item, i|
- assert_equal("#{link}#{i}", _item.about)
- assert_equal("#{title}#{i}", _item.title)
- assert_equal("#{link}#{i}", _item.link)
- assert_equal("#{description}#{i}", _item.description)
- end
-
- max_size = item_size / 2
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |_item|
- _item.title = "#{title}#{i}"
- _item.link = "#{link}#{i}"
- _item.description = "#{description}#{i}"
- end
- end
- maker.items.max_size = max_size
- end
- assert_equal(max_size, rss.items.size)
- rss.items.each_with_index do |_item, i|
- assert_equal("#{link}#{i}", _item.about)
- assert_equal("#{title}#{i}", _item.title)
- assert_equal("#{link}#{i}", _item.link)
- assert_equal("#{description}#{i}", _item.description)
- end
-
- max_size = 0
- assert_not_set_error("maker", %w(items)) do
- RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |_item|
- _item.title = "#{title}#{i}"
- _item.link = "#{link}#{i}"
- _item.description = "#{description}#{i}"
- end
- end
- maker.items.max_size = max_size
- end
- end
-
- max_size = -2
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |_item|
- _item.title = "#{title}#{i}"
- _item.link = "#{link}#{i}"
- _item.description = "#{description}#{i}"
- end
- end
- maker.items.max_size = max_size
- end
- assert_equal(item_size + max_size + 1, rss.items.size)
- rss.items.each_with_index do |_item, i|
- assert_equal("#{link}#{i}", _item.about)
- assert_equal("#{title}#{i}", _item.title)
- assert_equal("#{link}#{i}", _item.link)
- assert_equal("#{description}#{i}", _item.description)
- end
- end
-
- def test_items_with_new_api_since_018
- test_items(false)
- end
-
- def test_not_valid_items
- title = "TITLE"
- link = "http://hoge.com/"
-
- assert_not_set_error("maker.item", %w(title)) do
- RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.items.new_item do |item|
- # item.title = title
- item.link = link
- end
- end
- end
-
- assert_not_set_error("maker.item", %w(link)) do
- RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.items.new_item do |item|
- item.title = title
- # item.link = link
- end
- end
- end
-
- assert_not_set_error("maker.item", %w(title link)) do
- RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.items.new_item do |item|
- # item.title = title
- # item.link = link
- end
- end
- end
- end
-
- def test_textinput
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com"
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.link = link
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
-
- setup_dummy_item(maker)
- end
- textinput = rss.textinput
- assert_equal(link, textinput.about)
- assert_equal(link, rss.channel.textinput.resource)
- assert_equal(title, textinput.title)
- assert_equal(name, textinput.name)
- assert_equal(description, textinput.description)
- assert_equal(link, textinput.link)
-
- assert_not_set_error("maker.channel", %w(about link description title)) do
- RSS::Maker.make("1.0") do |maker|
- # setup_dummy_channel(maker)
-
- maker.textinput.link = link
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- end
- end
- end
-
- def test_not_valid_textinput
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com"
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- # maker.textinput.link = link
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
-
- setup_dummy_item(maker)
- end
- assert_nil(rss.channel.textinput)
- assert_nil(rss.textinput)
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.link = link
- # maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
-
- setup_dummy_item(maker)
- end
- assert_nil(rss.channel.textinput)
- assert_nil(rss.textinput)
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.link = link
- maker.textinput.title = title
- # maker.textinput.description = description
- maker.textinput.name = name
-
- setup_dummy_item(maker)
- end
- assert_nil(rss.channel.textinput)
- assert_nil(rss.textinput)
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.link = link
- maker.textinput.title = title
- maker.textinput.description = description
- # maker.textinput.name = name
-
- setup_dummy_item(maker)
- end
- assert_nil(rss.channel.textinput)
- assert_nil(rss.textinput)
- end
-
- end
-end
diff --git a/test/rss/test_maker_2.0.rb b/test/rss/test_maker_2.0.rb
deleted file mode 100644
index f6d83f0c3d..0000000000
--- a/test/rss/test_maker_2.0.rb
+++ /dev/null
@@ -1,758 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMaker20 < TestCase
- def test_supported?
- assert(RSS::Maker.supported?("2.0"))
- assert(RSS::Maker.supported?("rss2.0"))
- assert(!RSS::Maker.supported?("2.2"))
- assert(!RSS::Maker.supported?("rss2.2"))
- end
-
- def test_find_class
- assert_equal(RSS::Maker::RSS20, RSS::Maker["2.0"])
- assert_equal(RSS::Maker::RSS20, RSS::Maker["rss2.0"])
- end
-
- def test_rss
- assert_raise(LocalJumpError) do
- RSS::Maker.make("2.0")
- end
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- end
- assert_equal("2.0", rss.rss_version)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.encoding = "EUC-JP"
- end
- assert_equal("2.0", rss.rss_version)
- assert_equal("EUC-JP", rss.encoding)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.standalone = "yes"
- end
- assert_equal("2.0", rss.rss_version)
- assert_equal("yes", rss.standalone)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.encoding = "EUC-JP"
- maker.standalone = "yes"
- end
- assert_equal("2.0", rss.rss_version)
- assert_equal("EUC-JP", rss.encoding)
- assert_equal("yes", rss.standalone)
- end
-
- def test_channel
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
- language = "ja"
- copyright = "foo"
- managingEditor = "bar"
- webMaster = "web master"
- rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))'
- docs = "http://foo.com/doc"
- skipDays = [
- "Sunday",
- "Monday",
- ]
- skipHours = [
- "0",
- "13",
- ]
- pubDate = Time.now
- lastBuildDate = Time.now
- categories = [
- "Nespapers",
- "misc",
- ]
- generator = "RSS Maker"
- ttl = "60"
-
- rss = RSS::Maker.make("2.0") do |maker|
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- maker.channel.language = language
- maker.channel.copyright = copyright
- maker.channel.managingEditor = managingEditor
- maker.channel.webMaster = webMaster
- maker.channel.rating = rating
- maker.channel.docs = docs
- maker.channel.pubDate = pubDate
- maker.channel.lastBuildDate = lastBuildDate
-
- skipDays.each do |day|
- maker.channel.skipDays.new_day do |new_day|
- new_day.content = day
- end
- end
- skipHours.each do |hour|
- maker.channel.skipHours.new_hour do |new_hour|
- new_hour.content = hour
- end
- end
-
- categories.each do |category|
- maker.channel.categories.new_category do |new_category|
- new_category.content = category
- end
- end
-
- maker.channel.generator = generator
- maker.channel.ttl = ttl
- end
- channel = rss.channel
-
- assert_equal(title, channel.title)
- assert_equal(link, channel.link)
- assert_equal(description, channel.description)
- assert_equal(language, channel.language)
- assert_equal(copyright, channel.copyright)
- assert_equal(managingEditor, channel.managingEditor)
- assert_equal(webMaster, channel.webMaster)
- assert_equal(rating, channel.rating)
- assert_equal(docs, channel.docs)
- assert_equal(pubDate, channel.pubDate)
- assert_equal(pubDate, channel.date)
- assert_equal(lastBuildDate, channel.lastBuildDate)
-
- skipDays.each_with_index do |day, i|
- assert_equal(day, channel.skipDays.days[i].content)
- end
- skipHours.each_with_index do |hour, i|
- assert_equal(hour.to_i, channel.skipHours.hours[i].content)
- end
-
- channel.categories.each_with_index do |category, i|
- assert_equal(categories[i], category.content)
- end
-
- assert_equal(generator, channel.generator)
- assert_equal(ttl.to_i, channel.ttl)
-
- assert(channel.items.empty?)
- assert_nil(channel.image)
- assert_nil(channel.textInput)
- end
-
- def test_not_valid_channel
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
- language = "ja"
-
- assert_not_set_error("maker.channel", %w(title)) do
- RSS::Maker.make("2.0") do |maker|
- # maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- maker.channel.language = language
- end
- end
-
- assert_not_set_error("maker.channel", %w(link)) do
- RSS::Maker.make("2.0") do |maker|
- maker.channel.title = title
- # maker.channel.link = link
- maker.channel.description = description
- maker.channel.language = language
- end
- end
-
- assert_not_set_error("maker.channel", %w(description)) do
- RSS::Maker.make("2.0") do |maker|
- maker.channel.title = title
- maker.channel.link = link
- # maker.channel.description = description
- maker.channel.language = language
- end
- end
-
- rss = RSS::Maker.make("2.0") do |maker|
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- # maker.channel.language = language
- end
- assert_not_nil(rss)
- end
-
-
- def test_cloud
- domain = "rpc.sys.com"
- port = "80"
- path = "/RPC2"
- registerProcedure = "myCloud.rssPleaseNotify"
- protocol = "xml-rpc"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.channel.cloud.domain = domain
- maker.channel.cloud.port = port
- maker.channel.cloud.path = path
- maker.channel.cloud.registerProcedure = registerProcedure
- maker.channel.cloud.protocol = protocol
- end
- cloud = rss.channel.cloud
- assert_equal(domain, cloud.domain)
- assert_equal(port.to_i, cloud.port)
- assert_equal(path, cloud.path)
- assert_equal(registerProcedure, cloud.registerProcedure)
- assert_equal(protocol, cloud.protocol)
- end
-
- def test_not_valid_cloud
- domain = "rpc.sys.com"
- port = "80"
- path = "/RPC2"
- registerProcedure = "myCloud.rssPleaseNotify"
- protocol = "xml-rpc"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- # maker.channel.cloud.domain = domain
- maker.channel.cloud.port = port
- maker.channel.cloud.path = path
- maker.channel.cloud.registerProcedure = registerProcedure
- maker.channel.cloud.protocol = protocol
- end
- assert_nil(rss.channel.cloud)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.channel.cloud.domain = domain
- # maker.channel.cloud.port = port
- maker.channel.cloud.path = path
- maker.channel.cloud.registerProcedure = registerProcedure
- maker.channel.cloud.protocol = protocol
- end
- assert_nil(rss.channel.cloud)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.channel.cloud.domain = domain
- maker.channel.cloud.port = port
- # maker.channel.cloud.path = path
- maker.channel.cloud.registerProcedure = registerProcedure
- maker.channel.cloud.protocol = protocol
- end
- assert_nil(rss.channel.cloud)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.channel.cloud.domain = domain
- maker.channel.cloud.port = port
- maker.channel.cloud.path = path
- # maker.channel.cloud.registerProcedure = registerProcedure
- maker.channel.cloud.protocol = protocol
- end
- assert_nil(rss.channel.cloud)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.channel.cloud.domain = domain
- maker.channel.cloud.port = port
- maker.channel.cloud.path = path
- maker.channel.cloud.registerProcedure = registerProcedure
- # maker.channel.cloud.protocol = protocol
- end
- assert_nil(rss.channel.cloud)
- end
-
-
- def test_image
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
- width = "144"
- height = "400"
- description = "an image"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- image = rss.image
- assert_equal(title, image.title)
- assert_equal(link, image.link)
- assert_equal(url, image.url)
- assert_equal(width.to_i, image.width)
- assert_equal(height.to_i, image.height)
- assert_equal(description, image.description)
-
- assert_not_set_error("maker.channel", %w(title description)) do
- RSS::Maker.make("2.0") do |maker|
- # setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- end
- end
-
- def test_not_valid_image
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
- width = "144"
- height = "400"
- description = "an image"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- # maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- assert_nil(rss.image)
-
- assert_not_set_error("maker.channel", %w(link)) do
- RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- # maker.channel.link = link
- maker.channel.link = nil
-
- maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- end
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- # maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
- assert_nil(rss.image)
- end
-
- def test_items(with_convenience_way=true)
- title = "TITLE"
- link = "http://hoge.com/"
- description = "text hoge fuga"
- author = "oprah@oxygen.net"
- comments = "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290"
- pubDate = Time.now
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- end
- assert(rss.channel.items.empty?)
-
- item_size = 5
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{title}#{i}"
- item.link = "#{link}#{i}"
- item.description = "#{description}#{i}"
- item.author = "#{author}#{i}"
- item.comments = "#{comments}#{i}"
- item.date = pubDate - i
- end
- end
- maker.items.do_sort = true
- end
- assert_equal(item_size, rss.items.size)
- rss.channel.items.each_with_index do |item, i|
- assert_equal("#{title}#{i}", item.title)
- assert_equal("#{link}#{i}", item.link)
- assert_equal("#{description}#{i}", item.description)
- assert_equal("#{author}#{i}", item.author)
- assert_equal("#{comments}#{i}", item.comments)
- assert_equal(pubDate - i, item.pubDate)
- assert_equal(pubDate - i, item.date)
- end
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{title}#{i}"
- item.link = "#{link}#{i}"
- item.description = "#{description}#{i}"
- item.author = "#{author}#{i}"
- item.comments = "#{comments}#{i}"
- item.date = pubDate
- end
- end
- maker.items.do_sort = Proc.new do |x, y|
- if with_convenience_way
- y.title[-1] <=> x.title[-1]
- else
- y.title {|t| t.content[-1]} <=> x.title {|t| t.content[-1]}
- end
- end
- end
- assert_equal(item_size, rss.items.size)
- rss.channel.items.reverse.each_with_index do |item, i|
- assert_equal("#{title}#{i}", item.title)
- assert_equal("#{link}#{i}", item.link)
- assert_equal("#{description}#{i}", item.description)
- assert_equal("#{author}#{i}", item.author)
- assert_equal("#{comments}#{i}", item.comments)
- assert_equal(pubDate, item.pubDate)
- assert_equal(pubDate, item.date)
- end
- end
-
- def test_items_with_new_api_since_018
- test_items(false)
- end
-
- def test_pubDate_without_description
- title = "TITLE"
- link = "http://hoge.com/"
- # description = "text hoge fuga"
- author = "oprah@oxygen.net"
- pubDate = Time.now
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.items.new_item do |item|
- item.title = title
- item.link = link
- # item.description = description
- item.author = author
- item.pubDate = pubDate
- end
- end
- assert_equal(1, rss.items.size)
- rss.channel.items.each_with_index do |item, i|
- assert_equal(title, item.title)
- assert_equal(link, item.link)
- # assert_equal(description, item.description)
- assert_equal(author, item.author)
- assert_equal(pubDate, item.pubDate)
- assert_equal(pubDate, item.date)
- end
- end
-
- def test_guid
- isPermaLink = "true"
- content = "http://inessential.com/2002/09/01.php#a2"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- guid = maker.items.last.guid
- guid.isPermaLink = isPermaLink
- guid.content = content
- end
- guid = rss.channel.items.last.guid
- assert_equal(isPermaLink == "true", guid.isPermaLink)
- assert_equal(content, guid.content)
- end
-
- def test_guid_permanent_link
- content = "http://inessential.com/2002/09/01.php#a2"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- guid = maker.items.last.guid
- assert_equal(nil, guid.permanent_link?)
- assert_equal(guid.isPermaLink, guid.permanent_link?)
- guid.permanent_link = true
- assert_equal(true, guid.permanent_link?)
- assert_equal(guid.isPermaLink, guid.permanent_link?)
- guid.content = content
- end
- guid = rss.channel.items.last.guid
- assert_equal(true, guid.isPermaLink)
- assert_equal(content, guid.content)
- end
-
- def test_guid_permanent_link_false
- content = "http://inessential.com/2002/09/01.php#a2"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- guid = maker.items.last.guid
- assert_equal(nil, guid.permanent_link?)
- assert_equal(guid.isPermaLink, guid.permanent_link?)
- guid.permanent_link = false
- assert_equal(false, guid.permanent_link?)
- assert_equal(guid.isPermaLink, guid.permanent_link?)
- guid.content = content
- end
- guid = rss.channel.items.last.guid
- assert_equal(false, guid.isPermaLink)
- assert_equal(content, guid.content)
- end
-
- def test_not_valid_guid
- # content = "http://inessential.com/2002/09/01.php#a2"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- # guid = maker.items.last.guid
- # guid.content = content
- end
- assert_nil(rss.channel.items.last.guid)
- end
-
- def test_enclosure
- url = "http://www.scripting.com/mp3s/weatherReportSuite.mp3"
- length = "12216320"
- type = "audio/mpeg"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- enclosure = maker.items.last.enclosure
- enclosure.url = url
- enclosure.length = length
- enclosure.type = type
- end
- enclosure = rss.channel.items.last.enclosure
- assert_equal(url, enclosure.url)
- assert_equal(length.to_i, enclosure.length)
- assert_equal(type, enclosure.type)
- end
-
- def test_not_valid_enclosure
- url = "http://www.scripting.com/mp3s/weatherReportSuite.mp3"
- length = "12216320"
- type = "audio/mpeg"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- enclosure = maker.items.last.enclosure
- # enclosure.url = url
- enclosure.length = length
- enclosure.type = type
- end
- assert_nil(rss.channel.items.last.enclosure)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- enclosure = maker.items.last.enclosure
- enclosure.url = url
- # enclosure.length = length
- enclosure.type = type
- end
- assert_nil(rss.channel.items.last.enclosure)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- enclosure = maker.items.last.enclosure
- enclosure.url = url
- enclosure.length = length
- # enclosure.type = type
- end
- assert_nil(rss.channel.items.last.enclosure)
- end
-
-
- def test_source
- url = "http://static.userland.com/tomalak/links2.xml"
- content = "Tomalak's Realm"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- source = maker.items.last.source
- source.url = url
- source.content = content
- end
- source = rss.channel.items.last.source
- assert_equal(url, source.url)
- assert_equal(content, source.content)
- end
-
- def test_not_valid_source
- url = "http://static.userland.com/tomalak/links2.xml"
- content = "Tomalak's Realm"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- source = maker.items.last.source
- # source.url = url
- source.content = content
- end
- assert_nil(rss.channel.items.last.source)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- source = maker.items.last.source
- source.url = url
- # source.content = content
- end
- assert_nil(rss.channel.items.last.source)
- end
-
- def test_category
- domain = "http://www.fool.com/cusips"
- content = "MSFT"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- maker.items.last.categories.new_category do |category|
- category.domain = domain
- category.content = content
- end
- end
- category = rss.channel.items.last.categories.last
- assert_equal(domain, category.domain)
- assert_equal(content, category.content)
- end
-
- def test_not_valid_category
- # content = "Grateful Dead"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- maker.items.last.categories.new_category do |category|
- # category.content = content
- end
- end
- assert(rss.channel.items.last.categories.empty?)
- end
-
- def test_textInput
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
- textInput = rss.channel.textInput
- assert_equal(title, textInput.title)
- assert_equal(description, textInput.description)
- assert_equal(name, textInput.name)
- assert_equal(link, textInput.link)
-
- assert_not_set_error("maker.channel", %w(link description title)) do
- RSS::Maker.make("2.0") do |maker|
- # setup_dummy_channel(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
- end
- end
-
- def test_not_valid_textInput
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- # maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
- assert_nil(rss.channel.textInput)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.title = title
- # maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
- assert_nil(rss.channel.textInput)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- # maker.textinput.name = name
- maker.textinput.link = link
- end
- assert_nil(rss.channel.textInput)
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- # maker.textinput.link = link
- end
- assert_nil(rss.channel.textInput)
- end
- end
-end
diff --git a/test/rss/test_maker_atom_entry.rb b/test/rss/test_maker_atom_entry.rb
deleted file mode 100644
index 8e41c7c50e..0000000000
--- a/test/rss/test_maker_atom_entry.rb
+++ /dev/null
@@ -1,394 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerAtomEntry < TestCase
- def test_supported?
- assert(RSS::Maker.supported?("atom:entry"))
- assert(RSS::Maker.supported?("atom1.0:entry"))
- assert(!RSS::Maker.supported?("atom2.0:entry"))
- end
-
- def test_find_class
- assert_equal(RSS::Maker::Atom::Entry, RSS::Maker["atom:entry"])
- assert_equal(RSS::Maker::Atom::Entry, RSS::Maker["atom1.0:entry"])
- end
-
- def test_root_element
- entry = Maker.make("atom:entry") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- assert_equal(["atom", "1.0", "entry"], entry.feed_info)
-
- entry = Maker.make("atom:entry") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.encoding = "EUC-JP"
- end
- assert_equal(["atom", "1.0", "entry"], entry.feed_info)
- assert_equal("EUC-JP", entry.encoding)
-
- entry = Maker.make("atom:entry") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.standalone = "yes"
- end
- assert_equal(["atom", "1.0", "entry"], entry.feed_info)
- assert_equal("yes", entry.standalone)
-
- entry = Maker.make("atom:entry") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.encoding = "EUC-JP"
- maker.standalone = "yes"
- end
- assert_equal(["atom", "1.0", "entry"], entry.feed_info)
- assert_equal("EUC-JP", entry.encoding)
- assert_equal("yes", entry.standalone)
- end
-
- def test_invalid_feed
- assert_not_set_error("maker.item", %w(id title author updated)) do
- Maker.make("atom:entry") do |maker|
- end
- end
-
- assert_not_set_error("maker.item", %w(id title updated)) do
- Maker.make("atom:entry") do |maker|
- maker.channel.author = "foo"
- end
- end
-
- assert_not_set_error("maker.item", %w(title updated)) do
- Maker.make("atom:entry") do |maker|
- maker.channel.author = "foo"
- maker.channel.id = "http://example.com"
- end
- end
-
- assert_not_set_error("maker.item", %w(updated)) do
- Maker.make("atom:entry") do |maker|
- maker.channel.author = "foo"
- maker.channel.id = "http://example.com"
- maker.channel.title = "Atom Feed"
- end
- end
-
- assert_not_set_error("maker.item", %w(author)) do
- Maker.make("atom:entry") do |maker|
- maker.channel.id = "http://example.com"
- maker.channel.title = "Atom Feed"
- maker.channel.updated = Time.now
- end
- end
-
- entry = Maker.make("atom:entry") do |maker|
- maker.channel.author = "Foo"
- maker.channel.id = "http://example.com"
- maker.channel.title = "Atom Feed"
- maker.channel.updated = Time.now
- end
- assert_not_nil(entry)
- end
-
- def test_author
- assert_maker_atom_persons("entry",
- ["channel", "authors"],
- ["authors"],
- "maker.channel.author") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_persons("entry",
- ["items", "first", "authors"],
- ["authors"],
- "maker.item.author",
- "maker.item", ["author"]) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.channel.authors.clear
- maker.items.first.authors.clear
- end
-
- assert_maker_atom_persons("entry",
- ["items", "first", "source", "authors"],
- ["source", "authors"],
- "maker.item.source.author") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_category
- assert_maker_atom_categories("entry",
- ["channel", "categories"],
- ["categories"],
- "maker.channel.category") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_categories("entry",
- ["items", "first", "categories"],
- ["categories"],
- "maker.item.category") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_categories("entry",
- ["items", "first", "source", "categories"],
- ["source", "categories"],
- "maker.item.source.category") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_content
- assert_maker_atom_content("entry",
- ["items", "first", "content"],
- ["content"],
- "maker.item.content") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_contributor
- assert_maker_atom_persons("entry",
- ["channel", "contributors"],
- ["contributors"],
- "maker.channel.contributor") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_persons("entry",
- ["items", "first", "contributors"],
- ["contributors"],
- "maker.item.contributor") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_persons("entry",
- ["items", "first", "source", "contributors"],
- ["source", "contributors"],
- "maker.item.source.contributor") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_link
- assert_maker_atom_links("entry",
- ["channel", "links"],
- ["links"],
- "maker.channel.link") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.channel.links.clear
- maker.items.first.links.clear
- end
-
- assert_maker_atom_links("entry",
- ["items", "first", "links"],
- ["links"],
- "maker.item.link") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.channel.links.clear
- maker.items.first.links.clear
- end
-
- assert_maker_atom_links("entry",
- ["items", "first", "source", "links"],
- ["source", "links"],
- "maker.item.source.link", true) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_published
- assert_maker_atom_date_construct("entry",
- ["items", "first", "published"],
- ["published"]
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_rights
- assert_maker_atom_text_construct("entry",
- ["channel", "copyright"],
- ["rights"]) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_text_construct("entry",
- ["items", "first", "rights"],
- ["rights"],
- nil, nil, "maker.item.rights"
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_text_construct("entry",
- ["items", "first", "source", "rights"],
- ["source", "rights"],
- nil, nil, "maker.item.source.rights"
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
-
- def test_source_generator
- assert_maker_atom_generator("entry",
- ["items", "first", "source", "generator"],
- ["source", "generator"],
- "maker.item.source.generator") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_source_icon
- assert_maker_atom_icon("entry",
- ["items", "first", "source", "icon"],
- ["source", "icon"],
- nil, "maker.item.source.icon") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_source_id
- assert_maker_atom_id("entry",
- ["items", "first", "source"],
- ["source"],
- "maker.item.source") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_source_logo
- assert_maker_atom_logo("entry",
- ["items", "first", "source", "logo"],
- ["source", "logo"],
- nil,
- "maker.item.source.logo") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_source_subtitle
- assert_maker_atom_text_construct("entry",
- ["items", "first", "source", "subtitle"],
- ["source", "subtitle"],
- nil, nil,
- "maker.item.source.subtitle") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_summary
- assert_maker_atom_text_construct("entry",
- ["items", "first", "description"],
- ["summary"],
- nil, nil, "maker.item.description"
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_title
- assert_maker_atom_text_construct("entry",
- ["channel", "title"], ["title"],
- "maker.item", ["title"],
- "maker.channel.title") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.channel.title = nil
- maker.items.first.title = nil
- end
-
- assert_maker_atom_text_construct("entry",
- ["items", "first", "title"],
- ["title"],
- "maker.item", ["title"],
- "maker.item.title") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.channel.title = nil
- maker.items.first.title = nil
- end
-
- assert_maker_atom_text_construct("entry",
- ["items", "first", "source", "title"],
- ["source", "title"],
- nil, nil, "maker.item.source.title"
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_updated
- assert_maker_atom_date_construct("entry",
- ["channel", "updated"], ["updated"],
- "maker.item", ["updated"]) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.channel.updated = nil
- maker.items.first.updated = nil
- end
-
- assert_maker_atom_date_construct("entry",
- ["items", "first", "updated"],
- ["updated"],
- "maker.item", ["updated"]) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.channel.updated = nil
- maker.items.first.updated = nil
- end
-
- assert_maker_atom_date_construct("entry",
- ["items", "first", "source", "updated"],
- ["source", "updated"]) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_date
- date = Time.parse("2004/11/1 10:10")
- feed = Maker.make("atom:entry") do |maker|
- setup_dummy_channel_atom(maker)
- maker.channel.date = nil
- maker.items.new_item do |item|
- item.link = "http://example.com/article.html"
- item.title = "Sample Article"
- item.date = date
- end
- end
- assert_equal(date, feed.items[0].updated.content)
- assert_equal([date], feed.items[0].dc_dates.collect {|_date| _date.value})
- end
- end
-end
diff --git a/test/rss/test_maker_atom_feed.rb b/test/rss/test_maker_atom_feed.rb
deleted file mode 100644
index d4eacd36ad..0000000000
--- a/test/rss/test_maker_atom_feed.rb
+++ /dev/null
@@ -1,455 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerAtomFeed < TestCase
- def test_supported?
- assert(RSS::Maker.supported?("atom"))
- assert(RSS::Maker.supported?("atom:feed"))
- assert(RSS::Maker.supported?("atom1.0"))
- assert(RSS::Maker.supported?("atom1.0:feed"))
- assert(!RSS::Maker.supported?("atom2.0"))
- assert(!RSS::Maker.supported?("atom2.0:feed"))
- end
-
- def test_find_class
- assert_equal(RSS::Maker::Atom::Feed, RSS::Maker["atom"])
- assert_equal(RSS::Maker::Atom::Feed, RSS::Maker["atom:feed"])
- assert_equal(RSS::Maker::Atom::Feed, RSS::Maker["atom1.0"])
- assert_equal(RSS::Maker::Atom::Feed, RSS::Maker["atom1.0:feed"])
- end
-
- def test_root_element
- feed = Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
- end
- assert_equal(["atom", "1.0", "feed"], feed.feed_info)
-
- feed = Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
- maker.encoding = "EUC-JP"
- end
- assert_equal(["atom", "1.0", "feed"], feed.feed_info)
- assert_equal("EUC-JP", feed.encoding)
-
- feed = Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
- maker.standalone = "yes"
- end
- assert_equal(["atom", "1.0", "feed"], feed.feed_info)
- assert_equal("yes", feed.standalone)
-
- feed = Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
- maker.encoding = "EUC-JP"
- maker.standalone = "yes"
- end
- assert_equal(["atom", "1.0", "feed"], feed.feed_info)
- assert_equal("EUC-JP", feed.encoding)
- assert_equal("yes", feed.standalone)
- end
-
- def test_invalid_feed
- assert_not_set_error("maker.channel", %w(id title author updated)) do
- Maker.make("atom") do |maker|
- end
- end
-
- assert_not_set_error("maker.channel", %w(id title updated)) do
- Maker.make("atom") do |maker|
- maker.channel.author = "foo"
- end
- end
-
- assert_not_set_error("maker.channel", %w(title updated)) do
- Maker.make("atom") do |maker|
- maker.channel.author = "foo"
- maker.channel.id = "http://example.com"
- end
- end
-
- assert_not_set_error("maker.channel", %w(updated)) do
- Maker.make("atom") do |maker|
- maker.channel.author = "foo"
- maker.channel.id = "http://example.com"
- maker.channel.title = "Atom Feed"
- end
- end
-
- assert_not_set_error("maker.channel", %w(author)) do
- Maker.make("atom") do |maker|
- maker.channel.id = "http://example.com"
- maker.channel.title = "Atom Feed"
- maker.channel.updated = Time.now
- end
- end
-
- feed = Maker.make("atom") do |maker|
- maker.channel.author = "Foo"
- maker.channel.id = "http://example.com"
- maker.channel.title = "Atom Feed"
- maker.channel.updated = Time.now
- end
- assert_not_nil(feed)
- end
-
- def test_author
- assert_maker_atom_persons("feed",
- ["channel", "authors"],
- ["authors"],
- "maker.channel.author") do |maker|
- setup_dummy_channel_atom(maker)
- end
-
- assert_not_set_error("maker.channel", %w(author)) do
- RSS::Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.channel.authors.clear
- end
- end
-
- assert_maker_atom_persons("feed",
- ["items", "first", "authors"],
- ["entries", "first", "authors"],
- "maker.item.author") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_persons("feed",
- ["items", "first", "source", "authors"],
- ["entries", "first", "source", "authors"],
- "maker.item.source.author") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_category
- assert_maker_atom_categories("feed",
- ["channel", "categories"],
- ["categories"],
- "maker.channel.category") do |maker|
- setup_dummy_channel_atom(maker)
- end
-
- assert_maker_atom_categories("feed",
- ["items", "first", "categories"],
- ["entries", "first", "categories"],
- "maker.item.category") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_categories("feed",
- ["items", "first", "source", "categories"],
- ["entries", "first", "source", "categories"],
- "maker.item.source.category") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_contributor
- assert_maker_atom_persons("feed",
- ["channel", "contributors"],
- ["contributors"],
- "maker.channel.contributor") do |maker|
- setup_dummy_channel_atom(maker)
- end
-
- assert_maker_atom_persons("feed",
- ["items", "first", "contributors"],
- ["entries", "first", "contributors"],
- "maker.item.contributor") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_persons("feed",
- ["items", "first", "source", "contributors"],
- ["entries", "first", "source", "contributors"],
- "maker.item.source.contributor") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_generator
- assert_maker_atom_generator("feed",
- ["channel", "generator"],
- ["generator"]) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_generator("feed",
- ["items", "first", "source", "generator"],
- ["entries", "first", "source", "generator"],
- "maker.item.source.generator") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_icon
- assert_maker_atom_icon("feed", ["channel"], ["icon"], "icon") do |maker|
- setup_dummy_channel_atom(maker)
- end
-
- assert_maker_atom_icon("feed",
- ["items", "first", "source", "icon"],
- ["entries", "first", "source", "icon"],
- nil, "maker.item.source.icon") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_link
- assert_maker_atom_links("feed",
- ["channel", "links"],
- ["links"],
- "maker.channel.link") do |maker|
- setup_dummy_channel_atom(maker)
- end
-
- assert_maker_atom_links("feed",
- ["items", "first", "links"],
- ["entries", "first", "links"],
- "maker.item.link") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_links("feed",
- ["items", "first", "source", "links"],
- ["entries", "first", "source", "links"],
- "maker.item.source.link", true) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_logo
- assert_maker_atom_logo("feed", ["channel"], ["logo"], "logo") do |maker|
- setup_dummy_channel_atom(maker)
- end
-
- assert_maker_atom_logo("feed", ["image"], ["logo"], "url") do |maker|
- setup_dummy_channel_atom(maker)
- end
-
- assert_maker_atom_logo("feed",
- ["items", "first", "source", "logo"],
- ["entries", "first", "source", "logo"],
- nil, "maker.item.source.logo") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_rights
- assert_maker_atom_text_construct("feed",
- ["channel", "copyright"],
- ["rights"]) do |maker|
- setup_dummy_channel_atom(maker)
- end
-
- assert_maker_atom_text_construct("feed",
- ["items", "first", "rights"],
- ["entries", "first", "rights"],
- nil, nil, "maker.item.rights"
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
-
- assert_maker_atom_text_construct("feed",
- ["items", "first", "source", "rights"],
- ["entries", "first", "source", "rights"],
- nil, nil, "maker.item.source.rights"
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_subtitle
- assert_maker_atom_text_construct("feed",
- ["channel", "subtitle"],
- ["subtitle"],
- nil, nil,
- "maker.channel.description") do |maker|
- setup_dummy_channel_atom(maker)
- maker.channel.description = nil
- end
-
- assert_maker_atom_text_construct("feed",
- ["channel", "subtitle"],
- ["subtitle"],
- nil, nil,
- "maker.channel.description") do |maker|
- setup_dummy_channel_atom(maker)
- maker.channel.description {|d| d.content = nil}
- end
-
- assert_maker_atom_text_construct("feed",
- ["items", "first", "source", "subtitle"],
- ["entries", "first",
- "source", "subtitle"],
- nil, nil,
- "maker.item.source.subtitle") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_title
- assert_maker_atom_text_construct("feed",
- ["channel", "title"], ["title"],
- "maker.channel", ["title"]) do |maker|
- setup_dummy_channel_atom(maker)
- maker.channel.title = nil
- end
-
- assert_maker_atom_text_construct("feed",
- ["items", "first", "title"],
- ["entries", "first", "title"],
- "maker.item", ["title"],
- "maker.item.title") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.items.first.title = nil
- end
-
- assert_maker_atom_text_construct("feed",
- ["items", "first", "source", "title"],
- ["entries", "first", "source", "title"],
- nil, nil, "maker.item.source.title"
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_updated
- assert_maker_atom_date_construct("feed",
- ["channel", "updated"], ["updated"],
- "maker.channel", ["updated"]) do |maker|
- setup_dummy_channel_atom(maker)
- maker.channel.updated = nil
- end
-
- assert_maker_atom_date_construct("feed",
- ["items", "first", "updated"],
- ["entries", "first", "updated"],
- "maker.item", ["updated"]) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- maker.items.first.updated = nil
- end
-
- assert_maker_atom_date_construct("feed",
- ["items", "first", "source", "updated"],
- ["entries", "first", "source", "updated"]
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_published
- assert_maker_atom_date_construct("feed",
- ["items", "first", "published"],
- ["entries", "first", "published"]
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_summary
- assert_maker_atom_text_construct("feed",
- ["items", "first", "description"],
- ["entries", "first", "summary"],
- nil, nil, "maker.item.description"
- ) do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_content
- assert_maker_atom_content("feed",
- ["items", "first", "content"],
- ["entries", "first", "content"],
- "maker.item.content") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_id
- assert_maker_atom_id("feed",
- ["items", "first", "source"],
- ["entries", "first", "source"],
- "maker.item.source") do |maker|
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- end
-
- def test_language
- language = "ja"
- feed = Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
- maker.channel.language = "ja"
- end
- assert_equal(language, feed.dc_language)
- end
-
- def test_date
- date = Time.parse("2004/11/1 10:10")
- feed = Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
- maker.items.new_item do |item|
- item.link = "http://example.com/article.html"
- item.title = "sample article"
- item.date = date
- end
- end
- assert_equal(date, feed.items[0].updated.content)
- assert_equal([date], feed.items[0].dc_dates.collect {|_date| _date.value})
- end
-
- def test_channel_dc_date
- date = Time.parse("2004/11/1 10:10")
- feed = Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
- maker.channel.updated = nil
- maker.channel.dc_date = date
- setup_dummy_item_atom(maker)
- end
- assert_equal(date, feed.updated.content)
- assert_equal([date], feed.dc_dates.collect {|_date| _date.value})
- end
-
- def test_item_dc_date
- date = Time.parse("2004/11/1 10:10")
- feed = Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
- maker.items.new_item do |item|
- item.link = "http://example.com/article.html"
- item.title = "sample article"
- item.dc_date = date
- end
- end
- assert_equal(date, feed.items[0].updated.content)
- assert_equal([date], feed.items[0].dc_dates.collect {|_date| _date.value})
- end
- end
-end
diff --git a/test/rss/test_maker_content.rb b/test/rss/test_maker_content.rb
deleted file mode 100644
index e3b84c53a4..0000000000
--- a/test/rss/test_maker_content.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerContent < TestCase
-
- def setup
- @uri = "http://purl.org/rss/1.0/modules/content/"
-
- @elements = {
- :encoded => "<em>ATTENTION</em>",
- }
- end
-
- def test_rss10
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- setup_dummy_item(maker)
- item = maker.items.last
- @elements.each do |name, value|
- item.__send__("#{accessor_name(name)}=", value)
- end
- end
- assert_content(@elements, rss.items.last)
- end
-
- def test_rss20
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- setup_dummy_item(maker)
- item = maker.items.last
- @elements.each do |name, value|
- item.__send__("#{accessor_name(name)}=", value)
- end
- end
- assert_content(@elements, rss.items.last)
- end
-
- private
- def accessor_name(name)
- "content_#{name}"
- end
- end
-end
diff --git a/test/rss/test_maker_dc.rb b/test/rss/test_maker_dc.rb
deleted file mode 100644
index f5c8bad2b3..0000000000
--- a/test/rss/test_maker_dc.rb
+++ /dev/null
@@ -1,150 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerDublinCore < TestCase
-
- def setup
- @uri = "http://purl.org/dc/elements/1.1/"
-
- t = Time.iso8601("2000-01-01T12:00:05+00:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
-
- @elements = {
- :title => "hoge",
- :description =>
- " XML is placing increasingly heavy loads on
- the existing technical infrastructure of the Internet.",
- :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
- :subject => "XML",
- :publisher => "The O'Reilly Network",
- :contributor => "hogehoge",
- :type => "fugafuga",
- :format => "hohoho",
- :identifier => "fufufu",
- :source => "barbar",
- :language => "ja",
- :relation => "cococo",
- :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
- :date => t,
- }
- end
-
- def test_rss10
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- set_elements(maker.channel)
-
- setup_dummy_image(maker)
- set_elements(maker.image)
-
- setup_dummy_item(maker)
- item = maker.items.last
- @elements.each do |name, value|
- item.__send__("#{accessor_name(name)}=", value)
- end
-
- setup_dummy_textinput(maker)
- set_elements(maker.textinput)
- end
- assert_dublin_core(@elements, rss.channel)
- assert_dublin_core(@elements, rss.image)
- assert_dublin_core(@elements, rss.items.last)
- assert_dublin_core(@elements, rss.textinput)
- end
-
- def test_rss10_multiple
- assert_multiple_dublin_core_rss10("_list")
- assert_multiple_dublin_core_rss10("es")
- end
-
- def assert_multiple_dublin_core_rss10(multiple_rights_suffix)
- elems = []
- @elements.each do |name, value|
- plural = name.to_s + (name == :rights ? multiple_rights_suffix : "s")
- values = [value]
- if name == :date
- values << value + 60
- else
- values << value * 2
- end
- elems << [name, values, plural]
- end
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- set_multiple_elements(maker.channel, elems)
-
- setup_dummy_image(maker)
- set_multiple_elements(maker.image, elems)
-
- setup_dummy_item(maker)
- item = maker.items.last
- elems.each do |name, values, plural|
- dc_elems = item.__send__("dc_#{plural}")
- values.each do |value|
- elem = dc_elems.__send__("new_#{name}")
- elem.value = value
- end
- end
-
- setup_dummy_textinput(maker)
- set_multiple_elements(maker.textinput, elems)
- end
- assert_multiple_dublin_core(elems, rss.channel)
- assert_multiple_dublin_core(elems, rss.image)
- assert_multiple_dublin_core(elems, rss.items.last)
- assert_multiple_dublin_core(elems, rss.textinput)
- end
-
- def test_date
- t1 = Time.iso8601("2000-01-01T12:00:05+00:00")
- t2 = Time.iso8601("2005-01-01T12:00:05+00:00")
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.date = t1
- maker.channel.dc_dates.new_date do |date|
- date.value = t2
- end
-
- setup_dummy_item(maker)
- item = maker.items.last
- item.date = t2
- item.dc_dates.new_date do |date|
- date.value = t1
- end
- end
- assert_equal([t1, t2], rss.channel.dc_dates.collect{|x| x.value})
- assert_equal([t2, t1], rss.items.last.dc_dates.collect{|x| x.value})
- end
-
- private
- def accessor_name(name)
- "dc_#{name}"
- end
-
- def set_elements(target, elems=@elements)
- elems.each do |name, value|
- target.__send__("#{accessor_name(name)}=", value)
- end
- end
-
- def set_multiple_elements(target, elems)
- elems.each do |name, values, plural|
- plural ||= "#{name}s"
- dc_elems = target.__send__("dc_#{plural}")
- values.each do |value|
- dc_elems.__send__("new_#{name}") do |new_dc_elem|
- new_dc_elem.value = value
- end
- end
- end
- end
-
- end
-end
diff --git a/test/rss/test_maker_image.rb b/test/rss/test_maker_image.rb
deleted file mode 100644
index cc663c6a5c..0000000000
--- a/test/rss/test_maker_image.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerImage < TestCase
-
- def setup
- @uri = "http://web.resource.org/rss/1.0/modules/image/"
-
- @favicon_infos = {
- "about" => "http://www.kuro5hin.org/favicon.ico",
- "image_size" => "small",
- "dc_title" => "example",
- }
- @item_infos = {
- "about" => "http://www.example.org/item.png",
- "resource" => "http://www.example.org/item",
- "dc_title" => "Example Image",
- "image_width" => "100",
- "image_height" => "65",
- }
- end
-
- def test_rss10
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- @favicon_infos.each do |name, value|
- maker.channel.image_favicon.__send__("#{name}=", value)
- end
-
- setup_dummy_image(maker)
-
- setup_dummy_item(maker)
- item = maker.items.last
- @item_infos.each do |name, value|
- item.image_item.__send__("#{name}=", value)
- end
-
- setup_dummy_textinput(maker)
- end
-
- setup_rss = RSS::Maker.make("1.0") do |maker|
- rss.setup_maker(maker)
- end
-
- [rss, setup_rss].each_with_index do |target, i|
- favicon = target.channel.image_favicon
- assert_equal(@favicon_infos["about"], favicon.about)
- assert_equal(@favicon_infos["image_size"], favicon.image_size)
- assert_equal(@favicon_infos["dc_title"], favicon.dc_title)
-
- item = target.items.last.image_item
- assert_equal(@item_infos["about"], item.about)
- assert_equal(@item_infos["resource"], item.resource)
- assert_equal(@item_infos["image_width"].to_i, item.image_width)
- assert_equal(@item_infos["image_height"].to_i, item.image_height)
- assert_equal(@item_infos["dc_title"], item.dc_title)
- end
- end
- end
-end
diff --git a/test/rss/test_maker_itunes.rb b/test/rss/test_maker_itunes.rb
deleted file mode 100644
index cba612c099..0000000000
--- a/test/rss/test_maker_itunes.rb
+++ /dev/null
@@ -1,487 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerITunes < TestCase
- def test_author
- assert_maker_itunes_author(%w(channel))
- assert_maker_itunes_author(%w(items last))
- end
-
- def test_block
- assert_maker_itunes_block(%w(channel))
- assert_maker_itunes_block(%w(items last))
- end
-
- def test_category
- assert_maker_itunes_category(%w(channel))
- end
-
- def test_image
- assert_maker_itunes_image(%w(channel))
- end
-
- def test_duration
- assert_maker_itunes_duration(%w(items last))
- end
-
- def test_explicit
- assert_maker_itunes_explicit(%w(channel))
- assert_maker_itunes_explicit(%w(items last))
- end
-
- def test_keywords
- assert_maker_itunes_keywords(%w(channel))
- assert_maker_itunes_keywords(%w(items last))
- end
-
- def test_new_feed_url
- assert_maker_itunes_new_feed_url(%w(channel))
- end
-
- def test_owner
- assert_maker_itunes_owner(%w(channel))
- end
-
- def test_subtitle
- assert_maker_itunes_subtitle(%w(channel))
- assert_maker_itunes_subtitle(%w(items last))
- end
-
- def test_summary
- assert_maker_itunes_summary(%w(channel))
- assert_maker_itunes_summary(%w(items last))
- end
-
- private
-
- def assert_maker_itunes_author(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- author = "John Doe"
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- target.itunes_author = author
- end
- target = chain_reader(rss20, feed_readers)
- assert_equal(author, target.itunes_author)
- end
- end
-
- def _assert_maker_itunes_block(value, boolean_value, maker_readers,
- feed_readers)
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- target.itunes_block = value
- assert_equal(value, target.itunes_block)
- assert_equal(boolean_value, target.itunes_block?)
- end
- target = chain_reader(rss20, feed_readers)
- if [true, false].include?(value)
- value = value ? "yes" : "no"
- end
- assert_equal(value, target.itunes_block)
- assert_equal(boolean_value, target.itunes_block?)
- end
-
- def assert_maker_itunes_block(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- _assert_maker_itunes_block("yes", true, maker_readers, feed_readers)
- _assert_maker_itunes_block("Yes", true, maker_readers, feed_readers)
- _assert_maker_itunes_block("no", false, maker_readers, feed_readers)
- _assert_maker_itunes_block("", false, maker_readers, feed_readers)
- _assert_maker_itunes_block(true, true, maker_readers, feed_readers)
- _assert_maker_itunes_block(false, false, maker_readers, feed_readers)
- _assert_maker_itunes_block(nil, false, maker_readers, feed_readers)
- end
- end
-
- def _assert_maker_itunes_category(categories, maker_readers, feed_readers)
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- categories.each do |category|
- sub_target = target.itunes_categories
- if category.is_a?(Array)
- category.each do |sub_category|
- sub_target = sub_target.new_category
- sub_target.text = sub_category
- end
- else
- sub_target.new_category.text = category
- end
- end
- end
-
- target = chain_reader(rss20, feed_readers)
- actual_categories = target.itunes_categories.collect do |category|
- cat = category.text
- if category.itunes_categories.empty?
- cat
- else
- [cat, *category.itunes_categories.collect {|c| c.text}]
- end
- end
- assert_equal(categories, actual_categories)
- end
-
- def assert_maker_itunes_category(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- _assert_maker_itunes_category(["Audio Blogs"],
- maker_readers, feed_readers)
- _assert_maker_itunes_category([["Arts & Entertainment", "Games"]],
- maker_readers, feed_readers)
- _assert_maker_itunes_category([["Arts & Entertainment", "Games"],
- ["Technology", "Computers"],
- "Audio Blogs"],
- maker_readers, feed_readers)
- end
- end
-
- def assert_maker_itunes_image(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- url = "http://example.com/podcasts/everything/AllAboutEverything.jpg"
-
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- target.itunes_image = url
- end
-
- target = chain_reader(rss20, feed_readers)
- assert_not_nil(target.itunes_image)
- assert_equal(url, target.itunes_image.href)
- end
- end
-
- def _assert_maker_itunes_duration(hour, minute, second, value,
- maker_readers, feed_readers)
- _assert_maker_itunes_duration_by_value(hour, minute, second, value,
- maker_readers, feed_readers)
- _assert_maker_itunes_duration_by_hour_minute_second(hour, minute, second,
- value,
- maker_readers,
- feed_readers)
- end
-
- def _assert_maker_itunes_duration_by(hour, minute, second, value,
- maker_readers, feed_readers)
- expected_value = nil
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- expected_value = yield(target)
- assert_equal(expected_value, target.itunes_duration)
- target.itunes_duration do |duration|
- assert_equal([hour, minute, second, expected_value],
- [duration.hour, duration.minute,
- duration.second, duration.content])
- end
- end
- target = chain_reader(rss20, feed_readers)
- duration = target.itunes_duration
- assert_not_nil(duration)
- assert_equal([hour, minute, second, expected_value],
- [duration.hour, duration.minute,
- duration.second, duration.content])
- end
-
- def _assert_maker_itunes_duration_by_value(hour, minute, second, value,
- maker_readers, feed_readers)
- _assert_maker_itunes_duration_by(hour, minute, second, value,
- maker_readers, feed_readers) do |target|
- target.itunes_duration = value
- value
- end
- end
-
- def _assert_maker_itunes_duration_by_hour_minute_second(hour, minute, second,
- value,
- maker_readers,
- feed_readers)
- _assert_maker_itunes_duration_by(hour, minute, second, value,
- maker_readers, feed_readers) do |target|
- target.itunes_duration do |duration|
- duration.hour = hour
- duration.minute = minute
- duration.second = second
- end
- value.split(":").collect {|v| "%02d" % v.to_i}.join(":")
- end
- end
-
- def _assert_maker_itunes_duration_invalid_value(value, maker_readers)
- assert_raise(ArgumentError) do
- ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- target.itunes_duration = value
- end
- end
- end
-
- def assert_maker_itunes_duration(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- _assert_maker_itunes_duration(7, 14, 5, "07:14:05", maker_readers,
- feed_readers)
- _assert_maker_itunes_duration(7, 14, 5, "7:14:05", maker_readers,
- feed_readers)
- _assert_maker_itunes_duration(0, 4, 55, "04:55", maker_readers,
- feed_readers)
- _assert_maker_itunes_duration(0, 4, 5, "4:05", maker_readers,
- feed_readers)
- _assert_maker_itunes_duration(0, 0, 5, "0:05", maker_readers,
- feed_readers)
- _assert_maker_itunes_duration_by_value(0, 5, 15, "315", maker_readers,
- feed_readers)
- _assert_maker_itunes_duration_by_value(1, 0, 1, "3601", maker_readers,
- feed_readers)
-
- _assert_maker_itunes_duration_invalid_value("09:07:14:05", maker_readers)
- _assert_maker_itunes_duration_invalid_value("10:5", maker_readers)
- _assert_maker_itunes_duration_invalid_value("10:03:5", maker_readers)
- _assert_maker_itunes_duration_invalid_value("10:3:05", maker_readers)
-
- _assert_maker_itunes_duration_invalid_value("xx:xx:xx", maker_readers)
-
- _assert_maker_itunes_duration_invalid_value("", maker_readers)
- end
- end
-
- def _assert_maker_itunes_explicit(explicit, value,
- maker_readers, feed_readers)
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- target.itunes_explicit = value
- assert_equal(explicit, target.itunes_explicit?)
- end
- target = chain_reader(rss20, feed_readers)
- assert_equal(value, target.itunes_explicit)
- assert_equal(explicit, target.itunes_explicit?)
- end
-
- def assert_maker_itunes_explicit(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- _assert_maker_itunes_explicit(true, "explicit",
- maker_readers, feed_readers)
- _assert_maker_itunes_explicit(true, "yes",
- maker_readers, feed_readers)
- _assert_maker_itunes_explicit(true, "true",
- maker_readers, feed_readers)
- _assert_maker_itunes_explicit(false, "clean",
- maker_readers, feed_readers)
- _assert_maker_itunes_explicit(false, "no",
- maker_readers, feed_readers)
- _assert_maker_itunes_explicit(false, "false",
- maker_readers, feed_readers)
- _assert_maker_itunes_explicit(nil, "invalid",
- maker_readers, feed_readers)
- end
- end
-
- def _assert_maker_itunes_keywords(keywords, value,
- maker_readers, feed_readers)
- _assert_maker_itunes_keywords_by_value(keywords, value,
- maker_readers, feed_readers)
- _assert_maker_itunes_keywords_by_keywords(keywords, maker_readers,
- feed_readers)
- end
-
- def _assert_maker_itunes_keywords_by(keywords, maker_readers, feed_readers)
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- yield(target)
- end
- assert_nothing_raised do
- rss20 = ::RSS::Parser.parse(rss20.to_s)
- end
- target = chain_reader(rss20, feed_readers)
- assert_equal(keywords, target.itunes_keywords)
- end
-
- def _assert_maker_itunes_keywords_by_value(keywords, value,
- maker_readers, feed_readers)
- _assert_maker_itunes_keywords_by(keywords, maker_readers,
- feed_readers) do |target|
- target.itunes_keywords = value
- end
- end
-
- def _assert_maker_itunes_keywords_by_keywords(keywords,
- maker_readers, feed_readers)
- _assert_maker_itunes_keywords_by(keywords, maker_readers,
- feed_readers) do |target|
- target.itunes_keywords = keywords
- end
- end
-
- def assert_maker_itunes_keywords(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- _assert_maker_itunes_keywords(["salt"], "salt",
- maker_readers, feed_readers)
- _assert_maker_itunes_keywords(["salt"], " salt ",
- maker_readers, feed_readers)
- _assert_maker_itunes_keywords(["salt", "pepper", "shaker", "exciting"],
- "salt, pepper, shaker, exciting",
- maker_readers, feed_readers)
- _assert_maker_itunes_keywords(["metric", "socket", "wrenches",
- "toolsalt"],
- "metric, socket, wrenches, toolsalt",
- maker_readers, feed_readers)
- _assert_maker_itunes_keywords(["olitics", "red", "blue", "state"],
- "olitics, red, blue, state",
- maker_readers, feed_readers)
- end
- end
-
- def assert_maker_itunes_new_feed_url(maker_readers, feed_readers=nil)
- feed_readers ||= maker_readers
- url = "http://newlocation.com/example.rss"
-
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- target.itunes_new_feed_url = url
- end
- target = chain_reader(rss20, feed_readers)
- assert_equal(url, target.itunes_new_feed_url)
- end
-
- def _assert_maker_itunes_owner(name, email, maker_readers, feed_readers)
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- owner = target.itunes_owner
- owner.itunes_name = name
- owner.itunes_email = email
- end
- owner = chain_reader(rss20, feed_readers).itunes_owner
- if name.nil? and email.nil?
- assert_nil(owner)
- else
- assert_not_nil(owner)
- assert_equal(name, owner.itunes_name)
- assert_equal(email, owner.itunes_email)
- end
- end
-
- def assert_maker_itunes_owner(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- _assert_maker_itunes_owner("John Doe", "john.doe@example.com",
- maker_readers, feed_readers)
-
- not_set_name = (["maker"] + maker_readers + ["itunes_owner"]).join(".")
- assert_not_set_error(not_set_name, ["itunes_name"]) do
- _assert_maker_itunes_owner(nil, "john.doe@example.com",
- maker_readers, feed_readers)
- end
- assert_not_set_error(not_set_name, ["itunes_email"]) do
- _assert_maker_itunes_owner("John Doe", nil,
- maker_readers, feed_readers)
- end
-
- _assert_maker_itunes_owner(nil, nil, maker_readers, feed_readers)
- end
- end
-
- def _assert_maker_itunes_subtitle(subtitle, maker_readers, feed_readers)
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- target.itunes_subtitle = subtitle
- end
-
- target = chain_reader(rss20, feed_readers)
- assert_equal(subtitle, target.itunes_subtitle)
- end
-
- def assert_maker_itunes_subtitle(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- _assert_maker_itunes_subtitle("A show about everything",
- maker_readers, feed_readers)
- _assert_maker_itunes_subtitle("A short primer on table spices",
- maker_readers, feed_readers)
- _assert_maker_itunes_subtitle("Comparing socket wrenches is fun!",
- maker_readers, feed_readers)
- _assert_maker_itunes_subtitle("Red + Blue != Purple",
- maker_readers, feed_readers)
- end
- end
-
- def _assert_maker_itunes_summary(summary, maker_readers, feed_readers)
- rss20 = ::RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- target = chain_reader(maker, maker_readers)
- target.itunes_summary = summary
- end
-
- target = chain_reader(rss20, feed_readers)
- assert_equal(summary, target.itunes_summary)
- end
-
- def assert_maker_itunes_summary(maker_readers, feed_readers=nil)
- _wrap_assertion do
- feed_readers ||= maker_readers
- _assert_maker_itunes_summary("All About Everything is a show about " +
- "everything. Each week we dive into any " +
- "subject known to man and talk about it " +
- "as much as we can. Look for our Podcast " +
- "in the iTunes Music Store",
- maker_readers, feed_readers)
- _assert_maker_itunes_summary("This week we talk about salt and pepper " +
- "shakers, comparing and contrasting pour " +
- "rates, construction materials, and " +
- "overall aesthetics. Come and join the " +
- "party!",
- maker_readers, feed_readers)
- _assert_maker_itunes_summary("This week we talk about metric vs. old " +
- "english socket wrenches. Which one is " +
- "better? Do you really need both? Get " +
- "all of your answers here.",
- maker_readers, feed_readers)
- _assert_maker_itunes_summary("This week we talk about surviving in a " +
- "Red state if you're a Blue person. Or " +
- "vice versa.",
- maker_readers, feed_readers)
- end
- end
- end
-end
diff --git a/test/rss/test_maker_slash.rb b/test/rss/test_maker_slash.rb
deleted file mode 100644
index 5e5761ab0f..0000000000
--- a/test/rss/test_maker_slash.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerSlash < TestCase
- def setup
- @elements = {
- "section" => "articles",
- "department" => "not-an-ocean-unless-there-are-lobsters",
- "comments" => 177,
- "hit_parades" => [177, 155, 105, 33, 6, 3, 0],
- }
- end
-
- def test_rss10
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- setup_dummy_item(maker)
- item = maker.items.last
- @elements.each do |name, value|
- item.send("slash_#{name}=", value)
- end
- end
-
- item = rss.items.last
- assert_not_nil(item)
- assert_slash_elements(item)
- end
-
- private
- def assert_slash_elements(target)
- super(@elements, target)
- end
- end
-end
diff --git a/test/rss/test_maker_sy.rb b/test/rss/test_maker_sy.rb
deleted file mode 100644
index 6f4d6f8390..0000000000
--- a/test/rss/test_maker_sy.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerSyndication < TestCase
-
- def setup
- @uri = "http://purl.org/rss/1.0/modules/syndication/"
-
- t = Time.iso8601("2000-01-01T12:00:05+00:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
-
- @elements = {
- :updatePeriod => "hourly",
- :updateFrequency => "2",
- :updateBase => t,
- }
- end
-
- def test_rss10
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- set_elements(maker.channel)
- setup_dummy_item(maker)
- end
- assert_syndication(@elements, rss.channel)
- end
-
- private
- def accessor_name(name)
- "sy_#{name}"
- end
-
- def set_elements(target)
- @elements.each do |name, value|
- target.__send__("#{accessor_name(name)}=", value)
- end
- end
-
- end
-end
diff --git a/test/rss/test_maker_taxo.rb b/test/rss/test_maker_taxo.rb
deleted file mode 100644
index 9a19a52dc4..0000000000
--- a/test/rss/test_maker_taxo.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerTaxonomy < TestCase
-
- def setup
- @uri = "http://purl.org/rss/1.0/modules/taxonomy/"
-
- @resources = [
- "http://meerkat.oreillynet.com/?c=cat23",
- "http://meerkat.oreillynet.com/?c=47",
- "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
- ]
-
- @topics = [
- {
- :link => "http://meerkat.oreillynet.com/?c=cat23",
- :title => "Data: XML",
- :description => "A Meerkat channel",
- },
- {
- :link => "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
- :title => "XML",
- :subject => "XML",
- :description => "DMOZ category",
- :topics => [
- "http://meerkat.oreillynet.com/?c=cat23",
- "http://dmoz.org/Computers/Data_Formats/Markup_Languages/SGML/",
- "http://dmoz.org/Computers/Programming/Internet/",
- ]
- },
- ]
- end
-
- def test_rss10
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- set_topics(maker.channel)
-
- setup_dummy_item(maker)
- set_topics(maker.items.last)
-
- setup_taxo_topic(maker, @topics)
- end
- assert_equal(@resources, rss.channel.taxo_topics.resources)
- assert_equal(@resources, rss.items.last.taxo_topics.resources)
- assert_taxo_topic(@topics, rss)
- end
-
- def _test_date
- t1 = Time.iso8601("2000-01-01T12:00:05+00:00")
- t2 = Time.iso8601("2005-01-01T12:00:05+00:00")
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.date = t1
- maker.channel.dc_dates.new_date do |date|
- date.value = t2
- end
-
- setup_dummy_item(maker)
- item = maker.items.last
- item.date = t2
- item.dc_dates.new_date do |date|
- date.value = t1
- end
- end
- assert_equal([t1, t2], rss.channel.dc_dates.collect{|x| x.value})
- assert_equal([t2, t1], rss.items.last.dc_dates.collect{|x| x.value})
- end
-
- private
- def set_topics(target, resources=@resources)
- resources.each do |value|
- target.taxo_topics << value
- end
- end
- end
-end
diff --git a/test/rss/test_maker_trackback.rb b/test/rss/test_maker_trackback.rb
deleted file mode 100644
index b49e5c3f57..0000000000
--- a/test/rss/test_maker_trackback.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerTrackBack < TestCase
-
- def setup
- @uri = "http://madskills.com/public/xml/rss/module/trackback/"
-
- @elements = {
- :ping => "http://bar.com/tb.cgi?tb_id=rssplustrackback",
- :abouts => [
- "http://foo.com/trackback/tb.cgi?tb_id=20020923",
- "http://bar.com/trackback/tb.cgi?tb_id=20041114",
- ],
- }
- end
-
- def test_rss10
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- setup_dummy_item(maker)
- item = maker.items.last
- item.trackback_ping = @elements[:ping]
- @elements[:abouts].each do |about|
- item.trackback_abouts.new_about do |new_about|
- new_about.value = about
- end
- end
- end
- assert_trackback(@elements, rss.items.last)
- end
-
- private
- def accessor_name(name)
- "trackback_#{name}"
- end
- end
-end
diff --git a/test/rss/test_maker_xml-stylesheet.rb b/test/rss/test_maker_xml-stylesheet.rb
deleted file mode 100644
index 4563de9902..0000000000
--- a/test/rss/test_maker_xml-stylesheet.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestMakerXMLStyleSheet < TestCase
-
- def test_xml_stylesheet
- href = 'a.xsl'
- type = 'text/xsl'
- title = 'sample'
- media = 'printer'
- charset = 'UTF-8'
- alternate = 'yes'
-
- rss = RSS::Maker.make("1.0") do |maker|
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- xss.type = type
- xss.title = title
- xss.media = media
- xss.charset = charset
- xss.alternate = alternate
- end
-
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
- end
-
- xss = rss.xml_stylesheets.first
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- assert_equal(title, xss.title)
- assert_equal(media, xss.media)
- assert_equal(charset, xss.charset)
- assert_equal(alternate, xss.alternate)
-
-
- href = 'http://example.com/index.xsl'
- type = 'text/xsl'
- rss = RSS::Maker.make("1.0") do |maker|
- maker.xml_stylesheets.new_xml_stylesheet do |_xss|
- _xss.href = href
- end
-
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
- end
-
- xss = rss.xml_stylesheets.first
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- end
-
- def test_not_valid_xml_stylesheet
- href = 'xss.XXX'
- type = "text/xsl"
-
- rss = RSS::Maker.make("1.0") do |maker|
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- # xss.href = href
- xss.type = type
- end
-
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
- end
- assert(rss.xml_stylesheets.empty?)
-
- rss = RSS::Maker.make("1.0") do |maker|
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- # xss.type = type
- end
-
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
- end
- assert(rss.xml_stylesheets.empty?)
- end
-
- end
-end
diff --git a/test/rss/test_parser.rb b/test/rss/test_parser.rb
deleted file mode 100644
index 19344a0643..0000000000
--- a/test/rss/test_parser.rb
+++ /dev/null
@@ -1,121 +0,0 @@
-# frozen_string_literal: false
-require "tempfile"
-
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/dublincore"
-
-module RSS
- class TestParser < TestCase
- def setup
- @_default_parser = Parser.default_parser
- @rss10 = make_RDF(<<-EOR)
-#{make_channel}
-#{make_item}
-#{make_textinput}
-#{make_image}
-EOR
- @rss_tmp = Tempfile.new(%w"rss10- .rdf")
- @rss_tmp.print(@rss10)
- @rss_tmp.close
- @rss_file = @rss_tmp.path
- end
-
- def teardown
- Parser.default_parser = @_default_parser
- @rss_tmp.close(true)
- end
-
- def test_default_parser
- assert_nothing_raised do
- Parser.default_parser = RSS::AVAILABLE_PARSERS.first
- end
-
- assert_raise(RSS::NotValidXMLParser) do
- Parser.default_parser = RSS::Parser
- end
- end
-
- def test_parse
- assert_not_nil(RSS::Parser.parse(@rss_file))
-
- garbage_rss_file = @rss_file + "-garbage"
- if RSS::Parser.default_parser.name == "RSS::XMLParserParser"
- assert_raise(RSS::NotWellFormedError) do
- RSS::Parser.parse(garbage_rss_file)
- end
- else
- assert_nil(RSS::Parser.parse(garbage_rss_file))
- end
- end
-
- def test_parse_tag_includes_hyphen
- assert_nothing_raised do
- RSS::Parser.parse(make_RDF(<<-EOR))
-<xCal:x-calconnect-venue xmlns:xCal="urn:ietf:params:xml:ns:xcal" />
-#{make_channel}
-#{make_item}
-#{make_textinput}
-#{make_image}
-EOR
- end
- end
-
- def test_parse_option_validate_nil
- assert_raise(RSS::MissingTagError) do
- RSS::Parser.parse(make_RDF(<<-RDF), :validate => nil)
- RDF
- end
- end
-
- def test_parse_option_validate_true
- assert_raise(RSS::MissingTagError) do
- RSS::Parser.parse(make_RDF(<<-RDF), :validate => true)
- RDF
- end
- end
-
- def test_parse_option_validate_false
- rdf = RSS::Parser.parse(make_RDF(<<-RDF), :validate => false)
- RDF
- assert_nil(rdf.channel)
- end
-
- def test_parse_option_ignore_unknown_element_nil
- assert_nothing_raised do
- RSS::Parser.parse(make_RDF(<<-RDF), :ignore_unknown_element => nil)
-<unknown/>
-#{make_channel}
-#{make_item}
-#{make_textinput}
-#{make_image}
- RDF
- end
- end
-
- def test_parse_option_ignore_unknown_element_true
- assert_nothing_raised do
- RSS::Parser.parse(make_RDF(<<-RDF), :ignore_unknown_element => true)
-<unknown/>
-#{make_channel}
-#{make_item}
-#{make_textinput}
-#{make_image}
- RDF
- end
- end
-
- def test_parse_option_ignore_unknown_element_false
- assert_raise(RSS::NotExpectedTagError) do
- RSS::Parser.parse(make_RDF(<<-RDF), :ignore_unknown_element => false)
-<unknown/>
-#{make_channel}
-#{make_item}
-#{make_textinput}
-#{make_image}
- RDF
- end
- end
- end
-end
diff --git a/test/rss/test_parser_1.0.rb b/test/rss/test_parser_1.0.rb
deleted file mode 100644
index f7be5153af..0000000000
--- a/test/rss/test_parser_1.0.rb
+++ /dev/null
@@ -1,529 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/dublincore"
-
-module RSS
- class TestParser10 < TestCase
- def test_RDF
- assert_ns("", RDF::URI) do
- Parser.parse(<<-EOR)
-#{make_xmldecl}
-<RDF/>
-EOR
- end
-
- assert_ns("", RDF::URI) do
- Parser.parse(<<-EOR)
-#{make_xmldecl}
-<RDF xmlns="hoge"/>
-EOR
- end
-
- assert_ns("rdf", RDF::URI) do
- Parser.parse(<<-EOR)
-#{make_xmldecl}
-<rdf:RDF xmlns:rdf="hoge"/>
-EOR
- end
-
- assert_parse(<<-EOR, :missing_tag, "channel", "RDF")
-#{make_xmldecl}
-<rdf:RDF xmlns:rdf="#{RSS::RDF::URI}"/>
-EOR
-
- assert_parse(<<-EOR, :missing_tag, "channel", "RDF")
-#{make_xmldecl}
-<RDF xmlns="#{RSS::RDF::URI}"/>
-EOR
-
- assert_parse(<<-EOR, :missing_tag, "channel", "RDF")
-#{make_xmldecl}
-<RDF xmlns="#{RSS::RDF::URI}"/>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
-#{make_channel}
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
-#{make_channel}
-#{make_image}
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
-#{make_channel}
-#{make_textinput}
-EOR
-
- assert_too_much_tag("image", "RDF") do
- Parser.parse(make_RDF(<<-EOR))
-#{make_channel}
-#{make_image}
-#{make_image}
-#{make_item}
-#{make_textinput}
-EOR
- end
-
- assert_parse(make_RDF(<<-EOR), :nothing_raised)
-#{make_channel}
-#{make_item}
-#{make_image}
-#{make_textinput}
-EOR
-
- assert_parse(make_RDF(<<-EOR), :nothing_raised)
-#{make_channel}
-#{make_item}
-#{make_textinput}
-#{make_image}
-EOR
-
- assert_parse(make_RDF(<<-EOR), :nothing_raised)
-#{make_channel}
-#{make_image}
-#{make_item}
-EOR
-
- assert_parse(make_RDF(<<-EOR), :nothing_raised)
-#{make_channel}
-#{make_image}
-#{make_item}
-#{make_textinput}
-EOR
-
- 1.step(15, 3) do |i|
- rss = make_RDF() do
- res = make_channel
- i.times { res << make_item }
- res
- end
- assert_parse(rss, :nothing_raised)
- end
- end
-
- def test_undefined_entity
- return unless RSS::Parser.default_parser.raise_for_undefined_entity?
- assert_parse(make_RDF(<<-EOR), :raises, RSS::NotWellFormedError)
-#{make_channel}
-#{make_image}
-<item rdf:about="#{RDF_ABOUT}">
- <title>#{TITLE_VALUE} &UNKNOWN_ENTITY;</title>
- <link>#{LINK_VALUE}</link>
- <description>#{DESCRIPTION_VALUE}</description>
-</item>
-#{make_textinput}
-EOR
- end
-
- def test_channel
- assert_parse(make_RDF(<<-EOR), :missing_attribute, "channel", "rdf:about")
-<channel />
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "channel")
-<channel rdf:about="http://example.com/"/>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "channel")
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
-</channel>
-EOR
-
- assert_parse(make_RDF(<<EOR), :missing_tag, "description", "channel")
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
- <link>http://example.com/</link>
-</channel>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "items", "channel")
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
- <link>http://example.com/</link>
- <description>hogehoge</description>
-</channel>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_attribute, "image", "rdf:resource")
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
- <link>http://example.com/</link>
- <description>hogehoge</description>
- <image/>
-</channel>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "items", "channel")
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
- <link>http://example.com/</link>
- <description>hogehoge</description>
- <image rdf:resource="http://example.com/hoge.png" />
-</channel>
-EOR
-
- rss = make_RDF(<<-EOR)
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
- <link>http://example.com/</link>
- <description>hogehoge</description>
- <image rdf:resource="http://example.com/hoge.png" />
- <items/>
-</channel>
-EOR
-
- assert_missing_tag("Seq", "items") do
- Parser.parse(rss)
- end
-
- assert_missing_tag("item", "RDF") do
- Parser.parse(rss, false).validate
- end
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
- <link>http://example.com/</link>
- <description>hogehoge</description>
- <image rdf:resource="http://example.com/hoge.png" />
- <items>
- <rdf:Seq>
- </rdf:Seq>
- </items>
-</channel>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_attribute, "textinput", "rdf:resource")
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
- <link>http://example.com/</link>
- <description>hogehoge</description>
- <image rdf:resource="http://example.com/hoge.png" />
- <items>
- <rdf:Seq>
- </rdf:Seq>
- </items>
- <textinput/>
-</channel>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
- <link>http://example.com/</link>
- <description>hogehoge</description>
- <image rdf:resource="http://example.com/hoge.png" />
- <items>
- <rdf:Seq>
- </rdf:Seq>
- </items>
- <textinput rdf:resource="http://example.com/search" />
-</channel>
-EOR
- end
-
- def test_rdf_li
- rss = make_RDF(<<-EOR)
-<channel rdf:about="http://example.com/">
- <title>hoge</title>
- <link>http://example.com/</link>
- <description>hogehoge</description>
- <image rdf:resource="http://example.com/hoge.png" />
- <items>
- <rdf:Seq>
- <rdf:li \#{rdf_li_attr}/>
- </rdf:Seq>
- </items>
- <textinput rdf:resource="http://example.com/search" />
-</channel>
-#{make_item}
-EOR
-
- source = Proc.new do |rdf_li_attr|
- eval(%Q[%Q[#{rss}]], binding)
- end
-
- attr = %q[resource="http://example.com/hoge"]
- assert_parse(source.call(attr), :nothing_raised)
-
- attr = %q[rdf:resource="http://example.com/hoge"]
- assert_parse(source.call(attr), :nothing_raised)
-
- assert_parse(source.call(""), :missing_attribute, "li", "resource")
- end
-
- def test_image
- assert_parse(make_RDF(<<-EOR), :missing_attribute, "image", "rdf:about")
-#{make_channel}
-<image>
-</image>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "image")
-#{make_channel}
-<image rdf:about="http://example.com/hoge.png">
-</image>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "url", "image")
-#{make_channel}
-<image rdf:about="http://example.com/hoge.png">
- <title>hoge</title>
-</image>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "image")
-#{make_channel}
-<image rdf:about="http://example.com/hoge.png">
- <title>hoge</title>
- <url>http://example.com/hoge.png</url>
-</image>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "item", "RDF")
-#{make_channel}
-<image rdf:about="http://example.com/hoge.png">
- <title>hoge</title>
- <url>http://example.com/hoge.png</url>
- <link>http://example.com/</link>
-</image>
-EOR
-
- rss = make_RDF(<<-EOR)
-#{make_channel}
-<image rdf:about="http://example.com/hoge.png">
- <link>http://example.com/</link>
- <url>http://example.com/hoge.png</url>
- <title>hoge</title>
-</image>
-EOR
-
- assert_missing_tag("item", "RDF") do
- Parser.parse(rss)
- end
-
- assert_missing_tag("item", "RDF") do
- Parser.parse(rss, false).validate
- end
- end
-
- def test_item
- assert_parse(make_RDF(<<-EOR), :missing_attribute, "item", "rdf:about")
-#{make_channel}
-#{make_image}
-<item>
-</item>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "item")
-#{make_channel}
-#{make_image}
-<item rdf:about="http://example.com/hoge.html">
-</item>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "item")
-#{make_channel}
-#{make_image}
-<item rdf:about="http://example.com/hoge.html">
- <title>hoge</title>
-</item>
-EOR
-
- assert_too_much_tag("title", "item") do
- Parser.parse(make_RDF(<<-EOR))
-#{make_channel}
-#{make_image}
-<item rdf:about="http://example.com/hoge.html">
- <title>hoge</title>
- <title>hoge</title>
- <link>http://example.com/hoge.html</link>
-</item>
-EOR
- end
-
- assert_parse(make_RDF(<<-EOR), :nothing_raised)
-#{make_channel}
-#{make_image}
-<item rdf:about="http://example.com/hoge.html">
- <title>hoge</title>
- <link>http://example.com/hoge.html</link>
-</item>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :nothing_raised)
-#{make_channel}
-#{make_image}
-<item rdf:about="http://example.com/hoge.html">
- <title>hoge</title>
- <link>http://example.com/hoge.html</link>
- <description>hogehoge</description>
-</item>
-EOR
- end
-
- def test_textinput
- assert_parse(make_RDF(<<-EOR), :missing_attribute, "textinput", "rdf:about")
-#{make_channel}
-#{make_image}
-#{make_item}
-<textinput>
-</textinput>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "title", "textinput")
-#{make_channel}
-#{make_image}
-#{make_item}
-<textinput rdf:about="http://example.com/search.html">
-</textinput>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "description", "textinput")
-#{make_channel}
-#{make_image}
-#{make_item}
-<textinput rdf:about="http://example.com/search.html">
- <title>hoge</title>
-</textinput>
-EOR
-
- assert_too_much_tag("title", "textinput") do
- Parser.parse(make_RDF(<<-EOR))
-#{make_channel}
-#{make_image}
-#{make_item}
-<textinput rdf:about="http://example.com/search.html">
- <title>hoge</title>
- <title>hoge</title>
- <description>hogehoge</description>
-</textinput>
-EOR
- end
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "name", "textinput")
-#{make_channel}
-#{make_image}
-#{make_item}
-<textinput rdf:about="http://example.com/search.html">
- <title>hoge</title>
- <description>hogehoge</description>
-</textinput>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :missing_tag, "link", "textinput")
-#{make_channel}
-#{make_image}
-#{make_item}
-<textinput rdf:about="http://example.com/search.html">
- <title>hoge</title>
- <description>hogehoge</description>
- <name>key</name>
-</textinput>
-EOR
-
- assert_parse(make_RDF(<<-EOR), :nothing_raised)
-#{make_channel}
-#{make_image}
-#{make_item}
-<textinput rdf:about="http://example.com/search.html">
- <title>hoge</title>
- <description>hogehoge</description>
- <name>key</name>
- <link>http://example.com/search.html</link>
-</textinput>
-EOR
- end
-
- def test_ignore
- name = "a"
- rss = make_RDF(<<-EOR)
-#{make_channel}
-#{make_item}
-<#{name}/>
-EOR
- assert_not_expected_tag(name, ::RSS::URI, "RDF") do
- Parser.parse(rss, true, false)
- end
-
- uri = ""
- name = "a"
- rss = make_RDF(<<-EOR)
-#{make_channel}
-#{make_item}
-<#{name} xmlns=""/>
-EOR
- assert_parse(rss, :nothing_raised)
- assert_not_expected_tag(name, uri, "RDF") do
- Parser.parse(rss, true, false)
- end
-
- uri = "http://example.com/"
- name = "a"
- rss = make_RDF(<<-EOR)
-#{make_channel}
-#{make_item}
-<x:#{name} xmlns:x="#{uri}"/>
-EOR
- assert_parse(rss, :nothing_raised)
- assert_not_expected_tag(name, uri, "RDF") do
- Parser.parse(rss, true, false)
- end
-
- uri = ::RSS::URI
- name = "a"
- rss = make_RDF(<<-EOR)
-#{make_channel}
-#{make_item}
-#{make_image("<#{name}/>")}
-EOR
- assert_parse(rss, :nothing_raised)
- assert_not_expected_tag(name, uri, "image") do
- Parser.parse(rss, true, false)
- end
-
- uri = CONTENT_URI
- name = "encoded"
- elem = "<#{name} xmlns='#{uri}'/>"
- rss = make_RDF(<<-EOR)
-#{make_channel}
-#{make_item}
-#{make_image(elem)}
-EOR
- assert_parse(rss, :nothing_raised)
- assert_not_expected_tag(name, uri, "image") do
- Parser.parse(rss, true, false)
- end
- end
-
- def test_unknown_duplicated_element
- xmlns = {"test" => "http://localhost/test"}
- assert_parse(make_RDF(<<-EOR, xmlns), :nothing_raised)
- #{make_channel("<test:string/>")}
- #{make_item}
- #{make_image}
- EOR
- end
-
- def test_unknown_case_insensitive_duplicated_element
- xmlns = {
- "foaf" => "http://xmlns.com/foaf/0.1/",
- "dc" => "http://purl.org/dc/elements/1.1/",
- }
- assert_parse(make_RDF(<<-EOR, xmlns), :nothing_raised)
- #{make_channel}
- #{make_item}
- #{make_image}
- <foaf:Image rdf:about="http://example.com/myself.png">
- <dc:title>Myself</dc:title>
- <dc:link>http://example.com/</dc:link>
- </foaf:Image>
- EOR
- end
- end
-end
-
diff --git a/test/rss/test_parser_2.0.rb b/test/rss/test_parser_2.0.rb
deleted file mode 100644
index ac7a67b8b1..0000000000
--- a/test/rss/test_parser_2.0.rb
+++ /dev/null
@@ -1,123 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/2.0"
-
-module RSS
- class TestParser20 < TestCase
- def test_rss20
- assert_parse(make_rss20(<<-EOR), :missing_tag, "channel", "rss")
-EOR
-
- assert_parse(make_rss20(<<-EOR), :nothing_raised)
-#{make_channel20("")}
-EOR
- end
-
- def test_cloud20
- attrs = [
- ["domain", CLOUD_DOMAIN],
- ["port", CLOUD_PORT],
- ["path", CLOUD_PATH],
- ["registerProcedure", CLOUD_REGISTER_PROCEDURE],
- ["protocol", CLOUD_PROTOCOL],
- ]
-
- (attrs.size + 1).times do |i|
- missing_attr = attrs[i]
- if missing_attr
- meth = :missing_attribute
- args = ["cloud", missing_attr[0]]
- else
- meth = :nothing_raised
- args = []
- end
-
- cloud_attrs = []
- attrs.each_with_index do |attr, j|
- unless i == j
- cloud_attrs << %Q[#{attr[0]}="#{attr[1]}"]
- end
- end
-
- assert_parse(make_rss20(<<-EOR), meth, *args)
-#{make_channel20(%Q[<cloud #{cloud_attrs.join("\n")}/>])}
-EOR
- end
- end
-
- def test_source20
- assert_parse(make_rss20(<<-EOR), :missing_attribute, "source", "url")
-#{make_channel20(make_item20(%Q[<source>Example</source>]))}
-EOR
-
- assert_parse(make_rss20(<<-EOR), :nothing_raised)
-#{make_channel20(make_item20(%Q[<source url="http://example.com/" />]))}
-EOR
-
- assert_parse(make_rss20(<<-EOR), :nothing_raised)
-#{make_channel20(make_item20(%Q[<source url="http://example.com/">Example</source>]))}
-EOR
- end
-
- def test_enclosure20
- attrs = [
- ["url", ENCLOSURE_URL],
- ["length", ENCLOSURE_LENGTH],
- ["type", ENCLOSURE_TYPE],
- ]
-
- (attrs.size + 1).times do |i|
- missing_attr = attrs[i]
- if missing_attr
- meth = :missing_attribute
- args = ["enclosure", missing_attr[0]]
- else
- meth = :nothing_raised
- args = []
- end
-
- enclosure_attrs = []
- attrs.each_with_index do |attr, j|
- unless i == j
- enclosure_attrs << %Q[#{attr[0]}="#{attr[1]}"]
- end
- end
-
- assert_parse(make_rss20(<<-EOR), meth, *args)
-#{make_channel20(%Q[
-#{make_item20(%Q[
-<enclosure
- #{enclosure_attrs.join("\n")} />
- ])}
- ])}
-EOR
- end
- end
-
- def test_category20
- values = [nil, CATEGORY_DOMAIN]
- values.each do |value|
- domain = ""
- domain << %Q[domain="#{value}"] if value
-
- ["", "Example Text"].each do |text|
- rss_src = make_rss20(<<-EOR)
-#{make_channel20(%Q[
-#{make_item20(%Q[
-<category #{domain}>#{text}</category>
- ])}
- ])}
-EOR
- assert_parse(rss_src, :nothing_raised)
-
- rss = RSS::Parser.parse(rss_src)
- category = rss.items.last.categories.first
- assert_equal(value, category.domain)
- assert_equal(text, category.content)
- end
- end
- end
- end
-end
-
diff --git a/test/rss/test_parser_atom_entry.rb b/test/rss/test_parser_atom_entry.rb
deleted file mode 100644
index 4f54ba3cad..0000000000
--- a/test/rss/test_parser_atom_entry.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/atom"
-
-module RSS
- class TestParserAtom < TestCase
- def test_entry_validation
- assert_ns("", Atom::URI) do
- Parser.parse(<<-EOA)
-<entry/>
-EOA
- end
-
- assert_ns("", Atom::URI) do
- Parser.parse(<<-EOA)
-<entry xmlns="hoge"/>
-EOA
- end
-
- assert_parse(<<-EOA, :missing_tag, "id", "entry") do
-<entry xmlns="#{Atom::URI}"/>
-EOA
- end
-
- assert_parse(<<-EOA, :missing_tag, "title", "entry") do
-<entry xmlns="#{Atom::URI}">
- <id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
-</entry>
-EOA
- end
-
- assert_parse(<<-EOA, :missing_tag, "updated", "entry") do
-<entry xmlns="#{Atom::URI}">
- <id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
- <title>Example Entry</title>
-</entry>
-EOA
- end
-
- assert_parse(<<-EOA, :missing_tag, "author", "entry") do
-<entry xmlns="#{Atom::URI}">
- <id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
- <title>Example Entry</title>
- <updated>2003-10-10T18:30:02Z</updated>
-</entry>
-EOA
- end
-
- assert_parse(<<-EOA, :nothing_raised) do
-<entry xmlns="#{Atom::URI}">
- <id>urn:uuid:506e336c-a26e-4457-917b-b89dca7ae746</id>
- <title>Example Entry</title>
- <updated>2003-10-10T18:30:02Z</updated>
- <author>
- <name>A person</name>
- </author>
-</entry>
-EOA
- end
- end
-
- def test_entry
- entry = RSS::Parser.parse(<<-EOA)
-<?xml version="1.0" encoding="utf-8"?>
-<entry xmlns="http://www.w3.org/2005/Atom">
- <author>
- <name>A person</name>
- </author>
- <title>Atom-Powered Robots Run Amok</title>
- <link href="http://example.org/2003/12/13/atom03"/>
- <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
- <updated>2003-12-13T18:30:02Z</updated>
- <summary>Some text.</summary>
-</entry>
-EOA
- assert_not_nil(entry)
- assert_equal("Atom-Powered Robots Run Amok", entry.title.content)
- assert_equal("http://example.org/2003/12/13/atom03", entry.link.href)
- assert_equal("urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a",
- entry.id.content)
- assert_equal(Time.parse("2003-12-13T18:30:02Z"), entry.updated.content)
- assert_equal("Some text.", entry.summary.content)
- end
-
- def test_entry_author
- assert_atom_person("author", method(:make_entry_document)) do |entry|
- assert_equal(2, entry.authors.size)
- entry.authors.last
- end
- end
-
- def test_entry_category
- assert_atom_category(method(:make_entry_document)) do |entry|
- assert_equal(1, entry.categories.size)
- entry.category
- end
- end
-
- def test_entry_content_text
- assert_atom_content(method(:make_entry_document)) do |entry|
- entry.content
- end
- end
-
- def test_entry_contributor
- assert_atom_person("contributor", method(:make_entry_document)) do |entry|
- assert_equal(1, entry.contributors.size)
- entry.contributor
- end
- end
-
- def test_entry_id
- entry = RSS::Parser.parse(make_entry_document)
- assert_equal(ENTRY_ID, entry.id.content)
- end
-
- def test_entry_link
- assert_atom_link(method(:make_entry_document)) do |entry|
- assert_equal(1, entry.links.size)
- entry.link
- end
- end
-
- def test_published
- generator = method(:make_entry_document)
- assert_atom_date_construct("published", generator) do |entry|
- entry.published
- end
- end
-
- def test_entry_rights
- generator = method(:make_entry_document)
- assert_atom_text_construct("rights", generator) do |entry|
- entry.rights
- end
- end
-
- def test_entry_source
- generator = method(:make_entry_document_with_open_source)
- assert_atom_source(generator) do |entry|
- assert_not_nil(entry.source)
- entry.source
- end
- end
-
- def test_entry_summary
- generator = method(:make_entry_document)
- assert_atom_text_construct("summary", generator) do |entry|
- entry.summary
- end
- end
-
- def test_entry_title
- entry = RSS::Parser.parse(make_entry_document)
- assert_equal(ENTRY_TITLE, entry.title.content)
- end
-
- def test_entry_updated
- entry = RSS::Parser.parse(make_entry_document)
- assert_equal(Time.parse(ENTRY_UPDATED), entry.updated.content)
- end
- end
-end
diff --git a/test/rss/test_parser_atom_feed.rb b/test/rss/test_parser_atom_feed.rb
deleted file mode 100644
index 626062d23a..0000000000
--- a/test/rss/test_parser_atom_feed.rb
+++ /dev/null
@@ -1,277 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/atom"
-
-module RSS
- class TestParserAtomFeed < TestCase
- def test_feed_validation
- assert_ns("", Atom::URI) do
- Parser.parse(<<-EOA)
-<feed/>
-EOA
- end
-
- assert_ns("", Atom::URI) do
- Parser.parse(<<-EOA)
-<feed xmlns="hoge"/>
-EOA
- end
-
- assert_parse(<<-EOA, :missing_tag, "id", "feed") do
-<feed xmlns="#{Atom::URI}"/>
-EOA
- end
-
- assert_parse(<<-EOA, :missing_tag, "title", "feed") do
-<feed xmlns="#{Atom::URI}">
- <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
-</feed>
-EOA
- end
-
- assert_parse(<<-EOA, :missing_tag, "updated", "feed") do
-<feed xmlns="#{Atom::URI}">
- <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
- <title>Example Feed</title>
-</feed>
-EOA
- end
-
- assert_parse(<<-EOA, :missing_tag, "author", "feed") do
-<feed xmlns="#{Atom::URI}">
- <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
- <title>Example Feed</title>
- <updated>2003-12-13T18:30:02Z</updated>
-</feed>
-EOA
- end
-
- assert_parse(<<-EOA, :nothing_raised) do
-<feed xmlns="#{Atom::URI}">
- <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
- <title>Example Feed</title>
- <updated>2003-12-13T18:30:02Z</updated>
- <author>
- <name>A person</name>
- </author>
-</feed>
-EOA
- end
- end
-
- def test_lang
- feed = RSS::Parser.parse(<<-EOA)
-<feed xmlns="#{Atom::URI}" xml:lang="ja">
- <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
- <title xml:lang="en">Example Feed</title>
- <updated>2003-12-13T18:30:02Z</updated>
- <author xml:lang="en">
- <name>A person</name>
- </author>
-</feed>
-EOA
-
- assert_equal("ja", feed.lang)
- assert_equal("ja", feed.id.lang)
- assert_equal("en", feed.title.lang)
- assert_equal("ja", feed.updated.lang)
- assert_equal("en", feed.author.lang)
- assert_equal("en", feed.author.name.lang)
- end
-
- def test_base
- feed = RSS::Parser.parse(<<-EOA)
-<feed xmlns="#{Atom::URI}" xml:base="http://example.com/">
- <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
- <title xml:lang="en">Example Feed</title>
- <updated>2003-12-13T18:30:02Z</updated>
- <generator uri="generator">Generator</generator>
- <link hreflang="ja" href="http://example.org/link1"/>
- <link hreflang="en" href="link2"/>
- <link hreflang="fr" xml:base="http://example.net/" href="link3"/>
- <author>
- <name>A person</name>
- <uri>person</uri>
- </author>
-</feed>
-EOA
-
- assert_equal("http://example.com/", feed.base)
- assert_equal("http://example.com/", feed.id.base)
- assert_equal("http://example.com/", feed.title.base)
- assert_equal("http://example.com/", feed.updated.base)
- assert_equal("http://example.com/", feed.generator.base)
- assert_equal("http://example.com/generator", feed.generator.uri)
-
- assert_equal("http://example.com/", feed.links[0].base)
- assert_equal("http://example.org/link1", feed.links[0].href)
- assert_equal("http://example.com/", feed.links[1].base)
- assert_equal("http://example.com/link2", feed.links[1].href)
- assert_equal("http://example.net/", feed.links[2].base)
- assert_equal("http://example.net/link3", feed.links[2].href)
- assert_equal("http://example.com/person", feed.author.uri.content)
- end
-
- def test_feed_author
- assert_atom_person("author", method(:make_feed)) do |feed|
- assert_equal(2, feed.authors.size)
- feed.authors[1]
- end
- end
-
- def test_entry_author
- generator = method(:make_feed_with_open_entry)
- assert_atom_person("author", generator) do |feed|
- assert_equal(1, feed.entries.size)
- assert_equal(1, feed.entry.authors.size)
- feed.entry.author
- end
- end
-
- def test_feed_category
- assert_atom_category(method(:make_feed)) do |feed|
- assert_equal(1, feed.categories.size)
- feed.category
- end
- end
-
- def test_entry_category
- assert_atom_category(method(:make_feed_with_open_entry)) do |feed|
- assert_equal(1, feed.entries.size)
- assert_equal(1, feed.entry.categories.size)
- feed.entry.category
- end
- end
-
- def test_entry_content
- assert_atom_content(method(:make_feed_with_open_entry)) do |feed|
- assert_equal(1, feed.entries.size)
- feed.entry.content
- end
- end
-
- def test_feed_contributor
- assert_atom_person("contributor", method(:make_feed)) do |feed|
- assert_equal(1, feed.contributors.size)
- feed.contributor
- end
- end
-
- def test_entry_contributor
- generator = method(:make_feed_with_open_entry)
- assert_atom_person("contributor", generator) do |feed|
- assert_equal(1, feed.entries.size)
- assert_equal(1, feed.entry.contributors.size)
- feed.entry.contributor
- end
- end
-
- def test_feed_generator
- assert_atom_generator(method(:make_feed)) do |feed|
- feed.generator
- end
- end
-
- def test_feed_icon
- assert_atom_icon(method(:make_feed)) do |feed|
- feed.icon
- end
- end
-
- def test_feed_id
- feed = RSS::Parser.parse(make_feed(''))
- assert_equal(FEED_ID, feed.id.content)
- end
-
- def test_entry_id
- feed = RSS::Parser.parse(make_feed(''))
- assert_equal(ENTRY_ID, feed.entry.id.content)
- end
-
- def test_feed_link
- assert_atom_link(method(:make_feed)) do |feed|
- assert_equal(1, feed.links.size)
- feed.link
- end
- end
-
- def test_entry_link
- assert_atom_link(method(:make_feed_with_open_entry)) do |feed|
- assert_equal(1, feed.entries.size)
- assert_equal(1, feed.entry.links.size)
- feed.entry.link
- end
- end
-
- def test_feed_logo
- assert_atom_logo(method(:make_feed)) do |feed|
- feed.logo
- end
- end
-
- def test_feed_rights
- assert_atom_text_construct("rights", method(:make_feed)) do |feed|
- feed.rights
- end
- end
-
- def test_entry_rights
- generator = method(:make_feed_with_open_entry)
- assert_atom_text_construct("rights", generator) do |feed|
- assert_equal(1, feed.entries.size)
- feed.entry.rights
- end
- end
-
- def test_entry_source
- assert_atom_source(method(:make_feed_with_open_entry_source)) do |feed|
- assert_equal(1, feed.entries.size)
- assert_not_nil(feed.entry.source)
- feed.entry.source
- end
- end
-
- def test_feed_subtitle
- assert_atom_text_construct("subtitle", method(:make_feed)) do |feed|
- feed.subtitle
- end
- end
-
- def test_feed_title
- feed = RSS::Parser.parse(make_feed(''))
- assert_equal(FEED_TITLE, feed.title.content)
- end
-
- def test_entry_title
- feed = RSS::Parser.parse(make_feed(''))
- assert_equal(ENTRY_TITLE, feed.entry.title.content)
- end
-
- def test_feed_updated
- feed = RSS::Parser.parse(make_feed(''))
- assert_equal(Time.parse(FEED_UPDATED), feed.updated.content)
- end
-
- def test_entry_updated
- feed = RSS::Parser.parse(make_feed(''))
- assert_equal(Time.parse(ENTRY_UPDATED), feed.entry.updated.content)
- end
-
- def test_entry_published
- generator = method(:make_feed_with_open_entry)
- assert_atom_date_construct("published", generator) do |feed|
- assert_equal(1, feed.entries.size)
- feed.entry.published
- end
- end
-
- def test_entry_summary
- generator = method(:make_feed_with_open_entry)
- assert_atom_text_construct("summary", generator) do |feed|
- assert_equal(1, feed.entries.size)
- feed.entry.summary
- end
- end
- end
-end
diff --git a/test/rss/test_setup_maker_0.9.rb b/test/rss/test_setup_maker_0.9.rb
deleted file mode 100644
index 4eae62417a..0000000000
--- a/test/rss/test_setup_maker_0.9.rb
+++ /dev/null
@@ -1,247 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestSetupMaker09 < TestCase
-
- def test_setup_maker_channel
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
- language = "ja"
- copyright = "foo"
- managingEditor = "bar"
- webMaster = "web master"
- rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))'
- docs = "http://foo.com/doc"
- skipDays = [
- "Sunday",
- "Monday",
- ]
- skipHours = [
- "0",
- "13",
- ]
- pubDate = Time.now
- lastBuildDate = Time.now
-
- rss = RSS::Maker.make("0.91") do |maker|
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- maker.channel.language = language
- maker.channel.copyright = copyright
- maker.channel.managingEditor = managingEditor
- maker.channel.webMaster = webMaster
- maker.channel.rating = rating
- maker.channel.docs = docs
- maker.channel.pubDate = pubDate
- maker.channel.lastBuildDate = lastBuildDate
-
- skipDays.each do |day|
- maker.channel.skipDays.new_day do |new_day|
- new_day.content = day
- end
- end
- skipHours.each do |hour|
- maker.channel.skipHours.new_hour do |new_hour|
- new_hour.content = hour
- end
- end
-
- setup_dummy_image(maker)
- end
-
- assert_not_set_error("maker.image", %w(title url)) do
- RSS::Maker.make("0.91") do |maker|
- rss.channel.setup_maker(maker)
- end
- end
-
- new_rss = RSS::Maker.make("0.91") do |maker|
- rss.channel.setup_maker(maker)
- setup_dummy_image(maker)
- end
- channel = new_rss.channel
-
- assert_equal(title, channel.title)
- assert_equal(link, channel.link)
- assert_equal(description, channel.description)
- assert_equal(language, channel.language)
- assert_equal(copyright, channel.copyright)
- assert_equal(managingEditor, channel.managingEditor)
- assert_equal(webMaster, channel.webMaster)
- assert_equal(rating, channel.rating)
- assert_equal(docs, channel.docs)
- assert_equal(pubDate, channel.pubDate)
- assert_equal(lastBuildDate, channel.lastBuildDate)
-
- skipDays.each_with_index do |day, i|
- assert_equal(day, channel.skipDays.days[i].content)
- end
- skipHours.each_with_index do |hour, i|
- assert_equal(hour.to_i, channel.skipHours.hours[i].content)
- end
-
- assert(channel.items.empty?)
- assert_nil(channel.textInput)
- end
-
- def test_setup_maker_image
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
- width = "144"
- height = "400"
- description = "an image"
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
-
- new_rss = RSS::Maker.make("0.91") do |maker|
- rss.channel.setup_maker(maker)
- rss.image.setup_maker(maker)
- end
-
- image = new_rss.image
- assert_equal(title, image.title)
- assert_equal(link, image.link)
- assert_equal(url, image.url)
- assert_equal(width.to_i, image.width)
- assert_equal(height.to_i, image.height)
- assert_equal(description, image.description)
- end
-
- def test_setup_maker_textinput
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com"
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
-
- new_rss = RSS::Maker.make("0.91") do |maker|
- rss.channel.setup_maker(maker)
- rss.image.setup_maker(maker)
- rss.textinput.setup_maker(maker)
- end
-
- textInput = new_rss.channel.textInput
- assert_equal(title, textInput.title)
- assert_equal(description, textInput.description)
- assert_equal(name, textInput.name)
- assert_equal(link, textInput.link)
- end
-
- def test_setup_maker_items(for_backward_compatibility=false)
- title = "TITLE"
- link = "http://hoge.com/"
- description = "text hoge fuga"
-
- item_size = 5
-
- rss = RSS::Maker.make("0.91") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{title}#{i}"
- item.link = "#{link}#{i}"
- item.description = "#{description}#{i}"
- end
- end
-
- setup_dummy_image(maker)
- end
-
- new_rss = RSS::Maker.make("0.91") do |maker|
- rss.channel.setup_maker(maker)
-
- rss.items.each do |item|
- if for_backward_compatibility
- item.setup_maker(maker)
- else
- item.setup_maker(maker.items)
- end
- end
-
- rss.image.setup_maker(maker)
- end
-
- assert_equal(item_size, new_rss.items.size)
- new_rss.items.each_with_index do |item, i|
- assert_equal("#{title}#{i}", item.title)
- assert_equal("#{link}#{i}", item.link)
- assert_equal("#{description}#{i}", item.description)
- end
- end
-
- def test_setup_maker_items_backward_compatibility
- test_setup_maker_items(true)
- end
-
- def test_setup_maker
- encoding = "EUC-JP"
- standalone = true
-
- href = 'a.xsl'
- type = 'text/xsl'
- title = 'sample'
- media = 'printer'
- charset = 'UTF-8'
- alternate = 'yes'
-
- rss = RSS::Maker.make("0.91") do |maker|
- maker.encoding = encoding
- maker.standalone = standalone
-
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- xss.type = type
- xss.title = title
- xss.media = media
- xss.charset = charset
- xss.alternate = alternate
- end
-
- setup_dummy_channel(maker)
- setup_dummy_image(maker)
- end
-
- new_rss = RSS::Maker.make("0.91") do |maker|
- rss.setup_maker(maker)
- end
-
- assert_equal("0.91", new_rss.rss_version)
- assert_equal(encoding, new_rss.encoding)
- assert_equal(standalone, new_rss.standalone)
-
- xss = rss.xml_stylesheets.first
- assert_equal(1, rss.xml_stylesheets.size)
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- assert_equal(title, xss.title)
- assert_equal(media, xss.media)
- assert_equal(charset, xss.charset)
- assert_equal(alternate, xss.alternate)
- end
- end
-end
diff --git a/test/rss/test_setup_maker_1.0.rb b/test/rss/test_setup_maker_1.0.rb
deleted file mode 100644
index a9d60ddb97..0000000000
--- a/test/rss/test_setup_maker_1.0.rb
+++ /dev/null
@@ -1,551 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestSetupMaker10 < TestCase
-
- def setup
- t = Time.iso8601("2000-01-01T12:00:05+00:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
-
- @dc_elems = {
- :title => "hoge",
- :description =>
- " XML is placing increasingly heavy loads on
- the existing technical infrastructure of the Internet.",
- :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
- :subject => "XML",
- :publisher => "The O'Reilly Network",
- :contributor => "hogehoge",
- :type => "fugafuga",
- :format => "hohoho",
- :identifier => "fufufu",
- :source => "barbar",
- :language => "ja",
- :relation => "cococo",
- :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
- :date => t,
- }
-
- @sy_elems = {
- :updatePeriod => "hourly",
- :updateFrequency => "2",
- :updateBase => t,
- }
-
- @content_elems = {
- :encoded => "<em>ATTENTION</em>",
- }
-
- @trackback_elems = {
- :ping => "http://bar.com/tb.cgi?tb_id=rssplustrackback",
- :about => [
- "http://foo.com/trackback/tb.cgi?tb_id=20020923",
- "http://foo.com/trackback/tb.cgi?tb_id=20021010",
- ],
- }
-
- @taxo_topic_elems = [
- {
- :link => "http://meerkat.oreillynet.com/?c=cat23",
- :title => "Data: XML",
- :description => "A Meerkat channel",
- },
- {
- :link => "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
- :title => "XML",
- :subject => "XML",
- :description => "DMOZ category",
- :topics => [
- "http://meerkat.oreillynet.com/?c=cat23",
- "http://dmoz.org/Computers/Data_Formats/Markup_Languages/SGML/",
- "http://dmoz.org/Computers/Programming/Internet/",
- ]
- },
- ]
- end
-
- def test_setup_maker_channel
- about = "http://hoge.com"
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
-
- rss = RSS::Maker.make("1.0") do |maker|
- maker.channel.about = about
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
-
- @dc_elems.each do |var, value|
- maker.channel.__send__("dc_#{var}=", value)
- end
-
- @sy_elems.each do |var, value|
- maker.channel.__send__("sy_#{var}=", value)
- end
-
- setup_dummy_item(maker)
- end
-
- new_rss = RSS::Maker.make("1.0") do |maker|
- rss.channel.setup_maker(maker)
- rss.items.each do |item|
- item.setup_maker(maker)
- end
- end
- channel = new_rss.channel
-
- assert_equal(about, channel.about)
- assert_equal(title, channel.title)
- assert_equal(link, channel.link)
- assert_equal(description, channel.description)
- assert_equal(1, channel.items.Seq.lis.size)
- assert_nil(channel.image)
- assert_nil(channel.textinput)
-
- @dc_elems.each do |var, value|
- assert_equal(value, channel.__send__("dc_#{var}"))
- end
-
- @sy_elems.each do |var, value|
- value = value.to_i if var == :updateFrequency
- assert_equal(value, channel.__send__("sy_#{var}"))
- end
-
- end
-
- def test_setup_maker_image
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- maker.image.url = url
-
- @dc_elems.each do |var, value|
- maker.image.__send__("dc_#{var}=", value)
- end
-
- setup_dummy_item(maker)
- end
-
- new_rss = RSS::Maker.make("1.0") do |maker|
- rss.channel.setup_maker(maker)
- rss.image.setup_maker(maker)
- rss.items.each do |item|
- item.setup_maker(maker)
- end
- end
-
- image = new_rss.image
- assert_equal(url, image.about)
- assert_equal(url, new_rss.channel.image.resource)
- assert_equal(title, image.title)
- assert_equal(link, image.link)
- assert_equal(url, image.url)
-
- @dc_elems.each do |var, value|
- assert_equal(image.__send__("dc_#{var}"), value)
- end
- end
-
- def test_setup_maker_textinput
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com"
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.link = link
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
-
- @dc_elems.each do |var, value|
- maker.textinput.__send__("dc_#{var}=", value)
- end
-
- setup_dummy_item(maker)
- end
-
- new_rss = RSS::Maker.make("1.0") do |maker|
- rss.channel.setup_maker(maker)
- rss.textinput.setup_maker(maker)
- rss.items.each do |item|
- item.setup_maker(maker)
- end
- end
-
- textinput = new_rss.textinput
- assert_equal(link, textinput.about)
- assert_equal(link, new_rss.channel.textinput.resource)
- assert_equal(title, textinput.title)
- assert_equal(name, textinput.name)
- assert_equal(description, textinput.description)
- assert_equal(link, textinput.link)
-
- @dc_elems.each do |var, value|
- assert_equal(textinput.__send__("dc_#{var}"), value)
- end
- end
-
- def test_setup_maker_items(for_backward_compatibility=false)
- title = "TITLE"
- link = "http://hoge.com/"
- description = "text hoge fuga"
-
- item_size = 5
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{title}#{i}"
- item.link = "#{link}#{i}"
- item.description = "#{description}#{i}"
-
- @dc_elems.each do |var, value|
- item.__send__("dc_#{var}=", value)
- end
-
- @content_elems.each do |var, value|
- item.__send__("content_#{var}=", value)
- end
-
- item.trackback_ping = @trackback_elems[:ping]
- @trackback_elems[:about].each do |value|
- item.trackback_abouts.new_about do |new_about|
- new_about.value = value
- end
- end
- end
- end
- end
-
- new_rss = RSS::Maker.make("1.0") do |maker|
- rss.channel.setup_maker(maker)
-
- rss.items.each do |item|
- if for_backward_compatibility
- item.setup_maker(maker)
- else
- item.setup_maker(maker.items)
- end
- end
- end
-
- assert_equal(item_size, new_rss.items.size)
- new_rss.items.each_with_index do |item, i|
- assert_equal("#{link}#{i}", item.about)
- assert_equal("#{title}#{i}", item.title)
- assert_equal("#{link}#{i}", item.link)
- assert_equal("#{description}#{i}", item.description)
-
- @dc_elems.each do |var, value|
- assert_equal(item.__send__("dc_#{var}"), value)
- end
-
- @content_elems.each do |var, value|
- assert_equal(item.__send__("content_#{var}"), value)
- end
-
- assert_equal(@trackback_elems[:ping], item.trackback_ping)
- assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size)
- item.trackback_abouts.each_with_index do |about, j|
- assert_equal(@trackback_elems[:about][j], about.value)
- end
- end
- end
-
- def test_setup_maker_items_sort
- title = "TITLE"
- link = "http://hoge.com/"
- description = "text hoge fuga"
-
- item_size = 5
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- item = RSS::RDF::Item.new("#{link}#{i}")
- item.title = "#{title}#{i}"
- item.link = "#{link}#{i}"
- item.description = "#{description}#{i}"
- item.dc_date = Time.now + i * 60
- item.setup_maker(maker.items)
- end
- maker.items.do_sort = false
- end
- assert_equal(item_size, rss.items.size)
- rss.items.each_with_index do |item, i|
- assert_equal("#{link}#{i}", item.about)
- assert_equal("#{title}#{i}", item.title)
- assert_equal("#{link}#{i}", item.link)
- assert_equal("#{description}#{i}", item.description)
- end
-
-
- rss = RSS::Maker.make("1.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- item = RSS::RDF::Item.new("#{link}#{i}")
- item.title = "#{title}#{i}"
- item.link = "#{link}#{i}"
- item.description = "#{description}#{i}"
- item.dc_date = Time.now + i * 60
- item.setup_maker(maker.items)
- end
- maker.items.do_sort = true
- end
- assert_equal(item_size, rss.items.size)
- rss.items.reverse.each_with_index do |item, i|
- assert_equal("#{link}#{i}", item.about)
- assert_equal("#{title}#{i}", item.title)
- assert_equal("#{link}#{i}", item.link)
- assert_equal("#{description}#{i}", item.description)
- end
- end
-
- def test_setup_maker_items_backward_compatibility
- test_setup_maker_items(true)
- end
-
- def test_setup_maker
- encoding = "EUC-JP"
- standalone = true
-
- href = 'a.xsl'
- type = 'text/xsl'
- title = 'sample'
- media = 'printer'
- charset = 'UTF-8'
- alternate = 'yes'
-
- rss = RSS::Maker.make("1.0") do |maker|
- maker.encoding = encoding
- maker.standalone = standalone
-
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- xss.type = type
- xss.title = title
- xss.media = media
- xss.charset = charset
- xss.alternate = alternate
- end
-
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
- end
-
- new_rss = RSS::Maker.make("1.0") do |maker|
- rss.setup_maker(maker)
- end
-
- assert_equal("1.0", new_rss.rss_version)
- assert_equal(encoding, new_rss.encoding)
- assert_equal(standalone, new_rss.standalone)
-
- xss = new_rss.xml_stylesheets.first
- assert_equal(1, new_rss.xml_stylesheets.size)
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- assert_equal(title, xss.title)
- assert_equal(media, xss.media)
- assert_equal(charset, xss.charset)
- assert_equal(alternate, xss.alternate)
- end
-
- def test_setup_maker_full
- encoding = "EUC-JP"
- standalone = true
-
- href = 'a.xsl'
- type = 'text/xsl'
- title = 'sample'
- media = 'printer'
- charset = 'UTF-8'
- alternate = 'yes'
-
- channel_about = "http://hoge.com"
- channel_title = "fugafuga"
- channel_link = "http://hoge.com"
- channel_description = "fugafugafugafuga"
-
- image_title = "fugafuga"
- image_url = "http://hoge.com/hoge.png"
-
- textinput_title = "fugafuga"
- textinput_description = "text hoge fuga"
- textinput_name = "hoge"
- textinput_link = "http://hoge.com"
-
- item_title = "TITLE"
- item_link = "http://hoge.com/"
- item_description = "text hoge fuga"
-
- item_size = 5
-
- rss = RSS::Maker.make("1.0") do |maker|
- maker.encoding = encoding
- maker.standalone = standalone
-
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- xss.type = type
- xss.title = title
- xss.media = media
- xss.charset = charset
- xss.alternate = alternate
- end
-
- maker.channel.about = channel_about
- maker.channel.title = channel_title
- maker.channel.link = channel_link
- maker.channel.description = channel_description
- @dc_elems.each do |var, value|
- maker.channel.__send__("dc_#{var}=", value)
- end
- @sy_elems.each do |var, value|
- maker.channel.__send__("sy_#{var}=", value)
- end
-
- maker.image.title = image_title
- maker.image.url = image_url
- @dc_elems.each do |var, value|
- maker.image.__send__("dc_#{var}=", value)
- end
-
- maker.textinput.link = textinput_link
- maker.textinput.title = textinput_title
- maker.textinput.description = textinput_description
- maker.textinput.name = textinput_name
- @dc_elems.each do |var, value|
- maker.textinput.__send__("dc_#{var}=", value)
- end
-
- item_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{item_title}#{i}"
- item.link = "#{item_link}#{i}"
- item.description = "#{item_description}#{i}"
-
- @dc_elems.each do |var, value|
- item.__send__("dc_#{var}=", value)
- end
-
- @content_elems.each do |var, value|
- item.__send__("content_#{var}=", value)
- end
-
- item.trackback_ping = @trackback_elems[:ping]
- @trackback_elems[:about].each do |value|
- item.trackback_abouts.new_about do |new_about|
- new_about.value = value
- end
- end
- end
- end
-
- setup_taxo_topic(maker, @taxo_topic_elems)
- end
-
- new_rss = RSS::Maker.make("1.0") do |maker|
- rss.setup_maker(maker)
- end
-
- assert_equal("1.0", new_rss.rss_version)
- assert_equal(encoding, new_rss.encoding)
- assert_equal(standalone, new_rss.standalone)
-
- xss = new_rss.xml_stylesheets.first
- assert_equal(1, new_rss.xml_stylesheets.size)
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- assert_equal(title, xss.title)
- assert_equal(media, xss.media)
- assert_equal(charset, xss.charset)
- assert_equal(alternate, xss.alternate)
-
- channel = new_rss.channel
- assert_equal(channel_about, channel.about)
- assert_equal(channel_title, channel.title)
- assert_equal(channel_link, channel.link)
- assert_equal(channel_description, channel.description)
- item_resources = []
- item_size.times do |i|
- item_resources << "#{item_link}#{i}"
- end
- assert_equal(item_resources, channel.items.resources)
- assert_equal(image_url, channel.image.resource)
- assert_equal(textinput_link, channel.textinput.resource)
- @dc_elems.each do |var, value|
- assert_equal(value, channel.__send__("dc_#{var}"))
- end
- @sy_elems.each do |var, value|
- value = value.to_i if var == :updateFrequency
- assert_equal(value, channel.__send__("sy_#{var}"))
- end
-
- image = new_rss.image
- assert_equal(image_url, image.about)
- assert_equal(image_url, new_rss.channel.image.resource)
- assert_equal(image_title, image.title)
- assert_equal(channel_link, image.link)
- assert_equal(image_url, image.url)
- @dc_elems.each do |var, value|
- assert_equal(image.__send__("dc_#{var}"), value)
- end
-
- textinput = new_rss.textinput
- assert_equal(textinput_link, textinput.about)
- assert_equal(textinput_link, new_rss.channel.textinput.resource)
- assert_equal(textinput_title, textinput.title)
- assert_equal(textinput_name, textinput.name)
- assert_equal(textinput_description, textinput.description)
- assert_equal(textinput_link, textinput.link)
- @dc_elems.each do |var, value|
- assert_equal(textinput.__send__("dc_#{var}"), value)
- end
-
- assert_equal(item_size, new_rss.items.size)
- new_rss.items.each_with_index do |item, i|
- assert_equal("#{item_link}#{i}", item.about)
- assert_equal("#{item_title}#{i}", item.title)
- assert_equal("#{item_link}#{i}", item.link)
- assert_equal("#{item_description}#{i}", item.description)
-
- @dc_elems.each do |var, value|
- assert_equal(item.__send__("dc_#{var}"), value)
- end
-
- @content_elems.each do |var, value|
- assert_equal(item.__send__("content_#{var}"), value)
- end
-
- assert_equal(@trackback_elems[:ping], item.trackback_ping)
- assert_equal(@trackback_elems[:about].size, item.trackback_abouts.size)
- item.trackback_abouts.each_with_index do |about, j|
- assert_equal(@trackback_elems[:about][j], about.value)
- end
- end
-
- assert_taxo_topic(@taxo_topic_elems, new_rss)
- end
-
- end
-end
diff --git a/test/rss/test_setup_maker_2.0.rb b/test/rss/test_setup_maker_2.0.rb
deleted file mode 100644
index dffffe6da9..0000000000
--- a/test/rss/test_setup_maker_2.0.rb
+++ /dev/null
@@ -1,309 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestSetupMaker20 < TestCase
-
- def test_setup_maker_channel
- title = "fugafuga"
- link = "http://hoge.com"
- description = "fugafugafugafuga"
- language = "ja"
- copyright = "foo"
- managingEditor = "bar"
- webMaster = "web master"
- rating = '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))'
- docs = "http://foo.com/doc"
- skipDays = [
- "Sunday",
- "Monday",
- ]
- skipHours = [
- "0",
- "13",
- ]
- pubDate = Time.now
- lastBuildDate = Time.now
- categories = [
- "Nespapers",
- "misc",
- ]
- generator = "RSS Maker"
- ttl = "60"
-
- rss = RSS::Maker.make("2.0") do |maker|
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- maker.channel.language = language
- maker.channel.copyright = copyright
- maker.channel.managingEditor = managingEditor
- maker.channel.webMaster = webMaster
- maker.channel.rating = rating
- maker.channel.docs = docs
- maker.channel.pubDate = pubDate
- maker.channel.lastBuildDate = lastBuildDate
-
- skipDays.each do |day|
- maker.channel.skipDays.new_day do |new_day|
- new_day.content = day
- end
- end
- skipHours.each do |hour|
- maker.channel.skipHours.new_hour do |new_hour|
- new_hour.content = hour
- end
- end
-
-
- categories.each do |category|
- maker.channel.categories.new_category do |new_category|
- new_category.content = category
- end
- end
-
- maker.channel.generator = generator
- maker.channel.ttl = ttl
- end
-
- new_rss = RSS::Maker.make("2.0") do |maker|
- rss.channel.setup_maker(maker)
- end
- channel = new_rss.channel
-
- assert_equal(title, channel.title)
- assert_equal(link, channel.link)
- assert_equal(description, channel.description)
- assert_equal(language, channel.language)
- assert_equal(copyright, channel.copyright)
- assert_equal(managingEditor, channel.managingEditor)
- assert_equal(webMaster, channel.webMaster)
- assert_equal(rating, channel.rating)
- assert_equal(docs, channel.docs)
- assert_equal(pubDate, channel.pubDate)
- assert_equal(lastBuildDate, channel.lastBuildDate)
-
- skipDays.each_with_index do |day, i|
- assert_equal(day, channel.skipDays.days[i].content)
- end
- skipHours.each_with_index do |hour, i|
- assert_equal(hour.to_i, channel.skipHours.hours[i].content)
- end
-
-
- channel.categories.each_with_index do |category, i|
- assert_equal(categories[i], category.content)
- end
-
- assert_equal(generator, channel.generator)
- assert_equal(ttl.to_i, channel.ttl)
-
-
- assert(channel.items.empty?)
- assert_nil(channel.image)
- assert_nil(channel.textInput)
- end
-
- def test_setup_maker_image
- title = "fugafuga"
- link = "http://hoge.com"
- url = "http://hoge.com/hoge.png"
- width = "144"
- height = "400"
- description = "an image"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
- maker.channel.link = link
-
- maker.image.title = title
- maker.image.url = url
- maker.image.width = width
- maker.image.height = height
- maker.image.description = description
- end
-
- new_rss = RSS::Maker.make("2.0") do |maker|
- rss.channel.setup_maker(maker)
- rss.image.setup_maker(maker)
- end
-
- image = new_rss.image
- assert_equal(title, image.title)
- assert_equal(link, image.link)
- assert_equal(url, image.url)
- assert_equal(width.to_i, image.width)
- assert_equal(height.to_i, image.height)
- assert_equal(description, image.description)
- end
-
- def test_setup_maker_textinput
- title = "fugafuga"
- description = "text hoge fuga"
- name = "hoge"
- link = "http://hoge.com"
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- maker.textinput.title = title
- maker.textinput.description = description
- maker.textinput.name = name
- maker.textinput.link = link
- end
-
- new_rss = RSS::Maker.make("2.0") do |maker|
- rss.channel.setup_maker(maker)
- rss.textinput.setup_maker(maker)
- end
-
- textInput = new_rss.channel.textInput
- assert_equal(title, textInput.title)
- assert_equal(description, textInput.description)
- assert_equal(name, textInput.name)
- assert_equal(link, textInput.link)
- end
-
- def test_setup_maker_items(for_backward_compatibility=false)
- title = "TITLE"
- link = "http://hoge.com/"
- description = "text hoge fuga"
- author = "oprah@oxygen.net"
- comments = "http://www.myblog.org/cgi-local/mt/mt-comments.cgi?entry_id=290"
- pubDate = Time.now
-
- guid_isPermaLink = "true"
- guid_content = "http://inessential.com/2002/09/01.php#a2"
-
- enclosure_url = "http://www.scripting.com/mp3s/weatherReportSuite.mp3"
- enclosure_length = "12216320"
- enclosure_type = "audio/mpeg"
-
- source_url = "http://static.userland.com/tomalak/links2.xml"
- source_content = "Tomalak's Realm"
-
- category_domain = "http://www.fool.com/cusips"
- category_content = "MSFT"
-
- item_size = 5
-
- rss = RSS::Maker.make("2.0") do |maker|
- setup_dummy_channel(maker)
-
- item_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{title}#{i}"
- item.link = "#{link}#{i}"
- item.description = "#{description}#{i}"
- item.author = "#{author}#{i}"
- item.comments = "#{comments}#{i}"
- item.date = pubDate
-
- item.guid.isPermaLink = guid_isPermaLink
- item.guid.content = guid_content
-
- item.enclosure.url = enclosure_url
- item.enclosure.length = enclosure_length
- item.enclosure.type = enclosure_type
-
- item.source.url = source_url
- item.source.content = source_content
-
- category = item.categories.new_category
- category.domain = category_domain
- category.content = category_content
- end
- end
- end
-
- new_rss = RSS::Maker.make("2.0") do |maker|
- rss.channel.setup_maker(maker)
-
- rss.items.each do |item|
- if for_backward_compatibility
- item.setup_maker(maker)
- else
- item.setup_maker(maker.items)
- end
- end
- end
-
- assert_equal(item_size, new_rss.items.size)
- new_rss.items.each_with_index do |item, i|
- assert_equal("#{title}#{i}", item.title)
- assert_equal("#{link}#{i}", item.link)
- assert_equal("#{description}#{i}", item.description)
- assert_equal("#{author}#{i}", item.author)
- assert_equal("#{comments}#{i}", item.comments)
- assert_equal(pubDate, item.pubDate)
-
- assert_equal(guid_isPermaLink == "true", item.guid.isPermaLink)
- assert_equal(guid_content, item.guid.content)
-
- assert_equal(enclosure_url, item.enclosure.url)
- assert_equal(enclosure_length.to_i, item.enclosure.length)
- assert_equal(enclosure_type, item.enclosure.type)
-
- assert_equal(source_url, item.source.url)
- assert_equal(source_content, item.source.content)
-
- assert_equal(1, item.categories.size)
- assert_equal(category_domain, item.category.domain)
- assert_equal(category_content, item.category.content)
- end
-
- end
-
- def test_setup_maker_items_backward_compatibility
- test_setup_maker_items(true)
- end
-
- def test_setup_maker
- encoding = "EUC-JP"
- standalone = true
-
- href = 'a.xsl'
- type = 'text/xsl'
- title = 'sample'
- media = 'printer'
- charset = 'UTF-8'
- alternate = 'yes'
-
- rss = RSS::Maker.make("2.0") do |maker|
- maker.encoding = encoding
- maker.standalone = standalone
-
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- xss.type = type
- xss.title = title
- xss.media = media
- xss.charset = charset
- xss.alternate = alternate
- end
-
- setup_dummy_channel(maker)
- end
-
- new_rss = RSS::Maker.make("2.0") do |maker|
- rss.setup_maker(maker)
- end
-
- assert_equal("2.0", new_rss.rss_version)
- assert_equal(encoding, new_rss.encoding)
- assert_equal(standalone, new_rss.standalone)
-
- xss = rss.xml_stylesheets.first
- assert_equal(1, rss.xml_stylesheets.size)
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- assert_equal(title, xss.title)
- assert_equal(media, xss.media)
- assert_equal(charset, xss.charset)
- assert_equal(alternate, xss.alternate)
- end
-
- end
-end
diff --git a/test/rss/test_setup_maker_atom_entry.rb b/test/rss/test_setup_maker_atom_entry.rb
deleted file mode 100644
index f8649ea185..0000000000
--- a/test/rss/test_setup_maker_atom_entry.rb
+++ /dev/null
@@ -1,410 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestSetupMakerAtomEntry < TestCase
- def setup
- t = Time.iso8601("2000-01-01T12:00:05+00:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
-
- @dc_elems = {
- :title => "hoge",
- :description =>
- " XML is placing increasingly heavy loads on
- the existing technical infrastructure of the Internet.",
- :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
- :subject => "XML",
- :publisher => "The O'Reilly Network",
- :contributor => "hogehoge",
- :type => "fugafuga",
- :format => "hohoho",
- :identifier => "fufufu",
- :source => "barbar",
- :language => "ja",
- :relation => "cococo",
- :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
- :date => t,
- }
- end
-
- def test_setup_maker_entry(with_dc=true)
- authors = [
- {
- :name => "Bob",
- :uri => "http://example.com/~bob/",
- :email => "bob@example.com",
- },
- {
- :name => "Alice",
- :uri => "http://example.com/~alice/",
- :email => "alice@example.com",
- },
- ]
- categories = [
- {
- :term => "music",
- :label => "Music",
- },
- {
- :term => "book",
- :scheme => "http://example.com/category/book/",
- :label => "Book",
- },
- ]
- contributors = [
- {
- :name => "Chris",
- :email => "chris@example.com",
- },
- {
- :name => "Eva",
- :uri => "http://example.com/~eva/",
- },
- ]
- id = "urn:uuid:8b105336-7e20-45fc-bb78-37fb3e1db25a"
- link = "http://hoge.com"
- published = Time.now - 60 * 3600
- rights = "Copyrights (c) 2007 Alice and Bob"
- description = "fugafugafugafuga"
- title = "fugafuga"
- updated = Time.now
-
- feed = RSS::Maker.make("atom:entry") do |maker|
- maker.items.new_item do |item|
- authors.each do |author_info|
- item.authors.new_author do |author|
- author_info.each do |key, value|
- author.__send__("#{key}=", value)
- end
- end
- end
-
- categories.each do |category_info|
- item.categories.new_category do |category|
- category_info.each do |key, value|
- category.__send__("#{key}=", value)
- end
- end
- end
-
- contributors.each do |contributor_info|
- item.contributors.new_contributor do |contributor|
- contributor_info.each do |key, value|
- contributor.__send__("#{key}=", value)
- end
- end
- end
-
- item.id = id
- item.link = link
- item.published = published
- item.rights = rights
- item.description = description
- item.title = title
- item.updated = updated
-
- if with_dc
- @dc_elems.each do |var, value|
- if var == :date
- item.new_dc_date(value)
- else
- item.__send__("dc_#{var}=", value)
- end
- end
- end
- end
- end
- assert_not_nil(feed)
-
- new_feed = RSS::Maker.make("atom:entry") do |maker|
- feed.setup_maker(maker)
- end
- assert_not_nil(new_feed)
-
- new_authors = new_feed.authors.collect do |author|
- {
- :name => author.name.content,
- :uri => author.uri.content,
- :email => author.email.content,
- }
- end
- assert_equal(authors, new_authors)
-
- new_categories = new_feed.categories.collect do |category|
- {
- :term => category.term,
- :scheme => category.scheme,
- :label => category.label,
- }.reject {|key, value| value.nil?}
- end
- assert_equal(categories, new_categories)
-
- new_contributors = new_feed.contributors.collect do |contributor|
- info = {}
- info[:name] = contributor.name.content
- info[:uri] = contributor.uri.content if contributor.uri
- info[:email] = contributor.email.content if contributor.email
- info
- end
- assert_equal(contributors, new_contributors)
-
- assert_equal(id, new_feed.id.content)
- assert_equal(link, new_feed.link.href)
- assert_equal(published, new_feed.published.content)
- assert_equal(rights, new_feed.rights.content)
- assert_equal(description, new_feed.summary.content)
- assert_equal(title, new_feed.title.content)
- assert_equal(updated, new_feed.updated.content)
-
- if with_dc
- @dc_elems.each do |var, value|
- if var == :date
- assert_equal([updated, value],
- new_feed.dc_dates.collect {|date| date.value})
- else
- assert_equal(value, new_feed.__send__("dc_#{var}"))
- end
- end
- end
-
- assert_equal(1, new_feed.items.size)
- end
-
- def test_setup_maker_entry_without_dc
- test_setup_maker_entry(false)
- end
-
- def test_setup_maker_items(for_backward_compatibility=false)
- title = "TITLE"
- link = "http://hoge.com/"
- description = "text hoge fuga"
- updated = Time.now
-
- item_size = 5
- feed = RSS::Maker.make("atom:entry") do |maker|
- setup_dummy_channel_atom(maker)
-
- item_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{title}#{i}"
- item.link = "#{link}#{i}"
- item.description = "#{description}#{i}"
- item.updated = updated + i * 60
- end
- end
- end
-
- new_feed = RSS::Maker.make("atom:entry") do |maker|
- feed.items.each do |item|
- if for_backward_compatibility
- item.setup_maker(maker)
- else
- item.setup_maker(maker.items)
- end
- end
-
- feed.items.clear
- feed.setup_maker(maker)
- end
-
- assert_equal(1, new_feed.items.size)
- new_feed.items[0..1].each_with_index do |item, i|
- assert_equal("#{title}#{i}", item.title.content)
- assert_equal("#{link}#{i}", item.link.href)
- assert_equal("#{description}#{i}", item.summary.content)
- assert_equal(updated + i * 60, item.updated.content)
- end
- end
-
- def test_setup_maker_items_sort
- title = "TITLE"
- link = "http://hoge.com/"
- summary = "text hoge fuga"
- updated = Time.now
-
- feed_size = 5
- feed = RSS::Maker.make("atom:entry") do |maker|
- setup_dummy_channel_atom(maker)
-
- feed_size.times do |i|
- entry_class = RSS::Atom::Entry
- entry = entry_class.new
- entry.title = entry_class::Title.new(:content => "#{title}#{i}")
- entry.links << entry_class::Link.new(:href => "#{link}#{i}")
- entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
- entry.updated = entry_class::Updated.new(:content => updated + i * 60)
- entry.setup_maker(maker.items)
- end
- maker.items.do_sort = false
- end
- assert_equal(1, feed.items.size)
-
- assert_equal("#{title}0", feed.title.content)
- assert_equal("#{link}0", feed.link.href)
- assert_equal("#{summary}0", feed.summary.content)
-
-
- feed = RSS::Maker.make("atom:entry") do |maker|
- setup_dummy_channel_atom(maker)
-
- feed_size.times do |i|
- entry_class = RSS::Atom::Entry
- entry = entry_class.new
- entry.title = entry_class::Title.new(:content => "#{title}#{i}")
- entry.links << entry_class::Link.new(:href => "#{link}#{i}")
- entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
- entry.updated = entry_class::Updated.new(:content => updated + i * 60)
- entry.setup_maker(maker.items)
- end
- maker.items.do_sort = true
- end
- assert_equal(1, feed.items.size)
-
- assert_equal("#{title}#{feed_size - 1}", feed.title.content)
- assert_equal("#{link}#{feed_size - 1}", feed.link.href)
- assert_equal("#{summary}#{feed_size - 1}", feed.summary.content)
- end
-
- def test_setup_maker_items_backward_compatibility
- test_setup_maker_items(true)
- end
-
- def test_setup_maker
- encoding = "EUC-JP"
- standalone = true
-
- href = 'a.xsl'
- type = 'text/xsl'
- title = 'sample'
- media = 'printer'
- charset = 'UTF-8'
- alternate = 'yes'
-
- feed = RSS::Maker.make("atom:entry") do |maker|
- maker.encoding = encoding
- maker.standalone = standalone
-
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- xss.type = type
- xss.title = title
- xss.media = media
- xss.charset = charset
- xss.alternate = alternate
- end
-
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- assert_not_nil(feed)
-
- new_feed = RSS::Maker.make("atom:entry") do |maker|
- feed.setup_maker(maker)
- end
-
- assert_equal(["atom", "1.0", "entry"], new_feed.feed_info)
- assert_equal(encoding, new_feed.encoding)
- assert_equal(standalone, new_feed.standalone)
-
- xss = new_feed.xml_stylesheets.first
- assert_equal(1, new_feed.xml_stylesheets.size)
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- assert_equal(title, xss.title)
- assert_equal(media, xss.media)
- assert_equal(charset, xss.charset)
- assert_equal(alternate, xss.alternate)
- end
-
- def test_setup_maker_full
- encoding = "EUC-JP"
- standalone = true
-
- href = 'a.xsl'
- type = 'text/xsl'
- title = 'sample'
- media = 'printer'
- charset = 'UTF-8'
- alternate = 'yes'
-
- channel_about = "http://hoge.com"
- channel_title = "fugafuga"
- channel_link = "http://hoge.com"
- channel_description = "fugafugafugafuga"
- channel_author = "Bob"
-
- image_url = "http://hoge.com/hoge.png"
-
- item_title = "TITLE"
- item_link = "http://hoge.com/"
- item_description = "text hoge fuga"
-
- entry_size = 5
- feed = RSS::Maker.make("atom:entry") do |maker|
- maker.encoding = encoding
- maker.standalone = standalone
-
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- xss.type = type
- xss.title = title
- xss.media = media
- xss.charset = charset
- xss.alternate = alternate
- end
-
- maker.channel.about = channel_about
- maker.channel.title = channel_title
- maker.channel.link = channel_link
- maker.channel.description = channel_description
- maker.channel.author = channel_author
- @dc_elems.each do |var, value|
- maker.channel.__send__("dc_#{var}=", value)
- end
-
- maker.image.url = image_url
-
- entry_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{item_title}#{i}"
- item.link = "#{item_link}#{i}"
- item.description = "#{item_description}#{i}"
-
- @dc_elems.each do |var, value|
- item.__send__("dc_#{var}=", value)
- end
- end
- end
- end
-
- new_feed = RSS::Maker.make("atom:entry") do |maker|
- feed.setup_maker(maker)
- end
-
- assert_equal(["atom", "1.0", "entry"], new_feed.feed_info)
- assert_equal(encoding, new_feed.encoding)
- assert_equal(standalone, new_feed.standalone)
-
- xss = new_feed.xml_stylesheets.first
- assert_equal(1, new_feed.xml_stylesheets.size)
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- assert_equal(title, xss.title)
- assert_equal(media, xss.media)
- assert_equal(charset, xss.charset)
- assert_equal(alternate, xss.alternate)
-
- assert_equal("#{item_title}0", new_feed.title.content)
- assert_equal("#{item_link}0", new_feed.link.href)
- assert_equal("#{item_description}0", new_feed.summary.content)
- @dc_elems.each do |var, value|
- assert_equal(value, new_feed.__send__("dc_#{var}"))
- end
- assert_equal(1, new_feed.items.size)
- end
- end
-end
diff --git a/test/rss/test_setup_maker_atom_feed.rb b/test/rss/test_setup_maker_atom_feed.rb
deleted file mode 100644
index 2196f1a46a..0000000000
--- a/test/rss/test_setup_maker_atom_feed.rb
+++ /dev/null
@@ -1,446 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestSetupMakerAtomFeed < TestCase
- def setup
- t = Time.iso8601("2000-01-01T12:00:05+00:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
-
- @dc_elems = {
- :title => "hoge",
- :description =>
- " XML is placing increasingly heavy loads on
- the existing technical infrastructure of the Internet.",
- :creator => "Rael Dornfest (mailto:rael@oreilly.com)",
- :subject => "XML",
- :publisher => "The O'Reilly Network",
- :contributor => "hogehoge",
- :type => "fugafuga",
- :format => "hohoho",
- :identifier => "fufufu",
- :source => "barbar",
- :language => "ja",
- :relation => "cococo",
- :rights => "Copyright (c) 2000 O'Reilly &amp; Associates, Inc.",
- :date => t,
- }
- end
-
- def test_setup_maker_feed(with_dc=true)
- authors = [
- {
- :name => "Bob",
- :uri => "http://example.com/~bob/",
- :email => "bob@example.com",
- },
- {
- :name => "Alice",
- :uri => "http://example.com/~alice/",
- :email => "alice@example.com",
- },
- ]
- categories = [
- {
- :term => "music",
- :label => "Music",
- },
- {
- :term => "book",
- :scheme => "http://example.com/category/book/",
- :label => "Book",
- },
- ]
- contributors = [
- {
- :name => "Chris",
- :email => "chris@example.com",
- },
- {
- :name => "Eva",
- :uri => "http://example.com/~eva/",
- },
- ]
- generator = {
- :uri => "http://example.com/generator/",
- :version => "0.0.1",
- :content => "Feed Generator",
- }
- icon = "http://example.com/icon.png"
- about = "http://hoge.com"
- title = "fugafuga"
- link = "http://hoge.com"
- logo = "http://example.com/logo.png"
- rights = "Copyrights (c) 2007 Alice and Bob"
- description = "fugafugafugafuga"
- updated = Time.now
-
- feed = RSS::Maker.make("atom") do |maker|
- authors.each do |author_info|
- maker.channel.authors.new_author do |author|
- author_info.each do |key, value|
- author.__send__("#{key}=", value)
- end
- end
- end
-
- categories.each do |category_info|
- maker.channel.categories.new_category do |category|
- category_info.each do |key, value|
- category.__send__("#{key}=", value)
- end
- end
- end
-
- contributors.each do |contributor_info|
- maker.channel.contributors.new_contributor do |contributor|
- contributor_info.each do |key, value|
- contributor.__send__("#{key}=", value)
- end
- end
- end
-
- generator.each do |key, value|
- maker.channel.generator do |g|
- g.__send__("#{key}=", value)
- end
- end
-
- maker.channel.icon = icon
-
- maker.channel.about = about
- maker.channel.link = link
- maker.channel.logo = logo
- maker.channel.rights = rights
- maker.channel.title = title
- maker.channel.description = description
- maker.channel.updated = updated
-
- if with_dc
- @dc_elems.each do |var, value|
- if var == :date
- maker.channel.new_dc_date(value)
- else
- maker.channel.__send__("dc_#{var}=", value)
- end
- end
- end
-
- setup_dummy_item_atom(maker)
- end
- assert_not_nil(feed)
-
- new_feed = RSS::Maker.make("atom") do |maker|
- feed.setup_maker(maker)
- end
- assert_not_nil(new_feed)
-
- new_authors = new_feed.authors.collect do |author|
- {
- :name => author.name.content,
- :uri => author.uri.content,
- :email => author.email.content,
- }
- end
- assert_equal(authors, new_authors)
-
- new_categories = new_feed.categories.collect do |category|
- {
- :term => category.term,
- :scheme => category.scheme,
- :label => category.label,
- }.reject {|key, value| value.nil?}
- end
- assert_equal(categories, new_categories)
-
- new_contributors = new_feed.contributors.collect do |contributor|
- info = {}
- info[:name] = contributor.name.content
- info[:uri] = contributor.uri.content if contributor.uri
- info[:email] = contributor.email.content if contributor.email
- info
- end
- assert_equal(contributors, new_contributors)
-
- new_generator = {
- :uri => new_feed.generator.uri,
- :version => new_feed.generator.version,
- :content => new_feed.generator.content,
- }
- assert_equal(generator, new_generator)
-
- assert_equal(icon, new_feed.icon.content)
- assert_equal(about, new_feed.id.content)
- assert_equal(link, new_feed.link.href)
- assert_equal(logo, new_feed.logo.content)
- assert_equal(rights, new_feed.rights.content)
- assert_equal(description, new_feed.subtitle.content)
- assert_equal(title, new_feed.title.content)
- assert_equal(updated, new_feed.updated.content)
-
- if with_dc
- @dc_elems.each do |var, value|
- if var == :date
- assert_equal([updated, value],
- new_feed.dc_dates.collect {|date| date.value})
- else
- assert_equal(value, new_feed.__send__("dc_#{var}"))
- end
- end
- end
-
- assert_equal(1, new_feed.items.size)
- end
-
- def test_setup_maker_feed_without_dc
- test_setup_maker_feed(false)
- end
-
- def test_setup_maker_items(for_backward_compatibility=false)
- title = "TITLE"
- link = "http://hoge.com/"
- description = "text hoge fuga"
- updated = Time.now
-
- item_size = 5
- feed = RSS::Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
-
- item_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{title}#{i}"
- item.link = "#{link}#{i}"
- item.description = "#{description}#{i}"
- item.updated = updated + i * 60
- end
- end
- end
-
- new_feed = RSS::Maker.make("atom") do |maker|
- feed.items.each do |item|
- if for_backward_compatibility
- item.setup_maker(maker)
- else
- item.setup_maker(maker.items)
- end
- end
-
- feed.items.clear
- feed.setup_maker(maker)
- end
-
- assert_equal(item_size, new_feed.items.size)
- new_feed.items.each_with_index do |item, i|
- assert_equal("#{title}#{i}", item.title.content)
- assert_equal("#{link}#{i}", item.link.href)
- assert_equal("#{description}#{i}", item.summary.content)
- assert_equal(updated + i * 60, item.updated.content)
- end
- end
-
- def test_setup_maker_items_sort
- title = "TITLE"
- link = "http://hoge.com/"
- summary = "text hoge fuga"
- updated = Time.now
-
- feed_size = 5
- feed = RSS::Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
-
- feed_size.times do |i|
- entry_class = RSS::Atom::Feed::Entry
- entry = entry_class.new
- entry.title = entry_class::Title.new(:content => "#{title}#{i}")
- entry.links << entry_class::Link.new(:href => "#{link}#{i}")
- entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
- entry.updated = entry_class::Updated.new(:content => updated + i * 60)
- entry.setup_maker(maker.items)
- end
- maker.items.do_sort = false
- end
- assert_equal(feed_size, feed.entries.size)
- feed.entries.each_with_index do |entry, i|
- assert_equal("#{title}#{i}", entry.title.content)
- assert_equal("#{link}#{i}", entry.link.href)
- assert_equal("#{summary}#{i}", entry.summary.content)
- end
-
-
- feed = RSS::Maker.make("atom") do |maker|
- setup_dummy_channel_atom(maker)
-
- feed_size.times do |i|
- entry_class = RSS::Atom::Feed::Entry
- entry = entry_class.new
- entry.title = entry_class::Title.new(:content => "#{title}#{i}")
- entry.links << entry_class::Link.new(:href => "#{link}#{i}")
- entry.summary = entry_class::Summary.new(:content => "#{summary}#{i}")
- entry.updated = entry_class::Updated.new(:content => updated + i * 60)
- entry.setup_maker(maker.items)
- end
- maker.items.do_sort = true
- end
- assert_equal(feed_size, feed.entries.size)
- feed.entries.reverse.each_with_index do |entry, i|
- assert_equal("#{title}#{i}", entry.title.content)
- assert_equal("#{link}#{i}", entry.link.href)
- assert_equal("#{summary}#{i}", entry.summary.content)
- end
- end
-
- def test_setup_maker_items_backward_compatibility
- test_setup_maker_items(true)
- end
-
- def test_setup_maker
- encoding = "EUC-JP"
- standalone = true
-
- href = 'a.xsl'
- type = 'text/xsl'
- title = 'sample'
- media = 'printer'
- charset = 'UTF-8'
- alternate = 'yes'
-
- feed = RSS::Maker.make("atom") do |maker|
- maker.encoding = encoding
- maker.standalone = standalone
-
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- xss.type = type
- xss.title = title
- xss.media = media
- xss.charset = charset
- xss.alternate = alternate
- end
-
- setup_dummy_channel_atom(maker)
- setup_dummy_item_atom(maker)
- end
- assert_not_nil(feed)
-
- new_feed = RSS::Maker.make("atom") do |maker|
- feed.setup_maker(maker)
- end
-
- assert_equal(["atom", "1.0", "feed"], new_feed.feed_info)
- assert_equal(encoding, new_feed.encoding)
- assert_equal(standalone, new_feed.standalone)
-
- xss = new_feed.xml_stylesheets.first
- assert_equal(1, new_feed.xml_stylesheets.size)
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- assert_equal(title, xss.title)
- assert_equal(media, xss.media)
- assert_equal(charset, xss.charset)
- assert_equal(alternate, xss.alternate)
- end
-
- def test_setup_maker_full
- encoding = "EUC-JP"
- standalone = true
-
- href = 'a.xsl'
- type = 'text/xsl'
- title = 'sample'
- media = 'printer'
- charset = 'UTF-8'
- alternate = 'yes'
-
- channel_about = "http://hoge.com"
- channel_title = "fugafuga"
- channel_link = "http://hoge.com"
- channel_description = "fugafugafugafuga"
- channel_author = "Bob"
-
- image_url = "http://hoge.com/hoge.png"
-
- item_title = "TITLE"
- item_link = "http://hoge.com/"
- item_description = "text hoge fuga"
-
- entry_size = 5
- feed = RSS::Maker.make("atom") do |maker|
- maker.encoding = encoding
- maker.standalone = standalone
-
- maker.xml_stylesheets.new_xml_stylesheet do |xss|
- xss.href = href
- xss.type = type
- xss.title = title
- xss.media = media
- xss.charset = charset
- xss.alternate = alternate
- end
-
- maker.channel.about = channel_about
- maker.channel.title = channel_title
- maker.channel.link = channel_link
- maker.channel.description = channel_description
- maker.channel.author = channel_author
- @dc_elems.each do |var, value|
- maker.channel.__send__("dc_#{var}=", value)
- end
-
- maker.image.url = image_url
-
- entry_size.times do |i|
- maker.items.new_item do |item|
- item.title = "#{item_title}#{i}"
- item.link = "#{item_link}#{i}"
- item.description = "#{item_description}#{i}"
-
- @dc_elems.each do |var, value|
- item.__send__("dc_#{var}=", value)
- end
- end
- end
- end
-
- new_feed = RSS::Maker.make("atom") do |maker|
- feed.setup_maker(maker)
- end
-
- assert_equal(["atom", "1.0", "feed"], new_feed.feed_info)
- assert_equal(encoding, new_feed.encoding)
- assert_equal(standalone, new_feed.standalone)
-
- xss = new_feed.xml_stylesheets.first
- assert_equal(1, new_feed.xml_stylesheets.size)
- assert_equal(href, xss.href)
- assert_equal(type, xss.type)
- assert_equal(title, xss.title)
- assert_equal(media, xss.media)
- assert_equal(charset, xss.charset)
- assert_equal(alternate, xss.alternate)
-
- assert_equal(channel_title, new_feed.title.content)
- assert_equal(channel_link, new_feed.link.href)
- assert_equal(channel_description, new_feed.subtitle.content)
- assert_equal(channel_author, new_feed.author.name.content)
- assert_equal(image_url, new_feed.logo.content)
- @dc_elems.each do |var, value|
- assert_equal(value, new_feed.__send__("dc_#{var}"))
- end
-
- assert_equal(entry_size, new_feed.entries.size)
- new_feed.entries.each_with_index do |entry, i|
- assert_equal("#{item_title}#{i}", entry.title.content)
- assert_equal("#{item_link}#{i}", entry.link.href)
- assert_equal("#{item_description}#{i}", entry.summary.content)
-
- @dc_elems.each do |var, value|
- assert_equal(value, entry.__send__("dc_#{var}"))
- end
- end
- end
- end
-end
diff --git a/test/rss/test_setup_maker_itunes.rb b/test/rss/test_setup_maker_itunes.rb
deleted file mode 100644
index 35ecfb4829..0000000000
--- a/test/rss/test_setup_maker_itunes.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestSetupMakerITunes < TestCase
- def test_setup_maker_simple
- author = "John Doe"
- block = true
- categories = ["Audio Blogs"]
- image = "http://example.com/podcasts/everything/AllAboutEverything.jpg"
- duration = "4:05"
- duration_components = [0, 4, 5]
- explicit = true
- keywords = ["salt", "pepper", "shaker", "exciting"]
- owner = {:name => "John Doe", :email => "john.doe@example.com"}
- subtitle = "A show about everything"
- summary = "All About Everything is a show about " +
- "everything. Each week we dive into any " +
- "subject known to man and talk about it " +
- "as much as we can. Look for our Podcast " +
- "in the iTunes Music Store"
-
- feed = RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- channel = maker.channel
- channel.itunes_author = author
- channel.itunes_block = block
- categories.each do |category|
- channel.itunes_categories.new_category.text = category
- end
- channel.itunes_image = image
- channel.itunes_explicit = explicit
- channel.itunes_keywords = keywords
- channel.itunes_owner.itunes_name = owner[:name]
- channel.itunes_owner.itunes_email = owner[:email]
- channel.itunes_subtitle = subtitle
- channel.itunes_summary = summary
-
- item = maker.items.last
- item.itunes_author = author
- item.itunes_block = block
- item.itunes_duration = duration
- item.itunes_explicit = explicit
- item.itunes_keywords = keywords
- item.itunes_subtitle = subtitle
- item.itunes_summary = summary
- end
- assert_not_nil(feed)
-
- new_feed = RSS::Maker.make("rss2.0") do |maker|
- feed.setup_maker(maker)
- end
- assert_not_nil(new_feed)
-
- channel = new_feed.channel
- item = new_feed.items.last
-
- assert_equal(author, channel.itunes_author)
- assert_equal(author, item.itunes_author)
-
- assert_equal(block, channel.itunes_block?)
- assert_equal(block, item.itunes_block?)
-
- assert_equal(categories,
- collect_itunes_categories(channel.itunes_categories))
-
- assert_equal(image, channel.itunes_image.href)
-
- assert_equal(duration_components,
- [item.itunes_duration.hour,
- item.itunes_duration.minute,
- item.itunes_duration.second])
-
- assert_equal(explicit, channel.itunes_explicit?)
- assert_equal(explicit, item.itunes_explicit?)
-
- assert_equal(keywords, channel.itunes_keywords)
- assert_equal(keywords, item.itunes_keywords)
-
- assert_equal(owner,
- {
- :name => channel.itunes_owner.itunes_name,
- :email => channel.itunes_owner.itunes_email
- })
-
- assert_equal(subtitle, channel.itunes_subtitle)
- assert_equal(subtitle, item.itunes_subtitle)
-
- assert_equal(summary, channel.itunes_summary)
- assert_equal(summary, item.itunes_summary)
- end
-
- def test_setup_maker_with_nested_categories
- categories = [["Arts & Entertainment", "Games"],
- ["Technology", "Computers"],
- "Audio Blogs"]
-
- feed = RSS::Maker.make("rss2.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- channel = maker.channel
- categories.each do |category|
- target = channel.itunes_categories
- if category.is_a?(Array)
- category.each do |sub_category|
- target = target.new_category
- target.text = sub_category
- end
- else
- target.new_category.text = category
- end
- end
- end
- assert_not_nil(feed)
-
- new_feed = RSS::Maker.make("rss2.0") do |maker|
- feed.setup_maker(maker)
- end
- assert_not_nil(new_feed)
-
- channel = new_feed.channel
-
- assert_equal(categories,
- collect_itunes_categories(channel.itunes_categories))
- end
-
- private
- def collect_itunes_categories(categories)
- categories.collect do |c|
- rest = collect_itunes_categories(c.itunes_categories)
- if rest.empty?
- c.text
- else
- [c.text, *rest]
- end
- end
- end
- end
-end
diff --git a/test/rss/test_setup_maker_slash.rb b/test/rss/test_setup_maker_slash.rb
deleted file mode 100644
index d6973bed4e..0000000000
--- a/test/rss/test_setup_maker_slash.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: false
-require_relative "rss-testcase"
-
-require "rss/maker"
-
-module RSS
- class TestSetupMakerSlash < TestCase
- def test_setup_maker
- elements = {
- "section" => "articles",
- "department" => "not-an-ocean-unless-there-are-lobsters",
- "comments" => 177,
- "hit_parades" => [177, 155, 105, 33, 6, 3, 0],
- }
-
- rss = RSS::Maker.make("rss1.0") do |maker|
- setup_dummy_channel(maker)
- setup_dummy_item(maker)
-
- item = maker.items.last
- item.slash_section = elements["section"]
- item.slash_department = elements["department"]
- item.slash_comments = elements["comments"]
- item.slash_hit_parade = elements["hit_parades"].join(",")
- end
- assert_not_nil(rss)
-
- new_rss = RSS::Maker.make("rss1.0") do |maker|
- rss.setup_maker(maker)
- end
- assert_not_nil(new_rss)
-
- item = new_rss.items.last
- assert_not_nil(item)
-
- assert_slash_elements(elements, item)
- end
- end
-end
diff --git a/test/rss/test_slash.rb b/test/rss/test_slash.rb
deleted file mode 100644
index 6746e4488f..0000000000
--- a/test/rss/test_slash.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: false
-require "cgi"
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/slash"
-
-module RSS
- class TestSlash < TestCase
- def setup
- @elements = {
- "section" => "articles",
- "department" => "not-an-ocean-unless-there-are-lobsters",
- "comments" => 177,
- "hit_parades" => [177, 155, 105, 33, 6, 3, 0],
- }
-
- slash_nodes = @elements.collect do |name, value|
- if name == "hit_parades"
- name = "hit_parade"
- value = value.join(",")
- end
- "<slash:#{name}>#{value}</slash:#{name}>"
- end.join("\n")
-
- slash_ns = {"slash" => "http://purl.org/rss/1.0/modules/slash/"}
- @source = make_RDF(<<-EOR, slash_ns)
-#{make_channel}
-#{make_image}
-#{make_item(slash_nodes)}
-#{make_textinput}
-EOR
- end
-
- def test_parser
- rss = RSS::Parser.parse(@source)
-
- assert_not_nil(rss)
-
- item = rss.items[0]
- assert_not_nil(item)
-
- assert_slash_elements(item)
- end
-
- def test_to_s
- rss = RSS::Parser.parse(@source)
- rss = RSS::Parser.parse(rss.to_s)
-
- assert_not_nil(rss)
-
- item = rss.items[0]
- assert_not_nil(item)
-
- assert_slash_elements(item)
- end
-
- private
- def assert_slash_elements(target)
- super(@elements, target)
- end
- end
-end
diff --git a/test/rss/test_syndication.rb b/test/rss/test_syndication.rb
deleted file mode 100644
index ec3895eafc..0000000000
--- a/test/rss/test_syndication.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# frozen_string_literal: false
-require "cgi"
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/syndication"
-
-module RSS
- class TestSyndication < TestCase
-
- def setup
- @prefix = "sy"
- @uri = "http://purl.org/rss/1.0/modules/syndication/"
-
- @parents = %w(channel)
-
- t = Time.iso8601("2000-01-01T12:00:05+00:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
-
- @elems = {
- :updatePeriod => "hourly",
- :updateFrequency => "2",
- :updateBase => t,
- }
-
- @sy_nodes = @elems.collect do |name, value|
- "<#{@prefix}:#{name}>#{CGI.escapeHTML(value.to_s)}</#{@prefix}:#{name}>"
- end.join("\n")
-
- @rss_source = make_RDF(<<-EOR, {@prefix => @uri})
-#{make_channel(@sy_nodes)}
-#{make_image()}
-#{make_item()}
-#{make_textinput()}
-EOR
-
- @rss = Parser.parse(@rss_source)
- end
-
- def test_parser
-
- assert_nothing_raised do
- Parser.parse(@rss_source)
- end
-
- @elems.each do |tag, value|
- assert_too_much_tag(tag.to_s, "channel") do
- Parser.parse(make_RDF(<<-EOR, {@prefix => @uri}))
-#{make_channel(("<" + @prefix + ":" + tag.to_s + ">" +
- CGI.escapeHTML(value.to_s) +
- "</" + @prefix + ":" + tag.to_s + ">") * 2)}
-#{make_item}
-EOR
- end
- end
-
- end
-
- def test_accessor
-
- t = Time.iso8601("2003-01-01T12:00:23+09:00")
- class << t
- alias_method(:to_s, :iso8601)
- end
-
- new_value = {
- :updatePeriod => "daily",
- :updateFrequency => "11",
- :updateBase => t,
- }
-
- @elems.each do |name, value|
- value = value.to_i if name == :updateFrequency
- @parents.each do |parent|
- assert_equal(value, @rss.__send__(parent).__send__("sy_#{name}"))
- @rss.__send__(parent).__send__("sy_#{name}=", new_value[name])
- new_val = new_value[name]
- new_val = new_val.to_i if name == :updateFrequency
- assert_equal(new_val, @rss.__send__(parent).__send__("sy_#{name}"))
- end
- end
-
- %w(hourly daily weekly monthly yearly).each do |x|
- @parents.each do |parent|
- assert_nothing_raised do
- @rss.__send__(parent).sy_updatePeriod = x
- end
- end
- end
-
- %w(-2 0.3 -0.4).each do |x|
- @parents.each do |parent|
- assert_not_available_value("sy:updateBase", x) do
- @rss.__send__(parent).sy_updateBase = x
- end
- end
- end
-
- end
-
- def test_to_s
-
- @elems.each do |name, value|
- excepted = "<#{@prefix}:#{name}>#{value}</#{@prefix}:#{name}>"
- @parents.each do |parent|
- assert_equal(excepted,
- @rss.__send__(parent).__send__("sy_#{name}_element"))
- end
- end
-
- REXML::Document.new(@rss_source).root.each_element do |parent|
- if @parents.include?(parent.name)
- parent.each_element do |elem|
- if elem.namespace == @uri
- assert_equal(elem.text, @elems[elem.name.intern].to_s)
- end
- end
- end
- end
- end
- end
-end
diff --git a/test/rss/test_taxonomy.rb b/test/rss/test_taxonomy.rb
deleted file mode 100644
index 89f49a94c3..0000000000
--- a/test/rss/test_taxonomy.rb
+++ /dev/null
@@ -1,173 +0,0 @@
-# frozen_string_literal: false
-require "cgi"
-
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/2.0"
-require "rss/taxonomy"
-
-module RSS
- class TestTaxonomy < TestCase
-
- def setup
- @prefix = "taxo"
- @uri = "http://purl.org/rss/1.0/modules/taxonomy/"
- @dc_prefix = "dc"
- @dc_uri = "http://purl.org/dc/elements/1.1/"
-
- @ns = {
- @prefix => @uri,
- @dc_prefix => @dc_uri,
- }
-
- @topics_parents = %w(channel item)
-
- @topics_lis = [
- "http://meerkat.oreillynet.com/?c=cat23",
- "http://meerkat.oreillynet.com/?c=47",
- "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
- ]
-
- @topics_node = "<#{@prefix}:topics>\n"
- @topics_node << " <rdf:Bag>\n"
- @topics_lis.each do |value|
- resource = CGI.escapeHTML(value)
- @topics_node << " <rdf:li resource=\"#{resource}\"/>\n"
- end
- @topics_node << " </rdf:Bag>\n"
- @topics_node << "</#{@prefix}:topics>"
-
- @topic_topics_lis = \
- [
- "http://meerkat.oreillynet.com/?c=cat23",
- "http://dmoz.org/Computers/Data_Formats/Markup_Languages/SGML/",
- "http://dmoz.org/Computers/Programming/Internet/",
- ]
-
- @topic_contents = \
- [
- {
- :link => "http://meerkat.oreillynet.com/?c=cat23",
- :title => "Data: XML",
- :description => "A Meerkat channel",
- },
- {
- :link => "http://dmoz.org/Computers/Data_Formats/Markup_Languages/XML/",
- :title => "XML",
- :subject => "XML",
- :description => "DMOZ category",
- :topics => @topic_topics_lis,
- }
- ]
-
- @topic_nodes = @topic_contents.collect do |info|
- link = info[:link]
- rv = "<#{@prefix}:topic rdf:about=\"#{link}\">\n"
- info.each do |name, value|
- case name
- when :topics
- rv << " <#{@prefix}:topics>\n"
- rv << " <rdf:Bag>\n"
- value.each do |li|
- resource = CGI.escapeHTML(li)
- rv << " <rdf:li resource=\"#{resource}\"/>\n"
- end
- rv << " </rdf:Bag>\n"
- rv << " </#{@prefix}:topics>\n"
- else
- prefix = (name == :link ? @prefix : @dc_prefix)
- rv << " <#{prefix}:#{name}>#{value}</#{prefix}:#{name}>\n"
- end
- end
- rv << "</#{@prefix}:topic>"
- end
-
- @rss_source = make_RDF(<<-EOR, @ns)
-#{make_channel(@topics_node)}
-#{make_image()}
-#{make_item(@topics_node)}
-#{make_textinput()}
-#{@topic_nodes.join("\n")}
-EOR
-
- @rss = Parser.parse(@rss_source)
- end
-
- def test_parser
- assert_nothing_raised do
- Parser.parse(@rss_source)
- end
-
- assert_too_much_tag("topics", "channel") do
- Parser.parse(make_RDF(<<-EOR, @ns))
-#{make_channel(@topics_node * 2)}
-#{make_item()}
-EOR
- end
-
- assert_too_much_tag("topics", "item") do
- Parser.parse(make_RDF(<<-EOR, @ns))
-#{make_channel()}
-#{make_item(@topics_node * 2)}
-EOR
- end
- end
-
- def test_accessor
- topics = @rss.channel.taxo_topics
- assert_equal(@topics_lis.sort,
- topics.Bag.lis.collect {|li| li.resource}.sort)
- assert_equal(@topics_lis.sort, topics.resources.sort)
-
- assert_equal(@rss.taxo_topics.first, @rss.taxo_topic)
-
- @topic_contents.each_with_index do |info, i|
- topic = @rss.taxo_topics[i]
- info.each do |name, value|
- case name
- when :link
- assert_equal(value, topic.about)
- assert_equal(value, topic.taxo_link)
- when :topics
- assert_equal(value.sort, topic.taxo_topics.resources.sort)
- else
- assert_equal(value, topic.__send__("dc_#{name}"))
- end
- end
- end
- end
-
- def test_to_s
- @topics_parents.each do |parent|
- meth = "taxo_topics_element"
- assert_equal(@topics_node, @rss.__send__(parent).__send__(meth))
- end
-
- @topic_nodes.each_with_index do |node, i|
- expected_xml = taxo_xmlns_container(node)
- expected = REXML::Document.new(expected_xml).root.elements[1]
- actual_xml = taxo_xmlns_container(@rss.taxo_topics[i].to_s(true, ""))
- actual = REXML::Document.new(actual_xml).root.elements[1]
- expected_elems = expected.reject {|x| x.is_a?(REXML::Text)}
- actual_elems = actual.reject {|x| x.is_a?(REXML::Text)}
- expected_elems.sort! {|x, y| x.name <=> y.name}
- actual_elems.sort! {|x, y| x.name <=> y.name}
- assert_equal(expected_elems.collect {|x| x.to_s},
- actual_elems.collect {|x| x.to_s})
- assert_equal(expected.attributes.sort, actual.attributes.sort)
- end
- end
-
- private
- def taxo_xmlns_container(content)
- xmlns_container({
- @prefix => @uri,
- "dc" => "http://purl.org/dc/elements/1.1/",
- "rdf" => "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
- },
- content)
- end
- end
-end
-
diff --git a/test/rss/test_to_s.rb b/test/rss/test_to_s.rb
deleted file mode 100644
index bbdd74ef0b..0000000000
--- a/test/rss/test_to_s.rb
+++ /dev/null
@@ -1,701 +0,0 @@
-# frozen_string_literal: false
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/maker"
-require "rss/1.0"
-require "rss/2.0"
-require "rss/content"
-require "rss/dublincore"
-require "rss/syndication"
-require "rss/trackback"
-
-module RSS
- class TestToS < TestCase
- def setup
- @image_url = "http://example.com/foo.png"
- @textinput_link = "http://example.com/search.cgi"
- @item_links = [
- "http://example.com/1",
- "http://example.com/2",
- ]
-
- setup_xml_declaration_info
- setup_xml_stylesheet_infos
- setup_channel_info
- setup_item_infos
- setup_image_info
- setup_textinput_info
-
- setup_dublin_core_info
- setup_syndication_info
- setup_content_info
- setup_trackback_info
- end
-
- def test_to_s_10
- rss = RSS::Maker.make("1.0") do |maker|
- setup_full(maker)
- end
-
- assert_xml_declaration(@version, @encoding, @standalone, rss)
- assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
- assert_channel10(@channel_info, rss.channel)
- assert_items10(@item_infos, rss.items)
- rss.items.each do |item|
- assert_trackback(@trackback_info, item)
- end
- assert_image10(@image_info, rss.image)
- assert_textinput10(@textinput_info, rss.textinput)
-
- rss = RSS::Parser.parse(rss.to_s)
-
- assert_xml_declaration(@version, @encoding, @standalone, rss)
- assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
- assert_channel10(@channel_info, rss.channel)
- assert_items10(@item_infos, rss.items)
- assert_image10(@image_info, rss.image)
- assert_textinput10(@textinput_info, rss.textinput)
- end
-
- def test_to_s_09
- rss = RSS::Maker.make("0.91") do |maker|
- setup_full(maker)
- end
-
- assert_xml_declaration(@version, @encoding, @standalone, rss)
- assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
- assert_channel09(@channel_info, rss.channel)
- assert_items09(@item_infos, rss.items)
- assert_image09(@image_info, rss.image)
- assert_textinput09(@textinput_info, rss.textinput)
-
- rss = RSS::Parser.parse(rss.to_s)
-
- assert_xml_declaration(@version, @encoding, @standalone, rss)
- assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
- assert_channel09(@channel_info, rss.channel)
- assert_items09(@item_infos, rss.items)
- assert_image09(@image_info, rss.image)
- assert_textinput09(@textinput_info, rss.textinput)
- end
-
- def test_to_s_20
- rss = RSS::Maker.make("2.0") do |maker|
- setup_full(maker)
- end
-
- assert_xml_declaration(@version, @encoding, @standalone, rss)
- assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
- assert_channel20(@channel_info, rss.channel)
- assert_items20(@item_infos, rss.items)
- assert_image20(@image_info, rss.image)
- assert_textinput20(@textinput_info, rss.textinput)
-
- rss = RSS::Parser.parse(rss.to_s)
-
- assert_xml_declaration(@version, @encoding, @standalone, rss)
- assert_xml_stylesheets(@xs_infos, rss.xml_stylesheets)
- assert_channel20(@channel_info, rss.channel)
- assert_items20(@item_infos, rss.items)
- assert_image20(@image_info, rss.image)
- assert_textinput20(@textinput_info, rss.textinput)
- end
-
- def test_time_w3cdtf
- assert_equal("2015-09-05T01:25:48.0001Z",
- Time.utc(2015, 9, 5, 1, 25, 48, 100).w3cdtf,
- '[ruby-core:70667] [Bug #11509]')
- end
-
- def test_20_empty_text
- title = "Blog entries"
- link = "http://blog.example.com/"
- description = ""
- rss = RSS::Maker.make("2.0") do |maker|
- maker.channel.title = title
- maker.channel.link = link
- maker.channel.description = description
- end
-
- parsed_rss = RSS::Parser.parse(rss.to_s)
- assert_equal({
- title: title,
- link: link,
- description: description,
- },
- {
- title: parsed_rss.channel.title,
- link: parsed_rss.channel.link,
- description: parsed_rss.channel.description,
- },
- "[ruby-core:80965] [Bug #13531]")
- end
-
- private
- def setup_xml_declaration_info
- @version = "1.0"
- @encoding = "UTF-8"
- @standalone = false
- end
-
- def setup_xml_stylesheet_infos
- @xs_infos = [
- {
- "href" => "XXX.xsl",
- "type" => "text/xsl",
- "title" => "XXX",
- "media" => "print",
- "alternate" => "no",
- },
- {
- "href" => "YYY.css",
- "type" => "text/css",
- "title" => "YYY",
- "media" => "all",
- "alternate" => "no",
- },
- ]
- end
-
- def setup_channel_info
- @channel_info = {
- "about" => "http://example.com/index.rdf",
- "title" => "Sample RSS",
- "link" => "http://example.com/",
- "description" => "Sample\n\n\n\n\nSite",
- "language" => "en",
- "copyright" => "FDL",
- "managingEditor" => "foo@example.com",
- "webMaster" => "webmaster@example.com",
- "rating" => '(PICS-1.1 "http://www.rsac.org/ratingsv01.html" l gen true comment "RSACi North America Server" for "http://www.rsac.org" on "1996.04.16T08:15-0500" r (n 0 s 0 v 0 l 0))',
- "docs" => "http://backend.userland.com/rss091",
- "skipDays" => [
- "Monday",
- "Friday",
- ],
- "skipHours" => [
- "12",
- "23",
- ],
- "date" => Time.now,
- "lastBuildDate" => Time.now - 3600,
- "generator" => "RSS Maker",
- "ttl" => "60",
- "cloud" => {
- "domain" => "rpc.sys.com",
- "port" => "80",
- "path" => "/RPC2",
- "registerProcedure" => "myCloud.rssPleaseNotify",
- "protocol" => "xml-rpc",
- },
- "category" => {
- "domain" => "http://example.com/misc/",
- "content" => "misc",
- },
-
- "image" => {
- "resource" => @image_url,
- },
-
- "textinput" => {
- "resource" => @textinput_link,
- },
-
- "items" => @item_links.collect{|link| {"resource" => link}},
- }
- end
-
- def setup_item_infos
- @item_infos = [
- {
- "title" => "Sample item1",
- "link" => @item_links[0],
- "description" => "Sample description1",
- "date" => Time.now - 3600,
- "author" => "foo@example.com",
- "comments" => "http://example.com/1/comments",
- "guid" => {
- "isPermaLink" => "true",
- "content" => "http://example.com/1",
- },
- "enclosure" => {
- "url" => "http://example.com/1.mp3",
- "length" => "100",
- "type" => "audio/mpeg",
- },
- "source" => {
- "url" => "http:/example.com/",
- "content" => "Sample site",
- },
- "category" => {
- "domain" => "http://example.com/misc/",
- "content" => "misc",
- },
- },
-
- {
- "title" => "Sample item2",
- "link" => @item_links[1],
- "description" => "Sample description2",
- "date" => Time.now - 7200,
- "author" => "foo@example.com",
- "comments" => "http://example.com/2/comments",
- "guid" => {
- "isPermaLink" => "false",
- "content" => "http://example.com/2",
- },
- "enclosure" => {
- "url" => "http://example.com/2.mp3",
- "length" => "200",
- "type" => "audio/mpeg",
- },
- "source" => {
- "url" => "http:/example.com/",
- "content" => "Sample site",
- },
- "category" => {
- "domain" => "http://example.com/misc/",
- "content" => "misc",
- },
- },
- ]
- end
-
- def setup_image_info
- @image_info = {
- "title" => "Sample image",
- "url" => @image_url,
- "width" => "88",
- "height" => "31",
- "description" => "Sample",
- }
- end
-
- def setup_textinput_info
- @textinput_info = {
- "title" => "Sample textinput",
- "description" => "Search",
- "name" => "key",
- "link" => @textinput_link,
- }
- end
-
- def setup_dublin_core_info
- @dc_info = {
- "title" => "DC title",
- "description" => "DC desc",
- "creator" => "DC creator",
- "subject" => "DC subject",
- "publisher" => "DC publisher",
- "contributor" => "DC contributor",
- "type" => "DC type",
- "format" => "DC format",
- "identifier" => "DC identifier",
- "source" => "DC source",
- "language" => "ja",
- "relation" => "DC relation",
- "coverage" => "DC coverage",
- "rights" => "DC rights",
- "date" => Time.now - 60,
- }
- end
-
- def setup_syndication_info
- @sy_info = {
- "updatePeriod" => "hourly",
- "updateFrequency" => "2",
- "updateBase" => Time.now - 3600,
- }
- end
-
- def setup_content_info
- @content_info = {
- "encoded" => "<p>p</p>",
- }
- end
-
- def setup_trackback_info
- @trackback_info = {
- "ping" => "http://example.com/tb.cgi?tb_id=XXX",
- "abouts" => [
- "http://example.net/tb.cgi?tb_id=YYY",
- "http://example.org/tb.cgi?tb_id=ZZZ",
- ]
- }
- end
-
-
- def setup_full(maker)
- setup_xml_declaration(maker)
- setup_xml_stylesheets(maker)
- setup_channel(maker)
- setup_image(maker)
- setup_items(maker)
- setup_textinput(maker)
- end
-
- def setup_xml_declaration(maker)
- %w(version encoding standalone).each do |name|
- maker.__send__("#{name}=", instance_eval("@#{name}"))
- end
- end
-
- def setup_xml_stylesheets(maker)
- @xs_infos.each do |info|
- xs = maker.xml_stylesheets.new_xml_stylesheet
- info.each do |name, value|
- xs.__send__("#{name}=", value)
- end
- end
- end
-
- def setup_channel(maker)
- channel = maker.channel
- info = @channel_info
-
- %w(about title link description language copyright
- managingEditor webMaster rating docs date
- lastBuildDate generator ttl).each do |name|
- channel.__send__("#{name}=", info[name])
- end
-
- skipDays = channel.skipDays
- info["skipDays"].each do |day|
- new_day = skipDays.new_day
- new_day.content = day
- end
-
- skipHours = channel.skipHours
- info["skipHours"].each do |hour|
- new_hour = skipHours.new_hour
- new_hour.content = hour
- end
-
- cloud = channel.cloud
- %w(domain port path registerProcedure protocol).each do |name|
- cloud.__send__("#{name}=", info["cloud"][name])
- end
-
- category = channel.categories.new_category
- %w(domain content).each do |name|
- category.__send__("#{name}=", info["category"][name])
- end
- end
-
- def setup_image(maker)
- image = maker.image
- info = @image_info
-
- %w(title url width height description).each do |name|
- image.__send__("#{name}=", info[name])
- end
- end
-
- def setup_items(maker)
- items = maker.items
-
- @item_infos.each do |info|
- item = items.new_item
- %w(title link description date author comments).each do |name|
- item.__send__("#{name}=", info[name])
- end
-
- guid = item.guid
- %w(isPermaLink content).each do |name|
- guid.__send__("#{name}=", info["guid"][name])
- end
-
- enclosure = item.enclosure
- %w(url length type).each do |name|
- enclosure.__send__("#{name}=", info["enclosure"][name])
- end
-
- source = item.source
- %w(url content).each do |name|
- source.__send__("#{name}=", info["source"][name])
- end
-
- category = item.categories.new_category
- %w(domain content).each do |name|
- category.__send__("#{name}=", info["category"][name])
- end
-
- setup_trackback(item)
- end
- end
-
- def setup_textinput(maker)
- textinput = maker.textinput
- info = @textinput_info
-
- %w(title description name link).each do |name|
- textinput.__send__("#{name}=", info[name])
- end
- end
-
- def setup_content(target)
- prefix = "content"
- %w(encoded).each do |name|
- target.__send__("#{prefix}_#{name}=", @content_info[name])
- end
- end
-
- def setup_dublin_core(target)
- prefix = "dc"
- %w(title description creator subject publisher
- contributor type format identifier source language
- relation coverage rights).each do |name|
- target.__send__("#{prefix}_#{name}=", @dc_info[name])
- end
- end
-
- def setup_syndicate(target)
- prefix = "sy"
- %w(updatePeriod updateFrequency updateBase).each do |name|
- target.__send__("#{prefix}_#{name}=", @sy_info[name])
- end
- end
-
- def setup_trackback(target)
- target.trackback_ping = @trackback_info["ping"]
- @trackback_info["abouts"].each do |about|
- new_about = target.trackback_abouts.new_about
- new_about.value = about
- end
- end
-
-
- def assert_channel10(attrs, channel)
- _wrap_assertion do
- n_attrs = normalized_attrs(attrs)
-
- names = %w(about title link description)
- assert_attributes(attrs, names, channel)
-
- %w(image items textinput).each do |name|
- value = n_attrs[name]
- if value
- target = channel.__send__(name)
- __send__("assert_channel10_#{name}", value, target)
- end
- end
- end
- end
-
- def assert_channel10_image(attrs, image)
- _wrap_assertion do
- assert_attributes(attrs, %w(resource), image)
- end
- end
-
- def assert_channel10_textinput(attrs, textinput)
- _wrap_assertion do
- assert_attributes(attrs, %w(resource), textinput)
- end
- end
-
- def assert_channel10_items(attrs, items)
- _wrap_assertion do
- assert_equal(items.resources, items.Seq.lis.collect {|x| x.resource})
- items.Seq.lis.each_with_index do |li, i|
- assert_attributes(attrs[i], %w(resource), li)
- end
- end
- end
-
- def assert_image10(attrs, image)
- _wrap_assertion do
- names = %w(about title url link)
- assert_attributes(attrs, names, image)
- end
- end
-
- def assert_items10(attrs, items)
- _wrap_assertion do
- names = %w(about title link description)
- items.each_with_index do |item, i|
- assert_attributes(attrs[i], names, item)
- end
- end
- end
-
- def assert_textinput10(attrs, textinput)
- _wrap_assertion do
- names = %w(about title description name link)
- assert_attributes(attrs, names, textinput)
- end
- end
-
-
- def assert_channel09(attrs, channel)
- _wrap_assertion do
- n_attrs = normalized_attrs(attrs)
-
- names = %w(title description link language rating
- copyright pubDate lastBuildDate docs
- managingEditor webMaster)
- assert_attributes(attrs, names, channel)
-
- %w(skipHours skipDays).each do |name|
- value = n_attrs[name]
- if value
- target = channel.__send__(name)
- __send__("assert_channel09_#{name}", value, target)
- end
- end
- end
- end
-
- def assert_channel09_skipDays(contents, skipDays)
- _wrap_assertion do
- days = skipDays.days
- contents.each_with_index do |content, i|
- assert_equal(content, days[i].content)
- end
- end
- end
-
- def assert_channel09_skipHours(contents, skipHours)
- _wrap_assertion do
- hours = skipHours.hours
- contents.each_with_index do |content, i|
- assert_equal(content.to_i, hours[i].content)
- end
- end
- end
-
- def assert_image09(attrs, image)
- _wrap_assertion do
- names = %w(url link title description)
- names << ["width", :integer]
- names << ["height", :integer]
- assert_attributes(attrs, names, image)
- end
- end
-
- def assert_items09(attrs, items)
- _wrap_assertion do
- names = %w(title link description)
- items.each_with_index do |item, i|
- assert_attributes(attrs[i], names, item)
- end
- end
- end
-
- def assert_textinput09(attrs, textinput)
- _wrap_assertion do
- names = %w(title description name link)
- assert_attributes(attrs, names, textinput)
- end
- end
-
-
- def assert_channel20(attrs, channel)
- _wrap_assertion do
- n_attrs = normalized_attrs(attrs)
-
- names = %w(title link description language copyright
- managingEditor webMaster pubDate
- lastBuildDate generator docs rating)
- names << ["ttl", :integer]
- assert_attributes(attrs, names, channel)
-
- %w(cloud categories skipHours skipDays).each do |name|
- value = n_attrs[name]
- if value
- target = channel.__send__(name)
- __send__("assert_channel20_#{name}", value, target)
- end
- end
- end
- end
-
- def assert_channel20_skipDays(contents, skipDays)
- assert_channel09_skipDays(contents, skipDays)
- end
-
- def assert_channel20_skipHours(contents, skipHours)
- assert_channel09_skipHours(contents, skipHours)
- end
-
- def assert_channel20_cloud(attrs, cloud)
- _wrap_assertion do
- names = %w(domain path registerProcedure protocol)
- names << ["port", :integer]
- assert_attributes(attrs, names, cloud)
- end
- end
-
- def assert_channel20_categories(attrs, categories)
- _wrap_assertion do
- names = %w(domain content)
- categories.each_with_index do |category, i|
- assert_attributes(attrs[i], names, category)
- end
- end
- end
-
- def assert_image20(attrs, image)
- _wrap_assertion do
- names = %w(url link title description)
- names << ["width", :integer]
- names << ["height", :integer]
- assert_attributes(attrs, names, image)
- end
- end
-
- def assert_items20(attrs, items)
- _wrap_assertion do
- names = %w(about title link description)
- items.each_with_index do |item, i|
- assert_attributes(attrs[i], names, item)
-
- n_attrs = normalized_attrs(attrs[i])
-
- %w(source enclosure categories guid).each do |name|
- value = n_attrs[name]
- if value
- target = item.__send__(name)
- __send__("assert_items20_#{name}", value, target)
- end
- end
- end
- end
- end
-
- def assert_items20_source(attrs, source)
- _wrap_assertion do
- assert_attributes(attrs, %w(url content), source)
- end
- end
-
- def assert_items20_enclosure(attrs, enclosure)
- _wrap_assertion do
- names = ["url", ["length", :integer], "type"]
- assert_attributes(attrs, names, enclosure)
- end
- end
-
- def assert_items20_categories(attrs, categories)
- _wrap_assertion do
- assert_channel20_categories(attrs, categories)
- end
- end
-
- def assert_items20_guid(attrs, guid)
- _wrap_assertion do
- names = [["isPermaLink", :boolean], ["content"]]
- assert_attributes(attrs, names, guid)
- end
- end
-
- def assert_textinput20(attrs, textinput)
- _wrap_assertion do
- names = %w(title description name link)
- assert_attributes(attrs, names, textinput)
- end
- end
- end
-end
diff --git a/test/rss/test_trackback.rb b/test/rss/test_trackback.rb
deleted file mode 100644
index 2910b4b344..0000000000
--- a/test/rss/test_trackback.rb
+++ /dev/null
@@ -1,136 +0,0 @@
-# frozen_string_literal: false
-require "cgi"
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/2.0"
-require "rss/trackback"
-
-module RSS
- class TestTrackBack < TestCase
-
- def setup
- @prefix = "trackback"
- @uri = "http://madskills.com/public/xml/rss/module/trackback/"
-
- @parents = %w(item)
-
- @elems = {
- :ping => "http://bar.com/tb.cgi?tb_id=rssplustrackback",
- :about => "http://foo.com/trackback/tb.cgi?tb_id=20020923",
- }
-
- @content_nodes = @elems.collect do |name, value|
- "<#{@prefix}:#{name} rdf:resource=\"#{CGI.escapeHTML(value.to_s)}\"/>"
- end.join("\n")
-
- @content_nodes2 = @elems.collect do |name, value|
- "<#{@prefix}:#{name}>#{CGI.escapeHTML(value.to_s)}</#{@prefix}:#{name}>"
- end.join("\n")
-
- @rss_source = make_RDF(<<-EOR, {@prefix => @uri})
-#{make_channel()}
-#{make_image()}
-#{make_item(@content_nodes)}
-#{make_textinput()}
-EOR
-
- @rss = Parser.parse(@rss_source)
-
- @rss20_source = make_rss20(nil, {@prefix => @uri}) do
- make_channel20(nil) do
- make_item20(@content_nodes2)
- end
- end
-
- @rss20 = Parser.parse(@rss20_source, false)
- end
-
- def test_parser
-
- assert_nothing_raised do
- Parser.parse(@rss_source)
- end
-
- @elems.find_all{|k, v| k == :ping}.each do |tag, value|
- assert_too_much_tag(tag.to_s, "item") do
- Parser.parse(make_RDF(<<-EOR, {@prefix => @uri}))
-#{make_channel()}
-#{make_item(("<" + @prefix + ":" + tag.to_s + " rdf:resource=\"" +
- CGI.escapeHTML(value.to_s) +
- "\"/>") * 2)}
-EOR
- end
- end
-
- @elems.find_all{|k, v| k == :about}.each do |tag, value|
- assert_missing_tag("trackback:ping", "item") do
- Parser.parse(make_RDF(<<-EOR, {@prefix => @uri}))
-#{make_channel()}
-#{make_item(("<" + @prefix + ":" + tag.to_s + " rdf:resource=\"" +
- CGI.escapeHTML(value.to_s) +
- "\"/>") * 2)}
-EOR
- end
-
- end
-
- end
-
- def test_accessor
-
- new_value = {
- :ping => "http://baz.com/trackback/tb.cgi?tb_id=20030808",
- :about => "http://hoge.com/trackback/tb.cgi?tb_id=90030808",
- }
-
- @elems.each do |name, value|
- @parents.each do |parent|
- accessor = "#{RSS::TRACKBACK_PREFIX}_#{name}"
- target = @rss.__send__(parent)
- target20 = @rss20.channel.__send__(parent, -1)
- assert_equal(value, target.__send__(accessor))
- assert_equal(value, target20.__send__(accessor))
- if name == :about
- # abount is zero or more
- target.__send__("#{accessor}=", 0, new_value[name].to_s)
- target20.__send__("#{accessor}=", 0, new_value[name].to_s)
- else
- target.__send__("#{accessor}=", new_value[name].to_s)
- target20.__send__("#{accessor}=", new_value[name].to_s)
- end
- assert_equal(new_value[name], target.__send__(accessor))
- assert_equal(new_value[name], target20.__send__(accessor))
- end
- end
-
- end
-
- def test_to_s
-
- @elems.each do |name, value|
- excepted = %Q!<#{@prefix}:#{name} rdf:resource="#{CGI.escapeHTML(value)}"/>!
- @parents.each do |parent|
- meth = "#{RSS::TRACKBACK_PREFIX}_#{name}_element"
- meth << "s" if name == :about
- assert_equal(excepted, @rss.__send__(parent).__send__(meth))
- end
- end
-
- REXML::Document.new(@rss_source).root.each_element do |parent|
- if @parents.include?(parent.name)
- parent.each_element do |elem|
- if elem.namespace == @uri
- assert_equal(elem.attributes["resource"], @elems[elem.name.intern])
- end
- end
- end
- end
-
- end
-
- end
-end
-
diff --git a/test/rss/test_xml-stylesheet.rb b/test/rss/test_xml-stylesheet.rb
deleted file mode 100644
index 71be1d8fea..0000000000
--- a/test/rss/test_xml-stylesheet.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-# frozen_string_literal: false
-require "rexml/document"
-
-require_relative "rss-testcase"
-
-require "rss/1.0"
-require "rss/xml-stylesheet"
-
-module RSS
- class TestXMLStyleSheet < TestCase
-
- def test_accessor
- [
- {:href => "a.xsl", :type => "text/xsl"},
- {:media => "print", :title => "FOO"},
- {:charset => "UTF-8", :alternate => "yes"},
- ].each do |attrs|
- assert_xml_stylesheet_attrs(attrs, XMLStyleSheet.new(attrs))
- end
- end
-
- def test_to_s
- [
- {:href => "a.xsl", :type => "text/xsl"},
- {:type => "text/xsl"},
- {:href => "a.xsl", :guess_type => "text/xsl"},
- {:href => "a.css", :type => "text/css"},
- {:href => "a.css", :type => "text/xsl",
- :guess_type => "text/css"},
- {:href => "a.xsl", :type => "text/xsl",
- :title => "sample", :media => "printer",
- :charset => "UTF-8", :alternate => "yes"},
- {:href => "a.css", :guess_type => "text/css",
- :alternate => "no"},
- {:type => "text/xsl", :title => "sample",
- :media => "printer", :charset => "UTF-8",
- :alternate => "yes"},
- ].each do |attrs|
- target, contents = parse_pi(XMLStyleSheet.new(attrs).to_s)
- assert_xml_stylesheet(target, attrs, XMLStyleSheet.new(contents))
- end
- end
-
- def test_bad_alternate
- %w(a ___ ??? BAD_ALTERNATE).each do |value|
- xss = XMLStyleSheet.new
- assert_raise(NotAvailableValueError) do
- xss.alternate = value
- end
- xss.do_validate = false
- assert_nothing_raised do
- xss.alternate = value
- end
- assert_nil(xss.alternate)
- end
- end
-
- def test_parse
- [
- [{:href => "a.xsl", :type => "text/xsl"},],
- [{:media => "print", :title => "FOO"},],
- [{:charset => "UTF-8", :alternate => "yes"},],
- [{:href => "a.xsl", :type => "text/xsl"},
- {:type => "text/xsl"},
- {:href => "a.xsl", :guess_type => "text/xsl"},
- {:href => "a.css", :type => "text/css"},
- {:href => "a.css", :type => "text/xsl",
- :guess_type => "text/css"},
- {:href => "a.xsl", :type => "text/xsl",
- :title => "sample", :media => "printer",
- :charset => "UTF-8", :alternate => "yes"},
- {:href => "a.css", :guess_type => "text/css",
- :alternate => "no"},
- {:type => "text/xsl", :title => "sample",
- :media => "printer", :charset => "UTF-8",
- :alternate => "yes"},],
- ].each do |xsss|
- doc = REXML::Document.new(make_sample_RDF)
- root = doc.root
- xsss.each do |xss|
- content = xss.collect do |key, name|
- %Q[#{key}="#{name}"]
- end.join(" ")
- pi = REXML::Instruction.new("xml-stylesheet", content)
- root.previous_sibling = pi
- end
- rss = Parser.parse(doc.to_s)
- have_href_xsss = xsss.find_all {|xss| xss.has_key?(:href)}
- assert_equal(have_href_xsss.size, rss.xml_stylesheets.size)
- rss.xml_stylesheets.each_with_index do |stylesheet, i|
- target, = parse_pi(stylesheet.to_s)
- assert_xml_stylesheet(target, have_href_xsss[i], stylesheet)
- end
- end
- end
-
- def parse_pi(pi)
- /\A\s*<\?(\S+)([^?]*\?+(?:[^?>][^?]*\?+)*)>\s*\z/ =~ pi
- target = $1
- dummy = REXML::Document.new("<dummy #{$2.to_s.chop}/>").root
- contents = {}
- dummy.attributes.each do |name, value|
- contents[name] = value
- end
- [target, contents]
- end
-
- end
-end
diff --git a/test/ruby/enc/test_regex_casefold.rb b/test/ruby/enc/test_regex_casefold.rb
index 2b252bd441..ec5dc7f220 100644
--- a/test/ruby/enc/test_regex_casefold.rb
+++ b/test/ruby/enc/test_regex_casefold.rb
@@ -11,7 +11,7 @@ class TestCaseFold < Test::Unit::TestCase
def check_downcase_properties(expected, start, *flags)
assert_equal expected, start.downcase(*flags)
- temp = start
+ temp = start.dup
assert_equal expected, temp.downcase!(*flags)
assert_equal expected, expected.downcase(*flags)
temp = expected
diff --git a/test/ruby/test_alias.rb b/test/ruby/test_alias.rb
index 1acf12f7f3..99f2223b49 100644
--- a/test/ruby/test_alias.rb
+++ b/test/ruby/test_alias.rb
@@ -35,6 +35,18 @@ class TestAlias < Test::Unit::TestCase
end
end
+ class Alias4 < Alias0
+ alias foo1 foo
+ alias foo2 foo1
+ alias foo3 foo2
+ end
+
+ class Alias5 < Alias4
+ alias foo1 foo
+ alias foo3 foo2
+ alias foo2 foo1
+ end
+
def test_alias
x = Alias2.new
assert_equal "foo", x.bar
@@ -47,6 +59,20 @@ class TestAlias < Test::Unit::TestCase
assert_raise(NoMethodError) { x.quux }
end
+ def test_alias_inspect
+ o = Alias4.new
+ assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo()", o.method(:foo).inspect.split[1])
+ assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo1(foo)()", o.method(:foo1).inspect.split[1])
+ assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo2(foo)()", o.method(:foo2).inspect.split[1])
+ assert_equal("TestAlias::Alias4(TestAlias::Alias0)#foo3(foo)()", o.method(:foo3).inspect.split[1])
+
+ o = Alias5.new
+ assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo()", o.method(:foo).inspect.split[1])
+ assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo1(foo)()", o.method(:foo1).inspect.split[1])
+ assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo2(foo)()", o.method(:foo2).inspect.split[1])
+ assert_equal("TestAlias::Alias5(TestAlias::Alias0)#foo3(foo)()", o.method(:foo3).inspect.split[1])
+ end
+
def test_nonexistmethod
assert_raise(NameError){
Class.new{
diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb
index 5c2356524f..6262514241 100644
--- a/test/ruby/test_argf.rb
+++ b/test/ruby/test_argf.rb
@@ -387,6 +387,21 @@ class TestArgf < Test::Unit::TestCase
assert_equal("foo", File.read(name+suffix))
end
+ def test_inplace_bug_17117
+ assert_in_out_err(["-", @t1.path], "#{<<~"{#"}#{<<~'};'}")
+ {#
+ #!/usr/bin/ruby -pi.bak
+ BEGIN {
+ GC.start
+ arr = []
+ 1000000.times { |x| arr << "fooo#{x}" }
+ }
+ puts "hello"
+ };
+ assert_equal("hello\n1\nhello\n2\n", File.read(@t1.path))
+ assert_equal("1\n2\n", File.read("#{@t1.path}.bak"))
+ end
+
def test_encoding
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
{#
@@ -983,43 +998,10 @@ class TestArgf < Test::Unit::TestCase
assert_ruby_status(["-e", "2.times {STDIN.tty?; readlines}"], "", bug5952)
end
- def test_lines
- ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
- {#
- $stderr = $stdout
- s = []
- ARGF.lines {|l| s << l }
- p s
- };
- assert_equal("[\"1\\n\", \"2\\n\", \"3\\n\", \"4\\n\", \"5\\n\", \"6\\n\"]\n", f.read)
- end
- end
-
- def test_bytes
- ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
- {#
- $stderr = $stdout
- print Marshal.dump(ARGF.bytes.to_a)
- };
- assert_equal([49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10], Marshal.load(f.read))
- end
- end
-
- def test_chars
+ def test_each_codepoint
ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
{#
- $stderr = $stdout
- print [Marshal.dump(ARGF.chars.to_a)].pack('m')
- };
- assert_equal(["1", "\n", "2", "\n", "3", "\n", "4", "\n", "5", "\n", "6", "\n"], Marshal.load(f.read.unpack('m').first))
- end
- end
-
- def test_codepoints
- ruby('-W1', '-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
- {#
- $stderr = $stdout
- print Marshal.dump(ARGF.codepoints.to_a)
+ print Marshal.dump(ARGF.each_codepoint.to_a)
};
assert_equal([49, 10, 50, 10, 51, 10, 52, 10, 53, 10, 54, 10], Marshal.load(f.read))
end
diff --git a/test/ruby/test_arithmetic_sequence.rb b/test/ruby/test_arithmetic_sequence.rb
index 755f54ac5a..5e2a825265 100644
--- a/test/ruby/test_arithmetic_sequence.rb
+++ b/test/ruby/test_arithmetic_sequence.rb
@@ -162,11 +162,6 @@ class TestArithmeticSequence < Test::Unit::TestCase
assert_equal([], seq.first(1))
assert_equal([], seq.first(3))
- seq = 1.step(10, by: 0)
- assert_equal(1, seq.first)
- assert_equal([1], seq.first(1))
- assert_equal([1, 1, 1], seq.first(3))
-
seq = 10.0.step(-1.0, by: -2.0)
assert_equal(10.0, seq.first)
assert_equal([10.0], seq.first(1))
@@ -269,6 +264,11 @@ class TestArithmeticSequence < Test::Unit::TestCase
assert_instance_of Integer, res[1]
end
+ def test_last_bug17218
+ seq = (1.0997r .. 1.1r).step(0.0001r)
+ assert_equal(1.1r, seq.last, '[ruby-core:100312] [Bug #17218]')
+ end
+
def test_to_a
assert_equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 1.step(10).to_a)
assert_equal([1, 3, 5, 7, 9], 1.step(10, 2).to_a)
@@ -284,7 +284,7 @@ class TestArithmeticSequence < Test::Unit::TestCase
'[ruby-core:90648] [Bug #15444]')
end
- def test_last_bug17218
+ def test_to_a_bug17218
seq = (1.0997r .. 1.1r).step(0.0001r)
assert_equal([1.0997r, 1.0998r, 1.0999r, 1.1r], seq.to_a, '[ruby-core:100312] [Bug #17218]')
end
@@ -345,9 +345,6 @@ class TestArithmeticSequence < Test::Unit::TestCase
[10, 8, 6, 4, 2].each do |i|
assert_equal(i, seq.next)
end
-
- seq = ((1/10r)..(1/2r)).step(0)
- assert_equal(1/10r, seq.next)
end
def test_next_bug15444
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index f2956a7fba..30bf13795c 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -7,7 +7,6 @@ require "rbconfig/sizeof"
class TestArray < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
@cls = Array
end
@@ -15,6 +14,11 @@ class TestArray < Test::Unit::TestCase
$VERBOSE = @verbose
end
+ def assert_equal_instance(x, y, *msg)
+ assert_equal(x, y, *msg)
+ assert_instance_of(x.class, y)
+ end
+
def test_percent_i
assert_equal([:foo, :bar], %i[foo bar])
assert_equal([:"\"foo"], %i["foo])
@@ -114,6 +118,9 @@ class TestArray < Test::Unit::TestCase
assert_equal('1', (x * 1).join(":"))
assert_equal('', (x * 0).join(":"))
+ assert_instance_of(Array, (@cls[] * 5))
+ assert_instance_of(Array, (@cls[1] * 5))
+
*x = *(1..7).to_a
assert_equal(7, x.size)
assert_equal([1, 2, 3, 4, 5, 6, 7], x)
@@ -647,6 +654,15 @@ class TestArray < Test::Unit::TestCase
assert_raise(TypeError) { [0].concat(:foo) }
assert_raise(FrozenError) { [0].freeze.concat(:foo) }
+
+ a = @cls[nil]
+ def (x = Object.new).to_ary
+ ary = Array.new(2)
+ ary << [] << [] << :ok
+ end
+ EnvUtil.under_gc_stress {a.concat(x)}
+ GC.start
+ assert_equal(:ok, a.last)
end
def test_count
@@ -654,7 +670,7 @@ class TestArray < Test::Unit::TestCase
assert_equal(5, a.count)
assert_equal(2, a.count(1))
assert_equal(3, a.count {|x| x % 2 == 1 })
- assert_equal(2, a.count(1) {|x| x % 2 == 1 })
+ assert_equal(2, assert_warning(/given block not used/) {a.count(1) {|x| x % 2 == 1 }})
assert_raise(ArgumentError) { a.count(0, 1) }
bug8654 = '[ruby-core:56072]'
@@ -747,6 +763,15 @@ class TestArray < Test::Unit::TestCase
a = @cls[ 5, 6, 7, 8, 9, 10 ]
assert_equal(9, a.delete_if {|i| break i if i > 8; i < 7})
assert_equal(@cls[7, 8, 9, 10], a, bug2545)
+
+ assert_raise(FrozenError) do
+ a = @cls[1, 2, 3, 42]
+ a.delete_if do
+ a.freeze
+ true
+ end
+ end
+ assert_equal(@cls[1, 2, 3, 42], a)
end
def test_dup
@@ -842,14 +867,14 @@ class TestArray < Test::Unit::TestCase
a2 = @cls[ 5, 6 ]
a3 = @cls[ 4, a2 ]
a4 = @cls[ a1, a3 ]
- assert_equal(@cls[1, 2, 3, 4, 5, 6], a4.flatten)
- assert_equal(@cls[ a1, a3], a4)
+ assert_equal_instance([1, 2, 3, 4, 5, 6], a4.flatten)
+ assert_equal_instance(@cls[ a1, a3], a4)
a5 = @cls[ a1, @cls[], a3 ]
- assert_equal(@cls[1, 2, 3, 4, 5, 6], a5.flatten)
- assert_equal(@cls[1, 2, 3, 4, [5, 6]], a5.flatten(1))
- assert_equal(@cls[], @cls[].flatten)
- assert_equal(@cls[],
+ assert_equal_instance([1, 2, 3, 4, 5, 6], a5.flatten)
+ assert_equal_instance([1, 2, 3, 4, [5, 6]], a5.flatten(1))
+ assert_equal_instance([], @cls[].flatten)
+ assert_equal_instance([],
@cls[@cls[@cls[@cls[],@cls[]],@cls[@cls[]],@cls[]],@cls[@cls[@cls[]]]].flatten)
end
@@ -1092,7 +1117,7 @@ class TestArray < Test::Unit::TestCase
assert_nil(a.index('ca'))
assert_nil(a.index([1,2]))
- assert_equal(1, a.index(99) {|x| x == 'cat' })
+ assert_equal(1, assert_warn(/given block not used/) {a.index(99) {|x| x == 'cat' }})
end
def test_values_at
@@ -1103,42 +1128,42 @@ class TestArray < Test::Unit::TestCase
end
def test_join
- $, = ""
+ assert_deprecated_warning {$, = ""}
a = @cls[]
- assert_equal("", a.join)
+ assert_equal("", assert_deprecated_warn(/non-nil value/) {a.join})
assert_equal("", a.join(','))
- assert_equal(Encoding::US_ASCII, a.join.encoding)
+ assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {a.join}.encoding)
- $, = ""
+ assert_deprecated_warning {$, = ""}
a = @cls[1, 2]
- assert_equal("12", a.join)
- assert_equal("12", a.join(nil))
+ assert_equal("12", assert_deprecated_warn(/non-nil value/) {a.join})
+ assert_equal("12", assert_deprecated_warn(/non-nil value/) {a.join(nil)})
assert_equal("1,2", a.join(','))
- $, = ""
+ assert_deprecated_warning {$, = ""}
a = @cls[1, 2, 3]
- assert_equal("123", a.join)
- assert_equal("123", a.join(nil))
+ assert_equal("123", assert_deprecated_warn(/non-nil value/) {a.join})
+ assert_equal("123", assert_deprecated_warn(/non-nil value/) {a.join(nil)})
assert_equal("1,2,3", a.join(','))
- $, = ":"
+ assert_deprecated_warning {$, = ":"}
a = @cls[1, 2, 3]
- assert_equal("1:2:3", a.join)
- assert_equal("1:2:3", a.join(nil))
+ assert_equal("1:2:3", assert_deprecated_warn(/non-nil value/) {a.join})
+ assert_equal("1:2:3", assert_deprecated_warn(/non-nil value/) {a.join(nil)})
assert_equal("1,2,3", a.join(','))
- $, = ""
+ assert_deprecated_warning {$, = ""}
e = ''.force_encoding('EUC-JP')
u = ''.force_encoding('UTF-8')
- assert_equal(Encoding::US_ASCII, [[]].join.encoding)
- assert_equal(Encoding::US_ASCII, [1, [u]].join.encoding)
- assert_equal(Encoding::UTF_8, [u, [e]].join.encoding)
- assert_equal(Encoding::UTF_8, [u, [1]].join.encoding)
- assert_equal(Encoding::UTF_8, [Struct.new(:to_str).new(u)].join.encoding)
+ assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {[[]].join}.encoding)
+ assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {[1, [u]].join}.encoding)
+ assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[u, [e]].join}.encoding)
+ assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[u, [1]].join}.encoding)
+ assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[Struct.new(:to_str).new(u)].join}.encoding)
bug5379 = '[ruby-core:39776]'
- assert_equal(Encoding::US_ASCII, [[], u, nil].join.encoding, bug5379)
- assert_equal(Encoding::UTF_8, [[], "\u3042", nil].join.encoding, bug5379)
+ assert_equal(Encoding::US_ASCII, assert_deprecated_warn(/non-nil value/) {[[], u, nil].join}.encoding, bug5379)
+ assert_equal(Encoding::UTF_8, assert_deprecated_warn(/non-nil value/) {[[], "\u3042", nil].join}.encoding, bug5379)
ensure
$, = nil
end
@@ -1315,6 +1340,15 @@ class TestArray < Test::Unit::TestCase
a = @cls[ 5, 6, 7, 8, 9, 10 ]
assert_equal(9, a.reject! {|i| break i if i > 8; i < 7})
assert_equal(@cls[7, 8, 9, 10], a, bug2545)
+
+ assert_raise(FrozenError) do
+ a = @cls[1, 2, 3, 42]
+ a.reject! do
+ a.freeze
+ true
+ end
+ end
+ assert_equal(@cls[1, 2, 3, 42], a)
end
def test_shared_array_reject!
@@ -1432,7 +1466,7 @@ class TestArray < Test::Unit::TestCase
assert_nil(a.rindex('ca'))
assert_nil(a.rindex([1,2]))
- assert_equal(3, a.rindex(99) {|x| x == [1,2,3] })
+ assert_equal(3, assert_warning(/given block not used/) {a.rindex(99) {|x| x == [1,2,3] }})
bug15951 = "[Bug #15951]"
o2 = Object.new
@@ -1472,35 +1506,74 @@ class TestArray < Test::Unit::TestCase
assert_equal(1, a.slice(-100))
assert_nil(a.slice(-101))
- assert_equal(@cls[1], a.slice(0,1))
- assert_equal(@cls[100], a.slice(99,1))
- assert_equal(@cls[], a.slice(100,1))
- assert_equal(@cls[100], a.slice(99,100))
- assert_equal(@cls[100], a.slice(-1,1))
- assert_equal(@cls[99], a.slice(-2,1))
+ assert_equal_instance([1], a.slice(0,1))
+ assert_equal_instance([100], a.slice(99,1))
+ assert_equal_instance([], a.slice(100,1))
+ assert_equal_instance([100], a.slice(99,100))
+ assert_equal_instance([100], a.slice(-1,1))
+ assert_equal_instance([99], a.slice(-2,1))
- assert_equal(@cls[10, 11, 12], a.slice(9, 3))
- assert_equal(@cls[10, 11, 12], a.slice(-91, 3))
+ assert_equal_instance([10, 11, 12], a.slice(9, 3))
+ assert_equal_instance([10, 11, 12], a.slice(-91, 3))
assert_nil(a.slice(-101, 2))
- assert_equal(@cls[1], a.slice(0..0))
- assert_equal(@cls[100], a.slice(99..99))
- assert_equal(@cls[], a.slice(100..100))
- assert_equal(@cls[100], a.slice(99..200))
- assert_equal(@cls[100], a.slice(-1..-1))
- assert_equal(@cls[99], a.slice(-2..-2))
-
- assert_equal(@cls[10, 11, 12], a.slice(9..11))
- assert_equal(@cls[98, 99, 100], a.slice(97..))
- assert_equal(@cls[10, 11, 12], a.slice(-91..-89))
- assert_equal(@cls[10, 11, 12], a.slice(-91..-89))
+ assert_equal_instance([1], a.slice(0..0))
+ assert_equal_instance([100], a.slice(99..99))
+ assert_equal_instance([], a.slice(100..100))
+ assert_equal_instance([100], a.slice(99..200))
+ assert_equal_instance([100], a.slice(-1..-1))
+ assert_equal_instance([99], a.slice(-2..-2))
+
+ assert_equal_instance([10, 11, 12], a.slice(9..11))
+ assert_equal_instance([98, 99, 100], a.slice(97..))
+ assert_equal_instance([10, 11, 12], a.slice(-91..-89))
+ assert_equal_instance([10, 11, 12], a.slice(-91..-89))
+
+ assert_equal_instance([5, 8, 11], a.slice((4..12)%3))
+ assert_equal_instance([95, 97, 99], a.slice((94..)%2))
+
+ # [0] [1] [2] [3] [4] [5] [6] [7]
+ # ary = [ 1 2 3 4 5 6 7 8 ... ]
+ # (0) (1) (2) <- (..7) % 3
+ # (2) (1) (0) <- (7..) % -3
+ assert_equal_instance([1, 4, 7], a.slice((..7)%3))
+ assert_equal_instance([8, 5, 2], a.slice((7..)% -3))
+
+ # [-98] [-97] [-96] [-95] [-94] [-93] [-92] [-91] [-90]
+ # ary = [ ... 3 4 5 6 7 8 9 10 11 ... ]
+ # (0) (1) (2) <- (-98..-90) % 3
+ # (2) (1) (0) <- (-90..-98) % -3
+ assert_equal_instance([3, 6, 9], a.slice((-98..-90)%3))
+ assert_equal_instance([11, 8, 5], a.slice((-90..-98)% -3))
+
+ # [ 48] [ 49] [ 50] [ 51] [ 52] [ 53]
+ # [-52] [-51] [-50] [-49] [-48] [-47]
+ # ary = [ ... 49 50 51 52 53 54 ... ]
+ # (0) (1) (2) <- (48..-47) % 2
+ # (2) (1) (0) <- (-47..48) % -2
+ assert_equal_instance([49, 51, 53], a.slice((48..-47)%2))
+ assert_equal_instance([54, 52, 50], a.slice((-47..48)% -2))
+
+ idx = ((3..90) % 2).to_a
+ assert_equal_instance(a.values_at(*idx), a.slice((3..90)%2))
+ idx = 90.step(3, -2).to_a
+ assert_equal_instance(a.values_at(*idx), a.slice((90 .. 3)% -2))
+ end
+
+ def test_slice_out_of_range
+ a = @cls[*(1..100).to_a]
assert_nil(a.slice(-101..-1))
assert_nil(a.slice(-101..))
+ assert_raise_with_message(RangeError, "((-101..-1).%(2)) out of range") { a.slice((-101..-1)%2) }
+ assert_raise_with_message(RangeError, "((-101..).%(2)) out of range") { a.slice((-101..)%2) }
+
assert_nil(a.slice(10, -3))
assert_equal @cls[], a.slice(10..7)
+
+ assert_equal([100], a.slice(-1, 1_000_000_000))
end
def test_slice!
@@ -1513,15 +1586,18 @@ class TestArray < Test::Unit::TestCase
assert_equal(@cls[1, 2, 3, 5], a)
a = @cls[1, 2, 3, 4, 5]
- assert_equal(@cls[3,4], a.slice!(2,2))
+ s = a.slice!(2,2)
+ assert_equal_instance([3,4], s)
assert_equal(@cls[1, 2, 5], a)
a = @cls[1, 2, 3, 4, 5]
- assert_equal(@cls[4,5], a.slice!(-2,2))
+ s = a.slice!(-2,2)
+ assert_equal_instance([4,5], s)
assert_equal(@cls[1, 2, 3], a)
a = @cls[1, 2, 3, 4, 5]
- assert_equal(@cls[3,4], a.slice!(2..3))
+ s = a.slice!(2..3)
+ assert_equal_instance([3,4], s)
assert_equal(@cls[1, 2, 5], a)
a = @cls[1, 2, 3, 4, 5]
@@ -1546,6 +1622,21 @@ class TestArray < Test::Unit::TestCase
assert_raise(ArgumentError) { @cls[1].slice!(0, 0, 0) }
end
+ def test_slice_out_of_range!
+ a = @cls[*(1..100).to_a]
+
+ assert_nil(a.clone.slice!(-101..-1))
+ assert_nil(a.clone.slice!(-101..))
+
+ # assert_raise_with_message(RangeError, "((-101..-1).%(2)) out of range") { a.clone.slice!((-101..-1)%2) }
+ # assert_raise_with_message(RangeError, "((-101..).%(2)) out of range") { a.clone.slice!((-101..)%2) }
+
+ assert_nil(a.clone.slice!(10, -3))
+ assert_equal @cls[], a.clone.slice!(10..7)
+
+ assert_equal([100], a.clone.slice!(-1, 1_000_000_000))
+ end
+
def test_sort
a = @cls[ 4, 1, 2, 3 ]
assert_equal(@cls[1, 2, 3, 4], a.sort)
@@ -1648,6 +1739,13 @@ class TestArray < Test::Unit::TestCase
TEST
end
+ def test_sort_uncomparable
+ assert_raise(ArgumentError) {[1, Float::NAN].sort}
+ assert_raise(ArgumentError) {[1.0, Float::NAN].sort}
+ assert_raise(ArgumentError) {[Float::NAN, 1].sort}
+ assert_raise(ArgumentError) {[Float::NAN, 1.0].sort}
+ end
+
def test_to_a
a = @cls[ 1, 2, 3 ]
a_id = a.__id__
@@ -1679,19 +1777,19 @@ class TestArray < Test::Unit::TestCase
end
def test_to_s
- $, = ""
+ assert_deprecated_warning {$, = ""}
a = @cls[]
assert_equal("[]", a.to_s)
- $, = ""
+ assert_deprecated_warning {$, = ""}
a = @cls[1, 2]
assert_equal("[1, 2]", a.to_s)
- $, = ""
+ assert_deprecated_warning {$, = ""}
a = @cls[1, 2, 3]
assert_equal("[1, 2, 3]", a.to_s)
- $, = ":"
+ assert_deprecated_warning {$, = ""}
a = @cls[1, 2, 3]
assert_equal("[1, 2, 3]", a.to_s)
ensure
@@ -1745,10 +1843,12 @@ class TestArray < Test::Unit::TestCase
end
def test_min
+ assert_equal(3, [3].min)
assert_equal(1, [1, 2, 3, 1, 2].min)
assert_equal(3, [1, 2, 3, 1, 2].min {|a,b| b <=> a })
cond = ->((a, ia), (b, ib)) { (b <=> a).nonzero? or ia <=> ib }
assert_equal([3, 2], [1, 2, 3, 1, 2].each_with_index.min(&cond))
+ assert_equal(1.0, [3.0, 1.0, 2.0].min)
ary = %w(albatross dog horse)
assert_equal("albatross", ary.min)
assert_equal("dog", ary.min {|a,b| a.length <=> b.length })
@@ -1766,11 +1866,20 @@ class TestArray < Test::Unit::TestCase
assert_same(obj, [obj, 1.0].min)
end
+ def test_min_uncomparable
+ assert_raise(ArgumentError) {[1, Float::NAN].min}
+ assert_raise(ArgumentError) {[1.0, Float::NAN].min}
+ assert_raise(ArgumentError) {[Float::NAN, 1].min}
+ assert_raise(ArgumentError) {[Float::NAN, 1.0].min}
+ end
+
def test_max
+ assert_equal(1, [1].max)
assert_equal(3, [1, 2, 3, 1, 2].max)
assert_equal(1, [1, 2, 3, 1, 2].max {|a,b| b <=> a })
cond = ->((a, ia), (b, ib)) { (b <=> a).nonzero? or ia <=> ib }
assert_equal([1, 3], [1, 2, 3, 1, 2].each_with_index.max(&cond))
+ assert_equal(3.0, [1.0, 3.0, 2.0].max)
ary = %w(albatross dog horse)
assert_equal("horse", ary.max)
assert_equal("albatross", ary.max {|a,b| a.length <=> b.length })
@@ -1787,7 +1896,15 @@ class TestArray < Test::Unit::TestCase
assert_same(obj, [obj, 1.0].max)
end
+ def test_max_uncomparable
+ assert_raise(ArgumentError) {[1, Float::NAN].max}
+ assert_raise(ArgumentError) {[1.0, Float::NAN].max}
+ assert_raise(ArgumentError) {[Float::NAN, 1].max}
+ assert_raise(ArgumentError) {[Float::NAN, 1.0].max}
+ end
+
def test_minmax
+ assert_equal([3, 3], [3].minmax)
assert_equal([1, 3], [1, 2, 3, 1, 2].minmax)
assert_equal([3, 1], [1, 2, 3, 1, 2].minmax {|a,b| b <=> a })
cond = ->((a, ia), (b, ib)) { (b <=> a).nonzero? or ia <=> ib }
@@ -1858,26 +1975,22 @@ class TestArray < Test::Unit::TestCase
sc = Class.new(@cls)
a = sc[]
b = a.dup
- assert_instance_of(sc, a.uniq)
- assert_equal(sc[], a.uniq)
+ assert_equal_instance([], a.uniq)
assert_equal(b, a)
a = sc[1]
b = a.dup
- assert_instance_of(sc, a.uniq)
- assert_equal(sc[1], a.uniq)
+ assert_equal_instance([1], a.uniq)
assert_equal(b, a)
a = sc[1, 1]
b = a.dup
- assert_instance_of(sc, a.uniq)
- assert_equal(sc[1], a.uniq)
+ assert_equal_instance([1], a.uniq)
assert_equal(b, a)
a = sc[1, 1]
b = a.dup
- assert_instance_of(sc, a.uniq{|x| x})
- assert_equal(sc[1], a.uniq{|x| x})
+ assert_equal_instance([1], a.uniq{|x| x})
assert_equal(b, a)
end
@@ -2292,23 +2405,23 @@ class TestArray < Test::Unit::TestCase
end
def test_take
- assert_equal([1,2,3], [1,2,3,4,5,0].take(3))
+ assert_equal_instance([1,2,3], @cls[1,2,3,4,5,0].take(3))
assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].take(-1) }
- assert_equal([1,2], [1,2].take(1000000000), '[ruby-dev:34123]')
+ assert_equal_instance([1,2], @cls[1,2].take(1000000000), '[ruby-dev:34123]')
end
def test_take_while
- assert_equal([1,2], [1,2,3,4,5,0].take_while {|i| i < 3 })
+ assert_equal_instance([1,2], @cls[1,2,3,4,5,0].take_while {|i| i < 3 })
end
def test_drop
- assert_equal([4,5,0], [1,2,3,4,5,0].drop(3))
+ assert_equal_instance([4,5,0], @cls[1,2,3,4,5,0].drop(3))
assert_raise(ArgumentError, '[ruby-dev:34123]') { [1,2].drop(-1) }
- assert_equal([], [1,2].drop(1000000000), '[ruby-dev:34123]')
+ assert_equal_instance([], @cls[1,2].drop(1000000000), '[ruby-dev:34123]')
end
def test_drop_while
- assert_equal([3,4,5,0], [1,2,3,4,5,0].drop_while {|i| i < 3 })
+ assert_equal_instance([3,4,5,0], @cls[1,2,3,4,5,0].drop_while {|i| i < 3 })
end
LONGP = [127, 63, 31, 15, 7].map {|x| 2**x-1 }.find do |x|
@@ -2333,13 +2446,13 @@ class TestArray < Test::Unit::TestCase
def test_initialize
assert_nothing_raised { [].instance_eval { initialize } }
- assert_nothing_raised { Array.new { } }
+ assert_warning(/given block not used/) { Array.new { } }
assert_equal([1, 2, 3], Array.new([1, 2, 3]))
assert_raise(ArgumentError) { Array.new(-1, 1) }
assert_raise(ArgumentError) { Array.new(LONGP, 1) }
assert_equal([1, 1, 1], Array.new(3, 1))
assert_equal([1, 1, 1], Array.new(3) { 1 })
- assert_equal([1, 1, 1], Array.new(3, 1) { 1 })
+ assert_equal([1, 1, 1], assert_warning(/block supersedes default value argument/) {Array.new(3, 1) { 1 }})
end
def test_aset_error
@@ -2355,6 +2468,9 @@ class TestArray < Test::Unit::TestCase
assert_raise(ArgumentError) { [0].freeze[0, 0, 0] = 0 }
assert_raise(TypeError) { [0][:foo] = 0 }
assert_raise(FrozenError) { [0].freeze[:foo] = 0 }
+
+ # [Bug #17271]
+ assert_raise_with_message(RangeError, "-7.. out of range") { [*0..5][-7..] = 1 }
end
def test_first2
@@ -2385,11 +2501,11 @@ class TestArray < Test::Unit::TestCase
def test_aref
assert_raise(ArgumentError) { [][0, 0, 0] }
- assert_raise(TypeError) { [][(1..10).step(2)] }
+ assert_raise(ArgumentError) { @cls[][0, 0, 0] }
end
def test_fetch
- assert_equal(1, [].fetch(0, 0) { 1 })
+ assert_equal(1, assert_warning(/block supersedes default value argument/) {[].fetch(0, 0) { 1 }})
assert_equal(1, [0, 1].fetch(-1))
assert_raise(IndexError) { [0, 1].fetch(2) }
assert_raise(IndexError) { [0, 1].fetch(-3) }
@@ -2458,6 +2574,27 @@ class TestArray < Test::Unit::TestCase
assert_equal("12345", [1,[2,[3,4],5]].join)
end
+ def test_join_recheck_elements_type
+ x = Struct.new(:ary).new
+ def x.to_str
+ ary[2] = [0, 1, 2]
+ "z"
+ end
+ (x.ary = ["a", "b", "c", x])
+ assert_equal("ab012z", x.ary.join(""))
+ end
+
+ def test_join_recheck_array_length
+ x = Struct.new(:ary).new
+ def x.to_str
+ ary.clear
+ ary[0] = "b"
+ "z"
+ end
+ x.ary = Array.new(1023) {"a"*1} << x
+ assert_equal("b", x.ary.join(""))
+ end
+
def test_to_a2
klass = Class.new(Array)
a = klass.new.to_a
@@ -2506,6 +2643,15 @@ class TestArray < Test::Unit::TestCase
a = @cls[ 1, 2, 3, 4, 5 ]
a.select! {|i| a.clear if i == 5; false }
assert_equal(0, a.size, bug13053)
+
+ assert_raise(FrozenError) do
+ a = @cls[1, 2, 3, 42]
+ a.select! do
+ a.freeze
+ false
+ end
+ end
+ assert_equal(@cls[1, 2, 3, 42], a)
end
# also select!
@@ -2521,6 +2667,15 @@ class TestArray < Test::Unit::TestCase
a = @cls[ 1, 2, 3, 4, 5 ]
assert_equal(a, a.keep_if { |i| i > 3 })
assert_equal(@cls[4, 5], a)
+
+ assert_raise(FrozenError) do
+ a = @cls[1, 2, 3, 42]
+ a.keep_if do
+ a.freeze
+ false
+ end
+ end
+ assert_equal(@cls[1, 2, 3, 42], a)
end
def test_filter
@@ -2586,7 +2741,7 @@ class TestArray < Test::Unit::TestCase
def test_zip_bug
bug8153 = "ruby-core:53650"
- r = 1..1
+ r = [1]
def r.respond_to?(*)
super
end
@@ -2619,18 +2774,17 @@ class TestArray < Test::Unit::TestCase
assert_not_equal([0, 1, 2], [0, 1, 3])
end
- A = Array.new(3, &:to_s)
- B = A.dup
-
def test_equal_resize
+ $test_equal_resize_a = Array.new(3, &:to_s)
+ $test_equal_resize_b = $test_equal_resize_a.dup
o = Object.new
def o.==(o)
- A.clear
- B.clear
+ $test_equal_resize_a.clear
+ $test_equal_resize_b.clear
true
end
- A[1] = o
- assert_equal(A, B)
+ $test_equal_resize_a[1] = o
+ assert_equal($test_equal_resize_a, $test_equal_resize_b)
end
def test_flatten_error
@@ -2869,15 +3023,6 @@ class TestArray < Test::Unit::TestCase
end
end
- class Array2 < Array
- end
-
- def test_array_subclass
- assert_equal(Array2, Array2[1,2,3].uniq.class, "[ruby-dev:34581]")
- assert_equal(Array2, Array2[1,2][0,1].class) # embedded
- assert_equal(Array2, Array2[*(1..100)][1..99].class) #not embedded
- end
-
def test_initialize2
a = [1] * 1000
a.instance_eval { initialize }
@@ -3217,3 +3362,23 @@ class TestArray < Test::Unit::TestCase
end
end
end
+
+class TestArraySubclass < TestArray
+ def setup
+ @verbose = $VERBOSE
+ @cls = Class.new(Array)
+ end
+
+ def test_to_a
+ a = @cls[ 1, 2, 3 ]
+ a_id = a.__id__
+ assert_equal_instance([1, 2, 3], a.to_a)
+ assert_not_equal(a_id, a.to_a.__id__)
+ end
+
+ def test_array_subclass
+ assert_equal(Array, @cls[1,2,3].uniq.class, "[ruby-dev:34581]")
+ assert_equal(Array, @cls[1,2][0,1].class) # embedded
+ assert_equal(Array, @cls[*(1..100)][1..99].class) #not embedded
+ end
+end
diff --git a/test/ruby/test_autoload.rb b/test/ruby/test_autoload.rb
index 171dbb6293..98d513da87 100644
--- a/test/ruby/test_autoload.rb
+++ b/test/ruby/test_autoload.rb
@@ -66,6 +66,8 @@ p Foo::Bar
end
def test_autoload_with_unqualified_file_name # [ruby-core:69206]
+ Object.send(:remove_const, :A) if Object.const_defined?(:A)
+
lp = $LOAD_PATH.dup
lf = $LOADED_FEATURES.dup
@@ -426,20 +428,24 @@ p Foo::Bar
end
def test_source_location
- klass = self.class
bug = "Bug16764"
Dir.mktmpdir('autoload') do |tmpdir|
path = "#{tmpdir}/test-#{bug}.rb"
- File.write(path, "#{klass}::#{bug} = __FILE__\n")
- klass.autoload(:Bug16764, path)
- assert_equal [__FILE__, __LINE__-1], klass.const_source_location(bug)
- assert_equal path, klass.const_get(bug)
- assert_equal [path, 1], klass.const_source_location(bug)
+ File.write(path, "C::#{bug} = __FILE__\n")
+ assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-"end;"}")
+ begin;
+ class C; end
+ C.autoload(:Bug16764, #{path.dump})
+ assert_equal [__FILE__, __LINE__-1], C.const_source_location(#{bug.dump})
+ assert_equal #{path.dump}, C.const_get(#{bug.dump})
+ assert_equal [#{path.dump}, 1], C.const_source_location(#{bug.dump})
+ end;
end
end
- def test_no_leak
- assert_no_memory_leak([], '', <<~'end;', 'many autoloads', timeout: 60)
+ def test_no_memory_leak
+ assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", 'many autoloads', timeout: 60)
+ begin;
200000.times do |i|
m = Module.new
m.instance_eval do
@@ -458,5 +464,6 @@ p Foo::Bar
def remove_autoload_constant
$".replace($" - @autoload_paths)
::Object.class_eval {remove_const(:AutoloadTest)}
+ TestAutoload.class_eval {remove_const(:AutoloadTest)} if defined? TestAutoload::AutoloadTest
end
end
diff --git a/test/ruby/test_backtrace.rb b/test/ruby/test_backtrace.rb
index 00c96b3b9f..aa79db24cb 100644
--- a/test/ruby/test_backtrace.rb
+++ b/test/ruby/test_backtrace.rb
@@ -138,10 +138,66 @@ class TestBacktrace < Test::Unit::TestCase
rec[m]
end
+ def test_caller_with_limit
+ x = nil
+ c = Class.new do
+ define_method(:bar) do
+ x = caller(1, 1)
+ end
+ end
+ [c.new].group_by(&:bar)
+ assert_equal 1, x.length
+ assert_equal caller(0), caller(0, nil)
+ end
+
def test_caller_with_nil_length
assert_equal caller(0), caller(0, nil)
end
+ def test_caller_locations_first_label
+ def self.label
+ caller_locations.first.label
+ end
+
+ def self.label_caller
+ label
+ end
+
+ assert_equal 'label_caller', label_caller
+
+ [1].group_by do
+ assert_equal 'label_caller', label_caller
+ end
+ end
+
+ def test_caller_limit_cfunc_iseq_no_pc
+ def self.a; [1].group_by { b } end
+ def self.b
+ [
+ caller_locations(2, 1).first.base_label,
+ caller_locations(3, 1).first.base_label
+ ]
+ end
+ assert_equal({["each", "group_by"]=>[1]}, a)
+ end
+
+ def test_caller_location_inspect_cfunc_iseq_no_pc
+ def self.foo
+ @res = caller_locations(2, 1).inspect
+ end
+ @line = __LINE__ + 1
+ 1.times.map { 1.times.map { foo } }
+ assert_equal("[\"#{__FILE__}:#{@line}:in `times'\"]", @res)
+ end
+
+ def test_caller_location_path_cfunc_iseq_no_pc
+ def self.foo
+ @res = caller_locations(2, 1)[0].path
+ end
+ 1.times.map { 1.times.map { foo } }
+ assert_equal(__FILE__, @res)
+ end
+
def test_caller_locations
cs = caller(0); locs = caller_locations(0).map{|loc|
loc.to_s
diff --git a/test/ruby/test_basicinstructions.rb b/test/ruby/test_basicinstructions.rb
index ab32ee54e2..f6b69cc1e5 100644
--- a/test/ruby/test_basicinstructions.rb
+++ b/test/ruby/test_basicinstructions.rb
@@ -428,7 +428,9 @@ class TestBasicInstructions < Test::Unit::TestCase
end
class CVarA
- @@cv = 'CVarA@@cv'
+ def self.setup
+ @@cv = 'CVarA@@cv'
+ end
def self.cv() @@cv end
def self.cv=(v) @@cv = v end
class << self
@@ -449,6 +451,7 @@ class TestBasicInstructions < Test::Unit::TestCase
end
def test_class_variable
+ CVarA.setup
assert_equal 'CVarA@@cv', CVarA.cv
assert_equal 'CVarA@@cv', CVarA.cv2
assert_equal 'CVarA@@cv', CVarA.new.cv
diff --git a/test/ruby/test_bignum.rb b/test/ruby/test_bignum.rb
index 434c5befd9..a240c8e8af 100644
--- a/test/ruby/test_bignum.rb
+++ b/test/ruby/test_bignum.rb
@@ -35,7 +35,6 @@ class TestBignum < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
@fmax = Float::MAX.to_i
@fmax2 = @fmax * 2
@big = (1 << BIGNUM_MIN_BITS) - 1
@@ -214,9 +213,11 @@ class TestBignum < Test::Unit::TestCase
def test_to_f
assert_nothing_raised { T31P.to_f.to_i }
- assert_raise(FloatDomainError) { (1024**1024).to_f.to_i }
- assert_equal(1, (2**50000).to_f.infinite?)
- assert_equal(-1, (-(2**50000)).to_f.infinite?)
+ assert_raise(FloatDomainError) {
+ assert_warning(/out of Float range/) {(1024**1024).to_f}.to_i
+ }
+ assert_equal(1, assert_warning(/out of Float range/) {(2**50000).to_f}.infinite?)
+ assert_equal(-1, assert_warning(/out of Float range/) {(-(2**50000)).to_f}.infinite?)
end
def test_cmp
@@ -415,7 +416,7 @@ class TestBignum < Test::Unit::TestCase
def test_divide
bug5490 = '[ruby-core:40429]'
assert_raise(ZeroDivisionError, bug5490) {T1024./(0)}
- assert_equal(Float::INFINITY, T1024./(0.0), bug5490)
+ assert_equal(Float::INFINITY, assert_warning(/out of Float range/) {T1024./(0.0)}, bug5490)
end
def test_div
@@ -466,8 +467,8 @@ class TestBignum < Test::Unit::TestCase
def test_pow
assert_equal(1.0, T32 ** 0.0)
assert_equal(1.0 / T32, T32 ** -1)
- assert_equal(1, (T32 ** T32).infinite?)
- assert_equal(1, (T32 ** (2**30-1)).infinite?)
+ assert_equal(1, assert_warning(/may be too big/) {T32 ** T32}.infinite?)
+ assert_equal(1, assert_warning(/may be too big/) {T32 ** (2**30-1)}.infinite?)
### rational changes the behavior of Bignum#**
#assert_raise(TypeError) { T32**"foo" }
@@ -505,39 +506,57 @@ class TestBignum < Test::Unit::TestCase
end
def test_and_with_float
- assert_raise(TypeError) { T1024 & 1.5 }
+ assert_raise(TypeError) {
+ assert_warning(/out of Float range/) {T1024 & 1.5}
+ }
end
def test_and_with_rational
- assert_raise(TypeError, "#1792") { T1024 & Rational(3, 2) }
+ assert_raise(TypeError, "#1792") {
+ assert_warn(/out of Float range/) {T1024 & Rational(3, 2)}
+ }
end
def test_and_with_nonintegral_numeric
- assert_raise(TypeError, "#1792") { T1024 & DummyNumeric.new }
+ assert_raise(TypeError, "#1792") {
+ assert_warn(/out of Float range/) {T1024 & DummyNumeric.new}
+ }
end
def test_or_with_float
- assert_raise(TypeError) { T1024 | 1.5 }
+ assert_raise(TypeError) {
+ assert_warn(/out of Float range/) {T1024 | 1.5}
+ }
end
def test_or_with_rational
- assert_raise(TypeError, "#1792") { T1024 | Rational(3, 2) }
+ assert_raise(TypeError, "#1792") {
+ assert_warn(/out of Float range/) {T1024 | Rational(3, 2)}
+ }
end
def test_or_with_nonintegral_numeric
- assert_raise(TypeError, "#1792") { T1024 | DummyNumeric.new }
+ assert_raise(TypeError, "#1792") {
+ assert_warn(/out of Float range/) {T1024 | DummyNumeric.new}
+ }
end
def test_xor_with_float
- assert_raise(TypeError) { T1024 ^ 1.5 }
+ assert_raise(TypeError) {
+ assert_warn(/out of Float range/) {T1024 ^ 1.5}
+ }
end
def test_xor_with_rational
- assert_raise(TypeError, "#1792") { T1024 ^ Rational(3, 2) }
+ assert_raise(TypeError, "#1792") {
+ assert_warn(/out of Float range/) {T1024 ^ Rational(3, 2)}
+ }
end
def test_xor_with_nonintegral_numeric
- assert_raise(TypeError, "#1792") { T1024 ^ DummyNumeric.new }
+ assert_raise(TypeError, "#1792") {
+ assert_warn(/out of Float range/) {T1024 ^ DummyNumeric.new}
+ }
end
def test_shift2
diff --git a/test/ruby/test_call.rb b/test/ruby/test_call.rb
index 2a1b671cac..67b3a936d4 100644
--- a/test/ruby/test_call.rb
+++ b/test/ruby/test_call.rb
@@ -99,4 +99,13 @@ class TestCall < Test::Unit::TestCase
ary = [1, 2]
assert_equal([0, 1, 2, 1], aaa(0, *ary, ary.shift), bug12860)
end
+
+ def test_call_block_order
+ bug16504 = '[ruby-core:96769] [Bug# 16504]'
+ b = proc{}
+ ary = [1, 2, b]
+ assert_equal([1, 2, b], aaa(*ary, &ary.pop), bug16504)
+ ary = [1, 2, b]
+ assert_equal([0, 1, 2, b], aaa(0, *ary, &ary.pop), bug16504)
+ end
end
diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb
index 46485c4fd2..6a8234a9d3 100644
--- a/test/ruby/test_class.rb
+++ b/test/ruby/test_class.rb
@@ -312,7 +312,7 @@ class TestClass < Test::Unit::TestCase
end
def test_invalid_yield_from_class_definition
- assert_raise(LocalJumpError) {
+ assert_raise(SyntaxError) {
EnvUtil.suppress_warning {eval("class C; yield; end")}
}
end
diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb
index a4fe9d4232..a3a7546575 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -220,6 +220,11 @@ class Complex_Test < Test::Unit::TestCase
def test_polar
assert_equal([1,2], Complex.polar(1,2).polar)
assert_equal(Complex.polar(1.0, Math::PI * 2 / 3), Complex.polar(1, Math::PI * 2 / 3))
+
+ assert_in_out_err([], <<-'end;', ['OK'], [])
+ Complex.polar(1, Complex(1, 0))
+ puts :OK
+ end;
end
def test_uplus
diff --git a/test/ruby/test_const.rb b/test/ruby/test_const.rb
index 1c73b66648..f6b9ea83d3 100644
--- a/test/ruby/test_const.rb
+++ b/test/ruby/test_const.rb
@@ -3,20 +3,30 @@
require 'test/unit'
class TestConst < Test::Unit::TestCase
- TEST1 = 1
- TEST2 = 2
- module Const
- TEST3 = 3
- TEST4 = 4
- end
+ Constants_Setup = -> do
+ remove_const :TEST1 if defined? ::TestConst::TEST1
+ remove_const :TEST2 if defined? ::TestConst::TEST2
+ remove_const :Const if defined? ::TestConst::Const
+ remove_const :Const2 if defined? ::TestConst::Const2
+
+ TEST1 = 1
+ TEST2 = 2
- module Const2
- TEST3 = 6
- TEST4 = 8
+ module Const
+ TEST3 = 3
+ TEST4 = 4
+ end
+
+ module Const2
+ TEST3 = 6
+ TEST4 = 8
+ end
end
def test_const
+ Constants_Setup.call
+
assert defined?(TEST1)
assert_equal 1, TEST1
assert defined?(TEST2)
diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb
index e1571d5714..73c192a0ae 100644
--- a/test/ruby/test_defined.rb
+++ b/test/ruby/test_defined.rb
@@ -258,6 +258,23 @@ class TestDefined < Test::Unit::TestCase
assert_separately([], "assert_nil(defined?(super))")
end
+ def test_respond_to
+ obj = "#{self.class.name}##{__method__}"
+ class << obj
+ def respond_to?(mid)
+ true
+ end
+ end
+ assert_warn(/deprecated method signature.*\n.*respond_to\? is defined here/) do
+ Warning[:deprecated] = true
+ defined?(obj.foo)
+ end
+ assert_warn('') do
+ Warning[:deprecated] = false
+ defined?(obj.foo)
+ end
+ end
+
class ExampleRespondToMissing
attr_reader :called
@@ -301,4 +318,53 @@ class TestDefined < Test::Unit::TestCase
def test_top_level_constant_not_defined
assert_nil(defined?(TestDefined::Object))
end
+
+ class RefinedClass
+ end
+
+ module RefiningModule
+ refine RefinedClass do
+ def pub
+ end
+
+ private
+
+ def priv
+ end
+ end
+
+ def self.call_without_using(x = RefinedClass.new)
+ defined?(x.pub)
+ end
+
+ def self.vcall_without_using(x = RefinedClass.new)
+ x.instance_eval {defined?(priv)}
+ end
+
+ using self
+
+ def self.call_with_using(x = RefinedClass.new)
+ defined?(x.pub)
+ end
+
+ def self.vcall_with_using(x = RefinedClass.new)
+ x.instance_eval {defined?(priv)}
+ end
+ end
+
+ def test_defined_refined_call_without_using
+ assert(!RefiningModule.call_without_using, "refined public method without using")
+ end
+
+ def test_defined_refined_vcall_without_using
+ assert(!RefiningModule.vcall_without_using, "refined private method without using")
+ end
+
+ def test_defined_refined_call_with_using
+ assert(RefiningModule.call_with_using, "refined public method with using")
+ end
+
+ def test_defined_refined_vcall_with_using
+ assert(RefiningModule.vcall_with_using, "refined private method with using")
+ end
end
diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb
index 1bb228fd45..e5bcbeac73 100644
--- a/test/ruby/test_dir.rb
+++ b/test/ruby/test_dir.rb
@@ -8,7 +8,6 @@ class TestDir < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
@root = File.realpath(Dir.mktmpdir('__test_dir__'))
@nodir = File.join(@root, "dummy")
@dirs = []
@@ -88,36 +87,67 @@ class TestDir < Test::Unit::TestCase
end
def test_chdir
- @pwd = Dir.pwd
- @env_home = ENV["HOME"]
- @env_logdir = ENV["LOGDIR"]
+ pwd = Dir.pwd
+ env_home = ENV["HOME"]
+ env_logdir = ENV["LOGDIR"]
ENV.delete("HOME")
ENV.delete("LOGDIR")
assert_raise(Errno::ENOENT) { Dir.chdir(@nodir) }
assert_raise(ArgumentError) { Dir.chdir }
- ENV["HOME"] = @pwd
+ ENV["HOME"] = pwd
Dir.chdir do
- assert_equal(@pwd, Dir.pwd)
- Dir.chdir(@root)
+ assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+
+ assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) }
+ assert_equal(@root, Dir.pwd)
+
+ assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+
+ assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) }.join }
+ assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) { } }.join }
+
+ assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+
+ assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) }
assert_equal(@root, Dir.pwd)
+
+ assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+ Dir.chdir(@root) do
+ assert_equal(@root, Dir.pwd)
+ end
+ assert_equal(pwd, Dir.pwd)
end
ensure
begin
- Dir.chdir(@pwd)
+ Dir.chdir(pwd)
rescue
- abort("cannot return the original directory: #{ @pwd }")
+ abort("cannot return the original directory: #{ pwd }")
+ end
+ ENV["HOME"] = env_home
+ ENV["LOGDIR"] = env_logdir
+ end
+
+ def test_chdir_conflict
+ pwd = Dir.pwd
+ q = Queue.new
+ t = Thread.new do
+ q.pop
+ Dir.chdir(pwd) rescue $!
+ end
+ Dir.chdir(pwd) do
+ q.push nil
+ assert_instance_of(RuntimeError, t.value)
end
- if @env_home
- ENV["HOME"] = @env_home
- else
- ENV.delete("HOME")
+
+ t = Thread.new do
+ q.pop
+ Dir.chdir(pwd){} rescue $!
end
- if @env_logdir
- ENV["LOGDIR"] = @env_logdir
- else
- ENV.delete("LOGDIR")
+ Dir.chdir(pwd) do
+ q.push nil
+ assert_instance_of(RuntimeError, t.value)
end
end
@@ -136,15 +166,17 @@ class TestDir < Test::Unit::TestCase
def test_glob
assert_equal((%w(. ..) + ("a".."z").to_a).map{|f| File.join(@root, f) },
- Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH).sort)
- assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) }.sort,
- Dir.glob([@root, File.join(@root, "*")]).sort)
+ Dir.glob(File.join(@root, "*"), File::FNM_DOTMATCH))
+ assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) },
+ Dir.glob([@root, File.join(@root, "*")]))
+ assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) },
+ Dir.glob([@root, File.join(@root, "*")], sort: false).sort)
assert_raise_with_message(ArgumentError, /nul-separated/) do
Dir.glob(@root + "\0\0\0" + File.join(@root, "*"))
end
- assert_equal(("a".."z").step(2).map {|f| File.join(File.join(@root, f), "") }.sort,
- Dir.glob(File.join(@root, "*/")).sort)
+ assert_equal(("a".."z").step(2).map {|f| File.join(File.join(@root, f), "") },
+ Dir.glob(File.join(@root, "*/")))
assert_equal([File.join(@root, '//a')], Dir.glob(@root + '//a'))
FileUtils.touch(File.join(@root, "{}"))
@@ -154,7 +186,7 @@ class TestDir < Test::Unit::TestCase
assert_equal([], Dir.glob(File.join(@root, '[a-\\')))
assert_equal([File.join(@root, "a")], Dir.glob(File.join(@root, 'a\\')))
- assert_equal(("a".."f").map {|f| File.join(@root, f) }.sort, Dir.glob(File.join(@root, '[abc/def]')).sort)
+ assert_equal(("a".."f").map {|f| File.join(@root, f) }, Dir.glob(File.join(@root, '[abc/def]')))
open(File.join(@root, "}}{}"), "wb") {}
open(File.join(@root, "}}a"), "wb") {}
@@ -184,7 +216,7 @@ class TestDir < Test::Unit::TestCase
dirs = ["a/.x", "a/b/.y"]
FileUtils.mkdir_p(dirs)
dirs.map {|dir| open("#{dir}/z", "w") {}}
- assert_equal([], Dir.glob("a/**/z").sort, bug8283)
+ assert_equal([], Dir.glob("a/**/z"), bug8283)
assert_equal(["a/.x/z"], Dir.glob("a/**/.x/z"), bug8283)
assert_equal(["a/.x/z"], Dir.glob("a/.x/**/z"), bug8283)
assert_equal(["a/b/.y/z"], Dir.glob("a/**/.y/z"), bug8283)
@@ -202,6 +234,9 @@ class TestDir < Test::Unit::TestCase
bug15540 = '[ruby-core:91110] [Bug #15540]'
assert_equal(["c/d/a/", "c/d/a/b/", "c/d/a/b/c/", "c/e/a/", "c/e/a/b/", "c/e/a/b/c/"],
Dir.glob('c/{d,e}/a/**/'), bug15540)
+
+ assert_equal(["c/e/a/", "c/e/a/b/", "c/e/a/b/c/", "c/d/a/", "c/d/a/b/", "c/d/a/b/c/"],
+ Dir.glob('c/{e,d}/a/**/'))
end
end
@@ -213,6 +248,17 @@ class TestDir < Test::Unit::TestCase
end
end
+ def test_glob_order
+ Dir.chdir(@root) do
+ assert_equal(["#{@root}/a", "#{@root}/b"], Dir.glob("#{@root}/[ba]"))
+ assert_equal(["#{@root}/b", "#{@root}/a"], Dir.glob(%W"#{@root}/b #{@root}/a"))
+ assert_equal(["#{@root}/b", "#{@root}/a"], Dir.glob("#{@root}/{b,a}"))
+ end
+ assert_equal(["a", "b"], Dir.glob("[ba]", base: @root))
+ assert_equal(["b", "a"], Dir.glob(%W"b a", base: @root))
+ assert_equal(["b", "a"], Dir.glob("{b,a}", base: @root))
+ end
+
if Process.const_defined?(:RLIMIT_NOFILE)
def test_glob_too_may_open_files
assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}", chdir: @root)
@@ -237,21 +283,38 @@ class TestDir < Test::Unit::TestCase
Dir.mkdir(File.join(@root, "a/dir"))
dirs = @dirs + %w[a/dir/]
dirs.sort!
- assert_equal(files, Dir.glob("*/*.c", base: @root).sort)
- assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".").sort})
- assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a").sort})
- assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "").sort})
- assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil).sort})
- assert_equal(@dirs, Dir.glob("*/", base: @root).sort)
- assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".").sort})
- assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a").sort})
- assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "").sort})
- assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil).sort})
- assert_equal(dirs, Dir.glob("**/*/", base: @root).sort)
- assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".").sort})
- assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a").sort})
- assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "").sort})
- assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil).sort})
+
+ assert_equal(files, Dir.glob("*/*.c", base: @root))
+ assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".")})
+ assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a")})
+ assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "")})
+ assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil)})
+ assert_equal(@dirs, Dir.glob("*/", base: @root))
+ assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".")})
+ assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a")})
+ assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "")})
+ assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil)})
+ assert_equal(dirs, Dir.glob("**/*/", base: @root))
+ assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".")})
+ assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a")})
+ assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "")})
+ assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil)})
+
+ assert_equal(files, Dir.glob("*/*.c", base: @root, sort: false).sort)
+ assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: ".", sort: false).sort})
+ assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.glob("*.c", base: "a", sort: false).sort})
+ assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: "", sort: false).sort})
+ assert_equal(files, Dir.chdir(@root) {Dir.glob("*/*.c", base: nil, sort: false).sort})
+ assert_equal(@dirs, Dir.glob("*/", base: @root))
+ assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: ".", sort: false).sort})
+ assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("*/", base: "a", sort: false).sort})
+ assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: "", sort: false).sort})
+ assert_equal(@dirs, Dir.chdir(@root) {Dir.glob("*/", base: nil, sort: false).sort})
+ assert_equal(dirs, Dir.glob("**/*/", base: @root))
+ assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: ".", sort: false).sort})
+ assert_equal(%w[dir/], Dir.chdir(@root) {Dir.glob("**/*/", base: "a", sort: false).sort})
+ assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: "", sort: false).sort})
+ assert_equal(dirs, Dir.chdir(@root) {Dir.glob("**/*/", base: nil, sort: false).sort})
end
def test_glob_base_dir
@@ -260,12 +323,20 @@ class TestDir < Test::Unit::TestCase
Dir.mkdir(File.join(@root, "a/dir"))
dirs = @dirs + %w[a/dir/]
dirs.sort!
- assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d)}.sort)
+
+ assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d)})
assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*.c", base: d)}})
- assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d).sort})
- assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d).sort}})
- assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d).sort})
- assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d).sort}})
+ assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d)})
+ assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d)}})
+ assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d)})
+ assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d)}})
+
+ assert_equal(files, Dir.open(@root) {|d| Dir.glob("*/*.c", base: d, sort: false).sort})
+ assert_equal(%w[foo.c], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*.c", base: d, sort: false).sort}})
+ assert_equal(@dirs, Dir.open(@root) {|d| Dir.glob("*/", base: d, sort: false).sort})
+ assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("*/", base: d, sort: false).sort}})
+ assert_equal(dirs, Dir.open(@root) {|d| Dir.glob("**/*/", base: d, sort: false).sort})
+ assert_equal(%w[dir/], Dir.chdir(@root) {Dir.open("a") {|d| Dir.glob("**/*/", base: d, sort: false).sort}})
end
def assert_entries(entries, children_only = false)
@@ -277,26 +348,52 @@ class TestDir < Test::Unit::TestCase
def test_entries
assert_entries(Dir.open(@root) {|dir| dir.entries})
- assert_entries(Dir.entries(@root).to_a)
+ assert_entries(Dir.entries(@root))
assert_raise(ArgumentError) {Dir.entries(@root+"\0")}
+ [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc|
+ assert_equal(enc, Dir.entries(@root, encoding: enc).first.encoding)
+ end
end
def test_foreach
assert_entries(Dir.open(@root) {|dir| dir.each.to_a})
assert_entries(Dir.foreach(@root).to_a)
assert_raise(ArgumentError) {Dir.foreach(@root+"\0").to_a}
+ newdir = @root+"/new"
+ e = Dir.foreach(newdir)
+ assert_raise(Errno::ENOENT) {e.to_a}
+ Dir.mkdir(newdir)
+ File.write(newdir+"/a", "")
+ assert_equal(%w[. .. a], e.to_a.sort)
+ [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc|
+ e = Dir.foreach(newdir, encoding: enc)
+ assert_equal(enc, e.to_a.first.encoding)
+ end
end
def test_children
assert_entries(Dir.open(@root) {|dir| dir.children}, true)
assert_entries(Dir.children(@root), true)
assert_raise(ArgumentError) {Dir.children(@root+"\0")}
+ [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc|
+ assert_equal(enc, Dir.children(@root, encoding: enc).first.encoding)
+ end
end
def test_each_child
assert_entries(Dir.open(@root) {|dir| dir.each_child.to_a}, true)
assert_entries(Dir.each_child(@root).to_a, true)
assert_raise(ArgumentError) {Dir.each_child(@root+"\0").to_a}
+ newdir = @root+"/new"
+ e = Dir.each_child(newdir)
+ assert_raise(Errno::ENOENT) {e.to_a}
+ Dir.mkdir(newdir)
+ File.write(newdir+"/a", "")
+ assert_equal(%w[a], e.to_a)
+ [Encoding::UTF_8, Encoding::ASCII_8BIT].each do |enc|
+ e = Dir.each_child(newdir, encoding: enc)
+ assert_equal(enc, e.to_a.first.encoding)
+ end
end
def test_dir_enc
@@ -337,10 +434,10 @@ class TestDir < Test::Unit::TestCase
end
assert_equal([*"a".."z", *"symlink-a".."symlink-z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }.sort,
- Dir.glob(File.join(@root, "*/")).sort)
+ Dir.glob(File.join(@root, "*/")))
- assert_equal([@root + "/", *[*"a".."z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }.sort],
- Dir.glob(File.join(@root, "**/")).sort)
+ assert_equal([@root + "/", *[*"a".."z"].each_slice(2).map {|f, _| File.join(@root, f + "/") }],
+ Dir.glob(File.join(@root, "**/")))
end
def test_glob_metachar
@@ -424,8 +521,8 @@ class TestDir < Test::Unit::TestCase
Dir.mkdir('some-dir')
File.write('some-dir/foo', 'some content')
- assert_equal [ 'dir-symlink', 'some-dir' ], Dir['*'].sort
- assert_equal [ 'dir-symlink', 'some-dir', 'some-dir/foo' ], Dir['**/*'].sort
+ assert_equal [ 'dir-symlink', 'some-dir' ], Dir['*']
+ assert_equal [ 'dir-symlink', 'some-dir', 'some-dir/foo' ], Dir['**/*']
end
end
end
@@ -471,9 +568,21 @@ class TestDir < Test::Unit::TestCase
ensure
fs.clear
end
- list = Dir.glob("*").sort
+ list = Dir.glob("*")
assert_not_empty(list)
assert_equal([*"a".."z"], list)
end;
end if defined?(Process::RLIMIT_NOFILE)
+
+ def test_glob_array_with_destructive_element
+ args = Array.new(100, "")
+ pat = Struct.new(:ary).new(args)
+ args.push(pat, *Array.new(100) {"."*40})
+ def pat.to_path
+ ary.clear
+ GC.start
+ ""
+ end
+ assert_empty(Dir.glob(args))
+ end
end
diff --git a/test/ruby/test_dir_m17n.rb b/test/ruby/test_dir_m17n.rb
index c2c0c4999e..67bad8a514 100644
--- a/test/ruby/test_dir_m17n.rb
+++ b/test/ruby/test_dir_m17n.rb
@@ -17,27 +17,19 @@ class TestDir_M17N < Test::Unit::TestCase
assert_separately(["-E#{encoding}"], <<-EOS, :chdir=>dir)
filename = #{code}.chr('UTF-8').force_encoding("#{encoding}")
File.open(filename, "w") {}
- opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
- ents = Dir.entries(".", **(opts||{}))
+ ents = Dir.entries(".")
+ if /mswin|mingw/ =~ RUBY_PLATFORM
+ filename = filename.encode("UTF-8")
+ end
assert_include(ents, filename)
EOS
return if /cygwin/ =~ RUBY_PLATFORM
assert_separately(%w[-EASCII-8BIT], <<-EOS, :chdir=>dir)
filename = #{code}.chr('UTF-8').force_encoding("ASCII-8BIT")
- opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
- ents = Dir.entries(".", **(opts||{}))
- expected_filename = #{code}.chr('UTF-8').encode(Encoding.find("filesystem")) rescue expected_filename = "?"
- expected_filename = expected_filename.force_encoding("ASCII-8BIT")
+ ents = Dir.entries(".")
if /mswin|mingw/ =~ RUBY_PLATFORM
- case
- when ents.include?(filename)
- when ents.include?(expected_filename)
- filename = expected_filename
- else
- ents = Dir.entries(".", :encoding => Encoding.find("filesystem"))
- filename = expected_filename
- end
+ filename.force_encoding("UTF-8")
end
assert_include(ents, filename)
EOS
@@ -199,27 +191,23 @@ class TestDir_M17N < Test::Unit::TestCase
assert_separately(%w[-EEUC-JP], <<-'EOS', :chdir=>d)
filename = "\xA4\xA2".force_encoding("euc-jp")
File.open(filename, "w") {}
- opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
- ents = Dir.entries(".", **(opts||{}))
+ ents = Dir.entries(".")
if /darwin/ =~ RUBY_PLATFORM
filename = filename.encode("utf-8").force_encoding("euc-jp")
+ elsif /mswin|mingw/ =~ RUBY_PLATFORM
+ filename = filename.encode("utf-8")
end
assert_include(ents, filename)
EOS
assert_separately(%w[-EASCII-8BIT], <<-'EOS', :chdir=>d)
filename = "\xA4\xA2".force_encoding('ASCII-8BIT')
- win_expected_filename = filename.encode(Encoding.find("filesystem"), "euc-jp") rescue "?"
- opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
- ents = Dir.entries(".", **(opts||{}))
+ ents = Dir.entries(".")
unless ents.include?(filename)
case RUBY_PLATFORM
when /darwin/
filename = filename.encode("utf-8", "euc-jp").b
when /mswin|mingw/
- if ents.include?(win_expected_filename.b)
- ents = Dir.entries(".", :encoding => Encoding.find("filesystem"))
- filename = win_expected_filename
- end
+ filename = filename.encode("utf-8", "euc-jp")
end
end
assert_include(ents, filename)
@@ -414,13 +402,8 @@ class TestDir_M17N < Test::Unit::TestCase
orig.each {|n| open(n, "w") {}}
enc = Encoding.find("filesystem")
enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII
- if /mswin|mingw/ =~ RUBY_PLATFORM
- opts = {:encoding => enc}
- orig.map! {|o| o.encode("filesystem") rescue o.tr("^a-z", "?")}
- else
- orig.each {|o| o.force_encoding(enc) }
- end
- ents = Dir.entries(".", **(opts||{})).reject {|n| /\A\./ =~ n}
+ orig.each {|o| o.force_encoding(enc) }
+ ents = Dir.entries(".").reject {|n| /\A\./ =~ n}
ents.sort!
PP.assert_equal(orig, ents, bug7267)
}
@@ -431,13 +414,9 @@ class TestDir_M17N < Test::Unit::TestCase
expected = []
results = []
orig.each {|o|
- if /mswin|mingw/ =~ RUBY_PLATFORM
- n = (o.encode("filesystem") rescue next)
- else
- enc = Encoding.find("filesystem")
- enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII
- n = o.dup.force_encoding(enc)
- end
+ enc = Encoding.find("filesystem")
+ enc = Encoding::ASCII_8BIT if enc == Encoding::US_ASCII
+ n = o.dup.force_encoding(enc)
expected << n
with_tmpdir {
Dir.mkdir(o)
diff --git a/test/ruby/test_econv.rb b/test/ruby/test_econv.rb
index a469614d84..a1ab1c8df6 100644
--- a/test/ruby/test_econv.rb
+++ b/test/ruby/test_econv.rb
@@ -803,7 +803,7 @@ class TestEncodingConverter < Test::Unit::TestCase
assert_equal('', ec.finish)
ec = Encoding::Converter.new("", "xml_attr_content_escape")
- assert_equal('&amp;&lt;&gt;&quot;', ec.convert("&<>\""))
+ assert_equal('&amp;&lt;&gt;&quot;&apos;', ec.convert("&<>\"'"))
assert_equal('', ec.finish)
end
@@ -844,7 +844,7 @@ class TestEncodingConverter < Test::Unit::TestCase
def test_xml_hasharg
assert_equal("&amp;\e$B$&\e(B&#x2665;&amp;\"'".force_encoding("iso-2022-jp"),
"&\u3046\u2665&\"'".encode("iso-2022-jp", xml: :text))
- assert_equal("\"&amp;\e$B$&\e(B&#x2661;&amp;&quot;'\"".force_encoding("iso-2022-jp"),
+ assert_equal("\"&amp;\e$B$&\e(B&#x2661;&amp;&quot;&apos;\"".force_encoding("iso-2022-jp"),
"&\u3046\u2661&\"'".encode("iso-2022-jp", xml: :attr))
assert_equal("&amp;\u3046\u2661&amp;\"'".force_encoding("utf-8"),
@@ -912,6 +912,21 @@ class TestEncodingConverter < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /\u{3042}/) {
Encoding::Converter.new("", "", newline: "\u{3042}".to_sym)
}
+ newlines = %i[universal_newline crlf_newline cr_newline]
+ (2..newlines.size).each do |i|
+ newlines.combination(i) do |opts|
+ assert_raise(Encoding::ConverterNotFoundError, "#{opts} are mutually exclusive") do
+ Encoding::Converter.new("", "", **opts.inject({}) {|o,nl|o[nl]=true;o})
+ end
+ end
+ end
+ newlines.each do |nl|
+ opts = {newline: :universal, nl => true}
+ ec2 = assert_warning(/:newline option preceds/, opts.inspect) do
+ Encoding::Converter.new("", "", **opts)
+ end
+ assert_equal(ec1, ec2)
+ end
end
def test_default_external
diff --git a/test/ruby/test_encoding.rb b/test/ruby/test_encoding.rb
index 019cb2417f..2965c0bc7b 100644
--- a/test/ruby/test_encoding.rb
+++ b/test/ruby/test_encoding.rb
@@ -56,11 +56,36 @@ class TestEncoding < Test::Unit::TestCase
end
def test_replicate
- assert_instance_of(Encoding, Encoding::UTF_8.replicate('UTF-8-ANOTHER'))
- assert_instance_of(Encoding, Encoding::ISO_2022_JP.replicate('ISO-2022-JP-ANOTHER'))
+ assert_separately([], "#{<<~'END;'}")
+ assert_instance_of(Encoding, Encoding::UTF_8.replicate("UTF-8-ANOTHER#{Time.now.to_f}"))
+ assert_instance_of(Encoding, Encoding::ISO_2022_JP.replicate("ISO-2022-JP-ANOTHER#{Time.now.to_f}"))
bug3127 = '[ruby-dev:40954]'
assert_raise(TypeError, bug3127) {Encoding::UTF_8.replicate(0)}
- assert_raise(ArgumentError, bug3127) {Encoding::UTF_8.replicate("\0")}
+ assert_raise_with_message(ArgumentError, /\bNUL\b/, bug3127) {Encoding::UTF_8.replicate("\0")}
+ END;
+ end
+
+ def test_extra_encoding
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ 200.times {|i|
+ Encoding::UTF_8.replicate("dummy#{i}")
+ }
+ e = Encoding.list.last
+ format = "%d".force_encoding(e)
+ assert_equal("0", format % 0)
+ assert_equal(e, format.dup.encoding)
+ assert_equal(e, (format*1).encoding)
+
+ assert_equal(e, (("x"*30).force_encoding(e)*1).encoding)
+ GC.start
+
+ name = "A" * 64
+ Encoding.list.each do |enc|
+ assert_raise(ArgumentError) {enc.replicate(name)}
+ name.succ!
+ end
+ end;
end
def test_dummy_p
diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb
index ef732b9924..c527191eff 100644
--- a/test/ruby/test_enum.rb
+++ b/test/ruby/test_enum.rb
@@ -27,7 +27,6 @@ class TestEnumerable < Test::Unit::TestCase
end
end
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -63,11 +62,32 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal([[2, 1], [2, 4]], a)
end
+ def test_grep_optimization
+ bug17030 = '[ruby-core:99156]'
+ 'set last match' =~ /set last (.*)/
+ assert_equal([:a, 'b', :c], [:a, 'b', 'z', :c, 42, nil].grep(/[a-d]/), bug17030)
+ assert_equal(['z', 42, nil], [:a, 'b', 'z', :c, 42, nil].grep_v(/[a-d]/), bug17030)
+ assert_equal('match', $1, bug17030)
+
+ regexp = Regexp.new('x')
+ assert_equal([], @obj.grep(regexp), bug17030) # sanity check
+ def regexp.===(other)
+ true
+ end
+ assert_equal([1, 2, 3, 1, 2], @obj.grep(regexp), bug17030)
+
+ o = Object.new
+ def o.to_str
+ 'hello'
+ end
+ assert_same(o, [o].grep(/ll/).first, bug17030)
+ end
+
def test_count
assert_equal(5, @obj.count)
assert_equal(2, @obj.count(1))
assert_equal(3, @obj.count {|x| x % 2 == 1 })
- assert_equal(2, @obj.count(1) {|x| x % 2 == 1 })
+ assert_equal(2, assert_warning(/given block not used/) {@obj.count(1) {|x| x % 2 == 1 }})
assert_raise(ArgumentError) { @obj.count(0, 1) }
if RUBY_ENGINE == "ruby"
@@ -95,7 +115,7 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal(1, @obj.find_index {|x| x % 2 == 0 })
assert_equal(nil, @obj.find_index {|x| false })
assert_raise(ArgumentError) { @obj.find_index(0, 1) }
- assert_equal(1, @obj.find_index(2) {|x| x == 1 })
+ assert_equal(1, assert_warning(/given block not used/) {@obj.find_index(2) {|x| x == 1 }})
end
def test_find_all
@@ -211,7 +231,7 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal(48, @obj.inject {|z, x| z * 2 + x })
assert_equal(12, @obj.inject(:*))
assert_equal(24, @obj.inject(2) {|z, x| z * x })
- assert_equal(24, @obj.inject(2, :*) {|z, x| z * x })
+ assert_equal(24, assert_warning(/given block not used/) {@obj.inject(2, :*) {|z, x| z * x }})
assert_equal(nil, @empty.inject() {9})
end
@@ -246,6 +266,62 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal(2.0+3.0i, [2.0, 3.0i].inject(:+))
end
+ def test_inject_op_redefined
+ assert_separately([], "#{<<~"end;"}\n""end")
+ k = Class.new do
+ include Enumerable
+ def each
+ yield 1
+ yield 2
+ yield 3
+ end
+ end
+ all_assertions_foreach("", *%i[+ * / - %]) do |op|
+ bug = '[ruby-dev:49510] [Bug#12178] should respect redefinition'
+ begin
+ Integer.class_eval do
+ alias_method :orig, op
+ define_method(op) do |x|
+ 0
+ end
+ end
+ assert_equal(0, k.new.inject(op), bug)
+ ensure
+ Integer.class_eval do
+ undef_method op
+ alias_method op, :orig
+ end
+ end
+ end;
+ end
+
+ def test_inject_op_private
+ assert_separately([], "#{<<~"end;"}\n""end")
+ k = Class.new do
+ include Enumerable
+ def each
+ yield 1
+ yield 2
+ yield 3
+ end
+ end
+ all_assertions_foreach("", *%i[+ * / - %]) do |op|
+ bug = '[ruby-core:81349] [Bug #13592] should respect visibility'
+ assert_raise_with_message(NoMethodError, /private method/, bug) do
+ begin
+ Integer.class_eval do
+ private op
+ end
+ k.new.inject(op)
+ ensure
+ Integer.class_eval do
+ public op
+ end
+ end
+ end
+ end;
+ end
+
def test_inject_array_op_redefined
assert_separately([], "#{<<~"end;"}\n""end")
all_assertions_foreach("", *%i[+ * / - %]) do |op|
@@ -286,6 +362,25 @@ class TestEnumerable < Test::Unit::TestCase
end;
end
+ def test_refine_Enumerable_then_include
+ assert_separately([], "#{<<~"end;"}\n")
+ module RefinementBug
+ refine Enumerable do
+ def refined_method
+ :rm
+ end
+ end
+ end
+ using RefinementBug
+
+ class A
+ include Enumerable
+ end
+
+ assert_equal(:rm, [].refined_method)
+ end;
+ end
+
def test_partition
assert_equal([[1, 3, 1], [2, 2]], @obj.partition {|x| x % 2 == 1 })
cond = ->(x, i) { x % 2 == 1 }
@@ -359,7 +454,7 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal(false, [true, true, false].all?)
assert_equal(true, [].all?)
assert_equal(true, @empty.all?)
- assert_equal(true, @obj.all?(Fixnum))
+ assert_equal(true, @obj.all?(Integer))
assert_equal(false, @obj.all?(1..2))
end
diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb
index b619150571..eb15d4b616 100644
--- a/test/ruby/test_enumerator.rb
+++ b/test/ruby/test_enumerator.rb
@@ -69,16 +69,16 @@ class TestEnumerator < Test::Unit::TestCase
def test_initialize
assert_equal([1, 2, 3], @obj.to_enum(:foo, 1, 2, 3).to_a)
- _, err = capture_io do
- assert_equal([1, 2, 3], Enumerator.new(@obj, :foo, 1, 2, 3).to_a)
- end
+ assert_raise(ArgumentError) {
+ Enumerator.new(@obj, :foo, 1, 2, 3)
+ }
assert_equal([1, 2, 3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3))
assert_raise(ArgumentError) { Enumerator.new }
enum = @obj.to_enum
assert_raise(NoMethodError) { enum.each {} }
enum.freeze
- assert_raise(FrozenError) {
+ assert_raise(ArgumentError) {
capture_io do
# warning: Enumerator.new without a block is deprecated; use Object#to_enum
enum.__send__(:initialize, @obj, :foo)
diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb
index 02cd3b8502..6779c94dde 100644
--- a/test/ruby/test_env.rb
+++ b/test/ruby/test_env.rb
@@ -22,7 +22,6 @@ class TestEnv < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
@backup = ENV.to_hash
ENV.delete('test')
ENV.delete('TEST')
@@ -84,7 +83,6 @@ class TestEnv < Test::Unit::TestCase
ENV['test'] = val[0...-1]
assert_nil(ENV.key(val))
- assert_nil(ENV.index(val))
assert_nil(ENV.key(val.upcase))
ENV['test'] = val
if IGNORE_CASE
@@ -106,6 +104,7 @@ class TestEnv < Test::Unit::TestCase
assert_invalid_env {|v| ENV.delete(v)}
assert_nil(ENV.delete("TEST"))
assert_nothing_raised { ENV.delete(PATH_ENV) }
+ assert_equal("NO TEST", ENV.delete("TEST") {|name| "NO "+name})
end
def test_getenv
@@ -286,6 +285,17 @@ class TestEnv < Test::Unit::TestCase
assert_equal({"foo"=>"bar", "baz"=>"qux"}, ENV.slice("foo", "baz"))
end
+ def test_except
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ ENV["bar"] = "rab"
+ assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, ENV.except())
+ assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, ENV.except(""))
+ assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, ENV.except("unknown"))
+ assert_equal({"bar"=>"rab"}, ENV.except("foo", "baz"))
+ end
+
def test_clear
ENV.clear
assert_equal(0, ENV.size)
@@ -358,7 +368,8 @@ class TestEnv < Test::Unit::TestCase
assert_equal("foo", v)
end
assert_invalid_env {|var| ENV.assoc(var)}
- assert_equal(Encoding.find("locale"), v.encoding)
+ encoding = /mswin|mingw/ =~ RUBY_PLATFORM ? Encoding::UTF_8 : Encoding.find("locale")
+ assert_equal(encoding, v.encoding)
end
def test_has_value2
@@ -406,8 +417,8 @@ class TestEnv < Test::Unit::TestCase
def check(as, bs)
if IGNORE_CASE
- as = as.map {|xs| xs.map {|x| x.upcase } }
- bs = bs.map {|xs| xs.map {|x| x.upcase } }
+ as = as.map {|k, v| [k.upcase, v] }
+ bs = bs.map {|k, v| [k.upcase, v] }
end
assert_equal(as.sort, bs.sort)
end
@@ -568,15 +579,13 @@ class TestEnv < Test::Unit::TestCase
end;
end
- if Encoding.find("locale") == Encoding::UTF_8
- def test_utf8
- text = "testing \u{e5 e1 e2 e4 e3 101 3042}"
- test = ENV["test"]
- ENV["test"] = text
- assert_equal text, ENV["test"]
- ensure
- ENV["test"] = test
- end
+ def test_utf8
+ text = "testing \u{e5 e1 e2 e4 e3 101 3042}"
+ test = ENV["test"]
+ ENV["test"] = text
+ assert_equal text, ENV["test"]
+ ensure
+ ENV["test"] = test
end
end
end
diff --git a/test/ruby/test_eval.rb b/test/ruby/test_eval.rb
index 3d6116edbc..bf551c6845 100644
--- a/test/ruby/test_eval.rb
+++ b/test/ruby/test_eval.rb
@@ -347,6 +347,10 @@ class TestEval < Test::Unit::TestCase
assert_equal(55, eval("foo22"))
assert_equal(55, foo22)
}.call
+
+ self.class.class_eval do
+ remove_const :EvTest
+ end
end
def test_nil_instance_eval_cvar
@@ -470,9 +474,12 @@ class TestEval < Test::Unit::TestCase
end
def test_eval_location_binding
- assert_warning(/__FILE__ in eval/) do
- assert_equal(__FILE__, eval("__FILE__", binding))
- end
+ assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", nil))
+ assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", binding))
+ assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", nil, 'foo'))
+ assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", binding, 'foo'))
+ assert_equal(['foo', 2], eval("[__FILE__, __LINE__]", nil, 'foo', 2))
+ assert_equal(['foo', 2], eval("[__FILE__, __LINE__]", binding, 'foo', 2))
end
def test_fstring_instance_eval
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 9efcfc76cf..6ab72e7954 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -459,16 +459,6 @@ end.join
assert_not_send([e, :success?], "abort means failure")
end
- def test_nomethoderror
- bug3237 = '[ruby-core:29948]'
- str = "\u2600"
- id = :"\u2604"
- msg = "undefined method `#{id}' for \"#{str}\":String"
- assert_raise_with_message(NoMethodError, msg, bug3237) do
- str.__send__(id)
- end
- end
-
def test_errno
assert_equal(Encoding.find("locale"), Errno::EINVAL.new.message.encoding)
end
@@ -869,259 +859,6 @@ end.join
assert_in_out_err([], "raise Class.new(RuntimeError), 'foo'", [], /foo\n/)
end
- PrettyObject =
- Class.new(BasicObject) do
- alias object_id __id__
- def pretty_inspect; "`obj'"; end
- alias inspect pretty_inspect
- end
-
- def test_frozen_error_receiver
- obj = Object.new.freeze
- (obj.foo = 1) rescue (e = $!)
- assert_same(obj, e.receiver)
- obj.singleton_class.const_set(:A, 2) rescue (e = $!)
- assert_same(obj.singleton_class, e.receiver)
- end
-
- def test_frozen_error_initialize
- obj = Object.new
- exc = FrozenError.new("bar", receiver: obj)
- assert_equal("bar", exc.message)
- assert_same(obj, exc.receiver)
-
- exc = FrozenError.new("bar")
- assert_equal("bar", exc.message)
- assert_raise_with_message(ArgumentError, "no receiver is available") {
- exc.receiver
- }
-
- exc = FrozenError.new
- assert_equal("FrozenError", exc.message)
- assert_raise_with_message(ArgumentError, "no receiver is available") {
- exc.receiver
- }
- end
-
- def test_frozen_error_message
- obj = Object.new.freeze
- e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) {
- obj.instance_variable_set(:@test, true)
- }
- assert_include(e.message, obj.inspect)
-
- klass = Class.new do
- def init
- @x = true
- end
- def inspect
- init
- super
- end
- end
- obj = klass.new.freeze
- e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) {
- obj.init
- }
- assert_include(e.message, klass.inspect)
- end
-
- def test_name_error_new_default
- error = NameError.new
- assert_equal("NameError", error.message)
- end
-
- def test_name_error_new_message
- error = NameError.new("Message")
- assert_equal("Message", error.message)
- end
-
- def test_name_error_new_name
- error = NameError.new("Message")
- assert_nil(error.name)
-
- error = NameError.new("Message", :foo)
- assert_equal(:foo, error.name)
- end
-
- def test_name_error_new_receiver
- receiver = Object.new
-
- error = NameError.new
- assert_raise(ArgumentError) {error.receiver}
- assert_equal("NameError", error.message)
-
- error = NameError.new(receiver: receiver)
- assert_equal(["NameError", receiver],
- [error.message, error.receiver])
-
- error = NameError.new("Message", :foo, receiver: receiver)
- assert_equal(["Message", receiver, :foo],
- [error.message, error.receiver, error.name])
- end
-
- def test_nomethod_error_new_default
- error = NoMethodError.new
- assert_equal("NoMethodError", error.message)
- end
-
- def test_nomethod_error_new_message
- error = NoMethodError.new("Message")
- assert_equal("Message", error.message)
- end
-
- def test_nomethod_error_new_name
- error = NoMethodError.new("Message")
- assert_nil(error.name)
-
- error = NoMethodError.new("Message", :foo)
- assert_equal(:foo, error.name)
- end
-
- def test_nomethod_error_new_name_args
- error = NoMethodError.new("Message", :foo)
- assert_nil(error.args)
-
- error = NoMethodError.new("Message", :foo, [1, 2])
- assert_equal([:foo, [1, 2]], [error.name, error.args])
- end
-
- def test_nomethod_error_new_name_args_priv
- error = NoMethodError.new("Message", :foo, [1, 2])
- assert_not_predicate(error, :private_call?)
-
- error = NoMethodError.new("Message", :foo, [1, 2], true)
- assert_equal([:foo, [1, 2], true],
- [error.name, error.args, error.private_call?])
- end
-
- def test_nomethod_error_new_receiver
- receiver = Object.new
-
- error = NoMethodError.new
- assert_raise(ArgumentError) {error.receiver}
-
- error = NoMethodError.new(receiver: receiver)
- assert_equal(receiver, error.receiver)
-
- error = NoMethodError.new("Message")
- assert_raise(ArgumentError) {error.receiver}
-
- error = NoMethodError.new("Message", receiver: receiver)
- assert_equal(["Message", receiver],
- [error.message, error.receiver])
-
- error = NoMethodError.new("Message", :foo)
- assert_raise(ArgumentError) {error.receiver}
-
- msg = defined?(DidYouMean.formatter) ?
- "Message\nDid you mean? for" : "Message"
-
- error = NoMethodError.new("Message", :foo, receiver: receiver)
- assert_equal([msg, :foo, receiver],
- [error.message, error.name, error.receiver])
-
- error = NoMethodError.new("Message", :foo, [1, 2])
- assert_raise(ArgumentError) {error.receiver}
-
- error = NoMethodError.new("Message", :foo, [1, 2], receiver: receiver)
- assert_equal([msg, :foo, [1, 2], receiver],
- [error.message, error.name, error.args, error.receiver])
-
- error = NoMethodError.new("Message", :foo, [1, 2], true)
- assert_raise(ArgumentError) {error.receiver}
-
- error = NoMethodError.new("Message", :foo, [1, 2], true, receiver: receiver)
- assert_equal([:foo, [1, 2], true, receiver],
- [error.name, error.args, error.private_call?, error.receiver])
- end
-
- def test_name_error_info_const
- obj = PrettyObject.new
-
- e = assert_raise(NameError) {
- obj.instance_eval("Object")
- }
- assert_equal(:Object, e.name)
-
- e = assert_raise(NameError) {
- BasicObject::X
- }
- assert_same(BasicObject, e.receiver)
- assert_equal(:X, e.name)
- end
-
- def test_name_error_info_method
- obj = PrettyObject.new
-
- e = assert_raise(NameError) {
- obj.instance_eval {foo}
- }
- assert_equal(:foo, e.name)
- assert_same(obj, e.receiver)
-
- e = assert_raise(NoMethodError) {
- obj.foo(1, 2)
- }
- assert_equal(:foo, e.name)
- assert_equal([1, 2], e.args)
- assert_same(obj, e.receiver)
- assert_not_predicate(e, :private_call?)
-
- e = assert_raise(NoMethodError) {
- obj.instance_eval {foo(1, 2)}
- }
- assert_equal(:foo, e.name)
- assert_equal([1, 2], e.args)
- assert_same(obj, e.receiver)
- assert_predicate(e, :private_call?)
- end
-
- def test_name_error_info_local_variables
- obj = PrettyObject.new
- def obj.test(a, b=nil, *c, &d)
- e = a
- 1.times {|f| g = foo; g}
- e
- end
-
- e = assert_raise(NameError) {
- obj.test(3)
- }
- assert_equal(:foo, e.name)
- assert_same(obj, e.receiver)
- assert_equal(%i[a b c d e f g], e.local_variables.sort)
- end
-
- def test_name_error_info_method_missing
- obj = PrettyObject.new
- def obj.method_missing(*)
- super
- end
-
- e = assert_raise(NoMethodError) {
- obj.foo(1, 2)
- }
- assert_equal(:foo, e.name)
- assert_equal([1, 2], e.args)
- assert_same(obj, e.receiver)
- assert_not_predicate(e, :private_call?)
-
- e = assert_raise(NoMethodError) {
- obj.instance_eval {foo(1, 2)}
- }
- assert_equal(:foo, e.name)
- assert_equal([1, 2], e.args)
- assert_same(obj, e.receiver)
- assert_predicate(e, :private_call?)
- end
-
- def test_name_error_info_parent_iseq_mark
- assert_separately(['-', File.join(__dir__, 'bug-11928.rb')], <<-'end;')
- -> {require ARGV[0]}.call
- end;
- end
-
def test_output_string_encoding
# "\x82\xa0" in cp932 is "\u3042" (Japanese hiragana 'a')
# change $stderr to force calling rb_io_write() instead of fwrite()
@@ -1199,28 +936,37 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
end
- def capture_warning_warn
+ def capture_warning_warn(category: false)
verbose = $VERBOSE
deprecated = Warning[:deprecated]
+ experimental = Warning[:experimental]
warning = []
::Warning.class_eval do
alias_method :warn2, :warn
remove_method :warn
- define_method(:warn) do |str|
- warning << str
+ if category
+ define_method(:warn) do |str, category: nil|
+ warning << [str, category]
+ end
+ else
+ define_method(:warn) do |str|
+ warning << str
+ end
end
end
$VERBOSE = true
Warning[:deprecated] = true
+ Warning[:experimental] = true
yield
return warning
ensure
$VERBOSE = verbose
Warning[:deprecated] = deprecated
+ Warning[:experimental] = experimental
::Warning.class_eval do
remove_method :warn
@@ -1230,14 +976,38 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
def test_warning_warn
- warning = capture_warning_warn {@a}
- assert_match(/instance variable @a not initialized/, warning[0])
+ warning = capture_warning_warn {$asdfasdsda_test_warning_warn}
+ assert_match(/global variable `\$asdfasdsda_test_warning_warn' not initialized/, warning[0])
assert_equal(["a\nz\n"], capture_warning_warn {warn "a\n", "z"})
assert_equal([], capture_warning_warn {warn})
assert_equal(["\n"], capture_warning_warn {warn ""})
end
+ def test_warn_deprecated_backwards_compatibility_category
+ warning = capture_warning_warn { Dir.exists?("non-existent") }
+
+ assert_match(/deprecated/, warning[0])
+ end
+
+ def test_warn_deprecated_category
+ warning = capture_warning_warn(category: true) { Dir.exists?("non-existent") }
+
+ assert_equal :deprecated, warning[0][1]
+ end
+
+ def test_warn_deprecated_to_remove_backwards_compatibility_category
+ warning = capture_warning_warn { Object.new.tainted? }
+
+ assert_match(/deprecated/, warning[0])
+ end
+
+ def test_warn_deprecated_to_remove_category
+ warning = capture_warning_warn(category: true) { Object.new.tainted? }
+
+ assert_equal :deprecated, warning[0][1]
+ end
+
def test_kernel_warn_uplevel
warning = capture_warning_warn {warn("test warning", uplevel: 0)}
assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0])
@@ -1249,8 +1019,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
assert_raise(ArgumentError) {warn("test warning", uplevel: -1)}
assert_in_out_err(["-e", "warn 'ok', uplevel: 1"], '', [], /warning:/)
warning = capture_warning_warn {warn("test warning", {uplevel: 0})}
- assert_equal("#{__FILE__}:#{__LINE__-1}: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call\n", warning[0])
- assert_match(/warning: The called method (?:`.*' )?is defined here|warning: test warning/, warning[1])
+ assert_match(/test warning.*{:uplevel=>0}/m, warning[0])
warning = capture_warning_warn {warn("test warning", **{uplevel: 0})}
assert_equal("#{__FILE__}:#{__LINE__-1}: warning: test warning\n", warning[0])
warning = capture_warning_warn {warn("test warning", {uplevel: 0}, **{})}
@@ -1279,10 +1048,12 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
t.puts "require '#{basename}'"
t.close
$LOAD_PATH.push(File.dirname(t))
- warning = capture_warning_warn {require basename}
+ warning = capture_warning_warn {
+ assert require(basename)
+ }
ensure
$LOAD_PATH.pop
- $LOADED_FEATURES.delete(t)
+ $LOADED_FEATURES.delete(t.path)
end
assert_equal(1, warning.size)
assert_match(/circular require/, warning.first)
@@ -1290,7 +1061,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
def test_warning_warn_super
- assert_in_out_err(%[-W0], "#{<<~"{#"}\n#{<<~'};'}", [], /instance variable @a not initialized/)
+ assert_in_out_err(%[-W0], "#{<<~"{#"}\n#{<<~'};'}", [], /global variable `\$asdfiasdofa_test_warning_warn_super' not initialized/)
{#
module Warning
def warn(message)
@@ -1299,7 +1070,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
$VERBOSE = true
- @a
+ $asdfiasdofa_test_warning_warn_super
};
end
@@ -1310,6 +1081,54 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
assert_include([true, false], Warning[:experimental])
end
+ def test_warning_category_deprecated
+ warning = EnvUtil.verbose_warning do
+ deprecated = Warning[:deprecated]
+ Warning[:deprecated] = true
+ Warning.warn "deprecated feature", category: :deprecated
+ ensure
+ Warning[:deprecated] = deprecated
+ end
+ assert_equal "deprecated feature", warning
+
+ warning = EnvUtil.verbose_warning do
+ deprecated = Warning[:deprecated]
+ Warning[:deprecated] = false
+ Warning.warn "deprecated feature", category: :deprecated
+ ensure
+ Warning[:deprecated] = deprecated
+ end
+ assert_empty warning
+ end
+
+ def test_warning_category_experimental
+ warning = EnvUtil.verbose_warning do
+ experimental = Warning[:experimental]
+ Warning[:experimental] = true
+ Warning.warn "experimental feature", category: :experimental
+ ensure
+ Warning[:experimental] = experimental
+ end
+ assert_equal "experimental feature", warning
+
+ warning = EnvUtil.verbose_warning do
+ experimental = Warning[:experimental]
+ Warning[:experimental] = false
+ Warning.warn "experimental feature", category: :experimental
+ ensure
+ Warning[:experimental] = experimental
+ end
+ assert_empty warning
+ end
+
+ def test_undef_Warning_warn
+ assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
+ begin;
+ Warning.undef_method(:warn)
+ assert_raise(NoMethodError) { warn "" }
+ end;
+ end
+
def test_undefined_backtrace
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
begin;
@@ -1459,13 +1278,11 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
if Exception.to_tty?
assert_match(/\e/, message)
message = message.gsub(/\e\[[\d;]*m/, '')
- assert_operator(message, :start_with?, remark)
- assert_operator(message, :end_with?, bottom)
else
assert_not_match(/\e/, message)
- assert_operator(message, :start_with?, bottom)
- assert_operator(message, :end_with?, top)
end
+ assert_operator(message, :start_with?, bottom)
+ assert_operator(message, :end_with?, top)
end
def test_exception_in_message
diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb
index 20436eca69..9e994c7349 100644
--- a/test/ruby/test_fiber.rb
+++ b/test/ruby/test_fiber.rb
@@ -34,7 +34,7 @@ class TestFiber < Test::Unit::TestCase
end
def test_many_fibers
- skip 'This is unstable on GitHub Actions --jit-wait. TODO: debug it' if RubyVM::MJIT.enabled?
+ skip 'This is unstable on GitHub Actions --jit-wait. TODO: debug it' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
max = 10_000
assert_equal(max, max.times{
Fiber.new{}
@@ -50,7 +50,7 @@ class TestFiber < Test::Unit::TestCase
end
def test_many_fibers_with_threads
- assert_normal_exit <<-SRC, timeout: 60
+ assert_normal_exit <<-SRC, timeout: 180
max = 1000
@cnt = 0
(1..100).map{|ti|
@@ -169,6 +169,16 @@ class TestFiber < Test::Unit::TestCase
assert_equal(:ok, fib.raise)
end
+ def test_raise_transferring_fiber
+ root = Fiber.current
+ fib = Fiber.new { root.transfer }
+ fib.transfer
+ assert_raise(RuntimeError){
+ fib.raise "can raise with transfer: true"
+ }
+ assert_not_predicate(fib, :alive?)
+ end
+
def test_transfer
ary = []
f2 = nil
@@ -184,6 +194,33 @@ class TestFiber < Test::Unit::TestCase
assert_equal([:baz], ary)
end
+ def test_terminate_transferred_fiber
+ log = []
+ fa1 = fa2 = fb1 = r1 = nil
+
+ fa1 = Fiber.new{
+ fa2 = Fiber.new{
+ log << :fa2_terminate
+ }
+ fa2.resume
+ log << :fa1_terminate
+ }
+ fb1 = Fiber.new{
+ fa1.transfer
+ log << :fb1_terminate
+ }
+
+ r1 = Fiber.new{
+ fb1.transfer
+ log << :r1_terminate
+ }
+
+ r1.resume
+ log << :root_terminate
+
+ assert_equal [:fa2_terminate, :fa1_terminate, :r1_terminate, :root_terminate], log
+ end
+
def test_tls
#
def tvar(var, val)
@@ -278,29 +315,71 @@ class TestFiber < Test::Unit::TestCase
assert_instance_of(Class, Fiber.new(&Class.new.method(:undef_method)).resume(:to_s), bug5083)
end
- def test_prohibit_resume_transferred_fiber
+ def test_prohibit_transfer_to_resuming_fiber
+ root_fiber = Fiber.current
+
assert_raise(FiberError){
- root_fiber = Fiber.current
- f = Fiber.new{
- root_fiber.transfer
- }
- f.transfer
- f.resume
+ fiber = Fiber.new{ root_fiber.transfer }
+ fiber.resume
+ }
+
+ fa1 = Fiber.new{
+ _fa2 = Fiber.new{ root_fiber.transfer }
+ }
+ fb1 = Fiber.new{
+ _fb2 = Fiber.new{ root_fiber.transfer }
}
+ fa1.transfer
+ fb1.transfer
+
assert_raise(FiberError){
- g=nil
- f=Fiber.new{
- g.resume
- g.resume
- }
- g=Fiber.new{
- f.resume
- f.resume
+ fa1.transfer
+ }
+ assert_raise(FiberError){
+ fb1.transfer
+ }
+ end
+
+ def test_prohibit_transfer_to_yielding_fiber
+ f1 = f2 = f3 = nil
+
+ f1 = Fiber.new{
+ f2 = Fiber.new{
+ f3 = Fiber.new{
+ p f3: Fiber.yield
+ }
+ f3.resume
}
- f.transfer
+ f2.resume
+ }
+ f1.resume
+
+ assert_raise(FiberError){ f3.transfer 10 }
+ end
+
+ def test_prohibit_resume_to_transferring_fiber
+ root_fiber = Fiber.current
+
+ assert_raise(FiberError){
+ Fiber.new{
+ root_fiber.resume
+ }.transfer
+ }
+
+ f1 = f2 = nil
+ f1 = Fiber.new do
+ f2.transfer
+ end
+ f2 = Fiber.new do
+ f1.resume # attempt to resume transferring fiber
+ end
+
+ assert_raise(FiberError){
+ f1.transfer
}
end
+
def test_fork_from_fiber
skip 'fork not supported' unless Process.respond_to?(:fork)
pid = nil
@@ -329,6 +408,11 @@ class TestFiber < Test::Unit::TestCase
pid, status = Process.waitpid2(pid)
assert_not_predicate(status, :signaled?, bug5700)
assert_predicate(status, :success?, bug5700)
+
+ pid = Fiber.new {fork}.resume
+ pid, status = Process.waitpid2(pid)
+ assert_not_predicate(status, :signaled?)
+ assert_predicate(status, :success?)
end
def test_exit_in_fiber
@@ -347,50 +431,6 @@ class TestFiber < Test::Unit::TestCase
EOS
end
- def invoke_rec script, vm_stack_size, machine_stack_size, use_length = true
- env = {}
- env['RUBY_FIBER_VM_STACK_SIZE'] = vm_stack_size.to_s if vm_stack_size
- env['RUBY_FIBER_MACHINE_STACK_SIZE'] = machine_stack_size.to_s if machine_stack_size
- out = Dir.mktmpdir("test_fiber") {|tmpdir|
- out, err, status = EnvUtil.invoke_ruby([env, '-e', script], '', true, true, chdir: tmpdir, timeout: 30)
- assert(!status.signaled?, FailDesc[status, nil, err])
- out
- }
- use_length ? out.length : out
- end
-
- def test_stack_size
- h_default = eval(invoke_rec('p RubyVM::DEFAULT_PARAMS', nil, nil, false))
- h_0 = eval(invoke_rec('p RubyVM::DEFAULT_PARAMS', 0, 0, false))
- h_large = eval(invoke_rec('p RubyVM::DEFAULT_PARAMS', 1024 * 1024 * 5, 1024 * 1024 * 10, false))
-
- assert_operator(h_default[:fiber_vm_stack_size], :>, h_0[:fiber_vm_stack_size])
- assert_operator(h_default[:fiber_vm_stack_size], :<, h_large[:fiber_vm_stack_size])
- assert_operator(h_default[:fiber_machine_stack_size], :>=, h_0[:fiber_machine_stack_size])
- assert_operator(h_default[:fiber_machine_stack_size], :<=, h_large[:fiber_machine_stack_size])
-
- # check VM machine stack size
- script = '$stdout.sync=true; def rec; print "."; rec; end; Fiber.new{rec}.resume'
- size_default = invoke_rec script, nil, nil
- assert_operator(size_default, :>, 0)
- size_0 = invoke_rec script, 0, nil
- assert_operator(size_default, :>, size_0)
- size_large = invoke_rec script, 1024 * 1024 * 5, nil
- assert_operator(size_default, :<, size_large)
-
- return if /mswin|mingw/ =~ RUBY_PLATFORM
-
- # check machine stack size
- # Note that machine stack size may not change size (depend on OSs)
- script = '$stdout.sync=true; def rec; print "."; 1.times{1.times{1.times{rec}}}; end; Fiber.new{rec}.resume'
- vm_stack_size = 1024 * 1024
- size_default = invoke_rec script, vm_stack_size, nil
- size_0 = invoke_rec script, vm_stack_size, 0
- assert_operator(size_default, :>=, size_0)
- size_large = invoke_rec script, vm_stack_size, 1024 * 1024 * 10
- assert_operator(size_default, :<=, size_large)
- end
-
def test_separate_lastmatch
bug7678 = '[ruby-core:51331]'
/a/ =~ "a"
diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb
index 975bcb6bc2..e2314424b3 100644
--- a/test/ruby/test_file_exhaustive.rb
+++ b/test/ruby/test_file_exhaustive.rb
@@ -130,7 +130,7 @@ class TestFileExhaustive < Test::Unit::TestCase
@hardlinkfile = make_tmp_filename("hardlinkfile")
begin
File.link(regular_file, @hardlinkfile)
- rescue NotImplementedError, Errno::EINVAL # EINVAL for Windows Vista
+ rescue NotImplementedError, Errno::EINVAL, Errno::EACCES # EINVAL for Windows Vista, EACCES for Android Termux
@hardlinkfile = nil
end
@hardlinkfile
@@ -679,6 +679,13 @@ class TestFileExhaustive < Test::Unit::TestCase
File.utime(t + 1, t + 2, zerofile)
assert_equal(t + 1, File.atime(zerofile))
assert_equal(t + 2, File.mtime(zerofile))
+ Dir.mktmpdir do |dir|
+ Dir.chdir do
+ path = "foo\u{30b3 30d4 30fc}"
+ File.write(path, "") rescue next
+ assert_equal(1, File.utime(nil, nil, path))
+ end
+ end
end
def test_utime_symlinkfile
diff --git a/test/ruby/test_fixnum.rb b/test/ruby/test_fixnum.rb
index bd18067dda..2878258920 100644
--- a/test/ruby/test_fixnum.rb
+++ b/test/ruby/test_fixnum.rb
@@ -4,7 +4,6 @@ require 'test/unit'
class TestFixnum < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index 9c24dac8e6..b218b72db5 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -323,6 +323,7 @@ class TestFloat < Test::Unit::TestCase
assert_equal(1.0, 1.0 ** (2**32))
assert_equal(1.0, 1.0 ** 1.0)
assert_raise(TypeError) { 1.0 ** nil }
+ assert_equal(9.0, 3.0 ** 2)
end
def test_eql
@@ -782,6 +783,9 @@ class TestFloat < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /xxx/) {
1.0.round(half: "\0xxx")
}
+ assert_raise_with_message(Encoding::CompatibilityError, /ASCII incompatible/) {
+ 1.0.round(half: "up".force_encoding("utf-16be"))
+ }
end
def test_Float
@@ -907,7 +911,8 @@ class TestFloat < Test::Unit::TestCase
a = rand
b = a+rand*1000
s = (b - a) / 10
- assert_equal(10, (a...b).step(s).to_a.length)
+ seq = (a...b).step(s)
+ assert_equal(10, seq.to_a.length, seq.inspect)
end
assert_equal([1.0, 2.9, 4.8, 6.699999999999999], (1.0...6.8).step(1.9).to_a)
diff --git a/test/ruby/test_frozen_error.rb b/test/ruby/test_frozen_error.rb
new file mode 100644
index 0000000000..ace1e4c775
--- /dev/null
+++ b/test/ruby/test_frozen_error.rb
@@ -0,0 +1,57 @@
+require 'test/unit'
+
+class TestFrozenError < Test::Unit::TestCase
+ def test_new_default
+ exc = FrozenError.new
+ assert_equal("FrozenError", exc.message)
+ assert_raise_with_message(ArgumentError, "no receiver is available") {
+ exc.receiver
+ }
+ end
+
+ def test_new_message
+ exc = FrozenError.new("bar")
+ assert_equal("bar", exc.message)
+ assert_raise_with_message(ArgumentError, "no receiver is available") {
+ exc.receiver
+ }
+ end
+
+ def test_new_receiver
+ obj = Object.new
+ exc = FrozenError.new("bar", receiver: obj)
+ assert_equal("bar", exc.message)
+ assert_same(obj, exc.receiver)
+ end
+
+ def test_message
+ obj = Object.new.freeze
+ e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) {
+ obj.instance_variable_set(:@test, true)
+ }
+ assert_include(e.message, obj.inspect)
+
+ klass = Class.new do
+ def init
+ @x = true
+ end
+ def inspect
+ init
+ super
+ end
+ end
+ obj = klass.new.freeze
+ e = assert_raise_with_message(FrozenError, /can't modify frozen #{obj.class}/) {
+ obj.init
+ }
+ assert_include(e.message, klass.inspect)
+ end
+
+ def test_receiver
+ obj = Object.new.freeze
+ e = assert_raise(FrozenError) {def obj.foo; end}
+ assert_same(obj, e.receiver)
+ e = assert_raise(FrozenError) {obj.singleton_class.const_set(:A, 2)}
+ assert_same(obj.singleton_class, e.receiver)
+ end
+end
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb
index ef99f69f50..01df198b0d 100644
--- a/test/ruby/test_gc.rb
+++ b/test/ruby/test_gc.rb
@@ -56,6 +56,7 @@ class TestGc < Test::Unit::TestCase
return unless use_rgengc?
skip 'stress' if GC.stress
+ 3.times { GC.start } # full mark and next time it should be minor mark
GC.start(full_mark: false)
assert_nil GC.latest_gc_info(:major_by)
@@ -91,16 +92,23 @@ class TestGc < Test::Unit::TestCase
assert_kind_of(Integer, res[:count])
stat, count = {}, {}
- GC.start
- GC.stat(stat)
- ObjectSpace.count_objects(count)
+ 2.times{ # to ignore const cache imemo creation
+ GC.start
+ GC.stat(stat)
+ ObjectSpace.count_objects(count)
+ # repeat same methods invocation for cache object creation.
+ GC.stat(stat)
+ ObjectSpace.count_objects(count)
+ }
assert_equal(count[:TOTAL]-count[:FREE], stat[:heap_live_slots])
assert_equal(count[:FREE], stat[:heap_free_slots])
# measure again without GC.start
- 1000.times{ "a" + "b" }
- GC.stat(stat)
- ObjectSpace.count_objects(count)
+ 2.times{ # to ignore const cache imemo creation
+ 1000.times{ "a" + "b" }
+ GC.stat(stat)
+ ObjectSpace.count_objects(count)
+ }
assert_equal(count[:FREE], stat[:heap_free_slots])
end
@@ -141,10 +149,15 @@ class TestGc < Test::Unit::TestCase
assert_equal :newobj, GC.latest_gc_info[:gc_by]
eom
+ GC.latest_gc_info(h = {}) # allocate hash and rehearsal
GC.start
- assert_equal :force, GC.latest_gc_info[:major_by] if use_rgengc?
- assert_equal :method, GC.latest_gc_info[:gc_by]
- assert_equal true, GC.latest_gc_info[:immediate_sweep]
+ GC.start
+ GC.start
+ GC.latest_gc_info(h)
+
+ assert_equal :force, h[:major_by] if use_rgengc?
+ assert_equal :method, h[:gc_by]
+ assert_equal true, h[:immediate_sweep]
GC.stress = true
assert_equal :force, GC.latest_gc_info[:major_by]
@@ -162,6 +175,16 @@ class TestGc < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) {GC.latest_gc_info(:"\u{30eb 30d3 30fc}")}
end
+ def test_stress_compile_send
+ assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "")
+ GC.stress = true
+ begin
+ eval("A::B.c(1, 1, d: 234)")
+ rescue
+ end
+ EOS
+ end
+
def test_singleton_method
assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "[ruby-dev:42832]")
GC.stress = true
@@ -224,12 +247,6 @@ class TestGc < Test::Unit::TestCase
# always full GC when RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR < 1.0
assert_in_out_err([env, "-e", "1000_000.times{Object.new}; p(GC.stat[:minor_gc_count] < GC.stat[:major_gc_count])"], "", ['true'], //, "") if use_rgengc?
- # check obsolete
- assert_in_out_err([{'RUBY_FREE_MIN' => '100'}, '-w', '-eexit'], '', [],
- /RUBY_FREE_MIN is obsolete. Use RUBY_GC_HEAP_FREE_SLOTS instead/)
- assert_in_out_err([{'RUBY_HEAP_MIN_SLOTS' => '100'}, '-w', '-eexit'], '', [],
- /RUBY_HEAP_MIN_SLOTS is obsolete. Use RUBY_GC_HEAP_INIT_SLOTS instead/)
-
env = {
"RUBY_GC_MALLOC_LIMIT" => "60000000",
"RUBY_GC_MALLOC_LIMIT_MAX" => "160000000",
@@ -304,7 +321,7 @@ class TestGc < Test::Unit::TestCase
base_length = GC.stat[:heap_eden_pages]
(base_length * 500).times{ 'a' }
GC.start
- assert_in_epsilon base_length, (v = GC.stat[:heap_eden_pages]), 1/8r,
+ assert_in_epsilon base_length, (v = GC.stat[:heap_eden_pages]), 1/4r,
"invalid heap expanding (base_length: #{base_length}, GC.stat[:heap_eden_pages]: #{v})"
a = []
diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb
index 75d9b01f2c..4a8cff33f4 100644
--- a/test/ruby/test_gc_compact.rb
+++ b/test/ruby/test_gc_compact.rb
@@ -1,8 +1,98 @@
# frozen_string_literal: true
require 'test/unit'
require 'fiddle'
+require 'etc'
class TestGCCompact < Test::Unit::TestCase
+ class AutoCompact < Test::Unit::TestCase
+ def setup
+ skip "autocompact not supported on this platform" unless supports_auto_compact?
+ super
+ end
+
+ def test_enable_autocompact
+ before = GC.auto_compact
+ GC.auto_compact = true
+ assert GC.auto_compact
+ ensure
+ GC.auto_compact = before
+ end
+
+ def test_disable_autocompact
+ before = GC.auto_compact
+ GC.auto_compact = false
+ refute GC.auto_compact
+ ensure
+ GC.auto_compact = before
+ end
+
+ def test_major_compacts
+ before = GC.auto_compact
+ GC.auto_compact = true
+ compact = GC.stat :compact_count
+ GC.start
+ assert_operator GC.stat(:compact_count), :>, compact
+ ensure
+ GC.auto_compact = before
+ end
+
+ def test_implicit_compaction_does_something
+ before = GC.auto_compact
+ list = []
+ list2 = []
+
+ # Try to make some fragmentation
+ 500.times {
+ list << Object.new
+ Object.new
+ Object.new
+ }
+ count = GC.stat :compact_count
+ GC.auto_compact = true
+ loop do
+ break if count < GC.stat(:compact_count)
+ list2 << Object.new
+ end
+ compact_stats = GC.latest_compact_info
+ refute_predicate compact_stats[:considered], :empty?
+ refute_predicate compact_stats[:moved], :empty?
+ ensure
+ GC.auto_compact = before
+ end
+
+ private
+
+ def supports_auto_compact?
+ return true unless defined?(Etc::SC_PAGE_SIZE)
+
+ begin
+ return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0
+ rescue NotImplementedError
+ rescue ArgumentError
+ end
+
+ true
+ end
+ end
+
+ def os_page_size
+ return true unless defined?(Etc::SC_PAGE_SIZE)
+ end
+
+ def test_gc_compact_stats
+ list = []
+
+ # Try to make some fragmentation
+ 500.times {
+ list << Object.new
+ Object.new
+ Object.new
+ }
+ compact_stats = GC.compact
+ refute_predicate compact_stats[:considered], :empty?
+ refute_predicate compact_stats[:moved], :empty?
+ end
+
def memory_location(obj)
(Fiddle.dlwrap(obj) >> 1)
end
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index d4af130a07..d217776a2c 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -86,7 +86,6 @@ class TestHash < Test::Unit::TestCase
'nil' => nil
]
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -266,10 +265,13 @@ class TestHash < Test::Unit::TestCase
end
def test_AREF_fstring_key
+ # warmup ObjectSpace.count_objects
+ ObjectSpace.count_objects
+
h = {"abc" => 1}
- before = GC.stat(:total_allocated_objects)
+ before = ObjectSpace.count_objects[:T_STRING]
5.times{ h["abc"] }
- assert_equal before, GC.stat(:total_allocated_objects)
+ assert_equal before, ObjectSpace.count_objects[:T_STRING]
end
def test_ASET_fstring_key
@@ -417,6 +419,15 @@ class TestHash < Test::Unit::TestCase
true
}
assert_equal(base.size, n)
+
+ h = base.dup
+ assert_raise(FrozenError) do
+ h.delete_if do
+ h.freeze
+ true
+ end
+ end
+ assert_equal(base.dup, h)
end
def test_keep_if
@@ -424,6 +435,14 @@ class TestHash < Test::Unit::TestCase
assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 })
h = @cls[1=>2,3=>4,5=>6]
assert_equal({1=>2,3=>4,5=>6}, h.keep_if{true})
+ h = @cls[1=>2,3=>4,5=>6]
+ assert_raise(FrozenError) do
+ h.keep_if do
+ h.freeze
+ false
+ end
+ end
+ assert_equal(@cls[1=>2,3=>4,5=>6], h)
end
def test_compact
@@ -720,6 +739,15 @@ class TestHash < Test::Unit::TestCase
h = base.dup
assert_equal(h3, h.reject! {|k,v| v })
assert_equal(h3, h)
+
+ h = base.dup
+ assert_raise(FrozenError) do
+ h.reject! do
+ h.freeze
+ true
+ end
+ end
+ assert_equal(base.dup, h)
end
def test_replace
@@ -875,7 +903,7 @@ class TestHash < Test::Unit::TestCase
def test_to_s
h = @cls[ 1 => 2, "cat" => "dog", 1.5 => :fred ]
assert_equal(h.inspect, h.to_s)
- $, = ":"
+ assert_deprecated_warning { $, = ":" }
assert_equal(h.inspect, h.to_s)
h = @cls[]
assert_equal(h.inspect, h.to_s)
@@ -944,7 +972,7 @@ class TestHash < Test::Unit::TestCase
end
def test_fetch2
- assert_equal(:bar, @h.fetch(0, :foo) { :bar })
+ assert_equal(:bar, assert_warning(/block supersedes default value argument/) {@h.fetch(0, :foo) { :bar }})
end
def test_default_proc
@@ -1036,6 +1064,14 @@ class TestHash < Test::Unit::TestCase
assert_equal({3=>4,5=>6}, h)
h = @cls[1=>2,3=>4,5=>6]
assert_equal(nil, h.select!{true})
+ h = @cls[1=>2,3=>4,5=>6]
+ assert_raise(FrozenError) do
+ h.select! do
+ h.freeze
+ false
+ end
+ end
+ assert_equal(@cls[1=>2,3=>4,5=>6], h)
end
def test_slice
@@ -1046,6 +1082,14 @@ class TestHash < Test::Unit::TestCase
assert_equal({}, {}.slice)
end
+ def test_except
+ h = @cls[1=>2,3=>4,5=>6]
+ assert_equal({5=>6}, h.except(1, 3))
+ assert_equal({1=>2,3=>4,5=>6}, h.except(7))
+ assert_equal({1=>2,3=>4,5=>6}, h.except)
+ assert_equal({}, {}.except)
+ end
+
def test_filter
assert_equal({3=>4,5=>6}, @cls[1=>2,3=>4,5=>6].filter {|k, v| k + v >= 7 })
@@ -1080,6 +1124,14 @@ class TestHash < Test::Unit::TestCase
assert_equal({3=>4,5=>6}, h)
h = @cls[1=>2,3=>4,5=>6]
assert_equal(nil, h.filter!{true})
+ h = @cls[1=>2,3=>4,5=>6]
+ assert_raise(FrozenError) do
+ h.filter! do
+ h.freeze
+ false
+ end
+ end
+ assert_equal(@cls[1=>2,3=>4,5=>6], h)
end
def test_clear2
@@ -1114,6 +1166,7 @@ class TestHash < Test::Unit::TestCase
def o.to_hash; @cls[]; end
def o.==(x); true; end
assert_equal({}, o)
+ o.singleton_class.remove_method(:==)
def o.==(x); false; end
assert_not_equal({}, o)
@@ -1130,6 +1183,7 @@ class TestHash < Test::Unit::TestCase
def o.to_hash; @cls[]; end
def o.eql?(x); true; end
assert_send([@cls[], :eql?, o])
+ o.singleton_class.remove_method(:eql?)
def o.eql?(x); false; end
assert_not_send([@cls[], :eql?, o])
end
@@ -1637,6 +1691,8 @@ class TestHash < Test::Unit::TestCase
}
assert_equal([10, 20, 30], [1, 2, 3].map(&h))
+
+ assert_equal(true, h.to_proc.lambda?)
end
def test_transform_keys
@@ -1651,6 +1707,9 @@ class TestHash < Test::Unit::TestCase
y = x.transform_keys.with_index {|k, i| "#{k}.#{i}" }
assert_equal(%w(a.0 b.1 c.2), y.keys)
+
+ assert_equal({A: 1, B: 2, c: 3}, x.transform_keys({a: :A, b: :B, d: :D}))
+ assert_equal({A: 1, B: 2, "c" => 3}, x.transform_keys({a: :A, b: :B, d: :D}, &:to_s))
end
def test_transform_keys_bang
@@ -1670,9 +1729,20 @@ class TestHash < Test::Unit::TestCase
x.transform_keys! {|k| -k }
assert_equal([-1, :a, 1, :b], x.flatten)
+ x = @cls[a: 1, b: 2, c: 3]
+ x.transform_keys! { |k| k == :b && break }
+ assert_equal({false => 1, b: 2, c: 3}, x)
+
x = @cls[true => :a, false => :b]
x.transform_keys! {|k| !k }
assert_equal([false, :a, true, :b], x.flatten)
+
+ x = @cls[a: 1, b: 2, c: 3]
+ x.transform_keys!({a: :A, b: :B, d: :D})
+ assert_equal({A: 1, B: 2, c: 3}, x)
+ x = @cls[a: 1, b: 2, c: 3]
+ x.transform_keys!({a: :A, b: :B, d: :D}, &:to_s)
+ assert_equal({A: 1, B: 2, "c" => 3}, x)
end
def test_transform_values
@@ -1699,8 +1769,21 @@ class TestHash < Test::Unit::TestCase
assert_same(x, y)
x = @cls[a: 1, b: 2, c: 3]
+ x.transform_values! { |v| v == 2 && break }
+ assert_equal({a: false, b: 2, c: 3}, x)
+
+ x = @cls[a: 1, b: 2, c: 3]
y = x.transform_values!.with_index {|v, i| "#{v}.#{i}" }
assert_equal(%w(1.0 2.1 3.2), y.values_at(:a, :b, :c))
+
+ x = @cls[a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10]
+ assert_raise(FrozenError) do
+ x.transform_values!() do |v|
+ x.freeze if v == 2
+ v.succ
+ end
+ end
+ assert_equal(@cls[a: 2, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], x)
end
def test_broken_hash_value
@@ -1759,6 +1842,12 @@ class TestHash < Test::Unit::TestCase
@cls = SubHash
super
end
+
+ def test_reject
+ assert_warning(/extra states are no longer copied/) do
+ super
+ end
+ end
end
ruby2_keywords def get_flagged_hash(*args)
@@ -1842,4 +1931,36 @@ class TestHash < Test::Unit::TestCase
h[obj2] = true
assert_equal true, h[obj]
end
+
+ def test_bug_12706
+ assert_raise(ArgumentError) do
+ {a: 1}.each(&->(k, v) {})
+ end
+ end
+
+ def test_any_hash_fixable
+ 20.times do
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ require "delegate"
+ typename = DelegateClass(String)
+
+ hash = {
+ "Int" => true,
+ "Float" => true,
+ "String" => true,
+ "Boolean" => true,
+ "WidgetFilter" => true,
+ "WidgetAggregation" => true,
+ "WidgetEdge" => true,
+ "WidgetSortOrder" => true,
+ "WidgetGrouping" => true,
+ }
+
+ hash.each_key do |key|
+ assert_send([hash, :key?, typename.new(key)])
+ end
+ end;
+ end
+ end
end
diff --git a/test/ruby/test_inlinecache.rb b/test/ruby/test_inlinecache.rb
new file mode 100644
index 0000000000..6c2d86aefd
--- /dev/null
+++ b/test/ruby/test_inlinecache.rb
@@ -0,0 +1,110 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: true
+
+require 'test/unit'
+
+class TestMethod < Test::Unit::TestCase
+ def test_alias
+ m0 = Module.new do
+ def foo; :M0 end
+ end
+ m1 = Module.new do
+ include m0
+ end
+ c = Class.new do
+ include m1
+ alias bar foo
+ end
+ d = Class.new(c) do
+ end
+
+ test = -> do
+ d.new.bar
+ end
+
+ assert_equal :M0, test[]
+
+ c.class_eval do
+ def bar
+ :C
+ end
+ end
+
+ assert_equal :C, test[]
+ end
+
+ def test_zsuper
+ assert_separately [], <<-EOS
+ class C
+ private def foo
+ :C
+ end
+ end
+
+ class D < C
+ public :foo
+ end
+
+ class E < D; end
+ class F < E; end
+
+ test = -> do
+ F.new().foo
+ end
+
+ assert_equal :C, test[]
+
+ class E
+ def foo; :E; end
+ end
+
+ assert_equal :E, test[]
+ EOS
+ end
+
+ def test_module_methods_redefiniton
+ m0 = Module.new do
+ def foo
+ super
+ end
+ end
+
+ c1 = Class.new do
+ def foo
+ :C1
+ end
+ end
+
+ c2 = Class.new do
+ def foo
+ :C2
+ end
+ end
+
+ d1 = Class.new(c1) do
+ include m0
+ end
+
+ d2 = Class.new(c2) do
+ include m0
+ end
+
+ assert_equal :C1, d1.new.foo
+
+ m = Module.new do
+ def foo
+ super
+ end
+ end
+
+ d1.class_eval do
+ include m
+ end
+
+ d2.class_eval do
+ include m
+ end
+
+ assert_equal :C2, d2.new.foo
+ end
+end
diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb
index a111698771..2755987276 100644
--- a/test/ruby/test_integer.rb
+++ b/test/ruby/test_integer.rb
@@ -260,6 +260,7 @@ class TestInteger < Test::Unit::TestCase
assert_equal("a", "a".ord.chr)
assert_raise(RangeError) { (-1).chr }
assert_raise(RangeError) { 0x100.chr }
+ assert_raise_with_message(RangeError, "3000000000 out of char range") { 3_000_000_000.chr }
end
def test_upto
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index 37f1477483..e178e7579b 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -394,6 +394,24 @@ class TestIO < Test::Unit::TestCase
}
end
+ def test_each_byte_closed
+ pipe(proc do |w|
+ w << "abc def"
+ w.close
+ end, proc do |r|
+ assert_raise(IOError) do
+ r.each_byte {|byte| r.close if byte == 32 }
+ end
+ end)
+ make_tempfile {|t|
+ File.open(t, 'rt') {|f|
+ assert_raise(IOError) do
+ f.each_byte {|c| f.close if c == 10}
+ end
+ }
+ }
+ end
+
def test_each_codepoint
make_tempfile {|t|
bug2959 = '[ruby-core:28650]'
@@ -405,6 +423,24 @@ class TestIO < Test::Unit::TestCase
}
end
+ def test_each_codepoint_closed
+ pipe(proc do |w|
+ w.print("abc def")
+ w.close
+ end, proc do |r|
+ assert_raise(IOError) do
+ r.each_codepoint {|c| r.close if c == 32}
+ end
+ end)
+ make_tempfile {|t|
+ File.open(t, 'rt') {|f|
+ assert_raise(IOError) do
+ f.each_codepoint {|c| f.close if c == 10}
+ end
+ }
+ }
+ end
+
def test_rubydev33072
t = make_tempfile
path = t.path
@@ -619,7 +655,7 @@ class TestIO < Test::Unit::TestCase
if have_nonblock?
def test_copy_stream_no_busy_wait
- skip "MJIT has busy wait on GC. This sometimes fails with --jit." if RubyVM::MJIT.enabled?
+ skip "MJIT has busy wait on GC. This sometimes fails with --jit." if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
skip "multiple threads already active" if Thread.list.size > 1
msg = 'r58534 [ruby-core:80969] [Backport #13533]'
@@ -1595,7 +1631,7 @@ class TestIO < Test::Unit::TestCase
end if have_nonblock?
def test_read_nonblock_no_exceptions
- skip '[ruby-core:90895] MJIT worker may leave fd open in a forked child' if RubyVM::MJIT.enabled? # TODO: consider acquiring GVL from MJIT worker.
+ skip '[ruby-core:90895] MJIT worker may leave fd open in a forked child' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # TODO: consider acquiring GVL from MJIT worker.
with_pipe {|r, w|
assert_equal :wait_readable, r.read_nonblock(4096, exception: false)
w.puts "HI!"
@@ -1842,6 +1878,61 @@ class TestIO < Test::Unit::TestCase
end)
end
+ def test_each_line
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ e = nil
+ assert_warn('') {
+ e = r.each_line
+ }
+ assert_equal("foo\n", e.next)
+ assert_equal("bar\n", e.next)
+ assert_equal("baz\n", e.next)
+ assert_raise(StopIteration) { e.next }
+ end)
+ end
+
+ def test_each_byte2
+ pipe(proc do |w|
+ w.binmode
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ e = nil
+ assert_warn('') {
+ e = r.each_byte
+ }
+ (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+ assert_equal(c.ord, e.next)
+ end
+ assert_raise(StopIteration) { e.next }
+ end)
+ end
+
+ def test_each_char2
+ pipe(proc do |w|
+ w.puts "foo"
+ w.puts "bar"
+ w.puts "baz"
+ w.close
+ end, proc do |r|
+ e = nil
+ assert_warn('') {
+ e = r.each_char
+ }
+ (%w(f o o) + ["\n"] + %w(b a r) + ["\n"] + %w(b a z) + ["\n"]).each do |c|
+ assert_equal(c, e.next)
+ end
+ assert_raise(StopIteration) { e.next }
+ end)
+ end
+
def test_readbyte
pipe(proc do |w|
w.binmode
@@ -2188,7 +2279,7 @@ class TestIO < Test::Unit::TestCase
def test_autoclose_true_closed_by_finalizer
# http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1465760
# http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1469765
- skip 'this randomly fails with MJIT' if RubyVM::MJIT.enabled?
+ skip 'this randomly fails with MJIT' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
feature2250 = '[ruby-core:26222]'
pre = 'ft2250'
@@ -2240,26 +2331,14 @@ class TestIO < Test::Unit::TestCase
def o.to_open(**kw); kw; end
assert_equal({:a=>1}, open(o, a: 1))
- w = /Using the last argument as keyword parameters is deprecated.*The called method `(to_)?open'/m
- redefined = nil
- w.singleton_class.define_method(:===) do |s|
- match = super(s)
- redefined = !$1
- match
- end
-
- assert_warn(w) do
- assert_equal({:a=>1}, open(o, {a: 1}))
- end
+ assert_raise(ArgumentError) { open(o, {a: 1}) }
class << o
remove_method(:to_open)
end
def o.to_open(kw); kw; end
assert_equal({:a=>1}, open(o, a: 1))
- unless redefined
- assert_equal({:a=>1}, open(o, {a: 1}))
- end
+ assert_equal({:a=>1}, open(o, {a: 1}))
end
def test_open_pipe
@@ -2457,6 +2536,17 @@ class TestIO < Test::Unit::TestCase
end
end
+ def test_reopen_ivar
+ assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ f = File.open(IO::NULL)
+ f.instance_variable_set(:@foo, 42)
+ f.reopen(STDIN)
+ f.instance_variable_defined?(:@foo)
+ f.instance_variable_get(:@foo)
+ end;
+ end
+
def test_foreach
a = []
IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x }
@@ -2536,11 +2626,13 @@ class TestIO < Test::Unit::TestCase
end
def test_print_separators
- EnvUtil.suppress_warning {$, = ':'}
- $\ = "\n"
+ EnvUtil.suppress_warning {
+ $, = ':'
+ $\ = "\n"
+ }
pipe(proc do |w|
w.print('a')
- w.print('a','b','c')
+ EnvUtil.suppress_warning {w.print('a','b','c')}
w.close
end, proc do |r|
assert_equal("a\n", r.gets)
@@ -2598,7 +2690,7 @@ class TestIO < Test::Unit::TestCase
end
capture.clear
- assert_warning(/[.#]write is outdated/) do
+ assert_deprecated_warning(/[.#]write is outdated/) do
stdout, $stdout = $stdout, capture
puts "hey"
ensure
@@ -2781,7 +2873,7 @@ __END__
def test_flush_in_finalizer2
bug3910 = '[ruby-dev:42341]'
- Tempfile.open("bug3910") {|t|
+ Tempfile.create("bug3910") {|t|
path = t.path
t.close
begin
@@ -2800,7 +2892,6 @@ __END__
end
}
end
- t.close!
}
end
@@ -3094,11 +3185,8 @@ __END__
assert_equal("\00f", File.read(path))
assert_equal(1, File.write(path, "f", 0, encoding: "UTF-8"))
assert_equal("ff", File.read(path))
- assert_raise(TypeError) {
- assert_warn(/The last argument is split into positional and keyword parameters/) do
- File.write(path, "foo", Object.new => Object.new)
- end
- }
+ File.write(path, "foo", Object.new => Object.new)
+ assert_equal("foo", File.read(path))
end
end
@@ -3422,10 +3510,17 @@ __END__
tempfiles = []
(0..fd_setsize+1).map {|i|
- tempfiles << Tempfile.open("test_io_select_with_many_files")
+ tempfiles << Tempfile.create("test_io_select_with_many_files")
}
- IO.select(tempfiles)
+ begin
+ IO.select(tempfiles)
+ ensure
+ tempfiles.each { |t|
+ t.close
+ File.unlink(t.path)
+ }
+ end
}, bug8080, timeout: 100
end if defined?(Process::RLIMIT_NOFILE)
@@ -3599,15 +3694,27 @@ __END__
end
def test_open_flag_binary
+ binary_enc = Encoding.find("BINARY")
make_tempfile do |t|
open(t.path, File::RDONLY, flags: File::BINARY) do |f|
assert_equal true, f.binmode?
+ assert_equal binary_enc, f.external_encoding
end
open(t.path, 'r', flags: File::BINARY) do |f|
assert_equal true, f.binmode?
+ assert_equal binary_enc, f.external_encoding
end
open(t.path, mode: 'r', flags: File::BINARY) do |f|
assert_equal true, f.binmode?
+ assert_equal binary_enc, f.external_encoding
+ end
+ open(t.path, File::RDONLY|File::BINARY) do |f|
+ assert_equal true, f.binmode?
+ assert_equal binary_enc, f.external_encoding
+ end
+ open(t.path, File::RDONLY|File::BINARY, autoclose: true) do |f|
+ assert_equal true, f.binmode?
+ assert_equal binary_enc, f.external_encoding
end
end
end if File::BINARY != 0
@@ -3870,21 +3977,22 @@ __END__
end
end
- def test_select_leak
+ def test_select_memory_leak
# avoid malloc arena explosion from glibc and jemalloc:
env = {
'MALLOC_ARENA_MAX' => '1',
'MALLOC_ARENA_TEST' => '1',
'MALLOC_CONF' => 'narenas:1',
}
- assert_no_memory_leak([env], <<-"end;", <<-"end;", rss: true, timeout: 60)
+ assert_no_memory_leak([env], "#{<<~"begin;"}\n#{<<~'else;'}", "#{<<~'end;'}", rss: true, timeout: 60)
+ begin;
r, w = IO.pipe
rset = [r]
wset = [w]
exc = StandardError.new(-"select used to leak on exception")
exc.set_backtrace([])
Thread.new { IO.select(rset, wset, nil, 0) }.join
- end;
+ else;
th = Thread.new do
Thread.handle_interrupt(StandardError => :on_blocking) do
begin
@@ -3909,4 +4017,22 @@ __END__
assert_raise(TypeError) {Marshal.dump(w)}
}
end
+
+ def test_stdout_to_closed_pipe
+ EnvUtil.invoke_ruby(["-e", "loop {puts :ok}"], "", true, true) do
+ |in_p, out_p, err_p, pid|
+ out = out_p.gets
+ out_p.close
+ err = err_p.read
+ ensure
+ status = Process.wait2(pid)[1]
+ assert_equal("ok\n", out)
+ assert_empty(err)
+ assert_not_predicate(status, :success?)
+ if Signal.list["PIPE"]
+ assert_predicate(status, :signaled?)
+ assert_equal("PIPE", Signal.signame(status.termsig) || status.termsig)
+ end
+ end
+ end
end
diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb
index e5b0ef0585..27b16a2a36 100644
--- a/test/ruby/test_io_m17n.rb
+++ b/test/ruby/test_io_m17n.rb
@@ -776,10 +776,10 @@ EOT
assert_equal(eucjp, r.read)
end)
- assert_raise_with_message(ArgumentError, /invalid name encoding/) do
+ assert_raise_with_message(ArgumentError, /invalid encoding name/) do
with_pipe("UTF-8", "UTF-8".encode("UTF-32BE")) {}
end
- assert_raise_with_message(ArgumentError, /invalid name encoding/) do
+ assert_raise_with_message(ArgumentError, /invalid encoding name/) do
with_pipe("UTF-8".encode("UTF-32BE")) {}
end
@@ -2047,19 +2047,19 @@ EOT
with_tmpdir {
open("raw.txt", "wb", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" }
content = File.read("raw.txt", :mode=>"rb:ascii-8bit")
- assert_equal("\"&amp;&lt;&gt;&quot;'\u4E02\u3042\n\"".force_encoding("ascii-8bit"), content)
+ assert_equal("\"&amp;&lt;&gt;&quot;&apos;\u4E02\u3042\n\"".force_encoding("ascii-8bit"), content)
open("ascii.txt", "wb:us-ascii", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" }
content = File.read("ascii.txt", :mode=>"rb:ascii-8bit")
- assert_equal("\"&amp;&lt;&gt;&quot;'&#x4E02;&#x3042;\n\"".force_encoding("ascii-8bit"), content)
+ assert_equal("\"&amp;&lt;&gt;&quot;&apos;&#x4E02;&#x3042;\n\"".force_encoding("ascii-8bit"), content)
open("iso-2022-jp.txt", "wb:iso-2022-jp", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" }
content = File.read("iso-2022-jp.txt", :mode=>"rb:ascii-8bit")
- assert_equal("\"&amp;&lt;&gt;&quot;'&#x4E02;\e$B$\"\e(B\n\"".force_encoding("ascii-8bit"), content)
+ assert_equal("\"&amp;&lt;&gt;&quot;&apos;&#x4E02;\e$B$\"\e(B\n\"".force_encoding("ascii-8bit"), content)
open("utf-16be.txt", "wb:utf-16be", xml: :attr) {|f| f.print '&<>"\''; f.puts "\u4E02\u3042" }
content = File.read("utf-16be.txt", :mode=>"rb:ascii-8bit")
- assert_equal("\0\"\0&\0a\0m\0p\0;\0&\0l\0t\0;\0&\0g\0t\0;\0&\0q\0u\0o\0t\0;\0'\x4E\x02\x30\x42\0\n\0\"".force_encoding("ascii-8bit"), content)
+ assert_equal("\0\"\0&\0a\0m\0p\0;\0&\0l\0t\0;\0&\0g\0t\0;\0&\0q\0u\0o\0t\0;\0&\0a\0p\0o\0s\0;\x4E\x02\x30\x42\0\n\0\"".force_encoding("ascii-8bit"), content)
open("eucjp.txt", "w:euc-jp:utf-8", xml: :attr) {|f|
f.print "\u4E02" # U+4E02 is 0x3021 in JIS X 0212
diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index 709061d54a..08340c662c 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -82,6 +82,16 @@ class TestISeq < Test::Unit::TestCase
end;
end if defined?(RubyVM::InstructionSequence.load)
+ def test_lambda_with_ractor_roundtrip
+ iseq = compile(<<~EOF)
+ x = 42
+ y = lambda { x }
+ Ractor.make_shareable(y)
+ y.call
+ EOF
+ assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
+ end
+
def test_disasm_encoding
src = "\u{3042} = 1; \u{3042}; \u{3043}"
asm = compile(src).disasm
@@ -98,6 +108,22 @@ class TestISeq < Test::Unit::TestCase
assert_include(RubyVM::InstructionSequence.of(obj.method(name)).disasm, name)
end
+ def test_compile_file_encoding
+ Tempfile.create(%w"test_iseq .rb") do |f|
+ f.puts "{ '\u00de' => 'Th', '\u00df' => 'ss', '\u00e0' => 'a' }"
+ f.close
+
+ EnvUtil.with_default_external(Encoding::US_ASCII) do
+ assert_warn('') {
+ load f.path
+ }
+ assert_nothing_raised(SyntaxError) {
+ RubyVM::InstructionSequence.compile_file(f.path)
+ }
+ end
+ end
+ end
+
LINE_BEFORE_METHOD = __LINE__
def method_test_line_trace
@@ -187,8 +213,8 @@ class TestISeq < Test::Unit::TestCase
s1, s2, s3, s4 = compile(code, line, {frozen_string_literal: true}).eval
assert_predicate(s1, :frozen?)
assert_predicate(s2, :frozen?)
- assert_predicate(s3, :frozen?)
- assert_predicate(s4, :frozen?)
+ assert_not_predicate(s3, :frozen?)
+ assert_not_predicate(s4, :frozen?)
end
# Safe call chain is not optimized when Coverage is running.
@@ -465,6 +491,11 @@ class TestISeq < Test::Unit::TestCase
attr_reader :i
end
end;
+
+ # cleanup
+ ::Object.class_eval do
+ remove_const :P
+ end
end
def collect_from_binary_tracepoint_lines(tracepoint_type, filename)
@@ -568,4 +599,27 @@ class TestISeq < Test::Unit::TestCase
assert_not_nil(invokebuiltin)
assert_equal([:func_ptr, :argc, :index, :name], invokebuiltin[1].keys)
end
+
+ def test_iseq_builtin_load
+ Tempfile.create(["builtin", ".iseq"]) do |f|
+ f.binmode
+ f.write(RubyVM::InstructionSequence.of(1.method(:abs)).to_binary)
+ f.close
+ assert_separately(["-", f.path], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ bin = File.binread(ARGV[0])
+ assert_raise(ArgumentError) do
+ RubyVM::InstructionSequence.load_from_binary(bin)
+ end
+ end;
+ end
+ end
+
+ def test_iseq_option_debug_level
+ assert_raise(TypeError) {ISeq.compile("", debug_level: "")}
+ assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ RubyVM::InstructionSequence.compile("", debug_level: 5)
+ end;
+ end
end
diff --git a/test/ruby/test_iterator.rb b/test/ruby/test_iterator.rb
index 54c095338f..820d5591c1 100644
--- a/test/ruby/test_iterator.rb
+++ b/test/ruby/test_iterator.rb
@@ -339,8 +339,7 @@ class TestIterator < Test::Unit::TestCase
marity_test(:marity_test)
marity_test(:p)
- lambda(&method(:assert)).call(true)
- lambda(&get_block{|a,n| assert(a,n)}).call(true, "marity")
+ get_block{|a,n| assert(a,n)}.call(true, "marity")
end
def foo
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
index e3d8f9cee2..be3550033d 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -14,6 +14,7 @@ class TestJIT < Test::Unit::TestCase
]
MAX_CACHE_PATTERNS = [
/\AJIT compaction \([^)]+\): .+\n\z/,
+ /\AToo many JIT code, but skipped unloading units for JIT compaction\n\z/,
/\ANo units can be unloaded -- .+\n\z/,
]
@@ -21,7 +22,6 @@ class TestJIT < Test::Unit::TestCase
TEST_PENDING_INSNS = RubyVM::INSTRUCTION_NAMES.select { |n| n.start_with?('trace_') }.map(&:to_sym) + [
# not supported yet
:defineclass,
- :opt_call_c_function,
# to be tested
:invokebuiltin,
@@ -38,22 +38,35 @@ class TestJIT < Test::Unit::TestCase
@untested_insns ||= (RubyVM::INSTRUCTION_NAMES.map(&:to_sym) - TEST_PENDING_INSNS)
end
- def setup
- unless JITSupport.supported?
- skip 'JIT seems not supported on this platform'
+ def self.setup
+ return if defined?(@setup_hooked)
+ @setup_hooked = true
+
+ # ci.rvm.jp caches its build environment. Clean up temporary files left by SEGV.
+ if ENV['RUBY_DEBUG']&.include?('ci')
+ Dir.glob("#{ENV.fetch('TMPDIR', '/tmp')}/_ruby_mjit_p*u*.*").each do |file|
+ puts "test/ruby/test_jit.rb: removing #{file}"
+ File.unlink(file)
+ end
end
# ruby -w -Itest/lib test/ruby/test_jit.rb
- if $VERBOSE && !defined?(@@at_exit_hooked)
+ if $VERBOSE
at_exit do
unless TestJIT.untested_insns.empty?
warn "you may want to add tests for following insns, when you have a chance: #{TestJIT.untested_insns.join(' ')}"
end
end
- @@at_exit_hooked = true
end
end
+ def setup
+ unless JITSupport.supported?
+ skip 'JIT seems not supported on this platform'
+ end
+ self.class.setup
+ end
+
def test_compile_insn_nop
assert_compile_once('nil rescue true', result_inspect: 'nil', insns: %i[nop])
end
@@ -232,14 +245,6 @@ class TestJIT < Test::Unit::TestCase
assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings tostring])
end
- def test_compile_insn_freezestring
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~'end;'}", stdout: 'true', success_count: 1, insns: %i[freezestring])
- begin;
- # frozen_string_literal: true
- print proc { "#{true}".frozen? }.call
- end;
- end
-
def test_compile_insn_toregexp
assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0', insns: %i[toregexp])
end
@@ -357,7 +362,7 @@ class TestJIT < Test::Unit::TestCase
end
def test_compile_insn_send
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2, insns: %i[send])
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 3, insns: %i[send])
begin;
print proc { yield_self { 1 } }.call
end;
@@ -597,12 +602,11 @@ class TestJIT < Test::Unit::TestCase
assert_compile_once("'true' =~ /true/", result_inspect: '0', insns: %i[opt_regexpmatch2])
end
- def test_compile_insn_opt_call_c_function
- skip "support this in opt_call_c_function (low priority)"
- end
-
def test_compile_insn_opt_invokebuiltin_delegate_leave
- insns = collect_insns(RubyVM::InstructionSequence.of("\x00".method(:unpack)).to_a)
+ iseq = eval(EnvUtil.invoke_ruby(['-e', <<~'EOS'], '', true).first)
+ p RubyVM::InstructionSequence.of("\x00".method(:unpack)).to_a
+ EOS
+ insns = collect_insns(iseq)
mark_tested_insn(:opt_invokebuiltin_delegate_leave, used_insns: insns)
assert_eval_with_jit('print "\x00".unpack("c")', stdout: '[0]', success_count: 1)
end
@@ -680,30 +684,40 @@ class TestJIT < Test::Unit::TestCase
debug_info = %Q[stdout:\n"""\n#{out}\n"""\n\nstderr:\n"""\n#{err}"""\n]
assert_equal('012345678910', out, debug_info)
compactions, errs = err.lines.partition do |l|
- l.match?(/\AJIT compaction \(\d+\.\dms\): Compacted \d+ methods ->/)
+ l.match?(/\AJIT compaction \(\d+\.\dms\): Compacted \d+ methods /)
end
10.times do |i|
assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit#{i}@\(eval\):/, errs[i], debug_info)
end
- assert_equal("Too many JIT code -- 1 units unloaded\n", errs[10], debug_info)
- assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit10@\(eval\):/, errs[11], debug_info)
+ assert_equal("No units can be unloaded -- incremented max-cache-size to 11 for --jit-wait\n", errs[10], debug_info)
+ assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit10@\(eval\):/, errs[11], debug_info)
# On --jit-wait, when the number of JIT-ed code reaches --jit-max-cache,
# it should trigger compaction.
unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet
- assert_equal(3, compactions.size, debug_info)
+ assert_equal(1, compactions.size, debug_info)
end
if RUBY_PLATFORM.match?(/mswin/)
# "Permission Denied" error is preventing to remove so file on AppVeyor/RubyCI.
skip 'Removing so file is randomly failing on AppVeyor/RubyCI mswin due to Permission Denied.'
else
- # verify .o files are deleted on unload_units
+ # verify .c files are deleted on unload_units
assert_send([Dir, :empty?, dir], debug_info)
end
end
end
+ def test_newarraykwsplat_on_stack
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "[nil, [{:type=>:development}]]\n", success_count: 1, insns: %i[newarraykwsplat])
+ begin;
+ def arr
+ [nil, [:type => :development]]
+ end
+ p arr
+ end;
+ end
+
def test_local_stack_on_exception
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2)
begin;
@@ -763,6 +777,43 @@ class TestJIT < Test::Unit::TestCase
end;
end
+ def test_inlined_c_method
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 2, recompile_count: 1, min_calls: 2)
+ begin;
+ def test(obj, recursive: nil)
+ if recursive
+ test(recursive)
+ end
+ obj.to_s
+ end
+
+ print(test('a')) # set #to_s cc to String#to_s (expecting C method)
+ print(test('a')) # JIT with #to_s cc: String#to_s
+ # update #to_s cd->cc to Symbol#to_s, then go through the Symbol#to_s cd->cc
+ # after checking receiver class using inlined #to_s cc with String#to_s.
+ print(test('a', recursive: :foo))
+ end;
+ end
+
+ def test_inlined_exivar
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 3, recompile_count: 1, min_calls: 2)
+ begin;
+ class Foo < Hash
+ def initialize
+ @a = :a
+ end
+
+ def bar
+ @a
+ end
+ end
+
+ print(Foo.new.bar)
+ print(Foo.new.bar) # compile #initialize, #bar -> recompile #bar
+ print(Foo.new.bar) # compile #bar with exivar
+ end;
+ end
+
def test_inlined_undefined_ivar
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 3, min_calls: 3)
begin;
@@ -778,11 +829,9 @@ class TestJIT < Test::Unit::TestCase
end
end
- verbose, $VERBOSE = $VERBOSE, false # suppress "instance variable @b not initialized"
print(Foo.new.bar)
print(Foo.new.bar)
print(Foo.new.bar)
- $VERBOSE = verbose
end;
end
@@ -808,6 +857,18 @@ class TestJIT < Test::Unit::TestCase
end;
end
+ def test_inlined_getconstant
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 1, min_calls: 2)
+ begin;
+ FOO = 1
+ def const
+ FOO
+ end
+ print const
+ print const
+ end;
+ end
+
def test_attr_reader
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2)
begin;
@@ -872,6 +933,34 @@ class TestJIT < Test::Unit::TestCase
end;
end
+ def test_heap_promotion_of_ivar_in_the_middle_of_jit
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\n", success_count: 2, min_calls: 2)
+ begin;
+ class A
+ def initialize
+ @iv0 = nil
+ @iv1 = []
+ @iv2 = nil
+ end
+
+ def test(add)
+ @iv0.nil?
+ @iv2.nil?
+ add_ivar if add
+ @iv1.empty?
+ end
+
+ def add_ivar
+ @iv3 = nil
+ end
+ end
+
+ a = A.new
+ p a.test(false)
+ p a.test(true)
+ end;
+ end
+
def test_jump_to_precompiled_branch
assert_eval_with_jit("#{<<~'begin;'}\n#{<<~'end;'}", stdout: ".0", success_count: 1, min_calls: 1)
begin;
@@ -935,7 +1024,7 @@ class TestJIT < Test::Unit::TestCase
def test_frame_omitted_inlining
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2)
begin;
- class Numeric
+ class Integer
remove_method :zero?
def zero?
self == 0
@@ -961,6 +1050,10 @@ class TestJIT < Test::Unit::TestCase
end;
end
+ def test_builtin_frame_omitted_inlining
+ assert_eval_with_jit('0.zero?; 0.zero?; 3.times { p 0.zero? }', stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2)
+ end
+
def test_program_counter_with_regexpmatch
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aa", success_count: 1)
begin;
@@ -1050,12 +1143,13 @@ class TestJIT < Test::Unit::TestCase
end
# Shorthand for normal test cases
- def assert_eval_with_jit(script, stdout: nil, success_count:, min_calls: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: [])
+ def assert_eval_with_jit(script, stdout: nil, success_count:, recompile_count: nil, min_calls: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: [])
out, err = eval_with_jit(script, verbose: 1, min_calls: min_calls, max_cache: max_cache)
- actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
+ success_actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
+ recompile_actual = err.scan(/^#{JIT_RECOMPILE_PREFIX}:/).size
# Add --jit-verbose=2 logs for cl.exe because compiler's error message is suppressed
# for cl.exe with --jit-verbose=1. See `start_process` in mjit_worker.c.
- if RUBY_PLATFORM.match?(/mswin/) && success_count != actual
+ if RUBY_PLATFORM.match?(/mswin/) && success_count != success_actual
out2, err2 = eval_with_jit(script, verbose: 2, min_calls: min_calls, max_cache: max_cache)
end
@@ -1065,13 +1159,19 @@ class TestJIT < Test::Unit::TestCase
mark_tested_insn(insn, used_insns: used_insns, uplevel: uplevel + 3)
end
+ suffix = "script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}#{(
+ "\nstdout(verbose=2 retry):\n#{code_block(out2)}\nstderr(verbose=2 retry):\n#{code_block(err2)}" if out2 || err2
+ )}"
assert_equal(
- success_count, actual,
- "Expected #{success_count} times of JIT success, but succeeded #{actual} times.\n\n"\
- "script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}#{(
- "\nstdout(verbose=2 retry):\n#{code_block(out2)}\nstderr(verbose=2 retry):\n#{code_block(err2)}" if out2 || err2
- )}",
+ success_count, success_actual,
+ "Expected #{success_count} times of JIT success, but succeeded #{success_actual} times.\n\n#{suffix}",
)
+ if recompile_count
+ assert_equal(
+ recompile_count, recompile_actual,
+ "Expected #{success_count} times of JIT recompile, but recompiled #{success_actual} times.\n\n#{suffix}",
+ )
+ end
if stdout
assert_equal(stdout, out, "Expected stdout #{out.inspect} to match #{stdout.inspect} with script:\n#{code_block(script)}")
end
diff --git a/test/ruby/test_jit_debug.rb b/test/ruby/test_jit_debug.rb
new file mode 100644
index 0000000000..50e52b4c2e
--- /dev/null
+++ b/test/ruby/test_jit_debug.rb
@@ -0,0 +1,17 @@
+require_relative 'test_jit'
+
+return unless defined?(TestJIT)
+return if ENV.key?('APPVEYOR')
+return if ENV.key?('RUBYCI_NICKNAME')
+return if ENV['RUBY_DEBUG']&.include?('ci') # ci.rvm.jp
+return if /mswin/ =~ RUBY_PLATFORM
+
+class TestJITDebug < TestJIT
+ @@test_suites.delete TestJIT if self.respond_to? :on_parallel_worker?
+
+ def setup
+ super
+ # let `#eval_with_jit` use --jit-debug
+ @jit_debug = true
+ end
+end
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index ab3c11e149..03f539fc72 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -24,9 +24,7 @@ class TestKeywordArguments < Test::Unit::TestCase
def test_f2
assert_equal([:xyz, "foo", 424242], f2(:xyz))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `f2'/m) do
- assert_equal([{"bar"=>42}, "foo", 424242], f2("bar"=>42))
- end
+ assert_raise(ArgumentError) { f2("bar"=>42) }
end
@@ -192,6 +190,218 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(["bar", 111111], f[str: "bar", num: 111111])
end
+ def test_keyword_splat_new
+ kw = {}
+ h = {a: 1}
+
+ def self.assert_equal_not_same(kw, res)
+ assert_instance_of(Hash, res)
+ assert_equal(kw, res)
+ assert_not_same(kw, res)
+ end
+
+ def self.y(**kw) kw end
+ m = method(:y)
+ assert_equal(false, y(**{}).frozen?)
+ assert_equal_not_same(kw, y(**kw))
+ assert_equal_not_same(h, y(**h))
+ assert_equal(false, send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, send(:y, **kw))
+ assert_equal_not_same(h, send(:y, **h))
+ assert_equal(false, public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, public_send(:y, **kw))
+ assert_equal_not_same(h, public_send(:y, **h))
+ assert_equal(false, m.(**{}).frozen?)
+ assert_equal_not_same(kw, m.(**kw))
+ assert_equal_not_same(h, m.(**h))
+ assert_equal(false, m.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, **kw))
+ assert_equal_not_same(h, m.send(:call, **h))
+
+ m = method(:send)
+ assert_equal(false, m.(:y, **{}).frozen?)
+ assert_equal_not_same(kw, m.(:y, **kw))
+ assert_equal_not_same(h, m.(:y, **h))
+ assert_equal(false, m.send(:call, :y, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, :y, **kw))
+ assert_equal_not_same(h, m.send(:call, :y, **h))
+
+ singleton_class.send(:remove_method, :y)
+ define_singleton_method(:y) { |**kw| kw }
+ m = method(:y)
+ assert_equal(false, y(**{}).frozen?)
+ assert_equal_not_same(kw, y(**kw))
+ assert_equal_not_same(h, y(**h))
+ assert_equal(false, send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, send(:y, **kw))
+ assert_equal_not_same(h, send(:y, **h))
+ assert_equal(false, public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, public_send(:y, **kw))
+ assert_equal_not_same(h, public_send(:y, **h))
+ assert_equal(false, m.(**{}).frozen?)
+ assert_equal_not_same(kw, m.(**kw))
+ assert_equal_not_same(h, m.(**h))
+ assert_equal(false, m.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, **kw))
+ assert_equal_not_same(h, m.send(:call, **h))
+
+ y = lambda { |**kw| kw }
+ m = y.method(:call)
+ assert_equal(false, y.(**{}).frozen?)
+ assert_equal_not_same(kw, y.(**kw))
+ assert_equal_not_same(h, y.(**h))
+ assert_equal(false, y.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, y.send(:call, **kw))
+ assert_equal_not_same(h, y.send(:call, **h))
+ assert_equal(false, y.public_send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, y.public_send(:call, **kw))
+ assert_equal_not_same(h, y.public_send(:call, **h))
+ assert_equal(false, m.(**{}).frozen?)
+ assert_equal_not_same(kw, m.(**kw))
+ assert_equal_not_same(h, m.(**h))
+ assert_equal(false, m.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, **kw))
+ assert_equal_not_same(h, m.send(:call, **h))
+
+ y = :y.to_proc
+ m = y.method(:call)
+ assert_equal(false, y.(self, **{}).frozen?)
+ assert_equal_not_same(kw, y.(self, **kw))
+ assert_equal_not_same(h, y.(self, **h))
+ assert_equal(false, y.send(:call, self, **{}).frozen?)
+ assert_equal_not_same(kw, y.send(:call, self, **kw))
+ assert_equal_not_same(h, y.send(:call, self, **h))
+ assert_equal(false, y.public_send(:call, self, **{}).frozen?)
+ assert_equal_not_same(kw, y.public_send(:call, self, **kw))
+ assert_equal_not_same(h, y.public_send(:call, self, **h))
+ assert_equal(false, m.(self, **{}).frozen?)
+ assert_equal_not_same(kw, m.(self, **kw))
+ assert_equal_not_same(h, m.(self, **h))
+ assert_equal(false, m.send(:call, self, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, self, **kw))
+ assert_equal_not_same(h, m.send(:call, self, **h))
+
+ c = Class.new do
+ def y(**kw) kw end
+ end
+ o = c.new
+ def o.y(**kw) super end
+ m = o.method(:y)
+ assert_equal(false, o.y(**{}).frozen?)
+ assert_equal_not_same(kw, o.y(**kw))
+ assert_equal_not_same(h, o.y(**h))
+ assert_equal(false, o.send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:y, **kw))
+ assert_equal_not_same(h, o.send(:y, **h))
+ assert_equal(false, o.public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:y, **kw))
+ assert_equal_not_same(h, o.public_send(:y, **h))
+ assert_equal(false, m.(**{}).frozen?)
+ assert_equal_not_same(kw, m.(**kw))
+ assert_equal_not_same(h, m.(**h))
+ assert_equal(false, m.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, **kw))
+ assert_equal_not_same(h, m.send(:call, **h))
+
+ o.singleton_class.send(:remove_method, :y)
+ def o.y(**kw) super(**kw) end
+ assert_equal(false, o.y(**{}).frozen?)
+ assert_equal_not_same(kw, o.y(**kw))
+ assert_equal_not_same(h, o.y(**h))
+ assert_equal(false, o.send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:y, **kw))
+ assert_equal_not_same(h, o.send(:y, **h))
+ assert_equal(false, o.public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:y, **kw))
+ assert_equal_not_same(h, o.public_send(:y, **h))
+ assert_equal(false, m.(**{}).frozen?)
+ assert_equal_not_same(kw, m.(**kw))
+ assert_equal_not_same(h, m.(**h))
+ assert_equal(false, m.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, **kw))
+ assert_equal_not_same(h, m.send(:call, **h))
+
+ c = Class.new do
+ def method_missing(_, **kw) kw end
+ end
+ o = c.new
+ def o.y(**kw) super end
+ m = o.method(:y)
+ assert_equal(false, o.y(**{}).frozen?)
+ assert_equal_not_same(kw, o.y(**kw))
+ assert_equal_not_same(h, o.y(**h))
+ assert_equal(false, o.send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:y, **kw))
+ assert_equal_not_same(h, o.send(:y, **h))
+ assert_equal(false, o.public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:y, **kw))
+ assert_equal_not_same(h, o.public_send(:y, **h))
+ assert_equal(false, m.(**{}).frozen?)
+ assert_equal_not_same(kw, m.(**kw))
+ assert_equal_not_same(h, m.(**h))
+ assert_equal(false, m.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, **kw))
+ assert_equal_not_same(h, m.send(:call, **h))
+
+ o.singleton_class.send(:remove_method, :y)
+ def o.y(**kw) super(**kw) end
+ assert_equal(false, o.y(**{}).frozen?)
+ assert_equal_not_same(kw, o.y(**kw))
+ assert_equal_not_same(h, o.y(**h))
+ assert_equal(false, o.send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:y, **kw))
+ assert_equal_not_same(h, o.send(:y, **h))
+ assert_equal(false, o.public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:y, **kw))
+ assert_equal_not_same(h, o.public_send(:y, **h))
+ assert_equal(false, m.(**{}).frozen?)
+ assert_equal_not_same(kw, m.(**kw))
+ assert_equal_not_same(h, m.(**h))
+ assert_equal(false, m.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, **kw))
+ assert_equal_not_same(h, m.send(:call, **h))
+
+ c = Class.new do
+ attr_reader :kw
+ def initialize(**kw) @kw = kw end
+ end
+ m = c.method(:new)
+ assert_equal(false, c.new(**{}).kw.frozen?)
+ assert_equal_not_same(kw, c.new(**kw).kw)
+ assert_equal_not_same(h, c.new(**h).kw)
+ assert_equal(false, c.send(:new, **{}).kw.frozen?)
+ assert_equal_not_same(kw, c.send(:new, **kw).kw)
+ assert_equal_not_same(h, c.send(:new, **h).kw)
+ assert_equal(false, c.public_send(:new, **{}).kw.frozen?)
+ assert_equal_not_same(kw, c.public_send(:new, **kw).kw)
+ assert_equal_not_same(h, c.public_send(:new, **h).kw)
+ assert_equal(false, m.(**{}).kw.frozen?)
+ assert_equal_not_same(kw, m.(**kw).kw)
+ assert_equal_not_same(h, m.(**h).kw)
+ assert_equal(false, m.send(:call, **{}).kw.frozen?)
+ assert_equal_not_same(kw, m.send(:call, **kw).kw)
+ assert_equal_not_same(h, m.send(:call, **h).kw)
+
+ singleton_class.send(:attr_writer, :y)
+ m = method(:y=)
+ assert_equal_not_same(h, send(:y=, **h))
+ assert_equal_not_same(h, public_send(:y=, **h))
+ assert_equal_not_same(h, m.(**h))
+ assert_equal_not_same(h, m.send(:call, **h))
+
+ singleton_class.send(:remove_method, :y)
+ def self.method_missing(_, **kw) kw end
+ assert_equal(false, y(**{}).frozen?)
+ assert_equal_not_same(kw, y(**kw))
+ assert_equal_not_same(h, y(**h))
+ assert_equal(false, send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, send(:y, **kw))
+ assert_equal_not_same(h, send(:y, **h))
+ assert_equal(false, public_send(:y, **{}).frozen?)
+ assert_equal_not_same(kw, public_send(:y, **kw))
+ assert_equal_not_same(h, public_send(:y, **h))
+ end
+
def test_regular_kwsplat
kw = {}
h = {:a=>1}
@@ -224,12 +434,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.m(args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.m(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.m(**kw))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
assert_equal(kw, c.m(kw, **kw))
assert_equal(h, c.m(**h))
assert_equal(h, c.m(a: 1))
@@ -248,39 +454,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.m(**h2))
assert_equal(h3, c.m(**h3))
assert_equal(h3, c.m(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, c.m(h))
- end
+ assert_raise(ArgumentError) { c.m(h) }
assert_raise(ArgumentError) { c.m(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { c.m(h3) }
- end
+ assert_raise(ArgumentError) { c.m(h3) }
c.singleton_class.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.m(**{})
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.m(**kw)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.m(**h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.m(a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], c.m(**h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.m(**h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.m(a: 1, **h2))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
+ assert_raise(ArgumentError) { c.m(**h) }
+ assert_raise(ArgumentError) { c.m(a: 1) }
+ assert_raise(ArgumentError) { c.m(**h2) }
+ assert_raise(ArgumentError) { c.m(**h3) }
+ assert_raise(ArgumentError) { c.m(a: 1, **h2) }
assert_equal([h, kw], c.m(h))
assert_equal([h2, kw], c.m(h2))
assert_equal([h3, kw], c.m(h3))
@@ -296,13 +484,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([1, h2], c.m(**h2))
assert_equal([1, h3], c.m(**h3))
assert_equal([1, h3], c.m(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal([1, h], c.m(h))
- end
+ assert_equal([h, kw], c.m(h))
assert_equal([h2, kw], c.m(h2))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal([h2, h], c.m(h3))
- end
+ assert_equal([h3, kw], c.m(h3))
end
def test_implicit_super_kwsplat
@@ -313,19 +497,9 @@ class TestKeywordArguments < Test::Unit::TestCase
sc = Class.new
c = sc.new
- redef = -> do
- if defined?(c.m)
- class << c
- remove_method(:m)
- end
- end
- eval <<-END
- def c.m(*args, **kw)
- super(*args, **kw)
- end
- END
+ def c.m(*args, **kw)
+ super(*args, **kw)
end
- redef[]
sc.class_eval do
def m(*args)
args
@@ -357,13 +531,8 @@ class TestKeywordArguments < Test::Unit::TestCase
args
end
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.m(**{}))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.m(**kw))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
assert_equal(h, c.m(**h))
assert_equal(h, c.m(a: 1))
assert_equal(h2, c.m(**h2))
@@ -383,13 +552,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.m(**h2))
assert_equal(h3, c.m(**h3))
assert_equal(h3, c.m(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, c.m(h))
- end
+ assert_raise(ArgumentError) { c.m(h) }
assert_raise(ArgumentError) { c.m(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { c.m(h3) }
- end
+ assert_raise(ArgumentError) { c.m(h3) }
sc.class_eval do
remove_method(:m)
@@ -397,34 +562,13 @@ class TestKeywordArguments < Test::Unit::TestCase
[arg, args]
end
end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.m(**{})
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.m(**kw)
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.m(**h))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.m(a: 1))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], c.m(**h2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.m(**h3))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.m(a: 1, **h2))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
+ assert_raise(ArgumentError) { c.m(**h) }
+ assert_raise(ArgumentError) { c.m(a: 1) }
+ assert_raise(ArgumentError) { c.m(**h2) }
+ assert_raise(ArgumentError) { c.m(**h3) }
+ assert_raise(ArgumentError) { c.m(a: 1, **h2) }
sc.class_eval do
remove_method(:m)
@@ -449,19 +593,9 @@ class TestKeywordArguments < Test::Unit::TestCase
sc = Class.new
c = sc.new
- redef = -> do
- if defined?(c.m)
- class << c
- remove_method(:m)
- end
- end
- eval <<-END
- def c.m(*args, **kw)
- super(*args, **kw)
- end
- END
+ def c.m(*args, **kw)
+ super(*args, **kw)
end
- redef[]
sc.class_eval do
def m(*args)
args
@@ -493,13 +627,8 @@ class TestKeywordArguments < Test::Unit::TestCase
args
end
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.m(**{}))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.m(**kw))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
assert_equal(h, c.m(**h))
assert_equal(h, c.m(a: 1))
assert_equal(h2, c.m(**h2))
@@ -519,13 +648,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.m(**h2))
assert_equal(h3, c.m(**h3))
assert_equal(h3, c.m(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, c.m(h))
- end
+ assert_raise(ArgumentError) { c.m(h) }
assert_raise(ArgumentError) { c.m(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { c.m(h3) }
- end
+ assert_raise(ArgumentError) { c.m(h3) }
sc.class_eval do
remove_method(:m)
@@ -533,34 +658,13 @@ class TestKeywordArguments < Test::Unit::TestCase
[arg, args]
end
end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.m(**{})
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.m(**kw)
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.m(**h))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.m(a: 1))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], c.m(**h2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.m(**h3))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.m(a: 1, **h2))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
+ assert_raise(ArgumentError) { c.m(**h) }
+ assert_raise(ArgumentError) { c.m(a: 1) }
+ assert_raise(ArgumentError) { c.m(**h2) }
+ assert_raise(ArgumentError) { c.m(**h3) }
+ assert_raise(ArgumentError) { c.m(a: 1, **h2) }
sc.class_eval do
remove_method(:m)
@@ -592,12 +696,8 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_raise(ArgumentError) { f[**h3] }
f = ->(a) { a }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, f[**{}])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, f[**kw])
- end
+ assert_raise(ArgumentError) { f[**{}] }
+ assert_raise(ArgumentError) { f[**kw] }
assert_equal(h, f[**h])
assert_equal(h, f[a: 1])
assert_equal(h2, f[**h2])
@@ -612,36 +712,18 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, f[**h2])
assert_equal(h3, f[**h3])
assert_equal(h3, f[a: 1, **h2])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `\[\]'/m) do
- assert_equal(h, f[h])
- end
+ assert_raise(ArgumentError) { f[h] }
assert_raise(ArgumentError) { f[h2] }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `\[\]'/m) do
- assert_raise(ArgumentError) { f[h3] }
- end
+ assert_raise(ArgumentError) { f[h3] }
f = ->(a, **x) { [a,x] }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do
- assert_equal([{}, {}], f[**{}])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do
- assert_equal([{}, {}], f[**kw])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do
- assert_equal([h, {}], f[**h])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do
- assert_equal([h, {}], f[a: 1])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do
- assert_equal([h2, {}], f[**h2])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do
- assert_equal([h3, {}], f[**h3])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `\[\]'/m) do
- assert_equal([h3, {}], f[a: 1, **h2])
- end
+ assert_raise(ArgumentError) { f[**{}] }
+ assert_raise(ArgumentError) { f[**kw] }
+ assert_raise(ArgumentError) { f[**h] }
+ assert_raise(ArgumentError) { f[a: 1] }
+ assert_raise(ArgumentError) { f[**h2] }
+ assert_raise(ArgumentError) { f[**h3] }
+ assert_raise(ArgumentError) { f[a: 1, **h2] }
f = ->(a=1, **x) { [a, x] }
assert_equal([1, kw], f[**{}])
@@ -670,12 +752,8 @@ class TestKeywordArguments < Test::Unit::TestCase
f = ->(a) { a }
f = f.method(:call)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, f[**{}])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, f[**kw])
- end
+ assert_raise(ArgumentError) { f[**{}] }
+ assert_raise(ArgumentError) { f[**kw] }
assert_equal(h, f[**h])
assert_equal(h, f[a: 1])
assert_equal(h2, f[**h2])
@@ -691,37 +769,19 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, f[**h2])
assert_equal(h3, f[**h3])
assert_equal(h3, f[a: 1, **h2])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(h, f[h])
- end
+ assert_raise(ArgumentError) { f[h] }
assert_raise(ArgumentError) { f[h2] }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do
- assert_raise(ArgumentError) { f[h3] }
- end
+ assert_raise(ArgumentError) { f[h3] }
f = ->(a, **x) { [a,x] }
f = f.method(:call)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], f[**{}])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], f[**kw])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], f[**h])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], f[a: 1])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h2, {}], f[**h2])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], f[**h3])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], f[a: 1, **h2])
- end
+ assert_raise(ArgumentError) { f[**{}] }
+ assert_raise(ArgumentError) { f[**kw] }
+ assert_raise(ArgumentError) { f[**h] }
+ assert_raise(ArgumentError) { f[a: 1] }
+ assert_raise(ArgumentError) { f[**h2] }
+ assert_raise(ArgumentError) { f[**h3] }
+ assert_raise(ArgumentError) { f[a: 1, **h2] }
f = ->(a=1, **x) { [a, x] }
f = f.method(:call)
@@ -751,12 +811,8 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_raise(ArgumentError) { t.new(**h3, &f).value }
f = ->(a) { a }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, t.new(**{}, &f).value)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, t.new(**kw, &f).value)
- end
+ assert_raise(ArgumentError) { t.new(**{}, &f).value }
+ assert_raise(ArgumentError) { t.new(**kw, &f).value }
assert_equal(h, t.new(**h, &f).value)
assert_equal(h, t.new(a: 1, &f).value)
assert_equal(h2, t.new(**h2, &f).value)
@@ -771,36 +827,18 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, t.new(**h2, &f).value)
assert_equal(h3, t.new(**h3, &f).value)
assert_equal(h3, t.new(a: 1, **h2, &f).value)
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(h, t.new(h, &f).value)
- end
+ assert_raise(ArgumentError) { t.new(h, &f).value }
assert_raise(ArgumentError) { t.new(h2, &f).value }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do
- assert_raise(ArgumentError) { t.new(h3, &f).value }
- end
+ assert_raise(ArgumentError) { t.new(h3, &f).value }
f = ->(a, **x) { [a,x] }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], t.new(**{}, &f).value)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], t.new(**kw, &f).value)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], t.new(**h, &f).value)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], t.new(a: 1, &f).value)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h2, {}], t.new(**h2, &f).value)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], t.new(**h3, &f).value)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], t.new(a: 1, **h2, &f).value)
- end
+ assert_raise(ArgumentError) { t.new(**{}, &f).value }
+ assert_raise(ArgumentError) { t.new(**kw, &f).value }
+ assert_raise(ArgumentError) { t.new(**h, &f).value }
+ assert_raise(ArgumentError) { t.new(a: 1, &f).value }
+ assert_raise(ArgumentError) { t.new(**h2, &f).value }
+ assert_raise(ArgumentError) { t.new(**h3, &f).value }
+ assert_raise(ArgumentError) { t.new(a: 1, **h2, &f).value }
f = ->(a=1, **x) { [a, x] }
assert_equal([1, kw], t.new(**{}, &f).value)
@@ -830,12 +868,8 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_raise(ArgumentError) { t.new(&f).resume(**h3) }
f = ->(a) { a }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, t.new(&f).resume(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, t.new(&f).resume(**kw))
- end
+ assert_raise(ArgumentError) { t.new(&f).resume(**{}) }
+ assert_raise(ArgumentError) { t.new(&f).resume(**kw) }
assert_equal(h, t.new(&f).resume(**h))
assert_equal(h, t.new(&f).resume(a: 1))
assert_equal(h2, t.new(&f).resume(**h2))
@@ -850,36 +884,18 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, t.new(&f).resume(**h2))
assert_equal(h3, t.new(&f).resume(**h3))
assert_equal(h3, t.new(&f).resume(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(h, t.new(&f).resume(h))
- end
+ assert_raise(ArgumentError) { t.new(&f).resume(h) }
assert_raise(ArgumentError) { t.new(&f).resume(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do
- assert_raise(ArgumentError) { t.new(&f).resume(h3) }
- end
+ assert_raise(ArgumentError) { t.new(&f).resume(h3) }
f = ->(a, **x) { [a,x] }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], t.new(&f).resume(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], t.new(&f).resume(**kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], t.new(&f).resume(**h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], t.new(&f).resume(a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h2, {}], t.new(&f).resume(**h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], t.new(&f).resume(**h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], t.new(&f).resume(a: 1, **h2))
- end
+ assert_raise(ArgumentError) { t.new(&f).resume(**{}) }
+ assert_raise(ArgumentError) { t.new(&f).resume(**kw) }
+ assert_raise(ArgumentError) { t.new(&f).resume(**h) }
+ assert_raise(ArgumentError) { t.new(&f).resume(a: 1) }
+ assert_raise(ArgumentError) { t.new(&f).resume(**h2) }
+ assert_raise(ArgumentError) { t.new(&f).resume(**h3) }
+ assert_raise(ArgumentError) { t.new(&f).resume(a: 1, **h2) }
f = ->(a=1, **x) { [a, x] }
assert_equal([1, kw], t.new(&f).resume(**{}))
@@ -907,12 +923,8 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_raise(ArgumentError) { g.new(&f).each(**h3) }
f = ->(_, a) { a }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, g.new(&f).each(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, g.new(&f).each(**kw))
- end
+ assert_raise(ArgumentError) { g.new(&f).each(**{}) }
+ assert_raise(ArgumentError) { g.new(&f).each(**kw) }
assert_equal(h, g.new(&f).each(**h))
assert_equal(h, g.new(&f).each(a: 1))
assert_equal(h2, g.new(&f).each(**h2))
@@ -927,36 +939,18 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, g.new(&f).each(**h2))
assert_equal(h3, g.new(&f).each(**h3))
assert_equal(h3, g.new(&f).each(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(h, g.new(&f).each(h))
- end
+ assert_raise(ArgumentError) { g.new(&f).each(h) }
assert_raise(ArgumentError) { g.new(&f).each(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do
- assert_raise(ArgumentError) { g.new(&f).each(h3) }
- end
+ assert_raise(ArgumentError) { g.new(&f).each(h3) }
f = ->(_, a, **x) { [a,x] }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], g.new(&f).each(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], g.new(&f).each(**kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], g.new(&f).each(**h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], g.new(&f).each(a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h2, {}], g.new(&f).each(**h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], g.new(&f).each(**h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], g.new(&f).each(a: 1, **h2))
- end
+ assert_raise(ArgumentError) { g.new(&f).each(**{}) }
+ assert_raise(ArgumentError) { g.new(&f).each(**kw) }
+ assert_raise(ArgumentError) { g.new(&f).each(**h) }
+ assert_raise(ArgumentError) { g.new(&f).each(a: 1) }
+ assert_raise(ArgumentError) { g.new(&f).each(**h2) }
+ assert_raise(ArgumentError) { g.new(&f).each(**h3) }
+ assert_raise(ArgumentError) { g.new(&f).each(a: 1, **h2) }
f = ->(_, a=1, **x) { [a, x] }
assert_equal([1, kw], g.new(&f).each(**{}))
@@ -984,12 +978,8 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_raise(ArgumentError) { g.new{|y| y.yield(**h3)}.each(&f) }
f = ->(a) { a }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, g.new{|y| y.yield(**{})}.each(&f))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, g.new{|y| y.yield(**kw)}.each(&f))
- end
+ assert_raise(ArgumentError) { g.new{|y| y.yield(**{})}.each(&f) }
+ assert_raise(ArgumentError) { g.new{|y| y.yield(**kw)}.each(&f) }
assert_equal(h, g.new{|y| y.yield(**h)}.each(&f))
assert_equal(h, g.new{|y| y.yield(a: 1)}.each(&f))
assert_equal(h2, g.new{|y| y.yield(**h2)}.each(&f))
@@ -1004,36 +994,18 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, g.new{|y| y.yield(**h2)}.each(&f))
assert_equal(h3, g.new{|y| y.yield(**h3)}.each(&f))
assert_equal(h3, g.new{|y| y.yield(a: 1, **h2)}.each(&f))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(h, g.new{|y| y.yield(h)}.each(&f))
- end
+ assert_raise(ArgumentError) { g.new{|y| y.yield(h)}.each(&f) }
assert_raise(ArgumentError) { g.new{|y| y.yield(h2)}.each(&f) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do
- assert_raise(ArgumentError) { g.new{|y| y.yield(h3)}.each(&f) }
- end
+ assert_raise(ArgumentError) { g.new{|y| y.yield(h3)}.each(&f) }
f = ->(a, **x) { [a,x] }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], g.new{|y| y.yield(**{})}.each(&f))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([{}, {}], g.new{|y| y.yield(**kw)}.each(&f))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], g.new{|y| y.yield(**h)}.each(&f))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, {}], g.new{|y| y.yield(a: 1)}.each(&f))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h2, {}], g.new{|y| y.yield(**h2)}.each(&f))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], g.new{|y| y.yield(**h3)}.each(&f))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, {}], g.new{|y| y.yield(a: 1, **h2)}.each(&f))
- end
+ assert_raise(ArgumentError) { g.new{|y| y.yield(**{})}.each(&f) }
+ assert_raise(ArgumentError) { g.new{|y| y.yield(**kw)}.each(&f) }
+ assert_raise(ArgumentError) { g.new{|y| y.yield(**h)}.each(&f) }
+ assert_raise(ArgumentError) { g.new{|y| y.yield(a: 1)}.each(&f) }
+ assert_raise(ArgumentError) { g.new{|y| y.yield(**h2)}.each(&f) }
+ assert_raise(ArgumentError) { g.new{|y| y.yield(**h3)}.each(&f) }
+ assert_raise(ArgumentError) { g.new{|y| y.yield(a: 1, **h2)}.each(&f) }
f = ->(a=1, **x) { [a, x] }
assert_equal([1, kw], g.new{|y| y.yield(**{})}.each(&f))
@@ -1087,12 +1059,8 @@ class TestKeywordArguments < Test::Unit::TestCase
@args = args
end
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal(kw, c[**{}].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal(kw, c[**kw].args)
- end
+ assert_raise(ArgumentError) { c[**{}] }
+ assert_raise(ArgumentError) { c[**kw] }
assert_equal(h, c[**h].args)
assert_equal(h, c[a: 1].args)
assert_equal(h2, c[**h2].args)
@@ -1111,40 +1079,22 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c[**h2].args)
assert_equal(h3, c[**h3].args)
assert_equal(h3, c[a: 1, **h2].args)
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do
- assert_equal(h, c[h].args)
- end
+ assert_raise(ArgumentError) { c[h].args }
assert_raise(ArgumentError) { c[h2].args }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `initialize'/m) do
- assert_raise(ArgumentError) { c[h3].args }
- end
+ assert_raise(ArgumentError) { c[h3].args }
c = Class.new(sc) do
def initialize(arg, **args)
@args = [arg, args]
end
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([kw, kw], c[**{}].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([kw, kw], c[**kw].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h, kw], c[**h].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h, kw], c[a: 1].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h2, kw], c[**h2].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h3, kw], c[**h3].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h3, kw], c[a: 1, **h2].args)
- end
+ assert_raise(ArgumentError) { c[**{}].args }
+ assert_raise(ArgumentError) { c[**kw].args }
+ assert_raise(ArgumentError) { c[**h].args }
+ assert_raise(ArgumentError) { c[a: 1].args }
+ assert_raise(ArgumentError) { c[**h2].args }
+ assert_raise(ArgumentError) { c[**h3].args }
+ assert_raise(ArgumentError) { c[a: 1, **h2].args }
c = Class.new(sc) do
def initialize(arg=1, **args)
@@ -1199,12 +1149,8 @@ class TestKeywordArguments < Test::Unit::TestCase
@args = args
end
end.method(:new)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal(kw, c[**{}].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal(kw, c[**kw].args)
- end
+ assert_raise(ArgumentError) { c[**{}] }
+ assert_raise(ArgumentError) { c[**kw] }
assert_equal(h, c[**h].args)
assert_equal(h, c[a: 1].args)
assert_equal(h2, c[**h2].args)
@@ -1223,40 +1169,22 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c[**h2].args)
assert_equal(h3, c[**h3].args)
assert_equal(h3, c[a: 1, **h2].args)
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do
- assert_equal(h, c[h].args)
- end
+ assert_raise(ArgumentError) { c[h].args }
assert_raise(ArgumentError) { c[h2].args }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `initialize'/m) do
- assert_raise(ArgumentError) { c[h3].args }
- end
+ assert_raise(ArgumentError) { c[h3].args }
c = Class.new(sc) do
def initialize(arg, **args)
@args = [arg, args]
end
end.method(:new)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([kw, kw], c[**{}].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([kw, kw], c[**kw].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h, kw], c[**h].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h, kw], c[a: 1].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h2, kw], c[**h2].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h3, kw], c[**h3].args)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `initialize'/m) do
- assert_equal([h3, kw], c[a: 1, **h2].args)
- end
+ assert_raise(ArgumentError) { c[**{}].args }
+ assert_raise(ArgumentError) { c[**kw].args }
+ assert_raise(ArgumentError) { c[**h].args }
+ assert_raise(ArgumentError) { c[a: 1].args }
+ assert_raise(ArgumentError) { c[**h2].args }
+ assert_raise(ArgumentError) { c[**h3].args }
+ assert_raise(ArgumentError) { c[a: 1, **h2].args }
c = Class.new(sc) do
def initialize(arg=1, **args)
@@ -1304,12 +1232,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.m(args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.method(:m)[**{}])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.method(:m)[**kw])
- end
+ assert_raise(ArgumentError) { c.method(:m)[**{}] }
+ assert_raise(ArgumentError) { c.method(:m)[**kw] }
assert_equal(h, c.method(:m)[**h])
assert_equal(h, c.method(:m)[a: 1])
assert_equal(h2, c.method(:m)[**h2])
@@ -1327,39 +1251,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.method(:m)[**h2])
assert_equal(h3, c.method(:m)[**h3])
assert_equal(h3, c.method(:m)[a: 1, **h2])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, c.method(:m)[h])
- end
+ assert_raise(ArgumentError) { c.method(:m)[h] }
assert_raise(ArgumentError) { c.method(:m)[h2] }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { c.method(:m)[h3] }
- end
+ assert_raise(ArgumentError) { c.method(:m)[h3] }
c.singleton_class.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], c.method(:m)[**{}])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], c.method(:m)[**kw])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.method(:m)[**h])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.method(:m)[a: 1])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], c.method(:m)[**h2])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.method(:m)[**h3])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.method(:m)[a: 1, **h2])
- end
+ assert_raise(ArgumentError) { c.method(:m)[**{}] }
+ assert_raise(ArgumentError) { c.method(:m)[**kw] }
+ assert_raise(ArgumentError) { c.method(:m)[**h] }
+ assert_raise(ArgumentError) { c.method(:m)[a: 1] }
+ assert_raise(ArgumentError) { c.method(:m)[**h2] }
+ assert_raise(ArgumentError) { c.method(:m)[**h3] }
+ assert_raise(ArgumentError) { c.method(:m)[a: 1, **h2] }
c.singleton_class.remove_method(:m)
def c.m(arg=1, **args)
@@ -1407,12 +1313,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.m(args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, sc.instance_method(:m).bind_call(c, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, sc.instance_method(:m).bind_call(c, **kw))
- end
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **{}) }
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **kw) }
assert_equal(h, sc.instance_method(:m).bind_call(c, **h))
assert_equal(h, sc.instance_method(:m).bind_call(c, a: 1))
assert_equal(h2, sc.instance_method(:m).bind_call(c, **h2))
@@ -1430,39 +1332,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, sc.instance_method(:m).bind_call(c, **h2))
assert_equal(h3, sc.instance_method(:m).bind_call(c, **h3))
assert_equal(h3, sc.instance_method(:m).bind_call(c, a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, sc.instance_method(:m).bind_call(c, h))
- end
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h) }
assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h3) }
- end
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, h3) }
sc.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], sc.instance_method(:m).bind_call(c, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], sc.instance_method(:m).bind_call(c, **kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], sc.instance_method(:m).bind_call(c, **h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], sc.instance_method(:m).bind_call(c, a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], sc.instance_method(:m).bind_call(c, **h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], sc.instance_method(:m).bind_call(c, **h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], sc.instance_method(:m).bind_call(c, a: 1, **h2))
- end
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **{}) }
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **kw) }
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h) }
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, a: 1) }
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h2) }
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, **h3) }
+ assert_raise(ArgumentError) { sc.instance_method(:m).bind_call(c, a: 1, **h2) }
sc.remove_method(:m)
def c.m(arg=1, **args)
@@ -1509,12 +1393,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.m(args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.send(:m, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.send(:m, **kw))
- end
+ assert_raise(ArgumentError) { c.send(:m, **{}) }
+ assert_raise(ArgumentError) { c.send(:m, **kw) }
assert_equal(h, c.send(:m, **h))
assert_equal(h, c.send(:m, a: 1))
assert_equal(h2, c.send(:m, **h2))
@@ -1532,39 +1412,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.send(:m, **h2))
assert_equal(h3, c.send(:m, **h3))
assert_equal(h3, c.send(:m, a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, c.send(:m, h))
- end
+ assert_raise(ArgumentError) { c.send(:m, h) }
assert_raise(ArgumentError) { c.send(:m, h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { c.send(:m, h3) }
- end
+ assert_raise(ArgumentError) { c.send(:m, h3) }
c.singleton_class.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.send(:m, **{})
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.send(:m, **kw)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.send(:m, **h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.send(:m, a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], c.send(:m, **h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.send(:m, **h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.send(:m, a: 1, **h2))
- end
+ assert_raise(ArgumentError) { c.send(:m, **{}) }
+ assert_raise(ArgumentError) { c.send(:m, **kw) }
+ assert_raise(ArgumentError) { c.send(:m, **h) }
+ assert_raise(ArgumentError) { c.send(:m, a: 1) }
+ assert_raise(ArgumentError) { c.send(:m, **h2) }
+ assert_raise(ArgumentError) { c.send(:m, **h3) }
+ assert_raise(ArgumentError) { c.send(:m, a: 1, **h2) }
c.singleton_class.remove_method(:m)
def c.m(arg=1, **args)
@@ -1611,12 +1473,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.m(args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.public_send(:m, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.public_send(:m, **kw))
- end
+ assert_raise(ArgumentError) { c.public_send(:m, **{}) }
+ assert_raise(ArgumentError) { c.public_send(:m, **kw) }
assert_equal(h, c.public_send(:m, **h))
assert_equal(h, c.public_send(:m, a: 1))
assert_equal(h2, c.public_send(:m, **h2))
@@ -1634,39 +1492,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.public_send(:m, **h2))
assert_equal(h3, c.public_send(:m, **h3))
assert_equal(h3, c.public_send(:m, a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, c.public_send(:m, h))
- end
+ assert_raise(ArgumentError) { c.public_send(:m, h) }
assert_raise(ArgumentError) { c.public_send(:m, h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { c.public_send(:m, h3) }
- end
+ assert_raise(ArgumentError) { c.public_send(:m, h3) }
c.singleton_class.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.public_send(:m, **{})
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- c.public_send(:m, **kw)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.public_send(:m, **h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.public_send(:m, a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], c.public_send(:m, **h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.public_send(:m, **h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.public_send(:m, a: 1, **h2))
- end
+ assert_raise(ArgumentError) { c.public_send(:m, **{}) }
+ assert_raise(ArgumentError) { c.public_send(:m, **kw) }
+ assert_raise(ArgumentError) { c.public_send(:m, **h) }
+ assert_raise(ArgumentError) { c.public_send(:m, a: 1) }
+ assert_raise(ArgumentError) { c.public_send(:m, **h2) }
+ assert_raise(ArgumentError) { c.public_send(:m, **h3) }
+ assert_raise(ArgumentError) { c.public_send(:m, a: 1, **h2) }
c.singleton_class.remove_method(:m)
def c.m(arg=1, **args)
@@ -1716,12 +1556,8 @@ class TestKeywordArguments < Test::Unit::TestCase
args
end
m = c.method(:send)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, m.call(:m, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, m.call(:m, **kw))
- end
+ assert_raise(ArgumentError) { m.call(:m, **{}) }
+ assert_raise(ArgumentError) { m.call(:m, **kw) }
assert_equal(h, m.call(:m, **h))
assert_equal(h, m.call(:m, a: 1))
assert_equal(h2, m.call(:m, **h2))
@@ -1740,40 +1576,22 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, m.call(:m, **h2))
assert_equal(h3, m.call(:m, **h3))
assert_equal(h3, m.call(:m, a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, m.call(:m, h))
- end
+ assert_raise(ArgumentError) { m.call(:m, h) }
assert_raise(ArgumentError) { m.call(:m, h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { m.call(:m, h3) }
- end
+ assert_raise(ArgumentError) { m.call(:m, h3) }
c.singleton_class.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
m = c.method(:send)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- m.call(:m, **{})
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- m.call(:m, **kw)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], m.call(:m, **h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], m.call(:m, a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], m.call(:m, **h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], m.call(:m, **h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], m.call(:m, a: 1, **h2))
- end
+ assert_raise(ArgumentError) { m.call(:m, **{}) }
+ assert_raise(ArgumentError) { m.call(:m, **kw) }
+ assert_raise(ArgumentError) { m.call(:m, **h) }
+ assert_raise(ArgumentError) { m.call(:m, a: 1) }
+ assert_raise(ArgumentError) { m.call(:m, **h2) }
+ assert_raise(ArgumentError) { m.call(:m, **h3) }
+ assert_raise(ArgumentError) { m.call(:m, a: 1, **h2) }
c.singleton_class.remove_method(:m)
def c.m(arg=1, **args)
@@ -1821,12 +1639,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.m(args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, :m.to_proc.call(c, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, :m.to_proc.call(c, **kw))
- end
+ assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) }
+ assert_raise(ArgumentError) { :m.to_proc.call(c, **kw) }
assert_equal(h, :m.to_proc.call(c, **h))
assert_equal(h, :m.to_proc.call(c, a: 1))
assert_equal(h2, :m.to_proc.call(c, **h2))
@@ -1844,39 +1658,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, :m.to_proc.call(c, **h2))
assert_equal(h3, :m.to_proc.call(c, **h3))
assert_equal(h3, :m.to_proc.call(c, a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, :m.to_proc.call(c, h))
- end
+ assert_raise(ArgumentError) { :m.to_proc.call(c, h) }
assert_raise(ArgumentError) { :m.to_proc.call(c, h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { :m.to_proc.call(c, h3) }
- end
+ assert_raise(ArgumentError) { :m.to_proc.call(c, h3) }
c.singleton_class.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], :m.to_proc.call(c, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], :m.to_proc.call(c, **kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], :m.to_proc.call(c, **h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], :m.to_proc.call(c, a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], :m.to_proc.call(c, **h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], :m.to_proc.call(c, **h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], :m.to_proc.call(c, a: 1, **h2))
- end
+ assert_raise(ArgumentError) { :m.to_proc.call(c, **{}) }
+ assert_raise(ArgumentError) { :m.to_proc.call(c, **kw) }
+ assert_raise(ArgumentError) { :m.to_proc.call(c, **h) }
+ assert_raise(ArgumentError) { :m.to_proc.call(c, a: 1) }
+ assert_raise(ArgumentError) { :m.to_proc.call(c, **h2) }
+ assert_raise(ArgumentError) { :m.to_proc.call(c, **h3) }
+ assert_raise(ArgumentError) { :m.to_proc.call(c, a: 1, **h2) }
c.singleton_class.remove_method(:m)
def c.m(arg=1, **args)
@@ -1924,12 +1720,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.m(args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, m.call(c, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, m.call(c, **kw))
- end
+ assert_raise(ArgumentError) { m.call(c, **{}) }
+ assert_raise(ArgumentError) { m.call(c, **kw) }
assert_equal(h, m.call(c, **h))
assert_equal(h, m.call(c, a: 1))
assert_equal(h2, m.call(c, **h2))
@@ -1947,39 +1739,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, m.call(c, **h2))
assert_equal(h3, m.call(c, **h3))
assert_equal(h3, m.call(c, a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, m.call(c, h))
- end
+ assert_raise(ArgumentError) { m.call(c, h) }
assert_raise(ArgumentError) { m.call(c, h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { m.call(c, h3) }
- end
+ assert_raise(ArgumentError) { m.call(c, h3) }
c.singleton_class.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], m.call(c, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], m.call(c, **kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], m.call(c, **h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], m.call(c, a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], m.call(c, **h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], m.call(c, **h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], m.call(c, a: 1, **h2))
- end
+ assert_raise(ArgumentError) { m.call(c, **{}) }
+ assert_raise(ArgumentError) { m.call(c, **kw) }
+ assert_raise(ArgumentError) { m.call(c, **h) }
+ assert_raise(ArgumentError) { m.call(c, a: 1) }
+ assert_raise(ArgumentError) { m.call(c, **h2) }
+ assert_raise(ArgumentError) { m.call(c, **h3) }
+ assert_raise(ArgumentError) { m.call(c, a: 1, **h2) }
c.singleton_class.remove_method(:m)
def c.m(arg=1, **args)
@@ -2026,12 +1800,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.method_missing(_, args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.m(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.m(**kw))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
assert_equal(h, c.m(**h))
assert_equal(h, c.m(a: 1))
assert_equal(h2, c.m(**h2))
@@ -2049,39 +1819,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.m(**h2))
assert_equal(h3, c.m(**h3))
assert_equal(h3, c.m(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal(h, c.m(h))
- end
+ assert_raise(ArgumentError) { c.m(h) }
assert_raise(ArgumentError) { c.m(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_raise(ArgumentError) { c.m(h3) }
- end
+ assert_raise(ArgumentError) { c.m(h3) }
c.singleton_class.remove_method(:method_missing)
def c.method_missing(_, arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.m(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.m(**kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.m(**h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.m(a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h2, kw], c.m(**h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.m(**h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.m(a: 1, **h2))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
+ assert_raise(ArgumentError) { c.m(**h) }
+ assert_raise(ArgumentError) { c.m(a: 1) }
+ assert_raise(ArgumentError) { c.m(**h2) }
+ assert_raise(ArgumentError) { c.m(**h3) }
+ assert_raise(ArgumentError) { c.m(a: 1, **h2) }
c.singleton_class.remove_method(:method_missing)
def c.method_missing(_, arg=1, **args)
@@ -2128,22 +1880,12 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_raise(ArgumentError) { c.m(**h3) }
assert_raise(ArgumentError) { c.m(a: 1, **h2) }
- redef = -> do
- c.singleton_class.remove_method(:method_missing)
- eval <<-END
- def c.method_missing(_, args)
- args
- end
- END
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.m(**{}))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.m(**kw))
+ c.singleton_class.remove_method(:method_missing)
+ def c.method_missing(_, args)
+ args
end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
assert_equal(h, c.m(**h))
assert_equal(h, c.m(a: 1))
assert_equal(h2, c.m(**h2))
@@ -2161,50 +1903,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.m(**h2))
assert_equal(h3, c.m(**h3))
assert_equal(h3, c.m(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m'/m) do
- assert_equal(h, c.m(h))
- end
+ assert_raise(ArgumentError) { c.m(h) }
assert_raise(ArgumentError) { c.m(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `m'/m) do
- assert_raise(ArgumentError) { c.m(h3) }
- end
+ assert_raise(ArgumentError) { c.m(h3) }
- redef = -> do
- c.singleton_class.remove_method(:method_missing)
- eval <<-END
- def c.method_missing(_, arg, **args)
- [arg, args]
- end
- END
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.m(**{}))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.m(**kw))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.m(**h))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.m(a: 1))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h2, kw], c.m(**h2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.m(**h3))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.m(a: 1, **h2))
+ c.singleton_class.remove_method(:method_missing)
+ def c.method_missing(_, arg, **args)
+ [arg, args]
end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
+ assert_raise(ArgumentError) { c.m(**h) }
+ assert_raise(ArgumentError) { c.m(a: 1) }
+ assert_raise(ArgumentError) { c.m(**h2) }
+ assert_raise(ArgumentError) { c.m(**h3) }
+ assert_raise(ArgumentError) { c.m(a: 1, **h2) }
c.singleton_class.remove_method(:method_missing)
def c.method_missing(_, arg=1, **args)
@@ -2252,12 +1965,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.method_missing(_, args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.m(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.m(**kw))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
assert_equal(h, c.m(**h))
assert_equal(h, c.m(a: 1))
assert_equal(h2, c.m(**h2))
@@ -2275,39 +1984,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.m(**h2))
assert_equal(h3, c.m(**h3))
assert_equal(h3, c.m(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal(h, c.m(h))
- end
+ assert_raise(ArgumentError) { c.m(h) }
assert_raise(ArgumentError) { c.m(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_raise(ArgumentError) { c.m(h3) }
- end
+ assert_raise(ArgumentError) { c.m(h3) }
c.singleton_class.remove_method(:method_missing)
def c.method_missing(_, arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.m(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.m(**kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.m(**h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.m(a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h2, kw], c.m(**h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.m(**h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.m(a: 1, **h2))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
+ assert_raise(ArgumentError) { c.m(**h) }
+ assert_raise(ArgumentError) { c.m(a: 1) }
+ assert_raise(ArgumentError) { c.m(**h2) }
+ assert_raise(ArgumentError) { c.m(**h3) }
+ assert_raise(ArgumentError) { c.m(a: 1, **h2) }
c.singleton_class.remove_method(:method_missing)
def c.method_missing(_, arg=1, **args)
@@ -2344,12 +2035,8 @@ class TestKeywordArguments < Test::Unit::TestCase
class << c
define_method(:m) {|arg| arg }
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, c.m(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, c.m(**kw))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
assert_equal(h, c.m(**h))
assert_equal(h, c.m(a: 1))
assert_equal(h2, c.m(**h2))
@@ -2379,39 +2066,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.m(**h2))
assert_equal(h3, c.m(**h3))
assert_equal(h3, c.m(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated/m) do
- assert_equal(h, c.m(h))
- end
+ assert_raise(ArgumentError) { c.m(h) }
assert_raise(ArgumentError) { c.m(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do
- assert_raise(ArgumentError) { c.m(h3) }
- end
+ assert_raise(ArgumentError) { c.m(h3) }
c = Object.new
class << c
define_method(:m) {|arg, **opt| [arg, opt] }
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([kw, kw], c.m(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([kw, kw], c.m(**kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h, kw], c.m(**h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h, kw], c.m(a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h2, kw], c.m(**h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h3, kw], c.m(**h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h3, kw], c.m(a: 1, **h2))
- end
+ assert_raise(ArgumentError) { c.m(**{}) }
+ assert_raise(ArgumentError) { c.m(**kw) }
+ assert_raise(ArgumentError) { c.m(**h) }
+ assert_raise(ArgumentError) { c.m(a: 1) }
+ assert_raise(ArgumentError) { c.m(**h2) }
+ assert_raise(ArgumentError) { c.m(**h3) }
+ assert_raise(ArgumentError) { c.m(a: 1, **h2) }
c = Object.new
class << c
@@ -2429,23 +2098,15 @@ class TestKeywordArguments < Test::Unit::TestCase
class << c
define_method(:m) {|*args, **opt| [args, opt] }
end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([[], h], c.m(h))
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([[h], h], c.m(h, h))
- end
+ assert_equal([[h], kw], c.m(h))
+ assert_equal([[h, h], kw], c.m(h, h))
c = Object.new
class << c
define_method(:m) {|arg=nil, a: nil| [arg, a] }
end
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([h2, 1], c.m(h3))
- end
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([h2, 1], c.m(**h3))
- end
+ assert_equal([h3, nil], c.m(h3))
+ assert_raise(ArgumentError) { c.m(**h3) }
end
def test_define_method_method_kwsplat
@@ -2472,12 +2133,8 @@ class TestKeywordArguments < Test::Unit::TestCase
define_method(:m) {|arg| arg }
end
m = c.method(:m)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, m.call(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, m.call(**kw))
- end
+ assert_raise(ArgumentError) { m.call(**{}) }
+ assert_raise(ArgumentError) { m.call(**kw) }
assert_equal(h, m.call(**h))
assert_equal(h, m.call(a: 1))
assert_equal(h2, m.call(**h2))
@@ -2509,40 +2166,22 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, m.call(**h2))
assert_equal(h3, m.call(**h3))
assert_equal(h3, m.call(a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated/m) do
- assert_equal(h, m.call(h))
- end
+ assert_raise(ArgumentError) { m.call(h) }
assert_raise(ArgumentError) { m.call(h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do
- assert_raise(ArgumentError) { m.call(h3) }
- end
+ assert_raise(ArgumentError) { m.call(h3) }
c = Object.new
class << c
define_method(:m) {|arg, **opt| [arg, opt] }
end
m = c.method(:m)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([kw, kw], m.call(**{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([kw, kw], m.call(**kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h, kw], m.call(**h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h, kw], m.call(a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h2, kw], m.call(**h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h3, kw], m.call(**h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h3, kw], m.call(a: 1, **h2))
- end
+ assert_raise(ArgumentError) { m.call(**{}) }
+ assert_raise(ArgumentError) { m.call(**kw) }
+ assert_raise(ArgumentError) { m.call(**h) }
+ assert_raise(ArgumentError) { m.call(a: 1) }
+ assert_raise(ArgumentError) { m.call(**h2) }
+ assert_raise(ArgumentError) { m.call(**h3) }
+ assert_raise(ArgumentError) { m.call(a: 1, **h2) }
c = Object.new
class << c
@@ -2562,24 +2201,16 @@ class TestKeywordArguments < Test::Unit::TestCase
define_method(:m) {|*args, **opt| [args, opt] }
end
m = c.method(:m)
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([[], h], m.call(h))
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([[h], h], m.call(h, h))
- end
+ assert_equal([[h], kw], m.call(h))
+ assert_equal([[h, h], kw], m.call(h, h))
c = Object.new
class << c
define_method(:m) {|arg=nil, a: nil| [arg, a] }
end
m = c.method(:m)
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([h2, 1], m.call(h3))
- end
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([h2, 1], m.call(**h3))
- end
+ assert_equal([h3, nil], m.call(h3))
+ assert_raise(ArgumentError) { m.call(**h3) }
end
def test_attr_reader_kwsplat
@@ -2631,12 +2262,8 @@ class TestKeywordArguments < Test::Unit::TestCase
class << c
attr_writer :m
end
- assert_warn(/Passing the keyword argument for `m=' as the last hash parameter is deprecated/) do
- c.send(:m=, **{})
- end
- assert_warn(/Passing the keyword argument for `m=' as the last hash parameter is deprecated/) do
- c.send(:m=, **kw)
- end
+ assert_raise(ArgumentError) { c.send(:m=, **{}) }
+ assert_raise(ArgumentError) { c.send(:m=, **kw) }
assert_equal(h, c.send(:m=, **h))
assert_equal(h, c.send(:m=, a: 1))
assert_equal(h2, c.send(:m=, **h2))
@@ -2663,12 +2290,8 @@ class TestKeywordArguments < Test::Unit::TestCase
attr_writer :m
end
m = c.method(:m=)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- m.call(**{})
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- m.call(**kw)
- end
+ assert_raise(ArgumentError) { m.call(**{}) }
+ assert_raise(ArgumentError) { m.call(**kw) }
assert_equal(h, m.call(**h))
assert_equal(h, m.call(a: 1))
assert_equal(h2, m.call(**h2))
@@ -2691,13 +2314,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([[1], h1], foo.call(1, :a=>1, &->(*args, **kw){[args, kw]}))
assert_equal([1, h1], foo.call(1, :a=>1, &->(*args){args}))
- assert_warn(/Using the last argument as keyword parameters is deprecated/) do
- assert_equal([[1], h1], foo.call(1, {:a=>1}, &->(*args, **kw){[args, kw]}))
- end
+ assert_equal([[1, h1], {}], foo.call(1, {:a=>1}, &->(*args, **kw){[args, kw]}))
assert_equal([1, h1], foo.call(1, {:a=>1}, &->(*args){args}))
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h1, {}], foo.call(:a=>1, &->(arg, **kw){[arg, kw]}))
- end
+ assert_raise(ArgumentError) { foo.call(:a=>1, &->(arg, **kw){[arg, kw]}) }
assert_equal(h1, foo.call(:a=>1, &->(arg){arg}))
[->(){}, ->(arg){}, ->(*args, **kw){}, ->(*args, k: 1){}, ->(*args, k: ){}].each do |pr|
@@ -2724,6 +2343,12 @@ class TestKeywordArguments < Test::Unit::TestCase
end
def test_ruby2_keywords
+ assert_raise(ArgumentError) do
+ Class.new do
+ ruby2_keywords
+ end
+ end
+
c = Class.new do
ruby2_keywords def foo(meth, *args)
send(meth, *args)
@@ -2915,23 +2540,15 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([h1], o.foo_foo_baz(h1, **{}))
assert_equal([[h1], {}], o.foo_bar_after_bmethod(h1, **{}))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do
- assert_equal([[1], h1], o.foo(:bar, 1, h1))
- end
+ assert_equal([[1, h1], {}], o.foo(:bar, 1, h1))
assert_equal([1, h1], o.foo(:baz, 1, h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do
- assert_equal([[1], h1], o.bfoo(:bar, 1, h1))
- end
+ assert_equal([[1, h1], {}], o.bfoo(:bar, 1, h1))
assert_equal([1, h1], o.bfoo(:baz, 1, h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do
- assert_equal([[1], h1], o.store_foo(:bar, 1, h1))
- end
+ assert_equal([[1, h1], {}], o.store_foo(:bar, 1, h1))
assert_equal([1, h1], o.store_foo(:baz, 1, h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do
- assert_equal([[1], h1], o.foo_bar(1, h1))
- end
+ assert_equal([[1, h1], {}], o.foo_bar(1, h1))
assert_equal([1, h1], o.foo_baz(1, h1))
- assert_equal([[1], h1], o.foo_bar_after_bmethod(1, h1))
+ assert_equal([[1, h1], {}], o.foo_bar_after_bmethod(1, h1))
assert_equal([[1, h1, 1], {}], o.foo_mod(:bar, 1, :a=>1))
assert_equal([1, h1, 1], o.foo_mod(:baz, 1, :a=>1))
@@ -2943,10 +2560,10 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([[1, h1, 1], {}], o.foo_bar_mod(1, **h1))
assert_equal([1, h1, 1], o.foo_baz_mod(1, **h1))
- assert_equal([[h1, {}, 1], {}], o.foo_mod(:bar, h1, **{}))
- assert_equal([h1, {}, 1], o.foo_mod(:baz, h1, **{}))
- assert_equal([[h1, {}, 1], {}], o.foo_bar_mod(h1, **{}))
- assert_equal([h1, {}, 1], o.foo_baz_mod(h1, **{}))
+ assert_equal([[h1, 1], {}], o.foo_mod(:bar, h1, **{}))
+ assert_equal([h1, 1], o.foo_mod(:baz, h1, **{}))
+ assert_equal([[h1, 1], {}], o.foo_bar_mod(h1, **{}))
+ assert_equal([h1, 1], o.foo_baz_mod(h1, **{}))
assert_equal([[1, h1, 1], {}], o.foo_mod(:bar, 1, h1))
assert_equal([1, h1, 1], o.foo_mod(:baz, 1, h1))
@@ -2980,43 +2597,29 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([[h1], {}], o.foo_dbar(h1, **{}))
assert_equal([h1], o.foo_dbaz(h1, **{}))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([[1], h1], o.foo(:dbar, 1, h1))
- end
+ assert_equal([[1, h1], {}], o.foo(:dbar, 1, h1))
assert_equal([1, h1], o.foo(:dbaz, 1, h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([[1], h1], o.bfoo(:dbar, 1, h1))
- end
+ assert_equal([[1, h1], {}], o.bfoo(:dbar, 1, h1))
assert_equal([1, h1], o.bfoo(:dbaz, 1, h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([[1], h1], o.store_foo(:dbar, 1, h1))
- end
+ assert_equal([[1, h1], {}], o.store_foo(:dbar, 1, h1))
assert_equal([1, h1], o.store_foo(:dbaz, 1, h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal([[1], h1], o.foo_dbar(1, h1))
- end
+ assert_equal([[1, h1], {}], o.foo_dbar(1, h1))
assert_equal([1, h1], o.foo_dbaz(1, h1))
assert_equal([[1], h1], o.block(1, :a=>1))
assert_equal([[1], h1], o.block(1, **h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal([[1], h1], o.block(1, h1))
- end
+ assert_equal([[1, h1], {}], o.block(1, h1))
assert_equal([[h1], {}], o.block(h1, **{}))
assert_equal([[1], h1], o.cfunc(1, :a=>1))
assert_equal([[1], h1], o.cfunc(1, **h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do
- assert_equal([[1], h1], o.cfunc(1, h1))
- end
+ assert_equal([[1, h1], {}], o.cfunc(1, h1))
assert_equal([[h1], {}], o.cfunc(h1, **{}))
o = mmkw.new
assert_equal([[:b, 1], h1], o.b(1, :a=>1))
assert_equal([[:b, 1], h1], o.b(1, **h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal([[:b, 1], h1], o.b(1, h1))
- end
+ assert_equal([[:b, 1, h1], {}], o.b(1, h1))
assert_equal([[:b, h1], {}], o.b(h1, **{}))
o = mmnokw.new
@@ -3028,9 +2631,7 @@ class TestKeywordArguments < Test::Unit::TestCase
o = implicit_super.new
assert_equal([[1], h1], o.bar(1, :a=>1))
assert_equal([[1], h1], o.bar(1, **h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do
- assert_equal([[1], h1], o.bar(1, h1))
- end
+ assert_equal([[1, h1], {}], o.bar(1, h1))
assert_equal([[h1], {}], o.bar(h1, **{}))
assert_equal([1, h1], o.baz(1, :a=>1))
@@ -3041,9 +2642,7 @@ class TestKeywordArguments < Test::Unit::TestCase
o = explicit_super.new
assert_equal([[1], h1], o.bar(1, :a=>1))
assert_equal([[1], h1], o.bar(1, **h1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do
- assert_equal([[1], h1], o.bar(1, h1))
- end
+ assert_equal([[1, h1], {}], o.bar(1, h1))
assert_equal([[h1], {}], o.bar(h1, **{}))
assert_equal([1, h1], o.baz(1, :a=>1))
@@ -3051,19 +2650,8 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([1, h1], o.baz(1, h1))
assert_equal([h1], o.baz(h1, **{}))
- c.class_eval do
- remove_method(:bar)
- def bar(*args, **kw)
- [args, kw]
- end
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `bar'/m) do
- assert_equal([[1], h1], o.foo(:pass_bar, 1, :a=>1))
- end
-
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `initialize'/m) do
- assert_equal([[1], h1], o.foo(:pass_cfunc, 1, :a=>1))
- end
+ assert_equal([[1, h1], {}], o.foo(:pass_bar, 1, :a=>1))
+ assert_equal([[1, h1], {}], o.foo(:pass_cfunc, 1, :a=>1))
assert_warn(/Skipping set of ruby2_keywords flag for bar \(method accepts keywords or method does not accept argument splat\)/) do
assert_nil(c.send(:ruby2_keywords, :bar))
@@ -3151,25 +2739,14 @@ class TestKeywordArguments < Test::Unit::TestCase
end
assert_equal(c, [c].dig(0, **{}))
assert_equal(c, [c].dig(0, **kw))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do
- assert_equal(h, [c].dig(0, **h))
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do
- assert_equal(h, [c].dig(0, a: 1))
- end
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do
- assert_raise(ArgumentError) { [c].dig(0, **h3) }
- end
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do
- assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) }
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do
- assert_equal(h, [c].dig(0, h))
- end
+ assert_raise(ArgumentError) { [c].dig(0, **h) }
+ assert_raise(ArgumentError) { [c].dig(0, a: 1) }
+ assert_raise(ArgumentError) { [c].dig(0, **h2) }
+ assert_raise(ArgumentError) { [c].dig(0, **h3) }
+ assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) }
+ assert_raise(ArgumentError) { [c].dig(0, h) }
assert_raise(ArgumentError) { [c].dig(0, h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do
- assert_raise(ArgumentError) { [c].dig(0, h3) }
- end
+ assert_raise(ArgumentError) { [c].dig(0, h3) }
c.singleton_class.remove_method(:dig)
def c.dig(arg, **args)
@@ -3189,26 +2766,14 @@ class TestKeywordArguments < Test::Unit::TestCase
end
assert_equal(c, [c].dig(0, **{}))
assert_equal(c, [c].dig(0, **kw))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do
- assert_equal([1, h], [c].dig(0, **h))
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do
- assert_equal([1, h], [c].dig(0, a: 1))
- end
+ assert_equal([h, kw], [c].dig(0, **h))
+ assert_equal([h, kw], [c].dig(0, a: 1))
assert_equal([h2, kw], [c].dig(0, **h2))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do
- assert_equal([h2, h], [c].dig(0, **h3))
- end
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do
- assert_equal([h2, h], [c].dig(0, a: 1, **h2))
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `dig'/m) do
- assert_equal([1, h], [c].dig(0, h))
- end
+ assert_equal([h3, kw], [c].dig(0, **h3))
+ assert_equal([h3, kw], [c].dig(0, a: 1, **h2))
+ assert_equal([h, {}], [c].dig(0, h))
assert_equal([h2, kw], [c].dig(0, h2))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `dig'/m) do
- assert_equal([h2, h], [c].dig(0, h3))
- end
+ assert_equal([h3, kw], [c].dig(0, h3))
assert_equal([h, kw], [c].dig(0, h, **{}))
assert_equal([h2, kw], [c].dig(0, h2, **{}))
assert_equal([h3, kw], [c].dig(0, h3, **{}))
@@ -3261,25 +2826,14 @@ class TestKeywordArguments < Test::Unit::TestCase
end
assert_equal(c, [c].dig(0, **{}))
assert_equal(c, [c].dig(0, **kw))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal(h, [c].dig(0, **h))
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal(h, [c].dig(0, a: 1))
- end
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_raise(ArgumentError) { [c].dig(0, **h3) }
- end
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) }
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal(h, [c].dig(0, h))
- end
+ assert_raise(ArgumentError) { [c].dig(0, **h) }
+ assert_raise(ArgumentError) { [c].dig(0, a: 1) }
+ assert_raise(ArgumentError) { [c].dig(0, **h2) }
+ assert_raise(ArgumentError) { [c].dig(0, **h3) }
+ assert_raise(ArgumentError) { [c].dig(0, a: 1, **h2) }
+ assert_raise(ArgumentError) { [c].dig(0, h) }
assert_raise(ArgumentError) { [c].dig(0, h2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_raise(ArgumentError) { [c].dig(0, h3) }
- end
+ assert_raise(ArgumentError) { [c].dig(0, h3) }
c.singleton_class.remove_method(:method_missing)
def c.method_missing(_, arg, **args)
@@ -3299,26 +2853,14 @@ class TestKeywordArguments < Test::Unit::TestCase
end
assert_equal(c, [c].dig(0, **{}))
assert_equal(c, [c].dig(0, **kw))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal([1, h], [c].dig(0, **h))
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal([1, h], [c].dig(0, a: 1))
- end
+ assert_equal([h, kw], [c].dig(0, **h))
+ assert_equal([h, kw], [c].dig(0, a: 1))
assert_equal([h2, kw], [c].dig(0, **h2))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal([h2, h], [c].dig(0, **h3))
- end
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal([h2, h], [c].dig(0, a: 1, **h2))
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal([1, h], [c].dig(0, h))
- end
+ assert_equal([h3, kw], [c].dig(0, **h3))
+ assert_equal([h3, kw], [c].dig(0, a: 1, **h2))
+ assert_equal([h, kw], [c].dig(0, h))
assert_equal([h2, kw], [c].dig(0, h2))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `method_missing'/m) do
- assert_equal([h2, h], [c].dig(0, h3))
- end
+ assert_equal([h3, kw], [c].dig(0, h3))
assert_equal([h, kw], [c].dig(0, h, **{}))
assert_equal([h2, kw], [c].dig(0, h2, **{}))
assert_equal([h3, kw], [c].dig(0, h3, **{}))
@@ -3351,12 +2893,8 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_raise(ArgumentError) { c.to_enum(:each, a: 1, **h2, &m).size }
m = ->(args){ args }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, c.to_enum(:each, **{}, &m).size)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal(kw, c.to_enum(:each, **kw, &m).size)
- end
+ assert_raise(ArgumentError) { c.to_enum(:each, **{}, &m).size }
+ assert_raise(ArgumentError) { c.to_enum(:each, **kw, &m).size }
assert_equal(kw, c.to_enum(:each, kw, **kw, &m).size)
assert_equal(h, c.to_enum(:each, **h, &m).size)
assert_equal(h, c.to_enum(:each, a: 1, &m).size)
@@ -3372,36 +2910,18 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.to_enum(:each, **h2, &m).size)
assert_equal(h3, c.to_enum(:each, **h3, &m).size)
assert_equal(h3, c.to_enum(:each, a: 1, **h2, &m).size)
- assert_warn(/Using the last argument as keyword parameters is deprecated/m) do
- assert_equal(h, c.to_enum(:each, h, &m).size)
- end
+ assert_raise(ArgumentError) { c.to_enum(:each, h, &m).size }
assert_raise(ArgumentError) { c.to_enum(:each, h2, &m).size }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do
- assert_raise(ArgumentError) { c.to_enum(:each, h3, &m).size }
- end
+ assert_raise(ArgumentError) { c.to_enum(:each, h3, &m).size }
m = ->(arg, **args){ [arg, args] }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- c.to_enum(:each, **{}, &m).size
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- c.to_enum(:each, **kw, &m).size
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h, kw], c.to_enum(:each, **h, &m).size)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h, kw], c.to_enum(:each, a: 1, &m).size)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h2, kw], c.to_enum(:each, **h2, &m).size)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h3, kw], c.to_enum(:each, **h3, &m).size)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/m) do
- assert_equal([h3, kw], c.to_enum(:each, a: 1, **h2, &m).size)
- end
+ assert_raise(ArgumentError) { c.to_enum(:each, **{}, &m).size }
+ assert_raise(ArgumentError) { c.to_enum(:each, **kw, &m).size }
+ assert_raise(ArgumentError) { c.to_enum(:each, **h, &m).size }
+ assert_raise(ArgumentError) { c.to_enum(:each, a: 1, &m).size }
+ assert_raise(ArgumentError) { c.to_enum(:each, **h2, &m).size }
+ assert_raise(ArgumentError) { c.to_enum(:each, **h3, &m).size }
+ assert_raise(ArgumentError) { c.to_enum(:each, a: 1, **h2, &m).size }
assert_equal([h, kw], c.to_enum(:each, h, &m).size)
assert_equal([h2, kw], c.to_enum(:each, h2, &m).size)
assert_equal([h3, kw], c.to_enum(:each, h3, &m).size)
@@ -3414,13 +2934,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([1, h2], c.to_enum(:each, **h2, &m).size)
assert_equal([1, h3], c.to_enum(:each, **h3, &m).size)
assert_equal([1, h3], c.to_enum(:each, a: 1, **h2, &m).size)
- assert_warn(/Using the last argument as keyword parameters is deprecated/m) do
- assert_equal([1, h], c.to_enum(:each, h, &m).size)
- end
+ assert_equal([h, kw], c.to_enum(:each, h, &m).size)
assert_equal([h2, kw], c.to_enum(:each, h2, &m).size)
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do
- assert_equal([h2, h], c.to_enum(:each, h3, &m).size)
- end
+ assert_equal([h3, kw], c.to_enum(:each, h3, &m).size)
end
def test_instance_exec_kwsplat
@@ -3449,12 +2965,8 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) }
m = ->(args) { args }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal(kw, c.instance_exec(**{}, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal(kw, c.instance_exec(**kw, &m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(**{}, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**kw, &m) }
assert_equal(kw, c.instance_exec(kw, **kw, &m))
assert_equal(h, c.instance_exec(**h, &m))
assert_equal(h, c.instance_exec(a: 1, &m))
@@ -3470,36 +2982,18 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.instance_exec(**h2, &m))
assert_equal(h3, c.instance_exec(**h3, &m))
assert_equal(h3, c.instance_exec(a: 1, **h2, &m))
- assert_warn(/Using the last argument as keyword parameters is deprecated/) do
- assert_equal(h, c.instance_exec(h, &m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(h, &m) }
assert_raise(ArgumentError) { c.instance_exec(h2, &m) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do
- assert_raise(ArgumentError) { c.instance_exec(h3, &m) }
- end
+ assert_raise(ArgumentError) { c.instance_exec(h3, &m) }
m = ->(arg, **args) { [arg, args] }
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- c.instance_exec(**{}, &m)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- c.instance_exec(**kw, &m)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, kw], c.instance_exec(**h, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, kw], c.instance_exec(a: 1, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h2, kw], c.instance_exec(**h2, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, kw], c.instance_exec(**h3, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, kw], c.instance_exec(a: 1, **h2, &m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(**{}, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**kw, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**h, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**h2, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**h3, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) }
assert_equal([h, kw], c.instance_exec(h, &m))
assert_equal([h2, kw], c.instance_exec(h2, &m))
assert_equal([h3, kw], c.instance_exec(h3, &m))
@@ -3512,13 +3006,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([1, h2], c.instance_exec(**h2, &m))
assert_equal([1, h3], c.instance_exec(**h3, &m))
assert_equal([1, h3], c.instance_exec(a: 1, **h2, &m))
- assert_warn(/Using the last argument as keyword parameters is deprecated/m) do
- assert_equal([1, h], c.instance_exec(h, &m))
- end
+ assert_equal([h, kw], c.instance_exec(h, &m))
assert_equal([h2, kw], c.instance_exec(h2, &m))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/m) do
- assert_equal([h2, h], c.instance_exec(h3, &m))
- end
+ assert_equal([h3, kw], c.instance_exec(h3, &m))
end
def test_instance_exec_method_kwsplat
@@ -3557,12 +3047,8 @@ class TestKeywordArguments < Test::Unit::TestCase
args
end
m = c.method(:m)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal(kw, c.instance_exec(**{}, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal(kw, c.instance_exec(**kw, &m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(**{}, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**kw, &m) }
assert_equal(kw, c.instance_exec(kw, **kw, &m))
assert_equal(h, c.instance_exec(**h, &m))
assert_equal(h, c.instance_exec(a: 1, &m))
@@ -3582,40 +3068,22 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.instance_exec(**h2, &m))
assert_equal(h3, c.instance_exec(**h3, &m))
assert_equal(h3, c.instance_exec(a: 1, **h2, &m))
- assert_warn(/Using the last argument as keyword parameters is deprecated/) do
- assert_equal(h, c.instance_exec(h, &m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(h, &m) }
assert_raise(ArgumentError) { c.instance_exec(h2, &m) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do
- assert_raise(ArgumentError) { c.instance_exec(h3, &m) }
- end
+ assert_raise(ArgumentError) { c.instance_exec(h3, &m) }
c.singleton_class.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
m = c.method(:m)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- c.instance_exec(**{}, &m)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- c.instance_exec(**kw, &m)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, kw], c.instance_exec(**h, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, kw], c.instance_exec(a: 1, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h2, kw], c.instance_exec(**h2, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, kw], c.instance_exec(**h3, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, kw], c.instance_exec(a: 1, **h2, &m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(**{}, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**kw, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**h, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**h2, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**h3, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) }
assert_equal([h, kw], c.instance_exec(h, &m))
assert_equal([h2, kw], c.instance_exec(h2, &m))
assert_equal([h3, kw], c.instance_exec(h3, &m))
@@ -3632,13 +3100,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([1, h2], c.instance_exec(**h2, &m))
assert_equal([1, h3], c.instance_exec(**h3, &m))
assert_equal([1, h3], c.instance_exec(a: 1, **h2, &m))
- assert_warn(/Using the last argument as keyword parameters is deprecated/m) do
- assert_equal([1, h], c.instance_exec(h, &m))
- end
+ assert_equal([h, kw], c.instance_exec(h, &m))
assert_equal([h2, kw], c.instance_exec(h2, &m))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do
- assert_equal([h2, h], c.instance_exec(h3, &m))
- end
+ assert_equal([h3, kw], c.instance_exec(h3, &m))
end
def test_instance_exec_define_method_kwsplat
@@ -3677,12 +3141,8 @@ class TestKeywordArguments < Test::Unit::TestCase
args
end
m = c.method(:m)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal(kw, c.instance_exec(**{}, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal(kw, c.instance_exec(**kw, &m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(**{}, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**kw, &m) }
assert_equal(kw, c.instance_exec(kw, **kw, &m))
assert_equal(h, c.instance_exec(**h, &m))
assert_equal(h, c.instance_exec(a: 1, &m))
@@ -3702,40 +3162,22 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.instance_exec(**h2, &m))
assert_equal(h3, c.instance_exec(**h3, &m))
assert_equal(h3, c.instance_exec(a: 1, **h2, &m))
- assert_warn(/Using the last argument as keyword parameters is deprecated/) do
- assert_equal(h, c.instance_exec(h, &m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(h, &m) }
assert_raise(ArgumentError) { c.instance_exec(h2, &m) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do
- assert_raise(ArgumentError) { c.instance_exec(h3, &m) }
- end
+ assert_raise(ArgumentError) { c.instance_exec(h3, &m) }
c.singleton_class.remove_method(:m)
c.define_singleton_method(:m) do |arg, **args|
[arg, args]
end
m = c.method(:m)
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- c.instance_exec(**{}, &m)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- c.instance_exec(**kw, &m)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, kw], c.instance_exec(**h, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, kw], c.instance_exec(a: 1, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h2, kw], c.instance_exec(**h2, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, kw], c.instance_exec(**h3, &m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, kw], c.instance_exec(a: 1, **h2, &m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(**{}, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**kw, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**h, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(a: 1, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**h2, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(**h3, &m) }
+ assert_raise(ArgumentError) { c.instance_exec(a: 1, **h2, &m) }
assert_equal([h, kw], c.instance_exec(h, &m))
assert_equal([h2, kw], c.instance_exec(h2, &m))
assert_equal([h3, kw], c.instance_exec(h3, &m))
@@ -3752,13 +3194,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([1, h2], c.instance_exec(**h2, &m))
assert_equal([1, h3], c.instance_exec(**h3, &m))
assert_equal([1, h3], c.instance_exec(a: 1, **h2, &m))
- assert_warn(/Using the last argument as keyword parameters is deprecated/m) do
- assert_equal([1, h], c.instance_exec(h, &m))
- end
+ assert_equal([h, kw], c.instance_exec(h, &m))
assert_equal([h2, kw], c.instance_exec(h2, &m))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do
- assert_equal([h2, h], c.instance_exec(h3, &m))
- end
+ assert_equal([h3, kw], c.instance_exec(h3, &m))
end
def test_instance_exec_sym_proc_kwsplat
@@ -3794,12 +3232,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.m(args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal(kw, c.instance_exec(c, **{}, &:m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal(kw, c.instance_exec(c, **kw, &:m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(c, **{}, &:m) }
+ assert_raise(ArgumentError) { c.instance_exec(c, **kw, &:m) }
assert_equal(kw, c.instance_exec(c, kw, **kw, &:m))
assert_equal(h, c.instance_exec(c, **h, &:m))
assert_equal(h, c.instance_exec(c, a: 1, &:m))
@@ -3818,39 +3252,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(h2, c.instance_exec(c, **h2, &:m))
assert_equal(h3, c.instance_exec(c, **h3, &:m))
assert_equal(h3, c.instance_exec(c, a: 1, **h2, &:m))
- assert_warn(/Using the last argument as keyword parameters is deprecated/) do
- assert_equal(h, c.instance_exec(c, h, &:m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(c, h, &:m) }
assert_raise(ArgumentError) { c.instance_exec(c, h2, &:m) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do
- assert_raise(ArgumentError) { c.instance_exec(c, h3, &:m) }
- end
+ assert_raise(ArgumentError) { c.instance_exec(c, h3, &:m) }
c.singleton_class.remove_method(:m)
def c.m(arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- c.instance_exec(c, **{}, &:m)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- c.instance_exec(c, **kw, &:m)
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, kw], c.instance_exec(c, **h, &:m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h, kw], c.instance_exec(c, a: 1, &:m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h2, kw], c.instance_exec(c, **h2, &:m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, kw], c.instance_exec(c, **h3, &:m))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated/) do
- assert_equal([h3, kw], c.instance_exec(c, a: 1, **h2, &:m))
- end
+ assert_raise(ArgumentError) { c.instance_exec(c, **{}, &:m) }
+ assert_raise(ArgumentError) { c.instance_exec(c, **kw, &:m) }
+ assert_raise(ArgumentError) { c.instance_exec(c, **h, &:m) }
+ assert_raise(ArgumentError) { c.instance_exec(c, a: 1, &:m) }
+ assert_raise(ArgumentError) { c.instance_exec(c, **h2, &:m) }
+ assert_raise(ArgumentError) { c.instance_exec(c, **h3, &:m) }
+ assert_raise(ArgumentError) { c.instance_exec(c, a: 1, **h2, &:m) }
assert_equal([h, kw], c.instance_exec(c, h, &:m))
assert_equal([h2, kw], c.instance_exec(c, h2, &:m))
assert_equal([h3, kw], c.instance_exec(c, h3, &:m))
@@ -3866,13 +3282,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([1, h2], c.instance_exec(c, **h2, &:m))
assert_equal([1, h3], c.instance_exec(c, **h3, &:m))
assert_equal([1, h3], c.instance_exec(c, a: 1, **h2, &:m))
- assert_warn(/Using the last argument as keyword parameters is deprecated/m) do
- assert_equal([1, h], c.instance_exec(c, h, &:m))
- end
+ assert_equal([h, kw], c.instance_exec(c, h, &:m))
assert_equal([h2, kw], c.instance_exec(c, h2, &:m))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated/) do
- assert_equal([h2, h], c.instance_exec(c, h3, &:m))
- end
+ assert_equal([h3, kw], c.instance_exec(c, h3, &:m))
end
def test_rb_yield_block_kwsplat
@@ -3911,12 +3323,8 @@ class TestKeywordArguments < Test::Unit::TestCase
def c.c(args)
args
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do
- assert_equal(kw, c.m(:c, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do
- assert_equal(kw, c.m(:c, **kw))
- end
+ assert_raise(ArgumentError) { c.m(:c, **{}) }
+ assert_raise(ArgumentError) { c.m(:c, **kw) }
assert_equal(kw, c.m(:c, kw, **kw))
assert_equal(h, c.m(:c, **h))
assert_equal(h, c.m(:c, a: 1))
@@ -3936,39 +3344,21 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([h2, h2], c.m(:c, **h2, &m))
assert_equal([h3, h3], c.m(:c, **h3, &m))
assert_equal([h3, h3], c.m(:c, a: 1, **h2, &m))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `c'/m) do
- assert_equal([h, h], c.m(:c, h, &m))
- end
+ assert_raise(ArgumentError) { c.m(:c, h, &m) }
assert_raise(ArgumentError) { c.m(:c, h2, &m) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `c'/m) do
- assert_raise(ArgumentError) { c.m(:c, h3, &m) }
- end
+ assert_raise(ArgumentError) { c.m(:c, h3, &m) }
c.singleton_class.remove_method(:c)
def c.c(arg, **args)
[arg, args]
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do
- assert_equal([kw, kw], c.m(:c, **{}))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do
- assert_equal([kw, kw], c.m(:c, **kw))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do
- assert_equal([h, kw], c.m(:c, **h))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do
- assert_equal([h, kw], c.m(:c, a: 1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do
- assert_equal([h2, kw], c.m(:c, **h2))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do
- assert_equal([h3, kw], c.m(:c, **h3))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `c'/m) do
- assert_equal([h3, kw], c.m(:c, a: 1, **h2))
- end
+ assert_raise(ArgumentError) { c.m(:c, **{}, &m) }
+ assert_raise(ArgumentError) { c.m(:c, **kw, &m) }
+ assert_raise(ArgumentError) { c.m(:c, **h, &m) }
+ assert_raise(ArgumentError) { c.m(:c, a: 1, &m) }
+ assert_raise(ArgumentError) { c.m(:c, **h2, &m) }
+ assert_raise(ArgumentError) { c.m(:c, **h3, &m) }
+ assert_raise(ArgumentError) { c.m(:c, a: 1, **h2, &m) }
assert_equal([h, kw], c.m(:c, h))
assert_equal([h2, kw], c.m(:c, h2))
assert_equal([h3, kw], c.m(:c, h3))
@@ -3984,13 +3374,9 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([1, h2], c.m(:c, **h2))
assert_equal([1, h3], c.m(:c, **h3))
assert_equal([1, h3], c.m(:c, a: 1, **h2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `c'/m) do
- assert_equal([1, h], c.m(:c, h))
- end
+ assert_equal([h, kw], c.m(:c, h))
assert_equal([h2, kw], c.m(:c, h2))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `c'/m) do
- assert_equal([h2, h], c.m(:c, h3))
- end
+ assert_equal([h3, kw], c.m(:c, h3))
end
def p1
@@ -4118,25 +3504,21 @@ class TestKeywordArguments < Test::Unit::TestCase
def test_rest_keyrest
bug7665 = '[ruby-core:51278]'
bug8463 = '[ruby-core:55203] [Bug #8463]'
- expect = [*%w[foo bar], {zzz: 42}]
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `rest_keyrest'/m) do
- assert_equal(expect, rest_keyrest(*expect), bug7665)
- end
+ a = [*%w[foo bar], {zzz: 42}]
+ splat_expect = a + [{}]
+ nonsplat_expect = [a, {}]
+ assert_equal(splat_expect, rest_keyrest(*a), bug7665)
+ assert_equal(nonsplat_expect, rest_keyrest(a), bug7665)
+
pr = proc {|*args, **opt| next *args, opt}
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(expect, pr.call(*expect), bug7665)
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(expect, pr.call(expect), bug8463)
- end
+ assert_equal(splat_expect, pr.call(*a), bug7665)
+ assert_equal(nonsplat_expect, pr.call(a), bug8463)
+
pr = proc {|a, *b, **opt| next a, *b, opt}
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(expect, pr.call(expect), bug8463)
- end
+ assert_equal(splat_expect, pr.call(a), bug8463)
+
pr = proc {|a, **opt| next a, opt}
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(expect.values_at(0, -1), pr.call(expect), bug8463)
- end
+ assert_equal(splat_expect.values_at(0, -1), pr.call(splat_expect), bug8463)
end
def req_plus_keyword(x, **h)
@@ -4151,16 +3533,10 @@ class TestKeywordArguments < Test::Unit::TestCase
[a, h]
end
- def test_keyword_split
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `req_plus_keyword'/m) do
- assert_equal([{:a=>1}, {}], req_plus_keyword(:a=>1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `req_plus_keyword'/m) do
- assert_equal([{"a"=>1}, {}], req_plus_keyword("a"=>1))
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `req_plus_keyword'/m) do
- assert_equal([{"a"=>1, :a=>1}, {}], req_plus_keyword("a"=>1, :a=>1))
- end
+ def test_keyword_no_split
+ assert_raise(ArgumentError) { req_plus_keyword(:a=>1) }
+ assert_raise(ArgumentError) { req_plus_keyword("a"=>1) }
+ assert_raise(ArgumentError) { req_plus_keyword("a"=>1, :a=>1) }
assert_equal([{:a=>1}, {}], req_plus_keyword({:a=>1}))
assert_equal([{"a"=>1}, {}], req_plus_keyword({"a"=>1}))
assert_equal([{"a"=>1, :a=>1}, {}], req_plus_keyword({"a"=>1, :a=>1}))
@@ -4168,24 +3544,16 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal([1, {:a=>1}], opt_plus_keyword(:a=>1))
assert_equal([1, {"a"=>1}], opt_plus_keyword("a"=>1))
assert_equal([1, {"a"=>1, :a=>1}], opt_plus_keyword("a"=>1, :a=>1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `opt_plus_keyword'/m) do
- assert_equal([1, {:a=>1}], opt_plus_keyword({:a=>1}))
- end
+ assert_equal([{:a=>1}, {}], opt_plus_keyword({:a=>1}))
assert_equal([{"a"=>1}, {}], opt_plus_keyword({"a"=>1}))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `opt_plus_keyword'/m) do
- assert_equal([{"a"=>1}, {:a=>1}], opt_plus_keyword({"a"=>1, :a=>1}))
- end
+ assert_equal([{"a"=>1, :a=>1}, {}], opt_plus_keyword({"a"=>1, :a=>1}))
assert_equal([[], {:a=>1}], splat_plus_keyword(:a=>1))
assert_equal([[], {"a"=>1}], splat_plus_keyword("a"=>1))
assert_equal([[], {"a"=>1, :a=>1}], splat_plus_keyword("a"=>1, :a=>1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `splat_plus_keyword'/m) do
- assert_equal([[], {:a=>1}], splat_plus_keyword({:a=>1}))
- end
+ assert_equal([[{:a=>1}], {}], splat_plus_keyword({:a=>1}))
assert_equal([[{"a"=>1}], {}], splat_plus_keyword({"a"=>1}))
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `splat_plus_keyword'/m) do
- assert_equal([[{"a"=>1}], {:a=>1}], splat_plus_keyword({"a"=>1, :a=>1}))
- end
+ assert_equal([[{"a"=>1, :a=>1}], {}], splat_plus_keyword({"a"=>1, :a=>1}))
end
def test_bare_kwrest
@@ -4364,15 +3732,12 @@ class TestKeywordArguments < Test::Unit::TestCase
end
def test_precedence_of_keyword_arguments_with_post_argument
- bug8993 = '[ruby-core:57706] [Bug #8993]'
a = Class.new do
def foo(a, b, c=1, *d, e, f:2, **g)
[a, b, c, d, e, f, g]
end
end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `foo'/m) do
- assert_equal([1, 2, 1, [], {:f=>5}, 2, {}], a.new.foo(1, 2, f:5), bug8993)
- end
+ assert_raise(ArgumentError) { a.new.foo(1, 2, f:5) }
end
def test_splat_keyword_nondestructive
@@ -4399,18 +3764,12 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal({a: 1, b: 2}, m1(**o, **o2) {|x| break x}, bug9898)
end
- def test_implicit_hash_conversion
- bug10016 = '[ruby-core:63593] [Bug #10016]'
-
+ def test_no_implicit_hash_conversion
o = Object.new
def o.to_hash() { k: 9 } end
assert_equal([1, 42, [], o, :key, {}, nil], f9(1, o))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m1'/m) do
- assert_equal([1, 9], m1(1, o) {|a, k: 0| break [a, k]}, bug10016)
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `m1'/m) do
- assert_equal([1, 9], m1(1, o, &->(a, k: 0) {break [a, k]}), bug10016)
- end
+ assert_equal([1, 0], m1(1, o) {|a, k: 0| break [a, k]})
+ assert_raise(ArgumentError) { m1(1, o, &->(a, k: 0) {break [a, k]}) }
end
def test_splat_hash
@@ -4421,7 +3780,7 @@ class TestKeywordArguments < Test::Unit::TestCase
def m.f3(**a) a; end
def m.f4(*a) a; end
o = {a: 1}
- assert_raise_with_message(ArgumentError, /unknown keyword: :a/) {
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given 1, expected 0\)/) {
m.f(**o)
}
o = {}
@@ -4529,7 +3888,7 @@ class TestKeywordArguments < Test::Unit::TestCase
def test_nonsymbol_key
result = m(["a" => 10]) { |a = nil, **b| [a, b] }
- assert_equal([{"a" => 10}, {}], result)
+ assert_equal([[{"a" => 10}], {}], result)
end
def method_for_test_to_hash_call_during_setup_complex_parameters k1:, k2:, **rest_kw
@@ -4714,22 +4073,12 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_raise(ArgumentError) { c.call(**h3, &:m) }
assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) }
- redef = -> do
- c.singleton_class.remove_method(:m)
- eval <<-END
- def c.m(args)
- args
- end
- END
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.call(**{}, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal(kw, c.call(**kw, &:m))
+ c.singleton_class.remove_method(:m)
+ def c.m(args)
+ args
end
+ assert_raise(ArgumentError) { c.call(**{}, &:m) }
+ assert_raise(ArgumentError) { c.call(**kw, &:m) }
assert_equal(h, c.call(**h, &:m))
assert_equal(h, c.call(a: 1, &:m))
assert_equal(h2, c.call(**h2, &:m))
@@ -4747,50 +4096,21 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_equal(h2, c.call(**h2, &:m))
assert_equal(h3, c.call(**h3, &:m))
assert_equal(h3, c.call(a: 1, **h2, &:m))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(h, c.call(h, &:m))
- end
+ assert_raise(ArgumentError) { c.call(h, &:m) }
assert_raise(ArgumentError) { c.call(h2, &:m) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `call'/m) do
- assert_raise(ArgumentError) { c.call(h3, &:m) }
- end
+ assert_raise(ArgumentError) { c.call(h3, &:m) }
- redef = -> do
- c.singleton_class.remove_method(:m)
- eval <<-END
- def c.m(arg, **args)
- [arg, args]
- end
- END
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], c.call(**{}, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([kw, kw], c.call(**kw, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.call(**h, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h, kw], c.call(a: 1, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h2, kw], c.call(**h2, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.call(**h3, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `m'/m) do
- assert_equal([h3, kw], c.call(a: 1, **h2, &:m))
+ c.singleton_class.remove_method(:m)
+ def c.m(arg, **args)
+ [arg, args]
end
+ assert_raise(ArgumentError) { c.call(**{}, &:m) }
+ assert_raise(ArgumentError) { c.call(**kw, &:m) }
+ assert_raise(ArgumentError) { c.call(**h, &:m) }
+ assert_raise(ArgumentError) { c.call(a: 1, &:m) }
+ assert_raise(ArgumentError) { c.call(**h2, &:m) }
+ assert_raise(ArgumentError) { c.call(**h3, &:m) }
+ assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) }
c.singleton_class.remove_method(:m)
def c.m(arg=1, **args)
@@ -4834,22 +4154,12 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_raise(ArgumentError) { c.call(**h3, &:m) }
assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m) }
- redef = -> do
- c.singleton_class.remove_method(:method_missing)
- eval <<-END
- def c.method_missing(_, args)
- args
- end
- END
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.call(**{}, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.call(**kw, &:m))
+ c.singleton_class.remove_method(:method_missing)
+ def c.method_missing(_, args)
+ args
end
+ assert_raise(ArgumentError) { c.call(**{}, &:m) }
+ assert_raise(ArgumentError) { c.call(**kw, &:m) }
assert_equal(h, c.call(**h, &:m))
assert_equal(h, c.call(a: 1, &:m))
assert_equal(h2, c.call(**h2, &:m))
@@ -4867,50 +4177,21 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_equal(h2, c.call(**h2, &:m))
assert_equal(h3, c.call(**h3, &:m))
assert_equal(h3, c.call(a: 1, **h2, &:m))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(h, c.call(h, &:m2))
- end
+ assert_raise(ArgumentError) { c.call(h, &:m2) }
assert_raise(ArgumentError) { c.call(h2, &:m2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `call'/m) do
- assert_raise(ArgumentError) { c.call(h3, &:m2) }
- end
+ assert_raise(ArgumentError) { c.call(h3, &:m2) }
- redef = -> do
- c.singleton_class.remove_method(:method_missing)
- eval <<-END
- def c.method_missing(_, arg, **args)
- [arg, args]
- end
- END
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.call(**{}, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.call(**kw, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.call(**h, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.call(a: 1, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h2, kw], c.call(**h2, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.call(**h3, &:m))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.call(a: 1, **h2, &:m))
+ c.singleton_class.remove_method(:method_missing)
+ def c.method_missing(_, arg, **args)
+ [arg, args]
end
+ assert_raise(ArgumentError) { c.call(**{}, &:m2) }
+ assert_raise(ArgumentError) { c.call(**kw, &:m2) }
+ assert_raise(ArgumentError) { c.call(**h, &:m2) }
+ assert_raise(ArgumentError) { c.call(a: 1, &:m2) }
+ assert_raise(ArgumentError) { c.call(**h2, &:m2) }
+ assert_raise(ArgumentError) { c.call(**h3, &:m2) }
+ assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m2) }
c.singleton_class.remove_method(:method_missing)
def c.method_missing(_, arg=1, **args)
@@ -4954,22 +4235,12 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_raise(ArgumentError) { c.call(**h3, &:m2) }
assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m2) }
- redef = -> do
- c.singleton_class.remove_method(:method_missing)
- eval <<-END
- def c.method_missing(_, args)
- args
- end
- END
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.call(**{}, &:m2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal(kw, c.call(**kw, &:m2))
+ c.singleton_class.remove_method(:method_missing)
+ def c.method_missing(_, args)
+ args
end
+ assert_raise(ArgumentError) { c.call(**{}, &:m2) }
+ assert_raise(ArgumentError) { c.call(**kw, &:m2) }
assert_equal(h, c.call(**h, &:m2))
assert_equal(h, c.call(a: 1, &:m2))
assert_equal(h2, c.call(**h2, &:m2))
@@ -4987,50 +4258,21 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_equal(h2, c.call(**h2, &:m2))
assert_equal(h3, c.call(**h3, &:m2))
assert_equal(h3, c.call(a: 1, **h2, &:m2))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(h, c.call(h, &:m2))
- end
+ assert_raise(ArgumentError) { c.call(h, &:m2) }
assert_raise(ArgumentError) { c.call(h2, &:m2) }
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `call'/m) do
- assert_raise(ArgumentError) { c.call(h3, &:m2) }
- end
+ assert_raise(ArgumentError) { c.call(h3, &:m2) }
- redef = -> do
- c.singleton_class.remove_method(:method_missing)
- eval <<-END
- def c.method_missing(_, arg, **args)
- [arg, args]
- end
- END
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.call(**{}, &:m2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([kw, kw], c.call(**kw, &:m2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.call(**h, &:m2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h, kw], c.call(a: 1, &:m2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h2, kw], c.call(**h2, &:m2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.call(**h3, &:m2))
- end
- redef[]
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `method_missing'/m) do
- assert_equal([h3, kw], c.call(a: 1, **h2, &:m2))
+ c.singleton_class.remove_method(:method_missing)
+ def c.method_missing(_, arg, **args)
+ [arg, args]
end
+ assert_raise(ArgumentError) { c.call(**{}, &:m2) }
+ assert_raise(ArgumentError) { c.call(**kw, &:m2) }
+ assert_raise(ArgumentError) { c.call(**h, &:m2) }
+ assert_raise(ArgumentError) { c.call(a: 1, &:m2) }
+ assert_raise(ArgumentError) { c.call(**h2, &:m2) }
+ assert_raise(ArgumentError) { c.call(**h3, &:m2) }
+ assert_raise(ArgumentError) { c.call(a: 1, **h2, &:m2) }
c.singleton_class.remove_method(:method_missing)
def c.method_missing(_, arg=1, **args)
@@ -5066,18 +4308,4 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_raise(TypeError, bug16603) { p(**42) }
assert_raise(TypeError, bug16603) { p(k:1, **42) }
end
-
- def test_ruby2_keywords_hash_empty_kw_splat
- def self.foo(*a) a.last end
- singleton_class.send(:ruby2_keywords, :foo)
- bug16642 = '[ruby-core:97203] [Bug #16642]'
-
- res = foo(**{})
- assert_equal({}, res, bug16642)
- assert_equal(false, res.frozen?, bug16642)
-
- res = foo(*[], **{})
- assert_equal({}, res, bug16642)
- assert_equal(false, res.frozen?, bug16642)
- end
end
diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb
index 03b501a6c9..8e460475c0 100644
--- a/test/ruby/test_lambda.rb
+++ b/test/ruby/test_lambda.rb
@@ -83,15 +83,21 @@ class TestLambdaParameters < Test::Unit::TestCase
end
def test_create_non_lambda_for_proc_one_level
+ prev_warning, Warning[:deprecated] = Warning[:deprecated], false
f = pass_along {}
refute_predicate(f, :lambda?, '[Bug #15620]')
assert_nothing_raised(ArgumentError) { f.call(:extra_arg) }
+ ensure
+ Warning[:deprecated] = prev_warning
end
def test_create_non_lambda_for_proc_two_levels
+ prev_warning, Warning[:deprecated] = Warning[:deprecated], false
f = pass_along2 {}
refute_predicate(f, :lambda?, '[Bug #15620]')
assert_nothing_raised(ArgumentError) { f.call(:extra_arg) }
+ ensure
+ Warning[:deprecated] = prev_warning
end
def test_instance_exec
diff --git a/test/ruby/test_lazy_enumerator.rb b/test/ruby/test_lazy_enumerator.rb
index 6e5c1714a5..2116d0ee31 100644
--- a/test/ruby/test_lazy_enumerator.rb
+++ b/test/ruby/test_lazy_enumerator.rb
@@ -160,6 +160,10 @@ class TestLazyEnumerator < Test::Unit::TestCase
assert_equal([{?a=>97}, {?b=>98}, {?c=>99}], [?a, ?b, ?c].lazy.flat_map {|x| {x=>x.ord}}.force)
end
+ def test_flat_map_take
+ assert_equal([1,2]*3, [[1,2]].cycle.lazy.take(3).flat_map {|x| x}.to_a)
+ end
+
def test_reject
a = Step.new(1..6)
assert_equal(4, a.reject {|x| x < 4}.first)
@@ -678,4 +682,8 @@ EOS
ary = (0..Float::INFINITY).lazy.with_index.take(2).to_a
assert_equal([[0, 0], [1, 1]], ary)
end
+
+ def test_with_index_size
+ assert_equal(3, Enumerator::Lazy.new([1, 2, 3], 3){|y, v| y << v}.with_index.size)
+ end
end
diff --git a/test/ruby/test_literal.rb b/test/ruby/test_literal.rb
index 7f4a329c4a..679af20bb9 100644
--- a/test/ruby/test_literal.rb
+++ b/test/ruby/test_literal.rb
@@ -187,14 +187,14 @@ class TestRubyLiteral < Test::Unit::TestCase
if defined?(RubyVM::InstructionSequence.compile_option) and
RubyVM::InstructionSequence.compile_option.key?(:debug_frozen_string_literal)
def test_debug_frozen_string
- src = 'n = 1; _="foo#{n ? "-#{n}" : ""}"'; f = "test.rb"; n = 1
+ src = '_="foo-1"'; f = "test.rb"; n = 1
opt = {frozen_string_literal: true, debug_frozen_string_literal: true}
str = RubyVM::InstructionSequence.compile(src, f, f, n, **opt).eval
assert_equal("foo-1", str)
assert_predicate(str, :frozen?)
assert_raise_with_message(FrozenError, /created at #{Regexp.quote(f)}:#{n}/) {
str << "x"
- }
+ } unless ENV['RUBY_ISEQ_DUMP_DEBUG']
end
def test_debug_frozen_string_in_array_literal
diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb
index 6c7d0e6bae..3f28d55ac1 100644
--- a/test/ruby/test_m17n.rb
+++ b/test/ruby/test_m17n.rb
@@ -310,6 +310,7 @@ class TestM17N < Test::Unit::TestCase
def o.inspect
"abc".encode(Encoding.default_external)
end
+
assert_equal '[abc]', [o].inspect
Encoding.default_external = Encoding::US_ASCII
@@ -1324,10 +1325,14 @@ class TestM17N < Test::Unit::TestCase
end
def test_env
- locale_encoding = Encoding.find("locale")
+ if RUBY_PLATFORM =~ /bccwin|mswin|mingw/
+ env_encoding = Encoding::UTF_8
+ else
+ env_encoding = Encoding.find("locale")
+ end
ENV.each {|k, v|
- assert_equal(locale_encoding, k.encoding, k)
- assert_equal(locale_encoding, v.encoding, v)
+ assert_equal(env_encoding, k.encoding, k)
+ assert_equal(env_encoding, v.encoding, v)
}
end
diff --git a/test/ruby/test_m17n_comb.rb b/test/ruby/test_m17n_comb.rb
index cfb8bff882..49141790f0 100644
--- a/test/ruby/test_m17n_comb.rb
+++ b/test/ruby/test_m17n_comb.rb
@@ -751,8 +751,14 @@ class TestM17NComb < Test::Unit::TestCase
# glibc 2.16 or later denies salt contained other than [0-9A-Za-z./] #7312
# we use this check to test strict and non-strict behavior separately #11045
strict_crypt = if defined? Etc::CS_GNU_LIBC_VERSION
- glibcver = Etc.confstr(Etc::CS_GNU_LIBC_VERSION).scan(/\d+/).map(&:to_i)
- (glibcver <=> [2, 16]) >= 0
+ begin
+ confstr = Etc.confstr(Etc::CS_GNU_LIBC_VERSION)
+ rescue Errno::EINVAL
+ false
+ else
+ glibcver = confstr.scan(/\d+/).map(&:to_i)
+ (glibcver <=> [2, 16]) >= 0
+ end
end
def test_str_crypt
diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb
index 90899fa83f..ae6e8708ee 100644
--- a/test/ruby/test_marshal.rb
+++ b/test/ruby/test_marshal.rb
@@ -8,7 +8,6 @@ class TestMarshal < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -157,20 +156,29 @@ class TestMarshal < Test::Unit::TestCase
end
def test_change_class_name
+ self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3)
eval("class C3; def _dump(s); 'foo'; end; end")
m = Marshal.dump(C3.new)
assert_raise(TypeError) { Marshal.load(m) }
+ self.class.__send__(:remove_const, :C3)
eval("C3 = nil")
assert_raise(TypeError) { Marshal.load(m) }
+ ensure
+ self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3)
end
def test_change_struct
+ self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3)
eval("C3 = Struct.new(:foo, :bar)")
m = Marshal.dump(C3.new("FOO", "BAR"))
+ self.class.__send__(:remove_const, :C3)
eval("C3 = Struct.new(:foo)")
assert_raise(TypeError) { Marshal.load(m) }
+ self.class.__send__(:remove_const, :C3)
eval("C3 = Struct.new(:foo, :baz)")
assert_raise(TypeError) { Marshal.load(m) }
+ ensure
+ self.class.__send__(:remove_const, :C3) if self.class.const_defined?(:C3)
end
class C4
@@ -542,7 +550,7 @@ class TestMarshal < Test::Unit::TestCase
end
class TestForRespondToFalse
- def respond_to?(a)
+ def respond_to?(a, priv = false)
false
end
end
@@ -570,7 +578,7 @@ class TestMarshal < Test::Unit::TestCase
end
def test_continuation
- require "continuation"
+ EnvUtil.suppress_warning {require "continuation"}
c = Bug9523.new
assert_raise_with_message(RuntimeError, /Marshal\.dump reentered at marshal_dump/) do
Marshal.dump(c)
@@ -596,7 +604,8 @@ class TestMarshal < Test::Unit::TestCase
end
def test_unloadable_data
- c = eval("class Unloadable\u{23F0 23F3}<Time;;self;end")
+ name = "Unloadable\u{23F0 23F3}"
+ c = eval("class #{name} < Time;;self;end")
c.class_eval {
alias _dump_data _dump
undef _dump
@@ -605,10 +614,16 @@ class TestMarshal < Test::Unit::TestCase
assert_raise_with_message(TypeError, /Unloadable\u{23F0 23F3}/) {
Marshal.load(d)
}
+
+ # cleanup
+ self.class.class_eval do
+ remove_const name
+ end
end
def test_unloadable_userdef
- c = eval("class Userdef\u{23F0 23F3}<Time;self;end")
+ name = "Userdef\u{23F0 23F3}"
+ c = eval("class #{name} < Time;self;end")
class << c
undef _load
end
@@ -616,6 +631,11 @@ class TestMarshal < Test::Unit::TestCase
assert_raise_with_message(TypeError, /Userdef\u{23F0 23F3}/) {
Marshal.load(d)
}
+
+ # cleanup
+ self.class.class_eval do
+ remove_const name
+ end
end
def test_unloadable_usrmarshal
@@ -631,15 +651,16 @@ class TestMarshal < Test::Unit::TestCase
def test_no_internal_ids
opt = %w[--disable=gems]
- args = [opt, 'Marshal.dump("",STDOUT)', true, true, encoding: Encoding::ASCII_8BIT]
- out, err, status = EnvUtil.invoke_ruby(*args)
+ args = [opt, 'Marshal.dump("",STDOUT)', true, true]
+ kw = {encoding: Encoding::ASCII_8BIT}
+ out, err, status = EnvUtil.invoke_ruby(*args, **kw)
assert_empty(err)
assert_predicate(status, :success?)
expected = out
opt << "--enable=frozen-string-literal"
opt << "--debug=frozen-string-literal"
- out, err, status = EnvUtil.invoke_ruby(*args)
+ out, err, status = EnvUtil.invoke_ruby(*args, **kw)
assert_empty(err)
assert_predicate(status, :success?)
assert_equal(expected, out)
@@ -781,7 +802,64 @@ class TestMarshal < Test::Unit::TestCase
def test_marshal_with_ruby2_keywords_hash
flagged_hash = ruby2_keywords_hash(key: 42)
- hash = Marshal.load(Marshal.dump(flagged_hash))
+ data = Marshal.dump(flagged_hash)
+ hash = Marshal.load(data)
assert_equal(42, ruby2_keywords_test(*[hash]))
+
+ hash2 = Marshal.load(data.sub(/\x06K(?=T\z)/, "\x08KEY"))
+ assert_raise(ArgumentError, /\(given 1, expected 0\)/) {
+ ruby2_keywords_test(*[hash2])
+ }
+ end
+
+ def test_invalid_byte_sequence_symbol
+ data = Marshal.dump(:K)
+ data = data.sub(/:\x06K/, "I\\&\x06:\x0dencoding\"\x0dUTF-16LE")
+ assert_raise(ArgumentError, /UTF-16LE: "\\x4B"/) {
+ Marshal.load(data)
+ }
+ end
+
+ def exception_test
+ raise
+ end
+
+ def test_marshal_exception
+ begin
+ exception_test
+ rescue => e
+ e2 = Marshal.load(Marshal.dump(e))
+ assert_equal(e.message, e2.message)
+ assert_equal(e.backtrace, e2.backtrace)
+ assert_nil(e2.backtrace_locations) # temporal
+ end
+ end
+
+ def nameerror_test
+ unknown_method
+ end
+
+ def test_marshal_nameerror
+ begin
+ nameerror_test
+ rescue NameError => e
+ e2 = Marshal.load(Marshal.dump(e))
+ assert_equal(e.message, e2.message)
+ assert_equal(e.name, e2.name)
+ assert_equal(e.backtrace, e2.backtrace)
+ assert_nil(e2.backtrace_locations) # temporal
+ end
+ end
+
+ class TestMarshalFreezeProc < Test::Unit::TestCase
+ include MarshalTestLib
+
+ def encode(o)
+ Marshal.dump(o)
+ end
+
+ def decode(s)
+ Marshal.load(s, :freeze.to_proc)
+ end
end
end
diff --git a/test/ruby/test_memory_view.rb b/test/ruby/test_memory_view.rb
new file mode 100644
index 0000000000..5a39084d18
--- /dev/null
+++ b/test/ruby/test_memory_view.rb
@@ -0,0 +1,341 @@
+require "-test-/memory_view"
+require "rbconfig/sizeof"
+
+class TestMemoryView < Test::Unit::TestCase
+ NATIVE_ENDIAN = MemoryViewTestUtils::NATIVE_ENDIAN
+ LITTLE_ENDIAN = :little_endian
+ BIG_ENDIAN = :big_endian
+
+ %I(SHORT INT INT16 INT32 INT64 INTPTR LONG LONG_LONG FLOAT DOUBLE).each do |type|
+ name = :"#{type}_ALIGNMENT"
+ const_set(name, MemoryViewTestUtils.const_get(name))
+ end
+
+ def test_rb_memory_view_register_duplicated
+ assert_warning(/Duplicated registration of memory view to/) do
+ MemoryViewTestUtils.register(MemoryViewTestUtils::ExportableString)
+ end
+ end
+
+ def test_rb_memory_view_register_nonclass
+ assert_raise(TypeError) do
+ MemoryViewTestUtils.register(Object.new)
+ end
+ end
+
+ def sizeof(type)
+ RbConfig::SIZEOF[type.to_s]
+ end
+
+ def test_rb_memory_view_item_size_from_format
+ [
+ [nil, 1], ['c', 1], ['C', 1],
+ ['n', 2], ['v', 2],
+ ['l', 4], ['L', 4], ['N', 4], ['V', 4], ['f', 4], ['e', 4], ['g', 4],
+ ['q', 8], ['Q', 8], ['d', 8], ['E', 8], ['G', 8],
+ ['s', sizeof(:short)], ['S', sizeof(:short)], ['s!', sizeof(:short)], ['S!', sizeof(:short)],
+ ['i', sizeof(:int)], ['I', sizeof(:int)], ['i!', sizeof(:int)], ['I!', sizeof(:int)],
+ ['l!', sizeof(:long)], ['L!', sizeof(:long)],
+ ['q!', sizeof('long long')], ['Q!', sizeof('long long')],
+ ['j', sizeof(:intptr_t)], ['J', sizeof(:intptr_t)],
+ ].each do |format, expected|
+ actual, err = MemoryViewTestUtils.item_size_from_format(format)
+ assert_nil(err)
+ assert_equal(expected, actual, "rb_memory_view_item_size_from_format(#{format || 'NULL'}) == #{expected}")
+ end
+ end
+
+ def test_rb_memory_view_item_size_from_format_composed
+ actual, = MemoryViewTestUtils.item_size_from_format("ccc")
+ assert_equal(3, actual)
+
+ actual, = MemoryViewTestUtils.item_size_from_format("c3")
+ assert_equal(3, actual)
+
+ actual, = MemoryViewTestUtils.item_size_from_format("fd")
+ assert_equal(12, actual)
+
+ actual, = MemoryViewTestUtils.item_size_from_format("fx2d")
+ assert_equal(14, actual)
+ end
+
+ def test_rb_memory_view_item_size_from_format_with_spaces
+ # spaces should be ignored
+ actual, = MemoryViewTestUtils.item_size_from_format("f x2 d")
+ assert_equal(14, actual)
+ end
+
+ def test_rb_memory_view_item_size_from_format_error
+ assert_equal([-1, "a"], MemoryViewTestUtils.item_size_from_format("ccca"))
+ assert_equal([-1, "a"], MemoryViewTestUtils.item_size_from_format("ccc4a"))
+ end
+
+ def test_rb_memory_view_parse_item_format
+ total_size, members, err = MemoryViewTestUtils.parse_item_format("ccc2f3x2d4q!<")
+ assert_equal(58, total_size)
+ assert_nil(err)
+ assert_equal([
+ {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 0, size: 1, repeat: 1},
+ {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 1, size: 1, repeat: 1},
+ {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 2, size: 1, repeat: 2},
+ {format: 'f', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 4, size: 4, repeat: 3},
+ {format: 'd', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 18, size: 8, repeat: 4},
+ {format: 'q', native_size_p: true, endianness: :little_endian, offset: 50, size: sizeof('long long'), repeat: 1}
+ ],
+ members)
+ end
+
+ def test_rb_memory_view_parse_item_format_with_alignment_signle
+ [
+ ["c", false, NATIVE_ENDIAN, 1, 1, 1],
+ ["C", false, NATIVE_ENDIAN, 1, 1, 1],
+ ["s", false, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1],
+ ["S", false, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1],
+ ["s!", true, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1],
+ ["S!", true, NATIVE_ENDIAN, SHORT_ALIGNMENT, sizeof(:short), 1],
+ ["n", false, :big_endian, INT16_ALIGNMENT, sizeof(:int16_t), 1],
+ ["v", false, :little_endian, INT16_ALIGNMENT, sizeof(:int16_t), 1],
+ ["i", false, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1],
+ ["I", false, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1],
+ ["i!", true, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1],
+ ["I!", true, NATIVE_ENDIAN, INT_ALIGNMENT, sizeof(:int), 1],
+ ["l", false, NATIVE_ENDIAN, INT32_ALIGNMENT, sizeof(:int32_t), 1],
+ ["L", false, NATIVE_ENDIAN, INT32_ALIGNMENT, sizeof(:int32_t), 1],
+ ["l!", true, NATIVE_ENDIAN, LONG_ALIGNMENT, sizeof(:long), 1],
+ ["L!", true, NATIVE_ENDIAN, LONG_ALIGNMENT, sizeof(:long), 1],
+ ["N", false, :big_endian, INT32_ALIGNMENT, sizeof(:int32_t), 1],
+ ["V", false, :little_endian, INT32_ALIGNMENT, sizeof(:int32_t), 1],
+ ["f", false, NATIVE_ENDIAN, FLOAT_ALIGNMENT, sizeof(:float), 1],
+ ["e", false, :little_endian, FLOAT_ALIGNMENT, sizeof(:float), 1],
+ ["g", false, :big_endian, FLOAT_ALIGNMENT, sizeof(:float), 1],
+ ["q", false, NATIVE_ENDIAN, INT64_ALIGNMENT, sizeof(:int64_t), 1],
+ ["Q", false, NATIVE_ENDIAN, INT64_ALIGNMENT, sizeof(:int64_t), 1],
+ ["q!", true, NATIVE_ENDIAN, LONG_LONG_ALIGNMENT, sizeof("long long"), 1],
+ ["Q!", true, NATIVE_ENDIAN, LONG_LONG_ALIGNMENT, sizeof("long long"), 1],
+ ["d", false, NATIVE_ENDIAN, DOUBLE_ALIGNMENT, sizeof(:double), 1],
+ ["E", false, :little_endian, DOUBLE_ALIGNMENT, sizeof(:double), 1],
+ ["G", false, :big_endian, DOUBLE_ALIGNMENT, sizeof(:double), 1],
+ ["j", false, NATIVE_ENDIAN, INTPTR_ALIGNMENT, sizeof(:intptr_t), 1],
+ ["J", false, NATIVE_ENDIAN, INTPTR_ALIGNMENT, sizeof(:intptr_t), 1],
+ ].each do |type, native_size_p, endianness, alignment, size, repeat, total_size|
+ total_size, members, err = MemoryViewTestUtils.parse_item_format("|c#{type}")
+ assert_nil(err)
+
+ padding_size = alignment - 1
+ expected_total_size = 1 + padding_size + size
+ assert_equal(expected_total_size, total_size)
+
+ expected_result = [
+ {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 0, size: 1, repeat: 1},
+ {format: type[0], native_size_p: native_size_p, endianness: endianness, offset: alignment, size: size, repeat: repeat},
+ ]
+ assert_equal(expected_result, members)
+ end
+ end
+
+ def alignment_padding(total_size, alignment)
+ res = total_size % alignment
+ if res > 0
+ alignment - res
+ else
+ 0
+ end
+ end
+
+ def test_rb_memory_view_parse_item_format_with_alignment_total_size_with_tail_padding
+ total_size, _members, err = MemoryViewTestUtils.parse_item_format("|lqc")
+ assert_nil(err)
+
+ expected_total_size = sizeof(:int32_t)
+ expected_total_size += alignment_padding(expected_total_size, INT32_ALIGNMENT)
+ expected_total_size += sizeof(:int64_t)
+ expected_total_size += alignment_padding(expected_total_size, INT64_ALIGNMENT)
+ expected_total_size += 1
+ expected_total_size += alignment_padding(expected_total_size, INT64_ALIGNMENT)
+ assert_equal(expected_total_size, total_size)
+ end
+
+ def test_rb_memory_view_parse_item_format_with_alignment_compound
+ total_size, members, err = MemoryViewTestUtils.parse_item_format("|ccc2f3x2d4cq!<")
+ assert_nil(err)
+
+ expected_total_size = 1 + 1 + 1*2
+ expected_total_size += alignment_padding(expected_total_size, FLOAT_ALIGNMENT)
+ expected_total_size += sizeof(:float)*3 + 1*2
+ expected_total_size += alignment_padding(expected_total_size, DOUBLE_ALIGNMENT)
+ expected_total_size += sizeof(:double)*4 + 1
+ expected_total_size += alignment_padding(expected_total_size, LONG_LONG_ALIGNMENT)
+ expected_total_size += sizeof("long long")
+ assert_equal(expected_total_size, total_size)
+
+ expected_result = [
+ {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 0, size: 1, repeat: 1},
+ {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 1, size: 1, repeat: 1},
+ {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: 2, size: 1, repeat: 2},
+ ]
+ offset = 4
+
+ res = offset % FLOAT_ALIGNMENT
+ offset += FLOAT_ALIGNMENT - res if res > 0
+ expected_result << {format: 'f', native_size_p: false, endianness: NATIVE_ENDIAN, offset: offset, size: 4, repeat: 3}
+ offset += 12
+
+ offset += 2 # 2x
+
+ res = offset % DOUBLE_ALIGNMENT
+ offset += DOUBLE_ALIGNMENT - res if res > 0
+ expected_result << {format: 'd', native_size_p: false, endianness: NATIVE_ENDIAN, offset: offset, size: 8, repeat: 4}
+ offset += 32
+
+ expected_result << {format: 'c', native_size_p: false, endianness: NATIVE_ENDIAN, offset: offset, size: 1, repeat: 1}
+ offset += 1
+
+ res = offset % LONG_LONG_ALIGNMENT
+ offset += LONG_LONG_ALIGNMENT - res if res > 0
+ expected_result << {format: 'q', native_size_p: true, endianness: :little_endian, offset: offset, size: 8, repeat: 1}
+
+ assert_equal(expected_result, members)
+ end
+
+ def test_rb_memory_view_extract_item_members
+ m = MemoryViewTestUtils
+ assert_equal(1, m.extract_item_members([1].pack("c"), "c"))
+ assert_equal([1, 2], m.extract_item_members([1, 2].pack("ii"), "ii"))
+ assert_equal([1, 2, 3], m.extract_item_members([1, 2, 3].pack("cls"), "cls"))
+ end
+
+ def test_rb_memory_view_extract_item_members_endianness
+ m = MemoryViewTestUtils
+ assert_equal([0x0102, 0x0304], m.extract_item_members([1, 2, 3, 4].pack("c*"), "S>2"))
+ assert_equal([0x0102, 0x0304], m.extract_item_members([1, 2, 3, 4].pack("c*"), "n2"))
+ assert_equal([0x0201, 0x0403], m.extract_item_members([1, 2, 3, 4].pack("c*"), "S<2"))
+ assert_equal([0x0201, 0x0403], m.extract_item_members([1, 2, 3, 4].pack("c*"), "v2"))
+ assert_equal(0x01020304, m.extract_item_members([1, 2, 3, 4].pack("c*"), "L>"))
+ assert_equal(0x01020304, m.extract_item_members([1, 2, 3, 4].pack("c*"), "N"))
+ assert_equal(0x04030201, m.extract_item_members([1, 2, 3, 4].pack("c*"), "L<"))
+ assert_equal(0x04030201, m.extract_item_members([1, 2, 3, 4].pack("c*"), "V"))
+ assert_equal(0x0102030405060708, m.extract_item_members([1, 2, 3, 4, 5, 6, 7, 8].pack("c*"), "Q>"))
+ assert_equal(0x0807060504030201, m.extract_item_members([1, 2, 3, 4, 5, 6, 7, 8].pack("c*"), "Q<"))
+ end
+
+ def test_rb_memory_view_extract_item_members_float
+ m = MemoryViewTestUtils
+ packed = [1.23].pack("f")
+ assert_equal(packed.unpack("f")[0], m.extract_item_members(packed, "f"))
+ end
+
+ def test_rb_memory_view_extract_item_members_float_endianness
+ m = MemoryViewTestUtils
+ hi, lo = [1.23].pack("f").unpack("L")[0].divmod(0x10000)
+ packed = [lo, hi].pack("S*")
+ assert_equal(packed.unpack("e")[0], m.extract_item_members(packed, "e"))
+ packed = [hi, lo].pack("S*")
+ assert_equal(packed.unpack("g")[0], m.extract_item_members(packed, "g"))
+ end
+
+ def test_rb_memory_view_extract_item_members_doble
+ m = MemoryViewTestUtils
+ packed = [1.23].pack("d")
+ assert_equal(1.23, m.extract_item_members(packed, "d"))
+ end
+
+ def test_rb_memory_view_extract_item_members_doble_endianness
+ m = MemoryViewTestUtils
+ hi, lo = [1.23].pack("d").unpack("Q")[0].divmod(0x10000)
+ packed = [lo, hi].pack("L*")
+ assert_equal(packed.unpack("E")[0], m.extract_item_members(packed, "E"))
+ packed = [hi, lo].pack("L*")
+ assert_equal(packed.unpack("G")[0], m.extract_item_members(packed, "G"))
+ end
+
+ def test_rb_memory_view_available_p
+ es = MemoryViewTestUtils::ExportableString.new("ruby")
+ assert_equal(true, MemoryViewTestUtils.available?(es))
+ es = MemoryViewTestUtils::ExportableString.new(nil)
+ assert_equal(false, MemoryViewTestUtils.available?(es))
+ end
+
+ def test_ref_count_with_exported_object
+ es = MemoryViewTestUtils::ExportableString.new("ruby")
+ assert_equal(1, MemoryViewTestUtils.ref_count_while_exporting(es, 1))
+ assert_equal(2, MemoryViewTestUtils.ref_count_while_exporting(es, 2))
+ assert_equal(10, MemoryViewTestUtils.ref_count_while_exporting(es, 10))
+ assert_nil(MemoryViewTestUtils.ref_count_while_exporting(es, 0))
+ end
+
+ def test_rb_memory_view_init_as_byte_array
+ # ExportableString's memory view is initialized by rb_memory_view_init_as_byte_array
+ es = MemoryViewTestUtils::ExportableString.new("ruby")
+ memory_view_info = MemoryViewTestUtils.get_memory_view_info(es)
+ assert_equal({
+ obj: es,
+ byte_size: 4,
+ readonly: true,
+ format: nil,
+ item_size: 1,
+ ndim: 1,
+ shape: nil,
+ strides: nil,
+ sub_offsets: nil
+ },
+ memory_view_info)
+ end
+
+ def test_rb_memory_view_get_with_memory_view_unavailable_object
+ es = MemoryViewTestUtils::ExportableString.new(nil)
+ memory_view_info = MemoryViewTestUtils.get_memory_view_info(es)
+ assert_nil(memory_view_info)
+ end
+
+ def test_rb_memory_view_fill_contiguous_strides
+ row_major_strides = MemoryViewTestUtils.fill_contiguous_strides(3, 8, [2, 3, 4], true)
+ assert_equal([96, 32, 8],
+ row_major_strides)
+
+ column_major_strides = MemoryViewTestUtils.fill_contiguous_strides(3, 8, [2, 3, 4], false)
+ assert_equal([8, 16, 48],
+ column_major_strides)
+ end
+
+ def test_rb_memory_view_get_item_pointer_single_member
+ buf = [ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12 ].pack("l!*")
+ shape = [3, 4]
+ mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "l!", shape, nil)
+ assert_equal(1, mv[[0, 0]])
+ assert_equal(4, mv[[0, 3]])
+ assert_equal(6, mv[[1, 1]])
+ assert_equal(10, mv[[2, 1]])
+ end
+
+ def test_rb_memory_view_get_item_pointer_multiple_members
+ buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
+ -1, -2, -3, -4, -5, -6, -7, -8].pack("s*")
+ shape = [2, 4]
+ strides = [4*sizeof(:short)*2, sizeof(:short)*2]
+ mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides)
+ assert_equal([1, 2], mv[[0, 0]])
+ assert_equal([5, 6], mv[[0, 2]])
+ assert_equal([-1, -2], mv[[1, 0]])
+ assert_equal([-7, -8], mv[[1, 3]])
+ end
+
+ def test_ractor
+ assert_in_out_err([], <<-"end;", ["[5, 6]", "[-7, -8]"], [])
+ require "-test-/memory_view"
+ require "rbconfig/sizeof"
+ $VERBOSE = nil
+ r = Ractor.new RbConfig::SIZEOF["short"] do |sizeof_short|
+ buf = [ 1, 2, 3, 4, 5, 6, 7, 8,
+ -1, -2, -3, -4, -5, -6, -7, -8].pack("s*")
+ shape = [2, 4]
+ strides = [4*sizeof_short*2, sizeof_short*2]
+ mv = MemoryViewTestUtils::MultiDimensionalView.new(buf, "ss", shape, strides)
+ p mv[[0, 2]]
+ mv[[1, 3]]
+ end
+ p r.take
+ end;
+ end
+end
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index 03a6c560e6..0bd5dc63dd 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -5,7 +5,6 @@ require 'test/unit'
class TestMethod < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -104,6 +103,12 @@ class TestMethod < Test::Unit::TestCase
assert_raise(TypeError) do
um.bind(Base.new)
end
+
+ # cleanup
+ Derived.class_eval do
+ remove_method :foo
+ def foo() :derived; end
+ end
end
def test_callee
@@ -459,6 +464,23 @@ class TestMethod < Test::Unit::TestCase
c3.class_eval { alias bar foo }
m3 = c3.new.method(:bar)
assert_equal("#<Method: #{c3.inspect}(#{c.inspect})#bar(foo)() #{__FILE__}:#{line_no}>", m3.inspect, bug7806)
+
+ bug15608 = '[ruby-core:91570] [Bug #15608]'
+ c4 = Class.new(c)
+ c4.class_eval { alias bar foo }
+ o = c4.new
+ o.singleton_class
+ m4 = o.method(:bar)
+ assert_equal("#<Method: #{c4.inspect}(#{c.inspect})#bar(foo)() #{__FILE__}:#{line_no}>", m4.inspect, bug15608)
+
+ bug17428 = '[ruby-core:101635] [Bug #17428]'
+ assert_equal("#<Method: #<Class:String>(Module)#prepend(*)>", String.method(:prepend).inspect, bug17428)
+
+ c5 = Class.new(String)
+ m = Module.new{def prepend; end; alias prep prepend}; line_no = __LINE__
+ c5.extend(m)
+ c6 = Class.new(c5)
+ assert_equal("#<Method: #<Class:#{c6.inspect}>(#{m.inspect})#prep(prepend)() #{__FILE__}:#{line_no}>", c6.method(:prep).inspect, bug17428)
end
def test_callee_top_level
@@ -790,7 +812,9 @@ class TestMethod < Test::Unit::TestCase
assert_instance_of String, __dir__
assert_equal(File.dirname(File.realpath(__FILE__)), __dir__)
bug8436 = '[ruby-core:55123] [Bug #8436]'
- assert_equal(__dir__, eval("__dir__", binding), bug8436)
+ file, line = *binding.source_location
+ file = File.realpath(file)
+ assert_equal(__dir__, eval("__dir__", binding, file, line), bug8436)
bug8662 = '[ruby-core:56099] [Bug #8662]'
assert_equal("arbitrary", eval("__dir__", binding, "arbitrary/file.rb"), bug8662)
assert_equal("arbitrary", Object.new.instance_eval("__dir__", "arbitrary/file.rb"), bug8662)
@@ -812,7 +836,7 @@ class TestMethod < Test::Unit::TestCase
assert_equal(c, c.instance_method(:foo).owner)
assert_equal(c, x.method(:foo).owner)
assert_equal(x.singleton_class, x.method(:bar).owner)
- assert_not_equal(x.method(:foo), x.method(:bar), bug7613)
+ assert_equal(x.method(:foo), x.method(:bar), bug7613)
assert_equal(c, x.method(:zot).owner, bug7993)
assert_equal(c, c.instance_method(:zot).owner, bug7993)
end
@@ -1193,17 +1217,22 @@ class TestMethod < Test::Unit::TestCase
assert_equal([:bar, :foo], b.local_variables.sort, bug11012)
end
- class MethodInMethodClass
- def m1
- def m2
- end
+ MethodInMethodClass_Setup = -> do
+ remove_const :MethodInMethodClass if defined? MethodInMethodClass
- self.class.send(:define_method, :m3){} # [Bug #11754]
+ class MethodInMethodClass
+ def m1
+ def m2
+ end
+ self.class.send(:define_method, :m3){} # [Bug #11754]
+ end
+ private
end
- private
end
def test_method_in_method_visibility_should_be_public
+ MethodInMethodClass_Setup.call
+
assert_equal([:m1].sort, MethodInMethodClass.public_instance_methods(false).sort)
assert_equal([].sort, MethodInMethodClass.private_instance_methods(false).sort)
@@ -1253,6 +1282,42 @@ class TestMethod < Test::Unit::TestCase
assert_separately [], "RubyVM::InstructionSequence.compile_option = {trace_instruction: false}\n" + body
end
+ def test_zsuper_private_override_instance_method
+ assert_separately(%w(--disable-gems), <<-'end;', timeout: 30)
+ # Bug #16942 [ruby-core:98691]
+ module M
+ def x
+ end
+ end
+
+ module M2
+ prepend Module.new
+ include M
+ private :x
+ end
+
+ ::Object.prepend(M2)
+
+ m = Object.instance_method(:x)
+ assert_equal M, m.owner
+ end;
+ end
+
+ def test_override_optimized_method_on_class_using_prepend
+ assert_separately(%w(--disable-gems), <<-'end;', timeout: 30)
+ # Bug #17725 [ruby-core:102884]
+ $VERBOSE = nil
+ String.prepend(Module.new)
+ class String
+ def + other
+ 'blah blah'
+ end
+ end
+
+ assert_equal('blah blah', 'a' + 'b')
+ end;
+ end
+
def test_eqq
assert_operator(0.method(:<), :===, 5)
assert_not_operator(0.method(:<), :===, -5)
@@ -1359,4 +1424,8 @@ class TestMethod < Test::Unit::TestCase
assert_operator nummodule, :>, 0
assert_operator nummethod, :>, 0
end
+
+ def test_invalidating_CC_ASAN
+ assert_ruby_status(['-e', 'using Module.new'])
+ end
end
diff --git a/test/ruby/test_method_cache.rb b/test/ruby/test_method_cache.rb
new file mode 100644
index 0000000000..a8e7e22ae3
--- /dev/null
+++ b/test/ruby/test_method_cache.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class TestMethodCache < Test::Unit::TestCase
+ def test_undef
+ # clear same
+ c0 = Class.new do
+ def foo; end
+ undef foo
+ end
+
+ assert_raise(NoMethodError) do
+ c0.new.foo
+ end
+
+ c0.class_eval do
+ def foo; :ok; end
+ end
+
+ assert_equal :ok, c0.new.foo
+ end
+
+ def test_undef_with_subclasses
+ # with subclasses
+ c0 = Class.new do
+ def foo; end
+ undef foo
+ end
+
+ _c1 = Class.new(c0)
+
+ assert_raise(NoMethodError) do
+ c0.new.foo
+ end
+
+ c0.class_eval do
+ def foo; :ok; end
+ end
+
+ assert_equal :ok, c0.new.foo
+ end
+
+ def test_undef_with_subclasses_complicated
+ c0 = Class.new{ def foo; end }
+ c1 = Class.new(c0){ undef foo }
+ c2 = Class.new(c1)
+ c3 = Class.new(c2)
+ _c4 = Class.new(c3)
+
+ assert_raise(NoMethodError) do
+ c3.new.foo
+ end
+
+ c2.class_eval do
+ def foo; :c2; end
+ end
+
+ assert_raise(NoMethodError) do
+ c1.new.foo
+ end
+
+ assert_equal :c2, c3.new.foo
+ end
+end
+
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index 231ccd2072..5db6732fee 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -27,7 +27,6 @@ class TestModule < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
@deprecated = Warning[:deprecated]
Warning[:deprecated] = true
end
@@ -88,8 +87,11 @@ class TestModule < Test::Unit::TestCase
private :user3
end
- module Other
- def other
+ OtherSetup = -> do
+ remove_const :Other if defined? ::TestModule::Other
+ module Other
+ def other
+ end
end
end
@@ -223,6 +225,8 @@ class TestModule < Test::Unit::TestCase
@@class_eval = 'b'
def test_class_eval
+ OtherSetup.call
+
Other.class_eval("CLASS_EVAL = 1")
assert_equal(1, Other::CLASS_EVAL)
assert_include(Other.constants, :CLASS_EVAL)
@@ -297,6 +301,8 @@ class TestModule < Test::Unit::TestCase
end
def test_nested_get
+ OtherSetup.call
+
assert_equal Other, Object.const_get([self.class, 'Other'].join('::'))
assert_equal User::USER, self.class.const_get([User, 'USER'].join('::'))
assert_raise(NameError) {
@@ -305,6 +311,8 @@ class TestModule < Test::Unit::TestCase
end
def test_nested_get_symbol
+ OtherSetup.call
+
const = [self.class, Other].join('::').to_sym
assert_raise(NameError) {Object.const_get(const)}
@@ -331,6 +339,8 @@ class TestModule < Test::Unit::TestCase
end
def test_nested_defined
+ OtherSetup.call
+
assert_send([Object, :const_defined?, [self.class.name, 'Other'].join('::')])
assert_send([self.class, :const_defined?, 'User::USER'])
assert_not_send([self.class, :const_defined?, 'User::Foo'])
@@ -338,6 +348,8 @@ class TestModule < Test::Unit::TestCase
end
def test_nested_defined_symbol
+ OtherSetup.call
+
const = [self.class, Other].join('::').to_sym
assert_raise(NameError) {Object.const_defined?(const)}
@@ -363,6 +375,8 @@ class TestModule < Test::Unit::TestCase
end
def test_const_set
+ OtherSetup.call
+
assert_not_operator(Other, :const_defined?, :KOALA)
Other.const_set(:KOALA, 99)
assert_operator(Other, :const_defined?, :KOALA)
@@ -421,6 +435,8 @@ class TestModule < Test::Unit::TestCase
end
def test_dup
+ OtherSetup.call
+
bug6454 = '[ruby-core:45132]'
a = Module.new
@@ -462,6 +478,139 @@ class TestModule < Test::Unit::TestCase
assert_raise(ArgumentError) { Module.new { include } }
end
+ def test_prepend_works_with_duped_classes
+ m = Module.new
+ a = Class.new do
+ def b; 2 end
+ prepend m
+ end
+ a2 = a.dup.new
+ a.class_eval do
+ alias _b b
+ def b; 1 end
+ end
+ assert_equal(2, a2.b)
+ end
+
+ def test_gc_prepend_chain
+ assert_separately([], <<-EOS)
+ 10000.times { |i|
+ m1 = Module.new do
+ def foo; end
+ end
+ m2 = Module.new do
+ prepend m1
+ def bar; end
+ end
+ m3 = Module.new do
+ def baz; end
+ prepend m2
+ end
+ Class.new do
+ prepend m3
+ end
+ }
+ GC.start
+ EOS
+ end
+
+ def test_refine_module_then_include
+ assert_separately([], "#{<<~"end;"}\n")
+ module M
+ end
+ class C
+ include M
+ end
+ module RefinementBug
+ refine M do
+ def refined_method
+ :rm
+ end
+ end
+ end
+ using RefinementBug
+
+ class A
+ include M
+ end
+
+ assert_equal(:rm, C.new.refined_method)
+ end;
+ end
+
+ def test_include_into_module_already_included
+ c = Class.new{def foo; [:c] end}
+ modules = lambda do ||
+ sub = Class.new(c){def foo; [:sc] + super end}
+ [
+ Module.new{def foo; [:m1] + super end},
+ Module.new{def foo; [:m2] + super end},
+ Module.new{def foo; [:m3] + super end},
+ sub,
+ sub.new
+ ]
+ end
+
+ m1, m2, m3, sc, o = modules.call
+ assert_equal([:sc, :c], o.foo)
+ sc.include m1
+ assert_equal([:sc, :m1, :c], o.foo)
+ m1.include m2
+ assert_equal([:sc, :m1, :m2, :c], o.foo)
+ m2.include m3
+ assert_equal([:sc, :m1, :m2, :m3, :c], o.foo)
+
+ m1, m2, m3, sc, o = modules.call
+ sc.prepend m1
+ assert_equal([:m1, :sc, :c], o.foo)
+ m1.include m2
+ assert_equal([:m1, :m2, :sc, :c], o.foo)
+ m2.include m3
+ assert_equal([:m1, :m2, :m3, :sc, :c], o.foo)
+
+ m1, m2, m3, sc, o = modules.call
+ sc.include m2
+ assert_equal([:sc, :m2, :c], o.foo)
+ sc.prepend m1
+ assert_equal([:m1, :sc, :m2, :c], o.foo)
+ m1.include m2
+ assert_equal([:m1, :sc, :m2, :c], o.foo)
+ m1.include m3
+ assert_equal([:m1, :m3, :sc, :m2, :c], o.foo)
+
+ m1, m2, m3, sc, o = modules.call
+ sc.include m3
+ sc.include m2
+ assert_equal([:sc, :m2, :m3, :c], o.foo)
+ sc.prepend m1
+ assert_equal([:m1, :sc, :m2, :m3, :c], o.foo)
+ m1.include m2
+ m1.include m3
+ assert_equal([:m1, :sc, :m2, :m3, :c], o.foo)
+
+ m1, m2, m3, sc, o = modules.call
+ assert_equal([:sc, :c], o.foo)
+ sc.prepend m1
+ assert_equal([:m1, :sc, :c], o.foo)
+ m1.prepend m2
+ assert_equal([:m2, :m1, :sc, :c], o.foo)
+ m2.prepend m3
+ assert_equal([:m3, :m2, :m1, :sc, :c], o.foo)
+ m1, m2, m3, sc, o = modules.call
+ sc.include m1
+ assert_equal([:sc, :m1, :c], o.foo)
+ sc.prepend m2
+ assert_equal([:m2, :sc, :m1, :c], o.foo)
+ sc.prepend m3
+ assert_equal([:m3, :m2, :sc, :m1, :c], o.foo)
+ m1, m2, m3, sc, o = modules.call
+ sc.include m1
+ assert_equal([:sc, :m1, :c], o.foo)
+ m2.prepend m3
+ m1.include m2
+ assert_equal([:sc, :m1, :m3, :m2, :c], o.foo)
+ end
+
def test_included_modules
assert_equal([], Mixin.included_modules)
assert_equal([Mixin], User.included_modules)
@@ -472,6 +621,16 @@ class TestModule < Test::Unit::TestCase
assert_equal([Comparable, Kernel], String.included_modules - mixins)
end
+ def test_included_modules_with_prepend
+ m1 = Module.new
+ m2 = Module.new
+ m3 = Module.new
+
+ m2.prepend m1
+ m3.include m2
+ assert_equal([m1, m2], m3.included_modules)
+ end
+
def test_include_with_prepend
c = Class.new{def m; [:c] end}
p = Module.new{def m; [:p] + super end}
@@ -532,6 +691,11 @@ class TestModule < Test::Unit::TestCase
assert !c.method_defined?(:userx, false)
c.define_method(:userx){}
assert c.method_defined?(:userx, false)
+
+ # cleanup
+ User.class_eval do
+ remove_const :FOO
+ end
end
def module_exec_aux
@@ -562,6 +726,14 @@ class TestModule < Test::Unit::TestCase
def dynamically_added_method_4; end
end
assert_method_defined?(User, :dynamically_added_method_4)
+
+ # cleanup
+ User.class_eval do
+ remove_method :dynamically_added_method_1
+ remove_method :dynamically_added_method_2
+ remove_method :dynamically_added_method_3
+ remove_method :dynamically_added_method_4
+ end
end
def test_module_eval
@@ -605,13 +777,13 @@ class TestModule < Test::Unit::TestCase
n = Module.new
m.const_set(:N, n)
assert_nil(m.name)
- assert_nil(n.name)
+ assert_match(/::N$/, n.name)
assert_equal([:N], m.constants)
m.module_eval("module O end")
assert_equal([:N, :O], m.constants.sort)
m.module_eval("class C; end")
assert_equal([:C, :N, :O], m.constants.sort)
- assert_nil(m::N.name)
+ assert_match(/::N$/, m::N.name)
assert_match(/\A#<Module:.*>::O\z/, m::O.name)
assert_match(/\A#<Module:.*>::C\z/, m::C.name)
self.class.const_set(:M, m)
@@ -627,6 +799,11 @@ class TestModule < Test::Unit::TestCase
assert_raise(ExpectedException) { AClass.cm1 }
assert_raise(ExpectedException) { AClass.cm3 }
assert_equal("cm1cm2cm3", AClass.cm2)
+
+ c = Class.new(AClass)
+ c.class_eval {private_class_method [:cm1, :cm2]}
+ assert_raise(NoMethodError, /private method/) {c.cm1}
+ assert_raise(NoMethodError, /private method/) {c.cm2}
end
def test_private_instance_methods
@@ -649,6 +826,11 @@ class TestModule < Test::Unit::TestCase
assert_equal("cm1", MyClass.cm1)
assert_equal("cm1cm2cm3", MyClass.cm2)
assert_raise(ExpectedException) { eval "MyClass.cm3" }
+
+ c = Class.new(AClass)
+ c.class_eval {public_class_method [:cm1, :cm2]}
+ assert_equal("cm1", c.cm1)
+ assert_equal("cm1cm2cm3", c.cm2)
end
def test_public_instance_methods
@@ -656,12 +838,94 @@ class TestModule < Test::Unit::TestCase
assert_equal([:bClass1], BClass.public_instance_methods(false))
end
+ def test_s_public
+ o = (c = Class.new(AClass)).new
+ assert_raise(NoMethodError, /private method/) {o.aClass1}
+ assert_raise(NoMethodError, /protected method/) {o.aClass2}
+ c.class_eval {public :aClass1}
+ assert_equal(:aClass1, o.aClass1)
+
+ o = (c = Class.new(AClass)).new
+ c.class_eval {public :aClass1, :aClass2}
+ assert_equal(:aClass1, o.aClass1)
+ assert_equal(:aClass2, o.aClass2)
+
+ o = (c = Class.new(AClass)).new
+ c.class_eval {public [:aClass1, :aClass2]}
+ assert_equal(:aClass1, o.aClass1)
+ assert_equal(:aClass2, o.aClass2)
+
+ o = AClass.new
+ assert_equal(:aClass, o.aClass)
+ assert_raise(NoMethodError, /private method/) {o.aClass1}
+ assert_raise(NoMethodError, /protected method/) {o.aClass2}
+ end
+
+ def test_s_private
+ o = (c = Class.new(AClass)).new
+ assert_equal(:aClass, o.aClass)
+ c.class_eval {private :aClass}
+ assert_raise(NoMethodError, /private method/) {o.aClass}
+
+ o = (c = Class.new(AClass)).new
+ c.class_eval {private :aClass, :aClass2}
+ assert_raise(NoMethodError, /private method/) {o.aClass}
+ assert_raise(NoMethodError, /private method/) {o.aClass2}
+
+ o = (c = Class.new(AClass)).new
+ c.class_eval {private [:aClass, :aClass2]}
+ assert_raise(NoMethodError, /private method/) {o.aClass}
+ assert_raise(NoMethodError, /private method/) {o.aClass2}
+
+ o = AClass.new
+ assert_equal(:aClass, o.aClass)
+ assert_raise(NoMethodError, /private method/) {o.aClass1}
+ assert_raise(NoMethodError, /protected method/) {o.aClass2}
+ end
+
+ def test_s_protected
+ aclass = Class.new(AClass) do
+ def _aClass(o) o.aClass; end
+ def _aClass1(o) o.aClass1; end
+ def _aClass2(o) o.aClass2; end
+ end
+
+ o = (c = Class.new(aclass)).new
+ assert_equal(:aClass, o.aClass)
+ c.class_eval {protected :aClass}
+ assert_raise(NoMethodError, /protected method/) {o.aClass}
+ assert_equal(:aClass, c.new._aClass(o))
+
+ o = (c = Class.new(aclass)).new
+ c.class_eval {protected :aClass, :aClass1}
+ assert_raise(NoMethodError, /protected method/) {o.aClass}
+ assert_raise(NoMethodError, /protected method/) {o.aClass1}
+ assert_equal(:aClass, c.new._aClass(o))
+ assert_equal(:aClass1, c.new._aClass1(o))
+
+ o = (c = Class.new(aclass)).new
+ c.class_eval {protected [:aClass, :aClass1]}
+ assert_raise(NoMethodError, /protected method/) {o.aClass}
+ assert_raise(NoMethodError, /protected method/) {o.aClass1}
+ assert_equal(:aClass, c.new._aClass(o))
+ assert_equal(:aClass1, c.new._aClass1(o))
+
+ o = AClass.new
+ assert_equal(:aClass, o.aClass)
+ assert_raise(NoMethodError, /private method/) {o.aClass1}
+ assert_raise(NoMethodError, /protected method/) {o.aClass2}
+ end
+
def test_s_constants
c1 = Module.constants
Object.module_eval "WALTER = 99"
c2 = Module.constants
assert_equal([:WALTER], c2 - c1)
+ Object.class_eval do
+ remove_const :WALTER
+ end
+
assert_equal([], Module.constants(true))
assert_equal([], Module.constants(false))
@@ -724,14 +988,18 @@ class TestModule < Test::Unit::TestCase
end
def test_attr_obsoleted_flag
- c = Class.new
- c.class_eval do
+ c = Class.new do
+ extend Test::Unit::Assertions
def initialize
@foo = :foo
@bar = :bar
end
- attr :foo, true
- attr :bar, false
+ assert_deprecated_warning(/optional boolean argument/) do
+ attr :foo, true
+ end
+ assert_deprecated_warning(/optional boolean argument/) do
+ attr :bar, false
+ end
end
o = c.new
assert_equal(true, o.respond_to?(:foo))
@@ -776,6 +1044,7 @@ class TestModule < Test::Unit::TestCase
assert_equal(:foo, c2.const_get(:Foo))
assert_raise(NameError) { c2.const_get(:Foo, false) }
+ c1.__send__(:remove_const, :Foo)
eval("c1::Foo = :foo")
assert_raise(NameError) { c1::Bar }
assert_raise(NameError) { c2::Bar }
@@ -973,6 +1242,28 @@ class TestModule < Test::Unit::TestCase
assert_raise(NameError) do
c.instance_eval { attr_reader :"." }
end
+
+ assert_equal([:a], c.class_eval { attr :a })
+ assert_equal([:b, :c], c.class_eval { attr :b, :c })
+ assert_equal([:d], c.class_eval { attr_reader :d })
+ assert_equal([:e, :f], c.class_eval { attr_reader :e, :f })
+ assert_equal([:g=], c.class_eval { attr_writer :g })
+ assert_equal([:h=, :i=], c.class_eval { attr_writer :h, :i })
+ assert_equal([:j, :j=], c.class_eval { attr_accessor :j })
+ assert_equal([:k, :k=, :l, :l=], c.class_eval { attr_accessor :k, :l })
+ end
+
+ def test_alias_method
+ c = Class.new do
+ def foo; :foo end
+ end
+ o = c.new
+ assert_respond_to(o, :foo)
+ assert_not_respond_to(o, :bar)
+ r = c.class_eval {alias_method :bar, :foo}
+ assert_respond_to(o, :bar)
+ assert_equal(:foo, o.bar)
+ assert_equal(:bar, r)
end
def test_undef
@@ -1122,13 +1413,25 @@ class TestModule < Test::Unit::TestCase
end
def test_top_public_private
- assert_in_out_err([], <<-INPUT, %w([:foo] [:bar]), [])
+ assert_in_out_err([], <<-INPUT, %w([:foo] [:bar] [:bar,\ :foo] [] [:bar,\ :foo] []), [])
private
def foo; :foo; end
public
def bar; :bar; end
p self.private_methods.grep(/^foo$|^bar$/)
p self.methods.grep(/^foo$|^bar$/)
+
+ private :foo, :bar
+ p self.private_methods.grep(/^foo$|^bar$/).sort
+
+ public :foo, :bar
+ p self.private_methods.grep(/^foo$|^bar$/).sort
+
+ private [:foo, :bar]
+ p self.private_methods.grep(/^foo$|^bar$/).sort
+
+ public [:foo, :bar]
+ p self.private_methods.grep(/^foo$|^bar$/).sort
INPUT
end
@@ -1934,7 +2237,30 @@ class TestModule < Test::Unit::TestCase
assert_equal(0, 1 / 2)
end
- def test_visibility_after_refine_and_visibility_change
+ def test_visibility_after_refine_and_visibility_change_with_origin_class
+ m = Module.new
+ c = Class.new do
+ def x; :x end
+ end
+ c.prepend(m)
+ Module.new do
+ refine c do
+ def x; :y end
+ end
+ end
+
+ o1 = c.new
+ o2 = c.new
+ assert_equal(:x, o1.public_send(:x))
+ assert_equal(:x, o2.public_send(:x))
+ o1.singleton_class.send(:private, :x)
+ o2.singleton_class.send(:public, :x)
+
+ assert_raise(NoMethodError) { o1.public_send(:x) }
+ assert_equal(:x, o2.public_send(:x))
+ end
+
+ def test_visibility_after_multiple_refine_and_visibility_change_with_origin_class
m = Module.new
c = Class.new do
def x; :x end
@@ -1945,6 +2271,11 @@ class TestModule < Test::Unit::TestCase
def x; :y end
end
end
+ Module.new do
+ refine c do
+ def x; :z end
+ end
+ end
o1 = c.new
o2 = c.new
@@ -1957,6 +2288,86 @@ class TestModule < Test::Unit::TestCase
assert_equal(:x, o2.public_send(:x))
end
+ def test_visibility_after_refine_and_visibility_change_without_origin_class
+ c = Class.new do
+ def x; :x end
+ end
+ Module.new do
+ refine c do
+ def x; :y end
+ end
+ end
+ o1 = c.new
+ o2 = c.new
+ o1.singleton_class.send(:private, :x)
+ o2.singleton_class.send(:public, :x)
+ assert_raise(NoMethodError) { o1.public_send(:x) }
+ assert_equal(:x, o2.public_send(:x))
+ end
+
+ def test_visibility_after_multiple_refine_and_visibility_change_without_origin_class
+ c = Class.new do
+ def x; :x end
+ end
+ Module.new do
+ refine c do
+ def x; :y end
+ end
+ end
+ Module.new do
+ refine c do
+ def x; :z end
+ end
+ end
+ o1 = c.new
+ o2 = c.new
+ o1.singleton_class.send(:private, :x)
+ o2.singleton_class.send(:public, :x)
+ assert_raise(NoMethodError) { o1.public_send(:x) }
+ assert_equal(:x, o2.public_send(:x))
+ end
+
+ def test_visibility_after_refine_and_visibility_change_with_superclass
+ c = Class.new do
+ def x; :x end
+ end
+ sc = Class.new(c)
+ Module.new do
+ refine sc do
+ def x; :y end
+ end
+ end
+ o1 = sc.new
+ o2 = sc.new
+ o1.singleton_class.send(:private, :x)
+ o2.singleton_class.send(:public, :x)
+ assert_raise(NoMethodError) { o1.public_send(:x) }
+ assert_equal(:x, o2.public_send(:x))
+ end
+
+ def test_visibility_after_multiple_refine_and_visibility_change_with_superclass
+ c = Class.new do
+ def x; :x end
+ end
+ sc = Class.new(c)
+ Module.new do
+ refine sc do
+ def x; :y end
+ end
+ end
+ Module.new do
+ refine sc do
+ def x; :z end
+ end
+ end
+ o1 = sc.new
+ o2 = sc.new
+ o1.singleton_class.send(:private, :x)
+ o2.singleton_class.send(:public, :x)
+ assert_raise(NoMethodError) { o1.public_send(:x) }
+ assert_equal(:x, o2.public_send(:x))
+ end
+
def test_prepend_visibility
bug8005 = '[ruby-core:53106] [Bug #8005]'
c = Class.new do
@@ -1999,6 +2410,33 @@ class TestModule < Test::Unit::TestCase
assert_include(im, mixin, bug8025)
end
+ def test_prepended_module_with_super_and_alias
+ bug16736 = '[Bug #16736]'
+
+ a = labeled_class("A") do
+ def m; "A"; end
+ end
+ m = labeled_module("M") do
+ prepend Module.new
+
+ def self.included(base)
+ base.alias_method :base_m, :m
+ end
+
+ def m
+ super + "M"
+ end
+
+ def m2
+ base_m
+ end
+ end
+ b = labeled_class("B", a) do
+ include m
+ end
+ assert_equal("AM", b.new.m2, bug16736)
+ end
+
def test_prepend_super_in_alias
bug7842 = '[Bug #7842]'
@@ -2117,6 +2555,22 @@ class TestModule < Test::Unit::TestCase
assert_equal([:@@bar], m2.class_variables(false))
end
+ def test_class_variable_in_dup_class
+ a = Class.new do
+ @@a = 'A'
+ def a=(x)
+ @@a = x
+ end
+ def a
+ @@a
+ end
+ end
+
+ b = a.dup
+ b.new.a = 'B'
+ assert_equal 'A', a.new.a, '[ruby-core:17019]'
+ end
+
Bug6891 = '[ruby-core:47241]'
def test_extend_module_with_protected_method
@@ -2193,6 +2647,9 @@ class TestModule < Test::Unit::TestCase
class AttrTest
class << self
attr_accessor :cattr
+ def reset
+ self.cattr = nil
+ end
end
attr_accessor :iattr
def ivar
@@ -2202,7 +2659,7 @@ class TestModule < Test::Unit::TestCase
def test_uninitialized_instance_variable
a = AttrTest.new
- assert_warning(/instance variable @ivar not initialized/) do
+ assert_warning('') do
assert_nil(a.ivar)
end
a.instance_variable_set(:@ivar, 42)
@@ -2211,7 +2668,7 @@ class TestModule < Test::Unit::TestCase
end
name = "@\u{5909 6570}"
- assert_warning(/instance variable #{name} not initialized/) do
+ assert_warning('') do
assert_nil(a.instance_eval(name))
end
end
@@ -2235,6 +2692,8 @@ class TestModule < Test::Unit::TestCase
assert_warning '' do
assert_equal(42, AttrTest.cattr)
end
+
+ AttrTest.reset
end
def test_uninitialized_attr_non_object
@@ -2338,31 +2797,6 @@ class TestModule < Test::Unit::TestCase
assert_raise(NoMethodError, bug8284) {Object.remove_const}
end
- def test_include_module_with_constants_does_not_invalidate_method_cache
- assert_in_out_err([], <<-RUBY, %w(123 456 true), [])
- A = 123
-
- class Foo
- def self.a
- A
- end
- end
-
- module M
- A = 456
- end
-
- puts Foo.a
- starting = RubyVM.stat[:global_method_state]
-
- Foo.send(:include, M)
-
- ending = RubyVM.stat[:global_method_state]
- puts Foo.a
- puts starting == ending
- RUBY
- end
-
def test_return_value_of_define_method
retvals = []
Class.new.class_eval do
@@ -2401,7 +2835,10 @@ class TestModule < Test::Unit::TestCase
def test_inspect_segfault
bug_10282 = '[ruby-core:65214] [Bug #10282]'
- assert_separately [], <<-RUBY
+ assert_separately [], "#{<<~"begin;"}\n#{<<~'end;'}"
+ bug_10282 = "#{bug_10282}"
+ begin;
+ line = __LINE__ + 2
module ShallowInspect
def shallow_inspect
"foo"
@@ -2418,9 +2855,9 @@ class TestModule < Test::Unit::TestCase
A.prepend InspectIsShallow
- expect = "#<Method: A(ShallowInspect)#inspect(shallow_inspect)() -:7>"
- assert_equal expect, A.new.method(:inspect).inspect, "#{bug_10282}"
- RUBY
+ expect = "#<Method: A(ShallowInspect)#inspect(shallow_inspect)() -:#{line}>"
+ assert_equal expect, A.new.method(:inspect).inspect, bug_10282
+ end;
end
def test_define_method_with_unbound_method
@@ -2532,6 +2969,18 @@ class TestModule < Test::Unit::TestCase
assert_equal :M2, CloneTestC2.new.foo, '[Bug #15877]'
end
+ def test_clone_freeze
+ m = Module.new.freeze
+ assert_predicate m.clone, :frozen?
+ assert_not_predicate m.clone(freeze: false), :frozen?
+ end
+
+ def test_module_name_in_singleton_method
+ s = Object.new.singleton_class
+ mod = s.const_set(:Foo, Module.new)
+ assert_match(/::Foo$/, mod.name, '[Bug #14895]')
+ end
+
private
def assert_top_method_is_private(method)
diff --git a/test/ruby/test_name_error.rb b/test/ruby/test_name_error.rb
new file mode 100644
index 0000000000..813a976e96
--- /dev/null
+++ b/test/ruby/test_name_error.rb
@@ -0,0 +1,156 @@
+require 'test/unit'
+
+class TestNameError < Test::Unit::TestCase
+ def test_new_default
+ error = NameError.new
+ assert_equal("NameError", error.message)
+ end
+
+ def test_new_message
+ error = NameError.new("Message")
+ assert_equal("Message", error.message)
+ end
+
+ def test_new_name
+ error = NameError.new("Message")
+ assert_nil(error.name)
+
+ error = NameError.new("Message", :foo)
+ assert_equal(:foo, error.name)
+ end
+
+ def test_new_receiver
+ receiver = Object.new
+
+ error = NameError.new
+ assert_raise(ArgumentError) {error.receiver}
+ assert_equal("NameError", error.message)
+
+ error = NameError.new(receiver: receiver)
+ assert_equal(["NameError", receiver],
+ [error.message, error.receiver])
+
+ error = NameError.new("Message", :foo, receiver: receiver)
+ assert_equal(["Message", receiver, :foo],
+ [error.message, error.receiver, error.name])
+ end
+
+ PrettyObject =
+ Class.new(BasicObject) do
+ alias object_id __id__
+ def pretty_inspect; "`obj'"; end
+ alias inspect pretty_inspect
+ end
+
+ def test_info_const
+ obj = PrettyObject.new
+
+ e = assert_raise(NameError) {
+ obj.instance_eval("Object")
+ }
+ assert_equal(:Object, e.name)
+
+ e = assert_raise(NameError) {
+ BasicObject::X
+ }
+ assert_same(BasicObject, e.receiver)
+ assert_equal(:X, e.name)
+ end
+
+ def test_info_const_name
+ mod = Module.new do
+ def self.name
+ "ModuleName"
+ end
+
+ def self.inspect
+ raise "<unusable info>"
+ end
+ end
+ assert_raise_with_message(NameError, /ModuleName/) {mod::DOES_NOT_EXIST}
+ end
+
+ def test_info_method
+ obj = PrettyObject.new
+
+ e = assert_raise(NameError) {
+ obj.instance_eval {foo}
+ }
+ assert_equal(:foo, e.name)
+ assert_same(obj, e.receiver)
+
+ e = assert_raise(NoMethodError) {
+ obj.foo(1, 2)
+ }
+ assert_equal(:foo, e.name)
+ assert_equal([1, 2], e.args)
+ assert_same(obj, e.receiver)
+ assert_not_predicate(e, :private_call?)
+
+ e = assert_raise(NoMethodError) {
+ obj.instance_eval {foo(1, 2)}
+ }
+ assert_equal(:foo, e.name)
+ assert_equal([1, 2], e.args)
+ assert_same(obj, e.receiver)
+ assert_predicate(e, :private_call?)
+ end
+
+ def test_info_local_variables
+ obj = PrettyObject.new
+ def obj.test(a, b=nil, *c, &d)
+ e = a
+ 1.times {|f| g = foo; g}
+ e
+ end
+
+ e = assert_raise(NameError) {
+ obj.test(3)
+ }
+ assert_equal(:foo, e.name)
+ assert_same(obj, e.receiver)
+ assert_equal(%i[a b c d e f g], e.local_variables.sort)
+ end
+
+ def test_info_method_missing
+ obj = PrettyObject.new
+ def obj.method_missing(*)
+ super
+ end
+
+ e = assert_raise(NoMethodError) {
+ obj.foo(1, 2)
+ }
+ assert_equal(:foo, e.name)
+ assert_equal([1, 2], e.args)
+ assert_same(obj, e.receiver)
+ assert_not_predicate(e, :private_call?)
+
+ e = assert_raise(NoMethodError) {
+ obj.instance_eval {foo(1, 2)}
+ }
+ assert_equal(:foo, e.name)
+ assert_equal([1, 2], e.args)
+ assert_same(obj, e.receiver)
+ assert_predicate(e, :private_call?)
+ end
+
+ def test_info_parent_iseq_mark
+ assert_separately(['-', File.join(__dir__, 'bug-11928.rb')], <<-'end;')
+ -> {require ARGV[0]}.call
+ end;
+ end
+
+ def test_large_receiver_inspect
+ receiver = Class.new do
+ def self.inspect
+ 'A' * 120
+ end
+ end
+
+ error = assert_raise(NameError) do
+ receiver::FOO
+ end
+ assert_equal "uninitialized constant #{'A' * 120}::FOO", error.message
+ end
+end
diff --git a/test/ruby/test_nomethod_error.rb b/test/ruby/test_nomethod_error.rb
new file mode 100644
index 0000000000..8b81052905
--- /dev/null
+++ b/test/ruby/test_nomethod_error.rb
@@ -0,0 +1,109 @@
+require 'test/unit'
+
+class TestNoMethodError < Test::Unit::TestCase
+ def test_new_default
+ error = NoMethodError.new
+ assert_equal("NoMethodError", error.message)
+ end
+
+ def test_new_message
+ error = NoMethodError.new("Message")
+ assert_equal("Message", error.message)
+ end
+
+ def test_new_name
+ error = NoMethodError.new("Message")
+ assert_nil(error.name)
+
+ error = NoMethodError.new("Message", :foo)
+ assert_equal(:foo, error.name)
+ end
+
+ def test_new_name_args
+ error = NoMethodError.new("Message", :foo)
+ assert_nil(error.args)
+
+ error = NoMethodError.new("Message", :foo, [1, 2])
+ assert_equal([:foo, [1, 2]], [error.name, error.args])
+ end
+
+ def test_new_name_args_priv
+ error = NoMethodError.new("Message", :foo, [1, 2])
+ assert_not_predicate(error, :private_call?)
+
+ error = NoMethodError.new("Message", :foo, [1, 2], true)
+ assert_equal([:foo, [1, 2], true],
+ [error.name, error.args, error.private_call?])
+ end
+
+ def test_new_receiver
+ receiver = Object.new
+
+ error = NoMethodError.new
+ assert_raise(ArgumentError) {error.receiver}
+
+ error = NoMethodError.new(receiver: receiver)
+ assert_equal(receiver, error.receiver)
+
+ error = NoMethodError.new("Message")
+ assert_raise(ArgumentError) {error.receiver}
+
+ error = NoMethodError.new("Message", receiver: receiver)
+ assert_equal(["Message", receiver],
+ [error.message, error.receiver])
+
+ error = NoMethodError.new("Message", :foo)
+ assert_raise(ArgumentError) {error.receiver}
+
+ msg = "Message"
+
+ error = NoMethodError.new("Message", :foo, receiver: receiver)
+ assert_match msg, error.message
+ assert_equal :foo, error.name
+ assert_equal receiver, error.receiver
+
+ error = NoMethodError.new("Message", :foo, [1, 2])
+ assert_raise(ArgumentError) {error.receiver}
+
+ error = NoMethodError.new("Message", :foo, [1, 2], receiver: receiver)
+ assert_match msg, error.message
+ assert_equal :foo, error.name
+ assert_equal [1, 2], error.args
+ assert_equal receiver, error.receiver
+
+ error = NoMethodError.new("Message", :foo, [1, 2], true)
+ assert_raise(ArgumentError) {error.receiver}
+
+ error = NoMethodError.new("Message", :foo, [1, 2], true, receiver: receiver)
+ assert_equal :foo, error.name
+ assert_equal [1, 2], error.args
+ assert_equal receiver, error.receiver
+ assert error.private_call?, "private_call? was false."
+ end
+
+ def test_message_encoding
+ bug3237 = '[ruby-core:29948]'
+ str = "\u2600"
+ id = :"\u2604"
+ msg = "undefined method `#{id}' for \"#{str}\":String"
+ assert_raise_with_message(NoMethodError, msg, bug3237) do
+ str.__send__(id)
+ end
+ end
+
+ def test_to_s
+ pre = Module.new do
+ def name
+ BasicObject.new
+ end
+ end
+ mod = Module.new
+ mod.singleton_class.prepend(pre)
+
+ err = assert_raise(NoMethodError) do
+ mod.this_method_does_not_exist
+ end
+
+ assert_match(/undefined method.+this_method_does_not_exist.+for.+Module/, err.to_s)
+ end
+end
diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb
index 636f827fe3..c8751fbc57 100644
--- a/test/ruby/test_numeric.rb
+++ b/test/ruby/test_numeric.rb
@@ -267,12 +267,7 @@ class TestNumeric < Test::Unit::TestCase
assert_raise(ArgumentError) { 1.step(10, "1") { } }
assert_raise(ArgumentError) { 1.step(10, "1").size }
assert_raise(TypeError) { 1.step(10, nil) { } }
- assert_nothing_raised { 1.step(10, 0).size }
assert_nothing_raised { 1.step(10, nil).size }
- assert_nothing_raised { 1.step(by: 0, to: nil) }
- assert_nothing_raised { 1.step(by: 0, to: nil).size }
- assert_nothing_raised { 1.step(by: 0) }
- assert_nothing_raised { 1.step(by: 0).size }
assert_nothing_raised { 1.step(by: nil) }
assert_nothing_raised { 1.step(by: nil).size }
@@ -292,13 +287,26 @@ class TestNumeric < Test::Unit::TestCase
assert_raise(ArgumentError, bug9811) { 1.step(10, 1, by: 11) {} }
assert_raise(ArgumentError, bug9811) { 1.step(10, 1, by: 11).size }
-
- e = assert_warn(/Using the last argument as keyword parameters is deprecated/) {
- 1.step(10, {by: "1"})
- }
- assert_warn('') {
- assert_raise(ArgumentError) {e.size}
- }
+ feature15573 = "[ruby-core:91324] [Feature #15573]"
+ assert_raise(ArgumentError, feature15573) { 1.step(10, 0) }
+ assert_raise(ArgumentError, feature15573) { 1.step(10, by: 0) }
+ assert_raise(ArgumentError, feature15573) { 1.step(10, 0) { break } }
+ assert_raise(ArgumentError, feature15573) { 1.step(10, by: 0) { break } }
+ assert_raise(ArgumentError, feature15573) { 42.step(by: 0, to: -Float::INFINITY) }
+ assert_raise(ArgumentError, feature15573) { 42.step(by: 0, to: 42.5) }
+ assert_raise(ArgumentError, feature15573) { 4.2.step(by: 0.0) }
+ assert_raise(ArgumentError, feature15573) { 4.2.step(by: -0.0) }
+ assert_raise(ArgumentError, feature15573) { 42.step(by: 0.0, to: 44) }
+ assert_raise(ArgumentError, feature15573) { 42.step(by: 0.0, to: 0) }
+ assert_raise(ArgumentError, feature15573) { 42.step(by: -0.0, to: 44) }
+ assert_raise(ArgumentError, feature15573) { bignum.step(by: 0) }
+ assert_raise(ArgumentError, feature15573) { bignum.step(by: 0.0) }
+ assert_raise(ArgumentError, feature15573) { bignum.step(by: 0, to: bignum+1) }
+ assert_raise(ArgumentError, feature15573) { bignum.step(by: 0, to: 0) }
+
+ e = 1.step(10, {by: "1"})
+ assert_raise(TypeError) {e.next}
+ assert_raise(TypeError) {e.size}
assert_equal(bignum*2+1, (-bignum).step(bignum, 1).size)
assert_equal(bignum*2, (-bignum).step(bignum-1, 1).size)
@@ -325,8 +333,6 @@ class TestNumeric < Test::Unit::TestCase
assert_step [], [2, 1, 3]
assert_step [], [-2, -1, -3]
- assert_step [3, 3, 3, 3], [3, by: 0], inf: true
- assert_step [3, 3, 3, 3], [3, by: 0, to: 42], inf: true
assert_step [10], [10, 1, -bignum]
assert_step [], [1, 0, Float::INFINITY]
@@ -336,19 +342,6 @@ class TestNumeric < Test::Unit::TestCase
assert_step [10, 11, 12, 13], [10], inf: true
assert_step [10, 9, 8, 7], [10, by: -1], inf: true
assert_step [10, 9, 8, 7], [10, by: -1, to: nil], inf: true
-
- assert_step [42, 42, 42, 42], [42, by: 0, to: -Float::INFINITY], inf: true
- assert_step [42, 42, 42, 42], [42, by: 0, to: 42.5], inf: true
- assert_step [4.2, 4.2, 4.2, 4.2], [4.2, by: 0.0], inf: true
- assert_step [4.2, 4.2, 4.2, 4.2], [4.2, by: -0.0], inf: true
- assert_step [42.0, 42.0, 42.0, 42.0], [42, by: 0.0, to: 44], inf: true
- assert_step [42.0, 42.0, 42.0, 42.0], [42, by: 0.0, to: 0], inf: true
- assert_step [42.0, 42.0, 42.0, 42.0], [42, by: -0.0, to: 44], inf: true
-
- assert_step [bignum]*4, [bignum, by: 0], inf: true
- assert_step [bignum]*4, [bignum, by: 0.0], inf: true
- assert_step [bignum]*4, [bignum, by: 0, to: bignum+1], inf: true
- assert_step [bignum]*4, [bignum, by: 0, to: 0], inf: true
end
def test_step_bug15537
@@ -438,6 +431,26 @@ class TestNumeric < Test::Unit::TestCase
assert_equal(12, 12.pow(1, 10000000001), '[Bug #14259]')
assert_equal(12, 12.pow(1, 10000000002), '[Bug #14259]')
assert_equal(17298641040, 12.pow(72387894339363242, 243682743764), '[Bug #14259]')
+
+ integers = [-2, -1, 0, 1, 2, 3, 6, 1234567890123456789]
+ integers.each do |i|
+ assert_equal(0, i.pow(0, 1), '[Bug #17257]')
+ assert_equal(1, i.pow(0, 2))
+ assert_equal(1, i.pow(0, 3))
+ assert_equal(1, i.pow(0, 6))
+ assert_equal(1, i.pow(0, 1234567890123456789))
+
+ assert_equal(0, i.pow(0, -1))
+ assert_equal(-1, i.pow(0, -2))
+ assert_equal(-2, i.pow(0, -3))
+ assert_equal(-5, i.pow(0, -6))
+ assert_equal(-1234567890123456788, i.pow(0, -1234567890123456789))
+ end
+
+ assert_equal(0, 0.pow(2, 1))
+ assert_equal(0, 0.pow(3, 1))
+ assert_equal(0, 2.pow(3, 1))
+ assert_equal(0, -2.pow(3, 1))
end
end
diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb
index 442a7551a0..774b707742 100644
--- a/test/ruby/test_object.rb
+++ b/test/ruby/test_object.rb
@@ -5,7 +5,6 @@ require 'test/unit'
class TestObject < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -47,15 +46,27 @@ class TestObject < Test::Unit::TestCase
a = Object.new
def a.b; 2 end
+ c = a.clone
+ assert_equal(false, c.frozen?)
+ assert_equal(false, a.frozen?)
+ assert_equal(2, c.b)
+
+ c = a.clone(freeze: true)
+ assert_equal(true, c.frozen?)
+ assert_equal(false, a.frozen?)
+ assert_equal(2, c.b)
+
a.freeze
c = a.clone
assert_equal(true, c.frozen?)
+ assert_equal(true, a.frozen?)
assert_equal(2, c.b)
assert_raise(ArgumentError) {a.clone(freeze: [])}
d = a.clone(freeze: false)
def d.e; 3; end
assert_equal(false, d.frozen?)
+ assert_equal(true, a.frozen?)
assert_equal(2, d.b)
assert_equal(3, d.e)
@@ -75,6 +86,30 @@ class TestObject < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /\u{1f4a9}/) do
Object.new.clone(freeze: x)
end
+
+ c = Class.new do
+ attr_reader :f
+ end
+ o = c.new
+ def o.initialize_clone(_, freeze: true)
+ @f = freeze
+ super
+ end
+ clone = o.clone
+ assert_kind_of c, clone
+ assert_equal true, clone.f
+ clone = o.clone(freeze: false)
+ assert_kind_of c, clone
+ assert_equal false, clone.f
+
+ class << o
+ remove_method(:initialize_clone)
+ end
+ def o.initialize_clone(_)
+ super
+ end
+ assert_kind_of c, o.clone
+ assert_raise(ArgumentError) { o.clone(freeze: false) }
end
def test_init_dupclone
@@ -324,6 +359,7 @@ class TestObject < Test::Unit::TestCase
o = Object.new
def o.to_s; 1; end
assert_raise(TypeError) { String(o) }
+ o.singleton_class.remove_method(:to_s)
def o.to_s; "o"; end
assert_equal("o", String(o))
def o.to_str; "O"; end
@@ -336,6 +372,7 @@ class TestObject < Test::Unit::TestCase
o = Object.new
def o.to_a; 1; end
assert_raise(TypeError) { Array(o) }
+ o.singleton_class.remove_method(:to_a)
def o.to_a; [1]; end
assert_equal([1], Array(o))
def o.to_ary; [2]; end
@@ -353,6 +390,7 @@ class TestObject < Test::Unit::TestCase
o = Object.new
def o.to_hash; {a: 1, b: 2}; end
assert_equal({a: 1, b: 2}, Hash(o))
+ o.singleton_class.remove_method(:to_hash)
def o.to_hash; 9; end
assert_raise(TypeError) { Hash(o) }
end
@@ -361,6 +399,7 @@ class TestObject < Test::Unit::TestCase
o = Object.new
def o.to_i; nil; end
assert_raise(TypeError) { Integer(o) }
+ o.singleton_class.remove_method(:to_i)
def o.to_i; 42; end
assert_equal(42, Integer(o))
def o.respond_to?(*) false; end
@@ -595,7 +634,7 @@ class TestObject < Test::Unit::TestCase
called = []
p.singleton_class.class_eval do
- define_method(:respond_to?) do |a|
+ define_method(:respond_to?) do |a, priv = false|
called << [:respond_to?, a]
false
end
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index b42314b765..d0790c7463 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -452,7 +452,7 @@ class TestRubyOptimization < Test::Unit::TestCase
end
def test_tailcall_not_to_grow_stack
- skip 'currently JIT-ed code always creates a new stack frame' if RubyVM::MJIT.enabled?
+ skip 'currently JIT-ed code always creates a new stack frame' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
bug16161 = '[ruby-core:94881]'
tailcall("#{<<-"begin;"}\n#{<<~"end;"}")
@@ -701,16 +701,16 @@ class TestRubyOptimization < Test::Unit::TestCase
def test_block_parameter_should_not_create_objects
assert_separately [], <<-END
- #
def foo &b
end
h1 = {}; h2 = {}
- ObjectSpace.count_objects(h1) # reharsal
+ ObjectSpace.count_objects(h1) # rehearsal
+ GC.start; GC.disable # to disable GC while foo{}
ObjectSpace.count_objects(h1)
foo{}
ObjectSpace.count_objects(h2)
- assert_equal 0, h2[:TOTAL] - h1[:TOTAL]
+ assert_equal 0, h2[:T_DATA] - h1[:T_DATA] # Proc is T_DATA
END
end
diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb
index 1e909bce1b..d316a00b47 100644
--- a/test/ruby/test_parse.rb
+++ b/test/ruby/test_parse.rb
@@ -6,7 +6,6 @@ require 'stringio'
class TestParse < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -399,7 +398,6 @@ class TestParse < Test::Unit::TestCase
def test_arg2
o = Object.new
-
assert_nothing_raised do
eval <<-END, nil, __FILE__, __LINE__+1
def o.foo(a=42,*r,z,&b); b.call(r.inject(a*1000+z*100, :+)); end
@@ -411,6 +409,7 @@ class TestParse < Test::Unit::TestCase
assert_equal(-42100, o.foo(1) {|x| -x })
assert_raise(ArgumentError) { o.foo() }
+ o = Object.new
assert_nothing_raised do
eval <<-END, nil, __FILE__, __LINE__+1
def o.foo(a=42,z,&b); b.call(a*1000+z*100); end
@@ -420,6 +419,7 @@ class TestParse < Test::Unit::TestCase
assert_equal(-42100, o.foo(1) {|x| -x } )
assert_raise(ArgumentError) { o.foo() }
+ o = Object.new
assert_nothing_raised do
eval <<-END, nil, __FILE__, __LINE__+1
def o.foo(*r,z,&b); b.call(r.inject(z*100, :+)); end
@@ -562,6 +562,21 @@ class TestParse < Test::Unit::TestCase
assert_syntax_error("\"\\M-\x01\"", 'Invalid escape character syntax')
assert_syntax_error("\"\\M-\\C-\x01\"", 'Invalid escape character syntax')
assert_syntax_error("\"\\C-\\M-\x01\"", 'Invalid escape character syntax')
+
+ e = assert_syntax_error('"\c\u0000"', 'Invalid escape character syntax')
+ assert_equal(' ^~~~'"\n", e.message.lines.last)
+ e = assert_syntax_error('"\c\U0000"', 'Invalid escape character syntax')
+ assert_equal(' ^~~~'"\n", e.message.lines.last)
+
+ e = assert_syntax_error('"\C-\u0000"', 'Invalid escape character syntax')
+ assert_equal(' ^~~~~'"\n", e.message.lines.last)
+ e = assert_syntax_error('"\C-\U0000"', 'Invalid escape character syntax')
+ assert_equal(' ^~~~~'"\n", e.message.lines.last)
+
+ e = assert_syntax_error('"\M-\u0000"', 'Invalid escape character syntax')
+ assert_equal(' ^~~~~'"\n", e.message.lines.last)
+ e = assert_syntax_error('"\M-\U0000"', 'Invalid escape character syntax')
+ assert_equal(' ^~~~~'"\n", e.message.lines.last)
end
def test_question
@@ -599,6 +614,8 @@ class TestParse < Test::Unit::TestCase
assert_syntax_error('%s', /unterminated quoted string/)
assert_syntax_error('%ss', /unknown type/)
assert_syntax_error('%z()', /unknown type/)
+ assert_syntax_error("%\u3042", /unknown type/)
+ assert_syntax_error("%q\u3042", /unknown type/)
end
def test_symbol
@@ -722,13 +739,13 @@ x = __ENCODING__
end
def test_float
- assert_equal(1.0/0, eval("1e10000"))
+ assert_predicate(assert_warning(/out of range/) {eval("1e10000")}, :infinite?)
assert_syntax_error('1_E', /trailing `_'/)
assert_syntax_error('1E1E1', /unexpected constant/)
end
def test_global_variable
- assert_equal(nil, eval('$-x'))
+ assert_equal(nil, assert_warning(/not initialized/) {eval('$-x')})
assert_equal(nil, eval('alias $preserve_last_match $&'))
assert_equal(nil, eval('alias $& $test_parse_foobarbazqux'))
$test_parse_foobarbazqux = nil
@@ -821,13 +838,13 @@ x = __ENCODING__
end
def test_assign_in_conditional
- assert_nothing_raised do
+ assert_warning(/`= literal' in conditional/) do
eval <<-END, nil, __FILE__, __LINE__+1
(x, y = 1, 2) ? 1 : 2
END
end
- assert_nothing_raised do
+ assert_warning(/`= literal' in conditional/) do
eval <<-END, nil, __FILE__, __LINE__+1
if @x = true
1
@@ -839,13 +856,13 @@ x = __ENCODING__
end
def test_literal_in_conditional
- assert_nothing_raised do
+ assert_warning(/string literal in condition/) do
eval <<-END, nil, __FILE__, __LINE__+1
"foo" ? 1 : 2
END
end
- assert_nothing_raised do
+ assert_warning(/regex literal in condition/) do
x = "bar"
eval <<-END, nil, __FILE__, __LINE__+1
/foo#{x}baz/ ? 1 : 2
@@ -858,13 +875,13 @@ x = __ENCODING__
END
end
- assert_nothing_raised do
+ assert_warning(/string literal in flip-flop/) do
eval <<-END, nil, __FILE__, __LINE__+1
("foo".."bar") ? 1 : 2
END
end
- assert_nothing_raised do
+ assert_warning(/literal in condition/) do
x = "bar"
eval <<-END, nil, __FILE__, __LINE__+1
:"foo#{"x"}baz" ? 1 : 2
@@ -1172,6 +1189,122 @@ x = __ENCODING__
assert_equal(1, ex.message.scan(w).size, "same #{w.inspect} warning should be just once")
end
+ def eval_separately(code)
+ Class.new.class_eval(code)
+ end
+
+ def assert_raise_separately(error, message, code)
+ assert_raise_with_message(error, message) do
+ eval_separately(code)
+ end
+ end
+
+ def assert_ractor_shareable(obj)
+ assert Ractor.shareable?(obj), ->{"Expected #{mu_pp(obj)} to be ractor shareable"}
+ end
+
+ def assert_not_ractor_shareable(obj)
+ assert !Ractor.shareable?(obj), ->{"Expected #{mu_pp(obj)} not to be ractor shareable"}
+ end
+
+ def test_shareable_constant_value_invalid
+ assert_warning(/invalid value/) do
+ assert_valid_syntax("# shareable_constant_value: invalid-option", verbose: true)
+ end
+ end
+
+ def test_shareable_constant_value_ignored
+ assert_warning(/ignored/) do
+ assert_valid_syntax("nil # shareable_constant_value: true", verbose: true)
+ end
+ end
+
+ def test_shareable_constant_value_simple
+ obj = [['unsharable_value']]
+ a, b, c = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: experimental_everything
+ A = [[1]]
+ # shareable_constant_value: none
+ B = [[2]]
+ # shareable_constant_value: literal
+ C = [["shareable", "constant#{nil}"]]
+ D = A
+
+ [A, B, C]
+ end;
+ assert_ractor_shareable(a)
+ assert_not_ractor_shareable(b)
+ assert_ractor_shareable(c)
+ assert_equal([1], a[0])
+ assert_ractor_shareable(a[0])
+
+ a, obj = eval_separately(<<~'end;')
+ # shareable_constant_value: experimental_copy
+ obj = [["unshareable"]]
+ A = obj
+ [A, obj]
+ end;
+
+ assert_ractor_shareable(a)
+ assert_not_ractor_shareable(obj)
+ assert_equal obj, a
+ assert !obj.equal?(a)
+ end
+
+ def test_shareable_constant_value_nested
+ a, b = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: none
+ class X
+ # shareable_constant_value: experimental_everything
+ var = [[1]]
+ A = var
+ end
+ B = []
+ [X::A, B]
+ end;
+ assert_ractor_shareable(a)
+ assert_not_ractor_shareable(b)
+ assert_equal([1], a[0])
+ assert_ractor_shareable(a[0])
+ end
+
+ def test_shareable_constant_value_unshareable_literal
+ assert_raise_separately(Ractor::IsolationError, /unshareable/,
+ "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: literal
+ C = ["Not " + "shareable"]
+ end;
+ end
+
+ def test_shareable_constant_value_nonliteral
+ assert_raise_separately(Ractor::IsolationError, /unshareable/, "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: literal
+ var = [:not_frozen]
+ C = var
+ end;
+
+ assert_raise_separately(Ractor::IsolationError, /unshareable/, "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: literal
+ D = begin [] end
+ end;
+ end
+
+ def test_shareable_constant_value_unfrozen
+ assert_raise_separately(Ractor::Error, /does not freeze object correctly/,
+ "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: experimental_everything
+ o = Object.new
+ def o.freeze; self; end
+ C = [o]
+ end;
+ end
+
=begin
def test_past_scope_variable
assert_warning(/past scope/) {catch {|tag| eval("BEGIN{throw tag}; tap {a = 1}; a")}}
diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb
index 2afa823d53..e4c7507ac4 100644
--- a/test/ruby/test_pattern_matching.rb
+++ b/test/ruby/test_pattern_matching.rb
@@ -272,7 +272,7 @@ class TestPatternMatching < Test::Unit::TestCase
end
assert_syntax_error(%q{
- 0 in [a, a]
+ 0 => [a, a]
}, /duplicated variable name/)
end
@@ -736,6 +736,73 @@ END
end
end
+ def test_find_pattern
+ [0, 1, 2] => [*, 1 => a, *]
+ assert_equal(1, a)
+
+ [0, 1, 2] => [*a, 1 => b, *c]
+ assert_equal([0], a)
+ assert_equal(1, b)
+ assert_equal([2], c)
+
+ assert_block do
+ case [0, 1, 2]
+ in [*, 9, *]
+ false
+ else
+ true
+ end
+ end
+
+ assert_block do
+ case [0, 1, 2]
+ in [*, Integer, String, *]
+ false
+ else
+ true
+ end
+ end
+
+ [0, 1, 2] => [*a, 1 => b, 2 => c, *d]
+ assert_equal([0], a)
+ assert_equal(1, b)
+ assert_equal(2, c)
+ assert_equal([], d)
+
+ case [0, 1, 2]
+ in *, 1 => a, *;
+ assert_equal(1, a)
+ end
+
+ assert_block do
+ case [0, 1, 2]
+ in String(*, 1, *)
+ false
+ in Array(*, 1, *)
+ true
+ end
+ end
+
+ assert_block do
+ case [0, 1, 2]
+ in String[*, 1, *]
+ false
+ in Array[*, 1, *]
+ true
+ end
+ end
+
+ # https://bugs.ruby-lang.org/issues/17534
+ assert_block do
+ case [0, 1, 2]
+ in x
+ true
+ in [*, 2, *]
+ false
+ end
+ end
+ end
+
def test_hash_pattern
assert_block do
[{}, C.new({})].all? do |i|
@@ -1105,6 +1172,10 @@ END
end
end
+ def test_nomatchingpatternerror
+ assert_equal(StandardError, NoMatchingPatternError.superclass)
+ end
+
def test_invalid_syntax
assert_syntax_error(%q{
case 0
@@ -1208,6 +1279,94 @@ END
################################################################
+ class CDeconstructCache
+ def initialize(v)
+ @v = v
+ end
+
+ def deconstruct
+ @v.shift
+ end
+ end
+
+ def test_deconstruct_cache
+ assert_block do
+ case CDeconstructCache.new([[0]])
+ in [1]
+ in [0]
+ true
+ end
+ end
+
+ assert_block do
+ case CDeconstructCache.new([[0, 1]])
+ in [1,]
+ in [0,]
+ true
+ end
+ end
+
+ assert_block do
+ case CDeconstructCache.new([[[0]]])
+ in [[1]]
+ in [[*a]]
+ a == [0]
+ end
+ end
+
+ assert_block do
+ case CDeconstructCache.new([[0]])
+ in [x] if x > 0
+ in [0]
+ true
+ end
+ end
+
+ assert_block do
+ case CDeconstructCache.new([[0]])
+ in []
+ in [1] | [0]
+ true
+ end
+ end
+
+ assert_block do
+ case CDeconstructCache.new([[0]])
+ in [1] => _
+ in [0] => _
+ true
+ end
+ end
+
+ assert_block do
+ case CDeconstructCache.new([[0]])
+ in C[0]
+ in CDeconstructCache[0]
+ true
+ end
+ end
+
+ assert_block do
+ case [CDeconstructCache.new([[0], [1]])]
+ in [[1]]
+ false
+ in [[1]]
+ true
+ end
+ end
+
+ assert_block do
+ case CDeconstructCache.new([[0, :a, 1]])
+ in [*, String => x, *]
+ false
+ in [*, Symbol => x, *]
+ x == :a
+ end
+ end
+ end
+
+ ################################################################
+
class TestPatternMatchingRefinements < Test::Unit::TestCase
class C1
def deconstruct
@@ -1306,19 +1465,22 @@ END
################################################################
- def test_modifier_in
- 1 in a
+ def test_one_line
+ 1 => a
assert_equal 1, a
assert_raise(NoMatchingPatternError) do
- {a: 1} in {a: 0}
+ {a: 1} => {a: 0}
end
- assert_syntax_error("if {} in {a:}; end", /void value expression/)
+ assert_syntax_error("if {} => {a:}; end", /void value expression/)
assert_syntax_error(%q{
- 1 in a, b
+ 1 => a, b
}, /unexpected/, '[ruby-core:95098]')
assert_syntax_error(%q{
- 1 in a:
+ 1 => a:
}, /unexpected/, '[ruby-core:95098]')
+
+ assert_equal true, (1 in 1)
+ assert_equal false, (1 in 2)
end
def assert_experimental_warning(code)
@@ -1328,14 +1490,15 @@ END
assert_warn('') {eval(code)}
Warning[:experimental] = true
- assert_warn(/Pattern matching is experimental/) {eval(code)}
+ assert_warn(/is experimental/) {eval(code)}
ensure
Warning[:experimental] = w
end
def test_experimental_warning
- assert_experimental_warning("case 0; in 0; end")
- assert_experimental_warning("0 in 0")
+ assert_experimental_warning("case [0]; in [*, 0, *]; end")
+ assert_experimental_warning("0 => 0")
+ assert_experimental_warning("0 in a")
end
end
END_of_GUARD
diff --git a/test/ruby/test_primitive.rb b/test/ruby/test_primitive.rb
index 19af44ad32..f1db934000 100644
--- a/test/ruby/test_primitive.rb
+++ b/test/ruby/test_primitive.rb
@@ -26,24 +26,31 @@ class TestRubyPrimitive < Test::Unit::TestCase
assert_equal 4, c
end
- C = 1
- class A
- Const = 1
- class B
- Const = 2
- class C
- Const = 3
- def const
- Const
+ C_Setup = -> do
+ remove_const :C if defined? ::TestRubyPrimitive::C
+ remove_const :A if defined? ::TestRubyPrimitive::A
+
+ C = 1
+ class A
+ Const = 1
+ class B
+ Const = 2
+ class C
+ Const = 3
+ def const
+ Const
+ end
end
end
end
+ (1..2).map {
+ A::B::C::Const
+ }
end
- (1..2).map {
- A::B::C::Const
- }
def test_constant
+ C_Setup.call
+
assert_equal 1, C
assert_equal 1, C
assert_equal 1, A::Const
@@ -145,42 +152,60 @@ class TestRubyPrimitive < Test::Unit::TestCase
assert_equal 7, ($test_ruby_primitive_gvar = 7)
end
- class A7
- @@c = 1
- def m
- @@c += 1
+ A7_Setup = -> do
+ remove_const :A7 if defined? TestRubyPrimitive::A7
+
+ class A7
+ @@c = 1
+ def m
+ @@c += 1
+ end
end
end
def test_cvar_from_instance_method
+ A7_Setup.call
+
assert_equal 2, A7.new.m
assert_equal 3, A7.new.m
assert_equal 4, A7.new.m
end
- class A8
- @@c = 1
- class << self
- def m
- @@c += 1
+ A8_Setup = -> do
+ remove_const :A8 if defined? TestRubyPrimitive::A8
+
+ class A8
+ @@c = 1
+ class << self
+ def m
+ @@c += 1
+ end
end
end
end
def test_cvar_from_singleton_method
+ A8_Setup.call
+
assert_equal 2, A8.m
assert_equal 3, A8.m
assert_equal 4, A8.m
end
- class A9
- @@c = 1
- def self.m
- @@c += 1
+ A9_Setup = -> do
+ remove_const :A8 if defined? TestRubyPrimitive::A8
+
+ class A9
+ @@c = 1
+ def self.m
+ @@c += 1
+ end
end
end
def test_cvar_from_singleton_method2
+ A9_Setup.call
+
assert_equal 2, A9.m
assert_equal 3, A9.m
assert_equal 4, A9.m
@@ -199,6 +224,9 @@ class TestRubyPrimitive < Test::Unit::TestCase
@iv += 2
assert_equal 4, @iv
+ # init @@cv
+ @@cv = nil
+
@@cv ||= 1
assert_equal 1, @@cv
@@cv &&= 2
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index 3f0d599a04..5f2f797992 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -4,7 +4,6 @@ require 'test/unit'
class TestProc < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -53,16 +52,14 @@ class TestProc < Test::Unit::TestCase
assert_equal(5, x)
end
- def assert_arity(n)
+ def assert_arity(n, &block)
meta = class << self; self; end
- b = assert_warn(/Capturing the given block using Proc\.new is deprecated/) do
- Proc.new
- end
+ b = Proc.new(&block)
meta.class_eval {
- remove_method(:foo) if method_defined?(:foo)
- define_method(:foo, b)
+ remove_method(:foo_arity) if method_defined?(:foo_arity)
+ define_method(:foo_arity, b)
}
- assert_equal(n, method(:foo).arity)
+ assert_equal(n, method(:foo_arity).arity)
end
def test_arity
@@ -139,6 +136,14 @@ class TestProc < Test::Unit::TestCase
lambda { x }
end
+ def m_nest0(&block)
+ block
+ end
+
+ def m_nest(&block)
+ [m_nest0(&block), m_nest0(&block)]
+ end
+
def test_eq
a = m(1)
b = m(2)
@@ -150,6 +155,8 @@ class TestProc < Test::Unit::TestCase
a = lambda {|x| lambda {} }.call(1)
b = lambda {}
assert_not_equal(a, b, "[ruby-dev:22601]")
+
+ assert_equal(*m_nest{}, "[ruby-core:84583] Feature #14627")
end
def test_block_par
@@ -263,7 +270,7 @@ class TestProc < Test::Unit::TestCase
def test_curry_given_blocks
b = lambda {|x, y, &blk| blk.call(x + y) }.curry
- b = b.call(2) { raise }
+ b = assert_warning(/given block not used/) {b.call(2) { raise }}
b = b.call(3) {|x| x + 4 }
assert_equal(9, b)
end
@@ -273,7 +280,7 @@ class TestProc < Test::Unit::TestCase
assert_equal(false, l.lambda?)
assert_equal(false, l.curry.lambda?, '[ruby-core:24127]')
assert_equal(false, proc(&l).lambda?)
- assert_equal(false, lambda(&l).lambda?)
+ assert_equal(false, assert_deprecated_warning {lambda(&l)}.lambda?)
assert_equal(false, Proc.new(&l).lambda?)
l = lambda {}
assert_equal(true, l.lambda?)
@@ -283,6 +290,49 @@ class TestProc < Test::Unit::TestCase
assert_equal(true, Proc.new(&l).lambda?)
end
+ def self.helper_test_warn_lamda_with_passed_block &b
+ lambda(&b)
+ end
+
+ def self.def_lambda_warning name, warn
+ define_method(name, proc do
+ prev = Warning[:deprecated]
+ assert_warn warn do
+ Warning[:deprecated] = true
+ yield
+ end
+ ensure
+ Warning[:deprecated] = prev
+ end)
+ end
+
+ def_lambda_warning 'test_lambda_warning_normal', '' do
+ lambda{}
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_lambda', '' do
+ b = lambda{}
+ lambda(&b)
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_symbol_proc', '' do
+ lambda(&:to_s)
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_proc', /deprecated/ do
+ b = proc{}
+ lambda(&b)
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_block', /deprecated/ do
+ helper_test_warn_lamda_with_passed_block{}
+ end
+
+ def_lambda_warning 'test_lambda_warning_pass_block_symbol_proc', '' do
+ # Symbol#to_proc returns lambda
+ helper_test_warn_lamda_with_passed_block(&:to_s)
+ end
+
def test_curry_ski_fib
s = proc {|f, g, x| f[x][g[x]] }.curry
k = proc {|x, y| x }.curry
@@ -383,7 +433,7 @@ class TestProc < Test::Unit::TestCase
def test_proc_lambda
assert_raise(ArgumentError) { proc }
- assert_raise(ArgumentError) { lambda }
+ assert_raise(ArgumentError) { assert_warn(/deprecated/) {lambda} }
o = Object.new
def o.foo
@@ -391,14 +441,18 @@ class TestProc < Test::Unit::TestCase
1.times { b = lambda }
b
end
- assert_raise(ArgumentError) {o.foo { :foo }.call}
+ assert_raise(ArgumentError) do
+ assert_deprecated_warning {o.foo { :foo }}.call
+ end
- def o.foo(&b)
+ def o.bar(&b)
b = nil
1.times { b = lambda }
b
end
- assert_raise(ArgumentError) {o.foo { :foo }.call}
+ assert_raise(ArgumentError) do
+ assert_deprecated_warning {o.bar { :foo }}.call
+ end
end
def test_arity2
@@ -784,6 +838,33 @@ class TestProc < Test::Unit::TestCase
assert_equal [[1, 2], Proc, :x], (pr.call(1, 2){|x| x})
end
+ def test_proc_args_only_rest
+ pr = proc {|*c| c }
+ assert_equal [], pr.call()
+ assert_equal [1], pr.call(1)
+ assert_equal [[1]], pr.call([1])
+ assert_equal [1, 2], pr.call(1,2)
+ assert_equal [[1, 2]], pr.call([1,2])
+ end
+
+ def test_proc_args_rest_kw
+ pr = proc {|*c, a: 1| [c, a] }
+ assert_equal [[], 1], pr.call()
+ assert_equal [[1], 1], pr.call(1)
+ assert_equal [[[1]], 1], pr.call([1])
+ assert_equal [[1, 2], 1], pr.call(1,2)
+ assert_equal [[[1, 2]], 1], pr.call([1,2])
+ end
+
+ def test_proc_args_rest_kwsplat
+ pr = proc {|*c, **kw| [c, kw] }
+ assert_equal [[], {}], pr.call()
+ assert_equal [[1], {}], pr.call(1)
+ assert_equal [[[1]], {}], pr.call([1])
+ assert_equal [[1, 2], {}], pr.call(1,2)
+ assert_equal [[[1, 2]], {}], pr.call([1,2])
+ end
+
def test_proc_args_pos_rest_post_block
pr = proc {|a,b,*c,d,e,&f|
[a, b, c, d, e, f.class, f&&f.call(:x)]
@@ -1107,6 +1188,16 @@ class TestProc < Test::Unit::TestCase
assert_equal([[1, 2], [[1, 2, 3], {a: 1}], [[1, 2, 3], {a: 1}]], arr)
end
+ def test_proc_single_arg_with_keywords_accepted_and_yielded
+ def self.a
+ yield [], **{a: 1}
+ end
+ res = a do |arg, **opts|
+ [arg, opts]
+ end
+ assert_equal([[], {a: 1}], res)
+ end
+
def test_parameters
assert_equal([], proc {}.parameters)
assert_equal([], proc {||}.parameters)
@@ -1396,16 +1487,6 @@ class TestProc < Test::Unit::TestCase
end;
end
- def method_for_test_proc_without_block_for_symbol
- assert_warn(/Capturing the given block using Kernel#proc is deprecated/) do
- binding.eval('proc')
- end
- end
-
- def test_proc_without_block_for_symbol
- assert_equal('1', method_for_test_proc_without_block_for_symbol(&:to_s).call(1), '[Bug #14782]')
- end
-
def test_compose
f = proc {|x| x * 2}
g = proc {|x| x + 1}
@@ -1433,9 +1514,13 @@ class TestProc < Test::Unit::TestCase
def test_compose_with_lambda
f = lambda {|x| x * 2}
g = lambda {|x| x}
+ not_lambda = proc {|x| x}
assert_predicate((f << g), :lambda?)
assert_predicate((g >> f), :lambda?)
+ assert_predicate((not_lambda << f), :lambda?)
+ assert_not_predicate((f << not_lambda), :lambda?)
+ assert_not_predicate((not_lambda >> f), :lambda?)
end
def test_compose_with_method
@@ -1447,6 +1532,7 @@ class TestProc < Test::Unit::TestCase
assert_equal(6, (f << g).call(2))
assert_equal(5, (f >> g).call(2))
+ assert_predicate((f << g), :lambda?)
end
def test_compose_with_callable
@@ -1458,6 +1544,7 @@ class TestProc < Test::Unit::TestCase
assert_equal(6, (f << g).call(2))
assert_equal(5, (f >> g).call(2))
+ assert_predicate((f << g), :lambda?)
end
def test_compose_with_noncallable
@@ -1497,6 +1584,57 @@ class TestProc < Test::Unit::TestCase
assert_equal(42, Module.new { extend self
def m1(&b) b end; def m2(); m1 { next 42 } end }.m2.call)
end
+
+ def test_isolate
+ assert_raise_with_message ArgumentError, /\(a\)/ do
+ a = :a
+ Proc.new{p a}.isolate.call
+ end
+
+ assert_raise_with_message ArgumentError, /\(a\)/ do
+ a = :a
+ 1.times{
+ Proc.new{p a}.isolate.call
+ }
+ end
+
+ assert_raise_with_message ArgumentError, /yield/ do
+ Proc.new{yield}.isolate.call
+ end
+
+ # binding
+
+ :a.tap{|a|
+ :b.tap{|b|
+ Proc.new{
+ :c.tap{|c|
+ assert_equal :c, eval('c')
+
+ assert_raise_with_message SyntaxError, /\`a\'/ do
+ eval('p a')
+ end
+
+ assert_raise_with_message SyntaxError, /\`b\'/ do
+ eval('p b')
+ end
+
+ assert_raise_with_message SyntaxError, /can not yield from isolated Proc/ do
+ eval('p yield')
+ end
+
+ assert_equal :c, binding.local_variable_get(:c)
+
+ assert_raise_with_message NameError, /local variable \`a\' is not defined/ do
+ binding.local_variable_get(:a)
+ end
+
+ assert_equal [:c], local_variables
+ assert_equal [:c], binding.local_variables
+ }
+ }.isolate.call
+ }
+ }
+ end if proc{}.respond_to? :isolate
end
class TestProcKeywords < Test::Unit::TestCase
@@ -1505,29 +1643,15 @@ class TestProcKeywords < Test::Unit::TestCase
g = ->(kw) { kw.merge(:a=>2) }
assert_equal(2, (f >> g).call(a: 3)[:a])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (f << g).call(a: 3)[:a])
- end
+ assert_raise(ArgumentError) { (f << g).call(a: 3)[:a] }
assert_equal(2, (f >> g).call(a: 3)[:a])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (f << g).call({a: 3})[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(2, (f >> g).call({a: 3})[:a])
- end
+ assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] }
assert_equal(2, (g << f).call(a: 3)[:a])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (g >> f).call(a: 3)[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(2, (g << f).call({a: 3})[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (g >> f).call({a: 3})[:a])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (f << g).call(**{})[:a])
- end
+ assert_raise(ArgumentError) { (g >> f).call(a: 3)[:a] }
+ assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (f << g).call(**{})[:a] }
assert_equal(2, (f >> g).call(**{})[:a])
end
@@ -1535,29 +1659,15 @@ class TestProcKeywords < Test::Unit::TestCase
f = ->(**kw) { kw.merge(:a=>1) }.method(:call)
g = ->(kw) { kw.merge(:a=>2) }.method(:call)
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (f << g).call(a: 3)[:a])
- end
+ assert_raise(ArgumentError) { (f << g).call(a: 3)[:a] }
assert_equal(2, (f >> g).call(a: 3)[:a])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (f << g).call({a: 3})[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(2, (f >> g).call({a: 3})[:a])
- end
+ assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] }
assert_equal(2, (g << f).call(a: 3)[:a])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (g >> f).call(a: 3)[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(2, (g << f).call({a: 3})[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (g >> f).call({a: 3})[:a])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (f << g).call(**{})[:a])
- end
+ assert_raise(ArgumentError) { (g >> f).call(a: 3)[:a] }
+ assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (f << g).call(**{})[:a] }
assert_equal(2, (f >> g).call(**{})[:a])
end
@@ -1569,29 +1679,15 @@ class TestProcKeywords < Test::Unit::TestCase
def g.<<(f) to_proc << f end
def g.>>(f) to_proc >> f end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (f << g).call(a: 3)[:a])
- end
+ assert_raise(ArgumentError) { (f << g).call(a: 3)[:a] }
assert_equal(2, (f >> g).call(a: 3)[:a])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (f << g).call({a: 3})[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(2, (f >> g).call({a: 3})[:a])
- end
+ assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] }
assert_equal(2, (g << f).call(a: 3)[:a])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (g >> f).call(a: 3)[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(2, (g << f).call({a: 3})[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method is defined here/m) do
- assert_equal(1, (g >> f).call({a: 3})[:a])
- end
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*The called method `call'/m) do
- assert_equal(1, (f << g).call(**{})[:a])
- end
+ assert_raise(ArgumentError) { (g >> f).call(a: 3)[:a] }
+ assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (f << g).call(**{})[:a] }
assert_equal(2, (f >> g).call(**{})[:a])
f = ->(kw) { kw.merge(:a=>1) }
@@ -1602,29 +1698,15 @@ class TestProcKeywords < Test::Unit::TestCase
def g.>>(f) to_proc >> f end
assert_equal(1, (f << g).call(a: 3)[:a])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(2, (f >> g).call(a: 3)[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(1, (f << g).call({a: 3})[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(2, (f >> g).call({a: 3})[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(2, (g << f).call(a: 3)[:a])
- end
+ assert_raise(ArgumentError) { (f >> g).call(a: 3)[:a] }
+ assert_raise(ArgumentError) { (f << g).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (f >> g).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (g << f).call(a: 3)[:a] }
assert_equal(1, (g >> f).call(a: 3)[:a])
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(2, (g << f).call({a: 3})[:a])
- end
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(1, (g >> f).call({a: 3})[:a])
- end
+ assert_raise(ArgumentError) { (g << f).call({a: 3})[:a] }
+ assert_raise(ArgumentError) { (g >> f).call({a: 3})[:a] }
assert_equal(1, (f << g).call(**{})[:a])
- assert_warn(/Passing the keyword argument as the last hash parameter is deprecated.*Using the last argument as keyword parameters is deprecated.*The called method `call'/m) do
- assert_equal(2, (f >> g).call(**{})[:a])
- end
+ assert_raise(ArgumentError) { (f >> g).call(**{})[:a] }
end
end
diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
index ab723c6f63..d1b9d8a478 100644
--- a/test/ruby/test_process.rb
+++ b/test/ruby/test_process.rb
@@ -338,6 +338,13 @@ class TestProcess < Test::Unit::TestCase
ensure
ENV["hmm"] = old
end
+
+ assert_raise_with_message(ArgumentError, /fo=fo/) {
+ system({"fo=fo"=>"ha"}, *ENVCOMMAND)
+ }
+ assert_raise_with_message(ArgumentError, /\u{30c0}=\u{30e1}/) {
+ system({"\u{30c0}=\u{30e1}"=>"ha"}, *ENVCOMMAND)
+ }
end
def test_execopt_env_path
@@ -1418,6 +1425,8 @@ class TestProcess < Test::Unit::TestCase
assert_equal(s.to_i >> 1, s >> 1)
assert_equal(false, s.stopped?)
assert_equal(nil, s.stopsig)
+
+ assert_equal(s, Marshal.load(Marshal.dump(s)))
end
end
@@ -1435,6 +1444,8 @@ class TestProcess < Test::Unit::TestCase
assert_equal(expected,
[s.exited?, s.signaled?, s.stopped?, s.success?],
"[s.exited?, s.signaled?, s.stopped?, s.success?]")
+
+ assert_equal(s, Marshal.load(Marshal.dump(s)))
end
end
@@ -1449,6 +1460,27 @@ class TestProcess < Test::Unit::TestCase
"[s.exited?, s.signaled?, s.stopped?, s.success?]")
assert_equal("#<Process::Status: pid #{ s.pid } SIGQUIT (signal #{ s.termsig })>",
s.inspect.sub(/ \(core dumped\)(?=>\z)/, ''))
+
+ assert_equal(s, Marshal.load(Marshal.dump(s)))
+ end
+ end
+
+ def test_status_fail
+ ret = Process::Status.wait($$)
+ assert_instance_of(Process::Status, ret)
+ assert_equal(-1, ret.pid)
+ end
+
+
+ def test_status_wait
+ IO.popen([RUBY, "-e", "gets"], "w") do |io|
+ pid = io.pid
+ assert_nil(Process::Status.wait(pid, Process::WNOHANG))
+ io.puts
+ ret = Process::Status.wait(pid)
+ assert_instance_of(Process::Status, ret)
+ assert_equal(pid, ret.pid)
+ assert_predicate(ret, :exited?)
end
end
@@ -1598,6 +1630,34 @@ class TestProcess < Test::Unit::TestCase
rescue NotImplementedError
end
+ if Process::UID.respond_to?(:from_name)
+ def test_uid_from_name
+ if u = Etc.getpwuid(Process.uid)
+ assert_equal(Process.uid, Process::UID.from_name(u.name), u.name)
+ end
+ assert_raise_with_message(ArgumentError, /\u{4e0d 5b58 5728}/) {
+ Process::UID.from_name("\u{4e0d 5b58 5728}")
+ }
+ end
+ end
+
+ if Process::GID.respond_to?(:from_name) && !RUBY_PLATFORM.include?("android")
+ def test_gid_from_name
+ if g = Etc.getgrgid(Process.gid)
+ assert_equal(Process.gid, Process::GID.from_name(g.name), g.name)
+ end
+ expected_excs = [ArgumentError]
+ expected_excs << Errno::ENOENT if defined?(Errno::ENOENT)
+ expected_excs << Errno::ESRCH if defined?(Errno::ESRCH) # WSL 2 actually raises Errno::ESRCH
+ expected_excs << Errno::EBADF if defined?(Errno::EBADF)
+ expected_excs << Errno::EPERM if defined?(Errno::EPERM)
+ exc = assert_raise(*expected_excs) do
+ Process::GID.from_name("\u{4e0d 5b58 5728}") # fu son zai ("absent" in Kanji)
+ end
+ assert_match(/\u{4e0d 5b58 5728}/, exc.message) if exc.is_a?(ArgumentError)
+ end
+ end
+
def test_uid_re_exchangeable_p
r = Process::UID.re_exchangeable?
assert_include([true, false], r)
@@ -1646,7 +1706,7 @@ class TestProcess < Test::Unit::TestCase
Process.wait pid
assert_send [sig_r, :wait_readable, 5], 'self-pipe not readable'
end
- if RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE. It may trigger extra SIGCHLD.
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE. It may trigger extra SIGCHLD.
assert_equal [true], signal_received.uniq, "[ruby-core:19744]"
else
assert_equal [true], signal_received, "[ruby-core:19744]"
@@ -2260,8 +2320,6 @@ EOS
pid = fork {Process.kill(:QUIT, parent)}
IO.popen([ruby, -'--disable=gems'], -'r+'){}
Process.wait(pid)
- $stdout.puts
- $stdout.flush
end
INPUT
end if defined?(fork)
@@ -2383,7 +2441,7 @@ EOS
end
w.close
assert_equal "exec failed\n", r.gets
- vals = r.gets.chomp.split.map!(&:to_i)
+ vals = r.gets.split.map!(&:to_i)
assert_operator vals[0], :>, vals[1], vals.inspect
_, status = Process.waitpid2(pid)
end
@@ -2458,4 +2516,17 @@ EOS
Process.wait spawn(RUBY, "-e", "exit 13")
assert_same(Process.last_status, $?)
end
+
+ def test_last_status_failure
+ assert_nil system("sad")
+ assert_not_predicate $?, :success?
+ assert_equal $?.exitstatus, 127
+ end
+
+ def test_exec_failure_leaves_no_child
+ assert_raise(Errno::ENOENT) do
+ spawn('inexistent_command')
+ end
+ assert_empty(Process.waitall)
+ end
end
diff --git a/test/ruby/test_rand.rb b/test/ruby/test_rand.rb
index 939d17bdf7..13b7329269 100644
--- a/test/ruby/test_rand.rb
+++ b/test/ruby/test_rand.rb
@@ -2,14 +2,13 @@
require 'test/unit'
class TestRand < Test::Unit::TestCase
- def assert_random_int(ws, m, init = 0)
+ def assert_random_int(m, init = 0, iterate: 5)
srand(init)
rnds = [Random.new(init)]
rnds2 = [rnds[0].dup]
rnds3 = [rnds[0].dup]
- ws.each_with_index do |w, i|
- w = w.to_i
- assert_equal(w, rand(m))
+ iterate.times do |i|
+ w = rand(m)
rnds.each do |rnd|
assert_equal(w, rnd.rand(m))
end
@@ -27,133 +26,97 @@ class TestRand < Test::Unit::TestCase
end
def test_mt
- assert_random_int(%w(1067595299 955945823 477289528 4107218783 4228976476),
- 0x100000000, 0x00000456_00000345_00000234_00000123)
+ assert_random_int(0x100000000, 0x00000456_00000345_00000234_00000123)
end
def test_0x3fffffff
- assert_random_int(%w(209652396 398764591 924231285 404868288 441365315),
- 0x3fffffff)
+ assert_random_int(0x3fffffff)
end
def test_0x40000000
- assert_random_int(%w(209652396 398764591 924231285 404868288 441365315),
- 0x40000000)
+ assert_random_int(0x40000000)
end
def test_0x40000001
- assert_random_int(%w(209652396 398764591 924231285 441365315 192771779),
- 0x40000001)
+ assert_random_int(0x40000001)
end
def test_0xffffffff
- assert_random_int(%w(2357136044 2546248239 3071714933 3626093760 2588848963),
- 0xffffffff)
+ assert_random_int(0xffffffff)
end
def test_0x100000000
- assert_random_int(%w(2357136044 2546248239 3071714933 3626093760 2588848963),
- 0x100000000)
+ assert_random_int(0x100000000)
end
def test_0x100000001
- assert_random_int(%w(2546248239 1277901399 243580376 1171049868 2051556033),
- 0x100000001)
+ assert_random_int(0x100000001)
end
def test_rand_0x100000000
- assert_random_int(%w(4119812344 3870378946 80324654 4294967296 410016213),
- 0x100000001, 311702798)
+ assert_random_int(0x100000001, 311702798)
end
def test_0x1000000000000
- assert_random_int(%w(11736396900911
- 183025067478208
- 197104029029115
- 130583529618791
- 180361239846611),
- 0x1000000000000)
+ assert_random_int(0x1000000000000)
end
def test_0x1000000000001
- assert_random_int(%w(187121911899765
- 197104029029115
- 180361239846611
- 236336749852452
- 208739549485656),
- 0x1000000000001)
+ assert_random_int(0x1000000000001)
end
def test_0x3fffffffffffffff
- assert_random_int(%w(900450186894289455
- 3969543146641149120
- 1895649597198586619
- 827948490035658087
- 3203365596207111891),
- 0x3fffffffffffffff)
+ assert_random_int(0x3fffffffffffffff)
end
def test_0x4000000000000000
- assert_random_int(%w(900450186894289455
- 3969543146641149120
- 1895649597198586619
- 827948490035658087
- 3203365596207111891),
- 0x4000000000000000)
+ assert_random_int(0x4000000000000000)
end
def test_0x4000000000000001
- assert_random_int(%w(900450186894289455
- 3969543146641149120
- 1895649597198586619
- 827948490035658087
- 2279347887019741461),
- 0x4000000000000001)
+ assert_random_int(0x4000000000000001)
end
def test_0x10000000000
- ws = %w(455570294424 1073054410371 790795084744 2445173525 1088503892627)
- assert_random_int(ws, 0x10000000000, 3)
+ assert_random_int(0x10000000000, 3)
end
def test_0x10000
- ws = %w(2732 43567 42613 52416 45891)
- assert_random_int(ws, 0x10000)
+ assert_random_int(0x10000)
+ end
+
+ def assert_same_numbers(type, *nums)
+ nums.each do |n|
+ assert_instance_of(type, n)
+ end
+ x = nums.shift
+ nums.each do |n|
+ assert_equal(x, n)
+ end
+ x
end
def test_types
- srand(0)
- rnd = Random.new(0)
- assert_equal(44, rand(100.0))
- assert_equal(44, rnd.rand(100))
- assert_equal(1245085576965981900420779258691, rand((2**100).to_f))
- assert_equal(1245085576965981900420779258691, rnd.rand(2**100))
- assert_equal(914679880601515615685077935113, rand(-(2**100).to_f))
+ o = Object.new
+ class << o
+ def to_int; 100; end
+ def class; Integer; end
+ end
srand(0)
- rnd = Random.new(0)
- assert_equal(997707939797331598305742933184, rand(2**100))
- assert_equal(997707939797331598305742933184, rnd.rand(2**100))
- assert_in_delta(0.602763376071644, rand((2**100).coerce(0).first),
- 0.000000000000001)
- assert_raise(ArgumentError) {rnd.rand((2**100).coerce(0).first)}
+ nums = [100.0, (2**100).to_f, (2**100), o, o, o].map do |m|
+ k = Integer
+ assert_kind_of(k, x = rand(m), m.inspect)
+ [m, k, x]
+ end
+ assert_kind_of(Integer, rand(-(2**100).to_f))
srand(0)
rnd = Random.new(0)
- assert_in_delta(0.548813503927325, rand(nil),
- 0.000000000000001)
- assert_in_delta(0.548813503927325, rnd.rand(),
- 0.000000000000001)
- srand(0)
- rnd = Random.new(0)
- o = Object.new
- def o.to_int; 100; end
- assert_equal(44, rand(o))
- assert_equal(44, rnd.rand(o))
- assert_equal(47, rand(o))
- assert_equal(47, rnd.rand(o))
- assert_equal(64, rand(o))
- assert_equal(64, rnd.rand(o))
+ rnd2 = Random.new(0)
+ nums.each do |m, k, x|
+ assert_same_numbers(m.class, Random.rand(m), rnd.rand(m), rnd2.rand(m))
+ end
end
def test_srand
@@ -163,10 +126,13 @@ class TestRand < Test::Unit::TestCase
srand(2**100)
rnd = Random.new(2**100)
- %w(3258412053).each {|w|
- assert_equal(w.to_i, rand(0x100000000))
- assert_equal(w.to_i, rnd.rand(0x100000000))
- }
+ r = 3.times.map do
+ assert_same_numbers(Integer, rand(0x100000000), rnd.rand(0x100000000))
+ end
+ srand(2**100)
+ r.each do |n|
+ assert_same_numbers(Integer, n, rand(0x100000000))
+ end
end
def test_shuffle
@@ -177,17 +143,17 @@ class TestRand < Test::Unit::TestCase
end
def test_big_seed
- assert_random_int(%w(2757555016), 0x100000000, 2**1000000-1)
+ assert_random_int(0x100000000, 2**1000000-1)
end
def test_random_gc
r = Random.new(0)
- %w(2357136044 2546248239 3071714933).each do |w|
- assert_equal(w.to_i, r.rand(0x100000000))
+ 3.times do
+ assert_kind_of(Integer, r.rand(0x100000000))
end
GC.start
- %w(3626093760 2588848963 3684848379).each do |w|
- assert_equal(w.to_i, r.rand(0x100000000))
+ 3.times do
+ assert_kind_of(Integer, r.rand(0x100000000))
end
end
@@ -223,179 +189,56 @@ class TestRand < Test::Unit::TestCase
def test_random_dup
r1 = Random.new(0)
r2 = r1.dup
- %w(2357136044 2546248239 3071714933).each do |w|
- assert_equal(w.to_i, r1.rand(0x100000000))
- end
- %w(2357136044 2546248239 3071714933).each do |w|
- assert_equal(w.to_i, r2.rand(0x100000000))
+ 3.times do
+ assert_same_numbers(Integer, r1.rand(0x100000000), r2.rand(0x100000000))
end
r2 = r1.dup
- %w(3626093760 2588848963 3684848379).each do |w|
- assert_equal(w.to_i, r1.rand(0x100000000))
- end
- %w(3626093760 2588848963 3684848379).each do |w|
- assert_equal(w.to_i, r2.rand(0x100000000))
+ 3.times do
+ assert_same_numbers(Integer, r1.rand(0x100000000), r2.rand(0x100000000))
end
end
- def test_random_state
- state = <<END
-3877134065023083674777481835852171977222677629000095857864323111193832400974413
-4782302161934463784850675209112299537259006497924090422596764895633625964527441
-6943943249411681406395713106007661119327771293929504639878577616749110507385924
-0173026285378896836022134086386136835407107422834685854738117043791709411958489
-3504364936306163473541948635570644161010981140452515307286926529085424765299100
-1255453260115310687580777474046203049197643434654645011966794531914127596390825
-0832232869378617194193100828000236737535657699356156021286278281306055217995213
-8911536025132779573429499813926910299964681785069915877910855089314686097947757
-2621451199734871158015842198110309034467412292693435515184023707918034746119728
-8223459645048255809852819129671833854560563104716892857257229121211527031509280
-2390605053896565646658122125171846129817536096211475312518457776328637574563312
-8113489216547503743508184872149896518488714209752552442327273883060730945969461
-6568672445225657265545983966820639165285082194907591432296265618266901318398982
-0560425129536975583916120558652408261759226803976460322062347123360444839683204
-9868507788028894111577023917218846128348302845774997500569465902983227180328307
-3735301552935104196244116381766459468172162284042207680945316590536094294865648
-5953156978630954893391701383648157037914019502853776972615500142898763385846315
-8457790690531675205213829055442306187692107777193071680668153335688203945049935
-3404449910419303330872435985327845889440458370416464132629866593538629877042969
-7589948685901343135964343582727302330074331803900821801076139161904900333497836
-6627028345784450211920229170280462474456504317367706849373957309797251052447898
-8436235456995644876515032202483449807136139063937892187299239634252391529822163
-9187055268750679730919937006195967184206072757082920250075756273182004964087790
-3812024063897424219316687828337007888030994779068081666133751070479581394604974
-6022215489604777611774245181115126041390161592199230774968475944753915533936834
-4740049163514318351045644344358598159463605453475585370226041981040238023241538
-4958436364776113598408428801867643946791659645708540669432995503575075657406359
-8086928867900590554805639837071298576728564946552163206007997000988745940681607
-4542883814997403673656291618517107133421335645430345871041730410669209035640945
-5024601618318371192091626092482640364669969307766919645222516407626038616667754
-5781148898846306894862390724358039251444333889446128074209417936830253204064223
-3424784857908022314095011879203259864909560830176189727132432100010493659154644
-8407326292884826469503093409465946018496358514999175268200846200025235441426140
-7783386235191526371372655894290440356560751680752191224383460972099834655086068
-9989413443881686756951804138910911737670495391762470293978321414964443502180391
-4665982575919524372985773336921990352313629822677022891307943536442258282401255
-5387646898976193134193506239982621725093291970351083631367582570375381334759004
-1784150668048523676387894646666460369896619585113435743180899362844070393586212
-5023920017185866399742380706352739465848708746963693663004068892056705603018655
-8686663087894205699555906146534549176352859823832196938386172810274748624517052
-8356758650653040545267425513047130342286119889879774951060662713807133125543465
-5104086026298674827575216701372513525846650644773241437066782037334367982012148
-7987782004646896468089089826267467005660035604553432197455616078731159778086155
-9443250946037119223468305483694093795324036812927501783593256716590840500905291
-2096608538205270323065573109227029887731553399324547696295234105140157179430410
-4003109602564833086703863221058381556776789018351726488797845637981974580864082
-1630093543020854542240690897858757985640869209737744458407777584279553258261599
-0246922348101147034463235613998979344685018577901996218099622190722307356620796
-5137485271371502385527388080824050288371607602101805675021790116223360483508538
-8832149997794718410946818866375912486788005950091851067237358294899771385995876
-7088239104394332452501033090159333224995108984871426750597513314521294001864578
-2353528356752869732412552685554334966798888534847483030947310518891788722418172
-6008607577773612004956373863580996793809969715725508939568919714424871639667201
-7922255031431159347210833846575355772055570279673262115911154370983086189948124
-4653677615895887099814174914248255026619941911735341818489822197472499295786997
-7728418516719104857455960900092226749725407204388193002835497055305427730656889
-1508308778869166073740855838213112709306743479676740893150000714099064468263284
-1873435518542972182497755500300784177067568586395485329021157235696300013490087
-2866571034916258390528533374944905429089028336079264760836949419754851422499614
-5732326011260304142074554782259843903215064144396140106592193961703288125005023
-5334375212799817540775536847622032852415253966587517800661605905489339306359573
-2234947905196298436841723673626428243649931398749552780311877734063703985375067
-1239508613417041942487245370152912391885566432830659640677893488723724763120121
-4111855277511356759926232894062814360449757490961653026194107761340614059045172
-1123363102660719217740126157997033682099769790976313166682432732518101889210276
-9574144065390305904944821051736021310524344626348851573631697771556587859836330
-6997324121866564283654784470215100159122764509197570402997911258816526554863326
-9877535269005418736225944874608987238997316999444215865249840762640949599725696
-0773083894168959823152054508672272612355108904098579447774398451678239199426513
-3439507737424049578587487505080347686371029156845461151278198605267053408259090
-3158676794894709281917034995611352710898103415304769654883981727681820369090169
-9295163908214854813365413456264812190842699054830709079275249714169405719140093
-1347572458245530016346604698682269779841803667099480215265926316505737171177810
-9969036572310084022695109125200937135540995157279354438704321290061646592229860
-0156566013602344870223183295508278359111174872740360473845615437106413256386849
-2286259982118315248148847764929974917157683083659364623458927512616369119194574
-2254080
-END
- state = state.split.join.to_i
- r = Random.new(0)
+ def test_random_bytes
srand(0)
- assert_equal(state, r.instance_eval { state })
- assert_equal(state, Random.instance_eval { state })
- r.rand(0x100)
- assert_equal(state, r.instance_eval { state })
- end
-
- def test_random_left
r = Random.new(0)
- assert_equal(1, r.instance_eval { left })
- r.rand(0x100)
- assert_equal(624, r.instance_eval { left })
- r.rand(0x100)
- assert_equal(623, r.instance_eval { left })
- srand(0)
- assert_equal(1, Random.instance_eval { left })
- rand(0x100)
- assert_equal(624, Random.instance_eval { left })
- rand(0x100)
- assert_equal(623, Random.instance_eval { left })
- end
- def test_random_bytes
- assert_random_bytes(Random.new(0))
- end
-
- def assert_random_bytes(r)
- srand(0)
assert_equal("", r.bytes(0))
assert_equal("", Random.bytes(0))
- x = "\xAC".force_encoding("ASCII-8BIT")
- assert_equal(x, r.bytes(1))
+
+ x = r.bytes(1)
+ assert_equal(1, x.bytesize)
assert_equal(x, Random.bytes(1))
- x = "/\xAA\xC4\x97u\xA6\x16\xB7\xC0\xCC".force_encoding("ASCII-8BIT")
- assert_equal(x, r.bytes(10))
+
+ x = r.bytes(10)
+ assert_equal(10, x.bytesize)
assert_equal(x, Random.bytes(10))
end
def test_random_range
srand(0)
r = Random.new(0)
- %w(9 5 8).each {|w|
- assert_equal(w.to_i, rand(5..9))
- assert_equal(w.to_i, r.rand(5..9))
- }
- %w(-237 731 383).each {|w|
- assert_equal(w.to_i, rand(-1000..1000))
- assert_equal(w.to_i, r.rand(-1000..1000))
- }
- %w(1267650600228229401496703205382
- 1267650600228229401496703205384
- 1267650600228229401496703205383).each do |w|
- assert_equal(w.to_i, rand(2**100+5..2**100+9))
- assert_equal(w.to_i, r.rand(2**100+5..2**100+9))
- end
-
- v = rand(3.1..4)
- assert_instance_of(Float, v, '[ruby-core:24679]')
- assert_include(3.1..4, v)
-
- v = r.rand(3.1..4)
- assert_instance_of(Float, v, '[ruby-core:24679]')
- assert_include(3.1..4, v)
-
now = Time.now
- assert_equal(now, rand(now..now))
- assert_equal(now, r.rand(now..now))
+ [5..9, -1000..1000, 2**100+5..2**100+9, 3.1..4, now..(now+2)].each do |range|
+ 3.times do
+ x = rand(range)
+ assert_instance_of(range.first.class, x)
+ assert_equal(x, r.rand(range))
+ assert_include(range, x)
+ end
+ end
end
def test_random_float
r = Random.new(0)
- assert_in_delta(0.5488135039273248, r.rand, 0.0001)
- assert_in_delta(0.7151893663724195, r.rand, 0.0001)
- assert_in_delta(0.6027633760716439, r.rand, 0.0001)
- assert_in_delta(1.0897663659937937, r.rand(2.0), 0.0001)
- assert_in_delta(5.3704626067153264e+29, r.rand((2**100).to_f), 10**25)
+ 3.times do
+ assert_include(0...1.0, r.rand)
+ end
+ [2.0, (2**100).to_f].each do |x|
+ range = 0...x
+ 3.times do
+ assert_include(range, r.rand(x), "rand(#{x})")
+ end
+ end
assert_raise(Errno::EDOM, Errno::ERANGE) { r.rand(1.0 / 0.0) }
assert_raise(Errno::EDOM, Errno::ERANGE) { r.rand(0.0 / 0.0) }
@@ -403,10 +246,11 @@ END
assert_raise(Errno::EDOM) {r.rand(..1)}
r = Random.new(0)
- assert_in_delta(1.5488135039273248, r.rand(1.0...2.0), 0.0001, '[ruby-core:24655]')
- assert_in_delta(1.7151893663724195, r.rand(1.0...2.0), 0.0001, '[ruby-core:24655]')
- assert_in_delta(7.027633760716439, r.rand(1.0...11.0), 0.0001, '[ruby-core:24655]')
- assert_in_delta(3.0897663659937937, r.rand(2.0...4.0), 0.0001, '[ruby-core:24655]')
+ [1.0...2.0, 1.0...11.0, 2.0...4.0].each do |range|
+ 3.times do
+ assert_include(range, r.rand(range), "[ruby-core:24655] rand(#{range})")
+ end
+ end
assert_nothing_raised {r.rand(-Float::MAX..Float::MAX)}
end
@@ -492,18 +336,6 @@ END
}
end
- def test_default
- r1 = Random::DEFAULT.dup
- r2 = Random::DEFAULT.dup
- 3.times do
- x0 = rand
- x1 = r1.rand
- x2 = r2.rand
- assert_equal(x0, x1)
- assert_equal(x0, x2)
- end
- end
-
def test_marshal
bug3656 = '[ruby-core:31622]'
assert_raise(TypeError, bug3656) {
@@ -560,16 +392,19 @@ END
end
def test_default_seed
- assert_separately([], <<-End)
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ verbose, $VERBOSE = $VERBOSE, nil
seed = Random::DEFAULT::seed
rand1 = Random::DEFAULT::rand
+ $VERBOSE = verbose
rand2 = Random.new(seed).rand
assert_equal(rand1, rand2)
srand seed
rand3 = rand
assert_equal(rand1, rand3)
- End
+ end;
end
def test_urandom
diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb
index 3953b3ecc2..8ac1930be6 100644
--- a/test/ruby/test_range.rb
+++ b/test/ruby/test_range.rb
@@ -125,6 +125,13 @@ class TestRange < Test::Unit::TestCase
assert_raise(RangeError) { (1...).max(3) }
assert_raise(RangeError) { (..0).min {|a, b| a <=> b } }
+
+ assert_equal(2, (..2).max)
+ assert_raise(TypeError) { (...2).max }
+ assert_raise(TypeError) { (...2.0).max }
+
+ assert_equal(Float::INFINITY, (1..Float::INFINITY).max)
+ assert_nil((1..-Float::INFINITY).max)
end
def test_minmax
@@ -149,12 +156,15 @@ class TestRange < Test::Unit::TestCase
assert_equal(['a', 'c'], ('a'..'c').minmax)
assert_equal(['a', 'b'], ('a'...'c').minmax)
+
+ assert_equal([1, Float::INFINITY], (1..Float::INFINITY).minmax)
+ assert_equal([nil, nil], (1..-Float::INFINITY).minmax)
end
def test_initialize_twice
r = eval("1..2")
- assert_raise(NameError) { r.instance_eval { initialize 3, 4 } }
- assert_raise(NameError) { r.instance_eval { initialize_copy 3..4 } }
+ assert_raise(FrozenError) { r.instance_eval { initialize 3, 4 } }
+ assert_raise(FrozenError) { r.instance_eval { initialize_copy 3..4 } }
end
def test_uninitialized_range
@@ -261,8 +271,10 @@ class TestRange < Test::Unit::TestCase
assert_kind_of(Enumerator::ArithmeticSequence, (1..).step(2))
assert_raise(ArgumentError) { (0..10).step(-1) { } }
+ assert_raise(ArgumentError) { (0..10).step(0) }
assert_raise(ArgumentError) { (0..10).step(0) { } }
assert_raise(ArgumentError) { (0..).step(-1) { } }
+ assert_raise(ArgumentError) { (0..).step(0) }
assert_raise(ArgumentError) { (0..).step(0) { } }
a = []
@@ -293,6 +305,7 @@ class TestRange < Test::Unit::TestCase
(2**32-1 .. 2**32+1).step(2) {|x| a << x }
assert_equal([4294967295, 4294967297], a)
zero = (2**32).coerce(0).first
+ assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) }
assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } }
a = []
(2**32-1 .. ).step(2) {|x| a << x; break if a.size == 2 }
diff --git a/test/ruby/test_rational.rb b/test/ruby/test_rational.rb
index 5676b41445..fe9de64c4c 100644
--- a/test/ruby/test_rational.rb
+++ b/test/ruby/test_rational.rb
@@ -128,6 +128,13 @@ class Rational_Test < Test::Unit::TestCase
assert_raise(TypeError){Rational(Object.new, Object.new)}
assert_raise(TypeError){Rational(1, Object.new)}
+ bug12485 = '[ruby-core:75995] [Bug #12485]'
+ o = Object.new
+ def o.to_int; 1; end
+ assert_equal(1, Rational(o, 1), bug12485)
+ assert_equal(1, Rational(1, o), bug12485)
+ assert_equal(1, Rational(o, o), bug12485)
+
o = Object.new
def o.to_r; 1/42r; end
assert_equal(1/42r, Rational(o))
@@ -158,6 +165,14 @@ class Rational_Test < Test::Unit::TestCase
if (1.0/0).infinite?
assert_raise(FloatDomainError){Rational(1.0/0)}
end
+
+ bug16518 = "[ruby-core:96942] [Bug #16518]"
+ cls = Class.new(Numeric) do
+ def /(y); 42; end
+ def to_r; 1r; end
+ def to_int; 1; end
+ end
+ assert_equal(1/2r, Rational(cls.new, 2), bug16518)
end
def test_attr
@@ -841,6 +856,18 @@ class Rational_Test < Test::Unit::TestCase
assert_equal(nil, Rational(1, Object.new, exception: false))
}
+ bug12485 = '[ruby-core:75995] [Bug #12485]'
+ assert_nothing_raised(RuntimeError, bug12485) {
+ o = Object.new
+ def o.to_int; raise; end
+ assert_equal(nil, Rational(o, exception: false))
+ }
+ assert_nothing_raised(RuntimeError, bug12485) {
+ o = Object.new
+ def o.to_int; raise; end
+ assert_equal(nil, Rational(1, o, exception: false))
+ }
+
o = Object.new;
def o.to_r; raise; end
assert_nothing_raised(RuntimeError) {
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb
index 6fb04de5d6..ed31faec42 100644
--- a/test/ruby/test_refinement.rb
+++ b/test/ruby/test_refinement.rb
@@ -225,6 +225,8 @@ class TestRefinement < Test::Unit::TestCase
end
end
def test_method_should_use_refinements
+ skip if Minitest::Unit.current_repeat_count > 0
+
foo = Foo.new
assert_raise(NameError) { foo.method(:z) }
assert_equal("FooExt#z", FooExtClient.method_z(foo).call)
@@ -246,6 +248,8 @@ class TestRefinement < Test::Unit::TestCase
end
end
def test_instance_method_should_use_refinements
+ skip if Minitest::Unit.current_repeat_count > 0
+
foo = Foo.new
assert_raise(NameError) { Foo.instance_method(:z) }
assert_equal("FooExt#z", FooExtClient.instance_method_z(foo).bind(foo).call)
@@ -916,7 +920,7 @@ class TestRefinement < Test::Unit::TestCase
#{PrependAfterRefine_CODE}
undef PrependAfterRefine
}
- }, timeout: 30
+ }, timeout: 60
end
def test_prepend_after_refine
@@ -1648,7 +1652,6 @@ class TestRefinement < Test::Unit::TestCase
def test_reopen_refinement_module
assert_separately([], <<-"end;")
- $VERBOSE = nil
class C
end
@@ -1665,6 +1668,7 @@ class TestRefinement < Test::Unit::TestCase
module R
refine C do
+ alias m m
def m
:bar
end
@@ -2382,6 +2386,179 @@ class TestRefinement < Test::Unit::TestCase
assert_equal(0, Bug13446::GenericEnumerable.new.sum)
end
+ def test_unbound_refine_method
+ a = EnvUtil.labeled_class("A") do
+ def foo
+ self.class
+ end
+ end
+ b = EnvUtil.labeled_class("B")
+ bar = EnvUtil.labeled_module("R") do
+ break refine a do
+ def foo
+ super
+ end
+ end
+ end
+ assert_raise(TypeError) do
+ bar.instance_method(:foo).bind(b.new)
+ end
+ end
+
+ def test_refine_frozen_class
+ verbose_bak, $VERBOSE = $VERBOSE, nil
+ singleton_class.instance_variable_set(:@x, self)
+ class << self
+ c = Class.new do
+ def foo
+ :cfoo
+ end
+ end
+ foo = Module.new do
+ refine c do
+ def foo
+ :rfoo
+ end
+ end
+ end
+ using foo
+ @x.assert_equal(:rfoo, c.new.foo)
+ c.freeze
+ foo.module_eval do
+ refine c do
+ def foo
+ :rfoo2
+ end
+ def bar
+ :rbar
+ end
+ end
+ end
+ @x.assert_equal(:rfoo2, c.new.foo)
+ @x.assert_equal(:rbar, c.new.bar, '[ruby-core:71391] [Bug #11669]')
+ end
+ ensure
+ $VERBOSE = verbose_bak
+ end
+
+ # [Bug #17386]
+ def test_prepended_with_method_cache
+ foo = Class.new do
+ def foo
+ :Foo
+ end
+ end
+
+ code = Module.new do
+ def foo
+ :Code
+ end
+ end
+
+ _ext = Module.new do
+ refine foo do
+ def foo; end
+ end
+ end
+
+ obj = foo.new
+
+ assert_equal :Foo, obj.foo
+ foo.prepend code
+ assert_equal :Code, obj.foo
+ end
+
+ # [Bug #17417]
+ def test_prepended_with_method_cache_17417
+ assert_normal_exit %q{
+ module M
+ def hoge; end
+ end
+
+ module R
+ refine Hash do
+ def except *args; end
+ end
+ end
+
+ h = {}
+ h.method(:except) # put it on pCMC
+ Hash.prepend(M)
+ h.method(:except)
+ }
+ end
+
+ def test_defining_after_cached
+ klass = Class.new
+ refinement = Module.new { refine(klass) { def foo; end } }
+ klass.new.foo rescue nil # cache the refinement method entry
+ klass.define_method(:foo) { 42 }
+ assert_equal(42, klass.new.foo)
+ end
+
+ # [Bug #17806]
+ def test_two_refinements_for_prepended_class
+ assert_normal_exit %q{
+ module R1
+ refine Hash do
+ def foo; :r1; end
+ end
+ end
+
+ class Hash
+ prepend(Module.new)
+ end
+
+ class Hash
+ def foo; end
+ end
+
+ {}.method(:foo) # put it on pCMC
+
+ module R2
+ refine Hash do
+ def foo; :r2; end
+ end
+ end
+
+ {}.foo
+ }
+ end
+
+ # [Bug #17806]
+ def test_redefining_refined_for_prepended_class
+ klass = Class.new { def foo; end }
+ _refinement = Module.new do
+ refine(klass) { def foo; :refined; end }
+ end
+ klass.prepend(Module.new)
+ klass.new.foo # cache foo
+ klass.define_method(:foo) { :second }
+ assert_equal(:second, klass.new.foo)
+ end
+
+ class Bug17822
+ module Ext
+ refine(Bug17822) do
+ def foo = :refined
+ end
+ end
+
+ private(def foo = :not_refined)
+
+ module Client
+ using Ext
+ def self.call_foo
+ Bug17822.new.foo
+ end
+ end
+ end
+
+ # [Bug #17822]
+ def test_privatizing_refined_method
+ assert_equal(:refined, Bug17822::Client.call_foo)
+ end
+
private
def eval_using(mod, s)
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index 8709d05752..679a013cf0 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -5,7 +5,6 @@ require 'test/unit'
class TestRegexp < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -43,13 +42,14 @@ class TestRegexp < Test::Unit::TestCase
def test_yoshidam_net_20041111_1
s = "[\xC2\xA0-\xC3\xBE]"
- assert_match(Regexp.new(s, nil, "u"), "\xC3\xBE")
+ r = assert_deprecated_warning(/ignored/) {Regexp.new(s, nil, "u")}
+ assert_match(r, "\xC3\xBE")
end
def test_yoshidam_net_20041111_2
assert_raise(RegexpError) do
s = "[\xFF-\xFF]".force_encoding("utf-8")
- Regexp.new(s, nil, "u")
+ assert_warning(/ignored/) {Regexp.new(s, nil, "u")}
end
end
@@ -57,6 +57,17 @@ class TestRegexp < Test::Unit::TestCase
assert_equal('Ruby', 'Ruby'.sub(/[^a-z]/i, '-'))
end
+ def test_premature_end_char_property
+ ["\\p{",
+ "\\p{".dup.force_encoding("UTF-8"),
+ "\\p{".dup.force_encoding("US-ASCII")
+ ].each do |string|
+ assert_raise(RegexpError) do
+ Regexp.new(string)
+ end
+ end
+ end
+
def test_assert_normal_exit
# moved from knownbug. It caused core.
Regexp.union("a", "a")
@@ -254,6 +265,27 @@ class TestRegexp < Test::Unit::TestCase
assert_equal(re, re.match("foo").regexp)
end
+ def test_match_lambda_multithread
+ bug17507 = "[ruby-core:101901]"
+ str = "a-x-foo-bar-baz-z-b"
+
+ worker = lambda do
+ m = /foo-([A-Za-z0-9_\.]+)-baz/.match(str)
+ assert_equal("bar", m[1], bug17507)
+
+ # These two lines are needed to trigger the bug
+ File.exist? "/tmp"
+ str.gsub(/foo-bar-baz/, "foo-abc-baz")
+ end
+
+ def self. threaded_test(worker)
+ 6.times.map {Thread.new {10_000.times {worker.call}}}.each(&:join)
+ end
+
+ # The bug only occurs in a method calling a block/proc/lambda
+ threaded_test(worker)
+ end
+
def test_source
bug5484 = '[ruby-core:40364]'
assert_equal('', //.source)
@@ -469,7 +501,7 @@ class TestRegexp < Test::Unit::TestCase
def test_initialize
assert_raise(ArgumentError) { Regexp.new }
- assert_equal(/foo/, Regexp.new(/foo/, Regexp::IGNORECASE))
+ assert_equal(/foo/, assert_warning(/ignored/) {Regexp.new(/foo/, Regexp::IGNORECASE)})
assert_equal(Encoding.find("US-ASCII"), Regexp.new("b..", nil, "n").encoding)
assert_equal("bar", "foobarbaz"[Regexp.new("b..", nil, "n")])
@@ -561,7 +593,10 @@ class TestRegexp < Test::Unit::TestCase
assert_equal("bc", /../.match('abc', -2)[0])
assert_nil(/../.match("abc", -4))
assert_nil(/../.match("abc", 4))
- assert_equal('\x', /../n.match("\u3042" + '\x', 1)[0])
+
+ # use eval because only one warning is shown for the same regexp literal
+ pat = eval('/../n')
+ assert_equal('\x', assert_warning(/binary regexp/) {pat.match("\u3042" + '\x', 1)}[0])
r = nil
/.../.match("abc") {|m| r = m[0] }
@@ -637,7 +672,7 @@ class TestRegexp < Test::Unit::TestCase
def test_dup
assert_equal(//, //.dup)
- assert_raise(TypeError) { //.instance_eval { initialize_copy(nil) } }
+ assert_raise(TypeError) { //.dup.instance_eval { initialize_copy(nil) } }
end
def test_regsub
@@ -661,21 +696,10 @@ class TestRegexp < Test::Unit::TestCase
assert_equal('foobazquux/foobazquux', result, bug8856)
end
- def test_KCODE
- assert_nil($KCODE)
- assert_nothing_raised { $KCODE = nil }
- assert_equal(false, $=)
- assert_nothing_raised { $= = nil }
- end
-
- def test_KCODE_warning
- assert_warning(/variable \$KCODE is no longer effective; ignored/) { $KCODE = nil }
- assert_warning(/variable \$KCODE is no longer effective/) { $KCODE = nil }
- end
-
- def test_ignorecase_warning
- assert_warning(/variable \$= is no longer effective; ignored/) { $= = nil }
- assert_warning(/variable \$= is no longer effective/) { $= }
+ def test_ignorecase
+ v = assert_deprecated_warning(/variable \$= is no longer effective/) { $= }
+ assert_equal(false, v)
+ assert_deprecated_warning(/variable \$= is no longer effective; ignored/) { $= = nil }
end
def test_match_setter
@@ -742,11 +766,13 @@ class TestRegexp < Test::Unit::TestCase
end
def test_rindex_regexp
- assert_equal(3, "foobarbaz\u3042".rindex(/b../n, 5))
+ # use eval because only one warning is shown for the same regexp literal
+ pat = eval('/b../n')
+ assert_equal(3, assert_warning(/binary regexp/) {"foobarbaz\u3042".rindex(pat, 5)})
end
def assert_regexp(re, ss, fs = [], msg = nil)
- re = Regexp.new(re) unless re.is_a?(Regexp)
+ re = EnvUtil.suppress_warning {Regexp.new(re)} unless re.is_a?(Regexp)
ss = [ss] unless ss.is_a?(Array)
ss.each do |e, s|
s ||= e
@@ -779,7 +805,7 @@ class TestRegexp < Test::Unit::TestCase
check(/\A\80\z/, "80", ["\100", ""])
check(/\A\77\z/, "?")
check(/\A\78\z/, "\7" + '8', ["\100", ""])
- check(eval('/\A\Qfoo\E\z/'), "QfooE")
+ check(assert_warning(/Unknown escape/) {eval('/\A\Qfoo\E\z/')}, "QfooE")
check(/\Aa++\z/, "aaa")
check('\Ax]\z', "x]")
check(/x#foo/x, "x", "#foo")
@@ -823,8 +849,8 @@ class TestRegexp < Test::Unit::TestCase
check(/^(A+|B(?>\g<1>)*)[AC]$/, %w(AAAC BBBAAAAC), %w(BBBAAA))
check(/^()(?>\g<1>)*$/, "", "a")
check(/^(?>(?=a)(#{ "a" * 1000 }|))++$/, ["a" * 1000, "a" * 2000, "a" * 3000], ["", "a" * 500, "b" * 1000])
- check(eval('/^(?:a?)?$/'), ["", "a"], ["aa"])
- check(eval('/^(?:a+)?$/'), ["", "a", "aa"], ["ab"])
+ check(assert_warning(/nested repeat operator/) {eval('/^(?:a?)?$/')}, ["", "a"], ["aa"])
+ check(assert_warning(/nested repeat operator/) {eval('/^(?:a+)?$/')}, ["", "a", "aa"], ["ab"])
check(/^(?:a?)+?$/, ["", "a", "aa"], ["ab"])
check(/^a??[ab]/, [["a", "a"], ["a", "aa"], ["b", "b"], ["a", "ab"]], ["c"])
check(/^(?:a*){3,5}$/, ["", "a", "aa", "aaa", "aaaa", "aaaaa", "aaaaaa"], ["b"])
@@ -953,13 +979,13 @@ class TestRegexp < Test::Unit::TestCase
def test_posix_bracket
check(/\A[[:alpha:]0]\z/, %w(0 a), %w(1 .))
- check(eval('/\A[[:^alpha:]0]\z/'), %w(0 1 .), "a")
- check(eval('/\A[[:alpha\:]]\z/'), %w(a l p h a :), %w(b 0 1 .))
- check(eval('/\A[[:alpha:foo]0]\z/'), %w(0 a), %w(1 .))
+ check(assert_warning(/duplicated range/) {eval('/\A[[:^alpha:]0]\z/')}, %w(0 1 .), "a")
+ check(assert_warning(/duplicated range/) {eval('/\A[[:alpha\:]]\z/')}, %w(a l p h a :), %w(b 0 1 .))
+ check(assert_warning(/duplicated range/) {eval('/\A[[:alpha:foo]0]\z/')}, %w(0 a), %w(1 .))
check(/\A[[:xdigit:]&&[:alpha:]]\z/, "a", %w(g 0))
check('\A[[:abcdefghijklmnopqrstu:]]+\z', "[]")
failcheck('[[:alpha')
- failcheck('[[:alpha:')
+ assert_warning(/duplicated range/) {failcheck('[[:alpha:')}
failcheck('[[:alp:]]')
assert_match(/\A[[:digit:]]+\z/, "\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19")
@@ -1126,13 +1152,17 @@ class TestRegexp < Test::Unit::TestCase
end
def test_regexp_popped
- assert_nothing_raised { eval("a = 1; /\#{ a }/; a") }
- assert_nothing_raised { eval("a = 1; /\#{ a }/o; a") }
+ EnvUtil.suppress_warning do
+ assert_nothing_raised { eval("a = 1; /\#{ a }/; a") }
+ assert_nothing_raised { eval("a = 1; /\#{ a }/o; a") }
+ end
end
def test_invalid_fragment
bug2547 = '[ruby-core:27374]'
- assert_raise(SyntaxError, bug2547) {eval('/#{"\\\\"}y/')}
+ assert_raise(SyntaxError, bug2547) do
+ assert_warning(/ignored/) {eval('/#{"\\\\"}y/')}
+ end
end
def test_dup_warn
@@ -1172,7 +1202,8 @@ class TestRegexp < Test::Unit::TestCase
def test_raw_hyphen_and_tk_char_type_after_range
bug6853 = '[ruby-core:47115]'
# use Regexp.new instead of literal to ignore a parser warning.
- check(Regexp.new('[0-1-\\s]'), [' ', '-'], ['2', 'a'], bug6853)
+ re = assert_warning(/without escape/) {Regexp.new('[0-1-\\s]')}
+ check(re, [' ', '-'], ['2', 'a'], bug6853)
end
def test_error_message_on_failed_conversion
@@ -1208,6 +1239,20 @@ class TestRegexp < Test::Unit::TestCase
}
end
+ def test_quantifier_reduction
+ assert_equal('aa', eval('/(a+?)*/').match('aa')[0])
+ assert_equal('aa', eval('/(?:a+?)*/').match('aa')[0])
+
+ quantifiers = %w'? * + ?? *? +?'
+ quantifiers.product(quantifiers) do |q1, q2|
+ EnvUtil.suppress_warning do
+ r1 = eval("/(a#{q1})#{q2}/").match('aa')[0]
+ r2 = eval("/(?:a#{q1})#{q2}/").match('aa')[0]
+ assert_equal(r1, r2)
+ end
+ end
+ end
+
def test_once
pr1 = proc{|i| /#{i}/o}
assert_equal(/0/, pr1.call(0))
@@ -1299,6 +1344,15 @@ class TestRegexp < Test::Unit::TestCase
end
end
+ def test_invalid_group
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ assert_raise_with_message(RegexpError, /invalid conditional pattern/) do
+ Regexp.new("((?(1)x|x|)x)+")
+ end
+ end;
+ end
+
# This assertion is for porting x2() tests in testpy.py of Onigmo.
def assert_match_at(re, str, positions, msg = nil)
re = Regexp.new(re) unless re.is_a?(Regexp)
diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb
index a1adb4926f..9b658286c9 100644
--- a/test/ruby/test_require.rb
+++ b/test/ruby/test_require.rb
@@ -88,6 +88,7 @@ class TestRequire < Test::Unit::TestCase
end
def prepare_require_path(dir, encoding)
+ require 'enc/trans/single_byte'
Dir.mktmpdir {|tmp|
begin
require_path = File.join(tmp, dir, 'foo.rb').encode(encoding)
@@ -199,6 +200,7 @@ class TestRequire < Test::Unit::TestCase
end
def assert_syntax_error_backtrace
+ loaded_features = $LOADED_FEATURES.dup
Dir.mktmpdir do |tmp|
req = File.join(tmp, "test.rb")
File.write(req, ",\n")
@@ -208,6 +210,7 @@ class TestRequire < Test::Unit::TestCase
assert_not_nil(bt = e.backtrace, "no backtrace")
assert_not_empty(bt.find_all {|b| b.start_with? __FILE__}, proc {bt.inspect})
end
+ $LOADED_FEATURES.replace loaded_features
end
def test_require_syntax_error
@@ -388,6 +391,8 @@ class TestRequire < Test::Unit::TestCase
def test_relative
load_path = $:.dup
+ loaded_featrures = $LOADED_FEATURES.dup
+
$:.delete(".")
Dir.mktmpdir do |tmp|
Dir.chdir(tmp) do
@@ -407,6 +412,7 @@ class TestRequire < Test::Unit::TestCase
end
ensure
$:.replace(load_path) if load_path
+ $LOADED_FEATURES.replace loaded_featrures
end
def test_relative_symlink
@@ -525,6 +531,28 @@ class TestRequire < Test::Unit::TestCase
$".replace(features)
end
+ def test_default_loaded_features_encoding
+ Dir.mktmpdir {|tmp|
+ Dir.mkdir("#{tmp}/1")
+ Dir.mkdir("#{tmp}/2")
+ File.write("#{tmp}/1/bug18191-1.rb", "")
+ File.write("#{tmp}/2/bug18191-2.rb", "")
+ assert_separately(%W[-Eutf-8 -I#{tmp}/1 -], "#{<<~"begin;"}\n#{<<~'end;'}")
+ tmp = #{tmp.dump}"/2"
+ begin;
+ $:.unshift(tmp)
+ require "bug18191-1"
+ require "bug18191-2"
+ encs = [Encoding::US_ASCII, Encoding.find("filesystem")]
+ message = -> {
+ require "pp"
+ {filesystem: encs[1], **$".group_by(&:encoding)}.pretty_inspect
+ }
+ assert($".all? {|n| encs.include?(n.encoding)}, message)
+ end;
+ }
+ end
+
def test_require_changed_current_dir
bug7158 = '[ruby-core:47970]'
Dir.mktmpdir {|tmp|
@@ -764,6 +792,8 @@ class TestRequire < Test::Unit::TestCase
end if File.respond_to?(:mkfifo)
def test_loading_fifo_fd_leak
+ skip if RUBY_PLATFORM =~ /android/ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/android29-x86_64/ruby-master/log/20200419T124100Z.fail.html.gz
+
Tempfile.create(%w'fifo .rb') {|f|
f.close
File.unlink(f.path)
diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb
index 2842b63804..0d0f4b4d7e 100644
--- a/test/ruby/test_rubyoptions.rb
+++ b/test/ruby/test_rubyoptions.rb
@@ -8,7 +8,7 @@ require_relative '../lib/jit_support'
class TestRubyOptions < Test::Unit::TestCase
NO_JIT_DESCRIPTION =
- if RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
RUBY_DESCRIPTION.sub(/\+JIT /, '')
else
RUBY_DESCRIPTION
@@ -72,8 +72,9 @@ class TestRubyOptions < Test::Unit::TestCase
ENV['RUBYOPT'] = nil
assert_in_out_err(%w(-W0 -e) + ['p $-W'], "", %w(0), [])
assert_in_out_err(%w(-W1 -e) + ['p $-W'], "", %w(1), [])
- assert_in_out_err(%w(-Wx -e) + ['p $-W'], "", %w(1), [])
+ assert_in_out_err(%w(-Wx -e) + ['p $-W'], "", %w(2), [])
assert_in_out_err(%w(-W -e) + ['p $-W'], "", %w(2), [])
+ assert_in_out_err(%w(-We) + ['p $-W'], "", %w(2), [])
assert_in_out_err(%w(-w -W0 -e) + ['p $-W'], "", %w(0), [])
assert_in_out_err(%w(-W:deprecated -e) + ['p Warning[:deprecated]'], "", %w(true), [])
assert_in_out_err(%w(-W:no-deprecated -e) + ['p Warning[:deprecated]'], "", %w(false), [])
@@ -82,6 +83,7 @@ class TestRubyOptions < Test::Unit::TestCase
assert_in_out_err(%w(-W:qux), "", [], /unknown warning category: `qux'/)
assert_in_out_err(%w(-w -e) + ['p Warning[:deprecated]'], "", %w(true), [])
assert_in_out_err(%w(-W -e) + ['p Warning[:deprecated]'], "", %w(true), [])
+ assert_in_out_err(%w(-We) + ['p Warning[:deprecated]'], "", %w(true), [])
assert_in_out_err(%w(-e) + ['p Warning[:deprecated]'], "", %w(false), [])
code = 'puts "#{$VERBOSE}:#{Warning[:deprecated]}:#{Warning[:experimental]}"'
Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) do |t|
@@ -126,7 +128,7 @@ class TestRubyOptions < Test::Unit::TestCase
def test_verbose
assert_in_out_err(["-vve", ""]) do |r, e|
assert_match(VERSION_PATTERN, r[0])
- if RubyVM::MJIT.enabled? && !mjit_force_enabled? # checking -DMJIT_FORCE_ENABLE
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? && !mjit_force_enabled? # checking -DMJIT_FORCE_ENABLE
assert_equal(NO_JIT_DESCRIPTION, r[0])
else
assert_equal(RUBY_DESCRIPTION, r[0])
@@ -189,7 +191,7 @@ class TestRubyOptions < Test::Unit::TestCase
def test_version
assert_in_out_err(%w(--version)) do |r, e|
assert_match(VERSION_PATTERN, r[0])
- if RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
assert_equal(EnvUtil.invoke_ruby(['-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
else
assert_equal(RUBY_DESCRIPTION, r[0])
@@ -219,7 +221,7 @@ class TestRubyOptions < Test::Unit::TestCase
].each do |args|
assert_in_out_err(args) do |r, e|
assert_match(VERSION_PATTERN_WITH_JIT, r[0])
- if RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
+ if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # checking -DMJIT_FORCE_ENABLE
assert_equal(RUBY_DESCRIPTION, r[0])
else
assert_equal(EnvUtil.invoke_ruby(['--jit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
@@ -510,16 +512,18 @@ class TestRubyOptions < Test::Unit::TestCase
["case nil; when true", "end"],
["if false;", "end", "if true\nelse ", "end"],
["else", " end", "_ = if true\n"],
+ ["begin\n def f() = nil", "end"],
+ ["begin\n def self.f() = nil", "end"],
].each do
|b, e = 'end', pre = nil, post = nil|
src = ["#{pre}#{b}\n", " #{e}\n#{post}"]
k = b[/\A\s*(\S+)/, 1]
e = e[/\A\s*(\S+)/, 1]
- n = 2
- n += pre.count("\n") if pre
+ n = 1 + src[0].count("\n")
+ n1 = 1 + (pre ? pre.count("\n") : 0)
a.for("no directives with #{src}") do
- err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n-1}"]
+ err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"]
t.rewind
t.truncate(0)
t.puts src
@@ -538,7 +542,7 @@ class TestRubyOptions < Test::Unit::TestCase
end
a.for("false and true directives with #{src}") do
- err = ["#{t.path}:#{n+2}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n+1}"]
+ err = ["#{t.path}:#{n+2}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1+2}"]
t.rewind
t.truncate(0)
t.puts "# -*- warn-indent: false -*-"
@@ -560,7 +564,7 @@ class TestRubyOptions < Test::Unit::TestCase
end
a.for("BOM with #{src}") do
- err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n-1}"]
+ err = ["#{t.path}:#{n}: warning: mismatched indentations at '#{e}' with '#{k}' at #{n1}"]
t.rewind
t.truncate(0)
t.print "\u{feff}"
@@ -734,6 +738,8 @@ class TestRubyOptions < Test::Unit::TestCase
end
def assert_segv(args, message=nil)
+ skip if ENV['RUBY_ON_BUG']
+
test_stdin = ""
opt = SEGVTest::ExecOptions.dup
list = SEGVTest::ExpectedStderrList
@@ -1027,11 +1033,11 @@ class TestRubyOptions < Test::Unit::TestCase
err = !freeze ? [] : debug ? with_debug_pat : wo_debug_pat
[
['"foo" << "bar"', err],
- ['"foo#{123}bar" << "bar"', err],
+ ['"foo#{123}bar" << "bar"', []],
['+"foo#{123}bar" << "bar"', []],
- ['-"foo#{123}bar" << "bar"', freeze && debug ? with_debug_pat : wo_debug_pat],
+ ['-"foo#{123}bar" << "bar"', wo_debug_pat],
].each do |code, expected|
- assert_in_out_err(opt, code, [], expected, [opt, code])
+ assert_in_out_err(opt, code, [], expected, "#{opt} #{code}")
end
end
end
diff --git a/test/ruby/test_rubyvm.rb b/test/ruby/test_rubyvm.rb
index 7673d8dfbe..67d46e27ad 100644
--- a/test/ruby/test_rubyvm.rb
+++ b/test/ruby/test_rubyvm.rb
@@ -4,11 +4,11 @@ require 'test/unit'
class TestRubyVM < Test::Unit::TestCase
def test_stat
assert_kind_of Hash, RubyVM.stat
- assert_kind_of Integer, RubyVM.stat[:global_method_state]
+ assert_kind_of Integer, RubyVM.stat[:global_constant_state]
RubyVM.stat(stat = {})
assert_not_empty stat
- assert_equal stat[:global_method_state], RubyVM.stat(:global_method_state)
+ assert_equal stat[:global_constant_state], RubyVM.stat(:global_constant_state)
end
def test_stat_unknown
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 0c41f247be..2180c31d57 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -3,17 +3,21 @@ require 'test/unit'
class TestSetTraceFunc < Test::Unit::TestCase
def setup
- @original_compile_option = RubyVM::InstructionSequence.compile_option
- RubyVM::InstructionSequence.compile_option = {
- :trace_instruction => true,
- :specialized_instruction => false
- }
+ if defined?(RubyVM)
+ @original_compile_option = RubyVM::InstructionSequence.compile_option
+ RubyVM::InstructionSequence.compile_option = {
+ :trace_instruction => true,
+ :specialized_instruction => false
+ }
+ end
@target_thread = Thread.current
end
def teardown
set_trace_func(nil)
- RubyVM::InstructionSequence.compile_option = @original_compile_option
+ if defined?(RubyVM)
+ RubyVM::InstructionSequence.compile_option = @original_compile_option
+ end
@target_thread = nil
end
@@ -137,6 +141,10 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal(["c-call", 9, :set_trace_func, Kernel],
events.shift)
assert_equal([], events)
+
+ self.class.class_eval do
+ remove_const :Foo
+ end
end
def test_return # [ruby-dev:38701]
@@ -362,6 +370,11 @@ class TestSetTraceFunc < Test::Unit::TestCase
end
assert_equal([], events[:set])
assert_equal([], events[:add])
+
+ # cleanup
+ self.class.class_eval do
+ remove_const :ThreadTraceInnerClass
+ end
end
def test_trace_defined_method
@@ -472,8 +485,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
- [:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing],
- [:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self],
[:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1],
[:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
[:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing],
@@ -499,8 +510,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
[:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
[:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing],
- [:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing],
- [:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy],
[:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy],
[:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy],
[:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
@@ -607,8 +616,6 @@ CODE
[:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
- [:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing],
- [:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self],
[:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1],
[:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
[:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing],
@@ -634,8 +641,6 @@ CODE
[:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
[:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
[:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing],
- [:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing],
- [:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy],
[:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy],
[:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy],
[:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
@@ -942,9 +947,9 @@ CODE
when :line
assert_match(/ in /, str)
when :call, :c_call
- assert_match(/call \`/, str) # #<TracePoint:c_call `inherited'@../trunk/test.rb:11>
+ assert_match(/call \`/, str) # #<TracePoint:c_call `inherited' ../trunk/test.rb:11>
when :return, :c_return
- assert_match(/return \`/, str) # #<TracePoint:return `m'@../trunk/test.rb:3>
+ assert_match(/return \`/, str) # #<TracePoint:return `m' ../trunk/test.rb:3>
when /thread/
assert_match(/\#<Thread:/, str) # #<TracePoint:thread_end of #<Thread:0x87076c0>>
else
@@ -1682,7 +1687,7 @@ CODE
TracePoint.new(:return, &capture_events).enable{
o.alias_m
}
- assert_equal [[:return, :m, :alias_m]], events
+ assert_equal [[:return, :tap, :tap], [:return, :m, :alias_m]], events
events.clear
o = Class.new{
@@ -1706,13 +1711,13 @@ CODE
events.clear
o = Class.new{
- alias alias_tap tap
- define_method(:m){alias_tap{return}}
+ alias alias_singleton_class singleton_class
+ define_method(:m){alias_singleton_class}
}.new
TracePoint.new(:c_return, &capture_events).enable{
o.m
}
- assert_equal [[:c_return, :tap, :alias_tap]], events
+ assert_equal [[:c_return, :singleton_class, :alias_singleton_class]], events
events.clear
c = Class.new{
@@ -1968,7 +1973,7 @@ CODE
Thread.pass until t.status == 'sleep'
# When MJIT thread exists, t.status becomes 'sleep' even if it does not reach m2t_q.pop.
# This sleep forces it to reach m2t_q.pop for --jit-wait.
- sleep 1 if RubyVM::MJIT.enabled?
+ sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
t.add_trace_func proc{|ev, file, line, *args|
if file == __FILE__
@@ -2180,6 +2185,31 @@ CODE
assert_equal 'target_line is specified, but line event is not specified', e.message
end
+ def test_tracepoint_enable_with_target_line_two_times
+ events = []
+ line_0 = __LINE__
+ code1 = proc{
+ events << 1 # tp1
+ events << 2
+ events << 3 # tp2
+ }
+
+ tp1 = TracePoint.new(:line) do |tp|
+ events << :tp1
+ end
+ tp2 = TracePoint.new(:line) do |tp|
+ events << :tp2
+ end
+
+ tp1.enable(target: code1, target_line: line_0 + 2) do
+ tp2.enable(target: code1, target_line: line_0 + 4) do
+ # two hooks
+ code1.call
+ end
+ end
+ assert_equal [:tp1, 1, 2, :tp2, 3], events
+ end
+
def test_script_compiled
events = []
tp = TracePoint.new(:script_compiled){|tp|
@@ -2293,10 +2323,9 @@ CODE
def test_tracepoint_opt_invokebuiltin_delegate_leave
code = 'puts RubyVM::InstructionSequence.of("\x00".method(:unpack)).disasm'
out = EnvUtil.invoke_ruby(['-e', code], '', true).first
- assert_match /^0000 opt_invokebuiltin_delegate_leave /, out
+ assert_match(/^0000 opt_invokebuiltin_delegate_leave /, out)
event = eval(EnvUtil.invoke_ruby(['-e', <<~'EOS'], '', true).first)
- set_trace_func(proc {}); set_trace_func(nil) # Is it okay that this is required?
TracePoint.new(:return) do |tp|
p [tp.event, tp.method_id]
end.enable do
@@ -2305,4 +2334,19 @@ CODE
EOS
assert_equal [:return, :unpack], event
end
+
+ def test_while_in_while
+ lines = []
+
+ TracePoint.new(:line){|tp|
+ next unless target_thread?
+ lines << tp.lineno
+ }.enable{
+ n = 3
+ while n > 0
+ n -= 1 while n > 0
+ end
+ }
+ assert_equal [__LINE__ - 5, __LINE__ - 4, __LINE__ - 3], lines, 'Bug #17868'
+ end
end
diff --git a/test/ruby/test_stack.rb b/test/ruby/test_stack.rb
new file mode 100644
index 0000000000..763aeb6bc2
--- /dev/null
+++ b/test/ruby/test_stack.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'tmpdir'
+
+class TestStack < Test::Unit::TestCase
+ LARGE_VM_STACK_SIZE = 1024*1024*5
+ LARGE_MACHINE_STACK_SIZE = 1024*1024*10
+
+ def initialize(*)
+ super
+
+ @h_default = nil
+ @h_0 = nil
+ @h_large = nil
+ end
+
+ def invoke_ruby script, vm_stack_size: nil, machine_stack_size: nil
+ env = {}
+ env['RUBY_FIBER_VM_STACK_SIZE'] = vm_stack_size.to_s if vm_stack_size
+ env['RUBY_FIBER_MACHINE_STACK_SIZE'] = machine_stack_size.to_s if machine_stack_size
+ env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS']
+
+ stdout, stderr, status = EnvUtil.invoke_ruby([env, '-e', script], '', true, true, timeout: 30)
+ assert(!status.signaled?, FailDesc[status, nil, stderr])
+
+ return stdout
+ end
+
+ def h_default
+ @h_default ||= eval(invoke_ruby('p RubyVM::DEFAULT_PARAMS'))
+ end
+
+ def h_0
+ @h_0 ||= eval(invoke_ruby('p RubyVM::DEFAULT_PARAMS',
+ vm_stack_size: 0,
+ machine_stack_size: 0
+ ))
+ end
+
+ def h_large
+ @h_large ||= eval(invoke_ruby('p RubyVM::DEFAULT_PARAMS',
+ vm_stack_size: LARGE_VM_STACK_SIZE,
+ machine_stack_size: LARGE_MACHINE_STACK_SIZE
+ ))
+ end
+
+ def test_relative_stack_sizes
+ assert_operator(h_default[:fiber_vm_stack_size], :>, h_0[:fiber_vm_stack_size])
+ assert_operator(h_default[:fiber_vm_stack_size], :<, h_large[:fiber_vm_stack_size])
+ assert_operator(h_default[:fiber_machine_stack_size], :>=, h_0[:fiber_machine_stack_size])
+ assert_operator(h_default[:fiber_machine_stack_size], :<=, h_large[:fiber_machine_stack_size])
+ end
+
+ def test_vm_stack_size
+ script = '$stdout.sync=true; def rec; print "."; rec; end; Fiber.new{rec}.resume'
+
+ size_default = invoke_ruby(script).bytesize
+ assert_operator(size_default, :>, 0)
+
+ size_0 = invoke_ruby(script, vm_stack_size: 0).bytesize
+ assert_operator(size_default, :>, size_0)
+
+ size_large = invoke_ruby(script, vm_stack_size: LARGE_VM_STACK_SIZE).bytesize
+ assert_operator(size_default, :<, size_large)
+ end
+
+ # Depending on OS, machine stack size may not change size.
+ def test_machine_stack_size
+ return if /mswin|mingw/ =~ RUBY_PLATFORM
+
+ script = '$stdout.sync=true; def rec; print "."; 1.times{1.times{1.times{rec}}}; end; Fiber.new{rec}.resume'
+
+ vm_stack_size = 1024 * 1024
+ size_default = invoke_ruby(script, vm_stack_size: vm_stack_size).bytesize
+
+ size_0 = invoke_ruby(script, vm_stack_size: vm_stack_size, machine_stack_size: 0).bytesize
+ assert_operator(size_default, :>=, size_0)
+
+ size_large = invoke_ruby(script, vm_stack_size: vm_stack_size, machine_stack_size: LARGE_MACHINE_STACK_SIZE).bytesize
+ assert_operator(size_default, :<=, size_large)
+ end
+end
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index b6cb0321c8..57e7dae18f 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -2,8 +2,6 @@
require 'test/unit'
class TestString < Test::Unit::TestCase
- ENUMERATOR_WANTARRAY = RUBY_VERSION >= "3.0.0"
-
WIDE_ENCODINGS = [
Encoding::UTF_16BE, Encoding::UTF_16LE,
Encoding::UTF_32BE, Encoding::UTF_32LE,
@@ -267,6 +265,7 @@ CODE
assert_not_equal(S("CAT"), S('cat'))
assert_not_equal(S("CaT"), S('cAt'))
+ assert_not_equal(S("cat\0""dog"), S("cat\0"))
o = Object.new
def o.to_str; end
@@ -397,6 +396,8 @@ CODE
end
def test_chomp
+ verbose, $VERBOSE = $VERBOSE, nil
+
assert_equal(S("hello"), S("hello").chomp("\n"))
assert_equal(S("hello"), S("hello\n").chomp("\n"))
save = $/
@@ -462,9 +463,12 @@ CODE
assert_equal("foo", s.chomp("\n"))
ensure
$/ = save
+ $VERBOSE = verbose
end
def test_chomp!
+ verbose, $VERBOSE = $VERBOSE, nil
+
a = S("hello")
a.chomp!(S("\n"))
@@ -521,6 +525,7 @@ CODE
s = S("").freeze
assert_raise_with_message(FrozenError, /frozen/) {s.chomp!}
+ $VERBOSE = nil # EnvUtil.suppress_warning resets $VERBOSE to the original state
s = S("ax")
o = Struct.new(:s).new(s)
@@ -529,6 +534,7 @@ CODE
"x"
end
assert_raise_with_message(FrozenError, /frozen/) {s.chomp!(o)}
+ $VERBOSE = nil # EnvUtil.suppress_warning resets $VERBOSE to the original state
s = S("hello")
assert_equal("hel", s.chomp!('lo'))
@@ -579,6 +585,7 @@ CODE
assert_equal("foo", s.chomp!("\n"))
ensure
$/ = save
+ $VERBOSE = verbose
end
def test_chop
@@ -761,6 +768,7 @@ CODE
assert_equal(S("hello"), S("hello").downcase)
assert_equal(S("hello"), S("HELLO").downcase)
assert_equal(S("abc hello 123"), S("abc HELLO 123").downcase)
+ assert_equal(S("h\0""ello"), S("h\0""ELLO").downcase)
end
def test_downcase!
@@ -773,6 +781,12 @@ CODE
a=S("hello")
assert_nil(a.downcase!)
assert_equal(S("hello"), a)
+
+ a = S("h\0""ELLO")
+ b = a.dup
+ assert_equal(S("h\0""ello"), a.downcase!)
+ assert_equal(S("h\0""ello"), a)
+ assert_equal(S("h\0""ELLO"), b)
end
def test_dump
@@ -869,6 +883,8 @@ CODE
end
def test_each
+ verbose, $VERBOSE = $VERBOSE, nil
+
save = $/
$/ = "\n"
res=[]
@@ -888,6 +904,7 @@ CODE
assert_equal(S("world"), res[1])
ensure
$/ = save
+ $VERBOSE = verbose
end
def test_each_byte
@@ -906,21 +923,15 @@ CODE
s = S("ABC")
assert_equal [65, 66, 67], s.bytes
- if ENUMERATOR_WANTARRAY
- assert_warn(/block not used/) {
- assert_equal [65, 66, 67], s.bytes {}
- }
- else
- res = []
- assert_equal s.object_id, s.bytes {|x| res << x }.object_id
- assert_equal(65, res[0])
- assert_equal(66, res[1])
- assert_equal(67, res[2])
- s = S("ABC")
- res = []
- assert_same s, s.bytes {|x| res << x }
- assert_equal [65, 66, 67], res
- end
+ res = []
+ assert_equal s.object_id, s.bytes {|x| res << x }.object_id
+ assert_equal(65, res[0])
+ assert_equal(66, res[1])
+ assert_equal(67, res[2])
+ s = S("ABC")
+ res = []
+ assert_same s, s.bytes {|x| res << x }
+ assert_equal [65, 66, 67], res
end
def test_each_codepoint
@@ -945,21 +956,15 @@ CODE
s = S("\u3042\u3044\u3046")
assert_equal [0x3042, 0x3044, 0x3046], s.codepoints
- if ENUMERATOR_WANTARRAY
- assert_warn(/block not used/) {
- assert_equal [0x3042, 0x3044, 0x3046], s.codepoints {}
- }
- else
- res = []
- assert_equal s.object_id, s.codepoints {|x| res << x }.object_id
- assert_equal(0x3042, res[0])
- assert_equal(0x3044, res[1])
- assert_equal(0x3046, res[2])
- s = S("ABC")
- res = []
- assert_same s, s.codepoints {|x| res << x }
- assert_equal [65, 66, 67], res
- end
+ res = []
+ assert_equal s.object_id, s.codepoints {|x| res << x }.object_id
+ assert_equal(0x3042, res[0])
+ assert_equal(0x3044, res[1])
+ assert_equal(0x3046, res[2])
+ s = S("ABC")
+ res = []
+ assert_same s, s.codepoints {|x| res << x }
+ assert_equal [65, 66, 67], res
end
def test_each_char
@@ -978,17 +983,11 @@ CODE
s = S("ABC")
assert_equal ["A", "B", "C"], s.chars
- if ENUMERATOR_WANTARRAY
- assert_warn(/block not used/) {
- assert_equal ["A", "B", "C"], s.chars {}
- }
- else
- res = []
- assert_equal s.object_id, s.chars {|x| res << x }.object_id
- assert_equal("A", res[0])
- assert_equal("B", res[1])
- assert_equal("C", res[2])
- end
+ res = []
+ assert_equal s.object_id, s.chars {|x| res << x }.object_id
+ assert_equal("A", res[0])
+ assert_equal("B", res[1])
+ assert_equal("C", res[2])
end
def test_each_grapheme_cluster
@@ -1049,22 +1048,18 @@ CODE
end
assert_equal ["a", "b", "c"], "abc".b.grapheme_clusters
- if ENUMERATOR_WANTARRAY
- assert_warn(/block not used/) {
- assert_equal ["A", "B", "C"], "ABC".grapheme_clusters {}
- }
- else
- s = "ABC".b
- res = []
- assert_same s, s.grapheme_clusters {|x| res << x }
- assert_equal(3, res.size)
- assert_equal("A", res[0])
- assert_equal("B", res[1])
- assert_equal("C", res[2])
- end
+ s = "ABC".b
+ res = []
+ assert_same s, s.grapheme_clusters {|x| res << x }
+ assert_equal(3, res.size)
+ assert_equal("A", res[0])
+ assert_equal("B", res[1])
+ assert_equal("C", res[2])
end
def test_each_line
+ verbose, $VERBOSE = $VERBOSE, nil
+
save = $/
$/ = "\n"
res=[]
@@ -1111,6 +1106,7 @@ CODE
end
ensure
$/ = save
+ $VERBOSE = verbose
end
def test_each_line_chomp
@@ -1168,16 +1164,10 @@ CODE
assert_equal ["hello\n", "world"], s.lines
assert_equal ["hello\nworld"], s.lines(nil)
- if ENUMERATOR_WANTARRAY
- assert_warn(/block not used/) {
- assert_equal ["hello\n", "world"], s.lines {}
- }
- else
- res = []
- assert_equal s.object_id, s.lines {|x| res << x }.object_id
- assert_equal(S("hello\n"), res[0])
- assert_equal(S("world"), res[1])
- end
+ res = []
+ assert_equal s.object_id, s.lines {|x| res << x }.object_id
+ assert_equal(S("hello\n"), res[0])
+ assert_equal(S("world"), res[1])
end
def test_empty?
@@ -1341,6 +1331,8 @@ CODE
assert_nil("foo".index(//, -100))
assert_nil($~)
+
+ assert_equal(2, S("abcdbce").index(/b\Kc/))
end
def test_insert
@@ -1513,6 +1505,8 @@ CODE
assert_equal(3, "foo".rindex(//))
assert_equal([3, 3], $~.offset(0))
+
+ assert_equal(5, S("abcdbce").rindex(/b\Kc/))
end
def test_rjust
@@ -1604,8 +1598,10 @@ CODE
a = S("FooBar")
if @aref_slicebang_silent
assert_nil( a.slice!(6) )
+ assert_nil( a.slice!(6r) )
else
assert_raise(IndexError) { a.slice!(6) }
+ assert_raise(IndexError) { a.slice!(6r) }
end
assert_equal(S("FooBar"), a)
@@ -1819,6 +1815,11 @@ CODE
assert_equal("abc", s)
end
+ def test_split_lookbehind
+ assert_equal([S("ab"), S("d")], S("abcd").split(/(?<=b)c/))
+ assert_equal([S("ab"), S("d")], S("abcd").split(/b\Kc/))
+ end
+
def test_squeeze
assert_equal(S("abc"), S("aaabbbbccc").squeeze)
assert_equal(S("aa bb cc"), S("aa bb cc").squeeze(S(" ")))
@@ -1861,6 +1862,7 @@ CODE
def test_strip
assert_equal(S("x"), S(" x ").strip)
assert_equal(S("x"), S(" \n\r\t x \t\r\n\n ").strip)
+ assert_equal(S("x"), S("\x00x\x00").strip)
assert_equal("0b0 ".force_encoding("UTF-16BE"),
"\x00 0b0 ".force_encoding("UTF-16BE").strip)
@@ -1879,6 +1881,10 @@ CODE
assert_equal(S("x"), a.strip!)
assert_equal(S("x"), a)
+ a = S("\x00x\x00")
+ assert_equal(S("x"), a.strip!)
+ assert_equal(S("x"), a)
+
a = S("x")
assert_nil(a.strip!)
assert_equal(S("x") ,a)
@@ -2098,6 +2104,8 @@ CODE
def test_swapcase
assert_equal(S("hi&LOW"), S("HI&low").swapcase)
+ s = S("")
+ assert_not_same(s, s.swapcase)
end
def test_swapcase!
@@ -2333,6 +2341,7 @@ CODE
assert_equal(S("HELLO"), S("hello").upcase)
assert_equal(S("HELLO"), S("HELLO").upcase)
assert_equal(S("ABC HELLO 123"), S("abc HELLO 123").upcase)
+ assert_equal(S("H\0""ELLO"), S("H\0""ello").upcase)
end
def test_upcase!
@@ -2345,6 +2354,12 @@ CODE
a = S("HELLO")
assert_nil(a.upcase!)
assert_equal(S("HELLO"), a)
+
+ a = S("H\0""ello")
+ b = a.dup
+ assert_equal(S("H\0""ELLO"), a.upcase!)
+ assert_equal(S("H\0""ELLO"), a)
+ assert_equal(S("H\0""ello"), b)
end
def test_upto
@@ -2570,6 +2585,10 @@ CODE
hello = "hello"
hello.partition("hi").map(&:upcase!)
assert_equal("hello", hello, bug)
+
+ assert_equal(["", "", "foo"], "foo".partition(/^=*/))
+
+ assert_equal([S("ab"), S("c"), S("dbce")], S("abcdbce").partition(/b\Kc/))
end
def test_rpartition
@@ -2594,6 +2613,8 @@ CODE
hello = "hello"
hello.rpartition("hi").map(&:upcase!)
assert_equal("hello", hello, bug)
+
+ assert_equal([S("abcdb"), S("c"), S("e")], S("abcdbce").rpartition(/b\Kc/))
end
def test_setter
@@ -2661,6 +2682,7 @@ CODE
assert_equal(1, "FoO".casecmp("BaR"))
assert_equal(-1, "baR".casecmp("FoO"))
assert_equal(1, "\u3042B".casecmp("\u3042a"))
+ assert_equal(-1, "foo".casecmp("foo\0"))
assert_nil("foo".casecmp(:foo))
assert_nil("foo".casecmp(Object.new))
@@ -2675,6 +2697,7 @@ CODE
assert_equal(false, 'FoO'.casecmp?('BaR'))
assert_equal(false, 'baR'.casecmp?('FoO'))
assert_equal(true, 'äöü'.casecmp?('ÄÖÜ'))
+ assert_equal(false, "foo".casecmp?("foo\0"))
assert_nil("foo".casecmp?(:foo))
assert_nil("foo".casecmp?(Object.new))
@@ -2695,6 +2718,7 @@ CODE
def test_rstrip
assert_equal(" hello", " hello ".rstrip)
assert_equal("\u3042", "\u3042 ".rstrip)
+ assert_equal("\u3042", "\u3042\u0000".rstrip)
assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip }
end
@@ -2715,12 +2739,17 @@ CODE
assert_equal(nil, s4.rstrip!)
assert_equal("\u3042", s4)
+ s5 = S("\u3042\u0000")
+ assert_equal("\u3042", s5.rstrip!)
+ assert_equal("\u3042", s5)
+
assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip! }
end
def test_lstrip
assert_equal("hello ", " hello ".lstrip)
assert_equal("\u3042", " \u3042".lstrip)
+ assert_equal("hello ", "\x00hello ".lstrip)
end
def test_lstrip_bang
@@ -2739,6 +2768,11 @@ CODE
s4 = S("\u3042")
assert_equal(nil, s4.lstrip!)
assert_equal("\u3042", s4)
+
+ s5 = S("\u0000\u3042")
+ assert_equal("\u3042", s5.lstrip!)
+ assert_equal("\u3042", s5)
+
end
def test_delete_prefix
@@ -3144,6 +3178,22 @@ CODE
assert_same(str, -bar, "uminus deduplicates [Feature #13077]")
end
+ def test_uminus_frozen
+ # embedded
+ str1 = ("foobar" * 3).freeze
+ str2 = ("foobar" * 3).freeze
+ assert_not_same str1, str2
+ assert_same str1, -str1
+ assert_same str1, -str2
+
+ # regular
+ str1 = ("foobar" * 4).freeze
+ str2 = ("foobar" * 4).freeze
+ assert_not_same str1, str2
+ assert_same str1, -str1
+ assert_same str1, -str2
+ end
+
def test_uminus_no_freeze_not_bare
str = @cls.new("foo")
assert_instance_of(@cls, -str)
diff --git a/test/ruby/test_struct.rb b/test/ruby/test_struct.rb
index 85de0f23a9..c313ab0dbe 100644
--- a/test/ruby/test_struct.rb
+++ b/test/ruby/test_struct.rb
@@ -23,6 +23,10 @@ module TestStruct
test.bar = 47
assert_equal(47, test.bar)
+
+ @Struct.class_eval do
+ remove_const :Test
+ end
end
# [ruby-dev:26247] more than 10 struct members causes segmentation fault
@@ -145,12 +149,6 @@ module TestStruct
assert_equal 3, klass.new(1,2).total
end
- def test_each
- klass = @Struct.new(:a, :b)
- o = klass.new(1, 2)
- assert_equal([1, 2], o.each.to_a)
- end
-
def test_initialize_with_kw
klass = @Struct.new(:foo, :options) do
def initialize(foo, **options)
@@ -162,6 +160,12 @@ module TestStruct
assert_equal 2, x.options[:bar]
end
+ def test_each
+ klass = @Struct.new(:a, :b)
+ o = klass.new(1, 2)
+ assert_equal([1, 2], o.each.to_a)
+ end
+
def test_each_pair
klass = @Struct.new(:a, :b)
o = klass.new(1, 2)
@@ -335,15 +339,19 @@ module TestStruct
end
def test_redefinition_warning
- @Struct.new("RedefinitionWarning")
+ @Struct.new(name = "RedefinitionWarning")
e = EnvUtil.verbose_warning do
@Struct.new("RedefinitionWarning")
end
assert_match(/redefining constant #@Struct::RedefinitionWarning/, e)
+
+ @Struct.class_eval do
+ remove_const name
+ end
end
def test_nonascii
- struct_test = @Struct.new("R\u{e9}sum\u{e9}", :"r\u{e9}sum\u{e9}")
+ struct_test = @Struct.new(name = "R\u{e9}sum\u{e9}", :"r\u{e9}sum\u{e9}")
assert_equal(@Struct.const_get("R\u{e9}sum\u{e9}"), struct_test, '[ruby-core:24849]')
a = struct_test.new(42)
assert_equal("#<struct #@Struct::R\u{e9}sum\u{e9} r\u{e9}sum\u{e9}=42>", a.inspect, '[ruby-core:24849]')
@@ -353,6 +361,10 @@ module TestStruct
assert_nothing_raised(Encoding::CompatibilityError) do
assert_match(/redefining constant #@Struct::R\u{e9}sum\u{e9}/, e)
end
+
+ @Struct.class_eval do
+ remove_const name
+ end
end
def test_junk
diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb
index bbfc581500..3afde9b0e3 100644
--- a/test/ruby/test_super.rb
+++ b/test/ruby/test_super.rb
@@ -521,6 +521,37 @@ class TestSuper < Test::Unit::TestCase
assert_equal(%w[B A], result, bug9721)
end
+ # [Bug #18329]
+ def test_super_missing_prepended_module
+ a = Module.new do
+ def probe(*methods)
+ prepend(probing_module(methods))
+ end
+
+ def probing_module(methods)
+ Module.new do
+ methods.each do |method|
+ define_method(method) do |*args, **kwargs, &block|
+ super(*args, **kwargs, &block)
+ end
+ end
+ end
+ end
+ end
+
+ b = Class.new do
+ extend a
+
+ probe :danger!, :missing
+
+ def danger!; end
+ end
+
+ o = b.new
+ o.danger!
+ 2.times { o.missing rescue NoMethodError }
+ end
+
def test_from_eval
bug10263 = '[ruby-core:65122] [Bug #10263a]'
a = Class.new do
@@ -583,4 +614,81 @@ class TestSuper < Test::Unit::TestCase
def test_super_with_modified_rest_parameter
assert_equal [13], TestFor_super_with_modified_rest_parameter.new.foo
end
+
+ def test_super_with_define_method
+ superklass1 = Class.new do
+ def foo; :foo; end
+ def bar; :bar; end
+ def boo; :boo; end
+ end
+ superklass2 = Class.new(superklass1) do
+ alias baz boo
+ def boo; :boo2; end
+ end
+ subklass = Class.new(superklass2)
+ [:foo, :bar, :baz, :boo].each do |sym|
+ subklass.define_method(sym){ super() }
+ end
+ assert_equal :foo, subklass.new.foo
+ assert_equal :bar, subklass.new.bar
+ assert_equal :boo, subklass.new.baz
+ assert_equal :boo2, subklass.new.boo
+ end
+
+ def test_super_attr_writer # [Bug #16785]
+ writer_class = Class.new do
+ attr_writer :test
+ end
+ superwriter_class = Class.new(writer_class) do
+ def initialize
+ @test = 1 # index: 1
+ end
+
+ def test=(test)
+ super(test)
+ end
+ end
+ inherited_class = Class.new(superwriter_class) do
+ def initialize
+ @a = nil
+ @test = 2 # index: 2
+ end
+ end
+
+ superwriter = superwriter_class.new
+ superwriter.test = 3 # set ic->index of superwriter_class#test= to 1
+
+ inherited = inherited_class.new
+ inherited.test = 4 # it may set 4 to index=1 while it should be index=2
+
+ assert_equal 3, superwriter.instance_variable_get(:@test)
+ assert_equal 4, inherited.instance_variable_get(:@test)
+ end
+
+ def test_super_attr_reader
+ reader_class = Class.new do
+ attr_reader :test
+ end
+ superreader_class = Class.new(reader_class) do
+ def initialize
+ @test = 1 # index: 1
+ end
+
+ def test
+ super
+ end
+ end
+ inherited_class = Class.new(superreader_class) do
+ def initialize
+ @a = nil
+ @test = 2 # index: 2
+ end
+ end
+
+ superreader = superreader_class.new
+ assert_equal 1, superreader.test # set ic->index of superreader_class#test to 1
+
+ inherited = inherited_class.new
+ assert_equal 2, inherited.test # it may read index=1 while it should be index=2
+ end
end
diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb
index 660f2e1574..f7f17b8d67 100644
--- a/test/ruby/test_symbol.rb
+++ b/test/ruby/test_symbol.rb
@@ -105,6 +105,12 @@ class TestSymbol < Test::Unit::TestCase
end
end
+ def test_name
+ assert_equal("foo", :foo.name)
+ assert_same(:foo.name, :foo.name)
+ assert_predicate(:foo.name, :frozen?)
+ end
+
def test_to_proc
assert_equal %w(1 2 3), (1..3).map(&:to_s)
[
@@ -153,6 +159,14 @@ class TestSymbol < Test::Unit::TestCase
end;
end
+ def test_to_proc_lambda?
+ assert_predicate(:itself.to_proc, :lambda?)
+ end
+
+ def test_to_proc_arity
+ assert_equal(-2, :itself.to_proc.arity)
+ end
+
def test_to_proc_call_with_symbol_proc
first = 1
bug11594 = "[ruby-core:71088] [Bug #11594] corrupted the first local variable"
@@ -165,6 +179,9 @@ class TestSymbol < Test::Unit::TestCase
def _test_to_proc_arg_with_refinements_call(&block)
block.call TestToPRocArgWithRefinements.new
end
+ def _test_to_proc_with_refinements_call(&block)
+ block
+ end
using Module.new {
refine TestToPRocArgWithRefinements do
def hoge
@@ -176,6 +193,14 @@ class TestSymbol < Test::Unit::TestCase
assert_equal(:hoge, _test_to_proc_arg_with_refinements_call(&:hoge))
end
+ def test_to_proc_lambda_with_refinements
+ assert_predicate(_test_to_proc_with_refinements_call(&:hoge), :lambda?)
+ end
+
+ def test_to_proc_arity_with_refinements
+ assert_equal(-2, _test_to_proc_with_refinements_call(&:hoge).arity)
+ end
+
def self._test_to_proc_arg_with_refinements_call(&block)
block.call TestToPRocArgWithRefinements.new
end
@@ -219,11 +244,11 @@ class TestSymbol < Test::Unit::TestCase
begin;
bug11845 = '[ruby-core:72381] [Bug #11845]'
assert_nil(:class.to_proc.source_location, bug11845)
- assert_equal([[:rest]], :class.to_proc.parameters, bug11845)
+ assert_equal([[:req], [:rest]], :class.to_proc.parameters, bug11845)
c = Class.new {define_method(:klass, :class.to_proc)}
m = c.instance_method(:klass)
assert_nil(m.source_location, bug11845)
- assert_equal([[:rest]], m.parameters, bug11845)
+ assert_equal([[:req], [:rest]], m.parameters, bug11845)
end;
end
@@ -504,12 +529,14 @@ class TestSymbol < Test::Unit::TestCase
assert_nothing_raised(NoMethodError, bug10259) {obj.send("unagi=".intern, 1)}
end
- def test_symbol_fstr_leak
+ def test_symbol_fstr_memory_leak
bug10686 = '[ruby-core:67268] [Bug #10686]'
- x = x = 0
- assert_no_memory_leak([], '200_000.times { |i| i.to_s.to_sym }; GC.start', "#{<<-"begin;"}\n#{<<-"end;"}", bug10686, limit: 1.71, rss: true, timeout: 20)
+ assert_no_memory_leak([], "#{<<~"begin;"}\n#{<<~'else;'}", "#{<<~'end;'}", bug10686, limit: 1.71, rss: true, timeout: 20)
begin;
- 200_000.times { |i| (i + 200_000).to_s.to_sym }
+ n = 100_000
+ n.times { |i| i.to_s.to_sym }
+ else;
+ (2 * n).times { |i| (i + n).to_s.to_sym }
end;
end
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index 86417ba12f..a0cdb5b6fd 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -93,6 +93,17 @@ class TestSyntax < Test::Unit::TestCase
assert_valid_syntax("tap (proc do end)", __FILE__, bug9726)
end
+ def test_hash_kwsplat_hash
+ kw = {}
+ h = {a: 1}
+ assert_equal({}, {**{}})
+ assert_equal({}, {**kw})
+ assert_equal(h, {**h})
+ assert_equal(false, {**{}}.frozen?)
+ assert_equal(false, {**kw}.equal?(kw))
+ assert_equal(false, {**h}.equal?(h))
+ end
+
def test_array_kwsplat_hash
kw = {}
h = {a: 1}
@@ -182,9 +193,7 @@ class TestSyntax < Test::Unit::TestCase
h = {k3: 31}
assert_raise(ArgumentError) {o.kw(**h)}
h = {"k1"=>11, k2: 12}
- assert_warn(/Splitting the last argument into positional and keyword parameters is deprecated.*The called method `kw'/m) do
- assert_raise(ArgumentError) {o.kw(**h)}
- end
+ assert_raise(ArgumentError) {o.kw(**h)}
end
def test_keyword_duplicated
@@ -199,7 +208,7 @@ class TestSyntax < Test::Unit::TestCase
assert_equal([1, 2], a, bug10315)
a.clear
r = nil
- assert_warn(/duplicated/) {r = eval("a.f({k: a.add(1), k: a.add(2)})")}
+ assert_warn(/duplicated/) {r = eval("a.f(**{k: a.add(1), k: a.add(2)})")}
assert_equal(2, r)
assert_equal([1, 2], a, bug10315)
end
@@ -610,6 +619,11 @@ WARN
def test_do_block_after_lambda
bug11380 = '[ruby-core:70067] [Bug #11380]'
assert_valid_syntax('p -> { :hello }, a: 1 do end', bug11380)
+
+ assert_valid_syntax('->(opt = (foo.[] bar)) {}')
+ assert_valid_syntax('->(opt = (foo.[]= bar)) {}')
+ assert_valid_syntax('->(opt = (foo.[] bar)) do end')
+ assert_valid_syntax('->(opt = (foo.[]= bar)) do end')
end
def test_reserved_method_no_args
@@ -951,9 +965,14 @@ eom
def test_warning_for_cr
feature8699 = '[ruby-core:56240] [Feature #8699]'
- assert_warning(/encountered \\r/, feature8699) do
- eval("\r""__id__\r")
+ s = assert_warning(/encountered \\r/, feature8699) do
+ eval("'\r'\r")
+ end
+ assert_equal("\r", s)
+ s = assert_warning('') do
+ eval("'\r'\r\n")
end
+ assert_equal("\r", s)
end
def test_unexpected_fraction
@@ -984,6 +1003,19 @@ eom
assert_warn('') {eval("(1...)")}
assert_warn('') {eval("(1...\n2)")}
assert_warn('') {eval("{a: 1...\n2}")}
+
+ assert_warn(/\.\.\. at EOL/) do
+ assert_valid_syntax('foo.[]= ...', verbose: true)
+ end
+ assert_warn(/\.\.\. at EOL/) do
+ assert_valid_syntax('foo.[] ...', verbose: true)
+ end
+ assert_warn(/\.\.\. at EOL/) do
+ assert_syntax_error('foo.[]= bar, ...', /unexpected/, verbose: true)
+ end
+ assert_warn(/\.\.\. at EOL/) do
+ assert_syntax_error('foo.[] bar, ...', /unexpected/, verbose: true)
+ end
end
def test_too_big_nth_ref
@@ -1409,6 +1441,27 @@ eom
assert_equal(line, e.backtrace_locations[0].lineno)
end
+ def test_methoddef_endless
+ assert_valid_syntax('private def foo = 42')
+ assert_valid_syntax('private def foo() = 42')
+ assert_valid_syntax('private def inc(x) = x + 1')
+ assert_valid_syntax('private def obj.foo = 42')
+ assert_valid_syntax('private def obj.foo() = 42')
+ assert_valid_syntax('private def obj.inc(x) = x + 1')
+ k = Class.new do
+ class_eval('def rescued(x) = raise("to be caught") rescue "instance #{x}"')
+ class_eval('def self.rescued(x) = raise("to be caught") rescue "class #{x}"')
+ end
+ assert_equal("class ok", k.rescued("ok"))
+ assert_equal("instance ok", k.new.rescued("ok"))
+
+ error = /setter method cannot be defined in an endless method definition/
+ assert_syntax_error('def foo=() = 42', error)
+ assert_syntax_error('def obj.foo=() = 42', error)
+ assert_syntax_error('def foo=() = 42 rescue nil', error)
+ assert_syntax_error('def obj.foo=() = 42 rescue nil', error)
+ end
+
def test_methoddef_in_cond
assert_valid_syntax('while def foo; tap do end; end; break; end')
assert_valid_syntax('while def foo a = tap do end; end; break; end')
@@ -1446,13 +1499,12 @@ eom
assert_syntax_error('-> {_1; -> {_2}}', /numbered parameter is already used/)
assert_syntax_error('-> {-> {_1}; _2}', /numbered parameter is already used/)
assert_syntax_error('proc {_1; _1 = nil}', /Can't assign to numbered parameter _1/)
- mesg = proc {|n| /`_#{n}' is reserved for numbered parameter/}
- assert_warn(mesg[1]) {eval('proc {_1 = nil}')}
- assert_warn(mesg[2]) {eval('_2=1')}
- assert_warn(mesg[3]) {eval('proc {|_3|}')}
- assert_warn(mesg[4]) {instance_eval('def x(_4) end')}
- assert_warn(mesg[5]) {instance_eval('def _5; end')}
- assert_warn(mesg[6]) {instance_eval('def self._6; end')}
+ assert_syntax_error('proc {_1 = nil}', /_1 is reserved for numbered parameter/)
+ assert_syntax_error('_2=1', /_2 is reserved for numbered parameter/)
+ assert_syntax_error('proc {|_3|}', /_3 is reserved for numbered parameter/)
+ assert_syntax_error('def x(_4) end', /_4 is reserved for numbered parameter/)
+ assert_syntax_error('def _5; end', /_5 is reserved for numbered parameter/)
+ assert_syntax_error('def self._6; end', /_6 is reserved for numbered parameter/)
assert_raise_with_message(NameError, /undefined local variable or method `_1'/) {
eval('_1')
}
@@ -1461,7 +1513,13 @@ eom
assert_valid_syntax("->{_1;#{c};->{_1};end}\n")
end
- 1.times {_1}
+ 1.times {
+ [
+ _1,
+ assert_equal([:a], eval("[:a].map{_1}")),
+ assert_raise(NameError) {eval("_1")},
+ ]
+ }
end
def test_value_expr_in_condition
@@ -1472,6 +1530,11 @@ eom
assert_valid_syntax("tap {a = (break unless true)}")
end
+ def test_tautological_condition
+ assert_valid_syntax("def f() return if false and invalid; nil end")
+ assert_valid_syntax("def f() return unless true or invalid; nil end")
+ end
+
def test_argument_forwarding
assert_valid_syntax('def foo(...) bar(...) end')
assert_valid_syntax('def foo(...) end')
@@ -1480,10 +1543,11 @@ eom
assert_valid_syntax('def nil(...) end')
assert_valid_syntax('def true(...) end')
assert_valid_syntax('def false(...) end')
+ unexpected = /unexpected \.{3}/
assert_syntax_error('iter do |...| end', /unexpected/)
assert_syntax_error('iter {|...|}', /unexpected/)
- assert_syntax_error('->... {}', /unexpected/)
- assert_syntax_error('->(...) {}', /unexpected/)
+ assert_syntax_error('->... {}', unexpected)
+ assert_syntax_error('->(...) {}', unexpected)
assert_syntax_error('def foo(x, y, z) bar(...); end', /unexpected/)
assert_syntax_error('def foo(x, y, z) super(...); end', /unexpected/)
assert_syntax_error('def foo(...) yield(...); end', /unexpected/)
@@ -1539,12 +1603,12 @@ eom
assert_warning('') {
assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5))
}
- warning = "warning: Using the last argument as keyword parameters is deprecated"
- assert_warning(/\A\z|:(?!#{__LINE__+1})\d+: #{warning}/o) {
- assert_equal([[], {}], obj.foo({}) {|*x| x})
+ array = obj == obj3 ? [] : [{}]
+ assert_warning('') {
+ assert_equal([array, {}], obj.foo({}) {|*x| x})
}
- assert_warning(/\A\z|:(?!#{__LINE__+1})\d+: #{warning}/o) {
- assert_equal([[], {}], obj.foo({}))
+ assert_warning('') {
+ assert_equal([array, {}], obj.foo({}))
}
assert_equal(-1, obj.method(:foo).arity)
parameters = obj.method(:foo).parameters
@@ -1666,6 +1730,21 @@ eom
assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]}
end
+ def test_cdhash
+ assert_separately([], <<-RUBY)
+ n = case 1 when 2r then false else true end
+ assert_equal(n, true, '[ruby-core:103759] [Bug #17854]')
+ RUBY
+ assert_separately([], <<-RUBY)
+ n = case 3/2r when 1.5r then true else false end
+ assert_equal(n, true, '[ruby-core:103759] [Bug #17854]')
+ RUBY
+ assert_separately([], <<-RUBY)
+ n = case 1i when 1i then true else false end
+ assert_equal(n, true, '[ruby-core:103759] [Bug #17854]')
+ RUBY
+ end
+
private
def not_label(x) @result = x; @not_label ||= nil end
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index 30a3cc784e..3852cb7020 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -230,9 +230,9 @@ class TestThread < Test::Unit::TestCase
assert_equal(t1, t3.value)
ensure
- t1&.kill
- t2&.kill
- t3&.kill
+ t1&.kill&.join
+ t2&.kill&.join
+ t3&.kill&.join
end
{ 'FIXNUM_MAX' => RbConfig::LIMITS['FIXNUM_MAX'],
@@ -309,7 +309,7 @@ class TestThread < Test::Unit::TestCase
s += 1
end
Thread.pass until t.stop?
- sleep 1 if RubyVM::MJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait
+ sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait
assert_equal(1, s)
t.wakeup
Thread.pass while t.alive?
@@ -490,6 +490,19 @@ class TestThread < Test::Unit::TestCase
end;
end
+ def test_ignore_deadlock
+ if /mswin|mingw/ =~ RUBY_PLATFORM
+ skip "can't trap a signal from another process on Windows"
+ end
+ assert_in_out_err([], <<-INPUT, %w(false :sig), [], :signal=>:INT, timeout: 1, timeout_error: nil)
+ p Thread.ignore_deadlock
+ q = Queue.new
+ trap(:INT){q.push :sig}
+ Thread.ignore_deadlock = true
+ p q.pop
+ INPUT
+ end
+
def test_status_and_stop_p
a = ::Thread.new {
Thread.current.report_on_exception = false
@@ -617,7 +630,7 @@ class TestThread < Test::Unit::TestCase
Thread.pass until t.stop?
assert_predicate(t, :alive?)
ensure
- t&.kill
+ t&.kill&.join
end
def test_mutex_deadlock
@@ -1106,7 +1119,7 @@ q.pop
Thread.pass until mutex.locked?
assert_equal(mutex.owned?, false)
ensure
- th&.kill
+ th&.kill&.join
end
end
@@ -1325,7 +1338,7 @@ q.pop
opts = { timeout: 5, timeout_error: nil }
# prevent SIGABRT from slow shutdown with MJIT
- opts[:reprieve] = 3 if RubyVM::MJIT.enabled?
+ opts[:reprieve] = 3 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
assert_normal_exit(<<-_end, '[Bug #8996]', **opts)
Thread.report_on_exception = false
diff --git a/test/ruby/test_thread_queue.rb b/test/ruby/test_thread_queue.rb
index 41e6865ed4..b0fa878814 100644
--- a/test/ruby/test_thread_queue.rb
+++ b/test/ruby/test_thread_queue.rb
@@ -131,7 +131,7 @@ class TestThreadQueue < Test::Unit::TestCase
def test_thr_kill
bug5343 = '[ruby-core:39634]'
Dir.mktmpdir {|d|
- timeout = 60
+ timeout = EnvUtil.apply_timeout_scale(60)
total_count = 250
begin
assert_normal_exit(<<-"_eom", bug5343, **{:timeout => timeout, :chdir=>d})
@@ -572,6 +572,7 @@ class TestThreadQueue < Test::Unit::TestCase
Thread.new{
loop{
Process.kill :INT, $$
+ sleep 0.1
}
}
puts q.pop
diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb
index 1749d92a17..3f5cb9d3f2 100644
--- a/test/ruby/test_time.rb
+++ b/test/ruby/test_time.rb
@@ -7,7 +7,6 @@ require 'delegate'
class TestTime < Test::Unit::TestCase
def setup
@verbose = $VERBOSE
- $VERBOSE = nil
end
def teardown
@@ -108,6 +107,10 @@ class TestTime < Test::Unit::TestCase
assert_equal(78796800, Time.utc(1972, 7, 1, 0, 0, 0).tv_sec)
assert_equal(78796801, Time.utc(1972, 7, 1, 0, 0, 1).tv_sec)
assert_equal(946684800, Time.utc(2000, 1, 1, 0, 0, 0).tv_sec)
+
+ # Giveup to try 2nd test because some state is changed.
+ skip if Minitest::Unit.current_repeat_count > 0
+
assert_equal(0x7fffffff, Time.utc(2038, 1, 19, 3, 14, 7).tv_sec)
assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec)
else
@@ -417,8 +420,10 @@ class TestTime < Test::Unit::TestCase
def o.to_int; 0; end
def o.to_r; nil; end
assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) }
+ class << o; remove_method(:to_r); end
def o.to_r; ""; end
assert_raise(TypeError) { Time.gm(2000, 1, 1, 0, 0, o, :foo, :foo) }
+ class << o; remove_method(:to_r); end
def o.to_r; Rational(11); end
assert_equal(11, Time.gm(2000, 1, 1, 0, 0, o).sec)
o = Object.new
@@ -431,6 +436,10 @@ class TestTime < Test::Unit::TestCase
assert_equal(-4427700000, Time.utc(-4427700000,12,1).year)
assert_equal(-2**30+10, Time.utc(-2**30+10,1,1).year)
+
+ assert_raise(ArgumentError) { Time.gm(2000, 1, -1) }
+ assert_raise(ArgumentError) { Time.gm(2000, 1, 2**30 + 1) }
+ assert_raise(ArgumentError) { Time.gm(2000, 1, -2**30 + 1) }
end
def test_time_interval
@@ -596,13 +605,12 @@ class TestTime < Test::Unit::TestCase
assert_nil(t.getlocal("+02:00").zone)
end
- def test_plus_minus_succ
+ def test_plus_minus
t2000 = get_t2000
# assert_raise(RangeError) { t2000 + 10000000000 }
# assert_raise(RangeError) t2000 - 3094168449 }
# assert_raise(RangeError) { t2000 + 1200798848 }
assert_raise(TypeError) { t2000 + Time.now }
- assert_equal(t2000 + 1, t2000.succ)
end
def test_plus_type
@@ -705,7 +713,9 @@ class TestTime < Test::Unit::TestCase
assert_equal("12:00:00 AM", t2000.strftime("%r"))
assert_equal("Sat 2000-01-01T00:00:00", t2000.strftime("%3a %FT%T"))
- assert_equal("", t2000.strftime(""))
+ assert_warning(/strftime called with empty format string/) do
+ assert_equal("", t2000.strftime(""))
+ end
assert_equal("foo\0bar\x0000\x0000\x0000", t2000.strftime("foo\0bar\0%H\0%M\0%S"))
assert_equal("foo" * 1000, t2000.strftime("foo" * 1000))
@@ -1061,6 +1071,11 @@ class TestTime < Test::Unit::TestCase
t2 = (t+0.123456789).ceil(4)
assert_equal([59,59,23, 31,12,1999, 5,365,false,"UTC"], t2.to_a)
assert_equal(Rational(1235,10000), t2.subsec)
+
+ time = Time.utc(2016, 4, 23, 0, 0, 0.123456789r)
+ assert_equal(time, time.ceil(9))
+ assert_equal(time, time.ceil(10))
+ assert_equal(time, time.ceil(11))
end
def test_getlocal_dont_share_eigenclass
@@ -1136,6 +1151,9 @@ class TestTime < Test::Unit::TestCase
end
def test_2038
+ # Giveup to try 2nd test because some state is changed.
+ skip if Minitest::Unit.current_repeat_count > 0
+
if no_leap_seconds?
assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec)
end
@@ -1200,12 +1218,6 @@ class TestTime < Test::Unit::TestCase
assert_equal [00, 00, 9, 1, 1, 2000], t.getlocal("+09:00").to_a[0, 6]
assert_equal [20, 29, 21, 31, 12, 1999], t.getlocal("-02:30:40").to_a[0, 6]
assert_equal [35, 10, 9, 1, 1, 2000], t.getlocal("+09:10:35").to_a[0, 6]
- assert_equal [00, 30, 21, 31, 12, 1999], t.getlocal("-0230").to_a[0, 6]
- assert_equal [00, 00, 9, 1, 1, 2000], t.getlocal("+0900").to_a[0, 6]
- assert_equal [20, 29, 21, 31, 12, 1999], t.getlocal("-023040").to_a[0, 6]
- assert_equal [35, 10, 9, 1, 1, 2000], t.getlocal("+091035").to_a[0, 6]
- assert_raise(ArgumentError) {t.getlocal("-02:3040")}
- assert_raise(ArgumentError) {t.getlocal("+0910:35")}
end
def test_getlocal_nil
@@ -1266,6 +1278,7 @@ class TestTime < Test::Unit::TestCase
def test_memsize
# Time objects are common in some code, try to keep them small
skip "Time object size test" if /^(?:i.?86|x86_64)-linux/ !~ RUBY_PLATFORM
+ skip "GC is in debug" if GC::INTERNAL_CONSTANTS[:DEBUG]
require 'objspace'
t = Time.at(0)
size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb
index 5ee12e4dbd..dade0bff16 100644
--- a/test/ruby/test_time_tz.rb
+++ b/test/ruby/test_time_tz.rb
@@ -219,7 +219,6 @@ class TestTimeTZ < Test::Unit::TestCase
def test_right_utc
with_tz(tz="right/UTC") {
- ::Bug::Time.reset_leap_second_info
assert_time_constructor(tz, "2008-12-31 23:59:59 UTC", :utc, [2008,12,31,23,59,59])
assert_time_constructor(tz, "2008-12-31 23:59:60 UTC", :utc, [2008,12,31,23,59,60])
assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,24,0,0])
@@ -229,25 +228,23 @@ class TestTimeTZ < Test::Unit::TestCase
def test_right_utc_switching
with_tz("UTC") { # ensure no leap second timezone
- ::Bug::Time.reset_leap_second_info
assert_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i)
with_tz(tz="right/UTC") {
assert_time_constructor(tz, "2008-12-31 23:59:59 UTC", :utc, [2008,12,31,23,59,59])
- assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,23,59,60])
+ assert_time_constructor(tz, "2008-12-31 23:59:60 UTC", :utc, [2008,12,31,23,59,60])
assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,24,0,0])
assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2009,1,1,0,0,0])
- assert_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i)
+ assert_not_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i)
}
}
with_tz("right/UTC") {
- ::Bug::Time.reset_leap_second_info
assert_not_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i)
with_tz(tz="UTC") {
assert_time_constructor(tz, "2008-12-31 23:59:59 UTC", :utc, [2008,12,31,23,59,59])
assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,23,59,60])
assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2008,12,31,24,0,0])
assert_time_constructor(tz, "2009-01-01 00:00:00 UTC", :utc, [2009,1,1,0,0,0])
- assert_not_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i)
+ assert_equal(4102444800, Time.utc(2100,1,1,0,0,0).to_i)
}
}
end if has_right_tz
@@ -376,7 +373,6 @@ class TestTimeTZ < Test::Unit::TestCase
mesg = "#{mesg_utc}.localtime"
define_method(gen_test_name(tz)) {
with_tz(tz) {
- ::Bug::Time.reset_leap_second_info
t = nil
assert_nothing_raised(mesg) { t = Time.utc(*u) }
assert_equal(expected_utc, time_to_s(t), mesg_utc)
@@ -636,6 +632,7 @@ module TestTimeTZ::WithTZ
h, m = (utc_offset.abs / 60).divmod(60)
h = -h if utc_offset < 0
assert_equal("%+.2d%.2d %s" % [h, m, abbr], t.strftime("%z %Z"))
+ assert_equal("34 35 35", t.strftime("%U %V %W"))
end
def subtest_plus(time_class, tz, tzarg, tzname, abbr, utc_offset)
@@ -664,6 +661,12 @@ module TestTimeTZ::WithTZ
assert_equal(utc, t.to_i)
end
+ def subtest_to_a(time_class, tz, tzarg, tzname, abbr, utc_offset)
+ t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg)
+ ary = t.to_a
+ assert_equal(ary, [t.sec, t.min, t.hour, t.mday, t.mon, t.year, t.wday, t.yday, t.isdst, t.zone])
+ end
+
def subtest_marshal(time_class, tz, tzarg, tzname, abbr, utc_offset)
t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg)
t2 = Marshal.load(Marshal.dump(t))
diff --git a/test/ruby/test_transcode.rb b/test/ruby/test_transcode.rb
index 1f4c623acb..c8b0034e06 100644
--- a/test/ruby/test_transcode.rb
+++ b/test/ruby/test_transcode.rb
@@ -126,6 +126,28 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("D\xFCrst".force_encoding('iso-8859-2'), "D\xFCrst".encode('iso-8859-2', 'iso-8859-1'))
end
+ def test_encode_xml_multibyte
+ encodings = %w'UTF-8 UTF-16LE UTF-16BE UTF-32LE UTF-32BE'
+ encodings.each do |src_enc|
+ encodings.each do |dst_enc|
+ escaped = "<>".encode(src_enc).encode(dst_enc, :xml=>:text)
+ assert_equal("&lt;&gt;", escaped.encode('UTF-8'), "failed encoding #{src_enc} to #{dst_enc} with xml: :text")
+
+ escaped = '<">'.encode(src_enc).encode(dst_enc, :xml=>:attr)
+ assert_equal('"&lt;&quot;&gt;"', escaped.encode('UTF-8'), "failed encoding #{src_enc} to #{dst_enc} with xml: :attr")
+
+ escaped = "<>".encode(src_enc).force_encoding("UTF-8").encode(dst_enc, src_enc, :xml=>:text)
+ assert_equal("&lt;&gt;", escaped.encode('UTF-8'), "failed encoding #{src_enc} to #{dst_enc} with xml: :text")
+
+ escaped = '<">'.encode(src_enc).force_encoding("UTF-8").encode(dst_enc, src_enc, :xml=>:attr)
+ assert_equal('"&lt;&quot;&gt;"', escaped.encode('UTF-8'), "failed encoding #{src_enc} to #{dst_enc} with xml: :attr")
+ end
+ end
+ # regression test; U+6E7F (湿) uses the same bytes in ISO-2022-JP as "<>"
+ assert_equal( "&lt;&gt;\u6E7F", "<>\u6E7F".encode("ISO-2022-JP").encode("ISO-2022-JP", :xml=>:text).encode("UTF-8"))
+ assert_equal("\"&lt;&gt;\u6E7F\"", "<>\u6E7F".encode("ISO-2022-JP").encode("ISO-2022-JP", :xml=>:attr).encode("UTF-8"))
+ end
+
def test_ascii_range
encodings = [
'US-ASCII', 'ASCII-8BIT',
@@ -469,6 +491,25 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00A0", "\xFF", 'IBM437') # non-breaking space
end
+ def test_IBM720
+ assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'IBM720') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'IBM720') }
+ assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'IBM720') }
+ check_both_ways("\u0627", "\x9F", 'IBM720') # ا
+ check_both_ways("\u0628", "\xA0", 'IBM720') # ب
+ check_both_ways("\u00BB", "\xAF", 'IBM720') # »
+ check_both_ways("\u2591", "\xB0", 'IBM720') # ░
+ check_both_ways("\u2510", "\xBF", 'IBM720') # ┐
+ check_both_ways("\u2514", "\xC0", 'IBM720') # └
+ check_both_ways("\u2567", "\xCF", 'IBM720') # ╧
+ check_both_ways("\u2568", "\xD0", 'IBM720') # ╨
+ check_both_ways("\u2580", "\xDF", 'IBM720') # ▀
+ check_both_ways("\u0636", "\xE0", 'IBM720') # ض
+ check_both_ways("\u064A", "\xEF", 'IBM720') # ي
+ check_both_ways("\u2261", "\xF0", 'IBM720') # ≡
+ check_both_ways("\u00A0", "\xFF", 'IBM720') # non-breaking space
+ end
+
def test_IBM775
check_both_ways("\u0106", "\x80", 'IBM775') # Ć
check_both_ways("\u00C5", "\x8F", 'IBM775') # Å
@@ -2250,12 +2291,19 @@ class TestTranscode < Test::Unit::TestCase
"#{bug} coderange should not have side effects")
end
- def test_universal_newline
+ def test_newline_options
bug11324 = '[ruby-core:69841] [Bug #11324]'
usascii = Encoding::US_ASCII
s = "A\nB\r\nC".force_encoding(usascii)
assert_equal("A\nB\nC", s.encode(usascii, universal_newline: true), bug11324)
assert_equal("A\nB\nC", s.encode(usascii, universal_newline: true, undef: :replace), bug11324)
assert_equal("A\nB\nC", s.encode(usascii, universal_newline: true, undef: :replace, replace: ''), bug11324)
+ assert_equal("A\nB\nC", s.encode(usascii, newline: :universal))
+ assert_equal("A\nB\nC", s.encode(usascii, newline: :universal, undef: :replace))
+ assert_equal("A\nB\nC", s.encode(usascii, newline: :universal, undef: :replace, replace: ''))
+ assert_equal("A\rB\r\rC", s.encode(usascii, cr_newline: true))
+ assert_equal("A\rB\r\rC", s.encode(usascii, newline: :cr))
+ assert_equal("A\r\nB\r\r\nC", s.encode(usascii, crlf_newline: true))
+ assert_equal("A\r\nB\r\r\nC", s.encode(usascii, newline: :crlf))
end
end
diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb
index b053e11607..9795223fda 100644
--- a/test/ruby/test_variable.rb
+++ b/test/ruby/test_variable.rb
@@ -29,12 +29,20 @@ class TestVariable < Test::Unit::TestCase
@@rule = "Cronus" # modifies @@rule in Gods
include Olympians
def ruler4
- EnvUtil.suppress_warning {
- @@rule
- }
+ @@rule
end
end
+ def test_setting_class_variable_on_module_through_inheritance
+ mod = Module.new
+ mod.class_variable_set(:@@foo, 1)
+ mod.freeze
+ c = Class.new { include(mod) }
+ assert_raise(FrozenError) { c.class_variable_set(:@@foo, 2) }
+ assert_raise(FrozenError) { c.class_eval("@@foo = 2") }
+ assert_equal(1, c.class_variable_get(:@@foo))
+ end
+
def test_singleton_class_included_class_variable
c = Class.new
c.extend(Olympians)
@@ -107,7 +115,7 @@ class TestVariable < Test::Unit::TestCase
atlas = Titans.new
assert_equal("Cronus", atlas.ruler0)
assert_equal("Zeus", atlas.ruler3)
- assert_equal("Cronus", atlas.ruler4)
+ assert_raise(RuntimeError) { atlas.ruler4 }
assert_nothing_raised do
class << Gods
defined?(@@rule) && @@rule
diff --git a/test/ruby/test_vm_dump.rb b/test/ruby/test_vm_dump.rb
index 68f0fa7f27..679ce94b91 100644
--- a/test/ruby/test_vm_dump.rb
+++ b/test/ruby/test_vm_dump.rb
@@ -16,6 +16,6 @@ class TestVMDump < Test::Unit::TestCase
end
def test_darwin_invalid_access
- assert_darwin_vm_dump_works(['-rfiddle', '-eFiddle.dlunwrap(100).class'])
+ assert_darwin_vm_dump_works(['-rfiddle', '-eFiddle.dlunwrap(100).inspect'])
end
end
diff --git a/test/rubygems/data/null-required-ruby-version.gemspec.rz b/test/rubygems/data/null-required-ruby-version.gemspec.rz
new file mode 100644
index 0000000000..f4ec1a9620
--- /dev/null
+++ b/test/rubygems/data/null-required-ruby-version.gemspec.rz
Binary files differ
diff --git a/test/rubygems/data/null-required-rubygems-version.gemspec.rz b/test/rubygems/data/null-required-rubygems-version.gemspec.rz
new file mode 100644
index 0000000000..db3d0af084
--- /dev/null
+++ b/test/rubygems/data/null-required-rubygems-version.gemspec.rz
Binary files differ
diff --git a/test/rubygems/data/null-type.gemspec.rz b/test/rubygems/data/null-type.gemspec.rz
index bad99289d1..2134fcde29 100644
--- a/test/rubygems/data/null-type.gemspec.rz
+++ b/test/rubygems/data/null-type.gemspec.rz
Binary files differ
diff --git a/test/rubygems/encrypted_private_key.pem b/test/rubygems/encrypted_private_key.pem
index 868f332b7c..d9667689a6 100644
--- a/test/rubygems/encrypted_private_key.pem
+++ b/test/rubygems/encrypted_private_key.pem
@@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-CBC,4E38D58B5A059DB6
+DEK-Info: AES-256-CBC,CB6FD0B173EF450C6EE21A01DD785C1D
-IgWLfnHVnkErKkhysrUMoE0ubkRDtJXZv9KR02jGGFk/kGqWyTqPk08uzhwVNM+l
-eOk0qfPykkJM3KZgqTsD6xfA1D5WqFp5mLoFXVVTn9I3acSZsqOY0FweCipwdVpI
-x+9Fl+v62kIW06dOjyWLE1abed9hHiXesGGsD87/RJSywy4OBxOcrhR1fJLK4ElR
-ya0UzI7rWnmZMChjaZBssfzT1DR79/dARXhon2m5EiIJDjMpc8BKGYlQy5RHCHwA
-cnrhUTTvsggZbQtmLZ/yVx8FSJ273XpYR0pmwbw4j1R+zeXQRK5MroBnCfOGcYa7
-rmpERmDW3VAuxXR20SUAGdo1XOMTDe1uLbaotn6e56pXghIaYROTPS+HsuOkAZGY
-OYWEkUoyog4l4n+h/C1umFfTFGvKNATLgDugONFvTw/PLbjvl+sWMy2QfqH0MlNB
-DIUPxhEVCFD9oB4nfB86WDAmPp1DH9/IBet/21kbQ2eTIzakTdG3XiC+xzAQRu68
-EOCTbasFWGxlCix66gt4xWMLksEg8UhWSpjS3/HsifrKyNMB8sfUFYmZmOYMW4mf
-NuEtpBL3AdHNObN8nQ75HfehukzNpbYVRsLzWrVgtxvXHVpnvoCCpCvQBMHeRZxK
-6m028mhH1m6yYE/uGFiRKLrN7BKAttbUiqnGgVIg/lQQilFWwylxQ6aXqJGmNgxa
-oihzWZRlXivIhhrM7VMnLoKAF/YfmWpP3zahGpBQGfObtPtm44R0ezXPdtsivnyu
-CmFOPGzRNMKZtH/lwVhuIIK3AFIGDsRRP9ySN4YfjQZnTdu2sRlxBnANP9m8W9T2
-p+C4zVkDYAbsuWq2HpHwsdL8gqIiXeptsHLqkNw+ulSSLyeBCgM9fpV3RsNGjwqu
-k8QLb1CYp2VX46CE8UKvOd/nyFnEsD+EAc3WangEwA41m2IaXcbs9Au7xsG9oacZ
-DrxlJVNxlxO9YyP9dNOTfP0fHIiygKQQY2aU3y3oRneu7ogYES5V2mUNH7cYUWVL
-CHPXAoUXJErvDQ/opW2DroA9Eqv9sST6WqBf6LXRcWU0ntfzcFUbEqgmCmB7Cbu2
-8udEn6iWilQahLyDoAShLkU7+Tk78Z1c6RuqjyY4VboZPzxrTYK8YIXzwX+jj9bG
-KIIGS5eghK185+AjlwtzJ7MBdoL323YIik6uOZluhnJHLaxjxUXGa1VqDgsyqGi7
-ISRMTpVTrbR+UtoEi4ZhMjobtFUr7lGkt24VkXwBKdoyryj4RPHGdp7Tf6XDJufQ
-+KKhqt8QrpOTPiMskFN2disOSF5/YZCmtT84nkhU7Hf1lkQ2kfx1zfNk0GqYYXOW
-zHOAczy8gWBRetDMnhRYohDzQGWn//b+2Wr2n1RD8D9kyjMRhpFMYfQGfRcuPGjW
-91k/T0XFcjcjeZPL9s+HITmrh7zg5WxbCfTEp91j3Oy1bns196SY77TE0BzUsqR2
-geJggcUMEfyvHiiCMtijmSSD9nf8tNIxLVL8Jaf1coA6e1CrlHnYAu2f/Q3GIcvU
-EEEmw+cZRwsk4fffYzh5psxxGdXKBv1KcQ/CeBhZL0WJsCp2y5oxwg==
+KqHn2Df8hSuwNE+W+60MnGtc6xpoXmF3iN25iVwcN67krYn+N6cBhjFeXwXccYwJ
+2gHSu4iEK9Qe32vK0yuv8N9h/fmsabZl0TotnEem/pqO5T8W4LxyK+Rw0s6RB30S
+C+mUisRADTanAxyBxsNU8xR8OAUNMAAxV1me6It0W2lfNE3t5jg/Kr0NWMoRUNRx
+dkE6WlD5D8jBeC3QdZ6OuE7QXOCEAWAjcFMc0d1WJq2t2r3TrLVfTH7EOoRyvL1H
+rrFRx/dEW1UJfM6P11wB5R0nhg3rDXF7oDFszjwO/3tzARke0NZuN37l301lYRl1
+aolO6sShJLa0Ml/TgNcJw0S6rc6a1Z52gTfQKztKcL1UX4HLZg75zKmn6qfatMBC
+iXn+pQRYNsOPQ5h4r7lBBqvuV+gBw+rN768tYpZ2/YVDaygxETHcZAFCdAw/JNbP
+d0XPIbP79NRrCgzSo58LKQGuOQf3Hh0vp1YS+MilMtm/eogoj1enSPM+ymStHRwG
+i+D00xCQ6blSOZ2eUUBJXt11YzP22GYnv+XTR/5kGKkTIvoRMfd+39bQyR32IEv2
+Z+yweAGQInD94eifT9ObbIayJ47y01KP0+Vj6hz4RCFsmJKsYiai5JiKlmf7lV9w
+7zH3TtCOx/xSyomesXVRkqvFkdyeguU72kXc5tiMPaDXGCOeV0GWyR1GU1DUX9/K
+60E7ym0Wx77WGMKk2fkirZzBdOeliyCRUXd7ccN2rBCjTwtjAUIk27lwzdUaTUv7
+EmjauDvSMFtir58c+zjlLmBaSQOzKcj0KXMp0Oucls9bD85WGGbGyzGhTa0AZ+/+
+cCEJt7RAwW0kTEO/uO+BAZe/zBoi9ek+QBn54FK3E7CXfS4Oi9Qbc3fwlVyTlVmz
+ZGrCncO0TIVGErFWK24Z7lX8rBnk8enfnamrPfKtwn4LG9aDfhSj8DtisjlRUVT5
+chDQ+CCi9rh3wXh28lyS+nXJ3yFidCzRgcsc3PpN/c4DNRggZc+C/KDw+J2FW+8Y
+p65OliBQHQcG0PnCa2xRyCGevytPG0rfNDgyaY33dPEo90mBLVcwLbzGiSGBHgFl
+pr8A/rqbnFpRO39NYbACeRFCqPpzyzfARCCcjcDoFrENdIaJui0fjlBkoV3B/KiK
+EVjDcgwt1HAtz8bV2YJ+OpQbhD7E90e2vTRMuXAH21Ygo32VOS0LRlCRc9ZyZW4z
+PTyO/6a+FbXZ1zhVJxu/0bmBERZ14WVmWq56oxQav8knpxYeYPgpEmIZnrHnJ1Ko
+UoXcc8Hy4NKtaBmDcaF8TCobNsRZTxO/htqpdyNsOrBSsnX2kP5D/O1l1vuVYi1/
+RYfUqL9dvGzvfsFuuDDjDlQ/fIA6pFzJV3fy4KJHlF1r33qaE/lNMdpKljBwvUII
+Vog4cGmzxssqK5q9kuogcuyeOuFODjBNW4qt0WylSi9bwwy3ZwaZLRqhngz6+tCV
+Jp45Gk881XiVe3aVU0l+4DmJJ9/5vwqjH5Vo/GJqFU6gzB+Zv/0plYeNkuE0Xo2z
+ecdxnGKVPl42q44lvczjDw2KX0ahxQrfrbcl48//zR295u9POzCL97d6zpioI2NR
-----END RSA PRIVATE KEY-----
diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb
new file mode 100644
index 0000000000..a09d0783f6
--- /dev/null
+++ b/test/rubygems/helper.rb
@@ -0,0 +1,1595 @@
+# frozen_string_literal: true
+
+require 'rubygems'
+
+# If bundler gemspec exists, add to stubs
+bundler_gemspec = File.expand_path("../../../bundler/bundler.gemspec", __FILE__)
+if File.exist?(bundler_gemspec)
+ Gem::Specification.dirs.unshift File.dirname(bundler_gemspec)
+ Gem::Specification.class_variable_set :@@stubs, nil
+ Gem::Specification.stubs
+ Gem::Specification.dirs.shift
+end
+
+begin
+ gem 'test-unit', '~> 3.0'
+rescue Gem::LoadError
+end
+
+if File.exist?(bundler_gemspec)
+ require_relative '../../bundler/lib/bundler'
+else
+ require 'bundler'
+end
+
+require 'test/unit'
+
+ENV["JARS_SKIP"] = "true" if Gem.java_platform? # avoid unnecessary and noisy `jar-dependencies` post install hook
+
+require 'rubygems/deprecate'
+
+require 'fileutils'
+require 'pathname'
+require 'pp'
+require 'rubygems/package'
+require 'shellwords'
+require 'tmpdir'
+require 'uri'
+require 'zlib'
+require 'benchmark' # stdlib
+require 'rubygems/mock_gem_ui'
+
+module Gem
+
+ ##
+ # Allows setting the gem path searcher.
+
+ def self.searcher=(searcher)
+ @searcher = searcher
+ end
+
+ ##
+ # Allows toggling Windows behavior.
+
+ def self.win_platform=(val)
+ @@win_platform = val
+ end
+
+ ##
+ # Allows setting path to Ruby.
+
+ def self.ruby=(ruby)
+ @ruby = ruby
+ end
+
+ ##
+ # Sets the default user interaction to a MockGemUi.
+
+ module DefaultUserInteraction
+ @ui = Gem::MockGemUi.new
+ end
+end
+
+require "rubygems/command"
+
+class Gem::Command
+ ##
+ # Allows resetting the hash of specific args per command.
+
+ def self.specific_extra_args_hash=(value)
+ @specific_extra_args_hash = value
+ end
+end
+
+##
+# RubyGemTestCase provides a variety of methods for testing rubygems and
+# gem-related behavior in a sandbox. Through RubyGemTestCase you can install
+# and uninstall gems, fetch remote gems through a stub fetcher and be assured
+# your normal set of gems is not affected.
+
+class Gem::TestCase < Test::Unit::TestCase
+ extend Gem::Deprecate
+
+ attr_accessor :fetcher # :nodoc:
+
+ attr_accessor :gem_repo # :nodoc:
+
+ attr_accessor :uri # :nodoc:
+
+ def assert_activate(expected, *specs)
+ specs.each do |spec|
+ case spec
+ when String then
+ Gem::Specification.find_by_name(spec).activate
+ when Gem::Specification then
+ spec.activate
+ else
+ flunk spec.inspect
+ end
+ end
+
+ loaded = Gem.loaded_specs.values.map(&:full_name)
+
+ assert_equal expected.sort, loaded.sort if expected
+ end
+
+ def assert_directory_exists(path, msg = nil)
+ msg = build_message(msg, "Expected path '#{path}' to be a directory")
+ assert_path_exist path
+ assert File.directory?(path), msg
+ end
+
+ # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L188
+ def _synchronize
+ yield
+ end
+
+ # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L546
+ def capture_subprocess_io
+ _synchronize do
+ begin
+ require "tempfile"
+
+ captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err")
+
+ orig_stdout, orig_stderr = $stdout.dup, $stderr.dup
+ $stdout.reopen captured_stdout
+ $stderr.reopen captured_stderr
+
+ yield
+
+ $stdout.rewind
+ $stderr.rewind
+
+ return captured_stdout.read, captured_stderr.read
+ ensure
+ captured_stdout.unlink
+ captured_stderr.unlink
+ $stdout.reopen orig_stdout
+ $stderr.reopen orig_stderr
+
+ orig_stdout.close
+ orig_stderr.close
+ captured_stdout.close
+ captured_stderr.close
+ end
+ end
+ end
+
+ ##
+ # Sets the ENABLE_SHARED entry in RbConfig::CONFIG to +value+ and restores
+ # the original value when the block ends
+
+ def enable_shared(value)
+ enable_shared = RbConfig::CONFIG['ENABLE_SHARED']
+ RbConfig::CONFIG['ENABLE_SHARED'] = value
+
+ yield
+ ensure
+ if enable_shared
+ RbConfig::CONFIG['enable_shared'] = enable_shared
+ else
+ RbConfig::CONFIG.delete 'enable_shared'
+ end
+ end
+
+ ##
+ # Sets the vendordir entry in RbConfig::CONFIG to +value+ and restores the
+ # original value when the block ends
+ #
+ def vendordir(value)
+ vendordir = RbConfig::CONFIG['vendordir']
+
+ if value
+ RbConfig::CONFIG['vendordir'] = value
+ else
+ RbConfig::CONFIG.delete 'vendordir'
+ end
+
+ yield
+ ensure
+ if vendordir
+ RbConfig::CONFIG['vendordir'] = vendordir
+ else
+ RbConfig::CONFIG.delete 'vendordir'
+ end
+ end
+
+ ##
+ # Sets the bindir entry in RbConfig::CONFIG to +value+ and restores the
+ # original value when the block ends
+ #
+ def bindir(value)
+ with_clean_path_to_ruby do
+ bindir = RbConfig::CONFIG['bindir']
+
+ if value
+ RbConfig::CONFIG['bindir'] = value
+ else
+ RbConfig::CONFIG.delete 'bindir'
+ end
+
+ begin
+ yield
+ ensure
+ if bindir
+ RbConfig::CONFIG['bindir'] = bindir
+ else
+ RbConfig::CONFIG.delete 'bindir'
+ end
+ end
+ end
+ end
+
+ ##
+ # Sets the EXEEXT entry in RbConfig::CONFIG to +value+ and restores the
+ # original value when the block ends
+ #
+ def exeext(value)
+ exeext = RbConfig::CONFIG['EXEEXT']
+
+ if value
+ RbConfig::CONFIG['EXEEXT'] = value
+ else
+ RbConfig::CONFIG.delete 'EXEEXT'
+ end
+
+ yield
+ ensure
+ if exeext
+ RbConfig::CONFIG['EXEEXT'] = exeext
+ else
+ RbConfig::CONFIG.delete 'EXEEXT'
+ end
+ end
+
+ def scan_make_command_lines(output)
+ output.scan(/^#{Regexp.escape make_command}(?:[[:blank:]].*)?$/)
+ end
+
+ def parse_make_command_line_targets(line)
+ args = line.sub(/^#{Regexp.escape make_command}/, "").shellsplit
+
+ targets = []
+
+ args.each do |arg|
+ case arg
+ when /\A(\w+)=/
+ else
+ targets << arg
+ end
+ end
+
+ targets << '' if targets.empty?
+
+ targets
+ end
+
+ def assert_contains_make_command(target, output, msg = nil)
+ if output.match(/\n/)
+ msg = build_message(msg,
+ "Expected output containing make command \"%s\", but was \n\nBEGIN_OF_OUTPUT\n%sEND_OF_OUTPUT" % [
+ ('%s %s' % [make_command, target]).rstrip,
+ output,
+ ]
+ )
+ else
+ msg = build_message(msg,
+ 'Expected make command "%s", but was "%s"' % [
+ ('%s %s' % [make_command, target]).rstrip,
+ output,
+ ]
+ )
+ end
+
+ assert scan_make_command_lines(output).any? {|line|
+ targets = parse_make_command_line_targets(line)
+
+ if targets.include?(target)
+ true
+ else
+ false
+ end
+ }, msg
+ end
+
+ include Gem::DefaultUserInteraction
+
+ ##
+ # #setup prepares a sandboxed location to install gems. All installs are
+ # directed to a temporary directory. All install plugins are removed.
+ #
+ # If the +RUBY+ environment variable is set the given path is used for
+ # Gem::ruby. The local platform is set to <tt>i386-mswin32</tt> for Windows
+ # or <tt>i686-darwin8.10.1</tt> otherwise.
+
+ def setup
+ @orig_env = ENV.to_hash
+ @tmp = File.expand_path("tmp")
+
+ FileUtils.mkdir_p @tmp
+
+ ENV['GEM_VENDOR'] = nil
+ ENV['GEMRC'] = nil
+ ENV['XDG_CACHE_HOME'] = nil
+ ENV['XDG_CONFIG_HOME'] = nil
+ ENV['XDG_DATA_HOME'] = nil
+ ENV['SOURCE_DATE_EPOCH'] = nil
+ ENV['BUNDLER_VERSION'] = nil
+
+ @current_dir = Dir.pwd
+ @fetcher = nil
+
+ @back_ui = Gem::DefaultUserInteraction.ui
+ @ui = Gem::MockGemUi.new
+ # This needs to be a new instance since we call use_ui(@ui) when we want to
+ # capture output
+ Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new
+
+ @tempdir = Dir.mktmpdir("test_rubygems_", @tmp)
+ @tempdir.tap(&Gem::UNTAINT)
+
+ ENV["TMPDIR"] = @tempdir
+
+ @orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE
+ Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
+ Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
+ File.join(@tempdir, 'system-gemrc')
+
+ @gemhome = File.join @tempdir, 'gemhome'
+ @userhome = File.join @tempdir, 'userhome'
+ ENV["GEM_SPEC_CACHE"] = File.join @tempdir, 'spec_cache'
+
+ @orig_ruby = if ENV['RUBY']
+ ruby = Gem.ruby
+ Gem.ruby = ENV['RUBY']
+ ruby
+ end
+
+ @git = ENV['GIT'] || (win_platform? ? 'git.exe' : 'git')
+
+ Gem.ensure_gem_subdirectories @gemhome
+ Gem.ensure_default_gem_subdirectories @gemhome
+
+ @orig_LOAD_PATH = $LOAD_PATH.dup
+ $LOAD_PATH.map! do |s|
+ expand_path = File.realpath(s) rescue File.expand_path(s)
+ if expand_path != s
+ expand_path.tap(&Gem::UNTAINT)
+ if s.instance_variable_defined?(:@gem_prelude_index)
+ expand_path.instance_variable_set(:@gem_prelude_index, expand_path)
+ end
+ expand_path.freeze if s.frozen?
+ s = expand_path
+ end
+ s
+ end
+
+ Dir.chdir @tempdir
+
+ ENV['HOME'] = @userhome
+ Gem.instance_variable_set :@config_file, nil
+ Gem.instance_variable_set :@user_home, nil
+ Gem.instance_variable_set :@config_home, nil
+ Gem.instance_variable_set :@data_home, nil
+ Gem.instance_variable_set :@gemdeps, nil
+ Gem.instance_variable_set :@env_requirements_by_name, nil
+ Gem.send :remove_instance_variable, :@ruby_version if
+ Gem.instance_variables.include? :@ruby_version
+
+ FileUtils.mkdir_p @userhome
+
+ ENV['GEM_PRIVATE_KEY_PASSPHRASE'] = PRIVATE_KEY_PASSPHRASE
+
+ Gem.instance_variable_set(:@default_specifications_dir, nil)
+ if Gem.java_platform?
+ @orig_default_gem_home = RbConfig::CONFIG['default_gem_home']
+ RbConfig::CONFIG['default_gem_home'] = @gemhome
+ else
+ Gem.instance_variable_set(:@default_dir, @gemhome)
+ end
+
+ @orig_bindir = RbConfig::CONFIG["bindir"]
+ RbConfig::CONFIG["bindir"] = File.join @gemhome, "bin"
+
+ @orig_sitelibdir = RbConfig::CONFIG["sitelibdir"]
+ new_sitelibdir = @orig_sitelibdir.sub(RbConfig::CONFIG["prefix"], @gemhome)
+ $LOAD_PATH.insert(Gem.load_path_insert_index, new_sitelibdir)
+ RbConfig::CONFIG["sitelibdir"] = new_sitelibdir
+
+ @orig_mandir = RbConfig::CONFIG["mandir"]
+ RbConfig::CONFIG["mandir"] = File.join @gemhome, "share", "man"
+
+ Gem::Specification.unresolved_deps.clear
+ Gem.use_paths(@gemhome)
+
+ Gem.loaded_specs.clear
+ Gem.instance_variable_set(:@activated_gem_paths, 0)
+ Gem.clear_default_specs
+ Bundler.reset!
+
+ Gem.configuration.verbose = true
+ Gem.configuration.update_sources = true
+
+ Gem::RemoteFetcher.fetcher = Gem::FakeFetcher.new
+
+ @gem_repo = "http://gems.example.com/"
+ @uri = URI.parse @gem_repo
+ Gem.sources.replace [@gem_repo]
+
+ Gem.searcher = nil
+ Gem::SpecFetcher.fetcher = nil
+
+ @orig_arch = RbConfig::CONFIG['arch']
+
+ if win_platform?
+ util_set_arch 'i386-mswin32'
+ else
+ util_set_arch 'i686-darwin8.10.1'
+ end
+
+ @orig_hooks = {}
+ %w[post_install_hooks done_installing_hooks post_uninstall_hooks pre_uninstall_hooks pre_install_hooks pre_reset_hooks post_reset_hooks post_build_hooks].each do |name|
+ @orig_hooks[name] = Gem.send(name).dup
+ end
+
+ @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
+ @orig_LOADED_FEATURES = $LOADED_FEATURES.dup
+ end
+
+ ##
+ # #teardown restores the process to its original state and removes the
+ # tempdir
+
+ def teardown
+ $LOAD_PATH.replace @orig_LOAD_PATH if @orig_LOAD_PATH
+ if @orig_LOADED_FEATURES
+ if @orig_LOAD_PATH
+ ($LOADED_FEATURES - @orig_LOADED_FEATURES).each do |feat|
+ $LOADED_FEATURES.delete(feat) if feat.start_with?(@tmp)
+ end
+ else
+ $LOADED_FEATURES.replace @orig_LOADED_FEATURES
+ end
+ end
+
+ RbConfig::CONFIG['arch'] = @orig_arch
+
+ if defined? Gem::RemoteFetcher
+ Gem::RemoteFetcher.fetcher = nil
+ end
+
+ Dir.chdir @current_dir
+
+ FileUtils.rm_rf @tempdir
+
+ ENV.replace(@orig_env)
+
+ Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
+ Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
+ @orig_SYSTEM_WIDE_CONFIG_FILE
+
+ Gem.ruby = @orig_ruby if @orig_ruby
+
+ RbConfig::CONFIG['mandir'] = @orig_mandir
+ RbConfig::CONFIG['sitelibdir'] = @orig_sitelibdir
+ RbConfig::CONFIG['bindir'] = @orig_bindir
+
+ Gem.instance_variable_set :@default_specifications_dir, nil
+ if Gem.java_platform?
+ RbConfig::CONFIG['default_gem_home'] = @orig_default_gem_home
+ else
+ Gem.instance_variable_set :@default_dir, nil
+ end
+
+ Gem::Specification.unresolved_deps.clear
+ Gem::refresh
+
+ @orig_hooks.each do |name, hooks|
+ Gem.send(name).replace hooks
+ end
+
+ @back_ui.close
+ end
+
+ def credential_setup
+ @temp_cred = File.join(@userhome, '.gem', 'credentials')
+ FileUtils.mkdir_p File.dirname(@temp_cred)
+ File.write @temp_cred, ':rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97'
+ File.chmod 0600, @temp_cred
+ end
+
+ def credential_teardown
+ FileUtils.rm_rf @temp_cred
+ end
+
+ def common_installer_setup
+ common_installer_teardown
+
+ Gem.post_build do |installer|
+ @post_build_hook_arg = installer
+ true
+ end
+
+ Gem.post_install do |installer|
+ @post_install_hook_arg = installer
+ end
+
+ Gem.post_uninstall do |uninstaller|
+ @post_uninstall_hook_arg = uninstaller
+ end
+
+ Gem.pre_install do |installer|
+ @pre_install_hook_arg = installer
+ true
+ end
+
+ Gem.pre_uninstall do |uninstaller|
+ @pre_uninstall_hook_arg = uninstaller
+ end
+ end
+
+ def common_installer_teardown
+ Gem.post_build_hooks.clear
+ Gem.post_install_hooks.clear
+ Gem.done_installing_hooks.clear
+ Gem.post_reset_hooks.clear
+ Gem.post_uninstall_hooks.clear
+ Gem.pre_install_hooks.clear
+ Gem.pre_reset_hooks.clear
+ Gem.pre_uninstall_hooks.clear
+ end
+
+ def without_any_upwards_gemfiles
+ ENV["BUNDLE_GEMFILE"] = File.join(@tempdir, "Gemfile")
+ end
+
+ ##
+ # A git_gem is used with a gem dependencies file. The gem created here
+ # has no files, just a gem specification for the given +name+ and +version+.
+ #
+ # Yields the +specification+ to the block, if given
+
+ def git_gem(name = 'a', version = 1)
+ have_git?
+
+ directory = File.join 'git', name
+ directory = File.expand_path directory
+
+ git_spec = Gem::Specification.new name, version do |specification|
+ yield specification if block_given?
+ end
+
+ FileUtils.mkdir_p directory
+
+ gemspec = "#{name}.gemspec"
+
+ File.open File.join(directory, gemspec), 'w' do |io|
+ io.write git_spec.to_ruby
+ end
+
+ head = nil
+
+ Dir.chdir directory do
+ unless File.exist? '.git'
+ system @git, 'init', '--quiet'
+ system @git, 'config', 'user.name', 'RubyGems Tests'
+ system @git, 'config', 'user.email', 'rubygems@example'
+ end
+
+ system @git, 'add', gemspec
+ system @git, 'commit', '-a', '-m', 'a non-empty commit message', '--quiet'
+ head = Gem::Util.popen(@git, 'rev-parse', 'master').strip
+ end
+
+ return name, git_spec.version, directory, head
+ end
+
+ ##
+ # Skips this test unless you have a git executable
+
+ def have_git?
+ return if in_path? @git
+
+ skip 'cannot find git executable, use GIT environment variable to set'
+ end
+
+ def in_path?(executable) # :nodoc:
+ return true if %r{\A([A-Z]:|/)} =~ executable and File.exist? executable
+
+ ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory|
+ File.exist? File.join directory, executable
+ end
+ end
+
+ ##
+ # Builds and installs the Gem::Specification +spec+
+
+ def install_gem(spec, options = {})
+ require 'rubygems/installer'
+
+ gem = spec.cache_file
+
+ unless File.exist? gem
+ use_ui Gem::MockGemUi.new do
+ Dir.chdir @tempdir do
+ Gem::Package.build spec
+ end
+ end
+
+ gem = File.join(@tempdir, File.basename(gem)).tap(&Gem::UNTAINT)
+ end
+
+ Gem::Installer.at(gem, options.merge({:wrappers => true})).install
+ end
+
+ ##
+ # Builds and installs the Gem::Specification +spec+ into the user dir
+
+ def install_gem_user(spec)
+ install_gem spec, :user_install => true
+ end
+
+ ##
+ # Uninstalls the Gem::Specification +spec+
+ def uninstall_gem(spec)
+ require 'rubygems/uninstaller'
+
+ Class.new(Gem::Uninstaller) do
+ def ask_if_ok(spec)
+ true
+ end
+ end.new(spec.name, :executables => true, :user_install => true).uninstall
+ end
+
+ ##
+ # Enables pretty-print for all tests
+
+ def mu_pp(obj)
+ s = String.new
+ s = PP.pp obj, s
+ s = s.force_encoding(Encoding.default_external)
+ s.chomp
+ end
+
+ ##
+ # Reads a Marshal file at +path+
+
+ def read_cache(path)
+ File.open path.dup.tap(&Gem::UNTAINT), 'rb' do |io|
+ Marshal.load io.read
+ end
+ end
+
+ ##
+ # Reads a binary file at +path+
+
+ def read_binary(path)
+ Gem.read_binary path
+ end
+
+ ##
+ # Writes a binary file to +path+ which is relative to +@gemhome+
+
+ def write_file(path)
+ path = File.join @gemhome, path unless Pathname.new(path).absolute?
+ dir = File.dirname path
+ FileUtils.mkdir_p dir unless File.directory? dir
+
+ File.open path, 'wb' do |io|
+ yield io if block_given?
+ end
+
+ path
+ end
+
+ ##
+ # Load a YAML string, the psych 3 way
+
+ def load_yaml(yaml)
+ if YAML.respond_to?(:unsafe_load)
+ YAML.unsafe_load(yaml)
+ else
+ YAML.load(yaml)
+ end
+ end
+
+ ##
+ # Load a YAML file, the psych 3 way
+
+ def load_yaml_file(file)
+ if YAML.respond_to?(:unsafe_load_file)
+ YAML.unsafe_load_file(file)
+ else
+ YAML.load_file(file)
+ end
+ end
+
+ def all_spec_names
+ Gem::Specification.map(&:full_name)
+ end
+
+ ##
+ # Creates a Gem::Specification with a minimum of extra work. +name+ and
+ # +version+ are the gem's name and version, platform, author, email,
+ # homepage, summary and description are defaulted. The specification is
+ # yielded for customization.
+ #
+ # The gem is added to the installed gems in +@gemhome+ and the runtime.
+ #
+ # Use this with #write_file to build an installed gem.
+
+ def quick_gem(name, version='2')
+ require 'rubygems/specification'
+
+ spec = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = name
+ s.version = version
+ s.author = 'A User'
+ s.email = 'example@example.com'
+ s.homepage = 'http://example.com'
+ s.summary = "this is a summary"
+ s.description = "This is a test description"
+
+ yield(s) if block_given?
+ end
+
+ written_path = write_file spec.spec_file do |io|
+ io.write spec.to_ruby_for_cache
+ end
+
+ spec.loaded_from = written_path
+
+ Gem::Specification.reset
+
+ return spec
+ end
+
+ ##
+ # Builds a gem from +spec+ and places it in <tt>File.join @gemhome,
+ # 'cache'</tt>. Automatically creates files based on +spec.files+
+
+ def util_build_gem(spec)
+ dir = spec.gem_dir
+ FileUtils.mkdir_p dir
+
+ Dir.chdir dir do
+ spec.files.each do |file|
+ next if File.exist? file
+ FileUtils.mkdir_p File.dirname(file)
+
+ File.open file, 'w' do |fp|
+ fp.puts "# #{file}"
+ end
+ end
+
+ use_ui Gem::MockGemUi.new do
+ Gem::Package.build spec
+ end
+
+ cache = spec.cache_file
+ FileUtils.mv File.basename(cache), cache
+ end
+ end
+
+ def util_remove_gem(spec)
+ FileUtils.rm_rf spec.cache_file
+ FileUtils.rm_rf spec.spec_file
+ end
+
+ ##
+ # Removes all installed gems from +@gemhome+.
+
+ def util_clear_gems
+ FileUtils.rm_rf File.join(@gemhome, "gems")
+ FileUtils.mkdir File.join(@gemhome, "gems")
+ FileUtils.rm_rf File.join(@gemhome, "specifications")
+ FileUtils.mkdir File.join(@gemhome, "specifications")
+ Gem::Specification.reset
+ end
+
+ ##
+ # Install the provided specs
+
+ def install_specs(*specs)
+ specs.each do |spec|
+ Gem::Installer.for_spec(spec, :force => true).install
+ end
+
+ Gem.searcher = nil
+ end
+
+ ##
+ # Installs the provided default specs including writing the spec file
+
+ def install_default_gems(*specs)
+ specs.each do |spec|
+ installer = Gem::Installer.for_spec(spec, :install_as_default => true)
+ installer.install
+ Gem.register_default_spec(spec)
+ end
+ end
+
+ def loaded_spec_names
+ Gem.loaded_specs.values.map(&:full_name).sort
+ end
+
+ def unresolved_names
+ Gem::Specification.unresolved_deps.values.map(&:to_s).sort
+ end
+
+ def new_default_spec(name, version, deps = nil, *files)
+ spec = util_spec name, version, deps
+
+ spec.loaded_from = File.join(@gemhome, "specifications", "default", spec.spec_name)
+ spec.files = files
+
+ lib_dir = File.join(@tempdir, "default_gems", "lib")
+ lib_dir.instance_variable_set(:@gem_prelude_index, lib_dir)
+ Gem.instance_variable_set(:@default_gem_load_paths, [*Gem.send(:default_gem_load_paths), lib_dir])
+ $LOAD_PATH.unshift(lib_dir)
+ files.each do |file|
+ rb_path = File.join(lib_dir, file)
+ FileUtils.mkdir_p(File.dirname(rb_path))
+ File.open(rb_path, "w") do |rb|
+ rb << "# #{file}"
+ end
+ end
+
+ spec
+ end
+
+ ##
+ # Creates a spec with +name+, +version+. +deps+ can specify the dependency
+ # or a +block+ can be given for full customization of the specification.
+
+ def util_spec(name, version = 2, deps = nil, *files) # :yields: specification
+ raise "deps or block, not both" if deps and block_given?
+
+ spec = Gem::Specification.new do |s|
+ s.platform = Gem::Platform::RUBY
+ s.name = name
+ s.version = version
+ s.author = 'A User'
+ s.email = 'example@example.com'
+ s.homepage = 'http://example.com'
+ s.summary = "this is a summary"
+ s.description = "This is a test description"
+
+ s.files.push(*files) unless files.empty?
+
+ yield s if block_given?
+ end
+
+ if deps
+ deps.keys.each do |n|
+ spec.add_dependency n, (deps[n] || '>= 0')
+ end
+ end
+
+ unless files.empty?
+ write_file spec.spec_file do |io|
+ io.write spec.to_ruby_for_cache
+ end
+
+ util_build_gem spec
+
+ FileUtils.rm spec.spec_file
+ end
+
+ return spec
+ end
+
+ ##
+ # Creates a gem with +name+, +version+ and +deps+. The specification will
+ # be yielded before gem creation for customization. The gem will be placed
+ # in <tt>File.join @tempdir, 'gems'</tt>. The specification and .gem file
+ # location are returned.
+
+ def util_gem(name, version, deps = nil, &block)
+ if deps
+ block = proc do |s|
+ deps.keys.each do |n|
+ s.add_dependency n, (deps[n] || '>= 0')
+ end
+ end
+ end
+
+ spec = quick_gem(name, version, &block)
+
+ util_build_gem spec
+
+ cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
+ FileUtils.mkdir_p File.dirname cache_file
+ FileUtils.mv spec.cache_file, cache_file
+ FileUtils.rm spec.spec_file
+
+ spec.loaded_from = nil
+
+ [spec, cache_file]
+ end
+
+ ##
+ # Gzips +data+.
+
+ def util_gzip(data)
+ out = StringIO.new
+
+ Zlib::GzipWriter.wrap out do |io|
+ io.write data
+ end
+
+ out.string
+ end
+
+ ##
+ # Creates several default gems which all have a lib/code.rb file. The gems
+ # are not installed but are available in the cache dir.
+ #
+ # +@a1+:: gem a version 1, this is the best-described gem.
+ # +@a2+:: gem a version 2
+ # +@a3a:: gem a version 3.a
+ # +@a_evil9+:: gem a_evil version 9, use this to ensure similarly-named gems
+ # don't collide with a.
+ # +@b2+:: gem b version 2
+ # +@c1_2+:: gem c version 1.2
+ # +@pl1+:: gem pl version 1, this gem has a legacy platform of i386-linux.
+ #
+ # Additional +prerelease+ gems may also be created:
+ #
+ # +@a2_pre+:: gem a version 2.a
+ # TODO: nuke this and fix tests. this should speed up a lot
+
+ def util_make_gems(prerelease = false)
+ @a1 = quick_gem 'a', '1' do |s|
+ s.files = %w[lib/code.rb]
+ s.require_paths = %w[lib]
+ s.date = Gem::Specification::TODAY - 86400
+ s.homepage = 'http://a.example.com'
+ s.email = %w[example@example.com example2@example.com]
+ s.authors = %w[Example Example2]
+ s.description = <<-DESC
+This line is really, really long. So long, in fact, that it is more than eighty characters long! The purpose of this line is for testing wrapping behavior because sometimes people don't wrap their text to eighty characters. Without the wrapping, the text might not look good in the RSS feed.
+
+Also, a list:
+ * An entry that\'s actually kind of sort
+ * an entry that\'s really long, which will probably get wrapped funny. That's ok, somebody wasn't thinking straight when they made it more than eighty characters.
+ DESC
+ end
+
+ init = proc do |s|
+ s.files = %w[lib/code.rb]
+ s.require_paths = %w[lib]
+ end
+
+ @a2 = quick_gem('a', '2', &init)
+ @a3a = quick_gem('a', '3.a', &init)
+ @a_evil9 = quick_gem('a_evil', '9', &init)
+ @b2 = quick_gem('b', '2', &init)
+ @c1_2 = quick_gem('c', '1.2', &init)
+ @x = quick_gem('x', '1', &init)
+ @dep_x = quick_gem('dep_x', '1') do |s|
+ s.files = %w[lib/code.rb]
+ s.require_paths = %w[lib]
+ s.add_dependency 'x', '>= 1'
+ end
+
+ @pl1 = quick_gem 'pl', '1' do |s| # l for legacy
+ s.files = %w[lib/code.rb]
+ s.require_paths = %w[lib]
+ s.platform = Gem::Platform.new 'i386-linux'
+ s.instance_variable_set :@original_platform, 'i386-linux'
+ end
+
+ if prerelease
+ @a2_pre = quick_gem('a', '2.a', &init)
+ write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb])
+ util_build_gem @a2_pre
+ end
+
+ write_file File.join(*%W[gems #{@a1.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@a2.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@a_evil9.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@b2.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@x.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb])
+
+ [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1, @x, @dep_x].each do |spec|
+ util_build_gem spec
+ end
+
+ FileUtils.rm_r File.join(@gemhome, "gems", @pl1.original_name)
+ end
+
+ ##
+ # Set the platform to +arch+
+
+ def util_set_arch(arch)
+ RbConfig::CONFIG['arch'] = arch
+ platform = Gem::Platform.new arch
+
+ Gem.instance_variable_set :@platforms, nil
+ Gem::Platform.instance_variable_set :@local, nil
+
+ yield if block_given?
+
+ platform
+ end
+
+ ##
+ # Add +spec+ to +@fetcher+ serving the data in the file +path+.
+ # +repo+ indicates which repo to make +spec+ appear to be in.
+
+ def add_to_fetcher(spec, path=nil, repo=@gem_repo)
+ path ||= spec.cache_file
+ @fetcher.data["#{@gem_repo}gems/#{spec.file_name}"] = read_binary(path)
+ end
+
+ ##
+ # Sets up Gem::SpecFetcher to return information from the gems in +specs+.
+
+ def util_setup_spec_fetcher(*specs)
+ all_specs = Gem::Specification.to_a + specs
+ Gem::Specification._resort! all_specs
+
+ spec_fetcher = Gem::SpecFetcher.fetcher
+
+ prerelease, all = all_specs.partition {|spec| spec.version.prerelease? }
+ latest = Gem::Specification._latest_specs all_specs
+
+ spec_fetcher.specs[@uri] = []
+ all.each do |spec|
+ spec_fetcher.specs[@uri] << spec.name_tuple
+ end
+
+ spec_fetcher.latest_specs[@uri] = []
+ latest.each do |spec|
+ spec_fetcher.latest_specs[@uri] << spec.name_tuple
+ end
+
+ spec_fetcher.prerelease_specs[@uri] = []
+ prerelease.each do |spec|
+ spec_fetcher.prerelease_specs[@uri] << spec.name_tuple
+ end
+
+ # HACK for test_download_to_cache
+ unless Gem::RemoteFetcher === @fetcher
+ v = Gem.marshal_version
+
+ specs = all.map {|spec| spec.name_tuple }
+ s_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic specs
+
+ latest_specs = latest.map do |spec|
+ spec.name_tuple
+ end
+
+ l_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic latest_specs
+
+ prerelease_specs = prerelease.map {|spec| spec.name_tuple }
+ p_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic prerelease_specs
+
+ @fetcher.data["#{@gem_repo}specs.#{v}.gz"] = s_zip
+ @fetcher.data["#{@gem_repo}latest_specs.#{v}.gz"] = l_zip
+ @fetcher.data["#{@gem_repo}prerelease_specs.#{v}.gz"] = p_zip
+
+ write_marshalled_gemspecs(*all_specs)
+ end
+
+ nil # force errors
+ end
+
+ def write_marshalled_gemspecs(*all_specs)
+ v = Gem.marshal_version
+
+ all_specs.each do |spec|
+ path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz"
+ data = Marshal.dump spec
+ data_deflate = Zlib::Deflate.deflate data
+ @fetcher.data[path] = data_deflate
+ end
+ end
+
+ ##
+ # Deflates +data+
+
+ def util_zip(data)
+ Zlib::Deflate.deflate data
+ end
+
+ def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil, description = nil, engine = "ruby", engine_version = nil)
+ if Gem.instance_variables.include? :@ruby_version
+ Gem.send :remove_instance_variable, :@ruby_version
+ end
+
+ @RUBY_VERSION = RUBY_VERSION
+ @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
+ @RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION)
+ @RUBY_DESCRIPTION = RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION)
+ @RUBY_ENGINE = RUBY_ENGINE
+ @RUBY_ENGINE_VERSION = RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION)
+
+ util_clear_RUBY_VERSION
+
+ Object.const_set :RUBY_VERSION, version
+ Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel
+ Object.const_set :RUBY_REVISION, revision if revision
+ Object.const_set :RUBY_DESCRIPTION, description if description
+ Object.const_set :RUBY_ENGINE, engine
+ Object.const_set :RUBY_ENGINE_VERSION, engine_version if engine_version
+ end
+
+ def util_restore_RUBY_VERSION
+ util_clear_RUBY_VERSION
+
+ Object.const_set :RUBY_VERSION, @RUBY_VERSION
+ Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if
+ defined?(@RUBY_PATCHLEVEL)
+ Object.const_set :RUBY_REVISION, @RUBY_REVISION if
+ defined?(@RUBY_REVISION)
+ Object.const_set :RUBY_DESCRIPTION, @RUBY_DESCRIPTION if
+ defined?(@RUBY_DESCRIPTION)
+ Object.const_set :RUBY_ENGINE, @RUBY_ENGINE
+ Object.const_set :RUBY_ENGINE_VERSION, @RUBY_ENGINE_VERSION if
+ defined?(@RUBY_ENGINE_VERSION)
+ end
+
+ def util_clear_RUBY_VERSION
+ Object.send :remove_const, :RUBY_VERSION
+ Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
+ Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION)
+ Object.send :remove_const, :RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION)
+ Object.send :remove_const, :RUBY_ENGINE
+ Object.send :remove_const, :RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION)
+ end
+
+ ##
+ # Is this test being run on a Windows platform?
+
+ def self.win_platform?
+ Gem.win_platform?
+ end
+
+ ##
+ # Is this test being run on a Windows platform?
+
+ def win_platform?
+ Gem.win_platform?
+ end
+
+ ##
+ # Is this test being run on a Java platform?
+
+ def self.java_platform?
+ Gem.java_platform?
+ end
+
+ ##
+ # Is this test being run on a Java platform?
+
+ def java_platform?
+ Gem.java_platform?
+ end
+
+ ##
+ # Returns whether or not we're on a version of Ruby built with VC++ (or
+ # Borland) versus Cygwin, Mingw, etc.
+
+ def self.vc_windows?
+ RUBY_PLATFORM.match('mswin')
+ end
+
+ ##
+ # Returns whether or not we're on a version of Ruby built with VC++ (or
+ # Borland) versus Cygwin, Mingw, etc.
+
+ def vc_windows?
+ RUBY_PLATFORM.match('mswin')
+ end
+
+ ##
+ # Returns the make command for the current platform. For versions of Ruby
+ # built on MS Windows with VC++ or Borland it will return 'nmake'. On all
+ # other platforms, including Cygwin, it will return 'make'.
+
+ def self.make_command
+ ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make')
+ end
+
+ ##
+ # Returns the make command for the current platform. For versions of Ruby
+ # built on MS Windows with VC++ or Borland it will return 'nmake'. On all
+ # other platforms, including Cygwin, it will return 'make'.
+
+ def make_command
+ ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make')
+ end
+
+ ##
+ # Returns whether or not the nmake command could be found.
+
+ def nmake_found?
+ system('nmake /? 1>NUL 2>&1')
+ end
+
+ # In case we're building docs in a background process, this method waits for
+ # that process to exit (or if it's already been reaped, or never happened,
+ # swallows the Errno::ECHILD error).
+ def wait_for_child_process_to_exit
+ Process.wait if Process.respond_to?(:fork)
+ rescue Errno::ECHILD
+ end
+
+ ##
+ # Allows tests to use a random (but controlled) port number instead of
+ # a hardcoded one. This helps CI tools when running parallels builds on
+ # the same builder slave.
+
+ def self.process_based_port
+ @@process_based_port ||= 8000 + $$ % 1000
+ end
+
+ ##
+ # See ::process_based_port
+
+ def process_based_port
+ self.class.process_based_port
+ end
+
+ ##
+ # Allows the proper version of +rake+ to be used for the test.
+
+ def build_rake_in(good=true)
+ gem_ruby = Gem.ruby
+ Gem.ruby = self.class.rubybin
+ env_rake = ENV["rake"]
+ rake = (good ? @@good_rake : @@bad_rake)
+ ENV["rake"] = rake
+ yield rake
+ ensure
+ Gem.ruby = gem_ruby
+ if env_rake
+ ENV["rake"] = env_rake
+ else
+ ENV.delete("rake")
+ end
+ end
+
+ ##
+ # Finds the path to the Ruby executable
+
+ def self.rubybin
+ ruby = ENV["RUBY"]
+ return ruby if ruby
+ ruby = "ruby"
+ rubyexe = "#{ruby}.exe"
+
+ 3.times do
+ if File.exist? ruby and File.executable? ruby and !File.directory? ruby
+ return File.expand_path(ruby)
+ end
+ if File.exist? rubyexe and File.executable? rubyexe
+ return File.expand_path(rubyexe)
+ end
+ ruby = File.join("..", ruby)
+ end
+
+ begin
+ Gem.ruby
+ rescue LoadError
+ "ruby"
+ end
+ end
+
+ def ruby_with_rubygems_in_load_path
+ [Gem.ruby, "-I", rubygems_path]
+ end
+
+ def rubygems_path
+ $LOAD_PATH.find{|p| p == File.dirname($LOADED_FEATURES.find{|f| f.end_with?("/rubygems.rb") }) }
+ end
+
+ def with_clean_path_to_ruby
+ orig_ruby = Gem.ruby
+
+ Gem.instance_variable_set :@ruby, nil
+
+ yield
+ ensure
+ Gem.instance_variable_set :@ruby, orig_ruby
+ end
+
+ class << self
+ # :nodoc:
+ ##
+ # Return the join path, with escaping backticks, dollars, and
+ # double-quotes. Unlike `shellescape`, equal-sign is not escaped.
+
+ private
+
+ def escape_path(*path)
+ path = File.join(*path)
+ if %r{\A[-+:/=@,.\w]+\z} =~ path
+ path
+ else
+ "\"#{path.gsub(/[`$"]/, '\\&')}\""
+ end
+ end
+ end
+
+ @@good_rake = "#{rubybin} #{escape_path(__dir__, 'good_rake.rb')}"
+ @@bad_rake = "#{rubybin} #{escape_path(__dir__, 'bad_rake.rb')}"
+
+ ##
+ # Construct a new Gem::Dependency.
+
+ def dep(name, *requirements)
+ Gem::Dependency.new name, *requirements
+ end
+
+ ##
+ # Constructs a Gem::Resolver::DependencyRequest from a
+ # Gem::Dependency +dep+, a +from_name+ and +from_version+ requesting the
+ # dependency and a +parent+ DependencyRequest
+
+ def dependency_request(dep, from_name, from_version, parent = nil)
+ remote = Gem::Source.new @uri
+
+ unless parent
+ parent_dep = dep from_name, from_version
+ parent = Gem::Resolver::DependencyRequest.new parent_dep, nil
+ end
+
+ spec = Gem::Resolver::IndexSpecification.new \
+ nil, from_name, from_version, remote, Gem::Platform::RUBY
+ activation = Gem::Resolver::ActivationRequest.new spec, parent
+
+ Gem::Resolver::DependencyRequest.new dep, activation
+ end
+
+ ##
+ # Constructs a new Gem::Requirement.
+
+ def req(*requirements)
+ return requirements.first if Gem::Requirement === requirements.first
+ Gem::Requirement.create requirements
+ end
+
+ ##
+ # Constructs a new Gem::Specification.
+
+ def spec(name, version, &block)
+ Gem::Specification.new name, v(version), &block
+ end
+
+ ##
+ # Creates a SpecFetcher pre-filled with the gems or specs defined in the
+ # block.
+ #
+ # Yields a +fetcher+ object that responds to +spec+ and +gem+. +spec+ adds
+ # a specification to the SpecFetcher while +gem+ adds both a specification
+ # and the gem data to the RemoteFetcher so the built gem can be downloaded.
+ #
+ # If only the a-3 gem is supposed to be downloaded you can save setup
+ # time by creating only specs for the other versions:
+ #
+ # spec_fetcher do |fetcher|
+ # fetcher.spec 'a', 1
+ # fetcher.spec 'a', 2, 'b' => 3 # dependency on b = 3
+ # fetcher.gem 'a', 3 do |spec|
+ # # spec is a Gem::Specification
+ # # ...
+ # end
+ # end
+
+ def spec_fetcher(repository = @gem_repo)
+ Gem::TestCase::SpecFetcherSetup.declare self, repository do |spec_fetcher_setup|
+ yield spec_fetcher_setup if block_given?
+ end
+ end
+
+ ##
+ # Construct a new Gem::Version.
+
+ def v(string)
+ Gem::Version.create string
+ end
+
+ ##
+ # A vendor_gem is used with a gem dependencies file. The gem created here
+ # has no files, just a gem specification for the given +name+ and +version+.
+ #
+ # Yields the +specification+ to the block, if given
+
+ def vendor_gem(name = 'a', version = 1)
+ directory = File.join 'vendor', name
+
+ FileUtils.mkdir_p directory
+
+ save_gemspec name, version, directory
+ end
+
+ ##
+ # create_gemspec creates gem specification in given +directory+ or '.'
+ # for the given +name+ and +version+.
+ #
+ # Yields the +specification+ to the block, if given
+
+ def save_gemspec(name = 'a', version = 1, directory = '.')
+ vendor_spec = Gem::Specification.new name, version do |specification|
+ yield specification if block_given?
+ end
+
+ File.open File.join(directory, "#{name}.gemspec"), 'w' do |io|
+ io.write vendor_spec.to_ruby
+ end
+
+ return name, vendor_spec.version, directory
+ end
+
+ ##
+ # The StaticSet is a static set of gem specifications used for testing only.
+ # It is available by requiring Gem::TestCase.
+
+ class StaticSet < Gem::Resolver::Set
+ ##
+ # A StaticSet ignores remote because it has a fixed set of gems.
+
+ attr_accessor :remote
+
+ ##
+ # Creates a new StaticSet for the given +specs+
+
+ def initialize(specs)
+ super()
+
+ @specs = specs
+
+ @remote = true
+ end
+
+ ##
+ # Adds +spec+ to this set.
+
+ def add(spec)
+ @specs << spec
+ end
+
+ ##
+ # Finds +dep+ in this set.
+
+ def find_spec(dep)
+ @specs.reverse_each do |s|
+ return s if dep.matches_spec? s
+ end
+ end
+
+ ##
+ # Finds all gems matching +dep+ in this set.
+
+ def find_all(dep)
+ @specs.find_all {|s| dep.match? s, @prerelease }
+ end
+
+ ##
+ # Loads a Gem::Specification from this set which has the given +name+,
+ # version +ver+, +platform+. The +source+ is ignored.
+
+ def load_spec(name, ver, platform, source)
+ dep = Gem::Dependency.new name, ver
+ spec = find_spec dep
+
+ Gem::Specification.new spec.name, spec.version do |s|
+ s.platform = spec.platform
+ end
+ end
+
+ def prefetch(reqs) # :nodoc:
+ end
+ end
+
+ ##
+ # Loads certificate named +cert_name+ from <tt>test/rubygems/</tt>.
+
+ def self.load_cert(cert_name)
+ cert_file = cert_path cert_name
+
+ cert = File.read cert_file
+
+ OpenSSL::X509::Certificate.new cert
+ end
+
+ ##
+ # Returns the path to the certificate named +cert_name+ from
+ # <tt>test/rubygems/</tt>.
+
+ def self.cert_path(cert_name)
+ if 32 == (Time.at(2**32) rescue 32)
+ cert_file = "#{__dir__}/#{cert_name}_cert_32.pem"
+
+ return cert_file if File.exist? cert_file
+ end
+
+ "#{__dir__}/#{cert_name}_cert.pem"
+ end
+
+ ##
+ # Loads a private key named +key_name+ with +passphrase+ in <tt>test/rubygems/</tt>
+
+ def self.load_key(key_name, passphrase = nil)
+ key_file = key_path key_name
+
+ key = File.read key_file
+
+ OpenSSL::PKey.read key, passphrase
+ end
+
+ ##
+ # Returns the path to the key named +key_name+ from <tt>test/rubygems</tt>
+
+ def self.key_path(key_name)
+ "#{__dir__}/#{key_name}_key.pem"
+ end
+
+ # :stopdoc:
+ # only available in RubyGems tests
+
+ PRIVATE_KEY_PASSPHRASE = 'Foo bar'.freeze
+
+ begin
+ PRIVATE_KEY = load_key 'private'
+ PRIVATE_KEY_PATH = key_path 'private'
+
+ # ENCRYPTED_PRIVATE_KEY is PRIVATE_KEY encrypted with PRIVATE_KEY_PASSPHRASE
+ ENCRYPTED_PRIVATE_KEY = load_key 'encrypted_private', PRIVATE_KEY_PASSPHRASE
+ ENCRYPTED_PRIVATE_KEY_PATH = key_path 'encrypted_private'
+
+ PUBLIC_KEY = PRIVATE_KEY.public_key
+
+ PUBLIC_CERT = load_cert 'public'
+ PUBLIC_CERT_PATH = cert_path 'public'
+ rescue Errno::ENOENT
+ PRIVATE_KEY = nil
+ PUBLIC_KEY = nil
+ PUBLIC_CERT = nil
+ end if Gem::HAVE_OPENSSL
+end
+
+# https://github.com/seattlerb/minitest/blob/13c48a03d84a2a87855a4de0c959f96800100357/lib/minitest/mock.rb#L192
+class Object
+ def stub(name, val_or_callable, *block_args)
+ new_name = "__minitest_stub__#{name}"
+
+ metaclass = class << self; self; end
+
+ if respond_to? name and not methods.map(&:to_s).include? name.to_s
+ metaclass.send :define_method, name do |*args|
+ super(*args)
+ end
+ end
+
+ metaclass.send :alias_method, new_name, name
+
+ metaclass.send :define_method, name do |*args, &blk|
+ if val_or_callable.respond_to? :call
+ val_or_callable.call(*args, &blk)
+ else
+ blk.call(*block_args) if blk
+ val_or_callable
+ end
+ end
+
+ metaclass.send(:ruby2_keywords, name) if metaclass.respond_to?(:ruby2_keywords, true)
+
+ yield self
+ ensure
+ metaclass.send :undef_method, name
+ metaclass.send :alias_method, name, new_name
+ metaclass.send :undef_method, new_name
+ end
+end
+
+require_relative 'utilities'
diff --git a/test/rubygems/installer_test_case.rb b/test/rubygems/installer_test_case.rb
new file mode 100644
index 0000000000..824ac53a82
--- /dev/null
+++ b/test/rubygems/installer_test_case.rb
@@ -0,0 +1,247 @@
+# frozen_string_literal: true
+require_relative 'helper'
+require 'rubygems/installer'
+
+class Gem::Installer
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :bin_dir
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :build_args
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :gem_dir
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :force
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :format
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :gem_home
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :env_shebang
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :ignore_dependencies
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :format_executable
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :security_policy
+
+ ##
+ # Available through requiring rubygems/installer_test_case
+
+ attr_writer :wrappers
+end
+
+##
+# A test case for Gem::Installer.
+
+class Gem::InstallerTestCase < Gem::TestCase
+ def setup
+ super
+
+ Gem::Installer.path_warning = false
+ end
+
+ ##
+ # The path where installed executables live
+
+ def util_inst_bindir
+ File.join @gemhome, "bin"
+ end
+
+ ##
+ # Adds an executable named "executable" to +spec+ with the given +shebang+.
+ #
+ # The executable is also written to the bin dir in @tmpdir and the installed
+ # gem directory for +spec+.
+
+ def util_make_exec(spec = @spec, shebang = "#!/usr/bin/ruby", bindir = "bin")
+ spec.executables = %w[executable]
+ spec.bindir = bindir
+
+ exec_path = spec.bin_file "executable"
+ write_file exec_path do |io|
+ io.puts shebang
+ end
+
+ bin_path = File.join @tempdir, "bin", "executable"
+ write_file bin_path do |io|
+ io.puts shebang
+ end
+ end
+
+ ##
+ # Creates the following instance variables:
+ #
+ # @spec::
+ # a spec named 'a', intended for regular installs
+ #
+ # @gem::
+ # the path to a built gem from @spec
+ #
+ # And returns a Gem::Installer for the @spec that installs into @gemhome
+
+ def setup_base_installer(force = true)
+ @gem = setup_base_gem
+ util_installer @spec, @gemhome, false, force
+ end
+
+ ##
+ # Creates the following instance variables:
+ #
+ # @spec::
+ # a spec named 'a', intended for regular installs
+ #
+ # And returns a gem built for the @spec
+
+ def setup_base_gem
+ @spec = setup_base_spec
+ util_build_gem @spec
+ @spec.cache_file
+ end
+
+ ##
+ # Sets up a generic specification for testing the rubygems installer
+ #
+ # And returns it
+
+ def setup_base_spec
+ quick_gem 'a' do |spec|
+ util_make_exec spec
+ end
+ end
+
+ ##
+ # Creates the following instance variables:
+ #
+ # @spec::
+ # a spec named 'a', intended for regular installs
+ # @user_spec::
+ # a spec named 'b', intended for user installs
+ #
+ # @gem::
+ # the path to a built gem from @spec
+ # @user_gem::
+ # the path to a built gem from @user_spec
+ #
+ # And returns a Gem::Installer for the @user_spec that installs into Gem.user_dir
+
+ def setup_base_user_installer
+ @user_spec = quick_gem 'b' do |spec|
+ util_make_exec spec
+ end
+
+ util_build_gem @user_spec
+
+ @user_gem = @user_spec.cache_file
+
+ util_installer @user_spec, Gem.user_dir, :user
+ end
+
+ ##
+ # Sets up the base @gem, builds it and returns an installer for it.
+ #
+ def util_setup_installer(&block)
+ @gem = setup_base_gem
+
+ util_setup_gem(&block)
+ end
+
+ ##
+ # Builds the @spec gem and returns an installer for it. The built gem
+ # includes:
+ #
+ # bin/executable
+ # lib/code.rb
+ # ext/a/mkrf_conf.rb
+
+ def util_setup_gem(ui = @ui, force = true)
+ @spec.files << File.join('lib', 'code.rb')
+ @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb')
+
+ Dir.chdir @tempdir do
+ FileUtils.mkdir_p 'bin'
+ FileUtils.mkdir_p 'lib'
+ FileUtils.mkdir_p File.join('ext', 'a')
+
+ File.open File.join('bin', 'executable'), 'w' do |f|
+ f.puts "raise 'ran executable'"
+ end
+
+ File.open File.join('lib', 'code.rb'), 'w' do |f|
+ f.puts '1'
+ end
+
+ File.open File.join('ext', 'a', 'mkrf_conf.rb'), 'w' do |f|
+ f << <<-EOF
+ File.open 'Rakefile', 'w' do |rf| rf.puts "task :default" end
+ EOF
+ end
+
+ yield @spec if block_given?
+
+ use_ui ui do
+ FileUtils.rm_f @gem
+
+ @gem = Gem::Package.build @spec
+ end
+ end
+
+ Gem::Installer.at @gem, :force => force
+ end
+
+ ##
+ # Creates an installer for +spec+ that will install into +gem_home+. If
+ # +user+ is true a user-install will be performed.
+
+ def util_installer(spec, gem_home, user=false, force=true)
+ Gem::Installer.at(spec.cache_file,
+ :install_dir => gem_home,
+ :user_install => user,
+ :force => force)
+ end
+
+ @@symlink_supported = nil
+
+ # This is needed for Windows environment without symlink support enabled (the default
+ # for non admin) to be able to skip test for features using symlinks.
+ def symlink_supported?
+ if @@symlink_supported.nil?
+ begin
+ File.symlink("", "")
+ rescue Errno::ENOENT, Errno::EEXIST
+ @@symlink_supported = true
+ rescue NotImplementedError, SystemCallError
+ @@symlink_supported = false
+ end
+ end
+ @@symlink_supported
+ end
+end
diff --git a/test/rubygems/package/tar_test_case.rb b/test/rubygems/package/tar_test_case.rb
new file mode 100644
index 0000000000..99f503a23f
--- /dev/null
+++ b/test/rubygems/package/tar_test_case.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+require_relative '../helper'
+require 'rubygems/package'
+
+##
+# A test case for Gem::Package::Tar* classes
+
+class Gem::Package::TarTestCase < Gem::TestCase
+ def ASCIIZ(str, length)
+ str + "\0" * (length - str.length)
+ end
+
+ def SP(s)
+ s + " "
+ end
+
+ def SP_Z(s)
+ s + " \0"
+ end
+
+ def Z(s)
+ s + "\0"
+ end
+
+ def assert_headers_equal(expected, actual)
+ expected = expected.to_s unless String === expected
+ actual = actual.to_s unless String === actual
+
+ fields = %w[
+ name 100
+ mode 8
+ uid 8
+ gid 8
+ size 12
+ mtime 12
+ checksum 8
+ typeflag 1
+ linkname 100
+ magic 6
+ version 2
+ uname 32
+ gname 32
+ devmajor 8
+ devminor 8
+ prefix 155
+ ]
+
+ offset = 0
+
+ until fields.empty? do
+ name = fields.shift
+ length = fields.shift.to_i
+
+ if name == "checksum"
+ chksum_off = offset
+ offset += length
+ next
+ end
+
+ assert_equal expected[offset, length], actual[offset, length],
+ "Field #{name} of the tar header differs."
+
+ offset += length
+ end
+
+ assert_equal expected[chksum_off, 8], actual[chksum_off, 8]
+ end
+
+ def calc_checksum(header)
+ sum = header.unpack("C*").inject{|s,a| s + a }
+ SP(Z(to_oct(sum, 6)))
+ end
+
+ def header(type, fname, dname, length, mode, mtime, checksum = nil, linkname = "")
+ checksum ||= " " * 8
+
+ arr = [ # struct tarfile_entry_posix
+ ASCIIZ(fname, 100), # char name[100]; ASCII + (Z unless filled)
+ Z(to_oct(mode, 7)), # char mode[8]; 0 padded, octal null
+ Z(to_oct(0, 7)), # char uid[8]; ditto
+ Z(to_oct(0, 7)), # char gid[8]; ditto
+ Z(to_oct(length, 11)), # char size[12]; 0 padded, octal, null
+ Z(to_oct(mtime, 11)), # char mtime[12]; 0 padded, octal, null
+ checksum, # char checksum[8]; 0 padded, octal, null, space
+ type, # char typeflag[1]; file: "0" dir: "5"
+ ASCIIZ(linkname, 100), # char linkname[100]; ASCII + (Z unless filled)
+ "ustar\0", # char magic[6]; "ustar\0"
+ "00", # char version[2]; "00"
+ ASCIIZ("wheel", 32), # char uname[32]; ASCIIZ
+ ASCIIZ("wheel", 32), # char gname[32]; ASCIIZ
+ Z(to_oct(0, 7)), # char devmajor[8]; 0 padded, octal, null
+ Z(to_oct(0, 7)), # char devminor[8]; 0 padded, octal, null
+ ASCIIZ(dname, 155), # char prefix[155]; ASCII + (Z unless filled)
+ ]
+
+ h = arr.join
+ ret = h + "\0" * (512 - h.size)
+ assert_equal(512, ret.size)
+ ret
+ end
+
+ def tar_dir_header(name, prefix, mode, mtime)
+ h = header("5", name, prefix, 0, mode, mtime)
+ checksum = calc_checksum(h)
+ header("5", name, prefix, 0, mode, mtime, checksum)
+ end
+
+ def tar_file_header(fname, dname, mode, length, mtime)
+ h = header("0", fname, dname, length, mode, mtime)
+ checksum = calc_checksum(h)
+ header("0", fname, dname, length, mode, mtime, checksum)
+ end
+
+ def tar_symlink_header(fname, prefix, mode, mtime, linkname)
+ h = header("2", fname, prefix, 0, mode, mtime, nil, linkname)
+ checksum = calc_checksum(h)
+ header("2", fname, prefix, 0, mode, mtime, checksum, linkname)
+ end
+
+ def to_oct(n, pad_size)
+ "%0#{pad_size}o" % n
+ end
+
+ def util_entry(tar)
+ io = TempIO.new tar
+
+ header = Gem::Package::TarHeader.from io
+
+ Gem::Package::TarReader::Entry.new header, io
+ end
+
+ def util_dir_entry
+ util_entry tar_dir_header("foo", "bar", 0, Time.now)
+ end
+
+ def util_symlink_entry
+ util_entry tar_symlink_header("foo", "bar", 0, Time.now, "link")
+ end
+end
diff --git a/test/rubygems/packages/ascii_binder-0.1.10.1.gem b/test/rubygems/packages/ascii_binder-0.1.10.1.gem
new file mode 100644
index 0000000000..19c505395e
--- /dev/null
+++ b/test/rubygems/packages/ascii_binder-0.1.10.1.gem
Binary files differ
diff --git a/test/rubygems/packages/ill-formatted-platform-1.0.0.10.gem b/test/rubygems/packages/ill-formatted-platform-1.0.0.10.gem
new file mode 100644
index 0000000000..58a13535c2
--- /dev/null
+++ b/test/rubygems/packages/ill-formatted-platform-1.0.0.10.gem
Binary files differ
diff --git a/test/rubygems/plugin/load/rubygems_plugin.rb b/test/rubygems/plugin/load/rubygems_plugin.rb
index 85a6851ace..7cc6bef90b 100644
--- a/test/rubygems/plugin/load/rubygems_plugin.rb
+++ b/test/rubygems/plugin/load/rubygems_plugin.rb
@@ -1,6 +1,4 @@
# frozen_string_literal: true
class TestGem
-
TEST_PLUGIN_LOAD = :loaded
-
end
diff --git a/test/rubygems/private_ec_key.pem b/test/rubygems/private_ec_key.pem
new file mode 100644
index 0000000000..5d855d0dfc
--- /dev/null
+++ b/test/rubygems/private_ec_key.pem
@@ -0,0 +1,9 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,4107F98A374CB8EC18F1AA4EA4B6A0DB
+
+BRklFxJGcz7gqQYxek8TZkt8qbPhB0FSR6nyw3SYuio/2tlT9ohs74mlK3EbG9Lt
+Y4OquJbksBFmoB7fIoM4vnuIZ0Eoz2ooxn9tjhBtqJ3mVscYXwZmA3UDUWDMlviQ
+Fu37OpikQv4TFA1jlmUK0LM8xmUCfUeLl0kHD17lFsz2gkO2kwg8mn/YUMOIaDOu
+EnnmxbAwnZBpemQkQfpTt2mYL9gu3CcMt5gokBuGDxY=
+-----END EC PRIVATE KEY-----
diff --git a/test/rubygems/rubygems/commands/crash_command.rb b/test/rubygems/rubygems/commands/crash_command.rb
index a27a79f8dc..9155360e76 100644
--- a/test/rubygems/rubygems/commands/crash_command.rb
+++ b/test/rubygems/rubygems/commands/crash_command.rb
@@ -1,6 +1,4 @@
# frozen_string_literal: true
class Gem::Commands::CrashCommand < Gem::Command
-
raise "crash"
-
end
diff --git a/test/rubygems/rubygems_plugin.rb b/test/rubygems/rubygems_plugin.rb
index 7fac2ebec6..2dc7836904 100644
--- a/test/rubygems/rubygems_plugin.rb
+++ b/test/rubygems/rubygems_plugin.rb
@@ -11,7 +11,6 @@ module Gem::Commands
end
class Gem::Commands::InterruptCommand < Gem::Command
-
def initialize
super('interrupt', 'Raises an Interrupt Exception', {})
end
@@ -19,7 +18,6 @@ class Gem::Commands::InterruptCommand < Gem::Command
def execute
raise Interrupt, "Interrupt exception"
end
-
end
Gem::CommandManager.instance.register_command :interrupt
diff --git a/test/rubygems/specifications/bar-0.0.2.gemspec b/test/rubygems/specifications/bar-0.0.2.gemspec
index ceefa4ed16..37b6ea45da 100644
--- a/test/rubygems/specifications/bar-0.0.2.gemspec
+++ b/test/rubygems/specifications/bar-0.0.2.gemspec
@@ -1,5 +1,3 @@
-# -*- encoding: utf-8 -*-
-
Gem::Specification.new do |s|
s.name = "bar"
s.version = "0.0.2"
diff --git a/test/rubygems/specifications/rubyforge-0.0.1.gemspec b/test/rubygems/specifications/rubyforge-0.0.1.gemspec
index 0df2c4c379..c760a42073 100644
--- a/test/rubygems/specifications/rubyforge-0.0.1.gemspec
+++ b/test/rubygems/specifications/rubyforge-0.0.1.gemspec
@@ -1,5 +1,3 @@
-# -*- encoding: utf-8 -*-
-
Gem::Specification.new do |s|
s.name = "rubyforge"
s.version = "0.0.1"
diff --git a/test/rubygems/test_bundled_ca.rb b/test/rubygems/test_bundled_ca.rb
index 4224755562..fff5904aba 100644
--- a/test/rubygems/test_bundled_ca.rb
+++ b/test/rubygems/test_bundled_ca.rb
@@ -1,6 +1,12 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
-require 'net/https'
+require_relative 'helper'
+require 'net/http'
+require 'rubygems/openssl'
+
+unless Gem::HAVE_OPENSSL
+ warn 'Skipping bundled certificates tests. openssl not found.'
+end
+
require 'rubygems/request'
# = Testing Bundled CA
@@ -8,60 +14,47 @@ require 'rubygems/request'
# The tested hosts are explained in detail here: https://github.com/rubygems/rubygems/commit/5e16a5428f973667cabfa07e94ff939e7a83ebd9
#
-if ENV["CI"] || ENV["TEST_SSL"]
- class TestBundledCA < Gem::TestCase
-
- THIS_FILE = File.expand_path __FILE__
-
- def bundled_certificate_store
- store = OpenSSL::X509::Store.new
+class TestBundledCA < Gem::TestCase
+ def bundled_certificate_store
+ store = OpenSSL::X509::Store.new
- ssl_cert_glob =
- File.expand_path '../../../lib/rubygems/ssl_certs/*/*.pem', THIS_FILE
-
- Dir[ssl_cert_glob].each do |ssl_cert|
- store.add_file ssl_cert
- end
-
- store
+ Gem::Request.get_cert_files.each do |ssl_cert|
+ store.add_file ssl_cert
end
- def assert_https(host)
- if self.respond_to? :_assertions # minitest <= 4
- self._assertions += 1
- else # minitest >= 5
- self.assertions += 1
- end
- http = Net::HTTP.new(host, 443)
- http.use_ssl = true
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
- http.cert_store = bundled_certificate_store
- http.get('/')
- rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError
- skip "#{host} seems offline, I can't tell whether ssl would work."
- rescue OpenSSL::SSL::SSLError => e
- # Only fail for certificate verification errors
- if e.message =~ /certificate verify failed/
- flunk "#{host} is not verifiable using the included certificates. Error was: #{e.message}"
- end
- raise
- end
+ store
+ end
- def test_accessing_rubygems
- assert_https('rubygems.org')
+ def assert_https(host)
+ assert true
+ http = Net::HTTP.new(host, 443)
+ http.use_ssl = true
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
+ http.cert_store = bundled_certificate_store
+ http.get('/')
+ rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError
+ pend "#{host} seems offline, I can't tell whether ssl would work."
+ rescue OpenSSL::SSL::SSLError => e
+ # Only fail for certificate verification errors
+ if e.message =~ /certificate verify failed/
+ flunk "#{host} is not verifiable using the included certificates. Error was: #{e.message}"
end
+ raise
+ end
- def test_accessing_www_rubygems
- assert_https('www.rubygems.org')
- end
+ def test_accessing_rubygems
+ assert_https('rubygems.org')
+ end
- def test_accessing_staging
- assert_https('staging.rubygems.org')
- end
+ def test_accessing_www_rubygems
+ assert_https('www.rubygems.org')
+ end
- def test_accessing_new_index
- assert_https('index.rubygems.org')
- end
+ def test_accessing_staging
+ assert_https('staging.rubygems.org')
+ end
+ def test_accessing_new_index
+ assert_https('index.rubygems.org')
end
-end
+end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_config.rb b/test/rubygems/test_config.rb
index 70fc4e23f0..4d64f16fca 100644
--- a/test/rubygems/test_config.rb
+++ b/test/rubygems/test_config.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems'
require 'shellwords'
class TestConfig < Gem::TestCase
-
def test_datadir
util_make_gems
spec = Gem::Specification.find_by_name("a")
@@ -25,5 +24,4 @@ class TestConfig < Gem::TestCase
assert_equal(Gem.ruby, ruby)
assert_match(/\/bad_rake.rb\z/, rake)
end
-
end
diff --git a/test/rubygems/test_deprecate.rb b/test/rubygems/test_deprecate.rb
index b92bd1c3da..a619eccb37 100644
--- a/test/rubygems/test_deprecate.rb
+++ b/test/rubygems/test_deprecate.rb
@@ -1,15 +1,11 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
-# require 'rubygems/builder'
-# require 'rubygems/package'
+require_relative 'helper'
require 'rubygems/deprecate'
class TestDeprecate < Gem::TestCase
-
def setup
super
- # Gem::Deprecate.saved_warnings.clear
@original_skip = Gem::Deprecate.skip
Gem::Deprecate.skip = false
end
@@ -17,7 +13,6 @@ class TestDeprecate < Gem::TestCase
def teardown
super
- # Gem::Deprecate.saved_warnings.clear
Gem::Deprecate.skip = @original_skip
end
@@ -45,7 +40,34 @@ class TestDeprecate < Gem::TestCase
end
class Thing
+ extend Gem::Deprecate
+ attr_accessor :message
+ def foo
+ @message = "foo"
+ end
+ def bar
+ @message = "bar"
+ end
+ rubygems_deprecate :foo, :bar
+
+ def foo_arg(msg)
+ @message = "foo" + msg
+ end
+ def bar_arg(msg)
+ @message = "bar" + msg
+ end
+ rubygems_deprecate :foo_arg, :bar_arg
+
+ def foo_kwarg(message:)
+ @message = "foo" + message
+ end
+ def bar_kwarg(message:)
+ @message = "bar" + message
+ end
+ rubygems_deprecate :foo_kwarg, :bar_kwarg
+ end
+ class OtherThing
extend Gem::Deprecate
attr_accessor :message
def foo
@@ -56,25 +78,80 @@ class TestDeprecate < Gem::TestCase
end
deprecate :foo, :bar, 2099, 3
+ def foo_arg(msg)
+ @message = "foo" + msg
+ end
+ def bar_arg(msg)
+ @message = "bar" + msg
+ end
+ deprecate :foo_arg, :bar_arg, 2099, 3
+
+ def foo_kwarg(message:)
+ @message = "foo" + message
+ end
+ def bar_kwarg(message:)
+ @message = "bar" + message
+ end
+ deprecate :foo_kwarg, :bar_kwarg, 2099, 3
end
def test_deprecated_method_calls_the_old_method
- capture_io do
+ capture_output do
thing = Thing.new
thing.foo
assert_equal "foo", thing.message
+ thing.foo_arg("msg")
+ assert_equal "foomsg", thing.message
+ thing.foo_kwarg(message: "msg")
+ assert_equal "foomsg", thing.message
end
end
def test_deprecated_method_outputs_a_warning
- out, err = capture_io do
+ out, err = capture_output do
thing = Thing.new
thing.foo
+ thing.foo_arg("msg")
+ thing.foo_kwarg(message: "msg")
end
assert_equal "", out
assert_match(/Thing#foo is deprecated; use bar instead\./, err)
- assert_match(/on or after 2099-03-01/, err)
+ assert_match(/Thing#foo_arg is deprecated; use bar_arg instead\./, err)
+ assert_match(/Thing#foo_kwarg is deprecated; use bar_kwarg instead\./, err)
+ assert_match(/in Rubygems [0-9]+/, err)
+ end
+
+ def test_rubygems_deprecate_command
+ require 'rubygems/command'
+ foo_command = Class.new(Gem::Command) do
+ extend Gem::Deprecate
+
+ rubygems_deprecate_command
+
+ def execute
+ puts "pew pew!"
+ end
+ end
+
+ Gem::Commands.send(:const_set, :FooCommand, foo_command)
+ assert Gem::Commands::FooCommand.new("foo").deprecated?
+ ensure
+ Gem::Commands.send(:remove_const, :FooCommand)
end
+ def test_deprecated_method_outputs_a_warning_old_way
+ out, err = capture_output do
+ thing = OtherThing.new
+ thing.foo
+ thing.foo_arg("msg")
+ thing.foo_kwarg(message: "msg")
+ end
+
+ assert_equal "", out
+ assert_match(/OtherThing#foo is deprecated; use bar instead\./, err)
+ assert_match(/OtherThing#foo_arg is deprecated; use bar_arg instead\./, err)
+ assert_match(/OtherThing#foo_kwarg is deprecated; use bar_kwarg instead\./, err)
+ assert_match(/on or after 2099-03/, err)
+ end
end
diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb
index b5d399f972..832701a173 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -1,5 +1,5 @@
# coding: US-ASCII
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems'
require 'rubygems/command'
require 'rubygems/installer'
@@ -7,18 +7,7 @@ require 'pathname'
require 'tmpdir'
require 'rbconfig'
-if File.exist?(File.join(Dir.tmpdir, "Gemfile"))
- raise "rubygems/bundler tests do not work correctly if there is #{ File.join(Dir.tmpdir, "Gemfile") }"
-end
-
-# TODO: push this up to test_case.rb once battle tested
-
-$LOAD_PATH.map! do |path|
- path.dup.tap(&Gem::UNTAINT)
-end
-
class TestGem < Gem::TestCase
-
PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant
PROJECT_DIR = File.expand_path('../../..', __FILE__).tap(&Gem::UNTAINT)
@@ -30,79 +19,72 @@ class TestGem < Gem::TestCase
common_installer_setup
- ENV.delete 'RUBYGEMS_GEMDEPS'
- @additional = %w[a b].map { |d| File.join @tempdir, d }
+ @additional = %w[a b].map {|d| File.join @tempdir, d }
util_remove_interrupt_command
end
def test_self_finish_resolve
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2"
- install_specs c1, c2, b1, b2, a1
+ install_specs c1, c2, b1, b2, a1
- a1.activate
+ a1.activate
- assert_equal %w(a-1), loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- Gem.finish_resolve
+ Gem.finish_resolve
- assert_equal %w(a-1 b-2 c-2), loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_finish_resolve_wtf
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this
- b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this
- b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb"
- c1 = util_spec "c", "1" # this
- c2 = util_spec "c", "2"
- d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb"
- d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this
+ a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this
+ b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this
+ b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb"
+ c1 = util_spec "c", "1" # this
+ c2 = util_spec "c", "2"
+ d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb"
+ d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this
- install_specs c1, c2, b1, b2, d1, d2, a1
+ install_specs c1, c2, b1, b2, d1, d2, a1
- a1.activate
+ a1.activate
- assert_equal %w(a-1), loaded_spec_names
- assert_equal ["b (> 0)", "d (> 0)"], unresolved_names
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)", "d (> 0)"], unresolved_names
- Gem.finish_resolve
+ Gem.finish_resolve
- assert_equal %w(a-1 b-1 c-1 d-2), loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-1 c-1 d-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_finish_resolve_respects_loaded_specs
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2"
- install_specs c1, c2, b1, b2, a1
+ install_specs c1, c2, b1, b2, a1
- a1.activate
- c1.activate
+ a1.activate
+ c1.activate
- assert_equal %w(a-1 c-1), loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ assert_equal %w[a-1 c-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- Gem.finish_resolve
+ Gem.finish_resolve
- assert_equal %w(a-1 b-1 c-1), loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-1 c-1], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_install
@@ -115,9 +97,9 @@ class TestGem < Gem::TestCase
installed = Gem.install 'a', '= 1', :install_dir => gemhome2
- assert_equal %w[a-1], installed.map { |spec| spec.full_name }
+ assert_equal %w[a-1], installed.map {|spec| spec.full_name }
- assert_path_exists File.join(gemhome2, 'gems', 'a-1')
+ assert_path_exist File.join(gemhome2, 'gems', 'a-1')
end
def test_self_install_in_rescue
@@ -134,7 +116,7 @@ class TestGem < Gem::TestCase
rescue StandardError
Gem.install 'a', '= 1', :install_dir => gemhome2
end
- assert_equal %w[a-1], installed.map { |spec| spec.full_name }
+ assert_equal %w[a-1], installed.map {|spec| spec.full_name }
end
def test_self_install_permissions
@@ -175,7 +157,7 @@ class TestGem < Gem::TestCase
:prog_mode => win_platform? ? 0410 : 0510,
:data_mode => 0640,
:wrappers => true,
- :format_executable => format_executable
+ :format_executable => format_executable,
}
Dir.chdir @tempdir do
Dir.mkdir 'bin'
@@ -218,29 +200,25 @@ class TestGem < Gem::TestCase
end
assert_equal(expected, result)
ensure
- File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.tap(&Gem::UNTAINT)})
+ File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.tap(&Gem::UNTAINT) })
end
def test_require_missing
- save_loaded_features do
- assert_raises ::LoadError do
- require "test_require_missing"
- end
+ assert_raise ::LoadError do
+ require "test_require_missing"
end
end
def test_require_does_not_glob
- save_loaded_features do
- a1 = util_spec "a", "1", nil, "lib/a1.rb"
+ a1 = util_spec "a", "1", nil, "lib/a1.rb"
- install_specs a1
-
- assert_raises ::LoadError do
- require "a*"
- end
+ install_specs a1
- assert_equal [], loaded_spec_names
+ assert_raise ::LoadError do
+ require "a*"
end
+
+ assert_equal [], loaded_spec_names
end
def test_self_bin_path_active
@@ -272,7 +250,7 @@ class TestGem < Gem::TestCase
end
def test_self_activate_bin_path_no_exec_name
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
Gem.activate_bin_path 'a'
end
@@ -305,7 +283,59 @@ class TestGem < Gem::TestCase
gem 'c'
Gem.finish_resolve
- assert_equal %w(a-1 b-2 c-1), loaded_spec_names
+ assert_equal %w[a-1 b-2 c-1], loaded_spec_names
+ end
+
+ def test_activate_bin_path_does_not_error_if_a_gem_thats_not_finally_activated_has_orphaned_dependencies
+ a1 = util_spec 'a', '1' do |s|
+ s.executables = ['exec']
+ s.add_dependency 'b'
+ end
+
+ b1 = util_spec 'b', '1' do |s|
+ s.add_dependency 'c', '1'
+ end
+
+ b2 = util_spec 'b', '2' do |s|
+ s.add_dependency 'c', '2'
+ end
+
+ c2 = util_spec 'c', '2'
+
+ install_specs c2, b1, b2, a1
+
+ # c1 is missing, but not needed for activation, so we should not get any errors here
+
+ Gem.activate_bin_path("a", "exec", ">= 0")
+
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ end
+
+ def test_activate_bin_path_raises_a_meaningful_error_if_a_gem_thats_finally_activated_has_orphaned_dependencies
+ a1 = util_spec 'a', '1' do |s|
+ s.executables = ['exec']
+ s.add_dependency 'b'
+ end
+
+ b1 = util_spec 'b', '1' do |s|
+ s.add_dependency 'c', '1'
+ end
+
+ b2 = util_spec 'b', '2' do |s|
+ s.add_dependency 'c', '2'
+ end
+
+ c1 = util_spec 'c', '1'
+
+ install_specs c1, b1, b2, a1
+
+ # c2 is missing, and b2 which has it as a dependency will be activated, so we should get an error about the orphaned dependency
+
+ e = assert_raise Gem::UnsatisfiableDependencyError do
+ load Gem.activate_bin_path("a", "exec", ">= 0")
+ end
+
+ assert_equal "Unable to resolve dependency: 'b (>= 0)' requires 'c (= 2)'", e.message
end
def test_activate_bin_path_in_debug_mode
@@ -315,9 +345,10 @@ class TestGem < Gem::TestCase
install_specs a1
+ require "open3"
output, status = Open3.capture2e(
{ "GEM_HOME" => Gem.paths.home, "DEBUG_RESOLVER" => "1" },
- Gem.ruby, "-I", File.expand_path("../../lib", __dir__), "-e", "\"Gem.activate_bin_path('a', 'exec', '>= 0')\""
+ *ruby_with_rubygems_in_load_path, "-e", "\"Gem.activate_bin_path('a', 'exec', '>= 0')\""
)
assert status.success?, output
@@ -346,9 +377,9 @@ class TestGem < Gem::TestCase
L
end
- File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') }
+ File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') }
- e = assert_raises Gem::GemNotFoundException do
+ e = assert_raise Gem::GemNotFoundException do
load Gem.activate_bin_path("bundler", "bundle", ">= 0.a")
end
@@ -385,11 +416,11 @@ class TestGem < Gem::TestCase
L
end
- File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') }
+ File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') }
load Gem.activate_bin_path("bundler", "bundle", ">= 0.a")
- assert_equal %w(bundler-2.0.0), loaded_spec_names
+ assert_equal %w[bundler-2.0.0], loaded_spec_names
end
def test_activate_bin_path_respects_underscore_selection_if_given
@@ -419,15 +450,41 @@ class TestGem < Gem::TestCase
L
end
- File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') }
+ File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') }
load Gem.activate_bin_path("bundler", "bundle", "= 1.17.3")
- assert_equal %w(bundler-1.17.3), loaded_spec_names
+ assert_equal %w[bundler-1.17.3], loaded_spec_names
+ end
+
+ def test_activate_bin_path_gives_proper_error_for_bundler_when_underscore_selection_given
+ File.open("Gemfile.lock", "w") do |f|
+ f.write <<-L.gsub(/ {8}/, "")
+ GEM
+ remote: https://rubygems.org/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ 2.1.4
+ L
+ end
+
+ File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') }
+
+ e = assert_raise Gem::GemNotFoundException do
+ load Gem.activate_bin_path("bundler", "bundle", "= 2.2.8")
+ end
+
+ assert_equal "can't find gem bundler (= 2.2.8) with executable bundle", e.message
end
def test_self_bin_path_no_exec_name
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
Gem.bin_path 'a'
end
@@ -448,20 +505,20 @@ class TestGem < Gem::TestCase
util_spec 'a', '2' do |s|
s.executables = ['exec']
end
- assert_raises(Gem::GemNotFoundException) do
+ assert_raise(Gem::GemNotFoundException) do
Gem.bin_path('a', 'other', '2')
end
end
def test_self_bin_path_no_bin_file
util_spec 'a', '1'
- assert_raises(ArgumentError) do
+ assert_raise(ArgumentError) do
Gem.bin_path('a', nil, '1')
end
end
def test_self_bin_path_not_found
- assert_raises(Gem::GemNotFoundException) do
+ assert_raise(Gem::GemNotFoundException) do
Gem.bin_path('non-existent', 'blah')
end
end
@@ -472,7 +529,6 @@ class TestGem < Gem::TestCase
s.executables = []
end
install_specs spec
- # Should not find a-10's non-abin (bug)
assert_equal @abin_path, Gem.bin_path('a', 'abin')
end
@@ -528,7 +584,7 @@ class TestGem < Gem::TestCase
end
def test_self_datadir_nonexistent_package
- assert_raises(Gem::MissingSpecError) do
+ assert_raise(Gem::MissingSpecError) do
Gem::Specification.find_by_name("xyzzy").datadir
end
end
@@ -596,22 +652,22 @@ class TestGem < Gem::TestCase
end
def test_self_use_gemdeps
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
+ with_rubygems_gemdeps('-') do
+ FileUtils.mkdir_p 'detect/a/b'
+ FileUtils.mkdir_p 'detect/a/Isolate'
- FileUtils.mkdir_p 'detect/a/b'
- FileUtils.mkdir_p 'detect/a/Isolate'
+ FileUtils.touch 'detect/Isolate'
- FileUtils.touch 'detect/Isolate'
+ begin
+ Dir.chdir 'detect/a/b'
- begin
- Dir.chdir 'detect/a/b'
+ Gem.use_gemdeps
- assert_equal add_bundler_full_name([]), Gem.use_gemdeps.map(&:full_name)
- ensure
- Dir.chdir @tempdir
+ assert_equal add_bundler_full_name([]), loaded_spec_names
+ ensure
+ Dir.chdir @tempdir
+ end
end
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
end
def test_self_dir
@@ -624,12 +680,12 @@ class TestGem < Gem::TestCase
Gem.ensure_gem_subdirectories @gemhome
- assert_path_exists File.join @gemhome, 'build_info'
- assert_path_exists File.join @gemhome, 'cache'
- assert_path_exists File.join @gemhome, 'doc'
- assert_path_exists File.join @gemhome, 'extensions'
- assert_path_exists File.join @gemhome, 'gems'
- assert_path_exists File.join @gemhome, 'specifications'
+ assert_path_exist File.join @gemhome, 'build_info'
+ assert_path_exist File.join @gemhome, 'cache'
+ assert_path_exist File.join @gemhome, 'doc'
+ assert_path_exist File.join @gemhome, 'extensions'
+ assert_path_exist File.join @gemhome, 'gems'
+ assert_path_exist File.join @gemhome, 'specifications'
end
def test_self_ensure_gem_directories_permissions
@@ -670,7 +726,7 @@ class TestGem < Gem::TestCase
assert_directory_exists util_cache_dir
end
- unless win_platform? || Process.uid.zero? # only for FS that support write protection
+ unless win_platform? || Process.uid.zero? # only for FS that support write protection
def test_self_ensure_gem_directories_write_protected
gemdir = File.join @tempdir, "egd"
FileUtils.rm_r gemdir rescue nil
@@ -702,6 +758,11 @@ class TestGem < Gem::TestCase
ensure
FileUtils.chmod 0600, parent
end
+
+ def test_self_ensure_gem_directories_non_existent_paths
+ Gem.ensure_gem_subdirectories '/proc/0123456789/bogus' # should not raise
+ Gem.ensure_gem_subdirectories 'classpath:/bogus/x' # JRuby embed scenario
+ end
end
def test_self_extension_dir_shared
@@ -722,7 +783,7 @@ class TestGem < Gem::TestCase
discover_path = File.join 'lib', 'sff', 'discover.rb'
- foo1, foo2 = %w(1 2).map do |version|
+ foo1, foo2 = %w[1 2].map do |version|
spec = quick_gem 'sff', version do |s|
s.files << discover_path
end
@@ -754,7 +815,7 @@ class TestGem < Gem::TestCase
discover_path = File.join 'lib', 'sff', 'discover.rb'
- foo1, _ = %w(1 2).map do |version|
+ foo1, _ = %w[1 2].map do |version|
spec = quick_gem 'sff', version do |s|
s.files << discover_path
end
@@ -775,7 +836,7 @@ class TestGem < Gem::TestCase
expected = [
File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR),
- File.join(foo1.full_gem_path, discover_path)
+ File.join(foo1.full_gem_path, discover_path),
].sort
assert_equal expected, Gem.find_files('sff/discover').sort
@@ -790,7 +851,7 @@ class TestGem < Gem::TestCase
discover_path = File.join 'lib', 'sff', 'discover.rb'
- _, foo2 = %w(1 2).map do |version|
+ _, foo2 = %w[1 2].map do |version|
spec = quick_gem 'sff', version do |s|
s.files << discover_path
end
@@ -985,7 +1046,7 @@ class TestGem < Gem::TestCase
assert_equal ["\xCF", "\x80"], Gem.read_binary('test').chars.to_a
- skip 'chmod not supported' if Gem.win_platform?
+ pend 'chmod not supported' if Gem.win_platform?
begin
File.chmod 0444, 'test'
@@ -1030,23 +1091,23 @@ class TestGem < Gem::TestCase
Gem.refresh
- Gem::Specification.each{|spec| assert spec.activated? if spec == s}
+ Gem::Specification.each{|spec| assert spec.activated? if spec == s }
Gem.loaded_specs.delete(s)
Gem.refresh
end
def test_self_ruby_escaping_spaces_in_path
- with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do
- ruby_install_name "ruby" do
+ with_clean_path_to_ruby do
+ with_rb_config_ruby("C:/Ruby 1.8/bin/ruby.exe") do
assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby
end
end
end
def test_self_ruby_path_without_spaces
- with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do
- ruby_install_name "ruby" do
+ with_clean_path_to_ruby do
+ with_rb_config_ruby("C:/Ruby18/bin/ruby.exe") do
assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby
end
end
@@ -1071,7 +1132,7 @@ class TestGem < Gem::TestCase
assert_equal Gem::Requirement.create('>= 1.2.3'), Gem.env_requirement('foo')
assert_equal Gem::Requirement.create('1.2.3'), Gem.env_requirement('bAr')
- assert_raises(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') }
+ assert_raise(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') }
assert_equal Gem::Requirement.default, Gem.env_requirement('qux')
end
@@ -1172,7 +1233,7 @@ class TestGem < Gem::TestCase
def test_self_post_build
assert_equal 1, Gem.post_build_hooks.length
- Gem.post_build { |installer| }
+ Gem.post_build {|installer| }
assert_equal 2, Gem.post_build_hooks.length
end
@@ -1180,7 +1241,7 @@ class TestGem < Gem::TestCase
def test_self_post_install
assert_equal 1, Gem.post_install_hooks.length
- Gem.post_install { |installer| }
+ Gem.post_install {|installer| }
assert_equal 2, Gem.post_install_hooks.length
end
@@ -1188,7 +1249,7 @@ class TestGem < Gem::TestCase
def test_self_done_installing
assert_empty Gem.done_installing_hooks
- Gem.done_installing { |gems| }
+ Gem.done_installing {|gems| }
assert_equal 1, Gem.done_installing_hooks.length
end
@@ -1196,7 +1257,7 @@ class TestGem < Gem::TestCase
def test_self_post_reset
assert_empty Gem.post_reset_hooks
- Gem.post_reset { }
+ Gem.post_reset {}
assert_equal 1, Gem.post_reset_hooks.length
end
@@ -1204,7 +1265,7 @@ class TestGem < Gem::TestCase
def test_self_post_uninstall
assert_equal 1, Gem.post_uninstall_hooks.length
- Gem.post_uninstall { |installer| }
+ Gem.post_uninstall {|installer| }
assert_equal 2, Gem.post_uninstall_hooks.length
end
@@ -1212,7 +1273,7 @@ class TestGem < Gem::TestCase
def test_self_pre_install
assert_equal 1, Gem.pre_install_hooks.length
- Gem.pre_install { |installer| }
+ Gem.pre_install {|installer| }
assert_equal 2, Gem.pre_install_hooks.length
end
@@ -1220,7 +1281,7 @@ class TestGem < Gem::TestCase
def test_self_pre_reset
assert_empty Gem.pre_reset_hooks
- Gem.pre_reset { }
+ Gem.pre_reset {}
assert_equal 1, Gem.pre_reset_hooks.length
end
@@ -1228,7 +1289,7 @@ class TestGem < Gem::TestCase
def test_self_pre_uninstall
assert_equal 1, Gem.pre_uninstall_hooks.length
- Gem.pre_uninstall { |installer| }
+ Gem.pre_uninstall {|installer| }
assert_equal 2, Gem.pre_uninstall_hooks.length
end
@@ -1257,7 +1318,7 @@ class TestGem < Gem::TestCase
install_specs b1, b2, b3
- specs1 = Gem::Specification.stubs.find_all { |s| s.name == 'b' }
+ specs1 = Gem::Specification.stubs.find_all {|s| s.name == 'b' }
Gem::Specification.reset
specs2 = Gem::Specification.stubs_for('b')
assert_equal specs1.map(&:version), specs2.map(&:version)
@@ -1276,11 +1337,12 @@ class TestGem < Gem::TestCase
io.puts '# a_file.rb'
end
- e = assert_raises Gem::MissingSpecError do
+ e = assert_raise Gem::MissingSpecError do
Gem.try_activate 'a_file'
end
- assert_match %r%Could not find 'b' %, e.message
+ assert_match %r{Could not find 'b' }, e.message
+ assert_match %r{at: #{a.spec_file}}, e.message
end
def test_self_try_activate_missing_prerelease
@@ -1296,11 +1358,11 @@ class TestGem < Gem::TestCase
io.puts '# a_file.rb'
end
- e = assert_raises Gem::MissingSpecError do
+ e = assert_raise Gem::MissingSpecError do
Gem.try_activate 'a_file'
end
- assert_match %r%Could not find 'b' \(= 1.0rc1\)%, e.message
+ assert_match %r{Could not find 'b' \(= 1.0rc1\)}, e.message
end
def test_self_try_activate_missing_extensions
@@ -1315,7 +1377,7 @@ class TestGem < Gem::TestCase
io.write spec.to_ruby_for_cache
end
- _, err = capture_io do
+ _, err = capture_output do
refute Gem.try_activate 'nonexistent'
end
@@ -1340,7 +1402,7 @@ class TestGem < Gem::TestCase
end
def test_setting_paths_does_not_warn_about_unknown_keys
- stdout, stderr = capture_io do
+ stdout, stderr = capture_output do
Gem.paths = { 'foo' => [],
'bar' => Object.new,
'GEM_HOME' => Gem.paths.home,
@@ -1358,7 +1420,7 @@ class TestGem < Gem::TestCase
end
def test_deprecated_paths=
- stdout, stderr = capture_io do
+ stdout, stderr = capture_output do
Gem.paths = { 'GEM_HOME' => Gem.paths.home,
'GEM_PATH' => [Gem.paths.home, 'foo'] }
end
@@ -1380,6 +1442,8 @@ class TestGem < Gem::TestCase
parts = [@userhome, '.gem', Gem.ruby_engine]
parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty?
+ FileUtils.mkdir_p File.join(parts)
+
assert_equal File.join(parts), Gem.user_dir
end
@@ -1403,30 +1467,28 @@ class TestGem < Gem::TestCase
r.gem "b", "= 1"
end
- activated = Gem::Specification.map { |x| x.full_name }
+ activated = Gem::Specification.map {|x| x.full_name }
- assert_equal %w!a-1 b-1 c-2!, activated.sort
+ assert_equal %w[a-1 b-1 c-2], activated.sort
end
def test_self_needs_picks_up_unresolved_deps
- save_loaded_features do
- a = util_spec "a", "1"
- b = util_spec "b", "1", "c" => nil
- c = util_spec "c", "2"
- d = util_spec "d", "1", {'e' => '= 1'}, "lib/d#{$$}.rb"
- e = util_spec "e", "1"
-
- install_specs a, c, b, e, d
+ a = util_spec "a", "1"
+ b = util_spec "b", "1", "c" => nil
+ c = util_spec "c", "2"
+ d = util_spec "d", "1", {'e' => '= 1'}, "lib/d#{$$}.rb"
+ e = util_spec "e", "1"
- Gem.needs do |r|
- r.gem "a"
- r.gem "b", "= 1"
+ install_specs a, c, b, e, d
- require "d#{$$}"
- end
+ Gem.needs do |r|
+ r.gem "a"
+ r.gem "b", "= 1"
- assert_equal %w!a-1 b-1 c-2 d-1 e-1!, loaded_spec_names
+ require "d#{$$}"
end
+
+ assert_equal %w[a-1 b-1 c-2 d-1 e-1], loaded_spec_names
end
def test_self_gunzip
@@ -1495,7 +1557,6 @@ class TestGem < Gem::TestCase
install_gem foo2
end
- Gem.searcher = nil
Gem::Specification.reset
gem 'foo'
@@ -1505,6 +1566,31 @@ class TestGem < Gem::TestCase
assert_equal %w[plugin], PLUGINS_LOADED
end
+ def test_load_user_installed_plugins
+ plugin_path = File.join "lib", "rubygems_plugin.rb"
+
+ Dir.chdir @tempdir do
+ FileUtils.mkdir_p 'lib'
+ File.open plugin_path, "w" do |fp|
+ fp.puts "class TestGem; PLUGINS_LOADED << 'plugin'; end"
+ end
+
+ foo = util_spec 'foo', '1' do |s|
+ s.files << plugin_path
+ end
+
+ install_gem_user foo
+ end
+
+ Gem.paths = { "GEM_PATH" => [Gem.dir, Gem.user_dir].join(File::PATH_SEPARATOR) }
+
+ gem 'foo'
+
+ Gem.load_plugins
+
+ assert_equal %w[plugin], PLUGINS_LOADED
+ end
+
def test_load_env_plugins
with_plugin('load') { Gem.load_env_plugins }
assert_equal :loaded, TEST_PLUGIN_LOAD rescue nil
@@ -1525,8 +1611,8 @@ class TestGem < Gem::TestCase
def test_gem_path_ordering
refute_equal Gem.dir, Gem.user_dir
- write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" }
- write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" }
+ write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" }
+ write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" }
g = util_spec 'g', '1', nil, "lib/g.rb"
m = util_spec 'm', '1', nil, "lib/m.rb"
@@ -1540,7 +1626,7 @@ class TestGem < Gem::TestCase
tests = [
[:dir0, [ Gem.dir, Gem.user_dir], m0],
- [:dir1, [ Gem.user_dir, Gem.dir], m1]
+ [:dir1, [ Gem.user_dir, Gem.dir], m1],
]
tests.each do |_name, _paths, expected|
@@ -1581,8 +1667,8 @@ class TestGem < Gem::TestCase
end
def test_gem_path_ordering_short
- write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" }
- write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" }
+ write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" }
+ write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" }
g = util_spec 'g', '1', nil, "lib/g.rb"
m = util_spec 'm', '1', nil, "lib/m.rb"
@@ -1614,11 +1700,11 @@ class TestGem < Gem::TestCase
f.puts "gem 'c'"
end
- ENV['RUBYGEMS_GEMDEPS'] = path
-
- Gem.use_gemdeps
+ with_rubygems_gemdeps(path) do
+ Gem.use_gemdeps
- assert_equal add_bundler_full_name(%W(a-1 b-1 c-1)), loaded_spec_names
+ assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names
+ end
end
def test_auto_activation_of_used_gemdeps_file
@@ -1636,14 +1722,16 @@ class TestGem < Gem::TestCase
f.puts "gem 'c'"
end
- ENV['RUBYGEMS_GEMDEPS'] = "-"
+ with_rubygems_gemdeps("-") do
+ expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name)
+
+ Gem.use_gemdeps
- expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact
- assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name }
+ assert_equal expected_specs, loaded_spec_names
+ end
end
- LIB_PATH = File.expand_path "../../../lib".dup.tap(&Gem::UNTAINT), __FILE__.dup.tap(&Gem::UNTAINT)
- BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.tap(&Gem::UNTAINT)
+ BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }
BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze
def add_bundler_full_name(names)
@@ -1652,10 +1740,18 @@ class TestGem < Gem::TestCase
names
end
- def test_looks_for_gemdeps_files_automatically_on_start
- skip "Requiring bundler messes things up" if Gem.java_platform?
+ def test_looks_for_gemdeps_files_automatically_from_binstubs
+ pend "Requiring bundler messes things up" if Gem.java_platform?
+
+ a = util_spec "a", "1" do |s|
+ s.executables = %w[foo]
+ s.bindir = "exe"
+ end
+
+ write_file File.join(@tempdir, 'exe', 'foo') do |fp|
+ fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
+ end
- a = util_spec "a", "1", nil, "lib/a.rb"
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
@@ -1667,31 +1763,44 @@ class TestGem < Gem::TestCase
install_gem c, :install_dir => path
ENV['GEM_PATH'] = path
- ENV['RUBYGEMS_GEMDEPS'] = "-"
- path = File.join @tempdir, "gem.deps.rb"
- cmd = [Gem.ruby.dup.tap(&Gem::UNTAINT), "-I#{LIB_PATH.tap(&Gem::UNTAINT)}",
- "-I#{BUNDLER_LIB_PATH.tap(&Gem::UNTAINT)}", "-rrubygems"]
- cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort"
+ with_rubygems_gemdeps("-") do
+ new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
+ new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}"
- File.open path, "w" do |f|
- f.puts "gem 'a'"
- end
- out0 = IO.popen(cmd, &:read).split(/\n/)
+ path = File.join @tempdir, "gem.deps.rb"
- File.open path, "a" do |f|
- f.puts "gem 'b'"
- f.puts "gem 'c'"
- end
- out = IO.popen(cmd, &:read).split(/\n/)
+ File.open path, "w" do |f|
+ f.puts "gem 'a'"
+ end
+ out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
+ IO.popen("foo", &:read).split(/\n/)
+ end
- assert_equal ["b-1", "c-1"], out - out0
+ File.open path, "a" do |f|
+ f.puts "gem 'b'"
+ f.puts "gem 'c'"
+ end
+ out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
+ IO.popen("foo", &:read).split(/\n/)
+ end
+
+ assert_equal ["b-1", "c-1"], out - out0
+ end
end
- def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir
- skip "Requiring bundler messes things up" if Gem.java_platform?
+ def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir
+ pend "Requiring bundler messes things up" if Gem.java_platform?
+
+ a = util_spec "a", "1" do |s|
+ s.executables = %w[foo]
+ s.bindir = "exe"
+ end
+
+ write_file File.join(@tempdir, 'exe', 'foo') do |fp|
+ fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
+ end
- a = util_spec "a", "1", nil, "lib/a.rb"
b = util_spec "b", "1", nil, "lib/b.rb"
c = util_spec "c", "1", nil, "lib/c.rb"
@@ -1703,29 +1812,34 @@ class TestGem < Gem::TestCase
install_gem c, :install_dir => path
ENV['GEM_PATH'] = path
- ENV['RUBYGEMS_GEMDEPS'] = "-"
- Dir.mkdir "sub1"
+ with_rubygems_gemdeps("-") do
+ Dir.mkdir "sub1"
- path = File.join @tempdir, "gem.deps.rb"
- cmd = [Gem.ruby.dup.tap(&Gem::UNTAINT), "-Csub1", "-I#{LIB_PATH.tap(&Gem::UNTAINT)}",
- "-I#{BUNDLER_LIB_PATH.tap(&Gem::UNTAINT)}", "-rrubygems"]
- cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort"
+ new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
+ new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}"
- File.open path, "w" do |f|
- f.puts "gem 'a'"
- end
- out0 = IO.popen(cmd, &:read).split(/\n/)
+ path = File.join @tempdir, "gem.deps.rb"
- File.open path, "a" do |f|
- f.puts "gem 'b'"
- f.puts "gem 'c'"
- end
- out = IO.popen(cmd, &:read).split(/\n/)
+ File.open path, "w" do |f|
+ f.puts "gem 'a'"
+ end
+ out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
+ IO.popen("foo", :chdir => "sub1", &:read).split(/\n/)
+ end
+
+ File.open path, "a" do |f|
+ f.puts "gem 'b'"
+ f.puts "gem 'c'"
+ end
+ out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
+ IO.popen("foo", :chdir => "sub1", &:read).split(/\n/)
+ end
- Dir.rmdir "sub1"
+ Dir.rmdir "sub1"
- assert_equal ["b-1", "c-1"], out - out0
+ assert_equal ["b-1", "c-1"], out - out0
+ end
end
def test_register_default_spec
@@ -1773,7 +1887,7 @@ class TestGem < Gem::TestCase
spec = util_spec 'a', 1
install_specs spec
- spec = Gem::Specification.find { |s| s == spec }
+ spec = Gem::Specification.find {|s| s == spec }
refute spec.activated?
File.open gem_deps_file, 'w' do |io|
@@ -1784,30 +1898,28 @@ class TestGem < Gem::TestCase
Gem.use_gemdeps gem_deps_file
- assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names
+ assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
refute_nil Gem.gemdeps
end
def test_use_gemdeps_ENV
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
+ with_rubygems_gemdeps(nil) do
+ spec = util_spec 'a', 1
- spec = util_spec 'a', 1
+ refute spec.activated?
- refute spec.activated?
-
- File.open 'gem.deps.rb', 'w' do |io|
- io.write 'gem "a"'
- end
+ File.open 'gem.deps.rb', 'w' do |io|
+ io.write 'gem "a"'
+ end
- Gem.use_gemdeps
+ Gem.use_gemdeps
- refute spec.activated?
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ refute spec.activated?
+ end
end
def test_use_gemdeps_argument_missing
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
Gem.use_gemdeps 'gem.deps.rb'
end
@@ -1816,114 +1928,96 @@ class TestGem < Gem::TestCase
end
def test_use_gemdeps_argument_missing_match_ENV
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] =
- ENV['RUBYGEMS_GEMDEPS'], 'gem.deps.rb'
+ with_rubygems_gemdeps('gem.deps.rb') do
+ e = assert_raise ArgumentError do
+ Gem.use_gemdeps 'gem.deps.rb'
+ end
- e = assert_raises ArgumentError do
- Gem.use_gemdeps 'gem.deps.rb'
+ assert_equal 'Unable to find gem dependencies file at gem.deps.rb',
+ e.message
end
-
- assert_equal 'Unable to find gem dependencies file at gem.deps.rb',
- e.message
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
end
def test_use_gemdeps_automatic
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
+ with_rubygems_gemdeps('-') do
+ spec = util_spec 'a', 1
+ install_specs spec
+ spec = Gem::Specification.find {|s| s == spec }
- spec = util_spec 'a', 1
- install_specs spec
- spec = Gem::Specification.find { |s| s == spec }
-
- refute spec.activated?
+ refute spec.activated?
- File.open 'Gemfile', 'w' do |io|
- io.write 'gem "a"'
- end
+ File.open 'Gemfile', 'w' do |io|
+ io.write 'gem "a"'
+ end
- Gem.use_gemdeps
+ Gem.use_gemdeps
- assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
+ end
end
def test_use_gemdeps_automatic_missing
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
+ with_rubygems_gemdeps('-') do
+ Gem.use_gemdeps
- Gem.use_gemdeps
-
- assert true # count
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ assert true # count
+ end
end
def test_use_gemdeps_disabled
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], ''
+ with_rubygems_gemdeps('') do
+ spec = util_spec 'a', 1
- spec = util_spec 'a', 1
+ refute spec.activated?
- refute spec.activated?
-
- File.open 'gem.deps.rb', 'w' do |io|
- io.write 'gem "a"'
- end
+ File.open 'gem.deps.rb', 'w' do |io|
+ io.write 'gem "a"'
+ end
- Gem.use_gemdeps
+ Gem.use_gemdeps
- refute spec.activated?
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ refute spec.activated?
+ end
end
def test_use_gemdeps_missing_gem
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x'
-
- File.open 'x', 'w' do |io|
- io.write 'gem "a"'
- end
-
- platform = Bundler::GemHelpers.generic_local_platform
- if platform == Gem::Platform::RUBY
- platform = ''
- else
- platform = " #{platform}"
- end
+ with_rubygems_gemdeps('x') do
+ File.open 'x', 'w' do |io|
+ io.write 'gem "a"'
+ end
- expected = <<-EXPECTED
-Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile.
-You may need to `gem install -g` to install missing gems
+ expected = <<-EXPECTED
+Could not find gem 'a' in locally installed gems.
+You may need to `bundle install` to install missing gems
- EXPECTED
+ EXPECTED
- Gem::Deprecate.skip_during do
- assert_output nil, expected do
- Gem.use_gemdeps
+ Gem::Deprecate.skip_during do
+ actual_stdout, actual_stderr = capture_output do
+ Gem.use_gemdeps
+ end
+ assert_empty actual_stdout
+ assert_equal(expected, actual_stderr)
end
end
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
end
def test_use_gemdeps_specific
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x'
+ with_rubygems_gemdeps('x') do
+ spec = util_spec 'a', 1
+ install_specs spec
- spec = util_spec 'a', 1
- install_specs spec
-
- spec = Gem::Specification.find { |s| s == spec }
- refute spec.activated?
+ spec = Gem::Specification.find {|s| s == spec }
+ refute spec.activated?
- File.open 'x', 'w' do |io|
- io.write 'gem "a"'
- end
+ File.open 'x', 'w' do |io|
+ io.write 'gem "a"'
+ end
- Gem.use_gemdeps
+ Gem.use_gemdeps
- assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
+ end
end
def test_operating_system_defaults
@@ -1975,11 +2069,24 @@ You may need to `gem install -g` to install missing gems
end
end
- def with_bindir_and_exeext(bindir, exeext)
- bindir(bindir) do
- exeext(exeext) do
- yield
- end
+ def with_rb_config_ruby(path)
+ rb_config_singleton_class = class << RbConfig; self; end
+ orig_path = RbConfig.ruby
+
+ redefine_method(rb_config_singleton_class, :ruby, path)
+
+ yield
+ ensure
+ redefine_method(rb_config_singleton_class, :ruby, orig_path)
+ end
+
+ def redefine_method(base, method, new_result)
+ if RUBY_VERSION >= "2.5"
+ base.alias_method(method, method)
+ base.define_method(method) { new_result }
+ else
+ base.send(:alias_method, method, method)
+ base.send(:define_method, method) { new_result }
end
end
@@ -1992,7 +2099,7 @@ You may need to `gem install -g` to install missing gems
refute_includes $LOAD_PATH, test_plugin_path
$LOAD_PATH.unshift test_plugin_path
- capture_io do
+ capture_output do
yield
end
ensure
@@ -2029,4 +2136,21 @@ You may need to `gem install -g` to install missing gems
File.join Gem.dir, "cache"
end
+ def with_path_and_rubyopt(path_value, rubyopt_value)
+ path, ENV['PATH'] = ENV['PATH'], path_value
+ rubyopt, ENV['RUBYOPT'] = ENV['RUBYOPT'], rubyopt_value
+
+ yield
+ ensure
+ ENV['PATH'] = path
+ ENV['RUBYOPT'] = rubyopt
+ end
+
+ def with_rubygems_gemdeps(value)
+ rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], value
+
+ yield
+ ensure
+ ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
+ end
end
diff --git a/test/rubygems/test_gem_available_set.rb b/test/rubygems/test_gem_available_set.rb
index 64ee9a36a9..c4164d77f2 100644
--- a/test/rubygems/test_gem_available_set.rb
+++ b/test/rubygems/test_gem_available_set.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/available_set'
require 'rubygems/security'
class TestGemAvailableSet < Gem::TestCase
-
def setup
super
@@ -37,12 +36,12 @@ class TestGemAvailableSet < Gem::TestCase
dep = Gem::Resolver::DependencyRequest.new dep('a'), nil
- assert_equal %w[a-1], set.find_all(dep).map { |spec| spec.full_name }
+ assert_equal %w[a-1], set.find_all(dep).map {|spec| spec.full_name }
dep = Gem::Resolver::DependencyRequest.new dep('a', '>= 0.a'), nil
assert_equal %w[a-1 a-1.a],
- set.find_all(dep).map { |spec| spec.full_name }.sort
+ set.find_all(dep).map {|spec| spec.full_name }.sort
end
def test_match_platform
@@ -123,9 +122,8 @@ class TestGemAvailableSet < Gem::TestCase
set.add a2a, @source
set.add a2, @source
- g = set.sorted.map { |t| t.spec }
+ g = set.sorted.map {|t| t.spec }
assert_equal [a3a, a2, a2a, a1, a1a], g
end
-
end
diff --git a/test/rubygems/test_gem_bundler_version_finder.rb b/test/rubygems/test_gem_bundler_version_finder.rb
index 34a451b64d..e971e6ae29 100644
--- a/test/rubygems/test_gem_bundler_version_finder.rb
+++ b/test/rubygems/test_gem_bundler_version_finder.rb
@@ -1,20 +1,17 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemBundlerVersionFinder < Gem::TestCase
-
def setup
super
@argv = ARGV.dup
- @env = ENV.to_hash.clone
- ENV.delete("BUNDLER_VERSION")
@dollar_0 = $0
+ without_any_upwards_gemfiles
end
def teardown
ARGV.replace @argv
- ENV.replace @env
$0 = @dollar_0
super
@@ -78,6 +75,24 @@ class TestGemBundlerVersionFinder < Gem::TestCase
end
end
+ def test_deleted_directory
+ pend "Cannot perform this test on windows" if win_platform?
+ pend "Cannot perform this test on Solaris" if /solaris/ =~ RUBY_PLATFORM
+ require "tmpdir"
+
+ orig_dir = Dir.pwd
+
+ begin
+ Dir.mktmpdir("some_dir") do |dir|
+ Dir.chdir(dir)
+ end
+ ensure
+ Dir.chdir(orig_dir)
+ end
+
+ assert_nil bvf.bundler_version_with_reason
+ end
+
def test_compatible
assert bvf.compatible?(util_spec("foo"))
assert bvf.compatible?(util_spec("bundler", 1.1))
@@ -102,7 +117,7 @@ class TestGemBundlerVersionFinder < Gem::TestCase
def test_filter
versions = %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1]
- specs = versions.map { |v| util_spec("bundler", v) }
+ specs = versions.map {|v| util_spec("bundler", v) }
assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_filter_specs(specs).map(&:version).map(&:to_s)
@@ -128,5 +143,4 @@ class TestGemBundlerVersionFinder < Gem::TestCase
bvf.filter!(specs)
specs
end
-
end
diff --git a/test/rubygems/test_gem_command.rb b/test/rubygems/test_gem_command.rb
index 230baa5356..65b9b040b7 100644
--- a/test/rubygems/test_gem_command.rb
+++ b/test/rubygems/test_gem_command.rb
@@ -1,15 +1,12 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/command'
class Gem::Command
-
public :parser
-
end
class TestGemCommand < Gem::TestCase
-
def setup
super
@@ -34,7 +31,7 @@ class TestGemCommand < Gem::TestCase
def test_self_add_specific_extra_args
added_args = %w[--all]
- @cmd.add_option('--all') { |v,o| }
+ @cmd.add_option('--all') {|v,o| }
Gem::Command.add_specific_extra_args @cmd_name, added_args
@@ -57,6 +54,27 @@ class TestGemCommand < Gem::TestCase
assert_equal [], h
end
+ def test_self_extra_args
+ verbose, $VERBOSE, separator = $VERBOSE, nil, $;
+ extra_args = Gem::Command.extra_args
+
+ Gem::Command.extra_args = %w[--all]
+ assert_equal %w[--all], Gem::Command.extra_args
+
+ Gem::Command.extra_args = "--file --help"
+ assert_equal %w[--file --help], Gem::Command.extra_args
+
+ $; = "="
+
+ Gem::Command.extra_args = "--awesome=true --verbose"
+ assert_equal %w[--awesome=true --verbose], Gem::Command.extra_args
+
+ ensure
+ Gem::Command.extra_args = extra_args
+ $; = separator
+ $VERBOSE = verbose
+ end
+
def test_basic_accessors
assert_equal "doit", @cmd.command
assert_equal "gem doit", @cmd.program_name
@@ -82,7 +100,7 @@ class TestGemCommand < Gem::TestCase
@cmd.invoke
end
- assert_match %r|Usage: gem doit|, @ui.output
+ assert_match %r{Usage: gem doit}, @ui.output
end
def test_invoke
@@ -100,7 +118,7 @@ class TestGemCommand < Gem::TestCase
use_ui @ui do
@cmd.when_invoked { true }
- ex = assert_raises OptionParser::InvalidOption do
+ ex = assert_raise Gem::OptionParser::InvalidOption do
@cmd.invoke('-zzz')
end
@@ -168,7 +186,19 @@ class TestGemCommand < Gem::TestCase
@cmd.invoke '-h'
end
- assert_match %r|Usage: gem doit|, @ui.output
+ assert_match %r{Usage: gem doit}, @ui.output
+ end
+
+ def test_add_option
+ assert_nothing_raised RuntimeError do
+ @cmd.add_option('--force', 'skip validation of the spec') {|v,o| }
+ end
+ end
+
+ def test_add_option_with_empty
+ assert_raise RuntimeError, "Do not pass an empty string in opts" do
+ @cmd.add_option('', 'skip validation of the spec') {|v,o| }
+ end
end
def test_option_recognition
@@ -367,5 +397,4 @@ ERROR: Possible alternatives: non_existent_with_hint
assert_equal expected, @ui.error
end
-
end
diff --git a/test/rubygems/test_gem_command_manager.rb b/test/rubygems/test_gem_command_manager.rb
index 45be9f01be..ee71fc7c18 100644
--- a/test/rubygems/test_gem_command_manager.rb
+++ b/test/rubygems/test_gem_command_manager.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/command_manager'
class TestGemCommandManager < Gem::TestCase
-
PROJECT_DIR = File.expand_path('../../..', __FILE__).tap(&Gem::UNTAINT)
def setup
@@ -23,7 +22,7 @@ class TestGemCommandManager < Gem::TestCase
end
def test_find_command_ambiguous
- e = assert_raises Gem::CommandLineError do
+ e = assert_raise Gem::CommandLineError do
@command_manager.find_command 'u'
end
@@ -37,6 +36,18 @@ class TestGemCommandManager < Gem::TestCase
assert_kind_of Gem::Commands::InstallCommand, command
end
+ def test_find_login_alias_command
+ command = @command_manager.find_command 'login'
+
+ assert_kind_of Gem::Commands::SigninCommand, command
+ end
+
+ def test_find_logout_alias_comamnd
+ command = @command_manager.find_command 'logout'
+
+ assert_kind_of Gem::Commands::SignoutCommand, command
+ end
+
def test_find_command_ambiguous_exact
ins_command = Class.new
Gem::Commands.send :const_set, :InsCommand, ins_command
@@ -51,7 +62,7 @@ class TestGemCommandManager < Gem::TestCase
end
def test_find_command_unknown
- e = assert_raises Gem::CommandLineError do
+ e = assert_raise Gem::CommandLineError do
@command_manager.find_command 'xyz'
end
@@ -66,7 +77,7 @@ class TestGemCommandManager < Gem::TestCase
@command_manager.register_command :interrupt
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@command_manager.run %w[interrupt]
end
assert_equal '', ui.output
@@ -83,7 +94,7 @@ class TestGemCommandManager < Gem::TestCase
@command_manager.register_command :crash
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@command_manager.run %w[crash]
end
assert_equal '', ui.output
@@ -97,7 +108,7 @@ class TestGemCommandManager < Gem::TestCase
def test_process_args_bad_arg
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@command_manager.process_args %w[--bad-arg]
end
end
@@ -224,26 +235,34 @@ class TestGemCommandManager < Gem::TestCase
end
#check defaults
- @command_manager.process_args %w[query]
+ Gem::Deprecate.skip_during do
+ @command_manager.process_args %w[query]
+ end
assert_equal(//, check_options[:name])
assert_equal :local, check_options[:domain]
assert_equal false, check_options[:details]
#check settings
check_options = nil
- @command_manager.process_args %w[query --name foobar --local --details]
+ Gem::Deprecate.skip_during do
+ @command_manager.process_args %w[query --name foobar --local --details]
+ end
assert_equal(/foobar/i, check_options[:name])
assert_equal :local, check_options[:domain]
assert_equal true, check_options[:details]
#remote domain
check_options = nil
- @command_manager.process_args %w[query --remote]
+ Gem::Deprecate.skip_during do
+ @command_manager.process_args %w[query --remote]
+ end
assert_equal :remote, check_options[:domain]
#both (local/remote) domains
check_options = nil
- @command_manager.process_args %w[query --both]
+ Gem::Deprecate.skip_during do
+ @command_manager.process_args %w[query --both]
+ end
assert_equal :both, check_options[:domain]
end
@@ -268,4 +287,28 @@ class TestGemCommandManager < Gem::TestCase
assert_equal Dir.pwd, check_options[:install_dir]
end
+ def test_deprecated_command
+ require 'rubygems/command'
+ foo_command = Class.new(Gem::Command) do
+ extend Gem::Deprecate
+
+ rubygems_deprecate_command
+
+ def execute
+ say "pew pew!"
+ end
+ end
+
+ Gem::Commands.send(:const_set, :FooCommand, foo_command)
+ @command_manager.register_command(:foo, foo_command.new("foo"))
+
+ use_ui @ui do
+ @command_manager.process_args(%w[foo])
+ end
+
+ assert_equal "pew pew!\n", @ui.output
+ assert_match(/WARNING: foo command is deprecated. It will be removed in Rubygems [0-9]+/, @ui.error)
+ ensure
+ Gem::Commands.send(:remove_const, :FooCommand)
+ end
end
diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb
index 309e15f859..1304beb580 100644
--- a/test/rubygems/test_gem_commands_build_command.rb
+++ b/test/rubygems/test_gem_commands_build_command.rb
@@ -1,11 +1,9 @@
-
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/build_command'
require 'rubygems/package'
class TestGemCommandsBuildCommand < Gem::TestCase
-
CERT_FILE = cert_path 'public3072'
SIGNING_KEY = key_path 'private3072'
@@ -17,8 +15,13 @@ class TestGemCommandsBuildCommand < Gem::TestCase
readme_file = File.join(@tempdir, 'README.md')
- File.open readme_file, 'w' do |f|
- f.write 'My awesome gem'
+ begin
+ umask_orig = File.umask(2)
+ File.open readme_file, 'w' do |f|
+ f.write 'My awesome gem'
+ end
+ ensure
+ File.umask(umask_orig)
end
@gem = util_spec 'some_gem' do |s|
@@ -34,6 +37,8 @@ class TestGemCommandsBuildCommand < Gem::TestCase
assert @cmd.options[:force]
assert @cmd.options[:strict]
+ assert @cmd.handles?(%W[--platform #{Gem::Platform.local}])
+ assert_includes Gem.platforms, Gem::Platform.local
end
def test_options_filename
@@ -83,6 +88,26 @@ class TestGemCommandsBuildCommand < Gem::TestCase
util_test_build_gem @gem
end
+ def test_execute_platform
+ gemspec_file = File.join(@tempdir, @gem.spec_name)
+
+ File.open gemspec_file, 'w' do |gs|
+ gs.write @gem.to_ruby
+ end
+
+ @cmd.options[:args] = [gemspec_file]
+
+ platforms = Gem.platforms.dup
+ begin
+ Gem.platforms << Gem::Platform.new("java")
+
+ spec = util_test_build_gem @gem, suffix: "java"
+ ensure
+ Gem.platforms.replace(platforms)
+ end
+ assert_match spec.platform, "java"
+ end
+
def test_execute_bad_name
[".", "-", "_"].each do |special_char|
gem = util_spec 'some_gem_with_bad_name' do |s|
@@ -101,7 +126,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
use_ui @ui do
Dir.chdir @tempdir do
- assert_raises Gem::InvalidSpecificationException do
+ assert_raise Gem::InvalidSpecificationException do
@cmd.execute
end
end
@@ -123,7 +148,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_execute_rubyforge_project_warning
- rubyforge_gemspec = File.join SPECIFICATIONS, "rubyforge-0.0.1.gemspec"
+ rubyforge_gemspec = File.expand_path File.join("specifications", "rubyforge-0.0.1.gemspec"), __dir__
@cmd.options[:args] = [rubyforge_gemspec]
@@ -155,7 +180,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
use_ui @ui do
Dir.chdir @tempdir do
- assert_raises Gem::InvalidSpecificationException do
+ assert_raise Gem::InvalidSpecificationException do
@cmd.execute
end
end
@@ -183,8 +208,8 @@ class TestGemCommandsBuildCommand < Gem::TestCase
@cmd.options[:args] = [gemspec_file]
out, err = use_ui @ui do
- capture_io do
- assert_raises Gem::MockGemUi::TermError do
+ capture_output do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -200,13 +225,13 @@ class TestGemCommandsBuildCommand < Gem::TestCase
def test_execute_missing_file
@cmd.options[:args] = %w[some_gem]
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
assert_equal '', @ui.output
- assert_equal "ERROR: Gemspec file not found: some_gem.gemspec\n", @ui.error
+ assert_equal "ERROR: Couldn't find a gemspec file matching 'some_gem' in #{@tempdir}\n", @ui.error
end
def test_execute_outside_dir
@@ -247,8 +272,200 @@ class TestGemCommandsBuildCommand < Gem::TestCase
assert_equal "this is a summary", spec.summary
end
+ def test_execute_outside_dir_with_glob_argument
+ gemspec_dir = File.join @tempdir, 'build_command_gem'
+ gemspec_file = File.join gemspec_dir, @gem.spec_name
+ readme_file = File.join gemspec_dir, 'README.md'
+
+ FileUtils.mkdir_p gemspec_dir
+
+ File.open readme_file, 'w' do |f|
+ f.write "My awesome gem"
+ end
+
+ File.open gemspec_file, 'w' do |gs|
+ gs.write @gem.to_ruby
+ end
+
+ @cmd.options[:build_path] = gemspec_dir
+ @cmd.options[:args] = ["*.gemspec"]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ output = @ui.output.split "\n"
+ assert_equal " Successfully built RubyGem", output.shift
+ assert_equal " Name: some_gem", output.shift
+ assert_equal " Version: 2", output.shift
+ assert_equal " File: some_gem-2.gem", output.shift
+ assert_equal [], output
+
+ gem_file = File.join gemspec_dir, File.basename(@gem.cache_file)
+ assert File.exist?(gem_file)
+
+ spec = Gem::Package.new(gem_file).spec
+
+ assert_equal "some_gem", spec.name
+ assert_equal "this is a summary", spec.summary
+ end
+
+ def test_execute_outside_dir_no_gemspec_present
+ gemspec_dir = File.join @tempdir, 'build_command_gem'
+ gemspec_file = File.join @tempdir, @gem.spec_name
+ readme_file = File.join gemspec_dir, 'README.md'
+
+ FileUtils.mkdir_p gemspec_dir
+
+ File.open readme_file, 'w' do |f|
+ f.write "My awesome gem"
+ end
+
+ File.open gemspec_file, 'w' do |gs|
+ gs.write @gem.to_ruby
+ end
+
+ @cmd.options[:build_path] = gemspec_dir
+ @cmd.options[:args] = ["*.gemspec"]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError do
+ @cmd.execute
+ end
+ end
+
+ assert_equal "", @ui.output
+ assert_equal "ERROR: Couldn't find a gemspec file matching '*.gemspec' in #{gemspec_dir}\n", @ui.error
+
+ gem_file = File.join gemspec_dir, File.basename(@gem.cache_file)
+ refute File.exist?(gem_file)
+ end
+
+ def test_execute_outside_dir_without_gem_name
+ gemspec_dir = File.join(@tempdir, 'build_command_gem')
+ gemspec_file = File.join(gemspec_dir, @gem.spec_name)
+
+ readme_file = File.join gemspec_dir, 'README.md'
+
+ FileUtils.mkdir_p(gemspec_dir)
+
+ File.open readme_file, 'w' do |f|
+ f.write "My awesome gem"
+ end
+
+ File.open(gemspec_file, "w") do |gs|
+ gs.write(@gem.to_ruby)
+ end
+
+ @cmd.options[:build_path] = gemspec_dir
+ @cmd.options[:args] = []
+
+ use_ui @ui do
+ Dir.chdir(gemspec_dir) do
+ @cmd.execute
+ end
+ end
+
+ output = @ui.output.split("\n")
+ assert_equal " Successfully built RubyGem", output.shift
+ assert_equal " Name: some_gem", output.shift
+ assert_equal " Version: 2", output.shift
+ assert_equal " File: some_gem-2.gem", output.shift
+ assert_equal [], output
+
+ gem_file = File.join gemspec_dir, File.basename(@gem.cache_file)
+ assert File.exist?(gem_file)
+
+ spec = Gem::Package.new(gem_file).spec
+
+ assert_equal "some_gem", spec.name
+ assert_equal "this is a summary", spec.summary
+ end
+
+ def test_execute_outside_dir_with_external_gemspec
+ gemspec_dir = File.join @tempdir, 'gemspec_dir'
+ gemspec_file = File.join gemspec_dir, @gem.spec_name
+
+ gemcode_dir = File.join @tempdir, 'build_command_gem'
+ readme_file = File.join gemcode_dir, 'README.md'
+
+ FileUtils.mkdir_p gemspec_dir
+ FileUtils.mkdir_p gemcode_dir
+
+ File.open readme_file, 'w' do |f|
+ f.write "My awesome gem in nested directory"
+ end
+
+ File.open gemspec_file, 'w' do |gs|
+ gs.write @gem.to_ruby
+ end
+
+ @cmd.options[:build_path] = gemcode_dir
+ @cmd.options[:args] = [gemspec_file]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ output = @ui.output.split "\n"
+ assert_equal " Successfully built RubyGem", output.shift
+ assert_equal " Name: some_gem", output.shift
+ assert_equal " Version: 2", output.shift
+ assert_equal " File: some_gem-2.gem", output.shift
+ assert_equal [], output
+
+ gem_file = File.join gemcode_dir, File.basename(@gem.cache_file)
+ assert File.exist?(gem_file)
+
+ spec = Gem::Package.new(gem_file).spec
+
+ assert_equal "some_gem", spec.name
+ assert_equal "this is a summary", spec.summary
+ end
+
+ def test_execute_outside_dir_with_external_relative_gemspec
+ gemspec_dir = File.join @tempdir, 'gemspec_dir'
+ gemspec_file = File.join gemspec_dir, @gem.spec_name
+
+ gemcode_dir = File.join @tempdir, 'build_command_gem'
+ readme_file = File.join gemcode_dir, 'README.md'
+
+ FileUtils.mkdir_p gemspec_dir
+ FileUtils.mkdir_p gemcode_dir
+
+ File.open readme_file, 'w' do |f|
+ f.write "My awesome gem in nested directory"
+ end
+
+ File.open gemspec_file, 'w' do |gs|
+ gs.write @gem.to_ruby
+ end
+
+ @cmd.options[:build_path] = gemcode_dir
+ @cmd.options[:args] = [File.join("..", "gemspec_dir", @gem.spec_name)]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ output = @ui.output.split "\n"
+ assert_equal " Successfully built RubyGem", output.shift
+ assert_equal " Name: some_gem", output.shift
+ assert_equal " Version: 2", output.shift
+ assert_equal " File: some_gem-2.gem", output.shift
+ assert_equal [], output
+
+ gem_file = File.join gemcode_dir, File.basename(@gem.cache_file)
+ assert File.exist?(gem_file)
+
+ spec = Gem::Package.new(gem_file).spec
+
+ assert_equal "some_gem", spec.name
+ assert_equal "this is a summary", spec.summary
+ end
+
def test_can_find_gemspecs_without_dot_gemspec
- gemspec_file = File.join(@tempdir, @gem.spec_name)
+ gemspec_file = File.join(@tempdir, @gem.name)
File.open gemspec_file + ".gemspec", 'w' do |gs|
gs.write @gem.to_ruby
@@ -310,7 +527,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
use_ui @ui do
Dir.chdir(gemspec_dir) do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -324,27 +541,29 @@ class TestGemCommandsBuildCommand < Gem::TestCase
refute File.exist?(expected_gem)
end
- def util_test_build_gem(gem)
+ def util_test_build_gem(gem, suffix: nil)
use_ui @ui do
Dir.chdir @tempdir do
@cmd.execute
end
end
-
+ suffix &&= "-#{suffix}"
+ gem_file = "some_gem-2#{suffix}.gem"
output = @ui.output.split "\n"
assert_equal " Successfully built RubyGem", output.shift
assert_equal " Name: some_gem", output.shift
assert_equal " Version: 2", output.shift
- assert_equal " File: some_gem-2.gem", output.shift
+ assert_equal " File: #{gem_file}", output.shift
assert_equal [], output
- gem_file = File.join(@tempdir, File.basename(gem.cache_file))
+ gem_file = File.join(@tempdir, gem_file)
assert File.exist?(gem_file)
spec = Gem::Package.new(gem_file).spec
assert_equal "some_gem", spec.name
assert_equal "this is a summary", spec.summary
+ spec
end
def test_execute_force
@@ -363,7 +582,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_build_signed_gem
- skip 'openssl is missing' unless defined?(OpenSSL::SSL) && !java_platform?
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL && !java_platform?
trust_dir = Gem::Security.trust_dir
@@ -390,7 +609,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_build_signed_gem_with_cert_expiration_length_days
- skip 'openssl is missing' unless defined?(OpenSSL::SSL) && !java_platform?
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL && !java_platform?
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
@@ -434,7 +653,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_build_auto_resign_cert
- skip 'openssl is missing' unless defined?(OpenSSL::SSL) && !java_platform?
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL && !java_platform?
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
@@ -505,5 +724,4 @@ class TestGemCommandsBuildCommand < Gem::TestCase
ensure
ENV["SOURCE_DATE_EPOCH"] = epoch
end
-
end
diff --git a/test/rubygems/test_gem_commands_cert_command.rb b/test/rubygems/test_gem_commands_cert_command.rb
index fd1e66b915..901bf5aed6 100644
--- a/test/rubygems/test_gem_commands_cert_command.rb
+++ b/test/rubygems/test_gem_commands_cert_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/cert_command'
-unless defined?(OpenSSL::SSL)
+unless Gem::HAVE_OPENSSL
warn 'Skipping `gem cert` tests. openssl not found.'
end
@@ -11,13 +11,13 @@ if Gem.java_platform?
end
class TestGemCommandsCertCommand < Gem::TestCase
-
ALTERNATE_CERT = load_cert 'alternate'
EXPIRED_PUBLIC_CERT = load_cert 'expired'
- ALTERNATE_KEY_FILE = key_path 'alternate'
- PRIVATE_KEY_FILE = key_path 'private'
- PUBLIC_KEY_FILE = key_path 'public'
+ ALTERNATE_KEY_FILE = key_path 'alternate'
+ PRIVATE_KEY_FILE = key_path 'private'
+ PRIVATE_EC_KEY_FILE = key_path 'private_ec'
+ PUBLIC_KEY_FILE = key_path 'public'
ALTERNATE_CERT_FILE = cert_path 'alternate'
CHILD_CERT_FILE = cert_path 'child'
@@ -55,7 +55,7 @@ class TestGemCommandsCertCommand < Gem::TestCase
assert_equal PUBLIC_CERT.to_pem, match.first.to_pem
assert_equal @trust_dir.cert_path(PUBLIC_CERT), match.last
- assert_raises StopIteration do
+ assert_raise StopIteration do
matches.next
end
end
@@ -70,7 +70,7 @@ class TestGemCommandsCertCommand < Gem::TestCase
assert_equal ALTERNATE_CERT.to_pem, match.first.to_pem
assert_equal @trust_dir.cert_path(ALTERNATE_CERT), match.last
- assert_raises StopIteration do
+ assert_raise StopIteration do
matches.next
end
end
@@ -84,7 +84,7 @@ class TestGemCommandsCertCommand < Gem::TestCase
cert_path = @trust_dir.cert_path PUBLIC_CERT
- assert_path_exists cert_path
+ assert_path_exist cert_path
assert_equal "Added '/CN=nobody/DC=example'\n", @ui.output
assert_empty @ui.error
@@ -139,8 +139,44 @@ Added '/CN=alternate/DC=example'
assert_empty output
assert_empty @build_ui.error
- assert_path_exists File.join(@tempdir, 'gem-private_key.pem')
- assert_path_exists File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_exist File.join(@tempdir, 'gem-private_key.pem')
+ assert_path_exist File.join(@tempdir, 'gem-public_cert.pem')
+ end
+
+ def test_execute_build_key_algorithm_ec_key
+ passphrase = 'Foo bar'
+
+ @cmd.handle_options %W[--build nobody@example.com --key-algorithm ec]
+
+ @build_ui = Gem::MockGemUi.new "#{passphrase}\n#{passphrase}"
+
+ use_ui @build_ui do
+ @cmd.execute
+ end
+
+ output = @build_ui.output.squeeze("\n").split "\n"
+
+ assert_equal "Passphrase for your Private Key: ",
+ output.shift
+ assert_equal "Please repeat the passphrase for your Private Key: ",
+ output.shift
+ assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}",
+ output.shift
+ assert_equal "Private Key: #{File.join @tempdir, 'gem-private_key.pem'}",
+ output.shift
+
+ assert_equal "Don't forget to move the key file to somewhere private!",
+ output.shift
+
+ assert_empty output
+ assert_empty @build_ui.error
+
+ assert_path_exist File.join(@tempdir, 'gem-private_key.pem')
+
+ cert_path = File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_exist cert_path
+ cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
+ assert cert.public_key.is_a? OpenSSL::PKey::EC
end
def test_execute_build_bad_email_address
@@ -153,15 +189,15 @@ Added '/CN=alternate/DC=example'
use_ui @build_ui do
- e = assert_raises Gem::CommandLineError do
+ e = assert_raise Gem::CommandLineError do
@cmd.execute
end
assert_equal "Invalid email address #{email}",
e.message
- refute_path_exists File.join(@tempdir, 'gem-private_key.pem')
- refute_path_exists File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem')
+ assert_path_not_exist File.join(@tempdir, 'gem-public_cert.pem')
end
end
@@ -196,8 +232,8 @@ Added '/CN=alternate/DC=example'
assert_empty output
assert_empty @build_ui.error
- assert_path_exists File.join(@tempdir, 'gem-private_key.pem')
- assert_path_exists File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_exist File.join(@tempdir, 'gem-private_key.pem')
+ assert_path_exist File.join(@tempdir, 'gem-public_cert.pem')
pem = File.read("#{@tempdir}/gem-public_cert.pem")
cert = OpenSSL::X509::Certificate.new(pem)
@@ -215,7 +251,7 @@ Added '/CN=alternate/DC=example'
@build_ui = Gem::MockGemUi.new "#{passphrase}\n#{passphrase_confirmation}"
use_ui @build_ui do
- e = assert_raises Gem::CommandLineError do
+ e = assert_raise Gem::CommandLineError do
@cmd.execute
end
@@ -233,8 +269,8 @@ Added '/CN=alternate/DC=example'
end
- refute_path_exists File.join(@tempdir, 'gem-private_key.pem')
- refute_path_exists File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem')
+ assert_path_not_exist File.join(@tempdir, 'gem-public_cert.pem')
end
def test_execute_build_key
@@ -255,8 +291,8 @@ Added '/CN=alternate/DC=example'
assert_empty output
assert_empty @ui.error
- assert_path_exists File.join(@tempdir, 'gem-public_cert.pem')
- refute_path_exists File.join(@tempdir, 'gem-private_key.pem')
+ assert_path_exist File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem')
end
def test_execute_build_encrypted_key
@@ -277,7 +313,29 @@ Added '/CN=alternate/DC=example'
assert_empty output
assert_empty @ui.error
- assert_path_exists File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_exist File.join(@tempdir, 'gem-public_cert.pem')
+ end
+
+ def test_execute_build_ec_key
+ @cmd.handle_options %W[
+ --build nobody@example.com
+ --private-key #{PRIVATE_EC_KEY_FILE}
+ ]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ output = @ui.output.split "\n"
+
+ assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}",
+ output.shift
+
+ assert_empty output
+ assert_empty @ui.error
+
+ assert_path_exist File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem')
end
def test_execute_certificate
@@ -347,7 +405,7 @@ Added '/CN=alternate/DC=example'
cert_path = @trust_dir.cert_path PUBLIC_CERT
- assert_path_exists cert_path
+ assert_path_exist cert_path
@cmd.handle_options %W[--remove nobody]
@@ -358,7 +416,7 @@ Added '/CN=alternate/DC=example'
assert_equal "Removed '/CN=nobody/DC=example'\n", @ui.output
assert_equal '', @ui.error
- refute_path_exists cert_path
+ assert_path_not_exist cert_path
end
def test_execute_remove_multiple
@@ -368,8 +426,8 @@ Added '/CN=alternate/DC=example'
public_path = @trust_dir.cert_path PUBLIC_CERT
alternate_path = @trust_dir.cert_path ALTERNATE_CERT
- assert_path_exists public_path
- assert_path_exists alternate_path
+ assert_path_exist public_path
+ assert_path_exist alternate_path
@cmd.handle_options %W[--remove example]
@@ -385,8 +443,8 @@ Removed '/CN=nobody/DC=example'
assert_equal expected, @ui.output
assert_equal '', @ui.error
- refute_path_exists public_path
- refute_path_exists alternate_path
+ assert_path_not_exist public_path
+ assert_path_not_exist alternate_path
end
def test_execute_remove_twice
@@ -396,8 +454,8 @@ Removed '/CN=nobody/DC=example'
public_path = @trust_dir.cert_path PUBLIC_CERT
alternate_path = @trust_dir.cert_path ALTERNATE_CERT
- assert_path_exists public_path
- assert_path_exists alternate_path
+ assert_path_exist public_path
+ assert_path_exist alternate_path
@cmd.handle_options %W[--remove nobody --remove alternate]
@@ -413,8 +471,8 @@ Removed '/CN=alternate/DC=example'
assert_equal expected, @ui.output
assert_equal '', @ui.error
- refute_path_exists public_path
- refute_path_exists alternate_path
+ assert_path_not_exist public_path
+ assert_path_not_exist alternate_path
end
def test_execute_sign
@@ -553,7 +611,7 @@ Removed '/CN=alternate/DC=example'
@cmd.handle_options %W[--sign #{path}]
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -581,7 +639,7 @@ ERROR: --certificate not specified and ~/.gem/gem-public_cert.pem does not exis
@cmd.handle_options %W[--sign #{path}]
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -675,19 +733,19 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
]
assert_equal [PUBLIC_CERT.to_pem, ALTERNATE_CERT.to_pem],
- @cmd.options[:add].map { |cert| cert.to_pem }
+ @cmd.options[:add].map {|cert| cert.to_pem }
assert_equal %w[nobody example], @cmd.options[:remove]
assert_equal %w[nobody@example other@example],
- @cmd.options[:build].map { |name| name.to_s }
+ @cmd.options[:build].map {|name| name.to_s }
assert_equal ['', 'example'], @cmd.options[:list]
end
def test_handle_options_add_bad
nonexistent = File.join @tempdir, 'nonexistent'
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--add #{nonexistent}]
end
@@ -697,7 +755,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
bad = File.join @tempdir, 'bad'
FileUtils.touch bad
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--add #{bad}]
end
@@ -707,7 +765,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
def test_handle_options_certificate
nonexistent = File.join @tempdir, 'nonexistent'
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--certificate #{nonexistent}]
end
@@ -717,7 +775,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
bad = File.join @tempdir, 'bad'
FileUtils.touch bad
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--certificate #{bad}]
end
@@ -728,7 +786,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
def test_handle_options_key_bad
nonexistent = File.join @tempdir, 'nonexistent'
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--private-key #{nonexistent}]
end
@@ -739,14 +797,14 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
bad = File.join @tempdir, 'bad'
FileUtils.touch bad
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--private-key #{bad}]
end
- assert_equal "invalid argument: --private-key #{bad}: invalid RSA key",
+ assert_equal "invalid argument: --private-key #{bad}: invalid RSA, DSA, or EC key",
e.message
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--private-key #{PUBLIC_KEY_FILE}]
end
@@ -793,7 +851,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
def test_handle_options_sign_nonexistent
nonexistent = File.join @tempdir, 'nonexistent'
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[
--private-key #{ALTERNATE_KEY_FILE}
@@ -806,5 +864,4 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
assert_equal "invalid argument: --sign #{nonexistent}: does not exist",
e.message
end
-
-end if defined?(OpenSSL::SSL) && !Gem.java_platform?
+end if Gem::HAVE_OPENSSL && !Gem.java_platform?
diff --git a/test/rubygems/test_gem_commands_check_command.rb b/test/rubygems/test_gem_commands_check_command.rb
index 6a6033d35d..f280b060c4 100644
--- a/test/rubygems/test_gem_commands_check_command.rb
+++ b/test/rubygems/test_gem_commands_check_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/check_command'
class TestGemCommandsCheckCommand < Gem::TestCase
-
def setup
super
@@ -51,19 +50,18 @@ class TestGemCommandsCheckCommand < Gem::TestCase
FileUtils.rm b.spec_file
- assert_path_exists b.gem_dir
- refute_path_exists b.spec_file
+ assert_path_exist b.gem_dir
+ assert_path_not_exist b.spec_file
Gem.use_paths @gemhome
- capture_io do
+ capture_output do
use_ui @ui do
@cmd.doctor
end
end
- refute_path_exists b.gem_dir
- refute_path_exists b.spec_file
+ assert_path_not_exist b.gem_dir
+ assert_path_not_exist b.spec_file
end
-
end
diff --git a/test/rubygems/test_gem_commands_cleanup_command.rb b/test/rubygems/test_gem_commands_cleanup_command.rb
index 3494085a64..fc98998012 100644
--- a/test/rubygems/test_gem_commands_cleanup_command.rb
+++ b/test/rubygems/test_gem_commands_cleanup_command.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/cleanup_command'
require 'rubygems/installer'
class TestGemCommandsCleanupCommand < Gem::TestCase
-
def setup
super
@@ -23,10 +22,21 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
end
def test_handle_options_dry_run
- @cmd.handle_options %w[--dryrun]
+ @cmd.handle_options %w[--dry-run]
assert @cmd.options[:dryrun]
end
+ def test_handle_options_deprecated_dry_run
+ use_ui @ui do
+ @cmd.handle_options %w[--dryrun]
+ assert @cmd.options[:dryrun]
+ end
+
+ assert_equal \
+ "WARNING: The \"--dryrun\" option has been deprecated and will be removed in future versions of Rubygems. Use --dry-run instead\n",
+ @ui.error
+ end
+
def test_handle_options_n
@cmd.handle_options %w[-n]
assert @cmd.options[:dryrun]
@@ -52,7 +62,7 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
- refute_path_exists @a_1.gem_dir
+ assert_path_not_exist @a_1.gem_dir
end
def test_execute_all_dependencies
@@ -71,8 +81,8 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
- refute_path_exists @a_1.gem_dir
- refute_path_exists @b_1.gem_dir
+ assert_path_not_exist @a_1.gem_dir
+ assert_path_not_exist @b_1.gem_dir
end
def test_execute_dev_dependencies
@@ -91,7 +101,7 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
- assert_path_exists @a_1.gem_dir
+ assert_path_exist @a_1.gem_dir
end
def test_execute_without_dev_dependencies
@@ -110,7 +120,7 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
- refute_path_exists @a_1.gem_dir
+ assert_path_not_exist @a_1.gem_dir
end
def test_execute_all
@@ -133,8 +143,8 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
assert_equal @gemhome, Gem.dir, 'GEM_HOME'
assert_equal [@gemhome, gemhome2], Gem.path.sort, 'GEM_PATH'
- refute_path_exists @a_1.gem_dir
- refute_path_exists @b_1.gem_dir
+ assert_path_not_exist @a_1.gem_dir
+ assert_path_not_exist @b_1.gem_dir
end
def test_execute_all_user
@@ -143,15 +153,15 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
Gem::Specification.dirs = [Gem.dir, Gem.user_dir]
- assert_path_exists @a_1.gem_dir
- assert_path_exists @a_1_1.gem_dir
+ assert_path_exist @a_1.gem_dir
+ assert_path_exist @a_1_1.gem_dir
@cmd.options[:args] = %w[a]
@cmd.execute
- refute_path_exists @a_1.gem_dir
- refute_path_exists @a_1_1.gem_dir
+ assert_path_not_exist @a_1.gem_dir
+ assert_path_not_exist @a_1_1.gem_dir
end
def test_execute_all_user_no_sudo
@@ -162,15 +172,15 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
Gem::Specification.dirs = [Gem.dir, Gem.user_dir]
- assert_path_exists @a_1.gem_dir
- assert_path_exists @a_1_1.gem_dir
+ assert_path_exist @a_1.gem_dir
+ assert_path_exist @a_1_1.gem_dir
@cmd.options[:args] = %w[a]
@cmd.execute
- assert_path_exists @a_1.gem_dir
- assert_path_exists @a_1_1.gem_dir
+ assert_path_exist @a_1.gem_dir
+ assert_path_exist @a_1_1.gem_dir
ensure
FileUtils.chmod 0755, @gemhome
end unless win_platform? || Process.uid.zero?
@@ -181,7 +191,7 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
- assert_path_exists @a_1.gem_dir
+ assert_path_exist @a_1.gem_dir
end
def test_execute_keeps_older_versions_with_deps
@@ -200,7 +210,7 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
- assert_path_exists @b_1.gem_dir
+ assert_path_exist @b_1.gem_dir
end
def test_execute_ignore_default_gem_verbose
@@ -211,7 +221,7 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@b_2 = util_spec 'b', 3
install_gem @b_1
- install_default_specs @b_default
+ install_default_gems @b_default
install_gem @b_2
@cmd.options[:args] = []
@@ -220,7 +230,7 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r%^Skipped default gems: b-2%, @ui.output
+ assert_match %r{^Skipped default gems: b-2}, @ui.output
assert_empty @ui.error
end
@@ -247,9 +257,9 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
- assert_path_exists c_1.gem_dir
- refute_path_exists d_1.gem_dir
- refute_path_exists e_1.gem_dir
+ assert_path_exist c_1.gem_dir
+ assert_path_not_exist d_1.gem_dir
+ assert_path_not_exist e_1.gem_dir
end
def test_execute_user_install
@@ -272,11 +282,10 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
- refute_path_exists c_1.gem_dir
- assert_path_exists c_2.gem_dir
+ assert_path_not_exist c_1.gem_dir
+ assert_path_exist c_2.gem_dir
- assert_path_exists d_1.gem_dir
- assert_path_exists d_2.gem_dir
+ assert_path_exist d_1.gem_dir
+ assert_path_exist d_2.gem_dir
end
-
end
diff --git a/test/rubygems/test_gem_commands_contents_command.rb b/test/rubygems/test_gem_commands_contents_command.rb
index a8d6efe794..d79174717b 100644
--- a/test/rubygems/test_gem_commands_contents_command.rb
+++ b/test/rubygems/test_gem_commands_contents_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/contents_command'
class TestGemCommandsContentsCommand < Gem::TestCase
-
def setup
super
@@ -27,8 +26,8 @@ class TestGemCommandsContentsCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|lib/foo\.rb|, @ui.output
- assert_match %r|Rakefile|, @ui.output
+ assert_match %r{lib/foo\.rb}, @ui.output
+ assert_match %r{Rakefile}, @ui.output
assert_equal "", @ui.error
end
@@ -42,23 +41,23 @@ class TestGemCommandsContentsCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|lib/foo\.rb|, @ui.output
- assert_match %r|lib/bar\.rb|, @ui.output
- assert_match %r|Rakefile|, @ui.output
+ assert_match %r{lib/foo\.rb}, @ui.output
+ assert_match %r{lib/bar\.rb}, @ui.output
+ assert_match %r{Rakefile}, @ui.output
assert_equal "", @ui.error
end
def test_execute_bad_gem
@cmd.options[:args] = %w[foo]
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
end
- assert_match %r|Unable to find gem 'foo' in default gem paths|, @ui.output
- assert_match %r|Directories searched:|, @ui.output
+ assert_match %r{Unable to find gem 'foo' in default gem paths}, @ui.output
+ assert_match %r{Directories searched:}, @ui.output
assert_equal "", @ui.error
end
@@ -71,8 +70,8 @@ class TestGemCommandsContentsCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|lib/foo\.rb|, @ui.output
- assert_match %r|Rakefile|, @ui.output
+ assert_match %r{lib/foo\.rb}, @ui.output
+ assert_match %r{Rakefile}, @ui.output
assert_equal "", @ui.error
end
@@ -86,8 +85,8 @@ class TestGemCommandsContentsCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|lib/foo\.rb|, @ui.output
- refute_match %r|Rakefile|, @ui.output
+ assert_match %r{lib/foo\.rb}, @ui.output
+ refute_match %r{Rakefile}, @ui.output
assert_equal "", @ui.error
end
@@ -95,7 +94,23 @@ class TestGemCommandsContentsCommand < Gem::TestCase
def test_execute_missing_single
@cmd.options[:args] = %w[foo]
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_match "Unable to find gem 'foo'", @ui.output
+ assert_empty @ui.error
+ end
+
+ def test_execute_missing_version
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:version] = Gem::Requirement.new '= 2'
+
+ gem 'foo', 1
+
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
@@ -130,9 +145,9 @@ class TestGemCommandsContentsCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|lib/foo\.rb|, @ui.output
- assert_match %r|lib/bar\.rb|, @ui.output
- assert_match %r|Rakefile|, @ui.output
+ assert_match %r{lib/foo\.rb}, @ui.output
+ assert_match %r{lib/bar\.rb}, @ui.output
+ assert_match %r{Rakefile}, @ui.output
assert_equal "", @ui.error
end
@@ -152,6 +167,23 @@ class TestGemCommandsContentsCommand < Gem::TestCase
assert_equal "", @ui.error
end
+ def test_execute_show_install_dir_latest_version
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:show_install_dir] = true
+
+ gem 'foo', 1
+ gem 'foo', 2
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = File.join @gemhome, 'gems', 'foo-2'
+
+ assert_equal "#{expected}\n", @ui.output
+ assert_equal "", @ui.error
+ end
+
def test_execute_show_install_dir_version
@cmd.options[:args] = %w[foo]
@cmd.options[:show_install_dir] = true
@@ -195,7 +227,7 @@ lib/foo.rb
nil, "default/gem.rb")
default_gem_spec.executables = ["default_command"]
default_gem_spec.files += ["default_gem.so"]
- install_default_specs(default_gem_spec)
+ install_default_gems(default_gem_spec)
@cmd.options[:args] = %w[default]
@@ -206,8 +238,8 @@ lib/foo.rb
expected = [
[RbConfig::CONFIG['bindir'], 'default_command'],
[RbConfig::CONFIG['rubylibdir'], 'default/gem.rb'],
- [RbConfig::CONFIG['archdir'], 'default_gem.so']
- ].sort.map{|a|File.join a}.join "\n"
+ [RbConfig::CONFIG['archdir'], 'default_gem.so'],
+ ].sort.map{|a|File.join a }.join "\n"
assert_equal expected, @ui.output.chomp
assert_equal "", @ui.error
@@ -235,5 +267,4 @@ lib/foo.rb
assert_equal Gem::Requirement.new('0.0.2'), @cmd.options[:version]
assert @cmd.options[:show_install_dir]
end
-
end
diff --git a/test/rubygems/test_gem_commands_dependency_command.rb b/test/rubygems/test_gem_commands_dependency_command.rb
index eaa9594163..13c7c065b5 100644
--- a/test/rubygems/test_gem_commands_dependency_command.rb
+++ b/test/rubygems/test_gem_commands_dependency_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/dependency_command'
class TestGemCommandsDependencyCommand < Gem::TestCase
-
def setup
super
@stub_ui = Gem::MockGemUi.new
@@ -65,7 +64,7 @@ Gem x-2
def test_execute_no_match
@cmd.options[:args] = %w[foo]
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @stub_ui do
@cmd.execute
end
@@ -156,7 +155,7 @@ Gem foo-2
@cmd.options[:reverse_dependencies] = true
@cmd.options[:domain] = :remote
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @stub_ui do
@cmd.execute
end
@@ -225,5 +224,4 @@ ERROR: Only reverse dependencies for local gems are supported.
assert_equal "Gem a-2.a\n\n", @stub_ui.output
assert_equal '', @stub_ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_environment_command.rb b/test/rubygems/test_gem_commands_environment_command.rb
index 5dd0fc7521..2bf80d8d85 100644
--- a/test/rubygems/test_gem_commands_environment_command.rb
+++ b/test/rubygems/test_gem_commands_environment_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/environment_command'
class TestGemCommandsEnvironmentCommand < Gem::TestCase
-
def setup
super
@@ -22,29 +21,29 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|RUBYGEMS VERSION: (\d\.)+\d|, @ui.output
- assert_match %r|RUBY VERSION: \d+\.\d+\.\d+ \(.*\) \[.*\]|, @ui.output
- assert_match %r|INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}|,
+ assert_match %r{RUBYGEMS VERSION: (\d\.)+\d}, @ui.output
+ assert_match %r{RUBY VERSION: \d+\.\d+\.\d+ \(.*\) \[.*\]}, @ui.output
+ assert_match %r{INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}},
@ui.output
- assert_match %r|RUBYGEMS PREFIX: |, @ui.output
- assert_match %r|RUBY EXECUTABLE:.*#{RbConfig::CONFIG['ruby_install_name']}|,
+ assert_match %r{RUBYGEMS PREFIX: }, @ui.output
+ assert_match %r{RUBY EXECUTABLE:.*#{RbConfig::CONFIG['ruby_install_name']}},
@ui.output
- assert_match %r|GIT EXECUTABLE: #{@cmd.send(:git_path)}|, @ui.output
- assert_match %r|SYSTEM CONFIGURATION DIRECTORY:|, @ui.output
- assert_match %r|EXECUTABLE DIRECTORY:|, @ui.output
- assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output
- assert_match %r|- #{Gem::Platform.local}|, @ui.output
- assert_match %r|GEM PATHS:|, @ui.output
- assert_match %r|- #{Regexp.escape @gemhome}|, @ui.output
- assert_match %r|GEM CONFIGURATION:|, @ui.output
- assert_match %r|"gemcutter_key" => "\*\*\*\*"|, @ui.output
- assert_match %r|:verbose => |, @ui.output
- assert_match %r|REMOTE SOURCES:|, @ui.output
-
- assert_match %r|- SHELL PATH:|, @ui.output
- assert_match %r|- /usr/local/bin$|, @ui.output
- assert_match %r|- /usr/bin$|, @ui.output
- assert_match %r|- /bin$|, @ui.output
+ assert_match %r{GIT EXECUTABLE: #{@cmd.send(:git_path)}}, @ui.output
+ assert_match %r{SYSTEM CONFIGURATION DIRECTORY:}, @ui.output
+ assert_match %r{EXECUTABLE DIRECTORY:}, @ui.output
+ assert_match %r{RUBYGEMS PLATFORMS:}, @ui.output
+ assert_match %r{- #{Gem::Platform.local}}, @ui.output
+ assert_match %r{GEM PATHS:}, @ui.output
+ assert_match %r{- #{Regexp.escape @gemhome}}, @ui.output
+ assert_match %r{GEM CONFIGURATION:}, @ui.output
+ assert_match %r{"gemcutter_key" => "\*\*\*\*"}, @ui.output
+ assert_match %r{:verbose => }, @ui.output
+ assert_match %r{REMOTE SOURCES:}, @ui.output
+
+ assert_match %r{- SHELL PATH:}, @ui.output
+ assert_match %r{- /usr/local/bin$}, @ui.output
+ assert_match %r{- /usr/bin$}, @ui.output
+ assert_match %r{- /bin$}, @ui.output
assert_empty @ui.error
@@ -110,7 +109,7 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
def test_execute_unknown
@cmd.send :handle_options, %w[unknown]
- assert_raises Gem::CommandLineError do
+ assert_raise Gem::CommandLineError do
use_ui @ui do
@cmd.execute
end
@@ -141,5 +140,4 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
assert_equal "#{Gem.platforms.join File::PATH_SEPARATOR}\n", @ui.output
assert_equal '', @ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_fetch_command.rb b/test/rubygems/test_gem_commands_fetch_command.rb
index 9989f57bd7..c745648d56 100644
--- a/test/rubygems/test_gem_commands_fetch_command.rb
+++ b/test/rubygems/test_gem_commands_fetch_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/package'
require 'rubygems/security'
require 'rubygems/commands/fetch_command'
class TestGemCommandsFetchCommand < Gem::TestCase
-
def setup
super
@@ -17,7 +16,7 @@ class TestGemCommandsFetchCommand < Gem::TestCase
fetcher.gem 'a', 2
end
- refute_path_exists File.join(@tempdir, 'cache'), 'sanity check'
+ assert_path_not_exist File.join(@tempdir, 'cache'), 'sanity check'
@cmd.options[:args] = %w[a]
@@ -29,9 +28,9 @@ class TestGemCommandsFetchCommand < Gem::TestCase
a2 = specs['a-2']
- assert_path_exists(File.join(@tempdir, a2.file_name),
+ assert_path_exist(File.join(@tempdir, a2.file_name),
"#{a2.full_name} not fetched")
- refute_path_exists File.join(@tempdir, 'cache'),
+ assert_path_not_exist File.join(@tempdir, 'cache'),
'gem repository directories must not be created'
end
@@ -41,7 +40,7 @@ class TestGemCommandsFetchCommand < Gem::TestCase
fetcher.gem 'a', 2
end
- refute_path_exists File.join(@tempdir, 'cache'), 'sanity check'
+ assert_path_not_exist File.join(@tempdir, 'cache'), 'sanity check'
@cmd.options[:args] = %w[a]
@cmd.options[:version] = req('>= 0.1')
@@ -53,9 +52,9 @@ class TestGemCommandsFetchCommand < Gem::TestCase
end
a2 = specs['a-2']
- assert_path_exists(File.join(@tempdir, a2.file_name),
+ assert_path_exist(File.join(@tempdir, a2.file_name),
"#{a2.full_name} not fetched")
- refute_path_exists File.join(@tempdir, 'cache'),
+ assert_path_not_exist File.join(@tempdir, 'cache'),
'gem repository directories must not be created'
end
@@ -76,10 +75,46 @@ class TestGemCommandsFetchCommand < Gem::TestCase
a2 = specs['a-2']
- assert_path_exists(File.join(@tempdir, a2.file_name),
+ assert_path_exist(File.join(@tempdir, a2.file_name),
"#{a2.full_name} not fetched")
end
+ def test_execute_platform
+ a2_spec, a2 = util_gem("a", "2")
+
+ a2_universal_darwin_spec, a2_universal_darwin = util_gem("a", "2") do |s|
+ s.platform = 'universal-darwin'
+ end
+
+ Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new
+
+ write_marshalled_gemspecs(a2_spec, a2_universal_darwin_spec)
+
+ @cmd.options[:args] = %w[a]
+
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = util_gzip(Marshal.dump([
+ Gem::NameTuple.new(a2_spec.name, a2_spec.version, a2_spec.platform),
+ Gem::NameTuple.new(a2_universal_darwin_spec.name, a2_universal_darwin_spec.version, a2_universal_darwin_spec.platform),
+ ]))
+
+ @fetcher.data["#{@gem_repo}gems/#{a2_spec.file_name}"] = Gem.read_binary(a2)
+ FileUtils.cp a2, a2_spec.cache_file
+
+ @fetcher.data["#{@gem_repo}gems/#{a2_universal_darwin_spec.file_name}"] = Gem.read_binary(a2_universal_darwin)
+ FileUtils.cp a2_universal_darwin, a2_universal_darwin_spec.cache_file
+
+ util_set_arch 'arm64-darwin20' do
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ @cmd.execute
+ end
+ end
+ end
+
+ assert_path_exist(File.join(@tempdir, a2_universal_darwin_spec.file_name),
+ "#{a2_universal_darwin_spec.full_name} not fetched")
+ end
+
def test_execute_specific_prerelease
specs = spec_fetcher do |fetcher|
fetcher.gem 'a', 2
@@ -98,7 +133,7 @@ class TestGemCommandsFetchCommand < Gem::TestCase
a2_pre = specs['a-2.a']
- assert_path_exists(File.join(@tempdir, a2_pre.file_name),
+ assert_path_exist(File.join(@tempdir, a2_pre.file_name),
"#{a2_pre.full_name} not fetched")
end
@@ -119,8 +154,7 @@ class TestGemCommandsFetchCommand < Gem::TestCase
a1 = specs['a-1']
- assert_path_exists(File.join(@tempdir, a1.file_name),
+ assert_path_exist(File.join(@tempdir, a1.file_name),
"#{a1.full_name} not fetched")
end
-
end
diff --git a/test/rubygems/test_gem_commands_generate_index_command.rb b/test/rubygems/test_gem_commands_generate_index_command.rb
index d8fda32fc0..5b7b37a446 100644
--- a/test/rubygems/test_gem_commands_generate_index_command.rb
+++ b/test/rubygems/test_gem_commands_generate_index_command.rb
@@ -1,14 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/indexer'
require 'rubygems/commands/generate_index_command'
-unless defined?(Builder::XChar)
- warn "generate_index tests are being skipped. Install builder gem."
-end
-
class TestGemCommandsGenerateIndexCommand < Gem::TestCase
-
def setup
super
@@ -82,5 +77,4 @@ class TestGemCommandsGenerateIndexCommand < Gem::TestCase
"WARNING: The \"--no-modern\" option has been deprecated and will be removed in Rubygems 4.0. The `--no-modern` option is currently ignored. Modern indexes (specs, latest_specs, and prerelease_specs) are always generated.\n",
@ui.error
end
-
-end if defined?(Builder::XChar)
+end
diff --git a/test/rubygems/test_gem_commands_help_command.rb b/test/rubygems/test_gem_commands_help_command.rb
index f2a519775c..a70dd770e1 100644
--- a/test/rubygems/test_gem_commands_help_command.rb
+++ b/test/rubygems/test_gem_commands_help_command.rb
@@ -1,12 +1,11 @@
# frozen_string_literal: true
require "rubygems"
-require "rubygems/test_case"
+require_relative "helper"
require "rubygems/commands/help_command"
require "rubygems/package"
require "rubygems/command_manager"
class TestGemCommandsHelpCommand < Gem::TestCase
-
def setup
super
@@ -36,18 +35,38 @@ class TestGemCommandsHelpCommand < Gem::TestCase
end
end
+ def test_gem_help_build
+ util_gem 'build' do |out, err|
+ assert_match(/-C PATH *Run as if gem build was started in <PATH>/, out)
+ assert_equal '', err
+ end
+ end
+
def test_gem_help_commands
mgr = Gem::CommandManager.new
util_gem 'commands' do |out, err|
mgr.command_names.each do |cmd|
- assert_match(/\s+#{cmd}\s+\S+/, out)
+ unless mgr[cmd].deprecated?
+ assert_match(/\s+#{cmd}\s+\S+/, out)
+ end
end
- if defined?(OpenSSL::SSL)
+ if Gem::HAVE_OPENSSL
assert_empty err
- refute_match 'No command found for ', out
+ refute_match %r{No command found for }, out
+ end
+ end
+ end
+
+ def test_gem_help_commands_omits_deprecated_commands
+ mgr = Gem::CommandManager.new
+
+ util_gem 'commands' do |out, err|
+ deprecated_commands = mgr.command_names.select {|cmd| mgr[cmd].deprecated? }
+ deprecated_commands.each do |cmd|
+ refute_match(/\A\s+#{cmd}\s+\S+\z/, out)
end
end
end
@@ -71,5 +90,4 @@ class TestGemCommandsHelpCommand < Gem::TestCase
yield @ui.output, @ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_info_command.rb b/test/rubygems/test_gem_commands_info_command.rb
index 373fccceee..462075f98c 100644
--- a/test/rubygems/test_gem_commands_info_command.rb
+++ b/test/rubygems/test_gem_commands_info_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/info_command'
class TestGemCommandsInfoCommand < Gem::TestCase
-
def setup
super
@@ -33,13 +32,12 @@ class TestGemCommandsInfoCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r%#{@gem.name} \(#{@gem.version}\)\n%, @ui.output
- assert_match %r%Authors: #{@gem.authors.join(', ')}\n%, @ui.output
- assert_match %r%Homepage: #{@gem.homepage}\n%, @ui.output
- assert_match %r%License: #{@gem.license}\n%, @ui.output
- assert_match %r%Installed at: #{@gem.base_dir}\n%, @ui.output
- assert_match %r%#{@gem.summary}\n%, @ui.output
+ assert_match %r{#{@gem.name} \(#{@gem.version}\)\n}, @ui.output
+ assert_match %r{Authors: #{@gem.authors.join(', ')}\n}, @ui.output
+ assert_match %r{Homepage: #{@gem.homepage}\n}, @ui.output
+ assert_match %r{License: #{@gem.license}\n}, @ui.output
+ assert_match %r{Installed at: #{@gem.base_dir}\n}, @ui.output
+ assert_match %r{#{@gem.summary}\n}, @ui.output
assert_match "", @ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb
index a233377c4a..535180983b 100644
--- a/test/rubygems/test_gem_commands_install_command.rb
+++ b/test/rubygems/test_gem_commands_install_command.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/install_command'
require 'rubygems/request_set'
require 'rubygems/rdoc'
class TestGemCommandsInstallCommand < Gem::TestCase
-
def setup
super
common_installer_setup
@@ -38,12 +37,12 @@ class TestGemCommandsInstallCommand < Gem::TestCase
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
end
def test_execute_explicit_version_includes_prerelease
@@ -60,12 +59,12 @@ class TestGemCommandsInstallCommand < Gem::TestCase
assert @cmd.options[:version].satisfied_by?(a2_pre.version)
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-2.a], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2.a], @cmd.installed_specs.map {|spec| spec.full_name }
end
def test_execute_local
@@ -83,7 +82,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase
orig_dir = Dir.pwd
begin
Dir.chdir @tempdir
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
ensure
@@ -91,7 +90,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "1 gem installed", @ui.output
end
@@ -111,7 +110,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase
orig_dir = Dir.pwd
begin
Dir.chdir @tempdir
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
assert_equal 2, e.exit_code
@@ -143,7 +142,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
orig_dir = Dir.pwd
begin
Dir.chdir orig_dir
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
ensure
@@ -174,7 +173,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
begin
Dir.chdir @tempdir
FileUtils.rm_r [@gemhome, "gems"]
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
ensure
@@ -182,14 +181,14 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
end
end
- assert_equal %w[a-2 b-2.a c-3], @cmd.installed_specs.map { |spec| spec.full_name }.sort
+ assert_equal %w[a-2 b-2.a c-3], @cmd.installed_specs.map {|spec| spec.full_name }.sort
assert_match "3 gems installed", @ui.output
end
def test_execute_no_user_install
- skip 'skipped on MS Windows (chmod has no effect)' if win_platform?
- skip 'skipped in root privilege' if Process.uid.zero?
+ pend 'skipped on MS Windows (chmod has no effect)' if win_platform?
+ pend 'skipped in root privilege' if Process.uid.zero?
specs = spec_fetcher do |fetcher|
fetcher.gem 'a', 2
@@ -208,7 +207,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
FileUtils.chmod 0555, @gemhome
Dir.chdir @tempdir
- assert_raises Gem::FilePermissionError do
+ assert_raise Gem::FilePermissionError do
@cmd.execute
end
ensure
@@ -226,7 +225,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
@cmd.options[:args] = %w[no_such_gem]
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
assert_equal 2, e.exit_code
@@ -245,7 +244,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
@cmd.options[:args] = %w[no_such_gem]
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
assert_equal 2, e.exit_code
@@ -258,7 +257,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
def test_execute_no_gem
@cmd.options[:args] = %w[]
- assert_raises Gem::CommandLineError do
+ assert_raise Gem::CommandLineError do
@cmd.execute
end
end
@@ -269,7 +268,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
@cmd.options[:args] = %w[nonexistent]
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
assert_equal 2, e.exit_code
@@ -286,7 +285,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
@cmd.options[:args] = ['foo']
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
@@ -302,7 +301,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
def test_execute_http_proxy
use_ui @ui do
- e = assert_raises ArgumentError, @ui.error do
+ e = assert_raise ArgumentError, @ui.error do
@cmd.handle_options %w[-p=foo.bar.com]
end
@@ -328,7 +327,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
@cmd.options[:args] = %w[nonexistent]
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
assert_equal 2, e.exit_code
@@ -337,7 +336,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
errs = @ui.error.split("\n")
assert_match(/ould not find a valid gem 'nonexistent'/, errs.shift)
- assert_match(%r!Unable to download data from http://not-there.nothing!, errs.shift)
+ assert_match(%r{Unable to download data from http://not-there.nothing}, errs.shift)
end
def test_execute_nonexistent_hint_disabled
@@ -352,7 +351,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
@cmd.options[:suggest_alternate] = false
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
@@ -377,7 +376,7 @@ ERROR: Could not find a valid gem 'nonexistent_with_hint' (>= 0) in any reposit
@cmd.options[:args] = [misspelled]
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
@@ -402,7 +401,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = [misspelled]
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
@@ -411,7 +410,7 @@ ERROR: Possible alternatives: non_existent_with_hint
expected = [
"ERROR: Could not find a valid gem 'non-existent_with-hint' (>= 0) in any repository",
- "ERROR: Possible alternatives: nonexistent-with_hint"
+ "ERROR: Possible alternatives: nonexistent-with_hint",
]
output = @ui.error.split "\n"
@@ -424,7 +423,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:install_dir] = "whatever"
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -444,12 +443,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-1], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name }
end
def test_execute_prerelease_wins_over_previous_ver
@@ -462,12 +461,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-2.a], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2.a], @cmd.installed_specs.map {|spec| spec.full_name }
end
def test_execute_with_version_specified_by_colon
@@ -479,12 +478,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a:1]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-1], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name }
end
def test_execute_prerelease_skipped_when_non_pre_available
@@ -497,12 +496,143 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ end
+
+ def test_execute_required_ruby_version
+ next_ruby = Gem.ruby_version.segments.map.with_index{|n, i| i == 1 ? n + 1 : n }.join(".")
+
+ local = Gem::Platform.local
+ spec_fetcher do |fetcher|
+ fetcher.download 'a', 2
+ fetcher.download 'a', 2 do |s|
+ s.required_ruby_version = "< #{RUBY_VERSION}.a"
+ s.platform = local
+ end
+ fetcher.download 'a', 3 do |s|
+ s.required_ruby_version = ">= #{next_ruby}"
+ end
+ fetcher.download 'a', 3 do |s|
+ s.required_ruby_version = ">= #{next_ruby}"
+ s.platform = local
+ end
+ end
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
+ @cmd.execute
+ end
+ end
+
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ end
+
+ def test_execute_required_ruby_version_upper_bound
+ local = Gem::Platform.local
+ spec_fetcher do |fetcher|
+ fetcher.gem 'a', 2.0
+ fetcher.gem 'a', 2.0 do |s|
+ s.required_ruby_version = "< #{RUBY_VERSION}.a"
+ s.platform = local
+ end
+ end
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
+ @cmd.execute
+ end
+ end
+
+ assert_equal %w[a-2.0], @cmd.installed_specs.map {|spec| spec.full_name }
+ end
+
+ def test_execute_required_ruby_version_specific_not_met
+ spec_fetcher do |fetcher|
+ fetcher.gem 'a', '1.0' do |s|
+ s.required_ruby_version = '= 1.4.6'
+ end
+ end
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError do
+ @cmd.execute
+ end
+ end
+
+ errs = @ui.error.split("\n")
+ assert_equal "ERROR: Error installing a:", errs.shift
+ assert_equal "\ta-1.0 requires Ruby version = 1.4.6. The current ruby version is #{Gem.ruby_version}.", errs.shift
+ end
+
+ def test_execute_required_ruby_version_specific_prerelease_met
+ spec_fetcher do |fetcher|
+ fetcher.gem 'a', '1.0' do |s|
+ s.required_ruby_version = '>= 1.4.6.preview2'
+ end
+ end
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
+ @cmd.execute
+ end
+ end
+
+ assert_equal %w[a-1.0], @cmd.installed_specs.map {|spec| spec.full_name }
+ end
+
+ def test_execute_required_ruby_version_specific_prerelease_not_met
+ next_ruby_pre = Gem.ruby_version.segments.map.with_index{|n, i| i == 1 ? n + 1 : n }.join(".") + ".a"
+
+ spec_fetcher do |fetcher|
+ fetcher.gem 'a', '1.0' do |s|
+ s.required_ruby_version = "> #{next_ruby_pre}"
+ end
+ end
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError do
+ @cmd.execute
+ end
+ end
+
+ errs = @ui.error.split("\n")
+ assert_equal "ERROR: Error installing a:", errs.shift
+ assert_equal "\ta-1.0 requires Ruby version > #{next_ruby_pre}. The current ruby version is #{Gem.ruby_version}.", errs.shift
+ end
+
+ def test_execute_required_rubygems_version_wrong
+ spec_fetcher do |fetcher|
+ fetcher.gem 'a', '1.0' do |s|
+ s.required_rubygems_version = '< 0'
+ end
+ end
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError do
+ @cmd.execute
+ end
+ end
+
+ errs = @ui.error.split("\n")
+ assert_equal "ERROR: Error installing a:", errs.shift
+ assert_equal "\ta-1.0 requires RubyGems version < 0. The current RubyGems version is #{Gem.rubygems_version}. Try 'gem update --system' to update RubyGems itself.", errs.shift
end
def test_execute_rdoc
@@ -527,7 +657,7 @@ ERROR: Possible alternatives: non_existent_with_hint
begin
Dir.chdir @tempdir
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
ensure
@@ -537,8 +667,8 @@ ERROR: Possible alternatives: non_existent_with_hint
wait_for_child_process_to_exit
- assert_path_exists File.join(a2.doc_dir, 'ri')
- assert_path_exists File.join(a2.doc_dir, 'rdoc')
+ assert_path_exist File.join(a2.doc_dir, 'ri')
+ assert_path_exist File.join(a2.doc_dir, 'rdoc')
end
def test_execute_rdoc_with_path
@@ -564,7 +694,7 @@ ERROR: Possible alternatives: non_existent_with_hint
begin
Dir.chdir @tempdir
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
ensure
@@ -574,7 +704,7 @@ ERROR: Possible alternatives: non_existent_with_hint
wait_for_child_process_to_exit
- assert_path_exists 'whatever/doc/a-2', 'documentation not installed'
+ assert_path_exist 'whatever/doc/a-2', 'documentation not installed'
end
def test_execute_saves_build_args
@@ -582,7 +712,7 @@ ERROR: Possible alternatives: non_existent_with_hint
fetcher.gem 'a', 2
end
- args = %w!--with-awesome=true --more-awesome=yes!
+ args = %w[--with-awesome=true --more-awesome=yes]
Gem::Command.build_args = args
@@ -600,7 +730,7 @@ ERROR: Possible alternatives: non_existent_with_hint
begin
Dir.chdir @tempdir
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
ensure
@@ -609,7 +739,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
path = a2.build_info_file
- assert_path_exists path
+ assert_path_exist path
assert_equal args, a2.build_args
end
@@ -622,12 +752,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "1 gem installed", @ui.output
end
@@ -642,12 +772,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "1 gem installed", @ui.output
end
@@ -682,13 +812,13 @@ ERROR: Possible alternatives: non_existent_with_hint
use_ui @ui do
Dir.chdir @tempdir do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
end
- assert_equal %w[a-1], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "1 gem installed", @ui.output
@@ -714,7 +844,7 @@ ERROR: Possible alternatives: non_existent_with_hint
orig_dir = Dir.pwd
begin
Dir.chdir @tempdir
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
ensure
@@ -722,7 +852,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2 b-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2 b-2], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "2 gems installed", @ui.output
end
@@ -732,7 +862,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:version] = Gem::Requirement.new("> 1")
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
@@ -759,12 +889,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a:1 b:1]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-1 b-1], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-1 b-1], @cmd.installed_specs.map {|spec| spec.full_name }
end
def test_execute_conservative
@@ -782,7 +912,7 @@ ERROR: Possible alternatives: non_existent_with_hint
orig_dir = Dir.pwd
begin
Dir.chdir @tempdir
- assert_raises Gem::MockGemUi::SystemExitException do
+ assert_raise Gem::MockGemUi::SystemExitException do
@cmd.execute
end
ensure
@@ -790,7 +920,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[b-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[b-2], @cmd.installed_specs.map {|spec| spec.full_name }
assert_equal "", @ui.error
assert_match "1 gem installed", @ui.output
@@ -812,7 +942,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.install_gem 'a', '>= 0'
- assert_equal %w[a-2], @cmd.installed_specs.map { |s| s.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|s| s.full_name }
assert done_installing, 'documentation was not generated'
end
@@ -826,7 +956,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.install_gem 'a', '>= 0'
- assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
end
def test_install_gem_ignore_dependencies_remote_platform_local
@@ -843,7 +973,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.install_gem 'a', '>= 0'
- assert_equal %W[a-3-#{local}], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %W[a-3-#{local}], @cmd.installed_specs.map {|spec| spec.full_name }
end
def test_install_gem_ignore_dependencies_specific_file
@@ -857,7 +987,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.install_gem File.join(@tempdir, spec.file_name), nil
- assert_equal %w[a-2], @cmd.installed_specs.map { |s| s.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|s| s.full_name }
end
def test_parses_requirement_from_gemname
@@ -877,7 +1007,7 @@ ERROR: Possible alternatives: non_existent_with_hint
orig_dir = Dir.pwd
begin
Dir.chdir @tempdir
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
ensure
@@ -886,7 +1016,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
assert_equal 2, e.exit_code
- assert_match %r!Could not find a valid gem 'a' \(= 10.0\)!, @ui.error
+ assert_match %r{Could not find a valid gem 'a' \(= 10.0\)}, @ui.error
end
def test_show_errors_on_failure
@@ -899,7 +1029,7 @@ ERROR: Possible alternatives: non_existent_with_hint
orig_dir = Dir.pwd
begin
Dir.chdir @tempdir
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
ensure
@@ -922,12 +1052,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "1 gem installed", @ui.output
@@ -937,6 +1067,31 @@ ERROR: Possible alternatives: non_existent_with_hint
assert_equal x, e
end
+ def test_redact_credentials_from_uri_on_warning
+ spec_fetcher do |fetcher|
+ fetcher.download 'a', 2
+ end
+
+ Gem.sources << "http://username:SECURE_TOKEN@nonexistent.example"
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
+ @cmd.execute
+ end
+ end
+
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+
+ assert_match "1 gem installed", @ui.output
+
+ e = @ui.error
+
+ x = "WARNING: Unable to pull data from 'http://username:REDACTED@nonexistent.example': no data for http://username:REDACTED@nonexistent.example/specs.4.8.gz (http://username:REDACTED@nonexistent.example/specs.4.8.gz)\n"
+ assert_equal x, e
+ end
+
def test_execute_uses_from_a_gemdeps
spec_fetcher do |fetcher|
fetcher.gem 'a', 2
@@ -949,12 +1104,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:gemdeps] = @gemdeps
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "Using a (2)", @ui.output
assert File.exist?("#{@gemdeps}.lock")
@@ -973,12 +1128,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:gemdeps] = @gemdeps
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "Using a (2)", @ui.output
assert !File.exist?("#{@gemdeps}.lock")
@@ -998,12 +1153,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:gemdeps] = @gemdeps
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "Using a (1)", @ui.output
end
@@ -1020,12 +1175,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:gemdeps] = @gemdeps
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map { |spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
assert_match "Installing a (2)", @ui.output
end
@@ -1043,12 +1198,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:gemdeps] = @gemdeps
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- names = @cmd.installed_specs.map { |spec| spec.full_name }
+ names = @cmd.installed_specs.map {|spec| spec.full_name }
assert_equal %w[q-1.0 r-2.0], names
@@ -1070,12 +1225,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:gemdeps] = @gemdeps
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- names = @cmd.installed_specs.map { |spec| spec.full_name }
+ names = @cmd.installed_specs.map {|spec| spec.full_name }
assert_equal %w[r-2.0], names
@@ -1097,12 +1252,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:gemdeps] = @gemdeps
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- names = @cmd.installed_specs.map { |spec| spec.full_name }
+ names = @cmd.installed_specs.map {|spec| spec.full_name }
assert_equal %w[q-1.0 r-2.0], names
@@ -1129,12 +1284,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:gemdeps] = @gemdeps
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- names = @cmd.installed_specs.map { |spec| spec.full_name }
+ names = @cmd.installed_specs.map {|spec| spec.full_name }
assert_equal %w[q-1.0 r-2.0], names
@@ -1164,12 +1319,12 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:gemdeps] = @gemdeps
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
- names = @cmd.installed_specs.map { |spec| spec.full_name }
+ names = @cmd.installed_specs.map {|spec| spec.full_name }
assert_equal %w[r-2.0], names
@@ -1249,7 +1404,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
@@ -1276,7 +1431,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
@@ -1305,7 +1460,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
@@ -1335,7 +1490,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = %w[a]
use_ui @ui do
- assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
end
@@ -1346,5 +1501,4 @@ ERROR: Possible alternatives: non_existent_with_hint
assert_equal " a-3", out.shift
assert_empty out
end
-
end
diff --git a/test/rubygems/test_gem_commands_list_command.rb b/test/rubygems/test_gem_commands_list_command.rb
index a44ccb4175..d8cffce7a3 100644
--- a/test/rubygems/test_gem_commands_list_command.rb
+++ b/test/rubygems/test_gem_commands_list_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/list_command'
class TestGemCommandsListCommand < Gem::TestCase
-
def setup
super
@@ -21,7 +20,7 @@ class TestGemCommandsListCommand < Gem::TestCase
def test_execute_installed
@cmd.handle_options %w[c --installed]
- assert_raises Gem::MockGemUi::SystemExitException do
+ assert_raise Gem::MockGemUi::SystemExitException do
use_ui @ui do
@cmd.execute
end
@@ -30,5 +29,4 @@ class TestGemCommandsListCommand < Gem::TestCase
assert_equal "true\n", @ui.output
assert_equal '', @ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_lock_command.rb b/test/rubygems/test_gem_commands_lock_command.rb
index a35ed081cb..f8afca1e29 100644
--- a/test/rubygems/test_gem_commands_lock_command.rb
+++ b/test/rubygems/test_gem_commands_lock_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/lock_command'
class TestGemCommandsLockCommand < Gem::TestCase
-
def setup
super
@@ -56,7 +55,7 @@ gem 'd', '= 1'
def test_execute_strict
@cmd.handle_options %w[c-1 --strict]
- e = assert_raises Gem::Exception do
+ e = assert_raise Gem::Exception do
use_ui @ui do
@cmd.execute
end
@@ -64,5 +63,4 @@ gem 'd', '= 1'
assert_equal 'Could not find gem c-1, try using the full name', e.message
end
-
end
diff --git a/test/rubygems/test_gem_commands_mirror.rb b/test/rubygems/test_gem_commands_mirror.rb
index 07ec9f3d0c..470f1c30fa 100644
--- a/test/rubygems/test_gem_commands_mirror.rb
+++ b/test/rubygems/test_gem_commands_mirror.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/mirror_command'
class TestGemCommandsMirrorCommand < Gem::TestCase
-
def setup
super
@@ -15,7 +14,6 @@ class TestGemCommandsMirrorCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r%Install the rubygems-mirror%i, @ui.error
+ assert_match %r{Install the rubygems-mirror}i, @ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_open_command.rb b/test/rubygems/test_gem_commands_open_command.rb
index e73a138204..8447f7ea35 100644
--- a/test/rubygems/test_gem_commands_open_command.rb
+++ b/test/rubygems/test_gem_commands_open_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/open_command'
class TestGemCommandsOpenCommand < Gem::TestCase
-
def setup
super
@@ -26,16 +25,15 @@ class TestGemCommandsOpenCommand < Gem::TestCase
gem 'foo', '1.0.0'
spec = gem 'foo', '1.0.1'
- mock = MiniTest::Mock.new
- mock.expect(:call, true, [spec.full_gem_path])
- Dir.stub(:chdir, mock) do
- use_ui @ui do
- @cmd.execute
+ assert_nothing_raised Gem::MockGemUi::TermError do
+ Dir.stub(:chdir, spec.full_gem_path) do
+ use_ui @ui do
+ @cmd.execute
+ end
end
end
- assert mock.verify
assert_equal "", @ui.error
end
@@ -45,26 +43,26 @@ class TestGemCommandsOpenCommand < Gem::TestCase
gem "foo", "5.0"
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
end
- assert_match %r|Unable to find gem 'foo'|, @ui.output
+ assert_match %r{Unable to find gem 'foo'}, @ui.output
assert_equal "", @ui.error
end
def test_execute_bad_gem
@cmd.options[:args] = %w[foo]
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
end
- assert_match %r|Unable to find gem 'foo'|, @ui.output
+ assert_match %r{Unable to find gem 'foo'}, @ui.output
assert_equal "", @ui.error
end
@@ -87,14 +85,13 @@ class TestGemCommandsOpenCommand < Gem::TestCase
gem("foo", "1.0")
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
end
- assert_match %r|'foo' is a default gem and can't be opened\.| , @ui.output
+ assert_match %r{'foo' is a default gem and can't be opened\.} , @ui.output
assert_equal "", @ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_outdated_command.rb b/test/rubygems/test_gem_commands_outdated_command.rb
index 3c37e22a09..dc5c40a782 100644
--- a/test/rubygems/test_gem_commands_outdated_command.rb
+++ b/test/rubygems/test_gem_commands_outdated_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/outdated_command'
class TestGemCommandsOutdatedCommand < Gem::TestCase
-
def setup
super
@@ -30,4 +29,21 @@ class TestGemCommandsOutdatedCommand < Gem::TestCase
assert_equal "", @ui.error
end
+ def test_execute_with_up_to_date_platform_specific_gem
+ spec_fetcher do |fetcher|
+ fetcher.download 'foo', '2.0'
+
+ fetcher.gem 'foo', '1.0'
+ fetcher.gem 'foo', '2.0' do |s|
+ s.platform = Gem::Platform.local
+ end
+ end
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
+ end
end
diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb
index 799d631f8a..5b06b628c2 100644
--- a/test/rubygems/test_gem_commands_owner_command.rb
+++ b/test/rubygems/test_gem_commands_owner_command.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/owner_command'
class TestGemCommandsOwnerCommand < Gem::TestCase
-
def setup
super
+ credential_setup
+
ENV["RUBYGEMS_HOST"] = nil
@stub_ui = Gem::MockGemUi.new
@stub_fetcher = Gem::FakeFetcher.new
@@ -17,6 +18,12 @@ class TestGemCommandsOwnerCommand < Gem::TestCase
@cmd = Gem::Commands::OwnerCommand.new
end
+ def teardown
+ credential_teardown
+
+ super
+ end
+
def test_show_owners
response = <<EOF
---
@@ -46,7 +53,7 @@ EOF
end
def test_show_owners_dont_load_objects
- skip "testing a psych-only API" unless defined?(::Psych::DisallowedClass)
+ pend "testing a psych-only API" unless defined?(::Psych::DisallowedClass)
response = <<EOF
---
@@ -61,7 +68,7 @@ EOF
@stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
- assert_raises Psych::DisallowedClass do
+ assert_raise Psych::DisallowedClass do
use_ui @ui do
@cmd.show_owners("freewill")
end
@@ -102,7 +109,7 @@ EOF
response = "You don't have permission to push to this gem"
@stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 403, 'Forbidden']
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @stub_ui do
@cmd.show_owners("freewill")
end
@@ -119,7 +126,7 @@ EOF
end
Gem.configuration.load_api_keys
- @cmd.handle_options %w(-k other)
+ @cmd.handle_options %w[-k other]
@cmd.show_owners('freewill')
assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization']
@@ -177,7 +184,7 @@ EOF
end
Gem.configuration.load_api_keys
- @cmd.handle_options %w(-k other)
+ @cmd.handle_options %w[-k other]
@cmd.add_owners('freewill', ['user-new1@example.com'])
assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization']
@@ -217,7 +224,7 @@ EOF
end
Gem.configuration.load_api_keys
- @cmd.handle_options %w(-k other)
+ @cmd.handle_options %w[-k other]
@cmd.remove_owners('freewill', ['user-remove1@example.com'])
assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization']
@@ -240,7 +247,7 @@ EOF
@stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
[response_fail, 401, 'Unauthorized'],
- [response_success, 200, 'OK']
+ [response_success, 200, 'OK'],
]
@otp_ui = Gem::MockGemUi.new "111111\n"
@@ -269,4 +276,51 @@ EOF
assert_equal '111111', @stub_fetcher.last_request['OTP']
end
+ def test_remove_owners_unathorized_api_key
+ response_forbidden = "The API key doesn't have access"
+ response_success = "Owner removed successfully."
+
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
+ [response_forbidden, 403, 'Forbidden'],
+ [response_success, 200, "OK"],
+ ]
+ @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"]
+ @cmd.instance_variable_set :@scope, :remove_owner
+
+ @stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n"
+ use_ui @stub_ui do
+ @cmd.remove_owners("freewill", ["some@example"])
+ end
+
+ access_notice = "The existing key doesn't have access of remove_owner on RubyGems.org. Please sign in to update access."
+ assert_match access_notice, @stub_ui.output
+ assert_match "Email:", @stub_ui.output
+ assert_match "Password:", @stub_ui.output
+ assert_match "Added remove_owner scope to the existing API key", @stub_ui.output
+ assert_match response_success, @stub_ui.output
+ end
+
+ def test_add_owners_unathorized_api_key
+ response_forbidden = "The API key doesn't have access"
+ response_success = "Owner added successfully."
+
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
+ [response_forbidden, 403, 'Forbidden'],
+ [response_success, 200, "OK"],
+ ]
+ @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"]
+ @cmd.instance_variable_set :@scope, :add_owner
+
+ @stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n"
+ use_ui @stub_ui do
+ @cmd.add_owners("freewill", ["some@example"])
+ end
+
+ access_notice = "The existing key doesn't have access of add_owner on RubyGems.org. Please sign in to update access."
+ assert_match access_notice, @stub_ui.output
+ assert_match "Email:", @stub_ui.output
+ assert_match "Password:", @stub_ui.output
+ assert_match "Added add_owner scope to the existing API key", @stub_ui.output
+ assert_match response_success, @stub_ui.output
+ end
end
diff --git a/test/rubygems/test_gem_commands_pristine_command.rb b/test/rubygems/test_gem_commands_pristine_command.rb
index e872a80957..f4000f4657 100644
--- a/test/rubygems/test_gem_commands_pristine_command.rb
+++ b/test/rubygems/test_gem_commands_pristine_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/pristine_command'
class TestGemCommandsPristineCommand < Gem::TestCase
-
def setup
super
common_installer_setup
@@ -156,15 +155,13 @@ class TestGemCommandsPristineCommand < Gem::TestCase
@cmd.execute
end
- assert_path_exists gem_exec
+ assert_path_exist gem_exec
ruby_exec = sprintf Gem.default_exec_format, 'ruby'
- if win_platform?
- assert_match %r%\A#!\s*#{ruby_exec}%, File.read(gem_exec)
- else
- assert_match %r%\A#!\s*/usr/bin/env #{ruby_exec}%, File.read(gem_exec)
- end
+ bin_env = win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " "
+
+ assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(gem_exec)
end
def test_execute_extensions_explicit
@@ -215,7 +212,6 @@ class TestGemCommandsPristineCommand < Gem::TestCase
io.write "# extconf.rb\nrequire 'mkmf'; create_makefile 'a'"
end
- util_build_gem a
install_gem a
@cmd.options[:args] = %w[a]
@@ -249,7 +245,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase
RUBY
end
- build_args = %w!--with-awesome=true --sweet!
+ build_args = %w[--with-awesome=true --sweet]
install_gem a, :build_args => build_args
@@ -360,10 +356,10 @@ class TestGemCommandsPristineCommand < Gem::TestCase
assert_equal "Restored #{b.full_name}", out.shift
assert_empty out, out.inspect
- assert_path_exists File.join(@gemhome, "gems", 'a-2')
- refute_path_exists File.join(gemhome2, "gems", 'a-2')
- assert_path_exists File.join(gemhome2, "gems", 'b-2')
- refute_path_exists File.join(@gemhome, "gems", 'b-2')
+ assert_path_exist File.join(@gemhome, "gems", 'a-2')
+ assert_path_not_exist File.join(gemhome2, "gems", 'a-2')
+ assert_path_exist File.join(gemhome2, "gems", 'b-2')
+ assert_path_not_exist File.join(@gemhome, "gems", 'b-2')
end
def test_execute_missing_cache_gem
@@ -438,27 +434,27 @@ class TestGemCommandsPristineCommand < Gem::TestCase
assert_empty out, out.inspect
assert_empty @ui.error
- assert_path_exists File.join(@gemhome, "cache", 'a-1.gem')
- refute_path_exists File.join(gemhome2, "cache", 'a-2.gem')
- assert_path_exists File.join(@gemhome, "gems", 'a-1')
- refute_path_exists File.join(gemhome2, "gems", 'a-1')
+ assert_path_exist File.join(@gemhome, "cache", 'a-1.gem')
+ assert_path_not_exist File.join(gemhome2, "cache", 'a-2.gem')
+ assert_path_exist File.join(@gemhome, "gems", 'a-1')
+ assert_path_not_exist File.join(gemhome2, "gems", 'a-1')
- assert_path_exists File.join(gemhome2, "cache", 'b-1.gem')
- refute_path_exists File.join(@gemhome, "cache", 'b-2.gem')
- assert_path_exists File.join(gemhome2, "gems", 'b-1')
- refute_path_exists File.join(@gemhome, "gems", 'b-1')
+ assert_path_exist File.join(gemhome2, "cache", 'b-1.gem')
+ assert_path_not_exist File.join(@gemhome, "cache", 'b-2.gem')
+ assert_path_exist File.join(gemhome2, "gems", 'b-1')
+ assert_path_not_exist File.join(@gemhome, "gems", 'b-1')
end
def test_execute_no_gem
@cmd.options[:args] = %w[]
- e = assert_raises Gem::CommandLineError do
+ e = assert_raise Gem::CommandLineError do
use_ui @ui do
@cmd.execute
end
end
- assert_match %r|at least one gem name|, e.message
+ assert_match %r{at least one gem name}, e.message
end
def test_execute_only_executables
@@ -491,6 +487,42 @@ class TestGemCommandsPristineCommand < Gem::TestCase
refute File.exist? gem_lib
end
+ def test_execute_only_plugins
+ a = util_spec 'a' do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb lib/rubygems_plugin.rb]
+ end
+ write_file File.join(@tempdir, 'lib', 'a.rb') do |fp|
+ fp.puts "puts __FILE__"
+ end
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |fp|
+ fp.puts "puts __FILE__"
+ end
+ write_file File.join(@tempdir, 'bin', 'foo') do |fp|
+ fp.puts "#!/usr/bin/ruby"
+ end
+
+ install_gem a
+
+ gem_lib = File.join @gemhome, 'gems', a.full_name, 'lib', 'a.rb'
+ gem_plugin = File.join @gemhome, 'plugins', 'a_plugin.rb'
+ gem_exec = File.join @gemhome, 'bin', 'foo'
+
+ FileUtils.rm gem_exec
+ FileUtils.rm gem_plugin
+ FileUtils.rm gem_lib
+
+ @cmd.handle_options %w[--all --only-plugins]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ refute File.exist? gem_exec
+ assert File.exist? gem_plugin
+ refute File.exist? gem_lib
+ end
+
def test_execute_bindir
a = util_spec 'a' do |s|
s.name = "test_gem"
@@ -536,7 +568,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase
assert_equal([
"Restoring gems to pristine condition...",
"Cached gem for a-2 not found, attempting to fetch...",
- "Skipped a-2, it was not found from cache and remote sources"
+ "Skipped a-2, it was not found from cache and remote sources",
], @ui.output.split("\n"))
assert_empty @ui.error
@@ -545,7 +577,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase
def test_execute_default_gem
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
- install_default_specs(default_gem_spec)
+ install_default_gems(default_gem_spec)
@cmd.options[:args] = %w[default]
@@ -623,5 +655,4 @@ class TestGemCommandsPristineCommand < Gem::TestCase
assert @cmd.options[:extensions]
assert @cmd.options[:extensions_set]
end
-
end
diff --git a/test/rubygems/test_gem_commands_push_command.rb b/test/rubygems/test_gem_commands_push_command.rb
index f666c6d437..fa3968ffce 100644
--- a/test/rubygems/test_gem_commands_push_command.rb
+++ b/test/rubygems/test_gem_commands_push_command.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/push_command'
class TestGemCommandsPushCommand < Gem::TestCase
-
def setup
super
+
+ credential_setup
+
ENV["RUBYGEMS_HOST"] = nil
Gem.host = Gem::DEFAULT_HOST
Gem.configuration.disable_default_gem_server = false
@@ -37,6 +39,8 @@ class TestGemCommandsPushCommand < Gem::TestCase
end
def teardown
+ credential_teardown
+
super
singleton_gem_class.class_eval do
@@ -119,7 +123,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
Gem.configuration.disable_default_gem_server = true
response = "You must specify a gem server"
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.send_gem(@path)
end
@@ -148,10 +152,9 @@ class TestGemCommandsPushCommand < Gem::TestCase
keys = {
:rubygems_api_key => 'KEY',
- @host => @api_key
+ @host => @api_key,
}
- FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write keys.to_yaml
end
@@ -183,10 +186,9 @@ class TestGemCommandsPushCommand < Gem::TestCase
keys = {
:rubygems_api_key => 'KEY',
- @host => @api_key
+ @host => @api_key,
}
- FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write keys.to_yaml
end
@@ -228,7 +230,6 @@ class TestGemCommandsPushCommand < Gem::TestCase
:rubygems_api_key => @api_key,
}
- FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write keys.to_yaml
end
@@ -246,9 +247,9 @@ class TestGemCommandsPushCommand < Gem::TestCase
spec.metadata['allowed_push_host'] = "https://privategemserver.example"
end
- response = %{ERROR: "#{@host}" is not allowed by the gemspec, which only allows "https://privategemserver.example"}
+ response = %(ERROR: "#{@host}" is not allowed by the gemspec, which only allows "https://privategemserver.example")
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
send_battery
end
@@ -267,10 +268,9 @@ class TestGemCommandsPushCommand < Gem::TestCase
keys = {
:rubygems_api_key => 'KEY',
- @host => @api_key
+ @host => @api_key,
}
- FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write keys.to_yaml
end
@@ -280,7 +280,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
response = "ERROR: \"#{@host}\" is not allowed by the gemspec, which only allows \"#{push_host}\""
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
send_battery
end
@@ -298,10 +298,9 @@ class TestGemCommandsPushCommand < Gem::TestCase
api_key = "PRIVKEY"
keys = {
- host => api_key
+ host => api_key,
}
- FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write keys.to_yaml
end
@@ -328,7 +327,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
def test_raises_error_with_no_arguments
def @cmd.sign_in(*); end
- assert_raises Gem::CommandLineError do
+ assert_raise Gem::CommandLineError do
@cmd.execute
end
end
@@ -338,7 +337,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
@fetcher.data["#{@host}/api/v1/gems"] = [response, 403, 'Forbidden']
@cmd.instance_variable_set :@host, @host
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.send_gem(@path)
end
@@ -355,7 +354,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
end
Gem.configuration.load_api_keys
- @cmd.handle_options %w(-k other)
+ @cmd.handle_options %w[-k other]
@cmd.instance_variable_set :@host, @host
@cmd.send_gem(@path)
@@ -369,7 +368,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
@fetcher.data["#{Gem.host}/api/v1/gems"] = [
[response_fail, 401, 'Unauthorized'],
- [response_success, 200, 'OK']
+ [response_success, 200, 'OK'],
]
@otp_ui = Gem::MockGemUi.new "111111\n"
@@ -388,7 +387,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
@fetcher.data["#{Gem.host}/api/v1/gems"] = [response, 401, 'Unauthorized']
@otp_ui = Gem::MockGemUi.new "111111\n"
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @otp_ui do
@cmd.send_gem(@path)
end
@@ -400,10 +399,74 @@ class TestGemCommandsPushCommand < Gem::TestCase
assert_equal '111111', @fetcher.last_request['OTP']
end
+ def test_sending_gem_unathorized_api_key_with_mfa_enabled
+ response_mfa_enabled = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
+ response_forbidden = "The API key doesn't have access"
+ response_success = 'Successfully registered gem: freewill (1.0.0)'
+
+ @fetcher.data["#{@host}/api/v1/gems"] = [
+ [response_mfa_enabled, 401, 'Unauthorized'],
+ [response_forbidden, 403, 'Forbidden'],
+ [response_success, 200, "OK"],
+ ]
+
+ @fetcher.data["#{@host}/api/v1/api_key"] = ["", 200, "OK"]
+ @cmd.instance_variable_set :@host, @host
+ @cmd.instance_variable_set :@scope, :push_rubygem
+
+ @ui = Gem::MockGemUi.new "11111\nsome@mail.com\npass\n"
+ use_ui @ui do
+ @cmd.send_gem(@path)
+ end
+
+ mfa_notice = "You have enabled multi-factor authentication. Please enter OTP code."
+ access_notice = "The existing key doesn't have access of push_rubygem on https://rubygems.example. Please sign in to update access."
+ assert_match mfa_notice, @ui.output
+ assert_match access_notice, @ui.output
+ assert_match "Email:", @ui.output
+ assert_match "Password:", @ui.output
+ assert_match "Added push_rubygem scope to the existing API key", @ui.output
+ assert_match response_success, @ui.output
+ assert_equal '11111', @fetcher.last_request['OTP']
+ end
+
+ def test_sending_gem_with_no_local_creds
+ Gem.configuration.rubygems_api_key = nil
+
+ response_mfa_enabled = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
+ response_success = 'Successfully registered gem: freewill (1.0.0)'
+
+ @fetcher.data["#{@host}/api/v1/gems"] = [
+ [response_success, 200, "OK"],
+ ]
+
+ @fetcher.data["#{@host}/api/v1/api_key"] = [
+ [response_mfa_enabled, 401, 'Unauthorized'],
+ ["", 200, "OK"],
+ ]
+
+ @cmd.instance_variable_set :@scope, :push_rubygem
+ @cmd.options[:args] = [@path]
+ @cmd.options[:host] = @host
+
+ @ui = Gem::MockGemUi.new "some@mail.com\npass\n11111\n"
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ mfa_notice = "You have enabled multi-factor authentication. Please enter OTP code."
+ assert_match mfa_notice, @ui.output
+ assert_match "Enter your https://rubygems.example credentials.", @ui.output
+ assert_match "Email:", @ui.output
+ assert_match "Password:", @ui.output
+ assert_match "Signed in with API key:", @ui.output
+ assert_match response_success, @ui.output
+ assert_equal '11111', @fetcher.last_request['OTP']
+ end
+
private
def singleton_gem_class
class << Gem; self; end
end
-
end
diff --git a/test/rubygems/test_gem_commands_query_command.rb b/test/rubygems/test_gem_commands_query_command.rb
index 6183e592e9..0cc88b1685 100644
--- a/test/rubygems/test_gem_commands_query_command.rb
+++ b/test/rubygems/test_gem_commands_query_command.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/query_command'
module TestGemCommandsQueryCommandSetup
@@ -19,7 +19,6 @@ module TestGemCommandsQueryCommandSetup
end
class TestGemCommandsQueryCommandWithInstalledGems < Gem::TestCase
-
include TestGemCommandsQueryCommandSetup
def test_execute
@@ -214,7 +213,7 @@ pl (1)
def test_execute_installed
@cmd.handle_options %w[-n a --installed]
- assert_raises Gem::MockGemUi::SystemExitException do
+ assert_raise Gem::MockGemUi::SystemExitException do
use_ui @stub_ui do
@cmd.execute
end
@@ -227,7 +226,7 @@ pl (1)
def test_execute_installed_inverse
@cmd.handle_options %w[-n a --no-installed]
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
use_ui @stub_ui do
@cmd.execute
end
@@ -242,7 +241,7 @@ pl (1)
def test_execute_installed_inverse_not_installed
@cmd.handle_options %w[-n not_installed --no-installed]
- assert_raises Gem::MockGemUi::SystemExitException do
+ assert_raise Gem::MockGemUi::SystemExitException do
use_ui @stub_ui do
@cmd.execute
end
@@ -255,7 +254,7 @@ pl (1)
def test_execute_installed_no_name
@cmd.handle_options %w[--installed]
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
use_ui @stub_ui do
@cmd.execute
end
@@ -270,7 +269,7 @@ pl (1)
def test_execute_installed_not_installed
@cmd.handle_options %w[-n not_installed --installed]
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
use_ui @stub_ui do
@cmd.execute
end
@@ -285,7 +284,7 @@ pl (1)
def test_execute_installed_version
@cmd.handle_options %w[-n a --installed --version 2]
- assert_raises Gem::MockGemUi::SystemExitException do
+ assert_raise Gem::MockGemUi::SystemExitException do
use_ui @stub_ui do
@cmd.execute
end
@@ -298,7 +297,7 @@ pl (1)
def test_execute_installed_version_not_installed
@cmd.handle_options %w[-n c --installed --version 2]
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
use_ui @stub_ui do
@cmd.execute
end
@@ -580,8 +579,8 @@ pl (1 i386-linux)
@cmd.execute
end
- assert_match %r%^a %, @stub_ui.output
- assert_match %r%^pl %, @stub_ui.output
+ assert_match %r{^a }, @stub_ui.output
+ assert_match %r{^pl }, @stub_ui.output
assert_equal '', @stub_ui.error
end
@@ -593,8 +592,8 @@ pl (1 i386-linux)
@cmd.send :show_gems, /a/i
end
- assert_match %r%^a %, @stub_ui.output
- refute_match %r%^pl %, @stub_ui.output
+ assert_match %r{^a }, @stub_ui.output
+ refute_match %r{^pl }, @stub_ui.output
assert_empty @stub_ui.error
end
@@ -607,11 +606,9 @@ pl (1 i386-linux)
fetcher.spec 'a', '3.a'
end
end
-
end
class TestGemCommandsQueryCommandWithoutInstalledGems < Gem::TestCase
-
include TestGemCommandsQueryCommandSetup
def test_execute_platform
@@ -644,10 +641,10 @@ a (2 universal-darwin, 1 ruby x86-linux)
end
def test_execute_show_default_gems
- spec_fetcher { |fetcher| fetcher.spec 'a', 2 }
+ spec_fetcher {|fetcher| fetcher.spec 'a', 2 }
a1 = new_default_spec 'a', 1
- install_default_specs a1
+ install_default_gems a1
use_ui @stub_ui do
@cmd.execute
@@ -666,7 +663,7 @@ EOF
def test_execute_show_default_gems_with_platform
a1 = new_default_spec 'a', 1
a1.platform = 'java'
- install_default_specs a1
+ install_default_gems a1
use_ui @stub_ui do
@cmd.execute
@@ -688,7 +685,7 @@ EOF
end
a1 = new_default_spec 'a', 1
- install_default_specs a1
+ install_default_gems a1
@cmd.handle_options %w[-l -d]
@@ -844,6 +841,10 @@ othergem (1.2.3)
assert_equal expected, @stub_ui.output
end
+ def test_depprecated
+ assert @cmd.deprecated?
+ end
+
private
def add_gems_to_fetcher
@@ -853,5 +854,4 @@ othergem (1.2.3)
fetcher.download 'a', '3.a'
end
end
-
end
diff --git a/test/rubygems/test_gem_commands_search_command.rb b/test/rubygems/test_gem_commands_search_command.rb
index 9187050c30..6397dbd4d4 100644
--- a/test/rubygems/test_gem_commands_search_command.rb
+++ b/test/rubygems/test_gem_commands_search_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/search_command'
class TestGemCommandsSearchCommand < Gem::TestCase
-
def setup
super
@@ -13,5 +12,4 @@ class TestGemCommandsSearchCommand < Gem::TestCase
def test_initialize
assert_equal :remote, @cmd.defaults[:domain]
end
-
end
diff --git a/test/rubygems/test_gem_commands_server_command.rb b/test/rubygems/test_gem_commands_server_command.rb
index af15aadfd1..d5cd4d13bd 100644
--- a/test/rubygems/test_gem_commands_server_command.rb
+++ b/test/rubygems/test_gem_commands_server_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/server_command'
class TestGemCommandsServerCommand < Gem::TestCase
-
def setup
super
@@ -41,23 +40,22 @@ class TestGemCommandsServerCommand < Gem::TestCase
begin
@cmd.send :handle_options, %w[-p discard]
assert_equal 9, @cmd.options[:port]
- rescue OptionParser::InvalidArgument
+ rescue Gem::OptionParser::InvalidArgument
# for container environment on GitHub Actions
end
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.send :handle_options, %w[-p nonexistent]
end
assert_equal 'invalid argument: -p nonexistent: no such named service',
e.message
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.send :handle_options, %w[-p 65536]
end
assert_equal 'invalid argument: -p 65536: not a port number',
e.message
end
-
end
diff --git a/test/rubygems/test_gem_commands_setup_command.rb b/test/rubygems/test_gem_commands_setup_command.rb
index c63f7177c7..5cf94a1dc9 100644
--- a/test/rubygems/test_gem_commands_setup_command.rb
+++ b/test/rubygems/test_gem_commands_setup_command.rb
@@ -1,11 +1,9 @@
-# coding: UTF-8
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/setup_command'
class TestGemCommandsSetupCommand < Gem::TestCase
-
bundler_gemspec = File.expand_path("../../../bundler/lib/bundler/version.rb", __FILE__)
if File.exist?(bundler_gemspec)
BUNDLER_VERS = File.read(bundler_gemspec).match(/VERSION = "(#{Gem::Version::VERSION_PATTERN})"/)[1]
@@ -16,86 +14,50 @@ class TestGemCommandsSetupCommand < Gem::TestCase
def setup
super
- @install_dir = File.join @tempdir, 'install'
@cmd = Gem::Commands::SetupCommand.new
- @cmd.options[:prefix] = @install_dir
-
- FileUtils.mkdir_p 'bin'
- FileUtils.mkdir_p 'lib/rubygems/ssl_certs/rubygems.org'
-
- File.open 'bin/gem', 'w' do
- |io| io.puts '# gem'
- end
-
- File.open 'lib/rubygems.rb', 'w' do |io|
- io.puts '# rubygems.rb'
- end
-
- File.open 'lib/rubygems/test_case.rb', 'w' do |io|
- io.puts '# test_case.rb'
- end
-
- File.open 'lib/rubygems/ssl_certs/rubygems.org/foo.pem', 'w' do |io|
- io.puts 'PEM'
- end
-
- FileUtils.mkdir_p 'bundler/exe'
- FileUtils.mkdir_p 'bundler/lib/bundler'
- File.open 'bundler/exe/bundle', 'w' do |io|
- io.puts '# bundle'
- end
-
- File.open 'bundler/lib/bundler.rb', 'w' do |io|
- io.puts '# bundler.rb'
- end
-
- File.open 'bundler/lib/bundler/b.rb', 'w' do |io|
- io.puts '# b.rb'
- end
-
- FileUtils.mkdir_p 'default/gems'
+ filelist = %w[
+ bin/gem
+ lib/rubygems.rb
+ lib/rubygems/requirement.rb
+ lib/rubygems/ssl_certs/rubygems.org/foo.pem
+ bundler/exe/bundle
+ bundler/exe/bundler
+ bundler/lib/bundler.rb
+ bundler/lib/bundler/b.rb
+ bundler/bin/bundler/man/bundle-b.1
+ bundler/lib/bundler/man/bundle-b.1.ronn
+ bundler/lib/bundler/man/gemfile.5
+ bundler/lib/bundler/man/gemfile.5.ronn
+ bundler/lib/bundler/templates/.circleci/config.yml
+ bundler/lib/bundler/templates/.travis.yml
+ ]
+
+ create_dummy_files(filelist)
gemspec = Gem::Specification.new
gemspec.author = "Us"
gemspec.name = "bundler"
gemspec.version = BUNDLER_VERS
gemspec.bindir = "exe"
- gemspec.executables = ["bundle"]
+ gemspec.executables = ["bundle", "bundler"]
- File.open 'bundler/bundler.gemspec', 'w' do |io|
+ File.open 'bundler/bundler.gemspec', 'w' do |io|
io.puts gemspec.to_ruby
end
- open(File.join(Gem.default_specifications_dir, "bundler-1.15.4.gemspec"), 'w') do |io|
+ File.open(File.join(Gem.default_specifications_dir, "bundler-1.15.4.gemspec"), 'w') do |io|
gemspec.version = "1.15.4"
io.puts gemspec.to_ruby
end
- FileUtils.mkdir_p File.join(Gem.default_dir, "specifications")
+ spec_fetcher do |fetcher|
+ fetcher.download "bundler", "1.15.4"
- open(File.join(Gem.default_dir, "specifications", "bundler-#{BUNDLER_VERS}.gemspec"), 'w') do |io|
- io.puts "# bundler-#{BUNDLER_VERS}"
- end
+ fetcher.gem "bundler", BUNDLER_VERS
- open(File.join(Gem.default_dir, "specifications", "bundler-audit-1.0.0.gemspec"), 'w') do |io|
- io.puts '# bundler-audit'
+ fetcher.gem "bundler-audit", "1.0.0"
end
-
- FileUtils.mkdir_p 'default/gems/bundler-1.15.4'
- FileUtils.mkdir_p 'default/gems/bundler-audit-1.0.0'
- end
-
- def gem_install(name)
- gem = util_spec name do |s|
- s.executables = [name]
- s.files = %W[bin/#{name}]
- end
- write_file File.join @tempdir, 'bin', name do |f|
- f.puts '#!/usr/bin/ruby'
- end
- install_gem gem
- File.join @gemhome, 'bin', name
end
def test_execute_regenerate_binstubs
@@ -123,7 +85,46 @@ class TestGemCommandsSetupCommand < Gem::TestCase
assert_equal "I changed it!\n", File.read(gem_bin_path)
end
+ def test_execute_regenerate_plugins
+ gem_plugin_path = gem_install_with_plugin 'a'
+ write_file gem_plugin_path do |io|
+ io.puts 'I changed it!'
+ end
+
+ @cmd.options[:document] = []
+ @cmd.execute
+
+ assert_match %r{\Arequire}, File.read(gem_plugin_path)
+ end
+
+ def test_execute_no_regenerate_plugins
+ gem_plugin_path = gem_install_with_plugin 'a'
+ write_file gem_plugin_path do |io|
+ io.puts 'I changed it!'
+ end
+
+ @cmd.options[:document] = []
+ @cmd.options[:regenerate_plugins] = false
+ @cmd.execute
+
+ assert_equal "I changed it!\n", File.read(gem_plugin_path)
+ end
+
+ def test_execute_regenerate_plugins_creates_plugins_dir_if_not_there
+ gem_plugin_path = gem_install_with_plugin 'a'
+
+ # Simulate gem installed with an older rubygems without a plugins layout
+ FileUtils.rm_rf Gem.plugindir
+
+ @cmd.options[:document] = []
+ @cmd.execute
+
+ assert_match %r{\Arequire}, File.read(gem_plugin_path)
+ end
+
def test_execute_informs_about_installed_executables
+ @cmd.options[:document] = []
+
use_ui @ui do
@cmd.execute
end
@@ -133,6 +134,7 @@ class TestGemCommandsSetupCommand < Gem::TestCase
exec_line = out.shift until exec_line == "RubyGems installed the following executables:"
assert_equal "\t#{default_gem_bin_path}", out.shift
assert_equal "\t#{default_bundle_bin_path}", out.shift
+ assert_equal "\t#{default_bundler_bin_path}", out.shift
end
def test_env_shebang_flag
@@ -147,25 +149,31 @@ class TestGemCommandsSetupCommand < Gem::TestCase
ruby_exec = sprintf Gem.default_exec_format, 'ruby'
- if Gem.win_platform?
- assert_match %r%\A#!\s*#{ruby_exec}%, File.read(default_gem_bin_path)
- assert_match %r%\A#!\s*#{ruby_exec}%, File.read(default_bundle_bin_path)
- assert_match %r%\A#!\s*#{ruby_exec}%, File.read(gem_bin_path)
- else
- assert_match %r%\A#!/usr/bin/env #{ruby_exec}%, File.read(default_gem_bin_path)
- assert_match %r%\A#!/usr/bin/env #{ruby_exec}%, File.read(default_bundle_bin_path)
- assert_match %r%\A#!/usr/bin/env #{ruby_exec}%, File.read(gem_bin_path)
- end
+ bin_env = win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " "
+ assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_gem_bin_path)
+ assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_bundle_bin_path)
+ assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_bundler_bin_path)
+ assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(gem_bin_path)
end
- def test_pem_files_in
- assert_equal %w[rubygems/ssl_certs/rubygems.org/foo.pem],
- @cmd.pem_files_in('lib').sort
+ def test_destdir_flag_does_not_try_to_write_to_the_default_gem_home
+ FileUtils.chmod "-w", File.join(@gemhome, "plugins")
+
+ destdir = File.join(@tempdir, 'foo')
+
+ @cmd.options[:destdir] = destdir
+ @cmd.execute
+
+ spec = Gem::Specification.load("bundler/bundler.gemspec")
+
+ spec.executables.each do |e|
+ assert_path_exist File.join destdir, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'gems', spec.full_name, spec.bindir, e
+ end
end
- def test_rb_files_in
- assert_equal %w[rubygems.rb rubygems/test_case.rb],
- @cmd.rb_files_in('lib').sort
+ def test_files_in
+ assert_equal %w[rubygems.rb rubygems/requirement.rb rubygems/ssl_certs/rubygems.org/foo.pem],
+ @cmd.files_in('lib').sort
end
def test_install_lib
@@ -174,11 +182,14 @@ class TestGemCommandsSetupCommand < Gem::TestCase
Dir.mktmpdir 'lib' do |dir|
@cmd.install_lib dir
- assert_path_exists File.join(dir, 'rubygems.rb')
- assert_path_exists File.join(dir, 'rubygems/ssl_certs/rubygems.org/foo.pem')
+ assert_path_exist File.join(dir, 'rubygems.rb')
+ assert_path_exist File.join(dir, 'rubygems/ssl_certs/rubygems.org/foo.pem')
+
+ assert_path_exist File.join(dir, 'bundler.rb')
+ assert_path_exist File.join(dir, 'bundler/b.rb')
- assert_path_exists File.join(dir, 'bundler.rb')
- assert_path_exists File.join(dir, 'bundler/b.rb')
+ assert_path_exist File.join(dir, 'bundler/templates/.circleci/config.yml')
+ assert_path_exist File.join(dir, 'bundler/templates/.travis.yml')
end
end
@@ -194,34 +205,27 @@ class TestGemCommandsSetupCommand < Gem::TestCase
spec.executables.each do |e|
if Gem.win_platform?
- assert_path_exists File.join(bin_dir, "#{e}.bat")
+ assert_path_exist File.join(bin_dir, "#{e}.bat")
end
- assert_path_exists File.join bin_dir, Gem.default_exec_format % e
+ assert_path_exist File.join bin_dir, e
end
default_dir = Gem.default_specifications_dir
# expect to remove other versions of bundler gemspecs on default specification directory.
- refute_path_exists File.join(default_dir, "bundler-1.15.4.gemspec")
- assert_path_exists File.join(default_dir, "bundler-#{BUNDLER_VERS}.gemspec")
+ assert_path_not_exist File.join(default_dir, "bundler-1.15.4.gemspec")
+ assert_path_exist File.join(default_dir, "bundler-#{BUNDLER_VERS}.gemspec")
# expect to not remove bundler-* gemspecs.
- assert_path_exists File.join(Gem.default_dir, "specifications", "bundler-audit-1.0.0.gemspec")
+ assert_path_exist File.join(Gem.dir, "specifications", "bundler-audit-1.0.0.gemspec")
# expect to remove normal gem that was same version. because it's promoted default gems.
- refute_path_exists File.join(Gem.default_dir, "specifications", "bundler-#{BUNDLER_VERS}.gemspec")
+ assert_path_not_exist File.join(Gem.dir, "specifications", "bundler-#{BUNDLER_VERS}.gemspec")
- # expect to install default gems. It location was `site_ruby` directory on real world.
- assert_path_exists "default/gems/bundler-#{BUNDLER_VERS}"
-
- # expect to not remove other versions of bundler on `site_ruby`
- assert_path_exists 'default/gems/bundler-1.15.4'
-
- # TODO: We need to assert to remove same version of bundler on gem_dir directory(It's not site_ruby dir)
-
- # expect to not remove bundler-* directory.
- assert_path_exists 'default/gems/bundler-audit-1.0.0'
+ assert_path_exist "#{Gem.dir}/gems/bundler-#{BUNDLER_VERS}"
+ assert_path_exist "#{Gem.dir}/gems/bundler-1.15.4"
+ assert_path_exist "#{Gem.dir}/gems/bundler-audit-1.0.0"
end
def test_install_default_bundler_gem_with_force_flag
@@ -236,76 +240,112 @@ class TestGemCommandsSetupCommand < Gem::TestCase
f.puts 'echo "hello"'
end
- bindir(bin_dir) do
- @cmd.options[:force] = true
-
- @cmd.install_default_bundler_gem bin_dir
+ @cmd.options[:force] = true
- bundler_spec = Gem::Specification.load("bundler/bundler.gemspec")
- default_spec_path = File.join(Gem.default_specifications_dir, "#{bundler_spec.full_name}.gemspec")
- spec = Gem::Specification.load(default_spec_path)
+ @cmd.install_default_bundler_gem bin_dir
- spec.executables.each do |e|
- if Gem.win_platform?
- assert_path_exists File.join(bin_dir, "#{e}.bat")
- end
+ bundler_spec = Gem::Specification.load("bundler/bundler.gemspec")
+ default_spec_path = File.join(Gem.default_specifications_dir, "#{bundler_spec.full_name}.gemspec")
+ spec = Gem::Specification.load(default_spec_path)
- assert_path_exists File.join bin_dir, Gem.default_exec_format % e
+ spec.executables.each do |e|
+ if Gem.win_platform?
+ assert_path_exist File.join(bin_dir, "#{e}.bat")
end
+
+ assert_path_exist File.join bin_dir, e
+ end
+ end
+
+ def test_install_default_bundler_gem_with_destdir_flag
+ @cmd.extend FileUtils
+
+ FileUtils.chmod "-w", @gemhome
+
+ destdir = File.join(@tempdir, 'foo')
+ bin_dir = File.join(destdir, 'bin')
+
+ @cmd.options[:destdir] = destdir
+
+ @cmd.install_default_bundler_gem bin_dir
+
+ spec = Gem::Specification.load("bundler/bundler.gemspec")
+
+ spec.executables.each do |e|
+ assert_path_exist File.join destdir, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'gems', spec.full_name, spec.bindir, e
+ end
+ end
+
+ def test_install_default_bundler_gem_with_destdir_and_prefix_flags
+ @cmd.extend FileUtils
+
+ destdir = File.join(@tempdir, 'foo')
+ bin_dir = File.join(destdir, 'bin')
+
+ @cmd.options[:destdir] = destdir
+ @cmd.options[:prefix] = "/"
+
+ @cmd.install_default_bundler_gem bin_dir
+
+ spec = Gem::Specification.load("bundler/bundler.gemspec")
+
+ spec.executables.each do |e|
+ assert_path_exist File.join destdir, 'gems', spec.full_name, spec.bindir, e
end
end
def test_remove_old_lib_files
- lib = File.join @install_dir, 'lib'
+ lib = RbConfig::CONFIG["sitelibdir"]
lib_rubygems = File.join lib, 'rubygems'
lib_bundler = File.join lib, 'bundler'
lib_rubygems_defaults = File.join lib_rubygems, 'defaults'
+ lib_bundler_templates = File.join lib_bundler, 'templates'
securerandom_rb = File.join lib, 'securerandom.rb'
engine_defaults_rb = File.join lib_rubygems_defaults, 'jruby.rb'
os_defaults_rb = File.join lib_rubygems_defaults, 'operating_system.rb'
+ old_gauntlet_rubygems_rb = File.join lib, 'gauntlet_rubygems.rb'
+
old_builder_rb = File.join lib_rubygems, 'builder.rb'
old_format_rb = File.join lib_rubygems, 'format.rb'
old_bundler_c_rb = File.join lib_bundler, 'c.rb'
+ old_bundler_ci = File.join lib_bundler_templates, '.lecacy_ci', 'config.yml'
- FileUtils.mkdir_p lib_rubygems_defaults
- FileUtils.mkdir_p lib_bundler
+ files_that_go = [old_gauntlet_rubygems_rb, old_builder_rb, old_format_rb, old_bundler_c_rb, old_bundler_ci]
+ files_that_stay = [securerandom_rb, engine_defaults_rb, os_defaults_rb]
- File.open securerandom_rb, 'w' do |io|
- io.puts '# securerandom.rb'
- end
+ create_dummy_files(files_that_go + files_that_stay)
- File.open old_builder_rb, 'w' do |io|
- io.puts '# builder.rb'
- end
+ @cmd.remove_old_lib_files lib
- File.open old_format_rb, 'w' do |io|
- io.puts '# format.rb'
- end
+ files_that_go.each {|file| assert_path_not_exist(file) unless file == old_bundler_ci }
- File.open old_bundler_c_rb, 'w' do |io|
- io.puts '# c.rb'
- end
+ files_that_stay.each {|file| assert_path_exist file }
+ end
- File.open engine_defaults_rb, 'w' do |io|
- io.puts '# jruby.rb'
- end
+ def test_remove_old_man_files
+ man = File.join RbConfig::CONFIG['mandir'], 'man'
- File.open os_defaults_rb, 'w' do |io|
- io.puts '# operating_system.rb'
- end
+ ruby_1 = File.join man, 'man1', 'ruby.1'
+ bundle_b_1 = File.join man, 'man1', 'bundle-b.1'
+ bundle_b_1_ronn = File.join man, 'man1', 'bundle-b.1.ronn'
+ bundle_b_1_txt = File.join man, 'man1', 'bundle-b.1.txt'
+ gemfile_5 = File.join man, 'man5', 'gemfile.5'
+ gemfile_5_ronn = File.join man, 'man5', 'gemfile.5.ronn'
+ gemfile_5_txt = File.join man, 'man5', 'gemfile.5.txt'
- @cmd.remove_old_lib_files lib
+ files_that_go = [bundle_b_1, bundle_b_1_txt, bundle_b_1_ronn, gemfile_5, gemfile_5_txt, gemfile_5_ronn]
+ files_that_stay = [ruby_1]
+
+ create_dummy_files(files_that_go + files_that_stay)
- refute_path_exists old_builder_rb
- refute_path_exists old_format_rb
- refute_path_exists old_bundler_c_rb
+ @cmd.remove_old_man_files man
- assert_path_exists securerandom_rb
- assert_path_exists engine_defaults_rb
- assert_path_exists os_defaults_rb
+ files_that_go.each {|file| assert_path_not_exist file }
+
+ files_that_stay.each {|file| assert_path_exist file }
end
def test_show_release_notes
@@ -314,26 +354,24 @@ class TestGemCommandsSetupCommand < Gem::TestCase
@cmd.options[:previous_version] = Gem::Version.new '2.0.2'
- File.open 'History.txt', 'w' do |io|
- io.puts <<-History_txt
-# coding: UTF-8
-
-=== #{Gem::VERSION} / 2013-03-26
+ File.open 'CHANGELOG.md', 'w' do |io|
+ io.puts <<-HISTORY_TXT
+# #{Gem::VERSION} / 2013-03-26
-* Bug fixes:
+## Bug fixes:
* Fixed release note display for LANG=C when installing rubygems
* π is tasty
-=== 2.0.2 / 2013-03-06
+# 2.0.2 / 2013-03-06
-* Bug fixes:
+## Bug fixes:
* Other bugs fixed
-=== 2.0.1 / 2013-03-05
+# 2.0.1 / 2013-03-05
-* Bug fixes:
+## Bug fixes:
* Yet more bugs fixed
- History_txt
+ HISTORY_TXT
end
use_ui @ui do
@@ -341,9 +379,9 @@ class TestGemCommandsSetupCommand < Gem::TestCase
end
expected = <<-EXPECTED
-=== #{Gem::VERSION} / 2013-03-26
+# #{Gem::VERSION} / 2013-03-26
-* Bug fixes:
+## Bug fixes:
* Fixed release note display for LANG=C when installing rubygems
* π is tasty
@@ -359,14 +397,49 @@ class TestGemCommandsSetupCommand < Gem::TestCase
private
+ def create_dummy_files(list)
+ list.each do |file|
+ FileUtils.mkdir_p File.dirname(file)
+
+ File.open file, 'w' do |io|
+ io.puts "# #{File.basename(file)}"
+ end
+ end
+ end
+
+ def gem_install(name)
+ gem = util_spec name do |s|
+ s.executables = [name]
+ s.files = %W[bin/#{name}]
+ end
+ write_file File.join @tempdir, 'bin', name do |f|
+ f.puts '#!/usr/bin/ruby'
+ end
+ install_gem gem
+ File.join @gemhome, 'bin', name
+ end
+
+ def gem_install_with_plugin(name)
+ gem = util_spec name do |s|
+ s.files = %W[lib/rubygems_plugin.rb]
+ end
+ write_file File.join @tempdir, 'lib', 'rubygems_plugin.rb' do |f|
+ f.puts "require '#{gem.plugins.first}'"
+ end
+ install_gem gem
+
+ File.join Gem.plugindir, "#{name}_plugin.rb"
+ end
+
def default_gem_bin_path
- gem_exec = sprintf Gem.default_exec_format, 'gem'
- File.join @install_dir, 'bin', gem_exec
+ File.join RbConfig::CONFIG['bindir'], 'gem'
end
def default_bundle_bin_path
- bundle_exec = sprintf Gem.default_exec_format, 'bundle'
- File.join @install_dir, 'bin', bundle_exec
+ File.join RbConfig::CONFIG['bindir'], 'bundle'
end
+ def default_bundler_bin_path
+ File.join RbConfig::CONFIG['bindir'], 'bundler'
+ end
end unless Gem.java_platform?
diff --git a/test/rubygems/test_gem_commands_signin_command.rb b/test/rubygems/test_gem_commands_signin_command.rb
index c000c7a77a..0f856a53ba 100644
--- a/test/rubygems/test_gem_commands_signin_command.rb
+++ b/test/rubygems/test_gem_commands_signin_command.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/signin_command'
require 'rubygems/installer'
class TestGemCommandsSigninCommand < Gem::TestCase
-
def setup
super
+ credential_setup
+
Gem.configuration.rubygems_api_key = nil
Gem.configuration.api_keys.clear
@@ -15,13 +16,20 @@ class TestGemCommandsSigninCommand < Gem::TestCase
end
def teardown
- credentials_path = Gem.configuration.credentials_path
- File.delete(credentials_path) if File.exist?(credentials_path)
+ credential_teardown
+
super
end
def test_execute_when_not_already_signed_in
- sign_in_ui = util_capture() { @cmd.execute }
+ sign_in_ui = util_capture { @cmd.execute }
+ assert_match %r{Signed in.}, sign_in_ui.output
+ end
+
+ def test_execute_when_not_already_signed_in_and_not_preexisting_credentials_folder
+ FileUtils.rm Gem.configuration.credentials_path
+
+ sign_in_ui = util_capture { @cmd.execute }
assert_match %r{Signed in.}, sign_in_ui.output
end
@@ -29,10 +37,10 @@ class TestGemCommandsSigninCommand < Gem::TestCase
host = 'http://some-gemcutter-compatible-host.org'
util_capture(nil, host) { @cmd.execute }
- old_credentials = YAML.load_file Gem.configuration.credentials_path
+ old_credentials = load_yaml_file Gem.configuration.credentials_path
util_capture(nil, host) { @cmd.execute }
- new_credentials = YAML.load_file Gem.configuration.credentials_path
+ new_credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal old_credentials[host], new_credentials[host]
end
@@ -44,7 +52,7 @@ class TestGemCommandsSigninCommand < Gem::TestCase
host = 'http://some-gemcutter-compatible-host.org'
util_capture(nil, host, api_key) { @cmd.execute }
- credentials = YAML.load_file Gem.configuration.credentials_path
+ credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal credentials[:rubygems_api_key], api_key
@@ -59,27 +67,51 @@ class TestGemCommandsSigninCommand < Gem::TestCase
assert_match %r{Signed in.}, sign_in_ui.output
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
- credentials = YAML.load_file Gem.configuration.credentials_path
+ credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials[host]
end
def test_execute_with_valid_creds_set_for_default_host
- util_capture {@cmd.execute}
+ util_capture { @cmd.execute }
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
- credentials = YAML.load_file Gem.configuration.credentials_path
+ credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials[:rubygems_api_key]
end
+ def test_execute_with_key_name_and_scope
+ email = 'you@example.com'
+ password = 'secret'
+ api_key = '1234'
+ fetcher = Gem::RemoteFetcher.fetcher
+
+ key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\n"
+ util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute }
+
+ user = ENV["USER"] || ENV["USERNAME"]
+
+ assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output
+ assert_match "index_rubygems [y/N]", key_name_ui.output
+ assert_match "push_rubygem [y/N]", key_name_ui.output
+ assert_match "yank_rubygem [y/N]", key_name_ui.output
+ assert_match "add_owner [y/N]", key_name_ui.output
+ assert_match "remove_owner [y/N]", key_name_ui.output
+ assert_match "access_webhooks [y/N]", key_name_ui.output
+ assert_match "show_dashboard [y/N]", key_name_ui.output
+ assert_equal "name=test-key&push_rubygem=true", fetcher.last_request.body
+
+ credentials = load_yaml_file Gem.configuration.credentials_path
+ assert_equal api_key, credentials[:rubygems_api_key]
+ end
+
# Utility method to capture IO/UI within the block passed
- def util_capture(ui_stub = nil, host = nil, api_key = nil)
+ def util_capture(ui_stub = nil, host = nil, api_key = nil, fetcher = Gem::FakeFetcher.new)
api_key ||= 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
response = [api_key, 200, 'OK']
email = 'you@example.com'
password = 'secret'
- fetcher = Gem::FakeFetcher.new
# Set the expected response for the Web-API supplied
ENV['RUBYGEMS_HOST'] = host || Gem::DEFAULT_HOST
@@ -87,7 +119,7 @@ class TestGemCommandsSigninCommand < Gem::TestCase
fetcher.data[data_key] = response
Gem::RemoteFetcher.fetcher = fetcher
- sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n")
+ sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n")
use_ui sign_in_ui do
yield
@@ -95,5 +127,4 @@ class TestGemCommandsSigninCommand < Gem::TestCase
sign_in_ui
end
-
end
diff --git a/test/rubygems/test_gem_commands_signout_command.rb b/test/rubygems/test_gem_commands_signout_command.rb
index 814b55cf4f..aa6300b6ab 100644
--- a/test/rubygems/test_gem_commands_signout_command.rb
+++ b/test/rubygems/test_gem_commands_signout_command.rb
@@ -1,21 +1,15 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/signout_command'
require 'rubygems/installer'
class TestGemCommandsSignoutCommand < Gem::TestCase
-
def setup
super
@cmd = Gem::Commands::SignoutCommand.new
end
- def teardown
- super
- File.delete Gem.configuration.credentials_path if File.exist?(Gem.configuration.credentials_path)
- end
-
def test_execute_when_user_is_signed_in
FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path)
FileUtils::touch Gem.configuration.credentials_path
@@ -33,5 +27,4 @@ class TestGemCommandsSignoutCommand < Gem::TestCase
assert_match %r{You are not currently signed in}, @sign_out_ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_sources_command.rb b/test/rubygems/test_gem_commands_sources_command.rb
index 3a0899245b..7bca0f3803 100644
--- a/test/rubygems/test_gem_commands_sources_command.rb
+++ b/test/rubygems/test_gem_commands_sources_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/sources_command'
class TestGemCommandsSourcesCommand < Gem::TestCase
-
def setup
super
@@ -108,6 +107,36 @@ class TestGemCommandsSourcesCommand < Gem::TestCase
assert_empty ui.error
end
+ def test_execute_add_allow_typo_squatting_source_forced
+ rubygems_org = "https://rubyems.org"
+
+ spec_fetcher do |fetcher|
+ fetcher.spec("a", 1)
+ end
+
+ specs = Gem::Specification.map do |spec|
+ [spec.name, spec.version, spec.original_platform]
+ end
+
+ specs_dump_gz = StringIO.new
+ Zlib::GzipWriter.wrap(specs_dump_gz) do |io|
+ Marshal.dump(specs, io)
+ end
+
+ @fetcher.data["#{rubygems_org}/specs.#{@marshal_version}.gz"] = specs_dump_gz.string
+ @cmd.handle_options %W[--force --add #{rubygems_org}]
+
+ @cmd.execute
+
+ expected = "https://rubyems.org added to sources\n"
+ assert_equal expected, ui.output
+
+ source = Gem::Source.new(rubygems_org)
+ assert Gem.sources.include?(source)
+
+ assert_empty ui.error
+ end
+
def test_execute_add_deny_typo_squatting_source
rubygems_org = "https://rubyems.org"
@@ -133,7 +162,7 @@ class TestGemCommandsSourcesCommand < Gem::TestCase
use_ui ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -159,7 +188,7 @@ class TestGemCommandsSourcesCommand < Gem::TestCase
@cmd.handle_options %w[--add http://beta-gems.example.com]
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -270,7 +299,7 @@ source http://gems.example.com/ already present in the cache
ui = Gem::MockGemUi.new "n"
use_ui ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -284,6 +313,36 @@ source http://gems.example.com/ already present in the cache
assert_empty @ui.error
end
+ def test_execute_add_http_rubygems_org_forced
+ rubygems_org = "http://rubygems.org"
+
+ spec_fetcher do |fetcher|
+ fetcher.spec("a", 1)
+ end
+
+ specs = Gem::Specification.map do |spec|
+ [spec.name, spec.version, spec.original_platform]
+ end
+
+ specs_dump_gz = StringIO.new
+ Zlib::GzipWriter.wrap(specs_dump_gz) do |io|
+ Marshal.dump(specs, io)
+ end
+
+ @fetcher.data["#{rubygems_org}/specs.#{@marshal_version}.gz"] = specs_dump_gz.string
+ @cmd.handle_options %W[--force --add #{rubygems_org}]
+
+ @cmd.execute
+
+ expected = "http://rubygems.org added to sources\n"
+ assert_equal expected, ui.output
+
+ source = Gem::Source.new(rubygems_org)
+ assert Gem.sources.include?(source)
+
+ assert_empty ui.error
+ end
+
def test_execute_add_https_rubygems_org
https_rubygems_org = 'https://rubygems.org/'
@@ -308,7 +367,7 @@ source http://gems.example.com/ already present in the cache
ui = Gem::MockGemUi.new "n"
use_ui ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -326,7 +385,7 @@ source http://gems.example.com/ already present in the cache
@cmd.handle_options %w[--add beta-gems.example.com]
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -422,5 +481,4 @@ beta-gems.example.com is not a URI
assert_equal "source cache successfully updated\n", @ui.output
assert_equal '', @ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_specification_command.rb b/test/rubygems/test_gem_commands_specification_command.rb
index f56aa9777a..c8cb7df32e 100644
--- a/test/rubygems/test_gem_commands_specification_command.rb
+++ b/test/rubygems/test_gem_commands_specification_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/specification_command'
class TestGemCommandsSpecificationCommand < Gem::TestCase
-
def setup
super
@@ -21,8 +20,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|Gem::Specification|, @ui.output
- assert_match %r|name: foo|, @ui.output
+ assert_match %r{Gem::Specification}, @ui.output
+ assert_match %r{name: foo}, @ui.output
assert_equal '', @ui.error
end
@@ -37,10 +36,10 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|Gem::Specification|, @ui.output
- assert_match %r|name: foo|, @ui.output
- assert_match %r|version: 0.0.1|, @ui.output
- assert_match %r|version: 0.0.2|, @ui.output
+ assert_match %r{Gem::Specification}, @ui.output
+ assert_match %r{name: foo}, @ui.output
+ assert_match %r{version: 0.0.1}, @ui.output
+ assert_match %r{version: 0.0.2}, @ui.output
assert_equal '', @ui.error
end
@@ -52,7 +51,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.options[:all] = true
@cmd.options[:version] = "1"
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
@@ -65,7 +64,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
def test_execute_bad_name
@cmd.options[:args] = %w[foo]
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
@@ -79,7 +78,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.options[:args] = %w[foo]
@cmd.options[:version] = "1.3.2"
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
@@ -99,8 +98,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|Gem::Specification|, @ui.output
- assert_match %r|name: foo|, @ui.output
+ assert_match %r{Gem::Specification}, @ui.output
+ assert_match %r{name: foo}, @ui.output
assert_equal '', @ui.error
end
@@ -115,7 +114,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_equal "foo", YAML.load(@ui.output)
+ assert_equal "foo", load_yaml(@ui.output)
end
def test_execute_file
@@ -131,8 +130,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|Gem::Specification|, @ui.output
- assert_match %r|name: foo|, @ui.output
+ assert_match %r{Gem::Specification}, @ui.output
+ assert_match %r{name: foo}, @ui.output
assert_equal '', @ui.error
end
@@ -164,8 +163,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|\A--- !ruby/object:Gem::Specification|, @ui.output
- assert_match %r|name: foo|, @ui.output
+ assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output
+ assert_match %r{name: foo}, @ui.output
end
def test_execute_remote_with_version
@@ -187,6 +186,34 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
assert_equal Gem::Version.new("1"), spec.version
end
+ def test_execute_remote_with_version_and_platform
+ original_platforms = Gem.platforms.dup
+
+ spec_fetcher do |fetcher|
+ fetcher.spec 'foo', "1"
+ fetcher.spec 'foo', "1" do |s|
+ s.platform = 'x86_64-linux'
+ end
+ end
+
+ @cmd.options[:args] = %w[foo]
+ @cmd.options[:version] = "1"
+ @cmd.options[:domain] = :remote
+ @cmd.options[:added_platform] = true
+ Gem.platforms = [Gem::Platform::RUBY, Gem::Platform.new("x86_64-linux")]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ spec = Gem::Specification.from_yaml @ui.output
+
+ assert_equal Gem::Version.new("1"), spec.version
+ assert_equal Gem::Platform.new("x86_64-linux"), spec.platform
+ ensure
+ Gem.platforms = original_platforms
+ end
+
def test_execute_remote_without_prerelease
spec_fetcher do |fetcher|
fetcher.spec 'foo', '2.0.0'
@@ -200,10 +227,10 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|\A--- !ruby/object:Gem::Specification|, @ui.output
- assert_match %r|name: foo|, @ui.output
+ assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output
+ assert_match %r{name: foo}, @ui.output
- spec = YAML.load @ui.output
+ spec = load_yaml @ui.output
assert_equal Gem::Version.new("2.0.0"), spec.version
end
@@ -222,10 +249,10 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|\A--- !ruby/object:Gem::Specification|, @ui.output
- assert_match %r|name: foo|, @ui.output
+ assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output
+ assert_match %r{name: foo}, @ui.output
- spec = YAML.load @ui.output
+ spec = load_yaml @ui.output
assert_equal Gem::Version.new("2.0.1.pre"), spec.version
end
@@ -242,9 +269,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r|Gem::Specification.new|, @ui.output
- assert_match %r|s.name = "foo"|, @ui.output
+ assert_match %r{Gem::Specification.new}, @ui.output
+ assert_match %r{s.name = "foo"}, @ui.output
assert_equal '', @ui.error
end
-
end
diff --git a/test/rubygems/test_gem_commands_stale_command.rb b/test/rubygems/test_gem_commands_stale_command.rb
index a8909c6d13..83bd3e5def 100644
--- a/test/rubygems/test_gem_commands_stale_command.rb
+++ b/test/rubygems/test_gem_commands_stale_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/stale_command'
class TestGemCommandsStaleCommand < Gem::TestCase
-
def setup
super
@stub_ui = Gem::MockGemUi.new
@@ -40,5 +39,4 @@ class TestGemCommandsStaleCommand < Gem::TestCase
assert_equal("#{foo_bar.name}-#{foo_bar.version}", lines[0].split.first)
assert_equal("#{bar_baz.name}-#{bar_baz.version}", lines[1].split.first)
end
-
end
diff --git a/test/rubygems/test_gem_commands_uninstall_command.rb b/test/rubygems/test_gem_commands_uninstall_command.rb
index c3582390f9..5bd2c40d59 100644
--- a/test/rubygems/test_gem_commands_uninstall_command.rb
+++ b/test/rubygems/test_gem_commands_uninstall_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/installer_test_case'
+require_relative 'installer_test_case'
require 'rubygems/commands/uninstall_command'
class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
-
def setup
super
@cmd = Gem::Commands::UninstallCommand.new
@@ -378,7 +377,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
@cmd.options[:args] = ['a:4']
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
use_ui ui do
@cmd.execute
end
@@ -421,7 +420,7 @@ WARNING: Use your OS package manager to uninstall vendor gems
@cmd.options[:version] = Gem::Requirement.new("> 1")
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
@@ -437,7 +436,7 @@ WARNING: Use your OS package manager to uninstall vendor gems
def test_handle_options_vendor_missing
vendordir(nil) do
- e = assert_raises OptionParser::InvalidOption do
+ e = assert_raise Gem::OptionParser::InvalidOption do
@cmd.handle_options %w[--vendor]
end
@@ -478,7 +477,7 @@ WARNING: Use your OS package manager to uninstall vendor gems
e = nil
@cmd.stub :uninstall, uninstall_exception do
use_ui @ui do
- e = assert_raises Gem::MockGemUi::TermError do
+ e = assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
@@ -487,7 +486,7 @@ WARNING: Use your OS package manager to uninstall vendor gems
end
assert_empty @ui.output
- assert_match %r!Error: unable to successfully uninstall '#{@spec.name}'!, @ui.error
+ assert_match %r{Error: unable to successfully uninstall '#{@spec.name}'}, @ui.error
end
private
@@ -502,5 +501,4 @@ WARNING: Use your OS package manager to uninstall vendor gems
end
end
end
-
end
diff --git a/test/rubygems/test_gem_commands_unpack_command.rb b/test/rubygems/test_gem_commands_unpack_command.rb
index 7d96caaf57..55369f1eeb 100644
--- a/test/rubygems/test_gem_commands_unpack_command.rb
+++ b/test/rubygems/test_gem_commands_unpack_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/unpack_command'
class TestGemCommandsUnpackCommand < Gem::TestCase
-
def setup
super
@@ -152,7 +151,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
def test_execute_sudo
- skip 'Cannot perform this test on windows (chmod)' if win_platform?
+ pend 'Cannot perform this test on windows (chmod)' if win_platform?
util_make_gems
@@ -211,7 +210,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
end
- assert_path_exists File.join(@tempdir, foo_spec.full_name)
+ assert_path_exist File.join(@tempdir, foo_spec.full_name)
end
def test_handle_options_metadata
@@ -221,5 +220,4 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
assert @cmd.options[:spec]
end
-
end
diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb
index 37f990ea1a..a7ddddf2c1 100644
--- a/test/rubygems/test_gem_commands_update_command.rb
+++ b/test/rubygems/test_gem_commands_update_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/update_command'
class TestGemCommandsUpdateCommand < Gem::TestCase
-
def setup
super
common_installer_setup
@@ -96,7 +95,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
@cmd.options[:args] = []
@cmd.options[:system] = true
- assert_raises Gem::MockGemUi::SystemExitException do
+ assert_raise Gem::MockGemUi::SystemExitException do
use_ui @ui do
@cmd.execute
end
@@ -159,6 +158,91 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
assert_empty out
end
+ def test_execute_system_specific_older_than_minimum_supported_rubygems
+ spec_fetcher do |fetcher|
+ fetcher.download 'rubygems-update', "2.5.1" do |s|
+ s.files = %w[setup.rb]
+ end
+ end
+
+ @cmd.options[:args] = []
+ @cmd.options[:system] = "2.5.1"
+
+ oldest_version_mod = Module.new do
+ def oldest_supported_version
+ Gem::Version.new("2.5.2")
+ end
+ private :oldest_supported_version
+ end
+
+ @cmd.extend(oldest_version_mod)
+
+ assert_raise Gem::MockGemUi::TermError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_empty @ui.output
+ assert_equal "ERROR: rubygems 2.5.1 is not supported on #{RUBY_VERSION}. The oldest version supported by this ruby is 2.5.2\n", @ui.error
+ end
+
+ def test_execute_system_specific_older_than_3_2_removes_plugins_dir
+ spec_fetcher do |fetcher|
+ fetcher.download 'rubygems-update', 3.1 do |s|
+ s.files = %w[setup.rb]
+ end
+ end
+
+ oldest_version_mod = Module.new do
+ def oldest_supported_version
+ Gem::Version.new("2.5.2")
+ end
+ private :oldest_supported_version
+ end
+
+ @cmd.extend(oldest_version_mod)
+
+ @cmd.options[:args] = []
+ @cmd.options[:system] = "3.1"
+
+ FileUtils.mkdir_p Gem.plugindir
+ write_file File.join(Gem.plugindir, 'a_plugin.rb')
+
+ @cmd.execute
+
+ assert_path_not_exist Gem.plugindir, "Plugins folder not removed when updating rubygems to pre-3.2"
+ end
+
+ def test_execute_system_specific_newer_than_or_equal_to_3_2_leaves_plugins_dir_alone
+ spec_fetcher do |fetcher|
+ fetcher.download 'rubygems-update', "3.2.a" do |s|
+ s.files = %w[setup.rb]
+ end
+ end
+
+ oldest_version_mod = Module.new do
+ def oldest_supported_version
+ Gem::Version.new("2.5.2")
+ end
+ private :oldest_supported_version
+ end
+
+ @cmd.extend(oldest_version_mod)
+
+ @cmd.options[:args] = []
+ @cmd.options[:system] = "3.2.a"
+
+ FileUtils.mkdir_p Gem.plugindir
+ plugin_file = File.join(Gem.plugindir, 'a_plugin.rb')
+ write_file plugin_file
+
+ @cmd.execute
+
+ assert_path_exist Gem.plugindir, "Plugin folder removed when updating rubygems to post-3.2"
+ assert_path_exist plugin_file, "Plugin removed when updating rubygems to post-3.2"
+ end
+
def test_execute_system_specifically_to_latest_version
spec_fetcher do |fetcher|
fetcher.download 'rubygems-update', 8 do |s|
@@ -189,7 +273,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
@cmd.options[:args] = %w[gem]
@cmd.options[:system] = true
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@cmd.execute
end
@@ -200,6 +284,53 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
@ui.error
end
+ def test_execute_system_with_disabled_update
+ old_disable_system_update_message = Gem.disable_system_update_message
+ Gem.disable_system_update_message = "Please use package manager instead."
+
+ @cmd.options[:args] = []
+ @cmd.options[:system] = true
+
+ assert_raise Gem::MockGemUi::TermError do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_empty @ui.output
+ assert_equal "ERROR: Please use package manager instead.\n", @ui.error
+ ensure
+ Gem.disable_system_update_message = old_disable_system_update_message
+ end
+
+ # The other style of `gem update --system` tests don't actually run
+ # setup.rb, so we just check that setup.rb gets the `--silent` flag.
+ def test_execute_system_silent_passed_to_setuprb
+ @cmd.options[:args] = []
+ @cmd.options[:system] = true
+ @cmd.options[:silent] = true
+
+ assert_equal true, @cmd.update_rubygems_arguments.include?('--silent')
+ end
+
+ def test_execute_system_silent
+ spec_fetcher do |fetcher|
+ fetcher.download 'rubygems-update', 9 do |s|
+ s.files = %w[setup.rb]
+ end
+ end
+
+ @cmd.options[:args] = []
+ @cmd.options[:system] = true
+ @cmd.options[:silent] = true
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_empty @ui.output
+ end
+
# before:
# a1 -> c1.2
# after:
@@ -253,7 +384,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
a2 = @specs['a-2']
- assert_path_exists File.join(a2.doc_dir, 'rdoc')
+ assert_path_exist File.join(a2.doc_dir, 'rdoc')
end
def test_execute_named
@@ -359,10 +490,10 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
def test_execute_user_install
- spec_fetcher do |fetcher|
- fetcher.download 'a', 2
- fetcher.spec 'a', 1
- end
+ a = util_spec "a", 1
+ b = util_spec "b", 1
+ install_gem_user(a)
+ install_gem(b)
@cmd.handle_options %w[--user-install]
@@ -373,7 +504,13 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
installer = @cmd.installer
user_install = installer.instance_variable_get :@user_install
- assert user_install, 'user_install must be set on the installer'
+ assert user_install, "user_install must be set on the installer"
+
+ out = @ui.output.split "\n"
+ assert_equal "Updating installed gems", out.shift
+ assert_equal "Updating a", out.shift
+ assert_equal "Gems updated: a", out.shift
+ assert_empty out
end
def test_fetch_remote_gems
@@ -393,7 +530,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_fetch_remote_gems_error
Gem.sources.replace %w[http://nonexistent.example]
- assert_raises Gem::RemoteFetcher::FetchError do
+ assert_raise Gem::RemoteFetcher::FetchError do
@cmd.fetch_remote_gems @specs['a-1']
end
end
@@ -451,7 +588,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
def test_handle_options_system_non_version
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
@cmd.handle_options %w[--system non-version]
end
end
@@ -584,5 +721,4 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
assert_equal " a-2", out.shift
assert_empty out
end
-
end
diff --git a/test/rubygems/test_gem_commands_which_command.rb b/test/rubygems/test_gem_commands_which_command.rb
index 0d63bb9b37..a398dc5708 100644
--- a/test/rubygems/test_gem_commands_which_command.rb
+++ b/test/rubygems/test_gem_commands_which_command.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/which_command'
class TestGemCommandsWhichCommand < Gem::TestCase
-
def setup
super
Gem::Specification.reset
@@ -27,13 +26,13 @@ class TestGemCommandsWhichCommand < Gem::TestCase
@cmd.handle_options %w[directory]
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
assert_equal '', @ui.output
- assert_match %r%Can.t find Ruby library file or shared library directory\n%,
+ assert_match %r{Can.t find Ruby library file or shared library directory\n},
@ui.error
end
@@ -45,13 +44,13 @@ class TestGemCommandsWhichCommand < Gem::TestCase
@cmd.handle_options %w[foo_bar missinglib]
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
assert_equal "#{@foo_bar.full_gem_path}/lib/foo_bar.rb\n", @ui.output
- assert_match %r%Can.t find Ruby library file or shared library missinglib\n%,
+ assert_match %r{Can.t find Ruby library file or shared library missinglib\n},
@ui.error
end
@@ -59,13 +58,13 @@ class TestGemCommandsWhichCommand < Gem::TestCase
@cmd.handle_options %w[missinglib]
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
end
assert_equal '', @ui.output
- assert_match %r%Can.t find Ruby library file or shared library missinglib\n%,
+ assert_match %r{Can.t find Ruby library file or shared library missinglib\n},
@ui.error
end
@@ -82,5 +81,4 @@ class TestGemCommandsWhichCommand < Gem::TestCase
FileUtils.touch filename
end
end
-
end
diff --git a/test/rubygems/test_gem_commands_yank_command.rb b/test/rubygems/test_gem_commands_yank_command.rb
index 1aafc92bfb..b798eb3689 100644
--- a/test/rubygems/test_gem_commands_yank_command.rb
+++ b/test/rubygems/test_gem_commands_yank_command.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/commands/yank_command'
class TestGemCommandsYankCommand < Gem::TestCase
-
def setup
super
+ credential_setup
+
@cmd = Gem::Commands::YankCommand.new
@cmd.options[:host] = 'http://example'
@@ -16,6 +17,12 @@ class TestGemCommandsYankCommand < Gem::TestCase
Gem.configuration.api_keys[:KEY] = 'other'
end
+ def teardown
+ credential_teardown
+
+ super
+ end
+
def test_handle_options
@cmd.handle_options %w[a --version 1.0 --platform x86-darwin -k KEY --host HOST]
@@ -28,7 +35,7 @@ class TestGemCommandsYankCommand < Gem::TestCase
def test_handle_options_missing_argument
%w[-v --version -p --platform].each do |option|
- assert_raises OptionParser::MissingArgument do
+ assert_raise Gem::OptionParser::MissingArgument do
@cmd.handle_options %W[a #{option}]
end
end
@@ -46,8 +53,8 @@ class TestGemCommandsYankCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r%Yanking gem from http://example%, @ui.output
- assert_match %r%Successfully yanked%, @ui.output
+ assert_match %r{Yanking gem from http://example}, @ui.output
+ assert_match %r{Successfully yanked}, @ui.output
platform = Gem.platforms[1]
body = @fetcher.last_request.body.split('&').sort
@@ -63,7 +70,7 @@ class TestGemCommandsYankCommand < Gem::TestCase
yank_uri = 'http://example/api/v1/gems/yank'
@fetcher.data[yank_uri] = [
[response_fail, 401, 'Unauthorized'],
- ['Successfully yanked', 200, 'OK']
+ ['Successfully yanked', 200, 'OK'],
]
@cmd.options[:args] = %w[a]
@@ -77,8 +84,8 @@ class TestGemCommandsYankCommand < Gem::TestCase
assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output
assert_match 'Code: ', @otp_ui.output
- assert_match %r%Yanking gem from http://example%, @otp_ui.output
- assert_match %r%Successfully yanked%, @otp_ui.output
+ assert_match %r{Yanking gem from http://example}, @otp_ui.output
+ assert_match %r{Successfully yanked}, @otp_ui.output
assert_equal '111111', @fetcher.last_request['OTP']
end
@@ -132,8 +139,8 @@ class TestGemCommandsYankCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r%Yanking gem from https://other.example%, @ui.output
- assert_match %r%Successfully yanked%, @ui.output
+ assert_match %r{Yanking gem from https://other.example}, @ui.output
+ assert_match %r{Successfully yanked}, @ui.output
body = @fetcher.last_request.body.split('&').sort
assert_equal %w[gem_name=a version=1.0], body
@@ -141,4 +148,33 @@ class TestGemCommandsYankCommand < Gem::TestCase
assert_equal [yank_uri], @fetcher.paths
end
+ def test_yank_gem_unathorized_api_key
+ response_forbidden = "The API key doesn't have access"
+ response_success = 'Successfully yanked'
+ host = 'http://example'
+
+ @fetcher.data["#{host}/api/v1/gems/yank"] = [
+ [response_forbidden, 403, 'Forbidden'],
+ [response_success, 200, "OK"],
+ ]
+
+ @fetcher.data["#{host}/api/v1/api_key"] = ["", 200, "OK"]
+ @cmd.options[:args] = %w[a]
+ @cmd.options[:added_platform] = true
+ @cmd.options[:version] = req('= 1.0')
+ @cmd.instance_variable_set :@host, host
+ @cmd.instance_variable_set :@scope, :yank_rubygem
+
+ @ui = Gem::MockGemUi.new "some@mail.com\npass\n"
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ access_notice = "The existing key doesn't have access of yank_rubygem on http://example. Please sign in to update access."
+ assert_match access_notice, @ui.output
+ assert_match "Email:", @ui.output
+ assert_match "Password:", @ui.output
+ assert_match "Added yank_rubygem scope to the existing API key", @ui.output
+ assert_match response_success, @ui.output
+ end
end
diff --git a/test/rubygems/test_gem_config_file.rb b/test/rubygems/test_gem_config_file.rb
index 492a0c5a05..32375e6936 100644
--- a/test/rubygems/test_gem_config_file.rb
+++ b/test/rubygems/test_gem_config_file.rb
@@ -1,20 +1,17 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/config_file'
class TestGemConfigFile < Gem::TestCase
-
def setup
super
+ credential_setup
+
@temp_conf = File.join @tempdir, '.gemrc'
@cfg_args = %W[--config-file #{@temp_conf}]
- @orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE
- Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
- Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
- File.join(@tempdir, 'system-gemrc')
Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear
Gem::ConfigFile::PLATFORM_DEFAULTS.clear
@@ -27,12 +24,11 @@ class TestGemConfigFile < Gem::TestCase
def teardown
Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear
Gem::ConfigFile::PLATFORM_DEFAULTS.clear
- Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
- Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
- @orig_SYSTEM_WIDE_CONFIG_FILE
ENV['GEMRC'] = @env_gemrc
+ credential_teardown
+
super
end
@@ -45,6 +41,7 @@ class TestGemConfigFile < Gem::TestCase
assert_equal true, @cfg.verbose
assert_equal [@gem_repo], Gem.sources
assert_equal 365, @cfg.cert_expiration_length_days
+ assert_equal false, @cfg.ipv4_fallback_enabled
File.open @temp_conf, 'w' do |fp|
fp.puts ":backtrace: true"
@@ -60,6 +57,7 @@ class TestGemConfigFile < Gem::TestCase
fp.puts ":ssl_verify_mode: 0"
fp.puts ":ssl_ca_cert: /etc/ssl/certs"
fp.puts ":cert_expiration_length_days: 28"
+ fp.puts ":ipv4_fallback_enabled: true"
end
util_config_file
@@ -74,6 +72,14 @@ class TestGemConfigFile < Gem::TestCase
assert_equal 0, @cfg.ssl_verify_mode
assert_equal '/etc/ssl/certs', @cfg.ssl_ca_cert
assert_equal 28, @cfg.cert_expiration_length_days
+ assert_equal true, @cfg.ipv4_fallback_enabled
+ end
+
+ def test_initialize_ipv4_fallback_enabled_env
+ ENV['IPV4_FALLBACK_ENABLED'] = 'true'
+ util_config_file %W[--config-file #{@temp_conf}]
+
+ assert_equal true, @cfg.ipv4_fallback_enabled
end
def test_initialize_handle_arguments_config_file
@@ -177,7 +183,7 @@ class TestGemConfigFile < Gem::TestCase
assert_nil @cfg.instance_variable_get :@api_keys
temp_cred = File.join Gem.user_home, '.gem', 'credentials'
- FileUtils.mkdir File.dirname(temp_cred)
+ FileUtils.mkdir_p File.dirname(temp_cred)
File.open temp_cred, 'w', 0600 do |fp|
fp.puts ':rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97'
end
@@ -189,14 +195,14 @@ class TestGemConfigFile < Gem::TestCase
end
def test_check_credentials_permissions
- skip 'chmod not supported' if win_platform?
+ pend 'chmod not supported' if win_platform?
@cfg.rubygems_api_key = 'x'
File.chmod 0644, @cfg.credentials_path
use_ui @ui do
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cfg.load_api_keys
end
end
@@ -247,7 +253,7 @@ if you believe they were disclosed to a third party.
args = %w[--debug]
- _, err = capture_io do
+ _, err = capture_output do
@cfg.handle_arguments args
end
@@ -303,7 +309,7 @@ if you believe they were disclosed to a third party.
def test_load_api_keys
temp_cred = File.join Gem.user_home, '.gem', 'credentials'
- FileUtils.mkdir File.dirname(temp_cred)
+ FileUtils.mkdir_p File.dirname(temp_cred)
File.open temp_cred, 'w', 0600 do |fp|
fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97"
fp.puts ":other: a5fdbb6ba150cbb83aad2bb2fede64c"
@@ -316,13 +322,13 @@ if you believe they were disclosed to a third party.
end
def test_load_api_keys_bad_permission
- skip 'chmod not supported' if win_platform?
+ pend 'chmod not supported' if win_platform?
@cfg.rubygems_api_key = 'x'
File.chmod 0644, @cfg.credentials_path
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cfg.load_api_keys
end
end
@@ -348,7 +354,7 @@ if you believe they were disclosed to a third party.
:rubygems_api_key => 'x',
}
- assert_equal expected, YAML.load_file(@cfg.credentials_path)
+ assert_equal expected, load_yaml_file(@cfg.credentials_path)
unless win_platform?
stat = File.stat @cfg.credentials_path
@@ -358,13 +364,13 @@ if you believe they were disclosed to a third party.
end
def test_rubygems_api_key_equals_bad_permission
- skip 'chmod not supported' if win_platform?
+ pend 'chmod not supported' if win_platform?
@cfg.rubygems_api_key = 'x'
File.chmod 0644, @cfg.credentials_path
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cfg.rubygems_api_key = 'y'
end
@@ -372,7 +378,7 @@ if you believe they were disclosed to a third party.
:rubygems_api_key => 'x',
}
- assert_equal expected, YAML.load_file(@cfg.credentials_path)
+ assert_equal expected, load_yaml_file(@cfg.credentials_path)
stat = File.stat @cfg.credentials_path
@@ -392,7 +398,7 @@ if you believe they were disclosed to a third party.
util_config_file
# These should not be written out to the config file.
- assert_equal false, @cfg.backtrace, 'backtrace'
+ assert_equal false, @cfg.backtrace, 'backtrace'
assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold,
'bulk_threshold'
assert_equal true, @cfg.update_sources, 'update_sources'
@@ -495,5 +501,4 @@ if you believe they were disclosed to a third party.
util_config_file
assert_equal(true, @cfg.disable_default_gem_server)
end
-
end
diff --git a/test/rubygems/test_gem_dependency.rb b/test/rubygems/test_gem_dependency.rb
index 0caab10d32..1ca0fc378c 100644
--- a/test/rubygems/test_gem_dependency.rb
+++ b/test/rubygems/test_gem_dependency.rb
@@ -1,8 +1,13 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/dependency'
class TestGemDependency < Gem::TestCase
+ def setup
+ super
+
+ without_any_upwards_gemfiles
+ end
def test_initialize
d = dep "pkg", "> 1.0"
@@ -12,7 +17,7 @@ class TestGemDependency < Gem::TestCase
end
def test_initialize_type_bad
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
Gem::Dependency.new 'monkey' => '1.0'
end
@@ -44,7 +49,7 @@ class TestGemDependency < Gem::TestCase
assert_equal :runtime, dep("pkg").type
assert_equal :development, dep("pkg", [], :development).type
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
dep "pkg", :sometimes
end
end
@@ -249,7 +254,7 @@ class TestGemDependency < Gem::TestCase
a = dep 'a'
b = dep 'b'
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
a.merge b
end
@@ -331,7 +336,7 @@ class TestGemDependency < Gem::TestCase
dep = Gem::Dependency.new "a", "= 2.0"
- e = assert_raises Gem::MissingSpecVersionError do
+ e = assert_raise Gem::MissingSpecVersionError do
dep.to_specs
end
@@ -354,7 +359,7 @@ class TestGemDependency < Gem::TestCase
assert_equal [b, b_1], dep.to_specs
Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["3.5", "reason"]) do
- e = assert_raises Gem::MissingSpecVersionError do
+ e = assert_raise Gem::MissingSpecVersionError do
dep.to_specs
end
@@ -378,7 +383,7 @@ class TestGemDependency < Gem::TestCase
dep = Gem::Dependency.new "b", "= 2.0"
- e = assert_raises Gem::MissingSpecError do
+ e = assert_raise Gem::MissingSpecError do
dep.to_specs
end
@@ -391,5 +396,4 @@ class TestGemDependency < Gem::TestCase
assert_equal dep("a", " >= 1.a").identity, :abs_latest
assert_equal dep("a").identity, :latest
end
-
end
diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb
index 22f3a9158f..9cbdcefea4 100644
--- a/test/rubygems/test_gem_dependency_installer.rb
+++ b/test/rubygems/test_gem_dependency_installer.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/dependency_installer'
require 'rubygems/security'
class TestGemDependencyInstaller < Gem::TestCase
-
def setup
super
common_installer_setup
@@ -45,70 +44,7 @@ class TestGemDependencyInstaller < Gem::TestCase
s.add_development_dependency 'c'
end
- util_reset_gems
- end
-
- def test_available_set_for_name
- util_setup_gems
- p1a, = util_gem 'a', '10.a'
- util_setup_spec_fetcher p1a, @a1, @a1_pre
-
- inst = Gem::DependencyInstaller.new
-
- available = Gem::Deprecate.skip_during do
- inst.available_set_for 'a', Gem::Requirement.default
- end
-
- assert_equal %w[a-1], available.set.map { |s| s.spec.full_name }
- end
-
- def test_available_set_for_name_prerelease
- util_setup_gems
- p1a, = util_gem 'a', '10.a'
- util_setup_spec_fetcher p1a, @a1, @a1_pre
-
- inst = Gem::DependencyInstaller.new :prerelease => true
-
- available = Gem::Deprecate.skip_during do
- inst.available_set_for 'a', Gem::Requirement.default
- end
-
- assert_equal %w[a-10.a],
- available.sorted.map { |s| s.spec.full_name }
- end
-
- def test_available_set_for_dep
- util_setup_gems
- p1a, = util_gem 'a', '10.a'
- util_setup_spec_fetcher p1a, @a1, @a1_pre
-
- inst = Gem::DependencyInstaller.new
-
- dep = Gem::Dependency.new 'a', Gem::Requirement.default
-
- available = Gem::Deprecate.skip_during do
- inst.available_set_for dep, Gem::Requirement.default
- end
-
- assert_equal %w[a-1], available.set.map { |s| s.spec.full_name }
- end
-
- def test_available_set_for_dep_prerelease
- util_setup_gems
- p1a, = util_gem 'a', '10.a'
- util_setup_spec_fetcher p1a, @a1, @a1_pre
-
- inst = Gem::DependencyInstaller.new :prerelease => true
-
- dep = Gem::Dependency.new 'a', Gem::Requirement.default
- dep.prerelease = true
-
- available = Gem::Deprecate.skip_during do
- inst.available_set_for dep, Gem::Requirement.default
- end
-
- assert_equal %w[a-10.a],
- available.sorted.map { |s| s.spec.full_name }
+ util_setup_spec_fetcher(@a1, @a1_pre, @b1, @d1)
end
def test_install
@@ -177,7 +113,7 @@ class TestGemDependencyInstaller < Gem::TestCase
dep = Gem::Dependency.new "p"
inst = Gem::DependencyInstaller.new
- assert_raises Gem::UnsatisfiableDependencyError do
+ assert_raise Gem::UnsatisfiableDependencyError do
inst.install dep
end
@@ -211,7 +147,7 @@ class TestGemDependencyInstaller < Gem::TestCase
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
- FileUtils.mv e1_gem, @tempdir
+ FileUtils.mv e1_gem, @tempdir
inst = nil
@@ -220,7 +156,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name },
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name },
'sanity check'
Dir.chdir @tempdir do
@@ -228,7 +164,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'e'
end
- assert_equal %w[a-1 e-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 e-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_cache_dir
@@ -245,7 +181,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name }
assert File.exist? File.join(@gemhome, "cache", @a1.file_name)
assert File.exist? File.join(@gemhome, "cache", @b1.file_name)
@@ -270,7 +206,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'a', req("= 2")
end
- assert_equal %w[a-2], inst.installed_gems.map { |s| s.full_name },
+ assert_equal %w[a-2], inst.installed_gems.map {|s| s.full_name },
'sanity check'
FileUtils.rm File.join(@tempdir, a2.file_name)
@@ -281,7 +217,7 @@ class TestGemDependencyInstaller < Gem::TestCase
end
assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name)
- assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
end
# This asserts that if a gem's dependency is satisfied by an
@@ -302,7 +238,7 @@ class TestGemDependencyInstaller < Gem::TestCase
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv a2_gem, @tempdir # not in index
FileUtils.mv @b1_gem, @tempdir
- FileUtils.mv a3_gem, @tempdir
+ FileUtils.mv a3_gem, @tempdir
Dir.chdir @tempdir do
Gem::DependencyInstaller.new.install 'a', req("= 2")
@@ -318,7 +254,7 @@ class TestGemDependencyInstaller < Gem::TestCase
end
assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name)
- assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_dependency
@@ -341,7 +277,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name }
assert done_installing_ran, 'post installs hook was not run'
end
@@ -351,8 +287,6 @@ class TestGemDependencyInstaller < Gem::TestCase
@aa1, @aa1_gem = util_gem 'aa', '1'
- util_reset_gems
-
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
@@ -363,7 +297,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_dependency_development_deep
@@ -371,8 +305,6 @@ class TestGemDependencyInstaller < Gem::TestCase
@aa1, @aa1_gem = util_gem 'aa', '1'
- util_reset_gems
-
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
@@ -385,7 +317,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'd'
end
- assert_equal %w[a-1 aa-1 b-1 c-1 d-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 aa-1 b-1 c-1 d-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_dependency_development_shallow
@@ -393,8 +325,6 @@ class TestGemDependencyInstaller < Gem::TestCase
@aa1, @aa1_gem = util_gem 'aa', '1'
- util_reset_gems
-
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
@@ -407,7 +337,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'd'
end
- assert_equal %w[c-1 d-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[c-1 d-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_dependency_existing
@@ -423,7 +353,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_dependency_existing_extension
@@ -440,7 +370,7 @@ class TestGemDependencyInstaller < Gem::TestCase
e1 = util_spec 'e', '1', nil, 'extconf.rb' do |s|
s.extensions << 'extconf.rb'
end
- e1_gem = File.join @tempdir, 'gems', "#{e1.full_name}.gem"
+ e1_gem = e1.cache_file
_, f1_gem = util_gem 'f', '1', 'e' => nil
@@ -460,9 +390,9 @@ class TestGemDependencyInstaller < Gem::TestCase
Dir.chdir pwd
end
- assert_equal %w[f-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[f-1], inst.installed_gems.map {|s| s.full_name }
- assert_path_exists e1.extension_dir
+ assert_path_exist e1.extension_dir
end
def test_install_dependency_old
@@ -480,7 +410,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'f'
end
- assert_equal %w[f-2], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[f-2], inst.installed_gems.map {|s| s.full_name }
end
def test_install_local
@@ -494,7 +424,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'a-1.gem'
end
- assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_local_prerelease
@@ -508,7 +438,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'a-1.a.gem'
end
- assert_equal %w[a-1.a], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1.a], inst.installed_gems.map {|s| s.full_name }
end
def test_install_local_dependency
@@ -524,7 +454,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b-1.gem'
end
- assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_local_dependency_installed
@@ -542,7 +472,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b-1.gem'
end
- assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_local_subdir
@@ -555,7 +485,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'gems/a-1.gem'
end
- assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_minimal_deps
@@ -581,7 +511,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b', req('= 1')
end
- assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name },
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name },
'sanity check'
Dir.chdir @tempdir do
@@ -589,7 +519,41 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'e'
end
- assert_equal %w[a-1 e-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 e-1], inst.installed_gems.map {|s| s.full_name }
+ end
+
+ def test_install_no_minimal_deps
+ util_setup_gems
+
+ _, e1_gem = util_gem 'e', '1' do |s|
+ s.add_dependency 'b'
+ end
+
+ _, b2_gem = util_gem 'b', '2' do |s|
+ s.add_dependency 'a'
+ end
+
+ FileUtils.mv @a1_gem, @tempdir
+ FileUtils.mv @b1_gem, @tempdir
+ FileUtils.mv b2_gem, @tempdir
+ FileUtils.mv e1_gem, @tempdir
+
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :ignore_dependencies => true
+ inst.install 'b', req('= 1')
+ end
+
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name },
+ 'sanity check'
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new :minimal_deps => false
+ inst.install 'e'
+ end
+
+ assert_equal %w[a-1 b-2 e-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_no_document
@@ -622,7 +586,7 @@ class TestGemDependencyInstaller < Gem::TestCase
env = "/\\S+/env" unless Gem.win_platform?
- assert_match %r|\A#!#{env} #{RbConfig::CONFIG['ruby_install_name']}\n|,
+ assert_match %r{\A#!#{env} #{RbConfig::CONFIG['ruby_install_name']}\n},
File.read(File.join(@gemhome, 'bin', 'a_bin'))
end
@@ -639,7 +603,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_build_args
@@ -669,7 +633,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_install_dir
@@ -690,7 +654,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name }
assert File.exist?(File.join(gemhome2, 'specifications', @a1.spec_name))
assert File.exist?(File.join(gemhome2, 'cache', @a1.file_name))
@@ -714,7 +678,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name }
a1, b1 = inst.installed_gems
assert_equal a1.spec_file, a1.loaded_from
@@ -738,7 +702,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_domain_local
@@ -748,7 +712,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- e = assert_raises Gem::UnsatisfiableDependencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
inst = Gem::DependencyInstaller.new :domain => :local
inst.install 'b'
end
@@ -757,7 +721,7 @@ class TestGemDependencyInstaller < Gem::TestCase
assert_equal expected, e.message
end
- assert_equal [], inst.installed_gems.map { |s| s.full_name }
+ assert_equal [], inst.installed_gems.map {|s| s.full_name }
end
def test_install_domain_remote
@@ -773,7 +737,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = Gem::DependencyInstaller.new :domain => :remote
inst.install 'a'
- assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_dual_repository
@@ -790,7 +754,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'a'
end
- assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name },
+ assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name },
'sanity check'
ENV['GEM_HOME'] = @gemhome
@@ -802,7 +766,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'b'
end
- assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_reinstall
@@ -813,7 +777,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new
+ inst = Gem::DependencyInstaller.new :force => true
inst.install 'a'
end
@@ -837,7 +801,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install 'a'
end
- assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_remote_dep
@@ -857,7 +821,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install dep
end
- assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_remote_platform_newer
@@ -890,7 +854,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = Gem::DependencyInstaller.new :domain => :remote
inst.install 'a'
- assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_platform_is_ignored_when_a_file_is_specified
@@ -901,30 +865,32 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = Gem::DependencyInstaller.new :domain => :local
inst.install a_gem
- assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map {|s| s.full_name }
end
- if defined? OpenSSL
+ require 'rubygems/openssl'
+
+ if Gem::HAVE_OPENSSL
def test_install_security_policy
util_setup_gems
- data = File.open(@a1_gem, 'rb') { |f| f.read }
+ data = File.open(@a1_gem, 'rb') {|f| f.read }
@fetcher.data['http://gems.example.com/gems/a-1.gem'] = data
- data = File.open(@b1_gem, 'rb') { |f| f.read }
+ data = File.open(@b1_gem, 'rb') {|f| f.read }
@fetcher.data['http://gems.example.com/gems/b-1.gem'] = data
policy = Gem::Security::HighSecurity
inst = Gem::DependencyInstaller.new :security_policy => policy
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
inst.install 'b'
end
assert_equal 'unsigned gems are not allowed by the High Security policy',
e.message
- assert_equal %w[], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[], inst.installed_gems.map {|s| s.full_name }
end
end
@@ -938,7 +904,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = Gem::DependencyInstaller.new :wrappers => false, :format_executable => false
inst.install 'a'
- refute_match(%r|This file was generated by RubyGems.|,
+ refute_match(%r{This file was generated by RubyGems.},
File.read(File.join(@gemhome, 'bin', 'a_bin')))
end
end
@@ -946,126 +912,102 @@ class TestGemDependencyInstaller < Gem::TestCase
def test_install_version
util_setup_d
- data = File.open(@d2_gem, 'rb') { |f| f.read }
+ data = File.open(@d2_gem, 'rb') {|f| f.read }
@fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
- data = File.open(@d1_gem, 'rb') { |f| f.read }
+ data = File.open(@d1_gem, 'rb') {|f| f.read }
@fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
inst = Gem::DependencyInstaller.new
inst.install 'd', '= 1'
- assert_equal %w[d-1], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[d-1], inst.installed_gems.map {|s| s.full_name }
end
def test_install_version_default
util_setup_d
- data = File.open(@d2_gem, 'rb') { |f| f.read }
+ data = File.open(@d2_gem, 'rb') {|f| f.read }
@fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
- data = File.open(@d1_gem, 'rb') { |f| f.read }
+ data = File.open(@d1_gem, 'rb') {|f| f.read }
@fetcher.data['http://gems.example.com/gems/d-1.gem'] = data
inst = Gem::DependencyInstaller.new
inst.install 'd'
- assert_equal %w[d-2], inst.installed_gems.map { |s| s.full_name }
+ assert_equal %w[d-2], inst.installed_gems.map {|s| s.full_name }
end
- def test_find_gems_gems_with_sources
- util_setup_gems
-
- inst = Gem::DependencyInstaller.new
- dep = Gem::Dependency.new 'b', '>= 0'
-
- Gem::Specification.reset
+ def test_install_legacy_spec_with_nil_required_ruby_version
+ path = File.expand_path "../data/null-required-ruby-version.gemspec.rz", __FILE__
+ spec = Marshal.load Gem.read_binary(path)
+ def spec.validate(*args); end
- set = Gem::Deprecate.skip_during do
- inst.find_gems_with_sources(dep)
- end
+ util_build_gem spec
- assert_kind_of Gem::AvailableSet, set
+ cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
+ FileUtils.mkdir_p File.dirname cache_file
+ FileUtils.mv spec.cache_file, cache_file
- s = set.set.first
+ util_setup_spec_fetcher spec
- assert_equal @b1, s.spec
- assert_equal Gem::Source.new(@gem_repo), s.source
- end
+ data = Gem.read_binary(cache_file)
- def test_find_spec_by_name_and_version_wildcard
- util_gem 'a', 1
- FileUtils.mv 'gems/a-1.gem', @tempdir
+ @fetcher.data['http://gems.example.com/gems/activesupport-1.0.0.gem'] = data
- FileUtils.touch 'rdoc.gem'
+ dep = Gem::Dependency.new 'activesupport'
inst = Gem::DependencyInstaller.new
+ inst.install dep
- available = Gem::Deprecate.skip_during do
- inst.find_spec_by_name_and_version('*.gem')
- end
-
- assert_equal %w[a-1], available.each_spec.map { |spec| spec.full_name }
+ assert_equal %w[activesupport-1.0.0], Gem::Specification.map(&:full_name)
end
- def test_find_spec_by_name_and_version_wildcard_bad_gem
- FileUtils.touch 'rdoc.gem'
+ def test_install_legacy_spec_with_nil_required_rubygems_version
+ path = File.expand_path "../data/null-required-rubygems-version.gemspec.rz", __FILE__
+ spec = Marshal.load Gem.read_binary(path)
+ def spec.validate(*args); end
- inst = Gem::DependencyInstaller.new
+ util_build_gem spec
- assert_raises Gem::Package::FormatError do
- Gem::Deprecate.skip_during do
- inst.find_spec_by_name_and_version '*.gem'
- end
- end
- end
+ cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
+ FileUtils.mkdir_p File.dirname cache_file
+ FileUtils.mv spec.cache_file, cache_file
- def test_find_spec_by_name_and_version_bad_gem
- FileUtils.touch 'rdoc.gem'
+ util_setup_spec_fetcher spec
- inst = Gem::DependencyInstaller.new
+ data = Gem.read_binary(cache_file)
- e = assert_raises Gem::Package::FormatError do
- Gem::Deprecate.skip_during do
- inst.find_spec_by_name_and_version 'rdoc.gem'
- end
- end
-
- full_path = File.join @tempdir, 'rdoc.gem'
- assert_equal "package metadata is missing in #{full_path}", e.message
- end
+ @fetcher.data['http://gems.example.com/gems/activesupport-1.0.0.gem'] = data
- def test_find_spec_by_name_and_version_directory
- Dir.mkdir 'rdoc'
+ dep = Gem::Dependency.new 'activesupport'
inst = Gem::DependencyInstaller.new
+ inst.install dep
- e = assert_raises Gem::SpecificGemNotFoundException do
- Gem::Deprecate.skip_during do
- inst.find_spec_by_name_and_version 'rdoc'
- end
- end
-
- assert_equal "Could not find a valid gem 'rdoc' (>= 0) " +
- "locally or in a repository",
- e.message
+ assert_equal %w[activesupport-1.0.0], Gem::Specification.map(&:full_name)
end
- def test_find_spec_by_name_and_version_file
- FileUtils.touch 'rdoc'
+ def test_find_gems_gems_with_sources
+ util_setup_gems
inst = Gem::DependencyInstaller.new
+ dep = Gem::Dependency.new 'b', '>= 0'
- e = assert_raises Gem::SpecificGemNotFoundException do
- Gem::Deprecate.skip_during do
- inst.find_spec_by_name_and_version 'rdoc'
- end
+ Gem::Specification.reset
+
+ set = Gem::Deprecate.skip_during do
+ inst.find_gems_with_sources(dep)
end
- assert_equal "Could not find a valid gem 'rdoc' (>= 0) " +
- "locally or in a repository",
- e.message
+ assert_kind_of Gem::AvailableSet, set
+
+ s = set.set.first
+
+ assert_equal @b1, s.spec
+ assert_equal Gem::Source.new(@gem_repo), s.source
end
def test_find_gems_with_sources_local
@@ -1109,8 +1051,8 @@ class TestGemDependencyInstaller < Gem::TestCase
releases = set.all_specs
- assert releases.any? { |s| s.name == 'a' and s.version.to_s == '1' }
- refute releases.any? { |s| s.name == 'a' and s.version.to_s == '1.a' }
+ assert releases.any? {|s| s.name == 'a' and s.version.to_s == '1' }
+ refute releases.any? {|s| s.name == 'a' and s.version.to_s == '1.a' }
dependency.prerelease = true
@@ -1168,7 +1110,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = Gem::DependencyInstaller.new
request_set = inst.resolve_dependencies 'b', req('>= 0')
- requests = request_set.sorted_requests.map { |req| req.full_name }
+ requests = request_set.sorted_requests.map {|req| req.full_name }
assert_equal %w[a-1 b-1], requests
end
@@ -1182,7 +1124,7 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = Gem::DependencyInstaller.new :ignore_dependencies => true
request_set = inst.resolve_dependencies 'b', req('>= 0')
- requests = request_set.sorted_requests.map { |req| req.full_name }
+ requests = request_set.sorted_requests.map {|req| req.full_name }
assert request_set.ignore_dependencies
@@ -1199,71 +1141,15 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = Gem::DependencyInstaller.new
request_set = inst.resolve_dependencies 'a-1.gem', req('>= 0')
- requests = request_set.sorted_requests.map { |req| req.full_name }
+ requests = request_set.sorted_requests.map {|req| req.full_name }
assert_equal %w[a-1], requests
end
- def util_write_a1_bin
- write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp|
- fp.puts "#!/usr/bin/ruby"
- end
- end
-
- def util_setup_c1_pre
- @c1_pre, @c1_pre_gem = util_spec 'c', '1.a' do |s|
- s.add_dependency 'a', '1.a'
- s.add_dependency 'b', '1'
- end
-
- util_reset_gems
- end
-
def util_setup_d
@d1, @d1_gem = util_gem 'd', '1'
@d2, @d2_gem = util_gem 'd', '2'
- util_reset_gems
+ util_setup_spec_fetcher(@d1, @d2)
end
-
- def util_setup_wxyz
- @x1_m, @x1_m_gem = util_spec 'x', '1' do |s|
- s.platform = Gem::Platform.new %w[cpu my_platform 1]
- end
-
- @x1_o, @x1_o_gem = util_spec 'x', '1' do |s|
- s.platform = Gem::Platform.new %w[cpu other_platform 1]
- end
-
- @w1, @w1_gem = util_spec 'w', '1', 'x' => nil
-
- @y1, @y1_gem = util_spec 'y', '1'
- @y1_1_p, @y1_1_p_gem = util_spec 'y', '1.1' do |s|
- s.platform = Gem::Platform.new %w[cpu my_platform 1]
- end
-
- @z1, @z1_gem = util_spec 'z', '1', 'y' => nil
-
- util_reset_gems
- end
-
- def util_reset_gems
- @a1 ||= nil
- @b1 ||= nil
- @a1_pre ||= nil
- @c1_pre ||= nil
- @d1 ||= nil
- @d2 ||= nil
- @w1 ||= nil
- @x1_m ||= nil
- @x1_o ||= nil
- @y1 ||= nil
- @y1_1_p ||= nil
- @z1 ||= nil
-
- util_setup_spec_fetcher(*[@a1, @a1_pre, @b1, @c1_pre,
- @d1, @d2, @x1_m, @x1_o, @w1, @y1,
- @y1_1_p, @z1].compact)
- end
-
end
diff --git a/test/rubygems/test_gem_dependency_list.rb b/test/rubygems/test_gem_dependency_list.rb
index 6bf803fe5f..15c50de199 100644
--- a/test/rubygems/test_gem_dependency_list.rb
+++ b/test/rubygems/test_gem_dependency_list.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/dependency_list'
class TestGemDependencyList < Gem::TestCase
-
def setup
super
@@ -53,7 +52,7 @@ class TestGemDependencyList < Gem::TestCase
order = @deplist.dependency_order
- assert_equal %w[d-1 c-1 b-1 a-1], order.map { |s| s.full_name }
+ assert_equal %w[d-1 c-1 b-1 a-1], order.map {|s| s.full_name }
end
def test_dependency_order_circle
@@ -62,7 +61,7 @@ class TestGemDependencyList < Gem::TestCase
order = @deplist.dependency_order
- assert_equal %w[b-1 c-1 a-1], order.map { |s| s.full_name }
+ assert_equal %w[b-1 c-1 a-1], order.map {|s| s.full_name }
end
def test_dependency_order_development
@@ -80,7 +79,7 @@ class TestGemDependencyList < Gem::TestCase
order = deplist.dependency_order
- assert_equal %w[g-1 a-1 f-1 e-1], order.map { |s| s.full_name },
+ assert_equal %w[g-1 a-1 f-1 e-1], order.map {|s| s.full_name },
'development on'
deplist2 = Gem::DependencyList.new
@@ -88,7 +87,7 @@ class TestGemDependencyList < Gem::TestCase
order = deplist2.dependency_order
- assert_equal %w[a-1 g-1 f-1 e-1], order.map { |s| s.full_name },
+ assert_equal %w[a-1 g-1 f-1 e-1], order.map {|s| s.full_name },
'development off'
end
@@ -100,7 +99,7 @@ class TestGemDependencyList < Gem::TestCase
order = @deplist.dependency_order
- assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map { |s| s.full_name },
+ assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map {|s| s.full_name },
'deps of trimmed specs not included'
end
@@ -109,7 +108,7 @@ class TestGemDependencyList < Gem::TestCase
order = @deplist.dependency_order
- assert_equal %w[c-2 a-1], order.map { |s| s.full_name }
+ assert_equal %w[c-2 a-1], order.map {|s| s.full_name }
end
def test_find_name
@@ -134,14 +133,14 @@ class TestGemDependencyList < Gem::TestCase
end
def test_why_not_ok_eh
- assert_equal({}, @deplist.why_not_ok?)
+ assert_equal({}, @deplist.why_not_ok?)
@deplist.add @b2
exp = {
"b" => [
- Gem::Dependency.new("a", ">= 1")
- ]
+ Gem::Dependency.new("a", ">= 1"),
+ ],
}
assert_equal exp, @deplist.why_not_ok?
@@ -162,7 +161,7 @@ class TestGemDependencyList < Gem::TestCase
@deplist.add a, b0, b1
- assert_equal({}, @deplist.why_not_ok?)
+ assert_equal({}, @deplist.why_not_ok?)
end
def test_ok_eh_mismatch
@@ -262,5 +261,4 @@ class TestGemDependencyList < Gem::TestCase
@deplist.add @a1, @a2, @b1, @c2, @d1
end
-
end
diff --git a/test/rubygems/test_gem_dependency_resolution_error.rb b/test/rubygems/test_gem_dependency_resolution_error.rb
index cf4663650e..0e4a2fe31a 100644
--- a/test/rubygems/test_gem_dependency_resolution_error.rb
+++ b/test/rubygems/test_gem_dependency_resolution_error.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemDependencyResolutionError < Gem::TestCase
-
def setup
super
@@ -21,8 +20,7 @@ class TestGemDependencyResolutionError < Gem::TestCase
end
def test_message
- assert_match %r%^conflicting dependencies a \(= 1\) and a \(= 2\)$%,
+ assert_match %r{^conflicting dependencies a \(= 1\) and a \(= 2\)$},
@error.message
end
-
end
diff --git a/test/rubygems/test_gem_doctor.rb b/test/rubygems/test_gem_doctor.rb
index a0e3a18d7f..583c735dd3 100644
--- a/test/rubygems/test_gem_doctor.rb
+++ b/test/rubygems/test_gem_doctor.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/doctor'
class TestGemDoctor < Gem::TestCase
-
def gem(name)
spec = quick_gem name do |gem|
gem.files = %W[lib/#{name}.rb Rakefile]
@@ -28,31 +27,31 @@ class TestGemDoctor < Gem::TestCase
io.write 'this will raise an exception when evaluated.'
end
- assert_path_exists File.join(a.gem_dir, 'Rakefile')
- assert_path_exists File.join(a.gem_dir, 'lib', 'a.rb')
+ assert_path_exist File.join(a.gem_dir, 'Rakefile')
+ assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb')
- assert_path_exists b.gem_dir
- refute_path_exists b.spec_file
+ assert_path_exist b.gem_dir
+ assert_path_not_exist b.spec_file
- assert_path_exists c.gem_dir
- assert_path_exists c.spec_file
+ assert_path_exist c.gem_dir
+ assert_path_exist c.spec_file
doctor = Gem::Doctor.new @gemhome
- capture_io do
+ capture_output do
use_ui @ui do
doctor.doctor
end
end
- assert_path_exists File.join(a.gem_dir, 'Rakefile')
- assert_path_exists File.join(a.gem_dir, 'lib', 'a.rb')
+ assert_path_exist File.join(a.gem_dir, 'Rakefile')
+ assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb')
- refute_path_exists b.gem_dir
- refute_path_exists b.spec_file
+ assert_path_not_exist b.gem_dir
+ assert_path_not_exist b.spec_file
- refute_path_exists c.gem_dir
- refute_path_exists c.spec_file
+ assert_path_not_exist c.gem_dir
+ assert_path_not_exist c.spec_file
expected = <<-OUTPUT
Checking #{@gemhome}
@@ -81,31 +80,31 @@ Removed directory gems/c-2
io.write 'this will raise an exception when evaluated.'
end
- assert_path_exists File.join(a.gem_dir, 'Rakefile')
- assert_path_exists File.join(a.gem_dir, 'lib', 'a.rb')
+ assert_path_exist File.join(a.gem_dir, 'Rakefile')
+ assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb')
- assert_path_exists b.gem_dir
- refute_path_exists b.spec_file
+ assert_path_exist b.gem_dir
+ assert_path_not_exist b.spec_file
- assert_path_exists c.gem_dir
- assert_path_exists c.spec_file
+ assert_path_exist c.gem_dir
+ assert_path_exist c.spec_file
doctor = Gem::Doctor.new @gemhome, true
- capture_io do
+ capture_output do
use_ui @ui do
doctor.doctor
end
end
- assert_path_exists File.join(a.gem_dir, 'Rakefile')
- assert_path_exists File.join(a.gem_dir, 'lib', 'a.rb')
+ assert_path_exist File.join(a.gem_dir, 'Rakefile')
+ assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb')
- assert_path_exists b.gem_dir
- refute_path_exists b.spec_file
+ assert_path_exist b.gem_dir
+ assert_path_not_exist b.spec_file
- assert_path_exists c.gem_dir
- assert_path_exists c.spec_file
+ assert_path_exist c.gem_dir
+ assert_path_exist c.spec_file
expected = <<-OUTPUT
Checking #{@gemhome}
@@ -128,13 +127,13 @@ Extra directory gems/c-2
doctor = Gem::Doctor.new @tempdir
- capture_io do
+ capture_output do
use_ui @ui do
doctor.doctor
end
end
- assert_path_exists other_dir
+ assert_path_exist other_dir
expected = <<-OUTPUT
Checking #{@tempdir}
@@ -153,6 +152,34 @@ This directory does not appear to be a RubyGems repository, skipping
assert true # count
end
+ def test_doctor_badly_named_plugins
+ gem 'a'
+
+ Gem.use_paths @gemhome.to_s
+
+ FileUtils.mkdir_p Gem.plugindir
+ bad_plugin = File.join(Gem.plugindir, "a_badly_named_file.rb")
+ write_file bad_plugin
+
+ doctor = Gem::Doctor.new @gemhome
+
+ capture_output do
+ use_ui @ui do
+ doctor.doctor
+ end
+ end
+
+ # assert_path_not_exist bad_plugin
+
+ expected = <<-OUTPUT
+Checking #{@gemhome}
+Removed file plugins/a_badly_named_file.rb
+
+ OUTPUT
+
+ assert_equal expected, @ui.output
+ end
+
def test_gem_repository_eh
doctor = Gem::Doctor.new @gemhome
@@ -164,5 +191,4 @@ This directory does not appear to be a RubyGems repository, skipping
assert doctor.gem_repository?, 'gems installed'
end
-
end
diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb
index 7091acdca0..165194510e 100644
--- a/test/rubygems/test_gem_ext_builder.rb
+++ b/test/rubygems/test_gem_ext_builder.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/ext'
require 'rubygems/installer'
class TestGemExtBuilder < Gem::TestCase
-
def setup
super
@@ -15,6 +14,7 @@ class TestGemExtBuilder < Gem::TestCase
FileUtils.mkdir_p @dest_path
@orig_DESTDIR = ENV['DESTDIR']
+ @orig_make = ENV['make']
@spec = util_spec 'a'
@@ -23,6 +23,7 @@ class TestGemExtBuilder < Gem::TestCase
def teardown
ENV['DESTDIR'] = @orig_DESTDIR
+ ENV['make'] = @orig_make
super
end
@@ -31,9 +32,8 @@ class TestGemExtBuilder < Gem::TestCase
ENV['DESTDIR'] = 'destination'
results = []
- Dir.chdir @ext do
- File.open 'Makefile', 'w' do |io|
- io.puts <<-MAKEFILE
+ File.open File.join(@ext, 'Makefile'), 'w' do |io|
+ io.puts <<-MAKEFILE
all:
\t@#{Gem.ruby} -e "puts %Q{all: \#{ENV['DESTDIR']}}"
@@ -42,22 +42,21 @@ clean:
install:
\t@#{Gem.ruby} -e "puts %Q{install: \#{ENV['DESTDIR']}}"
- MAKEFILE
- end
-
- Gem::Ext::Builder.make @dest_path, results
+ MAKEFILE
end
- results = results.join "\n"
+ Gem::Ext::Builder.make @dest_path, results, @ext
+
+ results = results.join("\n").b
- assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results
- assert_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results
- assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results
+ assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} clean$}, results
+ assert_match %r{DESTDIR\\=#{ENV['DESTDIR']}$}, results
+ assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} install$}, results
if /nmake/ !~ results
- assert_match %r%^clean: destination$%, results
- assert_match %r%^all: destination$%, results
- assert_match %r%^install: destination$%, results
+ assert_match %r{^clean: destination$}, results
+ assert_match %r{^all: destination$}, results
+ assert_match %r{^install: destination$}, results
end
end
@@ -65,28 +64,49 @@ install:
ENV['DESTDIR'] = 'destination'
results = []
- Dir.chdir @ext do
- File.open 'Makefile', 'w' do |io|
- io.puts <<-MAKEFILE
+ File.open File.join(@ext, 'Makefile'), 'w' do |io|
+ io.puts <<-MAKEFILE
all:
\t@#{Gem.ruby} -e "puts %Q{all: \#{ENV['DESTDIR']}}"
install:
\t@#{Gem.ruby} -e "puts %Q{install: \#{ENV['DESTDIR']}}"
- MAKEFILE
- end
-
- Gem::Ext::Builder.make @dest_path, results
+ MAKEFILE
end
- results = results.join "\n"
+ Gem::Ext::Builder.make @dest_path, results, @ext
+
+ results = results.join("\n").b
- assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results
- assert_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results
- assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results
+ assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} clean$}, results
+ assert_match %r{DESTDIR\\=#{ENV['DESTDIR']}$}, results
+ assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} install$}, results
+ end
+
+ def test_custom_make_with_options
+ ENV['make'] = 'make V=1'
+ results = []
+ File.open File.join(@ext, 'Makefile'), 'w' do |io|
+ io.puts <<-MAKEFILE
+all:
+\t@#{Gem.ruby} -e "puts 'all: OK'"
+
+clean:
+\t@#{Gem.ruby} -e "puts 'clean: OK'"
+
+install:
+\t@#{Gem.ruby} -e "puts 'install: OK'"
+ MAKEFILE
+ end
+ Gem::Ext::Builder.make @dest_path, results, @ext
+ results = results.join("\n").b
+ assert_match %r{clean: OK}, results
+ assert_match %r{all: OK}, results
+ assert_match %r{install: OK}, results
end
def test_build_extensions
+ pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
@spec.extensions << 'ext/extconf.rb'
ext_dir = File.join @spec.gem_dir, 'ext'
@@ -113,15 +133,16 @@ install:
@builder.build_extensions
end
- assert_path_exists @spec.extension_dir
- assert_path_exists @spec.gem_build_complete_path
- assert_path_exists File.join @spec.extension_dir, 'gem_make.out'
- assert_path_exists File.join @spec.extension_dir, 'a.rb'
- assert_path_exists File.join @spec.gem_dir, 'lib', 'a.rb'
- assert_path_exists File.join @spec.gem_dir, 'lib', 'a', 'b.rb'
+ assert_path_exist @spec.extension_dir
+ assert_path_exist @spec.gem_build_complete_path
+ assert_path_exist File.join @spec.extension_dir, 'gem_make.out'
+ assert_path_exist File.join @spec.extension_dir, 'a.rb'
+ assert_path_exist File.join @spec.gem_dir, 'lib', 'a.rb'
+ assert_path_exist File.join @spec.gem_dir, 'lib', 'a', 'b.rb'
end
def test_build_extensions_with_gemhome_with_space
+ pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
new_gemhome = File.join @tempdir, 'gem home'
File.rename(@gemhome, new_gemhome)
@gemhome = new_gemhome
@@ -134,7 +155,6 @@ install:
def test_build_extensions_install_ext_only
class << Gem
-
alias orig_install_extension_in_lib install_extension_in_lib
remove_method :install_extension_in_lib
@@ -142,8 +162,8 @@ install:
def Gem.install_extension_in_lib
false
end
-
end
+ pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
@spec.extensions << 'ext/extconf.rb'
@@ -171,19 +191,17 @@ install:
@builder.build_extensions
end
- assert_path_exists @spec.extension_dir
- assert_path_exists @spec.gem_build_complete_path
- assert_path_exists File.join @spec.extension_dir, 'gem_make.out'
- assert_path_exists File.join @spec.extension_dir, 'a.rb'
- refute_path_exists File.join @spec.gem_dir, 'lib', 'a.rb'
- refute_path_exists File.join @spec.gem_dir, 'lib', 'a', 'b.rb'
+ assert_path_exist @spec.extension_dir
+ assert_path_exist @spec.gem_build_complete_path
+ assert_path_exist File.join @spec.extension_dir, 'gem_make.out'
+ assert_path_exist File.join @spec.extension_dir, 'a.rb'
+ assert_path_not_exist File.join @spec.gem_dir, 'lib', 'a.rb'
+ assert_path_not_exist File.join @spec.gem_dir, 'lib', 'a', 'b.rb'
ensure
class << Gem
-
remove_method :install_extension_in_lib
alias install_extension_in_lib orig_install_extension_in_lib
-
end
end
@@ -195,7 +213,7 @@ install:
assert_equal '', @ui.output
assert_equal '', @ui.error
- refute_path_exists File.join @spec.extension_dir, 'gem_make.out'
+ assert_path_not_exist File.join @spec.extension_dir, 'gem_make.out'
end
def test_build_extensions_rebuild_failure
@@ -204,13 +222,13 @@ install:
@spec.extensions << nil
- assert_raises Gem::Ext::BuildError do
+ assert_raise Gem::Ext::BuildError do
use_ui @ui do
@builder.build_extensions
end
end
- refute_path_exists @spec.gem_build_complete_path
+ assert_path_not_exist @spec.gem_build_complete_path
end
def test_build_extensions_extconf_bad
@@ -220,32 +238,23 @@ install:
FileUtils.mkdir_p @spec.gem_dir
- e = assert_raises Gem::Ext::BuildError do
+ e = assert_raise Gem::Ext::BuildError do
use_ui @ui do
@builder.build_extensions
end
end
assert_match(/\AERROR: Failed to build gem native extension.$/, e.message)
-
- assert_equal "Building native extensions. This could take a while...\n",
- @ui.output
+ assert_equal "Building native extensions. This could take a while...\n", @ui.output
assert_equal '', @ui.error
gem_make_out = File.join @spec.extension_dir, 'gem_make.out'
+ cmd_make_out = File.read(gem_make_out)
- assert_match %r%#{Regexp.escape Gem.ruby}.* extconf\.rb%,
- File.read(gem_make_out)
- assert_match %r%: No such file%,
- File.read(gem_make_out)
-
- refute_path_exists @spec.gem_build_complete_path
+ assert_match %r{#{Regexp.escape Gem.ruby} .* extconf\.rb}, cmd_make_out
+ assert_match %r{: No such file}, cmd_make_out
- skip "Gem.ruby is not the name of the binary being run in the end" \
- unless File.read(gem_make_out).include? "#{Gem.ruby}:"
-
- assert_match %r%#{Regexp.escape Gem.ruby}: No such file%,
- File.read(gem_make_out)
+ assert_path_not_exist @spec.gem_build_complete_path
assert_equal cwd, Dir.pwd
end
@@ -255,21 +264,19 @@ install:
gem_make_out = File.join @spec.extension_dir, 'gem_make.out'
@spec.extensions << nil
- e = assert_raises Gem::Ext::BuildError do
+ e = assert_raise Gem::Ext::BuildError do
use_ui @ui do
@builder.build_extensions
end
end
assert_match(/^\s*No builder for extension ''$/, e.message)
-
- assert_equal "Building native extensions. This could take a while...\n",
- @ui.output
+ assert_equal "Building native extensions. This could take a while...\n", @ui.output
assert_equal '', @ui.error
assert_equal "No builder for extension ''\n", File.read(gem_make_out)
- refute_path_exists @spec.gem_build_complete_path
+ assert_path_not_exist @spec.gem_build_complete_path
ensure
FileUtils.rm_f gem_make_out
end
@@ -304,7 +311,7 @@ install:
path = File.join @spec.gem_dir, "extconf_args"
assert_equal args.inspect, File.read(path).strip
- assert_path_exists @spec.extension_dir
+ assert_path_exist @spec.extension_dir
end
def test_initialize
@@ -328,5 +335,4 @@ install:
assert_equal %w[--with-foo-dir=/nonexistent], builder.build_args
end
-
end unless Gem.java_platform?
diff --git a/test/rubygems/test_gem_ext_cmake_builder.rb b/test/rubygems/test_gem_ext_cmake_builder.rb
index f7dc383fe9..5ab82c545f 100644
--- a/test/rubygems/test_gem_ext_cmake_builder.rb
+++ b/test/rubygems/test_gem_ext_cmake_builder.rb
@@ -1,20 +1,20 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/ext'
class TestGemExtCmakeBuilder < Gem::TestCase
-
def setup
super
# Details: https://github.com/rubygems/rubygems/issues/1270#issuecomment-177368340
- skip "CmakeBuilder doesn't work on Windows." if Gem.win_platform?
-
- skip "CmakeBuilder doesn't work on JRuby." if Gem.java_platform? && ENV["CI"]
+ pend "CmakeBuilder doesn't work on Windows." if Gem.win_platform?
- system('cmake', out: IO::NULL, err: [:child, :out])
-
- skip 'cmake not present' unless $?.success?
+ begin
+ _, status = Open3.capture2e('cmake')
+ pend 'cmake not present' unless status.success?
+ rescue Errno::ENOENT
+ pend 'cmake not present'
+ end
@ext = File.join @tempdir, 'ext'
@dest_path = File.join @tempdir, 'prefix'
@@ -25,49 +25,43 @@ class TestGemExtCmakeBuilder < Gem::TestCase
def test_self_build
File.open File.join(@ext, 'CMakeLists.txt'), 'w' do |cmakelists|
- cmakelists.write <<-eo_cmake
+ cmakelists.write <<-EO_CMAKE
cmake_minimum_required(VERSION 2.6)
project(self_build NONE)
install (FILES test.txt DESTINATION bin)
- eo_cmake
+ EO_CMAKE
end
FileUtils.touch File.join(@ext, 'test.txt')
output = []
- Dir.chdir @ext do
- Gem::Ext::CmakeBuilder.build nil, @dest_path, output
- end
+ Gem::Ext::CmakeBuilder.build nil, @dest_path, output, [], nil, @ext
output = output.join "\n"
- assert_match \
- %r%^cmake \. -DCMAKE_INSTALL_PREFIX=#{Regexp.escape @dest_path}%, output
- assert_match %r%#{Regexp.escape @ext}%, output
+ assert_match %r{^cmake \. -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}}, output
+ assert_match %r{#{Regexp.escape @ext}}, output
assert_contains_make_command '', output
assert_contains_make_command 'install', output
- assert_match %r%test\.txt%, output
+ assert_match %r{test\.txt}, output
end
def test_self_build_fail
output = []
- error = assert_raises Gem::InstallError do
- Dir.chdir @ext do
- Gem::Ext::CmakeBuilder.build nil, @dest_path, output
- end
+ error = assert_raise Gem::InstallError do
+ Gem::Ext::CmakeBuilder.build nil, @dest_path, output, [], nil, @ext
end
output = output.join "\n"
shell_error_msg = %r{(CMake Error: .*)}
- sh_prefix_cmake = "cmake . -DCMAKE_INSTALL_PREFIX="
assert_match 'cmake failed', error.message
- assert_match %r%^#{sh_prefix_cmake}#{Regexp.escape @dest_path}%, output
- assert_match %r%#{shell_error_msg}%, output
+ assert_match %r{^cmake . -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}}, output
+ assert_match %r{#{shell_error_msg}}, output
end
def test_self_build_has_makefile
@@ -77,14 +71,11 @@ install (FILES test.txt DESTINATION bin)
output = []
- Dir.chdir @ext do
- Gem::Ext::CmakeBuilder.build nil, @dest_path, output
- end
+ Gem::Ext::CmakeBuilder.build nil, @dest_path, output, [], nil, @ext
output = output.join "\n"
assert_contains_make_command '', output
assert_contains_make_command 'install', output
end
-
end
diff --git a/test/rubygems/test_gem_ext_configure_builder.rb b/test/rubygems/test_gem_ext_configure_builder.rb
index eeeb654ae9..76ccfe2dc4 100644
--- a/test/rubygems/test_gem_ext_configure_builder.rb
+++ b/test/rubygems/test_gem_ext_configure_builder.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/ext'
class TestGemExtConfigureBuilder < Gem::TestCase
-
def setup
super
@@ -18,11 +17,7 @@ class TestGemExtConfigureBuilder < Gem::TestCase
end
def test_self_build
- if java_platform? && ENV["CI"]
- skip("failing on jruby")
- end
-
- skip("test_self_build skipped on MS Windows (VC++)") if vc_windows?
+ pend("test_self_build skipped on MS Windows (VC++)") if vc_windows?
File.open File.join(@ext, './configure'), 'w' do |configure|
configure.puts "#!/bin/sh\necho \"#{@makefile_body}\" > Makefile"
@@ -30,12 +25,10 @@ class TestGemExtConfigureBuilder < Gem::TestCase
output = []
- Dir.chdir @ext do
- Gem::Ext::ConfigureBuilder.build nil, @dest_path, output
- end
+ Gem::Ext::ConfigureBuilder.build nil, @dest_path, output, [], nil, @ext
assert_match(/^current directory:/, output.shift)
- assert_equal "sh ./configure --prefix=#{@dest_path}", output.shift
+ assert_equal "sh ./configure --prefix\\=#{@dest_path}", output.shift
assert_equal "", output.shift
assert_match(/^current directory:/, output.shift)
assert_contains_make_command 'clean', output.shift
@@ -49,33 +42,27 @@ class TestGemExtConfigureBuilder < Gem::TestCase
end
def test_self_build_fail
- if java_platform? && ENV["CI"]
- skip("failing on jruby")
- end
-
- skip("test_self_build_fail skipped on MS Windows (VC++)") if vc_windows?
+ pend("test_self_build_fail skipped on MS Windows (VC++)") if vc_windows?
output = []
- error = assert_raises Gem::InstallError do
- Dir.chdir @ext do
- Gem::Ext::ConfigureBuilder.build nil, @dest_path, output
- end
+ error = assert_raise Gem::InstallError do
+ Gem::Ext::ConfigureBuilder.build nil, @dest_path, output, [], nil, @ext
end
shell_error_msg = %r{(\./configure: .*)|((?:[Cc]an't|cannot) open '?\./configure'?(?:: No such file or directory)?)}
- sh_prefix_configure = "sh ./configure --prefix="
+ sh_prefix_configure = "sh ./configure --prefix\\="
assert_match 'configure failed', error.message
assert_match(/^current directory:/, output.shift)
assert_equal "#{sh_prefix_configure}#{@dest_path}", output.shift
- assert_match %r(#{shell_error_msg}), output.shift
+ assert_match %r{#{shell_error_msg}}, output.shift
assert_equal true, output.empty?
end
def test_self_build_has_makefile
if vc_windows? && !nmake_found?
- skip("test_self_build_has_makefile skipped - nmake not found")
+ pend("test_self_build_has_makefile skipped - nmake not found")
end
File.open File.join(@ext, 'Makefile'), 'w' do |makefile|
@@ -83,13 +70,10 @@ class TestGemExtConfigureBuilder < Gem::TestCase
end
output = []
- Dir.chdir @ext do
- Gem::Ext::ConfigureBuilder.build nil, @dest_path, output
- end
+ Gem::Ext::ConfigureBuilder.build nil, @dest_path, output, [], nil, @ext
assert_contains_make_command 'clean', output[1]
assert_contains_make_command '', output[4]
assert_contains_make_command 'install', output[7]
end
-
end
diff --git a/test/rubygems/test_gem_ext_ext_conf_builder.rb b/test/rubygems/test_gem_ext_ext_conf_builder.rb
index 556761c979..10a544cbbc 100644
--- a/test/rubygems/test_gem_ext_ext_conf_builder.rb
+++ b/test/rubygems/test_gem_ext_ext_conf_builder.rb
@@ -1,11 +1,9 @@
-# coding: UTF-8
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/ext'
class TestGemExtExtConfBuilder < Gem::TestCase
-
def setup
super
@@ -18,11 +16,11 @@ class TestGemExtExtConfBuilder < Gem::TestCase
def test_class_build
if java_platform?
- skip("failing on jruby")
+ pend("failing on jruby")
end
if vc_windows? && !nmake_found?
- skip("test_class_build skipped - nmake not found")
+ pend("test_class_build skipped - nmake not found")
end
File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
@@ -31,12 +29,9 @@ class TestGemExtExtConfBuilder < Gem::TestCase
output = []
- Dir.chdir @ext do
- result =
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output
+ result = Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
- assert_same result, output
- end
+ assert_same result, output
assert_match(/^current directory:/, output[0])
assert_match(/^#{Gem.ruby}.* extconf.rb/, output[1])
@@ -46,11 +41,12 @@ class TestGemExtExtConfBuilder < Gem::TestCase
assert_contains_make_command '', output[7]
assert_contains_make_command 'install', output[10]
assert_empty Dir.glob(File.join(@ext, 'siteconf*.rb'))
+ assert_empty Dir.glob(File.join(@ext, '.gem.*'))
end
def test_class_build_rbconfig_make_prog
if java_platform?
- skip("failing on jruby")
+ pend("failing on jruby")
end
configure_args do
@@ -61,9 +57,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase
output = []
- Dir.chdir @ext do
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output
- end
+ Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
assert_equal "creating Makefile\n", output[2]
assert_contains_make_command 'clean', output[4]
@@ -72,12 +66,15 @@ class TestGemExtExtConfBuilder < Gem::TestCase
end
end
- def test_class_build_env_make
- env_make = ENV.delete 'MAKE'
+ def test_class_build_env_MAKE
+ env_make = ENV.delete 'make'
+ ENV['make'] = nil
+
+ env_MAKE = ENV.delete 'MAKE'
ENV['MAKE'] = 'anothermake'
if java_platform?
- skip("failing on jruby")
+ pend("failing on jruby")
end
configure_args '' do
@@ -87,22 +84,21 @@ class TestGemExtExtConfBuilder < Gem::TestCase
output = []
- assert_raises Gem::InstallError do
- Dir.chdir @ext do
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output
- end
+ assert_raise Gem::InstallError do
+ Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
end
assert_equal "creating Makefile\n", output[2]
assert_contains_make_command 'clean', output[4]
end
ensure
- ENV['MAKE'] = env_make
+ ENV['MAKE'] = env_MAKE
+ ENV['make'] = env_make
end
def test_class_build_extconf_fail
if vc_windows? && !nmake_found?
- skip("test_class_build_extconf_fail skipped - nmake not found")
+ pend("test_class_build_extconf_fail skipped - nmake not found")
end
File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
@@ -113,10 +109,8 @@ class TestGemExtExtConfBuilder < Gem::TestCase
output = []
- error = assert_raises Gem::InstallError do
- Dir.chdir @ext do
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output
- end
+ error = assert_raise Gem::InstallError do
+ Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
end
assert_equal 'extconf failed, exit code 1', error.message
@@ -125,12 +119,12 @@ class TestGemExtExtConfBuilder < Gem::TestCase
assert_match(File.join(@dest_path, 'mkmf.log'), output[4])
assert_includes(output, "To see why this extension failed to compile, please check the mkmf.log which can be found here:\n")
- assert_path_exists File.join @dest_path, 'mkmf.log'
+ assert_path_exist File.join @dest_path, 'mkmf.log'
end
def test_class_build_extconf_success_without_warning
if vc_windows? && !nmake_found?
- skip("test_class_build_extconf_fail skipped - nmake not found")
+ pend("test_class_build_extconf_fail skipped - nmake not found")
end
File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
@@ -141,18 +135,16 @@ class TestGemExtExtConfBuilder < Gem::TestCase
output = []
- Dir.chdir @ext do
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output
- end
+ Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
refute_includes(output, "To see why this extension failed to compile, please check the mkmf.log which can be found here:\n")
- assert_path_exists File.join @dest_path, 'mkmf.log'
+ assert_path_exist File.join @dest_path, 'mkmf.log'
end
def test_class_build_unconventional
if vc_windows? && !nmake_found?
- skip("test_class_build skipped - nmake not found")
+ pend("test_class_build skipped - nmake not found")
end
File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
@@ -183,9 +175,7 @@ end
output = []
- Dir.chdir @ext do
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output
- end
+ Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
assert_contains_make_command 'clean', output[4]
assert_contains_make_command '', output[7]
@@ -195,7 +185,7 @@ end
def test_class_make
if vc_windows? && !nmake_found?
- skip("test_class_make skipped - nmake not found")
+ pend("test_class_make skipped - nmake not found")
end
output = []
@@ -209,9 +199,7 @@ end
makefile.puts "install:"
end
- Dir.chdir @ext do
- Gem::Ext::ExtConfBuilder.make @ext, output
- end
+ Gem::Ext::ExtConfBuilder.make @ext, output, @ext
assert_contains_make_command 'clean', output[1]
assert_contains_make_command '', output[4]
@@ -219,10 +207,8 @@ end
end
def test_class_make_no_Makefile
- error = assert_raises Gem::InstallError do
- Dir.chdir @ext do
- Gem::Ext::ExtConfBuilder.make @ext, ['output']
- end
+ error = assert_raise Gem::InstallError do
+ Gem::Ext::ExtConfBuilder.make @ext, ['output'], @ext
end
assert_equal 'Makefile not found', error.message
@@ -241,5 +227,4 @@ end
RbConfig::CONFIG.delete 'configure_args'
end
end
-
end
diff --git a/test/rubygems/test_gem_ext_rake_builder.rb b/test/rubygems/test_gem_ext_rake_builder.rb
index c86ff07649..3d8922eed5 100644
--- a/test/rubygems/test_gem_ext_rake_builder.rb
+++ b/test/rubygems/test_gem_ext_rake_builder.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/ext'
class TestGemExtRakeBuilder < Gem::TestCase
-
def setup
super
@@ -19,15 +18,13 @@ class TestGemExtRakeBuilder < Gem::TestCase
output = []
build_rake_in do |rake|
- Dir.chdir @ext do
- Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output
- end
+ Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, [], nil, @ext
output = output.join "\n"
- refute_match %r%^rake failed:%, output
- assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, output
- assert_match %r%^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}%, output
+ refute_match %r{^rake failed:}, output
+ assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output
+ assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}}, output
end
end
@@ -39,31 +36,54 @@ class TestGemExtRakeBuilder < Gem::TestCase
output = []
build_rake_in do |rake|
- Dir.chdir @ext do
- non_empty_args_list = ['']
- Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, non_empty_args_list
- end
+ non_empty_args_list = ['']
+ Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, non_empty_args_list, nil, @ext
output = output.join "\n"
- refute_match %r%^rake failed:%, output
- assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, output
- assert_match %r%^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}%, output
+ refute_match %r{^rake failed:}, output
+ assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output
+ assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}}, output
+ end
+ end
+
+ def test_class_no_openssl_override
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+
+ create_temp_mkrf_file('task :default')
+
+ rake = util_spec 'rake' do |s|
+ s.executables = %w[rake]
+ s.files = %w[bin/rake]
+ end
+
+ output = []
+
+ write_file File.join(@tempdir, 'bin', 'rake') do |fp|
+ fp.puts "#!/usr/bin/ruby"
+ fp.puts "require 'openssl'; puts OpenSSL"
end
+
+ install_gem rake
+
+ Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, [''], nil, @ext
+
+ output = output.join "\n"
+
+ assert_match "OpenSSL", output
+ assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output
end
def test_class_build_no_mkrf_passes_args
output = []
build_rake_in do |rake|
- Dir.chdir @ext do
- Gem::Ext::RakeBuilder.build "ext/Rakefile", @dest_path, output, ["test1", "test2"]
- end
+ Gem::Ext::RakeBuilder.build "ext/Rakefile", @dest_path, output, ["test1", "test2"], nil, @ext
output = output.join "\n"
- refute_match %r%^rake failed:%, output
- assert_match %r%^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path} test1 test2%, output
+ refute_match %r{^rake failed:}, output
+ assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path} test1 test2}, output
end
end
@@ -72,13 +92,11 @@ class TestGemExtRakeBuilder < Gem::TestCase
output = []
build_rake_in(false) do |rake|
- error = assert_raises Gem::InstallError do
- Dir.chdir @ext do
- Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output
- end
+ error = assert_raise Gem::InstallError do
+ Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output, [], nil, @ext
end
- assert_match %r%^rake failed%, error.message
+ assert_match %r{^rake failed}, error.message
end
end
@@ -91,5 +109,4 @@ class TestGemExtRakeBuilder < Gem::TestCase
EO_MKRF
end
end
-
end
diff --git a/test/rubygems/test_gem_gem_runner.rb b/test/rubygems/test_gem_gem_runner.rb
index efde71dce6..6f5361cf2f 100644
--- a/test/rubygems/test_gem_gem_runner.rb
+++ b/test/rubygems/test_gem_gem_runner.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemGemRunner < Gem::TestCase
-
def setup
super
require 'rubygems/command'
@orig_args = Gem::Command.build_args
+ @orig_specific_extra_args = Gem::Command.specific_extra_args_hash.dup
+ @orig_extra_args = Gem::Command.extra_args.dup
require 'rubygems/gem_runner'
@runner = Gem::GemRunner.new
@@ -17,6 +18,8 @@ class TestGemGemRunner < Gem::TestCase
super
Gem::Command.build_args = @orig_args
+ Gem::Command.specific_extra_args_hash = @orig_specific_extra_args
+ Gem::Command.extra_args = @orig_extra_args
end
def test_do_configuration
@@ -67,4 +70,44 @@ class TestGemGemRunner < Gem::TestCase
assert_equal %w[--foo], args
end
+ def test_query_is_deprecated
+ args = %w[query]
+
+ use_ui @ui do
+ @runner.run(args)
+ end
+
+ assert_match(/WARNING: query command is deprecated. It will be removed in Rubygems [0-9]+/, @ui.error)
+ assert_match(/WARNING: It is recommended that you use `gem search` or `gem list` instead/, @ui.error)
+ end
+
+ def test_info_succeeds
+ args = %w[info]
+
+ use_ui @ui do
+ @runner.run(args)
+ end
+
+ assert_empty @ui.error
+ end
+
+ def test_list_succeeds
+ args = %w[list]
+
+ use_ui @ui do
+ @runner.run(args)
+ end
+
+ assert_empty @ui.error
+ end
+
+ def test_search_succeeds
+ args = %w[search]
+
+ use_ui @ui do
+ @runner.run(args)
+ end
+
+ assert_empty @ui.error
+ end
end
diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb
index 03bb78271b..0bcd1504e9 100644
--- a/test/rubygems/test_gem_gemcutter_utilities.rb
+++ b/test/rubygems/test_gem_gemcutter_utilities.rb
@@ -1,17 +1,20 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems'
require 'rubygems/command'
require 'rubygems/gemcutter_utilities'
class TestGemGemcutterUtilities < Gem::TestCase
-
def setup
super
+
+ credential_setup
+
# below needed for random testing, class property
Gem.configuration.disable_default_gem_server = nil
ENV['RUBYGEMS_HOST'] = nil
+ ENV['GEM_HOST_OTP_CODE'] = nil
Gem.configuration.rubygems_api_key = nil
@cmd = Gem::Command.new '', 'summary'
@@ -20,19 +23,20 @@ class TestGemGemcutterUtilities < Gem::TestCase
def teardown
ENV['RUBYGEMS_HOST'] = nil
+ ENV['GEM_HOST_OTP_CODE'] = nil
Gem.configuration.rubygems_api_key = nil
+ credential_teardown
+
super
end
def test_alternate_key_alternate_host
keys = {
:rubygems_api_key => 'KEY',
- "http://rubygems.engineyard.com" => "EYKEY"
+ "http://rubygems.engineyard.com" => "EYKEY",
}
- FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path
-
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write keys.to_yaml
end
@@ -46,7 +50,6 @@ class TestGemGemcutterUtilities < Gem::TestCase
def test_api_key
keys = { :rubygems_api_key => 'KEY' }
- FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write keys.to_yaml
@@ -59,7 +62,6 @@ class TestGemGemcutterUtilities < Gem::TestCase
def test_api_key_override
keys = { :rubygems_api_key => 'KEY', :other => 'OTHER' }
- FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write keys.to_yaml
@@ -97,7 +99,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
assert @fetcher.last_request["authorization"]
assert_match %r{Signed in.}, @sign_in_ui.output
- credentials = YAML.load_file Gem.configuration.credentials_path
+ credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials[:rubygems_api_key]
end
@@ -111,7 +113,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
assert @fetcher.last_request["authorization"]
assert_match %r{Signed in.}, @sign_in_ui.output
- credentials = YAML.load_file Gem.configuration.credentials_path
+ credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials['http://example.com']
end
@@ -125,7 +127,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
assert @fetcher.last_request["authorization"]
assert_match %r{Signed in.}, @sign_in_ui.output
- credentials = YAML.load_file Gem.configuration.credentials_path
+ credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials[:rubygems_api_key]
end
@@ -138,7 +140,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
assert @fetcher.last_request["authorization"]
assert_match %r{Signed in.}, @sign_in_ui.output
- credentials = YAML.load_file Gem.configuration.credentials_path
+ credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials['http://example.com']
end
@@ -164,7 +166,6 @@ class TestGemGemcutterUtilities < Gem::TestCase
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
other_api_key = 'f46dbb18bb6a9c97cdc61b5b85c186a17403cdcbf'
- FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path)
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write Hash[:other_api_key, other_api_key].to_yaml
end
@@ -173,13 +174,13 @@ class TestGemGemcutterUtilities < Gem::TestCase
assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output
assert_match %r{Signed in.}, @sign_in_ui.output
- credentials = YAML.load_file Gem.configuration.credentials_path
+ credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials[:rubygems_api_key]
assert_equal other_api_key, credentials[:other_api_key]
end
def test_sign_in_with_bad_credentials
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
util_sign_in ['Access Denied.', 403, 'Forbidden']
end
@@ -187,6 +188,16 @@ class TestGemGemcutterUtilities < Gem::TestCase
assert_match %r{Access Denied.}, @sign_in_ui.output
end
+ def test_signin_with_env_otp_code
+ ENV['GEM_HOST_OTP_CODE'] = '111111'
+ api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
+
+ util_sign_in [api_key, 200, 'OK']
+
+ assert_match 'Signed in with API key:', @sign_in_ui.output
+ assert_equal '111111', @fetcher.last_request['OTP']
+ end
+
def test_sign_in_with_correct_otp_code
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
@@ -198,14 +209,14 @@ class TestGemGemcutterUtilities < Gem::TestCase
assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @sign_in_ui.output
assert_match 'Code: ', @sign_in_ui.output
- assert_match 'Signed in.', @sign_in_ui.output
+ assert_match 'Signed in with API key:', @sign_in_ui.output
assert_equal '111111', @fetcher.last_request['OTP']
end
def test_sign_in_with_incorrect_otp_code
response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
util_sign_in [response, 401, 'Unauthorized'], nil, [], "111111\n"
end
@@ -229,7 +240,7 @@ class TestGemGemcutterUtilities < Gem::TestCase
@fetcher.data["#{host}/api/v1/api_key"] = response
Gem::RemoteFetcher.fetcher = @fetcher
- @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n" + extra_input)
+ @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n" + extra_input)
use_ui @sign_in_ui do
if args.length > 0
@@ -242,7 +253,6 @@ class TestGemGemcutterUtilities < Gem::TestCase
def test_verify_api_key
keys = {:other => 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'}
- FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path)
File.open Gem.configuration.credentials_path, 'w' do |f|
f.write keys.to_yaml
end
@@ -253,9 +263,8 @@ class TestGemGemcutterUtilities < Gem::TestCase
end
def test_verify_missing_api_key
- assert_raises Gem::MockGemUi::TermError do
+ assert_raise Gem::MockGemUi::TermError do
@cmd.verify_api_key :missing
end
end
-
end
diff --git a/test/rubygems/test_gem_impossible_dependencies_error.rb b/test/rubygems/test_gem_impossible_dependencies_error.rb
index 8a0f8d6196..971be151df 100644
--- a/test/rubygems/test_gem_impossible_dependencies_error.rb
+++ b/test/rubygems/test_gem_impossible_dependencies_error.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemImpossibleDependenciesError < Gem::TestCase
-
def test_message_conflict
request = dependency_request dep('net-ssh', '>= 2.0.13'), 'rye', '0.9.8'
@@ -57,5 +56,4 @@ rye-0.9.8 requires net-ssh (>= 2.0.13) but it conflicted:
assert_equal expected, error.message
end
-
end
diff --git a/test/rubygems/test_gem_indexer.rb b/test/rubygems/test_gem_indexer.rb
index fdef33e464..6653f29adf 100644
--- a/test/rubygems/test_gem_indexer.rb
+++ b/test/rubygems/test_gem_indexer.rb
@@ -1,13 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/indexer'
-unless defined?(Builder::XChar)
- warn "Gem::Indexer tests are being skipped. Install builder gem."
-end
-
class TestGemIndexer < Gem::TestCase
-
def setup
super
@@ -189,15 +184,15 @@ class TestGemIndexer < Gem::TestCase
@indexer.generate_index
end
- assert_match %r%^\.\.\.\.\.\.\.\.\.\.\.\.$%, @ui.output
- assert_match %r%^Generating Marshal quick index gemspecs for 12 gems$%,
+ assert_match %r{^\.\.\.\.\.\.\.\.\.\.\.\.$}, @ui.output
+ assert_match %r{^Generating Marshal quick index gemspecs for 12 gems$},
@ui.output
- assert_match %r%^Complete$%, @ui.output
- assert_match %r%^Generating specs index$%, @ui.output
- assert_match %r%^Generating latest specs index$%, @ui.output
- assert_match %r%^Generating prerelease specs index$%, @ui.output
- assert_match %r%^Complete$%, @ui.output
- assert_match %r%^Compressing indices$%, @ui.output
+ assert_match %r{^Complete$}, @ui.output
+ assert_match %r{^Generating specs index$}, @ui.output
+ assert_match %r{^Generating latest specs index$}, @ui.output
+ assert_match %r{^Generating prerelease specs index$}, @ui.output
+ assert_match %r{^Complete$}, @ui.output
+ assert_match %r{^Compressing indices$}, @ui.output
assert_equal '', @ui.error
end
@@ -359,5 +354,4 @@ class TestGemIndexer < Gem::TestCase
file = File.join dir, name
refute File.exist?(file), "#{file} exists"
end
-
-end if defined?(Builder::XChar)
+end
diff --git a/test/rubygems/test_gem_install_update_options.rb b/test/rubygems/test_gem_install_update_options.rb
index c6b4778336..a499c2be3b 100644
--- a/test/rubygems/test_gem_install_update_options.rb
+++ b/test/rubygems/test_gem_install_update_options.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/installer_test_case'
+require_relative 'installer_test_case'
require 'rubygems/install_update_options'
require 'rubygems/command'
require 'rubygems/dependency_installer'
class TestGemInstallUpdateOptions < Gem::InstallerTestCase
-
def setup
super
@@ -31,7 +30,7 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
args.concat %w[--vendor] unless Gem.java_platform?
- args.concat %w[-P HighSecurity] if defined?(OpenSSL::SSL)
+ args.concat %w[-P HighSecurity] if Gem::HAVE_OPENSSL
assert @cmd.handles?(args)
end
@@ -93,7 +92,7 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
end
def test_security_policy
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
@cmd.handle_options %w[-P HighSecurity]
@@ -101,11 +100,11 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
end
def test_security_policy_unknown
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
@cmd.add_install_update_options
- e = assert_raises OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %w[-P UnknownSecurity]
end
assert_includes e.message, "UnknownSecurity"
@@ -125,8 +124,8 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
@installer = Gem::Installer.at @gem, @cmd.options
@installer.install
- assert_path_exists File.join(Gem.user_dir, 'gems')
- assert_path_exists File.join(Gem.user_dir, 'gems', @spec.full_name)
+ assert_path_exist File.join(Gem.user_dir, 'gems')
+ assert_path_exist File.join(Gem.user_dir, 'gems', @spec.full_name)
end
def test_user_install_disabled_read_only
@@ -138,9 +137,9 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
@gem = @spec.cache_file
if win_platform?
- skip('test_user_install_disabled_read_only test skipped on MS Windows')
+ pend('test_user_install_disabled_read_only test skipped on MS Windows')
elsif Process.uid.zero?
- skip('test_user_install_disabled_read_only test skipped in root privilege')
+ pend('test_user_install_disabled_read_only test skipped in root privilege')
else
@cmd.handle_options %w[--no-user-install]
@@ -151,7 +150,7 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
Gem.use_paths @gemhome, @userhome
- assert_raises(Gem::FilePermissionError) do
+ assert_raise(Gem::FilePermissionError) do
Gem::Installer.at(@gem, @cmd.options).install
end
end
@@ -170,7 +169,7 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
def test_vendor_missing
vendordir(nil) do
- e = assert_raises OptionParser::InvalidOption do
+ e = assert_raise Gem::OptionParser::InvalidOption do
@cmd.handle_options %w[--vendor]
end
@@ -194,4 +193,15 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
assert_equal true, @cmd.options[:post_install_message]
end
+ def test_minimal_deps_no
+ @cmd.handle_options %w[--no-minimal-deps]
+
+ assert_equal false, @cmd.options[:minimal_deps]
+ end
+
+ def test_minimal_deps
+ @cmd.handle_options %w[--minimal-deps]
+
+ assert_equal true, @cmd.options[:minimal_deps]
+ end
end
diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb
index 731a1ac01d..dae2b070d5 100644
--- a/test/rubygems/test_gem_installer.rb
+++ b/test/rubygems/test_gem_installer.rb
@@ -1,26 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/installer_test_case'
+require_relative 'installer_test_case'
class TestGemInstaller < Gem::InstallerTestCase
-
- @@symlink_supported = nil
-
- # Our CI does not currently hit the "symlink not supported" case, but this is
- # needed for Windows developers without symlink support enabled (the default
- # for non admin) to be able to run the tests successfully
- def symlink_supported?
- if @@symlink_supported.nil?
- begin
- File.symlink("", "")
- rescue Errno::ENOENT, Errno::EEXIST
- @@symlink_supported = true
- rescue NotImplementedError, SystemCallError
- @@symlink_supported = false
- end
- end
- @@symlink_supported
- end
-
def setup
super
common_installer_setup
@@ -52,6 +33,8 @@ class TestGemInstaller < Gem::InstallerTestCase
require 'rubygems'
+Gem.use_gemdeps
+
version = \">= 0.a\"
str = ARGV.first
@@ -95,26 +78,26 @@ end
installer.generate_bin
installed_exec = File.join util_inst_bindir, 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r|generated by RubyGems|, wrapper
+ assert_match %r{generated by RubyGems}, wrapper
end
def test_check_executable_overwrite_default_bin_dir
- installer = setup_base_installer
+ installer = setup_base_installer(false)
bindir(Gem.bindir) do
util_conflict_executable false
ui = Gem::MockGemUi.new "n\n"
use_ui ui do
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.generate_bin
end
conflicted = File.join @gemhome, 'bin', 'executable'
- assert_match %r%\A"executable" from a conflicts with (?:#{Regexp.quote(conflicted)}|installed executable from conflict)\z%,
+ assert_match %r{\A"executable" from a conflicts with (?:#{Regexp.quote(conflicted)}|installed executable from conflict)\z},
e.message
end
end
@@ -153,23 +136,23 @@ gem 'other', version
installer.generate_bin # should not raise
installed_exec = File.join util_inst_bindir, 'foo-executable-bar'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r|generated by RubyGems|, wrapper
+ assert_match %r{generated by RubyGems}, wrapper
ensure
Gem::Installer.exec_format = nil
end
def test_check_executable_overwrite_other_gem
- installer = setup_base_installer
+ installer = setup_base_installer(false)
util_conflict_executable true
ui = Gem::MockGemUi.new "n\n"
use_ui ui do
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.generate_bin
end
@@ -188,10 +171,10 @@ gem 'other', version
installer.generate_bin
installed_exec = File.join util_inst_bindir, 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r|generated by RubyGems|, wrapper
+ assert_match %r{generated by RubyGems}, wrapper
end
def test_check_executable_overwrite_other_non_gem
@@ -203,10 +186,10 @@ gem 'other', version
installer.generate_bin
installed_exec = File.join util_inst_bindir, 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r|generated by RubyGems|, wrapper
+ assert_match %r{generated by RubyGems}, wrapper
end unless Gem.win_platform?
def test_check_that_user_bin_dir_is_in_path
@@ -215,7 +198,7 @@ gem 'other', version
bin_dir = installer.bin_dir
if Gem.win_platform?
- bin_dir = bin_dir.downcase.gsub(File::SEPARATOR, File::ALT_SEPARATOR)
+ bin_dir = bin_dir.downcase
end
orig_PATH, ENV['PATH'] =
@@ -226,12 +209,22 @@ gem 'other', version
end
assert_empty @ui.error
+
+ return unless win_platform?
+
+ ENV['PATH'] = [orig_PATH, bin_dir.tr(File::SEPARATOR, File::ALT_SEPARATOR)].join(File::PATH_SEPARATOR)
+
+ use_ui @ui do
+ installer.check_that_user_bin_dir_is_in_path
+ end
+
+ assert_empty @ui.error
ensure
ENV['PATH'] = orig_PATH
end
def test_check_that_user_bin_dir_is_in_path_tilde
- skip "Tilde is PATH is not supported under MS Windows" if win_platform?
+ pend "Tilde is PATH is not supported under MS Windows" if win_platform?
orig_PATH, ENV['PATH'] =
ENV['PATH'], [ENV['PATH'], '~/bin'].join(File::PATH_SEPARATOR)
@@ -258,7 +251,7 @@ gem 'other', version
expected = installer.bin_dir
if Gem.win_platform?
- expected = expected.downcase.gsub(File::SEPARATOR, File::ALT_SEPARATOR)
+ expected = expected.downcase
end
assert_match expected, @ui.error
@@ -273,7 +266,7 @@ gem 'other', version
assert installer.ensure_dependency(@spec, dep)
dep = Gem::Dependency.new 'b', '> 2'
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.ensure_dependency @spec, dep
end
@@ -287,7 +280,7 @@ gem 'other', version
installer = Gem::Installer.at a_gem
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.ensure_loadable_spec
end
@@ -295,8 +288,35 @@ gem 'other', version
"(SyntaxError)", e.message
end
+ def test_ensure_no_race_conditions_between_installing_and_loading_gemspecs
+ a, a_gem = util_gem 'a', 2
+
+ Gem::Installer.at(a_gem).install
+
+ t1 = Thread.new do
+ 5.times do
+ Gem::Installer.at(a_gem).install
+ sleep 0.1
+ end
+ end
+
+ t2 = Thread.new do
+ _, err = capture_output do
+ 20.times do
+ Gem::Specification.load(a.spec_file)
+ Gem::Specification.send(:clear_load_cache)
+ end
+ end
+
+ assert_empty err
+ end
+
+ t1.join
+ t2.join
+ end
+
def test_ensure_loadable_spec_security_policy
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
_, a_gem = util_gem 'a', 2 do |s|
s.add_dependency 'garbage ~> 5'
@@ -305,7 +325,7 @@ gem 'other', version
policy = Gem::Security::HighSecurity
installer = Gem::Installer.at a_gem, :security_policy => policy
- assert_raises Gem::Security::Exception do
+ assert_raise Gem::Security::Exception do
installer.ensure_loadable_spec
end
end
@@ -315,7 +335,7 @@ gem 'other', version
installer.extract_files
- assert_path_exists File.join @spec.gem_dir, 'bin/executable'
+ assert_path_exist File.join @spec.gem_dir, 'bin/executable'
end
def test_generate_bin_bindir
@@ -338,11 +358,11 @@ gem 'other', version
assert_directory_exists util_inst_bindir
installed_exec = File.join(util_inst_bindir, 'executable')
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
assert_equal mask, File.stat(installed_exec).mode unless win_platform?
wrapper = File.read installed_exec
- assert_match %r|generated by RubyGems|, wrapper
+ assert_match %r{generated by RubyGems}, wrapper
end
def test_generate_bin_bindir_with_user_install_warning
@@ -354,7 +374,7 @@ gem 'other', version
options = {
:bin_dir => bin_dir,
- :install_dir => "/non/existent"
+ :install_dir => "/non/existent",
}
inst = Gem::Installer.at '', options
@@ -381,11 +401,11 @@ gem 'other', version
installer.generate_bin
assert_directory_exists util_inst_bindir
installed_exec = File.join util_inst_bindir, 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
assert_equal mask, File.stat(installed_exec).mode unless win_platform?
wrapper = File.read installed_exec
- assert_match %r|generated by RubyGems|, wrapper
+ assert_match %r{generated by RubyGems}, wrapper
end
def test_generate_bin_script_format
@@ -400,7 +420,7 @@ gem 'other', version
installer.generate_bin
assert_directory_exists util_inst_bindir
installed_exec = File.join util_inst_bindir, 'foo-executable-bar'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
ensure
Gem::Installer.exec_format = nil
end
@@ -416,7 +436,7 @@ gem 'other', version
installer.generate_bin
assert_directory_exists util_inst_bindir
installed_exec = File.join util_inst_bindir, 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
ensure
Gem::Installer.exec_format = nil
end
@@ -440,11 +460,11 @@ gem 'other', version
installer.generate_bin
installed_exec = File.join("#{@gemhome}2", "bin", 'executable')
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
assert_equal mask, File.stat(installed_exec).mode unless win_platform?
wrapper = File.read installed_exec
- assert_match %r|generated by RubyGems|, wrapper
+ assert_match %r{generated by RubyGems}, wrapper
end
def test_generate_bin_script_no_execs
@@ -455,7 +475,7 @@ gem 'other', version
installer.wrappers = true
installer.generate_bin
- refute_path_exists util_inst_bindir, 'bin dir was created when not needed'
+ assert_path_not_exist util_inst_bindir, 'bin dir was created when not needed'
end
def test_generate_bin_script_no_perms
@@ -467,13 +487,13 @@ gem 'other', version
Dir.mkdir util_inst_bindir
if win_platform?
- skip('test_generate_bin_script_no_perms skipped on MS Windows')
+ pend('test_generate_bin_script_no_perms skipped on MS Windows')
elsif Process.uid.zero?
- skip('test_generate_bin_script_no_perms skipped in root privilege')
+ pend('test_generate_bin_script_no_perms skipped in root privilege')
else
FileUtils.chmod 0000, util_inst_bindir
- assert_raises Gem::FilePermissionError do
+ assert_raise Gem::FilePermissionError do
installer.generate_bin
end
end
@@ -497,11 +517,11 @@ gem 'other', version
installer.generate_bin
installed_exec = File.join @gemhome, 'bin', 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
assert_equal mask, File.stat(installed_exec).mode unless win_platform?
wrapper = File.read installed_exec
- assert_match %r|generated by RubyGems|, wrapper
+ assert_match %r{generated by RubyGems}, wrapper
# HACK some gems don't have #! in their executables, restore 2008/06
#assert_no_match %r|generated by RubyGems|, wrapper
end
@@ -524,17 +544,17 @@ gem 'other', version
installer.generate_bin
assert_directory_exists util_inst_bindir
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
assert_equal mask, File.stat(installed_exec).mode unless win_platform?
- assert_match %r|generated by RubyGems|, File.read(installed_exec)
+ assert_match %r{generated by RubyGems}, File.read(installed_exec)
- refute_match %r|generated by RubyGems|, File.read(real_exec),
+ refute_match %r{generated by RubyGems}, File.read(real_exec),
'real executable overwritten'
end
def test_generate_bin_symlink
- skip "Symlinks not supported or not enabled" unless symlink_supported?
+ pend "Symlinks not supported or not enabled" unless symlink_supported?
installer = setup_base_installer
@@ -558,7 +578,7 @@ gem 'other', version
installer.wrappers = false
installer.generate_bin
- refute_path_exists util_inst_bindir
+ assert_path_not_exist util_inst_bindir
end
def test_generate_bin_symlink_no_perms
@@ -571,13 +591,13 @@ gem 'other', version
Dir.mkdir util_inst_bindir
if win_platform?
- skip('test_generate_bin_symlink_no_perms skipped on MS Windows')
+ pend('test_generate_bin_symlink_no_perms skipped on MS Windows')
elsif Process.uid.zero?
- skip('test_user_install_disabled_read_only test skipped in root privilege')
+ pend('test_user_install_disabled_read_only test skipped in root privilege')
else
FileUtils.chmod 0000, util_inst_bindir
- assert_raises Gem::FilePermissionError do
+ assert_raise Gem::FilePermissionError do
installer.generate_bin
end
end
@@ -586,7 +606,7 @@ gem 'other', version
end
def test_generate_bin_symlink_update_newer
- skip "Symlinks not supported or not enabled" unless symlink_supported?
+ pend "Symlinks not supported or not enabled" unless symlink_supported?
installer = setup_base_installer
@@ -618,7 +638,7 @@ gem 'other', version
end
def test_generate_bin_symlink_update_older
- skip "Symlinks not supported or not enabled" unless symlink_supported?
+ pend "Symlinks not supported or not enabled" unless symlink_supported?
installer = setup_base_installer
@@ -656,7 +676,7 @@ gem 'other', version
end
def test_generate_bin_symlink_update_remove_wrapper
- skip "Symlinks not supported or not enabled" unless symlink_supported?
+ pend "Symlinks not supported or not enabled" unless symlink_supported?
installer = setup_base_installer
@@ -667,7 +687,7 @@ gem 'other', version
installer.generate_bin
installed_exec = File.join util_inst_bindir, 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
@spec = Gem::Specification.new do |s|
s.files = ['lib/code.rb']
@@ -710,7 +730,7 @@ gem 'other', version
assert_directory_exists util_inst_bindir
installed_exec = File.join(util_inst_bindir, 'executable')
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
if symlink_supported?
assert File.symlink?(installed_exec)
@@ -729,7 +749,7 @@ gem 'other', version
end
def test_generate_bin_uses_default_shebang
- skip "Symlinks not supported or not enabled" unless symlink_supported?
+ pend "Symlinks not supported or not enabled" unless symlink_supported?
installer = setup_base_installer
@@ -739,11 +759,173 @@ gem 'other', version
installer.generate_bin
default_shebang = Gem.ruby
- shebang_line = open("#{@gemhome}/bin/executable") { |f| f.readlines.first }
+ shebang_line = File.open("#{@gemhome}/bin/executable") {|f| f.readlines.first }
assert_match(/\A#!/, shebang_line)
assert_match(/#{default_shebang}/, shebang_line)
end
+ def test_generate_bin_with_dangling_symlink
+ gem_with_dangling_symlink = File.expand_path("packages/ascii_binder-0.1.10.1.gem", __dir__)
+
+ installer = Gem::Installer.at(
+ gem_with_dangling_symlink,
+ :user_install => false,
+ :force => true
+ )
+
+ build_rake_in do
+ use_ui @ui do
+ installer.install
+ end
+ end
+
+ assert_match %r{bin/ascii_binder` is dangling symlink pointing to `bin/asciibinder`}, @ui.error
+ assert_empty @ui.output
+ end
+
+ def test_generate_plugins
+ installer = util_setup_installer do |spec|
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ io.write "puts __FILE__"
+ end
+
+ spec.files += %w[lib/rubygems_plugin.rb]
+ end
+
+ build_rake_in do
+ installer.install
+ end
+
+ plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+
+ FileUtils.rm plugin_path
+
+ installer.generate_plugins
+
+ assert File.exist?(plugin_path), 'plugin not written'
+ end
+
+ def test_generate_plugins_with_install_dir
+ spec = quick_gem 'a' do |s|
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ io.write "puts __FILE__"
+ end
+
+ s.files += %w[lib/rubygems_plugin.rb]
+ end
+
+ util_build_gem spec
+
+ plugin_path = File.join "#{@gemhome}2", 'plugins', 'a_plugin.rb'
+ installer = util_installer spec, "#{@gemhome}2"
+
+ assert_equal spec, installer.install
+
+ assert File.exist?(plugin_path), 'plugin not written to install_dir'
+ end
+
+ def test_generate_plugins_with_user_install
+ spec = quick_gem 'a' do |s|
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ io.write "puts __FILE__"
+ end
+
+ s.files += %w[lib/rubygems_plugin.rb]
+ end
+
+ util_build_gem spec
+
+ File.chmod(0555, Gem.plugindir)
+ system_path = File.join(Gem.plugindir, 'a_plugin.rb')
+ user_path = File.join(Gem.plugindir(Gem.user_dir), 'a_plugin.rb')
+ installer = util_installer spec, Gem.dir, :user
+
+ assert_equal spec, installer.install
+
+ assert !File.exist?(system_path), 'plugin incorrectly written to system plugins_dir'
+ assert File.exist?(user_path), 'plugin not written to user plugins_dir'
+ end
+
+ def test_generate_plugins_with_build_root
+ spec = quick_gem 'a' do |s|
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ io.write "puts __FILE__"
+ end
+
+ s.files += %w[lib/rubygems_plugin.rb]
+ end
+
+ util_build_gem spec
+
+ File.chmod(0555, Gem.plugindir)
+ system_path = File.join(Gem.plugindir, 'a_plugin.rb')
+
+ build_root = File.join(@tempdir, 'build_root')
+ build_root_path = File.join(build_root, Gem.plugindir.gsub(/^[a-zA-Z]:/, ''), 'a_plugin.rb')
+
+ installer = Gem::Installer.at spec.cache_file, :build_root => build_root
+
+ assert_equal spec, installer.install
+
+ assert !File.exist?(system_path), 'plugin written incorrect written to system plugins_dir'
+ assert File.exist?(build_root_path), 'plugin not written to build_root'
+
+ refute_includes File.read(build_root_path), build_root
+ end
+
+ def test_keeps_plugins_up_to_date
+ # NOTE: version a-2 is already installed by setup hooks
+
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ io.write "puts __FILE__"
+ end
+
+ build_rake_in do
+ util_setup_installer do |spec|
+ spec.version = '1'
+ spec.files += %w[lib/rubygems_plugin.rb]
+ end.install
+
+ plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+ refute File.exist?(plugin_path), 'old version installed while newer version without plugin also installed, but plugin written'
+
+ util_setup_installer do |spec|
+ spec.version = '2'
+ spec.files += %w[lib/rubygems_plugin.rb]
+ end.install
+
+ plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+ assert File.exist?(plugin_path), 'latest version reinstalled, but plugin not written'
+ assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'written plugin has incorrect content'
+
+ util_setup_installer do |spec|
+ spec.version = '3'
+ spec.files += %w[lib/rubygems_plugin.rb]
+ end.install
+
+ plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+ assert File.exist?(plugin_path), 'latest version installed, but plugin removed'
+ assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'written plugin has incorrect content'
+
+ util_setup_installer do |spec|
+ spec.version = '4'
+ end.install
+
+ refute File.exist?(plugin_path), 'new version installed without a plugin while older version with a plugin installed, but plugin not removed'
+ end
+ end
+
+ def test_generates_plugins_dir_under_install_dir_if_not_there
+ Gem.use_paths "#{@gemhome}2" # Set GEM_HOME to an uninitialized repo
+
+ @spec = util_spec 'a'
+
+ path = Gem::Package.build @spec
+
+ installer = Gem::Installer.at path, :install_dir => "#{@gemhome}3"
+ assert_equal @spec, installer.install
+ end
+
def test_initialize
spec = util_spec 'a' do |s|
s.platform = Gem::Platform.new 'mswin32'
@@ -792,22 +974,19 @@ gem 'other', version
spec_file = File.join @gemhome, 'specifications', @spec.spec_name
Gem.pre_install do
- refute_path_exists cache_file, 'cache file must not exist yet'
- refute_path_exists spec_file, 'spec file must not exist yet'
+ assert_path_not_exist cache_file, 'cache file must not exist yet'
true
end
Gem.post_build do
- assert_path_exists gemdir, 'gem install dir must exist'
- assert_path_exists rakefile, 'gem executable must exist'
- refute_path_exists stub_exe, 'gem executable must not exist'
- refute_path_exists spec_file, 'spec file must not exist yet'
+ assert_path_exist gemdir, 'gem install dir must exist'
+ assert_path_exist rakefile, 'gem executable must exist'
+ assert_path_not_exist stub_exe, 'gem executable must not exist'
true
end
Gem.post_install do
- assert_path_exists cache_file, 'cache file must exist'
- assert_path_exists spec_file, 'spec file must exist'
+ assert_path_exist cache_file, 'cache file must exist'
end
@newspec = nil
@@ -818,21 +997,21 @@ gem 'other', version
end
assert_equal @spec, @newspec
- assert_path_exists gemdir
- assert_path_exists stub_exe, 'gem executable must exist'
+ assert_path_exist gemdir
+ assert_path_exist stub_exe, 'gem executable must exist'
exe = File.join gemdir, 'bin', 'executable'
- assert_path_exists exe
+ assert_path_exist exe
exe_mode = File.stat(exe).mode & 0111
assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform?
- assert_path_exists File.join gemdir, 'lib', 'code.rb'
+ assert_path_exist File.join gemdir, 'lib', 'code.rb'
- assert_path_exists rakefile
+ assert_path_exist rakefile
assert_equal spec_file, @newspec.loaded_from
- assert_path_exists spec_file
+ assert_path_exist spec_file
assert_same installer, @post_build_hook_arg
assert_same installer, @post_install_hook_arg
@@ -855,7 +1034,7 @@ gem 'other', version
exe = File.join gemdir, 'bin', 'executable'
- e = assert_raises RuntimeError do
+ e = assert_raise RuntimeError do
instance_eval File.read(exe)
end
@@ -901,7 +1080,7 @@ gem 'other', version
end
end
- e = assert_raises RuntimeError do
+ e = assert_raise RuntimeError do
instance_eval File.read(old_bin_file)
end
@@ -929,7 +1108,7 @@ gem 'other', version
begin
Gem::Specification.reset
- e = assert_raises Gem::GemNotFoundException do
+ e = assert_raise Gem::GemNotFoundException do
instance_eval File.read(exe)
end
ensure
@@ -940,7 +1119,13 @@ gem 'other', version
end
def test_install_creates_binstub_that_prefers_user_installed_gem_to_default
- install_default_gems new_default_spec('default', '2')
+ default_spec = new_default_spec('default', '2', nil, 'exe/executable')
+ default_spec.executables = 'executable'
+ install_default_gems default_spec
+
+ exe = File.join @gemhome, 'bin', 'executable'
+
+ assert_path_exist exe, "default gem's executable not installed"
installer = util_setup_installer do |spec|
spec.name = 'default'
@@ -958,9 +1143,7 @@ gem 'other', version
end
end
- exe = File.join @gemhome, 'bin', 'executable'
-
- e = assert_raises RuntimeError do
+ e = assert_raise RuntimeError do
instance_eval File.read(exe)
end
@@ -987,7 +1170,7 @@ gem 'other', version
begin
Gem::Specification.reset
- e = assert_raises RuntimeError do
+ e = assert_raise RuntimeError do
instance_eval File.read(exe)
end
ensure
@@ -1007,7 +1190,7 @@ gem 'other', version
end
gemdir = File.join(@gemhome, 'gems', @spec.full_name)
- assert_path_exists File.join gemdir, 'lib', 'code.rb'
+ assert_path_exist File.join gemdir, 'lib', 'code.rb'
installer = util_setup_installer
@@ -1023,26 +1206,39 @@ gem 'other', version
Gem::Package.build @spec
end
end
- installer = Gem::Installer.at @gem
+ installer = Gem::Installer.at @gem, :force => true
build_rake_in do
use_ui @ui do
assert_equal @spec, installer.install
end
end
- assert_path_exists File.join gemdir, 'lib', 'other.rb'
- refute_path_exists File.join gemdir, 'lib', 'code.rb',
+ assert_path_exist File.join gemdir, 'lib', 'other.rb'
+ assert_path_not_exist File.join gemdir, 'lib', 'code.rb',
"code.rb from prior install of same gem shouldn't remain here"
end
def test_install_force
+ _, missing_dep_gem = util_gem 'missing_dep', '1' do |s|
+ s.add_dependency 'doesnt_exist', '1'
+ end
+
use_ui @ui do
- installer = Gem::Installer.at old_ruby_required('= 1.4.6'), :force => true
+ installer = Gem::Installer.at missing_dep_gem, :force => true
installer.install
end
- gem_dir = File.join(@gemhome, 'gems', 'old_ruby_required-1')
- assert_path_exists gem_dir
+ gem_dir = File.join(@gemhome, 'gems', 'missing_dep-1')
+ assert_path_exist gem_dir
+ end
+
+ def test_install_build_root
+ build_root = File.join(@tempdir, 'build_root')
+
+ @gem = setup_base_gem
+ installer = Gem::Installer.at @gem, :build_root => build_root
+
+ assert_equal @spec, installer.install
end
def test_install_missing_dirs
@@ -1060,19 +1256,23 @@ gem 'other', version
assert_directory_exists File.join(Gem.dir, 'doc')
assert_directory_exists File.join(Gem.dir, 'specifications')
- assert_path_exists File.join @gemhome, 'cache', @spec.file_name
- assert_path_exists File.join @gemhome, 'specifications', @spec.spec_name
+ assert_path_exist File.join @gemhome, 'cache', @spec.file_name
+ assert_path_exist File.join @gemhome, 'specifications', @spec.spec_name
end
def test_install_post_build_false
- installer = setup_base_installer
+ @spec = util_spec 'a'
+
+ util_build_gem @spec
+
+ installer = util_installer @spec, @gemhome
Gem.post_build do
false
end
use_ui @ui do
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.install
end
@@ -1082,10 +1282,10 @@ gem 'other', version
end
spec_file = File.join @gemhome, 'specifications', @spec.spec_name
- refute_path_exists spec_file
+ assert_path_not_exist spec_file
gem_dir = File.join @gemhome, 'gems', @spec.full_name
- refute_path_exists gem_dir
+ assert_path_not_exist gem_dir
end
def test_install_post_build_nil
@@ -1100,21 +1300,25 @@ gem 'other', version
end
spec_file = File.join @gemhome, 'specifications', @spec.spec_name
- assert_path_exists spec_file
+ assert_path_exist spec_file
gem_dir = File.join @gemhome, 'gems', @spec.full_name
- assert_path_exists gem_dir
+ assert_path_exist gem_dir
end
def test_install_pre_install_false
- installer = setup_base_installer
+ @spec = util_spec 'a'
+
+ util_build_gem @spec
+
+ installer = util_installer @spec, @gemhome
Gem.pre_install do
false
end
use_ui @ui do
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.install
end
@@ -1124,7 +1328,7 @@ gem 'other', version
end
spec_file = File.join @gemhome, 'specifications', @spec.spec_name
- refute_path_exists spec_file
+ assert_path_not_exist spec_file
end
def test_install_pre_install_nil
@@ -1139,7 +1343,7 @@ gem 'other', version
end
spec_file = File.join @gemhome, 'specifications', @spec.spec_name
- assert_path_exists spec_file
+ assert_path_exist spec_file
end
def test_install_with_message
@@ -1153,7 +1357,7 @@ gem 'other', version
installer.install
end
- assert_match %r|I am a shiny gem!|, @ui.output
+ assert_match %r{I am a shiny gem!}, @ui.output
end
def test_install_with_skipped_message
@@ -1167,7 +1371,7 @@ gem 'other', version
installer.install
end
- refute_match %r|I am a shiny gem!|, @ui.output
+ refute_match %r{I am a shiny gem!}, @ui.output
end
def test_install_extension_dir
@@ -1193,7 +1397,7 @@ gem 'other', version
expected_makefile = File.join gemhome2, 'gems', @spec.full_name, 'Makefile'
- assert_path_exists expected_makefile
+ assert_path_exist expected_makefile
end
def test_install_extension_dir_is_removed_on_reinstall
@@ -1222,15 +1426,15 @@ gem 'other', version
write_file should_be_removed do |io|
io.write "DELETE ME ON REINSTALL"
end
- assert_path_exists should_be_removed
+ assert_path_exist should_be_removed
# reinstall the gem, this is also the same as pristine
use_ui @ui do
- installer = Gem::Installer.at path
+ installer = Gem::Installer.at path, :force => true
installer.install
end
- refute_path_exists should_be_removed
+ assert_path_not_exist should_be_removed
end
def test_install_user_extension_dir
@@ -1258,13 +1462,13 @@ gem 'other', version
expected_makefile = File.join Gem.user_dir, 'gems', @spec.full_name, 'Makefile'
- assert_path_exists expected_makefile
- assert_path_exists expected_extension_dir
- refute_path_exists File.join expected_extension_dir, 'gem_make.out'
+ assert_path_exist expected_makefile
+ assert_path_exist expected_extension_dir
+ assert_path_not_exist File.join expected_extension_dir, 'gem_make.out'
end
def test_find_lib_file_after_install
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
@spec = setup_base_spec
@spec.extensions << "extconf.rb"
@@ -1303,14 +1507,15 @@ gem 'other', version
installer.install
end
- expected = File.join @spec.full_require_paths.find { |path|
+ expected = File.join @spec.full_require_paths.find {|path|
File.exist? File.join path, 'b.rb'
}, 'b.rb'
assert_equal expected, @spec.matches_for_glob('b.rb').first
end
def test_install_extension_and_script
- skip "Makefile creation crashes on jruby" if Gem.java_platform?
+ pend "Makefile creation crashes on jruby" if Gem.java_platform?
+ pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
@spec = setup_base_spec
@spec.extensions << "extconf.rb"
@@ -1338,65 +1543,67 @@ gem 'other', version
RUBY
end
- refute_path_exists File.join @spec.gem_dir, rb
- refute_path_exists File.join @spec.gem_dir, rb2
+ assert_path_not_exist File.join @spec.gem_dir, rb
+ assert_path_not_exist File.join @spec.gem_dir, rb2
use_ui @ui do
path = Gem::Package.build @spec
installer = Gem::Installer.at path
installer.install
end
- assert_path_exists File.join @spec.gem_dir, rb
- assert_path_exists File.join @spec.gem_dir, rb2
+ assert_path_exist File.join @spec.gem_dir, rb
+ assert_path_exist File.join @spec.gem_dir, rb2
end
def test_install_extension_flat
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
- @spec = setup_base_spec
- @spec.require_paths = ["."]
+ begin
+ @spec = setup_base_spec
+ @spec.require_paths = ["."]
- @spec.extensions << "extconf.rb"
+ @spec.extensions << "extconf.rb"
- write_file File.join(@tempdir, "extconf.rb") do |io|
- io.write <<-RUBY
- require "mkmf"
+ write_file File.join(@tempdir, "extconf.rb") do |io|
+ io.write <<-RUBY
+ require "mkmf"
- CONFIG['CC'] = '$(TOUCH) $@ ||'
- CONFIG['LDSHARED'] = '$(TOUCH) $@ ||'
- $ruby = '#{Gem.ruby}'
+ CONFIG['CC'] = '$(TOUCH) $@ ||'
+ CONFIG['LDSHARED'] = '$(TOUCH) $@ ||'
+ $ruby = '#{Gem.ruby}'
- create_makefile("#{@spec.name}")
- RUBY
- end
+ create_makefile("#{@spec.name}")
+ RUBY
+ end
- # empty depend file for no auto dependencies
- @spec.files += %W"depend #{@spec.name}.c".each do |file|
- write_file File.join(@tempdir, file)
- end
+ # empty depend file for no auto dependencies
+ @spec.files += %W[depend #{@spec.name}.c].each do |file|
+ write_file File.join(@tempdir, file)
+ end
- so = File.join(@spec.gem_dir, "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}")
- refute_path_exists so
- use_ui @ui do
- path = Gem::Package.build @spec
+ so = File.join(@spec.gem_dir, "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}")
+ assert_path_not_exist so
+ use_ui @ui do
+ path = Gem::Package.build @spec
- installer = Gem::Installer.at path
- installer.install
- end
- assert_path_exists so
- rescue
- puts '-' * 78
- puts File.read File.join(@gemhome, 'gems', 'a-2', 'Makefile')
- puts '-' * 78
+ installer = Gem::Installer.at path
+ installer.install
+ end
+ assert_path_exist so
+ rescue
+ puts '-' * 78
+ puts File.read File.join(@gemhome, 'gems', 'a-2', 'Makefile')
+ puts '-' * 78
- path = File.join(@gemhome, 'gems', 'a-2', 'gem_make.out')
+ path = File.join(@gemhome, 'gems', 'a-2', 'gem_make.out')
- if File.exist?(path)
- puts File.read(path)
- puts '-' * 78
- end
+ if File.exist?(path)
+ puts File.read(path)
+ puts '-' * 78
+ end
- raise
+ raise
+ end
end
def test_installation_satisfies_dependency_eh
@@ -1426,9 +1633,10 @@ gem 'other', version
installer = setup_base_installer
@spec.add_dependency 'b', '> 5'
installer = util_setup_gem
+ installer.force = false
use_ui @ui do
- assert_raises Gem::InstallError do
+ assert_raise Gem::InstallError do
installer.install
end
end
@@ -1474,54 +1682,6 @@ gem 'other', version
end
end
- def test_pre_install_checks_ruby_version
- use_ui @ui do
- installer = Gem::Installer.at old_ruby_required('= 1.4.6')
- e = assert_raises Gem::RuntimeRequirementNotMetError do
- installer.pre_install_checks
- end
- rv = Gem.ruby_version
- assert_equal "old_ruby_required requires Ruby version = 1.4.6. The current ruby version is #{rv}.",
- e.message
- end
- end
-
- def test_pre_install_checks_ruby_version_with_prereleases
- util_set_RUBY_VERSION '2.6.0', -1, '63539', 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]'
-
- installer = Gem::Installer.at old_ruby_required('>= 2.6.0.preview2')
- assert installer.pre_install_checks
-
- installer = Gem::Installer.at old_ruby_required('> 2.6.0.preview2')
- e = assert_raises Gem::RuntimeRequirementNotMetError do
- assert installer.pre_install_checks
- end
- assert_equal "old_ruby_required requires Ruby version > 2.6.0.preview2. The current ruby version is 2.6.0.preview2.",
- e.message
- ensure
- util_restore_RUBY_VERSION
- end
-
- def test_pre_install_checks_wrong_rubygems_version
- spec = util_spec 'old_rubygems_required', '1' do |s|
- s.required_rubygems_version = '< 0'
- end
-
- util_build_gem spec
-
- gem = File.join(@gemhome, 'cache', spec.file_name)
-
- use_ui @ui do
- installer = Gem::Installer.at gem
- e = assert_raises Gem::RuntimeRequirementNotMetError do
- installer.pre_install_checks
- end
- rgv = Gem::VERSION
- assert_equal "old_rubygems_required requires RubyGems version < 0. The current RubyGems version is #{rgv}. " +
- "Try 'gem update --system' to update RubyGems itself.", e.message
- end
- end
-
def test_pre_install_checks_malicious_name
spec = util_spec '../malicious', '1'
def spec.full_name # so the spec is buildable
@@ -1535,7 +1695,7 @@ gem 'other', version
use_ui @ui do
installer = Gem::Installer.at gem
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.pre_install_checks
end
assert_equal '#<Gem::Specification name=../malicious version=1> has an invalid name', e.message
@@ -1555,7 +1715,7 @@ gem 'other', version
use_ui @ui do
installer = Gem::Installer.at gem
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.pre_install_checks
end
assert_equal "#<Gem::Specification name=malicious\n::Object.const_set(:FROM_EVAL, true)# version=1> has an invalid name", e.message
@@ -1577,7 +1737,7 @@ gem 'other', version
use_ui @ui do
installer = Gem::Installer.at gem
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.pre_install_checks
end
assert_equal "#<Gem::Specification name=malicious version=1> has an invalid require_paths", e.message
@@ -1585,7 +1745,7 @@ gem 'other', version
end
def test_pre_install_checks_malicious_extensions_before_eval
- skip "mswin environment disallow to create file contained the carriage return code." if Gem.win_platform?
+ pend "mswin environment disallow to create file contained the carriage return code." if Gem.win_platform?
spec = util_spec "malicious", '1'
def spec.full_name # so the spec is buildable
@@ -1600,7 +1760,7 @@ gem 'other', version
use_ui @ui do
installer = Gem::Installer.at gem
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.pre_install_checks
end
assert_equal "#<Gem::Specification name=malicious version=1> has an invalid extensions", e.message
@@ -1621,7 +1781,7 @@ gem 'other', version
use_ui @ui do
installer = Gem::Installer.at gem
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.pre_install_checks
end
assert_equal "#<Gem::Specification name=malicious version=1> has an invalid specification_version", e.message
@@ -1643,13 +1803,33 @@ gem 'other', version
use_ui @ui do
installer = Gem::Installer.at gem
installer.ignore_dependencies = true
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
installer.pre_install_checks
end
assert_equal "#<Gem::Specification name=malicious version=1> has an invalid dependencies", e.message
end
end
+ def test_pre_install_checks_malicious_platform_before_eval
+ gem_with_ill_formated_platform = File.expand_path("packages/ill-formatted-platform-1.0.0.10.gem", __dir__)
+
+ installer = Gem::Installer.at(
+ gem_with_ill_formated_platform,
+ :install_dir => @gem_home,
+ :user_install => false,
+ :force => true
+ )
+
+ use_ui @ui do
+ e = assert_raise Gem::InstallError do
+ installer.pre_install_checks
+ end
+
+ assert_equal "x86-mswin32\n system('id > /tmp/nyangawa')# is an invalid platform", e.message
+ assert_empty @ui.output
+ end
+ end
+
def test_shebang
installer = setup_base_installer
@@ -1670,13 +1850,24 @@ gem 'other', version
def test_process_options_build_root
build_root = File.join @tempdir, 'build_root'
+ bin_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'bin')
+ gem_home = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ''))
+ plugins_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'plugins')
@gem = setup_base_gem
- installer = Gem::Installer.at @gem, :build_root => build_root
+ installer = use_ui(@ui) { Gem::Installer.at @gem, :build_root => build_root }
+
+ assert_equal build_root, installer.build_root
+ assert_equal bin_dir, installer.bin_dir
+ assert_equal gem_home, installer.gem_home
- assert_equal Pathname(build_root), installer.build_root
- assert_equal File.join(build_root, @gemhome, 'bin'), installer.bin_dir
- assert_equal File.join(build_root, @gemhome), installer.gem_home
+ errors = @ui.error.split("\n")
+
+ assert_equal "WARNING: You build with buildroot.", errors.shift
+ assert_equal " Build root: #{build_root}", errors.shift
+ assert_equal " Bin dir: #{bin_dir}", errors.shift
+ assert_equal " Gem home: #{gem_home}", errors.shift
+ assert_equal " Plugins dir: #{plugins_dir}", errors.shift
end
def test_shebang_arguments
@@ -1726,9 +1917,9 @@ gem 'other', version
shebang = installer.shebang 'executable'
- env_shebang = "/usr/bin/env" unless Gem.win_platform?
+ bin_env = get_bin_env
- assert_equal("#!#{env_shebang} #{RbConfig::CONFIG['ruby_install_name']}",
+ assert_equal("#!#{bin_env} #{RbConfig::CONFIG['ruby_install_name']}",
shebang)
end
@@ -1807,10 +1998,18 @@ gem 'other', version
assert_equal "#!test", shebang
end
+ def get_bin_env
+ if win_platform?
+ ""
+ else
+ %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) }
+ end
+ end
+
def test_shebang_custom_with_expands
installer = setup_base_installer
- bin_env = win_platform? ? '' : '/usr/bin/env'
+ bin_env = get_bin_env
conf = Gem::ConfigFile.new []
conf[:custom_shebang] = '1 $env 2 $ruby 3 $exec 4 $name'
@@ -1826,7 +2025,7 @@ gem 'other', version
def test_shebang_custom_with_expands_and_arguments
installer = setup_base_installer
- bin_env = win_platform? ? '' : '/usr/bin/env'
+ bin_env = get_bin_env
conf = Gem::ConfigFile.new []
conf[:custom_shebang] = '1 $env 2 $ruby 3 $exec'
@@ -1848,14 +2047,14 @@ gem 'other', version
installer.unpack dest
end
- assert_path_exists File.join dest, 'lib', 'code.rb'
- assert_path_exists File.join dest, 'bin', 'executable'
+ assert_path_exist File.join dest, 'lib', 'code.rb'
+ assert_path_exist File.join dest, 'bin', 'executable'
end
def test_write_build_info_file
installer = setup_base_installer
- refute_path_exists @spec.build_info_file
+ assert_path_not_exist @spec.build_info_file
installer.build_args = %w[
--with-libyaml-dir /usr/local/Cellar/libyaml/0.1.4
@@ -1863,7 +2062,7 @@ gem 'other', version
installer.write_build_info_file
- assert_path_exists @spec.build_info_file
+ assert_path_exist @spec.build_info_file
expected = "--with-libyaml-dir\n/usr/local/Cellar/libyaml/0.1.4\n"
@@ -1873,11 +2072,11 @@ gem 'other', version
def test_write_build_info_file_empty
installer = setup_base_installer
- refute_path_exists @spec.build_info_file
+ assert_path_not_exist @spec.build_info_file
installer.write_build_info_file
- refute_path_exists @spec.build_info_file
+ assert_path_not_exist @spec.build_info_file
end
def test_write_build_info_file_install_dir
@@ -1890,8 +2089,8 @@ gem 'other', version
installer.write_build_info_file
- refute_path_exists @spec.build_info_file
- assert_path_exists \
+ assert_path_not_exist @spec.build_info_file
+ assert_path_exist \
File.join("#{@gemhome}2", 'build_info', "#{@spec.full_name}.info")
end
@@ -1901,27 +2100,27 @@ gem 'other', version
gem = File.join @gemhome, @spec.file_name
FileUtils.mv cache_file, gem
- refute_path_exists cache_file
+ assert_path_not_exist cache_file
installer = Gem::Installer.at gem
installer.gem_home = @gemhome
installer.write_cache_file
- assert_path_exists cache_file
+ assert_path_exist cache_file
end
def test_write_spec
@spec = setup_base_spec
FileUtils.rm @spec.spec_file
- refute_path_exists @spec.spec_file
+ assert_path_not_exist @spec.spec_file
installer = Gem::Installer.for_spec @spec
installer.gem_home = @gemhome
installer.write_spec
- assert_path_exists @spec.spec_file
+ assert_path_exist @spec.spec_file
loaded = Gem::Specification.load @spec.spec_file
@@ -1933,7 +2132,7 @@ gem 'other', version
def test_write_spec_writes_cached_spec
@spec = setup_base_spec
FileUtils.rm @spec.spec_file
- refute_path_exists @spec.spec_file
+ assert_path_not_exist @spec.spec_file
@spec.files = %w[a.rb b.rb c.rb]
@@ -1951,7 +2150,7 @@ gem 'other', version
def test_dir
installer = setup_base_installer
- assert_match %r!/gemhome/gems/a-2$!, installer.dir
+ assert_match %r{/gemhome/gems/a-2$}, installer.dir
end
def test_default_gem_loaded_from
@@ -1976,7 +2175,7 @@ gem 'other', version
assert_directory_exists File.join(@spec.gem_dir, 'bin')
installed_exec = File.join @spec.gem_dir, 'bin', 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
assert_directory_exists File.join(Gem.default_dir, 'specifications')
assert_directory_exists File.join(Gem.default_dir, 'specifications', 'default')
@@ -1988,10 +2187,16 @@ gem 'other', version
assert_directory_exists util_inst_bindir
installed_exec = File.join util_inst_bindir, 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
wrapper = File.read installed_exec
- refute_match %r|generated by RubyGems|, wrapper
+
+ if symlink_supported?
+ refute_match %r{generated by RubyGems}, wrapper
+ else # when symlink not supported, it warns and fallbacks back to installing wrapper
+ assert_match %r{Unable to use symlinks, installing wrapper}, @ui.error
+ assert_match %r{generated by RubyGems}, wrapper
+ end
end
def test_default_gem_with_wrappers
@@ -2008,10 +2213,10 @@ gem 'other', version
assert_directory_exists util_inst_bindir
installed_exec = File.join util_inst_bindir, 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r|generated by RubyGems|, wrapper
+ assert_match %r{generated by RubyGems}, wrapper
end
def test_default_gem_with_exe_as_bindir
@@ -2034,7 +2239,7 @@ gem 'other', version
assert_directory_exists File.join(@spec.gem_dir, 'exe')
installed_exec = File.join @spec.gem_dir, 'exe', 'executable'
- assert_path_exists installed_exec
+ assert_path_exist installed_exec
assert_directory_exists File.join(Gem.default_dir, 'specifications')
assert_directory_exists File.join(Gem.default_dir, 'specifications', 'default')
@@ -2044,6 +2249,23 @@ gem 'other', version
assert_equal ['exe/executable'], default_spec.files
end
+ def test_default_gem_to_specific_install_dir
+ @gem = setup_base_gem
+ installer = util_installer @spec, "#{@gemhome}2"
+ installer.options[:install_as_default] = true
+
+ use_ui @ui do
+ installer.install
+ end
+
+ assert_directory_exists File.join("#{@gemhome}2", 'specifications')
+ assert_directory_exists File.join("#{@gemhome}2", 'specifications', 'default')
+
+ default_spec = eval File.read File.join("#{@gemhome}2", 'specifications', 'default', 'a-2.gemspec')
+ assert_equal Gem::Version.new("2"), default_spec.version
+ assert_equal ['bin/executable'], default_spec.files
+ end
+
def test_package_attribute
gem = quick_gem 'c' do |spec|
util_make_exec spec, '#!/usr/bin/ruby', 'exe'
@@ -2054,14 +2276,14 @@ gem 'other', version
assert_kind_of(Gem::Package, installer.package)
end
- def old_ruby_required(requirement)
- spec = util_spec 'old_ruby_required', '1' do |s|
- s.required_ruby_version = requirement
+ def test_gem_attribute
+ gem = quick_gem 'c' do |spec|
+ util_make_exec spec, '#!/usr/bin/ruby', 'exe'
end
- util_build_gem spec
-
- spec.cache_file
+ installer = util_installer(gem, @gemhome)
+ assert_respond_to(installer, :gem)
+ assert_kind_of(String, installer.gem)
end
def util_execless
@@ -2084,7 +2306,6 @@ gem 'other', version
end
def mask
- 0100755 & (~File.umask)
+ 0100755
end
-
end
diff --git a/test/rubygems/test_gem_local_remote_options.rb b/test/rubygems/test_gem_local_remote_options.rb
index 6c21300c2a..948d1e3981 100644
--- a/test/rubygems/test_gem_local_remote_options.rb
+++ b/test/rubygems/test_gem_local_remote_options.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/local_remote_options'
require 'rubygems/command'
class TestGemLocalRemoteOptions < Gem::TestCase
-
def setup
super
@@ -124,11 +123,10 @@ class TestGemLocalRemoteOptions < Gem::TestCase
s1 = 'htp://more-gems.example.com'
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
@cmd.handle_options %W[--source #{s1}]
end
assert_equal [@gem_repo], Gem.sources
end
-
end
diff --git a/test/rubygems/test_gem_name_tuple.rb b/test/rubygems/test_gem_name_tuple.rb
index 5331e1cdbb..d87db9bc45 100644
--- a/test/rubygems/test_gem_name_tuple.rb
+++ b/test/rubygems/test_gem_name_tuple.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/name_tuple'
class TestGemNameTuple < Gem::TestCase
-
def test_full_name
n = Gem::NameTuple.new "a", Gem::Version.new(0), "ruby"
assert_equal "a-0", n.full_name
@@ -40,5 +39,4 @@ class TestGemNameTuple < Gem::TestCase
assert_equal 1, a_p.<=>(a)
end
-
end
diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb
index 64ceda39b2..48dcbee9f1 100644
--- a/test/rubygems/test_gem_package.rb
+++ b/test/rubygems/test_gem_package.rb
@@ -1,11 +1,9 @@
-# coding: utf-8
# frozen_string_literal: true
-require 'rubygems/package/tar_test_case'
-require 'digest'
+require_relative 'package/tar_test_case'
+require 'rubygems/openssl'
class TestGemPackage < Gem::Package::TarTestCase
-
def setup
super
@@ -24,7 +22,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_class_new_old_format
- skip "jruby can't require the simple_gem file" if Gem.java_platform?
+ pend "jruby can't require the simple_gem file" if Gem.java_platform?
require_relative "simple_gem"
File.open 'old_format.gem', 'wb' do |io|
io.write SIMPLE_GEM
@@ -86,24 +84,21 @@ class TestGemPackage < Gem::Package::TarTestCase
io.write spec.to_yaml
end
- metadata_sha256 = Digest::SHA256.hexdigest s.string
- metadata_sha512 = Digest::SHA512.hexdigest s.string
+ metadata_sha256 = OpenSSL::Digest::SHA256.hexdigest s.string
+ metadata_sha512 = OpenSSL::Digest::SHA512.hexdigest s.string
expected = {
'SHA512' => {
'metadata.gz' => metadata_sha512,
- 'data.tar.gz' => Digest::SHA512.hexdigest(tar),
- }
- }
-
- if defined?(OpenSSL::Digest)
- expected['SHA256'] = {
+ 'data.tar.gz' => OpenSSL::Digest::SHA512.hexdigest(tar),
+ },
+ 'SHA256' => {
'metadata.gz' => metadata_sha256,
- 'data.tar.gz' => Digest::SHA256.hexdigest(tar),
- }
- end
+ 'data.tar.gz' => OpenSSL::Digest::SHA256.hexdigest(tar),
+ },
+ }
- assert_equal expected, YAML.load(checksums)
+ assert_equal expected, load_yaml(checksums)
end
def test_build_time_uses_source_date_epoch
@@ -151,7 +146,7 @@ class TestGemPackage < Gem::Package::TarTestCase
FileUtils.mkdir_p 'lib/empty'
- File.open 'lib/code.rb', 'w' do |io|
+ File.open 'lib/code.rb', 'w' do |io|
io.write '# lib/code.rb'
end
@@ -185,7 +180,7 @@ class TestGemPackage < Gem::Package::TarTestCase
FileUtils.mkdir_p 'lib'
- File.open 'lib/code.rb', 'w' do |io|
+ File.open 'lib/code.rb', 'w' do |io|
io.write '# lib/code.rb'
end
@@ -195,7 +190,7 @@ class TestGemPackage < Gem::Package::TarTestCase
File.symlink('../lib/code.rb', 'lib/code_sym2.rb')
rescue Errno::EACCES => e
if win_platform?
- skip "symlink - must be admin with no UAC on Windows"
+ pend "symlink - must be admin with no UAC on Windows"
else
raise e
end
@@ -223,7 +218,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
assert_equal %w[lib/code.rb], files
- assert_equal [{'lib/code_sym.rb' => 'lib/code.rb'}, {'lib/code_sym2.rb' => '../lib/code.rb'}], symlinks
+ assert_equal [{'lib/code_sym.rb' => 'code.rb'}, {'lib/code_sym2.rb' => '../lib/code.rb'}], symlinks
end
def test_build
@@ -245,7 +240,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.build
assert_equal Gem::VERSION, spec.rubygems_version
- assert_path_exists spec.file_name
+ assert_path_exist spec.file_name
reader = Gem::Package.new spec.file_name
assert_equal spec, reader.spec
@@ -257,7 +252,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_build_auto_signed
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
FileUtils.mkdir_p File.join(Gem.user_home, '.gem')
@@ -284,7 +279,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.build
assert_equal Gem::VERSION, spec.rubygems_version
- assert_path_exists spec.file_name
+ assert_path_exist spec.file_name
reader = Gem::Package.new spec.file_name
assert reader.verify
@@ -300,7 +295,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_build_auto_signed_encrypted_key
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
FileUtils.mkdir_p File.join(Gem.user_home, '.gem')
@@ -327,7 +322,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.build
assert_equal Gem::VERSION, spec.rubygems_version
- assert_path_exists spec.file_name
+ assert_path_exist spec.file_name
reader = Gem::Package.new spec.file_name
assert reader.verify
@@ -348,7 +343,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new spec.file_name
package.spec = spec
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
package.build
end
@@ -361,7 +356,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new spec.file_name
package.spec = spec
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
package.build true, true
end
@@ -369,7 +364,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_build_signed
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
spec = Gem::Specification.new 'build', '1'
spec.summary = 'build'
@@ -390,7 +385,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.build
assert_equal Gem::VERSION, spec.rubygems_version
- assert_path_exists spec.file_name
+ assert_path_exist spec.file_name
reader = Gem::Package.new spec.file_name
assert reader.verify
@@ -406,7 +401,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_build_signed_encrypted_key
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
spec = Gem::Specification.new 'build', '1'
spec.summary = 'build'
@@ -427,7 +422,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.build
assert_equal Gem::VERSION, spec.rubygems_version
- assert_path_exists spec.file_name
+ assert_path_exist spec.file_name
reader = Gem::Package.new spec.file_name
assert reader.verify
@@ -443,7 +438,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_raw_spec
- data_tgz = util_tar_gz { }
+ data_tgz = util_tar_gz {}
gem = util_tar do |tar|
tar.add_file 'data.tar.gz', 0644 do |io|
@@ -481,7 +476,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.extract_files @destination
extracted = File.join @destination, 'lib/code.rb'
- assert_path_exists extracted
+ assert_path_exist extracted
mask = 0100666 & (~File.umask)
@@ -490,7 +485,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_extract_files_empty
- data_tgz = util_tar_gz { }
+ data_tgz = util_tar_gz {}
gem = util_tar do |tar|
tar.add_file 'data.tar.gz', 0644 do |io|
@@ -512,7 +507,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.extract_files @destination
- assert_path_exists @destination
+ assert_path_exist @destination
end
def test_extract_tar_gz_absolute
@@ -524,7 +519,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
end
- e = assert_raises Gem::Package::PathError do
+ e = assert_raise Gem::Package::PathError do
package.extract_tar_gz tgz_io, @destination
end
@@ -536,11 +531,11 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new @gem
tgz_io = util_tar_gz do |tar|
- tar.add_file 'relative.rb', 0644 do |io|
+ tar.add_file 'relative.rb', 0644 do |io|
io.write 'hi'
end
- tar.mkdir 'lib', 0755
+ tar.mkdir 'lib', 0755
tar.add_symlink 'lib/foo.rb', '../relative.rb', 0644
end
@@ -548,14 +543,14 @@ class TestGemPackage < Gem::Package::TarTestCase
package.extract_tar_gz tgz_io, @destination
rescue Errno::EACCES => e
if win_platform?
- skip "symlink - must be admin with no UAC on Windows"
+ pend "symlink - must be admin with no UAC on Windows"
else
raise e
end
end
extracted = File.join @destination, 'lib/foo.rb'
- assert_path_exists extracted
+ assert_path_exist extracted
assert_equal '../relative.rb',
File.readlink(extracted)
assert_equal 'hi',
@@ -579,18 +574,19 @@ class TestGemPackage < Gem::Package::TarTestCase
destination_subdir = File.join @destination, 'subdir'
FileUtils.mkdir_p destination_subdir
- e = assert_raises(Gem::Package::PathError, Errno::EACCES) do
+ expected_exceptions = win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError]
+
+ e = assert_raise(*expected_exceptions) do
package.extract_tar_gz tgz_io, destination_subdir
end
- if Gem::Package::PathError === e
- assert_equal("installing into parent path lib/link/outside.txt of " +
- "#{destination_subdir} is not allowed", e.message)
- elsif win_platform?
- skip "symlink - must be admin with no UAC on Windows"
- else
- raise e
- end
+ pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e
+
+ assert_equal("installing symlink 'lib/link' pointing to parent path #{@destination} of " +
+ "#{destination_subdir} is not allowed", e.message)
+
+ assert_path_not_exist File.join(@destination, "outside.txt")
+ assert_path_not_exist File.join(destination_subdir, "lib/link")
end
def test_extract_symlink_parent_doesnt_delete_user_dir
@@ -606,25 +602,27 @@ class TestGemPackage < Gem::Package::TarTestCase
destination_user_subdir = File.join destination_user_dir, 'dir'
FileUtils.mkdir_p destination_user_subdir
+ pend "TMPDIR seems too long to add it as symlink into tar" if destination_user_dir.size > 90
+
tgz_io = util_tar_gz do |tar|
tar.add_symlink 'link', destination_user_dir, 16877
tar.add_symlink 'link/dir', '.', 16877
end
- e = assert_raises(Gem::Package::PathError, Errno::EACCES) do
+ expected_exceptions = win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError]
+
+ e = assert_raise(*expected_exceptions) do
package.extract_tar_gz tgz_io, destination_subdir
end
- assert_path_exists destination_user_subdir
+ pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e
- if Gem::Package::PathError === e
- assert_equal("installing into parent path #{destination_user_subdir} of " +
- "#{destination_subdir} is not allowed", e.message)
- elsif win_platform?
- skip "symlink - must be admin with no UAC on Windows"
- else
- raise e
- end
+ assert_equal("installing symlink 'link' pointing to parent path #{destination_user_dir} of " +
+ "#{destination_subdir} is not allowed", e.message)
+
+ assert_path_exist destination_user_subdir
+ assert_path_not_exist File.join(destination_subdir, "link/dir")
+ assert_path_not_exist File.join(destination_subdir, "link")
end
def test_extract_tar_gz_directory
@@ -635,16 +633,16 @@ class TestGemPackage < Gem::Package::TarTestCase
tar.add_file 'lib/foo.rb', 0644 do |io|
io.write 'hi'
end
- tar.mkdir 'lib/foo', 0755
+ tar.mkdir 'lib/foo', 0755
end
package.extract_tar_gz tgz_io, @destination
extracted = File.join @destination, 'lib/foo.rb'
- assert_path_exists extracted
+ assert_path_exist extracted
extracted = File.join @destination, 'lib/foo'
- assert_path_exists extracted
+ assert_path_exist extracted
end
def test_extract_tar_gz_dot_slash
@@ -659,7 +657,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.extract_tar_gz tgz_io, @destination
extracted = File.join @destination, 'dot_slash.rb'
- assert_path_exists extracted
+ assert_path_exist extracted
end
def test_extract_tar_gz_dot_file
@@ -674,7 +672,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.extract_tar_gz tgz_io, @destination
extracted = File.join @destination, '.dot_file.rb'
- assert_path_exists extracted
+ assert_path_exist extracted
end
if Gem.win_platform?
@@ -690,7 +688,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package.extract_tar_gz tgz_io, @destination.upcase
extracted = File.join @destination, 'foo/file.rb'
- assert_path_exists extracted
+ assert_path_exist extracted
end
end
@@ -709,7 +707,7 @@ class TestGemPackage < Gem::Package::TarTestCase
def test_install_location_absolute
package = Gem::Package.new @gem
- e = assert_raises Gem::Package::PathError do
+ e = assert_raise Gem::Package::PathError do
package.install_location '/absolute.rb', @destination
end
@@ -750,7 +748,7 @@ class TestGemPackage < Gem::Package::TarTestCase
def test_install_location_relative
package = Gem::Package.new @gem
- e = assert_raises Gem::Package::PathError do
+ e = assert_raise Gem::Package::PathError do
package.install_location '../relative.rb', @destination
end
@@ -765,7 +763,7 @@ class TestGemPackage < Gem::Package::TarTestCase
filename = "../#{File.basename(@destination)}suffix.rb"
- e = assert_raises Gem::Package::PathError do
+ e = assert_raise Gem::Package::PathError do
package.install_location filename, @destination
end
@@ -835,7 +833,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new 'mismatch.gem'
- e = assert_raises Gem::Package::FormatError do
+ e = assert_raise Gem::Package::FormatError do
package.verify
end
@@ -859,7 +857,7 @@ class TestGemPackage < Gem::Package::TarTestCase
io.write metadata_gz
end
- digest = Digest::SHA1.new
+ digest = OpenSSL::Digest::SHA1.new
digest << metadata_gz
checksums = {
@@ -889,7 +887,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_verify_corrupt
- skip "jruby strips the null byte and does not think it's corrupt" if Gem.java_platform?
+ pend "jruby strips the null byte and does not think it's corrupt" if Gem.java_platform?
tf = Tempfile.open 'corrupt' do |io|
data = Gem::Util.gzip 'a' * 10
io.write \
@@ -899,7 +897,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new io.path
- e = assert_raises Gem::Package::FormatError do
+ e = assert_raise Gem::Package::FormatError do
package.verify
end
@@ -915,7 +913,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new 'empty.gem'
- e = assert_raises Gem::Package::FormatError do
+ e = assert_raise Gem::Package::FormatError do
package.verify
end
@@ -925,12 +923,12 @@ class TestGemPackage < Gem::Package::TarTestCase
def test_verify_nonexistent
package = Gem::Package.new 'nonexistent.gem'
- e = assert_raises Gem::Package::FormatError do
+ e = assert_raise Gem::Package::FormatError do
package.verify
end
- assert_match %r%^No such file or directory%, e.message
- assert_match %r%nonexistent.gem$%, e.message
+ assert_match %r{^No such file or directory}, e.message
+ assert_match %r{nonexistent.gem$}, e.message
end
def test_verify_duplicate_file
@@ -940,7 +938,7 @@ class TestGemPackage < Gem::Package::TarTestCase
build = Gem::Package.new @gem
build.spec = @spec
build.setup_signer
- open @gem, 'wb' do |gem_io|
+ File.open @gem, 'wb' do |gem_io|
Gem::Package::TarWriter.new gem_io do |gem|
build.add_metadata gem
build.add_contents gem
@@ -952,7 +950,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new @gem
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
package.verify
end
@@ -960,12 +958,12 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_verify_security_policy
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
package = Gem::Package.new @gem
package.security_policy = Gem::Security::HighSecurity
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
package.verify
end
@@ -977,7 +975,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_verify_security_policy_low_security
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
@spec.cert_chain = [PUBLIC_CERT.to_pem]
@spec.signing_key = PRIVATE_KEY
@@ -997,7 +995,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_verify_security_policy_checksum_missing
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
@spec.cert_chain = [PUBLIC_CERT.to_pem]
@spec.signing_key = PRIVATE_KEY
@@ -1018,7 +1016,7 @@ class TestGemPackage < Gem::Package::TarTestCase
bogus_data = Gem::Util.gzip 'hello'
fake_signer = Class.new do
def digest_name; 'SHA512'; end
- def digest_algorithm; Digest(:SHA512); end
+ def digest_algorithm; OpenSSL::Digest(:SHA512).new; end
def key; 'key'; end
def sign(*); 'fake_sig'; end
end
@@ -1035,7 +1033,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new @gem
package.security_policy = Gem::Security::HighSecurity
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
package.verify
end
@@ -1052,7 +1050,7 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new 'bad.gem'
- e = assert_raises Gem::Package::FormatError do
+ e = assert_raise Gem::Package::FormatError do
package.verify
end
@@ -1068,11 +1066,22 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new @gem
- e = assert_raises Gem::Package::FormatError do
- package.verify_entry entry
+ _, err = use_ui @ui do
+ e = nil
+
+ out_err = capture_output do
+ e = assert_raise ArgumentError do
+ package.verify_entry entry
+ end
+ end
+
+ assert_equal "whatever", e.message
+ assert_equal "full_name", e.backtrace_locations.first.label
+
+ out_err
end
- assert_equal "package is corrupt, exception while verifying: whatever (ArgumentError) in #{@gem}", e.message
+ assert_equal "Exception while verifying #{@gem}\n", err
valid_metadata = ["metadata", "metadata.gz"]
valid_metadata.each do |vm|
@@ -1097,7 +1106,7 @@ class TestGemPackage < Gem::Package::TarTestCase
$bad_name = vm
entry = Object.new
- def entry.full_name() $bad_name end
+ def entry.full_name() $bad_name end
package = Gem::Package.new(@gem)
package.instance_variable_set(:@files, [])
@@ -1132,11 +1141,18 @@ class TestGemPackage < Gem::Package::TarTestCase
def test_spec_from_io_raises_gem_error_for_io_not_at_start
io = StringIO.new Gem.read_binary @gem
io.read(1)
- assert_raises(Gem::Package::Error) do
+ assert_raise(Gem::Package::Error) do
Gem::Package.new io
end
end
+ def test_contents_from_io
+ io = StringIO.new Gem.read_binary @gem
+ package = Gem::Package.new io
+
+ assert_equal %w[lib/code.rb], package.contents
+ end
+
def util_tar
tar_io = StringIO.new
@@ -1161,5 +1177,4 @@ class TestGemPackage < Gem::Package::TarTestCase
StringIO.new tgz_io.string
end
-
end
diff --git a/test/rubygems/test_gem_package_old.rb b/test/rubygems/test_gem_package_old.rb
index d2ce59cfdd..945340a96a 100644
--- a/test/rubygems/test_gem_package_old.rb
+++ b/test/rubygems/test_gem_package_old.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
unless Gem.java_platform? # jruby can't require the simple_gem file
require 'rubygems/simple_gem'
class TestGemPackageOld < Gem::TestCase
-
def setup
super
@@ -24,11 +23,11 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
end
def test_contents_security_policy
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
@package.security_policy = Gem::Security::AlmostNoSecurity
- assert_raises Gem::Security::Exception do
+ assert_raise Gem::Security::Exception do
@package.contents
end
end
@@ -37,7 +36,7 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
@package.extract_files @destination
extracted = File.join @destination, 'lib/foo.rb'
- assert_path_exists extracted
+ assert_path_exist extracted
mask = 0100644 & (~File.umask)
@@ -45,11 +44,11 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
end
def test_extract_files_security_policy
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
@package.security_policy = Gem::Security::AlmostNoSecurity
- assert_raises Gem::Security::Exception do
+ assert_raise Gem::Security::Exception do
@package.extract_files @destination
end
end
@@ -59,17 +58,17 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
end
def test_spec_security_policy
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
@package.security_policy = Gem::Security::AlmostNoSecurity
- assert_raises Gem::Security::Exception do
+ assert_raise Gem::Security::Exception do
@package.spec
end
end
def test_verify
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
assert @package.verify
@@ -79,7 +78,7 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
@package.security_policy = Gem::Security::AlmostNoSecurity
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@package.verify
end
@@ -87,6 +86,5 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
'and cannot be verified',
e.message
end
-
end
end
diff --git a/test/rubygems/test_gem_package_tar_header.rb b/test/rubygems/test_gem_package_tar_header.rb
index 7e59073407..0e72a72d6a 100644
--- a/test/rubygems/test_gem_package_tar_header.rb
+++ b/test/rubygems/test_gem_package_tar_header.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/package/tar_test_case'
+require_relative 'package/tar_test_case'
require 'rubygems/package'
class TestGemPackageTarHeader < Gem::Package::TarTestCase
-
def setup
super
@@ -58,19 +57,19 @@ class TestGemPackageTarHeader < Gem::Package::TarTestCase
end
def test_initialize_bad
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
Gem::Package::TarHeader.new :name => '', :size => '', :mode => ''
end
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
Gem::Package::TarHeader.new :name => '', :size => '', :prefix => ''
end
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
Gem::Package::TarHeader.new :name => '', :prefix => '', :mode => ''
end
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
Gem::Package::TarHeader.new :prefix => '', :size => '', :mode => ''
end
end
@@ -157,7 +156,7 @@ group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
# overwrite the size field
header_s[124, 12] = val
io = TempIO.new header_s
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
Gem::Package::TarHeader.from io
end
io.close!
@@ -205,4 +204,22 @@ tjmather\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
assert_equal 6932, tar_header.checksum
end
+ def test_spaces_in_headers
+ stream = StringIO.new(
+ <<-EOF.dup.force_encoding('binary').split("\n").join
+Access_Points_09202018.csv
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
+\x00\x00100777 \x00 0 \x00 0 \x00 4357 13545040367 104501
+\x000
+ EOF
+ )
+
+ tar_header = Gem::Package::TarHeader.from stream
+
+ assert_equal 0, tar_header.uid
+ assert_equal 0, tar_header.gid
+ end
end
diff --git a/test/rubygems/test_gem_package_tar_reader.rb b/test/rubygems/test_gem_package_tar_reader.rb
index 489685d09d..277b552f1b 100644
--- a/test/rubygems/test_gem_package_tar_reader.rb
+++ b/test/rubygems/test_gem_package_tar_reader.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/package/tar_test_case'
+require_relative 'package/tar_test_case'
require 'rubygems/package'
class TestGemPackageTarReader < Gem::Package::TarTestCase
-
def test_each_entry
tar = tar_dir_header "foo", "bar", 0, Time.now
tar << tar_file_header("bar", "baz", 0, 0, Time.now)
@@ -85,5 +84,4 @@ class TestGemPackageTarReader < Gem::Package::TarTestCase
ensure
io.close!
end
-
end
diff --git a/test/rubygems/test_gem_package_tar_reader_entry.rb b/test/rubygems/test_gem_package_tar_reader_entry.rb
index 87f3471678..1be5870146 100644
--- a/test/rubygems/test_gem_package_tar_reader_entry.rb
+++ b/test/rubygems/test_gem_package_tar_reader_entry.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/package/tar_test_case'
+require_relative 'package/tar_test_case'
require 'rubygems/package'
class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
-
def setup
super
@@ -43,19 +42,19 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
assert @entry.bytes_read
- e = assert_raises(IOError) { @entry.eof? }
+ e = assert_raise(IOError) { @entry.eof? }
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
- e = assert_raises(IOError) { @entry.getc }
+ e = assert_raise(IOError) { @entry.getc }
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
- e = assert_raises(IOError) { @entry.pos }
+ e = assert_raise(IOError) { @entry.pos }
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
- e = assert_raises(IOError) { @entry.read }
+ e = assert_raise(IOError) { @entry.read }
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
- e = assert_raises(IOError) { @entry.rewind }
+ e = assert_raise(IOError) { @entry.rewind }
assert_equal 'closed Gem::Package::TarReader::Entry', e.message
end
@@ -76,10 +75,10 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
end
def test_full_name_null
- skip "jruby strips the null byte and does not think it's corrupt" if Gem.java_platform?
+ pend "jruby strips the null byte and does not think it's corrupt" if Gem.java_platform?
@entry.header.prefix << "\000"
- e = assert_raises Gem::Package::TarInvalidError do
+ e = assert_raise Gem::Package::TarInvalidError do
@entry.full_name
end
@@ -135,7 +134,7 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
end
def test_readpartial
- assert_raises(EOFError) do
+ assert_raise(EOFError) do
@entry.read(@contents.size)
@entry.readpartial(1)
end
@@ -150,5 +149,4 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
assert_equal char, @entry.getc
end
-
end
diff --git a/test/rubygems/test_gem_package_tar_writer.rb b/test/rubygems/test_gem_package_tar_writer.rb
index 903d681c7e..31a91fa21a 100644
--- a/test/rubygems/test_gem_package_tar_writer.rb
+++ b/test/rubygems/test_gem_package_tar_writer.rb
@@ -1,10 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/package/tar_test_case'
+require_relative 'package/tar_test_case'
require 'rubygems/package/tar_writer'
-require 'minitest/mock'
class TestGemPackageTarWriter < Gem::Package::TarTestCase
-
def setup
super
@@ -72,7 +70,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_add_file_digest
- digest_algorithms = Digest::SHA1, Digest::SHA512
+ digest_algorithms = Digest::SHA1.new, Digest::SHA512.new
Time.stub :now, Time.at(1458518157) do
digests = @tar_writer.add_file_digest 'x', 0644, digest_algorithms do |io|
@@ -95,7 +93,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_add_file_digest_multiple
- digest_algorithms = [Digest::SHA1, Digest::SHA512]
+ digest_algorithms = [Digest::SHA1.new, Digest::SHA512.new]
Time.stub :now, Time.at(1458518157) do
digests = @tar_writer.add_file_digest 'x', 0644, digest_algorithms do |io|
@@ -118,7 +116,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_add_file_signer
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
+ pend 'openssl is missing' unless Gem::HAVE_OPENSSL
signer = Gem::Security::Signer.new PRIVATE_KEY, [PUBLIC_CERT]
@@ -151,13 +149,12 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
signer = Gem::Security::Signer.new nil, nil
Time.stub :now, Time.at(1458518157) do
-
@tar_writer.add_file_signed 'x', 0644, signer do |io|
io.write 'a' * 10
end
assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now),
- @io.string[0, 512])
+ @io.string[0, 512])
end
assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
@@ -171,11 +168,11 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now),
- @io.string[0, 512])
- end
+ @io.string[0, 512])
- assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
- assert_equal 1024, @io.pos
+ assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
+ assert_equal 1024, @io.pos
+ end
end
def test_add_file_simple_source_date_epoch
@@ -186,7 +183,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc),
- @io.string[0, 512])
+ @io.string[0, 512])
end
end
@@ -195,14 +192,14 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
@tar_writer.add_file_simple 'x', 0, 100
assert_headers_equal tar_file_header('x', '', 0, 100, Time.now),
- @io.string[0, 512]
+ @io.string[0, 512]
end
assert_equal "\0" * 512, @io.string[512, 512]
end
def test_add_file_simple_data
- @tar_writer.add_file_simple("lib/foo/bar", 0, 10) { |f| f.write @data }
+ @tar_writer.add_file_simple("lib/foo/bar", 0, 10) {|f| f.write @data }
@tar_writer.flush
assert_equal @data + ("\0" * (512 - @data.size)),
@@ -210,7 +207,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_add_file_simple_size
- assert_raises Gem::Package::TarWriter::FileOverflow do
+ assert_raise Gem::Package::TarWriter::FileOverflow do
@tar_writer.add_file_simple("lib/foo/bar", 0, 10) do |io|
io.write "1" * 11
end
@@ -222,27 +219,27 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
assert_equal "\0" * 1024, @io.string
- e = assert_raises IOError do
+ e = assert_raise IOError do
@tar_writer.close
end
assert_equal 'closed Gem::Package::TarWriter', e.message
- e = assert_raises IOError do
+ e = assert_raise IOError do
@tar_writer.flush
end
assert_equal 'closed Gem::Package::TarWriter', e.message
- e = assert_raises IOError do
+ e = assert_raise IOError do
@tar_writer.add_file 'x', 0
end
assert_equal 'closed Gem::Package::TarWriter', e.message
- e = assert_raises IOError do
+ e = assert_raise IOError do
@tar_writer.add_file_simple 'x', 0, 0
end
assert_equal 'closed Gem::Package::TarWriter', e.message
- e = assert_raises IOError do
+ e = assert_raise IOError do
@tar_writer.mkdir 'x', 0
end
assert_equal 'closed Gem::Package::TarWriter', e.message
@@ -298,7 +295,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
assert_equal ['b' * 100, 'a'], @tar_writer.split_name(name)
name = File.join 'a', 'b' * 101
- exception = assert_raises Gem::Package::TooLongFileName do
+ exception = assert_raise Gem::Package::TooLongFileName do
@tar_writer.split_name name
end
assert_includes exception.message, name
@@ -306,7 +303,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
# note, GNU tar 1.28 is unable to handle this case too,
# tested with "tar --format=ustar -cPf /tmp/foo.tartar -- /aaaaaa....a"
name = '/' + 'a' * 100
- exception = assert_raises Gem::Package::TooLongFileName do
+ exception = assert_raise Gem::Package::TooLongFileName do
@tar_writer.split_name name
end
assert_includes exception.message, name
@@ -317,7 +314,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
assert_equal ['b', 'a' * 155], @tar_writer.split_name(name)
name = File.join 'a' * 156, 'b'
- exception = assert_raises Gem::Package::TooLongFileName do
+ exception = assert_raise Gem::Package::TooLongFileName do
@tar_writer.split_name name
end
assert_includes exception.message, name
@@ -325,10 +322,9 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
def test_split_name_too_long_total
name = 'a' * 257
- exception = assert_raises Gem::Package::TooLongFileName do
+ exception = assert_raise Gem::Package::TooLongFileName do
@tar_writer.split_name name
end
assert_includes exception.message, name
end
-
end
diff --git a/test/rubygems/test_gem_package_task.rb b/test/rubygems/test_gem_package_task.rb
index e01f4a4043..0cedfe56eb 100644
--- a/test/rubygems/test_gem_package_task.rb
+++ b/test/rubygems/test_gem_package_task.rb
@@ -1,22 +1,22 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems'
-require 'bundler/errors'
+
begin
require 'rubygems/package_task'
-rescue LoadError, Bundler::GemfileNotFound
+rescue LoadError => e
+ raise unless e.path == 'rake/packagetask'
end
-class TestGemPackageTask < Gem::TestCase
-
- def setup
- super
+unless defined?(Rake::PackageTask)
+ warn 'Skipping Gem::PackageTask tests. rake not found.'
+end
- Rake.application = Rake::Application.new
+class TestGemPackageTask < Gem::TestCase
+ def test_gem_package
+ original_rake_fileutils_verbosity = RakeFileUtils.verbose_flag
RakeFileUtils.verbose_flag = false
- end
- def test_gem_package
gem = Gem::Specification.new do |g|
g.name = "pkgr"
g.version = "1.2.3"
@@ -26,7 +26,9 @@ class TestGemPackageTask < Gem::TestCase
g.summary = 'summary'
end
- pkg = Gem::PackageTask.new(gem) do |p|
+ Rake.application = Rake::Application.new
+
+ pkg = Gem::PackageTask.new(gem) do |p|
p.package_files << "y"
end
@@ -38,8 +40,40 @@ class TestGemPackageTask < Gem::TestCase
Rake.application['package'].invoke
- assert_path_exists 'pkg/pkgr-1.2.3.gem'
+ assert_path_exist 'pkg/pkgr-1.2.3.gem'
end
+ ensure
+ RakeFileUtils.verbose_flag = original_rake_fileutils_verbosity
+ end
+
+ def test_gem_package_prints_to_stdout_by_default
+ gem = Gem::Specification.new do |g|
+ g.name = "pkgr"
+ g.version = "1.2.3"
+
+ g.authors = %w[author]
+ g.files = %w[x]
+ g.summary = 'summary'
+ end
+
+ _, err = capture_output do
+ Rake.application = Rake::Application.new
+
+ pkg = Gem::PackageTask.new(gem) do |p|
+ p.package_files << "y"
+ end
+
+ assert_equal %w[x y], pkg.package_files
+
+ Dir.chdir @tempdir do
+ FileUtils.touch 'x'
+ FileUtils.touch 'y'
+
+ Rake.application['package'].invoke
+ end
+ end
+
+ assert_empty err
end
def test_gem_package_with_current_platform
@@ -49,7 +83,7 @@ class TestGemPackageTask < Gem::TestCase
g.files = Rake::FileList["x"].resolve
g.platform = Gem::Platform::CURRENT
end
- pkg = Gem::PackageTask.new(gem) do |p|
+ pkg = Gem::PackageTask.new(gem) do |p|
p.package_files << "y"
end
assert_equal ["x", "y"], pkg.package_files
@@ -62,7 +96,7 @@ class TestGemPackageTask < Gem::TestCase
g.files = Rake::FileList["x"].resolve
g.platform = Gem::Platform::RUBY
end
- pkg = Gem::PackageTask.new(gem) do |p|
+ pkg = Gem::PackageTask.new(gem) do |p|
p.package_files << "y"
end
assert_equal ["x", "y"], pkg.package_files
@@ -80,5 +114,4 @@ class TestGemPackageTask < Gem::TestCase
assert_equal 'pkg/nokogiri-1.5.0-java', pkg.package_dir_path
end
-
end if defined?(Rake::PackageTask)
diff --git a/test/rubygems/test_gem_path_support.rb b/test/rubygems/test_gem_path_support.rb
index 8715bb62dc..88a3cc29b9 100644
--- a/test/rubygems/test_gem_path_support.rb
+++ b/test/rubygems/test_gem_path_support.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems'
require 'fileutils'
class TestGemPathSupport < Gem::TestCase
-
def setup
super
@@ -131,7 +130,7 @@ class TestGemPathSupport < Gem::TestCase
begin
File.symlink(dir, symlink)
rescue NotImplementedError, SystemCallError
- skip 'symlinks not supported'
+ pend 'symlinks not supported'
end
not_existing = "#{@tempdir}/does_not_exist"
path = "#{symlink}#{File::PATH_SEPARATOR}#{not_existing}"
@@ -140,5 +139,4 @@ class TestGemPathSupport < Gem::TestCase
assert_equal dir, ps.home
assert_equal [dir, not_existing], ps.path
end
-
end
diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb
index 289f078867..8029035db1 100644
--- a/test/rubygems/test_gem_platform.rb
+++ b/test/rubygems/test_gem_platform.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/platform'
require 'rbconfig'
class TestGemPlatform < Gem::TestCase
-
def test_self_local
util_set_arch 'i686-darwin8.10.1'
@@ -12,10 +11,69 @@ class TestGemPlatform < Gem::TestCase
end
def test_self_match
- assert Gem::Platform.match(nil), 'nil == ruby'
- assert Gem::Platform.match(Gem::Platform.local), 'exact match'
- assert Gem::Platform.match(Gem::Platform.local.to_s), '=~ match'
- assert Gem::Platform.match(Gem::Platform::RUBY), 'ruby'
+ Gem::Deprecate.skip_during do
+ assert Gem::Platform.match(nil), 'nil == ruby'
+ assert Gem::Platform.match(Gem::Platform.local), 'exact match'
+ assert Gem::Platform.match(Gem::Platform.local.to_s), '=~ match'
+ assert Gem::Platform.match(Gem::Platform::RUBY), 'ruby'
+ end
+ end
+
+ def test_self_match_gem?
+ assert Gem::Platform.match_gem?(nil, 'json'), 'nil == ruby'
+ assert Gem::Platform.match_gem?(Gem::Platform.local, 'json'), 'exact match'
+ assert Gem::Platform.match_gem?(Gem::Platform.local.to_s, 'json'), '=~ match'
+ assert Gem::Platform.match_gem?(Gem::Platform::RUBY, 'json'), 'ruby'
+ end
+
+ def test_self_match_spec?
+ make_spec = -> platform do
+ util_spec 'mygem-for-platform-match_spec', '1' do |s|
+ s.platform = platform
+ end
+ end
+
+ assert Gem::Platform.match_spec?(make_spec.call(nil)), 'nil == ruby'
+ assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform.local)), 'exact match'
+ assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform.local.to_s)), '=~ match'
+ assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform::RUBY)), 'ruby'
+ end
+
+ def test_self_match_spec_with_match_gem_override
+ make_spec = -> name, platform do
+ util_spec name, '1' do |s|
+ s.platform = platform
+ end
+ end
+
+ class << Gem::Platform
+ alias_method :original_match_gem?, :match_gem?
+ def match_gem?(platform, gem_name)
+ # e.g., sassc and libv8 are such gems, their native extensions do not use the Ruby C API
+ if gem_name == 'gem-with-ruby-impl-independent-precompiled-ext'
+ match_platforms?(platform, [Gem::Platform::RUBY, Gem::Platform.local])
+ else
+ match_platforms?(platform, Gem.platforms)
+ end
+ end
+ end
+
+ platforms = Gem.platforms
+ Gem.platforms = [Gem::Platform::RUBY]
+ begin
+ assert_equal true, Gem::Platform.match_spec?(make_spec.call('mygem', Gem::Platform::RUBY))
+ assert_equal false, Gem::Platform.match_spec?(make_spec.call('mygem', Gem::Platform.local))
+
+ name = 'gem-with-ruby-impl-independent-precompiled-ext'
+ assert_equal true, Gem::Platform.match_spec?(make_spec.call(name, Gem::Platform.local))
+ ensure
+ Gem.platforms = platforms
+ class << Gem::Platform
+ remove_method :match_gem?
+ alias_method :match_gem?, :original_match_gem? # rubocop:disable Lint/DuplicateMethods
+ remove_method :original_match_gem?
+ end
+ end
end
def test_self_new
@@ -64,6 +122,7 @@ class TestGemPlatform < Gem::TestCase
'i586-linux-gnu' => ['x86', 'linux', nil],
'i386-linux-gnu' => ['x86', 'linux', nil],
'i386-mingw32' => ['x86', 'mingw32', nil],
+ 'x64-mingw-ucrt' => ['x64', 'mingw', 'ucrt'],
'i386-mswin32' => ['x86', 'mswin32', nil],
'i386-mswin32_80' => ['x86', 'mswin32', '80'],
'i386-mswin32-80' => ['x86', 'mswin32', '80'],
@@ -298,6 +357,14 @@ class TestGemPlatform < Gem::TestCase
assert_local_match 'sparc-solaris2.8-mq5.3'
end
+ def test_inspect
+ result = Gem::Platform.new("universal-java11").inspect
+
+ assert_equal 1, result.scan(/@cpu=/).size
+ assert_equal 1, result.scan(/@os=/).size
+ assert_equal 1, result.scan(/@version=/).size
+ end
+
def assert_local_match(name)
assert_match Gem::Platform.local, name
end
@@ -305,5 +372,4 @@ class TestGemPlatform < Gem::TestCase
def refute_local_match(name)
refute_match Gem::Platform.local, name
end
-
end
diff --git a/test/rubygems/test_gem_rdoc.rb b/test/rubygems/test_gem_rdoc.rb
index 6184d4b457..7b8ad07b27 100644
--- a/test/rubygems/test_gem_rdoc.rb
+++ b/test/rubygems/test_gem_rdoc.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
require 'rubygems'
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/rdoc'
class TestGemRDoc < Gem::TestCase
-
Gem::RDoc.load_rdoc
def setup
@@ -25,7 +24,7 @@ class TestGemRDoc < Gem::TestCase
begin
Gem::RDoc.load_rdoc
rescue Gem::DocumentError => e
- skip e.message
+ pend e.message
end
Gem.configuration[:rdoc] = nil
@@ -85,16 +84,16 @@ class TestGemRDoc < Gem::TestCase
refute @hook.rdoc_installed?
refute @hook.ri_installed?
- assert_path_exists @a.doc_dir
+ assert_path_exist @a.doc_dir
end
def test_remove_unwritable
- skip 'chmod not supported' if Gem.win_platform?
- skip 'skipped in root privilege' if Process.uid.zero?
+ pend 'chmod not supported' if Gem.win_platform?
+ pend 'skipped in root privilege' if Process.uid.zero?
FileUtils.mkdir_p @a.base_dir
FileUtils.chmod 0, @a.base_dir
- e = assert_raises Gem::FilePermissionError do
+ e = assert_raise Gem::FilePermissionError do
@hook.remove
end
@@ -114,16 +113,16 @@ class TestGemRDoc < Gem::TestCase
def test_setup
@hook.setup
- assert_path_exists @a.doc_dir
+ assert_path_exist @a.doc_dir
end
def test_setup_unwritable
- skip 'chmod not supported' if Gem.win_platform?
- skip 'skipped in root privilege' if Process.uid.zero?
+ pend 'chmod not supported' if Gem.win_platform?
+ pend 'skipped in root privilege' if Process.uid.zero?
FileUtils.mkdir_p @a.doc_dir
FileUtils.chmod 0, @a.doc_dir
- e = assert_raises Gem::FilePermissionError do
+ e = assert_raise Gem::FilePermissionError do
@hook.setup
end
@@ -134,5 +133,4 @@ class TestGemRDoc < Gem::TestCase
FileUtils.rm_r @a.doc_dir
end
end
-
end
diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index 76a66af867..5ce420b91a 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -1,21 +1,15 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'webrick'
-begin
- require 'webrick/https'
-rescue LoadError => e
- raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
- e.message =~ / -- openssl$/
-end
+require 'webrick/https' if Gem::HAVE_OPENSSL
-unless defined?(OpenSSL::SSL)
- warn 'Skipping Gem::Request tests. openssl not found.'
+unless Gem::HAVE_OPENSSL
+ warn 'Skipping Gem::RemoteFetcher tests. openssl not found.'
end
require 'rubygems/remote_fetcher'
require 'rubygems/package'
-require 'minitest/mock'
# = Testing Proxy Settings
#
@@ -32,7 +26,6 @@ require 'minitest/mock'
# proxy is configured.
class TestGemRemoteFetcher < Gem::TestCase
-
include Gem::DefaultUserInteraction
SERVER_DATA = <<-EOY.freeze
@@ -78,12 +71,10 @@ gems:
PROXY_DATA = SERVER_DATA.gsub(/0.4.11/, '0.4.2')
- DIR = File.expand_path(File.dirname(__FILE__))
-
# Generated via:
# x = OpenSSL::PKey::DH.new(2048) # wait a while...
# x.to_s => pem
- TEST_KEY_DH2048 = OpenSSL::PKey::DH.new <<-_end_of_pem_
+ TEST_KEY_DH2048 = OpenSSL::PKey::DH.new <<-_END_OF_PEM_
-----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA3Ze2EHSfYkZLUn557torAmjBgPsqzbodaRaGZtgK1gEU+9nNJaFV
G1JKhmGUiEDyIW7idsBpe4sX/Wqjnp48Lr8IeI/SlEzLdoGpf05iRYXC8Cm9o8aM
@@ -92,7 +83,7 @@ cfmVgoSEAo9YLBpzoji2jHkO7Q5IPt4zxbTdlmmGFLc/GO9q7LGHhC+rcMcNTGsM
NP0fuvVAIB158VnQ0liHSwcl6+9vE1mL0Jo/qEXQxl0+UdKDjaGfTsn6HIrwTnmJ
PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
-----END DH PARAMETERS-----
- _end_of_pem_
+ _END_OF_PEM_
def setup
@proxies = %w[https_proxy http_proxy HTTP_PROXY http_proxy_user HTTP_PROXY_USER http_proxy_pass HTTP_PROXY_PASS no_proxy NO_PROXY]
@@ -100,20 +91,17 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
@proxies.each {|k| ENV[k] = nil }
super
- self.class.start_servers
- self.class.enable_yaml = true
- self.class.enable_zip = false
+ start_servers
+ self.enable_yaml = true
+ self.enable_zip = false
- base_server_uri = "http://localhost:#{self.class.normal_server_port}"
- @proxy_uri = "http://localhost:#{self.class.proxy_server_port}"
+ base_server_uri = "http://localhost:#{normal_server_port}"
+ @proxy_uri = "http://localhost:#{proxy_server_port}"
@server_uri = base_server_uri + "/yaml"
@server_z_uri = base_server_uri + "/yaml.Z"
- # REFACTOR: copied from test_gem_dependency_installer.rb
- @gems_dir = File.join @tempdir, 'gems'
@cache_dir = File.join @gemhome, "cache"
- FileUtils.mkdir @gems_dir
# TODO: why does the remote fetcher need it written to disk?
@a1, @a1_gem = util_gem 'a', '1' do |s|
@@ -129,7 +117,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def teardown
@fetcher.close_all
- self.class.stop_servers
+ stop_servers
super
Gem.configuration[:http_proxy] = nil
@proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] }
@@ -153,42 +141,22 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy).to_s
end
- def test_fetch_size_bad_uri
+ def test_fetch_path_bad_uri
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
- e = assert_raises ArgumentError do
- Gem::Deprecate.skip_during do
- fetcher.fetch_size 'gems.example.com/yaml'
- end
+ e = assert_raise ArgumentError do
+ @fetcher.fetch_path("gems.example.com/yaml", nil, true)
end
assert_equal 'uri scheme is invalid: nil', e.message
end
- def test_fetch_size_socket_error
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- def fetcher.request(uri, request_class, last_modified = nil)
- raise SocketError, "oops"
- end
-
- uri = 'http://gems.example.com/yaml'
- e = assert_raises Gem::RemoteFetcher::FetchError do
- Gem::Deprecate.skip_during do
- fetcher.fetch_size uri
- end
- end
-
- assert_equal "SocketError: oops (#{uri})", e.message
- end
-
def test_no_proxy
use_ui @stub_ui do
assert_data_from_server @fetcher.fetch_path(@server_uri)
- Gem::Deprecate.skip_during do
- assert_equal SERVER_DATA.size, @fetcher.fetch_size(@server_uri)
- end
+ response = @fetcher.fetch_path(@server_uri, nil, true)
+ assert_equal SERVER_DATA.size, response['content-length'].to_i
end
end
@@ -215,7 +183,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert_equal 'hello', data
- refute_path_exists path
+ assert_path_not_exist path
end
def util_fuck_with_fetcher(data, blow = false)
@@ -236,7 +204,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
@test_data
end
- raise Gem::RemoteFetcher::FetchError.new("haha!", nil)
+ raise Gem::RemoteFetcher::FetchError.new("haha!", '')
end
end
@@ -273,6 +241,36 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert File.exist?(a1_cache_gem)
end
+ def test_download_with_token
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ fetcher = util_fuck_with_fetcher a1_data
+
+ a1_cache_gem = @a1.cache_file
+ assert_equal a1_cache_gem, fetcher.download(@a1, 'http://token@gems.example.com')
+ assert_equal("http://token@gems.example.com/gems/a-1.gem",
+ fetcher.instance_variable_get(:@test_arg).to_s)
+ assert File.exist?(a1_cache_gem)
+ end
+
+ def test_download_with_x_oauth_basic
+ a1_data = nil
+ File.open @a1_gem, 'rb' do |fp|
+ a1_data = fp.read
+ end
+
+ fetcher = util_fuck_with_fetcher a1_data
+
+ a1_cache_gem = @a1.cache_file
+ assert_equal a1_cache_gem, fetcher.download(@a1, 'http://token:x-oauth-basic@gems.example.com')
+ assert_equal("http://token:x-oauth-basic@gems.example.com/gems/a-1.gem",
+ fetcher.instance_variable_get(:@test_arg).to_s)
+ assert File.exist?(a1_cache_gem)
+ end
+
def test_download_with_encoded_auth
a1_data = nil
File.open @a1_gem, 'rb' do |fp|
@@ -348,6 +346,8 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
local_path = File.join @tempdir, @a1.file_name
inst = nil
FileUtils.chmod 0555, @a1.cache_dir
+ FileUtils.mkdir_p File.join(Gem.user_dir, "cache") rescue nil
+ FileUtils.chmod 0555, File.join(Gem.user_dir, "cache")
Dir.chdir @tempdir do
inst = Gem::RemoteFetcher.fetcher
@@ -356,6 +356,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert_equal(File.join(@tempdir, @a1.file_name),
inst.download(@a1, local_path))
ensure
+ FileUtils.chmod 0755, File.join(Gem.user_dir, "cache")
FileUtils.chmod 0755, @a1.cache_dir
end
@@ -418,7 +419,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_download_unsupported
inst = Gem::RemoteFetcher.fetcher
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
inst.download @a1, 'ftp://gems.rubyforge.org'
end
@@ -479,7 +480,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
url = 'http://example.com/uri'
- e = assert_raises Gem::RemoteFetcher::FetchError do
+ e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
end
@@ -497,7 +498,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
url = 'http://example.com/uri'
- e = assert_raises Gem::RemoteFetcher::FetchError do
+ e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
end
@@ -515,11 +516,49 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
url = 'http://example.com/uri'
- e = assert_raises Gem::RemoteFetcher::FetchError do
+ e = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path url
+ end
+
+ assert_match %r{ECONNREFUSED:.*connect\(2\) \(#{Regexp.escape url}\)\z},
+ e.message
+ assert_equal url, e.uri
+ end
+
+ def test_fetch_path_timeout_error
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+
+ def fetcher.fetch_http(uri, mtime = nil, head = nil)
+ raise Timeout::Error, 'timed out'
+ end
+
+ url = 'http://example.com/uri'
+
+ e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
end
- assert_match %r|ECONNREFUSED:.*connect\(2\) \(#{Regexp.escape url}\)\z|,
+ assert_match %r{Timeout::Error: timed out \(#{Regexp.escape url}\)\z},
+ e.message
+ assert_equal url, e.uri
+ end
+
+ def test_fetch_path_getaddrinfo_error
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+
+ def fetcher.fetch_http(uri, mtime = nil, head = nil)
+ raise SocketError, 'getaddrinfo: nodename nor servname provided'
+ end
+
+ url = 'http://example.com/uri'
+
+ e = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path url
+ end
+
+ assert_match %r{SocketError: getaddrinfo: nodename nor servname provided \(#{Regexp.escape url}\)\z},
e.message
assert_equal url, e.uri
end
@@ -534,7 +573,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
url = 'http://example.com/uri'
- e = assert_raises Gem::RemoteFetcher::FetchError do
+ e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
end
@@ -624,7 +663,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
res
end
- e = assert_raises Gem::RemoteFetcher::FetchError do
+ e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_http URI.parse(url)
end
@@ -641,7 +680,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
res
end
- e = assert_raises Gem::RemoteFetcher::FetchError do
+ e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_http URI.parse(url)
end
@@ -691,7 +730,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_fetch_s3_config_creds
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:id => 'testuser', :secret => 'testpass'}
+ 'my-bucket' => {:id => 'testuser', :secret => 'testpass'},
}
url = 's3://my-bucket/gems/specs.4.8.gz'
Time.stub :now, Time.at(1561353581) do
@@ -703,7 +742,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_fetch_s3_config_creds_with_region
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :region => 'us-west-2'}
+ 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :region => 'us-west-2'},
}
url = 's3://my-bucket/gems/specs.4.8.gz'
Time.stub :now, Time.at(1561353581) do
@@ -715,7 +754,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_fetch_s3_config_creds_with_token
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :security_token => 'testtoken'}
+ 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :security_token => 'testtoken'},
}
url = 's3://my-bucket/gems/specs.4.8.gz'
Time.stub :now, Time.at(1561353581) do
@@ -730,14 +769,14 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
ENV['AWS_SECRET_ACCESS_KEY'] = 'testpass'
ENV['AWS_SESSION_TOKEN'] = nil
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'env'}
+ 'my-bucket' => {:provider => 'env'},
}
url = 's3://my-bucket/gems/specs.4.8.gz'
Time.stub :now, Time.at(1561353581) do
assert_fetch_s3 url, '20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b'
end
ensure
- ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS')}
+ ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS') }
Gem.configuration[:s3_source] = nil
end
@@ -746,14 +785,14 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
ENV['AWS_SECRET_ACCESS_KEY'] = 'testpass'
ENV['AWS_SESSION_TOKEN'] = nil
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'env', :region => 'us-west-2'}
+ 'my-bucket' => {:provider => 'env', :region => 'us-west-2'},
}
url = 's3://my-bucket/gems/specs.4.8.gz'
Time.stub :now, Time.at(1561353581) do
assert_fetch_s3 url, '4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9', nil, 'us-west-2'
end
ensure
- ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS')}
+ ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS') }
Gem.configuration[:s3_source] = nil
end
@@ -762,14 +801,14 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
ENV['AWS_SECRET_ACCESS_KEY'] = 'testpass'
ENV['AWS_SESSION_TOKEN'] = 'testtoken'
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'env'}
+ 'my-bucket' => {:provider => 'env'},
}
url = 's3://my-bucket/gems/specs.4.8.gz'
Time.stub :now, Time.at(1561353581) do
assert_fetch_s3 url, '935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c', 'testtoken'
end
ensure
- ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS')}
+ ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS') }
Gem.configuration[:s3_source] = nil
end
@@ -782,7 +821,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_fetch_s3_instance_profile_creds
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'instance_profile'}
+ 'my-bucket' => {:provider => 'instance_profile'},
}
url = 's3://my-bucket/gems/specs.4.8.gz'
@@ -796,7 +835,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_fetch_s3_instance_profile_creds_with_region
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'instance_profile', :region => 'us-west-2'}
+ 'my-bucket' => {:provider => 'instance_profile', :region => 'us-west-2'},
}
url = 's3://my-bucket/gems/specs.4.8.gz'
@@ -810,7 +849,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_fetch_s3_instance_profile_creds_with_token
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'instance_profile'}
+ 'my-bucket' => {:provider => 'instance_profile'},
}
url = 's3://my-bucket/gems/specs.4.8.gz'
@@ -826,7 +865,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
- e = assert_raises Gem::RemoteFetcher::FetchError do
+ e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_s3 URI.parse(url)
end
@@ -840,7 +879,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_fetch_s3_no_host
Gem.configuration[:s3_source] = {
- 'my-bucket' => {:id => 'testuser', :secret => 'testpass'}
+ 'my-bucket' => {:id => 'testuser', :secret => 'testpass'},
}
url = 's3://other-bucket/gems/specs.4.8.gz'
@@ -901,7 +940,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_yaml_error_on_size
use_ui @stub_ui do
- self.class.enable_yaml = false
+ self.enable_yaml = false
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
assert_error { fetcher.size }
@@ -909,23 +948,20 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
def test_ssl_connection
- ssl_server = self.class.start_ssl_server
- temp_ca_cert = File.join(DIR, 'ca_cert.pem')
+ ssl_server = start_ssl_server
+ temp_ca_cert = File.join(__dir__, 'ca_cert.pem')
with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
end
end
def test_ssl_client_cert_auth_connection
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
- skip 'openssl in jruby fails' if java_platform?
-
- ssl_server = self.class.start_ssl_server({
+ ssl_server = start_ssl_server({
:SSLVerifyClient =>
OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT})
- temp_ca_cert = File.join(DIR, 'ca_cert.pem')
- temp_client_cert = File.join(DIR, 'client.pem')
+ temp_ca_cert = File.join(__dir__, 'ca_cert.pem')
+ temp_client_cert = File.join(__dir__, 'client.pem')
with_configured_fetcher(
":ssl_ca_cert: #{temp_ca_cert}\n" +
@@ -935,48 +971,46 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
def test_do_not_allow_invalid_client_cert_auth_connection
- skip 'openssl is missing' unless defined?(OpenSSL::SSL)
-
- ssl_server = self.class.start_ssl_server({
+ ssl_server = start_ssl_server({
:SSLVerifyClient =>
OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT})
- temp_ca_cert = File.join(DIR, 'ca_cert.pem')
- temp_client_cert = File.join(DIR, 'invalid_client.pem')
+ temp_ca_cert = File.join(__dir__, 'ca_cert.pem')
+ temp_client_cert = File.join(__dir__, 'invalid_client.pem')
with_configured_fetcher(
":ssl_ca_cert: #{temp_ca_cert}\n" +
":ssl_client_cert: #{temp_client_cert}\n") do |fetcher|
- assert_raises Gem::RemoteFetcher::FetchError do
+ assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
end
end
end
def test_do_not_allow_insecure_ssl_connection_by_default
- ssl_server = self.class.start_ssl_server
+ ssl_server = start_ssl_server
with_configured_fetcher do |fetcher|
- assert_raises Gem::RemoteFetcher::FetchError do
+ assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
end
end
end
def test_ssl_connection_allow_verify_none
- ssl_server = self.class.start_ssl_server
+ ssl_server = start_ssl_server
with_configured_fetcher(":ssl_verify_mode: 0") do |fetcher|
fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
end
end
def test_do_not_follow_insecure_redirect
- ssl_server = self.class.start_ssl_server
- temp_ca_cert = File.join(DIR, 'ca_cert.pem')
+ ssl_server = start_ssl_server
+ temp_ca_cert = File.join(__dir__, 'ca_cert.pem')
expected_error_message =
"redirecting to non-https resource: #{@server_uri} (https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri})"
with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
- err = assert_raises Gem::RemoteFetcher::FetchError do
+ err = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri}")
end
@@ -985,11 +1019,11 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
def test_nil_ca_cert
- ssl_server = self.class.start_ssl_server
+ ssl_server = start_ssl_server
temp_ca_cert = nil
with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
- assert_raises Gem::RemoteFetcher::FetchError do
+ assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}")
end
end
@@ -1031,157 +1065,147 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
class NilLog < WEBrick::Log
-
def log(level, data) #Do nothing
end
-
end
- class << self
+ private
- attr_reader :normal_server, :proxy_server
- attr_accessor :enable_zip, :enable_yaml
+ attr_reader :normal_server, :proxy_server
+ attr_accessor :enable_zip, :enable_yaml
- def start_servers
- @normal_server ||= start_server(SERVER_DATA)
- @proxy_server ||= start_server(PROXY_DATA)
- @enable_yaml = true
- @enable_zip = false
- @ssl_server = nil
- @ssl_server_thread = nil
- end
+ def start_servers
+ @normal_server ||= start_server(SERVER_DATA)
+ @proxy_server ||= start_server(PROXY_DATA)
+ @enable_yaml = true
+ @enable_zip = false
+ @ssl_server = nil
+ @ssl_server_thread = nil
+ end
- def stop_servers
- if @normal_server
- @normal_server.kill.join
- @normal_server = nil
- end
- if @proxy_server
- @proxy_server.kill.join
- @proxy_server = nil
- end
- if @ssl_server
- @ssl_server.stop
- @ssl_server = nil
- end
- if @ssl_server_thread
- @ssl_server_thread.kill.join
- @ssl_server_thread = nil
- end
- utils = WEBrick::Utils # TimeoutHandler is since 1.9
- utils::TimeoutHandler.terminate if defined?(utils::TimeoutHandler.terminate)
+ def stop_servers
+ if @normal_server
+ @normal_server.kill.join
+ @normal_server = nil
end
-
- def normal_server_port
- @normal_server[:server].config[:Port]
+ if @proxy_server
+ @proxy_server.kill.join
+ @proxy_server = nil
end
-
- def proxy_server_port
- @proxy_server[:server].config[:Port]
+ if @ssl_server
+ @ssl_server.stop
+ @ssl_server = nil
end
+ if @ssl_server_thread
+ @ssl_server_thread.kill.join
+ @ssl_server_thread = nil
+ end
+ utils = WEBrick::Utils # TimeoutHandler is since 1.9
+ utils::TimeoutHandler.terminate if defined?(utils::TimeoutHandler.terminate)
+ end
- DIR = File.expand_path(File.dirname(__FILE__))
+ def normal_server_port
+ @normal_server[:server].config[:Port]
+ end
- def start_ssl_server(config = {})
- raise MiniTest::Skip, 'openssl not installed' unless
- defined?(OpenSSL::SSL)
+ def proxy_server_port
+ @proxy_server[:server].config[:Port]
+ end
- null_logger = NilLog.new
- server = WEBrick::HTTPServer.new({
- :Port => 0,
- :Logger => null_logger,
- :AccessLog => [],
- :SSLEnable => true,
- :SSLCACertificateFile => File.join(DIR, 'ca_cert.pem'),
- :SSLCertificate => cert('ssl_cert.pem'),
- :SSLPrivateKey => key('ssl_key.pem'),
- :SSLVerifyClient => nil,
- :SSLCertName => nil
- }.merge(config))
- server.mount_proc("/yaml") do |req, res|
- res.body = "--- true\n"
- end
- server.mount_proc("/insecure_redirect") do |req, res|
- res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, req.query['to'])
- end
- server.ssl_context.tmp_dh_callback = proc { TEST_KEY_DH2048 }
- t = Thread.new do
- begin
- server.start
- rescue Exception => ex
- abort ex.message
- puts "ERROR during server thread: #{ex.message}"
- ensure
- server.shutdown
- end
- end
- while server.status != :Running
- sleep 0.1
- unless t.alive?
- t.join
- raise
- end
- end
- @ssl_server = server
- @ssl_server_thread = t
- server
- end
-
- private
-
- def start_server(data)
- null_logger = NilLog.new
- s = WEBrick::HTTPServer.new(
- :Port => 0,
- :DocumentRoot => nil,
- :Logger => null_logger,
- :AccessLog => null_logger
- )
- s.mount_proc("/kill") { |req, res| s.shutdown }
- s.mount_proc("/yaml") do |req, res|
- if req["X-Captain"]
- res.body = req["X-Captain"]
- elsif @enable_yaml
- res.body = data
- res['Content-Type'] = 'text/plain'
- res['content-length'] = data.size
- else
- res.status = "404"
- res.body = "<h1>NOT FOUND</h1>"
- res['Content-Type'] = 'text/html'
- end
+ def start_ssl_server(config = {})
+ pend "starting this test server fails randomly on jruby" if Gem.java_platform?
+
+ null_logger = NilLog.new
+ server = WEBrick::HTTPServer.new({
+ :Port => 0,
+ :Logger => null_logger,
+ :AccessLog => [],
+ :SSLEnable => true,
+ :SSLCACertificateFile => File.join(__dir__, 'ca_cert.pem'),
+ :SSLCertificate => cert('ssl_cert.pem'),
+ :SSLPrivateKey => key('ssl_key.pem'),
+ :SSLVerifyClient => nil,
+ :SSLCertName => nil,
+ }.merge(config))
+ server.mount_proc("/yaml") do |req, res|
+ res.body = "--- true\n"
+ end
+ server.mount_proc("/insecure_redirect") do |req, res|
+ res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, req.query['to'])
+ end
+ server.ssl_context.tmp_dh_callback = proc { TEST_KEY_DH2048 }
+ t = Thread.new do
+ begin
+ server.start
+ rescue Exception => ex
+ puts "ERROR during server thread: #{ex.message}"
+ raise
+ ensure
+ server.shutdown
end
- s.mount_proc("/yaml.Z") do |req, res|
- if @enable_zip
- res.body = Zlib::Deflate.deflate(data)
- res['Content-Type'] = 'text/plain'
- else
- res.status = "404"
- res.body = "<h1>NOT FOUND</h1>"
- res['Content-Type'] = 'text/html'
- end
+ end
+ while server.status != :Running
+ sleep 0.1
+ unless t.alive?
+ t.join
+ raise
end
- th = Thread.new do
- begin
- s.start
- rescue Exception => ex
- abort "ERROR during server thread: #{ex.message}"
- ensure
- s.shutdown
- end
+ end
+ @ssl_server = server
+ @ssl_server_thread = t
+ server
+ end
+
+ def start_server(data)
+ null_logger = NilLog.new
+ s = WEBrick::HTTPServer.new(
+ :Port => 0,
+ :DocumentRoot => nil,
+ :Logger => null_logger,
+ :AccessLog => null_logger
+ )
+ s.mount_proc("/kill") {|req, res| s.shutdown }
+ s.mount_proc("/yaml") do |req, res|
+ if req["X-Captain"]
+ res.body = req["X-Captain"]
+ elsif @enable_yaml
+ res.body = data
+ res['Content-Type'] = 'text/plain'
+ res['content-length'] = data.size
+ else
+ res.status = "404"
+ res.body = "<h1>NOT FOUND</h1>"
+ res['Content-Type'] = 'text/html'
end
- th[:server] = s
- th
end
-
- def cert(filename)
- OpenSSL::X509::Certificate.new(File.read(File.join(DIR, filename)))
+ s.mount_proc("/yaml.Z") do |req, res|
+ if @enable_zip
+ res.body = Zlib::Deflate.deflate(data)
+ res['Content-Type'] = 'text/plain'
+ else
+ res.status = "404"
+ res.body = "<h1>NOT FOUND</h1>"
+ res['Content-Type'] = 'text/html'
+ end
end
-
- def key(filename)
- OpenSSL::PKey::RSA.new(File.read(File.join(DIR, filename)))
+ th = Thread.new do
+ begin
+ s.start
+ rescue Exception => ex
+ abort "ERROR during server thread: #{ex.message}"
+ ensure
+ s.shutdown
+ end
end
+ th[:server] = s
+ th
+ end
+ def cert(filename)
+ OpenSSL::X509::Certificate.new(File.read(File.join(__dir__, filename)))
end
-end if defined?(OpenSSL::SSL)
+ def key(filename)
+ OpenSSL::PKey::RSA.new(File.read(File.join(__dir__, filename)))
+ end
+end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_gem_request.rb b/test/rubygems/test_gem_request.rb
index 2a756eaad7..47654f6fa4 100644
--- a/test/rubygems/test_gem_request.rb
+++ b/test/rubygems/test_gem_request.rb
@@ -1,15 +1,14 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/request'
require 'ostruct'
require 'base64'
-unless defined?(OpenSSL::SSL)
+unless Gem::HAVE_OPENSSL
warn 'Skipping Gem::Request tests. openssl not found.'
end
class TestGemRequest < Gem::TestCase
-
CA_CERT_FILE = cert_path 'ca'
CHILD_CERT = load_cert 'child'
EXPIRED_CERT = load_cert 'expired'
@@ -186,7 +185,7 @@ class TestGemRequest < Gem::TestCase
end
def test_fetch
- uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+ uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}")
response = util_stub_net_http(:body => :junk, :code => 200) do
@request = make_request(uri, Net::HTTP::Get, nil, nil)
@@ -198,31 +197,57 @@ class TestGemRequest < Gem::TestCase
end
def test_fetch_basic_auth
- uri = URI.parse "https://user:pass@example.rubygems/specs.#{Gem.marshal_version}"
+ Gem.configuration.verbose = :really
+ uri = Gem::Uri.new(URI.parse "https://user:pass@example.rubygems/specs.#{Gem.marshal_version}")
conn = util_stub_net_http(:body => :junk, :code => 200) do |c|
- @request = make_request(uri, Net::HTTP::Get, nil, nil)
- @request.fetch
+ use_ui @ui do
+ @request = make_request(uri, Net::HTTP::Get, nil, nil)
+ @request.fetch
+ end
c
end
auth_header = conn.payload['Authorization']
assert_equal "Basic #{Base64.encode64('user:pass')}".strip, auth_header
+ assert_includes @ui.output, "GET https://user:REDACTED@example.rubygems/specs.#{Gem.marshal_version}"
end
def test_fetch_basic_auth_encoded
- uri = URI.parse "https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}"
+ Gem.configuration.verbose = :really
+ uri = Gem::Uri.new(URI.parse "https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}")
+
conn = util_stub_net_http(:body => :junk, :code => 200) do |c|
- @request = make_request(uri, Net::HTTP::Get, nil, nil)
- @request.fetch
+ use_ui @ui do
+ @request = make_request(uri, Net::HTTP::Get, nil, nil)
+ @request.fetch
+ end
c
end
auth_header = conn.payload['Authorization']
assert_equal "Basic #{Base64.encode64('user:{DEScede}pass')}".strip, auth_header
+ assert_includes @ui.output, "GET https://user:REDACTED@example.rubygems/specs.#{Gem.marshal_version}"
+ end
+
+ def test_fetch_basic_oauth_encoded
+ Gem.configuration.verbose = :really
+ uri = Gem::Uri.new(URI.parse "https://%7BDEScede%7Dpass:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}")
+
+ conn = util_stub_net_http(:body => :junk, :code => 200) do |c|
+ use_ui @ui do
+ @request = make_request(uri, Net::HTTP::Get, nil, nil)
+ @request.fetch
+ end
+ c
+ end
+
+ auth_header = conn.payload['Authorization']
+ assert_equal "Basic #{Base64.encode64('{DEScede}pass:x-oauth-basic')}".strip, auth_header
+ assert_includes @ui.output, "GET https://REDACTED:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}"
end
def test_fetch_head
- uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+ uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}")
response = util_stub_net_http(:body => '', :code => 200) do |conn|
@request = make_request(uri, Net::HTTP::Get, nil, nil)
@request.fetch
@@ -233,7 +258,7 @@ class TestGemRequest < Gem::TestCase
end
def test_fetch_unmodified
- uri = URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}"
+ uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}")
t = Time.utc(2013, 1, 2, 3, 4, 5)
conn, response = util_stub_net_http(:body => '', :code => 304) do |c|
@request = make_request(uri, Net::HTTP::Get, t, nil)
@@ -251,11 +276,11 @@ class TestGemRequest < Gem::TestCase
def test_user_agent
ua = make_request(@uri, nil, nil, nil).user_agent
- assert_match %r%^RubyGems/\S+ \S+ Ruby/\S+ \(.*?\)%, ua
- assert_match %r%RubyGems/#{Regexp.escape Gem::VERSION}%, ua
- assert_match %r% #{Regexp.escape Gem::Platform.local.to_s} %, ua
- assert_match %r%Ruby/#{Regexp.escape RUBY_VERSION}%, ua
- assert_match %r%\(#{Regexp.escape RUBY_RELEASE_DATE} %, ua
+ assert_match %r{^RubyGems/\S+ \S+ Ruby/\S+ \(.*?\)}, ua
+ assert_match %r{RubyGems/#{Regexp.escape Gem::VERSION}}, ua
+ assert_match %r{ #{Regexp.escape Gem::Platform.local.to_s} }, ua
+ assert_match %r{Ruby/#{Regexp.escape RUBY_VERSION}}, ua
+ assert_match %r{\(#{Regexp.escape RUBY_RELEASE_DATE} }, ua
end
def test_user_agent_engine
@@ -266,7 +291,7 @@ class TestGemRequest < Gem::TestCase
ua = make_request(@uri, nil, nil, nil).user_agent
- assert_match %r%\) vroom%, ua
+ assert_match %r{\) vroom}, ua
ensure
util_restore_version
end
@@ -279,7 +304,7 @@ class TestGemRequest < Gem::TestCase
ua = make_request(@uri, nil, nil, nil).user_agent
- assert_match %r%\)%, ua
+ assert_match %r{\)}, ua
ensure
util_restore_version
end
@@ -292,7 +317,7 @@ class TestGemRequest < Gem::TestCase
ua = make_request(@uri, nil, nil, nil).user_agent
- assert_match %r% patchlevel 5\)%, ua
+ assert_match %r{ patchlevel 5\)}, ua
ensure
util_restore_version
end
@@ -307,8 +332,8 @@ class TestGemRequest < Gem::TestCase
ua = make_request(@uri, nil, nil, nil).user_agent
- assert_match %r% revision 6\)%, ua
- assert_match %r%Ruby/#{Regexp.escape RUBY_VERSION}dev%, ua
+ assert_match %r{ revision 6\)}, ua
+ assert_match %r{Ruby/#{Regexp.escape RUBY_VERSION}dev}, ua
ensure
util_restore_version
end
@@ -322,37 +347,43 @@ class TestGemRequest < Gem::TestCase
ua = make_request(@uri, nil, nil, nil).user_agent
- assert_match %r%\(#{Regexp.escape RUBY_RELEASE_DATE}\)%, ua
+ assert_match %r{\(#{Regexp.escape RUBY_RELEASE_DATE}\)}, ua
ensure
util_restore_version
end
def test_verify_certificate
- skip if Gem.java_platform?
+ pend if Gem.java_platform?
+
+ error_number = OpenSSL::X509::V_ERR_OUT_OF_MEM
+
store = OpenSSL::X509::Store.new
context = OpenSSL::X509::StoreContext.new store
- context.error = OpenSSL::X509::V_ERR_OUT_OF_MEM
+ context.error = error_number
use_ui @ui do
Gem::Request.verify_certificate context
end
- assert_equal "ERROR: SSL verification error at depth 0: out of memory (17)\n",
+ assert_equal "ERROR: SSL verification error at depth 0: out of memory (#{error_number})\n",
@ui.error
end
def test_verify_certificate_extra_message
- skip if Gem.java_platform?
+ pend if Gem.java_platform?
+
+ error_number = OpenSSL::X509::V_ERR_INVALID_CA
+
store = OpenSSL::X509::Store.new
context = OpenSSL::X509::StoreContext.new store
- context.error = OpenSSL::X509::V_ERR_INVALID_CA
+ context.error = error_number
use_ui @ui do
Gem::Request.verify_certificate context
end
expected = <<-ERROR
-ERROR: SSL verification error at depth 0: invalid CA certificate (24)
+ERROR: SSL verification error at depth 0: invalid CA certificate (#{error_number})
ERROR: Certificate is an invalid CA certificate
ERROR
@@ -488,7 +519,6 @@ ERROR: Certificate is an invalid CA certificate
end
class Conn
-
attr_accessor :payload
def new(*args); self; end
@@ -507,7 +537,5 @@ ERROR: Certificate is an invalid CA certificate
self.payload = req
@response
end
-
end
-
-end if defined?(OpenSSL::SSL)
+end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_gem_request_connection_pools.rb b/test/rubygems/test_gem_request_connection_pools.rb
index f8d2095167..c5e7cf2ed4 100644
--- a/test/rubygems/test_gem_request_connection_pools.rb
+++ b/test/rubygems/test_gem_request_connection_pools.rb
@@ -1,18 +1,15 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/request'
require 'timeout'
class TestGemRequestConnectionPool < Gem::TestCase
-
class FakeHttp
-
def initialize(*args)
end
def start
end
-
end
def setup
@@ -143,12 +140,11 @@ class TestGemRequestConnectionPool < Gem::TestCase
pool.checkout
Thread.new do
- assert_raises(Timeout::Error) do
+ assert_raise(Timeout::Error) do
Timeout.timeout(1) do
pool.checkout
end
end
end.join
end
-
end
diff --git a/test/rubygems/test_gem_request_set.rb b/test/rubygems/test_gem_request_set.rb
index fb71829471..e2fe98b9bf 100644
--- a/test/rubygems/test_gem_request_set.rb
+++ b/test/rubygems/test_gem_request_set.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/request_set'
class TestGemRequestSet < Gem::TestCase
-
def setup
super
@@ -65,8 +64,8 @@ class TestGemRequestSet < Gem::TestCase
end
assert_includes installed, 'a-2'
- assert_path_exists File.join @gemhome, 'gems', 'a-2'
- assert_path_exists 'gem.deps.rb.lock'
+ assert_path_exist File.join @gemhome, 'gems', 'a-2'
+ assert_path_exist 'gem.deps.rb.lock'
assert rs.remote
refute done_installing_ran
@@ -88,9 +87,10 @@ Gems to install:
a-2
EXPECTED
- assert_output expected do
+ actual, _ = capture_output do
rs.install_from_gemdeps :gemdeps => io.path, :explain => true
end
+ assert_equal(expected, actual)
end
end
@@ -100,7 +100,7 @@ Gems to install:
end
util_clear_gems
- refute_path_exists File.join Gem.dir, 'gems', 'a-2'
+ assert_path_not_exist File.join Gem.dir, 'gems', 'a-2'
rs = Gem::RequestSet.new
installed = []
@@ -119,7 +119,7 @@ Gems to install:
end
assert_includes installed, 'a-2'
- refute_path_exists File.join Gem.dir, 'gems', 'a-2'
+ assert_path_not_exist File.join Gem.dir, 'gems', 'a-2'
end
def test_install_from_gemdeps_local
@@ -133,7 +133,7 @@ Gems to install:
io.puts 'gem "a"'
io.flush
- assert_raises Gem::UnsatisfiableDependencyError do
+ assert_raise Gem::UnsatisfiableDependencyError do
rs.install_from_gemdeps :gemdeps => io.path, :domain => :local
end
end
@@ -179,8 +179,8 @@ DEPENDENCIES
assert_includes installed, 'b-1'
assert_includes installed, 'a-1'
- assert_path_exists File.join @gemhome, 'specifications', 'a-1.gemspec'
- assert_path_exists File.join @gemhome, 'specifications', 'b-1.gemspec'
+ assert_path_exist File.join @gemhome, 'specifications', 'a-1.gemspec'
+ assert_path_exist File.join @gemhome, 'specifications', 'b-1.gemspec'
end
def test_install_from_gemdeps_complex_dependencies
@@ -232,7 +232,7 @@ end
assert_includes installed, 'z-1.0.3'
- assert_path_exists File.join @gemhome, 'specifications', 'z-1.0.3.gemspec'
+ assert_path_exist File.join @gemhome, 'specifications', 'z-1.0.3.gemspec'
end
def test_install_from_gemdeps_version_mismatch
@@ -324,7 +324,7 @@ ruby "0"
res = rs.resolve StaticSet.new([a, b])
assert_equal 2, res.size
- names = res.map { |s| s.full_name }.sort
+ names = res.map {|s| s.full_name }.sort
assert_equal ["a-2", "b-2"], names
@@ -343,7 +343,7 @@ ruby "0"
res = rs.resolve StaticSet.new([a, b, c])
assert_equal 3, res.size
- names = res.map { |s| s.full_name }.sort
+ names = res.map {|s| s.full_name }.sort
assert_equal %w[a-1.b b-1.b c-1.1.b], names
end
@@ -396,9 +396,9 @@ ruby "0"
rs = Gem::RequestSet.new
tf = Tempfile.open 'gem.deps.rb' do |io|
- io.puts <<-gems_deps_rb
+ io.puts <<-GEMS_DEPS_RB
gem "#{name}", :git => "#{repository}"
- gems_deps_rb
+ GEMS_DEPS_RB
io.flush
@@ -410,12 +410,12 @@ ruby "0"
res = rs.resolve
assert_equal 1, res.size
- names = res.map { |s| s.full_name }.sort
+ names = res.map {|s| s.full_name }.sort
assert_equal %w[a-1], names
assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet, @DR::SourceSet],
- rs.sets.map { |set| set.class }
+ rs.sets.map {|set| set.class }
end
def test_resolve_ignore_dependencies
@@ -429,7 +429,7 @@ ruby "0"
res = rs.resolve StaticSet.new([a, b])
assert_equal 1, res.size
- names = res.map { |s| s.full_name }.sort
+ names = res.map {|s| s.full_name }.sort
assert_equal %w[a-2], names
end
@@ -444,7 +444,7 @@ ruby "0"
set = StaticSet.new [a1, a2]
- assert_raises Gem::UnsatisfiableDependencyError do
+ assert_raise Gem::UnsatisfiableDependencyError do
rs.resolve set
end
end
@@ -459,10 +459,10 @@ ruby "0"
rs = Gem::RequestSet.new
tf = Tempfile.open 'gem.deps.rb' do |io|
- io.puts <<-gems_deps_rb
+ io.puts <<-GEMS_DEPS_RB
gem "#{a_name}", :path => "#{a_directory}"
gem "#{b_name}", :path => "#{b_directory}"
- gems_deps_rb
+ GEMS_DEPS_RB
io.flush
@@ -474,12 +474,12 @@ ruby "0"
res = rs.resolve
assert_equal 2, res.size
- names = res.map { |s| s.full_name }.sort
+ names = res.map {|s| s.full_name }.sort
assert_equal ["a-1", "b-2"], names
assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet, @DR::SourceSet],
- rs.sets.map { |set| set.class }
+ rs.sets.map {|set| set.class }
end
def test_sorted_requests
@@ -492,8 +492,8 @@ ruby "0"
rs.resolve StaticSet.new([a, b, c])
- names = rs.sorted_requests.map { |s| s.full_name }
- assert_equal %w!c-2 b-2 a-2!, names
+ names = rs.sorted_requests.map {|s| s.full_name }
+ assert_equal %w[c-2 b-2 a-2], names
end
def test_install
@@ -521,14 +521,14 @@ ruby "0"
installers << installer
end
- assert_equal %w[b-1 a-1], reqs.map { |req| req.full_name }
+ assert_equal %w[b-1 a-1], reqs.map {|req| req.full_name }
assert_equal %w[b-1 a-1],
- installers.map { |installer| installer.spec.full_name }
+ installers.map {|installer| installer.spec.full_name }
- assert_path_exists File.join @gemhome, 'specifications', 'a-1.gemspec'
- assert_path_exists File.join @gemhome, 'specifications', 'b-1.gemspec'
+ assert_path_exist File.join @gemhome, 'specifications', 'a-1.gemspec'
+ assert_path_exist File.join @gemhome, 'specifications', 'b-1.gemspec'
- assert_equal %w[b-1 a-1], installed.map { |s| s.full_name }
+ assert_equal %w[b-1 a-1], installed.map {|s| s.full_name }
assert done_installing_ran
end
@@ -548,10 +548,10 @@ ruby "0"
assert_equal @tempdir, ENV['GEM_HOME']
end
- assert_path_exists File.join @tempdir, 'specifications', 'a-1.gemspec'
- assert_path_exists File.join @tempdir, 'specifications', 'b-1.gemspec'
+ assert_path_exist File.join @tempdir, 'specifications', 'a-1.gemspec'
+ assert_path_exist File.join @tempdir, 'specifications', 'b-1.gemspec'
- assert_equal %w!b-1 a-1!, installed.map { |s| s.full_name }
+ assert_equal %w[b-1 a-1], installed.map {|s| s.full_name }
end
def test_install_into_development_shallow
@@ -583,7 +583,7 @@ ruby "0"
assert_equal @tempdir, ENV['GEM_HOME']
end
- assert_equal %w[a-1 b-1], installed.map { |s| s.full_name }.sort
+ assert_equal %w[a-1 b-1], installed.map {|s| s.full_name }.sort
end
def test_sorted_requests_development_shallow
@@ -608,7 +608,7 @@ ruby "0"
rs.resolve StaticSet.new [a_spec, b_spec, c_spec]
- assert_equal %w[b-1 a-1], rs.sorted_requests.map { |req| req.full_name }
+ assert_equal %w[b-1 a-1], rs.sorted_requests.map {|req| req.full_name }
end
def test_tsort_each_child_development
@@ -637,7 +637,7 @@ ruby "0"
deps = rs.enum_for(:tsort_each_child, a_req).to_a
- assert_equal %w[b], deps.map { |dep| dep.name }
+ assert_equal %w[b], deps.map {|dep| dep.name }
end
def test_tsort_each_child_development_shallow
@@ -668,5 +668,4 @@ ruby "0"
assert_empty deps
end
-
end
diff --git a/test/rubygems/test_gem_request_set_gem_dependency_api.rb b/test/rubygems/test_gem_request_set_gem_dependency_api.rb
index f3d4c6fc72..cc4f99df91 100644
--- a/test/rubygems/test_gem_request_set_gem_dependency_api.rb
+++ b/test/rubygems/test_gem_request_set_gem_dependency_api.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/request_set'
class TestGemRequestSetGemDependencyAPI < Gem::TestCase
-
def setup
super
@@ -49,8 +48,8 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
s.add_runtime_dependency 'bar', '>= 1.6.0', '< 1.6.4'
end
@gda.gemspec
- assert_equal %w{ foo bar }.sort, @set.dependencies.map(&:name).sort
- bar = @set.dependencies.find { |d| d.name == 'bar' }
+ assert_equal %w[ foo bar ].sort, @set.dependencies.map(&:name).sort
+ bar = @set.dependencies.find {|d| d.name == 'bar' }
assert_equal [["<", Gem::Version.create('1.6.4')],
[">=", Gem::Version.create('1.6.0')]], bar.requirement.requirements.sort
end
@@ -82,7 +81,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
def test_gem_duplicate
@gda.gem 'a'
- _, err = capture_io do
+ _, err = capture_output do
@gda.gem 'a'
end
@@ -130,7 +129,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gem_git_branch
- _, err = capture_io do
+ _, err = capture_output do
@gda.gem 'a', :git => 'git/a', :branch => 'other', :tag => 'v1'
end
expected = "Gem dependencies file gem.deps.rb includes git reference for both ref/branch and tag but only ref/branch is used."
@@ -151,7 +150,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gem_git_ref
- _, err = capture_io do
+ _, err = capture_output do
@gda.gem 'a', :git => 'git/a', :ref => 'abcd123', :branch => 'other'
end
expected = "Gem dependencies file gem.deps.rb includes git reference for both ref and branch but only ref is used."
@@ -389,7 +388,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gem_platforms_unknown
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
@gda.gem 'a', :platforms => :unknown
end
@@ -456,7 +455,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
gda = @GDA.new @set, nil
gda.gem name
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
gda.gem name, :path => directory
end
@@ -467,7 +466,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
gda.instance_variable_set :@vendor_set, @vendor_set
gda.gem name, :path => directory
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
gda.gem name
end
@@ -490,7 +489,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
groups = @gda.send :gem_group, 'a', :group => :b, :groups => [:c, :d]
end
- assert_equal [:a, :b, :c, :d], groups.sort_by { |group| group.to_s }
+ assert_equal [:a, :b, :c, :d], groups.sort_by {|group| group.to_s }
end
def test_gemspec
@@ -518,8 +517,8 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
def test_gemspec_bad
FileUtils.touch 'a.gemspec'
- e = assert_raises ArgumentError do
- capture_io do
+ e = assert_raise ArgumentError do
+ capture_output do
@gda.gemspec
end
end
@@ -551,7 +550,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
s.add_dependency 'c', 3
end
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
@gda.gemspec
end
@@ -583,7 +582,7 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gemspec_none
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
@gda.gemspec
end
@@ -659,14 +658,14 @@ end
gda.send :pin_gem_source, 'a'
gda.send :pin_gem_source, 'a'
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
gda.send :pin_gem_source, 'a', :path, 'vendor/a'
end
assert_equal "duplicate source path: vendor/a for gem a",
e.message
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
gda.send :pin_gem_source, 'a', :git, 'git://example/repo.git'
end
@@ -771,7 +770,7 @@ end
def test_ruby_engine_mismatch_engine
with_engine_version 'ruby', '2.0.0' do
- e = assert_raises Gem::RubyVersionMismatch do
+ e = assert_raise Gem::RubyVersionMismatch do
@gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4'
end
@@ -782,7 +781,7 @@ end
def test_ruby_engine_mismatch_version
with_engine_version 'jruby', '1.7.6' do
- e = assert_raises Gem::RubyVersionMismatch do
+ e = assert_raise Gem::RubyVersionMismatch do
@gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4'
end
@@ -792,7 +791,7 @@ end
end
def test_ruby_engine_no_engine_version
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
@gda.ruby RUBY_VERSION, :engine => 'jruby'
end
@@ -801,7 +800,7 @@ end
end
def test_ruby_mismatch
- e = assert_raises Gem::RubyVersionMismatch do
+ e = assert_raise Gem::RubyVersionMismatch do
@gda.ruby '1.8.0'
end
@@ -845,5 +844,4 @@ end
assert_equal engine_version, RUBY_ENGINE_VERSION if engine
end
-
end unless Gem.java_platform?
diff --git a/test/rubygems/test_gem_request_set_lockfile.rb b/test/rubygems/test_gem_request_set_lockfile.rb
index 7c5e256a2d..690b632d9b 100644
--- a/test/rubygems/test_gem_request_set_lockfile.rb
+++ b/test/rubygems/test_gem_request_set_lockfile.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/request_set'
require 'rubygems/request_set/lockfile'
class TestGemRequestSetLockfile < Gem::TestCase
-
def setup
super
@@ -52,7 +51,7 @@ class TestGemRequestSetLockfile < Gem::TestCase
expected = [
'DEPENDENCIES',
' a',
- nil
+ nil,
]
assert_equal expected, out
@@ -79,7 +78,7 @@ class TestGemRequestSetLockfile < Gem::TestCase
expected = [
'DEPENDENCIES',
' a (~> 2.0)',
- nil
+ nil,
]
assert_equal expected, out
@@ -112,7 +111,7 @@ class TestGemRequestSetLockfile < Gem::TestCase
' a (2)',
' b',
' b (2)',
- nil
+ nil,
]
assert_equal expected, out
@@ -140,7 +139,7 @@ class TestGemRequestSetLockfile < Gem::TestCase
'PLATFORMS',
' ruby',
' x86-darwin-8',
- nil
+ nil,
]
assert_equal expected, out
@@ -444,7 +443,7 @@ DEPENDENCIES
gem_deps_lock_file = "#{@gem_deps_file}.lock"
- assert_path_exists gem_deps_lock_file
+ assert_path_exist gem_deps_lock_file
refute_empty File.read gem_deps_lock_file
end
@@ -458,13 +457,12 @@ DEPENDENCIES
io.write 'hello'
end
- assert_raises Gem::UnsatisfiableDependencyError do
+ assert_raise Gem::UnsatisfiableDependencyError do
lockfile.write
end
- assert_path_exists gem_deps_lock_file
+ assert_path_exist gem_deps_lock_file
assert_equal 'hello', File.read(gem_deps_lock_file)
end
-
end
diff --git a/test/rubygems/test_gem_request_set_lockfile_parser.rb b/test/rubygems/test_gem_request_set_lockfile_parser.rb
index 7fc93c36e5..4007c3a69c 100644
--- a/test/rubygems/test_gem_request_set_lockfile_parser.rb
+++ b/test/rubygems/test_gem_request_set_lockfile_parser.rb
@@ -1,12 +1,11 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/request_set'
require 'rubygems/request_set/lockfile'
require 'rubygems/request_set/lockfile/tokenizer'
require 'rubygems/request_set/lockfile/parser'
class TestGemRequestSetLockfileParser < Gem::TestCase
-
def setup
super
@gem_deps_file = 'gem.deps.rb'
@@ -26,7 +25,7 @@ class TestGemRequestSetLockfileParser < Gem::TestCase
tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "foo", filename, 1, 0
parser = tokenizer.make_parser nil, nil
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ e = assert_raise Gem::RequestSet::Lockfile::ParseError do
parser.get :section
end
@@ -53,7 +52,7 @@ class TestGemRequestSetLockfileParser < Gem::TestCase
tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "x", filename, 1
parser = tokenizer.make_parser nil, nil
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ e = assert_raise Gem::RequestSet::Lockfile::ParseError do
parser.get :text, 'y'
end
@@ -94,7 +93,7 @@ DEPENDENCIES
assert lockfile_set, 'could not find a LockSet'
- assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
+ assert_equal %w[a-2], lockfile_set.specs.map {|tuple| tuple.full_name }
end
def test_parse_dependencies
@@ -124,7 +123,7 @@ DEPENDENCIES
assert lockfile_set, 'could not find a LockSet'
- assert_equal %w[a-2], lockfile_set.specs.map { |tuple| tuple.full_name }
+ assert_equal %w[a-2], lockfile_set.specs.map {|tuple| tuple.full_name }
end
def test_parse_DEPENDENCIES_git
@@ -218,7 +217,7 @@ DEPENDENCIES
assert lockfile_set, 'found a LockSet'
- assert_equal %w[a-2], lockfile_set.specs.map { |s| s.full_name }
+ assert_equal %w[a-2], lockfile_set.specs.map {|s| s.full_name }
end
def test_parse_GEM_remote_multiple
@@ -246,10 +245,10 @@ DEPENDENCIES
assert lockfile_set, 'found a LockSet'
- assert_equal %w[a-2], lockfile_set.specs.map { |s| s.full_name }
+ assert_equal %w[a-2], lockfile_set.specs.map {|s| s.full_name }
assert_equal %w[https://gems.example/ https://other.example/],
- lockfile_set.specs.flat_map { |s| s.sources.map{ |src| src.uri.to_s } }
+ lockfile_set.specs.flat_map {|s| s.sources.map{|src| src.uri.to_s } }
end
def test_parse_GIT
@@ -284,7 +283,7 @@ DEPENDENCIES
assert git_set, 'could not find a GitSet'
- assert_equal %w[a-2], git_set.specs.values.map { |s| s.full_name }
+ assert_equal %w[a-2], git_set.specs.values.map {|s| s.full_name }
assert_equal [dep('b', '>= 3'), dep('c')],
git_set.specs.values.first.dependencies
@@ -438,7 +437,7 @@ DEPENDENCIES
assert vendor_set, 'could not find a VendorSet'
- assert_equal %w[a-1], vendor_set.specs.values.map { |s| s.full_name }
+ assert_equal %w[a-1], vendor_set.specs.values.map {|s| s.full_name }
spec = vendor_set.load_spec 'a', nil, nil, nil
@@ -497,14 +496,14 @@ DEPENDENCIES
assert lockfile_set, 'could not find a LockSet'
- assert_equal %w[a-2 b-3], lockfile_set.specs.map { |tuple| tuple.full_name }
+ assert_equal %w[a-2 b-3], lockfile_set.specs.map {|tuple| tuple.full_name }
expected = [
Gem::Platform::RUBY,
Gem::Platform.new('x86_64-linux'),
]
- assert_equal expected, lockfile_set.specs.map { |tuple| tuple.platform }
+ assert_equal expected, lockfile_set.specs.map {|tuple| tuple.platform }
spec = lockfile_set.specs.first
@@ -519,7 +518,7 @@ DEPENDENCIES
end
def test_parse_missing
- assert_raises(Errno::ENOENT) do
+ assert_raise(Errno::ENOENT) do
parse_lockfile @set, []
end
@@ -541,5 +540,4 @@ DEPENDENCIES
parser = tokenizer.make_parser set, platforms
parser.parse
end
-
end
diff --git a/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb b/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb
index aa91fc4468..f779c33012 100644
--- a/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb
+++ b/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb
@@ -1,12 +1,11 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/request_set'
require 'rubygems/request_set/lockfile'
require 'rubygems/request_set/lockfile/tokenizer'
require 'rubygems/request_set/lockfile/parser'
class TestGemRequestSetLockfileTokenizer < Gem::TestCase
-
def setup
super
@@ -64,86 +63,86 @@ DEPENDENCIES
LOCKFILE
expected = [
- [:section, 'GEM', 0, 0],
- [:newline, nil, 3, 0],
-
- [:entry, 'remote', 2, 1],
- [:text, @gem_repo, 10, 1],
- [:newline, nil, 34, 1],
-
- [:entry, 'specs', 2, 2],
- [:newline, nil, 8, 2],
-
- [:text, 'a', 4, 3],
- [:l_paren, nil, 6, 3],
- [:text, '2', 7, 3],
- [:r_paren, nil, 8, 3],
- [:newline, nil, 9, 3],
-
- [:text, 'b', 6, 4],
- [:l_paren, nil, 8, 4],
- [:requirement, '=', 9, 4],
- [:text, '2', 11, 4],
- [:r_paren, nil, 12, 4],
- [:newline, nil, 13, 4],
-
- [:text, 'c', 6, 5],
- [:l_paren, nil, 8, 5],
- [:requirement, '!=', 9, 5],
- [:text, '3', 12, 5],
- [:r_paren, nil, 13, 5],
- [:newline, nil, 14, 5],
-
- [:text, 'd', 6, 6],
- [:l_paren, nil, 8, 6],
- [:requirement, '>', 9, 6],
- [:text, '4', 11, 6],
- [:r_paren, nil, 12, 6],
- [:newline, nil, 13, 6],
-
- [:text, 'e', 6, 7],
- [:l_paren, nil, 8, 7],
- [:requirement, '<', 9, 7],
- [:text, '5', 11, 7],
- [:r_paren, nil, 12, 7],
- [:newline, nil, 13, 7],
-
- [:text, 'f', 6, 8],
- [:l_paren, nil, 8, 8],
- [:requirement, '>=', 9, 8],
- [:text, '6', 12, 8],
- [:r_paren, nil, 13, 8],
- [:newline, nil, 14, 8],
-
- [:text, 'g', 6, 9],
- [:l_paren, nil, 8, 9],
- [:requirement, '<=', 9, 9],
- [:text, '7', 12, 9],
- [:r_paren, nil, 13, 9],
- [:newline, nil, 14, 9],
-
- [:text, 'h', 6, 10],
- [:l_paren, nil, 8, 10],
- [:requirement, '~>', 9, 10],
+ [:section, 'GEM', 0, 0],
+ [:newline, nil, 3, 0],
+
+ [:entry, 'remote', 2, 1],
+ [:text, @gem_repo, 10, 1],
+ [:newline, nil, 34, 1],
+
+ [:entry, 'specs', 2, 2],
+ [:newline, nil, 8, 2],
+
+ [:text, 'a', 4, 3],
+ [:l_paren, nil, 6, 3],
+ [:text, '2', 7, 3],
+ [:r_paren, nil, 8, 3],
+ [:newline, nil, 9, 3],
+
+ [:text, 'b', 6, 4],
+ [:l_paren, nil, 8, 4],
+ [:requirement, '=', 9, 4],
+ [:text, '2', 11, 4],
+ [:r_paren, nil, 12, 4],
+ [:newline, nil, 13, 4],
+
+ [:text, 'c', 6, 5],
+ [:l_paren, nil, 8, 5],
+ [:requirement, '!=', 9, 5],
+ [:text, '3', 12, 5],
+ [:r_paren, nil, 13, 5],
+ [:newline, nil, 14, 5],
+
+ [:text, 'd', 6, 6],
+ [:l_paren, nil, 8, 6],
+ [:requirement, '>', 9, 6],
+ [:text, '4', 11, 6],
+ [:r_paren, nil, 12, 6],
+ [:newline, nil, 13, 6],
+
+ [:text, 'e', 6, 7],
+ [:l_paren, nil, 8, 7],
+ [:requirement, '<', 9, 7],
+ [:text, '5', 11, 7],
+ [:r_paren, nil, 12, 7],
+ [:newline, nil, 13, 7],
+
+ [:text, 'f', 6, 8],
+ [:l_paren, nil, 8, 8],
+ [:requirement, '>=', 9, 8],
+ [:text, '6', 12, 8],
+ [:r_paren, nil, 13, 8],
+ [:newline, nil, 14, 8],
+
+ [:text, 'g', 6, 9],
+ [:l_paren, nil, 8, 9],
+ [:requirement, '<=', 9, 9],
+ [:text, '7', 12, 9],
+ [:r_paren, nil, 13, 9],
+ [:newline, nil, 14, 9],
+
+ [:text, 'h', 6, 10],
+ [:l_paren, nil, 8, 10],
+ [:requirement, '~>', 9, 10],
[:text, '8', 12, 10],
[:r_paren, nil, 13, 10],
[:newline, nil, 14, 10],
- [:newline, nil, 0, 11],
+ [:newline, nil, 0, 11],
- [:section, 'PLATFORMS', 0, 12],
- [:newline, nil, 9, 12],
+ [:section, 'PLATFORMS', 0, 12],
+ [:newline, nil, 9, 12],
- [:text, Gem::Platform::RUBY, 2, 13],
- [:newline, nil, 6, 13],
+ [:text, Gem::Platform::RUBY, 2, 13],
+ [:newline, nil, 6, 13],
- [:newline, nil, 0, 14],
+ [:newline, nil, 0, 14],
- [:section, 'DEPENDENCIES', 0, 15],
+ [:section, 'DEPENDENCIES', 0, 15],
[:newline, nil, 12, 15],
- [:text, 'a', 2, 16],
- [:newline, nil, 3, 16],
+ [:text, 'a', 2, 16],
+ [:newline, nil, 3, 16],
]
assert_equal expected, tokenize_lockfile
@@ -164,28 +163,28 @@ DEPENDENCIES
LOCKFILE
expected = [
- [:section, 'GEM', 0, 0],
- [:newline, nil, 3, 0],
- [:entry, 'remote', 2, 1],
+ [:section, 'GEM', 0, 0],
+ [:newline, nil, 3, 0],
+ [:entry, 'remote', 2, 1],
[:text, @gem_repo, 10, 1],
[:newline, nil, 34, 1],
- [:entry, 'specs', 2, 2],
- [:newline, nil, 8, 2],
- [:text, 'Ab', 4, 3],
- [:l_paren, nil, 7, 3],
- [:text, '2', 8, 3],
- [:r_paren, nil, 9, 3],
+ [:entry, 'specs', 2, 2],
+ [:newline, nil, 8, 2],
+ [:text, 'Ab', 4, 3],
+ [:l_paren, nil, 7, 3],
+ [:text, '2', 8, 3],
+ [:r_paren, nil, 9, 3],
[:newline, nil, 10, 3],
- [:newline, nil, 0, 4],
- [:section, 'PLATFORMS', 0, 5],
- [:newline, nil, 9, 5],
- [:text, Gem::Platform::RUBY, 2, 6],
- [:newline, nil, 6, 6],
- [:newline, nil, 0, 7],
- [:section, 'DEPENDENCIES', 0, 8],
+ [:newline, nil, 0, 4],
+ [:section, 'PLATFORMS', 0, 5],
+ [:newline, nil, 9, 5],
+ [:text, Gem::Platform::RUBY, 2, 6],
+ [:newline, nil, 6, 6],
+ [:newline, nil, 0, 7],
+ [:section, 'DEPENDENCIES', 0, 8],
[:newline, nil, 12, 8],
- [:text, 'Ab', 2, 9],
- [:newline, nil, 4, 9],
+ [:text, 'Ab', 2, 9],
+ [:newline, nil, 4, 9],
]
assert_equal expected, tokenize_lockfile
@@ -194,7 +193,7 @@ DEPENDENCIES
def test_tokenize_conflict_markers
write_lockfile '<<<<<<<'
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ e = assert_raise Gem::RequestSet::Lockfile::ParseError do
tokenize_lockfile
end
@@ -203,7 +202,7 @@ DEPENDENCIES
write_lockfile '|||||||'
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ e = assert_raise Gem::RequestSet::Lockfile::ParseError do
tokenize_lockfile
end
@@ -212,7 +211,7 @@ DEPENDENCIES
write_lockfile '======='
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ e = assert_raise Gem::RequestSet::Lockfile::ParseError do
tokenize_lockfile
end
@@ -221,7 +220,7 @@ DEPENDENCIES
write_lockfile '>>>>>>>'
- e = assert_raises Gem::RequestSet::Lockfile::ParseError do
+ e = assert_raise Gem::RequestSet::Lockfile::ParseError do
tokenize_lockfile
end
@@ -236,12 +235,12 @@ DEPENDENCIES
LOCKFILE
expected = [
- [:section, 'DEPENDENCIES', 0, 0],
- [:newline, nil, 12, 0],
+ [:section, 'DEPENDENCIES', 0, 0],
+ [:newline, nil, 12, 0],
- [:text, 'a', 2, 1],
- [:bang, nil, 3, 1],
- [:newline, nil, 4, 1],
+ [:text, 'a', 2, 1],
+ [:bang, nil, 3, 1],
+ [:newline, nil, 4, 1],
]
assert_equal expected, tokenize_lockfile
@@ -257,31 +256,31 @@ GEM
LOCKFILE
expected = [
- [:section, 'GEM', 0, 0],
- [:newline, nil, 3, 0],
-
- [:entry, 'remote', 2, 1],
- [:text, @gem_repo, 10, 1],
- [:newline, nil, 34, 1],
-
- [:entry, 'specs', 2, 2],
- [:newline, nil, 8, 2],
-
- [:text, 'a', 4, 3],
- [:l_paren, nil, 6, 3],
- [:text, '2', 7, 3],
- [:r_paren, nil, 8, 3],
- [:newline, nil, 9, 3],
-
- [:text, 'b', 6, 4],
- [:l_paren, nil, 8, 4],
- [:requirement, '~>', 9, 4],
- [:text, '3.0', 12, 4],
- [:comma, nil, 15, 4],
- [:requirement, '>=', 17, 4],
- [:text, '3.0.1', 20, 4],
- [:r_paren, nil, 25, 4],
- [:newline, nil, 26, 4],
+ [:section, 'GEM', 0, 0],
+ [:newline, nil, 3, 0],
+
+ [:entry, 'remote', 2, 1],
+ [:text, @gem_repo, 10, 1],
+ [:newline, nil, 34, 1],
+
+ [:entry, 'specs', 2, 2],
+ [:newline, nil, 8, 2],
+
+ [:text, 'a', 4, 3],
+ [:l_paren, nil, 6, 3],
+ [:text, '2', 7, 3],
+ [:r_paren, nil, 8, 3],
+ [:newline, nil, 9, 3],
+
+ [:text, 'b', 6, 4],
+ [:l_paren, nil, 8, 4],
+ [:requirement, '~>', 9, 4],
+ [:text, '3.0', 12, 4],
+ [:comma, nil, 15, 4],
+ [:requirement, '>=', 17, 4],
+ [:text, '3.0.1', 20, 4],
+ [:r_paren, nil, 25, 4],
+ [:newline, nil, 26, 4],
]
assert_equal expected, tokenize_lockfile
@@ -304,5 +303,4 @@ GEM
def tokenize_lockfile
Gem::RequestSet::Lockfile::Tokenizer.from_file(@lock_file).to_a
end
-
end
diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb
index 3db393e978..b20b3cc0dc 100644
--- a/test/rubygems/test_gem_requirement.rb
+++ b/test/rubygems/test_gem_requirement.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require "rubygems/requirement"
class TestGemRequirement < Gem::TestCase
-
def test_concat
r = req '>= 1'
@@ -23,6 +22,8 @@ class TestGemRequirement < Gem::TestCase
refute_requirement_equal "~> 1.3", "~> 1.3.0"
refute_requirement_equal "~> 1.3.0", "~> 1.3"
+ assert_requirement_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"]
+
assert_requirement_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"]
assert_requirement_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"]
@@ -82,6 +83,12 @@ class TestGemRequirement < Gem::TestCase
Gem::Requirement.parse(Gem::Version.new('2'))
end
+ if RUBY_VERSION >= '2.5' && !(Gem.java_platform? && ENV["JRUBY_OPTS"] =~ /--debug/)
+ def test_parse_deduplication
+ assert_same '~>', Gem::Requirement.parse('~> 1').first
+ end
+ end
+
def test_parse_bad
[
nil,
@@ -90,7 +97,7 @@ class TestGemRequirement < Gem::TestCase
'= junk',
'1..2',
].each do |bad|
- e = assert_raises Gem::Requirement::BadRequirementError do
+ e = assert_raise Gem::Requirement::BadRequirementError do
Gem::Requirement.parse bad
end
@@ -121,7 +128,7 @@ class TestGemRequirement < Gem::TestCase
refute_satisfied_by "1.2", r
assert_satisfied_by "1.3", r
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
assert_satisfied_by nil, r
end
end
@@ -133,7 +140,7 @@ class TestGemRequirement < Gem::TestCase
assert_satisfied_by "1.2", r
refute_satisfied_by "1.3", r
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
assert_satisfied_by nil, r
end
end
@@ -145,7 +152,7 @@ class TestGemRequirement < Gem::TestCase
assert_satisfied_by "1.2", r
refute_satisfied_by "1.3", r
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
assert_satisfied_by nil, r
end
end
@@ -157,7 +164,7 @@ class TestGemRequirement < Gem::TestCase
refute_satisfied_by "1.2", r
assert_satisfied_by "1.3", r
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
r.satisfied_by? nil
end
end
@@ -169,7 +176,7 @@ class TestGemRequirement < Gem::TestCase
assert_satisfied_by "1.2", r
assert_satisfied_by "1.3", r
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
r.satisfied_by? nil
end
end
@@ -181,7 +188,7 @@ class TestGemRequirement < Gem::TestCase
assert_satisfied_by "1.2", r
refute_satisfied_by "1.3", r
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
r.satisfied_by? nil
end
end
@@ -193,7 +200,7 @@ class TestGemRequirement < Gem::TestCase
refute_satisfied_by "1.2", r
refute_satisfied_by "1.3", r
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
r.satisfied_by? nil
end
end
@@ -205,7 +212,7 @@ class TestGemRequirement < Gem::TestCase
assert_satisfied_by "1.2", r
refute_satisfied_by "1.3", r
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
r.satisfied_by? nil
end
end
@@ -217,7 +224,7 @@ class TestGemRequirement < Gem::TestCase
assert_satisfied_by "1.2", r
assert_satisfied_by "1.3", r
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
r.satisfied_by? nil
end
end
@@ -275,18 +282,18 @@ class TestGemRequirement < Gem::TestCase
def test_illformed_requirements
[ ">>> 1.3.5", "> blah" ].each do |rq|
- assert_raises Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do
+ assert_raise Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do
Gem::Requirement.new rq
end
end
end
def test_satisfied_by_eh_non_versions
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
req(">= 0").satisfied_by? Object.new
end
- assert_raises ArgumentError do
+ assert_raise ArgumentError do
req(">= 0").satisfied_by? Gem::Requirement.default
end
end
@@ -390,11 +397,66 @@ class TestGemRequirement < Gem::TestCase
r2 = req('2.0', '1.0')
assert_equal r1.hash, r2.hash
- r1 = req('1.0', '2.0').tap { |r| r.concat(['3.0']) }
- r2 = req('3.0', '1.0').tap { |r| r.concat(['2.0']) }
+ r1 = req('1.0', '2.0').tap {|r| r.concat(['3.0']) }
+ r2 = req('3.0', '1.0').tap {|r| r.concat(['2.0']) }
assert_equal r1.hash, r2.hash
end
+ def test_hash_returns_equal_hashes_for_equivalent_requirements
+ refute_requirement_hash_equal "= 1.2", "= 1.3"
+ refute_requirement_hash_equal "= 1.3", "= 1.2"
+
+ refute_requirement_hash_equal "~> 1.3", "~> 1.3.0"
+ refute_requirement_hash_equal "~> 1.3.0", "~> 1.3"
+
+ assert_requirement_hash_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"]
+
+ assert_requirement_hash_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"]
+ assert_requirement_hash_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"]
+
+ assert_requirement_hash_equal "= 1.0", "= 1.0.0"
+ assert_requirement_hash_equal "= 1.1", "= 1.1.0"
+ assert_requirement_hash_equal "= 1", "= 1.0.0"
+
+ assert_requirement_hash_equal "1.0", "1.0.0"
+ assert_requirement_hash_equal "1.1", "1.1.0"
+ assert_requirement_hash_equal "1", "1.0.0"
+ end
+
+ class Exploit < RuntimeError
+ end
+
+ def self.exploit(arg)
+ raise Exploit, "arg = #{arg}"
+ end
+
+ def test_marshal_load_attack
+ wa = Net::WriteAdapter.allocate
+ wa.instance_variable_set(:@socket, self.class)
+ wa.instance_variable_set(:@method_id, :exploit)
+ request_set = Gem::RequestSet.allocate
+ request_set.instance_variable_set(:@git_set, "id")
+ request_set.instance_variable_set(:@sets, wa)
+ wa = Net::WriteAdapter.allocate
+ wa.instance_variable_set(:@socket, request_set)
+ wa.instance_variable_set(:@method_id, :resolve)
+ ent = Gem::Package::TarReader::Entry.allocate
+ ent.instance_variable_set(:@read, 0)
+ ent.instance_variable_set(:@header, "aaa")
+ io = Net::BufferedIO.allocate
+ io.instance_variable_set(:@io, ent)
+ io.instance_variable_set(:@debug_output, wa)
+ reader = Gem::Package::TarReader.allocate
+ reader.instance_variable_set(:@io, io)
+ requirement = Gem::Requirement.allocate
+ requirement.instance_variable_set(:@requirements, reader)
+ m = [Gem::SpecFetcher, Gem::Installer, requirement]
+ e = assert_raise(TypeError) do
+ Marshal.load(Marshal.dump(m))
+ end
+ assert_equal(e.message, "wrong @requirements")
+ end
+
# Assert that two requirements are equal. Handles Gem::Requirements,
# strings, arrays, numbers, and versions.
@@ -409,6 +471,13 @@ class TestGemRequirement < Gem::TestCase
"#{requirement} is satisfied by #{version}"
end
+ # Assert that two requirement hashes are equal. Handles Gem::Requirements,
+ # strings, arrays, numbers, and versions.
+
+ def assert_requirement_hash_equal(expected, actual)
+ assert_equal req(expected).hash, req(actual).hash
+ end
+
# Refute the assumption that two requirements are equal.
def refute_requirement_equal(unexpected, actual)
@@ -422,4 +491,9 @@ class TestGemRequirement < Gem::TestCase
"#{requirement} is not satisfied by #{version}"
end
+ # Refute the assumption that two requirements hashes are equal.
+
+ def refute_requirement_hash_equal(unexpected, actual)
+ refute_equal req(unexpected).hash, req(actual).hash
+ end
end
diff --git a/test/rubygems/test_gem_resolver.rb b/test/rubygems/test_gem_resolver.rb
index c35a264741..ea9f9049ce 100644
--- a/test/rubygems/test_gem_resolver.rb
+++ b/test/rubygems/test_gem_resolver.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolver < Gem::TestCase
-
def setup
super
@@ -26,10 +25,10 @@ class TestGemResolver < Gem::TestCase
def assert_resolves_to(expected, resolver)
actual = resolver.resolve
- exp = expected.sort_by { |s| s.full_name }
- act = actual.map { |a| a.spec.spec }.sort_by { |s| s.full_name }
+ exp = expected.sort_by {|s| s.full_name }
+ act = actual.map {|a| a.spec.spec }.sort_by {|s| s.full_name }
- msg = "Set of gems was not the same: #{exp.map { |x| x.full_name}.inspect} != #{act.map { |x| x.full_name}.inspect}"
+ msg = "Set of gems was not the same: #{exp.map {|x| x.full_name }.inspect} != #{act.map {|x| x.full_name }.inspect}"
assert_equal exp, act, msg
rescue Gem::DependencyResolutionError => e
@@ -77,7 +76,7 @@ class TestGemResolver < Gem::TestCase
assert_same index_set, composed
- e = assert_raises ArgumentError do
+ e = assert_raise ArgumentError do
@DR.compose_sets nil
end
@@ -105,7 +104,7 @@ class TestGemResolver < Gem::TestCase
res.requests a1, act, reqs
- assert_equal ['b (= 2)'], reqs.map { |req| req.to_s }
+ assert_equal ['b (= 2)'], reqs.map {|req| req.to_s }
end
def test_requests_development
@@ -127,7 +126,7 @@ class TestGemResolver < Gem::TestCase
res.requests spec, act, reqs
- assert_equal ['b (= 2)'], reqs.map { |req| req.to_s }
+ assert_equal ['b (= 2)'], reqs.map {|req| req.to_s }
assert spec.instance_variable_defined? :@called
end
@@ -267,14 +266,14 @@ class TestGemResolver < Gem::TestCase
res = Gem::Resolver.new [a_dep], Gem::Resolver::IndexSet.new
- e = assert_raises Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
res.resolve
end
refute_empty e.errors
end
- def test_no_overlap_specificly
+ def test_no_overlap_specifically
a = util_spec "a", '1'
b = util_spec "b", "1"
@@ -446,7 +445,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad, bd], s)
- e = assert_raises Gem::DependencyResolutionError do
+ e = assert_raise Gem::DependencyResolutionError do
r.resolve
end
@@ -470,7 +469,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad], set)
- e = assert_raises Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
@@ -487,7 +486,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad], set(a1))
- e = assert_raises Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
@@ -500,7 +499,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad], set(a1))
- e = assert_raises Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
@@ -517,7 +516,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad], set(a1))
- e = assert_raises Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
@@ -540,13 +539,13 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad, bd], s)
- e = assert_raises Gem::DependencyResolutionError do
+ e = assert_raise Gem::DependencyResolutionError do
r.resolve
end
dependency = e.conflict.dependency
- assert_includes %w(a b), dependency.name
+ assert_includes %w[a b], dependency.name
assert_equal req('>= 0'), dependency.requirement
activated = e.conflict.activated
@@ -612,7 +611,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([d1, d2, d3], s)
- assert_raises Gem::DependencyResolutionError do
+ assert_raise Gem::DependencyResolutionError do
r.resolve
end
end
@@ -630,7 +629,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new [a_dep, b_dep], s
- assert_raises Gem::DependencyResolutionError do
+ assert_raise Gem::DependencyResolutionError do
r.resolve
end
end
@@ -782,12 +781,11 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad], set(a1))
- e = assert_raises Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
assert_match "No match for 'a (= 1)' on this platform. Found: c-p-1",
e.message
end
-
end
diff --git a/test/rubygems/test_gem_resolver_activation_request.rb b/test/rubygems/test_gem_resolver_activation_request.rb
index dc11ad47c4..c7b726a230 100644
--- a/test/rubygems/test_gem_resolver_activation_request.rb
+++ b/test/rubygems/test_gem_resolver_activation_request.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverActivationRequest < Gem::TestCase
-
def setup
super
@@ -40,5 +39,4 @@ class TestGemResolverActivationRequest < Gem::TestCase
assert @req.installed?
end
-
end
diff --git a/test/rubygems/test_gem_resolver_api_set.rb b/test/rubygems/test_gem_resolver_api_set.rb
index f6b3e49c74..c3db25d7aa 100644
--- a/test/rubygems/test_gem_resolver_api_set.rb
+++ b/test/rubygems/test_gem_resolver_api_set.rb
@@ -1,36 +1,35 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverAPISet < Gem::TestCase
-
def setup
super
@DR = Gem::Resolver
- @dep_uri = URI "#{@gem_repo}api/v1/dependencies"
+ @dep_uri = URI "#{@gem_repo}info/"
end
def test_initialize
set = @DR::APISet.new
- assert_equal URI('https://rubygems.org/api/v1/dependencies'), set.dep_uri
- assert_equal URI('https://rubygems.org'), set.uri
- assert_equal Gem::Source.new(URI('https://rubygems.org')), set.source
+ assert_equal URI('https://index.rubygems.org/info/'), set.dep_uri
+ assert_equal URI('https://index.rubygems.org/'), set.uri
+ assert_equal Gem::Source.new(URI('https://index.rubygems.org')), set.source
end
def test_initialize_deeper_uri
- set = @DR::APISet.new 'https://rubygemsserver.com/mygems/api/v1/dependencies'
+ set = @DR::APISet.new 'https://rubygemsserver.com/mygems/info'
- assert_equal URI('https://rubygemsserver.com/mygems/api/v1/dependencies'), set.dep_uri
- assert_equal URI('https://rubygemsserver.com/mygems/'), set.uri
- assert_equal Gem::Source.new(URI('https://rubygemsserver.com/mygems/')), set.source
+ assert_equal URI('https://rubygemsserver.com/mygems/info'), set.dep_uri
+ assert_equal URI('https://rubygemsserver.com/'), set.uri
+ assert_equal Gem::Source.new(URI('https://rubygemsserver.com/')), set.source
end
def test_initialize_uri
set = @DR::APISet.new @dep_uri
- assert_equal URI("#{@gem_repo}api/v1/dependencies"), set.dep_uri
- assert_equal URI("#{@gem_repo}"), set.uri
+ assert_equal URI("#{@gem_repo}info/"), set.dep_uri
+ assert_equal URI("#{@gem_repo}"), set.uri
end
def test_find_all
@@ -40,17 +39,46 @@ class TestGemResolverAPISet < Gem::TestCase
{ :name => 'a',
:number => '1',
:platform => 'ruby',
- :dependencies => [], },
+ :dependencies => [] },
+ ]
+
+ @fetcher.data["#{@dep_uri}a"] = "---\n1 "
+
+ set = @DR::APISet.new @dep_uri
+
+ a_dep = @DR::DependencyRequest.new dep('a'), nil
+
+ expected = [
+ @DR::APISpecification.new(set, data.first),
+ ]
+
+ assert_equal expected, set.find_all(a_dep)
+ end
+
+ def test_find_all_prereleases
+ spec_fetcher
+
+ data = [
+ { :name => 'a',
+ :number => '1',
+ :platform => 'ruby',
+ :dependencies => [] },
+ { :name => 'a',
+ :number => '2.a',
+ :platform => 'ruby',
+ :dependencies => [] },
]
- @fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data
+ @fetcher.data["#{@dep_uri}a"] = "---\n1\n2.a"
set = @DR::APISet.new @dep_uri
+ set.prerelease = true
a_dep = @DR::DependencyRequest.new dep('a'), nil
expected = [
- @DR::APISpecification.new(set, data.first)
+ @DR::APISpecification.new(set, data.first),
+ @DR::APISpecification.new(set, data.last),
]
assert_equal expected, set.find_all(a_dep)
@@ -63,10 +91,10 @@ class TestGemResolverAPISet < Gem::TestCase
{ :name => 'a',
:number => '1',
:platform => 'ruby',
- :dependencies => [], },
+ :dependencies => [] },
]
- @fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data
+ @fetcher.data["#{@dep_uri}a"] = "---\n1 "
set = @DR::APISet.new @dep_uri
@@ -75,12 +103,12 @@ class TestGemResolverAPISet < Gem::TestCase
set.prefetch [a_dep]
expected = [
- @DR::APISpecification.new(set, data.first)
+ @DR::APISpecification.new(set, data.first),
]
assert_equal expected, set.find_all(a_dep)
- @fetcher.data.delete "#{@dep_uri}?gems=a"
+ @fetcher.data.delete "#{@dep_uri}a"
end
def test_find_all_local
@@ -95,7 +123,7 @@ class TestGemResolverAPISet < Gem::TestCase
def test_find_all_missing
spec_fetcher
- @fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump []
+ @fetcher.data["#{@dep_uri}a"] = "---"
set = @DR::APISet.new @dep_uri
@@ -103,7 +131,7 @@ class TestGemResolverAPISet < Gem::TestCase
assert_empty set.find_all(a_dep)
- @fetcher.data.delete "#{@dep_uri}?gems=a"
+ @fetcher.data.delete "#{@dep_uri}a"
assert_empty set.find_all(a_dep)
end
@@ -111,15 +139,8 @@ class TestGemResolverAPISet < Gem::TestCase
def test_prefetch
spec_fetcher
- data = [
- { :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [], },
- ]
-
- @fetcher.data["#{@dep_uri}?gems=a,b"] = Marshal.dump data
- @fetcher.data["#{@dep_uri}?gems=b"] = Marshal.dump []
+ @fetcher.data["#{@dep_uri}a"] = "---\n1 \n"
+ @fetcher.data["#{@dep_uri}b"] = "---"
set = @DR::APISet.new @dep_uri
@@ -128,21 +149,14 @@ class TestGemResolverAPISet < Gem::TestCase
set.prefetch [a_dep, b_dep]
- assert_equal %w[a-1], set.find_all(a_dep).map { |s| s.full_name }
+ assert_equal %w[a-1], set.find_all(a_dep).map {|s| s.full_name }
assert_empty set.find_all(b_dep)
end
def test_prefetch_cache
spec_fetcher
- data = [
- { :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [], },
- ]
-
- @fetcher.data["#{@dep_uri}?gems=a"] = Marshal.dump data
+ @fetcher.data["#{@dep_uri}a"] = "---\n1 \n"
set = @DR::APISet.new @dep_uri
@@ -151,8 +165,8 @@ class TestGemResolverAPISet < Gem::TestCase
set.prefetch [a_dep]
- @fetcher.data.delete "#{@dep_uri}?gems=a"
- @fetcher.data["#{@dep_uri}?gems=b"] = Marshal.dump []
+ @fetcher.data.delete "#{@dep_uri}a"
+ @fetcher.data["#{@dep_uri}?b"] = "---"
set.prefetch [a_dep, b_dep]
end
@@ -160,14 +174,8 @@ class TestGemResolverAPISet < Gem::TestCase
def test_prefetch_cache_missing
spec_fetcher
- data = [
- { :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [], },
- ]
-
- @fetcher.data["#{@dep_uri}?gems=a,b"] = Marshal.dump data
+ @fetcher.data["#{@dep_uri}a"] = "---\n1 \n"
+ @fetcher.data["#{@dep_uri}b"] = "---"
set = @DR::APISet.new @dep_uri
@@ -176,7 +184,8 @@ class TestGemResolverAPISet < Gem::TestCase
set.prefetch [a_dep, b_dep]
- @fetcher.data.delete "#{@dep_uri}?gems=a,b"
+ @fetcher.data.delete "#{@dep_uri}a"
+ @fetcher.data.delete "#{@dep_uri}b"
set.prefetch [a_dep, b_dep]
end
@@ -184,15 +193,8 @@ class TestGemResolverAPISet < Gem::TestCase
def test_prefetch_local
spec_fetcher
- data = [
- { :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [], },
- ]
-
- @fetcher.data["#{@dep_uri}?gems=a,b"] = Marshal.dump data
- @fetcher.data["#{@dep_uri}?gems=b"] = Marshal.dump []
+ @fetcher.data["#{@dep_uri}a"] = "---\n1 \n"
+ @fetcher.data["#{@dep_uri}b"] = "---"
set = @DR::APISet.new @dep_uri
set.remote = false
@@ -204,5 +206,4 @@ class TestGemResolverAPISet < Gem::TestCase
assert_empty set.instance_variable_get :@data
end
-
end
diff --git a/test/rubygems/test_gem_resolver_api_specification.rb b/test/rubygems/test_gem_resolver_api_specification.rb
index 87ff901320..3f9b81868f 100644
--- a/test/rubygems/test_gem_resolver_api_specification.rb
+++ b/test/rubygems/test_gem_resolver_api_specification.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverAPISpecification < Gem::TestCase
-
def test_initialize
set = Gem::Resolver::APISet.new
data = {
@@ -40,7 +39,7 @@ class TestGemResolverAPISpecification < Gem::TestCase
rails = specs['rails-3.0.3']
- repo = @gem_repo + 'api/v1/dependencies'
+ repo = @gem_repo + 'info'
set = Gem::Resolver::APISet.new repo
@@ -124,7 +123,7 @@ class TestGemResolverAPISpecification < Gem::TestCase
fetcher.spec 'a', 1
end
- dep_uri = URI(@gem_repo) + 'api/v1/dependencies'
+ dep_uri = URI(@gem_repo) + 'info'
set = Gem::Resolver::APISet.new dep_uri
data = {
:name => 'a',
@@ -148,7 +147,7 @@ class TestGemResolverAPISpecification < Gem::TestCase
end
end
- dep_uri = URI(@gem_repo) + 'api/v1/dependencies'
+ dep_uri = URI(@gem_repo) + 'info'
set = Gem::Resolver::APISet.new dep_uri
data = {
:name => 'j',
@@ -164,5 +163,4 @@ class TestGemResolverAPISpecification < Gem::TestCase
assert_kind_of Gem::Specification, spec
assert_equal 'j-1-java', spec.full_name
end
-
end
diff --git a/test/rubygems/test_gem_resolver_best_set.rb b/test/rubygems/test_gem_resolver_best_set.rb
index dc6c9b4c44..0e279d16a8 100644
--- a/test/rubygems/test_gem_resolver_best_set.rb
+++ b/test/rubygems/test_gem_resolver_best_set.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverBestSet < Gem::TestCase
-
def setup
super
@@ -30,7 +29,7 @@ class TestGemResolverBestSet < Gem::TestCase
found = set.find_all req
- assert_equal %w[a-1], found.map { |s| s.full_name }
+ assert_equal %w[a-1], found.map {|s| s.full_name }
end
def test_find_all_fallback
@@ -40,7 +39,7 @@ class TestGemResolverBestSet < Gem::TestCase
set = @DR::BestSet.new
- api_uri = URI(@gem_repo) + './api/v1/dependencies'
+ api_uri = URI(@gem_repo)
set.sets << Gem::Resolver::APISet.new(api_uri)
@@ -50,7 +49,7 @@ class TestGemResolverBestSet < Gem::TestCase
found = set.find_all req
- assert_equal %w[a-1], found.map { |s| s.full_name }
+ assert_equal %w[a-1], found.map {|s| s.full_name }
end
def test_find_all_local
@@ -100,12 +99,12 @@ class TestGemResolverBestSet < Gem::TestCase
def test_replace_failed_api_set
set = @DR::BestSet.new
- api_uri = URI(@gem_repo) + './api/v1/dependencies'
+ api_uri = URI(@gem_repo) + './info/'
api_set = Gem::Resolver::APISet.new api_uri
set.sets << api_set
- error_uri = api_uri + '?gems=a'
+ error_uri = api_uri + 'a'
error = Gem::RemoteFetcher::FetchError.new 'bogus', error_uri
@@ -127,11 +126,33 @@ class TestGemResolverBestSet < Gem::TestCase
error = Gem::RemoteFetcher::FetchError.new 'bogus', @gem_repo
- e = assert_raises Gem::RemoteFetcher::FetchError do
+ e = assert_raise Gem::RemoteFetcher::FetchError do
set.replace_failed_api_set error
end
assert_equal error, e
end
+ def test_replace_failed_api_set_uri_with_credentials
+ set = @DR::BestSet.new
+
+ api_uri = URI(@gem_repo) + './info/'
+ api_uri.user = 'user'
+ api_uri.password = 'pass'
+ api_set = Gem::Resolver::APISet.new api_uri
+
+ set.sets << api_set
+
+ error_uri = api_uri + 'a'
+
+ error = Gem::RemoteFetcher::FetchError.new 'bogus', error_uri
+
+ set.replace_failed_api_set error
+
+ assert_equal 1, set.sets.size
+
+ refute_includes set.sets, api_set
+
+ assert_kind_of Gem::Resolver::IndexSet, set.sets.first
+ end
end
diff --git a/test/rubygems/test_gem_resolver_composed_set.rb b/test/rubygems/test_gem_resolver_composed_set.rb
index 0e745433a9..405753a373 100644
--- a/test/rubygems/test_gem_resolver_composed_set.rb
+++ b/test/rubygems/test_gem_resolver_composed_set.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverComposedSet < Gem::TestCase
-
def test_errors
index_set = Gem::Resolver::IndexSet.new
current_set = Gem::Resolver::CurrentSet.new
@@ -41,5 +40,4 @@ class TestGemResolverComposedSet < Gem::TestCase
refute best_set.remote?
refute current_set.remote?
end
-
end
diff --git a/test/rubygems/test_gem_resolver_conflict.rb b/test/rubygems/test_gem_resolver_conflict.rb
index 2385c3eee9..1d46e69c3f 100644
--- a/test/rubygems/test_gem_resolver_conflict.rb
+++ b/test/rubygems/test_gem_resolver_conflict.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverConflict < Gem::TestCase
-
def test_explanation
root =
dependency_request dep('net-ssh', '>= 2.0.13'), 'rye', '0.9.8'
@@ -74,10 +73,9 @@ class TestGemResolverConflict < Gem::TestCase
expected = [
'net-ssh (>= 2.0.13), 2.2.2 activated',
- 'rye (= 0.9.8), 0.9.8 activated'
+ 'rye (= 0.9.8), 0.9.8 activated',
]
assert_equal expected, conflict.request_path(child.requester)
end
-
end
diff --git a/test/rubygems/test_gem_resolver_dependency_request.rb b/test/rubygems/test_gem_resolver_dependency_request.rb
index 51f0be9dcd..cea0a7952d 100644
--- a/test/rubygems/test_gem_resolver_dependency_request.rb
+++ b/test/rubygems/test_gem_resolver_dependency_request.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverDependencyRequest < Gem::TestCase
-
def setup
super
@@ -80,5 +79,4 @@ class TestGemResolverDependencyRequest < Gem::TestCase
assert_equal dependency, dr.dependency
end
-
end
diff --git a/test/rubygems/test_gem_resolver_git_set.rb b/test/rubygems/test_gem_resolver_git_set.rb
index f38859c8b4..145cd6c7df 100644
--- a/test/rubygems/test_gem_resolver_git_set.rb
+++ b/test/rubygems/test_gem_resolver_git_set.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverGitSet < Gem::TestCase
-
def setup
super
@@ -52,7 +51,7 @@ class TestGemResolverGitSet < Gem::TestCase
assert @set.need_submodules[repository]
- refute_path_exists spec.source.repo_cache_dir
+ assert_path_not_exist spec.source.repo_cache_dir
end
def test_find_all
@@ -185,5 +184,4 @@ class TestGemResolverGitSet < Gem::TestCase
assert_equal "#{@gemhome}2", spec.source.root_dir
end
-
end
diff --git a/test/rubygems/test_gem_resolver_git_specification.rb b/test/rubygems/test_gem_resolver_git_specification.rb
index 3391505555..857452c159 100644
--- a/test/rubygems/test_gem_resolver_git_specification.rb
+++ b/test/rubygems/test_gem_resolver_git_specification.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/installer'
class TestGemResolverGitSpecification < Gem::TestCase
-
def setup
super
@@ -63,7 +62,8 @@ class TestGemResolverGitSpecification < Gem::TestCase
# functional test for Gem::Ext::Builder
def test_install_extension
- skip if Gem.java_platform?
+ pend if Gem.java_platform?
+ pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
name, _, repository, = git_gem 'a', 1 do |s|
s.extensions << 'ext/extconf.rb'
end
@@ -92,7 +92,7 @@ class TestGemResolverGitSpecification < Gem::TestCase
git_spec.install({})
- assert_path_exists File.join git_spec.spec.extension_dir, 'b.rb'
+ assert_path_exist File.join git_spec.spec.extension_dir, 'b.rb'
end
def test_install_installed
@@ -110,5 +110,4 @@ class TestGemResolverGitSpecification < Gem::TestCase
assert called
end
-
end
diff --git a/test/rubygems/test_gem_resolver_index_set.rb b/test/rubygems/test_gem_resolver_index_set.rb
index d9a30d0f58..ddae0c2b82 100644
--- a/test/rubygems/test_gem_resolver_index_set.rb
+++ b/test/rubygems/test_gem_resolver_index_set.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverIndexSet < Gem::TestCase
-
def setup
super
@@ -42,7 +41,7 @@ class TestGemResolverIndexSet < Gem::TestCase
found = set.find_all req
- assert_equal %w[a-1], found.map { |s| s.full_name }
+ assert_equal %w[a-1], found.map {|s| s.full_name }
end
def test_find_all_local
@@ -83,7 +82,6 @@ class TestGemResolverIndexSet < Gem::TestCase
found = set.find_all req
- assert_equal %w[a-1.a], found.map { |s| s.full_name }
+ assert_equal %w[a-1.a], found.map {|s| s.full_name }
end
-
end
diff --git a/test/rubygems/test_gem_resolver_index_specification.rb b/test/rubygems/test_gem_resolver_index_specification.rb
index 43e8efd8b6..ef9c17034e 100644
--- a/test/rubygems/test_gem_resolver_index_specification.rb
+++ b/test/rubygems/test_gem_resolver_index_specification.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/available_set'
class TestGemResolverIndexSpecification < Gem::TestCase
-
def test_initialize
set = Gem::Resolver::IndexSet.new
source = Gem::Source.new @gem_repo
@@ -47,7 +46,7 @@ class TestGemResolverIndexSpecification < Gem::TestCase
called = installer
end
- assert_path_exists File.join @gemhome, 'specifications', 'a-2.gemspec'
+ assert_path_exist File.join @gemhome, 'specifications', 'a-2.gemspec'
assert_kind_of Gem::Installer, called
end
@@ -90,5 +89,4 @@ class TestGemResolverIndexSpecification < Gem::TestCase
assert_equal a_2_p.full_name, spec.full_name
end
-
end
diff --git a/test/rubygems/test_gem_resolver_installed_specification.rb b/test/rubygems/test_gem_resolver_installed_specification.rb
index e9422b75f8..0e5ea02fb9 100644
--- a/test/rubygems/test_gem_resolver_installed_specification.rb
+++ b/test/rubygems/test_gem_resolver_installed_specification.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverInstalledSpecification < Gem::TestCase
-
def setup
super
@@ -44,5 +43,4 @@ class TestGemResolverInstalledSpecification < Gem::TestCase
assert b_spec.installable_platform?
end
-
end
diff --git a/test/rubygems/test_gem_resolver_installer_set.rb b/test/rubygems/test_gem_resolver_installer_set.rb
index 5138743cdf..928a16b9d3 100644
--- a/test/rubygems/test_gem_resolver_installer_set.rb
+++ b/test/rubygems/test_gem_resolver_installer_set.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverInstallerSet < Gem::TestCase
-
def test_add_always_install
spec_fetcher do |fetcher|
fetcher.download 'a', 1
@@ -15,9 +14,9 @@ class TestGemResolverInstallerSet < Gem::TestCase
set.add_always_install dep('a')
- assert_equal %w[a-2], set.always_install.map { |s| s.full_name }
+ assert_equal %w[a-2], set.always_install.map {|s| s.full_name }
- e = assert_raises Gem::UnsatisfiableDependencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
set.add_always_install dep('b')
end
@@ -30,7 +29,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
set = Gem::Resolver::InstallerSet.new :both
- e = assert_raises Gem::UnsatisfiableDependencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
set.add_always_install dep 'a'
end
@@ -49,7 +48,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
set.add_always_install dep('a')
- assert_equal %w[a-1], set.always_install.map { |s| s.full_name }
+ assert_equal %w[a-1], set.always_install.map {|s| s.full_name }
end
def test_add_always_install_prerelease
@@ -62,7 +61,25 @@ class TestGemResolverInstallerSet < Gem::TestCase
set.add_always_install dep('a')
- assert_equal %w[a-1], set.always_install.map { |s| s.full_name }
+ assert_equal %w[a-1], set.always_install.map {|s| s.full_name }
+ end
+
+ def test_add_always_install_prerelease_github_problem
+ spec_fetcher do |fetcher|
+ fetcher.gem 'a', 1
+ end
+
+ # Github has an issue in which it will generate a misleading prerelease output in its RubyGems server API and
+ # returns a 0 version for the gem while it doesn't exist.
+ @fetcher.data["#{@gem_repo}prerelease_specs.#{Gem.marshal_version}.gz"] = util_gzip(Marshal.dump([
+ Gem::NameTuple.new('a', Gem::Version.new(0), 'ruby'),
+ ]))
+
+ set = Gem::Resolver::InstallerSet.new :both
+
+ set.add_always_install dep('a')
+
+ assert_equal %w[a-1], set.always_install.map {|s| s.full_name }
end
def test_add_always_install_prerelease_only
@@ -72,7 +89,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
set = Gem::Resolver::InstallerSet.new :both
- assert_raises Gem::UnsatisfiableDependencyError do
+ assert_raise Gem::UnsatisfiableDependencyError do
set.add_always_install dep('a')
end
end
@@ -93,7 +110,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
req = Gem::Resolver::DependencyRequest.new dep('a'), nil
- assert_equal %w[a-1], set.find_all(req).map { |spec| spec.full_name }
+ assert_equal %w[a-1], set.find_all(req).map {|spec| spec.full_name }
end
def test_consider_local_eh
@@ -149,7 +166,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
req = Gem::Resolver::DependencyRequest.new dep('a'), nil
- assert_equal %w[a-2], set.find_all(req).map { |spec| spec.full_name }
+ assert_equal %w[a-2], set.find_all(req).map {|spec| spec.full_name }
end
def test_find_all_prerelease
@@ -162,12 +179,12 @@ class TestGemResolverInstallerSet < Gem::TestCase
req = Gem::Resolver::DependencyRequest.new dep('a'), nil
- assert_equal %w[a-1], set.find_all(req).map { |spec| spec.full_name }
+ assert_equal %w[a-1], set.find_all(req).map {|spec| spec.full_name }
req = Gem::Resolver::DependencyRequest.new dep('a', '>= 0.a'), nil
assert_equal %w[a-1 a-1.a],
- set.find_all(req).map { |spec| spec.full_name }.sort
+ set.find_all(req).map {|spec| spec.full_name }.sort
end
def test_load_spec
@@ -193,7 +210,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
def (set.remote_set).prefetch(_)
raise "called"
end
- assert_raises(RuntimeError){ set.prefetch(nil) }
+ assert_raise(RuntimeError){ set.prefetch(nil) }
set = Gem::Resolver::InstallerSet.new :local
def (set.remote_set).prefetch(_)
@@ -255,5 +272,4 @@ class TestGemResolverInstallerSet < Gem::TestCase
refute set.consider_local?
refute set.consider_remote?
end
-
end
diff --git a/test/rubygems/test_gem_resolver_local_specification.rb b/test/rubygems/test_gem_resolver_local_specification.rb
index 82598f5188..c11f736128 100644
--- a/test/rubygems/test_gem_resolver_local_specification.rb
+++ b/test/rubygems/test_gem_resolver_local_specification.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/available_set'
class TestGemResolverLocalSpecification < Gem::TestCase
-
def setup
super
@@ -25,7 +24,7 @@ class TestGemResolverLocalSpecification < Gem::TestCase
called = installer
end
- assert_path_exists File.join @gemhome, 'specifications', 'a-2.gemspec'
+ assert_path_exist File.join @gemhome, 'specifications', 'a-2.gemspec'
assert_kind_of Gem::Installer, called
end
@@ -41,5 +40,4 @@ class TestGemResolverLocalSpecification < Gem::TestCase
assert b_spec.installable_platform?
end
-
end
diff --git a/test/rubygems/test_gem_resolver_lock_set.rb b/test/rubygems/test_gem_resolver_lock_set.rb
index d5258477d7..dc7767a3f8 100644
--- a/test/rubygems/test_gem_resolver_lock_set.rb
+++ b/test/rubygems/test_gem_resolver_lock_set.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverLockSet < Gem::TestCase
-
def setup
super
@@ -16,7 +15,7 @@ class TestGemResolverLockSet < Gem::TestCase
specs = @set.add 'a', '2', Gem::Platform::RUBY
spec = specs.first
- assert_equal %w[a-2], @set.specs.map { |t| t.full_name }
+ assert_equal %w[a-2], @set.specs.map {|t| t.full_name }
assert_kind_of Gem::Resolver::LockSpecification, spec
@@ -34,11 +33,11 @@ class TestGemResolverLockSet < Gem::TestCase
found = @set.find_all dep 'a'
- assert_equal %w[a-2], found.map { |s| s.full_name }
+ assert_equal %w[a-2], found.map {|s| s.full_name }
found = @set.find_all dep 'a', '>= 0.a'
- assert_equal %w[a-1.a a-2], found.map { |s| s.full_name }
+ assert_equal %w[a-1.a a-2], found.map {|s| s.full_name }
end
def test_load_spec
@@ -59,5 +58,4 @@ class TestGemResolverLockSet < Gem::TestCase
def test_prefetch
assert_respond_to @set, :prefetch
end
-
end
diff --git a/test/rubygems/test_gem_resolver_lock_specification.rb b/test/rubygems/test_gem_resolver_lock_specification.rb
index 7b9b0ac8f7..46c8e5edd6 100644
--- a/test/rubygems/test_gem_resolver_lock_specification.rb
+++ b/test/rubygems/test_gem_resolver_lock_specification.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/installer'
require 'rubygems/resolver'
class TestGemResolverLockSpecification < Gem::TestCase
-
def setup
super
@@ -95,5 +94,4 @@ class TestGemResolverLockSpecification < Gem::TestCase
assert_same real_spec, l_spec.spec
end
-
end
diff --git a/test/rubygems/test_gem_resolver_requirement_list.rb b/test/rubygems/test_gem_resolver_requirement_list.rb
index 4cbb939199..806c387669 100644
--- a/test/rubygems/test_gem_resolver_requirement_list.rb
+++ b/test/rubygems/test_gem_resolver_requirement_list.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverRequirementList < Gem::TestCase
-
def setup
super
@@ -16,5 +15,4 @@ class TestGemResolverRequirementList < Gem::TestCase
assert_equal [req], @list.each.to_a
end
-
end
diff --git a/test/rubygems/test_gem_resolver_specification.rb b/test/rubygems/test_gem_resolver_specification.rb
index e663ff1837..9f28c1c0cf 100644
--- a/test/rubygems/test_gem_resolver_specification.rb
+++ b/test/rubygems/test_gem_resolver_specification.rb
@@ -1,10 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverSpecification < Gem::TestCase
-
class TestSpec < Gem::Resolver::Specification
-
attr_writer :source
attr_reader :spec
@@ -13,7 +11,6 @@ class TestGemResolverSpecification < Gem::TestCase
@spec = spec
end
-
end
def test_install
@@ -29,7 +26,7 @@ class TestGemResolverSpecification < Gem::TestCase
a_spec.install :install_dir => gemhome
- assert_path_exists File.join gemhome, 'gems', a.full_name
+ assert_path_exist File.join gemhome, 'gems', a.full_name
expected = File.join gemhome, 'specifications', a.spec_name
@@ -62,5 +59,4 @@ class TestGemResolverSpecification < Gem::TestCase
assert_equal source, a_spec.source
end
-
end
diff --git a/test/rubygems/test_gem_resolver_vendor_set.rb b/test/rubygems/test_gem_resolver_vendor_set.rb
index 3fc79fec16..e16d43ac1a 100644
--- a/test/rubygems/test_gem_resolver_vendor_set.rb
+++ b/test/rubygems/test_gem_resolver_vendor_set.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverVendorSet < Gem::TestCase
-
def setup
super
@@ -28,7 +27,7 @@ class TestGemResolverVendorSet < Gem::TestCase
FileUtils.rm_r directory
- e = assert_raises Gem::GemNotFoundException do
+ e = assert_raise Gem::GemNotFoundException do
@set.add_vendor_gem name, directory
end
@@ -52,7 +51,7 @@ class TestGemResolverVendorSet < Gem::TestCase
source = Gem::Source::Vendor.new directory
expected = [
- Gem::Resolver::VendorSpecification.new(@set, spec, source)
+ Gem::Resolver::VendorSpecification.new(@set, spec, source),
]
assert_equal expected, found
@@ -75,9 +74,8 @@ class TestGemResolverVendorSet < Gem::TestCase
def test_load_spec
error = Object.const_defined?(:KeyError) ? KeyError : IndexError
- assert_raises error do
+ assert_raise error do
@set.load_spec 'b', v(1), Gem::Platform::RUBY, nil
end
end
-
end
diff --git a/test/rubygems/test_gem_resolver_vendor_specification.rb b/test/rubygems/test_gem_resolver_vendor_specification.rb
index 315ce05539..93382ccd81 100644
--- a/test/rubygems/test_gem_resolver_vendor_specification.rb
+++ b/test/rubygems/test_gem_resolver_vendor_specification.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemResolverVendorSpecification < Gem::TestCase
-
def setup
super
@@ -79,5 +78,4 @@ class TestGemResolverVendorSpecification < Gem::TestCase
assert_equal v(1), v_spec.version
end
-
end
diff --git a/test/rubygems/test_gem_security.rb b/test/rubygems/test_gem_security.rb
index 71185dc86e..d04bd4a8bd 100644
--- a/test/rubygems/test_gem_security.rb
+++ b/test/rubygems/test_gem_security.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/security'
-unless defined?(OpenSSL::SSL)
+unless Gem::HAVE_OPENSSL
warn 'Skipping Gem::Security tests. openssl not found.'
end
@@ -11,8 +11,8 @@ if Gem.java_platform?
end
class TestGemSecurity < Gem::TestCase
-
CHILD_KEY = load_key 'child'
+ EC_KEY = load_key 'private_ec', 'Foo bar'
ALTERNATE_CERT = load_cert 'child'
CHILD_CERT = load_cert 'child'
@@ -40,16 +40,16 @@ class TestGemSecurity < Gem::TestCase
assert_equal name.to_s, cert.subject.to_s
assert_equal 3, cert.extensions.length,
- cert.extensions.map { |e| e.to_a.first }
+ cert.extensions.map {|e| e.to_a.first }
- constraints = cert.extensions.find { |ext| ext.oid == 'basicConstraints' }
+ constraints = cert.extensions.find {|ext| ext.oid == 'basicConstraints' }
assert_equal 'CA:FALSE', constraints.value
- key_usage = cert.extensions.find { |ext| ext.oid == 'keyUsage' }
+ key_usage = cert.extensions.find {|ext| ext.oid == 'keyUsage' }
assert_equal 'Digital Signature, Key Encipherment, Data Encipherment',
key_usage.value
- key_ident = cert.extensions.find { |ext| ext.oid == 'subjectKeyIdentifier' }
+ key_ident = cert.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' }
assert_equal 59, key_ident.value.length
assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B',
key_ident.value
@@ -85,30 +85,57 @@ class TestGemSecurity < Gem::TestCase
assert_equal name.to_s, cert.issuer.to_s
assert_equal 5, cert.extensions.length,
- cert.extensions.map { |e| e.to_a.first }
+ cert.extensions.map {|e| e.to_a.first }
- constraints = cert.extensions.find { |ext| ext.oid == 'subjectAltName' }
+ constraints = cert.extensions.find {|ext| ext.oid == 'subjectAltName' }
assert_equal 'email:nobody@example', constraints.value
- constraints = cert.extensions.find { |ext| ext.oid == 'basicConstraints' }
+ constraints = cert.extensions.find {|ext| ext.oid == 'basicConstraints' }
assert_equal 'CA:FALSE', constraints.value
- key_usage = cert.extensions.find { |ext| ext.oid == 'keyUsage' }
+ key_usage = cert.extensions.find {|ext| ext.oid == 'keyUsage' }
assert_equal 'Digital Signature, Key Encipherment, Data Encipherment',
key_usage.value
- key_ident = cert.extensions.find { |ext| ext.oid == 'subjectKeyIdentifier' }
+ key_ident = cert.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' }
assert_equal 59, key_ident.value.length
assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B',
key_ident.value
end
def test_class_create_key
- key = @SEC.create_key 1024
+ key = @SEC.create_key 'rsa'
assert_kind_of OpenSSL::PKey::RSA, key
end
+ def test_class_create_key_downcases
+ key = @SEC.create_key 'DSA'
+
+ assert_kind_of OpenSSL::PKey::DSA, key
+ end
+
+ def test_class_create_key_raises_unknown_algorithm
+ e = assert_raise Gem::Security::Exception do
+ @SEC.create_key 'NOT_RSA'
+ end
+
+ assert_equal "NOT_RSA algorithm not found. RSA, DSA, and EC algorithms are supported.",
+ e.message
+ end
+
+ def test_class_get_public_key_rsa
+ pkey_pem = PRIVATE_KEY.public_key.to_pem
+
+ assert_equal pkey_pem, @SEC.get_public_key(PRIVATE_KEY).to_pem
+ end
+
+ def test_class_get_public_key_ec
+ pkey = @SEC.get_public_key(EC_KEY)
+
+ assert_respond_to pkey, :to_pem
+ end
+
def test_class_email_to_name
assert_equal '/CN=nobody/DC=example',
@SEC.email_to_name('nobody@example').to_s
@@ -136,7 +163,7 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_re_sign_not_self_signed
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
Gem::Security.re_sign CHILD_CERT, CHILD_KEY
end
@@ -150,7 +177,7 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_re_sign_wrong_key
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
Gem::Security.re_sign ALTERNATE_CERT, PRIVATE_KEY
end
@@ -188,20 +215,20 @@ class TestGemSecurity < Gem::TestCase
assert_in_delta Time.now + 60, signed.not_after, 10
assert_equal 4, signed.extensions.length,
- signed.extensions.map { |e| e.to_a.first }
+ signed.extensions.map {|e| e.to_a.first }
- constraints = signed.extensions.find { |ext| ext.oid == 'issuerAltName' }
+ constraints = signed.extensions.find {|ext| ext.oid == 'issuerAltName' }
assert_equal 'email:nobody@example', constraints.value, 'issuerAltName'
- constraints = signed.extensions.find { |ext| ext.oid == 'basicConstraints' }
+ constraints = signed.extensions.find {|ext| ext.oid == 'basicConstraints' }
assert_equal 'CA:FALSE', constraints.value
- key_usage = signed.extensions.find { |ext| ext.oid == 'keyUsage' }
+ key_usage = signed.extensions.find {|ext| ext.oid == 'keyUsage' }
assert_equal 'Digital Signature, Key Encipherment, Data Encipherment',
key_usage.value
key_ident =
- signed.extensions.find { |ext| ext.oid == 'subjectKeyIdentifier' }
+ signed.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' }
assert_equal 59, key_ident.value.length
assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B',
key_ident.value
@@ -227,23 +254,23 @@ class TestGemSecurity < Gem::TestCase
assert_equal "sha256WithRSAEncryption", signed.signature_algorithm
assert_equal 5, signed.extensions.length,
- signed.extensions.map { |e| e.to_a.first }
+ signed.extensions.map {|e| e.to_a.first }
- constraints = signed.extensions.find { |ext| ext.oid == 'issuerAltName' }
+ constraints = signed.extensions.find {|ext| ext.oid == 'issuerAltName' }
assert_equal 'email:nobody@example', constraints.value, 'issuerAltName'
- constraints = signed.extensions.find { |ext| ext.oid == 'subjectAltName' }
+ constraints = signed.extensions.find {|ext| ext.oid == 'subjectAltName' }
assert_equal 'email:signee@example', constraints.value, 'subjectAltName'
- constraints = signed.extensions.find { |ext| ext.oid == 'basicConstraints' }
+ constraints = signed.extensions.find {|ext| ext.oid == 'basicConstraints' }
assert_equal 'CA:FALSE', constraints.value
- key_usage = signed.extensions.find { |ext| ext.oid == 'keyUsage' }
+ key_usage = signed.extensions.find {|ext| ext.oid == 'keyUsage' }
assert_equal 'Digital Signature, Key Encipherment, Data Encipherment',
key_usage.value
key_ident =
- signed.extensions.find { |ext| ext.oid == 'subjectKeyIdentifier' }
+ signed.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' }
assert_equal 59, key_ident.value.length
assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B',
key_ident.value
@@ -260,13 +287,13 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_write
- key = @SEC.create_key 1024
+ key = @SEC.create_key 'rsa'
path = File.join @tempdir, 'test-private_key.pem'
@SEC.write key, path
- assert_path_exists path
+ assert_path_exist path
key_from_file = File.read path
@@ -274,7 +301,7 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_write_encrypted
- key = @SEC.create_key 1024
+ key = @SEC.create_key 'rsa'
path = File.join @tempdir, 'test-private_encrypted_key.pem'
@@ -282,7 +309,7 @@ class TestGemSecurity < Gem::TestCase
@SEC.write key, path, 0600, passphrase
- assert_path_exists path
+ assert_path_exist path
key_from_file = OpenSSL::PKey::RSA.new File.read(path), passphrase
@@ -290,7 +317,7 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_write_encrypted_cipher
- key = @SEC.create_key 1024
+ key = @SEC.create_key 'rsa'
path = File.join @tempdir, 'test-private_encrypted__with_non_default_cipher_key.pem'
@@ -300,7 +327,7 @@ class TestGemSecurity < Gem::TestCase
@SEC.write key, path, 0600, passphrase, cipher
- assert_path_exists path
+ assert_path_exist path
key_file_contents = File.read(path)
@@ -310,5 +337,4 @@ class TestGemSecurity < Gem::TestCase
assert_equal key.to_pem, key_from_file.to_pem
end
-
-end if defined?(OpenSSL::SSL) && !Gem.java_platform?
+end if Gem::HAVE_OPENSSL && !Gem.java_platform?
diff --git a/test/rubygems/test_gem_security_policy.rb b/test/rubygems/test_gem_security_policy.rb
index 8a1676cd3c..515b8ea00b 100644
--- a/test/rubygems/test_gem_security_policy.rb
+++ b/test/rubygems/test_gem_security_policy.rb
@@ -1,14 +1,12 @@
-# coding: utf-8
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
-unless defined?(OpenSSL::SSL)
+unless Gem::HAVE_OPENSSL
warn 'Skipping Gem::Security::Policy tests. openssl not found.'
end
class TestGemSecurityPolicy < Gem::TestCase
-
ALTERNATE_KEY = load_key 'alternate'
INVALID_KEY = load_key 'invalid'
CHILD_KEY = load_key 'child'
@@ -34,7 +32,7 @@ class TestGemSecurityPolicy < Gem::TestCase
s.files = %w[lib/code.rb]
end
- @digest = Gem::Security::DIGEST_ALGORITHM
+ @digest = OpenSSL::Digest.new Gem::Security::DIGEST_NAME
@trust_dir = Gem::Security.trust_dir.dir # HACK use the object
@no = Gem::Security::NoSecurity
@@ -79,7 +77,7 @@ class TestGemSecurityPolicy < Gem::TestCase
invalid = digest 'hello!'
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@almost_no.check_data PUBLIC_KEY, @digest, signature, invalid
end
@@ -93,7 +91,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_chain_empty_chain
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@chain.check_chain [], Time.now
end
@@ -103,7 +101,7 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_check_chain_invalid
chain = [PUBLIC_CERT, CHILD_CERT, INVALIDCHILD_CERT]
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@chain.check_chain chain, Time.now
end
@@ -113,7 +111,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_chain_no_chain
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@chain.check_chain nil, Time.now
end
@@ -125,7 +123,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_cert_expired
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@low.check_cert EXPIRED_CERT, nil, Time.now
end
@@ -135,7 +133,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_cert_future
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@low.check_cert FUTURE_CERT, nil, Time.now
end
@@ -145,7 +143,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_cert_invalid_issuer
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@low.check_cert INVALID_ISSUER_CERT, PUBLIC_CERT, Time.now
end
@@ -159,7 +157,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_cert_no_signer
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@high.check_cert(nil, nil, Time.now)
end
@@ -173,7 +171,7 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_check_key_no_signer
assert @almost_no.check_key(nil, nil)
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@high.check_key(nil, nil)
end
@@ -181,7 +179,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_key_wrong_key
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@almost_no.check_key(PUBLIC_CERT, ALTERNATE_KEY)
end
@@ -196,7 +194,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_root_empty_chain
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@chain.check_root [], Time.now
end
@@ -206,7 +204,7 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_check_root_invalid_signer
chain = [INVALID_SIGNER_CERT]
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@chain.check_root chain, Time.now
end
@@ -218,7 +216,7 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_check_root_not_self_signed
chain = [INVALID_ISSUER_CERT]
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@chain.check_root chain, Time.now
end
@@ -228,7 +226,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_root_no_chain
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@chain.check_root nil, Time.now
end
@@ -248,7 +246,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_trust_empty_chain
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@chain.check_trust [], @digest, @trust_dir
end
@@ -258,7 +256,7 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_check_trust_mismatch
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@high.check_trust [WRONG_KEY_CERT], @digest, @trust_dir
end
@@ -267,7 +265,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_trust_no_chain
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@chain.check_trust nil, @digest, @trust_dir
end
@@ -275,7 +273,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_trust_no_trust
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@high.check_trust [PUBLIC_CERT], @digest, @trust_dir
end
@@ -283,7 +281,7 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_trust_no_trust_child
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@high.check_trust [PUBLIC_CERT, CHILD_CERT], @digest, @trust_dir
end
@@ -317,7 +315,7 @@ class TestGemSecurityPolicy < Gem::TestCase
_, signatures = dummy_signatures
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@almost_no.verify [PUBLIC_CERT], nil, {}, signatures
end
@@ -329,7 +327,7 @@ class TestGemSecurityPolicy < Gem::TestCase
_, signatures = dummy_signatures
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@no.verify [PUBLIC_CERT], nil, {}, signatures
end
@@ -347,7 +345,7 @@ class TestGemSecurityPolicy < Gem::TestCase
assert_match "WARNING: some_gem is not signed\n", @ui.error
- assert_raises Gem::Security::Exception do
+ assert_raise Gem::Security::Exception do
@high.verify [PUBLIC_CERT], nil, digests, {}
end
end
@@ -372,7 +370,7 @@ class TestGemSecurityPolicy < Gem::TestCase
signatures[1] = PRIVATE_KEY.sign @digest.new, data.digest
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@almost_no.verify [PUBLIC_CERT], nil, digests, signatures
end
@@ -389,7 +387,7 @@ class TestGemSecurityPolicy < Gem::TestCase
assert_equal "WARNING: email:nobody@example is not trusted for some_gem\n",
@ui.error
- assert_raises Gem::Security::Exception do
+ assert_raise Gem::Security::Exception do
@medium.verify [PUBLIC_CERT], nil, digests, signatures
end
end
@@ -397,16 +395,14 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_verify_wrong_digest_type
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
- sha512 = OpenSSL::Digest::SHA512
-
- data = sha512.new
+ data = OpenSSL::Digest.new('SHA512')
data << 'hello'
digests = { 'SHA512' => { 0 => data } }
- signature = PRIVATE_KEY.sign sha512.new, data.digest
+ signature = PRIVATE_KEY.sign 'sha512', data.digest
signatures = { 0 => signature }
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@almost_no.verify [PUBLIC_CERT], nil, digests, signatures
end
@@ -482,7 +478,7 @@ class TestGemSecurityPolicy < Gem::TestCase
def s.full_name() 'metadata.gz' end
digests = package.digest s
- digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.new 'hello'
+ digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.hexdigest 'hello'
metadata_gz_digest = digests[Gem::Security::DIGEST_NAME]['metadata.gz']
@@ -490,7 +486,7 @@ class TestGemSecurityPolicy < Gem::TestCase
signatures['metadata.gz'] =
PRIVATE_KEY.sign @digest.new, metadata_gz_digest.digest
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@high.verify_signatures @spec, digests, signatures
end
@@ -511,9 +507,9 @@ class TestGemSecurityPolicy < Gem::TestCase
def s.full_name() 'metadata.gz' end
digests = package.digest s
- digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.new 'hello'
+ digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.hexdigest 'hello'
- assert_raises Gem::Security::Exception do
+ assert_raise Gem::Security::Exception do
@high.verify_signatures @spec, digests, {}
end
end
@@ -536,5 +532,4 @@ class TestGemSecurityPolicy < Gem::TestCase
return digests, signatures
end
-
-end if defined?(OpenSSL::SSL)
+end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_gem_security_signer.rb b/test/rubygems/test_gem_security_signer.rb
index 08e74e6276..7bd6510b50 100644
--- a/test/rubygems/test_gem_security_signer.rb
+++ b/test/rubygems/test_gem_security_signer.rb
@@ -1,12 +1,11 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
-unless defined?(OpenSSL::SSL)
+unless Gem::HAVE_OPENSSL
warn 'Skipping Gem::Security::Signer tests. openssl not found.'
end
class TestGemSecuritySigner < Gem::TestCase
-
ALTERNATE_KEY = load_key 'alternate'
CHILD_KEY = load_key 'child'
GRANDCHILD_KEY = load_key 'grandchild'
@@ -37,12 +36,12 @@ class TestGemSecuritySigner < Gem::TestCase
def test_initialize_cert_chain_mixed
signer = Gem::Security::Signer.new nil, [@cert_file, CHILD_CERT]
- assert_equal [PUBLIC_CERT, CHILD_CERT].map { |c| c.to_pem },
- signer.cert_chain.map { |c| c.to_pem }
+ assert_equal [PUBLIC_CERT, CHILD_CERT].map {|c| c.to_pem },
+ signer.cert_chain.map {|c| c.to_pem }
end
def test_initialize_cert_chain_invalid
- assert_raises OpenSSL::X509::CertificateError do
+ assert_raise OpenSSL::X509::CertificateError do
Gem::Security::Signer.new nil, ['garbage']
end
end
@@ -50,8 +49,8 @@ class TestGemSecuritySigner < Gem::TestCase
def test_initialize_cert_chain_path
signer = Gem::Security::Signer.new nil, [@cert_file]
- assert_equal [PUBLIC_CERT].map { |c| c.to_pem },
- signer.cert_chain.map { |c| c.to_pem }
+ assert_equal [PUBLIC_CERT].map {|c| c.to_pem },
+ signer.cert_chain.map {|c| c.to_pem }
end
def test_initialize_default
@@ -66,7 +65,7 @@ class TestGemSecuritySigner < Gem::TestCase
signer = Gem::Security::Signer.new nil, nil
assert_equal PRIVATE_KEY.to_pem, signer.key.to_pem
- assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map { |c| c.to_pem }
+ assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map {|c| c.to_pem }
end
def test_initialize_key_path
@@ -100,7 +99,7 @@ class TestGemSecuritySigner < Gem::TestCase
signer.load_cert_chain
assert_equal [PUBLIC_CERT.to_pem, CHILD_CERT.to_pem],
- signer.cert_chain.map { |c| c.to_pem }
+ signer.cert_chain.map {|c| c.to_pem }
end
def test_load_cert_chain_broken
@@ -112,7 +111,7 @@ class TestGemSecuritySigner < Gem::TestCase
signer.load_cert_chain
assert_equal [CHILD_CERT.to_pem, GRANDCHILD_CERT.to_pem],
- signer.cert_chain.map { |c| c.to_pem }
+ signer.cert_chain.map {|c| c.to_pem }
end
def test_sign
@@ -135,7 +134,7 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
def test_sign_expired
signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT]
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
signer.sign 'hello'
end
@@ -143,7 +142,7 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
end
def test_sign_expired_auto_update
- skip if Gem.java_platform?
+ pend if Gem.java_platform?
FileUtils.mkdir_p File.join(Gem.user_home, '.gem'), :mode => 0700
private_key_path = File.join(Gem.user_home, '.gem', 'gem-private_key.pem')
@@ -166,7 +165,7 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
expired_path =
File.join Gem.user_home, '.gem', "gem-public_cert.pem.expired.#{expiry}"
- assert_path_exists expired_path
+ assert_path_exist expired_path
assert_equal EXPIRED_CERT.to_pem, File.read(expired_path)
end
@@ -187,11 +186,11 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT]
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
signer.sign 'hello'
end
- assert_match %r%certificate /CN=nobody/DC=example not valid%, e.message
+ assert_match %r{certificate /CN=nobody/DC=example not valid}, e.message
end
def test_sign_no_key
@@ -203,7 +202,7 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
def test_sign_wrong_key
signer = Gem::Security::Signer.new ALTERNATE_KEY, [PUBLIC_CERT]
- assert_raises Gem::Security::Exception do
+ assert_raise Gem::Security::Exception do
signer.sign 'hello'
end
end
@@ -211,9 +210,8 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
def test_sign_no_certs
signer = Gem::Security::Signer.new ALTERNATE_KEY, []
- assert_raises Gem::Security::Exception do
+ assert_raise Gem::Security::Exception do
signer.sign 'hello'
end
end
-
-end if defined?(OpenSSL::SSL)
+end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_gem_security_trust_dir.rb b/test/rubygems/test_gem_security_trust_dir.rb
index f2b7b006dd..fc88c84865 100644
--- a/test/rubygems/test_gem_security_trust_dir.rb
+++ b/test/rubygems/test_gem_security_trust_dir.rb
@@ -1,12 +1,11 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
-unless defined?(OpenSSL::SSL)
+unless Gem::HAVE_OPENSSL
warn 'Skipping Gem::Security::TrustDir tests. openssl not found.'
end
class TestGemSecurityTrustDir < Gem::TestCase
-
CHILD_CERT = load_cert 'child'
def setup
@@ -18,7 +17,7 @@ class TestGemSecurityTrustDir < Gem::TestCase
end
def test_cert_path
- digest = Gem::Security::DIGEST_ALGORITHM.hexdigest PUBLIC_CERT.subject.to_s
+ digest = OpenSSL::Digest.hexdigest Gem::Security::DIGEST_NAME, PUBLIC_CERT.subject.to_s
expected = File.join @dest_dir, "cert-#{digest}.pem"
@@ -42,7 +41,7 @@ class TestGemSecurityTrustDir < Gem::TestCase
end
def test_name_path
- digest = Gem::Security::DIGEST_ALGORITHM.hexdigest PUBLIC_CERT.subject.to_s
+ digest = OpenSSL::Digest.hexdigest Gem::Security::DIGEST_NAME, PUBLIC_CERT.subject.to_s
expected = File.join @dest_dir, "cert-#{digest}.pem"
@@ -54,7 +53,7 @@ class TestGemSecurityTrustDir < Gem::TestCase
trusted = @trust_dir.cert_path PUBLIC_CERT
- assert_path_exists trusted
+ assert_path_exist trusted
mask = 0100600 & (~File.umask)
@@ -64,11 +63,11 @@ class TestGemSecurityTrustDir < Gem::TestCase
end
def test_verify
- refute_path_exists @dest_dir
+ assert_path_not_exist @dest_dir
@trust_dir.verify
- assert_path_exists @dest_dir
+ assert_path_exist @dest_dir
mask = 040700 & (~File.umask)
mask |= 0200000 if /aix/ =~ RUBY_PLATFORM
@@ -79,7 +78,7 @@ class TestGemSecurityTrustDir < Gem::TestCase
def test_verify_file
FileUtils.touch @dest_dir
- e = assert_raises Gem::Security::Exception do
+ e = assert_raise Gem::Security::Exception do
@trust_dir.verify
end
@@ -96,5 +95,4 @@ class TestGemSecurityTrustDir < Gem::TestCase
assert_equal mask, File.stat(@dest_dir).mode unless win_platform?
end
-
-end if defined?(OpenSSL::SSL)
+end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_gem_server.rb b/test/rubygems/test_gem_server.rb
index ca9ba4bf9c..f6aa99fb02 100644
--- a/test/rubygems/test_gem_server.rb
+++ b/test/rubygems/test_gem_server.rb
@@ -1,16 +1,13 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/server'
require 'stringio'
class Gem::Server
-
attr_reader :server
-
end
class TestGemServer < Gem::TestCase
-
def process_based_port
0
end
@@ -88,7 +85,7 @@ class TestGemServer < Gem::TestCase
end
assert_equal 200, @res.status, @res.body
- assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_match %r{ \d\d:\d\d:\d\d }, @res['date']
assert_equal 'application/octet-stream', @res['content-type']
assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]],
Marshal.load(@res.body)
@@ -127,7 +124,7 @@ class TestGemServer < Gem::TestCase
end
assert_equal 200, @res.status, @res.body
- assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_match %r{ \d\d:\d\d:\d\d }, @res['date']
assert_equal 'application/x-gzip', @res['content-type']
assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]],
Marshal.load(Gem::Util.gunzip(@res.body))
@@ -136,7 +133,7 @@ class TestGemServer < Gem::TestCase
def test_listen
util_listen
- capture_io do
+ capture_output do
@server.listen
end
@@ -146,7 +143,7 @@ class TestGemServer < Gem::TestCase
def test_listen_addresses
util_listen
- capture_io do
+ capture_output do
@server.listen %w[a b]
end
@@ -162,7 +159,7 @@ class TestGemServer < Gem::TestCase
end
assert_equal 200, @res.status, @res.body
- assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_match %r{ \d\d:\d\d:\d\d }, @res['date']
assert_equal 'application/octet-stream', @res['content-type']
assert_equal [['a', v('3.a'), Gem::Platform::RUBY]],
Marshal.load(@res.body)
@@ -177,7 +174,7 @@ class TestGemServer < Gem::TestCase
end
assert_equal 200, @res.status, @res.body
- assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_match %r{ \d\d:\d\d:\d\d }, @res['date']
assert_equal 'application/x-gzip', @res['content-type']
assert_equal [['a', v('3.a'), Gem::Platform::RUBY]],
Marshal.load(Gem::Util.gunzip(@res.body))
@@ -223,7 +220,7 @@ class TestGemServer < Gem::TestCase
@server.quick @req, @res
assert_equal 404, @res.status, @res.body
- assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_match %r{ \d\d:\d\d:\d\d }, @res['date']
assert_equal 'text/plain', @res['content-type']
assert_equal 'No gems found matching "z-9"', @res.body
assert_equal 404, @res.status
@@ -320,7 +317,7 @@ class TestGemServer < Gem::TestCase
@server.rdoc @req, @res
assert_equal 200, @res.status, @res.body
- assert_match %r|No documentation found|, @res.body
+ assert_match %r{No documentation found}, @res.body
assert_equal 'text/html', @res['content-type']
end
@@ -331,7 +328,7 @@ class TestGemServer < Gem::TestCase
@server.root @req, @res
assert_equal 200, @res.status, @res.body
- assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_match %r{ \d\d:\d\d:\d\d }, @res['date']
assert_equal 'text/html', @res['content-type']
end
@@ -368,7 +365,7 @@ class TestGemServer < Gem::TestCase
specs_dir = File.join dir, 'specifications'
FileUtils.mkdir_p specs_dir
- open File.join(specs_dir, spec.spec_name), 'w' do |io|
+ File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
io.write spec.to_ruby
end
@@ -423,7 +420,7 @@ class TestGemServer < Gem::TestCase
specs_dir = File.join dir, 'specifications'
FileUtils.mkdir_p specs_dir
- open File.join(specs_dir, spec.spec_name), 'w' do |io|
+ File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
io.write spec.to_ruby
end
@@ -478,7 +475,7 @@ class TestGemServer < Gem::TestCase
specs_dir = File.join dir, 'specifications'
FileUtils.mkdir_p specs_dir
- open File.join(specs_dir, spec.spec_name), 'w' do |io|
+ File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
io.write spec.to_ruby
end
@@ -505,7 +502,7 @@ class TestGemServer < Gem::TestCase
specs_dir = File.join dir, 'specifications'
FileUtils.mkdir_p specs_dir
- open File.join(specs_dir, spec.spec_name), 'w' do |io|
+ File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
io.write spec.to_ruby
end
@@ -529,7 +526,7 @@ class TestGemServer < Gem::TestCase
@server.specs @req, @res
assert_equal 200, @res.status, @res.body
- assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_match %r{ \d\d:\d\d:\d\d }, @res['date']
assert_equal 'application/octet-stream', @res['content-type']
assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY],
@@ -569,7 +566,7 @@ class TestGemServer < Gem::TestCase
@server.specs @req, @res
assert_equal 200, @res.status, @res.body
- assert_match %r| \d\d:\d\d:\d\d |, @res['date']
+ assert_match %r{ \d\d:\d\d:\d\d }, @res['date']
assert_equal 'application/x-gzip', @res['content-type']
assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY],
@@ -591,7 +588,7 @@ class TestGemServer < Gem::TestCase
@server.root @req, @res
- refute_match %r|%3A%2F%2F|, @res.body
+ refute_match %r{%3A%2F%2F}, @res.body
end
def util_listen
@@ -608,5 +605,4 @@ class TestGemServer < Gem::TestCase
@server.instance_variable_set :@server, webrick
end
-
end
diff --git a/test/rubygems/test_gem_silent_ui.rb b/test/rubygems/test_gem_silent_ui.rb
index d49166ff6f..355255fb48 100644
--- a/test/rubygems/test_gem_silent_ui.rb
+++ b/test/rubygems/test_gem_silent_ui.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/user_interaction'
require 'timeout'
class TestGemSilentUI < Gem::TestCase
-
def setup
super
@sui = Gem::SilentUI.new
@@ -17,7 +16,7 @@ class TestGemSilentUI < Gem::TestCase
def test_ask
value = nil
- out, err = capture_io do
+ out, err = capture_output do
use_ui @sui do
value = @sui.ask 'Problem?'
end
@@ -31,7 +30,7 @@ class TestGemSilentUI < Gem::TestCase
def test_ask_for_password
value = nil
- out, err = capture_io do
+ out, err = capture_output do
use_ui @sui do
value = @sui.ask_for_password 'Problem?'
end
@@ -45,9 +44,9 @@ class TestGemSilentUI < Gem::TestCase
def test_ask_yes_no
value = nil
- out, err = capture_io do
+ out, err = capture_output do
use_ui @sui do
- assert_raises(Gem::OperationNotSupportedError) do
+ assert_raise(Gem::OperationNotSupportedError) do
@sui.ask_yes_no 'Problem?'
end
end
@@ -56,7 +55,7 @@ class TestGemSilentUI < Gem::TestCase
assert_empty out, 'No output'
assert_empty err, 'No output'
- out, err = capture_io do
+ out, err = capture_output do
use_ui @sui do
value = @sui.ask_yes_no 'Problem?', true
end
@@ -67,7 +66,7 @@ class TestGemSilentUI < Gem::TestCase
assert value, 'Value is true'
- out, err = capture_io do
+ out, err = capture_output do
use_ui @sui do
value = @sui.ask_yes_no 'Problem?', false
end
@@ -81,7 +80,7 @@ class TestGemSilentUI < Gem::TestCase
def test_choose_from_list
value = nil
- out, err = capture_io do
+ out, err = capture_output do
use_ui @sui do
value = @sui.choose_from_list 'Problem?', %w[yes no]
end
@@ -94,7 +93,7 @@ class TestGemSilentUI < Gem::TestCase
end
def test_progress_reporter
- out, err = capture_io do
+ out, err = capture_output do
use_ui @sui do
@sui.progress_reporter 10, 'hi'
end
@@ -105,7 +104,7 @@ class TestGemSilentUI < Gem::TestCase
end
def test_download_reporter
- out, err = capture_io do
+ out, err = capture_output do
use_ui @sui do
@sui.download_reporter.fetch 'a.gem', 1024
end
@@ -114,5 +113,4 @@ class TestGemSilentUI < Gem::TestCase
assert_empty out, 'No output'
assert_empty err, 'No output'
end
-
end
diff --git a/test/rubygems/test_gem_source.rb b/test/rubygems/test_gem_source.rb
index 30b45ea267..24312626f4 100644
--- a/test/rubygems/test_gem_source.rb
+++ b/test/rubygems/test_gem_source.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/source'
require 'rubygems/indexer'
class TestGemSource < Gem::TestCase
-
def tuple(*args)
Gem::NameTuple.new(*args)
end
@@ -23,7 +22,7 @@ class TestGemSource < Gem::TestCase
end
def test_initialize_invalid_uri
- assert_raises URI::InvalidURIError do
+ assert_raise URI::InvalidURIError do
Gem::Source.new 'git@example:a.git'
end
end
@@ -45,9 +44,9 @@ class TestGemSource < Gem::TestCase
def test_dependency_resolver_set_bundler_api
response = Net::HTTPResponse.new '1.1', 200, 'OK'
- response.uri = URI('http://example') if response.respond_to? :uri
+ response.uri = URI('http://example')
- @fetcher.data["#{@gem_repo}api/v1/dependencies"] = response
+ @fetcher.data[@gem_repo] = response
set = @source.dependency_resolver_set
@@ -55,8 +54,6 @@ class TestGemSource < Gem::TestCase
end
def test_dependency_resolver_set_file_uri
- skip 'install builder gem' unless defined? Builder::XChar
-
Gem::Indexer.new(@tempdir).generate_index
source = Gem::Source.new "file://#{@tempdir}/"
@@ -125,7 +122,7 @@ class TestGemSource < Gem::TestCase
end
def test_load_specs
- released = @source.load_specs(:released).map { |spec| spec.full_name }
+ released = @source.load_specs(:released).map {|spec| spec.full_name }
assert_equal %W[a-2 a-1 b-2], released
cache_dir = File.join Gem.spec_cache_dir, 'gems.example.com%80'
@@ -188,7 +185,7 @@ class TestGemSource < Gem::TestCase
def test_load_specs_from_unavailable_uri
src = Gem::Source.new("http://not-there.nothing")
- assert_raises Gem::RemoteFetcher::FetchError do
+ assert_raise Gem::RemoteFetcher::FetchError do
src.load_specs :latest
end
end
@@ -199,30 +196,30 @@ class TestGemSource < Gem::TestCase
installed = Gem::Source::Installed.new
local = Gem::Source::Local.new
- assert_equal(0, remote. <=>(remote), 'remote <=> remote')
+ assert_equal(0, remote.<=>(remote), 'remote <=> remote')
- assert_equal(-1, remote. <=>(specific), 'remote <=> specific')
- assert_equal(1, specific. <=>(remote), 'specific <=> remote')
+ assert_equal(-1, remote.<=>(specific), 'remote <=> specific')
+ assert_equal(1, specific.<=>(remote), 'specific <=> remote')
- assert_equal(-1, remote. <=>(local), 'remote <=> local')
- assert_equal(1, local. <=>(remote), 'local <=> remote')
+ assert_equal(-1, remote.<=>(local), 'remote <=> local')
+ assert_equal(1, local.<=>(remote), 'local <=> remote')
- assert_equal(-1, remote. <=>(installed), 'remote <=> installed')
- assert_equal(1, installed.<=>(remote), 'installed <=> remote')
+ assert_equal(-1, remote.<=>(installed), 'remote <=> installed')
+ assert_equal(1, installed.<=>(remote), 'installed <=> remote')
no_uri = @source.dup
no_uri.instance_variable_set :@uri, nil
- assert_equal(-1, remote. <=>(no_uri), 'remote <=> no_uri')
+ assert_equal(-1, remote.<=>(no_uri), 'remote <=> no_uri')
end
def test_spaceship_order_is_preserved_when_uri_differs
sourceA = Gem::Source.new "http://example.com/a"
sourceB = Gem::Source.new "http://example.com/b"
- assert_equal(0, sourceA. <=>(sourceA), 'sourceA <=> sourceA')
- assert_equal(1, sourceA. <=>(sourceB), 'sourceA <=> sourceB')
- assert_equal(1, sourceB. <=>(sourceA), 'sourceB <=> sourceA')
+ assert_equal(0, sourceA.<=>(sourceA), 'sourceA <=> sourceA')
+ assert_equal(1, sourceA.<=>(sourceB), 'sourceA <=> sourceB')
+ assert_equal(1, sourceB.<=>(sourceA), 'sourceB <=> sourceA')
end
def test_update_cache_eh
@@ -243,10 +240,14 @@ class TestGemSource < Gem::TestCase
refute rubygems_source.typo_squatting?("rubysertgems.org")
end
+ def test_typo_squatting_false_positive
+ rubygems_source = Gem::Source.new("https://rubygems.org")
+ refute rubygems_source.typo_squatting?("rubygems.org")
+ end
+
def test_typo_squatting_custom_distance_threshold
rubygems_source = Gem::Source.new("https://rubgems.org")
distance_threshold = 5
assert rubygems_source.typo_squatting?("rubysertgems.org", distance_threshold)
end
-
end
diff --git a/test/rubygems/test_gem_source_fetch_problem.rb b/test/rubygems/test_gem_source_fetch_problem.rb
index 65b182890a..816407781d 100644
--- a/test/rubygems/test_gem_source_fetch_problem.rb
+++ b/test/rubygems/test_gem_source_fetch_problem.rb
@@ -1,15 +1,14 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemSourceFetchProblem < Gem::TestCase
-
def test_exception
source = Gem::Source.new @gem_repo
error = RuntimeError.new 'test'
sf = Gem::SourceFetchProblem.new source, error
- e = assert_raises RuntimeError do
+ e = assert_raise RuntimeError do
raise sf
end
@@ -25,4 +24,13 @@ class TestGemSourceFetchProblem < Gem::TestCase
refute_match sf.wordy, 'secret'
end
+ def test_source_password_no_redacted
+ source = Gem::Source.new 'https://username:secret@gemsource.com'
+ error = RuntimeError.new 'test'
+
+ sf = Gem::SourceFetchProblem.new source, error
+ sf.wordy
+
+ assert_match 'secret', source.uri.to_s
+ end
end
diff --git a/test/rubygems/test_gem_source_git.rb b/test/rubygems/test_gem_source_git.rb
index 6d7b6b0383..73ed8dd2ef 100644
--- a/test/rubygems/test_gem_source_git.rb
+++ b/test/rubygems/test_gem_source_git.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/source'
class TestGemSourceGit < Gem::TestCase
-
def setup
super
@@ -25,7 +24,7 @@ class TestGemSourceGit < Gem::TestCase
def test_checkout
@source.checkout
- assert_path_exists File.join @source.install_dir, 'a.gemspec'
+ assert_path_exist File.join @source.install_dir, 'a.gemspec'
end
def test_checkout_master
@@ -40,7 +39,7 @@ class TestGemSourceGit < Gem::TestCase
@source.checkout
- assert_path_exists File.join @source.install_dir, 'b.gemspec'
+ assert_path_exist File.join @source.install_dir, 'b.gemspec'
end
def test_checkout_local
@@ -50,7 +49,7 @@ class TestGemSourceGit < Gem::TestCase
install_dir = File.join Gem.dir, 'bundler', 'gems', "a-#{@head[0..11]}"
- refute_path_exists File.join install_dir, 'a.gemspec'
+ assert_path_not_exist File.join install_dir, 'a.gemspec'
end
def test_checkout_local_cached
@@ -60,35 +59,31 @@ class TestGemSourceGit < Gem::TestCase
@source.checkout
- assert_path_exists File.join @source.install_dir, 'a.gemspec'
+ assert_path_exist File.join @source.install_dir, 'a.gemspec'
end
def test_checkout_submodules
- # We need to allow to checkout submodules with file:// protocol
- # CVE-2022-39253
- # https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
- system(@git, *%W[config --global protocol.file.allow always])
-
source = Gem::Source::Git.new @name, @repository, 'master', true
git_gem 'b'
Dir.chdir 'git/a' do
- Gem::Util.silent_system @git, 'submodule', '--quiet',
- 'add', File.expand_path('../b'), 'b'
+ output, status = Open3.capture2e(@git, 'submodule', '--quiet', 'add', File.expand_path('../b'), 'b')
+ assert status.success?, output
+
system @git, 'commit', '--quiet', '-m', 'add submodule b'
end
source.checkout
- assert_path_exists File.join source.install_dir, 'a.gemspec'
- assert_path_exists File.join source.install_dir, 'b/b.gemspec'
+ assert_path_exist File.join source.install_dir, 'a.gemspec'
+ assert_path_exist File.join source.install_dir, 'b/b.gemspec'
end
def test_cache
assert @source.cache
- assert_path_exists @source.repo_cache_dir
+ assert_path_exist @source.repo_cache_dir
Dir.chdir @source.repo_cache_dir do
assert_equal @head, Gem::Util.popen(@git, 'rev-parse', 'master').strip
@@ -100,7 +95,7 @@ class TestGemSourceGit < Gem::TestCase
@source.cache
- refute_path_exists @source.repo_cache_dir
+ assert_path_not_exist @source.repo_cache_dir
end
def test_dir_shortref
@@ -191,8 +186,8 @@ class TestGemSourceGit < Gem::TestCase
source.cache
- e = assert_raises Gem::Exception do
- capture_subprocess_io {source.rev_parse}
+ e = assert_raise Gem::Exception do
+ capture_subprocess_io { source.rev_parse }
end
assert_equal "unable to find reference nonexistent in #{@repository}",
@@ -213,16 +208,16 @@ class TestGemSourceGit < Gem::TestCase
installed = Gem::Source::Installed.new
vendor = Gem::Source::Vendor.new 'vendor/foo'
- assert_equal(0, git. <=>(git), 'git <=> git')
+ assert_equal(0, git.<=>(git), 'git <=> git')
- assert_equal(1, git. <=>(remote), 'git <=> remote')
- assert_equal(-1, remote. <=>(git), 'remote <=> git')
+ assert_equal(1, git.<=>(remote), 'git <=> remote')
+ assert_equal(-1, remote.<=>(git), 'remote <=> git')
- assert_equal(1, git. <=>(installed), 'git <=> installed')
- assert_equal(-1, installed.<=>(git), 'installed <=> git')
+ assert_equal(1, git.<=>(installed), 'git <=> installed')
+ assert_equal(-1, installed.<=>(git), 'installed <=> git')
- assert_equal(-1, git. <=>(vendor), 'git <=> vendor')
- assert_equal(1, vendor. <=>(git), 'vendor <=> git')
+ assert_equal(-1, git.<=>(vendor), 'git <=> vendor')
+ assert_equal(1, vendor.<=>(git), 'vendor <=> git')
end
def test_specs
@@ -245,11 +240,11 @@ class TestGemSourceGit < Gem::TestCase
specs = nil
- capture_io do
+ capture_output do
specs = source.specs
end
- assert_equal %w[a-1 b-1], specs.map { |spec| spec.full_name }
+ assert_equal %w[a-1 b-1], specs.map {|spec| spec.full_name }
a_spec = specs.shift
@@ -280,7 +275,7 @@ class TestGemSourceGit < Gem::TestCase
source = Gem::Source::Git.new @name, @repository, 'master', true
source.remote = false
- capture_io do
+ capture_output do
assert_empty source.specs
end
end
@@ -304,5 +299,4 @@ class TestGemSourceGit < Gem::TestCase
assert_equal '291c4caac7feba8bb64c297987028acb3dde6cfe',
source.uri_hash
end
-
end
diff --git a/test/rubygems/test_gem_source_installed.rb b/test/rubygems/test_gem_source_installed.rb
index b4a75d8d4f..ef9b63e611 100644
--- a/test/rubygems/test_gem_source_installed.rb
+++ b/test/rubygems/test_gem_source_installed.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/source'
class TestGemSourceInstalled < Gem::TestCase
-
def test_spaceship
a1 = quick_gem 'a', '1'
util_build_gem a1
@@ -17,20 +16,19 @@ class TestGemSourceInstalled < Gem::TestCase
assert_equal(0, installed.<=>(installed), 'installed <=> installed')
- assert_equal(-1, remote. <=>(installed), 'remote <=> installed')
+ assert_equal(-1, remote.<=>(installed), 'remote <=> installed')
assert_equal(1, installed.<=>(remote), 'installed <=> remote')
assert_equal(1, installed.<=>(local), 'installed <=> local')
- assert_equal(-1, local. <=>(installed), 'local <=> installed')
+ assert_equal(-1, local.<=>(installed), 'local <=> installed')
- assert_equal(-1, specific. <=>(installed), 'specific <=> installed')
+ assert_equal(-1, specific.<=>(installed), 'specific <=> installed')
assert_equal(1, installed.<=>(specific), 'installed <=> specific')
- assert_equal(1, git. <=>(installed), 'git <=> installed')
- assert_equal(-1, installed.<=>(git), 'installed <=> git')
+ assert_equal(1, git. <=>(installed), 'git <=> installed')
+ assert_equal(-1, installed.<=>(git), 'installed <=> git')
- assert_equal(1, vendor. <=>(installed), 'vendor <=> installed')
- assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor')
+ assert_equal(1, vendor.<=>(installed), 'vendor <=> installed')
+ assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor')
end
-
end
diff --git a/test/rubygems/test_gem_source_list.rb b/test/rubygems/test_gem_source_list.rb
index b05703f0ba..6ac5dbb2a6 100644
--- a/test/rubygems/test_gem_source_list.rb
+++ b/test/rubygems/test_gem_source_list.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
+require 'rubygems'
require 'rubygems/source_list'
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemSourceList < Gem::TestCase
-
def setup
super
@@ -115,5 +115,4 @@ class TestGemSourceList < Gem::TestCase
@sl.delete Gem::Source.new(@uri)
assert_equal @sl.sources, []
end
-
end
diff --git a/test/rubygems/test_gem_source_local.rb b/test/rubygems/test_gem_source_local.rb
index 2f796f0ed7..2d4ddbc3a4 100644
--- a/test/rubygems/test_gem_source_local.rb
+++ b/test/rubygems/test_gem_source_local.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/source'
require 'fileutils'
class TestGemSourceLocal < Gem::TestCase
-
def setup
super
@@ -73,7 +72,7 @@ class TestGemSourceLocal < Gem::TestCase
@sl.load_specs :released
- inner = [@a, @ap, @b].map { |t| t.name_tuple }.inspect
+ inner = [@a, @ap, @b].map {|t| t.name_tuple }.inspect
assert_equal "#<Gem::Source::Local specs: #{inner}>", @sl.inspect
end
@@ -93,16 +92,15 @@ class TestGemSourceLocal < Gem::TestCase
installed = Gem::Source::Installed.new
local = Gem::Source::Local.new
- assert_equal(0, local. <=>(local), 'local <=> local')
+ assert_equal(0, local.<=>(local), 'local <=> local')
- assert_equal(-1, remote. <=>(local), 'remote <=> local')
- assert_equal(1, local. <=>(remote), 'local <=> remote')
+ assert_equal(-1, remote.<=>(local), 'remote <=> local')
+ assert_equal(1, local.<=>(remote), 'local <=> remote')
- assert_equal(1, installed.<=>(local), 'installed <=> local')
- assert_equal(-1, local. <=>(installed), 'local <=> installed')
+ assert_equal(1, installed.<=>(local), 'installed <=> local')
+ assert_equal(-1, local.<=>(installed), 'local <=> installed')
- assert_equal(-1, specific. <=>(local), 'specific <=> local')
- assert_equal(1, local. <=>(specific), 'local <=> specific')
+ assert_equal(-1, specific.<=>(local), 'specific <=> local')
+ assert_equal(1, local.<=>(specific), 'local <=> specific')
end
-
end
diff --git a/test/rubygems/test_gem_source_lock.rb b/test/rubygems/test_gem_source_lock.rb
index 953941b01a..5f916cdf7f 100644
--- a/test/rubygems/test_gem_source_lock.rb
+++ b/test/rubygems/test_gem_source_lock.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemSourceLock < Gem::TestCase
-
def test_fetch_spec
spec_fetcher do |fetcher|
fetcher.spec 'a', 1
@@ -59,31 +58,31 @@ class TestGemSourceLock < Gem::TestCase
lock = Gem::Source::Lock.new git
assert_equal(1, lock.<=>(git), 'lock <=> git')
- assert_equal(-1, git .<=>(lock), 'git <=> lock')
+ assert_equal(-1, git.<=>(lock), 'git <=> lock')
end
def test_spaceship_installed
installed = Gem::Source::Installed.new
lock = Gem::Source::Lock.new installed
- assert_equal(1, lock. <=>(installed), 'lock <=> installed')
- assert_equal(-1, installed.<=>(lock), 'installed <=> lock')
+ assert_equal(1, lock.<=>(installed), 'lock <=> installed')
+ assert_equal(-1, installed.<=>(lock), 'installed <=> lock')
end
def test_spaceship_local
local = Gem::Source::Local.new
lock = Gem::Source::Lock.new local # nonsense
- assert_equal(1, lock. <=>(local), 'lock <=> local')
- assert_equal(-1, local.<=>(lock), 'local <=> lock')
+ assert_equal(1, lock.<=>(local), 'lock <=> local')
+ assert_equal(-1, local.<=>(lock), 'local <=> lock')
end
def test_spaceship_remote
remote = Gem::Source.new @gem_repo
lock = Gem::Source::Lock.new remote
- assert_equal(1, lock. <=>(remote), 'lock <=> remote')
- assert_equal(-1, remote.<=>(lock), 'remote <=> lock')
+ assert_equal(1, lock.<=>(remote), 'lock <=> remote')
+ assert_equal(-1, remote.<=>(lock), 'remote <=> lock')
end
def test_spaceship_specific_file
@@ -92,7 +91,7 @@ class TestGemSourceLock < Gem::TestCase
specific = Gem::Source::SpecificFile.new gem
lock = Gem::Source::Lock.new specific # nonsense
- assert_equal(1, lock .<=>(specific), 'lock <=> specific')
+ assert_equal(1, lock.<=>(specific), 'lock <=> specific')
assert_equal(-1, specific.<=>(lock), 'specific <=> lock')
end
@@ -100,8 +99,8 @@ class TestGemSourceLock < Gem::TestCase
vendor = Gem::Source::Vendor.new 'vendor/a'
lock = Gem::Source::Lock.new vendor
- assert_equal(1, lock. <=>(vendor), 'lock <=> vendor')
- assert_equal(-1, vendor.<=>(lock), 'vendor <=> lock')
+ assert_equal(1, lock.<=>(vendor), 'lock <=> vendor')
+ assert_equal(-1, vendor.<=>(lock), 'vendor <=> lock')
end
def test_uri
@@ -110,5 +109,4 @@ class TestGemSourceLock < Gem::TestCase
assert_equal URI(@gem_repo), lock.uri
end
-
end
diff --git a/test/rubygems/test_gem_source_specific_file.rb b/test/rubygems/test_gem_source_specific_file.rb
index 9e4ebaa9c3..72ed993a88 100644
--- a/test/rubygems/test_gem_source_specific_file.rb
+++ b/test/rubygems/test_gem_source_specific_file.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/source'
class TestGemSourceSpecificFile < Gem::TestCase
-
def setup
super
@@ -28,7 +27,7 @@ class TestGemSourceSpecificFile < Gem::TestCase
end
def test_fetch_spec_fails_on_unknown_name
- assert_raises Gem::Exception do
+ assert_raise Gem::Exception do
@sf.fetch_spec(nil)
end
end
@@ -46,16 +45,16 @@ class TestGemSourceSpecificFile < Gem::TestCase
installed = Gem::Source::Installed.new
local = Gem::Source::Local.new
- assert_equal(0, specific. <=>(specific), 'specific <=> specific')
+ assert_equal(0, specific.<=>(specific), 'specific <=> specific')
- assert_equal(-1, remote. <=>(specific), 'remote <=> specific')
- assert_equal(1, specific. <=>(remote), 'specific <=> remote')
+ assert_equal(-1, remote.<=>(specific), 'remote <=> specific')
+ assert_equal(1, specific.<=>(remote), 'specific <=> remote')
- assert_equal(-1, specific. <=>(local), 'specific <=> local')
- assert_equal(1, local. <=>(specific), 'local <=> specific')
+ assert_equal(-1, specific.<=>(local), 'specific <=> local')
+ assert_equal(1, local. <=>(specific), 'local <=> specific')
- assert_equal(-1, specific. <=>(installed), 'specific <=> installed')
- assert_equal(1, installed.<=>(specific), 'installed <=> specific')
+ assert_equal(-1, specific. <=>(installed), 'specific <=> installed')
+ assert_equal(1, installed.<=>(specific), 'installed <=> specific')
a2 = quick_gem 'a', '2'
util_build_gem a2
@@ -73,5 +72,4 @@ class TestGemSourceSpecificFile < Gem::TestCase
assert_equal(0, a1_source.<=>(a1_source), 'a1_source <=> a1_source')
assert_equal(1, a2_source.<=>(a1_source), 'a2_source <=> a1_source')
end
-
end
diff --git a/test/rubygems/test_gem_source_subpath_problem.rb b/test/rubygems/test_gem_source_subpath_problem.rb
new file mode 100644
index 0000000000..c37df39f0c
--- /dev/null
+++ b/test/rubygems/test_gem_source_subpath_problem.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+require_relative 'helper'
+require 'rubygems/source'
+
+class TestGemSourceSubpathProblem < Gem::TestCase
+ def tuple(*args)
+ Gem::NameTuple.new(*args)
+ end
+
+ def setup
+ super
+
+ @gem_repo = "http://gems.example.com/private"
+
+ spec_fetcher
+
+ @source = Gem::Source.new(@gem_repo)
+
+ util_make_gems
+ end
+
+ def test_dependency_resolver_set
+ response = Net::HTTPResponse.new '1.1', 200, 'OK'
+ response.uri = URI('http://example')
+
+ @fetcher.data["#{@gem_repo}/"] = response
+
+ set = @source.dependency_resolver_set
+
+ assert_kind_of Gem::Resolver::APISet, set
+ end
+
+ def test_fetch_spec
+ @fetcher.data["#{@gem_repo}/#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}.rz"] = Zlib::Deflate.deflate(Marshal.dump(@a1))
+
+ spec = @source.fetch_spec tuple('a', Gem::Version.new(1), 'ruby')
+ assert_equal @a1.full_name, spec.full_name
+ end
+
+ def test_load_specs
+ @fetcher.data["#{@gem_repo}/latest_specs.#{Gem.marshal_version}.gz"] = util_gzip(Marshal.dump([
+ Gem::NameTuple.new(@a1.name, @a1.version, 'ruby'),
+ Gem::NameTuple.new(@b2.name, @b2.version, 'ruby'),
+ ]))
+
+ released = @source.load_specs(:latest).map {|spec| spec.full_name }
+ assert_equal %W[a-1 b-2], released
+ end
+end
diff --git a/test/rubygems/test_gem_source_vendor.rb b/test/rubygems/test_gem_source_vendor.rb
index fafe1a1907..a5ffb0f223 100644
--- a/test/rubygems/test_gem_source_vendor.rb
+++ b/test/rubygems/test_gem_source_vendor.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/source'
class TestGemSourceVendor < Gem::TestCase
-
def test_initialize
source = Gem::Source::Vendor.new 'vendor/foo'
@@ -16,16 +15,15 @@ class TestGemSourceVendor < Gem::TestCase
git = Gem::Source::Git.new 'a', 'a', 'master'
installed = Gem::Source::Installed.new
- assert_equal(0, vendor. <=>(vendor), 'vendor <=> vendor')
+ assert_equal(0, vendor.<=>(vendor), 'vendor <=> vendor')
- assert_equal(1, vendor. <=>(remote), 'vendor <=> remote')
- assert_equal(-1, remote. <=>(vendor), 'remote <=> vendor')
+ assert_equal(1, vendor.<=>(remote), 'vendor <=> remote')
+ assert_equal(-1, remote.<=>(vendor), 'remote <=> vendor')
- assert_equal(1, vendor. <=>(git), 'vendor <=> git')
- assert_equal(-1, git. <=>(vendor), 'git <=> vendor')
+ assert_equal(1, vendor.<=>(git), 'vendor <=> git')
+ assert_equal(-1, git.<=>(vendor), 'git <=> vendor')
- assert_equal(1, vendor. <=>(installed), 'vendor <=> installed')
- assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor')
+ assert_equal(1, vendor.<=>(installed), 'vendor <=> installed')
+ assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor')
end
-
end
diff --git a/test/rubygems/test_gem_spec_fetcher.rb b/test/rubygems/test_gem_spec_fetcher.rb
index 99862ce871..afae46e120 100644
--- a/test/rubygems/test_gem_spec_fetcher.rb
+++ b/test/rubygems/test_gem_spec_fetcher.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/spec_fetcher'
class TestGemSpecFetcher < Gem::TestCase
-
def tuple(*args)
Gem::NameTuple.new(*args)
end
@@ -39,7 +38,7 @@ class TestGemSpecFetcher < Gem::TestCase
end
def test_initialize_unwritable_home_dir
- skip 'chmod not supported' if Gem.win_platform?
+ pend 'chmod not supported' if Gem.win_platform?
FileUtils.chmod 0000, Gem.user_home
@@ -173,10 +172,19 @@ class TestGemSpecFetcher < Gem::TestCase
spec_fetcher do|fetcher|
fetcher.spec 'example', 1
fetcher.spec 'other-example', 1
+ fetcher.spec 'examp', 1
end
- suggestions = @sf.suggest_gems_from_name('examplw')
+ suggestions = @sf.suggest_gems_from_name('examplw', :latest, 1)
assert_equal ['example'], suggestions
+
+ suggestions = @sf.suggest_gems_from_name('other')
+ assert_equal ['other-example'], suggestions
+
+ suggestions = @sf.suggest_gems_from_name('exam')
+ assert suggestions.any? { ['examp'] }
+ assert suggestions.any? { ['example'] }
+ assert suggestions.any? { ['other-example'] }
end
def test_suggest_gems_from_name_prerelease
@@ -313,7 +321,7 @@ class TestGemSpecFetcher < Gem::TestCase
specs, _ = @sf.available_specs(:prerelease)
expected = Gem::NameTuple.from_list \
- [['a', v('2.a'), Gem::Platform::RUBY]]
+ [['a', v('2.a'), Gem::Platform::RUBY]]
assert_equal expected, specs[@source]
end
@@ -326,5 +334,4 @@ class TestGemSpecFetcher < Gem::TestCase
assert_equal({}, specs)
assert_kind_of Gem::SourceFetchProblem, errors.first
end
-
end
diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb
index 39a483378a..bfd0db347e 100644
--- a/test/rubygems/test_gem_specification.rb
+++ b/test/rubygems/test_gem_specification.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'benchmark'
-require 'rubygems/test_case'
+require_relative 'helper'
+require 'date'
require 'pathname'
require 'stringio'
require 'rubygems/ext'
@@ -9,7 +10,6 @@ require 'rubygems/installer'
require 'rubygems/platform'
class TestGemSpecification < Gem::TestCase
-
LEGACY_YAML_SPEC = <<-EOF.freeze
--- !ruby/object:Gem::Specification
rubygems_version: "1.0"
@@ -107,8 +107,6 @@ end
end
@current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
-
- load 'rubygems/syck_hack.rb'
end
def test_self_find_active_stub_by_path
@@ -129,265 +127,241 @@ end
end
def test_self_activate_ambiguous_direct
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec("b", "1", { "c" => ">= 1" }, "lib/d#{$$}.rb")
- b2 = util_spec("b", "2", { "c" => ">= 2" }, "lib/d#{$$}.rb")
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec("b", "1", { "c" => ">= 1" }, "lib/d#{$$}.rb")
+ b2 = util_spec("b", "2", { "c" => ">= 2" }, "lib/d#{$$}.rb")
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2"
- Gem::Specification.reset
- install_specs c1, c2, b1, b2, a1
+ Gem::Specification.reset
+ install_specs c1, c2, b1, b2, a1
- a1.activate
- assert_equal %w(a-1), loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a1.activate
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w(a-1 b-2 c-2), loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_find_in_unresolved_tree_is_not_exponentiental
- save_loaded_features do
- num_of_pkg = 7
- num_of_version_per_pkg = 3
- packages = (0..num_of_pkg).map do |pkgi|
- (0..num_of_version_per_pkg).map do |pkg_version|
- deps = Hash[((pkgi + 1)..num_of_pkg).map do |deppkgi|
- ["pkg#{deppkgi}", ">= 0"]
- end]
- util_spec "pkg#{pkgi}", pkg_version.to_s, deps
- end
+ num_of_pkg = 7
+ num_of_version_per_pkg = 3
+ packages = (0..num_of_pkg).map do |pkgi|
+ (0..num_of_version_per_pkg).map do |pkg_version|
+ deps = Hash[((pkgi + 1)..num_of_pkg).map do |deppkgi|
+ ["pkg#{deppkgi}", ">= 0"]
+ end]
+ util_spec "pkg#{pkgi}", pkg_version.to_s, deps
end
- base = util_spec "pkg_base", "1", {"pkg0" => ">= 0"}
+ end
+ base = util_spec "pkg_base", "1", {"pkg0" => ">= 0"}
- Gem::Specification.reset
- install_specs(*packages.flatten.reverse)
- install_specs base
- base.activate
+ Gem::Specification.reset
+ install_specs(*packages.flatten.reverse)
+ install_specs base
+ base.activate
- tms = Benchmark.measure do
- assert_raises(LoadError) { require 'no_such_file_foo' }
- end
- assert_operator tms.total, :<=, 10
+ tms = Benchmark.measure do
+ assert_raise(LoadError) { require 'no_such_file_foo' }
end
+ assert_operator tms.total, :<=, 10
end
def test_self_activate_ambiguous_indirect
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
- c2 = util_spec "c", "2", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
+ c2 = util_spec "c", "2", nil, "lib/d#{$$}.rb"
- install_specs c1, c2, b1, b2, a1
+ install_specs c1, c2, b1, b2, a1
- a1.activate
- assert_equal %w(a-1), loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a1.activate
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w(a-1 b-2 c-2), loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_activate_ambiguous_indirect_conflict
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- a2 = util_spec "a", "2", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
- c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2
+ a1 = util_spec "a", "1", "b" => "> 0"
+ a2 = util_spec "a", "2", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
+ c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2
- install_specs c1, b1, a1, a2, c2, b2
+ install_specs c1, b1, a1, a2, c2, b2
- a2.activate
- assert_equal %w(a-2), loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a2.activate
+ assert_equal %w[a-2], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w(a-2 b-1 c-1), loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-2 b-1 c-1], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_activate_ambiguous_unrelated
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb"
- install_specs d1, c1, c2, b1, b2, a1
+ install_specs d1, c1, c2, b1, b2, a1
- a1.activate
- assert_equal %w(a-1), loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a1.activate
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w(a-1 d-1), loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
- end
+ assert_equal %w[a-1 d-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
end
def test_require_should_prefer_latest_gem_level1
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 0"
- c1 = util_spec "c", "1", nil, "lib/c#{$$}.rb" # 1st level
- c2 = util_spec "c", "2", nil, "lib/c#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 0"
+ c1 = util_spec "c", "1", nil, "lib/c#{$$}.rb" # 1st level
+ c2 = util_spec "c", "2", nil, "lib/c#{$$}.rb"
- install_specs c1, c2, b1, b2, a1
+ install_specs c1, c2, b1, b2, a1
- a1.activate
+ a1.activate
- require "c#{$$}"
+ require "c#{$$}"
- assert_equal %w(a-1 b-2 c-2), loaded_spec_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
end
def test_require_should_prefer_latest_gem_level2
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 0"
- c1 = util_spec "c", "1", "d" => ">= 0" # 1st level
- c2 = util_spec "c", "2", "d" => ">= 0"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 0"
+ c1 = util_spec "c", "1", "d" => ">= 0" # 1st level
+ c2 = util_spec "c", "2", "d" => ">= 0"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- install_specs d1, d2, c1, c2, b1, b2, a1
+ install_specs d1, d2, c1, c2, b1, b2, a1
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w(a-1 b-2 c-2 d-2), loaded_spec_names
- end
+ assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names
end
def test_require_finds_in_2nd_level_indirect
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 0"
- c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
- c2 = util_spec "c", "2", "d" => "<= 2"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 0"
+ c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
+ c2 = util_spec "c", "2", "d" => "<= 2"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
- install_specs d1, d2, d3, c1, c2, b1, b2, a1
+ install_specs d1, d2, d3, c1, c2, b1, b2, a1
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w(a-1 b-2 c-2 d-2), loaded_spec_names
- end
+ assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names
end
def test_require_should_prefer_reachable_gems
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 0"
- c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
- c2 = util_spec "c", "2", "d" => "<= 2"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
- e = util_spec "anti_d", "1", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 0"
+ c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
+ c2 = util_spec "c", "2", "d" => "<= 2"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
+ e = util_spec "anti_d", "1", nil, "lib/d#{$$}.rb"
+
+ install_specs d1, d2, d3, e, c1, c2, b1, b2, a1
- install_specs d1, d2, d3, e, c1, c2, b1, b2, a1
-
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w(a-1 b-2 c-2 d-2), loaded_spec_names
- end
+ assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names
end
def test_require_should_not_conflict
- save_loaded_features do
- base = util_spec "0", "1", "A" => ">= 1"
- a1 = util_spec "A", "1", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb"
- a2 = util_spec "A", "2", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb"
- b1 = util_spec "b", "1", {"c" => "= 1"}, "lib/d#{$$}.rb"
- b2 = util_spec "b", "2", {"c" => "= 2"}, "lib/d#{$$}.rb"
- c1 = util_spec "c", "1", {}, "lib/c.rb"
- c2 = util_spec "c", "2", {}, "lib/c.rb"
- c3 = util_spec "c", "3", {}, "lib/c.rb"
-
- install_specs c1, c2, c3, b1, b2, a1, a2, base
-
- base.activate
- assert_equal %w(0-1), loaded_spec_names
- assert_equal ["A (>= 1)"], unresolved_names
+ base = util_spec "0", "1", "A" => ">= 1"
+ a1 = util_spec "A", "1", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb"
+ a2 = util_spec "A", "2", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb"
+ b1 = util_spec "b", "1", {"c" => "= 1"}, "lib/d#{$$}.rb"
+ b2 = util_spec "b", "2", {"c" => "= 2"}, "lib/d#{$$}.rb"
+ c1 = util_spec "c", "1", {}, "lib/c.rb"
+ c2 = util_spec "c", "2", {}, "lib/c.rb"
+ c3 = util_spec "c", "3", {}, "lib/c.rb"
- require "d#{$$}"
+ install_specs c1, c2, c3, b1, b2, a1, a2, base
- assert_equal %w(0-1 A-2 b-2 c-2), loaded_spec_names
- assert_equal [], unresolved_names
- end
+ base.activate
+ assert_equal %w[0-1], loaded_spec_names
+ assert_equal ["A (>= 1)"], unresolved_names
+
+ require "d#{$$}"
+
+ assert_equal %w[0-1 A-2 b-2 c-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_inner_clonflict_in_indirect_gems
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 1", "d" => "< 3"
- c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
- c2 = util_spec "c", "2", "d" => "<= 2"
- c3 = util_spec "c", "3", "d" => "<= 3"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 1", "d" => "< 3"
+ c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
+ c2 = util_spec "c", "2", "d" => "<= 2"
+ c3 = util_spec "c", "3", "d" => "<= 3"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
+
+ install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1
- install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1
-
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_includes [%w(a-1 b-2 c-3 d-2),%w(a-1 b-2 d-2)], loaded_spec_names
- end
+ assert_includes [%w[a-1 b-2 c-3 d-2],%w[a-1 b-2 d-2]], loaded_spec_names
end
def test_inner_clonflict_in_indirect_gems_reversed
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "xc" => ">= 1" # unresolved
- b2 = util_spec "b", "2", "xc" => ">= 1", "d" => "< 3"
- c1 = util_spec "xc", "1", "d" => "<= 3" # 1st level
- c2 = util_spec "xc", "2", "d" => "<= 2"
- c3 = util_spec "xc", "3", "d" => "<= 3"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
-
- install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "xc" => ">= 1" # unresolved
+ b2 = util_spec "b", "2", "xc" => ">= 1", "d" => "< 3"
+ c1 = util_spec "xc", "1", "d" => "<= 3" # 1st level
+ c2 = util_spec "xc", "2", "d" => "<= 2"
+ c3 = util_spec "xc", "3", "d" => "<= 3"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
+
+ install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_includes [%w(a-1 b-2 d-2 xc-3), %w(a-1 b-2 d-2)], loaded_spec_names
- end
+ assert_includes [%w[a-1 b-2 d-2 xc-3], %w[a-1 b-2 d-2]], loaded_spec_names
end
##
@@ -406,7 +380,7 @@ end
c = util_spec 'c', '1.0', 'b' => '= 2.0'
install_specs b1, b2, c, a
- e = assert_raises Gem::LoadError do
+ e = assert_raise Gem::LoadError do
assert_activate nil, a, c, "b"
end
@@ -428,7 +402,7 @@ end
install_specs b1, b2, c, a
- e = assert_raises Gem::ConflictError do
+ e = assert_raise Gem::ConflictError do
assert_activate nil, a, c, "b"
end
@@ -511,41 +485,37 @@ end
install_specs b1, b2, a1
a1.activate
- save_loaded_features do
- require "b/c"
- end
+ require "b/c"
- assert_equal %w(a-1 b-1), loaded_spec_names
+ assert_equal %w[a-1 b-1], loaded_spec_names
end
def test_self_activate_via_require_wtf
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this
- b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b#{$$}.rb"
- b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b#{$$}.rb" # this
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2" # this
- d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d#{$$}.rb"
- d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d#{$$}.rb" # this
+ a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this
+ b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b#{$$}.rb"
+ b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b#{$$}.rb" # this
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2" # this
+ d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d#{$$}.rb"
+ d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d#{$$}.rb" # this
- install_specs c1, c2, b1, b2, d1, d2, a1
+ install_specs c1, c2, b1, b2, d1, d2, a1
- a1.activate
+ a1.activate
- assert_equal %w(a-1), loaded_spec_names
- assert_equal ["b (> 0)", "d (> 0)"], unresolved_names
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)", "d (> 0)"], unresolved_names
- require "b#{$$}"
+ require "b#{$$}"
- e = assert_raises Gem::LoadError do
- require "d#{$$}"
- end
+ e = assert_raise Gem::LoadError do
+ require "d#{$$}"
+ end
- assert_equal "unable to find a version of 'd' to activate", e.message
+ assert_equal "unable to find a version of 'd' to activate", e.message
- assert_equal %w(a-1 b-2 c-2), loaded_spec_names
- assert_equal ["d (> 0)"], unresolved_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ assert_equal ["d (> 0)"], unresolved_names
end
def test_self_activate_deep_unambiguous
@@ -558,7 +528,7 @@ end
install_specs c1, c2, b1, b2, a1
a1.activate
- assert_equal %w(a-1 b-1 c-1), loaded_spec_names
+ assert_equal %w[a-1 b-1 c-1], loaded_spec_names
end
def test_self_activate_loaded
@@ -673,7 +643,7 @@ end
gem "b", "= 1.0"
- assert_raises Gem::LoadError do
+ assert_raise Gem::LoadError do
gem "b", "= 2.0"
end
end
@@ -720,7 +690,7 @@ end
version
]
- actual_value = Gem::Specification.attribute_names.map { |a| a.to_s }.sort
+ actual_value = Gem::Specification.attribute_names.map {|a| a.to_s }.sort
assert_equal expected_value, actual_value
end
@@ -747,125 +717,6 @@ end
spec.specification_version
end
- def test_self_from_yaml_syck_date_bug
- # This is equivalent to (and totally valid) psych 1.0 output and
- # causes parse errors on syck.
- yaml = @a1.to_yaml
- yaml.sub!(/^date:.*/, "date: 2011-04-26 00:00:00.000000000Z")
-
- spec = with_syck do
- Gem::Specification.from_yaml yaml
- end
-
- assert_kind_of Time, @a1.date
- assert_kind_of Time, spec.date
- end
-
- def test_self_from_yaml_syck_default_key_bug
- # This is equivalent to (and totally valid) psych 1.0 output and
- # causes parse errors on syck.
- yaml = <<-YAML
---- !ruby/object:Gem::Specification
-name: posix-spawn
-version: !ruby/object:Gem::Version
- version: 0.3.6
- prerelease:
-dependencies:
-- !ruby/object:Gem::Dependency
- name: rake-compiler
- requirement: &70243867725240 !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - =
- - !ruby/object:Gem::Version
- version: 0.7.6
- type: :development
- prerelease: false
- version_requirements: *70243867725240
-platform: ruby
-files: []
-test_files: []
-bindir:
- YAML
-
- spec = with_syck do
- Gem::Specification.from_yaml yaml
- end
-
- op = spec.dependencies.first.requirement.requirements.first.first
- refute_kind_of YAML::Syck::DefaultKey, op
-
- refute_match %r%DefaultKey%, spec.to_ruby
- end
-
- def test_self_from_yaml_cleans_up_defaultkey
- yaml = <<-YAML
---- !ruby/object:Gem::Specification
-name: posix-spawn
-version: !ruby/object:Gem::Version
- version: 0.3.6
- prerelease:
-dependencies:
-- !ruby/object:Gem::Dependency
- name: rake-compiler
- requirement: &70243867725240 !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - !ruby/object:YAML::Syck::DefaultKey {}
-
- - !ruby/object:Gem::Version
- version: 0.7.6
- type: :development
- prerelease: false
- version_requirements: *70243867725240
-platform: ruby
-files: []
-test_files: []
-bindir:
- YAML
-
- spec = Gem::Specification.from_yaml yaml
-
- op = spec.dependencies.first.requirement.requirements.first.first
- refute_kind_of YAML::Syck::DefaultKey, op
-
- refute_match %r%DefaultKey%, spec.to_ruby
- end
-
- def test_self_from_yaml_cleans_up_defaultkey_from_newer_192
- yaml = <<-YAML
---- !ruby/object:Gem::Specification
-name: posix-spawn
-version: !ruby/object:Gem::Version
- version: 0.3.6
- prerelease:
-dependencies:
-- !ruby/object:Gem::Dependency
- name: rake-compiler
- requirement: &70243867725240 !ruby/object:Gem::Requirement
- none: false
- requirements:
- - - !ruby/object:Syck::DefaultKey {}
-
- - !ruby/object:Gem::Version
- version: 0.7.6
- type: :development
- prerelease: false
- version_requirements: *70243867725240
-platform: ruby
-files: []
-test_files: []
-bindir:
- YAML
-
- spec = Gem::Specification.from_yaml yaml
-
- op = spec.dependencies.first.requirement.requirements.first.first
- refute_kind_of YAML::Syck::DefaultKey, op
-
- refute_match %r%DefaultKey%, spec.to_ruby
- end
-
def test_self_from_yaml_cleans_up_Date_objects
yaml = <<-YAML
--- !ruby/object:Gem::Specification
@@ -973,7 +824,7 @@ dependencies: []
io.write @a2.to_ruby_for_cache
end
rescue Errno::EINVAL
- skip "cannot create '#{full_path}' on this platform"
+ pend "cannot create '#{full_path}' on this platform"
end
spec = Gem::Specification.load full_path
@@ -992,7 +843,7 @@ dependencies: []
io.write @a2.to_ruby_for_cache
end
rescue Errno::EINVAL
- skip "cannot create '#{full_path}' on this platform"
+ pend "cannot create '#{full_path}' on this platform"
end
spec = Gem::Specification.load full_path
@@ -1011,7 +862,7 @@ dependencies: []
io.write @a2.to_ruby_for_cache
end
rescue Errno::EINVAL
- skip "cannot create '#{full_path}' on this platform"
+ pend "cannot create '#{full_path}' on this platform"
end
spec = Gem::Specification.load full_path
@@ -1113,13 +964,13 @@ dependencies: []
install_specs @a1
assert_includes Gem::Specification.all_names, 'a-1'
- assert_includes Gem::Specification.stubs.map { |s| s.full_name }, 'a-1'
+ assert_includes Gem::Specification.stubs.map {|s| s.full_name }, 'a-1'
uninstall_gem @a1
Gem::Specification.reset
refute_includes Gem::Specification.all_names, 'a-1'
- refute_includes Gem::Specification.stubs.map { |s| s.full_name }, 'a-1'
+ refute_includes Gem::Specification.stubs.map {|s| s.full_name }, 'a-1'
end
def test_self_remove_spec_removed
@@ -1134,49 +985,39 @@ dependencies: []
Gem::Specification.reset
refute_includes Gem::Specification.all_names, 'a-1'
- refute_includes Gem::Specification.stubs.map { |s| s.full_name }, 'a-1'
+ refute_includes Gem::Specification.stubs.map {|s| s.full_name }, 'a-1'
end
- def test_self_stubs
+ def test_self_stubs_for_lazy_loading
Gem.loaded_specs.clear
Gem::Specification.class_variable_set(:@@stubs, nil)
dir_standard_specs = File.join Gem.dir, 'specifications'
- dir_default_specs = Gem.default_specifications_dir
- # Create gemspecs in three locations used in stubs
- loaded_spec = Gem::Specification.new 'a', '3'
- Gem.loaded_specs['a'] = loaded_spec
- save_gemspec 'a', '2', dir_default_specs
- save_gemspec 'a', '1', dir_standard_specs
+ save_gemspec('a-1', '1', dir_standard_specs){|s| s.name = 'a' }
+ save_gemspec('b-1', '1', dir_standard_specs){|s| s.name = 'b' }
+
+ assert_equal ['a-1'], Gem::Specification.stubs_for('a').map {|s| s.full_name }
+ assert_equal 1, Gem::Specification.class_variable_get(:@@stubs_by_name).length
+ assert_equal ['b-1'], Gem::Specification.stubs_for('b').map {|s| s.full_name }
+ assert_equal 2, Gem::Specification.class_variable_get(:@@stubs_by_name).length
- full_names = ['a-3', 'a-2', 'a-1']
- assert_equal full_names, Gem::Specification.stubs.map { |s| s.full_name }
+ assert_equal(
+ Gem::Specification.stubs_for('a').map {|s| s.object_id },
+ Gem::Specification.stubs_for('a').map {|s| s.object_id }
+ )
Gem.loaded_specs.delete 'a'
+ Gem.loaded_specs.delete 'b'
Gem::Specification.class_variable_set(:@@stubs, nil)
end
- def test_self_stubs_for
- Gem.loaded_specs.clear
- Gem::Specification.class_variable_set(:@@stubs, nil)
-
- dir_standard_specs = File.join Gem.dir, 'specifications'
- dir_default_specs = Gem.default_specifications_dir
-
- # Create gemspecs in three locations used in stubs
- loaded_spec = Gem::Specification.new 'a', '3'
- Gem.loaded_specs['a'] = loaded_spec
- save_gemspec('a-2', '2', dir_default_specs) { |s| s.name = 'a' }
- save_gemspec('a-1', '1', dir_standard_specs) { |s| s.name = 'a' }
-
- full_names = ['a-3', 'a-2', 'a-1']
+ def test_self_stubs_for_no_lazy_loading_after_all_specs_setup
+ Gem::Specification.all = [util_spec('a', '1')]
- assert_equal full_names, Gem::Specification.stubs_for('a').map { |s| s.full_name }
- assert_equal 1, Gem::Specification.class_variable_get(:@@stubs_by_name).length
+ save_gemspec('b-1', '1', File.join(Gem.dir, 'specifications')){|s| s.name = 'b' }
- Gem.loaded_specs.delete 'a'
- Gem::Specification.class_variable_set(:@@stubs, nil)
+ assert_equal [], Gem::Specification.stubs_for('b').map {|s| s.full_name }
end
def test_self_stubs_for_mult_platforms
@@ -1187,7 +1028,7 @@ dependencies: []
# create user spec
user_spec_dir = File.join Gem.user_dir, 'specifications'
- FileUtils.mkdir_p(user_spec_dir) unless Dir.exist? user_spec_dir
+ FileUtils.mkdir_p(user_spec_dir) unless Dir.exist? user_spec_dir
# dirs doesn't include user ?
Gem::Specification.dirs << user_spec_dir
@@ -1197,7 +1038,7 @@ dependencies: []
#create specs
platforms.each do |plat|
- spec = Gem::Specification.new(gem, v) { |s| s.platform = plat }
+ spec = Gem::Specification.new(gem, v) {|s| s.platform = plat }
File.open File.join(user_spec_dir, "#{gem}-#{v}-#{plat}.gemspec"), 'w' do |io|
io.write spec.to_ruby
end
@@ -1218,10 +1059,18 @@ dependencies: []
Gem.platforms = orig_platform
end
- DATA_PATH = File.expand_path "../data", __FILE__
+ def test_self_stubs_returns_only_specified_named_specs
+ dir_standard_specs = File.join Gem.dir, 'specifications'
+
+ save_gemspec('a-1', '1', dir_standard_specs){|s| s.name = 'a' }
+ save_gemspec('a-2', '2', dir_standard_specs){|s| s.name = 'a' }
+ save_gemspec('a-a', '3', dir_standard_specs){|s| s.name = 'a-a' }
+
+ assert_equal ['a-1', 'a-2'], Gem::Specification.stubs_for('a').map(&:full_name).sort
+ end
def test_handles_private_null_type
- path = File.join DATA_PATH, "null-type.gemspec.rz"
+ path = File.expand_path "../data/null-type.gemspec.rz", __FILE__
data = Marshal.load Gem::Util.inflate(Gem.read_binary(path))
@@ -1347,7 +1196,7 @@ dependencies: []
spec.instance_variable_set :@licenses, (class << (Object.new);self;end)
spec.loaded_from = '/path/to/file'
- e = assert_raises Gem::FormatException do
+ e = assert_raise Gem::FormatException do
spec.dup
end
@@ -1388,12 +1237,12 @@ dependencies: []
awesome.add_dependency :gem_name
end
- assert_equal %w[true gem_name], gem.dependencies.map { |dep| dep.name }
+ assert_equal %w[true gem_name], gem.dependencies.map {|dep| dep.name }
end
def test_add_dependency_from_existing_dependency
dep = Gem::Dependency.new("existing_dep", Gem::Requirement.new('> 1'), :runtime)
- spec = Gem::Specification.new { |s| s.add_dependency dep }
+ spec = Gem::Specification.new {|s| s.add_dependency dep }
assert_equal dep, spec.dependencies.first
end
@@ -1402,7 +1251,7 @@ dependencies: []
awesome.add_development_dependency "monkey"
end
- monkey = gem.dependencies.detect { |d| d.name == "monkey" }
+ monkey = gem.dependencies.detect {|d| d.name == "monkey" }
assert_equal(:development, monkey.type)
end
@@ -1453,7 +1302,7 @@ dependencies: []
end
def test_build_args
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
assert_empty @ext.build_args
@@ -1472,10 +1321,10 @@ dependencies: []
end
def test_build_extensions
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
- refute_path_exists @ext.extension_dir, 'sanity check'
+ assert_path_not_exist @ext.extension_dir, 'sanity check'
refute_empty @ext.extensions, 'sanity check'
extconf_rb = File.join @ext.gem_dir, @ext.extensions.first
@@ -1493,14 +1342,14 @@ dependencies: []
@ext.build_extensions
- assert_path_exists @ext.extension_dir
+ assert_path_exist @ext.extension_dir
end
def test_default_spec_stub_is_marked_default
default = new_default_spec 'default', 2
install_default_gems default
- stub = Gem::Specification.stubs.find { |s| s.name == 'default' }
+ stub = Gem::Specification.stubs.find {|s| s.name == 'default' }
assert_predicate stub, :default_gem?
stub = Gem::Specification.find_all_by_name('default').first
@@ -1508,7 +1357,7 @@ dependencies: []
end
def test_build_extensions_built
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
refute_empty @ext.extensions, 'sanity check'
@@ -1522,7 +1371,7 @@ dependencies: []
@ext.build_extensions
gem_make_out = File.join @ext.extension_dir, 'gem_make.out'
- refute_path_exists gem_make_out
+ assert_path_not_exist gem_make_out
end
def test_build_extensions_default_gem
@@ -1543,25 +1392,25 @@ dependencies: []
spec.build_extensions
- refute_path_exists spec.extension_dir
+ assert_path_not_exist spec.extension_dir
end
def test_build_extensions_error
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
refute_empty @ext.extensions, 'sanity check'
- assert_raises Gem::Ext::BuildError do
+ assert_raise Gem::Ext::BuildError do
@ext.build_extensions
end
end
def test_build_extensions_extensions_dir_unwritable
- skip 'chmod not supported' if Gem.win_platform?
- skip 'skipped in root privilege' if Process.uid.zero?
+ pend 'chmod not supported' if Gem.win_platform?
+ pend 'skipped in root privilege' if Process.uid.zero?
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
refute_empty @ext.extensions, 'sanity check'
@@ -1584,7 +1433,7 @@ dependencies: []
FileUtils.chmod 0555, File.join(@ext.base_dir, 'extensions')
@ext.build_extensions
- refute_path_exists @ext.extension_dir
+ assert_path_not_exist @ext.extension_dir
ensure
unless ($DEBUG or win_platform? or Process.uid.zero? or Gem.java_platform?)
FileUtils.chmod 0755, File.join(@ext.base_dir, 'extensions')
@@ -1593,8 +1442,8 @@ dependencies: []
end
def test_build_extensions_no_extensions_dir_unwritable
- skip 'chmod not supported' if Gem.win_platform?
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend 'chmod not supported' if Gem.win_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
refute_empty @ext.extensions, 'sanity check'
@@ -1618,36 +1467,22 @@ dependencies: []
@ext.build_extensions
gem_make_out = File.join @ext.extension_dir, 'gem_make.out'
- refute_path_exists gem_make_out
+ assert_path_not_exist gem_make_out
ensure
FileUtils.chmod 0755, @gemhome
end
def test_build_extensions_none
- refute_path_exists @a1.extension_dir, 'sanity check'
+ assert_path_not_exist @a1.extension_dir, 'sanity check'
assert_empty @a1.extensions, 'sanity check'
@a1.build_extensions
- refute_path_exists @a1.extension_dir
- end
-
- def test_build_extensions_old
- skip "extensions don't quite work on jruby" if Gem.java_platform?
- ext_spec
-
- refute_empty @ext.extensions, 'sanity check'
-
- @ext.installed_by_version = v(0)
-
- @ext.build_extensions
-
- gem_make_out = File.join @ext.extension_dir, 'gem_make.out'
- refute_path_exists gem_make_out
+ assert_path_not_exist @a1.extension_dir
end
def test_build_extensions_preview
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
extconf_rb = File.join @ext.gem_dir, @ext.extensions.first
@@ -1670,7 +1505,7 @@ dependencies: []
@ext.build_extensions
gem_make_out = File.join @ext.extension_dir, 'gem_make.out'
- assert_path_exists gem_make_out
+ assert_path_exist gem_make_out
end
def test_contains_requirable_file_eh
@@ -1682,10 +1517,10 @@ dependencies: []
end
def test_contains_requirable_file_eh_extension
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
- _, err = capture_io do
+ _, err = capture_output do
refute @ext.contains_requirable_file? 'nonexistent'
end
@@ -1698,7 +1533,7 @@ dependencies: []
def test_contains_requirable_file_eh_extension_java_platform
ext_spec(platform: Gem::Platform.new("java"))
- _, err = capture_io do
+ _, err = capture_output do
refute @ext.contains_requirable_file? 'nonexistent'
end
@@ -1720,7 +1555,7 @@ dependencies: []
end
def test_date_equals_string_bad
- assert_raises Gem::InvalidSpecificationException do
+ assert_raise Gem::InvalidSpecificationException do
@a1.date = '9/11/2003'
end
end
@@ -1855,7 +1690,6 @@ dependencies: []
RbConfig::CONFIG['ENABLE_SHARED'], 'no'
class << Gem
-
alias orig_default_ext_dir_for default_ext_dir_for
remove_method :default_ext_dir_for
@@ -1863,7 +1697,6 @@ dependencies: []
def Gem.default_ext_dir_for(base_dir)
'elsewhere'
end
-
end
ext_spec
@@ -1877,20 +1710,18 @@ dependencies: []
RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared
class << Gem
-
remove_method :default_ext_dir_for
alias default_ext_dir_for orig_default_ext_dir_for
-
end
end
def test_files
- @a1.files = %w(files bin/common)
- @a1.test_files = %w(test_files bin/common)
- @a1.executables = %w(executables common)
- @a1.extra_rdoc_files = %w(extra_rdoc_files bin/common)
- @a1.extensions = %w(extensions bin/common)
+ @a1.files = %w[files bin/common]
+ @a1.test_files = %w[test_files bin/common]
+ @a1.executables = %w[executables common]
+ @a1.extra_rdoc_files = %w[extra_rdoc_files bin/common]
+ @a1.extensions = %w[extensions bin/common]
expected = %w[
bin/common
@@ -1904,11 +1735,11 @@ dependencies: []
end
def test_files_append
- @a1.files = %w(files bin/common)
- @a1.test_files = %w(test_files bin/common)
- @a1.executables = %w(executables common)
- @a1.extra_rdoc_files = %w(extra_rdoc_files bin/common)
- @a1.extensions = %w(extensions bin/common)
+ @a1.files = %w[files bin/common]
+ @a1.test_files = %w[test_files bin/common]
+ @a1.executables = %w[executables common]
+ @a1.extra_rdoc_files = %w[extra_rdoc_files bin/common]
+ @a1.extensions = %w[extensions bin/common]
expected = %w[
bin/common
@@ -2022,7 +1853,7 @@ dependencies: []
test_cases = {
'i386-mswin32' => 'a-1-x86-mswin32-60',
'i386-mswin32_80' => 'a-1-x86-mswin32-80',
- 'i386-mingw32' => 'a-1-x86-mingw32'
+ 'i386-mingw32' => 'a-1-x86-mingw32',
}
test_cases.each do |arch, expected|
@@ -2171,11 +2002,9 @@ dependencies: []
def test_require_paths_default_ext_dir_for
class << Gem
-
send :alias_method, :orig_default_ext_dir_for, :default_ext_dir_for
remove_method :default_ext_dir_for
-
end
def Gem.default_ext_dir_for(base_dir)
@@ -2191,11 +2020,9 @@ dependencies: []
end
ensure
class << Gem
-
send :remove_method, :default_ext_dir_for
send :alias_method, :default_ext_dir_for, :orig_default_ext_dir_for
send :remove_method, :orig_default_ext_dir_for
-
end
end
@@ -2291,43 +2118,39 @@ dependencies: []
end
def test_require_already_activated
- save_loaded_features do
- a1 = util_spec "a", "1", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", nil, "lib/d#{$$}.rb"
- install_specs a1 # , a2, b1, b2, c1, c2
+ install_specs a1 # , a2, b1, b2, c1, c2
- a1.activate
- assert_equal %w(a-1), loaded_spec_names
- assert_equal [], unresolved_names
+ a1.activate
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal [], unresolved_names
- assert require "d#{$$}"
+ assert require "d#{$$}"
- assert_equal %w(a-1), loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_require_already_activated_indirect_conflict
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- a2 = util_spec "a", "2", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
- c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2
+ a1 = util_spec "a", "1", "b" => "> 0"
+ a2 = util_spec "a", "2", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
+ c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2
- install_specs c1, b1, a1, a2, c2, b2
+ install_specs c1, b1, a1, a2, c2, b2
- a1.activate
- c1.activate
- assert_equal %w(a-1 c-1), loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a1.activate
+ c1.activate
+ assert_equal %w[a-1 c-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- assert require "d#{$$}"
+ assert require "d#{$$}"
- assert_equal %w(a-1 c-1), loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
- end
+ assert_equal %w[a-1 c-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
end
def test_requirements
@@ -2348,7 +2171,7 @@ dependencies: []
expected = %w[rake jabber4r pqa]
- assert_equal expected, @c1.runtime_dependencies.map { |d| d.name }
+ assert_equal expected, @c1.runtime_dependencies.map {|d| d.name }
end
def test_spaceship_name
@@ -2458,6 +2281,9 @@ end
end
def test_to_ruby_with_rsa_key
+ require 'rubygems/openssl'
+ pend 'openssl is missing' unless defined?(OpenSSL::PKey::RSA)
+
rsa_key = OpenSSL::PKey::RSA.new(2048)
@a2.signing_key = rsa_key
ruby_code = @a2.to_ruby
@@ -2640,7 +2466,7 @@ end
def test_to_yaml
yaml_str = @a1.to_yaml
- refute_match '!!null', yaml_str
+ refute_match %r{!!null}, yaml_str
same_spec = Gem::Specification.from_yaml(yaml_str)
@@ -2661,7 +2487,7 @@ end
def test_to_yaml_platform_empty_string
@a1.instance_variable_set :@original_platform, ''
- assert_match %r|^platform: ruby$|, @a1.to_yaml
+ assert_match %r{^platform: ruby$}, @a1.to_yaml
end
def test_to_yaml_platform_legacy
@@ -2670,7 +2496,7 @@ end
yaml_str = @a1.to_yaml
- same_spec = YAML.load yaml_str
+ same_spec = load_yaml yaml_str
assert_equal Gem::Platform.new('powerpc-darwin7'), same_spec.platform
assert_equal 'powerpc-darwin7.9.0', same_spec.original_platform
@@ -2679,7 +2505,7 @@ end
def test_to_yaml_platform_nil
@a1.instance_variable_set :@original_platform, nil
- assert_match %r|^platform: ruby$|, @a1.to_yaml
+ assert_match %r{^platform: ruby$}, @a1.to_yaml
end
def test_validate
@@ -2711,7 +2537,7 @@ end
assert_equal [], @a1.authors
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
@@ -2719,19 +2545,19 @@ end
@a1.authors = ["#{f} (who is writing this software)"]
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
- assert_equal %{"#{f}" or "#{t}" is not an author}, e.message
+ assert_equal %("#{f}" or "#{t}" is not an author), e.message
@a1.authors = ["#{t} (who is writing this software)"]
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
- assert_equal %{"#{f}" or "#{t}" is not an author}, e.message
+ assert_equal %("#{f}" or "#{t}" is not an author), e.message
end
end
@@ -2806,7 +2632,7 @@ end
@a1.add_development_dependency 'c', '>= 1.2.3'
use_ui @ui do
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
@@ -2856,6 +2682,37 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
end
end
+ def test_validate_rake_extension_have_rake_dependency_warning
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.extensions = ['Rakefile']
+ File.write File.join(@tempdir, 'Rakefile'), ''
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_match(/add rake as a dependency/, @ui.error)
+ end
+ end
+
+ def test_validate_rake_extension_have_rake_dependency_no_warning
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.extensions = ['Rakefile']
+ @a1.add_runtime_dependency 'rake'
+ File.write File.join(@tempdir, 'Rakefile'), ''
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ refute_match(/add rake as a dependency/, @ui.error)
+ end
+ end
+
def test_validate_description
util_setup_validate
@@ -2879,19 +2736,47 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
@a1.description = "#{f} (describe your package)"
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
- assert_equal %{"#{f}" or "#{t}" is not a description}, e.message
+ assert_equal %("#{f}" or "#{t}" is not a description), e.message
@a1.description = "#{t} (describe your package)"
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
+ @a1.validate
+ end
+
+ assert_equal %("#{f}" or "#{t}" is not a description), e.message
+
+ # Adding #{f} anywhere after the start of the description should be fine.
+ @a1.description = "(some description) #{f}"
+
+ assert_nothing_raised do
+ @a1.validate
+ end
+
+ # Adding #{t} anywhere after the start of the description should be fine.
+ @a1.description = "(some description) #{t}"
+
+ assert_nothing_raised do
+ @a1.validate
+ end
+
+ # Adding #{f} at the start of the second or later line should be fine.
+ @a1.description = "(some description)\n#{f}"
+
+ assert_nothing_raised do
@a1.validate
end
- assert_equal %{"#{f}" or "#{t}" is not a description}, e.message
+ # Adding #{t} at the start of the second or later line should be fine.
+ @a1.description = "(some description)\n#{t}"
+
+ assert_nothing_raised do
+ @a1.validate
+ end
end
end
@@ -2901,24 +2786,24 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
Dir.chdir @tempdir do
@a1.email = "FIxxxXME (your e-mail)".sub(/xxx/, "")
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
- assert_equal %{"#{f}" or "#{t}" is not an email}, e.message
+ assert_equal %("#{f}" or "#{t}" is not an email), e.message
@a1.email = "#{t} (your e-mail)"
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
- assert_equal %{"#{f}" or "#{t}" is not an email}, e.message
+ assert_equal %("#{f}" or "#{t}" is not an email), e.message
end
end
def test_validate_empty
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
Gem::Specification.new.validate
end
@@ -2926,7 +2811,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
end
def test_validate_error
- assert_raises Gem::InvalidSpecificationException do
+ assert_raise Gem::InvalidSpecificationException do
use_ui @ui do
Gem::Specification.new.validate
end
@@ -2956,12 +2841,12 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
def test_validate_empty_require_paths
if win_platform?
- skip 'test_validate_empty_require_paths skipped on MS Windows (symlink)'
+ pend 'test_validate_empty_require_paths skipped on MS Windows (symlink)'
else
util_setup_validate
@a1.require_paths = []
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
@@ -2971,7 +2856,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
end
def test_validate_files
- skip 'test_validate_files skipped on MS Windows (symlink)' if win_platform?
+ pend 'test_validate_files skipped on MS Windows (symlink)' if win_platform?
util_setup_validate
@a1.files += ['lib', 'lib2']
@@ -3011,9 +2896,11 @@ WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
Please report a bug if this causes problems.
EXPECTED
- assert_output nil, expected do
+ actual_stdout, actual_stderr = capture_output do
specification.reset
end
+ assert_empty actual_stdout
+ assert_equal(expected, actual_stderr)
end
def test_unresolved_specs_with_versions
@@ -3027,8 +2914,8 @@ Please report a bug if this causes problems.
specification.define_singleton_method(:find_all_by_name) do |dep_name|
[
- specification.new { |s| s.name = "z", s.version = Gem::Version.new("1") },
- specification.new { |s| s.name = "z", s.version = Gem::Version.new("2") }
+ specification.new {|s| s.name = "z", s.version = Gem::Version.new("1") },
+ specification.new {|s| s.name = "z", s.version = Gem::Version.new("2") },
]
end
@@ -3042,9 +2929,20 @@ WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'
Please report a bug if this causes problems.
EXPECTED
- assert_output nil, expected do
+ actual_stdout, actual_stderr = capture_output do
specification.reset
end
+ assert_empty actual_stdout
+ assert_equal(expected, actual_stderr)
+ end
+
+ def test_duplicate_runtime_dependency
+ expected = "WARNING: duplicated b dependency [\"~> 3.0\", \"~> 3.0\"]\n"
+ out, err = capture_output do
+ @a1.add_runtime_dependency "b", "~> 3.0", "~> 3.0"
+ end
+ assert_empty out
+ assert_equal(expected, err)
end
def set_orig(cls)
@@ -3059,7 +2957,7 @@ Please report a bug if this causes problems.
@a1.files = [@a1.file_name]
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
@@ -3091,7 +2989,7 @@ Please report a bug if this causes problems.
@a1.homepage = 'over at my cool site'
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
@@ -3099,7 +2997,7 @@ Please report a bug if this causes problems.
@a1.homepage = 'ftp://rubygems.org'
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
@@ -3122,10 +3020,21 @@ Please report a bug if this causes problems.
@a1.validate
end
- assert_match <<-warning, @ui.error
+ assert_match <<-WARNING, @ui.error
WARNING: licenses is empty, but is recommended. Use a license identifier from
http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
- warning
+ WARNING
+ end
+
+ def test_validate_license_in_a_non_packaging_context
+ util_setup_validate
+
+ use_ui @ui do
+ @a1.licenses.clear
+ @a1.validate(false)
+ end
+
+ assert_empty @ui.error
end
def test_removed_methods
@@ -3151,10 +3060,21 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
@a1.validate
end
- assert_match <<-warning, @ui.error
+ assert_match <<-WARNING, @ui.error
WARNING: license value 'BSD' is invalid. Use a license identifier from
http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
- warning
+ WARNING
+ end
+
+ def test_validate_license_ref
+ util_setup_validate
+
+ use_ui @ui do
+ @a1.licenses = ['LicenseRef-LICENSE.md']
+ @a1.validate
+ end
+
+ assert_empty @ui.error
end
def test_validate_license_values_plus
@@ -3198,14 +3118,14 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
@a1.validate
end
- assert_match <<-warning, @ui.error
+ assert_match <<-WARNING, @ui.error
WARNING: license value 'GPL-2.0+ FOO' is invalid. Use a license identifier from
http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
- warning
- assert_match <<-warning, @ui.error
+ WARNING
+ assert_match <<-WARNING, @ui.error
WARNING: license value 'GPL-2.0 FOO' is invalid. Use a license identifier from
http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
- warning
+ WARNING
end
def test_validate_license_with_invalid_exception
@@ -3216,10 +3136,10 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
@a1.validate
end
- assert_match <<-warning, @ui.error
+ assert_match <<-WARNING, @ui.error
WARNING: license value 'GPL-2.0+ WITH Autocofn-exception-2.0' is invalid. Use a license identifier from
http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
- warning
+ WARNING
end
def test_validate_license_gives_suggestions
@@ -3230,11 +3150,11 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
@a1.validate
end
- assert_match <<-warning, @ui.error
+ assert_match <<-WARNING, @ui.error
WARNING: license value 'ruby' is invalid. Use a license identifier from
http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
Did you mean 'Ruby'?
- warning
+ WARNING
end
def test_validate_empty_files
@@ -3277,7 +3197,7 @@ Did you mean 'Ruby'?
def test_validate_name
util_setup_validate
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.name = :json
@a1.validate
end
@@ -3285,31 +3205,31 @@ Did you mean 'Ruby'?
assert_equal 'invalid value for attribute name: ":json" must be a string', e.message
@a1.name = []
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
assert_equal "invalid value for attribute name: \"[]\" must be a string", e.message
@a1.name = ""
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
assert_equal "invalid value for attribute name: \"\" must include at least one letter", e.message
@a1.name = "12345"
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
assert_equal "invalid value for attribute name: \"12345\" must include at least one letter", e.message
@a1.name = "../malicious"
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
assert_equal "invalid value for attribute name: \"../malicious\" can only include letters, numbers, dashes, and underscores", e.message
@a1.name = "\ba\t"
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
assert_equal "invalid value for attribute name: \"\\ba\\t\" can only include letters, numbers, dashes, and underscores", e.message
@@ -3326,17 +3246,17 @@ Did you mean 'Ruby'?
spec = @a1.dup
spec.instance_variable_set "@#{name}", nil
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
spec.validate
end
- assert_match %r%^#{name}%, e.message
+ assert_match %r{^#{name}}, e.message
end
end
end
def test_validate_permissions
- skip 'chmod not supported' if Gem.win_platform?
+ pend 'chmod not supported' if Gem.win_platform?
util_setup_validate
@@ -3355,7 +3275,7 @@ Did you mean 'Ruby'?
end
def test_validate_permissions_of_missing_file_non_packaging
- skip 'chmod not supported' if Gem.win_platform?
+ pend 'chmod not supported' if Gem.win_platform?
util_setup_validate
@@ -3387,7 +3307,7 @@ Did you mean 'Ruby'?
util_setup_validate
@a1.rubygems_version = "3"
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
@@ -3401,7 +3321,7 @@ Did you mean 'Ruby'?
Dir.chdir @tempdir do
@a1.specification_version = '1.0'
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
use_ui @ui do
@a1.validate
end
@@ -3426,19 +3346,19 @@ Did you mean 'Ruby'?
@a1.summary = "#{f} (describe your package)"
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
- assert_equal %{"#{f}" or "#{t}" is not a summary}, e.message
+ assert_equal %("#{f}" or "#{t}" is not a summary), e.message
@a1.summary = "#{t} (describe your package)"
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
end
- assert_equal %{"#{f}" or "#{t}" is not a summary}, e.message
+ assert_equal %("#{f}" or "#{t}" is not a summary), e.message
end
end
@@ -3487,7 +3407,7 @@ Did you mean 'Ruby'?
specfile.write "raise 'boom'"
specfile.close
begin
- capture_io do
+ capture_output do
Gem::Specification.load(specfile.path)
end
rescue => e
@@ -3498,19 +3418,6 @@ Did you mean 'Ruby'?
specfile.delete
end
- ##
- # KEEP p-1-x86-darwin-8
- # KEEP p-1
- # KEEP c-1.2
- # KEEP a_evil-9
- # a-1
- # a-1-x86-my_platform-1
- # KEEP a-2
- # a-2-x86-other_platform-1
- # KEEP a-2-x86-my_platform-1
- # a-3.a
- # KEEP a-3-x86-other_platform-1
-
def test_latest_specs
spec_fetcher do |fetcher|
fetcher.spec 'a', 1 do |s|
@@ -3533,8 +3440,6 @@ Did you mean 'Ruby'?
end
expected = %W[
- a-2
- a-2-x86-my_platform-1
a-3-x86-other_platform-1
]
@@ -3552,7 +3457,8 @@ Did you mean 'Ruby'?
s.metadata = {
"one" => "two",
"home" => "three",
- "homepage_uri" => "https://example.com/user/repo"
+ "homepage_uri" => "https://example.com/user/repo",
+ "funding_uri" => "https://example.com/donate",
}
end
@@ -3571,7 +3477,7 @@ Did you mean 'Ruby'?
s.metadata = { 1 => "fail" }
end
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@m2.validate
end
@@ -3588,11 +3494,11 @@ Did you mean 'Ruby'?
s.metadata = { ("x" * 129) => "fail" }
end
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@m2.validate
end
- assert_equal "metadata key too large (129 > 128)", e.message
+ assert_equal "metadata key is too large (129 > 128)", e.message
end
end
@@ -3605,11 +3511,11 @@ Did you mean 'Ruby'?
s.metadata = { 'fail' => [] }
end
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@m2.validate
end
- assert_equal "metadata values must be a String", e.message
+ assert_equal "metadata['fail'] value must be a String", e.message
end
end
@@ -3622,11 +3528,11 @@ Did you mean 'Ruby'?
s.metadata = { 'fail' => ("x" * 1025) }
end
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@m2.validate
end
- assert_equal "metadata value too large (1025 > 1024)", e.message
+ assert_equal "metadata['fail'] value is too large (1025 > 1024)", e.message
end
end
@@ -3639,7 +3545,7 @@ Did you mean 'Ruby'?
s.metadata = { 'homepage_uri' => 'http:/example.com' }
end
- e = assert_raises Gem::InvalidSpecificationException do
+ e = assert_raise Gem::InvalidSpecificationException do
@m2.validate
end
@@ -3679,7 +3585,7 @@ end
end
def test_missing_extensions_eh
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
assert @ext.missing_extensions?
@@ -3709,18 +3615,6 @@ end
refute spec.missing_extensions?
end
- def test_missing_extensions_eh_legacy
- ext_spec
-
- @ext.installed_by_version = v '2.2.0.preview.2'
-
- assert @ext.missing_extensions?
-
- @ext.installed_by_version = v '2.2.0.preview.1'
-
- refute @ext.missing_extensions?
- end
-
def test_missing_extensions_eh_none
refute @a1.missing_extensions?
end
@@ -3758,7 +3652,7 @@ end
assert Gem::Specification.find_by_name "a", "1"
assert Gem::Specification.find_by_name "a", ">1"
- assert_raises Gem::MissingSpecError do
+ assert_raise Gem::MissingSpecError do
Gem::Specification.find_by_name "monkeys"
end
end
@@ -3779,7 +3673,7 @@ end
assert Gem::Specification.find_by_name "b"
- assert_raises Gem::MissingSpecVersionError do
+ assert_raise Gem::MissingSpecVersionError do
Gem::Specification.find_by_name "b", "1"
end
@@ -3812,7 +3706,7 @@ end
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
- spec_path = File.join(@default_spec_dir, default_gem_spec.spec_name)
+ spec_path = File.join(@gemhome, "specifications", "default", default_gem_spec.spec_name)
write_file(spec_path) do |file|
file.print(default_gem_spec.to_ruby)
end
@@ -3837,64 +3731,25 @@ end
FileUtils.mkdir_p "test"
FileUtils.mkdir_p "bin"
- FileUtils.touch File.join("ext", "a", "extconf.rb")
- FileUtils.touch File.join("lib", "code.rb")
- FileUtils.touch File.join("test", "suite.rb")
+ begin
+ umask_orig = File.umask(2)
+ FileUtils.touch File.join("ext", "a", "extconf.rb")
+ FileUtils.touch File.join("lib", "code.rb")
+ FileUtils.touch File.join("test", "suite.rb")
- File.open "bin/exec", "w", 0755 do |fp|
- fp.puts "#!#{Gem.ruby}"
+ File.open "bin/exec", "w", 0755 do |fp|
+ fp.puts "#!#{Gem.ruby}"
+ end
+ ensure
+ File.umask(umask_orig)
end
end
end
- def with_syck
- begin
- verbose, $VERBOSE = $VERBOSE, nil
- require "yaml"
- old_engine = YAML::ENGINE.yamler
- YAML::ENGINE.yamler = 'syck'
- load 'rubygems/syck_hack.rb'
- rescue NameError
- # probably on 1.8, ignore
- ensure
- $VERBOSE = verbose
- end
-
- yield
- ensure
- begin
- YAML::ENGINE.yamler = old_engine
- load 'rubygems/syck_hack.rb'
- rescue NameError
- # ignore
- end
- end
-
- def with_psych
- begin
- require "yaml"
- old_engine = YAML::ENGINE.yamler
- YAML::ENGINE.yamler = 'psych'
- load 'rubygems/syck_hack.rb'
- rescue NameError
- # probably on 1.8, ignore
- end
-
- yield
- ensure
- begin
- YAML::ENGINE.yamler = old_engine
- load 'rubygems/syck_hack.rb'
- rescue NameError
- # ignore
- end
- end
-
def silence_warnings
old_verbose, $VERBOSE = $VERBOSE, false
yield
ensure
$VERBOSE = old_verbose
end
-
end
diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb
index 33c25308b5..dc245c342a 100644
--- a/test/rubygems/test_gem_stream_ui.rb
+++ b/test/rubygems/test_gem_stream_ui.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/user_interaction'
require 'timeout'
class TestGemStreamUI < Gem::TestCase
-
- SHORT_TIMEOUT = (defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?) ? 1.0 : 0.1 # increase timeout with MJIT for --jit-wait testing
+ # increase timeout with MJIT for --jit-wait testing
+ mjit_enabled = defined?(RubyVM::JIT) ? RubyVM::JIT.enabled? : defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
+ SHORT_TIMEOUT = (RUBY_ENGINE == "ruby" && !mjit_enabled) ? 0.1 : 1.0
module IsTty
attr_accessor :tty
@@ -89,7 +90,7 @@ class TestGemStreamUI < Gem::TestCase
@in.tty = false
Timeout.timeout(SHORT_TIMEOUT) do
- assert_raises(Gem::OperationNotSupportedError) do
+ assert_raise(Gem::OperationNotSupportedError) do
@sui.ask_yes_no("do coconuts migrate?")
end
end
@@ -220,5 +221,4 @@ class TestGemStreamUI < Gem::TestCase
reporter.fetch 'a.gem', 1024
assert_equal "", @out.string
end
-
end
diff --git a/test/rubygems/test_gem_stub_specification.rb b/test/rubygems/test_gem_stub_specification.rb
index 91a46d7842..e008391ef7 100644
--- a/test/rubygems/test_gem_stub_specification.rb
+++ b/test/rubygems/test_gem_stub_specification.rb
@@ -1,17 +1,16 @@
# frozen_string_literal: true
-require "rubygems/test_case"
+require_relative "helper"
require "rubygems/stub_specification"
class TestStubSpecification < Gem::TestCase
-
- FOO = File.join SPECIFICATIONS, "foo-0.0.1-x86-mswin32.gemspec"
- BAR = File.join SPECIFICATIONS, "bar-0.0.2.gemspec"
+ FOO = File.expand_path File.join("specifications", "foo-0.0.1-x86-mswin32.gemspec"), __dir__
+ BAR = File.expand_path File.join("specifications", "bar-0.0.2.gemspec"), __dir__
def setup
super
- @base_dir = File.dirname(SPECIFICATIONS)
- @gems_dir = File.join File.dirname(SPECIFICATIONS), 'gem'
+ @base_dir = __dir__
+ @gems_dir = File.join __dir__, 'gem'
@foo = Gem::StubSpecification.gemspec_stub FOO, @base_dir, @gems_dir
end
@@ -66,9 +65,9 @@ class TestStubSpecification < Gem::TestCase
end
def test_contains_requirable_file_eh_extension
- skip "I guess making the stub match the running platform should work" if Gem.java_platform?
+ pend "I guess making the stub match the running platform should work" if Gem.java_platform?
stub_with_extension do |stub|
- _, err = capture_io do
+ _, err = capture_output do
refute stub.contains_requirable_file? 'nonexistent'
end
@@ -123,7 +122,7 @@ class TestStubSpecification < Gem::TestCase
end
def test_missing_extensions_eh
- skip "I guess making the stub match the running platform should work" if Gem.java_platform?
+ pend "I guess making the stub match the running platform should work" if Gem.java_platform?
stub = stub_with_extension do |s|
extconf_rb = File.join s.gem_dir, s.extensions.first
FileUtils.mkdir_p File.dirname extconf_rb
@@ -190,7 +189,7 @@ class TestStubSpecification < Gem::TestCase
def test_to_spec_missing_extensions
stub = stub_with_extension
- capture_io do
+ capture_output do
stub.contains_requirable_file? 'nonexistent'
end
@@ -291,5 +290,4 @@ end
return stub
end
end
-
end
diff --git a/test/rubygems/test_gem_text.rb b/test/rubygems/test_gem_text.rb
index ccac812c6d..069cfdc4e6 100644
--- a/test/rubygems/test_gem_text.rb
+++ b/test/rubygems/test_gem_text.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require "rubygems/text"
class TestGemText < Gem::TestCase
-
include Gem::Text
def test_format_text
@@ -23,7 +22,7 @@ class TestGemText < Gem::TestCase
end
def test_format_text_no_space
- assert_equal "texttowr\nap", format_text("texttowrap", 8)
+ assert_equal "texttowr\nap", format_text("texttowrap", 8)
end
def test_format_text_trailing # for two spaces after .
@@ -94,5 +93,4 @@ Without the wrapping, the text might not look good in the RSS feed.
def test_clean_text
assert_equal ".]2;nyan.", clean_text("\e]2;nyan\a")
end
-
end
diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb
index bf5ef5b4a2..9e18972864 100644
--- a/test/rubygems/test_gem_uninstaller.rb
+++ b/test/rubygems/test_gem_uninstaller.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/installer_test_case'
+require_relative 'installer_test_case'
require 'rubygems/uninstaller'
class TestGemUninstaller < Gem::InstallerTestCase
-
def setup
super
@installer = setup_base_installer
@@ -27,7 +26,7 @@ class TestGemUninstaller < Gem::InstallerTestCase
FileUtils.mkdir_p 'foo/bar'
uninstaller = Gem::Uninstaller.new nil, :install_dir => 'foo//bar'
- assert_match %r|foo/bar$|, uninstaller.instance_variable_get(:@gem_home)
+ assert_match %r{foo/bar$}, uninstaller.instance_variable_get(:@gem_home)
end
def test_ask_if_ok
@@ -55,7 +54,7 @@ class TestGemUninstaller < Gem::InstallerTestCase
uninstaller.remove_all [@spec]
end
- refute_path_exists @spec.gem_dir
+ assert_path_not_exist @spec.gem_dir
end
def test_remove_executables_force_keep
@@ -139,7 +138,7 @@ class TestGemUninstaller < Gem::InstallerTestCase
Dir.mkdir "#{@gemhome}2"
uninstaller = Gem::Uninstaller.new nil, :install_dir => "#{@gemhome}2"
- e = assert_raises Gem::GemNotInHomeException do
+ e = assert_raise Gem::GemNotInHomeException do
use_ui ui do
uninstaller.remove @spec
end
@@ -150,10 +149,12 @@ class TestGemUninstaller < Gem::InstallerTestCase
assert_equal expected, e.message
- assert_path_exists @spec.gem_dir
+ assert_path_exist @spec.gem_dir
end
def test_remove_symlinked_gem_home
+ pend "Symlinks not supported or not enabled" unless symlink_supported?
+
Dir.mktmpdir("gem_home") do |dir|
symlinked_gem_home = "#{dir}/#{File.basename(@gemhome)}"
@@ -165,8 +166,61 @@ class TestGemUninstaller < Gem::InstallerTestCase
uninstaller.remove @spec
end
- refute_path_exists @spec.gem_dir
+ assert_path_not_exist @spec.gem_dir
+ end
+ end
+
+ def test_remove_plugins
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ io.write "puts __FILE__"
+ end
+
+ @spec.files += %w[lib/rubygems_plugin.rb]
+
+ Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+
+ plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+ assert File.exist?(plugin_path), 'plugin not written'
+
+ Gem::Uninstaller.new(nil).remove_plugins @spec
+
+ refute File.exist?(plugin_path), 'plugin not removed'
+ end
+
+ def test_remove_plugins_with_install_dir
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ io.write "puts __FILE__"
+ end
+
+ @spec.files += %w[lib/rubygems_plugin.rb]
+
+ Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+
+ plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+ assert File.exist?(plugin_path), 'plugin not written'
+
+ Dir.mkdir "#{@gemhome}2"
+ Gem::Uninstaller.new(nil, :install_dir => "#{@gemhome}2").remove_plugins @spec
+
+ assert File.exist?(plugin_path), 'plugin unintentionally removed'
+ end
+
+ def test_regenerate_plugins_for
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ io.write "puts __FILE__"
end
+
+ @spec.files += %w[lib/rubygems_plugin.rb]
+
+ Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+
+ plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+ assert File.exist?(plugin_path), 'plugin not written'
+
+ FileUtils.rm plugin_path
+ Gem::Uninstaller.new(nil).regenerate_plugins_for @spec, Gem.plugindir
+
+ assert File.exist?(plugin_path), 'plugin not regenerated'
end
def test_path_ok_eh
@@ -241,9 +295,16 @@ class TestGemUninstaller < Gem::InstallerTestCase
uninstaller = Gem::Uninstaller.new spec.name, :executables => true
- uninstaller.uninstall
-
- refute_path_exists spec.gem_dir
+ ui = Gem::MockGemUi.new "1\ny\n"
+ use_ui ui do
+ uninstaller.uninstall
+ end
+ expected = "Successfully uninstalled default-2\n" \
+ "There was both a regular copy and a default copy of default-2. The " \
+ "regular copy was successfully uninstalled, but the default copy " \
+ "was left around because default gems can't be removed.\n"
+ assert_equal expected, ui.output
+ assert_path_not_exist spec.gem_dir
end
def test_uninstall_extension
@@ -260,22 +321,22 @@ create_makefile '#{@spec.name}'
use_ui @ui do
path = Gem::Package.build @spec
- installer = Gem::Installer.at path
+ installer = Gem::Installer.at path, :force => true
installer.install
end
- assert_path_exists @spec.extension_dir, 'sanity check'
+ assert_path_exist @spec.extension_dir, 'sanity check'
uninstaller = Gem::Uninstaller.new @spec.name, :executables => true
uninstaller.uninstall
- refute_path_exists @spec.extension_dir
+ assert_path_not_exist @spec.extension_dir
end
def test_uninstall_nonexistent
uninstaller = Gem::Uninstaller.new 'bogus', :executables => true
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
uninstaller.uninstall
end
@@ -297,7 +358,7 @@ create_makefile '#{@spec.name}'
ui = Gem::MockGemUi.new "n\n"
- assert_raises Gem::DependencyRemovalException do
+ assert_raise Gem::DependencyRemovalException do
use_ui ui do
uninstaller.uninstall
end
@@ -317,16 +378,16 @@ create_makefile '#{@spec.name}'
gem_dir = File.join @user_spec.gem_dir
Gem.pre_uninstall do
- assert_path_exists gem_dir
+ assert_path_exist gem_dir
end
Gem.post_uninstall do
- refute_path_exists gem_dir
+ assert_path_not_exist gem_dir
end
uninstaller.uninstall
- refute_path_exists gem_dir
+ assert_path_not_exist gem_dir
assert_same uninstaller, @pre_uninstall_hook_arg
assert_same uninstaller, @post_uninstall_hook_arg
@@ -338,7 +399,7 @@ create_makefile '#{@spec.name}'
uninstaller = Gem::Uninstaller.new @spec.name, :executables => true
- e = assert_raises Gem::InstallError do
+ e = assert_raise Gem::InstallError do
uninstaller.uninstall
end
@@ -405,12 +466,12 @@ create_makefile '#{@spec.name}'
lines = ui.output.split("\n")
lines.shift
- assert_match %r!You have requested to uninstall the gem:!, lines.shift
+ assert_match %r{You have requested to uninstall the gem:}, lines.shift
lines.shift
lines.shift
- assert_match %r!r-1 depends on q \(= 1\)!, lines.shift
- assert_match %r!Successfully uninstalled q-1!, lines.last
+ assert_match %r{r-1 depends on q \(= 1\)}, lines.shift
+ assert_match %r{Successfully uninstalled q-1}, lines.last
end
def test_uninstall_only_lists_unsatisfied_deps
@@ -435,12 +496,12 @@ create_makefile '#{@spec.name}'
lines = ui.output.split("\n")
lines.shift
- assert_match %r!You have requested to uninstall the gem:!, lines.shift
+ assert_match %r{You have requested to uninstall the gem:}, lines.shift
lines.shift
lines.shift
- assert_match %r!x-1 depends on q \(= 1.0\)!, lines.shift
- assert_match %r!Successfully uninstalled q-1.0!, lines.last
+ assert_match %r{x-1 depends on q \(= 1.0\)}, lines.shift
+ assert_match %r{Successfully uninstalled q-1.0}, lines.last
end
def test_uninstall_doesnt_prompt_when_other_gem_satisfies_requirement
@@ -492,7 +553,7 @@ create_makefile '#{@spec.name}'
un = Gem::Uninstaller.new('q', :abort_on_dependent => true)
ui = Gem::MockGemUi.new("y\n")
- assert_raises Gem::DependencyRemovalException do
+ assert_raise Gem::DependencyRemovalException do
use_ui ui do
un.uninstall
end
@@ -516,12 +577,41 @@ create_makefile '#{@spec.name}'
lines = ui.output.split("\n")
lines.shift
- assert_match %r!You have requested to uninstall the gem:!, lines.shift
+ assert_match %r{You have requested to uninstall the gem:}, lines.shift
lines.shift
lines.shift
- assert_match %r!r-1 depends on q \(= 1, development\)!, lines.shift
- assert_match %r!Successfully uninstalled q-1!, lines.last
+ assert_match %r{r-1 depends on q \(= 1, development\)}, lines.shift
+ assert_match %r{Successfully uninstalled q-1}, lines.last
+ end
+
+ def test_uninstall_prompt_only_lists_the_dependents_that_prevented_uninstallation
+ quick_gem 'r', '1' do |s|
+ s.add_development_dependency 'q', '= 1'
+ end
+
+ quick_gem 's', '1' do |s|
+ s.add_dependency 'q', '= 1'
+ end
+
+ quick_gem 'q', '1'
+
+ un = Gem::Uninstaller.new('q', :check_dev => false)
+ ui = Gem::MockGemUi.new("y\n")
+
+ use_ui ui do
+ un.uninstall
+ end
+
+ lines = ui.output.split("\n")
+ lines.shift
+
+ assert_match %r{You have requested to uninstall the gem:}, lines.shift
+ lines.shift
+ lines.shift
+
+ assert_match %r{s-1 depends on q \(= 1\)}, lines.shift
+ assert_match %r{Successfully uninstalled q-1}, lines.last
end
def test_uninstall_no_permission
@@ -536,10 +626,49 @@ create_makefile '#{@spec.name}'
end
FileUtils.stub :rm_r, stub_rm_r do
- assert_raises Gem::UninstallError do
+ assert_raise Gem::UninstallError do
uninstaller.uninstall
end
end
end
+ def test_uninstall_keeps_plugins_up_to_date
+ write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ io.write "puts __FILE__"
+ end
+
+ plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+
+ @spec.version = '1'
+ Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+
+ refute File.exist?(plugin_path), 'version without plugin installed, but plugin written'
+
+ @spec.files += %w[lib/rubygems_plugin.rb]
+ @spec.version = '2'
+ Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+
+ assert File.exist?(plugin_path), 'version with plugin installed, but plugin not written'
+ assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'written plugin has incorrect content'
+
+ @spec.version = '3'
+ Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+
+ assert File.exist?(plugin_path), 'version with plugin installed, but plugin removed'
+ assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'old version installed, but plugin updated'
+
+ Gem::Uninstaller.new('a', :version => '1', :executables => true).uninstall
+
+ assert File.exist?(plugin_path), 'plugin removed when old version uninstalled'
+ assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'old version uninstalled, but plugin updated'
+
+ Gem::Uninstaller.new('a', version: '3', :executables => true).uninstall
+
+ assert File.exist?(plugin_path), 'plugin removed when old version uninstalled and another version with plugin still present'
+ assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'latest version uninstalled, but plugin not updated to previous version'
+
+ Gem::Uninstaller.new('a', version: '2', :executables => true).uninstall
+
+ refute File.exist?(plugin_path), 'last version uninstalled, but plugin still present'
+ end
end
diff --git a/test/rubygems/test_gem_unsatisfiable_dependency_error.rb b/test/rubygems/test_gem_unsatisfiable_dependency_error.rb
index e68185ce25..f9d30123f0 100644
--- a/test/rubygems/test_gem_unsatisfiable_dependency_error.rb
+++ b/test/rubygems/test_gem_unsatisfiable_dependency_error.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestGemUnsatisfiableDependencyError < Gem::TestCase
-
def setup
super
@@ -28,5 +27,4 @@ class TestGemUnsatisfiableDependencyError < Gem::TestCase
def test_version
assert_equal @a_dep.requirement, @e.version
end
-
end
diff --git a/test/rubygems/test_gem_uri.rb b/test/rubygems/test_gem_uri.rb
new file mode 100644
index 0000000000..7fe572518b
--- /dev/null
+++ b/test/rubygems/test_gem_uri.rb
@@ -0,0 +1,39 @@
+require_relative 'helper'
+require 'rubygems/uri'
+
+class TestUri < Gem::TestCase
+ def test_to_s_not_string
+ assert_equal "not_a_uri", Gem::Uri.new(:not_a_uri).to_s
+ end
+
+ def test_to_s_invalid_uri
+ assert_equal "https://www.example.com:80index", Gem::Uri.new("https://www.example.com:80index").to_s
+ end
+
+ def test_redacted_with_user_pass
+ assert_equal "https://user:REDACTED@example.com", Gem::Uri.new("https://user:pass@example.com").redacted.to_s
+ end
+
+ def test_redacted_with_token
+ assert_equal "https://REDACTED@example.com", Gem::Uri.new("https://token@example.com").redacted.to_s
+ end
+
+ def test_redacted_with_user_x_oauth_basic
+ assert_equal "https://REDACTED:x-oauth-basic@example.com", Gem::Uri.new("https://token:x-oauth-basic@example.com").redacted.to_s
+ end
+
+ def test_redacted_without_credential
+ assert_equal "https://www.example.com", Gem::Uri.new("https://www.example.com").redacted.to_s
+ end
+
+ def test_redacted_with_invalid_uri
+ assert_equal "https://www.example.com:80index", Gem::Uri.new("https://www.example.com:80index").redacted.to_s
+ end
+
+ def test_redacted_does_not_modify_uri
+ url = 'https://user:password@example.com'
+ uri = Gem::Uri.new(url)
+ assert_equal 'https://user:REDACTED@example.com', uri.redacted.to_s
+ assert_equal url, uri.to_s
+ end
+end
diff --git a/test/rubygems/test_gem_uri_formatter.rb b/test/rubygems/test_gem_uri_formatter.rb
index b19bae9939..a41c9238ad 100644
--- a/test/rubygems/test_gem_uri_formatter.rb
+++ b/test/rubygems/test_gem_uri_formatter.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/uri_formatter'
class TestGemUriFormatter < Gem::TestCase
-
def test_normalize_uri
assert_equal 'FILE://example/',
Gem::UriFormatter.new('FILE://example/').normalize
@@ -24,5 +23,4 @@ class TestGemUriFormatter < Gem::TestCase
def test_unescape
assert_equal 'a@b\c', Gem::UriFormatter.new('a%40b%5Cc').unescape
end
-
end
diff --git a/test/rubygems/test_gem_util.rb b/test/rubygems/test_gem_util.rb
index 3f1d069a20..e0db5c283d 100644
--- a/test/rubygems/test_gem_util.rb
+++ b/test/rubygems/test_gem_util.rb
@@ -1,22 +1,25 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/util'
class TestGemUtil < Gem::TestCase
-
def test_class_popen
- skip "popen with a block does not behave well on jruby" if Gem.java_platform?
- assert_equal "0\n", Gem::Util.popen(Gem.ruby, '-I', File.expand_path('../../../lib', __FILE__), '-e', 'p 0')
+ pend "popen with a block does not behave well on jruby" if Gem.java_platform?
+ assert_equal "0\n", Gem::Util.popen(*ruby_with_rubygems_in_load_path, '-e', 'p 0')
- assert_raises Errno::ECHILD do
+ assert_raise Errno::ECHILD do
Process.wait(-1)
end
end
def test_silent_system
- skip if Gem.java_platform?
- assert_silent do
- Gem::Util.silent_system Gem.ruby, '-I', File.expand_path('../../../lib', __FILE__), '-e', 'puts "hello"; warn "hello"'
+ pend if Gem.java_platform?
+ Gem::Deprecate.skip_during do
+ out, err = capture_output do
+ Gem::Util.silent_system(*ruby_with_rubygems_in_load_path, '-e', 'puts "hello"; warn "hello"')
+ end
+ assert_empty out
+ assert_empty err
end
end
@@ -32,21 +35,21 @@ class TestGemUtil < Gem::TestCase
end
def test_traverse_parents_does_not_crash_on_permissions_error
- skip 'skipped on MS Windows (chmod has no effect)' if win_platform? || java_platform?
+ pend 'skipped on MS Windows (chmod has no effect)' if win_platform? || java_platform?
FileUtils.mkdir_p 'd/e/f'
# remove 'execute' permission from "e" directory and make it
# impossible to cd into it and its children
FileUtils.chmod(0666, 'd/e')
- skip 'skipped in root privilege' if Process.uid.zero?
+ pend 'skipped in root privilege' if Process.uid.zero?
paths = Gem::Util.traverse_parents('d/e/f').to_a
assert_equal File.join(@tempdir, 'd'), paths[0]
assert_equal @tempdir, paths[1]
- assert_equal File.realpath(Dir.tmpdir), paths[2]
- assert_equal File.realpath("..", Dir.tmpdir), paths[3]
+ assert_equal File.realpath("..", @tempdir), paths[2]
+ assert_equal File.realpath("../..", @tempdir), paths[3]
ensure
# restore default permissions, allow the directory to be removed
FileUtils.chmod(0775, 'd/e') unless win_platform? || java_platform?
@@ -56,8 +59,8 @@ class TestGemUtil < Gem::TestCase
list = [1,2,3,4,5].inject(Gem::List.new(0)) do |m,o|
Gem::List.new o, m
end
- assert_equal 5, list.find { |x| x == 5 }
- assert_equal 4, list.find { |x| x == 4 }
+ assert_equal 5, list.find {|x| x == 5 }
+ assert_equal 4, list.find {|x| x == 4 }
end
def test_glob_files_in_dir
@@ -71,10 +74,10 @@ class TestGemUtil < Gem::TestCase
]
files_with_absolute_base = Gem::Util.glob_files_in_dir('*.rb', File.join(@tempdir, 'g'))
- assert_equal expected_paths.to_set, files_with_absolute_base.to_set
+ assert_equal expected_paths.sort, files_with_absolute_base.sort
files_with_relative_base = Gem::Util.glob_files_in_dir('*.rb', 'g')
- assert_equal expected_paths.to_set, files_with_relative_base.to_set
+ assert_equal expected_paths.sort, files_with_relative_base.sort
end
def test_correct_for_windows_path
@@ -84,5 +87,4 @@ class TestGemUtil < Gem::TestCase
path = "/home/skillet"
assert_equal "/home/skillet", Gem::Util.correct_for_windows_path(path)
end
-
end
diff --git a/test/rubygems/test_gem_validator.rb b/test/rubygems/test_gem_validator.rb
index 34b7e5fb37..8090776b4a 100644
--- a/test/rubygems/test_gem_validator.rb
+++ b/test/rubygems/test_gem_validator.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require "rubygems/test_case"
+require_relative "helper"
require "rubygems/validator"
class TestGemValidator < Gem::TestCase
-
def setup
super
@@ -27,7 +26,7 @@ class TestGemValidator < Gem::TestCase
@spec.file_name => [
Gem::Validator::ErrorData.new('lib/b.rb', 'Missing file'),
Gem::Validator::ErrorData.new('lib/c.rb', 'Extra file'),
- ]
+ ],
}
assert_equal expected, alien
@@ -40,5 +39,4 @@ class TestGemValidator < Gem::TestCase
assert_empty alien
end
-
end
diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb
index 1deecc0eed..422e1ee86c 100644
--- a/test/rubygems/test_gem_version.rb
+++ b/test/rubygems/test_gem_version.rb
@@ -1,11 +1,8 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require "rubygems/version"
-require "minitest/benchmark"
-
class TestGemVersion < Gem::TestCase
-
class V < ::Gem::Version
end
@@ -48,9 +45,11 @@ class TestGemVersion < Gem::TestCase
assert_equal false, Gem::Version.correct?("an incorrect version")
expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n"
- assert_output nil, expected do
+ actual_stdout, actual_stderr = capture_output do
Gem::Version.correct?(nil)
end
+ assert_empty actual_stdout
+ assert_equal(expected, actual_stderr)
end
def test_class_new_subclass
@@ -101,7 +100,7 @@ class TestGemVersion < Gem::TestCase
invalid_versions << "2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e."
invalid_versions.each do |invalid|
- e = assert_raises ArgumentError, invalid do
+ e = assert_raise ArgumentError, invalid do
Gem::Version.new invalid
end
@@ -109,15 +108,6 @@ class TestGemVersion < Gem::TestCase
end
end
- def bench_anchored_version_pattern
- assert_performance_linear 0.5 do |count|
- version_string = count.times.map {|i| "0" * i.succ }.join(".") << "."
- version_string =~ Gem::Version::ANCHORED_VERSION_PATTERN
- end
- rescue RegexpError
- skip "It fails to allocate the memory for regex pattern of Gem::Version::ANCHORED_VERSION_PATTERN"
- end
-
def test_empty_version
["", " ", " "].each do |empty|
assert_equal "0", Gem::Version.new(empty).version
@@ -236,7 +226,7 @@ class TestGemVersion < Gem::TestCase
assert_equal expected, v(version).approximate_recommendation
end
- # Assert that the "approximate" recommendation for +version+ satifies +version+.
+ # Assert that the "approximate" recommendation for +version+ satisfies +version+.
def assert_approximate_satisfies_itself(version)
gem_version = v(version)
@@ -298,5 +288,4 @@ class TestGemVersion < Gem::TestCase
def refute_version_equal(unexpected, actual)
refute_equal v(unexpected), v(actual)
end
-
end
diff --git a/test/rubygems/test_gem_version_option.rb b/test/rubygems/test_gem_version_option.rb
index a680c5154e..74d7979e3a 100644
--- a/test/rubygems/test_gem_version_option.rb
+++ b/test/rubygems/test_gem_version_option.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems/command'
require 'rubygems/version_option'
class TestGemVersionOption < Gem::TestCase
-
def setup
super
@@ -57,7 +56,7 @@ class TestGemVersionOption < Gem::TestCase
@cmd.handle_options %w[--platform ruby]
expected = [
- Gem::Platform::RUBY
+ Gem::Platform::RUBY,
]
assert_equal expected, Gem.platforms
@@ -162,5 +161,4 @@ class TestGemVersionOption < Gem::TestCase
assert_equal expected, @cmd.options
end
-
end
diff --git a/test/rubygems/test_kernel.rb b/test/rubygems/test_kernel.rb
index daf9b57d7c..dee36d05ee 100644
--- a/test/rubygems/test_kernel.rb
+++ b/test/rubygems/test_kernel.rb
@@ -1,14 +1,15 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestKernel < Gem::TestCase
-
def setup
super
@old_path = $:.dup
util_make_gems
+
+ without_any_upwards_gemfiles
end
def teardown
@@ -19,7 +20,7 @@ class TestKernel < Gem::TestCase
def test_gem
assert gem('a', '= 1'), "Should load"
- assert $:.any? { |p| %r{a-1/lib} =~ p }
+ assert $:.any? {|p| %r{a-1/lib} =~ p }
end
def test_gem_default
@@ -39,7 +40,7 @@ class TestKernel < Gem::TestCase
def test_gem_re_gem_mismatch
assert gem('a', '=1')
- assert_raises Gem::LoadError do
+ assert_raise Gem::LoadError do
gem('a', '= 2')
end
@@ -49,13 +50,13 @@ class TestKernel < Gem::TestCase
def test_gem_redundant
assert gem('a', '= 1'), "Should load"
refute gem('a', '= 1'), "Should not load"
- assert_equal 1, $:.select { |p| %r{a-1/lib} =~ p }.size
+ assert_equal 1, $:.select {|p| %r{a-1/lib} =~ p }.size
end
def test_gem_overlapping
assert gem('a', '= 1'), "Should load"
refute gem('a', '>= 1'), "Should not load"
- assert_equal 1, $:.select { |p| %r{a-1/lib} =~ p }.size
+ assert_equal 1, $:.select {|p| %r{a-1/lib} =~ p }.size
end
def test_gem_prerelease
@@ -66,7 +67,7 @@ class TestKernel < Gem::TestCase
def test_gem_env_req
ENV["GEM_REQUIREMENT_A"] = '~> 2.0'
- assert_raises(Gem::MissingSpecVersionError) { gem('a', '= 1') }
+ assert_raise(Gem::MissingSpecVersionError) { gem('a', '= 1') }
assert gem('a', '> 1')
assert_equal @a2, Gem.loaded_specs['a']
end
@@ -74,7 +75,7 @@ class TestKernel < Gem::TestCase
def test_gem_conflicting
assert gem('a', '= 1'), "Should load"
- ex = assert_raises Gem::LoadError do
+ ex = assert_raise Gem::LoadError do
gem 'a', '= 2'
end
@@ -82,13 +83,13 @@ class TestKernel < Gem::TestCase
assert_match(/activated a-1/, ex.message)
assert_equal 'a', ex.name
- assert $:.any? { |p| %r{a-1/lib} =~ p }
- refute $:.any? { |p| %r{a-2/lib} =~ p }
+ assert $:.any? {|p| %r{a-1/lib} =~ p }
+ refute $:.any? {|p| %r{a-2/lib} =~ p }
end
def test_gem_not_adding_bin
assert gem('a', '= 1'), "Should load"
- refute $:.any? { |p| %r{a-1/bin} =~ p }
+ refute $:.any? {|p| %r{a-1/bin} =~ p }
end
def test_gem_failing_inside_require_doesnt_cause_double_exceptions
@@ -98,14 +99,12 @@ class TestKernel < Gem::TestCase
output, _ = Open3.capture2e(
{ "GEM_HOME" => Gem.paths.home },
- Gem.ruby,
- "-I",
- File.expand_path("../../lib", __dir__),
+ *ruby_with_rubygems_in_load_path,
"-r",
"./activate.rb"
)
- load_errors = output.split("\n").select { |line| line.include?("Could not find")}
+ load_errors = output.split("\n").select {|line| line.include?("Could not find") }
assert_equal 1, load_errors.size
end
@@ -115,7 +114,7 @@ class TestKernel < Gem::TestCase
quick_gem 'bundler', '2.a'
assert gem('bundler')
- assert $:.any? { |p| %r{bundler-1/lib} =~ p }
+ assert $:.any? {|p| %r{bundler-1/lib} =~ p }
end
def test_gem_bundler_missing_bundler_version
@@ -123,7 +122,7 @@ class TestKernel < Gem::TestCase
quick_gem 'bundler', '1'
quick_gem 'bundler', '2.a'
- e = assert_raises Gem::MissingSpecVersionError do
+ e = assert_raise Gem::MissingSpecVersionError do
gem('bundler')
end
assert_match "Could not find 'bundler' (55) required by reason.", e.message
@@ -136,8 +135,7 @@ class TestKernel < Gem::TestCase
quick_gem 'bundler', '2.a'
assert gem('bundler', '>= 0.a')
- assert $:.any? { |p| %r{bundler-1/lib} =~ p }
+ assert $:.any? {|p| %r{bundler-1/lib} =~ p }
end
end
-
end
diff --git a/test/rubygems/test_project_sanity.rb b/test/rubygems/test_project_sanity.rb
index 6a9eb3b83f..e9e3bfd1ba 100644
--- a/test/rubygems/test_project_sanity.rb
+++ b/test/rubygems/test_project_sanity.rb
@@ -1,15 +1,20 @@
# frozen_string_literal: true
+require_relative "helper"
require "open3"
-class TestProjectSanity < Minitest::Test
-
+class TestProjectSanity < Gem::TestCase
def test_manifest_is_up_to_date
- skip unless File.exist?(File.expand_path("../../../Rakefile", __FILE__))
+ pend unless File.exist?(File.expand_path("../../../Rakefile", __FILE__))
_, status = Open3.capture2e("rake check_manifest")
assert status.success?, "Expected Manifest.txt to be up to date, but it's not. Run `rake update_manifest` to sync it."
end
+ def test_require_rubygems_package
+ err, status = Open3.capture2e(*ruby_with_rubygems_in_load_path, "--disable-gems", "-e", "'require \"rubygems/package\"'")
+
+ assert status.success?, err
+ end
end
diff --git a/test/rubygems/test_remote_fetch_error.rb b/test/rubygems/test_remote_fetch_error.rb
index 766086756e..b9e58389d3 100644
--- a/test/rubygems/test_remote_fetch_error.rb
+++ b/test/rubygems/test_remote_fetch_error.rb
@@ -1,11 +1,10 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
class TestRemoteFetchError < Gem::TestCase
-
def test_password_redacted
error = Gem::RemoteFetcher::FetchError.new('There was an error fetching', 'https://user:secret@gemsource.org')
- refute_match 'secret', error.to_s
+ refute_match %r{secret}, error.to_s
end
def test_invalid_url
@@ -17,5 +16,4 @@ class TestRemoteFetchError < Gem::TestCase
error = Gem::RemoteFetcher::FetchError.new('There was an error fetching', 'https://gemsource.org')
assert_equal error.to_s, 'There was an error fetching (https://gemsource.org)'
end
-
end
diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb
index 392ede7ba0..56774116a9 100644
--- a/test/rubygems/test_require.rb
+++ b/test/rubygems/test_require.rb
@@ -1,11 +1,9 @@
# frozen_string_literal: true
-require 'rubygems/test_case'
+require_relative 'helper'
require 'rubygems'
class TestGemRequire < Gem::TestCase
-
class Latch
-
def initialize(count = 1)
@count = count
@lock = Monitor.new
@@ -24,17 +22,6 @@ class TestGemRequire < Gem::TestCase
@cv.wait_while { @count > 0 }
end
end
-
- end
-
- def setup
- super
-
- @old_loaded_features = $LOADED_FEATURES.dup
- assert_raises LoadError do
- require 'test_gem_require_a'
- end
- $LOADED_FEATURES.replace @old_loaded_features
end
def assert_require(path)
@@ -52,7 +39,7 @@ class TestGemRequire < Gem::TestCase
foo1 = File.join lp1, 'foo.rb'
FileUtils.mkdir_p lp1
- File.open(foo1, 'w') { |f| f.write "class Object; HELLO = 'foo1' end" }
+ File.open(foo1, 'w') {|f| f.write "class Object; HELLO = 'foo1' end" }
lp = $LOAD_PATH.dup
@@ -64,7 +51,7 @@ class TestGemRequire < Gem::TestCase
foo2 = File.join lp2, 'foo.rb'
FileUtils.mkdir_p lp2
- File.open(foo2, 'w') { |f| f.write "class Object; HELLO = 'foo2' end" }
+ File.open(foo2, 'w') {|f| f.write "class Object; HELLO = 'foo2' end" }
$LOAD_PATH.unshift lp2
refute_require 'foo'
@@ -89,9 +76,7 @@ class TestGemRequire < Gem::TestCase
c_rb = File.join dash_i_arg, 'b', 'c.rb'
FileUtils.mkdir_p File.dirname c_rb
- File.open(c_rb, 'w') { |f| f.write "class Object; HELLO = 'world' end" }
-
- lp = $LOAD_PATH.dup
+ File.open(c_rb, 'w') {|f| f.write "class Object; HELLO = 'world' end" }
# Pretend to provide a commandline argument that overrides a file in gem b
$LOAD_PATH.unshift dash_i_arg
@@ -99,9 +84,8 @@ class TestGemRequire < Gem::TestCase
assert_require 'test_gem_require_a'
assert_require 'b/c' # this should be required from -I
assert_equal "world", ::Object::HELLO
- assert_equal %w(a-1 b-1), loaded_spec_names
+ assert_equal %w[a-1 b-1], loaded_spec_names
ensure
- $LOAD_PATH.replace lp
Object.send :remove_const, :HELLO if Object.const_defined? :HELLO
end
@@ -123,7 +107,7 @@ class TestGemRequire < Gem::TestCase
c1 = new_default_spec "c", "1", nil, "c/c.rb"
c2 = new_default_spec "c", "2", nil, "c/c.rb"
- install_default_specs c1, c2, b1, a1
+ install_default_gems c1, c2, b1, a1
dir = Dir.mktmpdir("test_require", @tempdir)
dash_i_arg = File.join dir, 'lib'
@@ -131,40 +115,32 @@ class TestGemRequire < Gem::TestCase
c_rb = File.join dash_i_arg, 'c', 'c.rb'
FileUtils.mkdir_p File.dirname c_rb
- File.open(c_rb, 'w') { |f| f.write "class Object; HELLO = 'world' end" }
+ File.open(c_rb, 'w') {|f| f.write "class Object; HELLO = 'world' end" }
assert_require 'test_gem_require_a'
- lp = $LOAD_PATH.dup
-
# Pretend to provide a commandline argument that overrides a file in gem b
$LOAD_PATH.unshift dash_i_arg
assert_require 'b/c'
assert_require 'c/c' # this should be required from -I
assert_equal "world", ::Object::HELLO
- assert_equal %w(a-1 b-1), loaded_spec_names
+ assert_equal %w[a-1 b-1], loaded_spec_names
ensure
- $LOAD_PATH.replace lp
Object.send :remove_const, :HELLO if Object.const_defined? :HELLO
end
def test_dash_i_respects_default_library_extension_priority
- skip "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "not installed yet" unless RbConfig::TOPDIR
dash_i_ext_arg = util_install_extension_file('a')
dash_i_lib_arg = util_install_ruby_file('a')
- lp = $LOAD_PATH.dup
-
- begin
- $LOAD_PATH.unshift dash_i_lib_arg
- $LOAD_PATH.unshift dash_i_ext_arg
- assert_require 'a'
- assert_match(/a\.rb$/, $LOADED_FEATURES.last)
- ensure
- $LOAD_PATH.replace lp
- end
+ $LOAD_PATH.unshift dash_i_lib_arg
+ $LOAD_PATH.unshift dash_i_ext_arg
+ assert_require 'a'
+ assert_match(/a\.rb$/, $LOADED_FEATURES.last)
end
def test_concurrent_require
@@ -200,11 +176,11 @@ class TestGemRequire < Gem::TestCase
install_specs b1, b2, a1
assert_require 'test_gem_require_a'
- assert_equal %w(a-1 b-1), loaded_spec_names
+ assert_equal %w[a-1 b-1], loaded_spec_names
assert_equal unresolved_names, []
assert_require "b/c"
- assert_equal %w(a-1 b-1), loaded_spec_names
+ assert_equal %w[a-1 b-1], loaded_spec_names
end
def test_require_is_lazy_with_inexact_req
@@ -215,11 +191,11 @@ class TestGemRequire < Gem::TestCase
install_specs b1, b2, a1
assert_require 'test_gem_require_a'
- assert_equal %w(a-1), loaded_spec_names
+ assert_equal %w[a-1], loaded_spec_names
assert_equal unresolved_names, ["b (>= 1)"]
assert_require "b/c"
- assert_equal %w(a-1 b-2), loaded_spec_names
+ assert_equal %w[a-1 b-2], loaded_spec_names
end
def test_require_is_not_lazy_with_one_possible
@@ -229,11 +205,11 @@ class TestGemRequire < Gem::TestCase
install_specs b1, a1
assert_require 'test_gem_require_a'
- assert_equal %w(a-1 b-1), loaded_spec_names
+ assert_equal %w[a-1 b-1], loaded_spec_names
assert_equal unresolved_names, []
assert_require "b/c"
- assert_equal %w(a-1 b-1), loaded_spec_names
+ assert_equal %w[a-1 b-1], loaded_spec_names
end
def test_require_can_use_a_pathname_object
@@ -242,42 +218,87 @@ class TestGemRequire < Gem::TestCase
install_specs a1
assert_require Pathname.new 'test_gem_require_a'
- assert_equal %w(a-1), loaded_spec_names
+ assert_equal %w[a-1], loaded_spec_names
assert_equal unresolved_names, []
end
def test_activate_via_require_respects_loaded_files
- skip "Not sure what's going on. If another spec creates a 'a' gem before
+ pend "Not sure what's going on. If another spec creates a 'a' gem before
this test, somehow require will load the benchmark in b, and ignore that the
stdlib one is already in $LOADED_FEATURES?. Reproducible by running the
spaceship_specific_file test before this one" if java_platform?
- lp = $LOAD_PATH.dup
- lib_dir = File.expand_path(File.join(File.dirname(__FILE__), "../../lib"))
- if File.exist?(lib_dir)
+ pend "not installed yet" unless RbConfig::TOPDIR
+
+ lib_dir = File.expand_path("../../lib", File.dirname(__FILE__))
+ rubylibdir = File.realdirpath(RbConfig::CONFIG["rubylibdir"])
+ if rubylibdir == lib_dir
+ # testing in the ruby repository where RubyGems' lib/ == stdlib lib/
+ # In that case we want to move the stdlib lib/ to still be after b-2 in $LOAD_PATH
+ lp = $LOAD_PATH.dup
$LOAD_PATH.delete lib_dir
$LOAD_PATH.push lib_dir
+ load_path_changed = true
end
+ require 'benchmark' # the stdlib
+
a1 = util_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb"
b1 = util_spec "b", "1", nil, "lib/benchmark.rb"
b2 = util_spec "b", "2", nil, "lib/benchmark.rb"
install_specs b1, b2, a1
+ # Activates a-1, but not b-1 and b-2
assert_require 'test_gem_require_a'
+ assert_equal %w[a-1], loaded_spec_names
+ assert $LOAD_PATH.include? a1.load_paths[0]
+ refute $LOAD_PATH.include? b1.load_paths[0]
+ refute $LOAD_PATH.include? b2.load_paths[0]
+
assert_equal unresolved_names, ["b (>= 1)"]
- refute require('benchmark'), "benchmark should have already been loaded"
+ # The require('benchmark') below will activate b-2. However, its
+ # lib/benchmark.rb won't ever be loaded. The reason is MRI sees that even
+ # though b-2 is earlier in $LOAD_PATH it already loaded a benchmark.rb file
+ # and that still exists in $LOAD_PATH (further down),
+ # and as a result #gem_original_require returns false.
+ refute require('benchmark'), "the benchmark stdlib should be recognized as already loaded"
+
+ assert_includes $LOAD_PATH, b2.load_paths[0]
+ assert_includes $LOAD_PATH, rubylibdir
+ message = proc {
+ "this test relies on the b-2 gem lib/ to be before stdlib to make sense\n" +
+ $LOAD_PATH.pretty_inspect
+ }
+ assert_operator $LOAD_PATH.index(b2.load_paths[0]), :<, $LOAD_PATH.index(rubylibdir), message
# We detected that we should activate b-2, so we did so, but
- # then original_require decided "I've already got benchmark.rb" loaded.
- # This case is fine because our lazy loading is provided exactly
+ # then #gem_original_require decided "I've already got some benchmark.rb" loaded.
+ # This case is fine because our lazy loading provided exactly
# the same behavior as eager loading would have.
- assert_equal %w(a-1 b-2), loaded_spec_names
+ assert_equal %w[a-1 b-2], loaded_spec_names
ensure
- $LOAD_PATH.replace lp unless java_platform?
+ $LOAD_PATH.replace lp if load_path_changed
+ end
+
+ def test_activate_via_require_respects_loaded_default_from_default_gems
+ a1 = new_default_spec "a", "1", nil, "a.rb"
+
+ # simulate requiring a default gem before rubygems is loaded
+ Kernel.send(:gem_original_require, "a")
+
+ # simulate registering default specs on loading rubygems
+ install_default_gems a1
+
+ a2 = util_spec "a", "2", nil, "lib/a.rb"
+
+ install_specs a2
+
+ refute_require 'a'
+
+ assert_equal %w[a-1], loaded_spec_names
end
def test_already_activated_direct_conflict
@@ -291,12 +312,12 @@ class TestGemRequire < Gem::TestCase
a1.activate
c1.activate
- assert_equal %w(a-1 c-1), loaded_spec_names
+ assert_equal %w[a-1 c-1], loaded_spec_names
assert_equal ["b (> 0)"], unresolved_names
assert require("ib")
- assert_equal %w(a-1 b-1 c-1), loaded_spec_names
+ assert_equal %w[a-1 b-1 c-1], loaded_spec_names
assert_equal [], unresolved_names
end
@@ -313,10 +334,10 @@ class TestGemRequire < Gem::TestCase
a1.activate
c1.activate
- assert_equal %w(a-1 c-1), loaded_spec_names
+ assert_equal %w[a-1 c-1], loaded_spec_names
assert_equal ["b (> 0)", "x (> 0)"], unresolved_names
- e = assert_raises(Gem::LoadError) do
+ e = assert_raise(Gem::LoadError) do
require("ib")
end
@@ -336,10 +357,10 @@ class TestGemRequire < Gem::TestCase
a1.activate
c1.activate
- assert_equal %w(a-1 c-1), loaded_spec_names
+ assert_equal %w[a-1 c-1], loaded_spec_names
assert_equal ["b (> 0)"], unresolved_names
- e = assert_raises(Gem::LoadError) do
+ e = assert_raise(Gem::LoadError) do
require("ib")
end
@@ -362,26 +383,26 @@ class TestGemRequire < Gem::TestCase
# Remove an old default gem version directly from disk as if someone ran
# gem cleanup.
- FileUtils.rm_rf(File.join @default_dir, "#{b1.full_name}")
- FileUtils.rm_rf(File.join @default_spec_dir, "#{b1.full_name}.gemspec")
+ FileUtils.rm_rf(File.join @gemhome, "#{b1.full_name}")
+ FileUtils.rm_rf(File.join @gemhome, "specifications", "default", "#{b1.full_name}.gemspec")
# Require gems that have not been removed.
assert_require 'a/b'
- assert_equal %w(a-1.0), loaded_spec_names
+ assert_equal %w[a-1.0], loaded_spec_names
assert_require 'b/d'
- assert_equal %w(a-1.0 b-2.0), loaded_spec_names
+ assert_equal %w[a-1.0 b-2.0], loaded_spec_names
end
def test_require_doesnt_traverse_development_dependencies
a = util_spec("a#{$$}", "1", nil, "lib/a#{$$}.rb")
z = util_spec("z", "1", "w" => "> 0")
- w1 = util_spec("w", "1") { |s| s.add_development_dependency "non-existent" }
- w2 = util_spec("w", "2") { |s| s.add_development_dependency "non-existent" }
+ w1 = util_spec("w", "1") {|s| s.add_development_dependency "non-existent" }
+ w2 = util_spec("w", "2") {|s| s.add_development_dependency "non-existent" }
install_specs a, w1, w2, z
assert gem("z")
- assert_equal %w(z-1), loaded_spec_names
+ assert_equal %w[z-1], loaded_spec_names
assert_equal ["w (> 0)"], unresolved_names
assert require("a#{$$}")
@@ -390,15 +411,15 @@ class TestGemRequire < Gem::TestCase
def test_default_gem_only
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
- install_default_specs(default_gem_spec)
+ install_default_gems(default_gem_spec)
assert_require "default/gem"
- assert_equal %w(default-2.0.0.0), loaded_spec_names
+ assert_equal %w[default-2.0.0.0], loaded_spec_names
end
def test_default_gem_require_activates_just_once
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
- install_default_specs(default_gem_spec)
+ install_default_gems(default_gem_spec)
assert_require "default/gem"
@@ -423,40 +444,90 @@ class TestGemRequire < Gem::TestCase
end
def test_realworld_default_gem
- testing_ruby_repo = !ENV["GEM_COMMAND"].nil?
- skip "this test can't work under ruby-core setup" if testing_ruby_repo || java_platform?
+ omit "this test can't work under ruby-core setup" if testing_ruby_repo?
cmd = <<-RUBY
$stderr = $stdout
require "json"
puts Gem.loaded_specs["json"]
RUBY
- output = Gem::Util.popen(Gem.ruby, "-e", cmd).strip
+ output = Gem::Util.popen(*ruby_with_rubygems_in_load_path, "-e", cmd).strip
+ assert $?.success?
+ refute_empty output
+ end
+
+ def test_realworld_upgraded_default_gem
+ omit "this test can't work under ruby-core setup" if testing_ruby_repo?
+
+ newer_json = util_spec("json", "999.99.9", nil, ["lib/json.rb"])
+ install_gem newer_json
+
+ path = "#{@tempdir}/test_realworld_upgraded_default_gem.rb"
+ code = <<-RUBY
+ $stderr = $stdout
+ require "json"
+ puts Gem.loaded_specs["json"].version
+ puts $LOADED_FEATURES
+ RUBY
+ File.write(path, code)
+
+ output = Gem::Util.popen({ 'GEM_HOME' => @gemhome }, *ruby_with_rubygems_in_load_path, path).strip
+ assert $?.success?
refute_empty output
+ assert_equal "999.99.9", output.lines[0].chomp
+ # Make sure only files from the newer json gem are loaded, and no files from the default json gem
+ assert_equal ["#{@gemhome}/gems/json-999.99.9/lib/json.rb"], output.lines.grep(%r{/gems/json-}).map(&:chomp)
end
def test_default_gem_and_normal_gem
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
- install_default_specs(default_gem_spec)
+ install_default_gems(default_gem_spec)
normal_gem_spec = util_spec("default", "3.0", nil,
"lib/default/gem.rb")
install_specs(normal_gem_spec)
assert_require "default/gem"
- assert_equal %w(default-3.0), loaded_spec_names
+ assert_equal %w[default-3.0], loaded_spec_names
+ end
+
+ def test_normal_gems_with_overridden_load_error_message
+ normal_gem_spec = util_spec("normal", "3.0", nil, "lib/normal/gem.rb")
+
+ install_specs(normal_gem_spec)
+
+ File.write("require_with_overridden_load_error_message.rb", <<-RUBY)
+ LoadError.class_eval do
+ def message
+ "Overridden message"
+ end
+ end
+
+ require 'normal/gem'
+ RUBY
+
+ require "open3"
+
+ output, exit_status = Open3.capture2e(
+ { "GEM_HOME" => Gem.paths.home },
+ *ruby_with_rubygems_in_load_path,
+ "-r",
+ "./require_with_overridden_load_error_message.rb"
+ )
+
+ assert exit_status.success?, "Require failed due to #{output}"
end
def test_default_gem_prerelease
default_gem_spec = new_default_spec("default", "2.0.0",
nil, "default/gem.rb")
- install_default_specs(default_gem_spec)
+ install_default_gems(default_gem_spec)
normal_gem_higher_prerelease_spec = util_spec("default", "3.0.0.rc2", nil,
"lib/default/gem.rb")
- install_default_specs(normal_gem_higher_prerelease_spec)
+ install_default_gems(normal_gem_higher_prerelease_spec)
assert_require "default/gem"
- assert_equal %w(default-3.0.0.rc2), loaded_spec_names
+ assert_equal %w[default-3.0.0.rc2], loaded_spec_names
end
def loaded_spec_names
@@ -470,10 +541,8 @@ class TestGemRequire < Gem::TestCase
def test_try_activate_error_unlocks_require_monitor
silence_warnings do
class << ::Gem
-
alias old_try_activate try_activate
def try_activate(*); raise 'raised from try_activate'; end
-
end
end
@@ -484,9 +553,7 @@ class TestGemRequire < Gem::TestCase
ensure
silence_warnings do
class << ::Gem
-
alias try_activate old_try_activate
-
end
end
Kernel::RUBYGEMS_ACTIVATION_MONITOR.exit
@@ -495,14 +562,14 @@ class TestGemRequire < Gem::TestCase
def test_require_when_gem_defined
default_gem_spec = new_default_spec("default", "2.0.0.0",
nil, "default/gem.rb")
- install_default_specs(default_gem_spec)
+ install_default_gems(default_gem_spec)
c = Class.new do
def self.gem(*args)
raise "received #gem with #{args.inspect}"
end
end
assert c.send(:require, "default/gem")
- assert_equal %w(default-2.0.0.0), loaded_spec_names
+ assert_equal %w[default-2.0.0.0], loaded_spec_names
end
def test_require_default_when_gem_defined
@@ -514,7 +581,7 @@ class TestGemRequire < Gem::TestCase
end
end
assert c.send(:require, "a#{$$}")
- assert_equal %W(a#{$$}-1), loaded_spec_names
+ assert_equal %W[a#{$$}-1], loaded_spec_names
end
def test_require_bundler
@@ -535,7 +602,7 @@ class TestGemRequire < Gem::TestCase
b2a = util_spec('bundler', '2.a', nil, "lib/bundler/setup.rb")
install_specs b1, b2a
- e = assert_raises Gem::MissingSpecVersionError do
+ e = assert_raise Gem::MissingSpecVersionError do
gem('bundler')
end
assert_match "Could not find 'bundler' (55) required by reason.", e.message
@@ -558,36 +625,79 @@ class TestGemRequire < Gem::TestCase
if RUBY_VERSION >= "2.5"
["", "Kernel."].each do |prefix|
define_method "test_no_kernel_require_in_#{prefix.tr(".", "_")}warn_with_uplevel" do
- lib = File.realpath("../../../lib", __FILE__)
Dir.mktmpdir("warn_test") do |dir|
File.write(dir + "/sub.rb", "#{prefix}warn 'uplevel', 'test', uplevel: 1\n")
File.write(dir + "/main.rb", "require 'sub'\n")
_, err = capture_subprocess_io do
- system(@@ruby, "-w", "--disable=gems", "-I", lib, "-C", dir, "-I.", "main.rb")
+ system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb")
end
assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err)
_, err = capture_subprocess_io do
- system(@@ruby, "-w", "--enable=gems", "-I", lib, "-C", dir, "-I.", "main.rb")
+ system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb")
end
assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err)
end
end
define_method "test_no_other_behavioral_changes_with_#{prefix.tr(".", "_")}warn" do
- lib = File.realpath("../../../lib", __FILE__)
Dir.mktmpdir("warn_test") do |dir|
File.write(dir + "/main.rb", "#{prefix}warn({x:1}, {y:2}, [])\n")
_, err = capture_subprocess_io do
- system(@@ruby, "-w", "--disable=gems", "-I", lib, "-C", dir, "main.rb")
+ system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb")
end
assert_match(/{:x=>1}\n{:y=>2}\n$/, err)
_, err = capture_subprocess_io do
- system(@@ruby, "-w", "--enable=gems", "-I", lib, "-C", dir, "main.rb")
+ system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb")
end
assert_match(/{:x=>1}\n{:y=>2}\n$/, err)
end
end
end
+
+ def test_no_crash_when_overriding_warn_with_warning_module
+ Dir.mktmpdir("warn_test") do |dir|
+ File.write(dir + "/main.rb", "module Warning; def warn(str); super; end; end; warn 'Foo Bar'")
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb")
+ end
+ assert_match(/Foo Bar\n$/, err)
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb")
+ end
+ assert_match(/Foo Bar\n$/, err)
+ end
+ end
+
+ def test_expected_backtrace_location_when_inheriting_from_basic_object_and_including_kernel
+ Dir.mktmpdir("warn_test") do |dir|
+ File.write(dir + "/main.rb", "\nrequire 'sub'\n")
+ File.write(dir + "/sub.rb", <<-'RUBY')
+ require 'rubygems'
+ class C < BasicObject
+ include ::Kernel
+ def deprecated
+ warn "This is a deprecated method", uplevel: 2
+ end
+ end
+ C.new.deprecated
+ RUBY
+
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb")
+ end
+ assert_match(/main\.rb:2: warning: This is a deprecated method$/, err)
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb")
+ end
+ assert_match(/main\.rb:2: warning: This is a deprecated method$/, err)
+ end
+ end
+ end
+
+ private
+
+ def testing_ruby_repo?
+ !ENV["GEM_COMMAND"].nil?
end
def silence_warnings
@@ -621,12 +731,12 @@ class TestGemRequire < Gem::TestCase
spec.files += ["extconf.rb", "depend", "#{name}.c"]
so = File.join(spec.gem_dir, "#{name}.#{RbConfig::CONFIG["DLEXT"]}")
- refute_path_exists so
+ assert_path_not_exist so
path = Gem::Package.build spec
installer = Gem::Installer.at path
installer.install
- assert_path_exists so
+ assert_path_exist so
spec.gem_dir
end
@@ -638,9 +748,8 @@ class TestGemRequire < Gem::TestCase
a_rb = File.join dash_i_lib_arg, "#{name}.rb"
FileUtils.mkdir_p File.dirname a_rb
- File.open(a_rb, 'w') { |f| f.write "# #{name}.rb" }
+ File.open(a_rb, 'w') {|f| f.write "# #{name}.rb" }
dash_i_lib_arg
end
-
end
diff --git a/test/rubygems/test_rubygems.rb b/test/rubygems/test_rubygems.rb
new file mode 100644
index 0000000000..493b9fdf4a
--- /dev/null
+++ b/test/rubygems/test_rubygems.rb
@@ -0,0 +1,44 @@
+require_relative 'helper'
+
+class GemTest < Gem::TestCase
+ def test_rubygems_normal_behaviour
+ _ = Gem::Util.popen(*ruby_with_rubygems_in_load_path, '-e', "'require \"rubygems\"'", {:err => [:child, :out]}).strip
+ assert $?.success?
+ end
+
+ def test_operating_system_other_exceptions
+ pend "does not apply to truffleruby" if RUBY_ENGINE == 'truffleruby'
+
+ path = util_install_operating_system_rb <<-RUBY
+ intentionally_not_implemented_method
+ RUBY
+
+ output = Gem::Util.popen(*ruby_with_rubygems_and_fake_operating_system_in_load_path(path), '-e', "'require \"rubygems\"'", {:err => [:child, :out]}).strip
+ assert !$?.success?
+ assert_includes output, "undefined local variable or method `intentionally_not_implemented_method'"
+ assert_includes output, "Loading the rubygems/defaults/operating_system.rb file caused an error. " \
+ "This file is owned by your OS, not by rubygems upstream. " \
+ "Please find out which OS package this file belongs to and follow the guidelines from your OS to report " \
+ "the problem and ask for help."
+ end
+
+ private
+
+ def util_install_operating_system_rb(content)
+ dir_lib = Dir.mktmpdir("test_operating_system_lib", @tempdir)
+ dir_lib_arg = File.join dir_lib
+
+ dir_lib_rubygems_defaults_arg = File.join dir_lib_arg, "lib", "rubygems", "defaults"
+ FileUtils.mkdir_p dir_lib_rubygems_defaults_arg
+
+ operating_system_rb = File.join dir_lib_rubygems_defaults_arg, "operating_system.rb"
+
+ File.open(operating_system_rb, 'w') {|f| f.write content }
+
+ File.join dir_lib_arg, "lib"
+ end
+
+ def ruby_with_rubygems_and_fake_operating_system_in_load_path(operating_system_path)
+ [Gem.ruby, "-I", operating_system_path, "-I" , $LOAD_PATH.find{|p| p == File.dirname($LOADED_FEATURES.find{|f| f.end_with?("/rubygems.rb") }) }]
+ end
+end
diff --git a/test/rubygems/utilities.rb b/test/rubygems/utilities.rb
new file mode 100644
index 0000000000..20416fe70b
--- /dev/null
+++ b/test/rubygems/utilities.rb
@@ -0,0 +1,371 @@
+# frozen_string_literal: true
+require 'tempfile'
+require 'rubygems'
+require 'rubygems/remote_fetcher'
+
+##
+# A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP
+# requests when testing code that uses RubyGems.
+#
+# Example:
+#
+# @fetcher = Gem::FakeFetcher.new
+# @fetcher.data['http://gems.example.com/yaml'] = source_index.to_yaml
+# Gem::RemoteFetcher.fetcher = @fetcher
+#
+# use nested array if multiple response is needed
+#
+# @fetcher.data['http://gems.example.com/sequence'] = [['Success', 200, 'OK'], ['Failed', 401, 'Unauthorized']]
+#
+# @fetcher.fetch_path('http://gems.example.com/sequence') # => ['Success', 200, 'OK']
+# @fetcher.fetch_path('http://gems.example.com/sequence') # => ['Failed', 401, 'Unauthorized']
+#
+# # invoke RubyGems code
+#
+# paths = @fetcher.paths
+# assert_equal 'http://gems.example.com/yaml', paths.shift
+# assert paths.empty?, paths.join(', ')
+#
+# See RubyGems' tests for more examples of FakeFetcher.
+
+class Gem::FakeFetcher
+ attr_reader :data
+ attr_reader :last_request
+ attr_accessor :paths
+
+ def initialize
+ @data = {}
+ @paths = []
+ end
+
+ def find_data(path)
+ return Gem.read_binary path.path if URI === path and 'file' == path.scheme
+
+ if URI === path and "URI::#{path.scheme.upcase}" != path.class.name
+ raise ArgumentError,
+ "mismatch for scheme #{path.scheme} and class #{path.class}"
+ end
+
+ path = path.to_s
+ @paths << path
+ raise ArgumentError, 'need full URI' unless path.start_with?("https://", "http://")
+
+ unless @data.key? path
+ raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
+ end
+
+ if @data[path].kind_of?(Array) && @data[path].first.kind_of?(Array)
+ @data[path].shift
+ else
+ @data[path]
+ end
+ end
+
+ def fetch_path(path, mtime = nil, head = false)
+ data = find_data(path)
+
+ if data.respond_to?(:call)
+ data.call
+ else
+ if path.to_s.end_with?(".gz") and not data.nil? and not data.empty?
+ data = Gem::Util.gunzip data
+ end
+ data
+ end
+ end
+
+ def cache_update_path(uri, path = nil, update = true)
+ if data = fetch_path(uri)
+ File.open(path, 'wb') {|io| io.write data } if path and update
+ data
+ else
+ Gem.read_binary(path) if path
+ end
+ end
+
+ # Thanks, FakeWeb!
+ def open_uri_or_path(path)
+ data = find_data(path)
+ body, code, msg = data
+
+ response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
+ response.instance_variable_set(:@body, body)
+ response.instance_variable_set(:@read, true)
+ response
+ end
+
+ def request(uri, request_class, last_modified = nil)
+ data = find_data(uri)
+ body, code, msg = (data.respond_to?(:call) ? data.call : data)
+
+ @last_request = request_class.new uri.request_uri
+ yield @last_request if block_given?
+
+ response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
+ response.instance_variable_set(:@body, body)
+ response.instance_variable_set(:@read, true)
+ response
+ end
+
+ def pretty_print(q) # :nodoc:
+ q.group 2, '[FakeFetcher', ']' do
+ q.breakable
+ q.text 'URIs:'
+
+ q.breakable
+ q.pp @data.keys
+ end
+ end
+
+ def fetch_size(path)
+ path = path.to_s
+ @paths << path
+
+ raise ArgumentError, 'need full URI' unless path =~ %r{^http://}
+
+ unless @data.key? path
+ raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
+ end
+
+ data = @data[path]
+
+ data.respond_to?(:call) ? data.call : data.length
+ end
+
+ def download(spec, source_uri, install_dir = Gem.dir)
+ name = File.basename spec.cache_file
+ path = if Dir.pwd == install_dir # see fetch_command
+ install_dir
+ else
+ File.join install_dir, "cache"
+ end
+
+ path = File.join path, name
+
+ if source_uri =~ /^http/
+ File.open(path, "wb") do |f|
+ f.write fetch_path(File.join(source_uri, "gems", name))
+ end
+ else
+ FileUtils.cp source_uri, path
+ end
+
+ path
+ end
+
+ def download_to_cache(dependency)
+ found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dependency
+
+ return if found.empty?
+
+ spec, source = found.first
+
+ download spec, source.uri.to_s
+ end
+end
+
+# :stopdoc:
+class Gem::RemoteFetcher
+ def self.fetcher=(fetcher)
+ @fetcher = fetcher
+ end
+end
+# :startdoc:
+
+##
+# The SpecFetcherSetup allows easy setup of a remote source in RubyGems tests:
+#
+# spec_fetcher do |f|
+# f.gem 'a', 1
+# f.spec 'a', 2
+# f.gem 'b', 1' 'a' => '~> 1.0'
+# end
+#
+# The above declaration creates two gems, a-1 and b-1, with a dependency from
+# b to a. The declaration creates an additional spec a-2, but no gem for it
+# (so it cannot be installed).
+#
+# After the gems are created they are removed from Gem.dir.
+
+class Gem::TestCase::SpecFetcherSetup
+ ##
+ # Executes a SpecFetcher setup block. Yields an instance then creates the
+ # gems and specifications defined in the instance.
+
+ def self.declare(test, repository)
+ setup = new test, repository
+
+ yield setup
+
+ setup.execute
+ end
+
+ def initialize(test, repository) # :nodoc:
+ @test = test
+ @repository = repository
+
+ @gems = {}
+ @downloaded = []
+ @installed = []
+ @operations = []
+ end
+
+ ##
+ # Returns a Hash of created Specification full names and the corresponding
+ # Specification.
+
+ def created_specs
+ created = {}
+
+ @gems.keys.each do |spec|
+ created[spec.full_name] = spec
+ end
+
+ created
+ end
+
+ ##
+ # Creates any defined gems or specifications
+
+ def execute # :nodoc:
+ execute_operations
+
+ setup_fetcher
+
+ created_specs
+ end
+
+ def execute_operations # :nodoc:
+ @operations.each do |operation, *arguments|
+ block = arguments.pop
+ case operation
+ when :gem then
+ spec, gem = @test.util_gem(*arguments, &block)
+
+ write_spec spec
+
+ @gems[spec] = gem
+ @installed << spec
+ when :download then
+ spec, gem = @test.util_gem(*arguments, &block)
+
+ @gems[spec] = gem
+ @downloaded << spec
+ when :spec then
+ spec = @test.util_spec(*arguments, &block)
+
+ write_spec spec
+
+ @gems[spec] = nil
+ @installed << spec
+ end
+ end
+ end
+
+ ##
+ # Creates a gem with +name+, +version+ and +deps+. The created gem can be
+ # downloaded and installed.
+ #
+ # The specification will be yielded before gem creation for customization,
+ # but only the block or the dependencies may be set, not both.
+
+ def gem(name, version, dependencies = nil, &block)
+ @operations << [:gem, name, version, dependencies, block]
+ end
+
+ ##
+ # Creates a gem with +name+, +version+ and +deps+. The created gem is
+ # downloaded in to the cache directory but is not installed
+ #
+ # The specification will be yielded before gem creation for customization,
+ # but only the block or the dependencies may be set, not both.
+
+ def download(name, version, dependencies = nil, &block)
+ @operations << [:download, name, version, dependencies, block]
+ end
+
+ ##
+ # Creates a legacy platform spec with the name 'pl' and version 1
+
+ def legacy_platform
+ spec 'pl', 1 do |s|
+ s.platform = Gem::Platform.new 'i386-linux'
+ s.instance_variable_set :@original_platform, 'i386-linux'
+ end
+ end
+
+ def setup_fetcher # :nodoc:
+ require 'zlib'
+ require 'socket'
+ require 'rubygems/remote_fetcher'
+
+ unless @test.fetcher
+ @test.fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @test.fetcher
+ end
+
+ Gem::Specification.reset
+
+ begin
+ gem_repo, @test.gem_repo = @test.gem_repo, @repository
+ @test.uri = URI @repository
+
+ @test.util_setup_spec_fetcher(*@downloaded)
+ ensure
+ @test.gem_repo = gem_repo
+ @test.uri = URI gem_repo
+ end
+
+ @gems.each do |spec, gem|
+ next unless gem
+
+ @test.fetcher.data["#{@repository}gems/#{spec.file_name}"] =
+ Gem.read_binary(gem)
+
+ FileUtils.cp gem, spec.cache_file
+ end
+ end
+
+ ##
+ # Creates a spec with +name+, +version+ and +deps+. The created gem can be
+ # downloaded and installed.
+ #
+ # The specification will be yielded before creation for customization,
+ # but only the block or the dependencies may be set, not both.
+
+ def spec(name, version, dependencies = nil, &block)
+ @operations << [:spec, name, version, dependencies, block]
+ end
+
+ def write_spec(spec) # :nodoc:
+ File.open spec.spec_file, 'w' do |io|
+ io.write spec.to_ruby_for_cache
+ end
+ end
+end
+
+##
+# A StringIO duck-typed class that uses Tempfile instead of String as the
+# backing store.
+#
+# This class was added to flush out problems in Rubinius' IO implementation.
+
+class TempIO < Tempfile
+ ##
+ # Creates a new TempIO that will be initialized to contain +string+.
+
+ def initialize(string = '')
+ super "TempIO"
+ binmode
+ write string
+ rewind
+ end
+
+ ##
+ # The content of the TempIO as a String.
+
+ def string
+ flush
+ Gem.read_binary path
+ end
+end
diff --git a/test/sdbm/test_sdbm.rb b/test/sdbm/test_sdbm.rb
deleted file mode 100644
index 6cea36d3a5..0000000000
--- a/test/sdbm/test_sdbm.rb
+++ /dev/null
@@ -1,544 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'tmpdir'
-
-begin
- require 'sdbm'
-rescue LoadError
-end
-
-class TestSDBM < Test::Unit::TestCase
- def setup
- @tmpdir = Dir.mktmpdir("tmptest_sdbm")
- @prefix = "tmptest_sdbm_#{$$}"
- @path = "#{@tmpdir}/#{@prefix}_"
- assert_instance_of(SDBM, @sdbm = SDBM.new(@path))
- end
- def teardown
- assert_nil(@sdbm.close)
- ObjectSpace.each_object(SDBM) do |obj|
- obj.close unless obj.closed?
- end
- FileUtils.remove_entry_secure @tmpdir
- end
-
- def check_size(expect, sdbm=@sdbm)
- assert_equal(expect, sdbm.size)
- n = 0
- sdbm.each { n+=1 }
- assert_equal(expect, n)
- if expect == 0
- assert_equal(true, sdbm.empty?)
- else
- assert_equal(false, sdbm.empty?)
- end
- end
-
- def test_version
- assert(! SDBM.const_defined?(:VERSION))
- end
-
- def test_s_new_has_no_block
- # SDBM.new ignore the block
- foo = true
- assert_instance_of(SDBM, sdbm = SDBM.new("#{@tmpdir}/#{@prefix}") { foo = false })
- assert_equal(foo, true)
- assert_nil(sdbm.close)
- end
- def test_s_open_no_create
- assert_nil(sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", nil))
- ensure
- sdbm.close if sdbm
- end
- def test_s_open_with_block
- assert_equal(SDBM.open("#{@tmpdir}/#{@prefix}") { :foo }, :foo)
- end
-=begin
- # Is it guaranteed on many OS?
- def test_s_open_lock_one_process
- # locking on one process
- assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0644))
- assert_raise(Errno::EWOULDBLOCK) {
- begin
- SDBM.open("#{@tmpdir}/#{@prefix}", 0644)
- rescue Errno::EAGAIN
- raise Errno::EWOULDBLOCK
- end
- }
- end
-=end
-
- def open_db_child(dbname, *opts)
- opts = [0644, *opts].map(&:inspect).join(', ')
- args = [EnvUtil.rubybin, "-rsdbm", <<-SRC, dbname]
- STDOUT.sync = true
- gdbm = SDBM.open(ARGV.shift, #{opts})
- puts sdbm.class
- gets
- SRC
- IO.popen(args, "r+") do |f|
- dbclass = f.gets
- assert_equal("SDBM", dbclass.chomp)
- yield
- end
- end
-
- def test_s_open_nolock
- dbname = "#{@tmpdir}/#{@prefix}"
-
- open_db_child(dbname, SDBM::NOLOCK) do
- assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
- SDBM.open(dbname, 0644) {|sdbm|
- assert_instance_of(SDBM, sdbm)
- }
- }
- end
-
- p Dir.glob("#{@tmpdir}/#{@prefix}*") if $DEBUG
-
- open_db_child(dbname) do
- assert_no_exception(Errno::EWOULDBLOCK, Errno::EAGAIN, Errno::EACCES) {
- # this test is failed on Cygwin98 (???)
- SDBM.open(dbname, 0644, SDBM::NOLOCK) {|sdbm|
- assert_instance_of(SDBM, sdbm)
- }
- }
- end
- end if defined? SDBM::NOLOCK # sdbm 1.8.0 specific
-
- def test_s_open_error
- skip "doesn't support to avoid read access by owner on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
- skip "skipped because root can open anything" if Process.uid == 0
- assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}", 0))
- assert_raise(Errno::EACCES) {
- SDBM.open("#{@tmpdir}/#{@prefix}", 0)
- }
- sdbm.close
- end
-
- def test_close
- assert_instance_of(SDBM, sdbm = SDBM.open("#{@tmpdir}/#{@prefix}"))
- assert_nil(sdbm.close)
-
- # closed SDBM file
- assert_raise(SDBMError) { sdbm.close }
- end
-
- def test_aref
- assert_equal('bar', @sdbm['foo'] = 'bar')
- assert_equal('bar', @sdbm['foo'])
-
- assert_nil(@sdbm['bar'])
- end
-
- def test_fetch
- assert_equal('bar', @sdbm['foo']='bar')
- assert_equal('bar', @sdbm.fetch('foo'))
-
- # key not found
- assert_raise(IndexError) {
- @sdbm.fetch('bar')
- }
-
- # test for `ifnone' arg
- assert_equal('baz', @sdbm.fetch('bar', 'baz'))
-
- # test for `ifnone' block
- assert_equal('foobar', @sdbm.fetch('bar') {|key| 'foo' + key })
- end
-
- def test_aset
- num = 0
- 2.times {|i|
- assert_equal('foo', @sdbm['foo'] = 'foo')
- assert_equal('foo', @sdbm['foo'])
- assert_equal('bar', @sdbm['foo'] = 'bar')
- assert_equal('bar', @sdbm['foo'])
-
- num += 1 if i == 0
- assert_equal(num, @sdbm.size)
-
- # assign nil
- assert_equal('', @sdbm['bar'] = '')
- assert_equal('', @sdbm['bar'])
-
- num += 1 if i == 0
- assert_equal(num, @sdbm.size)
-
- # empty string
- assert_equal('', @sdbm[''] = '')
- assert_equal('', @sdbm[''])
-
- num += 1 if i == 0
- assert_equal(num, @sdbm.size)
-
- # Integer
- assert_equal('200', @sdbm['100'] = '200')
- assert_equal('200', @sdbm['100'])
-
- num += 1 if i == 0
- assert_equal(num, @sdbm.size)
-
- # Big key and value
- assert_equal('y' * 100, @sdbm['x' * 100] = 'y' * 100)
- assert_equal('y' * 100, @sdbm['x' * 100])
-
- num += 1 if i == 0
- assert_equal(num, @sdbm.size)
- }
- end
-
- def test_key
- assert_equal('bar', @sdbm['foo'] = 'bar')
- assert_equal('foo', @sdbm.key('bar'))
- assert_nil(@sdbm['bar'])
- end
-
- def test_values_at
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
- assert_equal(values.reverse, @sdbm.values_at(*keys.reverse))
- end
-
- def test_select_with_block
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
- ret = @sdbm.select {|k,v|
- assert_equal(k.upcase, v)
- k != "bar"
- }
- assert_equal([['baz', 'BAZ'], ['foo', 'FOO']],
- ret.sort)
- end
-
- def test_length
- num = 10
- assert_equal(0, @sdbm.size)
- num.times {|i|
- i = i.to_s
- @sdbm[i] = i
- }
- assert_equal(num, @sdbm.size)
-
- @sdbm.shift
-
- assert_equal(num - 1, @sdbm.size)
- end
-
- def test_empty?
- assert_equal(true, @sdbm.empty?)
- @sdbm['foo'] = 'FOO'
- assert_equal(false, @sdbm.empty?)
- end
-
- def test_each_pair
- n = 0
- @sdbm.each_pair { n += 1 }
- assert_equal(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- n = 0
- ret = @sdbm.each_pair {|key, val|
- assert_not_nil(i = keys.index(key))
- assert_equal(val, values[i])
-
- n += 1
- }
- assert_equal(keys.size, n)
- assert_equal(@sdbm, ret)
- end
-
- def test_each_value
- n = 0
- @sdbm.each_value { n += 1 }
- assert_equal(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- n = 0
- ret = @sdbm.each_value {|val|
- assert_not_nil(key = @sdbm.key(val))
- assert_not_nil(i = keys.index(key))
- assert_equal(val, values[i])
-
- n += 1
- }
- assert_equal(keys.size, n)
- assert_equal(@sdbm, ret)
- end
-
- def test_each_key
- n = 0
- @sdbm.each_key { n += 1 }
- assert_equal(0, n)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- n = 0
- ret = @sdbm.each_key {|key|
- assert_not_nil(i = keys.index(key))
- assert_equal(@sdbm[key], values[i])
-
- n += 1
- }
- assert_equal(keys.size, n)
- assert_equal(@sdbm, ret)
- end
-
- def test_keys
- assert_equal([], @sdbm.keys)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- assert_equal(keys.sort, @sdbm.keys.sort)
- assert_equal(values.sort, @sdbm.values.sort)
- end
-
- def test_values
- test_keys
- end
-
- def test_shift
- assert_nil(@sdbm.shift)
- assert_equal(0, @sdbm.size)
-
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- ret_keys = []
- ret_values = []
- while ret = @sdbm.shift
- ret_keys.push ret[0]
- ret_values.push ret[1]
-
- assert_equal(keys.size - ret_keys.size, @sdbm.size)
- end
-
- assert_equal(keys.sort, ret_keys.sort)
- assert_equal(values.sort, ret_values.sort)
- end
-
- def test_delete
- keys = %w(foo bar baz)
- values = %w(FOO BAR BAZ)
- key = keys[1]
-
- assert_nil(@sdbm.delete(key))
- assert_equal(0, @sdbm.size)
-
- @sdbm[keys[0]], @sdbm[keys[1]], @sdbm[keys[2]] = values
-
- assert_equal('BAR', @sdbm.delete(key))
- assert_nil(@sdbm[key])
- assert_equal(2, @sdbm.size)
-
- assert_nil(@sdbm.delete(key))
- end
- def test_delete_with_block
- key = 'no called block'
- @sdbm[key] = 'foo'
- assert_equal('foo', @sdbm.delete(key) {|k| k.replace 'called block'; :blockval})
- assert_equal(0, @sdbm.size)
-
- key = 'no called block'
- assert_equal(:blockval, @sdbm.delete(key) {|k| k.replace 'called block'; :blockval})
- assert_equal(0, @sdbm.size)
- end
-
- def test_delete_if
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
-
- ret = @sdbm.delete_if {|key, val| key.to_i < 50}
- assert_equal(@sdbm, ret)
- check_size(50, @sdbm)
-
- ret = @sdbm.delete_if {|key, val| key.to_i >= 50}
- assert_equal(@sdbm, ret)
- check_size(0, @sdbm)
-
- # break
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
- check_size(100, @sdbm)
- n = 0;
- @sdbm.delete_if {|key, val|
- break if n > 50
- n+=1
- true
- }
- assert_equal(51, n)
- check_size(49, @sdbm)
-
- @sdbm.clear
-
- # raise
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
- check_size(100, @sdbm)
- n = 0;
- begin
- @sdbm.delete_if {|key, val|
- raise "runtime error" if n > 50
- n+=1
- true
- }
- rescue RuntimeError
- end
- assert_equal(51, n)
- check_size(49, @sdbm)
- end
-
- def test_reject
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
-
- hash = @sdbm.reject {|key, val| key.to_i < 50}
- assert_instance_of(Hash, hash)
- assert_equal(100, @sdbm.size)
-
- assert_equal(50, hash.size)
- hash.each_pair {|key,val|
- assert_equal(false, key.to_i < 50)
- assert_equal(key, val)
- }
-
- hash = @sdbm.reject {|key, val| key.to_i < 100}
- assert_instance_of(Hash, hash)
- assert_equal(true, hash.empty?)
- end
-
- def test_clear
- v = "1"
- 100.times {v = v.next; @sdbm[v] = v}
-
- assert_equal(@sdbm, @sdbm.clear)
-
- # validate SDBM#size
- i = 0
- @sdbm.each { i += 1 }
- assert_equal(@sdbm.size, i)
- assert_equal(0, i)
- end
-
- def test_invert
- v = "0"
- 100.times {@sdbm[v] = v; v = v.next}
-
- hash = @sdbm.invert
- assert_instance_of(Hash, hash)
- assert_equal(100, hash.size)
- hash.each_pair {|key, val|
- assert_equal(key.to_i, val.to_i)
- }
- end
-
- def test_update
- hash = {}
- v = "0"
- 100.times {v = v.next; hash[v] = v}
-
- @sdbm["101"] = "101"
- @sdbm.update hash
- assert_equal(101, @sdbm.size)
- @sdbm.each_pair {|key, val|
- assert_equal(key.to_i, val.to_i)
- }
- end
-
- def test_replace
- hash = {}
- v = "0"
- 100.times {v = v.next; hash[v] = v}
-
- @sdbm["101"] = "101"
- @sdbm.replace hash
- assert_equal(100, @sdbm.size)
- @sdbm.each_pair {|key, val|
- assert_equal(key.to_i, val.to_i)
- }
- end
-
- def test_haskey?
- assert_equal('bar', @sdbm['foo']='bar')
- assert_equal(true, @sdbm.has_key?('foo'))
- assert_equal(false, @sdbm.has_key?('bar'))
- end
-
- def test_has_value?
- assert_equal('bar', @sdbm['foo']='bar')
- assert_equal(true, @sdbm.has_value?('bar'))
- assert_equal(false, @sdbm.has_value?('foo'))
- end
-
- def test_to_a
- v = "0"
- 100.times {v = v.next; @sdbm[v] = v}
-
- ary = @sdbm.to_a
- assert_instance_of(Array, ary)
- assert_equal(100, ary.size)
- ary.each {|key,val|
- assert_equal(key.to_i, val.to_i)
- }
- end
-
- def test_to_hash
- v = "0"
- 100.times {v = v.next; @sdbm[v] = v}
-
- hash = @sdbm.to_hash
- assert_instance_of(Hash, hash)
- assert_equal(100, hash.size)
- hash.each {|key,val|
- assert_equal(key.to_i, val.to_i)
- }
- end
-
- def test_closed
- assert_equal(false, @sdbm.closed?)
- @sdbm.close
- assert_equal(true, @sdbm.closed?)
- @sdbm = SDBM.new(@path)
- end
-
- def test_readonly
- skip "skipped because root can read anything" if /mswin|mingw/ !~ RUBY_PLATFORM && Process.uid == 0
- @sdbm["bar"] = "baz"
- @sdbm.close
- File.chmod(0444, @path + ".dir")
- File.chmod(0444, @path + ".pag")
- @sdbm = SDBM.new(@path)
- assert_raise(SDBMError) { @sdbm["bar"] = "foo" }
- assert_raise(SDBMError) { @sdbm.delete("bar") }
- assert_raise(SDBMError) { @sdbm.delete_if { true } }
- assert_raise(SDBMError) { @sdbm.clear }
- assert_nil(@sdbm.store("bar", nil))
- end
-
- def test_update2
- obj = Object.new
- def obj.each_pair
- yield []
- end
- assert_raise(ArgumentError) { @sdbm.update(obj) }
- end
-end if defined? SDBM
-
diff --git a/test/socket/test_addrinfo.rb b/test/socket/test_addrinfo.rb
index 92b61ea99e..1421c153a0 100644
--- a/test/socket/test_addrinfo.rb
+++ b/test/socket/test_addrinfo.rb
@@ -103,7 +103,7 @@ class TestSocketAddrinfo < Test::Unit::TestCase
end
def test_error_message
- e = assert_raise_with_message(SocketError, /getaddrinfo:/) do
+ e = assert_raise_with_message(SocketError, /getaddrinfo/) do
Addrinfo.ip("...")
end
m = e.message
@@ -367,7 +367,10 @@ class TestSocketAddrinfo < Test::Unit::TestCase
end
def errors_addrinuse
- [Errno::EADDRINUSE]
+ errs = [Errno::EADDRINUSE]
+ # MinGW fails with "Errno::EACCES: Permission denied - bind(2) for 0.0.0.0:49721"
+ errs << Errno::EACCES if /mingw/ =~ RUBY_PLATFORM
+ errs
end
def test_connect_from
diff --git a/test/socket/test_basicsocket.rb b/test/socket/test_basicsocket.rb
index c8e9b23f83..7b1c9b4a06 100644
--- a/test/socket/test_basicsocket.rb
+++ b/test/socket/test_basicsocket.rb
@@ -159,8 +159,6 @@ class TestSocket_BasicSocket < Test::Unit::TestCase
set_nb = true
buf = String.new
if ssock.respond_to?(:nonblock?)
- assert_not_predicate(ssock, :nonblock?)
- assert_not_predicate(csock, :nonblock?)
csock.nonblock = ssock.nonblock = false
# Linux may use MSG_DONTWAIT to avoid setting O_NONBLOCK
diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb
index f1ec927c4c..b5be0c7cf3 100644
--- a/test/socket/test_socket.rb
+++ b/test/socket/test_socket.rb
@@ -475,7 +475,7 @@ class TestSocket < Test::Unit::TestCase
end while IO.select([r], nil, nil, 0.1).nil?
n
end
- timeout = (RubyVM::MJIT.enabled? ? 120 : 30) # for --jit-wait
+ timeout = (defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? ? 120 : 30) # for --jit-wait
assert_equal([[s1],[],[]], IO.select([s1], nil, nil, timeout))
msg, _, _, stamp = s1.recvmsg
assert_equal("a", msg)
diff --git a/test/socket/test_tcp.rb b/test/socket/test_tcp.rb
index 7962cbe959..9aa716f7ec 100644
--- a/test/socket/test_tcp.rb
+++ b/test/socket/test_tcp.rb
@@ -55,6 +55,26 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
t.close if t && !t.closed?
end
+ def test_initialize_resolv_timeout
+ TCPServer.open("localhost", 0) do |svr|
+ th = Thread.new {
+ c = svr.accept
+ c.close
+ }
+ addr = svr.addr
+ s = TCPSocket.new(addr[3], addr[1], resolv_timeout: 10)
+ th.join
+ ensure
+ s.close()
+ end
+ end
+
+ def test_initialize_connect_timeout
+ assert_raise(Errno::ETIMEDOUT) do
+ TCPSocket.new("192.0.2.1", 80, connect_timeout: 0)
+ end
+ end
+
def test_recvfrom
TCPServer.open("localhost", 0) {|svr|
th = Thread.new {
@@ -109,7 +129,7 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
Thread.new { server.accept.close }
end
client_threads = Array.new(client_threads_count) do
- Thread.new { TCPSocket.open(server.addr[3], server.addr[1]) }
+ Thread.new { TCPSocket.open(server.addr[3], server.addr[1]) {} }
end
client_threads.each(&:join)
accept_threads.each(&:join)
diff --git a/test/socket/test_unix.rb b/test/socket/test_unix.rb
index 6efb1d60ee..8c74d0c939 100644
--- a/test/socket/test_unix.rb
+++ b/test/socket/test_unix.rb
@@ -47,10 +47,16 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
r.close
s1.send_io(s1)
- # klass = UNIXSocket FIXME: [ruby-core:71860] [Bug #11778]
+ klass = UNIXSocket
+ r = s2.recv_io(klass)
+ assert_instance_of klass, r, 'recv_io with proper klass'
+ assert_not_equal s1.fileno, r.fileno
+ r.close
+
+ s1.send_io(s1)
klass = IO
r = s2.recv_io(klass, 'r+')
- assert_instance_of klass, r, 'recv_io with proper klass'
+ assert_instance_of klass, r, 'recv_io with proper klass and mode'
assert_not_equal s1.fileno, r.fileno
r.close
end
@@ -542,16 +548,20 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
def test_getcred_xucred
return if /freebsd|darwin/ !~ RUBY_PLATFORM
- Dir.mktmpdir {|d|
+ Dir.mktmpdir do |d|
sockpath = "#{d}/sock"
serv = Socket.unix_server_socket(sockpath)
- Socket.unix(sockpath)
+ u = Socket.unix(sockpath)
s, = serv.accept
cred = s.getsockopt(0, Socket::LOCAL_PEERCRED)
inspect = cred.inspect
assert_match(/ euid=#{Process.euid} /, inspect)
assert_match(/ \(xucred\)/, inspect)
- }
+ ensure
+ s&.close
+ u&.close
+ serv&.close
+ end
end
def test_sendcred_ucred
diff --git a/test/stringio/test_ractor.rb b/test/stringio/test_ractor.rb
new file mode 100644
index 0000000000..1c334e2c3f
--- /dev/null
+++ b/test/stringio/test_ractor.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class TestStringIOInRactor < Test::Unit::TestCase
+ def setup
+ omit unless defined? Ractor
+ end
+
+ def test_ractor
+ assert_in_out_err([], <<-"end;", ["true"], [])
+ require "stringio"
+ $VERBOSE = nil
+ r = Ractor.new do
+ io = StringIO.new("")
+ io.puts "abc"
+ io.truncate(0)
+ io.puts "def"
+ "\0\0\0\0def\n" == io.string
+ end
+ puts r.take
+ end;
+ end
+end
diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb
index a99ccf4302..e0b4504b54 100644
--- a/test/stringio/test_stringio.rb
+++ b/test/stringio/test_stringio.rb
@@ -187,6 +187,40 @@ class TestStringIO < Test::Unit::TestCase
assert_equal(Encoding::UTF_8, s.encoding, "honor the original encoding over ASCII-8BIT")
end
+ def test_write_encoding_conversion
+ convertible = "\u{3042}"
+ inconvertible = "\u{1f363}"
+ conversion_encoding = Encoding::Windows_31J
+
+ s = StringIO.new.set_encoding(conversion_encoding)
+ s.write(convertible)
+ assert_equal(conversion_encoding, s.string.encoding)
+
+ s = StringIO.new.set_encoding(Encoding::UTF_8)
+ s.write("foo".force_encoding("ISO-8859-1"), convertible)
+ assert_equal(Encoding::UTF_8, s.string.encoding)
+
+ s = StringIO.new.set_encoding(Encoding::US_ASCII)
+ s.write("foo".force_encoding("US-ASCII"), convertible)
+ assert_equal(Encoding::UTF_8, s.string.encoding)
+
+ all_assertions do |a|
+ [
+ inconvertible,
+ convertible + inconvertible,
+ [convertible, inconvertible],
+ ["a", inconvertible],
+ ].each do |data|
+ a.for(data.inspect) do
+ s = StringIO.new.set_encoding(conversion_encoding)
+ assert_raise(Encoding::CompatibilityError) do
+ s.write(*data)
+ end
+ end
+ end
+ end
+ end
+
def test_write_integer_overflow
f = StringIO.new
f.pos = RbConfig::LIMITS["LONG_MAX"]
@@ -412,6 +446,15 @@ class TestStringIO < Test::Unit::TestCase
f.close unless f.closed?
end
+ def test_each_byte_closed
+ f = StringIO.new("1234")
+ assert_equal("1".ord, f.each_byte {|c| f.close; break c })
+ f = StringIO.new("1234")
+ assert_raise(IOError) do
+ f.each_byte { f.close }
+ end
+ end
+
def test_getbyte
f = StringIO.new("1234")
assert_equal("1".ord, f.getbyte)
@@ -486,11 +529,39 @@ class TestStringIO < Test::Unit::TestCase
assert_equal(%w(1 2 3 4), f.each_char.to_a)
end
+ def test_each_char_closed
+ f = StringIO.new("1234")
+ assert_equal("1", f.each_char {|c| f.close; break c })
+ f = StringIO.new("1234")
+ assert_raise(IOError) do
+ f.each_char { f.close }
+ end
+ end
+
def test_each_codepoint
f = StringIO.new("1234")
assert_equal([49, 50, 51, 52], f.each_codepoint.to_a)
end
+ def test_each_codepoint_closed
+ f = StringIO.new("1234")
+ assert_equal("1".ord, f.each_codepoint {|c| f.close; break c })
+ f = StringIO.new("1234")
+ assert_raise(IOError) do
+ f.each_codepoint { f.close }
+ end
+ end
+
+ def test_each_codepoint_enumerator
+ io = StringIO.new('你好построить')
+
+ chinese_part = io.each_codepoint.take(2).pack('U*')
+ russian_part = io.read(40).force_encoding('UTF-8')
+
+ assert_equal("你好", chinese_part)
+ assert_equal("построить", russian_part)
+ end
+
def test_gets2
f = StringIO.new("foo\nbar\nbaz\n")
assert_equal("fo", f.gets(2))
@@ -754,7 +825,7 @@ class TestStringIO < Test::Unit::TestCase
end
def test_overflow
- skip if RbConfig::SIZEOF["void*"] > RbConfig::SIZEOF["long"]
+ omit if RbConfig::SIZEOF["void*"] > RbConfig::SIZEOF["long"]
limit = RbConfig::LIMITS["INTPTR_MAX"] - 0x10
assert_separately(%w[-rstringio], "#{<<-"begin;"}\n#{<<-"end;"}")
begin;
@@ -764,7 +835,7 @@ class TestStringIO < Test::Unit::TestCase
x = "a"*0x100000
break if [x].pack("p").unpack("i!")[0] < 0
ary << x
- skip if ary.size > 100
+ omit if ary.size > 100
end
s = StringIO.new(x)
s.gets("xxx", limit)
diff --git a/test/strscan/test_ractor.rb b/test/strscan/test_ractor.rb
new file mode 100644
index 0000000000..480c1ae8a6
--- /dev/null
+++ b/test/strscan/test_ractor.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class TestStringScannerRactor < Test::Unit::TestCase
+ def setup
+ pend unless defined? Ractor
+ end
+
+ def test_ractor
+ assert_in_out_err([], <<-"end;", ["stra", " ", "strb", " ", "strc"], [])
+ require "strscan"
+ $VERBOSE = nil
+ r = Ractor.new do
+ s = StringScanner.new("stra strb strc", true)
+ [
+ s.scan(/\\w+/),
+ s.scan(/\\s+/),
+ s.scan(/\\w+/),
+ s.scan(/\\s+/),
+ s.scan(/\\w+/),
+ s.scan(/\\w+/),
+ s.scan(/\\w+/)
+ ]
+ end
+ puts r.take.compact
+ end;
+ end
+end
diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb
index 4b001b317e..6e30be1f7d 100644
--- a/test/strscan/test_stringscanner.rb
+++ b/test/strscan/test_stringscanner.rb
@@ -206,6 +206,23 @@ class TestStringScanner < Test::Unit::TestCase
assert_equal 11, s.charpos
end
+ def test_charpos_not_use_string_methods
+ string = +'abcädeföghi'
+ scanner = create_string_scanner(string)
+
+ class << string
+ EnvUtil.suppress_warning do
+ undef_method(*instance_methods)
+ end
+ end
+
+ assert_equal 0, scanner.charpos
+ assert_equal "abcä", scanner.scan_until(/ä/)
+ assert_equal 4, scanner.charpos
+ assert_equal "defö", scanner.scan_until(/ö/)
+ assert_equal 8, scanner.charpos
+ end
+
def test_concat
s = create_string_scanner('a'.dup)
s.scan(/a/)
diff --git a/test/test_delegate.rb b/test/test_delegate.rb
index 426a647808..57480b18ea 100644
--- a/test/test_delegate.rb
+++ b/test/test_delegate.rb
@@ -50,6 +50,21 @@ class TestDelegateClass < Test::Unit::TestCase
assert_equal(SimpleDelegator,simple.clone.class)
end
+ def test_simpledelegator_clone
+ simple=SimpleDelegator.new([])
+ simple.freeze
+
+ clone = simple.clone
+ assert_predicate clone, :frozen?
+ assert_predicate clone.__getobj__, :frozen?
+ assert_equal true, Kernel.instance_method(:frozen?).bind(clone).call
+
+ clone = simple.clone(freeze: false)
+ assert_not_predicate clone, :frozen?
+ assert_not_predicate clone.__getobj__, :frozen?
+ assert_equal false, Kernel.instance_method(:frozen?).bind(clone).call
+ end
+
class Object
def m
:o
@@ -91,6 +106,10 @@ class TestDelegateClass < Test::Unit::TestCase
protected
def parent_protected; end
+
+ private
+
+ def parent_private; end
end
class Child < DelegateClass(Parent)
@@ -102,6 +121,10 @@ class TestDelegateClass < Test::Unit::TestCase
protected
def parent_protected_added; end
+
+ private
+
+ def parent_private_added; end
end
def test_public_instance_methods
@@ -116,6 +139,32 @@ class TestDelegateClass < Test::Unit::TestCase
assert_equal([:parent_protected, :parent_protected_added], (Child.new(Parent.new).protected_methods - ignores).sort)
end
+ def test_instance_methods
+ ignores = Object.instance_methods | Delegator.instance_methods
+ assert_equal([:parent_protected, :parent_protected_added, :parent_public, :parent_public_added], (Child.instance_methods - ignores).sort)
+ assert_equal([:parent_protected, :parent_protected_added, :parent_public, :parent_public_added], (Child.new(Parent.new).methods - ignores).sort)
+ end
+
+ def test_DelegateClass_instance_method
+ assert_instance_of UnboundMethod, Child.instance_method(:parent_public)
+ assert_instance_of UnboundMethod, Child.instance_method(:parent_public_added)
+ assert_instance_of UnboundMethod, Child.instance_method(:parent_protected)
+ assert_instance_of UnboundMethod, Child.instance_method(:parent_protected_added)
+ assert_raise(NameError) { Child.instance_method(:parent_private) }
+ assert_raise(NameError) { Child.instance_method(:parent_private_added) }
+ assert_instance_of UnboundMethod, Child.instance_method(:to_s)
+ end
+
+ def test_DelegateClass_public_instance_method
+ assert_instance_of UnboundMethod, Child.public_instance_method(:parent_public)
+ assert_instance_of UnboundMethod, Child.public_instance_method(:parent_public_added)
+ assert_raise(NameError) { Child.public_instance_method(:parent_protected) }
+ assert_raise(NameError) { Child.public_instance_method(:parent_protected_added) }
+ assert_raise(NameError) { Child.instance_method(:parent_private) }
+ assert_raise(NameError) { Child.instance_method(:parent_private_added) }
+ assert_instance_of UnboundMethod, Child.public_instance_method(:to_s)
+ end
+
class IV < DelegateClass(Integer)
attr_accessor :var
@@ -190,9 +239,7 @@ class TestDelegateClass < Test::Unit::TestCase
assert_equal([], d.bar)
assert_equal([[], {:a=>1}], d.foo(:a=>1))
assert_equal([{:a=>1}], d.bar(:a=>1))
- assert_warn(/Using the last argument as keyword parameters is deprecated.*The called method `foo'/m) do
- assert_equal([[], {:a=>1}], d.foo({:a=>1}))
- end
+ assert_equal([[{:a=>1}], {}], d.foo({:a=>1}))
assert_equal([{:a=>1}], d.bar({:a=>1}))
end
diff --git a/test/test_extlibs.rb b/test/test_extlibs.rb
index 7dc22ee8a3..958c9ff73e 100644
--- a/test/test_extlibs.rb
+++ b/test/test_extlibs.rb
@@ -71,13 +71,11 @@ class TestExtLibs < Test::Unit::TestCase
check_existence "rbconfig/sizeof"
#check_existence "readline" # depend on libreadline
check_existence "ripper"
- check_existence "sdbm"
check_existence "socket"
check_existence "stringio"
check_existence "strscan"
check_existence "syslog"
check_existence "thread"
- check_existence "Win32API"
check_existence "win32ole"
check_existence "zlib", "this may be false positive, but should assert because rubygems requires this"
end
diff --git a/test/test_mutex_m.rb b/test/test_mutex_m.rb
index 30971dd352..e5cfbc8b5f 100644
--- a/test/test_mutex_m.rb
+++ b/test/test_mutex_m.rb
@@ -23,4 +23,36 @@ class TestMutexM < Test::Unit::TestCase
c.signal
assert_equal "abc", t.value
end
+
+ class KeywordInitializeParent
+ def initialize(x:)
+ end
+ end
+
+ class KeywordInitializeChild < KeywordInitializeParent
+ include Mutex_m
+ def initialize
+ super(x: 1)
+ end
+ end
+
+ def test_initialize_with_keyword_arg
+ assert KeywordInitializeChild.new
+ end
+
+ class NoArgInitializeParent
+ def initialize
+ end
+ end
+
+ class NoArgInitializeChild < NoArgInitializeParent
+ include Mutex_m
+ def initialize
+ super()
+ end
+ end
+
+ def test_initialize_no_args
+ assert NoArgInitializeChild.new
+ end
end
diff --git a/test/test_open3.rb b/test/test_open3.rb
index 24bd08e597..47d471c031 100644
--- a/test/test_open3.rb
+++ b/test/test_open3.rb
@@ -149,6 +149,17 @@ class TestOpen3 < Test::Unit::TestCase
}
end
+ def test_popen2e_noblock
+ i, o, t = Open3.popen2e(RUBY, '-e', 'STDOUT.print STDIN.read')
+ i.print "baz"
+ i.close
+ assert_equal("baz", o.read)
+ ensure
+ i.close
+ o.close
+ t.join
+ end
+
def test_capture3
o, e, s = Open3.capture3(RUBY, '-e', 'i=STDIN.read; print i+"o"; STDOUT.flush; STDERR.print i+"e"', :stdin_data=>"i")
assert_equal("io", o)
diff --git a/test/test_pp.rb b/test/test_pp.rb
index cd16af6394..4aa3195455 100644
--- a/test/test_pp.rb
+++ b/test/test_pp.rb
@@ -178,7 +178,7 @@ class PPSingleLineTest < Test::Unit::TestCase
end
def test_hash_in_array
- assert_equal("[{}]", PP.singleline_pp([->(*a){a.last}.ruby2_keywords.call(**{})], ''.dup))
+ assert_equal("[{}]", PP.singleline_pp([->(*a){a.last.clear}.ruby2_keywords.call(a: 1)], ''.dup))
assert_equal("[{}]", PP.singleline_pp([Hash.ruby2_keywords_hash({})], ''.dup))
end
end
@@ -211,12 +211,14 @@ class PPFileStatTest < Test::Unit::TestCase
end
end
-class PPAbstractSyntaxTree < Test::Unit::TestCase
- AST = RubyVM::AbstractSyntaxTree
- def test_lasgn_literal
- ast = AST.parse("_=1")
- expected = "(SCOPE@1:0-1:3 tbl: [:_] args: nil body: (LASGN@1:0-1:3 :_ (LIT@1:2-1:3 1)))"
- assert_equal(expected, PP.singleline_pp(ast, ''.dup), ast)
+if defined?(RubyVM)
+ class PPAbstractSyntaxTree < Test::Unit::TestCase
+ AST = RubyVM::AbstractSyntaxTree
+ def test_lasgn_literal
+ ast = AST.parse("_=1")
+ expected = "(SCOPE@1:0-1:3 tbl: [:_] args: nil body: (LASGN@1:0-1:3 :_ (LIT@1:2-1:3 1)))"
+ assert_equal(expected, PP.singleline_pp(ast, ''.dup), ast)
+ end
end
end
diff --git a/test/test_prime.rb b/test/test_prime.rb
index 9db13f08fe..8e8203e1c4 100644
--- a/test/test_prime.rb
+++ b/test/test_prime.rb
@@ -27,6 +27,14 @@ class TestPrime < Test::Unit::TestCase
assert_equal PRIMES, primes
end
+ def test_include?
+ assert_equal(false, Prime.include?(nil))
+ assert_equal(true, Prime.include?(3))
+ assert_equal(false, Prime.include?(4))
+ assert_equal(true, Prime.include?(Enumerable))
+ assert_equal(false, Prime.include?(Comparable))
+ end
+
def test_integer_each_prime
primes = []
Integer.each_prime(1000) do |p|
@@ -249,7 +257,18 @@ class TestPrime < Test::Unit::TestCase
assert_not_predicate(-2, :prime?)
assert_not_predicate(-3, :prime?)
assert_not_predicate(-4, :prime?)
+
+ assert_equal 1229, (1..10_000).count(&:prime?)
+ assert_equal 861, (100_000..110_000).count(&:prime?)
end
+
+=begin
+ # now Ractor should not use in test-all process
+ def test_prime_in_ractor
+ # Test usage of private constant...
+ assert_equal false, Ractor.new { ((2**13-1) * (2**17-1)).prime? }.take
+ end if defined?(Ractor)
+=end
end
def test_eratosthenes_works_fine_after_timeout
diff --git a/test/test_securerandom.rb b/test/test_securerandom.rb
index 7c8640fce4..ab96952e37 100644
--- a/test/test_securerandom.rb
+++ b/test/test_securerandom.rb
@@ -175,7 +175,7 @@ end
end
def assert_in_range(range, result, mesg = nil)
- assert(range.cover?(result), message(mesg) {"Expected #{result} to be in #{range}"})
+ assert(range.cover?(result), build_message(mesg, "Expected #{result} to be in #{range}"))
end
def test_with_openssl
diff --git a/test/test_set.rb b/test/test_set.rb
index b0f669ce86..e62f30d852 100644
--- a/test/test_set.rb
+++ b/test/test_set.rb
@@ -332,6 +332,24 @@ class TC_Set < Test::Unit::TestCase
}
end
+ def test_spacecraft_operator
+ set = Set[1,2,3]
+
+ assert_nil(set <=> 2)
+
+ assert_nil(set <=> set.to_a)
+
+ [Set, Set2].each { |klass|
+ assert_equal(-1, set <=> klass[1,2,3,4], klass.name)
+ assert_equal( 0, set <=> klass[3,2,1] , klass.name)
+ assert_equal(nil, set <=> klass[1,2,4] , klass.name)
+ assert_equal(+1, set <=> klass[2,3] , klass.name)
+ assert_equal(+1, set <=> klass[] , klass.name)
+
+ assert_equal(0, Set[] <=> klass[], klass.name)
+ }
+ end
+
def assert_intersect(expected, set, other)
case expected
when true
@@ -730,6 +748,22 @@ class TC_Set < Test::Unit::TestCase
}
end
+ def test_freeze_clone_false
+ set1 = Set[1,2,3]
+ set1.freeze
+ set2 = set1.clone(freeze: false)
+
+ assert_not_predicate set2, :frozen?
+ set2.add 5
+ assert_equal Set[1,2,3,5], set2
+ assert_equal Set[1,2,3], set1
+ end if Kernel.instance_method(:initialize_clone).arity != 1
+
+ def test_join
+ assert_equal('123', Set[1, 2, 3].join)
+ assert_equal('1 & 2 & 3', Set[1, 2, 3].join(' & '))
+ end
+
def test_inspect
set1 = Set[1, 2]
assert_equal('#<Set: {1, 2}>', set1.inspect)
@@ -785,113 +819,6 @@ class TC_Set < Test::Unit::TestCase
end
end
-class TC_SortedSet < Test::Unit::TestCase
- def test_sortedset
- s = SortedSet[4,5,3,1,2]
-
- assert_equal([1,2,3,4,5], s.to_a)
-
- prev = nil
- s.each { |o| assert(prev < o) if prev; prev = o }
- assert_not_nil(prev)
-
- s.map! { |o| -2 * o }
-
- assert_equal([-10,-8,-6,-4,-2], s.to_a)
-
- prev = nil
- ret = s.each { |o| assert(prev < o) if prev; prev = o }
- assert_not_nil(prev)
- assert_same(s, ret)
-
- s = SortedSet.new([2,1,3]) { |o| o * -2 }
- assert_equal([-6,-4,-2], s.to_a)
-
- s = SortedSet.new(['one', 'two', 'three', 'four'])
- a = []
- ret = s.delete_if { |o| a << o; o.start_with?('t') }
- assert_same(s, ret)
- assert_equal(['four', 'one'], s.to_a)
- assert_equal(['four', 'one', 'three', 'two'], a)
-
- s = SortedSet.new(['one', 'two', 'three', 'four'])
- a = []
- ret = s.reject! { |o| a << o; o.start_with?('t') }
- assert_same(s, ret)
- assert_equal(['four', 'one'], s.to_a)
- assert_equal(['four', 'one', 'three', 'two'], a)
-
- s = SortedSet.new(['one', 'two', 'three', 'four'])
- a = []
- ret = s.reject! { |o| a << o; false }
- assert_same(nil, ret)
- assert_equal(['four', 'one', 'three', 'two'], s.to_a)
- assert_equal(['four', 'one', 'three', 'two'], a)
- end
-
- def test_each
- ary = [1,3,5,7,10,20]
- set = SortedSet.new(ary)
-
- ret = set.each { |o| }
- assert_same(set, ret)
-
- e = set.each
- assert_instance_of(Enumerator, e)
-
- assert_nothing_raised {
- set.each { |o|
- ary.delete(o) or raise "unexpected element: #{o}"
- }
-
- ary.empty? or raise "forgotten elements: #{ary.join(', ')}"
- }
-
- assert_equal(6, e.size)
- set << 42
- assert_equal(7, e.size)
- end
-
- def test_freeze
- orig = set = SortedSet[3,2,1]
- assert_equal false, set.frozen?
- set << 4
- assert_same orig, set.freeze
- assert_equal true, set.frozen?
- assert_raise(FrozenError) {
- set << 5
- }
- assert_equal 4, set.size
-
- # https://bugs.ruby-lang.org/issues/12091
- assert_nothing_raised {
- assert_equal [1,2,3,4], set.to_a
- }
- end
-
- def test_freeze_dup
- set1 = SortedSet[1,2,3]
- set1.freeze
- set2 = set1.dup
-
- assert_not_predicate set2, :frozen?
- assert_nothing_raised {
- set2.add 4
- }
- end
-
- def test_freeze_clone
- set1 = SortedSet[1,2,3]
- set1.freeze
- set2 = set1.clone
-
- assert_predicate set2, :frozen?
- assert_raise(FrozenError) {
- set2.add 5
- }
- end
-end
-
class TC_Enumerable < Test::Unit::TestCase
def test_to_set
ary = [2,5,4,3,2,1,3]
@@ -906,13 +833,5 @@ class TC_Enumerable < Test::Unit::TestCase
assert_same set, set.to_set
assert_not_same set, set.to_set { |o| o }
-
- set = ary.to_set(SortedSet)
- assert_instance_of(SortedSet, set)
- assert_equal([1,2,3,4,5], set.to_a)
-
- set = ary.to_set(SortedSet) { |o| o * -2 }
- assert_instance_of(SortedSet, set)
- assert_equal([-10,-8,-6,-4,-2], set.sort)
end
end
diff --git a/test/test_sorted_set.rb b/test/test_sorted_set.rb
new file mode 100644
index 0000000000..f7ad7af299
--- /dev/null
+++ b/test/test_sorted_set.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'set'
+
+class TC_SortedSet < Test::Unit::TestCase
+ def base_dir
+ "#{__dir__}/../lib"
+ end
+
+ def assert_runs(ruby, options: nil)
+ options = ['-I', base_dir, *options]
+ r = system(RbConfig.ruby, *options, '-e', ruby)
+ assert(r)
+ end
+
+ def test_error
+ assert_runs <<~RUBY
+ require "set"
+
+ r = begin
+ puts SortedSet.new
+ rescue Exception => e
+ e.message
+ end
+ raise r unless r.match?(/has been extracted/)
+ RUBY
+ end
+
+ def test_ok_with_gem
+ assert_runs <<~RUBY, options: ['-I', "#{__dir__}/fixtures/fake_sorted_set_gem"]
+ require "set"
+
+ var = SortedSet.new.to_s
+ RUBY
+ end
+
+ def test_ok_require
+ assert_runs <<~RUBY, options: ['-I', "#{__dir__}/fixtures/fake_sorted_set_gem"]
+ require "set"
+ require "sorted_set"
+
+ var = SortedSet.new.to_s
+ RUBY
+ end
+end
diff --git a/test/test_tmpdir.rb b/test/test_tmpdir.rb
index ea2cc123c1..7ef9f59b54 100644
--- a/test/test_tmpdir.rb
+++ b/test/test_tmpdir.rb
@@ -5,7 +5,7 @@ require 'tmpdir'
class TestTmpdir < Test::Unit::TestCase
def test_tmpdir_modifiable
tmpdir = Dir.tmpdir
- assert_equal(false, tmpdir.frozen?)
+ assert_not_predicate(tmpdir, :frozen?)
tmpdir_org = tmpdir.dup
tmpdir << "foo"
assert_equal(tmpdir_org, Dir.tmpdir)
@@ -15,21 +15,34 @@ class TestTmpdir < Test::Unit::TestCase
skip "no meaning on this platform" if /mswin|mingw/ =~ RUBY_PLATFORM
Dir.mktmpdir do |tmpdir|
# ToDo: fix for parallel test
- olddir, ENV["TMPDIR"] = ENV["TMPDIR"], tmpdir
+ envs = %w[TMPDIR TMP TEMP]
+ oldenv = envs.each_with_object({}) {|v, h| h[v] = ENV.delete(v)}
begin
- assert_equal(tmpdir, Dir.tmpdir)
- File.chmod(0777, tmpdir)
- assert_not_equal(tmpdir, Dir.tmpdir)
- newdir = Dir.mktmpdir("d", tmpdir) do |dir|
- assert_file.directory? dir
- assert_equal(tmpdir, File.dirname(dir))
- dir
+ envs.each do |e|
+ tmpdirx = File.join(tmpdir, e)
+ ENV[e] = tmpdirx
+ assert_not_equal(tmpdirx, assert_warn('') {Dir.tmpdir})
+ File.write(tmpdirx, "")
+ assert_not_equal(tmpdirx, assert_warn(/not a directory/) {Dir.tmpdir})
+ File.unlink(tmpdirx)
+ ENV[e] = tmpdir
+ assert_equal(tmpdir, Dir.tmpdir)
+ File.chmod(0555, tmpdir)
+ assert_not_equal(tmpdir, assert_warn(/not writable/) {Dir.tmpdir})
+ File.chmod(0777, tmpdir)
+ assert_not_equal(tmpdir, assert_warn(/world-writable/) {Dir.tmpdir})
+ newdir = Dir.mktmpdir("d", tmpdir) do |dir|
+ assert_file.directory? dir
+ assert_equal(tmpdir, File.dirname(dir))
+ dir
+ end
+ assert_file.not_exist?(newdir)
+ File.chmod(01777, tmpdir)
+ assert_equal(tmpdir, Dir.tmpdir)
+ ENV[e] = nil
end
- assert_file.not_exist?(newdir)
- File.chmod(01777, tmpdir)
- assert_equal(tmpdir, Dir.tmpdir)
ensure
- ENV["TMPDIR"] = olddir
+ ENV.update(oldenv)
end
end
end
@@ -84,8 +97,6 @@ class TestTmpdir < Test::Unit::TestCase
target = target.chomp('/') + '/'
traversal_path = target.sub(/\A\w:/, '') # for DOSISH
traversal_path = Array.new(target.count('/')-2, '..').join('/') + traversal_path
- actual = yield traversal_path
- assert_not_send([File.absolute_path(actual), :start_with?, target])
[File::SEPARATOR, File::ALT_SEPARATOR].compact.each do |separator|
actual = yield traversal_path.tr('/', separator)
assert_not_send([File.absolute_path(actual), :start_with?, target])
diff --git a/test/test_win32api.rb b/test/test_win32api.rb
deleted file mode 100644
index f135964a27..0000000000
--- a/test/test_win32api.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-begin
- $VERBOSE, verbose = nil, $VERBOSE
- require "Win32API"
-rescue LoadError
-ensure
- $VERBOSE = verbose
-end
-
-class TestWin32API < Test::Unit::TestCase
- def test_params_string
- m2w = Win32API.new("kernel32", "MultiByteToWideChar", "ilpipi", "i")
- str = "utf-8 string".encode("utf-8")
- buf = "\0" * (str.size * 2)
- assert_equal str.size, m2w.call(65001, 0, str, str.bytesize, buf, str.size)
- assert_equal str.encode("utf-16le"), buf.force_encoding("utf-16le")
- end
-
- def test_params_array
- m2w = Win32API.new("kernel32", "MultiByteToWideChar", ["i", "l", "p", "i", "p", "i"], "i")
- str = "utf-8 string".encode("utf-8")
- buf = "\0" * (str.size * 2)
- assert_equal str.size, m2w.call(65001, 0, str, str.bytesize, buf, str.size)
- assert_equal str.encode("utf-16le"), buf.force_encoding("utf-16le")
- end
-end if defined?(Win32API)
diff --git a/test/uri/test_generic.rb b/test/uri/test_generic.rb
index 90f779c88c..b449a0a0d1 100644
--- a/test/uri/test_generic.rb
+++ b/test/uri/test_generic.rb
@@ -865,34 +865,30 @@ class URI::TestGeneric < Test::Unit::TestCase
end
def test_find_proxy_no_proxy
+ getaddress = IPSocket.method(:getaddress)
+ example_address = nil
+ IPSocket.singleton_class.class_eval do
+ undef getaddress
+ define_method(:getaddress) do |host|
+ case host
+ when "example.org", "www.example.org"
+ example_address
+ when /\A\d+(?:\.\d+){3}\z/
+ host
+ else
+ raise host
+ end
+ end
+ end
+
with_proxy_env('http_proxy'=>'http://127.0.0.1:8080', 'no_proxy'=>'192.0.2.2') {|env|
assert_equal(URI('http://127.0.0.1:8080'), URI("http://192.0.2.1/").find_proxy(env))
assert_nil(URI("http://192.0.2.2/").find_proxy(env))
- getaddress = IPSocket.method(:getaddress)
- begin
- class << IPSocket
- undef getaddress
- def getaddress(host)
- host == "example.org" or raise
- "192.0.2.1"
- end
- end
- assert_equal(URI('http://127.0.0.1:8080'), URI.parse("http://example.org").find_proxy(env))
- class << IPSocket
- undef getaddress
- def getaddress(host)
- host == "example.org" or raise
- "192.0.2.2"
- end
- end
- assert_nil(URI.parse("http://example.org").find_proxy(env))
- ensure
- IPSocket.singleton_class.class_eval do
- undef getaddress
- define_method(:getaddress, getaddress)
- end
- end
+ example_address = "192.0.2.1"
+ assert_equal(URI('http://127.0.0.1:8080'), URI.parse("http://example.org").find_proxy(env))
+ example_address = "192.0.2.2"
+ assert_nil(URI.parse("http://example.org").find_proxy(env))
}
with_proxy_env('http_proxy'=>'http://127.0.0.1:8080', 'no_proxy'=>'example.org') {|env|
assert_nil(URI("http://example.org/").find_proxy(env))
@@ -902,6 +898,11 @@ class URI::TestGeneric < Test::Unit::TestCase
assert_equal(URI('http://127.0.0.1:8080'), URI("http://example.org/").find_proxy(env))
assert_nil(URI("http://www.example.org/").find_proxy(env))
}
+ ensure
+ IPSocket.singleton_class.class_eval do
+ undef getaddress
+ define_method(:getaddress, getaddress)
+ end
end
def test_find_proxy_no_proxy_cidr
diff --git a/test/uri/test_ws.rb b/test/uri/test_ws.rb
new file mode 100644
index 0000000000..17acb0d9f2
--- /dev/null
+++ b/test/uri/test_ws.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'uri/http'
+require 'uri/ws'
+
+module URI
+
+
+class TestWS < Test::Unit::TestCase
+ def setup
+ end
+
+ def teardown
+ end
+
+ def uri_to_ary(uri)
+ uri.class.component.collect {|c| uri.send(c)}
+ end
+
+ def test_build
+ u = URI::WS.build(host: 'www.example.com', path: '/foo/bar')
+ assert_kind_of(URI::WS, u)
+ end
+
+ def test_parse
+ u = URI.parse('ws://a')
+ assert_kind_of(URI::WS, u)
+ assert_equal(['ws',
+ nil, 'a', URI::HTTP.default_port,
+ '', nil], uri_to_ary(u))
+ end
+
+ def test_normalize
+ host = 'aBcD'
+ u1 = URI.parse('ws://' + host + '/eFg?HiJ')
+ u2 = URI.parse('ws://' + host.downcase + '/eFg?HiJ')
+ assert(u1.normalize.host == 'abcd')
+ assert(u1.normalize.path == u1.path)
+ assert(u1.normalize == u2.normalize)
+ assert(!u1.normalize.host.equal?(u1.host))
+ assert( u2.normalize.host.equal?(u2.host))
+
+ assert_equal('ws://abc/', URI.parse('ws://abc').normalize.to_s)
+ end
+
+ def test_equal
+ assert(URI.parse('ws://abc') == URI.parse('ws://ABC'))
+ assert(URI.parse('ws://abc/def') == URI.parse('ws://ABC/def'))
+ assert(URI.parse('ws://abc/def') != URI.parse('ws://ABC/DEF'))
+ end
+
+ def test_request_uri
+ assert_equal('/', URI.parse('ws://a.b.c/').request_uri)
+ assert_equal('/?abc=def', URI.parse('ws://a.b.c/?abc=def').request_uri)
+ assert_equal('/', URI.parse('ws://a.b.c').request_uri)
+ assert_equal('/?abc=def', URI.parse('ws://a.b.c?abc=def').request_uri)
+ assert_equal(nil, URI.parse('ws:foo').request_uri)
+ end
+
+ def test_select
+ assert_equal(['ws', 'a.b.c', 80], URI.parse('ws://a.b.c/').select(:scheme, :host, :port))
+ u = URI.parse('ws://a.b.c/')
+ assert_equal(uri_to_ary(u), u.select(*u.component))
+ assert_raise(ArgumentError) do
+ u.select(:scheme, :host, :not_exist, :port)
+ end
+ end
+end
+
+
+end
diff --git a/test/webrick/test_cgi.rb b/test/webrick/test_cgi.rb
deleted file mode 100644
index 764c63f325..0000000000
--- a/test/webrick/test_cgi.rb
+++ /dev/null
@@ -1,170 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: false
-require_relative "utils"
-require "webrick"
-require "test/unit"
-
-class TestWEBrickCGI < Test::Unit::TestCase
- CRLF = "\r\n"
-
- def teardown
- WEBrick::Utils::TimeoutHandler.terminate
- super
- end
-
- def start_cgi_server(log_tester=TestWEBrick::DefaultLogTester, &block)
- config = {
- :CGIInterpreter => TestWEBrick::RubyBin,
- :DocumentRoot => File.dirname(__FILE__),
- :DirectoryIndex => ["webrick.cgi"],
- :RequestCallback => Proc.new{|req, res|
- def req.meta_vars
- meta = super
- meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
- meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
- return meta
- end
- },
- }
- if RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32/
- config[:CGIPathEnv] = ENV['PATH'] # runtime dll may not be in system dir.
- end
- TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
- block.call(server, addr, port, log)
- }
- end
-
- def test_cgi
- start_cgi_server{|server, addr, port, log|
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/webrick.cgi")
- http.request(req){|res| assert_equal("/webrick.cgi", res.body, log.call)}
- req = Net::HTTP::Get.new("/webrick.cgi/path/info")
- http.request(req){|res| assert_equal("/path/info", res.body, log.call)}
- req = Net::HTTP::Get.new("/webrick.cgi/%3F%3F%3F?foo=bar")
- http.request(req){|res| assert_equal("/???", res.body, log.call)}
- unless RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32/
- # Path info of res.body is passed via ENV.
- # ENV[] returns different value on Windows depending on locale.
- req = Net::HTTP::Get.new("/webrick.cgi/%A4%DB%A4%B2/%A4%DB%A4%B2")
- http.request(req){|res|
- assert_equal("/\xA4\xDB\xA4\xB2/\xA4\xDB\xA4\xB2", res.body, log.call)}
- end
- req = Net::HTTP::Get.new("/webrick.cgi?a=1;a=2;b=x")
- http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
- req = Net::HTTP::Get.new("/webrick.cgi?a=1&a=2&b=x")
- http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
-
- req = Net::HTTP::Post.new("/webrick.cgi?a=x;a=y;b=1")
- req["Content-Type"] = "application/x-www-form-urlencoded"
- http.request(req, "a=1;a=2;b=x"){|res|
- assert_equal("a=1, a=2, b=x", res.body, log.call)}
- req = Net::HTTP::Post.new("/webrick.cgi?a=x&a=y&b=1")
- req["Content-Type"] = "application/x-www-form-urlencoded"
- http.request(req, "a=1&a=2&b=x"){|res|
- assert_equal("a=1, a=2, b=x", res.body, log.call)}
- req = Net::HTTP::Get.new("/")
- http.request(req){|res|
- ary = res.body.lines.to_a
- assert_match(%r{/$}, ary[0], log.call)
- assert_match(%r{/webrick.cgi$}, ary[1], log.call)
- }
-
- req = Net::HTTP::Get.new("/webrick.cgi")
- req["Cookie"] = "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001"
- http.request(req){|res|
- assert_equal(
- "CUSTOMER=WILE_E_COYOTE\nPART_NUMBER=ROCKET_LAUNCHER_0001\n",
- res.body, log.call)
- }
-
- req = Net::HTTP::Get.new("/webrick.cgi")
- cookie = %{$Version="1"; }
- cookie << %{Customer="WILE_E_COYOTE"; $Path="/acme"; }
- cookie << %{Part_Number="Rocket_Launcher_0001"; $Path="/acme"; }
- cookie << %{Shipping="FedEx"; $Path="/acme"}
- req["Cookie"] = cookie
- http.request(req){|res|
- assert_equal("Customer=WILE_E_COYOTE, Shipping=FedEx",
- res["Set-Cookie"], log.call)
- assert_equal("Customer=WILE_E_COYOTE\n" +
- "Part_Number=Rocket_Launcher_0001\n" +
- "Shipping=FedEx\n", res.body, log.call)
- }
- }
- end
-
- def test_bad_request
- log_tester = lambda {|log, access_log|
- assert_match(/BadRequest/, log.join)
- }
- start_cgi_server(log_tester) {|server, addr, port, log|
- sock = TCPSocket.new(addr, port)
- begin
- sock << "POST /webrick.cgi HTTP/1.0" << CRLF
- sock << "Content-Type: application/x-www-form-urlencoded" << CRLF
- sock << "Content-Length: 1024" << CRLF
- sock << CRLF
- sock << "a=1&a=2&b=x"
- sock.close_write
- assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, sock.read, log.call)
- ensure
- sock.close
- end
- }
- end
-
- def test_cgi_env
- start_cgi_server do |server, addr, port, log|
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/webrick.cgi/dumpenv")
- req['proxy'] = 'http://example.com/'
- req['hello'] = 'world'
- http.request(req) do |res|
- env = Marshal.load(res.body)
- assert_equal 'world', env['HTTP_HELLO']
- assert_not_operator env, :include?, 'HTTP_PROXY'
- end
- end
- end
-
- CtrlSeq = [0x7f, *(1..31)].pack("C*").gsub(/\s+/, '')
- CtrlPat = /#{Regexp.quote(CtrlSeq)}/o
- DumpPat = /#{Regexp.quote(CtrlSeq.dump[1...-1])}/o
-
- def test_bad_uri
- log_tester = lambda {|log, access_log|
- assert_equal(1, log.length)
- assert_match(/ERROR bad URI/, log[0])
- }
- start_cgi_server(log_tester) {|server, addr, port, log|
- res = TCPSocket.open(addr, port) {|sock|
- sock << "GET /#{CtrlSeq}#{CRLF}#{CRLF}"
- sock.close_write
- sock.read
- }
- assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
- s = log.call.each_line.grep(/ERROR bad URI/)[0]
- assert_match(DumpPat, s)
- assert_not_match(CtrlPat, s)
- }
- end
-
- def test_bad_header
- log_tester = lambda {|log, access_log|
- assert_equal(1, log.length)
- assert_match(/ERROR bad header/, log[0])
- }
- start_cgi_server(log_tester) {|server, addr, port, log|
- res = TCPSocket.open(addr, port) {|sock|
- sock << "GET / HTTP/1.0#{CRLF}#{CtrlSeq}#{CRLF}#{CRLF}"
- sock.close_write
- sock.read
- }
- assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
- s = log.call.each_line.grep(/ERROR bad header/)[0]
- assert_match(DumpPat, s)
- assert_not_match(CtrlPat, s)
- }
- end
-end
diff --git a/test/webrick/test_filehandler.rb b/test/webrick/test_filehandler.rb
deleted file mode 100644
index 33b6d7b6f5..0000000000
--- a/test/webrick/test_filehandler.rb
+++ /dev/null
@@ -1,353 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require_relative "utils.rb"
-require "webrick"
-require "stringio"
-
-class WEBrick::TestFileHandler < Test::Unit::TestCase
- def teardown
- WEBrick::Utils::TimeoutHandler.terminate
- super
- end
-
- def default_file_handler(filename)
- klass = WEBrick::HTTPServlet::DefaultFileHandler
- klass.new(WEBrick::Config::HTTP, filename)
- end
-
- def windows?
- File.directory?("\\")
- end
-
- def get_res_body(res)
- sio = StringIO.new
- sio.binmode
- res.send_body(sio)
- sio.string
- end
-
- def make_range_request(range_spec)
- msg = <<-END_OF_REQUEST
- GET / HTTP/1.0
- Range: #{range_spec}
-
- END_OF_REQUEST
- return StringIO.new(msg.gsub(/^ {6}/, ""))
- end
-
- def make_range_response(file, range_spec)
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(make_range_request(range_spec))
- res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
- size = File.size(file)
- handler = default_file_handler(file)
- handler.make_partial_content(req, res, file, size)
- return res
- end
-
- def test_make_partial_content
- filename = __FILE__
- filesize = File.size(filename)
-
- res = make_range_response(filename, "bytes=#{filesize-100}-")
- assert_match(%r{^text/plain}, res["content-type"])
- assert_equal(100, get_res_body(res).size)
-
- res = make_range_response(filename, "bytes=-100")
- assert_match(%r{^text/plain}, res["content-type"])
- assert_equal(100, get_res_body(res).size)
-
- res = make_range_response(filename, "bytes=0-99")
- assert_match(%r{^text/plain}, res["content-type"])
- assert_equal(100, get_res_body(res).size)
-
- res = make_range_response(filename, "bytes=100-199")
- assert_match(%r{^text/plain}, res["content-type"])
- assert_equal(100, get_res_body(res).size)
-
- res = make_range_response(filename, "bytes=0-0")
- assert_match(%r{^text/plain}, res["content-type"])
- assert_equal(1, get_res_body(res).size)
-
- res = make_range_response(filename, "bytes=-1")
- assert_match(%r{^text/plain}, res["content-type"])
- assert_equal(1, get_res_body(res).size)
-
- res = make_range_response(filename, "bytes=0-0, -2")
- assert_match(%r{^multipart/byteranges}, res["content-type"])
- body = get_res_body(res)
- boundary = /; boundary=(.+)/.match(res['content-type'])[1]
- off = filesize - 2
- last = filesize - 1
-
- exp = "--#{boundary}\r\n" \
- "Content-Type: text/plain\r\n" \
- "Content-Range: bytes 0-0/#{filesize}\r\n" \
- "\r\n" \
- "#{IO.read(__FILE__, 1)}\r\n" \
- "--#{boundary}\r\n" \
- "Content-Type: text/plain\r\n" \
- "Content-Range: bytes #{off}-#{last}/#{filesize}\r\n" \
- "\r\n" \
- "#{IO.read(__FILE__, 2, off)}\r\n" \
- "--#{boundary}--\r\n"
- assert_equal exp, body
- end
-
- def test_filehandler
- config = { :DocumentRoot => File.dirname(__FILE__), }
- this_file = File.basename(__FILE__)
- filesize = File.size(__FILE__)
- this_data = File.binread(__FILE__)
- range = nil
- bug2593 = '[ruby-dev:40030]'
-
- TestWEBrick.start_httpserver(config) do |server, addr, port, log|
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/")
- http.request(req){|res|
- assert_equal("200", res.code, log.call)
- assert_equal("text/html", res.content_type, log.call)
- assert_match(/HREF="#{this_file}"/, res.body, log.call)
- }
- req = Net::HTTP::Get.new("/#{this_file}")
- http.request(req){|res|
- assert_equal("200", res.code, log.call)
- assert_equal("text/plain", res.content_type, log.call)
- assert_equal(this_data, res.body, log.call)
- }
-
- req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=#{filesize-100}-")
- http.request(req){|res|
- assert_equal("206", res.code, log.call)
- assert_equal("text/plain", res.content_type, log.call)
- assert_nothing_raised(bug2593) {range = res.content_range}
- assert_equal((filesize-100)..(filesize-1), range, log.call)
- assert_equal(this_data[-100..-1], res.body, log.call)
- }
-
- req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-100")
- http.request(req){|res|
- assert_equal("206", res.code, log.call)
- assert_equal("text/plain", res.content_type, log.call)
- assert_nothing_raised(bug2593) {range = res.content_range}
- assert_equal((filesize-100)..(filesize-1), range, log.call)
- assert_equal(this_data[-100..-1], res.body, log.call)
- }
-
- req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-99")
- http.request(req){|res|
- assert_equal("206", res.code, log.call)
- assert_equal("text/plain", res.content_type, log.call)
- assert_nothing_raised(bug2593) {range = res.content_range}
- assert_equal(0..99, range, log.call)
- assert_equal(this_data[0..99], res.body, log.call)
- }
-
- req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=100-199")
- http.request(req){|res|
- assert_equal("206", res.code, log.call)
- assert_equal("text/plain", res.content_type, log.call)
- assert_nothing_raised(bug2593) {range = res.content_range}
- assert_equal(100..199, range, log.call)
- assert_equal(this_data[100..199], res.body, log.call)
- }
-
- req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0")
- http.request(req){|res|
- assert_equal("206", res.code, log.call)
- assert_equal("text/plain", res.content_type, log.call)
- assert_nothing_raised(bug2593) {range = res.content_range}
- assert_equal(0..0, range, log.call)
- assert_equal(this_data[0..0], res.body, log.call)
- }
-
- req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-1")
- http.request(req){|res|
- assert_equal("206", res.code, log.call)
- assert_equal("text/plain", res.content_type, log.call)
- assert_nothing_raised(bug2593) {range = res.content_range}
- assert_equal((filesize-1)..(filesize-1), range, log.call)
- assert_equal(this_data[-1, 1], res.body, log.call)
- }
-
- req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0, -2")
- http.request(req){|res|
- assert_equal("206", res.code, log.call)
- assert_equal("multipart/byteranges", res.content_type, log.call)
- }
-
- end
- end
-
- def test_non_disclosure_name
- config = { :DocumentRoot => File.dirname(__FILE__), }
- log_tester = lambda {|log, access_log|
- log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
- log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s }
- assert_equal([], log)
- }
- this_file = File.basename(__FILE__)
- TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
- http = Net::HTTP.new(addr, port)
- doc_root_opts = server[:DocumentRootOptions]
- doc_root_opts[:NondisclosureName] = %w(.ht* *~ test_*)
- req = Net::HTTP::Get.new("/")
- http.request(req){|res|
- assert_equal("200", res.code, log.call)
- assert_equal("text/html", res.content_type, log.call)
- assert_no_match(/HREF="#{File.basename(__FILE__)}"/, res.body)
- }
- req = Net::HTTP::Get.new("/#{this_file}")
- http.request(req){|res|
- assert_equal("404", res.code, log.call)
- }
- doc_root_opts[:NondisclosureName] = %w(.ht* *~ TEST_*)
- http.request(req){|res|
- assert_equal("404", res.code, log.call)
- }
- end
- end
-
- def test_directory_traversal
- return if File.executable?(__FILE__) # skip on strange file system
-
- config = { :DocumentRoot => File.dirname(__FILE__), }
- log_tester = lambda {|log, access_log|
- log = log.reject {|s| /ERROR bad URI/ =~ s }
- log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
- assert_equal([], log)
- }
- TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/../../")
- http.request(req){|res| assert_equal("400", res.code, log.call) }
- req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}")
- http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code, log.call) }
- req = Net::HTTP::Get.new("/..%5c..%5cruby.c")
- http.request(req){|res| assert_equal("404", res.code, log.call) }
- end
- end
-
- def test_unwise_in_path
- if windows?
- config = { :DocumentRoot => File.dirname(__FILE__), }
- TestWEBrick.start_httpserver(config) do |server, addr, port, log|
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/..%5c..")
- http.request(req){|res| assert_equal("301", res.code, log.call) }
- end
- end
- end
-
- def test_short_filename
- return if File.executable?(__FILE__) # skip on strange file system
-
- config = {
- :CGIInterpreter => TestWEBrick::RubyBin,
- :DocumentRoot => File.dirname(__FILE__),
- :CGIPathEnv => ENV['PATH'],
- }
- log_tester = lambda {|log, access_log|
- log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
- log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s }
- assert_equal([], log)
- }
- TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
- http = Net::HTTP.new(addr, port)
- if windows?
- root = config[:DocumentRoot].tr("/", "\\")
- fname = IO.popen(%W[dir /x #{root}\\webrick_long_filename.cgi], &:read)
- fname.sub!(/\A.*$^$.*$^$/m, '')
- if fname
- fname = fname[/\s(w.+?cgi)\s/i, 1]
- fname.downcase!
- end
- else
- fname = "webric~1.cgi"
- end
- req = Net::HTTP::Get.new("/#{fname}/test")
- http.request(req) do |res|
- if windows?
- assert_equal("200", res.code, log.call)
- assert_equal("/test", res.body, log.call)
- else
- assert_equal("404", res.code, log.call)
- end
- end
-
- req = Net::HTTP::Get.new("/.htaccess")
- http.request(req) {|res| assert_equal("404", res.code, log.call) }
- req = Net::HTTP::Get.new("/htacce~1")
- http.request(req) {|res| assert_equal("404", res.code, log.call) }
- req = Net::HTTP::Get.new("/HTACCE~1")
- http.request(req) {|res| assert_equal("404", res.code, log.call) }
- end
- end
-
- def test_script_disclosure
- return if File.executable?(__FILE__) # skip on strange file system
-
- config = {
- :CGIInterpreter => TestWEBrick::RubyBinArray,
- :DocumentRoot => File.dirname(__FILE__),
- :CGIPathEnv => ENV['PATH'],
- :RequestCallback => Proc.new{|req, res|
- def req.meta_vars
- meta = super
- meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
- meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
- return meta
- end
- },
- }
- log_tester = lambda {|log, access_log|
- log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
- assert_equal([], log)
- }
- TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
- http = Net::HTTP.new(addr, port)
- http.read_timeout = EnvUtil.apply_timeout_scale(60)
- http.write_timeout = EnvUtil.apply_timeout_scale(60) if http.respond_to?(:write_timeout=)
-
- req = Net::HTTP::Get.new("/webrick.cgi/test")
- http.request(req) do |res|
- assert_equal("200", res.code, log.call)
- assert_equal("/test", res.body, log.call)
- end
-
- resok = windows?
- response_assertion = Proc.new do |res|
- if resok
- assert_equal("200", res.code, log.call)
- assert_equal("/test", res.body, log.call)
- else
- assert_equal("404", res.code, log.call)
- end
- end
- req = Net::HTTP::Get.new("/webrick.cgi%20/test")
- http.request(req, &response_assertion)
- req = Net::HTTP::Get.new("/webrick.cgi./test")
- http.request(req, &response_assertion)
- resok &&= File.exist?(__FILE__+"::$DATA")
- req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test")
- http.request(req, &response_assertion)
- end
- end
-
- def test_erbhandler
- config = { :DocumentRoot => File.dirname(__FILE__) }
- log_tester = lambda {|log, access_log|
- log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
- assert_equal([], log)
- }
- TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/webrick.rhtml")
- http.request(req) do |res|
- assert_equal("200", res.code, log.call)
- assert_match %r!\Areq to http://[^/]+/webrick\.rhtml {}\n!, res.body
- end
- end
- end
-end
diff --git a/test/webrick/test_httpproxy.rb b/test/webrick/test_httpproxy.rb
deleted file mode 100644
index 8149d78300..0000000000
--- a/test/webrick/test_httpproxy.rb
+++ /dev/null
@@ -1,466 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "net/http"
-require "webrick"
-require "webrick/httpproxy"
-begin
- require "webrick/ssl"
- require "net/https"
-rescue LoadError
- # test_connect will be skipped
-end
-require File.expand_path("utils.rb", File.dirname(__FILE__))
-
-class TestWEBrickHTTPProxy < Test::Unit::TestCase
- def teardown
- WEBrick::Utils::TimeoutHandler.terminate
- super
- end
-
- def test_fake_proxy
- assert_nil(WEBrick::FakeProxyURI.scheme)
- assert_nil(WEBrick::FakeProxyURI.host)
- assert_nil(WEBrick::FakeProxyURI.port)
- assert_nil(WEBrick::FakeProxyURI.path)
- assert_nil(WEBrick::FakeProxyURI.userinfo)
- assert_raise(NoMethodError){ WEBrick::FakeProxyURI.foo }
- end
-
- def test_proxy
- # Testing GET or POST to the proxy server
- # Note that the proxy server works as the origin server.
- # +------+
- # V |
- # client -------> proxy ---+
- # GET / POST GET / POST
- #
- proxy_handler_called = request_handler_called = 0
- config = {
- :ServerName => "localhost.localdomain",
- :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
- :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
- }
- TestWEBrick.start_httpproxy(config){|server, addr, port, log|
- server.mount_proc("/"){|req, res|
- res.body = "#{req.request_method} #{req.path} #{req.body}"
- }
- http = Net::HTTP.new(addr, port, addr, port)
-
- req = Net::HTTP::Get.new("/")
- http.request(req){|res|
- assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
- assert_equal("GET / ", res.body, log.call)
- }
- assert_equal(1, proxy_handler_called, log.call)
- assert_equal(2, request_handler_called, log.call)
-
- req = Net::HTTP::Head.new("/")
- http.request(req){|res|
- assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
- assert_nil(res.body, log.call)
- }
- assert_equal(2, proxy_handler_called, log.call)
- assert_equal(4, request_handler_called, log.call)
-
- req = Net::HTTP::Post.new("/")
- req.body = "post-data"
- req.content_type = "application/x-www-form-urlencoded"
- http.request(req){|res|
- assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
- assert_equal("POST / post-data", res.body, log.call)
- }
- assert_equal(3, proxy_handler_called, log.call)
- assert_equal(6, request_handler_called, log.call)
- }
- end
-
- def test_no_proxy
- # Testing GET or POST to the proxy server without proxy request.
- #
- # client -------> proxy
- # GET / POST
- #
- proxy_handler_called = request_handler_called = 0
- config = {
- :ServerName => "localhost.localdomain",
- :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
- :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
- }
- TestWEBrick.start_httpproxy(config){|server, addr, port, log|
- server.mount_proc("/"){|req, res|
- res.body = "#{req.request_method} #{req.path} #{req.body}"
- }
- http = Net::HTTP.new(addr, port)
-
- req = Net::HTTP::Get.new("/")
- http.request(req){|res|
- assert_nil(res["via"], log.call)
- assert_equal("GET / ", res.body, log.call)
- }
- assert_equal(0, proxy_handler_called, log.call)
- assert_equal(1, request_handler_called, log.call)
-
- req = Net::HTTP::Head.new("/")
- http.request(req){|res|
- assert_nil(res["via"], log.call)
- assert_nil(res.body, log.call)
- }
- assert_equal(0, proxy_handler_called, log.call)
- assert_equal(2, request_handler_called, log.call)
-
- req = Net::HTTP::Post.new("/")
- req.content_type = "application/x-www-form-urlencoded"
- req.body = "post-data"
- http.request(req){|res|
- assert_nil(res["via"], log.call)
- assert_equal("POST / post-data", res.body, log.call)
- }
- assert_equal(0, proxy_handler_called, log.call)
- assert_equal(3, request_handler_called, log.call)
- }
- end
-
- def test_big_bodies
- require 'digest/md5'
- rand_str = File.read(__FILE__)
- rand_str.freeze
- nr = 1024 ** 2 / rand_str.size # bigger works, too
- exp = Digest::MD5.new
- nr.times { exp.update(rand_str) }
- exp = exp.hexdigest
- TestWEBrick.start_httpserver do |o_server, o_addr, o_port, o_log|
- o_server.mount_proc('/') do |req, res|
- case req.request_method
- when 'GET'
- res['content-type'] = 'application/octet-stream'
- if req.path == '/length'
- res['content-length'] = (nr * rand_str.size).to_s
- else
- res.chunked = true
- end
- res.body = ->(socket) { nr.times { socket.write(rand_str) } }
- when 'POST'
- dig = Digest::MD5.new
- req.body { |buf| dig.update(buf); buf.clear }
- res['content-type'] = 'text/plain'
- res['content-length'] = '32'
- res.body = dig.hexdigest
- end
- end
-
- http = Net::HTTP.new(o_addr, o_port)
- IO.pipe do |rd, wr|
- headers = {
- 'Content-Type' => 'application/octet-stream',
- 'Transfer-Encoding' => 'chunked',
- }
- post = Net::HTTP::Post.new('/', headers)
- th = Thread.new { nr.times { wr.write(rand_str) }; wr.close }
- post.body_stream = rd
- http.request(post) do |res|
- assert_equal 'text/plain', res['content-type']
- assert_equal 32, res.content_length
- assert_equal exp, res.body
- end
- assert_nil th.value
- end
-
- TestWEBrick.start_httpproxy do |p_server, p_addr, p_port, p_log|
- http = Net::HTTP.new(o_addr, o_port, p_addr, p_port)
- http.request_get('/length') do |res|
- assert_equal(nr * rand_str.size, res.content_length)
- dig = Digest::MD5.new
- res.read_body { |buf| dig.update(buf); buf.clear }
- assert_equal exp, dig.hexdigest
- end
- http.request_get('/') do |res|
- assert_predicate res, :chunked?
- dig = Digest::MD5.new
- res.read_body { |buf| dig.update(buf); buf.clear }
- assert_equal exp, dig.hexdigest
- end
-
- IO.pipe do |rd, wr|
- headers = {
- 'Content-Type' => 'application/octet-stream',
- 'Content-Length' => (nr * rand_str.size).to_s,
- }
- post = Net::HTTP::Post.new('/', headers)
- th = Thread.new { nr.times { wr.write(rand_str) }; wr.close }
- post.body_stream = rd
- http.request(post) do |res|
- assert_equal 'text/plain', res['content-type']
- assert_equal 32, res.content_length
- assert_equal exp, res.body
- end
- assert_nil th.value
- end
-
- IO.pipe do |rd, wr|
- headers = {
- 'Content-Type' => 'application/octet-stream',
- 'Transfer-Encoding' => 'chunked',
- }
- post = Net::HTTP::Post.new('/', headers)
- th = Thread.new { nr.times { wr.write(rand_str) }; wr.close }
- post.body_stream = rd
- http.request(post) do |res|
- assert_equal 'text/plain', res['content-type']
- assert_equal 32, res.content_length
- assert_equal exp, res.body
- end
- assert_nil th.value
- end
- end
- end
- end
-
- def test_http10_proxy_chunked
- # Testing HTTP/1.0 client request and HTTP/1.1 chunked response
- # from origin server.
- # +------+
- # V |
- # client -------> proxy ---+
- # GET GET
- # HTTP/1.0 HTTP/1.1
- # non-chunked chunked
- #
- proxy_handler_called = request_handler_called = 0
- config = {
- :ServerName => "localhost.localdomain",
- :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
- :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
- }
- log_tester = lambda {|log, access_log|
- log.reject! {|str|
- %r{WARN chunked is set for an HTTP/1\.0 request\. \(ignored\)} =~ str
- }
- assert_equal([], log)
- }
- TestWEBrick.start_httpproxy(config, log_tester){|server, addr, port, log|
- body = nil
- server.mount_proc("/"){|req, res|
- body = "#{req.request_method} #{req.path} #{req.body}"
- res.chunked = true
- res.body = -> (socket) { body.each_char {|c| socket.write c } }
- }
-
- # Don't use Net::HTTP because it uses HTTP/1.1.
- TCPSocket.open(addr, port) {|s|
- s.write "GET / HTTP/1.0\r\nHost: localhost.localdomain\r\n\r\n"
- response = s.read
- assert_equal(body, response[/.*\z/])
- }
- }
- end
-
- def make_certificate(key, cn)
- subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=#{cn}")
- exts = [
- ["keyUsage", "keyEncipherment,digitalSignature", true],
- ]
- cert = OpenSSL::X509::Certificate.new
- cert.version = 2
- cert.serial = 1
- cert.subject = subject
- cert.issuer = subject
- cert.public_key = key
- cert.not_before = Time.now - 3600
- cert.not_after = Time.now + 3600
- ef = OpenSSL::X509::ExtensionFactory.new(cert, cert)
- exts.each {|args| cert.add_extension(ef.create_extension(*args)) }
- cert.sign(key, "sha256")
- return cert
- end if defined?(OpenSSL::SSL)
-
- def test_connect
- # Testing CONNECT to proxy server
- #
- # client -----------> proxy -----------> https
- # 1. CONNECT establish TCP
- # 2. ---- establish SSL session --->
- # 3. ------- GET or POST ---------->
- #
- key = TEST_KEY_RSA2048
- cert = make_certificate(key, "127.0.0.1")
- s_config = {
- :SSLEnable =>true,
- :ServerName => "localhost",
- :SSLCertificate => cert,
- :SSLPrivateKey => key,
- }
- config = {
- :ServerName => "localhost.localdomain",
- :RequestCallback => Proc.new{|req, res|
- assert_equal("CONNECT", req.request_method)
- },
- }
- TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
- s_server.mount_proc("/"){|req, res|
- res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
- }
- TestWEBrick.start_httpproxy(config){|server, addr, port, log|
- http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
- http.use_ssl = true
- http.verify_callback = Proc.new do |preverify_ok, store_ctx|
- store_ctx.current_cert.to_der == cert.to_der
- end
-
- req = Net::HTTP::Get.new("/")
- req["Content-Type"] = "application/x-www-form-urlencoded"
- http.request(req){|res|
- assert_equal("SSL GET / ", res.body, s_log.call + log.call)
- }
-
- req = Net::HTTP::Post.new("/")
- req["Content-Type"] = "application/x-www-form-urlencoded"
- req.body = "post-data"
- http.request(req){|res|
- assert_equal("SSL POST / post-data", res.body, s_log.call + log.call)
- }
- }
- }
- end if defined?(OpenSSL::SSL)
-
- def test_upstream_proxy
- # Testing GET or POST through the upstream proxy server
- # Note that the upstream proxy server works as the origin server.
- # +------+
- # V |
- # client -------> proxy -------> proxy ---+
- # GET / POST GET / POST GET / POST
- #
- up_proxy_handler_called = up_request_handler_called = 0
- proxy_handler_called = request_handler_called = 0
- up_config = {
- :ServerName => "localhost.localdomain",
- :ProxyContentHandler => Proc.new{|req, res| up_proxy_handler_called += 1},
- :RequestCallback => Proc.new{|req, res| up_request_handler_called += 1}
- }
- TestWEBrick.start_httpproxy(up_config){|up_server, up_addr, up_port, up_log|
- up_server.mount_proc("/"){|req, res|
- res.body = "#{req.request_method} #{req.path} #{req.body}"
- }
- config = {
- :ServerName => "localhost.localdomain",
- :ProxyURI => URI.parse("http://localhost:#{up_port}"),
- :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1},
- :RequestCallback => Proc.new{|req, res| request_handler_called += 1},
- }
- TestWEBrick.start_httpproxy(config){|server, addr, port, log|
- http = Net::HTTP.new(up_addr, up_port, addr, port)
-
- req = Net::HTTP::Get.new("/")
- http.request(req){|res|
- skip res.message unless res.code == '200'
- via = res["via"].split(/,\s+/)
- assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
- assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
- assert_equal("GET / ", res.body)
- }
- assert_equal(1, up_proxy_handler_called, up_log.call + log.call)
- assert_equal(2, up_request_handler_called, up_log.call + log.call)
- assert_equal(1, proxy_handler_called, up_log.call + log.call)
- assert_equal(1, request_handler_called, up_log.call + log.call)
-
- req = Net::HTTP::Head.new("/")
- http.request(req){|res|
- via = res["via"].split(/,\s+/)
- assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
- assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
- assert_nil(res.body, up_log.call + log.call)
- }
- assert_equal(2, up_proxy_handler_called, up_log.call + log.call)
- assert_equal(4, up_request_handler_called, up_log.call + log.call)
- assert_equal(2, proxy_handler_called, up_log.call + log.call)
- assert_equal(2, request_handler_called, up_log.call + log.call)
-
- req = Net::HTTP::Post.new("/")
- req.body = "post-data"
- req.content_type = "application/x-www-form-urlencoded"
- http.request(req){|res|
- via = res["via"].split(/,\s+/)
- assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
- assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
- assert_equal("POST / post-data", res.body, up_log.call + log.call)
- }
- assert_equal(3, up_proxy_handler_called, up_log.call + log.call)
- assert_equal(6, up_request_handler_called, up_log.call + log.call)
- assert_equal(3, proxy_handler_called, up_log.call + log.call)
- assert_equal(3, request_handler_called, up_log.call + log.call)
-
- if defined?(OpenSSL::SSL)
- # Testing CONNECT to the upstream proxy server
- #
- # client -------> proxy -------> proxy -------> https
- # 1. CONNECT CONNECT establish TCP
- # 2. -------- establish SSL session ------>
- # 3. ---------- GET or POST -------------->
- #
- key = TEST_KEY_RSA2048
- cert = make_certificate(key, "127.0.0.1")
- s_config = {
- :SSLEnable =>true,
- :ServerName => "localhost",
- :SSLCertificate => cert,
- :SSLPrivateKey => key,
- }
- TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
- s_server.mount_proc("/"){|req2, res|
- res.body = "SSL #{req2.request_method} #{req2.path} #{req2.body}"
- }
- http = Net::HTTP.new("127.0.0.1", s_port, addr, port, up_log.call + log.call + s_log.call)
- http.use_ssl = true
- http.verify_callback = Proc.new do |preverify_ok, store_ctx|
- store_ctx.current_cert.to_der == cert.to_der
- end
-
- req2 = Net::HTTP::Get.new("/")
- http.request(req2){|res|
- assert_equal("SSL GET / ", res.body, up_log.call + log.call + s_log.call)
- }
-
- req2 = Net::HTTP::Post.new("/")
- req2.body = "post-data"
- req2.content_type = "application/x-www-form-urlencoded"
- http.request(req2){|res|
- assert_equal("SSL POST / post-data", res.body, up_log.call + log.call + s_log.call)
- }
- }
- end
- }
- }
- end
-
- if defined?(OpenSSL::SSL)
- TEST_KEY_RSA2048 = OpenSSL::PKey.read <<-_end_of_pem_
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN
-s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign
-4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D
-kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl
-NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J
-DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb
-I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq
-PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V
-seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0
-Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc
-VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW
-wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G
-0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj
-XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb
-aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n
-h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw
-Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k
-IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb
-v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId
-U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr
-vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS
-Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC
-9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41
-gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG
-4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw==
------END RSA PRIVATE KEY-----
- _end_of_pem_
- end
-end
diff --git a/test/webrick/test_httprequest.rb b/test/webrick/test_httprequest.rb
deleted file mode 100644
index a594f14f72..0000000000
--- a/test/webrick/test_httprequest.rb
+++ /dev/null
@@ -1,476 +0,0 @@
-# frozen_string_literal: false
-require "webrick"
-require "stringio"
-require "test/unit"
-
-class TestWEBrickHTTPRequest < Test::Unit::TestCase
- def teardown
- WEBrick::Utils::TimeoutHandler.terminate
- super
- end
-
- def test_simple_request
- msg = <<-_end_of_message_
-GET /
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert(req.meta_vars) # fails if @header was not initialized and iteration is attempted on the nil reference
- end
-
- def test_parse_09
- msg = <<-_end_of_message_
- GET /
- foobar # HTTP/0.9 request don't have header nor entity body.
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal("GET", req.request_method)
- assert_equal("/", req.unparsed_uri)
- assert_equal(WEBrick::HTTPVersion.new("0.9"), req.http_version)
- assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
- assert_equal(80, req.port)
- assert_equal(false, req.keep_alive?)
- assert_equal(nil, req.body)
- assert(req.query.empty?)
- end
-
- def test_parse_10
- msg = <<-_end_of_message_
- GET / HTTP/1.0
-
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal("GET", req.request_method)
- assert_equal("/", req.unparsed_uri)
- assert_equal(WEBrick::HTTPVersion.new("1.0"), req.http_version)
- assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
- assert_equal(80, req.port)
- assert_equal(false, req.keep_alive?)
- assert_equal(nil, req.body)
- assert(req.query.empty?)
- end
-
- def test_parse_11
- msg = <<-_end_of_message_
- GET /path HTTP/1.1
-
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal("GET", req.request_method)
- assert_equal("/path", req.unparsed_uri)
- assert_equal("", req.script_name)
- assert_equal("/path", req.path_info)
- assert_equal(WEBrick::HTTPVersion.new("1.1"), req.http_version)
- assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
- assert_equal(80, req.port)
- assert_equal(true, req.keep_alive?)
- assert_equal(nil, req.body)
- assert(req.query.empty?)
- end
-
- def test_request_uri_too_large
- msg = <<-_end_of_message_
- GET /#{"a"*2084} HTTP/1.1
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- assert_raise(WEBrick::HTTPStatus::RequestURITooLarge){
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- }
- end
-
- def test_parse_headers
- msg = <<-_end_of_message_
- GET /path HTTP/1.1
- Host: test.ruby-lang.org:8080
- Connection: close
- Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
- text/html;level=2;q=0.4, */*;q=0.5
- Accept-Encoding: compress;q=0.5
- Accept-Encoding: gzip;q=1.0, identity; q=0.4, *;q=0
- Accept-Language: en;q=0.5, *; q=0
- Accept-Language: ja
- Content-Type: text/plain
- Content-Length: 7
- X-Empty-Header:
-
- foobar
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal(
- URI.parse("http://test.ruby-lang.org:8080/path"), req.request_uri)
- assert_equal("test.ruby-lang.org", req.host)
- assert_equal(8080, req.port)
- assert_equal(false, req.keep_alive?)
- assert_equal(
- %w(text/html;level=1 text/html */* text/html;level=2 text/*),
- req.accept)
- assert_equal(%w(gzip compress identity *), req.accept_encoding)
- assert_equal(%w(ja en *), req.accept_language)
- assert_equal(7, req.content_length)
- assert_equal("text/plain", req.content_type)
- assert_equal("foobar\n", req.body)
- assert_equal("", req["x-empty-header"])
- assert_equal(nil, req["x-no-header"])
- assert(req.query.empty?)
- end
-
- def test_parse_header2()
- msg = <<-_end_of_message_
- POST /foo/bar/../baz?q=a HTTP/1.0
- Content-Length: 9
- User-Agent:
- FOO BAR
- BAZ
-
- hogehoge
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal("POST", req.request_method)
- assert_equal("/foo/baz", req.path)
- assert_equal("", req.script_name)
- assert_equal("/foo/baz", req.path_info)
- assert_equal("9", req['content-length'])
- assert_equal("FOO BAR BAZ", req['user-agent'])
- assert_equal("hogehoge\n", req.body)
- end
-
- def test_parse_headers3
- msg = <<-_end_of_message_
- GET /path HTTP/1.1
- Host: test.ruby-lang.org
-
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal(URI.parse("http://test.ruby-lang.org/path"), req.request_uri)
- assert_equal("test.ruby-lang.org", req.host)
- assert_equal(80, req.port)
-
- msg = <<-_end_of_message_
- GET /path HTTP/1.1
- Host: 192.168.1.1
-
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal(URI.parse("http://192.168.1.1/path"), req.request_uri)
- assert_equal("192.168.1.1", req.host)
- assert_equal(80, req.port)
-
- msg = <<-_end_of_message_
- GET /path HTTP/1.1
- Host: [fe80::208:dff:feef:98c7]
-
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]/path"),
- req.request_uri)
- assert_equal("[fe80::208:dff:feef:98c7]", req.host)
- assert_equal(80, req.port)
-
- msg = <<-_end_of_message_
- GET /path HTTP/1.1
- Host: 192.168.1.1:8080
-
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal(URI.parse("http://192.168.1.1:8080/path"), req.request_uri)
- assert_equal("192.168.1.1", req.host)
- assert_equal(8080, req.port)
-
- msg = <<-_end_of_message_
- GET /path HTTP/1.1
- Host: [fe80::208:dff:feef:98c7]:8080
-
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]:8080/path"),
- req.request_uri)
- assert_equal("[fe80::208:dff:feef:98c7]", req.host)
- assert_equal(8080, req.port)
- end
-
- def test_parse_get_params
- param = "foo=1;foo=2;foo=3;bar=x"
- msg = <<-_end_of_message_
- GET /path?#{param} HTTP/1.1
- Host: test.ruby-lang.org:8080
-
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- query = req.query
- assert_equal("1", query["foo"])
- assert_equal(["1", "2", "3"], query["foo"].to_ary)
- assert_equal(["1", "2", "3"], query["foo"].list)
- assert_equal("x", query["bar"])
- assert_equal(["x"], query["bar"].list)
- end
-
- def test_parse_post_params
- param = "foo=1;foo=2;foo=3;bar=x"
- msg = <<-_end_of_message_
- POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
- Host: test.ruby-lang.org:8080
- Content-Length: #{param.size}
- Content-Type: application/x-www-form-urlencoded
-
- #{param}
- _end_of_message_
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- query = req.query
- assert_equal("1", query["foo"])
- assert_equal(["1", "2", "3"], query["foo"].to_ary)
- assert_equal(["1", "2", "3"], query["foo"].list)
- assert_equal("x", query["bar"])
- assert_equal(["x"], query["bar"].list)
- end
-
- def test_chunked
- crlf = "\x0d\x0a"
- expect = File.binread(__FILE__).freeze
- msg = <<-_end_of_message_
- POST /path HTTP/1.1
- Host: test.ruby-lang.org:8080
- Transfer-Encoding: chunked
-
- _end_of_message_
- msg.gsub!(/^ {6}/, "")
- open(__FILE__){|io|
- while chunk = io.read(100)
- msg << chunk.size.to_s(16) << crlf
- msg << chunk << crlf
- end
- }
- msg << "0" << crlf
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert_equal(expect, req.body)
-
- # chunked req.body_reader
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- dst = StringIO.new
- IO.copy_stream(req.body_reader, dst)
- assert_equal(expect, dst.string)
- end
-
- def test_forwarded
- msg = <<-_end_of_message_
- GET /foo HTTP/1.1
- Host: localhost:10080
- User-Agent: w3m/0.5.2
- X-Forwarded-For: 123.123.123.123
- X-Forwarded-Host: forward.example.com
- X-Forwarded-Server: server.example.com
- Connection: Keep-Alive
-
- _end_of_message_
- msg.gsub!(/^ {6}/, "")
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert_equal("server.example.com", req.server_name)
- assert_equal("http://forward.example.com/foo", req.request_uri.to_s)
- assert_equal("forward.example.com", req.host)
- assert_equal(80, req.port)
- assert_equal("123.123.123.123", req.remote_ip)
- assert(!req.ssl?)
-
- msg = <<-_end_of_message_
- GET /foo HTTP/1.1
- Host: localhost:10080
- User-Agent: w3m/0.5.2
- X-Forwarded-For: 192.168.1.10, 172.16.1.1, 123.123.123.123
- X-Forwarded-Host: forward.example.com:8080
- X-Forwarded-Server: server.example.com
- Connection: Keep-Alive
-
- _end_of_message_
- msg.gsub!(/^ {6}/, "")
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert_equal("server.example.com", req.server_name)
- assert_equal("http://forward.example.com:8080/foo", req.request_uri.to_s)
- assert_equal("forward.example.com", req.host)
- assert_equal(8080, req.port)
- assert_equal("123.123.123.123", req.remote_ip)
- assert(!req.ssl?)
-
- msg = <<-_end_of_message_
- GET /foo HTTP/1.1
- Host: localhost:10080
- Client-IP: 234.234.234.234
- X-Forwarded-Proto: https, http
- X-Forwarded-For: 192.168.1.10, 10.0.0.1, 123.123.123.123
- X-Forwarded-Host: forward.example.com
- X-Forwarded-Server: server.example.com
- X-Requested-With: XMLHttpRequest
- Connection: Keep-Alive
-
- _end_of_message_
- msg.gsub!(/^ {6}/, "")
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert_equal("server.example.com", req.server_name)
- assert_equal("https://forward.example.com/foo", req.request_uri.to_s)
- assert_equal("forward.example.com", req.host)
- assert_equal(443, req.port)
- assert_equal("234.234.234.234", req.remote_ip)
- assert(req.ssl?)
-
- msg = <<-_end_of_message_
- GET /foo HTTP/1.1
- Host: localhost:10080
- Client-IP: 234.234.234.234
- X-Forwarded-Proto: https
- X-Forwarded-For: 192.168.1.10
- X-Forwarded-Host: forward1.example.com:1234, forward2.example.com:5678
- X-Forwarded-Server: server1.example.com, server2.example.com
- X-Requested-With: XMLHttpRequest
- Connection: Keep-Alive
-
- _end_of_message_
- msg.gsub!(/^ {6}/, "")
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert_equal("server1.example.com", req.server_name)
- assert_equal("https://forward1.example.com:1234/foo", req.request_uri.to_s)
- assert_equal("forward1.example.com", req.host)
- assert_equal(1234, req.port)
- assert_equal("234.234.234.234", req.remote_ip)
- assert(req.ssl?)
-
- msg = <<-_end_of_message_
- GET /foo HTTP/1.1
- Host: localhost:10080
- Client-IP: 234.234.234.234
- X-Forwarded-Proto: https
- X-Forwarded-For: 192.168.1.10
- X-Forwarded-Host: [fd20:8b1e:b255:8154:250:56ff:fea8:4d84], forward2.example.com:5678
- X-Forwarded-Server: server1.example.com, server2.example.com
- X-Requested-With: XMLHttpRequest
- Connection: Keep-Alive
-
- _end_of_message_
- msg.gsub!(/^ {6}/, "")
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert_equal("server1.example.com", req.server_name)
- assert_equal("https://[fd20:8b1e:b255:8154:250:56ff:fea8:4d84]/foo", req.request_uri.to_s)
- assert_equal("[fd20:8b1e:b255:8154:250:56ff:fea8:4d84]", req.host)
- assert_equal(443, req.port)
- assert_equal("234.234.234.234", req.remote_ip)
- assert(req.ssl?)
-
- msg = <<-_end_of_message_
- GET /foo HTTP/1.1
- Host: localhost:10080
- Client-IP: 234.234.234.234
- X-Forwarded-Proto: https
- X-Forwarded-For: 192.168.1.10
- X-Forwarded-Host: [fd20:8b1e:b255:8154:250:56ff:fea8:4d84]:1234, forward2.example.com:5678
- X-Forwarded-Server: server1.example.com, server2.example.com
- X-Requested-With: XMLHttpRequest
- Connection: Keep-Alive
-
- _end_of_message_
- msg.gsub!(/^ {6}/, "")
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert_equal("server1.example.com", req.server_name)
- assert_equal("https://[fd20:8b1e:b255:8154:250:56ff:fea8:4d84]:1234/foo", req.request_uri.to_s)
- assert_equal("[fd20:8b1e:b255:8154:250:56ff:fea8:4d84]", req.host)
- assert_equal(1234, req.port)
- assert_equal("234.234.234.234", req.remote_ip)
- assert(req.ssl?)
- end
-
- def test_continue_sent
- msg = <<-_end_of_message_
- POST /path HTTP/1.1
- Expect: 100-continue
-
- _end_of_message_
- msg.gsub!(/^ {6}/, "")
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert req['expect']
- l = msg.size
- req.continue
- assert_not_equal l, msg.size
- assert_match(/HTTP\/1.1 100 continue\r\n\r\n\z/, msg)
- assert !req['expect']
- end
-
- def test_continue_not_sent
- msg = <<-_end_of_message_
- POST /path HTTP/1.1
-
- _end_of_message_
- msg.gsub!(/^ {6}/, "")
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg))
- assert !req['expect']
- l = msg.size
- req.continue
- assert_equal l, msg.size
- end
-
- def test_bad_messages
- param = "foo=1;foo=2;foo=3;bar=x"
- msg = <<-_end_of_message_
- POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
- Host: test.ruby-lang.org:8080
- Content-Type: application/x-www-form-urlencoded
-
- #{param}
- _end_of_message_
- assert_raise(WEBrick::HTTPStatus::LengthRequired){
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- req.body
- }
-
- msg = <<-_end_of_message_
- POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
- Host: test.ruby-lang.org:8080
- Content-Length: 100000
-
- body is too short.
- _end_of_message_
- assert_raise(WEBrick::HTTPStatus::BadRequest){
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- req.body
- }
-
- msg = <<-_end_of_message_
- POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
- Host: test.ruby-lang.org:8080
- Transfer-Encoding: foobar
-
- body is too short.
- _end_of_message_
- assert_raise(WEBrick::HTTPStatus::NotImplemented){
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
- req.body
- }
- end
-
- def test_eof_raised_when_line_is_nil
- assert_raise(WEBrick::HTTPStatus::EOFError) {
- req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
- req.parse(StringIO.new(""))
- }
- end
-end
diff --git a/test/webrick/test_httpresponse.rb b/test/webrick/test_httpresponse.rb
deleted file mode 100644
index e8c69a1212..0000000000
--- a/test/webrick/test_httpresponse.rb
+++ /dev/null
@@ -1,282 +0,0 @@
-# frozen_string_literal: false
-require "webrick"
-require "minitest/autorun"
-require "stringio"
-require "net/http"
-
-module WEBrick
- class TestHTTPResponse < MiniTest::Unit::TestCase
- class FakeLogger
- attr_reader :messages
-
- def initialize
- @messages = []
- end
-
- def warn msg
- @messages << msg
- end
- end
-
- attr_reader :config, :logger, :res
-
- def setup
- super
- @logger = FakeLogger.new
- @config = Config::HTTP
- @config[:Logger] = logger
- @res = HTTPResponse.new config
- @res.keep_alive = true
- end
-
- def test_prevent_response_splitting_headers_crlf
- res['X-header'] = "malicious\r\nCookie: hack"
- io = StringIO.new
- res.send_response io
- io.rewind
- res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
- assert_equal '500', res.code
- refute_match 'hack', io.string
- end
-
- def test_prevent_response_splitting_cookie_headers_crlf
- user_input = "malicious\r\nCookie: hack"
- res.cookies << WEBrick::Cookie.new('author', user_input)
- io = StringIO.new
- res.send_response io
- io.rewind
- res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
- assert_equal '500', res.code
- refute_match 'hack', io.string
- end
-
- def test_prevent_response_splitting_headers_cr
- res['X-header'] = "malicious\rCookie: hack"
- io = StringIO.new
- res.send_response io
- io.rewind
- res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
- assert_equal '500', res.code
- refute_match 'hack', io.string
- end
-
- def test_prevent_response_splitting_cookie_headers_cr
- user_input = "malicious\rCookie: hack"
- res.cookies << WEBrick::Cookie.new('author', user_input)
- io = StringIO.new
- res.send_response io
- io.rewind
- res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
- assert_equal '500', res.code
- refute_match 'hack', io.string
- end
-
- def test_prevent_response_splitting_headers_lf
- res['X-header'] = "malicious\nCookie: hack"
- io = StringIO.new
- res.send_response io
- io.rewind
- res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
- assert_equal '500', res.code
- refute_match 'hack', io.string
- end
-
- def test_prevent_response_splitting_cookie_headers_lf
- user_input = "malicious\nCookie: hack"
- res.cookies << WEBrick::Cookie.new('author', user_input)
- io = StringIO.new
- res.send_response io
- io.rewind
- res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
- assert_equal '500', res.code
- refute_match 'hack', io.string
- end
-
- def test_set_redirect_response_splitting
- url = "malicious\r\nCookie: hack"
- assert_raises(URI::InvalidURIError) do
- res.set_redirect(WEBrick::HTTPStatus::MultipleChoices, url)
- end
- end
-
- def test_set_redirect_html_injection
- url = 'http://example.com////?a</a><head></head><body><img src=1></body>'
- assert_raises(WEBrick::HTTPStatus::MultipleChoices) do
- res.set_redirect(WEBrick::HTTPStatus::MultipleChoices, url)
- end
- res.status = 300
- io = StringIO.new
- res.send_response(io)
- io.rewind
- res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
- assert_equal '300', res.code
- refute_match(/<img/, io.string)
- end
-
- def test_304_does_not_log_warning
- res.status = 304
- res.setup_header
- assert_equal 0, logger.messages.length
- end
-
- def test_204_does_not_log_warning
- res.status = 204
- res.setup_header
-
- assert_equal 0, logger.messages.length
- end
-
- def test_1xx_does_not_log_warnings
- res.status = 105
- res.setup_header
-
- assert_equal 0, logger.messages.length
- end
-
- def test_200_chunked_does_not_set_content_length
- res.chunked = false
- res["Transfer-Encoding"] = 'chunked'
- res.setup_header
- assert_nil res.header.fetch('content-length', nil)
- end
-
- def test_send_body_io
- IO.pipe {|body_r, body_w|
- body_w.write 'hello'
- body_w.close
-
- @res.body = body_r
-
- IO.pipe {|r, w|
-
- @res.send_body w
-
- w.close
-
- assert_equal 'hello', r.read
- }
- }
- assert_equal 0, logger.messages.length
- end
-
- def test_send_body_string
- @res.body = 'hello'
-
- IO.pipe {|r, w|
- @res.send_body w
-
- w.close
-
- assert_equal 'hello', r.read
- }
- assert_equal 0, logger.messages.length
- end
-
- def test_send_body_string_io
- @res.body = StringIO.new 'hello'
-
- IO.pipe {|r, w|
- @res.send_body w
-
- w.close
-
- assert_equal 'hello', r.read
- }
- assert_equal 0, logger.messages.length
- end
-
- def test_send_body_io_chunked
- @res.chunked = true
-
- IO.pipe {|body_r, body_w|
-
- body_w.write 'hello'
- body_w.close
-
- @res.body = body_r
-
- IO.pipe {|r, w|
- @res.send_body w
-
- w.close
-
- r.binmode
- assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
- }
- }
- assert_equal 0, logger.messages.length
- end
-
- def test_send_body_string_chunked
- @res.chunked = true
-
- @res.body = 'hello'
-
- IO.pipe {|r, w|
- @res.send_body w
-
- w.close
-
- r.binmode
- assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
- }
- assert_equal 0, logger.messages.length
- end
-
- def test_send_body_string_io_chunked
- @res.chunked = true
-
- @res.body = StringIO.new 'hello'
-
- IO.pipe {|r, w|
- @res.send_body w
-
- w.close
-
- r.binmode
- assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
- }
- assert_equal 0, logger.messages.length
- end
-
- def test_send_body_proc
- @res.body = Proc.new { |out| out.write('hello') }
- IO.pipe do |r, w|
- @res.send_body(w)
- w.close
- r.binmode
- assert_equal 'hello', r.read
- end
- assert_equal 0, logger.messages.length
- end
-
- def test_send_body_proc_chunked
- @res.body = Proc.new { |out| out.write('hello') }
- @res.chunked = true
- IO.pipe do |r, w|
- @res.send_body(w)
- w.close
- r.binmode
- assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
- end
- assert_equal 0, logger.messages.length
- end
-
- def test_set_error
- status = 400
- message = 'missing attribute'
- @res.status = status
- error = WEBrick::HTTPStatus[status].new(message)
- body = @res.set_error(error)
- assert_match(/#{@res.reason_phrase}/, body)
- assert_match(/#{message}/, body)
- end
-
- def test_no_extraneous_space
- [200, 300, 400, 500].each do |status|
- @res.status = status
- assert_match(/\S\r\n/, @res.status_line)
- end
- end
- end
-end
diff --git a/test/webrick/test_httpserver.rb b/test/webrick/test_httpserver.rb
deleted file mode 100644
index 2e5d44940c..0000000000
--- a/test/webrick/test_httpserver.rb
+++ /dev/null
@@ -1,543 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "net/http"
-require "webrick"
-require_relative "utils"
-
-class TestWEBrickHTTPServer < Test::Unit::TestCase
- empty_log = Object.new
- def empty_log.<<(str)
- assert_equal('', str)
- self
- end
- NoLog = WEBrick::Log.new(empty_log, WEBrick::BasicLog::WARN)
-
- def teardown
- WEBrick::Utils::TimeoutHandler.terminate
- super
- end
-
- def test_mount
- httpd = WEBrick::HTTPServer.new(
- :Logger => NoLog,
- :DoNotListen=>true
- )
- httpd.mount("/", :Root)
- httpd.mount("/foo", :Foo)
- httpd.mount("/foo/bar", :Bar, :bar1)
- httpd.mount("/foo/bar/baz", :Baz, :baz1, :baz2)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/")
- assert_equal(:Root, serv)
- assert_equal([], opts)
- assert_equal("", script_name)
- assert_equal("/", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/sub")
- assert_equal(:Root, serv)
- assert_equal([], opts)
- assert_equal("", script_name)
- assert_equal("/sub", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/sub/")
- assert_equal(:Root, serv)
- assert_equal([], opts)
- assert_equal("", script_name)
- assert_equal("/sub/", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo")
- assert_equal(:Foo, serv)
- assert_equal([], opts)
- assert_equal("/foo", script_name)
- assert_equal("", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo/")
- assert_equal(:Foo, serv)
- assert_equal([], opts)
- assert_equal("/foo", script_name)
- assert_equal("/", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo/sub")
- assert_equal(:Foo, serv)
- assert_equal([], opts)
- assert_equal("/foo", script_name)
- assert_equal("/sub", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar")
- assert_equal(:Bar, serv)
- assert_equal([:bar1], opts)
- assert_equal("/foo/bar", script_name)
- assert_equal("", path_info)
-
- serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar/baz")
- assert_equal(:Baz, serv)
- assert_equal([:baz1, :baz2], opts)
- assert_equal("/foo/bar/baz", script_name)
- assert_equal("", path_info)
- end
-
- class Req
- attr_reader :port, :host
- def initialize(addr, port, host)
- @addr, @port, @host = addr, port, host
- end
- def addr
- [0,0,0,@addr]
- end
- end
-
- def httpd(addr, port, host, ali)
- config ={
- :Logger => NoLog,
- :DoNotListen => true,
- :BindAddress => addr,
- :Port => port,
- :ServerName => host,
- :ServerAlias => ali,
- }
- return WEBrick::HTTPServer.new(config)
- end
-
- def assert_eql?(v1, v2)
- assert_equal(v1.object_id, v2.object_id)
- end
-
- def test_lookup_server
- addr1 = "192.168.100.1"
- addr2 = "192.168.100.2"
- addrz = "192.168.100.254"
- local = "127.0.0.1"
- port1 = 80
- port2 = 8080
- port3 = 10080
- portz = 32767
- name1 = "www.example.com"
- name2 = "www2.example.com"
- name3 = "www3.example.com"
- namea = "www.example.co.jp"
- nameb = "www.example.jp"
- namec = "www2.example.co.jp"
- named = "www2.example.jp"
- namez = "foobar.example.com"
- alias1 = [namea, nameb]
- alias2 = [namec, named]
-
- host1 = httpd(nil, port1, name1, nil)
- hosts = [
- host2 = httpd(addr1, port1, name1, nil),
- host3 = httpd(addr1, port1, name2, alias1),
- host4 = httpd(addr1, port2, name1, nil),
- host5 = httpd(addr1, port2, name2, alias1),
- httpd(addr1, port2, name3, alias2),
- host7 = httpd(addr2, nil, name1, nil),
- host8 = httpd(addr2, nil, name2, alias1),
- httpd(addr2, nil, name3, alias2),
- host10 = httpd(local, nil, nil, nil),
- host11 = httpd(nil, port3, nil, nil),
- ].sort_by{ rand }
- hosts.each{|h| host1.virtual_host(h) }
-
- # connect to addr1
- assert_eql?(host2, host1.lookup_server(Req.new(addr1, port1, name1)))
- assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, name2)))
- assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, namea)))
- assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, port1, namez)))
- assert_eql?(host4, host1.lookup_server(Req.new(addr1, port2, name1)))
- assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, name2)))
- assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, namea)))
- assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, port2, namez)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name1)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name2)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namea)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, nameb)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namez)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name1)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name2)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namea)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namez)))
-
- # connect to addr2
- assert_eql?(host7, host1.lookup_server(Req.new(addr2, port1, name1)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, name2)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, namea)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr2, port1, namez)))
- assert_eql?(host7, host1.lookup_server(Req.new(addr2, port2, name1)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, name2)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, namea)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr2, port2, namez)))
- assert_eql?(host7, host1.lookup_server(Req.new(addr2, port3, name1)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, name2)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, namea)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, nameb)))
- assert_eql?(host11, host1.lookup_server(Req.new(addr2, port3, namez)))
- assert_eql?(host7, host1.lookup_server(Req.new(addr2, portz, name1)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, name2)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, namea)))
- assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addr2, portz, namez)))
-
- # connect to addrz
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name1)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name2)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namea)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namez)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name1)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name2)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namea)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namez)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name1)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name2)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namea)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, nameb)))
- assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namez)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name1)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name2)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namea)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, nameb)))
- assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namez)))
-
- # connect to localhost
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name1)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name2)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namea)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, nameb)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namez)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name1)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name2)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namea)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, nameb)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namez)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name1)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name2)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namea)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, nameb)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namez)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name1)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name2)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namea)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, nameb)))
- assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namez)))
- end
-
- def test_callbacks
- accepted = started = stopped = 0
- requested0 = requested1 = 0
- config = {
- :ServerName => "localhost",
- :AcceptCallback => Proc.new{ accepted += 1 },
- :StartCallback => Proc.new{ started += 1 },
- :StopCallback => Proc.new{ stopped += 1 },
- :RequestCallback => Proc.new{|req, res| requested0 += 1 },
- }
- log_tester = lambda {|log, access_log|
- assert(log.find {|s| %r{ERROR `/' not found\.} =~ s })
- assert_equal([], log.reject {|s| %r{ERROR `/' not found\.} =~ s })
- }
- TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
- vhost_config = {
- :ServerName => "myhostname",
- :BindAddress => addr,
- :Port => port,
- :DoNotListen => true,
- :Logger => NoLog,
- :AccessLog => [],
- :RequestCallback => Proc.new{|req, res| requested1 += 1 },
- }
- server.virtual_host(WEBrick::HTTPServer.new(vhost_config))
-
- Thread.pass while server.status != :Running
- sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # server.status behaves unexpectedly with --jit-wait
- assert_equal(1, started, log.call)
- assert_equal(0, stopped, log.call)
- assert_equal(0, accepted, log.call)
-
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/")
- req["Host"] = "myhostname:#{port}"
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- req["Host"] = "localhost:#{port}"
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- assert_equal(6, accepted, log.call)
- assert_equal(3, requested0, log.call)
- assert_equal(3, requested1, log.call)
- }
- assert_equal(started, 1)
- assert_equal(stopped, 1)
- end
-
- class CustomRequest < ::WEBrick::HTTPRequest; end
- class CustomResponse < ::WEBrick::HTTPResponse; end
- class CustomServer < ::WEBrick::HTTPServer
- def create_request(config)
- CustomRequest.new(config)
- end
-
- def create_response(config)
- CustomResponse.new(config)
- end
- end
-
- def test_custom_server_request_and_response
- config = { :ServerName => "localhost" }
- TestWEBrick.start_server(CustomServer, config){|server, addr, port, log|
- server.mount_proc("/", lambda {|req, res|
- assert_kind_of(CustomRequest, req)
- assert_kind_of(CustomResponse, res)
- res.body = "via custom response"
- })
- Thread.pass while server.status != :Running
-
- Net::HTTP.start(addr, port) do |http|
- req = Net::HTTP::Get.new("/")
- http.request(req){|res|
- assert_equal("via custom response", res.body)
- }
- server.shutdown
- end
- }
- end
-
- # This class is needed by test_response_io_with_chunked_set method
- class EventManagerForChunkedResponseTest
- def initialize
- @listeners = []
- end
- def add_listener( &block )
- @listeners << block
- end
- def raise_str_event( str )
- @listeners.each{ |e| e.call( :str, str ) }
- end
- def raise_close_event()
- @listeners.each{ |e| e.call( :cls ) }
- end
- end
- def test_response_io_with_chunked_set
- evt_man = EventManagerForChunkedResponseTest.new
- t = Thread.new do
- begin
- config = {
- :ServerName => "localhost"
- }
- TestWEBrick.start_httpserver(config) do |server, addr, port, log|
- body_strs = [ 'aaaaaa', 'bb', 'cccc' ]
- server.mount_proc( "/", ->( req, res ){
- # Test for setting chunked...
- res.chunked = true
- r,w = IO.pipe
- evt_man.add_listener do |type,str|
- type == :cls ? ( w.close ) : ( w << str )
- end
- res.body = r
- } )
- Thread.pass while server.status != :Running
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/")
- http.request(req) do |res|
- i = 0
- evt_man.raise_str_event( body_strs[i] )
- res.read_body do |s|
- assert_equal( body_strs[i], s )
- i += 1
- if i < body_strs.length
- evt_man.raise_str_event( body_strs[i] )
- else
- evt_man.raise_close_event()
- end
- end
- assert_equal( body_strs.length, i )
- end
- end
- rescue => err
- flunk( 'exception raised in thread: ' + err.to_s )
- end
- end
- if t.join( 3 ).nil?
- evt_man.raise_close_event()
- flunk( 'timeout' )
- if t.join( 1 ).nil?
- Thread.kill t
- end
- end
- end
-
- def test_response_io_without_chunked_set
- config = {
- :ServerName => "localhost"
- }
- log_tester = lambda {|log, access_log|
- assert_equal(1, log.length)
- assert_match(/WARN Could not determine content-length of response body./, log[0])
- }
- TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
- server.mount_proc("/", lambda { |req, res|
- r,w = IO.pipe
- # Test for not setting chunked...
- # res.chunked = true
- res.body = r
- w << "foo"
- w.close
- })
- Thread.pass while server.status != :Running
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/")
- req['Connection'] = 'Keep-Alive'
- begin
- Timeout.timeout(2) do
- http.request(req){|res| assert_equal("foo", res.body) }
- end
- rescue Timeout::Error
- flunk('corrupted response')
- end
- }
- end
-
- def test_request_handler_callback_is_deprecated
- requested = 0
- config = {
- :ServerName => "localhost",
- :RequestHandler => Proc.new{|req, res| requested += 1 },
- }
- log_tester = lambda {|log, access_log|
- assert_equal(2, log.length)
- assert_match(/WARN :RequestHandler is deprecated, please use :RequestCallback/, log[0])
- assert_match(%r{ERROR `/' not found\.}, log[1])
- }
- TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
- Thread.pass while server.status != :Running
-
- http = Net::HTTP.new(addr, port)
- req = Net::HTTP::Get.new("/")
- req["Host"] = "localhost:#{port}"
- http.request(req){|res| assert_equal("404", res.code, log.call)}
- assert_match(%r{:RequestHandler is deprecated, please use :RequestCallback$}, log.call, log.call)
- }
- assert_equal(1, requested)
- end
-
- def test_shutdown_with_busy_keepalive_connection
- requested = 0
- config = {
- :ServerName => "localhost",
- }
- TestWEBrick.start_httpserver(config){|server, addr, port, log|
- server.mount_proc("/", lambda {|req, res| res.body = "heffalump" })
- Thread.pass while server.status != :Running
-
- Net::HTTP.start(addr, port) do |http|
- req = Net::HTTP::Get.new("/")
- http.request(req){|res| assert_equal('Keep-Alive', res['Connection'], log.call) }
- server.shutdown
- begin
- 10.times {|n| http.request(req); requested += 1 }
- rescue
- # Errno::ECONNREFUSED or similar
- end
- end
- }
- assert_equal(0, requested, "Server responded to #{requested} requests after shutdown")
- end
-
- def test_cntrl_in_path
- log_ary = []
- access_log_ary = []
- config = {
- :Port => 0,
- :BindAddress => '127.0.0.1',
- :Logger => WEBrick::Log.new(log_ary, WEBrick::BasicLog::WARN),
- :AccessLog => [[access_log_ary, '']],
- }
- s = WEBrick::HTTPServer.new(config)
- s.mount('/foo', WEBrick::HTTPServlet::FileHandler, __FILE__)
- th = Thread.new { s.start }
- addr = s.listeners[0].addr
-
- http = Net::HTTP.new(addr[3], addr[1])
- req = Net::HTTP::Get.new('/notexist%0a/foo')
- http.request(req) { |res| assert_equal('404', res.code) }
- exp = %Q(ERROR `/notexist\\n/foo' not found.\n)
- assert_equal 1, log_ary.size
- assert_include log_ary[0], exp
- ensure
- s&.shutdown
- th&.join
- end
-
- def test_gigantic_request_header
- log_tester = lambda {|log, access_log|
- assert_equal 1, log.size
- assert_include log[0], 'ERROR headers too large'
- }
- TestWEBrick.start_httpserver({}, log_tester){|server, addr, port, log|
- server.mount('/', WEBrick::HTTPServlet::FileHandler, __FILE__)
- TCPSocket.open(addr, port) do |c|
- c.write("GET / HTTP/1.0\r\n")
- junk = -"X-Junk: #{' ' * 1024}\r\n"
- assert_raise(Errno::ECONNRESET, Errno::EPIPE) do
- loop { c.write(junk) }
- end
- end
- }
- end
-
- def test_eof_in_chunk
- log_tester = lambda do |log, access_log|
- assert_equal 1, log.size
- assert_include log[0], 'ERROR bad chunk data size'
- end
- TestWEBrick.start_httpserver({}, log_tester){|server, addr, port, log|
- server.mount_proc('/', ->(req, res) { res.body = req.body })
- TCPSocket.open(addr, port) do |c|
- c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
- "Transfer-Encoding: chunked\r\n\r\n5\r\na")
- c.shutdown(Socket::SHUT_WR) # trigger EOF in server
- res = c.read
- assert_match %r{\AHTTP/1\.1 400 }, res
- end
- }
- end
-
- def test_big_chunks
- nr_out = 3
- buf = 'big' # 3 bytes is bigger than 2!
- config = { :InputBufferSize => 2 }.freeze
- total = 0
- all = ''
- TestWEBrick.start_httpserver(config){|server, addr, port, log|
- server.mount_proc('/', ->(req, res) {
- err = []
- ret = req.body do |chunk|
- n = chunk.bytesize
- n > config[:InputBufferSize] and err << "#{n} > :InputBufferSize"
- total += n
- all << chunk
- end
- ret.nil? or err << 'req.body should return nil'
- (buf * nr_out) == all or err << 'input body does not match expected'
- res.header['connection'] = 'close'
- res.body = err.join("\n")
- })
- TCPSocket.open(addr, port) do |c|
- c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
- "Transfer-Encoding: chunked\r\n\r\n")
- chunk = "#{buf.bytesize.to_s(16)}\r\n#{buf}\r\n"
- nr_out.times { c.write(chunk) }
- c.write("0\r\n\r\n")
- head, body = c.read.split("\r\n\r\n")
- assert_match %r{\AHTTP/1\.1 200 OK}, head
- assert_nil body
- end
- }
- end
-end
diff --git a/test/webrick/test_server.rb b/test/webrick/test_server.rb
deleted file mode 100644
index 8162a186db..0000000000
--- a/test/webrick/test_server.rb
+++ /dev/null
@@ -1,163 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "tempfile"
-require "webrick"
-require_relative "utils"
-
-class TestWEBrickServer < Test::Unit::TestCase
- class Echo < WEBrick::GenericServer
- def run(sock)
- while line = sock.gets
- sock << line
- end
- end
- end
-
- def test_server
- TestWEBrick.start_server(Echo){|server, addr, port, log|
- TCPSocket.open(addr, port){|sock|
- sock.puts("foo"); assert_equal("foo\n", sock.gets, log.call)
- sock.puts("bar"); assert_equal("bar\n", sock.gets, log.call)
- sock.puts("baz"); assert_equal("baz\n", sock.gets, log.call)
- sock.puts("qux"); assert_equal("qux\n", sock.gets, log.call)
- }
- }
- end
-
- def test_start_exception
- stopped = 0
-
- log = []
- logger = WEBrick::Log.new(log, WEBrick::BasicLog::WARN)
-
- assert_raise(SignalException) do
- listener = Object.new
- def listener.to_io # IO.select invokes #to_io.
- raise SignalException, 'SIGTERM' # simulate signal in main thread
- end
- def listener.shutdown
- end
- def listener.close
- end
-
- server = WEBrick::HTTPServer.new({
- :BindAddress => "127.0.0.1", :Port => 0,
- :StopCallback => Proc.new{ stopped += 1 },
- :Logger => logger,
- })
- server.listeners[0].close
- server.listeners[0] = listener
-
- server.start
- end
-
- assert_equal(1, stopped)
- assert_equal(1, log.length)
- assert_match(/FATAL SignalException: SIGTERM/, log[0])
- end
-
- def test_callbacks
- accepted = started = stopped = 0
- config = {
- :AcceptCallback => Proc.new{ accepted += 1 },
- :StartCallback => Proc.new{ started += 1 },
- :StopCallback => Proc.new{ stopped += 1 },
- }
- TestWEBrick.start_server(Echo, config){|server, addr, port, log|
- true while server.status != :Running
- sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # server.status behaves unexpectedly with --jit-wait
- assert_equal(1, started, log.call)
- assert_equal(0, stopped, log.call)
- assert_equal(0, accepted, log.call)
- TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
- TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
- TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
- assert_equal(3, accepted, log.call)
- }
- assert_equal(1, started)
- assert_equal(1, stopped)
- end
-
- def test_daemon
- begin
- r, w = IO.pipe
- pid1 = Process.fork{
- r.close
- WEBrick::Daemon.start
- w.puts(Process.pid)
- sleep 10
- }
- pid2 = r.gets.to_i
- assert(Process.kill(:KILL, pid2))
- assert_not_equal(pid1, pid2)
- rescue NotImplementedError
- # snip this test
- ensure
- Process.wait(pid1) if pid1
- r.close
- w.close
- end
- end
-
- def test_restart_after_shutdown
- address = '127.0.0.1'
- port = 0
- log = []
- config = {
- :BindAddress => address,
- :Port => port,
- :Logger => WEBrick::Log.new(log, WEBrick::BasicLog::WARN),
- }
- server = Echo.new(config)
- client_proc = lambda {|str|
- begin
- ret = server.listeners.first.connect_address.connect {|s|
- s.write(str)
- s.close_write
- s.read
- }
- assert_equal(str, ret)
- ensure
- server.shutdown
- end
- }
- server_thread = Thread.new { server.start }
- client_thread = Thread.new { client_proc.call("a") }
- assert_join_threads([client_thread, server_thread])
- server.listen(address, port)
- server_thread = Thread.new { server.start }
- client_thread = Thread.new { client_proc.call("b") }
- assert_join_threads([client_thread, server_thread])
- assert_equal([], log)
- end
-
- def test_restart_after_stop
- log = Object.new
- class << log
- include Test::Unit::Assertions
- def <<(msg)
- flunk "unexpected log: #{msg.inspect}"
- end
- end
- client_thread = nil
- wakeup = -> {client_thread.wakeup}
- warn_flunk = WEBrick::Log.new(log, WEBrick::BasicLog::WARN)
- server = WEBrick::HTTPServer.new(
- :StartCallback => wakeup,
- :StopCallback => wakeup,
- :BindAddress => '0.0.0.0',
- :Port => 0,
- :Logger => warn_flunk)
- 2.times {
- server_thread = Thread.start {
- server.start
- }
- client_thread = Thread.start {
- sleep 0.1 until server.status == :Running || !server_thread.status
- server.stop
- sleep 0.1 until server.status == :Stop || !server_thread.status
- }
- assert_join_threads([client_thread, server_thread])
- }
- end
-end
diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb
index e2cb4e3755..c469d24dfc 100644
--- a/test/zlib/test_zlib.rb
+++ b/test/zlib/test_zlib.rb
@@ -3,6 +3,7 @@
require 'test/unit'
require 'stringio'
require 'tempfile'
+require 'tmpdir'
require 'securerandom'
begin
@@ -364,6 +365,65 @@ if defined? Zlib
}
end
+ def test_inflate_buffer
+ s = Zlib::Deflate.deflate("foo")
+ z = Zlib::Inflate.new
+ buf = String.new
+ s = z.inflate(s, buffer: buf)
+ assert_same(buf, s)
+ buf = String.new
+ s << z.inflate(nil, buffer: buf)
+ assert_equal("foo", s)
+ z.inflate("foo", buffer: buf) # ???
+ z << "foo" # ???
+ end
+
+ def test_inflate_buffer_partial_input
+ deflated = Zlib::Deflate.deflate "\0"
+
+ z = Zlib::Inflate.new
+
+ inflated = "".dup
+
+ buf = String.new
+ deflated.each_char do |byte|
+ inflated << z.inflate(byte, buffer: buf)
+ end
+
+ inflated << z.finish
+
+ assert_equal "\0", inflated
+ end
+
+ def test_inflate_buffer_chunked
+ # s = Zlib::Deflate.deflate("0" * 100_000)
+ zeros = "x\234\355\3011\001\000\000\000\302\240J\353\237\316\032\036@" \
+ "\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \
+ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" \
+ "\000\000\000\000\000\000\000\257\006\351\247BH"
+
+ chunks = []
+
+ z = Zlib::Inflate.new
+
+ buf = String.new
+ z.inflate(zeros, buffer: buf) do |chunk|
+ assert_same(buf, chunk)
+ chunks << chunk.dup
+ end
+
+ assert_equal [16384, 16384, 16384, 16384, 16384, 16384, 1696],
+ chunks.map { |chunk| chunk.size }
+
+ assert chunks.all? { |chunk|
+ chunk =~ /\A0+\z/
+ }
+ end
+
def test_inflate_chunked_break
# zeros = Zlib::Deflate.deflate("0" * 100_000)
zeros = "x\234\355\3011\001\000\000\000\302\240J\353\237\316\032\036@" \
@@ -447,6 +507,7 @@ if defined? Zlib
def test_multithread_deflate
zd = Zlib::Deflate.new
+
s = "x" * 10000
(0...10).map do |x|
Thread.new do
@@ -462,6 +523,7 @@ if defined? Zlib
def test_multithread_inflate
zi = Zlib::Inflate.new
+
s = Zlib.deflate("x" * 10000)
(0...10).map do |x|
Thread.new do
@@ -511,6 +573,30 @@ if defined? Zlib
end
class TestZlibGzipFile < Test::Unit::TestCase
+ def test_gzip_reader_zcat
+ Tempfile.create("test_zlib_gzip_file_to_io") {|t|
+ gz = Zlib::GzipWriter.new(t)
+ gz.print("foo")
+ gz.close
+ t = File.open(t.path, 'ab')
+ gz = Zlib::GzipWriter.new(t)
+ gz.print("bar")
+ gz.close
+
+ results = []
+ t = File.open(t.path)
+ Zlib::GzipReader.zcat(t) do |str|
+ results << str
+ end
+ assert_equal(["foo", "bar"], results)
+ t.close
+
+ t = File.open(t.path)
+ assert_equal("foobar", Zlib::GzipReader.zcat(t))
+ t.close
+ }
+ end
+
def test_to_io
Tempfile.create("test_zlib_gzip_file_to_io") {|t|
t.close
@@ -702,6 +788,26 @@ if defined? Zlib
gz.close
}
end
+
+ if defined? File::TMPFILE
+ def test_path_tmpfile
+ sio = StringIO.new("".dup, 'w')
+ gz = Zlib::GzipWriter.new(sio)
+ gz.write "hi"
+ gz.close
+
+ File.open(Dir.mktmpdir, File::RDWR | File::TMPFILE) do |io|
+ io.write sio.string
+ io.rewind
+
+ gz = Zlib::GzipWriter.new(io)
+ assert_raise(NoMethodError) { gz.path }
+
+ gz = Zlib::GzipReader.new(io)
+ assert_raise(NoMethodError) { gz.path }
+ end
+ end
+ end
end
class TestZlibGzipReader < Test::Unit::TestCase
@@ -1186,6 +1292,19 @@ if defined? Zlib
assert_equal(0x02820145, Zlib.adler32("foo"))
assert_equal(0x02820145, Zlib.adler32("o", Zlib.adler32("fo")))
assert_equal(0x8a62c964, Zlib.adler32("abc\x01\x02\x03" * 10000))
+ Tempfile.create("test_zlib_gzip_file_to_io") {|t|
+ File.binwrite(t.path, "foo")
+ t.rewind
+ assert_equal(0x02820145, Zlib.adler32(t))
+
+ t.rewind
+ crc = Zlib.adler32(t.read(2))
+ assert_equal(0x02820145, Zlib.adler32(t, crc))
+
+ File.binwrite(t.path, "abc\x01\x02\x03" * 10000)
+ t.rewind
+ assert_equal(0x8a62c964, Zlib.adler32(t))
+ }
end
def test_adler32_combine
@@ -1208,6 +1327,19 @@ if defined? Zlib
assert_equal(0x8c736521, Zlib.crc32("foo"))
assert_equal(0x8c736521, Zlib.crc32("o", Zlib.crc32("fo")))
assert_equal(0x07f0d68f, Zlib.crc32("abc\x01\x02\x03" * 10000))
+ Tempfile.create("test_zlib_gzip_file_to_io") {|t|
+ File.binwrite(t.path, "foo")
+ t.rewind
+ assert_equal(0x8c736521, Zlib.crc32(t))
+
+ t.rewind
+ crc = Zlib.crc32(t.read(2))
+ assert_equal(0x8c736521, Zlib.crc32(t, crc))
+
+ File.binwrite(t.path, "abc\x01\x02\x03" * 10000)
+ t.rewind
+ assert_equal(0x07f0d68f, Zlib.crc32(t))
+ }
end
def test_crc32_combine
diff --git a/thread.c b/thread.c
index be6b46b155..59279ef8ff 100644
--- a/thread.c
+++ b/thread.c
@@ -63,24 +63,40 @@
/* for model 2 */
-#include "ruby/config.h"
-#include "ruby/io.h"
+#include "ruby/internal/config.h"
+
+#ifdef __linux__
+// Normally, gcc(1) translates calls to alloca() with inlined code. This is not done when either the -ansi, -std=c89, -std=c99, or the -std=c11 option is given and the header <alloca.h> is not included.
+# include <alloca.h>
+#endif
+
#include "eval_intern.h"
-#include "timev.h"
-#include "ruby/thread.h"
-#include "ruby/thread_native.h"
-#include "ruby/debug.h"
#include "gc.h"
+#include "hrtime.h"
#include "internal.h"
+#include "internal/class.h"
+#include "internal/cont.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/io.h"
+#include "internal/object.h"
+#include "internal/proc.h"
+#include "internal/scheduler.h"
+#include "internal/signal.h"
+#include "internal/thread.h"
+#include "internal/time.h"
+#include "internal/warnings.h"
#include "iseq.h"
-#include "vm_core.h"
#include "mjit.h"
-#include "hrtime.h"
-
-#ifdef __linux__
-// Normally, gcc(1) translates calls to alloca() with inlined code. This is not done when either the -ansi, -std=c89, -std=c99, or the -std=c11 option is given and the header <alloca.h> is not included.
-#include <alloca.h>
-#endif
+#include "ruby/debug.h"
+#include "ruby/io.h"
+#include "ruby/thread.h"
+#include "ruby/thread_native.h"
+#include "timev.h"
+#include "vm_core.h"
+#include "ractor_core.h"
+#include "vm_debug.h"
+#include "vm_sync.h"
#ifndef USE_NATIVE_THREAD_PRIORITY
#define USE_NATIVE_THREAD_PRIORITY 0
@@ -118,9 +134,9 @@ rb_thread_local_storage(VALUE thread)
static void sleep_hrtime(rb_thread_t *, rb_hrtime_t, unsigned int fl);
static void sleep_forever(rb_thread_t *th, unsigned int fl);
-static void rb_thread_sleep_deadly_allow_spurious_wakeup(void);
+static void rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker);
static int rb_threadptr_dead(rb_thread_t *th);
-static void rb_check_deadlock(rb_vm_t *vm);
+static void rb_check_deadlock(rb_ractor_t *r);
static int rb_threadptr_pending_interrupt_empty_p(const rb_thread_t *th);
static const char *thread_status_name(rb_thread_t *th, int detail);
static int hrtime_update_expire(rb_hrtime_t *, const rb_hrtime_t);
@@ -139,12 +155,6 @@ struct waiting_fd {
int fd;
};
-inline static void
-st_delete_wrap(st_table *table, st_data_t key)
-{
- st_delete(table, &key, 0);
-}
-
/********************************************************************************/
#define THREAD_SYSTEM_DEPENDENT_IMPLEMENTATION
@@ -160,20 +170,13 @@ static inline int blocking_region_begin(rb_thread_t *th, struct rb_blocking_regi
rb_unblock_function_t *ubf, void *arg, int fail_if_interrupted);
static inline void blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region);
-#define RB_GC_SAVE_MACHINE_CONTEXT(th) \
- do { \
- FLUSH_REGISTER_WINDOWS; \
- setjmp((th)->ec->machine.regs); \
- SET_MACHINE_STACK_END(&(th)->ec->machine.stack_end); \
- } while (0)
-
#define GVL_UNLOCK_BEGIN(th) do { \
RB_GC_SAVE_MACHINE_CONTEXT(th); \
- gvl_release(th->vm);
+ gvl_release(rb_ractor_gvl(th->ractor));
#define GVL_UNLOCK_END(th) \
- gvl_acquire(th->vm, th); \
- rb_thread_set_current(th); \
+ gvl_acquire(rb_ractor_gvl(th->ractor), th); \
+ rb_ractor_thread_switch(th->ractor, th); \
} while(0)
#ifdef __GNUC__
@@ -215,10 +218,10 @@ vm_check_ints_blocking(rb_execution_context_t *ec)
return rb_threadptr_execute_interrupts(th, 1);
}
-static int
-vm_living_thread_num(const rb_vm_t *vm)
+int
+rb_vm_check_ints_blocking(rb_execution_context_t *ec)
{
- return vm->living_thread_num;
+ return vm_check_ints_blocking(ec);
}
/*
@@ -304,7 +307,7 @@ static int rb_thread_debug_enabled;
*/
static VALUE
-rb_thread_s_debug(void)
+rb_thread_s_debug(VALUE _)
{
return INT2NUM(rb_thread_debug_enabled);
}
@@ -338,7 +341,6 @@ rb_thread_s_debug_set(VALUE self, VALUE val)
#endif
NOINLINE(static int thread_start_func_2(rb_thread_t *th, VALUE *stack_start));
-static void timer_thread_function(void);
void ruby_sigchld_handler(rb_vm_t *); /* signal.c */
static void
@@ -418,10 +420,10 @@ rb_thread_debug(
#include "thread_sync.c"
void
-rb_vm_gvl_destroy(rb_vm_t *vm)
+rb_vm_gvl_destroy(rb_global_vm_lock_t *gvl)
{
- gvl_release(vm);
- gvl_destroy(vm);
+ gvl_release(gvl);
+ gvl_destroy(gvl);
}
void
@@ -478,7 +480,7 @@ static void
unblock_function_clear(rb_thread_t *th)
{
rb_native_mutex_lock(&th->interrupt_lock);
- th->unblock.func = NULL;
+ th->unblock.func = 0;
rb_native_mutex_unlock(&th->interrupt_lock);
}
@@ -486,6 +488,7 @@ static void
rb_threadptr_interrupt_common(rb_thread_t *th, int trap)
{
rb_native_mutex_lock(&th->interrupt_lock);
+
if (trap) {
RUBY_VM_SET_TRAP_INTERRUPT(th->ec);
}
@@ -514,12 +517,12 @@ threadptr_trap_interrupt(rb_thread_t *th)
}
static void
-terminate_all(rb_vm_t *vm, const rb_thread_t *main_thread)
+terminate_all(rb_ractor_t *r, const rb_thread_t *main_thread)
{
rb_thread_t *th = 0;
- list_for_each(&vm->living_threads, th, vmlt_node) {
- if (th != main_thread) {
+ list_for_each(&r->threads.set, th, lt_node) {
+ if (th != main_thread) {
thread_debug("terminate_all: begin (thid: %"PRI_THREAD_ID", status: %s)\n",
thread_id_str(th), thread_status_name(th, TRUE));
rb_threadptr_pending_interrupt_enque(th, eTerminateSignal);
@@ -533,34 +536,57 @@ terminate_all(rb_vm_t *vm, const rb_thread_t *main_thread)
}
}
+static void
+rb_threadptr_join_list_wakeup(rb_thread_t *thread)
+{
+ while (thread->join_list) {
+ struct rb_waiting_list *join_list = thread->join_list;
+
+ // Consume the entry from the join list:
+ thread->join_list = join_list->next;
+
+ rb_thread_t *target_thread = join_list->thread;
+
+ if (target_thread->scheduler != Qnil && rb_fiberptr_blocking(join_list->fiber) == 0) {
+ rb_scheduler_unblock(target_thread->scheduler, target_thread->self, rb_fiberptr_self(join_list->fiber));
+ } else {
+ rb_threadptr_interrupt(target_thread);
+
+ switch (target_thread->status) {
+ case THREAD_STOPPED:
+ case THREAD_STOPPED_FOREVER:
+ target_thread->status = THREAD_RUNNABLE;
+ default:
+ break;
+ }
+ }
+ }
+}
+
void
rb_threadptr_unlock_all_locking_mutexes(rb_thread_t *th)
{
- const char *err;
- rb_mutex_t *mutex;
- rb_mutex_t *mutexes = th->keeping_mutexes;
+ while (th->keeping_mutexes) {
+ rb_mutex_t *mutex = th->keeping_mutexes;
+ th->keeping_mutexes = mutex->next_mutex;
+
+ /* rb_warn("mutex #<%p> remains to be locked by terminated thread", (void *)mutexes); */
- while (mutexes) {
- mutex = mutexes;
- /* rb_warn("mutex #<%p> remains to be locked by terminated thread",
- (void *)mutexes); */
- mutexes = mutex->next_mutex;
- err = rb_mutex_unlock_th(mutex, th);
- if (err) rb_bug("invalid keeping_mutexes: %s", err);
+ const char *error_message = rb_mutex_unlock_th(mutex, th, mutex->fiber);
+ if (error_message) rb_bug("invalid keeping_mutexes: %s", error_message);
}
}
void
-rb_thread_terminate_all(void)
+rb_thread_terminate_all(rb_thread_t *th)
{
- rb_thread_t *volatile th = GET_THREAD(); /* main thread */
+ rb_ractor_t *cr = th->ractor;
rb_execution_context_t * volatile ec = th->ec;
- rb_vm_t *volatile vm = th->vm;
volatile int sleeping = 0;
- if (vm->main_thread != th) {
- rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)",
- (void *)vm->main_thread, (void *)th);
+ if (cr->threads.main != th) {
+ rb_bug("rb_thread_terminate_all: called by child thread (%p, %p)",
+ (void *)cr->threads.main, (void *)th);
}
/* unlock all locking mutexes */
@@ -570,11 +596,11 @@ rb_thread_terminate_all(void)
if (EC_EXEC_TAG() == TAG_NONE) {
retry:
thread_debug("rb_thread_terminate_all (main thread: %p)\n", (void *)th);
- terminate_all(vm, th);
+ terminate_all(cr, th);
- while (vm_living_thread_num(vm) > 1) {
+ while (rb_ractor_living_thread_num(cr) > 1) {
rb_hrtime_t rel = RB_HRTIME_PER_SEC;
- /*
+ /*q
* Thread exiting routine in thread_start_func_2 notify
* me when the last sub-thread exit.
*/
@@ -605,6 +631,7 @@ thread_cleanup_func_before_exec(void *th_ptr)
{
rb_thread_t *th = th_ptr;
th->status = THREAD_KILLED;
+
// The thread stack doesn't exist in the forked process:
th->ec->machine.stack_start = th->ec->machine.stack_end = NULL;
@@ -657,27 +684,43 @@ rb_vm_proc_local_ep(VALUE proc)
}
}
-static void
-thread_do_start(rb_thread_t *th)
-{
- native_set_thread_name(th);
+// for ractor, defined in vm.c
+VALUE rb_vm_invoke_proc_with_self(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self,
+ int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler);
- if (th->invoke_type == thread_invoke_type_proc) {
- VALUE args = th->invoke_arg.proc.args;
- int args_len = (int)RARRAY_LEN(args);
- int kw_splat = th->invoke_arg.proc.kw_splat;
- const VALUE *args_ptr;
- VALUE procval = th->invoke_arg.proc.proc;
- rb_proc_t *proc;
- GetProcPtr(procval, proc);
-
- th->ec->errinfo = Qnil;
- th->ec->root_lep = rb_vm_proc_local_ep(procval);
- th->ec->root_svar = Qfalse;
-
- EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, 0, Qundef);
+static VALUE
+thread_do_start_proc(rb_thread_t *th)
+{
+ VALUE args = th->invoke_arg.proc.args;
+ const VALUE *args_ptr;
+ int args_len;
+ VALUE procval = th->invoke_arg.proc.proc;
+ rb_proc_t *proc;
+ GetProcPtr(procval, proc);
+
+ th->ec->errinfo = Qnil;
+ th->ec->root_lep = rb_vm_proc_local_ep(procval);
+ th->ec->root_svar = Qfalse;
+
+ vm_check_ints_blocking(th->ec);
+
+ if (th->invoke_type == thread_invoke_type_ractor_proc) {
+ VALUE self = rb_ractor_self(th->ractor);
+ VM_ASSERT(FIXNUM_P(args));
+ args_len = FIX2INT(args);
+ args_ptr = ALLOCA_N(VALUE, args_len);
+ rb_ractor_receive_parameters(th->ec, th->ractor, args_len, (VALUE *)args_ptr);
vm_check_ints_blocking(th->ec);
+ return rb_vm_invoke_proc_with_self(
+ th->ec, proc, self,
+ args_len, args_ptr,
+ th->invoke_arg.proc.kw_splat,
+ VM_BLOCK_HANDLER_NONE
+ );
+ }
+ else {
+ args_len = RARRAY_LENINT(args);
if (args_len < 8) {
/* free proc.args if the length is enough small */
args_ptr = ALLOCA_N(VALUE, args_len);
@@ -688,145 +731,225 @@ thread_do_start(rb_thread_t *th)
args_ptr = RARRAY_CONST_PTR(args);
}
- rb_adjust_argv_kw_splat(&args_len, &args_ptr, &kw_splat);
- th->value = rb_vm_invoke_proc(th->ec, proc,
- args_len, args_ptr,
- kw_splat, VM_BLOCK_HANDLER_NONE);
+ vm_check_ints_blocking(th->ec);
- EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_END, th->self, 0, 0, 0, Qundef);
+ return rb_vm_invoke_proc(
+ th->ec, proc,
+ args_len, args_ptr,
+ th->invoke_arg.proc.kw_splat,
+ VM_BLOCK_HANDLER_NONE
+ );
}
- else {
- th->value = (*th->invoke_arg.func.func)(th->invoke_arg.func.arg);
+}
+
+static void
+thread_do_start(rb_thread_t *th)
+{
+ native_set_thread_name(th);
+ VALUE result = Qundef;
+
+ EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, 0, Qundef);
+
+ switch (th->invoke_type) {
+ case thread_invoke_type_proc:
+ result = thread_do_start_proc(th);
+ break;
+
+ case thread_invoke_type_ractor_proc:
+ result = thread_do_start_proc(th);
+ rb_ractor_atexit(th->ec, result);
+ break;
+
+ case thread_invoke_type_func:
+ result = (*th->invoke_arg.func.func)(th->invoke_arg.func.arg);
+ break;
+
+ case thread_invoke_type_none:
+ rb_bug("unreachable");
}
+
+ rb_scheduler_set(Qnil);
+
+ th->value = result;
+
+ EXEC_EVENT_HOOK(th->ec, RUBY_EVENT_THREAD_END, th->self, 0, 0, 0, Qundef);
}
void rb_ec_clear_current_thread_trace_func(const rb_execution_context_t *ec);
+// io.c
+VALUE rb_io_prep_stdin(void);
+VALUE rb_io_prep_stdout(void);
+VALUE rb_io_prep_stderr(void);
+
static int
thread_start_func_2(rb_thread_t *th, VALUE *stack_start)
{
STACK_GROW_DIR_DETECTION;
enum ruby_tag_type state;
- rb_thread_list_t *join_list;
- rb_thread_t *main_th;
VALUE errinfo = Qnil;
size_t size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE);
+ rb_thread_t *ractor_main_th = th->ractor->threads.main;
VALUE * vm_stack = NULL;
- if (th == th->vm->main_thread) {
- rb_bug("thread_start_func_2 must not be used for main thread");
+ VM_ASSERT(th != th->vm->ractor.main_thread);
+ thread_debug("thread start: %p\n", (void *)th);
+
+ // setup native thread
+ gvl_acquire(rb_ractor_gvl(th->ractor), th);
+ ruby_thread_set_native(th);
+
+ // setup ractor
+ if (rb_ractor_status_p(th->ractor, ractor_blocking)) {
+ RB_VM_LOCK();
+ {
+ rb_vm_ractor_blocking_cnt_dec(th->vm, th->ractor, __FILE__, __LINE__);
+ rb_ractor_t *r = th->ractor;
+ r->r_stdin = rb_io_prep_stdin();
+ r->r_stdout = rb_io_prep_stdout();
+ r->r_stderr = rb_io_prep_stderr();
+ }
+ RB_VM_UNLOCK();
}
- thread_debug("thread start: %p\n", (void *)th);
- VM_ASSERT((size * sizeof(VALUE)) <= th->ec->machine.stack_maxsize);
+ // This assertion is not passed on win32 env. Check it later.
+ // VM_ASSERT((size * sizeof(VALUE)) <= th->ec->machine.stack_maxsize);
+ // setup VM and machine stack
vm_stack = alloca(size * sizeof(VALUE));
VM_ASSERT(vm_stack);
- gvl_acquire(th->vm, th);
-
rb_ec_initialize_vm_stack(th->ec, vm_stack, size);
th->ec->machine.stack_start = STACK_DIR_UPPER(vm_stack + size, vm_stack);
th->ec->machine.stack_maxsize -= size * sizeof(VALUE);
- ruby_thread_set_native(th);
+ thread_debug("thread start (get lock): %p\n", (void *)th);
- {
- thread_debug("thread start (get lock): %p\n", (void *)th);
- rb_thread_set_current(th);
+ // Ensure that we are not joinable.
+ VM_ASSERT(th->value == Qundef);
- EC_PUSH_TAG(th->ec);
- if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- SAVE_ROOT_JMPBUF(th, thread_do_start(th));
- }
- else {
- errinfo = th->ec->errinfo;
+ EC_PUSH_TAG(th->ec);
- VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef);
- if (!NIL_P(exc)) errinfo = exc;
+ if ((state = EC_EXEC_TAG()) == TAG_NONE) {
+ SAVE_ROOT_JMPBUF(th, thread_do_start(th));
+ } else {
+ errinfo = th->ec->errinfo;
- if (state == TAG_FATAL) {
- /* fatal error within this thread, need to stop whole script */
- }
- else if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
- /* exit on main_thread. */
- }
- else {
- if (th->report_on_exception) {
- VALUE mesg = rb_thread_to_s(th->self);
- rb_str_cat_cstr(mesg, " terminated with exception (report_on_exception is true):\n");
- rb_write_error_str(mesg);
- rb_ec_error_print(th->ec, errinfo);
- }
- if (th->vm->thread_abort_on_exception ||
- th->abort_on_exception || RTEST(ruby_debug)) {
- /* exit on main_thread */
- }
- else {
- errinfo = Qnil;
- }
- }
- th->value = Qnil;
- }
+ VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef);
+ if (!NIL_P(exc)) errinfo = exc;
- th->status = THREAD_KILLED;
- thread_debug("thread end: %p\n", (void *)th);
+ if (state == TAG_FATAL) {
+ if (th->invoke_type == thread_invoke_type_ractor_proc) {
+ rb_ractor_atexit(th->ec, Qnil);
+ }
+ /* fatal error within this thread, need to stop whole script */
+ }
+ else if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) {
+ /* exit on main_thread. */
+ }
+ else {
+ if (th->report_on_exception) {
+ VALUE mesg = rb_thread_to_s(th->self);
+ rb_str_cat_cstr(mesg, " terminated with exception (report_on_exception is true):\n");
+ rb_write_error_str(mesg);
+ rb_ec_error_print(th->ec, errinfo);
+ }
- main_th = th->vm->main_thread;
- if (main_th == th) {
- ruby_stop(0);
- }
- if (RB_TYPE_P(errinfo, T_OBJECT)) {
- /* treat with normal error object */
- rb_threadptr_raise(main_th, 1, &errinfo);
- }
- EC_POP_TAG();
+ if (th->invoke_type == thread_invoke_type_ractor_proc) {
+ rb_ractor_atexit_exception(th->ec);
+ }
- rb_ec_clear_current_thread_trace_func(th->ec);
+ if (th->vm->thread_abort_on_exception ||
+ th->abort_on_exception || RTEST(ruby_debug)) {
+ /* exit on main_thread */
+ }
+ else {
+ errinfo = Qnil;
+ }
+ }
+ th->value = Qnil;
+ }
- /* locking_mutex must be Qfalse */
- if (th->locking_mutex != Qfalse) {
- rb_bug("thread_start_func_2: locking_mutex must not be set (%p:%"PRIxVALUE")",
- (void *)th, th->locking_mutex);
- }
+ // The thread is effectively finished and can be joined.
+ VM_ASSERT(th->value != Qundef);
- /* delete self other than main thread from living_threads */
- rb_vm_living_threads_remove(th->vm, th);
- if (main_th->status == THREAD_KILLED && rb_thread_alone()) {
- /* I'm last thread. wake up main thread from rb_thread_terminate_all */
- rb_threadptr_interrupt(main_th);
- }
+ rb_threadptr_join_list_wakeup(th);
+ rb_threadptr_unlock_all_locking_mutexes(th);
- /* wake up joining threads */
- join_list = th->join_list;
- while (join_list) {
- rb_threadptr_interrupt(join_list->th);
- switch (join_list->th->status) {
- case THREAD_STOPPED: case THREAD_STOPPED_FOREVER:
- join_list->th->status = THREAD_RUNNABLE;
- default: break;
- }
- join_list = join_list->next;
- }
+ if (th->invoke_type == thread_invoke_type_ractor_proc) {
+ rb_thread_terminate_all(th);
+ rb_ractor_teardown(th->ec);
+ }
- rb_threadptr_unlock_all_locking_mutexes(th);
- rb_check_deadlock(th->vm);
+ th->status = THREAD_KILLED;
+ thread_debug("thread end: %p\n", (void *)th);
+
+ if (th->vm->ractor.main_thread == th) {
+ ruby_stop(0);
+ }
- rb_fiber_close(th->ec->fiber_ptr);
+ if (RB_TYPE_P(errinfo, T_OBJECT)) {
+ /* treat with normal error object */
+ rb_threadptr_raise(ractor_main_th, 1, &errinfo);
}
+ EC_POP_TAG();
+
+ rb_ec_clear_current_thread_trace_func(th->ec);
+
+ /* locking_mutex must be Qfalse */
+ if (th->locking_mutex != Qfalse) {
+ rb_bug("thread_start_func_2: locking_mutex must not be set (%p:%"PRIxVALUE")",
+ (void *)th, th->locking_mutex);
+ }
+
+ if (ractor_main_th->status == THREAD_KILLED &&
+ th->ractor->threads.cnt <= 2 /* main thread and this thread */) {
+ /* I'm last thread. wake up main thread from rb_thread_terminate_all */
+ rb_threadptr_interrupt(ractor_main_th);
+ }
+
+ rb_check_deadlock(th->ractor);
+
+ rb_fiber_close(th->ec->fiber_ptr);
+
thread_cleanup_func(th, FALSE);
VM_ASSERT(th->ec->vm_stack == NULL);
- gvl_release(th->vm);
+ if (th->invoke_type == thread_invoke_type_ractor_proc) {
+ // after rb_ractor_living_threads_remove()
+ // GC will happen anytime and this ractor can be collected (and destroy GVL).
+ // So gvl_release() should be before it.
+ gvl_release(rb_ractor_gvl(th->ractor));
+ rb_ractor_living_threads_remove(th->ractor, th);
+ }
+ else {
+ rb_ractor_living_threads_remove(th->ractor, th);
+ gvl_release(rb_ractor_gvl(th->ractor));
+ }
return 0;
}
+struct thread_create_params {
+ enum thread_invoke_type type;
+
+ // for normal proc thread
+ VALUE args;
+ VALUE proc;
+
+ // for ractor
+ rb_ractor_t *g;
+
+ // for func
+ VALUE (*fn)(void *);
+};
+
static VALUE
-thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(void *))
+thread_create_core(VALUE thval, struct thread_create_params *params)
{
- rb_thread_t *th = rb_thread_ptr(thval), *current_th = GET_THREAD();
+ rb_execution_context_t *ec = GET_EC();
+ rb_thread_t *th = rb_thread_ptr(thval), *current_th = rb_ec_thread_ptr(ec);
int err;
if (OBJ_FROZEN(current_th->thgroup)) {
@@ -834,19 +957,35 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(void *))
"can't start a new thread (frozen ThreadGroup)");
}
- if (fn) {
- th->invoke_type = thread_invoke_type_func;
- th->invoke_arg.func.func = fn;
- th->invoke_arg.func.arg = (void *)args;
- }
- else {
- (void)RARRAY_LENINT(args);
+ switch (params->type) {
+ case thread_invoke_type_proc:
th->invoke_type = thread_invoke_type_proc;
- th->invoke_arg.proc.proc = rb_block_proc();
- th->invoke_arg.proc.args = args;
- th->invoke_arg.proc.kw_splat = rb_empty_keyword_given_p() ?
- RB_PASS_EMPTY_KEYWORDS :
- rb_keyword_given_p();
+ th->invoke_arg.proc.args = params->args;
+ th->invoke_arg.proc.proc = params->proc;
+ th->invoke_arg.proc.kw_splat = rb_keyword_given_p();
+ break;
+
+ case thread_invoke_type_ractor_proc:
+#if RACTOR_CHECK_MODE > 0
+ rb_ractor_setup_belonging_to(thval, rb_ractor_id(params->g));
+#endif
+ th->invoke_type = thread_invoke_type_ractor_proc;
+ th->ractor = params->g;
+ th->ractor->threads.main = th;
+ th->invoke_arg.proc.proc = rb_proc_isolate_bang(params->proc);
+ th->invoke_arg.proc.args = INT2FIX(RARRAY_LENINT(params->args));
+ th->invoke_arg.proc.kw_splat = rb_keyword_given_p();
+ rb_ractor_send_parameters(ec, params->g, params->args);
+ break;
+
+ case thread_invoke_type_func:
+ th->invoke_type = thread_invoke_type_func;
+ th->invoke_arg.func.func = params->fn;
+ th->invoke_arg.func.arg = (void *)params->args;
+ break;
+
+ default:
+ rb_bug("unreachable");
}
th->priority = current_th->priority;
@@ -859,13 +998,17 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(void *))
rb_native_mutex_initialize(&th->interrupt_lock);
+ RUBY_DEBUG_LOG("r:%u th:%p", rb_ractor_id(th->ractor), th);
+
+ rb_ractor_living_threads_insert(th->ractor, th);
+
/* kick thread */
err = native_thread_create(th);
if (err) {
th->status = THREAD_KILLED;
- rb_raise(rb_eThreadError, "can't create Thread: %s", strerror(err));
+ rb_ractor_living_threads_remove(th->ractor, th);
+ rb_raise(rb_eThreadError, "can't create Thread: %s", strerror(err));
}
- rb_vm_living_threads_insert(th->vm, th);
return thval;
}
@@ -897,8 +1040,9 @@ thread_s_new(int argc, VALUE *argv, VALUE klass)
rb_thread_t *th;
VALUE thread = rb_thread_alloc(klass);
- if (GET_VM()->main_thread->status == THREAD_KILLED)
- rb_raise(rb_eThreadError, "can't alloc thread");
+ if (GET_RACTOR()->threads.main->status == THREAD_KILLED) {
+ rb_raise(rb_eThreadError, "can't alloc thread");
+ }
rb_obj_call_init_kw(thread, argc, argv, RB_PASS_CALLED_KEYWORDS);
th = rb_thread_ptr(thread);
@@ -922,7 +1066,12 @@ thread_s_new(int argc, VALUE *argv, VALUE klass)
static VALUE
thread_start(VALUE klass, VALUE args)
{
- return thread_create_core(rb_thread_alloc(klass), args, 0);
+ struct thread_create_params params = {
+ .type = thread_invoke_type_proc,
+ .args = args,
+ .proc = rb_block_proc(),
+ };
+ return thread_create_core(rb_thread_alloc(klass), &params);
}
static VALUE
@@ -957,141 +1106,194 @@ thread_initialize(VALUE thread, VALUE args)
}
}
else {
- return thread_create_core(thread, args, NULL);
+ struct thread_create_params params = {
+ .type = thread_invoke_type_proc,
+ .args = args,
+ .proc = rb_block_proc(),
+ };
+ return thread_create_core(thread, &params);
}
}
VALUE
rb_thread_create(VALUE (*fn)(void *), void *arg)
{
- return thread_create_core(rb_thread_alloc(rb_cThread), (VALUE)arg, fn);
+ struct thread_create_params params = {
+ .type = thread_invoke_type_func,
+ .fn = fn,
+ .args = (VALUE)arg,
+ };
+ return thread_create_core(rb_thread_alloc(rb_cThread), &params);
+}
+
+VALUE
+rb_thread_create_ractor(rb_ractor_t *g, VALUE args, VALUE proc)
+{
+ struct thread_create_params params = {
+ .type = thread_invoke_type_ractor_proc,
+ .g = g,
+ .args = args,
+ .proc = proc,
+ };
+ return thread_create_core(rb_thread_alloc(rb_cThread), &params);
}
struct join_arg {
- rb_thread_t *target, *waiting;
- rb_hrtime_t *limit;
+ struct rb_waiting_list *waiter;
+ rb_thread_t *target;
+ VALUE timeout;
};
static VALUE
remove_from_join_list(VALUE arg)
{
struct join_arg *p = (struct join_arg *)arg;
- rb_thread_t *target_th = p->target, *th = p->waiting;
+ rb_thread_t *target_thread = p->target;
- if (target_th->status != THREAD_KILLED) {
- rb_thread_list_t **p = &target_th->join_list;
+ if (target_thread->status != THREAD_KILLED) {
+ struct rb_waiting_list **join_list = &target_thread->join_list;
- while (*p) {
- if ((*p)->th == th) {
- *p = (*p)->next;
- break;
- }
- p = &(*p)->next;
- }
+ while (*join_list) {
+ if (*join_list == p->waiter) {
+ *join_list = (*join_list)->next;
+ break;
+ }
+
+ join_list = &(*join_list)->next;
+ }
}
return Qnil;
}
+static rb_hrtime_t *double2hrtime(rb_hrtime_t *, double);
+
+static int
+thread_finished(rb_thread_t *th)
+{
+ return th->status == THREAD_KILLED || th->value != Qundef;
+}
+
static VALUE
thread_join_sleep(VALUE arg)
{
struct join_arg *p = (struct join_arg *)arg;
- rb_thread_t *target_th = p->target, *th = p->waiting;
- rb_hrtime_t end = 0;
+ rb_thread_t *target_th = p->target, *th = p->waiter->thread;
+ rb_hrtime_t end = 0, rel = 0, *limit = 0;
+
+ /*
+ * This supports INFINITY and negative values, so we can't use
+ * rb_time_interval right now...
+ */
+ if (p->timeout == Qnil) {
+ /* unlimited */
+ }
+ else if (FIXNUM_P(p->timeout)) {
+ rel = rb_sec2hrtime(NUM2TIMET(p->timeout));
+ limit = &rel;
+ }
+ else {
+ limit = double2hrtime(&rel, rb_num2dbl(p->timeout));
+ }
- if (p->limit) {
- end = rb_hrtime_add(*p->limit, rb_hrtime_now());
+ if (limit) {
+ end = rb_hrtime_add(*limit, rb_hrtime_now());
}
- while (target_th->status != THREAD_KILLED) {
- if (!p->limit) {
- th->status = THREAD_STOPPED_FOREVER;
- th->vm->sleeper++;
- rb_check_deadlock(th->vm);
- native_sleep(th, 0);
- th->vm->sleeper--;
- }
- else {
- if (hrtime_update_expire(p->limit, end)) {
- thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n",
- thread_id_str(target_th));
- return Qfalse;
- }
- th->status = THREAD_STOPPED;
- native_sleep(th, p->limit);
- }
- RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
- th->status = THREAD_RUNNABLE;
- thread_debug("thread_join: interrupted (thid: %"PRI_THREAD_ID", status: %s)\n",
- thread_id_str(target_th), thread_status_name(target_th, TRUE));
+ while (!thread_finished(target_th)) {
+ VALUE scheduler = rb_scheduler_current();
+
+ if (scheduler != Qnil) {
+ rb_scheduler_block(scheduler, target_th->self, p->timeout);
+ } else if (!limit) {
+ th->status = THREAD_STOPPED_FOREVER;
+ rb_ractor_sleeper_threads_inc(th->ractor);
+ rb_check_deadlock(th->ractor);
+ native_sleep(th, 0);
+ rb_ractor_sleeper_threads_dec(th->ractor);
+ }
+ else {
+ if (hrtime_update_expire(limit, end)) {
+ thread_debug("thread_join: timeout (thid: %"PRI_THREAD_ID")\n",
+ thread_id_str(target_th));
+ return Qfalse;
+ }
+ th->status = THREAD_STOPPED;
+ native_sleep(th, limit);
+ }
+ RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
+ th->status = THREAD_RUNNABLE;
+ thread_debug("thread_join: interrupted (thid: %"PRI_THREAD_ID", status: %s)\n",
+ thread_id_str(target_th), thread_status_name(target_th, TRUE));
}
return Qtrue;
}
static VALUE
-thread_join(rb_thread_t *target_th, rb_hrtime_t *rel)
+thread_join(rb_thread_t *target_th, VALUE timeout)
{
- rb_thread_t *th = GET_THREAD();
- struct join_arg arg;
+ rb_execution_context_t *ec = GET_EC();
+ rb_thread_t *th = ec->thread_ptr;
+ rb_fiber_t *fiber = ec->fiber_ptr;
if (th == target_th) {
- rb_raise(rb_eThreadError, "Target thread must not be current thread");
- }
- if (GET_VM()->main_thread == target_th) {
- rb_raise(rb_eThreadError, "Target thread must not be main thread");
+ rb_raise(rb_eThreadError, "Target thread must not be current thread");
}
- arg.target = target_th;
- arg.waiting = th;
- arg.limit = rel;
+ if (th->ractor->threads.main == target_th) {
+ rb_raise(rb_eThreadError, "Target thread must not be main thread");
+ }
thread_debug("thread_join (thid: %"PRI_THREAD_ID", status: %s)\n",
- thread_id_str(target_th), thread_status_name(target_th, TRUE));
+ thread_id_str(target_th), thread_status_name(target_th, TRUE));
if (target_th->status != THREAD_KILLED) {
- rb_thread_list_t list;
- list.next = target_th->join_list;
- list.th = th;
- target_th->join_list = &list;
- if (!rb_ensure(thread_join_sleep, (VALUE)&arg,
- remove_from_join_list, (VALUE)&arg)) {
- return Qnil;
- }
+ struct rb_waiting_list waiter;
+ waiter.next = target_th->join_list;
+ waiter.thread = th;
+ waiter.fiber = fiber;
+ target_th->join_list = &waiter;
+
+ struct join_arg arg;
+ arg.waiter = &waiter;
+ arg.target = target_th;
+ arg.timeout = timeout;
+
+ if (!rb_ensure(thread_join_sleep, (VALUE)&arg, remove_from_join_list, (VALUE)&arg)) {
+ return Qnil;
+ }
}
thread_debug("thread_join: success (thid: %"PRI_THREAD_ID", status: %s)\n",
- thread_id_str(target_th), thread_status_name(target_th, TRUE));
+ thread_id_str(target_th), thread_status_name(target_th, TRUE));
if (target_th->ec->errinfo != Qnil) {
- VALUE err = target_th->ec->errinfo;
-
- if (FIXNUM_P(err)) {
- switch (err) {
- case INT2FIX(TAG_FATAL):
- thread_debug("thread_join: terminated (thid: %"PRI_THREAD_ID", status: %s)\n",
- thread_id_str(target_th), thread_status_name(target_th, TRUE));
-
- /* OK. killed. */
- break;
- default:
- rb_bug("thread_join: Fixnum (%d) should not reach here.", FIX2INT(err));
- }
- }
- else if (THROW_DATA_P(target_th->ec->errinfo)) {
- rb_bug("thread_join: THROW_DATA should not reach here.");
- }
- else {
- /* normal exception */
- rb_exc_raise(err);
- }
+ VALUE err = target_th->ec->errinfo;
+
+ if (FIXNUM_P(err)) {
+ switch (err) {
+ case INT2FIX(TAG_FATAL):
+ thread_debug("thread_join: terminated (thid: %"PRI_THREAD_ID", status: %s)\n",
+ thread_id_str(target_th), thread_status_name(target_th, TRUE));
+
+ /* OK. killed. */
+ break;
+ default:
+ rb_bug("thread_join: Fixnum (%d) should not reach here.", FIX2INT(err));
+ }
+ }
+ else if (THROW_DATA_P(target_th->ec->errinfo)) {
+ rb_bug("thread_join: THROW_DATA should not reach here.");
+ }
+ else {
+ /* normal exception */
+ rb_exc_raise(err);
+ }
}
return target_th->self;
}
-static rb_hrtime_t *double2hrtime(rb_hrtime_t *, double);
-
/*
* call-seq:
* thr.join -> thr
@@ -1134,25 +1336,24 @@ static rb_hrtime_t *double2hrtime(rb_hrtime_t *, double);
static VALUE
thread_join_m(int argc, VALUE *argv, VALUE self)
{
- VALUE limit;
- rb_hrtime_t rel, *to = 0;
+ VALUE timeout = Qnil;
- /*
- * This supports INFINITY and negative values, so we can't use
- * rb_time_interval right now...
- */
- if (!rb_check_arity(argc, 0, 1) || NIL_P(argv[0])) {
+ if (rb_check_arity(argc, 0, 1)) {
+ timeout = argv[0];
+ }
+
+ // Convert the timeout eagerly, so it's always converted and deterministic
+ if (timeout == Qnil) {
/* unlimited */
}
- else if (FIXNUM_P(limit = argv[0])) {
- rel = rb_sec2hrtime(NUM2TIMET(limit));
- to = &rel;
+ else if (FIXNUM_P(timeout)) {
+ /* handled directly in thread_join_sleep() */
}
else {
- to = double2hrtime(&rel, rb_num2dbl(limit));
+ timeout = rb_to_float(timeout);
}
- return thread_join(rb_thread_ptr(self), to);
+ return thread_join(rb_thread_ptr(self), timeout);
}
/*
@@ -1173,7 +1374,7 @@ static VALUE
thread_value(VALUE self)
{
rb_thread_t *th = rb_thread_ptr(self);
- thread_join(th, 0);
+ thread_join(th, Qnil);
return th->value;
}
@@ -1191,11 +1392,21 @@ thread_value(VALUE self)
#define TIMESPEC_SEC_MAX TIMET_MAX
#define TIMESPEC_SEC_MIN TIMET_MIN
+COMPILER_WARNING_PUSH
+#if __has_warning("-Wimplicit-int-float-conversion")
+COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion)
+#elif defined(_MSC_VER)
+/* C4305: 'initializing': truncation from '__int64' to 'const double' */
+COMPILER_WARNING_IGNORED(4305)
+#endif
+static const double TIMESPEC_SEC_MAX_as_double = TIMESPEC_SEC_MAX;
+COMPILER_WARNING_POP
+
static rb_hrtime_t *
double2hrtime(rb_hrtime_t *hrt, double d)
{
/* assume timespec.tv_sec has same signedness as time_t */
- const double TIMESPEC_SEC_MAX_PLUS_ONE = TIMET_MAX_PLUS_ONE;
+ const double TIMESPEC_SEC_MAX_PLUS_ONE = 2.0 * (TIMESPEC_SEC_MAX_as_double / 2.0 + 1.0);
if (TIMESPEC_SEC_MAX_PLUS_ONE <= d) {
return NULL;
@@ -1245,12 +1456,12 @@ sleep_forever(rb_thread_t *th, unsigned int fl)
RUBY_VM_CHECK_INTS_BLOCKING(th->ec);
while (th->status == status) {
if (fl & SLEEP_DEADLOCKABLE) {
- th->vm->sleeper++;
- rb_check_deadlock(th->vm);
+ rb_ractor_sleeper_threads_inc(th->ractor);
+ rb_check_deadlock(th->ractor);
}
native_sleep(th, 0);
if (fl & SLEEP_DEADLOCKABLE) {
- th->vm->sleeper--;
+ rb_ractor_sleeper_threads_dec(th->ractor);
}
woke = vm_check_ints_blocking(th->ec);
if (woke && !(fl & SLEEP_SPURIOUS_CHECK))
@@ -1336,10 +1547,15 @@ rb_thread_sleep_interruptible(void)
}
static void
-rb_thread_sleep_deadly_allow_spurious_wakeup(void)
+rb_thread_sleep_deadly_allow_spurious_wakeup(VALUE blocker)
{
- thread_debug("rb_thread_sleep_deadly_allow_spurious_wakeup\n");
- sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE);
+ VALUE scheduler = rb_scheduler_current();
+ if (scheduler != Qnil) {
+ rb_scheduler_block(scheduler, blocker, Qnil);
+ } else {
+ thread_debug("rb_thread_sleep_deadly_allow_spurious_wakeup\n");
+ sleep_forever(GET_THREAD(), SLEEP_DEADLOCKABLE);
+ }
}
void
@@ -1396,8 +1612,8 @@ rb_thread_schedule_limits(uint32_t limits_us)
if (th->running_time_us >= limits_us) {
thread_debug("rb_thread_schedule/switch start\n");
RB_GC_SAVE_MACHINE_CONTEXT(th);
- gvl_yield(th->vm, th);
- rb_thread_set_current(th);
+ gvl_yield(rb_ractor_gvl(th->ractor), th);
+ rb_ractor_thread_switch(th->ractor, th);
thread_debug("rb_thread_schedule/switch done\n");
}
}
@@ -1420,9 +1636,10 @@ blocking_region_begin(rb_thread_t *th, struct rb_blocking_region_buffer *region,
if (unblock_function_set(th, ubf, arg, fail_if_interrupted)) {
th->blocking_region_buffer = region;
th->status = THREAD_STOPPED;
+ rb_ractor_blocking_threads_inc(th->ractor, __FILE__, __LINE__);
thread_debug("enter blocking region (%p)\n", (void *)th);
RB_GC_SAVE_MACHINE_CONTEXT(th);
- gvl_release(th->vm);
+ gvl_release(rb_ractor_gvl(th->ractor));
return TRUE;
}
else {
@@ -1438,10 +1655,12 @@ blocking_region_end(rb_thread_t *th, struct rb_blocking_region_buffer *region)
/* entry to ubf_list impossible at this point, so unregister is safe: */
unregister_ubf_list(th);
- gvl_acquire(th->vm, th);
- rb_thread_set_current(th);
+ gvl_acquire(rb_ractor_gvl(th->ractor), th);
+ rb_ractor_thread_switch(th->ractor, th);
+
thread_debug("leave blocking region (%p)\n", (void *)th);
th->blocking_region_buffer = 0;
+ rb_ractor_blocking_threads_dec(th->ractor, __FILE__, __LINE__);
if (th->status == THREAD_STOPPED) {
th->status = region->prev_status;
}
@@ -1455,6 +1674,8 @@ rb_nogvl(void *(*func)(void *), void *data1,
void *val = 0;
rb_execution_context_t *ec = GET_EC();
rb_thread_t *th = rb_ec_thread_ptr(ec);
+ rb_vm_t *vm = rb_ec_vm_ptr(ec);
+ bool is_main_thread = vm->ractor.main_thread == th;
int saved_errno = 0;
VALUE ubf_th = Qfalse;
@@ -1462,9 +1683,9 @@ rb_nogvl(void *(*func)(void *), void *data1,
ubf = ubf_select;
data2 = th;
}
- else if (ubf && vm_living_thread_num(th->vm) == 1) {
+ else if (ubf && rb_ractor_living_thread_num(th->ractor) == 1 && is_main_thread) {
if (flags & RB_NOGVL_UBF_ASYNC_SAFE) {
- th->vm->ubf_async_safe = 1;
+ vm->ubf_async_safe = 1;
}
else {
ubf_th = rb_thread_start_unblock_thread();
@@ -1476,7 +1697,7 @@ rb_nogvl(void *(*func)(void *), void *data1,
saved_errno = errno;
}, ubf, data2, flags & RB_NOGVL_INTR_FAIL);
- th->vm->ubf_async_safe = 0;
+ if (is_main_thread) vm->ubf_async_safe = 0;
if ((flags & RB_NOGVL_INTR_FAIL) == 0) {
RUBY_VM_CHECK_INTS_BLOCKING(ec);
@@ -1597,18 +1818,23 @@ rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
rb_execution_context_t * volatile ec = GET_EC();
volatile int saved_errno = 0;
enum ruby_tag_type state;
- struct waiting_fd wfd;
+ COROUTINE_STACK_LOCAL(struct waiting_fd, wfd);
- wfd.fd = fd;
- wfd.th = rb_ec_thread_ptr(ec);
- list_add(&rb_ec_vm_ptr(ec)->waiting_fds, &wfd.wfd_node);
+ wfd->fd = fd;
+ wfd->th = rb_ec_thread_ptr(ec);
+
+ RB_VM_LOCK_ENTER();
+ {
+ list_add(&rb_ec_vm_ptr(ec)->waiting_fds, &wfd->wfd_node);
+ }
+ RB_VM_LOCK_LEAVE();
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- BLOCKING_REGION(wfd.th, {
+ BLOCKING_REGION(wfd->th, {
val = func(data1);
saved_errno = errno;
- }, ubf_select, wfd.th, FALSE);
+ }, ubf_select, wfd->th, FALSE);
}
EC_POP_TAG();
@@ -1616,7 +1842,12 @@ rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
* must be deleted before jump
* this will delete either from waiting_fds or on-stack LIST_HEAD(busy)
*/
- list_del(&wfd.wfd_node);
+ RB_VM_LOCK_ENTER();
+ {
+ list_del(&wfd->wfd_node);
+ COROUTINE_STACK_FREE(wfd);
+ }
+ RB_VM_LOCK_LEAVE();
if (state) {
EC_JUMP_TAG(ec, state);
@@ -1670,7 +1901,7 @@ rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
* because this thread is not Ruby's thread.
* What should we do?
*/
-
+ bp();
fprintf(stderr, "[BUG] rb_thread_call_with_gvl() is called by non-ruby thread\n");
exit(EXIT_FAILURE);
}
@@ -2203,18 +2434,25 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
int timer_interrupt;
int pending_interrupt;
int trap_interrupt;
+ int terminate_interrupt;
timer_interrupt = interrupt & TIMER_INTERRUPT_MASK;
pending_interrupt = interrupt & PENDING_INTERRUPT_MASK;
postponed_job_interrupt = interrupt & POSTPONED_JOB_INTERRUPT_MASK;
trap_interrupt = interrupt & TRAP_INTERRUPT_MASK;
+ terminate_interrupt = interrupt & TERMINATE_INTERRUPT_MASK; // request from other ractors
+
+ if (interrupt & VM_BARRIER_INTERRUPT_MASK) {
+ RB_VM_LOCK_ENTER();
+ RB_VM_LOCK_LEAVE();
+ }
if (postponed_job_interrupt) {
rb_postponed_job_flush(th->vm);
}
/* signal handling */
- if (trap_interrupt && (th == th->vm->main_thread)) {
+ if (trap_interrupt && (th == th->vm->ractor.main_thread)) {
enum rb_thread_status prev_status = th->status;
int sigwait_fd = rb_sigwait_fd_get(th);
@@ -2243,7 +2481,7 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
else if (err == eKillSignal /* Thread#kill received */ ||
err == eTerminateSignal /* Terminate thread */ ||
err == INT2FIX(TAG_FATAL) /* Thread.exit etc. */ ) {
- rb_threadptr_to_kill(th);
+ terminate_interrupt = 1;
}
else {
if (err == th->vm->special_exceptions[ruby_error_stream_closed]) {
@@ -2258,7 +2496,11 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing)
}
}
- if (timer_interrupt) {
+ if (terminate_interrupt) {
+ rb_threadptr_to_kill(th);
+ }
+
+ if (timer_interrupt) {
uint32_t limits_us = TIME_QUANTUM_USEC;
if (th->priority > 0)
@@ -2326,7 +2568,7 @@ rb_threadptr_signal_raise(rb_thread_t *th, int sig)
argv[0] = rb_eSignal;
argv[1] = INT2FIX(sig);
- rb_threadptr_raise(th->vm->main_thread, 2, argv);
+ rb_threadptr_raise(th->vm->ractor.main_thread, 2, argv);
}
void
@@ -2336,7 +2578,9 @@ rb_threadptr_signal_exit(rb_thread_t *th)
argv[0] = rb_eSystemExit;
argv[1] = rb_str_new2("exit");
- rb_threadptr_raise(th->vm->main_thread, 2, argv);
+
+ // TODO: check signal raise deliverly
+ rb_threadptr_raise(th->vm->ractor.main_thread, 2, argv);
}
int
@@ -2365,19 +2609,24 @@ rb_notify_fd_close(int fd, struct list_head *busy)
rb_vm_t *vm = GET_THREAD()->vm;
struct waiting_fd *wfd = 0, *next;
- list_for_each_safe(&vm->waiting_fds, wfd, next, wfd_node) {
- if (wfd->fd == fd) {
- rb_thread_t *th = wfd->th;
- VALUE err;
+ RB_VM_LOCK_ENTER();
+ {
+ list_for_each_safe(&vm->waiting_fds, wfd, next, wfd_node) {
+ if (wfd->fd == fd) {
+ rb_thread_t *th = wfd->th;
+ VALUE err;
- list_del(&wfd->wfd_node);
- list_add(busy, &wfd->wfd_node);
+ list_del(&wfd->wfd_node);
+ list_add(busy, &wfd->wfd_node);
- err = th->vm->special_exceptions[ruby_error_stream_closed];
- rb_threadptr_pending_interrupt_enque(th, err);
- rb_threadptr_interrupt(th);
- }
+ err = th->vm->special_exceptions[ruby_error_stream_closed];
+ rb_threadptr_pending_interrupt_enque(th, err);
+ rb_threadptr_interrupt(th);
+ }
+ }
}
+ RB_VM_LOCK_LEAVE();
+
return !list_empty(busy);
}
@@ -2449,7 +2698,7 @@ rb_thread_kill(VALUE thread)
if (th->to_kill || th->status == THREAD_KILLED) {
return thread;
}
- if (th == th->vm->main_thread) {
+ if (th == th->vm->ractor.main_thread) {
rb_exit(EXIT_SUCCESS);
}
@@ -2628,21 +2877,8 @@ thread_stop(VALUE _)
VALUE
rb_thread_list(void)
{
- VALUE ary = rb_ary_new();
- rb_vm_t *vm = GET_THREAD()->vm;
- rb_thread_t *th = 0;
-
- list_for_each(&vm->living_threads, th, vmlt_node) {
- switch (th->status) {
- case THREAD_RUNNABLE:
- case THREAD_STOPPED:
- case THREAD_STOPPED_FOREVER:
- rb_ary_push(ary, th->self);
- default:
- break;
- }
- }
- return ary;
+ // TODO
+ return rb_ractor_thread_list(GET_RACTOR());
}
/*
@@ -2695,7 +2931,7 @@ thread_s_current(VALUE klass)
VALUE
rb_thread_main(void)
{
- return GET_THREAD()->vm->main_thread->self;
+ return GET_RACTOR()->threads.main->self;
}
/*
@@ -2859,7 +3095,7 @@ rb_thread_abort_exc_set(VALUE thread, VALUE val)
*
* There is also an instance level method to set this for a specific thread,
* see #report_on_exception=.
- *
+ *
*/
static VALUE
@@ -2909,6 +3145,52 @@ rb_thread_s_report_exc_set(VALUE self, VALUE val)
/*
* call-seq:
+ * Thread.ignore_deadlock -> true or false
+ *
+ * Returns the status of the global ``ignore deadlock'' condition.
+ * The default is +false+, so that deadlock conditions are not ignored.
+ *
+ * See also ::ignore_deadlock=.
+ *
+ */
+
+static VALUE
+rb_thread_s_ignore_deadlock(VALUE _)
+{
+ return GET_THREAD()->vm->thread_ignore_deadlock ? Qtrue : Qfalse;
+}
+
+
+/*
+ * call-seq:
+ * Thread.ignore_deadlock = boolean -> true or false
+ *
+ * Returns the new state.
+ * When set to +true+, the VM will not check for deadlock conditions.
+ * It is only useful to set this if your application can break a
+ * deadlock condition via some other means, such as a signal.
+ *
+ * Thread.ignore_deadlock = true
+ * queue = Queue.new
+ *
+ * trap(:SIGUSR1){queue.push "Received signal"}
+ *
+ * # raises fatal error unless ignoring deadlock
+ * puts queue.pop
+ *
+ * See also ::ignore_deadlock.
+ */
+
+static VALUE
+rb_thread_s_ignore_deadlock_set(VALUE self, VALUE val)
+{
+ GET_THREAD()->vm->thread_ignore_deadlock = RTEST(val);
+ return val;
+}
+
+
+/*
+ * call-seq:
* thr.report_on_exception -> true or false
*
* Returns the status of the thread-local ``report on exception'' condition for
@@ -3060,11 +3342,11 @@ rb_thread_status(VALUE thread)
static VALUE
rb_thread_alive_p(VALUE thread)
{
- if (rb_threadptr_dead(rb_thread_ptr(thread))) {
- return Qfalse;
+ if (thread_finished(rb_thread_ptr(thread))) {
+ return Qfalse;
}
else {
- return Qtrue;
+ return Qtrue;
}
}
@@ -3100,23 +3382,6 @@ rb_thread_stop_p(VALUE thread)
}
/*
- * call-seq:
- * thr.safe_level -> integer
- *
- * Returns the safe level.
- *
- * This method is obsolete because $SAFE is a process global state.
- * Simply check $SAFE.
- */
-
-static VALUE
-rb_thread_safe_level(VALUE thread)
-{
- rb_warn("Thread#safe_level will be removed in Ruby 3.0");
- return UINT2NUM(GET_VM()->safe_level_);
-}
-
-/*
* call-seq:
* thr.name -> string
*
@@ -3199,11 +3464,11 @@ threadptr_local_aref(rb_thread_t *th, ID id)
return th->ec->local_storage_recursive_hash;
}
else {
- st_data_t val;
- st_table *local_storage = th->ec->local_storage;
+ VALUE val;
+ struct rb_id_table *local_storage = th->ec->local_storage;
- if (local_storage != NULL && st_lookup(local_storage, id, &val)) {
- return (VALUE)val;
+ if (local_storage != NULL && rb_id_table_lookup(local_storage, id, &val)) {
+ return val;
}
else {
return Qnil;
@@ -3320,7 +3585,7 @@ rb_thread_fetch(int argc, VALUE *argv, VALUE self)
return target_th->ec->local_storage_recursive_hash;
}
else if (id && target_th->ec->local_storage &&
- st_lookup(target_th->ec->local_storage, id, &val)) {
+ rb_id_table_lookup(target_th->ec->local_storage, id, &val)) {
return val;
}
else if (block_given) {
@@ -3342,18 +3607,18 @@ threadptr_local_aset(rb_thread_t *th, ID id, VALUE val)
return val;
}
else {
- st_table *local_storage = th->ec->local_storage;
+ struct rb_id_table *local_storage = th->ec->local_storage;
if (NIL_P(val)) {
if (!local_storage) return Qnil;
- st_delete_wrap(local_storage, id);
+ rb_id_table_delete(local_storage, id);
return Qnil;
}
else {
if (local_storage == NULL) {
- th->ec->local_storage = local_storage = st_init_numtable();
+ th->ec->local_storage = local_storage = rb_id_table_create(0);
}
- st_insert(local_storage, id, val);
+ rb_id_table_insert(local_storage, id, val);
return val;
}
}
@@ -3438,7 +3703,7 @@ rb_thread_variable_get(VALUE thread, VALUE key)
*/
static VALUE
-rb_thread_variable_set(VALUE thread, VALUE id, VALUE val)
+rb_thread_variable_set(VALUE thread, VALUE key, VALUE val)
{
VALUE locals;
@@ -3447,7 +3712,7 @@ rb_thread_variable_set(VALUE thread, VALUE id, VALUE val)
}
locals = rb_thread_local_storage(thread);
- return rb_hash_aset(locals, rb_to_symbol(id), val);
+ return rb_hash_aset(locals, rb_to_symbol(key), val);
}
/*
@@ -3466,13 +3731,14 @@ rb_thread_variable_set(VALUE thread, VALUE id, VALUE val)
static VALUE
rb_thread_key_p(VALUE self, VALUE key)
{
+ VALUE val;
ID id = rb_check_id(&key);
- st_table *local_storage = rb_thread_ptr(self)->ec->local_storage;
+ struct rb_id_table *local_storage = rb_thread_ptr(self)->ec->local_storage;
if (!id || local_storage == NULL) {
return Qfalse;
}
- else if (st_is_member(local_storage, id)) {
+ else if (rb_id_table_lookup(local_storage, id, &val)) {
return Qtrue;
}
else {
@@ -3480,17 +3746,18 @@ rb_thread_key_p(VALUE self, VALUE key)
}
}
-static int
-thread_keys_i(ID key, VALUE value, VALUE ary)
+static enum rb_id_table_iterator_result
+thread_keys_i(ID key, VALUE value, void *ary)
{
- rb_ary_push(ary, ID2SYM(key));
- return ST_CONTINUE;
+ rb_ary_push((VALUE)ary, ID2SYM(key));
+ return ID_TABLE_CONTINUE;
}
int
rb_thread_alone(void)
{
- return vm_living_thread_num(GET_VM()) == 1;
+ // TODO
+ return rb_ractor_living_thread_num(GET_RACTOR()) == 1;
}
/*
@@ -3510,11 +3777,11 @@ rb_thread_alone(void)
static VALUE
rb_thread_keys(VALUE self)
{
- st_table *local_storage = rb_thread_ptr(self)->ec->local_storage;
+ struct rb_id_table *local_storage = rb_thread_ptr(self)->ec->local_storage;
VALUE ary = rb_ary_new();
if (local_storage) {
- st_foreach(local_storage, thread_keys_i, ary);
+ rb_id_table_foreach(local_storage, thread_keys_i, (void *)ary);
}
return ary;
}
@@ -3579,16 +3846,13 @@ static VALUE
rb_thread_variable_p(VALUE thread, VALUE key)
{
VALUE locals;
- ID id = rb_check_id(&key);
-
- if (!id) return Qfalse;
if (LIKELY(!THREAD_LOCAL_STORAGE_INITIALISED_P(thread))) {
return Qfalse;
}
locals = rb_thread_local_storage(thread);
- if (rb_hash_lookup(locals, ID2SYM(id)) != Qnil) {
+ if (rb_hash_lookup(locals, rb_to_symbol(key)) != Qnil) {
return Qtrue;
}
else {
@@ -4129,7 +4393,7 @@ rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t *
* returns a mask of events
*/
int
-rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
+rb_thread_wait_for_single_fd(int fd, int events, struct timeval *timeout)
{
struct pollfd fds[2];
int result = 0, lerrno;
@@ -4142,7 +4406,13 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
wfd.th = GET_THREAD();
wfd.fd = fd;
- list_add(&wfd.th->vm->waiting_fds, &wfd.wfd_node);
+
+ RB_VM_LOCK_ENTER();
+ {
+ list_add(&wfd.th->vm->waiting_fds, &wfd.wfd_node);
+ }
+ RB_VM_LOCK_LEAVE();
+
EC_PUSH_TAG(wfd.th->ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
RUBY_VM_CHECK_INTS_BLOCKING(wfd.th->ec);
@@ -4190,7 +4460,13 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
} while (wait_retryable(&result, lerrno, to, end));
}
EC_POP_TAG();
- list_del(&wfd.wfd_node);
+
+ RB_VM_LOCK_ENTER();
+ {
+ list_del(&wfd.wfd_node);
+ }
+ RB_VM_LOCK_LEAVE();
+
if (state) {
EC_JUMP_TAG(wfd.th->ec, state);
}
@@ -4272,7 +4548,7 @@ select_single_cleanup(VALUE ptr)
}
int
-rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
+rb_thread_wait_for_single_fd(int fd, int events, struct timeval *timeout)
{
rb_fdset_t rfds, wfds, efds;
struct select_args args;
@@ -4283,11 +4559,16 @@ rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
args.read = (events & RB_WAITFD_IN) ? init_set_fd(fd, &rfds) : NULL;
args.write = (events & RB_WAITFD_OUT) ? init_set_fd(fd, &wfds) : NULL;
args.except = (events & RB_WAITFD_PRI) ? init_set_fd(fd, &efds) : NULL;
- args.tv = tv;
+ args.tv = timeout;
args.wfd.fd = fd;
args.wfd.th = GET_THREAD();
- list_add(&args.wfd.th->vm->waiting_fds, &args.wfd.wfd_node);
+ RB_VM_LOCK_ENTER();
+ {
+ list_add(&args.wfd.th->vm->waiting_fds, &args.wfd.wfd_node);
+ }
+ RB_VM_LOCK_LEAVE();
+
r = (int)rb_ensure(select_single, ptr, select_single_cleanup, ptr);
if (r == -1)
errno = args.as.error;
@@ -4324,17 +4605,6 @@ rb_threadptr_check_signal(rb_thread_t *mth)
}
static void
-timer_thread_function(void)
-{
- volatile rb_execution_context_t *ec;
-
- /* for time slice */
- ec = ACCESS_ONCE(rb_execution_context_t *,
- ruby_current_execution_context_ptr);
- if (ec) RUBY_VM_SET_TIMER_INTERRUPT(ec);
-}
-
-static void
async_bug_fd(const char *mesg, int errno_arg, int fd)
{
char buff[64];
@@ -4402,11 +4672,13 @@ check_signals_nogvl(rb_thread_t *th, int sigwait_fd)
ubf_wakeup_all_threads();
ruby_sigchld_handler(vm);
if (rb_signal_buff_size()) {
- if (th == vm->main_thread)
+ if (th == vm->ractor.main_thread) {
/* no need to lock + wakeup if already in main thread */
RUBY_VM_SET_TRAP_INTERRUPT(th->ec);
- else
- threadptr_trap_interrupt(vm->main_thread);
+ }
+ else {
+ threadptr_trap_interrupt(vm->ractor.main_thread);
+ }
ret = TRUE; /* for SIGCHLD_LOSSY && rb_sigwait_sleep */
}
return ret;
@@ -4473,21 +4745,30 @@ rb_clear_coverages(void)
}
#if defined(HAVE_WORKING_FORK)
+
static void
rb_thread_atfork_internal(rb_thread_t *th, void (*atfork)(rb_thread_t *, const rb_thread_t *))
{
rb_thread_t *i = 0;
rb_vm_t *vm = th->vm;
- vm->main_thread = th;
+ rb_ractor_t *r = th->ractor;
+ vm->ractor.main_ractor = r;
+ vm->ractor.main_thread = th;
+ r->threads.main = th;
+ r->status_ = ractor_created;
- gvl_atfork(th->vm);
+ gvl_atfork(rb_ractor_gvl(th->ractor));
ubf_list_atfork();
- list_for_each(&vm->living_threads, i, vmlt_node) {
- atfork(i, th);
+ // OK. Only this thread accesses:
+ list_for_each(&vm->ractor.set, r, vmlr_node) {
+ list_for_each(&r->threads.set, i, lt_node) {
+ atfork(i, th);
+ }
}
rb_vm_living_threads_init(vm);
- rb_vm_living_threads_insert(vm, th);
+
+ rb_ractor_atfork(vm, th);
/* may be held by MJIT threads in parent */
rb_native_mutex_initialize(&vm->waitpid_lock);
@@ -4497,9 +4778,11 @@ rb_thread_atfork_internal(rb_thread_t *th, void (*atfork)(rb_thread_t *, const r
rb_native_mutex_initialize(&th->interrupt_lock);
vm->fork_gen++;
-
- vm->sleeper = 0;
+ rb_ractor_sleeper_threads_clear(th->ractor);
rb_clear_coverages();
+
+ VM_ASSERT(vm->ractor.blocking_cnt == 0);
+ VM_ASSERT(vm->ractor.cnt == 1);
}
static void
@@ -4567,7 +4850,7 @@ thgroup_memsize(const void *ptr)
static const rb_data_type_t thgroup_data_type = {
"thgroup",
- {NULL, RUBY_TYPED_DEFAULT_FREE, thgroup_memsize,},
+ {0, RUBY_TYPED_DEFAULT_FREE, thgroup_memsize,},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -4616,11 +4899,11 @@ static VALUE
thgroup_list(VALUE group)
{
VALUE ary = rb_ary_new();
- rb_vm_t *vm = GET_THREAD()->vm;
rb_thread_t *th = 0;
+ rb_ractor_t *r = GET_RACTOR();
- list_for_each(&vm->living_threads, th, vmlt_node) {
- if (th->thgroup == group) {
+ list_for_each(&r->threads.set, th, lt_node) {
+ if (th->thgroup == group) {
rb_ary_push(ary, th->self);
}
}
@@ -4809,7 +5092,7 @@ rb_thread_shield_wait(VALUE self)
if (!mutex) return Qfalse;
m = mutex_ptr(mutex);
- if (m->th == GET_THREAD()) return Qnil;
+ if (m->fiber == GET_EC()->fiber_ptr) return Qnil;
rb_thread_shield_waiting_inc(self);
rb_mutex_lock(mutex);
rb_thread_shield_waiting_dec(self);
@@ -5052,10 +5335,7 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE
}
EC_POP_TAG();
if (!recursive_pop(p.list, p.obj, p.pairid)) {
- invalid:
- rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list "
- "for %+"PRIsVALUE" in %+"PRIsVALUE,
- sym, rb_thread_current());
+ goto invalid;
}
if (state != TAG_NONE) EC_JUMP_TAG(GET_EC(), state);
result = ret;
@@ -5063,6 +5343,12 @@ exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE pairid, VALUE
}
*(volatile struct exec_recursive_params *)&p;
return result;
+
+ invalid:
+ rb_raise(rb_eTypeError, "invalid inspect_tbl pair_list "
+ "for %+"PRIsVALUE" in %+"PRIsVALUE,
+ sym, rb_thread_current());
+ UNREACHABLE_RETURN(Qundef);
}
/*
@@ -5113,7 +5399,7 @@ rb_exec_recursive_paired_outer(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VAL
/*
* call-seq:
- * thread.backtrace -> array
+ * thread.backtrace -> array or nil
*
* Returns the current backtrace of the target thread.
*
@@ -5142,6 +5428,16 @@ rb_thread_backtrace_locations_m(int argc, VALUE *argv, VALUE thval)
return rb_vm_thread_backtrace_locations(argc, argv, thval);
}
+void
+Init_Thread_Mutex(void)
+{
+ rb_thread_t *th = GET_THREAD();
+
+ rb_native_mutex_initialize(&th->vm->waitpid_lock);
+ rb_native_mutex_initialize(&th->vm->workqueue_lock);
+ rb_native_mutex_initialize(&th->interrupt_lock);
+}
+
/*
* Document-class: ThreadError
*
@@ -5160,15 +5456,12 @@ rb_thread_backtrace_locations_m(int argc, VALUE *argv, VALUE thval)
void
Init_Thread(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
VALUE cThGroup;
rb_thread_t *th = GET_THREAD();
- sym_never = ID2SYM(rb_intern("never"));
- sym_immediate = ID2SYM(rb_intern("immediate"));
- sym_on_blocking = ID2SYM(rb_intern("on_blocking"));
+ sym_never = ID2SYM(rb_intern_const("never"));
+ sym_immediate = ID2SYM(rb_intern_const("immediate"));
+ sym_on_blocking = ID2SYM(rb_intern_const("on_blocking"));
rb_define_singleton_method(rb_cThread, "new", thread_s_new, -1);
rb_define_singleton_method(rb_cThread, "start", thread_start, -2);
@@ -5184,6 +5477,8 @@ Init_Thread(void)
rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
rb_define_singleton_method(rb_cThread, "report_on_exception", rb_thread_s_report_exc, 0);
rb_define_singleton_method(rb_cThread, "report_on_exception=", rb_thread_s_report_exc_set, 1);
+ rb_define_singleton_method(rb_cThread, "ignore_deadlock", rb_thread_s_ignore_deadlock, 0);
+ rb_define_singleton_method(rb_cThread, "ignore_deadlock=", rb_thread_s_ignore_deadlock_set, 1);
#if THREAD_DEBUG < 0
rb_define_singleton_method(rb_cThread, "DEBUG", rb_thread_s_debug, 0);
rb_define_singleton_method(rb_cThread, "DEBUG=", rb_thread_s_debug_set, 1);
@@ -5219,7 +5514,6 @@ Init_Thread(void)
rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
rb_define_method(rb_cThread, "report_on_exception", rb_thread_report_exc, 0);
rb_define_method(rb_cThread, "report_on_exception=", rb_thread_report_exc_set, 1);
- rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
rb_define_method(rb_cThread, "group", rb_thread_group, 0);
rb_define_method(rb_cThread, "backtrace", rb_thread_backtrace_m, -1);
rb_define_method(rb_cThread, "backtrace_locations", rb_thread_backtrace_locations_m, -1);
@@ -5240,11 +5534,11 @@ Init_Thread(void)
rb_define_method(cThGroup, "add", thgroup_add, 1);
{
- th->thgroup = th->vm->thgroup_default = rb_obj_alloc(cThGroup);
+ th->thgroup = th->ractor->thgroup_default = rb_obj_alloc(cThGroup);
rb_define_const(cThGroup, "Default", th->thgroup);
}
- recursive_key = rb_intern("__recursive_key__");
+ recursive_key = rb_intern_const("__recursive_key__");
rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
/* init thread core */
@@ -5252,11 +5546,8 @@ Init_Thread(void)
/* main thread setting */
{
/* acquire global vm lock */
- gvl_init(th->vm);
- gvl_acquire(th->vm, th);
- rb_native_mutex_initialize(&th->vm->waitpid_lock);
- rb_native_mutex_initialize(&th->vm->workqueue_lock);
- rb_native_mutex_initialize(&th->interrupt_lock);
+ rb_global_vm_lock_t *gvl = rb_ractor_gvl(th->ractor);
+ gvl_acquire(gvl, th);
th->pending_interrupt_queue = rb_ary_tmp_new(0);
th->pending_interrupt_queue_checked = 0;
@@ -5266,9 +5557,6 @@ Init_Thread(void)
rb_thread_create_timer_thread();
- /* suppress warnings on cygwin, mingw and mswin.*/
- (void)native_mutex_trylock;
-
Init_thread_sync();
}
@@ -5281,67 +5569,74 @@ ruby_native_thread_p(void)
}
static void
-debug_deadlock_check(rb_vm_t *vm, VALUE msg)
+debug_deadlock_check(rb_ractor_t *r, VALUE msg)
{
rb_thread_t *th = 0;
VALUE sep = rb_str_new_cstr("\n ");
rb_str_catf(msg, "\n%d threads, %d sleeps current:%p main thread:%p\n",
- vm_living_thread_num(vm), vm->sleeper, (void *)GET_THREAD(), (void *)vm->main_thread);
- list_for_each(&vm->living_threads, th, vmlt_node) {
- rb_str_catf(msg, "* %+"PRIsVALUE"\n rb_thread_t:%p "
- "native:%"PRI_THREAD_ID" int:%u",
- th->self, (void *)th, thread_id_str(th), th->ec->interrupt_flag);
- if (th->locking_mutex) {
- rb_mutex_t *mutex = mutex_ptr(th->locking_mutex);
- rb_str_catf(msg, " mutex:%p cond:%"PRIuSIZE,
- (void *)mutex->th, rb_mutex_num_waiting(mutex));
- }
- {
- rb_thread_list_t *list = th->join_list;
- while (list) {
- rb_str_catf(msg, "\n depended by: tb_thread_id:%p", (void *)list->th);
- list = list->next;
- }
- }
- rb_str_catf(msg, "\n ");
- rb_str_concat(msg, rb_ary_join(rb_ec_backtrace_str_ary(th->ec, 0, 0), sep));
- rb_str_catf(msg, "\n");
+ rb_ractor_living_thread_num(r), rb_ractor_sleeper_thread_num(r),
+ (void *)GET_THREAD(), (void *)r->threads.main);
+
+ list_for_each(&r->threads.set, th, lt_node) {
+ rb_str_catf(msg, "* %+"PRIsVALUE"\n rb_thread_t:%p "
+ "native:%"PRI_THREAD_ID" int:%u",
+ th->self, (void *)th, thread_id_str(th), th->ec->interrupt_flag);
+
+ if (th->locking_mutex) {
+ rb_mutex_t *mutex = mutex_ptr(th->locking_mutex);
+ rb_str_catf(msg, " mutex:%p cond:%"PRIuSIZE,
+ (void *)mutex->fiber, rb_mutex_num_waiting(mutex));
+ }
+
+ {
+ struct rb_waiting_list *list = th->join_list;
+ while (list) {
+ rb_str_catf(msg, "\n depended by: tb_thread_id:%p", (void *)list->thread);
+ list = list->next;
+ }
+ }
+ rb_str_catf(msg, "\n ");
+ rb_str_concat(msg, rb_ary_join(rb_ec_backtrace_str_ary(th->ec, 0, 0), sep));
+ rb_str_catf(msg, "\n");
}
}
static void
-rb_check_deadlock(rb_vm_t *vm)
+rb_check_deadlock(rb_ractor_t *r)
{
+ if (GET_THREAD()->vm->thread_ignore_deadlock) return;
+
int found = 0;
- rb_thread_t *th = 0;
+ rb_thread_t *th = NULL;
+ int sleeper_num = rb_ractor_sleeper_thread_num(r);
+ int ltnum = rb_ractor_living_thread_num(r);
- if (vm_living_thread_num(vm) > vm->sleeper) return;
- if (vm_living_thread_num(vm) < vm->sleeper) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
+ if (ltnum > sleeper_num) return;
+ if (ltnum < sleeper_num) rb_bug("sleeper must not be more than vm_living_thread_num(vm)");
if (patrol_thread && patrol_thread != GET_THREAD()) return;
- list_for_each(&vm->living_threads, th, vmlt_node) {
- if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th->ec)) {
- found = 1;
- }
- else if (th->locking_mutex) {
- rb_mutex_t *mutex = mutex_ptr(th->locking_mutex);
-
- if (mutex->th == th || (!mutex->th && !list_empty(&mutex->waitq))) {
- found = 1;
- }
- }
- if (found)
- break;
+ list_for_each(&r->threads.set, th, lt_node) {
+ if (th->status != THREAD_STOPPED_FOREVER || RUBY_VM_INTERRUPTED(th->ec)) {
+ found = 1;
+ }
+ else if (th->locking_mutex) {
+ rb_mutex_t *mutex = mutex_ptr(th->locking_mutex);
+ if (mutex->fiber == th->ec->fiber_ptr || (!mutex->fiber && !list_empty(&mutex->waitq))) {
+ found = 1;
+ }
+ }
+ if (found)
+ break;
}
if (!found) {
VALUE argv[2];
argv[0] = rb_eFatal;
argv[1] = rb_str_new2("No live threads left. Deadlock?");
- debug_deadlock_check(vm, argv[1]);
- vm->sleeper--;
- rb_threadptr_raise(vm->main_thread, 2, argv);
+ debug_deadlock_check(r, argv[1]);
+ rb_ractor_sleeper_threads_dec(GET_RACTOR());
+ rb_threadptr_raise(r->threads.main, 2, argv);
}
}
@@ -5400,6 +5695,8 @@ rb_resolve_me_location(const rb_method_entry_t *me, VALUE resolved_location[5])
{
VALUE path, beg_pos_lineno, beg_pos_column, end_pos_lineno, end_pos_column;
+ if (!me->def) return NULL; // negative cme
+
retry:
switch (me->def->type) {
case VM_METHOD_TYPE_ISEQ: {
@@ -5527,20 +5824,31 @@ rb_default_coverage(int n)
RARRAY_ASET(coverage, COVERAGE_INDEX_LINES, lines);
if (mode & COVERAGE_TARGET_BRANCHES) {
- branches = rb_ary_tmp_new_fill(2);
- /* internal data structures for branch coverage:
- *
- * [[base_type, base_first_lineno, base_first_column, base_last_lineno, base_last_column,
- * target_type_1, target_first_lineno_1, target_first_column_1, target_last_lineno_1, target_last_column_1, target_counter_index_1,
- * target_type_2, target_first_lineno_2, target_first_column_2, target_last_lineno_2, target_last_column_2, target_counter_index_2, ...],
- * ...]
- *
- * Example: [[:case, 1, 0, 4, 3,
- * :when, 2, 8, 2, 9, 0,
- * :when, 3, 8, 3, 9, 1, ...],
- * ...]
- */
- RARRAY_ASET(branches, 0, rb_ary_tmp_new(0));
+ branches = rb_ary_tmp_new_fill(2);
+ /* internal data structures for branch coverage:
+ *
+ * { branch base node =>
+ * [base_type, base_first_lineno, base_first_column, base_last_lineno, base_last_column, {
+ * branch target id =>
+ * [target_type, target_first_lineno, target_first_column, target_last_lineno, target_last_column, target_counter_index],
+ * ...
+ * }],
+ * ...
+ * }
+ *
+ * Example:
+ * { NODE_CASE =>
+ * [1, 0, 4, 3, {
+ * NODE_WHEN => [2, 8, 2, 9, 0],
+ * NODE_WHEN => [3, 8, 3, 9, 1],
+ * ...
+ * }],
+ * ...
+ * }
+ */
+ VALUE structure = rb_hash_new();
+ rb_obj_hide(structure);
+ RARRAY_ASET(branches, 0, structure);
/* branch execution counters */
RARRAY_ASET(branches, 1, rb_ary_tmp_new(0));
}
@@ -5549,6 +5857,19 @@ rb_default_coverage(int n)
return coverage;
}
+static VALUE
+uninterruptible_exit(VALUE v)
+{
+ rb_thread_t *cur_th = GET_THREAD();
+ rb_ary_pop(cur_th->pending_interrupt_mask_stack);
+
+ cur_th->pending_interrupt_queue_checked = 0;
+ if (!rb_threadptr_pending_interrupt_empty_p(cur_th)) {
+ RUBY_VM_SET_INTERRUPT(cur_th->ec);
+ }
+ return Qnil;
+}
+
VALUE
rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data)
{
@@ -5559,5 +5880,8 @@ rb_uninterruptible(VALUE (*b_proc)(VALUE), VALUE data)
OBJ_FREEZE_RAW(interrupt_mask);
rb_ary_push(cur_th->pending_interrupt_mask_stack, interrupt_mask);
- return rb_ensure(b_proc, data, rb_ary_pop, cur_th->pending_interrupt_mask_stack);
+ VALUE ret = rb_ensure(b_proc, data, uninterruptible_exit, Qnil);
+
+ RUBY_VM_CHECK_INTS(cur_th->ec);
+ return ret;
}
diff --git a/thread_pthread.c b/thread_pthread.c
index cbe6aa028a..134d1875cb 100644
--- a/thread_pthread.c
+++ b/thread_pthread.c
@@ -122,26 +122,14 @@ static struct {
};
#endif
-void rb_native_mutex_lock(rb_nativethread_lock_t *lock);
-void rb_native_mutex_unlock(rb_nativethread_lock_t *lock);
-static int native_mutex_trylock(rb_nativethread_lock_t *lock);
-void rb_native_mutex_initialize(rb_nativethread_lock_t *lock);
-void rb_native_mutex_destroy(rb_nativethread_lock_t *lock);
-void rb_native_cond_signal(rb_nativethread_cond_t *cond);
-void rb_native_cond_broadcast(rb_nativethread_cond_t *cond);
-void rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex);
-void rb_native_cond_initialize(rb_nativethread_cond_t *cond);
-void rb_native_cond_destroy(rb_nativethread_cond_t *cond);
-static void clear_thread_cache_altstack(void);
-static void ubf_wakeup_all_threads(void);
-static int ubf_threads_empty(void);
-static int native_cond_timedwait(rb_nativethread_cond_t *, pthread_mutex_t *,
- const rb_hrtime_t *abs);
static const rb_hrtime_t *sigwait_timeout(rb_thread_t *, int sigwait_fd,
const rb_hrtime_t *,
int *drained_p);
static void ubf_timer_disarm(void);
static void threadptr_trap_interrupt(rb_thread_t *);
+static void clear_thread_cache_altstack(void);
+static void ubf_wakeup_all_threads(void);
+static int ubf_threads_empty(void);
#define TIMER_THREAD_CREATED_P() (signal_self_pipe.owner_process == getpid())
@@ -180,17 +168,18 @@ static const void *const condattr_monotonic = NULL;
#define TIME_QUANTUM_NSEC (TIME_QUANTUM_USEC * 1000)
static rb_hrtime_t native_cond_timeout(rb_nativethread_cond_t *, rb_hrtime_t);
+static int native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, const rb_hrtime_t *abs);
/*
* Designate the next gvl.timer thread, favor the last thread in
* the waitq since it will be in waitq longest
*/
static int
-designate_timer_thread(rb_vm_t *vm)
+designate_timer_thread(rb_global_vm_lock_t *gvl)
{
native_thread_data_t *last;
- last = list_tail(&vm->gvl.waitq, native_thread_data_t, node.ubf);
+ last = list_tail(&gvl->waitq, native_thread_data_t, node.ubf);
if (last) {
rb_native_cond_signal(&last->cond.gvlq);
return TRUE;
@@ -203,29 +192,31 @@ designate_timer_thread(rb_vm_t *vm)
* periodically. Continue on old timeout if it expired.
*/
static void
-do_gvl_timer(rb_vm_t *vm, rb_thread_t *th)
+do_gvl_timer(rb_global_vm_lock_t *gvl, rb_thread_t *th)
{
+ rb_vm_t *vm = GET_VM();
static rb_hrtime_t abs;
native_thread_data_t *nd = &th->native_thread_data;
- vm->gvl.timer = th;
+ gvl->timer = th;
/* take over wakeups from UBF_TIMER */
ubf_timer_disarm();
- if (vm->gvl.timer_err == ETIMEDOUT) {
+ if (gvl->timer_err == ETIMEDOUT) {
abs = native_cond_timeout(&nd->cond.gvlq, TIME_QUANTUM_NSEC);
}
- vm->gvl.timer_err = native_cond_timedwait(&nd->cond.gvlq, &vm->gvl.lock, &abs);
+ gvl->timer_err = native_cond_timedwait(&nd->cond.gvlq, &gvl->lock, &abs);
ubf_wakeup_all_threads();
ruby_sigchld_handler(vm);
+
if (UNLIKELY(rb_signal_buff_size())) {
- if (th == vm->main_thread) {
+ if (th == vm->ractor.main_thread) {
RUBY_VM_SET_TRAP_INTERRUPT(th->ec);
}
else {
- threadptr_trap_interrupt(vm->main_thread);
+ threadptr_trap_interrupt(vm->ractor.main_thread);
}
}
@@ -233,77 +224,80 @@ do_gvl_timer(rb_vm_t *vm, rb_thread_t *th)
* Timeslice. Warning: the process may fork while this
* thread is contending for GVL:
*/
- if (vm->gvl.owner) timer_thread_function();
- vm->gvl.timer = 0;
+ if (gvl->owner) {
+ // strictly speaking, accessing "gvl->owner" is not thread-safe
+ RUBY_VM_SET_TIMER_INTERRUPT(gvl->owner->ec);
+ }
+ gvl->timer = 0;
}
static void
-gvl_acquire_common(rb_vm_t *vm, rb_thread_t *th)
+gvl_acquire_common(rb_global_vm_lock_t *gvl, rb_thread_t *th)
{
- if (vm->gvl.owner) {
+ if (gvl->owner) {
native_thread_data_t *nd = &th->native_thread_data;
VM_ASSERT(th->unblock.func == 0 &&
"we must not be in ubf_list and GVL waitq at the same time");
- list_add_tail(&vm->gvl.waitq, &nd->node.gvl);
+ list_add_tail(&gvl->waitq, &nd->node.gvl);
do {
- if (!vm->gvl.timer) {
- do_gvl_timer(vm, th);
+ if (!gvl->timer) {
+ do_gvl_timer(gvl, th);
}
else {
- rb_native_cond_wait(&nd->cond.gvlq, &vm->gvl.lock);
+ rb_native_cond_wait(&nd->cond.gvlq, &gvl->lock);
}
- } while (vm->gvl.owner);
+ } while (gvl->owner);
list_del_init(&nd->node.gvl);
- if (vm->gvl.need_yield) {
- vm->gvl.need_yield = 0;
- rb_native_cond_signal(&vm->gvl.switch_cond);
+ if (gvl->need_yield) {
+ gvl->need_yield = 0;
+ rb_native_cond_signal(&gvl->switch_cond);
}
}
else { /* reset timer if uncontended */
- vm->gvl.timer_err = ETIMEDOUT;
+ gvl->timer_err = ETIMEDOUT;
}
- vm->gvl.owner = th;
- if (!vm->gvl.timer) {
- if (!designate_timer_thread(vm) && !ubf_threads_empty()) {
+ gvl->owner = th;
+ if (!gvl->timer) {
+ if (!designate_timer_thread(gvl) && !ubf_threads_empty()) {
rb_thread_wakeup_timer_thread(-1);
}
}
}
static void
-gvl_acquire(rb_vm_t *vm, rb_thread_t *th)
+gvl_acquire(rb_global_vm_lock_t *gvl, rb_thread_t *th)
{
- rb_native_mutex_lock(&vm->gvl.lock);
- gvl_acquire_common(vm, th);
- rb_native_mutex_unlock(&vm->gvl.lock);
+ rb_native_mutex_lock(&gvl->lock);
+ gvl_acquire_common(gvl, th);
+ rb_native_mutex_unlock(&gvl->lock);
}
static const native_thread_data_t *
-gvl_release_common(rb_vm_t *vm)
+gvl_release_common(rb_global_vm_lock_t *gvl)
{
native_thread_data_t *next;
- vm->gvl.owner = 0;
- next = list_top(&vm->gvl.waitq, native_thread_data_t, node.ubf);
+ gvl->owner = 0;
+ next = list_top(&gvl->waitq, native_thread_data_t, node.ubf);
if (next) rb_native_cond_signal(&next->cond.gvlq);
return next;
}
static void
-gvl_release(rb_vm_t *vm)
+gvl_release(rb_global_vm_lock_t *gvl)
{
- rb_native_mutex_lock(&vm->gvl.lock);
- gvl_release_common(vm);
- rb_native_mutex_unlock(&vm->gvl.lock);
+ rb_native_mutex_lock(&gvl->lock);
+ gvl_release_common(gvl);
+ rb_native_mutex_unlock(&gvl->lock);
}
static void
-gvl_yield(rb_vm_t *vm, rb_thread_t *th)
+gvl_yield(rb_global_vm_lock_t *gvl, rb_thread_t *th)
{
const native_thread_data_t *next;
@@ -312,49 +306,49 @@ gvl_yield(rb_vm_t *vm, rb_thread_t *th)
* (perhaps looping in io_close_fptr) so we kick them:
*/
ubf_wakeup_all_threads();
- rb_native_mutex_lock(&vm->gvl.lock);
- next = gvl_release_common(vm);
+ rb_native_mutex_lock(&gvl->lock);
+ next = gvl_release_common(gvl);
/* An another thread is processing GVL yield. */
- if (UNLIKELY(vm->gvl.wait_yield)) {
- while (vm->gvl.wait_yield)
- rb_native_cond_wait(&vm->gvl.switch_wait_cond, &vm->gvl.lock);
+ if (UNLIKELY(gvl->wait_yield)) {
+ while (gvl->wait_yield)
+ rb_native_cond_wait(&gvl->switch_wait_cond, &gvl->lock);
}
else if (next) {
/* Wait until another thread task takes GVL. */
- vm->gvl.need_yield = 1;
- vm->gvl.wait_yield = 1;
- while (vm->gvl.need_yield)
- rb_native_cond_wait(&vm->gvl.switch_cond, &vm->gvl.lock);
- vm->gvl.wait_yield = 0;
- rb_native_cond_broadcast(&vm->gvl.switch_wait_cond);
+ gvl->need_yield = 1;
+ gvl->wait_yield = 1;
+ while (gvl->need_yield)
+ rb_native_cond_wait(&gvl->switch_cond, &gvl->lock);
+ gvl->wait_yield = 0;
+ rb_native_cond_broadcast(&gvl->switch_wait_cond);
}
else {
- rb_native_mutex_unlock(&vm->gvl.lock);
+ rb_native_mutex_unlock(&gvl->lock);
native_thread_yield();
- rb_native_mutex_lock(&vm->gvl.lock);
- rb_native_cond_broadcast(&vm->gvl.switch_wait_cond);
+ rb_native_mutex_lock(&gvl->lock);
+ rb_native_cond_broadcast(&gvl->switch_wait_cond);
}
- gvl_acquire_common(vm, th);
- rb_native_mutex_unlock(&vm->gvl.lock);
+ gvl_acquire_common(gvl, th);
+ rb_native_mutex_unlock(&gvl->lock);
}
-static void
-gvl_init(rb_vm_t *vm)
+void
+rb_gvl_init(rb_global_vm_lock_t *gvl)
{
- rb_native_mutex_initialize(&vm->gvl.lock);
- rb_native_cond_initialize(&vm->gvl.switch_cond);
- rb_native_cond_initialize(&vm->gvl.switch_wait_cond);
- list_head_init(&vm->gvl.waitq);
- vm->gvl.owner = 0;
- vm->gvl.timer = 0;
- vm->gvl.timer_err = ETIMEDOUT;
- vm->gvl.need_yield = 0;
- vm->gvl.wait_yield = 0;
+ rb_native_mutex_initialize(&gvl->lock);
+ rb_native_cond_initialize(&gvl->switch_cond);
+ rb_native_cond_initialize(&gvl->switch_wait_cond);
+ list_head_init(&gvl->waitq);
+ gvl->owner = 0;
+ gvl->timer = 0;
+ gvl->timer_err = ETIMEDOUT;
+ gvl->need_yield = 0;
+ gvl->wait_yield = 0;
}
static void
-gvl_destroy(rb_vm_t *vm)
+gvl_destroy(rb_global_vm_lock_t *gvl)
{
/*
* only called once at VM shutdown (not atfork), another thread
@@ -362,9 +356,9 @@ gvl_destroy(rb_vm_t *vm)
* the end of thread_start_func_2
*/
if (0) {
- rb_native_cond_destroy(&vm->gvl.switch_wait_cond);
- rb_native_cond_destroy(&vm->gvl.switch_cond);
- rb_native_mutex_destroy(&vm->gvl.lock);
+ rb_native_cond_destroy(&gvl->switch_wait_cond);
+ rb_native_cond_destroy(&gvl->switch_cond);
+ rb_native_mutex_destroy(&gvl->lock);
}
clear_thread_cache_altstack();
}
@@ -372,11 +366,11 @@ gvl_destroy(rb_vm_t *vm)
#if defined(HAVE_WORKING_FORK)
static void thread_cache_reset(void);
static void
-gvl_atfork(rb_vm_t *vm)
+gvl_atfork(rb_global_vm_lock_t *gvl)
{
thread_cache_reset();
- gvl_init(vm);
- gvl_acquire(vm, GET_THREAD());
+ rb_gvl_init(gvl);
+ gvl_acquire(gvl, GET_THREAD());
}
#endif
@@ -415,8 +409,8 @@ rb_native_mutex_unlock(pthread_mutex_t *lock)
}
}
-static inline int
-native_mutex_trylock(pthread_mutex_t *lock)
+int
+rb_native_mutex_trylock(pthread_mutex_t *lock)
{
int r;
mutex_debug("trylock", lock);
@@ -513,8 +507,7 @@ rb_native_cond_wait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex)
}
static int
-native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex,
- const rb_hrtime_t *abs)
+native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, const rb_hrtime_t *abs)
{
int r;
struct timespec ts;
@@ -526,16 +519,24 @@ native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex,
* Let's hide it from arch generic code.
*/
do {
- r = pthread_cond_timedwait(cond, mutex, rb_hrtime2timespec(&ts, abs));
+ rb_hrtime2timespec(&ts, abs);
+ r = pthread_cond_timedwait(cond, mutex, &ts);
} while (r == EINTR);
if (r != 0 && r != ETIMEDOUT) {
- rb_bug_errno("pthread_cond_timedwait", r);
+ rb_bug_errno("pthread_cond_timedwait", r);
}
return r;
}
+void
+rb_native_cond_timedwait(rb_nativethread_cond_t *cond, pthread_mutex_t *mutex, unsigned long msec)
+{
+ rb_hrtime_t hrmsec = native_cond_timeout(cond, RB_HRTIME_PER_MSEC * msec);
+ native_cond_timedwait(cond, mutex, &hrmsec);
+}
+
static rb_hrtime_t
native_cond_timeout(rb_nativethread_cond_t *cond, const rb_hrtime_t rel)
{
@@ -553,7 +554,11 @@ native_cond_timeout(rb_nativethread_cond_t *cond, const rb_hrtime_t rel)
#define native_cleanup_push pthread_cleanup_push
#define native_cleanup_pop pthread_cleanup_pop
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+static RB_THREAD_LOCAL_SPECIFIER rb_thread_t *ruby_native_thread;
+#else
static pthread_key_t ruby_native_thread_key;
+#endif
static void
null_func(int i)
@@ -564,13 +569,25 @@ null_func(int i)
static rb_thread_t *
ruby_thread_from_native(void)
{
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+ return ruby_native_thread;
+#else
return pthread_getspecific(ruby_native_thread_key);
+#endif
}
static int
ruby_thread_set_native(rb_thread_t *th)
{
+ if (th && th->ec) {
+ rb_ractor_set_current_ec(th->ractor, th->ec);
+ }
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+ ruby_native_thread = th;
+ return 1;
+#else
return pthread_setspecific(ruby_native_thread_key, th) == 0;
+#endif
}
static void native_thread_init(rb_thread_t *th);
@@ -587,8 +604,17 @@ Init_native_thread(rb_thread_t *th)
if (r) condattr_monotonic = NULL;
}
#endif
- pthread_key_create(&ruby_native_thread_key, NULL);
+
+#ifndef RB_THREAD_LOCAL_SPECIFIER
+ if (pthread_key_create(&ruby_native_thread_key, 0) == EAGAIN) {
+ rb_bug("pthread_key_create failed (ruby_native_thread_key)");
+ }
+ if (pthread_key_create(&ruby_current_ec_key, 0) == EAGAIN) {
+ rb_bug("pthread_key_create failed (ruby_current_ec_key)");
+ }
+#endif
th->thread_id = pthread_self();
+ ruby_thread_set_native(th);
fill_thread_id_str(th);
native_thread_init(th);
posix_signal(SIGVTALRM, null_func);
@@ -605,7 +631,6 @@ native_thread_init(rb_thread_t *th)
rb_native_cond_initialize(&nd->cond.gvlq);
if (&nd->cond.gvlq != &nd->cond.intr)
rb_native_cond_initialize(&nd->cond.intr);
- ruby_thread_set_native(th);
}
#ifndef USE_THREAD_CACHE
@@ -950,7 +975,7 @@ static void *
thread_start_func_1(void *th_ptr)
{
rb_thread_t *th = th_ptr;
- RB_ALTSTACK_INIT(void *altstack);
+ RB_ALTSTACK_INIT(void *altstack, th->altstack);
#if USE_THREAD_CACHE
thread_start:
#endif
@@ -1099,6 +1124,9 @@ native_thread_create(rb_thread_t *th)
const size_t stack_size = th->vm->default_params.thread_machine_stack_size + th->vm->default_params.thread_vm_stack_size;
const size_t space = space_size(stack_size);
+#ifdef USE_SIGALTSTACK
+ th->altstack = rb_allocate_sigaltstack();
+#endif
th->ec->machine.stack_maxsize = stack_size - space;
CHECK_ERR(pthread_attr_init(&attr));
@@ -1113,7 +1141,7 @@ native_thread_create(rb_thread_t *th)
# endif
CHECK_ERR(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
- err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th);
+ err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th);
thread_debug("create: %p (%d)\n", (void *)th, err);
/* should be done in the created thread */
fill_thread_id_str(th);
@@ -1204,7 +1232,7 @@ native_cond_sleep(rb_thread_t *th, rb_hrtime_t *rel)
}
end = native_cond_timeout(cond, *rel);
- native_cond_timedwait(cond, lock, &end);
+ native_cond_timedwait(cond, lock, &end);
}
}
th->unblock.func = 0;
@@ -1274,7 +1302,7 @@ static void
ubf_select(void *ptr)
{
rb_thread_t *th = (rb_thread_t *)ptr;
- rb_vm_t *vm = th->vm;
+ rb_global_vm_lock_t *gvl = rb_ractor_gvl(th->ractor);
const rb_thread_t *cur = ruby_thread_from_native(); /* may be 0 */
register_ubf_list(th);
@@ -1289,17 +1317,17 @@ ubf_select(void *ptr)
* sigwait_th thread, otherwise we can deadlock with a thread
* in unblock_function_clear.
*/
- if (cur != vm->gvl.timer && cur != sigwait_th) {
+ if (cur != gvl->timer && cur != sigwait_th) {
/*
* Double-checked locking above was to prevent nested locking
* by the SAME thread. We use trylock here to prevent deadlocks
* between DIFFERENT threads
*/
- if (native_mutex_trylock(&vm->gvl.lock) == 0) {
- if (!vm->gvl.timer) {
+ if (rb_native_mutex_trylock(&gvl->lock) == 0) {
+ if (!gvl->timer) {
rb_thread_wakeup_timer_thread(-1);
}
- rb_native_mutex_unlock(&vm->gvl.lock);
+ rb_native_mutex_unlock(&gvl->lock);
}
}
@@ -1468,7 +1496,7 @@ rb_thread_wakeup_timer_thread(int sig)
* on heap for maximum safety (and startup/shutdown speed)
*/
if (!vm) return;
- mth = vm->main_thread;
+ mth = vm->ractor.main_thread;
if (!mth || system_working <= 0) return;
/* this relies on GC for grace period before cont_free */
@@ -1569,6 +1597,18 @@ setup_communication_pipe_internal(int pipes[2])
# define SET_CURRENT_THREAD_NAME(name) prctl(PR_SET_NAME, name)
#endif
+enum {
+ THREAD_NAME_MAX =
+#if defined(__linux__)
+ 16
+#elif defined(__APPLE__)
+/* Undocumented, and main thread seems unlimited */
+ 64
+#else
+ 16
+#endif
+};
+
static VALUE threadptr_invoke_proc_location(rb_thread_t *th);
static void
@@ -1581,14 +1621,14 @@ native_set_thread_name(rb_thread_t *th)
}
else if ((loc = threadptr_invoke_proc_location(th)) != Qnil) {
char *name, *p;
- char buf[16];
+ char buf[THREAD_NAME_MAX];
size_t len;
int n;
name = RSTRING_PTR(RARRAY_AREF(loc, 0));
p = strrchr(name, '/'); /* show only the basename of the path. */
if (p && p[1])
- name = p + 1;
+ name = p + 1;
n = snprintf(buf, sizeof(buf), "%s:%d", name, NUM2INT(RARRAY_AREF(loc, 1)));
rb_gc_force_recycle(loc); /* acts as a GC guard, too */
@@ -1603,15 +1643,30 @@ native_set_thread_name(rb_thread_t *th)
#endif
}
-static VALUE
+static void
native_set_another_thread_name(rb_nativethread_id_t thread_id, VALUE name)
{
-#ifdef SET_ANOTHER_THREAD_NAME
+#if defined SET_ANOTHER_THREAD_NAME || defined SET_CURRENT_THREAD_NAME
+ char buf[THREAD_NAME_MAX];
const char *s = "";
- if (!NIL_P(name)) s = RSTRING_PTR(name);
+# if !defined SET_ANOTHER_THREAD_NAME
+ if (!pthread_equal(pthread_self(), thread_id)) return;
+# endif
+ if (!NIL_P(name)) {
+ long n;
+ RSTRING_GETMEM(name, s, n);
+ if (n >= (int)sizeof(buf)) {
+ memcpy(buf, s, sizeof(buf)-1);
+ buf[sizeof(buf)-1] = '\0';
+ s = buf;
+ }
+ }
+# if defined SET_ANOTHER_THREAD_NAME
SET_ANOTHER_THREAD_NAME(thread_id, s);
+# elif defined SET_CURRENT_THREAD_NAME
+ SET_CURRENT_THREAD_NAME(s);
+# endif
#endif
- return name;
}
static void
@@ -1704,6 +1759,7 @@ ubf_timer_disarm(void)
#if UBF_TIMER == UBF_TIMER_POSIX
rb_atomic_t prev;
+ if (timer_posix.owner && timer_posix.owner != getpid()) return;
prev = ATOMIC_CAS(timer_posix.state, RTIMER_ARMED, RTIMER_DISARM);
switch (prev) {
case RTIMER_DISARM: return; /* likely */
@@ -2033,12 +2089,12 @@ ubf_ppoll_sleep(void *ignore)
*/
#define GVL_UNLOCK_BEGIN_YIELD(th) do { \
const native_thread_data_t *next; \
- rb_vm_t *vm = th->vm; \
+ rb_global_vm_lock_t *gvl = rb_ractor_gvl(th->ractor); \
RB_GC_SAVE_MACHINE_CONTEXT(th); \
- rb_native_mutex_lock(&vm->gvl.lock); \
- next = gvl_release_common(vm); \
- rb_native_mutex_unlock(&vm->gvl.lock); \
- if (!next && vm_living_thread_num(vm) > 1) { \
+ rb_native_mutex_lock(&gvl->lock); \
+ next = gvl_release_common(gvl); \
+ rb_native_mutex_unlock(&gvl->lock); \
+ if (!next && rb_ractor_living_thread_num(th->ractor) > 1) { \
native_thread_yield(); \
}
@@ -2087,6 +2143,7 @@ static void
native_sleep(rb_thread_t *th, rb_hrtime_t *rel)
{
int sigwait_fd = rb_sigwait_fd_get(th);
+ rb_ractor_blocking_threads_inc(th->ractor, __FILE__, __LINE__);
if (sigwait_fd >= 0) {
rb_native_mutex_lock(&th->interrupt_lock);
@@ -2106,12 +2163,14 @@ native_sleep(rb_thread_t *th, rb_hrtime_t *rel)
rb_sigwait_fd_put(th, sigwait_fd);
rb_sigwait_fd_migrate(th->vm);
}
- else if (th == th->vm->main_thread) { /* always able to handle signals */
+ else if (th == th->vm->ractor.main_thread) { /* always able to handle signals */
native_ppoll_sleep(th, rel);
}
else {
native_cond_sleep(th, rel);
}
+
+ rb_ractor_blocking_threads_dec(th->ractor, __FILE__, __LINE__);
}
#if UBF_TIMER == UBF_TIMER_PTHREAD
@@ -2119,7 +2178,7 @@ static void *
timer_pthread_fn(void *p)
{
rb_vm_t *vm = p;
- pthread_t main_thread_id = vm->main_thread->thread_id;
+ pthread_t main_thread_id = vm->ractor.main_thread->thread_id;
struct pollfd pfd;
int timeout = -1;
int ccp;
diff --git a/thread_pthread.h b/thread_pthread.h
index c5244fa32f..1d6ea1385f 100644
--- a/thread_pthread.h
+++ b/thread_pthread.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_THREAD_PTHREAD_H
+#define RUBY_THREAD_PTHREAD_H
/**********************************************************************
thread_pthread.h -
@@ -8,9 +10,6 @@
**********************************************************************/
-#ifndef RUBY_THREAD_PTHREAD_H
-#define RUBY_THREAD_PTHREAD_H
-
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
@@ -18,8 +17,6 @@
#define RB_NATIVETHREAD_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
#define RB_NATIVETHREAD_COND_INIT PTHREAD_COND_INITIALIZER
-typedef pthread_cond_t rb_nativethread_cond_t;
-
typedef struct native_thread_data_struct {
union {
struct list_node ubf;
@@ -40,8 +37,6 @@ typedef struct native_thread_data_struct {
} cond;
} native_thread_data_t;
-void rb_native_mutex_destroy(rb_nativethread_lock_t *lock);
-
#undef except
#undef try
#undef leave
@@ -74,4 +69,47 @@ typedef struct rb_global_vm_lock_struct {
int wait_yield;
} rb_global_vm_lock_t;
+
+#if __STDC_VERSION__ >= 201112
+ #define RB_THREAD_LOCAL_SPECIFIER _Thread_local
+#elif defined(__GNUC__)
+ /* note that ICC (linux) and Clang are covered by __GNUC__ */
+ #define RB_THREAD_LOCAL_SPECIFIER __thread
+#else
+
+typedef pthread_key_t native_tls_key_t;
+
+static inline void *
+native_tls_get(native_tls_key_t key)
+{
+ void *ptr = pthread_getspecific(key);
+ if (UNLIKELY(ptr == NULL)) {
+ rb_bug("pthread_getspecific returns NULL");
+ }
+ return ptr;
+}
+
+static inline void
+native_tls_set(native_tls_key_t key, void *ptr)
+{
+ if (UNLIKELY(pthread_setspecific(key, ptr) != 0)) {
+ rb_bug("pthread_setspecific error");
+ }
+}
+#endif
+
+RUBY_SYMBOL_EXPORT_BEGIN
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+ #if __APPLE__
+ // on Darwin, TLS can not be accessed across .so
+ struct rb_execution_context_struct *rb_current_ec();
+ void rb_current_ec_set(struct rb_execution_context_struct *);
+ #else
+ RUBY_EXTERN RB_THREAD_LOCAL_SPECIFIER struct rb_execution_context_struct *ruby_current_ec;
+ #endif
+#else
+ RUBY_EXTERN native_tls_key_t ruby_current_ec_key;
+#endif
+RUBY_SYMBOL_EXPORT_END
+
#endif /* RUBY_THREAD_PTHREAD_H */
diff --git a/thread_sync.c b/thread_sync.c
index 4c065dd25b..26d5e6b686 100644
--- a/thread_sync.c
+++ b/thread_sync.c
@@ -1,12 +1,22 @@
/* included by thread.c */
#include "ccan/list/list.h"
+#include "coroutine/Stack.h"
static VALUE rb_cMutex, rb_cQueue, rb_cSizedQueue, rb_cConditionVariable;
static VALUE rb_eClosedQueueError;
+/* Mutex */
+typedef struct rb_mutex_struct {
+ rb_fiber_t *fiber;
+ struct rb_mutex_struct *next_mutex;
+ struct list_head waitq; /* protected by GVL */
+} rb_mutex_t;
+
/* sync_waiter is always on-stack */
struct sync_waiter {
+ VALUE self;
rb_thread_t *th;
+ rb_fiber_t *fiber;
struct list_node node;
};
@@ -18,12 +28,19 @@ sync_wakeup(struct list_head *head, long max)
struct sync_waiter *cur = 0, *next;
list_for_each_safe(head, cur, next, node) {
- list_del_init(&cur->node);
- if (cur->th->status != THREAD_KILLED) {
- rb_threadptr_interrupt(cur->th);
- cur->th->status = THREAD_RUNNABLE;
- if (--max == 0) return;
- }
+ list_del_init(&cur->node);
+
+ if (cur->th->status != THREAD_KILLED) {
+
+ if (cur->th->scheduler != Qnil && rb_fiberptr_blocking(cur->fiber) == 0) {
+ rb_scheduler_unblock(cur->th->scheduler, cur->self, rb_fiberptr_self(cur->fiber));
+ } else {
+ rb_threadptr_interrupt(cur->th);
+ cur->th->status = THREAD_RUNNABLE;
+ }
+
+ if (--max == 0) return;
+ }
}
}
@@ -39,20 +56,12 @@ wakeup_all(struct list_head *head)
sync_wakeup(head, LONG_MAX);
}
-/* Mutex */
-
-typedef struct rb_mutex_struct {
- rb_thread_t *th;
- struct rb_mutex_struct *next_mutex;
- struct list_head waitq; /* protected by GVL */
-} rb_mutex_t;
-
#if defined(HAVE_WORKING_FORK)
static void rb_mutex_abandon_all(rb_mutex_t *mutexes);
static void rb_mutex_abandon_keeping_mutexes(rb_thread_t *th);
static void rb_mutex_abandon_locking_mutex(rb_thread_t *th);
#endif
-static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th);
+static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th, rb_fiber_t *fiber);
/*
* Document-class: Mutex
@@ -78,7 +87,7 @@ static const char* rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th);
*
*/
-#define mutex_mark NULL
+#define mutex_mark ((void(*)(void*))0)
static size_t
rb_mutex_num_waiting(rb_mutex_t *mutex)
@@ -93,13 +102,15 @@ rb_mutex_num_waiting(rb_mutex_t *mutex)
return n;
}
+rb_thread_t* rb_fiber_threadptr(const rb_fiber_t *fiber);
+
static void
mutex_free(void *ptr)
{
rb_mutex_t *mutex = ptr;
- if (mutex->th) {
+ if (mutex->fiber) {
/* rb_warn("free locked mutex"); */
- const char *err = rb_mutex_unlock_th(mutex, mutex->th);
+ const char *err = rb_mutex_unlock_th(mutex, rb_fiber_threadptr(mutex->fiber), mutex->fiber);
if (err) rb_bug("%s", err);
}
ruby_xfree(ptr);
@@ -145,6 +156,7 @@ mutex_alloc(VALUE klass)
rb_mutex_t *mutex;
obj = TypedData_Make_Struct(klass, rb_mutex_t, &mutex_data_type, mutex);
+
list_head_init(&mutex->waitq);
return obj;
}
@@ -178,7 +190,31 @@ rb_mutex_locked_p(VALUE self)
{
rb_mutex_t *mutex = mutex_ptr(self);
- return mutex->th ? Qtrue : Qfalse;
+ return mutex->fiber ? Qtrue : Qfalse;
+}
+
+static void
+thread_mutex_insert(rb_thread_t *thread, rb_mutex_t *mutex) {
+ if (thread->keeping_mutexes) {
+ mutex->next_mutex = thread->keeping_mutexes;
+ }
+
+ thread->keeping_mutexes = mutex;
+}
+
+static void
+thread_mutex_remove(rb_thread_t *thread, rb_mutex_t *mutex) {
+ rb_mutex_t **keeping_mutexes = &thread->keeping_mutexes;
+
+ while (*keeping_mutexes && *keeping_mutexes != mutex) {
+ // Move to the next mutex in the list:
+ keeping_mutexes = &(*keeping_mutexes)->next_mutex;
+ }
+
+ if (*keeping_mutexes) {
+ *keeping_mutexes = mutex->next_mutex;
+ mutex->next_mutex = NULL;
+ }
}
static void
@@ -186,10 +222,7 @@ mutex_locked(rb_thread_t *th, VALUE self)
{
rb_mutex_t *mutex = mutex_ptr(self);
- if (th->keeping_mutexes) {
- mutex->next_mutex = th->keeping_mutexes;
- }
- th->keeping_mutexes = mutex;
+ thread_mutex_insert(th, mutex);
}
/*
@@ -203,17 +236,17 @@ VALUE
rb_mutex_trylock(VALUE self)
{
rb_mutex_t *mutex = mutex_ptr(self);
- VALUE locked = Qfalse;
- if (mutex->th == 0) {
+ if (mutex->fiber == 0) {
+ rb_fiber_t *fiber = GET_EC()->fiber_ptr;
rb_thread_t *th = GET_THREAD();
- mutex->th = th;
- locked = Qtrue;
+ mutex->fiber = fiber;
mutex_locked(th, self);
+ return Qtrue;
}
- return locked;
+ return Qfalse;
}
/*
@@ -224,9 +257,9 @@ rb_mutex_trylock(VALUE self)
static const rb_thread_t *patrol_thread = NULL;
static VALUE
-mutex_owned_p(rb_thread_t *th, rb_mutex_t *mutex)
+mutex_owned_p(rb_fiber_t *fiber, rb_mutex_t *mutex)
{
- if (mutex->th == th) {
+ if (mutex->fiber == fiber) {
return Qtrue;
}
else {
@@ -234,10 +267,27 @@ mutex_owned_p(rb_thread_t *th, rb_mutex_t *mutex)
}
}
+static VALUE call_rb_scheduler_block(VALUE mutex) {
+ return rb_scheduler_block(rb_scheduler_current(), mutex, Qnil);
+}
+
+static VALUE
+delete_from_waitq(VALUE v)
+{
+ struct sync_waiter *w = (void *)v;
+ list_del(&w->node);
+
+ COROUTINE_STACK_FREE(w);
+
+ return Qnil;
+}
+
static VALUE
do_mutex_lock(VALUE self, int interruptible_p)
{
- rb_thread_t *th = GET_THREAD();
+ rb_execution_context_t *ec = GET_EC();
+ rb_thread_t *th = ec->thread_ptr;
+ rb_fiber_t *fiber = ec->fiber_ptr;
rb_mutex_t *mutex = mutex_ptr(self);
/* When running trap handler */
@@ -247,71 +297,90 @@ do_mutex_lock(VALUE self, int interruptible_p)
}
if (rb_mutex_trylock(self) == Qfalse) {
- struct sync_waiter w;
-
- if (mutex->th == th) {
- rb_raise(rb_eThreadError, "deadlock; recursive locking");
- }
-
- w.th = th;
-
- while (mutex->th != th) {
- enum rb_thread_status prev_status = th->status;
- rb_hrtime_t *timeout = 0;
- rb_hrtime_t rel = rb_msec2hrtime(100);
-
- th->status = THREAD_STOPPED_FOREVER;
- th->locking_mutex = self;
- th->vm->sleeper++;
- /*
- * Carefully! while some contended threads are in native_sleep(),
- * vm->sleeper is unstable value. we have to avoid both deadlock
- * and busy loop.
- */
- if ((vm_living_thread_num(th->vm) == th->vm->sleeper) &&
- !patrol_thread) {
- timeout = &rel;
- patrol_thread = th;
- }
-
- list_add_tail(&mutex->waitq, &w.node);
- native_sleep(th, timeout); /* release GVL */
- list_del(&w.node);
-
- if (!mutex->th) {
- mutex->th = th;
- }
-
- if (patrol_thread == th)
- patrol_thread = NULL;
-
- th->locking_mutex = Qfalse;
- if (mutex->th && timeout && !RUBY_VM_INTERRUPTED(th->ec)) {
- rb_check_deadlock(th->vm);
- }
- if (th->status == THREAD_STOPPED_FOREVER) {
- th->status = prev_status;
- }
- th->vm->sleeper--;
+ if (mutex->fiber == fiber) {
+ rb_raise(rb_eThreadError, "deadlock; recursive locking");
+ }
+
+ while (mutex->fiber != fiber) {
+ VALUE scheduler = rb_scheduler_current();
+ if (scheduler != Qnil) {
+ COROUTINE_STACK_LOCAL(struct sync_waiter, w);
+ w->self = self;
+ w->th = th;
+ w->fiber = fiber;
+
+ list_add_tail(&mutex->waitq, &w->node);
+
+ rb_ensure(call_rb_scheduler_block, self, delete_from_waitq, (VALUE)w);
+
+ if (!mutex->fiber) {
+ mutex->fiber = fiber;
+ }
+ } else {
+ enum rb_thread_status prev_status = th->status;
+ rb_hrtime_t *timeout = 0;
+ rb_hrtime_t rel = rb_msec2hrtime(100);
+
+ th->status = THREAD_STOPPED_FOREVER;
+ th->locking_mutex = self;
+ rb_ractor_sleeper_threads_inc(th->ractor);
+ /*
+ * Carefully! while some contended threads are in native_sleep(),
+ * ractor->sleeper is unstable value. we have to avoid both deadlock
+ * and busy loop.
+ */
+ if ((rb_ractor_living_thread_num(th->ractor) == rb_ractor_sleeper_thread_num(th->ractor)) &&
+ !patrol_thread) {
+ timeout = &rel;
+ patrol_thread = th;
+ }
+
+ COROUTINE_STACK_LOCAL(struct sync_waiter, w);
+ w->self = self;
+ w->th = th;
+ w->fiber = fiber;
+
+ list_add_tail(&mutex->waitq, &w->node);
+
+ native_sleep(th, timeout); /* release GVL */
+
+ list_del(&w->node);
+
+ COROUTINE_STACK_FREE(w);
+
+ if (!mutex->fiber) {
+ mutex->fiber = fiber;
+ }
+
+ if (patrol_thread == th)
+ patrol_thread = NULL;
+
+ th->locking_mutex = Qfalse;
+ if (mutex->fiber && timeout && !RUBY_VM_INTERRUPTED(th->ec)) {
+ rb_check_deadlock(th->ractor);
+ }
+ if (th->status == THREAD_STOPPED_FOREVER) {
+ th->status = prev_status;
+ }
+ rb_ractor_sleeper_threads_dec(th->ractor);
+ }
if (interruptible_p) {
/* release mutex before checking for interrupts...as interrupt checking
* code might call rb_raise() */
- if (mutex->th == th) mutex->th = 0;
+ if (mutex->fiber == fiber) mutex->fiber = 0;
RUBY_VM_CHECK_INTS_BLOCKING(th->ec); /* may release mutex */
- if (!mutex->th) {
- mutex->th = th;
- mutex_locked(th, self);
+ if (!mutex->fiber) {
+ mutex->fiber = fiber;
}
}
- else {
- if (mutex->th == th) mutex_locked(th, self);
- }
- }
+ }
+
+ if (mutex->fiber == fiber) mutex_locked(th, self);
}
// assertion
- if (mutex_owned_p(th, mutex) == Qfalse) rb_bug("do_mutex_lock: mutex is not owned.");
+ if (mutex_owned_p(fiber, mutex) == Qfalse) rb_bug("do_mutex_lock: mutex is not owned.");
return self;
}
@@ -344,49 +413,51 @@ rb_mutex_lock(VALUE self)
VALUE
rb_mutex_owned_p(VALUE self)
{
- rb_thread_t *th = GET_THREAD();
+ rb_fiber_t *fiber = GET_EC()->fiber_ptr;
rb_mutex_t *mutex = mutex_ptr(self);
- return mutex_owned_p(th, mutex);
+ return mutex_owned_p(fiber, mutex);
}
static const char *
-rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th)
+rb_mutex_unlock_th(rb_mutex_t *mutex, rb_thread_t *th, rb_fiber_t *fiber)
{
const char *err = NULL;
- if (mutex->th == 0) {
- err = "Attempt to unlock a mutex which is not locked";
+ if (mutex->fiber == 0) {
+ err = "Attempt to unlock a mutex which is not locked";
}
- else if (mutex->th != th) {
- err = "Attempt to unlock a mutex which is locked by another thread";
+ else if (mutex->fiber != fiber) {
+ err = "Attempt to unlock a mutex which is locked by another thread/fiber";
}
else {
- struct sync_waiter *cur = 0, *next;
- rb_mutex_t **th_mutex = &th->keeping_mutexes;
-
- mutex->th = 0;
- list_for_each_safe(&mutex->waitq, cur, next, node) {
- list_del_init(&cur->node);
- switch (cur->th->status) {
- case THREAD_RUNNABLE: /* from someone else calling Thread#run */
- case THREAD_STOPPED_FOREVER: /* likely (rb_mutex_lock) */
- rb_threadptr_interrupt(cur->th);
- goto found;
- case THREAD_STOPPED: /* probably impossible */
- rb_bug("unexpected THREAD_STOPPED");
- case THREAD_KILLED:
- /* not sure about this, possible in exit GC? */
- rb_bug("unexpected THREAD_KILLED");
- continue;
- }
- }
- found:
- while (*th_mutex != mutex) {
- th_mutex = &(*th_mutex)->next_mutex;
- }
- *th_mutex = mutex->next_mutex;
- mutex->next_mutex = NULL;
+ struct sync_waiter *cur = 0, *next;
+
+ mutex->fiber = 0;
+ list_for_each_safe(&mutex->waitq, cur, next, node) {
+ list_del_init(&cur->node);
+
+ if (cur->th->scheduler != Qnil && rb_fiberptr_blocking(cur->fiber) == 0) {
+ rb_scheduler_unblock(cur->th->scheduler, cur->self, rb_fiberptr_self(cur->fiber));
+ goto found;
+ } else {
+ switch (cur->th->status) {
+ case THREAD_RUNNABLE: /* from someone else calling Thread#run */
+ case THREAD_STOPPED_FOREVER: /* likely (rb_mutex_lock) */
+ rb_threadptr_interrupt(cur->th);
+ goto found;
+ case THREAD_STOPPED: /* probably impossible */
+ rb_bug("unexpected THREAD_STOPPED");
+ case THREAD_KILLED:
+ /* not sure about this, possible in exit GC? */
+ rb_bug("unexpected THREAD_KILLED");
+ continue;
+ }
+ }
+ }
+
+ found:
+ thread_mutex_remove(th, mutex);
}
return err;
@@ -404,8 +475,9 @@ rb_mutex_unlock(VALUE self)
{
const char *err;
rb_mutex_t *mutex = mutex_ptr(self);
+ rb_thread_t *th = GET_THREAD();
- err = rb_mutex_unlock_th(mutex, GET_THREAD());
+ err = rb_mutex_unlock_th(mutex, th, GET_EC()->fiber_ptr);
if (err) rb_raise(rb_eThreadError, "%s", err);
return self;
@@ -438,7 +510,7 @@ rb_mutex_abandon_all(rb_mutex_t *mutexes)
while (mutexes) {
mutex = mutexes;
mutexes = mutex->next_mutex;
- mutex->th = 0;
+ mutex->fiber = 0;
mutex->next_mutex = 0;
list_head_init(&mutex->waitq);
}
@@ -446,9 +518,9 @@ rb_mutex_abandon_all(rb_mutex_t *mutexes)
#endif
static VALUE
-rb_mutex_sleep_forever(VALUE time)
+rb_mutex_sleep_forever(VALUE self)
{
- rb_thread_sleep_deadly_allow_spurious_wakeup();
+ rb_thread_sleep_deadly_allow_spurious_wakeup(self);
return Qnil;
}
@@ -464,7 +536,6 @@ rb_mutex_wait_for(VALUE time)
VALUE
rb_mutex_sleep(VALUE self, VALUE timeout)
{
- time_t beg, end;
struct timeval t;
if (!NIL_P(timeout)) {
@@ -472,18 +543,23 @@ rb_mutex_sleep(VALUE self, VALUE timeout)
}
rb_mutex_unlock(self);
- beg = time(0);
- if (NIL_P(timeout)) {
- rb_ensure(rb_mutex_sleep_forever, Qnil, mutex_lock_uninterruptible, self);
+ time_t beg = time(0);
+
+ VALUE scheduler = rb_scheduler_current();
+ if (scheduler != Qnil) {
+ rb_scheduler_kernel_sleep(scheduler, timeout);
+ mutex_lock_uninterruptible(self);
+ } else {
+ if (NIL_P(timeout)) {
+ rb_ensure(rb_mutex_sleep_forever, self, mutex_lock_uninterruptible, self);
+ } else {
+ rb_hrtime_t rel = rb_timeval2hrtime(&t);
+ rb_ensure(rb_mutex_wait_for, (VALUE)&rel, mutex_lock_uninterruptible, self);
+ }
}
- else {
- rb_hrtime_t rel = rb_timeval2hrtime(&t);
- rb_ensure(rb_mutex_wait_for, (VALUE)&rel,
- mutex_lock_uninterruptible, self);
- }
RUBY_VM_CHECK_INTS_BLOCKING(GET_EC());
- end = time(0) - beg;
+ time_t end = time(0) - beg;
return TIMET2NUM(end);
}
@@ -863,9 +939,9 @@ rb_queue_push(VALUE self, VALUE obj)
}
static VALUE
-queue_sleep(VALUE arg)
+queue_sleep(VALUE self)
{
- rb_thread_sleep_deadly_allow_spurious_wakeup();
+ rb_thread_sleep_deadly_allow_spurious_wakeup(self);
return Qnil;
}
@@ -885,6 +961,8 @@ queue_sleep_done(VALUE p)
list_del(&qw->w.node);
qw->as.q->num_waiting--;
+ COROUTINE_STACK_FREE(qw);
+
return Qfalse;
}
@@ -896,6 +974,8 @@ szqueue_sleep_done(VALUE p)
list_del(&qw->w.node);
qw->as.sq->num_waiting_push--;
+ COROUTINE_STACK_FREE(qw);
+
return Qfalse;
}
@@ -905,25 +985,30 @@ queue_do_pop(VALUE self, struct rb_queue *q, int should_block)
check_array(self, q->que);
while (RARRAY_LEN(q->que) == 0) {
- if (!should_block) {
- rb_raise(rb_eThreadError, "queue empty");
- }
- else if (queue_closed_p(self)) {
- return queue_closed_result(self, q);
- }
- else {
- struct queue_waiter qw;
-
- assert(RARRAY_LEN(q->que) == 0);
- assert(queue_closed_p(self) == 0);
-
- qw.w.th = GET_THREAD();
- qw.as.q = q;
- list_add_tail(queue_waitq(qw.as.q), &qw.w.node);
- qw.as.q->num_waiting++;
-
- rb_ensure(queue_sleep, self, queue_sleep_done, (VALUE)&qw);
- }
+ if (!should_block) {
+ rb_raise(rb_eThreadError, "queue empty");
+ }
+ else if (queue_closed_p(self)) {
+ return queue_closed_result(self, q);
+ }
+ else {
+ rb_execution_context_t *ec = GET_EC();
+
+ assert(RARRAY_LEN(q->que) == 0);
+ assert(queue_closed_p(self) == 0);
+
+ COROUTINE_STACK_LOCAL(struct queue_waiter, qw);
+
+ qw->w.self = self;
+ qw->w.th = ec->thread_ptr;
+ qw->w.fiber = ec->fiber_ptr;
+
+ qw->as.q = q;
+ list_add_tail(queue_waitq(qw->as.q), &qw->w.node);
+ qw->as.q->num_waiting++;
+
+ rb_ensure(queue_sleep, self, queue_sleep_done, (VALUE)qw);
+ }
}
return rb_ary_shift(q->que);
@@ -1147,28 +1232,31 @@ rb_szqueue_push(int argc, VALUE *argv, VALUE self)
int should_block = szqueue_push_should_block(argc, argv);
while (queue_length(self, &sq->q) >= sq->max) {
- if (!should_block) {
- rb_raise(rb_eThreadError, "queue full");
- }
- else if (queue_closed_p(self)) {
- goto closed;
- }
- else {
- struct queue_waiter qw;
- struct list_head *pushq = szqueue_pushq(sq);
-
- qw.w.th = GET_THREAD();
- qw.as.sq = sq;
- list_add_tail(pushq, &qw.w.node);
- sq->num_waiting_push++;
-
- rb_ensure(queue_sleep, self, szqueue_sleep_done, (VALUE)&qw);
- }
+ if (!should_block) {
+ rb_raise(rb_eThreadError, "queue full");
+ }
+ else if (queue_closed_p(self)) {
+ break;
+ }
+ else {
+ rb_execution_context_t *ec = GET_EC();
+ COROUTINE_STACK_LOCAL(struct queue_waiter, qw);
+ struct list_head *pushq = szqueue_pushq(sq);
+
+ qw->w.self = self;
+ qw->w.th = ec->thread_ptr;
+ qw->w.fiber = ec->fiber_ptr;
+
+ qw->as.sq = sq;
+ list_add_tail(pushq, &qw->w.node);
+ sq->num_waiting_push++;
+
+ rb_ensure(queue_sleep, self, szqueue_sleep_done, (VALUE)qw);
+ }
}
if (queue_closed_p(self)) {
- closed:
- raise_closed_queue_error(self);
+ raise_closed_queue_error(self);
}
return queue_do_push(self, &sq->q, argv[0]);
@@ -1374,15 +1462,6 @@ do_sleep(VALUE args)
return rb_funcallv(p->mutex, id_sleep, 1, &p->timeout);
}
-static VALUE
-delete_from_waitq(VALUE v)
-{
- struct sync_waiter *w = (void *)v;
- list_del(&w->node);
-
- return Qnil;
-}
-
/*
* Document-method: ConditionVariable#wait
* call-seq: wait(mutex, timeout=nil)
@@ -1396,15 +1475,20 @@ delete_from_waitq(VALUE v)
static VALUE
rb_condvar_wait(int argc, VALUE *argv, VALUE self)
{
+ rb_execution_context_t *ec = GET_EC();
+
struct rb_condvar *cv = condvar_ptr(self);
struct sleep_call args;
- struct sync_waiter w;
rb_scan_args(argc, argv, "11", &args.mutex, &args.timeout);
- w.th = GET_THREAD();
- list_add_tail(&cv->waitq, &w.node);
- rb_ensure(do_sleep, (VALUE)&args, delete_from_waitq, (VALUE)&w);
+ COROUTINE_STACK_LOCAL(struct sync_waiter, w);
+ w->self = args.mutex;
+ w->th = ec->thread_ptr;
+ w->fiber = ec->fiber_ptr;
+
+ list_add_tail(&cv->waitq, &w->node);
+ rb_ensure(do_sleep, (VALUE)&args, delete_from_waitq, (VALUE)w);
return self;
}
@@ -1437,6 +1521,7 @@ rb_condvar_broadcast(VALUE self)
return self;
}
+NORETURN(static VALUE undumpable(VALUE obj));
/* :nodoc: */
static VALUE
undumpable(VALUE obj)
diff --git a/thread_win32.c b/thread_win32.c
index d8eb2b1ee6..f4b4ea214c 100644
--- a/thread_win32.c
+++ b/thread_win32.c
@@ -28,8 +28,6 @@
static volatile DWORD ruby_native_thread_key = TLS_OUT_OF_INDEXES;
static int w32_wait_events(HANDLE *events, int count, DWORD timeout, rb_thread_t *th);
-void rb_native_mutex_lock(rb_nativethread_lock_t *lock);
-void rb_native_mutex_unlock(rb_nativethread_lock_t *lock);
static void
w32_error(const char *func)
@@ -54,12 +52,12 @@ w32_error(const char *func)
}
static int
-w32_mutex_lock(HANDLE lock)
+w32_mutex_lock(HANDLE lock, bool try)
{
DWORD result;
while (1) {
thread_debug("rb_native_mutex_lock: %p\n", lock);
- result = w32_wait_events(&lock, 1, INFINITE, 0);
+ result = w32_wait_events(&lock, 1, try ? 0 : INFINITE, 0);
switch (result) {
case WAIT_OBJECT_0:
/* get mutex object */
@@ -72,7 +70,7 @@ w32_mutex_lock(HANDLE lock)
return 0;
case WAIT_TIMEOUT:
thread_debug("timeout mutex: %p\n", lock);
- break;
+ return EBUSY;
case WAIT_ABANDONED:
rb_bug("win32_mutex_lock: WAIT_ABANDONED");
break;
@@ -97,38 +95,38 @@ w32_mutex_create(void)
#define GVL_DEBUG 0
static void
-gvl_acquire(rb_vm_t *vm, rb_thread_t *th)
+gvl_acquire(rb_global_vm_lock_t *gvl, rb_thread_t *th)
{
- w32_mutex_lock(vm->gvl.lock);
+ w32_mutex_lock(gvl->lock, false);
if (GVL_DEBUG) fprintf(stderr, "gvl acquire (%p): acquire\n", th);
}
static void
-gvl_release(rb_vm_t *vm)
+gvl_release(rb_global_vm_lock_t *gvl)
{
- ReleaseMutex(vm->gvl.lock);
+ ReleaseMutex(gvl->lock);
}
static void
-gvl_yield(rb_vm_t *vm, rb_thread_t *th)
+gvl_yield(rb_global_vm_lock_t *gvl, rb_thread_t *th)
{
- gvl_release(th->vm);
+ gvl_release(gvl);
native_thread_yield();
- gvl_acquire(vm, th);
+ gvl_acquire(gvl, th);
}
-static void
-gvl_init(rb_vm_t *vm)
+void
+rb_gvl_init(rb_global_vm_lock_t *gvl)
{
if (GVL_DEBUG) fprintf(stderr, "gvl init\n");
- vm->gvl.lock = w32_mutex_create();
+ gvl->lock = w32_mutex_create();
}
static void
-gvl_destroy(rb_vm_t *vm)
+gvl_destroy(rb_global_vm_lock_t *gvl)
{
if (GVL_DEBUG) fprintf(stderr, "gvl destroy\n");
- CloseHandle(vm->gvl.lock);
+ CloseHandle(gvl->lock);
}
static rb_thread_t *
@@ -140,13 +138,21 @@ ruby_thread_from_native(void)
static int
ruby_thread_set_native(rb_thread_t *th)
{
+ if (th && th->ec) {
+ rb_ractor_set_current_ec(th->ractor, th->ec);
+ }
return TlsSetValue(ruby_native_thread_key, th);
}
void
Init_native_thread(rb_thread_t *th)
{
- ruby_native_thread_key = TlsAlloc();
+ if ((ruby_current_ec_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) {
+ rb_bug("TlsAlloc() for ruby_current_ec_key fails");
+ }
+ if ((ruby_native_thread_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) {
+ rb_bug("TlsAlloc() for ruby_native_thread_key fails");
+ }
ruby_thread_set_native(th);
DuplicateHandle(GetCurrentProcess(),
GetCurrentThread(),
@@ -317,40 +323,30 @@ void
rb_native_mutex_lock(rb_nativethread_lock_t *lock)
{
#if USE_WIN32_MUTEX
- w32_mutex_lock(lock->mutex);
+ w32_mutex_lock(lock->mutex, false);
#else
EnterCriticalSection(&lock->crit);
#endif
}
-void
-rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
+int
+rb_native_mutex_trylock(rb_nativethread_lock_t *lock)
{
#if USE_WIN32_MUTEX
- thread_debug("release mutex: %p\n", lock->mutex);
- ReleaseMutex(lock->mutex);
+ return w32_mutex_lock(lock->mutex, true);
#else
- LeaveCriticalSection(&lock->crit);
+ return TryEnterCriticalSection(&lock->crit) == 0 ? EBUSY : 0;
#endif
}
-static int
-native_mutex_trylock(rb_nativethread_lock_t *lock)
+void
+rb_native_mutex_unlock(rb_nativethread_lock_t *lock)
{
#if USE_WIN32_MUTEX
- int result;
- thread_debug("native_mutex_trylock: %p\n", lock->mutex);
- result = w32_wait_events(&lock->mutex, 1, 1, 0);
- thread_debug("native_mutex_trylock result: %d\n", result);
- switch (result) {
- case WAIT_OBJECT_0:
- return 0;
- case WAIT_TIMEOUT:
- return EBUSY;
- }
- return EINVAL;
+ thread_debug("release mutex: %p\n", lock->mutex);
+ ReleaseMutex(lock->mutex);
#else
- return TryEnterCriticalSection(&lock->crit) == 0;
+ LeaveCriticalSection(&lock->crit);
#endif
}
@@ -458,7 +454,6 @@ rb_native_cond_wait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex)
native_cond_timedwait_ms(cond, mutex, INFINITE);
}
-#if 0
static unsigned long
abs_timespec_to_timeout_ms(const struct timespec *ts)
{
@@ -487,6 +482,19 @@ native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mute
return native_cond_timedwait_ms(cond, mutex, timeout_ms);
}
+static struct timespec native_cond_timeout(rb_nativethread_cond_t *cond, struct timespec timeout_rel);
+
+void
+rb_native_cond_timedwait(rb_nativethread_cond_t *cond, rb_nativethread_lock_t *mutex, unsigned long msec)
+{
+ struct timespec rel = {
+ .tv_sec = msec / 1000,
+ .tv_nsec = (msec % 1000) * 1000 * 1000,
+ };
+ struct timespec ts = native_cond_timeout(cond, rel);
+ native_cond_timedwait(cond, mutex, &ts);
+}
+
static struct timespec
native_cond_timeout(rb_nativethread_cond_t *cond, struct timespec timeout_rel)
{
@@ -516,7 +524,6 @@ native_cond_timeout(rb_nativethread_cond_t *cond, struct timespec timeout_rel)
return timeout;
}
-#endif
void
rb_native_cond_initialize(rb_nativethread_cond_t *cond)
@@ -692,11 +699,11 @@ timer_thread_func(void *dummy)
rb_vm_t *vm = GET_VM();
thread_debug("timer_thread\n");
rb_w32_set_thread_description(GetCurrentThread(), L"ruby-timer-thread");
- while (WaitForSingleObject(timer_thread.lock, TIME_QUANTUM_USEC/1000) ==
- WAIT_TIMEOUT) {
- timer_thread_function();
+ while (WaitForSingleObject(timer_thread.lock,
+ TIME_QUANTUM_USEC/1000) == WAIT_TIMEOUT) {
+ vm->clock++;
ruby_sigchld_handler(vm); /* probably no-op */
- rb_threadptr_check_signal(vm->main_thread);
+ rb_threadptr_check_signal(vm->ractor.main_thread);
}
thread_debug("timer killed\n");
return 0;
diff --git a/thread_win32.h b/thread_win32.h
index 1a46929ddc..f0294ee7f6 100644
--- a/thread_win32.h
+++ b/thread_win32.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_THREAD_WIN32_H
+#define RUBY_THREAD_WIN32_H
/**********************************************************************
thread_win32.h -
@@ -9,13 +11,13 @@
**********************************************************************/
/* interface */
-#ifndef RUBY_THREAD_WIN32_H
-#define RUBY_THREAD_WIN32_H
# ifdef __CYGWIN__
# undef _WIN32
# endif
+#define USE_VM_CLOCK 1
+
WINBASEAPI BOOL WINAPI
TryEnterCriticalSection(IN OUT LPCRITICAL_SECTION lpCriticalSection);
@@ -32,7 +34,28 @@ typedef struct rb_global_vm_lock_struct {
HANDLE lock;
} rb_global_vm_lock_t;
-void rb_native_mutex_destroy(rb_nativethread_lock_t *lock);
+typedef DWORD native_tls_key_t; // TLS index
+
+static inline void *
+native_tls_get(native_tls_key_t key)
+{
+ void *ptr = TlsGetValue(key);
+ if (UNLIKELY(ptr == NULL)) {
+ rb_bug("TlsGetValue() returns NULL");
+ }
+ return ptr;
+}
+
+static inline void
+native_tls_set(native_tls_key_t key, void *ptr)
+{
+ if (UNLIKELY(TlsSetValue(key, ptr) == 0)) {
+ rb_bug("TlsSetValue() error");
+ }
+}
+
+RUBY_SYMBOL_EXPORT_BEGIN
+RUBY_EXTERN native_tls_key_t ruby_current_ec_key;
+RUBY_SYMBOL_EXPORT_END
#endif /* RUBY_THREAD_WIN32_H */
-
diff --git a/time.c b/time.c
index e1d91cad75..d8f3b6a4aa 100644
--- a/time.c
+++ b/time.c
@@ -11,34 +11,44 @@
#define _DEFAULT_SOURCE
#define _BSD_SOURCE
-#include "ruby/encoding.h"
-#include "internal.h"
-#include <sys/types.h>
-#include <time.h>
+#include "ruby/internal/config.h"
+
#include <errno.h>
+#include <float.h>
+#include <math.h>
+#include <time.h>
+#include <sys/types.h>
#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+# include <unistd.h>
#endif
-#include <float.h>
-#include <math.h>
-
#ifdef HAVE_STRINGS_H
-#include <strings.h>
+# include <strings.h>
#endif
#if defined(HAVE_SYS_TIME_H)
-#include <sys/time.h>
+# include <sys/time.h>
#endif
-#include "timev.h"
#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/compar.h"
+#include "internal/numeric.h"
+#include "internal/rational.h"
+#include "internal/string.h"
+#include "internal/time.h"
+#include "internal/variable.h"
+#include "ruby/encoding.h"
+#include "timev.h"
static ID id_submicro, id_nano_num, id_nano_den, id_offset, id_zone;
static ID id_nanosecond, id_microsecond, id_millisecond, id_nsec, id_usec;
static ID id_local_to_utc, id_utc_to_local, id_find_timezone;
static ID id_year, id_mon, id_mday, id_hour, id_min, id_sec, id_isdst;
+static VALUE str_utc, str_empty;
+
#define id_quo idQuo
#define id_div idDiv
#define id_divmod idDivmod
@@ -502,47 +512,37 @@ num_exact(VALUE v)
{
VALUE tmp;
- if (NIL_P(v)) {
- rb_raise(rb_eTypeError, "can't convert nil into an exact number");
- }
- else if (RB_INTEGER_TYPE_P(v)) {
+ switch (TYPE(v)) {
+ case T_FIXNUM:
+ case T_BIGNUM:
return v;
- }
- else if (RB_TYPE_P(v, T_RATIONAL)) {
- goto rational;
- }
- else if (RB_TYPE_P(v, T_STRING)) {
- goto typeerror;
- }
- else {
+
+ case T_RATIONAL:
+ return rb_rational_canonicalize(v);
+
+ default:
if ((tmp = rb_check_funcall(v, idTo_r, 0, NULL)) != Qundef) {
/* test to_int method availability to reject non-Numeric
* objects such as String, Time, etc which have to_r method. */
- if (!rb_respond_to(v, idTo_int)) goto typeerror;
+ if (!rb_respond_to(v, idTo_int)) {
+ /* FALLTHROUGH */
+ }
+ else if (RB_INTEGER_TYPE_P(tmp)) {
+ return tmp;
+ }
+ else if (RB_TYPE_P(tmp, T_RATIONAL)) {
+ return rb_rational_canonicalize(tmp);
+ }
}
else if (!NIL_P(tmp = rb_check_to_int(v))) {
return tmp;
}
- else {
- goto typeerror;
- }
- }
- if (RB_INTEGER_TYPE_P(tmp)) {
- v = tmp;
- }
- else if (RB_TYPE_P(tmp, T_RATIONAL)) {
- v = tmp;
- rational:
- if (RRATIONAL(v)->den == INT2FIX(1))
- v = RRATIONAL(v)->num;
- }
- else {
- typeerror:
+ case T_NIL:
+ case T_STRING:
rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into an exact number",
rb_obj_class(v));
}
- return v;
}
/* time_t */
@@ -646,7 +646,7 @@ VALUE rb_cTime;
static VALUE rb_cTimeTM;
static int obj2int(VALUE obj);
-static uint32_t obj2ubits(VALUE obj, size_t bits);
+static uint32_t obj2ubits(VALUE obj, unsigned int bits);
static VALUE obj2vint(VALUE obj);
static uint32_t month_arg(VALUE arg);
static VALUE validate_utc_offset(VALUE utc_offset);
@@ -672,6 +672,14 @@ static int leap_year_p(long y);
static VALUE tm_from_time(VALUE klass, VALUE time);
bool ruby_tz_uptodate_p;
+void ruby_reset_leap_second_info(void);
+
+void
+ruby_reset_timezone(void)
+{
+ ruby_tz_uptodate_p = false;
+ ruby_reset_leap_second_info();
+}
static void
update_tz(void)
@@ -1015,7 +1023,7 @@ gmtimew_noleapsecond(wideval_t timew, struct vtm *vtm)
}
vtm->utc_offset = INT2FIX(0);
- vtm->zone = rb_fstring_lit("UTC");
+ vtm->zone = str_utc;
}
static struct tm *
@@ -1295,7 +1303,7 @@ gmtimew(wideval_t timew, struct vtm *result)
static struct tm *localtime_with_gmtoff_zone(const time_t *t, struct tm *result, long *gmtoff, VALUE *zone);
/*
- * The idea is borrowed from Perl:
+ * The idea, extrapolate localtime() function, is borrowed from Perl:
* http://web.archive.org/web/20080211114141/http://use.perl.org/articles/08/02/07/197204.shtml
*
* compat_common_month_table is generated by the following program.
@@ -1447,7 +1455,7 @@ guess_local_offset(struct vtm *vtm_utc, int *isdst_ret, VALUE *zone_ret)
timev = w2v(rb_time_unmagnify(timegmw(&vtm2)));
t = NUM2TIMET(timev);
- zone = rb_fstring_lit("UTC");
+ zone = str_utc;
if (localtime_with_gmtoff_zone(&t, &tm, &gmtoff, &zone)) {
if (isdst_ret)
*isdst_ret = tm.tm_isdst;
@@ -1757,6 +1765,14 @@ static VALUE time_get_tm(VALUE, struct time_object *);
time_get_tm((time), (tobj)); \
} \
} while (0)
+#define MAKE_TM_ENSURE(time, tobj, cond) \
+ do { \
+ MAKE_TM(time, tobj); \
+ if (!(cond)) { \
+ VALUE zone = (tobj)->vtm.zone; \
+ if (!NIL_P(zone)) zone_localtime(zone, (time)); \
+ } \
+ } while (0)
static void
time_mark(void *ptr)
@@ -1959,10 +1975,8 @@ vtm_add_offset(struct vtm *vtm, VALUE off, int sign)
vtm->subsecx = subv(vtm->subsecx, INT2FIX(TIME_SCALE));
sec += 1;
}
- goto not_zero_sec;
}
if (sec) {
- not_zero_sec:
/* If sec + subsec == 0, don't change vtm->sec.
* It may be 60 which is a leap second. */
sec += vtm->sec;
@@ -2071,10 +2085,9 @@ utc_offset_arg(VALUE arg)
VALUE tmp;
if (!NIL_P(tmp = rb_check_string_type(arg))) {
int n = 0;
- const char *s = RSTRING_PTR(tmp), *min = NULL, *sec = NULL;
+ char *s = RSTRING_PTR(tmp);
if (!rb_enc_str_asciicompat_p(tmp)) {
- invalid_utc_offset:
- return Qnil;
+ goto invalid_utc_offset;
}
switch (RSTRING_LEN(tmp)) {
case 1:
@@ -2100,38 +2113,24 @@ utc_offset_arg(VALUE arg)
if (STRNCASECMP("UTC", s, 3) == 0) {
return UTC_ZONE;
}
- break; /* +HH */
- case 5: /* +HHMM */
- min = s+3;
- break;
- case 6: /* +HH:MM */
- min = s+4;
- break;
- case 7: /* +HHMMSS */
- sec = s+5;
- min = s+3;
- break;
- case 9: /* +HH:MM:SS */
- sec = s+7;
- min = s+4;
- break;
+ goto invalid_utc_offset;
+ case 9:
+ if (s[6] != ':') goto invalid_utc_offset;
+ if (!ISDIGIT(s[7]) || !ISDIGIT(s[8])) goto invalid_utc_offset;
+ n += (s[7] * 10 + s[8] - '0' * 11);
+ /* fall through */
+ case 6:
+ if (s[0] != '+' && s[0] != '-') goto invalid_utc_offset;
+ if (!ISDIGIT(s[1]) || !ISDIGIT(s[2])) goto invalid_utc_offset;
+ if (s[3] != ':') goto invalid_utc_offset;
+ if (!ISDIGIT(s[4]) || !ISDIGIT(s[5])) goto invalid_utc_offset;
+ if (s[4] > '5') goto invalid_utc_offset;
+ break;
default:
goto invalid_utc_offset;
}
- if (sec) {
- if (sec == s+7 && *(sec-1) != ':') goto invalid_utc_offset;
- if (!ISDIGIT(sec[0]) || !ISDIGIT(sec[1])) goto invalid_utc_offset;
- n += (sec[0] * 10 + sec[1] - '0' * 11);
- }
- if (min) {
- if (min == s+4 && *(min-1) != ':') goto invalid_utc_offset;
- if (!ISDIGIT(min[0]) || !ISDIGIT(min[1])) goto invalid_utc_offset;
- if (min[0] > '5') goto invalid_utc_offset;
- n += (min[0] * 10 + min[1] - '0' * 11) * 60;
- }
- if (s[0] != '+' && s[0] != '-') goto invalid_utc_offset;
- if (!ISDIGIT(s[1]) || !ISDIGIT(s[2])) goto invalid_utc_offset;
n += (s[1] * 10 + s[2] - '0' * 11) * 3600;
+ n += (s[4] * 10 + s[5] - '0' * 11) * 60;
if (s[0] == '-')
n = -n;
return INT2FIX(n);
@@ -2139,6 +2138,8 @@ utc_offset_arg(VALUE arg)
else {
return num_exact(arg);
}
+ invalid_utc_offset:
+ return Qnil;
}
static void
@@ -2305,7 +2306,7 @@ time_init_1(int argc, VALUE *argv, VALUE time)
vtm.wday = VTM_WDAY_INITVAL;
vtm.yday = 0;
- vtm.zone = rb_fstring_lit("");
+ vtm.zone = str_empty;
/* year mon mday hour min sec off */
rb_scan_args(argc, argv, "16", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6]);
@@ -2401,12 +2402,12 @@ time_init_1(int argc, VALUE *argv, VALUE time)
* It is initialized to the current system time if no argument is given.
*
* *Note:* The new object will use the resolution available on your
- * system clock, and may include fractional seconds.
+ * system clock, and may include subsecond.
*
* If one or more arguments are specified, the time is initialized to the
* specified time.
*
- * +sec+ may have fraction if it is a rational.
+ * +sec+ may have subsecond if it is a rational.
*
* +tz+ specifies the timezone.
* It can be an offset from UTC, given either as a string such as "+09:00"
@@ -2415,11 +2416,11 @@ time_init_1(int argc, VALUE *argv, VALUE time)
* Or it can be a timezone object,
* see {Timezone argument}[#class-Time-label-Timezone+argument] for details.
*
- * a = Time.new #=> 2007-11-19 07:50:02 -0600
- * b = Time.new #=> 2007-11-19 07:50:02 -0600
+ * a = Time.new #=> 2020-07-21 01:27:44.917547285 +0900
+ * b = Time.new #=> 2020-07-21 01:27:44.917617713 +0900
* a == b #=> false
- * "%.6f" % a.to_f #=> "1195480202.282373"
- * "%.6f" % b.to_f #=> "1195480202.283415"
+ * "%.6f" % a.to_f #=> "1595262464.917547"
+ * "%.6f" % b.to_f #=> "1595262464.917618"
*
* Time.new(2008,6,21, 13,30,0, "+09:00") #=> 2008-06-21 13:30:00 +0900
*
@@ -2802,10 +2803,12 @@ get_scale(VALUE unit)
* +seconds+ and +microseconds_with_frac+ since the Epoch.
* +seconds_with_frac+ and +microseconds_with_frac+
* can be an Integer, Float, Rational, or other Numeric.
- * non-portable feature allows the offset to be negative on some systems.
*
* If +in+ argument is given, the result is in that timezone or UTC offset, or
* if a numeric argument is given, the result is in local time.
+ * The +in+ argument accepts the same types of arguments as +tz+ argument of
+ * Time.new: string, number of seconds, or a timezone object.
+ *
*
* Time.at(0) #=> 1969-12-31 18:00:00 -0600
* Time.at(Time.at(0)) #=> 1969-12-31 18:00:00 -0600
@@ -2814,6 +2817,15 @@ get_scale(VALUE unit)
* Time.at(946684800.2).usec #=> 200000
* Time.at(946684800, 123456.789).nsec #=> 123456789
* Time.at(946684800, 123456789, :nsec).nsec #=> 123456789
+ *
+ * Time.at(1582721899, in: "+09:00") #=> 2020-02-26 21:58:19 +0900
+ * Time.at(1582721899, in: "UTC") #=> 2020-02-26 12:58:19 UTC
+ * Time.at(1582721899, in: "C") #=> 2020-02-26 13:58:19 +0300
+ * Time.at(1582721899, in: 32400) #=> 2020-02-26 21:58:19 +0900
+ *
+ * require 'tzinfo'
+ * Time.at(1582721899, in: TZInfo::Timezone.get('Europe/Kiev'))
+ * #=> 2020-02-26 14:58:19 +0200
*/
static VALUE
@@ -2867,20 +2879,16 @@ obj2int(VALUE obj)
return NUM2INT(obj);
}
+/* bits should be 0 <= x <= 31 */
static uint32_t
-obj2ubits(VALUE obj, size_t bits)
+obj2ubits(VALUE obj, unsigned int bits)
{
- static const uint32_t u32max = (uint32_t)-1;
- const uint32_t usable_mask = ~(u32max << bits);
- uint32_t rv;
- int tmp = obj2int(obj);
+ const unsigned int usable_mask = (1U << bits) - 1;
+ unsigned int rv = (unsigned int)obj2int(obj);
- if (tmp < 0)
- rb_raise(rb_eArgError, "argument out of range");
- rv = tmp;
if ((rv & usable_mask) != rv)
rb_raise(rb_eArgError, "argument out of range");
- return rv;
+ return (uint32_t)rv;
}
static VALUE
@@ -2927,6 +2935,10 @@ month_arg(VALUE arg)
{
int i, mon;
+ if (FIXNUM_P(arg)) {
+ return obj2ubits(arg, 4);
+ }
+
VALUE s = rb_check_string_type(arg);
if (!NIL_P(s) && RSTRING_LEN(s) > 0) {
mon = 0;
@@ -3000,7 +3012,7 @@ time_arg(int argc, const VALUE *argv, struct vtm *vtm)
vtm->wday = 0;
vtm->yday = 0;
vtm->isdst = 0;
- vtm->zone = rb_fstring_lit("");
+ vtm->zone = str_empty;
if (argc == 10) {
v[0] = argv[5];
@@ -3260,8 +3272,8 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp)
status = 1;
while (guess_lo + 1 < guess_hi) {
+ binsearch:
if (status == 0) {
- binsearch:
guess = guess_lo / 2 + guess_hi / 2;
if (guess <= guess_lo)
guess = guess_lo + 1;
@@ -3290,6 +3302,7 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp)
if (guess <= guess_lo) fprintf(stderr, "too small guess: %ld <= %ld\n", guess, guess_lo);
if (guess_hi <= guess) fprintf(stderr, "too big guess: %ld <= %ld\n", guess_hi, guess);
#endif
+ status = 0;
goto binsearch;
}
}
@@ -3310,64 +3323,8 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp)
DEBUG_REPORT_GUESSRANGE;
}
else {
- found:
- if (!utc_p) {
- /* If localtime is nonmonotonic, another result may exist. */
- time_t guess2;
- if (find_dst) {
- guess2 = guess - 2 * 60 * 60;
- tm = LOCALTIME(&guess2, result);
- if (tm) {
- if (tptr->tm_hour != (tm->tm_hour + 2) % 24 ||
- tptr->tm_min != tm->tm_min ||
- tptr->tm_sec != tm->tm_sec) {
- guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
- (tm->tm_min - tptr->tm_min) * 60 +
- (tm->tm_sec - tptr->tm_sec);
- if (tptr->tm_mday != tm->tm_mday)
- guess2 += 24 * 60 * 60;
- if (guess != guess2) {
- tm = LOCALTIME(&guess2, result);
- if (tm && tmcmp(tptr, tm) == 0) {
- if (guess < guess2)
- *tp = guess;
- else
- *tp = guess2;
- return NULL;
- }
- }
- }
- }
- }
- else {
- guess2 = guess + 2 * 60 * 60;
- tm = LOCALTIME(&guess2, result);
- if (tm) {
- if ((tptr->tm_hour + 2) % 24 != tm->tm_hour ||
- tptr->tm_min != tm->tm_min ||
- tptr->tm_sec != tm->tm_sec) {
- guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
- (tm->tm_min - tptr->tm_min) * 60 +
- (tm->tm_sec - tptr->tm_sec);
- if (tptr->tm_mday != tm->tm_mday)
- guess2 -= 24 * 60 * 60;
- if (guess != guess2) {
- tm = LOCALTIME(&guess2, result);
- if (tm && tmcmp(tptr, tm) == 0) {
- if (guess < guess2)
- *tp = guess2;
- else
- *tp = guess;
- return NULL;
- }
- }
- }
- }
- }
- }
- *tp = guess;
- return NULL;
- }
+ goto found;
+ }
}
/* Given argument has no corresponding time_t. Let's extrapolate. */
@@ -3396,6 +3353,64 @@ find_time_t(struct tm *tptr, int utc_p, time_t *tp)
return NULL;
+ found:
+ if (!utc_p) {
+ /* If localtime is nonmonotonic, another result may exist. */
+ time_t guess2;
+ if (find_dst) {
+ guess2 = guess - 2 * 60 * 60;
+ tm = LOCALTIME(&guess2, result);
+ if (tm) {
+ if (tptr->tm_hour != (tm->tm_hour + 2) % 24 ||
+ tptr->tm_min != tm->tm_min ||
+ tptr->tm_sec != tm->tm_sec) {
+ guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
+ (tm->tm_min - tptr->tm_min) * 60 +
+ (tm->tm_sec - tptr->tm_sec);
+ if (tptr->tm_mday != tm->tm_mday)
+ guess2 += 24 * 60 * 60;
+ if (guess != guess2) {
+ tm = LOCALTIME(&guess2, result);
+ if (tm && tmcmp(tptr, tm) == 0) {
+ if (guess < guess2)
+ *tp = guess;
+ else
+ *tp = guess2;
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+ else {
+ guess2 = guess + 2 * 60 * 60;
+ tm = LOCALTIME(&guess2, result);
+ if (tm) {
+ if ((tptr->tm_hour + 2) % 24 != tm->tm_hour ||
+ tptr->tm_min != tm->tm_min ||
+ tptr->tm_sec != tm->tm_sec) {
+ guess2 -= (tm->tm_hour - tptr->tm_hour) * 60 * 60 +
+ (tm->tm_min - tptr->tm_min) * 60 +
+ (tm->tm_sec - tptr->tm_sec);
+ if (tptr->tm_mday != tm->tm_mday)
+ guess2 -= 24 * 60 * 60;
+ if (guess != guess2) {
+ tm = LOCALTIME(&guess2, result);
+ if (tm && tmcmp(tptr, tm) == 0) {
+ if (guess < guess2)
+ *tp = guess2;
+ else
+ *tp = guess;
+ return NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+ *tp = guess;
+ return NULL;
+
out_of_range:
return "time out of range";
@@ -3503,7 +3518,7 @@ time_s_mkutc(int argc, VALUE *argv, VALUE klass)
* Time.mktime(year, month, day, hour, min, sec, usec_with_frac) -> time
* Time.mktime(sec, min, hour, day, month, year, dummy, dummy, isdst, dummy) -> time
*
- * Same as Time::gm, but interprets the values in the
+ * Same as Time.utc, but interprets the values in the
* local time zone.
*
* Time.local(2000,"jan",1,20,15,1) #=> 2000-01-01 20:15:01 -0600
@@ -3526,9 +3541,10 @@ time_s_mktime(int argc, VALUE *argv, VALUE klass)
* Returns the value of _time_ as an integer number of seconds
* since the Epoch.
*
- * t = Time.now
- * "%10.5f" % t.to_f #=> "1270968656.89607"
- * t.to_i #=> 1270968656
+ * If _time_ contains subsecond, they are truncated.
+ *
+ * t = Time.now #=> 2020-07-21 01:41:29.746012609 +0900
+ * t.to_i #=> 1595263289
*/
static VALUE
@@ -3546,13 +3562,22 @@ time_to_i(VALUE time)
*
* Returns the value of _time_ as a floating point number of
* seconds since the Epoch.
+ * The return value approximate the exact value in the Time object
+ * because floating point numbers cannot represent all rational numbers
+ * exactly.
*
- * t = Time.now
- * "%10.5f" % t.to_f #=> "1270968744.77658"
- * t.to_i #=> 1270968744
+ * t = Time.now #=> 2020-07-20 22:00:29.38740268 +0900
+ * t.to_f #=> 1595250029.3874028
+ * t.to_i #=> 1595250029
*
* Note that IEEE 754 double is not accurate enough to represent
* the exact number of nanoseconds since the Epoch.
+ * (IEEE 754 double has 53bit mantissa.
+ * So it can represent exact number of nanoseconds only in
+ * `2 ** 53 / 1_000_000_000 / 60 / 60 / 24 = 104.2` days.)
+ * When Ruby uses a nanosecond-resolution clock function,
+ * such as +clock_gettime+ of POSIX, to obtain the current time,
+ * Time#to_f can lost information of a Time object created with +Time.now+.
*/
static VALUE
@@ -3571,12 +3596,11 @@ time_to_f(VALUE time)
* Returns the value of _time_ as a rational number of seconds
* since the Epoch.
*
- * t = Time.now
- * t.to_r #=> (1270968792716287611/1000000000)
+ * t = Time.now #=> 2020-07-20 22:03:45.212167333 +0900
+ * t.to_r #=> (1595250225212167333/1000000000)
*
- * This methods is intended to be used to get an accurate value
- * representing the nanoseconds since the Epoch. You can use this method
- * to convert _time_ to another Epoch.
+ * This method is intended to be used to get an accurate value
+ * representing the seconds (including subsecond) since the Epoch.
*/
static VALUE
@@ -3598,11 +3622,19 @@ time_to_r(VALUE time)
* time.usec -> int
* time.tv_usec -> int
*
- * Returns the number of microseconds for _time_.
+ * Returns the number of microseconds for the subsecond part of _time_.
+ * The result is a non-negative integer less than 10**6.
+ *
+ * t = Time.now #=> 2020-07-20 22:05:58.459785953 +0900
+ * t.usec #=> 459785
+ *
+ * If _time_ has fraction of microsecond (such as nanoseconds),
+ * it is truncated.
*
- * t = Time.now #=> 2007-11-19 08:03:26 -0600
- * "%10.6f" % t.to_f #=> "1195481006.775195"
- * t.usec #=> 775195
+ * t = Time.new(2000,1,1,0,0,0.666_777_888_999r)
+ * t.usec #=> 666777
+ *
+ * Time#subsec can be used to obtain the subsecond part exactly.
*/
static VALUE
@@ -3623,17 +3655,19 @@ time_usec(VALUE time)
* time.nsec -> int
* time.tv_nsec -> int
*
- * Returns the number of nanoseconds for _time_.
+ * Returns the number of nanoseconds for the subsecond part of _time_.
+ * The result is a non-negative integer less than 10**9.
*
- * t = Time.now #=> 2007-11-17 15:18:03 +0900
- * "%10.9f" % t.to_f #=> "1195280283.536151409"
- * t.nsec #=> 536151406
+ * t = Time.now #=> 2020-07-20 22:07:10.963933942 +0900
+ * t.nsec #=> 963933942
*
- * The lowest digits of #to_f and #nsec are different because
- * IEEE 754 double is not accurate enough to represent
- * the exact number of nanoseconds since the Epoch.
+ * If _time_ has fraction of nanosecond (such as picoseconds),
+ * it is truncated.
+ *
+ * t = Time.new(2000,1,1,0,0,0.666_777_888_999r)
+ * t.nsec #=> 666777888
*
- * The more accurate value is returned by #nsec.
+ * Time#subsec can be used to obtain the subsecond part exactly.
*/
static VALUE
@@ -3649,19 +3683,21 @@ time_nsec(VALUE time)
* call-seq:
* time.subsec -> number
*
- * Returns the fraction for _time_.
+ * Returns the subsecond for _time_.
*
* The return value can be a rational number.
*
- * t = Time.now #=> 2009-03-26 22:33:12 +0900
- * "%10.9f" % t.to_f #=> "1238074392.940563917"
- * t.subsec #=> (94056401/100000000)
+ * t = Time.now #=> 2020-07-20 15:40:26.867462289 +0900
+ * t.subsec #=> (867462289/1000000000)
*
- * The lowest digits of #to_f and #subsec are different because
- * IEEE 754 double is not accurate enough to represent
- * the rational number.
+ * t = Time.now #=> 2020-07-20 15:40:50.313828595 +0900
+ * t.subsec #=> (62765719/200000000)
+ *
+ * t = Time.new(2000,1,1,2,3,4) #=> 2000-01-01 02:03:04 +0900
+ * t.subsec #=> 0
+ *
+ * Time.new(2000,1,1,0,0,1/3r,"UTC").subsec #=> (1/3)
*
- * The more accurate value is returned by #subsec.
*/
static VALUE
@@ -3677,9 +3713,9 @@ time_subsec(VALUE time)
* call-seq:
* time <=> other_time -> -1, 0, +1, or nil
*
- * Comparison---Compares +time+ with +other_time+.
+ * Compares +time+ with +other_time+.
*
- * -1, 0, +1 or nil depending on whether +time+ is less than, equal to, or
+ * -1, 0, +1 or nil depending on whether +time+ is less than, equal to, or
* greater than +other_time+.
*
* +nil+ is returned if the two values are incomparable.
@@ -3722,7 +3758,7 @@ time_cmp(VALUE time1, VALUE time2)
* time.eql?(other_time)
*
* Returns +true+ if _time_ and +other_time+ are
- * both Time objects with the same seconds and fractional seconds.
+ * both Time objects with the same seconds (including subsecond) from the Epoch.
*/
static VALUE
@@ -3924,7 +3960,7 @@ time_gmtime(VALUE time)
time_modify(time);
}
- vtm.zone = rb_fstring_lit("UTC");
+ vtm.zone = str_utc;
GMTIMEW(tobj->timew, &vtm);
tobj->vtm = vtm;
@@ -4106,7 +4142,7 @@ time_to_s(VALUE time)
* time.inspect -> string
*
* Returns a detailed string representing _time_. Unlike to_s,
- * preserves nanoseconds in the representation for easier debugging.
+ * preserves subsecond in the representation for easier debugging.
*
* t = Time.now
* t.inspect #=> "2012-11-10 18:16:12.261257655 +0100"
@@ -4129,7 +4165,7 @@ time_inspect(VALUE time)
}
else if (FIXNUM_P(subsec) && FIX2LONG(subsec) < TIME_SCALE) {
long len;
- str = rb_enc_sprintf(rb_usascii_encoding(), "%"PRIsVALUE".%09ld", str, FIX2LONG(subsec));
+ rb_str_catf(str, ".%09ld", FIX2LONG(subsec));
for (len=RSTRING_LEN(str); RSTRING_PTR(str)[len-1] == '0' && len > 0; len--)
;
rb_str_resize(str, len);
@@ -4175,11 +4211,11 @@ time_add(const struct time_object *tobj, VALUE torig, VALUE offset, int sign)
* call-seq:
* time + numeric -> time
*
- * Addition --- Adds some number of seconds (possibly fractional) to
+ * Adds some number of seconds (possibly including subsecond) to
* _time_ and returns that value as a new Time object.
*
- * t = Time.now #=> 2007-11-19 08:22:21 -0600
- * t + (60 * 60 * 24) #=> 2007-11-20 08:22:21 -0600
+ * t = Time.now #=> 2020-07-20 22:14:43.170490982 +0900
+ * t + (60 * 60 * 24) #=> 2020-07-21 22:14:43.170490982 +0900
*/
static VALUE
@@ -4199,14 +4235,14 @@ time_plus(VALUE time1, VALUE time2)
* time - other_time -> float
* time - numeric -> time
*
- * Difference --- Returns a difference in seconds as a Float
+ * Returns a difference in seconds as a Float
* between _time_ and +other_time+, or subtracts the given number
* of seconds in +numeric+ from _time_.
*
- * t = Time.now #=> 2007-11-19 08:23:10 -0600
- * t2 = t + 2592000 #=> 2007-12-19 08:23:10 -0600
+ * t = Time.now #=> 2020-07-20 22:15:49.302766336 +0900
+ * t2 = t + 2592000 #=> 2020-08-19 22:15:49.302766336 +0900
* t2 - t #=> 2592000.0
- * t2 - 2592000 #=> 2007-11-19 08:23:10 -0600
+ * t2 - 2592000 #=> 2020-07-20 22:15:49.302766336 +0900
*/
static VALUE
@@ -4224,40 +4260,6 @@ time_minus(VALUE time1, VALUE time2)
return time_add(tobj, time1, time2, -1);
}
-/*
- * call-seq:
- * time.succ -> new_time
- *
- * Returns a new Time object, one second later than _time_.
- * Time#succ is obsolete since 1.9.2 for time is not a discrete value.
- *
- * t = Time.now #=> 2007-11-19 08:23:57 -0600
- * t.succ #=> 2007-11-19 08:23:58 -0600
- *
- * Use instead <code>time + 1</code>
- *
- * t + 1 #=> 2007-11-19 08:23:58 -0600
- */
-
-VALUE
-rb_time_succ(VALUE time)
-{
- struct time_object *tobj;
- struct time_object *tobj2;
-
- rb_warn("Time#succ is obsolete; use time + 1");
- GetTimeval(time, tobj);
- time = time_new_timew(rb_cTime, wadd(tobj->timew, WINT2FIXWV(TIME_SCALE)));
- GetTimeval(time, tobj2);
- TZMODE_COPY(tobj2, tobj);
- if (TZMODE_LOCALTIME_P(tobj2) && maybe_tzobj_p(tobj2->vtm.zone)) {
- zone_localtime(tobj2->vtm.zone, time);
- }
- return time;
-}
-
-#define time_succ rb_time_succ
-
static VALUE
ndigits_denominator(VALUE ndigits)
{
@@ -4277,31 +4279,29 @@ ndigits_denominator(VALUE ndigits)
* call-seq:
* time.round([ndigits]) -> new_time
*
- * Rounds sub seconds to a given precision in decimal digits (0 digits by default).
+ * Rounds subsecond to a given precision in decimal digits (0 digits by default).
* It returns a new Time object.
* +ndigits+ should be zero or a positive integer.
*
- * require 'time'
- *
* t = Time.utc(2010,3,30, 5,43,25.123456789r)
- * t.iso8601(10) #=> "2010-03-30T05:43:25.1234567890Z"
- * t.round.iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z"
- * t.round(0).iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z"
- * t.round(1).iso8601(10) #=> "2010-03-30T05:43:25.1000000000Z"
- * t.round(2).iso8601(10) #=> "2010-03-30T05:43:25.1200000000Z"
- * t.round(3).iso8601(10) #=> "2010-03-30T05:43:25.1230000000Z"
- * t.round(4).iso8601(10) #=> "2010-03-30T05:43:25.1235000000Z"
+ * t #=> 2010-03-30 05:43:25.123456789 UTC
+ * t.round #=> 2010-03-30 05:43:25 UTC
+ * t.round(0) #=> 2010-03-30 05:43:25 UTC
+ * t.round(1) #=> 2010-03-30 05:43:25.1 UTC
+ * t.round(2) #=> 2010-03-30 05:43:25.12 UTC
+ * t.round(3) #=> 2010-03-30 05:43:25.123 UTC
+ * t.round(4) #=> 2010-03-30 05:43:25.1235 UTC
*
* t = Time.utc(1999,12,31, 23,59,59)
- * (t + 0.4).round.iso8601(3) #=> "1999-12-31T23:59:59.000Z"
- * (t + 0.49).round.iso8601(3) #=> "1999-12-31T23:59:59.000Z"
- * (t + 0.5).round.iso8601(3) #=> "2000-01-01T00:00:00.000Z"
- * (t + 1.4).round.iso8601(3) #=> "2000-01-01T00:00:00.000Z"
- * (t + 1.49).round.iso8601(3) #=> "2000-01-01T00:00:00.000Z"
- * (t + 1.5).round.iso8601(3) #=> "2000-01-01T00:00:01.000Z"
- *
- * t = Time.utc(1999,12,31, 23,59,59)
- * (t + 0.123456789).round(4).iso8601(6) #=> "1999-12-31T23:59:59.123500Z"
+ * (t + 0.4).round #=> 1999-12-31 23:59:59 UTC
+ * (t + 0.49).round #=> 1999-12-31 23:59:59 UTC
+ * (t + 0.5).round #=> 2000-01-01 00:00:00 UTC
+ * (t + 1.4).round #=> 2000-01-01 00:00:00 UTC
+ * (t + 1.49).round #=> 2000-01-01 00:00:00 UTC
+ * (t + 1.5).round #=> 2000-01-01 00:00:01 UTC
+ *
+ * t = Time.utc(1999,12,31, 23,59,59) #=> 1999-12-31 23:59:59 UTC
+ * (t + 0.123456789).round(4).iso8601(6) #=> 1999-12-31 23:59:59.1235 UTC
*/
static VALUE
@@ -4329,29 +4329,27 @@ time_round(int argc, VALUE *argv, VALUE time)
* call-seq:
* time.floor([ndigits]) -> new_time
*
- * Floors sub seconds to a given precision in decimal digits (0 digits by default).
+ * Floors subsecond to a given precision in decimal digits (0 digits by default).
* It returns a new Time object.
* +ndigits+ should be zero or a positive integer.
*
- * require 'time'
- *
* t = Time.utc(2010,3,30, 5,43,25.123456789r)
- * t.iso8601(10) #=> "2010-03-30T05:43:25.1234567890Z"
- * t.floor.iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z"
- * t.floor(0).iso8601(10) #=> "2010-03-30T05:43:25.0000000000Z"
- * t.floor(1).iso8601(10) #=> "2010-03-30T05:43:25.1000000000Z"
- * t.floor(2).iso8601(10) #=> "2010-03-30T05:43:25.1200000000Z"
- * t.floor(3).iso8601(10) #=> "2010-03-30T05:43:25.1230000000Z"
- * t.floor(4).iso8601(10) #=> "2010-03-30T05:43:25.1234000000Z"
+ * t #=> 2010-03-30 05:43:25.123456789 UTC
+ * t.floor #=> 2010-03-30 05:43:25 UTC
+ * t.floor(0) #=> 2010-03-30 05:43:25 UTC
+ * t.floor(1) #=> 2010-03-30 05:43:25.1 UTC
+ * t.floor(2) #=> 2010-03-30 05:43:25.12 UTC
+ * t.floor(3) #=> 2010-03-30 05:43:25.123 UTC
+ * t.floor(4) #=> 2010-03-30 05:43:25.1234 UTC
*
* t = Time.utc(1999,12,31, 23,59,59)
- * (t + 0.4).floor.iso8601(3) #=> "1999-12-31T23:59:59.000Z"
- * (t + 0.9).floor.iso8601(3) #=> "1999-12-31T23:59:59.000Z"
- * (t + 1.4).floor.iso8601(3) #=> "2000-01-01T00:00:00.000Z"
- * (t + 1.9).floor.iso8601(3) #=> "2000-01-01T00:00:00.000Z"
+ * (t + 0.4).floor #=> 1999-12-31 23:59:59 UTC
+ * (t + 0.9).floor #=> 1999-12-31 23:59:59 UTC
+ * (t + 1.4).floor #=> 2000-01-01 00:00:00 UTC
+ * (t + 1.9).floor #=> 2000-01-01 00:00:00 UTC
*
* t = Time.utc(1999,12,31, 23,59,59)
- * (t + 0.123456789).floor(4).iso8601(6) #=> "1999-12-31T23:59:59.123400Z"
+ * (t + 0.123456789).floor(4) #=> 1999-12-31 23:59:59.1234 UTC
*/
static VALUE
@@ -4376,29 +4374,27 @@ time_floor(int argc, VALUE *argv, VALUE time)
* call-seq:
* time.ceil([ndigits]) -> new_time
*
- * Ceils sub seconds to a given precision in decimal digits (0 digits by default).
+ * Ceils subsecond to a given precision in decimal digits (0 digits by default).
* It returns a new Time object.
* +ndigits+ should be zero or a positive integer.
*
- * require 'time'
- *
* t = Time.utc(2010,3,30, 5,43,25.0123456789r)
- * t.iso8601(10) #=> "2010-03-30T05:43:25.0123456789Z"
- * t.ceil.iso8601(10) #=> "2010-03-30T05:43:26.0000000000Z"
- * t.ceil(0).iso8601(10) #=> "2010-03-30T05:43:26.0000000000Z"
- * t.ceil(1).iso8601(10) #=> "2010-03-30T05:43:25.1000000000Z"
- * t.ceil(2).iso8601(10) #=> "2010-03-30T05:43:25.0200000000Z"
- * t.ceil(3).iso8601(10) #=> "2010-03-30T05:43:25.0130000000Z"
- * t.ceil(4).iso8601(10) #=> "2010-03-30T05:43:25.0124000000Z"
+ * t #=> 2010-03-30 05:43:25 123456789/10000000000 UTC
+ * t.ceil #=> 2010-03-30 05:43:26 UTC
+ * t.ceil(0) #=> 2010-03-30 05:43:26 UTC
+ * t.ceil(1) #=> 2010-03-30 05:43:25.1 UTC
+ * t.ceil(2) #=> 2010-03-30 05:43:25.02 UTC
+ * t.ceil(3) #=> 2010-03-30 05:43:25.013 UTC
+ * t.ceil(4) #=> 2010-03-30 05:43:25.0124 UTC
*
* t = Time.utc(1999,12,31, 23,59,59)
- * (t + 0.4).ceil.iso8601(3) #=> "2000-01-01T00:00:00.000Z"
- * (t + 0.9).ceil.iso8601(3) #=> "2000-01-01T00:00:00.000Z"
- * (t + 1.4).ceil.iso8601(3) #=> "2000-01-01T00:00:01.000Z"
- * (t + 1.9).ceil.iso8601(3) #=> "2000-01-01T00:00:01.000Z"
+ * (t + 0.4).ceil #=> 2000-01-01 00:00:00 UTC
+ * (t + 0.9).ceil #=> 2000-01-01 00:00:00 UTC
+ * (t + 1.4).ceil #=> 2000-01-01 00:00:01 UTC
+ * (t + 1.9).ceil #=> 2000-01-01 00:00:01 UTC
*
* t = Time.utc(1999,12,31, 23,59,59)
- * (t + 0.123456789).ceil(4).iso8601(6) #=> "1999-12-31T23:59:59.123500Z"
+ * (t + 0.123456789).ceil(4) #=> 1999-12-31 23:59:59.1235 UTC
*/
static VALUE
@@ -4416,7 +4412,10 @@ time_ceil(int argc, VALUE *argv, VALUE time)
v = w2v(rb_time_unmagnify(tobj->timew));
v = modv(v, den);
- return time_add(tobj, time, subv(den, v), 1);
+ if (!rb_equal(v, INT2FIX(0))) {
+ v = subv(den, v);
+ }
+ return time_add(tobj, time, v, 1);
}
/*
@@ -4426,7 +4425,7 @@ time_ceil(int argc, VALUE *argv, VALUE time)
* Returns the second of the minute (0..60) for _time_.
*
* *Note:* Seconds range from zero to 60 to allow the system to inject
- * leap seconds. See http://en.wikipedia.org/wiki/Leap_second for further
+ * leap seconds. See https://en.wikipedia.org/wiki/Leap_second for further
* details.
*
* t = Time.now #=> 2007-11-19 08:25:02 -0600
@@ -4488,7 +4487,7 @@ time_hour(VALUE time)
* time.day -> integer
* time.mday -> integer
*
- * Returns the day of the month (1..n) for _time_.
+ * Returns the day of the month (1..31) for _time_.
*
* t = Time.now #=> 2007-11-19 08:27:03 -0600
* t.day #=> 19
@@ -4571,11 +4570,7 @@ time_wday(VALUE time)
struct time_object *tobj;
GetTimeval(time, tobj);
- MAKE_TM(time, tobj);
- if (tobj->vtm.wday == VTM_WDAY_INITVAL) {
- VALUE zone = tobj->vtm.zone;
- if (!NIL_P(zone)) zone_localtime(zone, time);
- }
+ MAKE_TM_ENSURE(time, tobj, tobj->vtm.wday != VTM_WDAY_INITVAL);
return INT2FIX((int)tobj->vtm.wday);
}
@@ -4711,11 +4706,7 @@ time_yday(VALUE time)
struct time_object *tobj;
GetTimeval(time, tobj);
- MAKE_TM(time, tobj);
- if (tobj->vtm.yday == 0) {
- VALUE zone = tobj->vtm.zone;
- if (!NIL_P(zone)) zone_localtime(zone, time);
- }
+ MAKE_TM_ENSURE(time, tobj, tobj->vtm.yday != 0);
return INT2FIX(tobj->vtm.yday);
}
@@ -4832,7 +4823,7 @@ rb_time_utc_offset(VALUE time)
*
* See the individual methods for an explanation of the
* valid ranges of each value. The ten elements can be passed directly
- * to Time::utc or Time::local to create a
+ * to Time.utc or Time.local to create a
* new Time object.
*
* t = Time.now #=> 2007-11-19 08:36:01 -0600
@@ -4845,7 +4836,7 @@ time_to_a(VALUE time)
struct time_object *tobj;
GetTimeval(time, tobj);
- MAKE_TM(time, tobj);
+ MAKE_TM_ENSURE(time, tobj, tobj->vtm.yday != 0);
return rb_ary_new3(10,
INT2FIX(tobj->vtm.sec),
INT2FIX(tobj->vtm.min),
@@ -5087,7 +5078,7 @@ time_strftime(VALUE time, VALUE format)
VALUE tmp;
GetTimeval(time, tobj);
- MAKE_TM(time, tobj);
+ MAKE_TM_ENSURE(time, tobj, tobj->vtm.yday != 0);
StringValue(format);
if (!rb_enc_str_asciicompat_p(format)) {
rb_raise(rb_eArgError, "format should have ASCII compatible encoding");
@@ -5315,8 +5306,8 @@ time_mload(VALUE time, VALUE str)
get_attr(nano_num, {});
get_attr(nano_den, {});
get_attr(submicro, {});
- get_attr(offset, (offset = rb_rescue(validate_utc_offset, offset, NULL, Qnil)));
- get_attr(zone, (zone = rb_rescue(validate_zone_name, zone, NULL, Qnil)));
+ get_attr(offset, (offset = rb_rescue(validate_utc_offset, offset, 0, Qnil)));
+ get_attr(zone, (zone = rb_rescue(validate_zone_name, zone, 0, Qnil)));
get_attr(year, {});
#undef get_attr
@@ -5326,8 +5317,7 @@ time_mload(VALUE time, VALUE str)
StringValue(str);
buf = (unsigned char *)RSTRING_PTR(str);
if (RSTRING_LEN(str) < base_dump_size) {
- invalid_format:
- rb_raise(rb_eTypeError, "marshaled time format differ");
+ goto invalid_format;
}
p = s = 0;
@@ -5378,7 +5368,7 @@ time_mload(VALUE time, VALUE str)
vtm.utc_offset = INT2FIX(0);
vtm.yday = vtm.wday = 0;
vtm.isdst = 0;
- vtm.zone = rb_fstring_lit("");
+ vtm.zone = str_empty;
usec = (long)(s & 0xfffff);
nsec = usec * 1000;
@@ -5430,6 +5420,10 @@ end_submicro: ;
}
return time;
+
+ invalid_format:
+ rb_raise(rb_eTypeError, "marshaled time format differ");
+ UNREACHABLE_RETURN(Qundef);
}
/* :nodoc: */
@@ -5659,7 +5653,7 @@ Init_tm(VALUE outer, const char *name)
#endif
rb_define_method(tm, "initialize", tm_initialize, -1);
rb_define_method(tm, "utc", tm_to_time, 0);
- rb_alias(tm, rb_intern("to_time"), rb_intern("utc"));
+ rb_alias(tm, rb_intern_const("to_time"), rb_intern_const("utc"));
rb_define_singleton_method(tm, "from_time", tm_from_time, 1);
/* :startdoc:*/
@@ -5699,15 +5693,19 @@ rb_time_zone_abbreviation(VALUE zone, VALUE time)
/*
* Time is an abstraction of dates and times. Time is stored internally as
- * the number of seconds with fraction since the _Epoch_, January 1, 1970
- * 00:00 UTC. Also see the library module Date. The Time class treats GMT
+ * the number of seconds with subsecond since the _Epoch_,
+ * 1970-01-01 00:00:00 UTC.
+ *
+ * The Time class treats GMT
* (Greenwich Mean Time) and UTC (Coordinated Universal Time) as equivalent.
* GMT is the older way of referring to these baseline times but persists in
* the names of calls on POSIX systems.
*
- * All times may have fraction. Be aware of this fact when comparing times
+ * All times may have subsecond. Be aware of this fact when comparing times
* with each other -- times that are apparently equal when displayed may be
* different when compared.
+ * (Since Ruby 2.7.0, Time#inspect shows subsecond but
+ * Time#to_s still doesn't show subsecond.)
*
* Since Ruby 1.9.2, Time implementation uses a signed 63 bit integer,
* Bignum or Rational.
@@ -5722,9 +5720,9 @@ rb_time_zone_abbreviation(VALUE zone, VALUE time)
*
* == Creating a new Time instance
*
- * You can create a new instance of Time with Time::new. This will use the
- * current system time. Time::now is an alias for this. You can also
- * pass parts of the time to Time::new such as year, month, minute, etc. When
+ * You can create a new instance of Time with Time.new. This will use the
+ * current system time. Time.now is an alias for this. You can also
+ * pass parts of the time to Time.new such as year, month, minute, etc. When
* you want to construct a time this way you must pass at least a year. If you
* pass the year with nothing else time will default to January 1 of that year
* at 00:00:00 with the current system timezone. Here are some examples:
@@ -5742,13 +5740,13 @@ rb_time_zone_abbreviation(VALUE zone, VALUE time)
* tz = timezone("Europe/Athens") # Eastern European Time, UTC+2
* Time.new(2002, 10, 31, 2, 2, 2, tz) #=> 2002-10-31 02:02:02 +0200
*
- * You can also use Time::gm, Time::local and Time::utc to infer GMT,
+ * You can also use Time.local and Time.utc to infer
* local and UTC timezones instead of using the current system
* setting.
*
- * You can also create a new time using Time::at which takes the number of
- * seconds (or fraction of seconds) since the {Unix
- * Epoch}[http://en.wikipedia.org/wiki/Unix_time].
+ * You can also create a new time using Time.at which takes the number of
+ * seconds (with subsecond) since the {Unix
+ * Epoch}[https://en.wikipedia.org/wiki/Unix_time].
*
* Time.at(628232400) #=> 1989-11-28 00:00:00 -0500
*
@@ -5802,9 +5800,9 @@ rb_time_zone_abbreviation(VALUE zone, VALUE time)
* result also should be a Time or Time-like object (not necessary to
* be the same class). The #zone of the result is just ignored.
* Time-like argument to these methods is similar to a Time object in
- * UTC without sub-second; it has attribute readers for the parts,
+ * UTC without subsecond; it has attribute readers for the parts,
* e.g. #year, #month, and so on, and epoch time readers, #to_i. The
- * sub-second attributes are fixed as 0, and #utc_offset, #zone,
+ * subsecond attributes are fixed as 0, and #utc_offset, #zone,
* #isdst, and their aliases are same as a Time object in UTC.
* Also #to_time, #+, and #- methods are defined.
*
@@ -5829,29 +5827,31 @@ rb_time_zone_abbreviation(VALUE zone, VALUE time)
void
Init_Time(void)
{
-#undef rb_intern
-#define rb_intern(str) rb_intern_const(str)
-
- id_submicro = rb_intern("submicro");
- id_nano_num = rb_intern("nano_num");
- id_nano_den = rb_intern("nano_den");
- id_offset = rb_intern("offset");
- id_zone = rb_intern("zone");
- id_nanosecond = rb_intern("nanosecond");
- id_microsecond = rb_intern("microsecond");
- id_millisecond = rb_intern("millisecond");
- id_nsec = rb_intern("nsec");
- id_usec = rb_intern("usec");
- id_local_to_utc = rb_intern("local_to_utc");
- id_utc_to_local = rb_intern("utc_to_local");
- id_year = rb_intern("year");
- id_mon = rb_intern("mon");
- id_mday = rb_intern("mday");
- id_hour = rb_intern("hour");
- id_min = rb_intern("min");
- id_sec = rb_intern("sec");
- id_isdst = rb_intern("isdst");
- id_find_timezone = rb_intern("find_timezone");
+ id_submicro = rb_intern_const("submicro");
+ id_nano_num = rb_intern_const("nano_num");
+ id_nano_den = rb_intern_const("nano_den");
+ id_offset = rb_intern_const("offset");
+ id_zone = rb_intern_const("zone");
+ id_nanosecond = rb_intern_const("nanosecond");
+ id_microsecond = rb_intern_const("microsecond");
+ id_millisecond = rb_intern_const("millisecond");
+ id_nsec = rb_intern_const("nsec");
+ id_usec = rb_intern_const("usec");
+ id_local_to_utc = rb_intern_const("local_to_utc");
+ id_utc_to_local = rb_intern_const("utc_to_local");
+ id_year = rb_intern_const("year");
+ id_mon = rb_intern_const("mon");
+ id_mday = rb_intern_const("mday");
+ id_hour = rb_intern_const("hour");
+ id_min = rb_intern_const("min");
+ id_sec = rb_intern_const("sec");
+ id_isdst = rb_intern_const("isdst");
+ id_find_timezone = rb_intern_const("find_timezone");
+
+ str_utc = rb_fstring_lit("UTC");
+ rb_gc_register_mark_object(str_utc);
+ str_empty = rb_fstring_lit("");
+ rb_gc_register_mark_object(str_empty);
rb_cTime = rb_define_class("Time", rb_cObject);
rb_include_module(rb_cTime, rb_mComparable);
@@ -5889,7 +5889,6 @@ Init_Time(void)
rb_define_method(rb_cTime, "+", time_plus, 1);
rb_define_method(rb_cTime, "-", time_minus, 1);
- rb_define_method(rb_cTime, "succ", time_succ, 0);
rb_define_method(rb_cTime, "round", time_round, -1);
rb_define_method(rb_cTime, "floor", time_floor, -1);
rb_define_method(rb_cTime, "ceil", time_ceil, -1);
diff --git a/timev.h b/timev.h
index 6f124aa6bf..af97ed95b5 100644
--- a/timev.h
+++ b/timev.h
@@ -1,5 +1,6 @@
#ifndef RUBY_TIMEV_H
#define RUBY_TIMEV_H
+#include "ruby/ruby.h"
#if 0
struct vtm {/* dummy for TAGS */};
diff --git a/tool/actions-commit-info.sh b/tool/actions-commit-info.sh
deleted file mode 100755
index 56f857c1d9..0000000000
--- a/tool/actions-commit-info.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-set -euo pipefail
-cd $(dirname "$0")/..
-set_output () {
- echo "$1=$2"
- echo "::set-output name=$1::$2"
-}
-COMMIT_TIMESTAMP="$(git log -1 --format=%ct)"
-set_output "COMMIT_TIMESTAMP" "$COMMIT_TIMESTAMP"
-LOGS=$(TZ=UTC git log --since='0:00' --date=iso-local --format='%cd %s')
-echo "commits of today:"
-echo "$LOGS"
-COUNT=$(echo "$LOGS" | wc -l)
-# strip spaces
-COUNT=$((0 + COUNT))
-set_output "COMMIT_NUMBER_OF_DAY" "$COUNT"
-set_output "COMMIT_DATE" "$(TZ=UTC git log --since='0:00' --date=short-local --format=%cd -1)"
diff --git a/tool/bundler/rubocop_gems.rb b/tool/bundler/rubocop_gems.rb
new file mode 100644
index 0000000000..84cb226330
--- /dev/null
+++ b/tool/bundler/rubocop_gems.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "rubocop", "~> 1.7"
+
+gem "minitest"
+gem "rake"
+gem "rake-compiler"
+gem "rspec"
+gem "test-unit"
diff --git a/tool/bundler/rubocop_gems.rb.lock b/tool/bundler/rubocop_gems.rb.lock
new file mode 100644
index 0000000000..fdbbdbdcc3
--- /dev/null
+++ b/tool/bundler/rubocop_gems.rb.lock
@@ -0,0 +1,63 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ ast (2.4.2)
+ diff-lcs (1.4.4)
+ minitest (5.14.4)
+ parallel (1.21.0)
+ parser (3.0.2.0)
+ ast (~> 2.4.1)
+ power_assert (2.0.1)
+ rainbow (3.0.0)
+ rake (13.0.6)
+ rake-compiler (1.1.1)
+ rake
+ regexp_parser (2.1.1)
+ rexml (3.2.5)
+ rspec (3.10.0)
+ rspec-core (~> 3.10.0)
+ rspec-expectations (~> 3.10.0)
+ rspec-mocks (~> 3.10.0)
+ rspec-core (3.10.1)
+ rspec-support (~> 3.10.0)
+ rspec-expectations (3.10.1)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.10.0)
+ rspec-mocks (3.10.2)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.10.0)
+ rspec-support (3.10.3)
+ rubocop (1.23.0)
+ parallel (~> 1.10)
+ parser (>= 3.0.0.0)
+ rainbow (>= 2.2.2, < 4.0)
+ regexp_parser (>= 1.8, < 3.0)
+ rexml
+ rubocop-ast (>= 1.12.0, < 2.0)
+ ruby-progressbar (~> 1.7)
+ unicode-display_width (>= 1.4.0, < 3.0)
+ rubocop-ast (1.13.0)
+ parser (>= 3.0.1.1)
+ ruby-progressbar (1.11.0)
+ test-unit (3.5.1)
+ power_assert
+ unicode-display_width (2.1.0)
+
+PLATFORMS
+ arm64-darwin-20
+ arm64-darwin-21
+ universal-java-11
+ x86_64-darwin-19
+ x86_64-darwin-20
+ x86_64-linux
+
+DEPENDENCIES
+ minitest
+ rake
+ rake-compiler
+ rspec
+ rubocop (~> 1.7)
+ test-unit
+
+BUNDLED WITH
+ 2.2.33
diff --git a/tool/bundler/standard_gems.rb b/tool/bundler/standard_gems.rb
new file mode 100644
index 0000000000..1cd189742d
--- /dev/null
+++ b/tool/bundler/standard_gems.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "standard", "~> 1.0"
+
+gem "minitest"
+gem "rake"
+gem "rake-compiler"
+gem "rspec"
+gem "test-unit"
diff --git a/tool/bundler/standard_gems.rb.lock b/tool/bundler/standard_gems.rb.lock
new file mode 100644
index 0000000000..af22080659
--- /dev/null
+++ b/tool/bundler/standard_gems.rb.lock
@@ -0,0 +1,69 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ ast (2.4.2)
+ diff-lcs (1.4.4)
+ minitest (5.14.4)
+ parallel (1.21.0)
+ parser (3.0.2.0)
+ ast (~> 2.4.1)
+ power_assert (2.0.1)
+ rainbow (3.0.0)
+ rake (13.0.6)
+ rake-compiler (1.1.1)
+ rake
+ regexp_parser (2.1.1)
+ rexml (3.2.5)
+ rspec (3.10.0)
+ rspec-core (~> 3.10.0)
+ rspec-expectations (~> 3.10.0)
+ rspec-mocks (~> 3.10.0)
+ rspec-core (3.10.1)
+ rspec-support (~> 3.10.0)
+ rspec-expectations (3.10.1)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.10.0)
+ rspec-mocks (3.10.2)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.10.0)
+ rspec-support (3.10.3)
+ rubocop (1.22.3)
+ parallel (~> 1.10)
+ parser (>= 3.0.0.0)
+ rainbow (>= 2.2.2, < 4.0)
+ regexp_parser (>= 1.8, < 3.0)
+ rexml
+ rubocop-ast (>= 1.12.0, < 2.0)
+ ruby-progressbar (~> 1.7)
+ unicode-display_width (>= 1.4.0, < 3.0)
+ rubocop-ast (1.13.0)
+ parser (>= 3.0.1.1)
+ rubocop-performance (1.11.5)
+ rubocop (>= 1.7.0, < 2.0)
+ rubocop-ast (>= 0.4.0)
+ ruby-progressbar (1.11.0)
+ standard (1.4.0)
+ rubocop (= 1.22.3)
+ rubocop-performance (= 1.11.5)
+ test-unit (3.5.1)
+ power_assert
+ unicode-display_width (2.1.0)
+
+PLATFORMS
+ arm64-darwin-20
+ arm64-darwin-21
+ universal-java-11
+ x86_64-darwin-19
+ x86_64-darwin-20
+ x86_64-linux
+
+DEPENDENCIES
+ minitest
+ rake
+ rake-compiler
+ rspec
+ standard (~> 1.0)
+ test-unit
+
+BUNDLED WITH
+ 2.3.0.dev
diff --git a/tool/bundler/test_gems.rb b/tool/bundler/test_gems.rb
new file mode 100644
index 0000000000..215d23183e
--- /dev/null
+++ b/tool/bundler/test_gems.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "rack", "2.0.8"
+gem "webrick", "1.7.0"
+gem "rack-test", "~> 1.1"
+gem "artifice", "~> 0.6.0"
+gem "compact_index", "~> 0.13.0"
+gem "sinatra", "~> 2.0"
+gem "rake", "13.0.1"
+gem "builder", "~> 3.2"
diff --git a/tool/bundler/test_gems.rb.lock b/tool/bundler/test_gems.rb.lock
new file mode 100644
index 0000000000..7c65d17837
--- /dev/null
+++ b/tool/bundler/test_gems.rb.lock
@@ -0,0 +1,44 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ artifice (0.6)
+ rack-test
+ builder (3.2.4)
+ compact_index (0.13.0)
+ mustermann (1.1.1)
+ ruby2_keywords (~> 0.0.1)
+ rack (2.0.8)
+ rack-protection (2.0.8.1)
+ rack
+ rack-test (1.1.0)
+ rack (>= 1.0, < 3)
+ rake (13.0.1)
+ ruby2_keywords (0.0.5)
+ sinatra (2.0.8.1)
+ mustermann (~> 1.0)
+ rack (~> 2.0)
+ rack-protection (= 2.0.8.1)
+ tilt (~> 2.0)
+ tilt (2.0.10)
+ webrick (1.7.0)
+
+PLATFORMS
+ java
+ ruby
+ universal-java-11
+ x64-mingw32
+ x86_64-darwin-20
+ x86_64-linux
+
+DEPENDENCIES
+ artifice (~> 0.6.0)
+ builder (~> 3.2)
+ compact_index (~> 0.13.0)
+ rack (= 2.0.8)
+ rack-test (~> 1.1)
+ rake (= 13.0.1)
+ sinatra (~> 2.0)
+ webrick (= 1.7.0)
+
+BUNDLED WITH
+ 2.2.33
diff --git a/tool/downloader.rb b/tool/downloader.rb
index 9a89010b03..d09afc5ad7 100644
--- a/tool/downloader.rb
+++ b/tool/downloader.rb
@@ -51,7 +51,12 @@ class Downloader
class GNU < self
def self.download(name, *rest)
if https?
- super("https://cdn.jsdelivr.net/gh/gcc-mirror/gcc@master/#{name}", name, *rest)
+ begin
+ super("https://cdn.jsdelivr.net/gh/gcc-mirror/gcc@master/#{name}", name, *rest)
+ rescue => e
+ STDERR.puts "Download failed (#{e.message}), try another URL"
+ super("https://raw.githubusercontent.com/gcc-mirror/gcc/master/#{name}", name, *rest)
+ end
else
super("https://repo.or.cz/official-gcc.git/blob_plain/HEAD:/#{name}", name, *rest)
end
@@ -71,7 +76,7 @@ class Downloader
class Unicode < self
INDEX = {} # cache index file information across files in the same directory
- UNICODE_PUBLIC = "http://www.unicode.org/Public/"
+ UNICODE_PUBLIC = "https://www.unicode.org/Public/"
def self.download(name, dir = nil, since = true, options = {})
options = options.dup
@@ -192,7 +197,7 @@ class Downloader
$stdout.flush
end
begin
- data = with_retry(9) do
+ data = with_retry(10) do
url.read(options.merge(http_options(file, since.nil? ? true : since)))
end
rescue OpenURI::HTTPError => http_error
diff --git a/tool/extlibs.rb b/tool/extlibs.rb
index f021a2bf01..8a9c5a8fd0 100755
--- a/tool/extlibs.rb
+++ b/tool/extlibs.rb
@@ -7,13 +7,27 @@ require 'digest'
require_relative 'downloader'
require_relative 'lib/colorize'
+class Vars < Hash
+ def pattern
+ /\$\((#{Regexp.union(keys)})\)/
+ end
+
+ def expand(str)
+ if empty?
+ str
+ else
+ str.gsub(pattern) {self[$1]}
+ end
+ end
+end
+
class ExtLibs
def initialize
@colorize = Colorize.new
end
def cache_file(url, cache_dir)
- Downloader.cache_file(url, nil, :cache_dir => cache_dir)
+ Downloader.cache_file(url, nil, cache_dir).to_path
end
def do_download(url, cache_dir)
@@ -80,6 +94,46 @@ class ExtLibs
$?.success? or raise "failed to patch #{patch}"
end
+ def do_link(file, src, dest)
+ file = File.join(dest, file)
+ if (target = src).start_with?("/")
+ target = File.join([".."] * file.count("/"), src)
+ end
+ return unless File.exist?(File.expand_path(target, File.dirname(file)))
+ File.unlink(file) rescue nil
+ begin
+ File.symlink(target, file)
+ rescue
+ else
+ if $VERBOSE
+ $stdout.puts "linked #{target} to #{file}"
+ $stdout.flush
+ end
+ return
+ end
+ begin
+ src = src.sub(/\A\//, '')
+ File.copy_stream(src, file)
+ rescue
+ if $VERBOSE
+ $stdout.puts "failed to link #{src} to #{file}: #{$!.message}"
+ end
+ else
+ if $VERBOSE
+ $stdout.puts "copied #{src} to #{file}"
+ end
+ end
+ end
+
+ def do_exec(command, dir, dest)
+ dir = dir ? File.join(dest, dir) : dest
+ if $VERBOSE
+ $stdout.puts "running #{command.dump} under #{dir}"
+ $stdout.flush
+ end
+ system(command, chdir: dir) or raise "failed #{command.dump}"
+ end
+
def do_command(mode, dest, url, cache_dir, chksums)
extracted = false
base = /.*(?=\.tar(?:\.\w+)?\z)/
@@ -143,19 +197,37 @@ class ExtLibs
$stdout.puts "downloading for #{list}"
$stdout.flush
end
+ vars = Vars.new
extracted = false
dest = File.dirname(list)
url = chksums = nil
IO.foreach(list) do |line|
line.sub!(/\s*#.*/, '')
+ if /^(\w+)\s*=\s*(.*)/ =~ line
+ vars[$1] = vars.expand($2)
+ next
+ end
if chksums
chksums.concat(line.split)
elsif /^\t/ =~ line
if extracted and (mode == :all or mode == :patch)
- patch, *args = line.split
+ patch, *args = line.split.map {|s| vars.expand(s)}
do_patch(dest, patch, args)
end
next
+ elsif /^!\s*(?:chdir:\s*([^|\s]+)\|\s*)?(.*)/ =~ line
+ if extracted and (mode == :all or mode == :patch)
+ command = vars.expand($2.strip)
+ chdir = $1 and chdir = vars.expand(chdir)
+ do_exec(command, chdir, dest)
+ end
+ next
+ elsif /->/ =~ line
+ if extracted and (mode == :all or mode == :patch)
+ link, file = $`.strip, $'.strip
+ do_link(vars.expand(link), vars.expand(file), dest)
+ end
+ next
else
url, *chksums = line.split(' ')
end
@@ -163,7 +235,11 @@ class ExtLibs
chksums.pop
next
end
- next unless url
+ unless url
+ chksums = nil
+ next
+ end
+ url = vars.expand(url)
begin
extracted = do_command(mode, dest, url, cache_dir, chksums)
rescue => e
diff --git a/tool/fake.rb b/tool/fake.rb
index 4946fd6234..42174052e2 100644
--- a/tool/fake.rb
+++ b/tool/fake.rb
@@ -43,7 +43,6 @@ prehook = proc do |extmk|
$extout_prefix = '$(extout)$(target_prefix)/'
config = RbConfig::CONFIG
mkconfig = RbConfig::MAKEFILE_CONFIG
- $builtruby ||= File.join(builddir, config['RUBY_INSTALL_NAME'] + config['EXEEXT'])
RbConfig.fire_update!("builddir", builddir)
RbConfig.fire_update!("buildlibdir", builddir)
RbConfig.fire_update!("libdir", builddir)
diff --git a/tool/fetch-bundled_gems.rb b/tool/fetch-bundled_gems.rb
index ba16d726fd..ebb70e88f9 100755
--- a/tool/fetch-bundled_gems.rb
+++ b/tool/fetch-bundled_gems.rb
@@ -8,24 +8,20 @@ BEGIN {
Dir.chdir(dir)
}
-n, v, u = $F
-case n
-when "minitest"
- v = "master"
-when "test-unit"
-else
- v = "v" + v
-end
+n, v, u, r = $F
+
+next if n =~ /^#/
if File.directory?(n)
puts "updating #{n} ..."
- if v == "master"
- system(*%W"git pull", chdir: n) or abort
- else
- system(*%W"git fetch", chdir: n) or abort
- end
+ system("git", "fetch", chdir: n) or abort
else
puts "retrieving #{n} ..."
system(*%W"git clone #{u} #{n}") or abort
end
-system(*%W"git checkout #{v}", chdir: n) or abort
+c = r || "v#{v}"
+checkout = %w"git -c advice.detachedHead=false checkout"
+puts "checking out #{c} (v=#{v}, r=#{r}) ..."
+unless system(*checkout, c, "--", chdir: n)
+ abort
+end
diff --git a/tool/gem-unpack.rb b/tool/gem-unpack.rb
index 08faec9355..cb05719463 100644
--- a/tool/gem-unpack.rb
+++ b/tool/gem-unpack.rb
@@ -11,7 +11,7 @@ def Gem.unpack(file, dir = nil)
target = spec.full_name
target = File.join(dir, target) if dir
pkg.extract_files target
- spec_file = File.join(target, "#{spec.name}.gemspec")
+ spec_file = File.join(target, "#{spec.name}-#{spec.version}.gemspec")
open(spec_file, 'wb') do |f|
f.print spec.to_ruby
end
diff --git a/tool/leaked-globals b/tool/leaked-globals
index ec116211de..0fb9e657c9 100755
--- a/tool/leaked-globals
+++ b/tool/leaked-globals
@@ -21,10 +21,10 @@ print "Checking leaked global symbols..."
STDOUT.flush
IO.foreach("|#{NM} -Pgp #{ARGV.join(' ')}") do |line|
n, t, = line.split
- next unless /[BDT]/ =~ t
+ next unless /[A-TV-Z]/ =~ t
next unless n.sub!(/^#{SYMBOL_PREFIX}/o, "")
next if n.include?(".")
- next if /\A(?:Init_|InitVM_|ruby_|rb_|[Oo]nig|dln_|mjit_|coroutine_|nu(?:comp|rat)_)/ =~ n
+ next if /\A(?:Init_|InitVM_|RUBY_|ruby_|rb_|[Oo]nig|dln_|mjit_|coroutine_|nu(?:comp|rat)_)/ =~ n
next if REPLACE.include?(n)
puts col.fail("leaked") if count.zero?
count += 1
diff --git a/tool/lib/colorize.rb b/tool/lib/colorize.rb
index 7494a2198a..6699aef572 100644
--- a/tool/lib/colorize.rb
+++ b/tool/lib/colorize.rb
@@ -1,8 +1,12 @@
# frozen-string-literal: true
class Colorize
+ # call-seq:
+ # Colorize.new(colorize = nil)
+ # Colorize.new(color: color, colors_file: colors_file)
def initialize(color = nil, opts = ((_, color = color, nil)[0] if Hash === color))
@colors = @reset = nil
+ @color = (opts[:color] if opts)
if color or (color == nil && STDOUT.tty?)
if (/\A\e\[.*m\z/ =~ IO.popen("tput smso", "r", :err => IO::NULL, &:read) rescue nil)
@beg = "\e["
@@ -29,7 +33,8 @@ class Colorize
"bold"=>"1", "underline"=>"4", "reverse"=>"7",
}
- def decorate(str, name)
+ # colorize.decorate(str, name = color_name)
+ def decorate(str, name = @color)
if @colors and color = (@colors[name] || DEFAULTS[name])
"#{@beg}#{color}m#{str}#{@reset}"
else
@@ -45,7 +50,6 @@ class Colorize
end
if $0 == __FILE__
- colorize = Colorize.new
- col = ARGV.shift
- ARGV.each {|str| puts colorize.decorate(str, col)}
+ colorize = Colorize.new(ARGV.shift)
+ ARGV.each {|str| puts colorize.decorate(str)}
end
diff --git a/tool/lib/envutil.rb b/tool/lib/envutil.rb
index 74575cd50c..937e1128a6 100644
--- a/tool/lib/envutil.rb
+++ b/tool/lib/envutil.rb
@@ -53,7 +53,7 @@ module EnvUtil
@original_internal_encoding = Encoding.default_internal
@original_external_encoding = Encoding.default_external
@original_verbose = $VERBOSE
- @original_warning = %i[deprecated experimental].to_h {|i| [i, Warning[i]]}
+ @original_warning = defined?(Warning.[]) ? %i[deprecated experimental].to_h {|i| [i, Warning[i]]} : nil
end
end
@@ -87,7 +87,20 @@ module EnvUtil
when nil, false
pgroup = pid
end
+
+ lldb = true if /darwin/ =~ RUBY_PLATFORM
+
while signal = signals.shift
+
+ if lldb and [:ABRT, :KILL].include?(signal)
+ lldb = false
+ # sudo -n: --non-interactive
+ # lldb -p: attach
+ # -o: run command
+ system(*%W[sudo -n lldb -p #{pid} --batch -o bt\ all -o call\ rb_vmdebug_stack_dump_all_threads() -o quit])
+ true
+ end
+
begin
Process.kill signal, pgroup
rescue Errno::EINVAL
@@ -101,6 +114,8 @@ module EnvUtil
begin
Timeout.timeout(reprieve) {Process.wait(pid)}
rescue Timeout::Error
+ else
+ break
end
end
end
@@ -135,11 +150,14 @@ module EnvUtil
if RUBYLIB and lib = child_env["RUBYLIB"]
child_env["RUBYLIB"] = [lib, RUBYLIB].join(File::PATH_SEPARATOR)
end
+ child_env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS']
args = [args] if args.kind_of?(String)
pid = spawn(child_env, *precommand, rubybin, *args, **opt)
in_c.close
- out_c.close if capture_stdout
- err_c.close if capture_stderr && capture_stderr != :merge_to_stdout
+ out_c&.close
+ out_c = nil
+ err_c&.close
+ err_c = nil
if block_given?
return yield in_p, out_p, err_p, pid
else
@@ -181,11 +199,6 @@ module EnvUtil
end
module_function :invoke_ruby
- alias rubyexec invoke_ruby
- class << self
- alias rubyexec invoke_ruby
- end
-
def verbose_warning
class << (stderr = "".dup)
alias write concat
@@ -193,13 +206,12 @@ module EnvUtil
end
stderr, $stderr = $stderr, stderr
$VERBOSE = true
- Warning[:deprecated] = true
yield stderr
return $stderr
ensure
stderr, $stderr = $stderr, stderr
$VERBOSE = EnvUtil.original_verbose
- EnvUtil.original_warning.each {|i, v| Warning[i] = v}
+ EnvUtil.original_warning&.each {|i, v| Warning[i] = v}
end
module_function :verbose_warning
@@ -245,7 +257,11 @@ module EnvUtil
def labeled_module(name, &block)
Module.new do
- singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s}
+ singleton_class.class_eval {
+ define_method(:to_s) {name}
+ alias inspect to_s
+ alias name to_s
+ }
class_eval(&block) if block
end
end
@@ -253,7 +269,11 @@ module EnvUtil
def labeled_class(name, superclass = Object, &block)
Class.new(superclass) do
- singleton_class.class_eval {define_method(:to_s) {name}; alias inspect to_s}
+ singleton_class.class_eval {
+ define_method(:to_s) {name}
+ alias inspect to_s
+ alias name to_s
+ }
class_eval(&block) if block
end
end
diff --git a/tool/lib/leakchecker.rb b/tool/lib/leakchecker.rb
index 57e28665d6..4b01d57792 100644
--- a/tool/lib/leakchecker.rb
+++ b/tool/lib/leakchecker.rb
@@ -1,15 +1,23 @@
# frozen_string_literal: true
class LeakChecker
+ @@try_lsof = nil # not-tried-yet
+
def initialize
@fd_info = find_fds
+ @@skip = false
@tempfile_info = find_tempfiles
@thread_info = find_threads
@env_info = find_env
@encoding_info = find_encodings
@old_verbose = $VERBOSE
+ @old_warning_flags = find_warning_flags
end
def check(test_name)
+ if /i386-solaris/ =~ RUBY_PLATFORM && /TestGem/ =~ test_name
+ GC.verify_internal_consistency
+ end
+
leaks = [
check_fd_leak(test_name),
check_thread_leak(test_name),
@@ -17,6 +25,7 @@ class LeakChecker
check_env(test_name),
check_encodings(test_name),
check_verbose(test_name),
+ check_warning_flags(test_name),
]
GC.start if leaks.any?
end
@@ -29,19 +38,19 @@ class LeakChecker
if IO.respond_to?(:console) and (m = IO.method(:console)).arity.nonzero?
m[:close]
end
- fd_dir = "/proc/self/fd"
- if File.directory?(fd_dir)
- fds = Dir.open(fd_dir) {|d|
- a = d.grep(/\A\d+\z/, &:to_i)
- if d.respond_to? :fileno
- a -= [d.fileno]
- end
- a
- }
- fds.sort
- else
- []
+ %w"/proc/self/fd /dev/fd".each do |fd_dir|
+ if File.directory?(fd_dir)
+ fds = Dir.open(fd_dir) {|d|
+ a = d.grep(/\A\d+\z/, &:to_i)
+ if d.respond_to? :fileno
+ a -= [d.fileno]
+ end
+ a
+ }
+ return fds.sort
+ end
end
+ []
end
def check_fd_leak(test_name)
@@ -55,7 +64,7 @@ class LeakChecker
}
end
fd_leaked = live2 - live1
- if !fd_leaked.empty?
+ if !@@skip && !fd_leaked.empty?
leaked = true
h = {}
ObjectSpace.each_object(IO) {|io|
@@ -68,7 +77,7 @@ class LeakChecker
end
(h[fd] ||= []) << [io, autoclose, inspect]
}
- fd_leaked.each {|fd|
+ fd_leaked.select! {|fd|
str = ''.dup
pos = nil
if h[fd]
@@ -83,20 +92,39 @@ class LeakChecker
}.sort.each {|s|
str << s
}
+ else
+ begin
+ io = IO.for_fd(fd, autoclose: false)
+ s = io.stat
+ rescue Errno::EBADF
+ # something un-stat-able
+ next
+ else
+ next if /darwin/ =~ RUBY_PLATFORM and [0, -1].include?(s.dev)
+ str << ' ' << s.inspect
+ ensure
+ io&.close
+ end
end
puts "Leaked file descriptor: #{test_name}: #{fd}#{str}"
puts " The IO was created at #{pos}" if pos
+ true
}
- #system("lsof -p #$$") if !fd_leaked.empty?
+ unless fd_leaked.empty?
+ unless @@try_lsof == false
+ @@try_lsof |= system("lsof -p #$$", out: MiniTest::Unit.output)
+ end
+ end
h.each {|fd, list|
next if list.length <= 1
if 1 < list.count {|io, autoclose, inspect| autoclose }
str = list.map {|io, autoclose, inspect| " #{inspect}" + (autoclose ? "(autoclose)" : "") }.sort.join
- puts "Multiple autoclose IO object for a file descriptor:#{str}"
+ puts "Multiple autoclose IO objects for a file descriptor in: #{test_name}: #{str}"
end
}
end
@fd_info = live2
+ @@skip = false
return leaked
end
@@ -211,22 +239,49 @@ class LeakChecker
end
def find_encodings
- [Encoding.default_internal, Encoding.default_external]
+ {
+ 'Encoding.default_internal' => Encoding.default_internal,
+ 'Encoding.default_external' => Encoding.default_external,
+ 'STDIN.internal_encoding' => STDIN.internal_encoding,
+ 'STDIN.external_encoding' => STDIN.external_encoding,
+ 'STDOUT.internal_encoding' => STDOUT.internal_encoding,
+ 'STDOUT.external_encoding' => STDOUT.external_encoding,
+ 'STDERR.internal_encoding' => STDERR.internal_encoding,
+ 'STDERR.external_encoding' => STDERR.external_encoding,
+ }
end
def check_encodings(test_name)
- old_internal, old_external = @encoding_info
- new_internal, new_external = find_encodings
+ old_encoding_info = @encoding_info
+ @encoding_info = find_encodings
leaked = false
- if new_internal != old_internal
- leaked = true
- puts "Encoding.default_internal changed: #{test_name} : #{old_internal.inspect} to #{new_internal.inspect}"
+ @encoding_info.each do |key, new_encoding|
+ old_encoding = old_encoding_info[key]
+ if new_encoding != old_encoding
+ leaked = true
+ puts "#{key} changed: #{test_name} : #{old_encoding.inspect} to #{new_encoding.inspect}"
+ end
end
- if new_external != old_external
- leaked = true
- puts "Encoding.default_external changed: #{test_name} : #{old_external.inspect} to #{new_external.inspect}"
+ leaked
+ end
+
+ WARNING_CATEGORIES = (Warning.respond_to?(:[]) ? %i[deprecated experimental] : []).freeze
+
+ def find_warning_flags
+ WARNING_CATEGORIES.to_h do |category|
+ [category, Warning[category]]
+ end
+ end
+
+ def check_warning_flags(test_name)
+ new_warning_flags = find_warning_flags
+ leaked = false
+ WARNING_CATEGORIES.each do |category|
+ if new_warning_flags[category] != @old_warning_flags[category]
+ leaked = true
+ puts "Warning[#{category.inspect}] changed: #{test_name} : #{@old_warning_flags[category]} to #{new_warning_flags[category]}"
+ end
end
- @encoding_info = [new_internal, new_external]
return leaked
end
@@ -237,4 +292,8 @@ class LeakChecker
end
output.puts(*a)
end
+
+ def self.skip
+ @@skip = true
+ end
end
diff --git a/tool/lib/minitest/benchmark.rb b/tool/lib/minitest/benchmark.rb
index b3f2bc28b3..547b516c4b 100644
--- a/tool/lib/minitest/benchmark.rb
+++ b/tool/lib/minitest/benchmark.rb
@@ -219,7 +219,7 @@ class MiniTest::Unit # :nodoc:
##
# Takes an array of x/y pairs and calculates the general R^2 value.
#
- # See: http://en.wikipedia.org/wiki/Coefficient_of_determination
+ # See: https://en.wikipedia.org/wiki/Coefficient_of_determination
def fit_error xys
y_bar = sigma(xys) { |x, y| y } / xys.size.to_f
diff --git a/tool/lib/minitest/unit.rb b/tool/lib/minitest/unit.rb
index 8ac0f146bd..9f07313e1b 100644
--- a/tool/lib/minitest/unit.rb
+++ b/tool/lib/minitest/unit.rb
@@ -181,10 +181,12 @@ module MiniTest
def _assertions= n # :nodoc:
@_assertions = n
end
+ alias assertions= _assertions=
def _assertions # :nodoc:
@_assertions ||= 0
end
+ alias assertions _assertions
##
# Fails unless +test+ is a true value.
@@ -446,6 +448,20 @@ module MiniTest
assert caught, message(msg) { default }
end
+ def assert_path_exists(path, msg = nil)
+ msg = message(msg) { "Expected path '#{path}' to exist" }
+ assert File.exist?(path), msg
+ end
+ alias assert_path_exist assert_path_exists
+ alias refute_path_not_exist assert_path_exists
+
+ def refute_path_exists(path, msg = nil)
+ msg = message(msg) { "Expected path '#{path}' to not exist" }
+ refute File.exist?(path), msg
+ end
+ alias refute_path_exist refute_path_exists
+ alias assert_path_not_exist refute_path_exists
+
##
# Captures $stdout and $stderr into strings:
#
@@ -763,12 +779,13 @@ module MiniTest
# Lazy accessor for options.
def options
- @options ||= {}
+ @options ||= {seed: 42}
end
@@installed_at_exit ||= false
@@out = $stdout
@@after_tests = []
+ @@current_repeat_count = 0
##
# A simple hook allowing you to run a block of code after _all_ of
@@ -867,6 +884,10 @@ module MiniTest
##
# Runner for a given +type+ (eg, test vs bench).
+ def self.current_repeat_count
+ @@current_repeat_count
+ end
+
def _run_anything type
suites = TestCase.send "#{type}_suites"
return if suites.empty?
@@ -880,7 +901,7 @@ module MiniTest
sync = output.respond_to? :"sync=" # stupid emacs
old_sync, output.sync = output.sync, true if sync
- count = 0
+ @@current_repeat_count = 0
begin
start = Time.now
@@ -891,15 +912,15 @@ module MiniTest
test_count += @test_count
assertion_count += @assertion_count
t = Time.now - start
- count += 1
+ @@current_repeat_count += 1
unless @repeat_count
puts
puts
end
puts "Finished%s %ss in %.6fs, %.4f tests/s, %.4f assertions/s.\n" %
- [(@repeat_count ? "(#{count}/#{@repeat_count}) " : ""), type,
+ [(@repeat_count ? "(#{@@current_repeat_count}/#{@repeat_count}) " : ""), type,
t, @test_count.fdiv(t), @assertion_count.fdiv(t)]
- end while @repeat_count && count < @repeat_count &&
+ end while @repeat_count && @@current_repeat_count < @repeat_count &&
report.empty? && failures.zero? && errors.zero?
output.sync = old_sync if sync
@@ -1293,6 +1314,8 @@ module MiniTest
start_time = Time.now
result = ""
+ srand(runner.options[:seed])
+
begin
@passed = nil
self.before_setup
@@ -1381,11 +1404,31 @@ module MiniTest
end
def self.test_order # :nodoc:
- :random
+ :sorted
end
def self.test_suites # :nodoc:
- @@test_suites.keys.sort_by { |ts| ts.name.to_s }
+ suites = @@test_suites.keys
+
+ case self.test_order
+ when :random
+ # shuffle test suites based on CRC32 of their names
+ salt = "\n" + rand(1 << 32).to_s
+ crc_tbl = (0..255).map do |i|
+ (0..7).inject(i) {|c,| (c & 1 == 1) ? (0xEDB88320 ^ (c >> 1)) : (c >> 1) }
+ end
+ suites = suites.sort_by do |suite|
+ crc32 = 0xffffffff
+ (suite.name + salt).each_byte do |data|
+ crc32 = crc_tbl[(crc32 ^ data) & 0xff] ^ (crc32 >> 8)
+ end
+ crc32 ^ 0xffffffff
+ end
+ when :nosort
+ suites
+ else
+ suites.sort_by { |ts| ts.name.to_s }
+ end
end
def self.test_methods # :nodoc:
@@ -1400,6 +1443,8 @@ module MiniTest
methods.sort.sort_by { rand max }
when :alpha, :sorted then
methods.sort
+ when :nosort
+ methods
else
raise "Unknown test_order: #{self.test_order.inspect}"
end
diff --git a/tool/lib/test/unit.rb b/tool/lib/test/unit.rb
index 42d1d83442..38369a1040 100644
--- a/tool/lib/test/unit.rb
+++ b/tool/lib/test/unit.rb
@@ -64,7 +64,18 @@ module Test
args = @init_hook.call(args, options) if @init_hook
non_options(args, options)
@run_options = orig_args
- @help = orig_args.map { |s| s =~ /[\s|&<>$()]/ ? s.inspect : s }.join " "
+
+ if seed = options[:seed]
+ srand(seed)
+ else
+ seed = options[:seed] = srand % 100_000
+ srand(seed)
+ orig_args.unshift "--seed=#{seed}"
+ end
+
+ @help = "\n" + orig_args.map { |s|
+ " " + (s =~ /[\s|&<>$()]/ ? s.inspect : s)
+ }.join("\n")
@options = options
end
@@ -79,7 +90,7 @@ module Test
end
opts.on '-s', '--seed SEED', Integer, "Sets random seed" do |m|
- options[:seed] = m
+ options[:seed] = m.to_i
end
opts.on '-v', '--verbose', "Verbose. Show progress processing files." do
@@ -91,7 +102,7 @@ module Test
(options[:filter] ||= []) << a
end
- opts.on '--test-order=random|alpha|sorted', [:random, :alpha, :sorted] do |a|
+ opts.on '--test-order=random|alpha|sorted|nosort', [:random, :alpha, :sorted, :nosort] do |a|
MiniTest::Unit::TestCase.test_order = a
end
end
@@ -106,6 +117,9 @@ module Test
filter = nil
elsif negative.empty? and positive.size == 1 and pos_pat !~ positive[0]
filter = positive[0]
+ unless /\A[A-Z]\w*(?:::[A-Z]\w*)*#/ =~ filter
+ filter = /##{Regexp.quote(filter)}\z/
+ end
else
filter = Regexp.union(*positive.map! {|s| Regexp.new(s[pos_pat, 1] || "\\A#{Regexp.quote(s)}\\z")})
end
@@ -114,6 +128,7 @@ module Test
filter = /\A(?=.*#{filter})(?!.*#{negative})/
end
if Regexp === filter
+ filter = filter.dup
# bypass conversion in minitest
def filter.=~(other) # :nodoc:
super unless Regexp === other
@@ -191,6 +206,10 @@ module Test
opts.on '--ruby VAL', "Path to ruby which is used at -j option" do |a|
options[:ruby] = a.split(/ /).reject(&:empty?)
end
+
+ opts.on '--timetable-data=FILE', "Path to timetable data" do |a|
+ options[:timetable_data] = a
+ end
end
class Worker
@@ -204,8 +223,12 @@ module Test
end
attr_reader :quit_called
+ attr_accessor :start_time
+
+ @@worker_number = 0
def initialize(io, pid, status)
+ @num = (@@worker_number += 1)
@io = io
@pid = pid
@status = status
@@ -216,6 +239,10 @@ module Test
@quit_called = false
end
+ def name
+ "Worker #{@num}"
+ end
+
def puts(*args)
@io.puts(*args)
end
@@ -228,6 +255,7 @@ module Test
@loadpath = $:.dup
puts "run #{task} #{type}"
@status = :prepare
+ @start_time = Time.now
rescue Errno::EPIPE
died
rescue IOError
@@ -320,6 +348,22 @@ module Test
warn "or, a bug of test/unit/parallel.rb. try again without -j"
warn "option."
warn ""
+ if File.exist?('core')
+ require 'fileutils'
+ require 'time'
+ Dir.glob('/tmp/test-unit-core.*').each do |f|
+ if Time.now - File.mtime(f) > 7 * 24 * 60 * 60 # 7 days
+ warn "Deleting an old core file: #{f}"
+ FileUtils.rm(f)
+ end
+ end
+ core_path = "/tmp/test-unit-core.#{Time.now.utc.iso8601}"
+ warn "A core file is found. Saving it at: #{core_path.dump}"
+ FileUtils.mv('core', core_path)
+ cmd = ['gdb', RbConfig.ruby, '-c', core_path, '-ex', 'bt', '-batch']
+ p cmd # debugging why it's not working
+ system(*cmd)
+ end
STDERR.flush
exit c
end
@@ -393,6 +437,7 @@ module Test
worker = @workers_hash[io]
cmd = worker.read
cmd.sub!(/\A\.+/, '') if cmd # read may return nil
+
case cmd
when ''
# just only dots, ignore
@@ -425,10 +470,19 @@ module Test
rep << {file: worker.real_file, report: r[2], result: r[3], testcase: r[5]}
$:.push(*r[4]).uniq!
jobs_status(worker) if @options[:job_status] == :replace
+
return true
when /^record (.+?)$/
begin
r = Marshal.load($1.unpack("m")[0])
+
+ suite = r.first
+ key = [worker.name, suite]
+ if @records[key]
+ @records[key][1] = worker.start_time = Time.now
+ else
+ @records[key] = [worker.start_time, Time.now]
+ end
rescue => e
print "unknown record: #{e.message} #{$1.unpack("m")[0].dump}"
return true
@@ -455,6 +509,8 @@ module Test
end
def _run_parallel suites, type, result
+ @records = {}
+
if @options[:parallel] < 1
warn "Error: parameter of -j option should be greater than 0."
return
@@ -463,6 +519,16 @@ module Test
# Require needed thing for parallel running
require 'timeout'
@tasks = @files.dup # Array of filenames.
+
+ case MiniTest::Unit::TestCase.test_order
+ when :random
+ @tasks.shuffle!
+ else
+ # JIT first
+ ts = @tasks.group_by{|e| /test_jit/ =~ e ? 0 : 1}
+ @tasks = ts[0] + ts[1] if ts.size == 2
+ end
+
@need_quit = false
@dead_workers = [] # Array of dead workers.
@warnings = []
@@ -494,6 +560,14 @@ module Test
@interrupt = ex
return result
ensure
+ if file = @options[:timetable_data]
+ open(file, 'w'){|f|
+ @records.each{|(worker, suite), (st, ed)|
+ f.puts '[' + [worker.dump, suite.dump, st.to_f * 1_000, ed.to_f * 1_000].join(", ") + '],'
+ }
+ }
+ end
+
if @interrupt
@ios.select!{|x| @workers_hash[x].status == :running }
while !@ios.empty? && (__io = IO.select(@ios,[],[],10))
@@ -508,7 +582,7 @@ module Test
parallel = @options[:parallel]
@options[:parallel] = false
suites, rep = rep.partition {|r| r[:testcase] && r[:file] && r[:report].any? {|e| !e[2].is_a?(MiniTest::Skip)}}
- suites.map {|r| r[:file]}.uniq.each {|file| require file}
+ suites.map {|r| File.realpath(r[:file])}.uniq.each {|file| require file}
suites.map! {|r| eval("::"+r[:testcase])}
del_status_line or puts
unless suites.empty?
diff --git a/tool/lib/test/unit/assertions.rb b/tool/lib/test/unit/assertions.rb
index e2b865899a..14442c0029 100644
--- a/tool/lib/test/unit/assertions.rb
+++ b/tool/lib/test/unit/assertions.rb
@@ -8,32 +8,6 @@ module Test
module Assertions
include Test::Unit::CoreAssertions
- MINI_DIR = File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), "minitest") #:nodoc:
-
- # :call-seq:
- # assert(test, [failure_message])
- #
- #Tests if +test+ is true.
- #
- #+msg+ may be a String or a Proc. If +msg+ is a String, it will be used
- #as the failure message. Otherwise, the result of calling +msg+ will be
- #used as the message if the assertion fails.
- #
- #If no +msg+ is given, a default message will be used.
- #
- # assert(false, "This was expected to be true")
- def assert(test, *msgs)
- case msg = msgs.first
- when String, Proc
- when nil
- msgs.shift
- else
- bt = caller.reject { |s| s.start_with?(MINI_DIR) }
- raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt
- end unless msgs.empty?
- super
- end
-
# :call-seq:
# assert_block( failure_message = nil )
#
@@ -53,50 +27,6 @@ module Test
end
# :call-seq:
- # assert_nothing_raised( *args, &block )
- #
- #If any exceptions are given as arguments, the assertion will
- #fail if one of those exceptions are raised. Otherwise, the test fails
- #if any exceptions are raised.
- #
- #The final argument may be a failure message.
- #
- # assert_nothing_raised RuntimeError do
- # raise Exception #Assertion passes, Exception is not a RuntimeError
- # end
- #
- # assert_nothing_raised do
- # raise Exception #Assertion fails
- # end
- def assert_nothing_raised(*args)
- self._assertions += 1
- if Module === args.last
- msg = nil
- else
- msg = args.pop
- end
- begin
- line = __LINE__; yield
- rescue MiniTest::Skip
- raise
- rescue Exception => e
- bt = e.backtrace
- as = e.instance_of?(MiniTest::Assertion)
- if as
- ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o
- bt.reject! {|ln| ans =~ ln}
- end
- if ((args.empty? && !as) ||
- args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a })
- msg = message(msg) { "Exception raised:\n<#{mu_pp(e)}>" }
- raise MiniTest::Assertion, msg.call, bt
- else
- raise
- end
- end
- end
-
- # :call-seq:
# assert_nothing_thrown( failure_message = nil, &block )
#
#Fails if the given block uses a call to Kernel#throw, and
@@ -226,52 +156,6 @@ EOT
end
# :call-seq:
- # assert_respond_to( object, method, failure_message = nil )
- #
- #Tests if the given Object responds to +method+.
- #
- #An optional failure message may be provided as the final argument.
- #
- # assert_respond_to("hello", :reverse) #Succeeds
- # assert_respond_to("hello", :does_not_exist) #Fails
- def assert_respond_to(obj, (meth, *priv), msg = nil)
- unless priv.empty?
- msg = message(msg) {
- "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv[0]}"
- }
- return assert obj.respond_to?(meth, *priv), msg
- end
- #get rid of overcounting
- if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
- return if obj.respond_to?(meth)
- end
- super(obj, meth, msg)
- end
-
- # :call-seq:
- # assert_not_respond_to( object, method, failure_message = nil )
- #
- #Tests if the given Object does not respond to +method+.
- #
- #An optional failure message may be provided as the final argument.
- #
- # assert_not_respond_to("hello", :reverse) #Fails
- # assert_not_respond_to("hello", :does_not_exist) #Succeeds
- def assert_not_respond_to(obj, (meth, *priv), msg = nil)
- unless priv.empty?
- msg = message(msg) {
- "Expected #{mu_pp(obj)} (#{obj.class}) to not respond to ##{meth}#{" privately" if priv[0]}"
- }
- return assert !obj.respond_to?(meth, *priv), msg
- end
- #get rid of overcounting
- if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
- return unless obj.respond_to?(meth)
- end
- refute_respond_to(obj, meth, msg)
- end
-
- # :call-seq:
# assert_send( +send_array+, failure_message = nil )
#
# Passes if the method send returns a true value.
@@ -354,60 +238,9 @@ EOT
# compatibility with test-unit
alias pend skip
- if defined?(RubyVM::InstructionSequence)
- def syntax_check(code, fname, line)
- code = code.dup.force_encoding(Encoding::UTF_8)
- RubyVM::InstructionSequence.compile(code, fname, fname, line)
- :ok
- ensure
- raise if SyntaxError === $!
- end
- else
- def syntax_check(code, fname, line)
- code = code.b
- code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) {
- "#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ok}\n"
- }
- code = code.force_encoding(Encoding::UTF_8)
- catch {|tag| eval(code, binding, fname, line - 1)}
- end
- end
-
- def prepare_syntax_check(code, fname = nil, mesg = nil, verbose: nil)
- fname ||= caller_locations(2, 1)[0]
- mesg ||= fname.to_s
- verbose, $VERBOSE = $VERBOSE, verbose
- case
- when Array === fname
- fname, line = *fname
- when defined?(fname.path) && defined?(fname.lineno)
- fname, line = fname.path, fname.lineno
- else
- line = 1
- end
- yield(code, fname, line, message(mesg) {
- if code.end_with?("\n")
- "```\n#{code}```\n"
- else
- "```\n#{code}\n```\n""no-newline"
- end
- })
- ensure
- $VERBOSE = verbose
- end
-
- def assert_valid_syntax(code, *args, **opt)
+ def assert_syntax_error(code, error, *args, **opt)
prepare_syntax_check(code, *args, **opt) do |src, fname, line, mesg|
yield if defined?(yield)
- assert_nothing_raised(SyntaxError, mesg) do
- assert_equal(:ok, syntax_check(src, fname, line), mesg)
- end
- end
- end
-
- def assert_syntax_error(code, error, *args)
- prepare_syntax_check(code, *args) do |src, fname, line, mesg|
- yield if defined?(yield)
e = assert_raise(SyntaxError, mesg) do
syntax_check(src, fname, line)
end
@@ -416,17 +249,6 @@ EOT
end
end
- def assert_normal_exit(testsrc, message = '', child_env: nil, **opt)
- assert_valid_syntax(testsrc, caller_locations(1, 1)[0])
- if child_env
- child_env = [child_env]
- else
- child_env = []
- end
- out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, **opt)
- assert !status.signaled?, FailDesc[status, message, out]
- end
-
def assert_no_warning(pat, msg = nil)
result = nil
stderr = EnvUtil.verbose_warning {
@@ -439,51 +261,6 @@ EOT
result
end
- def assert_no_memory_leak(args, prepare, code, message=nil, limit: 2.0, rss: false, **opt)
- # TODO: consider choosing some appropriate limit for MJIT and stop skipping this once it does not randomly fail
- skip 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
-
- require_relative '../../memory_status'
- raise MiniTest::Skip, "unsupported platform" unless defined?(Memory::Status)
-
- token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m"
- token_dump = token.dump
- token_re = Regexp.quote(token)
- envs = args.shift if Array === args and Hash === args.first
- args = [
- "--disable=gems",
- "-r", File.expand_path("../../../memory_status", __FILE__),
- *args,
- "-v", "-",
- ]
- if defined? Memory::NO_MEMORY_LEAK_ENVS then
- envs ||= {}
- newenvs = envs.merge(Memory::NO_MEMORY_LEAK_ENVS) { |_, _, _| break }
- envs = newenvs if newenvs
- end
- args.unshift(envs) if envs
- cmd = [
- 'END {STDERR.puts '"#{token_dump}"'"FINAL=#{Memory::Status.new}"}',
- prepare,
- 'STDERR.puts('"#{token_dump}"'"START=#{$initial_status = Memory::Status.new}")',
- '$initial_size = $initial_status.size',
- code,
- 'GC.start',
- ].join("\n")
- _, err, status = EnvUtil.invoke_ruby(args, cmd, true, true, **opt)
- before = err.sub!(/^#{token_re}START=(\{.*\})\n/, '') && Memory::Status.parse($1)
- after = err.sub!(/^#{token_re}FINAL=(\{.*\})\n/, '') && Memory::Status.parse($1)
- assert(status.success?, FailDesc[status, message, err])
- ([:size, (rss && :rss)] & after.members).each do |n|
- b = before[n]
- a = after[n]
- next unless a > 0 and b > 0
- assert_operator(a.fdiv(b), :<, limit, message(message) {"#{n}: #{b} => #{a}"})
- end
- rescue LoadError
- skip
- end
-
# kernel resolution can limit the minimum time we can measure
# [ruby-core:81540]
MIN_HZ = MiniTest::Unit::TestCase.windows? ? 67 : 100
@@ -523,49 +300,6 @@ EOT
assert(1.0/f == -Float::INFINITY, "#{f} is not -0.0")
end
- # pattern_list is an array which contains regexp and :*.
- # :* means any sequence.
- #
- # pattern_list is anchored.
- # Use [:*, regexp, :*] for non-anchored match.
- def assert_pattern_list(pattern_list, actual, message=nil)
- rest = actual
- anchored = true
- pattern_list.each_with_index {|pattern, i|
- if pattern == :*
- anchored = false
- else
- if anchored
- match = /\A#{pattern}/.match(rest)
- else
- match = pattern.match(rest)
- end
- unless match
- msg = message(msg) {
- expect_msg = "Expected #{mu_pp pattern}\n"
- if /\n[^\n]/ =~ rest
- actual_mesg = +"to match\n"
- rest.scan(/.*\n+/) {
- actual_mesg << ' ' << $&.inspect << "+\n"
- }
- actual_mesg.sub!(/\+\n\z/, '')
- else
- actual_mesg = "to match " + mu_pp(rest)
- end
- actual_mesg << "\nafter #{i} patterns with #{actual.length - rest.length} characters"
- expect_msg + actual_mesg
- }
- assert false, msg
- end
- rest = match.post_match
- anchored = true
- end
- }
- if anchored
- assert_equal("", rest)
- end
- end
-
def assert_all_assertions_foreach(msg = nil, *keys, &block)
all = AllFailures.new
all.foreach(*keys, &block)
diff --git a/tool/lib/test/unit/core_assertions.rb b/tool/lib/test/unit/core_assertions.rb
index 00555d6e32..abd0e45035 100644
--- a/tool/lib/test/unit/core_assertions.rb
+++ b/tool/lib/test/unit/core_assertions.rb
@@ -94,6 +94,161 @@ module Test
end
end
+ if defined?(RubyVM::InstructionSequence)
+ def syntax_check(code, fname, line)
+ code = code.dup.force_encoding(Encoding::UTF_8)
+ RubyVM::InstructionSequence.compile(code, fname, fname, line)
+ :ok
+ ensure
+ raise if SyntaxError === $!
+ end
+ else
+ def syntax_check(code, fname, line)
+ code = code.b
+ code.sub!(/\A(?:\xef\xbb\xbf)?(\s*\#.*$)*(\n)?/n) {
+ "#$&#{"\n" if $1 && !$2}BEGIN{throw tag, :ok}\n"
+ }
+ code = code.force_encoding(Encoding::UTF_8)
+ catch {|tag| eval(code, binding, fname, line - 1)}
+ end
+ end
+
+ def assert_no_memory_leak(args, prepare, code, message=nil, limit: 2.0, rss: false, **opt)
+ # TODO: consider choosing some appropriate limit for MJIT and stop skipping this once it does not randomly fail
+ pend 'assert_no_memory_leak may consider MJIT memory usage as leak' if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
+
+ require_relative '../../memory_status'
+ raise MiniTest::Skip, "unsupported platform" unless defined?(Memory::Status)
+
+ token = "\e[7;1m#{$$.to_s}:#{Time.now.strftime('%s.%L')}:#{rand(0x10000).to_s(16)}:\e[m"
+ token_dump = token.dump
+ token_re = Regexp.quote(token)
+ envs = args.shift if Array === args and Hash === args.first
+ args = [
+ "--disable=gems",
+ "-r", File.expand_path("../../../memory_status", __FILE__),
+ *args,
+ "-v", "-",
+ ]
+ if defined? Memory::NO_MEMORY_LEAK_ENVS then
+ envs ||= {}
+ newenvs = envs.merge(Memory::NO_MEMORY_LEAK_ENVS) { |_, _, _| break }
+ envs = newenvs if newenvs
+ end
+ args.unshift(envs) if envs
+ cmd = [
+ 'END {STDERR.puts '"#{token_dump}"'"FINAL=#{Memory::Status.new}"}',
+ prepare,
+ 'STDERR.puts('"#{token_dump}"'"START=#{$initial_status = Memory::Status.new}")',
+ '$initial_size = $initial_status.size',
+ code,
+ 'GC.start',
+ ].join("\n")
+ _, err, status = EnvUtil.invoke_ruby(args, cmd, true, true, **opt)
+ before = err.sub!(/^#{token_re}START=(\{.*\})\n/, '') && Memory::Status.parse($1)
+ after = err.sub!(/^#{token_re}FINAL=(\{.*\})\n/, '') && Memory::Status.parse($1)
+ assert(status.success?, FailDesc[status, message, err])
+ ([:size, (rss && :rss)] & after.members).each do |n|
+ b = before[n]
+ a = after[n]
+ next unless a > 0 and b > 0
+ assert_operator(a.fdiv(b), :<, limit, message(message) {"#{n}: #{b} => #{a}"})
+ end
+ rescue LoadError
+ pend
+ end
+
+ # :call-seq:
+ # assert_nothing_raised( *args, &block )
+ #
+ #If any exceptions are given as arguments, the assertion will
+ #fail if one of those exceptions are raised. Otherwise, the test fails
+ #if any exceptions are raised.
+ #
+ #The final argument may be a failure message.
+ #
+ # assert_nothing_raised RuntimeError do
+ # raise Exception #Assertion passes, Exception is not a RuntimeError
+ # end
+ #
+ # assert_nothing_raised do
+ # raise Exception #Assertion fails
+ # end
+ def assert_nothing_raised(*args)
+ self._assertions += 1
+ if Module === args.last
+ msg = nil
+ else
+ msg = args.pop
+ end
+ begin
+ line = __LINE__; yield
+ rescue MiniTest::Skip
+ raise
+ rescue Exception => e
+ bt = e.backtrace
+ as = e.instance_of?(MiniTest::Assertion)
+ if as
+ ans = /\A#{Regexp.quote(__FILE__)}:#{line}:in /o
+ bt.reject! {|ln| ans =~ ln}
+ end
+ if ((args.empty? && !as) ||
+ args.any? {|a| a.instance_of?(Module) ? e.is_a?(a) : e.class == a })
+ msg = message(msg) {
+ "Exception raised:\n<#{mu_pp(e)}>\n" +
+ "Backtrace:\n" +
+ e.backtrace.map{|frame| " #{frame}"}.join("\n")
+ }
+ raise MiniTest::Assertion, msg.call, bt
+ else
+ raise
+ end
+ end
+ end
+
+ def prepare_syntax_check(code, fname = nil, mesg = nil, verbose: nil)
+ fname ||= caller_locations(2, 1)[0]
+ mesg ||= fname.to_s
+ verbose, $VERBOSE = $VERBOSE, verbose
+ case
+ when Array === fname
+ fname, line = *fname
+ when defined?(fname.path) && defined?(fname.lineno)
+ fname, line = fname.path, fname.lineno
+ else
+ line = 1
+ end
+ yield(code, fname, line, message(mesg) {
+ if code.end_with?("\n")
+ "```\n#{code}```\n"
+ else
+ "```\n#{code}\n```\n""no-newline"
+ end
+ })
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def assert_valid_syntax(code, *args, **opt)
+ prepare_syntax_check(code, *args, **opt) do |src, fname, line, mesg|
+ yield if defined?(yield)
+ assert_nothing_raised(SyntaxError, mesg) do
+ assert_equal(:ok, syntax_check(src, fname, line), mesg)
+ end
+ end
+ end
+
+ def assert_normal_exit(testsrc, message = '', child_env: nil, **opt)
+ assert_valid_syntax(testsrc, caller_locations(1, 1)[0])
+ if child_env
+ child_env = [child_env]
+ else
+ child_env = []
+ end
+ out, _, status = EnvUtil.invoke_ruby(child_env + %W'-W0', testsrc, true, :merge_to_stdout, **opt)
+ assert !status.signaled?, FailDesc[status, message, out]
+ end
+
def assert_ruby_status(args, test_stdin="", message=nil, **opt)
out, _, status = EnvUtil.invoke_ruby(args, test_stdin, true, :merge_to_stdout, **opt)
desc = FailDesc[status, message, out]
@@ -104,35 +259,57 @@ module Test
ABORT_SIGNALS = Signal.list.values_at(*%w"ILL ABRT BUS SEGV TERM")
+ def separated_runner(out = nil)
+ out = out ? IO.new(out, 'w') : STDOUT
+ at_exit {
+ out.puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}"
+ }
+ Test::Unit::Runner.class_variable_set(:@@stop_auto_run, true) if defined?(Test::Unit::Runner)
+ end
+
def assert_separately(args, file = nil, line = nil, src, ignore_stderr: nil, **opt)
unless file and line
loc, = caller_locations(1,1)
file ||= loc.path
line ||= loc.lineno
end
+ capture_stdout = true
+ unless /mswin|mingw/ =~ RUBY_PLATFORM
+ capture_stdout = false
+ opt[:out] = MiniTest::Unit.output if defined?(MiniTest::Unit)
+ res_p, res_c = IO.pipe
+ opt[res_c.fileno] = res_c.fileno
+ end
src = <<eom
# -*- coding: #{line += __LINE__; src.encoding}; -*-
+BEGIN {
require "test/unit";include Test::Unit::Assertions;require #{(__dir__ + "/core_assertions").dump};include Test::Unit::CoreAssertions
- END {
- puts [Marshal.dump($!)].pack('m'), "assertions=\#{self._assertions}"
- }
+ separated_runner #{res_c&.fileno}
+}
#{line -= __LINE__; src}
- class Test::Unit::Runner
- @@stop_auto_run = true
- end
eom
args = args.dup
args.insert((Hash === args.first ? 1 : 0), "-w", "--disable=gems", *$:.map {|l| "-I#{l}"})
- stdout, stderr, status = EnvUtil.invoke_ruby(args, src, true, true, **opt)
+ stdout, stderr, status = EnvUtil.invoke_ruby(args, src, capture_stdout, true, **opt)
+ ensure
+ if res_c
+ res_c.close
+ res = res_p.read
+ res_p.close
+ else
+ res = stdout
+ end
+ raise if $!
abort = status.coredump? || (status.signaled? && ABORT_SIGNALS.include?(status.termsig))
assert(!abort, FailDesc[status, nil, stderr])
- self._assertions += stdout[/^assertions=(\d+)/, 1].to_i
+ self._assertions += res[/^assertions=(\d+)/, 1].to_i
begin
- res = Marshal.load(stdout.unpack("m")[0])
+ res = Marshal.load(res.unpack1("m"))
rescue => marshal_error
ignore_stderr = nil
+ res = nil
end
- if res
+ if res and !(SystemExit === res)
if bt = res.backtrace
bt.each do |l|
l.sub!(/\A-:(\d+)/){"#{file}:#{line + $1.to_i}"}
@@ -141,7 +318,7 @@ eom
else
res.set_backtrace(caller)
end
- raise res unless SystemExit === res
+ raise res
end
# really is it succeed?
@@ -153,6 +330,27 @@ eom
raise marshal_error if marshal_error
end
+ # Run Ractor-related test without influencing the main test suite
+ def assert_ractor(src, args: [], require: nil, require_relative: nil, file: nil, line: nil, ignore_stderr: nil, **opt)
+ return unless defined?(Ractor)
+
+ require = "require #{require.inspect}" if require
+ if require_relative
+ dir = File.dirname(caller_locations[0,1][0].absolute_path)
+ full_path = File.expand_path(require_relative, dir)
+ require = "#{require}; require #{full_path.inspect}"
+ end
+
+ assert_separately(args, file, line, <<~RUBY, ignore_stderr: ignore_stderr, **opt)
+ #{require}
+ previous_verbose = $VERBOSE
+ $VERBOSE = nil
+ Ractor.new {} # trigger initial warning
+ $VERBOSE = previous_verbose
+ #{src}
+ RUBY
+ end
+
# :call-seq:
# assert_throw( tag, failure_message = nil, &block )
#
@@ -279,6 +477,121 @@ eom
ex
end
+ MINI_DIR = File.join(File.dirname(File.dirname(File.expand_path(__FILE__))), "minitest") #:nodoc:
+
+ # :call-seq:
+ # assert(test, [failure_message])
+ #
+ #Tests if +test+ is true.
+ #
+ #+msg+ may be a String or a Proc. If +msg+ is a String, it will be used
+ #as the failure message. Otherwise, the result of calling +msg+ will be
+ #used as the message if the assertion fails.
+ #
+ #If no +msg+ is given, a default message will be used.
+ #
+ # assert(false, "This was expected to be true")
+ def assert(test, *msgs)
+ case msg = msgs.first
+ when String, Proc
+ when nil
+ msgs.shift
+ else
+ bt = caller.reject { |s| s.start_with?(MINI_DIR) }
+ raise ArgumentError, "assertion message must be String or Proc, but #{msg.class} was given.", bt
+ end unless msgs.empty?
+ super
+ end
+
+ # :call-seq:
+ # assert_respond_to( object, method, failure_message = nil )
+ #
+ #Tests if the given Object responds to +method+.
+ #
+ #An optional failure message may be provided as the final argument.
+ #
+ # assert_respond_to("hello", :reverse) #Succeeds
+ # assert_respond_to("hello", :does_not_exist) #Fails
+ def assert_respond_to(obj, (meth, *priv), msg = nil)
+ unless priv.empty?
+ msg = message(msg) {
+ "Expected #{mu_pp(obj)} (#{obj.class}) to respond to ##{meth}#{" privately" if priv[0]}"
+ }
+ return assert obj.respond_to?(meth, *priv), msg
+ end
+ #get rid of overcounting
+ if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
+ return if obj.respond_to?(meth)
+ end
+ super(obj, meth, msg)
+ end
+
+ # :call-seq:
+ # assert_not_respond_to( object, method, failure_message = nil )
+ #
+ #Tests if the given Object does not respond to +method+.
+ #
+ #An optional failure message may be provided as the final argument.
+ #
+ # assert_not_respond_to("hello", :reverse) #Fails
+ # assert_not_respond_to("hello", :does_not_exist) #Succeeds
+ def assert_not_respond_to(obj, (meth, *priv), msg = nil)
+ unless priv.empty?
+ msg = message(msg) {
+ "Expected #{mu_pp(obj)} (#{obj.class}) to not respond to ##{meth}#{" privately" if priv[0]}"
+ }
+ return assert !obj.respond_to?(meth, *priv), msg
+ end
+ #get rid of overcounting
+ if caller_locations(1, 1)[0].path.start_with?(MINI_DIR)
+ return unless obj.respond_to?(meth)
+ end
+ refute_respond_to(obj, meth, msg)
+ end
+
+ # pattern_list is an array which contains regexp and :*.
+ # :* means any sequence.
+ #
+ # pattern_list is anchored.
+ # Use [:*, regexp, :*] for non-anchored match.
+ def assert_pattern_list(pattern_list, actual, message=nil)
+ rest = actual
+ anchored = true
+ pattern_list.each_with_index {|pattern, i|
+ if pattern == :*
+ anchored = false
+ else
+ if anchored
+ match = /\A#{pattern}/.match(rest)
+ else
+ match = pattern.match(rest)
+ end
+ unless match
+ msg = message(msg) {
+ expect_msg = "Expected #{mu_pp pattern}\n"
+ if /\n[^\n]/ =~ rest
+ actual_mesg = +"to match\n"
+ rest.scan(/.*\n+/) {
+ actual_mesg << ' ' << $&.inspect << "+\n"
+ }
+ actual_mesg.sub!(/\+\n\z/, '')
+ else
+ actual_mesg = "to match " + mu_pp(rest)
+ end
+ actual_mesg << "\nafter #{i} patterns with #{actual.length - rest.length} characters"
+ expect_msg + actual_mesg
+ }
+ assert false, msg
+ end
+ rest = match.post_match
+ anchored = true
+ end
+ }
+ if anchored
+ assert_equal("", rest)
+ end
+ end
+
def assert_warning(pat, msg = nil)
result = nil
stderr = EnvUtil.with_default_internal(pat.encoding) {
@@ -295,6 +608,20 @@ eom
assert_warning(*args) {$VERBOSE = false; yield}
end
+ def assert_deprecated_warning(mesg = /deprecated/)
+ assert_warning(mesg) do
+ Warning[:deprecated] = true
+ yield
+ end
+ end
+
+ def assert_deprecated_warn(mesg = /deprecated/)
+ assert_warn(mesg) do
+ Warning[:deprecated] = true
+ yield
+ end
+ end
+
class << (AssertFile = Struct.new(:failure_message).new)
include CoreAssertions
def assert_file_predicate(predicate, *args)
@@ -415,6 +742,22 @@ eom
super
end
end
+
+ def diff(exp, act)
+ require 'pp'
+ q = PP.new(+"")
+ q.guard_inspect_key do
+ q.group(2, "expected: ") do
+ q.pp exp
+ end
+ q.text q.newline
+ q.group(2, "actual: ") do
+ q.pp act
+ end
+ q.flush
+ end
+ q.output
+ end
end
end
end
diff --git a/tool/lib/test/unit/parallel.rb b/tool/lib/test/unit/parallel.rb
index 15f9ac575a..ccaf1a913a 100644
--- a/tool/lib/test/unit/parallel.rb
+++ b/tool/lib/test/unit/parallel.rb
@@ -43,10 +43,9 @@ module Test
th = Thread.new do
begin
while buf = (self.verbose ? i.gets : i.readpartial(1024))
- _report "p", buf
+ _report "p", buf or break
end
rescue IOError
- rescue Errno::EPIPE
end
end
@@ -77,9 +76,7 @@ module Test
result << ($: - @old_loadpath)
result << suite.name
- begin
- _report "done", Marshal.dump(result)
- rescue Errno::EPIPE; end
+ _report "done", Marshal.dump(result)
return result
ensure
MiniTest::Unit.output = orig_stdout
@@ -128,32 +125,25 @@ module Test
_run_suites MiniTest::Unit::TestCase.test_suites-suites, $2.to_sym
if @need_exit
- begin
- _report "bye"
- rescue Errno::EPIPE; end
+ _report "bye"
exit
else
_report "ready"
end
when /^quit$/
- begin
- _report "bye"
- rescue Errno::EPIPE; end
+ _report "bye"
exit
end
end
- rescue Errno::EPIPE
rescue Exception => e
- begin
- trace = e.backtrace || ['unknown method']
- err = ["#{trace.shift}: #{e.message} (#{e.class})"] + trace.map{|t| "\t" + t }
+ trace = e.backtrace || ['unknown method']
+ err = ["#{trace.shift}: #{e.message} (#{e.class})"] + trace.map{|t| "\t" + t }
- if @stdout
- _report "bye", Marshal.dump(err.join("\n"))
- else
- raise "failed to report a failure due to lack of @stdout"
- end
- rescue Errno::EPIPE;end
+ if @stdout
+ _report "bye", Marshal.dump(err.join("\n"))
+ else
+ raise "failed to report a failure due to lack of @stdout"
+ end
exit
ensure
@stdin.close if @stdin
@@ -163,6 +153,8 @@ module Test
def _report(res, *args) # :nodoc:
@stdout.write(args.empty? ? "#{res}\n" : "#{res} #{args.pack("m0")}\n")
+ true
+ rescue Errno::EPIPE
rescue TypeError => e
abort("#{e.inspect} in _report(#{res.inspect}, #{args.inspect})\n#{e.backtrace.join("\n")}")
end
@@ -206,6 +198,9 @@ if $0 == __FILE__
def on_parallel_worker?
true
end
+ def self.on_parallel_worker?
+ true
+ end
end
end
end
diff --git a/tool/lib/test/unit/testcase.rb b/tool/lib/test/unit/testcase.rb
index 58cfbcab99..68149a4880 100644
--- a/tool/lib/test/unit/testcase.rb
+++ b/tool/lib/test/unit/testcase.rb
@@ -18,10 +18,6 @@ module Test
super runner
end
- def self.test_order
- :sorted
- end
-
def self.method_added(name)
super
return unless name.to_s.start_with?("test_")
diff --git a/tool/lib/vcs.rb b/tool/lib/vcs.rb
index fcee91a7a4..c6d6cddded 100644
--- a/tool/lib/vcs.rb
+++ b/tool/lib/vcs.rb
@@ -23,101 +23,35 @@ def IO.pread(*args)
popen(*args) {|f|f.read}
end
-if RUBY_VERSION < "2.0"
- class IO
- @orig_popen = method(:popen)
-
- if defined?(fork)
- def self.popen(command, *rest, &block)
- if command.kind_of?(Hash)
- env = command
- command = rest.shift
- end
- opts = rest.last
- if opts.kind_of?(Hash)
- dir = opts.delete(:chdir)
- rest.pop if opts.empty?
- opts.delete(:external_encoding)
- end
-
- if block
- @orig_popen.call("-", *rest) do |f|
- if f
- yield(f)
- else
- Dir.chdir(dir) if dir
- ENV.replace(env) if env
- exec(*command)
- end
- end
- else
- f = @orig_popen.call("-", *rest)
- unless f
- Dir.chdir(dir) if dir
- ENV.replace(env) if env
- exec(*command)
- end
- f
- end
- end
- else
- require 'shellwords'
- def self.popen(command, *rest, &block)
- if command.kind_of?(Hash)
- env = command
- oldenv = ENV.to_hash
- command = rest.shift
- end
- opts = rest.last
- if opts.kind_of?(Hash)
- dir = opts.delete(:chdir)
- rest.pop if opts.empty?
- opts.delete(:external_encoding)
- end
-
- command = command.shelljoin if Array === command
- Dir.chdir(dir || ".") do
- ENV.replace(env) if env
- @orig_popen.call(command, *rest, &block)
- ENV.replace(oldenv) if oldenv
- end
- end
- end
- end
-else
- module DebugPOpen
- verbose, $VERBOSE = $VERBOSE, nil if RUBY_VERSION < "2.1"
- refine IO.singleton_class do
- def popen(*args)
- VCS::DEBUG_OUT.puts args.inspect if $DEBUG
- super
- end
- end
- ensure
- $VERBOSE = verbose unless verbose.nil?
- end
- using DebugPOpen
- module DebugSystem
- def system(*args)
+module DebugPOpen
+ refine IO.singleton_class do
+ def popen(*args)
VCS::DEBUG_OUT.puts args.inspect if $DEBUG
- exception = false
- opts = Hash.try_convert(args[-1])
- if RUBY_VERSION >= "2.6"
- unless opts
- opts = {}
- args << opts
- end
- exception = opts.fetch(:exception) {opts[:exception] = true}
- elsif opts
- exception = opts.delete(:exception) {true}
- args.pop if opts.empty?
- end
- ret = super(*args)
- raise "Command failed with status (#$?): #{args[0]}" if exception and !ret
- ret
+ super
end
end
end
+using DebugPOpen
+module DebugSystem
+ def system(*args)
+ VCS::DEBUG_OUT.puts args.inspect if $DEBUG
+ exception = false
+ opts = Hash.try_convert(args[-1])
+ if RUBY_VERSION >= "2.6"
+ unless opts
+ opts = {}
+ args << opts
+ end
+ exception = opts.fetch(:exception) {opts[:exception] = true}
+ elsif opts
+ exception = opts.delete(:exception) {true}
+ args.pop if opts.empty?
+ end
+ ret = super(*args)
+ raise "Command failed with status (#$?): #{args[0]}" if exception and !ret
+ ret
+ end
+end
class VCS
prepend(DebugSystem) if defined?(DebugSystem)
@@ -408,9 +342,7 @@ class VCS
range = [to || 'HEAD', (from ? from+1 : branch_beginning(url))].compact.join(':')
IO.popen({'TZ' => 'JST-9', 'LANG' => 'C', 'LC_ALL' => 'C'},
%W"#{COMMAND} log -r#{range} #{url}") do |r|
- open(path, 'w') do |w|
- IO.copy_stream(r, w)
- end
+ IO.copy_stream(r, path)
end
end
@@ -635,21 +567,36 @@ class VCS
cmd << date
cmd.concat(arg)
File.open(path, 'w') do |w|
+ w.print "-*- coding: utf-8 -*-\n\n"
cmd_pipe(env, cmd, chdir: @srcdir) do |r|
while s = r.gets("\ncommit ")
+ h, s = s.split(/^$/, 2)
+ h.gsub!(/^(?:Author|Date): /, ' \&')
if s.sub!(/\nNotes \(log-fix\):\n((?: +.*\n)+)/, '')
fix = $1
- h, s = s.split(/^$/, 2)
s = s.lines
fix.each_line do |x|
- if %r[^ +(\d+)s/(.+)/(.+)/] =~ x
- s[$1.to_i][$2] = $3
+ if %r[^ +(\d+)s/(.+)/(.*)/] =~ x
+ begin
+ s[$1.to_i][$2] = $3
+ rescue IndexError
+ message = ["format_changelog failed to replace #{$2.dump} with #{$3.dump} at #$1\n"]
+ from = [1, $1.to_i-2].max
+ to = [s.size-1, $1.to_i+2].min
+ s.each_with_index do |e, i|
+ next if i < from
+ break if to < i
+ message << "#{i}:#{e}"
+ end
+ raise message.join('')
+ end
end
end
- s = [h, s.join('')].join('')
+ s = s.join('')
end
s.gsub!(/ +\n/, "\n")
- w.print s
+ s.sub!(/^Notes:/, ' \&')
+ w.print h, s
end
end
end
@@ -658,7 +605,7 @@ class VCS
def format_changelog_as_svn(path, arg)
cmd = %W"#{COMMAND} log --topo-order --no-notes -z --format=%an%n%at%n%B"
cmd.concat(arg)
- open(path, 'w') do |w|
+ File.open(path, 'w') do |w|
sep = "-"*72 + "\n"
w.print sep
cmd_pipe(cmd) do |r|
@@ -724,7 +671,7 @@ class VCS
commits = cmd_read([COMMAND, "log", "--reverse", "--format=%H %ae %ce", "#{com}..@"], "rb").split("\n")
commits.each_with_index do |l, i|
- r, a, c = l.split
+ r, a, c = l.split(' ')
dcommit = [COMMAND, "svn", "dcommit"]
dcommit.insert(-2, "-n") if dryrun
dcommit << "--add-author-from" unless a == c
diff --git a/tool/lib/webrick.rb b/tool/lib/webrick.rb
new file mode 100644
index 0000000000..b854b68db4
--- /dev/null
+++ b/tool/lib/webrick.rb
@@ -0,0 +1,232 @@
+# frozen_string_literal: false
+##
+# = WEB server toolkit.
+#
+# WEBrick is an HTTP server toolkit that can be configured as an HTTPS server,
+# a proxy server, and a virtual-host server. WEBrick features complete
+# logging of both server operations and HTTP access. WEBrick supports both
+# basic and digest authentication in addition to algorithms not in RFC 2617.
+#
+# A WEBrick server can be composed of multiple WEBrick servers or servlets to
+# provide differing behavior on a per-host or per-path basis. WEBrick
+# includes servlets for handling CGI scripts, ERB pages, Ruby blocks and
+# directory listings.
+#
+# WEBrick also includes tools for daemonizing a process and starting a process
+# at a higher privilege level and dropping permissions.
+#
+# == Security
+#
+# *Warning:* WEBrick is not recommended for production. It only implements
+# basic security checks.
+#
+# == Starting an HTTP server
+#
+# To create a new WEBrick::HTTPServer that will listen to connections on port
+# 8000 and serve documents from the current user's public_html folder:
+#
+# require 'webrick'
+#
+# root = File.expand_path '~/public_html'
+# server = WEBrick::HTTPServer.new :Port => 8000, :DocumentRoot => root
+#
+# To run the server you will need to provide a suitable shutdown hook as
+# starting the server blocks the current thread:
+#
+# trap 'INT' do server.shutdown end
+#
+# server.start
+#
+# == Custom Behavior
+#
+# The easiest way to have a server perform custom operations is through
+# WEBrick::HTTPServer#mount_proc. The block given will be called with a
+# WEBrick::HTTPRequest with request info and a WEBrick::HTTPResponse which
+# must be filled in appropriately:
+#
+# server.mount_proc '/' do |req, res|
+# res.body = 'Hello, world!'
+# end
+#
+# Remember that +server.mount_proc+ must precede +server.start+.
+#
+# == Servlets
+#
+# Advanced custom behavior can be obtained through mounting a subclass of
+# WEBrick::HTTPServlet::AbstractServlet. Servlets provide more modularity
+# when writing an HTTP server than mount_proc allows. Here is a simple
+# servlet:
+#
+# class Simple < WEBrick::HTTPServlet::AbstractServlet
+# def do_GET request, response
+# status, content_type, body = do_stuff_with request
+#
+# response.status = 200
+# response['Content-Type'] = 'text/plain'
+# response.body = 'Hello, World!'
+# end
+# end
+#
+# To initialize the servlet you mount it on the server:
+#
+# server.mount '/simple', Simple
+#
+# See WEBrick::HTTPServlet::AbstractServlet for more details.
+#
+# == Virtual Hosts
+#
+# A server can act as a virtual host for multiple host names. After creating
+# the listening host, additional hosts that do not listen can be created and
+# attached as virtual hosts:
+#
+# server = WEBrick::HTTPServer.new # ...
+#
+# vhost = WEBrick::HTTPServer.new :ServerName => 'vhost.example',
+# :DoNotListen => true, # ...
+# vhost.mount '/', ...
+#
+# server.virtual_host vhost
+#
+# If no +:DocumentRoot+ is provided and no servlets or procs are mounted on the
+# main server it will return 404 for all URLs.
+#
+# == HTTPS
+#
+# To create an HTTPS server you only need to enable SSL and provide an SSL
+# certificate name:
+#
+# require 'webrick'
+# require 'webrick/https'
+#
+# cert_name = [
+# %w[CN localhost],
+# ]
+#
+# server = WEBrick::HTTPServer.new(:Port => 8000,
+# :SSLEnable => true,
+# :SSLCertName => cert_name)
+#
+# This will start the server with a self-generated self-signed certificate.
+# The certificate will be changed every time the server is restarted.
+#
+# To create a server with a pre-determined key and certificate you can provide
+# them:
+#
+# require 'webrick'
+# require 'webrick/https'
+# require 'openssl'
+#
+# cert = OpenSSL::X509::Certificate.new File.read '/path/to/cert.pem'
+# pkey = OpenSSL::PKey::RSA.new File.read '/path/to/pkey.pem'
+#
+# server = WEBrick::HTTPServer.new(:Port => 8000,
+# :SSLEnable => true,
+# :SSLCertificate => cert,
+# :SSLPrivateKey => pkey)
+#
+# == Proxy Server
+#
+# WEBrick can act as a proxy server:
+#
+# require 'webrick'
+# require 'webrick/httpproxy'
+#
+# proxy = WEBrick::HTTPProxyServer.new :Port => 8000
+#
+# trap 'INT' do proxy.shutdown end
+#
+# See WEBrick::HTTPProxy for further details including modifying proxied
+# responses.
+#
+# == Basic and Digest authentication
+#
+# WEBrick provides both Basic and Digest authentication for regular and proxy
+# servers. See WEBrick::HTTPAuth, WEBrick::HTTPAuth::BasicAuth and
+# WEBrick::HTTPAuth::DigestAuth.
+#
+# == WEBrick as a daemonized Web Server
+#
+# WEBrick can be run as a daemonized server for small loads.
+#
+# === Daemonizing
+#
+# To start a WEBrick server as a daemon simple run WEBrick::Daemon.start
+# before starting the server.
+#
+# === Dropping Permissions
+#
+# WEBrick can be started as one user to gain permission to bind to port 80 or
+# 443 for serving HTTP or HTTPS traffic then can drop these permissions for
+# regular operation. To listen on all interfaces for HTTP traffic:
+#
+# sockets = WEBrick::Utils.create_listeners nil, 80
+#
+# Then drop privileges:
+#
+# WEBrick::Utils.su 'www'
+#
+# Then create a server that does not listen by default:
+#
+# server = WEBrick::HTTPServer.new :DoNotListen => true, # ...
+#
+# Then overwrite the listening sockets with the port 80 sockets:
+#
+# server.listeners.replace sockets
+#
+# === Logging
+#
+# WEBrick can separately log server operations and end-user access. For
+# server operations:
+#
+# log_file = File.open '/var/log/webrick.log', 'a+'
+# log = WEBrick::Log.new log_file
+#
+# For user access logging:
+#
+# access_log = [
+# [log_file, WEBrick::AccessLog::COMBINED_LOG_FORMAT],
+# ]
+#
+# server = WEBrick::HTTPServer.new :Logger => log, :AccessLog => access_log
+#
+# See WEBrick::AccessLog for further log formats.
+#
+# === Log Rotation
+#
+# To rotate logs in WEBrick on a HUP signal (like syslogd can send), open the
+# log file in 'a+' mode (as above) and trap 'HUP' to reopen the log file:
+#
+# trap 'HUP' do log_file.reopen '/path/to/webrick.log', 'a+'
+#
+# == Copyright
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+#
+# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#--
+# $IPR: webrick.rb,v 1.12 2002/10/01 17:16:31 gotoyuzo Exp $
+
+module WEBrick
+end
+
+require 'webrick/compat.rb'
+
+require 'webrick/version.rb'
+require 'webrick/config.rb'
+require 'webrick/log.rb'
+require 'webrick/server.rb'
+require_relative 'webrick/utils.rb'
+require 'webrick/accesslog'
+
+require 'webrick/htmlutils.rb'
+require 'webrick/httputils.rb'
+require 'webrick/cookie.rb'
+require 'webrick/httpversion.rb'
+require 'webrick/httpstatus.rb'
+require 'webrick/httprequest.rb'
+require 'webrick/httpresponse.rb'
+require 'webrick/httpserver.rb'
+require 'webrick/httpservlet.rb'
+require 'webrick/httpauth.rb'
diff --git a/lib/webrick/.document b/tool/lib/webrick/.document
index c62f89083b..c62f89083b 100644
--- a/lib/webrick/.document
+++ b/tool/lib/webrick/.document
diff --git a/lib/webrick/accesslog.rb b/tool/lib/webrick/accesslog.rb
index e4849637f3..e4849637f3 100644
--- a/lib/webrick/accesslog.rb
+++ b/tool/lib/webrick/accesslog.rb
diff --git a/lib/webrick/cgi.rb b/tool/lib/webrick/cgi.rb
index bb0ae2fc84..bb0ae2fc84 100644
--- a/lib/webrick/cgi.rb
+++ b/tool/lib/webrick/cgi.rb
diff --git a/lib/webrick/compat.rb b/tool/lib/webrick/compat.rb
index c497a1933c..c497a1933c 100644
--- a/lib/webrick/compat.rb
+++ b/tool/lib/webrick/compat.rb
diff --git a/lib/webrick/config.rb b/tool/lib/webrick/config.rb
index 9f2ab44f49..9f2ab44f49 100644
--- a/lib/webrick/config.rb
+++ b/tool/lib/webrick/config.rb
diff --git a/lib/webrick/cookie.rb b/tool/lib/webrick/cookie.rb
index 5fd3bfb228..5fd3bfb228 100644
--- a/lib/webrick/cookie.rb
+++ b/tool/lib/webrick/cookie.rb
diff --git a/lib/webrick/htmlutils.rb b/tool/lib/webrick/htmlutils.rb
index ed9f4ac0d3..ed9f4ac0d3 100644
--- a/lib/webrick/htmlutils.rb
+++ b/tool/lib/webrick/htmlutils.rb
diff --git a/lib/webrick/httpauth.rb b/tool/lib/webrick/httpauth.rb
index f8bf09a6f1..f8bf09a6f1 100644
--- a/lib/webrick/httpauth.rb
+++ b/tool/lib/webrick/httpauth.rb
diff --git a/tool/lib/webrick/httpauth/authenticator.rb b/tool/lib/webrick/httpauth/authenticator.rb
new file mode 100644
index 0000000000..8f0eaa3aca
--- /dev/null
+++ b/tool/lib/webrick/httpauth/authenticator.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: false
+#--
+# httpauth/authenticator.rb -- Authenticator mix-in module.
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: authenticator.rb,v 1.3 2003/02/20 07:15:47 gotoyuzo Exp $
+
+module WEBrick
+ module HTTPAuth
+
+ ##
+ # Module providing generic support for both Digest and Basic
+ # authentication schemes.
+
+ module Authenticator
+
+ RequestField = "Authorization" # :nodoc:
+ ResponseField = "WWW-Authenticate" # :nodoc:
+ ResponseInfoField = "Authentication-Info" # :nodoc:
+ AuthException = HTTPStatus::Unauthorized # :nodoc:
+
+ ##
+ # Method of authentication, must be overridden by the including class
+
+ AuthScheme = nil
+
+ ##
+ # The realm this authenticator covers
+
+ attr_reader :realm
+
+ ##
+ # The user database for this authenticator
+
+ attr_reader :userdb
+
+ ##
+ # The logger for this authenticator
+
+ attr_reader :logger
+
+ private
+
+ # :stopdoc:
+
+ ##
+ # Initializes the authenticator from +config+
+
+ def check_init(config)
+ [:UserDB, :Realm].each{|sym|
+ unless config[sym]
+ raise ArgumentError, "Argument #{sym.inspect} missing."
+ end
+ }
+ @realm = config[:Realm]
+ @userdb = config[:UserDB]
+ @logger = config[:Logger] || Log::new($stderr)
+ @reload_db = config[:AutoReloadUserDB]
+ @request_field = self::class::RequestField
+ @response_field = self::class::ResponseField
+ @resp_info_field = self::class::ResponseInfoField
+ @auth_exception = self::class::AuthException
+ @auth_scheme = self::class::AuthScheme
+ end
+
+ ##
+ # Ensures +req+ has credentials that can be authenticated.
+
+ def check_scheme(req)
+ unless credentials = req[@request_field]
+ error("no credentials in the request.")
+ return nil
+ end
+ unless match = /^#{@auth_scheme}\s+/i.match(credentials)
+ error("invalid scheme in %s.", credentials)
+ info("%s: %s", @request_field, credentials) if $DEBUG
+ return nil
+ end
+ return match.post_match
+ end
+
+ def log(meth, fmt, *args)
+ msg = format("%s %s: ", @auth_scheme, @realm)
+ msg << fmt % args
+ @logger.__send__(meth, msg)
+ end
+
+ def error(fmt, *args)
+ if @logger.error?
+ log(:error, fmt, *args)
+ end
+ end
+
+ def info(fmt, *args)
+ if @logger.info?
+ log(:info, fmt, *args)
+ end
+ end
+
+ # :startdoc:
+ end
+
+ ##
+ # Module providing generic support for both Digest and Basic
+ # authentication schemes for proxies.
+
+ module ProxyAuthenticator
+ RequestField = "Proxy-Authorization" # :nodoc:
+ ResponseField = "Proxy-Authenticate" # :nodoc:
+ InfoField = "Proxy-Authentication-Info" # :nodoc:
+ AuthException = HTTPStatus::ProxyAuthenticationRequired # :nodoc:
+ end
+ end
+end
diff --git a/lib/webrick/httpauth/basicauth.rb b/tool/lib/webrick/httpauth/basicauth.rb
index 7d0a9cfc8f..7d0a9cfc8f 100644
--- a/lib/webrick/httpauth/basicauth.rb
+++ b/tool/lib/webrick/httpauth/basicauth.rb
diff --git a/lib/webrick/httpauth/digestauth.rb b/tool/lib/webrick/httpauth/digestauth.rb
index 3cf12899d2..3cf12899d2 100644
--- a/lib/webrick/httpauth/digestauth.rb
+++ b/tool/lib/webrick/httpauth/digestauth.rb
diff --git a/lib/webrick/httpauth/htdigest.rb b/tool/lib/webrick/httpauth/htdigest.rb
index 93b18e2c75..93b18e2c75 100644
--- a/lib/webrick/httpauth/htdigest.rb
+++ b/tool/lib/webrick/httpauth/htdigest.rb
diff --git a/lib/webrick/httpauth/htgroup.rb b/tool/lib/webrick/httpauth/htgroup.rb
index e06c441b18..e06c441b18 100644
--- a/lib/webrick/httpauth/htgroup.rb
+++ b/tool/lib/webrick/httpauth/htgroup.rb
diff --git a/lib/webrick/httpauth/htpasswd.rb b/tool/lib/webrick/httpauth/htpasswd.rb
index abca30532e..abca30532e 100644
--- a/lib/webrick/httpauth/htpasswd.rb
+++ b/tool/lib/webrick/httpauth/htpasswd.rb
diff --git a/lib/webrick/httpauth/userdb.rb b/tool/lib/webrick/httpauth/userdb.rb
index 7a17715cdf..7a17715cdf 100644
--- a/lib/webrick/httpauth/userdb.rb
+++ b/tool/lib/webrick/httpauth/userdb.rb
diff --git a/tool/lib/webrick/httpproxy.rb b/tool/lib/webrick/httpproxy.rb
new file mode 100644
index 0000000000..7607c3df88
--- /dev/null
+++ b/tool/lib/webrick/httpproxy.rb
@@ -0,0 +1,354 @@
+# frozen_string_literal: false
+#
+# httpproxy.rb -- HTTPProxy Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2002 GOTO Kentaro
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httpproxy.rb,v 1.18 2003/03/08 18:58:10 gotoyuzo Exp $
+# $kNotwork: straw.rb,v 1.3 2002/02/12 15:13:07 gotoken Exp $
+
+require_relative "httpserver"
+require "net/http"
+
+module WEBrick
+
+ NullReader = Object.new # :nodoc:
+ class << NullReader # :nodoc:
+ def read(*args)
+ nil
+ end
+ alias gets read
+ end
+
+ FakeProxyURI = Object.new # :nodoc:
+ class << FakeProxyURI # :nodoc:
+ def method_missing(meth, *args)
+ if %w(scheme host port path query userinfo).member?(meth.to_s)
+ return nil
+ end
+ super
+ end
+ end
+
+ # :startdoc:
+
+ ##
+ # An HTTP Proxy server which proxies GET, HEAD and POST requests.
+ #
+ # To create a simple proxy server:
+ #
+ # require 'webrick'
+ # require 'webrick/httpproxy'
+ #
+ # proxy = WEBrick::HTTPProxyServer.new Port: 8000
+ #
+ # trap 'INT' do proxy.shutdown end
+ # trap 'TERM' do proxy.shutdown end
+ #
+ # proxy.start
+ #
+ # See ::new for proxy-specific configuration items.
+ #
+ # == Modifying proxied responses
+ #
+ # To modify content the proxy server returns use the +:ProxyContentHandler+
+ # option:
+ #
+ # handler = proc do |req, res|
+ # if res['content-type'] == 'text/plain' then
+ # res.body << "\nThis content was proxied!\n"
+ # end
+ # end
+ #
+ # proxy =
+ # WEBrick::HTTPProxyServer.new Port: 8000, ProxyContentHandler: handler
+
+ class HTTPProxyServer < HTTPServer
+
+ ##
+ # Proxy server configurations. The proxy server handles the following
+ # configuration items in addition to those supported by HTTPServer:
+ #
+ # :ProxyAuthProc:: Called with a request and response to authorize a
+ # request
+ # :ProxyVia:: Appended to the via header
+ # :ProxyURI:: The proxy server's URI
+ # :ProxyContentHandler:: Called with a request and response and allows
+ # modification of the response
+ # :ProxyTimeout:: Sets the proxy timeouts to 30 seconds for open and 60
+ # seconds for read operations
+
+ def initialize(config={}, default=Config::HTTP)
+ super(config, default)
+ c = @config
+ @via = "#{c[:HTTPVersion]} #{c[:ServerName]}:#{c[:Port]}"
+ end
+
+ # :stopdoc:
+ def service(req, res)
+ if req.request_method == "CONNECT"
+ do_CONNECT(req, res)
+ elsif req.unparsed_uri =~ %r!^http://!
+ proxy_service(req, res)
+ else
+ super(req, res)
+ end
+ end
+
+ def proxy_auth(req, res)
+ if proc = @config[:ProxyAuthProc]
+ proc.call(req, res)
+ end
+ req.header.delete("proxy-authorization")
+ end
+
+ def proxy_uri(req, res)
+ # should return upstream proxy server's URI
+ return @config[:ProxyURI]
+ end
+
+ def proxy_service(req, res)
+ # Proxy Authentication
+ proxy_auth(req, res)
+
+ begin
+ public_send("do_#{req.request_method}", req, res)
+ rescue NoMethodError
+ raise HTTPStatus::MethodNotAllowed,
+ "unsupported method `#{req.request_method}'."
+ rescue => err
+ logger.debug("#{err.class}: #{err.message}")
+ raise HTTPStatus::ServiceUnavailable, err.message
+ end
+
+ # Process contents
+ if handler = @config[:ProxyContentHandler]
+ handler.call(req, res)
+ end
+ end
+
+ def do_CONNECT(req, res)
+ # Proxy Authentication
+ proxy_auth(req, res)
+
+ ua = Thread.current[:WEBrickSocket] # User-Agent
+ raise HTTPStatus::InternalServerError,
+ "[BUG] cannot get socket" unless ua
+
+ host, port = req.unparsed_uri.split(":", 2)
+ # Proxy authentication for upstream proxy server
+ if proxy = proxy_uri(req, res)
+ proxy_request_line = "CONNECT #{host}:#{port} HTTP/1.0"
+ if proxy.userinfo
+ credentials = "Basic " + [proxy.userinfo].pack("m0")
+ end
+ host, port = proxy.host, proxy.port
+ end
+
+ begin
+ @logger.debug("CONNECT: upstream proxy is `#{host}:#{port}'.")
+ os = TCPSocket.new(host, port) # origin server
+
+ if proxy
+ @logger.debug("CONNECT: sending a Request-Line")
+ os << proxy_request_line << CRLF
+ @logger.debug("CONNECT: > #{proxy_request_line}")
+ if credentials
+ @logger.debug("CONNECT: sending credentials")
+ os << "Proxy-Authorization: " << credentials << CRLF
+ end
+ os << CRLF
+ proxy_status_line = os.gets(LF)
+ @logger.debug("CONNECT: read Status-Line from the upstream server")
+ @logger.debug("CONNECT: < #{proxy_status_line}")
+ if %r{^HTTP/\d+\.\d+\s+200\s*} =~ proxy_status_line
+ while line = os.gets(LF)
+ break if /\A(#{CRLF}|#{LF})\z/om =~ line
+ end
+ else
+ raise HTTPStatus::BadGateway
+ end
+ end
+ @logger.debug("CONNECT #{host}:#{port}: succeeded")
+ res.status = HTTPStatus::RC_OK
+ rescue => ex
+ @logger.debug("CONNECT #{host}:#{port}: failed `#{ex.message}'")
+ res.set_error(ex)
+ raise HTTPStatus::EOFError
+ ensure
+ if handler = @config[:ProxyContentHandler]
+ handler.call(req, res)
+ end
+ res.send_response(ua)
+ access_log(@config, req, res)
+
+ # Should clear request-line not to send the response twice.
+ # see: HTTPServer#run
+ req.parse(NullReader) rescue nil
+ end
+
+ begin
+ while fds = IO::select([ua, os])
+ if fds[0].member?(ua)
+ buf = ua.readpartial(1024);
+ @logger.debug("CONNECT: #{buf.bytesize} byte from User-Agent")
+ os.write(buf)
+ elsif fds[0].member?(os)
+ buf = os.readpartial(1024);
+ @logger.debug("CONNECT: #{buf.bytesize} byte from #{host}:#{port}")
+ ua.write(buf)
+ end
+ end
+ rescue
+ os.close
+ @logger.debug("CONNECT #{host}:#{port}: closed")
+ end
+
+ raise HTTPStatus::EOFError
+ end
+
+ def do_GET(req, res)
+ perform_proxy_request(req, res, Net::HTTP::Get)
+ end
+
+ def do_HEAD(req, res)
+ perform_proxy_request(req, res, Net::HTTP::Head)
+ end
+
+ def do_POST(req, res)
+ perform_proxy_request(req, res, Net::HTTP::Post, req.body_reader)
+ end
+
+ def do_OPTIONS(req, res)
+ res['allow'] = "GET,HEAD,POST,OPTIONS,CONNECT"
+ end
+
+ private
+
+ # Some header fields should not be transferred.
+ HopByHop = %w( connection keep-alive proxy-authenticate upgrade
+ proxy-authorization te trailers transfer-encoding )
+ ShouldNotTransfer = %w( set-cookie proxy-connection )
+ def split_field(f) f ? f.split(/,\s+/).collect{|i| i.downcase } : [] end
+
+ def choose_header(src, dst)
+ connections = split_field(src['connection'])
+ src.each{|key, value|
+ key = key.downcase
+ if HopByHop.member?(key) || # RFC2616: 13.5.1
+ connections.member?(key) || # RFC2616: 14.10
+ ShouldNotTransfer.member?(key) # pragmatics
+ @logger.debug("choose_header: `#{key}: #{value}'")
+ next
+ end
+ dst[key] = value
+ }
+ end
+
+ # Net::HTTP is stupid about the multiple header fields.
+ # Here is workaround:
+ def set_cookie(src, dst)
+ if str = src['set-cookie']
+ cookies = []
+ str.split(/,\s*/).each{|token|
+ if /^[^=]+;/o =~ token
+ cookies[-1] << ", " << token
+ elsif /=/o =~ token
+ cookies << token
+ else
+ cookies[-1] << ", " << token
+ end
+ }
+ dst.cookies.replace(cookies)
+ end
+ end
+
+ def set_via(h)
+ if @config[:ProxyVia]
+ if h['via']
+ h['via'] << ", " << @via
+ else
+ h['via'] = @via
+ end
+ end
+ end
+
+ def setup_proxy_header(req, res)
+ # Choose header fields to transfer
+ header = Hash.new
+ choose_header(req, header)
+ set_via(header)
+ return header
+ end
+
+ def setup_upstream_proxy_authentication(req, res, header)
+ if upstream = proxy_uri(req, res)
+ if upstream.userinfo
+ header['proxy-authorization'] =
+ "Basic " + [upstream.userinfo].pack("m0")
+ end
+ return upstream
+ end
+ return FakeProxyURI
+ end
+
+ def create_net_http(uri, upstream)
+ Net::HTTP.new(uri.host, uri.port, upstream.host, upstream.port)
+ end
+
+ def perform_proxy_request(req, res, req_class, body_stream = nil)
+ uri = req.request_uri
+ path = uri.path.dup
+ path << "?" << uri.query if uri.query
+ header = setup_proxy_header(req, res)
+ upstream = setup_upstream_proxy_authentication(req, res, header)
+
+ body_tmp = []
+ http = create_net_http(uri, upstream)
+ req_fib = Fiber.new do
+ http.start do
+ if @config[:ProxyTimeout]
+ ################################## these issues are
+ http.open_timeout = 30 # secs # necessary (maybe because
+ http.read_timeout = 60 # secs # Ruby's bug, but why?)
+ ##################################
+ end
+ if body_stream && req['transfer-encoding'] =~ /\bchunked\b/i
+ header['Transfer-Encoding'] = 'chunked'
+ end
+ http_req = req_class.new(path, header)
+ http_req.body_stream = body_stream if body_stream
+ http.request(http_req) do |response|
+ # Persistent connection requirements are mysterious for me.
+ # So I will close the connection in every response.
+ res['proxy-connection'] = "close"
+ res['connection'] = "close"
+
+ # stream Net::HTTP::HTTPResponse to WEBrick::HTTPResponse
+ res.status = response.code.to_i
+ res.chunked = response.chunked?
+ choose_header(response, res)
+ set_cookie(response, res)
+ set_via(res)
+ response.read_body do |buf|
+ body_tmp << buf
+ Fiber.yield # wait for res.body Proc#call
+ end
+ end # http.request
+ end
+ end
+ req_fib.resume # read HTTP response headers and first chunk of the body
+ res.body = ->(socket) do
+ while buf = body_tmp.shift
+ socket.write(buf)
+ buf.clear
+ req_fib.resume # continue response.read_body
+ end
+ end
+ end
+ # :stopdoc:
+ end
+end
diff --git a/tool/lib/webrick/httprequest.rb b/tool/lib/webrick/httprequest.rb
new file mode 100644
index 0000000000..d34eac7ecf
--- /dev/null
+++ b/tool/lib/webrick/httprequest.rb
@@ -0,0 +1,636 @@
+# frozen_string_literal: false
+#
+# httprequest.rb -- HTTPRequest Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httprequest.rb,v 1.64 2003/07/13 17:18:22 gotoyuzo Exp $
+
+require 'fiber'
+require 'uri'
+require_relative 'httpversion'
+require_relative 'httpstatus'
+require_relative 'httputils'
+require_relative 'cookie'
+
+module WEBrick
+
+ ##
+ # An HTTP request. This is consumed by service and do_* methods in
+ # WEBrick servlets
+
+ class HTTPRequest
+
+ BODY_CONTAINABLE_METHODS = [ "POST", "PUT" ] # :nodoc:
+
+ # :section: Request line
+
+ ##
+ # The complete request line such as:
+ #
+ # GET / HTTP/1.1
+
+ attr_reader :request_line
+
+ ##
+ # The request method, GET, POST, PUT, etc.
+
+ attr_reader :request_method
+
+ ##
+ # The unparsed URI of the request
+
+ attr_reader :unparsed_uri
+
+ ##
+ # The HTTP version of the request
+
+ attr_reader :http_version
+
+ # :section: Request-URI
+
+ ##
+ # The parsed URI of the request
+
+ attr_reader :request_uri
+
+ ##
+ # The request path
+
+ attr_reader :path
+
+ ##
+ # The script name (CGI variable)
+
+ attr_accessor :script_name
+
+ ##
+ # The path info (CGI variable)
+
+ attr_accessor :path_info
+
+ ##
+ # The query from the URI of the request
+
+ attr_accessor :query_string
+
+ # :section: Header and entity body
+
+ ##
+ # The raw header of the request
+
+ attr_reader :raw_header
+
+ ##
+ # The parsed header of the request
+
+ attr_reader :header
+
+ ##
+ # The parsed request cookies
+
+ attr_reader :cookies
+
+ ##
+ # The Accept header value
+
+ attr_reader :accept
+
+ ##
+ # The Accept-Charset header value
+
+ attr_reader :accept_charset
+
+ ##
+ # The Accept-Encoding header value
+
+ attr_reader :accept_encoding
+
+ ##
+ # The Accept-Language header value
+
+ attr_reader :accept_language
+
+ # :section:
+
+ ##
+ # The remote user (CGI variable)
+
+ attr_accessor :user
+
+ ##
+ # The socket address of the server
+
+ attr_reader :addr
+
+ ##
+ # The socket address of the client
+
+ attr_reader :peeraddr
+
+ ##
+ # Hash of request attributes
+
+ attr_reader :attributes
+
+ ##
+ # Is this a keep-alive connection?
+
+ attr_reader :keep_alive
+
+ ##
+ # The local time this request was received
+
+ attr_reader :request_time
+
+ ##
+ # Creates a new HTTP request. WEBrick::Config::HTTP is the default
+ # configuration.
+
+ def initialize(config)
+ @config = config
+ @buffer_size = @config[:InputBufferSize]
+ @logger = config[:Logger]
+
+ @request_line = @request_method =
+ @unparsed_uri = @http_version = nil
+
+ @request_uri = @host = @port = @path = nil
+ @script_name = @path_info = nil
+ @query_string = nil
+ @query = nil
+ @form_data = nil
+
+ @raw_header = Array.new
+ @header = nil
+ @cookies = []
+ @accept = []
+ @accept_charset = []
+ @accept_encoding = []
+ @accept_language = []
+ @body = ""
+
+ @addr = @peeraddr = nil
+ @attributes = {}
+ @user = nil
+ @keep_alive = false
+ @request_time = nil
+
+ @remaining_size = nil
+ @socket = nil
+
+ @forwarded_proto = @forwarded_host = @forwarded_port =
+ @forwarded_server = @forwarded_for = nil
+ end
+
+ ##
+ # Parses a request from +socket+. This is called internally by
+ # WEBrick::HTTPServer.
+
+ def parse(socket=nil)
+ @socket = socket
+ begin
+ @peeraddr = socket.respond_to?(:peeraddr) ? socket.peeraddr : []
+ @addr = socket.respond_to?(:addr) ? socket.addr : []
+ rescue Errno::ENOTCONN
+ raise HTTPStatus::EOFError
+ end
+
+ read_request_line(socket)
+ if @http_version.major > 0
+ read_header(socket)
+ @header['cookie'].each{|cookie|
+ @cookies += Cookie::parse(cookie)
+ }
+ @accept = HTTPUtils.parse_qvalues(self['accept'])
+ @accept_charset = HTTPUtils.parse_qvalues(self['accept-charset'])
+ @accept_encoding = HTTPUtils.parse_qvalues(self['accept-encoding'])
+ @accept_language = HTTPUtils.parse_qvalues(self['accept-language'])
+ end
+ return if @request_method == "CONNECT"
+ return if @unparsed_uri == "*"
+
+ begin
+ setup_forwarded_info
+ @request_uri = parse_uri(@unparsed_uri)
+ @path = HTTPUtils::unescape(@request_uri.path)
+ @path = HTTPUtils::normalize_path(@path)
+ @host = @request_uri.host
+ @port = @request_uri.port
+ @query_string = @request_uri.query
+ @script_name = ""
+ @path_info = @path.dup
+ rescue
+ raise HTTPStatus::BadRequest, "bad URI `#{@unparsed_uri}'."
+ end
+
+ if /\Aclose\z/io =~ self["connection"]
+ @keep_alive = false
+ elsif /\Akeep-alive\z/io =~ self["connection"]
+ @keep_alive = true
+ elsif @http_version < "1.1"
+ @keep_alive = false
+ else
+ @keep_alive = true
+ end
+ end
+
+ ##
+ # Generate HTTP/1.1 100 continue response if the client expects it,
+ # otherwise does nothing.
+
+ def continue # :nodoc:
+ if self['expect'] == '100-continue' && @config[:HTTPVersion] >= "1.1"
+ @socket << "HTTP/#{@config[:HTTPVersion]} 100 continue#{CRLF}#{CRLF}"
+ @header.delete('expect')
+ end
+ end
+
+ ##
+ # Returns the request body.
+
+ def body(&block) # :yields: body_chunk
+ block ||= Proc.new{|chunk| @body << chunk }
+ read_body(@socket, block)
+ @body.empty? ? nil : @body
+ end
+
+ ##
+ # Prepares the HTTPRequest object for use as the
+ # source for IO.copy_stream
+
+ def body_reader
+ @body_tmp = []
+ @body_rd = Fiber.new do
+ body do |buf|
+ @body_tmp << buf
+ Fiber.yield
+ end
+ end
+ @body_rd.resume # grab the first chunk and yield
+ self
+ end
+
+ # for IO.copy_stream.
+ def readpartial(size, buf = ''.b) # :nodoc
+ res = @body_tmp.shift or raise EOFError, 'end of file reached'
+ if res.length > size
+ @body_tmp.unshift(res[size..-1])
+ res = res[0..size - 1]
+ end
+ buf.replace(res)
+ res.clear
+ # get more chunks - check alive? because we can take a partial chunk
+ @body_rd.resume if @body_rd.alive?
+ buf
+ end
+
+ ##
+ # Request query as a Hash
+
+ def query
+ unless @query
+ parse_query()
+ end
+ @query
+ end
+
+ ##
+ # The content-length header
+
+ def content_length
+ return Integer(self['content-length'])
+ end
+
+ ##
+ # The content-type header
+
+ def content_type
+ return self['content-type']
+ end
+
+ ##
+ # Retrieves +header_name+
+
+ def [](header_name)
+ if @header
+ value = @header[header_name.downcase]
+ value.empty? ? nil : value.join(", ")
+ end
+ end
+
+ ##
+ # Iterates over the request headers
+
+ def each
+ if @header
+ @header.each{|k, v|
+ value = @header[k]
+ yield(k, value.empty? ? nil : value.join(", "))
+ }
+ end
+ end
+
+ ##
+ # The host this request is for
+
+ def host
+ return @forwarded_host || @host
+ end
+
+ ##
+ # The port this request is for
+
+ def port
+ return @forwarded_port || @port
+ end
+
+ ##
+ # The server name this request is for
+
+ def server_name
+ return @forwarded_server || @config[:ServerName]
+ end
+
+ ##
+ # The client's IP address
+
+ def remote_ip
+ return self["client-ip"] || @forwarded_for || @peeraddr[3]
+ end
+
+ ##
+ # Is this an SSL request?
+
+ def ssl?
+ return @request_uri.scheme == "https"
+ end
+
+ ##
+ # Should the connection this request was made on be kept alive?
+
+ def keep_alive?
+ @keep_alive
+ end
+
+ def to_s # :nodoc:
+ ret = @request_line.dup
+ @raw_header.each{|line| ret << line }
+ ret << CRLF
+ ret << body if body
+ ret
+ end
+
+ ##
+ # Consumes any remaining body and updates keep-alive status
+
+ def fixup() # :nodoc:
+ begin
+ body{|chunk| } # read remaining body
+ rescue HTTPStatus::Error => ex
+ @logger.error("HTTPRequest#fixup: #{ex.class} occurred.")
+ @keep_alive = false
+ rescue => ex
+ @logger.error(ex)
+ @keep_alive = false
+ end
+ end
+
+ # This method provides the metavariables defined by the revision 3
+ # of "The WWW Common Gateway Interface Version 1.1"
+ # To browse the current document of CGI Version 1.1, see below:
+ # http://tools.ietf.org/html/rfc3875
+
+ def meta_vars
+ meta = Hash.new
+
+ cl = self["Content-Length"]
+ ct = self["Content-Type"]
+ meta["CONTENT_LENGTH"] = cl if cl.to_i > 0
+ meta["CONTENT_TYPE"] = ct.dup if ct
+ meta["GATEWAY_INTERFACE"] = "CGI/1.1"
+ meta["PATH_INFO"] = @path_info ? @path_info.dup : ""
+ #meta["PATH_TRANSLATED"] = nil # no plan to be provided
+ meta["QUERY_STRING"] = @query_string ? @query_string.dup : ""
+ meta["REMOTE_ADDR"] = @peeraddr[3]
+ meta["REMOTE_HOST"] = @peeraddr[2]
+ #meta["REMOTE_IDENT"] = nil # no plan to be provided
+ meta["REMOTE_USER"] = @user
+ meta["REQUEST_METHOD"] = @request_method.dup
+ meta["REQUEST_URI"] = @request_uri.to_s
+ meta["SCRIPT_NAME"] = @script_name.dup
+ meta["SERVER_NAME"] = @host
+ meta["SERVER_PORT"] = @port.to_s
+ meta["SERVER_PROTOCOL"] = "HTTP/" + @config[:HTTPVersion].to_s
+ meta["SERVER_SOFTWARE"] = @config[:ServerSoftware].dup
+
+ self.each{|key, val|
+ next if /^content-type$/i =~ key
+ next if /^content-length$/i =~ key
+ name = "HTTP_" + key
+ name.gsub!(/-/o, "_")
+ name.upcase!
+ meta[name] = val
+ }
+
+ meta
+ end
+
+ private
+
+ # :stopdoc:
+
+ MAX_URI_LENGTH = 2083 # :nodoc:
+
+ # same as Mongrel, Thin and Puma
+ MAX_HEADER_LENGTH = (112 * 1024) # :nodoc:
+
+ def read_request_line(socket)
+ @request_line = read_line(socket, MAX_URI_LENGTH) if socket
+ raise HTTPStatus::EOFError unless @request_line
+
+ @request_bytes = @request_line.bytesize
+ if @request_bytes >= MAX_URI_LENGTH and @request_line[-1, 1] != LF
+ raise HTTPStatus::RequestURITooLarge
+ end
+
+ @request_time = Time.now
+ if /^(\S+)\s+(\S++)(?:\s+HTTP\/(\d+\.\d+))?\r?\n/mo =~ @request_line
+ @request_method = $1
+ @unparsed_uri = $2
+ @http_version = HTTPVersion.new($3 ? $3 : "0.9")
+ else
+ rl = @request_line.sub(/\x0d?\x0a\z/o, '')
+ raise HTTPStatus::BadRequest, "bad Request-Line `#{rl}'."
+ end
+ end
+
+ def read_header(socket)
+ if socket
+ while line = read_line(socket)
+ break if /\A(#{CRLF}|#{LF})\z/om =~ line
+ if (@request_bytes += line.bytesize) > MAX_HEADER_LENGTH
+ raise HTTPStatus::RequestEntityTooLarge, 'headers too large'
+ end
+ @raw_header << line
+ end
+ end
+ @header = HTTPUtils::parse_header(@raw_header.join)
+ end
+
+ def parse_uri(str, scheme="http")
+ if @config[:Escape8bitURI]
+ str = HTTPUtils::escape8bit(str)
+ end
+ str.sub!(%r{\A/+}o, '/')
+ uri = URI::parse(str)
+ return uri if uri.absolute?
+ if @forwarded_host
+ host, port = @forwarded_host, @forwarded_port
+ elsif self["host"]
+ pattern = /\A(#{URI::REGEXP::PATTERN::HOST})(?::(\d+))?\z/n
+ host, port = *self['host'].scan(pattern)[0]
+ elsif @addr.size > 0
+ host, port = @addr[2], @addr[1]
+ else
+ host, port = @config[:ServerName], @config[:Port]
+ end
+ uri.scheme = @forwarded_proto || scheme
+ uri.host = host
+ uri.port = port ? port.to_i : nil
+ return URI::parse(uri.to_s)
+ end
+
+ def read_body(socket, block)
+ return unless socket
+ if tc = self['transfer-encoding']
+ case tc
+ when /\Achunked\z/io then read_chunked(socket, block)
+ else raise HTTPStatus::NotImplemented, "Transfer-Encoding: #{tc}."
+ end
+ elsif self['content-length'] || @remaining_size
+ @remaining_size ||= self['content-length'].to_i
+ while @remaining_size > 0
+ sz = [@buffer_size, @remaining_size].min
+ break unless buf = read_data(socket, sz)
+ @remaining_size -= buf.bytesize
+ block.call(buf)
+ end
+ if @remaining_size > 0 && @socket.eof?
+ raise HTTPStatus::BadRequest, "invalid body size."
+ end
+ elsif BODY_CONTAINABLE_METHODS.member?(@request_method) && !@socket.eof
+ raise HTTPStatus::LengthRequired
+ end
+ return @body
+ end
+
+ def read_chunk_size(socket)
+ line = read_line(socket)
+ if /^([0-9a-fA-F]+)(?:;(\S+))?/ =~ line
+ chunk_size = $1.hex
+ chunk_ext = $2
+ [ chunk_size, chunk_ext ]
+ else
+ raise HTTPStatus::BadRequest, "bad chunk `#{line}'."
+ end
+ end
+
+ def read_chunked(socket, block)
+ chunk_size, = read_chunk_size(socket)
+ while chunk_size > 0
+ begin
+ sz = [ chunk_size, @buffer_size ].min
+ data = read_data(socket, sz) # read chunk-data
+ if data.nil? || data.bytesize != sz
+ raise HTTPStatus::BadRequest, "bad chunk data size."
+ end
+ block.call(data)
+ end while (chunk_size -= sz) > 0
+
+ read_line(socket) # skip CRLF
+ chunk_size, = read_chunk_size(socket)
+ end
+ read_header(socket) # trailer + CRLF
+ @header.delete("transfer-encoding")
+ @remaining_size = 0
+ end
+
+ def _read_data(io, method, *arg)
+ begin
+ WEBrick::Utils.timeout(@config[:RequestTimeout]){
+ return io.__send__(method, *arg)
+ }
+ rescue Errno::ECONNRESET
+ return nil
+ rescue Timeout::Error
+ raise HTTPStatus::RequestTimeout
+ end
+ end
+
+ def read_line(io, size=4096)
+ _read_data(io, :gets, LF, size)
+ end
+
+ def read_data(io, size)
+ _read_data(io, :read, size)
+ end
+
+ def parse_query()
+ begin
+ if @request_method == "GET" || @request_method == "HEAD"
+ @query = HTTPUtils::parse_query(@query_string)
+ elsif self['content-type'] =~ /^application\/x-www-form-urlencoded/
+ @query = HTTPUtils::parse_query(body)
+ elsif self['content-type'] =~ /^multipart\/form-data; boundary=(.+)/
+ boundary = HTTPUtils::dequote($1)
+ @query = HTTPUtils::parse_form_data(body, boundary)
+ else
+ @query = Hash.new
+ end
+ rescue => ex
+ raise HTTPStatus::BadRequest, ex.message
+ end
+ end
+
+ PrivateNetworkRegexp = /
+ ^unknown$|
+ ^((::ffff:)?127.0.0.1|::1)$|
+ ^(::ffff:)?(10|172\.(1[6-9]|2[0-9]|3[01])|192\.168)\.
+ /ixo
+
+ # It's said that all X-Forwarded-* headers will contain more than one
+ # (comma-separated) value if the original request already contained one of
+ # these headers. Since we could use these values as Host header, we choose
+ # the initial(first) value. (apr_table_mergen() adds new value after the
+ # existing value with ", " prefix)
+ def setup_forwarded_info
+ if @forwarded_server = self["x-forwarded-server"]
+ @forwarded_server = @forwarded_server.split(",", 2).first
+ end
+ if @forwarded_proto = self["x-forwarded-proto"]
+ @forwarded_proto = @forwarded_proto.split(",", 2).first
+ end
+ if host_port = self["x-forwarded-host"]
+ host_port = host_port.split(",", 2).first
+ if host_port =~ /\A(\[[0-9a-fA-F:]+\])(?::(\d+))?\z/
+ @forwarded_host = $1
+ tmp = $2
+ else
+ @forwarded_host, tmp = host_port.split(":", 2)
+ end
+ @forwarded_port = (tmp || (@forwarded_proto == "https" ? 443 : 80)).to_i
+ end
+ if addrs = self["x-forwarded-for"]
+ addrs = addrs.split(",").collect(&:strip)
+ addrs.reject!{|ip| PrivateNetworkRegexp =~ ip }
+ @forwarded_for = addrs.first
+ end
+ end
+
+ # :startdoc:
+ end
+end
diff --git a/lib/webrick/httpresponse.rb b/tool/lib/webrick/httpresponse.rb
index ba4494ab74..ba4494ab74 100644
--- a/lib/webrick/httpresponse.rb
+++ b/tool/lib/webrick/httpresponse.rb
diff --git a/lib/webrick/https.rb b/tool/lib/webrick/https.rb
index b0a49bc40b..b0a49bc40b 100644
--- a/lib/webrick/https.rb
+++ b/tool/lib/webrick/https.rb
diff --git a/lib/webrick/httpserver.rb b/tool/lib/webrick/httpserver.rb
index e85d059319..e85d059319 100644
--- a/lib/webrick/httpserver.rb
+++ b/tool/lib/webrick/httpserver.rb
diff --git a/lib/webrick/httpservlet.rb b/tool/lib/webrick/httpservlet.rb
index da49a1405b..da49a1405b 100644
--- a/lib/webrick/httpservlet.rb
+++ b/tool/lib/webrick/httpservlet.rb
diff --git a/lib/webrick/httpservlet/abstract.rb b/tool/lib/webrick/httpservlet/abstract.rb
index bccb091861..bccb091861 100644
--- a/lib/webrick/httpservlet/abstract.rb
+++ b/tool/lib/webrick/httpservlet/abstract.rb
diff --git a/lib/webrick/httpservlet/cgi_runner.rb b/tool/lib/webrick/httpservlet/cgi_runner.rb
index 0398c16749..0398c16749 100644
--- a/lib/webrick/httpservlet/cgi_runner.rb
+++ b/tool/lib/webrick/httpservlet/cgi_runner.rb
diff --git a/lib/webrick/httpservlet/cgihandler.rb b/tool/lib/webrick/httpservlet/cgihandler.rb
index 4457770b7a..4457770b7a 100644
--- a/lib/webrick/httpservlet/cgihandler.rb
+++ b/tool/lib/webrick/httpservlet/cgihandler.rb
diff --git a/lib/webrick/httpservlet/erbhandler.rb b/tool/lib/webrick/httpservlet/erbhandler.rb
index cd09e5f216..cd09e5f216 100644
--- a/lib/webrick/httpservlet/erbhandler.rb
+++ b/tool/lib/webrick/httpservlet/erbhandler.rb
diff --git a/tool/lib/webrick/httpservlet/filehandler.rb b/tool/lib/webrick/httpservlet/filehandler.rb
new file mode 100644
index 0000000000..010df0e918
--- /dev/null
+++ b/tool/lib/webrick/httpservlet/filehandler.rb
@@ -0,0 +1,552 @@
+# frozen_string_literal: false
+#
+# filehandler.rb -- FileHandler Module
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: filehandler.rb,v 1.44 2003/06/07 01:34:51 gotoyuzo Exp $
+
+require 'time'
+
+require_relative '../htmlutils'
+require_relative '../httputils'
+require_relative '../httpstatus'
+
+module WEBrick
+ module HTTPServlet
+
+ ##
+ # Servlet for serving a single file. You probably want to use the
+ # FileHandler servlet instead as it handles directories and fancy indexes.
+ #
+ # Example:
+ #
+ # server.mount('/my_page.txt', WEBrick::HTTPServlet::DefaultFileHandler,
+ # '/path/to/my_page.txt')
+ #
+ # This servlet handles If-Modified-Since and Range requests.
+
+ class DefaultFileHandler < AbstractServlet
+
+ ##
+ # Creates a DefaultFileHandler instance for the file at +local_path+.
+
+ def initialize(server, local_path)
+ super(server, local_path)
+ @local_path = local_path
+ end
+
+ # :stopdoc:
+
+ def do_GET(req, res)
+ st = File::stat(@local_path)
+ mtime = st.mtime
+ res['etag'] = sprintf("%x-%x-%x", st.ino, st.size, st.mtime.to_i)
+
+ if not_modified?(req, res, mtime, res['etag'])
+ res.body = ''
+ raise HTTPStatus::NotModified
+ elsif req['range']
+ make_partial_content(req, res, @local_path, st.size)
+ raise HTTPStatus::PartialContent
+ else
+ mtype = HTTPUtils::mime_type(@local_path, @config[:MimeTypes])
+ res['content-type'] = mtype
+ res['content-length'] = st.size.to_s
+ res['last-modified'] = mtime.httpdate
+ res.body = File.open(@local_path, "rb")
+ end
+ end
+
+ def not_modified?(req, res, mtime, etag)
+ if ir = req['if-range']
+ begin
+ if Time.httpdate(ir) >= mtime
+ return true
+ end
+ rescue
+ if HTTPUtils::split_header_value(ir).member?(res['etag'])
+ return true
+ end
+ end
+ end
+
+ if (ims = req['if-modified-since']) && Time.parse(ims) >= mtime
+ return true
+ end
+
+ if (inm = req['if-none-match']) &&
+ HTTPUtils::split_header_value(inm).member?(res['etag'])
+ return true
+ end
+
+ return false
+ end
+
+ # returns a lambda for webrick/httpresponse.rb send_body_proc
+ def multipart_body(body, parts, boundary, mtype, filesize)
+ lambda do |socket|
+ begin
+ begin
+ first = parts.shift
+ last = parts.shift
+ socket.write(
+ "--#{boundary}#{CRLF}" \
+ "Content-Type: #{mtype}#{CRLF}" \
+ "Content-Range: bytes #{first}-#{last}/#{filesize}#{CRLF}" \
+ "#{CRLF}"
+ )
+
+ begin
+ IO.copy_stream(body, socket, last - first + 1, first)
+ rescue NotImplementedError
+ body.seek(first, IO::SEEK_SET)
+ IO.copy_stream(body, socket, last - first + 1)
+ end
+ socket.write(CRLF)
+ end while parts[0]
+ socket.write("--#{boundary}--#{CRLF}")
+ ensure
+ body.close
+ end
+ end
+ end
+
+ def make_partial_content(req, res, filename, filesize)
+ mtype = HTTPUtils::mime_type(filename, @config[:MimeTypes])
+ unless ranges = HTTPUtils::parse_range_header(req['range'])
+ raise HTTPStatus::BadRequest,
+ "Unrecognized range-spec: \"#{req['range']}\""
+ end
+ File.open(filename, "rb"){|io|
+ if ranges.size > 1
+ time = Time.now
+ boundary = "#{time.sec}_#{time.usec}_#{Process::pid}"
+ parts = []
+ ranges.each {|range|
+ prange = prepare_range(range, filesize)
+ next if prange[0] < 0
+ parts.concat(prange)
+ }
+ raise HTTPStatus::RequestRangeNotSatisfiable if parts.empty?
+ res["content-type"] = "multipart/byteranges; boundary=#{boundary}"
+ if req.http_version < '1.1'
+ res['connection'] = 'close'
+ else
+ res.chunked = true
+ end
+ res.body = multipart_body(io.dup, parts, boundary, mtype, filesize)
+ elsif range = ranges[0]
+ first, last = prepare_range(range, filesize)
+ raise HTTPStatus::RequestRangeNotSatisfiable if first < 0
+ res['content-type'] = mtype
+ res['content-range'] = "bytes #{first}-#{last}/#{filesize}"
+ res['content-length'] = (last - first + 1).to_s
+ res.body = io.dup
+ else
+ raise HTTPStatus::BadRequest
+ end
+ }
+ end
+
+ def prepare_range(range, filesize)
+ first = range.first < 0 ? filesize + range.first : range.first
+ return -1, -1 if first < 0 || first >= filesize
+ last = range.last < 0 ? filesize + range.last : range.last
+ last = filesize - 1 if last >= filesize
+ return first, last
+ end
+
+ # :startdoc:
+ end
+
+ ##
+ # Serves a directory including fancy indexing and a variety of other
+ # options.
+ #
+ # Example:
+ #
+ # server.mount('/assets', WEBrick::HTTPServlet::FileHandler,
+ # '/path/to/assets')
+
+ class FileHandler < AbstractServlet
+ HandlerTable = Hash.new # :nodoc:
+
+ ##
+ # Allow custom handling of requests for files with +suffix+ by class
+ # +handler+
+
+ def self.add_handler(suffix, handler)
+ HandlerTable[suffix] = handler
+ end
+
+ ##
+ # Remove custom handling of requests for files with +suffix+
+
+ def self.remove_handler(suffix)
+ HandlerTable.delete(suffix)
+ end
+
+ ##
+ # Creates a FileHandler servlet on +server+ that serves files starting
+ # at directory +root+
+ #
+ # +options+ may be a Hash containing keys from
+ # WEBrick::Config::FileHandler or +true+ or +false+.
+ #
+ # If +options+ is true or false then +:FancyIndexing+ is enabled or
+ # disabled respectively.
+
+ def initialize(server, root, options={}, default=Config::FileHandler)
+ @config = server.config
+ @logger = @config[:Logger]
+ @root = File.expand_path(root)
+ if options == true || options == false
+ options = { :FancyIndexing => options }
+ end
+ @options = default.dup.update(options)
+ end
+
+ # :stopdoc:
+
+ def set_filesystem_encoding(str)
+ enc = Encoding.find('filesystem')
+ if enc == Encoding::US_ASCII
+ str.b
+ else
+ str.dup.force_encoding(enc)
+ end
+ end
+
+ def service(req, res)
+ # if this class is mounted on "/" and /~username is requested.
+ # we're going to override path information before invoking service.
+ if defined?(Etc) && @options[:UserDir] && req.script_name.empty?
+ if %r|^(/~([^/]+))| =~ req.path_info
+ script_name, user = $1, $2
+ path_info = $'
+ begin
+ passwd = Etc::getpwnam(user)
+ @root = File::join(passwd.dir, @options[:UserDir])
+ req.script_name = script_name
+ req.path_info = path_info
+ rescue
+ @logger.debug "#{self.class}#do_GET: getpwnam(#{user}) failed"
+ end
+ end
+ end
+ prevent_directory_traversal(req, res)
+ super(req, res)
+ end
+
+ def do_GET(req, res)
+ unless exec_handler(req, res)
+ set_dir_list(req, res)
+ end
+ end
+
+ def do_POST(req, res)
+ unless exec_handler(req, res)
+ raise HTTPStatus::NotFound, "`#{req.path}' not found."
+ end
+ end
+
+ def do_OPTIONS(req, res)
+ unless exec_handler(req, res)
+ super(req, res)
+ end
+ end
+
+ # ToDo
+ # RFC2518: HTTP Extensions for Distributed Authoring -- WEBDAV
+ #
+ # PROPFIND PROPPATCH MKCOL DELETE PUT COPY MOVE
+ # LOCK UNLOCK
+
+ # RFC3253: Versioning Extensions to WebDAV
+ # (Web Distributed Authoring and Versioning)
+ #
+ # VERSION-CONTROL REPORT CHECKOUT CHECK_IN UNCHECKOUT
+ # MKWORKSPACE UPDATE LABEL MERGE ACTIVITY
+
+ private
+
+ def trailing_pathsep?(path)
+ # check for trailing path separator:
+ # File.dirname("/aaaa/bbbb/") #=> "/aaaa")
+ # File.dirname("/aaaa/bbbb/x") #=> "/aaaa/bbbb")
+ # File.dirname("/aaaa/bbbb") #=> "/aaaa")
+ # File.dirname("/aaaa/bbbbx") #=> "/aaaa")
+ return File.dirname(path) != File.dirname(path+"x")
+ end
+
+ def prevent_directory_traversal(req, res)
+ # Preventing directory traversal on Windows platforms;
+ # Backslashes (0x5c) in path_info are not interpreted as special
+ # character in URI notation. So the value of path_info should be
+ # normalize before accessing to the filesystem.
+
+ # dirty hack for filesystem encoding; in nature, File.expand_path
+ # should not be used for path normalization. [Bug #3345]
+ path = req.path_info.dup.force_encoding(Encoding.find("filesystem"))
+ if trailing_pathsep?(req.path_info)
+ # File.expand_path removes the trailing path separator.
+ # Adding a character is a workaround to save it.
+ # File.expand_path("/aaa/") #=> "/aaa"
+ # File.expand_path("/aaa/" + "x") #=> "/aaa/x"
+ expanded = File.expand_path(path + "x")
+ expanded.chop! # remove trailing "x"
+ else
+ expanded = File.expand_path(path)
+ end
+ expanded.force_encoding(req.path_info.encoding)
+ req.path_info = expanded
+ end
+
+ def exec_handler(req, res)
+ raise HTTPStatus::NotFound, "`#{req.path}' not found." unless @root
+ if set_filename(req, res)
+ handler = get_handler(req, res)
+ call_callback(:HandlerCallback, req, res)
+ h = handler.get_instance(@config, res.filename)
+ h.service(req, res)
+ return true
+ end
+ call_callback(:HandlerCallback, req, res)
+ return false
+ end
+
+ def get_handler(req, res)
+ suffix1 = (/\.(\w+)\z/ =~ res.filename) && $1.downcase
+ if /\.(\w+)\.([\w\-]+)\z/ =~ res.filename
+ if @options[:AcceptableLanguages].include?($2.downcase)
+ suffix2 = $1.downcase
+ end
+ end
+ handler_table = @options[:HandlerTable]
+ return handler_table[suffix1] || handler_table[suffix2] ||
+ HandlerTable[suffix1] || HandlerTable[suffix2] ||
+ DefaultFileHandler
+ end
+
+ def set_filename(req, res)
+ res.filename = @root
+ path_info = req.path_info.scan(%r|/[^/]*|)
+
+ path_info.unshift("") # dummy for checking @root dir
+ while base = path_info.first
+ base = set_filesystem_encoding(base)
+ break if base == "/"
+ break unless File.directory?(File.expand_path(res.filename + base))
+ shift_path_info(req, res, path_info)
+ call_callback(:DirectoryCallback, req, res)
+ end
+
+ if base = path_info.first
+ base = set_filesystem_encoding(base)
+ if base == "/"
+ if file = search_index_file(req, res)
+ shift_path_info(req, res, path_info, file)
+ call_callback(:FileCallback, req, res)
+ return true
+ end
+ shift_path_info(req, res, path_info)
+ elsif file = search_file(req, res, base)
+ shift_path_info(req, res, path_info, file)
+ call_callback(:FileCallback, req, res)
+ return true
+ else
+ raise HTTPStatus::NotFound, "`#{req.path}' not found."
+ end
+ end
+
+ return false
+ end
+
+ def check_filename(req, res, name)
+ if nondisclosure_name?(name) || windows_ambiguous_name?(name)
+ @logger.warn("the request refers nondisclosure name `#{name}'.")
+ raise HTTPStatus::NotFound, "`#{req.path}' not found."
+ end
+ end
+
+ def shift_path_info(req, res, path_info, base=nil)
+ tmp = path_info.shift
+ base = base || set_filesystem_encoding(tmp)
+ req.path_info = path_info.join
+ req.script_name << base
+ res.filename = File.expand_path(res.filename + base)
+ check_filename(req, res, File.basename(res.filename))
+ end
+
+ def search_index_file(req, res)
+ @config[:DirectoryIndex].each{|index|
+ if file = search_file(req, res, "/"+index)
+ return file
+ end
+ }
+ return nil
+ end
+
+ def search_file(req, res, basename)
+ langs = @options[:AcceptableLanguages]
+ path = res.filename + basename
+ if File.file?(path)
+ return basename
+ elsif langs.size > 0
+ req.accept_language.each{|lang|
+ path_with_lang = path + ".#{lang}"
+ if langs.member?(lang) && File.file?(path_with_lang)
+ return basename + ".#{lang}"
+ end
+ }
+ (langs - req.accept_language).each{|lang|
+ path_with_lang = path + ".#{lang}"
+ if File.file?(path_with_lang)
+ return basename + ".#{lang}"
+ end
+ }
+ end
+ return nil
+ end
+
+ def call_callback(callback_name, req, res)
+ if cb = @options[callback_name]
+ cb.call(req, res)
+ end
+ end
+
+ def windows_ambiguous_name?(name)
+ return true if /[. ]+\z/ =~ name
+ return true if /::\$DATA\z/ =~ name
+ return false
+ end
+
+ def nondisclosure_name?(name)
+ @options[:NondisclosureName].each{|pattern|
+ if File.fnmatch(pattern, name, File::FNM_CASEFOLD)
+ return true
+ end
+ }
+ return false
+ end
+
+ def set_dir_list(req, res)
+ redirect_to_directory_uri(req, res)
+ unless @options[:FancyIndexing]
+ raise HTTPStatus::Forbidden, "no access permission to `#{req.path}'"
+ end
+ local_path = res.filename
+ list = Dir::entries(local_path).collect{|name|
+ next if name == "." || name == ".."
+ next if nondisclosure_name?(name)
+ next if windows_ambiguous_name?(name)
+ st = (File::stat(File.join(local_path, name)) rescue nil)
+ if st.nil?
+ [ name, nil, -1 ]
+ elsif st.directory?
+ [ name + "/", st.mtime, -1 ]
+ else
+ [ name, st.mtime, st.size ]
+ end
+ }
+ list.compact!
+
+ query = req.query
+
+ d0 = nil
+ idx = nil
+ %w[N M S].each_with_index do |q, i|
+ if d = query.delete(q)
+ idx ||= i
+ d0 ||= d
+ end
+ end
+ d0 ||= "A"
+ idx ||= 0
+ d1 = (d0 == "A") ? "D" : "A"
+
+ if d0 == "A"
+ list.sort!{|a,b| a[idx] <=> b[idx] }
+ else
+ list.sort!{|a,b| b[idx] <=> a[idx] }
+ end
+
+ namewidth = query["NameWidth"]
+ if namewidth == "*"
+ namewidth = nil
+ elsif !namewidth or (namewidth = namewidth.to_i) < 2
+ namewidth = 25
+ end
+ query = query.inject('') {|s, (k, v)| s << '&' << HTMLUtils::escape("#{k}=#{v}")}
+
+ type = "text/html"
+ case enc = Encoding.find('filesystem')
+ when Encoding::US_ASCII, Encoding::ASCII_8BIT
+ else
+ type << "; charset=\"#{enc.name}\""
+ end
+ res['content-type'] = type
+
+ title = "Index of #{HTMLUtils::escape(req.path)}"
+ res.body = <<-_end_of_html_
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<HTML>
+ <HEAD>
+ <TITLE>#{title}</TITLE>
+ <style type="text/css">
+ <!--
+ .name, .mtime { text-align: left; }
+ .size { text-align: right; }
+ td { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
+ table { border-collapse: collapse; }
+ tr th { border-bottom: 2px groove; }
+ //-->
+ </style>
+ </HEAD>
+ <BODY>
+ <H1>#{title}</H1>
+ _end_of_html_
+
+ res.body << "<TABLE width=\"100%\"><THEAD><TR>\n"
+ res.body << "<TH class=\"name\"><A HREF=\"?N=#{d1}#{query}\">Name</A></TH>"
+ res.body << "<TH class=\"mtime\"><A HREF=\"?M=#{d1}#{query}\">Last modified</A></TH>"
+ res.body << "<TH class=\"size\"><A HREF=\"?S=#{d1}#{query}\">Size</A></TH>\n"
+ res.body << "</TR></THEAD>\n"
+ res.body << "<TBODY>\n"
+
+ query.sub!(/\A&/, '?')
+ list.unshift [ "..", File::mtime(local_path+"/.."), -1 ]
+ list.each{ |name, time, size|
+ if name == ".."
+ dname = "Parent Directory"
+ elsif namewidth and name.size > namewidth
+ dname = name[0...(namewidth - 2)] << '..'
+ else
+ dname = name
+ end
+ s = "<TR><TD class=\"name\"><A HREF=\"#{HTTPUtils::escape(name)}#{query if name.end_with?('/')}\">#{HTMLUtils::escape(dname)}</A></TD>"
+ s << "<TD class=\"mtime\">" << (time ? time.strftime("%Y/%m/%d %H:%M") : "") << "</TD>"
+ s << "<TD class=\"size\">" << (size >= 0 ? size.to_s : "-") << "</TD></TR>\n"
+ res.body << s
+ }
+ res.body << "</TBODY></TABLE>"
+ res.body << "<HR>"
+
+ res.body << <<-_end_of_html_
+ <ADDRESS>
+ #{HTMLUtils::escape(@config[:ServerSoftware])}<BR>
+ at #{req.host}:#{req.port}
+ </ADDRESS>
+ </BODY>
+</HTML>
+ _end_of_html_
+ end
+
+ # :startdoc:
+ end
+ end
+end
diff --git a/lib/webrick/httpservlet/prochandler.rb b/tool/lib/webrick/httpservlet/prochandler.rb
index 599ffc4340..599ffc4340 100644
--- a/lib/webrick/httpservlet/prochandler.rb
+++ b/tool/lib/webrick/httpservlet/prochandler.rb
diff --git a/lib/webrick/httpstatus.rb b/tool/lib/webrick/httpstatus.rb
index c811f21964..c811f21964 100644
--- a/lib/webrick/httpstatus.rb
+++ b/tool/lib/webrick/httpstatus.rb
diff --git a/tool/lib/webrick/httputils.rb b/tool/lib/webrick/httputils.rb
new file mode 100644
index 0000000000..f1b9ddf9f0
--- /dev/null
+++ b/tool/lib/webrick/httputils.rb
@@ -0,0 +1,512 @@
+# frozen_string_literal: false
+#
+# httputils.rb -- HTTPUtils Module
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: httputils.rb,v 1.34 2003/06/05 21:34:08 gotoyuzo Exp $
+
+require 'socket'
+require 'tempfile'
+
+module WEBrick
+ CR = "\x0d" # :nodoc:
+ LF = "\x0a" # :nodoc:
+ CRLF = "\x0d\x0a" # :nodoc:
+
+ ##
+ # HTTPUtils provides utility methods for working with the HTTP protocol.
+ #
+ # This module is generally used internally by WEBrick
+
+ module HTTPUtils
+
+ ##
+ # Normalizes a request path. Raises an exception if the path cannot be
+ # normalized.
+
+ def normalize_path(path)
+ raise "abnormal path `#{path}'" if path[0] != ?/
+ ret = path.dup
+
+ ret.gsub!(%r{/+}o, '/') # // => /
+ while ret.sub!(%r'/\.(?:/|\Z)', '/'); end # /. => /
+ while ret.sub!(%r'/(?!\.\./)[^/]+/\.\.(?:/|\Z)', '/'); end # /foo/.. => /foo
+
+ raise "abnormal path `#{path}'" if %r{/\.\.(/|\Z)} =~ ret
+ ret
+ end
+ module_function :normalize_path
+
+ ##
+ # Default mime types
+
+ DefaultMimeTypes = {
+ "ai" => "application/postscript",
+ "asc" => "text/plain",
+ "avi" => "video/x-msvideo",
+ "bin" => "application/octet-stream",
+ "bmp" => "image/bmp",
+ "class" => "application/octet-stream",
+ "cer" => "application/pkix-cert",
+ "crl" => "application/pkix-crl",
+ "crt" => "application/x-x509-ca-cert",
+ #"crl" => "application/x-pkcs7-crl",
+ "css" => "text/css",
+ "dms" => "application/octet-stream",
+ "doc" => "application/msword",
+ "dvi" => "application/x-dvi",
+ "eps" => "application/postscript",
+ "etx" => "text/x-setext",
+ "exe" => "application/octet-stream",
+ "gif" => "image/gif",
+ "htm" => "text/html",
+ "html" => "text/html",
+ "jpe" => "image/jpeg",
+ "jpeg" => "image/jpeg",
+ "jpg" => "image/jpeg",
+ "js" => "application/javascript",
+ "json" => "application/json",
+ "lha" => "application/octet-stream",
+ "lzh" => "application/octet-stream",
+ "mjs" => "application/javascript",
+ "mov" => "video/quicktime",
+ "mpe" => "video/mpeg",
+ "mpeg" => "video/mpeg",
+ "mpg" => "video/mpeg",
+ "pbm" => "image/x-portable-bitmap",
+ "pdf" => "application/pdf",
+ "pgm" => "image/x-portable-graymap",
+ "png" => "image/png",
+ "pnm" => "image/x-portable-anymap",
+ "ppm" => "image/x-portable-pixmap",
+ "ppt" => "application/vnd.ms-powerpoint",
+ "ps" => "application/postscript",
+ "qt" => "video/quicktime",
+ "ras" => "image/x-cmu-raster",
+ "rb" => "text/plain",
+ "rd" => "text/plain",
+ "rtf" => "application/rtf",
+ "sgm" => "text/sgml",
+ "sgml" => "text/sgml",
+ "svg" => "image/svg+xml",
+ "tif" => "image/tiff",
+ "tiff" => "image/tiff",
+ "txt" => "text/plain",
+ "wasm" => "application/wasm",
+ "xbm" => "image/x-xbitmap",
+ "xhtml" => "text/html",
+ "xls" => "application/vnd.ms-excel",
+ "xml" => "text/xml",
+ "xpm" => "image/x-xpixmap",
+ "xwd" => "image/x-xwindowdump",
+ "zip" => "application/zip",
+ }
+
+ ##
+ # Loads Apache-compatible mime.types in +file+.
+
+ def load_mime_types(file)
+ # note: +file+ may be a "| command" for now; some people may
+ # rely on this, but currently we do not use this method by default.
+ open(file){ |io|
+ hash = Hash.new
+ io.each{ |line|
+ next if /^#/ =~ line
+ line.chomp!
+ mimetype, ext0 = line.split(/\s+/, 2)
+ next unless ext0
+ next if ext0.empty?
+ ext0.split(/\s+/).each{ |ext| hash[ext] = mimetype }
+ }
+ hash
+ }
+ end
+ module_function :load_mime_types
+
+ ##
+ # Returns the mime type of +filename+ from the list in +mime_tab+. If no
+ # mime type was found application/octet-stream is returned.
+
+ def mime_type(filename, mime_tab)
+ suffix1 = (/\.(\w+)$/ =~ filename && $1.downcase)
+ suffix2 = (/\.(\w+)\.[\w\-]+$/ =~ filename && $1.downcase)
+ mime_tab[suffix1] || mime_tab[suffix2] || "application/octet-stream"
+ end
+ module_function :mime_type
+
+ ##
+ # Parses an HTTP header +raw+ into a hash of header fields with an Array
+ # of values.
+
+ def parse_header(raw)
+ header = Hash.new([].freeze)
+ field = nil
+ raw.each_line{|line|
+ case line
+ when /^([A-Za-z0-9!\#$%&'*+\-.^_`|~]+):\s*(.*?)\s*\z/om
+ field, value = $1, $2
+ field.downcase!
+ header[field] = [] unless header.has_key?(field)
+ header[field] << value
+ when /^\s+(.*?)\s*\z/om
+ value = $1
+ unless field
+ raise HTTPStatus::BadRequest, "bad header '#{line}'."
+ end
+ header[field][-1] << " " << value
+ else
+ raise HTTPStatus::BadRequest, "bad header '#{line}'."
+ end
+ }
+ header.each{|key, values|
+ values.each(&:strip!)
+ }
+ header
+ end
+ module_function :parse_header
+
+ ##
+ # Splits a header value +str+ according to HTTP specification.
+
+ def split_header_value(str)
+ str.scan(%r'\G((?:"(?:\\.|[^"])+?"|[^",]+)+)
+ (?:,\s*|\Z)'xn).flatten
+ end
+ module_function :split_header_value
+
+ ##
+ # Parses a Range header value +ranges_specifier+
+
+ def parse_range_header(ranges_specifier)
+ if /^bytes=(.*)/ =~ ranges_specifier
+ byte_range_set = split_header_value($1)
+ byte_range_set.collect{|range_spec|
+ case range_spec
+ when /^(\d+)-(\d+)/ then $1.to_i .. $2.to_i
+ when /^(\d+)-/ then $1.to_i .. -1
+ when /^-(\d+)/ then -($1.to_i) .. -1
+ else return nil
+ end
+ }
+ end
+ end
+ module_function :parse_range_header
+
+ ##
+ # Parses q values in +value+ as used in Accept headers.
+
+ def parse_qvalues(value)
+ tmp = []
+ if value
+ parts = value.split(/,\s*/)
+ parts.each {|part|
+ if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
+ val = m[1]
+ q = (m[2] or 1).to_f
+ tmp.push([val, q])
+ end
+ }
+ tmp = tmp.sort_by{|val, q| -q}
+ tmp.collect!{|val, q| val}
+ end
+ return tmp
+ end
+ module_function :parse_qvalues
+
+ ##
+ # Removes quotes and escapes from +str+
+
+ def dequote(str)
+ ret = (/\A"(.*)"\Z/ =~ str) ? $1 : str.dup
+ ret.gsub!(/\\(.)/, "\\1")
+ ret
+ end
+ module_function :dequote
+
+ ##
+ # Quotes and escapes quotes in +str+
+
+ def quote(str)
+ '"' << str.gsub(/[\\\"]/o, "\\\1") << '"'
+ end
+ module_function :quote
+
+ ##
+ # Stores multipart form data. FormData objects are created when
+ # WEBrick::HTTPUtils.parse_form_data is called.
+
+ class FormData < String
+ EmptyRawHeader = [].freeze # :nodoc:
+ EmptyHeader = {}.freeze # :nodoc:
+
+ ##
+ # The name of the form data part
+
+ attr_accessor :name
+
+ ##
+ # The filename of the form data part
+
+ attr_accessor :filename
+
+ attr_accessor :next_data # :nodoc:
+ protected :next_data
+
+ ##
+ # Creates a new FormData object.
+ #
+ # +args+ is an Array of form data entries. One FormData will be created
+ # for each entry.
+ #
+ # This is called by WEBrick::HTTPUtils.parse_form_data for you
+
+ def initialize(*args)
+ @name = @filename = @next_data = nil
+ if args.empty?
+ @raw_header = []
+ @header = nil
+ super("")
+ else
+ @raw_header = EmptyRawHeader
+ @header = EmptyHeader
+ super(args.shift)
+ unless args.empty?
+ @next_data = self.class.new(*args)
+ end
+ end
+ end
+
+ ##
+ # Retrieves the header at the first entry in +key+
+
+ def [](*key)
+ begin
+ @header[key[0].downcase].join(", ")
+ rescue StandardError, NameError
+ super
+ end
+ end
+
+ ##
+ # Adds +str+ to this FormData which may be the body, a header or a
+ # header entry.
+ #
+ # This is called by WEBrick::HTTPUtils.parse_form_data for you
+
+ def <<(str)
+ if @header
+ super
+ elsif str == CRLF
+ @header = HTTPUtils::parse_header(@raw_header.join)
+ if cd = self['content-disposition']
+ if /\s+name="(.*?)"/ =~ cd then @name = $1 end
+ if /\s+filename="(.*?)"/ =~ cd then @filename = $1 end
+ end
+ else
+ @raw_header << str
+ end
+ self
+ end
+
+ ##
+ # Adds +data+ at the end of the chain of entries
+ #
+ # This is called by WEBrick::HTTPUtils.parse_form_data for you.
+
+ def append_data(data)
+ tmp = self
+ while tmp
+ unless tmp.next_data
+ tmp.next_data = data
+ break
+ end
+ tmp = tmp.next_data
+ end
+ self
+ end
+
+ ##
+ # Yields each entry in this FormData
+
+ def each_data
+ tmp = self
+ while tmp
+ next_data = tmp.next_data
+ yield(tmp)
+ tmp = next_data
+ end
+ end
+
+ ##
+ # Returns all the FormData as an Array
+
+ def list
+ ret = []
+ each_data{|data|
+ ret << data.to_s
+ }
+ ret
+ end
+
+ ##
+ # A FormData will behave like an Array
+
+ alias :to_ary :list
+
+ ##
+ # This FormData's body
+
+ def to_s
+ String.new(self)
+ end
+ end
+
+ ##
+ # Parses the query component of a URI in +str+
+
+ def parse_query(str)
+ query = Hash.new
+ if str
+ str.split(/[&;]/).each{|x|
+ next if x.empty?
+ key, val = x.split(/=/,2)
+ key = unescape_form(key)
+ val = unescape_form(val.to_s)
+ val = FormData.new(val)
+ val.name = key
+ if query.has_key?(key)
+ query[key].append_data(val)
+ next
+ end
+ query[key] = val
+ }
+ end
+ query
+ end
+ module_function :parse_query
+
+ ##
+ # Parses form data in +io+ with the given +boundary+
+
+ def parse_form_data(io, boundary)
+ boundary_regexp = /\A--#{Regexp.quote(boundary)}(--)?#{CRLF}\z/
+ form_data = Hash.new
+ return form_data unless io
+ data = nil
+ io.each_line{|line|
+ if boundary_regexp =~ line
+ if data
+ data.chop!
+ key = data.name
+ if form_data.has_key?(key)
+ form_data[key].append_data(data)
+ else
+ form_data[key] = data
+ end
+ end
+ data = FormData.new
+ next
+ else
+ if data
+ data << line
+ end
+ end
+ }
+ return form_data
+ end
+ module_function :parse_form_data
+
+ #####
+
+ reserved = ';/?:@&=+$,'
+ num = '0123456789'
+ lowalpha = 'abcdefghijklmnopqrstuvwxyz'
+ upalpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+ mark = '-_.!~*\'()'
+ unreserved = num + lowalpha + upalpha + mark
+ control = (0x0..0x1f).collect{|c| c.chr }.join + "\x7f"
+ space = " "
+ delims = '<>#%"'
+ unwise = '{}|\\^[]`'
+ nonascii = (0x80..0xff).collect{|c| c.chr }.join
+
+ module_function
+
+ # :stopdoc:
+
+ def _make_regex(str) /([#{Regexp.escape(str)}])/n end
+ def _make_regex!(str) /([^#{Regexp.escape(str)}])/n end
+ def _escape(str, regex)
+ str = str.b
+ str.gsub!(regex) {"%%%02X" % $1.ord}
+ # %-escaped string should contain US-ASCII only
+ str.force_encoding(Encoding::US_ASCII)
+ end
+ def _unescape(str, regex)
+ str = str.b
+ str.gsub!(regex) {$1.hex.chr}
+ # encoding of %-unescaped string is unknown
+ str
+ end
+
+ UNESCAPED = _make_regex(control+space+delims+unwise+nonascii)
+ UNESCAPED_FORM = _make_regex(reserved+control+delims+unwise+nonascii)
+ NONASCII = _make_regex(nonascii)
+ ESCAPED = /%([0-9a-fA-F]{2})/
+ UNESCAPED_PCHAR = _make_regex!(unreserved+":@&=+$,")
+
+ # :startdoc:
+
+ ##
+ # Escapes HTTP reserved and unwise characters in +str+
+
+ def escape(str)
+ _escape(str, UNESCAPED)
+ end
+
+ ##
+ # Unescapes HTTP reserved and unwise characters in +str+
+
+ def unescape(str)
+ _unescape(str, ESCAPED)
+ end
+
+ ##
+ # Escapes form reserved characters in +str+
+
+ def escape_form(str)
+ ret = _escape(str, UNESCAPED_FORM)
+ ret.gsub!(/ /, "+")
+ ret
+ end
+
+ ##
+ # Unescapes form reserved characters in +str+
+
+ def unescape_form(str)
+ _unescape(str.gsub(/\+/, " "), ESCAPED)
+ end
+
+ ##
+ # Escapes path +str+
+
+ def escape_path(str)
+ result = ""
+ str.scan(%r{/([^/]*)}).each{|i|
+ result << "/" << _escape(i[0], UNESCAPED_PCHAR)
+ }
+ return result
+ end
+
+ ##
+ # Escapes 8 bit characters in +str+
+
+ def escape8bit(str)
+ _escape(str, NONASCII)
+ end
+ end
+end
diff --git a/lib/webrick/httpversion.rb b/tool/lib/webrick/httpversion.rb
index 8a251944a2..8a251944a2 100644
--- a/lib/webrick/httpversion.rb
+++ b/tool/lib/webrick/httpversion.rb
diff --git a/lib/webrick/log.rb b/tool/lib/webrick/log.rb
index 2c1fdfe602..2c1fdfe602 100644
--- a/lib/webrick/log.rb
+++ b/tool/lib/webrick/log.rb
diff --git a/tool/lib/webrick/server.rb b/tool/lib/webrick/server.rb
new file mode 100644
index 0000000000..fd6b7a61b5
--- /dev/null
+++ b/tool/lib/webrick/server.rb
@@ -0,0 +1,381 @@
+# frozen_string_literal: false
+#
+# server.rb -- GenericServer Class
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: server.rb,v 1.62 2003/07/22 19:20:43 gotoyuzo Exp $
+
+require 'socket'
+require_relative 'config'
+require_relative 'log'
+
+module WEBrick
+
+ ##
+ # Server error exception
+
+ class ServerError < StandardError; end
+
+ ##
+ # Base server class
+
+ class SimpleServer
+
+ ##
+ # A SimpleServer only yields when you start it
+
+ def SimpleServer.start
+ yield
+ end
+ end
+
+ ##
+ # A generic module for daemonizing a process
+
+ class Daemon
+
+ ##
+ # Performs the standard operations for daemonizing a process. Runs a
+ # block, if given.
+
+ def Daemon.start
+ Process.daemon
+ File.umask(0)
+ yield if block_given?
+ end
+ end
+
+ ##
+ # Base TCP server class. You must subclass GenericServer and provide a #run
+ # method.
+
+ class GenericServer
+
+ ##
+ # The server status. One of :Stop, :Running or :Shutdown
+
+ attr_reader :status
+
+ ##
+ # The server configuration
+
+ attr_reader :config
+
+ ##
+ # The server logger. This is independent from the HTTP access log.
+
+ attr_reader :logger
+
+ ##
+ # Tokens control the number of outstanding clients. The
+ # <code>:MaxClients</code> configuration sets this.
+
+ attr_reader :tokens
+
+ ##
+ # Sockets listening for connections.
+
+ attr_reader :listeners
+
+ ##
+ # Creates a new generic server from +config+. The default configuration
+ # comes from +default+.
+
+ def initialize(config={}, default=Config::General)
+ @config = default.dup.update(config)
+ @status = :Stop
+ @config[:Logger] ||= Log::new
+ @logger = @config[:Logger]
+
+ @tokens = Thread::SizedQueue.new(@config[:MaxClients])
+ @config[:MaxClients].times{ @tokens.push(nil) }
+
+ webrickv = WEBrick::VERSION
+ rubyv = "#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
+ @logger.info("WEBrick #{webrickv}")
+ @logger.info("ruby #{rubyv}")
+
+ @listeners = []
+ @shutdown_pipe = nil
+ unless @config[:DoNotListen]
+ raise ArgumentError, "Port must an integer" unless @config[:Port].to_s == @config[:Port].to_i.to_s
+
+ @config[:Port] = @config[:Port].to_i
+ if @config[:Listen]
+ warn(":Listen option is deprecated; use GenericServer#listen", uplevel: 1)
+ end
+ listen(@config[:BindAddress], @config[:Port])
+ if @config[:Port] == 0
+ @config[:Port] = @listeners[0].addr[1]
+ end
+ end
+ end
+
+ ##
+ # Retrieves +key+ from the configuration
+
+ def [](key)
+ @config[key]
+ end
+
+ ##
+ # Adds listeners from +address+ and +port+ to the server. See
+ # WEBrick::Utils::create_listeners for details.
+
+ def listen(address, port)
+ @listeners += Utils::create_listeners(address, port)
+ end
+
+ ##
+ # Starts the server and runs the +block+ for each connection. This method
+ # does not return until the server is stopped from a signal handler or
+ # another thread using #stop or #shutdown.
+ #
+ # If the block raises a subclass of StandardError the exception is logged
+ # and ignored. If an IOError or Errno::EBADF exception is raised the
+ # exception is ignored. If an Exception subclass is raised the exception
+ # is logged and re-raised which stops the server.
+ #
+ # To completely shut down a server call #shutdown from ensure:
+ #
+ # server = WEBrick::GenericServer.new
+ # # or WEBrick::HTTPServer.new
+ #
+ # begin
+ # server.start
+ # ensure
+ # server.shutdown
+ # end
+
+ def start(&block)
+ raise ServerError, "already started." if @status != :Stop
+ server_type = @config[:ServerType] || SimpleServer
+
+ setup_shutdown_pipe
+
+ server_type.start{
+ @logger.info \
+ "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
+ @status = :Running
+ call_callback(:StartCallback)
+
+ shutdown_pipe = @shutdown_pipe
+
+ thgroup = ThreadGroup.new
+ begin
+ while @status == :Running
+ begin
+ sp = shutdown_pipe[0]
+ if svrs = IO.select([sp, *@listeners])
+ if svrs[0].include? sp
+ # swallow shutdown pipe
+ buf = String.new
+ nil while String ===
+ sp.read_nonblock([sp.nread, 8].max, buf, exception: false)
+ break
+ end
+ svrs[0].each{|svr|
+ @tokens.pop # blocks while no token is there.
+ if sock = accept_client(svr)
+ unless config[:DoNotReverseLookup].nil?
+ sock.do_not_reverse_lookup = !!config[:DoNotReverseLookup]
+ end
+ th = start_thread(sock, &block)
+ th[:WEBrickThread] = true
+ thgroup.add(th)
+ else
+ @tokens.push(nil)
+ end
+ }
+ end
+ rescue Errno::EBADF, Errno::ENOTSOCK, IOError => ex
+ # if the listening socket was closed in GenericServer#shutdown,
+ # IO::select raise it.
+ rescue StandardError => ex
+ msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
+ @logger.error msg
+ rescue Exception => ex
+ @logger.fatal ex
+ raise
+ end
+ end
+ ensure
+ cleanup_shutdown_pipe(shutdown_pipe)
+ cleanup_listener
+ @status = :Shutdown
+ @logger.info "going to shutdown ..."
+ thgroup.list.each{|th| th.join if th[:WEBrickThread] }
+ call_callback(:StopCallback)
+ @logger.info "#{self.class}#start done."
+ @status = :Stop
+ end
+ }
+ end
+
+ ##
+ # Stops the server from accepting new connections.
+
+ def stop
+ if @status == :Running
+ @status = :Shutdown
+ end
+
+ alarm_shutdown_pipe {|f| f.write_nonblock("\0")}
+ end
+
+ ##
+ # Shuts down the server and all listening sockets. New listeners must be
+ # provided to restart the server.
+
+ def shutdown
+ stop
+
+ alarm_shutdown_pipe(&:close)
+ end
+
+ ##
+ # You must subclass GenericServer and implement \#run which accepts a TCP
+ # client socket
+
+ def run(sock)
+ @logger.fatal "run() must be provided by user."
+ end
+
+ private
+
+ # :stopdoc:
+
+ ##
+ # Accepts a TCP client socket from the TCP server socket +svr+ and returns
+ # the client socket.
+
+ def accept_client(svr)
+ case sock = svr.to_io.accept_nonblock(exception: false)
+ when :wait_readable
+ nil
+ else
+ if svr.respond_to?(:start_immediately)
+ sock = OpenSSL::SSL::SSLSocket.new(sock, ssl_context)
+ sock.sync_close = true
+ # we cannot do OpenSSL::SSL::SSLSocket#accept here because
+ # a slow client can prevent us from accepting connections
+ # from other clients
+ end
+ sock
+ end
+ rescue Errno::ECONNRESET, Errno::ECONNABORTED,
+ Errno::EPROTO, Errno::EINVAL
+ nil
+ rescue StandardError => ex
+ msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
+ @logger.error msg
+ nil
+ end
+
+ ##
+ # Starts a server thread for the client socket +sock+ that runs the given
+ # +block+.
+ #
+ # Sets the socket to the <code>:WEBrickSocket</code> thread local variable
+ # in the thread.
+ #
+ # If any errors occur in the block they are logged and handled.
+
+ def start_thread(sock, &block)
+ Thread.start{
+ begin
+ Thread.current[:WEBrickSocket] = sock
+ begin
+ addr = sock.peeraddr
+ @logger.debug "accept: #{addr[3]}:#{addr[1]}"
+ rescue SocketError
+ @logger.debug "accept: <address unknown>"
+ raise
+ end
+ if sock.respond_to?(:sync_close=) && @config[:SSLStartImmediately]
+ WEBrick::Utils.timeout(@config[:RequestTimeout]) do
+ begin
+ sock.accept # OpenSSL::SSL::SSLSocket#accept
+ rescue Errno::ECONNRESET, Errno::ECONNABORTED,
+ Errno::EPROTO, Errno::EINVAL
+ Thread.exit
+ end
+ end
+ end
+ call_callback(:AcceptCallback, sock)
+ block ? block.call(sock) : run(sock)
+ rescue Errno::ENOTCONN
+ @logger.debug "Errno::ENOTCONN raised"
+ rescue ServerError => ex
+ msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
+ @logger.error msg
+ rescue Exception => ex
+ @logger.error ex
+ ensure
+ @tokens.push(nil)
+ Thread.current[:WEBrickSocket] = nil
+ if addr
+ @logger.debug "close: #{addr[3]}:#{addr[1]}"
+ else
+ @logger.debug "close: <address unknown>"
+ end
+ sock.close
+ end
+ }
+ end
+
+ ##
+ # Calls the callback +callback_name+ from the configuration with +args+
+
+ def call_callback(callback_name, *args)
+ @config[callback_name]&.call(*args)
+ end
+
+ def setup_shutdown_pipe
+ return @shutdown_pipe ||= IO.pipe
+ end
+
+ def cleanup_shutdown_pipe(shutdown_pipe)
+ @shutdown_pipe = nil
+ shutdown_pipe&.each(&:close)
+ end
+
+ def alarm_shutdown_pipe
+ _, pipe = @shutdown_pipe # another thread may modify @shutdown_pipe.
+ if pipe
+ if !pipe.closed?
+ begin
+ yield pipe
+ rescue IOError # closed by another thread.
+ end
+ end
+ end
+ end
+
+ def cleanup_listener
+ @listeners.each{|s|
+ if @logger.debug?
+ addr = s.addr
+ @logger.debug("close TCPSocket(#{addr[2]}, #{addr[1]})")
+ end
+ begin
+ s.shutdown
+ rescue Errno::ENOTCONN
+ # when `Errno::ENOTCONN: Socket is not connected' on some platforms,
+ # call #close instead of #shutdown.
+ # (ignore @config[:ShutdownSocketWithoutClose])
+ s.close
+ else
+ unless @config[:ShutdownSocketWithoutClose]
+ s.close
+ end
+ end
+ }
+ @listeners.clear
+ end
+ end # end of GenericServer
+end
diff --git a/tool/lib/webrick/ssl.rb b/tool/lib/webrick/ssl.rb
new file mode 100644
index 0000000000..e448095a12
--- /dev/null
+++ b/tool/lib/webrick/ssl.rb
@@ -0,0 +1,215 @@
+# frozen_string_literal: false
+#
+# ssl.rb -- SSL/TLS enhancement for GenericServer
+#
+# Copyright (c) 2003 GOTOU Yuuzou All rights reserved.
+#
+# $Id$
+
+require 'webrick'
+require 'openssl'
+
+module WEBrick
+ module Config
+ svrsoft = General[:ServerSoftware]
+ osslv = ::OpenSSL::OPENSSL_VERSION.split[1]
+
+ ##
+ # Default SSL server configuration.
+ #
+ # WEBrick can automatically create a self-signed certificate if
+ # <code>:SSLCertName</code> is set. For more information on the various
+ # SSL options see OpenSSL::SSL::SSLContext.
+ #
+ # :ServerSoftware ::
+ # The server software name used in the Server: header.
+ # :SSLEnable :: false,
+ # Enable SSL for this server. Defaults to false.
+ # :SSLCertificate ::
+ # The SSL certificate for the server.
+ # :SSLPrivateKey ::
+ # The SSL private key for the server certificate.
+ # :SSLClientCA :: nil,
+ # Array of certificates that will be sent to the client.
+ # :SSLExtraChainCert :: nil,
+ # Array of certificates that will be added to the certificate chain
+ # :SSLCACertificateFile :: nil,
+ # Path to a CA certificate file
+ # :SSLCACertificatePath :: nil,
+ # Path to a directory containing CA certificates
+ # :SSLCertificateStore :: nil,
+ # OpenSSL::X509::Store used for certificate validation of the client
+ # :SSLTmpDhCallback :: nil,
+ # Callback invoked when DH parameters are required.
+ # :SSLVerifyClient ::
+ # Sets whether the client is verified. This defaults to VERIFY_NONE
+ # which is typical for an HTTPS server.
+ # :SSLVerifyDepth ::
+ # Number of CA certificates to walk when verifying a certificate chain
+ # :SSLVerifyCallback ::
+ # Custom certificate verification callback
+ # :SSLServerNameCallback::
+ # Custom servername indication callback
+ # :SSLTimeout ::
+ # Maximum session lifetime
+ # :SSLOptions ::
+ # Various SSL options
+ # :SSLCiphers ::
+ # Ciphers to be used
+ # :SSLStartImmediately ::
+ # Immediately start SSL upon connection? Defaults to true
+ # :SSLCertName ::
+ # SSL certificate name. Must be set to enable automatic certificate
+ # creation.
+ # :SSLCertComment ::
+ # Comment used during automatic certificate creation.
+
+ SSL = {
+ :ServerSoftware => "#{svrsoft} OpenSSL/#{osslv}",
+ :SSLEnable => false,
+ :SSLCertificate => nil,
+ :SSLPrivateKey => nil,
+ :SSLClientCA => nil,
+ :SSLExtraChainCert => nil,
+ :SSLCACertificateFile => nil,
+ :SSLCACertificatePath => nil,
+ :SSLCertificateStore => nil,
+ :SSLTmpDhCallback => nil,
+ :SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE,
+ :SSLVerifyDepth => nil,
+ :SSLVerifyCallback => nil, # custom verification
+ :SSLTimeout => nil,
+ :SSLOptions => nil,
+ :SSLCiphers => nil,
+ :SSLStartImmediately => true,
+ # Must specify if you use auto generated certificate.
+ :SSLCertName => nil,
+ :SSLCertComment => "Generated by Ruby/OpenSSL"
+ }
+ General.update(SSL)
+ end
+
+ module Utils
+ ##
+ # Creates a self-signed certificate with the given number of +bits+,
+ # the issuer +cn+ and a +comment+ to be stored in the certificate.
+
+ def create_self_signed_cert(bits, cn, comment)
+ rsa = OpenSSL::PKey::RSA.new(bits){|p, n|
+ case p
+ when 0; $stderr.putc "." # BN_generate_prime
+ when 1; $stderr.putc "+" # BN_generate_prime
+ when 2; $stderr.putc "*" # searching good prime,
+ # n = #of try,
+ # but also data from BN_generate_prime
+ when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q,
+ # but also data from BN_generate_prime
+ else; $stderr.putc "*" # BN_generate_prime
+ end
+ }
+ cert = OpenSSL::X509::Certificate.new
+ cert.version = 2
+ cert.serial = 1
+ name = (cn.kind_of? String) ? OpenSSL::X509::Name.parse(cn)
+ : OpenSSL::X509::Name.new(cn)
+ cert.subject = name
+ cert.issuer = name
+ cert.not_before = Time.now
+ cert.not_after = Time.now + (365*24*60*60)
+ cert.public_key = rsa.public_key
+
+ ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
+ ef.issuer_certificate = cert
+ cert.extensions = [
+ ef.create_extension("basicConstraints","CA:FALSE"),
+ ef.create_extension("keyUsage", "keyEncipherment, digitalSignature, keyAgreement, dataEncipherment"),
+ ef.create_extension("subjectKeyIdentifier", "hash"),
+ ef.create_extension("extendedKeyUsage", "serverAuth"),
+ ef.create_extension("nsComment", comment),
+ ]
+ aki = ef.create_extension("authorityKeyIdentifier",
+ "keyid:always,issuer:always")
+ cert.add_extension(aki)
+ cert.sign(rsa, "SHA256")
+
+ return [ cert, rsa ]
+ end
+ module_function :create_self_signed_cert
+ end
+
+ ##
+ #--
+ # Updates WEBrick::GenericServer with SSL functionality
+
+ class GenericServer
+
+ ##
+ # SSL context for the server when run in SSL mode
+
+ def ssl_context # :nodoc:
+ @ssl_context ||= begin
+ if @config[:SSLEnable]
+ ssl_context = setup_ssl_context(@config)
+ @logger.info("\n" + @config[:SSLCertificate].to_text)
+ ssl_context
+ end
+ end
+ end
+
+ undef listen
+
+ ##
+ # Updates +listen+ to enable SSL when the SSL configuration is active.
+
+ def listen(address, port) # :nodoc:
+ listeners = Utils::create_listeners(address, port)
+ if @config[:SSLEnable]
+ listeners.collect!{|svr|
+ ssvr = ::OpenSSL::SSL::SSLServer.new(svr, ssl_context)
+ ssvr.start_immediately = @config[:SSLStartImmediately]
+ ssvr
+ }
+ end
+ @listeners += listeners
+ setup_shutdown_pipe
+ end
+
+ ##
+ # Sets up an SSL context for +config+
+
+ def setup_ssl_context(config) # :nodoc:
+ unless config[:SSLCertificate]
+ cn = config[:SSLCertName]
+ comment = config[:SSLCertComment]
+ cert, key = Utils::create_self_signed_cert(2048, cn, comment)
+ config[:SSLCertificate] = cert
+ config[:SSLPrivateKey] = key
+ end
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.key = config[:SSLPrivateKey]
+ ctx.cert = config[:SSLCertificate]
+ ctx.client_ca = config[:SSLClientCA]
+ ctx.extra_chain_cert = config[:SSLExtraChainCert]
+ ctx.ca_file = config[:SSLCACertificateFile]
+ ctx.ca_path = config[:SSLCACertificatePath]
+ ctx.cert_store = config[:SSLCertificateStore]
+ ctx.tmp_dh_callback = config[:SSLTmpDhCallback]
+ ctx.verify_mode = config[:SSLVerifyClient]
+ ctx.verify_depth = config[:SSLVerifyDepth]
+ ctx.verify_callback = config[:SSLVerifyCallback]
+ ctx.servername_cb = config[:SSLServerNameCallback] || proc { |args| ssl_servername_callback(*args) }
+ ctx.timeout = config[:SSLTimeout]
+ ctx.options = config[:SSLOptions]
+ ctx.ciphers = config[:SSLCiphers]
+ ctx
+ end
+
+ ##
+ # ServerNameIndication callback
+
+ def ssl_servername_callback(sslsocket, hostname = nil)
+ # default
+ end
+
+ end
+end
diff --git a/tool/lib/webrick/utils.rb b/tool/lib/webrick/utils.rb
new file mode 100644
index 0000000000..a96d6f03fd
--- /dev/null
+++ b/tool/lib/webrick/utils.rb
@@ -0,0 +1,265 @@
+# frozen_string_literal: false
+#
+# utils.rb -- Miscellaneous utilities
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
+# Copyright (c) 2002 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: utils.rb,v 1.10 2003/02/16 22:22:54 gotoyuzo Exp $
+
+require 'socket'
+require 'io/nonblock'
+require 'etc'
+
+module WEBrick
+ module Utils
+ ##
+ # Sets IO operations on +io+ to be non-blocking
+ def set_non_blocking(io)
+ io.nonblock = true if io.respond_to?(:nonblock=)
+ end
+ module_function :set_non_blocking
+
+ ##
+ # Sets the close on exec flag for +io+
+ def set_close_on_exec(io)
+ io.close_on_exec = true if io.respond_to?(:close_on_exec=)
+ end
+ module_function :set_close_on_exec
+
+ ##
+ # Changes the process's uid and gid to the ones of +user+
+ def su(user)
+ if pw = Etc.getpwnam(user)
+ Process::initgroups(user, pw.gid)
+ Process::Sys::setgid(pw.gid)
+ Process::Sys::setuid(pw.uid)
+ else
+ warn("WEBrick::Utils::su doesn't work on this platform", uplevel: 1)
+ end
+ end
+ module_function :su
+
+ ##
+ # The server hostname
+ def getservername
+ Socket::gethostname
+ end
+ module_function :getservername
+
+ ##
+ # Creates TCP server sockets bound to +address+:+port+ and returns them.
+ #
+ # It will create IPV4 and IPV6 sockets on all interfaces.
+ def create_listeners(address, port)
+ unless port
+ raise ArgumentError, "must specify port"
+ end
+ sockets = Socket.tcp_server_sockets(address, port)
+ sockets = sockets.map {|s|
+ s.autoclose = false
+ ts = TCPServer.for_fd(s.fileno)
+ s.close
+ ts
+ }
+ return sockets
+ end
+ module_function :create_listeners
+
+ ##
+ # Characters used to generate random strings
+ RAND_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+ "0123456789" +
+ "abcdefghijklmnopqrstuvwxyz"
+
+ ##
+ # Generates a random string of length +len+
+ def random_string(len)
+ rand_max = RAND_CHARS.bytesize
+ ret = ""
+ len.times{ ret << RAND_CHARS[rand(rand_max)] }
+ ret
+ end
+ module_function :random_string
+
+ ###########
+
+ require "timeout"
+ require "singleton"
+
+ ##
+ # Class used to manage timeout handlers across multiple threads.
+ #
+ # Timeout handlers should be managed by using the class methods which are
+ # synchronized.
+ #
+ # id = TimeoutHandler.register(10, Timeout::Error)
+ # begin
+ # sleep 20
+ # puts 'foo'
+ # ensure
+ # TimeoutHandler.cancel(id)
+ # end
+ #
+ # will raise Timeout::Error
+ #
+ # id = TimeoutHandler.register(10, Timeout::Error)
+ # begin
+ # sleep 5
+ # puts 'foo'
+ # ensure
+ # TimeoutHandler.cancel(id)
+ # end
+ #
+ # will print 'foo'
+ #
+ class TimeoutHandler
+ include Singleton
+
+ ##
+ # Mutex used to synchronize access across threads
+ TimeoutMutex = Thread::Mutex.new # :nodoc:
+
+ ##
+ # Registers a new timeout handler
+ #
+ # +time+:: Timeout in seconds
+ # +exception+:: Exception to raise when timeout elapsed
+ def TimeoutHandler.register(seconds, exception)
+ at = Process.clock_gettime(Process::CLOCK_MONOTONIC) + seconds
+ instance.register(Thread.current, at, exception)
+ end
+
+ ##
+ # Cancels the timeout handler +id+
+ def TimeoutHandler.cancel(id)
+ instance.cancel(Thread.current, id)
+ end
+
+ def self.terminate
+ instance.terminate
+ end
+
+ ##
+ # Creates a new TimeoutHandler. You should use ::register and ::cancel
+ # instead of creating the timeout handler directly.
+ def initialize
+ TimeoutMutex.synchronize{
+ @timeout_info = Hash.new
+ }
+ @queue = Thread::Queue.new
+ @watcher = nil
+ end
+
+ # :nodoc:
+ private \
+ def watch
+ to_interrupt = []
+ while true
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ wakeup = nil
+ to_interrupt.clear
+ TimeoutMutex.synchronize{
+ @timeout_info.each {|thread, ary|
+ next unless ary
+ ary.each{|info|
+ time, exception = *info
+ if time < now
+ to_interrupt.push [thread, info.object_id, exception]
+ elsif !wakeup || time < wakeup
+ wakeup = time
+ end
+ }
+ }
+ }
+ to_interrupt.each {|arg| interrupt(*arg)}
+ if !wakeup
+ @queue.pop
+ elsif (wakeup -= now) > 0
+ begin
+ (th = Thread.start {@queue.pop}).join(wakeup)
+ ensure
+ th&.kill&.join
+ end
+ end
+ @queue.clear
+ end
+ end
+
+ # :nodoc:
+ private \
+ def watcher
+ (w = @watcher)&.alive? and return w # usual case
+ TimeoutMutex.synchronize{
+ (w = @watcher)&.alive? and next w # pathological check
+ @watcher = Thread.start(&method(:watch))
+ }
+ end
+
+ ##
+ # Interrupts the timeout handler +id+ and raises +exception+
+ def interrupt(thread, id, exception)
+ if cancel(thread, id) && thread.alive?
+ thread.raise(exception, "execution timeout")
+ end
+ end
+
+ ##
+ # Registers a new timeout handler
+ #
+ # +time+:: Timeout in seconds
+ # +exception+:: Exception to raise when timeout elapsed
+ def register(thread, time, exception)
+ info = nil
+ TimeoutMutex.synchronize{
+ (@timeout_info[thread] ||= []) << (info = [time, exception])
+ }
+ @queue.push nil
+ watcher
+ return info.object_id
+ end
+
+ ##
+ # Cancels the timeout handler +id+
+ def cancel(thread, id)
+ TimeoutMutex.synchronize{
+ if ary = @timeout_info[thread]
+ ary.delete_if{|info| info.object_id == id }
+ if ary.empty?
+ @timeout_info.delete(thread)
+ end
+ return true
+ end
+ return false
+ }
+ end
+
+ ##
+ def terminate
+ TimeoutMutex.synchronize{
+ @timeout_info.clear
+ @watcher&.kill&.join
+ }
+ end
+ end
+
+ ##
+ # Executes the passed block and raises +exception+ if execution takes more
+ # than +seconds+.
+ #
+ # If +seconds+ is zero or nil, simply executes the block
+ def timeout(seconds, exception=Timeout::Error)
+ return yield if seconds.nil? or seconds.zero?
+ # raise ThreadError, "timeout within critical session" if Thread.critical
+ id = TimeoutHandler.register(seconds, exception)
+ begin
+ yield(seconds)
+ ensure
+ TimeoutHandler.cancel(id)
+ end
+ end
+ module_function :timeout
+ end
+end
diff --git a/tool/lib/webrick/version.rb b/tool/lib/webrick/version.rb
new file mode 100644
index 0000000000..b62988bdbb
--- /dev/null
+++ b/tool/lib/webrick/version.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: false
+#--
+# version.rb -- version and release date
+#
+# Author: IPR -- Internet Programming with Ruby -- writers
+# Copyright (c) 2000 TAKAHASHI Masayoshi, GOTOU YUUZOU
+# Copyright (c) 2003 Internet Programming with Ruby writers. All rights
+# reserved.
+#
+# $IPR: version.rb,v 1.74 2003/07/22 19:20:43 gotoyuzo Exp $
+
+module WEBrick
+
+ ##
+ # The WEBrick version
+
+ VERSION = "1.7.0"
+end
diff --git a/tool/m4/ruby_setjmp_type.m4 b/tool/m4/ruby_setjmp_type.m4
index 9da9a88680..29893543a4 100644
--- a/tool/m4/ruby_setjmp_type.m4
+++ b/tool/m4/ruby_setjmp_type.m4
@@ -47,6 +47,6 @@ AS_IF([test x$setjmp_prefix:$setjmp_sigmask = xsig:], [
AC_MSG_RESULT(${setjmp_prefix}setjmp${setjmp_suffix}${setjmp_cast:+\($setjmp_cast\)}${setjmp_sigmask})
AC_DEFINE_UNQUOTED([RUBY_SETJMP(env)], [${setjmp_prefix}setjmp${setjmp_suffix}($setjmp_cast(env)${setjmp_sigmask})])
AC_DEFINE_UNQUOTED([RUBY_LONGJMP(env,val)], [${setjmp_prefix}longjmp($setjmp_cast(env),val)])
-AS_IF([test x$setjmp_prefix != x__builtin_], AC_DEFINE_UNQUOTED(RUBY_JMP_BUF, ${setjmp_sigmask+${setjmp_prefix}}jmp_buf))
+AS_IF([test "(" "$GCC" != yes ")" -o x$setjmp_prefix != x__builtin_], AC_DEFINE_UNQUOTED(RUBY_JMP_BUF, ${setjmp_sigmask+${setjmp_prefix}}jmp_buf))
AS_IF([test x$setjmp_suffix = xex], [AC_DEFINE_UNQUOTED(RUBY_USE_SETJMPEX, 1)])
])dnl
diff --git a/tool/m4/ruby_try_cxxflags.m4 b/tool/m4/ruby_try_cxxflags.m4
new file mode 100644
index 0000000000..265f79a450
--- /dev/null
+++ b/tool/m4/ruby_try_cxxflags.m4
@@ -0,0 +1,17 @@
+# -*- Autoconf -*-
+AC_DEFUN([RUBY_TRY_CXXFLAGS], [
+ save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="[$]CXXFLAGS $1"
+ AC_MSG_CHECKING([whether ]$1[ is accepted as CXXFLAGS])
+ RUBY_WERROR_FLAG([
+ AC_LANG_PUSH([C++])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[$4]], [[$5]])],
+ [$2
+ AC_MSG_RESULT(yes)],
+ [$3
+ AC_MSG_RESULT(no)])
+ ])
+ AC_LANG_POP([C++])
+ CXXFLAGS="$save_CXXFLAGS"
+ save_CXXFLAGS=
+])dnl
diff --git a/tool/make-snapshot b/tool/make-snapshot
index 79289d6bfb..131d7b91c9 100755
--- a/tool/make-snapshot
+++ b/tool/make-snapshot
@@ -54,7 +54,7 @@ PACKAGES = {
DEFAULT_PACKAGES = PACKAGES.keys - ["tar"]
if !$no7z and system("7z", out: IO::NULL)
PACKAGES["gzip"] = %w".tar.gz 7z a dummy -tgzip -mx -so"
- PACKAGES["zip"] = %w".zip 7z a -tzip -mx -mtc=off" << {out: IO::NULL}
+ PACKAGES["zip"] = %w".zip 7z a -tzip -l -mx -mtc=off" << {out: IO::NULL}
elsif gzip = ENV.delete("GZIP")
PACKAGES["gzip"].concat(gzip.shellsplit)
end
@@ -242,6 +242,16 @@ class MAKE < Struct.new(:prog, :args)
end
end
+def measure
+ clock = Process::CLOCK_MONOTONIC
+ t0 = Process.clock_gettime(clock)
+ STDOUT.flush
+ result = yield
+ printf(" %6.3f", Process.clock_gettime(clock) - t0)
+ STDOUT.flush
+ result
+end
+
def package(vcs, rev, destdir, tmp = nil)
pwd = Dir.pwd
patchlevel = false
@@ -311,7 +321,7 @@ def package(vcs, rev, destdir, tmp = nil)
end
if $srcdir
Dir.glob($srcdir + "/{tool/config.{guess,sub},gems/*.gem,.downloaded-cache/*,enc/unicode/data/**/*.txt}") do |file|
- puts "copying #{file}"
+ puts "copying #{file}" if $VERBOSE
dest = exported + file[$srcdir.size..-1]
FileUtils.mkpath(File.dirname(dest))
begin
@@ -497,11 +507,13 @@ touch-unicode-files:
system(*%W"#{YACC} -o parse.c parse.y")
end
vcs.after_export(".") if exported
+ clean.concat(Dir.glob("ext/**/autom4te.cache"))
FileUtils.rm_rf(clean) unless $keep_temp
FileUtils.rm_rf(".downloaded-cache")
if File.exist?("gems/bundled_gems")
gems = Dir.glob("gems/*.gem")
gems -= File.readlines("gems/bundled_gems").map {|line|
+ next if /^\s*(?:#|$)/ =~ line
name, version, _ = line.split(' ')
"gems/#{name}-#{version}.gem"
}
@@ -542,7 +554,7 @@ touch-unicode-files:
else
tarball = ext == ".tar" ? file : "#{$archname||v}.tar"
print "creating tarball... #{tarball}"
- if tar_create(tarball, v)
+ if measure {tar_create(tarball, v)}
puts $colorize.pass(" done")
File.utime(modified, modified, tarball) if modified
next if tarball == file
@@ -553,7 +565,7 @@ touch-unicode-files:
end
end
print "creating #{mesg} tarball... #{file}"
- done = system(*cmd, tarball, out: file)
+ done = measure {system(*cmd, tarball, out: file)}
else
print "creating #{mesg} archive... #{file}"
if Hash === cmd.last
@@ -562,7 +574,7 @@ touch-unicode-files:
else
(cmd = cmd.dup) << file << v
end
- done = system(*cmd)
+ done = measure {system(*cmd)}
end
if done
puts $colorize.pass(" done")
diff --git a/tool/mjit_tabs.rb b/tool/mjit_tabs.rb
new file mode 100644
index 0000000000..8b91af2479
--- /dev/null
+++ b/tool/mjit_tabs.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+# This is a script to run a command in ARGV, expanding tabs in some files
+# included by vm.c to normalize indentation of MJIT header. You can enable
+# this feature by passing `--without-mjit-tabs` in configure.
+#
+# Note that preprocessor of GCC converts a hard tab to one spaces, where
+# we expect it to be shown as 8 spaces. To obviate this script, we need
+# to convert all tabs to spaces in these files.
+
+require 'fileutils'
+
+EXPAND_TARGETS = %w[
+ vm*.*
+ include/ruby/ruby.h
+]
+
+# These files have no hard tab indentations. Skip normalizing these files from the glob result.
+SKIPPED_FILES = %w[
+ vm_callinfo.h
+ vm_debug.h
+ vm_exec.h
+ vm_opts.h
+]
+
+srcdir = File.expand_path('..', __dir__)
+targets = EXPAND_TARGETS.flat_map { |t| Dir.glob(File.join(srcdir, t)) } - SKIPPED_FILES.map { |f| File.join(srcdir, f) }
+sources = {}
+mtimes = {}
+
+mjit_tabs, *command = ARGV
+
+targets.each do |target|
+ next if mjit_tabs != 'false'
+ unless File.writable?(target)
+ puts "tool/mjit_without_tabs.rb: Skipping #{target.dump} as it's not writable."
+ next
+ end
+ source = File.read(target)
+ begin
+ expanded = source.gsub(/^\t+/) { |tab| ' ' * 8 * tab.length }
+ rescue ArgumentError # invalid byte sequence in UTF-8 (Travis, RubyCI)
+ puts "tool/mjit_without_tabs.rb: Skipping #{target.dump} as the encoding is #{source.encoding}."
+ next
+ end
+
+ sources[target] = source
+ mtimes[target] = File.mtime(target)
+
+ if sources[target] == expanded
+ puts "#{target.dump} has no hard tab indentation. This should be ignored in tool/mjit_without_tabs.rb."
+ end
+ File.write(target, expanded)
+ FileUtils.touch(target, mtime: mtimes[target])
+end
+
+result = system(*command)
+
+targets.each do |target|
+ if sources.key?(target)
+ File.write(target, sources[target])
+ FileUtils.touch(target, mtime: mtimes.fetch(target))
+ end
+end
+
+exit result
diff --git a/tool/mk_builtin_binary.rb b/tool/mk_builtin_binary.rb
deleted file mode 100644
index 1b3fe50ac9..0000000000
--- a/tool/mk_builtin_binary.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# make builtin_binary.inc file.
-#
-
-def dump_bin iseq
- bin = iseq.to_binary
- bin.each_byte.with_index{|b, index|
- print "\n " if (index%20) == 0
- print " 0x#{'%02x' % b.ord},"
- }
- print "\n"
-end
-
-$stdout = open('builtin_binary.inc', 'wb')
-
-puts <<H
-// -*- c -*-
-// DO NOT MODIFY THIS FILE DIRECTLY.
-// auto-generated file by #{File.basename(__FILE__)}
-
-H
-
-if ARGV.include?('--cross=yes')
- # do nothing
-else
- ary = []
- RubyVM::each_builtin{|feature, iseq|
- ary << [feature, iseq]
- }
-
- ary.each{|feature, iseq|
- print "\n""static const unsigned char #{feature}_bin[] = {"
- dump_bin(iseq)
- puts "};"
- }
-
- print "\n""static const struct builtin_binary builtin_binary[] = {\n"
- ary.each{|feature, iseq|
- puts " {#{feature.dump}, #{feature}_bin, sizeof(#{feature}_bin)},"
- }
- puts " {NULL}," # dummy sentry
- puts "};"
- puts "#define BUILTIN_BINARY_SIZE #{ary.size}"
-end
diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb
index dcd4b93532..17f0d99a50 100644
--- a/tool/mk_builtin_loader.rb
+++ b/tool/mk_builtin_loader.rb
@@ -1,8 +1,32 @@
+# Parse built-in script and make rbinc file
-def inline_text argc, prev_insn
+require 'ripper'
+require 'stringio'
+require_relative 'ruby_vm/helpers/c_escape'
+
+def string_literal(lit, str = [])
+ while lit
+ case lit.first
+ when :string_concat, :string_embexpr, :string_content
+ _, *lit = lit
+ lit.each {|s| string_literal(s, str)}
+ return str
+ when :string_literal
+ _, lit = lit
+ when :@tstring_content
+ str << lit[1]
+ return str
+ else
+ raise "unexpected #{lit.first}"
+ end
+ end
+end
+
+def inline_text argc, arg1
raise "argc (#{argc}) of inline! should be 1" unless argc == 1
- raise "1st argument should be string literal" unless prev_insn[0] == :putstring
- prev_insn[1].rstrip
+ arg1 = string_literal(arg1)
+ raise "1st argument should be string literal" unless arg1
+ arg1.join("").rstrip
end
def make_cfunc_name inlines, name, lineno
@@ -27,62 +51,110 @@ def make_cfunc_name inlines, name, lineno
end
end
-def collect_builtin base, iseq_ary, name, bs, inlines
- case type = iseq_ary[9]
- when :method
- name = iseq_ary[5]
- when :class
- name = 'class'
+def collect_locals tree
+ _type, name, (line, _cols) = tree
+ if locals = LOCALS_DB[[name, line]]
+ locals
else
+ if false # for debugging
+ pp LOCALS_DB
+ raise "not found: [#{name}, #{line}]"
+ end
end
+end
- code = iseq_ary[13]
- params = iseq_ary[10]
- prev_insn = nil
- lineno = nil
-
- code.each{|insn|
- case insn
- when Array
- # ok
- when Integer
- lineno = insn
+def collect_builtin base, tree, name, bs, inlines, locals = nil
+ while tree
+ recv = sep = mid = args = nil
+ case tree.first
+ when :def
+ locals = collect_locals(tree[1])
+ tree = tree[3]
next
- else
+ when :defs
+ locals = collect_locals(tree[3])
+ tree = tree[5]
next
+ when :class
+ name = 'class'
+ tree = tree[3]
+ next
+ when :sclass, :module
+ name = 'class'
+ tree = tree[2]
+ next
+ when :method_add_arg
+ _, mid, (_, (_, args)) = tree
+ case mid.first
+ when :call
+ _, recv, sep, mid = mid
+ when :fcall
+ _, mid = mid
+ else
+ mid = nil
+ end
+ when :vcall
+ _, mid = tree
+ when :command # FCALL
+ _, mid, (_, args) = tree
+ when :call, :command_call # CALL
+ _, recv, sep, mid, (_, args) = tree
end
-
- next unless Array === insn
- case insn[0]
- when :send
- ci = insn[1]
- if /\A__builtin_(.+)/ =~ ci[:mid]
- cfunc_name = func_name = $1
- argc = ci[:orig_argc]
+ if mid
+ raise "unknown sexp: #{mid.inspect}" unless mid.first == :@ident
+ _, mid, (lineno,) = mid
+ if recv
+ func_name = nil
+ case recv.first
+ when :var_ref
+ _, recv = recv
+ if recv.first == :@const and recv[1] == "Primitive"
+ func_name = mid.to_s
+ end
+ when :vcall
+ _, recv = recv
+ if recv.first == :@ident and recv[1] == "__builtin"
+ func_name = mid.to_s
+ end
+ end
+ collect_builtin(base, recv, name, bs, inlines) unless func_name
+ else
+ func_name = mid[/\A__builtin_(.+)/, 1]
+ end
+ if func_name
+ cfunc_name = func_name
+ args.pop unless (args ||= []).last
+ argc = args.size
if /(.+)\!\z/ =~ func_name
case $1
+ when 'attr'
+ text = inline_text(argc, args.first)
+ if text != 'inline'
+ raise "Only 'inline' is allowed to be annotated (but got: '#{text}')"
+ end
+ break
when 'cstmt'
- text = inline_text argc, prev_insn
+ text = inline_text argc, args.first
func_name = "_bi#{inlines.size}"
cfunc_name = make_cfunc_name(inlines, name, lineno)
- inlines[cfunc_name] = [lineno, text, params, func_name]
+ inlines[cfunc_name] = [lineno, text, locals, func_name]
argc -= 1
when 'cexpr', 'cconst'
- text = inline_text argc, prev_insn
+ text = inline_text argc, args.first
code = "return #{text};"
func_name = "_bi#{inlines.size}"
cfunc_name = make_cfunc_name(inlines, name, lineno)
- params = [] if $1 == 'cconst'
- inlines[cfunc_name] = [lineno, code, params, func_name]
+ locals = [] if $1 == 'cconst'
+ inlines[cfunc_name] = [lineno, code, locals, func_name]
argc -= 1
when 'cinit'
- text = inline_text argc, prev_insn
- func_name = nil
- inlines[inlines.size] = [nil, [lineno, text, nil, nil]]
+ text = inline_text argc, args.first
+ func_name = nil # required
+ inlines[inlines.size] = [lineno, text, nil, nil]
argc -= 1
end
end
@@ -94,26 +166,80 @@ def collect_builtin base, iseq_ary, name, bs, inlines
bs[func_name] = [argc, cfunc_name] if func_name
end
- else
- insn[1..-1].each{|op|
- if op.is_a?(Array) && op[0] == "YARVInstructionSequence/SimpleDataFormat"
- collect_builtin base, op, name, bs, inlines
- end
- }
+ break unless tree = args
end
- prev_insn = insn
- }
+
+ tree.each do |t|
+ collect_builtin base, t, name, bs, inlines, locals if Array === t
+ end
+ break
+ end
end
+
# ruby mk_builtin_loader.rb TARGET_FILE.rb
# #=> generate TARGET_FILE.rbinc
#
+LOCALS_DB = {} # [method_name, first_line] = locals
+
+def collect_iseq iseq_ary
+ # iseq_ary.each_with_index{|e, i| p [i, e]}
+ label = iseq_ary[5]
+ first_line = iseq_ary[8]
+ type = iseq_ary[9]
+ locals = iseq_ary[10]
+ insns = iseq_ary[13]
+
+ if type == :method
+ LOCALS_DB[[label, first_line].freeze] = locals
+ end
+
+ insns.each{|insn|
+ case insn
+ when Integer
+ # ignore
+ when Array
+ # p insn.shift # insn name
+ insn.each{|op|
+ if Array === op && op[0] == "YARVInstructionSequence/SimpleDataFormat"
+ collect_iseq op
+ end
+ }
+ end
+ }
+end
+
+def generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name)
+ f = StringIO.new
+ f.puts '{'
+ lineno += 1
+ locals.reverse_each.with_index{|param, i|
+ next unless Symbol === param
+ f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});"
+ lineno += 1
+ }
+ f.puts "#line #{body_lineno} \"#{line_file}\""
+ lineno += 1
+
+ f.puts text
+ lineno += text.count("\n") + 1
+
+ f.puts "#line #{lineno + 2} \"#{ofile}\"" # TODO: restore line number.
+ f.puts "}"
+ f.puts
+ lineno += 3
+
+ return lineno, f.string
+end
+
def mk_builtin_header file
base = File.basename(file, '.rb')
ofile = "#{file}inc"
# bs = { func_name => argc }
- collect_builtin(base, RubyVM::InstructionSequence.compile_file(file, false).to_a, 'top', bs = {}, inlines = {})
+ code = File.read(file)
+ collect_iseq RubyVM::InstructionSequence.compile(code).to_a
+ collect_builtin(base, Ripper.sexp(code), 'top', bs = {}, inlines = {})
begin
f = open(ofile, 'w')
@@ -122,34 +248,31 @@ def mk_builtin_header file
f = open(File.basename(ofile), 'w')
end
begin
+ if File::ALT_SEPARATOR
+ file = file.tr(File::ALT_SEPARATOR, File::SEPARATOR)
+ ofile = ofile.tr(File::ALT_SEPARATOR, File::SEPARATOR)
+ end
+ lineno = __LINE__
f.puts "// -*- c -*-"
f.puts "// DO NOT MODIFY THIS FILE DIRECTLY."
f.puts "// auto-generated file"
f.puts "// by #{__FILE__}"
f.puts "// with #{file}"
+ f.puts '#include "internal/compilers.h" /* for MAYBE_UNUSED */'
+ f.puts '#include "internal/warnings.h" /* for COMPILER_WARNING_PUSH */'
+ f.puts '#include "ruby/ruby.h" /* for VALUE */'
+ f.puts '#include "builtin.h" /* for RB_BUILTIN_FUNCTION */'
+ f.puts 'struct rb_execution_context_struct; /* in vm_core.h */'
f.puts
- lineno = 6
- line_file = file.gsub('\\', '/')
+ lineno = __LINE__ - lineno - 1
+ line_file = file
- inlines.each{|cfunc_name, (body_lineno, text, params, func_name)|
+ inlines.each{|cfunc_name, (body_lineno, text, locals, func_name)|
if String === cfunc_name
- f.puts "static VALUE #{cfunc_name}(rb_execution_context_t *ec, const VALUE self) {"
- lineno += 1
-
- params.reverse_each.with_index{|param, i|
- next unless Symbol === param
- f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});"
- lineno += 1
- }
- f.puts "#line #{body_lineno} \"#{line_file}\""
+ f.puts "static VALUE #{cfunc_name}(struct rb_execution_context_struct *ec, const VALUE self)"
lineno += 1
-
- f.puts text
- lineno += text.count("\n") + 1
-
- f.puts "#line #{lineno + 2} \"#{ofile}\"" # TODO: restore line number.
- f.puts "}"
- lineno += 2
+ lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name)
+ f.write str
else
# cinit!
f.puts "#line #{body_lineno} \"#{line_file}\""
@@ -161,16 +284,54 @@ def mk_builtin_header file
end
}
- f.puts "static void load_#{base}(void)"
+ bs.each_pair{|func, (argc, cfunc_name)|
+ decl = ', VALUE' * argc
+ argv = argc \
+ . times \
+ . map {|i|", argv[#{i}]"} \
+ . join('')
+ f.puts %'static void'
+ f.puts %'mjit_compile_invokebuiltin_for_#{func}(FILE *f, long index, unsigned stack_size, bool inlinable_p)'
+ f.puts %'{'
+ f.puts %' fprintf(f, " VALUE self = GET_SELF();\\n");'
+ f.puts %' fprintf(f, " typedef VALUE (*func)(rb_execution_context_t *, VALUE#{decl});\\n");'
+ if inlines.has_key? cfunc_name
+ body_lineno, text, locals, func_name = inlines[cfunc_name]
+ lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name)
+ f.puts %' if (inlinable_p) {'
+ str.gsub(/^(?!#)/, ' ').each_line {|i|
+ j = RubyVM::CEscape.rstring2cstr(i).dup
+ j.sub!(/^ return\b/ , ' val =')
+ f.printf(%' fprintf(f, "%%s", %s);\n', j)
+ }
+ f.puts(%' return;')
+ f.puts(%' }')
+ end
+ if argc > 0
+ f.puts %' if (index == -1) {'
+ f.puts %' fprintf(f, " const VALUE *argv = &stack[%d];\\n", stack_size - #{argc});'
+ f.puts %' }'
+ f.puts %' else {'
+ f.puts %' fprintf(f, " const unsigned int lnum = GET_ISEQ()->body->local_table_size;\\n");'
+ f.puts %' fprintf(f, " const VALUE *argv = GET_EP() - lnum - VM_ENV_DATA_SIZE + 1 + %ld;\\n", index);'
+ f.puts %' }'
+ end
+ f.puts %' fprintf(f, " func f = (func)%"PRIdPTR"; /* == #{cfunc_name} */\\n", (intptr_t)#{cfunc_name});'
+ f.puts %' fprintf(f, " val = f(ec, self#{argv});\\n");'
+ f.puts %'}'
+ f.puts
+ }
+
+ f.puts "void Init_builtin_#{base}(void)"
f.puts "{"
table = "#{base}_table"
f.puts " // table definition"
f.puts " static const struct rb_builtin_function #{table}[] = {"
bs.each.with_index{|(func, (argc, cfunc_name)), i|
- f.puts " RB_BUILTIN_FUNCTION(#{i}, #{func}, #{cfunc_name}, #{argc}),"
+ f.puts " RB_BUILTIN_FUNCTION(#{i}, #{func}, #{cfunc_name}, #{argc}, mjit_compile_invokebuiltin_for_#{func}),"
}
- f.puts " RB_BUILTIN_FUNCTION(-1, NULL, NULL, 0),"
+ f.puts " RB_BUILTIN_FUNCTION(-1, NULL, NULL, 0, 0),"
f.puts " };"
f.puts
@@ -184,7 +345,6 @@ def mk_builtin_header file
}
f.puts "COMPILER_WARNING_POP"
-
f.puts
f.puts " // load"
f.puts " rb_load_with_builtin_functions(#{base.dump}, #{table});"
diff --git a/tool/mk_call_iseq_optimized.rb b/tool/mk_call_iseq_optimized.rb
deleted file mode 100644
index eba44531c2..0000000000
--- a/tool/mk_call_iseq_optimized.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-
-puts <<EOS
-/* -*- c -*- */
-#if 1 /* enable or disable this optimization */
-
-/* DO NOT EDIT THIS FILE DIRECTLY
- *
- * This file is generated by tool/mk_call_iseq_optimized.rb
- */
-
-EOS
-
-P = (0..3)
-L = (0..5)
-
-def fname param, local
- "vm_call_iseq_setup_normal_0start_#{param}params_#{local}locals"
-end
-
-P.each{|param|
- L.each{|local|
- puts <<EOS
-static VALUE
-#{fname(param, local)}(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling, struct rb_call_data *cd)
-{
- RB_DEBUG_COUNTER_INC(ccf_iseq_fix);
- return vm_call_iseq_setup_normal(ec, cfp, calling, cd->cc.me, 0, #{param}, #{local});
-}
-
-EOS
- #
- }
-}
-
-puts <<EOS
-/* vm_call_iseq_handlers[param][local] */
-static const vm_call_handler vm_call_iseq_handlers[][#{L.to_a.size}] = {
-#{P.map{|param| '{' + L.map{|local| fname(param, local)}.join(",\n ") + '}'}.join(",\n")}
-};
-
-static inline vm_call_handler
-vm_call_iseq_setup_func(const struct rb_call_info *ci, const int param_size, const int local_size)
-{
- if (UNLIKELY(ci->flag & VM_CALL_TAILCALL)) {
- return &vm_call_iseq_setup_tailcall_0start;
- }
- else if (0) { /* to disable optimize */
- return &vm_call_iseq_setup_normal_0start;
- }
- else {
- if (param_size <= #{P.end} &&
- local_size <= #{L.end}) {
- VM_ASSERT(local_size >= 0);
- return vm_call_iseq_handlers[param_size][local_size];
- }
- return &vm_call_iseq_setup_normal_0start;
- }
-}
-
-#else
-
-
-static inline vm_call_handler
-vm_call_iseq_setup_func(const struct rb_call_info *ci, const int param_size, const int local_size)
-{
- if (UNLIKELY(ci->flag & VM_CALL_TAILCALL)) {
- return &vm_call_iseq_setup_tailcall_0start;
- }
- else {
- return &vm_call_iseq_setup_normal_0start;
- }
-}
-#endif
-EOS
diff --git a/tool/mkconfig.rb b/tool/mkconfig.rb
index 05ecb815ca..c4f9d5bf2f 100755
--- a/tool/mkconfig.rb
+++ b/tool/mkconfig.rb
@@ -283,9 +283,9 @@ print <<EOS
# require 'rbconfig'
#
# print <<-END_OF_MAKEFILE
- # prefix = \#{Config::MAKEFILE_CONFIG['prefix']}
- # exec_prefix = \#{Config::MAKEFILE_CONFIG['exec_prefix']}
- # bindir = \#{Config::MAKEFILE_CONFIG['bindir']}
+ # prefix = \#{RbConfig::MAKEFILE_CONFIG['prefix']}
+ # exec_prefix = \#{RbConfig::MAKEFILE_CONFIG['exec_prefix']}
+ # bindir = \#{RbConfig::MAKEFILE_CONFIG['bindir']}
# END_OF_MAKEFILE
#
# => prefix = /usr/local
@@ -295,7 +295,7 @@ print <<EOS
# RbConfig.expand is used for resolving references like above in rbconfig.
#
# require 'rbconfig'
- # p Config.expand(Config::MAKEFILE_CONFIG["bindir"])
+ # p RbConfig.expand(RbConfig::MAKEFILE_CONFIG["bindir"])
# # => "/usr/local/bin"
MAKEFILE_CONFIG = {}
CONFIG.each{|k,v| MAKEFILE_CONFIG[k] = v.dup}
@@ -333,8 +333,8 @@ print <<EOS
# :nodoc:
# call-seq:
#
- # RbConfig.fire_update!(key, val) -> string
- # RbConfig.fire_update!(key, val, mkconf, conf) -> string
+ # RbConfig.fire_update!(key, val) -> array
+ # RbConfig.fire_update!(key, val, mkconf, conf) -> array
#
# updates +key+ in +mkconf+ with +val+, and all values depending on
# the +key+ in +mkconf+.
diff --git a/tool/mkrunnable.rb b/tool/mkrunnable.rb
index 01756a3529..cb211fd474 100755
--- a/tool/mkrunnable.rb
+++ b/tool/mkrunnable.rb
@@ -45,6 +45,10 @@ end
def ln_safe(src, dest)
ln_sf(src, dest)
+rescue Errno::ENOENT
+ # Windows disallows to create broken symboic links, probably because
+ # it is a kind of reparse points.
+ raise if File.exist?(src)
end
alias ln_dir_safe ln_safe
@@ -64,8 +68,8 @@ def relative_path_from(path, base)
base = clean_path(base)
path, base = [path, base].map{|s|s.split("/")}
until path.empty? or base.empty? or path[0] != base[0]
- path.shift
- base.shift
+ path.shift
+ base.shift
end
path, base = [path, base].map{|s|s.join("/")}
if /(\A|\/)\.\.\// =~ base
diff --git a/tool/pure_parser.rb b/tool/pure_parser.rb
index dfd66ffc84..21c87cc5d6 100755
--- a/tool/pure_parser.rb
+++ b/tool/pure_parser.rb
@@ -1,4 +1,4 @@
-#!/usr/bin/ruby -pi
+#!/usr/bin/ruby -pi.bak
BEGIN {
# pathological setting
ENV['LANG'] = ENV['LC_MESSAGES'] = ENV['LC_ALL'] = 'C'
diff --git a/tool/rbinstall.rb b/tool/rbinstall.rb
index 060390626f..7232865c9e 100755
--- a/tool/rbinstall.rb
+++ b/tool/rbinstall.rb
@@ -20,7 +20,7 @@ require 'fileutils'
require 'shellwords'
require 'optparse'
require 'optparse/shellwords'
-require 'ostruct'
+require 'pathname'
require 'rubygems'
begin
require "zlib"
@@ -39,6 +39,7 @@ def parse_args(argv = ARGV)
$make = 'make'
$mflags = []
$install = []
+ $installed = {}
$installed_list = nil
$exclude = []
$dryrun = false
@@ -148,7 +149,9 @@ end
$install_procs = Hash.new {[]}
def install?(*types, &block)
- $install_procs[:all] <<= block
+ unless types.delete(:nodefault)
+ $install_procs[:all] <<= block
+ end
types.each do |type|
$install_procs[type] <<= block
end
@@ -170,9 +173,12 @@ def install(src, dest, options = {})
options = options.clone
strip = options.delete(:strip)
options[:preserve] = true
+ srcs = Array(src).select {|s| !$installed[$made_dirs[dest] ? File.join(dest, s) : dest]}
+ return if srcs.empty?
+ src = srcs if Array === src
d = with_destdir(dest)
super(src, d, **options)
- srcs = Array(src)
+ srcs.each {|s| $installed[$made_dirs[dest] ? File.join(dest, s) : dest] = true}
if strip
d = srcs.map {|s| File.join(d, File.basename(s))} if $made_dirs[dest]
strip_file(d)
@@ -478,7 +484,12 @@ _=_\\
=end
EOS
-installer = Struct.new(:ruby_shebang, :ruby_bin, :ruby_install_name, :stub, :trans)
+installer = Struct.new(:ruby_shebang, :ruby_bin, :ruby_install_name, :stub, :trans) do
+ def transform(name)
+ RbConfig.expand(trans[name])
+ end
+end
+
$script_installer = Class.new(installer) do
ruby_shebang = File.join(bindir, ruby_install_name)
if File::ALT_SEPARATOR
@@ -523,7 +534,7 @@ $script_installer = Class.new(installer) do
end
def install(src, cmd)
- cmd = cmd.sub(/[^\/]*\z/m) {|n| RbConfig.expand(trans[n])}
+ cmd = cmd.sub(/[^\/]*\z/m) {|n| transform(n)}
shebang, body = open(src, "rb") do |f|
next f.gets, f.read
@@ -628,8 +639,13 @@ install?(:local, :comm, :man) do
class << (w = [])
alias print push
end
- open(mdoc) {|r| Mdoc2Man.mdoc2man(r, w)}
- w = w.join("")
+ if File.basename(mdoc).start_with?('bundle') ||
+ File.basename(mdoc).start_with?('gemfile')
+ w = File.read(mdoc)
+ else
+ open(mdoc) {|r| Mdoc2Man.mdoc2man(r, w)}
+ w = w.join("")
+ end
if compress
require 'tmpdir'
Dir.mktmpdir("man") {|d|
@@ -646,6 +662,20 @@ install?(:local, :comm, :man) do
end
end
+install?(:dbg, :nodefault) do
+ prepare "debugger commands", bindir
+ prepare "debugger scripts", rubylibdir
+ conf = RbConfig::MAKEFILE_CONFIG.merge({"prefix"=>"${prefix#/}"})
+ Dir.glob(File.join(srcdir, "template/ruby-*db.in")) do |src|
+ cmd = $script_installer.transform(File.basename(src, ".in"))
+ open_for_install(File.join(bindir, cmd), $script_mode) {
+ RbConfig.expand(File.read(src), conf)
+ }
+ end
+ install File.join(srcdir, "misc/lldb_cruby.py"), File.join(rubylibdir, "lldb_cruby.py")
+ install File.join(srcdir, ".gdbinit"), File.join(rubylibdir, "gdbinit")
+end
+
module RbInstall
module Specs
class FileCollector
@@ -672,6 +702,10 @@ module RbInstall
when "lib"
base = @base_dir
prefix = base.sub(/lib\/.*?\z/, "") + "lib/"
+ # for lib/net/net-smtp.gemspec
+ if m = Pathname.new(@gemspec).basename(".gemspec").to_s.match(/.*\-(.*)\z/)
+ base = "#{@base_dir}/#{m[1]}" unless remove_prefix(prefix, @base_dir).include?(m[1])
+ end
end
if base
@@ -679,7 +713,7 @@ module RbInstall
remove_prefix(prefix, ruby_source)
end
else
- [remove_prefix(File.dirname(@gemspec) + '/', @gemspec.gsub(/gemspec/, 'rb'))]
+ [File.basename(@gemspec, '.gemspec') + '.rb']
end
end
@@ -710,28 +744,37 @@ module RbInstall
end
end
- class UnpackedInstaller < Gem::Installer
- module DirPackage
- def extract_files(destination_dir, pattern = "*")
- path = File.dirname(@gem.path)
- return if path == destination_dir
- File.chmod(0700, destination_dir)
- mode = pattern == "bin/*" ? $script_mode : $data_mode
- spec.files.each do |f|
- src = File.join(path, f)
- dest = File.join(without_destdir(destination_dir), f)
- makedirs(dest[/.*(?=\/)/m])
- install src, dest, :mode => mode
- end
- File.chmod($dir_mode, destination_dir)
- end
+ class DirPackage
+ attr_reader :spec
+
+ attr_accessor :dir_mode
+ attr_accessor :prog_mode
+ attr_accessor :data_mode
+
+ def initialize(spec)
+ @spec = spec
+ @src_dir = File.dirname(@spec.loaded_from)
end
- def initialize(spec, *options)
- super(spec.loaded_from, *options)
- @package.extend(DirPackage).spec = spec
+ def extract_files(destination_dir, pattern = "*")
+ return if @src_dir == destination_dir
+ File.chmod(0700, destination_dir) unless $dryrun
+ mode = pattern == File.join(spec.bindir, '*') ? prog_mode : data_mode
+ destdir = without_destdir(destination_dir)
+ spec.files.each do |f|
+ src = File.join(@src_dir, f)
+ dest = File.join(destdir, f)
+ makedirs(dest[/.*(?=\/)/m])
+ install src, dest, :mode => mode
+ end
+ File.chmod(dir_mode, destination_dir) unless $dryrun
end
+ end
+ class GemInstaller < Gem::Installer
+ end
+
+ class UnpackedInstaller < GemInstaller
def write_cache_file
end
@@ -771,25 +814,56 @@ module RbInstall
end
false
end
+
+ def write_spec
+ super unless $dryrun
+ $installed_list.puts(without_destdir(spec_file)) if $installed_list
+ end
end
-end
-class Gem::Installer
- install = instance_method(:install)
- define_method(:install) do
- spec.post_install_message = nil
- begin
+ class GemInstaller
+ def install
+ spec.post_install_message = nil
u = File.umask(0022)
- install.bind(self).call
+ if $dryrun
+ fu = ::Object.class_eval do
+ fu = remove_const(:FileUtils)
+ const_set(:FileUtils, fu::NoWrite)
+ fu
+ end
+ dir_mode = options.delete(:dir_mode)
+ end
+ super
ensure
+ options[:dir_mode] = dir_mode if dir_mode
+ if fu
+ ::Object.class_eval do
+ remove_const(:FileUtils)
+ const_set(:FileUtils, fu)
+ end
+ end
File.umask(u)
end
- end
- generate_bin_script = instance_method(:generate_bin_script)
- define_method(:generate_bin_script) do |filename, bindir|
- generate_bin_script.bind(self).call(filename, bindir)
- File.chmod($script_mode, File.join(bindir, formatted_program_filename(filename)))
+ def generate_bin_script(filename, bindir)
+ name = formatted_program_filename(filename)
+ unless $dryrun
+ super
+ File.chmod($script_mode, File.join(bindir, name))
+ end
+ $installed_list.puts(File.join(without_destdir(bindir), name)) if $installed_list
+ end
+
+ def verify_gem_home # :nodoc:
+ end
+
+ def ensure_writable_dir(dir)
+ $made_dirs.fetch(d = without_destdir(dir)) do
+ $made_dirs[d] = true
+ super unless $dryrun
+ $installed_list.puts(d) if $installed_list
+ end
+ end
end
end
@@ -802,27 +876,38 @@ install?(:ext, :arch, :gem, :'default-gems', :'default-gems-arch') do
install_default_gem('ext', srcdir)
end
-def load_gemspec(file)
+def load_gemspec(file, expanded = false)
file = File.realpath(file)
code = File.read(file, encoding: "utf-8:-")
- code.gsub!(/`git.*?`/m, '""')
- code.gsub!(/%x\[git.*?\]/m, '""')
+ code.gsub!(/(?:`git[^\`]*`|%x\[git[^\]]*\])\.split\([^\)]*\)/m) do
+ files = []
+ if expanded
+ base = File.dirname(file)
+ Dir.glob("**/*", File::FNM_DOTMATCH, base: base) do |n|
+ case File.basename(n); when ".", ".."; next; end
+ next if File.directory?(File.join(base, n))
+ files << n.dump
+ end
+ end
+ "[" + files.join(", ") + "]"
+ end
spec = eval(code, binding, file)
unless Gem::Specification === spec
raise TypeError, "[#{file}] isn't a Gem::Specification (#{spec.class} instead)."
end
spec.loaded_from = file
+ spec.files.reject! {|n| n.end_with?(".gemspec") or n.start_with?(".git")}
+
spec
end
def install_default_gem(dir, srcdir)
gem_dir = Gem.default_dir
- directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => $dir_mode)
- prepare "default gems from #{dir}", gem_dir, directories
+ install_dir = with_destdir(gem_dir)
+ prepare "default gems from #{dir}", gem_dir
+ makedirs(Gem.ensure_default_gem_subdirectories(install_dir, $dir_mode).map {|d| File.join(gem_dir, d)})
- spec_dir = File.join(gem_dir, directories.grep(/^spec/)[0])
- default_spec_dir = "#{spec_dir}/default"
- makedirs(default_spec_dir)
+ default_spec_dir = Gem.default_specifications_dir
gems = Dir.glob("#{srcdir}/#{dir}/**/*.gemspec").map {|src|
spec = load_gemspec(src)
@@ -835,7 +920,7 @@ def install_default_gem(dir, srcdir)
gems.compact.sort_by(&:name).each do |gemspec|
old_gemspecs = Dir[File.join(with_destdir(default_spec_dir), "#{gemspec.name}-*.gemspec")]
if old_gemspecs.size > 0
- old_gemspecs.each {|spec| FileUtils.rm spec }
+ old_gemspecs.each {|spec| rm spec }
end
full_name = "#{gemspec.name}-#{gemspec.version}"
@@ -864,9 +949,9 @@ end
install?(:ext, :comm, :gem, :'bundled-gems') do
gem_dir = Gem.default_dir
- directories = Gem.ensure_gem_subdirectories(gem_dir, :mode => $dir_mode)
- prepare "bundled gems", gem_dir, directories
install_dir = with_destdir(gem_dir)
+ prepare "bundled gems", gem_dir
+ makedirs(Gem.ensure_gem_subdirectories(install_dir, $dir_mode).map {|d| File.join(gem_dir, d)})
installed_gems = {}
options = {
:install_dir => install_dir,
@@ -875,25 +960,37 @@ install?(:ext, :comm, :gem, :'bundled-gems') do
:ignore_dependencies => true,
:dir_mode => $dir_mode,
:data_mode => $data_mode,
- :prog_mode => $prog_mode,
+ :prog_mode => $script_mode,
:wrappers => true,
:format_executable => true,
}
gem_ext_dir = "#$extout/gems/#{CONFIG['arch']}"
extensions_dir = Gem::StubSpecification.gemspec_stub("", gem_dir, gem_dir).extensions_dir
- dirs = Gem::Util.glob_files_in_dir "*/", "#{srcdir}/gems"
- Gem::Specification.each_gemspec(dirs) do |path|
- spec = load_gemspec(path)
+ File.foreach("#{srcdir}/gems/bundled_gems") do |name|
+ next if /^\s*(?:#|$)/ =~ name
+ next unless /^(\S+)\s+(\S+).*/ =~ name
+ gem_name = "#$1-#$2"
+ path = "#{srcdir}/.bundle/gems/#{gem_name}/#{gem_name}.gemspec"
+ if File.exist?(path)
+ spec = load_gemspec(path)
+ else
+ path = "#{srcdir}/.bundle/gems/#{gem_name}/#$1.gemspec"
+ next unless File.exist?(path)
+ spec = load_gemspec(path, true)
+ end
next unless spec.platform == Gem::Platform::RUBY
- next unless spec.full_name == path[srcdir.size..-1][/\A\/gems\/([^\/]+)/, 1]
+ next unless spec.full_name == gem_name
spec.extension_dir = "#{extensions_dir}/#{spec.full_name}"
if File.directory?(ext = "#{gem_ext_dir}/#{spec.full_name}")
spec.extensions[0] ||= "-"
end
- ins = RbInstall::UnpackedInstaller.new(spec, options)
+ package = RbInstall::DirPackage.new spec
+ ins = RbInstall::UnpackedInstaller.new(package, options)
puts "#{INDENT}#{spec.name} #{spec.version}"
ins.install
- File.chmod($data_mode, File.join(install_dir, "specifications", "#{spec.full_name}.gemspec"))
+ unless $dryrun
+ File.chmod($data_mode, File.join(install_dir, "specifications", "#{spec.full_name}.gemspec"))
+ end
unless spec.extensions.empty?
install_recursive(ext, spec.extension_dir)
end
@@ -901,6 +998,7 @@ install?(:ext, :comm, :gem, :'bundled-gems') do
end
installed_gems, gems = Dir.glob(srcdir+'/gems/*.gem').partition {|gem| installed_gems.key?(File.basename(gem, '.gem'))}
unless installed_gems.empty?
+ prepare "bundled gem cache", gem_dir+"/cache"
install installed_gems, gem_dir+"/cache"
end
next if gems.empty?
@@ -908,7 +1006,8 @@ install?(:ext, :comm, :gem, :'bundled-gems') do
Gem.instance_variable_set(:@ruby, with_destdir(File.join(bindir, ruby_install_name)))
silent = Gem::SilentUI.new
gems.each do |gem|
- inst = Gem::Installer.new(gem, options)
+ package = Gem::Package.new(gem)
+ inst = RbInstall::GemInstaller.new(package, options)
inst.spec.extension_dir = with_destdir(inst.spec.extension_dir)
begin
Gem::DefaultUserInteraction.use_ui(silent) {inst.install}
diff --git a/tool/rbuninstall.rb b/tool/rbuninstall.rb
index eb324c966e..f0c286012c 100755
--- a/tool/rbuninstall.rb
+++ b/tool/rbuninstall.rb
@@ -23,14 +23,15 @@ BEGIN {
$files = []
}
list = ($_.chomp!('/') ? $dirs : $files)
-$_ = File.join($destdir, $_) if $destdir
list << $_
END {
status = true
- $\ = ors = (!$dryrun and $tty) ? "\e[K\r" : "\n"
+ $\ = nil
+ ors = (!$dryrun and $tty) ? "\e[K\r" : "\n"
$files.each do |file|
- print "rm #{file}"
+ print "rm #{file}#{ors}"
unless $dryrun
+ file = File.join($destdir, file) if $destdir
begin
File.unlink(file)
rescue Errno::ENOENT
@@ -45,15 +46,17 @@ END {
unlink[dir] = true
end
while dir = $dirs.pop
- print "rmdir #{dir}"
+ dir = File.dirname(dir) while File.basename(dir) == '.'
+ print "rmdir #{dir}#{ors}"
unless $dryrun
+ realdir = $destdir ? File.join($destdir, dir) : dir
begin
begin
unlink.delete(dir)
- Dir.rmdir(dir)
+ Dir.rmdir(realdir)
rescue Errno::ENOTDIR
- raise unless File.symlink?(dir)
- File.unlink(dir)
+ raise unless File.symlink?(realdir)
+ File.unlink(realdir)
end
rescue Errno::ENOENT, Errno::ENOTEMPTY
rescue
@@ -65,7 +68,6 @@ END {
end
end
end
- $\ = nil
print ors.chomp
exit(status)
}
diff --git a/tool/redmine-backporter.rb b/tool/redmine-backporter.rb
index 9281219faa..9d1f5fbe48 100755
--- a/tool/redmine-backporter.rb
+++ b/tool/redmine-backporter.rb
@@ -241,7 +241,7 @@ def find_svn_log(pattern)
end
def find_git_log(pattern)
- `git #{RUBY_REPO_PATH ? "-C #{RUBY_REPO_PATH.shellecape}" : ""} log --grep="#{pattern}"`
+ `git #{RUBY_REPO_PATH ? "-C #{RUBY_REPO_PATH.shellescape}" : ""} log --grep="#{pattern}"`
end
def show_last_journal(http, uri)
@@ -271,7 +271,7 @@ def backport_command_string
# check if the Git revision is included in trunk
begin
- uri = URI("#{REDMINE_BASE}/projects/ruby-trunk/repository/git/revisions/#{c}")
+ uri = URI("#{REDMINE_BASE}/projects/ruby-master/repository/git/revisions/#{c}")
uri.read($openuri_options)
true
rescue
@@ -301,7 +301,7 @@ class CommandSyntaxError < RuntimeError; end
commands = {
"ls" => proc{|args|
raise CommandSyntaxError unless /\A(\d+)?\z/ =~ args
- uri = URI(REDMINE_BASE+'/projects/ruby-trunk/issues.json?'+URI.encode_www_form(@query.dup.merge('page' => ($1 ? $1.to_i : 1))))
+ uri = URI(REDMINE_BASE+'/projects/ruby-master/issues.json?'+URI.encode_www_form(@query.dup.merge('page' => ($1 ? $1.to_i : 1))))
# puts uri
res = JSON(uri.read($openuri_options))
@issues = issues = res["issues"]
@@ -379,10 +379,10 @@ eom
case args
when /\Ar?(\d+)\z/ # SVN
rev = $1
- uri = URI("#{REDMINE_BASE}/projects/ruby-trunk/repository/trunk/revisions/#{rev}/issues.json")
+ uri = URI("#{REDMINE_BASE}/projects/ruby-master/repository/trunk/revisions/#{rev}/issues.json")
when /\A\h{7,40}\z/ # Git
rev = args
- uri = URI("#{REDMINE_BASE}/projects/ruby-trunk/repository/git/revisions/#{rev}/issues.json")
+ uri = URI("#{REDMINE_BASE}/projects/ruby-master/repository/git/revisions/#{rev}/issues.json")
else
raise CommandSyntaxError
end
@@ -447,8 +447,12 @@ eom
end
if log && rev
str = log[/merge revision\(s\) ([^:]+)(?=:)/]
- str.insert(5, "d")
- str = "ruby_#{TARGET_VERSION.tr('.','_')} #{rev} #{str}."
+ if str
+ str.insert(5, "d")
+ str = "ruby_#{TARGET_VERSION.tr('.','_')} #{rev} #{str}."
+ else
+ str = "ruby_#{TARGET_VERSION.tr('.','_')} #{rev}."
+ end
if notes
str << "\n"
str << notes
diff --git a/tool/releng/gen-mail.rb b/tool/releng/gen-mail.rb
new file mode 100755
index 0000000000..b958a64e65
--- /dev/null
+++ b/tool/releng/gen-mail.rb
@@ -0,0 +1,50 @@
+#!/usr/bin/env ruby
+require "open-uri"
+require "yaml"
+
+lang = ARGV.shift
+unless lang
+ abort "usage: #$1 {en,ja} | pbcopy"
+end
+
+# Confirm current directory is www.ruby-lang.org's working directory
+def confirm_w_r_l_o_wd
+ File.foreach('.git/config') do |line|
+ return true if line.include?('git@github.com:ruby/www.ruby-lang.org.git')
+ end
+ abort "Run this script in www.ruby-lang.org's working directory"
+end
+confirm_w_r_l_o_wd
+
+releases = YAML.load_file('_data/releases.yml')
+
+url = "https://hackmd.io/@naruse/ruby-relnote-#{lang}/download"
+src = URI(url).read
+src.gsub!(/[ \t]+$/, "")
+src.sub!(/(?<!\n)\z/, "\n")
+src.sub!(/^breaks: false\n/, '')
+
+if /^\{% assign release = site.data.releases \| where: "version", "([^"]+)" \| first %\}/ =~ src
+ version = $1
+else
+ abort %[#{url} doesn't include `{% assign release = site.data.releases | where: "version", "<version>" | first %}`]
+end
+
+release = releases.find{|rel|rel['version'] == version}
+unless release
+ abort "#{version} is not found in '_data/releases.yml'"
+end
+
+src.gsub!(/^{% assign .*\n/, '')
+src.gsub!(/\{\{(.*?)\}\}/) do
+ var = $1.strip
+ case var
+ when /\Arelease\.(.*)/
+ val = release.dig(*$1.split('.'))
+ raise "invalid variable '#{var}'" unless val
+ else
+ raise "unknown variable '#{var}'"
+ end
+ val
+end
+puts src
diff --git a/tool/releng/gen-release-note.rb b/tool/releng/gen-release-note.rb
new file mode 100755
index 0000000000..559ddeba1b
--- /dev/null
+++ b/tool/releng/gen-release-note.rb
@@ -0,0 +1,36 @@
+#!/usr/bin/env ruby
+require 'open-uri'
+require 'time'
+require 'yaml'
+
+# Confirm current directory is www.ruby-lang.org's working directory
+def confirm_w_r_l_o_wd
+ File.foreach('.git/config') do |line|
+ return true if line.include?('git@github.com:ruby/www.ruby-lang.org.git')
+ end
+ abort "Run this script in www.ruby-lang.org's working directory"
+end
+confirm_w_r_l_o_wd
+
+%w[
+ https://hackmd.io/@naruse/ruby-relnote-en/download
+ https://hackmd.io/@naruse/ruby-relnote-ja/download
+].each do |url|
+ src = URI(url).read
+ src.gsub!(/[ \t]+$/, "")
+ src.sub!(/\s+\z/, "\n")
+ src.sub!(/^breaks: false\n/, '')
+ if /^\{% assign release = site.data.releases \| where: "version", "([^"]+)" \| first %\}/ =~ src
+ version = $1
+ else
+ abort %[#{url} doesn't include `{% assign release = site.data.releases | where: "version", "<version>" | first %}`]
+ end
+ puts "#{url} -> #{version}"
+
+
+ # Write release note article
+ path = Time.parse(src[/^date: (.*)/, 1]).
+ strftime("./#{src[/^lang: (\w+)/, 1]}/news/_posts/%Y-%m-%d-ruby-#{version}-released.md")
+ puts path
+ File.write(path, src)
+end
diff --git a/tool/releng/update-www-meta.rb b/tool/releng/update-www-meta.rb
new file mode 100755
index 0000000000..8a5651dcd0
--- /dev/null
+++ b/tool/releng/update-www-meta.rb
@@ -0,0 +1,213 @@
+#!/usr/bin/env ruby
+require "open-uri"
+require "yaml"
+
+class Tarball
+ attr_reader :version, :size, :sha1, :sha256, :sha512
+
+ def initialize(version, url, size, sha1, sha256, sha512)
+ @url = url
+ @size = size
+ @sha1 = sha1
+ @sha256 = sha256
+ @sha512 = sha512
+ @version = version
+ @xy = version[/\A\d+\.\d+/]
+ end
+
+ def gz?; @url.end_with?('.gz'); end
+ def zip?; @url.end_with?('.zip'); end
+ def xz?; @url.end_with?('.xz'); end
+
+ def ext; @url[/(?:zip|tar\.(?:gz|xz))\z/]; end
+
+ def to_md
+ <<eom
+* <https://cache.ruby-lang.org/pub/ruby/#{@xy}/ruby-#{@version}.#{ext}>
+
+ SIZE: #{@size} bytes
+ SHA1: #{@sha1}
+ SHA256: #{@sha256}
+ SHA512: #{@sha512}
+eom
+ end
+
+ # * /home/naruse/obj/ruby-trunk/tmp/ruby-2.6.0-preview3.tar.gz
+ # SIZE: 17116009 bytes
+ # SHA1: 21f62c369661a2ab1b521fd2fa8191a4273e12a1
+ # SHA256: 97cea8aa63dfa250ba6902b658a7aa066daf817b22f82b7ee28f44aec7c2e394
+ # SHA512: 1e2042324821bb4e110af7067f52891606dcfc71e640c194ab1c117f0b941550e0b3ac36ad3511214ac80c536b9e5cfaf8789eec74cf56971a832ea8fc4e6d94
+ def self.parse(wwwdir, version)
+ unless /\A(\d+)\.(\d+)\.(\d+)(?:-(?:preview|rc)\d+)?\z/ =~ version
+ raise "unexpected version string '#{version}'"
+ end
+ x = $1.to_i
+ y = $2.to_i
+ z = $3.to_i
+ # previous tag for git diff --shortstat
+ # It's only for x.y.0 release
+ if z != 0
+ prev_tag = nil
+ elsif y != 0
+ prev_tag = "v#{x}_#{y-1}_0"
+ prev_ver = "#{x}.#{y-1}.0"
+ elsif x == 3 && y == 0 && z == 0
+ prev_tag = "v2_7_0"
+ prev_ver = "2.7.0"
+ else
+ raise "unexpected version for prev_ver '#{version}'"
+ end
+
+ uri = "https://cache.ruby-lang.org/pub/tmp/ruby-info-#{version}-draft.yml"
+ info = YAML.load(URI(uri).read)
+ if info.size != 1
+ raise "unexpected info.yml '#{uri}'"
+ end
+ tarballs = []
+ info[0]["size"].each_key do |ext|
+ url = info[0]["url"][ext]
+ size = info[0]["size"][ext]
+ sha1 = info[0]["sha1"][ext]
+ sha256 = info[0]["sha256"][ext]
+ sha512 = info[0]["sha512"][ext]
+ tarball = Tarball.new(version, url, size, sha1, sha256, sha512)
+ tarballs << tarball
+ end
+
+ if prev_tag
+ # show diff shortstat
+ tag = "v#{version.gsub(/[.\-]/, '_')}"
+ rubydir = File.expand_path(File.join(__FILE__, '../../../'))
+ puts %`git -C #{rubydir} diff --shortstat #{prev_tag}..#{tag}`
+ stat = `git -C #{rubydir} diff --shortstat #{prev_tag}..#{tag}`
+ files_changed, insertions, deletions = stat.scan(/\d+/)
+ end
+
+ xy = version[/\A\d+\.\d+/]
+ #puts "## Download\n\n"
+ #tarballs.each do |tarball|
+ # puts tarball.to_md
+ #end
+ update_branches_yml(version, xy, wwwdir)
+ update_downloads_yml(version, xy, wwwdir)
+ update_releases_yml(version, xy, tarballs, wwwdir, files_changed, insertions, deletions)
+ end
+
+ def self.update_branches_yml(ver, xy, wwwdir)
+ filename = "_data/branches.yml"
+ data = File.read(File.join(wwwdir, filename))
+ if data.include?("\n- name: #{xy}\n")
+ data.sub!(/\n- name: #{Regexp.escape(xy)}\n(?: .*\n)*/) do |node|
+ unless ver.include?("-")
+ # assume this is X.Y.0 release
+ node.sub!(/^ status: preview\n/, " status: normal maintenance\n")
+ node.sub!(/^ date:\n/, " date: #{Time.now.year}-12-25\n")
+ end
+ node
+ end
+ else
+ if ver.include?("-")
+ status = "preview"
+ year = nil
+ else
+ status = "normal maintenance"
+ year = Time.now.year
+ end
+ entry = <<eom
+- name: #{xy}
+ status: #{status}
+ date:#{ year && " #{year}-12-25" }
+ eol_date:
+
+eom
+ data.sub!(/(?=^- name)/, entry)
+ end
+ File.write(File.join(wwwdir, filename), data)
+ end
+
+ def self.update_downloads_yml(ver, xy, wwwdir)
+ filename = "_data/downloads.yml"
+ data = File.read(File.join(wwwdir, filename))
+
+ if /^preview:\n\n(?: .*\n)* - #{Regexp.escape(xy)}\./ =~ data
+ if ver.include?("-")
+ data.sub!(/^ - #{Regexp.escape(xy)}\..*/, " - #{ver}")
+ else
+ data.sub!(/^ - #{Regexp.escape(xy)}\..*\n/, "")
+ data.sub!(/(?<=^stable:\n\n)/, " - #{ver}\n")
+ end
+ else
+ unless data.sub!(/^ - #{Regexp.escape(xy)}\..*/, " - #{ver}")
+ if ver.include?("-")
+ data.sub!(/(?<=^preview:\n\n)/, " - #{ver}\n")
+ else
+ data.sub!(/(?<=^stable:\n\n)/, " - #{ver}\n")
+ end
+ end
+ end
+ File.write(File.join(wwwdir, filename), data)
+ end
+
+ def self.update_releases_yml(ver, xy, ary, wwwdir, files_changed, insertions, deletions)
+ filename = "_data/releases.yml"
+ data = File.read(File.join(wwwdir, filename))
+
+ date = Time.now.utc # use utc to use previous day in midnight
+ entry = <<eom
+- version: #{ver}
+ tag: v#{ver.tr('-.', '_')}
+ date: #{date.strftime("%Y-%m-%d")}
+ post: /en/news/#{date.strftime("%Y/%m/%d")}/ruby-#{ver.tr('.', '-')}-released/
+ stats:
+ files_changed: #{files_changed}
+ insertions: #{insertions}
+ deletions: #{deletions}
+ url:
+ gz: https://cache.ruby-lang.org/pub/ruby/#{xy}/ruby-#{ver}.tar.gz
+ zip: https://cache.ruby-lang.org/pub/ruby/#{xy}/ruby-#{ver}.zip
+ xz: https://cache.ruby-lang.org/pub/ruby/#{xy}/ruby-#{ver}.tar.xz
+ size:
+ gz: #{ary.find{|x|x.gz? }.size}
+ zip: #{ary.find{|x|x.zip?}.size}
+ xz: #{ary.find{|x|x.xz? }.size}
+ sha1:
+ gz: #{ary.find{|x|x.gz? }.sha1}
+ zip: #{ary.find{|x|x.zip?}.sha1}
+ xz: #{ary.find{|x|x.xz? }.sha1}
+ sha256:
+ gz: #{ary.find{|x|x.gz? }.sha256}
+ zip: #{ary.find{|x|x.zip?}.sha256}
+ xz: #{ary.find{|x|x.xz? }.sha256}
+ sha512:
+ gz: #{ary.find{|x|x.gz? }.sha512}
+ zip: #{ary.find{|x|x.zip?}.sha512}
+ xz: #{ary.find{|x|x.xz? }.sha512}
+eom
+
+ if data.include?("\n- version: #{ver}\n")
+ elsif data.sub!(/\n# #{Regexp.escape(xy)} series\n/, "\\&\n#{entry}")
+ else
+ data.sub!(/^$/, "\n# #{xy} series\n\n#{entry}")
+ end
+ File.write(File.join(wwwdir, filename), data)
+ end
+end
+
+# Confirm current directory is www.ruby-lang.org's working directory
+def confirm_w_r_l_o_wd
+ File.foreach('.git/config') do |line|
+ return true if line.include?('git@github.com:ruby/www.ruby-lang.org.git')
+ end
+ abort "Run this script in www.ruby-lang.org's working directory"
+end
+
+def main
+ if ARGV.size != 1
+ abort "usage: #$1 <version>"
+ end
+ confirm_w_r_l_o_wd
+ version = ARGV.shift
+ Tarball.parse(Dir.pwd, version)
+end
+
+main
diff --git a/tool/ruby_vm/helpers/c_escape.rb b/tool/ruby_vm/helpers/c_escape.rb
index 3e2bf2e02c..34fafd1e34 100644
--- a/tool/ruby_vm/helpers/c_escape.rb
+++ b/tool/ruby_vm/helpers/c_escape.rb
@@ -17,7 +17,7 @@ module RubyVM::CEscape
# generate comment, with escaps.
def commentify str
- return "/* #{str.strip.b.gsub '*/', '*\\/'} */"
+ return "/* #{str.b.gsub('*/', '*\\/').gsub('/*', '/\\*')} */"
end
# Mimic gensym of CL.
@@ -46,7 +46,7 @@ module RubyVM::CEscape
# I believe this is the fastest implementation done in pure-ruby.
# Constants cached, gsub skips block evaluation, string literal optimized.
buf = str.b
- buf.gsub! %r/./n, RString2CStr
+ buf.gsub! %r/./nm, RString2CStr
return %'"#{buf}"'
end
@@ -60,7 +60,7 @@ module RubyVM::CEscape
"\x18"=>"\\x18", "\x19"=>"\\x19", "\x1A"=>"\\x1a", "\e"=>"\\x1b",
"\x1C"=>"\\x1c", "\x1D"=>"\\x1d", "\x1E"=>"\\x1e", "\x1F"=>"\\x1f",
" "=> " ", "!"=> "!", "\""=> "\\\"", "#"=> "#",
- "$"=> "$", "%"=> "%", "&"=> "&", "'"=> "\\'",
+ "$"=> "$", "%"=> "%", "&"=> "&", "'"=> "'",
"("=> "(", ")"=> ")", "*"=> "*", "+"=> "+",
","=> ",", "-"=> "-", "."=> ".", "/"=> "/",
"0"=> "0", "1"=> "1", "2"=> "2", "3"=> "3",
diff --git a/tool/ruby_vm/helpers/dumper.rb b/tool/ruby_vm/helpers/dumper.rb
index 00c301c01c..98104f4b92 100644
--- a/tool/ruby_vm/helpers/dumper.rb
+++ b/tool/ruby_vm/helpers/dumper.rb
@@ -25,7 +25,8 @@ class RubyVM::Dumper
end
def new_erb spec
- path = Pathname.new(__FILE__).relative_path_from(Pathname.pwd).dirname
+ path = Pathname.new(__FILE__)
+ path = (path.relative_path_from(Pathname.pwd) rescue path).dirname
path += '../views'
path += spec
src = path.read mode: 'rt:utf-8:utf-8'
diff --git a/tool/ruby_vm/helpers/scanner.rb b/tool/ruby_vm/helpers/scanner.rb
index 593271a415..ef6de8120e 100644
--- a/tool/ruby_vm/helpers/scanner.rb
+++ b/tool/ruby_vm/helpers/scanner.rb
@@ -20,7 +20,8 @@ class RubyVM::Scanner
attr_reader :__LINE__
def initialize path
- src = Pathname.new(__FILE__).relative_path_from(Pathname.pwd).dirname
+ src = Pathname.new(__FILE__)
+ src = (src.relative_path_from(Pathname.pwd) rescue src).dirname
src += path
@__LINE__ = 1
@__FILE__ = src.to_path
diff --git a/tool/ruby_vm/loaders/insns_def.rb b/tool/ruby_vm/loaders/insns_def.rb
index 47e4ba29f5..034905f74e 100644
--- a/tool/ruby_vm/loaders/insns_def.rb
+++ b/tool/ruby_vm/loaders/insns_def.rb
@@ -25,10 +25,10 @@ grammar = %r'
(?<ws> \g<comment> | \s ){0}
(?<ident> [_a-zA-Z] [0-9_a-zA-Z]* ){0}
(?<type> (?: \g<keyword> \g<ws>+ )* \g<ident> ){0}
- (?<arg> \g<type> \g<ws>+ \g<ident> | \.\.\. ){0}
+ (?<arg> \g<type> \g<ws>+ \g<ident> ){0}
(?<argv> (?# empty ) |
void |
- \g<arg> (?: \g<ws>* , \g<ws>* \g<arg> \g<ws>* )* ){0}
+ (?: \.\.\. | \g<arg>) (?: \g<ws>* , \g<ws>* \g<arg> \g<ws>* )* ){0}
(?<pragma> \g<ws>* // \s* attr \g<ws>+
(?<pragma:type> \g<type> ) \g<ws>+
(?<pragma:name> \g<ident> ) \g<ws>*
@@ -57,6 +57,10 @@ until scanner.eos? do
ope = split.(scanner["insn:opes"])
pop = split.(scanner["insn:pops"])
ret = split.(scanner["insn:rets"])
+ if ope.include?("...")
+ raise sprintf("parse error at %s:%d:%s: operands cannot be variadic",
+ scanner.__FILE__, scanner.__LINE__, name)
+ end
attrs = []
while l2 = scanner.scan(/\G#{grammar}\g<pragma>/o) do
diff --git a/tool/ruby_vm/models/bare_instructions.rb b/tool/ruby_vm/models/bare_instructions.rb
index b0cc83a65a..6b5f1f6cf8 100755
--- a/tool/ruby_vm/models/bare_instructions.rb
+++ b/tool/ruby_vm/models/bare_instructions.rb
@@ -112,6 +112,10 @@ class RubyVM::BareInstructions
@attrs.fetch('leaf').expr.expr == 'true;'
end
+ def leaf_without_check_ints?
+ @attrs.fetch('leaf').expr.expr == 'leafness_of_check_ints;'
+ end
+
def handle_canary stmt
# Stack canary is basically a good thing that we want to add, however:
#
diff --git a/tool/ruby_vm/models/typemap.rb b/tool/ruby_vm/models/typemap.rb
index c4b13f67f9..ed3aea7d2e 100644
--- a/tool/ruby_vm/models/typemap.rb
+++ b/tool/ruby_vm/models/typemap.rb
@@ -14,7 +14,6 @@ RubyVM::Typemap = {
"..." => %w[. TS_VARIABLE],
"CALL_DATA" => %w[C TS_CALLDATA],
"CDHASH" => %w[H TS_CDHASH],
- "GENTRY" => %w[G TS_GENTRY],
"IC" => %w[K TS_IC],
"IVC" => %w[A TS_IVC],
"ID" => %w[I TS_ID],
diff --git a/tool/ruby_vm/views/_insn_entry.erb b/tool/ruby_vm/views/_insn_entry.erb
index 90e1268d90..bdd0fa3c7c 100644
--- a/tool/ruby_vm/views/_insn_entry.erb
+++ b/tool/ruby_vm/views/_insn_entry.erb
@@ -39,7 +39,7 @@ INSN_ENTRY(<%= insn.name %>)
% if insn.handles_sp?
POPN(INSN_ATTR(popn));
% end
-<%= insn.handle_canary "SETUP_CANARY()" -%>
+<%= insn.handle_canary "SETUP_CANARY(leaf)" -%>
COLLECT_USAGE_INSN(INSN_ATTR(bin));
% insn.opes.each_with_index do |ope, i|
COLLECT_USAGE_OPERAND(INSN_ATTR(bin), <%= i %>, <%= ope[:name] %>);
@@ -55,7 +55,7 @@ INSN_ENTRY(<%= insn.name %>)
/* ### Instruction trailers. ### */
CHECK_VM_STACK_OVERFLOW_FOR_INSN(VM_REG_CFP, INSN_ATTR(retn));
-<%= insn.handle_canary "CHECK_CANARY()" -%>
+<%= insn.handle_canary "CHECK_CANARY(leaf, INSN_ATTR(bin))" -%>
% if insn.handles_sp?
% insn.rets.reverse_each do |ret|
PUSH(<%= insn.cast_to_VALUE ret %>);
diff --git a/tool/ruby_vm/views/_leaf_helpers.erb b/tool/ruby_vm/views/_leaf_helpers.erb
index ac60f2dcbc..cbb7373e1c 100644
--- a/tool/ruby_vm/views/_leaf_helpers.erb
+++ b/tool/ruby_vm/views/_leaf_helpers.erb
@@ -8,65 +8,12 @@
%;
#line <%= __LINE__ + 1 %> <%=cstr __FILE__ %>
-static bool
-leafness_of_getglobal(VALUE gentry)
-{
- const struct rb_global_entry *e = (void *)gentry;
-
- if (UNLIKELY(rb_gvar_is_traced(e))) {
- return false;
- }
- else {
- /* We cannot write this function using a switch() because a
- * case label cannot be a function pointer. */
- static rb_gvar_getter_t *const allowlist[] = {
- rb_gvar_val_getter,
- rb_gvar_var_getter,
- /* rb_gvar_undef_getter issues rb_warning() */
- };
- rb_gvar_getter_t *f = rb_gvar_getter_function_of(e);
- int i;
-
- for (i = 0; i < numberof(allowlist); i++) {
- if (f == allowlist[i]) {
- return true;
- }
- }
- return false;
- }
-}
-
-static bool
-leafness_of_setglobal(VALUE gentry)
-{
- const struct rb_global_entry *e = (void *)gentry;
-
- if (UNLIKELY(rb_gvar_is_traced(e))) {
- return false;
- }
- else {
- /* We cannot write this function using a switch() because a
- * case label cannot be a function pointer. */
- static rb_gvar_setter_t *const allowlist[] = {
- rb_gvar_val_setter,
- /* rb_gvar_readonly_setter issues rb_name_error() */
- rb_gvar_var_setter,
- rb_gvar_undef_setter,
- };
- rb_gvar_setter_t *f = rb_gvar_setter_function_of(e);
- int i;
-
- for (i = 0; i < numberof(allowlist); i++) {
- if (f == allowlist[i]) {
- return true;
- }
- }
- return false;
- }
-}
-
#include "iseq.h"
+// This is used to tell MJIT that this insn would be leaf if CHECK_INTS didn't exist.
+// It should be used only when RUBY_VM_CHECK_INTS is directly written in insns.def.
+static bool leafness_of_check_ints = false;
+
static bool
leafness_of_defined(rb_num_t op_type)
{
diff --git a/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb b/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb
new file mode 100644
index 0000000000..1acfdb7f0b
--- /dev/null
+++ b/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb
@@ -0,0 +1,31 @@
+% # -*- C -*-
+% # Copyright (c) 2020 Takashi Kokubun. All rights reserved.
+% #
+% # This file is a part of the programming language Ruby. Permission is hereby
+% # granted, to either redistribute and/or modify this file, provided that the
+% # conditions mentioned in the file COPYING are met. Consult the file for
+% # details.
+%
+% # compiler: Declare dst and ic
+% insn.opes.each_with_index do |ope, i|
+ <%= ope.fetch(:decl) %> = (<%= ope.fetch(:type) %>)operands[<%= i %>];
+% end
+
+% # compiler: Capture IC values, locking getinlinecache
+ struct iseq_inline_constant_cache_entry *ice = ic->entry;
+ if (ice != NULL && ice->ic_serial && !status->compile_info->disable_const_cache) {
+% # JIT: Inline everything in IC, and cancel the slow path
+ fprintf(f, " if (vm_inlined_ic_hit_p(0x%"PRIxVALUE", 0x%"PRIxVALUE", (const rb_cref_t *)0x%"PRIxVALUE", %"PRI_SERIALT_PREFIX"u, reg_cfp->ep)) {", ice->flags, ice->value, (VALUE)ice->ic_cref, ice->ic_serial);
+ fprintf(f, " stack[%d] = 0x%"PRIxVALUE";\n", b->stack_size, ice->value);
+ fprintf(f, " goto label_%d;\n", pos + insn_len(insn) + (int)dst);
+ fprintf(f, " }");
+ fprintf(f, " else {");
+ fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size);
+ fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos);
+ fprintf(f, " goto const_cancel;\n");
+ fprintf(f, " }");
+
+% # compiler: Move JIT compiler's internal stack pointer
+ b->stack_size += <%= insn.call_attribute('sp_inc') %>;
+ break;
+ }
diff --git a/tool/ruby_vm/views/_mjit_compile_insn.erb b/tool/ruby_vm/views/_mjit_compile_insn.erb
index 8f45121615..f54d1b0e0e 100644
--- a/tool/ruby_vm/views/_mjit_compile_insn.erb
+++ b/tool/ruby_vm/views/_mjit_compile_insn.erb
@@ -7,7 +7,6 @@
% # details.
fprintf(f, "{\n");
{
- MAYBE_UNUSED(int pc_moved_p) = FALSE;
% # compiler: Prepare operands which may be used by `insn.call_attribute`
% insn.opes.each_with_index do |ope, i|
MAYBE_UNUSED(<%= ope.fetch(:decl) %>) = (<%= ope.fetch(:type) %>)operands[<%= i %>];
@@ -35,7 +34,7 @@
% when 'ID'
comment_id(f, (ID)operands[<%= i %>]);
% when 'CALL_DATA'
- comment_id(f, ((CALL_DATA)operands[<%= i %>])->ci.mid);
+ comment_id(f, vm_ci_mid(((CALL_DATA)operands[<%= i %>])->ci));
% when 'VALUE'
if (SYMBOL_P((VALUE)operands[<%= i %>])) comment_id(f, SYM2ID((VALUE)operands[<%= i %>]));
% end
@@ -60,7 +59,8 @@
% end
%
% # JIT: We should evaluate ISeq modified for TracePoint if it's enabled. Note: This is slow.
-% unless insn.always_leaf?
+% # leaf insn may not cancel JIT. leaf_without_check_ints is covered in RUBY_VM_CHECK_INTS of _mjit_compile_insn_body.erb.
+% unless insn.always_leaf? || insn.leaf_without_check_ints?
fprintf(f, " if (UNLIKELY(!mjit_call_p)) {\n");
fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size + (int)<%= insn.call_attribute('sp_inc') %>);
if (!pc_moved_p) {
diff --git a/tool/ruby_vm/views/_mjit_compile_insn_body.erb b/tool/ruby_vm/views/_mjit_compile_insn_body.erb
index a2a750fbdc..187e043837 100644
--- a/tool/ruby_vm/views/_mjit_compile_insn_body.erb
+++ b/tool/ruby_vm/views/_mjit_compile_insn_body.erb
@@ -20,14 +20,14 @@
% # For `leave`. We can't proceed next ISeq in the same JIT function.
% expr.gsub!(/^(?<indent>\s*)RESTORE_REGS\(\);\n/) do
% indent = Regexp.last_match[:indent]
-% <<-RESTORE_REGS.gsub(/^ +/, '')
+% <<-end.gsub(/^ +/, '')
% #if OPT_CALL_THREADED_CODE
% #{indent}rb_ec_thread_ptr(ec)->retval = val;
% #{indent}return 0;
% #else
% #{indent}return val;
% #endif
-% RESTORE_REGS
+% end
% end
% expr.gsub!(/^(?<indent>\s*)NEXT_INSN\(\);\n/) do
% indent = Regexp.last_match[:indent]
@@ -47,6 +47,20 @@
% #
% # TODO: support combination of following macros in the same line
% case line
+% when /\A\s+RUBY_VM_CHECK_INTS\(ec\);\s+\z/
+% if insn.leaf_without_check_ints? # lazily move PC and optionalize mjit_call_p here
+ fprintf(f, " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n");
+ fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", next_pos); /* ADD_PC(INSN_ATTR(width)); */
+ fprintf(f, " rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);\n");
+ fprintf(f, " if (UNLIKELY(!mjit_call_p)) {\n");
+ fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size);
+ fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_invalidate_all);\n");
+ fprintf(f, " goto cancel;\n");
+ fprintf(f, " }\n");
+ fprintf(f, " }\n");
+% else
+ fprintf(f, <%= to_cstr.call(line) %>);
+% end
% when /\A\s+JUMP\((?<dest>[^)]+)\);\s+\z/
% dest = Regexp.last_match[:dest]
%
@@ -101,7 +115,7 @@
% # #define STACK_ADDR_FROM_TOP(n) (GET_SP()-(n))
% num = Regexp.last_match[:num]
fprintf(f, <%= to_cstr.call(line.sub(/\bSTACK_ADDR_FROM_TOP\(([^)]+)\)/, '%s')) %>,
- (status->local_stack_p ? "stack + (stack_size - (<%= num %>))" : "STACK_ADDR_FROM_TOP(<%= num %>)"));
+ (status->local_stack_p ? "(stack + (stack_size - (<%= num %>)))" : "STACK_ADDR_FROM_TOP(<%= num %>)"));
% when /\bTOPN\((?<num>[^)]+)\)/
% # #define TOPN(n) (*(GET_SP()-(n)-1))
% num = Regexp.last_match[:num]
diff --git a/tool/ruby_vm/views/_mjit_compile_invokebuiltin.erb b/tool/ruby_vm/views/_mjit_compile_invokebuiltin.erb
new file mode 100644
index 0000000000..a3796ffc5e
--- /dev/null
+++ b/tool/ruby_vm/views/_mjit_compile_invokebuiltin.erb
@@ -0,0 +1,29 @@
+% # -*- C -*-
+% # Copyright (c) 2020 Urabe, Shyouhei. All rights reserved.
+% #
+% # This file is a part of the programming language Ruby. Permission is hereby
+% # granted, to either redistribute and/or modify this file, provided that the
+% # conditions mentioned in the file COPYING are met. Consult the file for
+% # details.
+%
+% insn.opes.each_with_index do |ope, i|
+ <%= ope.fetch(:decl) %> = (<%= ope.fetch(:type) %>)operands[<%= i %>];
+% end
+ rb_snum_t sp_inc = <%= insn.call_attribute('sp_inc') %>;
+ unsigned sp = b->stack_size + (unsigned)sp_inc;
+ VM_ASSERT(b->stack_size > -sp_inc);
+ VM_ASSERT(sp_inc < UINT_MAX - b->stack_size);
+
+ if (bf->compiler) {
+ fprintf(f, "{\n");
+ fprintf(f, " VALUE val;\n");
+ bf->compiler(f, <%=
+ insn.name == 'invokebuiltin' ? '-1' : '(rb_num_t)operands[1]'
+ %>, b->stack_size, body->builtin_inline_p);
+ fprintf(f, " stack[%u] = val;\n", sp - 1);
+ fprintf(f, "}\n");
+% if insn.name != 'opt_invokebuiltin_delegate_leave'
+ b->stack_size = sp;
+ break;
+% end
+ }
diff --git a/tool/ruby_vm/views/_mjit_compile_ivar.erb b/tool/ruby_vm/views/_mjit_compile_ivar.erb
index 57f8d14b76..5105584ba3 100644
--- a/tool/ruby_vm/views/_mjit_compile_ivar.erb
+++ b/tool/ruby_vm/views/_mjit_compile_ivar.erb
@@ -16,33 +16,79 @@
% # compiler: Use copied IVC to avoid race condition
IVC ic_copy = &(status->is_entries + ((union iseq_inline_storage_entry *)ic - body->is_entries))->iv_cache;
%
-% # compiler: Consider cfp->self as T_OBJECT if ic_copy->ic_serial is set
- if (!status->compile_info->disable_ivar_cache && ic_copy->ic_serial) {
+ if (!status->compile_info->disable_ivar_cache && ic_copy->entry) { // Only ic_copy is enabled.
% # JIT: optimize away motion of sp and pc. This path does not call rb_warning() and so it's always leaf and not `handles_sp`.
% # <%= render 'mjit_compile_pc_and_sp', locals: { insn: insn } -%>
%
-% # JIT: prepare vm_getivar's arguments and variables
+% # JIT: prepare vm_getivar/vm_setivar arguments and variables
fprintf(f, "{\n");
fprintf(f, " VALUE obj = GET_SELF();\n");
- fprintf(f, " const rb_serial_t ic_serial = (rb_serial_t)%"PRI_SERIALT_PREFIX"u;\n", ic_copy->ic_serial);
- fprintf(f, " const st_index_t index = %"PRIuSIZE";\n", ic_copy->index);
-% # JIT: cache hit path of vm_getivar, or cancel JIT.
+ fprintf(f, " const uint32_t index = %u;\n", (ic_copy->entry->index));
+ if (status->merge_ivar_guards_p) {
+% # JIT: Access ivar without checking these VM_ASSERTed prerequisites as we checked them in the beginning of `mjit_compile_body`
+ fprintf(f, " VM_ASSERT(RB_TYPE_P(obj, T_OBJECT));\n");
+ fprintf(f, " VM_ASSERT((rb_serial_t)%"PRI_SERIALT_PREFIX"u == RCLASS_SERIAL(RBASIC(obj)->klass));\n", ic_copy->entry->class_serial);
+ fprintf(f, " VM_ASSERT(index < ROBJECT_NUMIV(obj));\n");
% if insn.name == 'setinstancevariable'
- fprintf(f, " VALUE val = stack[%d];\n", b->stack_size - 1);
- fprintf(f, " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && !RB_OBJ_FROZEN(obj))) {\n");
- fprintf(f, " VALUE *ptr = ROBJECT_IVPTR(obj);\n");
- fprintf(f, " RB_OBJ_WRITE(obj, &ptr[index], val);\n");
- fprintf(f, " }\n");
+ fprintf(f, " if (LIKELY(!RB_OBJ_FROZEN_RAW(obj) && %s)) {\n", status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX ? "true" : "RB_FL_ANY_RAW(obj, ROBJECT_EMBED)");
+ fprintf(f, " RB_OBJ_WRITE(obj, &ROBJECT(obj)->as.%s, stack[%d]);\n",
+ status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX ? "heap.ivptr[index]" : "ary[index]", b->stack_size - 1);
+ fprintf(f, " }\n");
+% else
+ fprintf(f, " VALUE val;\n");
+ fprintf(f, " if (LIKELY(%s && (val = ROBJECT(obj)->as.%s) != Qundef)) {\n",
+ status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX ? "true" : "RB_FL_ANY_RAW(obj, ROBJECT_EMBED)",
+ status->max_ivar_index >= ROBJECT_EMBED_LEN_MAX ? "heap.ivptr[index]" : "ary[index]");
+ fprintf(f, " stack[%d] = val;\n", b->stack_size);
+ fprintf(f, " }\n");
+%end
+ }
+ else {
+ fprintf(f, " const rb_serial_t ic_serial = (rb_serial_t)%"PRI_SERIALT_PREFIX"u;\n", ic_copy->entry->class_serial);
+% # JIT: cache hit path of vm_getivar/vm_setivar, or cancel JIT (recompile it with exivar)
+% if insn.name == 'setinstancevariable'
+ fprintf(f, " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && !RB_OBJ_FROZEN_RAW(obj))) {\n");
+ fprintf(f, " VALUE *ptr = ROBJECT_IVPTR(obj);\n");
+ fprintf(f, " RB_OBJ_WRITE(obj, &ptr[index], stack[%d]);\n", b->stack_size - 1);
+ fprintf(f, " }\n");
% else
+ fprintf(f, " VALUE val;\n");
+ fprintf(f, " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && (val = ROBJECT_IVPTR(obj)[index]) != Qundef)) {\n");
+ fprintf(f, " stack[%d] = val;\n", b->stack_size);
+ fprintf(f, " }\n");
+% end
+ }
+ fprintf(f, " else {\n");
+ fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos);
+ fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size);
+ fprintf(f, " goto ivar_cancel;\n");
+ fprintf(f, " }\n");
+
+% # compiler: Move JIT compiler's internal stack pointer
+ b->stack_size += <%= insn.call_attribute('sp_inc') %>;
+ fprintf(f, "}\n");
+ break;
+ }
+% if insn.name == 'getinstancevariable'
+ else if (!status->compile_info->disable_exivar_cache && ic_copy->entry) {
+% # JIT: optimize away motion of sp and pc. This path does not call rb_warning() and so it's always leaf and not `handles_sp`.
+% # <%= render 'mjit_compile_pc_and_sp', locals: { insn: insn } -%>
+%
+% # JIT: prepare vm_getivar's arguments and variables
+ fprintf(f, "{\n");
+ fprintf(f, " VALUE obj = GET_SELF();\n");
+ fprintf(f, " const rb_serial_t ic_serial = (rb_serial_t)%"PRI_SERIALT_PREFIX"u;\n", ic_copy->entry->class_serial);
+ fprintf(f, " const uint32_t index = %u;\n", ic_copy->entry->index);
+% # JIT: cache hit path of vm_getivar, or cancel JIT (recompile it without any ivar optimization)
+ fprintf(f, " struct gen_ivtbl *ivtbl;\n");
fprintf(f, " VALUE val;\n");
- fprintf(f, " if (LIKELY(RB_TYPE_P(obj, T_OBJECT) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && index < ROBJECT_NUMIV(obj) && (val = ROBJECT_IVPTR(obj)[index]) != Qundef)) {\n");
+ fprintf(f, " if (LIKELY(FL_TEST_RAW(obj, FL_EXIVAR) && ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass) && rb_ivar_generic_ivtbl_lookup(obj, &ivtbl) && index < ivtbl->numiv && (val = ivtbl->ivptr[index]) != Qundef)) {\n");
fprintf(f, " stack[%d] = val;\n", b->stack_size);
fprintf(f, " }\n");
-% end
fprintf(f, " else {\n");
fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos);
fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size);
- fprintf(f, " goto ivar_cancel;\n");
+ fprintf(f, " goto exivar_cancel;\n");
fprintf(f, " }\n");
% # compiler: Move JIT compiler's internal stack pointer
@@ -50,5 +96,6 @@
fprintf(f, "}\n");
break;
}
+% end
}
#endif // OPT_IC_FOR_IVAR
diff --git a/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb b/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb
index 545b9f72f5..390b3ce525 100644
--- a/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb
+++ b/tool/ruby_vm/views/_mjit_compile_pc_and_sp.erb
@@ -5,10 +5,12 @@
% # conditions mentioned in the file COPYING are met. Consult the file for
% # details.
%
-% # JIT: Move pc for catch table on catch_except_p, and for #caller_locations and rb_profile_frames on !insn.always_leaf?
- if (body->catch_except_p || <%= insn.always_leaf? ? 'FALSE' : 'TRUE' %>) {
+% # JIT: When an insn is leaf, we don't need to Move pc for a catch table on catch_except_p, #caller_locations,
+% # and rb_profile_frames. For check_ints, we lazily move PC when we have interruptions.
+ MAYBE_UNUSED(bool pc_moved_p) = false;
+ if (<%= !(insn.always_leaf? || insn.leaf_without_check_ints?) %>) {
fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", next_pos); /* ADD_PC(INSN_ATTR(width)); */
- pc_moved_p = TRUE;
+ pc_moved_p = true;
}
%
% # JIT: move sp to use or preserve stack variables
diff --git a/tool/ruby_vm/views/_mjit_compile_send.erb b/tool/ruby_vm/views/_mjit_compile_send.erb
index ec8eec5589..d1540f69bb 100644
--- a/tool/ruby_vm/views/_mjit_compile_send.erb
+++ b/tool/ruby_vm/views/_mjit_compile_send.erb
@@ -8,100 +8,110 @@
%
% # Optimized case of send / opt_send_without_block instructions.
{
- MAYBE_UNUSED(int pc_moved_p) = FALSE;
% # compiler: Prepare operands which may be used by `insn.call_attribute`
% insn.opes.each_with_index do |ope, i|
MAYBE_UNUSED(<%= ope.fetch(:decl) %>) = (<%= ope.fetch(:type) %>)operands[<%= i %>];
% end
-% # compiler: Use copied cc to avoid race condition
- CALL_CACHE cc_copy = status->cc_entries + call_data_index(cd, body);
+% # compiler: Use captured cc to avoid race condition
+ const struct rb_callcache *captured_cc = captured_cc_entries(status)[call_data_index(cd, body)];
%
- if (!status->compile_info->disable_send_cache && has_valid_method_type(cc_copy)) {
- const rb_iseq_t *iseq;
- const CALL_INFO ci = &cd->ci;
- unsigned int argc = ci->orig_argc; // this `argc` variable is for calculating a value's position on stack considering `blockarg`.
-% if insn.name == 'send'
- argc += ((ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0); // simulate `vm_caller_setup_arg_block`'s `--reg_cfp->sp`
-% end
+% # compiler: Inline send insn where some supported fastpath is used.
+ const rb_iseq_t *iseq = NULL;
+ const CALL_INFO ci = cd->ci;
+ int kw_splat = IS_ARGS_KW_SPLAT(ci) > 0;
+ extern bool rb_splat_or_kwargs_p(const struct rb_callinfo *restrict ci);
+ if (!status->compile_info->disable_send_cache && has_valid_method_type(captured_cc) && (
+% # `CC_SET_FASTPATH(cd->cc, vm_call_cfunc_with_frame, ...)` in `vm_call_cfunc`
+ (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC
+ && !rb_splat_or_kwargs_p(ci) && !kw_splat)
+% # `CC_SET_FASTPATH(cc, vm_call_iseq_setup_func(...), vm_call_iseq_optimizable_p(...))` in `vm_callee_setup_arg`,
+% # and support only non-VM_CALL_TAILCALL path inside it
+ || (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_ISEQ
+ && fastpath_applied_iseq_p(ci, captured_cc, iseq = def_iseq_ptr(vm_cc_cme(captured_cc)->def))
+ && !(vm_ci_flag(ci) & VM_CALL_TAILCALL))
+ )) {
+ const bool cfunc_debug = false; // Set true when you want to see inlined cfunc
+ if (cfunc_debug && vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC)
+ fprintf(stderr, " * %s\n", rb_id2name(vm_ci_mid(ci)));
- if (!(ci->flag & VM_CALL_TAILCALL) // inlining non-tailcall path
- && cc_copy->me->def->type == VM_METHOD_TYPE_ISEQ && fastpath_applied_iseq_p(ci, cc_copy, iseq = def_iseq_ptr(cc_copy->me->def))) { // CC_SET_FASTPATH in vm_callee_setup_arg
- int param_size = iseq->body->param.size;
-
- fprintf(f, "{\n");
-% # JIT: Declare stack_size to be used in some macro of _mjit_compile_insn_body.erb
- if (status->local_stack_p) {
- fprintf(f, " MAYBE_UNUSED(unsigned int) stack_size = %u;\n", b->stack_size);
- }
+ int sp_inc = (int)sp_inc_of_sendish(ci);
+ fprintf(f, "{\n");
% # JIT: Invalidate call cache if it requires vm_search_method. This allows to inline some of following things.
- fprintf(f, " if (UNLIKELY(GET_GLOBAL_METHOD_STATE() != %"PRI_SERIALT_PREFIX"u ||\n", cc_copy->method_state);
- fprintf(f, " RCLASS_SERIAL(CLASS_OF(stack[%d])) != %"PRI_SERIALT_PREFIX"u)) {\n", b->stack_size - 1 - argc, cc_copy->class_serial[0]);
- fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos);
- fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size);
- fprintf(f, " goto send_cancel;\n");
- fprintf(f, " }\n");
+ bool opt_class_of = !maybe_special_const_class_p(captured_cc->klass); // If true, use RBASIC_CLASS instead of CLASS_OF to reduce code size
+ fprintf(f, " const struct rb_callcache *cc = (const struct rb_callcache *)0x%"PRIxVALUE";\n", (VALUE)captured_cc);
+ fprintf(f, " const rb_callable_method_entry_t *cc_cme = (const rb_callable_method_entry_t *)0x%"PRIxVALUE";\n", (VALUE)vm_cc_cme(captured_cc));
+ fprintf(f, " const VALUE recv = stack[%d];\n", b->stack_size + sp_inc - 1);
+ fprintf(f, " if (UNLIKELY(%s || !vm_cc_valid_p(cc, cc_cme, %s(recv)))) {\n", opt_class_of ? "RB_SPECIAL_CONST_P(recv)" : "false", opt_class_of ? "RBASIC_CLASS" : "CLASS_OF");
+ fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos);
+ fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size);
+ fprintf(f, " goto send_cancel;\n");
+ fprintf(f, " }\n");
% # JIT: move sp and pc if necessary
<%= render 'mjit_compile_pc_and_sp', locals: { insn: insn } -%>
% # JIT: If ISeq is inlinable, call the inlined method without pushing a frame.
- if (status->inlined_iseqs != NULL && status->inlined_iseqs[pos] == iseq->body) {
- fprintf(f, " {\n");
- fprintf(f, " VALUE orig_self = reg_cfp->self;\n");
- fprintf(f, " reg_cfp->self = stack[%d];\n", b->stack_size - argc - 1);
- fprintf(f, " stack[%d] = _mjit_inlined_%d(ec, reg_cfp, orig_self, original_iseq);\n", b->stack_size - argc - 1, pos);
- fprintf(f, " reg_cfp->self = orig_self;\n");
- fprintf(f, " }\n");
- }
- else {
-% # JIT: Print insn body in insns.def
- fprintf(f, " {\n");
- fprintf(f, " struct rb_calling_info calling;\n");
+ if (iseq && status->inlined_iseqs != NULL && iseq->body == status->inlined_iseqs[pos]) {
+ fprintf(f, " {\n");
+ fprintf(f, " VALUE orig_self = reg_cfp->self;\n");
+ fprintf(f, " reg_cfp->self = stack[%d];\n", b->stack_size + sp_inc - 1);
+ fprintf(f, " stack[%d] = _mjit%d_inlined_%d(ec, reg_cfp, orig_self, original_iseq);\n", b->stack_size + sp_inc - 1, status->compiled_id, pos);
+ fprintf(f, " reg_cfp->self = orig_self;\n");
+ fprintf(f, " }\n");
+ }
+ else {
+% # JIT: Forked `vm_sendish` (except method_explorer = vm_search_method_wrap) to inline various things
+ fprintf(f, " {\n");
+ fprintf(f, " VALUE val;\n");
+ fprintf(f, " struct rb_calling_info calling;\n");
% if insn.name == 'send'
- fprintf(f, " calling.block_handler = vm_caller_setup_arg_block(ec, reg_cfp, (CALL_INFO)0x%"PRIxVALUE", (rb_iseq_t *)0x%"PRIxVALUE", FALSE);\n", (VALUE)ci, (VALUE)blockiseq);
+ fprintf(f, " calling.block_handler = vm_caller_setup_arg_block(ec, reg_cfp, (const struct rb_callinfo *)0x%"PRIxVALUE", (rb_iseq_t *)0x%"PRIxVALUE", FALSE);\n", (VALUE)ci, (VALUE)blockiseq);
% else
- fprintf(f, " calling.block_handler = VM_BLOCK_HANDLER_NONE;\n");
+ fprintf(f, " calling.block_handler = VM_BLOCK_HANDLER_NONE;\n");
% end
- fprintf(f, " calling.argc = %d;\n", ci->orig_argc);
- fprintf(f, " calling.recv = stack[%d];\n", b->stack_size - 1 - argc);
+ fprintf(f, " calling.kw_splat = %d;\n", kw_splat);
+ fprintf(f, " calling.recv = stack[%d];\n", b->stack_size + sp_inc - 1);
+ fprintf(f, " calling.argc = %d;\n", vm_ci_argc(ci));
-% # JIT: Special CALL_METHOD. Bypass cc_copy->call and inline vm_call_iseq_setup_normal for vm_call_iseq_setup_func FASTPATH.
- fprintf(f, " {\n");
- fprintf(f, " VALUE v;\n");
- fprintf(f, " vm_call_iseq_setup_normal(ec, reg_cfp, &calling, (const rb_callable_method_entry_t *)0x%"PRIxVALUE", 0, %d, %d);\n",
- (VALUE)cc_copy->me, param_size, iseq->body->local_table_size); // fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE
+ if (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC) {
+% # TODO: optimize this more
+ fprintf(f, " calling.ci = (CALL_INFO)0x%"PRIxVALUE";\n", (VALUE)ci); // creating local cd here because operand's cd->cc may not be the same as inlined cc.
+ fprintf(f, " calling.cc = cc;");
+ fprintf(f, " val = vm_call_cfunc_with_frame(ec, reg_cfp, &calling);\n");
+ }
+ else { // VM_METHOD_TYPE_ISEQ
+% # fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE
+ fprintf(f, " vm_call_iseq_setup_normal(ec, reg_cfp, &calling, cc_cme, 0, %d, %d);\n", iseq->body->param.size, iseq->body->local_table_size);
if (iseq->body->catch_except_p) {
- fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n");
- fprintf(f, " v = vm_exec(ec, TRUE);\n");
+ fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n");
+ fprintf(f, " val = vm_exec(ec, true);\n");
}
else {
- fprintf(f, " if ((v = mjit_exec(ec)) == Qundef) {\n");
- fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); // This is vm_call0_body's code after vm_call_iseq_setup
- fprintf(f, " v = vm_exec(ec, FALSE);\n");
- fprintf(f, " }\n");
+ fprintf(f, " if ((val = mjit_exec(ec)) == Qundef) {\n");
+ fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); // This is vm_call0_body's code after vm_call_iseq_setup
+ fprintf(f, " val = vm_exec(ec, false);\n");
+ fprintf(f, " }\n");
}
- fprintf(f, " stack[%d] = v;\n", b->stack_size - argc - 1);
- fprintf(f, " }\n");
-
- fprintf(f, " }\n");
+ }
+ fprintf(f, " stack[%d] = val;\n", b->stack_size + sp_inc - 1);
+ fprintf(f, " }\n");
% # JIT: We should evaluate ISeq modified for TracePoint if it's enabled. Note: This is slow.
- fprintf(f, " if (UNLIKELY(!mjit_call_p)) {\n");
- fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size + (int)<%= insn.call_attribute('sp_inc') %>);
- if (!pc_moved_p) {
- fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", next_pos);
- }
- fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_invalidate_all);\n");
- fprintf(f, " goto cancel;\n");
- fprintf(f, " }\n");
+ fprintf(f, " if (UNLIKELY(!mjit_call_p)) {\n");
+ fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size + (int)<%= insn.call_attribute('sp_inc') %>);
+ if (!pc_moved_p) {
+ fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", next_pos);
}
+ fprintf(f, " RB_DEBUG_COUNTER_INC(mjit_cancel_invalidate_all);\n");
+ fprintf(f, " goto cancel;\n");
+ fprintf(f, " }\n");
+ }
% # compiler: Move JIT compiler's internal stack pointer
- b->stack_size += <%= insn.call_attribute('sp_inc') %>;
+ b->stack_size += <%= insn.call_attribute('sp_inc') %>;
- fprintf(f, "}\n");
- break;
- }
+ fprintf(f, "}\n");
+ break;
}
}
diff --git a/tool/ruby_vm/views/_sp_inc_helpers.erb b/tool/ruby_vm/views/_sp_inc_helpers.erb
index f4cf50b8c8..d0b0bd79ef 100644
--- a/tool/ruby_vm/views/_sp_inc_helpers.erb
+++ b/tool/ruby_vm/views/_sp_inc_helpers.erb
@@ -9,7 +9,7 @@
#line <%= __LINE__ + 1 %> <%=cstr __FILE__ %>
static rb_snum_t
-sp_inc_of_sendish(const struct rb_call_info *ci)
+sp_inc_of_sendish(const struct rb_callinfo *ci)
{
/* Send-ish instructions will:
*
@@ -18,8 +18,8 @@ sp_inc_of_sendish(const struct rb_call_info *ci)
* 3. Pop receiver.
* 4. Push return value.
*/
- const int argb = (ci->flag & VM_CALL_ARGS_BLOCKARG) ? 1 : 0;
- const int argc = ci->orig_argc;
+ const int argb = (vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) ? 1 : 0;
+ const int argc = vm_ci_argc(ci);
const int recv = 1;
const int retn = 1;
@@ -28,7 +28,7 @@ sp_inc_of_sendish(const struct rb_call_info *ci)
}
static rb_snum_t
-sp_inc_of_invokeblock(const struct rb_call_info *ci)
+sp_inc_of_invokeblock(const struct rb_callinfo *ci)
{
/* sp_inc of invokeblock is almost identical to that of sendish
* instructions, except that it does not pop receiver. */
diff --git a/tool/ruby_vm/views/_trace_instruction.erb b/tool/ruby_vm/views/_trace_instruction.erb
index be2b091d48..d604e0318b 100644
--- a/tool/ruby_vm/views/_trace_instruction.erb
+++ b/tool/ruby_vm/views/_trace_instruction.erb
@@ -10,7 +10,7 @@
/* insn <%= insn.pretty_name %> */
INSN_ENTRY(<%= insn.name %>)
{
- vm_trace(ec, GET_CFP(), GET_PC());
+ vm_trace(ec, GET_CFP());
DISPATCH_ORIGINAL_INSN(<%= insn.jump_destination %>);
END_INSN(<%= insn.name %>);
}
diff --git a/tool/ruby_vm/views/mjit_compile.inc.erb b/tool/ruby_vm/views/mjit_compile.inc.erb
index 95e71183d9..5820f81770 100644
--- a/tool/ruby_vm/views/mjit_compile.inc.erb
+++ b/tool/ruby_vm/views/mjit_compile.inc.erb
@@ -16,8 +16,7 @@
} -%>
%
% unsupported_insns = [
-% 'defineclass', # low priority
-% 'opt_call_c_function', # low priority
+% 'defineclass', # low priority
% ]
%
% opt_send_without_block = RubyVM::Instructions.find { |i| i.name == 'opt_send_without_block' }
@@ -36,9 +35,9 @@
% # GET_CFP(): refers to `reg_cfp`
% # GET_EP(): refers to `reg_cfp->ep`
% # GET_SP(): refers to `reg_cfp->sp`, or `(stack + stack_size)` if local_stack_p
-% # GET_SELF(): refers to `reg_cfp->self`
+% # GET_SELF(): refers to `cfp_self`
% # GET_LEP(): refers to `VM_EP_LEP(reg_cfp->ep)`
-% # EXEC_EC_CFP(): refers to `val = vm_exec(ec, TRUE)` with frame setup
+% # EXEC_EC_CFP(): refers to `val = vm_exec(ec, true)` with frame setup
% # CALL_METHOD(): using `GET_CFP()` and `EXEC_EC_CFP()`
% # TOPN(): refers to `reg_cfp->sp`, or `*(stack + (stack_size - num - 1))` if local_stack_p
% # STACK_ADDR_FROM_TOP(): refers to `reg_cfp->sp`, or `stack + (stack_size - num)` if local_stack_p
@@ -49,7 +48,7 @@
switch (insn) {
% (RubyVM::BareInstructions.to_a + RubyVM::OperandsUnifications.to_a).each do |insn|
% next if unsupported_insns.include?(insn.name)
- case BIN(<%= insn.name %>):
+ case BIN(<%= insn.name %>): {
% # Instruction-specific behavior in JIT
% case insn.name
% when 'opt_send_without_block', 'send'
@@ -57,30 +56,48 @@ switch (insn) {
% when *send_compatible_opt_insns
% # To avoid cancel, just emit `opt_send_without_block` instead of `opt_*` insn if call cache is populated.
% cd_index = insn.opes.index { |o| o.fetch(:type) == 'CALL_DATA' }
- if (has_valid_method_type(status->cc_entries + call_data_index((CALL_DATA)operands[<%= cd_index %>], body))) {
-<%= render 'mjit_compile_send', locals: { insn: opt_send_without_block } -%>
-<%= render 'mjit_compile_insn', locals: { insn: opt_send_without_block } -%>
- break;
- }
+ if (has_cache_for_send(captured_cc_entries(status)[call_data_index((CALL_DATA)operands[<%= cd_index %>], body)], BIN(<%= insn.name %>))) {
+<%= render 'mjit_compile_send', locals: { insn: opt_send_without_block } -%>
+<%= render 'mjit_compile_insn', locals: { insn: opt_send_without_block } -%>
+ break;
+ }
% when 'getinstancevariable', 'setinstancevariable'
<%= render 'mjit_compile_ivar', locals: { insn: insn } -%>
-% when 'leave'
- if (b->stack_size != 1) {
- if (mjit_opts.warnings || mjit_opts.verbose)
- fprintf(stderr, "MJIT warning: Unexpected JIT stack_size on leave: %d\n", b->stack_size);
- status->success = false;
- }
-% # Special leave for an inlined call.
- if (status->inlined_iseqs == NULL) { // the current ISeq is being inlined
- fprintf(f, " return stack[0];\n");
- b->stack_size += <%= insn.call_attribute('sp_inc') %>;
- break;
- }
+% when 'invokebuiltin', 'opt_invokebuiltin_delegate'
+<%= render 'mjit_compile_invokebuiltin', locals: { insn: insn } -%>
+% when 'opt_getinlinecache'
+<%= render 'mjit_compile_getinlinecache', locals: { insn: insn } -%>
+% when 'leave', 'opt_invokebuiltin_delegate_leave'
+% # opt_invokebuiltin_delegate_leave also implements leave insn. We need to handle it here for inlining.
+% if insn.name == 'opt_invokebuiltin_delegate_leave'
+<%= render 'mjit_compile_invokebuiltin', locals: { insn: insn } -%>
+% else
+ if (b->stack_size != 1) {
+ if (mjit_opts.warnings || mjit_opts.verbose)
+ fprintf(stderr, "MJIT warning: Unexpected JIT stack_size on leave: %d\n", b->stack_size);
+ status->success = false;
+ }
+% end
+% # Skip vm_pop_frame for inlined call
+ if (status->inlined_iseqs != NULL) { // the current ISeq is NOT being inlined
+% # Cancel on interrupts to make leave insn leaf
+ fprintf(f, " if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(ec))) {\n");
+ fprintf(f, " reg_cfp->sp = vm_base_ptr(reg_cfp) + %d;\n", b->stack_size);
+ fprintf(f, " reg_cfp->pc = original_body_iseq + %d;\n", pos);
+ fprintf(f, " rb_threadptr_execute_interrupts(rb_ec_thread_ptr(ec), 0);\n");
+ fprintf(f, " }\n");
+ fprintf(f, " ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(reg_cfp);\n"); // vm_pop_frame
+ }
+ fprintf(f, " return stack[0];\n");
+ b->stack_size += <%= insn.call_attribute('sp_inc') %>;
+ b->finish_p = TRUE;
+ break;
% end
%
% # Main insn implementation generated by insns.def
<%= render 'mjit_compile_insn', locals: { insn: insn } -%>
break;
+ }
% end
%
% # We don't support InstructionsUnifications yet because it's not used for now.
diff --git a/tool/runruby.rb b/tool/runruby.rb
index 4715ff4d5c..9562efc00d 100755
--- a/tool/runruby.rb
+++ b/tool/runruby.rb
@@ -85,7 +85,8 @@ config = File.read(conffile)
config.sub!(/^(\s*)RUBY_VERSION\b.*(\sor\s*)\n.*\n/, '')
config = Module.new {module_eval(config, conffile)}::RbConfig::CONFIG
-ruby = File.join(archdir, config["RUBY_INSTALL_NAME"]+config['EXEEXT'])
+install_name = config["RUBY_INSTALL_NAME"]+config['EXEEXT']
+ruby = File.join(archdir, install_name)
unless File.exist?(ruby)
abort "#{ruby} is not found.\nTry `make' first, then `make test', please.\n"
end
@@ -106,7 +107,7 @@ env = {
'RUBY_FIBER_MACHINE_STACK_SIZE' => '1',
}
-runner = File.join(abs_archdir, "exe/ruby#{config['EXEEXT']}")
+runner = File.join(abs_archdir, "exe/#{install_name}")
runner = nil unless File.exist?(runner)
abs_ruby = runner || File.expand_path(ruby)
env["RUBY"] = abs_ruby
diff --git a/tool/search-cgvars.rb b/tool/search-cgvars.rb
new file mode 100644
index 0000000000..c62641a3ff
--- /dev/null
+++ b/tool/search-cgvars.rb
@@ -0,0 +1,55 @@
+#
+# Listing C's global variables in .so or .o, or .bundle on Mac OS using "objdump -t" (elf64-x86-64)
+# to check ractor-safety.
+#
+# Usage: ruby search-cgvars.rb foo.so bar.o .ext/x86_64-darwin18/psych.bundle
+#
+MAC_OS = RbConfig::CONFIG['host_os'].match? /darwin|mac os/
+
+def gvars file
+ # '0000000000031ac8 g O .bss 0000000000000008 rb_cSockIfaddr'
+ # On mac, with .bundle files:
+ # '0000000000004258 l O __DATA,__bss _passwd_blocking'
+
+ strs = `objdump -t #{file}`
+ found = {}
+ strs.each_line{|line|
+ if /[\da-f]{16} / =~ line
+ addr = line[0...16]
+ flags = line[17...24].tr(' ', '').split(//).sort.uniq
+ rest = line[25..]
+ if MAC_OS
+ seg, name = rest.split(/\s+/)
+ else
+ seg, size, name = rest.split(/\s+/)
+ end
+ if flags.include?('O')
+ # p [addr, flags, seg, size, name]
+ found[name] = [flags, seg, *size]
+ end
+ end
+ }
+ puts "## #{file}:"
+ found.sort_by{|name, (flags, *)|
+ [flags, name]
+ }.each{|name, rest|
+ flags, seg, size = *rest
+ next if (size.to_i == 0 && !MAC_OS) && seg != '*UND*'
+ case seg
+ when ".rodata", ".data.rel.ro", ".got.plt", ".eh_frame", ".fini_array"
+ next
+ when /,__const$/ # Mac OS
+ next
+ end
+ case name
+ when /^id_/, /^rbimpl_id/, /^sym_/, /^rb_[cme]/, /\Acompleted\.\d+\z/
+ next
+ when /^_id_/, /\.rbimpl_id(\.\d+)?$/ # Mac OS
+ next
+ end
+ puts " %40s %s" % [name, rest.inspect]
+ }
+end
+ARGV.each{|file|
+ gvars file
+}
diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb
index 676441d7a5..77854a6a48 100644
--- a/tool/sync_default_gems.rb
+++ b/tool/sync_default_gems.rb
@@ -1,62 +1,11 @@
-# sync following repositories to ruby repository
-#
-# * https://github.com/rubygems/rubygems
-# * https://github.com/bundler/bundler
-# * https://github.com/ruby/rdoc
-# * https://github.com/ruby/reline
-# * https://github.com/flori/json
-# * https://github.com/ruby/psych
-# * https://github.com/ruby/fileutils
-# * https://github.com/ruby/fiddle
-# * https://github.com/ruby/stringio
-# * https://github.com/ruby/io-console
-# * https://github.com/ruby/csv
-# * https://github.com/ruby/webrick
-# * https://github.com/ruby/dbm
-# * https://github.com/ruby/gdbm
-# * https://github.com/ruby/sdbm
-# * https://github.com/ruby/etc
-# * https://github.com/ruby/date
-# * https://github.com/ruby/zlib
-# * https://github.com/ruby/fcntl
-# * https://github.com/ruby/strscan
-# * https://github.com/ruby/ipaddr
-# * https://github.com/ruby/logger
-# * https://github.com/ruby/prime
-# * https://github.com/ruby/matrix
-# * https://github.com/ruby/ostruct
-# * https://github.com/ruby/rexml
-# * https://github.com/ruby/rss
-# * https://github.com/ruby/irb
-# * https://github.com/ruby/tracer
-# * https://github.com/ruby/forwardable
-# * https://github.com/ruby/mutex_m
-# * https://github.com/ruby/racc
-# * https://github.com/ruby/singleton
-# * https://github.com/ruby/open3
-# * https://github.com/ruby/getoptlong
-# * https://github.com/ruby/pstore
-# * https://github.com/ruby/delegate
-# * https://github.com/ruby/benchmark
-# * https://github.com/ruby/net-pop
-# * https://github.com/ruby/net-smtp
-# * https://github.com/ruby/cgi
-# * https://github.com/ruby/readline
-# * https://github.com/ruby/readline-ext
-# * https://github.com/ruby/observer
-# * https://github.com/ruby/timeout
-# * https://github.com/ruby/yaml
-# * https://github.com/ruby/uri
-# * https://github.com/ruby/openssl
-# * https://github.com/ruby/did_you_mean
-#
+# sync upstream github repositories to ruby repository
require 'fileutils'
include FileUtils
-$repositories = {
+REPOSITORIES = {
rubygems: 'rubygems/rubygems',
- bundler: 'bundler/bundler',
+ bundler: 'rubygems/rubygems',
rdoc: 'ruby/rdoc',
reline: 'ruby/reline',
json: 'flori/json',
@@ -64,12 +13,12 @@ $repositories = {
fileutils: 'ruby/fileutils',
fiddle: 'ruby/fiddle',
stringio: 'ruby/stringio',
- ioconsole: 'ruby/io-console',
+ "io-console": 'ruby/io-console',
+ "io-nonblock": 'ruby/io-nonblock',
+ "io-wait": 'ruby/io-wait',
csv: 'ruby/csv',
- webrick: 'ruby/webrick',
dbm: 'ruby/dbm',
gdbm: 'ruby/gdbm',
- sdbm: 'ruby/sdbm',
etc: 'ruby/etc',
date: 'ruby/date',
zlib: 'ruby/zlib',
@@ -80,8 +29,6 @@ $repositories = {
prime: 'ruby/prime',
matrix: 'ruby/matrix',
ostruct: 'ruby/ostruct',
- rexml: 'ruby/rexml',
- rss: 'ruby/rss',
irb: 'ruby/irb',
tracer: 'ruby/tracer',
forwardable: "ruby/forwardable",
@@ -93,39 +40,72 @@ $repositories = {
pstore: "ruby/pstore",
delegate: "ruby/delegate",
benchmark: "ruby/benchmark",
- netpop: "ruby/net-pop",
- netsmtp: "ruby/net-smtp",
+ "net-pop": "ruby/net-pop",
+ "net-smtp": "ruby/net-smtp",
cgi: "ruby/cgi",
readline: "ruby/readline",
- readlineext: "ruby/readline-ext",
+ "readline-ext": "ruby/readline-ext",
observer: "ruby/observer",
timeout: "ruby/timeout",
yaml: "ruby/yaml",
uri: "ruby/uri",
openssl: "ruby/openssl",
- did_you_mean: "ruby/did_you_mean"
+ did_you_mean: "ruby/did_you_mean",
+ weakref: "ruby/weakref",
+ tempfile: "ruby/tempfile",
+ tmpdir: "ruby/tmpdir",
+ English: "ruby/English",
+ "net-protocol": "ruby/net-protocol",
+ "net-imap": "ruby/net-imap",
+ "net-ftp": "ruby/net-ftp",
+ "net-http": "ruby/net-http",
+ bigdecimal: "ruby/bigdecimal",
+ optparse: "ruby/optparse",
+ set: "ruby/set",
+ find: "ruby/find",
+ rinda: "ruby/rinda",
+ erb: "ruby/erb",
+ nkf: "ruby/nkf",
+ tsort: "ruby/tsort",
+ abbrev: "ruby/abbrev",
+ shellwords: "ruby/shellwords",
+ base64: "ruby/base64",
+ syslog: "ruby/syslog",
+ "open-uri": "ruby/open-uri",
+ securerandom: "ruby/securerandom",
+ resolv: "ruby/resolv",
+ "resolv-replace": "ruby/resolv-replace",
+ time: "ruby/time",
+ pp: "ruby/pp",
+ prettyprint: "ruby/prettyprint",
+ drb: "ruby/drb",
+ pathname: "ruby/pathname",
+ digest: "ruby/digest",
}
def sync_default_gems(gem)
- puts "Sync #{$repositories[gem.to_sym]}"
+ puts "Sync #{REPOSITORIES[gem.to_sym]}"
- upstream = File.join("..", "..", $repositories[gem.to_sym])
+ upstream = File.join("..", "..", REPOSITORIES[gem.to_sym])
case gem
when "rubygems"
- rm_rf(%w[lib/rubygems* test/rubygems])
+ rm_rf(%w[lib/rubygems lib/rubygems.rb test/rubygems])
cp_r(Dir.glob("#{upstream}/lib/rubygems*"), "lib")
cp_r("#{upstream}/test/rubygems", "test")
when "bundler"
- rm_rf(%w[lib/bundler* libexec/bundler libexec/bundle spec/bundler man/bundle* man/gemfile*])
- cp_r(Dir.glob("#{upstream}/lib/bundler*"), "lib")
- cp_r(Dir.glob("#{upstream}/exe/bundle*"), "libexec")
- cp_r("#{upstream}/bundler.gemspec", "lib/bundler")
- cp_r("#{upstream}/spec", "spec/bundler")
- cp_r(Dir.glob("#{upstream}/man/*.{1,5,1\.txt,5\.txt,ronn}"), "man")
+ rm_rf(%w[lib/bundler lib/bundler.rb libexec/bundler libexec/bundle spec/bundler tool/bundler/*] + Dir.glob("man/{bundle*,gemfile*}"))
+ cp_r(Dir.glob("#{upstream}/bundler/lib/bundler*"), "lib")
+ cp_r(Dir.glob("#{upstream}/bundler/exe/bundle*"), "libexec")
+ cp_r("#{upstream}/bundler/bundler.gemspec", "lib/bundler")
+ cp_r("#{upstream}/bundler/spec", "spec/bundler")
+ cp_r(Dir.glob("#{upstream}/bundler/tool/bundler/test_gems*"), "tool/bundler")
+ cp_r(Dir.glob("#{upstream}/bundler/tool/bundler/rubocop_gems*"), "tool/bundler")
+ cp_r(Dir.glob("#{upstream}/bundler/tool/bundler/standard_gems*"), "tool/bundler")
+ cp_r(Dir.glob("#{upstream}/bundler/man/*.{1,5,1\.txt,5\.txt,ronn}"), "man")
rm_rf(%w[spec/bundler/support/artifice/vcr_cassettes])
when "rdoc"
- rm_rf(%w[lib/rdoc* test/rdoc libexec/rdoc libexec/ri])
+ rm_rf(%w[lib/rdoc lib/rdoc.rb test/rdoc libexec/rdoc libexec/ri])
cp_r(Dir.glob("#{upstream}/lib/rdoc*"), "lib")
cp_r("#{upstream}/test/rdoc", "test")
cp_r("#{upstream}/rdoc.gemspec", "lib/rdoc")
@@ -134,7 +114,7 @@ def sync_default_gems(gem)
rm_rf(%w[lib/rdoc/markdown.kpeg lib/rdoc/markdown/literals.kpeg lib/rdoc/rd/block_parser.ry lib/rdoc/rd/inline_parser.ry])
`git checkout lib/rdoc/.document`
when "reline"
- rm_rf(%w[lib/reline* test/reline])
+ rm_rf(%w[lib/reline lib/reline.rb test/reline])
cp_r(Dir.glob("#{upstream}/lib/reline*"), "lib")
cp_r("#{upstream}/test/reline", "test")
cp_r("#{upstream}/reline.gemspec", "lib/reline")
@@ -142,8 +122,10 @@ def sync_default_gems(gem)
rm_rf(%w[ext/json test/json])
cp_r("#{upstream}/ext/json/ext", "ext/json")
cp_r("#{upstream}/tests", "test/json")
+ rm_rf("test/json/lib")
cp_r("#{upstream}/lib", "ext/json")
cp_r("#{upstream}/json.gemspec", "ext/json")
+ cp_r("#{upstream}/VERSION", "ext/json")
rm_rf(%w[ext/json/lib/json/ext ext/json/lib/json/pure.rb ext/json/lib/json/pure])
`git checkout ext/json/extconf.rb ext/json/parser/prereq.mk ext/json/generator/depend ext/json/parser/depend ext/json/depend`
when "psych"
@@ -170,7 +152,7 @@ def sync_default_gems(gem)
cp_r("#{upstream}/test/stringio", "test")
cp_r("#{upstream}/stringio.gemspec", "ext/stringio")
`git checkout ext/stringio/depend ext/stringio/README.md`
- when "ioconsole"
+ when "io-console"
rm_rf(%w[ext/io/console test/io/console])
cp_r("#{upstream}/ext/io/console", "ext/io")
cp_r("#{upstream}/test/io/console", "test/io")
@@ -178,6 +160,18 @@ def sync_default_gems(gem)
cp_r("#{upstream}/lib/io/console", "ext/io/console/lib")
cp_r("#{upstream}/io-console.gemspec", "ext/io/console")
`git checkout ext/io/console/depend`
+ when "io-nonblock"
+ rm_rf(%w[ext/io/nonblock test/io/nonblock])
+ cp_r("#{upstream}/ext/io/nonblock", "ext/io")
+ cp_r("#{upstream}/test/io/nonblock", "test/io")
+ cp_r("#{upstream}/io-nonblock.gemspec", "ext/io/nonblock")
+ `git checkout ext/io/nonblock/depend`
+ when "io-wait"
+ rm_rf(%w[ext/io/wait test/io/wait])
+ cp_r("#{upstream}/ext/io/wait", "ext/io")
+ cp_r("#{upstream}/test/io/wait", "test/io")
+ cp_r("#{upstream}/io-wait.gemspec", "ext/io/wait")
+ `git checkout ext/io/wait/depend`
when "dbm"
rm_rf(%w[ext/dbm test/dbm])
cp_r("#{upstream}/ext/dbm", "ext")
@@ -190,12 +184,6 @@ def sync_default_gems(gem)
cp_r("#{upstream}/test/gdbm", "test")
cp_r("#{upstream}/gdbm.gemspec", "ext/gdbm")
`git checkout ext/gdbm/depend ext/gdbm/README`
- when "sdbm"
- rm_rf(%w[ext/sdbm test/sdbm])
- cp_r("#{upstream}/ext/sdbm", "ext")
- cp_r("#{upstream}/test/sdbm", "test")
- cp_r("#{upstream}/sdbm.gemspec", "ext/sdbm")
- `git checkout ext/sdbm/depend`
when "etc"
rm_rf(%w[ext/etc test/etc])
cp_r("#{upstream}/ext/etc", "ext")
@@ -229,7 +217,7 @@ def sync_default_gems(gem)
rm_rf(%w["ext/strscan/regenc.h ext/strscan/regint.h"])
`git checkout ext/strscan/depend`
when "racc"
- rm_rf(%w[lib/racc* ext/racc test/racc])
+ rm_rf(%w[lib/racc lib/racc.rb ext/racc test/racc])
cp_r(Dir.glob("#{upstream}/lib/racc*"), "lib")
mkdir_p("ext/racc/cparse")
cp_r(Dir.glob("#{upstream}/ext/racc/cparse/*"), "ext/racc/cparse")
@@ -248,59 +236,137 @@ def sync_default_gems(gem)
when "openssl"
rm_rf(%w[ext/openssl test/openssl])
cp_r("#{upstream}/ext/openssl", "ext")
- mkdir_p("ext/openssl/lib")
- cp_r("#{upstream}/lib/openssl", "ext/openssl/lib")
- cp_r("#{upstream}/lib/openssl.rb", "ext/openssl/lib")
- cp_r("#{upstream}/test", "test/openssl")
+ cp_r("#{upstream}/lib", "ext/openssl")
+ cp_r("#{upstream}/test/openssl", "test")
rm_rf("test/openssl/envutil.rb")
cp_r("#{upstream}/openssl.gemspec", "ext/openssl")
cp_r("#{upstream}/History.md", "ext/openssl")
`git checkout ext/openssl/depend`
- when "netpop"
- sync_lib "net-pop"
- mv "lib/net-pop.gemspec", "lib/net/pop"
- when "netsmtp"
- sync_lib "net-smtp"
- mv "lib/net-smtp.gemspec", "lib/net/smtp"
- when "readlineext"
- sync_lib "readline-ext"
- mv "lib/readline-ext.gemspec", "ext/readline"
+ when "net-pop"
+ rm_rf(%w[lib/net/pop.rb lib/net/net-pop.gemspec test/net/pop])
+ cp_r("#{upstream}/lib/net/pop.rb", "lib/net")
+ cp_r("#{upstream}/test/net/pop", "test/net")
+ cp_r("#{upstream}/net-pop.gemspec", "lib/net")
+ when "net-smtp"
+ rm_rf(%w[lib/net/smtp.rb lib/net/net-smtp.gemspec test/net/smtp])
+ cp_r("#{upstream}/lib/net/smtp.rb", "lib/net")
+ cp_r("#{upstream}/test/net/smtp", "test/net")
+ cp_r("#{upstream}/net-smtp.gemspec", "lib/net")
+ when "net-protocol"
+ rm_rf(%w[lib/net/protocol.rb lib/net/net-protocol.gemspec test/net/protocol])
+ cp_r("#{upstream}/lib/net/protocol.rb", "lib/net")
+ cp_r("#{upstream}/test/net/protocol", "test/net")
+ cp_r("#{upstream}/net-protocol.gemspec", "lib/net")
+ when "net-imap"
+ rm_rf(%w[lib/net/imap.rb lib/net/net-imap.gemspec test/net/imap])
+ cp_r("#{upstream}/lib/net/imap.rb", "lib/net")
+ cp_r("#{upstream}/test/net/imap", "test/net")
+ cp_r("#{upstream}/net-imap.gemspec", "lib/net")
+ when "net-ftp"
+ rm_rf(%w[lib/net/ftp.rb lib/net/net-ftp.gemspec test/net/ftp])
+ cp_r("#{upstream}/lib/net/ftp.rb", "lib/net")
+ cp_r("#{upstream}/test/net/ftp", "test/net")
+ cp_r("#{upstream}/net-ftp.gemspec", "lib/net")
+ when "net-http"
+ rm_rf(%w[lib/net/http.rb lib/net/http test/net/http])
+ cp_r("#{upstream}/lib/net/http.rb", "lib/net")
+ cp_r("#{upstream}/lib/net/http", "lib/net")
+ cp_r("#{upstream}/test/net/http", "test/net")
+ cp_r("#{upstream}/net-http.gemspec", "lib/net/http")
+ when "readline-ext"
+ rm_rf(%w[ext/readline test/readline])
+ cp_r("#{upstream}/ext/readline", "ext")
+ cp_r("#{upstream}/test/readline", "test")
+ cp_r("#{upstream}/readline-ext.gemspec", "ext/readline")
+ `git checkout ext/readline/depend`
when "did_you_mean"
- rm_rf(%w[lib/did_you_mean* test/did_you_mean])
+ rm_rf(%w[lib/did_you_mean lib/did_you_mean.rb test/did_you_mean])
cp_r(Dir.glob("#{upstream}/lib/did_you_mean*"), "lib")
cp_r("#{upstream}/did_you_mean.gemspec", "lib/did_you_mean")
cp_r("#{upstream}/test", "test/did_you_mean")
rm_rf(%w[test/did_you_mean/tree_spell/test_explore.rb])
+ when "erb"
+ rm_rf(%w[lib/erb* test/erb libexec/erb])
+ cp_r("#{upstream}/lib/erb.rb", "lib")
+ cp_r("#{upstream}/test/erb", "test")
+ cp_r("#{upstream}/erb.gemspec", "lib")
+ cp_r("#{upstream}/libexec/erb", "libexec")
+ when "nkf"
+ rm_rf(%w[ext/nkf test/nkf])
+ cp_r("#{upstream}/ext/nkf", "ext")
+ cp_r("#{upstream}/lib", "ext/nkf")
+ cp_r("#{upstream}/test/nkf", "test")
+ cp_r("#{upstream}/nkf.gemspec", "ext/nkf")
+ `git checkout ext/nkf/depend`
+ when "syslog"
+ rm_rf(%w[ext/syslog test/syslog test/test_syslog.rb])
+ cp_r("#{upstream}/ext/syslog", "ext")
+ cp_r("#{upstream}/lib", "ext/syslog")
+ cp_r("#{upstream}/test/syslog", "test")
+ cp_r("#{upstream}/test/test_syslog.rb", "test")
+ cp_r("#{upstream}/syslog.gemspec", "ext/syslog")
+ `git checkout ext/syslog/depend`
+ when "bigdecimal"
+ rm_rf(%w[ext/bigdecimal test/bigdecimal])
+ cp_r("#{upstream}/ext/bigdecimal", "ext")
+ cp_r("#{upstream}/sample", "ext/bigdecimal")
+ cp_r("#{upstream}/lib", "ext/bigdecimal")
+ cp_r("#{upstream}/test/bigdecimal", "test")
+ cp_r("#{upstream}/bigdecimal.gemspec", "ext/bigdecimal")
+ `git checkout ext/bigdecimal/depend`
+ when "pathname"
+ rm_rf(%w[ext/pathname test/pathname])
+ cp_r("#{upstream}/ext/pathname", "ext")
+ cp_r("#{upstream}/test/pathname", "test")
+ cp_r("#{upstream}/lib", "ext/pathname")
+ cp_r("#{upstream}/pathname.gemspec", "ext/pathname")
+ `git checkout ext/pathname/depend`
+ when "digest"
+ rm_rf(%w[ext/digest test/digest])
+ cp_r("#{upstream}/ext/digest", "ext")
+ mkdir_p("#{upstream}/ext/digest/lib")
+ cp_r("#{upstream}/lib/digest.rb", "ext/digest/lib/")
+ cp_r("#{upstream}/test/digest", "test")
+ cp_r("#{upstream}/digest.gemspec", "ext/digest")
+ `git checkout ext/digest/depend ext/digest/*/depend`
+ when "set"
+ sync_lib gem, upstream
+ cp_r("#{upstream}/test", ".")
else
- sync_lib gem
+ sync_lib gem, upstream
end
end
-IGNORE_FILE_PATTERN = /(\.travis.yml|appveyor\.yml|azure\-pipelines\.yml|\.gitignore|Gemfile|README\.md|History\.txt|Rakefile|CODE_OF_CONDUCT\.md)/
+IGNORE_FILE_PATTERN =
+ /\A(?:[A-Z]\w*\.(?:md|txt)
+ |[^\/]+\.yml
+ |\.git.*
+ |[A-Z]\w+file
+ )\z/x
-def sync_default_gems_with_commits(gem, range)
- puts "Sync #{$repositories[gem.to_sym]} with commit history."
+def sync_default_gems_with_commits(gem, ranges, edit: nil)
+ puts "Sync #{REPOSITORIES[gem.to_sym]} with commit history."
IO.popen(%W"git remote") do |f|
unless f.read.split.include?(gem)
- `git remote add #{gem} git@github.com:#{$repositories[gem.to_sym]}.git`
+ `git remote add #{gem} git@github.com:#{REPOSITORIES[gem.to_sym]}.git`
end
end
system(*%W"git fetch --no-tags #{gem}")
- unless range.include?("..")
- range = "#{range}~1..#{range}"
- end
+ commits = ranges.flat_map do |range|
+ unless range.include?("..")
+ range = "#{range}~1..#{range}"
+ end
- commits = IO.popen(%W"git log --format=%H,%s #{range}") do |f|
- f.read.split("\n").reverse.map{|commit| commit.split(',', 2)}
+ IO.popen(%W"git log --format=%H,%s #{range}") do |f|
+ f.read.split("\n").reverse.map{|commit| commit.split(',', 2)}
+ end
end
# Ignore Merge commit and insufficiency commit for ruby core repository.
commits.delete_if do |sha, subject|
- files = IO.popen(%W"git diff-tree --no-commit-id --name-only -r #{sha}") do |f|
- f.readlines
- end
+ files = IO.popen(%W"git diff-tree --no-commit-id --name-only -r #{sha}", &:readlines)
subject =~ /^Merge/ || subject =~ /^Auto Merge/ || files.all?{|file| file =~ IGNORE_FILE_PATTERN}
end
@@ -313,10 +379,10 @@ def sync_default_gems_with_commits(gem, range)
ENV["FILTER_BRANCH_SQUELCH_WARNING"] = "1"
commits.each do |sha, subject|
- puts "Pick #{sha} from #{$repositories[gem.to_sym]}."
+ puts "Pick #{sha} from #{REPOSITORIES[gem.to_sym]}."
skipped = false
- result = IO.popen(%W"git cherry-pick #{sha}").read
+ result = IO.popen(%W"git cherry-pick #{sha}", &:read)
if result =~ /nothing\ to\ commit/
`git reset`
skipped = true
@@ -325,18 +391,42 @@ def sync_default_gems_with_commits(gem, range)
next if skipped
if result.empty?
+ skipped = true
+ elsif /^CONFLICT/ =~ result
+ result = IO.popen(%W"git status --porcelain", &:readlines).each(&:chomp!)
+ result.map! {|line| line[/^.U (.*)/, 1]}
+ result.compact!
+ ignore, conflict = result.partition {|name| IGNORE_FILE_PATTERN =~ name}
+ unless ignore.empty?
+ system(*%W"git reset HEAD --", *ignore)
+ system(*%W"git checkout HEAD --", *ignore)
+ end
+ unless conflict.empty?
+ if edit
+ case
+ when (editor = ENV["GIT_EDITOR"] and !editor.empty?)
+ when (editor = `git config core.editor` and (editor.chomp!; !editor.empty?))
+ end
+ if editor
+ system([editor, conflict].join(' '))
+ end
+ end
+ end
+ skipped = !system({"GIT_EDITOR"=>"true"}, *%W"git cherry-pick --no-edit --continue")
+ end
+
+ if skipped
failed_commits << sha
`git reset` && `git checkout .` && `git clean -fd`
- skipped = true
puts "Failed to pick #{sha}"
+ next
end
- next if skipped
puts "Update commit message: #{sha}"
- prefix = "[#{($repositories[gem.to_sym])}]".gsub(/\//, '\/')
- suffix = "https://github.com/#{($repositories[gem.to_sym])}/commit/#{sha[0,10]}"
- `git filter-branch -f --msg-filter 'sed "1s/^/#{prefix} /" && echo && echo #{suffix}' -- HEAD~1..HEAD`
+ prefix = "[#{(REPOSITORIES[gem.to_sym])}]".gsub(/\//, '\/')
+ suffix = "https://github.com/#{(REPOSITORIES[gem.to_sym])}/commit/#{sha[0,10]}"
+ `git filter-branch -f --msg-filter 'grep "" - | sed "1s/^/#{prefix} /" && echo && echo #{suffix}' -- HEAD~1..HEAD`
unless $?.success?
puts "Failed to modify commit message of #{sha}"
break
@@ -349,28 +439,31 @@ def sync_default_gems_with_commits(gem, range)
end
end
-def sync_lib(repo)
- unless File.directory?("../#{repo}")
- abort %[Expected '../#{repo}' \(#{File.expand_path("../#{repo}")}\) to be a directory, but it wasn't.]
+def sync_lib(repo, upstream = nil)
+ unless upstream and File.directory?(upstream) or File.directory?(upstream = "../#{repo}")
+ abort %[Expected '#{upstream}' \(#{File.expand_path("#{upstream}")}\) to be a directory, but it wasn't.]
end
rm_rf(["lib/#{repo}.rb", "lib/#{repo}/*", "test/test_#{repo}.rb"])
- cp_r(Dir.glob("../#{repo}/lib/*"), "lib")
+ cp_r(Dir.glob("#{upstream}/lib/*"), "lib")
tests = if File.directory?("test/#{repo}")
"test/#{repo}"
else
"test/test_#{repo}.rb"
end
- cp_r("../#{repo}/#{tests}", "test") if File.exist?("../#{repo}/#{tests}")
+ cp_r("#{upstream}/#{tests}", "test") if File.exist?("#{upstream}/#{tests}")
gemspec = if File.directory?("lib/#{repo}")
"lib/#{repo}/#{repo}.gemspec"
else
"lib/#{repo}.gemspec"
end
- cp_r("../#{repo}/#{repo}.gemspec", "#{gemspec}")
+ cp_r("#{upstream}/#{repo}.gemspec", "#{gemspec}")
end
def update_default_gems(gem)
- author, repository = $repositories[gem.to_sym].split('/')
+
+ author, repository = REPOSITORIES[gem.to_sym].split('/')
+
+ puts "Update #{author}/#{repository}"
unless File.exist?("../../#{author}/#{repository}")
mkdir_p("../../#{author}")
@@ -380,28 +473,66 @@ def update_default_gems(gem)
Dir.chdir("../../#{author}/#{repository}") do
unless `git remote`.match(/ruby\-core/)
`git remote add ruby-core git@github.com:ruby/ruby.git`
- `git fetch ruby-core --no-tags`
- `git co ruby-core/master`
- `git branch ruby-core`
end
- `git co ruby-core`
`git fetch ruby-core master --no-tags`
+ unless `git branch`.match(/ruby\-core/)
+ `git checkout ruby-core/master`
+ `git branch ruby-core`
+ end
+ `git checkout ruby-core`
`git rebase ruby-core/master`
- `git co master`
- `git stash`
- `git pull --rebase`
+ `git checkout master`
+ `git fetch origin master`
+ `git rebase origin/master`
end
end
case ARGV[0]
when "up"
- $repositories.keys.each{|gem| update_default_gems(gem.to_s)}
+ if ARGV[1]
+ update_default_gems(ARGV[1])
+ else
+ REPOSITORIES.keys.each{|gem| update_default_gems(gem.to_s)}
+ end
when "all"
- $repositories.keys.each{|gem| sync_default_gems(gem.to_s)}
+ REPOSITORIES.keys.each{|gem| sync_default_gems(gem.to_s)}
+when "list"
+ ARGV.shift
+ pattern = Regexp.new(ARGV.join('|'))
+ REPOSITORIES.each_pair do |name, gem|
+ next unless pattern =~ name or pattern =~ gem
+ printf "%-15s https://github.com/%s\n", name, gem
+ end
+when nil, "-h", "--help"
+ puts <<-HELP
+\e[1mSync with upstream code of default libraries\e[0m
+
+\e[1mImport a default library through `git clone` and `cp -rf` (git commits are lost)\e[0m
+ ruby #$0 rubygems
+
+\e[1mPick a single commit from the upstream repository\e[0m
+ ruby #$0 rubygems 97e9768612
+
+\e[1mPick a commit range from the upstream repository\e[0m
+ ruby #$0 rubygems 97e9768612..9e53702832
+
+\e[1mList known libraries\e[0m
+ ruby #$0 list
+
+\e[1mList known libraries matching with patterns\e[0m
+ ruby #$0 list read
+ HELP
+
+ exit
else
- if ARGV[1]
- sync_default_gems_with_commits(ARGV[0], ARGV[1])
+ if ARGV[0] == "-e"
+ edit = true
+ ARGV.shift
+ end
+ gem = ARGV.shift
+ if ARGV[0]
+ sync_default_gems_with_commits(gem, ARGV, edit: edit)
else
- sync_default_gems(ARGV[0])
+ sync_default_gems(gem)
end
end
diff --git a/tool/test-bundled-gems.rb b/tool/test-bundled-gems.rb
index ded4bc852a..b9a1e559d4 100644
--- a/tool/test-bundled-gems.rb
+++ b/tool/test-bundled-gems.rb
@@ -1,28 +1,55 @@
require 'rbconfig'
+require 'timeout'
allowed_failures = ENV['TEST_BUNDLED_GEMS_ALLOW_FAILURES'] || ''
allowed_failures = allowed_failures.split(',').reject(&:empty?)
-gem_dir = File.expand_path('../../gems', __FILE__)
+rake = File.realpath("../../.bundle/bin/rake", __FILE__)
+gem_dir = File.realpath('../../gems', __FILE__)
exit_code = 0
ruby = ENV['RUBY'] || RbConfig.ruby
+failed = []
File.foreach("#{gem_dir}/bundled_gems") do |line|
+ next if /^\s*(?:#|$)/ =~ line
gem = line.split.first
+ next if ARGV.any? {|pat| !File.fnmatch?(pat, gem)}
puts "\nTesting the #{gem} gem"
- gem_src_dir = File.expand_path("#{gem_dir}/src/#{gem}", __FILE__)
- test_command = "#{ruby} -C #{gem_src_dir} -Ilib ../../../.bundle/bin/rake"
+ test_command = "#{ruby} -C #{gem_dir}/src/#{gem} -Ilib #{rake} test"
+ first_timeout = 600 # 10min
+
+ if gem == "rbs"
+ racc = File.realpath("../../libexec/racc", __FILE__)
+ pid = Process.spawn("#{ruby} -C #{gem_dir}/src/#{gem} -Ilib #{racc} -v -o lib/rbs/parser.rb lib/rbs/parser.y")
+ Process.waitpid(pid)
+ test_command << " stdlib_test validate"
+
+ first_timeout *= 3
+ end
+
puts test_command
- system test_command
+ pid = Process.spawn(test_command, "#{/mingw|mswin/ =~ RUBY_PLATFORM ? 'new_' : ''}pgroup": true)
+ {nil => first_timeout, INT: 30, TERM: 10, KILL: nil}.each do |sig, sec|
+ if sig
+ puts "Sending #{sig} signal"
+ Process.kill("-#{sig}", pid)
+ end
+ begin
+ break Timeout.timeout(sec) {Process.wait(pid)}
+ rescue Timeout::Error
+ end
+ end
unless $?.success?
puts "Tests failed with exit code #{$?.exitstatus}"
if allowed_failures.include?(gem)
puts "Ignoring test failures for #{gem} due to \$TEST_BUNDLED_GEMS_ALLOW_FAILURES"
else
+ failed << gem
exit_code = $?.exitstatus
end
end
end
+puts "Failed gems: #{failed.join(', ')}" unless failed.empty?
exit exit_code
diff --git a/tool/test-coverage.rb b/tool/test-coverage.rb
index e0d7dd06e1..4950bc65de 100644
--- a/tool/test-coverage.rb
+++ b/tool/test-coverage.rb
@@ -44,7 +44,7 @@ def save_coverage_data(res1)
if cov[:methods]
h = {}
cov[:methods].each do |(klass, *key), count|
- h[[klass.inspect, *key]] = count
+ h[[klass.name, *key]] = count
end
cov[:methods].replace h
end
diff --git a/tool/test/minitest/test_minitest_unit.rb b/tool/test/minitest/test_minitest_unit.rb
index 1286b15372..5476cf9795 100644
--- a/tool/test/minitest/test_minitest_unit.rb
+++ b/tool/test/minitest/test_minitest_unit.rb
@@ -1372,6 +1372,9 @@ class TestMiniTestUnitTestCase < MiniTest::Unit::TestCase
assert_not_same assert_nothing_raised
assert_nothing_thrown assert_raise]
+ # These are compatibility methods for Minitest 5
+ ignores += %w[assertions assertions=]
+
asserts = methods.grep(/^assert/).sort - ignores
refutes = methods.grep(/^refute/).sort - ignores
diff --git a/tool/test/testunit/test_hideskip.rb b/tool/test/testunit/test_hideskip.rb
index 0188316a2c..13d887189e 100644
--- a/tool/test/testunit/test_hideskip.rb
+++ b/tool/test/testunit/test_hideskip.rb
@@ -6,7 +6,7 @@ class TestHideSkip < Test::Unit::TestCase
assert_not_match(/^ *1\) Skipped/, hideskip)
assert_match(/^ *1\) Skipped/, hideskip("--show-skip"))
output = hideskip("--hide-skip")
- output.gsub!(/Successful MJIT finish\n/, '') if RubyVM::MJIT.enabled?
+ output.gsub!(/Successful MJIT finish\n/, '') if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
assert_match(/assertions\/s.\n+1 tests, 0 assertions, 0 failures, 0 errors, 1 skips/, output)
end
diff --git a/tool/test/testunit/test_parallel.rb b/tool/test/testunit/test_parallel.rb
index d5f7cf4487..44e9eb18d8 100644
--- a/tool/test/testunit/test_parallel.rb
+++ b/tool/test/testunit/test_parallel.rb
@@ -6,7 +6,7 @@ module TestParallel
PARALLEL_RB = "#{File.dirname(__FILE__)}/../../lib/test/unit/parallel.rb"
TESTS = "#{File.dirname(__FILE__)}/tests_for_parallel"
# use large timeout for --jit-wait
- TIMEOUT = EnvUtil.apply_timeout_scale(RubyVM::MJIT.enabled? ? 100 : 30)
+ TIMEOUT = EnvUtil.apply_timeout_scale(defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? ? 100 : 30)
class TestParallelWorker < Test::Unit::TestCase
def setup
diff --git a/test/webrick/.htaccess b/tool/test/webrick/.htaccess
index 69d4659b9f..69d4659b9f 100644
--- a/test/webrick/.htaccess
+++ b/tool/test/webrick/.htaccess
diff --git a/tool/test/webrick/test_cgi.rb b/tool/test/webrick/test_cgi.rb
new file mode 100644
index 0000000000..7a75cf565e
--- /dev/null
+++ b/tool/test/webrick/test_cgi.rb
@@ -0,0 +1,170 @@
+# coding: US-ASCII
+# frozen_string_literal: false
+require_relative "utils"
+require "webrick"
+require "test/unit"
+
+class TestWEBrickCGI < Test::Unit::TestCase
+ CRLF = "\r\n"
+
+ def teardown
+ WEBrick::Utils::TimeoutHandler.terminate
+ super
+ end
+
+ def start_cgi_server(log_tester=TestWEBrick::DefaultLogTester, &block)
+ config = {
+ :CGIInterpreter => TestWEBrick::RubyBin,
+ :DocumentRoot => File.dirname(__FILE__),
+ :DirectoryIndex => ["webrick.cgi"],
+ :RequestCallback => Proc.new{|req, res|
+ def req.meta_vars
+ meta = super
+ meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
+ meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
+ return meta
+ end
+ },
+ }
+ if RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32/
+ config[:CGIPathEnv] = ENV['PATH'] # runtime dll may not be in system dir.
+ end
+ TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
+ block.call(server, addr, port, log)
+ }
+ end
+
+ def test_cgi
+ start_cgi_server{|server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/webrick.cgi")
+ http.request(req){|res| assert_equal("/webrick.cgi", res.body, log.call)}
+ req = Net::HTTP::Get.new("/webrick.cgi/path/info")
+ http.request(req){|res| assert_equal("/path/info", res.body, log.call)}
+ req = Net::HTTP::Get.new("/webrick.cgi/%3F%3F%3F?foo=bar")
+ http.request(req){|res| assert_equal("/???", res.body, log.call)}
+ unless RUBY_PLATFORM =~ /mswin|mingw|cygwin|bccwin32|java/
+ # Path info of res.body is passed via ENV.
+ # ENV[] returns different value on Windows depending on locale.
+ req = Net::HTTP::Get.new("/webrick.cgi/%A4%DB%A4%B2/%A4%DB%A4%B2")
+ http.request(req){|res|
+ assert_equal("/\xA4\xDB\xA4\xB2/\xA4\xDB\xA4\xB2", res.body, log.call)}
+ end
+ req = Net::HTTP::Get.new("/webrick.cgi?a=1;a=2;b=x")
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
+ req = Net::HTTP::Get.new("/webrick.cgi?a=1&a=2&b=x")
+ http.request(req){|res| assert_equal("a=1, a=2, b=x", res.body, log.call)}
+
+ req = Net::HTTP::Post.new("/webrick.cgi?a=x;a=y;b=1")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ http.request(req, "a=1;a=2;b=x"){|res|
+ assert_equal("a=1, a=2, b=x", res.body, log.call)}
+ req = Net::HTTP::Post.new("/webrick.cgi?a=x&a=y&b=1")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ http.request(req, "a=1&a=2&b=x"){|res|
+ assert_equal("a=1, a=2, b=x", res.body, log.call)}
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ ary = res.body.lines.to_a
+ assert_match(%r{/$}, ary[0], log.call)
+ assert_match(%r{/webrick.cgi$}, ary[1], log.call)
+ }
+
+ req = Net::HTTP::Get.new("/webrick.cgi")
+ req["Cookie"] = "CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001"
+ http.request(req){|res|
+ assert_equal(
+ "CUSTOMER=WILE_E_COYOTE\nPART_NUMBER=ROCKET_LAUNCHER_0001\n",
+ res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/webrick.cgi")
+ cookie = %{$Version="1"; }
+ cookie << %{Customer="WILE_E_COYOTE"; $Path="/acme"; }
+ cookie << %{Part_Number="Rocket_Launcher_0001"; $Path="/acme"; }
+ cookie << %{Shipping="FedEx"; $Path="/acme"}
+ req["Cookie"] = cookie
+ http.request(req){|res|
+ assert_equal("Customer=WILE_E_COYOTE, Shipping=FedEx",
+ res["Set-Cookie"], log.call)
+ assert_equal("Customer=WILE_E_COYOTE\n" +
+ "Part_Number=Rocket_Launcher_0001\n" +
+ "Shipping=FedEx\n", res.body, log.call)
+ }
+ }
+ end
+
+ def test_bad_request
+ log_tester = lambda {|log, access_log|
+ assert_match(/BadRequest/, log.join)
+ }
+ start_cgi_server(log_tester) {|server, addr, port, log|
+ sock = TCPSocket.new(addr, port)
+ begin
+ sock << "POST /webrick.cgi HTTP/1.0" << CRLF
+ sock << "Content-Type: application/x-www-form-urlencoded" << CRLF
+ sock << "Content-Length: 1024" << CRLF
+ sock << CRLF
+ sock << "a=1&a=2&b=x"
+ sock.close_write
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, sock.read, log.call)
+ ensure
+ sock.close
+ end
+ }
+ end
+
+ def test_cgi_env
+ start_cgi_server do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/webrick.cgi/dumpenv")
+ req['proxy'] = 'http://example.com/'
+ req['hello'] = 'world'
+ http.request(req) do |res|
+ env = Marshal.load(res.body)
+ assert_equal 'world', env['HTTP_HELLO']
+ assert_not_operator env, :include?, 'HTTP_PROXY'
+ end
+ end
+ end
+
+ CtrlSeq = [0x7f, *(1..31)].pack("C*").gsub(/\s+/, '')
+ CtrlPat = /#{Regexp.quote(CtrlSeq)}/o
+ DumpPat = /#{Regexp.quote(CtrlSeq.dump[1...-1])}/o
+
+ def test_bad_uri
+ log_tester = lambda {|log, access_log|
+ assert_equal(1, log.length)
+ assert_match(/ERROR bad URI/, log[0])
+ }
+ start_cgi_server(log_tester) {|server, addr, port, log|
+ res = TCPSocket.open(addr, port) {|sock|
+ sock << "GET /#{CtrlSeq}#{CRLF}#{CRLF}"
+ sock.close_write
+ sock.read
+ }
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
+ s = log.call.each_line.grep(/ERROR bad URI/)[0]
+ assert_match(DumpPat, s)
+ assert_not_match(CtrlPat, s)
+ }
+ end
+
+ def test_bad_header
+ log_tester = lambda {|log, access_log|
+ assert_equal(1, log.length)
+ assert_match(/ERROR bad header/, log[0])
+ }
+ start_cgi_server(log_tester) {|server, addr, port, log|
+ res = TCPSocket.open(addr, port) {|sock|
+ sock << "GET / HTTP/1.0#{CRLF}#{CtrlSeq}#{CRLF}#{CRLF}"
+ sock.close_write
+ sock.read
+ }
+ assert_match(%r{\AHTTP/\d.\d 400 Bad Request}, res)
+ s = log.call.each_line.grep(/ERROR bad header/)[0]
+ assert_match(DumpPat, s)
+ assert_not_match(CtrlPat, s)
+ }
+ end
+end
diff --git a/test/webrick/test_config.rb b/tool/test/webrick/test_config.rb
index a54a667452..a54a667452 100644
--- a/test/webrick/test_config.rb
+++ b/tool/test/webrick/test_config.rb
diff --git a/test/webrick/test_cookie.rb b/tool/test/webrick/test_cookie.rb
index e46185f127..e46185f127 100644
--- a/test/webrick/test_cookie.rb
+++ b/tool/test/webrick/test_cookie.rb
diff --git a/test/webrick/test_do_not_reverse_lookup.rb b/tool/test/webrick/test_do_not_reverse_lookup.rb
index efcb5a9299..efcb5a9299 100644
--- a/test/webrick/test_do_not_reverse_lookup.rb
+++ b/tool/test/webrick/test_do_not_reverse_lookup.rb
diff --git a/tool/test/webrick/test_filehandler.rb b/tool/test/webrick/test_filehandler.rb
new file mode 100644
index 0000000000..998e03f690
--- /dev/null
+++ b/tool/test/webrick/test_filehandler.rb
@@ -0,0 +1,402 @@
+# frozen_string_literal: false
+require "test/unit"
+require_relative "utils.rb"
+require "webrick"
+require "stringio"
+require "tmpdir"
+
+class WEBrick::TestFileHandler < Test::Unit::TestCase
+ def teardown
+ WEBrick::Utils::TimeoutHandler.terminate
+ super
+ end
+
+ def default_file_handler(filename)
+ klass = WEBrick::HTTPServlet::DefaultFileHandler
+ klass.new(WEBrick::Config::HTTP, filename)
+ end
+
+ def windows?
+ File.directory?("\\")
+ end
+
+ def get_res_body(res)
+ sio = StringIO.new
+ sio.binmode
+ res.send_body(sio)
+ sio.string
+ end
+
+ def make_range_request(range_spec)
+ msg = <<-END_OF_REQUEST
+ GET / HTTP/1.0
+ Range: #{range_spec}
+
+ END_OF_REQUEST
+ return StringIO.new(msg.gsub(/^ {6}/, ""))
+ end
+
+ def make_range_response(file, range_spec)
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(make_range_request(range_spec))
+ res = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
+ size = File.size(file)
+ handler = default_file_handler(file)
+ handler.make_partial_content(req, res, file, size)
+ return res
+ end
+
+ def test_make_partial_content
+ filename = __FILE__
+ filesize = File.size(filename)
+
+ res = make_range_response(filename, "bytes=#{filesize-100}-")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(100, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=-100")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(100, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=0-99")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(100, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=100-199")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(100, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=0-0")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(1, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=-1")
+ assert_match(%r{^text/plain}, res["content-type"])
+ assert_equal(1, get_res_body(res).size)
+
+ res = make_range_response(filename, "bytes=0-0, -2")
+ assert_match(%r{^multipart/byteranges}, res["content-type"])
+ body = get_res_body(res)
+ boundary = /; boundary=(.+)/.match(res['content-type'])[1]
+ off = filesize - 2
+ last = filesize - 1
+
+ exp = "--#{boundary}\r\n" \
+ "Content-Type: text/plain\r\n" \
+ "Content-Range: bytes 0-0/#{filesize}\r\n" \
+ "\r\n" \
+ "#{IO.read(__FILE__, 1)}\r\n" \
+ "--#{boundary}\r\n" \
+ "Content-Type: text/plain\r\n" \
+ "Content-Range: bytes #{off}-#{last}/#{filesize}\r\n" \
+ "\r\n" \
+ "#{IO.read(__FILE__, 2, off)}\r\n" \
+ "--#{boundary}--\r\n"
+ assert_equal exp, body
+ end
+
+ def test_filehandler
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ this_file = File.basename(__FILE__)
+ filesize = File.size(__FILE__)
+ this_data = File.binread(__FILE__)
+ range = nil
+ bug2593 = '[ruby-dev:40030]'
+
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
+ begin
+ server[:DocumentRootOptions][:NondisclosureName] = []
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("200", res.code, log.call)
+ assert_equal("text/html", res.content_type, log.call)
+ assert_match(/HREF="#{this_file}"/, res.body, log.call)
+ }
+ req = Net::HTTP::Get.new("/#{this_file}")
+ http.request(req){|res|
+ assert_equal("200", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_equal(this_data, res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=#{filesize-100}-")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal((filesize-100)..(filesize-1), range, log.call)
+ assert_equal(this_data[-100..-1], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-100")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal((filesize-100)..(filesize-1), range, log.call)
+ assert_equal(this_data[-100..-1], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-99")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal(0..99, range, log.call)
+ assert_equal(this_data[0..99], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=100-199")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal(100..199, range, log.call)
+ assert_equal(this_data[100..199], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal(0..0, range, log.call)
+ assert_equal(this_data[0..0], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=-1")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("text/plain", res.content_type, log.call)
+ assert_nothing_raised(bug2593) {range = res.content_range}
+ assert_equal((filesize-1)..(filesize-1), range, log.call)
+ assert_equal(this_data[-1, 1], res.body, log.call)
+ }
+
+ req = Net::HTTP::Get.new("/#{this_file}", "range"=>"bytes=0-0, -2")
+ http.request(req){|res|
+ assert_equal("206", res.code, log.call)
+ assert_equal("multipart/byteranges", res.content_type, log.call)
+ }
+ ensure
+ server[:DocumentRootOptions].delete :NondisclosureName
+ end
+ end
+ end
+
+ def test_non_disclosure_name
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ log_tester = lambda {|log, access_log|
+ log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
+ log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s }
+ assert_equal([], log)
+ }
+ this_file = File.basename(__FILE__)
+ TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ doc_root_opts = server[:DocumentRootOptions]
+ doc_root_opts[:NondisclosureName] = %w(.ht* *~ test_*)
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("200", res.code, log.call)
+ assert_equal("text/html", res.content_type, log.call)
+ assert_no_match(/HREF="#{File.basename(__FILE__)}"/, res.body)
+ }
+ req = Net::HTTP::Get.new("/#{this_file}")
+ http.request(req){|res|
+ assert_equal("404", res.code, log.call)
+ }
+ doc_root_opts[:NondisclosureName] = %w(.ht* *~ TEST_*)
+ http.request(req){|res|
+ assert_equal("404", res.code, log.call)
+ }
+ end
+ end
+
+ def test_directory_traversal
+ return if File.executable?(__FILE__) # skip on strange file system
+
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ log_tester = lambda {|log, access_log|
+ log = log.reject {|s| /ERROR bad URI/ =~ s }
+ log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/../../")
+ http.request(req){|res| assert_equal("400", res.code, log.call) }
+ req = Net::HTTP::Get.new("/..%5c../#{File.basename(__FILE__)}")
+ http.request(req){|res| assert_equal(windows? ? "200" : "404", res.code, log.call) }
+ req = Net::HTTP::Get.new("/..%5c..%5cruby.c")
+ http.request(req){|res| assert_equal("404", res.code, log.call) }
+ end
+ end
+
+ def test_unwise_in_path
+ if windows?
+ config = { :DocumentRoot => File.dirname(__FILE__), }
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/..%5c..")
+ http.request(req){|res| assert_equal("301", res.code, log.call) }
+ end
+ end
+ end
+
+ def test_short_filename
+ return if File.executable?(__FILE__) # skip on strange file system
+
+ config = {
+ :CGIInterpreter => TestWEBrick::RubyBin,
+ :DocumentRoot => File.dirname(__FILE__),
+ :CGIPathEnv => ENV['PATH'],
+ }
+ log_tester = lambda {|log, access_log|
+ log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
+ log = log.reject {|s| /WARN the request refers nondisclosure name/ =~ s }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ if windows?
+ root = config[:DocumentRoot].tr("/", "\\")
+ fname = IO.popen(%W[dir /x #{root}\\webrick_long_filename.cgi], encoding: "binary", &:read)
+ fname.sub!(/\A.*$^$.*$^$/m, '')
+ if fname
+ fname = fname[/\s(w.+?cgi)\s/i, 1]
+ fname.downcase!
+ end
+ else
+ fname = "webric~1.cgi"
+ end
+ req = Net::HTTP::Get.new("/#{fname}/test")
+ http.request(req) do |res|
+ if windows?
+ assert_equal("200", res.code, log.call)
+ assert_equal("/test", res.body, log.call)
+ else
+ assert_equal("404", res.code, log.call)
+ end
+ end
+
+ req = Net::HTTP::Get.new("/.htaccess")
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
+ req = Net::HTTP::Get.new("/htacce~1")
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
+ req = Net::HTTP::Get.new("/HTACCE~1")
+ http.request(req) {|res| assert_equal("404", res.code, log.call) }
+ end
+ end
+
+ def test_multibyte_char_in_path
+ if Encoding.default_external == Encoding.find('US-ASCII')
+ reset_encoding = true
+ verb = $VERBOSE
+ $VERBOSE = false
+ Encoding.default_external = Encoding.find('UTF-8')
+ end
+
+ c = "\u00a7"
+ begin
+ c = c.encode('filesystem')
+ rescue EncodingError
+ c = c.b
+ end
+ Dir.mktmpdir(c) do |dir|
+ basename = "#{c}.txt"
+ File.write("#{dir}/#{basename}", "test_multibyte_char_in_path")
+ Dir.mkdir("#{dir}/#{c}")
+ File.write("#{dir}/#{c}/#{basename}", "nested")
+ config = {
+ :DocumentRoot => dir,
+ :DirectoryIndex => [basename],
+ }
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ path = "/#{basename}"
+ req = Net::HTTP::Get.new(WEBrick::HTTPUtils::escape(path))
+ http.request(req){|res| assert_equal("200", res.code, log.call + "\nFilesystem encoding is #{Encoding.find('filesystem')}") }
+ path = "/#{c}/#{basename}"
+ req = Net::HTTP::Get.new(WEBrick::HTTPUtils::escape(path))
+ http.request(req){|res| assert_equal("200", res.code, log.call) }
+ req = Net::HTTP::Get.new('/')
+ http.request(req){|res|
+ assert_equal("test_multibyte_char_in_path", res.body, log.call)
+ }
+ end
+ end
+ ensure
+ if reset_encoding
+ Encoding.default_external = Encoding.find('US-ASCII')
+ $VERBOSE = verb
+ end
+ end
+
+ def test_script_disclosure
+ return if File.executable?(__FILE__) # skip on strange file system
+
+ config = {
+ :CGIInterpreter => TestWEBrick::RubyBinArray,
+ :DocumentRoot => File.dirname(__FILE__),
+ :CGIPathEnv => ENV['PATH'],
+ :RequestCallback => Proc.new{|req, res|
+ def req.meta_vars
+ meta = super
+ meta["RUBYLIB"] = $:.join(File::PATH_SEPARATOR)
+ meta[RbConfig::CONFIG['LIBPATHENV']] = ENV[RbConfig::CONFIG['LIBPATHENV']] if RbConfig::CONFIG['LIBPATHENV']
+ return meta
+ end
+ },
+ }
+ log_tester = lambda {|log, access_log|
+ log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ http.read_timeout = EnvUtil.apply_timeout_scale(60)
+ http.write_timeout = EnvUtil.apply_timeout_scale(60) if http.respond_to?(:write_timeout=)
+
+ req = Net::HTTP::Get.new("/webrick.cgi/test")
+ http.request(req) do |res|
+ assert_equal("200", res.code, log.call)
+ assert_equal("/test", res.body, log.call)
+ end
+
+ resok = windows?
+ response_assertion = Proc.new do |res|
+ if resok
+ assert_equal("200", res.code, log.call)
+ assert_equal("/test", res.body, log.call)
+ else
+ assert_equal("404", res.code, log.call)
+ end
+ end
+ req = Net::HTTP::Get.new("/webrick.cgi%20/test")
+ http.request(req, &response_assertion)
+ req = Net::HTTP::Get.new("/webrick.cgi./test")
+ http.request(req, &response_assertion)
+ resok &&= File.exist?(__FILE__+"::$DATA")
+ req = Net::HTTP::Get.new("/webrick.cgi::$DATA/test")
+ http.request(req, &response_assertion)
+ end
+ end
+
+ def test_erbhandler
+ config = { :DocumentRoot => File.dirname(__FILE__) }
+ log_tester = lambda {|log, access_log|
+ log = log.reject {|s| /ERROR `.*\' not found\./ =~ s }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpserver(config, log_tester) do |server, addr, port, log|
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/webrick.rhtml")
+ http.request(req) do |res|
+ assert_equal("200", res.code, log.call)
+ assert_match %r!\Areq to http://[^/]+/webrick\.rhtml {}\n!, res.body
+ end
+ end
+ end
+end
diff --git a/test/webrick/test_htgroup.rb b/tool/test/webrick/test_htgroup.rb
index 8749711df5..8749711df5 100644
--- a/test/webrick/test_htgroup.rb
+++ b/tool/test/webrick/test_htgroup.rb
diff --git a/test/webrick/test_htmlutils.rb b/tool/test/webrick/test_htmlutils.rb
index ae1b8efa95..ae1b8efa95 100644
--- a/test/webrick/test_htmlutils.rb
+++ b/tool/test/webrick/test_htmlutils.rb
diff --git a/test/webrick/test_httpauth.rb b/tool/test/webrick/test_httpauth.rb
index 9fe8af8be2..9fe8af8be2 100644
--- a/test/webrick/test_httpauth.rb
+++ b/tool/test/webrick/test_httpauth.rb
diff --git a/tool/test/webrick/test_httpproxy.rb b/tool/test/webrick/test_httpproxy.rb
new file mode 100644
index 0000000000..1c2f2fce52
--- /dev/null
+++ b/tool/test/webrick/test_httpproxy.rb
@@ -0,0 +1,466 @@
+# frozen_string_literal: false
+require "test/unit"
+require "net/http"
+require "webrick"
+require "webrick/httpproxy"
+begin
+ require "webrick/ssl"
+ require "net/https"
+rescue LoadError
+ # test_connect will be skipped
+end
+require File.expand_path("utils.rb", File.dirname(__FILE__))
+
+class TestWEBrickHTTPProxy < Test::Unit::TestCase
+ def teardown
+ WEBrick::Utils::TimeoutHandler.terminate
+ super
+ end
+
+ def test_fake_proxy
+ assert_nil(WEBrick::FakeProxyURI.scheme)
+ assert_nil(WEBrick::FakeProxyURI.host)
+ assert_nil(WEBrick::FakeProxyURI.port)
+ assert_nil(WEBrick::FakeProxyURI.path)
+ assert_nil(WEBrick::FakeProxyURI.userinfo)
+ assert_raise(NoMethodError){ WEBrick::FakeProxyURI.foo }
+ end
+
+ def test_proxy
+ # Testing GET or POST to the proxy server
+ # Note that the proxy server works as the origin server.
+ # +------+
+ # V |
+ # client -------> proxy ---+
+ # GET / POST GET / POST
+ #
+ proxy_handler_called = request_handler_called = 0
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
+ server.mount_proc("/"){|req, res|
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
+ }
+ http = Net::HTTP.new(addr, port, addr, port)
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
+ assert_equal("GET / ", res.body, log.call)
+ }
+ assert_equal(1, proxy_handler_called, log.call)
+ assert_equal(2, request_handler_called, log.call)
+
+ req = Net::HTTP::Head.new("/")
+ http.request(req){|res|
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
+ assert_nil(res.body, log.call)
+ }
+ assert_equal(2, proxy_handler_called, log.call)
+ assert_equal(4, request_handler_called, log.call)
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ req.content_type = "application/x-www-form-urlencoded"
+ http.request(req){|res|
+ assert_equal("1.1 localhost.localdomain:#{port}", res["via"], log.call)
+ assert_equal("POST / post-data", res.body, log.call)
+ }
+ assert_equal(3, proxy_handler_called, log.call)
+ assert_equal(6, request_handler_called, log.call)
+ }
+ end
+
+ def test_no_proxy
+ # Testing GET or POST to the proxy server without proxy request.
+ #
+ # client -------> proxy
+ # GET / POST
+ #
+ proxy_handler_called = request_handler_called = 0
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
+ server.mount_proc("/"){|req, res|
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
+ }
+ http = Net::HTTP.new(addr, port)
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_nil(res["via"], log.call)
+ assert_equal("GET / ", res.body, log.call)
+ }
+ assert_equal(0, proxy_handler_called, log.call)
+ assert_equal(1, request_handler_called, log.call)
+
+ req = Net::HTTP::Head.new("/")
+ http.request(req){|res|
+ assert_nil(res["via"], log.call)
+ assert_nil(res.body, log.call)
+ }
+ assert_equal(0, proxy_handler_called, log.call)
+ assert_equal(2, request_handler_called, log.call)
+
+ req = Net::HTTP::Post.new("/")
+ req.content_type = "application/x-www-form-urlencoded"
+ req.body = "post-data"
+ http.request(req){|res|
+ assert_nil(res["via"], log.call)
+ assert_equal("POST / post-data", res.body, log.call)
+ }
+ assert_equal(0, proxy_handler_called, log.call)
+ assert_equal(3, request_handler_called, log.call)
+ }
+ end
+
+ def test_big_bodies
+ require 'digest/md5'
+ rand_str = File.read(__FILE__)
+ rand_str.freeze
+ nr = 1024 ** 2 / rand_str.size # bigger works, too
+ exp = Digest::MD5.new
+ nr.times { exp.update(rand_str) }
+ exp = exp.hexdigest
+ TestWEBrick.start_httpserver do |o_server, o_addr, o_port, o_log|
+ o_server.mount_proc('/') do |req, res|
+ case req.request_method
+ when 'GET'
+ res['content-type'] = 'application/octet-stream'
+ if req.path == '/length'
+ res['content-length'] = (nr * rand_str.size).to_s
+ else
+ res.chunked = true
+ end
+ res.body = ->(socket) { nr.times { socket.write(rand_str) } }
+ when 'POST'
+ dig = Digest::MD5.new
+ req.body { |buf| dig.update(buf); buf.clear }
+ res['content-type'] = 'text/plain'
+ res['content-length'] = '32'
+ res.body = dig.hexdigest
+ end
+ end
+
+ http = Net::HTTP.new(o_addr, o_port)
+ IO.pipe do |rd, wr|
+ headers = {
+ 'Content-Type' => 'application/octet-stream',
+ 'Transfer-Encoding' => 'chunked',
+ }
+ post = Net::HTTP::Post.new('/', headers)
+ th = Thread.new { nr.times { wr.write(rand_str) }; wr.close }
+ post.body_stream = rd
+ http.request(post) do |res|
+ assert_equal 'text/plain', res['content-type']
+ assert_equal 32, res.content_length
+ assert_equal exp, res.body
+ end
+ assert_nil th.value
+ end
+
+ TestWEBrick.start_httpproxy do |p_server, p_addr, p_port, p_log|
+ http = Net::HTTP.new(o_addr, o_port, p_addr, p_port)
+ http.request_get('/length') do |res|
+ assert_equal(nr * rand_str.size, res.content_length)
+ dig = Digest::MD5.new
+ res.read_body { |buf| dig.update(buf); buf.clear }
+ assert_equal exp, dig.hexdigest
+ end
+ http.request_get('/') do |res|
+ assert_predicate res, :chunked?
+ dig = Digest::MD5.new
+ res.read_body { |buf| dig.update(buf); buf.clear }
+ assert_equal exp, dig.hexdigest
+ end
+
+ IO.pipe do |rd, wr|
+ headers = {
+ 'Content-Type' => 'application/octet-stream',
+ 'Content-Length' => (nr * rand_str.size).to_s,
+ }
+ post = Net::HTTP::Post.new('/', headers)
+ th = Thread.new { nr.times { wr.write(rand_str) }; wr.close }
+ post.body_stream = rd
+ http.request(post) do |res|
+ assert_equal 'text/plain', res['content-type']
+ assert_equal 32, res.content_length
+ assert_equal exp, res.body
+ end
+ assert_nil th.value
+ end
+
+ IO.pipe do |rd, wr|
+ headers = {
+ 'Content-Type' => 'application/octet-stream',
+ 'Transfer-Encoding' => 'chunked',
+ }
+ post = Net::HTTP::Post.new('/', headers)
+ th = Thread.new { nr.times { wr.write(rand_str) }; wr.close }
+ post.body_stream = rd
+ http.request(post) do |res|
+ assert_equal 'text/plain', res['content-type']
+ assert_equal 32, res.content_length
+ assert_equal exp, res.body
+ end
+ assert_nil th.value
+ end
+ end
+ end
+ end if RUBY_VERSION >= '2.5'
+
+ def test_http10_proxy_chunked
+ # Testing HTTP/1.0 client request and HTTP/1.1 chunked response
+ # from origin server.
+ # +------+
+ # V |
+ # client -------> proxy ---+
+ # GET GET
+ # HTTP/1.0 HTTP/1.1
+ # non-chunked chunked
+ #
+ proxy_handler_called = request_handler_called = 0
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1 },
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1 }
+ }
+ log_tester = lambda {|log, access_log|
+ log.reject! {|str|
+ %r{WARN chunked is set for an HTTP/1\.0 request\. \(ignored\)} =~ str
+ }
+ assert_equal([], log)
+ }
+ TestWEBrick.start_httpproxy(config, log_tester){|server, addr, port, log|
+ body = nil
+ server.mount_proc("/"){|req, res|
+ body = "#{req.request_method} #{req.path} #{req.body}"
+ res.chunked = true
+ res.body = -> (socket) { body.each_char {|c| socket.write c } }
+ }
+
+ # Don't use Net::HTTP because it uses HTTP/1.1.
+ TCPSocket.open(addr, port) {|s|
+ s.write "GET / HTTP/1.0\r\nHost: localhost.localdomain\r\n\r\n"
+ response = s.read
+ assert_equal(body, response[/.*\z/])
+ }
+ }
+ end
+
+ def make_certificate(key, cn)
+ subject = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=#{cn}")
+ exts = [
+ ["keyUsage", "keyEncipherment,digitalSignature", true],
+ ]
+ cert = OpenSSL::X509::Certificate.new
+ cert.version = 2
+ cert.serial = 1
+ cert.subject = subject
+ cert.issuer = subject
+ cert.public_key = key
+ cert.not_before = Time.now - 3600
+ cert.not_after = Time.now + 3600
+ ef = OpenSSL::X509::ExtensionFactory.new(cert, cert)
+ exts.each {|args| cert.add_extension(ef.create_extension(*args)) }
+ cert.sign(key, "sha256")
+ return cert
+ end if defined?(OpenSSL::SSL)
+
+ def test_connect
+ # Testing CONNECT to proxy server
+ #
+ # client -----------> proxy -----------> https
+ # 1. CONNECT establish TCP
+ # 2. ---- establish SSL session --->
+ # 3. ------- GET or POST ---------->
+ #
+ key = TEST_KEY_RSA2048
+ cert = make_certificate(key, "127.0.0.1")
+ s_config = {
+ :SSLEnable =>true,
+ :ServerName => "localhost",
+ :SSLCertificate => cert,
+ :SSLPrivateKey => key,
+ }
+ config = {
+ :ServerName => "localhost.localdomain",
+ :RequestCallback => Proc.new{|req, res|
+ assert_equal("CONNECT", req.request_method)
+ },
+ }
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
+ s_server.mount_proc("/"){|req, res|
+ res.body = "SSL #{req.request_method} #{req.path} #{req.body}"
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
+ http = Net::HTTP.new("127.0.0.1", s_port, addr, port)
+ http.use_ssl = true
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
+ store_ctx.current_cert.to_der == cert.to_der
+ end
+
+ req = Net::HTTP::Get.new("/")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ http.request(req){|res|
+ assert_equal("SSL GET / ", res.body, s_log.call + log.call)
+ }
+
+ req = Net::HTTP::Post.new("/")
+ req["Content-Type"] = "application/x-www-form-urlencoded"
+ req.body = "post-data"
+ http.request(req){|res|
+ assert_equal("SSL POST / post-data", res.body, s_log.call + log.call)
+ }
+ }
+ }
+ end if defined?(OpenSSL::SSL)
+
+ def test_upstream_proxy
+ # Testing GET or POST through the upstream proxy server
+ # Note that the upstream proxy server works as the origin server.
+ # +------+
+ # V |
+ # client -------> proxy -------> proxy ---+
+ # GET / POST GET / POST GET / POST
+ #
+ up_proxy_handler_called = up_request_handler_called = 0
+ proxy_handler_called = request_handler_called = 0
+ up_config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyContentHandler => Proc.new{|req, res| up_proxy_handler_called += 1},
+ :RequestCallback => Proc.new{|req, res| up_request_handler_called += 1}
+ }
+ TestWEBrick.start_httpproxy(up_config){|up_server, up_addr, up_port, up_log|
+ up_server.mount_proc("/"){|req, res|
+ res.body = "#{req.request_method} #{req.path} #{req.body}"
+ }
+ config = {
+ :ServerName => "localhost.localdomain",
+ :ProxyURI => URI.parse("http://localhost:#{up_port}"),
+ :ProxyContentHandler => Proc.new{|req, res| proxy_handler_called += 1},
+ :RequestCallback => Proc.new{|req, res| request_handler_called += 1},
+ }
+ TestWEBrick.start_httpproxy(config){|server, addr, port, log|
+ http = Net::HTTP.new(up_addr, up_port, addr, port)
+
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ skip res.message unless res.code == '200'
+ via = res["via"].split(/,\s+/)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
+ assert_equal("GET / ", res.body)
+ }
+ assert_equal(1, up_proxy_handler_called, up_log.call + log.call)
+ assert_equal(2, up_request_handler_called, up_log.call + log.call)
+ assert_equal(1, proxy_handler_called, up_log.call + log.call)
+ assert_equal(1, request_handler_called, up_log.call + log.call)
+
+ req = Net::HTTP::Head.new("/")
+ http.request(req){|res|
+ via = res["via"].split(/,\s+/)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
+ assert_nil(res.body, up_log.call + log.call)
+ }
+ assert_equal(2, up_proxy_handler_called, up_log.call + log.call)
+ assert_equal(4, up_request_handler_called, up_log.call + log.call)
+ assert_equal(2, proxy_handler_called, up_log.call + log.call)
+ assert_equal(2, request_handler_called, up_log.call + log.call)
+
+ req = Net::HTTP::Post.new("/")
+ req.body = "post-data"
+ req.content_type = "application/x-www-form-urlencoded"
+ http.request(req){|res|
+ via = res["via"].split(/,\s+/)
+ assert(via.include?("1.1 localhost.localdomain:#{up_port}"), up_log.call + log.call)
+ assert(via.include?("1.1 localhost.localdomain:#{port}"), up_log.call + log.call)
+ assert_equal("POST / post-data", res.body, up_log.call + log.call)
+ }
+ assert_equal(3, up_proxy_handler_called, up_log.call + log.call)
+ assert_equal(6, up_request_handler_called, up_log.call + log.call)
+ assert_equal(3, proxy_handler_called, up_log.call + log.call)
+ assert_equal(3, request_handler_called, up_log.call + log.call)
+
+ if defined?(OpenSSL::SSL)
+ # Testing CONNECT to the upstream proxy server
+ #
+ # client -------> proxy -------> proxy -------> https
+ # 1. CONNECT CONNECT establish TCP
+ # 2. -------- establish SSL session ------>
+ # 3. ---------- GET or POST -------------->
+ #
+ key = TEST_KEY_RSA2048
+ cert = make_certificate(key, "127.0.0.1")
+ s_config = {
+ :SSLEnable =>true,
+ :ServerName => "localhost",
+ :SSLCertificate => cert,
+ :SSLPrivateKey => key,
+ }
+ TestWEBrick.start_httpserver(s_config){|s_server, s_addr, s_port, s_log|
+ s_server.mount_proc("/"){|req2, res|
+ res.body = "SSL #{req2.request_method} #{req2.path} #{req2.body}"
+ }
+ http = Net::HTTP.new("127.0.0.1", s_port, addr, port, up_log.call + log.call + s_log.call)
+ http.use_ssl = true
+ http.verify_callback = Proc.new do |preverify_ok, store_ctx|
+ store_ctx.current_cert.to_der == cert.to_der
+ end
+
+ req2 = Net::HTTP::Get.new("/")
+ http.request(req2){|res|
+ assert_equal("SSL GET / ", res.body, up_log.call + log.call + s_log.call)
+ }
+
+ req2 = Net::HTTP::Post.new("/")
+ req2.body = "post-data"
+ req2.content_type = "application/x-www-form-urlencoded"
+ http.request(req2){|res|
+ assert_equal("SSL POST / post-data", res.body, up_log.call + log.call + s_log.call)
+ }
+ }
+ end
+ }
+ }
+ end
+
+ if defined?(OpenSSL::SSL)
+ TEST_KEY_RSA2048 = OpenSSL::PKey.read <<-_end_of_pem_
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAuV9ht9J7k4NBs38jOXvvTKY9gW8nLICSno5EETR1cuF7i4pN
+s9I1QJGAFAX0BEO4KbzXmuOvfCpD3CU+Slp1enenfzq/t/e/1IRW0wkJUJUFQign
+4CtrkJL+P07yx18UjyPlBXb81ApEmAB5mrJVSrWmqbjs07JbuS4QQGGXLc+Su96D
+kYKmSNVjBiLxVVSpyZfAY3hD37d60uG+X8xdW5v68JkRFIhdGlb6JL8fllf/A/bl
+NwdJOhVr9mESHhwGjwfSeTDPfd8ZLE027E5lyAVX9KZYcU00mOX+fdxOSnGqS/8J
+DRh0EPHDL15RcJjV2J6vZjPb0rOYGDoMcH+94wIDAQABAoIBAAzsamqfYQAqwXTb
+I0CJtGg6msUgU7HVkOM+9d3hM2L791oGHV6xBAdpXW2H8LgvZHJ8eOeSghR8+dgq
+PIqAffo4x1Oma+FOg3A0fb0evyiACyrOk+EcBdbBeLo/LcvahBtqnDfiUMQTpy6V
+seSoFCwuN91TSCeGIsDpRjbG1vxZgtx+uI+oH5+ytqJOmfCksRDCkMglGkzyfcl0
+Xc5CUhIJ0my53xijEUQl19rtWdMnNnnkdbG8PT3LZlOta5Do86BElzUYka0C6dUc
+VsBDQ0Nup0P6rEQgy7tephHoRlUGTYamsajGJaAo1F3IQVIrRSuagi7+YpSpCqsW
+wORqorkCgYEA7RdX6MDVrbw7LePnhyuaqTiMK+055/R1TqhB1JvvxJ1CXk2rDL6G
+0TLHQ7oGofd5LYiemg4ZVtWdJe43BPZlVgT6lvL/iGo8JnrncB9Da6L7nrq/+Rvj
+XGjf1qODCK+LmreZWEsaLPURIoR/Ewwxb9J2zd0CaMjeTwafJo1CZvcCgYEAyCgb
+aqoWvUecX8VvARfuA593Lsi50t4MEArnOXXcd1RnXoZWhbx5rgO8/ATKfXr0BK/n
+h2GF9PfKzHFm/4V6e82OL7gu/kLy2u9bXN74vOvWFL5NOrOKPM7Kg+9I131kNYOw
+Ivnr/VtHE5s0dY7JChYWE1F3vArrOw3T00a4CXUCgYEA0SqY+dS2LvIzW4cHCe9k
+IQqsT0yYm5TFsUEr4sA3xcPfe4cV8sZb9k/QEGYb1+SWWZ+AHPV3UW5fl8kTbSNb
+v4ng8i8rVVQ0ANbJO9e5CUrepein2MPL0AkOATR8M7t7dGGpvYV0cFk8ZrFx0oId
+U0PgYDotF/iueBWlbsOM430CgYEAqYI95dFyPI5/AiSkY5queeb8+mQH62sdcCCr
+vd/w/CZA/K5sbAo4SoTj8dLk4evU6HtIa0DOP63y071eaxvRpTNqLUOgmLh+D6gS
+Cc7TfLuFrD+WDBatBd5jZ+SoHccVrLR/4L8jeodo5FPW05A+9gnKXEXsTxY4LOUC
+9bS4e1kCgYAqVXZh63JsMwoaxCYmQ66eJojKa47VNrOeIZDZvd2BPVf30glBOT41
+gBoDG3WMPZoQj9pb7uMcrnvs4APj2FIhMU8U15LcPAj59cD6S6rWnAxO8NFK7HQG
+4Jxg3JNNf8ErQoCHb1B3oVdXJkmbJkARoDpBKmTCgKtP8ADYLmVPQw==
+-----END RSA PRIVATE KEY-----
+ _end_of_pem_
+ end
+end
diff --git a/tool/test/webrick/test_httprequest.rb b/tool/test/webrick/test_httprequest.rb
new file mode 100644
index 0000000000..759ccbdada
--- /dev/null
+++ b/tool/test/webrick/test_httprequest.rb
@@ -0,0 +1,488 @@
+# frozen_string_literal: false
+require "webrick"
+require "stringio"
+require "test/unit"
+
+class TestWEBrickHTTPRequest < Test::Unit::TestCase
+ def teardown
+ WEBrick::Utils::TimeoutHandler.terminate
+ super
+ end
+
+ def test_simple_request
+ msg = <<-_end_of_message_
+GET /
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert(req.meta_vars) # fails if @header was not initialized and iteration is attempted on the nil reference
+ end
+
+ def test_parse_09
+ msg = <<-_end_of_message_
+ GET /
+ foobar # HTTP/0.9 request don't have header nor entity body.
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("GET", req.request_method)
+ assert_equal("/", req.unparsed_uri)
+ assert_equal(WEBrick::HTTPVersion.new("0.9"), req.http_version)
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
+ assert_equal(80, req.port)
+ assert_equal(false, req.keep_alive?)
+ assert_equal(nil, req.body)
+ assert(req.query.empty?)
+ end
+
+ def test_parse_10
+ msg = <<-_end_of_message_
+ GET / HTTP/1.0
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("GET", req.request_method)
+ assert_equal("/", req.unparsed_uri)
+ assert_equal(WEBrick::HTTPVersion.new("1.0"), req.http_version)
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
+ assert_equal(80, req.port)
+ assert_equal(false, req.keep_alive?)
+ assert_equal(nil, req.body)
+ assert(req.query.empty?)
+ end
+
+ def test_parse_11
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("GET", req.request_method)
+ assert_equal("/path", req.unparsed_uri)
+ assert_equal("", req.script_name)
+ assert_equal("/path", req.path_info)
+ assert_equal(WEBrick::HTTPVersion.new("1.1"), req.http_version)
+ assert_equal(WEBrick::Config::HTTP[:ServerName], req.host)
+ assert_equal(80, req.port)
+ assert_equal(true, req.keep_alive?)
+ assert_equal(nil, req.body)
+ assert(req.query.empty?)
+ end
+
+ def test_request_uri_too_large
+ msg = <<-_end_of_message_
+ GET /#{"a"*2084} HTTP/1.1
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ assert_raise(WEBrick::HTTPStatus::RequestURITooLarge){
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ }
+ end
+
+ def test_parse_headers
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Connection: close
+ Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1,
+ text/html;level=2;q=0.4, */*;q=0.5
+ Accept-Encoding: compress;q=0.5
+ Accept-Encoding: gzip;q=1.0, identity; q=0.4, *;q=0
+ Accept-Language: en;q=0.5, *; q=0
+ Accept-Language: ja
+ Content-Type: text/plain
+ Content-Length: 7
+ X-Empty-Header:
+
+ foobar
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(
+ URI.parse("http://test.ruby-lang.org:8080/path"), req.request_uri)
+ assert_equal("test.ruby-lang.org", req.host)
+ assert_equal(8080, req.port)
+ assert_equal(false, req.keep_alive?)
+ assert_equal(
+ %w(text/html;level=1 text/html */* text/html;level=2 text/*),
+ req.accept)
+ assert_equal(%w(gzip compress identity *), req.accept_encoding)
+ assert_equal(%w(ja en *), req.accept_language)
+ assert_equal(7, req.content_length)
+ assert_equal("text/plain", req.content_type)
+ assert_equal("foobar\n", req.body)
+ assert_equal("", req["x-empty-header"])
+ assert_equal(nil, req["x-no-header"])
+ assert(req.query.empty?)
+ end
+
+ def test_parse_header2()
+ msg = <<-_end_of_message_
+ POST /foo/bar/../baz?q=a HTTP/1.0
+ Content-Length: 9
+ User-Agent:
+ FOO BAR
+ BAZ
+
+ hogehoge
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal("POST", req.request_method)
+ assert_equal("/foo/baz", req.path)
+ assert_equal("", req.script_name)
+ assert_equal("/foo/baz", req.path_info)
+ assert_equal("9", req['content-length'])
+ assert_equal("FOO BAR BAZ", req['user-agent'])
+ assert_equal("hogehoge\n", req.body)
+ end
+
+ def test_parse_headers3
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: test.ruby-lang.org
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://test.ruby-lang.org/path"), req.request_uri)
+ assert_equal("test.ruby-lang.org", req.host)
+ assert_equal(80, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: 192.168.1.1
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://192.168.1.1/path"), req.request_uri)
+ assert_equal("192.168.1.1", req.host)
+ assert_equal(80, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: [fe80::208:dff:feef:98c7]
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]/path"),
+ req.request_uri)
+ assert_equal("[fe80::208:dff:feef:98c7]", req.host)
+ assert_equal(80, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: 192.168.1.1:8080
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://192.168.1.1:8080/path"), req.request_uri)
+ assert_equal("192.168.1.1", req.host)
+ assert_equal(8080, req.port)
+
+ msg = <<-_end_of_message_
+ GET /path HTTP/1.1
+ Host: [fe80::208:dff:feef:98c7]:8080
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ assert_equal(URI.parse("http://[fe80::208:dff:feef:98c7]:8080/path"),
+ req.request_uri)
+ assert_equal("[fe80::208:dff:feef:98c7]", req.host)
+ assert_equal(8080, req.port)
+ end
+
+ def test_parse_get_params
+ param = "foo=1;foo=2;foo=3;bar=x"
+ msg = <<-_end_of_message_
+ GET /path?#{param} HTTP/1.1
+ Host: test.ruby-lang.org:8080
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ query = req.query
+ assert_equal("1", query["foo"])
+ assert_equal(["1", "2", "3"], query["foo"].to_ary)
+ assert_equal(["1", "2", "3"], query["foo"].list)
+ assert_equal("x", query["bar"])
+ assert_equal(["x"], query["bar"].list)
+ end
+
+ def test_parse_post_params
+ param = "foo=1;foo=2;foo=3;bar=x"
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Length: #{param.size}
+ Content-Type: application/x-www-form-urlencoded
+
+ #{param}
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ query = req.query
+ assert_equal("1", query["foo"])
+ assert_equal(["1", "2", "3"], query["foo"].to_ary)
+ assert_equal(["1", "2", "3"], query["foo"].list)
+ assert_equal("x", query["bar"])
+ assert_equal(["x"], query["bar"].list)
+ end
+
+ def test_chunked
+ crlf = "\x0d\x0a"
+ expect = File.binread(__FILE__).freeze
+ msg = <<-_end_of_message_
+ POST /path HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Transfer-Encoding: chunked
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ open(__FILE__){|io|
+ while chunk = io.read(100)
+ msg << chunk.size.to_s(16) << crlf
+ msg << chunk << crlf
+ end
+ }
+ msg << "0" << crlf
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal(expect, req.body)
+
+ # chunked req.body_reader
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ dst = StringIO.new
+ IO.copy_stream(req.body_reader, dst)
+ assert_equal(expect, dst.string)
+ end
+
+ def test_forwarded
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ User-Agent: w3m/0.5.2
+ X-Forwarded-For: 123.123.123.123
+ X-Forwarded-Host: forward.example.com
+ X-Forwarded-Server: server.example.com
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server.example.com", req.server_name)
+ assert_equal("http://forward.example.com/foo", req.request_uri.to_s)
+ assert_equal("forward.example.com", req.host)
+ assert_equal(80, req.port)
+ assert_equal("123.123.123.123", req.remote_ip)
+ assert(!req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ User-Agent: w3m/0.5.2
+ X-Forwarded-For: 192.168.1.10, 172.16.1.1, 123.123.123.123
+ X-Forwarded-Host: forward.example.com:8080
+ X-Forwarded-Server: server.example.com
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server.example.com", req.server_name)
+ assert_equal("http://forward.example.com:8080/foo", req.request_uri.to_s)
+ assert_equal("forward.example.com", req.host)
+ assert_equal(8080, req.port)
+ assert_equal("123.123.123.123", req.remote_ip)
+ assert(!req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ Client-IP: 234.234.234.234
+ X-Forwarded-Proto: https, http
+ X-Forwarded-For: 192.168.1.10, 10.0.0.1, 123.123.123.123
+ X-Forwarded-Host: forward.example.com
+ X-Forwarded-Server: server.example.com
+ X-Requested-With: XMLHttpRequest
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server.example.com", req.server_name)
+ assert_equal("https://forward.example.com/foo", req.request_uri.to_s)
+ assert_equal("forward.example.com", req.host)
+ assert_equal(443, req.port)
+ assert_equal("234.234.234.234", req.remote_ip)
+ assert(req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ Client-IP: 234.234.234.234
+ X-Forwarded-Proto: https
+ X-Forwarded-For: 192.168.1.10
+ X-Forwarded-Host: forward1.example.com:1234, forward2.example.com:5678
+ X-Forwarded-Server: server1.example.com, server2.example.com
+ X-Requested-With: XMLHttpRequest
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server1.example.com", req.server_name)
+ assert_equal("https://forward1.example.com:1234/foo", req.request_uri.to_s)
+ assert_equal("forward1.example.com", req.host)
+ assert_equal(1234, req.port)
+ assert_equal("234.234.234.234", req.remote_ip)
+ assert(req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ Client-IP: 234.234.234.234
+ X-Forwarded-Proto: https
+ X-Forwarded-For: 192.168.1.10
+ X-Forwarded-Host: [fd20:8b1e:b255:8154:250:56ff:fea8:4d84], forward2.example.com:5678
+ X-Forwarded-Server: server1.example.com, server2.example.com
+ X-Requested-With: XMLHttpRequest
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server1.example.com", req.server_name)
+ assert_equal("https://[fd20:8b1e:b255:8154:250:56ff:fea8:4d84]/foo", req.request_uri.to_s)
+ assert_equal("[fd20:8b1e:b255:8154:250:56ff:fea8:4d84]", req.host)
+ assert_equal(443, req.port)
+ assert_equal("234.234.234.234", req.remote_ip)
+ assert(req.ssl?)
+
+ msg = <<-_end_of_message_
+ GET /foo HTTP/1.1
+ Host: localhost:10080
+ Client-IP: 234.234.234.234
+ X-Forwarded-Proto: https
+ X-Forwarded-For: 192.168.1.10
+ X-Forwarded-Host: [fd20:8b1e:b255:8154:250:56ff:fea8:4d84]:1234, forward2.example.com:5678
+ X-Forwarded-Server: server1.example.com, server2.example.com
+ X-Requested-With: XMLHttpRequest
+ Connection: Keep-Alive
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert_equal("server1.example.com", req.server_name)
+ assert_equal("https://[fd20:8b1e:b255:8154:250:56ff:fea8:4d84]:1234/foo", req.request_uri.to_s)
+ assert_equal("[fd20:8b1e:b255:8154:250:56ff:fea8:4d84]", req.host)
+ assert_equal(1234, req.port)
+ assert_equal("234.234.234.234", req.remote_ip)
+ assert(req.ssl?)
+ end
+
+ def test_continue_sent
+ msg = <<-_end_of_message_
+ POST /path HTTP/1.1
+ Expect: 100-continue
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert req['expect']
+ l = msg.size
+ req.continue
+ assert_not_equal l, msg.size
+ assert_match(/HTTP\/1.1 100 continue\r\n\r\n\z/, msg)
+ assert !req['expect']
+ end
+
+ def test_continue_not_sent
+ msg = <<-_end_of_message_
+ POST /path HTTP/1.1
+
+ _end_of_message_
+ msg.gsub!(/^ {6}/, "")
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg))
+ assert !req['expect']
+ l = msg.size
+ req.continue
+ assert_equal l, msg.size
+ end
+
+ def test_empty_post
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Type: application/x-www-form-urlencoded
+
+ _end_of_message_
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ end
+
+ def test_bad_messages
+ param = "foo=1;foo=2;foo=3;bar=x"
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Type: application/x-www-form-urlencoded
+
+ #{param}
+ _end_of_message_
+ assert_raise(WEBrick::HTTPStatus::LengthRequired){
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ }
+
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Content-Length: 100000
+
+ body is too short.
+ _end_of_message_
+ assert_raise(WEBrick::HTTPStatus::BadRequest){
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ }
+
+ msg = <<-_end_of_message_
+ POST /path?foo=x;foo=y;foo=z;bar=1 HTTP/1.1
+ Host: test.ruby-lang.org:8080
+ Transfer-Encoding: foobar
+
+ body is too short.
+ _end_of_message_
+ assert_raise(WEBrick::HTTPStatus::NotImplemented){
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(msg.gsub(/^ {6}/, "")))
+ req.body
+ }
+ end
+
+ def test_eof_raised_when_line_is_nil
+ assert_raise(WEBrick::HTTPStatus::EOFError) {
+ req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
+ req.parse(StringIO.new(""))
+ }
+ end
+end
diff --git a/tool/test/webrick/test_httpresponse.rb b/tool/test/webrick/test_httpresponse.rb
new file mode 100644
index 0000000000..89a0f7036e
--- /dev/null
+++ b/tool/test/webrick/test_httpresponse.rb
@@ -0,0 +1,282 @@
+# frozen_string_literal: false
+require "webrick"
+require "minitest/autorun"
+require "stringio"
+require "net/http"
+
+module WEBrick
+ class TestHTTPResponse < MiniTest::Unit::TestCase
+ class FakeLogger
+ attr_reader :messages
+
+ def initialize
+ @messages = []
+ end
+
+ def warn msg
+ @messages << msg
+ end
+ end
+
+ attr_reader :config, :logger, :res
+
+ def setup
+ super
+ @logger = FakeLogger.new
+ @config = Config::HTTP
+ @config[:Logger] = logger
+ @res = HTTPResponse.new config
+ @res.keep_alive = true
+ end
+
+ def test_prevent_response_splitting_headers_crlf
+ res['X-header'] = "malicious\r\nCookie: cracked_indicator_for_test"
+ io = StringIO.new
+ res.send_response io
+ io.rewind
+ res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
+ assert_equal '500', res.code
+ refute_match 'cracked_indicator_for_test', io.string
+ end
+
+ def test_prevent_response_splitting_cookie_headers_crlf
+ user_input = "malicious\r\nCookie: cracked_indicator_for_test"
+ res.cookies << WEBrick::Cookie.new('author', user_input)
+ io = StringIO.new
+ res.send_response io
+ io.rewind
+ res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
+ assert_equal '500', res.code
+ refute_match 'cracked_indicator_for_test', io.string
+ end
+
+ def test_prevent_response_splitting_headers_cr
+ res['X-header'] = "malicious\rCookie: cracked_indicator_for_test"
+ io = StringIO.new
+ res.send_response io
+ io.rewind
+ res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
+ assert_equal '500', res.code
+ refute_match 'cracked_indicator_for_test', io.string
+ end
+
+ def test_prevent_response_splitting_cookie_headers_cr
+ user_input = "malicious\rCookie: cracked_indicator_for_test"
+ res.cookies << WEBrick::Cookie.new('author', user_input)
+ io = StringIO.new
+ res.send_response io
+ io.rewind
+ res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
+ assert_equal '500', res.code
+ refute_match 'cracked_indicator_for_test', io.string
+ end
+
+ def test_prevent_response_splitting_headers_lf
+ res['X-header'] = "malicious\nCookie: cracked_indicator_for_test"
+ io = StringIO.new
+ res.send_response io
+ io.rewind
+ res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
+ assert_equal '500', res.code
+ refute_match 'cracked_indicator_for_test', io.string
+ end
+
+ def test_prevent_response_splitting_cookie_headers_lf
+ user_input = "malicious\nCookie: cracked_indicator_for_test"
+ res.cookies << WEBrick::Cookie.new('author', user_input)
+ io = StringIO.new
+ res.send_response io
+ io.rewind
+ res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
+ assert_equal '500', res.code
+ refute_match 'cracked_indicator_for_test', io.string
+ end
+
+ def test_set_redirect_response_splitting
+ url = "malicious\r\nCookie: cracked_indicator_for_test"
+ assert_raises(URI::InvalidURIError) do
+ res.set_redirect(WEBrick::HTTPStatus::MultipleChoices, url)
+ end
+ end
+
+ def test_set_redirect_html_injection
+ url = 'http://example.com////?a</a><head></head><body><img src=1></body>'
+ assert_raises(WEBrick::HTTPStatus::MultipleChoices) do
+ res.set_redirect(WEBrick::HTTPStatus::MultipleChoices, url)
+ end
+ res.status = 300
+ io = StringIO.new
+ res.send_response(io)
+ io.rewind
+ res = Net::HTTPResponse.read_new(Net::BufferedIO.new(io))
+ assert_equal '300', res.code
+ refute_match(/<img/, io.string)
+ end
+
+ def test_304_does_not_log_warning
+ res.status = 304
+ res.setup_header
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_204_does_not_log_warning
+ res.status = 204
+ res.setup_header
+
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_1xx_does_not_log_warnings
+ res.status = 105
+ res.setup_header
+
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_200_chunked_does_not_set_content_length
+ res.chunked = false
+ res["Transfer-Encoding"] = 'chunked'
+ res.setup_header
+ assert_nil res.header.fetch('content-length', nil)
+ end
+
+ def test_send_body_io
+ IO.pipe {|body_r, body_w|
+ body_w.write 'hello'
+ body_w.close
+
+ @res.body = body_r
+
+ IO.pipe {|r, w|
+
+ @res.send_body w
+
+ w.close
+
+ assert_equal 'hello', r.read
+ }
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_string
+ @res.body = 'hello'
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ assert_equal 'hello', r.read
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_string_io
+ @res.body = StringIO.new 'hello'
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ assert_equal 'hello', r.read
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_io_chunked
+ @res.chunked = true
+
+ IO.pipe {|body_r, body_w|
+
+ body_w.write 'hello'
+ body_w.close
+
+ @res.body = body_r
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ r.binmode
+ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
+ }
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_string_chunked
+ @res.chunked = true
+
+ @res.body = 'hello'
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ r.binmode
+ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_string_io_chunked
+ @res.chunked = true
+
+ @res.body = StringIO.new 'hello'
+
+ IO.pipe {|r, w|
+ @res.send_body w
+
+ w.close
+
+ r.binmode
+ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
+ }
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_proc
+ @res.body = Proc.new { |out| out.write('hello') }
+ IO.pipe do |r, w|
+ @res.send_body(w)
+ w.close
+ r.binmode
+ assert_equal 'hello', r.read
+ end
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_send_body_proc_chunked
+ @res.body = Proc.new { |out| out.write('hello') }
+ @res.chunked = true
+ IO.pipe do |r, w|
+ @res.send_body(w)
+ w.close
+ r.binmode
+ assert_equal "5\r\nhello\r\n0\r\n\r\n", r.read
+ end
+ assert_equal 0, logger.messages.length
+ end
+
+ def test_set_error
+ status = 400
+ message = 'missing attribute'
+ @res.status = status
+ error = WEBrick::HTTPStatus[status].new(message)
+ body = @res.set_error(error)
+ assert_match(/#{@res.reason_phrase}/, body)
+ assert_match(/#{message}/, body)
+ end
+
+ def test_no_extraneous_space
+ [200, 300, 400, 500].each do |status|
+ @res.status = status
+ assert_match(/\S\r\n/, @res.status_line)
+ end
+ end
+ end
+end
diff --git a/test/webrick/test_https.rb b/tool/test/webrick/test_https.rb
index ec0aac354a..ec0aac354a 100644
--- a/test/webrick/test_https.rb
+++ b/tool/test/webrick/test_https.rb
diff --git a/tool/test/webrick/test_httpserver.rb b/tool/test/webrick/test_httpserver.rb
new file mode 100644
index 0000000000..4133be85ad
--- /dev/null
+++ b/tool/test/webrick/test_httpserver.rb
@@ -0,0 +1,543 @@
+# frozen_string_literal: false
+require "test/unit"
+require "net/http"
+require "webrick"
+require_relative "utils"
+
+class TestWEBrickHTTPServer < Test::Unit::TestCase
+ empty_log = Object.new
+ def empty_log.<<(str)
+ assert_equal('', str)
+ self
+ end
+ NoLog = WEBrick::Log.new(empty_log, WEBrick::BasicLog::WARN)
+
+ def teardown
+ WEBrick::Utils::TimeoutHandler.terminate
+ super
+ end
+
+ def test_mount
+ httpd = WEBrick::HTTPServer.new(
+ :Logger => NoLog,
+ :DoNotListen=>true
+ )
+ httpd.mount("/", :Root)
+ httpd.mount("/foo", :Foo)
+ httpd.mount("/foo/bar", :Bar, :bar1)
+ httpd.mount("/foo/bar/baz", :Baz, :baz1, :baz2)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/")
+ assert_equal(:Root, serv)
+ assert_equal([], opts)
+ assert_equal("", script_name)
+ assert_equal("/", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/sub")
+ assert_equal(:Root, serv)
+ assert_equal([], opts)
+ assert_equal("", script_name)
+ assert_equal("/sub", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/sub/")
+ assert_equal(:Root, serv)
+ assert_equal([], opts)
+ assert_equal("", script_name)
+ assert_equal("/sub/", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo")
+ assert_equal(:Foo, serv)
+ assert_equal([], opts)
+ assert_equal("/foo", script_name)
+ assert_equal("", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/")
+ assert_equal(:Foo, serv)
+ assert_equal([], opts)
+ assert_equal("/foo", script_name)
+ assert_equal("/", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/sub")
+ assert_equal(:Foo, serv)
+ assert_equal([], opts)
+ assert_equal("/foo", script_name)
+ assert_equal("/sub", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar")
+ assert_equal(:Bar, serv)
+ assert_equal([:bar1], opts)
+ assert_equal("/foo/bar", script_name)
+ assert_equal("", path_info)
+
+ serv, opts, script_name, path_info = httpd.search_servlet("/foo/bar/baz")
+ assert_equal(:Baz, serv)
+ assert_equal([:baz1, :baz2], opts)
+ assert_equal("/foo/bar/baz", script_name)
+ assert_equal("", path_info)
+ end
+
+ class Req
+ attr_reader :port, :host
+ def initialize(addr, port, host)
+ @addr, @port, @host = addr, port, host
+ end
+ def addr
+ [0,0,0,@addr]
+ end
+ end
+
+ def httpd(addr, port, host, ali)
+ config ={
+ :Logger => NoLog,
+ :DoNotListen => true,
+ :BindAddress => addr,
+ :Port => port,
+ :ServerName => host,
+ :ServerAlias => ali,
+ }
+ return WEBrick::HTTPServer.new(config)
+ end
+
+ def assert_eql?(v1, v2)
+ assert_equal(v1.object_id, v2.object_id)
+ end
+
+ def test_lookup_server
+ addr1 = "192.168.100.1"
+ addr2 = "192.168.100.2"
+ addrz = "192.168.100.254"
+ local = "127.0.0.1"
+ port1 = 80
+ port2 = 8080
+ port3 = 10080
+ portz = 32767
+ name1 = "www.example.com"
+ name2 = "www2.example.com"
+ name3 = "www3.example.com"
+ namea = "www.example.co.jp"
+ nameb = "www.example.jp"
+ namec = "www2.example.co.jp"
+ named = "www2.example.jp"
+ namez = "foobar.example.com"
+ alias1 = [namea, nameb]
+ alias2 = [namec, named]
+
+ host1 = httpd(nil, port1, name1, nil)
+ hosts = [
+ host2 = httpd(addr1, port1, name1, nil),
+ host3 = httpd(addr1, port1, name2, alias1),
+ host4 = httpd(addr1, port2, name1, nil),
+ host5 = httpd(addr1, port2, name2, alias1),
+ httpd(addr1, port2, name3, alias2),
+ host7 = httpd(addr2, nil, name1, nil),
+ host8 = httpd(addr2, nil, name2, alias1),
+ httpd(addr2, nil, name3, alias2),
+ host10 = httpd(local, nil, nil, nil),
+ host11 = httpd(nil, port3, nil, nil),
+ ].sort_by{ rand }
+ hosts.each{|h| host1.virtual_host(h) }
+
+ # connect to addr1
+ assert_eql?(host2, host1.lookup_server(Req.new(addr1, port1, name1)))
+ assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, name2)))
+ assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, namea)))
+ assert_eql?(host3, host1.lookup_server(Req.new(addr1, port1, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, port1, namez)))
+ assert_eql?(host4, host1.lookup_server(Req.new(addr1, port2, name1)))
+ assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, name2)))
+ assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, namea)))
+ assert_eql?(host5, host1.lookup_server(Req.new(addr1, port2, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, port2, namez)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name1)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, name2)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namea)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, nameb)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr1, port3, namez)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr1, portz, namez)))
+
+ # connect to addr2
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, port1, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port1, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr2, port1, namez)))
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, port2, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port2, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr2, port2, namez)))
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, port3, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, port3, nameb)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addr2, port3, namez)))
+ assert_eql?(host7, host1.lookup_server(Req.new(addr2, portz, name1)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, name2)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, namea)))
+ assert_eql?(host8, host1.lookup_server(Req.new(addr2, portz, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addr2, portz, namez)))
+
+ # connect to addrz
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port1, namez)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, port2, namez)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name1)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, name2)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namea)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, nameb)))
+ assert_eql?(host11, host1.lookup_server(Req.new(addrz, port3, namez)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name1)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, name2)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namea)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, nameb)))
+ assert_eql?(nil, host1.lookup_server(Req.new(addrz, portz, namez)))
+
+ # connect to localhost
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port1, namez)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port2, namez)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, port3, namez)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name1)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, name2)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namea)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, nameb)))
+ assert_eql?(host10, host1.lookup_server(Req.new(local, portz, namez)))
+ end
+
+ def test_callbacks
+ accepted = started = stopped = 0
+ requested0 = requested1 = 0
+ config = {
+ :ServerName => "localhost",
+ :AcceptCallback => Proc.new{ accepted += 1 },
+ :StartCallback => Proc.new{ started += 1 },
+ :StopCallback => Proc.new{ stopped += 1 },
+ :RequestCallback => Proc.new{|req, res| requested0 += 1 },
+ }
+ log_tester = lambda {|log, access_log|
+ assert(log.find {|s| %r{ERROR `/' not found\.} =~ s })
+ assert_equal([], log.reject {|s| %r{ERROR `/' not found\.} =~ s })
+ }
+ TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
+ vhost_config = {
+ :ServerName => "myhostname",
+ :BindAddress => addr,
+ :Port => port,
+ :DoNotListen => true,
+ :Logger => NoLog,
+ :AccessLog => [],
+ :RequestCallback => Proc.new{|req, res| requested1 += 1 },
+ }
+ server.virtual_host(WEBrick::HTTPServer.new(vhost_config))
+
+ Thread.pass while server.status != :Running
+ sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # server.status behaves unexpectedly with --jit-wait
+ assert_equal(1, started, log.call)
+ assert_equal(0, stopped, log.call)
+ assert_equal(0, accepted, log.call)
+
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ req["Host"] = "myhostname:#{port}"
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ req["Host"] = "localhost:#{port}"
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ assert_equal(6, accepted, log.call)
+ assert_equal(3, requested0, log.call)
+ assert_equal(3, requested1, log.call)
+ }
+ assert_equal(started, 1)
+ assert_equal(stopped, 1)
+ end
+
+ class CustomRequest < ::WEBrick::HTTPRequest; end
+ class CustomResponse < ::WEBrick::HTTPResponse; end
+ class CustomServer < ::WEBrick::HTTPServer
+ def create_request(config)
+ CustomRequest.new(config)
+ end
+
+ def create_response(config)
+ CustomResponse.new(config)
+ end
+ end
+
+ def test_custom_server_request_and_response
+ config = { :ServerName => "localhost" }
+ TestWEBrick.start_server(CustomServer, config){|server, addr, port, log|
+ server.mount_proc("/", lambda {|req, res|
+ assert_kind_of(CustomRequest, req)
+ assert_kind_of(CustomResponse, res)
+ res.body = "via custom response"
+ })
+ Thread.pass while server.status != :Running
+
+ Net::HTTP.start(addr, port) do |http|
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res|
+ assert_equal("via custom response", res.body)
+ }
+ server.shutdown
+ end
+ }
+ end
+
+ # This class is needed by test_response_io_with_chunked_set method
+ class EventManagerForChunkedResponseTest
+ def initialize
+ @listeners = []
+ end
+ def add_listener( &block )
+ @listeners << block
+ end
+ def raise_str_event( str )
+ @listeners.each{ |e| e.call( :str, str ) }
+ end
+ def raise_close_event()
+ @listeners.each{ |e| e.call( :cls ) }
+ end
+ end
+ def test_response_io_with_chunked_set
+ evt_man = EventManagerForChunkedResponseTest.new
+ t = Thread.new do
+ begin
+ config = {
+ :ServerName => "localhost"
+ }
+ TestWEBrick.start_httpserver(config) do |server, addr, port, log|
+ body_strs = [ 'aaaaaa', 'bb', 'cccc' ]
+ server.mount_proc( "/", ->( req, res ){
+ # Test for setting chunked...
+ res.chunked = true
+ r,w = IO.pipe
+ evt_man.add_listener do |type,str|
+ type == :cls ? ( w.close ) : ( w << str )
+ end
+ res.body = r
+ } )
+ Thread.pass while server.status != :Running
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ http.request(req) do |res|
+ i = 0
+ evt_man.raise_str_event( body_strs[i] )
+ res.read_body do |s|
+ assert_equal( body_strs[i], s )
+ i += 1
+ if i < body_strs.length
+ evt_man.raise_str_event( body_strs[i] )
+ else
+ evt_man.raise_close_event()
+ end
+ end
+ assert_equal( body_strs.length, i )
+ end
+ end
+ rescue => err
+ flunk( 'exception raised in thread: ' + err.to_s )
+ end
+ end
+ if t.join( 3 ).nil?
+ evt_man.raise_close_event()
+ flunk( 'timeout' )
+ if t.join( 1 ).nil?
+ Thread.kill t
+ end
+ end
+ end
+
+ def test_response_io_without_chunked_set
+ config = {
+ :ServerName => "localhost"
+ }
+ log_tester = lambda {|log, access_log|
+ assert_equal(1, log.length)
+ assert_match(/WARN Could not determine content-length of response body./, log[0])
+ }
+ TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
+ server.mount_proc("/", lambda { |req, res|
+ r,w = IO.pipe
+ # Test for not setting chunked...
+ # res.chunked = true
+ res.body = r
+ w << "foo"
+ w.close
+ })
+ Thread.pass while server.status != :Running
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ req['Connection'] = 'Keep-Alive'
+ begin
+ Timeout.timeout(2) do
+ http.request(req){|res| assert_equal("foo", res.body) }
+ end
+ rescue Timeout::Error
+ flunk('corrupted response')
+ end
+ }
+ end
+
+ def test_request_handler_callback_is_deprecated
+ requested = 0
+ config = {
+ :ServerName => "localhost",
+ :RequestHandler => Proc.new{|req, res| requested += 1 },
+ }
+ log_tester = lambda {|log, access_log|
+ assert_equal(2, log.length)
+ assert_match(/WARN :RequestHandler is deprecated, please use :RequestCallback/, log[0])
+ assert_match(%r{ERROR `/' not found\.}, log[1])
+ }
+ TestWEBrick.start_httpserver(config, log_tester){|server, addr, port, log|
+ Thread.pass while server.status != :Running
+
+ http = Net::HTTP.new(addr, port)
+ req = Net::HTTP::Get.new("/")
+ req["Host"] = "localhost:#{port}"
+ http.request(req){|res| assert_equal("404", res.code, log.call)}
+ assert_match(%r{:RequestHandler is deprecated, please use :RequestCallback$}, log.call, log.call)
+ }
+ assert_equal(1, requested)
+ end
+
+ def test_shutdown_with_busy_keepalive_connection
+ requested = 0
+ config = {
+ :ServerName => "localhost",
+ }
+ TestWEBrick.start_httpserver(config){|server, addr, port, log|
+ server.mount_proc("/", lambda {|req, res| res.body = "heffalump" })
+ Thread.pass while server.status != :Running
+
+ Net::HTTP.start(addr, port) do |http|
+ req = Net::HTTP::Get.new("/")
+ http.request(req){|res| assert_equal('Keep-Alive', res['Connection'], log.call) }
+ server.shutdown
+ begin
+ 10.times {|n| http.request(req); requested += 1 }
+ rescue
+ # Errno::ECONNREFUSED or similar
+ end
+ end
+ }
+ assert_equal(0, requested, "Server responded to #{requested} requests after shutdown")
+ end
+
+ def test_cntrl_in_path
+ log_ary = []
+ access_log_ary = []
+ config = {
+ :Port => 0,
+ :BindAddress => '127.0.0.1',
+ :Logger => WEBrick::Log.new(log_ary, WEBrick::BasicLog::WARN),
+ :AccessLog => [[access_log_ary, '']],
+ }
+ s = WEBrick::HTTPServer.new(config)
+ s.mount('/foo', WEBrick::HTTPServlet::FileHandler, __FILE__)
+ th = Thread.new { s.start }
+ addr = s.listeners[0].addr
+
+ http = Net::HTTP.new(addr[3], addr[1])
+ req = Net::HTTP::Get.new('/notexist%0a/foo')
+ http.request(req) { |res| assert_equal('404', res.code) }
+ exp = %Q(ERROR `/notexist\\n/foo' not found.\n)
+ assert_equal 1, log_ary.size
+ assert_include log_ary[0], exp
+ ensure
+ s&.shutdown
+ th&.join
+ end
+
+ def test_gigantic_request_header
+ log_tester = lambda {|log, access_log|
+ assert_equal 1, log.size
+ assert_include log[0], 'ERROR headers too large'
+ }
+ TestWEBrick.start_httpserver({}, log_tester){|server, addr, port, log|
+ server.mount('/', WEBrick::HTTPServlet::FileHandler, __FILE__)
+ TCPSocket.open(addr, port) do |c|
+ c.write("GET / HTTP/1.0\r\n")
+ junk = -"X-Junk: #{' ' * 1024}\r\n"
+ assert_raise(Errno::ECONNRESET, Errno::EPIPE, Errno::EPROTOTYPE) do
+ loop { c.write(junk) }
+ end
+ end
+ }
+ end
+
+ def test_eof_in_chunk
+ log_tester = lambda do |log, access_log|
+ assert_equal 1, log.size
+ assert_include log[0], 'ERROR bad chunk data size'
+ end
+ TestWEBrick.start_httpserver({}, log_tester){|server, addr, port, log|
+ server.mount_proc('/', ->(req, res) { res.body = req.body })
+ TCPSocket.open(addr, port) do |c|
+ c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
+ "Transfer-Encoding: chunked\r\n\r\n5\r\na")
+ c.shutdown(Socket::SHUT_WR) # trigger EOF in server
+ res = c.read
+ assert_match %r{\AHTTP/1\.1 400 }, res
+ end
+ }
+ end
+
+ def test_big_chunks
+ nr_out = 3
+ buf = 'big' # 3 bytes is bigger than 2!
+ config = { :InputBufferSize => 2 }.freeze
+ total = 0
+ all = ''
+ TestWEBrick.start_httpserver(config){|server, addr, port, log|
+ server.mount_proc('/', ->(req, res) {
+ err = []
+ ret = req.body do |chunk|
+ n = chunk.bytesize
+ n > config[:InputBufferSize] and err << "#{n} > :InputBufferSize"
+ total += n
+ all << chunk
+ end
+ ret.nil? or err << 'req.body should return nil'
+ (buf * nr_out) == all or err << 'input body does not match expected'
+ res.header['connection'] = 'close'
+ res.body = err.join("\n")
+ })
+ TCPSocket.open(addr, port) do |c|
+ c.write("POST / HTTP/1.1\r\nHost: example.com\r\n" \
+ "Transfer-Encoding: chunked\r\n\r\n")
+ chunk = "#{buf.bytesize.to_s(16)}\r\n#{buf}\r\n"
+ nr_out.times { c.write(chunk) }
+ c.write("0\r\n\r\n")
+ head, body = c.read.split("\r\n\r\n")
+ assert_match %r{\AHTTP/1\.1 200 OK}, head
+ assert_nil body
+ end
+ }
+ end
+end
diff --git a/test/webrick/test_httpstatus.rb b/tool/test/webrick/test_httpstatus.rb
index fd0570d5c6..fd0570d5c6 100644
--- a/test/webrick/test_httpstatus.rb
+++ b/tool/test/webrick/test_httpstatus.rb
diff --git a/test/webrick/test_httputils.rb b/tool/test/webrick/test_httputils.rb
index 00f297bd09..00f297bd09 100644
--- a/test/webrick/test_httputils.rb
+++ b/tool/test/webrick/test_httputils.rb
diff --git a/test/webrick/test_httpversion.rb b/tool/test/webrick/test_httpversion.rb
index e50ee17971..e50ee17971 100644
--- a/test/webrick/test_httpversion.rb
+++ b/tool/test/webrick/test_httpversion.rb
diff --git a/tool/test/webrick/test_server.rb b/tool/test/webrick/test_server.rb
new file mode 100644
index 0000000000..815cc3ce39
--- /dev/null
+++ b/tool/test/webrick/test_server.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: false
+require "test/unit"
+require "tempfile"
+require "webrick"
+require_relative "utils"
+
+class TestWEBrickServer < Test::Unit::TestCase
+ class Echo < WEBrick::GenericServer
+ def run(sock)
+ while line = sock.gets
+ sock << line
+ end
+ end
+ end
+
+ def test_server
+ TestWEBrick.start_server(Echo){|server, addr, port, log|
+ TCPSocket.open(addr, port){|sock|
+ sock.puts("foo"); assert_equal("foo\n", sock.gets, log.call)
+ sock.puts("bar"); assert_equal("bar\n", sock.gets, log.call)
+ sock.puts("baz"); assert_equal("baz\n", sock.gets, log.call)
+ sock.puts("qux"); assert_equal("qux\n", sock.gets, log.call)
+ }
+ }
+ end
+
+ def test_start_exception
+ stopped = 0
+
+ log = []
+ logger = WEBrick::Log.new(log, WEBrick::BasicLog::WARN)
+
+ assert_raise(SignalException) do
+ listener = Object.new
+ def listener.to_io # IO.select invokes #to_io.
+ raise SignalException, 'SIGTERM' # simulate signal in main thread
+ end
+ def listener.shutdown
+ end
+ def listener.close
+ end
+
+ server = WEBrick::HTTPServer.new({
+ :BindAddress => "127.0.0.1", :Port => 0,
+ :StopCallback => Proc.new{ stopped += 1 },
+ :Logger => logger,
+ })
+ server.listeners[0].close
+ server.listeners[0] = listener
+
+ server.start
+ end
+
+ assert_equal(1, stopped)
+ assert_equal(1, log.length)
+ assert_match(/FATAL SignalException: SIGTERM/, log[0])
+ end
+
+ def test_callbacks
+ accepted = started = stopped = 0
+ config = {
+ :AcceptCallback => Proc.new{ accepted += 1 },
+ :StartCallback => Proc.new{ started += 1 },
+ :StopCallback => Proc.new{ stopped += 1 },
+ }
+ TestWEBrick.start_server(Echo, config){|server, addr, port, log|
+ true while server.status != :Running
+ sleep 1 if defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled? # server.status behaves unexpectedly with --jit-wait
+ assert_equal(1, started, log.call)
+ assert_equal(0, stopped, log.call)
+ assert_equal(0, accepted, log.call)
+ TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
+ TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
+ TCPSocket.open(addr, port){|sock| (sock << "foo\n").gets }
+ assert_equal(3, accepted, log.call)
+ }
+ assert_equal(1, started)
+ assert_equal(1, stopped)
+ end
+
+ def test_daemon
+ begin
+ r, w = IO.pipe
+ pid1 = Process.fork{
+ r.close
+ WEBrick::Daemon.start
+ w.puts(Process.pid)
+ sleep 10
+ }
+ pid2 = r.gets.to_i
+ assert(Process.kill(:KILL, pid2))
+ assert_not_equal(pid1, pid2)
+ rescue NotImplementedError
+ # snip this test
+ ensure
+ Process.wait(pid1) if pid1
+ r.close
+ w.close
+ end
+ end
+
+ def test_restart_after_shutdown
+ address = '127.0.0.1'
+ port = 0
+ log = []
+ config = {
+ :BindAddress => address,
+ :Port => port,
+ :Logger => WEBrick::Log.new(log, WEBrick::BasicLog::WARN),
+ }
+ server = Echo.new(config)
+ client_proc = lambda {|str|
+ begin
+ ret = server.listeners.first.connect_address.connect {|s|
+ s.write(str)
+ s.close_write
+ s.read
+ }
+ assert_equal(str, ret)
+ ensure
+ server.shutdown
+ end
+ }
+ server_thread = Thread.new { server.start }
+ client_thread = Thread.new { client_proc.call("a") }
+ assert_join_threads([client_thread, server_thread])
+ server.listen(address, port)
+ server_thread = Thread.new { server.start }
+ client_thread = Thread.new { client_proc.call("b") }
+ assert_join_threads([client_thread, server_thread])
+ assert_equal([], log)
+ end
+
+ def test_restart_after_stop
+ log = Object.new
+ class << log
+ include Test::Unit::Assertions
+ def <<(msg)
+ flunk "unexpected log: #{msg.inspect}"
+ end
+ end
+ client_thread = nil
+ wakeup = -> {client_thread.wakeup}
+ warn_flunk = WEBrick::Log.new(log, WEBrick::BasicLog::WARN)
+ server = WEBrick::HTTPServer.new(
+ :StartCallback => wakeup,
+ :StopCallback => wakeup,
+ :BindAddress => '0.0.0.0',
+ :Port => 0,
+ :Logger => warn_flunk)
+ 2.times {
+ server_thread = Thread.start {
+ server.start
+ }
+ client_thread = Thread.start {
+ sleep 0.1 until server.status == :Running || !server_thread.status
+ server.stop
+ sleep 0.1 until server.status == :Stop || !server_thread.status
+ }
+ assert_join_threads([client_thread, server_thread])
+ }
+ end
+
+ def test_port_numbers
+ config = {
+ :BindAddress => '0.0.0.0',
+ :Logger => WEBrick::Log.new([], WEBrick::BasicLog::WARN),
+ }
+
+ ports = [0, "0"]
+
+ ports.each do |port|
+ config[:Port]= port
+ server = WEBrick::GenericServer.new(config)
+ server_thread = Thread.start { server.start }
+ client_thread = Thread.start {
+ sleep 0.1 until server.status == :Running || !server_thread.status
+ server_port = server.listeners[0].addr[1]
+ server.stop
+ assert_equal server.config[:Port], server_port
+ sleep 0.1 until server.status == :Stop || !server_thread.status
+ }
+ assert_join_threads([client_thread, server_thread])
+ end
+
+ assert_raise(ArgumentError) do
+ config[:Port]= "FOO"
+ WEBrick::GenericServer.new(config)
+ end
+ end
+end
diff --git a/test/webrick/test_ssl_server.rb b/tool/test/webrick/test_ssl_server.rb
index 4e52598bf5..4e52598bf5 100644
--- a/test/webrick/test_ssl_server.rb
+++ b/tool/test/webrick/test_ssl_server.rb
diff --git a/test/webrick/test_utils.rb b/tool/test/webrick/test_utils.rb
index c2b7a36e8a..c2b7a36e8a 100644
--- a/test/webrick/test_utils.rb
+++ b/tool/test/webrick/test_utils.rb
diff --git a/test/webrick/utils.rb b/tool/test/webrick/utils.rb
index 56d3a30ea4..56d3a30ea4 100644
--- a/test/webrick/utils.rb
+++ b/tool/test/webrick/utils.rb
diff --git a/test/webrick/webrick.cgi b/tool/test/webrick/webrick.cgi
index a294fa72f9..a294fa72f9 100644
--- a/test/webrick/webrick.cgi
+++ b/tool/test/webrick/webrick.cgi
diff --git a/test/webrick/webrick.rhtml b/tool/test/webrick/webrick.rhtml
index a7bbe43fb5..a7bbe43fb5 100644
--- a/test/webrick/webrick.rhtml
+++ b/tool/test/webrick/webrick.rhtml
diff --git a/test/webrick/webrick_long_filename.cgi b/tool/test/webrick/webrick_long_filename.cgi
index 43c1af825c..43c1af825c 100644
--- a/test/webrick/webrick_long_filename.cgi
+++ b/tool/test/webrick/webrick_long_filename.cgi
diff --git a/tool/transcode-tblgen.rb b/tool/transcode-tblgen.rb
index 156b2de197..c6b58dbe78 100644
--- a/tool/transcode-tblgen.rb
+++ b/tool/transcode-tblgen.rb
@@ -895,9 +895,9 @@ static const rb_transcoder
#{max_input}, /* max_input */
#{max_output}, /* max_output */
#{ascii_compatibility}, /* asciicompat_type */
- 0, NULL, NULL, /* state_size, state_init, state_fini */
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL
+ 0, 0, 0, /* state_size, state_init, state_fini */
+ 0, 0, 0, 0,
+ 0, 0, 0
};
End
TRANSCODE_GENERATED_TRANSCODER_CODE << transcoder_code
diff --git a/tool/transform_mjit_header.rb b/tool/transform_mjit_header.rb
index 5f89446c81..2359ceab7c 100644
--- a/tool/transform_mjit_header.rb
+++ b/tool/transform_mjit_header.rb
@@ -27,7 +27,9 @@ module MJITHeader
# These macros are relied on this script's transformation
PREFIXED_MACROS = [
'ALWAYS_INLINE',
+ 'COLDFUNC',
'inline',
+ 'RBIMPL_ATTR_COLD',
]
# For MinGW's ras.h. Those macros have its name in its definition and can't be preprocessed multiple times.
@@ -60,9 +62,15 @@ module MJITHeader
'vm_opt_aref_with',
'vm_opt_aset_with',
'vm_opt_not',
- 'vm_getinstancevariable',
- 'vm_setinstancevariable',
- 'vm_setivar',
+ ]
+
+ COLD_FUNCTIONS = %w[
+ setup_parameters_complex
+ vm_call_iseq_setup
+ vm_call_iseq_setup_2
+ vm_call_iseq_setup_tailcall
+ vm_call_method_each_type
+ vm_ic_update
]
# Return start..stop of last decl in CODE ending STOP
@@ -105,7 +113,7 @@ module MJITHeader
su2_regex = /{([^{}]|#{su1_regex})*}/
su3_regex = /{([^{}]|#{su2_regex})*}/ # 3 nested structs/unions is probably enough
reduced_decl.gsub!(su3_regex, '') # remove structs/unions in the header
- id_seq_regex = /\s*(#{ident_regex}(\s+|\s*[*]+\s*))*/
+ id_seq_regex = /\s*(?:#{ident_regex}(?:\s+|\s*[*]+\s*))*/
# Process function header:
match = /\A#{id_seq_regex}(?<name>#{ident_regex})\s*\(/.match(reduced_decl)
return match[:name] if match
@@ -204,6 +212,10 @@ if ARGV.size != 3
abort "Usage: #{$0} <c-compiler> <header file> <out>"
end
+if STDOUT.tty?
+ require_relative 'lib/colorize'
+ color = Colorize.new
+end
cc = ARGV[0]
code = File.binread(ARGV[1]) # Current version of the header file.
outfile = ARGV[2]
@@ -243,10 +255,10 @@ end
# Check initial file correctness in the manner of final output.
MJITHeader.check_code!(code_to_check, cc, cflags, 'initial')
-puts "\nTransforming external functions to static:"
-stop_pos = -1
-extern_names = []
+stop_pos = -1
+extern_names = []
+transform_logs = Hash.new { |h, k| h[k] = [] }
# This loop changes function declarations to static inline.
while (decl_range = MJITHeader.find_decl(code, stop_pos))
@@ -255,8 +267,13 @@ while (decl_range = MJITHeader.find_decl(code, stop_pos))
decl_name = MJITHeader.decl_name_of(decl)
if MJITHeader::IGNORED_FUNCTIONS.include?(decl_name) && /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl)
- puts "#{PROGRAM}: changing definition of '#{decl_name}' to declaration"
+ transform_logs[:def_to_decl] << decl_name
code[decl_range] = decl.sub(/{.+}/m, ';')
+ elsif MJITHeader::COLD_FUNCTIONS.include?(decl_name) && match = /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl)
+ header = match[0].sub(/{\z/, '').strip
+ header = "static #{header.sub(/\A((static|inline) )+/, '')}"
+ decl[match.begin(0)...match.end(0)] = '{' # remove header
+ code[decl_range] = "\nCOLDFUNC #{header} #{decl}"
elsif MJITHeader::ALWAYS_INLINED_FUNCTIONS.include?(decl_name) && match = /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl)
header = match[0].sub(/{\z/, '').strip
header = "static inline #{header.sub(/\A((static|inline) )+/, '')}"
@@ -265,13 +282,13 @@ while (decl_range = MJITHeader.find_decl(code, stop_pos))
elsif extern_names.include?(decl_name) && (decl =~ /#{MJITHeader::FUNC_HEADER_REGEXP};/)
decl.sub!(/(extern|static|inline) /, ' ')
unless decl_name =~ /\Aattr_\w+_\w+\z/ # skip too-many false-positive warnings in insns_info.inc.
- puts "#{PROGRAM}: making declaration of '#{decl_name}' static inline"
+ transform_logs[:static_inline_decl] << decl_name
end
code[decl_range] = "static inline #{decl}"
elsif (match = /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl)) && (header = match[0]) !~ /static/
unless decl_name.match(MJITHeader::TARGET_NAME_REGEXP)
- puts "#{PROGRAM}: SKIPPED to transform #{decl_name}"
+ transform_logs[:skipped] << decl_name
next
end
@@ -279,12 +296,12 @@ while (decl_range = MJITHeader.find_decl(code, stop_pos))
decl[match.begin(0)...match.end(0)] = ''
if decl =~ /\bstatic\b/
- puts "warning: a static decl inside external definition of '#{decl_name}'"
+ abort "#{PROGRAM}: a static decl was found inside external definition #{decl_name.dump}"
end
header.sub!(/(extern|inline) /, ' ')
unless decl_name =~ /\Aattr_\w+_\w+\z/ # skip too-many false-positive warnings in insns_info.inc.
- puts "#{PROGRAM}: making external definition of '#{decl_name}' static inline"
+ transform_logs[:static_inline_def] << decl_name
end
code[decl_range] = "static inline #{header}#{decl}"
end
@@ -296,3 +313,14 @@ code << macro
MJITHeader.check_code!(code, cc, cflags, 'final')
MJITHeader.write(code, outfile)
+
+messages = {
+ def_to_decl: 'changing definition to declaration',
+ static_inline_def: 'making external definition static inline',
+ static_inline_decl: 'making declaration static inline',
+ skipped: 'SKIPPED to transform',
+}
+transform_logs.each do |key, decl_names|
+ decl_names = decl_names.map { |s| color.bold(s) } if color
+ puts("#{PROGRAM}: #{messages.fetch(key)}: #{decl_names.join(', ')}")
+end
diff --git a/tool/update-bundled_gems.rb b/tool/update-bundled_gems.rb
new file mode 100644
index 0000000000..cef31e2f13
--- /dev/null
+++ b/tool/update-bundled_gems.rb
@@ -0,0 +1,14 @@
+#!ruby -pla
+BEGIN {
+ require 'rubygems'
+}
+unless /^[^#]/ !~ (gem = $F[0])
+ (gem, src), = Gem::SpecFetcher.fetcher.detect(:latest) {|s|
+ s.platform == "ruby" && s.name == gem
+ }
+ gem = src.fetch_spec(gem)
+ uri = gem.metadata["source_code_uri"] || gem.homepage
+ uri = uri.sub(%r[\Ahttps://github\.com/[^/]+/[^/]+\K/tree/.*], "").chomp(".git")
+ $F[3][$F[1]] = gem.version.to_s if $F[3] && $F[3].include?($F[1])
+ $_ = [gem.name, gem.version, uri, *$F[3..-1]].join(" ")
+end
diff --git a/tool/update-deps b/tool/update-deps
index 07c14dce62..c59debee77 100755
--- a/tool/update-deps
+++ b/tool/update-deps
@@ -262,7 +262,7 @@ end
def read_make_deps(cwd)
dependencies = {}
- make_p, make_p_stderr, make_p_status = Open3.capture3("make -p all miniruby ruby-runner golf")
+ make_p, make_p_stderr, make_p_status = Open3.capture3("make -p all miniruby exe/ruby golf")
File.open('update-deps.make.out.log', 'w') {|f| f.print make_p }
File.open('update-deps.make.err.log', 'w') {|f| f.print make_p_stderr }
if !make_p_status.success?
diff --git a/trace_point.rb b/trace_point.rb
index a8c46a0a0e..d68eed4248 100644
--- a/trace_point.rb
+++ b/trace_point.rb
@@ -93,7 +93,7 @@ class TracePoint
# Access from other threads is also forbidden.
#
def self.new(*events)
- __builtin_tracepoint_new_s(events)
+ Primitive.tracepoint_new_s(events)
end
# call-seq:
@@ -102,7 +102,7 @@ class TracePoint
# Return a string containing a human-readable TracePoint
# status.
def inspect
- __builtin_tracepoint_inspect
+ Primitive.tracepoint_inspect
end
# call-seq:
@@ -115,7 +115,7 @@ class TracePoint
#
# This method is only for debugging TracePoint itself.
def self.stat
- __builtin_tracepoint_stat_s
+ Primitive.tracepoint_stat_s
end
# Document-method: trace
@@ -132,7 +132,7 @@ class TracePoint
# trace.enabled? #=> true
#
def self.trace(*events)
- __builtin_tracepoint_trace_s(events)
+ Primitive.tracepoint_trace_s(events)
end
# call-seq:
@@ -183,7 +183,7 @@ class TracePoint
# t.enable(target: method(:m1))
#
# m1
- # # prints #<TracePoint:line@test.rb:5 in `m1'>
+ # # prints #<TracePoint:line test.rb:4 in `m1'>
# m2
# # prints nothing
#
@@ -193,7 +193,7 @@ class TracePoint
# #=> RuntimeError: access from outside
#
def enable(target: nil, target_line: nil, target_thread: nil)
- __builtin_tracepoint_enable_m(target, target_line, target_thread)
+ Primitive.tracepoint_enable_m(target, target_line, target_thread)
end
# call-seq:
@@ -229,7 +229,7 @@ class TracePoint
# trace.disable { p tp.lineno }
# #=> RuntimeError: access from outside
def disable
- __builtin_tracepoint_disable_m
+ Primitive.tracepoint_disable_m
end
# call-seq:
@@ -237,40 +237,40 @@ class TracePoint
#
# The current status of the trace
def enabled?
- __builtin_tracepoint_enabled_p
+ Primitive.tracepoint_enabled_p
end
# Type of event
#
# See TracePoint@Events for more information.
def event
- __builtin_tracepoint_attr_event
+ Primitive.tracepoint_attr_event
end
# Line number of the event
def lineno
- __builtin_tracepoint_attr_lineno
+ Primitive.tracepoint_attr_lineno
end
# Path of the file being run
def path
- __builtin_tracepoint_attr_path
+ Primitive.tracepoint_attr_path
end
# Return the parameters definition of the method or block that the
# current hook belongs to. Format is the same as for Method#parameters
def parameters
- __builtin_tracepoint_attr_parameters
+ Primitive.tracepoint_attr_parameters
end
# Return the name at the definition of the method being called
def method_id
- __builtin_tracepoint_attr_method_id
+ Primitive.tracepoint_attr_method_id
end
# Return the called name of the method being called
def callee_id
- __builtin_tracepoint_attr_callee_id
+ Primitive.tracepoint_attr_callee_id
end
# Return class or module of the method being called.
@@ -306,12 +306,12 @@ class TracePoint
# C.foo
# end
def defined_class
- __builtin_tracepoint_attr_defined_class
+ Primitive.tracepoint_attr_defined_class
end
# Return the generated binding object from event
def binding
- __builtin_tracepoint_attr_binding
+ Primitive.tracepoint_attr_binding
end
# Return the trace object during event
@@ -319,23 +319,23 @@ class TracePoint
# Same as TracePoint#binding:
# trace.binding.eval('self')
def self
- __builtin_tracepoint_attr_self
+ Primitive.tracepoint_attr_self
end
# Return value from +:return+, +c_return+, and +b_return+ event
def return_value
- __builtin_tracepoint_attr_return_value
+ Primitive.tracepoint_attr_return_value
end
# Value from exception raised on the +:raise+ event
def raised_exception
- __builtin_tracepoint_attr_raised_exception
+ Primitive.tracepoint_attr_raised_exception
end
# Compiled source code (String) on *eval methods on the +:script_compiled+ event.
# If loaded from a file, it will return nil.
def eval_script
- __builtin_tracepoint_attr_eval_script
+ Primitive.tracepoint_attr_eval_script
end
# Compiled instruction sequence represented by a RubyVM::InstructionSequence instance
@@ -343,6 +343,6 @@ class TracePoint
#
# Note that this method is MRI specific.
def instruction_sequence
- __builtin_tracepoint_attr_instruction_sequence
+ Primitive.tracepoint_attr_instruction_sequence
end
end
diff --git a/transcode.c b/transcode.c
index 1c9cc01f36..d2abd9e0e5 100644
--- a/transcode.c
+++ b/transcode.c
@@ -9,10 +9,19 @@
**********************************************************************/
-#include "ruby/encoding.h"
+#include "ruby/internal/config.h"
+
+#include <ctype.h>
+
#include "internal.h"
+#include "internal/array.h"
+#include "internal/inits.h"
+#include "internal/object.h"
+#include "internal/string.h"
+#include "internal/transcode.h"
+#include "ruby/encoding.h"
+
#include "transcode_data.h"
-#include <ctype.h>
#include "id.h"
#define ENABLE_ECONV_NEWLINE_OPTION 1
@@ -2039,7 +2048,6 @@ make_econv_exception(rb_econv_t *ec)
size_t readagain_len = ec->last_error.readagain_len;
VALUE bytes2 = Qnil;
VALUE dumped2;
- int idx;
if (ec->last_error.result == econv_incomplete_input) {
mesg = rb_sprintf("incomplete %s on %s",
StringValueCStr(dumped),
@@ -2063,17 +2071,7 @@ make_econv_exception(rb_econv_t *ec)
rb_ivar_set(exc, rb_intern("error_bytes"), bytes);
rb_ivar_set(exc, rb_intern("readagain_bytes"), bytes2);
rb_ivar_set(exc, rb_intern("incomplete_input"), ec->last_error.result == econv_incomplete_input ? Qtrue : Qfalse);
-
- set_encs:
- rb_ivar_set(exc, rb_intern("source_encoding_name"), rb_str_new2(ec->last_error.source_encoding));
- rb_ivar_set(exc, rb_intern("destination_encoding_name"), rb_str_new2(ec->last_error.destination_encoding));
- idx = rb_enc_find_index(ec->last_error.source_encoding);
- if (0 <= idx)
- rb_ivar_set(exc, rb_intern("source_encoding"), rb_enc_from_encoding(rb_enc_from_index(idx)));
- idx = rb_enc_find_index(ec->last_error.destination_encoding);
- if (0 <= idx)
- rb_ivar_set(exc, rb_intern("destination_encoding"), rb_enc_from_encoding(rb_enc_from_index(idx)));
- return exc;
+ goto set_encs;
}
if (ec->last_error.result == econv_undefined_conversion) {
VALUE bytes = rb_str_new((const char *)ec->last_error.error_bytes_start,
@@ -2125,6 +2123,17 @@ make_econv_exception(rb_econv_t *ec)
goto set_encs;
}
return Qnil;
+
+ set_encs:
+ rb_ivar_set(exc, rb_intern("source_encoding_name"), rb_str_new2(ec->last_error.source_encoding));
+ rb_ivar_set(exc, rb_intern("destination_encoding_name"), rb_str_new2(ec->last_error.destination_encoding));
+ int idx = rb_enc_find_index(ec->last_error.source_encoding);
+ if (0 <= idx)
+ rb_ivar_set(exc, rb_intern("source_encoding"), rb_enc_from_encoding(rb_enc_from_index(idx)));
+ idx = rb_enc_find_index(ec->last_error.destination_encoding);
+ if (0 <= idx)
+ rb_ivar_set(exc, rb_intern("destination_encoding"), rb_enc_from_encoding(rb_enc_from_index(idx)));
+ return exc;
}
static void
@@ -2411,6 +2420,7 @@ static int
econv_opts(VALUE opt, int ecflags)
{
VALUE v;
+ int newlineflag = 0;
v = rb_hash_aref(opt, sym_invalid);
if (NIL_P(v)) {
@@ -2456,6 +2466,7 @@ econv_opts(VALUE opt, int ecflags)
#ifdef ENABLE_ECONV_NEWLINE_OPTION
v = rb_hash_aref(opt, sym_newline);
if (!NIL_P(v)) {
+ newlineflag = 2;
ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
if (v == sym_universal) {
ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
@@ -2477,10 +2488,9 @@ econv_opts(VALUE opt, int ecflags)
rb_raise(rb_eArgError, "unexpected value for newline option");
}
}
- else
#endif
{
- int setflags = 0, newlineflag = 0;
+ int setflags = 0;
v = rb_hash_aref(opt, sym_universal_newline);
if (RTEST(v))
@@ -2497,9 +2507,15 @@ econv_opts(VALUE opt, int ecflags)
setflags |= ECONV_CR_NEWLINE_DECORATOR;
newlineflag |= !NIL_P(v);
- if (newlineflag) {
+ switch (newlineflag) {
+ case 1:
ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
ecflags |= setflags;
+ break;
+
+ case 3:
+ rb_warning(":newline option preceds other newline options");
+ break;
}
}
@@ -2703,6 +2719,12 @@ str_transcode0(int argc, VALUE *argv, VALUE *self, int ecflags, VALUE ecopts)
}
}
else {
+ if (senc && denc && !rb_enc_asciicompat(senc) && !rb_enc_asciicompat(denc)) {
+ rb_encoding *utf8 = rb_utf8_encoding();
+ str = rb_str_conv_enc(str, senc, utf8);
+ senc = utf8;
+ sname = "UTF-8";
+ }
if (encoding_equal(sname, dname)) {
sname = "";
dname = "";
@@ -2768,14 +2790,14 @@ str_encode_associate(VALUE str, int encidx)
/*
* call-seq:
- * str.encode!(encoding [, options] ) -> str
- * str.encode!(dst_encoding, src_encoding [, options] ) -> str
+ * str.encode!(encoding, **options) -> str
+ * str.encode!(dst_encoding, src_encoding, **options) -> str
*
* The first form transcodes the contents of <i>str</i> from
* str.encoding to +encoding+.
* The second form transcodes the contents of <i>str</i> from
* src_encoding to dst_encoding.
- * The options Hash gives details for conversion. See String#encode
+ * The +options+ keyword arguments give details for conversion. See String#encode
* for details.
* Returns the string even if no changes were made.
*/
@@ -2804,9 +2826,9 @@ static VALUE encoded_dup(VALUE newstr, VALUE str, int encidx);
/*
* call-seq:
- * str.encode(encoding [, options] ) -> str
- * str.encode(dst_encoding, src_encoding [, options] ) -> str
- * str.encode([options]) -> str
+ * str.encode(encoding, **options) -> str
+ * str.encode(dst_encoding, src_encoding, **options) -> str
+ * str.encode(**options) -> str
*
* The first form returns a copy of +str+ transcoded
* to encoding +encoding+.
@@ -2822,8 +2844,8 @@ static VALUE encoded_dup(VALUE newstr, VALUE str, int encidx);
* in the source encoding. The last form by default does not raise
* exceptions but uses replacement strings.
*
- * The +options+ Hash gives details for conversion and can have the following
- * keys:
+ * The +options+ keyword arguments give details for conversion.
+ * The arguments are:
*
* :invalid ::
* If the value is +:replace+, #encode replaces invalid byte sequences in
@@ -2911,7 +2933,7 @@ econv_memsize(const void *ptr)
static const rb_data_type_t econv_data_type = {
"econv",
- {NULL, econv_free, econv_memsize,},
+ {0, econv_free, econv_memsize,},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -4446,7 +4468,7 @@ InitVM_transcode(void)
rb_define_method(rb_cString, "encode", str_encode, -1);
rb_define_method(rb_cString, "encode!", str_encode_bang, -1);
- rb_cEncodingConverter = rb_define_class_under(rb_cEncoding, "Converter", rb_cData);
+ rb_cEncodingConverter = rb_define_class_under(rb_cEncoding, "Converter", rb_cObject);
rb_define_alloc_func(rb_cEncodingConverter, econv_s_allocate);
rb_define_singleton_method(rb_cEncodingConverter, "asciicompat_encoding", econv_s_asciicompat_encoding, 1);
rb_define_singleton_method(rb_cEncodingConverter, "search_convpath", econv_s_search_convpath, -1);
diff --git a/transcode_data.h b/transcode_data.h
index 2007eb06d3..9455ec93c9 100644
--- a/transcode_data.h
+++ b/transcode_data.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_TRANSCODE_DATA_H
+#define RUBY_TRANSCODE_DATA_H 1
/**********************************************************************
transcode_data.h -
@@ -11,9 +13,6 @@
#include "ruby/ruby.h"
-#ifndef RUBY_TRANSCODE_DATA_H
-#define RUBY_TRANSCODE_DATA_H 1
-
RUBY_SYMBOL_EXPORT_BEGIN
#define WORDINDEX_SHIFT_BITS 2
diff --git a/transient_heap.c b/transient_heap.c
index 6e9cf6440e..5b6fd89889 100644
--- a/transient_heap.c
+++ b/transient_heap.c
@@ -6,14 +6,21 @@
**********************************************************************/
-#include "ruby/ruby.h"
-#include "ruby/debug.h"
-#include "vm_debug.h"
+#include "debug_counter.h"
#include "gc.h"
#include "internal.h"
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/sanitizers.h"
+#include "internal/static_assert.h"
+#include "internal/struct.h"
+#include "internal/variable.h"
+#include "ruby/debug.h"
+#include "ruby/ruby.h"
#include "ruby_assert.h"
#include "transient_heap.h"
-#include "debug_counter.h"
+#include "vm_debug.h"
+#include "vm_sync.h"
#if USE_TRANSIENT_HEAP /* USE_TRANSIENT_HEAP */
/*
@@ -55,6 +62,7 @@
#define TRANSIENT_HEAP_TOTAL_SIZE (1024 * 1024 * 32) /* 32 MB */
#define TRANSIENT_HEAP_ALLOC_MAX (1024 * 2 ) /* 2 KB */
#define TRANSIENT_HEAP_BLOCK_NUM (TRANSIENT_HEAP_TOTAL_SIZE / TRANSIENT_HEAP_BLOCK_SIZE)
+#define TRANSIENT_HEAP_USABLE_SIZE (TRANSIENT_HEAP_BLOCK_SIZE - sizeof(struct transient_heap_block_header))
#define TRANSIENT_HEAP_ALLOC_MAGIC 0xfeab
#define TRANSIENT_HEAP_ALLOC_ALIGN RUBY_ALIGNOF(void *)
@@ -70,13 +78,12 @@ enum transient_heap_status {
struct transient_heap_block {
struct transient_heap_block_header {
- int16_t size; /* sizeof(block) = TRANSIENT_HEAP_BLOCK_SIZE - sizeof(struct transient_heap_block_header) */
int16_t index;
int16_t last_marked_index;
int16_t objects;
struct transient_heap_block *next_block;
} info;
- char buff[TRANSIENT_HEAP_BLOCK_SIZE - sizeof(struct transient_heap_block_header)];
+ char buff[TRANSIENT_HEAP_USABLE_SIZE];
};
struct transient_heap {
@@ -147,7 +154,7 @@ transient_heap_dump(struct transient_heap* theap)
transient_heap_blocks_dump(theap, theap->free_blocks, "free_blocks");
}
-/* Debug: dump all tarnsient_heap blocks */
+/* Debug: dump all transient_heap blocks */
void
rb_transient_heap_dump(void)
{
@@ -233,7 +240,6 @@ static void
reset_block(struct transient_heap_block *block)
{
__msan_allocated_memory(block, sizeof block);
- block->info.size = TRANSIENT_HEAP_BLOCK_SIZE - sizeof(struct transient_heap_block_header);
block->info.index = 0;
block->info.objects = 0;
block->info.last_marked_index = TRANSIENT_HEAP_ALLOC_MARKING_LAST;
@@ -338,9 +344,9 @@ transient_heap_allocatable_header(struct transient_heap* theap, size_t size)
struct transient_heap_block *block = theap->using_blocks;
while (block) {
- TH_ASSERT(block->info.size >= block->info.index);
+ TH_ASSERT(block->info.index <= (int16_t)TRANSIENT_HEAP_USABLE_SIZE);
- if (block->info.size - block->info.index >= (int32_t)size) {
+ if (TRANSIENT_HEAP_USABLE_SIZE - block->info.index >= size) {
struct transient_alloc_header *header = (void *)&block->buff[block->info.index];
block->info.index += size;
block->info.objects++;
@@ -358,6 +364,10 @@ transient_heap_allocatable_header(struct transient_heap* theap, size_t size)
void *
rb_transient_heap_alloc(VALUE obj, size_t req_size)
{
+ // only on single main ractor
+ if (ruby_single_main_ractor == NULL) return NULL;
+
+ void *ret;
struct transient_heap* theap = transient_heap_get();
size_t size = ROUND_UP(req_size + sizeof(struct transient_alloc_header), TRANSIENT_HEAP_ALLOC_ALIGN);
@@ -368,17 +378,17 @@ rb_transient_heap_alloc(VALUE obj, size_t req_size)
if (size > TRANSIENT_HEAP_ALLOC_MAX) {
if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [too big: %ld] %s\n", (long)size, rb_obj_info(obj));
- return NULL;
+ ret = NULL;
}
#if TRANSIENT_HEAP_DEBUG_DONT_PROMOTE == 0
else if (RB_OBJ_PROMOTED_RAW(obj)) {
if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [promoted object] %s\n", rb_obj_info(obj));
- return NULL;
+ ret = NULL;
}
#else
else if (RBASIC_CLASS(obj) == 0) {
if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [hidden object] %s\n", rb_obj_info(obj));
- return NULL;
+ ret = NULL;
}
#endif
else {
@@ -412,14 +422,16 @@ rb_transient_heap_alloc(VALUE obj, size_t req_size)
/* ptr is set up; OK to unpoison. */
asan_unpoison_memory_region(ptr, size - sizeof *header, true);
- return ptr;
+ ret = ptr;
}
else {
if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, "rb_transient_heap_alloc: [no enough space: %ld] %s\n", (long)size, rb_obj_info(obj));
RB_DEBUG_COUNTER_INC(theap_alloc_fail);
- return NULL;
+ ret = NULL;
}
}
+
+ return ret;
}
void
@@ -455,7 +467,7 @@ blocks_alloc_header_to_block(struct transient_heap *theap, struct transient_heap
struct transient_heap_block *block = blocks;
while (block) {
- if (block->buff <= (char *)header && (char *)header < block->buff + block->info.size) {
+ if (block->buff <= (char *)header && (char *)header < block->buff + TRANSIENT_HEAP_USABLE_SIZE) {
return block;
}
block = block->info.next_block;
@@ -528,6 +540,8 @@ alloc_header_to_block(struct transient_heap *theap, struct transient_alloc_heade
void
rb_transient_heap_mark(VALUE obj, const void *ptr)
{
+ ASSERT_vm_locking();
+
struct transient_alloc_header *header = ptr_to_alloc_header(ptr);
asan_unpoison_memory_region(header, sizeof *header, false);
if (header->magic != TRANSIENT_HEAP_ALLOC_MAGIC) rb_bug("rb_transient_heap_mark: wrong header, %s (%p)", rb_obj_info(obj), ptr);
@@ -639,6 +653,8 @@ transient_heap_promote_add(struct transient_heap* theap, VALUE obj)
void
rb_transient_heap_promote(VALUE obj)
{
+ ASSERT_vm_locking();
+
if (transient_heap_ptr(obj, FALSE)) {
struct transient_heap* theap = transient_heap_get();
transient_heap_promote_add(theap, obj);
@@ -657,6 +673,8 @@ alloc_header(struct transient_heap_block* block, int index)
static void
transient_heap_reset(void)
{
+ ASSERT_vm_locking();
+
struct transient_heap* theap = transient_heap_get();
struct transient_heap_block* block;
@@ -695,9 +713,10 @@ transient_heap_block_evacuate(struct transient_heap* theap, struct transient_hea
while (marked_index >= 0) {
struct transient_alloc_header *header = alloc_header(block, marked_index);
+ asan_unpoison_memory_region(header, sizeof *header, true);
VALUE obj = header->obj;
TH_ASSERT(header->magic == TRANSIENT_HEAP_ALLOC_MAGIC);
- if (header->magic != TRANSIENT_HEAP_ALLOC_MAGIC) rb_bug("rb_transient_heap_mark: wrong header %s\n", rb_obj_info(obj));
+ if (header->magic != TRANSIENT_HEAP_ALLOC_MAGIC) rb_bug("transient_heap_block_evacuate: wrong header %p %s\n", (void *)header, rb_obj_info(obj));
if (TRANSIENT_HEAP_DEBUG >= 3) fprintf(stderr, " * transient_heap_block_evacuate %p %s\n", (void *)header, rb_obj_info(obj));
@@ -718,17 +737,35 @@ transient_heap_block_evacuate(struct transient_heap* theap, struct transient_hea
rb_hash_transient_heap_evacuate(obj, !TRANSIENT_HEAP_DEBUG_DONT_PROMOTE);
break;
default:
- rb_bug("unsupporeted: %s\n", rb_obj_info(obj));
+ rb_bug("unsupported: %s\n", rb_obj_info(obj));
}
header->obj = Qundef; /* for debug */
}
marked_index = header->next_marked_index;
+ asan_poison_memory_region(header, sizeof *header);
}
}
+#if USE_RUBY_DEBUG_LOG
+static const char *
+transient_heap_status_cstr(enum transient_heap_status status)
+{
+ switch (status) {
+ case transient_heap_none: return "none";
+ case transient_heap_marking: return "marking";
+ case transient_heap_escaping: return "escaping";
+ }
+ UNREACHABLE_RETURN(NULL);
+}
+#endif
+
static void
transient_heap_update_status(struct transient_heap* theap, enum transient_heap_status status)
{
+ RUBY_DEBUG_LOG("%s -> %s",
+ transient_heap_status_cstr(theap->status),
+ transient_heap_status_cstr(status));
+
TH_ASSERT(theap->status != status);
theap->status = status;
}
@@ -738,53 +775,66 @@ transient_heap_evacuate(void *dmy)
{
struct transient_heap* theap = transient_heap_get();
+ if (theap->total_marked_objects == 0) return;
+ if (ruby_single_main_ractor == NULL) rb_bug("not single ractor mode");
if (theap->status == transient_heap_marking) {
if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! transient_heap_evacuate: skip while transient_heap_marking\n");
}
else {
VALUE gc_disabled = rb_gc_disable_no_rest();
- struct transient_heap_block* block;
+ {
+ struct transient_heap_block* block;
+
+ RUBY_DEBUG_LOG("start gc_disabled:%d", RTEST(gc_disabled));
- if (TRANSIENT_HEAP_DEBUG >= 1) {
- int i;
- fprintf(stderr, "!! transient_heap_evacuate start total_blocks:%d\n", theap->total_blocks);
- if (TRANSIENT_HEAP_DEBUG >= 4) {
- for (i=0; i<theap->promoted_objects_index; i++) fprintf(stderr, "%4d %s\n", i, rb_obj_info(theap->promoted_objects[i]));
+ if (TRANSIENT_HEAP_DEBUG >= 1) {
+ int i;
+ fprintf(stderr, "!! transient_heap_evacuate start total_blocks:%d\n", theap->total_blocks);
+ if (TRANSIENT_HEAP_DEBUG >= 4) {
+ for (i=0; i<theap->promoted_objects_index; i++) fprintf(stderr, "%4d %s\n", i, rb_obj_info(theap->promoted_objects[i]));
+ }
}
- }
- if (TRANSIENT_HEAP_DEBUG >= 2) transient_heap_dump(theap);
+ if (TRANSIENT_HEAP_DEBUG >= 2) transient_heap_dump(theap);
- TH_ASSERT(theap->status == transient_heap_none);
- transient_heap_update_status(theap, transient_heap_escaping);
+ TH_ASSERT(theap->status == transient_heap_none);
+ transient_heap_update_status(theap, transient_heap_escaping);
- /* evacuate from marked blocks */
- block = theap->marked_blocks;
- while (block) {
- transient_heap_block_evacuate(theap, block);
- block = block->info.next_block;
- }
+ /* evacuate from marked blocks */
+ block = theap->marked_blocks;
+ while (block) {
+ transient_heap_block_evacuate(theap, block);
+ block = block->info.next_block;
+ }
- /* evacuate from using blocks
+ /* evacuate from using blocks
only affect incremental marking */
- block = theap->using_blocks;
- while (block) {
- transient_heap_block_evacuate(theap, block);
- block = block->info.next_block;
- }
+ block = theap->using_blocks;
+ while (block) {
+ transient_heap_block_evacuate(theap, block);
+ block = block->info.next_block;
+ }
- /* all objects in marked_objects are escaped. */
- transient_heap_reset();
+ /* all objects in marked_objects are escaped. */
+ transient_heap_reset();
- if (TRANSIENT_HEAP_DEBUG > 0) {
- fprintf(stderr, "!! transient_heap_evacuate end total_blocks:%d\n", theap->total_blocks);
- }
+ if (TRANSIENT_HEAP_DEBUG > 0) {
+ fprintf(stderr, "!! transient_heap_evacuate end total_blocks:%d\n", theap->total_blocks);
+ }
- transient_heap_verify(theap);
- transient_heap_update_status(theap, transient_heap_none);
+ transient_heap_verify(theap);
+ transient_heap_update_status(theap, transient_heap_none);
+ }
if (gc_disabled != Qtrue) rb_gc_enable();
+ RUBY_DEBUG_LOG("finish", 0);
}
}
+void
+rb_transient_heap_evacuate(void)
+{
+ transient_heap_evacuate(NULL);
+}
+
static void
clear_marked_index(struct transient_heap_block* block)
{
@@ -817,26 +867,17 @@ blocks_clear_marked_index(struct transient_heap_block* block)
static void
transient_heap_block_update_refs(struct transient_heap* theap, struct transient_heap_block* block)
{
- int i=0, n=0;
+ int marked_index = block->info.last_marked_index;
- while (i<block->info.index) {
- void *ptr = &block->buff[i];
- struct transient_alloc_header *header = ptr;
+ while (marked_index >= 0) {
+ struct transient_alloc_header *header = alloc_header(block, marked_index);
asan_unpoison_memory_region(header, sizeof *header, false);
- void *poisoned = __asan_region_is_poisoned((void *)header->obj, SIZEOF_VALUE);
- asan_unpoison_object(header->obj, false);
-
header->obj = rb_gc_location(header->obj);
- if (poisoned) {
- asan_poison_object(header->obj);
- }
-
- i += header->size;
+ marked_index = header->next_marked_index;
asan_poison_memory_region(header, sizeof *header);
- n++;
}
}
@@ -852,6 +893,8 @@ transient_heap_blocks_update_refs(struct transient_heap* theap, struct transient
void
rb_transient_heap_update_references(void)
{
+ ASSERT_vm_locking();
+
struct transient_heap* theap = transient_heap_get();
int i;
@@ -867,9 +910,12 @@ rb_transient_heap_update_references(void)
void
rb_transient_heap_start_marking(int full_marking)
{
+ ASSERT_vm_locking();
+ RUBY_DEBUG_LOG("full?:%d", full_marking);
+
struct transient_heap* theap = transient_heap_get();
- if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! rb_transient_heap_start_marking objects:%d blocks:%d promtoed:%d full_marking:%d\n",
+ if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! rb_transient_heap_start_marking objects:%d blocks:%d promoted:%d full_marking:%d\n",
theap->total_objects, theap->total_blocks, theap->promoted_objects_index, full_marking);
if (TRANSIENT_HEAP_DEBUG >= 2) transient_heap_dump(theap);
@@ -915,11 +961,14 @@ rb_transient_heap_start_marking(int full_marking)
void
rb_transient_heap_finish_marking(void)
{
+ ASSERT_vm_locking();
+ RUBY_DEBUG_LOG("", 0);
+
struct transient_heap* theap = transient_heap_get();
- if (TRANSIENT_HEAP_DEBUG >= 1) fprintf(stderr, "!! rb_transient_heap_finish_marking objects:%d, marked:%d\n",
- theap->total_objects,
- theap->total_marked_objects);
+ RUBY_DEBUG_LOG("objects:%d, marked:%d",
+ theap->total_objects,
+ theap->total_marked_objects);
if (TRANSIENT_HEAP_DEBUG >= 2) transient_heap_dump(theap);
TH_ASSERT(theap->total_objects >= theap->total_marked_objects);
diff --git a/transient_heap.h b/transient_heap.h
index 7b5c42ca8e..4ac52aad07 100644
--- a/transient_heap.h
+++ b/transient_heap.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_TRANSIENT_HEAP_H
+#define RUBY_TRANSIENT_HEAP_H
/**********************************************************************
transient_heap.h - declarations of transient_heap related APIs.
@@ -6,9 +8,6 @@
**********************************************************************/
-#ifndef RUBY_TRANSIENT_HEAP_H
-#define RUBY_TRANSIENT_HEAP_H
-
#include "internal.h"
#if USE_TRANSIENT_HEAP
@@ -32,6 +31,9 @@ void rb_transient_heap_start_marking(int full_marking);
void rb_transient_heap_finish_marking(void);
void rb_transient_heap_update_references(void);
+/* used by ractor.c */
+void rb_transient_heap_evacuate(void);
+
/* for debug API */
void rb_transient_heap_dump(void);
void rb_transient_heap_verify(void);
@@ -50,6 +52,7 @@ void rb_struct_transient_heap_evacuate(VALUE st, int promote);
#define rb_transient_heap_promote(obj) ((void)0)
#define rb_transient_heap_start_marking(full_marking) ((void)0)
#define rb_transient_heap_update_references() ((void)0)
+#define rb_transient_heap_evacuate() ((void)0)
#define rb_transient_heap_finish_marking() ((void)0)
#define rb_transient_heap_mark(obj, ptr) ((void)0)
diff --git a/util.c b/util.c
index aa8e7ef3f2..8ec0cd60e5 100644
--- a/util.c
+++ b/util.c
@@ -10,22 +10,26 @@
**********************************************************************/
#if defined __MINGW32__ || defined __MINGW64__
-#define MINGW_HAS_SECURE_API 1
+# define MINGW_HAS_SECURE_API 1
#endif
-#include "internal.h"
+#include "ruby/internal/config.h"
#include <ctype.h>
-#include <stdio.h>
#include <errno.h>
-#include <math.h>
#include <float.h>
+#include <math.h>
+#include <stdio.h>
#ifdef _WIN32
-#include "missing/file.h"
+# include "missing/file.h"
#endif
+#include "internal.h"
+#include "internal/sanitizers.h"
+#include "internal/util.h"
#include "ruby/util.h"
+#include "ruby_atomic.h"
const char ruby_hexdigits[] = "0123456789abcdef0123456789ABCDEF";
#define hexdigit ruby_hexdigits
diff --git a/util/remove_openssl.rb b/util/remove_openssl.rb
new file mode 100644
index 0000000000..a98f227f28
--- /dev/null
+++ b/util/remove_openssl.rb
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+require "rbconfig"
+require "fileutils"
+
+class OpensslSimulator
+ attr_reader :openssl_rb, :openssl_gemspec, :openssl_ext
+
+ def initialize
+ archdir = RbConfig::CONFIG["archdir"]
+ rubylibdir = RbConfig::CONFIG["rubylibdir"]
+ default_specifications_dir = Gem.default_specifications_dir
+
+ @openssl_rb = File.join(rubylibdir, "openssl.rb")
+ @openssl_gemspec = Dir.glob("#{default_specifications_dir}/openssl-*.gemspec").first
+
+ @openssl_ext = if RUBY_PLATFORM == "java"
+ File.join(rubylibdir, "jopenssl.jar")
+ else
+ File.join(archdir, "openssl.so")
+ end
+ end
+
+ def hide_openssl
+ hide_file openssl_rb
+ hide_file openssl_ext
+ hide_file openssl_gemspec if openssl_gemspec
+ end
+
+ def unhide_openssl
+ unhide_file openssl_gemspec if openssl_gemspec
+ unhide_file openssl_ext
+ unhide_file openssl_rb
+ end
+
+ private
+
+ def hide_file(file)
+ FileUtils.mv file, file + "_"
+ end
+
+ def unhide_file(file)
+ FileUtils.mv file + "_", file
+ end
+end
+
+if $0 == __FILE__
+ openssl_simulate = OpensslSimulator.new
+
+ if ARGV[0] == "--revert"
+ openssl_simulate.unhide_openssl
+ else
+ openssl_simulate.hide_openssl
+ end
+end
diff --git a/variable.c b/variable.c
index 3146168924..74a7f59790 100644
--- a/variable.c
+++ b/variable.c
@@ -11,19 +11,35 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/st.h"
-#include "ruby/util.h"
-#include "internal.h"
-#include "id_table.h"
+#include "ruby/internal/config.h"
+#include <stddef.h>
+#include "ruby/internal/stdbool.h"
+#include "ccan/list/list.h"
#include "constant.h"
+#include "debug_counter.h"
#include "id.h"
-#include "ccan/list/list.h"
#include "id_table.h"
-#include "debug_counter.h"
-#include "vm_core.h"
+#include "internal.h"
+#include "internal/class.h"
+#include "internal/compilers.h"
+#include "internal/error.h"
+#include "internal/eval.h"
+#include "internal/hash.h"
+#include "internal/object.h"
+#include "internal/re.h"
+#include "internal/symbol.h"
+#include "internal/thread.h"
+#include "internal/variable.h"
+#include "ruby/encoding.h"
+#include "ruby/st.h"
+#include "ruby/util.h"
#include "transient_heap.h"
#include "variable.h"
+#include "vm_core.h"
+#include "ractor_core.h"
+#include "vm_sync.h"
+
+typedef void rb_gvar_compact_t(void *var);
static struct rb_id_table *rb_global_tbl;
static ID autoload, classpath, tmp_classpath;
@@ -32,8 +48,7 @@ static VALUE autoload_featuremap; /* feature => autoload_i */
static void check_before_mod_set(VALUE, ID, VALUE, const char *);
static void setup_const_entry(rb_const_entry_t *, VALUE, VALUE, rb_const_flag_t);
static VALUE rb_const_search(VALUE klass, ID id, int exclude, int recurse, int visibility);
-static st_table *generic_iv_tbl;
-static st_table *generic_iv_tbl_compat;
+static st_table *generic_iv_tbl_;
struct ivar_update {
union {
@@ -48,7 +63,7 @@ void
Init_var_tables(void)
{
rb_global_tbl = rb_id_table_create(0);
- generic_iv_tbl = st_init_numtable();
+ generic_iv_tbl_ = st_init_numtable();
autoload = rb_intern_const("__autoload__");
/* __classpath__: fully qualified class path */
classpath = rb_intern_const("__classpath__");
@@ -62,6 +77,7 @@ rb_namespace_p(VALUE obj)
if (RB_SPECIAL_CONST_P(obj)) return false;
switch (RB_BUILTIN_TYPE(obj)) {
case T_MODULE: case T_CLASS: return true;
+ default: break;
}
return false;
}
@@ -248,9 +264,7 @@ rb_path_to_class(VALUE pathname)
pbeg = p;
}
if (!id) {
- undefined_class:
- rb_raise(rb_eArgError, "undefined class/module % "PRIsVALUE,
- rb_str_subseq(pathname, 0, p-path));
+ goto undefined_class;
}
c = rb_const_search(c, id, TRUE, FALSE, FALSE);
if (c == Qundef) goto undefined_class;
@@ -262,6 +276,11 @@ rb_path_to_class(VALUE pathname)
RB_GC_GUARD(pathname);
return c;
+
+ undefined_class:
+ rb_raise(rb_eArgError, "undefined class/module % "PRIsVALUE,
+ rb_str_subseq(pathname, 0, p-path));
+ UNREACHABLE_RETURN(Qundef);
}
VALUE
@@ -305,9 +324,16 @@ struct rb_global_variable {
rb_gvar_getter_t *getter;
rb_gvar_setter_t *setter;
rb_gvar_marker_t *marker;
+ rb_gvar_compact_t *compactor;
struct trace_var *trace;
};
+struct rb_global_entry {
+ struct rb_global_variable *var;
+ ID id;
+ bool ractor_local;
+};
+
static struct rb_global_entry*
rb_find_global_entry(ID id)
{
@@ -315,14 +341,33 @@ rb_find_global_entry(ID id)
VALUE data;
if (!rb_id_table_lookup(rb_global_tbl, id, &data)) {
- return NULL;
+ entry = NULL;
}
- entry = (struct rb_global_entry *)data;
- ASSUME(entry != NULL);
+ else {
+ entry = (struct rb_global_entry *)data;
+ RUBY_ASSERT(entry != NULL);
+ }
+
+ if (UNLIKELY(!rb_ractor_main_p()) && (!entry || !entry->ractor_local)) {
+ rb_raise(rb_eRactorIsolationError, "can not access global variables %s from non-main Ractors", rb_id2name(id));
+ }
+
return entry;
}
-MJIT_FUNC_EXPORTED struct rb_global_entry*
+void
+rb_gvar_ractor_local(const char *name)
+{
+ struct rb_global_entry *entry = rb_find_global_entry(rb_intern(name));
+ entry->ractor_local = true;
+}
+
+static void
+rb_gvar_undef_compactor(void *var)
+{
+}
+
+static struct rb_global_entry*
rb_global_entry(ID id)
{
struct rb_global_entry *entry = rb_find_global_entry(id);
@@ -332,11 +377,13 @@ rb_global_entry(ID id)
var = ALLOC(struct rb_global_variable);
entry->id = id;
entry->var = var;
+ entry->ractor_local = false;
var->counter = 1;
var->data = 0;
var->getter = rb_gvar_undef_getter;
var->setter = rb_gvar_undef_setter;
var->marker = rb_gvar_undef_marker;
+ var->compactor = rb_gvar_undef_compactor;
var->block_trace = 0;
var->trace = 0;
@@ -353,6 +400,21 @@ rb_gvar_undef_getter(ID id, VALUE *_)
return Qnil;
}
+static void
+rb_gvar_val_compactor(void *_var)
+{
+ struct rb_global_variable *var = (struct rb_global_variable *)_var;
+
+ VALUE obj = (VALUE)var->data;
+
+ if (obj) {
+ VALUE new = rb_gc_location(obj);
+ if (new != obj) {
+ var->data = (void*)new;
+ }
+ }
+}
+
void
rb_gvar_undef_setter(VALUE val, ID id, VALUE *_)
{
@@ -360,6 +422,7 @@ rb_gvar_undef_setter(VALUE val, ID id, VALUE *_)
var->getter = rb_gvar_val_getter;
var->setter = rb_gvar_val_setter;
var->marker = rb_gvar_val_marker;
+ var->compactor = rb_gvar_val_compactor;
var->data = (void*)val;
}
@@ -386,7 +449,7 @@ void
rb_gvar_val_marker(VALUE *var)
{
VALUE data = (VALUE)var;
- if (data) rb_gc_mark_maybe(data);
+ if (data) rb_gc_mark_movable(data);
}
VALUE
@@ -433,8 +496,27 @@ mark_global_entry(VALUE v, void *ignored)
void
rb_gc_mark_global_tbl(void)
{
- if (rb_global_tbl)
+ if (rb_global_tbl) {
rb_id_table_foreach_values(rb_global_tbl, mark_global_entry, 0);
+ }
+}
+
+static enum rb_id_table_iterator_result
+update_global_entry(VALUE v, void *ignored)
+{
+ struct rb_global_entry *entry = (struct rb_global_entry *)v;
+ struct rb_global_variable *var = entry->var;
+
+ (*var->compactor)(var);
+ return ID_TABLE_CONTINUE;
+}
+
+void
+rb_gc_update_global_tbl(void)
+{
+ if (rb_global_tbl) {
+ rb_id_table_foreach_values(rb_global_tbl, update_global_entry, 0);
+ }
}
static ID
@@ -577,18 +659,17 @@ rb_f_untrace_var(int argc, const VALUE *argv)
ID id;
struct rb_global_entry *entry;
struct trace_var *trace;
- VALUE data;
rb_scan_args(argc, argv, "11", &var, &cmd);
id = rb_check_id(&var);
if (!id) {
rb_name_error_str(var, "undefined global variable %"PRIsVALUE"", QUOTE(var));
}
- if (!rb_id_table_lookup(rb_global_tbl, id, &data)) {
+ if ((entry = rb_find_global_entry(id)) == NULL) {
rb_name_error(id, "undefined global variable %"PRIsVALUE"", QUOTE_ID(id));
}
- trace = (entry = (struct rb_global_entry *)data)->var->trace;
+ trace = entry->var->trace;
if (NIL_P(cmd)) {
VALUE ary = rb_ary_new();
@@ -615,13 +696,6 @@ rb_f_untrace_var(int argc, const VALUE *argv)
return Qnil;
}
-MJIT_FUNC_EXPORTED VALUE
-rb_gvar_get(struct rb_global_entry *entry)
-{
- struct rb_global_variable *var = entry->var;
- return (*var->getter)(entry->id, var->data);
-}
-
struct trace_data {
struct trace_var *trace;
VALUE val;
@@ -650,8 +724,8 @@ trace_en(VALUE v)
return Qnil; /* not reached */
}
-MJIT_FUNC_EXPORTED VALUE
-rb_gvar_set(struct rb_global_entry *entry, VALUE val)
+static VALUE
+rb_gvar_set_entry(struct rb_global_entry *entry, VALUE val)
{
struct trace_data trace;
struct rb_global_variable *var = entry->var;
@@ -668,18 +742,31 @@ rb_gvar_set(struct rb_global_entry *entry, VALUE val)
}
VALUE
-rb_gv_set(const char *name, VALUE val)
+rb_gvar_set(ID id, VALUE val)
{
struct rb_global_entry *entry;
+ entry = rb_global_entry(id);
+
+ return rb_gvar_set_entry(entry, val);
+}
- entry = rb_global_entry(global_id(name));
- return rb_gvar_set(entry, val);
+VALUE
+rb_gv_set(const char *name, VALUE val)
+{
+ return rb_gvar_set(global_id(name), val);
+}
+
+VALUE
+rb_gvar_get(ID id)
+{
+ struct rb_global_entry *entry = rb_global_entry(id);
+ struct rb_global_variable *var = entry->var;
+ return (*var->getter)(entry->id, var->data);
}
VALUE
rb_gv_get(const char *name)
{
- struct rb_global_entry *entry;
ID id = find_global_id(name);
if (!id) {
@@ -687,35 +774,31 @@ rb_gv_get(const char *name)
return Qnil;
}
- entry = rb_global_entry(id);
- return rb_gvar_get(entry);
+ return rb_gvar_get(id);
}
MJIT_FUNC_EXPORTED VALUE
-rb_gvar_defined(struct rb_global_entry *entry)
+rb_gvar_defined(ID id)
{
+ struct rb_global_entry *entry = rb_global_entry(id);
if (entry->var->getter == rb_gvar_undef_getter) return Qfalse;
return Qtrue;
}
rb_gvar_getter_t *
-rb_gvar_getter_function_of(const struct rb_global_entry *entry)
+rb_gvar_getter_function_of(ID id)
{
+ const struct rb_global_entry *entry = rb_global_entry(id);
return entry->var->getter;
}
rb_gvar_setter_t *
-rb_gvar_setter_function_of(const struct rb_global_entry *entry)
+rb_gvar_setter_function_of(ID id)
{
+ const struct rb_global_entry *entry = rb_global_entry(id);
return entry->var->setter;
}
-bool
-rb_gvar_is_traced(const struct rb_global_entry *entry)
-{
- return !!entry->var->trace;
-}
-
static enum rb_id_table_iterator_result
gvar_i(ID key, VALUE val, void *a)
{
@@ -730,6 +813,10 @@ rb_f_global_variables(void)
VALUE ary = rb_ary_new();
VALUE sym, backref = rb_backref_get();
+ if (!rb_ractor_main_p()) {
+ rb_raise(rb_eRactorIsolationError, "can not access global variables from non-main Ractors");
+ }
+
rb_id_table_foreach(rb_global_tbl, gvar_i, (void *)ary);
if (!NIL_P(backref)) {
char buf[2];
@@ -757,12 +844,17 @@ rb_alias_variable(ID name1, ID name2)
{
struct rb_global_entry *entry1, *entry2;
VALUE data1;
+ struct rb_id_table *gtbl = rb_global_tbl;
+
+ if (!rb_ractor_main_p()) {
+ rb_raise(rb_eRactorIsolationError, "can not access global variables from non-main Ractors");
+ }
entry2 = rb_global_entry(name2);
- if (!rb_id_table_lookup(rb_global_tbl, name1, &data1)) {
+ if (!rb_id_table_lookup(gtbl, name1, &data1)) {
entry1 = ALLOC(struct rb_global_entry);
entry1->id = name1;
- rb_id_table_insert(rb_global_tbl, name1, (VALUE)entry1);
+ rb_id_table_insert(gtbl, name1, (VALUE)entry1);
}
else if ((entry1 = (struct rb_global_entry *)data1)->var != entry2->var) {
struct rb_global_variable *var = entry1->var;
@@ -787,22 +879,102 @@ rb_alias_variable(ID name1, ID name2)
entry1->var = entry2->var;
}
+static bool
+iv_index_tbl_lookup(struct st_table *tbl, ID id, uint32_t *indexp)
+{
+ struct rb_iv_index_tbl_entry *ent;
+ int r;
+
+ if (tbl == NULL) return false;
+
+ RB_VM_LOCK_ENTER();
+ {
+ r = st_lookup(tbl, (st_data_t)id, (st_data_t *)&ent);
+ }
+ RB_VM_LOCK_LEAVE();
+
+ if (r) {
+ *indexp = ent->index;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static void
+IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(ID id)
+{
+ if (UNLIKELY(!rb_ractor_main_p())) {
+ if (rb_is_instance_id(id)) { // check only normal ivars
+ rb_raise(rb_eRactorIsolationError, "can not access instance variables of classes/modules from non-main Ractors");
+ }
+ }
+}
+
+#define CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() \
+ if (UNLIKELY(!rb_ractor_main_p())) { \
+ rb_raise(rb_eRactorIsolationError, "can not access class variables from non-main Ractors"); \
+ }
+
+static inline struct st_table *
+generic_ivtbl(VALUE obj, ID id, bool force_check_ractor)
+{
+ ASSERT_vm_locking();
+
+ if ((force_check_ractor || LIKELY(rb_is_instance_id(id)) /* not internal ID */ ) &&
+ !RB_OBJ_FROZEN_RAW(obj) &&
+ UNLIKELY(!rb_ractor_main_p()) &&
+ UNLIKELY(rb_ractor_shareable_p(obj))) {
+
+ rb_raise(rb_eRactorIsolationError, "can not access instance variables of shareable objects from non-main Ractors");
+ }
+ return generic_iv_tbl_;
+}
+
+static inline struct st_table *
+generic_ivtbl_no_ractor_check(VALUE obj)
+{
+ return generic_ivtbl(obj, 0, false);
+}
+
static int
-gen_ivtbl_get(VALUE obj, struct gen_ivtbl **ivtbl)
+gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl)
{
st_data_t data;
+ int r = 0;
- if (st_lookup(generic_iv_tbl, (st_data_t)obj, &data)) {
- *ivtbl = (struct gen_ivtbl *)data;
- return 1;
+ RB_VM_LOCK_ENTER();
+ {
+ if (st_lookup(generic_ivtbl(obj, id, false), (st_data_t)obj, &data)) {
+ *ivtbl = (struct gen_ivtbl *)data;
+ r = 1;
+ }
}
- return 0;
+ RB_VM_LOCK_LEAVE();
+
+ return r;
+}
+
+MJIT_FUNC_EXPORTED int
+rb_ivar_generic_ivtbl_lookup(VALUE obj, struct gen_ivtbl **ivtbl)
+{
+ return gen_ivtbl_get(obj, 0, ivtbl);
}
-MJIT_FUNC_EXPORTED struct st_table *
-rb_ivar_generic_ivtbl(void)
+MJIT_FUNC_EXPORTED VALUE
+rb_ivar_generic_lookup_with_index(VALUE obj, ID id, uint32_t index)
{
- return generic_iv_tbl;
+ struct gen_ivtbl *ivtbl;
+
+ if (gen_ivtbl_get(obj, id, &ivtbl)) {
+ if (LIKELY(index < ivtbl->numiv)) {
+ VALUE val = ivtbl->ivptr[index];
+ return val;
+ }
+ }
+
+ return Qundef;
}
static VALUE
@@ -810,11 +982,11 @@ generic_ivar_delete(VALUE obj, ID id, VALUE undef)
{
struct gen_ivtbl *ivtbl;
- if (gen_ivtbl_get(obj, &ivtbl)) {
+ if (gen_ivtbl_get(obj, id, &ivtbl)) {
st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
- st_data_t index;
+ uint32_t index;
- if (st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
+ if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &index)) {
if (index < ivtbl->numiv) {
VALUE ret = ivtbl->ivptr[index];
@@ -831,11 +1003,11 @@ generic_ivar_get(VALUE obj, ID id, VALUE undef)
{
struct gen_ivtbl *ivtbl;
- if (gen_ivtbl_get(obj, &ivtbl)) {
+ if (gen_ivtbl_get(obj, id, &ivtbl)) {
st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
- st_data_t index;
+ uint32_t index;
- if (st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
+ if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &index)) {
if (index < ivtbl->numiv) {
VALUE ret = ivtbl->ivptr[index];
@@ -882,42 +1054,36 @@ gen_ivtbl_dup(const struct gen_ivtbl *orig)
static uint32_t
iv_index_tbl_newsize(struct ivar_update *ivup)
{
- uint32_t index = (uint32_t)ivup->index; /* should not overflow */
- uint32_t newsize = (index+1) + (index+1)/4; /* (index+1)*1.25 */
-
- if (!ivup->iv_extended &&
- ivup->u.iv_index_tbl->num_entries < (st_index_t)newsize) {
- newsize = (uint32_t)ivup->u.iv_index_tbl->num_entries;
+ if (!ivup->iv_extended) {
+ return (uint32_t)ivup->u.iv_index_tbl->num_entries;
+ }
+ else {
+ uint32_t index = (uint32_t)ivup->index; /* should not overflow */
+ return (index+1) + (index+1)/4; /* (index+1)*1.25 */
}
- return newsize;
}
static int
generic_ivar_update(st_data_t *k, st_data_t *v, st_data_t u, int existing)
{
- VALUE obj = (VALUE)*k;
+ ASSERT_vm_locking();
+
struct ivar_update *ivup = (struct ivar_update *)u;
- uint32_t newsize;
- int ret = ST_CONTINUE;
- struct gen_ivtbl *ivtbl;
+ struct gen_ivtbl *ivtbl = 0;
if (existing) {
ivtbl = (struct gen_ivtbl *)*v;
- if (ivup->index >= ivtbl->numiv) {
- goto resize;
- }
- ret = ST_STOP;
- }
- else {
- FL_SET(obj, FL_EXIVAR);
- ivtbl = 0;
-resize:
- newsize = iv_index_tbl_newsize(ivup);
- ivtbl = gen_ivtbl_resize(ivtbl, newsize);
- *v = (st_data_t)ivtbl;
+ if (ivup->index < ivtbl->numiv) {
+ ivup->u.ivtbl = ivtbl;
+ return ST_STOP;
+ }
}
+ FL_SET((VALUE)*k, FL_EXIVAR);
+ uint32_t newsize = iv_index_tbl_newsize(ivup);
+ ivtbl = gen_ivtbl_resize(ivtbl, newsize);
+ *v = (st_data_t)ivtbl;
ivup->u.ivtbl = ivtbl;
- return ret;
+ return ST_CONTINUE;
}
static VALUE
@@ -925,11 +1091,10 @@ generic_ivar_defined(VALUE obj, ID id)
{
struct gen_ivtbl *ivtbl;
st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
- st_data_t index;
+ uint32_t index;
- if (!iv_index_tbl) return Qfalse;
- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) return Qfalse;
- if (!gen_ivtbl_get(obj, &ivtbl)) return Qfalse;
+ if (!iv_index_tbl_lookup(iv_index_tbl, id, &index)) return Qfalse;
+ if (!gen_ivtbl_get(obj, id, &ivtbl)) return Qfalse;
if ((index < ivtbl->numiv) && (ivtbl->ivptr[index] != Qundef))
return Qtrue;
@@ -941,13 +1106,12 @@ static int
generic_ivar_remove(VALUE obj, ID id, VALUE *valp)
{
struct gen_ivtbl *ivtbl;
- st_data_t key = (st_data_t)id;
- st_data_t index;
+ uint32_t index;
st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
if (!iv_index_tbl) return 0;
- if (!st_lookup(iv_index_tbl, key, &index)) return 0;
- if (!gen_ivtbl_get(obj, &ivtbl)) return 0;
+ if (!iv_index_tbl_lookup(iv_index_tbl, id, &index)) return 0;
+ if (!gen_ivtbl_get(obj, id, &ivtbl)) return 0;
if (index < ivtbl->numiv) {
if (ivtbl->ivptr[index] != Qundef) {
@@ -974,7 +1138,7 @@ rb_mark_generic_ivar(VALUE obj)
{
struct gen_ivtbl *ivtbl;
- if (gen_ivtbl_get(obj, &ivtbl)) {
+ if (gen_ivtbl_get(obj, 0, &ivtbl)) {
gen_ivtbl_mark(ivtbl);
}
}
@@ -985,8 +1149,8 @@ rb_mv_generic_ivar(VALUE rsrc, VALUE dst)
st_data_t key = (st_data_t)rsrc;
struct gen_ivtbl *ivtbl;
- if (st_delete(generic_iv_tbl, &key, (st_data_t *)&ivtbl))
- st_insert(generic_iv_tbl, (st_data_t)dst, (st_data_t)ivtbl);
+ if (st_delete(generic_ivtbl_no_ractor_check(rsrc), &key, (st_data_t *)&ivtbl))
+ st_insert(generic_ivtbl_no_ractor_check(dst), (st_data_t)dst, (st_data_t)ivtbl);
}
void
@@ -995,15 +1159,8 @@ rb_free_generic_ivar(VALUE obj)
st_data_t key = (st_data_t)obj;
struct gen_ivtbl *ivtbl;
- if (st_delete(generic_iv_tbl, &key, (st_data_t *)&ivtbl))
+ if (st_delete(generic_ivtbl_no_ractor_check(obj), &key, (st_data_t *)&ivtbl))
xfree(ivtbl);
-
- if (generic_iv_tbl_compat) {
- st_table *tbl;
-
- if (st_delete(generic_iv_tbl_compat, &key, (st_data_t *)&tbl))
- st_free_table(tbl);
- }
}
RUBY_FUNC_EXPORTED size_t
@@ -1011,7 +1168,7 @@ rb_generic_ivar_memsize(VALUE obj)
{
struct gen_ivtbl *ivtbl;
- if (gen_ivtbl_get(obj, &ivtbl))
+ if (gen_ivtbl_get(obj, 0, &ivtbl))
return gen_ivtbl_bytes(ivtbl->numiv);
return 0;
}
@@ -1034,30 +1191,37 @@ gen_ivtbl_count(const struct gen_ivtbl *ivtbl)
VALUE
rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
{
- VALUE val, *ptr;
- struct st_table *iv_index_tbl;
- uint32_t len;
- st_data_t index;
+ VALUE val;
if (SPECIAL_CONST_P(obj)) return undef;
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- len = ROBJECT_NUMIV(obj);
- ptr = ROBJECT_IVPTR(obj);
- iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
- if (!iv_index_tbl) break;
- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
- if (len <= index) break;
- val = ptr[index];
- if (val != Qundef)
- return val;
- break;
+ {
+ uint32_t index;
+ uint32_t len = ROBJECT_NUMIV(obj);
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+
+ if (iv_index_tbl_lookup(ROBJECT_IV_INDEX_TBL(obj), id, &index) &&
+ index < len &&
+ (val = ptr[index]) != Qundef) {
+ return val;
+ }
+ else {
+ break;
+ }
+ }
case T_CLASS:
case T_MODULE:
- if (RCLASS_IV_TBL(obj) &&
- st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, &index))
- return (VALUE)index;
- break;
+ {
+ IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
+ if (RCLASS_IV_TBL(obj) &&
+ st_lookup(RCLASS_IV_TBL(obj), (st_data_t)id, (st_data_t *)&val)) {
+ return val;
+ }
+ else {
+ break;
+ }
+ }
default:
if (FL_TEST(obj, FL_EXIVAR))
return generic_ivar_get(obj, id, undef);
@@ -1069,14 +1233,8 @@ rb_ivar_lookup(VALUE obj, ID id, VALUE undef)
VALUE
rb_ivar_get(VALUE obj, ID id)
{
- VALUE iv = rb_ivar_lookup(obj, id, Qundef);
+ VALUE iv = rb_ivar_lookup(obj, id, Qnil);
RB_DEBUG_COUNTER_INC(ivar_get_base);
-
- if (iv == Qundef) {
- if (RTEST(ruby_verbose))
- rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id));
- iv = Qnil;
- }
return iv;
}
@@ -1091,8 +1249,7 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
{
VALUE val, *ptr;
struct st_table *iv_index_tbl;
- uint32_t len;
- st_data_t index;
+ uint32_t len, index;
rb_check_frozen(obj);
switch (BUILTIN_TYPE(obj)) {
@@ -1100,19 +1257,23 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef)
len = ROBJECT_NUMIV(obj);
ptr = ROBJECT_IVPTR(obj);
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
- if (!iv_index_tbl) break;
- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
- if (len <= index) break;
- val = ptr[index];
- ptr[index] = Qundef;
- if (val != Qundef)
- return val;
- break;
+ if (iv_index_tbl_lookup(iv_index_tbl, id, &index) &&
+ index < len) {
+ val = ptr[index];
+ ptr[index] = Qundef;
+
+ if (val != Qundef) {
+ return val;
+ }
+ }
+ break;
case T_CLASS:
case T_MODULE:
+ IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
if (RCLASS_IV_TBL(obj) &&
- st_delete(RCLASS_IV_TBL(obj), (st_data_t *)&id, &index))
- return (VALUE)index;
+ st_delete(RCLASS_IV_TBL(obj), (st_data_t *)&id, (st_data_t *)&val)) {
+ return val;
+ }
break;
default:
if (FL_TEST(obj, FL_EXIVAR))
@@ -1129,42 +1290,61 @@ rb_attr_delete(VALUE obj, ID id)
}
static st_table *
-iv_index_tbl_make(VALUE obj)
+iv_index_tbl_make(VALUE obj, VALUE klass)
{
- VALUE klass = rb_obj_class(obj);
- st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(klass);
+ st_table *iv_index_tbl;
+
+ if (UNLIKELY(!klass)) {
+ rb_raise(rb_eTypeError, "hidden object cannot have instance variables");
+ }
- if (!iv_index_tbl) {
- iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable();
+ if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) {
+ RB_VM_LOCK_ENTER();
+ if ((iv_index_tbl = RCLASS_IV_INDEX_TBL(klass)) == NULL) {
+ iv_index_tbl = RCLASS_IV_INDEX_TBL(klass) = st_init_numtable();
+ }
+ RB_VM_LOCK_LEAVE();
}
return iv_index_tbl;
}
static void
-iv_index_tbl_extend(struct ivar_update *ivup, ID id)
+iv_index_tbl_extend(struct ivar_update *ivup, ID id, VALUE klass)
{
- if (st_lookup(ivup->u.iv_index_tbl, (st_data_t)id, &ivup->index)) {
+ ASSERT_vm_locking();
+ struct rb_iv_index_tbl_entry *ent;
+
+ if (st_lookup(ivup->u.iv_index_tbl, (st_data_t)id, (st_data_t *)&ent)) {
+ ivup->index = ent->index;
return;
}
if (ivup->u.iv_index_tbl->num_entries >= INT_MAX) {
rb_raise(rb_eArgError, "too many instance variables");
}
- ivup->index = (st_data_t)ivup->u.iv_index_tbl->num_entries;
- st_add_direct(ivup->u.iv_index_tbl, (st_data_t)id, ivup->index);
+ ent = ALLOC(struct rb_iv_index_tbl_entry);
+ ent->index = ivup->index = (uint32_t)ivup->u.iv_index_tbl->num_entries;
+ ent->class_value = klass;
+ ent->class_serial = RCLASS_SERIAL(klass);
+ st_add_direct(ivup->u.iv_index_tbl, (st_data_t)id, (st_data_t)ent);
ivup->iv_extended = 1;
}
static void
generic_ivar_set(VALUE obj, ID id, VALUE val)
{
+ VALUE klass = rb_obj_class(obj);
struct ivar_update ivup;
-
ivup.iv_extended = 0;
- ivup.u.iv_index_tbl = iv_index_tbl_make(obj);
- iv_index_tbl_extend(&ivup, id);
- st_update(generic_iv_tbl, (st_data_t)obj, generic_ivar_update,
- (st_data_t)&ivup);
+ ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass);
+
+ RB_VM_LOCK_ENTER();
+ {
+ iv_index_tbl_extend(&ivup, id, klass);
+ st_update(generic_ivtbl(obj, id, false), (st_data_t)obj, generic_ivar_update,
+ (st_data_t)&ivup);
+ }
+ RB_VM_LOCK_LEAVE();
ivup.u.ivtbl->ivptr[ivup.index] = val;
@@ -1232,44 +1412,56 @@ rb_obj_transient_heap_evacuate(VALUE obj, int promote)
}
#endif
+static void
+init_iv_list(VALUE obj, uint32_t len, uint32_t newsize, st_table *index_tbl)
+{
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+ VALUE *newptr;
+
+ if (RBASIC(obj)->flags & ROBJECT_EMBED) {
+ newptr = obj_ivar_heap_alloc(obj, newsize);
+ MEMCPY(newptr, ptr, VALUE, len);
+ RBASIC(obj)->flags &= ~ROBJECT_EMBED;
+ ROBJECT(obj)->as.heap.ivptr = newptr;
+ } else {
+ newptr = obj_ivar_heap_realloc(obj, len, newsize);
+ }
+
+ for (; len < newsize; len++) {
+ newptr[len] = Qundef;
+ }
+ ROBJECT(obj)->as.heap.numiv = newsize;
+ ROBJECT(obj)->as.heap.iv_index_tbl = index_tbl;
+}
+
+void
+rb_init_iv_list(VALUE obj)
+{
+ st_table *index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ uint32_t newsize = (uint32_t)index_tbl->num_entries;
+ uint32_t len = ROBJECT_NUMIV(obj);
+ init_iv_list(obj, len, newsize, index_tbl);
+}
+
static VALUE
obj_ivar_set(VALUE obj, ID id, VALUE val)
{
+ VALUE klass = rb_obj_class(obj);
struct ivar_update ivup;
- uint32_t i, len;
-
+ uint32_t len;
ivup.iv_extended = 0;
- ivup.u.iv_index_tbl = iv_index_tbl_make(obj);
- iv_index_tbl_extend(&ivup, id);
+ ivup.u.iv_index_tbl = iv_index_tbl_make(obj, klass);
+
+ RB_VM_LOCK_ENTER();
+ {
+ iv_index_tbl_extend(&ivup, id, klass);
+ }
+ RB_VM_LOCK_LEAVE();
+
len = ROBJECT_NUMIV(obj);
if (len <= ivup.index) {
- VALUE *ptr = ROBJECT_IVPTR(obj);
- if (ivup.index < ROBJECT_EMBED_LEN_MAX) {
- RBASIC(obj)->flags |= ROBJECT_EMBED;
- ptr = ROBJECT(obj)->as.ary;
- for (i = 0; i < ROBJECT_EMBED_LEN_MAX; i++) {
- ptr[i] = Qundef;
- }
- }
- else {
- VALUE *newptr;
- uint32_t newsize = iv_index_tbl_newsize(&ivup);
-
- if (RBASIC(obj)->flags & ROBJECT_EMBED) {
- newptr = obj_ivar_heap_alloc(obj, newsize);
- MEMCPY(newptr, ptr, VALUE, len);
- RBASIC(obj)->flags &= ~ROBJECT_EMBED;
- ROBJECT(obj)->as.heap.ivptr = newptr;
- }
- else {
- newptr = obj_ivar_heap_realloc(obj, len, newsize);
- }
- for (; len < newsize; len++) {
- newptr[len] = Qundef;
- }
- ROBJECT(obj)->as.heap.numiv = newsize;
- ROBJECT(obj)->as.heap.iv_index_tbl = ivup.u.iv_index_tbl;
- }
+ uint32_t newsize = iv_index_tbl_newsize(&ivup);
+ init_iv_list(obj, len, newsize, ivup.u.iv_index_tbl);
}
RB_OBJ_WRITE(obj, &ROBJECT_IVPTR(obj)[ivup.index], val);
@@ -1287,6 +1479,7 @@ ivar_set(VALUE obj, ID id, VALUE val)
break;
case T_CLASS:
case T_MODULE:
+ IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
if (!RCLASS_IV_TBL(obj)) RCLASS_IV_TBL(obj) = st_init_numtable();
rb_class_ivar_set(obj, id, val);
break;
@@ -1318,21 +1511,21 @@ rb_ivar_defined(VALUE obj, ID id)
{
VALUE val;
struct st_table *iv_index_tbl;
- st_data_t index;
+ uint32_t index;
if (SPECIAL_CONST_P(obj)) return Qfalse;
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
- if (!iv_index_tbl) break;
- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
- if (ROBJECT_NUMIV(obj) <= index) break;
- val = ROBJECT_IVPTR(obj)[index];
- if (val != Qundef)
+ if (iv_index_tbl_lookup(iv_index_tbl, id, &index) &&
+ index < ROBJECT_NUMIV(obj) &&
+ (val = ROBJECT_IVPTR(obj)[index]) != Qundef) {
return Qtrue;
+ }
break;
case T_CLASS:
case T_MODULE:
+ IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
if (RCLASS_IV_TBL(obj) && st_is_member(RCLASS_IV_TBL(obj), (st_data_t)id))
return Qtrue;
break;
@@ -1345,80 +1538,72 @@ rb_ivar_defined(VALUE obj, ID id)
}
typedef int rb_ivar_foreach_callback_func(ID key, VALUE val, st_data_t arg);
+st_data_t rb_st_nth_key(st_table *tab, st_index_t index);
-struct obj_ivar_tag {
- VALUE obj;
- rb_ivar_foreach_callback_func *func;
- st_data_t arg;
-};
-
-static int
-obj_ivar_i(st_data_t key, st_data_t index, st_data_t arg)
+static ID
+iv_index_tbl_nth_id(st_table *iv_index_tbl, uint32_t index)
{
- struct obj_ivar_tag *data = (struct obj_ivar_tag *)arg;
- if (index < ROBJECT_NUMIV(data->obj)) {
- VALUE val = ROBJECT_IVPTR(data->obj)[index];
- if (val != Qundef) {
- return (data->func)((ID)key, val, data->arg);
+ st_data_t key;
+ RB_VM_LOCK_ENTER();
+ {
+ key = rb_st_nth_key(iv_index_tbl, index);
+ }
+ RB_VM_LOCK_LEAVE();
+ return (ID)key;
+}
+
+static inline bool
+ivar_each_i(st_table *iv_index_tbl, VALUE val, uint32_t i, rb_ivar_foreach_callback_func *func, st_data_t arg)
+{
+ if (val != Qundef) {
+ ID id = iv_index_tbl_nth_id(iv_index_tbl, i);
+ switch (func(id, val, arg)) {
+ case ST_CHECK:
+ case ST_CONTINUE:
+ break;
+ case ST_STOP:
+ return true;
+ default:
+ rb_bug("unreachable");
}
}
- return ST_CONTINUE;
+ return false;
}
static void
obj_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
{
- st_table *tbl;
- struct obj_ivar_tag data;
-
- tbl = ROBJECT_IV_INDEX_TBL(obj);
- if (!tbl)
- return;
-
- data.obj = obj;
- data.func = (int (*)(ID key, VALUE val, st_data_t arg))func;
- data.arg = arg;
-
- st_foreach_safe(tbl, obj_ivar_i, (st_data_t)&data);
-}
-
-struct gen_ivar_tag {
- struct gen_ivtbl *ivtbl;
- rb_ivar_foreach_callback_func *func;
- st_data_t arg;
-};
-
-static int
-gen_ivar_each_i(st_data_t key, st_data_t index, st_data_t data)
-{
- struct gen_ivar_tag *arg = (struct gen_ivar_tag *)data;
+ st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ if (!iv_index_tbl) return;
+ uint32_t i=0;
- if (index < arg->ivtbl->numiv) {
- VALUE val = arg->ivtbl->ivptr[index];
- if (val != Qundef) {
- return (arg->func)((ID)key, val, arg->arg);
+ for (i=0; i < ROBJECT_NUMIV(obj); i++) {
+ VALUE val = ROBJECT_IVPTR(obj)[i];
+ if (ivar_each_i(iv_index_tbl, val, i, func, arg)) {
+ return;
}
}
- return ST_CONTINUE;
}
static void
gen_ivar_each(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
{
- struct gen_ivar_tag data;
+ struct gen_ivtbl *ivtbl;
st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
-
if (!iv_index_tbl) return;
- if (!gen_ivtbl_get(obj, &data.ivtbl)) return;
+ if (!gen_ivtbl_get(obj, 0, &ivtbl)) return;
- data.func = (int (*)(ID key, VALUE val, st_data_t arg))func;
- data.arg = arg;
-
- st_foreach_safe(iv_index_tbl, gen_ivar_each_i, (st_data_t)&data);
+ for (uint32_t i=0; i<ivtbl->numiv; i++) {
+ VALUE val = ivtbl->ivptr[i];
+ if (ivar_each_i(iv_index_tbl, val, i, func, arg)) {
+ return;
+ }
+ }
}
struct givar_copy {
VALUE obj;
+ VALUE klass;
st_table *iv_index_tbl;
struct gen_ivtbl *ivtbl;
};
@@ -1431,7 +1616,13 @@ gen_ivar_copy(ID id, VALUE val, st_data_t arg)
ivup.iv_extended = 0;
ivup.u.iv_index_tbl = c->iv_index_tbl;
- iv_index_tbl_extend(&ivup, id);
+
+ RB_VM_LOCK_ENTER();
+ {
+ iv_index_tbl_extend(&ivup, id, c->klass);
+ }
+ RB_VM_LOCK_LEAVE();
+
if (ivup.index >= c->ivtbl->numiv) {
uint32_t newsize = iv_index_tbl_newsize(&ivup);
c->ivtbl = gen_ivtbl_resize(c->ivtbl, newsize);
@@ -1451,21 +1642,16 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj)
rb_check_frozen(clone);
if (!FL_TEST(obj, FL_EXIVAR)) {
- clear:
- if (FL_TEST(clone, FL_EXIVAR)) {
- rb_free_generic_ivar(clone);
- FL_UNSET(clone, FL_EXIVAR);
- }
- return;
+ goto clear;
}
- if (gen_ivtbl_get(obj, &ivtbl)) {
+ if (gen_ivtbl_get(obj, 0, &ivtbl)) {
struct givar_copy c;
uint32_t i;
if (gen_ivtbl_count(ivtbl) == 0)
goto clear;
- if (gen_ivtbl_get(clone, &c.ivtbl)) {
+ if (gen_ivtbl_get(clone, 0, &c.ivtbl)) {
for (i = 0; i < c.ivtbl->numiv; i++)
c.ivtbl->ivptr[i] = Qundef;
}
@@ -1474,18 +1660,53 @@ rb_copy_generic_ivar(VALUE clone, VALUE obj)
FL_SET(clone, FL_EXIVAR);
}
- c.iv_index_tbl = iv_index_tbl_make(clone);
- c.obj = clone;
+ VALUE klass = rb_obj_class(clone);
+ c.iv_index_tbl = iv_index_tbl_make(clone, klass);
+ c.obj = clone;
+ c.klass = klass;
gen_ivar_each(obj, gen_ivar_copy, (st_data_t)&c);
/*
* c.ivtbl may change in gen_ivar_copy due to realloc,
* no need to free
*/
- st_insert(generic_iv_tbl, (st_data_t)clone, (st_data_t)c.ivtbl);
+ RB_VM_LOCK_ENTER();
+ {
+ generic_ivtbl_no_ractor_check(clone);
+ st_insert(generic_ivtbl_no_ractor_check(obj), (st_data_t)clone, (st_data_t)c.ivtbl);
+ }
+ RB_VM_LOCK_LEAVE();
+ }
+ return;
+
+ clear:
+ if (FL_TEST(clone, FL_EXIVAR)) {
+ rb_free_generic_ivar(clone);
+ FL_UNSET(clone, FL_EXIVAR);
}
}
void
+rb_replace_generic_ivar(VALUE clone, VALUE obj)
+{
+ RUBY_ASSERT(FL_TEST(obj, FL_EXIVAR));
+
+ RB_VM_LOCK_ENTER();
+ {
+ struct gen_ivtbl **ivtbl;
+ if (st_lookup(generic_iv_tbl_, (st_data_t)obj, (st_data_t *)&ivtbl)) {
+ st_insert(generic_iv_tbl_, (st_data_t)clone, (st_data_t)ivtbl);
+ st_delete(generic_iv_tbl_, (st_data_t *)&obj, NULL);
+ }
+ else {
+ rb_bug("unreachable");
+ }
+ }
+ RB_VM_LOCK_LEAVE();
+
+ FL_SET(clone, FL_EXIVAR);
+}
+
+void
rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
{
if (SPECIAL_CONST_P(obj)) return;
@@ -1495,6 +1716,7 @@ rb_ivar_foreach(VALUE obj, rb_ivar_foreach_callback_func *func, st_data_t arg)
break;
case T_CLASS:
case T_MODULE:
+ IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(0);
if (RCLASS_IV_TBL(obj)) {
st_foreach_safe(RCLASS_IV_TBL(obj), func, arg);
}
@@ -1516,7 +1738,7 @@ rb_ivar_count(VALUE obj)
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- if ((tbl = ROBJECT_IV_INDEX_TBL(obj)) != 0) {
+ if (ROBJECT_IV_INDEX_TBL(obj) != 0) {
st_index_t i, count, num = ROBJECT_NUMIV(obj);
const VALUE *const ivptr = ROBJECT_IVPTR(obj);
for (i = count = 0; i < num; ++i) {
@@ -1537,7 +1759,7 @@ rb_ivar_count(VALUE obj)
if (FL_TEST(obj, FL_EXIVAR)) {
struct gen_ivtbl *ivtbl;
- if (gen_ivtbl_get(obj, &ivtbl)) {
+ if (gen_ivtbl_get(obj, 0, &ivtbl)) {
return gen_ivtbl_count(ivtbl);
}
}
@@ -1637,7 +1859,7 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
const ID id = id_for_var(obj, name, an, instance);
st_data_t n, v;
struct st_table *iv_index_tbl;
- st_data_t index;
+ uint32_t index;
rb_check_frozen(obj);
if (!id) {
@@ -1647,17 +1869,16 @@ rb_obj_remove_instance_variable(VALUE obj, VALUE name)
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
- if (!iv_index_tbl) break;
- if (!st_lookup(iv_index_tbl, (st_data_t)id, &index)) break;
- if (ROBJECT_NUMIV(obj) <= index) break;
- val = ROBJECT_IVPTR(obj)[index];
- if (val != Qundef) {
+ if (iv_index_tbl_lookup(iv_index_tbl, id, &index) &&
+ index < ROBJECT_NUMIV(obj) &&
+ (val = ROBJECT_IVPTR(obj)[index]) != Qundef) {
ROBJECT_IVPTR(obj)[index] = Qundef;
return val;
}
break;
case T_CLASS:
case T_MODULE:
+ IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(id);
n = id;
if (RCLASS_IV_TBL(obj) && st_delete(RCLASS_IV_TBL(obj), &n, &v)) {
return (VALUE)v;
@@ -2122,13 +2343,18 @@ autoload_defined_p(VALUE mod, ID id)
static void const_tbl_update(struct autoload_const *);
static VALUE
-autoload_const_set(VALUE arg)
+autoload_const_set(struct autoload_const *ac)
{
- struct autoload_const *ac = (struct autoload_const *)arg;
VALUE klass = ac->mod;
ID id = ac->id;
check_before_mod_set(klass, id, ac->value, "constant");
- const_tbl_update(ac);
+
+ RB_VM_LOCK_ENTER();
+ {
+ const_tbl_update(ac);
+ }
+ RB_VM_LOCK_LEAVE();
+
return 0; /* ignored */
}
@@ -2168,7 +2394,7 @@ autoload_reset(VALUE arg)
list_for_each_safe(&ele->constants, ac, next, cnode) {
if (ac->value != Qundef) {
- autoload_const_set((VALUE)ac);
+ autoload_const_set(ac);
}
}
}
@@ -2309,10 +2535,10 @@ rb_const_warn_if_deprecated(const rb_const_entry_t *ce, VALUE klass, ID id)
if (RB_CONST_DEPRECATED_P(ce) &&
rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) {
if (klass == rb_cObject) {
- rb_warn("constant ::%"PRIsVALUE" is deprecated", QUOTE_ID(id));
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "constant ::%"PRIsVALUE" is deprecated", QUOTE_ID(id));
}
else {
- rb_warn("constant %"PRIsVALUE"::%"PRIsVALUE" is deprecated",
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "constant %"PRIsVALUE"::%"PRIsVALUE" is deprecated",
rb_class_name(klass), QUOTE_ID(id));
}
}
@@ -2322,7 +2548,14 @@ static VALUE
rb_const_get_0(VALUE klass, ID id, int exclude, int recurse, int visibility)
{
VALUE c = rb_const_search(klass, id, exclude, recurse, visibility);
- if (c != Qundef) return c;
+ if (c != Qundef) {
+ if (UNLIKELY(!rb_ractor_main_p())) {
+ if (!rb_ractor_shareable_p(c)) {
+ rb_raise(rb_eRactorIsolationError, "can not access non-shareable objects in constant %"PRIsVALUE"::%s by non-main Ractor.", rb_class_path(klass), rb_id2name(id));
+ }
+ }
+ return c;
+ }
return rb_const_missing(klass, ID2SYM(id));
}
@@ -2554,8 +2787,13 @@ rb_local_constants(VALUE mod)
if (!tbl) return rb_ary_new2(0);
- ary = rb_ary_new2(rb_id_table_size(tbl));
- rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary);
+ RB_VM_LOCK_ENTER();
+ {
+ ary = rb_ary_new2(rb_id_table_size(tbl));
+ rb_id_table_foreach(tbl, rb_local_constants_i, (void *)ary);
+ }
+ RB_VM_LOCK_LEAVE();
+
return ary;
}
@@ -2567,7 +2805,11 @@ rb_mod_const_at(VALUE mod, void *data)
tbl = st_init_numtable();
}
if (RCLASS_CONST_TBL(mod)) {
- rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
+ RB_VM_LOCK_ENTER();
+ {
+ rb_id_table_foreach(RCLASS_CONST_TBL(mod), sv_i, tbl);
+ }
+ RB_VM_LOCK_LEAVE();
}
return tbl;
}
@@ -2743,42 +2985,57 @@ static void
set_namespace_path(VALUE named_namespace, VALUE namespace_path)
{
struct rb_id_table *const_table = RCLASS_CONST_TBL(named_namespace);
- if (!RCLASS_IV_TBL(named_namespace)) {
- RCLASS_IV_TBL(named_namespace) = st_init_numtable();
- }
- rb_class_ivar_set(named_namespace, classpath, namespace_path);
- if (const_table) {
- rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
+
+ RB_VM_LOCK_ENTER();
+ {
+ if (!RCLASS_IV_TBL(named_namespace)) {
+ RCLASS_IV_TBL(named_namespace) = st_init_numtable();
+ }
+ rb_class_ivar_set(named_namespace, classpath, namespace_path);
+ if (const_table) {
+ rb_id_table_foreach(const_table, set_namespace_path_i, &namespace_path);
+ }
}
+ RB_VM_LOCK_LEAVE();
}
void
rb_const_set(VALUE klass, ID id, VALUE val)
{
rb_const_entry_t *ce;
- struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
if (NIL_P(klass)) {
rb_raise(rb_eTypeError, "no class/module to define constant %"PRIsVALUE"",
QUOTE_ID(id));
}
- check_before_mod_set(klass, id, val, "constant");
- if (!tbl) {
- RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0);
- rb_clear_constant_cache();
- ce = ZALLOC(rb_const_entry_t);
- rb_id_table_insert(tbl, id, (VALUE)ce);
- setup_const_entry(ce, klass, val, CONST_PUBLIC);
+ if (!rb_ractor_main_p() && !rb_ractor_shareable_p(val)) {
+ rb_raise(rb_eRactorIsolationError, "can not set constants with non-shareable objects by non-main Ractors");
}
- else {
- struct autoload_const ac = {
- .mod = klass, .id = id,
- .value = val, .flag = CONST_PUBLIC,
- /* fill the rest with 0 */
- };
- const_tbl_update(&ac);
+
+ check_before_mod_set(klass, id, val, "constant");
+
+ RB_VM_LOCK_ENTER();
+ {
+ struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
+ if (!tbl) {
+ RCLASS_CONST_TBL(klass) = tbl = rb_id_table_create(0);
+ rb_clear_constant_cache();
+ ce = ZALLOC(rb_const_entry_t);
+ rb_id_table_insert(tbl, id, (VALUE)ce);
+ setup_const_entry(ce, klass, val, CONST_PUBLIC);
+ }
+ else {
+ struct autoload_const ac = {
+ .mod = klass, .id = id,
+ .value = val, .flag = CONST_PUBLIC,
+ /* fill the rest with 0 */
+ };
+ const_tbl_update(&ac);
+ }
}
+ RB_VM_LOCK_LEAVE();
+
/*
* Resolve and cache class name immediately to resolve ambiguity
* and avoid order-dependency on const_tbl
@@ -2793,14 +3050,16 @@ rb_const_set(VALUE klass, ID id, VALUE val)
else {
int parental_path_permanent;
VALUE parental_path = classname(klass, &parental_path_permanent);
- if (!NIL_P(parental_path)) {
- if (parental_path_permanent && !val_path_permanent) {
- set_namespace_path(val, build_const_path(parental_path, id));
- }
- else if (!parental_path_permanent && NIL_P(val_path)) {
- rb_ivar_set(val, tmp_classpath, build_const_path(parental_path, id));
- }
- }
+ if (NIL_P(parental_path)) {
+ int throwaway;
+ parental_path = rb_tmp_class_path(klass, &throwaway, make_temporary_path);
+ }
+ if (parental_path_permanent && !val_path_permanent) {
+ set_namespace_path(val, build_const_path(parental_path, id));
+ }
+ else if (!parental_path_permanent && NIL_P(val_path)) {
+ rb_ivar_set(val, tmp_classpath, build_const_path(parental_path, id));
+ }
}
}
}
@@ -3058,8 +3317,9 @@ cvar_overtaken(VALUE front, VALUE target, ID id)
if (front && target != front) {
st_data_t did = (st_data_t)id;
- if (RTEST(ruby_verbose) && original_module(front) != original_module(target)) {
- rb_warning("class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
+ if (original_module(front) != original_module(target)) {
+ rb_raise(rb_eRuntimeError,
+ "class variable % "PRIsVALUE" of %"PRIsVALUE" is overtaken by %"PRIsVALUE"",
ID2SYM(id), rb_class_name(original_module(front)),
rb_class_name(original_module(target)));
}
@@ -3077,6 +3337,7 @@ cvar_overtaken(VALUE front, VALUE target, ID id)
}
#define CVAR_LOOKUP(v,r) do {\
+ CVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR(); \
if (cvar_lookup_at(klass, id, (v))) {r;}\
CVAR_FOREACH_ANCESTORS(klass, v, r);\
} while(0)
@@ -3095,6 +3356,9 @@ rb_cvar_set(VALUE klass, ID id, VALUE val)
target = tmp;
}
+ if (RB_TYPE_P(target, T_ICLASS)) {
+ target = RBASIC(target)->klass;
+ }
check_before_mod_set(target, id, val, "class variable");
if (!RCLASS_IV_TBL(target)) {
RCLASS_IV_TBL(target) = st_init_numtable();
@@ -3264,13 +3528,12 @@ rb_mod_class_variables(int argc, const VALUE *argv, VALUE mod)
* call-seq:
* remove_class_variable(sym) -> obj
*
- * Removes the definition of the <i>sym</i>, returning that
- * constant's value.
+ * Removes the named class variable from the receiver, returning that
+ * variable's value.
*
- * class Dummy
+ * class Example
* @@var = 99
- * puts @@var
- * remove_class_variable(:@@var)
+ * puts remove_class_variable(:@@var)
* p(defined? @@var)
* end
*
@@ -3287,9 +3550,7 @@ rb_mod_remove_cvar(VALUE mod, VALUE name)
st_data_t val, n = id;
if (!id) {
- not_defined:
- rb_name_err_raise("class variable %1$s not defined for %2$s",
- mod, name);
+ goto not_defined;
}
rb_check_frozen(mod);
if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {
@@ -3298,7 +3559,10 @@ rb_mod_remove_cvar(VALUE mod, VALUE name)
if (rb_cvar_defined(mod, id)) {
rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id));
}
- goto not_defined;
+ not_defined:
+ rb_name_err_raise("class variable %1$s not defined for %2$s",
+ mod, name);
+ UNREACHABLE_RETURN(Qundef);
}
VALUE
@@ -3307,8 +3571,6 @@ rb_iv_get(VALUE obj, const char *name)
ID id = rb_check_id_cstr(name, strlen(name), rb_usascii_encoding());
if (!id) {
- if (RTEST(ruby_verbose))
- rb_warning("instance variable %s not initialized", name);
return Qnil;
}
return rb_ivar_get(obj, id);
@@ -3352,10 +3614,17 @@ MJIT_FUNC_EXPORTED rb_const_entry_t *
rb_const_lookup(VALUE klass, ID id)
{
struct rb_id_table *tbl = RCLASS_CONST_TBL(klass);
- VALUE val;
- if (tbl && rb_id_table_lookup(tbl, id, &val)) {
- return (rb_const_entry_t *)val;
+ if (tbl) {
+ VALUE val;
+ bool r;
+ RB_VM_LOCK_ENTER();
+ {
+ r = rb_id_table_lookup(tbl, id, &val);
+ }
+ RB_VM_LOCK_LEAVE();
+
+ if (r) return (rb_const_entry_t *)val;
}
- return 0;
+ return NULL;
}
diff --git a/variable.h b/variable.h
index 67fe480149..bfe1be2d47 100644
--- a/variable.h
+++ b/variable.h
@@ -1,3 +1,13 @@
+#ifndef RUBY_TOPLEVEL_VARIABLE_H /*-*-C-*-vi:se ft=c:*/
+#define RUBY_TOPLEVEL_VARIABLE_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.
+ */
/* per-object */
@@ -6,4 +16,7 @@ struct gen_ivtbl {
VALUE ivptr[FLEX_ARY_LEN];
};
-struct st_table *rb_ivar_generic_ivtbl(void);
+int rb_ivar_generic_ivtbl_lookup(VALUE obj, struct gen_ivtbl **);
+VALUE rb_ivar_generic_lookup_with_index(VALUE obj, ID id, uint32_t index);
+
+#endif /* RUBY_TOPLEVEL_VARIABLE_H */
diff --git a/version.h b/version.h
index 6c826b5f0a..e00808d240 100644
--- a/version.h
+++ b/version.h
@@ -1,12 +1,22 @@
+#ifndef RUBY_TOPLEVEL_VERSION_H /*-*-C-*-vi:se ft=c:*/
+#define RUBY_TOPLEVEL_VERSION_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.
+ */
# define RUBY_VERSION_MAJOR RUBY_API_VERSION_MAJOR
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
-#define RUBY_VERSION_TEENY 7
+#define RUBY_VERSION_TEENY 4
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 220
+#define RUBY_PATCHLEVEL 208
#define RUBY_RELEASE_YEAR 2022
-#define RUBY_RELEASE_MONTH 11
-#define RUBY_RELEASE_DAY 24
+#define RUBY_RELEASE_MONTH 4
+#define RUBY_RELEASE_DAY 12
#include "ruby/version.h"
@@ -75,3 +85,5 @@
RUBY_BIRTH_YEAR_STR"-" \
RUBY_RELEASE_YEAR_STR" " \
RUBY_AUTHOR
+
+#endif /* RUBY_TOPLEVEL_VERSION_H */
diff --git a/vm.c b/vm.c
index 0750606bd6..2503ca9a9f 100644
--- a/vm.c
+++ b/vm.c
@@ -1,6 +1,6 @@
/**********************************************************************
- vm.c -
+ Vm.c -
$Author$
@@ -8,17 +8,35 @@
**********************************************************************/
-#include "internal.h"
-#include "ruby/vm.h"
-#include "ruby/st.h"
-
#define vm_exec rb_vm_exec
+#include "eval_intern.h"
#include "gc.h"
+#include "internal.h"
+#include "internal/compile.h"
+#include "internal/cont.h"
+#include "internal/error.h"
+#include "internal/eval.h"
+#include "internal/inits.h"
+#include "internal/object.h"
+#include "internal/parse.h"
+#include "internal/proc.h"
+#include "internal/re.h"
+#include "internal/symbol.h"
+#include "internal/vm.h"
+#include "internal/sanitizers.h"
+#include "iseq.h"
+#include "mjit.h"
+#include "ruby/st.h"
+#include "ruby/vm.h"
#include "vm_core.h"
+#include "vm_callinfo.h"
#include "vm_debug.h"
-#include "iseq.h"
-#include "eval_intern.h"
+#include "vm_exec.h"
+#include "vm_insnhelper.h"
+#include "ractor_core.h"
+#include "vm_sync.h"
+
#include "builtin.h"
#ifndef MJIT_HEADER
@@ -39,7 +57,7 @@ RUBY_FUNC_EXPORTED
#else
MJIT_FUNC_EXPORTED
#endif
-VALUE vm_exec(rb_execution_context_t *, int);
+VALUE vm_exec(rb_execution_context_t *, bool);
PUREFUNC(static inline const VALUE *VM_EP_LEP(const VALUE *));
static inline const VALUE *
@@ -104,13 +122,6 @@ rb_vm_cframe_keyword_p(const rb_control_frame_t *cfp)
return VM_FRAME_CFRAME_KW_P(cfp);
}
-/* -- Remove In 3.0 -- */
-int
-rb_vm_cframe_empty_keyword_p(const rb_control_frame_t *cfp)
-{
- return VM_FRAME_CFRAME_EMPTY_KW_P(cfp);
-}
-
VALUE
rb_vm_frame_block_handler(const rb_control_frame_t *cfp)
{
@@ -148,7 +159,7 @@ VM_EP_IN_HEAP_P(const rb_execution_context_t *ec, const VALUE *ep)
}
}
-int
+static int
vm_ep_in_heap_p_(const rb_execution_context_t *ec, const VALUE *ep)
{
if (VM_EP_IN_HEAP_P(ec, ep)) {
@@ -338,9 +349,6 @@ extern VALUE rb_vm_invoke_bmethod(rb_execution_context_t *ec, rb_proc_t *proc, V
const rb_callable_method_entry_t *me);
static VALUE vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self, int argc, const VALUE *argv, int kw_splat, VALUE block_handler);
-#include "mjit.h"
-#include "vm_insnhelper.h"
-#include "vm_exec.h"
#include "vm_insnhelper.c"
#ifndef MJIT_HEADER
@@ -370,18 +378,49 @@ VALUE rb_block_param_proxy;
#define ruby_vm_redefined_flag GET_VM()->redefined_flag
VALUE ruby_vm_const_missing_count = 0;
rb_vm_t *ruby_current_vm_ptr = NULL;
-rb_execution_context_t *ruby_current_execution_context_ptr = NULL;
+rb_ractor_t *ruby_single_main_ractor;
+
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+RB_THREAD_LOCAL_SPECIFIER rb_execution_context_t *ruby_current_ec;
+
+#ifdef __APPLE__
+ rb_execution_context_t *
+ rb_current_ec(void)
+ {
+ return ruby_current_ec;
+ }
+ void
+ rb_current_ec_set(rb_execution_context_t *ec)
+ {
+ ruby_current_ec = ec;
+ }
+#endif
+
+#else
+native_tls_key_t ruby_current_ec_key;
+#endif
rb_event_flag_t ruby_vm_event_flags;
rb_event_flag_t ruby_vm_event_enabled_global_flags;
unsigned int ruby_vm_event_local_num;
-rb_serial_t ruby_vm_global_method_state = 1;
rb_serial_t ruby_vm_global_constant_state = 1;
rb_serial_t ruby_vm_class_serial = 1;
+static const struct rb_callcache vm_empty_cc = {
+ .flags = T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE,
+ .klass = Qfalse,
+ .cme_ = NULL,
+ .call_ = vm_call_general,
+ .aux_ = {
+ .v = Qfalse,
+ }
+};
+
static void thread_free(void *ptr);
+//
+
void
rb_vm_inc_const_missing_count(void)
{
@@ -435,7 +474,6 @@ rb_dtrace_setup(rb_execution_context_t *ec, VALUE klass, ID id,
* This hash includes information about method/constant cache serials:
*
* {
- * :global_method_state=>251,
* :global_constant_state=>481,
* :class_serial=>9029
* }
@@ -449,7 +487,7 @@ rb_dtrace_setup(rb_execution_context_t *ec, VALUE klass, ID id,
static VALUE
vm_stat(int argc, VALUE *argv, VALUE self)
{
- static VALUE sym_global_method_state, sym_global_constant_state, sym_class_serial;
+ static VALUE sym_global_constant_state, sym_class_serial;
VALUE arg = Qnil;
VALUE hash = Qnil, key = Qnil;
@@ -466,9 +504,8 @@ vm_stat(int argc, VALUE *argv, VALUE self)
hash = rb_hash_new();
}
- if (sym_global_method_state == 0) {
+ if (sym_global_constant_state == 0) {
#define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
- S(global_method_state);
S(global_constant_state);
S(class_serial);
#undef S
@@ -480,7 +517,6 @@ vm_stat(int argc, VALUE *argv, VALUE self)
else if (hash != Qnil) \
rb_hash_aset(hash, sym_##name, SERIALT2NUM(attr));
- SET(global_method_state, ruby_vm_global_method_state);
SET(global_constant_state, ruby_vm_global_constant_state);
SET(class_serial, ruby_vm_class_serial);
#undef SET
@@ -552,7 +588,6 @@ rb_vm_get_binding_creatable_next_cfp(const rb_execution_context_t *ec, const rb_
MJIT_FUNC_EXPORTED rb_control_frame_t *
rb_vm_get_ruby_level_next_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
{
- if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) bp();
while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(ec, cfp)) {
if (VM_FRAME_RUBYFRAME_P(cfp)) {
return (rb_control_frame_t *)cfp;
@@ -704,18 +739,17 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co
if (!VM_ENV_LOCAL_P(ep)) {
const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
+ if (!VM_ENV_ESCAPED_P(prev_ep)) {
+ rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
- if (!VM_ENV_ESCAPED_P(prev_ep)) {
- rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
-
- while (prev_cfp->ep != prev_ep) {
- prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(prev_cfp);
- VM_ASSERT(prev_cfp->ep != NULL);
- }
+ while (prev_cfp->ep != prev_ep) {
+ prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(prev_cfp);
+ VM_ASSERT(prev_cfp->ep != NULL);
+ }
- vm_make_env_each(ec, prev_cfp);
- VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_SPECVAL], VM_GUARDED_PREV_EP(prev_cfp->ep));
- }
+ vm_make_env_each(ec, prev_cfp);
+ VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_SPECVAL], VM_GUARDED_PREV_EP(prev_cfp->ep));
+ }
}
else {
VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep);
@@ -801,7 +835,8 @@ rb_vm_env_prev_env(const rb_env_t *env)
return NULL;
}
else {
- return VM_ENV_ENVVAL_PTR(VM_ENV_PREV_EP(ep));
+ const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
+ return VM_ENV_ENVVAL_PTR(prev_ep);
}
}
@@ -820,6 +855,7 @@ static void
collect_local_variables_in_env(const rb_env_t *env, const struct local_var_list *vars)
{
do {
+ if (VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_ISOLATED)) break;
collect_local_variables_in_iseq(env->iseq, vars);
} while ((env = rb_vm_env_prev_env(env)) != NULL);
}
@@ -870,8 +906,8 @@ vm_proc_create_from_captured(VALUE klass,
VM_ASSERT(VM_EP_IN_HEAP_P(GET_EC(), captured->ep));
/* copy block */
- RB_OBJ_WRITE(procval, &proc->block.as.captured.self, captured->self);
RB_OBJ_WRITE(procval, &proc->block.as.captured.code.val, captured->code.val);
+ RB_OBJ_WRITE(procval, &proc->block.as.captured.self, captured->self);
rb_vm_block_ep_update(procval, &proc->block, captured->ep);
vm_block_type_set(&proc->block, block_type);
@@ -924,10 +960,193 @@ rb_proc_dup(VALUE self)
GetProcPtr(self, src);
procval = proc_create(rb_cProc, &src->block, src->is_from_method, src->is_lambda);
+ if (RB_OBJ_SHAREABLE_P(self)) FL_SET_RAW(procval, RUBY_FL_SHAREABLE);
RB_GC_GUARD(self); /* for: body = rb_proc_dup(body) */
return procval;
}
+struct collect_outer_variable_name_data {
+ VALUE ary;
+ VALUE read_only;
+ bool yield;
+ bool isolate;
+};
+
+static enum rb_id_table_iterator_result
+collect_outer_variable_names(ID id, VALUE val, void *ptr)
+{
+ struct collect_outer_variable_name_data *data = (struct collect_outer_variable_name_data *)ptr;
+
+ if (id == rb_intern("yield")) {
+ data->yield = true;
+ }
+ else {
+ if (data->isolate ||
+ val == Qtrue /* write */) {
+ if (data->ary == Qfalse) data->ary = rb_ary_new();
+ rb_ary_push(data->ary, rb_id2str(id));
+ }
+ else {
+ if (data->read_only == Qfalse) data->read_only = rb_ary_new();
+ rb_ary_push(data->read_only, rb_id2str(id));
+ }
+ }
+ return ID_TABLE_CONTINUE;
+}
+
+static const rb_env_t *
+env_copy(const VALUE *src_ep, VALUE read_only_variables)
+{
+ const rb_env_t *src_env = (rb_env_t *)VM_ENV_ENVVAL(src_ep);
+ VM_ASSERT(src_env->ep == src_ep);
+
+ VALUE *env_body = ZALLOC_N(VALUE, src_env->env_size); // fill with Qfalse
+ VALUE *ep = &env_body[src_env->env_size - 2];
+ volatile VALUE prev_env = Qnil;
+
+ if (read_only_variables) {
+ for (int i=RARRAY_LENINT(read_only_variables)-1; i>=0; i--) {
+ ID id = SYM2ID(rb_str_intern(RARRAY_AREF(read_only_variables, i)));
+
+ for (unsigned int j=0; j<src_env->iseq->body->local_table_size; j++) {
+ if (id == src_env->iseq->body->local_table[j]) {
+ VALUE v = src_env->env[j];
+ if (!rb_ractor_shareable_p(v)) {
+ rb_raise(rb_eRactorIsolationError,
+ "can not make shareable Proc because it can refer unshareable object %"
+ PRIsVALUE" from variable `%s'", rb_inspect(v), rb_id2name(id));
+ }
+ env_body[j] = v;
+ rb_ary_delete_at(read_only_variables, i);
+ break;
+ }
+ }
+ }
+ }
+
+ ep[VM_ENV_DATA_INDEX_ME_CREF] = src_ep[VM_ENV_DATA_INDEX_ME_CREF];
+ ep[VM_ENV_DATA_INDEX_FLAGS] = src_ep[VM_ENV_DATA_INDEX_FLAGS] | VM_ENV_FLAG_ISOLATED;
+
+ if (!VM_ENV_LOCAL_P(src_ep)) {
+ const VALUE *prev_ep = VM_ENV_PREV_EP(src_env->ep);
+ const rb_env_t *new_prev_env = env_copy(prev_ep, read_only_variables);
+ prev_env = (VALUE)new_prev_env;
+ ep[VM_ENV_DATA_INDEX_SPECVAL] = VM_GUARDED_PREV_EP(new_prev_env->ep);
+ }
+ else {
+ ep[VM_ENV_DATA_INDEX_SPECVAL] = VM_BLOCK_HANDLER_NONE;
+ }
+
+ const rb_env_t *copied_env = vm_env_new(ep, env_body, src_env->env_size, src_env->iseq);
+ RB_GC_GUARD(prev_env);
+ return copied_env;
+}
+
+static void
+proc_isolate_env(VALUE self, rb_proc_t *proc, VALUE read_only_variables)
+{
+ const struct rb_captured_block *captured = &proc->block.as.captured;
+ const rb_env_t *env = env_copy(captured->ep, read_only_variables);
+ *((const VALUE **)&proc->block.as.captured.ep) = env->ep;
+ RB_OBJ_WRITTEN(self, Qundef, env);
+}
+
+VALUE
+rb_proc_isolate_bang(VALUE self)
+{
+ const rb_iseq_t *iseq = vm_proc_iseq(self);
+
+ if (iseq) {
+ rb_proc_t *proc = (rb_proc_t *)RTYPEDDATA_DATA(self);
+ if (proc->block.type != block_type_iseq) rb_raise(rb_eRuntimeError, "not supported yet");
+
+ if (iseq->body->outer_variables) {
+ struct collect_outer_variable_name_data data = {
+ .isolate = true,
+ .ary = Qfalse,
+ .yield = false,
+ };
+ rb_id_table_foreach(iseq->body->outer_variables, collect_outer_variable_names, (void *)&data);
+
+ if (data.ary != Qfalse) {
+ VALUE str = rb_ary_join(data.ary, rb_str_new2(", "));
+ if (data.yield) {
+ rb_raise(rb_eArgError, "can not isolate a Proc because it accesses outer variables (%s) and uses `yield'.",
+ StringValueCStr(str));
+ }
+ else {
+ rb_raise(rb_eArgError, "can not isolate a Proc because it accesses outer variables (%s).",
+ StringValueCStr(str));
+ }
+ }
+ else {
+ VM_ASSERT(data.yield);
+ rb_raise(rb_eArgError, "can not isolate a Proc because it uses `yield'.");
+ }
+ }
+
+ proc_isolate_env(self, proc, Qfalse);
+ proc->is_isolated = TRUE;
+ }
+
+ FL_SET_RAW(self, RUBY_FL_SHAREABLE);
+ return self;
+}
+
+VALUE
+rb_proc_isolate(VALUE self)
+{
+ VALUE dst = rb_proc_dup(self);
+ rb_proc_isolate_bang(dst);
+ return dst;
+}
+
+VALUE
+rb_proc_ractor_make_shareable(VALUE self)
+{
+ const rb_iseq_t *iseq = vm_proc_iseq(self);
+
+ if (iseq) {
+ rb_proc_t *proc = (rb_proc_t *)RTYPEDDATA_DATA(self);
+ if (proc->block.type != block_type_iseq) rb_raise(rb_eRuntimeError, "not supported yet");
+
+ VALUE read_only_variables = Qfalse;
+
+ if (iseq->body->outer_variables) {
+ struct collect_outer_variable_name_data data = {
+ .isolate = false,
+ .ary = Qfalse,
+ .read_only = Qfalse,
+ .yield = false,
+ };
+
+ rb_id_table_foreach(iseq->body->outer_variables, collect_outer_variable_names, (void *)&data);
+
+ if (data.ary != Qfalse) {
+ VALUE str = rb_ary_join(data.ary, rb_str_new2(", "));
+ if (data.yield) {
+ rb_raise(rb_eArgError, "can not make a Proc shareable because it accesses outer variables (%s) and uses `yield'.",
+ StringValueCStr(str));
+ }
+ else {
+ rb_raise(rb_eArgError, "can not make a Proc shareable because it accesses outer variables (%s).",
+ StringValueCStr(str));
+ }
+ }
+ else if (data.yield) {
+ rb_raise(rb_eArgError, "can not make a Proc shareable because it uses `yield'.");
+ }
+
+ read_only_variables = data.read_only;
+ }
+
+ proc_isolate_env(self, proc, read_only_variables);
+ proc->is_isolated = TRUE;
+ }
+
+ FL_SET_RAW(self, RUBY_FL_SHAREABLE);
+ return self;
+}
MJIT_FUNC_EXPORTED VALUE
rb_vm_make_proc_lambda(const rb_execution_context_t *ec, const struct rb_captured_block *captured, VALUE klass, int8_t is_lambda)
@@ -1041,7 +1260,7 @@ invoke_block(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE self, cons
ec->cfp->sp + arg_size,
iseq->body->local_table_size - arg_size,
iseq->body->stack_max);
- return vm_exec(ec, TRUE);
+ return vm_exec(ec, true);
}
static VALUE
@@ -1071,7 +1290,7 @@ invoke_bmethod(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE self, co
me->def->original_id, me->called_id, me->owner, Qnil, FALSE);
}
VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);
- ret = vm_exec(ec, TRUE);
+ ret = vm_exec(ec, true);
EXEC_EVENT_HOOK(ec, RUBY_EVENT_RETURN, self, me->def->original_id, me->called_id, me->owner, ret);
if ((hooks = me->def->body.bmethod.hooks) != NULL &&
@@ -1215,9 +1434,16 @@ invoke_block_from_c_proc(rb_execution_context_t *ec, const rb_proc_t *proc,
case block_type_iseq:
return invoke_iseq_block_from_c(ec, &block->as.captured, self, argc, argv, kw_splat, passed_block_handler, NULL, is_lambda, me);
case block_type_ifunc:
- if (kw_splat == 1 && RHASH_EMPTY_P(argv[argc-1])) {
- argc--;
- kw_splat = 2;
+ if (kw_splat == 1) {
+ VALUE keyword_hash = argv[argc-1];
+ if (!RB_TYPE_P(keyword_hash, T_HASH)) {
+ keyword_hash = rb_to_hash_type(keyword_hash);
+ }
+ if (RHASH_EMPTY_P(keyword_hash)) {
+ argc--;
+ } else {
+ ((VALUE *)argv)[argc-1] = rb_hash_dup(keyword_hash);
+ }
}
return vm_yield_with_cfunc(ec, &block->as.captured, self, argc, argv, kw_splat, passed_block_handler, me);
case block_type_symbol:
@@ -1260,6 +1486,20 @@ rb_vm_invoke_proc(rb_execution_context_t *ec, rb_proc_t *proc,
}
}
+VALUE
+rb_vm_invoke_proc_with_self(rb_execution_context_t *ec, rb_proc_t *proc, VALUE self,
+ int argc, const VALUE *argv, int kw_splat, VALUE passed_block_handler)
+{
+ vm_block_handler_verify(passed_block_handler);
+
+ if (proc->is_from_method) {
+ return rb_vm_invoke_bmethod(ec, proc, self, argc, argv, kw_splat, passed_block_handler, NULL);
+ }
+ else {
+ return vm_invoke_proc(ec, proc, self, argc, argv, kw_splat, passed_block_handler);
+ }
+}
+
/* special variable */
static rb_control_frame_t *
@@ -1556,7 +1796,7 @@ rb_iter_break_value(VALUE val)
/* optimization: redefine management */
-static st_table *vm_opt_method_table = 0;
+static st_table *vm_opt_method_def_table = 0;
static st_table *vm_opt_mid_table = 0;
static int
@@ -1568,7 +1808,9 @@ vm_redefinition_check_flag(VALUE klass)
if (klass == rb_cArray) return ARRAY_REDEFINED_OP_FLAG;
if (klass == rb_cHash) return HASH_REDEFINED_OP_FLAG;
if (klass == rb_cSymbol) return SYMBOL_REDEFINED_OP_FLAG;
+#if 0
if (klass == rb_cTime) return TIME_REDEFINED_OP_FLAG;
+#endif
if (klass == rb_cRegexp) return REGEXP_REDEFINED_OP_FLAG;
if (klass == rb_cNilClass) return NIL_REDEFINED_OP_FLAG;
if (klass == rb_cTrueClass) return TRUE_REDEFINED_OP_FLAG;
@@ -1603,13 +1845,13 @@ static void
rb_vm_check_redefinition_opt_method(const rb_method_entry_t *me, VALUE klass)
{
st_data_t bop;
- if (RB_TYPE_P(klass, T_ICLASS) && FL_TEST(klass, RICLASS_IS_ORIGIN)) {
+ if (RB_TYPE_P(klass, T_ICLASS) && FL_TEST(klass, RICLASS_IS_ORIGIN) &&
+ RB_TYPE_P(RBASIC_CLASS(klass), T_CLASS)) {
klass = RBASIC_CLASS(klass);
}
if (vm_redefinition_check_method_type(me->def)) {
- if (st_lookup(vm_opt_method_table, (st_data_t)me, &bop)) {
- int flag = vm_redefinition_check_flag(klass);
-
+ if (st_lookup(vm_opt_method_def_table, (st_data_t)me->def, &bop)) {
+ int flag = vm_redefinition_check_flag(klass);
ruby_vm_redefined_flag[bop] |= flag;
}
}
@@ -1640,7 +1882,7 @@ add_opt_method(VALUE klass, ID mid, VALUE bop)
const rb_method_entry_t *me = rb_method_entry_at(klass, mid);
if (me && vm_redefinition_check_method_type(me->def)) {
- st_insert(vm_opt_method_table, (st_data_t)me, (st_data_t)bop);
+ st_insert(vm_opt_method_def_table, (st_data_t)me->def, (st_data_t)bop);
st_insert(vm_opt_mid_table, (st_data_t)mid, (st_data_t)Qtrue);
}
else {
@@ -1654,7 +1896,7 @@ vm_init_redefined_flag(void)
ID mid;
VALUE bop;
- vm_opt_method_table = st_init_numtable();
+ vm_opt_method_def_table = st_init_numtable();
vm_opt_mid_table = st_init_numtable();
#define OP(mid_, bop_) (mid = id##mid_, bop = BOP_##bop_, ruby_vm_redefined_flag[bop] = 0)
@@ -1677,7 +1919,7 @@ vm_init_redefined_flag(void)
OP(Length, LENGTH), (C(Array), C(String), C(Hash));
OP(Size, SIZE), (C(Array), C(String), C(Hash));
OP(EmptyP, EMPTY_P), (C(Array), C(String), C(Hash));
- OP(Succ, SUCC), (C(Integer), C(String), C(Time));
+ OP(Succ, SUCC), (C(Integer), C(String));
OP(EqTilde, MATCH), (C(Regexp), C(String));
OP(Freeze, FREEZE), (C(String));
OP(UMinus, UMINUS), (C(String));
@@ -1752,7 +1994,7 @@ static void
hook_before_rewind(rb_execution_context_t *ec, const rb_control_frame_t *cfp,
int will_finish_vm_exec, int state, struct vm_throw_data *err)
{
- if (state == TAG_RAISE && RBASIC_CLASS(err) == rb_eSysStackError) {
+ if (state == TAG_RAISE && RBASIC(err)->klass == rb_eSysStackError) {
return;
}
else {
@@ -1906,7 +2148,7 @@ vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state,
VALUE errinfo, VALUE *initial);
VALUE
-vm_exec(rb_execution_context_t *ec, int mjit_enable_p)
+vm_exec(rb_execution_context_t *ec, bool mjit_enable_p)
{
enum ruby_tag_type state;
VALUE result = Qundef;
@@ -2059,10 +2301,16 @@ vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state,
}
}
}
- else if (state == TAG_BREAK && !escape_cfp) {
- type = CATCH_TYPE_BREAK;
+ else if ((state == TAG_BREAK && !escape_cfp) ||
+ (state == TAG_REDO) ||
+ (state == TAG_NEXT)) {
+ type = (const enum catch_type[TAG_MASK]) {
+ [TAG_BREAK] = CATCH_TYPE_BREAK,
+ [TAG_NEXT] = CATCH_TYPE_NEXT,
+ [TAG_REDO] = CATCH_TYPE_REDO,
+ /* otherwise = dontcare */
+ }[state];
- search_restart_point:
ct = cfp->iseq->body->catch_table;
if (ct) for (i = 0; i < ct->size; i++) {
entry = UNALIGNED_MEMBER_PTR(ct, entries[i]);
@@ -2092,14 +2340,6 @@ vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state,
}
}
}
- else if (state == TAG_REDO) {
- type = CATCH_TYPE_REDO;
- goto search_restart_point;
- }
- else if (state == TAG_NEXT) {
- type = CATCH_TYPE_NEXT;
- goto search_restart_point;
- }
else {
ct = cfp->iseq->body->catch_table;
if (ct) for (i = 0; i < ct->size; i++) {
@@ -2165,7 +2405,7 @@ rb_iseq_eval(const rb_iseq_t *iseq)
rb_execution_context_t *ec = GET_EC();
VALUE val;
vm_set_top_stack(ec, iseq);
- val = vm_exec(ec, TRUE);
+ val = vm_exec(ec, true);
return val;
}
@@ -2176,7 +2416,7 @@ rb_iseq_eval_main(const rb_iseq_t *iseq)
VALUE val;
vm_set_main_stack(ec, iseq);
- val = vm_exec(ec, TRUE);
+ val = vm_exec(ec, true);
return val;
}
@@ -2235,26 +2475,84 @@ rb_vm_update_references(void *ptr)
{
if (ptr) {
rb_vm_t *vm = ptr;
+
rb_gc_update_tbl_refs(vm->frozen_strings);
+ vm->mark_object_ary = rb_gc_location(vm->mark_object_ary);
+ vm->load_path = rb_gc_location(vm->load_path);
+ vm->load_path_snapshot = rb_gc_location(vm->load_path_snapshot);
+
+ if (vm->load_path_check_cache) {
+ vm->load_path_check_cache = rb_gc_location(vm->load_path_check_cache);
+ }
+
+ vm->expanded_load_path = rb_gc_location(vm->expanded_load_path);
+ vm->loaded_features = rb_gc_location(vm->loaded_features);
+ vm->loaded_features_snapshot = rb_gc_location(vm->loaded_features_snapshot);
+ vm->top_self = rb_gc_location(vm->top_self);
+ vm->orig_progname = rb_gc_location(vm->orig_progname);
+
+ if (vm->coverages) {
+ vm->coverages = rb_gc_location(vm->coverages);
+ }
}
}
void
+rb_vm_each_stack_value(void *ptr, void (*cb)(VALUE, void*), void *ctx)
+{
+ if (ptr) {
+ rb_vm_t *vm = ptr;
+ rb_ractor_t *r = 0;
+ list_for_each(&vm->ractor.set, r, vmlr_node) {
+ VM_ASSERT(rb_ractor_status_p(r, ractor_blocking) ||
+ rb_ractor_status_p(r, ractor_running));
+ if (r->threads.cnt > 0) {
+ rb_thread_t *th = 0;
+ list_for_each(&r->threads.set, th, lt_node) {
+ VM_ASSERT(th != NULL);
+ rb_execution_context_t * ec = th->ec;
+ if (ec->vm_stack) {
+ VALUE *p = ec->vm_stack;
+ VALUE *sp = ec->cfp->sp;
+ while (p <= sp) {
+ if (!rb_special_const_p(*p)) {
+ cb(*p, ctx);
+ }
+ p++;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static enum rb_id_table_iterator_result
+vm_mark_negative_cme(VALUE val, void *dmy)
+{
+ rb_gc_mark(val);
+ return ID_TABLE_CONTINUE;
+}
+
+void
rb_vm_mark(void *ptr)
{
RUBY_MARK_ENTER("vm");
RUBY_GC_INFO("-------------------------------------------------\n");
if (ptr) {
rb_vm_t *vm = ptr;
- rb_thread_t *th = 0;
+ rb_ractor_t *r = 0;
long i, len;
const VALUE *obj_ary;
- list_for_each(&vm->living_threads, th, vmlt_node) {
- rb_gc_mark(th->self);
+ list_for_each(&vm->ractor.set, r, vmlr_node) {
+ // ractor.set only contains blocking or running ractors
+ VM_ASSERT(rb_ractor_status_p(r, ractor_blocking) ||
+ rb_ractor_status_p(r, ractor_running));
+ rb_gc_mark(rb_ractor_self(r));
}
- rb_gc_mark(vm->thgroup_default);
- rb_gc_mark(vm->mark_object_ary);
+
+ rb_gc_mark_movable(vm->mark_object_ary);
len = RARRAY_LEN(vm->mark_object_ary);
obj_ary = RARRAY_CONST_PTR(vm->mark_object_ary);
@@ -2271,15 +2569,15 @@ rb_vm_mark(void *ptr)
obj_ary++;
}
- rb_gc_mark(vm->load_path);
- rb_gc_mark(vm->load_path_snapshot);
- RUBY_MARK_UNLESS_NULL(vm->load_path_check_cache);
- rb_gc_mark(vm->expanded_load_path);
- rb_gc_mark(vm->loaded_features);
- rb_gc_mark(vm->loaded_features_snapshot);
- rb_gc_mark(vm->top_self);
- rb_gc_mark(vm->orig_progname);
- RUBY_MARK_UNLESS_NULL(vm->coverages);
+ rb_gc_mark_movable(vm->load_path);
+ rb_gc_mark_movable(vm->load_path_snapshot);
+ RUBY_MARK_MOVABLE_UNLESS_NULL(vm->load_path_check_cache);
+ rb_gc_mark_movable(vm->expanded_load_path);
+ rb_gc_mark_movable(vm->loaded_features);
+ rb_gc_mark_movable(vm->loaded_features_snapshot);
+ rb_gc_mark_movable(vm->top_self);
+ rb_gc_mark_movable(vm->orig_progname);
+ RUBY_MARK_MOVABLE_UNLESS_NULL(vm->coverages);
/* Prevent classes from moving */
rb_mark_tbl(vm->defined_module_hash);
@@ -2287,10 +2585,22 @@ rb_vm_mark(void *ptr)
rb_mark_tbl(vm->loading_table);
}
- rb_hook_list_mark(&vm->global_hooks);
-
rb_gc_mark_values(RUBY_NSIG, vm->trap_list.cmd);
+ rb_id_table_foreach_values(vm->negative_cme_table, vm_mark_negative_cme, NULL);
+ for (i=0; i<VM_GLOBAL_CC_CACHE_TABLE_SIZE; i++) {
+ const struct rb_callcache *cc = vm->global_cc_cache_table[i];
+
+ if (cc != NULL) {
+ if (!vm_cc_invalidated_p(cc)) {
+ rb_gc_mark((VALUE)cc);
+ }
+ else {
+ vm->global_cc_cache_table[i] = NULL;
+ }
+ }
+ }
+
mjit_mark();
}
@@ -2309,7 +2619,7 @@ rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE cls,
}
int
-rb_vm_add_root_module(ID id, VALUE module)
+rb_vm_add_root_module(VALUE module)
{
rb_vm_t *vm = GET_VM();
@@ -2331,10 +2641,11 @@ ruby_vm_destruct(rb_vm_t *vm)
RUBY_FREE_ENTER("vm");
if (vm) {
- rb_thread_t *th = vm->main_thread;
+ rb_thread_t *th = vm->ractor.main_thread;
struct rb_objspace *objspace = vm->objspace;
- vm->main_thread = 0;
- if (th) {
+ vm->ractor.main_thread = NULL;
+
+ if (th) {
rb_fiber_reset_root_local_storage(th);
thread_free(th);
}
@@ -2349,7 +2660,6 @@ ruby_vm_destruct(rb_vm_t *vm)
st_free_table(vm->frozen_strings);
vm->frozen_strings = 0;
}
- rb_vm_gvl_destroy(vm);
RB_ALTSTACK_FREE(vm->main_altstack);
if (objspace) {
rb_objspace_free(objspace);
@@ -2370,7 +2680,8 @@ vm_memsize(const void *ptr)
const rb_vm_t *vmobj = ptr;
size_t size = sizeof(rb_vm_t);
- size += vmobj->living_thread_num * sizeof(rb_thread_t);
+ // TODO
+ // size += vmobj->ractor_num * sizeof(rb_ractor_t);
if (vmobj->defined_strings) {
size += DEFINED_EXPR * sizeof(VALUE);
@@ -2380,7 +2691,7 @@ vm_memsize(const void *ptr)
static const rb_data_type_t vm_data_type = {
"VM",
- {NULL, NULL, vm_memsize,},
+ {0, 0, vm_memsize,},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -2475,11 +2786,21 @@ rb_execution_context_update(const rb_execution_context_t *ec)
{
/* update VM stack */
if (ec->vm_stack) {
+ long i;
VM_ASSERT(ec->cfp);
-
+ VALUE *p = ec->vm_stack;
+ VALUE *sp = ec->cfp->sp;
rb_control_frame_t *cfp = ec->cfp;
rb_control_frame_t *limit_cfp = (void *)(ec->vm_stack + ec->vm_stack_size);
+ for (i = 0; i < (long)(sp - p); i++) {
+ VALUE ref = p[i];
+ VALUE update = rb_gc_location(ref);
+ if (ref != update) {
+ p[i] = update;
+ }
+ }
+
while (cfp != limit_cfp) {
const VALUE *ep = cfp->ep;
cfp->self = rb_gc_location(cfp->self);
@@ -2487,9 +2808,14 @@ rb_execution_context_update(const rb_execution_context_t *ec)
cfp->block_code = (void *)rb_gc_location((VALUE)cfp->block_code);
if (!VM_ENV_LOCAL_P(ep)) {
- VALUE *prev_ep = (VALUE *)VM_ENV_PREV_EP(ep);
+ const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
- prev_ep[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(prev_ep[VM_ENV_DATA_INDEX_ENV]);
+ VM_FORCE_WRITE(&prev_ep[VM_ENV_DATA_INDEX_ENV], rb_gc_location(prev_ep[VM_ENV_DATA_INDEX_ENV]));
+ }
+
+ if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)) {
+ VM_FORCE_WRITE(&ep[VM_ENV_DATA_INDEX_ENV], rb_gc_location(ep[VM_ENV_DATA_INDEX_ENV]));
+ VM_FORCE_WRITE(&ep[VM_ENV_DATA_INDEX_ME_CREF], rb_gc_location(ep[VM_ENV_DATA_INDEX_ME_CREF]));
}
}
@@ -2498,6 +2824,13 @@ rb_execution_context_update(const rb_execution_context_t *ec)
}
}
+static enum rb_id_table_iterator_result
+mark_local_storage_i(VALUE local, void *data)
+{
+ rb_gc_mark(local);
+ return ID_TABLE_CONTINUE;
+}
+
void
rb_execution_context_mark(const rb_execution_context_t *ec)
{
@@ -2509,6 +2842,7 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
rb_control_frame_t *cfp = ec->cfp;
rb_control_frame_t *limit_cfp = (void *)(ec->vm_stack + ec->vm_stack_size);
+ VM_ASSERT(sp == ec->cfp->sp);
rb_gc_mark_vm_stack_values((long)(sp - p), p);
while (cfp != limit_cfp) {
@@ -2518,12 +2852,17 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
rb_gc_mark_movable((VALUE)cfp->iseq);
rb_gc_mark_movable((VALUE)cfp->block_code);
- if (!VM_ENV_LOCAL_P(ep)) {
- const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
- if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
+ if (!VM_ENV_LOCAL_P(ep)) {
+ const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
+ if (VM_ENV_FLAGS(prev_ep, VM_ENV_FLAG_ESCAPED)) {
rb_gc_mark_movable(prev_ep[VM_ENV_DATA_INDEX_ENV]);
+ }
+
+ if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ESCAPED)) {
+ rb_gc_mark_movable(ep[VM_ENV_DATA_INDEX_ENV]);
+ rb_gc_mark(ep[VM_ENV_DATA_INDEX_ME_CREF]);
}
- }
+ }
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
@@ -2541,7 +2880,9 @@ rb_execution_context_mark(const rb_execution_context_t *ec)
RUBY_MARK_UNLESS_NULL(ec->errinfo);
RUBY_MARK_UNLESS_NULL(ec->root_svar);
- rb_mark_tbl(ec->local_storage);
+ if (ec->local_storage) {
+ rb_id_table_foreach_values(ec->local_storage, mark_local_storage_i, NULL);
+ }
RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash);
RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash_for_trace);
RUBY_MARK_UNLESS_NULL(ec->private_const_reference);
@@ -2556,11 +2897,12 @@ static void
thread_compact(void *ptr)
{
rb_thread_t *th = ptr;
- rb_fiber_update_self(th->ec->fiber_ptr);
- if (th->root_fiber) rb_fiber_update_self(th->root_fiber);
+ th->self = rb_gc_location(th->self);
- rb_execution_context_update(th->ec);
+ if (!th->root_fiber) {
+ rb_execution_context_update(th->ec);
+ }
}
static void
@@ -2573,6 +2915,7 @@ thread_mark(void *ptr)
/* mark ruby objects */
switch (th->invoke_type) {
case thread_invoke_type_proc:
+ case thread_invoke_type_ractor_proc:
RUBY_MARK_UNLESS_NULL(th->invoke_arg.proc.proc);
RUBY_MARK_UNLESS_NULL(th->invoke_arg.proc.args);
break;
@@ -2583,6 +2926,7 @@ thread_mark(void *ptr)
break;
}
+ rb_gc_mark(rb_ractor_self(th->ractor));
RUBY_MARK_UNLESS_NULL(th->thgroup);
RUBY_MARK_UNLESS_NULL(th->value);
RUBY_MARK_UNLESS_NULL(th->pending_interrupt_queue);
@@ -2598,6 +2942,8 @@ thread_mark(void *ptr)
RUBY_MARK_UNLESS_NULL(th->locking_mutex);
RUBY_MARK_UNLESS_NULL(th->name);
+ RUBY_MARK_UNLESS_NULL(th->scheduler);
+
RUBY_MARK_LEAVE("thread");
}
@@ -2616,8 +2962,8 @@ thread_free(void *ptr)
rb_threadptr_root_fiber_release(th);
- if (th->vm && th->vm->main_thread == th) {
- RUBY_GC_INFO("main thread\n");
+ if (th->vm && th->vm->ractor.main_thread == th) {
+ RUBY_GC_INFO("MRI main thread\n");
}
else {
ruby_xfree(ptr);
@@ -2636,7 +2982,7 @@ thread_memsize(const void *ptr)
size += th->ec->vm_stack_size * sizeof(VALUE);
}
if (th->ec->local_storage) {
- size += st_memsize(th->ec->local_storage);
+ size += rb_id_table_memsize(th->ec->local_storage);
}
return size;
}
@@ -2712,6 +3058,10 @@ th_init(rb_thread_t *th, VALUE self)
th->self = self;
rb_threadptr_root_fiber_setup(th);
+ /* All threads are blocking until a non-blocking fiber is scheduled */
+ th->blocking = 1;
+ th->scheduler = Qnil;
+
if (self == 0) {
size_t size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE);
rb_ec_initialize_vm_stack(th->ec, ALLOC_N(VALUE, size), size);
@@ -2732,25 +3082,31 @@ th_init(rb_thread_t *th, VALUE self)
th->thread_id_string[0] = '\0';
#endif
+ th->value = Qundef;
+
#if OPT_CALL_THREADED_CODE
th->retval = Qundef;
#endif
th->name = Qnil;
th->report_on_exception = th->vm->thread_report_on_exception;
+ th->ext_config.ractor_safe = true;
}
static VALUE
ruby_thread_init(VALUE self)
{
- rb_thread_t *th = rb_thread_ptr(self);
- rb_vm_t *vm = GET_THREAD()->vm;
+ rb_thread_t *th = GET_THREAD();
+ rb_thread_t *target_th = rb_thread_ptr(self);
+ rb_vm_t *vm = th->vm;
- th->vm = vm;
- th_init(th, self);
+ target_th->vm = vm;
+ th_init(target_th, self);
+
+ target_th->top_wrapper = 0;
+ target_th->top_self = rb_vm_top_self();
+ target_th->ec->root_svar = Qfalse;
+ target_th->ractor = th->ractor;
- th->top_wrapper = 0;
- th->top_self = rb_vm_top_self();
- th->ec->root_svar = Qfalse;
return self;
}
@@ -2793,8 +3149,9 @@ static VALUE
m_core_undef_method(VALUE self, VALUE cbase, VALUE sym)
{
REWIND_CFP({
- rb_undef(cbase, SYM2ID(sym));
- rb_clear_method_cache_by_class(self);
+ ID mid = SYM2ID(sym);
+ rb_undef(cbase, mid);
+ rb_clear_method_cache(self, mid);
});
return Qnil;
}
@@ -2842,6 +3199,24 @@ m_core_hash_merge_kwd(VALUE recv, VALUE hash, VALUE kw)
}
static VALUE
+m_core_make_shareable(VALUE recv, VALUE obj)
+{
+ return rb_ractor_make_shareable(obj);
+}
+
+static VALUE
+m_core_make_shareable_copy(VALUE recv, VALUE obj)
+{
+ return rb_ractor_make_shareable_copy(obj);
+}
+
+static VALUE
+m_core_ensure_shareable(VALUE recv, VALUE obj, VALUE name)
+{
+ return rb_ractor_ensure_shareable(obj, name);
+}
+
+static VALUE
core_hash_merge_kwd(VALUE hash, VALUE kw)
{
rb_hash_foreach(rb_to_hash_type(kw), kwmerge_i, hash);
@@ -2949,6 +3324,20 @@ f_lambda(VALUE _)
return rb_block_lambda();
}
+static VALUE
+vm_mtbl(VALUE self, VALUE obj, VALUE sym)
+{
+ vm_mtbl_dump(CLASS_OF(obj), RTEST(sym) ? SYM2ID(sym) : 0);
+ return Qnil;
+}
+
+static VALUE
+vm_mtbl2(VALUE self, VALUE obj, VALUE sym)
+{
+ vm_mtbl_dump(obj, RTEST(sym) ? SYM2ID(sym) : 0);
+ return Qnil;
+}
+
void
Init_VM(void)
{
@@ -2979,6 +3368,7 @@ Init_VM(void)
/* FrozenCore (hidden) */
fcore = rb_class_new(rb_cBasicObject);
+ rb_set_class_path(fcore, rb_cRubyVM, "FrozenCore");
RBASIC(fcore)->flags = T_ICLASS;
klass = rb_singleton_class(fcore);
rb_define_method_id(klass, id_core_set_method_alias, m_core_set_method_alias, 3);
@@ -2990,6 +3380,9 @@ Init_VM(void)
rb_define_method_id(klass, id_core_raise, f_raise, -1);
rb_define_method_id(klass, idProc, f_proc, 0);
rb_define_method_id(klass, idLambda, f_lambda, 0);
+ rb_define_method(klass, "make_shareable", m_core_make_shareable, 1);
+ rb_define_method(klass, "make_shareable_copy", m_core_make_shareable_copy, 1);
+ rb_define_method(klass, "ensure_shareable", m_core_ensure_shareable, 2);
rb_obj_freeze(fcore);
RBASIC_CLEAR_CLASS(klass);
rb_obj_freeze(klass);
@@ -3236,9 +3629,13 @@ Init_VM(void)
#if VMDEBUG
rb_define_singleton_method(rb_cRubyVM, "SDR", sdr, 0);
rb_define_singleton_method(rb_cRubyVM, "NSDR", nsdr, 0);
+ rb_define_singleton_method(rb_cRubyVM, "mtbl", vm_mtbl, 2);
+ rb_define_singleton_method(rb_cRubyVM, "mtbl2", vm_mtbl2, 2);
#else
(void)sdr;
(void)nsdr;
+ (void)vm_mtbl;
+ (void)vm_mtbl2;
#endif
/* VM bootstrap: phase 2 */
@@ -3248,21 +3645,21 @@ Init_VM(void)
VALUE filename = rb_fstring_lit("<main>");
const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP);
+ // Ractor setup
+ rb_ractor_main_setup(vm, th->ractor, th);
+
/* create vm object */
vm->self = TypedData_Wrap_Struct(rb_cRubyVM, &vm_data_type, vm);
/* create main thread */
th->self = TypedData_Wrap_Struct(rb_cThread, &thread_data_type, th);
- vm->main_thread = th;
- vm->running_thread = th;
+ vm->ractor.main_thread = th;
+ vm->ractor.main_ractor = th->ractor;
th->vm = vm;
th->top_wrapper = 0;
th->top_self = rb_vm_top_self();
- rb_thread_set_current(th);
- rb_vm_living_threads_insert(vm, th);
-
- rb_gc_register_mark_object((VALUE)iseq);
+ rb_gc_register_mark_object((VALUE)iseq);
th->ec->cfp->iseq = iseq;
th->ec->cfp->pc = iseq->body->iseq_encoded;
th->ec->cfp->self = th->top_self;
@@ -3290,7 +3687,7 @@ Init_VM(void)
void
rb_vm_set_progname(VALUE filename)
{
- rb_thread_t *th = GET_VM()->main_thread;
+ rb_thread_t *th = GET_VM()->ractor.main_thread;
rb_control_frame_t *cfp = (void *)(th->ec->vm_stack + th->ec->vm_stack_size);
--cfp;
@@ -3314,12 +3711,18 @@ Init_BareVM(void)
vm->objspace = rb_objspace_alloc();
ruby_current_vm_ptr = vm;
+ vm->negative_cme_table = rb_id_table_create(16);
Init_native_thread(th);
th->vm = vm;
th_init(th, 0);
- rb_thread_set_current_raw(th);
+ vm->ractor.main_ractor = th->ractor = rb_ractor_main_alloc();
+ rb_ractor_set_current_ec(th->ractor, th->ec);
ruby_thread_init_stack(th);
+
+ rb_native_mutex_initialize(&vm->ractor.sync.lock);
+ rb_native_cond_initialize(&vm->ractor.sync.barrier_cond);
+ rb_native_cond_initialize(&vm->ractor.sync.terminate_cond);
}
void
@@ -3361,28 +3764,18 @@ Init_top_self(void)
rb_define_alias(rb_singleton_class(rb_vm_top_self()), "inspect", "to_s");
}
-static VALUE *
-ruby_vm_verbose_ptr(rb_vm_t *vm)
-{
- return &vm->verbose;
-}
-
-static VALUE *
-ruby_vm_debug_ptr(rb_vm_t *vm)
-{
- return &vm->debug;
-}
-
VALUE *
rb_ruby_verbose_ptr(void)
{
- return ruby_vm_verbose_ptr(GET_VM());
+ rb_ractor_t *cr = GET_RACTOR();
+ return &cr->verbose;
}
VALUE *
rb_ruby_debug_ptr(void)
{
- return ruby_vm_debug_ptr(GET_VM());
+ rb_ractor_t *cr = GET_RACTOR();
+ return &cr->debug;
}
/* iseq.c */
@@ -3656,9 +4049,9 @@ usage_analysis_register_clear(VALUE self)
#else
-MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_insn)(int insn)) = NULL;
-MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)) = NULL;
-MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_register)(int reg, int isset)) = NULL;
+MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_insn)(int insn)) = 0;
+MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op)) = 0;
+MAYBE_UNUSED(static void (*ruby_vm_collect_usage_func_register)(int reg, int isset)) = 0;
#endif
@@ -3703,6 +4096,12 @@ vm_collect_usage_register(int reg, int isset)
}
#endif
+MJIT_FUNC_EXPORTED const struct rb_callcache *
+rb_vm_empty_cc(void)
+{
+ return &vm_empty_cc;
+}
+
#endif /* #ifndef MJIT_HEADER */
#include "vm_call_iseq_optimized.inc" /* required from vm_insnhelper.c */
diff --git a/vm_args.c b/vm_args.c
index cf0328d4b7..9ee2832ad1 100644
--- a/vm_args.c
+++ b/vm_args.c
@@ -12,7 +12,7 @@ NORETURN(static void raise_argument_error(rb_execution_context_t *ec, const rb_i
NORETURN(static void argument_arity_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const int miss_argc, const int min_argc, const int max_argc));
NORETURN(static void argument_kw_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const char *error, const VALUE keys));
VALUE rb_keyword_error_new(const char *error, VALUE keys); /* class.c */
-static VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv,
+static VALUE method_missing(rb_execution_context_t *ec, VALUE obj, ID id, int argc, const VALUE *argv,
enum method_missing_reason call_status, int kw_splat);
#if !defined(_MSC_VER) || !defined(MJIT_HEADER)
MJIT_FUNC_EXPORTED
@@ -27,7 +27,7 @@ struct args_info {
/* additional args info */
int rest_index;
int rest_dupped;
- const struct rb_call_info_kw_arg *kw_arg;
+ const struct rb_callinfo_kwarg *kw_arg;
VALUE *kw_argv;
VALUE rest;
};
@@ -187,128 +187,10 @@ args_rest_array(struct args_info *args)
return ary;
}
-#define KW_HASH_HAS_NO_KEYS 0
-#define KW_HASH_HAS_SYMBOL_KEY 1
-#define KW_HASH_HAS_OTHER_KEY 2
-#define KW_HASH_HAS_BOTH_KEYS 3
-
-static int
-keyword_hash_symbol_other_iter(st_data_t key, st_data_t val, st_data_t arg)
-{
- *(int*)arg |= SYMBOL_P((VALUE)key) ? KW_HASH_HAS_SYMBOL_KEY : KW_HASH_HAS_OTHER_KEY;
-
- if ((*(int*)arg & KW_HASH_HAS_BOTH_KEYS) == KW_HASH_HAS_BOTH_KEYS) {
- return ST_STOP;
- }
-
- return ST_CONTINUE;
-}
-
-static int
-keyword_hash_symbol_other(VALUE hash)
-{
- int symbol_other = KW_HASH_HAS_NO_KEYS;
- rb_hash_stlike_foreach(hash, keyword_hash_symbol_other_iter, (st_data_t)(&symbol_other));
- return symbol_other;
-}
-
-static int
-keyword_hash_split_iter(st_data_t key, st_data_t val, st_data_t arg)
-{
- if (SYMBOL_P((VALUE)key)) {
- rb_hash_aset((VALUE)arg, (VALUE)key, (VALUE)val);
- return ST_DELETE;
- }
-
- return ST_CONTINUE;
-}
-
-static void
-keyword_hash_split(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr)
-{
- *kw_hash_ptr = rb_hash_new();
- rb_hash_stlike_foreach(*rest_hash_ptr, keyword_hash_split_iter, (st_data_t)(*kw_hash_ptr));
-}
-
-static int
-keyword_hash_p(VALUE *kw_hash_ptr, VALUE *rest_hash_ptr, int check_only_symbol)
-{
- *rest_hash_ptr = rb_check_hash_type(*kw_hash_ptr);
-
- if (!NIL_P(*rest_hash_ptr)) {
- if (check_only_symbol) {
- switch (keyword_hash_symbol_other(*rest_hash_ptr)) {
- case KW_HASH_HAS_NO_KEYS:
- case KW_HASH_HAS_SYMBOL_KEY:
- break;
- case KW_HASH_HAS_OTHER_KEY:
- *kw_hash_ptr = Qnil;
- return FALSE;
- case KW_HASH_HAS_BOTH_KEYS:
- *rest_hash_ptr = rb_hash_dup(*rest_hash_ptr);
- keyword_hash_split(kw_hash_ptr, rest_hash_ptr);
- return TRUE;
- }
- }
- *kw_hash_ptr = *rest_hash_ptr;
- *rest_hash_ptr = Qfalse;
- return TRUE;
- }
- else {
- *kw_hash_ptr = Qnil;
- return FALSE;
- }
-}
-
-static VALUE
-args_pop_keyword_hash(struct args_info *args, VALUE *kw_hash_ptr, int check_only_symbol)
-{
- VALUE rest_hash;
-
- if (args->rest == Qfalse) {
- from_argv:
- VM_ASSERT(args->argc > 0);
- *kw_hash_ptr = args->argv[args->argc-1];
-
- if (keyword_hash_p(kw_hash_ptr, &rest_hash, check_only_symbol)) {
- if (rest_hash) {
- args->argv[args->argc-1] = rest_hash;
- }
- else {
- args->argc--;
- return TRUE;
- }
- }
- }
- else {
- long len = RARRAY_LEN(args->rest);
-
- if (len > 0) {
- *kw_hash_ptr = RARRAY_AREF(args->rest, len - 1);
-
- if (keyword_hash_p(kw_hash_ptr, &rest_hash, check_only_symbol)) {
- if (rest_hash) {
- RARRAY_ASET(args->rest, len - 1, rest_hash);
- }
- else {
- arg_rest_dup(args);
- rb_ary_pop(args->rest);
- return TRUE;
- }
- }
- }
- else {
- goto from_argv;
- }
- }
-
- return FALSE;
-}
-
static int
args_kw_argv_to_hash(struct args_info *args)
{
- const struct rb_call_info_kw_arg *kw_arg = args->kw_arg;
+ const struct rb_callinfo_kwarg *kw_arg = args->kw_arg;
const VALUE *const passed_keywords = kw_arg->keywords;
const int kw_len = kw_arg->keyword_len;
VALUE h = rb_hash_new_with_size(kw_len);
@@ -326,29 +208,6 @@ args_kw_argv_to_hash(struct args_info *args)
return args->argc;
}
-static void
-args_stored_kw_argv_to_hash(struct args_info *args)
-{
- int i;
- const struct rb_call_info_kw_arg *kw_arg = args->kw_arg;
- const VALUE *const passed_keywords = kw_arg->keywords;
- const int passed_keyword_len = kw_arg->keyword_len;
- VALUE h = rb_hash_new_with_size(passed_keyword_len);
-
- for (i=0; i<passed_keyword_len; i++) {
- rb_hash_aset(h, passed_keywords[i], args->kw_argv[i]);
- }
- args->kw_argv = NULL;
-
- if (args->rest) {
- arg_rest_dup(args);
- rb_ary_push(args->rest, h);
- }
- else {
- args->argv[args->argc++] = h;
- }
-}
-
static inline void
args_setup_lead_parameters(struct args_info *args, int argc, VALUE *locals)
{
@@ -541,9 +400,15 @@ args_setup_kw_parameters(rb_execution_context_t *const ec, const rb_iseq_t *cons
}
static inline void
-args_setup_kw_rest_parameter(VALUE keyword_hash, VALUE *locals)
+args_setup_kw_rest_parameter(VALUE keyword_hash, VALUE *locals, int kw_flag)
{
- locals[0] = NIL_P(keyword_hash) ? rb_hash_new() : rb_hash_dup(keyword_hash);
+ if (NIL_P(keyword_hash)) {
+ keyword_hash = rb_hash_new();
+ }
+ else if (!(kw_flag & VM_CALL_KW_SPLAT_MUT)) {
+ keyword_hash = rb_hash_dup(keyword_hash);
+ }
+ locals[0] = keyword_hash;
}
static inline void
@@ -570,171 +435,40 @@ fill_keys_values(st_data_t key, st_data_t val, st_data_t ptr)
}
static inline int
-ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq)
-{
- if (!(iseq->body->param.flags.has_kw) &&
- !(iseq->body->param.flags.has_kwrest)) {
- keyword_hash = rb_check_hash_type(keyword_hash);
-
- if (!NIL_P(keyword_hash) && RHASH_EMPTY_P(keyword_hash)) {
- return 1;
- }
- }
-
- return 0;
-}
-
-VALUE rb_iseq_location(const rb_iseq_t *iseq);
-
-/* -- Remove In 3.0 -- */
-
-/* This is a map from caller PC to a set of callee methods.
- * When a warning about keyword argument change is printed,
- * it keeps the pair of callee and caller.
- */
-static st_table *caller_to_callees = 0;
-
-static VALUE
-rb_warn_check(const rb_execution_context_t * const ec, const rb_iseq_t *const iseq)
-{
- if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_DEPRECATED)) return 1;
-
- if (!iseq) return 0;
-
- const st_data_t callee = (st_data_t)(iseq->body->iseq_unique_id * 2);
-
- const rb_control_frame_t * const cfp = rb_vm_get_ruby_level_next_cfp(ec, ec->cfp);
-
- if (!cfp) return 0;
-
- const st_data_t caller = (st_data_t)cfp->pc;
-
- if (!caller_to_callees) {
- caller_to_callees = st_init_numtable();
- }
-
- st_data_t val;
- if (st_lookup(caller_to_callees, caller, &val)) {
- st_table *callees;
-
- if (val & 1) {
- val &= ~(st_data_t)1;
- if (val == callee) return 1; /* already warned */
-
- callees = st_init_numtable();
- st_insert(callees, val, 1);
- }
- else {
- callees = (st_table *) val;
- if (st_is_member(callees, callee)) return 1; /* already warned */
- }
- st_insert(callees, callee, 1);
- st_insert(caller_to_callees, caller, (st_data_t) callees);
- }
- else {
- st_insert(caller_to_callees, caller, callee | 1);
- }
-
- return 0; /* not warned yet for the pair of caller and callee */
-}
-
-static inline void
-rb_warn_keyword_to_last_hash(rb_execution_context_t * const ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
-{
- if (rb_warn_check(ec, iseq)) return;
-
- VALUE name, loc;
- if (calling->recv == Qundef) {
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- return;
- }
- name = rb_id2str(ci->mid);
- loc = rb_iseq_location(iseq);
- if (NIL_P(loc)) {
- rb_warn("Passing the keyword argument for `%"PRIsVALUE"' as the last hash parameter is deprecated",
- name);
- }
- else {
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- if (name) {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method `%"PRIsVALUE"' is defined here", name);
- }
- else {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method is defined here");
- }
- }
-}
-
-static inline void
-rb_warn_split_last_hash_to_keyword(rb_execution_context_t * const ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
-{
- if (rb_warn_check(ec, iseq)) return;
-
- VALUE name, loc;
- name = rb_id2str(ci->mid);
- loc = rb_iseq_location(iseq);
- if (NIL_P(loc)) {
- rb_warn("Splitting the last argument for `%"PRIsVALUE"' into positional and keyword parameters is deprecated",
- name);
- }
- else {
- rb_warn("Splitting the last argument into positional and keyword parameters is deprecated");
- if (calling->recv != Qundef) {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method `%"PRIsVALUE"' is defined here", name);
- }
- else {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method is defined here");
- }
- }
-}
-
-static inline void
-rb_warn_last_hash_to_keyword(rb_execution_context_t * const ec, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t * const iseq)
+ignore_keyword_hash_p(VALUE keyword_hash, const rb_iseq_t * const iseq, unsigned int * kw_flag, VALUE * converted_keyword_hash)
{
- if (rb_warn_check(ec, iseq)) return;
-
- VALUE name, loc;
- name = rb_id2str(ci->mid);
- loc = rb_iseq_location(iseq);
- if (NIL_P(loc)) {
- rb_warn("Using the last argument for `%"PRIsVALUE"' as keyword parameters is deprecated; maybe ** should be added to the call",
- name);
+ if (!RB_TYPE_P(keyword_hash, T_HASH)) {
+ keyword_hash = rb_to_hash_type(keyword_hash);
}
- else {
- rb_warn("Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call");
- if (calling->recv != Qundef) {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method `%"PRIsVALUE"' is defined here", name);
- }
- else {
- rb_compile_warn(RSTRING_PTR(RARRAY_AREF(loc, 0)), FIX2INT(RARRAY_AREF(loc, 1)),
- "The called method is defined here");
- }
+ if (!(*kw_flag & VM_CALL_KW_SPLAT_MUT) &&
+ (iseq->body->param.flags.has_kwrest ||
+ iseq->body->param.flags.ruby2_keywords)) {
+ *kw_flag |= VM_CALL_KW_SPLAT_MUT;
+ keyword_hash = rb_hash_dup(keyword_hash);
}
+ *converted_keyword_hash = keyword_hash;
+ return !(iseq->body->param.flags.has_kw) &&
+ !(iseq->body->param.flags.has_kwrest) &&
+ RHASH_EMPTY_P(keyword_hash);
}
static int
setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * const iseq,
struct rb_calling_info *const calling,
- const struct rb_call_info *ci,
- VALUE * const locals, const enum arg_setup_type arg_setup_type)
+ const struct rb_callinfo *ci,
+ VALUE * const locals, const enum arg_setup_type arg_setup_type)
{
const int min_argc = iseq->body->param.lead_num + iseq->body->param.post_num;
const int max_argc = (iseq->body->param.flags.has_rest == FALSE) ? min_argc + iseq->body->param.opt_num : UNLIMITED_ARGUMENTS;
int given_argc;
- int kw_splat = FALSE;
- unsigned int kw_flag = ci->flag & (VM_CALL_KWARG | VM_CALL_KW_SPLAT);
+ unsigned int kw_flag = vm_ci_flag(ci) & (VM_CALL_KWARG | VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT);
int opt_pc = 0, allow_autosplat = !kw_flag;
struct args_info args_body, *args;
VALUE keyword_hash = Qnil;
VALUE * const orig_sp = ec->cfp->sp;
unsigned int i;
- int remove_empty_keyword_hash = 1;
VALUE flag_keyword_hash = 0;
+ VALUE converted_keyword_hash = 0;
vm_check_canary(ec, orig_sp);
/*
@@ -763,7 +497,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
args->rest_dupped = FALSE;
if (kw_flag & VM_CALL_KWARG) {
- args->kw_arg = ((struct rb_call_info_with_kwarg *)ci)->kw_arg;
+ args->kw_arg = vm_ci_kwarg(ci);
if (iseq->body->param.flags.has_kw) {
int kw_len = args->kw_arg->keyword_len;
@@ -776,7 +510,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
else {
args->kw_argv = NULL;
given_argc = args_kw_argv_to_hash(args);
- kw_flag |= VM_CALL_KW_SPLAT;
+ kw_flag |= VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT;
}
}
else {
@@ -784,11 +518,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
args->kw_argv = NULL;
}
- if (kw_flag && iseq->body->param.flags.ruby2_keywords) {
- remove_empty_keyword_hash = 0;
- }
-
- if (ci->flag & VM_CALL_ARGS_SPLAT) {
+ if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) {
VALUE rest_last = 0;
int len;
args->rest = locals[--args->argc];
@@ -801,10 +531,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
if (RB_TYPE_P(rest_last, T_HASH) &&
(((struct RHash *)rest_last)->basic.flags & RHASH_PASS_AS_KEYWORDS)) {
rest_last = rb_hash_dup(rest_last);
- kw_flag |= VM_CALL_KW_SPLAT;
- if (iseq->body->param.flags.ruby2_keywords) {
- remove_empty_keyword_hash = 0;
- }
+ kw_flag |= VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT;
}
else {
rest_last = 0;
@@ -812,55 +539,53 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
}
if (kw_flag & VM_CALL_KW_SPLAT) {
- if (len > 0 && ignore_keyword_hash_p(rest_last, iseq)) {
- if (given_argc != min_argc) {
- if (remove_empty_keyword_hash) {
- arg_rest_dup(args);
- rb_ary_pop(args->rest);
- given_argc--;
- kw_flag &= ~VM_CALL_KW_SPLAT;
- }
- else {
- if (RB_TYPE_P(rest_last, T_HASH) && rb_obj_frozen_p(rest_last)) {
- rest_last = rb_hash_new();
- RARRAY_ASET(args->rest, len - 1, rest_last);
- }
- flag_keyword_hash = rest_last;
- }
+ if (ignore_keyword_hash_p(rest_last, iseq, &kw_flag, &converted_keyword_hash)) {
+ arg_rest_dup(args);
+ rb_ary_pop(args->rest);
+ given_argc--;
+ kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT);
+ }
+ else {
+ if (rest_last != converted_keyword_hash) {
+ rest_last = converted_keyword_hash;
+ arg_rest_dup(args);
+ RARRAY_ASET(args->rest, len - 1, rest_last);
+ }
+
+ if (iseq->body->param.flags.ruby2_keywords && rest_last) {
+ flag_keyword_hash = rest_last;
}
- else {
- rb_warn_keyword_to_last_hash(ec, calling, ci, iseq);
+ else if (iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) {
+ arg_rest_dup(args);
+ rb_ary_pop(args->rest);
+ given_argc--;
+ keyword_hash = rest_last;
}
- }
- else if (!remove_empty_keyword_hash && rest_last) {
- flag_keyword_hash = rest_last;
}
}
}
else {
if (kw_flag & VM_CALL_KW_SPLAT) {
VALUE last_arg = args->argv[args->argc-1];
- if (ignore_keyword_hash_p(last_arg, iseq)) {
- if (given_argc != min_argc) {
- if (remove_empty_keyword_hash) {
- args->argc--;
- given_argc--;
- kw_flag &= ~VM_CALL_KW_SPLAT;
- }
- else {
- if (RB_TYPE_P(last_arg, T_HASH) && rb_obj_frozen_p(last_arg)) {
- last_arg = rb_hash_new();
- args->argv[args->argc-1] = last_arg;
- }
- flag_keyword_hash = last_arg;
- }
+ if (ignore_keyword_hash_p(last_arg, iseq, &kw_flag, &converted_keyword_hash)) {
+ args->argc--;
+ given_argc--;
+ kw_flag &= ~(VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT);
+ }
+ else {
+ if (last_arg != converted_keyword_hash) {
+ last_arg = converted_keyword_hash;
+ args->argv[args->argc-1] = last_arg;
}
- else {
- rb_warn_keyword_to_last_hash(ec, calling, ci, iseq);
+
+ if (iseq->body->param.flags.ruby2_keywords) {
+ flag_keyword_hash = last_arg;
+ }
+ else if (iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) {
+ args->argc--;
+ given_argc--;
+ keyword_hash = last_arg;
}
- }
- else if (!remove_empty_keyword_hash) {
- flag_keyword_hash = args->argv[args->argc-1];
}
}
args->rest = Qfalse;
@@ -874,14 +599,14 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
rb_raise(rb_eArgError, "no keywords accepted");
}
+
switch (arg_setup_type) {
case arg_setup_method:
break; /* do nothing special */
case arg_setup_block:
- if (given_argc == 1 &&
+ if (given_argc == (keyword_hash == Qnil ? 1 : 2) &&
allow_autosplat &&
- (min_argc > 0 || iseq->body->param.opt_num > 1 ||
- iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest) &&
+ (min_argc > 0 || iseq->body->param.opt_num > 1) &&
!iseq->body->param.flags.ambiguous_param0 &&
args_check_block_arg0(args)) {
given_argc = RARRAY_LENINT(args->rest);
@@ -891,60 +616,13 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
/* argc check */
if (given_argc < min_argc) {
- if (given_argc == min_argc - 1 && args->kw_argv) {
- args_stored_kw_argv_to_hash(args);
- given_argc = args_argc(args);
- }
- else {
- if (arg_setup_type == arg_setup_block) {
- CHECK_VM_STACK_OVERFLOW(ec->cfp, min_argc);
- given_argc = min_argc;
- args_extend(args, min_argc);
- }
- else {
- argument_arity_error(ec, iseq, given_argc, min_argc, max_argc);
- }
- }
- }
-
- if (kw_flag & VM_CALL_KW_SPLAT) {
- kw_splat = !iseq->body->param.flags.has_rest;
- }
- if ((iseq->body->param.flags.has_kw || iseq->body->param.flags.has_kwrest ||
- (kw_splat && given_argc > max_argc)) &&
- args->kw_argv == NULL) {
- if (given_argc > min_argc) {
- if (kw_flag) {
- int check_only_symbol = (kw_flag & VM_CALL_KW_SPLAT) &&
- iseq->body->param.flags.has_kw &&
- !iseq->body->param.flags.has_kwrest;
-
- if (args_pop_keyword_hash(args, &keyword_hash, check_only_symbol)) {
- given_argc--;
- }
- else if (check_only_symbol) {
- if (keyword_hash != Qnil) {
- rb_warn_split_last_hash_to_keyword(ec, calling, ci, iseq);
- }
- else {
- rb_warn_keyword_to_last_hash(ec, calling, ci, iseq);
- }
- }
- }
- else if (args_pop_keyword_hash(args, &keyword_hash, 1)) {
- /* Warn the following:
- * def foo(k:1) p [k]; end
- * foo({k:42}) #=> 42
- */
- rb_warn_last_hash_to_keyword(ec, calling, ci, iseq);
- given_argc--;
- }
- else if (keyword_hash != Qnil) {
- rb_warn_split_last_hash_to_keyword(ec, calling, ci, iseq);
- }
+ if (arg_setup_type == arg_setup_block) {
+ CHECK_VM_STACK_OVERFLOW(ec->cfp, min_argc);
+ given_argc = min_argc;
+ args_extend(args, min_argc);
}
- else if (given_argc == min_argc && kw_flag) {
- rb_warn_keyword_to_last_hash(ec, calling, ci, iseq);
+ else {
+ argument_arity_error(ec, iseq, given_argc, min_argc, max_argc);
}
}
@@ -984,7 +662,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
VALUE * const klocals = locals + iseq->body->param.keyword->bits_start - iseq->body->param.keyword->num;
if (args->kw_argv != NULL) {
- const struct rb_call_info_kw_arg *kw_arg = args->kw_arg;
+ const struct rb_callinfo_kwarg *kw_arg = args->kw_arg;
args_setup_kw_parameters(ec, iseq, args->kw_argv, kw_arg->keyword_len, kw_arg->keywords, klocals);
}
else if (!NIL_P(keyword_hash)) {
@@ -1004,7 +682,7 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
}
}
else if (iseq->body->param.flags.has_kwrest) {
- args_setup_kw_rest_parameter(keyword_hash, locals + iseq->body->param.keyword->rest_start);
+ args_setup_kw_rest_parameter(keyword_hash, locals + iseq->body->param.keyword->rest_start, kw_flag);
}
else if (!NIL_P(keyword_hash) && RHASH_SIZE(keyword_hash) > 0 && arg_setup_type == arg_setup_method) {
argument_kw_error(ec, iseq, "unknown", rb_hash_keys(keyword_hash));
@@ -1032,8 +710,6 @@ setup_parameters_complex(rb_execution_context_t * const ec, const rb_iseq_t * co
return opt_pc;
}
-void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self); /* vm_backtrace.c */
-
static void
raise_argument_error(rb_execution_context_t *ec, const rb_iseq_t *iseq, const VALUE exc)
{
@@ -1112,11 +788,10 @@ vm_caller_setup_arg_splat(rb_control_frame_t *cfp, struct rb_calling_info *calli
}
static inline void
-vm_caller_setup_arg_kw(rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci)
+vm_caller_setup_arg_kw(rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_callinfo *ci)
{
- struct rb_call_info_with_kwarg *ci_kw = (struct rb_call_info_with_kwarg *)ci;
- const VALUE *const passed_keywords = ci_kw->kw_arg->keywords;
- const int kw_len = ci_kw->kw_arg->keyword_len;
+ const VALUE *const passed_keywords = vm_ci_kwarg(ci)->keywords;
+ const int kw_len = vm_ci_kwarg(ci)->keyword_len;
const VALUE h = rb_hash_new_with_size(kw_len);
VALUE *sp = cfp->sp;
int i;
@@ -1164,13 +839,11 @@ refine_sym_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
{
VALUE obj;
ID mid;
- const rb_callable_method_entry_t *me;
+ const rb_callable_method_entry_t *me = 0; /* for hidden object case */
rb_execution_context_t *ec;
const VALUE symbol = RARRAY_AREF(callback_arg, 0);
const VALUE refinements = RARRAY_AREF(callback_arg, 1);
int kw_splat = RB_PASS_CALLED_KEYWORDS;
- VALUE v;
- VALUE ret;
VALUE klass;
if (argc-- < 1) {
@@ -1191,22 +864,17 @@ refine_sym_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg))
if (!NIL_P(blockarg)) {
vm_passed_block_handler_set(ec, blockarg);
}
- v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
if (!me) {
- ret = method_missing(obj, mid, argc, argv, MISSING_NOENTRY, kw_splat);
- }
- else {
- ret = rb_vm_call0(ec, obj, mid, argc, argv, me, kw_splat);
+ return method_missing(ec, obj, mid, argc, argv, MISSING_NOENTRY, kw_splat);
}
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_vm_call0(ec, obj, mid, argc, argv, me, kw_splat);
}
static VALUE
vm_caller_setup_arg_block(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp,
- const struct rb_call_info *ci, const rb_iseq_t *blockiseq, const int is_super)
+ const struct rb_callinfo *ci, const rb_iseq_t *blockiseq, const int is_super)
{
- if (ci->flag & VM_CALL_ARGS_BLOCKARG) {
+ if (vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) {
VALUE block_code = *(--reg_cfp->sp);
if (NIL_P(block_code)) {
@@ -1229,7 +897,7 @@ vm_caller_setup_arg_block(const rb_execution_context_t *ec, rb_control_frame_t *
rb_ary_push(callback_arg, block_code);
rb_ary_push(callback_arg, ref);
OBJ_FREEZE_RAW(callback_arg);
- func = rb_func_proc_new(refine_sym_proc_call, callback_arg);
+ func = rb_func_lambda_new(refine_sym_proc_call, callback_arg, 1, UNLIMITED_ARGUMENTS);
rb_hash_aset(ref, block_code, func);
}
block_code = func;
diff --git a/vm_backtrace.c b/vm_backtrace.c
index f6b4e8e1d6..70c2ab7b8a 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -9,13 +9,13 @@
**********************************************************************/
-#include "ruby/encoding.h"
-#include "ruby/debug.h"
-#include "internal.h"
-
-#include "vm_core.h"
#include "eval_intern.h"
+#include "internal.h"
+#include "internal/vm.h"
#include "iseq.h"
+#include "ruby/debug.h"
+#include "ruby/encoding.h"
+#include "vm_core.h"
static VALUE rb_cBacktrace;
static VALUE rb_cBacktraceLocation;
@@ -29,6 +29,9 @@ id2str(ID id)
}
#define rb_id2str(id) id2str(id)
+#define BACKTRACE_START 0
+#define ALL_BACKTRACE_LINES -1
+
inline static int
calc_lineno(const rb_iseq_t *iseq, const VALUE *pc)
{
@@ -87,7 +90,6 @@ typedef struct rb_backtrace_location_struct {
LOCATION_TYPE_ISEQ = 1,
LOCATION_TYPE_ISEQ_CALCED,
LOCATION_TYPE_CFUNC,
- LOCATION_TYPE_IFUNC
} type;
union {
@@ -123,10 +125,9 @@ location_mark_entry(rb_backtrace_location_t *fi)
switch (fi->type) {
case LOCATION_TYPE_ISEQ:
case LOCATION_TYPE_ISEQ_CALCED:
- rb_gc_mark((VALUE)fi->body.iseq.iseq);
+ rb_gc_mark_movable((VALUE)fi->body.iseq.iseq);
break;
case LOCATION_TYPE_CFUNC:
- case LOCATION_TYPE_IFUNC:
default:
break;
}
@@ -196,7 +197,6 @@ location_label(rb_backtrace_location_t *loc)
return loc->body.iseq.iseq->body->location.label;
case LOCATION_TYPE_CFUNC:
return rb_id2str(loc->body.cfunc.mid);
- case LOCATION_TYPE_IFUNC:
default:
rb_bug("location_label: unreachable");
UNREACHABLE;
@@ -245,7 +245,6 @@ location_base_label(rb_backtrace_location_t *loc)
return loc->body.iseq.iseq->body->location.base_label;
case LOCATION_TYPE_CFUNC:
return rb_id2str(loc->body.cfunc.mid);
- case LOCATION_TYPE_IFUNC:
default:
rb_bug("location_base_label: unreachable");
UNREACHABLE;
@@ -275,7 +274,6 @@ location_path(rb_backtrace_location_t *loc)
return location_path(loc->body.cfunc.prev_loc);
}
return Qnil;
- case LOCATION_TYPE_IFUNC:
default:
rb_bug("location_path: unreachable");
UNREACHABLE;
@@ -283,7 +281,9 @@ location_path(rb_backtrace_location_t *loc)
}
/*
- * Returns the file name of this frame.
+ * Returns the file name of this frame. This will generally be an absolute
+ * path, unless the frame is in the main script, in which case it will be the
+ * script location passed on the command line.
*
* For example, using +caller_locations.rb+ from Thread::Backtrace::Location
*
@@ -308,7 +308,6 @@ location_realpath(rb_backtrace_location_t *loc)
return location_realpath(loc->body.cfunc.prev_loc);
}
return Qnil;
- case LOCATION_TYPE_IFUNC:
default:
rb_bug("location_realpath: unreachable");
UNREACHABLE;
@@ -318,7 +317,8 @@ location_realpath(rb_backtrace_location_t *loc)
/*
* Returns the full file path of this frame.
*
- * Same as #path, but includes the absolute path.
+ * Same as #path, except that it will return absolute path
+ * even if the frame is in the main script.
*/
static VALUE
location_absolute_path_m(VALUE self)
@@ -373,7 +373,6 @@ location_to_str(rb_backtrace_location_t *loc)
}
name = rb_id2str(loc->body.cfunc.mid);
break;
- case LOCATION_TYPE_IFUNC:
default:
rb_bug("location_to_str: unreachable");
}
@@ -402,7 +401,6 @@ location_inspect_m(VALUE self)
typedef struct rb_backtrace_struct {
rb_backtrace_location_t *backtrace;
- rb_backtrace_location_t *backtrace_base;
int backtrace_size;
VALUE strary;
VALUE locary;
@@ -417,18 +415,45 @@ backtrace_mark(void *ptr)
for (i=0; i<s; i++) {
location_mark_entry(&bt->backtrace[i]);
}
- rb_gc_mark(bt->strary);
- rb_gc_mark(bt->locary);
+ rb_gc_mark_movable(bt->strary);
+ rb_gc_mark_movable(bt->locary);
}
static void
backtrace_free(void *ptr)
{
rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
- if (bt->backtrace) ruby_xfree(bt->backtrace_base);
+ if (bt->backtrace) ruby_xfree(bt->backtrace);
ruby_xfree(bt);
}
+static void
+location_update_entry(rb_backtrace_location_t *fi)
+{
+ switch (fi->type) {
+ case LOCATION_TYPE_ISEQ:
+ case LOCATION_TYPE_ISEQ_CALCED:
+ fi->body.iseq.iseq = (rb_iseq_t*)rb_gc_location((VALUE)fi->body.iseq.iseq);
+ break;
+ case LOCATION_TYPE_CFUNC:
+ default:
+ break;
+ }
+}
+
+static void
+backtrace_update(void *ptr)
+{
+ rb_backtrace_t *bt = (rb_backtrace_t *)ptr;
+ size_t i, s = bt->backtrace_size;
+
+ for (i=0; i<s; i++) {
+ location_update_entry(&bt->backtrace[i]);
+ }
+ bt->strary = rb_gc_location(bt->strary);
+ bt->locary = rb_gc_location(bt->locary);
+}
+
static size_t
backtrace_memsize(const void *ptr)
{
@@ -438,7 +463,7 @@ backtrace_memsize(const void *ptr)
static const rb_data_type_t backtrace_data_type = {
"backtrace",
- {backtrace_mark, backtrace_free, backtrace_memsize,},
+ {backtrace_mark, backtrace_free, backtrace_memsize, backtrace_update},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -456,22 +481,50 @@ backtrace_alloc(VALUE klass)
return obj;
}
-static void
+static long
+backtrace_size(const rb_execution_context_t *ec)
+{
+ const rb_control_frame_t *last_cfp = ec->cfp;
+ const rb_control_frame_t *start_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
+
+ if (start_cfp == NULL) {
+ return -1;
+ }
+
+ start_cfp =
+ RUBY_VM_NEXT_CONTROL_FRAME(
+ RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); /* skip top frames */
+
+ if (start_cfp < last_cfp) {
+ return 0;
+ }
+
+ return start_cfp - last_cfp + 1;
+}
+
+static bool is_internal_location(const rb_control_frame_t *cfp);
+static void bt_iter_skip_skip_internal(void *ptr, const rb_control_frame_t *cfp);
+
+static int
backtrace_each(const rb_execution_context_t *ec,
+ ptrdiff_t from_last,
+ long num_frames,
void (*init)(void *arg, size_t size),
void (*iter_iseq)(void *arg, const rb_control_frame_t *cfp),
void (*iter_cfunc)(void *arg, const rb_control_frame_t *cfp, ID mid),
+ void (*iter_skip)(void *arg, const rb_control_frame_t *cfp),
void *arg)
{
const rb_control_frame_t *last_cfp = ec->cfp;
const rb_control_frame_t *start_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
const rb_control_frame_t *cfp;
- ptrdiff_t size, i;
+ ptrdiff_t size, real_size, i, j, last, start = 0;
+ int ret = 0;
// In the case the thread vm_stack or cfp is not initialized, there is no backtrace.
if (start_cfp == NULL) {
init(arg, 0);
- return;
+ return ret;
}
/* <- start_cfp (end control frame)
@@ -489,21 +542,94 @@ backtrace_each(const rb_execution_context_t *ec,
RUBY_VM_NEXT_CONTROL_FRAME(start_cfp)); /* skip top frames */
if (start_cfp < last_cfp) {
- size = 0;
+ real_size = size = last = 0;
}
else {
- size = start_cfp - last_cfp + 1;
+ /* Ensure we don't look at frames beyond the ones requested */
+ for(; from_last > 0 && start_cfp >= last_cfp; from_last--) {
+ if (last_cfp->iseq && !last_cfp->pc) {
+ from_last++;
+ }
+ last_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(last_cfp);
+ }
+
+ real_size = size = start_cfp - last_cfp + 1;
+
+ if (from_last > size) {
+ size = last = 0;
+ ret = 1;
+ }
+ else if (num_frames >= 0 && num_frames < size) {
+ if (from_last + num_frames > size) {
+ size -= from_last;
+ last = size;
+ }
+ else {
+ start = size - from_last - num_frames;
+ size = num_frames;
+ last = start + size;
+ }
+ }
+ else {
+ size -= from_last;
+ last = size;
+ }
}
init(arg, size);
- /* SDR(); */
- for (i=0, cfp = start_cfp; i<size; i++, cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
+ /* If a limited number of frames is requested, scan the VM stack for
+ * from the current frame (after skipping the number of frames requested above)
+ * towards the earliest frame (start_cfp). Track the total number of frames
+ * and the number of frames that will be part of the backtrace. Start the
+ * scan at the oldest frame that should still be part of the backtrace.
+ *
+ * If the last frame in the backtrace is a cfunc frame, continue scanning
+ * till earliest frame to find the first iseq frame with pc, so that the
+ * location can be used for the trailing cfunc frames in the backtrace.
+ */
+ if (start > 0 && num_frames >= 0 && num_frames < real_size) {
+ int found_frames = 0, total_frames = 0;
+ bool last_frame_cfunc = FALSE;
+ const rb_control_frame_t *new_start_cfp;
+
+ for (cfp = last_cfp; found_frames < num_frames && start_cfp >= cfp; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp), total_frames++) {
+ if ((cfp->iseq && cfp->pc) || RUBYVM_CFUNC_FRAME_P(cfp)) {
+ last_frame_cfunc = RUBYVM_CFUNC_FRAME_P(cfp);
+ found_frames++;
+ }
+ }
+ new_start_cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp);
+ if (iter_skip && (last_frame_cfunc || iter_skip == bt_iter_skip_skip_internal)) {
+ for (; start_cfp >= cfp; cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)) {
+ if (cfp->iseq && cfp->pc && (iter_skip != bt_iter_skip_skip_internal || !is_internal_location(cfp))) {
+ iter_skip(arg, cfp);
+ break;
+ }
+ }
+ }
+
+ last = found_frames;
+ real_size = total_frames;
+ start = 0;
+ start_cfp = new_start_cfp;
+ }
+
+ for (i=0, j=0, cfp = start_cfp; i<last && j<real_size; i++, j++, cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) {
+ if (j < start) {
+ if (iter_skip) {
+ iter_skip(arg, cfp);
+ }
+ continue;
+ }
+
/* fprintf(stderr, "cfp: %d\n", (rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size) - cfp); */
if (cfp->iseq) {
- if (cfp->pc) {
- iter_iseq(arg, cfp);
- }
+ if (cfp->pc) {
+ iter_iseq(arg, cfp);
+ } else {
+ i--;
+ }
}
else if (RUBYVM_CFUNC_FRAME_P(cfp)) {
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
@@ -512,22 +638,37 @@ backtrace_each(const rb_execution_context_t *ec,
iter_cfunc(arg, cfp, mid);
}
}
+
+ return ret;
}
struct bt_iter_arg {
rb_backtrace_t *bt;
VALUE btobj;
rb_backtrace_location_t *prev_loc;
+ const rb_control_frame_t *prev_cfp;
+ rb_backtrace_location_t *init_loc;
};
+static bool
+is_internal_location(const rb_control_frame_t *cfp)
+{
+ static const char prefix[] = "<internal:";
+ const size_t prefix_len = sizeof(prefix) - 1;
+ VALUE file = rb_iseq_path(cfp->iseq);
+ return strncmp(prefix, RSTRING_PTR(file), prefix_len) == 0;
+}
+
static void
bt_init(void *ptr, size_t size)
{
struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
arg->btobj = backtrace_alloc(rb_cBacktrace);
GetCoreDataFromValue(arg->btobj, rb_backtrace_t, arg->bt);
- arg->bt->backtrace_base = arg->bt->backtrace = ALLOC_N(rb_backtrace_location_t, size);
- arg->bt->backtrace_size = 0;
+ arg->bt->backtrace = ZALLOC_N(rb_backtrace_location_t, size+1);
+ arg->bt->backtrace_size = 1;
+ arg->prev_cfp = NULL;
+ arg->init_loc = &arg->bt->backtrace[size];
}
static void
@@ -536,7 +677,7 @@ bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
const rb_iseq_t *iseq = cfp->iseq;
const VALUE *pc = cfp->pc;
struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
- rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
+ rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++-1];
loc->type = LOCATION_TYPE_ISEQ;
loc->body.iseq.iseq = iseq;
loc->body.iseq.lineno.pc = pc;
@@ -544,44 +685,103 @@ bt_iter_iseq(void *ptr, const rb_control_frame_t *cfp)
}
static void
+bt_iter_iseq_skip_internal(void *ptr, const rb_control_frame_t *cfp)
+{
+ struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
+ rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++-1];
+
+ if (!is_internal_location(cfp)) {
+ loc->type = LOCATION_TYPE_ISEQ;
+ loc->body.iseq.iseq = cfp->iseq;
+ loc->body.iseq.lineno.pc = cfp->pc;
+ arg->prev_loc = loc;
+ } else if (arg->prev_cfp) {
+ loc->type = LOCATION_TYPE_ISEQ;
+ loc->body.iseq.iseq = arg->prev_cfp->iseq;
+ loc->body.iseq.lineno.pc = arg->prev_cfp->pc;
+ arg->prev_loc = loc;
+ } else {
+ rb_bug("No non-internal backtrace entry before an <internal: backtrace entry");
+ }
+}
+
+static void
bt_iter_cfunc(void *ptr, const rb_control_frame_t *cfp, ID mid)
{
struct bt_iter_arg *arg = (struct bt_iter_arg *)ptr;
- rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++];
+ rb_backtrace_location_t *loc = &arg->bt->backtrace[arg->bt->backtrace_size++-1];
loc->type = LOCATION_TYPE_CFUNC;
loc->body.cfunc.mid = mid;
- loc->body.cfunc.prev_loc = arg->prev_loc;
+ if (arg->prev_loc) {
+ loc->body.cfunc.prev_loc = arg->prev_loc;
+ }
+ else if (arg->prev_cfp) {
+ const rb_iseq_t *iseq = arg->prev_cfp->iseq;
+ const VALUE *pc = arg->prev_cfp->pc;
+ arg->init_loc->type = LOCATION_TYPE_ISEQ;
+ arg->init_loc->body.iseq.iseq = iseq;
+ arg->init_loc->body.iseq.lineno.pc = pc;
+ loc->body.cfunc.prev_loc = arg->prev_loc = arg->init_loc;
+ } else {
+ loc->body.cfunc.prev_loc = NULL;
+ }
}
-MJIT_FUNC_EXPORTED VALUE
-rb_ec_backtrace_object(const rb_execution_context_t *ec)
+static void
+bt_iter_skip(void *ptr, const rb_control_frame_t *cfp)
+{
+ if (cfp->iseq && cfp->pc) {
+ ((struct bt_iter_arg *)ptr)->prev_cfp = cfp;
+ }
+}
+
+static void
+bt_iter_skip_skip_internal(void *ptr, const rb_control_frame_t *cfp)
+{
+ if (cfp->iseq && cfp->pc) {
+ if (!is_internal_location(cfp)) {
+ ((struct bt_iter_arg *) ptr)->prev_cfp = cfp;
+ }
+ }
+}
+
+static VALUE
+rb_ec_partial_backtrace_object(const rb_execution_context_t *ec, long lev, long n, int* level_too_large, bool skip_internal)
{
struct bt_iter_arg arg;
+ int too_large;
arg.prev_loc = 0;
- backtrace_each(ec,
- bt_init,
- bt_iter_iseq,
- bt_iter_cfunc,
- &arg);
+ too_large = backtrace_each(ec,
+ lev,
+ n,
+ bt_init,
+ skip_internal ? bt_iter_iseq_skip_internal : bt_iter_iseq,
+ bt_iter_cfunc,
+ skip_internal ? bt_iter_skip_skip_internal : bt_iter_skip,
+ &arg);
+
+ if (level_too_large) *level_too_large = too_large;
return arg.btobj;
}
+MJIT_FUNC_EXPORTED VALUE
+rb_ec_backtrace_object(const rb_execution_context_t *ec)
+{
+ return rb_ec_partial_backtrace_object(ec, BACKTRACE_START, ALL_BACKTRACE_LINES, NULL, FALSE);
+}
+
static VALUE
-backtrace_collect(rb_backtrace_t *bt, long lev, long n, VALUE (*func)(rb_backtrace_location_t *, void *arg), void *arg)
+backtrace_collect(rb_backtrace_t *bt, VALUE (*func)(rb_backtrace_location_t *, void *arg), void *arg)
{
VALUE btary;
int i;
- if (UNLIKELY(lev < 0 || n < 0)) {
- rb_bug("backtrace_collect: unreachable");
- }
-
- btary = rb_ary_new2(n);
+ btary = rb_ary_new2(bt->backtrace_size-1);
- for (i=0; i+lev<bt->backtrace_size && i<n; i++) {
- rb_backtrace_location_t *loc = &bt->backtrace[bt->backtrace_size - 1 - (lev+i)];
+ for (i=0; i<bt->backtrace_size-1; i++) {
+ rb_backtrace_location_t *loc = &bt->backtrace[bt->backtrace_size - 2 - i];
rb_ary_push(btary, func(loc, arg));
}
@@ -595,23 +795,12 @@ location_to_str_dmyarg(rb_backtrace_location_t *loc, void *dmy)
}
static VALUE
-backtrace_to_str_ary(VALUE self, long lev, long n)
+backtrace_to_str_ary(VALUE self)
{
- rb_backtrace_t *bt;
- int size;
VALUE r;
-
+ rb_backtrace_t *bt;
GetCoreDataFromValue(self, rb_backtrace_t, bt);
- size = bt->backtrace_size;
-
- if (n == 0) {
- n = size;
- }
- if (lev > size) {
- return Qnil;
- }
-
- r = backtrace_collect(bt, lev, n, location_to_str_dmyarg, 0);
+ r = backtrace_collect(bt, location_to_str_dmyarg, 0);
RB_GC_GUARD(self);
return r;
}
@@ -623,7 +812,7 @@ rb_backtrace_to_str_ary(VALUE self)
GetCoreDataFromValue(self, rb_backtrace_t, bt);
if (!bt->strary) {
- bt->strary = backtrace_to_str_ary(self, 0, bt->backtrace_size);
+ bt->strary = backtrace_to_str_ary(self);
}
return bt->strary;
}
@@ -636,9 +825,9 @@ rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self)
rb_backtrace_location_t *loc;
GetCoreDataFromValue(self, rb_backtrace_t, bt);
- VM_ASSERT(bt->backtrace_size > 0);
+ VM_ASSERT(bt->backtrace_size > 1);
- loc = &bt->backtrace[bt->backtrace_size - 1];
+ loc = &bt->backtrace[bt->backtrace_size - 2];
iseq = loc->body.iseq.iseq;
VM_ASSERT(loc->type == LOCATION_TYPE_ISEQ);
@@ -661,23 +850,12 @@ location_create(rb_backtrace_location_t *srcloc, void *btobj)
}
static VALUE
-backtrace_to_location_ary(VALUE self, long lev, long n)
+backtrace_to_location_ary(VALUE self)
{
- rb_backtrace_t *bt;
- int size;
VALUE r;
-
+ rb_backtrace_t *bt;
GetCoreDataFromValue(self, rb_backtrace_t, bt);
- size = bt->backtrace_size;
-
- if (n == 0) {
- n = size;
- }
- if (lev > size) {
- return Qnil;
- }
-
- r = backtrace_collect(bt, lev, n, location_create, (void *)self);
+ r = backtrace_collect(bt, location_create, (void *)self);
RB_GC_GUARD(self);
return r;
}
@@ -689,7 +867,7 @@ rb_backtrace_to_location_ary(VALUE self)
GetCoreDataFromValue(self, rb_backtrace_t, bt);
if (!bt->locary) {
- bt->locary = backtrace_to_location_ary(self, 0, 0);
+ bt->locary = backtrace_to_location_ary(self);
}
return bt->locary;
}
@@ -713,13 +891,13 @@ backtrace_load_data(VALUE self, VALUE str)
VALUE
rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n)
{
- return backtrace_to_str_ary(rb_ec_backtrace_object(ec), lev, n);
+ return backtrace_to_str_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, FALSE));
}
VALUE
-rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n)
+rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal)
{
- return backtrace_to_location_ary(rb_ec_backtrace_object(ec), lev, n);
+ return backtrace_to_location_ary(rb_ec_partial_backtrace_object(ec, lev, n, NULL, skip_internal));
}
/* make old style backtrace directly */
@@ -786,9 +964,12 @@ vm_backtrace_print(FILE *fp)
arg.func = oldbt_print;
arg.data = (void *)fp;
backtrace_each(GET_EC(),
+ BACKTRACE_START,
+ ALL_BACKTRACE_LINES,
oldbt_init,
oldbt_iter_iseq,
oldbt_iter_cfunc,
+ NULL,
&arg);
}
@@ -819,9 +1000,12 @@ rb_backtrace_print_as_bugreport(void)
arg.data = (int *)&i;
backtrace_each(GET_EC(),
+ BACKTRACE_START,
+ ALL_BACKTRACE_LINES,
oldbt_init,
oldbt_iter_iseq,
oldbt_iter_cfunc,
+ NULL,
&arg);
}
@@ -862,16 +1046,19 @@ rb_backtrace_each(VALUE (*iter)(VALUE recv, VALUE str), VALUE output)
arg.func = oldbt_print_to;
arg.data = &parg;
backtrace_each(GET_EC(),
+ BACKTRACE_START,
+ ALL_BACKTRACE_LINES,
oldbt_init,
oldbt_iter_iseq,
oldbt_iter_cfunc,
+ NULL,
&arg);
}
VALUE
rb_make_backtrace(void)
{
- return rb_ec_backtrace_str_ary(GET_EC(), 0, 0);
+ return rb_ec_backtrace_str_ary(GET_EC(), BACKTRACE_START, ALL_BACKTRACE_LINES);
}
static VALUE
@@ -879,11 +1066,9 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg
{
VALUE level, vn;
long lev, n;
- VALUE btval = rb_ec_backtrace_object(ec);
+ VALUE btval;
VALUE r;
- rb_backtrace_t *bt;
-
- GetCoreDataFromValue(btval, rb_backtrace_t, bt);
+ int too_large;
rb_scan_args(argc, argv, "02", &level, &vn);
@@ -892,19 +1077,19 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg
switch (argc) {
case 0:
lev = lev_default + lev_plus;
- n = bt->backtrace_size - lev;
+ n = ALL_BACKTRACE_LINES;
break;
case 1:
{
- long beg, len;
- switch (rb_range_beg_len(level, &beg, &len, bt->backtrace_size - lev_plus, 0)) {
+ long beg, len, bt_size = backtrace_size(ec);
+ switch (rb_range_beg_len(level, &beg, &len, bt_size - lev_plus, 0)) {
case Qfalse:
lev = NUM2LONG(level);
if (lev < 0) {
rb_raise(rb_eArgError, "negative level (%ld)", lev);
}
lev += lev_plus;
- n = bt->backtrace_size - lev;
+ n = ALL_BACKTRACE_LINES;
break;
case Qnil:
return Qnil;
@@ -935,11 +1120,17 @@ ec_backtrace_to_ary(const rb_execution_context_t *ec, int argc, const VALUE *arg
return rb_ary_new();
}
+ btval = rb_ec_partial_backtrace_object(ec, lev, n, &too_large, FALSE);
+
+ if (too_large) {
+ return Qnil;
+ }
+
if (to_str) {
- r = backtrace_to_str_ary(btval, lev, n);
+ r = backtrace_to_str_ary(btval);
}
else {
- r = backtrace_to_location_ary(btval, lev, n);
+ r = backtrace_to_location_ary(btval);
}
RB_GC_GUARD(btval);
return r;
@@ -968,6 +1159,16 @@ rb_vm_thread_backtrace_locations(int argc, const VALUE *argv, VALUE thval)
return thread_backtrace_to_ary(argc, argv, thval, 0);
}
+VALUE rb_vm_backtrace(int argc, const VALUE * argv, struct rb_execution_context_struct * ec)
+{
+ return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 1);
+}
+
+VALUE rb_vm_backtrace_locations(int argc, const VALUE * argv, struct rb_execution_context_struct * ec)
+{
+ return ec_backtrace_to_ary(ec, argc, argv, 0, 0, 0);
+}
+
/*
* call-seq:
* caller(start=1, length=nil) -> array or nil
@@ -1201,9 +1402,12 @@ collect_caller_bindings(const rb_execution_context_t *ec)
data.ary = rb_ary_new();
backtrace_each(ec,
+ BACKTRACE_START,
+ ALL_BACKTRACE_LINES,
collect_caller_bindings_init,
collect_caller_bindings_iseq,
collect_caller_bindings_cfunc,
+ NULL,
&data);
result = rb_ary_reverse(data.ary);
@@ -1240,7 +1444,7 @@ rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data)
dbg_context.ec = ec;
dbg_context.cfp = dbg_context.ec->cfp;
- dbg_context.backtrace = rb_ec_backtrace_location_ary(ec, 0, 0);
+ dbg_context.backtrace = rb_ec_backtrace_location_ary(ec, BACKTRACE_START, ALL_BACKTRACE_LINES, FALSE);
dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace);
dbg_context.contexts = collect_caller_bindings(ec);
@@ -1332,6 +1536,14 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines)
i++;
}
+ else {
+ cme = rb_vm_frame_method_entry(cfp);
+ if (cme && cme->def->type == VM_METHOD_TYPE_CFUNC) {
+ buff[i] = (VALUE)cme;
+ if (lines) lines[i] = 0;
+ i++;
+ }
+ }
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
}
@@ -1371,9 +1583,42 @@ rb_profile_frame_path(VALUE frame)
return iseq ? rb_iseq_path(iseq) : Qnil;
}
+static const rb_callable_method_entry_t *
+cframe(VALUE frame)
+{
+ if (frame == Qnil) return NULL;
+
+ if (RB_TYPE_P(frame, T_IMEMO)) {
+ switch (imemo_type(frame)) {
+ case imemo_ment:
+ {
+ const rb_callable_method_entry_t *cme = (rb_callable_method_entry_t *)frame;
+ switch (cme->def->type) {
+ case VM_METHOD_TYPE_CFUNC:
+ return cme;
+ default:
+ return NULL;
+ }
+ }
+ default:
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
VALUE
rb_profile_frame_absolute_path(VALUE frame)
{
+ if (cframe(frame)) {
+ static VALUE cfunc_str = Qfalse;
+ if (!cfunc_str) {
+ cfunc_str = rb_str_new_literal("<cfunc>");
+ rb_gc_register_mark_object(cfunc_str);
+ }
+ return cfunc_str;
+ }
const rb_iseq_t *iseq = frame2iseq(frame);
return iseq ? rb_iseq_realpath(iseq) : Qnil;
}
@@ -1451,15 +1696,18 @@ rb_profile_frame_singleton_method_p(VALUE frame)
VALUE
rb_profile_frame_method_name(VALUE frame)
{
+ const rb_callable_method_entry_t *cme = cframe(frame);
+ if (cme) {
+ ID mid = cme->def->original_id;
+ return id2str(mid);
+ }
const rb_iseq_t *iseq = frame2iseq(frame);
return iseq ? rb_iseq_method_name(iseq) : Qnil;
}
-VALUE
-rb_profile_frame_qualified_method_name(VALUE frame)
+static VALUE
+qualified_method_name(VALUE frame, VALUE method_name)
{
- VALUE method_name = rb_profile_frame_method_name(frame);
-
if (method_name != Qnil) {
VALUE classpath = rb_profile_frame_classpath(frame);
VALUE singleton_p = rb_profile_frame_singleton_method_p(frame);
@@ -1478,8 +1726,23 @@ rb_profile_frame_qualified_method_name(VALUE frame)
}
VALUE
+rb_profile_frame_qualified_method_name(VALUE frame)
+{
+ VALUE method_name = rb_profile_frame_method_name(frame);
+
+ return qualified_method_name(frame, method_name);
+}
+
+VALUE
rb_profile_frame_full_label(VALUE frame)
{
+ const rb_callable_method_entry_t *cme = cframe(frame);
+ if (cme) {
+ ID mid = cme->def->original_id;
+ VALUE method_name = id2str(mid);
+ return qualified_method_name(frame, method_name);
+ }
+
VALUE label = rb_profile_frame_label(frame);
VALUE base_label = rb_profile_frame_base_label(frame);
VALUE qualified_method_name = rb_profile_frame_qualified_method_name(frame);
diff --git a/vm_callinfo.h b/vm_callinfo.h
new file mode 100644
index 0000000000..081b67d2b9
--- /dev/null
+++ b/vm_callinfo.h
@@ -0,0 +1,455 @@
+#ifndef RUBY_VM_CALLINFO_H /*-*-C-*-vi:se ft=c:*/
+#define RUBY_VM_CALLINFO_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.
+ */
+
+#include "debug_counter.h"
+
+enum vm_call_flag_bits {
+ VM_CALL_ARGS_SPLAT_bit, /* m(*args) */
+ VM_CALL_ARGS_BLOCKARG_bit, /* m(&block) */
+ VM_CALL_FCALL_bit, /* m(...) */
+ VM_CALL_VCALL_bit, /* m */
+ VM_CALL_ARGS_SIMPLE_bit, /* (ci->flag & (SPLAT|BLOCKARG)) && blockiseq == NULL && ci->kw_arg == NULL */
+ VM_CALL_BLOCKISEQ_bit, /* has blockiseq */
+ VM_CALL_KWARG_bit, /* has kwarg */
+ VM_CALL_KW_SPLAT_bit, /* m(**opts) */
+ VM_CALL_TAILCALL_bit, /* located at tail position */
+ VM_CALL_SUPER_bit, /* super */
+ VM_CALL_ZSUPER_bit, /* zsuper */
+ VM_CALL_OPT_SEND_bit, /* internal flag */
+ VM_CALL_KW_SPLAT_MUT_bit, /* kw splat hash can be modified (to avoid allocating a new one) */
+ VM_CALL__END
+};
+
+#define VM_CALL_ARGS_SPLAT (0x01 << VM_CALL_ARGS_SPLAT_bit)
+#define VM_CALL_ARGS_BLOCKARG (0x01 << VM_CALL_ARGS_BLOCKARG_bit)
+#define VM_CALL_FCALL (0x01 << VM_CALL_FCALL_bit)
+#define VM_CALL_VCALL (0x01 << VM_CALL_VCALL_bit)
+#define VM_CALL_ARGS_SIMPLE (0x01 << VM_CALL_ARGS_SIMPLE_bit)
+#define VM_CALL_BLOCKISEQ (0x01 << VM_CALL_BLOCKISEQ_bit)
+#define VM_CALL_KWARG (0x01 << VM_CALL_KWARG_bit)
+#define VM_CALL_KW_SPLAT (0x01 << VM_CALL_KW_SPLAT_bit)
+#define VM_CALL_TAILCALL (0x01 << VM_CALL_TAILCALL_bit)
+#define VM_CALL_SUPER (0x01 << VM_CALL_SUPER_bit)
+#define VM_CALL_ZSUPER (0x01 << VM_CALL_ZSUPER_bit)
+#define VM_CALL_OPT_SEND (0x01 << VM_CALL_OPT_SEND_bit)
+#define VM_CALL_KW_SPLAT_MUT (0x01 << VM_CALL_KW_SPLAT_MUT_bit)
+
+struct rb_callinfo_kwarg {
+ int keyword_len;
+ VALUE keywords[];
+};
+
+static inline size_t
+rb_callinfo_kwarg_bytes(int keyword_len)
+{
+ return rb_size_mul_add_or_raise(
+ keyword_len,
+ sizeof(VALUE),
+ sizeof(struct rb_callinfo_kwarg),
+ rb_eRuntimeError);
+}
+
+// imemo_callinfo
+struct rb_callinfo {
+ VALUE flags;
+ const struct rb_callinfo_kwarg *kwarg;
+ VALUE mid;
+ VALUE flag;
+ VALUE argc;
+};
+
+#ifndef USE_EMBED_CI
+#define USE_EMBED_CI 1
+#endif
+
+#if SIZEOF_VALUE == 8
+#define CI_EMBED_TAG_bits 1
+#define CI_EMBED_ARGC_bits 15
+#define CI_EMBED_FLAG_bits 16
+#define CI_EMBED_ID_bits 32
+#elif SIZEOF_VALUE == 4
+#define CI_EMBED_TAG_bits 1
+#define CI_EMBED_ARGC_bits 3
+#define CI_EMBED_FLAG_bits 13
+#define CI_EMBED_ID_bits 15
+#endif
+
+#if (CI_EMBED_TAG_bits + CI_EMBED_ARGC_bits + CI_EMBED_FLAG_bits + CI_EMBED_ID_bits) != (SIZEOF_VALUE * 8)
+#error
+#endif
+
+#define CI_EMBED_FLAG 0x01
+#define CI_EMBED_ARGC_SHFT (CI_EMBED_TAG_bits)
+#define CI_EMBED_ARGC_MASK ((((VALUE)1)<<CI_EMBED_ARGC_bits) - 1)
+#define CI_EMBED_FLAG_SHFT (CI_EMBED_TAG_bits + CI_EMBED_ARGC_bits)
+#define CI_EMBED_FLAG_MASK ((((VALUE)1)<<CI_EMBED_FLAG_bits) - 1)
+#define CI_EMBED_ID_SHFT (CI_EMBED_TAG_bits + CI_EMBED_ARGC_bits + CI_EMBED_FLAG_bits)
+#define CI_EMBED_ID_MASK ((((VALUE)1)<<CI_EMBED_ID_bits) - 1)
+
+static inline bool
+vm_ci_packed_p(const struct rb_callinfo *ci)
+{
+#if USE_EMBED_CI
+ if (LIKELY(((VALUE)ci) & 0x01)) {
+ return 1;
+ }
+ else {
+ VM_ASSERT(IMEMO_TYPE_P(ci, imemo_callinfo));
+ return 0;
+ }
+#else
+ return 0;
+#endif
+}
+
+static inline bool
+vm_ci_p(const struct rb_callinfo *ci)
+{
+ if (vm_ci_packed_p(ci) || IMEMO_TYPE_P(ci, imemo_callinfo)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+static inline ID
+vm_ci_mid(const struct rb_callinfo *ci)
+{
+ if (vm_ci_packed_p(ci)) {
+ return (((VALUE)ci) >> CI_EMBED_ID_SHFT) & CI_EMBED_ID_MASK;
+ }
+ else {
+ return (ID)ci->mid;
+ }
+}
+
+static inline unsigned int
+vm_ci_flag(const struct rb_callinfo *ci)
+{
+ if (vm_ci_packed_p(ci)) {
+ return (unsigned int)((((VALUE)ci) >> CI_EMBED_FLAG_SHFT) & CI_EMBED_FLAG_MASK);
+ }
+ else {
+ return (unsigned int)ci->flag;
+ }
+}
+
+static inline unsigned int
+vm_ci_argc(const struct rb_callinfo *ci)
+{
+ if (vm_ci_packed_p(ci)) {
+ return (unsigned int)((((VALUE)ci) >> CI_EMBED_ARGC_SHFT) & CI_EMBED_ARGC_MASK);
+ }
+ else {
+ return (unsigned int)ci->argc;
+ }
+}
+
+static inline const struct rb_callinfo_kwarg *
+vm_ci_kwarg(const struct rb_callinfo *ci)
+{
+ if (vm_ci_packed_p(ci)) {
+ return NULL;
+ }
+ else {
+ return ci->kwarg;
+ }
+}
+
+static inline void
+vm_ci_dump(const struct rb_callinfo *ci)
+{
+ if (vm_ci_packed_p(ci)) {
+ fprintf(stderr, "packed_ci ID:%s flag:%x argc:%u\n",
+ rb_id2name(vm_ci_mid(ci)), vm_ci_flag(ci), vm_ci_argc(ci));
+ }
+ else {
+ rp(ci);
+ }
+}
+
+#define vm_ci_new(mid, flag, argc, kwarg) vm_ci_new_(mid, flag, argc, kwarg, __FILE__, __LINE__)
+#define vm_ci_new_runtime(mid, flag, argc, kwarg) vm_ci_new_runtime_(mid, flag, argc, kwarg, __FILE__, __LINE__)
+
+#/* This is passed to STATIC_ASSERT. Cannot be an inline function. */
+#define VM_CI_EMBEDDABLE_P(mid, flag, argc, kwarg) \
+ (((mid ) & ~CI_EMBED_ID_MASK) ? false : \
+ ((flag) & ~CI_EMBED_FLAG_MASK) ? false : \
+ ((argc) & ~CI_EMBED_ARGC_MASK) ? false : \
+ (kwarg) ? false : true)
+
+#define vm_ci_new_id(mid, flag, argc, must_zero) \
+ ((const struct rb_callinfo *) \
+ ((((VALUE)(mid )) << CI_EMBED_ID_SHFT) | \
+ (((VALUE)(flag)) << CI_EMBED_FLAG_SHFT) | \
+ (((VALUE)(argc)) << CI_EMBED_ARGC_SHFT) | \
+ RUBY_FIXNUM_FLAG))
+
+static inline const struct rb_callinfo *
+vm_ci_new_(ID mid, unsigned int flag, unsigned int argc, const struct rb_callinfo_kwarg *kwarg, const char *file, int line)
+{
+#if USE_EMBED_CI
+ if (VM_CI_EMBEDDABLE_P(mid, flag, argc, kwarg)) {
+ RB_DEBUG_COUNTER_INC(ci_packed);
+ return vm_ci_new_id(mid, flag, argc, kwarg);
+ }
+#endif
+
+ const bool debug = 0;
+ if (debug) fprintf(stderr, "%s:%d ", file, line);
+
+ // TODO: dedup
+ const struct rb_callinfo *ci = (const struct rb_callinfo *)
+ rb_imemo_new(imemo_callinfo,
+ (VALUE)mid,
+ (VALUE)flag,
+ (VALUE)argc,
+ (VALUE)kwarg);
+ if (debug) rp(ci);
+ if (kwarg) {
+ RB_DEBUG_COUNTER_INC(ci_kw);
+ }
+ else {
+ RB_DEBUG_COUNTER_INC(ci_nokw);
+ }
+
+ VM_ASSERT(vm_ci_flag(ci) == flag);
+ VM_ASSERT(vm_ci_argc(ci) == argc);
+
+ return ci;
+}
+
+
+static inline const struct rb_callinfo *
+vm_ci_new_runtime_(ID mid, unsigned int flag, unsigned int argc, const struct rb_callinfo_kwarg *kwarg, const char *file, int line)
+{
+ RB_DEBUG_COUNTER_INC(ci_runtime);
+ return vm_ci_new_(mid, flag, argc, kwarg, file, line);
+}
+
+#define VM_CALLINFO_NOT_UNDER_GC IMEMO_FL_USER0
+
+static inline bool
+vm_ci_markable(const struct rb_callinfo *ci)
+{
+ if (! ci) {
+ return false; /* or true? This is Qfalse... */
+ }
+ else if (vm_ci_packed_p(ci)) {
+ return true;
+ }
+ else {
+ VM_ASSERT(IMEMO_TYPE_P(ci, imemo_callinfo));
+ return ! FL_ANY_RAW((VALUE)ci, VM_CALLINFO_NOT_UNDER_GC);
+ }
+}
+
+#define VM_CI_ON_STACK(mid_, flags_, argc_, kwarg_) \
+ (struct rb_callinfo) { \
+ .flags = T_IMEMO | \
+ (imemo_callinfo << FL_USHIFT) | \
+ VM_CALLINFO_NOT_UNDER_GC, \
+ .mid = mid_, \
+ .flag = flags_, \
+ .argc = argc_, \
+ .kwarg = kwarg_, \
+ }
+
+typedef VALUE (*vm_call_handler)(
+ struct rb_execution_context_struct *ec,
+ struct rb_control_frame_struct *cfp,
+ struct rb_calling_info *calling);
+
+// imemo_callcache
+
+struct rb_callcache {
+ const VALUE flags;
+
+ /* inline cache: key */
+ const VALUE klass; // should not mark it because klass can not be free'd
+ // because of this marking. When klass is collected,
+ // cc will be cleared (cc->klass = 0) at vm_ccs_free().
+
+ /* inline cache: values */
+ const struct rb_callable_method_entry_struct * const cme_;
+ const vm_call_handler call_;
+
+ union {
+ const unsigned int attr_index;
+ const enum method_missing_reason method_missing_reason; /* used by method_missing */
+ VALUE v;
+ } aux_;
+};
+
+#define VM_CALLCACHE_UNMARKABLE IMEMO_FL_USER0
+
+static inline const struct rb_callcache *
+vm_cc_new(VALUE klass,
+ const struct rb_callable_method_entry_struct *cme,
+ vm_call_handler call)
+{
+ const struct rb_callcache *cc = (const struct rb_callcache *)rb_imemo_new(imemo_callcache, (VALUE)cme, (VALUE)call, 0, klass);
+ RB_DEBUG_COUNTER_INC(cc_new);
+ return cc;
+}
+
+#define VM_CC_ON_STACK(clazz, call, aux, cme) \
+ (struct rb_callcache) { \
+ .flags = T_IMEMO | \
+ (imemo_callcache << FL_USHIFT) | \
+ VM_CALLCACHE_UNMARKABLE, \
+ .klass = clazz, \
+ .cme_ = cme, \
+ .call_ = call, \
+ .aux_ = aux, \
+ }
+
+static inline bool
+vm_cc_class_check(const struct rb_callcache *cc, VALUE klass)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ VM_ASSERT(cc->klass == 0 ||
+ RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
+ return cc->klass == klass;
+}
+
+static inline const struct rb_callable_method_entry_struct *
+vm_cc_cme(const struct rb_callcache *cc)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ return cc->cme_;
+}
+
+static inline vm_call_handler
+vm_cc_call(const struct rb_callcache *cc)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ return cc->call_;
+}
+
+static inline unsigned int
+vm_cc_attr_index(const struct rb_callcache *cc)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ return cc->aux_.attr_index;
+}
+
+static inline unsigned int
+vm_cc_cmethod_missing_reason(const struct rb_callcache *cc)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ return cc->aux_.method_missing_reason;
+}
+
+static inline int
+vm_cc_markable(const struct rb_callcache *cc)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ return FL_TEST_RAW((VALUE)cc, VM_CALLCACHE_UNMARKABLE) == 0;
+}
+
+static inline bool
+vm_cc_invalidated_p(const struct rb_callcache *cc)
+{
+ if (cc->klass && METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc))) {
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+// For MJIT. cc_cme is supposed to have inlined `vm_cc_cme(cc)`.
+static inline bool
+vm_cc_valid_p(const struct rb_callcache *cc, const rb_callable_method_entry_t *cc_cme, VALUE klass)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ if (cc->klass == klass && !METHOD_ENTRY_INVALIDATED(cc_cme)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+extern const struct rb_callcache *rb_vm_empty_cc(void);
+#define vm_cc_empty() rb_vm_empty_cc()
+
+/* callcache: mutate */
+
+static inline void
+vm_cc_call_set(const struct rb_callcache *cc, vm_call_handler call)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ VM_ASSERT(cc != vm_cc_empty());
+ *(vm_call_handler *)&cc->call_ = call;
+}
+
+static inline void
+vm_cc_attr_index_set(const struct rb_callcache *cc, int index)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ VM_ASSERT(cc != vm_cc_empty());
+ *(int *)&cc->aux_.attr_index = index;
+}
+
+static inline void
+vm_cc_method_missing_reason_set(const struct rb_callcache *cc, enum method_missing_reason reason)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ VM_ASSERT(cc != vm_cc_empty());
+ *(enum method_missing_reason *)&cc->aux_.method_missing_reason = reason;
+}
+
+static inline void
+vm_cc_invalidate(const struct rb_callcache *cc)
+{
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ VM_ASSERT(cc != vm_cc_empty());
+ VM_ASSERT(cc->klass != 0); // should be enable
+
+ *(VALUE *)&cc->klass = 0;
+ RB_DEBUG_COUNTER_INC(cc_ent_invalidate);
+}
+
+/* calldata */
+
+struct rb_call_data {
+ const struct rb_callinfo *ci;
+ const struct rb_callcache *cc;
+};
+
+struct rb_class_cc_entries {
+#if VM_CHECK_MODE > 0
+ VALUE debug_sig;
+#endif
+ int capa;
+ int len;
+ const struct rb_callable_method_entry_struct *cme;
+ struct rb_class_cc_entries_entry {
+ const struct rb_callinfo *ci;
+ const struct rb_callcache *cc;
+ } *entries;
+};
+
+#if VM_CHECK_MODE > 0
+static inline bool
+vm_ccs_p(const struct rb_class_cc_entries *ccs)
+{
+ return ccs->debug_sig == ~(VALUE)ccs;
+}
+#endif
+
+// gc.c
+void rb_vm_ccs_free(struct rb_class_cc_entries *ccs);
+
+#endif /* RUBY_VM_CALLINFO_H */
diff --git a/vm_core.h b/vm_core.h
index 12c3ac3775..6ab3608edd 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_VM_CORE_H
+#define RUBY_VM_CORE_H
/**********************************************************************
vm_core.h -
@@ -9,9 +11,6 @@
**********************************************************************/
-#ifndef RUBY_VM_CORE_H
-#define RUBY_VM_CORE_H
-
/*
* Enable check mode.
* 1: enable local assertions.
@@ -46,6 +45,12 @@
#define VMDEBUG 3
#endif
+#include "ruby/internal/config.h"
+
+#include <stddef.h>
+#include <signal.h>
+#include <stdarg.h>
+
#include "ruby_assert.h"
#if VM_CHECK_MODE > 0
@@ -57,27 +62,21 @@
#define VM_UNREACHABLE(func) UNREACHABLE
#endif
-#define RUBY_VM_THREAD_MODEL 2
-
-/*
- * implementation selector of get_insn_info algorithm
- * 0: linear search
- * 1: binary search
- * 2: succinct bitvector
- */
-#ifndef VM_INSN_INFO_TABLE_IMPL
-# define VM_INSN_INFO_TABLE_IMPL 2
-#endif
-
-#include "ruby/ruby.h"
-#include "ruby/st.h"
+#include <setjmp.h>
-#include "node.h"
-#include "vm_opts.h"
+#include "ruby/internal/stdbool.h"
+#include "ccan/list/list.h"
#include "id.h"
+#include "internal.h"
+#include "internal/array.h"
+#include "internal/serial.h"
+#include "internal/vm.h"
#include "method.h"
+#include "node.h"
+#include "ruby/ruby.h"
+#include "ruby/st.h"
#include "ruby_atomic.h"
-#include "ccan/list/list.h"
+#include "vm_opts.h"
#include "ruby/thread_native.h"
#if defined(_WIN32)
@@ -86,8 +85,17 @@
#include "thread_pthread.h"
#endif
-#include <setjmp.h>
-#include <signal.h>
+#define RUBY_VM_THREAD_MODEL 2
+
+/*
+ * implementation selector of get_insn_info algorithm
+ * 0: linear search
+ * 1: binary search
+ * 2: succinct bitvector
+ */
+#ifndef VM_INSN_INFO_TABLE_IMPL
+# define VM_INSN_INFO_TABLE_IMPL 2
+#endif
#if defined(NSIG_MAX) /* POSIX issue 8 */
# undef NSIG
@@ -123,22 +131,15 @@
/* define to 0 to test old code path */
#define WAITPID_USE_SIGCHLD (RUBY_SIGCHLD || SIGCHLD_LOSSY)
-#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
-
#if defined(SIGSEGV) && defined(HAVE_SIGALTSTACK) && defined(SA_SIGINFO) && !defined(__NetBSD__)
# define USE_SIGALTSTACK
-void *rb_register_sigaltstack(void);
-# define RB_ALTSTACK_INIT(var) var = rb_register_sigaltstack()
-# define RB_ALTSTACK_FREE(var) xfree(var)
+void *rb_allocate_sigaltstack(void);
+void *rb_register_sigaltstack(void *);
+# define RB_ALTSTACK_INIT(var, altstack) var = rb_register_sigaltstack(altstack)
+# define RB_ALTSTACK_FREE(var) free(var)
# define RB_ALTSTACK(var) var
#else /* noop */
-# define RB_ALTSTACK_INIT(var)
+# define RB_ALTSTACK_INIT(var, altstack)
# define RB_ALTSTACK_FREE(var)
# define RB_ALTSTACK(var) (0)
#endif
@@ -217,15 +218,22 @@ struct rb_control_frame_struct;
/* iseq data type */
typedef struct rb_compile_option_struct rb_compile_option_t;
-struct iseq_inline_cache_entry {
- rb_serial_t ic_serial;
- const rb_cref_t *ic_cref;
- VALUE value;
+// imemo_constcache
+struct iseq_inline_constant_cache_entry {
+ VALUE flags;
+
+ VALUE value; // v0
+ const rb_cref_t *ic_cref; // v1
+ rb_serial_t ic_serial; // v2
+ // v3
+};
+
+struct iseq_inline_constant_cache {
+ struct iseq_inline_constant_cache_entry *entry;
};
struct iseq_inline_iv_cache_entry {
- rb_serial_t ic_serial;
- size_t index;
+ struct rb_iv_index_tbl_entry *entry;
};
union iseq_inline_storage_entry {
@@ -233,34 +241,20 @@ union iseq_inline_storage_entry {
struct rb_thread_struct *running_thread;
VALUE value;
} once;
- struct iseq_inline_cache_entry cache;
+ struct iseq_inline_constant_cache ic_cache;
struct iseq_inline_iv_cache_entry iv_cache;
};
-struct rb_call_info_kw_arg {
- int keyword_len;
- VALUE keywords[1];
-};
-
-struct rb_call_info_with_kwarg {
- struct rb_call_info ci;
- struct rb_call_info_kw_arg *kw_arg;
-};
-
struct rb_calling_info {
+ const struct rb_callinfo *ci;
+ const struct rb_callcache *cc;
VALUE block_handler;
VALUE recv;
int argc;
int kw_splat;
};
-struct rb_kwarg_call_data {
- struct rb_call_cache cc;
- struct rb_call_info_with_kwarg ci_kw;
-};
-
struct rb_execution_context_struct;
-typedef VALUE (*vm_call_handler)(struct rb_execution_context_struct *ec, struct rb_control_frame_struct *cfp, struct rb_calling_info *calling, struct rb_call_data *cd);
#if 1
#define CoreDataFromValue(obj, type) (type*)DATA_PTR(obj)
@@ -418,12 +412,7 @@ struct rb_iseq_constant_body {
struct rb_iseq_struct *local_iseq; /* local_iseq->flip_cnt can be modified */
union iseq_inline_storage_entry *is_entries;
- struct rb_call_data *call_data; /* A buffer for two arrays:
- * struct rb_call_data calls[ci_size];
- * struct rb_kwarg_call_data kw_calls[ci_kw_size];
- * Such that:
- * struct rb_kwarg_call_data *kw_calls = &body->call_data[ci_size];
- */
+ struct rb_call_data *call_data; //struct rb_call_data calls[ci_size];
struct {
rb_snum_t flip_count;
@@ -435,10 +424,11 @@ struct rb_iseq_constant_body {
unsigned int local_table_size;
unsigned int is_size;
unsigned int ci_size;
- unsigned int ci_kw_size;
unsigned int stack_max; /* for stack overflow check */
char catch_except_p; /* If a frame of this ISeq may catch exception, set TRUE */
+ bool builtin_inline_p; // This ISeq's builtin func is safe to be inlined by MJIT
+ struct rb_id_table *outer_variables;
#if USE_MJIT
/* The following fields are MJIT related info. */
@@ -447,8 +437,6 @@ struct rb_iseq_constant_body {
long unsigned total_calls; /* number of total calls with `mjit_exec()` */
struct rb_mjit_unit *jit_unit;
#endif
-
- uintptr_t iseq_unique_id; /* -- Remove In 3.0 -- */
};
/* T_IMEMO/iseq */
@@ -576,12 +564,30 @@ typedef const struct rb_builtin_function *RB_BUILTIN;
typedef struct rb_vm_struct {
VALUE self;
- rb_global_vm_lock_t gvl;
+ struct {
+ struct list_head set;
+ unsigned int cnt;
+ unsigned int blocking_cnt;
- struct rb_thread_struct *main_thread;
+ struct rb_ractor_struct *main_ractor;
+ struct rb_thread_struct *main_thread; // == vm->ractor.main_ractor->threads.main
- /* persists across uncontended GVL release/acquire for time slice */
- const struct rb_thread_struct *running_thread;
+ struct {
+ // monitor
+ rb_nativethread_lock_t lock;
+ struct rb_ractor_struct *lock_owner;
+ unsigned int lock_rec;
+
+ // barrier
+ bool barrier_waiting;
+ unsigned int barrier_cnt;
+ rb_nativethread_cond_t barrier_cond;
+
+ // join at exit
+ rb_nativethread_cond_t terminate_cond;
+ bool terminate_waiting;
+ } sync;
+ } ractor;
#ifdef USE_SIGALTSTACK
void *main_altstack;
@@ -592,9 +598,6 @@ typedef struct rb_vm_struct {
struct list_head waiting_pids; /* PID > 0: <=> struct waitpid_state */
struct list_head waiting_grps; /* PID <= 0: <=> struct waitpid_state */
struct list_head waiting_fds; /* <=> struct waiting_fd */
- struct list_head living_threads;
- VALUE thgroup_default;
- int living_thread_num;
/* set in single-threaded processes only: */
volatile int ubf_async_safe;
@@ -602,9 +605,7 @@ typedef struct rb_vm_struct {
unsigned int running: 1;
unsigned int thread_abort_on_exception: 1;
unsigned int thread_report_on_exception: 1;
-
- unsigned int safe_level_: 1;
- int sleeper;
+ unsigned int thread_ignore_deadlock: 1;
/* object management */
VALUE mark_object_ary;
@@ -626,15 +627,12 @@ typedef struct rb_vm_struct {
VALUE cmd[RUBY_NSIG];
} trap_list;
- /* hook */
- rb_hook_list_t global_hooks;
-
/* relation table of ensure - rollback for callcc */
struct st_table *ensure_rollback_table;
/* postponed_job (async-signal-safe, NOT thread-safe) */
struct rb_postponed_job_struct *postponed_job_buffer;
- int postponed_job_index;
+ rb_atomic_t postponed_job_index;
int src_encoding_index;
@@ -642,7 +640,7 @@ typedef struct rb_vm_struct {
struct list_head workqueue; /* <=> rb_workqueue_job.jnode */
rb_nativethread_lock_t workqueue_lock;
- VALUE verbose, debug, orig_progname, progname;
+ VALUE orig_progname, progname;
VALUE coverages;
int coverage_mode;
@@ -658,6 +656,17 @@ typedef struct rb_vm_struct {
const struct rb_builtin_function *builtin_function_table;
int builtin_inline_index;
+ struct rb_id_table *negative_cme_table;
+
+#ifndef VM_GLOBAL_CC_CACHE_TABLE_SIZE
+#define VM_GLOBAL_CC_CACHE_TABLE_SIZE 1023
+#endif
+ const struct rb_callcache *global_cc_cache_table[VM_GLOBAL_CC_CACHE_TABLE_SIZE]; // vm_eval.c
+
+#if USE_VM_CLOCK
+ uint32_t clock;
+#endif
+
/* params */
struct { /* size in byte */
size_t thread_vm_stack_size;
@@ -802,6 +811,7 @@ struct rb_vm_tag {
rb_jmpbuf_t buf;
struct rb_vm_tag *prev;
enum ruby_tag_type state;
+ unsigned int lock_rec;
};
STATIC_ASSERT(rb_vm_tag_buf_offset, offsetof(struct rb_vm_tag, buf) > 0);
@@ -820,11 +830,6 @@ struct rb_unblock_callback {
struct rb_mutex_struct;
-typedef struct rb_thread_list_struct{
- struct rb_thread_list_struct *next;
- struct rb_thread_struct *th;
-} rb_thread_list_t;
-
typedef struct rb_ensure_entry {
VALUE marker;
VALUE (*e_proc)(VALUE);
@@ -840,7 +845,13 @@ typedef char rb_thread_id_string_t[sizeof(rb_nativethread_id_t) * 2 + 3];
typedef struct rb_fiber_struct rb_fiber_t;
-typedef struct rb_execution_context_struct {
+struct rb_waiting_list {
+ struct rb_waiting_list *next;
+ struct rb_thread_struct *thread;
+ struct rb_fiber_struct *fiber;
+};
+
+struct rb_execution_context_struct {
/* execution information */
VALUE *vm_stack; /* must free, must mark */
size_t vm_stack_size; /* size in word (byte size / sizeof(VALUE)) */
@@ -852,12 +863,15 @@ typedef struct rb_execution_context_struct {
/* interrupt flags */
rb_atomic_t interrupt_flag;
rb_atomic_t interrupt_mask; /* size should match flag */
+#if USE_VM_CLOCK
+ uint32_t checked_clock;
+#endif
rb_fiber_t *fiber_ptr;
struct rb_thread_struct *thread_ptr;
/* storage (ec (fiber) local) */
- st_table *local_storage;
+ struct rb_id_table *local_storage;
VALUE local_storage_recursive_hash;
VALUE local_storage_recursive_hash_for_trace;
@@ -889,7 +903,12 @@ typedef struct rb_execution_context_struct {
size_t stack_maxsize;
RUBY_ALIGNAS(SIZEOF_VALUE) jmp_buf regs;
} machine;
-} rb_execution_context_t;
+};
+
+#ifndef rb_execution_context_t
+typedef struct rb_execution_context_struct rb_execution_context_t;
+#define rb_execution_context_t rb_execution_context_t
+#endif
// for builtin.h
#define VM_CORE_H_EC_DEFINED 1
@@ -907,9 +926,16 @@ void rb_ec_initialize_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t
// @param ec the execution context to update.
void rb_ec_clear_vm_stack(rb_execution_context_t *ec);
+struct rb_ext_config {
+ bool ractor_safe;
+};
+
+typedef struct rb_ractor_struct rb_ractor_t;
+
typedef struct rb_thread_struct {
- struct list_node vmlt_node;
+ struct list_node lt_node; // managed by a ractor
VALUE self;
+ rb_ractor_t *ractor;
rb_vm_t *vm;
rb_execution_context_t *ec;
@@ -958,7 +984,7 @@ typedef struct rb_thread_struct {
VALUE locking_mutex;
struct rb_mutex_struct *keeping_mutexes;
- rb_thread_list_t *join_list;
+ struct rb_waiting_list *join_list;
union {
struct {
@@ -972,9 +998,10 @@ typedef struct rb_thread_struct {
} func;
} invoke_arg;
- enum {
+ enum thread_invoke_type {
thread_invoke_type_none = 0,
thread_invoke_type_proc,
+ thread_invoke_type_ractor_proc,
thread_invoke_type_func
} invoke_type;
@@ -985,9 +1012,17 @@ typedef struct rb_thread_struct {
rb_fiber_t *root_fiber;
rb_jmpbuf_t root_jmpbuf;
+ VALUE scheduler;
+ unsigned blocking;
+
/* misc */
VALUE name;
+ struct rb_ext_config ext_config;
+
+#ifdef USE_SIGALTSTACK
+ void *altstack;
+#endif
} rb_thread_t;
typedef enum {
@@ -1009,11 +1044,13 @@ typedef enum {
RUBY_SYMBOL_EXPORT_BEGIN
/* node -> iseq */
-rb_iseq_t *rb_iseq_new (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type);
-rb_iseq_t *rb_iseq_new_top (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent);
-rb_iseq_t *rb_iseq_new_main (const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent);
-rb_iseq_t *rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno,
- const rb_iseq_t *parent, enum iseq_type, const rb_compile_option_t*);
+rb_iseq_t *rb_iseq_new (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type);
+rb_iseq_t *rb_iseq_new_top (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent);
+rb_iseq_t *rb_iseq_new_main (const rb_ast_body_t *ast, VALUE path, VALUE realpath, const rb_iseq_t *parent);
+rb_iseq_t *rb_iseq_new_eval (const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth);
+rb_iseq_t *rb_iseq_new_with_opt(const rb_ast_body_t *ast, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, int isolated_depth,
+ enum iseq_type, const rb_compile_option_t*);
+
struct iseq_link_anchor;
struct rb_iseq_new_with_callback_callback_func {
VALUE flags;
@@ -1050,8 +1087,15 @@ typedef struct {
const struct rb_block block;
unsigned int is_from_method: 1; /* bool */
unsigned int is_lambda: 1; /* bool */
+ unsigned int is_isolated: 1; /* bool */
} rb_proc_t;
+RUBY_SYMBOL_EXPORT_BEGIN
+VALUE rb_proc_isolate(VALUE self);
+VALUE rb_proc_isolate_bang(VALUE self);
+VALUE rb_proc_ractor_make_shareable(VALUE self);
+RUBY_SYMBOL_EXPORT_END
+
typedef struct {
VALUE flags; /* imemo header */
rb_iseq_t *iseq;
@@ -1082,35 +1126,6 @@ enum vm_check_match_type {
#define VM_CHECKMATCH_TYPE_MASK 0x03
#define VM_CHECKMATCH_ARRAY 0x04
-enum vm_call_flag_bits {
- VM_CALL_ARGS_SPLAT_bit, /* m(*args) */
- VM_CALL_ARGS_BLOCKARG_bit, /* m(&block) */
- VM_CALL_FCALL_bit, /* m(...) */
- VM_CALL_VCALL_bit, /* m */
- VM_CALL_ARGS_SIMPLE_bit, /* (ci->flag & (SPLAT|BLOCKARG)) && blockiseq == NULL && ci->kw_arg == NULL */
- VM_CALL_BLOCKISEQ_bit, /* has blockiseq */
- VM_CALL_KWARG_bit, /* has kwarg */
- VM_CALL_KW_SPLAT_bit, /* m(**opts) */
- VM_CALL_TAILCALL_bit, /* located at tail position */
- VM_CALL_SUPER_bit, /* super */
- VM_CALL_ZSUPER_bit, /* zsuper */
- VM_CALL_OPT_SEND_bit, /* internal flag */
- VM_CALL__END
-};
-
-#define VM_CALL_ARGS_SPLAT (0x01 << VM_CALL_ARGS_SPLAT_bit)
-#define VM_CALL_ARGS_BLOCKARG (0x01 << VM_CALL_ARGS_BLOCKARG_bit)
-#define VM_CALL_FCALL (0x01 << VM_CALL_FCALL_bit)
-#define VM_CALL_VCALL (0x01 << VM_CALL_VCALL_bit)
-#define VM_CALL_ARGS_SIMPLE (0x01 << VM_CALL_ARGS_SIMPLE_bit)
-#define VM_CALL_BLOCKISEQ (0x01 << VM_CALL_BLOCKISEQ_bit)
-#define VM_CALL_KWARG (0x01 << VM_CALL_KWARG_bit)
-#define VM_CALL_KW_SPLAT (0x01 << VM_CALL_KW_SPLAT_bit)
-#define VM_CALL_TAILCALL (0x01 << VM_CALL_TAILCALL_bit)
-#define VM_CALL_SUPER (0x01 << VM_CALL_SUPER_bit)
-#define VM_CALL_ZSUPER (0x01 << VM_CALL_ZSUPER_bit)
-#define VM_CALL_OPT_SEND (0x01 << VM_CALL_OPT_SEND_bit)
-
enum vm_special_object_type {
VM_SPECIAL_OBJECT_VMCORE = 1,
VM_SPECIAL_OBJECT_CBASE,
@@ -1126,11 +1141,11 @@ enum vm_svar_index {
};
/* inline cache */
-typedef struct iseq_inline_cache_entry *IC;
+typedef struct iseq_inline_constant_cache *IC;
typedef struct iseq_inline_iv_cache_entry *IVC;
typedef union iseq_inline_storage_entry *ISE;
-typedef struct rb_call_info *CALL_INFO;
-typedef struct rb_call_cache *CALL_CACHE;
+typedef const struct rb_callinfo *CALL_INFO;
+typedef const struct rb_callcache *CALL_CACHE;
typedef struct rb_call_data *CALL_DATA;
typedef VALUE CDHASH;
@@ -1151,11 +1166,11 @@ typedef rb_control_frame_t *
enum {
/* Frame/Environment flag bits:
- * MMMM MMMM MMMM MMMM ____ FFFF FFFF EEEX (LSB)
+ * MMMM MMMM MMMM MMMM ____ _FFF FFFF EEEX (LSB)
*
* X : tag for GC marking (It seems as Fixnum)
* EEE : 3 bits Env flags
- * FF..: 8 bits Frame flags
+ * FF..: 7 bits Frame flags
* MM..: 15 bits frame magic (to check frame corruption)
*/
@@ -1173,19 +1188,19 @@ enum {
VM_FRAME_MAGIC_MASK = 0x7fff0001,
/* frame flag */
- VM_FRAME_FLAG_PASSED = 0x0010,
VM_FRAME_FLAG_FINISH = 0x0020,
VM_FRAME_FLAG_BMETHOD = 0x0040,
VM_FRAME_FLAG_CFRAME = 0x0080,
VM_FRAME_FLAG_LAMBDA = 0x0100,
VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM = 0x0200,
VM_FRAME_FLAG_CFRAME_KW = 0x0400,
- VM_FRAME_FLAG_CFRAME_EMPTY_KW = 0x0800, /* -- Remove In 3.0 -- */
+ VM_FRAME_FLAG_PASSED = 0x0800,
/* env flag */
VM_ENV_FLAG_LOCAL = 0x0002,
VM_ENV_FLAG_ESCAPED = 0x0004,
- VM_ENV_FLAG_WB_REQUIRED = 0x0008
+ VM_ENV_FLAG_WB_REQUIRED = 0x0008,
+ VM_ENV_FLAG_ISOLATED = 0x0010,
};
#define VM_ENV_DATA_SIZE ( 3)
@@ -1241,13 +1256,6 @@ VM_FRAME_CFRAME_KW_P(const rb_control_frame_t *cfp)
return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME_KW) != 0;
}
-/* -- Remove In 3.0 -- */
-static inline int
-VM_FRAME_CFRAME_EMPTY_KW_P(const rb_control_frame_t *cfp)
-{
- return VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_CFRAME_EMPTY_KW) != 0;
-}
-
static inline int
VM_FRAME_FINISHED_P(const rb_control_frame_t *cfp)
{
@@ -1639,7 +1647,7 @@ extern void rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const
#define SDR() rb_vmdebug_stack_dump_raw(GET_EC(), GET_EC()->cfp)
#define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_EC(), (cfp))
void rb_vm_bugreport(const void *);
-typedef RETSIGTYPE (*ruby_sighandler_t)(int);
+typedef void (*ruby_sighandler_t)(int);
NORETURN(void rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *, const char *fmt, ...));
/* functions about thread/vm execution */
@@ -1676,11 +1684,12 @@ VALUE rb_vm_env_local_variables(const rb_env_t *env);
const rb_env_t *rb_vm_env_prev_env(const rb_env_t *env);
const VALUE *rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const ID *dynvars);
void rb_vm_inc_const_missing_count(void);
-void rb_vm_gvl_destroy(rb_vm_t *vm);
VALUE rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc,
const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat);
MJIT_STATIC void rb_vm_pop_frame(rb_execution_context_t *ec);
+void rb_gvl_destroy(rb_global_vm_lock_t *gvl);
+
void rb_thread_start_timer_thread(void);
void rb_thread_stop_timer_thread(void);
void rb_thread_reset_timer_thread(void);
@@ -1693,22 +1702,7 @@ rb_vm_living_threads_init(rb_vm_t *vm)
list_head_init(&vm->waiting_pids);
list_head_init(&vm->workqueue);
list_head_init(&vm->waiting_grps);
- list_head_init(&vm->living_threads);
- vm->living_thread_num = 0;
-}
-
-static inline void
-rb_vm_living_threads_insert(rb_vm_t *vm, rb_thread_t *th)
-{
- list_add_tail(&vm->living_threads, &th->vmlt_node);
- vm->living_thread_num++;
-}
-
-static inline void
-rb_vm_living_threads_remove(rb_vm_t *vm, rb_thread_t *th)
-{
- list_del(&th->vmlt_node);
- vm->living_thread_num--;
+ list_head_init(&vm->ractor.set);
}
typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE);
@@ -1734,27 +1728,29 @@ MJIT_STATIC const rb_callable_method_entry_t *rb_vm_frame_method_entry(const rb_
#define sysstack_error GET_VM()->special_exceptions[ruby_error_sysstack]
-#define RUBY_CONST_ASSERT(expr) (1/!!(expr)) /* expr must be a compile-time constant */
-#define VM_STACK_OVERFLOWED_P(cfp, sp, margin) \
- (!RUBY_CONST_ASSERT(sizeof(*(sp)) == sizeof(VALUE)) || \
- !RUBY_CONST_ASSERT(sizeof(*(cfp)) == sizeof(rb_control_frame_t)) || \
- ((rb_control_frame_t *)((sp) + (margin)) + 1) >= (cfp))
-#define WHEN_VM_STACK_OVERFLOWED(cfp, sp, margin) \
- if (LIKELY(!VM_STACK_OVERFLOWED_P(cfp, sp, margin))) {(void)0;} else /* overflowed */
-#define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) \
- WHEN_VM_STACK_OVERFLOWED(cfp, sp, margin) vm_stackoverflow()
+#define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin) do { \
+ STATIC_ASSERT(sizeof_sp, sizeof(*(sp)) == sizeof(VALUE)); \
+ STATIC_ASSERT(sizeof_cfp, sizeof(*(cfp)) == sizeof(rb_control_frame_t)); \
+ const struct rb_control_frame_struct *bound = (void *)&(sp)[(margin)]; \
+ if (UNLIKELY((cfp) <= &bound[1])) { \
+ vm_stackoverflow(); \
+ } \
+} while (0)
+
#define CHECK_VM_STACK_OVERFLOW(cfp, margin) \
- WHEN_VM_STACK_OVERFLOWED(cfp, (cfp)->sp, margin) vm_stackoverflow()
+ CHECK_VM_STACK_OVERFLOW0((cfp), (cfp)->sp, (margin))
VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_tag_type *stateptr);
+rb_execution_context_t *rb_vm_main_ractor_ec(rb_vm_t *vm); // ractor.c
+
/* for thread */
#if RUBY_VM_THREAD_MODEL == 2
RUBY_SYMBOL_EXPORT_BEGIN
+RUBY_EXTERN struct rb_ractor_struct *ruby_single_main_ractor; // ractor.c
RUBY_EXTERN rb_vm_t *ruby_current_vm_ptr;
-RUBY_EXTERN rb_execution_context_t *ruby_current_execution_context_ptr;
RUBY_EXTERN rb_event_flag_t ruby_vm_event_flags;
RUBY_EXTERN rb_event_flag_t ruby_vm_event_enabled_global_flags;
RUBY_EXTERN unsigned int ruby_vm_event_local_num;
@@ -1762,8 +1758,9 @@ RUBY_EXTERN unsigned int ruby_vm_event_local_num;
RUBY_SYMBOL_EXPORT_END
#define GET_VM() rb_current_vm()
+#define GET_RACTOR() rb_current_ractor()
#define GET_THREAD() rb_current_thread()
-#define GET_EC() rb_current_execution_context()
+#define GET_EC() rb_current_execution_context(true)
static inline rb_thread_t *
rb_ec_thread_ptr(const rb_execution_context_t *ec)
@@ -1771,6 +1768,19 @@ rb_ec_thread_ptr(const rb_execution_context_t *ec)
return ec->thread_ptr;
}
+static inline rb_ractor_t *
+rb_ec_ractor_ptr(const rb_execution_context_t *ec)
+{
+ const rb_thread_t *th = rb_ec_thread_ptr(ec);
+ if (th) {
+ VM_ASSERT(th->ractor != NULL);
+ return th->ractor;
+ }
+ else {
+ return NULL;
+ }
+}
+
static inline rb_vm_t *
rb_ec_vm_ptr(const rb_execution_context_t *ec)
{
@@ -1784,9 +1794,19 @@ rb_ec_vm_ptr(const rb_execution_context_t *ec)
}
static inline rb_execution_context_t *
-rb_current_execution_context(void)
-{
- return ruby_current_execution_context_ptr;
+rb_current_execution_context(bool expect_ec)
+{
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+ #if __APPLE__
+ rb_execution_context_t *ec = rb_current_ec();
+ #else
+ rb_execution_context_t *ec = ruby_current_ec;
+ #endif
+#else
+ rb_execution_context_t *ec = native_tls_get(ruby_current_ec_key);
+#endif
+ VM_ASSERT(!expect_ec || ec != NULL);
+ return ec;
}
static inline rb_thread_t *
@@ -1796,30 +1816,47 @@ rb_current_thread(void)
return rb_ec_thread_ptr(ec);
}
+static inline rb_ractor_t *
+rb_current_ractor(void)
+{
+ if (ruby_single_main_ractor) {
+ return ruby_single_main_ractor;
+ }
+ else {
+ const rb_execution_context_t *ec = GET_EC();
+ return rb_ec_ractor_ptr(ec);
+ }
+}
+
static inline rb_vm_t *
rb_current_vm(void)
{
+#if 0 // TODO: reconsider the assertions
VM_ASSERT(ruby_current_vm_ptr == NULL ||
ruby_current_execution_context_ptr == NULL ||
rb_ec_thread_ptr(GET_EC()) == NULL ||
+ rb_ec_thread_ptr(GET_EC())->status == THREAD_KILLED ||
rb_ec_vm_ptr(GET_EC()) == ruby_current_vm_ptr);
+#endif
+
return ruby_current_vm_ptr;
}
-static inline void
-rb_thread_set_current_raw(const rb_thread_t *th)
-{
- ruby_current_execution_context_ptr = th->ec;
-}
+void rb_ec_vm_lock_rec_release(const rb_execution_context_t *ec,
+ unsigned int recorded_lock_rec,
+ unsigned int current_lock_rec);
-static inline void
-rb_thread_set_current(rb_thread_t *th)
+static inline unsigned int
+rb_ec_vm_lock_rec(const rb_execution_context_t *ec)
{
- if (th->vm->running_thread != th) {
- th->running_time_us = 0;
+ rb_vm_t *vm = rb_ec_vm_ptr(ec);
+
+ if (vm->ractor.sync.lock_owner != rb_ec_ractor_ptr(ec)) {
+ return 0;
+ }
+ else {
+ return vm->ractor.sync.lock_rec;
}
- rb_thread_set_current_raw(th);
- th->vm->running_thread = th;
}
#else
@@ -1830,16 +1867,33 @@ enum {
TIMER_INTERRUPT_MASK = 0x01,
PENDING_INTERRUPT_MASK = 0x02,
POSTPONED_JOB_INTERRUPT_MASK = 0x04,
- TRAP_INTERRUPT_MASK = 0x08
+ TRAP_INTERRUPT_MASK = 0x08,
+ TERMINATE_INTERRUPT_MASK = 0x10,
+ VM_BARRIER_INTERRUPT_MASK = 0x20,
};
#define RUBY_VM_SET_TIMER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TIMER_INTERRUPT_MASK)
#define RUBY_VM_SET_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, PENDING_INTERRUPT_MASK)
#define RUBY_VM_SET_POSTPONED_JOB_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, POSTPONED_JOB_INTERRUPT_MASK)
#define RUBY_VM_SET_TRAP_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TRAP_INTERRUPT_MASK)
+#define RUBY_VM_SET_TERMINATE_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, TERMINATE_INTERRUPT_MASK)
+#define RUBY_VM_SET_VM_BARRIER_INTERRUPT(ec) ATOMIC_OR((ec)->interrupt_flag, VM_BARRIER_INTERRUPT_MASK)
#define RUBY_VM_INTERRUPTED(ec) ((ec)->interrupt_flag & ~(ec)->interrupt_mask & \
(PENDING_INTERRUPT_MASK|TRAP_INTERRUPT_MASK))
-#define RUBY_VM_INTERRUPTED_ANY(ec) ((ec)->interrupt_flag & ~(ec)->interrupt_mask)
+
+static inline bool
+RUBY_VM_INTERRUPTED_ANY(rb_execution_context_t *ec)
+{
+#if USE_VM_CLOCK
+ uint32_t current_clock = rb_ec_vm_ptr(ec)->clock;
+
+ if (current_clock != ec->checked_clock) {
+ ec->checked_clock = current_clock;
+ RUBY_VM_SET_TIMER_INTERRUPT(ec);
+ }
+#endif
+ return ec->interrupt_flag & ~(ec)->interrupt_mask;
+}
VALUE rb_exc_set_backtrace(VALUE exc, VALUE bt);
int rb_signal_buff_size(void);
@@ -1858,6 +1912,11 @@ void rb_execution_context_update(const rb_execution_context_t *ec);
void rb_execution_context_mark(const rb_execution_context_t *ec);
void rb_fiber_close(rb_fiber_t *fib);
void Init_native_thread(rb_thread_t *th);
+int rb_vm_check_ints_blocking(rb_execution_context_t *ec);
+
+// vm_sync.h
+void rb_vm_cond_wait(rb_vm_t *vm, rb_nativethread_cond_t *cond);
+void rb_vm_cond_timedwait(rb_vm_t *vm, rb_nativethread_cond_t *cond, unsigned long msec);
#define RUBY_VM_CHECK_INTS(ec) rb_vm_check_ints(ec)
static inline void
@@ -1926,17 +1985,24 @@ rb_exec_event_hook_orig(rb_execution_context_t *ec, rb_hook_list_t *hooks, rb_ev
rb_exec_event_hooks(&trace_arg, hooks, pop_p);
}
+struct rb_ractor_pub {
+ VALUE self;
+ uint32_t id;
+ rb_hook_list_t hooks;
+};
+
static inline rb_hook_list_t *
-rb_vm_global_hooks(const rb_execution_context_t *ec)
+rb_ec_ractor_hooks(const rb_execution_context_t *ec)
{
- return &rb_ec_vm_ptr(ec)->global_hooks;
+ struct rb_ractor_pub *cr_pub = (struct rb_ractor_pub *)rb_ec_ractor_ptr(ec);
+ return &cr_pub->hooks;
}
#define EXEC_EVENT_HOOK(ec_, flag_, self_, id_, called_id_, klass_, data_) \
- EXEC_EVENT_HOOK_ORIG(ec_, rb_vm_global_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 0)
+ EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_ractor_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 0)
#define EXEC_EVENT_HOOK_AND_POP_FRAME(ec_, flag_, self_, id_, called_id_, klass_, data_) \
- EXEC_EVENT_HOOK_ORIG(ec_, rb_vm_global_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 1)
+ EXEC_EVENT_HOOK_ORIG(ec_, rb_ec_ractor_hooks(ec_), flag_, self_, id_, called_id_, klass_, data_, 1)
static inline void
rb_exec_event_hook_script_compiled(rb_execution_context_t *ec, const rb_iseq_t *iseq, VALUE eval_script)
@@ -1963,6 +2029,10 @@ extern void rb_reset_coverages(void);
void rb_postponed_job_flush(rb_vm_t *vm);
+// ractor.c
+RUBY_EXTERN VALUE rb_eRactorUnsafeError;
+RUBY_EXTERN VALUE rb_eRactorIsolationError;
+
RUBY_SYMBOL_EXPORT_END
#endif /* RUBY_VM_CORE_H */
diff --git a/vm_debug.h b/vm_debug.h
index 8e0350d147..a3631c0309 100644
--- a/vm_debug.h
+++ b/vm_debug.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_DEBUG_H
+#define RUBY_DEBUG_H
/**********************************************************************
vm_debug.h - YARV Debug function interface
@@ -9,9 +11,6 @@
**********************************************************************/
-#ifndef RUBY_DEBUG_H
-#define RUBY_DEBUG_H
-
#include "ruby/ruby.h"
#include "node.h"
@@ -31,4 +30,87 @@ void ruby_set_debug_option(const char *str);
RUBY_SYMBOL_EXPORT_END
+#if RUBY_DEVEL
+#ifndef USE_RUBY_DEBUG_LOG
+#define USE_RUBY_DEBUG_LOG 0
+#endif
+#else
+// disable on !RUBY_DEVEL
+#ifdef USE_RUBY_DEBUG_LOG
+#undef USE_RUBY_DEBUG_LOG
+#endif
+#endif
+
+/* RUBY_DEBUG_LOG: Logging debug information mechanism
+ *
+ * This feature provides a mechanism to store logging information
+ * to a file, stderr or memory space with simple macros.
+ *
+ * The following information will be stored.
+ * * (1) __FILE__, __LINE__ in C
+ * * (2) __FILE__, __LINE__ in Ruby
+ * * (3) __func__ in C (message title)
+ * * (4) given string with sprintf format
+ * * (5) Thread number (if multiple threads are running)
+ *
+ * This feature is enabled only USE_RUBY_DEBUG_LOG is enabled.
+ * Release version should not enable it.
+ *
+ * Running with the `RUBY_DEBUG_LOG` environment variable enables
+ * this feature.
+ *
+ * # logging into a file
+ * RUBY_DEBUG_LOG=/path/to/file STDERR
+ *
+ * # logging into STDERR
+ * RUBY_DEBUG_LOG=stderr
+ *
+ * # logging into memory space (check with a debugger)
+ * # It will help if the timing is important.
+ * RUBY_DEBUG_LOG=mem
+ *
+ * RUBY_DEBUG_LOG_FILTER environment variable can specify the filter string.
+ * If "(3) __func__ in C (message title)" contains the specified string, the
+ * information will be stored (example: RUBY_DEBUG_LOG_FILTER=str will enable
+ * only on str related information).
+ *
+ * In a MRI source code, you can use the following macros:
+ * * RUBY_DEBUG_LOG(fmt, ...): Above (1) to (4) will be logged.
+ * * RUBY_DEBUG_LOG2(file, line, fmt, ...):
+ * Same as RUBY_DEBUG_LOG(), but (1) will be replaced with given file, line.
+ */
+
+extern enum ruby_debug_log_mode {
+ ruby_debug_log_disabled = 0x00,
+ ruby_debug_log_memory = 0x01,
+ ruby_debug_log_stderr = 0x02,
+ ruby_debug_log_file = 0x04,
+} ruby_debug_log_mode;
+
+void ruby_debug_log(const char *file, int line, const char *func_name, const char *fmt, ...);
+void ruby_debug_log_print(unsigned int n);
+bool ruby_debug_log_filter(const char *func_name);
+
+// convenient macro to log even if the USE_RUBY_DEBUG_LOG macro is not specified.
+// You can use this macro for temporary usage (you should not commit it).
+#define _RUBY_DEBUG_LOG(fmt, ...) ruby_debug_log(__FILE__, __LINE__, __func__, fmt, __VA_ARGS__)
+
+#if USE_RUBY_DEBUG_LOG
+
+#define RUBY_DEBUG_LOG(fmt, ...) do { \
+ if (ruby_debug_log_mode && ruby_debug_log_filter(__func__)) \
+ ruby_debug_log(__FILE__, __LINE__, __func__, fmt, __VA_ARGS__); \
+} while (0)
+
+#define RUBY_DEBUG_LOG2(file, line, fmt, ...) do { \
+ if (ruby_debug_log_mode && ruby_debug_log_filter(__func__)) \
+ ruby_debug_log(file, line, __func__, fmt, __VA_ARGS__); \
+} while (0)
+
+#else
+// do nothing
+#define RUBY_DEBUG_LOG(fmt, ...)
+#define RUBY_DEBUG_LOG2(file, line, fmt, ...)
+#endif // USE_RUBY_DEBUG_LOG
+
#endif /* RUBY_DEBUG_H */
diff --git a/vm_dump.c b/vm_dump.c
index c778e1b4dd..47fc9f93a6 100644
--- a/vm_dump.c
+++ b/vm_dump.c
@@ -8,31 +8,34 @@
**********************************************************************/
-
-#include "internal.h"
-#include "addr2line.h"
-#include "vm_core.h"
-#include "iseq.h"
-#include "gc.h"
+#include "ruby/internal/config.h"
#ifdef HAVE_UCONTEXT_H
-#include <ucontext.h>
+# include <ucontext.h>
#endif
+
#ifdef __APPLE__
-#ifdef HAVE_LIBPROC_H
-#include <libproc.h>
-#endif
-#include <mach/vm_map.h>
-#include <mach/mach_init.h>
-#ifdef __LP64__
-#define vm_region_recurse vm_region_recurse_64
-#endif
+# ifdef HAVE_LIBPROC_H
+# include <libproc.h>
+# endif
+# include <mach/vm_map.h>
+# include <mach/mach_init.h>
+# ifdef __LP64__
+# define vm_region_recurse vm_region_recurse_64
+# endif
+/* that is defined in sys/queue.h, and conflicts with
+ * ccan/list/list.h */
+# undef LIST_HEAD
#endif
-/* see vm_insnhelper.h for the values */
-#ifndef VMDEBUG
-#define VMDEBUG 0
-#endif
+#include "addr2line.h"
+#include "gc.h"
+#include "internal.h"
+#include "internal/variable.h"
+#include "internal/vm.h"
+#include "iseq.h"
+#include "vm_core.h"
+#include "ractor_core.h"
#define MAX_POSBUF 128
@@ -103,11 +106,11 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c
}
if (cfp->iseq != 0) {
-#define RUBY_VM_IFUNC_P(ptr) imemo_type_p((VALUE)ptr, imemo_ifunc)
+#define RUBY_VM_IFUNC_P(ptr) IMEMO_TYPE_P(ptr, imemo_ifunc)
if (RUBY_VM_IFUNC_P(cfp->iseq)) {
iseq_name = "<ifunc>";
}
- else if (SYMBOL_P(cfp->iseq)) {
+ else if (SYMBOL_P((VALUE)cfp->iseq)) {
tmp = rb_sym2str((VALUE)cfp->iseq);
iseq_name = RSTRING_PTR(tmp);
snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name);
@@ -159,7 +162,7 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c
char buff[0x100];
if (me) {
- if (imemo_type_p((VALUE)me, imemo_ment)) {
+ if (IMEMO_TYPE_P(me, imemo_ment)) {
fprintf(stderr, " me:\n");
fprintf(stderr, " called_id: %s, type: %s\n", rb_id2name(me->called_id), rb_method_type_name(me->def->type));
fprintf(stderr, " owner class: %s\n", rb_raw_obj_info(buff, 0x100, me->owner));
@@ -724,7 +727,7 @@ dump_thread(void *arg)
if (pSymFromAddr(ph, addr, &displacement, info)) {
if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath)))
fprintf(stderr, "%s", libpath);
- fprintf(stderr, "(%s+0x%I64x)",
+ fprintf(stderr, "(%s+0x%"PRI_64_PREFIX"x)",
info->Name, displacement);
}
fprintf(stderr, " [0x%p]", (void *)(VALUE)addr);
@@ -753,7 +756,7 @@ rb_print_backtrace(void)
#define MAX_NATIVE_TRACE 1024
static void *trace[MAX_NATIVE_TRACE];
int n = (int)backtrace(trace, MAX_NATIVE_TRACE);
-#if (defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)) && defined(HAVE_DLADDR) && !defined(__sparc)
+#if (defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)) && defined(HAVE_DLADDR) && !defined(__sparc) && !defined(__riscv)
rb_dump_backtrace_with_lines(n, trace);
#else
char **syms = backtrace_symbols(trace, n);
@@ -778,7 +781,7 @@ rb_print_backtrace(void)
#endif
#if defined __linux__
-# if defined __x86_64__ || defined __i386__
+# if defined __x86_64__ || defined __i386__ || defined __aarch64__ || defined __arm__
# define HAVE_PRINT_MACHINE_REGISTERS 1
# endif
#elif defined __APPLE__
@@ -808,7 +811,11 @@ print_machine_register(size_t reg, const char *reg_name, int col_count, int max_
return col_count;
}
# ifdef __linux__
-# define dump_machine_register(reg) (col_count = print_machine_register(mctx->gregs[REG_##reg], #reg, col_count, 80))
+# if defined(__x86_64__) || defined(__i386__)
+# define dump_machine_register(reg) (col_count = print_machine_register(mctx->gregs[REG_##reg], #reg, col_count, 80))
+# elif defined(__aarch64__) || defined(__arm__)
+# define dump_machine_register(reg, regstr) (col_count = print_machine_register(reg, #regstr, col_count, 80))
+# endif
# elif defined __APPLE__
# define dump_machine_register(reg) (col_count = print_machine_register(mctx->MCTX_SS_REG(reg), #reg, col_count, 80))
# endif
@@ -864,6 +871,43 @@ rb_dump_machine_register(const ucontext_t *ctx)
dump_machine_register(EFL);
dump_machine_register(UESP);
dump_machine_register(SS);
+# elif defined __aarch64__
+ dump_machine_register(mctx->regs[0], "x0");
+ dump_machine_register(mctx->regs[1], "x1");
+ dump_machine_register(mctx->regs[2], "x2");
+ dump_machine_register(mctx->regs[3], "x3");
+ dump_machine_register(mctx->regs[4], "x4");
+ dump_machine_register(mctx->regs[5], "x5");
+ dump_machine_register(mctx->regs[6], "x6");
+ dump_machine_register(mctx->regs[7], "x7");
+ dump_machine_register(mctx->regs[18], "x18");
+ dump_machine_register(mctx->regs[19], "x19");
+ dump_machine_register(mctx->regs[20], "x20");
+ dump_machine_register(mctx->regs[21], "x21");
+ dump_machine_register(mctx->regs[22], "x22");
+ dump_machine_register(mctx->regs[23], "x23");
+ dump_machine_register(mctx->regs[24], "x24");
+ dump_machine_register(mctx->regs[25], "x25");
+ dump_machine_register(mctx->regs[26], "x26");
+ dump_machine_register(mctx->regs[27], "x27");
+ dump_machine_register(mctx->regs[28], "x28");
+ dump_machine_register(mctx->regs[29], "x29");
+ dump_machine_register(mctx->sp, "sp");
+ dump_machine_register(mctx->fault_address, "fault_address");
+# elif defined __arm__
+ dump_machine_register(mctx->arm_r0, "r0");
+ dump_machine_register(mctx->arm_r1, "r1");
+ dump_machine_register(mctx->arm_r2, "r2");
+ dump_machine_register(mctx->arm_r3, "r3");
+ dump_machine_register(mctx->arm_r4, "r4");
+ dump_machine_register(mctx->arm_r5, "r5");
+ dump_machine_register(mctx->arm_r6, "r6");
+ dump_machine_register(mctx->arm_r7, "r7");
+ dump_machine_register(mctx->arm_r8, "r8");
+ dump_machine_register(mctx->arm_r9, "r9");
+ dump_machine_register(mctx->arm_r10, "r10");
+ dump_machine_register(mctx->arm_sp, "sp");
+ dump_machine_register(mctx->fault_address, "fault_address");
# endif
}
# elif defined __APPLE__
@@ -917,6 +961,18 @@ rb_dump_machine_register(const ucontext_t *ctx)
void
rb_vm_bugreport(const void *ctx)
{
+#if RUBY_DEVEL
+ const char *cmd = getenv("RUBY_ON_BUG");
+ if (cmd) {
+ char buf[0x100];
+ snprintf(buf, sizeof(buf), "%s %"PRI_PIDT_PREFIX"d", cmd, getpid());
+ int r = system(buf);
+ if (r == -1) {
+ snprintf(buf, sizeof(buf), "Launching RUBY_ON_BUG command failed.");
+ }
+ }
+#endif
+
#ifdef __linux__
# define PROC_MAPS_NAME "/proc/self/maps"
#endif
@@ -926,8 +982,9 @@ rb_vm_bugreport(const void *ctx)
enum {other_runtime_info = 0};
#endif
const rb_vm_t *const vm = GET_VM();
+ const rb_execution_context_t *ec = rb_current_execution_context(false);
- if (vm) {
+ if (vm && ec) {
SDR();
rb_backtrace_print_as_bugreport();
fputs("\n", stderr);
@@ -957,39 +1014,43 @@ rb_vm_bugreport(const void *ctx)
(((len = RSTRING_LEN(s)) > max_name_length) ? max_name_length : (int)len)
name = vm->progname;
- fprintf(stderr, "* Loaded script: %.*s\n",
- LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
- fprintf(stderr, "\n");
- fprintf(stderr, "* Loaded features:\n\n");
- for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) {
- name = RARRAY_AREF(vm->loaded_features, i);
- if (RB_TYPE_P(name, T_STRING)) {
- fprintf(stderr, " %4d %.*s\n", i,
- LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
- }
- else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) {
- const char *const type = RB_TYPE_P(name, T_CLASS) ?
- "class" : "module";
- name = rb_search_class_path(rb_class_real(name));
- if (!RB_TYPE_P(name, T_STRING)) {
- fprintf(stderr, " %4d %s:<unnamed>\n", i, type);
- continue;
- }
- fprintf(stderr, " %4d %s:%.*s\n", i, type,
- LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
- }
- else {
- VALUE klass = rb_search_class_path(rb_obj_class(name));
- if (!RB_TYPE_P(klass, T_STRING)) {
- fprintf(stderr, " %4d #<%p:%p>\n", i,
- (void *)CLASS_OF(name), (void *)name);
- continue;
- }
- fprintf(stderr, " %4d #<%.*s:%p>\n", i,
- LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass),
- (void *)name);
- }
- }
+ if (name) {
+ fprintf(stderr, "* Loaded script: %.*s\n",
+ LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
+ fprintf(stderr, "\n");
+ }
+ if (vm->loaded_features) {
+ fprintf(stderr, "* Loaded features:\n\n");
+ for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) {
+ name = RARRAY_AREF(vm->loaded_features, i);
+ if (RB_TYPE_P(name, T_STRING)) {
+ fprintf(stderr, " %4d %.*s\n", i,
+ LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
+ }
+ else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) {
+ const char *const type = RB_TYPE_P(name, T_CLASS) ?
+ "class" : "module";
+ name = rb_search_class_path(rb_class_real(name));
+ if (!RB_TYPE_P(name, T_STRING)) {
+ fprintf(stderr, " %4d %s:<unnamed>\n", i, type);
+ continue;
+ }
+ fprintf(stderr, " %4d %s:%.*s\n", i, type,
+ LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
+ }
+ else {
+ VALUE klass = rb_search_class_path(rb_obj_class(name));
+ if (!RB_TYPE_P(klass, T_STRING)) {
+ fprintf(stderr, " %4d #<%p:%p>\n", i,
+ (void *)CLASS_OF(name), (void *)name);
+ continue;
+ }
+ fprintf(stderr, " %4d #<%.*s:%p>\n", i,
+ LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass),
+ (void *)name);
+ }
+ }
+ }
fprintf(stderr, "\n");
}
@@ -1078,12 +1139,13 @@ const char *ruby_fill_thread_id_string(rb_nativethread_id_t thid, rb_thread_id_s
void
rb_vmdebug_stack_dump_all_threads(void)
{
- rb_vm_t *vm = GET_VM();
rb_thread_t *th = NULL;
+ rb_ractor_t *r = GET_RACTOR();
- list_for_each(&vm->living_threads, th, vmlt_node) {
+ // TODO: now it only shows current ractor
+ list_for_each(&r->threads.set, th, lt_node) {
#ifdef NON_SCALAR_THREAD_ID
- rb_thread_id_string_t buf;
+ rb_thread_id_string_t buf;
ruby_fill_thread_id_string(th->thread_id, buf);
fprintf(stderr, "th: %p, native_id: %s\n", th, buf);
#else
diff --git a/vm_eval.c b/vm_eval.c
index 76e56fac8a..59d5614dd2 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -15,12 +15,12 @@ struct local_var_list {
VALUE tbl;
};
-static inline VALUE method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat);
+static inline VALUE method_missing(rb_execution_context_t *ec, VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat);
static inline VALUE vm_yield_with_cref(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat, const rb_cref_t *cref, int is_lambda);
static inline VALUE vm_yield(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_splat);
static inline VALUE vm_yield_with_block(rb_execution_context_t *ec, int argc, const VALUE *argv, VALUE block_handler, int kw_splat);
static inline VALUE vm_yield_force_blockarg(rb_execution_context_t *ec, VALUE args);
-VALUE vm_exec(rb_execution_context_t *ec, int mjit_enable_p);
+VALUE vm_exec(rb_execution_context_t *ec, bool mjit_enable_p);
static void vm_set_eval_stack(rb_execution_context_t * th, const rb_iseq_t *iseq, const rb_cref_t *cref, const struct rb_block *base_block);
static int vm_collect_local_variables_in_heap(const VALUE *dfp, const struct local_var_list *vars);
@@ -38,38 +38,82 @@ typedef enum call_type {
} call_type;
static VALUE send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope);
-static VALUE vm_call0_body(rb_execution_context_t* ec, struct rb_calling_info *calling, struct rb_call_data *cd, const VALUE *argv);
+static VALUE vm_call0_body(rb_execution_context_t* ec, struct rb_calling_info *calling, const VALUE *argv);
#ifndef MJIT_HEADER
MJIT_FUNC_EXPORTED VALUE
-rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat)
+rb_vm_call0(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const rb_callable_method_entry_t *cme, int kw_splat)
{
- struct rb_calling_info calling = { Qundef, recv, argc, kw_splat, };
- struct rb_call_info ci = { id, (kw_splat ? VM_CALL_KW_SPLAT : 0), argc, };
- struct rb_call_cache cc = { 0, { 0, }, me, me->def->method_serial, vm_call_general, { 0, }, };
- struct rb_call_data cd = { cc, ci, };
- return vm_call0_body(ec, &calling, &cd, argv);
+ struct rb_calling_info calling = {
+ .ci = &VM_CI_ON_STACK(id, kw_splat ? VM_CALL_KW_SPLAT : 0, argc, NULL),
+ .cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, { 0 }, cme),
+ .block_handler = vm_passed_block_handler(ec),
+ .recv = recv,
+ .argc = argc,
+ .kw_splat = kw_splat,
+ };
+
+ return vm_call0_body(ec, &calling, argv);
+}
+
+static inline VALUE
+vm_call0_cc(rb_execution_context_t *ec, VALUE recv, ID id, int argc, const VALUE *argv, const struct rb_callcache *cc, int kw_splat)
+{
+ struct rb_calling_info calling = {
+ .ci = &VM_CI_ON_STACK(id, kw_splat ? VM_CALL_KW_SPLAT : 0, argc, NULL),
+ .cc = cc,
+ .block_handler = vm_passed_block_handler(ec),
+ .recv = recv,
+ .argc = argc,
+ .kw_splat = kw_splat,
+ };
+
+ return vm_call0_body(ec, &calling, argv);
+}
+
+static VALUE
+vm_call0_cme(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, const rb_callable_method_entry_t *cme)
+{
+ calling->cc = &VM_CC_ON_STACK(Qfalse, vm_call_general, { 0 }, cme);
+ return vm_call0_body(ec, calling, argv);
+}
+
+static VALUE
+vm_call0_super(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv, VALUE klass, enum method_missing_reason ex)
+{
+ ID mid = vm_ci_mid(calling->ci);
+ klass = RCLASS_SUPER(klass);
+
+ if (klass) {
+ const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
+
+ if (cme) {
+ RUBY_VM_CHECK_INTS(ec);
+ return vm_call0_cme(ec, calling, argv, cme);
+ }
+ }
+
+ vm_passed_block_handler_set(ec, calling->block_handler);
+ return method_missing(ec, calling->recv, mid, calling->argc, argv, ex, calling->kw_splat);
}
static VALUE
-vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *calling, struct rb_call_data *cd, const VALUE *argv)
+vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *calling, const VALUE *argv)
{
- const struct rb_call_info *ci = &cd->ci;
- const struct rb_call_cache *cc = &cd->cc;
+ const struct rb_callinfo *ci = calling->ci;
VALUE val;
- const rb_callable_method_entry_t *me = cc->me;
+ const rb_callable_method_entry_t *me = vm_cc_cme(calling->cc);
const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(me->def, body.cfunc);
int len = cfunc->argc;
VALUE recv = calling->recv;
int argc = calling->argc;
- ID mid = ci->mid;
+ ID mid = vm_ci_mid(ci);
VALUE block_handler = calling->block_handler;
int frame_flags = VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL;
if (calling->kw_splat) {
if (argc > 0 && RB_TYPE_P(argv[argc-1], T_HASH) && RHASH_EMPTY_P(argv[argc-1])) {
- frame_flags |= VM_FRAME_FLAG_CFRAME_EMPTY_KW;
argc--;
}
else {
@@ -100,24 +144,20 @@ vm_call0_cfunc_with_frame(rb_execution_context_t* ec, struct rb_calling_info *ca
}
static VALUE
-vm_call0_cfunc(rb_execution_context_t *ec, struct rb_calling_info *calling, struct rb_call_data *cd, const VALUE *argv)
+vm_call0_cfunc(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv)
{
- return vm_call0_cfunc_with_frame(ec, calling, cd, argv);
+ return vm_call0_cfunc_with_frame(ec, calling, argv);
}
/* `ci' should point temporal value (on stack value) */
static VALUE
-vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struct rb_call_data *cd, const VALUE *argv)
+vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, const VALUE *argv)
{
- const struct rb_call_info *ci = &cd->ci;
- struct rb_call_cache *cc = &cd->cc;
-
+ const struct rb_callinfo *ci = calling->ci;
+ const struct rb_callcache *cc = calling->cc;
VALUE ret;
- calling->block_handler = vm_passed_block_handler(ec);
-
- again:
- switch (cc->me->def->type) {
+ switch (vm_cc_cme(cc)->def->type) {
case VM_METHOD_TYPE_ISEQ:
{
rb_control_frame_t *reg_cfp = ec->cfp;
@@ -131,29 +171,24 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc
*reg_cfp->sp++ = argv[i];
}
- vm_call_iseq_setup(ec, reg_cfp, calling, cd);
+ vm_call_iseq_setup(ec, reg_cfp, calling);
VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);
- return vm_exec(ec, TRUE); /* CHECK_INTS in this function */
+ return vm_exec(ec, true); /* CHECK_INTS in this function */
}
case VM_METHOD_TYPE_NOTIMPLEMENTED:
case VM_METHOD_TYPE_CFUNC:
- ret = vm_call0_cfunc(ec, calling, cd, argv);
+ ret = vm_call0_cfunc(ec, calling, argv);
goto success;
case VM_METHOD_TYPE_ATTRSET:
if (calling->kw_splat &&
calling->argc > 0 &&
RB_TYPE_P(argv[calling->argc-1], T_HASH) &&
RHASH_EMPTY_P(argv[calling->argc-1])) {
- if (calling->argc == 1) {
- rb_warn("Passing the keyword argument as the last hash parameter is deprecated");
- }
- else {
- calling->argc--;
- }
+ calling->argc--;
}
rb_check_arity(calling->argc, 1, 1);
- ret = rb_ivar_set(calling->recv, cc->me->def->body.attr.id, argv[0]);
+ ret = rb_ivar_set(calling->recv, vm_cc_cme(cc)->def->body.attr.id, argv[0]);
goto success;
case VM_METHOD_TYPE_IVAR:
if (calling->kw_splat &&
@@ -164,49 +199,38 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc
}
rb_check_arity(calling->argc, 0, 0);
- ret = rb_attr_get(calling->recv, cc->me->def->body.attr.id);
+ ret = rb_attr_get(calling->recv, vm_cc_cme(cc)->def->body.attr.id);
goto success;
case VM_METHOD_TYPE_BMETHOD:
- ret = vm_call_bmethod_body(ec, calling, cd, argv);
+ ret = vm_call_bmethod_body(ec, calling, argv);
goto success;
case VM_METHOD_TYPE_ZSUPER:
+ {
+ VALUE klass = RCLASS_ORIGIN(vm_cc_cme(cc)->defined_class);
+ return vm_call0_super(ec, calling, argv, klass, MISSING_SUPER);
+ }
case VM_METHOD_TYPE_REFINED:
{
- const rb_method_type_t type = cc->me->def->type;
- VALUE super_class = cc->me->defined_class;
+ const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
- if (type == VM_METHOD_TYPE_ZSUPER) {
- super_class = RCLASS_ORIGIN(super_class);
- }
- else if (cc->me->def->body.refined.orig_me) {
- CC_SET_ME(cc, refined_method_callable_without_refinement(cc->me));
- goto again;
- }
-
- super_class = RCLASS_SUPER(super_class);
- if (super_class) {
- CC_SET_ME(cc, rb_callable_method_entry(super_class, ci->mid));
- if (cc->me) {
- RUBY_VM_CHECK_INTS(ec);
- goto again;
- }
+ if (cme->def->body.refined.orig_me) {
+ const rb_callable_method_entry_t *orig_cme = refined_method_callable_without_refinement(cme);
+ return vm_call0_cme(ec, calling, argv, orig_cme);
}
- enum method_missing_reason ex = (type == VM_METHOD_TYPE_ZSUPER) ? MISSING_SUPER : 0;
- ret = method_missing(calling->recv, ci->mid, calling->argc, argv, ex, calling->kw_splat);
- goto success;
+ VALUE klass = cme->defined_class;
+ return vm_call0_super(ec, calling, argv, klass, 0);
}
case VM_METHOD_TYPE_ALIAS:
- CC_SET_ME(cc, aliased_callable_method_entry(cc->me));
- goto again;
+ return vm_call0_cme(ec, calling, argv, aliased_callable_method_entry(vm_cc_cme(cc)));
case VM_METHOD_TYPE_MISSING:
{
- vm_passed_block_handler_set(ec, calling->block_handler);
- return method_missing(calling->recv, ci->mid, calling->argc,
+ vm_passed_block_handler_set(ec, calling->block_handler);
+ return method_missing(ec, calling->recv, vm_ci_mid(ci), calling->argc,
argv, MISSING_NOENTRY, calling->kw_splat);
}
case VM_METHOD_TYPE_OPTIMIZED:
- switch (cc->me->def->body.optimize_type) {
+ switch (vm_cc_cme(cc)->def->body.optimize_type) {
case OPTIMIZED_METHOD_TYPE_SEND:
ret = send_internal(calling->argc, argv, calling->recv, calling->kw_splat ? CALL_FCALL_KW : CALL_FCALL);
goto success;
@@ -218,13 +242,13 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc
goto success;
}
default:
- rb_bug("vm_call0: unsupported optimized method type (%d)", cc->me->def->body.optimize_type);
+ rb_bug("vm_call0: unsupported optimized method type (%d)", vm_cc_cme(cc)->def->body.optimize_type);
}
break;
case VM_METHOD_TYPE_UNDEF:
break;
}
- rb_bug("vm_call0: unsupported method type (%d)", cc->me->def->type);
+ rb_bug("vm_call0: unsupported method type (%d)", vm_cc_cme(cc)->def->type);
return Qundef;
success:
@@ -232,42 +256,10 @@ vm_call0_body(rb_execution_context_t *ec, struct rb_calling_info *calling, struc
return ret;
}
-/* Caller should keep the reference to the return value until argv becomes useless. */
-MJIT_FUNC_EXPORTED VALUE
-rb_adjust_argv_kw_splat(int *argc, const VALUE **argv, int *kw_splat)
-{
- if (*kw_splat == RB_PASS_CALLED_KEYWORDS || *kw_splat == RB_PASS_EMPTY_KEYWORDS) {
- if (*kw_splat == RB_PASS_EMPTY_KEYWORDS || rb_empty_keyword_given_p()) {
- int n = *argc;
- VALUE v;
- VALUE *ptr = rb_alloc_tmp_buffer2(&v, n+1, sizeof(VALUE));
- if (n) memcpy(ptr, *argv, sizeof(VALUE)*n);
- ptr[n] = rb_hash_new();
- *argc = ++n;
- *argv = ptr;
- *kw_splat = 1;
- return v;
- }
- else {
- *kw_splat = rb_keyword_given_p();
- }
- }
-
- if (*kw_splat && (*argc == 0 || !RB_TYPE_P((*argv)[(*argc)-1], T_HASH))) {
- rb_warn("Keyword flag passed calling internal method, but last entry is not a hash, unsetting keyword flag");
- *kw_splat = 0;
- }
-
- return 0;
-}
-
MJIT_FUNC_EXPORTED VALUE
rb_vm_call_kw(rb_execution_context_t *ec, VALUE recv, VALUE id, int argc, const VALUE *argv, const rb_callable_method_entry_t *me, int kw_splat)
{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_vm_call0(ec, recv, id, argc, argv, me, kw_splat);
}
static inline VALUE
@@ -289,7 +281,7 @@ vm_call_super(rb_execution_context_t *ec, int argc, const VALUE *argv, int kw_sp
me = rb_callable_method_entry(klass, id);
if (!me) {
- return method_missing(recv, id, argc, argv, MISSING_SUPER, kw_splat);
+ return method_missing(ec, recv, id, argc, argv, MISSING_SUPER, kw_splat);
}
return rb_vm_call_kw(ec, recv, id, argc, argv, me, kw_splat);
}
@@ -335,9 +327,116 @@ stack_check(rb_execution_context_t *ec)
#ifndef MJIT_HEADER
+void
+rb_check_stack_overflow(void)
+{
+#ifndef RB_THREAD_LOCAL_SPECIFIER
+ if (!ruby_current_ec_key) return;
+#endif
+ rb_execution_context_t *ec = GET_EC();
+ if (ec) stack_check(ec);
+}
+
+NORETURN(static void uncallable_object(VALUE recv, ID mid));
static inline const rb_callable_method_entry_t *rb_search_method_entry(VALUE recv, ID mid);
static inline enum method_missing_reason rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry_t *me, call_type scope, VALUE self);
+static const struct rb_callcache *
+cc_new(VALUE klass, ID mid, int argc, const rb_callable_method_entry_t *cme)
+{
+ const struct rb_callcache *cc;
+
+ RB_VM_LOCK_ENTER();
+ {
+ struct rb_class_cc_entries *ccs;
+ struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
+
+ if (rb_id_table_lookup(cc_tbl, mid, (VALUE*)&ccs)) {
+ // ok
+ }
+ else {
+ ccs = vm_ccs_create(klass, cme);
+ rb_id_table_insert(cc_tbl, mid, (VALUE)ccs);
+ }
+
+ if (ccs->len > 0) {
+ cc = ccs->entries[0].cc;
+ }
+ else {
+ const struct rb_callinfo *ci = vm_ci_new(mid, 0, argc, false); // TODO: proper ci
+ cc = vm_cc_new(klass, cme, vm_call_general);
+ METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme);
+ vm_ccs_push(klass, ccs, ci, cc);
+ }
+ }
+ RB_VM_LOCK_LEAVE();
+
+ return cc;
+}
+
+static VALUE
+gccct_hash(VALUE klass, ID mid)
+{
+ return (klass >> 3) ^ (VALUE)mid;
+}
+
+NOINLINE(static const struct rb_callcache *gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index));
+
+static const struct rb_callcache *
+gccct_method_search_slowpath(rb_vm_t *vm, VALUE klass, ID mid, int argc, unsigned int index)
+{
+ const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
+ const struct rb_callcache *cc;
+
+ if (cme != NULL) {
+ cc = cc_new(klass, mid, argc, cme);
+ }
+ else {
+ cc = NULL;
+ }
+
+ return vm->global_cc_cache_table[index] = cc;
+}
+
+static inline const struct rb_callcache *
+gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc)
+{
+ VALUE klass;
+
+ if (!SPECIAL_CONST_P(recv)) {
+ klass = RBASIC_CLASS(recv);
+ if (UNLIKELY(!klass)) uncallable_object(recv, mid);
+ }
+ else {
+ klass = CLASS_OF(recv);
+ }
+
+ // search global method cache
+ unsigned int index = (unsigned int)(gccct_hash(klass, mid) % VM_GLOBAL_CC_CACHE_TABLE_SIZE);
+ rb_vm_t *vm = rb_ec_vm_ptr(ec);
+ const struct rb_callcache *cc = vm->global_cc_cache_table[index];
+
+ if (LIKELY(cc)) {
+ if (LIKELY(vm_cc_class_check(cc, klass))) {
+ const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
+ if (LIKELY(!METHOD_ENTRY_INVALIDATED(cme) &&
+ cme->called_id == mid)) {
+
+ VM_ASSERT(vm_cc_cme(cc) == rb_callable_method_entry(klass, mid));
+ RB_DEBUG_COUNTER_INC(gccct_hit);
+
+ return cc;
+ }
+ }
+ }
+ else {
+ RB_DEBUG_COUNTER_INC(gccct_null);
+ }
+
+ RB_DEBUG_COUNTER_INC(gccct_miss);
+ return gccct_method_search_slowpath(vm, klass, mid, argc, index);
+}
+
/*!
* \internal
* calls the specified method.
@@ -359,7 +458,6 @@ rb_call0(rb_execution_context_t *ec,
VALUE recv, ID mid, int argc, const VALUE *argv,
call_type call_scope, VALUE self)
{
- const rb_callable_method_entry_t *me;
enum method_missing_reason call_status;
call_type scope = call_scope;
int kw_splat = RB_NO_KEYWORDS;
@@ -377,19 +475,34 @@ rb_call0(rb_execution_context_t *ec,
break;
}
+ const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc);
+
if (scope == CALL_PUBLIC) {
- me = rb_callable_method_entry_with_refinements(CLASS_OF(recv), mid, NULL);
+ RB_DEBUG_COUNTER_INC(call0_public);
+
+ const rb_callable_method_entry_t *cc_cme = cc ? vm_cc_cme(cc) : NULL;
+ const rb_callable_method_entry_t *cme = callable_method_entry_refeinements0(CLASS_OF(recv), mid, NULL, true, cc_cme);
+ call_status = rb_method_call_status(ec, cme, scope, self);
+
+ if (UNLIKELY(call_status != MISSING_NONE)) {
+ return method_missing(ec, recv, mid, argc, argv, call_status, kw_splat);
+ }
+ else if (UNLIKELY(cc_cme != cme)) { // refinement is solved
+ stack_check(ec);
+ return rb_vm_call_kw(ec, recv, mid, argc, argv, cme, kw_splat);
+ }
}
else {
- me = rb_search_method_entry(recv, mid);
- }
- call_status = rb_method_call_status(ec, me, scope, self);
+ RB_DEBUG_COUNTER_INC(call0_other);
+ call_status = rb_method_call_status(ec, cc ? vm_cc_cme(cc) : NULL, scope, self);
- if (call_status != MISSING_NONE) {
- return method_missing(recv, mid, argc, argv, call_status, kw_splat);
+ if (UNLIKELY(call_status != MISSING_NONE)) {
+ return method_missing(ec, recv, mid, argc, argv, call_status, kw_splat);
+ }
}
+
stack_check(ec);
- return rb_vm_call_kw(ec, recv, mid, argc, argv, me, kw_splat);
+ return vm_call0_cc(ec, recv, mid, argc, argv, cc, kw_splat);
}
struct rescue_funcall_args {
@@ -397,7 +510,7 @@ struct rescue_funcall_args {
VALUE recv;
ID mid;
rb_execution_context_t *ec;
- const rb_method_entry_t *me;
+ const rb_callable_method_entry_t *cme;
unsigned int respond: 1;
unsigned int respond_to_missing: 1;
int argc;
@@ -411,7 +524,7 @@ check_funcall_exec(VALUE v)
struct rescue_funcall_args *args = (void *)v;
return call_method_entry(args->ec, args->defined_class,
args->recv, idMethodMissing,
- args->me, args->argc, args->argv, args->kw_splat);
+ args->cme, args->argc, args->argv, args->kw_splat);
}
static VALUE
@@ -420,8 +533,8 @@ check_funcall_failed(VALUE v, VALUE e)
struct rescue_funcall_args *args = (void *)v;
int ret = args->respond;
if (!ret) {
- switch (rb_method_boundp(args->defined_class, args->mid,
- BOUND_PRIVATE|BOUND_RESPONDS)) {
+ switch (method_boundp(args->defined_class, args->mid,
+ BOUND_PRIVATE|BOUND_RESPONDS)) {
case 2:
ret = TRUE;
break;
@@ -455,7 +568,7 @@ static VALUE
check_funcall_missing(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int respond, VALUE def, int kw_splat)
{
struct rescue_funcall_args args;
- const rb_method_entry_t *me;
+ const rb_callable_method_entry_t *cme;
VALUE ret = Qundef;
ret = basic_obj_respond_to_missing(ec, klass, recv,
@@ -464,8 +577,9 @@ check_funcall_missing(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mi
args.respond = respond > 0;
args.respond_to_missing = (ret != Qundef);
ret = def;
- me = method_entry_get(klass, idMethodMissing, &args.defined_class);
- if (me && !METHOD_ENTRY_BASIC(me)) {
+ cme = callable_method_entry(klass, idMethodMissing, &args.defined_class);
+
+ if (cme && !METHOD_ENTRY_BASIC(cme)) {
VALUE argbuf, *new_args = ALLOCV_N(VALUE, argbuf, argc+1);
new_args[0] = ID2SYM(mid);
@@ -480,7 +594,7 @@ check_funcall_missing(rb_execution_context_t *ec, VALUE klass, VALUE recv, ID mi
ec->method_missing_reason = MISSING_NOENTRY;
args.ec = ec;
args.recv = recv;
- args.me = me;
+ args.cme = cme;
args.mid = mid;
args.argc = argc + 1;
args.argv = new_args;
@@ -606,7 +720,6 @@ rb_type_str(enum ruby_value_type type)
return NULL;
}
-NORETURN(static void uncallable_object(VALUE recv, ID mid));
static void
uncallable_object(VALUE recv, ID mid)
{
@@ -662,8 +775,7 @@ rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry
rb_method_visibility_t visi;
if (UNDEFINED_METHOD_ENTRY_P(me)) {
- undefined:
- return scope == CALL_VCALL ? MISSING_VCALL : MISSING_NOENTRY;
+ goto undefined;
}
if (me->def->type == VM_METHOD_TYPE_REFINED) {
me = rb_resolve_refined_method_callable(Qnil, me);
@@ -697,6 +809,8 @@ rb_method_call_status(rb_execution_context_t *ec, const rb_callable_method_entry
}
return MISSING_NONE;
+ undefined:
+ return scope == CALL_VCALL ? MISSING_VCALL : MISSING_NOENTRY;
}
@@ -839,18 +953,16 @@ vm_raise_method_missing(rb_execution_context_t *ec, int argc, const VALUE *argv,
}
static inline VALUE
-method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat)
+method_missing(rb_execution_context_t *ec, VALUE obj, ID id, int argc, const VALUE *argv, enum method_missing_reason call_status, int kw_splat)
{
VALUE *nargv, result, work, klass;
- rb_execution_context_t *ec = GET_EC();
VALUE block_handler = vm_passed_block_handler(ec);
const rb_callable_method_entry_t *me;
ec->method_missing_reason = call_status;
if (id == idMethodMissing) {
- missing:
- raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING);
+ goto missing;
}
nargv = ALLOCV_N(VALUE, work, argc + 1);
@@ -874,10 +986,52 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, enum method_missin
result = rb_vm_call_kw(ec, obj, idMethodMissing, argc, argv, me, kw_splat);
if (work) ALLOCV_END(work);
return result;
+ missing:
+ raise_method_missing(ec, argc, argv, obj, call_status | MISSING_MISSING);
+ UNREACHABLE_RETURN(Qundef);
}
#ifndef MJIT_HEADER
+static inline VALUE
+rb_funcallv_scope(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope)
+{
+ rb_execution_context_t *ec = GET_EC();
+ const struct rb_callcache *cc = gccct_method_search(ec, recv, mid, argc);
+ VALUE self = ec->cfp->self;
+
+ if (LIKELY(cc) &&
+ LIKELY(rb_method_call_status(ec, vm_cc_cme(cc), scope, self) == MISSING_NONE)) {
+ // fastpath
+ return vm_call0_cc(ec, recv, mid, argc, argv, cc, false);
+ }
+ else {
+ return rb_call0(ec, recv, mid, argc, argv, scope, self);
+ }
+}
+
+#ifdef rb_funcallv
+#undef rb_funcallv
+#endif
+/*!
+ * Calls a method
+ * \param recv receiver of the method
+ * \param mid an ID that represents the name of the method
+ * \param argc the number of arguments
+ * \param argv pointer to an array of method arguments
+ */
+VALUE
+rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
+{
+ return rb_funcallv_scope(recv, mid, argc, argv, CALL_FCALL);
+}
+
+VALUE
+rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
+{
+ return rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
+}
+
/*!
* Calls a method
* \param recv receiver of the method
@@ -903,7 +1057,8 @@ rb_apply(VALUE recv, ID mid, VALUE args)
}
argv = ALLOCA_N(VALUE, argc);
MEMCPY(argv, RARRAY_CONST_PTR_TRANSIENT(args), VALUE, argc);
- return rb_call(recv, mid, argc, argv, CALL_FCALL);
+
+ return rb_funcallv(recv, mid, argc, argv);
}
#ifdef rb_funcall
@@ -927,7 +1082,7 @@ rb_funcall(VALUE recv, ID mid, int n, ...)
if (n > 0) {
long i;
- va_init_list(ar, n);
+ va_start(ar, n);
argv = ALLOCA_N(VALUE, n);
@@ -939,32 +1094,34 @@ rb_funcall(VALUE recv, ID mid, int n, ...)
else {
argv = 0;
}
- return rb_call(recv, mid, n, argv, CALL_FCALL);
+ return rb_funcallv(recv, mid, n, argv);
}
-#ifdef rb_funcallv
-#undef rb_funcallv
-#endif
/*!
- * Calls a method
+ * Calls a method only if it is the basic method of `ancestor`
+ * otherwise returns Qundef;
* \param recv receiver of the method
* \param mid an ID that represents the name of the method
+ * \param ancestor the Class that defined the basic method
* \param argc the number of arguments
* \param argv pointer to an array of method arguments
+ * \param kw_splat bool
*/
VALUE
-rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
+rb_check_funcall_basic_kw(VALUE recv, ID mid, VALUE ancestor, int argc, const VALUE *argv, int kw_splat)
{
- return rb_call(recv, mid, argc, argv, CALL_FCALL);
-}
+ const rb_callable_method_entry_t *cme;
+ rb_execution_context_t *ec;
+ VALUE klass = CLASS_OF(recv);
+ if (!klass) return Qundef; /* hidden object */
-VALUE
-rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
-{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_FCALL_KW : CALL_FCALL);
- rb_free_tmp_buffer(&v);
- return ret;
+ cme = rb_callable_method_entry(klass, mid);
+ if (cme && METHOD_ENTRY_BASIC(cme) && RBASIC_CLASS(cme->defined_class) == ancestor) {
+ ec = GET_EC();
+ return rb_vm_call0(ec, recv, mid, argc, argv, cme, kw_splat);
+ }
+
+ return Qundef;
}
/*!
@@ -979,71 +1136,27 @@ rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
VALUE
rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
{
- return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
+ return rb_funcallv_scope(recv, mid, argc, argv, CALL_PUBLIC);
}
VALUE
rb_funcallv_public_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
- rb_free_tmp_buffer(&v);
- return ret;
-}
-
-/*!
- * Calls a method
- * \private
- * \param cd opaque call data
- * \param recv receiver of the method
- * \param mid an ID that represents the name of the method
- * \param argc the number of arguments
- * \param argv pointer to an array of method arguments
- */
-VALUE
-rb_funcallv_with_cc(struct rb_call_data *cd, VALUE recv, ID mid, int argc, const VALUE *argv)
-{
- const struct rb_call_info *ci = &cd->ci;
- struct rb_call_cache *cc = &cd->cc;
-
- if (LIKELY(ci->mid == mid)) {
- vm_search_method(cd, recv);
-
- if (LIKELY(! UNDEFINED_METHOD_ENTRY_P(cc->me))) {
- return vm_call0_body(
- GET_EC(),
- &(struct rb_calling_info) {
- Qundef,
- recv,
- argc,
- RB_NO_KEYWORDS,
- },
- cd,
- argv
- );
- }
- }
-
- *cd = (struct rb_call_data) /* reset */ { { 0, }, { mid, }, };
- return rb_funcallv(recv, mid, argc, argv);
+ return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
}
VALUE
rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv)
{
PASS_PASSED_BLOCK_HANDLER();
- return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
+ return rb_funcallv_public(recv, mid, argc, argv);
}
VALUE
rb_funcall_passing_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret;
PASS_PASSED_BLOCK_HANDLER();
- ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
}
VALUE
@@ -1053,7 +1166,7 @@ rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE pas
vm_passed_block_handler_set(GET_EC(), passed_procval);
}
- return rb_call(recv, mid, argc, argv, CALL_PUBLIC);
+ return rb_funcallv_public(recv, mid, argc, argv);
}
VALUE
@@ -1063,10 +1176,7 @@ rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE
vm_passed_block_handler_set(GET_EC(), passed_procval);
}
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_call(recv, mid, argc, argv, kw_splat ? CALL_PUBLIC_KW : CALL_PUBLIC);
}
static VALUE *
@@ -1140,10 +1250,7 @@ send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope)
static VALUE
send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope)
{
- VALUE v=0, ret;
- int kw_splat = RB_PASS_CALLED_KEYWORDS;
- v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- if (kw_splat) {
+ if (rb_keyword_given_p()) {
switch (scope) {
case CALL_PUBLIC:
scope = CALL_PUBLIC_KW;
@@ -1155,9 +1262,7 @@ send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope)
break;
}
}
- ret = send_internal(argc, argv, recv, scope);
- rb_free_tmp_buffer(&v);
- return ret;
+ return send_internal(argc, argv, recv, scope);
}
/*
@@ -1168,12 +1273,14 @@ send_internal_kw(int argc, const VALUE *argv, VALUE recv, call_type scope)
* foo.__send__(string [, args...]) -> obj
*
* Invokes the method identified by _symbol_, passing it any
- * arguments specified. You can use <code>__send__</code> if the name
- * +send+ clashes with an existing method in _obj_.
+ * arguments specified.
* When the method is identified by a string, the string is converted
* to a symbol.
*
* BasicObject implements +__send__+, Kernel implements +send+.
+ * <code>__send__</code> is safer than +send+
+ * when _obj_ has the same method name like <code>Socket</code>.
+ * See also <code>public_send</code>.
*
* class Klass
* def hello(*args)
@@ -1215,10 +1322,7 @@ rb_f_public_send(int argc, VALUE *argv, VALUE recv)
static inline VALUE
rb_yield_0_kw(int argc, const VALUE * argv, int kw_splat)
{
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = vm_yield(GET_EC(), argc, argv, kw_splat);
- rb_free_tmp_buffer(&v);
- return ret;
+ return vm_yield(GET_EC(), argc, argv, kw_splat);
}
static inline VALUE
@@ -1237,10 +1341,10 @@ VALUE
rb_yield(VALUE val)
{
if (val == Qundef) {
- return rb_yield_0(0, 0);
+ return rb_yield_0(0, NULL);
}
else {
- return rb_yield_1(val);
+ return rb_yield_0(1, &val);
}
}
@@ -1257,7 +1361,7 @@ rb_yield_values(int n, ...)
va_list args;
argv = ALLOCA_N(VALUE, n);
- va_init_list(args, n);
+ va_start(args, n);
for (i=0; i<n; i++) {
argv[i] = va_arg(args, VALUE);
}
@@ -1314,13 +1418,9 @@ rb_yield_force_blockarg(VALUE values)
VALUE
rb_yield_block(RB_BLOCK_CALL_FUNC_ARGLIST(val, arg))
{
- int kw_splat = RB_PASS_CALLED_KEYWORDS;
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
- VALUE ret = vm_yield_with_block(GET_EC(), argc, argv,
- NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg,
- kw_splat);
- rb_free_tmp_buffer(&v);
- return ret;
+ return vm_yield_with_block(GET_EC(), argc, argv,
+ NIL_P(blockarg) ? VM_BLOCK_HANDLER_NONE : blockarg,
+ rb_keyword_given_p());
}
static VALUE
@@ -1486,15 +1586,12 @@ rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE * argv,
{
struct iter_method_arg arg;
- VALUE v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
arg.obj = obj;
arg.mid = mid;
arg.argc = argc;
arg.argv = argv;
arg.kw_splat = kw_splat;
- VALUE ret = rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_iterate(iterate_method, (VALUE)&arg, bl_proc, data2);
}
VALUE
@@ -1554,6 +1651,23 @@ eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind,
VALUE realpath = Qnil;
rb_iseq_t *iseq = NULL;
rb_ast_t *ast;
+ int isolated_depth = 0;
+ {
+ int depth = 1;
+ const VALUE *ep = vm_block_ep(base_block);
+
+ while (1) {
+ if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) {
+ isolated_depth = depth;
+ break;
+ }
+ else if (VM_ENV_LOCAL_P(ep)) {
+ break;
+ }
+ ep = VM_ENV_PREV_EP(ep);
+ depth++;
+ }
+ }
if (!fname) {
fname = rb_source_location(&line);
@@ -1563,12 +1677,6 @@ eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind,
if (!NIL_P(fname)) fname = rb_fstring(fname);
realpath = fname;
}
- else if (bind) {
- fname = pathobj_path(bind->pathobj);
- realpath = pathobj_realpath(bind->pathobj);
- line = bind->first_lineno;
- rb_parser_warn_location(parser, TRUE);
- }
else {
fname = rb_fstring_lit("(eval)");
}
@@ -1576,10 +1684,10 @@ eval_make_iseq(VALUE src, VALUE fname, int line, const rb_binding_t *bind,
rb_parser_set_context(parser, parent, FALSE);
ast = rb_parser_compile_string_path(parser, fname, src, line);
if (ast->body.root) {
- iseq = rb_iseq_new_with_opt(&ast->body,
- parent->body->location.label,
- fname, realpath, INT2FIX(line),
- parent, ISEQ_TYPE_EVAL, NULL);
+ iseq = rb_iseq_new_eval(&ast->body,
+ parent->body->location.label,
+ fname, realpath, INT2FIX(line),
+ parent, isolated_depth);
}
rb_ast_dispose(ast);
@@ -1624,7 +1732,7 @@ eval_string_with_cref(VALUE self, VALUE src, rb_cref_t *cref, VALUE file, int li
vm_set_eval_stack(ec, iseq, cref, &block);
/* kick */
- return vm_exec(ec, TRUE);
+ return vm_exec(ec, true);
}
static VALUE
@@ -1645,7 +1753,7 @@ eval_string_with_scope(VALUE scope, VALUE src, VALUE file, int line)
}
/* kick */
- return vm_exec(ec, TRUE);
+ return vm_exec(ec, true);
}
/*
@@ -1820,13 +1928,6 @@ rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat)
return val;
}
-VALUE
-rb_eval_cmd(VALUE cmd, VALUE arg, int _level)
-{
- rb_warn("rb_eval_cmd will be removed in Ruby 3.0");
- return rb_eval_cmd_kw(cmd, arg, RB_NO_KEYWORDS);
-}
-
/* block eval under the class/module context */
static VALUE
@@ -1841,9 +1942,6 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat)
const VALUE *ep = NULL;
rb_cref_t *cref;
int is_lambda = FALSE;
- VALUE v = 0, ret;
-
- v = rb_adjust_argv_kw_splat(&argc, &argv, &kw_splat);
if (block_handler != VM_BLOCK_HANDLER_NONE) {
again:
@@ -1863,10 +1961,9 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat)
block_handler = vm_proc_to_block_handler(VM_BH_TO_PROC(block_handler));
goto again;
case block_handler_type_symbol:
- ret = rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
- argc, argv, kw_splat, VM_BLOCK_HANDLER_NONE);
- rb_free_tmp_buffer(&v);
- return ret;
+ return rb_sym_proc_call(SYM2ID(VM_BH_TO_SYMBOL(block_handler)),
+ argc, argv, kw_splat,
+ VM_BLOCK_HANDLER_NONE);
}
new_captured.self = self;
@@ -1876,9 +1973,7 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv, int kw_splat)
}
cref = vm_cref_push(ec, under, ep, TRUE);
- ret = vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda);
- rb_free_tmp_buffer(&v);
- return ret;
+ return vm_yield_with_cref(ec, argc, argv, kw_splat, cref, is_lambda);
}
VALUE
@@ -2424,7 +2519,6 @@ rb_f_local_variables(VALUE _)
/*
* call-seq:
* block_given? -> true or false
- * iterator? -> true or false
*
* Returns <code>true</code> if <code>yield</code> would execute a
* block in the current context. The <code>iterator?</code> form
@@ -2442,7 +2536,6 @@ rb_f_local_variables(VALUE _)
* try do "hello" end #=> "hello"
*/
-
static VALUE
rb_f_block_given_p(VALUE _)
{
@@ -2458,6 +2551,20 @@ rb_f_block_given_p(VALUE _)
}
}
+/*
+ * call-seq:
+ * iterator? -> true or false
+ *
+ * Deprecated. Use block_given? instead.
+ */
+
+static VALUE
+rb_f_iterator_p(VALUE self)
+{
+ rb_warn_deprecated("iterator?", "block_given?");
+ return rb_f_block_given_p(self);
+}
+
VALUE
rb_current_realfilepath(void)
{
@@ -2473,7 +2580,7 @@ Init_vm_eval(void)
{
rb_define_global_function("eval", rb_f_eval, -1);
rb_define_global_function("local_variables", rb_f_local_variables, 0);
- rb_define_global_function("iterator?", rb_f_block_given_p, 0);
+ rb_define_global_function("iterator?", rb_f_iterator_p, 0);
rb_define_global_function("block_given?", rb_f_block_given_p, 0);
rb_define_global_function("catch", rb_f_catch, -1);
diff --git a/vm_exec.c b/vm_exec.c
index cb09738247..7aa56f6ad6 100644
--- a/vm_exec.c
+++ b/vm_exec.c
@@ -15,6 +15,36 @@
static void vm_analysis_insn(int insn);
#endif
+#if USE_INSNS_COUNTER
+static size_t rb_insns_counter[VM_INSTRUCTION_SIZE];
+
+static void
+vm_insns_counter_count_insn(int insn)
+{
+ rb_insns_counter[insn]++;
+}
+
+__attribute__((destructor))
+static void
+vm_insns_counter_show_results_at_exit(void)
+{
+ int insn_end = (ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS)
+ ? VM_INSTRUCTION_SIZE : VM_INSTRUCTION_SIZE / 2;
+
+ size_t total = 0;
+ for (int insn = 0; insn < insn_end; insn++)
+ total += rb_insns_counter[insn];
+
+ for (int insn = 0; insn < insn_end; insn++) {
+ fprintf(stderr, "[RUBY_INSNS_COUNTER]\t%-32s%'12"PRIuSIZE" (%4.1f%%)\n",
+ insn_name(insn), rb_insns_counter[insn],
+ 100.0 * rb_insns_counter[insn] / total);
+ }
+}
+#else
+static void vm_insns_counter_count_insn(int insn) {}
+#endif
+
#if VMDEBUG > 0
#define DECL_SC_REG(type, r, reg) register type reg_##r
@@ -35,17 +65,6 @@ static void vm_analysis_insn(int insn);
#endif
/* #define DECL_SC_REG(r, reg) VALUE reg_##r */
-#if VM_DEBUG_STACKOVERFLOW
-NORETURN(static void vm_stack_overflow_for_insn(void));
-static void
-vm_stack_overflow_for_insn(void)
-{
- rb_bug("CHECK_VM_STACK_OVERFLOW_FOR_INSN: should not overflow here. "
- "Please contact ruby-core/dev with your (a part of) script. "
- "This check will be removed soon.");
-}
-#endif
-
#if !OPT_CALL_THREADED_CODE
static VALUE
vm_exec_core(rb_execution_context_t *ec, VALUE initial)
diff --git a/vm_exec.h b/vm_exec.h
index 9c8b42371d..1f2a052ff4 100644
--- a/vm_exec.h
+++ b/vm_exec.h
@@ -1,3 +1,5 @@
+#ifndef RUBY_VM_EXEC_H
+#define RUBY_VM_EXEC_H
/**********************************************************************
vm.h -
@@ -9,9 +11,6 @@
**********************************************************************/
-#ifndef RUBY_VM_EXEC_H
-#define RUBY_VM_EXEC_H
-
typedef long OFFSET;
typedef unsigned long lindex_t;
typedef VALUE GENTRY;
@@ -41,6 +40,10 @@ typedef rb_iseq_t *ISEQ;
#define throwdebug if(0)printf
/* #define throwdebug printf */
+#ifndef USE_INSNS_COUNTER
+#define USE_INSNS_COUNTER 0
+#endif
+
/************************************************/
#if defined(DISPATCH_XXX)
error !
@@ -75,7 +78,8 @@ error !
(reg_pc - reg_cfp->iseq->body->iseq_encoded), \
(reg_cfp->pc - reg_cfp->iseq->body->iseq_encoded), \
RSTRING_PTR(rb_iseq_path(reg_cfp->iseq)), \
- rb_iseq_line_no(reg_cfp->iseq, reg_pc - reg_cfp->iseq->body->iseq_encoded));
+ rb_iseq_line_no(reg_cfp->iseq, reg_pc - reg_cfp->iseq->body->iseq_encoded)); \
+ if (USE_INSNS_COUNTER) vm_insns_counter_count_insn(BIN(insn));
#define INSN_DISPATCH_SIG(insn)
@@ -181,8 +185,7 @@ default: \
#define VM_DEBUG_STACKOVERFLOW 0
#if VM_DEBUG_STACKOVERFLOW
-#define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin) \
- WHEN_VM_STACK_OVERFLOWED(cfp, (cfp)->sp, margin) vm_stack_overflow_for_insn()
+#define CHECK_VM_STACK_OVERFLOW_FOR_INSN CHECK_VM_STACK_OVERFLOW
#else
#define CHECK_VM_STACK_OVERFLOW_FOR_INSN(cfp, margin)
#endif
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 5f03e8daef..757e75d66f 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -8,17 +8,27 @@
**********************************************************************/
+#include "ruby/internal/config.h"
+
+#include <math.h>
+
+#include "constant.h"
+#include "debug_counter.h"
+#include "internal.h"
+#include "internal/class.h"
+#include "internal/compar.h"
+#include "internal/hash.h"
+#include "internal/numeric.h"
+#include "internal/proc.h"
+#include "internal/random.h"
+#include "internal/variable.h"
+#include "variable.h"
+
/* finish iseq array */
#include "insns.inc"
#ifndef MJIT_HEADER
#include "insns_info.inc"
#endif
-#include <math.h>
-#include "constant.h"
-#include "internal.h"
-#include "ruby/config.h"
-#include "debug_counter.h"
-#include "variable.h"
extern rb_method_definition_t *rb_method_definition_create(rb_method_type_t type, ID mid);
extern void rb_method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, void *opts);
@@ -26,6 +36,10 @@ extern int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_me
extern VALUE rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj,
int argc, const VALUE *argv, int priv);
+#ifndef MJIT_HEADER
+static const struct rb_callcache vm_empty_cc;
+#endif
+
/* control stack frame */
static rb_control_frame_t *vm_get_ruby_level_caller_cfp(const rb_execution_context_t *ec, const rb_control_frame_t *cfp);
@@ -55,6 +69,9 @@ ec_stack_overflow(rb_execution_context_t *ec, int setup)
}
NORETURN(static void vm_stackoverflow(void));
+#ifdef MJIT_HEADER
+NOINLINE(static COLDFUNC void vm_stackoverflow(void));
+#endif
static void
vm_stackoverflow(void)
@@ -66,7 +83,10 @@ NORETURN(MJIT_STATIC void rb_ec_stack_overflow(rb_execution_context_t *ec, int c
MJIT_STATIC void
rb_ec_stack_overflow(rb_execution_context_t *ec, int crit)
{
- if (crit || rb_during_gc()) {
+ if (rb_during_gc()) {
+ rb_bug("system stack overflow during GC. Faulty native extension?");
+ }
+ if (crit) {
ec->raised_flag = RAISED_STACKOVERFLOW;
ec->errinfo = rb_ec_vm_ptr(ec)->special_exceptions[ruby_error_stackfatal];
EC_JUMP_TAG(ec, TAG_RAISE);
@@ -86,6 +106,8 @@ callable_class_p(VALUE klass)
#if VM_CHECK_MODE >= 2
if (!klass) return FALSE;
switch (RB_BUILTIN_TYPE(klass)) {
+ default:
+ break;
case T_ICLASS:
if (!RB_TYPE_P(RCLASS_SUPER(klass), T_MODULE)) break;
case T_MODULE:
@@ -104,13 +126,20 @@ callable_class_p(VALUE klass)
}
static int
-callable_method_entry_p(const rb_callable_method_entry_t *me)
+callable_method_entry_p(const rb_callable_method_entry_t *cme)
{
- if (me == NULL || callable_class_p(me->defined_class)) {
- return TRUE;
+ if (cme == NULL) {
+ return TRUE;
}
else {
- return FALSE;
+ VM_ASSERT(IMEMO_TYPE_P((VALUE)cme, imemo_ment));
+
+ if (callable_class_p(cme->defined_class)) {
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
}
}
@@ -206,8 +235,9 @@ vm_check_frame(VALUE type,
static VALUE vm_stack_canary; /* Initialized later */
static bool vm_stack_canary_was_born = false;
-static void
-vm_check_canary(const rb_execution_context_t *ec, VALUE *sp)
+#ifndef MJIT_HEADER
+MJIT_FUNC_EXPORTED void
+rb_vm_check_canary(const rb_execution_context_t *ec, VALUE *sp)
{
const struct rb_control_frame_struct *reg_cfp = ec->cfp;
const struct rb_iseq_struct *iseq;
@@ -253,12 +283,69 @@ vm_check_canary(const rb_execution_context_t *ec, VALUE *sp)
name, stri, pos, strd);
rb_bug("see above.");
}
+#endif
+#define vm_check_canary(ec, sp) rb_vm_check_canary(ec, sp)
+
#else
#define vm_check_canary(ec, sp)
#define vm_check_frame(a, b, c, d)
#endif /* VM_CHECK_MODE > 0 */
-static inline rb_control_frame_t *
+#if USE_DEBUG_COUNTER
+static void
+vm_push_frame_debug_counter_inc(
+ const struct rb_execution_context_struct *ec,
+ const struct rb_control_frame_struct *reg_cfp,
+ VALUE type)
+{
+ const struct rb_control_frame_struct *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(reg_cfp);
+
+ RB_DEBUG_COUNTER_INC(frame_push);
+
+ if (RUBY_VM_END_CONTROL_FRAME(ec) != prev_cfp) {
+ const bool curr = VM_FRAME_RUBYFRAME_P(reg_cfp);
+ const bool prev = VM_FRAME_RUBYFRAME_P(prev_cfp);
+ if (prev) {
+ if (curr) {
+ RB_DEBUG_COUNTER_INC(frame_R2R);
+ }
+ else {
+ RB_DEBUG_COUNTER_INC(frame_R2C);
+ }
+ }
+ else {
+ if (curr) {
+ RB_DEBUG_COUNTER_INC(frame_C2R);
+ }
+ else {
+ RB_DEBUG_COUNTER_INC(frame_C2C);
+ }
+ }
+ }
+
+ switch (type & VM_FRAME_MAGIC_MASK) {
+ case VM_FRAME_MAGIC_METHOD: RB_DEBUG_COUNTER_INC(frame_push_method); return;
+ case VM_FRAME_MAGIC_BLOCK: RB_DEBUG_COUNTER_INC(frame_push_block); return;
+ case VM_FRAME_MAGIC_CLASS: RB_DEBUG_COUNTER_INC(frame_push_class); return;
+ case VM_FRAME_MAGIC_TOP: RB_DEBUG_COUNTER_INC(frame_push_top); return;
+ case VM_FRAME_MAGIC_CFUNC: RB_DEBUG_COUNTER_INC(frame_push_cfunc); return;
+ case VM_FRAME_MAGIC_IFUNC: RB_DEBUG_COUNTER_INC(frame_push_ifunc); return;
+ case VM_FRAME_MAGIC_EVAL: RB_DEBUG_COUNTER_INC(frame_push_eval); return;
+ case VM_FRAME_MAGIC_RESCUE: RB_DEBUG_COUNTER_INC(frame_push_rescue); return;
+ case VM_FRAME_MAGIC_DUMMY: RB_DEBUG_COUNTER_INC(frame_push_dummy); return;
+ }
+
+ rb_bug("unreachable");
+}
+#else
+#define vm_push_frame_debug_counter_inc(ec, cfp, t) /* void */
+#endif
+
+STATIC_ASSERT(VM_ENV_DATA_INDEX_ME_CREF, VM_ENV_DATA_INDEX_ME_CREF == -2);
+STATIC_ASSERT(VM_ENV_DATA_INDEX_SPECVAL, VM_ENV_DATA_INDEX_SPECVAL == -1);
+STATIC_ASSERT(VM_ENV_DATA_INDEX_FLAGS, VM_ENV_DATA_INDEX_FLAGS == -0);
+
+static void
vm_push_frame(rb_execution_context_t *ec,
const rb_iseq_t *iseq,
VALUE type,
@@ -279,14 +366,6 @@ vm_push_frame(rb_execution_context_t *ec,
CHECK_VM_STACK_OVERFLOW0(cfp, sp, local_size + stack_max);
vm_check_canary(ec, sp);
- ec->cfp = cfp;
-
- /* setup new frame */
- cfp->pc = (VALUE *)pc;
- cfp->iseq = (rb_iseq_t *)iseq;
- cfp->self = self;
- cfp->block_code = NULL;
-
/* setup vm value stack */
/* initialize local variables */
@@ -295,54 +374,30 @@ vm_push_frame(rb_execution_context_t *ec,
}
/* setup ep with managing data */
- VM_ASSERT(VM_ENV_DATA_INDEX_ME_CREF == -2);
- VM_ASSERT(VM_ENV_DATA_INDEX_SPECVAL == -1);
- VM_ASSERT(VM_ENV_DATA_INDEX_FLAGS == -0);
*sp++ = cref_or_me; /* ep[-2] / Qnil or T_IMEMO(cref) or T_IMEMO(ment) */
*sp++ = specval /* ep[-1] / block handler or prev env ptr */;
- *sp = type; /* ep[-0] / ENV_FLAGS */
-
- /* Store initial value of ep as bp to skip calculation cost of bp on JIT cancellation. */
- cfp->ep = sp;
- cfp->__bp__ = cfp->sp = sp + 1;
+ *sp++ = type; /* ep[-0] / ENV_FLAGS */
+ /* setup new frame */
+ *cfp = (const struct rb_control_frame_struct) {
+ .pc = pc,
+ .sp = sp,
+ .iseq = iseq,
+ .self = self,
+ .ep = sp - 1,
+ .block_code = NULL,
+ .__bp__ = sp, /* Store initial value of ep as bp to skip calculation cost of bp on JIT cancellation. */
#if VM_DEBUG_BP_CHECK
- cfp->bp_check = sp + 1;
+ .bp_check = sp,
#endif
+ };
+
+ ec->cfp = cfp;
if (VMDEBUG == 2) {
SDR();
}
-
-#if USE_DEBUG_COUNTER
- RB_DEBUG_COUNTER_INC(frame_push);
- switch (type & VM_FRAME_MAGIC_MASK) {
- case VM_FRAME_MAGIC_METHOD: RB_DEBUG_COUNTER_INC(frame_push_method); break;
- case VM_FRAME_MAGIC_BLOCK: RB_DEBUG_COUNTER_INC(frame_push_block); break;
- case VM_FRAME_MAGIC_CLASS: RB_DEBUG_COUNTER_INC(frame_push_class); break;
- case VM_FRAME_MAGIC_TOP: RB_DEBUG_COUNTER_INC(frame_push_top); break;
- case VM_FRAME_MAGIC_CFUNC: RB_DEBUG_COUNTER_INC(frame_push_cfunc); break;
- case VM_FRAME_MAGIC_IFUNC: RB_DEBUG_COUNTER_INC(frame_push_ifunc); break;
- case VM_FRAME_MAGIC_EVAL: RB_DEBUG_COUNTER_INC(frame_push_eval); break;
- case VM_FRAME_MAGIC_RESCUE: RB_DEBUG_COUNTER_INC(frame_push_rescue); break;
- case VM_FRAME_MAGIC_DUMMY: RB_DEBUG_COUNTER_INC(frame_push_dummy); break;
- default: rb_bug("unreachable");
- }
- {
- rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
- if (RUBY_VM_END_CONTROL_FRAME(ec) != prev_cfp) {
- int cur_ruby_frame = VM_FRAME_RUBYFRAME_P(cfp);
- int pre_ruby_frame = VM_FRAME_RUBYFRAME_P(prev_cfp);
-
- pre_ruby_frame ? (cur_ruby_frame ? RB_DEBUG_COUNTER_INC(frame_R2R) :
- RB_DEBUG_COUNTER_INC(frame_R2C)):
- (cur_ruby_frame ? RB_DEBUG_COUNTER_INC(frame_C2R) :
- RB_DEBUG_COUNTER_INC(frame_C2C));
- }
- }
-#endif
-
- return cfp;
+ vm_push_frame_debug_counter_inc(ec, cfp, type);
}
/* return TRUE if the frame is finished */
@@ -622,8 +677,19 @@ rb_vm_frame_method_entry(const rb_control_frame_t *cfp)
return check_method_entry(ep[VM_ENV_DATA_INDEX_ME_CREF], TRUE);
}
+static rb_iseq_t *
+method_entry_iseqptr(const rb_callable_method_entry_t *me)
+{
+ switch (me->def->type) {
+ case VM_METHOD_TYPE_ISEQ:
+ return me->def->body.iseq.iseqptr;
+ default:
+ return NULL;
+ }
+}
+
static rb_cref_t *
-method_entry_cref(rb_callable_method_entry_t *me)
+method_entry_cref(const rb_callable_method_entry_t *me)
{
switch (me->def->type) {
case VM_METHOD_TYPE_ISEQ:
@@ -934,7 +1000,13 @@ vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, bool allow_
if (is_defined) {
return 1;
}
- else {
+ else {
+ if (UNLIKELY(!rb_ractor_main_p())) {
+ if (!rb_ractor_shareable_p(val)) {
+ rb_raise(rb_eRactorIsolationError,
+ "can not access non-shareable objects in constant %"PRIsVALUE"::%s by non-main ractor.", rb_class_path(klass), rb_id2name(id));
+ }
+ }
return val;
}
}
@@ -969,7 +1041,7 @@ vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, bool allow_
}
static inline VALUE
-vm_get_cvar_base(const rb_cref_t *cref, rb_control_frame_t *cfp)
+vm_get_cvar_base(const rb_cref_t *cref, rb_control_frame_t *cfp, int top_level_raise)
{
VALUE klass;
@@ -982,8 +1054,8 @@ vm_get_cvar_base(const rb_cref_t *cref, rb_control_frame_t *cfp)
CREF_PUSHED_BY_EVAL(cref))) {
cref = CREF_NEXT(cref);
}
- if (!CREF_NEXT(cref)) {
- rb_warn("class variable access from toplevel");
+ if (top_level_raise && !CREF_NEXT(cref)) {
+ rb_raise(rb_eRuntimeError, "class variable access from toplevel");
}
klass = vm_get_iclass(cfp, CREF_CLASS(cref));
@@ -1008,9 +1080,40 @@ vm_search_const_defined_class(const VALUE cbase, ID id)
return 0;
}
-ALWAYS_INLINE(static VALUE vm_getivar(VALUE, ID, IVC, struct rb_call_cache *, int));
+static bool
+iv_index_tbl_lookup(struct st_table *iv_index_tbl, ID id, struct rb_iv_index_tbl_entry **ent)
+{
+ int found;
+
+ if (iv_index_tbl == NULL) return false;
+
+ RB_VM_LOCK_ENTER();
+ {
+ found = st_lookup(iv_index_tbl, (st_data_t)id, (st_data_t *)ent);
+ }
+ RB_VM_LOCK_LEAVE();
+
+ return found ? true : false;
+}
+
+ALWAYS_INLINE(static void fill_ivar_cache(const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr, struct rb_iv_index_tbl_entry *ent));
+
+static inline void
+fill_ivar_cache(const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr, struct rb_iv_index_tbl_entry *ent)
+{
+ // fill cache
+ if (!is_attr) {
+ ic->entry = ent;
+ RB_OBJ_WRITTEN(iseq, Qundef, ent->class_value);
+ }
+ else {
+ vm_cc_attr_index_set(cc, (int)ent->index + 1);
+ }
+}
+
+ALWAYS_INLINE(static VALUE vm_getivar(VALUE, ID, const rb_iseq_t *, IVC, const struct rb_callcache *, int));
static inline VALUE
-vm_getivar(VALUE obj, ID id, IVC ic, struct rb_call_cache *cc, int is_attr)
+vm_getivar(VALUE obj, ID id, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)
{
#if OPT_IC_FOR_IVAR
VALUE val = Qundef;
@@ -1019,64 +1122,48 @@ vm_getivar(VALUE obj, ID id, IVC ic, struct rb_call_cache *cc, int is_attr)
// frozen?
}
else if (LIKELY(is_attr ?
- RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_unset, cc->aux.index > 0) :
+ RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_unset, vm_cc_attr_index(cc) > 0) :
RB_DEBUG_COUNTER_INC_UNLESS(ivar_get_ic_miss_serial,
- ic->ic_serial == RCLASS_SERIAL(RBASIC(obj)->klass)))) {
- st_index_t index = !is_attr ? ic->index : (cc->aux.index - 1);
+ ic->entry && ic->entry->class_serial == RCLASS_SERIAL(RBASIC(obj)->klass)))) {
+ uint32_t index = !is_attr ? ic->entry->index : (vm_cc_attr_index(cc) - 1);
RB_DEBUG_COUNTER_INC(ivar_get_ic_hit);
if (LIKELY(BUILTIN_TYPE(obj) == T_OBJECT) &&
LIKELY(index < ROBJECT_NUMIV(obj))) {
val = ROBJECT_IVPTR(obj)[index];
+
+ VM_ASSERT(rb_ractor_shareable_p(obj) ? rb_ractor_shareable_p(val) : true);
}
else if (FL_TEST_RAW(obj, FL_EXIVAR)) {
- struct gen_ivtbl *ivtbl;
-
- if (LIKELY(st_lookup(rb_ivar_generic_ivtbl(), (st_data_t)obj, (st_data_t *)&ivtbl)) &&
- LIKELY(index < ivtbl->numiv)) {
- val = ivtbl->ivptr[index];
- }
+ val = rb_ivar_generic_lookup_with_index(obj, id, index);
}
+
goto ret;
}
else {
- struct st_table *iv_index_tbl;
- st_index_t numiv;
- VALUE *ivptr;
-
- st_data_t index;
+ struct rb_iv_index_tbl_entry *ent;
if (BUILTIN_TYPE(obj) == T_OBJECT) {
- iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
- numiv = ROBJECT_NUMIV(obj);
- ivptr = ROBJECT_IVPTR(obj);
-
- fill:
- if (iv_index_tbl) {
- if (st_lookup(iv_index_tbl, id, &index)) {
- if (!is_attr) {
- ic->index = index;
- ic->ic_serial = RCLASS_SERIAL(RBASIC(obj)->klass);
- }
- else { /* call_info */
- cc->aux.index = (int)index + 1;
- }
+ struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
- if (index < numiv) {
- val = ivptr[index];
- }
- }
- }
- }
+ if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &ent)) {
+ fill_ivar_cache(iseq, ic, cc, is_attr, ent);
+
+ // get value
+ if (ent->index < ROBJECT_NUMIV(obj)) {
+ val = ROBJECT_IVPTR(obj)[ent->index];
+
+ VM_ASSERT(rb_ractor_shareable_p(obj) ? rb_ractor_shareable_p(val) : true);
+ }
+ }
+ }
else if (FL_TEST_RAW(obj, FL_EXIVAR)) {
- struct gen_ivtbl *ivtbl;
+ struct st_table *iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
- if (LIKELY(st_lookup(rb_ivar_generic_ivtbl(), (st_data_t)obj, (st_data_t *)&ivtbl))) {
- numiv = ivtbl->numiv;
- ivptr = ivtbl->ivptr;
- iv_index_tbl = RCLASS_IV_INDEX_TBL(rb_obj_class(obj));
- goto fill;
+ if (iv_index_tbl && iv_index_tbl_lookup(iv_index_tbl, id, &ent)) {
+ fill_ivar_cache(iseq, ic, cc, is_attr, ent);
+ val = rb_ivar_generic_lookup_with_index(obj, id, ent->index);
}
}
else {
@@ -1089,9 +1176,6 @@ vm_getivar(VALUE obj, ID id, IVC ic, struct rb_call_cache *cc, int is_attr)
return val;
}
else {
- if (!is_attr && RTEST(ruby_verbose)) {
- rb_warning("instance variable %"PRIsVALUE" not initialized", QUOTE_ID(id));
- }
return Qnil;
}
}
@@ -1107,64 +1191,106 @@ vm_getivar(VALUE obj, ID id, IVC ic, struct rb_call_cache *cc, int is_attr)
}
}
+ALWAYS_INLINE(static VALUE vm_setivar_slowpath(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr));
+NOINLINE(static VALUE vm_setivar_slowpath_ivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic));
+NOINLINE(static VALUE vm_setivar_slowpath_attr(VALUE obj, ID id, VALUE val, const struct rb_callcache *cc));
+
+static VALUE
+vm_setivar_slowpath(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)
+{
+ rb_check_frozen_internal(obj);
+
+#if OPT_IC_FOR_IVAR
+ if (RB_TYPE_P(obj, T_OBJECT)) {
+ struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ struct rb_iv_index_tbl_entry *ent;
+
+ if (iv_index_tbl_lookup(iv_index_tbl, id, &ent)) {
+ if (!is_attr) {
+ ic->entry = ent;
+ RB_OBJ_WRITTEN(iseq, Qundef, ent->class_value);
+ }
+ else if (ent->index >= INT_MAX) {
+ rb_raise(rb_eArgError, "too many instance variables");
+ }
+ else {
+ vm_cc_attr_index_set(cc, (int)(ent->index + 1));
+ }
+
+ uint32_t index = ent->index;
+
+ if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {
+ rb_init_iv_list(obj);
+ }
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+ RB_OBJ_WRITE(obj, &ptr[index], val);
+ RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_iv_hit);
+
+ return val;
+ }
+ }
+#endif
+ RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
+ return rb_ivar_set(obj, id, val);
+}
+
+static VALUE
+vm_setivar_slowpath_ivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic)
+{
+ return vm_setivar_slowpath(obj, id, val, iseq, ic, NULL, false);
+}
+
+static VALUE
+vm_setivar_slowpath_attr(VALUE obj, ID id, VALUE val, const struct rb_callcache *cc)
+{
+ return vm_setivar_slowpath(obj, id, val, NULL, NULL, cc, true);
+}
+
static inline VALUE
-vm_setivar(VALUE obj, ID id, VALUE val, IVC ic, struct rb_call_cache *cc, int is_attr)
+vm_setivar(VALUE obj, ID id, VALUE val, const rb_iseq_t *iseq, IVC ic, const struct rb_callcache *cc, int is_attr)
{
#if OPT_IC_FOR_IVAR
- rb_check_frozen_internal(obj);
+ if (LIKELY(RB_TYPE_P(obj, T_OBJECT)) &&
+ LIKELY(!RB_OBJ_FROZEN_RAW(obj))) {
- if (LIKELY(RB_TYPE_P(obj, T_OBJECT))) {
- VALUE klass = RBASIC(obj)->klass;
- st_data_t index;
+ VM_ASSERT(!rb_ractor_shareable_p(obj));
if (LIKELY(
- (!is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_serial, ic->ic_serial == RCLASS_SERIAL(klass))) ||
- ( is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_unset, cc->aux.index > 0)))) {
- VALUE *ptr = ROBJECT_IVPTR(obj);
- index = !is_attr ? ic->index : cc->aux.index-1;
-
- if (RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_oorange, index < ROBJECT_NUMIV(obj))) {
- RB_OBJ_WRITE(obj, &ptr[index], val);
- RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
- return val; /* inline cache hit */
- }
- }
- else {
- struct st_table *iv_index_tbl = ROBJECT_IV_INDEX_TBL(obj);
+ (!is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_serial, ic->entry && ic->entry->class_serial == RCLASS_SERIAL(RBASIC(obj)->klass))) ||
+ ( is_attr && RB_DEBUG_COUNTER_INC_UNLESS(ivar_set_ic_miss_unset, vm_cc_attr_index(cc) > 0)))) {
+ uint32_t index = !is_attr ? ic->entry->index : vm_cc_attr_index(cc)-1;
- if (iv_index_tbl && st_lookup(iv_index_tbl, (st_data_t)id, &index)) {
- if (!is_attr) {
- ic->index = index;
- ic->ic_serial = RCLASS_SERIAL(klass);
- }
- else if (index >= INT_MAX) {
- rb_raise(rb_eArgError, "too many instance variables");
- }
- else {
- cc->aux.index = (int)(index + 1);
- }
- }
- /* fall through */
+ if (UNLIKELY(index >= ROBJECT_NUMIV(obj))) {
+ rb_init_iv_list(obj);
+ }
+ VALUE *ptr = ROBJECT_IVPTR(obj);
+ RB_OBJ_WRITE(obj, &ptr[index], val);
+ RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);
+ return val; /* inline cache hit */
}
}
else {
RB_DEBUG_COUNTER_INC(ivar_set_ic_miss_noobject);
}
#endif /* OPT_IC_FOR_IVAR */
- RB_DEBUG_COUNTER_INC(ivar_set_ic_miss);
- return rb_ivar_set(obj, id, val);
+ if (is_attr) {
+ return vm_setivar_slowpath_attr(obj, id, val, cc);
+ }
+ else {
+ return vm_setivar_slowpath_ivar(obj, id, val, iseq, ic);
+ }
}
static inline VALUE
-vm_getinstancevariable(VALUE obj, ID id, IVC ic)
+vm_getinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, IVC ic)
{
- return vm_getivar(obj, id, ic, NULL, FALSE);
+ return vm_getivar(obj, id, iseq, ic, NULL, FALSE);
}
static inline void
-vm_setinstancevariable(VALUE obj, ID id, VALUE val, IVC ic)
+vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic)
{
- vm_setivar(obj, id, val, ic, 0, 0);
+ vm_setivar(obj, id, val, iseq, ic, 0, 0);
}
static VALUE
@@ -1422,245 +1548,321 @@ vm_expandarray(VALUE *sp, VALUE ary, rb_num_t num, int flag)
RB_GC_GUARD(ary);
}
-static VALUE vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, struct rb_call_data *cd);
+static VALUE vm_call_general(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling);
-#ifdef __has_attribute
-#if __has_attribute(artificial)
-__attribute__((__artificial__))
-#endif
-#endif
-static inline vm_call_handler
-calccall(const struct rb_call_data *cd, const rb_callable_method_entry_t *me)
+static VALUE vm_mtbl_dump(VALUE klass, ID target_mid);
+
+static struct rb_class_cc_entries *
+vm_ccs_create(VALUE klass, const rb_callable_method_entry_t *cme)
{
- const struct rb_call_info *ci = &cd->ci;
- const struct rb_call_cache *cc = &cd->cc;
+ struct rb_class_cc_entries *ccs = ALLOC(struct rb_class_cc_entries);
+#if VM_CHECK_MODE > 0
+ ccs->debug_sig = ~(VALUE)ccs;
+#endif
+ ccs->capa = 0;
+ ccs->len = 0;
+ RB_OBJ_WRITE(klass, &ccs->cme, cme);
+ METHOD_ENTRY_CACHED_SET((rb_callable_method_entry_t *)cme);
+ ccs->entries = NULL;
+ return ccs;
+}
- if (UNLIKELY(!me)) {
- RB_DEBUG_COUNTER_INC(mc_miss_by_nome);
- return vm_call_general; /* vm_call_method_nome() situation */
- }
- else if (LIKELY(cc->me != me)) {
- RB_DEBUG_COUNTER_INC(mc_miss_by_distinct);
- return vm_call_general; /* normal cases */
+static void
+vm_ccs_push(VALUE klass, struct rb_class_cc_entries *ccs, const struct rb_callinfo *ci, const struct rb_callcache *cc)
+{
+ if (! vm_cc_markable(cc)) {
+ return;
}
- else if (UNLIKELY(cc->method_serial != me->def->method_serial)) {
- RB_DEBUG_COUNTER_INC(mc_miss_by_refine);
- return vm_call_general; /* cc->me was refined elsewhere */
+ else if (! vm_ci_markable(ci)) {
+ return;
}
- /* "Calling a formerly-public method, which is now privatised, with an
- * explicit receiver" is the only situation we have to check here. A
- * formerly-private method now publicised is an absolutely safe thing.
- * Calling a private method without specifying a receiver is also safe. */
- else if ((METHOD_ENTRY_VISI(cc->me) != METHOD_VISI_PUBLIC) &&
- !(ci->flag & VM_CALL_FCALL)) {
- RB_DEBUG_COUNTER_INC(mc_miss_by_visi);
- return vm_call_general;
+
+ if (UNLIKELY(ccs->len == ccs->capa)) {
+ if (ccs->capa == 0) {
+ ccs->capa = 1;
+ ccs->entries = ALLOC_N(struct rb_class_cc_entries_entry, ccs->capa);
+ }
+ else {
+ ccs->capa *= 2;
+ REALLOC_N(ccs->entries, struct rb_class_cc_entries_entry, ccs->capa);
+ }
}
- else {
- RB_DEBUG_COUNTER_INC(mc_miss_spurious);
- (void)RB_DEBUG_COUNTER_INC_IF(mc_miss_reuse_call, cc->call != vm_call_general);
- return cc->call;
+ VM_ASSERT(ccs->len < ccs->capa);
+
+ const int pos = ccs->len++;
+ RB_OBJ_WRITE(klass, &ccs->entries[pos].ci, ci);
+ RB_OBJ_WRITE(klass, &ccs->entries[pos].cc, cc);
+
+ if (RB_DEBUG_COUNTER_SETMAX(ccs_maxlen, ccs->len)) {
+ // for tuning
+ // vm_mtbl_dump(klass, 0);
}
}
-MJIT_FUNC_EXPORTED void
-rb_vm_search_method_slowpath(struct rb_call_data *cd, VALUE klass)
-{
- const struct rb_call_info *ci = &cd->ci;
- struct rb_call_cache *cc = &cd->cc;
- const rb_callable_method_entry_t *me =
- rb_callable_method_entry(klass, ci->mid);
- const vm_call_handler call = calccall(cd, me);
- struct rb_call_cache buf = {
- GET_GLOBAL_METHOD_STATE(),
- { RCLASS_SERIAL(klass) },
- me,
- me ? me->def->method_serial : 0,
- call,
- };
- if (call != vm_call_general) {
- for (int i = 0; i < numberof(cc->class_serial) - 1; i++) {
- buf.class_serial[i + 1] = cc->class_serial[i];
- }
+#if VM_CHECK_MODE > 0
+void
+rb_vm_ccs_dump(struct rb_class_cc_entries *ccs)
+{
+ fprintf(stderr, "ccs:%p (%d,%d)\n", (void *)ccs, ccs->len, ccs->capa);
+ for (int i=0; i<ccs->len; i++) {
+ vm_ci_dump(ccs->entries[i].ci);
+ rp(ccs->entries[i].cc);
}
- MEMCPY(cc, &buf, struct rb_call_cache, 1);
- VM_ASSERT(callable_method_entry_p(cc->me));
-}
-
-/* # Description of what `vm_cache_check_for_class_serial()` is doing #########
- *
- * - Let's assume a `struct rb_call_cache` has its `class_serial` as an array
- * of length 3 (typical situation for 64 bit environments):
- *
- * ```C
- * struct rb_call_cache {
- * rb_serial_t method_state;
- * rb_serial_t class_serial[3];
- * rb_callable_method_entry_t *me;
- * rb_method_definition_struct *def;
- * vm_call_handler call;
- * union { ... snip ... } aux;
- * };
- * ```
- *
- * - Initially, the `cc->class_serial` array is filled with zeros.
- *
- * - If the cache mishits, and if that was due to mc_miss_spurious situation,
- * `rb_vm_search_method_slowpath()` pushes the newest class serial at the
- * leftmost position of the `cc->class_serial`.
- *
- * ```
- * from: +--------------+-----+-----+-----+----+-----+------+-----+
- * | method_state | (x) | (y) | (z) | me | def | call | aux |
- * +--------------+-----+-----+-----+----+-----+------+-----+
- * \ \
- * \ \
- * \ \
- * \ \
- * \ \
- * v v
- * to: +--------------+-----+-----+-----+----+-----+------+-----+
- * | method_state | NEW | (x) | (y) | me | def | call | aux |
- * +--------------+-----+-----+-----+----+-----+------+-----+
- * ^^^
- * fill RCLASS_SERIAL(klass)
- * ```
- *
- * - Eventually, the `cc->class_serial` is filled with a series of classes that
- * share the same method entry for the same call site.
- *
- * - `vm_cache_check_for_class_serial()` can say that the cache now hits if
- * _any_ of the class serials stored inside of `cc->class_serial` is equal to
- * the given `class_serial` value.
- *
- * - It scans the array from left to right, looking for the expected class
- * serial. If it finds that at `cc->class_serial[0]` (this branch
- * probability is 98% according to @shyouhei's experiment), just returns
- * true. If it reaches the end of the array without finding anything,
- * returns false. This is done in the #1 loop below.
- *
- * - What needs to be complicated is when the class serial is found at either
- * `cc->class_serial[1]` or `cc->class_serial[2]`. When that happens, its
- * return value is true because `cc->me` and `cc->call` are valid. But
- * `cc->aux` might be invalid. Also the found class serial is expected to
- * hit next time. In this case we reorder the array and wipe out `cc->aux`.
- * This is done in the #2 loop below.
- *
- * ```
- * from: +--------------+-----+-----+-----+----+-----+------+-----+
- * | method_state | (x) | (y) | (z) | me | def | call | aux |
- * +--------------+-----+-----+-----+----+-----+------+-----+
- * \ \ |
- * \ \ |
- * +- \ --- \ -+
- * | \ \
- * | \ \
- * v v v
- * to: +--------------+-----+-----+-----+----+-----+------+-----+
- * | method_state | (z) | (x) | (y) | me | def | call | 000 |
- * +--------------+-----+-----+-----+----+-----+------+-----+
- * ^^^
- * wipe out
- * ```
- *
- */
-static inline bool
-vm_cache_check_for_class_serial(struct rb_call_cache *cc, rb_serial_t class_serial)
+}
+
+static int
+vm_ccs_verify(struct rb_class_cc_entries *ccs, ID mid, VALUE klass)
{
- int i;
- rb_serial_t j;
+ VM_ASSERT(vm_ccs_p(ccs));
+ VM_ASSERT(ccs->len <= ccs->capa);
- /* This is the loop #1 in above description. */
- for (i = 0; i < numberof(cc->class_serial); i++) {
- j = cc->class_serial[i];
+ for (int i=0; i<ccs->len; i++) {
+ const struct rb_callinfo *ci = ccs->entries[i].ci;
+ const struct rb_callcache *cc = ccs->entries[i].cc;
- if (! j) {
- break;
- }
- else if (j != class_serial) {
- continue;
+ VM_ASSERT(vm_ci_p(ci));
+ VM_ASSERT(vm_ci_mid(ci) == mid);
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ VM_ASSERT(vm_cc_class_check(cc, klass));
+ VM_ASSERT(vm_cc_cme(cc) == ccs->cme);
+ }
+ return TRUE;
+}
+#endif
+
+#ifndef MJIT_HEADER
+static const struct rb_callcache *
+vm_search_cc(const VALUE klass, const struct rb_callinfo * const ci)
+{
+ const ID mid = vm_ci_mid(ci);
+ struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
+ struct rb_class_cc_entries *ccs = NULL;
+
+ if (cc_tbl) {
+ if (rb_id_table_lookup(cc_tbl, mid, (VALUE *)&ccs)) {
+ const int ccs_len = ccs->len;
+ VM_ASSERT(vm_ccs_verify(ccs, mid, klass));
+
+ if (UNLIKELY(METHOD_ENTRY_INVALIDATED(ccs->cme))) {
+ rb_vm_ccs_free(ccs);
+ rb_id_table_delete(cc_tbl, mid);
+ ccs = NULL;
+ }
+ else {
+ for (int i=0; i<ccs_len; i++) {
+ const struct rb_callinfo *ccs_ci = ccs->entries[i].ci;
+ const struct rb_callcache *ccs_cc = ccs->entries[i].cc;
+
+ VM_ASSERT(vm_ci_p(ccs_ci));
+ VM_ASSERT(IMEMO_TYPE_P(ccs_cc, imemo_callcache));
+
+ if (ccs_ci == ci) { // TODO: equality
+ RB_DEBUG_COUNTER_INC(cc_found_in_ccs);
+
+ VM_ASSERT(vm_cc_cme(ccs_cc)->called_id == mid);
+ VM_ASSERT(ccs_cc->klass == klass);
+ VM_ASSERT(!METHOD_ENTRY_INVALIDATED(vm_cc_cme(ccs_cc)));
+
+ return ccs_cc;
+ }
+ }
+ }
}
- else if (! i) {
- return true;
+ }
+ else {
+ cc_tbl = RCLASS_CC_TBL(klass) = rb_id_table_create(2);
+ }
+
+ RB_DEBUG_COUNTER_INC(cc_not_found_in_ccs);
+
+ const rb_callable_method_entry_t *cme;
+
+ if (ccs) {
+ cme = ccs->cme;
+ cme = UNDEFINED_METHOD_ENTRY_P(cme) ? NULL : cme;
+
+ VM_ASSERT(cme == rb_callable_method_entry(klass, mid));
+ }
+ else {
+ cme = rb_callable_method_entry(klass, mid);
+ }
+
+ VM_ASSERT(cme == NULL || IMEMO_TYPE_P(cme, imemo_ment));
+
+ if (cme == NULL) {
+ // undef or not found: can't cache the information
+ VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL);
+ return &vm_empty_cc;
+ }
+
+#if VM_CHECK_MODE > 0
+ const rb_callable_method_entry_t *searched_cme = rb_callable_method_entry(klass, mid);
+ VM_ASSERT(cme == searched_cme);
+#endif
+
+ const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general);
+ METHOD_ENTRY_CACHED_SET((struct rb_callable_method_entry_struct *)cme);
+
+ if (ccs == NULL) {
+ VM_ASSERT(cc_tbl != NULL);
+
+ if (LIKELY(rb_id_table_lookup(cc_tbl, mid, (VALUE*)&ccs))) {
+ // rb_callable_method_entry() prepares ccs.
}
else {
- goto hit;
+ // TODO: required?
+ ccs = vm_ccs_create(klass, cme);
+ rb_id_table_insert(cc_tbl, mid, (VALUE)ccs);
}
}
- RB_DEBUG_COUNTER_INC(mc_class_serial_miss);
- return false;
+ vm_ccs_push(klass, ccs, ci, cc);
- hit:
- /* This is the loop #2 in above description. */
- for (; i > 0; i--) {
- cc->class_serial[i] = cc->class_serial[i - 1];
+ VM_ASSERT(vm_cc_cme(cc) != NULL);
+ VM_ASSERT(cme->called_id == mid);
+ VM_ASSERT(vm_cc_cme(cc)->called_id == mid);
+
+ return cc;
+}
+
+MJIT_FUNC_EXPORTED const struct rb_callcache *
+rb_vm_search_method_slowpath(const struct rb_callinfo *ci, VALUE klass)
+{
+ const struct rb_callcache *cc;
+
+ VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_ICLASS));
+
+ RB_VM_LOCK_ENTER();
+ {
+ cc = vm_search_cc(klass, ci);
+
+ VM_ASSERT(cc);
+ VM_ASSERT(IMEMO_TYPE_P(cc, imemo_callcache));
+ VM_ASSERT(cc == vm_cc_empty() || cc->klass == klass);
+ VM_ASSERT(cc == vm_cc_empty() || callable_method_entry_p(vm_cc_cme(cc)));
+ VM_ASSERT(cc == vm_cc_empty() || !METHOD_ENTRY_INVALIDATED(vm_cc_cme(cc)));
+ VM_ASSERT(cc == vm_cc_empty() || vm_cc_cme(cc)->called_id == vm_ci_mid(ci));
}
+ RB_VM_LOCK_LEAVE();
- cc->class_serial[0] = j;
- MEMZERO(&cc->aux, cc->aux, 1); /* cc->call is valid, but cc->aux might not. */
- return true;
+ return cc;
}
+#endif
-static void
-vm_search_method_fastpath(struct rb_call_data *cd, VALUE klass)
+static const struct rb_callcache *
+vm_search_method_slowpath0(VALUE cd_owner, struct rb_call_data *cd, VALUE klass)
+{
+#if USE_DEBUG_COUNTER
+ const struct rb_callcache *old_cc = cd->cc;
+#endif
+
+ const struct rb_callcache *cc = rb_vm_search_method_slowpath(cd->ci, klass);
+
+#if OPT_INLINE_METHOD_CACHE
+ cd->cc = cc;
+
+ const struct rb_callcache *empty_cc =
+#ifdef MJIT_HEADER
+ rb_vm_empty_cc();
+#else
+ &vm_empty_cc;
+#endif
+ if (cd_owner && cc != empty_cc) RB_OBJ_WRITTEN(cd_owner, Qundef, cc);
+
+#if USE_DEBUG_COUNTER
+ if (old_cc == &empty_cc) {
+ // empty
+ RB_DEBUG_COUNTER_INC(mc_inline_miss_empty);
+ }
+ else if (old_cc == cc) {
+ RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cc);
+ }
+ else if (vm_cc_cme(old_cc) == vm_cc_cme(cc)) {
+ RB_DEBUG_COUNTER_INC(mc_inline_miss_same_cme);
+ }
+ else if (vm_cc_cme(old_cc) && vm_cc_cme(cc) &&
+ vm_cc_cme(old_cc)->def == vm_cc_cme(cc)->def) {
+ RB_DEBUG_COUNTER_INC(mc_inline_miss_same_def);
+ }
+ else {
+ RB_DEBUG_COUNTER_INC(mc_inline_miss_diff);
+ }
+#endif
+#endif // OPT_INLINE_METHOD_CACHE
+
+ VM_ASSERT(vm_cc_cme(cc) == NULL ||
+ vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci));
+
+ return cc;
+}
+
+#ifndef MJIT_HEADER
+ALWAYS_INLINE(static const struct rb_callcache *vm_search_method_fastpath(VALUE cd_owner, struct rb_call_data *cd, VALUE klass));
+#endif
+static const struct rb_callcache *
+vm_search_method_fastpath(VALUE cd_owner, struct rb_call_data *cd, VALUE klass)
{
- struct rb_call_cache *cc = &cd->cc;
+ const struct rb_callcache *cc = cd->cc;
#if OPT_INLINE_METHOD_CACHE
- if (LIKELY(RB_DEBUG_COUNTER_INC_UNLESS(mc_global_state_miss,
- GET_GLOBAL_METHOD_STATE() == cc->method_state) &&
- vm_cache_check_for_class_serial(cc, RCLASS_SERIAL(klass)))) {
- /* cache hit! */
- VM_ASSERT(cc->call != NULL);
- RB_DEBUG_COUNTER_INC(mc_inline_hit);
- return;
+ if (LIKELY(vm_cc_class_check(cc, klass))) {
+ const struct rb_callable_method_entry_struct *cme = vm_cc_cme(cc);
+ if (LIKELY(cme && !METHOD_ENTRY_INVALIDATED(cme))) {
+ VM_ASSERT(callable_method_entry_p(vm_cc_cme(cc)));
+ RB_DEBUG_COUNTER_INC(mc_inline_hit);
+ VM_ASSERT(vm_cc_cme(cc) == NULL || // not found
+ (vm_ci_flag(cd->ci) & VM_CALL_SUPER) || // search_super w/ define_method
+ vm_cc_cme(cc)->called_id == vm_ci_mid(cd->ci)); // cme->called_id == ci->mid
+
+ return cc;
+ }
+ RB_DEBUG_COUNTER_INC(mc_inline_miss_invalidated);
+ }
+ else {
+ RB_DEBUG_COUNTER_INC(mc_inline_miss_klass);
}
- RB_DEBUG_COUNTER_INC(mc_inline_miss);
#endif
- rb_vm_search_method_slowpath(cd, klass);
+
+ return vm_search_method_slowpath0(cd_owner, cd, klass);
}
-static void
-vm_search_method(struct rb_call_data *cd, VALUE recv)
+static const struct rb_callcache *
+vm_search_method(VALUE cd_owner, struct rb_call_data *cd, VALUE recv)
{
VALUE klass = CLASS_OF(recv);
-
VM_ASSERT(klass != Qfalse);
VM_ASSERT(RBASIC_CLASS(klass) == 0 || rb_obj_is_kind_of(klass, rb_cClass));
- vm_search_method_fastpath(cd, klass);
+
+ return vm_search_method_fastpath(cd_owner, cd, klass);
}
static inline int
check_cfunc(const rb_callable_method_entry_t *me, VALUE (*func)())
{
- if (me && me->def->type == VM_METHOD_TYPE_CFUNC &&
- me->def->body.cfunc.func == func) {
- return 1;
+ if (! me) {
+ return false;
}
else {
- return 0;
+ VM_ASSERT(IMEMO_TYPE_P(me, imemo_ment));
+ VM_ASSERT(callable_method_entry_p(me));
+ VM_ASSERT(me->def);
+ if (me->def->type != VM_METHOD_TYPE_CFUNC) {
+ return false;
+ }
+ else {
+ return me->def->body.cfunc.func == func;
+ }
}
}
static inline int
-vm_method_cfunc_is(CALL_DATA cd, VALUE recv, VALUE (*func)())
-{
- vm_search_method(cd, recv);
- return check_cfunc(cd->cc.me, func);
-}
-
-static VALUE
-opt_equal_fallback(VALUE recv, VALUE obj, CALL_DATA cd)
+vm_method_cfunc_is(const rb_iseq_t *iseq, CALL_DATA cd, VALUE recv, VALUE (*func)())
{
- if (vm_method_cfunc_is(cd, recv, rb_obj_equal)) {
- return recv == obj ? Qtrue : Qfalse;
- }
-
- return Qundef;
+ VM_ASSERT(iseq != NULL);
+ const struct rb_callcache *cc = vm_search_method((VALUE)iseq, cd, recv);
+ return check_cfunc(vm_cc_cme(cc), func);
}
-#define BUILTIN_CLASS_P(x, k) (!SPECIAL_CONST_P(x) && RBASIC_CLASS(x) == k)
#define EQ_UNREDEFINED_P(t) BASIC_OP_UNREDEFINED_P(BOP_EQ, t##_REDEFINED_OP_FLAG)
static inline bool
@@ -1692,101 +1894,132 @@ FLONUM_2_P(VALUE a, VALUE b)
#endif
}
-/* 1: compare by identity, 0: not applicable, -1: redefined */
-static inline int
-comparable_by_identity(VALUE recv, VALUE obj)
+static VALUE
+opt_equality_specialized(VALUE recv, VALUE obj)
{
- if (FIXNUM_2_P(recv, obj)) {
- return (EQ_UNREDEFINED_P(INTEGER) != 0) * 2 - 1;
+ if (FIXNUM_2_P(recv, obj) && EQ_UNREDEFINED_P(INTEGER)) {
+ goto compare_by_identity;
}
- if (FLONUM_2_P(recv, obj)) {
- return (EQ_UNREDEFINED_P(FLOAT) != 0) * 2 - 1;
+ else if (FLONUM_2_P(recv, obj) && EQ_UNREDEFINED_P(FLOAT)) {
+ goto compare_by_identity;
}
- if (SYMBOL_P(recv) && SYMBOL_P(obj)) {
- return (EQ_UNREDEFINED_P(SYMBOL) != 0) * 2 - 1;
+ else if (STATIC_SYM_P(recv) && STATIC_SYM_P(obj) && EQ_UNREDEFINED_P(SYMBOL)) {
+ goto compare_by_identity;
}
- return 0;
-}
+ else if (SPECIAL_CONST_P(recv)) {
+ //
+ }
+ else if (RBASIC_CLASS(recv) == rb_cFloat && RB_FLOAT_TYPE_P(obj) && EQ_UNREDEFINED_P(FLOAT)) {
+ double a = RFLOAT_VALUE(recv);
+ double b = RFLOAT_VALUE(obj);
-static
-#ifndef NO_BIG_INLINE
-inline
+#if MSC_VERSION_BEFORE(1300)
+ if (isnan(a)) {
+ return Qfalse;
+ }
+ else if (isnan(b)) {
+ return Qfalse;
+ }
+ else
#endif
-VALUE
-opt_eq_func(VALUE recv, VALUE obj, CALL_DATA cd)
-{
- switch (comparable_by_identity(recv, obj)) {
- case 1:
- return (recv == obj) ? Qtrue : Qfalse;
- case -1:
- goto fallback;
- }
- if (0) {
- }
- else if (BUILTIN_CLASS_P(recv, rb_cFloat)) {
- if (EQ_UNREDEFINED_P(FLOAT)) {
- return rb_float_equal(recv, obj);
- }
+ if (a == b) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
}
- else if (BUILTIN_CLASS_P(recv, rb_cString) && EQ_UNREDEFINED_P(STRING)) {
- if (recv == obj) return Qtrue;
- if (RB_TYPE_P(obj, T_STRING)) {
- return rb_str_eql_internal(recv, obj);
+ else if (RBASIC_CLASS(recv) == rb_cString && EQ_UNREDEFINED_P(STRING)) {
+ if (recv == obj) {
+ return Qtrue;
+ }
+ else if (RB_TYPE_P(obj, T_STRING)) {
+ return rb_str_eql_internal(obj, recv);
}
}
+ return Qundef;
- fallback:
- return opt_equal_fallback(recv, obj, cd);
+ compare_by_identity:
+ if (recv == obj) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
}
-static
-#ifndef NO_BIG_INLINE
-inline
-#endif
-VALUE
-opt_eql_func(VALUE recv, VALUE obj, CALL_DATA cd)
+static VALUE
+opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd)
{
- switch (comparable_by_identity(recv, obj)) {
- case 1:
- return (recv == obj) ? Qtrue : Qfalse;
- case -1:
- goto fallback;
+ VM_ASSERT(cd_owner != NULL);
+
+ VALUE val = opt_equality_specialized(recv, obj);
+ if (val != Qundef) return val;
+
+ if (!vm_method_cfunc_is(cd_owner, cd, recv, rb_obj_equal)) {
+ return Qundef;
}
- if (0) {
+ else {
+ if (recv == obj) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
}
- else if (BUILTIN_CLASS_P(recv, rb_cFloat)) {
- if (EQ_UNREDEFINED_P(FLOAT)) {
- return rb_float_eql(recv, obj);
- }
+}
+
+#undef EQ_UNREDEFINED_P
+
+#ifndef MJIT_HEADER
+
+static inline const struct rb_callcache *gccct_method_search(rb_execution_context_t *ec, VALUE recv, ID mid, int argc); // vm_eval.c
+NOINLINE(static VALUE opt_equality_by_mid_slowpath(VALUE recv, VALUE obj, ID mid));
+
+static VALUE
+opt_equality_by_mid_slowpath(VALUE recv, VALUE obj, ID mid)
+{
+ const struct rb_callcache *cc = gccct_method_search(GET_EC(), recv, mid, 1);
+
+ if (cc && check_cfunc(vm_cc_cme(cc), rb_obj_equal)) {
+ if (recv == obj) {
+ return Qtrue;
+ }